aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/.gitignore470
-rw-r--r--lib/Makefile11
-rw-r--r--lib/asn1/c_src/asn1_erl_nif.c10
-rw-r--r--lib/asn1/doc/src/Makefile11
-rw-r--r--lib/asn1/doc/src/fascicules.xml18
-rw-r--r--lib/asn1/doc/src/notes.xml155
-rw-r--r--lib/asn1/src/asn1ct.erl51
-rw-r--r--lib/asn1/src/asn1ct_check.erl6
-rw-r--r--lib/asn1/src/asn1ct_constructed_per.erl6
-rw-r--r--lib/asn1/src/asn1ct_gen.erl104
-rw-r--r--lib/asn1/src/asn1ct_gen_per.erl20
-rw-r--r--lib/asn1/src/asn1rtt_per_common.erl1
-rw-r--r--lib/asn1/src/asn1rtt_real_common.erl6
-rw-r--r--lib/asn1/test/Makefile1
-rw-r--r--lib/asn1/test/asn1_SUITE.erl75
-rw-r--r--lib/asn1/test/asn1_SUITE_data/EnumN2N.asn122
-rw-r--r--lib/asn1/test/asn1_SUITE_data/ExtensionDefault.asn112
-rw-r--r--lib/asn1/test/asn1_SUITE_data/ImportsFrom.asn13
-rw-r--r--lib/asn1/test/asn1_SUITE_data/ImportsFrom2.asn15
-rw-r--r--lib/asn1/test/testExtensionDefault.erl53
-rw-r--r--lib/asn1/test/testUniqueObjectSets.erl7
-rw-r--r--lib/asn1/test/test_modified_x420.erl4
-rw-r--r--lib/asn1/vsn.mk2
-rw-r--r--lib/common_test/doc/src/Makefile25
-rw-r--r--lib/common_test/doc/src/ct.xml50
-rw-r--r--lib/common_test/doc/src/ct_ftp.xml8
-rw-r--r--lib/common_test/doc/src/ct_hooks_chapter.xml45
-rw-r--r--lib/common_test/doc/src/fascicules.xml18
-rw-r--r--lib/common_test/doc/src/notes.xml122
-rw-r--r--lib/common_test/doc/src/part_notes.xml41
-rw-r--r--lib/common_test/doc/src/part_notes_history.xml35
-rw-r--r--lib/common_test/src/Makefile4
-rw-r--r--lib/common_test/src/common_test.app.src5
-rw-r--r--lib/common_test/src/ct.erl933
-rw-r--r--lib/common_test/src/ct_config.erl7
-rw-r--r--lib/common_test/src/ct_config_plain.erl4
-rw-r--r--lib/common_test/src/ct_conn_log_h.erl4
-rw-r--r--lib/common_test/src/ct_cover.erl42
-rw-r--r--lib/common_test/src/ct_default_gl.erl3
-rw-r--r--lib/common_test/src/ct_event.erl9
-rw-r--r--lib/common_test/src/ct_framework.erl53
-rw-r--r--lib/common_test/src/ct_ftp.erl143
-rw-r--r--lib/common_test/src/ct_gen_conn.erl106
-rw-r--r--lib/common_test/src/ct_groups.erl10
-rw-r--r--lib/common_test/src/ct_hooks.erl18
-rw-r--r--lib/common_test/src/ct_hooks_lock.erl15
-rw-r--r--lib/common_test/src/ct_logs.erl352
-rw-r--r--lib/common_test/src/ct_make.erl48
-rw-r--r--lib/common_test/src/ct_master.erl116
-rw-r--r--lib/common_test/src/ct_master_event.erl9
-rw-r--r--lib/common_test/src/ct_master_logs.erl27
-rw-r--r--lib/common_test/src/ct_master_status.erl8
-rw-r--r--lib/common_test/src/ct_netconfc.erl2
-rw-r--r--lib/common_test/src/ct_netconfc.hrl6
-rw-r--r--lib/common_test/src/ct_property_test.erl63
-rw-r--r--lib/common_test/src/ct_release_test.erl158
-rw-r--r--lib/common_test/src/ct_repeat.erl10
-rw-r--r--lib/common_test/src/ct_rpc.erl112
-rw-r--r--lib/common_test/src/ct_run.erl106
-rw-r--r--lib/common_test/src/ct_slave.erl190
-rw-r--r--lib/common_test/src/ct_snmp.erl289
-rw-r--r--lib/common_test/src/ct_ssh.erl619
-rw-r--r--lib/common_test/src/ct_telnet.erl415
-rw-r--r--lib/common_test/src/ct_telnet_client.erl1
-rw-r--r--lib/common_test/src/ct_testspec.erl17
-rw-r--r--lib/common_test/src/ct_util.erl190
-rw-r--r--lib/common_test/src/ct_webtool.erl5
-rw-r--r--lib/common_test/src/ct_webtool_sup.erl3
-rw-r--r--lib/common_test/src/cth_log_redirect.erl245
-rw-r--r--lib/common_test/src/cth_surefire.erl19
-rw-r--r--lib/common_test/src/test_server.erl113
-rw-r--r--lib/common_test/src/test_server_ctrl.erl85
-rw-r--r--lib/common_test/src/test_server_gl.erl1
-rw-r--r--lib/common_test/src/test_server_io.erl9
-rw-r--r--lib/common_test/src/test_server_node.erl23
-rw-r--r--lib/common_test/src/test_server_sup.erl11
-rw-r--r--lib/common_test/src/unix_telnet.erl65
-rw-r--r--lib/common_test/src/vts.erl6
-rw-r--r--lib/common_test/test/Makefile3
-rw-r--r--lib/common_test/test/ct_auto_clean_SUITE.erl262
-rw-r--r--lib/common_test/test/ct_auto_clean_SUITE_data/ac_SUITE.erl181
-rw-r--r--lib/common_test/test/ct_auto_clean_SUITE_data/cth_auto_clean.erl214
-rw-r--r--lib/common_test/test/ct_config_SUITE.erl4
-rw-r--r--lib/common_test/test/ct_cover_SUITE_data/cover_SUITE.erl6
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/verify_config.erl38
-rw-r--r--lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl8
-rw-r--r--lib/common_test/test/ct_hooks_SUITE.erl25
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_tc_cth_SUITE.erl22
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/cth_log_SUITE.erl4
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl42
-rw-r--r--lib/common_test/test/ct_log_SUITE.erl4
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl6
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/ns.erl5
-rw-r--r--lib/common_test/test/ct_pre_post_test_io_SUITE.erl10
-rw-r--r--lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl6
-rw-r--r--lib/common_test/test/ct_repeat_testrun_SUITE_data/a_test/r1_SUITE.erl10
-rw-r--r--lib/common_test/test/ct_repeat_testrun_SUITE_data/b_test/r2_SUITE.erl10
-rw-r--r--lib/common_test/test/ct_snmp_SUITE_data/snmp_SUITE.erl6
-rw-r--r--lib/common_test/test/ct_surefire_SUITE_data/surefire_SUITE.erl6
-rw-r--r--lib/common_test/test/ct_test_support.erl18
-rw-r--r--lib/common_test/test/ct_test_support_eh.erl8
-rw-r--r--lib/common_test/test/ct_unicode_SUITE.erl2
-rw-r--r--lib/common_test/test/ct_unicode_SUITE_data/unicode_atoms_SUITE.erl4
-rw-r--r--lib/common_test/test/ct_userconfig_callback.erl4
-rw-r--r--lib/common_test/test/ct_verbosity_SUITE_data/simple_evh.erl8
-rw-r--r--lib/common_test/test/erl2html2_SUITE.erl4
-rw-r--r--lib/common_test/test/telnet_server.erl20
-rw-r--r--lib/common_test/test/test_server_SUITE.erl15
-rw-r--r--lib/common_test/test/test_server_test_lib.erl4
-rw-r--r--lib/common_test/test_server/ts.erl4
-rw-r--r--lib/common_test/test_server/ts_autoconf_win32.erl14
-rw-r--r--lib/common_test/test_server/ts_erl_config.erl24
-rw-r--r--lib/common_test/test_server/ts_install.erl34
-rw-r--r--lib/common_test/test_server/ts_install_cth.erl37
-rw-r--r--lib/common_test/test_server/ts_lib.erl34
-rw-r--r--lib/common_test/test_server/ts_run.erl25
-rw-r--r--lib/common_test/vsn.mk2
-rw-r--r--lib/compiler/doc/src/Makefile27
-rw-r--r--lib/compiler/doc/src/compile.xml37
-rw-r--r--lib/compiler/doc/src/fascicules.xml15
-rw-r--r--lib/compiler/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/compiler/doc/src/notes.xml547
-rw-r--r--lib/compiler/doc/src/part_notes.xml40
-rw-r--r--lib/compiler/doc/src/part_notes_history.xml40
-rw-r--r--lib/compiler/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/compiler/doc/src/warning.gifbin1498 -> 0 bytes
-rw-r--r--lib/compiler/internal_doc/cerl-notes.md75
-rw-r--r--lib/compiler/src/Makefile16
-rw-r--r--lib/compiler/src/beam_a.erl16
-rw-r--r--lib/compiler/src/beam_asm.erl60
-rw-r--r--lib/compiler/src/beam_block.erl406
-rw-r--r--lib/compiler/src/beam_bs.erl5
-rw-r--r--lib/compiler/src/beam_bsm.erl24
-rw-r--r--lib/compiler/src/beam_clean.erl81
-rw-r--r--lib/compiler/src/beam_dead.erl94
-rw-r--r--lib/compiler/src/beam_disasm.erl101
-rw-r--r--lib/compiler/src/beam_disasm.hrl5
-rw-r--r--lib/compiler/src/beam_except.erl5
-rw-r--r--lib/compiler/src/beam_flatten.erl11
-rw-r--r--lib/compiler/src/beam_jump.erl149
-rw-r--r--lib/compiler/src/beam_listing.erl70
-rw-r--r--lib/compiler/src/beam_peep.erl39
-rw-r--r--lib/compiler/src/beam_receive.erl7
-rw-r--r--lib/compiler/src/beam_record.erl129
-rw-r--r--lib/compiler/src/beam_reorder.erl5
-rw-r--r--lib/compiler/src/beam_split.erl9
-rw-r--r--lib/compiler/src/beam_type.erl762
-rw-r--r--lib/compiler/src/beam_utils.erl693
-rw-r--r--lib/compiler/src/beam_validator.erl280
-rw-r--r--lib/compiler/src/beam_z.erl35
-rw-r--r--lib/compiler/src/cerl.erl2
-rw-r--r--lib/compiler/src/cerl_clauses.erl2
-rw-r--r--lib/compiler/src/cerl_inline.erl17
-rw-r--r--lib/compiler/src/cerl_trees.erl116
-rw-r--r--lib/compiler/src/compile.erl142
-rw-r--r--lib/compiler/src/compiler.app.src4
-rw-r--r--lib/compiler/src/core_lint.erl18
-rw-r--r--lib/compiler/src/core_parse.yrl10
-rw-r--r--lib/compiler/src/core_pp.erl10
-rw-r--r--lib/compiler/src/core_scan.erl4
-rw-r--r--lib/compiler/src/erl_bifs.erl6
-rwxr-xr-xlib/compiler/src/genop.tab31
-rw-r--r--lib/compiler/src/sys_core_alias.erl307
-rw-r--r--lib/compiler/src/sys_core_bsm.erl270
-rw-r--r--lib/compiler/src/sys_core_dsetel.erl5
-rw-r--r--lib/compiler/src/sys_core_fold.erl491
-rw-r--r--lib/compiler/src/sys_core_inline.erl6
-rw-r--r--lib/compiler/src/v3_codegen.erl1687
-rw-r--r--lib/compiler/src/v3_core.erl142
-rw-r--r--lib/compiler/src/v3_kernel.erl214
-rw-r--r--lib/compiler/src/v3_kernel.hrl2
-rw-r--r--lib/compiler/src/v3_kernel_pp.erl11
-rw-r--r--lib/compiler/src/v3_life.erl468
-rw-r--r--lib/compiler/src/v3_life.hrl29
-rw-r--r--lib/compiler/test/Makefile1
-rw-r--r--lib/compiler/test/andor_SUITE.erl4
-rw-r--r--lib/compiler/test/apply_SUITE.erl4
-rw-r--r--lib/compiler/test/beam_block_SUITE.erl76
-rw-r--r--lib/compiler/test/beam_except_SUITE.erl4
-rw-r--r--lib/compiler/test/beam_jump_SUITE.erl4
-rw-r--r--lib/compiler/test/beam_reorder_SUITE.erl4
-rw-r--r--lib/compiler/test/beam_type_SUITE.erl159
-rw-r--r--lib/compiler/test/beam_utils_SUITE.erl220
-rw-r--r--lib/compiler/test/beam_validator_SUITE.erl88
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/bad_try_catch_nesting.S64
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/bad_tuples.S88
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/receive_stacked.S390
-rw-r--r--lib/compiler/test/beam_validator_SUITE_data/receive_stacked.erl92
-rw-r--r--lib/compiler/test/bif_SUITE.erl4
-rw-r--r--lib/compiler/test/bs_bincomp_SUITE.erl15
-rw-r--r--lib/compiler/test/bs_bit_binaries_SUITE.erl6
-rw-r--r--lib/compiler/test/bs_construct_SUITE.erl17
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl237
-rw-r--r--lib/compiler/test/bs_utf_SUITE.erl4
-rw-r--r--lib/compiler/test/compilation_SUITE.erl4
-rw-r--r--lib/compiler/test/compilation_SUITE_data/opt_crash.erl8
-rw-r--r--lib/compiler/test/compile_SUITE.erl192
-rw-r--r--lib/compiler/test/compile_SUITE_data/big.erl6
-rw-r--r--lib/compiler/test/compile_SUITE_data/deterministic_module.erl21
-rw-r--r--lib/compiler/test/core_SUITE.erl14
-rw-r--r--lib/compiler/test/core_SUITE_data/fun_letrec_effect.core25
-rw-r--r--lib/compiler/test/core_SUITE_data/name_capture.core110
-rw-r--r--lib/compiler/test/core_SUITE_data/non_variable_apply.core80
-rw-r--r--lib/compiler/test/core_alias_SUITE.erl195
-rw-r--r--lib/compiler/test/core_fold_SUITE.erl100
-rw-r--r--lib/compiler/test/error_SUITE.erl4
-rw-r--r--lib/compiler/test/float_SUITE.erl4
-rw-r--r--lib/compiler/test/fun_SUITE.erl15
-rw-r--r--lib/compiler/test/guard_SUITE.erl42
-rw-r--r--lib/compiler/test/inline_SUITE.erl4
-rw-r--r--lib/compiler/test/lc_SUITE.erl37
-rw-r--r--lib/compiler/test/map_SUITE.erl214
-rw-r--r--lib/compiler/test/match_SUITE.erl152
-rw-r--r--lib/compiler/test/misc_SUITE.erl30
-rw-r--r--lib/compiler/test/overridden_bif_SUITE.erl4
-rw-r--r--lib/compiler/test/receive_SUITE.erl94
-rw-r--r--lib/compiler/test/record_SUITE.erl4
-rw-r--r--lib/compiler/test/regressions_SUITE.erl21
-rw-r--r--lib/compiler/test/trycatch_SUITE.erl238
-rw-r--r--lib/compiler/test/warnings_SUITE.erl4
-rw-r--r--lib/compiler/test/z_SUITE.erl7
-rw-r--r--lib/compiler/vsn.mk2
-rw-r--r--lib/cosEvent/AUTHORS5
-rw-r--r--lib/cosEvent/Makefile42
-rw-r--r--lib/cosEvent/doc/src/CosEventChannelAdmin.xml78
-rw-r--r--lib/cosEvent/doc/src/CosEventChannelAdmin_ConsumerAdmin.xml73
-rw-r--r--lib/cosEvent/doc/src/CosEventChannelAdmin_EventChannel.xml95
-rw-r--r--lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPullConsumer.xml85
-rw-r--r--lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPullSupplier.xml112
-rw-r--r--lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPushConsumer.xml99
-rw-r--r--lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPushSupplier.xml85
-rw-r--r--lib/cosEvent/doc/src/CosEventChannelAdmin_SupplierAdmin.xml73
-rw-r--r--lib/cosEvent/doc/src/Makefile150
-rw-r--r--lib/cosEvent/doc/src/book.gifbin1081 -> 0 bytes
-rw-r--r--lib/cosEvent/doc/src/book.xml50
-rw-r--r--lib/cosEvent/doc/src/ch_contents.xml71
-rw-r--r--lib/cosEvent/doc/src/ch_event_service.xml222
-rw-r--r--lib/cosEvent/doc/src/ch_introduction.xml57
-rw-r--r--lib/cosEvent/doc/src/cosEventApp.xml169
-rw-r--r--lib/cosEvent/doc/src/e_s_components.gifbin4458 -> 0 bytes
-rw-r--r--lib/cosEvent/doc/src/e_s_models.gifbin10354 -> 0 bytes
-rw-r--r--lib/cosEvent/doc/src/fascicules.xml18
-rw-r--r--lib/cosEvent/doc/src/notes.gifbin2005 -> 0 bytes
-rw-r--r--lib/cosEvent/doc/src/notes.xml333
-rw-r--r--lib/cosEvent/doc/src/part.xml40
-rw-r--r--lib/cosEvent/doc/src/part_notes.xml38
-rw-r--r--lib/cosEvent/doc/src/ref_man.gifbin1530 -> 0 bytes
-rw-r--r--lib/cosEvent/doc/src/ref_man.xml46
-rw-r--r--lib/cosEvent/doc/src/summary.html.src1
-rw-r--r--lib/cosEvent/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/cosEvent/info2
-rw-r--r--lib/cosEvent/src/CosEventChannelAdmin.cfg6
-rw-r--r--lib/cosEvent/src/CosEventChannelAdmin.idl66
-rw-r--r--lib/cosEvent/src/CosEventChannelAdmin_ProxyPullConsumer_impl.erl206
-rw-r--r--lib/cosEvent/src/CosEventChannelAdmin_ProxyPushConsumer_impl.erl170
-rw-r--r--lib/cosEvent/src/CosEventChannelAdmin_SupplierAdmin_impl.erl160
-rw-r--r--lib/cosEvent/src/CosEventComm.idl37
-rw-r--r--lib/cosEvent/src/Makefile217
-rw-r--r--lib/cosEvent/src/cosEvent.app.src46
-rw-r--r--lib/cosEvent/src/cosEvent.appup.src6
-rw-r--r--lib/cosEvent/src/cosEventApp.cfg15
-rw-r--r--lib/cosEvent/src/cosEventApp.erl301
-rw-r--r--lib/cosEvent/src/cosEventApp.hrl63
-rw-r--r--lib/cosEvent/src/cosEventApp.idl26
-rw-r--r--lib/cosEvent/src/oe_CosEventComm_CAdmin_impl.erl234
-rw-r--r--lib/cosEvent/src/oe_CosEventComm_Channel_impl.erl247
-rw-r--r--lib/cosEvent/src/oe_CosEventComm_PullerS_impl.erl282
-rw-r--r--lib/cosEvent/src/oe_CosEventComm_PusherS_impl.erl218
-rw-r--r--lib/cosEvent/test/Makefile150
-rw-r--r--lib/cosEvent/test/cosEvent.cover2
-rw-r--r--lib/cosEvent/test/cosEvent.spec1
-rw-r--r--lib/cosEvent/test/event_channel_SUITE.erl326
-rw-r--r--lib/cosEvent/test/event_test_PullC_impl.erl44
-rw-r--r--lib/cosEvent/test/event_test_PullS_impl.erl58
-rw-r--r--lib/cosEvent/test/event_test_PushC_impl.erl47
-rw-r--r--lib/cosEvent/test/event_test_PushS_impl.erl42
-rw-r--r--lib/cosEvent/test/event_test_server.idl48
-rw-r--r--lib/cosEvent/test/generated_SUITE.erl473
-rw-r--r--lib/cosEvent/vsn.mk2
-rw-r--r--lib/cosEventDomain/AUTHORS4
-rw-r--r--lib/cosEventDomain/Makefile42
-rw-r--r--lib/cosEventDomain/doc/pdf/.gitignore0
-rw-r--r--lib/cosEventDomain/doc/src/CosEventDomainAdmin.xml93
-rw-r--r--lib/cosEventDomain/doc/src/CosEventDomainAdmin_EventDomain.xml627
-rw-r--r--lib/cosEventDomain/doc/src/CosEventDomainAdmin_EventDomainFactory.xml88
-rw-r--r--lib/cosEventDomain/doc/src/Makefile144
-rw-r--r--lib/cosEventDomain/doc/src/book.gifbin1081 -> 0 bytes
-rw-r--r--lib/cosEventDomain/doc/src/book.xml49
-rw-r--r--lib/cosEventDomain/doc/src/ch_QoS.xml118
-rw-r--r--lib/cosEventDomain/doc/src/ch_contents.xml69
-rw-r--r--lib/cosEventDomain/doc/src/ch_event_domain_service.xml111
-rw-r--r--lib/cosEventDomain/doc/src/ch_introduction.xml53
-rw-r--r--lib/cosEventDomain/doc/src/cosEventDomainApp.xml150
-rw-r--r--lib/cosEventDomain/doc/src/fascicules.xml18
-rw-r--r--lib/cosEventDomain/doc/src/notes.gifbin2005 -> 0 bytes
-rw-r--r--lib/cosEventDomain/doc/src/notes.xml316
-rw-r--r--lib/cosEventDomain/doc/src/part.xml40
-rw-r--r--lib/cosEventDomain/doc/src/part_notes.xml37
-rw-r--r--lib/cosEventDomain/doc/src/ref_man.gifbin1530 -> 0 bytes
-rw-r--r--lib/cosEventDomain/doc/src/ref_man.xml40
-rw-r--r--lib/cosEventDomain/doc/src/summary.html.src1
-rw-r--r--lib/cosEventDomain/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/cosEventDomain/ebin/.gitignore0
-rw-r--r--lib/cosEventDomain/example/.gitignore0
-rw-r--r--lib/cosEventDomain/include/.gitignore0
-rw-r--r--lib/cosEventDomain/info2
-rw-r--r--lib/cosEventDomain/src/CosEventDomainAdmin.cfg4
-rw-r--r--lib/cosEventDomain/src/CosEventDomainAdmin.idl280
-rw-r--r--lib/cosEventDomain/src/CosEventDomainAdmin_EventDomainFactory_impl.erl183
-rw-r--r--lib/cosEventDomain/src/CosEventDomainAdmin_EventDomain_impl.erl1426
-rw-r--r--lib/cosEventDomain/src/Makefile185
-rw-r--r--lib/cosEventDomain/src/cosEventDomain.app.src33
-rw-r--r--lib/cosEventDomain/src/cosEventDomain.appup.src6
-rw-r--r--lib/cosEventDomain/src/cosEventDomainApp.erl341
-rw-r--r--lib/cosEventDomain/src/cosEventDomainApp.hrl70
-rw-r--r--lib/cosEventDomain/test/Makefile104
-rw-r--r--lib/cosEventDomain/test/cosEventDomain.cover2
-rw-r--r--lib/cosEventDomain/test/cosEventDomain.spec1
-rw-r--r--lib/cosEventDomain/test/event_domain_SUITE.erl464
-rw-r--r--lib/cosEventDomain/test/generated_SUITE.erl384
-rw-r--r--lib/cosEventDomain/vsn.mk2
-rw-r--r--lib/cosFileTransfer/AUTHORS4
-rw-r--r--lib/cosFileTransfer/Makefile42
-rw-r--r--lib/cosFileTransfer/doc/html/.gitignore0
-rw-r--r--lib/cosFileTransfer/doc/man3/.gitignore0
-rw-r--r--lib/cosFileTransfer/doc/man6/.gitignore0
-rw-r--r--lib/cosFileTransfer/doc/pdf/.gitignore0
-rw-r--r--lib/cosFileTransfer/doc/src/CosFileTransfer.gifbin10889 -> 0 bytes
-rw-r--r--lib/cosFileTransfer/doc/src/CosFileTransfer_Directory.xml69
-rw-r--r--lib/cosFileTransfer/doc/src/CosFileTransfer_File.xml94
-rw-r--r--lib/cosFileTransfer/doc/src/CosFileTransfer_FileIterator.xml86
-rw-r--r--lib/cosFileTransfer/doc/src/CosFileTransfer_FileTransferSession.xml191
-rw-r--r--lib/cosFileTransfer/doc/src/CosFileTransfer_VirtualFileSystem.xml83
-rw-r--r--lib/cosFileTransfer/doc/src/Makefile147
-rw-r--r--lib/cosFileTransfer/doc/src/book.gifbin1081 -> 0 bytes
-rw-r--r--lib/cosFileTransfer/doc/src/book.xml49
-rw-r--r--lib/cosFileTransfer/doc/src/ch_contents.xml75
-rw-r--r--lib/cosFileTransfer/doc/src/ch_example.xml96
-rw-r--r--lib/cosFileTransfer/doc/src/ch_install.xml58
-rw-r--r--lib/cosFileTransfer/doc/src/ch_introduction.xml57
-rw-r--r--lib/cosFileTransfer/doc/src/ch_system.xml138
-rw-r--r--lib/cosFileTransfer/doc/src/cosFileTransferApp.xml173
-rw-r--r--lib/cosFileTransfer/doc/src/fascicules.xml18
-rw-r--r--lib/cosFileTransfer/doc/src/notes.gifbin2005 -> 0 bytes
-rw-r--r--lib/cosFileTransfer/doc/src/notes.xml364
-rw-r--r--lib/cosFileTransfer/doc/src/part.xml41
-rw-r--r--lib/cosFileTransfer/doc/src/part_notes.xml37
-rw-r--r--lib/cosFileTransfer/doc/src/ref_man.gifbin1530 -> 0 bytes
-rw-r--r--lib/cosFileTransfer/doc/src/ref_man.xml42
-rw-r--r--lib/cosFileTransfer/doc/src/summary.html.src1
-rw-r--r--lib/cosFileTransfer/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/cosFileTransfer/ebin/.gitignore0
-rw-r--r--lib/cosFileTransfer/examples/.gitignore0
-rw-r--r--lib/cosFileTransfer/include/.gitignore0
-rw-r--r--lib/cosFileTransfer/info3
-rw-r--r--lib/cosFileTransfer/priv/.gitignore0
-rw-r--r--lib/cosFileTransfer/src/CosFileTransfer.cfg10
-rw-r--r--lib/cosFileTransfer/src/CosFileTransfer.idl157
-rw-r--r--lib/cosFileTransfer/src/CosFileTransfer_Directory_impl.erl453
-rw-r--r--lib/cosFileTransfer/src/CosFileTransfer_FileIterator_impl.erl158
-rw-r--r--lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl1061
-rw-r--r--lib/cosFileTransfer/src/CosFileTransfer_File_impl.erl385
-rw-r--r--lib/cosFileTransfer/src/CosFileTransfer_VirtualFileSystem_impl.erl217
-rw-r--r--lib/cosFileTransfer/src/Makefile188
-rw-r--r--lib/cosFileTransfer/src/cosFileTransfer.app.src43
-rw-r--r--lib/cosFileTransfer/src/cosFileTransfer.appup.src7
-rw-r--r--lib/cosFileTransfer/src/cosFileTransferApp.erl471
-rw-r--r--lib/cosFileTransfer/src/cosFileTransferApp.hrl69
-rw-r--r--lib/cosFileTransfer/src/cosFileTransferNATIVE_file.erl359
-rw-r--r--lib/cosFileTransfer/test/Makefile132
-rw-r--r--lib/cosFileTransfer/test/cosFileTransfer.cover2
-rw-r--r--lib/cosFileTransfer/test/cosFileTransfer.spec1
-rw-r--r--lib/cosFileTransfer/test/fileTransfer_SUITE.erl938
-rw-r--r--lib/cosFileTransfer/vsn.mk1
-rw-r--r--lib/cosNotification/AUTHORS4
-rw-r--r--lib/cosNotification/Makefile42
-rw-r--r--lib/cosNotification/doc/html/.gitignore0
-rw-r--r--lib/cosNotification/doc/man3/.gitignore0
-rw-r--r--lib/cosNotification/doc/man6/.gitignore0
-rw-r--r--lib/cosNotification/doc/pdf/.gitignore0
-rw-r--r--lib/cosNotification/doc/src/CosNotification.xml235
-rw-r--r--lib/cosNotification/doc/src/CosNotification_AdminPropertiesAdmin.xml79
-rw-r--r--lib/cosNotification/doc/src/CosNotification_QoSAdmin.xml107
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_ConsumerAdmin.xml242
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_EventChannel.xml226
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_EventChannelFactory.xml89
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyConsumer.xml128
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPullConsumer.xml113
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPullSupplier.xml112
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPushConsumer.xml98
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPushSupplier.xml110
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxySupplier.xml175
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPullConsumer.xml112
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPullSupplier.xml146
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPushConsumer.xml109
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPushSupplier.xml111
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPullConsumer.xml110
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPullSupplier.xml140
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPushConsumer.xml110
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPushSupplier.xml110
-rw-r--r--lib/cosNotification/doc/src/CosNotifyChannelAdmin_SupplierAdmin.xml195
-rw-r--r--lib/cosNotification/doc/src/CosNotifyComm_NotifyPublish.xml66
-rw-r--r--lib/cosNotification/doc/src/CosNotifyComm_NotifySubscribe.xml64
-rw-r--r--lib/cosNotification/doc/src/CosNotifyFilter_Filter.xml223
-rw-r--r--lib/cosNotification/doc/src/CosNotifyFilter_FilterAdmin.xml112
-rw-r--r--lib/cosNotification/doc/src/CosNotifyFilter_FilterFactory.xml74
-rw-r--r--lib/cosNotification/doc/src/CosNotifyFilter_MappingFilter.xml228
-rw-r--r--lib/cosNotification/doc/src/Makefile172
-rw-r--r--lib/cosNotification/doc/src/book.gifbin1081 -> 0 bytes
-rw-r--r--lib/cosNotification/doc/src/book.xml49
-rw-r--r--lib/cosNotification/doc/src/ch_BNF.xml457
-rw-r--r--lib/cosNotification/doc/src/ch_QoS.xml252
-rw-r--r--lib/cosNotification/doc/src/ch_contents.xml75
-rw-r--r--lib/cosNotification/doc/src/ch_example.xml170
-rw-r--r--lib/cosNotification/doc/src/ch_install.xml147
-rw-r--r--lib/cosNotification/doc/src/ch_introduction.xml58
-rw-r--r--lib/cosNotification/doc/src/ch_system.xml84
-rw-r--r--lib/cosNotification/doc/src/cosNotificationApp.xml309
-rw-r--r--lib/cosNotification/doc/src/eventstructure.gifbin89760 -> 0 bytes
-rw-r--r--lib/cosNotification/doc/src/fascicules.xml18
-rw-r--r--lib/cosNotification/doc/src/notes.gifbin2005 -> 0 bytes
-rw-r--r--lib/cosNotification/doc/src/notes.xml617
-rw-r--r--lib/cosNotification/doc/src/notificationFlow.gifbin167734 -> 0 bytes
-rw-r--r--lib/cosNotification/doc/src/part.xml43
-rw-r--r--lib/cosNotification/doc/src/part_notes.xml37
-rw-r--r--lib/cosNotification/doc/src/ref_man.gifbin1530 -> 0 bytes
-rw-r--r--lib/cosNotification/doc/src/ref_man.xml64
-rw-r--r--lib/cosNotification/doc/src/summary.html.src1
-rw-r--r--lib/cosNotification/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/cosNotification/ebin/.gitignore0
-rw-r--r--lib/cosNotification/examples/.gitignore0
-rw-r--r--lib/cosNotification/include/.gitignore0
-rw-r--r--lib/cosNotification/info3
-rw-r--r--lib/cosNotification/priv/.gitignore0
-rw-r--r--lib/cosNotification/src/CosEvent.cfg20
-rw-r--r--lib/cosNotification/src/CosNotification.cfg0
-rw-r--r--lib/cosNotification/src/CosNotification.idl146
-rw-r--r--lib/cosNotification/src/CosNotification_Common.erl1240
-rw-r--r--lib/cosNotification/src/CosNotification_Definitions.hrl343
-rw-r--r--lib/cosNotification/src/CosNotifyChannelAdmin.cfg60
-rw-r--r--lib/cosNotification/src/CosNotifyChannelAdmin.idl275
-rw-r--r--lib/cosNotification/src/CosNotifyChannelAdmin_ConsumerAdmin_impl.erl671
-rw-r--r--lib/cosNotification/src/CosNotifyChannelAdmin_EventChannelFactory_impl.erl143
-rw-r--r--lib/cosNotification/src/CosNotifyChannelAdmin_EventChannel_impl.erl722
-rw-r--r--lib/cosNotification/src/CosNotifyChannelAdmin_SupplierAdmin_impl.erl580
-rw-r--r--lib/cosNotification/src/CosNotifyComm.cfg0
-rw-r--r--lib/cosNotification/src/CosNotifyComm.idl83
-rw-r--r--lib/cosNotification/src/CosNotifyFilter.cfg6
-rw-r--r--lib/cosNotification/src/CosNotifyFilter.idl140
-rw-r--r--lib/cosNotification/src/CosNotifyFilter_FilterFactory_impl.erl126
-rw-r--r--lib/cosNotification/src/CosNotifyFilter_Filter_impl.erl672
-rw-r--r--lib/cosNotification/src/CosNotifyFilter_MappingFilter_impl.erl580
-rw-r--r--lib/cosNotification/src/CosTypedEvent.idl57
-rw-r--r--lib/cosNotification/src/CosTypedNotification.idl109
-rw-r--r--lib/cosNotification/src/Makefile379
-rw-r--r--lib/cosNotification/src/PullerConsumer_impl.erl774
-rw-r--r--lib/cosNotification/src/PullerSupplier_impl.erl915
-rw-r--r--lib/cosNotification/src/PusherConsumer_impl.erl730
-rw-r--r--lib/cosNotification/src/PusherSupplier_impl.erl1053
-rw-r--r--lib/cosNotification/src/cosNotification.app.src122
-rw-r--r--lib/cosNotification/src/cosNotification.appup.src7
-rw-r--r--lib/cosNotification/src/cosNotificationApp.erl436
-rw-r--r--lib/cosNotification/src/cosNotificationAppComm.idl17
-rw-r--r--lib/cosNotification/src/cosNotificationComm.cfg3
-rw-r--r--lib/cosNotification/src/cosNotification_Filter.erl965
-rw-r--r--lib/cosNotification/src/cosNotification_Grammar.yrl168
-rw-r--r--lib/cosNotification/src/cosNotification_Scanner.erl269
-rw-r--r--lib/cosNotification/src/cosNotification_eventDB.erl1351
-rw-r--r--lib/cosNotification/test/Makefile192
-rw-r--r--lib/cosNotification/test/cosNotification.cover2
-rw-r--r--lib/cosNotification/test/cosNotification.spec1
-rw-r--r--lib/cosNotification/test/eventDB_SUITE.erl896
-rw-r--r--lib/cosNotification/test/generated_SUITE.erl1928
-rw-r--r--lib/cosNotification/test/grammar_SUITE.erl1091
-rw-r--r--lib/cosNotification/test/notification_SUITE.erl2163
-rw-r--r--lib/cosNotification/test/notify_test_impl.erl300
-rw-r--r--lib/cosNotification/test/notify_test_server.cfg55
-rw-r--r--lib/cosNotification/test/notify_test_server.idl114
-rw-r--r--lib/cosNotification/vsn.mk2
-rw-r--r--lib/cosProperty/AUTHORS4
-rw-r--r--lib/cosProperty/Makefile42
-rw-r--r--lib/cosProperty/doc/html/.gitignore0
-rw-r--r--lib/cosProperty/doc/man3/.gitignore0
-rw-r--r--lib/cosProperty/doc/man6/.gitignore0
-rw-r--r--lib/cosProperty/doc/pdf/.gitignore0
-rw-r--r--lib/cosProperty/doc/src/CosPropertyService_PropertiesIterator.xml95
-rw-r--r--lib/cosProperty/doc/src/CosPropertyService_PropertyNamesIterator.xml97
-rw-r--r--lib/cosProperty/doc/src/CosPropertyService_PropertySet.xml201
-rw-r--r--lib/cosProperty/doc/src/CosPropertyService_PropertySetDef.xml168
-rw-r--r--lib/cosProperty/doc/src/CosPropertyService_PropertySetDefFactory.xml95
-rw-r--r--lib/cosProperty/doc/src/CosPropertyService_PropertySetFactory.xml93
-rw-r--r--lib/cosProperty/doc/src/Makefile149
-rw-r--r--lib/cosProperty/doc/src/book.gifbin1081 -> 0 bytes
-rw-r--r--lib/cosProperty/doc/src/book.xml49
-rw-r--r--lib/cosProperty/doc/src/ch_contents.xml75
-rw-r--r--lib/cosProperty/doc/src/ch_example.xml76
-rw-r--r--lib/cosProperty/doc/src/ch_install.xml56
-rw-r--r--lib/cosProperty/doc/src/ch_introduction.xml54
-rw-r--r--lib/cosProperty/doc/src/cosProperty.xml150
-rw-r--r--lib/cosProperty/doc/src/fascicules.xml18
-rw-r--r--lib/cosProperty/doc/src/notes.gifbin2005 -> 0 bytes
-rw-r--r--lib/cosProperty/doc/src/notes.xml362
-rw-r--r--lib/cosProperty/doc/src/part.xml40
-rw-r--r--lib/cosProperty/doc/src/part_notes.xml37
-rw-r--r--lib/cosProperty/doc/src/ref_man.gifbin1530 -> 0 bytes
-rw-r--r--lib/cosProperty/doc/src/ref_man.xml43
-rw-r--r--lib/cosProperty/doc/src/summary.html.src1
-rw-r--r--lib/cosProperty/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/cosProperty/ebin/.gitignore0
-rw-r--r--lib/cosProperty/examples/.gitignore0
-rw-r--r--lib/cosProperty/include/.gitignore0
-rw-r--r--lib/cosProperty/info2
-rw-r--r--lib/cosProperty/priv/.gitignore0
-rw-r--r--lib/cosProperty/src/CosProperty.cfg5
-rw-r--r--lib/cosProperty/src/CosProperty.idl192
-rw-r--r--lib/cosProperty/src/CosPropertyService_PropertiesIterator_impl.erl167
-rw-r--r--lib/cosProperty/src/CosPropertyService_PropertyNamesIterator_impl.erl159
-rw-r--r--lib/cosProperty/src/CosPropertyService_PropertySetDefFactory_impl.erl186
-rw-r--r--lib/cosProperty/src/CosPropertyService_PropertySetDef_impl.erl1042
-rw-r--r--lib/cosProperty/src/CosPropertyService_PropertySetFactory_impl.erl183
-rw-r--r--lib/cosProperty/src/Makefile188
-rw-r--r--lib/cosProperty/src/cosProperty.app.src47
-rw-r--r--lib/cosProperty/src/cosProperty.appup.src6
-rw-r--r--lib/cosProperty/src/cosProperty.erl416
-rw-r--r--lib/cosProperty/src/cosProperty.hrl82
-rw-r--r--lib/cosProperty/test/Makefile129
-rw-r--r--lib/cosProperty/test/cosProperty.cover2
-rw-r--r--lib/cosProperty/test/cosProperty.spec1
-rw-r--r--lib/cosProperty/test/generated_SUITE.erl546
-rw-r--r--lib/cosProperty/test/property_SUITE.erl736
-rw-r--r--lib/cosProperty/vsn.mk2
-rw-r--r--lib/cosTime/AUTHORS4
-rw-r--r--lib/cosTime/Makefile42
-rw-r--r--lib/cosTime/doc/html/.gitignore0
-rw-r--r--lib/cosTime/doc/man3/.gitignore0
-rw-r--r--lib/cosTime/doc/man6/.gitignore0
-rw-r--r--lib/cosTime/doc/pdf/.gitignore0
-rw-r--r--lib/cosTime/doc/src/CosTime_TIO.xml109
-rw-r--r--lib/cosTime/doc/src/CosTime_TimeService.xml104
-rw-r--r--lib/cosTime/doc/src/CosTime_UTO.xml156
-rw-r--r--lib/cosTime/doc/src/CosTimerEvent_TimerEventHandler.xml125
-rw-r--r--lib/cosTime/doc/src/CosTimerEvent_TimerEventService.xml84
-rw-r--r--lib/cosTime/doc/src/Makefile143
-rw-r--r--lib/cosTime/doc/src/book.gifbin1081 -> 0 bytes
-rw-r--r--lib/cosTime/doc/src/book.xml49
-rw-r--r--lib/cosTime/doc/src/ch_contents.xml75
-rw-r--r--lib/cosTime/doc/src/ch_example.xml113
-rw-r--r--lib/cosTime/doc/src/ch_install.xml56
-rw-r--r--lib/cosTime/doc/src/ch_introduction.xml59
-rw-r--r--lib/cosTime/doc/src/cosTime.xml175
-rw-r--r--lib/cosTime/doc/src/fascicules.xml18
-rw-r--r--lib/cosTime/doc/src/notes.gifbin2005 -> 0 bytes
-rw-r--r--lib/cosTime/doc/src/notes.xml345
-rw-r--r--lib/cosTime/doc/src/part.xml40
-rw-r--r--lib/cosTime/doc/src/part_notes.xml37
-rw-r--r--lib/cosTime/doc/src/ref_man.gifbin1530 -> 0 bytes
-rw-r--r--lib/cosTime/doc/src/ref_man.xml42
-rw-r--r--lib/cosTime/doc/src/summary.html.src1
-rw-r--r--lib/cosTime/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/cosTime/ebin/.gitignore0
-rw-r--r--lib/cosTime/examples/.gitignore0
-rw-r--r--lib/cosTime/include/.gitignore0
-rw-r--r--lib/cosTime/info12
-rw-r--r--lib/cosTime/priv/.gitignore0
-rw-r--r--lib/cosTime/src/CosTime.cfg6
-rw-r--r--lib/cosTime/src/CosTime.idl59
-rw-r--r--lib/cosTime/src/CosTime_TIO_impl.erl201
-rw-r--r--lib/cosTime/src/CosTime_TimeService_impl.erl182
-rw-r--r--lib/cosTime/src/CosTime_UTO_impl.erl242
-rw-r--r--lib/cosTime/src/CosTimerEvent.cfg4
-rw-r--r--lib/cosTime/src/CosTimerEvent.idl45
-rw-r--r--lib/cosTime/src/CosTimerEvent_TimerEventHandler_impl.erl305
-rw-r--r--lib/cosTime/src/CosTimerEvent_TimerEventService_impl.erl119
-rw-r--r--lib/cosTime/src/Makefile207
-rw-r--r--lib/cosTime/src/TimeBase.idl22
-rw-r--r--lib/cosTime/src/cosTime.app.src32
-rw-r--r--lib/cosTime/src/cosTime.appup.src6
-rw-r--r--lib/cosTime/src/cosTime.erl343
-rw-r--r--lib/cosTime/src/cosTimeApp.hrl77
-rw-r--r--lib/cosTime/test/Makefile135
-rw-r--r--lib/cosTime/test/cosTime.cover2
-rw-r--r--lib/cosTime/test/cosTime.spec1
-rw-r--r--lib/cosTime/test/generated_SUITE.erl289
-rw-r--r--lib/cosTime/test/time_SUITE.erl301
-rw-r--r--lib/cosTime/vsn.mk2
-rw-r--r--lib/cosTransactions/AUTHORS4
-rw-r--r--lib/cosTransactions/Makefile42
-rw-r--r--lib/cosTransactions/doc/html/.gitignore0
-rw-r--r--lib/cosTransactions/doc/man3/.gitignore0
-rw-r--r--lib/cosTransactions/doc/man6/.gitignore0
-rw-r--r--lib/cosTransactions/doc/pdf/.gitignore0
-rw-r--r--lib/cosTransactions/doc/src/CosTransactions_Control.xml74
-rw-r--r--lib/cosTransactions/doc/src/CosTransactions_Coordinator.xml230
-rw-r--r--lib/cosTransactions/doc/src/CosTransactions_RecoveryCoordinator.xml82
-rw-r--r--lib/cosTransactions/doc/src/CosTransactions_Resource.xml129
-rw-r--r--lib/cosTransactions/doc/src/CosTransactions_SubtransactionAwareResource.xml75
-rw-r--r--lib/cosTransactions/doc/src/CosTransactions_Synchronization.xml70
-rw-r--r--lib/cosTransactions/doc/src/CosTransactions_Terminator.xml73
-rw-r--r--lib/cosTransactions/doc/src/CosTransactions_TransactionFactory.xml64
-rw-r--r--lib/cosTransactions/doc/src/CosTransactions_TransactionalObject.xml43
-rw-r--r--lib/cosTransactions/doc/src/Makefile147
-rw-r--r--lib/cosTransactions/doc/src/book.gifbin1081 -> 0 bytes
-rw-r--r--lib/cosTransactions/doc/src/book.xml49
-rw-r--r--lib/cosTransactions/doc/src/ch_contents.xml75
-rw-r--r--lib/cosTransactions/doc/src/ch_example.xml283
-rw-r--r--lib/cosTransactions/doc/src/ch_install.xml104
-rw-r--r--lib/cosTransactions/doc/src/ch_introduction.xml65
-rw-r--r--lib/cosTransactions/doc/src/ch_skeletons.xml214
-rw-r--r--lib/cosTransactions/doc/src/cosTransactions.xml142
-rw-r--r--lib/cosTransactions/doc/src/fascicules.xml18
-rw-r--r--lib/cosTransactions/doc/src/notes.gifbin2005 -> 0 bytes
-rw-r--r--lib/cosTransactions/doc/src/notes.xml392
-rw-r--r--lib/cosTransactions/doc/src/part.xml41
-rw-r--r--lib/cosTransactions/doc/src/part_notes.xml37
-rw-r--r--lib/cosTransactions/doc/src/ref_man.gifbin1530 -> 0 bytes
-rw-r--r--lib/cosTransactions/doc/src/ref_man.xml44
-rw-r--r--lib/cosTransactions/doc/src/summary.html.src1
-rw-r--r--lib/cosTransactions/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/cosTransactions/ebin/.gitignore0
-rw-r--r--lib/cosTransactions/examples/Makefile158
-rw-r--r--lib/cosTransactions/include/.gitignore0
-rw-r--r--lib/cosTransactions/info2
-rw-r--r--lib/cosTransactions/priv/.gitignore0
-rw-r--r--lib/cosTransactions/src/CosTransactions.cfg15
-rw-r--r--lib/cosTransactions/src/CosTransactions.idl193
-rw-r--r--lib/cosTransactions/src/CosTransactions_Terminator_impl.erl363
-rw-r--r--lib/cosTransactions/src/CosTransactions_TransactionFactory_impl.erl180
-rw-r--r--lib/cosTransactions/src/ETraP_Common.erl187
-rw-r--r--lib/cosTransactions/src/ETraP_Common.hrl341
-rw-r--r--lib/cosTransactions/src/ETraP_Server_impl.erl1745
-rw-r--r--lib/cosTransactions/src/Makefile181
-rw-r--r--lib/cosTransactions/src/cosTransactions.app.src44
-rw-r--r--lib/cosTransactions/src/cosTransactions.appup.src6
-rw-r--r--lib/cosTransactions/src/cosTransactions.erl116
-rw-r--r--lib/cosTransactions/src/etrap_logmgr.erl201
-rw-r--r--lib/cosTransactions/test/Makefile151
-rw-r--r--lib/cosTransactions/test/cosTransactions.cover2
-rw-r--r--lib/cosTransactions/test/cosTransactions.spec1
-rw-r--r--lib/cosTransactions/test/etrap_test.cfg21
-rw-r--r--lib/cosTransactions/test/etrap_test.idl39
-rw-r--r--lib/cosTransactions/test/etrap_test_lib.erl126
-rw-r--r--lib/cosTransactions/test/etrap_test_lib.hrl101
-rw-r--r--lib/cosTransactions/test/etrap_test_server_impl.erl211
-rw-r--r--lib/cosTransactions/test/generated_SUITE.erl543
-rw-r--r--lib/cosTransactions/test/transactions_SUITE.erl396
-rw-r--r--lib/cosTransactions/vsn.mk1
-rw-r--r--lib/crypto/c_src/Makefile.in25
-rw-r--r--lib/crypto/c_src/crypto.c3661
-rw-r--r--lib/crypto/c_src/otp_test_engine.c280
-rw-r--r--lib/crypto/doc/specs/.gitignore1
-rw-r--r--lib/crypto/doc/src/Makefile28
-rw-r--r--lib/crypto/doc/src/algorithm_details.xml297
-rw-r--r--lib/crypto/doc/src/crypto.xml1527
-rw-r--r--lib/crypto/doc/src/crypto_app.xml18
-rw-r--r--lib/crypto/doc/src/engine_keys.xml129
-rw-r--r--lib/crypto/doc/src/engine_load.xml129
-rw-r--r--lib/crypto/doc/src/fascicules.xml18
-rw-r--r--lib/crypto/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/crypto/doc/src/notes.xml377
-rw-r--r--lib/crypto/doc/src/specs.xml4
-rw-r--r--lib/crypto/doc/src/usersguide.xml10
-rw-r--r--lib/crypto/doc/src/warning.gifbin1498 -> 0 bytes
-rw-r--r--lib/crypto/src/Makefile20
-rw-r--r--lib/crypto/src/crypto.app.src2
-rw-r--r--lib/crypto/src/crypto.erl1584
-rw-r--r--lib/crypto/src/crypto_ec_curves.erl36
-rw-r--r--lib/crypto/test/Makefile7
-rw-r--r--lib/crypto/test/blowfish_SUITE.erl7
-rw-r--r--lib/crypto/test/crypto_SUITE.erl934
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VADT128.rsp1823
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VADT192.rsp1823
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VADT256.rsp1823
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VNT128.rsp456
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VNT192.rsp456
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VNT256.rsp456
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VPT128.rsp1383
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VPT192.rsp1383
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VPT256.rsp1383
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.rsp1589
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.txt1589
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.rsp1589
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.txt1589
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.rsp1589
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.txt1589
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/Readme.txt9
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT128.rsp1823
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT192.rsp1823
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT256.rsp1823
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT128.rsp456
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT192.rsp456
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT256.rsp456
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT128.rsp1383
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT192.rsp1383
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT256.rsp1383
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT128.rsp393
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT192.rsp393
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT256.rsp393
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/ccmtestvectors.zipbin0 -> 319267 bytes
-rw-r--r--lib/crypto/test/engine_SUITE.erl875
-rw-r--r--lib/crypto/test/engine_SUITE_data/pkcs8/dsa_private_key.pem9
-rw-r--r--lib/crypto/test/engine_SUITE_data/pkcs8/dsa_public_key.pem12
-rw-r--r--lib/crypto/test/engine_SUITE_data/pkcs8/ecdsa_private_key.pem8
-rw-r--r--lib/crypto/test/engine_SUITE_data/pkcs8/ecdsa_public_key.pem6
-rw-r--r--lib/crypto/test/engine_SUITE_data/pkcs8/rsa_private_key.pem28
-rw-r--r--lib/crypto/test/engine_SUITE_data/pkcs8/rsa_private_key_pwd.pem30
-rw-r--r--lib/crypto/test/engine_SUITE_data/pkcs8/rsa_public_key.pem9
-rw-r--r--lib/crypto/test/engine_SUITE_data/pkcs8/rsa_public_key_pwd.pem9
-rw-r--r--lib/crypto/vsn.mk2
-rw-r--r--lib/debugger/doc/src/Makefile5
-rw-r--r--lib/debugger/doc/src/fascicules.xml15
-rw-r--r--lib/debugger/doc/src/notes.xml62
-rw-r--r--lib/debugger/src/dbg_debugged.erl40
-rw-r--r--lib/debugger/src/dbg_icmd.erl4
-rw-r--r--lib/debugger/src/dbg_ieval.erl15
-rw-r--r--lib/debugger/src/dbg_wx_break_win.erl4
-rw-r--r--lib/debugger/src/dbg_wx_mon.erl6
-rw-r--r--lib/debugger/src/dbg_wx_mon_win.erl4
-rw-r--r--lib/debugger/src/dbg_wx_trace.erl29
-rw-r--r--lib/debugger/src/dbg_wx_win.erl4
-rw-r--r--lib/debugger/src/debugger.app.src4
-rw-r--r--lib/debugger/src/i.erl10
-rw-r--r--lib/debugger/test/guard_SUITE.erl7
-rw-r--r--lib/debugger/test/int_eval_SUITE.erl11
-rw-r--r--lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl6
-rw-r--r--lib/debugger/vsn.mk2
-rw-r--r--lib/dialyzer/doc/src/Makefile19
-rw-r--r--lib/dialyzer/doc/src/fascicules.xml18
-rw-r--r--lib/dialyzer/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/dialyzer/doc/src/notes.xml169
-rw-r--r--lib/dialyzer/doc/src/part_notes.xml37
-rw-r--r--lib/dialyzer/doc/src/warning.gifbin1498 -> 0 bytes
-rw-r--r--lib/dialyzer/src/dialyzer.app.src4
-rw-r--r--lib/dialyzer/src/dialyzer.erl24
-rw-r--r--lib/dialyzer/src/dialyzer_analysis_callgraph.erl6
-rw-r--r--lib/dialyzer/src/dialyzer_cl.erl2
-rw-r--r--lib/dialyzer/src/dialyzer_cl_parse.erl6
-rw-r--r--lib/dialyzer/src/dialyzer_contracts.erl102
-rw-r--r--lib/dialyzer/src/dialyzer_dataflow.erl71
-rw-r--r--lib/dialyzer/src/dialyzer_gui_wx.erl6
-rw-r--r--lib/dialyzer/src/dialyzer_plt.erl29
-rw-r--r--lib/dialyzer/src/dialyzer_races.erl66
-rw-r--r--lib/dialyzer/src/dialyzer_typesig.erl22
-rw-r--r--lib/dialyzer/src/dialyzer_utils.erl108
-rw-r--r--lib/dialyzer/src/typer.erl19
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args2
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/proper/proper_typeserver.erl10
-rw-r--r--lib/dialyzer/test/dialyzer_common.erl10
-rw-r--r--lib/dialyzer/test/map_SUITE_data/results/loop4
-rw-r--r--lib/dialyzer/test/map_SUITE_data/results/map_anon_fun2
-rw-r--r--lib/dialyzer/test/map_SUITE_data/results/map_galore12
-rw-r--r--lib/dialyzer/test/map_SUITE_data/results/opaque_key1
-rw-r--r--lib/dialyzer/test/map_SUITE_data/src/loop.erl92
-rw-r--r--lib/dialyzer/test/map_SUITE_data/src/map_anon_fun.erl9
-rw-r--r--lib/dialyzer/test/map_SUITE_data/src/opaque_key/opaque_key_adt.erl2
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/para_bug/same.erl15
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/para_bug/same_type.erl13
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl10
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/results/compiler2
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_validator.erl2
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/compile.erl6
-rw-r--r--lib/dialyzer/test/options2_SUITE_data/results/unused_unknown_type2
-rw-r--r--lib/dialyzer/test/options2_SUITE_data/src/unused_unknown_type.erl32
-rw-r--r--lib/dialyzer/test/overspecs_SUITE_data/dialyzer_options1
-rw-r--r--lib/dialyzer/test/overspecs_SUITE_data/results/iodata2
-rw-r--r--lib/dialyzer/test/overspecs_SUITE_data/results/iolist2
-rw-r--r--lib/dialyzer/test/overspecs_SUITE_data/src/iodata.erl41
-rw-r--r--lib/dialyzer/test/overspecs_SUITE_data/src/iolist.erl41
-rw-r--r--lib/dialyzer/test/plt_SUITE.erl40
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_esi.erl2
-rw-r--r--lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_tm.erl2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/chars6
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/extra_range4
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/fun_arity32
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/left_assoc2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/maps_sum2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/record_match3
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/stacktrace5
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/unused_funs5
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/abs.erl9
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/bsL.erl13
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/chars.erl18
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/erl_tar_table.erl14
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/extra_range.erl59
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/left_assoc.erl96
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/record_match.erl17
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/stacktrace.erl73
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/unused_funs.erl21
-rw-r--r--lib/dialyzer/test/specdiffs_SUITE_data/dialyzer_options1
-rw-r--r--lib/dialyzer/test/specdiffs_SUITE_data/results/iodata3
-rw-r--r--lib/dialyzer/test/specdiffs_SUITE_data/results/iolist2
-rw-r--r--lib/dialyzer/test/specdiffs_SUITE_data/src/iodata.erl41
-rw-r--r--lib/dialyzer/test/specdiffs_SUITE_data/src/iolist.erl41
-rw-r--r--lib/dialyzer/vsn.mk2
-rwxr-xr-xlib/diameter/bin/diameterc6
-rw-r--r--lib/diameter/doc/src/Makefile3
-rw-r--r--lib/diameter/doc/src/diameter.xml275
-rw-r--r--lib/diameter/doc/src/diameter_app.xml9
-rw-r--r--lib/diameter/doc/src/diameter_codec.xml25
-rw-r--r--lib/diameter/doc/src/diameter_dict.xml6
-rw-r--r--lib/diameter/doc/src/diameter_sctp.xml63
-rw-r--r--lib/diameter/doc/src/diameter_soc.xml1327
-rw-r--r--lib/diameter/doc/src/diameter_soc_rfc6733.xml8693
-rw-r--r--lib/diameter/doc/src/diameter_tcp.xml58
-rw-r--r--lib/diameter/doc/src/files.mk5
-rw-r--r--lib/diameter/doc/src/notes.xml315
-rw-r--r--lib/diameter/doc/src/seealso.ent7
-rw-r--r--lib/diameter/doc/standard/rfc7683.txt2355
-rw-r--r--lib/diameter/examples/code/client.erl10
-rw-r--r--lib/diameter/examples/code/client_cb.erl29
-rw-r--r--lib/diameter/examples/code/node.erl29
-rw-r--r--lib/diameter/include/diameter_gen.hrl8
-rw-r--r--lib/diameter/src/Makefile11
-rw-r--r--lib/diameter/src/app.sed41
-rw-r--r--lib/diameter/src/base/diameter.erl71
-rw-r--r--lib/diameter/src/base/diameter_callback.erl6
-rw-r--r--lib/diameter/src/base/diameter_codec.erl217
-rw-r--r--lib/diameter/src/base/diameter_config.erl285
-rw-r--r--lib/diameter/src/base/diameter_gen.erl1002
-rw-r--r--lib/diameter/src/base/diameter_internal.hrl5
-rw-r--r--lib/diameter/src/base/diameter_lib.erl17
-rw-r--r--lib/diameter/src/base/diameter_peer.erl6
-rw-r--r--lib/diameter/src/base/diameter_peer_fsm.erl241
-rw-r--r--lib/diameter/src/base/diameter_reg.erl253
-rw-r--r--lib/diameter/src/base/diameter_service.erl141
-rw-r--r--lib/diameter/src/base/diameter_traffic.erl479
-rw-r--r--lib/diameter/src/base/diameter_watchdog.erl39
-rw-r--r--lib/diameter/src/compiler/diameter_codegen.erl17
-rw-r--r--lib/diameter/src/compiler/diameter_dict_util.erl4
-rw-r--r--lib/diameter/src/compiler/diameter_exprecs.erl6
-rw-r--r--lib/diameter/src/compiler/diameter_make.erl6
-rw-r--r--lib/diameter/src/diameter.app.src17
-rw-r--r--lib/diameter/src/diameter.appup.src20
-rw-r--r--lib/diameter/src/dict/doic_rfc7683.dia50
-rw-r--r--lib/diameter/src/modules.mk1
-rw-r--r--lib/diameter/src/transport/diameter_sctp.erl135
-rw-r--r--lib/diameter/src/transport/diameter_tcp.erl247
-rw-r--r--lib/diameter/test/diameter_app_SUITE.erl14
-rw-r--r--lib/diameter/test/diameter_codec_SUITE.erl3
-rw-r--r--lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl3
-rw-r--r--lib/diameter/test/diameter_codec_test.erl8
-rw-r--r--lib/diameter/test/diameter_event_SUITE.erl11
-rw-r--r--lib/diameter/test/diameter_examples_SUITE.erl4
-rw-r--r--lib/diameter/test/diameter_reg_SUITE.erl11
-rw-r--r--lib/diameter/test/diameter_traffic_SUITE.erl1051
-rw-r--r--lib/diameter/test/diameter_transport_SUITE.erl39
-rw-r--r--lib/diameter/test/diameter_util.erl13
-rw-r--r--lib/diameter/test/diameter_watchdog_SUITE.erl9
-rw-r--r--lib/diameter/vsn.mk4
-rw-r--r--lib/edoc/doc/src/Makefile34
-rw-r--r--lib/edoc/doc/src/fascicules.xml15
-rw-r--r--lib/edoc/doc/src/notes.xml74
-rw-r--r--lib/edoc/doc/src/part_notes.xml39
-rw-r--r--lib/edoc/priv/Makefile17
-rw-r--r--lib/edoc/priv/edoc_generate50
-rw-r--r--lib/edoc/priv/edoc_generate.src74
-rw-r--r--lib/edoc/src/Makefile3
-rw-r--r--lib/edoc/src/edoc.app.src3
-rw-r--r--lib/edoc/src/edoc_doclet.erl8
-rw-r--r--lib/edoc/src/edoc_layout.erl8
-rw-r--r--lib/edoc/src/edoc_lib.erl12
-rw-r--r--lib/edoc/src/edoc_run.erl6
-rw-r--r--lib/edoc/src/edoc_specs.erl4
-rw-r--r--lib/edoc/src/edoc_types.erl2
-rw-r--r--lib/edoc/src/otpsgml_layout.erl836
-rw-r--r--lib/edoc/vsn.mk2
-rw-r--r--lib/eldap/doc/src/Makefile3
-rw-r--r--lib/eldap/doc/src/fascicules.xml18
-rw-r--r--lib/eldap/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/eldap/doc/src/notes.xml47
-rw-r--r--lib/eldap/doc/src/warning.gifbin1498 -> 0 bytes
-rw-r--r--lib/eldap/src/eldap.erl4
-rw-r--r--lib/eldap/test/eldap_basic_SUITE.erl2
-rw-r--r--lib/eldap/vsn.mk2
-rw-r--r--lib/erl_docgen/doc/src/Makefile1
-rw-r--r--lib/erl_docgen/doc/src/fasc_dtds.xml116
-rw-r--r--lib/erl_docgen/doc/src/fascicules.xml15
-rw-r--r--lib/erl_docgen/doc/src/notes.xml90
-rwxr-xr-xlib/erl_docgen/priv/bin/codeline_preprocessing.escript5
-rwxr-xr-xlib/erl_docgen/priv/bin/github_link.escript51
-rwxr-xr-xlib/erl_docgen/priv/bin/xml_from_edoc.escript9
-rw-r--r--lib/erl_docgen/priv/css/otp_doc.css21
-rw-r--r--lib/erl_docgen/priv/dtd/chapter.dtd3
-rw-r--r--lib/erl_docgen/priv/dtd/common.image.dtd4
-rw-r--r--lib/erl_docgen/priv/dtd/common.refs.dtd7
-rw-r--r--lib/erl_docgen/priv/dtd/erlref.dtd1
-rw-r--r--lib/erl_docgen/priv/xsl/Makefile5
-rw-r--r--lib/erl_docgen/priv/xsl/db_eix.xsl81
-rw-r--r--lib/erl_docgen/priv/xsl/db_funcs.xsl136
-rw-r--r--lib/erl_docgen/priv/xsl/db_html.xsl250
-rw-r--r--lib/erl_docgen/priv/xsl/db_man.xsl8
-rw-r--r--lib/erl_docgen/priv/xsl/db_pdf.xsl106
-rw-r--r--lib/erl_docgen/priv/xsl/db_pdf_params.xsl129
-rw-r--r--lib/erl_docgen/src/docgen_edoc_xml_cb.erl6
-rw-r--r--lib/erl_docgen/src/docgen_otp_specs.erl14
-rw-r--r--lib/erl_docgen/src/erl_docgen.app.src2
-rw-r--r--lib/erl_docgen/vsn.mk2
-rw-r--r--lib/erl_interface/configure.in15
-rw-r--r--lib/erl_interface/doc/src/Makefile32
-rw-r--r--lib/erl_interface/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/erl_interface/doc/src/notes.xml143
-rw-r--r--lib/erl_interface/doc/src/part_notes.xml39
-rw-r--r--lib/erl_interface/doc/src/part_notes_history.xml37
-rw-r--r--lib/erl_interface/doc/src/warning.gifbin1498 -> 0 bytes
-rw-r--r--lib/erl_interface/src/Makefile4
-rw-r--r--lib/erl_interface/src/Makefile.in4
-rw-r--r--lib/erl_interface/src/connect/ei_connect.c109
-rw-r--r--lib/erl_interface/src/connect/ei_resolve.c7
-rw-r--r--lib/erl_interface/src/decode/decode_atom.c64
-rw-r--r--lib/erl_interface/src/legacy/erl_marshal.c6
-rw-r--r--lib/erl_interface/src/misc/ei_pthreads.c3
-rw-r--r--lib/erl_interface/src/prog/erl_call.c15
-rw-r--r--lib/erl_interface/test/ei_accept_SUITE.erl117
-rw-r--r--lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c43
-rw-r--r--lib/erl_interface/test/ei_connect_SUITE.erl18
-rw-r--r--lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c14
-rw-r--r--lib/erl_interface/test/ei_decode_SUITE.erl22
-rw-r--r--lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c7
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE.erl8
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c3
-rw-r--r--lib/erl_interface/test/ei_encode_SUITE.erl24
-rw-r--r--lib/erl_interface/test/ei_format_SUITE.erl14
-rw-r--r--lib/erl_interface/test/ei_print_SUITE.erl14
-rw-r--r--lib/erl_interface/test/ei_tmo_SUITE.erl30
-rw-r--r--lib/erl_interface/test/ei_tmo_SUITE_data/ei_tmo_test.c3
-rw-r--r--lib/erl_interface/test/erl_connect_SUITE.erl12
-rw-r--r--lib/erl_interface/test/erl_eterm_SUITE.erl80
-rw-r--r--lib/erl_interface/test/erl_ext_SUITE.erl15
-rw-r--r--lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c14
-rw-r--r--lib/erl_interface/test/erl_format_SUITE.erl12
-rw-r--r--lib/erl_interface/test/erl_global_SUITE.erl11
-rw-r--r--lib/erl_interface/test/erl_match_SUITE.erl9
-rw-r--r--lib/erl_interface/test/port_call_SUITE.erl8
-rw-r--r--lib/erl_interface/test/runner.erl65
-rw-r--r--lib/erl_interface/vsn.mk2
-rw-r--r--lib/et/doc/src/Makefile8
-rw-r--r--lib/et/doc/src/et_collector.xml10
-rw-r--r--lib/et/doc/src/et_selector.xml6
-rw-r--r--lib/et/doc/src/files.mk9
-rw-r--r--lib/et/doc/src/notes.xml47
-rw-r--r--lib/et/src/et.app.src6
-rw-r--r--lib/et/src/et_collector.erl38
-rw-r--r--lib/et/src/et_selector.erl8
-rw-r--r--lib/et/src/et_wx_contents_viewer.erl25
-rw-r--r--lib/et/src/et_wx_viewer.erl24
-rw-r--r--lib/et/test/et_test_lib.erl4
-rw-r--r--lib/et/test/ett.erl4
-rw-r--r--lib/et/vsn.mk2
-rw-r--r--lib/eunit/doc/src/Makefile38
-rw-r--r--lib/eunit/doc/src/fascicules.xml18
-rw-r--r--lib/eunit/doc/src/notes.xml62
-rw-r--r--lib/eunit/doc/src/part_notes.xml40
-rw-r--r--lib/eunit/src/eunit.app.src2
-rw-r--r--lib/eunit/src/eunit_lib.erl28
-rw-r--r--lib/eunit/src/eunit_listener.erl3
-rw-r--r--lib/eunit/src/eunit_proc.erl2
-rw-r--r--lib/eunit/src/eunit_test.erl51
-rw-r--r--lib/eunit/src/eunit_tty.erl2
-rw-r--r--lib/eunit/vsn.mk2
-rw-r--r--lib/ftp/AUTHORS11
-rw-r--r--lib/ftp/Makefile78
-rw-r--r--lib/ftp/doc/archive/rfc2428.txt (renamed from lib/inets/doc/archive/rfc2428.txt)0
-rw-r--r--lib/ftp/doc/archive/rfc2577.txt (renamed from lib/inets/doc/archive/rfc2577.txt)0
-rw-r--r--lib/ftp/doc/archive/rfc959.txt (renamed from lib/inets/doc/archive/rfc959.txt)0
-rw-r--r--lib/ftp/doc/html/.gitignore (renamed from lib/cosEvent/doc/html/.gitignore)0
-rw-r--r--lib/ftp/doc/man3/.gitignore (renamed from lib/cosEvent/doc/man3/.gitignore)0
-rw-r--r--lib/ftp/doc/man6/.gitignore (renamed from lib/cosEvent/doc/man6/.gitignore)0
-rw-r--r--lib/ftp/doc/pdf/.gitignore (renamed from lib/cosEvent/doc/pdf/.gitignore)0
-rw-r--r--lib/ftp/doc/src/Makefile155
-rw-r--r--lib/ftp/doc/src/book.xml49
-rw-r--r--lib/ftp/doc/src/ftp.xml983
-rw-r--r--lib/ftp/doc/src/ftp_client.xml86
-rw-r--r--lib/ftp/doc/src/introduction.xml46
-rw-r--r--lib/ftp/doc/src/notes.xml68
-rw-r--r--lib/ftp/doc/src/part.xml37
-rw-r--r--lib/ftp/doc/src/ref_man.xml36
-rw-r--r--lib/ftp/ebin/.gitignore (renamed from lib/cosEvent/ebin/.gitignore)0
-rw-r--r--lib/ftp/info2
-rw-r--r--lib/ftp/src/Makefile118
-rw-r--r--lib/ftp/src/ftp.app.src19
-rw-r--r--lib/ftp/src/ftp.appup.src26
-rw-r--r--lib/ftp/src/ftp.erl2618
-rw-r--r--lib/ftp/src/ftp_app.erl47
-rw-r--r--lib/ftp/src/ftp_internal.hrl35
-rw-r--r--lib/ftp/src/ftp_progress.erl136
-rw-r--r--lib/ftp/src/ftp_response.erl203
-rw-r--r--lib/ftp/src/ftp_sup.erl68
-rw-r--r--lib/ftp/test/Makefile251
-rw-r--r--lib/ftp/test/erl_make_certs.erl475
-rw-r--r--lib/ftp/test/ftp.config1
-rw-r--r--lib/ftp/test/ftp.cover2
-rw-r--r--lib/ftp/test/ftp.spec1
-rw-r--r--lib/ftp/test/ftp_SUITE.erl1263
-rw-r--r--lib/ftp/test/ftp_SUITE_data/ftpd_hosts.skel (renamed from lib/inets/test/ftp_SUITE_data/ftpd_hosts.skel)0
-rw-r--r--lib/ftp/test/ftp_SUITE_data/vsftpd.conf33
-rw-r--r--lib/ftp/test/ftp_bench.spec1
-rw-r--r--lib/ftp/test/ftp_format_SUITE.erl328
l---------lib/ftp/test/ftp_internal.hrl1
-rw-r--r--lib/ftp/test/ftp_property_test_SUITE.erl55
-rw-r--r--lib/ftp/test/ftp_test_lib.erl126
-rw-r--r--lib/ftp/test/property_test/README12
-rw-r--r--lib/ftp/test/property_test/ftp_simple_client_server.erl307
-rw-r--r--lib/ftp/test/property_test/ftp_simple_client_server_data/vsftpd.conf26
-rw-r--r--lib/ftp/vsn.mk24
-rw-r--r--lib/hipe/cerl/Makefile4
-rw-r--r--lib/hipe/cerl/cerl_cconv.erl2
-rw-r--r--lib/hipe/cerl/cerl_messagean.erl1095
-rw-r--r--lib/hipe/cerl/erl_bif_types.erl49
-rw-r--r--lib/hipe/cerl/erl_types.erl352
-rw-r--r--lib/hipe/doc/src/Makefile19
-rw-r--r--lib/hipe/doc/src/fascicules.xml12
-rw-r--r--lib/hipe/doc/src/hipe_app.xml134
-rw-r--r--lib/hipe/doc/src/notes.xml163
-rw-r--r--lib/hipe/doc/src/part_notes.xml36
-rw-r--r--lib/hipe/icode/hipe_beam_to_icode.erl55
-rw-r--r--lib/hipe/icode/hipe_icode.erl30
-rw-r--r--lib/hipe/icode/hipe_icode.hrl8
-rw-r--r--lib/hipe/icode/hipe_icode_inline_bifs.erl22
-rw-r--r--lib/hipe/icode/hipe_icode_liveness.erl1
-rw-r--r--lib/hipe/icode/hipe_icode_pp.erl5
-rw-r--r--lib/hipe/icode/hipe_icode_primops.erl23
-rw-r--r--lib/hipe/icode/hipe_icode_range.erl6
-rw-r--r--lib/hipe/llvm/hipe_llvm.erl13
-rw-r--r--lib/hipe/llvm/hipe_llvm_main.erl2
-rw-r--r--lib/hipe/llvm/hipe_rtl_to_llvm.erl4
-rw-r--r--lib/hipe/main/hipe.app.src8
-rw-r--r--lib/hipe/main/hipe.erl30
-rw-r--r--lib/hipe/main/hipe_main.erl5
-rw-r--r--lib/hipe/opt/hipe_schedule.erl1483
-rw-r--r--lib/hipe/opt/hipe_schedule_prio.erl53
-rw-r--r--lib/hipe/opt/hipe_target_machine.erl87
-rw-r--r--lib/hipe/opt/hipe_ultra_mod2.erl233
-rw-r--r--lib/hipe/opt/hipe_ultra_prio.erl298
-rw-r--r--lib/hipe/rtl/Makefile2
-rw-r--r--lib/hipe/rtl/hipe_rtl.erl5
-rw-r--r--lib/hipe/rtl/hipe_rtl_binary_construct.erl41
-rw-r--r--lib/hipe/rtl/hipe_rtl_binary_match.erl10
-rw-r--r--lib/hipe/rtl/hipe_rtl_cleanup_const.erl4
-rw-r--r--lib/hipe/rtl/hipe_rtl_lcm.erl110
-rw-r--r--lib/hipe/rtl/hipe_rtl_primops.erl29
-rw-r--r--lib/hipe/rtl/hipe_rtl_varmap.erl2
-rw-r--r--lib/hipe/rtl/hipe_rtl_verify_gcsafe.erl89
-rw-r--r--lib/hipe/rtl/hipe_tagscheme.erl141
-rw-r--r--lib/hipe/ssa/hipe_ssa.inc28
-rw-r--r--lib/hipe/test/Makefile3
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_exceptions.erl215
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_issues_hipe.erl28
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_receive.erl89
-rw-r--r--lib/hipe/test/bs_SUITE_data/bs_construct.erl13
-rw-r--r--lib/hipe/test/erl_types_SUITE.erl197
-rw-r--r--lib/hipe/test/hipe_testsuite_driver.erl16
-rw-r--r--lib/hipe/test/opt_verify_SUITE.erl8
-rw-r--r--lib/hipe/test/opt_verify_SUITE_data/call_elim_test_branches_opt_poss.erl10
-rw-r--r--lib/hipe/vsn.mk2
-rw-r--r--lib/hipe/x86/hipe_rtl_to_x86.erl24
-rw-r--r--lib/hipe/x86/hipe_x86_assemble.erl1
-rw-r--r--lib/ic/AUTHORS8
-rw-r--r--lib/ic/Makefile42
-rw-r--r--lib/ic/c_src/Makefile25
-rw-r--r--lib/ic/c_src/Makefile.in165
-rw-r--r--lib/ic/c_src/Makefile.win32109
-rw-r--r--lib/ic/c_src/ic.c613
-rw-r--r--lib/ic/c_src/ic_tmo.c136
-rw-r--r--lib/ic/c_src/oe_ei_code_erlang_binary.c106
-rw-r--r--lib/ic/c_src/oe_ei_decode_longlong.c26
-rw-r--r--lib/ic/c_src/oe_ei_decode_ulonglong.c26
-rw-r--r--lib/ic/c_src/oe_ei_decode_wchar.c26
-rw-r--r--lib/ic/c_src/oe_ei_decode_wstring.c108
-rw-r--r--lib/ic/c_src/oe_ei_encode_atom.c47
-rw-r--r--lib/ic/c_src/oe_ei_encode_char.c45
-rw-r--r--lib/ic/c_src/oe_ei_encode_double.c44
-rw-r--r--lib/ic/c_src/oe_ei_encode_list_header.c42
-rw-r--r--lib/ic/c_src/oe_ei_encode_long.c45
-rw-r--r--lib/ic/c_src/oe_ei_encode_longlong.c45
-rw-r--r--lib/ic/c_src/oe_ei_encode_pid.c46
-rw-r--r--lib/ic/c_src/oe_ei_encode_port.c47
-rw-r--r--lib/ic/c_src/oe_ei_encode_ref.c47
-rw-r--r--lib/ic/c_src/oe_ei_encode_string.c48
-rw-r--r--lib/ic/c_src/oe_ei_encode_term.c49
-rw-r--r--lib/ic/c_src/oe_ei_encode_tuple_header.c45
-rw-r--r--lib/ic/c_src/oe_ei_encode_ulong.c44
-rw-r--r--lib/ic/c_src/oe_ei_encode_ulonglong.c45
-rw-r--r--lib/ic/c_src/oe_ei_encode_version.c43
-rw-r--r--lib/ic/c_src/oe_ei_encode_wchar.c28
-rw-r--r--lib/ic/c_src/oe_ei_encode_wstring.c63
-rw-r--r--lib/ic/doc/html/.gitignore0
-rw-r--r--lib/ic/doc/man1/.gitignore0
-rw-r--r--lib/ic/doc/man3/.gitignore0
-rw-r--r--lib/ic/doc/pdf/.gitignore0
-rw-r--r--lib/ic/doc/src/CORBA_Environment_alloc.xml143
-rw-r--r--lib/ic/doc/src/Makefile232
-rw-r--r--lib/ic/doc/src/book.gifbin1081 -> 0 bytes
-rw-r--r--lib/ic/doc/src/book.xml50
-rw-r--r--lib/ic/doc/src/c-part.xml39
-rw-r--r--lib/ic/doc/src/ch_basic_idl.xml164
-rw-r--r--lib/ic/doc/src/ch_c_client.xml150
-rw-r--r--lib/ic/doc/src/ch_c_corba_env.xml386
-rw-r--r--lib/ic/doc/src/ch_c_mapping.xml893
-rw-r--r--lib/ic/doc/src/ch_c_server.xml149
-rw-r--r--lib/ic/doc/src/ch_erl_genserv.xml206
-rw-r--r--lib/ic/doc/src/ch_erl_plain.xml176
-rw-r--r--lib/ic/doc/src/ch_ic_protocol.xml234
-rw-r--r--lib/ic/doc/src/ch_introduction.xml149
-rw-r--r--lib/ic/doc/src/ch_java.xml738
-rw-r--r--lib/ic/doc/src/erl-part.xml37
-rw-r--r--lib/ic/doc/src/fascicules.xml18
-rw-r--r--lib/ic/doc/src/ic.gifbin17015 -> 0 bytes
-rw-r--r--lib/ic/doc/src/ic.xml468
-rw-r--r--lib/ic/doc/src/ic_c_protocol.xml157
-rw-r--r--lib/ic/doc/src/ic_clib.xml247
-rw-r--r--lib/ic/doc/src/java-part.xml36
-rw-r--r--lib/ic/doc/src/notes.gifbin2005 -> 0 bytes
-rw-r--r--lib/ic/doc/src/notes.xml776
-rw-r--r--lib/ic/doc/src/part.xml46
-rw-r--r--lib/ic/doc/src/part_notes.xml38
-rw-r--r--lib/ic/doc/src/ref_man.gifbin1530 -> 0 bytes
-rw-r--r--lib/ic/doc/src/ref_man.xml39
-rw-r--r--lib/ic/doc/src/summary.html.src1
-rw-r--r--lib/ic/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/ic/ebin/.gitignore0
-rw-r--r--lib/ic/examples/all-against-all/Makefile118
-rw-r--r--lib/ic/examples/all-against-all/Makefile.win32139
-rw-r--r--lib/ic/examples/all-against-all/ReadMe122
-rw-r--r--lib/ic/examples/all-against-all/callbacks.c46
-rw-r--r--lib/ic/examples/all-against-all/client.c154
-rw-r--r--lib/ic/examples/all-against-all/client.erl54
-rw-r--r--lib/ic/examples/all-against-all/client.java61
-rw-r--r--lib/ic/examples/all-against-all/random.idl51
-rw-r--r--lib/ic/examples/all-against-all/rmod_random_impl.erl49
-rw-r--r--lib/ic/examples/all-against-all/server.c262
-rw-r--r--lib/ic/examples/all-against-all/server.erl41
-rw-r--r--lib/ic/examples/all-against-all/server.java83
-rw-r--r--lib/ic/examples/all-against-all/serverImpl.java43
-rw-r--r--lib/ic/examples/c-client/Makefile87
-rw-r--r--lib/ic/examples/c-client/ReadMe46
-rw-r--r--lib/ic/examples/c-client/client.c131
-rw-r--r--lib/ic/examples/c-client/random.idl52
-rw-r--r--lib/ic/examples/c-client/rmod_random_impl.erl53
-rw-r--r--lib/ic/examples/c-client/test.erl44
-rw-r--r--lib/ic/examples/c-server/Makefile90
-rw-r--r--lib/ic/examples/c-server/ReadMe45
-rw-r--r--lib/ic/examples/c-server/callbacks.c46
-rw-r--r--lib/ic/examples/c-server/client.c125
-rw-r--r--lib/ic/examples/c-server/client.erl45
-rw-r--r--lib/ic/examples/c-server/random.idl50
-rw-r--r--lib/ic/examples/c-server/server.c246
-rw-r--r--lib/ic/examples/erl-genserv/ReadMe30
-rw-r--r--lib/ic/examples/erl-genserv/random.idl51
-rw-r--r--lib/ic/examples/erl-genserv/rmod_random_impl.erl64
-rw-r--r--lib/ic/examples/erl-plain/ReadMe27
-rw-r--r--lib/ic/examples/erl-plain/random.idl53
-rw-r--r--lib/ic/examples/erl-plain/rmod_random_impl.erl33
-rw-r--r--lib/ic/examples/java-client-server/ReadMe69
-rw-r--r--lib/ic/examples/java-client-server/client.java61
-rw-r--r--lib/ic/examples/java-client-server/random.idl50
-rw-r--r--lib/ic/examples/java-client-server/server.java83
-rw-r--r--lib/ic/examples/java-client-server/serverImpl.java43
-rw-r--r--lib/ic/examples/pre_post_condition/Makefile135
-rw-r--r--lib/ic/examples/pre_post_condition/ReadMe.txt74
-rw-r--r--lib/ic/examples/pre_post_condition/ex.idl30
-rw-r--r--lib/ic/examples/pre_post_condition/m_i_impl.erl50
-rw-r--r--lib/ic/examples/pre_post_condition/tracer.erl57
-rw-r--r--lib/ic/include/erlang.idl58
-rw-r--r--lib/ic/include/ic.h432
-rw-r--r--lib/ic/info2
-rw-r--r--lib/ic/internal_doc/c-improvements-1.txt84
-rw-r--r--lib/ic/internal_doc/protocol.txt182
-rw-r--r--lib/ic/java_src/Makefile42
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/Any.java1026
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/AnyHelper.java79
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/AnyHolder.java61
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/BooleanHolder.java63
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/ByteHolder.java62
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/CharHolder.java64
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/DoubleHolder.java62
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/Environment.java480
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/FloatHolder.java63
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/Holder.java34
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/IntHolder.java63
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/LongHolder.java61
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/Makefile122
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/Pid.java56
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/PidHelper.java145
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/PidHolder.java55
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/Port.java49
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/PortHelper.java141
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/PortHolder.java57
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/Ref.java61
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/RefHelper.java142
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/RefHolder.java55
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/ShortHolder.java62
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/StringHolder.java63
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/TCKind.java200
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/Term.java1113
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/TermHelper.java142
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/TermHolder.java59
-rw-r--r--lib/ic/java_src/com/ericsson/otp/ic/TypeCode.java883
-rw-r--r--lib/ic/prebuild.skip1
-rw-r--r--lib/ic/priv/lib/.gitignore0
-rw-r--r--lib/ic/priv/obj/.gitignore0
-rw-r--r--lib/ic/src/Makefile219
-rw-r--r--lib/ic/src/ic.app.src53
-rw-r--r--lib/ic/src/ic.erl415
-rw-r--r--lib/ic/src/ic.hrl159
-rw-r--r--lib/ic/src/ic_array_java.erl296
-rw-r--r--lib/ic/src/ic_attribute_java.erl413
-rw-r--r--lib/ic/src/ic_cbe.erl1307
-rw-r--r--lib/ic/src/ic_cclient.erl1210
-rw-r--r--lib/ic/src/ic_code.erl585
-rw-r--r--lib/ic/src/ic_codegen.erl423
-rw-r--r--lib/ic/src/ic_constant_java.erl100
-rw-r--r--lib/ic/src/ic_cserver.erl2420
-rw-r--r--lib/ic/src/ic_debug.hrl38
-rw-r--r--lib/ic/src/ic_enum_java.erl313
-rw-r--r--lib/ic/src/ic_erl_template.erl640
-rw-r--r--lib/ic/src/ic_erlbe.erl1142
-rw-r--r--lib/ic/src/ic_error.erl376
-rw-r--r--lib/ic/src/ic_fetch.erl389
-rw-r--r--lib/ic/src/ic_file.erl448
-rw-r--r--lib/ic/src/ic_forms.erl442
-rw-r--r--lib/ic/src/ic_genobj.erl245
-rw-r--r--lib/ic/src/ic_java_type.erl1214
-rw-r--r--lib/ic/src/ic_jbe.erl1488
-rw-r--r--lib/ic/src/ic_noc.erl1117
-rw-r--r--lib/ic/src/ic_options.erl364
-rw-r--r--lib/ic/src/ic_plainbe.erl356
-rw-r--r--lib/ic/src/ic_pp.erl2245
-rw-r--r--lib/ic/src/ic_pragma.erl1957
-rw-r--r--lib/ic/src/ic_sequence_java.erl240
-rw-r--r--lib/ic/src/ic_struct_java.erl315
-rw-r--r--lib/ic/src/ic_symtab.erl235
-rw-r--r--lib/ic/src/ic_union_java.erl755
-rw-r--r--lib/ic/src/ic_util.erl314
-rw-r--r--lib/ic/src/icenum.erl206
-rw-r--r--lib/ic/src/iceval.erl556
-rw-r--r--lib/ic/src/icforms.hrl70
-rw-r--r--lib/ic/src/icparse.yrl872
-rw-r--r--lib/ic/src/icpreproc.erl112
-rw-r--r--lib/ic/src/icscan.erl453
-rw-r--r--lib/ic/src/icstruct.erl1917
-rw-r--r--lib/ic/src/ictk.erl874
-rw-r--r--lib/ic/src/ictype.erl1417
-rw-r--r--lib/ic/src/icunion.erl1491
-rw-r--r--lib/ic/src/icyeccpre.hrl125
-rw-r--r--lib/ic/test/Makefile276
-rw-r--r--lib/ic/test/c_client_erl_server_SUITE.erl265
-rw-r--r--lib/ic/test/c_client_erl_server_SUITE_data/Makefile.src155
-rw-r--r--lib/ic/test/c_client_erl_server_SUITE_data/c_client.c1760
-rw-r--r--lib/ic/test/c_client_erl_server_SUITE_data/c_erl_test.idl175
-rw-r--r--lib/ic/test/c_client_erl_server_SUITE_data/erl_server.erl29
-rw-r--r--lib/ic/test/c_client_erl_server_SUITE_data/m_i_impl.erl162
-rw-r--r--lib/ic/test/c_client_erl_server_proto_SUITE.erl265
-rw-r--r--lib/ic/test/c_client_erl_server_proto_SUITE_data/Makefile.src156
-rw-r--r--lib/ic/test/c_client_erl_server_proto_SUITE_data/c_client.c1764
-rw-r--r--lib/ic/test/c_client_erl_server_proto_SUITE_data/c_erl_test.idl174
-rw-r--r--lib/ic/test/c_client_erl_server_proto_SUITE_data/erl_server.erl29
-rw-r--r--lib/ic/test/c_client_erl_server_proto_SUITE_data/m_i_impl.erl162
-rw-r--r--lib/ic/test/c_client_erl_server_proto_SUITE_data/my.c51
-rw-r--r--lib/ic/test/c_client_erl_server_proto_tmo_SUITE.erl265
-rw-r--r--lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/Makefile.src155
-rw-r--r--lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_client.c1764
-rw-r--r--lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_erl_test.idl174
-rw-r--r--lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/erl_server.erl29
-rw-r--r--lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/m_i_impl.erl162
-rw-r--r--lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/my.c52
-rw-r--r--lib/ic/test/erl_client_c_server_SUITE.erl298
-rw-r--r--lib/ic/test/erl_client_c_server_SUITE_data/Makefile.src160
-rw-r--r--lib/ic/test/erl_client_c_server_SUITE_data/c_server.c300
-rw-r--r--lib/ic/test/erl_client_c_server_SUITE_data/callbacks.c611
-rw-r--r--lib/ic/test/erl_client_c_server_SUITE_data/erl_c_test.idl175
-rw-r--r--lib/ic/test/erl_client_c_server_SUITE_data/erl_client.erl332
-rw-r--r--lib/ic/test/erl_client_c_server_proto_SUITE.erl298
-rw-r--r--lib/ic/test/erl_client_c_server_proto_SUITE_data/Makefile.src160
-rw-r--r--lib/ic/test/erl_client_c_server_proto_SUITE_data/c_server.c300
-rw-r--r--lib/ic/test/erl_client_c_server_proto_SUITE_data/callbacks.c611
-rw-r--r--lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_c_test.idl175
-rw-r--r--lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_client.erl332
-rw-r--r--lib/ic/test/erl_client_c_server_proto_SUITE_data/my.c35
-rw-r--r--lib/ic/test/ic.cover2
-rw-r--r--lib/ic/test/ic.spec1
-rw-r--r--lib/ic/test/ic.spec.vxworks2
-rw-r--r--lib/ic/test/ic_SUITE.erl894
-rw-r--r--lib/ic/test/ic_SUITE_data/Corba.idl1013
-rw-r--r--lib/ic/test/ic_SUITE_data/Coss.idl1537
-rw-r--r--lib/ic/test/ic_SUITE_data/attr.idl30
-rw-r--r--lib/ic/test/ic_SUITE_data/c_err1.idl64
-rw-r--r--lib/ic/test/ic_SUITE_data/c_err2.idl31
-rw-r--r--lib/ic/test/ic_SUITE_data/c_err3.idl29
-rw-r--r--lib/ic/test/ic_SUITE_data/c_norm.idl164
-rw-r--r--lib/ic/test/ic_SUITE_data/enum.idl33
-rw-r--r--lib/ic/test/ic_SUITE_data/forward.idl35
-rw-r--r--lib/ic/test/ic_SUITE_data/include.idl31
-rw-r--r--lib/ic/test/ic_SUITE_data/include2.idl27
-rw-r--r--lib/ic/test/ic_SUITE_data/include3.idl26
-rw-r--r--lib/ic/test/ic_SUITE_data/inherit.idl69
-rw-r--r--lib/ic/test/ic_SUITE_data/inherit_err.idl72
-rw-r--r--lib/ic/test/ic_SUITE_data/inherit_warn.idl65
-rw-r--r--lib/ic/test/ic_SUITE_data/mult_ids.idl93
-rw-r--r--lib/ic/test/ic_SUITE_data/nasty.idl61
-rw-r--r--lib/ic/test/ic_SUITE_data/one.idl30
-rw-r--r--lib/ic/test/ic_SUITE_data/one_followed.idl55
-rw-r--r--lib/ic/test/ic_SUITE_data/one_out.idl29
-rw-r--r--lib/ic/test/ic_SUITE_data/one_raises.idl33
-rw-r--r--lib/ic/test/ic_SUITE_data/one_void.idl31
-rw-r--r--lib/ic/test/ic_SUITE_data/raises_reg.idl53
-rw-r--r--lib/ic/test/ic_SUITE_data/struct.idl54
-rw-r--r--lib/ic/test/ic_SUITE_data/syntax1.idl29
-rw-r--r--lib/ic/test/ic_SUITE_data/syntax2.idl28
-rw-r--r--lib/ic/test/ic_SUITE_data/syntax3.idl21
-rw-r--r--lib/ic/test/ic_SUITE_data/syntax4.idl24
-rw-r--r--lib/ic/test/ic_SUITE_data/syntax5.idl23
-rw-r--r--lib/ic/test/ic_SUITE_data/syntax6.idl21
-rw-r--r--lib/ic/test/ic_SUITE_data/type.idl191
-rw-r--r--lib/ic/test/ic_SUITE_data/typeid.idl29
-rw-r--r--lib/ic/test/ic_SUITE_data/u_case_mult.idl55
-rw-r--r--lib/ic/test/ic_SUITE_data/u_default.idl52
-rw-r--r--lib/ic/test/ic_SUITE_data/u_mult.idl62
-rw-r--r--lib/ic/test/ic_SUITE_data/u_norm.idl64
-rw-r--r--lib/ic/test/ic_SUITE_data/u_type.idl83
-rw-r--r--lib/ic/test/ic_SUITE_data/undef_id.idl64
-rw-r--r--lib/ic/test/ic_be_SUITE.erl75
-rw-r--r--lib/ic/test/ic_be_SUITE_data/plain.idl34
-rw-r--r--lib/ic/test/ic_pp_SUITE.erl569
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/arg.idl39
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/cascade.idl30
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/comment.idl73
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/concat.idl61
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/define.idl42
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/if.idl33
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/if_zero.idl32
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/improp_nest_constr.idl31
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/inc.idl69
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/included1.idl36
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/included2.idl42
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/includer.idl46
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/line.idl46
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/misc.idl45
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/nopara.idl36
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/predef.idl34
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/predef_time.idl25
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/self_ref.idl27
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/separate.idl38
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/swallow_sc.idl38
-rw-r--r--lib/ic/test/ic_pp_SUITE_data/unintended_grp.idl30
-rw-r--r--lib/ic/test/ic_pragma_SUITE.erl301
-rw-r--r--lib/ic/test/ic_pragma_SUITE_data/reg_m0.idl78
-rw-r--r--lib/ic/test/ic_pragma_SUITE_data/reg_m1.idl76
-rw-r--r--lib/ic/test/ic_pragma_SUITE_data/reg_m2.idl41
-rw-r--r--lib/ic/test/ic_pragma_SUITE_data/reg_m3.idl39
-rw-r--r--lib/ic/test/ic_pragma_SUITE_data/reg_m4.idl65
-rw-r--r--lib/ic/test/ic_pragma_SUITE_data/reg_m5.idl29
-rw-r--r--lib/ic/test/ic_pragma_SUITE_data/reg_m6.idl39
-rw-r--r--lib/ic/test/ic_pragma_SUITE_data/reg_m7.idl63
-rw-r--r--lib/ic/test/ic_pragma_SUITE_data/uggly.idl205
-rw-r--r--lib/ic/test/ic_register_SUITE.erl422
-rw-r--r--lib/ic/test/ic_register_SUITE_data/reg_m10.idl38
-rw-r--r--lib/ic/test/ic_register_SUITE_data/reg_m11.idl33
-rw-r--r--lib/ic/test/ic_register_SUITE_data/reg_m12.idl41
-rw-r--r--lib/ic/test/ic_register_SUITE_data/reg_m8.idl33
-rw-r--r--lib/ic/test/ic_register_SUITE_data/reg_m9.idl33
-rw-r--r--lib/ic/test/ic_smoke.spec1
-rw-r--r--lib/ic/test/java_client_erl_server_SUITE.erl319
-rw-r--r--lib/ic/test/java_client_erl_server_SUITE_data/JavaClient.java760
-rw-r--r--lib/ic/test/java_client_erl_server_SUITE_data/Makefile.src101
-rw-r--r--lib/ic/test/java_client_erl_server_SUITE_data/java_erl_test.idl69
-rw-r--r--lib/ic/test/java_client_erl_server_SUITE_data/m_i_impl.erl170
-rw-r--r--lib/ic/vsn.mk1
-rw-r--r--lib/inets/doc/src/Makefile29
-rw-r--r--lib/inets/doc/src/book.gifbin1081 -> 0 bytes
-rw-r--r--lib/inets/doc/src/fascicules.xml19
-rw-r--r--lib/inets/doc/src/ftp.xml948
-rw-r--r--lib/inets/doc/src/ftp_client.xml86
-rw-r--r--lib/inets/doc/src/http_client.xml17
-rw-r--r--lib/inets/doc/src/http_uri.xml37
-rw-r--r--lib/inets/doc/src/httpc.xml55
-rw-r--r--lib/inets/doc/src/httpd.xml15
-rw-r--r--lib/inets/doc/src/inets.gifbin9763 -> 0 bytes
-rw-r--r--lib/inets/doc/src/inets.xml9
-rw-r--r--lib/inets/doc/src/introduction.xml10
-rw-r--r--lib/inets/doc/src/min_head.gifbin2652 -> 0 bytes
-rw-r--r--lib/inets/doc/src/mod_esi.xml70
-rw-r--r--lib/inets/doc/src/mod_security.xml5
-rw-r--r--lib/inets/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/inets/doc/src/notes.gifbin2005 -> 0 bytes
-rw-r--r--lib/inets/doc/src/notes.xml407
-rw-r--r--lib/inets/doc/src/part.xml9
-rw-r--r--lib/inets/doc/src/part_notes.xml40
-rw-r--r--lib/inets/doc/src/part_notes_history.xml35
-rw-r--r--lib/inets/doc/src/ref_man.gifbin1530 -> 0 bytes
-rw-r--r--lib/inets/doc/src/ref_man.xml12
-rw-r--r--lib/inets/doc/src/summary.html.src1
-rw-r--r--lib/inets/doc/src/tftp.xml647
-rw-r--r--lib/inets/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/inets/doc/src/warning.gifbin1498 -> 0 bytes
-rw-r--r--lib/inets/src/ftp/Makefile104
-rw-r--r--lib/inets/src/ftp/ftp.erl2596
-rw-r--r--lib/inets/src/ftp/ftp_internal.hrl33
-rw-r--r--lib/inets/src/ftp/ftp_progress.erl136
-rw-r--r--lib/inets/src/ftp/ftp_response.erl203
-rw-r--r--lib/inets/src/ftp/ftp_sup.erl60
-rw-r--r--lib/inets/src/http_client/httpc.erl174
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl138
-rw-r--r--lib/inets/src/http_client/httpc_internal.hrl8
-rw-r--r--lib/inets/src/http_client/httpc_manager.erl48
-rw-r--r--lib/inets/src/http_client/httpc_request.erl84
-rw-r--r--lib/inets/src/http_client/httpc_response.erl266
-rw-r--r--lib/inets/src/http_lib/http_request.erl8
-rw-r--r--lib/inets/src/http_lib/http_uri.erl51
-rw-r--r--lib/inets/src/http_lib/http_util.erl32
-rw-r--r--lib/inets/src/http_server/httpd.erl40
-rw-r--r--lib/inets/src/http_server/httpd_esi.erl29
-rw-r--r--lib/inets/src/http_server/httpd_example.erl37
-rw-r--r--lib/inets/src/http_server/httpd_file.erl5
-rw-r--r--lib/inets/src/http_server/httpd_request.erl56
-rw-r--r--lib/inets/src/http_server/httpd_request_handler.erl173
-rw-r--r--lib/inets/src/http_server/httpd_response.erl38
-rw-r--r--lib/inets/src/http_server/httpd_script_env.erl16
-rw-r--r--lib/inets/src/http_server/mod_alias.erl24
-rw-r--r--lib/inets/src/http_server/mod_disk_log.erl29
-rw-r--r--lib/inets/src/http_server/mod_esi.erl141
-rw-r--r--lib/inets/src/http_server/mod_log.erl6
-rw-r--r--lib/inets/src/inets_app/Makefile6
-rw-r--r--lib/inets/src/inets_app/inets.app.src17
-rw-r--r--lib/inets/src/inets_app/inets.appup.src8
-rw-r--r--lib/inets/src/inets_app/inets.erl16
-rw-r--r--lib/inets/src/inets_app/inets_ftp_wrapper.erl48
-rw-r--r--lib/inets/src/inets_app/inets_internal.hrl4
-rw-r--r--lib/inets/src/inets_app/inets_sup.erl30
-rw-r--r--lib/inets/src/inets_app/inets_tftp_wrapper.erl48
-rw-r--r--lib/inets/src/subdirs.mk2
-rw-r--r--lib/inets/src/tftp/Makefile109
-rw-r--r--lib/inets/src/tftp/tftp.erl398
-rw-r--r--lib/inets/src/tftp/tftp.hrl69
-rw-r--r--lib/inets/src/tftp/tftp_binary.erl239
-rw-r--r--lib/inets/src/tftp/tftp_engine.erl1422
-rw-r--r--lib/inets/src/tftp/tftp_file.erl390
-rw-r--r--lib/inets/src/tftp/tftp_lib.erl474
-rw-r--r--lib/inets/src/tftp/tftp_logger.erl99
-rw-r--r--lib/inets/src/tftp/tftp_sup.erl111
-rw-r--r--lib/inets/test/Makefile68
-rw-r--r--lib/inets/test/ftp_SUITE.erl1180
-rw-r--r--lib/inets/test/ftp_SUITE_data/vsftpd.conf26
-rw-r--r--lib/inets/test/ftp_format_SUITE.erl328
l---------lib/inets/test/ftp_internal.hrl1
-rw-r--r--lib/inets/test/ftp_property_test_SUITE.erl53
-rw-r--r--lib/inets/test/http_format_SUITE.erl9
-rw-r--r--lib/inets/test/http_test_lib.erl199
-rw-r--r--lib/inets/test/httpc_SUITE.erl687
-rw-r--r--lib/inets/test/httpd_SUITE.erl454
-rw-r--r--lib/inets/test/httpd_basic_SUITE.erl5
-rw-r--r--lib/inets/test/httpd_bench_SUITE.erl846
-rw-r--r--lib/inets/test/httpd_bench_SUITE_data/1M_filebin0 -> 1000000 bytes
-rw-r--r--lib/inets/test/httpd_bench_SUITE_data/1k_filebin0 -> 1000 bytes
-rw-r--r--lib/inets/test/httpd_block.erl372
-rw-r--r--lib/inets/test/httpd_mod.erl9
-rw-r--r--lib/inets/test/httpd_test_lib.erl73
-rw-r--r--lib/inets/test/inets.spec4
-rw-r--r--lib/inets/test/inets_SUITE.erl81
-rw-r--r--lib/inets/test/inets_bench.spec1
-rw-r--r--lib/inets/test/inets_socketwrap_SUITE.erl36
-rw-r--r--lib/inets/test/inets_sup_SUITE.erl54
-rw-r--r--lib/inets/test/inets_test_lib.erl196
-rw-r--r--lib/inets/test/make_certs.erl530
-rw-r--r--lib/inets/test/old_httpd_SUITE.erl2347
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/Makefile.src14
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/cgi_echo.c97
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/Makefile210
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/auth/group3
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/auth/passwd4
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.bat9
-rwxr-xr-xlib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.sh6
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf79
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf63
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf269
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/conf/mime.types465
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf66
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/config.shtml70
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_open/dummy.html10
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/dummy.html10
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/top_secret/index.html9
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/echo.shtml35
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/exec.shtml30
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/flastmod.shtml29
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/fsize.shtml29
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/include.shtml33
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/index.html25
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/last_modified.html22
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/friedrich.html7
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/oech.html4
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/welcome.html1
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_open/dummy.html10
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/dummy.html10
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/top_secret/index.html9
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/open/dummy.html10
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/dummy.html10
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/top_secret/index.html9
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/README161
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/a.gifbin246 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.black.gifbin242 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.red.gifbin247 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/apache_pb.gifbin2326 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/back.gifbin216 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.gray.gifbin233 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.red.gifbin205 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/binary.gifbin246 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/binhex.gifbin246 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/blank.gifbin148 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/bomb.gifbin308 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/box1.gifbin251 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/box2.gifbin268 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/broken.gifbin247 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/burst.gifbin235 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button1.gifbin755 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button10.gifbin781 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button2.gifbin785 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button3.gifbin745 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button4.gifbin786 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button5.gifbin780 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button6.gifbin791 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button7.gifbin796 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button8.gifbin784 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button9.gifbin784 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonl.gifbin587 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonr.gifbin576 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/c.gifbin242 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.blue.gifbin251 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.gray.gifbin246 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/compressed.gifbin1038 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/continued.gifbin214 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/dir.gifbin225 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/down.gifbin163 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/dvi.gifbin238 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/f.gifbin236 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.gifbin225 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.open.gifbin242 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.sec.gifbin243 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/forward.gifbin219 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.gifbin221 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.red.gifbin220 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.sec.gifbin249 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.right.gifbin217 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.up.gifbin223 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/htdig.gifbin1822 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/icon.sheet.gifbin11977 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/image1.gifbin274 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/image2.gifbin309 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/image3.gifbin286 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/index.gifbin268 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/layout.gifbin276 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/left.gifbin172 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/link.gifbin249 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/movie.gifbin243 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/p.gifbin237 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/patch.gifbin251 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pdf.gifbin249 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie0.gifbin188 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie1.gifbin198 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie2.gifbin198 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie3.gifbin191 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie4.gifbin193 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie5.gifbin189 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie6.gifbin186 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie7.gifbin185 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie8.gifbin173 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/portal.gifbin254 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/poweredby.gifbin2748 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/ps.gifbin244 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/quill.gifbin267 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/right.gifbin172 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw1.gifbin258 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw2.gifbin263 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/script.gifbin242 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound1.gifbin248 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound2.gifbin221 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere1.gifbin285 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere2.gifbin264 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/star.gifbin89 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/star_blank.gifbin53 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/tar.gifbin243 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/tex.gifbin251 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/text.gifbin229 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/transfer.gifbin242 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/unknown.gifbin245 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/up.gifbin164 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/uu.gifbin236 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/uuencoded.gifbin236 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/world1.gifbin228 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/world2.gifbin261 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/logs/Dummy_File_Needed_By_WinZip1
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_client.pem31
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_server.pem31
-rw-r--r--lib/inets/test/tftp_SUITE.erl949
-rw-r--r--lib/inets/test/tftp_test_lib.erl308
-rw-r--r--lib/inets/test/tftp_test_lib.hrl44
-rw-r--r--lib/inets/test/uri_SUITE.erl27
-rw-r--r--lib/inets/vsn.mk4
-rw-r--r--lib/jinterface/doc/src/Makefile39
-rw-r--r--lib/jinterface/doc/src/fascicules.xml18
-rw-r--r--lib/jinterface/doc/src/index.html.src99
-rw-r--r--lib/jinterface/doc/src/notes.gifbin2005 -> 0 bytes
-rw-r--r--lib/jinterface/doc/src/notes.xml47
-rw-r--r--lib/jinterface/doc/src/part_notes.xml39
-rw-r--r--lib/jinterface/doc/src/part_notes_history.xml37
-rw-r--r--lib/jinterface/doc/src/ref_man.gifbin1530 -> 0 bytes
-rw-r--r--lib/jinterface/doc/src/summary.html.src1
-rw-r--r--lib/jinterface/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile5
-rw-r--r--lib/jinterface/java_src/pom.xml.src11
-rw-r--r--lib/jinterface/test/jinterface_SUITE.erl22
-rw-r--r--lib/jinterface/test/nc_SUITE.erl17
-rw-r--r--lib/jinterface/vsn.mk2
-rw-r--r--lib/kernel/doc/src/.gitignore1
-rw-r--r--lib/kernel/doc/src/Makefile57
-rw-r--r--lib/kernel/doc/src/application.xml12
-rw-r--r--lib/kernel/doc/src/book.xml5
-rw-r--r--lib/kernel/doc/src/code.xml20
-rw-r--r--lib/kernel/doc/src/config.xml15
-rw-r--r--lib/kernel/doc/src/disk_log.xml2
-rw-r--r--lib/kernel/doc/src/erl_epmd.xml104
-rw-r--r--lib/kernel/doc/src/error_logger.xml325
-rw-r--r--lib/kernel/doc/src/fascicules.xml15
-rw-r--r--lib/kernel/doc/src/file.xml277
-rw-r--r--lib/kernel/doc/src/gen_sctp.xml69
-rw-r--r--lib/kernel/doc/src/gen_tcp.xml35
-rw-r--r--lib/kernel/doc/src/gen_udp.xml35
-rw-r--r--lib/kernel/doc/src/heart.xml7
-rw-r--r--lib/kernel/doc/src/inet.xml234
-rw-r--r--lib/kernel/doc/src/inet_res.xml8
-rw-r--r--lib/kernel/doc/src/introduction_chapter.xml63
-rw-r--r--lib/kernel/doc/src/kernel_app.xml248
-rw-r--r--lib/kernel/doc/src/logger.xml1190
-rw-r--r--lib/kernel/doc/src/logger_arch.diabin0 -> 2527 bytes
-rw-r--r--lib/kernel/doc/src/logger_arch.pngbin0 -> 117205 bytes
-rw-r--r--lib/kernel/doc/src/logger_chapter.xml1333
-rw-r--r--lib/kernel/doc/src/logger_disk_log_h.xml158
-rw-r--r--lib/kernel/doc/src/logger_filters.xml254
-rw-r--r--lib/kernel/doc/src/logger_formatter.xml354
-rw-r--r--lib/kernel/doc/src/logger_std_h.xml139
-rw-r--r--lib/kernel/doc/src/net_kernel.xml17
-rw-r--r--lib/kernel/doc/src/notes.xml565
-rw-r--r--lib/kernel/doc/src/os.xml133
-rw-r--r--lib/kernel/doc/src/part.xml37
-rw-r--r--lib/kernel/doc/src/part_notes.xml40
-rw-r--r--lib/kernel/doc/src/part_notes_history.xml40
-rw-r--r--lib/kernel/doc/src/ref_man.xml12
-rw-r--r--lib/kernel/doc/src/rpc.xml11
-rw-r--r--lib/kernel/doc/src/seq_trace.xml11
-rw-r--r--lib/kernel/doc/src/specs.xml6
-rw-r--r--lib/kernel/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/kernel/examples/Makefile2
-rw-r--r--lib/kernel/examples/gen_tcp_dist/Makefile20
-rw-r--r--lib/kernel/examples/gen_tcp_dist/ebin/.gitignore (renamed from lib/cosEvent/example/.gitignore)0
-rw-r--r--lib/kernel/examples/gen_tcp_dist/src/gen_tcp_dist.erl781
-rw-r--r--lib/kernel/include/dist.hrl7
-rw-r--r--lib/kernel/include/dist_util.hrl14
-rw-r--r--lib/kernel/include/logger.hrl53
-rw-r--r--lib/kernel/src/Makefile52
-rw-r--r--lib/kernel/src/application_controller.erl81
-rw-r--r--lib/kernel/src/application_master.erl6
-rw-r--r--lib/kernel/src/auth.erl8
-rw-r--r--lib/kernel/src/code.erl11
-rw-r--r--lib/kernel/src/code_server.erl43
-rw-r--r--lib/kernel/src/disk_log.erl4
-rw-r--r--lib/kernel/src/disk_log_1.erl4
-rw-r--r--lib/kernel/src/dist_util.erl474
-rw-r--r--lib/kernel/src/erl_boot_server.erl41
-rw-r--r--lib/kernel/src/erl_epmd.erl74
-rw-r--r--lib/kernel/src/erl_reply.erl4
-rw-r--r--lib/kernel/src/erl_signal_handler.erl13
-rw-r--r--lib/kernel/src/error_handler.erl6
-rw-r--r--lib/kernel/src/error_logger.erl611
-rw-r--r--lib/kernel/src/erts_debug.erl169
-rw-r--r--lib/kernel/src/file.erl96
-rw-r--r--lib/kernel/src/file_int.hrl33
-rw-r--r--lib/kernel/src/file_io_server.erl73
-rw-r--r--lib/kernel/src/file_server.erl149
-rw-r--r--lib/kernel/src/gen_sctp.erl22
-rw-r--r--lib/kernel/src/gen_tcp.erl22
-rw-r--r--lib/kernel/src/gen_udp.erl23
-rw-r--r--lib/kernel/src/global.erl16
-rw-r--r--lib/kernel/src/group.erl301
-rw-r--r--lib/kernel/src/group_history.erl4
-rw-r--r--lib/kernel/src/hipe_unified_loader.erl8
-rw-r--r--lib/kernel/src/inet.erl57
-rw-r--r--lib/kernel/src/inet6_tcp.erl8
-rw-r--r--lib/kernel/src/inet_config.erl4
-rw-r--r--lib/kernel/src/inet_dns.erl6
-rw-r--r--lib/kernel/src/inet_hosts.erl5
-rw-r--r--lib/kernel/src/inet_int.hrl15
-rw-r--r--lib/kernel/src/inet_parse.erl4
-rw-r--r--lib/kernel/src/inet_res.erl40
-rw-r--r--lib/kernel/src/inet_tcp.erl8
-rw-r--r--lib/kernel/src/inet_tcp_dist.erl150
-rw-r--r--lib/kernel/src/kernel.app.src32
-rw-r--r--lib/kernel/src/kernel.appup.src10
-rw-r--r--lib/kernel/src/kernel.erl53
-rw-r--r--lib/kernel/src/kernel_config.erl9
-rw-r--r--lib/kernel/src/kernel_refc.erl139
-rw-r--r--lib/kernel/src/logger.erl917
-rw-r--r--lib/kernel/src/logger_backend.erl133
-rw-r--r--lib/kernel/src/logger_config.erl150
-rw-r--r--lib/kernel/src/logger_disk_log_h.erl723
-rw-r--r--lib/kernel/src/logger_filters.erl127
-rw-r--r--lib/kernel/src/logger_formatter.erl514
-rw-r--r--lib/kernel/src/logger_h_common.erl336
-rw-r--r--lib/kernel/src/logger_h_common.hrl263
-rw-r--r--lib/kernel/src/logger_handler_watcher.erl113
-rw-r--r--lib/kernel/src/logger_internal.hrl101
-rw-r--r--lib/kernel/src/logger_server.erl527
-rw-r--r--lib/kernel/src/logger_simple_h.erl212
-rw-r--r--lib/kernel/src/logger_std_h.erl828
-rw-r--r--lib/kernel/src/logger_sup.erl57
-rw-r--r--lib/kernel/src/net_kernel.erl357
-rw-r--r--lib/kernel/src/os.erl162
-rw-r--r--lib/kernel/src/pg2.erl4
-rw-r--r--lib/kernel/src/raw_file_io.erl75
-rw-r--r--lib/kernel/src/raw_file_io_compressed.erl134
-rw-r--r--lib/kernel/src/raw_file_io_deflate.erl159
-rw-r--r--lib/kernel/src/raw_file_io_delayed.erl320
-rw-r--r--lib/kernel/src/raw_file_io_inflate.erl261
-rw-r--r--lib/kernel/src/raw_file_io_list.erl128
-rw-r--r--lib/kernel/src/raw_file_io_raw.erl25
-rw-r--r--lib/kernel/src/rpc.erl15
-rw-r--r--lib/kernel/src/seq_trace.erl8
-rw-r--r--lib/kernel/src/user.erl6
-rw-r--r--lib/kernel/src/user_drv.erl33
-rw-r--r--lib/kernel/test/Makefile21
-rw-r--r--lib/kernel/test/application_SUITE.erl58
-rw-r--r--lib/kernel/test/code_SUITE.erl64
-rw-r--r--lib/kernel/test/code_SUITE_data/upgrade_client.erl1
-rw-r--r--lib/kernel/test/disk_log_SUITE.erl220
-rw-r--r--lib/kernel/test/erl_distribution_SUITE.erl38
-rw-r--r--lib/kernel/test/erl_distribution_wb_SUITE.erl16
-rw-r--r--lib/kernel/test/erl_prim_loader_SUITE.erl5
-rw-r--r--lib/kernel/test/error_logger_SUITE.erl64
-rw-r--r--lib/kernel/test/error_logger_warn_SUITE.erl16
-rw-r--r--lib/kernel/test/file_SUITE.erl275
-rw-r--r--lib/kernel/test/file_name_SUITE.erl28
-rw-r--r--lib/kernel/test/gen_sctp_SUITE.erl8
-rw-r--r--lib/kernel/test/gen_tcp_api_SUITE.erl6
-rw-r--r--lib/kernel/test/gen_tcp_misc_SUITE.erl340
-rw-r--r--lib/kernel/test/gen_udp_SUITE.erl302
-rw-r--r--lib/kernel/test/global_SUITE.erl47
-rw-r--r--lib/kernel/test/heart_SUITE.erl23
-rw-r--r--lib/kernel/test/inet_SUITE.erl33
-rw-r--r--lib/kernel/test/inet_res_SUITE.erl6
-rw-r--r--lib/kernel/test/init_SUITE.erl73
-rw-r--r--lib/kernel/test/kernel_SUITE.erl71
-rw-r--r--lib/kernel/test/kernel_bench.spec2
-rw-r--r--lib/kernel/test/kernel_config_SUITE.erl4
-rw-r--r--lib/kernel/test/logger.cover14
-rw-r--r--lib/kernel/test/logger.spec11
-rw-r--r--lib/kernel/test/logger_SUITE.erl1318
-rw-r--r--lib/kernel/test/logger_disk_log_h_SUITE.erl1572
-rw-r--r--lib/kernel/test/logger_env_var_SUITE.erl683
-rw-r--r--lib/kernel/test/logger_filters_SUITE.erl227
-rw-r--r--lib/kernel/test/logger_formatter_SUITE.erl886
-rw-r--r--lib/kernel/test/logger_legacy_SUITE.erl288
-rw-r--r--lib/kernel/test/logger_simple_h_SUITE.erl209
-rw-r--r--lib/kernel/test/logger_std_h_SUITE.erl1607
-rw-r--r--lib/kernel/test/logger_test_lib.erl82
-rw-r--r--lib/kernel/test/os_SUITE.erl40
-rw-r--r--lib/kernel/test/pdict_SUITE.erl34
-rw-r--r--lib/kernel/test/prim_file_SUITE.erl754
-rw-r--r--lib/kernel/test/sendfile_SUITE.erl138
-rw-r--r--lib/kernel/test/seq_trace_SUITE.erl129
-rw-r--r--lib/kernel/test/wrap_log_reader_SUITE.erl19
-rw-r--r--lib/kernel/test/wrap_log_reader_SUITE_data/wrap_log_test.erl26
-rw-r--r--lib/kernel/test/zlib_SUITE.erl876
-rw-r--r--lib/kernel/test/zzz_SUITE.erl37
-rw-r--r--lib/kernel/vsn.mk2
-rw-r--r--lib/megaco/doc/src/Makefile36
-rw-r--r--lib/megaco/doc/src/book.gifbin1081 -> 0 bytes
-rw-r--r--lib/megaco/doc/src/book.xml7
-rw-r--r--lib/megaco/doc/src/fascicules.xml18
-rw-r--r--lib/megaco/doc/src/files.mk11
-rw-r--r--lib/megaco/doc/src/index.html.src113
-rw-r--r--lib/megaco/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/megaco/doc/src/notes.gifbin2005 -> 0 bytes
-rw-r--r--lib/megaco/doc/src/notes.xml191
-rw-r--r--lib/megaco/doc/src/part_notes.xml40
-rw-r--r--lib/megaco/doc/src/part_notes_history.xml41
-rw-r--r--lib/megaco/doc/src/ref_man.gifbin1530 -> 0 bytes
-rw-r--r--lib/megaco/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/megaco/doc/src/warning.gifbin1498 -> 0 bytes
-rw-r--r--lib/megaco/vsn.mk2
-rw-r--r--lib/mnesia/doc/src/Makefile46
-rw-r--r--lib/mnesia/doc/src/Mnesia_chap2.xmlsrc4
-rw-r--r--lib/mnesia/doc/src/Mnesia_chap5.xmlsrc8
-rw-r--r--lib/mnesia/doc/src/book.gifbin1081 -> 0 bytes
-rw-r--r--lib/mnesia/doc/src/company.erl9
-rw-r--r--lib/mnesia/doc/src/company_o.erl8
-rw-r--r--lib/mnesia/doc/src/fascicules.xml18
-rw-r--r--lib/mnesia/doc/src/mnesia.gifbin15184 -> 0 bytes
-rw-r--r--lib/mnesia/doc/src/mnesia_frag_hash.xml4
-rw-r--r--lib/mnesia/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/mnesia/doc/src/notes.gifbin2005 -> 0 bytes
-rw-r--r--lib/mnesia/doc/src/notes.xml173
-rw-r--r--lib/mnesia/doc/src/part_notes.xml42
-rw-r--r--lib/mnesia/doc/src/part_notes_history.xml42
-rw-r--r--lib/mnesia/doc/src/ref_man.gifbin1530 -> 0 bytes
-rw-r--r--lib/mnesia/doc/src/summary.html.src1
-rw-r--r--lib/mnesia/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/mnesia/doc/src/warning.gifbin1498 -> 0 bytes
-rw-r--r--lib/mnesia/src/mnesia.app.src2
-rw-r--r--lib/mnesia/src/mnesia.erl39
-rw-r--r--lib/mnesia/src/mnesia.hrl6
-rw-r--r--lib/mnesia/src/mnesia_bup.erl14
-rw-r--r--lib/mnesia/src/mnesia_checkpoint.erl26
-rw-r--r--lib/mnesia/src/mnesia_controller.erl69
-rw-r--r--lib/mnesia/src/mnesia_dumper.erl23
-rw-r--r--lib/mnesia/src/mnesia_event.erl12
-rw-r--r--lib/mnesia/src/mnesia_frag.erl7
-rw-r--r--lib/mnesia/src/mnesia_index.erl6
-rw-r--r--lib/mnesia/src/mnesia_late_loader.erl6
-rw-r--r--lib/mnesia/src/mnesia_lib.erl40
-rw-r--r--lib/mnesia/src/mnesia_loader.erl51
-rw-r--r--lib/mnesia/src/mnesia_locker.erl13
-rw-r--r--lib/mnesia/src/mnesia_log.erl46
-rw-r--r--lib/mnesia/src/mnesia_monitor.erl28
-rw-r--r--lib/mnesia/src/mnesia_recover.erl16
-rw-r--r--lib/mnesia/src/mnesia_schema.erl67
-rw-r--r--lib/mnesia/src/mnesia_subscr.erl8
-rw-r--r--lib/mnesia/src/mnesia_text.erl16
-rw-r--r--lib/mnesia/src/mnesia_tm.erl56
-rw-r--r--lib/mnesia/test/mnesia_SUITE.erl17
-rw-r--r--lib/mnesia/test/mnesia_atomicity_test.erl32
-rw-r--r--lib/mnesia/test/mnesia_bench_SUITE.erl10
-rw-r--r--lib/mnesia/test/mnesia_consistency_test.erl75
-rw-r--r--lib/mnesia/test/mnesia_cost.erl65
-rw-r--r--lib/mnesia/test/mnesia_dirty_access_test.erl32
-rw-r--r--lib/mnesia/test/mnesia_durability_test.erl137
-rw-r--r--lib/mnesia/test/mnesia_evil_backup.erl17
-rw-r--r--lib/mnesia/test/mnesia_evil_coverage_test.erl130
-rw-r--r--lib/mnesia/test/mnesia_examples_test.erl11
-rw-r--r--lib/mnesia/test/mnesia_frag_test.erl23
-rw-r--r--lib/mnesia/test/mnesia_install_test.erl9
-rw-r--r--lib/mnesia/test/mnesia_isolation_test.erl54
-rw-r--r--lib/mnesia/test/mnesia_majority_test.erl10
-rw-r--r--lib/mnesia/test/mnesia_measure_test.erl47
-rw-r--r--lib/mnesia/test/mnesia_nice_coverage_test.erl10
-rw-r--r--lib/mnesia/test/mnesia_qlc_test.erl15
-rw-r--r--lib/mnesia/test/mnesia_recovery_test.erl78
-rw-r--r--lib/mnesia/test/mnesia_registry_test.erl9
-rw-r--r--lib/mnesia/test/mnesia_schema_recovery_test.erl76
-rw-r--r--lib/mnesia/test/mnesia_test_lib.erl8
-rw-r--r--lib/mnesia/test/mnesia_test_lib.hrl14
-rw-r--r--lib/mnesia/test/mnesia_trans_access_test.erl25
-rw-r--r--lib/mnesia/vsn.mk2
-rw-r--r--lib/observer/doc/src/Makefile26
-rw-r--r--lib/observer/doc/src/fascicules.xml18
-rw-r--r--lib/observer/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/observer/doc/src/notes.xml222
-rw-r--r--lib/observer/doc/src/part_notes.xml39
-rw-r--r--lib/observer/doc/src/part_notes_history.xml39
-rw-r--r--lib/observer/include/etop.hrl4
-rwxr-xr-xlib/observer/priv/bin/cdv2
-rw-r--r--lib/observer/priv/bin/cdv.bat2
-rw-r--r--lib/observer/src/cdv_atom_cb.erl4
-rw-r--r--lib/observer/src/cdv_bin_cb.erl5
-rw-r--r--lib/observer/src/cdv_detail_wx.erl41
-rw-r--r--lib/observer/src/cdv_dist_cb.erl4
-rw-r--r--lib/observer/src/cdv_html_wx.erl25
-rw-r--r--lib/observer/src/cdv_info_wx.erl14
-rw-r--r--lib/observer/src/cdv_mem_cb.erl6
-rw-r--r--lib/observer/src/cdv_multi_wx.erl10
-rw-r--r--lib/observer/src/cdv_port_cb.erl19
-rw-r--r--lib/observer/src/cdv_proc_cb.erl8
-rw-r--r--lib/observer/src/cdv_sched_cb.erl20
-rw-r--r--lib/observer/src/cdv_table_wx.erl10
-rw-r--r--lib/observer/src/cdv_term_cb.erl18
-rw-r--r--lib/observer/src/cdv_virtual_list_wx.erl18
-rw-r--r--lib/observer/src/cdv_wx.erl48
-rw-r--r--lib/observer/src/crashdump_viewer.erl1357
-rw-r--r--lib/observer/src/crashdump_viewer.hrl18
-rw-r--r--lib/observer/src/etop_tr.erl6
-rw-r--r--lib/observer/src/etop_txt.erl38
-rw-r--r--lib/observer/src/multitrace.erl16
-rw-r--r--lib/observer/src/observer.app.src7
-rw-r--r--lib/observer/src/observer_alloc_wx.erl8
-rw-r--r--lib/observer/src/observer_app_wx.erl2
-rw-r--r--lib/observer/src/observer_html_lib.erl74
-rw-r--r--lib/observer/src/observer_lib.erl182
-rw-r--r--lib/observer/src/observer_perf_wx.erl8
-rw-r--r--lib/observer/src/observer_port_wx.erl8
-rw-r--r--lib/observer/src/observer_pro_wx.erl50
-rw-r--r--lib/observer/src/observer_procinfo.erl23
-rw-r--r--lib/observer/src/observer_sys_wx.erl63
-rw-r--r--lib/observer/src/observer_trace_wx.erl49
-rw-r--r--lib/observer/src/observer_traceoptions_wx.erl23
-rw-r--r--lib/observer/src/observer_tv_table.erl55
-rw-r--r--lib/observer/src/observer_tv_wx.erl359
-rw-r--r--lib/observer/src/observer_wx.erl6
-rw-r--r--lib/observer/src/ttb.erl75
-rw-r--r--lib/observer/src/ttb_et.erl14
-rw-r--r--lib/observer/test/Makefile5
-rw-r--r--lib/observer/test/crashdump_helper.erl55
-rw-r--r--lib/observer/test/crashdump_helper_unicode.erl22
-rw-r--r--lib/observer/test/crashdump_viewer_SUITE.erl336
-rw-r--r--lib/observer/test/observer_SUITE.erl18
-rw-r--r--lib/observer/test/ttb_SUITE.erl34
-rw-r--r--lib/observer/vsn.mk2
-rw-r--r--lib/odbc/doc/src/Makefile31
-rw-r--r--lib/odbc/doc/src/book.gifbin1081 -> 0 bytes
-rw-r--r--lib/odbc/doc/src/fascicules.xml19
-rw-r--r--lib/odbc/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/odbc/doc/src/notes.gifbin2005 -> 0 bytes
-rw-r--r--lib/odbc/doc/src/notes.xml72
-rw-r--r--lib/odbc/doc/src/odbc.gifbin15184 -> 0 bytes
-rw-r--r--lib/odbc/doc/src/odbc_index.gifbin15184 -> 0 bytes
-rw-r--r--lib/odbc/doc/src/part_notes.xml41
-rw-r--r--lib/odbc/doc/src/part_notes_history.xml35
-rw-r--r--lib/odbc/doc/src/ref_man.gifbin1530 -> 0 bytes
-rw-r--r--lib/odbc/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/odbc/doc/src/warning.gifbin1498 -> 0 bytes
-rw-r--r--lib/odbc/vsn.mk2
-rw-r--r--lib/orber/AUTHORS8
-rw-r--r--lib/orber/COSS/CosNaming/CosNaming_BindingIterator_impl.erl94
-rw-r--r--lib/orber/COSS/CosNaming/CosNaming_NamingContextExt_impl.erl756
-rw-r--r--lib/orber/COSS/CosNaming/Makefile153
-rw-r--r--lib/orber/COSS/CosNaming/cos_naming.idl77
-rw-r--r--lib/orber/COSS/CosNaming/cos_naming_ext.idl37
-rw-r--r--lib/orber/COSS/CosNaming/lname.erl134
-rw-r--r--lib/orber/COSS/CosNaming/lname.hrl34
-rw-r--r--lib/orber/COSS/CosNaming/lname_component.erl84
-rw-r--r--lib/orber/COSS/CosNaming/orber_cosnaming.hrl64
-rw-r--r--lib/orber/COSS/CosNaming/orber_cosnaming_utils.erl762
-rw-r--r--lib/orber/Makefile42
-rw-r--r--lib/orber/c_src/InitialReference.cc206
-rw-r--r--lib/orber/c_src/InitialReference.hh60
-rw-r--r--lib/orber/c_src/Makefile24
-rw-r--r--lib/orber/c_src/Makefile.in100
-rw-r--r--lib/orber/c_src/main.cc32
-rw-r--r--lib/orber/doc/etc/.gitignore0
-rw-r--r--lib/orber/doc/html/.gitignore0
-rw-r--r--lib/orber/doc/javadoc/.gitignore0
-rw-r--r--lib/orber/doc/man1/.gitignore0
-rw-r--r--lib/orber/doc/man3/.gitignore0
-rw-r--r--lib/orber/doc/pdf/.gitignore0
-rw-r--r--lib/orber/doc/src/CosNaming.xml71
-rw-r--r--lib/orber/doc/src/CosNaming_BindingIterator.xml99
-rw-r--r--lib/orber/doc/src/CosNaming_NamingContext.xml250
-rw-r--r--lib/orber/doc/src/CosNaming_NamingContextExt.xml103
-rw-r--r--lib/orber/doc/src/Makefile177
-rw-r--r--lib/orber/doc/src/Module_Interface.xml356
-rw-r--r--lib/orber/doc/src/Orber/InitialReference.java131
-rw-r--r--lib/orber/doc/src/Orber/Makefile71
-rw-r--r--lib/orber/doc/src/any.xml117
-rw-r--r--lib/orber/doc/src/book.gifbin1081 -> 0 bytes
-rw-r--r--lib/orber/doc/src/book.xml49
-rw-r--r--lib/orber/doc/src/ch_contents.xml173
-rw-r--r--lib/orber/doc/src/ch_debugging.xml210
-rw-r--r--lib/orber/doc/src/ch_exceptions.xml238
-rw-r--r--lib/orber/doc/src/ch_idl_to_erlang_mapping.xml1504
-rw-r--r--lib/orber/doc/src/ch_ifr.xml50
-rw-r--r--lib/orber/doc/src/ch_install.xml1001
-rw-r--r--lib/orber/doc/src/ch_interceptors.xml279
-rw-r--r--lib/orber/doc/src/ch_introduction.xml145
-rw-r--r--lib/orber/doc/src/ch_naming_service.xml465
-rw-r--r--lib/orber/doc/src/ch_orber_kernel.xml103
-rw-r--r--lib/orber/doc/src/ch_orberweb.xml222
-rw-r--r--lib/orber/doc/src/ch_security.xml96
-rw-r--r--lib/orber/doc/src/ch_stubs.xml284
-rw-r--r--lib/orber/doc/src/corba.xml454
-rw-r--r--lib/orber/doc/src/corba_object.xml194
-rw-r--r--lib/orber/doc/src/dataframe1.gifbin21074 -> 0 bytes
-rw-r--r--lib/orber/doc/src/dataframe2.gifbin27848 -> 0 bytes
-rw-r--r--lib/orber/doc/src/dataframe3.gifbin30290 -> 0 bytes
-rw-r--r--lib/orber/doc/src/dataframe4.gifbin40114 -> 0 bytes
-rw-r--r--lib/orber/doc/src/dataframe5.gifbin11184 -> 0 bytes
-rw-r--r--lib/orber/doc/src/dataframe6.gifbin12331 -> 0 bytes
-rw-r--r--lib/orber/doc/src/dataframe7.gifbin12768 -> 0 bytes
-rw-r--r--lib/orber/doc/src/dataframe8.gifbin29939 -> 0 bytes
-rw-r--r--lib/orber/doc/src/dependent.gifbin1936 -> 0 bytes
-rw-r--r--lib/orber/doc/src/example_part.xml36
-rw-r--r--lib/orber/doc/src/fascicules.xml18
-rw-r--r--lib/orber/doc/src/firewall_nat.gifbin11939 -> 0 bytes
-rw-r--r--lib/orber/doc/src/fixed.xml161
-rw-r--r--lib/orber/doc/src/ifr_notes.txt53
-rw-r--r--lib/orber/doc/src/iiop.gifbin5899 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/GridBagEx.gifbin2453 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/OpenBookIcon.gifbin2241 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/blue-ball-small.gifbin255 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/blue-ball.gifbin925 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/class-index.gifbin1497 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/constructor-index.gifbin1711 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/constructors.gifbin1565 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/cyan-ball-small.gifbin255 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/cyan-ball.gifbin925 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/error-index.gifbin1438 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/exception-index.gifbin1707 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/green-ball-small.gifbin102 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/green-ball.gifbin886 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/interface-index.gifbin1648 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/magenta-ball-small.gifbin104 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/magenta-ball.gifbin896 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/method-index.gifbin1588 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/methods.gifbin1403 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/package-index.gifbin1607 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/red-ball-small.gifbin255 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/red-ball.gifbin527 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/variable-index.gifbin1576 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/variables.gifbin1380 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/yellow-ball-small.gifbin255 -> 0 bytes
-rw-r--r--lib/orber/doc/src/images/yellow-ball.gifbin925 -> 0 bytes
-rw-r--r--lib/orber/doc/src/interceptor_operations.gifbin14537 -> 0 bytes
-rw-r--r--lib/orber/doc/src/interceptors.xml284
-rw-r--r--lib/orber/doc/src/intro_part.xml41
-rw-r--r--lib/orber/doc/src/lname.xml166
-rw-r--r--lib/orber/doc/src/lname_component.xml113
-rw-r--r--lib/orber/doc/src/menuframe.gifbin12007 -> 0 bytes
-rw-r--r--lib/orber/doc/src/name.gifbin5015 -> 0 bytes
-rw-r--r--lib/orber/doc/src/notes.gifbin2005 -> 0 bytes
-rw-r--r--lib/orber/doc/src/notes.xml839
-rw-r--r--lib/orber/doc/src/orber.gifbin17015 -> 0 bytes
-rw-r--r--lib/orber/doc/src/orber.xml653
-rw-r--r--lib/orber/doc/src/orber_acl.xml107
-rw-r--r--lib/orber/doc/src/orber_diagnostics.xml81
-rw-r--r--lib/orber/doc/src/orber_ifr.xml1035
-rw-r--r--lib/orber/doc/src/orber_tc.xml259
-rw-r--r--lib/orber/doc/src/orbs.gifbin2817 -> 0 bytes
-rw-r--r--lib/orber/doc/src/part.xml49
-rw-r--r--lib/orber/doc/src/part_notes.xml37
-rw-r--r--lib/orber/doc/src/ref_man.gifbin1530 -> 0 bytes
-rw-r--r--lib/orber/doc/src/ref_man.xml53
-rw-r--r--lib/orber/doc/src/summary.html.src1
-rw-r--r--lib/orber/doc/src/theORB.gifbin4706 -> 0 bytes
-rw-r--r--lib/orber/doc/src/tools_debugging_part.xml40
-rw-r--r--lib/orber/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/orber/ebin/.gitignore0
-rw-r--r--lib/orber/examples/Makefile42
-rw-r--r--lib/orber/examples/Stack/InitialReferences.idl12
-rw-r--r--lib/orber/examples/Stack/Makefile128
-rw-r--r--lib/orber/examples/Stack/StackClient.cc97
-rw-r--r--lib/orber/examples/Stack/StackClient.java73
-rw-r--r--lib/orber/examples/Stack/StackModule_StackFactory_impl.erl41
-rw-r--r--lib/orber/examples/Stack/StackModule_Stack_impl.erl47
-rw-r--r--lib/orber/examples/Stack/stack.idl27
-rw-r--r--lib/orber/examples/Stack/stack_client.erl56
-rw-r--r--lib/orber/examples/Stack/stack_factory.erl38
-rw-r--r--lib/orber/include/corba.hrl149
-rw-r--r--lib/orber/include/ifr_types.hrl73
-rw-r--r--lib/orber/include/orber_pi.hrl77
-rw-r--r--lib/orber/info2
-rw-r--r--lib/orber/java_src/Makefile42
-rw-r--r--lib/orber/java_src/Orber/InitialReference.java131
-rw-r--r--lib/orber/java_src/Orber/Makefile71
-rw-r--r--lib/orber/prebuild.skip5
-rw-r--r--lib/orber/priv/Makefile67
-rw-r--r--lib/orber/priv/Orber/.gitignore0
-rw-r--r--lib/orber/priv/bin/.gitignore0
-rw-r--r--lib/orber/priv/blank.html6
-rw-r--r--lib/orber/priv/info_frames.html9
-rw-r--r--lib/orber/priv/main_frame.html9
-rw-r--r--lib/orber/priv/obj/.gitignore0
-rw-r--r--lib/orber/priv/orber.tool2
-rw-r--r--lib/orber/priv/orber_help.txt42
-rw-r--r--lib/orber/priv/start_info.html31
-rw-r--r--lib/orber/src/CORBA.idl22
-rw-r--r--lib/orber/src/Makefile263
-rw-r--r--lib/orber/src/OrberApp_IFR_impl.erl102
-rw-r--r--lib/orber/src/OrberCSIv2.asn145
-rw-r--r--lib/orber/src/OrberCSIv2.set.asn5
-rw-r--r--lib/orber/src/OrberIFR.idl12
-rw-r--r--lib/orber/src/PKIX1Algorithms88.asn1274
-rw-r--r--lib/orber/src/PKIX1Explicit88.asn1619
-rw-r--r--lib/orber/src/PKIX1Implicit88.asn1349
-rw-r--r--lib/orber/src/PKIXAttributeCertificate.asn1189
-rw-r--r--lib/orber/src/any.erl74
-rw-r--r--lib/orber/src/cdr_decode.erl1536
-rw-r--r--lib/orber/src/cdr_encode.erl1172
-rw-r--r--lib/orber/src/cdrlib.erl415
-rw-r--r--lib/orber/src/corba.erl2206
-rw-r--r--lib/orber/src/corba_boa.erl135
-rw-r--r--lib/orber/src/corba_nvlist.erl98
-rw-r--r--lib/orber/src/corba_object.erl221
-rw-r--r--lib/orber/src/fixed.erl306
-rw-r--r--lib/orber/src/ifr_objects.hrl422
-rw-r--r--lib/orber/src/iop_ior.erl1717
-rw-r--r--lib/orber/src/orber.app.src111
-rw-r--r--lib/orber/src/orber.appup.src7
-rw-r--r--lib/orber/src/orber.erl1238
-rw-r--r--lib/orber/src/orber_acl.erl397
-rw-r--r--lib/orber/src/orber_diagnostics.erl241
-rw-r--r--lib/orber/src/orber_env.erl1545
-rw-r--r--lib/orber/src/orber_exceptions.erl718
-rw-r--r--lib/orber/src/orber_ifr.erl1820
-rw-r--r--lib/orber/src/orber_ifr.hrl35
-rw-r--r--lib/orber/src/orber_ifr_aliasdef.erl135
-rw-r--r--lib/orber/src/orber_ifr_arraydef.erl104
-rw-r--r--lib/orber/src/orber_ifr_attributedef.erl138
-rw-r--r--lib/orber/src/orber_ifr_constantdef.erl148
-rw-r--r--lib/orber/src/orber_ifr_contained.erl248
-rw-r--r--lib/orber/src/orber_ifr_container.erl464
-rw-r--r--lib/orber/src/orber_ifr_enumdef.erl130
-rw-r--r--lib/orber/src/orber_ifr_exceptiondef.erl145
-rw-r--r--lib/orber/src/orber_ifr_fixeddef.erl80
-rw-r--r--lib/orber/src/orber_ifr_idltype.erl75
-rw-r--r--lib/orber/src/orber_ifr_interfacedef.erl340
-rw-r--r--lib/orber/src/orber_ifr_irobject.erl73
-rw-r--r--lib/orber/src/orber_ifr_moduledef.erl184
-rw-r--r--lib/orber/src/orber_ifr_operationdef.erl192
-rw-r--r--lib/orber/src/orber_ifr_orb.erl100
-rw-r--r--lib/orber/src/orber_ifr_primitivedef.erl70
-rw-r--r--lib/orber/src/orber_ifr_repository.erl288
-rw-r--r--lib/orber/src/orber_ifr_sequencedef.erl104
-rw-r--r--lib/orber/src/orber_ifr_stringdef.erl75
-rw-r--r--lib/orber/src/orber_ifr_structdef.erl156
-rw-r--r--lib/orber/src/orber_ifr_typecode.erl108
-rw-r--r--lib/orber/src/orber_ifr_typedef.erl125
-rw-r--r--lib/orber/src/orber_ifr_uniondef.erl176
-rw-r--r--lib/orber/src/orber_ifr_utils.erl437
-rw-r--r--lib/orber/src/orber_ifr_wstringdef.erl73
-rw-r--r--lib/orber/src/orber_iiop.erl551
-rw-r--r--lib/orber/src/orber_iiop.hrl1016
-rw-r--r--lib/orber/src/orber_iiop_inproxy.erl399
-rw-r--r--lib/orber/src/orber_iiop_inrequest.erl541
-rw-r--r--lib/orber/src/orber_iiop_insup.erl86
-rw-r--r--lib/orber/src/orber_iiop_net.erl511
-rw-r--r--lib/orber/src/orber_iiop_net_accept.erl95
-rw-r--r--lib/orber/src/orber_iiop_outproxy.erl511
-rw-r--r--lib/orber/src/orber_iiop_outsup.erl88
-rw-r--r--lib/orber/src/orber_iiop_pm.erl894
-rw-r--r--lib/orber/src/orber_iiop_socketsup.erl86
-rw-r--r--lib/orber/src/orber_iiop_tracer.erl232
-rw-r--r--lib/orber/src/orber_iiop_tracer_silent.erl191
-rw-r--r--lib/orber/src/orber_iiop_tracer_stealth.erl187
-rw-r--r--lib/orber/src/orber_initial_references.erl328
-rw-r--r--lib/orber/src/orber_interceptors.erl154
-rw-r--r--lib/orber/src/orber_objectkeys.erl571
-rw-r--r--lib/orber/src/orber_pi.erl1213
-rw-r--r--lib/orber/src/orber_request_number.erl83
-rw-r--r--lib/orber/src/orber_socket.erl530
-rw-r--r--lib/orber/src/orber_tb.erl222
-rw-r--r--lib/orber/src/orber_tc.erl284
-rw-r--r--lib/orber/src/orber_typedefs.erl83
-rw-r--r--lib/orber/src/orber_web.erl864
-rw-r--r--lib/orber/src/orber_web_server.erl190
-rw-r--r--lib/orber/test/Makefile220
-rw-r--r--lib/orber/test/cdrcoding_10_SUITE.erl587
-rw-r--r--lib/orber/test/cdrcoding_11_SUITE.erl587
-rw-r--r--lib/orber/test/cdrcoding_12_SUITE.erl575
-rw-r--r--lib/orber/test/cdrlib_SUITE.erl479
-rw-r--r--lib/orber/test/corba_SUITE.erl897
-rw-r--r--lib/orber/test/csiv2_SUITE.erl889
-rw-r--r--lib/orber/test/data_types_SUITE.erl187
-rw-r--r--lib/orber/test/generated_SUITE.erl372
-rw-r--r--lib/orber/test/idl_output/.gitignore0
-rw-r--r--lib/orber/test/iiop_module_do_test_impl.erl113
-rw-r--r--lib/orber/test/iiop_module_test_impl.erl129
-rw-r--r--lib/orber/test/iiop_test.idl112
-rw-r--r--lib/orber/test/iiop_test_impl.erl35
-rw-r--r--lib/orber/test/interceptors_SUITE.erl349
-rw-r--r--lib/orber/test/iop_ior_10_SUITE.erl184
-rw-r--r--lib/orber/test/iop_ior_11_SUITE.erl203
-rw-r--r--lib/orber/test/iop_ior_12_SUITE.erl204
-rw-r--r--lib/orber/test/ip_v4v6_interop_SUITE.erl199
-rw-r--r--lib/orber/test/lname_SUITE.erl213
-rw-r--r--lib/orber/test/multi_ORB_SUITE.erl2286
-rw-r--r--lib/orber/test/naming_context_SUITE.erl390
-rw-r--r--lib/orber/test/orber.cover2
-rw-r--r--lib/orber/test/orber.spec1
-rw-r--r--lib/orber/test/orber_SUITE.erl213
-rw-r--r--lib/orber/test/orber_acl_SUITE.erl299
-rw-r--r--lib/orber/test/orber_firewall_ipv4_in_SUITE.erl284
-rw-r--r--lib/orber/test/orber_firewall_ipv4_out_SUITE.erl229
-rw-r--r--lib/orber/test/orber_firewall_ipv6_in_SUITE.erl315
-rw-r--r--lib/orber/test/orber_firewall_ipv6_out_SUITE.erl236
-rw-r--r--lib/orber/test/orber_nat_SUITE.erl364
-rw-r--r--lib/orber/test/orber_test.idl96
-rw-r--r--lib/orber/test/orber_test_lib.erl1564
-rw-r--r--lib/orber/test/orber_test_server.cfg28
-rw-r--r--lib/orber/test/orber_test_server.idl177
-rw-r--r--lib/orber/test/orber_test_server_impl.erl276
-rw-r--r--lib/orber/test/orber_test_timeout_server_impl.erl66
-rw-r--r--lib/orber/test/orber_web_SUITE.erl440
-rw-r--r--lib/orber/test/tc_SUITE.erl605
-rw-r--r--lib/orber/vsn.mk1
-rw-r--r--lib/os_mon/doc/src/Makefile28
-rw-r--r--lib/os_mon/doc/src/fascicules.xml15
-rw-r--r--lib/os_mon/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/os_mon/doc/src/notes.xml65
-rw-r--r--lib/os_mon/doc/src/os_mon_mib.xml7
-rw-r--r--lib/os_mon/doc/src/part_notes.xml37
-rw-r--r--lib/os_mon/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/os_mon/doc/src/warning.gifbin1498 -> 0 bytes
-rw-r--r--lib/os_mon/src/cpu_sup.erl4
-rw-r--r--lib/os_mon/src/disksup.erl102
-rw-r--r--lib/os_mon/src/memsup.erl4
-rw-r--r--lib/os_mon/test/cpu_sup_SUITE.erl11
-rw-r--r--lib/os_mon/test/disksup_SUITE.erl40
-rw-r--r--lib/os_mon/vsn.mk2
-rw-r--r--lib/otp_mibs/doc/src/Makefile16
-rw-r--r--lib/otp_mibs/doc/src/fascicules.xml19
-rw-r--r--lib/otp_mibs/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/otp_mibs/doc/src/notes.xml48
-rw-r--r--lib/otp_mibs/doc/src/otp_mib.xml7
-rw-r--r--lib/otp_mibs/doc/src/part_notes.xml38
-rw-r--r--lib/otp_mibs/src/otp_mib.erl5
-rw-r--r--lib/otp_mibs/vsn.mk2
-rw-r--r--lib/parsetools/doc/src/Makefile25
-rw-r--r--lib/parsetools/doc/src/fascicules.xml15
-rw-r--r--lib/parsetools/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/parsetools/doc/src/notes.xml47
-rw-r--r--lib/parsetools/doc/src/part_notes.xml44
-rw-r--r--lib/parsetools/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/parsetools/doc/src/warning.gifbin1498 -> 0 bytes
-rw-r--r--lib/parsetools/include/leexinc.hrl4
-rw-r--r--lib/parsetools/include/yeccpre.hrl5
-rw-r--r--lib/parsetools/src/leex.erl34
-rw-r--r--lib/parsetools/src/yecc.erl22
-rw-r--r--lib/parsetools/src/yeccparser.erl16
-rw-r--r--lib/parsetools/test/yecc_SUITE.erl5
-rw-r--r--lib/parsetools/vsn.mk2
-rw-r--r--lib/public_key/asn1/PKCS-7.asn110
-rw-r--r--lib/public_key/doc/specs/.gitignore1
-rw-r--r--lib/public_key/doc/src/Makefile16
-rw-r--r--lib/public_key/doc/src/fascicules.xml19
-rw-r--r--lib/public_key/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/public_key/doc/src/notes.xml233
-rw-r--r--lib/public_key/doc/src/part_notes.xml39
-rw-r--r--lib/public_key/doc/src/public_key.xml927
-rw-r--r--lib/public_key/doc/src/public_key_records.xml14
-rw-r--r--lib/public_key/doc/src/specs.xml4
-rw-r--r--lib/public_key/doc/src/using_public_key.xml6
-rw-r--r--lib/public_key/include/public_key.hrl5
-rw-r--r--lib/public_key/priv/moduli429
-rw-r--r--lib/public_key/src/pubkey_cert.erl411
-rw-r--r--lib/public_key/src/pubkey_crl.erl37
-rw-r--r--lib/public_key/src/pubkey_moduli.hrl502
-rw-r--r--lib/public_key/src/pubkey_pbe.erl5
-rw-r--r--lib/public_key/src/pubkey_pem.erl4
-rw-r--r--lib/public_key/src/pubkey_ssh.erl160
-rw-r--r--lib/public_key/src/public_key.app.src2
-rw-r--r--lib/public_key/src/public_key.erl710
-rw-r--r--lib/public_key/test/erl_make_certs.erl8
-rw-r--r--lib/public_key/test/pbe_SUITE.erl12
-rw-r--r--lib/public_key/test/public_key_SUITE.erl315
-rw-r--r--lib/public_key/test/public_key_SUITE_data/dsa_key_pkcs8.pem9
-rw-r--r--lib/public_key/test/public_key_SUITE_data/ec_key2.pem29
-rw-r--r--lib/public_key/test/public_key_SUITE_data/ec_key_param0.pem28
-rw-r--r--lib/public_key/test/public_key_SUITE_data/ec_key_param1.pem25
-rw-r--r--lib/public_key/test/public_key_SUITE_data/ec_key_pkcs8.pem5
-rw-r--r--lib/public_key/test/public_key_SUITE_data/pkix_verify_hostname_subjAltName.pem24
-rw-r--r--lib/public_key/test/public_key_SUITE_data/pkix_verify_hostname_subjAltName_IP.pem13
-rw-r--r--lib/public_key/test/public_key_SUITE_data/rsa_key_pkcs8.pem10
-rw-r--r--lib/public_key/test/public_key_SUITE_data/verify_hostname.conf3
-rw-r--r--lib/public_key/test/public_key_SUITE_data/verify_hostname_ip.conf17
-rw-r--r--lib/public_key/vsn.mk2
-rw-r--r--lib/reltool/doc/src/Makefile3
-rw-r--r--lib/reltool/doc/src/notes.xml53
-rw-r--r--lib/reltool/doc/src/reltool.xml4
-rw-r--r--lib/reltool/doc/src/reltool_examples.xml58
-rw-r--r--lib/reltool/src/reltool.app.src4
-rw-r--r--lib/reltool/src/reltool.erl6
-rw-r--r--lib/reltool/src/reltool.hrl6
-rw-r--r--lib/reltool/src/reltool_app_win.erl14
-rw-r--r--lib/reltool/src/reltool_fgraph_win.erl4
-rw-r--r--lib/reltool/src/reltool_mod_win.erl14
-rw-r--r--lib/reltool/src/reltool_server.erl45
-rw-r--r--lib/reltool/src/reltool_sys_win.erl28
-rw-r--r--lib/reltool/src/reltool_target.erl51
-rw-r--r--lib/reltool/src/reltool_utils.erl21
-rw-r--r--lib/reltool/test/reltool_app_SUITE.erl4
-rw-r--r--lib/reltool/test/reltool_manual_gui_SUITE.erl4
-rw-r--r--lib/reltool/test/reltool_server_SUITE.erl31
-rw-r--r--lib/reltool/test/reltool_test_lib.erl4
-rw-r--r--lib/reltool/test/reltool_wx_SUITE.erl4
-rw-r--r--lib/reltool/test/rtt.erl4
-rw-r--r--lib/reltool/vsn.mk2
-rw-r--r--lib/runtime_tools/doc/src/LTTng.xml38
-rw-r--r--lib/runtime_tools/doc/src/Makefile39
-rw-r--r--lib/runtime_tools/doc/src/dbg.xml4
-rw-r--r--lib/runtime_tools/doc/src/fascicules.xml15
-rw-r--r--lib/runtime_tools/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/runtime_tools/doc/src/notes.xml113
-rw-r--r--lib/runtime_tools/doc/src/part_notes.xml39
-rw-r--r--lib/runtime_tools/doc/src/part_notes_history.xml39
-rw-r--r--lib/runtime_tools/doc/src/ref_man.xml3
-rw-r--r--lib/runtime_tools/doc/src/scheduler.xml135
-rw-r--r--lib/runtime_tools/doc/src/specs.xml1
-rw-r--r--lib/runtime_tools/doc/src/warning.gifbin1498 -> 0 bytes
-rw-r--r--lib/runtime_tools/examples/efile_drv.d105
-rw-r--r--lib/runtime_tools/examples/efile_drv.systemtap113
-rw-r--r--lib/runtime_tools/src/Makefile3
-rw-r--r--lib/runtime_tools/src/appmon_info.erl4
-rw-r--r--lib/runtime_tools/src/dbg.erl2
-rw-r--r--lib/runtime_tools/src/erts_alloc_config.erl38
-rw-r--r--lib/runtime_tools/src/msacc.erl5
-rw-r--r--lib/runtime_tools/src/observer_backend.erl57
-rw-r--r--lib/runtime_tools/src/runtime_tools.app.src3
-rw-r--r--lib/runtime_tools/src/scheduler.erl152
-rw-r--r--lib/runtime_tools/src/system_information.erl236
-rw-r--r--lib/runtime_tools/test/Makefile4
-rw-r--r--lib/runtime_tools/test/dbg_SUITE.erl102
-rw-r--r--lib/runtime_tools/test/dyntrace_SUITE.erl8
-rw-r--r--lib/runtime_tools/test/scheduler_SUITE.erl104
-rw-r--r--lib/runtime_tools/test/zzz_SUITE.erl37
-rw-r--r--lib/runtime_tools/vsn.mk2
-rw-r--r--lib/sasl/doc/src/Makefile27
-rw-r--r--lib/sasl/doc/src/appup.xml16
-rw-r--r--lib/sasl/doc/src/error_logging.xml55
-rw-r--r--lib/sasl/doc/src/fascicules.xml18
-rw-r--r--lib/sasl/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/sasl/doc/src/notes.xml174
-rw-r--r--lib/sasl/doc/src/part_notes.xml39
-rw-r--r--lib/sasl/doc/src/part_notes_history.xml39
-rw-r--r--lib/sasl/doc/src/release_handler.xml4
-rw-r--r--lib/sasl/doc/src/sasl_app.xml193
-rw-r--r--lib/sasl/doc/src/systools.xml6
-rw-r--r--lib/sasl/doc/src/warning.gifbin1498 -> 0 bytes
-rw-r--r--lib/sasl/src/Makefile4
-rw-r--r--lib/sasl/src/erlsrv.erl25
-rw-r--r--lib/sasl/src/format_lib_supp.erl12
-rw-r--r--lib/sasl/src/rb.erl6
-rw-r--r--lib/sasl/src/rb_format_supp.erl2
-rw-r--r--lib/sasl/src/release_handler.erl44
-rw-r--r--lib/sasl/src/sasl.app.src11
-rw-r--r--lib/sasl/src/sasl.appup.src10
-rw-r--r--lib/sasl/src/sasl.erl100
-rw-r--r--lib/sasl/src/sasl_report.erl81
-rw-r--r--lib/sasl/src/sasl_report_file_h.erl18
-rw-r--r--lib/sasl/src/si.erl169
-rw-r--r--lib/sasl/src/si_sasl_supp.erl380
-rw-r--r--lib/sasl/src/systools_make.erl233
-rw-r--r--lib/sasl/src/systools_relup.erl4
-rw-r--r--lib/sasl/test/rb_SUITE.erl20
-rw-r--r--lib/sasl/test/release_handler_SUITE.erl195
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/Makefile.src18
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/ebin/u.app8
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/src/u.erl50
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/src/u_sup.erl38
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/ebin/u.app8
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/ebin/u.appup3
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/src/u.erl55
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/src/u_sup.erl38
-rw-r--r--lib/sasl/test/sasl_SUITE.erl16
-rw-r--r--lib/sasl/test/sasl_report_SUITE.erl130
-rw-r--r--lib/sasl/test/systools_SUITE.erl69
-rw-r--r--lib/sasl/test/test_lib.hrl4
-rw-r--r--lib/sasl/vsn.mk2
-rw-r--r--lib/snmp/doc/src/Makefile39
-rw-r--r--lib/snmp/doc/src/book.gifbin1081 -> 0 bytes
-rw-r--r--lib/snmp/doc/src/fascicules.xml18
-rw-r--r--lib/snmp/doc/src/files.mk21
-rw-r--r--lib/snmp/doc/src/index.html.src99
-rw-r--r--lib/snmp/doc/src/min_head.gifbin2652 -> 0 bytes
-rw-r--r--lib/snmp/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/snmp/doc/src/notes.gifbin2005 -> 0 bytes
-rw-r--r--lib/snmp/doc/src/notes.xml535
-rw-r--r--lib/snmp/doc/src/part_notes.xml41
-rw-r--r--lib/snmp/doc/src/part_notes_history.xml42
-rw-r--r--lib/snmp/doc/src/ref_man.gifbin1530 -> 0 bytes
-rw-r--r--lib/snmp/doc/src/snmp.gifbin15889 -> 0 bytes
-rw-r--r--lib/snmp/doc/src/snmp.xml33
-rw-r--r--lib/snmp/doc/src/snmp_impl_example_agent.xml12
-rw-r--r--lib/snmp/doc/src/snmpa.xml38
-rw-r--r--lib/snmp/doc/src/snmpm.xml38
-rw-r--r--lib/snmp/doc/src/summary.html.src1
-rw-r--r--lib/snmp/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/snmp/doc/src/warning.gifbin1498 -> 0 bytes
-rw-r--r--lib/snmp/src/agent/snmpa_net_if.erl111
-rw-r--r--lib/snmp/src/app/snmp.appup.src8
-rw-r--r--lib/snmp/src/compile/snmpc.erl109
-rw-r--r--lib/snmp/src/compile/snmpc_lib.erl39
-rw-r--r--lib/snmp/src/manager/snmpm_net_if.erl4
-rw-r--r--lib/snmp/src/misc/snmp_log.erl334
-rw-r--r--lib/snmp/test/snmp_agent_test.erl30
-rw-r--r--lib/snmp/test/snmp_compiler_test.erl62
-rw-r--r--lib/snmp/test/snmp_manager_test.erl29
-rw-r--r--lib/snmp/test/snmp_test_data/OTP14196-MIB.mib47
-rw-r--r--lib/snmp/test/snmp_test_data/Test-LLDP-MIB.mib251
-rw-r--r--lib/snmp/test/snmp_to_snmpnet_SUITE.erl27
-rw-r--r--lib/snmp/vsn.mk4
-rw-r--r--lib/ssh/doc/specs/.gitignore1
-rw-r--r--lib/ssh/doc/src/Makefile43
-rw-r--r--lib/ssh/doc/src/configure_algos.xml429
-rw-r--r--lib/ssh/doc/src/fascicules.xml18
-rw-r--r--lib/ssh/doc/src/introduction.xml4
-rw-r--r--lib/ssh/doc/src/notes.xml717
-rw-r--r--lib/ssh/doc/src/part_notes.xml38
-rw-r--r--lib/ssh/doc/src/ref_man.xml5
-rw-r--r--lib/ssh/doc/src/specs.xml13
-rw-r--r--lib/ssh/doc/src/ssh.xml1627
-rw-r--r--lib/ssh/doc/src/ssh_app.xml74
-rw-r--r--lib/ssh/doc/src/ssh_channel.xml443
-rw-r--r--lib/ssh/doc/src/ssh_client_channel.xml440
-rw-r--r--lib/ssh/doc/src/ssh_client_key_api.xml70
-rw-r--r--lib/ssh/doc/src/ssh_connection.xml118
-rw-r--r--lib/ssh/doc/src/ssh_protocol.xml8
-rw-r--r--lib/ssh/doc/src/ssh_server_channel.xml176
-rw-r--r--lib/ssh/doc/src/ssh_server_key_api.xml63
-rw-r--r--lib/ssh/doc/src/ssh_sftp.xml21
-rw-r--r--lib/ssh/doc/src/ssh_sftpd.xml5
-rw-r--r--lib/ssh/doc/src/usersguide.xml3
-rw-r--r--lib/ssh/doc/src/using_ssh.xml7
-rw-r--r--lib/ssh/src/Makefile48
-rw-r--r--lib/ssh/src/ssh.app.src8
-rw-r--r--lib/ssh/src/ssh.erl224
-rw-r--r--lib/ssh/src/ssh.hrl329
-rw-r--r--lib/ssh/src/ssh_acceptor.erl50
-rw-r--r--lib/ssh/src/ssh_acceptor_sup.erl9
-rw-r--r--lib/ssh/src/ssh_auth.erl53
-rw-r--r--lib/ssh/src/ssh_channel.erl315
-rw-r--r--lib/ssh/src/ssh_channel_sup.erl57
-rw-r--r--lib/ssh/src/ssh_cli.erl306
-rw-r--r--lib/ssh/src/ssh_client_channel.erl458
-rw-r--r--lib/ssh/src/ssh_client_key.erl35
-rw-r--r--lib/ssh/src/ssh_client_key_api.erl33
-rw-r--r--lib/ssh/src/ssh_connect.hrl6
-rw-r--r--lib/ssh/src/ssh_connection.erl814
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl1361
-rw-r--r--lib/ssh/src/ssh_connection_sup.erl7
-rw-r--r--lib/ssh/src/ssh_daemon_channel.erl38
-rw-r--r--lib/ssh/src/ssh_dbg.erl595
-rw-r--r--lib/ssh/src/ssh_dbg.hrl27
-rw-r--r--lib/ssh/src/ssh_file.erl23
-rw-r--r--lib/ssh/src/ssh_info.erl10
-rw-r--r--lib/ssh/src/ssh_io.erl8
-rw-r--r--lib/ssh/src/ssh_message.erl115
-rw-r--r--lib/ssh/src/ssh_no_io.erl29
-rw-r--r--lib/ssh/src/ssh_options.erl344
-rw-r--r--lib/ssh/src/ssh_server_channel.erl55
-rw-r--r--lib/ssh/src/ssh_server_channel_sup.erl62
-rw-r--r--lib/ssh/src/ssh_server_key.erl34
-rw-r--r--lib/ssh/src/ssh_server_key_api.erl14
-rw-r--r--lib/ssh/src/ssh_sftp.erl102
-rw-r--r--lib/ssh/src/ssh_sftpd.erl51
-rw-r--r--lib/ssh/src/ssh_shell.erl43
-rw-r--r--lib/ssh/src/ssh_subsystem_sup.erl22
-rw-r--r--lib/ssh/src/ssh_sup.erl17
-rw-r--r--lib/ssh/src/ssh_system_sup.erl15
-rw-r--r--lib/ssh/src/ssh_transport.erl652
-rw-r--r--lib/ssh/src/ssh_transport.hrl5
-rw-r--r--lib/ssh/src/ssh_xfer.erl4
-rw-r--r--lib/ssh/src/sshc_sup.erl16
-rw-r--r--lib/ssh/src/sshd_sup.erl8
-rw-r--r--lib/ssh/test/Makefile13
-rw-r--r--lib/ssh/test/property_test/ssh_eqc_client_info_timing.erl11
-rw-r--r--lib/ssh/test/property_test/ssh_eqc_subsys.erl4
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE.erl30
-rw-r--r--lib/ssh/test/ssh_basic_SUITE.erl645
-rw-r--r--lib/ssh/test/ssh_bench_SUITE.erl55
-rw-r--r--lib/ssh/test/ssh_bench_dev_null.erl4
-rw-r--r--lib/ssh/test/ssh_chan_behaviours_SUITE.erl152
-rw-r--r--lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_dsa_key (renamed from lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_dsa_key)0
-rw-r--r--lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_dsa_key.pub (renamed from lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_dsa_key.pub)0
-rw-r--r--lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_ecdsa_key6
-rw-r--r--lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_ecdsa_key.pub1
-rw-r--r--lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_rsa_key (renamed from lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_rsa_key)0
-rw-r--r--lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_rsa_key.pub (renamed from lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_rsa_key.pub)0
-rw-r--r--lib/ssh/test/ssh_chan_behaviours_client.erl143
-rw-r--r--lib/ssh/test/ssh_chan_behaviours_server.erl96
-rw-r--r--lib/ssh/test/ssh_compat_SUITE.erl1398
-rwxr-xr-xlib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-base-image38
-rwxr-xr-xlib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-dropbear-ssh28
-rwxr-xr-xlib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-dropbear-ssh-run27
-rwxr-xr-xlib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-ssh-image72
-rwxr-xr-xlib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-ssl-image71
-rwxr-xr-xlib/ssh/test/ssh_compat_SUITE_data/build_scripts/create_all89
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_dsa_key12
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_dsa_key.pub1
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key2565
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key256.pub1
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key3846
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key384.pub1
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key5217
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key521.pub1
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_rsa_key27
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_rsa_key.pub1
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_dsa12
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_dsa.pub1
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa5
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa2565
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa256.pub1
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa3846
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa384.pub1
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa5217
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa521.pub1
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_rsa27
-rw-r--r--lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_rsa.pub1
-rw-r--r--lib/ssh/test/ssh_connection_SUITE.erl203
-rw-r--r--lib/ssh/test/ssh_dbg_SUITE.erl465
-rw-r--r--lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_dsa_key13
-rw-r--r--lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_dsa_key.pub11
-rw-r--r--lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key2565
-rw-r--r--lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key256.pub1
-rw-r--r--lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key3846
-rw-r--r--lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key384.pub1
-rw-r--r--lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key5217
-rw-r--r--lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key521.pub1
-rw-r--r--lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_rsa_key16
-rw-r--r--lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_rsa_key.pub5
-rw-r--r--lib/ssh/test/ssh_echo_server.erl4
-rw-r--r--lib/ssh/test/ssh_engine_SUITE.erl146
-rw-r--r--lib/ssh/test/ssh_engine_SUITE_data/dsa_private_key.pem9
-rw-r--r--lib/ssh/test/ssh_engine_SUITE_data/ecdsa_private_key.pem8
-rw-r--r--lib/ssh/test/ssh_engine_SUITE_data/rsa_private_key.pem28
-rw-r--r--lib/ssh/test/ssh_engine_SUITE_data/rsa_private_key_pwd.pem30
-rw-r--r--lib/ssh/test/ssh_key_cb_engine_keys.erl62
-rw-r--r--lib/ssh/test/ssh_options_SUITE.erl157
-rw-r--r--lib/ssh/test/ssh_peername_sockname_server.erl4
-rw-r--r--lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_dsa_key13
-rw-r--r--lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_dsa_key.pub11
-rw-r--r--lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_ecdsa_key5
-rw-r--r--lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_ecdsa_key.pub1
-rw-r--r--lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_rsa_key16
-rw-r--r--lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_rsa_key.pub5
-rw-r--r--lib/ssh/test/ssh_protocol_SUITE.erl145
-rw-r--r--lib/ssh/test/ssh_renegotiate_SUITE.erl237
-rw-r--r--lib/ssh/test/ssh_renegotiate_SUITE_data/id_dsa13
-rw-r--r--lib/ssh/test/ssh_renegotiate_SUITE_data/id_rsa15
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE.erl36
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE.erl6
-rw-r--r--lib/ssh/test/ssh_sup_SUITE.erl148
-rw-r--r--lib/ssh/test/ssh_test_lib.erl82
-rw-r--r--lib/ssh/test/ssh_test_lib.hrl12
-rw-r--r--lib/ssh/test/ssh_to_openssh_SUITE.erl364
-rw-r--r--lib/ssh/vsn.mk3
-rw-r--r--lib/ssl/doc/src/Makefile25
-rw-r--r--lib/ssl/doc/src/fascicules.xml19
-rw-r--r--lib/ssl/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/ssl/doc/src/notes.xml773
-rw-r--r--lib/ssl/doc/src/pkix_certs.xml59
-rw-r--r--lib/ssl/doc/src/release_notes.xml50
-rw-r--r--lib/ssl/doc/src/ssl.xml534
-rw-r--r--lib/ssl/doc/src/ssl_app.xml43
-rw-r--r--lib/ssl/doc/src/ssl_crl_cache.xml8
-rw-r--r--lib/ssl/doc/src/ssl_distribution.xml166
-rw-r--r--lib/ssl/doc/src/ssl_introduction.xml9
-rw-r--r--lib/ssl/doc/src/ssl_protocol.xml26
-rw-r--r--lib/ssl/doc/src/using_ssl.xml123
-rw-r--r--lib/ssl/doc/src/warning.gifbin1498 -> 0 bytes
-rw-r--r--lib/ssl/examples/src/client_server.erl14
-rw-r--r--lib/ssl/src/Makefile14
-rw-r--r--lib/ssl/src/dtls.erl113
-rw-r--r--lib/ssl/src/dtls_connection.erl1318
-rw-r--r--lib/ssl/src/dtls_handshake.erl171
-rw-r--r--lib/ssl/src/dtls_listener_sup.erl62
-rw-r--r--lib/ssl/src/dtls_packet_demux.erl309
-rw-r--r--lib/ssl/src/dtls_record.erl309
-rw-r--r--lib/ssl/src/dtls_socket.erl83
-rw-r--r--lib/ssl/src/dtls_udp_listener.erl304
-rw-r--r--lib/ssl/src/dtls_udp_sup.erl62
-rw-r--r--lib/ssl/src/dtls_v1.erl16
-rw-r--r--lib/ssl/src/inet6_tls_dist.erl7
-rw-r--r--lib/ssl/src/inet_tls_dist.erl932
-rw-r--r--lib/ssl/src/ssl.app.src16
-rw-r--r--lib/ssl/src/ssl.appup.src4
-rw-r--r--lib/ssl/src/ssl.erl582
-rw-r--r--lib/ssl/src/ssl_alert.erl104
-rw-r--r--lib/ssl/src/ssl_alert.hrl7
-rw-r--r--lib/ssl/src/ssl_api.hrl14
-rw-r--r--lib/ssl/src/ssl_certificate.erl137
-rw-r--r--lib/ssl/src/ssl_cipher.erl1593
-rw-r--r--lib/ssl/src/ssl_cipher.hrl53
-rw-r--r--lib/ssl/src/ssl_cipher_format.erl1764
-rw-r--r--lib/ssl/src/ssl_config.erl20
-rw-r--r--lib/ssl/src/ssl_connection.erl1169
-rw-r--r--lib/ssl/src/ssl_connection.hrl22
-rw-r--r--lib/ssl/src/ssl_connection_sup.erl12
-rw-r--r--lib/ssl/src/ssl_crl_cache.erl18
-rw-r--r--lib/ssl/src/ssl_dist_sup.erl77
-rw-r--r--lib/ssl/src/ssl_handshake.erl2202
-rw-r--r--lib/ssl/src/ssl_handshake.hrl11
-rw-r--r--lib/ssl/src/ssl_internal.hrl25
-rw-r--r--lib/ssl/src/ssl_manager.erl14
-rw-r--r--lib/ssl/src/ssl_pem_cache.erl16
-rw-r--r--lib/ssl/src/ssl_pkix_db.erl34
-rw-r--r--lib/ssl/src/ssl_record.erl28
-rw-r--r--lib/ssl/src/ssl_tls_dist_proxy.erl479
-rw-r--r--lib/ssl/src/ssl_v2.erl38
-rw-r--r--lib/ssl/src/ssl_v3.erl4
-rw-r--r--lib/ssl/src/tls.erl112
-rw-r--r--lib/ssl/src/tls_connection.erl878
-rw-r--r--lib/ssl/src/tls_handshake.erl250
-rw-r--r--lib/ssl/src/tls_record.erl287
-rw-r--r--lib/ssl/src/tls_sender.erl410
-rw-r--r--lib/ssl/src/tls_socket.erl54
-rw-r--r--lib/ssl/src/tls_v1.erl28
-rw-r--r--lib/ssl/test/Makefile12
-rw-r--r--lib/ssl/test/erl_make_certs.erl477
-rw-r--r--lib/ssl/test/make_certs.erl30
-rw-r--r--lib/ssl/test/ssl.spec7
-rw-r--r--lib/ssl/test/ssl_ECC.erl172
-rw-r--r--lib/ssl/test/ssl_ECC_SUITE.erl571
-rw-r--r--lib/ssl/test/ssl_ECC_openssl_SUITE.erl218
-rw-r--r--lib/ssl/test/ssl_alpn_handshake_SUITE.erl87
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl901
-rw-r--r--lib/ssl/test/ssl_bench.spec2
-rw-r--r--lib/ssl/test/ssl_bench_SUITE.erl64
-rw-r--r--lib/ssl/test/ssl_bench_test_lib.erl75
-rw-r--r--lib/ssl/test/ssl_certificate_verify_SUITE.erl325
-rw-r--r--lib/ssl/test/ssl_crl_SUITE.erl14
-rw-r--r--lib/ssl/test/ssl_dist_SUITE.erl328
-rw-r--r--lib/ssl/test/ssl_dist_bench_SUITE.erl526
-rw-r--r--lib/ssl/test/ssl_dist_test_lib.erl343
-rw-r--r--lib/ssl/test/ssl_dist_test_lib.hrl26
-rw-r--r--lib/ssl/test/ssl_engine_SUITE.erl162
-rw-r--r--lib/ssl/test/ssl_handshake_SUITE.erl40
-rw-r--r--lib/ssl/test/ssl_npn_handshake_SUITE.erl11
-rw-r--r--lib/ssl/test/ssl_packet_SUITE.erl109
-rw-r--r--lib/ssl/test/ssl_payload_SUITE.erl11
-rw-r--r--lib/ssl/test/ssl_pem_cache_SUITE.erl47
-rw-r--r--lib/ssl/test/ssl_session_cache_SUITE.erl6
-rw-r--r--lib/ssl/test/ssl_sni_SUITE.erl240
-rw-r--r--lib/ssl/test/ssl_test_lib.erl1176
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl1047
-rw-r--r--lib/ssl/test/x509_test.erl288
-rw-r--r--lib/ssl/vsn.mk2
-rw-r--r--lib/stdlib/doc/src/Makefile22
-rw-r--r--lib/stdlib/doc/src/assert_hrl.xml4
-rw-r--r--lib/stdlib/doc/src/c.xml11
-rw-r--r--lib/stdlib/doc/src/calendar.xml93
-rw-r--r--lib/stdlib/doc/src/digraph.xml6
-rw-r--r--lib/stdlib/doc/src/epp.xml8
-rw-r--r--lib/stdlib/doc/src/erl_tar.xml47
-rw-r--r--lib/stdlib/doc/src/ets.xml57
-rw-r--r--lib/stdlib/doc/src/fascicules.xml18
-rw-r--r--lib/stdlib/doc/src/filelib.xml33
-rw-r--r--lib/stdlib/doc/src/filename.xml83
-rw-r--r--lib/stdlib/doc/src/gb_sets.xml4
-rw-r--r--lib/stdlib/doc/src/gen_event.xml7
-rw-r--r--lib/stdlib/doc/src/gen_server.xml60
-rw-r--r--lib/stdlib/doc/src/gen_statem.xml291
-rw-r--r--lib/stdlib/doc/src/io.xml126
-rw-r--r--lib/stdlib/doc/src/io_lib.xml43
-rw-r--r--lib/stdlib/doc/src/lib.xml103
-rw-r--r--lib/stdlib/doc/src/lists.xml16
-rw-r--r--lib/stdlib/doc/src/maps.xml96
-rw-r--r--lib/stdlib/doc/src/notes.xml658
-rw-r--r--lib/stdlib/doc/src/ordsets.xml11
-rw-r--r--lib/stdlib/doc/src/part_notes.xml39
-rw-r--r--lib/stdlib/doc/src/part_notes_history.xml39
-rw-r--r--lib/stdlib/doc/src/proc_lib.xml49
-rw-r--r--lib/stdlib/doc/src/rand.xml193
-rw-r--r--lib/stdlib/doc/src/ref_man.xml4
-rw-r--r--lib/stdlib/doc/src/sets.xml11
-rw-r--r--lib/stdlib/doc/src/specs.xml2
-rw-r--r--lib/stdlib/doc/src/string.xml10
-rw-r--r--lib/stdlib/doc/src/supervisor.xml14
-rw-r--r--lib/stdlib/doc/src/sys.xml12
-rw-r--r--lib/stdlib/doc/src/timer.xml6
-rw-r--r--lib/stdlib/doc/src/unicode.xml9
-rw-r--r--lib/stdlib/doc/src/unicode_usage.xml8
-rw-r--r--lib/stdlib/doc/src/uri_string.xml359
-rw-r--r--lib/stdlib/doc/src/user_guide.gifbin1581 -> 0 bytes
-rw-r--r--lib/stdlib/include/assert.hrl22
-rw-r--r--lib/stdlib/src/Makefile13
-rw-r--r--lib/stdlib/src/array.erl4
-rw-r--r--lib/stdlib/src/base64.erl623
-rw-r--r--lib/stdlib/src/beam_lib.erl28
-rw-r--r--lib/stdlib/src/binary.erl30
-rw-r--r--lib/stdlib/src/c.erl30
-rw-r--r--lib/stdlib/src/calendar.erl185
-rw-r--r--lib/stdlib/src/dets.erl57
-rw-r--r--lib/stdlib/src/dets_utils.erl7
-rw-r--r--lib/stdlib/src/edlin.erl138
-rw-r--r--lib/stdlib/src/edlin_expand.erl26
-rw-r--r--lib/stdlib/src/epp.erl163
-rw-r--r--lib/stdlib/src/erl_compile.erl3
-rw-r--r--lib/stdlib/src/erl_error.erl421
-rw-r--r--lib/stdlib/src/erl_eval.erl408
-rw-r--r--lib/stdlib/src/erl_internal.erl6
-rw-r--r--lib/stdlib/src/erl_lint.erl136
-rw-r--r--lib/stdlib/src/erl_parse.yrl88
-rw-r--r--lib/stdlib/src/erl_posix_msg.erl7
-rw-r--r--lib/stdlib/src/erl_pp.erl44
-rw-r--r--lib/stdlib/src/erl_scan.erl6
-rw-r--r--lib/stdlib/src/erl_tar.erl82
-rw-r--r--lib/stdlib/src/erl_tar.hrl16
-rw-r--r--lib/stdlib/src/error_logger_file_h.erl36
-rw-r--r--lib/stdlib/src/error_logger_tty_h.erl116
-rw-r--r--lib/stdlib/src/escript.erl36
-rw-r--r--lib/stdlib/src/ets.erl59
-rw-r--r--lib/stdlib/src/eval_bits.erl21
-rw-r--r--lib/stdlib/src/file_sorter.erl10
-rw-r--r--lib/stdlib/src/filelib.erl63
-rw-r--r--lib/stdlib/src/filename.erl154
-rw-r--r--lib/stdlib/src/gen.erl89
-rw-r--r--lib/stdlib/src/gen_event.erl106
-rw-r--r--lib/stdlib/src/gen_fsm.erl125
-rw-r--r--lib/stdlib/src/gen_server.erl186
-rw-r--r--lib/stdlib/src/gen_statem.erl1786
-rw-r--r--lib/stdlib/src/io.erl13
-rw-r--r--lib/stdlib/src/io_lib.erl251
-rw-r--r--lib/stdlib/src/io_lib_format.erl300
-rw-r--r--lib/stdlib/src/io_lib_fread.erl4
-rw-r--r--lib/stdlib/src/io_lib_pretty.erl678
-rw-r--r--lib/stdlib/src/lib.erl746
-rw-r--r--lib/stdlib/src/lists.erl19
-rw-r--r--lib/stdlib/src/maps.erl128
-rw-r--r--lib/stdlib/src/ms_transform.erl13
-rw-r--r--lib/stdlib/src/ordsets.erl11
-rw-r--r--lib/stdlib/src/otp_internal.erl36
-rw-r--r--lib/stdlib/src/pool.erl8
-rw-r--r--lib/stdlib/src/proc_lib.erl164
-rw-r--r--lib/stdlib/src/qlc.erl65
-rw-r--r--lib/stdlib/src/rand.erl261
-rw-r--r--lib/stdlib/src/sets.erl10
-rw-r--r--lib/stdlib/src/shell.erl39
-rw-r--r--lib/stdlib/src/slave.erl20
-rw-r--r--lib/stdlib/src/stdlib.app.src7
-rw-r--r--lib/stdlib/src/stdlib.appup.src8
-rw-r--r--lib/stdlib/src/string.erl949
-rw-r--r--lib/stdlib/src/supervisor.erl997
-rw-r--r--lib/stdlib/src/supervisor_bridge.erl29
-rw-r--r--lib/stdlib/src/sys.erl65
-rw-r--r--lib/stdlib/src/uri_string.erl2148
-rw-r--r--lib/stdlib/src/zip.erl5
-rw-r--r--lib/stdlib/test/Makefile11
-rw-r--r--lib/stdlib/test/array_SUITE.erl10
-rw-r--r--lib/stdlib/test/base64_SUITE.erl109
-rw-r--r--lib/stdlib/test/beam_lib_SUITE.erl34
-rw-r--r--lib/stdlib/test/c_SUITE.erl55
-rw-r--r--lib/stdlib/test/calendar_SUITE.erl161
-rw-r--r--lib/stdlib/test/dets_SUITE.erl21
-rw-r--r--lib/stdlib/test/edlin_expand_SUITE.erl26
-rw-r--r--lib/stdlib/test/epp_SUITE.erl189
-rw-r--r--lib/stdlib/test/epp_SUITE_data/source_name.erl27
-rw-r--r--lib/stdlib/test/erl_eval_SUITE.erl268
-rw-r--r--lib/stdlib/test/erl_internal_SUITE.erl4
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl121
-rw-r--r--lib/stdlib/test/erl_pp_SUITE.erl6
-rw-r--r--lib/stdlib/test/error_logger_h_SUITE.erl20
-rwxr-xr-xlib/stdlib/test/escript_SUITE_data/unicode12
-rwxr-xr-xlib/stdlib/test/escript_SUITE_data/unicode22
-rw-r--r--lib/stdlib/test/ets_SUITE.erl251
-rw-r--r--lib/stdlib/test/filelib_SUITE.erl90
-rw-r--r--lib/stdlib/test/filename_SUITE.erl120
-rw-r--r--lib/stdlib/test/gen_fsm_SUITE.erl8
-rw-r--r--lib/stdlib/test/gen_server_SUITE.erl125
-rw-r--r--lib/stdlib/test/gen_server_SUITE_data/oc_server.erl12
-rw-r--r--lib/stdlib/test/gen_statem_SUITE.erl63
-rw-r--r--lib/stdlib/test/id_transform_SUITE.erl11
-rw-r--r--lib/stdlib/test/io_SUITE.erl287
-rw-r--r--lib/stdlib/test/lists_SUITE.erl20
-rw-r--r--lib/stdlib/test/maps_SUITE.erl48
-rw-r--r--lib/stdlib/test/proc_lib_SUITE.erl89
-rw-r--r--lib/stdlib/test/property_test/README12
-rw-r--r--lib/stdlib/test/property_test/uri_string_recompose.erl571
-rw-r--r--lib/stdlib/test/qlc_SUITE.erl47
-rw-r--r--lib/stdlib/test/rand_SUITE.erl803
-rw-r--r--lib/stdlib/test/re_SUITE.erl17
-rw-r--r--lib/stdlib/test/re_SUITE_data/testoutput14
-rw-r--r--lib/stdlib/test/re_SUITE_data/testoutput216
-rw-r--r--lib/stdlib/test/re_SUITE_data/testoutput58
-rw-r--r--lib/stdlib/test/re_SUITE_data/testoutput84
-rw-r--r--lib/stdlib/test/sets_SUITE.erl17
-rw-r--r--lib/stdlib/test/sets_test_lib.erl15
-rw-r--r--lib/stdlib/test/shell_SUITE.erl81
-rw-r--r--lib/stdlib/test/stdlib.spec3
-rw-r--r--lib/stdlib/test/stdlib_bench.spec10
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE.erl546
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE_data/generic_fsm.erl59
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE_data/generic_server.erl31
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE_data/generic_server_timer.erl31
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE_data/generic_statem.erl58
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE_data/generic_statem_complex.erl66
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE_data/simple_server.erl31
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_mon.erl33
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_timer.erl33
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_timer_mon.erl35
-rw-r--r--lib/stdlib/test/string_SUITE.erl174
-rw-r--r--lib/stdlib/test/supervisor_1.erl4
-rw-r--r--lib/stdlib/test/supervisor_SUITE.erl373
-rw-r--r--lib/stdlib/test/supervisor_deadlock.erl2
-rw-r--r--lib/stdlib/test/sys_SUITE.erl28
-rw-r--r--lib/stdlib/test/tar_SUITE.erl30
-rw-r--r--lib/stdlib/test/unicode_expand.erl36
-rw-r--r--lib/stdlib/test/unicode_util_SUITE.erl87
-rw-r--r--lib/stdlib/test/unicode_util_SUITE_data/GraphemeBreakTest.txt175
-rw-r--r--lib/stdlib/test/unicode_util_SUITE_data/LineBreakTest.txt23
-rw-r--r--lib/stdlib/test/unicode_util_SUITE_data/NormalizationTest.txt30
-rw-r--r--lib/stdlib/test/uri_string_SUITE.erl1164
-rw-r--r--lib/stdlib/test/uri_string_property_test_SUITE.erl44
-rw-r--r--lib/stdlib/test/zip_SUITE.erl5
-rw-r--r--lib/stdlib/test/zzz_SUITE.erl37
-rw-r--r--lib/stdlib/uc_spec/CaseFolding.txt8
-rw-r--r--lib/stdlib/uc_spec/CompositionExclusions.txt6
-rw-r--r--lib/stdlib/uc_spec/GraphemeBreakProperty.txt78
-rw-r--r--lib/stdlib/uc_spec/PropList.txt83
-rw-r--r--lib/stdlib/uc_spec/SpecialCasing.txt8
-rw-r--r--lib/stdlib/uc_spec/UnicodeData.txt1028
-rwxr-xr-xlib/stdlib/uc_spec/gen_unicode_mod.escript57
-rw-r--r--lib/stdlib/vsn.mk2
-rw-r--r--lib/syntax_tools/doc/src/Makefile32
-rw-r--r--lib/syntax_tools/doc/src/fascicules.xml18
-rw-r--r--lib/syntax_tools/doc/src/notes.xml115
-rw-r--r--lib/syntax_tools/doc/src/part_notes.xml42
-rw-r--r--lib/syntax_tools/src/Makefile2
-rw-r--r--lib/syntax_tools/src/epp_dodger.erl40
-rw-r--r--lib/syntax_tools/src/erl_comment_scan.erl4
-rw-r--r--lib/syntax_tools/src/erl_prettypr.erl20
-rw-r--r--lib/syntax_tools/src/erl_syntax.erl114
-rw-r--r--lib/syntax_tools/src/erl_syntax_lib.erl4
-rw-r--r--lib/syntax_tools/src/erl_tidy.erl24
-rw-r--r--lib/syntax_tools/src/igor.erl20
-rw-r--r--lib/syntax_tools/src/merl.erl6
-rw-r--r--lib/syntax_tools/src/merl_transform.erl2
-rw-r--r--lib/syntax_tools/src/syntax_tools.app.src2
-rw-r--r--lib/syntax_tools/test/merl_SUITE.erl14
-rw-r--r--lib/syntax_tools/test/syntax_tools_SUITE.erl110
-rw-r--r--lib/syntax_tools/vsn.mk2
-rw-r--r--lib/tftp/AUTHORS11
-rw-r--r--lib/tftp/Makefile78
-rw-r--r--lib/tftp/doc/html/.gitignore (renamed from lib/cosEvent/include/.gitignore)0
-rw-r--r--lib/tftp/doc/man3/.gitignore (renamed from lib/cosEvent/test/idl_output/.gitignore)0
-rw-r--r--lib/tftp/doc/man6/.gitignore (renamed from lib/cosEventDomain/doc/html/.gitignore)0
-rw-r--r--lib/tftp/doc/pdf/.gitignore (renamed from lib/cosEventDomain/doc/man3/.gitignore)0
-rw-r--r--lib/tftp/doc/src/Makefile155
-rw-r--r--lib/tftp/doc/src/book.xml49
-rw-r--r--lib/tftp/doc/src/getting_started.xml81
-rw-r--r--lib/tftp/doc/src/introduction.xml62
-rw-r--r--lib/tftp/doc/src/notes.xml68
-rw-r--r--lib/tftp/doc/src/ref_man.xml36
-rw-r--r--lib/tftp/doc/src/tftp.xml599
-rw-r--r--lib/tftp/doc/src/usersguide.xml37
-rw-r--r--lib/tftp/ebin/.gitignore (renamed from lib/cosEventDomain/doc/man6/.gitignore)0
-rw-r--r--lib/tftp/info2
-rw-r--r--lib/tftp/src/Makefile110
-rw-r--r--lib/tftp/src/tftp.app.src22
-rw-r--r--lib/tftp/src/tftp.appup.src26
-rw-r--r--lib/tftp/src/tftp.erl409
-rw-r--r--lib/tftp/src/tftp.hrl69
-rw-r--r--lib/tftp/src/tftp_app.erl56
-rw-r--r--lib/tftp/src/tftp_binary.erl239
-rw-r--r--lib/tftp/src/tftp_engine.erl1422
-rw-r--r--lib/tftp/src/tftp_file.erl390
-rw-r--r--lib/tftp/src/tftp_lib.erl474
-rw-r--r--lib/tftp/src/tftp_logger.erl99
-rw-r--r--lib/tftp/src/tftp_sup.erl111
-rw-r--r--lib/tftp/test/Makefile250
-rw-r--r--lib/tftp/test/tftp.config1
-rw-r--r--lib/tftp/test/tftp.cover2
-rw-r--r--lib/tftp/test/tftp.spec1
-rw-r--r--lib/tftp/test/tftp_SUITE.erl1001
-rw-r--r--lib/tftp/test/tftp_bench.spec1
-rw-r--r--lib/tftp/test/tftp_test_lib.erl308
-rw-r--r--lib/tftp/test/tftp_test_lib.hrl44
-rw-r--r--lib/tftp/vsn.mk24
-rw-r--r--lib/tools/doc/specs/.gitignore1
-rw-r--r--lib/tools/doc/src/Makefile35
-rw-r--r--lib/tools/doc/src/fascicules.xml18
-rw-r--r--lib/tools/doc/src/fprof.xml12
-rw-r--r--lib/tools/doc/src/instrument.xml527
-rw-r--r--lib/tools/doc/src/lcnt.xml108
-rw-r--r--lib/tools/doc/src/lcnt_chapter.xml9
-rw-r--r--lib/tools/doc/src/note.gifbin1539 -> 0 bytes
-rw-r--r--lib/tools/doc/src/notes.xml189
-rw-r--r--lib/tools/doc/src/part_notes.xml39
-rw-r--r--lib/tools/doc/src/part_notes_history.xml39
-rw-r--r--lib/tools/doc/src/specs.xml12
-rw-r--r--lib/tools/doc/src/venn2.fig66
-rw-r--r--lib/tools/doc/src/venn2.gifbin3369 -> 3507 bytes
-rw-r--r--lib/tools/doc/src/warning.gifbin1498 -> 0 bytes
-rw-r--r--lib/tools/doc/src/xref.xml12
-rw-r--r--lib/tools/emacs/Makefile20
-rw-r--r--lib/tools/emacs/erlang-skels.el248
-rw-r--r--lib/tools/emacs/erlang.el328
-rw-r--r--lib/tools/emacs/test.erl.indented784
-rw-r--r--lib/tools/emacs/test.erl.orig784
-rw-r--r--lib/tools/priv/styles.css91
-rw-r--r--lib/tools/src/Makefile7
-rw-r--r--lib/tools/src/cover.erl145
-rw-r--r--lib/tools/src/eprof.erl30
-rw-r--r--lib/tools/src/fprof.erl41
-rw-r--r--lib/tools/src/instrument.erl538
-rw-r--r--lib/tools/src/lcnt.erl93
-rw-r--r--lib/tools/src/make.erl48
-rw-r--r--lib/tools/src/tools.app.src4
-rw-r--r--lib/tools/src/xref.erl6
-rw-r--r--lib/tools/src/xref_base.erl47
-rw-r--r--lib/tools/src/xref_parser.yrl6
-rw-r--r--lib/tools/src/xref_reader.erl18
-rw-r--r--lib/tools/src/xref_utils.erl22
-rw-r--r--lib/tools/test/cover_SUITE.erl28
-rw-r--r--lib/tools/test/emacs_SUITE.erl75
-rw-r--r--lib/tools/test/emacs_SUITE_data/comments25
-rw-r--r--lib/tools/test/emacs_SUITE_data/comprehensions47
-rw-r--r--lib/tools/test/emacs_SUITE_data/funcs174
-rw-r--r--lib/tools/test/emacs_SUITE_data/highlight78
-rw-r--r--lib/tools/test/emacs_SUITE_data/icr157
-rw-r--r--lib/tools/test/emacs_SUITE_data/macros31
-rw-r--r--lib/tools/test/emacs_SUITE_data/records35
-rw-r--r--lib/tools/test/emacs_SUITE_data/terms174
-rw-r--r--lib/tools/test/emacs_SUITE_data/try_catch166
-rw-r--r--lib/tools/test/emacs_SUITE_data/type_specs110
-rw-r--r--lib/tools/test/eprof_SUITE_data/eed.erl6
-rw-r--r--lib/tools/test/fprof_SUITE.erl21
-rw-r--r--lib/tools/test/fprof_SUITE_data/fprof_unicode.erl36
-rw-r--r--lib/tools/test/instrument_SUITE.erl391
-rw-r--r--lib/tools/test/lcnt_SUITE.erl22
-rw-r--r--lib/tools/test/make_SUITE.erl43
-rw-r--r--lib/tools/test/xref_SUITE.erl98
-rw-r--r--lib/tools/vsn.mk2
-rw-r--r--lib/wx/api_gen/README3
-rw-r--r--lib/wx/api_gen/gen_util.erl6
-rw-r--r--lib/wx/api_gen/gl_gen.erl6
-rw-r--r--lib/wx/api_gen/gl_gen_erl.erl42
-rw-r--r--lib/wx/api_gen/gl_scan_doc.erl6
-rw-r--r--lib/wx/api_gen/wx_doxygen.conf6
-rw-r--r--lib/wx/api_gen/wx_extra/wxGraphicsRenderer.c_src58
-rw-r--r--lib/wx/api_gen/wx_gen.erl18
-rw-r--r--lib/wx/api_gen/wx_gen_cpp.erl11
-rw-r--r--lib/wx/api_gen/wx_gen_erl.erl9
-rw-r--r--lib/wx/api_gen/wxapi.conf31
-rw-r--r--lib/wx/c_src/gen/wxe_funcs.cpp38
-rw-r--r--lib/wx/c_src/gen/wxe_init.cpp116
-rw-r--r--lib/wx/c_src/gen/wxe_macros.h10
-rw-r--r--lib/wx/c_src/wxe_driver.c190
-rw-r--r--lib/wx/c_src/wxe_driver.h4
-rw-r--r--lib/wx/c_src/wxe_main.cpp15
-rw-r--r--lib/wx/c_src/wxe_ps_init.c15
-rw-r--r--lib/wx/doc/src/Makefile45
-rw-r--r--lib/wx/doc/src/fascicules.xml15
-rw-r--r--lib/wx/doc/src/notes.xml79
-rw-r--r--lib/wx/doc/src/part_notes.xml38
-rw-r--r--lib/wx/examples/demo/demo.erl2
-rw-r--r--lib/wx/examples/demo/ex_aui.erl5
-rw-r--r--lib/wx/examples/simple/hello.erl3
-rw-r--r--lib/wx/examples/simple/hello2.erl7
-rw-r--r--lib/wx/examples/simple/menu.erl33
-rw-r--r--lib/wx/examples/simple/minimal.erl4
-rw-r--r--lib/wx/examples/sudoku/sudoku.erl5
-rw-r--r--lib/wx/examples/sudoku/sudoku_game.erl25
-rw-r--r--lib/wx/examples/sudoku/sudoku_gui.erl4
-rw-r--r--lib/wx/examples/xrc/xrc.erl4
-rw-r--r--lib/wx/include/wx.hrl18
-rw-r--r--lib/wx/src/gen/gl.erl9455
-rw-r--r--lib/wx/src/gen/glu.erl405
-rw-r--r--lib/wx/src/gen/wxGraphicsContext.erl4
-rw-r--r--lib/wx/src/gen/wxe_debug.hrl10
-rw-r--r--lib/wx/src/gen/wxe_funcs.hrl10
-rw-r--r--lib/wx/src/wx.erl12
-rw-r--r--lib/wx/src/wx_object.erl22
-rw-r--r--lib/wx/src/wxe_master.erl15
-rw-r--r--lib/wx/src/wxe_server.erl10
-rw-r--r--lib/wx/test/wx_app_SUITE.erl9
-rw-r--r--lib/wx/test/wx_basic_SUITE.erl6
-rw-r--r--lib/wx/test/wx_class_SUITE.erl12
-rw-r--r--lib/wx/test/wx_event_SUITE.erl11
-rw-r--r--lib/wx/test/wx_oc_object.erl4
-rw-r--r--lib/wx/test/wx_opengl_SUITE.erl4
-rw-r--r--lib/wx/test/wx_test_lib.erl15
-rw-r--r--lib/wx/test/wx_xtra_SUITE.erl5
-rwxr-xr-xlib/wx/test/wxt6
-rw-r--r--lib/wx/test/wxt.erl34
-rw-r--r--lib/wx/vsn.mk2
-rw-r--r--lib/xmerl/doc/src/Makefile45
-rw-r--r--lib/xmerl/doc/src/fascicules.xml18
-rw-r--r--lib/xmerl/doc/src/notes.xml47
-rw-r--r--lib/xmerl/doc/src/part_notes.xml40
-rw-r--r--lib/xmerl/src/xmerl_scan.erl4
-rw-r--r--lib/xmerl/src/xmerl_xsd.erl4
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/eventp/CMOM.xml2
-rw-r--r--lib/xmerl/test/xmerl_SUITE_data/eventp/CelloMOM.xml2
-rw-r--r--lib/xmerl/vsn.mk2
2957 files changed, 164197 insertions, 275153 deletions
diff --git a/lib/.gitignore b/lib/.gitignore
index 283393faa9..07a94c7ae6 100644
--- a/lib/.gitignore
+++ b/lib/.gitignore
@@ -1,32 +1,3 @@
-# common test
-
-/common_test/doc/src/ct.xml
-/common_test/doc/src/ct_cover.xml
-/common_test/doc/src/ct_ftp.xml
-/common_test/doc/src/ct_master.xml
-/common_test/doc/src/ct_rpc.xml
-/common_test/doc/src/ct_snmp.xml
-/common_test/doc/src/ct_ssh.xml
-/common_test/doc/src/ct_netconfc.xml
-/common_test/doc/src/ct_telnet.xml
-/common_test/doc/src/unix_telnet.xml
-
-# edoc
-
-/edoc/doc/src/chapter.xml
-/edoc/doc/src/edoc.xml
-/edoc/doc/src/edoc_doclet.xml
-/edoc/doc/src/edoc_extract.xml
-/edoc/doc/src/edoc_layout.xml
-/edoc/doc/src/edoc_lib.xml
-/edoc/doc/src/edoc_run.xml
-
-# eunit
-
-/eunit/doc/src/chapter.xml
-/eunit/doc/src/eunit.xml
-/eunit/doc/src/eunit_surefire.xml
-
# erl_interface
/erl_interface/bin
@@ -34,15 +5,6 @@
/erl_interface/obj.st
/erl_interface/obj
-# gs
-
-/gs/doc/src/gs_chapter2.xml
-/gs/doc/src/gs_chapter4.xml
-/gs/doc/src/gs_chapter5.xml
-/gs/doc/src/gs_chapter6.xml
-/gs/doc/src/gs_chapter7.xml
-/gs/doc/src/gs_chapter8.xml
-
# megaco
/megaco/src/binary/megaco_ber_bin_drv_media_gateway_control_prev3a.erl
@@ -129,435 +91,3 @@
/megaco/src/text/megaco_text_parser_v1.erl
/megaco/src/text/megaco_text_parser_v2.erl
/megaco/src/text/megaco_text_parser_v3.erl
-/megaco/doc/html/mstone1.jpg
-
-# mnesia
-
-/mnesia/doc/src/Mnesia_App_A.xml
-/mnesia/doc/src/Mnesia_App_B.xml
-/mnesia/doc/src/Mnesia_App_C.xml
-/mnesia/doc/src/Mnesia_App_D.xml
-/mnesia/doc/src/Mnesia_chap2.xml
-/mnesia/doc/src/Mnesia_chap3.xml
-/mnesia/doc/src/Mnesia_chap4.xml
-/mnesia/doc/src/Mnesia_chap5.xml
-/mnesia/doc/src/Mnesia_chap7.xml
-
-# orber & cos* applications
-
-/orber/test/idl_output
-/cosEvent/test/idl_output
-/cosNotification/test/idl_output
-/cosTransactions/test/idl_output
-
-/cosEvent/include/CosEventChannelAdmin.hrl
-/cosEvent/include/CosEventChannelAdmin_ConsumerAdmin.hrl
-/cosEvent/include/CosEventChannelAdmin_EventChannel.hrl
-/cosEvent/include/CosEventChannelAdmin_ProxyPullConsumer.hrl
-/cosEvent/include/CosEventChannelAdmin_ProxyPullSupplier.hrl
-/cosEvent/include/CosEventChannelAdmin_ProxyPushConsumer.hrl
-/cosEvent/include/CosEventChannelAdmin_ProxyPushSupplier.hrl
-/cosEvent/include/CosEventChannelAdmin_SupplierAdmin.hrl
-/cosEvent/include/CosEventComm.hrl
-/cosEvent/include/CosEventComm_PullConsumer.hrl
-/cosEvent/include/CosEventComm_PullSupplier.hrl
-/cosEvent/include/CosEventComm_PushConsumer.hrl
-/cosEvent/include/CosEventComm_PushSupplier.hrl
-/cosEvent/include/oe_CosEventChannelAdmin.hrl
-/cosEvent/include/oe_CosEventComm.hrl
-/cosEvent/src/CosEventChannelAdmin_AlreadyConnected.erl
-/cosEvent/src/CosEventChannelAdmin_ConsumerAdmin.erl
-/cosEvent/src/CosEventChannelAdmin_EventChannel.erl
-/cosEvent/src/CosEventChannelAdmin_ProxyPullConsumer.erl
-/cosEvent/src/CosEventChannelAdmin_ProxyPullSupplier.erl
-/cosEvent/src/CosEventChannelAdmin_ProxyPushConsumer.erl
-/cosEvent/src/CosEventChannelAdmin_ProxyPushSupplier.erl
-/cosEvent/src/CosEventChannelAdmin_SupplierAdmin.erl
-/cosEvent/src/CosEventChannelAdmin_TypeError.erl
-/cosEvent/src/CosEventComm_Disconnected.erl
-/cosEvent/src/CosEventComm_PullConsumer.erl
-/cosEvent/src/CosEventComm_PullSupplier.erl
-/cosEvent/src/CosEventComm_PushConsumer.erl
-/cosEvent/src/CosEventComm_PushSupplier.erl
-/cosEvent/src/oe_CosEventChannelAdmin.erl
-/cosEvent/src/oe_CosEventComm.erl
-/cosEvent/src/oe_CosEventComm_CAdmin.erl
-/cosEvent/src/oe_CosEventComm_CAdmin.hrl
-/cosEvent/src/oe_CosEventComm_Channel.erl
-/cosEvent/src/oe_CosEventComm_Channel.hrl
-/cosEvent/src/oe_CosEventComm_Event.erl
-/cosEvent/src/oe_CosEventComm_Event.hrl
-/cosEvent/src/oe_CosEventComm_PullerS.erl
-/cosEvent/src/oe_CosEventComm_PullerS.hrl
-/cosEvent/src/oe_CosEventComm_PusherS.erl
-/cosEvent/src/oe_CosEventComm_PusherS.hrl
-/cosEvent/src/oe_cosEventApp.erl
-/cosEvent/src/oe_cosEventApp.hrl
-/cosEventDomain/include/CosEventDomainAdmin.hrl
-/cosEventDomain/include/CosEventDomainAdmin_EventDomain.hrl
-/cosEventDomain/include/CosEventDomainAdmin_EventDomainFactory.hrl
-/cosEventDomain/include/oe_CosEventDomainAdmin.hrl
-/cosEventDomain/src/CosEventDomainAdmin.erl
-/cosEventDomain/src/CosEventDomainAdmin_AlreadyExists.erl
-/cosEventDomain/src/CosEventDomainAdmin_Connection.erl
-/cosEventDomain/src/CosEventDomainAdmin_ConnectionIDSeq.erl
-/cosEventDomain/src/CosEventDomainAdmin_ConnectionNotFound.erl
-/cosEventDomain/src/CosEventDomainAdmin_CycleCreationForbidden.erl
-/cosEventDomain/src/CosEventDomainAdmin_CycleSeq.erl
-/cosEventDomain/src/CosEventDomainAdmin_DiamondCreationForbidden.erl
-/cosEventDomain/src/CosEventDomainAdmin_DiamondSeq.erl
-/cosEventDomain/src/CosEventDomainAdmin_DomainIDSeq.erl
-/cosEventDomain/src/CosEventDomainAdmin_DomainNotFound.erl
-/cosEventDomain/src/CosEventDomainAdmin_EventDomain.erl
-/cosEventDomain/src/CosEventDomainAdmin_EventDomainFactory.erl
-/cosEventDomain/src/CosEventDomainAdmin_MemberIDSeq.erl
-/cosEventDomain/src/CosEventDomainAdmin_RouteSeq.erl
-/cosEventDomain/src/oe_CosEventDomainAdmin.erl
-/cosFileTransfer/include/CosFileTransfer.hrl
-/cosFileTransfer/include/CosFileTransfer_Directory.hrl
-/cosFileTransfer/include/CosFileTransfer_File.hrl
-/cosFileTransfer/include/CosFileTransfer_FileIterator.hrl
-/cosFileTransfer/include/CosFileTransfer_FileTransferSession.hrl
-/cosFileTransfer/include/CosFileTransfer_VirtualFileSystem.hrl
-/cosFileTransfer/include/oe_CosFileTransfer.hrl
-/cosFileTransfer/src/CosFileTransfer.erl
-/cosFileTransfer/src/CosFileTransfer_AccessLevel.erl
-/cosFileTransfer/src/CosFileTransfer_CommandNotImplementedException.erl
-/cosFileTransfer/src/CosFileTransfer_Directory.erl
-/cosFileTransfer/src/CosFileTransfer_File.erl
-/cosFileTransfer/src/CosFileTransfer_FileIterator.erl
-/cosFileTransfer/src/CosFileTransfer_FileList.erl
-/cosFileTransfer/src/CosFileTransfer_FileNameList.erl
-/cosFileTransfer/src/CosFileTransfer_FileNotFoundException.erl
-/cosFileTransfer/src/CosFileTransfer_FileTransferSession.erl
-/cosFileTransfer/src/CosFileTransfer_FileWrapper.erl
-/cosFileTransfer/src/CosFileTransfer_IllegalOperationException.erl
-/cosFileTransfer/src/CosFileTransfer_ProtocolAddressList.erl
-/cosFileTransfer/src/CosFileTransfer_ProtocolSupport.erl
-/cosFileTransfer/src/CosFileTransfer_RequestFailureException.erl
-/cosFileTransfer/src/CosFileTransfer_SessionException.erl
-/cosFileTransfer/src/CosFileTransfer_SupportedProtocolAddresses.erl
-/cosFileTransfer/src/CosFileTransfer_TransferException.erl
-/cosFileTransfer/src/CosFileTransfer_VirtualFileSystem.erl
-/cosFileTransfer/src/CosFileTransfer_VirtualFileSystem_ContentList.erl
-/cosFileTransfer/src/oe_CosFileTransfer.erl
-/cosNotification/include/CosNotification.hrl
-/cosNotification/include/CosNotification_AdminPropertiesAdmin.hrl
-/cosNotification/include/CosNotification_QoSAdmin.hrl
-/cosNotification/include/CosNotifyChannelAdmin.hrl
-/cosNotification/include/CosNotifyChannelAdmin_ConsumerAdmin.hrl
-/cosNotification/include/CosNotifyChannelAdmin_EventChannel.hrl
-/cosNotification/include/CosNotifyChannelAdmin_EventChannelFactory.hrl
-/cosNotification/include/CosNotifyChannelAdmin_ProxyConsumer.hrl
-/cosNotification/include/CosNotifyChannelAdmin_ProxyPullConsumer.hrl
-/cosNotification/include/CosNotifyChannelAdmin_ProxyPullSupplier.hrl
-/cosNotification/include/CosNotifyChannelAdmin_ProxyPushConsumer.hrl
-/cosNotification/include/CosNotifyChannelAdmin_ProxyPushSupplier.hrl
-/cosNotification/include/CosNotifyChannelAdmin_ProxySupplier.hrl
-/cosNotification/include/CosNotifyChannelAdmin_SequenceProxyPullConsumer.hrl
-/cosNotification/include/CosNotifyChannelAdmin_SequenceProxyPullSupplier.hrl
-/cosNotification/include/CosNotifyChannelAdmin_SequenceProxyPushConsumer.hrl
-/cosNotification/include/CosNotifyChannelAdmin_SequenceProxyPushSupplier.hrl
-/cosNotification/include/CosNotifyChannelAdmin_StructuredProxyPullConsumer.hrl
-/cosNotification/include/CosNotifyChannelAdmin_StructuredProxyPullSupplier.hrl
-/cosNotification/include/CosNotifyChannelAdmin_StructuredProxyPushConsumer.hrl
-/cosNotification/include/CosNotifyChannelAdmin_StructuredProxyPushSupplier.hrl
-/cosNotification/include/CosNotifyChannelAdmin_SupplierAdmin.hrl
-/cosNotification/include/CosNotifyComm.hrl
-/cosNotification/include/CosNotifyComm_NotifyPublish.hrl
-/cosNotification/include/CosNotifyComm_NotifySubscribe.hrl
-/cosNotification/include/CosNotifyComm_PullConsumer.hrl
-/cosNotification/include/CosNotifyComm_PullSupplier.hrl
-/cosNotification/include/CosNotifyComm_PushConsumer.hrl
-/cosNotification/include/CosNotifyComm_PushSupplier.hrl
-/cosNotification/include/CosNotifyComm_SequencePullConsumer.hrl
-/cosNotification/include/CosNotifyComm_SequencePullSupplier.hrl
-/cosNotification/include/CosNotifyComm_SequencePushConsumer.hrl
-/cosNotification/include/CosNotifyComm_SequencePushSupplier.hrl
-/cosNotification/include/CosNotifyComm_StructuredPullConsumer.hrl
-/cosNotification/include/CosNotifyComm_StructuredPullSupplier.hrl
-/cosNotification/include/CosNotifyComm_StructuredPushConsumer.hrl
-/cosNotification/include/CosNotifyComm_StructuredPushSupplier.hrl
-/cosNotification/include/CosNotifyFilter.hrl
-/cosNotification/include/CosNotifyFilter_Filter.hrl
-/cosNotification/include/CosNotifyFilter_FilterAdmin.hrl
-/cosNotification/include/CosNotifyFilter_FilterFactory.hrl
-/cosNotification/include/CosNotifyFilter_MappingFilter.hrl
-/cosNotification/include/oe_CosNotification.hrl
-/cosNotification/include/oe_CosNotifyChannelAdmin.hrl
-/cosNotification/include/oe_CosNotifyComm.hrl
-/cosNotification/include/oe_CosNotifyFilter.hrl
-/cosNotification/src/CosNotification.erl
-/cosNotification/src/CosNotification_AdminPropertiesAdmin.erl
-/cosNotification/src/CosNotification_EventBatch.erl
-/cosNotification/src/CosNotification_EventHeader.erl
-/cosNotification/src/CosNotification_EventType.erl
-/cosNotification/src/CosNotification_EventTypeSeq.erl
-/cosNotification/src/CosNotification_FixedEventHeader.erl
-/cosNotification/src/CosNotification_NamedPropertyRange.erl
-/cosNotification/src/CosNotification_NamedPropertyRangeSeq.erl
-/cosNotification/src/CosNotification_Property.erl
-/cosNotification/src/CosNotification_PropertyError.erl
-/cosNotification/src/CosNotification_PropertyErrorSeq.erl
-/cosNotification/src/CosNotification_PropertyRange.erl
-/cosNotification/src/CosNotification_PropertySeq.erl
-/cosNotification/src/CosNotification_QoSAdmin.erl
-/cosNotification/src/CosNotification_StructuredEvent.erl
-/cosNotification/src/CosNotification_UnsupportedAdmin.erl
-/cosNotification/src/CosNotification_UnsupportedQoS.erl
-/cosNotification/src/CosNotifyChannelAdmin_AdminIDSeq.erl
-/cosNotification/src/CosNotifyChannelAdmin_AdminLimit.erl
-/cosNotification/src/CosNotifyChannelAdmin_AdminLimitExceeded.erl
-/cosNotification/src/CosNotifyChannelAdmin_AdminNotFound.erl
-/cosNotification/src/CosNotifyChannelAdmin_ChannelIDSeq.erl
-/cosNotification/src/CosNotifyChannelAdmin_ChannelNotFound.erl
-/cosNotification/src/CosNotifyChannelAdmin_ConnectionAlreadyActive.erl
-/cosNotification/src/CosNotifyChannelAdmin_ConnectionAlreadyInactive.erl
-/cosNotification/src/CosNotifyChannelAdmin_ConsumerAdmin.erl
-/cosNotification/src/CosNotifyChannelAdmin_EventChannel.erl
-/cosNotification/src/CosNotifyChannelAdmin_EventChannelFactory.erl
-/cosNotification/src/CosNotifyChannelAdmin_NotConnected.erl
-/cosNotification/src/CosNotifyChannelAdmin_ProxyConsumer.erl
-/cosNotification/src/CosNotifyChannelAdmin_ProxyIDSeq.erl
-/cosNotification/src/CosNotifyChannelAdmin_ProxyNotFound.erl
-/cosNotification/src/CosNotifyChannelAdmin_ProxyPullConsumer.erl
-/cosNotification/src/CosNotifyChannelAdmin_ProxyPullSupplier.erl
-/cosNotification/src/CosNotifyChannelAdmin_ProxyPushConsumer.erl
-/cosNotification/src/CosNotifyChannelAdmin_ProxyPushSupplier.erl
-/cosNotification/src/CosNotifyChannelAdmin_ProxySupplier.erl
-/cosNotification/src/CosNotifyChannelAdmin_SequenceProxyPullConsumer.erl
-/cosNotification/src/CosNotifyChannelAdmin_SequenceProxyPullSupplier.erl
-/cosNotification/src/CosNotifyChannelAdmin_SequenceProxyPushConsumer.erl
-/cosNotification/src/CosNotifyChannelAdmin_SequenceProxyPushSupplier.erl
-/cosNotification/src/CosNotifyChannelAdmin_StructuredProxyPullConsumer.erl
-/cosNotification/src/CosNotifyChannelAdmin_StructuredProxyPullSupplier.erl
-/cosNotification/src/CosNotifyChannelAdmin_StructuredProxyPushConsumer.erl
-/cosNotification/src/CosNotifyChannelAdmin_StructuredProxyPushSupplier.erl
-/cosNotification/src/CosNotifyChannelAdmin_SupplierAdmin.erl
-/cosNotification/src/CosNotifyComm_InvalidEventType.erl
-/cosNotification/src/CosNotifyComm_NotifyPublish.erl
-/cosNotification/src/CosNotifyComm_NotifySubscribe.erl
-/cosNotification/src/CosNotifyComm_PullConsumer.erl
-/cosNotification/src/CosNotifyComm_PullSupplier.erl
-/cosNotification/src/CosNotifyComm_PushConsumer.erl
-/cosNotification/src/CosNotifyComm_PushSupplier.erl
-/cosNotification/src/CosNotifyComm_SequencePullConsumer.erl
-/cosNotification/src/CosNotifyComm_SequencePullSupplier.erl
-/cosNotification/src/CosNotifyComm_SequencePushConsumer.erl
-/cosNotification/src/CosNotifyComm_SequencePushSupplier.erl
-/cosNotification/src/CosNotifyComm_StructuredPullConsumer.erl
-/cosNotification/src/CosNotifyComm_StructuredPullSupplier.erl
-/cosNotification/src/CosNotifyComm_StructuredPushConsumer.erl
-/cosNotification/src/CosNotifyComm_StructuredPushSupplier.erl
-/cosNotification/src/CosNotifyFilter_CallbackIDSeq.erl
-/cosNotification/src/CosNotifyFilter_CallbackNotFound.erl
-/cosNotification/src/CosNotifyFilter_ConstraintExp.erl
-/cosNotification/src/CosNotifyFilter_ConstraintExpSeq.erl
-/cosNotification/src/CosNotifyFilter_ConstraintIDSeq.erl
-/cosNotification/src/CosNotifyFilter_ConstraintInfo.erl
-/cosNotification/src/CosNotifyFilter_ConstraintInfoSeq.erl
-/cosNotification/src/CosNotifyFilter_ConstraintNotFound.erl
-/cosNotification/src/CosNotifyFilter_DuplicateConstraintID.erl
-/cosNotification/src/CosNotifyFilter_Filter.erl
-/cosNotification/src/CosNotifyFilter_FilterAdmin.erl
-/cosNotification/src/CosNotifyFilter_FilterFactory.erl
-/cosNotification/src/CosNotifyFilter_FilterIDSeq.erl
-/cosNotification/src/CosNotifyFilter_FilterNotFound.erl
-/cosNotification/src/CosNotifyFilter_InvalidConstraint.erl
-/cosNotification/src/CosNotifyFilter_InvalidGrammar.erl
-/cosNotification/src/CosNotifyFilter_InvalidValue.erl
-/cosNotification/src/CosNotifyFilter_MappingConstraintInfo.erl
-/cosNotification/src/CosNotifyFilter_MappingConstraintInfoSeq.erl
-/cosNotification/src/CosNotifyFilter_MappingConstraintPair.erl
-/cosNotification/src/CosNotifyFilter_MappingConstraintPairSeq.erl
-/cosNotification/src/CosNotifyFilter_MappingFilter.erl
-/cosNotification/src/CosNotifyFilter_UnsupportedFilterableData.erl
-/cosNotification/src/cosNotification_Grammar.erl
-/cosNotification/src/oe_CosNotification.erl
-/cosNotification/src/oe_CosNotificationComm.hrl
-/cosNotification/src/oe_CosNotificationComm_Event.erl
-/cosNotification/src/oe_CosNotificationComm_Event.hrl
-/cosNotification/src/oe_CosNotifyChannelAdmin.erl
-/cosNotification/src/oe_CosNotifyComm.erl
-/cosNotification/src/oe_CosNotifyFilter.erl
-/cosNotification/src/oe_cosNotificationAppComm.erl
-/cosNotification/src/oe_cosNotificationAppComm.hrl
-/cosProperty/include/CosPropertyService.hrl
-/cosProperty/include/CosPropertyService_PropertiesIterator.hrl
-/cosProperty/include/CosPropertyService_PropertyNamesIterator.hrl
-/cosProperty/include/CosPropertyService_PropertySet.hrl
-/cosProperty/include/CosPropertyService_PropertySetDef.hrl
-/cosProperty/include/CosPropertyService_PropertySetDefFactory.hrl
-/cosProperty/include/CosPropertyService_PropertySetFactory.hrl
-/cosProperty/include/oe_CosProperty.hrl
-/cosProperty/src/CosPropertyService_ConflictingProperty.erl
-/cosProperty/src/CosPropertyService_ConstraintNotSupported.erl
-/cosProperty/src/CosPropertyService_FixedProperty.erl
-/cosProperty/src/CosPropertyService_InvalidPropertyName.erl
-/cosProperty/src/CosPropertyService_MultipleExceptions.erl
-/cosProperty/src/CosPropertyService_Properties.erl
-/cosProperty/src/CosPropertyService_PropertiesIterator.erl
-/cosProperty/src/CosPropertyService_Property.erl
-/cosProperty/src/CosPropertyService_PropertyDef.erl
-/cosProperty/src/CosPropertyService_PropertyDefs.erl
-/cosProperty/src/CosPropertyService_PropertyException.erl
-/cosProperty/src/CosPropertyService_PropertyExceptions.erl
-/cosProperty/src/CosPropertyService_PropertyMode.erl
-/cosProperty/src/CosPropertyService_PropertyModes.erl
-/cosProperty/src/CosPropertyService_PropertyNames.erl
-/cosProperty/src/CosPropertyService_PropertyNamesIterator.erl
-/cosProperty/src/CosPropertyService_PropertyNotFound.erl
-/cosProperty/src/CosPropertyService_PropertySet.erl
-/cosProperty/src/CosPropertyService_PropertySetDef.erl
-/cosProperty/src/CosPropertyService_PropertySetDefFactory.erl
-/cosProperty/src/CosPropertyService_PropertySetFactory.erl
-/cosProperty/src/CosPropertyService_PropertyTypes.erl
-/cosProperty/src/CosPropertyService_ReadOnlyProperty.erl
-/cosProperty/src/CosPropertyService_UnsupportedMode.erl
-/cosProperty/src/CosPropertyService_UnsupportedProperty.erl
-/cosProperty/src/CosPropertyService_UnsupportedTypeCode.erl
-/cosProperty/src/oe_CosProperty.erl
-/cosTime/include/CosTime.hrl
-/cosTime/include/CosTime_TIO.hrl
-/cosTime/include/CosTime_TimeService.hrl
-/cosTime/include/CosTime_UTO.hrl
-/cosTime/include/CosTimerEvent.hrl
-/cosTime/include/CosTimerEvent_TimerEventHandler.hrl
-/cosTime/include/CosTimerEvent_TimerEventService.hrl
-/cosTime/include/TimeBase.hrl
-/cosTime/include/oe_CosTime.hrl
-/cosTime/include/oe_CosTimerEvent.hrl
-/cosTime/include/oe_TimeBase.hrl
-/cosTime/src/CosTime_TIO.erl
-/cosTime/src/CosTime_TimeService.erl
-/cosTime/src/CosTime_TimeUnavailable.erl
-/cosTime/src/CosTime_UTO.erl
-/cosTime/src/CosTimerEvent_TimerEventHandler.erl
-/cosTime/src/CosTimerEvent_TimerEventService.erl
-/cosTime/src/CosTimerEvent_TimerEventT.erl
-/cosTime/src/TimeBase_IntervalT.erl
-/cosTime/src/TimeBase_UtcT.erl
-/cosTime/src/oe_CosTime.erl
-/cosTime/src/oe_CosTimerEvent.erl
-/cosTime/src/oe_TimeBase.erl
-/cosTransactions/include/CosTransactions.hrl
-/cosTransactions/include/CosTransactions_Control.hrl
-/cosTransactions/include/CosTransactions_Coordinator.hrl
-/cosTransactions/include/CosTransactions_RecoveryCoordinator.hrl
-/cosTransactions/include/CosTransactions_Resource.hrl
-/cosTransactions/include/CosTransactions_SubtransactionAwareResource.hrl
-/cosTransactions/include/CosTransactions_Terminator.hrl
-/cosTransactions/include/CosTransactions_TransactionFactory.hrl
-/cosTransactions/include/ETraP.hrl
-/cosTransactions/include/ETraP_Server.hrl
-/cosTransactions/include/oe_CosTransactions.hrl
-/cosTransactions/src/CosTransactions_Control.erl
-/cosTransactions/src/CosTransactions_Coordinator.erl
-/cosTransactions/src/CosTransactions_HeuristicCommit.erl
-/cosTransactions/src/CosTransactions_HeuristicHazard.erl
-/cosTransactions/src/CosTransactions_HeuristicMixed.erl
-/cosTransactions/src/CosTransactions_HeuristicRollback.erl
-/cosTransactions/src/CosTransactions_Inactive.erl
-/cosTransactions/src/CosTransactions_InvalidControl.erl
-/cosTransactions/src/CosTransactions_NoTransaction.erl
-/cosTransactions/src/CosTransactions_NotPrepared.erl
-/cosTransactions/src/CosTransactions_NotSubtransaction.erl
-/cosTransactions/src/CosTransactions_PropagationContext.erl
-/cosTransactions/src/CosTransactions_RecoveryCoordinator.erl
-/cosTransactions/src/CosTransactions_Resource.erl
-/cosTransactions/src/CosTransactions_SubtransactionAwareResource.erl
-/cosTransactions/src/CosTransactions_SubtransactionsUnavailable.erl
-/cosTransactions/src/CosTransactions_SynchronizationUnavailable.erl
-/cosTransactions/src/CosTransactions_Terminator.erl
-/cosTransactions/src/CosTransactions_TransIdentity.erl
-/cosTransactions/src/CosTransactions_TransactionFactory.erl
-/cosTransactions/src/CosTransactions_Unavailable.erl
-/cosTransactions/src/CosTransactions_WrongTransaction.erl
-/cosTransactions/src/CosTransactions_otid_t.erl
-/cosTransactions/src/ETraP_Server.erl
-/cosTransactions/src/oe_CosTransactions.erl
-/orber/COSS/CosNaming/CosNaming.hrl
-/orber/COSS/CosNaming/CosNaming_Binding.erl
-/orber/COSS/CosNaming/CosNaming_BindingIterator.erl
-/orber/COSS/CosNaming/CosNaming_BindingIterator.hrl
-/orber/COSS/CosNaming/CosNaming_BindingList.erl
-/orber/COSS/CosNaming/CosNaming_Name.erl
-/orber/COSS/CosNaming/CosNaming_NameComponent.erl
-/orber/COSS/CosNaming/CosNaming_NamingContext.erl
-/orber/COSS/CosNaming/CosNaming_NamingContext.hrl
-/orber/COSS/CosNaming/CosNaming_NamingContextExt.erl
-/orber/COSS/CosNaming/CosNaming_NamingContextExt.hrl
-/orber/COSS/CosNaming/CosNaming_NamingContextExt_AlreadyBound.erl
-/orber/COSS/CosNaming/CosNaming_NamingContextExt_CannotProceed.erl
-/orber/COSS/CosNaming/CosNaming_NamingContextExt_InvalidAddress.erl
-/orber/COSS/CosNaming/CosNaming_NamingContextExt_InvalidName.erl
-/orber/COSS/CosNaming/CosNaming_NamingContextExt_NotEmpty.erl
-/orber/COSS/CosNaming/CosNaming_NamingContextExt_NotFound.erl
-/orber/COSS/CosNaming/CosNaming_NamingContext_AlreadyBound.erl
-/orber/COSS/CosNaming/CosNaming_NamingContext_CannotProceed.erl
-/orber/COSS/CosNaming/CosNaming_NamingContext_InvalidName.erl
-/orber/COSS/CosNaming/CosNaming_NamingContext_NotEmpty.erl
-/orber/COSS/CosNaming/CosNaming_NamingContext_NotFound.erl
-/orber/COSS/CosNaming/oe_cos_naming.erl
-/orber/COSS/CosNaming/oe_cos_naming.hrl
-/orber/COSS/CosNaming/oe_cos_naming_ext.erl
-/orber/COSS/CosNaming/oe_cos_naming_ext.hrl
-/orber/examples/Stack/StackModule.hrl
-/orber/examples/Stack/StackModule_EmptyStack.erl
-/orber/examples/Stack/StackModule_Stack.erl
-/orber/examples/Stack/StackModule_Stack.hrl
-/orber/examples/Stack/StackModule_StackFactory.erl
-/orber/examples/Stack/StackModule_StackFactory.hrl
-/orber/examples/Stack/oe_stack.erl
-/orber/examples/Stack/oe_stack.hrl
-/orber/src/CORBA.hrl
-/orber/src/OrberApp.hrl
-/orber/src/OrberApp_IFR.erl
-/orber/src/OrberApp_IFR.hrl
-/orber/src/erlang.hrl
-/orber/src/erlang_binary.erl
-/orber/src/erlang_pid.erl
-/orber/src/erlang_port.erl
-/orber/src/erlang_ref.erl
-/orber/src/oe_CORBA.erl
-/orber/src/oe_CORBA.hrl
-/orber/src/oe_OrberIFR.erl
-/orber/src/oe_OrberIFR.hrl
-/orber/src/oe_erlang.erl
-/orber/src/oe_erlang.hrl
-
-# snmp
-
-snmp/doc/intex.html
-
-# syntax_tools
-
-/syntax_tools/doc/src/chapter.xml
-/syntax_tools/doc/src/epp_dodger.xml
-/syntax_tools/doc/src/erl_comment_scan.xml
-/syntax_tools/doc/src/erl_prettypr.xml
-/syntax_tools/doc/src/erl_recomment.xml
-/syntax_tools/doc/src/erl_syntax.xml
-/syntax_tools/doc/src/erl_syntax_lib.xml
-/syntax_tools/doc/src/erl_tidy.xml
-/syntax_tools/doc/src/merl.xml
-/syntax_tools/doc/src/merl_transform.xml
-/syntax_tools/doc/src/igor.xml
-/syntax_tools/doc/src/prettypr.xml
-
-# wx
-
-/wx/doc/src/chapter.xml
-/wx/doc/src/gl.xml
-/wx/doc/src/glu.xml
-/wx/doc/src/ref_man.xml
-
-# xmerl
-
-/xmerl/doc/src/xmerl.xml
-/xmerl/doc/src/xmerl_eventp.xml
-/xmerl/doc/src/xmerl_scan.xml
-/xmerl/doc/src/xmerl_ug.xml
-/xmerl/doc/src/xmerl_xpath.xml
-/xmerl/doc/src/xmerl_xs.xml
-/xmerl/doc/src/xmerl_xsd.xml
diff --git a/lib/Makefile b/lib/Makefile
index ae466ed518..cdb3f3f3dc 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2016. All Rights Reserved.
+# Copyright Ericsson AB 1996-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -31,11 +31,10 @@ ERLANG_APPLICATIONS = tools common_test runtime_tools inets parsetools
ALL_ERLANG_APPLICATIONS = xmerl edoc erl_docgen snmp otp_mibs erl_interface \
asn1 jinterface \
wx debugger reltool \
- ic mnesia crypto orber os_mon syntax_tools \
+ mnesia crypto os_mon syntax_tools \
public_key ssl observer odbc diameter \
- cosTransactions cosEvent cosTime cosNotification \
- cosProperty cosFileTransfer cosEventDomain et megaco \
- eunit ssh eldap dialyzer hipe
+ et megaco \
+ eunit ssh eldap dialyzer hipe ftp tftp
ifdef BUILD_ALL
ERLANG_APPLICATIONS += $(ALL_ERLANG_APPLICATIONS)
@@ -59,7 +58,7 @@ else
SUB_DIRECTORIES = hipe parsetools asn1/src
else
ifdef TERTIARY_BOOTSTRAP
- SUB_DIRECTORIES = snmp sasl jinterface ic syntax_tools wx
+ SUB_DIRECTORIES = snmp sasl jinterface syntax_tools wx
else
ifdef DOC_BOOTSTRAP
SUB_DIRECTORIES = xmerl edoc erl_docgen
diff --git a/lib/asn1/c_src/asn1_erl_nif.c b/lib/asn1/c_src/asn1_erl_nif.c
index d5aaadb89b..797be6d4f8 100644
--- a/lib/asn1/c_src/asn1_erl_nif.c
+++ b/lib/asn1/c_src/asn1_erl_nif.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2017. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -949,6 +949,12 @@ static int ber_decode_value(ErlNifEnv* env, ERL_NIF_TERM *value, unsigned char *
unsigned char *tmp_out_buff;
ERL_NIF_TERM term = 0, curr_head = 0;
+ /* Recursion depth limitation, borrow a signed int: maybe_ret */
+ maybe_ret = (int) (ErlNifSInt) ((char *)value - (char *)ib_index);
+ maybe_ret = maybe_ret < 0 ? -maybe_ret : maybe_ret;
+ if (maybe_ret >= sizeof(void *) * 8192) /* 8 k pointer words */
+ return ASN1_ERROR;
+
if (((in_buf[*ib_index]) & 0x80) == ASN1_SHORT_DEFINITE_LENGTH) {
len = in_buf[*ib_index];
} else if (in_buf[*ib_index] == ASN1_INDEFINITE_LENGTH) {
@@ -993,7 +999,7 @@ static int ber_decode_value(ErlNifEnv* env, ERL_NIF_TERM *value, unsigned char *
while (*ib_index < end_index) {
if ((maybe_ret = ber_decode(env, &term, in_buf, ib_index,
- in_buf_len)) <= ASN1_ERROR
+ *ib_index + len)) <= ASN1_ERROR
)
return maybe_ret;
curr_head = enif_make_list_cell(env, term, curr_head);
diff --git a/lib/asn1/doc/src/Makefile b/lib/asn1/doc/src/Makefile
index 9a388e4e8a..9c0d865884 100644
--- a/lib/asn1/doc/src/Makefile
+++ b/lib/asn1/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -51,13 +51,14 @@ XML_CHAPTER_FILES = \
asn1_introduction.xml \
asn1_getting_started.xml \
asn1_overview.xml \
- asn1_spec.xml \
notes.xml
BOOK_FILES = book.xml
XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \
- $(GEN_XML) $(XML_PART_FILES) $(XML_CHAPTER_FILES)
+ $(XML_PART_FILES) $(XML_CHAPTER_FILES)
+
+XML_GEN_FILES = $(GEN_XML:%=$(XMLDIR)/%)
GIF_FILES = \
exclusive_Win_But.gif \
@@ -75,7 +76,8 @@ EXTRA_FILES = \
$(DEFAULT_HTML_FILES) \
$(ASN1_FILES) \
$(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html)
+ $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html) \
+ $(GEN_XML:%.xml=$(HTMLDIR)/%.html) \
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
@@ -105,6 +107,7 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(GEN_XML) errs core *~
diff --git a/lib/asn1/doc/src/fascicules.xml b/lib/asn1/doc/src/fascicules.xml
deleted file mode 100644
index 837b4f57f4..0000000000
--- a/lib/asn1/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml
index 26640acabc..086b5f38c6 100644
--- a/lib/asn1/doc/src/notes.xml
+++ b/lib/asn1/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,159 @@
<p>This document describes the changes made to the asn1 application.</p>
+<section><title>Asn1 5.0.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>A bug in ASN.1 BER decoding has been fixed. When
+ decoding a recursively enclosed term the length was not
+ propagated to that term decoding, so if the length of the
+ enclosed term was longer than the enclosing that error
+ was not detected.</p> <p>A hard coded C stack limitation
+ for decoding recursive ASN.1 terms has been introduced.
+ This is currently set to 8 kWords giving a nesting depth
+ of about 1000 levels. Deeper terms can not be decoded,
+ which should not be much of a real world limitation.</p>
+ <p>
+ Own Id: OTP-14440 Aux Id: ERIERL-220 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 5.0.6</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Update to use the new string api instead of the old.</p>
+ <p>
+ Own Id: OTP-15036</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 5.0.5.1</title>
+
+ <section><title>Known Bugs and Problems</title>
+ <list>
+ <item>
+ <p>A bug in ASN.1 BER decoding has been fixed. When
+ decoding a recursively enclosed term the length was not
+ propagated to that term decoding, so if the length of the
+ enclosed term was longer than the enclosing that error
+ was not dectected</p> <p>A hard coded C stack limitation
+ for decoding recursive ASN.1 terms has been introduced.
+ This is currently set to 8 kWords giving a nesting depth
+ of about 1000 levels. Deeper terms can not be decoded,
+ which should not be much of a real world limitation.</p>
+ <p>
+ Own Id: OTP-14440 Aux Id: ERIERL-220 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 5.0.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Dialyzer suppression has been added for the generated
+ ASN.1 helper function to_bitstring/1 that previously
+ created irrelevant warnings.</p>
+ <p>
+ Own Id: OTP-13882 Aux Id: ERIERL-144 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 5.0.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ There was a issue with BER encoding and the
+ <c>undec_rest</c> option in generated decoders. An
+ exception could be thrown instead of returning an error
+ tuple.</p>
+ <p>
+ Own Id: OTP-14786 Aux Id: ERL-518 </p>
+ </item>
+ <item>
+ <p>
+ The asn1ct:test functions crashed on decoders generated
+ with options <c>no_ok_wrapper</c>, <c>undec_rest</c>.</p>
+ <p>
+ Own Id: OTP-14787 Aux Id: ERL-518 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 5.0.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Compiling an ASN.1 module using the option {n2n,
+ EnumTypeName} when EnumTypeName contains a hypen like for
+ example Cause-Misc caused syntax errors when compiling
+ the generated Erlang code. This is now corrected.</p>
+ <p>
+ Own Id: OTP-14495 Aux Id: ERL-437 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 5.0.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Default values now work in extension for PER, so if you
+ give the atom <c>asn1_DEFAULT</c> instead of a value it
+ will become the default value.</p>
+ <p>
+ Own Id: OTP-13011 Aux Id: ERIERL-60 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 5.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed compilation error of generated code caused by a
+ missing quotation of function names as part of an
+ external call for encoding.</p>
+ <p>
+ Own Id: OTP-14519 Aux Id: ERIERL-49 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Asn1 5.0</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl
index f36d71a601..cd50d30aa8 100644
--- a/lib/asn1/src/asn1ct.erl
+++ b/lib/asn1/src/asn1ct.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -292,8 +292,7 @@ run_passes_1([{pass,Name,Pass}|Passes], #st{run=Run}=St0)
done ->
ok
catch
- Class:Error ->
- Stk = erlang:get_stacktrace(),
+ Class:Error:Stk ->
io:format("Internal error: ~p:~p\n~p\n",
[Class,Error,Stk]),
{error,{internal_error,{Class,Error}}}
@@ -1335,25 +1334,39 @@ test_value(Module, Type, Value) ->
in_process(fun() ->
case catch Module:encode(Type, Value) of
{ok, Bytes} ->
- NewBytes = prepare_bytes(Bytes),
- case Module:decode(Type, NewBytes) of
- {ok, Value} ->
- {ok, {Module, Type, Value}};
- {ok, Res} ->
- {error, {asn1,
- {encode_decode_mismatch,
- {{Module, Type, Value}, Res}}}};
- Error ->
- {error, {asn1,
- {{decode,
- {Module, Type, Value}, Error}}}}
- end;
+ test_value_decode(Module, Type, Value, Bytes);
+ Bytes when is_binary(Bytes) ->
+ test_value_decode(Module, Type, Value, Bytes);
Error ->
{error, {asn1,
{encode, {{Module, Type, Value}, Error}}}}
end
end).
+
+test_value_decode(Module, Type, Value, Bytes) ->
+ NewBytes = prepare_bytes(Bytes),
+ case Module:decode(Type, NewBytes) of
+ {ok,Value} -> {ok, {Module,Type,Value}};
+ {ok,Value,<<>>} -> {ok, {Module,Type,Value}};
+ Value -> {ok, {Module,Type,Value}};
+ {Value,<<>>} -> {ok, {Module,Type,Value}};
+
+ %% Errors:
+ {ok, Res} ->
+ {error, {asn1,
+ {encode_decode_mismatch,
+ {{Module, Type, Value}, Res}}}};
+ {ok, Res, Rest} ->
+ {error, {asn1,
+ {encode_decode_mismatch,
+ {{Module, Type, Value}, {Res,Rest}}}}};
+ Error ->
+ {error, {asn1,
+ {{decode,
+ {Module, Type, Value}, Error}}}}
+ end.
+
value(Module, Type) -> value(Module, Type, []).
value(Module, Type, Includes) ->
@@ -2376,13 +2389,13 @@ in_process(Fun) ->
receive
{Pid, Result} -> Result;
{Pid, Class, Reason, Stack} ->
- ST = try throw(x) catch throw:x -> erlang:get_stacktrace() end,
+ ST = try throw(x) catch throw:x:Stk -> Stk end,
erlang:raise(Class, Reason, Stack ++ ST)
end.
process(Parent, Fun) ->
try
Parent ! {self(), Fun()}
- catch Class:Reason ->
- Parent ! {self(), Class, Reason, erlang:get_stacktrace()}
+ catch Class:Reason:Stack ->
+ Parent ! {self(), Class, Reason, Stack}
end.
diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl
index 83d12600b7..321980e5e4 100644
--- a/lib/asn1/src/asn1ct_check.erl
+++ b/lib/asn1/src/asn1ct_check.erl
@@ -1576,13 +1576,15 @@ printable_string_1(#'Externalvaluereference'{value=Type}) ->
printable_string_1({Atom,Line}) when is_atom(Atom), is_integer(Line) ->
q(Atom);
printable_string_1({object,definedsyntax,L}) ->
- q(string:join([printable_string_1(Item) || Item <- L], " "));
+ Str = lists:join($\s, [printable_string_1(Item) || Item <- L]),
+ q(lists:flatten(Str));
printable_string_1([_|_]=Def) ->
case lists:all(fun is_integer/1, Def) of
true ->
lists:flatten(io_lib:format("~p", [Def]));
false ->
- q(string:join([printable_string_1(Item) || Item <- Def], " "))
+ Str = lists:join($\s, [printable_string_1(Item) || Item <- Def]),
+ q(lists:flatten(Str))
end;
printable_string_1(Def) ->
lists:flatten(io_lib:format("~p", [Def])).
diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl
index 3f1be4febb..aff383479b 100644
--- a/lib/asn1/src/asn1ct_constructed_per.erl
+++ b/lib/asn1/src/asn1ct_constructed_per.erl
@@ -985,9 +985,11 @@ gen_enc_components_call1(Gen, TopType, [C|Rest], DynamicEnc, Ext) ->
Imm1;
'OPTIONAL' ->
enc_absent(Gen, Element, [asn1_NOVALUE], Imm1);
- {'DEFAULT',Def} ->
+ {'DEFAULT',Def} when Ext =:= noext ->
DefValues = def_values(Type, Def),
- enc_absent(Gen, Element, DefValues, Imm1)
+ enc_absent(Gen, Element, DefValues, Imm1);
+ {'DEFAULT',_} ->
+ enc_absent(Gen, Element, [asn1_DEFAULT], Imm1)
end,
Imm = case Imm2 of
[] -> [];
diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl
index 838d59a512..28836ff264 100644
--- a/lib/asn1/src/asn1ct_gen.erl
+++ b/lib/asn1/src/asn1ct_gen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -145,27 +145,37 @@ pgen_n2nconversion(_Erules,#typedef{name=TypeName,typespec=#type{def={'ENUMERATE
pgen_n2nconversion(_Erules,_) ->
true.
-pgen_name2numfunc(_TypeName,[], _) ->
+pgen_name2numfunc(TypeNameAsAtom,Mapping,Ext) when is_atom(TypeNameAsAtom) ->
+ FuncName = list_to_atom("name2num_"++atom_to_list(TypeNameAsAtom)),
+ pgen_name2numfunc1(FuncName,Mapping,Ext).
+
+pgen_name2numfunc1(_FuncName,[], _) ->
true;
-pgen_name2numfunc(TypeName,[{Atom,Number}], extension_marker) ->
- emit(["name2num_",TypeName,"(",{asis,Atom},") ->",Number,";",nl]),
- emit(["name2num_",TypeName,"({asn1_enum, Num}) -> Num.",nl,nl]);
-pgen_name2numfunc(TypeName,[{Atom,Number}], _) ->
- emit(["name2num_",TypeName,"(",{asis,Atom},") ->",Number,".",nl,nl]);
-pgen_name2numfunc(TypeName,[{Atom,Number}|NNRest], EM) ->
- emit(["name2num_",TypeName,"(",{asis,Atom},") ->",Number,";",nl]),
- pgen_name2numfunc(TypeName,NNRest, EM).
-
-pgen_num2namefunc(_TypeName,[], _) ->
+pgen_name2numfunc1(FuncName,[{Atom,Number}], extension_marker) ->
+ emit([{asis,FuncName},"(",{asis,Atom},") ->",Number,";",nl]),
+ emit([{asis,FuncName},"({asn1_enum, Num}) -> Num.",nl,nl]);
+pgen_name2numfunc1(FuncName,[{Atom,Number}], _) ->
+ emit([{asis,FuncName},"(",{asis,Atom},") ->",Number,".",nl,nl]);
+pgen_name2numfunc1(FuncName,[{Atom,Number}|NNRest], EM) ->
+ emit([{asis,FuncName},"(",{asis,Atom},") ->",Number,";",nl]),
+ pgen_name2numfunc1(FuncName,NNRest, EM).
+
+pgen_num2namefunc(TypeNameAsAtom,Mapping,Ext) when is_atom(TypeNameAsAtom) ->
+ FuncName = list_to_atom("num2name_"++atom_to_list(TypeNameAsAtom)),
+ pgen_num2namefunc1(FuncName,Mapping,Ext).
+
+pgen_num2namefunc1(_FuncName,[], _) ->
true;
-pgen_num2namefunc(TypeName,[{Atom,Number}], extension_marker) ->
- emit(["num2name_",TypeName,"(",Number,") ->",{asis,Atom},";",nl]),
- emit(["num2name_",TypeName,"(ExtensionNum) -> {asn1_enum, ExtensionNum}.",nl,nl]);
-pgen_num2namefunc(TypeName,[{Atom,Number}], _) ->
- emit(["num2name_",TypeName,"(",Number,") ->",{asis,Atom},".",nl,nl]);
-pgen_num2namefunc(TypeName,[{Atom,Number}|NNRest], EM) ->
- emit(["num2name_",TypeName,"(",Number,") ->",{asis,Atom},";",nl]),
- pgen_num2namefunc(TypeName,NNRest, EM).
+pgen_num2namefunc1(FuncName,[{Atom,Number}], extension_marker) ->
+ emit([{asis,FuncName},"(",Number,") ->",{asis,Atom},";",nl]),
+ emit([{asis,FuncName},"(ExtensionNum) -> {asn1_enum, ExtensionNum}.",nl,nl]);
+pgen_num2namefunc1(FuncName,[{Atom,Number}], _) ->
+ emit([{asis,FuncName},"(",Number,") ->",{asis,Atom},".",nl,nl]);
+pgen_num2namefunc1(FuncName,[{Atom,Number}|NNRest], EM) ->
+ emit([{asis,FuncName},"(",Number,") ->",{asis,Atom},";",nl]),
+ pgen_num2namefunc1(FuncName,NNRest, EM).
+
+
pgen_objects(_,_,_,[]) ->
true;
@@ -697,6 +707,7 @@ gen_exports([_|_]=L0, Prefix, Arity) ->
pgen_dispatcher(Erules, []) ->
gen_info_functions(Erules);
pgen_dispatcher(Gen, Types) ->
+ %% MODULE HEAD
emit(["-export([encode/2,decode/2]).",nl,nl]),
gen_info_functions(Gen),
@@ -704,6 +715,7 @@ pgen_dispatcher(Gen, Types) ->
NoFinalPadding = lists:member(no_final_padding, Options),
NoOkWrapper = proplists:get_bool(no_ok_wrapper, Options),
+ %% ENCODER
Call = case Gen of
#gen{erule=per,aligned=true} ->
asn1ct_func:need({per,complete,1}),
@@ -730,6 +742,7 @@ pgen_dispatcher(Gen, Types) ->
end,
emit([nl,nl]),
+ %% DECODER
ReturnRest = proplists:get_bool(undec_rest, Gen#gen.options),
Data = case Gen#gen.erule =:= ber andalso ReturnRest of
true -> "Data0";
@@ -737,6 +750,12 @@ pgen_dispatcher(Gen, Types) ->
end,
emit(["decode(Type, ",Data,") ->",nl]),
+
+ case NoOkWrapper of
+ false -> emit(["try",nl]);
+ true -> ok
+ end,
+
DecWrap =
case {Gen,ReturnRest} of
{#gen{erule=ber},false} ->
@@ -744,32 +763,38 @@ pgen_dispatcher(Gen, Types) ->
"element(1, ber_decode_nif(Data))";
{#gen{erule=ber},true} ->
asn1ct_func:need({ber,ber_decode_nif,1}),
- emit(["{Data,Rest} = ber_decode_nif(Data0),",nl]),
+ emit([" {Data,Rest} = ber_decode_nif(Data0),",nl]),
"Data";
{_,_} ->
"Data"
end,
- emit([case NoOkWrapper of
- false -> "try";
- true -> "case"
- end, " decode_disp(Type, ",DecWrap,") of",nl]),
- case Gen of
- #gen{erule=ber} ->
- emit([" Result ->",nl]);
- #gen{erule=per} ->
- emit([" {Result,Rest} ->",nl])
- end,
- case ReturnRest of
- false -> result_line(NoOkWrapper, ["Result"]);
- true -> result_line(NoOkWrapper, ["Result","Rest"])
+
+ DecodeDisp = ["decode_disp(Type, ",DecWrap,")"],
+ case {Gen,ReturnRest} of
+ {#gen{erule=ber},true} ->
+ emit([" Result = ",DecodeDisp,",",nl]),
+ result_line(NoOkWrapper, ["Result","Rest"]);
+ {#gen{erule=ber},false} ->
+ emit([" Result = ",DecodeDisp,",",nl]),
+ result_line(NoOkWrapper, ["Result"]);
+
+
+ {#gen{erule=per},true} ->
+ emit([" {Result,Rest} = ",DecodeDisp,",",nl]),
+ result_line(NoOkWrapper, ["Result","Rest"]);
+ {#gen{erule=per},false} ->
+ emit([" {Result,_Rest} = ",DecodeDisp,",",nl]),
+ result_line(NoOkWrapper, ["Result"])
end,
+
case NoOkWrapper of
false ->
emit([nl,try_catch(),nl,nl]);
true ->
- emit([nl,"end.",nl,nl])
+ emit([".",nl,nl])
end,
+ %% REST of MODULE
gen_decode_partial_incomplete(Gen),
gen_partial_inc_dispatcher(Gen),
@@ -777,7 +802,7 @@ pgen_dispatcher(Gen, Types) ->
gen_dispatcher(Types, "decode_disp", "dec_").
result_line(NoOkWrapper, Items) ->
- S = [" "|case NoOkWrapper of
+ S = [" "|case NoOkWrapper of
false -> result_line_1(["ok"|Items]);
true -> result_line_1(Items)
end],
@@ -786,12 +811,11 @@ result_line(NoOkWrapper, Items) ->
result_line_1([SingleItem]) ->
SingleItem;
result_line_1(Items) ->
- ["{",string:join(Items, ","),"}"].
+ ["{",lists:join(",",Items),"}"].
try_catch() ->
[" catch",nl,
- " Class:Exception when Class =:= error; Class =:= exit ->",nl,
- " Stk = erlang:get_stacktrace(),",nl,
+ " Class:Exception:Stk when Class =:= error; Class =:= exit ->",nl,
" case Exception of",nl,
" {error,{asn1,Reason}} ->",nl,
" {error,{asn1,{Reason,Stk}}};",nl,
@@ -933,7 +957,7 @@ open_hrl(OutFile,Module) ->
hrl_protector(OutFile) ->
BaseName = filename:basename(OutFile),
- P = "_" ++ string:to_upper(BaseName) ++ "_HRL_",
+ P = "_" ++ string:uppercase(BaseName) ++ "_HRL_",
[if
$A =< C, C =< $Z -> C;
$a =< C, C =< $a -> C;
diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl
index 28b4e46b0c..c09b0f47d1 100644
--- a/lib/asn1/src/asn1ct_gen_per.erl
+++ b/lib/asn1/src/asn1ct_gen_per.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -47,14 +47,20 @@ dialyzer_suppressions(#gen{erule=per,aligned=Aligned}) ->
false -> uper;
true -> per
end,
- case asn1ct_func:is_used({Mod,complete,1}) of
+ suppress({Mod,complete,1}),
+ suppress({per_common,to_bitstring,2}),
+ emit([" ok.",nl]).
+
+suppress({M,F,A}=MFA) ->
+ case asn1ct_func:is_used(MFA) of
false ->
ok;
true ->
- emit([" _ = complete(Arg),",nl])
- end,
- emit([" ok.",nl]).
-
+ Args =
+ [lists:concat(["element(",I,", Arg)"])
+ || I <- lists:seq(1, A)],
+ emit([" ",{call,M,F,Args},com,nl])
+ end.
gen_encode(Erules,Type) when is_record(Type,typedef) ->
gen_encode_user(Erules,Type).
@@ -101,7 +107,7 @@ gen_encode_user(Erules,D) when is_record(D,typedef) ->
#'Externaltypereference'{module=CurrMod,type=Etype} ->
emit([{asis,enc_func(Etype)},"(Val).",nl]);
#'Externaltypereference'{module=Emod,type=Etype} ->
- emit([{asis,Emod},":",enc_func(Etype),"(Val).",nl])
+ emit([{asis,Emod},":",{asis,enc_func(Etype)},"(Val).",nl])
end.
diff --git a/lib/asn1/src/asn1rtt_per_common.erl b/lib/asn1/src/asn1rtt_per_common.erl
index 2ecc9e4bc7..5b5f47dfee 100644
--- a/lib/asn1/src/asn1rtt_per_common.erl
+++ b/lib/asn1/src/asn1rtt_per_common.erl
@@ -542,6 +542,7 @@ extension_bitmap(_Val, Pos, Limit, Acc) when Pos >= Limit ->
extension_bitmap(Val, Pos, Limit, Acc) ->
Bit = case element(Pos, Val) of
asn1_NOVALUE -> 0;
+ asn1_DEFAULT -> 0;
_ -> 1
end,
extension_bitmap(Val, Pos+1, Limit, (Acc bsl 1) bor Bit).
diff --git a/lib/asn1/src/asn1rtt_real_common.erl b/lib/asn1/src/asn1rtt_real_common.erl
index 3a79209015..0d53447eb7 100644
--- a/lib/asn1/src/asn1rtt_real_common.erl
+++ b/lib/asn1/src/asn1rtt_real_common.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-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.
@@ -125,7 +125,7 @@ encode_real(_C, {_,Base,_}) ->
encode_real(C, Real) when is_list(Real) ->
%% The Real string may come in as a NR1, NR2 or NR3 string.
{Mantissa, Exponent} =
- case string:tokens(Real,"Ee") of
+ case string:lexemes(Real,"Ee") of
[NR2] ->
{NR2,0};
[NR3MB,NR3E] ->
@@ -144,7 +144,7 @@ encode_real(C, Real) when is_list(Real) ->
NewMan = remove_trailing_zeros(Dec),
{NewMan,length(ZeroDecimal(NewMan))};
_ ->
- case string:tokens(Mantissa,",.") of
+ case string:lexemes(Mantissa,",.") of
[Num] -> %% No decimal-mark
{integer_to_list(list_to_integer(Num)),0};
[Num,Dec] ->
diff --git a/lib/asn1/test/Makefile b/lib/asn1/test/Makefile
index f4041fa89b..c38d1c6ebd 100644
--- a/lib/asn1/test/Makefile
+++ b/lib/asn1/test/Makefile
@@ -43,6 +43,7 @@ MODULES= \
testChoTypeRefSet \
testConstraints \
testDef \
+ testExtensionDefault \
testOpt \
testSeqDefault \
testSeqExtension \
diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl
index 5fe6945ff2..5506923341 100644
--- a/lib/asn1/test/asn1_SUITE.erl
+++ b/lib/asn1/test/asn1_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -132,7 +132,8 @@ groups() ->
testSeq2738,
% Uses 'Constructed'
{group, [], [constructed,
- ber_decode_error]},
+ ber_decode_error,
+ otp_14440]},
testSeqSetIndefinite,
testChoiceIndefinite,
per_open_type,
@@ -147,6 +148,7 @@ groups() ->
testImport,
testDER,
testDEFAULT,
+ testExtensionDefault,
testMvrasn6,
testContextSwitchingTypes,
testOpenTypeImplicitTag,
@@ -226,10 +228,9 @@ test(Config, TestF, Rules) ->
try
TestF(C, R, O)
catch
- Class:Reason ->
+ Class:Reason:Stk ->
NewReason = {Reason, [{rule, R}, {options, O}]},
- erlang:raise(Class, NewReason,
- erlang:get_stacktrace())
+ erlang:raise(Class, NewReason, Stk)
end
end,
Result = [run_case(Config, Fun, rule(Rule), opts(Rule)) || Rule <- Rules],
@@ -265,7 +266,7 @@ replace_path(PathA, PathB) ->
true = code:add_patha(PathB).
join(Rule, Opts) ->
- string:join([atom_to_list(Rule)|lists:map(fun atom_to_list/1, Opts)], "_").
+ lists:join("_", [atom_to_list(Rule)|lists:map(fun atom_to_list/1, Opts)]).
%%------------------------------------------------------------------------------
%% Test cases
@@ -444,6 +445,12 @@ testDEFAULT(Config, Rule, Opts) ->
testDef:main(Rule),
testSeqSetDefaultVal:main(Rule, Opts).
+testExtensionDefault(Config) ->
+ test(Config, fun testExtensionDefault/3).
+testExtensionDefault(Config, Rule, Opts) ->
+ asn1_test_lib:compile_all(["ExtensionDefault"], Config, [Rule|Opts]),
+ testExtensionDefault:main(Rule).
+
testMaps(Config) ->
test(Config, fun testMaps/3,
[{ber,[maps,no_ok_wrapper]},
@@ -730,6 +737,36 @@ ber_decode_error(Config, Rule, Opts) ->
asn1_test_lib:compile("Constructed", Config, [Rule|Opts]),
ber_decode_error:run(Opts).
+otp_14440(_Config) ->
+ Args = " -pa \"" ++ filename:dirname(code:which(?MODULE)) ++ "\"",
+ {ok,N} = slave:start(hostname(), otp_14440, Args),
+ Result = rpc:call(N, ?MODULE, otp_14440_decode, []),
+ io:format("Decode result = ~p~n", [Result]),
+ case Result of
+ {exit,{error,{asn1,{invalid_value,5}}}} ->
+ ok = slave:stop(N);
+ %% We get this if stack depth limit kicks in:
+ {exit,{error,{asn1,{unknown,_}}}} ->
+ ok = slave:stop(N);
+ _ ->
+ _ = slave:stop(N),
+ ?t:fail(Result)
+ end.
+%%
+otp_14440_decode() ->
+ Data =
+ iolist_to_binary(
+ lists:duplicate(
+ 32, list_to_binary(lists:duplicate(1024, 16#7f)))),
+ try asn1rt_nif:decode_ber_tlv(Data) of
+ Result ->
+ {unexpected_return,Result}
+ catch
+ Class:Reason ->
+ {Class,Reason}
+ end.
+
+
h323test(Config) -> test(Config, fun h323test/3).
h323test(Config, Rule, Opts) ->
Files = ["H235-SECURITY-MESSAGES", "H323-MESSAGES",
@@ -1198,14 +1235,14 @@ testComment(Config) ->
testName2Number(Config) ->
N2NOptions0 = [{n2n,Type} ||
- Type <- ['CauseMisc', 'CauseProtocol',
- 'CauseRadioNetwork',
- 'CauseTransport','CauseNas']],
+ Type <- ['Cause-Misc', 'CauseProtocol']],
N2NOptions = [?NO_MAPS_MODULE|N2NOptions0],
- asn1_test_lib:compile("S1AP-IEs", Config, N2NOptions),
+ asn1_test_lib:compile("EnumN2N", Config, N2NOptions),
- 0 = 'S1AP-IEs':name2num_CauseMisc('control-processing-overload'),
- 'unknown-PLMN' = 'S1AP-IEs':num2name_CauseMisc(5),
+ 0 = 'EnumN2N':'name2num_Cause-Misc'('control-processing-overload'),
+ 'unknown-PLMN' = 'EnumN2N':'num2name_Cause-Misc'(5),
+ 4 = 'EnumN2N':name2num_CauseProtocol('semantic-error'),
+ 'transfer-syntax-error' = 'EnumN2N':num2name_CauseProtocol(0),
%% OTP-10144
%% Test that n2n option generates name2num and num2name functions supporting
@@ -1344,12 +1381,12 @@ xref_export_all(_Config) ->
{ok,_} = xref:q(S, Def),
{ok,Unused} = xref:q(S, "X - Called - range (closure E | Called)"),
xref:stop(S),
- case Unused of
+ case Unused -- [{?MODULE,otp_14440_decode,0}] of
[] ->
ok;
[_|_] ->
- S = [io_lib:format("~p:~p/~p\n", [M,F,A]) || {M,F,A} <- Unused],
- io:format("There are unused functions:\n\n~s\n", [S]),
+ Msg = [io_lib:format("~p:~p/~p\n", [M,F,A]) || {M,F,A} <- Unused],
+ io:format("There are unused functions:\n\n~s\n", [Msg]),
?t:fail(unused_functions)
end.
@@ -1379,3 +1416,11 @@ all_called_1([F|T]) when is_atom(F) ->
L ++ all_called_1(T);
all_called_1([]) ->
[].
+
+hostname() ->
+ hostname(atom_to_list(node())).
+
+hostname([$@ | Hostname]) ->
+ list_to_atom(Hostname);
+hostname([_C | Cs]) ->
+ hostname(Cs).
diff --git a/lib/asn1/test/asn1_SUITE_data/EnumN2N.asn1 b/lib/asn1/test/asn1_SUITE_data/EnumN2N.asn1
index a724f2f3f5..a610eb6230 100644
--- a/lib/asn1/test/asn1_SUITE_data/EnumN2N.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/EnumN2N.asn1
@@ -1,6 +1,28 @@
EnumN2N DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
+Cause-Misc ::= ENUMERATED {
+ control-processing-overload,
+ not-enough-user-plane-processing-resources,
+ hardware-failure,
+ om-intervention,
+ unspecified,
+ unknown-PLMN,
+...
+}
+
+CauseProtocol ::= ENUMERATED {
+ transfer-syntax-error,
+ abstract-syntax-error-reject,
+ abstract-syntax-error-ignore-and-notify,
+ message-not-compatible-with-receiver-state,
+ semantic-error,
+ abstract-syntax-error-falsely-constructed-message,
+ unspecified,
+ ...
+}
+
+
NoExt ::= ENUMERATED {
blue(0),
red(1),
diff --git a/lib/asn1/test/asn1_SUITE_data/ExtensionDefault.asn1 b/lib/asn1/test/asn1_SUITE_data/ExtensionDefault.asn1
new file mode 100644
index 0000000000..67d9cb6312
--- /dev/null
+++ b/lib/asn1/test/asn1_SUITE_data/ExtensionDefault.asn1
@@ -0,0 +1,12 @@
+ExtensionDefault DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+Message ::= SEQUENCE {
+ id INTEGER (0..5),
+ ...,
+ priority Priority DEFAULT low
+}
+Priority ::= ENUMERATED { low(0), high(1), ... }
+
+END
diff --git a/lib/asn1/test/asn1_SUITE_data/ImportsFrom.asn1 b/lib/asn1/test/asn1_SUITE_data/ImportsFrom.asn1
index 32b8f75dde..dee3cd5048 100644
--- a/lib/asn1/test/asn1_SUITE_data/ImportsFrom.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/ImportsFrom.asn1
@@ -1,8 +1,9 @@
ImportsFrom DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
-IMPORTS Int FROM ImportsFrom2;
+IMPORTS Int, Quoted-Seq FROM ImportsFrom2;
i Int ::= 42
+My-Seq ::= Quoted-Seq
END
diff --git a/lib/asn1/test/asn1_SUITE_data/ImportsFrom2.asn1 b/lib/asn1/test/asn1_SUITE_data/ImportsFrom2.asn1
index b0c29d24ae..a8e619e215 100644
--- a/lib/asn1/test/asn1_SUITE_data/ImportsFrom2.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/ImportsFrom2.asn1
@@ -2,6 +2,11 @@ ImportsFrom2 DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
IMPORTS Int FROM ImportsFrom3;
+Quoted-Seq ::= SEQUENCE {
+ x INTEGER(0..17),
+ y INTEGER(0..666)
+}
+
LocalDef ::= OCTET STRING
END
diff --git a/lib/asn1/test/testExtensionDefault.erl b/lib/asn1/test/testExtensionDefault.erl
new file mode 100644
index 0000000000..cc50fa95b8
--- /dev/null
+++ b/lib/asn1/test/testExtensionDefault.erl
@@ -0,0 +1,53 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+-module(testExtensionDefault).
+
+-export([main/1]).
+
+main(_Erule) ->
+ roundtrip('Message', {'Message',1,low}), %Will be explicitly encoded.
+ roundtrip('Message', {'Message',1,high}),
+ roundtrip('Message', {'Message',1,asn1_DEFAULT}, {'Message',1,low}),
+
+ map_roundtrip('Message', #{id=>1,priority=>low}), %Will be explicitly encoded.
+ map_roundtrip('Message', #{id=>1,priority=>high}),
+ map_roundtrip('Message', #{id=>1}, #{id=>1,priority=>low}),
+ ok.
+
+roundtrip(Type, Value) ->
+ asn1_test_lib:roundtrip('ExtensionDefault', Type, Value).
+
+roundtrip(Type, Value, Expected) ->
+ %% asn1_test_lib:roundtrip/3 will invoke map_roundtrip/3, which will
+ %% not work in this case. Therefore, implement the roundtrip ourselves.
+ M = 'ExtensionDefault',
+ {ok,Enc} = M:encode(Type, Value),
+ {ok,Expected} = M:decode(Type, Enc),
+ ok.
+
+map_roundtrip(Type, Value) ->
+ map_roundtrip(Type, Value, Value).
+
+map_roundtrip(Type, Value, Expected) ->
+ M = 'maps_ExtensionDefault',
+ Enc = M:encode(Type, Value),
+ Expected = M:decode(Type, Enc),
+ ok.
diff --git a/lib/asn1/test/testUniqueObjectSets.erl b/lib/asn1/test/testUniqueObjectSets.erl
index 476d190651..0c61da96a1 100644
--- a/lib/asn1/test/testUniqueObjectSets.erl
+++ b/lib/asn1/test/testUniqueObjectSets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2014-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2014-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,8 +30,7 @@ seq_roundtrip(I, D0) ->
asn1_test_lib:map_roundtrip(M, 'Seq', Enc),
{ok,{'Seq',I,D}} = M:decode('Seq', Enc),
D
- catch C:E ->
- Stk = erlang:get_stacktrace(),
+ catch C:E:Stk ->
io:format("FAILED: ~p ~p\n", [I,D0]),
erlang:raise(C, E, Stk)
end.
@@ -60,7 +59,7 @@ main(CaseDir, Rule, Opts) ->
Objs = [gen_obj(I) || {I,_,_} <- D1],
DupObjs = [gen_dup_obj(I, T) || {I,T,_} <- D1],
DupObjRefs0 = [gen_dup_obj_refs(I) || {I,_,_} <- D1],
- DupObjRefs = string:join(DupObjRefs0, " |\n"),
+ DupObjRefs = lists:join(" |\n", DupObjRefs0),
Asn1Spec = 'UniqueObjectSets',
A = ["UniqueObjectSets DEFINITIONS AUTOMATIC TAGS ::=\n",
"BEGIN\n\n",
diff --git a/lib/asn1/test/test_modified_x420.erl b/lib/asn1/test/test_modified_x420.erl
index 6cd9e0e33b..a4b335026d 100644
--- a/lib/asn1/test/test_modified_x420.erl
+++ b/lib/asn1/test/test_modified_x420.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@ read_pem(File) ->
extract_base64(Binary) ->
- extract_base64_lines(string:tokens(binary_to_list(Binary), "\n")).
+ extract_base64_lines(string:lexemes(binary_to_list(Binary), "\n")).
extract_base64_lines(["-----BEGIN"++_ | Lines]) ->
take_base64_lines(Lines, _Acc = []);
diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk
index 7329a9f879..970479cc44 100644
--- a/lib/asn1/vsn.mk
+++ b/lib/asn1/vsn.mk
@@ -1 +1 @@
-ASN1_VSN = 5.0
+ASN1_VSN = 5.0.7
diff --git a/lib/common_test/doc/src/Makefile b/lib/common_test/doc/src/Makefile
index faa2d58a06..b5acdc6f95 100644
--- a/lib/common_test/doc/src/Makefile
+++ b/lib/common_test/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2017. All Rights Reserved.
+# Copyright Ericsson AB 2003-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -57,11 +57,10 @@ XML_REF3_FILES = ct.xml \
ct_testspec.xml
XML_REF6_FILES = common_test_app.xml
-XML_PART_FILES = part.xml
-# part_notes.xml \
-# part_notes_history.xml
+XML_PART_FILES = part.xml
XML_CHAPTER_FILES = \
+ introduction.xml \
basics_chapter.xml \
getting_started_chapter.xml \
install_chapter.xml \
@@ -76,8 +75,7 @@ XML_CHAPTER_FILES = \
event_handler_chapter.xml \
ct_hooks_chapter.xml \
dependencies_chapter.xml \
- notes.xml \
- notes_history.xml
+ notes.xml
BOOK_FILES = book.xml
@@ -111,10 +109,10 @@ SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
TOP_SPECS_FILE = specs.xml
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
+XML_FLAGS +=
+DVIPS_FLAGS +=
SPECS_FLAGS = -I../../include -I../../../snmp/include \
-I../../../kernel/include
@@ -131,27 +129,28 @@ $(TOP_PDF_FILE): $(XML_FILES)
pdf: $(TOP_PDF_FILE)
-html: gifs $(HTML_REF_MAN_FILE)
+html: gifs $(HTML_REF_MAN_FILE)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
man: $(MAN6_FILES) $(MAN3_FILES) $(MAN1_FILES)
-debug opt:
+debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN1DIR)/*
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(SPECDIR)/*
- rm -f errs core *~
+ rm -f errs core *~
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
diff --git a/lib/common_test/doc/src/ct.xml b/lib/common_test/doc/src/ct.xml
index 1a3cfdb0c5..c0380c4142 100644
--- a/lib/common_test/doc/src/ct.xml
+++ b/lib/common_test/doc/src/ct.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2010</year><year>2017</year>
+ <year>2010</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -572,6 +572,16 @@
</func>
<func>
+ <name>get_progname() -&gt; string()</name>
+ <fsummary>Returns the command used to start this Erlang instance.</fsummary>
+ <desc><marker id="get_progname-0"/>
+ <p>Returns the command used to start this Erlang instance.
+ If this information could not be found, the string
+ <c>"no_prog_name"</c> is returned.</p>
+ </desc>
+ </func>
+
+ <func>
<name>get_status() -&gt; TestStatus | {error, Reason} | no_tests_running</name>
<fsummary>Returns status of ongoing test.</fsummary>
<type>
@@ -1060,6 +1070,42 @@
</desc>
</func>
+ <func>
+ <name>remaining_test_procs() -&gt; {TestProcs,SharedGL,OtherGLs}</name>
+ <fsummary>>This function will return the identity of test- and group
+ leader processes that are still running at the time of this call.</fsummary>
+ <type>
+ <v>TestProcs = [{pid(),GL}]</v>
+ <v>GL = pid()</v>
+ <v>SharedGL = pid()</v>
+ <v>OtherGLs = [pid()]</v>
+ </type>
+ <desc><marker id="remaining_test_procs-0"/>
+ <p>This function will return the identity of test- and group
+ leader processes that are still running at the time of this call.
+ <c>TestProcs</c> are processes in the system that have a Common Test IO
+ process as group leader. <c>SharedGL</c> is the central Common Test
+ IO process, responsible for printing to log files for configuration
+ functions and sequentially executing test cases. <c>OtherGLs</c> are
+ Common Test IO processes that print to log files for test cases
+ in parallel test case groups.</p>
+ <p>The process information returned by this function may be
+ used to locate and terminate remaining processes after tests have
+ finished executing. The function would typically by called from
+ Common Test Hook functions.</p>
+ <p>Note that processes that execute configuration functions or
+ test cases are never included in <c>TestProcs</c>. It is therefore safe
+ to use post configuration hook functions (such as post_end_per_suite,
+ post_end_per_group, post_end_per_testcase) to terminate all processes
+ in <c>TestProcs</c> that have the current group leader process as its group
+ leader.</p>
+ <p>Note also that the shared group leader (<c>SharedGL</c>) must never be
+ terminated by the user, only by Common Test. Group leader processes
+ for parallel test case groups (<c>OtherGLs</c>) may however be terminated
+ in post_end_per_group hook functions.</p>
+ </desc>
+ </func>
+
<func>
<name>remove_config(Callback, Config) -&gt; ok</name>
<fsummary>Removes configuration variables (together with
@@ -1476,7 +1522,7 @@
<v>Hours = integer()</v>
<v>Mins = integer()</v>
<v>Secs = integer()</v>
- <v>Millisecs = integer() | float()</v>
+ <v>Millisecs = integer()</v>
<v>Func = {M, F, A} | function()</v>
<v>M = atom()</v>
<v>F = atom()</v>
diff --git a/lib/common_test/doc/src/ct_ftp.xml b/lib/common_test/doc/src/ct_ftp.xml
index e8c6f72db7..592c5eb05d 100644
--- a/lib/common_test/doc/src/ct_ftp.xml
+++ b/lib/common_test/doc/src/ct_ftp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2010</year><year>2016</year>
+ <year>2010</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,13 +33,11 @@
<file>ct_ftp.xml</file>
</header>
<module>ct_ftp</module>
- <modulesummary>FTP client module (based on the FTP support of the Inets
- application).</modulesummary>
+ <modulesummary>FTP client module (based on the FTP application).</modulesummary>
<description>
- <p>FTP client module (based on the FTP support of the <c>Inets</c>
- application).</p>
+ <p>FTP client module (based on the <c>ftp</c> application).</p>
</description>
diff --git a/lib/common_test/doc/src/ct_hooks_chapter.xml b/lib/common_test/doc/src/ct_hooks_chapter.xml
index 7ecc2e4298..ea4b67be08 100644
--- a/lib/common_test/doc/src/ct_hooks_chapter.xml
+++ b/lib/common_test/doc/src/ct_hooks_chapter.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2011</year><year>2017</year>
+ <year>2011</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -379,7 +379,7 @@
(in Kernel):
</p>
<code>
- %%% @doc Common Test Example Common Test Hook module.
+ %%% Common Test Example Common Test Hook module.
-module(example_cth).
%% Callbacks
@@ -408,51 +408,51 @@
-record(state, { file_handle, total, suite_total, ts, tcs, data }).
- %% @doc Return a unique id for this CTH.
+ %% Return a unique id for this CTH.
id(Opts) ->
proplists:get_value(filename, Opts, "/tmp/file.log").
- %% @doc Always called before any other callback function. Use this to initiate
+ %% Always called before any other callback function. Use this to initiate
%% any common state.
init(Id, Opts) ->
{ok,D} = file:open(Id,[write]),
{ok, #state{ file_handle = D, total = 0, data = [] }}.
- %% @doc Called before init_per_suite is called.
+ %% Called before init_per_suite is called.
pre_init_per_suite(Suite,Config,State) ->
{Config, State#state{ suite_total = 0, tcs = [] }}.
- %% @doc Called after init_per_suite.
+ %% Called after init_per_suite.
post_init_per_suite(Suite,Config,Return,State) ->
{Return, State}.
- %% @doc Called before end_per_suite.
+ %% Called before end_per_suite.
pre_end_per_suite(Suite,Config,State) ->
{Config, State}.
- %% @doc Called after end_per_suite.
+ %% Called after end_per_suite.
post_end_per_suite(Suite,Config,Return,State) ->
Data = {suites, Suite, State#state.suite_total, lists:reverse(State#state.tcs)},
{Return, State#state{ data = [Data | State#state.data] ,
total = State#state.total + State#state.suite_total } }.
- %% @doc Called before each init_per_group.
+ %% Called before each init_per_group.
pre_init_per_group(Suite,Group,Config,State) ->
{Config, State}.
- %% @doc Called after each init_per_group.
+ %% Called after each init_per_group.
post_init_per_group(Suite,Group,Config,Return,State) ->
{Return, State}.
- %% @doc Called before each end_per_group.
+ %% Called before each end_per_group.
pre_end_per_group(Suite,Group,Config,State) ->
{Config, State}.
- %% @doc Called after each end_per_group.
+ %% Called after each end_per_group.
post_end_per_group(Suite,Group,Config,Return,State) ->
{Return, State}.
- %% @doc Called before each init_per_testcase.
+ %% Called before each init_per_testcase.
pre_init_per_testcase(Suite,TC,Config,State) ->
{Config, State#state{ ts = now(), total = State#state.suite_total + 1 } }.
@@ -460,26 +460,26 @@
post_init_per_testcase(Suite,TC,Config,Return,State) ->
{Return, State}
-%% @doc Called before each end_per_testcase (immediately after the test case).
+%% Called before each end_per_testcase (immediately after the test case).
pre_end_per_testcase(Suite,TC,Config,State) ->
{Config, State}.
- %% @doc Called after each end_per_testcase.
+ %% Called after each end_per_testcase.
post_end_per_testcase(Suite,TC,Config,Return,State) ->
TCInfo = {testcase, Suite, TC, Return, timer:now_diff(now(), State#state.ts)},
{Return, State#state{ ts = undefined, tcs = [TCInfo | State#state.tcs] } }.
- %% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group,
+ %% Called after post_init_per_suite, post_end_per_suite, post_init_per_group,
%% post_end_per_group and post_end_per_testcase if the suite, group or test case failed.
on_tc_fail(Suite, TC, Reason, State) ->
State.
- %% @doc Called when a test case is skipped by either user action
+ %% Called when a test case is skipped by either user action
%% or due to an init function failing.
on_tc_skip(Suite, TC, Reason, State) ->
State.
- %% @doc Called when the scope of the CTH is done
+ %% Called when the scope of the CTH is done
terminate(State) ->
io:format(State#state.file_handle, "~p.~n",
[{test_run, State#state.total, State#state.data}]),
@@ -501,12 +501,13 @@
<tag><c>cth_log_redirect</c></tag>
<item>
<p>Built-in</p>
- <p>Captures all <c>error_logger</c> and SASL logging
- events and prints them to the current test case log. If an event cannot be
- associated with a test case, it is printed in the <c>Common Test</c> framework log.
+ <p>Captures all log events that would normally be printed by the default
+ logger handler, and prints them to the current test case log.
+ If an event cannot be associated with a test case, it is printed in
+ the <c>Common Test</c> framework log.
This happens for test cases running in parallel and events occuring
in-between test cases. You can configure the level of
- <seealso marker="sasl:sasl_app">SASL</seealso> events report
+ <seealso marker="sasl:sasl_app">SASL</seealso> reports
using the normal SASL mechanisms.</p>
</item>
<tag><c>cth_surefire</c></tag>
diff --git a/lib/common_test/doc/src/fascicules.xml b/lib/common_test/doc/src/fascicules.xml
deleted file mode 100644
index c4a28a699a..0000000000
--- a/lib/common_test/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml
index 28b2d44168..118dcd88bd 100644
--- a/lib/common_test/doc/src/notes.xml
+++ b/lib/common_test/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,6 +33,126 @@
<file>notes.xml</file>
</header>
+<section><title>Common_Test 1.16.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The Logger handler cth_log_redirect earlier called the
+ report callback (report_cb) before calling the logger
+ formatter. In some cases this would fail, since
+ cth_log_redirect could not handle report callbacks with
+ two arguments. This is now corrected, so only the
+ formatter will call the report callback.</p>
+ <p>
+ Own Id: OTP-15307</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Common_Test 1.16</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Use the compiler option <c>nowarn_export_all</c> to
+ disable <c>export_all</c> warnings when automatically
+ compiling test suites.</p>
+ <p>
+ Own Id: OTP-14810</p>
+ </item>
+ <item>
+ <p>
+ Use uri_string module instead of http_uri.</p>
+ <p>
+ Own Id: OTP-14902</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Common_Test 1.15.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed problem with 'skip_groups' in combination with 'all
+ suites' option in test specification.</p>
+ <p>
+ Own Id: OTP-14953</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Common_Test 1.15.3</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A new function, <c>ct:remaining_test_procs/0</c>, returns
+ the identity of test- and group leader processes that are
+ still running at the time of the call.</p>
+ <p>
+ Own Id: OTP-13832</p>
+ </item>
+ <item>
+ <p>
+ A "latest test result" link is now displayed in the
+ footer of each test index page, which performs a jump to
+ the most recently generated test index. This is useful
+ for making quick comparisons of results between test runs
+ without having to traverse the log file tree.</p>
+ <p>
+ Own Id: OTP-14281</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Common_Test 1.15.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ General Unicode improvements.</p>
+ <p>
+ Own Id: OTP-14462</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Common_Test 1.15.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ In OTP-20.0, the behavior of c, make, and ct_make was
+ changed so that in some cases the beam files by default
+ would be written to the directory where the source files
+ were found. This is now changed back to the old behavior
+ so beam files are by default written to current
+ directory.</p>
+ <p>
+ Own Id: OTP-14489 Aux Id: ERL-438 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Common_Test 1.15</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/common_test/doc/src/part_notes.xml b/lib/common_test/doc/src/part_notes.xml
deleted file mode 100644
index 360c535e96..0000000000
--- a/lib/common_test/doc/src/part_notes.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Common Test</title>
- <prepared>Peter Andersson</prepared>
- <docno></docno>
- <date>2007-12-01</date>
- <rev></rev>
- <file>part_notes.xml</file>
- </header>
- <description>
- <p>Common Test - tool for automated testing, based on the Erlang/OTP Test Server.</p>
- <p>For information about older versions see
- <url href="part_notes_history_frame.html">release notes
- history</url>.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
-
diff --git a/lib/common_test/doc/src/part_notes_history.xml b/lib/common_test/doc/src/part_notes_history.xml
deleted file mode 100644
index d13bb858db..0000000000
--- a/lib/common_test/doc/src/part_notes_history.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Common Test</title>
- <prepared>Peter Andersson</prepared>
- <docno></docno>
- <date>2007-12-01</date>
- <rev></rev>
- <file>part_notes.xml</file>
- </header>
- <include file="notes_history"></include>
-</part>
-
-
diff --git a/lib/common_test/src/Makefile b/lib/common_test/src/Makefile
index 9d751996ad..80eaed70bd 100644
--- a/lib/common_test/src/Makefile
+++ b/lib/common_test/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2016. All Rights Reserved.
+# Copyright Ericsson AB 2003-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -165,3 +165,5 @@ release_tests_spec: opt
release_docs_spec: docs
+# Include dependencies -- list below added by Kostis Sagonas
+$(EBIN)/cth_log_redirect.beam: ../../kernel/include/logger.hrl ../../kernel/src/logger_internal.hrl
diff --git a/lib/common_test/src/common_test.app.src b/lib/common_test/src/common_test.app.src
index 430a4fa2fb..efebea896c 100644
--- a/lib/common_test/src/common_test.app.src
+++ b/lib/common_test/src/common_test.app.src
@@ -1,7 +1,7 @@
% This is an -*- erlang -*- file.
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -85,6 +85,7 @@
"crypto-3.6",
"debugger-4.1",
"erts-7.0",
+ "ftp-1.0.0",
"inets-6.0",
"kernel-4.0",
"observer-2.1",
@@ -92,7 +93,7 @@
"sasl-2.4.2",
"snmp-5.1.2",
"ssh-4.0",
- "stdlib-2.5",
+ "stdlib-3.5",
"syntax_tools-1.7",
"tools-2.8",
"xmerl-1.3.8"
diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl
index 19b0ee20fe..778ea2e9e2 100644
--- a/lib/common_test/src/ct.erl
+++ b/lib/common_test/src/ct.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,38 +18,6 @@
%% %CopyrightEnd%
%%
-%%% @doc Main user interface for the Common Test framework.
-%%%
-%%% <p> This module implements the command line interface for running
-%%% tests and some basic functions for common test case issues
-%%% such as configuration and logging. </p>
-%%%
-%%% <p><strong>Test Suite Support Macros</strong></p>
-%%%
-%%% <p>The <c>config</c> macro is defined in <c>ct.hrl</c>. This
-%%% macro should be used to retrieve information from the
-%%% <c>Config</c> variable sent to all test cases. It is used with two
-%%% arguments, where the first is the name of the configuration
-%%% variable you wish to retrieve, and the second is the <c>Config</c>
-%%% variable supplied to the test case.</p>
-%%%
-%%% <p>Possible configuration variables include:</p>
-%%% <ul>
-%%% <li><c>data_dir</c> - Data file directory.</li>
-%%% <li><c>priv_dir</c> - Scratch file directory.</li>
-%%% <li>Whatever added by <c>init_per_suite/1</c> or
-%%% <c>init_per_testcase/2</c> in the test suite.</li>
-%%% </ul>
-
-%%% @type var_name() = atom(). A variable name which is specified when
-%%% <c>ct:require/2</c> is called,
-%%% e.g. <c>ct:require(mynodename,{node,[telnet]})</c>
-%%%
-%%% @type target_name() = var_name(). The name of a target.
-%%%
-%%% @type handle() = ct_gen_conn:handle() | term(). The identity of a
-%%% specific connection.
-
-module(ct).
-include("ct.hrl").
@@ -87,8 +55,11 @@
decrypt_config_file/2, decrypt_config_file/3]).
-export([get_target_name/1]).
+-export([get_progname/0]).
-export([parse_table/1, listenv/1]).
+-export([remaining_test_procs/0]).
+
%%----------------------------------------------------------------------
%% Exported types
%%----------------------------------------------------------------------
@@ -118,209 +89,34 @@
%%----------------------------------------------------------------------
-
-%%%-----------------------------------------------------------------
-%%% @spec install(Opts) -> ok | {error,Reason}
-%%% Opts = [Opt]
-%%% Opt = {config,ConfigFiles} | {event_handler,Modules} |
-%%% {decrypt,KeyOrFile}
-%%% ConfigFiles = [ConfigFile]
-%%% ConfigFile = string()
-%%% Modules = [atom()]
-%%% KeyOrFile = {key,Key} | {file,KeyFile}
-%%% Key = string()
-%%% KeyFile = string()
-%%% @doc Install config files and event handlers.
-%%%
-%%% <p>Run this function once before first test.</p>
-%%%
-%%% <p>Example:<br/>
-%%% <c>install([{config,["config_node.ctc","config_user.ctc"]}])</c>.</p>
-%%%
-%%% <p>Note that this function is automatically run by the
-%%% <c>ct_run</c> program.</p>
install(Opts) ->
ct_run:install(Opts).
-%%%-----------------------------------------------------------------
-%%% @spec run(TestDir,Suite,Cases) -> Result
-%%% TestDir = string()
-%%% Suite = atom()
-%%% Cases = atom() | [atom()]
-%%% Result = [TestResult] | {error,Reason}
-%%%
-%%% @doc Run the given test case(s).
-%%%
-%%% <p>Requires that <c>ct:install/1</c> has been run first.</p>
-%%%
-%%% <p>Suites (*_SUITE.erl) files must be stored in
-%%% <c>TestDir</c> or <c>TestDir/test</c>. All suites
-%%% will be compiled when test is run.</p>
run(TestDir,Suite,Cases) ->
ct_run:run(TestDir,Suite,Cases).
-%%%-----------------------------------------------------------------
-%%% @spec run(TestDir,Suite) -> Result
-%%%
-%%% @doc Run all test cases in the given suite.
-%%% @see run/3.
run(TestDir,Suite) ->
ct_run:run(TestDir,Suite).
-%%%-----------------------------------------------------------------
-%%% @spec run(TestDirs) -> Result
-%%% TestDirs = TestDir | [TestDir]
-%%%
-%%% @doc Run all test cases in all suites in the given directories.
-%%% @see run/3.
run(TestDirs) ->
ct_run:run(TestDirs).
-%%%-----------------------------------------------------------------
-%%% @spec run_test(Opts) -> Result
-%%% Opts = [OptTuples]
-%%% OptTuples = {dir,TestDirs} | {suite,Suites} | {group,Groups} |
-%%% {testcase,Cases} | {spec,TestSpecs} | {join_specs,Bool} |
-%%% {label,Label} | {config,CfgFiles} | {userconfig, UserConfig} |
-%%% {allow_user_terms,Bool} | {logdir,LogDir} |
-%%% {silent_connections,Conns} | {stylesheet,CSSFile} |
-%%% {cover,CoverSpecFile} | {cover_stop,Bool} | {step,StepOpts} |
-%%% {event_handler,EventHandlers} | {include,InclDirs} |
-%%% {auto_compile,Bool} | {abort_if_missing_suites,Bool} |
-%%% {create_priv_dir,CreatePrivDir} |
-%%% {multiply_timetraps,M} | {scale_timetraps,Bool} |
-%%% {repeat,N} | {duration,DurTime} | {until,StopTime} |
-%%% {force_stop,ForceStop} | {decrypt,DecryptKeyOrFile} |
-%%% {refresh_logs,LogDir} | {logopts,LogOpts} |
-%%% {verbosity,VLevels} | {basic_html,Bool} |
-%%% {esc_chars,Bool} | {ct_hooks, CTHs} |
-%%% {enable_builtin_hooks,Bool} | {release_shell,Bool}
-%%% TestDirs = [string()] | string()
-%%% Suites = [string()] | [atom()] | string() | atom()
-%%% Cases = [atom()] | atom()
-%%% Groups = GroupNameOrPath | [GroupNameOrPath]
-%%% GroupNameOrPath = [atom()] | atom() | all
-%%% TestSpecs = [string()] | string()
-%%% Label = string() | atom()
-%%% CfgFiles = [string()] | string()
-%%% UserConfig = [{CallbackMod,CfgStrings}] | {CallbackMod,CfgStrings}
-%%% CallbackMod = atom()
-%%% CfgStrings = [string()] | string()
-%%% LogDir = string()
-%%% Conns = all | [atom()]
-%%% CSSFile = string()
-%%% CoverSpecFile = string()
-%%% StepOpts = [StepOpt] | []
-%%% StepOpt = config | keep_inactive
-%%% EventHandlers = EH | [EH]
-%%% EH = atom() | {atom(),InitArgs} | {[atom()],InitArgs}
-%%% InitArgs = [term()]
-%%% InclDirs = [string()] | string()
-%%% CreatePrivDir = auto_per_run | auto_per_tc | manual_per_tc
-%%% M = integer()
-%%% N = integer()
-%%% DurTime = string(HHMMSS)
-%%% StopTime = string(YYMoMoDDHHMMSS) | string(HHMMSS)
-%%% ForceStop = skip_rest | Bool
-%%% DecryptKeyOrFile = {key,DecryptKey} | {file,DecryptFile}
-%%% DecryptKey = string()
-%%% DecryptFile = string()
-%%% LogOpts = [LogOpt]
-%%% LogOpt = no_nl | no_src
-%%% VLevels = VLevel | [{Category,VLevel}]
-%%% VLevel = integer()
-%%% Category = atom()
-%%% CTHs = [CTHModule | {CTHModule, CTHInitArgs}]
-%%% CTHModule = atom()
-%%% CTHInitArgs = term()
-%%% Result = {Ok,Failed,{UserSkipped,AutoSkipped}} | TestRunnerPid | {error,Reason}
-%%% Ok = integer()
-%%% Failed = integer()
-%%% UserSkipped = integer()
-%%% AutoSkipped = integer()
-%%% TestRunnerPid = pid()
-%%% Reason = term()
-%%% @doc <p>Run tests as specified by the combination of options in <c>Opts</c>.
-%%% The options are the same as those used with the
-%%% <seealso marker="ct_run#ct_run"><c>ct_run</c></seealso> program.
-%%% Note that here a <c>TestDir</c> can be used to point out the path to
-%%% a <c>Suite</c>. Note also that the option <c>testcase</c>
-%%% corresponds to the <c>-case</c> option in the <c>ct_run</c>
-%%% program. Configuration files specified in <c>Opts</c> will be
-%%% installed automatically at startup.</p>
-%%% <p><c>TestRunnerPid</c> is returned if <c>release_shell == true</c>
-%%% (see <c>break/1</c> for details).</p>
-%%% <p><c>Reason</c> indicates what type of error has been encountered.</p>
run_test(Opts) ->
ct_run:run_test(Opts).
-%%%-----------------------------------------------------------------
-%%% @spec run_testspec(TestSpec) -> Result
-%%% TestSpec = [term()]
-%%% Result = {Ok,Failed,{UserSkipped,AutoSkipped}} | {error,Reason}
-%%% Ok = integer()
-%%% Failed = integer()
-%%% UserSkipped = integer()
-%%% AutoSkipped = integer()
-%%% Reason = term()
-%%% @doc Run test specified by <c>TestSpec</c>. The terms are
-%%% the same as those used in test specification files.
-%%% <p><c>Reason</c> indicates what type of error has been encountered.</p>
run_testspec(TestSpec) ->
ct_run:run_testspec(TestSpec).
-%%%-----------------------------------------------------------------
-%%% @spec step(TestDir,Suite,Case) -> Result
-%%% Case = atom()
-%%%
-%%% @doc Step through a test case with the debugger.
-%%% @see run/3
step(TestDir,Suite,Case) ->
ct_run:step(TestDir,Suite,Case).
-%%%-----------------------------------------------------------------
-%%% @spec step(TestDir,Suite,Case,Opts) -> Result
-%%% Case = atom()
-%%% Opts = [Opt] | []
-%%% Opt = config | keep_inactive
-%%%
-%%% @doc Step through a test case with the debugger. If the
-%%% <c>config</c> option has been given, breakpoints will
-%%% be set also on the configuration functions in <c>Suite</c>.
-%%% @see run/3
step(TestDir,Suite,Case,Opts) ->
ct_run:step(TestDir,Suite,Case,Opts).
-%%%-----------------------------------------------------------------
-%%% @spec start_interactive() -> ok
-%%%
-%%% @doc Start CT in interactive mode.
-%%%
-%%% <p>From this mode all test case support functions can be executed
-%%% directly from the erlang shell. The interactive mode can also be
-%%% started from the OS command line with <c>ct_run -shell
-%%% [-config File...]</c>.</p>
-%%%
-%%% <p>If any functions using "required config data" (e.g. telnet or
-%%% ftp functions) are to be called from the erlang shell, config data
-%%% must first be required with <c>ct:require/2</c>.</p>
-%%%
-%%% <p>Example:<br/>
-%%% <c>&gt; ct:require(unix_telnet, unix).</c><br/>
-%%% <c>ok</c><br/>
-%%% <c>&gt; ct_telnet:open(unix_telnet).</c><br/>
-%%% <c>{ok,&lt;0.105.0&gt;}</c><br/>
-%%% <c>&gt; ct_telnet:cmd(unix_telnet, "ls .").</c><br/>
-%%% <c>{ok,["ls","file1 ...",...]}</c></p>
start_interactive() ->
_ = ct_util:start(interactive),
ok.
-%%%-----------------------------------------------------------------
-%%% @spec stop_interactive() -> ok
-%%%
-%%% @doc Exit the interactive mode.
-%%% @see start_interactive/0
stop_interactive() ->
ct_util:stop(normal),
ok.
@@ -329,181 +125,24 @@ stop_interactive() ->
%%% MISC INTERFACE
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%%-----------------------------------------------------------------
-%%% @spec require(Required) -> ok | {error,Reason}
-%%% Required = Key | {Key,SubKeys} | {Key,SubKey,SubKeys}
-%%% Key = atom()
-%%% SubKeys = SubKey | [SubKey]
-%%% SubKey = atom()
-%%%
-%%% @doc Check if the required configuration is available. It is possible
-%%% to specify arbitrarily deep tuples as <c>Required</c>. Note that it is
-%%% only the last element of the tuple which can be a list of <c>SubKey</c>s.
-%%%
-%%% <p>Example 1: require the variable <c>myvar</c>:</p>
-%%% <pre>ok = ct:require(myvar).</pre>
-%%%
-%%% <p>In this case the config file must at least contain:</p>
-%%% <pre>{myvar,Value}.</pre>
-%%%
-%%% <p>Example 2: require the key <c>myvar</c> with
-%%% subkeys <c>sub1</c> and <c>sub2</c>:</p>
-%%% <pre>ok = ct:require({myvar,[sub1,sub2]}).</pre>
-%%%
-%%% <p>In this case the config file must at least contain:</p>
-%%% <pre>{myvar,[{sub1,Value},{sub2,Value}]}.</pre>
-%%%
-%%% <p>Example 3: require the key <c>myvar</c> with
-%%% subkey <c>sub1</c> with <c>subsub1</c>:</p>
-%%% <pre>ok = ct:require({myvar,sub1,sub2}).</pre>
-%%%
-%%% <p>In this case the config file must at least contain:</p>
-%%% <pre>{myvar,[{sub1,[{sub2,Value}]}]}.</pre>
-%%%
-%%% @see require/2
-%%% @see get_config/1
-%%% @see get_config/2
-%%% @see get_config/3
require(Required) ->
ct_config:require(Required).
-%%%-----------------------------------------------------------------
-%%% @spec require(Name,Required) -> ok | {error,Reason}
-%%% Name = atom()
-%%% Required = Key | {Key,SubKey} | {Key,SubKey,SubKey}
-%%% SubKey = Key
-%%% Key = atom()
-%%%
-%%% @doc Check if the required configuration is available, and give it
-%%% a name. The semantics for <c>Required</c> is the same as in
-%%% <c>required/1</c> except that it is not possible to specify a list
-%%% of <c>SubKey</c>s.
-%%%
-%%% <p>If the requested data is available, the sub entry will be
-%%% associated with <c>Name</c> so that the value of the element
-%%% can be read with <c>get_config/1,2</c> provided
-%%% <c>Name</c> instead of the whole <c>Required</c> term.</p>
-%%%
-%%% <p>Example: Require one node with a telnet connection and an
-%%% ftp connection. Name the node <c>a</c>:
-%%% <pre>ok = ct:require(a,{machine,node}).</pre>
-%%% All references to this node may then use the node name.
-%%% E.g. you can fetch a file over ftp like this:</p>
-%%% <pre>ok = ct:ftp_get(a,RemoteFile,LocalFile).</pre>
-%%%
-%%% <p>For this to work, the config file must at least contain:</p>
-%%% <pre>{machine,[{node,[{telnet,IpAddr},{ftp,IpAddr}]}]}.</pre>
-%%%
-%%% <note><p>The behaviour of this function changed radically in common_test
-%%% 1.6.2. In order too keep some backwards compatability it is still possible
-%%% to do: <br/><c>ct:require(a,{node,[telnet,ftp]}).</c><br/>
-%%% This will associate the name <c>a</c> with the top level <c>node</c> entry.
-%%% For this to work, the config file must at least contain:<br/>
-%%% <c>{node,[{telnet,IpAddr},{ftp,IpAddr}]}.</c></p></note>
-%%%
-%%% @see require/1
-%%% @see get_config/1
-%%% @see get_config/2
-%%% @see get_config/3
require(Name,Required) ->
ct_config:require(Name,Required).
-%%%-----------------------------------------------------------------
-%%% @spec get_config(Required) -> Value
-%%% @equiv get_config(Required,undefined,[])
get_config(Required) ->
ct_config:get_config(Required,undefined,[]).
-%%%-----------------------------------------------------------------
-%%% @spec get_config(Required,Default) -> Value
-%%% @equiv get_config(Required,Default,[])
get_config(Required,Default) ->
ct_config:get_config(Required,Default,[]).
-%%%-----------------------------------------------------------------
-%%% @spec get_config(Required,Default,Opts) -> ValueOrElement
-%%% Required = KeyOrName | {KeyOrName,SubKey} | {KeyOrName,SubKey,SubKey}
-%%% KeyOrName = atom()
-%%% SubKey = atom()
-%%% Default = term()
-%%% Opts = [Opt] | []
-%%% Opt = element | all
-%%% ValueOrElement = term() | Default
-%%%
-%%% @doc Read config data values.
-%%%
-%%% <p>This function returns the matching value(s) or config element(s),
-%%% given a config variable key or its associated name
-%%% (if one has been specified with <c>require/2</c> or a
-%%% require statement).</p>
-%%%
-%%% <p>Example, given the following config file:</p>
-%%% <pre>
-%%% {unix,[{telnet,IpAddr},
-%%% {user,[{username,Username},
-%%% {password,Password}]}]}.</pre>
-%%% <p><c>ct:get_config(unix,Default) ->
-%%% [{telnet,IpAddr},
-%%% {user, [{username,Username},
-%%% {password,Password}]}]</c><br/>
-%%% <c>ct:get_config({unix,telnet},Default) -> IpAddr</c><br/>
-%%% <c>ct:get_config({unix,user,username},Default) -> Username</c><br/>
-%%% <c>ct:get_config({unix,ftp},Default) -> Default</c><br/>
-%%% <c>ct:get_config(unknownkey,Default) -> Default</c></p>
-%%%
-%%% <p>If a config variable key has been associated with a name (by
-%%% means of <c>require/2</c> or a require statement), the name
-%%% may be used instead of the key to read the value:</p>
-%%%
-%%% <p><c>ct:require(myuser,{unix,user}) -> ok.</c><br/>
-%%% <c>ct:get_config(myuser,Default) ->
-%%% [{username,Username},
-%%% {password,Password}]</c></p>
-%%%
-%%% <p>If a config variable is defined in multiple files and you want to
-%%% access all possible values, use the <c>all</c> option. The
-%%% values will be returned in a list and the order of the elements
-%%% corresponds to the order that the config files were specified at
-%%% startup.</p>
-%%%
-%%% <p>If you want config elements (key-value tuples) returned as result
-%%% instead of values, use the <c>element</c> option.
-%%% The returned elements will then be on the form <c>{Required,Value}</c></p>
-%%%
-%%% @see get_config/1
-%%% @see get_config/2
-%%% @see require/1
-%%% @see require/2
get_config(Required,Default,Opts) ->
ct_config:get_config(Required,Default,Opts).
-%%%-----------------------------------------------------------------
-%%% @spec reload_config(Required) -> ValueOrElement
-%%% Required = KeyOrName | {KeyOrName,SubKey} | {KeyOrName,SubKey,SubKey}
-%%% KeyOrName = atom()
-%%% SubKey = atom()
-%%% ValueOrElement = term()
-%%%
-%%% @doc Reload config file which contains specified configuration key.
-%%%
-%%% <p>This function performs updating of the configuration data from which the
-%%% given configuration variable was read, and returns the (possibly) new
-%%% value of this variable.</p>
-%%% <p>Note that if some variables were present in the configuration but are not loaded
-%%% using this function, they will be removed from the configuration table together
-%%% with their aliases.</p>
-%%%
reload_config(Required)->
ct_config:reload_config(Required).
-%%%-----------------------------------------------------------------
-%%% @spec get_testspec_terms() -> TestSpecTerms | undefined
-%%% TestSpecTerms = [{Tag,Value}]
-%%% Value = [term()]
-%%%
-%%% @doc Get a list of all test specification terms used to
-%%% configure and run this test.
-%%%
get_testspec_terms() ->
case ct_util:get_testdata(testspec) of
undefined ->
@@ -512,25 +151,6 @@ get_testspec_terms() ->
ct_testspec:testspec_rec2list(CurrSpecRec)
end.
-%%%-----------------------------------------------------------------
-%%% @spec get_testspec_terms(Tags) -> TestSpecTerms | undefined
-%%% Tags = [Tag] | Tag
-%%% Tag = atom()
-%%% TestSpecTerms = [{Tag,Value}] | {Tag,Value}
-%%% Value = [{Node,term()}] | [term()]
-%%% Node = atom()
-%%%
-%%% @doc Read one or more terms from the test specification used
-%%% to configure and run this test. Tag is any valid test specification
-%%% tag, such as e.g. <c>label</c>, <c>config</c>, <c>logdir</c>.
-%%% User specific terms are also available to read if the
-%%% <c>allow_user_terms</c> option has been set. Note that all value tuples
-%%% returned, except user terms, will have the node name as first element.
-%%% Note also that in order to read test terms, use <c>Tag = tests</c>
-%%% (rather than <c>suites</c>, <c>groups</c> or <c>cases</c>). Value is
-%%% then the list of *all* tests on the form:
-%%% <c>[{Node,Dir,[{TestSpec,GroupsAndCases1},...]},...], where
-%%% GroupsAndCases = [{Group,[Case]}] | [Case]</c>.
get_testspec_terms(Tags) ->
case ct_util:get_testdata(testspec) of
undefined ->
@@ -539,24 +159,9 @@ get_testspec_terms(Tags) ->
ct_testspec:testspec_rec2list(Tags, CurrSpecRec)
end.
-
-%%%-----------------------------------------------------------------
-%%% @spec escape_chars(IoList1) -> IoList2 | {error,Reason}
-%%% IoList1 = iolist()
-%%% IoList2 = iolist()
-%%%
-%%% @doc Escape special characters to be printed in html log
-%%%
escape_chars(IoList) ->
ct_logs:escape_chars(IoList).
-%%%-----------------------------------------------------------------
-%%% @spec escape_chars(Format, Args) -> IoList | {error,Reason}
-%%% Format = string()
-%%% Args = list()
-%%%
-%%% @doc Escape special characters to be printed in html log
-%%%
escape_chars(Format, Args) ->
try io_lib:format(Format, Args) of
IoList ->
@@ -566,17 +171,9 @@ escape_chars(Format, Args) ->
{error,Reason}
end.
-%%%-----------------------------------------------------------------
-%%% @spec log(Format) -> ok
-%%% @equiv log(default,50,Format,[],[])
log(Format) ->
log(default,?STD_IMPORTANCE,Format,[],[]).
-%%%-----------------------------------------------------------------
-%%% @spec log(X1,X2) -> ok
-%%% X1 = Category | Importance | Format
-%%% X2 = Format | Args
-%%% @equiv log(Category,Importance,Format,Args,[])
log(X1,X2) ->
{Category,Importance,Format,Args} =
if is_atom(X1) -> {X1,?STD_IMPORTANCE,X2,[]};
@@ -585,12 +182,6 @@ log(X1,X2) ->
end,
log(Category,Importance,Format,Args,[]).
-%%%-----------------------------------------------------------------
-%%% @spec log(X1,X2,X3) -> ok
-%%% X1 = Category | Importance | Format
-%%% X2 = Importance | Format | Args
-%%% X3 = Format | Args | Opts
-%%% @equiv log(Category,Importance,Format,Args,Opts)
log(X1,X2,X3) ->
{Category,Importance,Format,Args,Opts} =
if is_atom(X1), is_integer(X2) -> {X1,X2,X3,[],[]};
@@ -600,13 +191,6 @@ log(X1,X2,X3) ->
end,
log(Category,Importance,Format,Args,Opts).
-%%%-----------------------------------------------------------------
-%%% @spec log(X1,X2,X3,X4) -> ok
-%%% X1 = Category | Importance
-%%% X2 = Importance | Format
-%%% X3 = Format | Args
-%%% X4 = Args | Opts
-%%% @equiv log(Category,Importance,Format,Args,Opts)
log(X1,X2,X3,X4) ->
{Category,Importance,Format,Args,Opts} =
if is_atom(X1), is_integer(X2) -> {X1,X2,X3,X4,[]};
@@ -615,40 +199,12 @@ log(X1,X2,X3,X4) ->
end,
log(Category,Importance,Format,Args,Opts).
-%%%-----------------------------------------------------------------
-%%% @spec log(Category,Importance,Format,Args,Opts) -> ok
-%%% Category = atom()
-%%% Importance = integer()
-%%% Format = string()
-%%% Args = list()
-%%% Opts = [Opt]
-%%% Opt = {heading,string()} | esc_chars | no_css
-%%%
-%%% @doc Printout from a test case to the log file.
-%%%
-%%% <p>This function is meant for printing a string directly from a
-%%% test case to the test case log file.</p>
-%%%
-%%% <p>Default <c>Category</c> is <c>default</c>,
-%%% default <c>Importance</c> is <c>?STD_IMPORTANCE</c>,
-%%% and default value for <c>Args</c> is <c>[]</c>.</p>
-%%% <p>Please see the User's Guide for details on <c>Category</c>
-%%% and <c>Importance</c>.</p>
log(Category,Importance,Format,Args,Opts) ->
ct_logs:tc_log(Category,Importance,Format,Args,Opts).
-
-%%%-----------------------------------------------------------------
-%%% @spec print(Format) -> ok
-%%% @equiv print(default,50,Format,[],[])
print(Format) ->
print(default,?STD_IMPORTANCE,Format,[],[]).
-%%%-----------------------------------------------------------------
-%%% @spec print(X1,X2) -> ok
-%%% X1 = Category | Importance | Format
-%%% X2 = Format | Args
-%%% @equiv print(Category,Importance,Format,Args,[])
print(X1,X2) ->
{Category,Importance,Format,Args} =
if is_atom(X1) -> {X1,?STD_IMPORTANCE,X2,[]};
@@ -657,12 +213,6 @@ print(X1,X2) ->
end,
print(Category,Importance,Format,Args,[]).
-%%%-----------------------------------------------------------------
-%%% @spec print(X1,X2,X3) -> ok
-%%% X1 = Category | Importance | Format
-%%% X2 = Importance | Format | Args
-%%% X3 = Format | Args | Opts
-%%% @equiv print(Category,Importance,Format,Args,Opts)
print(X1,X2,X3) ->
{Category,Importance,Format,Args,Opts} =
if is_atom(X1), is_integer(X2) -> {X1,X2,X3,[],[]};
@@ -672,13 +222,6 @@ print(X1,X2,X3) ->
end,
print(Category,Importance,Format,Args,Opts).
-%%%-----------------------------------------------------------------
-%%% @spec print(X1,X2,X3,X4) -> ok
-%%% X1 = Category | Importance
-%%% X2 = Importance | Format
-%%% X3 = Format | Args
-%%% X4 = Args | Opts
-%%% @equiv print(Category,Importance,Format,Args,Opts)
print(X1,X2,X3,X4) ->
{Category,Importance,Format,Args,Opts} =
if is_atom(X1), is_integer(X2) -> {X1,X2,X3,X4,[]};
@@ -687,40 +230,12 @@ print(X1,X2,X3,X4) ->
end,
print(Category,Importance,Format,Args,Opts).
-%%%-----------------------------------------------------------------
-%%% @spec print(Category,Importance,Format,Args,Opts) -> ok
-%%% Category = atom()
-%%% Importance = integer()
-%%% Format = string()
-%%% Args = list()
-%%% Opts = [Opt]
-%%% Opt = {heading,string()}
-%%%
-%%% @doc Printout from a test case to the console.
-%%%
-%%% <p>This function is meant for printing a string from a test case
-%%% to the console.</p>
-%%%
-%%% <p>Default <c>Category</c> is <c>default</c>,
-%%% default <c>Importance</c> is <c>?STD_IMPORTANCE</c>,
-%%% and default value for <c>Args</c> is <c>[]</c>.</p>
-%%% <p>Please see the User's Guide for details on <c>Category</c>
-%%% and <c>Importance</c>.</p>
print(Category,Importance,Format,Args,Opts) ->
ct_logs:tc_print(Category,Importance,Format,Args,Opts).
-
-%%%-----------------------------------------------------------------
-%%% @spec pal(Format) -> ok
-%%% @equiv pal(default,50,Format,[],[])
pal(Format) ->
pal(default,?STD_IMPORTANCE,Format,[]).
-%%%-----------------------------------------------------------------
-%%% @spec pal(X1,X2) -> ok
-%%% X1 = Category | Importance | Format
-%%% X2 = Format | Args
-%%% @equiv pal(Category,Importance,Format,Args,[])
pal(X1,X2) ->
{Category,Importance,Format,Args} =
if is_atom(X1) -> {X1,?STD_IMPORTANCE,X2,[]};
@@ -729,12 +244,6 @@ pal(X1,X2) ->
end,
pal(Category,Importance,Format,Args,[]).
-%%%-----------------------------------------------------------------
-%%% @spec pal(X1,X2,X3) -> ok
-%%% X1 = Category | Importance | Format
-%%% X2 = Importance | Format | Args
-%%% X3 = Format | Args | Opts
-%%% @equiv pal(Category,Importance,Format,Args,Opts)
pal(X1,X2,X3) ->
{Category,Importance,Format,Args,Opts} =
if is_atom(X1), is_integer(X2) -> {X1,X2,X3,[],[]};
@@ -744,13 +253,6 @@ pal(X1,X2,X3) ->
end,
pal(Category,Importance,Format,Args,Opts).
-%%%-----------------------------------------------------------------
-%%% @spec pal(X1,X2,X3,X4) -> ok
-%%% X1 = Category | Importance
-%%% X2 = Importance | Format
-%%% X3 = Format | Args
-%%% X4 = Args | Opts
-%%% @equiv pal(Category,Importance,Format,Args,Opts)
pal(X1,X2,X3,X4) ->
{Category,Importance,Format,Args,Opts} =
if is_atom(X1), is_integer(X2) -> {X1,X2,X3,X4,[]};
@@ -759,96 +261,31 @@ pal(X1,X2,X3,X4) ->
end,
pal(Category,Importance,Format,Args,Opts).
-%%%-----------------------------------------------------------------
-%%% @spec pal(Category,Importance,Format,Args,Opts) -> ok
-%%% Category = atom()
-%%% Importance = integer()
-%%% Format = string()
-%%% Args = list()
-%%% Opts = [Opt]
-%%% Opt = {heading,string()} | no_css
-%%%
-%%% @doc Print and log from a test case.
-%%%
-%%% <p>This function is meant for printing a string from a test case,
-%%% both to the test case log file and to the console.</p>
-%%%
-%%% <p>Default <c>Category</c> is <c>default</c>,
-%%% default <c>Importance</c> is <c>?STD_IMPORTANCE</c>,
-%%% and default value for <c>Args</c> is <c>[]</c>.</p>
-%%% <p>Please see the User's Guide for details on <c>Category</c>
-%%% and <c>Importance</c>.</p>
pal(Category,Importance,Format,Args,Opts) ->
ct_logs:tc_pal(Category,Importance,Format,Args,Opts).
-%%%-----------------------------------------------------------------
-%%% @spec set_verbosity(Category, Level) -> ok
-%%% Category = default | atom()
-%%% Level = integer()
-%%%
-%%% @doc Set the verbosity level for a category
set_verbosity(Category, Level) ->
ct_util:set_verbosity({Category,Level}).
-%%%-----------------------------------------------------------------
-%%% @spec get_verbosity(Category) -> Level | undefined
-%%% Category = default | atom()
-%%% Level = integer()
-%%%
-%%% @doc Read the verbosity level for a category
get_verbosity(Category) ->
ct_util:get_verbosity(Category).
-%%%-----------------------------------------------------------------
-%%% @spec capture_start() -> ok
-%%%
-%%% @doc Start capturing all text strings printed to stdout during
-%%% execution of the test case.
-%%%
-%%% @see capture_stop/0
-%%% @see capture_get/1
capture_start() ->
test_server:capture_start().
-%%%-----------------------------------------------------------------
-%%% @spec capture_stop() -> ok
-%%%
-%%% @doc Stop capturing text strings (a session started with
-%%% <c>capture_start/0</c>).
-%%%
-%%% @see capture_start/0
-%%% @see capture_get/1
capture_stop() ->
test_server:capture_stop().
-%%%-----------------------------------------------------------------
-%%% @spec capture_get() -> ListOfStrings
-%%% ListOfStrings = [string()]
-%%%
-%%% @equiv capture_get([default])
capture_get() ->
%% remove default log printouts (e.g. ct:log/2 printouts)
capture_get([default]).
-%%%-----------------------------------------------------------------
-%%% @spec capture_get(ExclCategories) -> ListOfStrings
-%%% ExclCategories = [atom()]
-%%% ListOfStrings = [string()]
-%%%
-%%% @doc Return and purge the list of text strings buffered
-%%% during the latest session of capturing printouts to stdout.
-%%% With <c>ExclCategories</c> it's possible to specify
-%%% log categories that should be ignored in <c>ListOfStrings</c>.
-%%% If <c>ExclCategories = []</c>, no filtering takes place.
-%%%
-%%% @see capture_start/0
-%%% @see capture_stop/0
-%%% @see log/3
capture_get([ExclCat | ExclCategories]) ->
Strs = test_server:capture_get(),
CatsStr = [atom_to_list(ExclCat) |
[[$| | atom_to_list(EC)] || EC <- ExclCategories]],
- {ok,MP} = re:compile("<div class=\"(" ++ lists:flatten(CatsStr) ++ ")\">.*"),
+ {ok,MP} = re:compile("<div class=\"(" ++ lists:flatten(CatsStr) ++ ")\">.*",
+ [unicode]),
lists:flatmap(fun(Str) ->
case re:run(Str, MP) of
{match,_} -> [];
@@ -859,40 +296,26 @@ capture_get([ExclCat | ExclCategories]) ->
capture_get([]) ->
test_server:capture_get().
-%%%-----------------------------------------------------------------
-%%% @spec fail(Reason) -> ok
-%%% Reason = term()
-%%%
-%%% @doc Terminate a test case with the given error
-%%% <c>Reason</c>.
fail(Reason) ->
try
exit({test_case_failed,Reason})
catch
- Class:R ->
- case erlang:get_stacktrace() of
+ Class:R:S ->
+ case S of
[{?MODULE,fail,1,_}|Stk] -> ok;
Stk -> ok
end,
erlang:raise(Class, R, Stk)
end.
-%%%-----------------------------------------------------------------
-%%% @spec fail(Format, Args) -> ok
-%%% Format = string()
-%%% Args = list()
-%%%
-%%% @doc Terminate a test case with an error message specified
-%%% by a format string and a list of values (used as arguments to
-%%% <c>io_lib:format/2</c>).
fail(Format, Args) ->
try io_lib:format(Format, Args) of
Str ->
try
exit({test_case_failed,lists:flatten(Str)})
catch
- Class:R ->
- case erlang:get_stacktrace() of
+ Class:R:S ->
+ case S of
[{?MODULE,fail,2,_}|Stk] -> ok;
Stk -> ok
end,
@@ -903,16 +326,6 @@ fail(Format, Args) ->
exit({BadArgs,{?MODULE,fail,[Format,Args]}})
end.
-%%%-----------------------------------------------------------------
-%%% @spec comment(Comment) -> ok
-%%% Comment = term()
-%%%
-%%% @doc Print the given <c>Comment</c> in the comment field in
-%%% the table on the test suite result page.
-%%%
-%%% <p>If called several times, only the last comment is printed.
-%%% The test case return value <c>{comment,Comment}</c>
-%%% overwrites the string set by this function.</p>
comment(Comment) when is_list(Comment) ->
Formatted =
case (catch io_lib:format("~ts",[Comment])) of
@@ -926,19 +339,6 @@ comment(Comment) ->
Formatted = io_lib:format("~tp",[Comment]),
send_html_comment(lists:flatten(Formatted)).
-%%%-----------------------------------------------------------------
-%%% @spec comment(Format, Args) -> ok
-%%% Format = string()
-%%% Args = list()
-%%%
-%%% @doc Print the formatted string in the comment field in
-%%% the table on the test suite result page.
-%%%
-%%% <p>The <c>Format</c> and <c>Args</c> arguments are
-%%% used in call to <c>io_lib:format/2</c> in order to create
-%%% the comment string. The behaviour of <c>comment/2</c> is
-%%% otherwise the same as the <c>comment/1</c> function (see
-%%% above for details).</p>
comment(Format, Args) when is_list(Format), is_list(Args) ->
Formatted =
case (catch io_lib:format(Format, Args)) of
@@ -954,64 +354,28 @@ send_html_comment(Comment) ->
ct_util:set_testdata({{comment,group_leader()},Html}),
test_server:comment(Html).
-%%%-----------------------------------------------------------------
-%%% @spec make_priv_dir() -> ok | {error,Reason}
-%%% Reason = term()
-%%% @doc If the test has been started with the create_priv_dir
-%%% option set to manual_per_tc, in order for the test case to use
-%%% the private directory, it must first create it by calling
-%%% this function.
make_priv_dir() ->
test_server:make_priv_dir().
-%%%-----------------------------------------------------------------
-%%% @spec get_target_name(Handle) -> {ok,TargetName} | {error,Reason}
-%%% Handle = handle()
-%%% TargetName = target_name()
-%%% @doc Return the name of the target that the given connection
-%%% belongs to.
get_target_name(Handle) ->
ct_util:get_target_name(Handle).
-
-%%%-----------------------------------------------------------------
-%%% @spec parse_table(Data) -> {Heading,Table}
-%%% Data = [string()]
-%%% Heading = tuple()
-%%% Table = [tuple()]
-%%%
-%%% @doc Parse the printout from an SQL table and return a list of tuples.
-%%%
-%%% <p>The printout to parse would typically be the result of a
-%%% <c>select</c> command in SQL. The returned
-%%% <c>Table</c> is a list of tuples, where each tuple is a row
-%%% in the table.</p>
-%%%
-%%% <p><c>Heading</c> is a tuple of strings representing the
-%%% headings of each column in the table.</p>
+
+-spec get_progname() -> string().
+
+get_progname() ->
+ case init:get_argument(progname) of
+ {ok, [[Prog]]} ->
+ Prog;
+ _Other ->
+ "no_prog_name"
+ end.
+
parse_table(Data) ->
ct_util:parse_table(Data).
-%%%-----------------------------------------------------------------
-%%% @spec listenv(Telnet) -> [Env]
-%%% Telnet = term()
-%%% Env = {Key,Value}
-%%% Key = string()
-%%% Value = string()
-%%%
-%%% @doc Performs the listenv command on the given telnet connection
-%%% and returns the result as a list of Key-Value pairs.
listenv(Telnet) ->
ct_util:listenv(Telnet).
-
-%%%-----------------------------------------------------------------
-%%% @spec testcases(TestDir, Suite) -> Testcases | {error,Reason}
-%%% TestDir = string()
-%%% Suite = atom()
-%%% Testcases = list()
-%%% Reason = term()
-%%%
-%%% @doc Returns all test cases in the specified suite.
testcases(TestDir, Suite) ->
case make_and_load(TestDir, Suite) of
E = {error,_} ->
@@ -1029,7 +393,7 @@ make_and_load(Dir, Suite) ->
EnvInclude =
case os:getenv("CT_INCLUDE_PATH") of
false -> [];
- CtInclPath -> string:tokens(CtInclPath, [$:,$ ,$,])
+ CtInclPath -> string:lexemes(CtInclPath, [$:,$ ,$,])
end,
StartInclude =
case init:get_argument(include) of
@@ -1051,15 +415,6 @@ make_and_load(Dir, Suite) ->
end
end.
-%%%-----------------------------------------------------------------
-%%% @spec userdata(TestDir, Suite) -> SuiteUserData | {error,Reason}
-%%% TestDir = string()
-%%% Suite = atom()
-%%% SuiteUserData = [term()]
-%%% Reason = term()
-%%%
-%%% @doc Returns any data specified with the tag <c>userdata</c>
-%%% in the list of tuples returned from <c>Suite:suite/0</c>.
userdata(TestDir, Suite) ->
case make_and_load(TestDir, Suite) of
E = {error,_} ->
@@ -1085,18 +440,6 @@ get_userdata(List, _) when is_list(List) ->
get_userdata(_BadTerm, Spec) ->
{error,list_to_atom(Spec ++ " must return a list")}.
-%%%-----------------------------------------------------------------
-%%% @spec userdata(TestDir, Suite, GroupOrCase) -> TCUserData | {error,Reason}
-%%% TestDir = string()
-%%% Suite = atom()
-%%% GroupOrCase = {group,GroupName} | atom()
-%%% GroupName = atom()
-%%% TCUserData = [term()]
-%%% Reason = term()
-%%%
-%%% @doc Returns any data specified with the tag <c>userdata</c>
-%%% in the list of tuples returned from <c>Suite:group(GroupName)</c>
-%%% or <c>Suite:Case()</c>.
userdata(TestDir, Suite, {group,GroupName}) ->
case make_and_load(TestDir, Suite) of
E = {error,_} ->
@@ -1115,27 +458,6 @@ userdata(TestDir, Suite, Case) when is_atom(Case) ->
get_userdata(Info, atom_to_list(Case)++"/0")
end.
-
-%%%-----------------------------------------------------------------
-%%% @spec get_status() -> TestStatus | {error,Reason} | no_tests_running
-%%% TestStatus = [StatusElem]
-%%% StatusElem = {current,TestCaseInfo} | {successful,Successful} |
-%%% {failed,Failed} | {skipped,Skipped} | {total,Total}
-%%% TestCaseInfo = {Suite,TestCase} | [{Suite,TestCase}]
-%%% Suite = atom()
-%%% TestCase = atom()
-%%% Successful = integer()
-%%% Failed = integer()
-%%% Skipped = {UserSkipped,AutoSkipped}
-%%% UserSkipped = integer()
-%%% AutoSkipped = integer()
-%%% Total = integer()
-%%% Reason = term()
-%%%
-%%% @doc Returns status of ongoing test. The returned list contains info about
-%%% which test case is currently executing (a list of cases when a
-%%% parallel test case group is executing), as well as counters for
-%%% successful, failed, skipped, and total test cases so far.
get_status() ->
case get_testdata(curr_tc) of
{ok,TestCase} ->
@@ -1167,176 +489,37 @@ get_testdata(Key) ->
{ok,Data}
end.
-%%%-----------------------------------------------------------------
-%%% @spec abort_current_testcase(Reason) -> ok | {error,ErrorReason}
-%%% Reason = term()
-%%% ErrorReason = no_testcase_running | parallel_group
-%%%
-%%% @doc <p>When calling this function, the currently executing test case will be aborted.
-%%% It is the user's responsibility to know for sure which test case is currently
-%%% executing. The function is therefore only safe to call from a function which
-%%% has been called (or synchronously invoked) by the test case.</p>
-%%%
-%%% <p><c>Reason</c>, the reason for aborting the test case, is printed
-%%% in the test case log.</p>
abort_current_testcase(Reason) ->
test_server_ctrl:abort_current_testcase(Reason).
-%%%-----------------------------------------------------------------
-%%% @spec get_event_mgr_ref() -> EvMgrRef
-%%% EvMgrRef = atom()
-%%%
-%%% @doc <p>Call this function in order to get a reference to the
-%%% CT event manager. The reference can be used to e.g. add
-%%% a user specific event handler while tests are running.
-%%% Example:
-%%% <c>gen_event:add_handler(ct:get_event_mgr_ref(), my_ev_h, [])</c></p>
get_event_mgr_ref() ->
?CT_EVMGR_REF.
-%%%-----------------------------------------------------------------
-%%% @spec encrypt_config_file(SrcFileName, EncryptFileName) ->
-%%% ok | {error,Reason}
-%%% SrcFileName = string()
-%%% EncryptFileName = string()
-%%% Reason = term()
-%%%
-%%% @doc <p>This function encrypts the source config file with DES3 and
-%%% saves the result in file <c>EncryptFileName</c>. The key,
-%%% a string, must be available in a text file named
-%%% <c>.ct_config.crypt</c> in the current directory, or the
-%%% home directory of the user (it is searched for in that order).</p>
-%%% <p>See the Common Test User's Guide for information about using
-%%% encrypted config files when running tests.</p>
-%%% <p>See the <c>crypto</c> application for details on DES3
-%%% encryption/decryption.</p>
encrypt_config_file(SrcFileName, EncryptFileName) ->
ct_config:encrypt_config_file(SrcFileName, EncryptFileName).
-%%%-----------------------------------------------------------------
-%%% @spec encrypt_config_file(SrcFileName, EncryptFileName, KeyOrFile) ->
-%%% ok | {error,Reason}
-%%% SrcFileName = string()
-%%% EncryptFileName = string()
-%%% KeyOrFile = {key,string()} | {file,string()}
-%%% Reason = term()
-%%%
-%%% @doc <p>This function encrypts the source config file with DES3 and
-%%% saves the result in the target file <c>EncryptFileName</c>.
-%%% The encryption key to use is either the value in
-%%% <c>{key,Key}</c> or the value stored in the file specified
-%%% by <c>{file,File}</c>.</p>
-%%% <p>See the Common Test User's Guide for information about using
-%%% encrypted config files when running tests.</p>
-%%% <p>See the <c>crypto</c> application for details on DES3
-%%% encryption/decryption.</p>
encrypt_config_file(SrcFileName, EncryptFileName, KeyOrFile) ->
ct_config:encrypt_config_file(SrcFileName, EncryptFileName, KeyOrFile).
-%%%-----------------------------------------------------------------
-%%% @spec decrypt_config_file(EncryptFileName, TargetFileName) ->
-%%% ok | {error,Reason}
-%%% EncryptFileName = string()
-%%% TargetFileName = string()
-%%% Reason = term()
-%%%
-%%% @doc <p>This function decrypts <c>EncryptFileName</c>, previously
-%%% generated with <c>encrypt_config_file/2/3</c>. The original
-%%% file contents is saved in the target file. The encryption key, a
-%%% string, must be available in a text file named
-%%% <c>.ct_config.crypt</c> in the current directory, or the
-%%% home directory of the user (it is searched for in that order).</p>
decrypt_config_file(EncryptFileName, TargetFileName) ->
ct_config:decrypt_config_file(EncryptFileName, TargetFileName).
-%%%-----------------------------------------------------------------
-%%% @spec decrypt_config_file(EncryptFileName, TargetFileName, KeyOrFile) ->
-%%% ok | {error,Reason}
-%%% EncryptFileName = string()
-%%% TargetFileName = string()
-%%% KeyOrFile = {key,string()} | {file,string()}
-%%% Reason = term()
-%%%
-%%% @doc <p>This function decrypts <c>EncryptFileName</c>, previously
-%%% generated with <c>encrypt_config_file/2/3</c>. The original
-%%% file contents is saved in the target file. The key must have the
-%%% the same value as that used for encryption.</p>
decrypt_config_file(EncryptFileName, TargetFileName, KeyOrFile) ->
ct_config:decrypt_config_file(EncryptFileName, TargetFileName, KeyOrFile).
-
-%%%-----------------------------------------------------------------
-%%% @spec add_config(Callback, Config) -> ok | {error, Reason}
-%%% Callback = atom()
-%%% Config = string()
-%%% Reason = term()
-%%%
-%%% @doc <p>This function loads configuration variables using the
-%%% given callback module and configuration string. Callback module
-%%% should be either loaded or present in the code part. Loaded
-%%% configuration variables can later be removed using
-%%% <c>remove_config/2</c> function.</p>
add_config(Callback, Config)->
ct_config:add_config(Callback, Config).
-%%%-----------------------------------------------------------------
-%%% @spec remove_config(Callback, Config) -> ok
-%%% Callback = atom()
-%%% Config = string()
-%%% Reason = term()
-%%%
-%%% @doc <p>This function removes configuration variables (together with
-%%% their aliases) which were loaded with specified callback module and
-%%% configuration string.</p>
remove_config(Callback, Config) ->
ct_config:remove_config(Callback, Config).
-%%%-----------------------------------------------------------------
-%%% @spec timetrap(Time) -> ok
-%%% Time = {hours,Hours} | {minutes,Mins} | {seconds,Secs} | Millisecs | infinity | Func
-%%% Hours = integer()
-%%% Mins = integer()
-%%% Secs = integer()
-%%% Millisecs = integer() | float()
-%%% Func = {M,F,A} | fun()
-%%% M = atom()
-%%% F = atom()
-%%% A = list()
-%%%
-%%% @doc <p>Use this function to set a new timetrap for the running test case.
-%%% If the argument is <c>Func</c>, the timetrap will be triggered
-%%% when this function returns. <c>Func</c> may also return a new
-%%% <c>Time</c> value, which in that case will be the value for the
-%%% new timetrap.</p>
timetrap(Time) ->
test_server:timetrap_cancel(),
test_server:timetrap(Time).
-%%%-----------------------------------------------------------------
-%%% @spec get_timetrap_info() -> {Time,Scale}
-%%% Time = integer() | infinity
-%%% Scale = true | false
-%%%
-%%% @doc <p>Read info about the timetrap set for the current test case.
-%%% <c>Scale</c> indicates if Common Test will attempt to automatically
-%%% compensate timetraps for runtime delays introduced by e.g. tools like
-%%% cover.</p>
get_timetrap_info() ->
test_server:get_timetrap_info().
-%%%-----------------------------------------------------------------
-%%% @spec sleep(Time) -> ok
-%%% Time = {hours,Hours} | {minutes,Mins} | {seconds,Secs} | Millisecs | infinity
-%%% Hours = integer()
-%%% Mins = integer()
-%%% Secs = integer()
-%%% Millisecs = integer() | float()
-%%%
-%%% @doc <p>This function, similar to <c>timer:sleep/1</c>, suspends the test
-%%% case for specified time. However, this function also multiplies
-%%% <c>Time</c> with the 'multiply_timetraps' value (if set) and under
-%%% certain circumstances also scales up the time automatically
-%%% if 'scale_timetraps' is set to true (default is false).</p>
sleep({hours,Hs}) ->
sleep(trunc(Hs * 1000 * 60 * 60));
sleep({minutes,Ms}) ->
@@ -1346,52 +529,12 @@ sleep({seconds,Ss}) ->
sleep(Time) ->
test_server:adjusted_sleep(Time).
-%%%-----------------------------------------------------------------
-%%% @spec notify(Name,Data) -> ok
-%%% Name = atom()
-%%% Data = term()
-%%%
-%%% @doc <p>Sends a asynchronous notification of type <c>Name</c> with
-%%% <c>Data</c>to the common_test event manager. This can later be
-%%% caught by any installed event manager. </p>
-%%% @see //stdlib/gen_event
notify(Name,Data) ->
ct_event:notify(Name, Data).
-%%%-----------------------------------------------------------------
-%%% @spec sync_notify(Name,Data) -> ok
-%%% Name = atom()
-%%% Data = term()
-%%%
-%%% @doc <p>Sends a synchronous notification of type <c>Name</c> with
-%%% <c>Data</c>to the common_test event manager. This can later be
-%%% caught by any installed event manager. </p>
-%%% @see //stdlib/gen_event
sync_notify(Name,Data) ->
ct_event:sync_notify(Name, Data).
-%%%-----------------------------------------------------------------
-%%% @spec break(Comment) -> ok | {error,Reason}
-%%% Comment = string()
-%%% Reason = {multiple_cases_running,TestCases} |
-%%% 'enable break with release_shell option'
-%%% TestCases = [atom()]
-%%%
-%%% @doc <p>This function will cancel any active timetrap and pause the
-%%% execution of the current test case until the user calls the
-%%% <c>continue/0</c> function. It gives the user the opportunity
-%%% to interact with the erlang node running the tests, e.g. for
-%%% debugging purposes or for manually executing a part of the
-%%% test case. If a parallel group is executing, <c>break/2</c>
-%%% should be called instead.</p>
-%%% <p>A cancelled timetrap will not be automatically
-%%% reactivated after the break, but must be started exlicitly with
-%%% <c>ct:timetrap/1</c></p>
-%%% <p>In order for the break/continue functionality to work,
-%%% Common Test must release the shell process controlling stdin.
-%%% This is done by setting the <c>release_shell</c> start option
-%%% to <c>true</c>. See the User's Guide for more information.</p>
-
break(Comment) ->
case {ct_util:get_testdata(starter),
ct_util:get_testdata(release_shell)} of
@@ -1414,19 +557,6 @@ break(Comment) ->
end
end.
-%%%-----------------------------------------------------------------
-%%% @spec break(TestCase, Comment) -> ok | {error,Reason}
-%%% TestCase = atom()
-%%% Comment = string()
-%%% Reason = 'test case not running' |
-%%% 'enable break with release_shell option'
-%%%
-%%% @doc <p>This function works the same way as <c>break/1</c>,
-%%% only the <c>TestCase</c> argument makes it possible to
-%%% pause a test case executing in a parallel group. The
-%%% <c>continue/1</c> function should be used to resume
-%%% execution of <c>TestCase</c>.</p>
-%%% <p>See <c>break/1</c> for more details.</p>
break(TestCase, Comment) ->
case {ct_util:get_testdata(starter),
ct_util:get_testdata(release_shell)} of
@@ -1453,23 +583,12 @@ break(TestCase, Comment) ->
end
end.
-%%%-----------------------------------------------------------------
-%%% @spec continue() -> ok
-%%%
-%%% @doc <p>This function must be called in order to continue after a
-%%% test case (not executing in a parallel group) has called
-%%% <c>break/1</c>.</p>
continue() ->
test_server:continue().
-%%%-----------------------------------------------------------------
-%%% @spec continue(TestCase) -> ok
-%%% TestCase = atom()
-%%%
-%%% @doc <p>This function must be called in order to continue after a
-%%% test case has called <c>break/2</c>. If the paused test case,
-%%% <c>TestCase</c>, executes in a parallel group, this
-%%% function - rather than <c>continue/0</c> - must be used
-%%% in order to let the test case proceed.</p>
continue(TestCase) ->
test_server:continue(TestCase).
+
+
+remaining_test_procs() ->
+ ct_util:remaining_test_procs().
diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl
index d48ae830bb..a10d939919 100644
--- a/lib/common_test/src/ct_config.erl
+++ b/lib/common_test/src/ct_config.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -81,6 +81,7 @@ start(Mode) ->
do_start(Parent) ->
process_flag(trap_exit,true),
+ ct_util:mark_process(),
register(ct_config_server,self()),
ct_util:create_table(?attr_table,bag,#ct_conf.key),
{ok,StartDir} = file:get_cwd(),
@@ -659,7 +660,7 @@ decrypt_config_file(EncryptFileName, TargetFileName, {key,Key}) ->
get_crypt_key_from_file(File) ->
case file:read_file(File) of
{ok,Bin} ->
- case catch string:tokens(binary_to_list(Bin), [$\n,$\r]) of
+ case catch string:lexemes(binary_to_list(Bin), [$\n, [$\r,$\n]]) of
[Key] ->
Key;
_ ->
@@ -693,7 +694,7 @@ get_crypt_key_from_file() ->
noent ->
Result;
_ ->
- case catch string:tokens(binary_to_list(Result), [$\n,$\r]) of
+ case catch string:lexemes(binary_to_list(Result), [$\n, [$\r,$\n]]) of
[Key] ->
io:format("~nCrypt key file: ~ts~n", [FullName]),
Key;
diff --git a/lib/common_test/src/ct_config_plain.erl b/lib/common_test/src/ct_config_plain.erl
index e72b55971b..7b68ac6597 100644
--- a/lib/common_test/src/ct_config_plain.erl
+++ b/lib/common_test/src/ct_config_plain.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -106,7 +106,7 @@ read_config_terms1({done,{eof,EL},_}, L, _, _) ->
read_config_terms1({done,{error,Info,EL},_}, L, _, _) ->
{error,{Info,{L,EL}}};
read_config_terms1({more,_}, L, Terms, Rest) ->
- case string:tokens(Rest, [$\n,$\r,$\t]) of
+ case string:lexemes(Rest, [$\n,[$\r,$\n],$\t]) of
[] ->
lists:reverse(Terms);
_ ->
diff --git a/lib/common_test/src/ct_conn_log_h.erl b/lib/common_test/src/ct_conn_log_h.erl
index cf0a228e1b..3e83020f45 100644
--- a/lib/common_test/src/ct_conn_log_h.erl
+++ b/lib/common_test/src/ct_conn_log_h.erl
@@ -224,7 +224,7 @@ now_to_time({_,_,MicroS}=Now) ->
{calendar:now_to_local_time(Now),MicroS}.
pretty_head({{{Y,Mo,D},{H,Mi,S}},MicroS},ConnMod,Text0) ->
- Text = string:to_upper(atom_to_list(ConnMod) ++ Text0),
+ Text = string:uppercase(atom_to_list(ConnMod) ++ Text0),
io_lib:format("= ~s ==== ~s-~s-~w::~s:~s:~s,~s ",
[Text,t(D),month(Mo),Y,t(H),t(Mi),t(S),
micro2milli(MicroS)]).
@@ -275,7 +275,7 @@ pad0(N,Str) ->
lists:duplicate(N-M,$0) ++ Str.
pad_char_end(N,Str,Char) ->
- case length(lists:flatten(Str)) of
+ case string:length(Str) of
M when M<N -> Str ++ lists:duplicate(N-M,Char);
_ -> Str
end.
diff --git a/lib/common_test/src/ct_cover.erl b/lib/common_test/src/ct_cover.erl
index c258516915..d286f20a4d 100644
--- a/lib/common_test/src/ct_cover.erl
+++ b/lib/common_test/src/ct_cover.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,11 +18,6 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test Framework code coverage support module.
-%%%
-%%% <p>This module exports help functions for performing code
-%%% coverage analysis.</p>
-
-module(ct_cover).
-export([get_spec/1, add_nodes/1, remove_nodes/1, cross_cover_analyse/2]).
@@ -31,16 +26,6 @@
-include_lib("kernel/include/file.hrl").
-%%%-----------------------------------------------------------------
-%%% @spec add_nodes(Nodes) -> {ok,StartedNodes} | {error,Reason}
-%%% Nodes = [atom()]
-%%% StartedNodes = [atom()]
-%%% Reason = cover_not_running | not_main_node
-%%%
-%%% @doc Add nodes to current cover test (only works if cover support
-%%% is active!). To have effect, this function should be called
-%%% from init_per_suite/1 before any actual tests are performed.
-%%%
add_nodes([]) ->
{ok,[]};
add_nodes(Nodes) ->
@@ -67,17 +52,6 @@ add_nodes(Nodes) ->
end
end.
-
-%%%-----------------------------------------------------------------
-%%% @spec remove_nodes(Nodes) -> ok | {error,Reason}
-%%% Nodes = [atom()]
-%%% Reason = cover_not_running | not_main_node
-%%%
-%%% @doc Remove nodes from current cover test. Call this function
-%%% to stop cover test on nodes previously added with add_nodes/1.
-%%% Results on the remote node are transferred to the Common Test
-%%% node.
-%%%
remove_nodes([]) ->
ok;
remove_nodes(Nodes) ->
@@ -103,25 +77,11 @@ remove_nodes(Nodes) ->
end
end.
-
-%%%-----------------------------------------------------------------
-%%% @spec cross_cover_analyse(Level,Tests) -> ok
-%%% Level = overview | details
-%%% Tests = [{Tag,Dir}]
-%%% Tag = atom()
-%%% Dir = string()
-%%%
-%%% @doc Accumulate cover results over multiple tests.
-%%% See the chapter about <seealso
-%%% marker="cover_chapter#cross_cover">cross cover
-%%% analysis</seealso> in the users's guide.
-%%%
cross_cover_analyse(Level,Tests) ->
test_server_ctrl:cross_cover_analyse(Level,Tests).
%%%-----------------------------------------------------------------
-%%% @hidden
%% Read cover specification file and return the parsed info.
%% -> CoverSpec: {CoverFile,Nodes,Import,Export,AppCoverInfo}
diff --git a/lib/common_test/src/ct_default_gl.erl b/lib/common_test/src/ct_default_gl.erl
index d1b52e5f4f..cf1bcc058d 100644
--- a/lib/common_test/src/ct_default_gl.erl
+++ b/lib/common_test/src/ct_default_gl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-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.
@@ -55,6 +55,7 @@ stop() ->
init([ParentGL]) ->
register(?MODULE, self()),
+ ct_util:mark_process(),
{ok,#{parent_gl_pid => ParentGL,
parent_gl_monitor => erlang:monitor(process,ParentGL)}}.
diff --git a/lib/common_test/src/ct_event.erl b/lib/common_test/src/ct_event.erl
index 1a0ee4f3cd..3689c6bc45 100644
--- a/lib/common_test/src/ct_event.erl
+++ b/lib/common_test/src/ct_event.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,14 +18,14 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test Framework Event Handler
+%%% doc Common Test Framework Event Handler
%%%
-%%% <p>This module implements an event handler that CT uses to
+%%% This module implements an event handler that CT uses to
%%% handle status and progress notifications during test runs.
%%% The notifications are handled locally (per node) and passed
%%% on to ct_master when CT runs in distributed mode. This
%%% module may be used as a template for other event handlers
-%%% that can be plugged in to handle local logging and reporting.</p>
+%%% that can be plugged in to handle local logging and reporting.
-module(ct_event).
-behaviour(gen_event).
@@ -137,6 +137,7 @@ is_alive() ->
%% this function is called to initialize the event handler.
%%--------------------------------------------------------------------
init(RecvPids) ->
+ ct_util:mark_process(),
%% RecvPids = [{RecvTag,Pid}]
{ok,#state{receivers=RecvPids}}.
diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl
index 6066470233..134ae0e1cc 100644
--- a/lib/common_test/src/ct_framework.erl
+++ b/lib/common_test/src/ct_framework.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,10 +18,10 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test Framework callback module.
+%%% Common Test Framework callback module.
%%%
-%%% <p>This module exports framework callback functions which are
-%%% called from the test_server.</p>
+%%% This module exports framework callback functions which are
+%%% called from the test_server.
-module(ct_framework).
@@ -42,7 +42,7 @@
-define(rev(L), lists:reverse(L)).
%%%-----------------------------------------------------------------
-%%% @spec init_tc(Mod,Func,Args) -> {ok,NewArgs} | {error,Reason} |
+%%% -spec init_tc(Mod,Func,Args) -> {ok,NewArgs} | {error,Reason} |
%%% {skip,Reason} | {auto_skip,Reason}
%%% Mod = atom()
%%% Func = atom()
@@ -50,7 +50,7 @@
%%% NewArgs = list()
%%% Reason = term()
%%%
-%%% @doc Test server framework callback, called by the test_server
+%%% Test server framework callback, called by the test_server
%%% when a new test case is started.
init_tc(_,{end_per_testcase_not_run,_},[Config]) ->
%% Testcase is completed (skipped or failed), but end_per_testcase
@@ -649,7 +649,7 @@ try_set_default(Name,Key,Info,Where) ->
%%%-----------------------------------------------------------------
-%%% @spec end_tc(Mod,Func,Args) -> {ok,NewArgs}| {error,Reason} |
+%%% -spec end_tc(Mod,Func,Args) -> {ok,NewArgs}| {error,Reason} |
%%% {skip,Reason} | {auto_skip,Reason}
%%% Mod = atom()
%%% Func = atom()
@@ -657,7 +657,7 @@ try_set_default(Name,Key,Info,Where) ->
%%% NewArgs = list()
%%% Reason = term()
%%%
-%%% @doc Test server framework callback, called by the test_server
+%%% Test server framework callback, called by the test_server
%%% when a test case is finished.
end_tc(Mod, Fun, Args) ->
%% Have to keep end_tc/3 for backwards compatibility issues
@@ -903,15 +903,15 @@ tag(_Other) ->
ok.
%%%-----------------------------------------------------------------
-%%% @spec error_notification(Mod,Func,Args,Error) -> ok
+%%% -spec error_notification(Mod,Func,Args,Error) -> ok
%%% Mod = atom()
%%% Func = atom()
%%% Args = list()
%%% Error = term()
%%%
-%%% @doc This function is called as the result of testcase
-%%% <code>Func</code> in suite <code>Mod</code> crashing.
-%%% <code>Error</code> specifies the reason for failing.
+%%% This function is called as the result of testcase
+%%% Func in suite Mod crashing.
+%%% Error specifies the reason for failing.
error_notification(Mod,Func,_Args,{Error,Loc}) ->
ErrorSpec = case Error of
{What={_E,_R},Trace} when is_list(Trace) ->
@@ -921,9 +921,10 @@ error_notification(Mod,Func,_Args,{Error,Loc}) ->
end,
ErrorStr = case ErrorSpec of
{badmatch,Descr} ->
- Descr1 = lists:flatten(io_lib:format("~tP",[Descr,10])),
- if length(Descr1) > 50 ->
- Descr2 = string:substr(Descr1,1,50),
+ Descr1 = io_lib:format("~tP",[Descr,10]),
+ DescrLength = string:length(Descr1),
+ if DescrLength > 50 ->
+ Descr2 = string:slice(Descr1,0,50),
io_lib:format("{badmatch,~ts...}",[Descr2]);
true ->
io_lib:format("{badmatch,~ts}",[Descr1])
@@ -1048,11 +1049,11 @@ group_or_func(Func, _Config) ->
Func.
%%%-----------------------------------------------------------------
-%%% @spec get_suite(Mod, Func) -> Tests
+%%% -spec get_suite(Mod, Func) -> Tests
%%%
-%%% @doc Called from test_server for every suite (<code>Func==all</code>)
-%%% and every test case. If the former, all test cases in the suite
-%%% should be returned.
+%%% Called from test_server for every suite (Func==all)
+%%% and every test case. If the former, all test cases in the suite
+%%% should be returned.
get_suite(Mod, all) ->
case catch apply(Mod, groups, []) of
@@ -1354,7 +1355,7 @@ end_per_group(GroupName, _) ->
ok.
%%%-----------------------------------------------------------------
-%%% @spec report(What,Data) -> ok
+%%% -spec report(What,Data) -> ok
report(What,Data) ->
case What of
loginfo ->
@@ -1518,14 +1519,14 @@ add_to_stats(Result) ->
ct_util:update_testdata(stats, Update).
%%%-----------------------------------------------------------------
-%%% @spec warn(What) -> true | false
+%%% -spec warn(What) -> true | false
warn(What) when What==nodes; What==processes ->
false;
warn(_What) ->
true.
%%%-----------------------------------------------------------------
-%%% @spec add_data_dir(File0, Config) -> File1
+%%% -spec add_data_dir(File0, Config) -> File1
add_data_dir(File,Config) when is_atom(File) ->
add_data_dir(atom_to_list(File),Config);
@@ -1544,7 +1545,7 @@ add_data_dir(File,Config) when is_list(File) ->
end.
%%%-----------------------------------------------------------------
-%%% @spec get_logopts() -> [LogOpt]
+%%% -spec get_logopts() -> [LogOpt]
get_logopts() ->
case ct_util:get_testdata(logopts) of
undefined ->
@@ -1554,12 +1555,12 @@ get_logopts() ->
end.
%%%-----------------------------------------------------------------
-%%% @spec format_comment(Comment) -> HtmlComment
+%%% -spec format_comment(Comment) -> HtmlComment
format_comment(Comment) ->
"<font color=\"green\">" ++ Comment ++ "</font>".
%%%-----------------------------------------------------------------
-%%% @spec get_html_wrapper(TestName, PrintLabel, Cwd) -> Header
+%%% -spec get_html_wrapper(TestName, PrintLabel, Cwd) -> Header
get_html_wrapper(TestName, PrintLabel, Cwd, TableCols) ->
get_html_wrapper(TestName, PrintLabel, Cwd, TableCols, utf8).
@@ -1567,6 +1568,6 @@ get_html_wrapper(TestName, PrintLabel, Cwd, TableCols, Encoding) ->
ct_logs:get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols, Encoding).
%%%-----------------------------------------------------------------
-%%% @spec get_log_dir() -> {ok,LogDir}
+%%% -spec get_log_dir() -> {ok,LogDir}
get_log_dir() ->
ct_logs:get_log_dir(true).
diff --git a/lib/common_test/src/ct_ftp.erl b/lib/common_test/src/ct_ftp.erl
index 8effb06e7e..93d1f88041 100644
--- a/lib/common_test/src/ct_ftp.erl
+++ b/lib/common_test/src/ct_ftp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,12 +18,6 @@
%% %CopyrightEnd%
%%
-%%% @doc FTP client module (based on the FTP support of the INETS application).
-%%%
-%%% @type connection() = handle() | ct:target_name()
-%%% @type handle() = ct_gen_conn:handle(). Handle for a specific
-%%% ftp connection.
-
-module(ct_ftp).
%% API
@@ -42,76 +36,14 @@
%%%=================================================================
%%% API
-%%%-----------------------------------------------------------------
-%%% @spec put(KeyOrName,LocalFile,RemoteFile) -> ok | {error,Reason}
-%%% KeyOrName = Key | Name
-%%% Key = atom()
-%%% Name = ct:target_name()
-%%% LocalFile = string()
-%%% RemoteFile = string()
-%%%
-%%% @doc Open a ftp connection and send a file to the remote host.
-%%%
-%%% <p><code>LocalFile</code> and <code>RemoteFile</code> must be
-%%% absolute paths.</p>
-%%%
-%%% <p>If the target host is a "special" node, the ftp address must be
-%%% specified in the config file like this:</p>
-%%% <pre>
-%%% {node,[{ftp,IpAddr}]}.</pre>
-%%%
-%%% <p>If the target host is something else, e.g. a unix host, the
-%%% config file must also include the username and password (both
-%%% strings):</p>
-%%% <pre>
-%%% {unix,[{ftp,IpAddr},
-%%% {username,Username},
-%%% {password,Password}]}.</pre>
-%%% @see ct:require/2
put(KeyOrName,LocalFile,RemoteFile) ->
Fun = fun(Ftp) -> send(Ftp,LocalFile,RemoteFile) end,
open_and_do(KeyOrName,Fun).
-%%%-----------------------------------------------------------------
-%%% @spec get(KeyOrName,RemoteFile,LocalFile) -> ok | {error,Reason}
-%%% KeyOrName = Key | Name
-%%% Key = atom()
-%%% Name = ct:target_name()
-%%% RemoteFile = string()
-%%% LocalFile = string()
-%%%
-%%% @doc Open a ftp connection and fetch a file from the remote host.
-%%%
-%%% <p><code>RemoteFile</code> and <code>LocalFile</code> must be
-%%% absolute paths.</p>
-%%%
-%%% <p>The config file must be as for put/3.</p>
-%%% @see put/3
-%%% @see ct:require/2
get(KeyOrName,RemoteFile,LocalFile) ->
Fun = fun(Ftp) -> recv(Ftp,RemoteFile,LocalFile) end,
open_and_do(KeyOrName,Fun).
-
-%%%-----------------------------------------------------------------
-%%% @spec open(KeyOrName) -> {ok,Handle} | {error,Reason}
-%%% KeyOrName = Key | Name
-%%% Key = atom()
-%%% Name = ct:target_name()
-%%% Handle = handle()
-%%%
-%%% @doc Open an FTP connection to the specified node.
-%%% <p>You can open one connection for a particular <code>Name</code> and
-%%% use the same name as reference for all subsequent operations. If you
-%%% want the connection to be associated with <code>Handle</code> instead
-%%% (in case you need to open multiple connections to a host for example),
-%%% simply use <code>Key</code>, the configuration variable name, to
-%%% specify the target. Note that a connection that has no associated target
-%%% name can only be closed with the handle value.</p>
-%%%
-%%% <p>See <c>ct:require/2</c> for how to create a new <c>Name</c></p>
-%%%
-%%% @see ct:require/2
open(KeyOrName) ->
case ct_util:get_key_from_name(KeyOrName) of
{ok,node} ->
@@ -152,25 +84,9 @@ open(KeyOrName,Username,Password) ->
ct_gen_conn:start(KeyOrName,full_addr(Addr),{Username,Password},?MODULE)
end.
-
-%%%-----------------------------------------------------------------
-%%% @spec send(Connection,LocalFile) -> ok | {error,Reason}
-%%%
-%%% @doc Send a file over FTP.
-%%% <p>The file will get the same name on the remote host.</p>
-%%% @see send/3
send(Connection,LocalFile) ->
send(Connection,LocalFile,filename:basename(LocalFile)).
-%%%-----------------------------------------------------------------
-%%% @spec send(Connection,LocalFile,RemoteFile) -> ok | {error,Reason}
-%%% Connection = connection()
-%%% LocalFile = string()
-%%% RemoteFile = string()
-%%%
-%%% @doc Send a file over FTP.
-%%%
-%%% <p>The file will be named <code>RemoteFile</code> on the remote host.</p>
send(Connection,LocalFile,RemoteFile) ->
case get_handle(Connection) of
{ok,Pid} ->
@@ -179,24 +95,9 @@ send(Connection,LocalFile,RemoteFile) ->
Error
end.
-%%%-----------------------------------------------------------------
-%%% @spec recv(Connection,RemoteFile) -> ok | {error,Reason}
-%%%
-%%% @doc Fetch a file over FTP.
-%%% <p>The file will get the same name on the local host.</p>
-%%% @see recv/3
recv(Connection,RemoteFile) ->
recv(Connection,RemoteFile,filename:basename(RemoteFile)).
-%%%-----------------------------------------------------------------
-%%% @spec recv(Connection,RemoteFile,LocalFile) -> ok | {error,Reason}
-%%% Connection = connection()
-%%% RemoteFile = string()
-%%% LocalFile = string()
-%%%
-%%% @doc Fetch a file over FTP.
-%%%
-%%% <p>The file will be named <code>LocalFile</code> on the local host.</p>
recv(Connection,RemoteFile,LocalFile) ->
case get_handle(Connection) of
{ok,Pid} ->
@@ -205,12 +106,6 @@ recv(Connection,RemoteFile,LocalFile) ->
Error
end.
-%%%-----------------------------------------------------------------
-%%% @spec cd(Connection,Dir) -> ok | {error,Reason}
-%%% Connection = connection()
-%%% Dir = string()
-%%%
-%%% @doc Change directory on remote host.
cd(Connection,Dir) ->
case get_handle(Connection) of
{ok,Pid} ->
@@ -219,13 +114,6 @@ cd(Connection,Dir) ->
Error
end.
-%%%-----------------------------------------------------------------
-%%% @spec ls(Connection,Dir) -> {ok,Listing} | {error,Reason}
-%%% Connection = connection()
-%%% Dir = string()
-%%% Listing = string()
-%%%
-%%% @doc List the directory Dir.
ls(Connection,Dir) ->
case get_handle(Connection) of
{ok,Pid} ->
@@ -234,12 +122,6 @@ ls(Connection,Dir) ->
Error
end.
-%%%-----------------------------------------------------------------
-%%% @spec type(Connection,Type) -> ok | {error,Reason}
-%%% Connection = connection()
-%%% Type = ascii | binary
-%%%
-%%% @doc Change file transfer type
type(Connection,Type) ->
case get_handle(Connection) of
{ok,Pid} ->
@@ -248,12 +130,6 @@ type(Connection,Type) ->
Error
end.
-%%%-----------------------------------------------------------------
-%%% @spec delete(Connection,File) -> ok | {error,Reason}
-%%% Connection = connection()
-%%% File = string()
-%%%
-%%% @doc Delete a file on remote host
delete(Connection,File) ->
case get_handle(Connection) of
{ok,Pid} ->
@@ -262,11 +138,6 @@ delete(Connection,File) ->
Error
end.
-%%%-----------------------------------------------------------------
-%%% @spec close(Connection) -> ok | {error,Reason}
-%%% Connection = connection()
-%%%
-%%% @doc Close the FTP connection.
close(Connection) ->
case get_handle(Connection) of
{ok,Pid} ->
@@ -279,21 +150,20 @@ close(Connection) ->
%%%=================================================================
%%% Callback functions
-%% @hidden
init(KeyOrName,{IP,Port},{Username,Password}) ->
case ftp_connect(IP,Port,Username,Password) of
{ok,FtpPid} ->
log(heading(init,KeyOrName),
"Opened ftp connection:\nIP: ~tp\nUsername: ~tp\nPassword: ~p\n",
- [IP,Username,lists:duplicate(length(Password),$*)]),
+ [IP,Username,lists:duplicate(string:length(Password),$*)]),
{ok,FtpPid,#state{ftp_pid=FtpPid,target_name=KeyOrName}};
Error ->
Error
end.
ftp_connect(IP,Port,Username,Password) ->
- _ = inets:start(),
- case inets:start(ftpc,[{host,IP},{port,Port}]) of
+ _ = ftp:start(),
+ case ftp:start_service([{host,IP},{port,Port}]) of
{ok,FtpPid} ->
case ftp:user(FtpPid,Username,Password) of
ok ->
@@ -305,7 +175,6 @@ ftp_connect(IP,Port,Username,Password) ->
{error,{open,Reason}}
end.
-%% @hidden
handle_msg({send,LocalFile,RemoteFile},State) ->
log(heading(send,State#state.target_name),
"LocalFile: ~tp\nRemoteFile: ~tp\n",[LocalFile,RemoteFile]),
@@ -333,15 +202,13 @@ handle_msg({delete,File},State) ->
Result = ftp:delete(State#state.ftp_pid,File),
{Result,State}.
-%% @hidden
reconnect(_Addr,_State) ->
{error,no_reconnection_of_ftp}.
-%% @hidden
terminate(FtpPid,State) ->
log(heading(terminate,State#state.target_name),
"Closing FTP connection.\nHandle: ~p\n",[FtpPid]),
- inets:stop(ftpc,FtpPid).
+ ftp:stop_service(FtpPid).
%%%=================================================================
diff --git a/lib/common_test/src/ct_gen_conn.erl b/lib/common_test/src/ct_gen_conn.erl
index badb7c52ae..1ab9946d96 100644
--- a/lib/common_test/src/ct_gen_conn.erl
+++ b/lib/common_test/src/ct_gen_conn.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,9 +18,9 @@
%% %CopyrightEnd%
%%
-%%% @doc Generic connection owner process.
+%%% Generic connection owner process.
%%%
-%%% @type handle() = pid(). A handle for using a connection implemented
+%%% -type handle() = pid(). A handle for using a connection implemented
%%% with ct_gen_conn.erl.
-module(ct_gen_conn).
@@ -48,7 +48,7 @@
ct_util_server}).
%%%-----------------------------------------------------------------
-%%% @spec start(Address,InitData,CallbackMod,Opts) ->
+%%% -spec start(Address,InitData,CallbackMod,Opts) ->
%%% {ok,Handle} | {error,Reason}
%%% Name = term()
%%% CallbackMod = atom()
@@ -58,57 +58,52 @@
%%% Opt = {name,Name} | {use_existing_connection,boolean()} |
%%% {reconnect,boolean()} | {forward_messages,boolean()}
%%%
-%%% @doc Open a connection and start the generic connection owner process.
+%%% Open a connection and start the generic connection owner process.
%%%
-%%% <p>The <code>CallbackMod</code> is a specific callback module for
+%%% The CallbackMod is a specific callback module for
%%% each type of connection (e.g. telnet, ftp,...). It must export the
-%%% function <code>init/3</code> which takes the arguments
-%%% <code>Name</code>, <code>Addresse</code>) and
-%%% <code>InitData</code> and returna
-%%% <code>{ok,ConnectionPid,State}</code> or
-%%% <code>{error,Reason}</code>.</p>
+%%% function init/3 which takes the arguments
+%%% Name, Addresse) and
+%%% InitData and returna
+%%% {ok,ConnectionPid,State} or
+%%% {error,Reason}.
%%%
-%%% If no name is given, the <code>Name</code> argument in init/3 will
-%%% have the value <code>undefined</code>.
+%%% If no name is given, the Name argument in init/3 will
+%%% have the value undefined.
%%%
%%% The callback modules must also export
-%%% ```
+%%%
%%% handle_msg(Msg,From,State) -> {reply,Reply,State} |
%%% {noreply,State} |
%%% {stop,Reply,State}
%%% terminate(ConnectionPid,State) -> term()
%%% close(Handle) -> term()
-%%% '''
%%%
-%%% The <code>close/1</code> callback function is actually a callback
+%%% The close/1 callback function is actually a callback
%%% for ct_util, for closing registered connections when
-%%% ct_util_server is terminated. <code>Handle</code> is the Pid of
+%%% ct_util_server is terminated. Handle is the Pid of
%%% the ct_gen_conn process.
%%%
-%%% If option <code>reconnect</code> is <code>true</code>, then the
+%%% If option reconnect is true, then the
%%% callback must also export
-%%% ```
+%%%
%%% reconnect(Address,State) -> {ok,ConnectionPid,State}
-%%% '''
%%%
-%%% If option <code>forward_messages</code> is <ocde>true</code>, then
+%%% If option forward_messages is <ocde>true, then
%%% the callback must also export
-%%% ```
+%%%
%%% handle_msg(Msg,State) -> {noreply,State} | {stop,State}
-%%% '''
%%%
%%% An old interface still exists. This is used by ct_telnet, ct_ftp
%%% and ct_ssh. The start function then has an explicit
-%%% <code>Name</code> argument, and no <code>Opts</code> argument. The
+%%% Name argument, and no Opts argument. The
%%% callback must export:
%%%
-%%% ```
%%% init(Name,Address,InitData) -> {ok,ConnectionPid,State}
%%% handle_msg(Msg,State) -> {Reply,State}
%%% reconnect(Address,State) -> {ok,ConnectionPid,State}
%%% terminate(ConnectionPid,State) -> term()
%%% close(Handle) -> term()
-%%% '''
%%%
start(Address,InitData,CallbackMod,Opts) when is_list(Opts) ->
do_start(Address,InitData,CallbackMod,Opts);
@@ -116,79 +111,81 @@ start(Name,Address,InitData,CallbackMod) ->
do_start(Address,InitData,CallbackMod,[{name,Name},{old,true}]).
%%%-----------------------------------------------------------------
-%%% @spec stop(Handle) -> ok
+%%% -spec stop(Handle) -> ok
%%% Handle = handle()
%%%
-%%% @doc Close the connection and stop the process managing it.
+%%% Close the connection and stop the process managing it.
stop(Handle) ->
call(Handle,stop,5000).
%%%-----------------------------------------------------------------
-%%% @spec get_conn_pid(Handle) -> ok
+%%% -spec get_conn_pid(Handle) -> ok
%%% Handle = handle()
%%%
-%%% @doc Return the connection pid associated with Handle
+%%% Return the connection pid associated with Handle
get_conn_pid(Handle) ->
call(Handle,get_conn_pid).
%%%-----------------------------------------------------------------
-%%% @spec log(Heading,Format,Args) -> ok
+%%% -spec log(Heading,Format,Args) -> ok
%%%
-%%% @doc Log activities on the current connection (tool-internal use only).
-%%% @see ct_logs:log/3
+%%% Log activities on the current connection (tool-internal use only).
+%%% See ct_logs:log/3
log(Heading,Format,Args) ->
log(log,[Heading,Format,Args]).
%%%-----------------------------------------------------------------
-%%% @spec start_log(Heading) -> ok
+%%% -spec start_log(Heading) -> ok
%%%
-%%% @doc Log activities on the current connection (tool-internal use only).
-%%% @see ct_logs:start_log/1
+%%% Log activities on the current connection (tool-internal use only).
+%%% See ct_logs:start_log/1
start_log(Heading) ->
log(start_log,[Heading]).
%%%-----------------------------------------------------------------
-%%% @spec cont_log(Format,Args) -> ok
+%%% -spec cont_log(Format,Args) -> ok
%%%
-%%% @doc Log activities on the current connection (tool-internal use only).
-%%% @see ct_logs:cont_log/2
+%%% Log activities on the current connection (tool-internal use only).
+%%% See ct_logs:cont_log/2
cont_log(Format,Args) ->
log(cont_log,[Format,Args]).
%%%-----------------------------------------------------------------
-%%% @spec cont_log_no_timestamp(Format,Args) -> ok
+%%% -spec cont_log_no_timestamp(Format,Args) -> ok
%%%
-%%% @doc Log activities on the current connection (tool-internal use only).
-%%% @see ct_logs:cont_log/2
+%%% Log activities on the current connection (tool-internal use only).
+%%% See ct_logs:cont_log/2
cont_log_no_timestamp(Format,Args) ->
log(cont_log_no_timestamp,[Format,Args]).
%%%-----------------------------------------------------------------
-%%% @spec end_log() -> ok
+%%% -spec end_log() -> ok
%%%
-%%% @doc Log activities on the current connection (tool-internal use only).
-%%% @see ct_logs:end_log/0
+%%% Log activities on the current connection (tool-internal use only).
+%%% See ct_logs:end_log/0
end_log() ->
log(end_log,[]).
%%%-----------------------------------------------------------------
-%%% @spec do_within_time(Fun,Timeout) -> FunResult | {error,Reason}
+%%% -spec do_within_time(Fun,Timeout) -> FunResult | {error,Reason}
%%% Fun = function()
%%% Timeout = integer()
%%%
-%%% @doc Execute a function within a limited time (tool-internal use only).
+%%% Execute a function within a limited time (tool-internal use only).
%%%
-%%% <p>Execute the given <code>Fun</code>, but interrupt if it takes
-%%% more than <code>Timeout</code> milliseconds.</p>
+%%% Execute the given Fun, but interrupt if it takes
+%%% more than Timeout milliseconds.
%%%
-%%% <p>The execution is also interrupted if the connection is
-%%% closed.</p>
+%%% The execution is also interrupted if the connection is
+%%% closed.
do_within_time(Fun,Timeout) ->
Self = self(),
Silent = get(silent),
- TmpPid = spawn_link(fun() -> put(silent,Silent),
- R = Fun(),
- Self ! {self(),R}
+ TmpPid = spawn_link(fun() ->
+ ct_util:mark_process(),
+ put(silent,Silent),
+ R = Fun(),
+ Self ! {self(),R}
end),
ConnPid = get(conn_pid),
receive
@@ -301,6 +298,7 @@ return({To,Ref},Result) ->
init_gen(Parent,Opts) ->
process_flag(trap_exit,true),
+ ct_util:mark_process(),
put(silent,false),
try (Opts#gen_opts.callback):init(Opts#gen_opts.name,
Opts#gen_opts.address,
diff --git a/lib/common_test/src/ct_groups.erl b/lib/common_test/src/ct_groups.erl
index 2235365a0e..d867069dce 100644
--- a/lib/common_test/src/ct_groups.erl
+++ b/lib/common_test/src/ct_groups.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,11 +18,9 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test Framework callback module.
-%%%
-%%% <p>This module contains CT internal help functions for searching
-%%% through groups specification trees and producing resulting
-%%% tests.</p>
+%%% This module contains CT internal help functions for searching
+%%% through groups specification trees and producing resulting
+%%% tests.
-module(ct_groups).
diff --git a/lib/common_test/src/ct_hooks.erl b/lib/common_test/src/ct_hooks.erl
index f0592a40be..49587b3edd 100644
--- a/lib/common_test/src/ct_hooks.erl
+++ b/lib/common_test/src/ct_hooks.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,10 +18,6 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test Framework test execution control module.
-%%%
-%%% <p>This module is a proxy for calling and handling common test hooks.</p>
-
-module(ct_hooks).
%% API Exports
@@ -47,14 +43,12 @@
%% API Functions
%% -------------------------------------------------------------------------
-%% @doc Called before any suites are started
-spec init(State :: term()) -> ok |
{fail, Reason :: term()}.
init(Opts) ->
call(get_builtin_hooks(Opts) ++ get_new_hooks(Opts, undefined),
ok, init, []).
-%% @doc Called after all suites are done.
-spec terminate(Hooks :: term()) ->
ok.
terminate(Hooks) ->
@@ -63,8 +57,6 @@ terminate(Hooks) ->
ct_hooks_terminate_dummy, terminate, Hooks),
ok.
-%% @doc Called as each test case is started. This includes all configuration
-%% tests.
-spec init_tc(Mod :: atom(),
FuncSpec :: atom() |
{ConfigFunc :: init_per_testcase | end_per_testcase,
@@ -104,8 +96,6 @@ init_tc(Mod, {end_per_testcase,TC}, Config) ->
init_tc(Mod, TC = error_in_suite, Config) ->
call(fun call_generic_fallback/3, Config, [pre_init_per_testcase, Mod, TC]).
-%% @doc Called as each test case is completed. This includes all configuration
-%% tests.
-spec end_tc(Mod :: atom(),
FuncSpec :: atom() |
{ConfigFunc :: init_per_testcase | end_per_testcase,
@@ -233,8 +223,7 @@ call([{Hook, call_id, NextFun} | Rest], Config, Meta, Hooks) ->
Rest ++ [{NewId, call_init}, {NewId,NextFun}]}
end,
call(resort(NewRest,NewHooks,Meta), Config, Meta, NewHooks)
- catch Error:Reason ->
- Trace = erlang:get_stacktrace(),
+ catch Error:Reason:Trace ->
ct_logs:log("Suite Hook","Failed to start a CTH: ~tp:~tp",
[Error,{Reason,Trace}]),
call([], {fail,"Failed to start CTH"
@@ -422,8 +411,7 @@ catch_apply(M,F,A, Default, Fallback) ->
catch_apply(M,F,A) ->
try
erlang:apply(M,F,A)
- catch _:Reason ->
- Trace = erlang:get_stacktrace(),
+ catch _:Reason:Trace ->
ct_logs:log("Suite Hook","Call to CTH failed: ~w:~tp",
[error,{Reason,Trace}]),
throw({error_in_cth_call,
diff --git a/lib/common_test/src/ct_hooks_lock.erl b/lib/common_test/src/ct_hooks_lock.erl
index fea298e535..be50a33e01 100644
--- a/lib/common_test/src/ct_hooks_lock.erl
+++ b/lib/common_test/src/ct_hooks_lock.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,11 +18,6 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test Framework test execution control module.
-%%%
-%%% <p>This module is a proxy for calling and handling locks in
-%%% common test hooks.</p>
-
-module(ct_hooks_lock).
-behaviour(gen_server).
@@ -42,7 +37,6 @@
%%% API
%%%===================================================================
-%% @doc Starts the server
start(Id) ->
case gen_server:start({local, ?SERVER}, ?MODULE, Id, []) of
{error,{already_started, Pid}} ->
@@ -76,11 +70,10 @@ release() ->
%%% gen_server callbacks
%%%===================================================================
-%% @doc Initiates the server
init(Id) ->
+ ct_util:mark_process(),
{ok, #state{ id = Id }}.
-%% @doc Handling call messages
handle_call({stop,Id}, _From, #state{ id = Id, requests = Reqs } = State) ->
_ = [gen_server:reply(Req, locker_stopped) || {Req,_ReqId} <- Reqs],
{stop, normal, stopped, State};
@@ -107,11 +100,9 @@ handle_call({release, Pid}, _From,
handle_call({release, _Pid}, _From, State) ->
{reply, not_locked, State}.
-%% @doc Handling cast messages
handle_cast(_Msg, State) ->
{noreply, State}.
-%% @doc Handling all non call/cast messages
handle_info({'DOWN',Ref,process,Pid,_},
#state{ locked = {true, Pid, Ref},
requests = [{NextFrom,NextPid}|Rest] } = State) ->
@@ -120,11 +111,9 @@ handle_info({'DOWN',Ref,process,Pid,_},
{noreply,State#state{ locked = {true, NextPid, NextRef},
requests = Rest } }.
-%% @doc This function is called by a gen_server when it is about to terminate.
terminate(_Reason, _State) ->
ok.
-%% @doc Convert process state when code is changed
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl
index ba7660fe6a..07a1693d5d 100644
--- a/lib/common_test/src/ct_logs.erl
+++ b/lib/common_test/src/ct_logs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,14 +18,12 @@
%% %CopyrightEnd%
%%
-%%% @doc Logging functionality for Common Test Framework.
+%%% Logging functionality for Common Test Framework.
%%%
-%%% <p>This module implements
-%%% <ul>
-%%% <li>Internal logging of activities in Common Test Framework</li>
-%%% <li>Compilation of test results into index pages on several levels</li>
-%%% </ul>
-%%% </p>
+%%% This module implements:
+%%%
+%%% Internal logging of activities in Common Test Framework, and
+%%% Compilation of test results into index pages on several levels
-module(ct_logs).
@@ -84,17 +82,17 @@
tests = []}).
%%%-----------------------------------------------------------------
-%%% @spec init(Mode, Verbosity) -> Result
+%%% -spec init(Mode, Verbosity) -> Result
%%% Mode = normal | interactive
%%% Result = {StartTime,LogDir}
%%% StartTime = term()
%%% LogDir = string()
%%%
-%%% @doc Initiate the logging mechanism (tool-internal use only).
+%%% Initiate the logging mechanism (tool-internal use only).
%%%
-%%% <p>This function is called by ct_util.erl when testing is
-%%% started. A new directory named ct_run.&lt;timestamp&gt; is created
-%%% and all logs are stored under this directory.</p>
+%%% This function is called by ct_util.erl when testing is
+%%% started. A new directory named ct_run.<timestamp> is created
+%%% and all logs are stored under this directory.
%%%
init(Mode, Verbosity) ->
Self = self(),
@@ -129,9 +127,9 @@ datestr_from_dirname([]) ->
"".
%%%-----------------------------------------------------------------
-%%% @spec close(Info, StartDir) -> ok
+%%% -spec close(Info, StartDir) -> ok
%%%
-%%% @doc Create index pages with test results and close the CT Log
+%%% Create index pages with test results and close the CT Log
%%% (tool-internal use only).
close(Info, StartDir) ->
%% close executes on the ct_util process, not on the logger process
@@ -204,22 +202,22 @@ close(Info, StartDir) ->
ok.
%%%-----------------------------------------------------------------
-%%% @spec set_stylesheet(TC,SSFile) -> ok
+%%% -spec set_stylesheet(TC,SSFile) -> ok
set_stylesheet(TC, SSFile) ->
cast({set_stylesheet,TC,SSFile}).
%%%-----------------------------------------------------------------
-%%% @spec clear_stylesheet(TC) -> ok
+%%% -spec clear_stylesheet(TC) -> ok
clear_stylesheet(TC) ->
cast({clear_stylesheet,TC}).
%%%-----------------------------------------------------------------
-%%% @spec get_log_dir() -> {ok,Dir} | {error,Reason}
+%%% -spec get_log_dir() -> {ok,Dir} | {error,Reason}
get_log_dir() ->
get_log_dir(false).
%%%-----------------------------------------------------------------
-%%% @spec get_log_dir(ReturnAbsName) -> {ok,Dir} | {error,Reason}
+%%% -spec get_log_dir(ReturnAbsName) -> {ok,Dir} | {error,Reason}
get_log_dir(ReturnAbsName) ->
case call({get_log_dir,ReturnAbsName}) of
{error,does_not_exist} when ReturnAbsName == true ->
@@ -278,58 +276,58 @@ get_format_args(Content) ->
end, Content).
%%%-----------------------------------------------------------------
-%%% @spec init_tc(RefreshLog) -> ok
+%%% -spec init_tc(RefreshLog) -> ok
%%%
-%%% @doc Test case initiation (tool-internal use only).
+%%% Test case initiation (tool-internal use only).
%%%
-%%% <p>This function is called by ct_framework:init_tc/3</p>
+%%% This function is called by ct_framework:init_tc/3
init_tc(RefreshLog) ->
call({init_tc,self(),group_leader(),RefreshLog}),
tc_io_format(group_leader(), xhtml("", "<br />"), []),
ok.
%%%-----------------------------------------------------------------
-%%% @spec end_tc(TCPid) -> ok
+%%% -spec end_tc(TCPid) -> ok
%%%
-%%% @doc Test case clean up (tool-internal use only).
+%%% Test case clean up (tool-internal use only).
%%%
-%%% <p>This function is called by ct_framework:end_tc/3</p>
+%%% This function is called by ct_framework:end_tc/3
end_tc(TCPid) ->
%% use call here so that the TC process will wait and receive
%% possible exit signals from ct_logs before end_tc returns ok
call({end_tc,TCPid}).
%%%-----------------------------------------------------------------
-%%% @spec register_groupleader(Pid,GroupLeader) -> ok
+%%% -spec register_groupleader(Pid,GroupLeader) -> ok
%%%
-%%% @doc To enable logging to a group leader (tool-internal use only).
+%%% To enable logging to a group leader (tool-internal use only).
%%%
-%%% <p>This function is called by ct_framework:report/2</p>
+%%% This function is called by ct_framework:report/2
register_groupleader(Pid,GroupLeader) ->
call({register_groupleader,Pid,GroupLeader}),
ok.
%%%-----------------------------------------------------------------
-%%% @spec unregister_groupleader(Pid) -> ok
+%%% -spec unregister_groupleader(Pid) -> ok
%%%
-%%% @doc To disable logging to a group leader (tool-internal use only).
+%%% To disable logging to a group leader (tool-internal use only).
%%%
-%%% <p>This function is called by ct_framework:report/2</p>
+%%% This function is called by ct_framework:report/2
unregister_groupleader(Pid) ->
call({unregister_groupleader,Pid}),
ok.
%%%-----------------------------------------------------------------
-%%% @spec log(Heading,Format,Args) -> ok
+%%% -spec log(Heading,Format,Args) -> ok
%%%
-%%% @doc Log internal activity (tool-internal use only).
+%%% Log internal activity (tool-internal use only).
%%%
-%%% <p>This function writes an entry to the currently active log,
-%%% i.e. either the CT log or a test case log.</p>
+%%% This function writes an entry to the currently active log,
+%%% i.e. either the CT log or a test case log.
%%%
-%%% <p><code>Heading</code> is a short string indicating what type of
-%%% activity it is. <code>Format</code> and <code>Args</code> is the
-%%% data to log (as in <code>io:format(Format,Args)</code>).</p>
+%%% Heading is a short string indicating what type of
+%%% activity it is. Format and Args is the
+%%% data to log (as in io:format(Format,Args)).
log(Heading,Format,Args) ->
cast({log,sync,self(),group_leader(),ct_internal,?MAX_IMPORTANCE,
[{hd,int_header(),[log_timestamp(?now),Heading]},
@@ -339,32 +337,29 @@ log(Heading,Format,Args) ->
ok.
%%%-----------------------------------------------------------------
-%%% @spec start_log(Heading) -> ok
+%%% -spec start_log(Heading) -> ok
%%%
-%%% @doc Starts the logging of an activity (tool-internal use only).
+%%% Starts the logging of an activity (tool-internal use only).
%%%
-%%% <p>This function must be used in combination with
-%%% <code>cont_log/2</code> and <code>end_log/0</code>. The intention
-%%% is to call <code>start_log</code> once, then <code>cont_log</code>
-%%% any number of times and finally <code>end_log</code> once.</p>
+%%% This function must be used in combination with
+%%% cont_log/2 and end_log/0. The intention
+%%% is to call start_log once, then cont_log
+%%% any number of times and finally end_log once.
%%%
-%%% <p>For information about the parameters, see <code>log/3</code>.</p>
+%%% For information about the parameters, see log/3.
%%%
-%%% @see log/3
-%%% @see cont_log/2
-%%% @see end_log/0
+%%% See log/3, cont_log/2, and end_log/0.
start_log(Heading) ->
cast({log,sync,self(),group_leader(),ct_internal,?MAX_IMPORTANCE,
[{hd,int_header(),[log_timestamp(?now),Heading]}],false}),
ok.
%%%-----------------------------------------------------------------
-%%% @spec cont_log(Format,Args) -> ok
+%%% -spec cont_log(Format,Args) -> ok
%%%
-%%% @doc Adds information about an activity (tool-internal use only).
+%%% Adds information about an activity (tool-internal use only).
%%%
-%%% @see start_log/1
-%%% @see end_log/0
+%%% See start_log/1 and end_log/0.
cont_log([],[]) ->
ok;
cont_log(Format,Args) ->
@@ -374,12 +369,11 @@ cont_log(Format,Args) ->
ok.
%%%-----------------------------------------------------------------
-%%% @spec cont_log_no_timestamp(Format,Args) -> ok
+%%% -spec cont_log_no_timestamp(Format,Args) -> ok
%%%
-%%% @doc Adds information about an activity (tool-internal use only).
+%%% Adds information about an activity (tool-internal use only).
%%%
-%%% @see start_log/1
-%%% @see end_log/0
+%%% See start_log/1 and end_log/0.
cont_log_no_timestamp([],[]) ->
ok;
cont_log_no_timestamp(Format,Args) ->
@@ -388,12 +382,11 @@ cont_log_no_timestamp(Format,Args) ->
ok.
%%%-----------------------------------------------------------------
-%%% @spec end_log() -> ok
+%%% -spec end_log() -> ok
%%%
-%%% @doc Ends the logging of an activity (tool-internal use only).
+%%% Ends the logging of an activity (tool-internal use only).
%%%
-%%% @see start_log/1
-%%% @see cont_log/2
+%%% See start_log/1 and cont_log/2.
end_log() ->
cast({log,sync,self(),group_leader(),ct_internal,?MAX_IMPORTANCE,
[{ft,int_footer(), []}],false}),
@@ -401,15 +394,15 @@ end_log() ->
%%%-----------------------------------------------------------------
-%%% @spec add_external_logs(Logs) -> ok
+%%% -spec add_external_logs(Logs) -> ok
%%% Logs = [Log]
%%% Log = string()
%%%
-%%% @doc Print a link to each given <code>Log</code> in the test case
+%%% Print a link to each given Log in the test case
%%% log.
%%%
-%%% <p>The given <code>Logs</code> must exist in the priv dir of the
-%%% calling test suite.</p>
+%%% The given Logs must exist in the priv dir of the
+%%% calling test suite.
add_external_logs(Logs) ->
start_log("External Logs"),
[cont_log("<a href=\"~ts\">~ts</a>\n",
@@ -417,12 +410,12 @@ add_external_logs(Logs) ->
end_log().
%%%-----------------------------------------------------------------
-%%% @spec add_link(Heading,File,Type) -> ok
+%%% -spec add_link(Heading,File,Type) -> ok
%%% Heading = string()
%%% File = string()
%%% Type = string()
%%%
-%%% @doc Print a link to a given file stored in the priv_dir of the
+%%% Print a link to a given file stored in the priv_dir of the
%%% calling test suite.
add_link(Heading,File,Type) ->
log(Heading,"<a href=\"~ts\" type=~tp>~ts</a>\n",
@@ -430,25 +423,25 @@ add_link(Heading,File,Type) ->
%%%-----------------------------------------------------------------
-%%% @spec tc_log(Category,Format,Args) -> ok
-%%% @equiv tc_log(Category,?STD_IMPORTANCE,Format,Args)
+%%% -spec tc_log(Category,Format,Args) -> ok
+%%% Equivalent to tc_log(Category,?STD_IMPORTANCE,Format,Args)
tc_log(Category,Format,Args) ->
tc_log(Category,?STD_IMPORTANCE,"User",Format,Args,[]).
%%%-----------------------------------------------------------------
-%%% @spec tc_log(Category,Importance,Format,Args) -> ok
-%%% @equiv tc_log(Category,Importance,"User",Format,Args)
+%%% -spec tc_log(Category,Importance,Format,Args) -> ok
+%%% Equivalent to tc_log(Category,Importance,"User",Format,Args)
tc_log(Category,Importance,Format,Args) ->
tc_log(Category,Importance,"User",Format,Args,[]).
%%%-----------------------------------------------------------------
-%%% @spec tc_log(Category,Importance,Format,Args) -> ok
-%%% @equiv tc_log(Category,Importance,"User",Format,Args)
+%%% -spec tc_log(Category,Importance,Format,Args) -> ok
+%%% Equivalent to tc_log(Category,Importance,"User",Format,Args)
tc_log(Category,Importance,Format,Args,Opts) ->
tc_log(Category,Importance,"User",Format,Args,Opts).
%%%-----------------------------------------------------------------
-%%% @spec tc_log(Category,Importance,Heading,Format,Args,Opts) -> ok
+%%% -spec tc_log(Category,Importance,Heading,Format,Args,Opts) -> ok
%%% Category = atom()
%%% Importance = integer()
%%% Heading = string()
@@ -456,11 +449,11 @@ tc_log(Category,Importance,Format,Args,Opts) ->
%%% Args = list()
%%% Opts = list()
%%%
-%%% @doc Printout from a testcase.
+%%% Printout from a testcase.
%%%
-%%% <p>This function is called by <code>ct</code> when logging
+%%% This function is called by ct when logging
%%% stuff directly from a testcase (i.e. not from within the CT
-%%% framework).</p>
+%%% framework).
tc_log(Category,Importance,Heading,Format,Args,Opts) ->
Data =
case lists:member(no_css, Opts) of
@@ -481,26 +474,26 @@ tc_log(Category,Importance,Heading,Format,Args,Opts) ->
ok.
%%%-----------------------------------------------------------------
-%%% @spec tc_log_async(Category,Format,Args) -> ok
-%%% @equiv tc_log_async(Category,?STD_IMPORTANCE,"User",Format,Args)
+%%% -spec tc_log_async(Category,Format,Args) -> ok
+%%% Equivalent to tc_log_async(Category,?STD_IMPORTANCE,"User",Format,Args)
tc_log_async(Category,Format,Args) ->
tc_log_async(Category,?STD_IMPORTANCE,"User",Format,Args).
%%%-----------------------------------------------------------------
-%%% @spec tc_log_async(Category,Importance,Format,Args) -> ok
+%%% -spec tc_log_async(Category,Importance,Format,Args) -> ok
%%% Category = atom()
%%% Importance = integer()
%%% Heading = string()
%%% Format = string()
%%% Args = list()
%%%
-%%% @doc Internal use only.
+%%% Internal use only.
%%%
-%%% <p>This function is used to perform asynchronous printouts
+%%% This function is used to perform asynchronous printouts
%%% towards the test server IO handler. This is necessary in order
%%% to avoid deadlocks when e.g. the hook that handles SASL printouts
%%% prints to the test case log file at the same time test server
-%%% asks ct_logs for an html wrapper.</p>
+%%% asks ct_logs for an html wrapper.
tc_log_async(Category,Importance,Heading,Format,Args) ->
cast({log,async,self(),group_leader(),Category,Importance,
[{hd,div_header(Category,Heading),[]},
@@ -509,29 +502,29 @@ tc_log_async(Category,Importance,Heading,Format,Args) ->
true}),
ok.
%%%-----------------------------------------------------------------
-%%% @spec tc_print(Category,Format,Args)
-%%% @equiv tc_print(Category,?STD_IMPORTANCE,Format,Args,[])
+%%% -spec tc_print(Category,Format,Args)
+%%% Equivalent to tc_print(Category,?STD_IMPORTANCE,Format,Args,[])
tc_print(Category,Format,Args) ->
tc_print(Category,?STD_IMPORTANCE,Format,Args,[]).
%%%-----------------------------------------------------------------
-%%% @spec tc_print(Category,Importance,Format,Args)
-%%% @equiv tc_print(Category,Importance,Format,Args,[])
+%%% -spec tc_print(Category,Importance,Format,Args)
+%%% Equivalent to tc_print(Category,Importance,Format,Args,[])
tc_print(Category,Importance,Format,Args) ->
tc_print(Category,Importance,Format,Args,[]).
%%%-----------------------------------------------------------------
-%%% @spec tc_print(Category,Importance,Format,Args,Opts) -> ok
+%%% -spec tc_print(Category,Importance,Format,Args,Opts) -> ok
%%% Category = atom()
%%% Importance = integer()
%%% Format = string()
%%% Args = list()
%%% Opts = list()
%%%
-%%% @doc Console printout from a testcase.
+%%% Console printout from a testcase.
%%%
-%%% <p>This function is called by <code>ct</code> when printing
-%%% stuff from a testcase on the user console.</p>
+%%% This function is called by ct when printing
+%%% stuff from a testcase on the user console.
tc_print(Category,Importance,Format,Args,Opts) ->
VLvl = case ct_util:get_verbosity(Category) of
undefined ->
@@ -572,44 +565,44 @@ get_header(Heading) ->
%%%-----------------------------------------------------------------
-%%% @spec tc_pal(Category,Format,Args) -> ok
-%%% @equiv tc_pal(Category,?STD_IMPORTANCE,Format,Args,[]) -> ok
+%%% -spec tc_pal(Category,Format,Args) -> ok
+%%% Equivalent to tc_pal(Category,?STD_IMPORTANCE,Format,Args,[]) -> ok
tc_pal(Category,Format,Args) ->
tc_pal(Category,?STD_IMPORTANCE,Format,Args,[]).
%%%-----------------------------------------------------------------
-%%% @spec tc_pal(Category,Importance,Format,Args) -> ok
-%%% @equiv tc_pal(Category,Importance,Format,Args,[]) -> ok
+%%% -spec tc_pal(Category,Importance,Format,Args) -> ok
+%%% Equivalent to tc_pal(Category,Importance,Format,Args,[]) -> ok
tc_pal(Category,Importance,Format,Args) ->
tc_pal(Category,Importance,Format,Args,[]).
%%%-----------------------------------------------------------------
-%%% @spec tc_pal(Category,Importance,Format,Args,Opts) -> ok
+%%% -spec tc_pal(Category,Importance,Format,Args,Opts) -> ok
%%% Category = atom()
%%% Importance = integer()
%%% Format = string()
%%% Args = list()
%%% Opts = list()
%%%
-%%% @doc Print and log from a testcase.
+%%% Print and log from a testcase.
%%%
-%%% <p>This function is called by <code>ct</code> when logging
+%%% This function is called by ct when logging
%%% stuff directly from a testcase. The info is written both in the
-%%% log and on the console.</p>
+%%% log and on the console.
tc_pal(Category,Importance,Format,Args,Opts) ->
tc_print(Category,Importance,Format,Args,Opts),
tc_log(Category,Importance,"User",Format,Args,[esc_chars|Opts]).
%%%-----------------------------------------------------------------
-%%% @spec ct_log(Category,Format,Args) -> ok
+%%% -spec ct_log(Category,Format,Args) -> ok
%%% Category = atom()
%%% Format = string()
%%% Args = list()
%%%
-%%% @doc Print to the ct framework log
+%%% Print to the ct framework log
%%%
-%%% <p>This function is called by internal ct functions to
-%%% force logging to the ct framework log</p>
+%%% This function is called by internal ct functions to
+%%% force logging to the ct framework log
ct_log(Category,Format,Args) ->
cast({ct_log,[{hd,div_header(Category),[]},
{Format,Args},
@@ -666,6 +659,7 @@ log_timestamp({MS,S,US}) ->
logger(Parent, Mode, Verbosity) ->
register(?MODULE,self()),
+ ct_util:mark_process(),
%%! Below is a temporary workaround for the limitation of
%%! max one test run per second.
%%! --->
@@ -1004,6 +998,7 @@ print_to_log(async, FromPid, Category, TCGL, Content, EscChars, State) ->
if FromPid /= TCGL ->
IoFun = create_io_fun(FromPid, CtLogFd, EscChars),
fun() ->
+ ct_util:mark_process(),
test_server:permit_io(TCGL, self()),
%% Since asynchronous io gets can get buffered if
@@ -1035,6 +1030,7 @@ print_to_log(async, FromPid, Category, TCGL, Content, EscChars, State) ->
end;
true ->
fun() ->
+ ct_util:mark_process(),
unexpected_io(FromPid, Category, ?MAX_IMPORTANCE,
Content, CtLogFd, EscChars)
end
@@ -1188,26 +1184,23 @@ print_style(Fd, IoFormat, StyleSheet) ->
case file:read_file(StyleSheet) of
{ok,Bin} ->
Str = b2s(Bin,encoding(StyleSheet)),
- Pos0 = case string:str(Str,"<style>") of
- 0 -> string:str(Str,"<STYLE>");
- N0 -> N0
- end,
- Pos1 = case string:str(Str,"</style>") of
- 0 -> string:str(Str,"</STYLE>");
- N1 -> N1
- end,
- if (Pos0 == 0) and (Pos1 /= 0) ->
- print_style_error(Fd, IoFormat,
- StyleSheet, missing_style_start_tag);
- (Pos0 /= 0) and (Pos1 == 0) ->
- print_style_error(Fd, IoFormat,
- StyleSheet,missing_style_end_tag);
- Pos0 /= 0 ->
- Style = string:sub_string(Str,Pos0,Pos1+7),
- IoFormat(Fd,"~ts\n",[Style]);
- Pos0 == 0 ->
- IoFormat(Fd,"<style>\n~ts</style>\n",[Str])
- end;
+ case re:run(Str,"<style>.*</style>",
+ [dotall,caseless,{capture,all,list}]) of
+ nomatch ->
+ case re:run(Str,"</?style>",[caseless,{capture,all,list}]) of
+ nomatch ->
+ IoFormat(Fd,"<style>\n~ts</style>\n",[Str]);
+ {match,["</"++_]} ->
+ print_style_error(Fd, IoFormat,
+ StyleSheet,
+ missing_style_start_tag);
+ {match,[_]} ->
+ print_style_error(Fd, IoFormat,
+ StyleSheet,missing_style_end_tag)
+ end;
+ {match,[Style]} ->
+ IoFormat(Fd,"~ts\n",[Style])
+ end;
{error,Reason} ->
print_style_error(Fd,IoFormat,StyleSheet,Reason)
end.
@@ -1414,9 +1407,9 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip,
{Lbl,Timestamp,Node,AllInfo} =
case All of
{true,OldRuns} ->
- [_Prefix,NodeOrDate|_] = string:tokens(Link,"."),
- Node1 = case string:chr(NodeOrDate,$@) of
- 0 -> "-";
+ [_Prefix,NodeOrDate|_] = string:lexemes(Link,"."),
+ Node1 = case string:find(NodeOrDate,[$@]) of
+ nomatch -> "-";
_ -> NodeOrDate
end,
@@ -1523,7 +1516,7 @@ not_built(BaseName,_LogDir,_All,Missing) ->
%% Top.ObjDir | Top.ObjDir.suites | Top.ObjDir.Suite |
%% Top.ObjDir.Suite.cases | Top.ObjDir.Suite.Case
Failed =
- case string:tokens(BaseName,".") of
+ case string:lexemes(BaseName,".") of
[T,O] when is_list(T) -> % all under Top.ObjDir
locate_info({T,O},all,Missing);
[T,O,"suites"] ->
@@ -2051,9 +2044,9 @@ sort_all_runs(Dirs) ->
%% "YYYY-MM-DD_HH.MM.SS"
lists:sort(fun(Dir1,Dir2) ->
[SS1,MM1,HH1,Date1|_] =
- lists:reverse(string:tokens(Dir1,[$.,$_])),
+ lists:reverse(string:lexemes(Dir1,[$.,$_])),
[SS2,MM2,HH2,Date2|_] =
- lists:reverse(string:tokens(Dir2,[$.,$_])),
+ lists:reverse(string:lexemes(Dir2,[$.,$_])),
{Date1,HH1,MM1,SS1} > {Date2,HH2,MM2,SS2}
end, Dirs).
@@ -2063,9 +2056,9 @@ sort_ct_runs(Dirs) ->
lists:sort(
fun(Dir1,Dir2) ->
[SS1,MM1,DateHH1 | _] =
- lists:reverse(string:tokens(filename:dirname(Dir1),[$.])),
+ lists:reverse(string:lexemes(filename:dirname(Dir1),[$.])),
[SS2,MM2,DateHH2 | _] =
- lists:reverse(string:tokens(filename:dirname(Dir2),[$.])),
+ lists:reverse(string:lexemes(filename:dirname(Dir2),[$.])),
{DateHH1,MM1,SS1} =< {DateHH2,MM2,SS2}
end, Dirs).
@@ -2211,27 +2204,15 @@ runentry(Dir, Totals={Node,Label,Logs,
0 -> "-";
N -> integer_to_list(N)
end,
- StripExt =
- fun(File) ->
- string:sub_string(File,1,
- length(File)-
- length(?logdir_ext)) ++ ", "
- end,
- Polish = fun(S) -> case lists:reverse(S) of
- [32,$,|Rev] -> lists:reverse(Rev);
- [$,|Rev] -> lists:reverse(Rev);
- _ -> S
- end
- end,
- TestNames = Polish(lists:flatten(lists:map(StripExt,Logs))),
+
+ RootNames = lists:map(fun(F) -> filename:rootname(F,?logdir_ext) end, Logs),
+ TestNames = lists:flatten(lists:join(", ", RootNames)),
TestNamesTrunc =
- if TestNames=="" ->
- "";
- length(TestNames) < ?testname_width ->
+ if length(TestNames) < ?testname_width ->
TestNames;
true ->
- Trunc = Polish(string:substr(TestNames,1,
- ?testname_width-3)),
+ Trunc = string:trim(string:slice(TestNames,0,?testname_width-3),
+ trailing,",\s"),
lists:flatten(io_lib:format("~ts...",[Trunc]))
end,
TotMissingStr =
@@ -2374,7 +2355,7 @@ force_rename(From,To,Number) ->
timestamp(Dir) ->
- TsR = lists:reverse(string:tokens(Dir,".-_")),
+ TsR = lists:reverse(string:lexemes(Dir,".-_")),
[S,Min,H,D,M,Y] = [list_to_integer(N) || N <- lists:sublist(TsR,6)],
format_time({{Y,M,D},{H,Min,S}}).
@@ -2923,7 +2904,7 @@ cache_vsn() ->
VSNfile = filename:join([EbinDir,"..","vsn.mk"]),
case file:read_file(VSNfile) of
{ok,Bin} ->
- [_,VSN] = string:tokens(binary_to_list(Bin),[$=,$\n,$ ]),
+ [_,VSN] = string:lexemes(binary_to_list(Bin),[$=,$\n,$ ]),
VSN;
_ ->
undefined
@@ -3005,18 +2986,19 @@ rm_files([]) ->
ok.
%%%-----------------------------------------------------------------
-%%% @spec simulate() -> pid()
+%%% -spec simulate() -> pid()
%%%
-%%% @doc Simulate the logger process.
+%%% Simulate the logger process.
%%%
-%%% <p>Simulate the logger process - for use when testing code using
+%%% Simulate the logger process - for use when testing code using
%%% ct_logs logging mechanism without using the ct
-%%% environment. (E.g. when testing code with ts)</p>
+%%% environment. (E.g. when testing code with ts)
simulate() ->
cast(stop),
S = self(),
Pid = spawn(fun() ->
register(?MODULE,self()),
+ ct_util:mark_process(),
S ! {self(),started},
simulate_logger_loop()
end),
@@ -3038,9 +3020,7 @@ simulate_logger_loop() ->
end.
%%%-----------------------------------------------------------------
-%%% @spec notify_and_lock_file(Files) -> ok
-%%%
-%%% @doc
+%%% -spec notify_and_lock_file(Files) -> ok
%%%
notify_and_lock_file(File) ->
case ct_event:is_alive() of
@@ -3053,9 +3033,7 @@ notify_and_lock_file(File) ->
end.
%%%-----------------------------------------------------------------
-%%% @spec notify_and_unlock_file(Files) -> ok
-%%%
-%%% @doc
+%%% -spec notify_and_unlock_file(Files) -> ok
%%%
notify_and_unlock_file(File) ->
case ct_event:is_alive() of
@@ -3068,9 +3046,7 @@ notify_and_unlock_file(File) ->
end.
%%%-----------------------------------------------------------------
-%%% @spec get_run_dirs(Dir) -> [string()] | false
-%%%
-%%% @doc
+%%% -spec get_run_dirs(Dir) -> [string()] | false
%%%
get_run_dirs(Dir) ->
case filelib:wildcard(filename:join(Dir, "run.[1-2]*")) of
@@ -3081,9 +3057,7 @@ get_run_dirs(Dir) ->
end.
%%%-----------------------------------------------------------------
-%%% @spec xhtml(HTML, XHTML) -> HTML | XHTML
-%%%
-%%% @doc
+%%% -spec xhtml(HTML, XHTML) -> HTML | XHTML
%%%
xhtml(HTML, XHTML) when is_function(HTML),
is_function(XHTML) ->
@@ -3098,9 +3072,7 @@ xhtml(HTML, XHTML) ->
end.
%%%-----------------------------------------------------------------
-%%% @spec odd_or_even() -> "odd" | "even"
-%%%
-%%% @doc
+%%% -spec odd_or_even() -> "odd" | "even"
%%%
odd_or_even() ->
case get(odd_or_even) of
@@ -3113,9 +3085,7 @@ odd_or_even() ->
end.
%%%-----------------------------------------------------------------
-%%% @spec basic_html() -> true | false
-%%%
-%%% @doc
+%%% -spec basic_html() -> true | false
%%%
basic_html() ->
case application:get_env(common_test, basic_html) of
@@ -3126,9 +3096,7 @@ basic_html() ->
end.
%%%-----------------------------------------------------------------
-%%% @spec locate_priv_file(FileName) -> PrivFile
-%%%
-%%% @doc
+%%% -spec locate_priv_file(FileName) -> PrivFile
%%%
locate_priv_file(FileName) ->
{ok,CWD} = file:get_cwd(),
@@ -3144,8 +3112,8 @@ locate_priv_file(FileName) ->
filename:join(get(ct_run_dir), FileName);
_ ->
%% executed on other process than ct_logs
- {ok,RunDir} = get_log_dir(true),
- filename:join(RunDir, FileName)
+ {ok,LogDir} = get_log_dir(true),
+ filename:join(LogDir, FileName)
end,
case filelib:is_file(PrivResultFile) of
true ->
@@ -3158,13 +3126,13 @@ locate_priv_file(FileName) ->
end.
%%%-----------------------------------------------------------------
-%%% @spec make_relative(AbsDir, Cwd) -> RelDir
+%%% -spec make_relative(AbsDir, Cwd) -> RelDir
%%%
-%%% @doc Return directory path to File (last element of AbsDir), which
-%%% is the path relative to Cwd. Examples when Cwd == "/ldisk/test/logs":
-%%% make_relative("/ldisk/test/logs/run/trace.log") -> "run/trace.log"
-%%% make_relative("/ldisk/test/trace.log") -> "../trace.log"
-%%% make_relative("/ldisk/test/logs/trace.log") -> "trace.log"
+%%% Return directory path to File (last element of AbsDir), which
+%%% is the path relative to Cwd. Examples when Cwd == "/ldisk/test/logs":
+%%% make_relative("/ldisk/test/logs/run/trace.log") -> "run/trace.log"
+%%% make_relative("/ldisk/test/trace.log") -> "../trace.log"
+%%% make_relative("/ldisk/test/logs/trace.log") -> "trace.log"
make_relative(AbsDir) ->
{ok,Cwd} = file:get_cwd(),
make_relative(AbsDir, Cwd).
@@ -3188,11 +3156,9 @@ make_relative1(DirTs, CwdTs) ->
Ups ++ DirTs.
%%%-----------------------------------------------------------------
-%%% @spec get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols, Encoding)
+%%% -spec get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols, Encoding)
%%% -> {Mode,Header,Footer}
%%%
-%%% @doc
-%%%
get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols, Encoding) ->
get_ts_html_wrapper(TestName, undefined, PrintLabel, Cwd, TableCols, Encoding).
@@ -3227,6 +3193,10 @@ get_ts_html_wrapper(TestName, Logdir, PrintLabel, Cwd, TableCols, Encoding) ->
?all_runs_name), Cwd),
TestIndex = make_relative(filename:join(filename:dirname(CtLogdir),
?index_name), Cwd),
+ LatestTest = make_relative(filename:join(filename:dirname(CtLogdir),
+ ?suitelog_name++".latest.html"),
+ Cwd),
+
case Basic of
true ->
TileFile = filename:join(filename:join(CTPath,"priv"),"tile1.jpg"),
@@ -3253,7 +3223,9 @@ get_ts_html_wrapper(TestName, Logdir, PrintLabel, Cwd, TableCols, Encoding) ->
"<a href=\"", uri(AllRuns),
"\">Test run history\n</a> | ",
"<a href=\"", uri(TestIndex),
- "\">Top level test index\n</a>\n</p>\n",
+ "\">Top level test index\n</a> | ",
+ "<a href=\"", uri(LatestTest),
+ "\">Latest test result</a>\n</p>\n",
Copyright,"</center>\n</body>\n</html>\n"]};
_ ->
Copyright =
@@ -3300,7 +3272,9 @@ get_ts_html_wrapper(TestName, Logdir, PrintLabel, Cwd, TableCols, Encoding) ->
"<a href=\"", uri(AllRuns),
"\">Test run history\n</a> | ",
"<a href=\"", uri(TestIndex),
- "\">Top level test index\n</a>\n</p>\n",
+ "\">Top level test index\n</a> | ",
+ "<a href=\"", uri(LatestTest),
+ "\">Latest test result</a>\n</p>\n",
Copyright,"</center>\n</body>\n</html>\n"]}
end.
@@ -3320,7 +3294,7 @@ insert_javascript({tablesorter,TableName,
end, [{"CTDateSorter",DateCols},
{"CTTextSorter",TextCols},
{"CTValSorter",ValCols}]))),
- Headers1 = string:substr(Headers, 1, length(Headers)-2),
+ Headers1 = string:trim(Headers, trailing, ",\n"),
["<script type=\"text/javascript\">\n",
"// Parser for date format, e.g: Wed Jul 4 2012 11:24:15\n",
diff --git a/lib/common_test/src/ct_make.erl b/lib/common_test/src/ct_make.erl
index 4d66796b83..220cb0473d 100644
--- a/lib/common_test/src/ct_make.erl
+++ b/lib/common_test/src/ct_make.erl
@@ -280,15 +280,47 @@ recompile(File, NoExec, Load, Opts) ->
do_recompile(_File, true, _Load, _Opts) ->
out_of_date;
-do_recompile(File, false, noload, Opts) ->
+do_recompile(File, false, Load, Opts) ->
io:format("Recompile: ~ts\n",[File]),
- compile:file(File, [report_errors, report_warnings, error_summary |Opts]);
-do_recompile(File, false, load, Opts) ->
- io:format("Recompile: ~ts\n",[File]),
- c:c(File, Opts);
-do_recompile(File, false, netload, Opts) ->
- io:format("Recompile: ~ts\n",[File]),
- c:nc(File, Opts).
+ case compile:file(File, [report_errors, report_warnings |Opts]) of
+ Ok when is_tuple(Ok), element(1,Ok)==ok ->
+ maybe_load(element(2,Ok), Load, Opts);
+ _Error ->
+ error
+ end.
+
+maybe_load(_Mod, noload, _Opts) ->
+ ok;
+maybe_load(Mod, Load, Opts) ->
+ %% We have compiled File with options Opts. Find out where the
+ %% output file went to, and load it.
+ case compile:output_generated(Opts) of
+ true ->
+ Dir = proplists:get_value(outdir,Opts,"."),
+ do_load(Dir, Mod, Load);
+ false ->
+ io:format("** Warning: No object file created - nothing loaded **~n"),
+ ok
+ end.
+
+do_load(Dir, Mod, load) ->
+ code:purge(Mod),
+ case code:load_abs(filename:join(Dir, Mod),Mod) of
+ {module,Mod} ->
+ {ok,Mod};
+ Other ->
+ Other
+ end;
+do_load(Dir, Mod, netload) ->
+ Obj = atom_to_list(Mod) ++ code:objfile_extension(),
+ Fname = filename:join(Dir, Obj),
+ case file:read_file(Fname) of
+ {ok,Bin} ->
+ rpc:eval_everywhere(code,load_binary,[Mod,Fname,Bin]),
+ {ok,Mod};
+ Other ->
+ Other
+ end.
exists(File) ->
case file:read_file_info(File) of
diff --git a/lib/common_test/src/ct_master.erl b/lib/common_test/src/ct_master.erl
index 6e6d1879c2..fd33ee2280 100644
--- a/lib/common_test/src/ct_master.erl
+++ b/lib/common_test/src/ct_master.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,9 +18,6 @@
%% %CopyrightEnd%
%%
-%%% @doc Distributed test execution control for Common Test.
-%%% <p>This module exports functions for running Common Test nodes
-%%% on multiple hosts in parallel.</p>
-module(ct_master).
-export([run/1,run/3,run/4]).
@@ -45,50 +42,14 @@
blocked=[]
}).
-%%%-----------------------------------------------------------------
-%%% @spec run_test(Node,Opts) -> ok
-%%% Node = atom()
-%%% Opts = [OptTuples]
-%%% OptTuples = {config,CfgFiles} | {dir,TestDirs} | {suite,Suites} |
-%%% {testcase,Cases} | {spec,TestSpecs} | {allow_user_terms,Bool} |
-%%% {logdir,LogDir} | {event_handler,EventHandlers} |
-%%% {silent_connections,Conns} | {cover,CoverSpecFile} |
-%%% {cover_stop,Bool} | {userconfig, UserCfgFiles}
-%%% CfgFiles = string() | [string()]
-%%% TestDirs = string() | [string()]
-%%% Suites = atom() | [atom()]
-%%% Cases = atom() | [atom()]
-%%% TestSpecs = string() | [string()]
-%%% LogDir = string()
-%%% EventHandlers = EH | [EH]
-%%% EH = atom() | {atom(),InitArgs} | {[atom()],InitArgs}
-%%% InitArgs = [term()]
-%%% Conns = all | [atom()]
-%%%
-%%% @doc Tests are spawned on <code>Node</code> using <code>ct:run_test/1</code>.
run_test(Node,Opts) ->
run_test([{Node,Opts}]).
-%%% @hidden
run_test({Node,Opts}) ->
run_test([{Node,Opts}]);
run_test(NodeOptsList) when is_list(NodeOptsList) ->
start_master(NodeOptsList).
-%%%-----------------------------------------------------------------
-%%% @spec run(TestSpecs,AllowUserTerms,InclNodes,ExclNodes) -> ok
-%%% TestSpecs = string() | [SeparateOrMerged]
-%%% SeparateOrMerged = string() | [string()]
-%%% AllowUserTerms = bool()
-%%% InclNodes = [atom()]
-%%% ExclNodes = [atom()]
-%%%
-%%% @doc Tests are spawned on the nodes as specified in <code>TestSpecs</code>.
-%%% Each specification in TestSpec will be handled separately. It is however
-%%% possible to also specify a list of specifications that should be merged
-%%% into one before the tests are executed. Any test without a particular node
-%%% specification will also be executed on the nodes in <code>InclNodes</code>.
-%%% Nodes in the <code>ExclNodes</code> list will be excluded from the test.
run([TS|TestSpecs],AllowUserTerms,InclNodes,ExclNodes) when is_list(TS),
is_list(InclNodes),
is_list(ExclNodes) ->
@@ -128,22 +89,9 @@ run(TS,AllowUserTerms,InclNodes,ExclNodes) when is_list(InclNodes),
is_list(ExclNodes) ->
run([TS],AllowUserTerms,InclNodes,ExclNodes).
-%%%-----------------------------------------------------------------
-%%% @spec run(TestSpecs,InclNodes,ExclNodes) -> ok
-%%% TestSpecs = string() | [SeparateOrMerged]
-%%% SeparateOrMerged = string() | [string()]
-%%% InclNodes = [atom()]
-%%% ExclNodes = [atom()]
-%%%
-%%% @equiv run(TestSpecs,false,InclNodes,ExclNodes)
run(TestSpecs,InclNodes,ExclNodes) ->
run(TestSpecs,false,InclNodes,ExclNodes).
-%%%-----------------------------------------------------------------
-%%% @spec run(TestSpecs) -> ok
-%%% TestSpecs = string() | [SeparateOrMerged]
-%%%
-%%% @equiv run(TestSpecs,false,[],[])
run(TestSpecs=[TS|_]) when is_list(TS) ->
run(TestSpecs,false,[],[]);
run(TS) ->
@@ -156,15 +104,6 @@ exclude_nodes([],RunSkipPerNode) ->
RunSkipPerNode.
-%%%-----------------------------------------------------------------
-%%% @spec run_on_node(TestSpecs,AllowUserTerms,Node) -> ok
-%%% TestSpecs = string() | [SeparateOrMerged]
-%%% SeparateOrMerged = string() | [string()]
-%%% AllowUserTerms = bool()
-%%% Node = atom()
-%%%
-%%% @doc Tests are spawned on <code>Node</code> according to
-%%% <code>TestSpecs</code>.
run_on_node([TS|TestSpecs],AllowUserTerms,Node) when is_list(TS),is_atom(Node) ->
case catch ct_testspec:collect_tests_from_file([TS],[Node],
AllowUserTerms) of
@@ -194,13 +133,6 @@ run_on_node([],_,_) ->
run_on_node(TS,AllowUserTerms,Node) when is_atom(Node) ->
run_on_node([TS],AllowUserTerms,Node).
-%%%-----------------------------------------------------------------
-%%% @spec run_on_node(TestSpecs,Node) -> ok
-%%% TestSpecs = string() | [SeparateOrMerged]
-%%% SeparateOrMerged = string() | [string()]
-%%% Node = atom()
-%%%
-%%% @equiv run_on_node(TestSpecs,false,Node)
run_on_node(TestSpecs,Node) ->
run_on_node(TestSpecs,false,Node).
@@ -264,64 +196,25 @@ run_all([],AllLogDirs,_,AllEvHs,_AllIncludes,
ok.
-%%%-----------------------------------------------------------------
-%%% @spec abort() -> ok
-%%%
-%%% @doc Stops all running tests.
abort() ->
call(abort).
-%%%-----------------------------------------------------------------
-%%% @spec abort(Nodes) -> ok
-%%% Nodes = atom() | [atom()]
-%%%
-%%% @doc Stops tests on specified nodes.
abort(Nodes) when is_list(Nodes) ->
call({abort,Nodes});
abort(Node) when is_atom(Node) ->
abort([Node]).
-%%%-----------------------------------------------------------------
-%%% @spec progress() -> [{Node,Status}]
-%%% Node = atom()
-%%% Status = finished_ok | ongoing | aborted | {error,Reason}
-%%% Reason = term()
-%%%
-%%% @doc Returns test progress. If <code>Status</code> is <code>ongoing</code>,
-%%% tests are running on the node and have not yet finished.
progress() ->
call(progress).
-%%%-----------------------------------------------------------------
-%%% @spec get_event_mgr_ref() -> MasterEvMgrRef
-%%% MasterEvMgrRef = atom()
-%%%
-%%% @doc <p>Call this function in order to get a reference to the
-%%% CT master event manager. The reference can be used to e.g.
-%%% add a user specific event handler while tests are running.
-%%% Example:
-%%% <c>gen_event:add_handler(ct_master:get_event_mgr_ref(), my_ev_h, [])</c></p>
get_event_mgr_ref() ->
?CT_MEVMGR_REF.
-%%%-----------------------------------------------------------------
-%%% @spec basic_html(Bool) -> ok
-%%% Bool = true | false
-%%%
-%%% @doc If set to true, the ct_master logs will be written on a
-%%% primitive html format, not using the Common Test CSS style
-%%% sheet.
basic_html(Bool) ->
application:set_env(common_test_master, basic_html, Bool),
ok.
-%%%-----------------------------------------------------------------
-%%% @spec esc_chars(Bool) -> ok
-%%% Bool = true | false
-%%%
-%%% @doc If set to false, the ct_master logs will be written without
-%%% special characters being escaped in the HTML logs.
esc_chars(Bool) ->
application:set_env(common_test_master, esc_chars, Bool),
ok.
@@ -340,12 +233,12 @@ start_master(NodeOptsList,EvHandlers,MasterLogDir,LogDirs,InitOptions,Specs) ->
{Master,Result} -> Result
end.
-%%% @hidden
init_master(Parent,NodeOptsList,EvHandlers,MasterLogDir,LogDirs,
InitOptions,Specs) ->
case whereis(ct_master) of
undefined ->
register(ct_master,self()),
+ ct_util:mark_process(),
ok;
_Pid ->
io:format("~nWarning: ct_master already running!~n"),
@@ -686,10 +579,10 @@ refresh_logs([],Refreshed) ->
%%%-----------------------------------------------------------------
%%% NODE CONTROLLER, runs and controls tests on a test node.
%%%-----------------------------------------------------------------
-%%% @hidden
init_node_ctrl(MasterPid,Cookie,Opts) ->
%% make sure tests proceed even if connection to master is lost
process_flag(trap_exit, true),
+ ct_util:mark_process(),
MasterNode = node(MasterPid),
group_leader(whereis(user),self()),
io:format("~n********** node_ctrl process ~w started on ~w **********~n",
@@ -740,7 +633,6 @@ start_ct_event() ->
%%%-----------------------------------------------------------------
%%% Event handling
%%%-----------------------------------------------------------------
-%%% @hidden
status(MasterPid,Event=#event{name=start_make}) ->
call(MasterPid,Event);
status(MasterPid,Event=#event{name=finished_make}) ->
@@ -807,7 +699,7 @@ filter_accessible(InitOptions, Inaccessible)->
start_nodes(InitOptions)->
lists:foreach(fun({NodeName, Options})->
- [NodeS,HostS]=string:tokens(atom_to_list(NodeName), "@"),
+ [NodeS,HostS]=string:lexemes(atom_to_list(NodeName), "@"),
Node=list_to_atom(NodeS),
Host=list_to_atom(HostS),
HasNodeStart = lists:keymember(node_start, 1, Options),
diff --git a/lib/common_test/src/ct_master_event.erl b/lib/common_test/src/ct_master_event.erl
index d535d1274e..a6ec5a7a75 100644
--- a/lib/common_test/src/ct_master_event.erl
+++ b/lib/common_test/src/ct_master_event.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,13 +18,13 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test Framework Event Handler
+%%% Common Test Framework Event Handler
%%%
-%%% <p>This module implements an event handler that the CT Master
+%%% This module implements an event handler that the CT Master
%%% uses to handle status and progress notifications sent to the
%%% master node during test runs. This module may be used as a
%%% template for other event handlers that can be plugged in to
-%%% handle logging and reporting on the master node.</p>
+%%% handle logging and reporting on the master node.
-module(ct_master_event).
-behaviour(gen_event).
@@ -116,6 +116,7 @@ sync_notify(Event) ->
%% this function is called to initialize the event handler.
%%--------------------------------------------------------------------
init(_) ->
+ ct_util:mark_process(),
ct_master_logs:log("CT Master Event Handler started","",[]),
{ok,#state{}}.
diff --git a/lib/common_test/src/ct_master_logs.erl b/lib/common_test/src/ct_master_logs.erl
index d8ecd641ed..ea6f93b565 100644
--- a/lib/common_test/src/ct_master_logs.erl
+++ b/lib/common_test/src/ct_master_logs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,10 +18,10 @@
%% %CopyrightEnd%
%%
-%%% @doc Logging functionality for Common Test Master.
+%%% Logging functionality for Common Test Master.
%%%
-%%% <p>This module implements a logger for the master
-%%% node.</p>
+%%% This module implements a logger for the master
+%%% node.
-module(ct_master_logs).
-export([start/2, make_all_runs_index/0, log/3, nodedir/2,
@@ -88,6 +88,7 @@ stop() ->
init(Parent,LogDir,Nodes) ->
register(?MODULE,self()),
+ ct_util:mark_process(),
Time = calendar:local_time(),
RunDir = make_dirname(Time),
RunDirAbs = filename:join(LogDir,RunDir),
@@ -297,7 +298,7 @@ sort_all_runs(Dirs) ->
%% "YYYY-MM-DD_HH.MM.SS"
KeyList =
lists:map(fun(Dir) ->
- case lists:reverse(string:tokens(Dir,[$.,$_])) of
+ case lists:reverse(string:lexemes(Dir,[$.,$_])) of
[SS,MM,HH,Date|_] ->
{{Date,HH,MM,SS},Dir};
_Other ->
@@ -312,18 +313,8 @@ runentry(Dir) ->
{MasterStr,NodesStr} =
case read_details_file(Dir) of
{Master,Nodes} when is_list(Nodes) ->
- [_,Host] = string:tokens(atom_to_list(Master),"@"),
- NodesList =
- lists:reverse(lists:map(fun(N) ->
- atom_to_list(N) ++ ", "
- end,Nodes)),
- case NodesList of
- [N|NListR] ->
- N1 = string:sub_string(N,1,length(N)-2),
- {Host,lists:flatten(lists:reverse([N1|NListR]))};
- [] ->
- {Host,""}
- end;
+ [_,Host] = string:lexemes(atom_to_list(Master),"@"),
+ {Host,lists:concat(lists:join(", ",Nodes))};
_Error ->
{"unknown",""}
end,
@@ -348,7 +339,7 @@ all_runs_header() ->
xhtml("", "</tr></thead>\n<tbody>\n")]].
timestamp(Dir) ->
- [S,Min,H,D,M,Y|_] = lists:reverse(string:tokens(Dir,".-_")),
+ [S,Min,H,D,M,Y|_] = lists:reverse(string:lexemes(Dir,".-_")),
[S1,Min1,H1,D1,M1,Y1] = [list_to_integer(N) || N <- [S,Min,H,D,M,Y]],
format_time({{Y1,M1,D1},{H1,Min1,S1}}).
diff --git a/lib/common_test/src/ct_master_status.erl b/lib/common_test/src/ct_master_status.erl
index b27fdd341e..cb01220121 100644
--- a/lib/common_test/src/ct_master_status.erl
+++ b/lib/common_test/src/ct_master_status.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,12 +18,12 @@
%% %CopyrightEnd%
%%
-%%% @doc Logging functionality for Common Test Master.
+%%% doc Logging functionality for Common Test Master.
%%%
-%%% <p>This module keeps a list of <code>{Node,Status}</code>
+%%% This module keeps a list of {Node,Status}
%%% tuples. It is possible to anytime during a test run get
%%% a snapshot of the test status. The module is an event
-%%% handler for the master event manager.</p>
+%%% handler for the master event manager.
-module(ct_master_status).
-behaviour(gen_event).
diff --git a/lib/common_test/src/ct_netconfc.erl b/lib/common_test/src/ct_netconfc.erl
index 2c4b97df20..29188a648e 100644
--- a/lib/common_test/src/ct_netconfc.erl
+++ b/lib/common_test/src/ct_netconfc.erl
@@ -1467,7 +1467,7 @@ decode_data(Other) ->
{error,{unexpected_rpc_reply,Other}}.
get_qualified_name(Tag) ->
- case string:tokens(atom_to_list(Tag),":") of
+ case string:lexemes(atom_to_list(Tag),":") of
[TagStr] -> {[],TagStr};
[PrefixStr,TagStr] -> {PrefixStr,TagStr}
end.
diff --git a/lib/common_test/src/ct_netconfc.hrl b/lib/common_test/src/ct_netconfc.hrl
index 5eeeafa318..1d81c762ba 100644
--- a/lib/common_test/src/ct_netconfc.hrl
+++ b/lib/common_test/src/ct_netconfc.hrl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-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.
@@ -24,9 +24,7 @@
%% This file defines constant values and records used by the
%% netconf client ct_netconfc.
%%
-%% @author Support
-%% @doc Netconf Client Interface.
-%% @end
+%% Netconf Client Interface.
%%----------------------------------------------------------------------
%%----------------------------------------------------------------------
diff --git a/lib/common_test/src/ct_property_test.erl b/lib/common_test/src/ct_property_test.erl
index 94ccb59af9..f51f454d08 100644
--- a/lib/common_test/src/ct_property_test.erl
+++ b/lib/common_test/src/ct_property_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,46 +28,6 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%% @doc EXPERIMENTAL support in common-test for calling property based tests.
-%%%
-%%% <p>This module is a first step towards running Property Based testing in the
-%%% Common Test framework. A property testing tool like QuickCheck or PropEr is
-%%% assumed to be installed.</p>
-%%%
-%%% <p>The idea is to have a common_test testsuite calling a property testing
-%%% tool with special property test suites as defined by that tool. In this manual
-%%% we assume the usual Erlang Application directory structure. The tests are
-%%% collected in the application's <c>test</c> directory. The test directory
-%%% has a sub-directory called <c>property_test</c> where everything needed for
-%%% the property tests are collected.</p>
-%%%
-%%% <p>A typical ct test suite using <c>ct_property_test</c> is organized as follows:
-%%% </p>
-%%% ```
-%%% -include_lib("common_test/include/ct.hrl").
-%%%
-%%% all() -> [prop_ftp_case].
-%%%
-%%% init_per_suite(Config) ->
-%%% ct_property_test:init_per_suite(Config).
-%%%
-%%% %%%---- test case
-%%% prop_ftp_case(Config) ->
-%%% ct_property_test:quickcheck(
-%%% ftp_simple_client_server:prop_ftp(Config),
-%%% Config
-%%% ).
-%%% '''
-%%%
-%%% <warning>
-%%% <p>
-%%% This is experimental code which may be changed or removed
-%%% anytime without any warning.
-%%% </p>
-%%% </warning>
-%%%
-%%% @end
-
-module(ct_property_test).
%% API
@@ -76,19 +36,6 @@
-include_lib("common_test/include/ct.hrl").
-%%%-----------------------------------------------------------------
-%%% @spec init_per_suite(Config) -> Config | {skip,Reason}
-%%%
-%%% @doc Initializes Config for property testing.
-%%%
-%%% <p>The function investigates if support is available for either Quickcheck, PropEr,
-%%% or Triq.
-%%% The options <c>{property_dir,AbsPath}</c> and
-%%% <c>{property_test_tool,Tool}</c> is set in the Config returned.</p>
-%%% <p>The function is intended to be called in the init_per_suite in the test suite.</p>
-%%% <p>The property tests are assumed to be in the subdirectory <c>property_test</c>.</p>
-%%% @end
-
init_per_suite(Config) ->
case which_module_exists([eqc,proper,triq]) of
{ok,ToolModule} ->
@@ -108,14 +55,6 @@ init_per_suite(Config) ->
{skip, "No property testing tool found"}
end.
-%%%-----------------------------------------------------------------
-%%% @spec quickcheck(Property, Config) -> true | {fail,Reason}
-%%%
-%%% @doc Call quickcheck and return the result in a form suitable for common_test.
-%%%
-%%% <p>The function is intended to be called in the test cases in the test suite.</p>
-%%% @end
-
quickcheck(Property, Config) ->
Tool = proplists:get_value(property_test_tool,Config),
F = function_name(quickcheck, Tool),
diff --git a/lib/common_test/src/ct_release_test.erl b/lib/common_test/src/ct_release_test.erl
index 551a7e06d7..60d17f43dc 100644
--- a/lib/common_test/src/ct_release_test.erl
+++ b/lib/common_test/src/ct_release_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2014-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2014-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
%%
%%-----------------------------------------------------------------
-%% @doc EXPERIMENTAL support for testing of upgrade.
+%% EXPERIMENTAL support for testing of upgrade.
%%
%% This is a library module containing support for test of release
%% related activities in one or more applications. Currenty it
@@ -27,7 +27,7 @@
%% == Configuration ==
%%
%% In order to find version numbers of applications to upgrade from,
-%% `{@module}' needs to access and start old OTP
+%% ct_release_test needs to access and start old OTP
%% releases. A `common_test' configuration file can be used for
%% specifying the location of such releases, for example:
%%
@@ -39,48 +39,45 @@
%% The configuration file should preferably point out the latest patch
%% level on each major release.
%%
-%% If no such configuration file is given, {@link init/1} will return
-%% `{skip,Reason}' and any attempt at running {@link upgrade/4}
+%% If no such configuration file is given, init/1 will return
+%% {skip,Reason} and any attempt at running upgrade/4
%% will fail.
%%
%% == Callback functions ==
%%
-%% The following functions should be exported from a {@module}
+%% The following functions should be exported from a ct_release_test
%% callback module.
%%
%% All callback functions are called on the node where the upgrade is
%% executed.
%%
-%% <dl>
-%% <dt>Module:upgrade_init(CtData,State) -> NewState</dt>
-%% <dd>Types:
+%% Module:upgrade_init(CtData,State) -> NewState
+%% Types:
%%
-%% <b><code>CtData = {@link ct_data()}</code></b><br/>
-%% <b><code>State = NewState = cb_state()</code></b>
+%% CtData = ct_data()
+%% State = NewState = cb_state()
%%
%% Initialyze system before upgrade test starts.
%%
%% This function is called before the upgrade is started. All
-%% applications given in {@link upgrade/4} are already started by
+%% applications given in upgrade/4 are already started by
%% the boot script, so this callback is intended for additional
%% initialization, if necessary.
%%
-%% <code>CtData</code> is an opaque data structure which shall be used
-%% in any call to <code>ct_release_test</code> inside the callback.
+%% CtData is an opaque data structure which shall be used
+%% in any call to ct_release_test inside the callback.
%%
%% Example:
%%
-%% ```
%% upgrade_init(CtData,State) ->
%% {ok,{FromVsn,ToVsn}} = ct_release_test:get_app_vsns(CtData,myapp),
-%% open_connection(State).'''
-%% </dd>
+%% open_connection(State).
%%
-%% <dt>Module:upgrade_upgraded(CtData,State) -> NewState</dt>
-%% <dd>Types:
+%% Module:upgrade_upgraded(CtData,State) -> NewState
+%% Types:
%%
-%% <b><code>CtData = {@link ct_data()}</code></b><br/>
-%% <b><code>State = NewState = cb_state()</code></b>
+%% CtData = ct_data()
+%% State = NewState = cb_state()
%%
%% Check that upgrade was successful.
%%
@@ -89,21 +86,19 @@
%% been made permanent. It allows application specific checks to
%% ensure that the upgrade was successful.
%%
-%% <code>CtData</code> is an opaque data structure which shall be used
-%% in any call to <code>ct_release_test</code> inside the callback.
+%% CtData is an opaque data structure which shall be used
+%% in any call to ct_release_test inside the callback.
%%
%% Example:
%%
-%% ```
%% upgrade_upgraded(CtData,State) ->
-%% check_connection_still_open(State).'''
-%% </dd>
+%% check_connection_still_open(State).
%%
-%% <dt>Module:upgrade_downgraded(CtData,State) -> NewState</dt>
-%% <dd>Types:
+%% Module:upgrade_downgraded(CtData,State) -> NewState
+%% Types:
%%
-%% <b><code>CtData = {@link ct_data()}</code></b><br/>
-%% <b><code>State = NewState = cb_state()</code></b>
+%% CtData = ct_data()
+%% State = NewState = cb_state()
%%
%% Check that downgrade was successful.
%%
@@ -112,17 +107,13 @@
%% made permanent. It allows application specific checks to ensure
%% that the downgrade was successful.
%%
-%% <code>CtData</code> is an opaque data structure which shall be used
-%% in any call to <code>ct_release_test</code> inside the callback.
+%% CtData is an opaque data structure which shall be used
+%% in any call to ct_release_test inside the callback.
%%
%% Example:
%%
-%% ```
%% upgrade_downgraded(CtData,State) ->
-%% check_connection_closed(State).'''
-%% </dd>
-%% </dl>
-%% @end
+%% check_connection_closed(State).
%%-----------------------------------------------------------------
-module(ct_release_test).
@@ -152,7 +143,7 @@
Config :: config(),
Result :: config() | SkipOrFail,
SkipOrFail :: {skip,Reason} | {fail,Reason}.
-%% @doc Initialize `{@module}'.
+%% Initialize ct_release_test.
%%
%% This function can be called from any of the
%% `init_per_*' functions in the test suite. It updates
@@ -168,9 +159,8 @@
%%
%% Example:
%%
-%% ```
%% init_per_suite(Config) ->
-%% ct_release_test:init(Config).'''
+%% ct_release_test:init(Config).
%%
init(Config) ->
try init_upgrade_test() of
@@ -194,47 +184,42 @@ init(Config) ->
Callback :: {module(),InitState},
InitState :: cb_state(),
Config :: config().
-%% @doc Test upgrade of the given application(s).
+%% Test upgrade of the given application(s).
%%
%% This function can be called from a test case. It requires that
-%% `Config' has been initialized by calling {@link
-%% init/1} prior to this, for example from `init_per_suite/1'.
+%% `Config' has been initialized by calling
+%% init/1 prior to this, for example from `init_per_suite/1'.
%%
%% Upgrade tests are performed as follows:
%%
-%% <ol>
-%% <li>Figure out which OTP release to test upgrade
+%% Figure out which OTP release to test upgrade
%% from. Start a node running that release and find the
%% application versions on that node. Terminate the
-%% node.</li>
-%% <li>Figure out all dependencies for the applications under
-%% test.</li>
-%% <li>Create a release containing the core
+%% node.
+%% Figure out all dependencies for the applications under
+%% test.
+%% Create a release containing the core
%% applications `kernel', `stdlib' and `sasl'
%% in addition to the application(s) under test and all
%% dependencies of these. The versions of the applications
%% under test will be the ones found on the OTP release to
%% upgrade from. The versions of all other applications will
%% be those found on the current node, i.e. the common_test
-%% node. This is the "From"-release.</li>
-%% <li>Create another release containing the same
+%% node. This is the "From"-release.
+%% Create another release containing the same
%% applications as in the previous step, but with all
%% application versions taken from the current node. This is
-%% the "To"-release.</li>
-%% <li>Install the "From"-release and start a new node
-%% running this release.</li>
-%% <li>Perform the upgrade test and allow customized
+%% the "To"-release.
+%% Install the "From"-release and start a new node
+%% running this release.
+%% Perform the upgrade test and allow customized
%% control by using callbacks:
-%% <ol>
-%% <li>Callback: `upgrade_init/2'</li>
-%% <li>Unpack the new release</li>
-%% <li>Install the new release</li>
-%% <li>Callback: `upgrade_upgraded/2'</li>
-%% <li>Install the original release</li>
-%% <li>Callback: `upgrade_downgraded/2'</li>
-%% </ol>
-%% </li>
-%% </ol>
+%% Callback: `upgrade_init/2'
+%% Unpack the new release
+%% Install the new release
+%% Callback: `upgrade_upgraded/2'
+%% Install the original release
+%% Callback: `upgrade_downgraded/2'
%%
%% `App' or `Apps'
%% specifies the applications under test, i.e. the applications
@@ -244,27 +229,25 @@ init(Config) ->
%%
%% `Level' specifies which OTP release to
%% pick the "From" versions from.
-%% <dl>
-%% <dt>major</dt>
-%% <dd>From verions are picked from the previous major
+%% major
+%% From verions are picked from the previous major
%% release. For example, if the test is run on an OTP-17
-%% node, `{@module}' will pick the application
+%% node, ct_release_test will pick the application
%% "From" versions from an OTP installation running OTP
-%% R16B.</dd>
+%% R16B.
%%
-%% <dt>minor</dt>
-%% <dd>From verions are picked from the current major
+%% minor
+%% From verions are picked from the current major
%% release. For example, if the test is run on an OTP-17
-%% node, `{@module}' will pick the application
+%% node, ct_release_test will pick the application
%% "From" versions from an OTP installation running an
-%% earlier patch level of OTP-17.</dd>
-%% </dl>
+%% earlier patch level of OTP-17.
%%
%% The application "To" versions are allways picked from the
%% current node, i.e. the common_test node.
%%
%% `Callback' specifies the module (normally the
-%% test suite) which implements the {@section Callback functions}, and
+%% test suite) which implements the Callback functions, and
%% the initial value of the `State' variable used in these
%% functions.
%%
@@ -273,10 +256,8 @@ init(Config) ->
%%
%% Example:
%%
-%% ```
%% minor_upgrade(Config) ->
%% ct_release_test:upgrade(ssl,minor,{?MODULE,[]},Config).
-%% '''
%%
upgrade(App,Level,Callback,Config) when is_atom(App) ->
upgrade([App],Level,Callback,Config);
@@ -318,10 +299,10 @@ upgrade(Apps,Level,Callback,Config) ->
-spec cleanup(Config) -> Result when
Config :: config(),
Result :: config().
-%% @doc Clean up after tests.
+%% Clean up after tests.
%%
%% This function shall be called from the `end_per_*' function
-%% complementing the `init_per_*' function where {@link init/1}
+%% complementing the `init_per_*' function where init/1
%% is called.
%%
%% It cleans up after the test, for example kills hanging
@@ -329,9 +310,8 @@ upgrade(Apps,Level,Callback,Config) ->
%%
%% Example:
%%
-%% ```
%% end_per_suite(Config) ->
-%% ct_release_test:cleanup(Config).'''
+%% ct_release_test:cleanup(Config).
%%
cleanup(Config) ->
AllNodes = [node_name(?testnode)|nodes()],
@@ -352,15 +332,15 @@ cleanup(Config) ->
From :: string(),
To :: string(),
Reason :: {app_not_found,App}.
-%% @doc Get versions involved in this upgrade for the given application.
+%% Get versions involved in this upgrade for the given application.
%%
%% This function can be called from inside any of the callback
%% functions. It returns the old (From) and new (To) versions involved
%% in the upgrade/downgrade test for the given application.
%%
-%% <code>CtData</code> must be the first argument received in the
+%% CtData must be the first argument received in the
%% calling callback function - an opaque data structure set by
-%% <code>ct_release_tests</code>.
+%% ct_release_tests.
get_app_vsns(#ct_data{from=FromApps,to=ToApps},App) ->
case {lists:keyfind(App,1,FromApps),lists:keyfind(App,1,ToApps)} of
{{App,FromVsn,_},{App,ToVsn,_}} ->
@@ -380,16 +360,16 @@ get_app_vsns(#ct_data{from=FromApps,to=ToApps},App) ->
Down :: [Instr],
Instr :: term(),
Reason :: {app_not_found,App} | {vsn_not_found,{App,From}}.
-%% @doc Get appup instructions for the given application.
+%% Get appup instructions for the given application.
%%
%% This function can be called from inside any of the callback
%% functions. It reads the appup file for the given application and
%% returns the instructions for upgrade and downgrade for the versions
%% in the test.
%%
-%% <code>CtData</code> must be the first argument received in the
+%% CtData must be the first argument received in the
%% calling callback function - an opaque data structure set by
-%% <code>ct_release_tests</code>.
+%% ct_release_tests.
%%
%% See reference manual for appup files for types definitions for the
%% instructions.
@@ -817,7 +797,7 @@ get_runtime_deps([App|Apps],StartApps,Acc,Visited) ->
RuntimeDeps =
lists:flatmap(
fun(Str) ->
- [RuntimeAppStr,_] = string:tokens(Str,"-"),
+ [RuntimeAppStr,_] = string:lexemes(Str,"-"),
RuntimeApp = list_to_atom(RuntimeAppStr),
case {lists:keymember(RuntimeApp,1,Acc),
lists:member(RuntimeApp,StartApps)} of
diff --git a/lib/common_test/src/ct_repeat.erl b/lib/common_test/src/ct_repeat.erl
index c043c9846c..8b1c7d47bb 100644
--- a/lib/common_test/src/ct_repeat.erl
+++ b/lib/common_test/src/ct_repeat.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,14 +18,14 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test Framework module that handles repeated test runs
+%%% doc Common Test Framework module that handles repeated test runs
%%%
-%%% <p>This module exports functions for repeating tests. The following
+%%% This module exports functions for repeating tests. The following
%%% start flags (or equivalent ct:run_test/1 options) are supported:
%%% -until <StopTime>, StopTime = YYMoMoDDHHMMSS | HHMMSS
%%% -duration <DurTime>, DurTime = HHMMSS
%%% -force_stop [skip_rest]
-%%% -repeat <N>, N = integer()</p>
+%%% -repeat <N>, N = integer()
-module(ct_repeat).
@@ -70,6 +70,7 @@ loop_test(If,Args) when is_list(Args) ->
CtrlPid = self(),
spawn(
fun() ->
+ ct_util:mark_process(),
stop_after(CtrlPid,Secs,ForceStop)
end)
end,
@@ -134,6 +135,7 @@ spawn_tester(script,Ctrl,Args) ->
spawn_tester(func,Ctrl,Opts) ->
Tester = fun() ->
+ ct_util:mark_process(),
case catch ct_run:run_test2(Opts) of
{'EXIT',Reason} ->
exit(Reason);
diff --git a/lib/common_test/src/ct_rpc.erl b/lib/common_test/src/ct_rpc.erl
index b4a0bc9d74..cef5ad14e5 100644
--- a/lib/common_test/src/ct_rpc.erl
+++ b/lib/common_test/src/ct_rpc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,8 +18,6 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test specific layer on Erlang/OTP rpc.
-
-module(ct_rpc).
%%% API
@@ -29,49 +27,12 @@
%%%=========================================================================
%%% API
%%%=========================================================================
-%%% @spec app_node(App, Candidates) -> NodeName
-%%%
-%%% App = atom()
-%%% Candidates = [NodeName]
-%%% NodeName = atom()
-%%%
-%%% @doc From a set of candidate nodes determines which of them is
-%%% running the application App. If none of the candidate nodes
-%%% is running the application the function will make the test case
-%%% calling this function fail. This function is the same as calling
-%%% <code>app_node(App, Candidates, true)</code>.
-%%%
app_node(App, Candidates) ->
app_node(App, Candidates, true, []).
-%%% @spec app_node(App, Candidates, FailOnBadRPC) -> NodeName
-%%%
-%%% App = atom()
-%%% Candidates = [NodeName]
-%%% NodeName = atom()
-%%% FailOnBadRPC = true | false
-%%%
-%%% @doc Same as <code>app_node/2</code> only the <code>FailOnBadRPC</code>
-%%% argument will determine if the search for a candidate node should
-%%% stop or not if <code>badrpc</code> is received at some point.
-%%%
app_node(App, Candidates, FailOnBadRPC) ->
app_node(App, Candidates, FailOnBadRPC, []).
-%%% @spec app_node(App, Candidates, FailOnBadRPC, Cookie) -> NodeName
-%%%
-%%% App = atom()
-%%% Candidates = [NodeName]
-%%% NodeName = atom()
-%%% FailOnBadRPC = true | false
-%%% Cookie = atom()
-%%%
-%%% @doc Same as <code>app_node/2</code> only the <code>FailOnBadRPC</code>
-%%% argument will determine if the search for a candidate node should
-%%% stop or not if <code>badrpc</code> is received at some point.
-%%% The cookie on the client node will be set to <code>Cookie</code>
-%%% for this rpc operation (use to match the server node cookie).
-%%%
app_node(App, [], _, _) ->
ct:fail({application_not_running, App});
@@ -96,49 +57,12 @@ app_node(App, _Candidates = [CandidateNode | Nodes], FailOnBadRPC, Cookie) ->
end
end.
-%%% @spec call(Node, Module, Function, Args) -> term() | {badrpc, Reason}
-%%%
-%%% @doc Same as call(Node, Module, Function, Args, infinity)
-%%%
call(Node, Module, Function, Args) ->
call(Node, Module, Function, Args, infinity, []).
-%%% @spec call(Node, Module, Function, Args, TimeOut) ->
-%%% term() | {badrpc, Reason}
-%%% Node = NodeName | {Fun, FunArgs}
-%%% Fun = fun()
-%%% FunArgs = term()
-%%% NodeName = atom()
-%%% Module = atom()
-%%% Function = atom()
-%%% Args = [term()]
-%%% Reason = timeout | term()
-%%%
-%%% @doc Evaluates apply(Module, Function, Args) on the node Node.
-%%% Returns whatever Function returns or {badrpc, Reason} if the
-%%% remote procedure call fails. If Node is {Fun, FunArgs} applying
-%%% Fun to FunArgs should return a node name.
call(Node, Module, Function, Args, TimeOut) ->
call(Node, Module, Function, Args, TimeOut, []).
-%%% @spec call(Node, Module, Function, Args, TimeOut, Cookie) ->
-%%% term() | {badrpc, Reason}
-%%% Node = NodeName | {Fun, FunArgs}
-%%% Fun = fun()
-%%% FunArgs = term()
-%%% NodeName = atom()
-%%% Module = atom()
-%%% Function = atom()
-%%% Args = [term()]
-%%% Reason = timeout | term()
-%%% Cookie = atom()
-%%%
-%%% @doc Evaluates apply(Module, Function, Args) on the node Node.
-%%% Returns whatever Function returns or {badrpc, Reason} if the
-%%% remote procedure call fails. If Node is {Fun, FunArgs} applying
-%%% Fun to FunArgs should return a node name.
-%%% The cookie on the client node will be set to <code>Cookie</code>
-%%% for this rpc operation (use to match the server node cookie).
call({Fun, FunArgs}, Module, Function, Args, TimeOut, Cookie) ->
Node = Fun(FunArgs),
call(Node, Module, Function, Args, TimeOut, Cookie);
@@ -148,42 +72,9 @@ call(Node, Module, Function, Args, TimeOut, Cookie) when is_atom(Node) ->
_ = set_the_cookie(Cookie0),
Result.
-%%% @spec cast(Node, Module, Function, Args) -> ok
-%%% Node = NodeName | {Fun, FunArgs}
-%%% Fun = fun()
-%%% FunArgs = term()
-%%% NodeName = atom()
-%%% Module = atom()
-%%% Function = atom()
-%%% Args = [term()]
-%%% Reason = timeout | term()
-%%%
-%%% @doc Evaluates apply(Module, Function, Args) on the node Node.
-%%% No response is delivered and the process which makes the call is
-%%% not suspended until the evaluation is compleated as in the case of
-%%% call/[3,4]. If Node is {Fun, FunArgs} applying
-%%% Fun to FunArgs should return a node name.
cast(Node, Module, Function, Args) ->
cast(Node, Module, Function, Args, []).
-%%% @spec cast(Node, Module, Function, Args, Cookie) -> ok
-%%% Node = NodeName | {Fun, FunArgs}
-%%% Fun = fun()
-%%% FunArgs = term()
-%%% NodeName = atom()
-%%% Module = atom()
-%%% Function = atom()
-%%% Args = [term()]
-%%% Reason = timeout | term()
-%%% Cookie = atom()
-%%%
-%%% @doc Evaluates apply(Module, Function, Args) on the node Node.
-%%% No response is delivered and the process which makes the call is
-%%% not suspended until the evaluation is compleated as in the case of
-%%% call/[3,4]. If Node is {Fun, FunArgs} applying
-%%% Fun to FunArgs should return a node name.
-%%% The cookie on the client node will be set to <code>Cookie</code>
-%%% for this rpc operation (use to match the server node cookie).
cast({Fun, FunArgs}, Module, Function, Args, Cookie) ->
Node = Fun(FunArgs),
cast(Node, Module, Function, Args, Cookie);
@@ -196,7 +87,6 @@ cast(Node, Module, Function, Args, Cookie) when is_atom(Node) ->
%%%---------- Internal -----------
-%%% @hidden
set_the_cookie([]) ->
[];
set_the_cookie(Cookie) ->
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index 14f28f9ca3..c9d406f1fd 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,11 +18,6 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test Framework test execution control module.
-%%%
-%%% <p>This module exports functions for installing and running tests
-%%% withing the Common Test Framework.</p>
-
-module(ct_run).
%% Script interface
@@ -84,17 +79,6 @@
tests,
starter}).
-%%%-----------------------------------------------------------------
-%%% @spec script_start() -> term()
-%%%
-%%% @doc Start tests via the ct_run program or script.
-%%%
-%%% <p>Example:<br/><code>./ct_run -config config.ctc -dir
-%%% $TEST_DIR</code></p>
-%%%
-%%% <p>Example:<br/><code>./ct_run -config config.ctc -suite
-%%% $SUITE_PATH/$SUITE_NAME [-case $CASE_NAME]</code></p>
-%%%
script_start() ->
process_flag(trap_exit, true),
Init = init:get_arguments(),
@@ -147,7 +131,7 @@ script_start(Args) ->
CTVsn =
case filename:basename(code:lib_dir(common_test)) of
CTBase when is_list(CTBase) ->
- case string:tokens(CTBase, "-") of
+ case string:lexemes(CTBase, "-") of
["common_test",Vsn] -> " v"++Vsn;
_ -> ""
end
@@ -250,6 +234,8 @@ finish(Tracing, ExitStatus, Args) ->
end.
script_start1(Parent, Args) ->
+ %% tag this process
+ ct_util:mark_process(),
%% read general start flags
Label = get_start_opt(label, fun([Lbl]) -> Lbl end, Args),
Profile = get_start_opt(profile, fun([Prof]) -> Prof end, Args),
@@ -315,7 +301,7 @@ script_start1(Parent, Args) ->
{undefined,InclDirs};
CtInclPath ->
AllInclDirs =
- string:tokens(CtInclPath,[$:,$ ,$,]) ++ InclDirs,
+ string:lexemes(CtInclPath,[$:,$ ,$,]) ++ InclDirs,
application:set_env(common_test, include, AllInclDirs),
{undefined,AllInclDirs}
end;
@@ -440,11 +426,9 @@ script_start2(Opts = #opts{vts = undefined,
TestSpecData ->
execute_all_specs(TestSpecData, Opts, Args, [])
catch
- throw:{error,Reason} ->
- StackTrace = erlang:get_stacktrace(),
+ throw:{error,Reason}:StackTrace ->
{error,{invalid_testspec,{Reason,StackTrace}}};
- _:Reason ->
- StackTrace = erlang:get_stacktrace(),
+ _:Reason:StackTrace ->
{error,{invalid_testspec,{Reason,StackTrace}}}
end;
[] ->
@@ -799,9 +783,6 @@ script_start4(#opts{shell = true, cover = Cover}, _) ->
script_start4(Opts = #opts{tests = Tests}, Args) ->
do_run(Tests, [], Opts, Args).
-%%%-----------------------------------------------------------------
-%%% @spec script_usage() -> ok
-%%% @doc Print usage information for <code>ct_run</code>.
script_usage() ->
io:format("\nUsage:\n\n"),
io:format("Run tests from command line:\n\n"
@@ -885,9 +866,6 @@ script_usage() ->
"\n\t [-basic_html]"
"\n\t [-no_esc_chars]\n\n").
-%%%-----------------------------------------------------------------
-%%% @hidden
-%%% @equiv ct:install/1
install(Opts) ->
install(Opts, ".").
@@ -931,15 +909,6 @@ install(Opts, LogDir) ->
variables_file_name(Dir) ->
filename:join(Dir, "variables-"++atom_to_list(node())).
-%%%-----------------------------------------------------------------
-%%% @spec run_test(Opts) -> Result
-%%% Opts = [tuple()]
-%%% Result = [TestResult] | {error,Reason}
-%%%
-%%% @doc Start tests from the erlang shell or from an erlang program.
-%%% @equiv ct:run_test/1
-%%%-----------------------------------------------------------------
-
run_test(StartOpt) when is_tuple(StartOpt) ->
run_test([StartOpt]);
@@ -956,7 +925,10 @@ run_test(StartOpts) when is_list(StartOpts) ->
-spec run_test1_fun(_) -> fun(() -> no_return()).
run_test1_fun(StartOpts) ->
- fun() -> run_test1(StartOpts) end.
+ fun() ->
+ ct_util:mark_process(),
+ run_test1(StartOpts)
+ end.
run_test1(StartOpts) when is_list(StartOpts) ->
case proplists:get_value(refresh_logs, StartOpts) of
@@ -1096,7 +1068,7 @@ run_test2(StartOpts) ->
application:set_env(common_test, include, InclDirs),
{undefined,InclDirs};
CtInclPath ->
- InclDirs1 = string:tokens(CtInclPath, [$:,$ ,$,]),
+ InclDirs1 = string:lexemes(CtInclPath, [$:,$ ,$,]),
AllInclDirs = InclDirs1++InclDirs,
application:set_env(common_test, include, AllInclDirs),
{undefined,AllInclDirs}
@@ -1206,11 +1178,9 @@ run_spec_file(Relaxed,
TestSpecData ->
run_all_specs(TestSpecData, Opts, StartOpts, [])
catch
- throw:{error,CTReason} ->
- StackTrace = erlang:get_stacktrace(),
+ throw:{error,CTReason}:StackTrace ->
exit({error,{invalid_testspec,{CTReason,StackTrace}}});
- _:CTReason ->
- StackTrace = erlang:get_stacktrace(),
+ _:CTReason:StackTrace ->
exit({error,{invalid_testspec,{CTReason,StackTrace}}})
end.
@@ -1426,14 +1396,6 @@ run_dir(Opts = #opts{logdir = LogDir,
exit({error,{incorrect_start_options,{Dir,Suite,GsAndCs}}})
end.
-%%%-----------------------------------------------------------------
-%%% @spec run_testspec(TestSpec) -> Result
-%%% TestSpec = [term()]
-%%%
-%%% @doc Run test specified by <code>TestSpec</code>. The terms are
-%%% the same as those used in test specification files.
-%%% @equiv ct:run_testspec/1
-%%%-----------------------------------------------------------------
run_testspec(TestSpec) ->
CTPid = spawn(run_testspec1_fun(TestSpec)),
Ref = monitor(process, CTPid),
@@ -1447,7 +1409,10 @@ run_testspec(TestSpec) ->
-spec run_testspec1_fun(_) -> fun(() -> no_return()).
run_testspec1_fun(TestSpec) ->
- fun() -> run_testspec1(TestSpec) end.
+ fun() ->
+ ct_util:mark_process(),
+ run_testspec1(TestSpec)
+ end.
run_testspec1(TestSpec) ->
{ok,Cwd} = file:get_cwd(),
@@ -1482,7 +1447,7 @@ run_testspec2(TestSpec) ->
false ->
Opts#opts.include;
CtInclPath ->
- EnvInclude = string:tokens(CtInclPath, [$:,$ ,$,]),
+ EnvInclude = string:lexemes(CtInclPath, [$:,$ ,$,]),
EnvInclude++Opts#opts.include
end,
application:set_env(common_test, include, AllInclude),
@@ -1630,9 +1595,6 @@ delistify([E]) -> E;
delistify(E) -> E.
-%%%-----------------------------------------------------------------
-%%% @hidden
-%%% @equiv ct:run/3
run(TestDir, Suite, Cases) ->
case install([]) of
ok ->
@@ -1641,9 +1603,6 @@ run(TestDir, Suite, Cases) ->
Error
end.
-%%%-----------------------------------------------------------------
-%%% @hidden
-%%% @equiv ct:run/2
run(TestDir, Suite) when is_list(TestDir), is_integer(hd(TestDir)) ->
case install([]) of
ok ->
@@ -1652,9 +1611,6 @@ run(TestDir, Suite) when is_list(TestDir), is_integer(hd(TestDir)) ->
Error
end.
-%%%-----------------------------------------------------------------
-%%% @hidden
-%%% @equiv ct:run/1
run(TestDirs) ->
case install([]) of
ok ->
@@ -1906,10 +1862,12 @@ possibly_spawn(true, Tests, Skip, Opts) ->
CTUtilSrv = whereis(ct_util_server),
Supervisor =
fun() ->
+ ct_util:mark_process(),
process_flag(trap_exit, true),
link(CTUtilSrv),
TestRun =
fun() ->
+ ct_util:mark_process(),
TestResult = (catch do_run_test(Tests, Skip, Opts)),
case TestResult of
{EType,_} = Error when EType == user_error;
@@ -1951,7 +1909,8 @@ auto_compile(TestSuites) ->
SuiteMakeErrors =
lists:flatmap(fun({TestDir,Suite} = TS) ->
case run_make(suites, TestDir,
- Suite, UserInclude) of
+ Suite, UserInclude,
+ [nowarn_export_all]) of
{error,{make_failed,Bad}} ->
[{TS,Bad}];
{error,_} ->
@@ -1969,7 +1928,7 @@ auto_compile(TestSuites) ->
case lists:member(Dir, Done) of
false ->
Failed1 =
- case run_make(helpmods, Dir, Suite, UserInclude) of
+ case run_make(helpmods, Dir, Suite, UserInclude, []) of
{error,{make_failed,BadMods}} ->
[{{Dir,all},BadMods}|Failed];
{error,_} ->
@@ -2062,16 +2021,9 @@ get_bad_suites([], BadSuites) ->
BadSuites.
-
-%%%-----------------------------------------------------------------
-%%% @hidden
-%%% @equiv ct:step/3
step(TestDir, Suite, Case) ->
step(TestDir, Suite, Case, []).
-%%%-----------------------------------------------------------------
-%%% @hidden
-%%% @equiv ct:step/4
step(TestDir, Suite, Case, Opts) when is_list(TestDir),
is_atom(Suite), is_atom(Case),
Suite =/= all, Case =/= all ->
@@ -2718,12 +2670,12 @@ get_name(Dir) ->
run_make(TestDir, Mod, UserInclude) ->
- run_make(suites, TestDir, Mod, UserInclude).
+ run_make(suites, TestDir, Mod, UserInclude, [nowarn_export_all]).
-run_make(Targets, TestDir0, Mod, UserInclude) when is_list(Mod) ->
- run_make(Targets, TestDir0, list_to_atom(Mod), UserInclude);
+run_make(Targets, TestDir0, Mod, UserInclude, COpts) when is_list(Mod) ->
+ run_make(Targets, TestDir0, list_to_atom(Mod), UserInclude, COpts);
-run_make(Targets, TestDir0, Mod, UserInclude) ->
+run_make(Targets, TestDir0, Mod, UserInclude, COpts) ->
case locate_test_dir(TestDir0, Mod) of
{ok,TestDir} ->
%% send a start_make notification which may suspend
@@ -2738,7 +2690,7 @@ run_make(Targets, TestDir0, Mod, UserInclude) ->
XmerlInclude = get_dir(xmerl, "include"),
ErlFlags = UserInclude ++ [{i,CtInclude},
{i,XmerlInclude},
- debug_info],
+ debug_info] ++ COpts,
Result =
if Mod == all ; Targets == helpmods ->
case (catch ct_make:all([noexec|ErlFlags])) of
diff --git a/lib/common_test/src/ct_slave.erl b/lib/common_test/src/ct_slave.erl
index 4188bd7c3b..dde33440be 100644
--- a/lib/common_test/src/ct_slave.erl
+++ b/lib/common_test/src/ct_slave.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -17,13 +17,6 @@
%%
%% %CopyrightEnd%
-%%% @doc Common Test Framework functions for starting and stopping nodes for
-%%% Large Scale Testing.
-%%%
-%%% <p>This module exports functions which are used by the Common Test Master
-%%% to start and stop "slave" nodes. It is the default callback module for the
-%%% <code>{init, node_start}</code> term of the Test Specification.</p>
-
%%----------------------------------------------------------------------
%% File : ct_slave.erl
%% Description : CT module for starting nodes for large-scale testing.
@@ -38,44 +31,12 @@
-record(options, {username, password, boot_timeout, init_timeout,
startup_timeout, startup_functions, monitor_master,
- kill_if_fail, erl_flags, env, ssh_port, ssh_opts}).
-
-%%%-----------------------------------------------------------------
-%%% @spec start(Node) -> Result
-%%% Node = atom()
-%%% Result = {ok, NodeName} |
-%%% {error, Reason, NodeName}
-%%% Reason = already_started |
-%%% started_not_connected |
-%%% boot_timeout |
-%%% init_timeout |
-%%% startup_timeout |
-%%% not_alive
-%%% NodeName = atom()
-%%% @doc Starts an Erlang node with name <code>Node</code> on the local host.
-%%% @see start/3
+ kill_if_fail, erl_flags, env, ssh_port, ssh_opts,
+ stop_timeout}).
+
start(Node) ->
start(gethostname(), Node).
-%%%-----------------------------------------------------------------
-%%% @spec start(HostOrNode, NodeOrOpts) -> Result
-%%% HostOrNode = atom()
-%%% NodeOrOpts = atom() | list()
-%%% Result = {ok, NodeName} |
-%%% {error, Reason, NodeName}
-%%% Reason = already_started |
-%%% started_not_connected |
-%%% boot_timeout |
-%%% init_timeout |
-%%% startup_timeout |
-%%% not_alive
-%%% NodeName = atom()
-%%% @doc Starts an Erlang node with default options on a specified
-%%% host, or on the local host with specified options. That is,
-%%% the call is interpreted as <code>start(Host, Node)</code> when the
-%%% second argument is atom-valued and <code>start(Node, Opts)</code>
-%%% when it's list-valued.
-%%% @see start/3
start(_HostOrNode = Node, _NodeOrOpts = Opts) %% match to satiate edoc
when is_list(Opts) ->
start(gethostname(), Node, Opts);
@@ -83,104 +44,6 @@ start(_HostOrNode = Node, _NodeOrOpts = Opts) %% match to satiate edoc
start(Host, Node) ->
start(Host, Node, []).
-%%%-----------------------------------------------------------------
-%%% @spec start(Host, Node, Opts) -> Result
-%%% Node = atom()
-%%% Host = atom()
-%%% Opts = [OptTuples]
-%%% OptTuples = {username, Username} |
-%%% {password, Password} |
-%%% {boot_timeout, BootTimeout} | {init_timeout, InitTimeout} |
-%%% {startup_timeout, StartupTimeout} |
-%%% {startup_functions, StartupFunctions} |
-%%% {monitor_master, Monitor} |
-%%% {kill_if_fail, KillIfFail} |
-%%% {erl_flags, ErlangFlags} |
-%%% {env, [{EnvVar,Value}]}
-%%% Username = string()
-%%% Password = string()
-%%% BootTimeout = integer()
-%%% InitTimeout = integer()
-%%% StartupTimeout = integer()
-%%% StartupFunctions = [StartupFunctionSpec]
-%%% StartupFunctionSpec = {Module, Function, Arguments}
-%%% Module = atom()
-%%% Function = atom()
-%%% Arguments = [term]
-%%% Monitor = bool()
-%%% KillIfFail = bool()
-%%% ErlangFlags = string()
-%%% EnvVar = string()
-%%% Value = string()
-%%% Result = {ok, NodeName} |
-%%% {error, Reason, NodeName}
-%%% Reason = already_started |
-%%% started_not_connected |
-%%% boot_timeout |
-%%% init_timeout |
-%%% startup_timeout |
-%%% not_alive
-%%% NodeName = atom()
-%%% @doc Starts an Erlang node with name <code>Node</code> on host
-%%% <code>Host</code> as specified by the combination of options in
-%%% <code>Opts</code>.
-%%%
-%%% <p>Options <code>Username</code> and <code>Password</code> will be used
-%%% to log in onto the remote host <code>Host</code>.
-%%% Username, if omitted, defaults to the current user name,
-%%% and password is empty by default.</p>
-%%%
-%%% <p>A list of functions specified in the <code>Startup</code> option will be
-%%% executed after startup of the node. Note that all used modules should be
-%%% present in the code path on the <code>Host</code>.</p>
-%%%
-%%% <p>The timeouts are applied as follows:</p>
-%%% <list>
-%%% <item>
-%%% <code>BootTimeout</code> - time to start the Erlang node, in seconds.
-%%% Defaults to 3 seconds. If node does not become pingable within this time,
-%%% the result <code>{error, boot_timeout, NodeName}</code> is returned;
-%%% </item>
-%%% <item>
-%%% <code>InitTimeout</code> - time to wait for the node until it calls the
-%%% internal callback function informing master about successfull startup.
-%%% Defaults to one second.
-%%% In case of timed out message the result
-%%% <code>{error, init_timeout, NodeName}</code> is returned;
-%%% </item>
-%%% <item>
-%%% <code>StartupTimeout</code> - time to wait intil the node finishes to run
-%%% the <code>StartupFunctions</code>. Defaults to one second.
-%%% If this timeout occurs, the result
-%%% <code>{error, startup_timeout, NodeName}</code> is returned.
-%%% </item>
-%%% </list>
-%%%
-%%% <p>Option <code>monitor_master</code> specifies, if the slave node should be
-%%% stopped in case of master node stop. Defaults to false.</p>
-%%%
-%%% <p>Option <code>kill_if_fail</code> specifies, if the slave node should be
-%%% killed in case of a timeout during initialization or startup.
-%%% Defaults to true. Note that node also may be still alive it the boot
-%%% timeout occurred, but it will not be killed in this case.</p>
-%%%
-%%% <p>Option <code>erlang_flags</code> specifies, which flags will be added
-%%% to the parameters of the <code>erl</code> executable.</p>
-%%%
-%%% <p>Option <code>env</code> specifies a list of environment variables
-%%% that will extended the environment.</p>
-%%%
-%%% <p>Special return values are:</p>
-%%% <list>
-%%% <item><code>{error, already_started, NodeName}</code> - if the node with
-%%% the given name is already started on a given host;</item>
-%%% <item><code>{error, started_not_connected, NodeName}</code> - if node is
-%%% started, but not connected to the master node.</item>
-%%% <item><code>{error, not_alive, NodeName}</code> - if node on which the
-%%% <code>ct_slave:start/3</code> is called, is not alive. Note that
-%%% <code>NodeName</code> is the name of current node in this case.</item>
-%%% </list>
-%%%
start(Host, Node, Opts) ->
ENode = enodename(Host, Node),
case erlang:is_alive() of
@@ -198,36 +61,22 @@ start(Host, Node, Opts) ->
end
end.
-%%% @spec stop(Node) -> Result
-%%% Node = atom()
-%%% Result = {ok, NodeName} |
-%%% {error, Reason, NodeName}
-%%% Reason = not_started |
-%%% not_connected |
-%%% stop_timeout
-
-%%% NodeName = atom()
-%%% @doc Stops the running Erlang node with name <code>Node</code> on
-%%% the localhost.
stop(Node) ->
stop(gethostname(), Node).
-%%% @spec stop(Host, Node) -> Result
-%%% Host = atom()
-%%% Node = atom()
-%%% Result = {ok, NodeName} |
-%%% {error, Reason, NodeName}
-%%% Reason = not_started |
-%%% not_connected |
-%%% stop_timeout
-%%% NodeName = atom()
-%%% @doc Stops the running Erlang node with name <code>Node</code> on
-%%% host <code>Host</code>.
+stop(_HostOrNode = Node, _NodeOrOpts = Opts) %% match to satiate edoc
+ when is_list(Opts) ->
+ stop(gethostname(), Node, Opts);
+
stop(Host, Node) ->
+ stop(Host, Node, []).
+
+stop(Host, Node, Opts) ->
ENode = enodename(Host, Node),
case is_started(ENode) of
{true, connected}->
- do_stop(ENode);
+ OptionsRec = fetch_options(Opts),
+ do_stop(ENode, OptionsRec);
{true, not_connected}->
{error, not_connected, ENode};
false->
@@ -257,31 +106,31 @@ fetch_options(Options) ->
EnvVars = get_option_value(env, Options, []),
SSHPort = get_option_value(ssh_port, Options, []),
SSHOpts = get_option_value(ssh_opts, Options, []),
+ StopTimeout = get_option_value(stop_timeout, Options, 5),
#options{username=UserName, password=Password,
boot_timeout=BootTimeout, init_timeout=InitTimeout,
startup_timeout=StartupTimeout, startup_functions=StartupFunctions,
monitor_master=Monitor, kill_if_fail=KillIfFail,
- erl_flags=ErlFlags, env=EnvVars, ssh_port=SSHPort, ssh_opts=SSHOpts}.
+ erl_flags=ErlFlags, env=EnvVars, ssh_port=SSHPort, ssh_opts=SSHOpts,
+ stop_timeout=StopTimeout}.
% send a message when slave node is started
-% @hidden
slave_started(ENode, MasterPid) ->
MasterPid ! {node_started, ENode},
ok.
% send a message when slave node has finished startup
-% @hidden
slave_ready(ENode, MasterPid) ->
MasterPid ! {node_ready, ENode},
ok.
% start monitoring of the master node
-% @hidden
monitor_master(MasterNode) ->
spawn(fun() -> monitor_master_int(MasterNode) end).
% code of the masterdeath-waiter process
monitor_master_int(MasterNode) ->
+ ct_util:mark_process(),
erlang:monitor_node(MasterNode, true),
receive
{nodedown, MasterNode}->
@@ -461,6 +310,8 @@ wait_for_node_alive(Node, N) ->
% call init:stop on a remote node
do_stop(ENode) ->
+ do_stop(ENode, fetch_options([])).
+do_stop(ENode, Options) ->
{Cover,MainCoverNode} =
case test_server:is_cover() of
true ->
@@ -471,7 +322,8 @@ do_stop(ENode) ->
{false,undefined}
end,
spawn(ENode, init, stop, []),
- case wait_for_node_dead(ENode, 5) of
+ StopTimeout = Options#options.stop_timeout,
+ case wait_for_node_dead(ENode, StopTimeout) of
{ok,ENode} ->
if Cover ->
%% To avoid that cover is started again if a node
diff --git a/lib/common_test/src/ct_snmp.erl b/lib/common_test/src/ct_snmp.erl
index 5844909d17..27b74dd04e 100644
--- a/lib/common_test/src/ct_snmp.erl
+++ b/lib/common_test/src/ct_snmp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,139 +18,8 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test user interface module for the OTP snmp application
-%%%
-%%% <p>The purpose of this module is to make snmp configuration easier for
-%%% the test case writer. Many test cases can use default values for common
-%%% operations and then no snmp configuration files need to be supplied. When
-%%% it is necessary to change particular configuration parameters, a subset
-%%% of the relevant snmp configuration files may be passed to <code>ct_snmp</code>
-%%% by means of Common Test configuration files.
-%%% For more specialized configuration parameters, it is possible to place a
-%%% "simple snmp configuration file" in the test suite data directory.
-%%% To simplify the test suite, Common Test keeps track
-%%% of some of the snmp manager information. This way the test suite doesn't
-%%% have to handle as many input parameters as it would if it had to interface the
-%%% OTP snmp manager directly.</p>
-%%%
-%%% <p> The following snmp manager and agent parameters are configurable: </p>
-%%%
-%%% <pre>
-%%% {snmp,
-%%% %%% Manager config
-%%% [{start_manager, boolean()} % Optional - default is true
-%%% {users, [{user_name(), [call_back_module(), user_data()]}]}, %% Optional
-%%% {usm_users, [{usm_user_name(), [usm_config()]}]},%% Optional - snmp v3 only
-%%% % managed_agents is optional
-%%% {managed_agents,[{agent_name(), [user_name(), agent_ip(), agent_port(), [agent_config()]]}]},
-%%% {max_msg_size, integer()}, % Optional - default is 484
-%%% {mgr_port, integer()}, % Optional - default is 5000
-%%% {engine _id, string()}, % Optional - default is "mgrEngine"
-%%%
-%%% %%% Agent config
-%%% {start_agent, boolean()}, % Optional - default is false
-%%% {agent_sysname, string()}, % Optional - default is "ct_test"
-%%% {agent_manager_ip, manager_ip()}, % Optional - default is localhost
-%%% {agent_vsns, list()}, % Optional - default is [v2]
-%%% {agent_trap_udp, integer()}, % Optional - default is 5000
-%%% {agent_udp, integer()}, % Optional - default is 4000
-%%% {agent_notify_type, atom()}, % Optional - default is trap
-%%% {agent_sec_type, sec_type()}, % Optional - default is none
-%%% {agent_passwd, string()}, % Optional - default is ""
-%%% {agent_engine_id, string()}, % Optional - default is "agentEngine"
-%%% {agent_max_msg_size, string()},% Optional - default is 484
-%%%
-%%% %% The following parameters represents the snmp configuration files
-%%% %% context.conf, standard.conf, community.conf, vacm.conf,
-%%% %% usm.conf, notify.conf, target_addr.conf and target_params.conf.
-%%% %% Note all values in agent.conf can be altered by the parametes
-%%% %% above. All these configuration files have default values set
-%%% %% up by the snmp application. These values can be overridden by
-%%% %% suppling a list of valid configuration values or a file located
-%%% %% in the test suites data dir that can produce a list
-%%% %% of valid configuration values if you apply file:consult/1 to the
-%%% %% file.
-%%% {agent_contexts, [term()] | {data_dir_file, rel_path()}}, % Optional
-%%% {agent_community, [term()] | {data_dir_file, rel_path()}},% Optional
-%%% {agent_sysinfo, [term()] | {data_dir_file, rel_path()}}, % Optional
-%%% {agent_vacm, [term()] | {data_dir_file, rel_path()}}, % Optional
-%%% {agent_usm, [term()] | {data_dir_file, rel_path()}}, % Optional
-%%% {agent_notify_def, [term()] | {data_dir_file, rel_path()}},% Optional
-%%% {agent_target_address_def, [term()] | {data_dir_file, rel_path()}},% Optional
-%%% {agent_target_param_def, [term()] | {data_dir_file, rel_path()}},% Optional
-%%% ]}.
-%%% </pre>
-%%%
-%%% <p>The <code>MgrAgentConfName</code> parameter in the functions
-%%% should be a name you allocate in your test suite using a
-%%% <code>require</code> statement.
-%%% Example (where <code>MgrAgentConfName = snmp_mgr_agent</code>):</p>
-%%% <pre> suite() -> [{require, snmp_mgr_agent, snmp}].</pre>
-%%% <p>or</p>
-%%% <pre> ct:require(snmp_mgr_agent, snmp).</pre>
-%%%
-%%% <p> Note that Usm users are needed for snmp v3 configuration and are
-%%% not to be confused with users.</p>
-%%%
-%%% <p> Snmp traps, inform and report messages are handled by the
-%%% user callback module. For more information about this see
-%%% the snmp application. </p>
-%%% <p> Note: It is recommended to use the .hrl-files created by the
-%%% Erlang/OTP mib-compiler to define the oids.
-%%% Example for the getting the erlang node name from the erlNodeTable
-%%% in the OTP-MIB:</p>
-%%% <pre>Oid = ?erlNodeEntry ++ [?erlNodeName, 1] </pre>
-%%%
-%%% <p>It is also possible to set values for snmp application configuration
-%%% parameters, such as <code>config</code>, <code>server</code>,
-%%% <code>net_if</code>, etc (see the "Configuring the application" chapter in
-%%% the OTP snmp User's Guide for a list of valid parameters and types). This is
-%%% done by defining a configuration data variable on the following form:</p>
-%%% <pre>
-%%% {snmp_app, [{manager, [snmp_app_manager_params()]},
-%%% {agent, [snmp_app_agent_params()]}]}.</pre>
-%%%
-%%% <p>A name for the data needs to be allocated in the suite using
-%%% <code>require</code> (see example above), and this name passed as
-%%% the <code>SnmpAppConfName</code> argument to <code>start/3</code>.
-%%% <code>ct_snmp</code> specifies default values for some snmp application
-%%% configuration parameters (such as <code>{verbosity,trace}</code> for the
-%%% <code>config</code> parameter). This set of defaults will be
-%%% merged with the parameters specified by the user, and user values
-%%% override <code>ct_snmp</code> defaults.</p>
-
-module(ct_snmp).
-%%% Common Types
-%%% @type agent_ip() = ip()
-%%% @type manager_ip() = ip()
-%%% @type agent_name() = atom()
-%%% @type ip() = string() | {integer(), integer(),
-%%% integer(), integer()}
-%%% @type agent_port() = integer()
-%%% @type agent_config() = {Item, Value}
-%%% @type user_name() = atom()
-%%% @type usm_user_name() = string()
-%%% @type usm_config() = {Item, Value}
-%%% @type call_back_module() = atom()
-%%% @type user_data() = term()
-%%% @type oids() = [oid()]
-%%% @type oid() = [byte()]
-%%% @type snmpreply() = {error_status(), error_index(), varbinds()}
-%%% @type error_status() = noError | atom()
-%%% @type error_index() = integer()
-%%% @type varbinds() = [varbind()]
-%%% @type varbind() = term()
-%%% @type value_type() = o ('OBJECT IDENTIFIER') | i ('INTEGER') |
-%%% u ('Unsigned32') | g ('Unsigned32') | s ('OCTET STRING')
-%%% @type varsandvals() = [var_and_val()]
-%%% @type var_and_val() = {oid(), value_type(), value()}
-%%% @type sec_type() = none | minimum | semi
-%%% @type rel_path() = string()
-%%% @type snmp_app_manager_params() = term()
-%%% @type snmp_app_agent_params() = term()
-
-
-include("snmp_types.hrl").
-include("inet.hrl").
-include("ct.hrl").
@@ -181,31 +50,9 @@
%%% API
%%%=========================================================================
-%%%-----------------------------------------------------------------
-%%% @spec start(Config, MgrAgentConfName) -> ok
-%%% @equiv start(Config, MgrAgentConfName, undefined)
start(Config, MgrAgentConfName) ->
start(Config, MgrAgentConfName, undefined).
-%%% @spec start(Config, MgrAgentConfName, SnmpAppConfName) -> ok
-%%% Config = [{Key, Value}]
-%%% Key = atom()
-%%% Value = term()
-%%% MgrAgentConfName = atom()
-%%% SnmpConfName = atom()
-%%%
-%%% @doc Starts an snmp manager and/or agent. In the manager case,
-%%% registrations of users and agents as specified by the configuration
-%%% <code>MgrAgentConfName</code> will be performed. When using snmp
-%%% v3 also so called usm users will be registered. Note that users,
-%%% usm_users and managed agents may also be registered at a later time
-%%% using ct_snmp:register_users/2, ct_snmp:register_agents/2, and
-%%% ct_snmp:register_usm_users/2. The agent started will be
-%%% called <code>snmp_master_agent</code>. Use ct_snmp:load_mibs/1 to load
-%%% mibs into the agent. With <code>SnmpAppConfName</code> it's possible
-%%% to configure the snmp application with parameters such as <code>config</code>,
-%%% <code>mibs</code>, <code>net_if</code>, etc. The values will be merged
-%%% with (and possibly override) default values set by <code>ct_snmp</code>.
start(Config, MgrAgentConfName, SnmpAppConfName) ->
StartManager= ct:get_config({MgrAgentConfName, start_manager}, true),
StartAgent = ct:get_config({MgrAgentConfName, start_agent}, false),
@@ -233,12 +80,6 @@ start_application(App) ->
Else
end.
-%%% @spec stop(Config) -> ok
-%%% Config = [{Key, Value}]
-%%% Key = atom()
-%%% Value = term()
-%%%
-%%% @doc Stops the snmp manager and/or agent removes all files created.
stop(Config) ->
PrivDir = ?config(priv_dir, Config),
ok = application:stop(snmp),
@@ -251,41 +92,16 @@ stop(Config) ->
catch del_dir(DbDir).
-%%% @spec get_values(Agent, Oids, MgrAgentConfName) -> SnmpReply
-%%%
-%%% Agent = agent_name()
-%%% Oids = oids()
-%%% MgrAgentConfName = atom()
-%%% SnmpReply = snmpreply()
-%%%
-%%% @doc Issues a synchronous snmp get request.
get_values(Agent, Oids, MgrAgentConfName) ->
[Uid | _] = agent_conf(Agent, MgrAgentConfName),
{ok, SnmpReply, _} = snmpm:sync_get2(Uid, target_name(Agent), Oids),
SnmpReply.
-%%% @spec get_next_values(Agent, Oids, MgrAgentConfName) -> SnmpReply
-%%%
-%%% Agent = agent_name()
-%%% Oids = oids()
-%%% MgrAgentConfName = atom()
-%%% SnmpReply = snmpreply()
-%%%
-%%% @doc Issues a synchronous snmp get next request.
get_next_values(Agent, Oids, MgrAgentConfName) ->
[Uid | _] = agent_conf(Agent, MgrAgentConfName),
{ok, SnmpReply, _} = snmpm:sync_get_next2(Uid, target_name(Agent), Oids),
SnmpReply.
-%%% @spec set_values(Agent, VarsAndVals, MgrAgentConfName, Config) -> SnmpReply
-%%%
-%%% Agent = agent_name()
-%%% Oids = oids()
-%%% MgrAgentConfName = atom()
-%%% Config = [{Key, Value}]
-%%% SnmpReply = snmpreply()
-%%%
-%%% @doc Issues a synchronous snmp set request.
set_values(Agent, VarsAndVals, MgrAgentConfName, Config) ->
PrivDir = ?config(priv_dir, Config),
[Uid | _] = agent_conf(Agent, MgrAgentConfName),
@@ -301,19 +117,6 @@ set_values(Agent, VarsAndVals, MgrAgentConfName, Config) ->
end,
SnmpSetReply.
-%%% @spec set_info(Config) -> [{Agent, OldVarsAndVals, NewVarsAndVals}]
-%%%
-%%% Config = [{Key, Value}]
-%%% Agent = agent_name()
-%%% OldVarsAndVals = varsandvals()
-%%% NewVarsAndVals = varsandvals()
-%%%
-%%% @doc Returns a list of all successful set requests performed in
-%%% the test case in reverse order. The list contains the involved
-%%% user and agent, the value prior to the set and the new value. This
-%%% is intended to facilitate the clean up in the end_per_testcase
-%%% function i.e. the undoing of the set requests and its possible
-%%% side-effects.
set_info(Config) ->
PrivDir = ?config(priv_dir, Config),
SetLogFile = filename:join(PrivDir, ?CT_SNMP_LOG_FILE),
@@ -325,18 +128,6 @@ set_info(Config) ->
[]
end.
-%%% @spec register_users(MgrAgentConfName, Users) -> ok | {error, Reason}
-%%%
-%%% MgrAgentConfName = atom()
-%%% Users = [user()]
-%%% Reason = term()
-%%%
-%%% @doc Register the manager entity (=user) responsible for specific agent(s).
-%%% Corresponds to making an entry in users.conf.
-%%%
-%%% <p>This function will try to register the given users, without
-%%% checking if any of them already exist. In order to change an
-%%% already registered user, the user must first be unregistered.</p>
register_users(MgrAgentConfName, Users) ->
case setup_users(Users) of
ok ->
@@ -350,19 +141,6 @@ register_users(MgrAgentConfName, Users) ->
Error
end.
-%%% @spec register_agents(MgrAgentConfName, ManagedAgents) -> ok | {error, Reason}
-%%%
-%%% MgrAgentConfName = atom()
-%%% ManagedAgents = [agent()]
-%%% Reason = term()
-%%%
-%%% @doc Explicitly instruct the manager to handle this agent.
-%%% Corresponds to making an entry in agents.conf
-%%%
-%%% <p>This function will try to register the given managed agents,
-%%% without checking if any of them already exist. In order to change
-%%% an already registered managed agent, the agent must first be
-%%% unregistered.</p>
register_agents(MgrAgentConfName, ManagedAgents) ->
case setup_managed_agents(MgrAgentConfName,ManagedAgents) of
ok ->
@@ -377,18 +155,6 @@ register_agents(MgrAgentConfName, ManagedAgents) ->
Error
end.
-%%% @spec register_usm_users(MgrAgentConfName, UsmUsers) -> ok | {error, Reason}
-%%%
-%%% MgrAgentConfName = atom()
-%%% UsmUsers = [usm_user()]
-%%% Reason = term()
-%%%
-%%% @doc Explicitly instruct the manager to handle this USM user.
-%%% Corresponds to making an entry in usm.conf
-%%%
-%%% <p>This function will try to register the given users, without
-%%% checking if any of them already exist. In order to change an
-%%% already registered user, the user must first be unregistered.</p>
register_usm_users(MgrAgentConfName, UsmUsers) ->
EngineID = ct:get_config({MgrAgentConfName, engine_id}, ?ENGINE_ID),
case setup_usm_users(UsmUsers, EngineID) of
@@ -403,23 +169,10 @@ register_usm_users(MgrAgentConfName, UsmUsers) ->
Error
end.
-%%% @spec unregister_users(MgrAgentConfName) -> ok
-%%%
-%%% MgrAgentConfName = atom()
-%%% Reason = term()
-%%%
-%%% @doc Unregister all users.
unregister_users(MgrAgentConfName) ->
Users = [Id || {Id,_} <- ct:get_config({MgrAgentConfName, users},[])],
unregister_users(MgrAgentConfName,Users).
-%%% @spec unregister_users(MgrAgentConfName,Users) -> ok
-%%%
-%%% MgrAgentConfName = atom()
-%%% Users = [user_name()]
-%%% Reason = term()
-%%%
-%%% @doc Unregister the given users.
unregister_users(MgrAgentConfName,Users) ->
takedown_users(Users),
SnmpVals = ct:get_config(MgrAgentConfName),
@@ -432,25 +185,12 @@ unregister_users(MgrAgentConfName,Users) ->
ct_config:update_config(MgrAgentConfName, NewSnmpVals),
ok.
-%%% @spec unregister_agents(MgrAgentConfName) -> ok
-%%%
-%%% MgrAgentConfName = atom()
-%%% Reason = term()
-%%%
-%%% @doc Unregister all managed agents.
unregister_agents(MgrAgentConfName) ->
ManagedAgents = [AgentName ||
{AgentName, _} <-
ct:get_config({MgrAgentConfName,managed_agents},[])],
unregister_agents(MgrAgentConfName,ManagedAgents).
-%%% @spec unregister_agents(MgrAgentConfName,ManagedAgents) -> ok
-%%%
-%%% MgrAgentConfName = atom()
-%%% ManagedAgents = [agent_name()]
-%%% Reason = term()
-%%%
-%%% @doc Unregister the given managed agents.
unregister_agents(MgrAgentConfName,ManagedAgents) ->
takedown_managed_agents(MgrAgentConfName, ManagedAgents),
SnmpVals = ct:get_config(MgrAgentConfName),
@@ -464,23 +204,10 @@ unregister_agents(MgrAgentConfName,ManagedAgents) ->
ct_config:update_config(MgrAgentConfName, NewSnmpVals),
ok.
-%%% @spec unregister_usm_users(MgrAgentConfName) -> ok
-%%%
-%%% MgrAgentConfName = atom()
-%%% Reason = term()
-%%%
-%%% @doc Unregister all usm users.
unregister_usm_users(MgrAgentConfName) ->
UsmUsers = [Id || {Id,_} <- ct:get_config({MgrAgentConfName, usm_users},[])],
unregister_usm_users(MgrAgentConfName,UsmUsers).
-%%% @spec unregister_usm_users(MgrAgentConfName,UsmUsers) -> ok
-%%%
-%%% MgrAgentConfName = atom()
-%%% UsmUsers = [usm_user_name()]
-%%% Reason = term()
-%%%
-%%% @doc Unregister the given usm users.
unregister_usm_users(MgrAgentConfName,UsmUsers) ->
EngineID = ct:get_config({MgrAgentConfName, engine_id}, ?ENGINE_ID),
takedown_usm_users(UsmUsers,EngineID),
@@ -495,23 +222,9 @@ unregister_usm_users(MgrAgentConfName,UsmUsers) ->
ct_config:update_config(MgrAgentConfName, NewSnmpVals),
ok.
-%%% @spec load_mibs(Mibs) -> ok | {error, Reason}
-%%%
-%%% Mibs = [MibName]
-%%% MibName = string()
-%%% Reason = term()
-%%%
-%%% @doc Load the mibs into the agent 'snmp_master_agent'.
load_mibs(Mibs) ->
snmpa:load_mibs(snmp_master_agent, Mibs).
-%%% @spec unload_mibs(Mibs) -> ok | {error, Reason}
-%%%
-%%% Mibs = [MibName]
-%%% MibName = string()
-%%% Reason = term()
-%%%
-%%% @doc Unload the mibs from the agent 'snmp_master_agent'.
unload_mibs(Mibs) ->
snmpa:unload_mibs(snmp_master_agent, Mibs).
diff --git a/lib/common_test/src/ct_ssh.erl b/lib/common_test/src/ct_ssh.erl
index ca62357e1c..79ab122452 100644
--- a/lib/common_test/src/ct_ssh.erl
+++ b/lib/common_test/src/ct_ssh.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,44 +18,6 @@
%% %CopyrightEnd%
%%
-%%% @doc SSH/SFTP client module.
-%%%
-%%% <p>ct_ssh uses the OTP ssh application and more detailed information
-%%% about e.g. functions, types and options can be found in the
-%%% documentation for this application.</p>
-%%%
-%%% <p>The <code>Server</code> argument in the SFTP functions should
-%%% only be used for SFTP sessions that have been started on existing
-%%% SSH connections (i.e. when the original connection type is
-%%% <code>ssh</code>). Whenever the connection type is
-%%% <code>sftp</code>, use the SSH connection reference only.</p>
-%%%
-%%% <p>The following options are valid for specifying an SSH/SFTP
-%%% connection (i.e. may be used as config elements):</p>
-%%%
-%%% <pre>
-%%%
-%%% [{ConnType, Addr},
-%%% {port, Port},
-%%% {user, UserName}
-%%% {password, Pwd}
-%%% {user_dir, String}
-%%% {public_key_alg, PubKeyAlg}
-%%% {connect_timeout, Timeout}
-%%% {key_cb, KeyCallbackMod}]
-%%% </pre>
-%%%
-%%% <p><code>ConnType = ssh | sftp</code>.</p>
-%%% <p>Please see ssh(3) for other types.</p>
-%%%
-%%% <p>All timeout parameters in ct_ssh functions are values in
-%%% milliseconds.</p>
-%%%
-%%% @type connection() = handle() | ct:target_name()
-%%% @type handle() = ct_gen_conn:handle(). Handle for a specific
-%%% SSH/SFTP connection.
-%%% @type ssh_sftp_return() = term(). A return value from an ssh_sftp function.
-
-module(ct_ssh).
%% SSH Functions
@@ -100,64 +62,15 @@
%%%-----------------------------------------------------------------
%%%------------------------ SSH COMMANDS ---------------------------
-%%%-----------------------------------------------------------------
-%%% @spec connect(KeyOrName) -> {ok,Handle} | {error,Reason}
-%%% @equiv connect(KeyOrName,host,[])
connect(KeyOrName) ->
connect(KeyOrName, host).
-%%%-----------------------------------------------------------------
-%%% @spec connect(KeyOrName,ConnType) -> {ok,Handle} | {error,Reason}
-%%% @equiv connect(KeyOrName,ConnType,[])
connect(KeyOrName, ConnType) when is_atom(ConnType) ->
connect(KeyOrName, ConnType, []);
-%%%-----------------------------------------------------------------
-%%% @spec connect(KeyOrName,ExtraOpts) -> {ok,Handle} | {error,Reason}
-%%% @equiv connect(KeyOrName,host,ExtraOpts)
connect(KeyOrName, ExtraOpts) when is_list(ExtraOpts) ->
connect(KeyOrName, host, ExtraOpts).
-%%%-----------------------------------------------------------------
-%%% @spec connect(KeyOrName,ConnType,ExtraOpts) ->
-%%% {ok,Handle} | {error,Reason}
-%%% KeyOrName = Key | Name
-%%% Key = atom()
-%%% Name = ct:target_name()
-%%% ConnType = ssh | sftp | host
-%%% ExtraOpts = ssh_connect_options()
-%%% Handle = handle()
-%%% Reason = term()
-%%%
-%%% @doc Open an SSH or SFTP connection using the information
-%%% associated with <code>KeyOrName</code>.
-%%%
-%%% <p>If <code>Name</code> (an alias name for <code>Key</code>),
-%%% is used to identify the connection, this name may
-%%% be used as connection reference for subsequent calls.
-%%% It's only possible to have one open connection at a time
-%%% associated with <code>Name</code>. If <code>Key</code> is
-%%% used, the returned handle must be used for subsequent calls
-%%% (multiple connections may be opened using the config
-%%% data specified by <code>Key</code>). See <c>ct:require/2</c>
-%%% for how to create a new <c>Name</c></p>
-%%%
-%%% <p><code>ConnType</code> will always override the type
-%%% specified in the address tuple in the configuration data (and
-%%% in <code>ExtraOpts</code>). So it is possible to for example
-%%% open an sftp connection directly using data originally
-%%% specifying an ssh connection. The value <code>host</code>
-%%% means the connection type specified by the host option
-%%% (either in the configuration data or in <code>ExtraOpts</code>)
-%%% will be used.</p>
-%%%
-%%% <p><code>ExtraOpts</code> (optional) are extra SSH options
-%%% to be added to the config data for <code>KeyOrName</code>.
-%%% The extra options will override any existing options with the
-%%% same key in the config data. For details on valid SSH
-%%% options, see the documentation for the OTP ssh application.</p>
-%%%
-%%% @see ct:require/2
connect(KeyOrName, ConnType, ExtraOpts) ->
case ct:get_config(KeyOrName) of
undefined ->
@@ -232,12 +145,6 @@ connect(KeyOrName, ConnType, ExtraOpts) ->
end
end.
-%%%-----------------------------------------------------------------
-%%% @spec disconnect(SSH) -> ok | {error,Reason}
-%%% SSH = connection()
-%%% Reason = term()
-%%%
-%%% @doc Close an SSH/SFTP connection.
disconnect(SSH) ->
case get_handle(SSH) of
{ok,Pid} ->
@@ -252,242 +159,78 @@ disconnect(SSH) ->
Error
end.
-%%%-----------------------------------------------------------------
-%%% @spec session_open(SSH) -> {ok,ChannelId} | {error, Reason}
-%%% @equiv session_open(SSH,DefaultTimeout)
session_open(SSH) ->
call(SSH, {session_open,?DEFAULT_TIMEOUT}).
-%%%-----------------------------------------------------------------
-%%% @spec session_open(SSH,Timeout) -> {ok,ChannelId} | {error, Reason}
-%%% SSH = connection()
-%%% Timeout = integer()
-%%% ChannelId = integer()
-%%% Reason = term()
-%%%
-%%% @doc Opens a channel for an SSH session.
session_open(SSH, Timeout) ->
call(SSH, {session_open,Timeout}).
-%%%-----------------------------------------------------------------
-%%% @spec session_close(SSH,ChannelId) -> ok | {error, Reason}
-%%% SSH = connection()
-%%% ChannelId = integer()
-%%% Reason = term()
-%%%
-%%% @doc Closes an SSH session channel.
session_close(SSH, ChannelId) ->
call(SSH, {session_close,ChannelId}).
-%%%-----------------------------------------------------------------
-%%% @spec exec(SSH,Command) -> {ok,Data} | {error,Reason}
-%%% @equiv exec(SSH,Command,DefaultTimeout)
exec(SSH, Command) ->
exec(SSH, undefined, Command, ?DEFAULT_TIMEOUT).
-%%%-----------------------------------------------------------------
-%%% @spec exec(SSH,Command,Timeout) -> {ok,Data} | {error,Reason}
-%%% SSH = connection()
-%%% Command = string()
-%%% Timeout = integer()
-%%% Data = list()
-%%% Reason = term()
-%%%
-%%% @doc Requests server to perform <code>Command</code>. A session
-%%% channel is opened automatically for the request.
-%%% <code>Data</code> is received from the server as a result
-%%% of the command.
exec(SSH, Command, Timeout) when is_list(Command) ->
exec(SSH, undefined, Command, Timeout);
-%%%-----------------------------------------------------------------
-%%% @spec exec(SSH,ChannelId,Command) -> {ok,Data} | {error,Reason}
-%%% @equiv exec(SSH,ChannelId,Command,DefaultTimeout)
exec(SSH, ChannelId, Command) when is_integer(ChannelId) ->
exec(SSH, ChannelId, Command, ?DEFAULT_TIMEOUT).
-%%%-----------------------------------------------------------------
-%%% @spec exec(SSH,ChannelId,Command,Timeout) -> {ok,Data} | {error,Reason}
-%%% SSH = connection()
-%%% ChannelId = integer()
-%%% Command = string()
-%%% Timeout = integer()
-%%% Data = list()
-%%% Reason = term()
-%%%
-%%% @doc Requests server to perform <code>Command</code>. A previously
-%%% opened session channel is used for the request.
-%%% <code>Data</code> is received from the server as a result
-%%% of the command.
exec(SSH, ChannelId, Command, Timeout) ->
call(SSH, {exec,ChannelId,Command,Timeout}).
-%%%-----------------------------------------------------------------
-%%% @spec receive_response(SSH,ChannelId) -> {ok,Data} | {error,Reason}
-%%% @equiv receive_response(SSH,ChannelId,close)
receive_response(SSH, ChannelId) ->
receive_response(SSH, ChannelId, close, ?DEFAULT_TIMEOUT).
-%%%-----------------------------------------------------------------
-%%% @spec receive_response(SSH,ChannelId,End) -> {ok,Data} | {error,Reason}
-%%% @equiv receive_response(SSH,ChannelId,End,DefaultTimeout)
receive_response(SSH, ChannelId, End) when is_function(End) ->
receive_response(SSH, ChannelId, End, ?DEFAULT_TIMEOUT);
-%%%-----------------------------------------------------------------
-%%% @spec receive_response(SSH,ChannelId,Timeout) -> {ok,Data} | {error,Reason}
-%%% @equiv receive_response(SSH,ChannelId,close,Timeout)
receive_response(SSH, ChannelId, Timeout) when is_integer(Timeout) ->
receive_response(SSH, ChannelId, close, Timeout).
-%%%-----------------------------------------------------------------
-%%% @spec receive_response(SSH,ChannelId,End,Timeout) ->
-%%% {ok,Data} | {timeout,Data} | {error,Reason}
-%%% SSH = connection()
-%%% ChannelId = integer()
-%%% End = Fun | close | timeout
-%%% Timeout = integer()
-%%% Data = list()
-%%% Reason = term()
-%%%
-%%% @doc Receives expected data from server on the specified
-%%% session channel.
-%%%
-%%% <p>If <code>End == close</code>, data is returned
-%%% to the caller when the channel is closed by the
-%%% server. If a timeout occurs before this happens,
-%%% the function returns <code>{timeout,Data}</code>
-%%% (where <code>Data</code> is the data received so far).
-%%% If <code>End == timeout</code>, a timeout is expected
-%%% and <code>{ok,Data}</code> is returned both in the case
-%%% of a timeout and when the channel is closed. If
-%%% <code>End</code> is a fun, this fun will be
-%%% called with one argument - the data value in a received
-%%% <code>ssh_cm</code> message (see ssh_connection(3)). The
-%%% fun should return <code>true</code> to end the receiving
-%%% operation (and have the so far collected data returned), or
-%%% <code>false</code> to wait for more data from the server.
-%%% (Note that even if a fun is supplied, the function returns
-%%% immediately if the server closes the channel).</p>
receive_response(SSH, ChannelId, End, Timeout) ->
call(SSH, {receive_response,ChannelId,End,Timeout}).
-%%%-----------------------------------------------------------------
-%%% @spec send(SSH,ChannelId,Data) -> ok | {error,Reason}
-%%% @equiv send(SSH,ChannelId,0,Data,DefaultTimeout)
send(SSH, ChannelId, Data) ->
send(SSH, ChannelId, 0, Data, ?DEFAULT_TIMEOUT).
-%%%-----------------------------------------------------------------
-%%% @spec send(SSH,ChannelId,Data,Timeout) -> ok | {error,Reason}
-%%% @equiv send(SSH,ChannelId,0,Data,Timeout)
send(SSH, ChannelId, Data, Timeout) when is_integer(Timeout) ->
send(SSH, ChannelId, 0, Data, Timeout);
-%%%-----------------------------------------------------------------
-%%% @spec send(SSH,ChannelId,Type,Data) -> ok | {error,Reason}
-%%% @equiv send(SSH,ChannelId,Type,Data,DefaultTimeout)
send(SSH, ChannelId, Type, Data) when is_integer(Type) ->
send(SSH, ChannelId, Type, Data, ?DEFAULT_TIMEOUT).
-%%%-----------------------------------------------------------------
-%%% @spec send(SSH,ChannelId,Type,Data,Timeout) -> ok | {error,Reason}
-%%% SSH = connection()
-%%% ChannelId = integer()
-%%% Type = integer()
-%%% Data = list()
-%%% Timeout = integer()
-%%% Reason = term()
-%%%
-%%% @doc Send data to server on specified session channel.
send(SSH, ChannelId, Type, Data, Timeout) ->
call(SSH, {send,ChannelId,Type,Data,Timeout}).
-%%%-----------------------------------------------------------------
-%%% @spec send_and_receive(SSH,ChannelId,Data) ->
-%%% {ok,Data} | {error,Reason}
-%%% @equiv send_and_receive(SSH,ChannelId,Data,close)
send_and_receive(SSH, ChannelId, Data) ->
send_and_receive(SSH, ChannelId, 0, Data, close, ?DEFAULT_TIMEOUT).
-%%%-----------------------------------------------------------------
-%%% @spec send_and_receive(SSH,ChannelId,Data,End) ->
-%%% {ok,Data} | {error,Reason}
-%%% @equiv send_and_receive(SSH,ChannelId,0,Data,End,DefaultTimeout)
send_and_receive(SSH, ChannelId, Data, End) when is_function(End) ->
send_and_receive(SSH, ChannelId, 0, Data, End, ?DEFAULT_TIMEOUT);
-%%%-----------------------------------------------------------------
-%%% @spec send_and_receive(SSH,ChannelId,Data,Timeout) ->
-%%% {ok,Data} | {error,Reason}
-%%% @equiv send_and_receive(SSH,ChannelId,0,Data,close,Timeout)
send_and_receive(SSH, ChannelId, Data, Timeout) when is_integer(Timeout) ->
send_and_receive(SSH, ChannelId, 0, Data, close, Timeout);
-%%%-----------------------------------------------------------------
-%%% @spec send_and_receive(SSH,ChannelId,Type,Data) ->
-%%% {ok,Data} | {error,Reason}
-%%% @equiv send_and_receive(SSH,ChannelId,Type,Data,close,DefaultTimeout)
send_and_receive(SSH, ChannelId, Type, Data) when is_integer(Type) ->
send_and_receive(SSH, ChannelId, Type, Data, close, ?DEFAULT_TIMEOUT).
-%%%-----------------------------------------------------------------
-%%% @spec send_and_receive(SSH,ChannelId,Data,End,Timeout) ->
-%%% {ok,Data} | {error,Reason}
-%%% @equiv send_and_receive(SSH,ChannelId,0,Data,End,Timeout)
send_and_receive(SSH, ChannelId, Data, End, Timeout) when is_integer(Timeout) ->
send_and_receive(SSH, ChannelId, 0, Data, End, Timeout);
-%%%-----------------------------------------------------------------
-%%% @spec send_and_receive(SSH,ChannelId,Type,Data,Timeout) ->
-%%% {ok,Data} | {error,Reason}
-%%% @equiv send_and_receive(SSH,ChannelId,Type,Data,close,Timeout)
send_and_receive(SSH, ChannelId, Type, Data, Timeout) when is_integer(Type) ->
send_and_receive(SSH, ChannelId, Type, Data, close, Timeout);
-%%%-----------------------------------------------------------------
-%%% @spec send_and_receive(SSH,ChannelId,Type,Data,End) ->
-%%% {ok,Data} | {error,Reason}
-%%% @equiv send_and_receive(SSH,ChannelId,Type,Data,End,DefaultTimeout)
send_and_receive(SSH, ChannelId, Type, Data, End) when is_function(End) ->
send_and_receive(SSH, ChannelId, Type, Data, End, ?DEFAULT_TIMEOUT).
-%%%-----------------------------------------------------------------
-%%% @spec send_and_receive(SSH,ChannelId,Type,Data,End,Timeout) ->
-%%% {ok,Data} | {error,Reason}
-%%% SSH = connection()
-%%% ChannelId = integer()
-%%% Type = integer()
-%%% Data = list()
-%%% End = Fun | close | timeout
-%%% Timeout = integer()
-%%% Reason = term()
-%%%
-%%% @doc Send data to server on specified session channel and wait
-%%% to receive the server response.
-%%%
-%%% <p>See <code>receive_response/4</code> for details on the
-%%% <code>End</code> argument.</p>
send_and_receive(SSH, ChannelId, Type, Data, End, Timeout) ->
call(SSH, {send_and_receive,ChannelId,Type,Data,End,Timeout}).
-%%%-----------------------------------------------------------------
-%%% @spec subsystem(SSH,ChannelId,Subsystem) -> Status | {error,Reason}
-%%% @equiv subsystem(SSH,ChannelId,Subsystem,DefaultTimeout)
subsystem(SSH, ChannelId, Subsystem) ->
subsystem(SSH, ChannelId, Subsystem, ?DEFAULT_TIMEOUT).
-%%%-----------------------------------------------------------------
-%%% @spec subsystem(SSH,ChannelId,Subsystem,Timeout) ->
-%%% Status | {error,Reason}
-%%% SSH = connection()
-%%% ChannelId = integer()
-%%% Subsystem = string()
-%%% Timeout = integer()
-%%% Status = success | failure
-%%% Reason = term()
-%%%
-%%% @doc Sends a request to execute a predefined subsystem.
subsystem(SSH, ChannelId, Subsystem, Timeout) ->
call(SSH, {subsystem,ChannelId,Subsystem,Timeout}).
@@ -511,439 +254,157 @@ shell(SSH, ChannelId, Timeout) ->
%%%-----------------------------------------------------------------
%%%------------------------ SFTP COMMANDS --------------------------
-%%%-----------------------------------------------------------------
-%%% @spec sftp_connect(SSH) -> {ok,Server} | {error,Reason}
-%%% SSH = connection()
-%%% Server = pid()
-%%% Reason = term()
-%%% @doc Starts an SFTP session on an already existing SSH connection.
-%%% <code>Server</code> identifies the new session and must be
-%%% specified whenever SFTP requests are to be sent.
sftp_connect(SSH) ->
call(SSH, sftp_connect).
-%%%-----------------------------------------------------------------
-%%% @spec read_file(SSH, File) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
read_file(SSH, File) ->
call(SSH, {read_file,sftp,File}).
-%%%-----------------------------------------------------------------
-%%% @spec read_file(SSH, Server, File) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
read_file(SSH, Server, File) ->
call(SSH, {read_file,Server,File}).
-%%%-----------------------------------------------------------------
-%%% @spec write_file(SSH, File, Iolist) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
write_file(SSH, File, Iolist) ->
call(SSH, {write_file,sftp,File,Iolist}).
-%%%-----------------------------------------------------------------
-%%% @spec write_file(SSH, Server, File, Iolist) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
write_file(SSH, Server, File, Iolist) ->
call(SSH, {write_file,Server,File,Iolist}).
-%%%-----------------------------------------------------------------
-%%% @spec list_dir(SSH, Path) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
list_dir(SSH, Path) ->
call(SSH, {list_dir,sftp,Path}).
-%%%-----------------------------------------------------------------
-%%% @spec list_dir(SSH, Server, Path) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
list_dir(SSH, Server, Path) ->
call(SSH, {list_dir,Server,Path}).
-%%%-----------------------------------------------------------------
-%%% @spec open(SSH, File, Mode) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
open(SSH, File, Mode) ->
call(SSH, {open,sftp,File,Mode}).
-%%%-----------------------------------------------------------------
-%%% @spec open(SSH, Server, File, Mode) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
open(SSH, Server, File, Mode) ->
call(SSH, {open,Server,File,Mode}).
-%%%-----------------------------------------------------------------
-%%% @spec opendir(SSH, Path) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
opendir(SSH, Path) ->
call(SSH, {opendir,sftp,Path}).
-%%%-----------------------------------------------------------------
-%%% @spec opendir(SSH, Server, Path) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
opendir(SSH, Server, Path) ->
call(SSH, {opendir,Server,Path}).
-%%%-----------------------------------------------------------------
-%%% @spec close(SSH, Handle) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
close(SSH, Handle) ->
call(SSH, {close,sftp,Handle}).
-%%%-----------------------------------------------------------------
-%%% @spec close(SSH, Server, Handle) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
close(SSH, Server, Handle) ->
call(SSH, {close,Server,Handle}).
-%%%-----------------------------------------------------------------
-%%% @spec read(SSH, Handle, Len) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
read(SSH, Handle, Len) ->
call(SSH, {read,sftp,Handle,Len}).
-%%%-----------------------------------------------------------------
-%%% @spec read(SSH, Server, Handle, Len) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
read(SSH, Server, Handle, Len) ->
call(SSH, {read,Server,Handle,Len}).
-%%%-----------------------------------------------------------------
-%%% @spec pread(SSH, Handle, Position, Length) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
pread(SSH, Handle, Position, Length) ->
call(SSH, {pread,sftp,Handle,Position,Length}).
-%%%-----------------------------------------------------------------
-%%% @spec pread(SSH, Server, Handle, Position, Length) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
pread(SSH, Server, Handle, Position, Length) ->
call(SSH, {pread,Server,Handle,Position,Length}).
-%%%-----------------------------------------------------------------
-%%% @spec aread(SSH, Handle, Len) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
aread(SSH, Handle, Len) ->
call(SSH, {aread,sftp,Handle,Len}).
-%%%-----------------------------------------------------------------
-%%% @spec aread(SSH, Server, Handle, Len) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
aread(SSH, Server, Handle, Len) ->
call(SSH, {aread,Server,Handle,Len}).
-%%%-----------------------------------------------------------------
-%%% @spec apread(SSH, Handle, Position, Length) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
apread(SSH, Handle, Position, Length) ->
call(SSH, {apread,sftp,Handle,Position,Length}).
-%%%-----------------------------------------------------------------
-%%% @spec apread(SSH, Server, Handle, Position, Length) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
apread(SSH, Server, Handle, Position, Length) ->
call(SSH, {apread,Server,Handle,Position,Length}).
-%%%-----------------------------------------------------------------
-%%% @spec write(SSH, Handle, Data) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
write(SSH, Handle, Data) ->
call(SSH, {write,sftp,Handle,Data}).
-%%%-----------------------------------------------------------------
-%%% @spec write(SSH, Server, Handle, Data) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
write(SSH, Server, Handle, Data) ->
call(SSH, {write,Server,Handle,Data}).
-%%%-----------------------------------------------------------------
-%%% @spec pwrite(SSH, Handle, Position, Data) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
pwrite(SSH, Handle, Position, Data) ->
call(SSH, {pwrite,sftp,Handle,Position,Data}).
-%%%-----------------------------------------------------------------
-%%% @spec pwrite(SSH, Server, Handle, Position, Data) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
pwrite(SSH, Server, Handle, Position, Data) ->
call(SSH, {pwrite,Server,Handle,Position,Data}).
-%%%-----------------------------------------------------------------
-%%% @spec awrite(SSH, Handle, Data) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
awrite(SSH, Handle, Data) ->
call(SSH, {awrite,sftp,Handle, Data}).
-%%%-----------------------------------------------------------------
-%%% @spec awrite(SSH, Server, Handle, Data) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
awrite(SSH, Server, Handle, Data) ->
call(SSH, {awrite,Server,Handle, Data}).
-%%%-----------------------------------------------------------------
-%%% @spec apwrite(SSH, Handle, Position, Data) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
apwrite(SSH, Handle, Position, Data) ->
call(SSH, {apwrite,sftp,Handle,Position,Data}).
-%%%-----------------------------------------------------------------
-%%% @spec apwrite(SSH, Server, Handle, Position, Data) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
apwrite(SSH, Server, Handle, Position, Data) ->
call(SSH, {apwrite,Server,Handle,Position,Data}).
-%%%-----------------------------------------------------------------
-%%% @spec position(SSH, Handle, Location) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
position(SSH, Handle, Location) ->
call(SSH, {position,sftp,Handle,Location}).
-%%%-----------------------------------------------------------------
-%%% @spec position(SSH, Server, Handle, Location) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
position(SSH, Server, Handle, Location) ->
call(SSH, {position,Server,Handle,Location}).
-%%%-----------------------------------------------------------------
-%%% @spec read_file_info(SSH, Name) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
read_file_info(SSH, Name) ->
call(SSH, {read_file_info,sftp,Name}).
-%%%-----------------------------------------------------------------
-%%% @spec read_file_info(SSH, Server, Name) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
read_file_info(SSH, Server, Name) ->
call(SSH, {read_file_info,Server,Name}).
-%%%-----------------------------------------------------------------
-%%% @spec get_file_info(SSH, Handle) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
get_file_info(SSH, Handle) ->
call(SSH, {get_file_info,sftp,Handle}).
-%%%-----------------------------------------------------------------
-%%% @spec get_file_info(SSH, Server, Handle) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
get_file_info(SSH, Server, Handle) ->
call(SSH, {get_file_info,Server,Handle}).
-%%%-----------------------------------------------------------------
-%%% @spec read_link_info(SSH, Name) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
read_link_info(SSH, Name) ->
call(SSH, {read_link_info,sftp,Name}).
-%%%-----------------------------------------------------------------
-%%% @spec read_link_info(SSH, Server, Name) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
read_link_info(SSH, Server, Name) ->
call(SSH, {read_link_info,Server,Name}).
-%%%-----------------------------------------------------------------
-%%% @spec write_file_info(SSH, Name, Info) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
write_file_info(SSH, Name, Info) ->
call(SSH, {write_file_info,sftp,Name,Info}).
-%%%-----------------------------------------------------------------
-%%% @spec write_file_info(SSH, Server, Name, Info) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
write_file_info(SSH, Server, Name, Info) ->
call(SSH, {write_file_info,Server,Name,Info}).
-%%%-----------------------------------------------------------------
-%%% @spec read_link(SSH, Name) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
read_link(SSH, Name) ->
call(SSH, {read_link,sftp,Name}).
-%%%-----------------------------------------------------------------
-%%% @spec read_link(SSH, Server, Name) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
read_link(SSH, Server, Name) ->
call(SSH, {read_link,Server,Name}).
-%%%-----------------------------------------------------------------
-%%% @spec make_symlink(SSH, Name, Target) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
make_symlink(SSH, Name, Target) ->
call(SSH, {make_symlink,sftp,Name,Target}).
-%%%-----------------------------------------------------------------
-%%% @spec make_symlink(SSH, Server, Name, Target) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
make_symlink(SSH, Server, Name, Target) ->
call(SSH, {make_symlink,Server,Name,Target}).
-%%%-----------------------------------------------------------------
-%%% @spec rename(SSH, OldName, NewName) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
rename(SSH, OldName, NewName) ->
call(SSH, {rename,sftp,OldName,NewName}).
-%%%-----------------------------------------------------------------
-%%% @spec rename(SSH, Server, OldName, NewName) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
rename(SSH, Server, OldName, NewName) ->
call(SSH, {rename,Server,OldName,NewName}).
-%%%-----------------------------------------------------------------
-%%% @spec delete(SSH, Name) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
delete(SSH, Name) ->
call(SSH, {delete,sftp,Name}).
-%%%-----------------------------------------------------------------
-%%% @spec delete(SSH, Server, Name) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
delete(SSH, Server, Name) ->
call(SSH, {delete,Server,Name}).
-%%%-----------------------------------------------------------------
-%%% @spec make_dir(SSH, Name) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
make_dir(SSH, Name) ->
call(SSH, {make_dir,sftp,Name}).
-%%%-----------------------------------------------------------------
-%%% @spec make_dir(SSH, Server, Name) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
make_dir(SSH, Server, Name) ->
call(SSH, {make_dir,Server,Name}).
-%%%-----------------------------------------------------------------
-%%% @spec del_dir(SSH, Name) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
del_dir(SSH, Name) ->
call(SSH, {del_dir,sftp,Name}).
-%%%-----------------------------------------------------------------
-%%% @spec del_dir(SSH, Server, Name) -> Result
-%%% SSH = connection()
-%%% Result = ssh_sftp_return() | {error,Reason}
-%%% Reason = term()
-%%% @doc For info and other types, see ssh_sftp(3).
+
del_dir(SSH, Server, Name) ->
call(SSH, {del_dir,Server,Name}).
@@ -952,7 +413,6 @@ del_dir(SSH, Server, Name) ->
%%% Callback functions
%%%=================================================================
-%% @hidden
init(KeyOrName, {ConnType,Addr,Port}, AllOpts) ->
User = proplists:get_value(user, AllOpts),
Password = case proplists:get_value(password, AllOpts) of
@@ -996,12 +456,12 @@ init(KeyOrName, {ConnType,Addr,Port}, AllOpts) ->
try_log(heading(init,KeyOrName),
"Opened ~w connection:\n"
"Host: ~tp (~p)\nUser: ~tp\nPassword: ~p\n",
- [ConnType,Addr,Port,User,lists:duplicate(length(Password),$*)]),
+ [ConnType,Addr,Port,User,
+ lists:duplicate(string:length(Password),$*)]),
{ok,SSHRef,#state{ssh_ref=SSHRef, conn_type=ConnType,
target=KeyOrName}}
end.
-%% @hidden
handle_msg(sftp_connect, State) ->
#state{ssh_ref=SSHRef, target=Target} = State,
try_log(heading(sftp_connect,Target), "SSH Ref: ~p", [SSHRef]),
@@ -1245,15 +705,12 @@ handle_msg({del_dir,Srv,Name}=Cmd, S=#state{ssh_ref=SSHRef}) ->
[SSHRef,ref(Srv,SSHRef),mod(Cmd)]),
{ssh_sftp:del_dir(ref(Srv,SSHRef), Name),S}.
-%% @hidden
reconnect(_Addr,_State) ->
{error,no_reconnection_of_ssh}.
-%% @hidden
close(SSHRef) ->
disconnect(SSHRef).
-%% @hidden
terminate(SSHRef, State) ->
case State#state.conn_type of
ssh ->
@@ -1270,8 +727,6 @@ terminate(SSHRef, State) ->
%%%=================================================================
%%% Internal functions
-%%%-----------------------------------------------------------------
-%%%
do_recv_response(SSH, Chn, Data, End, Timeout) ->
receive
{ssh_cm, SSH, {open,Chn,RemoteChn,{session}}} ->
@@ -1350,8 +805,6 @@ do_recv_response(SSH, Chn, Data, End, Timeout) ->
end
end.
-%%%-----------------------------------------------------------------
-%%%
get_handle(SSH) when is_pid(SSH) ->
{ok,SSH};
get_handle(SSH) ->
@@ -1364,8 +817,6 @@ get_handle(SSH) ->
Error
end.
-%%%-----------------------------------------------------------------
-%%%
call(SSH, Msg) ->
call(SSH, Msg, infinity).
@@ -1377,29 +828,19 @@ call(SSH, Msg, Timeout) ->
Error
end.
-%%%-----------------------------------------------------------------
-%%%
ref(sftp, SSHRef) -> SSHRef;
ref(Server, _) -> Server.
-%%%-----------------------------------------------------------------
-%%%
mod(Cmd) ->
[Op,_Server|Args] = tuple_to_list(Cmd),
list_to_tuple([Op|Args]).
-%%%-----------------------------------------------------------------
-%%%
heading(Function, Ref) ->
io_lib:format("ct_ssh:~tw ~tp",[Function,Ref]).
-%%%-----------------------------------------------------------------
-%%%
log(Heading, Str, Args) ->
ct_gen_conn:log(Heading, Str, Args).
-%%%-----------------------------------------------------------------
-%%%
try_log(Heading, Str, Args) ->
try_log(Heading, Str, Args, infinity).
@@ -1413,8 +854,6 @@ try_log(Heading, Str, Args, Timeout) ->
ok
end.
-%%%-----------------------------------------------------------------
-%%%
debug(Str) ->
debug(Str, []).
diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl
index 14d9d381da..f9abecfd38 100644
--- a/lib/common_test/src/ct_telnet.erl
+++ b/lib/common_test/src/ct_telnet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,131 +18,6 @@
%% %CopyrightEnd%
%%
-%% @doc Common Test specific layer on top of telnet client `ct_telnet_client.erl'
-%%
-%% <p>Use this module to set up telnet connections, send commands and
-%% perform string matching on the result.
-%% See the `unix_telnet' manual page for information about how to use
-%% `ct_telnet', and configure connections, specifically for unix hosts.</p>
-%% <p>The following default values are defined in `ct_telnet':</p>
-%% <pre>
-%% Connection timeout = 10 sec (time to wait for connection)
-%% Command timeout = 10 sec (time to wait for a command to return)
-%% Max no of reconnection attempts = 3
-%% Reconnection interval = 5 sek (time to wait in between reconnection attempts)
-%% Keep alive = true (will send NOP to the server every 8 sec if connection is idle)
-%% Polling limit = 0 (max number of times to poll to get a remaining string terminated)
-%% Polling interval = 1 sec (sleep time between polls)</pre>
-%% <p>These parameters can be altered by the user with the following
-%% configuration term:</p>
-%% <pre>
-%% {telnet_settings, [{connect_timeout,Millisec},
-%% {command_timeout,Millisec},
-%% {reconnection_attempts,N},
-%% {reconnection_interval,Millisec},
-%% {keep_alive,Bool},
-%% {poll_limit,N},
-%% {poll_interval,Millisec},
-%% {tcp_nodelay,Bool}]}.</pre>
-%% <p><code>Millisec = integer(), N = integer()</code></p>
-%% <p>Enter the <code>telnet_settings</code> term in a configuration
-%% file included in the test and ct_telnet will retrieve the information
-%% automatically. Note that `keep_alive' may be specified per connection if
-%% required. See `unix_telnet' for details.</p>
-%%
-%% == Logging ==
-%%
-%% The default logging behaviour of `ct_telnet' is to print information
-%% to the test case HTML log about performed operations and commands
-%% and their corresponding results. What won't be printed to the HTML log
-%% are text strings sent from the telnet server that are not explicitly
-%% received by means of a `ct_telnet' function such as `expect/3'.
-%% `ct_telnet' may however be configured to use a special purpose event handler,
-%% implemented in `ct_conn_log_h', for logging <b>all</b> telnet traffic.
-%% To use this handler, you need to install a Common Test hook named
-%% `cth_conn_log'. Example (using the test suite info function):
-%%
-%% ```
-%% suite() ->
-%% [{ct_hooks, [{cth_conn_log, [{conn_mod(),hook_options()}]}]}].
-%% '''
-%%
-%% `conn_mod()' is the name of the common_test module implementing
-%% the connection protocol, i.e. `ct_telnet'.
-%%
-%% The `cth_conn_log' hook performs unformatted logging of telnet data to
-%% a separate text file. All telnet communication is captured and printed,
-%% including arbitrary data sent from the server. The link to this text file
-%% can be found on the top of the test case HTML log.
-%%
-%% By default, data for all telnet connections is logged in one common
-%% file (named `default'), which might get messy e.g. if multiple telnet
-%% sessions are running in parallel. It is therefore possible to create a
-%% separate log file for each connection. To configure this, use the hook
-%% option `hosts' and list the names of the servers/connections that will be
-%% used in the suite. Note that the connections must be named for this to work
-%% (see the `open' function below).
-%%
-%% The hook option named `log_type' may be used to change the `cth_conn_log'
-%% behaviour. The default value of this option is `raw', which results in the
-%% behaviour described above. If the value is set to `html', all telnet
-%% communication is printed to the test case HTML log instead.
-%%
-%% All `cth_conn_log' hook options described above can also be specified in
-%% a configuration file with the configuration variable `ct_conn_log'. Example:
-%%
-%% ```
-%% {ct_conn_log, [{ct_telnet,[{log_type,raw},
-%% {hosts,[key_or_name()]}]}]}
-%% '''
-%%
-%% <b>Note</b> that hook options specified in a configuration file
-%% will overwrite any hardcoded hook options in the test suite!
-%%
-%% === Logging example ===
-%%
-%% The following `ct_hooks' statement will cause printing of telnet traffic
-%% to separate logs for the connections named `server1' and `server2'.
-%% Traffic for any other connections will be logged in the default telnet log.
-%%
-%% ```
-%% suite() ->
-%% [{ct_hooks,
-%% [{cth_conn_log, [{ct_telnet,[{hosts,[server1,server2]}]}]}]}].
-%%'''
-%%
-%% As previously explained, the above specification could also be provided
-%% by means of an entry like this in a configuration file:
-%%
-%% ```
-%% {ct_conn_log, [{ct_telnet,[{hosts,[server1,server2]}]}]}.
-%% '''
-%%
-%% in which case the `ct_hooks' statement in the test suite may simply look
-%% like this:
-%%
-%% ```
-%% suite() ->
-%% [{ct_hooks, [{cth_conn_log, []}]}].
-%% '''
-%%
-%% @end
-
-%% @type connection_type() = telnet | ts1 | ts2
-
-%% @type connection() = handle() |
-%% {ct:target_name(),connection_type()} | ct:target_name()
-
-%% @type handle() = ct_gen_conn:handle(). Handle for a
-%% specific telnet connection.
-
-%% @type prompt_regexp() = string(). A regular expression which
-%% matches all possible prompts for a specific type of target. The
-%% regexp must not have any groups i.e. when matching, re:run/3 shall
-%% return a list with one single element.
-%%
-%% @see unix_telnet
-
-module(ct_telnet).
-export([open/1, open/2, open/3, open/4, close/1]).
@@ -186,20 +61,9 @@
reconn_int=?RECONN_TIMEOUT,
tcp_nodelay=false}).
-%%%-----------------------------------------------------------------
-%%% @spec open(Name) -> {ok,Handle} | {error,Reason}
-%%% @equiv open(Name,telnet)
open(Name) ->
open(Name,telnet).
-%%%-----------------------------------------------------------------
-%%% @spec open(Name,ConnType) -> {ok,Handle} | {error,Reason}
-%%% Name = target_name()
-%%% ConnType = ct_telnet:connection_type()
-%%% Handle = ct_telnet:handle()
-%%% Reason = term()
-%%%
-%%% @doc Open a telnet connection to the specified target host.
open(Name,ConnType) ->
case ct_util:get_key_from_name(Name) of
{ok, unix} -> % unix host
@@ -210,44 +74,9 @@ open(Name,ConnType) ->
Error
end.
-%%%-----------------------------------------------------------------
-%%% @spec open(KeyOrName,ConnType,TargetMod) ->
-%%% {ok,Handle} | {error,Reason}
-%%% @equiv open(KeyOrName,ConnType,TargetMod,[])
open(KeyOrName,ConnType,TargetMod) ->
open(KeyOrName,ConnType,TargetMod,KeyOrName).
-%%%-----------------------------------------------------------------
-%%% @spec open(KeyOrName,ConnType,TargetMod,Extra) ->
-%%% {ok,Handle} | {error,Reason}
-%%% KeyOrName = Key | Name
-%%% Key = atom()
-%%% Name = ct:target_name()
-%%% ConnType = connection_type()
-%%% TargetMod = atom()
-%%% Extra = term()
-%%% Handle = handle()
-%%% Reason = term()
-%%%
-%%% @doc Open a telnet connection to the specified target host.
-%%%
-%%% <p>The target data must exist in a configuration file. The connection
-%%% may be associated with either <code>Name</code> and/or the returned
-%%% <code>Handle</code>. To allocate a name for the target,
-%%% use <code>ct:require/2</code> in a test case, or use a
-%%% <code>require</code> statement in the suite info function
-%%% (<code>suite/0</code>), or in a test case info function.
-%%% If you want the connection to be associated with <code>Handle</code> only
-%%% (in case you need to open multiple connections to a host for example),
-%%% simply use <code>Key</code>, the configuration variable name, to
-%%% specify the target. Note that a connection that has no associated target
-%%% name can only be closed with the handle value.</p>
-%%%
-%%% <p><code>TargetMod</code> is a module which exports the functions
-%%% <code>connect(Ip,Port,KeepAlive,Extra)</code> and <code>get_prompt_regexp()</code>
-%%% for the given <code>TargetType</code> (e.g. <code>unix_telnet</code>).</p>
-%%%
-%%% @see ct:require/2
open(KeyOrName,ConnType,TargetMod,Extra) ->
case ct:get_config({KeyOrName,ConnType}) of
undefined ->
@@ -287,17 +116,6 @@ open(KeyOrName,ConnType,TargetMod,Extra) ->
{old,true}])
end.
-%%%-----------------------------------------------------------------
-%%% @spec close(Connection) -> ok | {error,Reason}
-%%% Connection = ct_telnet:connection()
-%%% Reason = term()
-%%%
-%%% @doc Close the telnet connection and stop the process managing it.
-%%%
-%%% <p>A connection may be associated with a target name and/or a handle.
-%%% If <code>Connection</code> has no associated target name, it may only
-%%% be closed with the handle value (see the <code>open/4</code>
-%%% function).</p>
close(Connection) ->
case get_handle(Connection) of
{ok,Pid} ->
@@ -315,30 +133,10 @@ close(Connection) ->
%%%=================================================================
%%% Test suite interface
%%%-----------------------------------------------------------------
-%%% @spec cmd(Connection,Cmd) -> {ok,Data} | {error,Reason}
-%%% @equiv cmd(Connection,Cmd,[])
+
cmd(Connection,Cmd) ->
cmd(Connection,Cmd,[]).
-%%%-----------------------------------------------------------------
-%%% @spec cmd(Connection,Cmd,Opts) -> {ok,Data} | {error,Reason}
-%%% Connection = ct_telnet:connection()
-%%% Cmd = string()
-%%% Opts = [Opt]
-%%% Opt = {timeout,timeout()} | {newline,boolean()}
-%%% Data = [string()]
-%%% Reason = term()
-%%% @doc Send a command via telnet and wait for prompt.
-%%%
-%%% <p>This function will by default add a newline to the end of the
-%%% given command. If this is not desired, the option
-%%% `{newline,false}' can be used. This is necessary, for example,
-%%% when sending telnet command sequences (prefixed with the
-%%% Interprete As Command, IAC, character).</p>
-%%%
-%%% <p>The option `timeout' specifies how long the client shall wait for
-%%% prompt. If the time expires, the function returns
-%%% `{error,timeout}'. See the module description for information
-%%% about the default value for the command timeout.</p>
+
cmd(Connection,Cmd,Opts) when is_list(Opts) ->
case check_cmd_opts(Opts) of
ok ->
@@ -363,42 +161,13 @@ check_cmd_opts([]) ->
check_cmd_opts(Opts) ->
check_send_opts(Opts).
-%%%-----------------------------------------------------------------
-%%% @spec cmdf(Connection,CmdFormat,Args) -> {ok,Data} | {error,Reason}
-%%% @equiv cmdf(Connection,CmdFormat,Args,[])
cmdf(Connection,CmdFormat,Args) ->
cmdf(Connection,CmdFormat,Args,[]).
-%%%-----------------------------------------------------------------
-%%% @spec cmdf(Connection,CmdFormat,Args,Opts) -> {ok,Data} | {error,Reason}
-%%% Connection = ct_telnet:connection()
-%%% CmdFormat = string()
-%%% Args = list()
-%%% Opts = [Opt]
-%%% Opt = {timeout,timeout()} | {newline,boolean()}
-%%% Data = [string()]
-%%% Reason = term()
-%%% @doc Send a telnet command and wait for prompt
-%%% (uses a format string and list of arguments to build the command).
-%%%
-%%% <p>See {@link cmd/3} further description.</p>
+
cmdf(Connection,CmdFormat,Args,Opts) when is_list(Args) ->
Cmd = lists:flatten(io_lib:format(CmdFormat,Args)),
cmd(Connection,Cmd,Opts).
-%%%-----------------------------------------------------------------
-%%% @spec get_data(Connection) -> {ok,Data} | {error,Reason}
-%%% Connection = ct_telnet:connection()
-%%% Data = [string()]
-%%% Reason = term()
-%%% @doc Get all data that has been received by the telnet client
-%%% since the last command was sent. Note that only newline terminated
-%%% strings are returned. If the last string received has not yet
-%%% been terminated, the connection may be polled automatically until
-%%% the string is complete. The polling feature is controlled
-%%% by the `poll_limit' and `poll_interval' config values and is
-%%% by default disabled (meaning the function will immediately
-%%% return all complete strings received and save a remaining
-%%% non-terminated string for a later `get_data' call).
get_data(Connection) ->
case get_handle(Connection) of
{ok,Pid} ->
@@ -407,29 +176,9 @@ get_data(Connection) ->
Error
end.
-%%%-----------------------------------------------------------------
-%%% @spec send(Connection,Cmd) -> ok | {error,Reason}
-%%% @equiv send(Connection,Cmd,[])
send(Connection,Cmd) ->
send(Connection,Cmd,[]).
-%%%-----------------------------------------------------------------
-%%% @spec send(Connection,Cmd,Opts) -> ok | {error,Reason}
-%%% Connection = ct_telnet:connection()
-%%% Cmd = string()
-%%% Opts = [Opt]
-%%% Opt = {newline,boolean()}
-%%% Reason = term()
-%%% @doc Send a telnet command and return immediately.
-%%%
-%%% This function will by default add a newline to the end of the
-%%% given command. If this is not desired, the option
-%%% `{newline,false}' can be used. This is necessary, for example,
-%%% when sending telnet command sequences (prefixed with the
-%%% Interprete As Command, IAC, character).
-%%%
-%%% <p>The resulting output from the command can be read with
-%%% <code>get_data/1</code> or <code>expect/2/3</code>.</p>
send(Connection,Cmd,Opts) ->
case check_send_opts(Opts) of
ok ->
@@ -450,142 +199,16 @@ check_send_opts([Invalid|_]) ->
check_send_opts([]) ->
ok.
-
-%%%-----------------------------------------------------------------
-%%% @spec sendf(Connection,CmdFormat,Args) -> ok | {error,Reason}
-%%% @equiv sendf(Connection,CmdFormat,Args,[])
sendf(Connection,CmdFormat,Args) when is_list(Args) ->
sendf(Connection,CmdFormat,Args,[]).
-%%%-----------------------------------------------------------------
-%%% @spec sendf(Connection,CmdFormat,Args,Opts) -> ok | {error,Reason}
-%%% Connection = ct_telnet:connection()
-%%% CmdFormat = string()
-%%% Args = list()
-%%% Opts = [Opt]
-%%% Opt = {newline,boolean()}
-%%% Reason = term()
-%%% @doc Send a telnet command and return immediately (uses a format
-%%% string and a list of arguments to build the command).
sendf(Connection,CmdFormat,Args,Opts) when is_list(Args) ->
Cmd = lists:flatten(io_lib:format(CmdFormat,Args)),
send(Connection,Cmd,Opts).
-%%%-----------------------------------------------------------------
-%%% @spec expect(Connection,Patterns) -> term()
-%%% @equiv expect(Connections,Patterns,[])
expect(Connection,Patterns) ->
expect(Connection,Patterns,[]).
-%%%-----------------------------------------------------------------
-%%% @spec expect(Connection,Patterns,Opts) -> {ok,Match} |
-%%% {ok,MatchList,HaltReason} |
-%%% {error,Reason}
-%%% Connection = ct_telnet:connection()
-%%% Patterns = Pattern | [Pattern]
-%%% Pattern = string() | {Tag,string()} | prompt | {prompt,Prompt}
-%%% Prompt = string()
-%%% Tag = term()
-%%% Opts = [Opt]
-%%% Opt = {idle_timeout,IdleTimeout} | {total_timeout,TotalTimeout} |
-%%% repeat | {repeat,N} | sequence | {halt,HaltPatterns} |
-%%% ignore_prompt | no_prompt_check | wait_for_prompt |
-%%% {wait_for_prompt,Prompt}
-%%% IdleTimeout = infinity | integer()
-%%% TotalTimeout = infinity | integer()
-%%% N = integer()
-%%% HaltPatterns = Patterns
-%%% MatchList = [Match]
-%%% Match = RxMatch | {Tag,RxMatch} | {prompt,Prompt}
-%%% RxMatch = [string()]
-%%% HaltReason = done | Match
-%%% Reason = timeout | {prompt,Prompt}
-%%%
-%%% @doc Get data from telnet and wait for the expected pattern.
-%%%
-%%% <p><code>Pattern</code> can be a POSIX regular expression. The function
-%%% returns as soon as a pattern has been successfully matched (at least one,
-%%% in the case of multiple patterns).</p>
-%%%
-%%% <p><code>RxMatch</code> is a list of matched strings. It looks
-%%% like this: <code>[FullMatch, SubMatch1, SubMatch2, ...]</code>
-%%% where <code>FullMatch</code> is the string matched by the whole
-%%% regular expression and <code>SubMatchN</code> is the string that
-%%% matched subexpression no <code>N</code>. Subexpressions are
-%%% denoted with '(' ')' in the regular expression</p>
-%%%
-%%% <p>If a <code>Tag</code> is given, the returned <code>Match</code>
-%%% will also include the matched <code>Tag</code>. Else, only
-%%% <code>RxMatch</code> is returned.</p>
-%%%
-%%% <p>The <code>idle_timeout</code> option indicates that the function
-%%% shall return if the telnet client is idle (i.e. if no data is
-%%% received) for more than <code>IdleTimeout</code> milliseconds. Default
-%%% timeout is 10 seconds.</p>
-%%%
-%%% <p>The <code>total_timeout</code> option sets a time limit for
-%%% the complete expect operation. After <code>TotalTimeout</code>
-%%% milliseconds, <code>{error,timeout}</code> is returned. The default
-%%% value is <code>infinity</code> (i.e. no time limit).</p>
-%%%
-%%% <p>The function will return when a prompt is received, even if no
-%%% pattern has yet been matched. In this event,
-%%% <code>{error,{prompt,Prompt}}</code> is returned.
-%%% However, this behaviour may be modified with the
-%%% <code>ignore_prompt</code> or <code>no_prompt_check</code> option, which
-%%% tells <code>expect</code> to return only when a match is found or after a
-%%% timeout.</p>
-%%%
-%%% <p>If the <code>ignore_prompt</code> option is used,
-%%% <code>ct_telnet</code> will ignore any prompt found. This option
-%%% is useful if data sent by the server could include a pattern that
-%%% would match the prompt regexp (as returned by
-%%% <code>TargedMod:get_prompt_regexp/0</code>), but which should not
-%%% cause the function to return.</p>
-%%%
-%%% <p>If the <code>no_prompt_check</code> option is used,
-%%% <code>ct_telnet</code> will not search for a prompt at all. This
-%%% is useful if, for instance, the <code>Pattern</code> itself
-%%% matches the prompt.</p>
-%%%
-%%% <p>The <code>wait_for_prompt</code> option forces <code>ct_telnet</code>
-%%% to wait until the prompt string has been received before returning
-%%% (even if a pattern has already been matched). This is equal to calling:
-%%% <code>expect(Conn, Patterns++[{prompt,Prompt}], [sequence|Opts])</code>.
-%%% Note that <code>idle_timeout</code> and <code>total_timeout</code>
-%%% may abort the operation of waiting for prompt.</p>
-%%%
-%%% <p>The <code>repeat</code> option indicates that the pattern(s)
-%%% shall be matched multiple times. If <code>N</code> is given, the
-%%% pattern(s) will be matched <code>N</code> times, and the function
-%%% will return with <code>HaltReason = done</code>.</p>
-%%%
-%%% <p>The <code>sequence</code> option indicates that all patterns
-%%% shall be matched in a sequence. A match will not be concluded
-%%% untill all patterns are matched.</p>
-%%%
-%%% <p>Both <code>repeat</code> and <code>sequence</code> can be
-%%% interrupted by one or more <code>HaltPatterns</code>. When
-%%% <code>sequence</code> or <code>repeat</code> is used, there will
-%%% always be a <code>MatchList</code> returned, i.e. a list of
-%%% <code>Match</code> instead of only one <code>Match</code>. There
-%%% will also be a <code>HaltReason</code> returned.</p>
-%%%
-%%% <p><underline>Examples:</underline><br/>
-%%% <code>expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],</code>
-%%% <code>[sequence,{halt,[{nnn,"NNN"}]}]).</code><br/> will try to match
-%%% "ABC" first and then "XYZ", but if "NNN" appears the function will
-%%% return <code>{error,{nnn,["NNN"]}}</code>. If both "ABC" and "XYZ"
-%%% are matched, the function will return
-%%% <code>{ok,[AbcMatch,XyzMatch]}</code>.</p>
-%%%
-%%% <p><code>expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],</code>
-%%% <code>[{repeat,2},{halt,[{nnn,"NNN"}]}]).</code><br/> will try to match
-%%% "ABC" or "XYZ" twice. If "NNN" appears the function will return
-%%% with <code>HaltReason = {nnn,["NNN"]}</code>.</p>
-%%%
-%%% <p>The <code>repeat</code> and <code>sequence</code> options can be
-%%% combined in order to match a sequence multiple times.</p>
expect(Connection,Patterns,Opts) ->
case get_handle(Connection) of
{ok,Pid} ->
@@ -596,7 +219,7 @@ expect(Connection,Patterns,Opts) ->
%%%=================================================================
%%% Callback functions
-%% @hidden
+
init(Name,{Ip,Port,Type},{TargetMod,KeepAlive,Extra}) ->
S0 = case ct:get_config(telnet_settings) of
undefined ->
@@ -677,7 +300,6 @@ set_telnet_defaults([Unknown|Ss],S) ->
set_telnet_defaults([],S) ->
S.
-%% @hidden
handle_msg({cmd,Cmd,Opts},State) ->
start_gen_log(heading(cmd,State#state.name)),
log(State,cmd,"Cmd: ~tp",[Cmd]),
@@ -803,7 +425,6 @@ handle_msg({expect,Pattern,Opts},State) ->
{Return1,State#state{buffer=NewBuffer,prompt=Prompt}}.
-%% @hidden
reconnect({Ip,Port,_Type},State) ->
reconnect(Ip,Port,State#state.reconns,State).
reconnect(Ip,Port,N,State=#state{name=Name,
@@ -834,7 +455,6 @@ reconnect(Ip,Port,N,State=#state{name=Name,
end.
-%% @hidden
terminate(TelnPid,State) ->
Result = ct_telnet_client:close(TelnPid),
log(State,close,"Telnet connection for ~w closed.",[TelnPid]),
@@ -902,7 +522,6 @@ force_log(State,Action,String,Args) ->
log(State,Action,String,Args,true).
%%%-----------------------------------------------------------------
-%%% @hidden
log(State,Action,String,Args) when is_record(State, state) ->
log(State,Action,String,Args,false);
log(Name,Action,String,Args) when is_atom(Name) ->
@@ -911,7 +530,6 @@ log(TelnPid,Action,String,Args) when is_pid(TelnPid) ->
log(#state{teln_pid=TelnPid},Action,String,Args,false).
%%%-----------------------------------------------------------------
-%%% @hidden
log(undefined,String,Args) ->
log(#state{},undefined,String,Args,false);
log(Name,String,Args) when is_atom(Name) ->
@@ -920,7 +538,6 @@ log(TelnPid,String,Args) when is_pid(TelnPid) ->
log(#state{teln_pid=TelnPid},undefined,String,Args).
%%%-----------------------------------------------------------------
-%%% @hidden
log(#state{name=Name,teln_pid=TelnPid,host=Host,port=Port},
Action,String,Args,ForcePrint) ->
Name1 = if Name == undefined -> get({ct_telnet_pid2name,TelnPid});
@@ -971,7 +588,6 @@ log(#state{name=Name,teln_pid=TelnPid,host=Host,port=Port},
end.
%%%-----------------------------------------------------------------
-%%% @hidden
start_gen_log(Heading) ->
%% check if output is suppressed
case ct_util:is_silenced(telnet) of
@@ -980,7 +596,6 @@ start_gen_log(Heading) ->
end.
%%%-----------------------------------------------------------------
-%%% @hidden
end_gen_log() ->
%% check if output is suppressed
case ct_util:is_silenced(telnet) of
@@ -988,7 +603,6 @@ end_gen_log() ->
false -> ct_gen_conn:end_log()
end.
-%%% @hidden
%% Debug printouts.
debug_cont_gen_log(Str,Args) ->
Old = put(silent,true),
@@ -1038,8 +652,7 @@ teln_get_all_data(State=#state{teln_pid=Pid,prx=Prx},Data,Acc,LastLine,Polls) ->
found_prompt=false,
prompt_check=true}).
-%% @hidden
-%% @doc Externally the silent_teln_expect function shall only be used
+%% Externally the silent_teln_expect function shall only be used
%% by the TargetModule, i.e. the target specific module which
%% implements connect/2 and get_prompt_regexp/0.
silent_teln_expect(Name,Pid,Data,Pattern,Prx,Opts) ->
@@ -1057,9 +670,9 @@ silent_teln_expect(Name,Pid,Data,Pattern,Prx,Opts) ->
%% 2) Sequence: Several patterns are given, and they are matched in
%% the order they appear in the pattern list.
%% 3a) Repeat (single): 1) is repeated either N times or until a halt
-%% condition is fullfilled.
+%% condition is fulfilled.
%% 3b) Repeat (sequence): 2) is repeated either N times or until a
-%% halt condition is fullfilled.
+%% halt condition is fulfilled.
teln_expect(Name,Pid,Data,Pattern0,Prx,Opts) ->
HaltPatterns =
case get_ignore_prompt(Opts) of
@@ -1203,7 +816,7 @@ wait_for_prompt2(Prompt, Pattern, Opts) ->
{true,Pattern1,Opts1}.
%% Repeat either single or sequence. All match results are accumulated
-%% and returned when a halt condition is fulllfilled.
+%% and returned when a halt condition is fulfilled.
repeat_expect(_Name,_Pid,Rest,_Pattern,Acc,#eo{repeat=0}) ->
{ok,lists:reverse(Acc),done,Rest};
repeat_expect(Name,Pid,Data,Pattern,Acc,EO) ->
@@ -1342,7 +955,7 @@ one_expect1(Name,Pid,Data,Pattern,Rest,EO) ->
%% 2) Sequence.
%% First the whole data chunk is searched for a prompt (to avoid doing
%% a regexp match for the prompt at each line).
-%% If we are searching for anyting else, the datachunk is split into
+%% If we are searching for anything else, the datachunk is split into
%% lines and each line is matched against the first pattern in the list.
%% When a match is found, the match result is accumulated, and we keep
%% searching for the next pattern in the list.
@@ -1455,7 +1068,7 @@ match_line(Name,Pid,Line,[{prompt,PromptType}|Patterns],FoundPrompt,Term,
when PromptType=/=FoundPrompt ->
match_line(Name,Pid,Line,Patterns,FoundPrompt,Term,EO,RetTag);
match_line(Name,Pid,Line,[{Tag,Pattern}|Patterns],FoundPrompt,Term,EO,RetTag) ->
- case re:run(Line,Pattern,[{capture,all,list}]) of
+ case re:run(Line,Pattern,[{capture,all,list},unicode]) of
nomatch ->
match_line(Name,Pid,Line,Patterns,FoundPrompt,Term,EO,RetTag);
{match,Match} ->
@@ -1463,7 +1076,7 @@ match_line(Name,Pid,Line,[{Tag,Pattern}|Patterns],FoundPrompt,Term,EO,RetTag) ->
{RetTag,{Tag,Match}}
end;
match_line(Name,Pid,Line,[Pattern|Patterns],FoundPrompt,Term,EO,RetTag) ->
- case re:run(Line,Pattern,[{capture,all,list}]) of
+ case re:run(Line,Pattern,[{capture,all,list},unicode]) of
nomatch ->
match_line(Name,Pid,Line,Patterns,FoundPrompt,Term,EO,RetTag);
{match,Match} ->
@@ -1530,8 +1143,6 @@ add_tabs([],[$\n|Acc],LastLine) ->
add_tabs([],[],LastLine) ->
{[],lists:reverse(LastLine)}.
-
-%%% @hidden
teln_receive_until_prompt(Pid,Prx,Timeout) ->
Fun = fun() -> teln_receive_until_prompt(Pid,Prx,[],[]) end,
ct_gen_conn:do_within_time(Fun, Timeout).
@@ -1575,7 +1186,7 @@ split_lines([],Line,Lines) ->
match_prompt(Str,Prx) ->
match_prompt(Str,Prx,[]).
match_prompt(Str,Prx,Acc) ->
- case re:run(Str,Prx) of
+ case re:run(Str,Prx,[unicode]) of
nomatch ->
noprompt;
{match,[{Start,Len}]} ->
diff --git a/lib/common_test/src/ct_telnet_client.erl b/lib/common_test/src/ct_telnet_client.erl
index c8d217cd2a..76e4b9ea70 100644
--- a/lib/common_test/src/ct_telnet_client.erl
+++ b/lib/common_test/src/ct_telnet_client.erl
@@ -118,6 +118,7 @@ get_data(Pid) ->
%%%-----------------------------------------------------------------
%%% Internal functions
init(Parent, Server, Port, Timeout, KeepAlive, NoDelay, ConnName) ->
+ ct_util:mark_process(),
case gen_tcp:connect(Server, Port, [list,{packet,0},{nodelay,NoDelay}], Timeout) of
{ok,Sock} ->
dbg("~tp connected to: ~tp (port: ~w, keep_alive: ~w)\n",
diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl
index 09839bd35d..2c18caf18f 100644
--- a/lib/common_test/src/ct_testspec.erl
+++ b/lib/common_test/src/ct_testspec.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,10 +18,6 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test Framework functions handling test specifications.
-%%%
-%%% <p>This module exports functions that are used within CT to
-%%% scan and parse test specifikations.</p>
-module(ct_testspec).
-export([prepare_tests/1, prepare_tests/2,
@@ -537,7 +533,7 @@ replace_names_in_elems([],Modified,_Defs) ->
replace_names_in_string(Term,Defs=[{Name,Replacement=[Ch|_]}|Ds])
when is_integer(Ch) ->
try re:replace(Term,[$'|atom_to_list(Name)]++"'",
- Replacement,[{return,list}]) of
+ Replacement,[{return,list},unicode]) of
Term -> % no match, proceed
replace_names_in_string(Term,Ds);
Term1 ->
@@ -569,7 +565,7 @@ replace_names_in_node1(NodeStr,Defs=[{Name,Replacement}|Ds]) ->
replace_names_in_node1(NodeStr,Ds);
true ->
case re:replace(NodeStr,atom_to_list(Name),
- ReplStr,[{return,list}]) of
+ ReplStr,[{return,list},unicode]) of
NodeStr -> % no match, proceed
replace_names_in_node1(NodeStr,Ds);
NodeStr1 ->
@@ -1425,7 +1421,12 @@ skip_groups1(Suite,Groups,Cmt,Suites0) ->
GrAndCases1 = GrAndCases0 ++ SkipGroups,
insert_in_order({Suite,GrAndCases1},Suites0,replace);
false ->
- insert_in_order({Suite,SkipGroups},Suites0,replace)
+ case Suites0 of
+ [{all,_}=All|Skips]->
+ [All|Skips++[{Suite,SkipGroups}]];
+ _ ->
+ insert_in_order({Suite,SkipGroups},Suites0,replace)
+ end
end.
skip_cases(Node,Dir,Suite,Cases,Cmt,Tests,false) when is_list(Cases) ->
diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl
index abf131f4df..d8fd401a64 100644
--- a/lib/common_test/src/ct_util.erl
+++ b/lib/common_test/src/ct_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,11 +18,11 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test Framework Utilities.
+%%% Common Test Framework Utilities.
%%%
-%%% <p>This is a support module for the Common Test Framework. It
+%%% This is a support module for the Common Test Framework. It
%%% implements the process ct_util_server which acts like a data
-%%% holder for suite, configuration and connection data.</p>
+%%% holder for suite, configuration and connection data.
%%%
-module(ct_util).
@@ -65,6 +65,9 @@
-export([warn_duplicates/1]).
+-export([mark_process/0, mark_process/1, is_marked/1, is_marked/2,
+ remaining_test_procs/0]).
+
-export([get_profile_data/0, get_profile_data/1,
get_profile_data/2, open_url/3]).
@@ -80,20 +83,20 @@
%%%-----------------------------------------------------------------
start() ->
start(normal, ".", ?default_verbosity).
-%%% @spec start(Mode) -> Pid | exit(Error)
+%%% -spec start(Mode) -> Pid | exit(Error)
%%% Mode = normal | interactive
%%% Pid = pid()
%%%
-%%% @doc Start start the ct_util_server process
+%%% Start start the ct_util_server process
%%% (tool-internal use only).
%%%
-%%% <p>This function is called from ct_run.erl. It starts and initiates
-%%% the <code>ct_util_server</code></p>
+%%% This function is called from ct_run.erl. It starts and initiates
+%%% the ct_util_server
%%%
-%%% <p>Returns the process identity of the
-%%% <code>ct_util_server</code>.</p>
+%%% Returns the process identity of the
+%%% ct_util_server.
%%%
-%%% @see ct
+%%% See ct.
start(LogDir) when is_list(LogDir) ->
start(normal, LogDir, ?default_verbosity);
start(Mode) ->
@@ -126,6 +129,7 @@ start(Mode, LogDir, Verbosity) ->
do_start(Parent, Mode, LogDir, Verbosity) ->
process_flag(trap_exit,true),
register(ct_util_server,self()),
+ mark_process(),
create_table(?conn_table,#conn.handle),
create_table(?board_table,2),
create_table(?suite_table,#suite_data.key),
@@ -205,11 +209,10 @@ do_start(Parent, Mode, LogDir, Verbosity) ->
self() ! {{stop,{self(),{user_error,CTHReason}}},
{Parent,make_ref()}}
catch
- _:CTHReason ->
+ _:CTHReason:StackTrace ->
ErrorInfo = if is_atom(CTHReason) ->
io_lib:format("{~tp,~tp}",
- [CTHReason,
- erlang:get_stacktrace()]);
+ [CTHReason, StackTrace]);
true ->
CTHReason
end,
@@ -517,19 +520,19 @@ get_key_from_name(Name)->
ct_config:get_key_from_name(Name).
%%%-----------------------------------------------------------------
-%%% @spec register_connection(TargetName,Address,Callback,Handle) ->
+%%% -spec register_connection(TargetName,Address,Callback,Handle) ->
%%% ok | {error,Reason}
%%% TargetName = ct:target_name()
%%% Address = term()
%%% Callback = atom()
%%% Handle = term
%%%
-%%% @doc Register a new connection (tool-internal use only).
+%%% Register a new connection (tool-internal use only).
%%%
-%%% <p>This function can be called when a new connection is
+%%% This function can be called when a new connection is
%%% established. The connection data is stored in the connection
%%% table, and ct_util will close all registered connections when the
-%%% test is finished by calling <code>Callback:close/1</code>.</p>
+%%% test is finished by calling Callback:close/1.
register_connection(TargetName,Address,Callback,Handle) ->
%% If TargetName is a registered alias for a config
%% variable, use it as reference for the connection,
@@ -550,28 +553,28 @@ register_connection(TargetName,Address,Callback,Handle) ->
ok.
%%%-----------------------------------------------------------------
-%%% @spec unregister_connection(Handle) -> ok
+%%% -spec unregister_connection(Handle) -> ok
%%% Handle = term
%%%
-%%% @doc Unregister a connection (tool-internal use only).
+%%% Unregister a connection (tool-internal use only).
%%%
-%%% <p>This function should be called when a registered connection is
+%%% This function should be called when a registered connection is
%%% closed. It removes the connection data from the connection
-%%% table.</p>
+%%% table.
unregister_connection(Handle) ->
ets:delete(?conn_table,Handle),
ok.
%%%-----------------------------------------------------------------
-%%% @spec does_connection_exist(TargetName,Address,Callback) ->
+%%% -spec does_connection_exist(TargetName,Address,Callback) ->
%%% {ok,Handle} | false
%%% TargetName = ct:target_name()
%%% Address = address
%%% Callback = atom()
%%% Handle = term()
%%%
-%%% @doc Check if a connection already exists.
+%%% Check if a connection already exists.
does_connection_exist(TargetName,Address,Callback) ->
case ct_config:get_key_from_name(TargetName) of
{ok,_Key} ->
@@ -591,7 +594,7 @@ does_connection_exist(TargetName,Address,Callback) ->
end.
%%%-----------------------------------------------------------------
-%%% @spec get_connection(TargetName,Callback) ->
+%%% -spec get_connection(TargetName,Callback) ->
%%% {ok,Connection} | {error,Reason}
%%% TargetName = ct:target_name()
%%% Callback = atom()
@@ -599,8 +602,8 @@ does_connection_exist(TargetName,Address,Callback) ->
%%% Handle = term()
%%% Address = term()
%%%
-%%% @doc Return the connection for <code>Callback</code> on the
-%%% given target (<code>TargetName</code>).
+%%% Return the connection for Callback on the
+%%% given target (TargetName).
get_connection(TargetName,Callback) ->
%% check that TargetName is a registered alias
case ct_config:get_key_from_name(TargetName) of
@@ -621,7 +624,7 @@ get_connection(TargetName,Callback) ->
end.
%%%-----------------------------------------------------------------
-%%% @spec get_connections(ConnPid) ->
+%%% -spec get_connections(ConnPid) ->
%%% {ok,Connections} | {error,Reason}
%%% Connections = [Connection]
%%% Connection = {TargetName,Handle,Callback,Address}
@@ -630,8 +633,8 @@ get_connection(TargetName,Callback) ->
%%% Callback = atom()
%%% Address = term()
%%%
-%%% @doc Get data for all connections associated with a particular
-%%% connection pid (see Callback:init/3).
+%%% Get data for all connections associated with a particular
+%%% connection pid (see Callback:init/3).
get_connections(ConnPid) ->
Conns = ets:tab2list(?conn_table),
lists:flatmap(fun(#conn{targetref=TargetName,
@@ -651,8 +654,7 @@ get_connections(ConnPid) ->
end, Conns).
%%%-----------------------------------------------------------------
-%%% @hidden
-%%% @equiv ct:get_target_name/1
+%%% Equivalent to ct:get_target_name/1
get_target_name(Handle) ->
case ets:select(?conn_table,[{#conn{handle=Handle,targetref='$1',_='_'},
[],
@@ -664,17 +666,14 @@ get_target_name(Handle) ->
end.
%%%-----------------------------------------------------------------
-%%% @spec close_connections() -> ok
+%%% -spec close_connections() -> ok
%%%
-%%% @doc Close all open connections.
+%%% Close all open connections.
close_connections() ->
close_connections(ets:tab2list(?conn_table)),
ok.
%%%-----------------------------------------------------------------
-%%% @spec
-%%%
-%%% @doc
override_silence_all_connections() ->
Protocols = [telnet,ftp,rpc,snmp,ssh],
override_silence_connections(Protocols),
@@ -735,12 +734,12 @@ reset_silent_connections() ->
%%%-----------------------------------------------------------------
-%%% @spec stop(Info) -> ok
+%%% -spec stop(Info) -> ok
%%%
-%%% @doc Stop the ct_util_server and close all existing connections
+%%% Stop the ct_util_server and close all existing connections
%%% (tool-internal use only).
%%%
-%%% @see ct
+%%% See ct.
stop(Info) ->
case whereis(ct_util_server) of
undefined ->
@@ -754,26 +753,25 @@ stop(Info) ->
end.
%%%-----------------------------------------------------------------
-%%% @spec update_last_run_index() -> ok
+%%% -spec update_last_run_index() -> ok
%%%
-%%% @doc Update <code>ct_run.&lt;timestamp&gt;/index.html</code>
+%%% Update ct_run.<timestamp>/index.html
%%% (tool-internal use only).
update_last_run_index() ->
call(update_last_run_index).
%%%-----------------------------------------------------------------
-%%% @spec get_mode() -> Mode
+%%% -spec get_mode() -> Mode
%%% Mode = normal | interactive
%%%
-%%% @doc Return the current mode of the ct_util_server
+%%% Return the current mode of the ct_util_server
%%% (tool-internal use only).
get_mode() ->
call(get_mode).
%%%-----------------------------------------------------------------
-%%% @hidden
-%%% @equiv ct:listenv/1
+%%% Equivalent to ct:listenv/1
listenv(Telnet) ->
case ct_telnet:send(Telnet,"listenv") of
ok ->
@@ -787,33 +785,32 @@ listenv(Telnet) ->
end.
%%%-----------------------------------------------------------------
-%%% @hidden
-%%% @equiv ct:parse_table/1
+%%% Equivalent to ct:parse_table/1
parse_table(Data) ->
{Heading, Rest} = get_headings(Data),
Lines = parse_row(Rest,[],size(Heading)),
{Heading,Lines}.
get_headings(["|" ++ Headings | Rest]) ->
- {remove_space(string:tokens(Headings, "|"),[]), Rest};
+ {remove_space(string:lexemes(Headings, "|"),[]), Rest};
get_headings([_ | Rest]) ->
get_headings(Rest);
get_headings([]) ->
{{},[]}.
parse_row(["|" ++ _ = Row | T], Rows, NumCols) when NumCols > 1 ->
- case string:tokens(Row, "|") of
+ case string:lexemes(Row, "|") of
Values when length(Values) =:= NumCols ->
parse_row(T,[remove_space(Values,[])|Rows], NumCols);
Values when length(Values) < NumCols ->
parse_row([Row ++"\n"++ hd(T) | tl(T)], Rows, NumCols)
end;
-parse_row(["|" ++ _ = Row | T], Rows, 1 = NumCols) ->
- case string:rchr(Row, $|) of
- 1 ->
+parse_row(["|" ++ X = Row | T], Rows, 1 = NumCols) ->
+ case string:find(X, [$|]) of
+ nomatch ->
parse_row([Row ++"\n"++hd(T) | tl(T)], Rows, NumCols);
_Else ->
- parse_row(T, [remove_space(string:tokens(Row,"|"),[])|Rows],
+ parse_row(T, [remove_space(string:lexemes(Row,"|"),[])|Rows],
NumCols)
end;
parse_row([_Skip | T], Rows, NumCols) ->
@@ -822,22 +819,16 @@ parse_row([], Rows, _NumCols) ->
lists:reverse(Rows).
remove_space([Str|Rest],Acc) ->
- remove_space(Rest,[string:strip(string:strip(Str),both,$')|Acc]);
+ remove_space(Rest,[string:trim(string:trim(Str,both,[$\s]),both,[$'])|Acc]);
remove_space([],Acc) ->
list_to_tuple(lists:reverse(Acc)).
%%%-----------------------------------------------------------------
-%%% @spec
-%%%
-%%% @doc
is_test_dir(Dir) ->
- lists:last(string:tokens(filename:basename(Dir), "_")) == "test".
+ lists:last(string:lexemes(filename:basename(Dir), "_")) == "test".
%%%-----------------------------------------------------------------
-%%% @spec
-%%%
-%%% @doc
get_testdir(Dir, all) ->
Abs = abs_name(Dir),
case is_test_dir(Abs) of
@@ -881,9 +872,6 @@ get_testdir(Dir, _) ->
get_testdir(Dir, all).
%%%-----------------------------------------------------------------
-%%% @spec
-%%%
-%%% @doc
get_attached(TCPid) ->
case dbg_iserver:safe_call({get_attpid,TCPid}) of
{ok,AttPid} when is_pid(AttPid) ->
@@ -893,9 +881,6 @@ get_attached(TCPid) ->
end.
%%%-----------------------------------------------------------------
-%%% @spec
-%%%
-%%% @doc
kill_attached(undefined,_AttPid) ->
ok;
kill_attached(_TCPid,undefined) ->
@@ -910,9 +895,6 @@ kill_attached(TCPid,AttPid) ->
%%%-----------------------------------------------------------------
-%%% @spec
-%%%
-%%% @doc
warn_duplicates(Suites) ->
Warn =
fun(Mod) ->
@@ -931,9 +913,67 @@ warn_duplicates(Suites) ->
ok.
%%%-----------------------------------------------------------------
-%%% @spec
-%%%
-%%% @doc
+mark_process() ->
+ mark_process(system).
+
+mark_process(Type) ->
+ put(ct_process_type, Type).
+
+is_marked(Pid) ->
+ is_marked(Pid, system).
+
+is_marked(Pid, Type) ->
+ case process_info(Pid, dictionary) of
+ {dictionary,List} ->
+ Type == proplists:get_value(ct_process_type, List);
+ undefined ->
+ false
+ end.
+
+remaining_test_procs() ->
+ Procs = processes(),
+ {SharedGL,OtherGLs,Procs2} =
+ lists:foldl(
+ fun(Pid, ProcTypes = {Shared,Other,Procs1}) ->
+ case is_marked(Pid, group_leader) of
+ true ->
+ if not is_pid(Shared) ->
+ case test_server_io:get_gl(true) of
+ Pid ->
+ {Pid,Other,
+ lists:delete(Pid,Procs1)};
+ _ ->
+ {Shared,[Pid|Other],Procs1}
+ end;
+ true -> % SharedGL already found
+ {Shared,[Pid|Other],Procs1}
+ end;
+ false ->
+ case is_marked(Pid) of
+ true ->
+ {Shared,Other,lists:delete(Pid,Procs1)};
+ false ->
+ ProcTypes
+ end
+ end
+ end, {undefined,[],Procs}, Procs),
+
+ AllGLs = [SharedGL | OtherGLs],
+ TestProcs =
+ lists:flatmap(fun(Pid) ->
+ case process_info(Pid, group_leader) of
+ {group_leader,GL} ->
+ case lists:member(GL, AllGLs) of
+ true -> [{Pid,GL}];
+ false -> []
+ end;
+ undefined ->
+ []
+ end
+ end, Procs2),
+ {TestProcs, SharedGL, OtherGLs}.
+
+%%%-----------------------------------------------------------------
get_profile_data() ->
get_profile_data(all).
@@ -1077,7 +1117,7 @@ open_url(iexplore, Args, URL) ->
_ = case win32reg:values(R) of
{ok, Paths} ->
Path = proplists:get_value(default, Paths),
- [Cmd | _] = string:tokens(Path, "%"),
+ [Cmd | _] = string:lexemes(Path, "%"),
Cmd1 = Cmd ++ " " ++ Args ++ " " ++ URL,
io:format(?def_gl, "~nOpening ~ts with command:~n ~ts~n", [URL,Cmd1]),
open_port({spawn,Cmd1}, []);
diff --git a/lib/common_test/src/ct_webtool.erl b/lib/common_test/src/ct_webtool.erl
index 9016aca899..32d4255217 100644
--- a/lib/common_test/src/ct_webtool.erl
+++ b/lib/common_test/src/ct_webtool.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -343,6 +343,7 @@ code_change(_,State,_)->
% Start the gen_server
%----------------------------------------------------------------------
init({Path,Config})->
+ ct_util:mark_process(),
case filelib:is_dir(Path) of
true ->
{ok, Table} = get_tool_files_data(),
@@ -770,7 +771,7 @@ fill_out(Nr)->
%Controls whether the user selected a tool to start
%----------------------------------------------------------------------
get_tools(Input)->
- case httpd:parse_query(Input) of
+ case uri_string:dissect_query(Input) of
[]->
no_tools;
Tools->
diff --git a/lib/common_test/src/ct_webtool_sup.erl b/lib/common_test/src/ct_webtool_sup.erl
index c02ec69d04..04fbbf8745 100644
--- a/lib/common_test/src/ct_webtool_sup.erl
+++ b/lib/common_test/src/ct_webtool_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -46,6 +46,7 @@ stop(Pid)->
%% {error, Reason}
%%----------------------------------------------------------------------
init(_StartArgs) ->
+ ct_util:mark_process(),
%%Child1 =
%%Child2 ={webcover_backend,{webcover_backend,start_link,[]},permanent,2000,worker,[webcover_backend]},
%%{ok,{{simple_one_for_one,5,10},[Child1]}}.
diff --git a/lib/common_test/src/cth_log_redirect.erl b/lib/common_test/src/cth_log_redirect.erl
index 8b29d0f96d..4980d1ee4b 100644
--- a/lib/common_test/src/cth_log_redirect.erl
+++ b/lib/common_test/src/cth_log_redirect.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,11 +19,9 @@
%%
-module(cth_log_redirect).
-%%% @doc Common Test Framework functions handling test specifications.
+%%% Common Test Framework functions handling test specifications.
%%%
-%%% <p>This module redirects sasl and error logger info to common test log.</p>
-%%% @end
-
+%%% This module redirects sasl and error logger info to common test log.
%% CTH Callbacks
-export([id/1, init/2,
@@ -33,17 +31,19 @@
pre_init_per_testcase/4, post_init_per_testcase/5,
pre_end_per_testcase/4, post_end_per_testcase/5]).
-%% Event handler Callbacks
--export([init/1,
- handle_event/2, handle_call/2, handle_info/2,
- terminate/1, terminate/2, code_change/3]).
+%% Logger handler and gen_server callbacks
+-export([log/2,
+ init/1,
+ handle_cast/2, handle_call/3,
+ terminate/1, terminate/2]).
%% Other
-export([handle_remote_events/1]).
-include("ct.hrl").
+-include("../../kernel/src/logger_internal.hrl").
--behaviour(gen_event).
+-behaviour(gen_server).
-record(eh_state, {log_func,
curr_suite,
@@ -56,7 +56,8 @@ id(_Opts) ->
?MODULE.
init(?MODULE, _Opts) ->
- error_logger:add_report_handler(?MODULE),
+ ct_util:mark_process(),
+ ok = start_log_handler(),
tc_log_async.
pre_init_per_suite(Suite, Config, State) ->
@@ -99,7 +100,7 @@ pre_end_per_testcase(_Suite, _TC, Config, State) ->
post_end_per_testcase(_Suite, _TC, _Config, Result, State) ->
%% Make sure that the event queue is flushed
%% before ending this test case.
- gen_event:call(error_logger, ?MODULE, flush, 300000),
+ gen_server:call(?MODULE, flush, 300000),
{Result, State}.
pre_end_per_group(_Suite, Group, Config, {tc_log, Group}) ->
@@ -113,127 +114,146 @@ post_end_per_group(_Suite, _Group, Config, Return, State) ->
set_curr_func({group,undefined}, Config),
{Return, State}.
-%% Copied and modified from sasl_report_tty_h.erl
-init(_Type) ->
- {ok, #eh_state{log_func = tc_log_async}}.
-
-handle_event({_Type,GL,_Msg}, #eh_state{handle_remote_events = false} = State)
- when node(GL) /= node() ->
- {ok, State};
-handle_event(Event, #eh_state{log_func = LogFunc} = State) ->
- case lists:keyfind(sasl, 1, application:which_applications()) of
- false ->
- sasl_not_started;
- _Else ->
- {ok, ErrLogType} = application:get_env(sasl, errlog_type),
- SReport = sasl_report:format_report(group_leader(), ErrLogType,
- tag_event(Event, local)),
- if is_list(SReport) ->
- SaslHeader = format_header(State),
- case LogFunc of
- tc_log ->
- ct_logs:tc_log(sasl, ?STD_IMPORTANCE,
- SaslHeader, SReport, [], []);
- tc_log_async ->
- ct_logs:tc_log_async(sasl, ?STD_IMPORTANCE,
- SaslHeader, SReport, [])
- end;
- true -> %% Report is an atom if no logging is to be done
- ignore
- end
- end,
- %% note that error_logger (unlike sasl) expects UTC time
- EReport = error_logger_tty_h:write_event(
- tag_event(Event, utc), io_lib),
- if is_list(EReport) ->
- ErrHeader = format_header(State),
- case LogFunc of
- tc_log ->
- ct_logs:tc_log(error_logger, ?STD_IMPORTANCE,
- ErrHeader, EReport, [], []);
- tc_log_async ->
- ct_logs:tc_log_async(error_logger, ?STD_IMPORTANCE,
- ErrHeader, EReport, [])
- end;
- true -> %% Report is an atom if no logging is to be done
- ignore
+start_log_handler() ->
+ case whereis(?MODULE) of
+ undefined ->
+ ChildSpec =
+ #{id=>?MODULE,
+ start=>{gen_server,start_link,[{local,?MODULE},?MODULE,[],[]]},
+ restart=>transient,
+ shutdown=>2000,
+ type=>worker,
+ modules=>[?MODULE]},
+ {ok,_} = supervisor:start_child(logger_sup,ChildSpec);
+ _Pid ->
+ ok
end,
- {ok, State}.
+ ok = logger:add_handler(?MODULE,?MODULE,
+ #{level=>info,
+ formatter=>{?DEFAULT_FORMATTER,
+ ?DEFAULT_FORMAT_CONFIG}}).
+
+init([]) ->
+ {ok, #eh_state{log_func = tc_log_async}}.
-handle_info({'EXIT',User,killed}, State) ->
- case whereis(user) of
- %% init:stop/1/2 has been called, let's finish!
+log(#{msg:={report,Msg},meta:=#{domain:=[otp,sasl]}}=Log,Config) ->
+ case whereis(sasl_sup) of
undefined ->
- remove_handler;
- User ->
- remove_handler;
- _ ->
- {ok,State}
+ ok; % sasl application is not started
+ _Else ->
+ Level =
+ case application:get_env(sasl, errlog_type) of
+ {ok,error} ->
+ error;
+ {ok,_} ->
+ info;
+ undefined ->
+ info
+ end,
+ case Level of
+ error ->
+ case Msg of
+ #{label:={_,progress}} ->
+ ok;
+ _ ->
+ do_log(add_log_category(Log,sasl),Config)
+ end;
+ _ ->
+ do_log(add_log_category(Log,sasl),Config)
+ end
end;
+log(#{meta:=#{domain:=[otp]}}=Log,Config) ->
+ do_log(add_log_category(Log,error_logger),Config);
+log(#{meta:=#{domain:=_}},_) ->
+ ok;
+log(Log,Config) ->
+ do_log(add_log_category(Log,error_logger),Config).
+
+add_log_category(#{meta:=Meta}=Log,Category) ->
+ Log#{meta=>Meta#{?MODULE=>#{category=>Category}}}.
+
+do_log(Log,Config) ->
+ gen_server:call(?MODULE,{log,Log,Config}).
-handle_info(_, State) ->
- {ok,State}.
+handle_cast(_, State) ->
+ {noreply,State}.
-handle_call(flush,State) ->
- {ok, ok, State};
+handle_call({log,#{meta:=#{gl:=GL}},_}, _From,
+ #eh_state{handle_remote_events=false}=State)
+ when node(GL) /= node() ->
+ {reply, ok, State};
+
+handle_call({log,
+ #{meta:=#{?MODULE:=#{category:=Category}}}=Log,
+ #{formatter:={Formatter,FConfig}}},
+ _From,
+ #eh_state{log_func=LogFunc}=State) ->
+ Header = format_header(State),
+ String = Formatter:format(Log,FConfig),
+ case LogFunc of
+ tc_log ->
+ ct_logs:tc_log(Category, ?STD_IMPORTANCE,
+ Header, String, [], []);
+ tc_log_async ->
+ ct_logs:tc_log_async(sasl, ?STD_IMPORTANCE,
+ Header, String, [])
+ end,
+ {reply,ok,State};
-handle_call({set_curr_func,{group,Group,Conf},Config},
- State) when is_list(Config) ->
+handle_call(flush,_From,State) ->
+ {reply, ok, State};
+
+handle_call({set_curr_func,{group,Group,Conf},Config},_From,State)
+ when is_list(Config) ->
Parallel = case proplists:get_value(tc_group_properties, Config) of
undefined -> false;
Props -> lists:member(parallel, Props)
end,
- {ok, ok, State#eh_state{curr_group = Group,
- curr_func = Conf,
- parallel_tcs = Parallel}};
-handle_call({set_curr_func,{group,Group,Conf},_SkipOrFail}, State) ->
- {ok, ok, State#eh_state{curr_group = Group,
- curr_func = Conf,
- parallel_tcs = false}};
-handle_call({set_curr_func,{group,undefined},_Config}, State) ->
- {ok, ok, State#eh_state{curr_group = undefined,
- curr_func = undefined,
- parallel_tcs = false}};
-handle_call({set_curr_func,{Suite,Conf},_Config}, State) ->
- {ok, ok, State#eh_state{curr_suite = Suite,
- curr_func = Conf,
- parallel_tcs = false}};
-handle_call({set_curr_func,undefined,_Config}, State) ->
- {ok, ok, State#eh_state{curr_suite = undefined,
- curr_func = undefined,
- parallel_tcs = false}};
-handle_call({set_curr_func,TC,_Config}, State) ->
- {ok, ok, State#eh_state{curr_func = TC}};
-
-handle_call({set_logfunc,NewLogFunc}, State) ->
- {ok, NewLogFunc, State#eh_state{log_func = NewLogFunc}};
-
-handle_call({handle_remote_events,Bool}, State) ->
- {ok, ok, State#eh_state{handle_remote_events = Bool}};
-
-handle_call(_Query, _State) ->
- {error, bad_query}.
+ {reply, ok, State#eh_state{curr_group = Group,
+ curr_func = Conf,
+ parallel_tcs = Parallel}};
+handle_call({set_curr_func,{group,Group,Conf},_SkipOrFail}, _From, State) ->
+ {reply, ok, State#eh_state{curr_group = Group,
+ curr_func = Conf,
+ parallel_tcs = false}};
+handle_call({set_curr_func,{group,undefined},_Config}, _From, State) ->
+ {reply, ok, State#eh_state{curr_group = undefined,
+ curr_func = undefined,
+ parallel_tcs = false}};
+handle_call({set_curr_func,{Suite,Conf},_Config}, _From, State) ->
+ {reply, ok, State#eh_state{curr_suite = Suite,
+ curr_func = Conf,
+ parallel_tcs = false}};
+handle_call({set_curr_func,undefined,_Config}, _From, State) ->
+ {reply, ok, State#eh_state{curr_suite = undefined,
+ curr_func = undefined,
+ parallel_tcs = false}};
+handle_call({set_curr_func,TC,_Config}, _From, State) ->
+ {reply, ok, State#eh_state{curr_func = TC}};
+
+handle_call({set_logfunc,NewLogFunc}, _From, State) ->
+ {reply, NewLogFunc, State#eh_state{log_func = NewLogFunc}};
+
+handle_call({handle_remote_events,Bool}, _From, State) ->
+ {reply, ok, State#eh_state{handle_remote_events = Bool}}.
terminate(_) ->
- error_logger:delete_report_handler(?MODULE),
- [].
+ _ = logger:remove_handler(?MODULE),
+ _ = supervisor:terminate_child(logger_sup,?MODULE),
+ _ = supervisor:delete_child(logger_sup,?MODULE),
+ ok.
terminate(_Arg, _State) ->
ok.
-tag_event(Event, utc) ->
- {calendar:universal_time(), Event};
-tag_event(Event, _) ->
- {calendar:local_time(), Event}.
-
set_curr_func(CurrFunc, Config) ->
- gen_event:call(error_logger, ?MODULE, {set_curr_func, CurrFunc, Config}).
+ gen_server:call(?MODULE, {set_curr_func, CurrFunc, Config}).
set_log_func(Func) ->
- gen_event:call(error_logger, ?MODULE, {set_logfunc, Func}).
+ gen_server:call(?MODULE, {set_logfunc, Func}).
handle_remote_events(Bool) ->
- gen_event:call(error_logger, ?MODULE, {handle_remote_events, Bool}).
+ gen_server:call(?MODULE, {handle_remote_events, Bool}).
%%%-----------------------------------------------------------------
@@ -271,6 +291,3 @@ format_header(#eh_state{curr_suite = Suite,
curr_func = TC}) ->
io_lib:format("System report during ~w:~tw/1 in ~tw",
[Suite,TC,Group]).
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
diff --git a/lib/common_test/src/cth_surefire.erl b/lib/common_test/src/cth_surefire.erl
index da68bd105e..b0742717ae 100644
--- a/lib/common_test/src/cth_surefire.erl
+++ b/lib/common_test/src/cth_surefire.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,10 +18,10 @@
%% %CopyrightEnd%
%%--------------------------------------------------------------------
-%%% @doc Common Test Framework functions handling test specifications.
+%%% Common Test Framework functions handling test specifications.
%%%
-%%% <p>This module creates a junit report of the test run if plugged in
-%%% as a suite_callback.</p>
+%%% This module creates a junit report of the test run if plugged in
+%%% as a suite_callback.
-module(cth_surefire).
@@ -184,15 +184,14 @@ end_tc(Name, _Config, _Res, State = #state{ curr_suite = Suite,
Log =
case Log0 of
"" ->
- LowerSuiteName = string:to_lower(atom_to_list(Suite)),
+ LowerSuiteName = string:lowercase(atom_to_list(Suite)),
filename:join(CurrLogDir,LowerSuiteName++"."++Name++".html");
_ ->
Log0
end,
Url = make_url(UrlBase,Log),
ClassName = atom_to_list(Suite),
- PGroup = string:join([ atom_to_list(Group)||
- Group <- lists:reverse(Groups)],"."),
+ PGroup = lists:concat(lists:join(".",lists:reverse(Groups))),
TimeTakes = io_lib:format("~f",[timer:now_diff(?now,TS) / 1000000]),
State#state{ test_cases = [#testcase{ log = Log,
url = Url,
@@ -317,9 +316,9 @@ make_url(undefined,_) ->
make_url(_,[]) ->
undefined;
make_url(UrlBase0,Log) ->
- UrlBase = string:strip(UrlBase0,right,$/),
+ UrlBase = string:trim(UrlBase0,trailing,[$/]),
RelativeLog = get_relative_log_url(Log),
- string:join([UrlBase,RelativeLog],"/").
+ lists:flatten(lists:join($/,[UrlBase,RelativeLog])).
get_test_root(Log) ->
LogParts = filename:split(Log),
@@ -329,7 +328,7 @@ get_relative_log_url(Log) ->
LogParts = filename:split(Log),
Start = length(LogParts)-?log_depth,
Length = ?log_depth+1,
- string:join(lists:sublist(LogParts,Start,Length),"/").
+ lists:flatten(lists:join($/,lists:sublist(LogParts,Start,Length))).
count_tcs([#testcase{name=ConfCase}|TCs],Ok,F,S)
when ConfCase=="init_per_suite";
diff --git a/lib/common_test/src/test_server.erl b/lib/common_test/src/test_server.erl
index ee3a5e4bba..a896a0551b 100644
--- a/lib/common_test/src/test_server.erl
+++ b/lib/common_test/src/test_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
-define(DEFAULT_TIMETRAP_SECS, 60).
%%% TEST_SERVER_CTRL INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--export([run_test_case_apply/1,init_target_info/0]).
+-export([run_test_case_apply/1,init_target_info/0,init_valgrind/0]).
-export([cover_compile/1,cover_analyse/2]).
%%% TEST_SERVER_SUP INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -49,6 +49,10 @@
-export([break/1,break/2,break/3,continue/0,continue/1]).
+%%% DEBUGGER INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-export([valgrind_new_leaks/0, valgrind_format/2,
+ is_valgrind/0]).
+
%%% PRIVATE EXPORTED %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-export([]).
@@ -69,6 +73,10 @@ init_target_info() ->
username=test_server_sup:get_username(),
cookie=atom_to_list(erlang:get_cookie())}.
+init_valgrind() ->
+ valgrind_new_leaks().
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% cover_compile(#cover{app=App,incl=Include,excl=Exclude,cross=Cross}) ->
%% {ok,#cover{mods=AnalyseModules}} | {error,Reason}
@@ -358,11 +366,12 @@ stick_all_sticky(Node,Sticky) ->
%% compensate timetraps for runtime delays introduced by e.g. tools like
%% cover.
-run_test_case_apply({Mod,Func,Args,Name,RunInit,TimetrapData}) ->
+run_test_case_apply({CaseNum,Mod,Func,Args,Name,RunInit,TimetrapData}) ->
case is_valgrind() of
false ->
ok;
true ->
+ valgrind_format("Test case #~w ~w:~w/1", [CaseNum, Mod, Func]),
os:putenv("VALGRIND_LOGFILE_INFIX",atom_to_list(Mod)++"."++
atom_to_list(Func)++"-")
end,
@@ -370,6 +379,7 @@ run_test_case_apply({Mod,Func,Args,Name,RunInit,TimetrapData}) ->
Result = run_test_case_apply(Mod, Func, Args, Name, RunInit,
TimetrapData),
ProcAft = erlang:system_info(process_count),
+ valgrind_new_leaks(),
DetFail = get(test_server_detected_fail),
{Result,DetFail,ProcBef,ProcAft}.
@@ -405,6 +415,7 @@ run_test_case_apply(Mod, Func, Args, Name, RunInit, TimetrapData) ->
St = #st{ref=Ref,pid=Pid,mf={Mod,Func},last_known_loc=unknown,
status=starting,ret_val=[],comment="",timeout=infinity,
config=hd(Args)},
+ ct_util:mark_process(),
run_test_case_msgloop(St).
%% Ugly bug (pre R5A):
@@ -452,11 +463,12 @@ run_test_case_msgloop(#st{ref=Ref,pid=Pid,end_conf_pid=EndConfPid0}=St0) ->
%% it as a comment, potentially replacing user data
Error = lists:flatten(io_lib:format("Aborted: ~tp",
[Reason])),
- Error1 = lists:flatten([string:strip(S,left) ||
- S <- string:tokens(Error,
- [$\n])]),
- Comment = if length(Error1) > 63 ->
- string:substr(Error1,1,60) ++ "...";
+ Error1 = lists:flatten([string:trim(S,leading,"\s") ||
+ S <- string:lexemes(Error,
+ [$\n])]),
+ ErrorLength = string:length(Error1),
+ Comment = if ErrorLength > 63 ->
+ string:slice(Error1,0,60) ++ "...";
true ->
Error1
end,
@@ -774,6 +786,7 @@ spawn_fw_call(Mod,IPTC={init_per_testcase,Func},CurrConf,Pid,
Why,Loc,SendTo) ->
FwCall =
fun() ->
+ ct_util:mark_process(),
Skip = {skip,{failed,{Mod,init_per_testcase,Why}}},
%% if init_per_testcase fails, the test case
%% should be skipped
@@ -804,6 +817,7 @@ spawn_fw_call(Mod,EPTC={end_per_testcase,Func},EndConf,Pid,
Why,_Loc,SendTo) ->
FwCall =
fun() ->
+ ct_util:mark_process(),
{RetVal,Report} =
case proplists:get_value(tc_status, EndConf) of
undefined ->
@@ -853,6 +867,7 @@ spawn_fw_call(Mod,EPTC={end_per_testcase,Func},EndConf,Pid,
spawn_fw_call(FwMod,FwFunc,_,_Pid,{framework_error,FwError},_,SendTo) ->
FwCall =
fun() ->
+ ct_util:mark_process(),
test_server_sup:framework_call(report, [framework_error,
{{FwMod,FwFunc},
FwError}]),
@@ -869,6 +884,7 @@ spawn_fw_call(FwMod,FwFunc,_,_Pid,{framework_error,FwError},_,SendTo) ->
spawn_link(FwCall);
spawn_fw_call(Mod,Func,CurrConf,Pid,Error,Loc,SendTo) ->
+ ct_util:mark_process(),
{Func1,EndTCFunc} = case Func of
CF when CF == init_per_suite; CF == end_per_suite;
CF == init_per_group; CF == end_per_group ->
@@ -907,6 +923,7 @@ start_job_proxy() ->
%% The io_reply_proxy is not the most satisfying solution but it works...
io_reply_proxy(ReplyTo) ->
+ ct_util:mark_process(),
receive
IoReply when is_tuple(IoReply),
element(1, IoReply) == io_reply ->
@@ -916,6 +933,7 @@ io_reply_proxy(ReplyTo) ->
end.
job_proxy_msgloop() ->
+ ct_util:mark_process(),
receive
%%
@@ -1322,13 +1340,12 @@ do_init_per_testcase(Mod, Args) ->
{skip,Reason};
exit:{Skip,Reason} when Skip =:= skip; Skip =:= skipped ->
{skip,Reason};
- throw:Other ->
- set_loc(erlang:get_stacktrace()),
+ throw:Other:Stk ->
+ set_loc(Stk),
Line = get_loc(),
print_init_conf_result(Line,"thrown",Other),
{skip,{failed,{Mod,init_per_testcase,Other}}};
- _:Reason0 ->
- Stk = erlang:get_stacktrace(),
+ _:Reason0:Stk ->
Reason = {Reason0,Stk},
set_loc(Stk),
Line = get_loc(),
@@ -1377,20 +1394,19 @@ do_end_per_testcase(Mod,EndFunc,Func,Conf) ->
_ ->
ok
catch
- throw:Other ->
+ throw:Other:Stk ->
Comment0 = case read_comment() of
"" -> "";
Cmt -> Cmt ++ test_server_ctrl:xhtml("<br>",
"<br />")
end,
- set_loc(erlang:get_stacktrace()),
+ set_loc(Stk),
comment(io_lib:format("~ts<font color=\"red\">"
"WARNING: ~w thrown!"
"</font>\n",[Comment0,EndFunc])),
print_end_tc_warning(EndFunc,Other,"thrown",get_loc()),
{failed,{Mod,end_per_testcase,Other}};
- Class:Reason ->
- Stk = erlang:get_stacktrace(),
+ Class:Reason:Stk ->
set_loc(Stk),
Why = case Class of
exit -> {'EXIT',Reason};
@@ -1532,8 +1548,7 @@ ts_tc(M, F, A) ->
throw:{skipped, Reason} -> {skip, Reason};
exit:{skip, Reason} -> {skip, Reason};
exit:{skipped, Reason} -> {skip, Reason};
- Type:Reason ->
- Stk = erlang:get_stacktrace(),
+ Type:Reason:Stk ->
set_loc(Stk),
case Type of
throw ->
@@ -1722,8 +1737,8 @@ fail(Reason) ->
try
exit({suite_failed,Reason})
catch
- Class:R ->
- case erlang:get_stacktrace() of
+ Class:R:Stacktrace ->
+ case Stacktrace of
[{?MODULE,fail,1,_}|Stk] -> ok;
Stk -> ok
end,
@@ -1745,8 +1760,8 @@ fail() ->
try
exit(suite_failed)
catch
- Class:R ->
- case erlang:get_stacktrace() of
+ Class:R:Stacktrace ->
+ case Stacktrace of
[{?MODULE,fail,0,_}|Stk] -> ok;
Stk -> ok
end,
@@ -1793,6 +1808,7 @@ break(CBM, TestCase, Comment) ->
spawn_break_process(Pid, PName) ->
spawn(fun() ->
register(PName, self()),
+ ct_util:mark_process(),
receive
continue -> continue(Pid);
cancel -> ok
@@ -1990,6 +2006,7 @@ time_ms_apply(Func, TCPid, MultAndScale) ->
user_timetrap_supervisor(Func, Spawner, TCPid, GL, T0, MultAndScale) ->
process_flag(trap_exit, true),
+ ct_util:mark_process(),
Spawner ! {self(),infinity},
MonRef = monitor(process, TCPid),
UserTTSup = self(),
@@ -2023,15 +2040,15 @@ call_user_timetrap(Func, Sup) when is_function(Func) ->
try Func() of
Result ->
Sup ! {self(),Result}
- catch _:Error ->
- exit({Error,erlang:get_stacktrace()})
+ catch _:Error:Stk ->
+ exit({Error,Stk})
end;
call_user_timetrap({M,F,A}, Sup) ->
try apply(M,F,A) of
Result ->
Sup ! {self(),Result}
- catch _:Error ->
- exit({Error,erlang:get_stacktrace()})
+ catch _:Error:Stk ->
+ exit({Error,Stk})
end.
save_user_timetrap(TCPid, UserTTSup, StartTime) ->
@@ -2560,6 +2577,7 @@ run_on_shielded_node(Fun, CArgs) when is_function(Fun), is_list(CArgs) ->
-spec start_job_proxy_fun(_, _) -> fun(() -> no_return()).
start_job_proxy_fun(Master, Fun) ->
fun () ->
+ ct_util:mark_process(),
_ = start_job_proxy(),
receive
Ref ->
@@ -2687,9 +2705,9 @@ is_cover() ->
is_debug() ->
case catch erlang:system_info(debug_compiled) of
{'EXIT', _} ->
- case string:str(erlang:system_info(system_version), "debug") of
- Int when is_integer(Int), Int > 0 -> true;
- _ -> false
+ case string:find(erlang:system_info(system_version), "debug") of
+ nomatch -> false;
+ _ -> true
end;
Res ->
Res
@@ -2725,9 +2743,9 @@ has_superfluous_schedulers() ->
%% We might want to do more tests on a commercial platform, for instance
%% ensuring that all applications have documentation).
is_commercial() ->
- case string:str(erlang:system_info(system_version), "source") of
- Int when is_integer(Int), Int > 0 -> false;
- _ -> true
+ case string:find(erlang:system_info(system_version), "source") of
+ nomatch -> true;
+ _ -> false
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2735,11 +2753,36 @@ is_commercial() ->
%%
%% Returns true if valgrind is running, else false
is_valgrind() ->
- case os:getenv("TS_RUN_VALGRIND") of
- false -> false;
- _ -> true
+ case catch erlang:system_info({valgrind, running}) of
+ {'EXIT', _} -> false;
+ Res -> Res
end.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% DEBUGGER INTERFACE %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% valgrind_new_leaks() -> ok
+%%
+%% Checks for new memory leaks if Valgrind is active.
+valgrind_new_leaks() ->
+ catch erlang:system_info({valgrind, memory}),
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% valgrind_format(Format, Args) -> ok
+%% Format = string()
+%% Args = lists()
+%%
+%% Outputs the formatted string to Valgrind's logfile,if Valgrind is active.
+valgrind_format(Format, Args) ->
+ (catch erlang:system_info({valgrind, io_lib:format(Format, Args)})),
+ ok.
+
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Apply given function and reply to caller or proxy.
diff --git a/lib/common_test/src/test_server_ctrl.erl b/lib/common_test/src/test_server_ctrl.erl
index 9412c43187..8bd6cd583a 100644
--- a/lib/common_test/src/test_server_ctrl.erl
+++ b/lib/common_test/src/test_server_ctrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -89,6 +89,7 @@
-define(logdir_ext, ".logs").
-define(data_dir_suffix, "_data/").
-define(suitelog_name, "suite.log").
+-define(suitelog_latest_name, "suite.log.latest").
-define(coverlog_name, "cover.html").
-define(raw_coverlog_name, "cover.log").
-define(cross_coverlog_name, "cross_cover.html").
@@ -1126,6 +1127,7 @@ init_tester(Mod, Func, Args, Dir, Name, {_,_,MinLev}=Levels,
RejectIoReqs, CreatePrivDir, TCCallback, ExtraTools) ->
process_flag(trap_exit, true),
_ = test_server_io:start_link(),
+ put(app, common_test),
put(test_server_name, Name),
put(test_server_dir, Dir),
put(test_server_total_time, 0),
@@ -1150,6 +1152,12 @@ init_tester(Mod, Func, Args, Dir, Name, {_,_,MinLev}=Levels,
end,
%% before first print, read and set logging options
+ FWLogDir =
+ case test_server_sup:framework_call(get_log_dir, [], []) of
+ {ok,FwDir} -> FwDir;
+ _ -> filename:dirname(Dir)
+ end,
+ put(test_server_framework_logdir, FWLogDir),
LogOpts = test_server_sup:framework_call(get_logopts, [], []),
put(test_server_logopts, LogOpts),
@@ -1464,13 +1472,14 @@ get_suites([], Mods) ->
lists:reverse(Mods).
add_mod(Mod, Mods) ->
- case string:rstr(atom_to_list(Mod), "_SUITE") of
- 0 -> false;
- _ -> % test suite
+ case lists:reverse(atom_to_list(Mod)) of
+ "ETIUS_" ++ _ -> % test suite
case lists:member(Mod, Mods) of
true -> false;
false -> true
- end
+ end;
+ _ ->
+ false
end.
@@ -1711,6 +1720,12 @@ start_log_file() ->
test_server_io:set_fd(html, Html),
test_server_io:set_fd(unexpected_io, Unexpected),
+ %% we must assume the redirection file (to the latest suite index) can
+ %% be stored on the level above the log directory of the current test
+ TopDir = filename:dirname(get(test_server_framework_logdir)),
+ RedirectLink = filename:join(TopDir, ?suitelog_latest_name ++ ?html_ext),
+ make_html_link(RedirectLink, HtmlName, redirect),
+
make_html_link(filename:absname(?last_test ++ ?html_ext),
HtmlName, filename:basename(Dir)),
LinkName = filename:join(Dir, ?last_link),
@@ -1739,11 +1754,18 @@ make_html_link(LinkName, Target, Explanation) ->
false ->
"file:" ++ uri_encode(Target)
end,
- H = [html_header(Explanation),
- "<h1>Last test</h1>\n"
- "<a href=\"",Href,"\">",Explanation,"</a>\n"
- "</body>\n</html>\n"],
+ H = if Explanation == redirect ->
+ Meta = ["<meta http-equiv=\"refresh\" "
+ "content=\"0; url=", Href, "\" />\n"],
+ [html_header("redirect", Meta), "</html>\n"];
+ true ->
+ [html_header(Explanation),
+ "<h1>Last test</h1>\n"
+ "<a href=\"",Href,"\">",Explanation,"</a>\n"
+ "</body>\n</html>\n"]
+ end,
ok = write_html_file(LinkName, H).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% start_minor_log_file(Mod, Func, ParallelTC) -> AbsName
@@ -2163,6 +2185,7 @@ do_add_end_per_suite_and_skip(LastMod, LastRef, Mod, FwMod) ->
%% Runs the specified tests, then displays/logs the summary.
run_test_cases(TestSpec, Config, TimetrapData) ->
+ test_server:init_valgrind(),
case lists:member(no_src, get(test_server_logopts)) of
true ->
ok;
@@ -2278,7 +2301,7 @@ run_test_cases(TestSpec, Config, TimetrapData) ->
%% test_server_io:print_buffered/1 to print the data. To help with this,
%% two variables in the process dictionary are used:
%% 'test_server_common_io_handler' and 'test_server_queued_io'. The values
-%% are set to as follwing:
+%% are set to as following:
%%
%% Value Meaning
%% ----- -------
@@ -2610,7 +2633,7 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0,
NumStr ->
%% Ex: "123 456 789" or "123,456,789" -> {123,456,789}
list_to_tuple([list_to_integer(NS) ||
- NS <- string:tokens(NumStr, [$ ,$:,$,])])
+ NS <- string:lexemes(NumStr, [$ ,$:,$,])])
end,
{shuffle_cases(Ref, Cs0, UseSeed),{shuffle,UseSeed}}
end;
@@ -3703,6 +3726,7 @@ run_test_case(Ref, Num, Mod, Func, Args, RunInit, TimetrapData, Mode) ->
spawn_link(
fun() ->
process_flag(trap_exit, true),
+ ct_util:mark_process(),
_ = [put(Key, Val) || {Key,Val} <- Dictionary],
set_io_buffering({tc,Main}),
run_test_case1(Ref, Num, Mod, Func, Args, RunInit,
@@ -3796,7 +3820,7 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit,
%% run the test case
{Result,DetectedFail,ProcsBefore,ProcsAfter} =
- run_test_case_apply(Mod, Func, [UpdatedArgs], GrName,
+ run_test_case_apply(Num, Mod, Func, [UpdatedArgs], GrName,
RunInit, TimetrapData),
{Time,RetVal,Loc,Opts,Comment} =
case Result of
@@ -3978,11 +4002,12 @@ progress(skip, CaseNum, Mod, Func, GrName, Loc, Reason, Time,
true -> "~w"
end, [Time]),
ReasonStr = escape_chars(reason_to_string(Reason1)),
- ReasonStr1 = lists:flatten([string:strip(S,left) ||
- S <- string:tokens(ReasonStr,[$\n])]),
+ ReasonStr1 = lists:flatten([string:trim(S,leading,"\s") ||
+ S <- string:lexemes(ReasonStr,[$\n])]),
+ ReasonLength = string:length(ReasonStr1),
ReasonStr2 =
- if length(ReasonStr1) > 80 ->
- string:substr(ReasonStr1, 1, 77) ++ "...";
+ if ReasonLength > 80 ->
+ string:slice(ReasonStr1, 0, 77) ++ "...";
true ->
ReasonStr1
end,
@@ -4066,11 +4091,12 @@ progress(failed, CaseNum, Mod, Func, GrName, unknown, Reason, Time,
true -> "~w"
end, [Time]),
ErrorReason = escape_chars(lists:flatten(io_lib:format("~tp", [Reason]))),
- ErrorReason1 = lists:flatten([string:strip(S,left) ||
- S <- string:tokens(ErrorReason,[$\n])]),
+ ErrorReason1 = lists:flatten([string:trim(S,leading,"\s") ||
+ S <- string:lexemes(ErrorReason,[$\n])]),
+ ErrorReasonLength = string:length(ErrorReason1),
ErrorReason2 =
- if length(ErrorReason1) > 63 ->
- string:substr(ErrorReason1, 1, 60) ++ "...";
+ if ErrorReasonLength > 63 ->
+ string:slice(ErrorReason1, 0, 60) ++ "...";
true ->
ErrorReason1
end,
@@ -4356,7 +4382,7 @@ do_format_exception(Reason={Error,Stack}) ->
PF = fun(Term, I) ->
io_lib:format("~." ++ integer_to_list(I) ++ "tp", [Term])
end,
- case catch lib:format_exception(1, error, Error, Stack, StackFun, PF, utf8) of
+ case catch erl_error:format_exception(1, error, Error, Stack, StackFun, PF, utf8) of
{'EXIT',_R} ->
{"~tp",Reason};
Formatted ->
@@ -4366,7 +4392,7 @@ do_format_exception(Reason={Error,Stack}) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% run_test_case_apply(Mod, Func, Args, Name, RunInit,
+%% run_test_case_apply(CaseNum, Mod, Func, Args, Name, RunInit,
%% TimetrapData) ->
%% {{Time,RetVal,Loc,Opts,Comment},DetectedFail,ProcessesBefore,ProcessesAfter} |
%% {{died,Reason,unknown,Comment},DetectedFail,ProcessesBefore,ProcessesAfter}
@@ -4380,9 +4406,9 @@ do_format_exception(Reason={Error,Stack}) ->
%% ProcessesBefore = ProcessesAfter = integer()
%%
-run_test_case_apply(Mod, Func, Args, Name, RunInit,
+run_test_case_apply(CaseNum, Mod, Func, Args, Name, RunInit,
TimetrapData) ->
- test_server:run_test_case_apply({Mod,Func,Args,Name,RunInit,
+ test_server:run_test_case_apply({CaseNum,Mod,Func,Args,Name,RunInit,
TimetrapData}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -5141,7 +5167,7 @@ display_info([Pid|T], R, M) ->
Other
end,
Reds = fetch(reductions, Info),
- LM = length(fetch(messages, Info)),
+ LM = fetch(message_queue_len, Info),
pformat(io_lib:format("~w", [Pid]),
io_lib:format("~tw", [Call]),
io_lib:format("~tw", [Curr]), Reds, LM),
@@ -5654,6 +5680,13 @@ html_header(Title) ->
"<body bgcolor=\"white\" text=\"black\" "
"link=\"blue\" vlink=\"purple\" alink=\"red\">\n"].
+html_header(Title, Meta) ->
+ ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n"
+ "<!-- autogenerated by '", atom_to_list(?MODULE), "'. -->\n"
+ "<html>\n"
+ "<head>\n"
+ "<title>", Title, "</title>\n"] ++ Meta ++ ["</head>\n"].
+
open_html_file(File) ->
open_utf8_file(File).
@@ -5706,7 +5739,7 @@ uri_encode_comp([Char|Chars],Encoding) ->
Reserved = sets:is_element(Char, reserved()),
case (Char>127 andalso Encoding==latin1) orelse Reserved of
true ->
- [ $% | http_util:integer_to_hexlist(Char)] ++
+ [ $% | integer_to_list(Char, 16)] ++
uri_encode_comp(Chars,Encoding);
false ->
[Char | uri_encode_comp(Chars,Encoding)]
diff --git a/lib/common_test/src/test_server_gl.erl b/lib/common_test/src/test_server_gl.erl
index ce7682d101..24dd5cd54c 100644
--- a/lib/common_test/src/test_server_gl.erl
+++ b/lib/common_test/src/test_server_gl.erl
@@ -132,6 +132,7 @@ set_props(GL, PropList) ->
%%% Internal functions.
init([TSIO]) ->
+ ct_util:mark_process(group_leader),
EscChars = case application:get_env(test_server, esc_chars) of
{ok,ECBool} -> ECBool;
_ -> true
diff --git a/lib/common_test/src/test_server_io.erl b/lib/common_test/src/test_server_io.erl
index 062e3bd8ff..ef31521950 100644
--- a/lib/common_test/src/test_server_io.erl
+++ b/lib/common_test/src/test_server_io.erl
@@ -184,6 +184,7 @@ reset_state() ->
init([]) ->
process_flag(trap_exit, true),
+ ct_util:mark_process(),
Empty = gb_trees:empty(),
{ok,Shared} = test_server_gl:start_link(self()),
{ok,#st{fds=Empty,shared_gl=Shared,gls=gb_sets:empty(),
@@ -262,7 +263,7 @@ handle_call(reset_state, From, #st{phase=stopping,pending_ops=Ops}=St) ->
{Result,NewSt1}
end,
{noreply,St#st{pending_ops=[{From,Op}|Ops]}};
-handle_call(reset_state, _From, #st{fds=Fds,tags=Tags,gls=Gls,
+handle_call(reset_state, _From, #st{fds=Fds,tags=Tags,shared_gl=Shared0,gls=Gls,
offline_buffer=OfflineBuff}) ->
%% close open log files
lists:foreach(fun(Tag) ->
@@ -273,6 +274,7 @@ handle_call(reset_state, _From, #st{fds=Fds,tags=Tags,gls=Gls,
file:close(Fd)
end
end, Tags),
+ test_server_gl:stop(Shared0),
GlList = gb_sets:to_list(Gls),
_ = [test_server_gl:stop(GL) || GL <- GlList],
timer:sleep(100),
@@ -320,7 +322,7 @@ handle_call(finish, From, St) ->
handle_info({'EXIT',Pid,normal}, #st{gls=Gls0,stopping=From}=St) ->
Gls = gb_sets:delete_any(Pid, Gls0),
- case gb_sets:is_empty(Gls) andalso stopping =/= undefined of
+ case gb_sets:is_empty(Gls) andalso From =/= undefined of
true ->
%% No more group leaders left.
gen_server:reply(From, ok),
@@ -329,6 +331,9 @@ handle_info({'EXIT',Pid,normal}, #st{gls=Gls0,stopping=From}=St) ->
%% Wait for more group leaders to finish.
{noreply,St#st{gls=Gls,phase=stopping}}
end;
+handle_info({'EXIT',Pid,killed}, #st{gls=Gls0}=St) ->
+ %% forced termination of group leader
+ {noreply,St#st{gls=gb_sets:delete_any(Pid, Gls0)}};
handle_info({'EXIT',_Pid,Reason}, _St) ->
exit(Reason);
handle_info(stop_group_leaders, #st{gls=Gls}=St) ->
diff --git a/lib/common_test/src/test_server_node.erl b/lib/common_test/src/test_server_node.erl
index a18ff1fd62..ea7ad8538e 100644
--- a/lib/common_test/src/test_server_node.erl
+++ b/lib/common_test/src/test_server_node.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -315,9 +315,11 @@ start_node_peer(SlaveName, OptList, From, TI) ->
Prog0 = start_node_get_option_value(erl, OptList, default),
Prog = quote_progname(pick_erl_program(Prog0)),
Args =
- case string:str(SuppliedArgs,"-setcookie") of
- 0 -> "-setcookie " ++ TI#target_info.cookie ++ " " ++ SuppliedArgs;
- _ -> SuppliedArgs
+ case string:find(SuppliedArgs,"-setcookie") of
+ nomatch ->
+ "-setcookie " ++ TI#target_info.cookie ++ " " ++ SuppliedArgs;
+ _ ->
+ SuppliedArgs
end,
Cmd = lists:concat([Prog,
" -detached ",
@@ -589,7 +591,7 @@ cast_to_list(X) -> lists:flatten(io_lib:format("~tw", [X])).
%%% this
%%%
pick_erl_program(default) ->
- cast_to_list(lib:progname());
+ ct:get_progname();
pick_erl_program(L) ->
P = random_element(L),
case P of
@@ -598,7 +600,7 @@ pick_erl_program(L) ->
{release, S} ->
find_release(S);
this ->
- cast_to_list(lib:progname())
+ ct:get_progname()
end.
%% This is an attempt to distinguish between spaces in the program
@@ -609,10 +611,10 @@ pick_erl_program(L) ->
%% ({prog,String}) or if the -program switch to beam is used and
%% includes arguments (typically done by cerl in OTP test environment
%% in order to ensure that slave/peer nodes are started with the same
-%% emulator and flags as the test node. The return from lib:progname()
-%% could then typically be '/<full_path_to>/cerl -gcov').
+%% emulator and flags as the test node. The return from ct:get_progname()
+%% could then typically be "/<full_path_to>/cerl -gcov").
quote_progname(Progname) ->
- do_quote_progname(string:tokens(Progname," ")).
+ do_quote_progname(string:lexemes(Progname," ")).
do_quote_progname([Prog]) ->
"\""++Prog++"\"";
@@ -692,7 +694,7 @@ find_rel_suse_2(Rel, RootWc) ->
case file:list_dir(RelDir) of
{ok,Dirs} ->
case lists:filter(fun(Dir) ->
- case re:run(Dir, Pat) of
+ case re:run(Dir, Pat, [unicode]) of
nomatch -> false;
_ -> true
end
@@ -747,6 +749,7 @@ unpack(Bin) ->
id(I) -> I.
print_data(Port) ->
+ ct_util:mark_process(),
receive
{Port, {data, Bytes}} ->
io:put_chars(Bytes),
diff --git a/lib/common_test/src/test_server_sup.erl b/lib/common_test/src/test_server_sup.erl
index 9a26de4774..26e7534c6c 100644
--- a/lib/common_test/src/test_server_sup.erl
+++ b/lib/common_test/src/test_server_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -56,6 +56,7 @@ timetrap(Timeout0, Scale, Pid) ->
timetrap(Timeout0, ReportTVal, Scale, Pid) ->
process_flag(priority, max),
+ ct_util:mark_process(),
Timeout = if not Scale -> Timeout0;
true -> test_server:timetrap_scale_factor() * Timeout0
end,
@@ -346,7 +347,7 @@ check_appup_clauses_plausible([], _Direction, _Modules) ->
ok;
check_appup_clauses_plausible([{Re, Instrs} | Rest], Direction, Modules)
when is_binary(Re) ->
- case re:compile(Re) of
+ case re:compile(Re,[unicode]) of
{ok, _} ->
case check_appup_instructions(Instrs, Direction, Modules) of
ok ->
@@ -773,14 +774,15 @@ framework_call(Callback,Func,Args,DefaultReturn) ->
false ->
ok
end,
+ ct_util:mark_process(),
try apply(Mod,Func,Args) of
Result ->
Result
catch
exit:Why ->
EH(Why);
- error:Why ->
- EH({Why,erlang:get_stacktrace()});
+ error:Why:Stacktrace ->
+ EH({Why,Stacktrace});
throw:Why ->
EH(Why)
end;
@@ -850,6 +852,7 @@ util_start() ->
undefined ->
spawn_link(fun() ->
register(?MODULE, self()),
+ put(app, common_test),
util_loop(#util_state{starter=Starter})
end),
ok;
diff --git a/lib/common_test/src/unix_telnet.erl b/lib/common_test/src/unix_telnet.erl
index 8ac467014c..7a210237a8 100644
--- a/lib/common_test/src/unix_telnet.erl
+++ b/lib/common_test/src/unix_telnet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,39 +18,6 @@
%% %CopyrightEnd%
%%
-%%% @doc Callback module for ct_telnet, for connecting to a telnet
-%%% server on a unix host.
-%%%
-%%% <p>It requires the following entry in the config file:</p>
-%%% <pre>
-%%% {unix,[{telnet,HostNameOrIpAddress},
-%%% {port,PortNum}, % optional
-%%% {username,UserName},
-%%% {password,Password},
-%%% {keep_alive,Bool}, % optional
-%%% {tcp_nodely,Bool}]} % optional</pre>
-%%%
-%%% <p>To communicate via telnet to the host specified by
-%%% <code>HostNameOrIpAddress</code>, use the interface functions in
-%%% <code>ct_telnet</code>, e.g. <code>open(Name), cmd(Name,Cmd), ...</code>.</p>
-%%%
-%%% <p><code>Name</code> is the name you allocated to the unix host in
-%%% your <code>require</code> statement. E.g.</p>
-%%% <pre> suite() -> [{require,Name,{unix,[telnet]}}].</pre>
-%%% <p>or</p>
-%%% <pre> ct:require(Name,{unix,[telnet]}).</pre>
-%%%
-%%% <p>The "keep alive" activity (i.e. that Common Test sends NOP to the server
-%%% every 10 seconds if the connection is idle) may be enabled or disabled for one
-%%% particular connection as described here. It may be disabled for all connections
-%%% using <c>telnet_settings</c> (see <c>ct_telnet</c>).</p>
-%%%
-%%% <p>Note that the <code>{port,PortNum}</code> tuple is optional and if
-%%% omitted, default telnet port 23 will be used. Also the <c>keep_alive</c> tuple
-%%% is optional, and the value defauls to true (enabled).</p>
-%%%
-%%% @see ct
-%%% @see ct_telnet
-module(unix_telnet).
%% Callbacks for ct_telnet.erl
@@ -61,36 +28,9 @@
-define(password,"Password: ").
-define(prx,"login: |Password: |\\\$ |> ").
-%%%-----------------------------------------------------------------
-%%% @spec get_prompt_regexp() -> PromptRegexp
-%%% PromptRegexp = ct_telnet:prompt_regexp()
-%%%
-%%% @doc Callback for ct_telnet.erl.
-%%%
-%%% <p>Return a suitable regexp string that will match common
-%%% prompts for users on unix hosts.</p>
get_prompt_regexp() ->
?prx.
-
-%%%-----------------------------------------------------------------
-%%% @spec connect(ConnName,Ip,Port,Timeout,KeepAlive,Extra) ->
-%%% {ok,Handle} | {error,Reason}
-%%% ConnName = ct:target_name()
-%%% Ip = string() | {integer(),integer(),integer(),integer()}
-%%% Port = integer()
-%%% Timeout = integer()
-%%% KeepAlive = bool()
-%%% TCPNoDelay = bool()
-%%% Extra = ct:target_name() | {Username,Password}
-%%% Username = string()
-%%% Password = string()
-%%% Handle = ct_telnet:handle()
-%%% Reason = term()
-%%%
-%%% @doc Callback for ct_telnet.erl.
-%%%
-%%% <p>Setup telnet connection to a unix host.</p>
connect(ConnName,Ip,Port,Timeout,KeepAlive,TCPNoDelay,Extra) ->
case Extra of
{Username,Password} ->
@@ -121,7 +61,8 @@ connect1(Name,Ip,Port,Timeout,KeepAlive,TCPNoDelay,Username,Password) ->
prompt,?prx,[]) of
{ok,{prompt,?password},_} ->
ok = ct_telnet_client:send_data(Pid,Password),
- Stars = lists:duplicate(length(Password),$*),
+ Stars =
+ lists:duplicate(string:length(Password),$*),
log(Name,send,"Password: ~s",[Stars]),
% ok = ct_telnet_client:send_data(Pid,""),
case ct_telnet:silent_teln_expect(Name,Pid,[],
diff --git a/lib/common_test/src/vts.erl b/lib/common_test/src/vts.erl
index 99a109cfe8..38e549d2d6 100644
--- a/lib/common_test/src/vts.erl
+++ b/lib/common_test/src/vts.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -157,6 +157,7 @@ test_info(_VtsPid,Type,Data) ->
init(Parent) ->
register(?MODULE,self()),
process_flag(trap_exit,true),
+ ct_util:mark_process(),
Parent ! {self(),started},
{ok,Cwd} = file:get_cwd(),
InitState = #state{start_dir=Cwd},
@@ -284,6 +285,7 @@ run_test1(State=#state{tests=Tests,current_log_dir=LogDir,
logopts=LogOpts}) ->
Self=self(),
RunTest = fun() ->
+ ct_util:mark_process(),
case ct_run:do_run(Tests,[],LogDir,LogOpts) of
{error,_Reason} ->
aborted();
@@ -917,7 +919,7 @@ get_input_data(Input,Key)->
end.
parse(Input) ->
- httpd:parse_query(Input).
+ uri_string:dissect_query(Input).
vts_integer_to_list(X) when is_atom(X) ->
atom_to_list(X);
diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile
index 0d9149f489..ecd1f727a2 100644
--- a/lib/common_test/test/Makefile
+++ b/lib/common_test/test/Makefile
@@ -73,7 +73,8 @@ MODULES= \
ct_log_SUITE \
ct_SUITE \
ct_keep_logs_SUITE \
- ct_unicode_SUITE
+ ct_unicode_SUITE \
+ ct_auto_clean_SUITE
ERL_FILES= $(MODULES:%=%.erl)
HRL_FILES= test_server_test_lib.hrl
diff --git a/lib/common_test/test/ct_auto_clean_SUITE.erl b/lib/common_test/test/ct_auto_clean_SUITE.erl
new file mode 100644
index 0000000000..a89c90eb79
--- /dev/null
+++ b/lib/common_test/test/ct_auto_clean_SUITE.erl
@@ -0,0 +1,262 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(ct_auto_clean_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-define(eh, ct_test_support_eh).
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) -> Config1 | {skip,Reason}
+%%
+%% Config0 = Config1 = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Reason = term()
+%% The reason for skipping the suite.
+%%
+%% Description: Since Common Test starts another Test Server
+%% instance, the tests need to be performed on a separate node (or
+%% there will be clashes with logging processes etc).
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ DataDir = ?config(data_dir, Config),
+ CTHs = filelib:wildcard(filename:join(DataDir,"cth_*.erl")),
+ ct:pal("CTHs: ~p",[CTHs]),
+ [ct:pal("Compiling ~p: ~p",
+ [FileName,compile:file(FileName,[{outdir,DataDir},debug_info])]) ||
+ FileName <- CTHs],
+ ct_test_support:init_per_suite([{path_dirs,[DataDir]} | Config]).
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config) -> void()
+%%
+%% Config = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Cleanup after the suite.
+%%--------------------------------------------------------------------
+end_per_suite(Config) ->
+ ct_test_support:end_per_suite(Config).
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) -> Config1 |
+%% {skip,Reason}
+%% TestCase = atom()
+%% Name of the test case that is about to run.
+%% Config0 = Config1 = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Reason = term()
+%% The reason for skipping the test case.
+%%
+%% Description: Initialization before each test case.
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%%--------------------------------------------------------------------
+init_per_testcase(TestCase, Config) ->
+ ct_test_support:init_per_testcase(TestCase, Config).
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config) -> void()
+%%
+%% TestCase = atom()
+%% Name of the test case that is finished.
+%% Config = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Cleanup after each test case.
+%%--------------------------------------------------------------------
+end_per_testcase(TestCase, Config) ->
+ ct_test_support:end_per_testcase(TestCase, Config).
+
+%%--------------------------------------------------------------------
+%% Function: all(Clause) -> Descr | TestCases | {skip,Reason}
+%%
+%% Clause = doc | suite
+%% Indicates expected return value.
+%% Descr = [string()] | []
+%% String that describes the test suite.
+%% TestCases = [TestCase]
+%% TestCase = atom()
+%% Name of a test case.
+%% Reason = term()
+%% The reason for skipping the test suite.
+%%
+%% Description: Returns a description of the test suite (doc) and a
+%% list of all test cases in the suite (suite).
+%%--------------------------------------------------------------------
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [clean].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Arg) -> Descr | Spec | ok | exit() | {skip,Reason}
+%%
+%% Arg = doc | suite | Config
+%% Indicates expected behaviour and return value.
+%% Config = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Descr = [string()] | []
+%% String that describes the test case.
+%% Spec = [tuple()] | []
+%% A test specification.
+%% Reason = term()
+%% The reason for skipping the test case.
+%%
+%% Description: Test case function. Returns a description of the test
+%% case (doc), then returns a test specification (suite),
+%% or performs the actual test (Config).
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+
+clean(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ ACSuite = filename:join(DataDir, "ac_SUITE"),
+ Opts0 = ct_test_support:get_opts(Config),
+ Opts = eh_opts(Config) ++ Opts0 ++ [{suite,ACSuite},
+ {ct_hooks,[cth_auto_clean]}],
+
+ ERPid = ct_test_support:start_event_receiver(Config),
+
+ ok = ct_test_support:run(Opts, Config),
+
+ Events = ct_test_support:get_events(ERPid, Config),
+ ct_test_support:log_events(?FUNCTION_NAME,
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+ TestEvents = events_to_check(?FUNCTION_NAME),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+
+eh_opts(Config) ->
+ Level = ?config(trace_level, Config),
+ [{event_handler,{?eh,[{cbm,ct_test_support},{trace_level,Level}]}}].
+
+events_to_check(Test) ->
+ %% 2 tests (ct:run_test + script_start) is default
+ events_to_check(Test, 2).
+
+events_to_check(_, 0) ->
+ [];
+events_to_check(Test, N) ->
+ events(Test) ++ events_to_check(Test, N-1).
+
+events(clean) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,9}},
+
+ {?eh,tc_start,{ac_SUITE,init_per_suite}},
+ {?eh,tc_done,{ac_SUITE,init_per_suite,ok}},
+
+ {?eh,tc_start,{ac_SUITE,tc1}},
+ {?eh,tc_done,{ac_SUITE,tc1,ok}},
+
+ {?eh,test_stats,{1,0,{0,0}}},
+
+ {?eh,tc_start,{ac_SUITE,tc2}},
+ {?eh,tc_done,{ac_SUITE,tc2,ok}},
+
+ {?eh,test_stats,{2,0,{0,0}}},
+
+ [{?eh,tc_start,{ac_SUITE,{init_per_group,s1,[]}}},
+ {?eh,tc_done,{ac_SUITE,{init_per_group,s1,[]},ok}},
+
+ {?eh,tc_start,{ac_SUITE,stc1}},
+ {?eh,tc_done,{ac_SUITE,stc1,ok}},
+
+ {?eh,test_stats,{3,0,{0,0}}},
+
+ {?eh,tc_start,{ac_SUITE,stc2}},
+ {?eh,tc_done,{ac_SUITE,stc2,ok}},
+
+ {?eh,test_stats,{4,0,{0,0}}},
+
+ {?eh,tc_start,{ac_SUITE,{end_per_group,s1,[]}}},
+ {?eh,tc_done,{ac_SUITE,{end_per_group,s1,[]},ok}}],
+
+ {parallel,
+ [{?eh,tc_start,{ac_SUITE,{init_per_group,p1,[parallel]}}},
+ {?eh,tc_done,{ac_SUITE,{init_per_group,p1,[parallel]},ok}},
+
+ {?eh,tc_start,{ac_SUITE,ptc1}},
+ {?eh,tc_start,{ac_SUITE,ptc2}},
+ {?eh,tc_done,{ac_SUITE,ptc1,ok}},
+ {?eh,test_stats,{5,0,{0,0}}},
+ {?eh,tc_done,{ac_SUITE,ptc2,ok}},
+ {?eh,test_stats,{6,0,{0,0}}},
+
+ {?eh,tc_start,{ac_SUITE,{end_per_group,p1,[parallel]}}},
+ {?eh,tc_done,{ac_SUITE,{end_per_group,p1,[parallel]},ok}}]},
+
+ [{?eh,tc_start,{ac_SUITE,{init_per_group,s2,[]}}},
+ {?eh,tc_done,{ac_SUITE,{init_per_group,s2,[]},ok}},
+
+ {?eh,tc_start,{ac_SUITE,stc1}},
+ {?eh,tc_done,{ac_SUITE,stc1,ok}},
+
+ {?eh,test_stats,{7,0,{0,0}}},
+
+ {?eh,tc_start,{ac_SUITE,stc2}},
+ {?eh,tc_done,{ac_SUITE,stc2,ok}},
+
+ {?eh,test_stats,{8,0,{0,0}}},
+
+ {?eh,tc_start,{ac_SUITE,{end_per_group,s2,[]}}},
+ {?eh,tc_done,{ac_SUITE,{end_per_group,s2,[]},ok}}],
+
+ {?eh,tc_start,{ac_SUITE,tc1}},
+ {?eh,tc_done,{ac_SUITE,tc1,ok}},
+
+ {?eh,test_stats,{9,0,{0,0}}},
+
+ {?eh,tc_start,{ac_SUITE,end_per_suite}},
+ {?eh,tc_done,{ac_SUITE,end_per_suite,ok}},
+
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ].
diff --git a/lib/common_test/test/ct_auto_clean_SUITE_data/ac_SUITE.erl b/lib/common_test/test/ct_auto_clean_SUITE_data/ac_SUITE.erl
new file mode 100644
index 0000000000..e779f70693
--- /dev/null
+++ b/lib/common_test/test/ct_auto_clean_SUITE_data/ac_SUITE.erl
@@ -0,0 +1,181 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(ac_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% @spec suite() -> Info
+%% Info = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% @spec init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ start_processes(),
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_suite(Config0) -> term() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ start_processes(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ start_processes(),
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_group(GroupName, Config0) ->
+%% term() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ start_processes(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ start_processes(),
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_testcase(TestCase, Config0) ->
+%% term() | {save_config,Config1} | {fail,Reason}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ start_processes(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%% @end
+%%--------------------------------------------------------------------
+groups() ->
+ [{s1,[],[stc1,stc2]},
+ {p1,[parallel],[ptc1,ptc2]},
+ {s2,[],[stc1,stc2]}].
+
+%%! What about nested groups??
+
+%%--------------------------------------------------------------------
+%% @spec all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+all() ->
+ [
+ [tc1,tc2],
+ {group,s1},
+ {group,p1},
+ {group,s2},
+ tc1
+ ].
+
+tc1(_Config) ->
+ start_processes(),
+ ok.
+
+tc2(_Config) ->
+ start_processes(),
+ ok.
+
+stc1(_Config) ->
+ start_processes(),
+ ok.
+
+stc2(_Config) ->
+ start_processes(),
+ ok.
+
+ptc1(_Config) ->
+ start_processes(),
+ ok.
+
+ptc2(_Config) ->
+ start_processes(),
+ ok.
+
+
+%%%-----------------------------------------------------------------
+%%%
+
+start_processes() ->
+ Init = fun() ->
+ process_flag(trap_exit, true),
+ do_spawn(fun() -> receive _ -> ok end end),
+ receive _ ->
+ ok
+ end
+ end,
+ do_spawn(Init).
+
+do_spawn(Fun) ->
+ Pid = spawn(Fun),
+ ct:log("Process ~w started with group leader ~w",
+ [Pid,element(2, process_info(Pid, group_leader))]),
+ Pid.
diff --git a/lib/common_test/test/ct_auto_clean_SUITE_data/cth_auto_clean.erl b/lib/common_test/test/ct_auto_clean_SUITE_data/cth_auto_clean.erl
new file mode 100644
index 0000000000..3f8d3957cc
--- /dev/null
+++ b/lib/common_test/test/ct_auto_clean_SUITE_data/cth_auto_clean.erl
@@ -0,0 +1,214 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(cth_auto_clean).
+
+%% CTH Callbacks
+-export([id/1, init/2,
+ pre_init_per_suite/3, post_init_per_suite/4,
+ pre_end_per_suite/3, post_end_per_suite/4,
+ pre_init_per_group/4, post_init_per_group/5,
+ pre_end_per_group/4, post_end_per_group/5,
+ pre_init_per_testcase/4, post_init_per_testcase/5,
+ pre_end_per_testcase/4, post_end_per_testcase/5]).
+
+id(_Opts) ->
+ ?MODULE.
+
+init(?MODULE, _Opts) ->
+ ok.
+
+pre_init_per_suite(_Suite, Config, State) ->
+ identify(?FUNCTION_NAME),
+ SharedGL = test_server_io:get_gl(true),
+ SharedGL = find_and_kill(),
+ do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}),
+ %% get status of processes at startup, to be compared with end result
+ {Config, [{all_procs,processes()} | State]}.
+
+post_init_per_suite(_Suite, _Config, Return, State) ->
+ identify(?FUNCTION_NAME),
+ SharedGL = find_and_kill(),
+ do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}),
+ {Return, State}.
+
+pre_end_per_suite(_Suite, Config, State) ->
+ identify(?FUNCTION_NAME),
+ SharedGL = find_and_kill(),
+ do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}),
+ {Config, State}.
+
+post_end_per_suite(_Suite, _Config, Return, State) ->
+ identify(?FUNCTION_NAME),
+ SharedGL = find_and_kill(),
+ do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}),
+ AllProcs = processes(),
+ Remaining = AllProcs--proplists:get_value(all_procs, State),
+ ct:pal("Final remaining processes = ~p", [Remaining]),
+ %% only the end_per_suite process shoud remain at this point!
+ Remaining = [self()],
+ {Return, State}.
+
+pre_init_per_group(_Suite, _Group, Config, State) ->
+ identify(?FUNCTION_NAME),
+ SharedGL = find_and_kill(procs_and_gls),
+ do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}),
+ {Config, State}.
+
+post_init_per_group(_Suite, _Group, _Config, Result, State) ->
+ identify(?FUNCTION_NAME),
+ SharedGL = find_and_kill(procs_and_gls),
+ do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}),
+ {Result, State}.
+
+pre_init_per_testcase(_Suite, _TC, Config, State) ->
+ identify(?FUNCTION_NAME),
+ ThisGL = group_leader(),
+ find_and_kill(proc, ThisGL),
+ case proplists:get_value(tc_group_properties, Config) of
+ [{name,_},parallel] ->
+ timer:sleep(1000);
+ _ ->
+ do_until(fun() -> element(1,ct:remaining_test_procs()) end, [])
+ end,
+ {Config, State}.
+
+post_init_per_testcase(_Suite, _TC, Config, Return, State) ->
+ identify(?FUNCTION_NAME),
+ ThisGL = group_leader(),
+ find_and_kill(proc, ThisGL),
+ case proplists:get_value(tc_group_properties, Config) of
+ [{name,_},parallel] ->
+ timer:sleep(1000);
+ _ ->
+ do_until(fun() -> element(1,ct:remaining_test_procs()) end, [])
+ end,
+ {Return, State}.
+
+pre_end_per_testcase(_Suite, _TC, Config, State) ->
+ identify(?FUNCTION_NAME),
+ ThisGL = group_leader(),
+ find_and_kill(proc, ThisGL),
+ case proplists:get_value(tc_group_properties, Config) of
+ [{name,_},parallel] ->
+ timer:sleep(1000);
+ _ ->
+ do_until(fun() -> element(1,ct:remaining_test_procs()) end, [])
+ end,
+ {Config, State}.
+
+post_end_per_testcase(_Suite, _TC, Config, Result, State) ->
+ identify(?FUNCTION_NAME),
+ ThisGL = group_leader(),
+ find_and_kill(proc, ThisGL),
+ case proplists:get_value(tc_group_properties, Config) of
+ [{name,_},parallel] ->
+ timer:sleep(1000);
+ _ ->
+ do_until(fun() -> element(1,ct:remaining_test_procs()) end, [])
+ end,
+ {Result, State}.
+
+pre_end_per_group(_Suite, _Group, Config, State) ->
+ identify(?FUNCTION_NAME),
+ SharedGL = find_and_kill(procs_and_gls),
+ do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}),
+ {Config, State}.
+
+post_end_per_group(_Suite, _Group, _Config, Return, State) ->
+ identify(?FUNCTION_NAME),
+ SharedGL = find_and_kill(procs_and_gls),
+ do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}),
+ {Return, State}.
+
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+
+identify(Func) ->
+ ct:pal("********** THIS IS ~w on ~w", [Func, self()]),
+ ok.
+
+find_and_kill() ->
+ find_and_kill(procs).
+
+find_and_kill(procs) ->
+ {Procs,SharedGL,_ParallelGLs} = ct:remaining_test_procs(),
+ ct:pal("Remaining test processes = ~p", [pi(Procs)]),
+ [pkill(P, kill) || {P,_GL} <- Procs],
+ SharedGL;
+
+find_and_kill(procs_and_gls) ->
+ {Procs,SharedGL,GLs} = ct:remaining_test_procs(),
+ ct:pal("Remaining test processes = ~p", [pi(Procs)]),
+ [pkill(P, kill) || {P,_GL} <- Procs],
+ ct:pal("Remaining group leaders = ~p", [pi(GLs)]),
+ [pkill(GL, kill) || GL <- GLs, GL /= SharedGL],
+ SharedGL.
+
+find_and_kill(proc, ProcGL) ->
+ {Procs,SharedGL,GLs} = ct:remaining_test_procs(),
+ ct:pal("Remaining test processes = ~p", [pi(Procs++GLs)]),
+ [pkill(P, kill) || {P,GL} <- Procs, GL == ProcGL],
+ SharedGL.
+
+pi([{P,_GL}|Ps]) ->
+ pi([P|Ps]);
+pi([P|Ps]) ->
+ case node() == node(P) of
+ true ->
+ {_,GL} = process_info(P,group_leader),
+ {_,CF} = process_info(P,current_function),
+ {_,IC} = process_info(P,initial_call),
+ {_,D} = process_info(P,dictionary),
+ Shared = test_server_io:get_gl(true),
+ User = whereis(user),
+ if (GL /= P) and (GL /= Shared) and (GL /= User) ->
+ [{P,GL,CF,IC,D} | pi([GL|Ps])];
+ true ->
+ [{P,GL,CF,IC,D} | pi(Ps)]
+ end;
+ false ->
+ pi(Ps)
+ end;
+pi([]) ->
+ [].
+
+do_until(Fun, Until) ->
+ io:format("Will do until ~p~n", [Until]),
+ do_until(Fun, Until, 1000).
+
+do_until(_, Until, 0) ->
+ io:format("Couldn't get ~p~n", [Until]),
+ exit({not_reached,Until});
+
+do_until(Fun, Until, N) ->
+ case Fun() of
+ Until ->
+ ok;
+ _Tmp ->
+ do_until(Fun, Until, N-1)
+ end.
+
+pkill(P, How) ->
+ ct:pal("KILLING ~w NOW!", [P]),
+ exit(P, How).
+
diff --git a/lib/common_test/test/ct_config_SUITE.erl b/lib/common_test/test/ct_config_SUITE.erl
index 250700741c..5ffc735d6a 100644
--- a/lib/common_test/test/ct_config_SUITE.erl
+++ b/lib/common_test/test/ct_config_SUITE.erl
@@ -213,8 +213,8 @@ reformat_events(Events, EH) ->
skip_dynamic() ->
case os:getenv("TS_EXTRA_PLATFORM_LABEL") of
TSExtraPlatformLabel when is_list(TSExtraPlatformLabel) ->
- case string:str(TSExtraPlatformLabel,"TimeWarpingOS") of
- 0 -> false;
+ case string:find(TSExtraPlatformLabel,"TimeWarpingOS") of
+ nomatch -> false;
_ -> true
end;
_ ->
diff --git a/lib/common_test/test/ct_cover_SUITE_data/cover_SUITE.erl b/lib/common_test/test/ct_cover_SUITE_data/cover_SUITE.erl
index 4e013b8056..e9e8b2a54d 100644
--- a/lib/common_test/test/ct_cover_SUITE_data/cover_SUITE.erl
+++ b/lib/common_test/test/ct_cover_SUITE_data/cover_SUITE.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-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.
@@ -23,9 +23,7 @@
%% Description:
%% This file contains the test cases for the code coverage support
%%
-%% @author Support
-%% @doc Test of code coverage support in common_test
-%% @end
+%% Test of code coverage support in common_test
%%----------------------------------------------------------------------
%%----------------------------------------------------------------------
-module(cover_SUITE).
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/verify_config.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/verify_config.erl
index 530ee09654..ef8c05cb2e 100644
--- a/lib/common_test/test/ct_error_SUITE_data/error/test/verify_config.erl
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/verify_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,9 +18,9 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test Example Suite Callback module.
+%%% Common Test Example Suite Callback module.
%%%
-%%% <p>This module gives an example of a common test CTH (Common Test Hook).
+%%% This module gives an example of a common test CTH (Common Test Hook).
%%% There are many ways to add a CTH to a test run, you can do it either in
%%% the command line using -ct_hook, in a test spec using
%%% {ct_hook,M} or in the suite it self by returning ct_hook
@@ -31,7 +31,7 @@
%%% it will be stopped after end_per_suite and so on. See terminate
%%% documentation for a table describing the scoping machanics.
%%%
-%%% All of callbacks except init/1 in a CTH are optional.</p>
+%%% All of callbacks except init/1 in a CTH are optional.
-module(verify_config).
@@ -69,14 +69,14 @@
-record(state, { id = ?MODULE :: term()}).
-%% @doc Always called before any other callback function. Use this to initiate
+%% Always called before any other callback function. Use this to initiate
%% any common state. It should return an state for this CTH.
-spec init(Id :: term(), Opts :: proplists:proplist()) ->
{ok, State :: #state{}}.
init(Id, Opts) ->
{ok,Opts}.
-%% @doc The ID is used to uniquly identify an CTH instance, if two CTH's
+%% The ID is used to uniquly identify an CTH instance, if two CTH's
%% return the same ID the seconds CTH is ignored. This function should NOT
%% have any side effects as it might be called multiple times by common test.
-spec id(Opts :: proplists:proplist()) ->
@@ -84,7 +84,7 @@ init(Id, Opts) ->
id(Opts) ->
os:timestamp().
-%% @doc Called before init_per_suite is called. Note that this callback is
+%% Called before init_per_suite is called. Note that this callback is
%% only called if the CTH is added before init_per_suite is run (eg. in a test
%% specification, suite/0 function etc).
%% You can change the config in the this function.
@@ -95,7 +95,7 @@ id(Opts) ->
pre_init_per_suite(Suite,Config,State) ->
{Config, State}.
-%% @doc Called after init_per_suite.
+%% Called after init_per_suite.
%% you can change the return value in this function.
-spec post_init_per_suite(Suite :: atom(),
Config :: config(),
@@ -105,7 +105,7 @@ pre_init_per_suite(Suite,Config,State) ->
post_init_per_suite(Suite,Config,Return,State) ->
{Return, State}.
-%% @doc Called before end_per_suite. The config/state can be changed here,
+%% Called before end_per_suite. The config/state can be changed here,
%% though it will only affect the *end_per_suite function.
-spec pre_end_per_suite(Suite :: atom(),
Config :: config() | skip_or_fail(),
@@ -114,7 +114,7 @@ post_init_per_suite(Suite,Config,Return,State) ->
pre_end_per_suite(Suite,Config,State) ->
{Config, State}.
-%% @doc Called after end_per_suite. Note that the config cannot be
+%% Called after end_per_suite. Note that the config cannot be
%% changed here, only the status of the suite.
-spec post_end_per_suite(Suite :: atom(),
Config :: config(),
@@ -124,7 +124,7 @@ pre_end_per_suite(Suite,Config,State) ->
post_end_per_suite(Suite,Config,Return,State) ->
{Return, State}.
-%% @doc Called before each init_per_group.
+%% Called before each init_per_group.
%% You can change the config in this function.
-spec pre_init_per_group(Group :: atom(),
Config :: config(),
@@ -133,7 +133,7 @@ post_end_per_suite(Suite,Config,Return,State) ->
pre_init_per_group(Group,Config,State) ->
{Config, State}.
-%% @doc Called after each init_per_group.
+%% Called after each init_per_group.
%% You can change the return value in this function.
-spec post_init_per_group(Group :: atom(),
Config :: config(),
@@ -143,7 +143,7 @@ pre_init_per_group(Group,Config,State) ->
post_init_per_group(Group,Config,Return,State) ->
{Return, State}.
-%% @doc Called after each end_per_group. The config/state can be changed here,
+%% Called after each end_per_group. The config/state can be changed here,
%% though it will only affect the *end_per_group functions.
-spec pre_end_per_group(Group :: atom(),
Config :: config() | skip_or_fail(),
@@ -152,7 +152,7 @@ post_init_per_group(Group,Config,Return,State) ->
pre_end_per_group(Group,Config,State) ->
{Config, State}.
-%% @doc Called after each end_per_group. Note that the config cannot be
+%% Called after each end_per_group. Note that the config cannot be
%% changed here, only the status of the group.
-spec post_end_per_group(Group :: atom(),
Config :: config(),
@@ -162,7 +162,7 @@ pre_end_per_group(Group,Config,State) ->
post_end_per_group(Group,Config,Return,State) ->
{Return, State}.
-%% @doc Called before each test case.
+%% Called before each test case.
%% You can change the config in this function.
-spec pre_init_per_testcase(TC :: atom(),
Config :: config(),
@@ -171,7 +171,7 @@ post_end_per_group(Group,Config,Return,State) ->
pre_init_per_testcase(TC,Config,State) ->
{Config, State}.
-%% @doc Called after each test case. Note that the config cannot be
+%% Called after each test case. Note that the config cannot be
%% changed here, only the status of the test case.
-spec post_end_per_testcase(TC :: atom(),
Config :: config(),
@@ -198,7 +198,7 @@ post_end_per_testcase(TC,Config,Return,State) ->
end,
{Return, State}.
-%% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group,
+%% Called after post_init_per_suite, post_end_per_suite, post_init_per_group,
%% post_end_per_group and post_end_per_tc if the suite, group or test case failed.
%% This function should be used for extra cleanup which might be needed.
%% It is not possible to modify the config or the status of the test run.
@@ -209,7 +209,7 @@ post_end_per_testcase(TC,Config,Return,State) ->
on_tc_fail(TC, Reason, State) ->
State.
-%% @doc Called when a test case is skipped by either user action
+%% Called when a test case is skipped by either user action
%% or due to an init function failing. Test case can be
%% end_per_suite, init_per_group, end_per_group and the actual test cases.
-spec on_tc_skip(TC :: end_per_suite |
@@ -221,7 +221,7 @@ on_tc_fail(TC, Reason, State) ->
on_tc_skip(TC, Reason, State) ->
State.
-%% @doc Called when the scope of the CTH is done, this depends on
+%% Called when the scope of the CTH is done, this depends on
%% when the CTH was specified. This translation table describes when this
%% function is called.
%%
diff --git a/lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl b/lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl
index 07b21b4178..e4c7be3cac 100644
--- a/lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl
+++ b/lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,10 +18,10 @@
%% %CopyrightEnd%
%%
-%%% @doc Event handler module
+%%% Event handler module
%%%
-%%% <p>This is an event handler module used for testing that
-%%% Common Test generates events as expected.</p>
+%%% This is an event handler module used for testing that
+%%% Common Test generates events as expected.
%%%
-module(eh_A).
diff --git a/lib/common_test/test/ct_hooks_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE.erl
index 8ba14e63bc..0f5636a789 100644
--- a/lib/common_test/test/ct_hooks_SUITE.erl
+++ b/lib/common_test/test/ct_hooks_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -257,16 +257,21 @@ cth_log(Config) when is_list(Config) ->
lists:foreach(
fun(UnexpIoLog) ->
{ok,Bin} = file:read_file(UnexpIoLog),
- Ts = string:tokens(binary_to_list(Bin),[$\n]),
- Matches = lists:foldl(fun([$=,$E,$R,$R,$O,$R|_], N) ->
- N+1;
- ([$L,$o,$g,$g,$e,$r|_], N) ->
- N+1;
+ Ts = string:lexemes(binary_to_list(Bin),[$\n]),
+ Matches = lists:foldl(fun([$=,$E,$R,$R,$O,$R|_], {E,I,L}) ->
+ {E+1,I,L};
+ ([$=,$I,$N,$F,$O|_], {E,I,L}) ->
+ {E,I+1,L};
+ ([$L,$o,$g,$g,$e,$r|_], {E,I,L}) ->
+ {E,I,L+1};
(_, N) -> N
- end, 0, Ts),
- ct:pal("~p matches in ~tp", [Matches,UnexpIoLog]),
- if Matches > 10 -> ok;
- true -> exit({no_unexpected_io_found,UnexpIoLog})
+ end, {0,0,0}, Ts),
+ ct:pal("~p ({Error,Info,Log}) matches in ~tp",
+ [Matches,UnexpIoLog]),
+ MatchList = tuple_to_list(Matches),
+ case [N || N <- MatchList, N<3] of
+ [] -> ok;
+ _ -> exit({missing_unexpected_io,UnexpIoLog})
end
end, UnexpIoLogs),
ok.
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_tc_cth_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_tc_cth_SUITE.erl
index d400348354..404fb33476 100644
--- a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_tc_cth_SUITE.erl
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_tc_cth_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,6 @@
%% Test server callback functions
%%--------------------------------------------------------------------
-%% @doc
%% Config - [tuple()]
%% A list of key/value pairs, holding the test case configuration.
%%
@@ -38,27 +37,23 @@
%% Note: This function is free to add any key/value pairs to the Config
%% variable, but should NOT alter/remove any existing entries.
%%
-%% @spec init_per_suite(Config) -> Config
-%% @end
+%% -spec init_per_suite(Config) -> Config
%%--------------------------------------------------------------------
init_per_suite(Config) ->
Config.
%%--------------------------------------------------------------------
-%% @doc
%% Config - [tuple()]
%% A list of key/value pairs, holding the test case configuration.
%%
%% Cleanup after the whole suite
%%
-%% @spec end_per_suite(Config) -> _
-%% @end
+%% -spec end_per_suite(Config) -> _
%%--------------------------------------------------------------------
end_per_suite(_Config) ->
ok.
%%--------------------------------------------------------------------
-%% @doc
%% Case - atom()
%% Name of the test case that is about to be run.
%% Config - [tuple()]
@@ -70,14 +65,12 @@ end_per_suite(_Config) ->
%% variable, but should NOT alter/remove any existing entries.
%% Initiation before each test case
%%
-%% @spec init_per_testcase(TestCase, Config) -> Config
-%% @end
+%% -spec init_per_testcase(TestCase, Config) -> Config
%%--------------------------------------------------------------------
init_per_testcase(_TestCase, Config) ->
[{ct_hooks,[empty_cth]}|Config].
%%--------------------------------------------------------------------
-%% @doc
%% Case - atom()
%% Name of the test case that is about to be run.
%% Config - [tuple()]
@@ -85,22 +78,19 @@ init_per_testcase(_TestCase, Config) ->
%%
%% Cleanup after each test case
%%
-%% @spec end_per_testcase(TestCase, Config) -> _
-%% @end
+%% -spec end_per_testcase(TestCase, Config) -> _
%%--------------------------------------------------------------------
end_per_testcase(_TestCase, _Config) ->
ok.
%%--------------------------------------------------------------------
-%% @doc
%% TestCases - [Case]
%% Case - atom()
%% Name of a test case.
%%
%% Returns a list of all test cases in this test suite
%%
-%% @spec all() -> TestCases
-%% @end
+%% -spec all() -> TestCases
%%--------------------------------------------------------------------
all() ->
[test_case].
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/cth_log_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/cth_log_SUITE.erl
index bd1ac54781..eda190b682 100644
--- a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/cth_log_SUITE.erl
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/cth_log_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -124,6 +124,6 @@ gen() ->
gen_loop(N) ->
ct:log("Logger iteration: ~p", [N]),
error_logger:error_report(N),
- error_logger:info_report(progress, N),
+ error_logger:info_report(N),
ct:sleep(150),
gen_loop(N+1).
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl
index 961ea68d2d..c648367838 100644
--- a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,9 +18,9 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test Example Suite Callback module.
+%%% Common Test Example Suite Callback module.
%%%
-%%% <p>This module gives an example of a common test CTH (Common Test Hook).
+%%% This module gives an example of a common test CTH (Common Test Hook).
%%% There are many ways to add a CTH to a test run, you can do it either in
%%% the command line using -ct_hook, in a test spec using
%%% {ct_hook,M} or in the suite it self by returning ct_hook
@@ -31,7 +31,7 @@
%%% it will be stopped after end_per_suite and so on. See terminate
%%% documentation for a table describing the scoping machanics.
%%%
-%%% All of callbacks except init/1 in a CTH are optional.</p>
+%%% All of callbacks except init/1 in a CTH are optional.
-module(empty_cth).
@@ -71,7 +71,7 @@
-record(state, { id = ?MODULE :: term()}).
-%% @doc Always called before any other callback function. Use this to initiate
+%% Always called before any other callback function. Use this to initiate
%% any common state. It should return an state for this CTH.
-spec init(Id :: term(), Opts :: proplists:proplist()) ->
{ok, State :: #state{}}.
@@ -81,7 +81,7 @@ init(Id, Opts) ->
ct:log("~w:init called", [?MODULE]),
{ok,Opts}.
-%% @doc The ID is used to uniquly identify an CTH instance, if two CTH's
+%% The ID is used to uniquly identify an CTH instance, if two CTH's
%% return the same ID the seconds CTH is ignored. This function should NOT
%% have any side effects as it might be called multiple times by common test.
-spec id(Opts :: proplists:proplist()) ->
@@ -92,7 +92,7 @@ id(Opts) ->
ct:log("~w:id called", [?MODULE]),
ct_test_support:unique_timestamp().
-%% @doc Called before init_per_suite is called. Note that this callback is
+%% Called before init_per_suite is called. Note that this callback is
%% only called if the CTH is added before init_per_suite is run (eg. in a test
%% specification, suite/0 function etc).
%% You can change the config in the this function.
@@ -108,7 +108,7 @@ pre_init_per_suite(Suite,Config,State) ->
ct:log("~w:pre_init_per_suite(~w) called", [?MODULE,Suite]),
{Config, State}.
-%% @doc Called after init_per_suite.
+%% Called after init_per_suite.
%% you can change the return value in this function.
-spec post_init_per_suite(Suite :: atom(),
Config :: config(),
@@ -123,7 +123,7 @@ post_init_per_suite(Suite,Config,Return,State) ->
ct:log("~w:post_init_per_suite(~w) called", [?MODULE,Suite]),
{Return, State}.
-%% @doc Called before end_per_suite. The config/state can be changed here,
+%% Called before end_per_suite. The config/state can be changed here,
%% though it will only affect the *end_per_suite function.
-spec pre_end_per_suite(Suite :: atom(),
Config :: config() | skip_or_fail(),
@@ -137,7 +137,7 @@ pre_end_per_suite(Suite,Config,State) ->
ct:log("~w:pre_end_per_suite(~w) called", [?MODULE,Suite]),
{Config, State}.
-%% @doc Called after end_per_suite. Note that the config cannot be
+%% Called after end_per_suite. Note that the config cannot be
%% changed here, only the status of the suite.
-spec post_end_per_suite(Suite :: atom(),
Config :: config(),
@@ -152,7 +152,7 @@ post_end_per_suite(Suite,Config,Return,State) ->
ct:log("~w:post_end_per_suite(~w) called", [?MODULE,Suite]),
{Return, State}.
-%% @doc Called before each init_per_group.
+%% Called before each init_per_group.
%% You can change the config in this function.
-spec pre_init_per_group(Suite :: atom(),
Group :: atom(),
@@ -167,7 +167,7 @@ pre_init_per_group(Suite,Group,Config,State) ->
ct:log("~w:pre_init_per_group(~w,~w) called", [?MODULE,Suite,Group]),
{Config, State}.
-%% @doc Called after each init_per_group.
+%% Called after each init_per_group.
%% You can change the return value in this function.
-spec post_init_per_group(Suite :: atom(),
Group :: atom(),
@@ -183,7 +183,7 @@ post_init_per_group(Suite,Group,Config,Return,State) ->
ct:log("~w:post_init_per_group(~w,~w) called", [?MODULE,Suite,Group]),
{Return, State}.
-%% @doc Called after each end_per_group. The config/state can be changed here,
+%% Called after each end_per_group. The config/state can be changed here,
%% though it will only affect the *end_per_group functions.
-spec pre_end_per_group(Suite :: atom(),
Group :: atom(),
@@ -198,7 +198,7 @@ pre_end_per_group(Suite,Group,Config,State) ->
ct:log("~w:pre_end_per_group(~w~w) called", [?MODULE,Suite,Group]),
{Config, State}.
-%% @doc Called after each end_per_group. Note that the config cannot be
+%% Called after each end_per_group. Note that the config cannot be
%% changed here, only the status of the group.
-spec post_end_per_group(Suite :: atom(),
Group :: atom(),
@@ -214,7 +214,7 @@ post_end_per_group(Suite,Group,Config,Return,State) ->
ct:log("~w:post_end_per_group(~w,~w) called", [?MODULE,Suite,Group]),
{Return, State}.
-%% @doc Called before init_per_testcase/2 for each test case.
+%% Called before init_per_testcase/2 for each test case.
%% You can change the config in this function.
-spec pre_init_per_testcase(Suite :: atom(),
TC :: atom(),
@@ -229,7 +229,7 @@ pre_init_per_testcase(Suite,TC,Config,State) ->
ct:log("~w:pre_init_per_testcase(~w,~w) called", [?MODULE,Suite,TC]),
{Config, State}.
-%% @doc Called after init_per_testcase/2, and before the test case.
+%% Called after init_per_testcase/2, and before the test case.
-spec post_init_per_testcase(Suite :: atom(),
TC :: atom(),
Config :: config(),
@@ -244,7 +244,7 @@ post_init_per_testcase(Suite,TC,Config,Return,State) ->
ct:log("~w:post_init_per_testcase(~w,~w) called", [?MODULE,Suite,TC]),
{Return, State}.
-%% @doc Called before end_per_testacse/2. No skip or fail allowed here,
+%% Called before end_per_testacse/2. No skip or fail allowed here,
%% only config additions.
-spec pre_end_per_testcase(Suite :: atom(),
TC :: atom(),
@@ -259,7 +259,7 @@ pre_end_per_testcase(Suite,TC,Config,State) ->
ct:log("~w:pre_end_per_testcase(~w,~w) called", [?MODULE,Suite,TC]),
{Config, State}.
-%% @doc Called after end_per_testcase/2 for each test case. Note that
+%% Called after end_per_testcase/2 for each test case. Note that
%% the config cannot be changed here, only the status of the test case.
-spec post_end_per_testcase(Suite :: atom(),
TC :: atom(),
@@ -275,7 +275,7 @@ post_end_per_testcase(Suite,TC,Config,Return,State) ->
ct:log("~w:post_end_per_testcase(~w,~w) called", [?MODULE,Suite,TC]),
{Return, State}.
-%% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group,
+%% Called after post_init_per_suite, post_end_per_suite, post_init_per_group,
%% post_end_per_group and post_end_per_tc if the suite, group or test case failed.
%% This function should be used for extra cleanup which might be needed.
%% It is not possible to modify the config or the status of the test run.
@@ -292,7 +292,7 @@ on_tc_fail(Suite, TC, Reason, State) ->
ct:log("~w:on_tc_fail(~w,~w) called", [?MODULE,Suite,TC]),
State.
-%% @doc Called when a test case is skipped by either user action
+%% Called when a test case is skipped by either user action
%% or due to an init function failing. Test case can be
%% end_per_suite, init_per_group, end_per_group and the actual test cases.
-spec on_tc_skip(Suite :: atom(),
@@ -310,7 +310,7 @@ on_tc_skip(Suite, TC, Reason, State) ->
ct:log("~w:on_tc_skip(~w,~w) called", [?MODULE,Suite,TC]),
State.
-%% @doc Called when the scope of the CTH is done, this depends on
+%% Called when the scope of the CTH is done, this depends on
%% when the CTH was specified. This translation table describes when this
%% function is called.
%%
diff --git a/lib/common_test/test/ct_log_SUITE.erl b/lib/common_test/test/ct_log_SUITE.erl
index 93affda398..214eb17e1a 100644
--- a/lib/common_test/test/ct_log_SUITE.erl
+++ b/lib/common_test/test/ct_log_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -174,7 +174,7 @@ verify(Config) ->
TcLogFile = proplists:get_value(the_logfile, SavedCfg),
Pid = proplists:get_value(the_pid, SavedCfg),
StrPid = lists:flatten(io_lib:format("~p",[Pid])),
- EscPid = "&lt;" ++ string:substr(StrPid, 2, length(StrPid)-2) ++ "&gt;",
+ EscPid = "&lt;" ++ string:slice(StrPid, 1, length(StrPid)-2) ++ "&gt;",
String = proplists:get_value(the_string, SavedCfg),
ct:log("Read from prev testcase: ~p & ~p", [TcLogFile,Pid]),
{ok,Dev} = file:open(TcLogFile, [read]),
diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
index 586589ad40..a2fa099a8c 100644
--- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,9 +23,7 @@
%% Description:
%% This file contains the test cases for the ct_netconfc API.
%%
-%% @author Support
-%% @doc Netconf Client Interface.
-%% @end
+%% Netconf Client Interface.
%%----------------------------------------------------------------------
%%----------------------------------------------------------------------
-module(netconfc1_SUITE).
diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl b/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl
index 63bf9be134..656fdb4a40 100644
--- a/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2012-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.
@@ -231,8 +231,7 @@ data_for_channel(CM, Ch, Data, State) ->
{ok, NewState}
end
catch
- Class:Reason ->
- Stacktrace = erlang:get_stacktrace(),
+ Class:Reason:Stacktrace ->
error_logger:error_report([{?MODULE, data_for_channel},
{request, Data},
{buffer, State#session.buffer},
diff --git a/lib/common_test/test/ct_pre_post_test_io_SUITE.erl b/lib/common_test/test/ct_pre_post_test_io_SUITE.erl
index 7ffe6f045b..bca2d5f3de 100644
--- a/lib/common_test/test/ct_pre_post_test_io_SUITE.erl
+++ b/lib/common_test/test/ct_pre_post_test_io_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -164,7 +164,7 @@ pre_post_io(Config) ->
fun(PrePostIoFile) ->
ct:log("Reading Pre/Post Test IO Log file: ~ts", [PrePostIoFile]),
{ok,Bin} = file:read_file(PrePostIoFile),
- Ts = string:tokens(binary_to_list(Bin),[$\n]),
+ Ts = string:lexemes(binary_to_list(Bin),[$\n]),
PrePostIOEntries =
lists:foldl(fun([$L,$o,$g,$g,$e,$r|_],
{pre,PreLogN,PreErrN,0,0}) ->
@@ -203,7 +203,7 @@ pre_post_io(Config) ->
fun(UnexpIoFile) ->
ct:log("Reading Unexpected IO Log file: ~ts", [UnexpIoFile]),
{ok,Bin} = file:read_file(UnexpIoFile),
- Ts = string:tokens(binary_to_list(Bin),[$\n]),
+ Ts = string:lexemes(binary_to_list(Bin),[$\n]),
UnexpIOEntries =
lists:foldl(fun([$L,$o,$g,$g,$e,$r|_], [LogN,ErrN]) ->
[LogN+1,ErrN];
@@ -241,7 +241,7 @@ try_loop(_Fun, 0) ->
gave_up;
try_loop(Fun, N) ->
try Fun() of
- {error,_} ->
+ {Error,_} when Error==error; Error==badrpc ->
timer:sleep(10),
try_loop(Fun, N-1);
Result ->
@@ -257,7 +257,7 @@ try_loop(M, F, _A, 0) ->
gave_up;
try_loop(M, F, A, N) ->
try apply(M, F, A) of
- {error,_} ->
+ {Error,_Reason} when Error==error; Error==badrpc ->
timer:sleep(10),
try_loop(M, F, A, N-1);
Result ->
diff --git a/lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl b/lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl
index 1b171801a3..0e10ec187d 100644
--- a/lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl
+++ b/lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -126,12 +126,12 @@ default(Config) ->
auto_per_tc(Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
- ["log_private",_] = string:tokens(filename:basename(PrivDir), "."),
+ ["log_private",_] = string:lexemes(filename:basename(PrivDir), "."),
{ok,_} = file:list_dir(PrivDir).
manual_per_tc(Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
- ["log_private",_] = string:tokens(filename:basename(PrivDir), "."),
+ ["log_private",_] = string:lexemes(filename:basename(PrivDir), "."),
{error,_} = file:list_dir(PrivDir),
ok = ct:make_priv_dir(),
{ok,_} = file:list_dir(PrivDir).
diff --git a/lib/common_test/test/ct_repeat_testrun_SUITE_data/a_test/r1_SUITE.erl b/lib/common_test/test/ct_repeat_testrun_SUITE_data/a_test/r1_SUITE.erl
index 4ce375b4ee..1a305b1516 100644
--- a/lib/common_test/test/ct_repeat_testrun_SUITE_data/a_test/r1_SUITE.erl
+++ b/lib/common_test/test/ct_repeat_testrun_SUITE_data/a_test/r1_SUITE.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,14 +19,6 @@
%%
%%----------------------------------------------------------------------
%% File: r1_SUITE.erl
-%%
-%% Description:
-%%
-%%
-%% @author Support
-%% @doc
-%% @end
-%%----------------------------------------------------------------------
%%----------------------------------------------------------------------
-module(r1_SUITE).
-include_lib("common_test/include/ct.hrl").
diff --git a/lib/common_test/test/ct_repeat_testrun_SUITE_data/b_test/r2_SUITE.erl b/lib/common_test/test/ct_repeat_testrun_SUITE_data/b_test/r2_SUITE.erl
index 77bb544080..393cbcc780 100644
--- a/lib/common_test/test/ct_repeat_testrun_SUITE_data/b_test/r2_SUITE.erl
+++ b/lib/common_test/test/ct_repeat_testrun_SUITE_data/b_test/r2_SUITE.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,14 +19,6 @@
%%
%%----------------------------------------------------------------------
%% File: r2_SUITE.erl
-%%
-%% Description:
-%%
-%%
-%% @author Support
-%% @doc
-%% @end
-%%----------------------------------------------------------------------
%%----------------------------------------------------------------------
-module(r2_SUITE).
-include_lib("common_test/include/ct.hrl").
diff --git a/lib/common_test/test/ct_snmp_SUITE_data/snmp_SUITE.erl b/lib/common_test/test/ct_snmp_SUITE_data/snmp_SUITE.erl
index a6533641d8..1c81bbe95d 100644
--- a/lib/common_test/test/ct_snmp_SUITE_data/snmp_SUITE.erl
+++ b/lib/common_test/test/ct_snmp_SUITE_data/snmp_SUITE.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-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.
@@ -23,9 +23,7 @@
%% Description:
%% This file contains the test cases for the ct_snmp API.
%%
-%% @author Support
-%% @doc Test of SNMP support in common_test
-%% @end
+%% Test of SNMP support in common_test
%%----------------------------------------------------------------------
%%----------------------------------------------------------------------
-module(snmp_SUITE).
diff --git a/lib/common_test/test/ct_surefire_SUITE_data/surefire_SUITE.erl b/lib/common_test/test/ct_surefire_SUITE_data/surefire_SUITE.erl
index ed10356cdd..7a73e45b43 100644
--- a/lib/common_test/test/ct_surefire_SUITE_data/surefire_SUITE.erl
+++ b/lib/common_test/test/ct_surefire_SUITE_data/surefire_SUITE.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-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.
@@ -23,9 +23,7 @@
%% Description:
%% This file contains the test cases for cth_surefire.
%%
-%% @author Support
-%% @doc Test of surefire support in common_test
-%% @end
+%% Test of surefire support in common_test
%%----------------------------------------------------------------------
%%----------------------------------------------------------------------
-module(surefire_SUITE).
diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl
index 44c27e54c2..388d5d46c6 100644
--- a/lib/common_test/test/ct_test_support.erl
+++ b/lib/common_test/test/ct_test_support.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,9 +18,9 @@
%% %CopyrightEnd%
%%
-%%% @doc Test support functions
+%%% Test support functions
%%%
-%%% <p>This is a support module for testing the Common Test Framework.</p>
+%%% This is a support module for testing the Common Test Framework.
%%%
-module(ct_test_support).
@@ -88,7 +88,7 @@ start_slave(Config, Level) ->
start_slave(ct, Config, Level).
start_slave(NodeName, Config, Level) ->
- [_,Host] = string:tokens(atom_to_list(node()), "@"),
+ [_,Host] = string:lexemes(atom_to_list(node()), "@"),
test_server:format(0, "Trying to start ~s~n",
[atom_to_list(NodeName)++"@"++Host]),
PR = proplists:get_value(printable_range,Config,io:printable_range()),
@@ -1088,8 +1088,8 @@ locate({TEH,Name,{'DEF','RUNDIR'}}, Node, [Ev|Evs], Config) ->
{TEH,#event{name=Name, node=Node, data=EvData}} ->
{_,{_,LogDir}} = lists:keysearch(logdir, 1, get_opts(Config)),
D = filename:join(LogDir, "ct_run." ++ atom_to_list(Node)),
- case string:str(EvData, D) of
- 0 -> exit({badmatch,EvData});
+ case string:find(EvData, D) of
+ nomatch -> exit({badmatch,EvData});
_ -> ok
end,
{Config,Evs};
@@ -1104,8 +1104,8 @@ locate({TEH,Name,{'DEF',{'START_TIME','LOGDIR'}}}, Node, [Ev|Evs], Config) ->
{DT={{_,_,_},{_,_,_}},Dir} when is_list(Dir) ->
{_,{_,LogDir}} = lists:keysearch(logdir, 1, get_opts(Config)),
D = filename:join(LogDir, "ct_run." ++ atom_to_list(Node)),
- case string:str(Dir, D) of
- 0 -> exit({badmatch,Dir});
+ case string:find(Dir, D) of
+ nomatch -> exit({badmatch,Dir});
_ -> ok
end,
{[{start_time,DT}|Config],Evs};
@@ -1373,7 +1373,7 @@ delete_dirs(LogDir) ->
Dirs2Del =
lists:foldl(fun(Dir, Del) ->
[S,Mi,H,D,Mo,Y|_] =
- lists:reverse(string:tokens(Dir, [$.,$-,$_])),
+ lists:reverse(string:lexemes(Dir, [$.,$-,$_])),
S2I = fun(Str) -> list_to_integer(Str) end,
DT = {{S2I(Y),S2I(Mo),S2I(D)}, {S2I(H),S2I(Mi),S2I(S)}},
Then = calendar:datetime_to_gregorian_seconds(DT),
diff --git a/lib/common_test/test/ct_test_support_eh.erl b/lib/common_test/test/ct_test_support_eh.erl
index e8db52dcd3..120692dc7c 100644
--- a/lib/common_test/test/ct_test_support_eh.erl
+++ b/lib/common_test/test/ct_test_support_eh.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,10 +18,10 @@
%% %CopyrightEnd%
%%
-%%% @doc Event handler module
+%%% Event handler module
%%%
-%%% <p>This is an event handler module used for testing that
-%%% Common Test generates events as expected.</p>
+%%% This is an event handler module used for testing that
+%%% Common Test generates events as expected.
%%%
-module(ct_test_support_eh).
diff --git a/lib/common_test/test/ct_unicode_SUITE.erl b/lib/common_test/test/ct_unicode_SUITE.erl
index 355503a5dc..6f6ec97ceb 100644
--- a/lib/common_test/test/ct_unicode_SUITE.erl
+++ b/lib/common_test/test/ct_unicode_SUITE.erl
@@ -191,7 +191,7 @@ check_logs(Dirs) ->
[] ->
ok;
Match ->
- MatchStr = string:join(Match,"\n"),
+ MatchStr = lists:join("\n",Match),
ct:log("ERROR: Escaped unicode characters found in:~n~ts",[MatchStr]),
ct:fail(escaped_unicode_characters_found)
end.
diff --git a/lib/common_test/test/ct_unicode_SUITE_data/unicode_atoms_SUITE.erl b/lib/common_test/test/ct_unicode_SUITE_data/unicode_atoms_SUITE.erl
index 993452500e..4f9dd20e3e 100644
--- a/lib/common_test/test/ct_unicode_SUITE_data/unicode_atoms_SUITE.erl
+++ b/lib/common_test/test/ct_unicode_SUITE_data/unicode_atoms_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -77,7 +77,7 @@ all() ->
'fail_αβ_4'(_Config) ->
ct:log("This is test case ~tw",[?FUNCTION_NAME]),
- S = try throw(ok) catch throw:ok -> erlang:get_stacktrace() end,
+ S = try throw(ok) catch throw:ok:Stacktrace -> Stacktrace end,
erlang:raise(error,{error,testcase,?FUNCTION_NAME},S),
ok.
diff --git a/lib/common_test/test/ct_userconfig_callback.erl b/lib/common_test/test/ct_userconfig_callback.erl
index c723f4ca1c..e48d338dd5 100644
--- a/lib/common_test/test/ct_userconfig_callback.erl
+++ b/lib/common_test/test/ct_userconfig_callback.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
-export([check_parameter/1, read_config/1]).
read_config(Str) ->
- KeyVals = string:tokens(Str, " "),
+ KeyVals = string:lexemes(Str, " "),
{ok,read_config1(KeyVals)}.
read_config1([Key,Val | KeyVals]) ->
diff --git a/lib/common_test/test/ct_verbosity_SUITE_data/simple_evh.erl b/lib/common_test/test/ct_verbosity_SUITE_data/simple_evh.erl
index 03a0832e53..d1c293b4af 100644
--- a/lib/common_test/test/ct_verbosity_SUITE_data/simple_evh.erl
+++ b/lib/common_test/test/ct_verbosity_SUITE_data/simple_evh.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,14 +18,14 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test Framework Event Handler
+%%% Common Test Framework Event Handler
%%%
-%%% <p>This module implements an event handler that CT uses to
+%%% This module implements an event handler that CT uses to
%%% handle status and progress notifications during test runs.
%%% The notifications are handled locally (per node) and passed
%%% on to ct_master when CT runs in distributed mode. This
%%% module may be used as a template for other event handlers
-%%% that can be plugged in to handle local logging and reporting.</p>
+%%% that can be plugged in to handle local logging and reporting.
-module(simple_evh).
-behaviour(gen_event).
diff --git a/lib/common_test/test/erl2html2_SUITE.erl b/lib/common_test/test/erl2html2_SUITE.erl
index 53a63578b2..b2336ff0bc 100644
--- a/lib/common_test/test/erl2html2_SUITE.erl
+++ b/lib/common_test/test/erl2html2_SUITE.erl
@@ -214,10 +214,10 @@ check_line_number(Last,Line,OrigLine) ->
[$>|Rest] = lists:dropwhile(fun($>) -> false; (_) -> true end,Line),
check_line_number(Last,Rest,OrigLine);
_ ->
- [N |_] = string:tokens(Line,":"),
+ [N |_] = string:lexemes(Line,":"),
% erlang:display(N),
Num =
- try list_to_integer(string:strip(N))
+ try list_to_integer(string:trim(N,both,"\s"))
catch _:_ -> ct:fail({no_line_number_after,Last,OrigLine})
end,
if Num == Last+1 ->
diff --git a/lib/common_test/test/telnet_server.erl b/lib/common_test/test/telnet_server.erl
index 65300b0bdf..cef7784333 100644
--- a/lib/common_test/test/telnet_server.erl
+++ b/lib/common_test/test/telnet_server.erl
@@ -249,7 +249,7 @@ do_handle_data("echo " ++ Data,State) ->
send(Data++"\r\n> ",State),
{ok,State};
do_handle_data("echo_sep " ++ Data,State) ->
- Msgs = string:tokens(Data," "),
+ Msgs = string:lexemes(Data," "),
lists:foreach(fun(Msg) ->
send(Msg,State),
timer:sleep(10)
@@ -260,28 +260,28 @@ do_handle_data("echo_no_prompt " ++ Data,State) ->
send(Data,State),
{ok,State};
do_handle_data("echo_ml " ++ Data,State) ->
- Lines = string:tokens(Data," "),
- ReturnData = string:join(Lines,"\n"),
+ Lines = string:lexemes(Data," "),
+ ReturnData = lists:flatten(lists:join("\n",Lines)),
send(ReturnData++"\r\n> ",State),
{ok,State};
do_handle_data("echo_ml_no_prompt " ++ Data,State) ->
- Lines = string:tokens(Data," "),
- ReturnData = string:join(Lines,"\n"),
+ Lines = string:lexemes(Data," "),
+ ReturnData = lists:flatten(lists:join("\n",Lines)),
send(ReturnData,State),
{ok,State};
do_handle_data("echo_loop " ++ Data,State) ->
- [TStr|Lines] = string:tokens(Data," "),
- ReturnData = string:join(Lines,"\n"),
+ [TStr|Lines] = string:lexemes(Data," "),
+ ReturnData = lists:flatten(lists:join("\n",Lines)),
send_loop(list_to_integer(TStr),ReturnData,State),
{ok,State};
do_handle_data("echo_delayed_prompt "++Data,State) ->
- [MsStr|EchoData] = string:tokens(Data, " "),
- send(string:join(EchoData,"\n"),State),
+ [MsStr|EchoData] = string:lexemes(Data, " "),
+ send(lists:flatten(lists:join("\n",EchoData)),State),
timer:sleep(list_to_integer(MsStr)),
send("\r\n> ",State),
{ok,State};
do_handle_data("disconnect_after " ++WaitStr,State) ->
- Wait = list_to_integer(string:strip(WaitStr,right,$\n)),
+ Wait = list_to_integer(string:trim(WaitStr,trailing,"\n")),
dbg("Server will close connection in ~w ms...", [Wait]),
erlang:send_after(Wait,self(),disconnect),
{ok,State};
diff --git a/lib/common_test/test/test_server_SUITE.erl b/lib/common_test/test/test_server_SUITE.erl
index 50d8bdd1ac..05737cfac9 100644
--- a/lib/common_test/test/test_server_SUITE.erl
+++ b/lib/common_test/test/test_server_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,12 +18,7 @@
%% %CopyrightEnd%
%%
%%%-------------------------------------------------------------------
-%%% @author Lukas Larsson <[email protected]>
-%%% @copyright (C) 2011, Erlang Solutions Ltd.
-%%% @doc
-%%%
-%%% @end
-%%% Created : 15 Feb 2011 by Lukas Larsson <[email protected]>
+%%% Author: Lukas Larsson <[email protected]>
%%%-------------------------------------------------------------------
-module(test_server_SUITE).
@@ -71,7 +66,7 @@ init_per_testcase(_TestCase, Config) ->
%% @spec end_per_testcase(TestCase, Config0) ->
%% void() | {save_config,Config1} | {fail,Reason}
end_per_testcase(test_server_unicode, _Config) ->
- [_,Host] = string:tokens(atom_to_list(node()), "@"),
+ [_,Host] = string:lexemes(atom_to_list(node()), "@"),
N1 = list_to_atom("test_server_tester_latin1" ++ "@" ++ Host),
N2 = list_to_atom("test_server_tester_utf8" ++ "@" ++ Host),
test_server:stop_node(N1),
@@ -347,7 +342,7 @@ generate_and_run_unicode_test(Config0,Encoding) ->
RunDir = get_latest_run_dir(LogDir),
true = filelib:is_dir(RunDir),
- LowerModStr = string:to_lower(ModStr),
+ LowerModStr = string:lowercase(ModStr),
SuiteHtml = translate_filename(LowerModStr++".src.html",Encoding),
true = filelib:is_regular(filename:join(RunDir,SuiteHtml)),
@@ -362,7 +357,7 @@ generate_and_run_unicode_test(Config0,Encoding) ->
%% remote file system on master - i.e. they will use same file name
%% mode as the master.
start_node(Config,Name,Args) ->
- [_,Host] = string:tokens(atom_to_list(node()), "@"),
+ [_,Host] = string:lexemes(atom_to_list(node()), "@"),
ct:log("Trying to start ~w@~s~n",[Name,Host]),
case test_server:start_node(Name, peer, [{args,Args}]) of
{error,Reason} ->
diff --git a/lib/common_test/test/test_server_test_lib.erl b/lib/common_test/test/test_server_test_lib.erl
index c18b89b178..9ee946af0b 100644
--- a/lib/common_test/test/test_server_test_lib.erl
+++ b/lib/common_test/test/test_server_test_lib.erl
@@ -43,7 +43,7 @@ pre_init_per_testcase(_TC,Config,State) ->
{start_slave(Config, 50),State}.
start_slave(Config,_Level) ->
- [_,Host] = string:tokens(atom_to_list(node()), "@"),
+ [_,Host] = string:lexemes(atom_to_list(node()), "@"),
ct:log("Trying to start ~s~n",
["test_server_tester@"++Host]),
@@ -121,7 +121,7 @@ parse_suite(FileName) ->
end.
fline(Fd) ->
- case prim_file:read_line(Fd) of
+ case file:read_line(Fd) of
eof -> eof;
{ok, Line} -> Line
end.
diff --git a/lib/common_test/test_server/ts.erl b/lib/common_test/test_server/ts.erl
index 5bfea9f4de..179380a562 100644
--- a/lib/common_test/test_server/ts.erl
+++ b/lib/common_test/test_server/ts.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -583,7 +583,7 @@ is_list_of_suites(List) ->
S = if is_atom(Suite) -> atom_to_list(Suite);
true -> Suite
end,
- try lists:last(string:tokens(S,"_")) of
+ try lists:last(string:lexemes(S,"_")) of
"SUITE" -> true;
"suite" -> true;
_ -> false
diff --git a/lib/common_test/test_server/ts_autoconf_win32.erl b/lib/common_test/test_server/ts_autoconf_win32.erl
index 52e5ac8e69..1179dfe0e5 100644
--- a/lib/common_test/test_server/ts_autoconf_win32.erl
+++ b/lib/common_test/test_server/ts_autoconf_win32.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -228,7 +228,7 @@ make(Vars) ->
end.
find_make(MakeCmd, Vars) ->
- [Make|_] = string:tokens(MakeCmd, " \t"),
+ [Make|_] = string:lexemes(MakeCmd, " \t"),
case os:find_executable(Make) of
false ->
{no, Vars};
@@ -248,9 +248,9 @@ javac(Vars) ->
end.
is_debug_build() ->
- case catch string:str(erlang:system_info(system_version), "debug") of
- Int when is_integer(Int), Int > 0 ->
- true;
- _ ->
- false
+ case catch string:find(erlang:system_info(system_version), "debug") of
+ nomatch ->
+ false;
+ _Else ->
+ true
end.
diff --git a/lib/common_test/test_server/ts_erl_config.erl b/lib/common_test/test_server/ts_erl_config.erl
index 032593bdda..537628e39a 100644
--- a/lib/common_test/test_server/ts_erl_config.erl
+++ b/lib/common_test/test_server/ts_erl_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -311,7 +311,7 @@ lib_dir(Vars, Lib) ->
end,
CLibDir = filename:join(CLibDirList),
Cmd = "ls -d " ++ CLibDir ++ "*",
- XLibDir = lists:last(string:tokens(os:cmd(Cmd),"\n")),
+ XLibDir = lists:last(string:lexemes(os:cmd(Cmd),"\n")),
case file:list_dir(XLibDir) of
{error, enoent} ->
[];
@@ -358,18 +358,22 @@ link_library(_LibName,_Other) ->
%% Returns emulator specific variables.
emu_vars(Vars) ->
[{is_source_build, is_source_build()},
- {erl_name, atom_to_list(lib:progname())}|Vars].
+ {erl_name, get_progname()}|Vars].
+
+get_progname() ->
+ case init:get_argument(progname) of
+ {ok, [[Prog]]} ->
+ Prog;
+ _Other ->
+ "no_prog_name"
+ end.
is_source_build() ->
- string:str(erlang:system_info(system_version), "[source]") > 0.
+ string:find(erlang:system_info(system_version), "source") =/= nomatch.
is_debug_build() ->
- case catch string:str(erlang:system_info(system_version), "debug") of
- Int when is_integer(Int), Int > 0 ->
- true;
- _ ->
- false
- end.
+ string:find(erlang:system_info(system_version), "debug") =/= nomatch.
+
%%
%% ssl_libdir
%%
diff --git a/lib/common_test/test_server/ts_install.erl b/lib/common_test/test_server/ts_install.erl
index c4e0223ac7..048e5493d2 100644
--- a/lib/common_test/test_server/ts_install.erl
+++ b/lib/common_test/test_server/ts_install.erl
@@ -115,7 +115,7 @@ get_vars(_, _, _, _) ->
config_flags() ->
case os:getenv("CONFIG_FLAGS") of
false -> [];
- CF -> string:tokens(CF, " \t\n")
+ CF -> string:lexemes(CF, " \t\n")
end.
unix_autoconf(XConf) ->
@@ -127,7 +127,7 @@ unix_autoconf(XConf) ->
Threads = [" --enable-shlib-thread-safety" ||
erlang:system_info(threads) /= false],
Debug = [" --enable-debug-mode" ||
- string:str(erlang:system_info(system_version),"debug") > 0],
+ string:find(erlang:system_info(system_version),"debug") =/= nomatch],
MXX_Build = [Y || Y <- config_flags(),
Y == "--enable-m64-build"
orelse Y == "--enable-m32-build"],
@@ -159,10 +159,8 @@ assign_vars([]) ->
assign_vars([{VAR,FlagsStr} | VARs]) ->
[{VAR,assign_vars(FlagsStr)} | assign_vars(VARs)];
assign_vars(FlagsStr) ->
- Flags = [assign_all_vars(Str,[]) || Str <- string:tokens(FlagsStr, [$ ])],
- string:strip(lists:flatten(lists:map(fun(Flag) ->
- Flag ++ " "
- end, Flags)), right).
+ Flags = [assign_all_vars(Str,[]) || Str <- string:lexemes(FlagsStr, [$\s])],
+ lists:flatten(lists:join(" ", Flags)).
assign_all_vars([$$ | Rest], FlagSoFar) ->
{VarName,Rest1} = get_var_name(Rest, []),
@@ -292,7 +290,7 @@ add_vars(Vars0, Opts0) ->
get_testcase_callback() ->
case os:getenv("TS_TESTCASE_CALLBACK") of
ModFunc when is_list(ModFunc), ModFunc /= "" ->
- case string:tokens(ModFunc, " ") of
+ case string:lexemes(ModFunc, " ") of
[_Mod,_Func] -> ModFunc;
_ -> ""
end;
@@ -408,17 +406,13 @@ off_heap_msgq() ->
end.
schedulers() ->
- case catch erlang:system_info(smp_support) of
- true ->
- case {erlang:system_info(schedulers),
- erlang:system_info(schedulers_online)} of
- {S,S} ->
- "/S"++integer_to_list(S);
- {S,O} ->
- "/S"++integer_to_list(S) ++ ":" ++
- integer_to_list(O)
- end;
- _ -> ""
+ case {erlang:system_info(schedulers),
+ erlang:system_info(schedulers_online)} of
+ {S,S} ->
+ "/S"++integer_to_list(S);
+ {S,O} ->
+ "/S"++integer_to_list(S) ++ ":" ++
+ integer_to_list(O)
end.
bind_type() ->
@@ -434,8 +428,8 @@ bind_type() ->
debug() ->
- case string:str(erlang:system_info(system_version), "debug") of
- 0 -> "";
+ case string:find(erlang:system_info(system_version), "debug") of
+ nomatch -> "";
_ -> "/Debug"
end.
diff --git a/lib/common_test/test_server/ts_install_cth.erl b/lib/common_test/test_server/ts_install_cth.erl
index 5d325b1115..b6503fb864 100644
--- a/lib/common_test/test_server/ts_install_cth.erl
+++ b/lib/common_test/test_server/ts_install_cth.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
%%
-%%% @doc TS Installed SCB
+%%% TS Installed SCB
%%%
%%% This module does what the make parts of the ts:run/x command did,
%%% but not the Makefile.first parts! So they have to be done by ts or
@@ -60,13 +60,13 @@
-record(state, { ts_conf_dir, target_system, install_opts, nodenames, nodes }).
-%% @doc The id of this SCB
+%% The id of this SCB
-spec id(Opts :: term()) ->
Id :: term().
id(_Opts) ->
?MODULE.
-%% @doc Always called before any other callback function.
+%% Always called before any other callback function.
-spec init(Id :: term(), Opts :: proplists:proplist()) ->
{ok, State :: #state{}}.
init(_Id, Opts) ->
@@ -81,7 +81,7 @@ init(_Id, Opts) ->
target_system = TargetSystem,
install_opts = InstallOpts } }.
-%% @doc Called before init_per_suite is called.
+%% Called before init_per_suite is called.
-spec pre_init_per_suite(Suite :: atom(),
Config :: config(),
State :: #state{}) ->
@@ -108,13 +108,12 @@ pre_init_per_suite(_Suite,Config,State) ->
{add_node_name(Config, State), State}
catch error:{badmatch,{error,enoent}} ->
{add_node_name(Config, State), State};
- Error:Reason ->
- Stack = erlang:get_stacktrace(),
+ Error:Reason:Stack ->
ct:pal("~p failed! ~p:{~p,~p}",[?MODULE,Error,Reason,Stack]),
{{fail,{?MODULE,{Error,Reason, Stack}}},State}
end.
-%% @doc Called after init_per_suite.
+%% Called after init_per_suite.
-spec post_init_per_suite(Suite :: atom(),
Config :: config(),
Return :: config() | skip_or_fail(),
@@ -124,7 +123,7 @@ post_init_per_suite(_Suite,_Config,Return,State) ->
test_server_ctrl:kill_slavenodes(),
{Return, State}.
-%% @doc Called before end_per_suite.
+%% Called before end_per_suite.
-spec pre_end_per_suite(Suite :: atom(),
Config :: config() | skip_or_fail(),
State :: #state{}) ->
@@ -132,7 +131,7 @@ post_init_per_suite(_Suite,_Config,Return,State) ->
pre_end_per_suite(_Suite,Config,State) ->
{Config, State}.
-%% @doc Called after end_per_suite.
+%% Called after end_per_suite.
-spec post_end_per_suite(Suite :: atom(),
Config :: config(),
Return :: term(),
@@ -141,7 +140,7 @@ pre_end_per_suite(_Suite,Config,State) ->
post_end_per_suite(_Suite,_Config,Return,State) ->
{Return, State}.
-%% @doc Called before each init_per_group.
+%% Called before each init_per_group.
-spec pre_init_per_group(Group :: atom(),
Config :: config(),
State :: #state{}) ->
@@ -149,7 +148,7 @@ post_end_per_suite(_Suite,_Config,Return,State) ->
pre_init_per_group(_Group,Config,State) ->
{add_node_name(Config, State), State}.
-%% @doc Called after each init_per_group.
+%% Called after each init_per_group.
-spec post_init_per_group(Group :: atom(),
Config :: config(),
Return :: config() | skip_or_fail(),
@@ -158,7 +157,7 @@ pre_init_per_group(_Group,Config,State) ->
post_init_per_group(_Group,_Config,Return,State) ->
{Return, State}.
-%% @doc Called after each end_per_group.
+%% Called after each end_per_group.
-spec pre_end_per_group(Group :: atom(),
Config :: config() | skip_or_fail(),
State :: #state{}) ->
@@ -166,7 +165,7 @@ post_init_per_group(_Group,_Config,Return,State) ->
pre_end_per_group(_Group,Config,State) ->
{Config, State}.
-%% @doc Called after each end_per_group.
+%% Called after each end_per_group.
-spec post_end_per_group(Group :: atom(),
Config :: config(),
Return :: term(),
@@ -175,7 +174,7 @@ pre_end_per_group(_Group,Config,State) ->
post_end_per_group(_Group,_Config,Return,State) ->
{Return, State}.
-%% @doc Called before each test case.
+%% Called before each test case.
-spec pre_init_per_testcase(TC :: atom(),
Config :: config(),
State :: #state{}) ->
@@ -191,7 +190,7 @@ pre_init_per_testcase(_TC,Config,State) ->
post_init_per_testcase(_TC,_Config,Return,State) ->
{Return, State}.
-%% @doc Called after each test case.
+%% Called after each test case.
-spec pre_end_per_testcase(TC :: atom(),
Config :: config(),
State :: #state{}) ->
@@ -207,7 +206,7 @@ pre_end_per_testcase(_TC,Config,State) ->
post_end_per_testcase(_TC,_Config,Return,State) ->
{Return, State}.
-%% @doc Called after a test case failed.
+%% Called after a test case failed.
-spec on_tc_fail(TC :: init_per_suite | end_per_suite |
init_per_group | end_per_group | atom(),
Reason :: term(), State :: #state{}) ->
@@ -215,7 +214,7 @@ post_end_per_testcase(_TC,_Config,Return,State) ->
on_tc_fail(_TC, _Reason, State) ->
State.
-%% @doc Called when a test case is skipped.
+%% Called when a test case is skipped.
-spec on_tc_skip(TC :: end_per_suite | init_per_group | end_per_group | atom(),
{tc_auto_skip, {failed, {Mod :: atom(), Function :: atom(),
Reason :: term()}}} |
@@ -225,7 +224,7 @@ on_tc_fail(_TC, _Reason, State) ->
on_tc_skip(_TC, _Reason, State) ->
State.
-%% @doc Called when the scope of the SCB is done.
+%% Called when the scope of the SCB is done.
-spec terminate(State :: #state{}) ->
term().
terminate(_State) ->
diff --git a/lib/common_test/test_server/ts_lib.erl b/lib/common_test/test_server/ts_lib.erl
index a7be740c5c..7c1c14f467 100644
--- a/lib/common_test/test_server/ts_lib.erl
+++ b/lib/common_test/test_server/ts_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -99,7 +99,7 @@ specialized_specs(Dir,PostFix) ->
sort_tests([begin
DirPart = filename:dirname(Name),
AppTest = hd(lists:reverse(filename:split(DirPart))),
- list_to_atom(string:substr(AppTest, 1, length(AppTest)-5))
+ list_to_atom(string:slice(AppTest, 0, string:length(AppTest)-5))
end || Name <- Specs]).
specs(Dir) ->
@@ -111,16 +111,17 @@ specs(Dir) ->
[Spec,TestDir|_] =
lists:reverse(filename:split(FullName)),
[_TestSuffix|TDParts] =
- lists:reverse(string:tokens(TestDir,[$_,$.])),
+ lists:reverse(string:lexemes(TestDir,[$_,$.])),
[_SpecSuffix|SParts] =
- lists:reverse(string:tokens(Spec,[$_,$.])),
+ lists:reverse(string:lexemes(Spec,[$_,$.])),
if TDParts == SParts ->
[filename_to_atom(FullName)];
true ->
[]
end
end, Specs),
- sort_tests(MainSpecs).
+
+ sort_tests(filter_tests(MainSpecs)).
test_categories(Dir, App) ->
Specs = filelib:wildcard(filename:join([filename:dirname(Dir),
@@ -141,10 +142,29 @@ suites(Dir, App) ->
"*_SUITE.erl"]),
Suites=filelib:wildcard(Glob),
[filename_to_atom(Name) || Name <- Suites].
-
+
filename_to_atom(Name) ->
list_to_atom(filename:rootname(filename:basename(Name))).
+%% Filter out tests of applications that are not accessible
+
+filter_tests(Tests) ->
+ lists:filter(
+ fun(Special) when Special == epmd;
+ Special == emulator;
+ Special == system ->
+ true;
+ (Test) ->
+ case application:load(filename_to_atom(Test)) of
+ {error, {already_loaded, _}} ->
+ true;
+ {error,_NoSuchApplication} ->
+ false;
+ _ ->
+ true
+ end
+ end, Tests).
+
%% Sorts a list of either log files directories or spec files.
sort_tests(Tests) ->
@@ -253,7 +273,7 @@ do_test(Rest, Vars, Test) ->
get_arg([$(|Rest], Vars, Stop, _) ->
get_arg(Rest, Vars, Stop, []);
get_arg([Stop|Rest], Vars, Stop, Acc) ->
- Arg = string:strip(lists:reverse(Acc)),
+ Arg = string:trim(lists:reverse(Acc),both,[$\s]),
Subst = subst(Arg, Vars),
{Subst,Rest};
get_arg([C|Rest], Vars, Stop, Acc) ->
diff --git a/lib/common_test/test_server/ts_run.erl b/lib/common_test/test_server/ts_run.erl
index 82ae44ec06..7e12b9652c 100644
--- a/lib/common_test/test_server/ts_run.erl
+++ b/lib/common_test/test_server/ts_run.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -96,6 +96,9 @@ ct_run_test(Dir, CommonTestArgs) ->
case ct:run_test(CommonTestArgs) of
{_,_,_} ->
ok;
+ {error,{make_failed, _Modules} = Error} ->
+ io:format("ERROR: ~P\n", [Error,20]),
+ erlang:halt(123, [{flush,false}]);
{error,Error} ->
io:format("ERROR: ~P\n", [Error,20]);
Other ->
@@ -196,7 +199,7 @@ make_command(Vars, Spec, State) ->
TestPath = filename:nativename(TestDir),
Erl = case os:getenv("TS_RUN_VALGRIND") of
false ->
- atom_to_list(lib:progname());
+ ct:get_progname();
_ ->
case State#state.file of
Dir when is_list(Dir) ->
@@ -204,11 +207,7 @@ make_command(Vars, Spec, State) ->
_ ->
ok
end,
- "cerl -valgrind" ++
- case erlang:system_info(smp_support) of
- true -> " -smp";
- false -> ""
- end
+ "cerl -valgrind"
end,
Naming =
case ts_lib:var(longnames, Vars) of
@@ -288,6 +287,10 @@ tricky_print_data(Port, Timeout) ->
receive
{Port, {exit_status, 0}} ->
ok;
+ {Port, {exit_status, 123 = N}} ->
+ io:format(user, "Test run exited with status ~p,"
+ "aborting rest of test~n", [N]),
+ erlang:halt(123, [{flush,false}]);
{Port, {exit_status, N}} ->
io:format(user, "Test run exited with status ~p~n", [N])
after 1 ->
@@ -408,9 +411,9 @@ make_common_test_args(Args0, Options0, _Vars) ->
end,
ConfigFiles = [{config,[filename:join(ConfigPath,File)
|| File <- get_config_files()]}],
- io_lib:format("~100000p",[[{abort_if_missing_suites,true} |
- Args0++Trace++Cover++Logdir++
- ConfigFiles++Options++TimeTrap]]).
+ io_lib:format("~0p",[[{abort_if_missing_suites,true} |
+ Args0++Trace++Cover++Logdir++
+ ConfigFiles++Options++TimeTrap]]).
to_list(X) when is_atom(X) ->
atom_to_list(X);
@@ -461,4 +464,4 @@ split_one(Path) ->
filename:split(Path).
split_path(Path) ->
- string:tokens(Path,";").
+ string:lexemes(Path,";").
diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk
index a219aa4736..fd5d4a57aa 100644
--- a/lib/common_test/vsn.mk
+++ b/lib/common_test/vsn.mk
@@ -1 +1 @@
-COMMON_TEST_VSN = 1.15
+COMMON_TEST_VSN = 1.16.1
diff --git a/lib/compiler/doc/src/Makefile b/lib/compiler/doc/src/Makefile
index c6864cb835..32f150eef8 100644
--- a/lib/compiler/doc/src/Makefile
+++ b/lib/compiler/doc/src/Makefile
@@ -1,8 +1,8 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
+#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -14,7 +14,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
+#
# %CopyrightEnd%
#
include $(ERL_TOP)/make/target.mk
@@ -38,13 +38,12 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
XML_APPLICATION_FILES = ref_man.xml
XML_REF3_FILES = compile.xml
-XML_PART_FILES = part_notes.xml part_notes_history.xml
-XML_CHAPTER_FILES = notes.xml notes_history.xml
+XML_PART_FILES =
+XML_CHAPTER_FILES = notes.xml
BOOK_FILES = book.xml
-GIF_FILES = \
- warning.gif
+GIF_FILES =
XML_FILES = \
$(BOOK_FILES) $(XML_CHAPTER_FILES) \
@@ -64,9 +63,9 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
+XML_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -86,17 +85,18 @@ man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-debug opt:
+debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
+ rm -f errs core *~
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
@@ -110,4 +110,3 @@ release_docs_spec: docs
$(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
-
diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml
index 10164890f2..cfbd4c7fda 100644
--- a/lib/compiler/doc/src/compile.xml
+++ b/lib/compiler/doc/src/compile.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -123,6 +123,17 @@
in the Efficiency Guide.</p>
</item>
+ <tag><c>{compile_info, [{atom(), term()}]}</c></tag>
+ <item>
+ <p>Allows compilers built on top of <c>compile</c> to attach
+ extra compilation metadata to the <c>compile_info</c> chunk
+ in the generated beam file.</p>
+
+ <p>It is advised for compilers to remove all non-deterministic
+ information if the <c>deterministic</c> option is supported and
+ it was supplied by the user.</p>
+ </item>
+
<tag><c>compressed</c></tag>
<item>
<p>The compiler will compress the generated object code,
@@ -192,7 +203,8 @@
<tag><c>deterministic</c></tag>
<item>
<p>Omit the <c>options</c> and <c>source</c> tuples in
- the list returned by <c>Module:module_info(compile)</c>.
+ the list returned by <c>Module:module_info(compile)</c>, and
+ reduce the paths in stack traces to the module name alone.
This option will make it easier to achieve reproducible builds.
</p>
</item>
@@ -222,6 +234,15 @@ module.beam: module.erl \
header.hrl</code>
</item>
+ <tag><c>makedep_side_effect</c></tag>
+ <item>
+ <p>The dependecies are created as a side effect to the
+ normal compilation process. This means that the object
+ file will also be produced. This option override the
+ <c>makedep</c> option.
+ </p>
+ </item>
+
<tag><c>{makedep_output, Output}</c></tag>
<item>
<p>Writes generated rules to <c>Output</c> instead of the
@@ -327,8 +348,8 @@ module.beam: module.erl \
<tag><c>{source,FileName}</c></tag>
<item>
- <p>Sets the value of the source, as returned by
- <c>module_info(compile)</c>.</p>
+ <p>Overrides the source file name as presented in
+ <c>module_info(compile)</c> and stack traces.</p>
</item>
<tag><c>{outdir,Dir}</c></tag>
@@ -629,14 +650,6 @@ module.beam: module.erl \
<p>Turns off warnings for unused record types. Default is to
emit warnings for unused locally defined record types.</p>
</item>
-
- <tag><c>nowarn_get_stacktrace</c></tag>
- <item>
- <p>Turns off warnings for using <c>get_stacktrace/0</c> in a context
- where it will probably not work in a future release. For example,
- by default there will be a warning if <c>get_stacktrace/0</c> is
- used following a <c>catch</c> expression.</p>
- </item>
</taglist>
<p>Another class of warnings is generated by the compiler
diff --git a/lib/compiler/doc/src/fascicules.xml b/lib/compiler/doc/src/fascicules.xml
deleted file mode 100644
index fadd37eefb..0000000000
--- a/lib/compiler/doc/src/fascicules.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/compiler/doc/src/note.gif b/lib/compiler/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/compiler/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml
index f3d42a909b..b175669bd8 100644
--- a/lib/compiler/doc/src/notes.xml
+++ b/lib/compiler/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,518 @@
<p>This document describes the changes made to the Compiler
application.</p>
+<section><title>Compiler 7.2.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a bug that prevented certain variable-sized
+ binary comprehensions from compiling.</p>
+ <p>
+ Own Id: OTP-15186 Aux Id: ERL-665 </p>
+ </item>
+ <item>
+ <p>When compiling from Core Erlang, funs created in
+ certain expressions that were only used for their
+ side-effects were subtly broken.</p>
+ <p>
+ Own Id: OTP-15188 Aux Id: ERL-658 </p>
+ </item>
+ <item>
+ <p>There could be an internal consistency failure when a
+ <c>receive</c> was nested in a
+ <c>try</c>/<c>catch</c>.</p>
+ <p>
+ Own Id: OTP-15218 Aux Id: ERL-684 </p>
+ </item>
+ <item>
+ <p>In rare circumstances, the matched out tail of a
+ binary could be the entire original binary.</p>
+ <p>
+ Own Id: OTP-15219 Aux Id: ERL-689 </p>
+ </item>
+ <item>
+ <p>When <c>is_map_key/2</c> was used in a guard together
+ with the <c>not/1</c> or <c>or/2</c> operators, the error
+ behavior could be wrong when <c>is_map_key/2</c> was
+ passed a non-map as the second argument. </p>
+ <p>In rare circumstances, compiling code that uses
+ <c>is_map_key/2</c> could cause an internal consistency
+ check failure.</p>
+ <p>
+ Own Id: OTP-15227 Aux Id: ERL-699 </p>
+ </item>
+ <item>
+ <p>The compiler could crash when compiling a function
+ with multiple receives in multiple clauses.</p>
+ <p>
+ Own Id: OTP-15235 Aux Id: ERL-703 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.2.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fix a regression in OTP-15204 that removed
+ <c>.beam</c> file metadata that some external build tools
+ relied on.</p>
+ <p>
+ Own Id: OTP-15292</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed an issue where files compiled with the
+ <c>+deterministic</c> option differed if they were
+ compiled in a different directory but were otherwise
+ identical.</p>
+ <p>
+ Own Id: OTP-15204 Aux Id: ERL-679 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>In rare cases involving matching of binary literal
+ strings, the compiler could optimize away code that
+ should be executed.</p>
+ <p>
+ Own Id: OTP-15156 Aux Id: ERL-655 </p>
+ </item>
+ <item>
+ <p>There could be an internal consistency check failure
+ when compiling code that called <c>map_get(Key, Map)</c>
+ and then updated the same map.</p>
+ <p>
+ Own Id: OTP-15157</p>
+ </item>
+ <item>
+ <p>In rare circumstances, the compiler could crash in
+ <c>beam_jump</c> when compiling a floating point
+ operation.</p>
+ <p>
+ Own Id: OTP-15166 Aux Id: ERL-660 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The could could crash when compiling a complicated
+ function that used the binary syntax.</p>
+ <p>
+ Own Id: OTP-15150 Aux Id: ERL-650 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed an error in an optimization pass that caused
+ impossible tuple matching.</p>
+ <p>
+ Own Id: OTP-14855 Aux Id: ERL-549 </p>
+ </item>
+ <item>
+ <p>The exception thrown when a list comprehension was
+ given a non-list term was not always correct.</p>
+ <p>
+ Own Id: OTP-14992 Aux Id: ERL-572 </p>
+ </item>
+ <item>
+ <p>The compiler could produce incorrect code in rare
+ circumstances when the <c>[{inline,F/A}]</c> option was
+ used.</p>
+ <p>
+ Own Id: OTP-15115 Aux Id: PR-1831 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Changed the default behaviour of <c>.erlang</c>
+ loading: <c>.erlang</c> is no longer loaded from the
+ current directory. <c>c:erlangrc(PathList)</c> can be
+ used to search and load an <c>.erlang</c> file from user
+ specified directories.</p> <p><c>escript</c>,
+ <c>erlc</c>, <c>dialyzer</c> and <c>typer</c> no longer
+ load an <c>.erlang</c> at all.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-14439</p>
+ </item>
+ <item>
+ <p>Support for "tuple calls" have been removed from the
+ run-time system. Tuple calls was an undocumented and
+ unsupported feature which allowed the module argument for
+ an apply operation to be a tuple: <c>Var = dict:new(),
+ Var:size()</c>. This "feature" frequently caused
+ confusion, especially when such call failed. The
+ stacktrace would point out functions that don't exist in
+ the source code.</p>
+ <p>For legacy code that need to use parameterized modules
+ or tuple calls for some other reason, there is a new
+ compiler option called <c>tuple_calls</c>. When this
+ option is given, the compiler will generate extra code
+ that emulates the old behavior for calls where the module
+ is a variable.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-14497</p>
+ </item>
+ <item>
+ <p>In code such as <c>example({ok, Val}) -&gt; {ok,
+ Val}.</c> a tuple would be built. The compiler will now
+ automatically rewrite the code to
+ <c>example({ok,Val}=Tuple) -&gt; Tuple.</c> which will
+ reduce code size, execution time, and remove GC
+ pressure.</p>
+ <p>
+ Own Id: OTP-14505</p>
+ </item>
+ <item>
+ <p>The optimization of <c>case</c> expression where only
+ one of the case arms can execute successfully has been
+ improved.</p>
+ <p>
+ Own Id: OTP-14525</p>
+ </item>
+ <item>
+ <p>Some uses of binary matching has been slightly
+ improved, eliminating unnecessary register shuffling.</p>
+ <p>
+ Own Id: OTP-14594 Aux Id: ERL-444 </p>
+ </item>
+ <item>
+ <p>There is a new <c>{compile_info,Info}</c> option for
+ the compiler that allows BEAM-based languages such as
+ Elixir and LFE to add their own compiler versions.</p>
+ <p>
+ Own Id: OTP-14615 Aux Id: PR-1558 </p>
+ </item>
+ <item>
+ <p>Loaded BEAM code in a 64-bit system requires less
+ memory because of better packing of operands for
+ instructions.</p>
+ <p>These memory savings were achieved by major
+ improvements to the <c>beam_makeops</c> scripts used when
+ building the run time system and BEAM compiler. There is
+ also new for documentation for <c>beam_makeops</c> that
+ describes how new BEAM instructions and loader
+ transformations can be implemented. The documentation is
+ found in here in a source directory or git repository:
+ erts/emulator/internal_doc/beam_makeops.md. An online
+ version can be found here:
+ https://github.com/erlang/otp/blob/master/erts/emulator/internal_doc/beam_makeops.md</p>
+ <p>
+ Own Id: OTP-14626</p>
+ </item>
+ <item>
+ <p>Size calculations for binary constructions has been
+ somewhat optimized, producing smaller code.</p>
+ <p>
+ Own Id: OTP-14654</p>
+ </item>
+ <item>
+ <p>When the value returned from a '<c>catch</c>'
+ expression is ignored, no stacktrace will be built if an
+ exception is caught. That will save time and produce less
+ garbage. There are also some minor optimizations of
+ '<c>try</c>/<c>catch</c>' both in the compiler and
+ run-time system.</p>
+ <p>
+ Own Id: OTP-14683</p>
+ </item>
+ <item>
+ <p>There is a new syntax in '<c>try/catch</c>' for
+ retrieving the stacktrace without calling
+ '<c>erlang:get_stacktrace/0</c>'. See the reference
+ manual for a description of the new syntax. The
+ '<c>erlang:get_stacktrace/0</c>' BIF is now
+ deprecated.</p>
+ <p>
+ Own Id: OTP-14692</p>
+ </item>
+ <item>
+ <p>The following is an internal change in the compiler,
+ that is not noticeable for normal use of the compiler:
+ The module <c>v3_life</c> has been removed. Its
+ functionality has been simplified and integrated into
+ <c>v3_codegen</c>.</p>
+ <p>
+ Own Id: OTP-14712</p>
+ </item>
+ <item>
+ <p>The optimization of binary matching that delays
+ creation of sub binaries (see the Efficiency Guide) could
+ be thwarted by the argument order and could be necessary
+ to change the argument order. The compiler has now become
+ smarter and can handle any argument order.</p>
+ <p>
+ Own Id: OTP-14774</p>
+ </item>
+ <item>
+ <p>When the compiler was faced with complex case
+ expressions it would unnecessarily allocate stack
+ elements and shuffle data between x and y registers.
+ Improved code generation to only allocate a stack frame
+ when strictly necessary.</p>
+ <p>
+ Own Id: OTP-14808 Aux Id: ERL-514 </p>
+ </item>
+ <item>
+ <p>There is a new option '<c>makedep_side_effect</c>' for
+ the compiler and <c>-MMD</c> for '<c>erlc</c>' that
+ generates dependencies and continues to compile as
+ normal.</p>
+ <p>
+ Own Id: OTP-14830</p>
+ </item>
+ <item>
+ <p>When compiling modules with huge functions, the
+ compiler would generate a lot of atoms for its internal,
+ sometimes so many that the atom table would overflow. The
+ compiler has been rewritten to generate far less internal
+ atoms to avoid filling the atom table.</p>
+ <p>
+ Own Id: OTP-14968 Aux Id: ERL-563 </p>
+ </item>
+ <item>
+ <p>External funs with literal values for module, name,
+ and arity (e.g. <c>erlang:abs/1</c>) are now treated as
+ literals. That means more efficient code that produces
+ less garbage on the heap.</p>
+ <p>
+ Own Id: OTP-15003</p>
+ </item>
+ <item>
+ <p>Two new guards BIFs operating on maps have been added:
+ <c>map_get/2</c> and <c>is_map_key/2</c>. They do the
+ same as <c>maps:get/2</c> and <c>maps:is_key/2</c>,
+ respectively, except that they are allowed to be used in
+ guards.</p>
+ <p>
+ Own Id: OTP-15037 Aux Id: PR-1784, PR-1802 </p>
+ </item>
+ <item>
+ <p>A call or apply of a literal external fun will be
+ replaced with a direct call.</p>
+ <p>
+ Own Id: OTP-15044 Aux Id: ERL-614 </p>
+ </item>
+ <item>
+ <p>Part of EEP-44 has been implemented.</p>
+ <p>There is a new predefined macro called
+ <c>OTP_RELEASE</c> which is an integer indicating the OTP
+ release number (its value is <c>21</c> in this
+ release).</p>
+ <p>There are new preprocessor directives
+ <c>-if(Condition).</c> and <c>-elif(Condition).</c>. The
+ <c>if/elif</c> supports the builtin function
+ <c>defined(Symbol)</c>.</p>
+ <p>
+ Own Id: OTP-15087 Aux Id: PR-1810 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.1.5.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fix a regression in OTP-15204 that removed
+ <c>.beam</c> file metadata that some external build tools
+ relied on.</p>
+ <p>
+ Own Id: OTP-15292</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.1.5.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed an issue where files compiled with the
+ <c>+deterministic</c> option differed if they were
+ compiled in a different directory but were otherwise
+ identical.</p>
+ <p>
+ Own Id: OTP-15204 Aux Id: ERL-679 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.1.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The internal compiler pass (<c>beam_validator</c>)
+ that validates the generated code has been
+ strengthened.</p>
+ <p>When compiling from BEAM assembly code, the
+ <c>beam_type</c> optimizer pass could make the code
+ unsafe. Corrected.</p>
+ <p>
+ Own Id: OTP-14863</p>
+ </item>
+ <item>
+ <p>Corrected optimizations of integers matched out from
+ binaries and used in bit operations.</p>
+ <p>
+ Own Id: OTP-14898</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.1.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The '<c>deterministic</c>' option was not recognized
+ when given in a <c>-compile()</c> attribute in the source
+ code.</p>
+ <p>
+ Own Id: OTP-14773 Aux Id: ERL-498 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.1.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The compiler could issue an incorrect internal
+ consistency failure diagnostic for some complicated bit
+ syntax maches.</p>
+ <p>
+ Own Id: OTP-14640 Aux Id: ERL-490 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.1.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fail labels on guard BIFs weren't taken into account
+ during an optimization pass, and a bug in the validation
+ pass sometimes prevented this from being noticed when a
+ fault occurred.</p>
+ <p>
+ Own Id: OTP-14522 Aux Id: ERIERL-48 </p>
+ </item>
+ <item>
+ <p>
+ When compiling from Core Erlang, an 'apply' with a nested
+ apply in the function position would be treated as an
+ invalid call. Corrected. (Thanks to Mikael Pettersson for
+ reporting this bug.)</p>
+ <p>
+ Own Id: OTP-14526</p>
+ </item>
+ <item>
+ <p>Fixed checking of binary matching in the
+ <c>beam_validator</c> module to ensure that potential
+ compiler bugs are found at compile-time instead as
+ emulator crash at run-time.</p>
+ <p>
+ Own Id: OTP-14591</p>
+ </item>
+ <item>
+ <p>There could be false warnings for
+ <c>erlang:get_stacktrace/0</c> being used outside of a
+ <c>try</c> block when using multiple <c>catch</c>
+ clauses.</p>
+ <p>
+ Own Id: OTP-14600 Aux Id: ERL-478 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> The Erlang code linter no longer checks that the
+ functions mentioned in <c>nowarn_deprecated_function</c>
+ options are declared in the module. </p>
+ <p>
+ Own Id: OTP-14378</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fail labels on guard BIFs weren't taken into account
+ during an optimization pass, and a bug in the validation
+ pass sometimes prevented this from being noticed when a
+ fault occurred.</p>
+ <p>
+ Own Id: OTP-14522 Aux Id: ERIERL-48 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 7.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -206,6 +718,23 @@
</section>
+<section><title>Compiler 7.0.4.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fail labels on guard BIFs weren't taken into account
+ during an optimization pass, and a bug in the validation
+ pass sometimes prevented this from being noticed when a
+ fault occurred.</p>
+ <p>
+ Own Id: OTP-14522 Aux Id: ERIERL-48 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 7.0.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -405,6 +934,22 @@
</section>
+
+<section><title>Compiler 6.0.3.1</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fail labels on guard BIFs weren't taken into account
+ during an optimization pass, and a bug in the validation
+ pass sometimes prevented this from being noticed when a
+ fault occurred.</p>
+ <p>
+ Own Id: OTP-14522 Aux Id: ERIERL-48 </p>
+ </item>
+ </list>
+ </section>
+</section>
+
<section><title>Compiler 6.0.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/compiler/doc/src/part_notes.xml b/lib/compiler/doc/src/part_notes.xml
deleted file mode 100644
index c1f0ff3861..0000000000
--- a/lib/compiler/doc/src/part_notes.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Compiler Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date>2004-09-07</date>
- <rev>1.0</rev>
- </header>
- <description>
- <p>The <em>Compiler</em> application compiles Erlang
- code to byte-code. The highly compact byte-code is executed by
- the Erlang emulator.</p>
- <p>For information about older versions, see
- <url href="part_notes_history_frame.html">Release Notes History</url>.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/compiler/doc/src/part_notes_history.xml b/lib/compiler/doc/src/part_notes_history.xml
deleted file mode 100644
index 4019676b83..0000000000
--- a/lib/compiler/doc/src/part_notes_history.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2006</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Compiler Release Notes History</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p>The <em>Compiler</em> application compiles Erlang
- code to byte-code. The highly compact byte-code is executed by
- the Erlang emulator.</p>
- </description>
- <include file="notes_history"></include>
-</part>
-
diff --git a/lib/compiler/doc/src/user_guide.gif b/lib/compiler/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/compiler/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/compiler/doc/src/warning.gif b/lib/compiler/doc/src/warning.gif
deleted file mode 100644
index 96af52360e..0000000000
--- a/lib/compiler/doc/src/warning.gif
+++ /dev/null
Binary files differ
diff --git a/lib/compiler/internal_doc/cerl-notes.md b/lib/compiler/internal_doc/cerl-notes.md
new file mode 100644
index 0000000000..705fe8f42d
--- /dev/null
+++ b/lib/compiler/internal_doc/cerl-notes.md
@@ -0,0 +1,75 @@
+Some notes on the cerl modules
+==============================
+
+Maps in cerl_clauses:match/3
+----------------------------
+
+Not much optimization is done for maps in `cerl_clauses:match/3`.
+
+The reason is that the inliner (`cerl_inline`) was not designed for
+data types that depend on variables bound in the enclosing environment
+(for example, the keys for maps). If we attempt to extend the
+optimizations for maps similar to the optimizations for the other data
+types, the inliner will crash for certain code. Here is an example of
+code that would crash the inliner:
+
+ t() ->
+ f(key).
+
+ f(K) ->
+ case #{K => value} of
+ #{key := V} -> V
+ end.
+
+The reason for the crash is that the inliner works in several
+passes and calls `cerl_clauses:match/3` twice. The inliner will
+assume that the same result will be returned both times, but
+for this example different bindings will be returned.
+
+Here is the rough outline of what happens:
+
+* The first time `cerl_clauses:match/3` will be asked to match the
+pattern `#{K := V}` against `#{key => value}`. It cannot say more
+than that the pattern *may* match.
+
+* Now the inliner will add the bindings to body of the clause (which
+is simply `V`). In this case, the bindings are still empty, so
+nothing is added.
+
+* The inliner will now do some substitutions and renaming. The
+variable `K` will be replaced with `key`.
+
+* The next time `cerl_clauses:match/3` is called, it will be asked to
+match the pattern `#{key := V}` against `#{key => value#}`. In this
+case, there will be a match and the bindings can be extended with
+`{V,value}`.
+
+* The inliner will see that the entire case can be removed. Only
+the body for the clause needs to be kept.
+
+Thus, after inlining the function `t/0` will look like this:
+
+ t() ->
+ V.
+
+The problem here is that the inliner assumed that the bindings from
+the first and second call to `cer_clauses:match/3` would be the same.
+It used the empty bindings from the first call for the body.
+
+The correct way would be to add the bindings from the second call:
+
+ t() ->
+ let V = value in V.
+
+### How to fix this ###
+
+The inliner will need to call `cerl_clauses:match/3` after doing
+all substitutions and renaming. It is not clear to me how difficult
+that would be. I assume that the inliner is written the way it is
+for a good reason. That means that switching the order things are
+done would lead to correctness and/or performance problems.
+
+### What must also be done to fix this ###
+
+`cerl_inline:make_template/3` must be extended to create a template
+for maps. That is relatively straightforward.
diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile
index ef6db66ff6..2408c76b48 100644
--- a/lib/compiler/src/Makefile
+++ b/lib/compiler/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2017. All Rights Reserved.
+# Copyright Ericsson AB 1996-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -83,6 +83,7 @@ MODULES = \
core_scan \
erl_bifs \
rec_env \
+ sys_core_alias \
sys_core_bsm \
sys_core_dsetel \
sys_core_fold \
@@ -92,16 +93,14 @@ MODULES = \
v3_codegen \
v3_core \
v3_kernel \
- v3_kernel_pp \
- v3_life
+ v3_kernel_pp
BEAM_H = $(wildcard ../priv/beam_h/*.h)
HRL_FILES= \
beam_disasm.hrl \
core_parse.hrl \
- v3_kernel.hrl \
- v3_life.hrl
+ v3_kernel.hrl
YRL_FILE = core_parse.yrl
@@ -186,20 +185,19 @@ release_docs_spec:
# ----------------------------------------------------
$(EBIN)/beam_disasm.beam: $(EGEN)/beam_opcodes.hrl beam_disasm.hrl
-$(EBIN)/beam_listing.beam: v3_life.hrl
-$(EBIN)/beam_validator.beam: beam_disasm.hrl
+$(EBIN)/beam_listing.beam: core_parse.hrl v3_kernel.hrl
$(EBIN)/cerl.beam: core_parse.hrl
$(EBIN)/compile.beam: core_parse.hrl ../../stdlib/include/erl_compile.hrl
$(EBIN)/core_lib.beam: core_parse.hrl
$(EBIN)/core_lint.beam: core_parse.hrl
$(EBIN)/core_parse.beam: core_parse.hrl $(EGEN)/core_parse.erl
$(EBIN)/core_pp.beam: core_parse.hrl
+$(EBIN)/sys_core_alias.beam: core_parse.hrl
$(EBIN)/sys_core_dsetel.beam: core_parse.hrl
$(EBIN)/sys_core_fold.beam: core_parse.hrl
$(EBIN)/sys_core_fold_lists.beam: core_parse.hrl
$(EBIN)/sys_core_inline.beam: core_parse.hrl
-$(EBIN)/v3_codegen.beam: v3_life.hrl
+$(EBIN)/v3_codegen.beam: v3_kernel.hrl
$(EBIN)/v3_core.beam: core_parse.hrl
$(EBIN)/v3_kernel.beam: core_parse.hrl v3_kernel.hrl
$(EBIN)/v3_kernel_pp.beam: v3_kernel.hrl
-$(EBIN)/v3_life.beam: v3_kernel.hrl v3_life.hrl
diff --git a/lib/compiler/src/beam_a.erl b/lib/compiler/src/beam_a.erl
index cdb32d5d55..6fd4ace540 100644
--- a/lib/compiler/src/beam_a.erl
+++ b/lib/compiler/src/beam_a.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,8 +42,7 @@ function({function,Name,Arity,CLabel,Is0}) ->
Is = beam_jump:remove_unused_labels(Is1),
{function,Name,Arity,CLabel,Is}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
@@ -59,8 +58,17 @@ rename_instrs([{call_only,A,F}|Is]) ->
rename_instrs([{call_ext_only,A,F}|Is]) ->
[{call_ext,A,F},return|rename_instrs(Is)];
rename_instrs([{'%live',_}|Is]) ->
- %% When compiling from old .S files.
+ %% Ignore old type of live annotation. Only happens when compiling
+ %% from very old .S files.
rename_instrs(Is);
+rename_instrs([{get_list,S,D1,D2}|Is]) ->
+ %% Only happens when compiling from old .S files.
+ if
+ D1 =:= S ->
+ [{get_tl,S,D2},{get_hd,S,D1}|rename_instrs(Is)];
+ true ->
+ [{get_hd,S,D1},{get_tl,S,D2}|rename_instrs(Is)]
+ end;
rename_instrs([I|Is]) ->
[rename_instr(I)|rename_instrs(Is)];
rename_instrs([]) -> [].
diff --git a/lib/compiler/src/beam_asm.erl b/lib/compiler/src/beam_asm.erl
index c35efdfc9d..df0321e85a 100644
--- a/lib/compiler/src/beam_asm.erl
+++ b/lib/compiler/src/beam_asm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,10 +21,10 @@
-module(beam_asm).
--export([module/5]).
+-export([module/4]).
-export([encode/2]).
--export_type([fail/0,label/0,reg/0,src/0,module_code/0,function_name/0]).
+-export_type([fail/0,label/0,reg/0,reg_num/0,src/0,module_code/0,function_name/0]).
-import(lists, [map/2,member/2,keymember/3,duplicate/2,splitwith/2]).
-include("beam_opcodes.hrl").
@@ -55,20 +55,20 @@
-type module_code() ::
{module(),[_],[_],[asm_function()],pos_integer()}.
--spec module(module_code(), [{binary(), binary()}], [_], [compile:option()], [compile:option()]) ->
+-spec module(module_code(), [{binary(), binary()}], [{atom(),term()}], [compile:option()]) ->
{'ok',binary()}.
-module(Code, ExtraChunks, SourceFile, Opts, CompilerOpts) ->
- {ok,assemble(Code, ExtraChunks, SourceFile, Opts, CompilerOpts)}.
+module(Code, ExtraChunks, CompileInfo, CompilerOpts) ->
+ {ok,assemble(Code, ExtraChunks, CompileInfo, CompilerOpts)}.
-assemble({Mod,Exp0,Attr0,Asm0,NumLabels}, ExtraChunks, SourceFile, Opts, CompilerOpts) ->
+assemble({Mod,Exp0,Attr0,Asm0,NumLabels}, ExtraChunks, CompileInfo, CompilerOpts) ->
{1,Dict0} = beam_dict:atom(Mod, beam_dict:new()),
{0,Dict1} = beam_dict:fname(atom_to_list(Mod) ++ ".erl", Dict0),
NumFuncs = length(Asm0),
{Asm,Attr} = on_load(Asm0, Attr0),
Exp = cerl_sets:from_list(Exp0),
{Code,Dict2} = assemble_1(Asm, Exp, Dict1, []),
- build_file(Code, Attr, Dict2, NumLabels, NumFuncs, ExtraChunks, SourceFile, Opts, CompilerOpts).
+ build_file(Code, Attr, Dict2, NumLabels, NumFuncs, ExtraChunks, CompileInfo, CompilerOpts).
on_load(Fs0, Attr0) ->
case proplists:get_value(on_load, Attr0) of
@@ -111,7 +111,7 @@ assemble_function([H|T], Acc, Dict0) ->
assemble_function([], Code, Dict) ->
{Code, Dict}.
-build_file(Code, Attr, Dict, NumLabels, NumFuncs, ExtraChunks, SourceFile, Opts, CompilerOpts) ->
+build_file(Code, Attr, Dict, NumLabels, NumFuncs, ExtraChunks, CompileInfo, CompilerOpts) ->
%% Create the code chunk.
CodeChunk = chunk(<<"Code">>,
@@ -182,7 +182,7 @@ build_file(Code, Attr, Dict, NumLabels, NumFuncs, ExtraChunks, SourceFile, Opts,
Essentials1 = [iolist_to_binary(C) || C <- Essentials0],
MD5 = module_md5(Essentials1),
Essentials = finalize_fun_table(Essentials1, MD5),
- {Attributes,Compile} = build_attributes(Opts, SourceFile, Attr, MD5),
+ {Attributes,Compile} = build_attributes(Attr, CompileInfo, MD5),
AttrChunk = chunk(<<"Attr">>, Attributes),
CompileChunk = chunk(<<"CInf">>, Compile),
@@ -192,7 +192,7 @@ build_file(Code, Attr, Dict, NumLabels, NumFuncs, ExtraChunks, SourceFile, Opts,
%% Create IFF chunk.
- Chunks = case member(slim, Opts) of
+ Chunks = case member(slim, CompilerOpts) of
true ->
[Essentials,AttrChunk];
false ->
@@ -240,9 +240,7 @@ build_form(Id, Chunks0) when byte_size(Id) =:= 4, is_list(Chunks0) ->
chunk(Id, Contents) when byte_size(Id) =:= 4, is_binary(Contents) ->
Size = byte_size(Contents),
- [<<Id/binary,Size:32>>,Contents|pad(Size)];
-chunk(Id, Contents) when is_list(Contents) ->
- chunk(Id, list_to_binary(Contents)).
+ [<<Id/binary,Size:32>>,Contents|pad(Size)].
%% Build a correctly padded chunk (with a sub-header).
@@ -264,22 +262,10 @@ flatten_exports(Exps) ->
flatten_imports(Imps) ->
list_to_binary(map(fun({M,F,A}) -> <<M:32,F:32,A:32>> end, Imps)).
-build_attributes(Opts, SourceFile, Attr, MD5) ->
- Misc0 = case SourceFile of
- [] -> [];
- [_|_] -> [{source,SourceFile}]
- end,
- Misc = case member(slim, Opts) of
- false -> Misc0;
- true -> []
- end,
- Compile = case member(deterministic, Opts) of
- false ->
- [{options,Opts},{version,?COMPILER_VSN}|Misc];
- true ->
- [{version,?COMPILER_VSN}]
- end,
- {term_to_binary(set_vsn_attribute(Attr, MD5)),term_to_binary(Compile)}.
+build_attributes(Attr, Compile, MD5) ->
+ AttrBinary = term_to_binary(set_vsn_attribute(Attr, MD5)),
+ CompileBinary = term_to_binary([{version,?COMPILER_VSN}|Compile]),
+ {AttrBinary,CompileBinary}.
build_line_table(Dict) ->
{NumLineInstrs,NumFnames0,Fnames0,NumLines,Lines0} =
@@ -421,7 +407,17 @@ encode_arg({atom, Atom}, Dict0) when is_atom(Atom) ->
{Index, Dict} = beam_dict:atom(Atom, Dict0),
{encode(?tag_a, Index), Dict};
encode_arg({integer, N}, Dict) ->
- {encode(?tag_i, N), Dict};
+ %% Conservatily assume that all integers whose absolute
+ %% value is greater than 1 bsl 128 will be bignums in
+ %% the runtime system.
+ if
+ N >= 1 bsl 128 ->
+ encode_arg({literal, N}, Dict);
+ N =< -(1 bsl 128) ->
+ encode_arg({literal, N}, Dict);
+ true ->
+ {encode(?tag_i, N), Dict}
+ end;
encode_arg(nil, Dict) ->
{encode(?tag_a, 0), Dict};
encode_arg({f, W}, Dict) ->
@@ -479,7 +475,7 @@ encode_alloc_list_1([{floats,Floats}|T], Dict, Acc0) ->
encode_alloc_list_1([], Dict, Acc) ->
{iolist_to_binary(Acc),Dict}.
--spec encode(non_neg_integer(), pos_integer()) -> iodata().
+-spec encode(non_neg_integer(), integer()) -> iolist() | integer().
encode(Tag, N) when N < 0 ->
encode1(Tag, negative_to_bytes(N));
diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl
index 6543e05e20..fe43163455 100644
--- a/lib/compiler/src/beam_block.erl
+++ b/lib/compiler/src/beam_block.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,30 +23,36 @@
-module(beam_block).
-export([module/2]).
--import(lists, [reverse/1,reverse/2,foldl/3,member/2]).
+-import(lists, [reverse/1,reverse/2,member/2]).
-spec module(beam_utils:module_code(), [compile:option()]) ->
{'ok',beam_utils:module_code()}.
-module({Mod,Exp,Attr,Fs0,Lc}, _Opt) ->
- Fs = [function(F) || F <- Fs0],
+module({Mod,Exp,Attr,Fs0,Lc}, Opts) ->
+ Blockify = not member(no_blockify, Opts),
+ Fs = [function(F, Blockify) || F <- Fs0],
{ok,{Mod,Exp,Attr,Fs,Lc}}.
-function({function,Name,Arity,CLabel,Is0}) ->
+function({function,Name,Arity,CLabel,Is0}, Blockify) ->
try
%% Collect basic blocks and optimize them.
- Is1 = blockify(Is0),
- Is2 = embed_lines(Is1),
- Is3 = move_allocates(Is2),
- Is4 = beam_utils:live_opt(Is3),
- Is5 = opt_blocks(Is4),
- Is6 = beam_utils:delete_live_annos(Is5),
-
- %% Done.
- {function,Name,Arity,CLabel,Is6}
+ Is1 = case Blockify of
+ false -> Is0;
+ true -> blockify(Is0)
+ end,
+ Is2 = embed_lines(Is1),
+ Is3 = local_cse(Is2),
+ Is4 = beam_utils:anno_defs(Is3),
+ Is5 = move_allocates(Is4),
+ Is6 = beam_utils:live_opt(Is5),
+ Is7 = opt_blocks(Is6),
+ Is8 = beam_utils:delete_annos(Is7),
+ Is = opt_allocs(Is8),
+
+ %% Done.
+ {function,Name,Arity,CLabel,Is}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
@@ -102,7 +108,8 @@ collect({put_tuple,A,D}) -> {set,[D],[],{put_tuple,A}};
collect({put,S}) -> {set,[],[S],put};
collect({get_tuple_element,S,I,D}) -> {set,[D],[S],{get_tuple_element,I}};
collect({set_tuple_element,S,D,I}) -> {set,[],[S,D],{set_tuple_element,I}};
-collect({get_list,S,D1,D2}) -> {set,[D1,D2],[S],get_list};
+collect({get_hd,S,D}) -> {set,[D],[S],get_hd};
+collect({get_tl,S,D}) -> {set,[D],[S],get_tl};
collect(remove_message) -> {set,[],[],remove_message};
collect({put_map,F,Op,S,D,R,{list,Puts}}) ->
{set,[D],[S|Puts],{alloc,R,{put_map,Op,F}}};
@@ -130,23 +137,27 @@ embed_lines([{block,B2},{line,_}=Line,{block,B1}|T], Acc) ->
embed_lines([{block,B1},{line,_}=Line|T], Acc) ->
B = {block,[{set,[],[],Line}|B1]},
embed_lines([B|T], Acc);
+embed_lines([{block,B2},{block,B1}|T], Acc) ->
+ %% This can only happen when beam_block is run for
+ %% the second time.
+ B = {block,B1++B2},
+ embed_lines([B|T], Acc);
embed_lines([I|Is], Acc) ->
embed_lines(Is, [I|Acc]);
embed_lines([], Acc) -> Acc.
opt_blocks([{block,Bl0}|Is]) ->
%% The live annotation at the beginning is not useful.
- [{'%live',_,_}|Bl] = Bl0,
+ [{'%anno',_}|Bl] = Bl0,
[{block,opt_block(Bl)}|opt_blocks(Is)];
opt_blocks([I|Is]) ->
[I|opt_blocks(Is)];
opt_blocks([]) -> [].
opt_block(Is0) ->
- Is = find_fixpoint(fun(Is) ->
- opt_tuple_element(opt(Is))
- end, Is0),
- opt_alloc(Is).
+ find_fixpoint(fun(Is) ->
+ opt_tuple_element(opt(Is))
+ end, Is0).
find_fixpoint(OptFun, Is0) ->
case OptFun(Is0) of
@@ -173,7 +184,7 @@ find_fixpoint(OptFun, Is0) ->
%% safe to assume that if x(N) is initialized, then all lower-numbered
%% x registers are also initialized.
%%
-%% For example, in general it is not safe to transform the following
+%% For example, we must be careful when transforming the following
%% instructions:
%%
%% get_tuple_element x(0) Element => x(1)
@@ -185,13 +196,9 @@ find_fixpoint(OptFun, Is0) ->
%% get_tuple_element x(0) Element => x(1)
%%
%% The transformation is safe if and only if x(1) has been
-%% initialized previously. Unfortunately, beam_reorder may have moved
-%% a get_tuple_element instruction so that x(1) is not always
-%% initialized when this code is reached. To find whether or not x(1)
-%% is initialized, we would need to analyze all code preceding these
-%% two instructions (across branches). Since we currently don't have
-%% any practical mechanism for doing that, we will have to
-%% conservatively assume that the transformation is unsafe.
+%% initialized previously. We will use the annotations added by
+%% beam_utils:anno_defs/1 to determine whether x(a) has been
+%% initialized.
move_allocates([{block,Bl0}|Is]) ->
Bl = move_allocates_1(reverse(Bl0), []),
@@ -200,40 +207,77 @@ move_allocates([I|Is]) ->
[I|move_allocates(Is)];
move_allocates([]) -> [].
-move_allocates_1([I|Is], [{set,[],[],{alloc,Live0,Info}}|Acc]=Acc0) ->
- case {alloc_may_pass(I),alloc_live_regs(I, Live0)} of
- {false,_} ->
- move_allocates_1(Is, [I|Acc0]);
- {true,not_possible} ->
- move_allocates_1(Is, [I|Acc0]);
- {true,Live} when is_integer(Live) ->
- A = {set,[],[],{alloc,Live,Info}},
- move_allocates_1(Is, [A,I|Acc])
+move_allocates_1([{'%anno',_}|Is], Acc) ->
+ move_allocates_1(Is, Acc);
+move_allocates_1([I|Is], [{set,[],[],{alloc,Live0,Info0}}|Acc]=Acc0) ->
+ case alloc_may_pass(I) of
+ false ->
+ move_allocates_1(Is, [I|Acc0]);
+ true ->
+ case alloc_live_regs(I, Is, Live0) of
+ not_possible ->
+ move_allocates_1(Is, [I|Acc0]);
+ Live when is_integer(Live) ->
+ Info = safe_info(Info0),
+ A = {set,[],[],{alloc,Live,Info}},
+ move_allocates_1(Is, [A,I|Acc])
+ end
end;
move_allocates_1([I|Is], Acc) ->
move_allocates_1(Is, [I|Acc]);
move_allocates_1([], Acc) -> Acc.
+alloc_may_pass({set,_,[{fr,_}],fmove}) -> false;
alloc_may_pass({set,_,_,{alloc,_,_}}) -> false;
alloc_may_pass({set,_,_,{set_tuple_element,_}}) -> false;
alloc_may_pass({set,_,_,put_list}) -> false;
alloc_may_pass({set,_,_,put}) -> false;
alloc_may_pass({set,_,_,_}) -> true.
-
+
+safe_info({nozero,Stack,Heap,_}) ->
+ %% nozero is not safe if the allocation instruction is moved
+ %% upwards past an instruction that may throw an exception
+ %% (such as element/2).
+ {zero,Stack,Heap,[]};
+safe_info(Info) -> Info.
+
%% opt([Instruction]) -> [Instruction]
%% Optimize the instruction stream inside a basic block.
opt([{set,[X],[X],move}|Is]) -> opt(Is);
+opt([{set,[Dst],_,move},{set,[Dst],[Src],move}=I|Is]) when Dst =/= Src ->
+ opt([I|Is]);
+opt([{set,[{x,0}],[S1],move}=I1,{set,[D2],[{x,0}],move}|Is]) ->
+ opt([I1,{set,[D2],[S1],move}|Is]);
+opt([{set,[{x,0}],[S1],move}=I1,{set,[D2],[S2],move}|Is0]) when S1 =/= D2 ->
+ %% Place move S x0 at the end of move sequences so that
+ %% loader can merge with the following instruction
+ {Ds,Is} = opt_moves([D2], Is0),
+ [{set,Ds,[S2],move}|opt([I1|Is])];
opt([{set,_,_,{line,_}}=Line1,
{set,[D1],[{integer,Idx1},Reg],{bif,element,{f,0}}}=I1,
{set,_,_,{line,_}}=Line2,
{set,[D2],[{integer,Idx2},Reg],{bif,element,{f,0}}}=I2|Is])
when Idx1 < Idx2, D1 =/= D2, D1 =/= Reg, D2 =/= Reg ->
opt([Line2,I2,Line1,I1|Is]);
+opt([{set,[D1],[{integer,Idx1},Reg],{bif,element,{f,L}}}=I1,
+ {set,[D2],[{integer,Idx2},Reg],{bif,element,{f,L}}}=I2|Is])
+ when Idx1 < Idx2, D1 =/= D2, D1 =/= Reg, D2 =/= Reg ->
+ opt([I2,I1|Is]);
+opt([{set,Hd0,Cons,get_hd}=GetHd,
+ {set,Tl0,Cons,get_tl}=GetTl|Is0]) ->
+ case {opt_moves(Hd0, [GetTl|Is0]),opt_moves(Tl0, [GetHd|Is0])} of
+ {{Hd0,Is},{Tl0,_}} ->
+ [GetHd|opt(Is)];
+ {{Hd,Is},{Tl0,_}} ->
+ [{set,Hd,Cons,get_hd}|opt(Is)];
+ {{_,_},{Tl,Is}} ->
+ [{set,Tl,Cons,get_tl}|opt(Is)]
+ end;
opt([{set,Ds0,Ss,Op}|Is0]) ->
{Ds,Is} = opt_moves(Ds0, Is0),
[{set,Ds,Ss,Op}|opt(Is)];
-opt([{'%live',_,_}=I|Is]) ->
+opt([{'%anno',_}=I|Is]) ->
[I|opt(Is)];
opt([]) -> [].
@@ -245,17 +289,6 @@ opt_moves([D0]=Ds, Is0) ->
case opt_move(D0, Is0) of
not_possible -> {Ds,Is0};
{D1,Is} -> {[D1],Is}
- end;
-opt_moves([X0,Y0], Is0) ->
- {X,Is2} = case opt_move(X0, Is0) of
- not_possible -> {X0,Is0};
- {Y0,_} -> {X0,Is0};
- {_X1,_Is1} = XIs1 -> XIs1
- end,
- case opt_move(Y0, Is2) of
- not_possible -> {[X,Y0],Is2};
- {X,_} -> {[X,Y0],Is2};
- {Y,Is} -> {[X,Y],Is}
end.
%% opt_move(Dest, [Instruction]) -> {UpdatedDest,[Instruction]} | not_possible
@@ -269,7 +302,7 @@ opt_move(Dest, Is) ->
opt_move_1(R, [{set,[D],[R],move}|Is0], Acc) ->
%% Provided that the source register is killed by instructions
%% that follow, the optimization is safe.
- case eliminate_use_of_from_reg(Is0, R, D, []) of
+ case eliminate_use_of_from_reg(Is0, R, D) of
{yes,Is} -> opt_move_rev(D, Acc, Is);
no -> not_possible
end;
@@ -327,13 +360,21 @@ opt_tuple_element_1([{set,_,_,{alloc,_,_}}|_], _, _, _) ->
opt_tuple_element_1([{set,_,_,{try_catch,_,_}}|_], _, _, _) ->
no;
opt_tuple_element_1([{set,[D],[S],move}|Is0], I0, {_,S}, Acc) ->
- case eliminate_use_of_from_reg(Is0, S, D, []) of
+ case eliminate_use_of_from_reg(Is0, S, D) of
no ->
no;
- {yes,Is} ->
+ {yes,Is1} ->
{set,[S],Ss,Op} = I0,
I = {set,[D],Ss,Op},
- {yes,reverse(Acc, [I|Is])}
+ case opt_move_rev(S, Acc, [I|Is1]) of
+ not_possible ->
+ %% Not safe because the move of the
+ %% get_tuple_element instruction would cause the
+ %% result of a previous instruction to be ignored.
+ no;
+ {_,Is} ->
+ {yes,Is}
+ end
end;
opt_tuple_element_1([{set,Ds,Ss,_}=I|Is], MovedI, {S,D}=Regs, Acc) ->
case member(S, Ds) orelse member(D, Ss) of
@@ -369,6 +410,14 @@ is_killed_or_used(R, {set,Ss,Ds,_}) ->
%% that FromRegister is still used and that the optimization is not
%% possible.
+eliminate_use_of_from_reg(Is, From, To) ->
+ try
+ eliminate_use_of_from_reg(Is, From, To, [])
+ catch
+ throw:not_possible ->
+ no
+ end.
+
eliminate_use_of_from_reg([{set,_,_,{alloc,Live,_}}|_]=Is0, {x,X}, _, Acc) ->
if
X < Live ->
@@ -377,21 +426,32 @@ eliminate_use_of_from_reg([{set,_,_,{alloc,Live,_}}|_]=Is0, {x,X}, _, Acc) ->
{yes,reverse(Acc, Is0)}
end;
eliminate_use_of_from_reg([{set,Ds,Ss0,Op}=I0|Is], From, To, Acc) ->
+ ensure_safe_tuple(I0, To),
I = case member(From, Ss0) of
- true ->
- Ss = [case S of
- From -> To;
- _ -> S
- end || S <- Ss0],
- {set,Ds,Ss,Op};
- false ->
- I0
- end,
+ true ->
+ Ss = [case S of
+ From -> To;
+ _ -> S
+ end || S <- Ss0],
+ {set,Ds,Ss,Op};
+ false ->
+ I0
+ end,
case member(From, Ds) of
- true ->
- {yes,reverse(Acc, [I|Is])};
- false ->
- eliminate_use_of_from_reg(Is, From, To, [I|Acc])
+ true ->
+ {yes,reverse(Acc, [I|Is])};
+ false ->
+ case member(To, Ds) of
+ true ->
+ case beam_utils:is_killed_block(From, Is) of
+ true ->
+ {yes,reverse(Acc, [I|Is])};
+ false ->
+ no
+ end;
+ false ->
+ eliminate_use_of_from_reg(Is, From, To, [I|Acc])
+ end
end;
eliminate_use_of_from_reg([I]=Is, From, _To, Acc) ->
case beam_utils:is_killed_block(From, [I]) of
@@ -401,31 +461,51 @@ eliminate_use_of_from_reg([I]=Is, From, _To, Acc) ->
no
end.
+ensure_safe_tuple({set,[To],[],{put_tuple,_}}, To) ->
+ throw(not_possible);
+ensure_safe_tuple(_, _) -> ok.
+
+%% opt_allocs(Instructions) -> Instructions. Optimize allocate
+%% instructions inside blocks. If safe, replace an allocate_zero
+%% instruction with the slightly cheaper allocate instruction.
+
+opt_allocs(Is) ->
+ D = beam_utils:index_labels(Is),
+ opt_allocs_1(Is, D).
+
+opt_allocs_1([{block,Bl0}|Is], D) ->
+ Bl = opt_alloc(Bl0, {D,Is}),
+ [{block,Bl}|opt_allocs_1(Is, D)];
+opt_allocs_1([I|Is], D) ->
+ [I|opt_allocs_1(Is, D)];
+opt_allocs_1([], _) -> [].
+
%% opt_alloc(Instructions) -> Instructions'
%% Optimises all allocate instructions.
opt_alloc([{set,[],[],{alloc,Live0,Info0}},
- {set,[],[],{alloc,Live,Info}}|Is]) ->
+ {set,[],[],{alloc,Live,Info}}|Is], D) ->
Live = Live0, %Assertion.
Alloc = combine_alloc(Info0, Info),
I = {set,[],[],{alloc,Live,Alloc}},
- opt_alloc([I|Is]);
-opt_alloc([{set,[],[],{alloc,R,{_,Ns,Nh,[]}}}|Is]) ->
- [{set,[],[],opt_alloc(Is, Ns, Nh, R)}|Is];
-opt_alloc([I|Is]) -> [I|opt_alloc(Is)];
-opt_alloc([]) -> [].
+ opt_alloc([I|Is], D);
+opt_alloc([{set,[],[],{alloc,R,{_,Ns,Nh,[]}}}|Is], D) ->
+ [{set,[],[],opt_alloc(Is, D, Ns, Nh, R)}|Is];
+opt_alloc([I|Is], D) -> [I|opt_alloc(Is, D)];
+opt_alloc([], _) -> [].
combine_alloc({_,Ns,Nh1,Init}, {_,nostack,Nh2,[]}) ->
{zero,Ns,beam_utils:combine_heap_needs(Nh1, Nh2),Init}.
-
+
%% opt_alloc(Instructions, FrameSize, HeapNeed, LivingRegs) -> [Instr]
%% Generates the optimal sequence of instructions for
%% allocating and initalizing the stack frame and needed heap.
-opt_alloc(_Is, nostack, Nh, LivingRegs) ->
+opt_alloc(_Is, _D, nostack, Nh, LivingRegs) ->
{alloc,LivingRegs,{nozero,nostack,Nh,[]}};
-opt_alloc(Is, Ns, Nh, LivingRegs) ->
- InitRegs = init_yreg(Is, 0),
+opt_alloc(Bl, {D,OuterIs}, Ns, Nh, LivingRegs) ->
+ Is = [{block,Bl}|OuterIs],
+ InitRegs = init_yregs(Ns, Is, D),
case count_ones(InitRegs) of
N when N*2 > Ns ->
{alloc,LivingRegs,{nozero,Ns,Nh,gen_init(Ns, InitRegs)}};
@@ -441,19 +521,14 @@ gen_init(Fs, Regs, Y, Acc) when Regs band 1 =:= 0 ->
gen_init(Fs, Regs, Y, Acc) ->
gen_init(Fs, Regs bsr 1, Y+1, Acc).
-%% init_yreg(Instructions, RegSet) -> RegSetInitialized
-%% Calculate the set of initialized y registers.
-
-init_yreg([{set,_,_,{bif,_,_}}|_], Reg) -> Reg;
-init_yreg([{set,_,_,{alloc,_,{gc_bif,_,_}}}|_], Reg) -> Reg;
-init_yreg([{set,_,_,{alloc,_,{put_map,_,_}}}|_], Reg) -> Reg;
-init_yreg([{set,Ds,_,_}|Is], Reg) -> init_yreg(Is, add_yregs(Ds, Reg));
-init_yreg(_Is, Reg) -> Reg.
-
-add_yregs(Ys, Reg) -> foldl(fun(Y, R0) -> add_yreg(Y, R0) end, Reg, Ys).
-
-add_yreg({y,Y}, Reg) -> Reg bor (1 bsl Y);
-add_yreg(_, Reg) -> Reg.
+init_yregs(Y, Is, D) when Y >= 0 ->
+ case beam_utils:is_killed({y,Y}, Is, D) of
+ true ->
+ (1 bsl Y) bor init_yregs(Y-1, Is, D);
+ false ->
+ init_yregs(Y-1, Is, D)
+ end;
+init_yregs(_, _, _) -> 0.
count_ones(Bits) -> count_ones(Bits, 0).
count_ones(0, Acc) -> Acc;
@@ -463,16 +538,34 @@ count_ones(Bits, Acc) ->
%% Calculate the new number of live registers when we move an allocate
%% instruction upwards, passing a 'set' instruction.
-alloc_live_regs({set,Ds,Ss,_}, Regs0) ->
+alloc_live_regs({set,Ds,Ss,_}, Is, Regs0) ->
Rset = x_live(Ss, x_dead(Ds, (1 bsl Regs0)-1)),
- live_regs(0, Rset).
+ Live = live_regs(0, Rset),
+ case ensure_contiguous(Rset, Live) of
+ not_possible ->
+ %% Liveness information (looking forward in the
+ %% instruction stream) can't prove that moving this
+ %% allocation instruction is safe. Now use the annotation
+ %% of defined registers at the beginning of the current
+ %% block to see whether moving would be safe.
+ Def0 = defined_regs(Is, 0),
+ Def = Def0 band ((1 bsl Live) - 1),
+ ensure_contiguous(Rset bor Def, Live);
+ Live ->
+ %% Safe based on liveness information.
+ Live
+ end.
live_regs(N, 0) ->
N;
-live_regs(N, Regs) when Regs band 1 =:= 1 ->
- live_regs(N+1, Regs bsr 1);
-live_regs(_, _) ->
- not_possible.
+live_regs(N, Regs) ->
+ live_regs(N+1, Regs bsr 1).
+
+ensure_contiguous(Regs, Live) ->
+ case (1 bsl Live) - 1 of
+ Regs -> Live;
+ _ -> not_possible
+ end.
x_dead([{x,N}|Rs], Regs) -> x_dead(Rs, Regs band (bnot (1 bsl N)));
x_dead([_|Rs], Regs) -> x_dead(Rs, Regs);
@@ -481,3 +574,120 @@ x_dead([], Regs) -> Regs.
x_live([{x,N}|Rs], Regs) -> x_live(Rs, Regs bor (1 bsl N));
x_live([_|Rs], Regs) -> x_live(Rs, Regs);
x_live([], Regs) -> Regs.
+
+%% defined_regs(ReversedInstructions) -> RegBitmap.
+%% Given a reversed instruction stream, determine the
+%% the registers that are defined.
+
+defined_regs([{'%anno',{def,Def}}|_], Regs) ->
+ Def bor Regs;
+defined_regs([{set,Ds,_,{alloc,Live,_}}|_], Regs) ->
+ x_live(Ds, Regs bor ((1 bsl Live) - 1));
+defined_regs([{set,Ds,_,_}|Is], Regs) ->
+ defined_regs(Is, x_live(Ds, Regs)).
+
+%%%
+%%% Do local common sub expression elimination (CSE) in each block.
+%%%
+
+local_cse([{block,Bl0}|Is]) ->
+ Bl = cse_block(Bl0, orddict:new(), []),
+ [{block,Bl}|local_cse(Is)];
+local_cse([I|Is]) ->
+ [I|local_cse(Is)];
+local_cse([]) -> [].
+
+cse_block([I|Is], Es0, Acc0) ->
+ Es1 = cse_clear(I, Es0),
+ case cse_expr(I) of
+ none ->
+ %% Instruction is not suitable for CSE.
+ cse_block(Is, Es1, [I|Acc0]);
+ {ok,D,Expr} ->
+ %% Suitable instruction. First update the dictionary of
+ %% suitable expressions for the next iteration.
+ Es = cse_add(D, Expr, Es1),
+
+ %% Search for a previous identical expression.
+ case cse_find(Expr, Es0) of
+ error ->
+ %% Nothing found
+ cse_block(Is, Es, [I|Acc0]);
+ Src ->
+ %% Use the previously calculated result.
+ %% Also eliminate any line instruction.
+ Move = {set,[D],[Src],move},
+ case Acc0 of
+ [{set,_,_,{line,_}}|Acc] ->
+ cse_block(Is, Es, [Move|Acc]);
+ [_|_] ->
+ cse_block(Is, Es, [Move|Acc0])
+ end
+ end
+ end;
+cse_block([], _, Acc) ->
+ reverse(Acc).
+
+%% cse_find(Expr, Expressions) -> error | Register.
+%% Find a previously evaluated expression whose result can be reused,
+%% or return 'error' if no such expression is found.
+
+cse_find(Expr, Es) ->
+ case orddict:find(Expr, Es) of
+ {ok,{Src,_}} -> Src;
+ error -> error
+ end.
+
+cse_expr({set,[D],Ss,{bif,N,_}}) ->
+ case D of
+ {fr,_} ->
+ %% There are too many things that can go wrong.
+ none;
+ _ ->
+ {ok,D,{{bif,N},Ss}}
+ end;
+cse_expr({set,[D],Ss,{alloc,_,{gc_bif,N,_}}}) ->
+ {ok,D,{{gc_bif,N},Ss}};
+cse_expr({set,[D],Ss,put_list}) ->
+ {ok,D,{put_list,Ss}};
+cse_expr(_) -> none.
+
+%% cse_clear(Instr, Expressions0) -> Expressions.
+%% Remove all previous expressions that will become
+%% invalid when this instruction is executed. Basically,
+%% an expression is no longer safe to reuse when the
+%% register it has been stored to has been modified, killed,
+%% or if any of the source operands have changed.
+
+cse_clear({set,Ds,_,{alloc,Live,_}}, Es) ->
+ cse_clear_1(Es, Live, Ds);
+cse_clear({set,Ds,_,_}, Es) ->
+ cse_clear_1(Es, all, Ds).
+
+cse_clear_1(Es, Live, Ds0) ->
+ Ds = ordsets:from_list(Ds0),
+ [E || E <- Es, cse_is_safe(E, Live, Ds)].
+
+cse_is_safe({_,{Dst,Interfering}}, Live, Ds) ->
+ ordsets:is_disjoint(Interfering, Ds) andalso
+ case Dst of
+ {x,X} ->
+ X < Live;
+ _ ->
+ true
+ end.
+
+%% cse_add(Dest, Expr, Expressions0) -> Expressions.
+%% Provided that it is safe, add a new expression to the dictionary
+%% of already evaluated expressions.
+
+cse_add(D, {_,Ss}=Expr, Es) ->
+ case member(D, Ss) of
+ false ->
+ Interfering = ordsets:from_list([D|Ss]),
+ orddict:store(Expr, {D,Interfering}, Es);
+ true ->
+ %% Unsafe because the instruction overwrites one of
+ %% source operands.
+ Es
+ end.
diff --git a/lib/compiler/src/beam_bs.erl b/lib/compiler/src/beam_bs.erl
index beb055b23d..5f1b9ed488 100644
--- a/lib/compiler/src/beam_bs.erl
+++ b/lib/compiler/src/beam_bs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -38,8 +38,7 @@ function({function,Name,Arity,CLabel,Is0}, Lc0) ->
{Is,Lc} = bsm_opt(Is1, Lc0),
{{function,Name,Arity,CLabel,Is},Lc}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
diff --git a/lib/compiler/src/beam_bsm.erl b/lib/compiler/src/beam_bsm.erl
index 9a4e7fb133..1c8e0e9854 100644
--- a/lib/compiler/src/beam_bsm.erl
+++ b/lib/compiler/src/beam_bsm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -105,8 +105,7 @@ function({function,Name,Arity,Entry,Is}, FIndex) ->
D = #btb{f=FIndex,index=Index},
{function,Name,Arity,Entry,btb_opt_1(Is, D, [])}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
@@ -125,20 +124,21 @@ btb_opt_1([{test,bs_get_binary2,F,_,[Reg,{atom,all},U,Fs],Reg}=I0|Is], D, Acc0)
end,
btb_opt_1(Is, D, Acc)
end;
-btb_opt_1([{test,bs_get_binary2,F,_,[Ctx,{atom,all},U,Fs],Dst}=I0|Is], D, Acc0) ->
- case btb_reaches_match(Is, [Ctx,Dst], D) of
+btb_opt_1([{test,bs_get_binary2,F,_,[Ctx,{atom,all},U,Fs],Dst}=I0|Is0], D, Acc0) ->
+ case btb_reaches_match(Is0, [Ctx,Dst], D) of
{error,Reason} ->
Comment = btb_comment_no_opt(Reason, Fs),
- btb_opt_1(Is, D, [Comment,I0|Acc0]);
+ btb_opt_1(Is0, D, [Comment,I0|Acc0]);
{ok,MustSave} when U =:= 1 ->
Comment = btb_comment_opt(Fs),
- Acc1 = btb_gen_save(MustSave, Ctx, [Comment|Acc0]),
- Acc = [{move,Ctx,Dst}|Acc1],
+ Acc = btb_gen_save(MustSave, Ctx, [Comment|Acc0]),
+ Is = prepend_move(Ctx, Dst, Is0),
btb_opt_1(Is, D, Acc);
{ok,MustSave} ->
Comment = btb_comment_opt(Fs),
Acc1 = btb_gen_save(MustSave, Ctx, [Comment|Acc0]),
- Acc = [{move,Ctx,Dst},{test,bs_test_unit,F,[Ctx,U]}|Acc1],
+ Acc = [{test,bs_test_unit,F,[Ctx,U]}|Acc1],
+ Is = prepend_move(Ctx, Dst, Is0),
btb_opt_1(Is, D, Acc)
end;
btb_opt_1([I|Is], D, Acc) ->
@@ -151,6 +151,12 @@ btb_gen_save(true, Reg, Acc) ->
[{bs_save2,Reg,{atom,start}}|Acc];
btb_gen_save(false, _, Acc) -> Acc.
+prepend_move(Ctx, Dst, [{block,Bl0}|Is]) ->
+ Bl = [{set,[Dst],[Ctx],move}|Bl0],
+ [{block,Bl}|Is];
+prepend_move(Ctx, Dst, Is) ->
+ [{move,Ctx,Dst}|Is].
+
%% btb_reaches_match([Instruction], [Register], D) ->
%% {ok,MustSave}|{error,Reason}
%%
diff --git a/lib/compiler/src/beam_clean.erl b/lib/compiler/src/beam_clean.erl
index b736d39f9c..207f1c4deb 100644
--- a/lib/compiler/src/beam_clean.erl
+++ b/lib/compiler/src/beam_clean.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@
-export([module/2]).
-export([bs_clean_saves/1]).
-export([clean_labels/1]).
--import(lists, [map/2,foldl/3,reverse/1,filter/2]).
+-import(lists, [foldl/3,reverse/1]).
-spec module(beam_utils:module_code(), [compile:option()]) ->
{'ok',beam_utils:module_code()}.
@@ -118,7 +118,7 @@ add_to_work_list(F, {Fs,Used}=Sets) ->
clean_labels(Fs0) ->
St0 = #st{lmap=[],entry=1,lc=1},
{Fs1,#st{lmap=Lmap0,lc=Lc}} = function_renumber(Fs0, St0, []),
- Lmap = gb_trees:from_orddict(ordsets:from_list(Lmap0)),
+ Lmap = maps:from_list(Lmap0),
Fs = function_replace(Fs1, Lmap, []),
{Fs,Lc}.
@@ -187,7 +187,8 @@ is_record_tuple(_, _, _) -> no.
function_replace([{function,Name,Arity,Entry,Asm0}|Fs], Dict, Acc) ->
Asm = try
- replace(Asm0, [], Dict)
+ Fb = fun(Old) -> throw({error,{undefined_label,Old}}) end,
+ beam_utils:replace_labels(Asm0, [], Dict, Fb)
catch
throw:{error,{undefined_label,Lbl}=Reason} ->
io:format("Function ~s/~w refers to undefined label ~w\n",
@@ -197,57 +198,6 @@ function_replace([{function,Name,Arity,Entry,Asm0}|Fs], Dict, Acc) ->
function_replace(Fs, Dict, [{function,Name,Arity,Entry,Asm}|Acc]);
function_replace([], _, Acc) -> Acc.
-replace([{test,Test,{f,Lbl},Ops}|Is], Acc, D) ->
- replace(Is, [{test,Test,{f,label(Lbl, D)},Ops}|Acc], D);
-replace([{test,Test,{f,Lbl},Live,Ops,Dst}|Is], Acc, D) ->
- replace(Is, [{test,Test,{f,label(Lbl, D)},Live,Ops,Dst}|Acc], D);
-replace([{select,I,R,{f,Fail0},Vls0}|Is], Acc, D) ->
- Vls = map(fun ({f,L}) -> {f,label(L, D)};
- (Other) -> Other
- end, Vls0),
- Fail = label(Fail0, D),
- replace(Is, [{select,I,R,{f,Fail},Vls}|Acc], D);
-replace([{'try',R,{f,Lbl}}|Is], Acc, D) ->
- replace(Is, [{'try',R,{f,label(Lbl, D)}}|Acc], D);
-replace([{'catch',R,{f,Lbl}}|Is], Acc, D) ->
- replace(Is, [{'catch',R,{f,label(Lbl, D)}}|Acc], D);
-replace([{jump,{f,Lbl}}|Is], Acc, D) ->
- replace(Is, [{jump,{f,label(Lbl, D)}}|Acc], D);
-replace([{loop_rec,{f,Lbl},R}|Is], Acc, D) ->
- replace(Is, [{loop_rec,{f,label(Lbl, D)},R}|Acc], D);
-replace([{loop_rec_end,{f,Lbl}}|Is], Acc, D) ->
- replace(Is, [{loop_rec_end,{f,label(Lbl, D)}}|Acc], D);
-replace([{wait,{f,Lbl}}|Is], Acc, D) ->
- replace(Is, [{wait,{f,label(Lbl, D)}}|Acc], D);
-replace([{wait_timeout,{f,Lbl},To}|Is], Acc, D) ->
- replace(Is, [{wait_timeout,{f,label(Lbl, D)},To}|Acc], D);
-replace([{bif,Name,{f,Lbl},As,R}|Is], Acc, D) when Lbl =/= 0 ->
- replace(Is, [{bif,Name,{f,label(Lbl, D)},As,R}|Acc], D);
-replace([{gc_bif,Name,{f,Lbl},Live,As,R}|Is], Acc, D) when Lbl =/= 0 ->
- replace(Is, [{gc_bif,Name,{f,label(Lbl, D)},Live,As,R}|Acc], D);
-replace([{call,Ar,{f,Lbl}}|Is], Acc, D) ->
- replace(Is, [{call,Ar,{f,label(Lbl,D)}}|Acc], D);
-replace([{make_fun2,{f,Lbl},U1,U2,U3}|Is], Acc, D) ->
- replace(Is, [{make_fun2,{f,label(Lbl, D)},U1,U2,U3}|Acc], D);
-replace([{bs_init,{f,Lbl},Info,Live,Ss,Dst}|Is], Acc, D) when Lbl =/= 0 ->
- replace(Is, [{bs_init,{f,label(Lbl, D)},Info,Live,Ss,Dst}|Acc], D);
-replace([{bs_put,{f,Lbl},Info,Ss}|Is], Acc, D) when Lbl =/= 0 ->
- replace(Is, [{bs_put,{f,label(Lbl, D)},Info,Ss}|Acc], D);
-replace([{put_map=I,{f,Lbl},Op,Src,Dst,Live,List}|Is], Acc, D)
- when Lbl =/= 0 ->
- replace(Is, [{I,{f,label(Lbl, D)},Op,Src,Dst,Live,List}|Acc], D);
-replace([{get_map_elements=I,{f,Lbl},Src,List}|Is], Acc, D) when Lbl =/= 0 ->
- replace(Is, [{I,{f,label(Lbl, D)},Src,List}|Acc], D);
-replace([I|Is], Acc, D) ->
- replace(Is, [I|Acc], D);
-replace([], Acc, _) -> Acc.
-
-label(Old, D) ->
- case gb_trees:lookup(Old, D) of
- {value,Val} -> Val;
- none -> throw({error,{undefined_label,Old}})
- end.
-
%%%
%%% Final fixup of bs_start_match2/5,bs_save2/bs_restore2 instructions for
%%% new bit syntax matching (introduced in R11B).
@@ -304,7 +254,7 @@ bs_restores([_|Is], Dict) ->
bs_restores([], Dict) -> Dict.
%% Pass 2.
-bs_replace([{test,bs_start_match2,F,Live,[Src,Ctx],CtxR}|T], Dict, Acc) when is_atom(Ctx) ->
+bs_replace([{test,bs_start_match2,F,Live,[Src,{context,Ctx}],CtxR}|T], Dict, Acc) ->
Slots = case gb_trees:lookup(Ctx, Dict) of
{value,Slots0} -> Slots0;
none -> 0
@@ -353,8 +303,21 @@ maybe_remove_lines(Fs, Opts) ->
end.
remove_lines([{function,N,A,Lbl,Is0}|T]) ->
- Is = filter(fun({line,_}) -> false;
- (_) -> true
- end, Is0),
+ Is = remove_lines_fun(Is0),
[{function,N,A,Lbl,Is}|remove_lines(T)];
remove_lines([]) -> [].
+
+remove_lines_fun([{line,_}|Is]) ->
+ remove_lines_fun(Is);
+remove_lines_fun([{block,Bl0}|Is]) ->
+ Bl = remove_lines_block(Bl0),
+ [{block,Bl}|remove_lines_fun(Is)];
+remove_lines_fun([I|Is]) ->
+ [I|remove_lines_fun(Is)];
+remove_lines_fun([]) -> [].
+
+remove_lines_block([{set,_,_,{line,_}}|Is]) ->
+ remove_lines_block(Is);
+remove_lines_block([I|Is]) ->
+ [I|remove_lines_block(Is)];
+remove_lines_block([]) -> [].
diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl
index d379fdc4eb..efad082152 100644
--- a/lib/compiler/src/beam_dead.erl
+++ b/lib/compiler/src/beam_dead.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -56,8 +56,7 @@ function({function,Name,Arity,CLabel,Is0}, Lc0) ->
Is = move_move_into_block(Is3, []),
{{function,Name,Arity,CLabel,Is},Lc}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
@@ -272,7 +271,8 @@ backward([{jump,{f,To0}},{move,Src,Reg}=Move|Is], D, Acc) ->
end;
backward([{jump,{f,To}}=J|[{bif,Op,{f,BifFail},Ops,Reg}|Is]=Is0], D, Acc) ->
try replace_comp_op(To, Reg, Op, Ops, D) of
- I -> backward(Is, D, I++Acc)
+ {Test,Jump} ->
+ backward([Jump,Test|Is], D, Acc)
catch
throw:not_possible ->
case To =:= BifFail of
@@ -294,24 +294,25 @@ backward([{jump,{f,To}}=J|[{gc_bif,_,{f,To},_,_,_Dst}|Is]], D, Acc) ->
%% register is initialized, and it is therefore no need to test
%% for liveness of the destination register at label To.
backward([J|Is], D, Acc);
-backward([{test,bs_start_match2,F,Live,[R,_]=Args,Ctxt}|Is], D,
- [{test,bs_match_string,F,[Ctxt,Bs]},
- {test,bs_test_tail2,F,[Ctxt,0]}|Acc0]=Acc) ->
+backward([{test,bs_start_match2,F,Live,[Src,_]=Args,Ctxt}|Is], D, Acc0) ->
{f,To0} = F,
- case beam_utils:is_killed(Ctxt, Acc0, D) of
- true ->
- To = shortcut_bs_context_to_binary(To0, R, D),
- Eq = {test,is_eq_exact,{f,To},[R,{literal,Bs}]},
- backward(Is, D, [Eq|Acc0]);
- false ->
- To = shortcut_bs_start_match(To0, R, D),
- I = {test,bs_start_match2,{f,To},Live,Args,Ctxt},
- backward(Is, D, [I|Acc])
+ case test_bs_literal(F, Ctxt, D, Acc0) of
+ {none,Acc} ->
+ %% Ctxt killed immediately after bs_start_match2.
+ To = shortcut_bs_context_to_binary(To0, Src, D),
+ I = {test,is_bitstr,{f,To},[Src]},
+ backward(Is, D, [I|Acc]);
+ {Literal,Acc} ->
+ %% Ctxt killed after matching a literal.
+ To = shortcut_bs_context_to_binary(To0, Src, D),
+ Eq = {test,is_eq_exact,{f,To},[Src,{literal,Literal}]},
+ backward(Is, D, [Eq|Acc]);
+ not_killed ->
+ %% Ctxt not killed. Not much to do.
+ To = shortcut_bs_start_match(To0, Src, D),
+ I = {test,bs_start_match2,{f,To},Live,Args,Ctxt},
+ backward(Is, D, [I|Acc0])
end;
-backward([{test,bs_start_match2,{f,To0},Live,[Src|_]=Info,Dst}|Is], D, Acc) ->
- To = shortcut_bs_start_match(To0, Src, D),
- I = {test,bs_start_match2,{f,To},Live,Info,Dst},
- backward(Is, D, [I|Acc]);
backward([{test,Op,{f,To0},Ops0}|Is], D, Acc) ->
To1 = shortcut_bs_test(To0, Is, D),
To2 = shortcut_label(To1, D),
@@ -391,6 +392,26 @@ backward([{bif,'or',{f,To0},[Dst,{atom,false}],Dst}=I|Is], D,
_ ->
backward(Is, D, [I|Acc])
end;
+backward([{bif,map_get,{f,FF},[Key,Map],_}=I0,
+ {test,has_map_fields,{f,FT}=F,[Map|Keys0]}=I1|Is], D, Acc) when FF =/= 0 ->
+ case shortcut_label(FF, D) of
+ FT ->
+ case lists:delete(Key, Keys0) of
+ [] ->
+ backward([I0|Is], D, Acc);
+ Keys ->
+ Test = {test,has_map_fields,F,[Map|Keys]},
+ backward([Test|Is], D, [I0|Acc])
+ end;
+ _ ->
+ backward([I1|Is], D, [I0|Acc])
+ end;
+backward([{bif,map_get,{f,FF},[_,Map],_}=I0,
+ {test,is_map,{f,FT},[Map]}=I1|Is], D, Acc) when FF =/= 0 ->
+ case shortcut_label(FF, D) of
+ FT -> backward([I0|Is], D, Acc);
+ _ -> backward([I1|Is], D, [I0|Acc])
+ end;
backward([I|Is], D, Acc) ->
backward(Is, D, [I|Acc]);
backward([], _D, Acc) -> Acc.
@@ -446,7 +467,7 @@ prune_redundant([], _) -> [].
replace_comp_op(To, Reg, Op, Ops, D) ->
False = comp_op_find_shortcut(To, Reg, {atom,false}, D),
True = comp_op_find_shortcut(To, Reg, {atom,true}, D),
- [bif_to_test(Op, Ops, False),{jump,{f,True}}].
+ {bif_to_test(Op, Ops, False),{jump,{f,True}}}.
comp_op_find_shortcut(To0, Reg, Val, D) ->
case shortcut_select_label(To0, Reg, Val, D) of
@@ -483,15 +504,22 @@ not_possible() -> throw(not_possible).
%% F1: is_eq_exact F2 Reg Lit2 F1: is_eq_exact F2 Reg Lit2
%% L2: .... L2:
%%
-combine_eqs(To, [Reg,{Type,_}=Lit1]=Ops, D, [{label,L1}|_])
- when Type =:= atom; Type =:= integer ->
+combine_eqs(To, [Reg,{Type,_}=Lit1]=Ops, D, Acc)
+ when Type =:= atom; Type =:= integer ->
+ Next = case Acc of
+ [{label,Lbl}|_] -> Lbl;
+ [{jump,{f,Lbl}}|_] -> Lbl
+ end,
case beam_utils:code_at(To, D) of
[{test,is_eq_exact,{f,F2},[Reg,{Type,_}=Lit2]},
{label,L2}|_] when Lit1 =/= Lit2 ->
- {select,select_val,Reg,{f,F2},[Lit1,{f,L1},Lit2,{f,L2}]};
+ {select,select_val,Reg,{f,F2},[Lit1,{f,Next},Lit2,{f,L2}]};
+ [{test,is_eq_exact,{f,F2},[Reg,{Type,_}=Lit2]},
+ {jump,{f,L2}}|_] when Lit1 =/= Lit2 ->
+ {select,select_val,Reg,{f,F2},[Lit1,{f,Next},Lit2,{f,L2}]};
[{select,select_val,Reg,{f,F2},[{Type,_}|_]=List0}|_] ->
List = remove_from_list(Lit1, List0),
- {select,select_val,Reg,{f,F2},[Lit1,{f,L1}|List]};
+ {select,select_val,Reg,{f,F2},[Lit1,{f,Next}|List]};
_Is ->
{test,is_eq_exact,{f,To},Ops}
end;
@@ -504,6 +532,22 @@ remove_from_list(Lit, [Val,{f,_}=Fail|T]) ->
[Val,Fail|remove_from_list(Lit, T)];
remove_from_list(_, []) -> [].
+
+test_bs_literal(F, Ctxt, D,
+ [{test,bs_match_string,F,[Ctxt,Bs]},
+ {test,bs_test_tail2,F,[Ctxt,0]}|Acc]) ->
+ test_bs_literal_1(Ctxt, Acc, D, Bs);
+test_bs_literal(F, Ctxt, D, [{test,bs_test_tail2,F,[Ctxt,0]}|Acc]) ->
+ test_bs_literal_1(Ctxt, Acc, D, <<>>);
+test_bs_literal(_, Ctxt, D, Acc) ->
+ test_bs_literal_1(Ctxt, Acc, D, none).
+
+test_bs_literal_1(Ctxt, Is, D, Literal) ->
+ case beam_utils:is_killed(Ctxt, Is, D) of
+ true -> {Literal,Is};
+ false -> not_killed
+ end.
+
%% shortcut_bs_test(TargetLabel, ReversedInstructions, D) -> TargetLabel'
%% Try to shortcut the failure label for bit syntax matching.
diff --git a/lib/compiler/src/beam_disasm.erl b/lib/compiler/src/beam_disasm.erl
index 8fd0b36d05..6cee9acae4 100644
--- a/lib/compiler/src/beam_disasm.erl
+++ b/lib/compiler/src/beam_disasm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -163,8 +163,8 @@ pp_instr(I) ->
file(File) ->
try process_chunks(File)
- catch error:Reason ->
- {error,?MODULE,{internal,{Reason,erlang:get_stacktrace()}}}
+ catch error:Reason:Stack ->
+ {error,?MODULE,{internal,{Reason,Stack}}}
end.
%%-----------------------------------------------------------------------
@@ -719,42 +719,6 @@ resolve_inst({wait,[Lbl]},_,_,_) ->
{wait,Lbl};
resolve_inst({wait_timeout,[Lbl,Int]},_,_,_) ->
{wait_timeout,Lbl,resolve_arg(Int)};
-resolve_inst({m_plus,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'+',W,[SrcR1,SrcR2],DstR};
-resolve_inst({m_minus,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'-',W,[SrcR1,SrcR2],DstR};
-resolve_inst({m_times,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'*',W,[SrcR1,SrcR2],DstR};
-resolve_inst({m_div,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'/',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_div,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'div',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_rem,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'rem',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_band,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'band',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_bor,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'bor',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_bxor,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'bxor',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_bsl,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'bsl',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_bsr,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'bsr',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_bnot,Args},_,_,_) ->
- [W,SrcR,DstR] = resolve_args(Args),
- {arithbif,'bnot',W,[SrcR],DstR};
resolve_inst({is_lt=I,Args0},_,_,_) ->
[L|Args] = resolve_args(Args0),
{test,I,L,Args};
@@ -800,9 +764,6 @@ resolve_inst({is_nil=I,Args0},_,_,_) ->
resolve_inst({is_binary=I,Args0},_,_,_) ->
[L|Args] = resolve_args(Args0),
{test,I,L,Args};
-resolve_inst({is_constant=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
resolve_inst({is_list=I,Args0},_,_,_) ->
[L|Args] = resolve_args(Args0),
{test,I,L,Args};
@@ -840,11 +801,6 @@ resolve_inst({get_tuple_element,[Src,{u,Off},Dst]},_,_,_) ->
{get_tuple_element,resolve_arg(Src),Off,resolve_arg(Dst)};
resolve_inst({set_tuple_element,[Src,Dst,{u,Off}]},_,_,_) ->
{set_tuple_element,resolve_arg(Src),resolve_arg(Dst),Off};
-resolve_inst({put_string,[{u,Len},{u,Off},Dst]},_,Strings,_) ->
- String = if Len > 0 -> binary_to_list(Strings, Off+1, Off+Len);
- true -> ""
- end,
- {put_string,Len,{string,String},Dst};
resolve_inst({put_list,[Src1,Src2,Dst]},_,_,_) ->
{put_list,resolve_arg(Src1),resolve_arg(Src2),Dst};
resolve_inst({put_tuple,[{u,Arity},Dst]},_,_,_) ->
@@ -859,9 +815,6 @@ resolve_inst({case_end,[X]},_,_,_) ->
{case_end,resolve_arg(X)};
resolve_inst({call_fun,[{u,N}]},_,_,_) ->
{call_fun,N};
-resolve_inst({make_fun,Args},_,_,Lbls) ->
- [{f,L},Magic,FreeVars] = resolve_args(Args),
- {make_fun,lookup(L,Lbls),Magic,FreeVars};
resolve_inst({is_function=I,Args0},_,_,_) ->
[L|Args] = resolve_args(Args0),
{test,I,L,Args};
@@ -870,30 +823,6 @@ resolve_inst({call_ext_only,[{u,N},{u,MFAix}]},Imports,_,_) ->
%%
%% Instructions for handling binaries added in R7A & R7B
%%
-resolve_inst({bs_start_match,[F,Reg]},_,_,_) ->
- {bs_start_match,F,Reg};
-resolve_inst({bs_get_integer=I,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
- [A2,A5] = resolve_args([Arg2,Arg5]),
- {test,I,Lbl,[A2,N,decode_field_flags(U),A5]};
-resolve_inst({bs_get_float=I,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
- [A2,A5] = resolve_args([Arg2,Arg5]),
- {test,I,Lbl,[A2,N,decode_field_flags(U),A5]};
-resolve_inst({bs_get_binary=I,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
- [A2,A5] = resolve_args([Arg2,Arg5]),
- {test,I,Lbl,[A2,N,decode_field_flags(U),A5]};
-resolve_inst({bs_skip_bits,[Lbl,Arg2,{u,N},{u,U}]},_,_,_) ->
- A2 = resolve_arg(Arg2),
- {test,bs_skip_bits,Lbl,[A2,N,decode_field_flags(U)]};
-resolve_inst({bs_test_tail,[F,{u,N}]},_,_,_) ->
- {test,bs_test_tail,F,[N]};
-resolve_inst({bs_save,[{u,N}]},_,_,_) ->
- {bs_save,N};
-resolve_inst({bs_restore,[{u,N}]},_,_,_) ->
- {bs_restore,N};
-resolve_inst({bs_init,[{u,N},{u,U}]},_,_,_) ->
- {bs_init,N,decode_field_flags(U)};
-resolve_inst({bs_final,[F,X]},_,_,_) ->
- {bs_final,F,X};
resolve_inst({bs_put_integer,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
[A2,A5] = resolve_args([Arg2,Arg5]),
{bs_put_integer,Lbl,A2,N,decode_field_flags(U),A5};
@@ -908,8 +837,6 @@ resolve_inst({bs_put_string,[{u,Len},{u,Off}]},_,Strings,_) ->
true -> ""
end,
{bs_put_string,Len,{string,String}};
-resolve_inst({bs_need_buf,[{u,N}]},_,_,_) ->
- {bs_need_buf,N};
%%
%% Instructions for handling floating point numbers added in June 2001 (R8).
@@ -961,9 +888,6 @@ resolve_inst({raise,[_Reg1,_Reg2]=Regs},_,_,_) ->
resolve_inst({bs_init2,[Lbl,Arg2,{u,W},{u,R},{u,F},Arg6]},_,_,_) ->
[A2,A6] = resolve_args([Arg2,Arg6]),
{bs_init2,Lbl,A2,W,R,decode_field_flags(F),A6};
-resolve_inst({bs_bits_to_bytes,[Lbl,Arg2,Arg3]},_,_,_) ->
- [A2,A3] = resolve_args([Arg2,Arg3]),
- {bs_bits_to_bytes,Lbl,A2,A3};
resolve_inst({bs_add=I,[Lbl,Arg2,Arg3,Arg4,Arg5]},_,_,_) ->
[A2,A3,A4,A5] = resolve_args([Arg2,Arg3,Arg4,Arg5]),
{I,Lbl,[A2,A3,A4],A5};
@@ -1041,12 +965,6 @@ resolve_inst({gc_bif3,Args},Imports,_,_) ->
{gc_bif,BifName,F,Live,[A1,A2,A3],Reg};
%%
-%% New instructions for creating non-byte aligned binaries.
-%%
-resolve_inst({bs_final2,[X,Y]},_,_,_) ->
- {bs_final2,X,Y};
-
-%%
%% R11B-5.
%%
resolve_inst({is_bitstr=I,Args0},_,_,_) ->
@@ -1165,6 +1083,19 @@ resolve_inst({get_map_elements,Args0},_,_,_) ->
{get_map_elements,FLbl,Src,{list,List}};
%%
+%% OTP 21.
+%%
+
+resolve_inst({build_stacktrace,[]},_,_,_) ->
+ build_stacktrace;
+resolve_inst({raw_raise,[]},_,_,_) ->
+ raw_raise;
+resolve_inst({get_hd,[Src,Dst]},_,_,_) ->
+ {get_hd,Src,Dst};
+resolve_inst({get_tl,[Src,Dst]},_,_,_) ->
+ {get_tl,Src,Dst};
+
+%%
%% Catches instructions that are not yet handled.
%%
resolve_inst(X,_,_,_) -> ?exit({resolve_inst,X}).
diff --git a/lib/compiler/src/beam_disasm.hrl b/lib/compiler/src/beam_disasm.hrl
index d968cd9587..e8ebfc4cfc 100644
--- a/lib/compiler/src/beam_disasm.hrl
+++ b/lib/compiler/src/beam_disasm.hrl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,8 @@
%% IT SHOULD BE MOVED TO A FILE THAT DEFINES (AND EXPORTS)
%% PROPER TYPES FOR THE SET OF BEAM INSTRUCTIONS.
%%
--type beam_instr() :: 'bs_init_writable' | 'fclearerror' | 'if_end'
+-type beam_instr() :: 'bs_init_writable' | 'build_stacktrace'
+ | 'fclearerror' | 'if_end' | 'raw_raise'
| 'remove_message' | 'return' | 'send' | 'timeout'
| tuple(). %% XXX: Very underspecified - FIX THIS
diff --git a/lib/compiler/src/beam_except.erl b/lib/compiler/src/beam_except.erl
index 9801c68ee2..05c0f4fbc7 100644
--- a/lib/compiler/src/beam_except.erl
+++ b/lib/compiler/src/beam_except.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -45,8 +45,7 @@ function({function,Name,Arity,CLabel,Is0}) ->
Is = function_1(Is0),
{function,Name,Arity,CLabel,Is}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
diff --git a/lib/compiler/src/beam_flatten.erl b/lib/compiler/src/beam_flatten.erl
index a4d45a4ca6..20bd23a912 100644
--- a/lib/compiler/src/beam_flatten.erl
+++ b/lib/compiler/src/beam_flatten.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -50,6 +50,9 @@ norm_block([{set,[],[],{alloc,R,Alloc}}|Is], Acc0) ->
Acc ->
norm_block(Is, Acc)
end;
+norm_block([{set,[D1],[S],get_hd},{set,[D2],[S],get_tl}|Is], Acc) ->
+ I = {get_list,S,D1,D2},
+ norm_block(Is, [I|Acc]);
norm_block([I|Is], Acc) -> norm_block(Is, [norm(I)|Acc]);
norm_block([], Acc) -> Acc.
@@ -64,12 +67,14 @@ norm({set,[D],[],{put_tuple,A}}) -> {put_tuple,A,D};
norm({set,[],[S],put}) -> {put,S};
norm({set,[D],[S],{get_tuple_element,I}}) -> {get_tuple_element,S,I,D};
norm({set,[],[S,D],{set_tuple_element,I}}) -> {set_tuple_element,S,D,I};
-norm({set,[D1,D2],[S],get_list}) -> {get_list,S,D1,D2};
+norm({set,[D],[S],get_hd}) -> {get_hd,S,D};
+norm({set,[D],[S],get_tl}) -> {get_tl,S,D};
norm({set,[D],[S|Puts],{alloc,R,{put_map,Op,F}}}) ->
{put_map,F,Op,S,D,R,{list,Puts}};
norm({set,[],[],remove_message}) -> remove_message;
norm({set,[],[],fclearerror}) -> fclearerror;
-norm({set,[],[],fcheckerror}) -> {fcheckerror,{f,0}}.
+norm({set,[],[],fcheckerror}) -> {fcheckerror,{f,0}};
+norm({set,[],[],{line,_}=Line}) -> Line.
norm_allocate({_Zero,nostack,Nh,[]}, Regs) ->
[{test_heap,Nh,Regs}];
diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl
index 4365451356..9eee56d604 100644
--- a/lib/compiler/src/beam_jump.erl
+++ b/lib/compiler/src/beam_jump.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -71,9 +71,9 @@
%%%
%%% jump L2
%%% . . .
-%%% L1:
%%% L2: ...
%%%
+%%% and all preceding uses of L1 renamed to L2.
%%% If the jump is unreachable, it will be removed according to (1).
%%%
%%% (5) In
@@ -275,14 +275,15 @@ extract_seq_1(_, _) -> no.
-record(st,
{
entry :: beam_asm:label(), %Entry label (must not be moved).
- mlbl :: #{beam_asm:label() := [beam_asm:label()]}, %Moved labels.
- labels :: cerl_sets:set() %Set of referenced labels.
+ replace :: #{beam_asm:label() := beam_asm:label()}, %Labels to replace.
+ labels :: cerl_sets:set(), %Set of referenced labels.
+ index :: beam_utils:code_index() | {lazy,[beam_utils:instruction()]} %Index built lazily only if needed
}).
opt(Is0, CLabel) ->
find_fixpoint(fun(Is) ->
Lbls = initial_labels(Is),
- St = #st{entry=CLabel,mlbl=#{},labels=Lbls},
+ St = #st{entry=CLabel,replace=#{},labels=Lbls,index={lazy,Is}},
opt(Is, [], St)
end, Is0).
@@ -292,7 +293,7 @@ find_fixpoint(OptFun, Is0) ->
Is -> find_fixpoint(OptFun, Is)
end.
-opt([{test,_,{f,L}=Lbl,_}=I|[{jump,{f,L}}|_]=Is], Acc, St) ->
+opt([{test,_,{f,L}=Lbl,_}=I|[{jump,{f,L}}|_]=Is], Acc0, St0) ->
%% We have
%% Test Label Ops
%% jump Label
@@ -301,10 +302,23 @@ opt([{test,_,{f,L}=Lbl,_}=I|[{jump,{f,L}}|_]=Is], Acc, St) ->
case beam_utils:is_pure_test(I) of
false ->
%% Test is not pure; we must keep it.
- opt(Is, [I|Acc], label_used(Lbl, St));
+ opt(Is, [I|Acc0], label_used(Lbl, St0));
true ->
%% The test is pure and its failure label is the same
%% as in the jump that follows -- thus it is not needed.
+ %% Check if any of the previous instructions could also be eliminated.
+ {Acc,St} = opt_useless_loads(Acc0, L, St0),
+ opt(Is, Acc, St)
+ end;
+opt([{test,_,{f,L}=Lbl,_}=I|[{label,L}|_]=Is], Acc0, St0) ->
+ %% Similar to the above, except we have a fall-through rather than jump
+ %% Test Label Ops
+ %% label Label
+ case beam_utils:is_pure_test(I) of
+ false ->
+ opt(Is, [I|Acc0], label_used(Lbl, St0));
+ true ->
+ {Acc,St} = opt_useless_loads(Acc0, L, St0),
opt(Is, Acc, St)
end;
opt([{test,Test0,{f,L}=Lbl,Ops}=I|[{jump,To}|Is]=Is0], Acc, St) ->
@@ -326,30 +340,16 @@ opt([{test,_,{f,_}=Lbl,_,_,_}=I|Is], Acc, St) ->
opt(Is, [I|Acc], label_used(Lbl, St));
opt([{select,_,_R,Fail,Vls}=I|Is], Acc, St) ->
skip_unreachable(Is, [I|Acc], label_used([Fail|Vls], St));
-opt([{label,Lbl}=I|Is], Acc, #st{mlbl=Mlbl}=St0) ->
- case maps:find(Lbl, Mlbl) of
- {ok,Lbls} ->
- %% Essential to remove the list of labels from the dictionary,
- %% since we will rescan the inserted labels. We MUST rescan.
- St = St0#st{mlbl=maps:remove(Lbl, Mlbl)},
- insert_labels([Lbl|Lbls], Is, Acc, St);
- error ->
- opt(Is, [I|Acc], St0)
- end;
+opt([{label,From}=I,{label,To}|Is], Acc, #st{replace=Replace}=St) ->
+ opt([I|Is], Acc, St#st{replace=Replace#{To => From}});
opt([{jump,{f,_}=X}|[{label,_},{jump,X}|_]=Is], Acc, St) ->
opt(Is, Acc, St);
opt([{jump,{f,Lbl}}|[{label,Lbl}|_]=Is], Acc, St) ->
opt(Is, Acc, St);
-opt([{jump,{f,L}=Lbl}=I|Is], Acc0, #st{mlbl=Mlbl0}=St0) ->
- %% All labels before this jump instruction should now be
- %% moved to the location of the jump's target.
- {Lbls,Acc} = collect_labels(Acc0, St0),
- St = case Lbls of
- [] -> St0;
- [_|_] ->
- Mlbl = maps_append_list(L, Lbls, Mlbl0),
- St0#st{mlbl=Mlbl}
- end,
+opt([{jump,{f,L}=Lbl}=I|Is], Acc0, St0) ->
+ %% Replace all labels before this jump instruction into the
+ %% location of the jump's target.
+ {Acc,St} = collect_labels(Acc0, L, St0),
skip_unreachable(Is, [I|Acc], label_used(Lbl, St));
%% Optimization: quickly handle some common instructions that don't
%% have any failure labels and where is_unreachable_after(I) =:= false.
@@ -369,36 +369,72 @@ opt([I|Is], Acc, #st{labels=Used0}=St0) ->
true -> skip_unreachable(Is, [I|Acc], St);
false -> opt(Is, [I|Acc], St)
end;
-opt([], Acc, #st{mlbl=Mlbl}) ->
- Code = reverse(Acc),
- insert_fc_labels(Code, Mlbl).
-
-insert_fc_labels([{label,L}=I|Is0], Mlbl) ->
- case maps:find(L, Mlbl) of
- error ->
- [I|insert_fc_labels(Is0, Mlbl)];
- {ok,Lbls} ->
- Is = [{label,Lb} || Lb <- Lbls] ++ Is0,
- [I|insert_fc_labels(Is, maps:remove(L, Mlbl))]
+opt([], Acc, #st{replace=Replace0}) when Replace0 =/= #{} ->
+ Replace = normalize_replace(maps:to_list(Replace0), Replace0, []),
+ beam_utils:replace_labels(Acc, [], Replace, fun(Old) -> Old end);
+opt([], Acc, #st{replace=Replace}) when Replace =:= #{} ->
+ reverse(Acc).
+
+normalize_replace([{From,To0}|Rest], Replace, Acc) ->
+ case Replace of
+ #{To0 := To} ->
+ normalize_replace([{From,To}|Rest], Replace, Acc);
+ _ ->
+ normalize_replace(Rest, Replace, [{From,To0}|Acc])
end;
-insert_fc_labels([_|_]=Is, _) -> Is.
-
-maps_append_list(K,Vs,M) ->
- case M of
- #{K:=Vs0} -> M#{K:=Vs0++Vs}; % same order as dict
- _ -> M#{K => Vs}
- end.
+normalize_replace([], _Replace, Acc) ->
+ maps:from_list(Acc).
+
+%% After eliminating a test, it might happen, that a register was only used
+%% in this test. Let's check if that was the case and if it was so, we can
+%% eliminate the load into the register completely.
+opt_useless_loads([{block,_}|_]=Is, L, #st{index={lazy,FIs}}=St) ->
+ opt_useless_loads(Is, L, St#st{index=beam_utils:index_labels(FIs)});
+opt_useless_loads([{block,Block0}|Is], L, #st{index=Index}=St) ->
+ case opt_useless_block_loads(Block0, L, Index) of
+ [] ->
+ opt_useless_loads(Is, L, St);
+ [_|_]=Block ->
+ {[{block,Block}|Is],St}
+ end;
+%% After eliminating the test and useless blocks, it might happen,
+%% that the previous test could also be eliminated.
+%% It might be that the label was already marked as used, even if ultimately,
+%% it never will be - we can't do much about it at that point, though
+opt_useless_loads([{test,_,{f,L},_}=I|Is], L, St) ->
+ case beam_utils:is_pure_test(I) of
+ false ->
+ {[I|Is],St};
+ true ->
+ opt_useless_loads(Is, L, St)
+ end;
+opt_useless_loads(Is, _L, St) ->
+ {Is,St}.
+
+opt_useless_block_loads([{set,[Dst],_,_}=I|Is], L, Index) ->
+ BlockJump = [{block,Is},{jump,{f,L}}],
+ case beam_utils:is_killed(Dst, BlockJump, Index) of
+ true ->
+ %% The register is killed and not used, we can remove the load
+ opt_useless_block_loads(Is, L, Index);
+ false ->
+ [I|opt_useless_block_loads(Is, L, Index)]
+ end;
+opt_useless_block_loads([I|Is], L, Index) ->
+ [I|opt_useless_block_loads(Is, L, Index)];
+opt_useless_block_loads([], _L, _Index) ->
+ [].
-collect_labels(Is, #st{entry=Entry}) ->
- collect_labels_1(Is, Entry, []).
+collect_labels(Is, Label, #st{entry=Entry,replace=Replace} = St) ->
+ collect_labels_1(Is, Label, Entry, Replace, St).
-collect_labels_1([{label,Entry}|_]=Is, Entry, Acc) ->
+collect_labels_1([{label,Entry}|_]=Is, _Label, Entry, Acc, St) ->
%% Never move the entry label.
- {Acc,Is};
-collect_labels_1([{label,L}|Is], Entry, Acc) ->
- collect_labels_1(Is, Entry, [L|Acc]);
-collect_labels_1(Is, _Entry, Acc) ->
- {Acc,Is}.
+ {Is,St#st{replace=Acc}};
+collect_labels_1([{label,L}|Is], Label, Entry, Acc, St) ->
+ collect_labels_1(Is, Label, Entry, Acc#{L => Label}, St);
+collect_labels_1(Is, _Label, _Entry, Acc, St) ->
+ {Is,St#st{replace=Acc}}.
%% label_defined(Is, Label) -> true | false.
%% Test whether the label Label is defined at the start of the instruction
@@ -418,13 +454,6 @@ invert_test(is_eq_exact) -> is_ne_exact;
invert_test(is_ne_exact) -> is_eq_exact;
invert_test(_) -> not_possible.
-insert_labels([L|Ls], Is, [{jump,{f,L}}|Acc], St) ->
- insert_labels(Ls, [{label,L}|Is], Acc, St);
-insert_labels([L|Ls], Is, Acc, St) ->
- insert_labels(Ls, [{label,L}|Is], Acc, St);
-insert_labels([], Is, Acc, St) ->
- opt(Is, Acc, St).
-
%% skip_unreachable([Instruction], St).
%% Remove all instructions (including definitions of labels
%% that have not been referenced yet) up to the next
diff --git a/lib/compiler/src/beam_listing.erl b/lib/compiler/src/beam_listing.erl
index 94b47cf568..518b958794 100644
--- a/lib/compiler/src/beam_listing.erl
+++ b/lib/compiler/src/beam_listing.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,14 +23,13 @@
-include("core_parse.hrl").
-include("v3_kernel.hrl").
--include("v3_life.hrl").
+-include("beam_disasm.hrl").
-import(lists, [foreach/2]).
-type code() :: cerl:c_module()
| beam_utils:module_code()
| #k_mdef{}
- | {module(),_,_,_} %v3_life
| [_]. %form-based format
-spec module(file:io_device(), code()) -> 'ok'.
@@ -42,13 +41,9 @@ module(File, #k_mdef{}=Kern) ->
%% This is a kernel module.
io:put_chars(File, v3_kernel_pp:format(Kern));
%%io:put_chars(File, io_lib:format("~p~n", [Kern]));
-module(File, {Mod,Exp,Attr,Kern}) ->
- %% This is output from beam_life (v3).
- io:fwrite(File, "~w.~n~p.~n~p.~n", [Mod,Exp,Attr]),
- foreach(fun (F) -> function(File, F) end, Kern);
module(Stream, {Mod,Exp,Attr,Code,NumLabels}) ->
- %% This is output from beam_codegen.
- io:format(Stream, "{module, ~p}. %% version = ~w\n",
+ %% This is output from v3_codegen.
+ io:format(Stream, "{module, ~p}. %% version = ~w\n",
[Mod, beam_opcodes:format_number()]),
io:format(Stream, "\n{exports, ~p}.\n", [Exp]),
io:format(Stream, "\n{attributes, ~p}.\n", [Attr]),
@@ -68,60 +63,3 @@ format_asm([{label,L}|Is]) ->
format_asm([I|Is]) ->
[io_lib:format(" ~p", [I]),".\n"|format_asm(Is)];
format_asm([]) -> [].
-
-function(File, {function,Name,Arity,Args,Body,Vdb,_Anno}) ->
- io:nl(File),
- io:format(File, "function ~p/~p.\n", [Name,Arity]),
- io:format(File, " ~p.\n", [Args]),
- print_vdb(File, Vdb),
- put(beam_listing_nl, false),
- nl(File),
- foreach(fun(F) -> format(File, F, []) end, Body),
- nl(File),
- erase(beam_listing_nl).
-
-format(File, #l{ke=Ke,i=I,vdb=Vdb}, Ind) ->
- nl(File),
- ind_format(File, Ind, "~p ", [I]),
- print_vdb(File, Vdb),
- nl(File),
- format(File, Ke, Ind);
-format(File, Tuple, Ind) when is_tuple(Tuple) ->
- ind_format(File, Ind, "{", []),
- format_list(File, tuple_to_list(Tuple), [$\s|Ind]),
- ind_format(File, Ind, "}", []);
-format(File, List, Ind) when is_list(List) ->
- ind_format(File, Ind, "[", []),
- format_list(File, List, [$\s|Ind]),
- ind_format(File, Ind, "]", []);
-format(File, F, Ind) ->
- ind_format(File, Ind, "~p", [F]).
-
-format_list(File, [F], Ind) ->
- format(File, F, Ind);
-format_list(File, [F|Fs], Ind) ->
- format(File, F, Ind),
- ind_format(File, Ind, ",", []),
- format_list(File, Fs, Ind);
-format_list(_, [], _) -> ok.
-
-
-print_vdb(File, [{Var,F,E}|Vs]) ->
- io:format(File, "~p:~p..~p ", [Var,F,E]),
- print_vdb(File, Vs);
-print_vdb(_, []) -> ok.
-
-ind_format(File, Ind, Format, Args) ->
- case get(beam_listing_nl) of
- true ->
- put(beam_listing_nl, false),
- io:put_chars(File, Ind);
- false -> ok
- end,
- io:format(File, Format, Args).
-
-nl(File) ->
- case put(beam_listing_nl, true) of
- true -> ok;
- false -> io:nl(File)
- end.
diff --git a/lib/compiler/src/beam_peep.erl b/lib/compiler/src/beam_peep.erl
index 6df5c02334..2b8dd40e29 100644
--- a/lib/compiler/src/beam_peep.erl
+++ b/lib/compiler/src/beam_peep.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -41,8 +41,7 @@ function({function,Name,Arity,CLabel,Is0}) ->
Is = beam_jump:remove_unused_labels(Is1),
{function,Name,Arity,CLabel,Is}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
@@ -78,6 +77,12 @@ peep([{bif,tuple_size,_,[_]=Ops,Dst}=I|Is], SeenTests0, Acc) ->
%% Kill all remembered tests that depend on the destination register.
SeenTests = kill_seen(Dst, SeenTests1),
peep(Is, SeenTests, [I|Acc]);
+peep([{bif,map_get,_,[Key,Map],Dst}=I|Is], SeenTests0, Acc) ->
+ %% Pretend that we have seen {test,has_map_fields,_,[Map,Key]}
+ SeenTests1 = gb_sets:add({has_map_fields,[Map,Key]}, SeenTests0),
+ %% Kill all remembered tests that depend on the destination register.
+ SeenTests = kill_seen(Dst, SeenTests1),
+ peep(Is, SeenTests, [I|Acc]);
peep([{bif,_,_,_,Dst}=I|Is], SeenTests0, Acc) ->
%% Kill all remembered tests that depend on the destination register.
SeenTests = kill_seen(Dst, SeenTests0),
@@ -89,15 +94,37 @@ peep([{gc_bif,_,_,_,_,Dst}=I|Is], SeenTests0, Acc) ->
peep([{jump,{f,L}},{label,L}=I|Is], _, Acc) ->
%% Sometimes beam_jump has missed this optimization.
peep(Is, gb_sets:empty(), [I|Acc]);
-peep([{select,Op,R,F,Vls0}|Is], _, Acc) ->
+peep([{select,Op,R,F,Vls0}|Is], SeenTests0, Acc0) ->
case prune_redundant_values(Vls0, F) of
[] ->
%% No values left. Must convert to plain jump.
I = {jump,F},
- peep(Is, gb_sets:empty(), [I|Acc]);
+ peep([I|Is], gb_sets:empty(), Acc0);
+ [{atom,_}=Value,Lbl] when Op =:= select_val ->
+ %% Single value left. Convert to regular test and pop redundant tests.
+ Is1 = [{test,is_eq_exact,F,[R,Value]},{jump,Lbl}|Is],
+ case Acc0 of
+ [{test,is_atom,F,[R]}|Acc] ->
+ peep(Is1, SeenTests0, Acc);
+ _ ->
+ peep(Is1, SeenTests0, Acc0)
+ end;
+ [{integer,_}=Value,Lbl] when Op =:= select_val ->
+ %% Single value left. Convert to regular test and pop redundant tests.
+ Is1 = [{test,is_eq_exact,F,[R,Value]},{jump,Lbl}|Is],
+ case Acc0 of
+ [{test,is_integer,F,[R]}|Acc] ->
+ peep(Is1, SeenTests0, Acc);
+ _ ->
+ peep(Is1, SeenTests0, Acc0)
+ end;
+ [Arity,Lbl] when Op =:= select_tuple_arity ->
+ %% Single value left. Convert to regular test
+ Is1 = [{test,test_arity,F,[R,Arity]},{jump,Lbl}|Is],
+ peep(Is1, SeenTests0, Acc0);
[_|_]=Vls ->
I = {select,Op,R,F,Vls},
- peep(Is, gb_sets:empty(), [I|Acc])
+ peep(Is, gb_sets:empty(), [I|Acc0])
end;
peep([{test,Op,_,Ops}=I|Is], SeenTests0, Acc) ->
case beam_utils:is_pure_test(I) of
diff --git a/lib/compiler/src/beam_receive.erl b/lib/compiler/src/beam_receive.erl
index 1403e1e05e..ddbe67605a 100644
--- a/lib/compiler/src/beam_receive.erl
+++ b/lib/compiler/src/beam_receive.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -82,8 +82,7 @@ function({function,Name,Arity,Entry,Is}) ->
D = beam_utils:index_labels(Is),
{function,Name,Arity,Entry,opt(Is, D, [])}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
@@ -207,6 +206,8 @@ opt_update_regs({label,Lbl}, R, L) ->
%% A catch label for a previously seen catch instruction is OK.
{R,L}
end;
+opt_update_regs({'try',_,{f,Lbl}}, R, L) ->
+ {R,gb_sets:add(Lbl, L)};
opt_update_regs({try_end,_}, R, L) ->
{R,L};
opt_update_regs({line,_}, R, L) ->
diff --git a/lib/compiler/src/beam_record.erl b/lib/compiler/src/beam_record.erl
index 419089b1bc..58a6de6775 100644
--- a/lib/compiler/src/beam_record.erl
+++ b/lib/compiler/src/beam_record.erl
@@ -15,19 +15,12 @@
%%
%% %CopyrightEnd%
%%
-%% File: beam_record.erl
-%% Author: Björn-Egil Dahlberg
-%% Created: 2014-09-03
-%%
-
--module(beam_record).
--export([module/2]).
%% Rewrite the instruction stream on tagged tuple tests.
-%% Tagged tuples means a tuple of any arity with an atom as its first element.
-%% Typically records, ok-tuples and error-tuples.
-%%
-%% from:
+%% Tagged tuples means a tuple of any arity with an atom as its
+%% first element, such as records and error tuples.
+%%
+%% From:
%% ...
%% {test,is_tuple,Fail,[Src]}.
%% {test,test_arity,Fail,[Src,Sz]}.
@@ -36,13 +29,16 @@
%% ...
%% {test,is_eq_exact,Fail,[Dst,Atom]}.
%% ...
-%% to:
+%% To:
%% ...
%% {test,is_tagged_tuple,Fail,[Src,Sz,Atom]}.
%% ...
+%%
+-module(beam_record).
+-export([module/2]).
--import(lists, [reverse/1]).
+-import(lists, [reverse/1,reverse/2]).
-spec module(beam_utils:module_code(), [compile:option()]) ->
{'ok',beam_utils:module_code()}.
@@ -51,56 +47,85 @@ module({Mod,Exp,Attr,Fs0,Lc}, _Opt) ->
Fs = [function(F) || F <- Fs0],
{ok,{Mod,Exp,Attr,Fs,Lc}}.
-function({function,Name,Arity,CLabel,Is}) ->
+function({function,Name,Arity,CLabel,Is0}) ->
try
- Idx = beam_utils:index_labels(Is),
- {function,Name,Arity,CLabel,rewrite(Is,Idx)}
+ Is1 = beam_utils:anno_defs(Is0),
+ Idx = beam_utils:index_labels(Is1),
+ Is = rewrite(reverse(Is1), Idx),
+ {function,Name,Arity,CLabel,Is}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
-rewrite(Is,Idx) ->
- rewrite(Is,Idx,[]).
+rewrite(Is, Idx) ->
+ rewrite(Is, Idx, 0, []).
-rewrite([{test,is_tuple,Fail,[Src]}=I1,
- {test,test_arity,Fail,[Src,N]}=I2|Is],Idx,Acc) ->
- case is_tagged_tuple(Is,Fail,Src,Idx) of
+rewrite([{test,test_arity,Fail,[Src,N]}=TA,
+ {test,is_tuple,Fail,[Src]}=TT|Is], Idx, Def, Acc0) ->
+ case is_tagged_tuple(Acc0, Def, Fail, Src, Idx) of
no ->
- rewrite(Is,Idx,[I2,I1|Acc]);
- {Atom,[{block,[]}|Is1]} ->
- rewrite(Is1,Idx,[{test,is_tagged_tuple,Fail,[Src,N,Atom]}|Acc]);
- {Atom,Is1} ->
- rewrite(Is1,Idx,[{test,is_tagged_tuple,Fail,[Src,N,Atom]}|Acc])
+ rewrite(Is, Idx, 0, [TT,TA|Acc0]);
+ {yes,Atom,Acc} ->
+ I = {test,is_tagged_tuple,Fail,[Src,N,Atom]},
+ rewrite(Is, Idx, Def, [I|Acc])
end;
-rewrite([I|Is],Idx,Acc) ->
- rewrite(Is,Idx,[I|Acc]);
-rewrite([],_,Acc) -> reverse(Acc).
-
-is_tagged_tuple([{block,[{set,[Dst],[Src],{get_tuple_element,0}}=B|Bs]},
- {test,is_eq_exact,Fail,[Dst,{atom,_}=Atom]}|Is],Fail,Src,Idx) ->
+rewrite([{block,[{'%anno',{def,Def}}|Bl]}|Is], Idx, _Def, Acc) ->
+ rewrite(Is, Idx, Def, [{block,Bl}|Acc]);
+rewrite([{label,L}=I|Is], Idx0, Def, Acc) ->
+ Idx = beam_utils:index_label(L, Acc, Idx0),
+ rewrite(Is, Idx, Def, [I|Acc]);
+rewrite([I|Is], Idx, Def, Acc) ->
+ rewrite(Is, Idx, Def, [I|Acc]);
+rewrite([], _, _, Acc) -> Acc.
- %% if Dst is killed in the instruction stream and at fail label,
- %% we can safely remove get_tuple_element.
- %%
- %% if Dst is not killed in the stream, we cannot remove get_tuple_element
- %% since it is referenced.
-
- case is_killed(Dst,Is,Fail,Idx) of
- true -> {Atom,[{block,Bs}|Is]};
- false -> {Atom,[{block,[B|Bs]}|Is]}
+is_tagged_tuple([{block,Bl},
+ {test,is_eq_exact,Fail,[Dst,{atom,_}=Atom]}|Is],
+ Def, Fail, Src, Idx) ->
+ case is_tagged_tuple_1(Bl, Is, Fail, Src, Dst, Idx, Def, []) of
+ no ->
+ no;
+ {yes,[]} ->
+ {yes,Atom,Is};
+ {yes,[_|_]=Block} ->
+ {yes,Atom,[{block,Block}|Is]}
end;
-is_tagged_tuple([{block,[{set,_,_,_}=B|Bs]},
- {test,is_eq_exact,_,_}=I|Is],Fail,Src,Idx) ->
- case is_tagged_tuple([{block,Bs},I|Is],Fail,Src,Idx) of
- {Atom,[{block,Bsr}|Isr]} -> {Atom,[{block,[B|Bsr]}|Isr]};
- no -> no
+is_tagged_tuple(_, _, _, _, _) ->
+ no.
+
+is_tagged_tuple_1([{set,[Dst],[Src],{get_tuple_element,0}}=I|Bl],
+ Is, Fail, Src, Dst, Idx, Def, Acc) ->
+ %% Check usage of Dst to find out whether the get_tuple_element
+ %% is needed.
+ case usage(Dst, Is, Fail, Idx) of
+ killed ->
+ %% Safe to remove the get_tuple_element instruction.
+ {yes,reverse(Acc, Bl)};
+ used ->
+ %% Actively used. Must keep instruction.
+ {yes,reverse(Acc, [I|Bl])};
+ not_used ->
+ %% Not actually used (but must be initialized).
+ case is_defined(Dst, Def) of
+ false ->
+ %% Dst must be initialized, but the
+ %% actual value does not matter.
+ Kill = {set,[Dst],[nil],move},
+ {yes,reverse(Acc, [Kill|Bl])};
+ true ->
+ %% The register is previously initialized.
+ %% We can remove the instruction.
+ {yes,reverse(Acc, Bl)}
+ end
end;
-is_tagged_tuple(_Is,_Fail,_Src,_Idx) ->
+is_tagged_tuple_1([I|Bl], Is, Fail, Src, Dst, Idx, Def, Acc) ->
+ is_tagged_tuple_1(Bl, Is, Fail, Src, Dst, Idx, Def, [I|Acc]);
+is_tagged_tuple_1(_, _, _, _, _, _, _, _) ->
no.
-is_killed(Dst,Is,{_,Lbl},Idx) ->
- beam_utils:is_killed(Dst,Is,Idx) andalso
- beam_utils:is_killed_at(Dst,Lbl,Idx).
+usage(Dst, Is, Fail, Idx) ->
+ beam_utils:usage(Dst, [{test,is_number,Fail,[nil]}|Is], Idx).
+
+is_defined({x,X}, Def) ->
+ (Def bsr X) band 1 =:= 1.
diff --git a/lib/compiler/src/beam_reorder.erl b/lib/compiler/src/beam_reorder.erl
index 910b7f6b0a..8d2ef5a431 100644
--- a/lib/compiler/src/beam_reorder.erl
+++ b/lib/compiler/src/beam_reorder.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,8 +35,7 @@ function({function,Name,Arity,CLabel,Is0}) ->
Is = reorder(Is0),
{function,Name,Arity,CLabel,Is}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
diff --git a/lib/compiler/src/beam_split.erl b/lib/compiler/src/beam_split.erl
index d041f18806..809e49b3d0 100644
--- a/lib/compiler/src/beam_split.erl
+++ b/lib/compiler/src/beam_split.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -50,8 +50,9 @@ split_block([{set,[R],[_,_,_]=As,{bif,is_record,{f,Lbl}}}|Is], Bl, Acc) ->
split_block(Is, [], [{bif,is_record,{f,Lbl},As,R}|make_block(Bl, Acc)]);
split_block([{set,[R],As,{bif,N,{f,Lbl}=Fail}}|Is], Bl, Acc) when Lbl =/= 0 ->
split_block(Is, [], [{bif,N,Fail,As,R}|make_block(Bl, Acc)]);
-split_block([{set,[R],As,{bif,raise,{f,_}=Fail}}|Is], Bl, Acc) ->
- split_block(Is, [], [{bif,raise,Fail,As,R}|make_block(Bl, Acc)]);
+split_block([{set,[],[],{line,_}=Line},
+ {set,[R],As,{bif,raise,{f,_}=Fail}}|Is], Bl, Acc) ->
+ split_block(Is, [], [{bif,raise,Fail,As,R},Line|make_block(Bl, Acc)]);
split_block([{set,[R],As,{alloc,Live,{gc_bif,N,{f,Lbl}=Fail}}}|Is], Bl, Acc)
when Lbl =/= 0 ->
split_block(Is, [], [{gc_bif,N,Fail,Live,As,R}|make_block(Bl, Acc)]);
@@ -61,8 +62,6 @@ split_block([{set,[D],[S|Puts],{alloc,R,{put_map,Op,{f,Lbl}=Fail}}}|Is],
make_block(Bl, Acc)]);
split_block([{set,[R],[],{try_catch,Op,L}}|Is], Bl, Acc) ->
split_block(Is, [], [{Op,R,L}|make_block(Bl, Acc)]);
-split_block([{set,[],[],{line,_}=Line}|Is], Bl, Acc) ->
- split_block(Is, [], [Line|make_block(Bl, Acc)]);
split_block([I|Is], Bl, Acc) ->
split_block(Is, [I|Bl], Acc);
split_block([], Bl, Acc) -> make_block(Bl, Acc).
diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl
index 3d842a6fd3..b5c979e529 100644
--- a/lib/compiler/src/beam_type.erl
+++ b/lib/compiler/src/beam_type.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -17,14 +17,15 @@
%%
%% %CopyrightEnd%
%%
-%% Purpose : Type-based optimisations.
+%% Purpose: Type-based optimisations. See the comment for verified_type/1
+%% the very end of this file for a description of the types in the
+%% type database.
-module(beam_type).
-export([module/2]).
--import(lists, [filter/2,foldl/3,keyfind/3,member/2,
- reverse/1,reverse/2,sort/1]).
+-import(lists, [foldl/3,member/2,reverse/1,reverse/2,sort/1]).
-define(UNICODE_INT, {integer,{0,16#10FFFF}}).
@@ -40,11 +41,10 @@ function({function,Name,Arity,CLabel,Asm0}) ->
Asm1 = beam_utils:live_opt(Asm0),
Asm2 = opt(Asm1, [], tdb_new()),
Asm3 = beam_utils:live_opt(Asm2),
- Asm = beam_utils:delete_live_annos(Asm3),
+ Asm = beam_utils:delete_annos(Asm3),
{function,Name,Arity,CLabel,Asm}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
@@ -81,96 +81,81 @@ simplify(Is0, TypeDb0) ->
%% Basic simplification, mostly tuples, no floating point optimizations.
simplify_basic(Is, Ts) ->
- simplify_basic_1(Is, Ts, []).
-
-simplify_basic_1([{set,[D],[{integer,Index},Reg],{bif,element,_}}=I0|Is], Ts0, Acc) ->
- I = case max_tuple_size(Reg, Ts0) of
- Sz when 0 < Index, Index =< Sz ->
- {set,[D],[Reg],{get_tuple_element,Index-1}};
- _Other -> I0
- end,
- Ts = update(I, Ts0),
- simplify_basic_1(Is, Ts, [I|Acc]);
-simplify_basic_1([{set,[D],[TupleReg],{get_tuple_element,0}}=I|Is0], Ts0, Acc) ->
- case tdb_find(TupleReg, Ts0) of
- {tuple,_,[Contents]} ->
- simplify_basic_1([{set,[D],[Contents],move}|Is0], Ts0, Acc);
- _ ->
- Ts = update(I, Ts0),
- simplify_basic_1(Is0, Ts, [I|Acc])
+ simplify_basic(Is, Ts, []).
+
+simplify_basic([I0|Is], Ts0, Acc) ->
+ case simplify_instr(I0, Ts0) of
+ [] ->
+ simplify_basic(Is, Ts0, Acc);
+ [I] ->
+ Ts = update(I, Ts0),
+ simplify_basic(Is, Ts, [I|Acc])
+ end;
+simplify_basic([], Ts, Acc) ->
+ {reverse(Acc),Ts}.
+
+%% simplify_instr(Instruction, Ts) -> [Instruction].
+
+%% Simplify a simple instruction using type information. Return an
+%% empty list if the instruction should be removed, or a list with
+%% the original or modified instruction.
+
+simplify_instr({set,[D],[{integer,Index},Reg],{bif,element,_}}=I, Ts) ->
+ case max_tuple_size(Reg, Ts) of
+ Sz when 0 < Index, Index =< Sz ->
+ [{set,[D],[Reg],{get_tuple_element,Index-1}}];
+ _ -> [I]
end;
-simplify_basic_1([{set,_,_,{try_catch,_,_}}=I|Is], _Ts, Acc) ->
- simplify_basic_1(Is, tdb_new(), [I|Acc]);
-simplify_basic_1([{test,is_atom,_,[R]}=I|Is], Ts, Acc) ->
+simplify_instr({test,Test,Fail,[R]}=I, Ts) ->
case tdb_find(R, Ts) of
- boolean -> simplify_basic_1(Is, Ts, Acc);
- _ -> simplify_basic_1(Is, Ts, [I|Acc])
+ any ->
+ [I];
+ Type ->
+ case will_succeed(Test, Type) of
+ yes -> [];
+ no -> [{jump,Fail}];
+ maybe -> [I]
+ end
+ end;
+simplify_instr({set,[D],[TupleReg],{get_tuple_element,0}}=I, Ts) ->
+ case tdb_find(TupleReg, Ts) of
+ {tuple,_,_,[Contents]} ->
+ [{set,[D],[Contents],move}];
+ _ ->
+ [I]
end;
-simplify_basic_1([{test,is_integer,_,[R]}=I|Is], Ts, Acc) ->
+simplify_instr({test,test_arity,_,[R,Arity]}=I, Ts) ->
case tdb_find(R, Ts) of
- integer -> simplify_basic_1(Is, Ts, Acc);
- {integer,_} -> simplify_basic_1(Is, Ts, Acc);
- _ -> simplify_basic_1(Is, Ts, [I|Acc])
+ {tuple,exact_size,Arity,_} -> [];
+ _ -> [I]
end;
-simplify_basic_1([{test,is_tuple,_,[R]}=I|Is], Ts, Acc) ->
+simplify_instr({test,is_eq_exact,Fail,[R,{atom,A}=Atom]}=I, Ts) ->
case tdb_find(R, Ts) of
- {tuple,_,_} -> simplify_basic_1(Is, Ts, Acc);
- _ -> simplify_basic_1(Is, Ts, [I|Acc])
+ {atom,_}=Atom -> [];
+ boolean when is_boolean(A) -> [I];
+ any -> [I];
+ _ -> [{jump,Fail}]
end;
-simplify_basic_1([{test,test_arity,_,[R,Arity]}=I|Is], Ts0, Acc) ->
- case tdb_find(R, Ts0) of
- {tuple,Arity,_} ->
- simplify_basic_1(Is, Ts0, Acc);
- _Other ->
- Ts = update(I, Ts0),
- simplify_basic_1(Is, Ts, [I|Acc])
+simplify_instr({test,is_record,_,[R,{atom,_}=Tag,{integer,Arity}]}=I, Ts) ->
+ case tdb_find(R, Ts) of
+ {tuple,exact_size,Arity,[Tag]} -> [];
+ _ -> [I]
end;
-simplify_basic_1([{test,is_map,_,[R]}=I|Is], Ts0, Acc) ->
- case tdb_find(R, Ts0) of
- map -> simplify_basic_1(Is, Ts0, Acc);
- _Other ->
- Ts = update(I, Ts0),
- simplify_basic_1(Is, Ts, [I|Acc])
+simplify_instr({select,select_val,Reg,_,_}=I, Ts) ->
+ [case tdb_find(Reg, Ts) of
+ {integer,Range} ->
+ simplify_select_val_int(I, Range);
+ boolean ->
+ simplify_select_val_bool(I);
+ _ ->
+ I
+ end];
+simplify_instr({test,bs_test_unit,_,[Src,Unit]}=I, Ts) ->
+ case tdb_find(Src, Ts) of
+ {binary,U} when U rem Unit =:= 0 -> [];
+ _ -> [I]
end;
-simplify_basic_1([{test,is_nonempty_list,_,[R]}=I|Is], Ts0, Acc) ->
- case tdb_find(R, Ts0) of
- nonempty_list -> simplify_basic_1(Is, Ts0, Acc);
- _Other ->
- Ts = update(I, Ts0),
- simplify_basic_1(Is, Ts, [I|Acc])
- end;
-simplify_basic_1([{test,is_eq_exact,Fail,[R,{atom,_}=Atom]}=I|Is0], Ts0, Acc0) ->
- Acc = case tdb_find(R, Ts0) of
- {atom,_}=Atom -> Acc0;
- {atom,_} -> [{jump,Fail}|Acc0];
- _ -> [I|Acc0]
- end,
- Ts = update(I, Ts0),
- simplify_basic_1(Is0, Ts, Acc);
-simplify_basic_1([{test,is_record,_,[R,{atom,_}=Tag,{integer,Arity}]}=I|Is], Ts0, Acc) ->
- case tdb_find(R, Ts0) of
- {tuple,Arity,[Tag]} ->
- simplify_basic_1(Is, Ts0, Acc);
- _Other ->
- Ts = update(I, Ts0),
- simplify_basic_1(Is, Ts, [I|Acc])
- end;
-simplify_basic_1([{select,select_val,Reg,_,_}=I0|Is], Ts, Acc) ->
- I = case tdb_find(Reg, Ts) of
- {integer,Range} ->
- simplify_select_val_int(I0, Range);
- boolean ->
- simplify_select_val_bool(I0);
- _ ->
- I0
- end,
- simplify_basic_1(Is, tdb_new(), [I|Acc]);
-simplify_basic_1([I|Is], Ts0, Acc) ->
- Ts = update(I, Ts0),
- simplify_basic_1(Is, Ts, [I|Acc]);
-simplify_basic_1([], Ts, Acc) ->
- Is = reverse(Acc),
- {Is,Ts}.
+simplify_instr(I, _) -> [I].
simplify_select_val_int({select,select_val,R,_,L0}=I, {Min,Max}) ->
Vs = sort([V || {integer,V} <- L0]),
@@ -198,6 +183,53 @@ eq_ranges([H], H, H) -> true;
eq_ranges([H|T], H, Max) -> eq_ranges(T, H+1, Max);
eq_ranges(_, _, _) -> false.
+%% will_succeed(TestOperation, Type) -> yes|no|maybe.
+%% Test whether TestOperation applied to an argument of type Type
+%% will succeed. Return yes, no, or maybe.
+%%
+%% Type is a type as described in the comment for verified_type/1 at
+%% the very end of this file, but it will *never* be 'any'.
+
+will_succeed(is_atom, Type) ->
+ case Type of
+ {atom,_} -> yes;
+ boolean -> yes;
+ _ -> no
+ end;
+will_succeed(is_binary, Type) ->
+ case Type of
+ {binary,U} when U rem 8 =:= 0 -> yes;
+ {binary,_} -> maybe;
+ _ -> no
+ end;
+will_succeed(is_bitstr, Type) ->
+ case Type of
+ {binary,_} -> yes;
+ _ -> no
+ end;
+will_succeed(is_integer, Type) ->
+ case Type of
+ integer -> yes;
+ {integer,_} -> yes;
+ _ -> no
+ end;
+will_succeed(is_map, Type) ->
+ case Type of
+ map -> yes;
+ _ -> no
+ end;
+will_succeed(is_nonempty_list, Type) ->
+ case Type of
+ nonempty_list -> yes;
+ _ -> no
+ end;
+will_succeed(is_tuple, Type) ->
+ case Type of
+ {tuple,_,_,_} -> yes;
+ _ -> no
+ end;
+will_succeed(_, _) -> maybe.
+
%% simplify_float([Instruction], TypeDatabase) ->
%% {[Instruction],TypeDatabase'} | not_possible
%% Simplify floating point operations in blocks.
@@ -227,7 +259,7 @@ simplify_float_1([{set,[D0],[A0],{alloc,_,{gc_bif,'-',{f,0}}}}=I|Is]=Is0,
{D,Rs} = find_dest(D0, Rs1),
Areg = fetch_reg(A, Rs),
Acc = [{set,[D],[Areg],{bif,fnegate,{f,0}}}|clearerror(Acc1)],
- Ts = tdb_update([{D0,float}], Ts0),
+ Ts = tdb_store(D0, float, Ts0),
simplify_float_1(Is, Ts, Rs, Acc);
_Other ->
Ts = update(I, Ts0),
@@ -250,7 +282,7 @@ simplify_float_1([{set,[D0],[A0,B0],{alloc,_,{gc_bif,Op0,{f,0}}}}=I|Is]=Is0,
Areg = fetch_reg(A, Rs),
Breg = fetch_reg(B, Rs),
Acc = [{set,[D],[Areg,Breg],{bif,Op,{f,0}}}|clearerror(Acc2)],
- Ts = tdb_update([{D0,float}], Ts0),
+ Ts = tdb_store(D0, float, Ts0),
simplify_float_1(Is, Ts, Rs, Acc)
end;
simplify_float_1([{set,_,_,{try_catch,_,_}}=I|Is]=Is0, _Ts, Rs0, Acc0) ->
@@ -301,7 +333,7 @@ clearerror([], OrigIs) -> [{set,[],[],fclearerror}|OrigIs].
%% Combine two blocks and eliminate any move instructions that assign
%% to registers that are killed later in the block.
%%
-merge_blocks(B1, [{'%live',_,_}|B2]) ->
+merge_blocks(B1, [{'%anno',_}|B2]) ->
merge_blocks_1(B1++[{set,[],[],stop_here}|B2]).
merge_blocks_1([{set,[],_,stop_here}|Is]) -> Is;
@@ -350,27 +382,17 @@ flt_need_heap_2({set,_,_,{put_tuple,_}}, H, Fl) ->
{[],H+1,Fl};
flt_need_heap_2({set,_,_,put}, H, Fl) ->
{[],H+1,Fl};
-%% Then the "neutral" instructions. We just pass them.
-flt_need_heap_2({set,[{fr,_}],_,_}, H, Fl) ->
- {[],H,Fl};
-flt_need_heap_2({set,[],[],fclearerror}, H, Fl) ->
- {[],H,Fl};
-flt_need_heap_2({set,[],[],fcheckerror}, H, Fl) ->
- {[],H,Fl};
-flt_need_heap_2({set,_,_,{bif,_,_}}, H, Fl) ->
- {[],H,Fl};
-flt_need_heap_2({set,_,_,move}, H, Fl) ->
- {[],H,Fl};
-flt_need_heap_2({set,_,_,{get_tuple_element,_}}, H, Fl) ->
- {[],H,Fl};
-flt_need_heap_2({set,_,_,get_list}, H, Fl) ->
- {[],H,Fl};
-flt_need_heap_2({set,_,_,{try_catch,_,_}}, H, Fl) ->
- {[],H,Fl};
-%% All other instructions should cause the insertion of an allocation
+%% The following instructions cause the insertion of an allocation
%% instruction if needed.
+flt_need_heap_2({set,_,_,{alloc,_,_}}, H, Fl) ->
+ {flt_alloc(H, Fl),0,0};
+flt_need_heap_2({set,_,_,{set_tuple_element,_}}, H, Fl) ->
+ {flt_alloc(H, Fl),0,0};
+flt_need_heap_2({'%anno',_}, H, Fl) ->
+ {flt_alloc(H, Fl),0,0};
+%% All other instructions are "neutral". We just pass them.
flt_need_heap_2(_, H, Fl) ->
- {flt_alloc(H, Fl),0,0}.
+ {[],H,Fl}.
flt_alloc(0, 0) ->
[];
@@ -393,7 +415,7 @@ build_alloc(Words, Floats) -> {alloc,[{words,Words},{floats,Floats}]}.
%% is not continous at an allocation function (e.g. if {x,0} and {x,2}
%% are live, but not {x,1}).
-flt_liveness([{'%live',_Live,Regs}=LiveInstr|Is]) ->
+flt_liveness([{'%anno',{used,Regs}}=LiveInstr|Is]) ->
flt_liveness_1(Is, Regs, [LiveInstr]).
flt_liveness_1([{set,Ds,Ss,{alloc,Live0,Alloc}}|Is], Regs0, Acc) ->
@@ -405,7 +427,7 @@ flt_liveness_1([{set,Ds,Ss,{alloc,Live0,Alloc}}|Is], Regs0, Acc) ->
flt_liveness_1([{set,Ds,_,_}=I|Is], Regs0, Acc) ->
Regs = x_live(Ds, Regs0),
flt_liveness_1(Is, Regs, [I|Acc]);
-flt_liveness_1([{'%live',_,_}], _Regs, Acc) ->
+flt_liveness_1([{'%anno',_}], _Regs, Acc) ->
reverse(Acc).
init_regs(Live) ->
@@ -429,103 +451,107 @@ x_live([], Regs) -> Regs.
%% Update the type database to account for executing an instruction.
%%
%% First the cases for instructions inside basic blocks.
-update({'%live',_,_}, Ts) -> Ts;
+update({'%anno',_}, Ts) ->
+ Ts;
update({set,[D],[S],move}, Ts) ->
tdb_copy(S, D, Ts);
-update({set,[D],[{integer,I},Reg],{bif,element,_}}, Ts0) ->
- tdb_update([{Reg,{tuple,I,[]}},{D,kill}], Ts0);
-update({set,[D],[_Index,Reg],{bif,element,_}}, Ts0) ->
- tdb_update([{Reg,{tuple,0,[]}},{D,kill}], Ts0);
-update({set,[D],Args,{bif,N,_}}, Ts0) ->
+update({set,[D],[Index,Reg],{bif,element,_}}, Ts0) ->
+ MinSize = case Index of
+ {integer,I} -> I;
+ _ -> 0
+ end,
+ Ts = tdb_meet(Reg, {tuple,min_size,MinSize,[]}, Ts0),
+ tdb_store(D, any, Ts);
+update({set,[D],[_Key,Map],{bif,map_get,_}}, Ts0) ->
+ Ts = tdb_meet(Map, map, Ts0),
+ tdb_store(D, any, Ts);
+update({set,[D],Args,{bif,N,_}}, Ts) ->
Ar = length(Args),
BoolOp = erl_internal:new_type_test(N, Ar) orelse
erl_internal:comp_op(N, Ar) orelse
erl_internal:bool_op(N, Ar),
- case BoolOp of
- true ->
- tdb_update([{D,boolean}], Ts0);
- false ->
- tdb_update([{D,kill}], Ts0)
+ Type = case BoolOp of
+ true -> boolean;
+ false -> unary_op_type(N)
+ end,
+ tdb_store(D, Type, Ts);
+update({set,[D],[S],{get_tuple_element,0}}, Ts0) ->
+ if
+ D =:= S ->
+ tdb_store(D, any, Ts0);
+ true ->
+ Ts = tdb_store(D, {tuple_element,S,0}, Ts0),
+ tdb_store(S, {tuple,min_size,1,[]}, Ts)
end;
-update({set,[D],[S],{get_tuple_element,0}}, Ts) ->
- tdb_update([{D,{tuple_element,S,0}}], Ts);
update({set,[D],[S],{alloc,_,{gc_bif,float,{f,0}}}}, Ts0) ->
%% Make sure we reject non-numeric literal argument.
case possibly_numeric(S) of
- true -> tdb_update([{D,float}], Ts0);
- false -> Ts0
+ true -> tdb_store(D, float, Ts0);
+ false -> Ts0
end;
update({set,[D],[S1,S2],{alloc,_,{gc_bif,'band',{f,0}}}}, Ts) ->
- case keyfind(integer, 1, [S1,S2]) of
- {integer,N} ->
- update_band(N, D, Ts);
- false ->
- tdb_update([{D,integer}], Ts)
- end;
-update({set,[D],[S1,S2],{alloc,_,{gc_bif,'/',{f,0}}}}, Ts0) ->
+ Type = band_type(S1, S2, Ts),
+ tdb_store(D, Type, Ts);
+update({set,[D],[S1,S2],{alloc,_,{gc_bif,'/',{f,0}}}}, Ts) ->
%% Make sure we reject non-numeric literals.
case possibly_numeric(S1) andalso possibly_numeric(S2) of
- true -> tdb_update([{D,float}], Ts0);
- false -> Ts0
+ true -> tdb_store(D, float, Ts);
+ false -> Ts
end;
update({set,[D],[S1,S2],{alloc,_,{gc_bif,Op,{f,0}}}}, Ts0) ->
case op_type(Op) of
integer ->
- tdb_update([{D,integer}], Ts0);
- {float,_} ->
- case {tdb_find(S1, Ts0),tdb_find(S2, Ts0)} of
- {float,_} -> tdb_update([{D,float}], Ts0);
- {_,float} -> tdb_update([{D,float}], Ts0);
- {_,_} -> tdb_update([{D,kill}], Ts0)
- end;
- unknown ->
- tdb_update([{D,kill}], Ts0)
- end;
-update({set,[],_Src,_Op}, Ts0) -> Ts0;
-update({set,[D],_Src,_Op}, Ts0) ->
- tdb_update([{D,kill}], Ts0);
-update({set,[D1,D2],_Src,_Op}, Ts0) ->
- tdb_update([{D1,kill},{D2,kill}], Ts0);
+ tdb_store(D, integer, Ts0);
+ {float,_} ->
+ case {tdb_find(S1, Ts0),tdb_find(S2, Ts0)} of
+ {float,_} -> tdb_store(D, float, Ts0);
+ {_,float} -> tdb_store(D, float, Ts0);
+ {_,_} -> tdb_store(D, any, Ts0)
+ end;
+ Type ->
+ tdb_store(D, Type, Ts0)
+ end;
+update({set,[D],[_],{alloc,_,{gc_bif,Op,{f,0}}}}, Ts) ->
+ tdb_store(D, unary_op_type(Op), Ts);
+update({set,[],_Src,_Op}, Ts) ->
+ Ts;
+update({set,[D],_Src,_Op}, Ts) ->
+ tdb_store(D, any, Ts);
update({kill,D}, Ts) ->
- tdb_update([{D,kill}], Ts);
+ tdb_store(D, any, Ts);
%% Instructions outside of blocks.
-update({test,is_float,_Fail,[Src]}, Ts0) ->
- tdb_update([{Src,float}], Ts0);
-update({test,test_arity,_Fail,[Src,Arity]}, Ts0) ->
- tdb_update([{Src,{tuple,Arity,[]}}], Ts0);
-update({test,is_map,_Fail,[Src]}, Ts0) ->
- tdb_update([{Src,map}], Ts0);
+update({test,test_arity,_Fail,[Src,Arity]}, Ts) ->
+ tdb_meet(Src, {tuple,exact_size,Arity,[]}, Ts);
update({get_map_elements,_,Src,{list,Elems0}}, Ts0) ->
+ Ts1 = tdb_meet(Src, map, Ts0),
{_Ss,Ds} = beam_utils:split_even(Elems0),
- Elems = [{Dst,kill} || Dst <- Ds],
- tdb_update([{Src,map}|Elems], Ts0);
-update({test,is_nonempty_list,_Fail,[Src]}, Ts0) ->
- tdb_update([{Src,nonempty_list}], Ts0);
-update({test,is_eq_exact,_,[Reg,{atom,_}=Atom]}, Ts) ->
- case tdb_find(Reg, Ts) of
- error ->
- Ts;
- {tuple_element,TupleReg,0} ->
- tdb_update([{TupleReg,{tuple,1,[Atom]}}], Ts);
- _ ->
- Ts
- end;
+ foldl(fun(Dst, A) -> tdb_store(Dst, any, A) end, Ts1, Ds);
+update({test,is_eq_exact,_,[Reg,{atom,_}=Atom]}, Ts0) ->
+ Ts = case tdb_find_source_tuple(Reg, Ts0) of
+ {source_tuple,TupleReg} ->
+ tdb_meet(TupleReg, {tuple,min_size,1,[Atom]}, Ts0);
+ none ->
+ Ts0
+ end,
+ tdb_meet(Reg, Atom, Ts);
update({test,is_record,_Fail,[Src,Tag,{integer,Arity}]}, Ts) ->
- tdb_update([{Src,{tuple,Arity,[Tag]}}], Ts);
+ tdb_meet(Src, {tuple,exact_size,Arity,[Tag]}, Ts);
-%% Binary matching
+%% Binaries and binary matching.
update({test,bs_get_integer2,_,_,Args,Dst}, Ts) ->
- tdb_update([{Dst,get_bs_integer_type(Args)}], Ts);
+ tdb_store(Dst, get_bs_integer_type(Args), Ts);
update({test,bs_get_utf8,_,_,_,Dst}, Ts) ->
- tdb_update([{Dst,?UNICODE_INT}], Ts);
+ tdb_store(Dst, ?UNICODE_INT, Ts);
update({test,bs_get_utf16,_,_,_,Dst}, Ts) ->
- tdb_update([{Dst,?UNICODE_INT}], Ts);
+ tdb_store(Dst, ?UNICODE_INT, Ts);
update({test,bs_get_utf32,_,_,_,Dst}, Ts) ->
- tdb_update([{Dst,?UNICODE_INT}], Ts);
+ tdb_store(Dst, ?UNICODE_INT, Ts);
+update({bs_init,_,{bs_init2,_,_},_,_,Dst}, Ts) ->
+ tdb_store(Dst, {binary,8}, Ts);
update({bs_init,_,_,_,_,Dst}, Ts) ->
- tdb_update([{Dst,kill}], Ts);
+ tdb_store(Dst, {binary,1}, Ts);
update({bs_put,_,_,_}, Ts) ->
Ts;
update({bs_save2,_,_}, Ts) ->
@@ -533,14 +559,31 @@ update({bs_save2,_,_}, Ts) ->
update({bs_restore2,_,_}, Ts) ->
Ts;
update({bs_context_to_binary,Dst}, Ts) ->
- tdb_update([{Dst,kill}], Ts);
-update({test,bs_start_match2,_,_,_,Dst}, Ts) ->
- tdb_update([{Dst,kill}], Ts);
-update({test,bs_get_binary2,_,_,_,Dst}, Ts) ->
- tdb_update([{Dst,kill}], Ts);
+ tdb_store(Dst, any, Ts);
+update({test,bs_start_match2,_,_,[Src,_],Dst}, Ts0) ->
+ Ts = tdb_meet(Src, {binary,1}, Ts0),
+ tdb_copy(Src, Dst, Ts);
+update({test,bs_get_binary2,_,_,[_,_,Unit,_],Dst}, Ts) ->
+ true = is_integer(Unit), %Assertion.
+ tdb_store(Dst, {binary,Unit}, Ts);
update({test,bs_get_float2,_,_,_,Dst}, Ts) ->
- tdb_update([{Dst,float}], Ts);
-
+ tdb_store(Dst, float, Ts);
+update({test,bs_test_unit,_,[Src,Unit]}, Ts) ->
+ tdb_meet(Src, {binary,Unit}, Ts);
+
+%% Other test instructions
+update({test,Test,_Fail,[Src]}, Ts) ->
+ Type = case Test of
+ is_binary -> {binary,8};
+ is_bitstr -> {binary,1};
+ is_boolean -> boolean;
+ is_float -> float;
+ is_integer -> integer;
+ is_map -> map;
+ is_nonempty_list -> nonempty_list;
+ _ -> any
+ end,
+ tdb_meet(Src, Type, Ts);
update({test,_Test,_Fail,_Other}, Ts) ->
Ts;
@@ -548,13 +591,13 @@ update({test,_Test,_Fail,_Other}, Ts) ->
update({call_ext,Ar,{extfunc,math,Math,Ar}}, Ts) ->
case is_math_bif(Math, Ar) of
- true -> tdb_update([{{x,0},float}], Ts);
+ true -> tdb_store({x,0}, float, Ts);
false -> tdb_kill_xregs(Ts)
end;
update({call_ext,3,{extfunc,erlang,setelement,3}}, Ts0) ->
Ts = tdb_kill_xregs(Ts0),
case tdb_find({x,1}, Ts0) of
- {tuple,Sz,_}=T0 ->
+ {tuple,SzKind,Sz,_}=T0 ->
T = case tdb_find({x,0}, Ts0) of
{integer,{I,I}} when I > 1 ->
%% First element is not changed. The result
@@ -563,9 +606,9 @@ update({call_ext,3,{extfunc,erlang,setelement,3}}, Ts0) ->
_ ->
%% Position is 1 or unknown. May change the
%% first element of the tuple.
- {tuple,Sz,[]}
+ {tuple,SzKind,Sz,[]}
end,
- tdb_update([{{x,0},T}], Ts);
+ tdb_store({x,0}, T, Ts);
_ ->
Ts
end;
@@ -576,24 +619,32 @@ update({call_fun, _}, Ts) -> tdb_kill_xregs(Ts);
update({apply, _}, Ts) -> tdb_kill_xregs(Ts);
update({line,_}, Ts) -> Ts;
+update({'%',_}, Ts) -> Ts;
%% The instruction is unknown. Kill all information.
update(_I, _Ts) -> tdb_new().
-update_band(N, Reg, Ts) ->
- Type = update_band_1(N, 0),
- tdb_update([{Reg,Type}], Ts).
+band_type({integer,Int}, Other, Ts) ->
+ band_type_1(Int, Other, Ts);
+band_type(Other, {integer,Int}, Ts) ->
+ band_type_1(Int, Other, Ts);
+band_type(_, _, _) -> integer.
-update_band_1(N, Bits) when Bits < 64 ->
+band_type_1(Int, OtherSrc, Ts) ->
+ Type = band_type_2(Int, 0),
+ OtherType = tdb_find(OtherSrc, Ts),
+ meet(Type, OtherType).
+
+band_type_2(N, Bits) when Bits < 64 ->
case 1 bsl Bits of
P when P =:= N + 1 ->
{integer,{0,N}};
P when P > N + 1 ->
integer;
_ ->
- update_band_1(N, Bits+1)
+ band_type_2(N, Bits+1)
end;
-update_band_1(_, _) ->
+band_type_2(_, _) ->
%% Negative or large positive number. Give up.
integer.
@@ -647,7 +698,7 @@ possibly_numeric(_) -> false.
max_tuple_size(Reg, Ts) ->
case tdb_find(Reg, Ts) of
- {tuple,Sz,_} -> Sz;
+ {tuple,_,Sz,_} -> Sz;
_Other -> 0
end.
@@ -717,7 +768,15 @@ op_type('bxor') -> integer;
op_type('bsl') -> integer;
op_type('bsr') -> integer;
op_type('div') -> integer;
-op_type(_) -> unknown.
+op_type(_) -> any.
+
+unary_op_type(bit_size) -> integer;
+unary_op_type(byte_size) -> integer;
+unary_op_type(length) -> integer;
+unary_op_type(map_size) -> integer;
+unary_op_type(size) -> integer;
+unary_op_type(tuple_size) -> integer;
+unary_op_type(_) -> any.
flush(Rs, [{set,[_],[_,_,_],{bif,is_record,_}}|_]=Is0, Acc0) ->
Acc = flush_all(Rs, Is0, Acc0),
@@ -800,37 +859,39 @@ checkerror_1([], OrigIs) -> OrigIs.
checkerror_2(OrigIs) -> [{set,[],[],fcheckerror}|OrigIs].
-%%% Routines for maintaining a type database. The type database
+%%% Routines for maintaining a type database. The type database
%%% associates type information with registers.
%%%
-%%% {tuple,Size,First} means that the corresponding register contains a
-%%% tuple with *at least* Size elements. An tuple with unknown
-%%% size is represented as {tuple,0,[]}. First is either [] (meaning that
-%%% the tuple's first element is unknown) or [FirstElement] (the contents
-%%% of the first element).
-%%%
-%%% 'float' means that the register contains a float.
-%%%
-%%% 'integer' or {integer,{Min,Max}} that the register contains an
-%%% integer.
+%%% See the comment for verified_type/1 at the end of module for
+%%% a description of the possible types.
%% tdb_new() -> EmptyDataBase
%% Creates a new, empty type database.
tdb_new() -> [].
-%% tdb_find(Register, Db) -> Information|error
+%% tdb_find(Register, Db) -> Type
%% Returns type information or the atom error if there is no type
%% information available for Register.
+%%
+%% See the comment for verified_type/1 at the end of module for
+%% a description of the possible types.
-tdb_find({x,_}=K, Ts) -> tdb_find_1(K, Ts);
-tdb_find({y,_}=K, Ts) -> tdb_find_1(K, Ts);
-tdb_find(_, _) -> error.
+tdb_find(Reg, Ts) ->
+ case tdb_find_raw(Reg, Ts) of
+ {tuple_element,_,_} -> any;
+ Type -> Type
+ end.
-tdb_find_1(K, Ts) ->
- case orddict:find(K, Ts) of
- {ok,Val} -> Val;
- error -> error
+%% tdb_find_source_tuple(Register, Ts) -> {source_tuple,Register} | 'none'.
+%% Find the tuple whose first element was fetched to the register Register.
+
+tdb_find_source_tuple(Reg, Ts) ->
+ case tdb_find_raw(Reg, Ts) of
+ {tuple_element,Src,0} ->
+ {source_tuple,Src};
+ _ ->
+ none
end.
%% tdb_copy(Source, Dest, Db) -> Db'
@@ -838,9 +899,9 @@ tdb_find_1(K, Ts) ->
%% as the Source.
tdb_copy({Tag,_}=S, D, Ts) when Tag =:= x; Tag =:= y ->
- case tdb_find(S, Ts) of
- error -> orddict:erase(D, Ts);
- Type -> orddict:store(D, Type, Ts)
+ case tdb_find_raw(S, Ts) of
+ any -> orddict:erase(D, Ts);
+ Type -> orddict:store(D, Type, Ts)
end;
tdb_copy(Literal, D, Ts) ->
Type = case Literal of
@@ -851,15 +912,90 @@ tdb_copy(Literal, D, Ts) ->
{literal,#{}} -> map;
{literal,Tuple} when tuple_size(Tuple) >= 1 ->
Lit = tag_literal(element(1, Tuple)),
- {tuple,tuple_size(Tuple),[Lit]};
- _ -> term
+ {tuple,exact_size,tuple_size(Tuple),[Lit]};
+ _ -> any
end,
- if
- Type =:= term ->
- orddict:erase(D, Ts);
- true ->
- verify_type(Type),
- orddict:store(D, Type, Ts)
+ tdb_store(D, verified_type(Type), Ts).
+
+%% tdb_store(Register, Type, Ts0) -> Ts.
+%% Store a new type for register Register. Return the update type
+%% database. Use this function when a new value is assigned to
+%% a register.
+%%
+%% See the comment for verified_type/1 at the end of module for
+%% a description of the possible types.
+
+tdb_store(Reg, any, Ts) ->
+ erase(Reg, Ts);
+tdb_store(Reg, Type, Ts) ->
+ store(Reg, verified_type(Type), Ts).
+
+store(Key, New, [{K,_}|_]=Dict) when Key < K ->
+ [{Key,New}|Dict];
+store(Key, New, [{K,Val}=E|Dict]) when Key > K ->
+ case Val of
+ {tuple_element,Key,_} -> store(Key, New, Dict);
+ _ -> [E|store(Key, New, Dict)]
+ end;
+store(Key, New, [{_K,Old}|Dict]) -> %Key == K
+ case Old of
+ {tuple,_,_,_} ->
+ [{Key,New}|erase_tuple_element(Key, Dict)];
+ _ ->
+ [{Key,New}|Dict]
+ end;
+store(Key, New, []) -> [{Key,New}].
+
+erase(Key, [{K,_}=E|Dict]) when Key < K ->
+ [E|Dict];
+erase(Key, [{K,Val}=E|Dict]) when Key > K ->
+ case Val of
+ {tuple_element,Key,_} -> erase(Key, Dict);
+ _ -> [E|erase(Key, Dict)]
+ end;
+erase(Key, [{_K,Val}|Dict]) -> %Key == K
+ case Val of
+ {tuple,_,_,_} -> erase_tuple_element(Key, Dict);
+ _ -> Dict
+ end;
+erase(_, []) -> [].
+
+erase_tuple_element(Key, [{_,{tuple_element,Key,_}}|Dict]) ->
+ erase_tuple_element(Key, Dict);
+erase_tuple_element(Key, [E|Dict]) ->
+ [E|erase_tuple_element(Key, Dict)];
+erase_tuple_element(_Key, []) -> [].
+
+%% tdb_meet(Register, Type, Ts0) -> Ts.
+%% Update information of a register that is used as the source for an
+%% instruction. The type Type will be combined using the meet operation
+%% with the previous type information for the register, resulting in
+%% narrower (more specific) type.
+%%
+%% For example, if the previous type is {tuple,min_size,2,[]} and the
+%% the new type is {tuple,exact_size,5,[]}, the meet of the types will
+%% be {tuple,exact_size,5,[]}.
+%%
+%% See the comment for verified_type/1 at the end of module for
+%% a description of the possible types.
+
+tdb_meet(Reg, NewType, Ts) ->
+ Update = fun(Type0) -> meet(Type0, NewType) end,
+ orddict:update(Reg, Update, NewType, Ts).
+
+%%%
+%%% Here follows internal helper functions for accessing and
+%%% updating the type database.
+%%%
+
+tdb_find_raw({x,_}=K, Ts) -> tdb_find_raw_1(K, Ts);
+tdb_find_raw({y,_}=K, Ts) -> tdb_find_raw_1(K, Ts);
+tdb_find_raw(_, _) -> any.
+
+tdb_find_raw_1(K, Ts) ->
+ case orddict:find(K, Ts) of
+ {ok,Val} -> Val;
+ error -> any
end.
tag_literal(A) when is_atom(A) -> {atom,A};
@@ -868,45 +1004,6 @@ tag_literal(I) when is_integer(I) -> {integer,I};
tag_literal([]) -> nil;
tag_literal(Lit) -> {literal,Lit}.
-%% tdb_update([UpdateOp], Db) -> NewDb
-%% UpdateOp = {Register,kill}|{Register,NewInfo}
-%% Updates a type database. If a 'kill' operation is given, the type
-%% information for that register will be removed from the database.
-%% A kill operation takes precedence over other operations for the same
-%% register (i.e. [{{x,0},kill},{{x,0},{tuple,5,[]}}] means that the
-%% the existing type information, if any, will be discarded, and the
-%% the '{tuple,5,[]}' information ignored.
-%%
-%% If NewInfo information is given and there exists information about
-%% the register, the old and new type information will be merged.
-%% For instance, {tuple,5,_} and {tuple,10,_} will be merged to produce
-%% {tuple,10,_}.
-
-tdb_update(Uis0, Ts0) ->
- Uis1 = filter(fun ({{x,_},_Op}) -> true;
- ({{y,_},_Op}) -> true;
- (_) -> false
- end, Uis0),
- tdb_update1(lists:sort(Uis1), Ts0).
-
-tdb_update1([{Key,kill}|Ops], [{K,_Old}|_]=Db) when Key < K ->
- tdb_update1(remove_key(Key, Ops), Db);
-tdb_update1([{Key,Type}=New|Ops], [{K,_Old}|_]=Db) when Key < K ->
- verify_type(Type),
- [New|tdb_update1(Ops, Db)];
-tdb_update1([{Key,kill}|Ops], [{Key,_}|Db]) ->
- tdb_update1(remove_key(Key, Ops), Db);
-tdb_update1([{Key,NewInfo}|Ops], [{Key,OldInfo}|Db]) ->
- [{Key,merge_type_info(NewInfo, OldInfo)}|tdb_update1(Ops, Db)];
-tdb_update1([{_,_}|_]=Ops, [Old|Db]) ->
- [Old|tdb_update1(Ops, Db)];
-tdb_update1([{Key,kill}|Ops], []) ->
- tdb_update1(remove_key(Key, Ops), []);
-tdb_update1([{_,Type}=New|Ops], []) ->
- verify_type(Type),
- [New|tdb_update1(Ops, [])];
-tdb_update1([], Db) -> Db.
-
%% tdb_kill_xregs(Db) -> NewDb
%% Kill all information about x registers. Also kill all tuple_element
%% dependencies from y registers to x registers.
@@ -915,37 +1012,106 @@ tdb_kill_xregs([{{x,_},_Type}|Db]) -> tdb_kill_xregs(Db);
tdb_kill_xregs([{{y,_},{tuple_element,{x,_},_}}|Db]) -> tdb_kill_xregs(Db);
tdb_kill_xregs([Any|Db]) -> [Any|tdb_kill_xregs(Db)];
tdb_kill_xregs([]) -> [].
-
-remove_key(Key, [{Key,_Op}|Ops]) -> remove_key(Key, Ops);
-remove_key(_, Ops) -> Ops.
-
-merge_type_info(I, I) -> I;
-merge_type_info({tuple,Sz1,Same}, {tuple,Sz2,Same}=Max) when Sz1 < Sz2 ->
+
+%% meet(Type1, Type2) -> Type
+%% Returns the "meet" of Type1 and Type2. The meet is a narrower
+%% type than Type1 and Type2. For example:
+%%
+%% meet(integer, {integer,{0,3}}) -> {integer,{0,3}}
+%%
+%% The meet for two different types result in 'none', which is
+%% the bottom element for our type lattice:
+%%
+%% meet(integer, map) -> none
+
+meet(T, T) ->
+ T;
+meet({integer,_}=T, integer) ->
+ T;
+meet(integer, {integer,_}=T) ->
+ T;
+meet({integer,{Min1,Max1}}, {integer,{Min2,Max2}}) ->
+ {integer,{max(Min1, Min2),min(Max1, Max2)}};
+meet({tuple,min_size,Sz1,Same}, {tuple,min_size,Sz2,Same}=Max) when Sz1 < Sz2 ->
Max;
-merge_type_info({tuple,Sz1,Same}=Max, {tuple,Sz2,Same}) when Sz1 > Sz2 ->
+meet({tuple,min_size,Sz1,Same}=Max, {tuple,min_size,Sz2,Same}) when Sz1 > Sz2 ->
Max;
-merge_type_info({tuple,Sz1,[]}, {tuple,_Sz2,First}=Tuple2) ->
- merge_type_info({tuple,Sz1,First}, Tuple2);
-merge_type_info({tuple,_Sz1,First}=Tuple1, {tuple,Sz2,_}) ->
- merge_type_info(Tuple1, {tuple,Sz2,First});
-merge_type_info(integer, {integer,_}=Int) ->
- Int;
-merge_type_info({integer,_}=Int, integer) ->
- Int;
-merge_type_info({integer,{Min1,Max1}}, {integer,{Min2,Max2}}) ->
- {integer,{max(Min1, Min2),min(Max1, Max2)}};
-merge_type_info(NewType, _) ->
- verify_type(NewType),
- NewType.
-
-verify_type({atom,_}) -> ok;
-verify_type(boolean) -> ok;
-verify_type(integer) -> ok;
-verify_type({integer,{Min,Max}})
- when is_integer(Min), is_integer(Max) -> ok;
-verify_type(map) -> ok;
-verify_type(nonempty_list) -> ok;
-verify_type({tuple,Sz,[]}) when is_integer(Sz) -> ok;
-verify_type({tuple,Sz,[_]}) when is_integer(Sz) -> ok;
-verify_type({tuple_element,_,_}) -> ok;
-verify_type(float) -> ok.
+meet({tuple,exact_size,_,Same}=Exact, {tuple,_,_,Same}) ->
+ Exact;
+meet({tuple,_,_,Same},{tuple,exact_size,_,Same}=Exact) ->
+ Exact;
+meet({tuple,SzKind1,Sz1,[]}, {tuple,_SzKind2,_Sz2,First}=Tuple2) ->
+ meet({tuple,SzKind1,Sz1,First}, Tuple2);
+meet({tuple,_SzKind1,_Sz1,First}=Tuple1, {tuple,SzKind2,Sz2,_}) ->
+ meet(Tuple1, {tuple,SzKind2,Sz2,First});
+meet({binary,U1}, {binary,U2}) ->
+ {binary,max(U1, U2)};
+meet(T1, T2) ->
+ case is_any(T1) of
+ true ->
+ verified_type(T2);
+ false ->
+ case is_any(T2) of
+ true ->
+ verified_type(T1);
+ false ->
+ none %The bottom element.
+ end
+ end.
+
+is_any(any) -> true;
+is_any({tuple_element,_,_}) -> true;
+is_any(_) -> false.
+
+%% verified_type(Type) -> Type
+%% Returns the passed in type if it is one of the defined types.
+%% Crashes if there is anything wrong with the type.
+%%
+%% Here are all possible types:
+%%
+%% any Any Erlang term (top element for the type lattice).
+%%
+%% {atom,Atom} The specific atom Atom.
+%% {binary,Unit} Binary/bitstring aligned to unit Unit.
+%% boolean 'true' | 'false'
+%% float Floating point number.
+%% integer Integer.
+%% {integer,{Min,Max}} Integer in the inclusive range Min through Max.
+%% map Map.
+%% nonempty_list Nonempty list.
+%% {tuple,_,_,_} Tuple (see below).
+%%
+%% none No type (bottom element for the type lattice).
+%%
+%% {tuple,min_size,Size,First} means that the corresponding register
+%% contains a tuple with *at least* Size elements (conversely,
+%% {tuple,exact_size,Size,First} means that it contains a tuple with
+%% *exactly* Size elements). An tuple with unknown size is
+%% represented as {tuple,min_size,0,[]}. First is either [] (meaning
+%% that the tuple's first element is unknown) or [FirstElement] (the
+%% contents of the first element).
+%%
+%% There is also a pseudo-type called {tuple_element,_,_}:
+%%
+%% {tuple_element,SrcTuple,ElementNumber}
+%%
+%% that does not provide any information about the type of the
+%% register itself, but provides a link back to the source tuple that
+%% the register got its value from.
+%%
+%% Note that {tuple_element,_,_} will *never* be returned by tdb_find/2.
+%% Use tdb_find_source_tuple/2 to locate the source tuple for a register.
+
+verified_type(any=T) -> T;
+verified_type({atom,_}=T) -> T;
+verified_type({binary,U}=T) when is_integer(U) -> T;
+verified_type(boolean=T) -> T;
+verified_type(integer=T) -> T;
+verified_type({integer,{Min,Max}}=T)
+ when is_integer(Min), is_integer(Max) -> T;
+verified_type(map=T) -> T;
+verified_type(nonempty_list=T) -> T;
+verified_type({tuple,_,Sz,[]}=T) when is_integer(Sz) -> T;
+verified_type({tuple,_,Sz,[_]}=T) when is_integer(Sz) -> T;
+verified_type({tuple_element,_,_}=T) -> T;
+verified_type(float=T) -> T.
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl
index cc6e54ca16..5580d2f123 100644
--- a/lib/compiler/src/beam_utils.erl
+++ b/lib/compiler/src/beam_utils.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,15 +22,23 @@
-module(beam_utils).
-export([is_killed_block/2,is_killed/3,is_killed_at/3,
- is_not_used/3,
- empty_label_index/0,index_label/3,index_labels/1,
+ is_not_used/3,usage/3,
+ empty_label_index/0,index_label/3,index_labels/1,replace_labels/4,
code_at/2,bif_to_test/3,is_pure_test/1,
- live_opt/1,delete_live_annos/1,combine_heap_needs/2,
- split_even/1]).
+ live_opt/1,delete_annos/1,combine_heap_needs/2,
+ anno_defs/1,
+ split_even/1
+ ]).
-export_type([code_index/0,module_code/0,instruction/0]).
--import(lists, [member/2,sort/1,reverse/1,splitwith/2]).
+-import(lists, [flatmap/2,map/2,member/2,sort/1,reverse/1,splitwith/2]).
+
+-define(is_const(Val), (Val =:= nil orelse
+ element(1, Val) =:= integer orelse
+ element(1, Val) =:= float orelse
+ element(1, Val) =:= atom orelse
+ element(1, Val) =:= literal)).
%% instruction() describes all instructions that are used during optimzation
%% (from beam_a to beam_z).
@@ -54,6 +62,23 @@
{lbl :: code_index(), %Label to code index.
res :: result_cache()}). %Result cache for each label.
+%% usage(Register, [Instruction], State) -> killed|not_used|used.
+%% Determine the usage of Register in the instruction sequence.
+%% The return value is one of:
+%%
+%% killed - The register is not used in any way.
+%% not_used - The register is referenced only by an allocating instruction
+%% (the actual value does not matter).
+%% used - The register is used (its value do matter).
+
+-spec usage(beam_asm:reg(), [instruction()], code_index()) ->
+ 'killed' | 'not_used' | 'used'.
+
+usage(R, Is, D) ->
+ St = #live{lbl=D,res=gb_trees:empty()},
+ {Usage,_} = check_liveness(R, Is, St),
+ Usage.
+
%% is_killed_block(Register, [Instruction]) -> true|false
%% Determine whether a register is killed by the instruction sequence inside
@@ -70,7 +95,7 @@ is_killed_block({x,X}, [{set,_,_,{alloc,Live,_}}|_]) ->
X >= Live;
is_killed_block(R, [{set,Ds,Ss,_Op}|Is]) ->
not member(R, Ss) andalso (member(R, Ds) orelse is_killed_block(R, Is));
-is_killed_block(R, [{'%live',_,Regs}|Is]) ->
+is_killed_block(R, [{'%anno',{used,Regs}}|Is]) ->
case R of
{x,X} when (Regs bsr X) band 1 =:= 0 -> true;
_ -> is_killed_block(R, Is)
@@ -93,6 +118,7 @@ is_killed(R, Is, D) ->
St = #live{lbl=D,res=gb_trees:empty()},
case check_liveness(R, Is, St) of
{killed,_} -> true;
+ {exit_not_used,_} -> false;
{_,_} -> false
end.
@@ -105,6 +131,7 @@ is_killed_at(R, Lbl, D) when is_integer(Lbl) ->
St0 = #live{lbl=D,res=gb_trees:empty()},
case check_liveness_at(R, Lbl, St0) of
{killed,_} -> true;
+ {exit_not_used,_} -> false;
{_,_} -> false
end.
@@ -121,6 +148,7 @@ is_not_used(R, Is, D) ->
St = #live{lbl=D,res=gb_trees:empty()},
case check_liveness(R, Is, St) of
{used,_} -> false;
+ {exit_not_used,_} -> true;
{_,_} -> true
end.
@@ -160,6 +188,18 @@ index_label(Lbl, Is0, Acc) ->
code_at(L, Ll) ->
gb_trees:get(L, Ll).
+%% replace_labels(FunctionIs, Tail, ReplaceDb, Fallback) -> FunctionIs.
+%% Replace all labels in instructions according to the ReplaceDb.
+%% If label is not found the Fallback is called with the label to
+%% produce a new one.
+
+-spec replace_labels([instruction()],
+ [instruction()],
+ #{beam_asm:label() => beam_asm:label()},
+ fun((beam_asm:label()) -> term())) -> [instruction()].
+replace_labels(Is, Acc, D, Fb) ->
+ replace_labels_1(Is, Acc, D, Fb).
+
%% bif_to_test(Bif, [Op], Fail) -> {test,Test,Fail,[Op]}
%% Convert a BIF to a test. Fail if not possible.
@@ -185,10 +225,20 @@ bif_to_test('>', [A,B], Fail) -> {test,is_lt,Fail,[B,A]};
bif_to_test('<', [_,_]=Ops, Fail) -> {test,is_lt,Fail,Ops};
bif_to_test('>=', [_,_]=Ops, Fail) -> {test,is_ge,Fail,Ops};
bif_to_test('==', [A,nil], Fail) -> {test,is_nil,Fail,[A]};
+bif_to_test('==', [nil,A], Fail) -> {test,is_nil,Fail,[A]};
+bif_to_test('==', [C,A], Fail) when ?is_const(C) ->
+ {test,is_eq,Fail,[A,C]};
bif_to_test('==', [_,_]=Ops, Fail) -> {test,is_eq,Fail,Ops};
+bif_to_test('/=', [C,A], Fail) when ?is_const(C) ->
+ {test,is_ne,Fail,[A,C]};
bif_to_test('/=', [_,_]=Ops, Fail) -> {test,is_ne,Fail,Ops};
bif_to_test('=:=', [A,nil], Fail) -> {test,is_nil,Fail,[A]};
+bif_to_test('=:=', [nil,A], Fail) -> {test,is_nil,Fail,[A]};
+bif_to_test('=:=', [C,A], Fail) when ?is_const(C) ->
+ {test,is_eq_exact,Fail,[A,C]};
bif_to_test('=:=', [_,_]=Ops, Fail) -> {test,is_eq_exact,Fail,Ops};
+bif_to_test('=/=', [C,A], Fail) when ?is_const(C) ->
+ {test,is_ne_exact,Fail,[A,C]};
bif_to_test('=/=', [_,_]=Ops, Fail) -> {test,is_ne_exact,Fail,Ops};
bif_to_test(is_record, [_,_,_]=Ops, Fail) -> {test,is_record,Fail,Ops}.
@@ -220,7 +270,7 @@ is_pure_test({test,Op,_,Ops}) ->
%% Go through the instruction sequence in reverse execution
%% order, keep track of liveness and remove 'move' instructions
%% whose destination is a register that will not be used.
-%% Also insert {'%live',Live,Regs} annotations at the beginning
+%% Also insert {used,Regs} annotations at the beginning
%% and end of each block.
-spec live_opt([instruction()]) -> [instruction()].
@@ -235,35 +285,52 @@ live_opt(Is0) ->
Bef ++ [Fi|live_opt(reverse(Is), 0, D, [])].
-%% delete_live_annos([Instruction]) -> [Instruction].
-%% Delete all live annotations.
+%% delete_annos([Instruction]) -> [Instruction].
+%% Delete all annotations.
--spec delete_live_annos([instruction()]) -> [instruction()].
+-spec delete_annos([instruction()]) -> [instruction()].
-delete_live_annos([{block,Bl0}|Is]) ->
- case delete_live_annos(Bl0) of
- [] -> delete_live_annos(Is);
- [_|_]=Bl -> [{block,Bl}|delete_live_annos(Is)]
+delete_annos([{block,Bl0}|Is]) ->
+ case delete_annos(Bl0) of
+ [] -> delete_annos(Is);
+ [_|_]=Bl -> [{block,Bl}|delete_annos(Is)]
end;
-delete_live_annos([{'%live',_,_}|Is]) ->
- delete_live_annos(Is);
-delete_live_annos([I|Is]) ->
- [I|delete_live_annos(Is)];
-delete_live_annos([]) -> [].
-
+delete_annos([{'%anno',_}|Is]) ->
+ delete_annos(Is);
+delete_annos([I|Is]) ->
+ [I|delete_annos(Is)];
+delete_annos([]) -> [].
+
%% combine_heap_needs(HeapNeed1, HeapNeed2) -> HeapNeed
%% Combine the heap need for two allocation instructions.
--spec combine_heap_needs(term(), term()) -> term().
+-type heap_need_tag() :: 'floats' | 'words'.
+-type heap_need() :: non_neg_integer() |
+ {'alloc',[{heap_need_tag(),non_neg_integer()}]}.
+-spec combine_heap_needs(heap_need(), heap_need()) -> heap_need().
-combine_heap_needs({alloc,Alloc1}, {alloc,Alloc2}) ->
- {alloc,combine_alloc_lists(Alloc1, Alloc2)};
-combine_heap_needs({alloc,Alloc}, Words) when is_integer(Words) ->
- {alloc,combine_alloc_lists(Alloc, [{words,Words}])};
-combine_heap_needs(Words, {alloc,Alloc}) when is_integer(Words) ->
- {alloc,combine_alloc_lists(Alloc, [{words,Words}])};
combine_heap_needs(H1, H2) when is_integer(H1), is_integer(H2) ->
- H1+H2.
+ H1 + H2;
+combine_heap_needs(H1, H2) ->
+ {alloc,combine_alloc_lists([H1,H2])}.
+
+
+%% anno_defs(Instructions) -> Instructions'
+%% Add {def,RegisterBitmap} annotations to the beginning of
+%% each block. Iff bit X is set in the the bitmap, it means
+%% that {x,X} is defined when the block is entered.
+
+-spec anno_defs([instruction()]) -> [instruction()].
+
+anno_defs(Is0) ->
+ {Bef,[Fi|Is1]} =
+ splitwith(fun({func_info,_,_,_}) -> false;
+ (_) -> true
+ end, Is0),
+ {func_info,_,_,Arity} = Fi,
+ Regs = init_def_regs(Arity),
+ Is = defs(Is1, Regs, #{}),
+ Bef ++ [Fi|Is].
%% split_even/1
%% [1,2,3,4,5,6] -> {[1,3,5],[2,4,6]}
@@ -272,7 +339,6 @@ combine_heap_needs(H1, H2) when is_integer(H1), is_integer(H2) ->
split_even(Rs) -> split_even(Rs, [], []).
-
%%%
%%% Local functions.
%%%
@@ -284,12 +350,22 @@ split_even(Rs) -> split_even(Rs, [], []).
%%
%% killed - Reg is assigned or killed by an allocation instruction.
%% not_used - the value of Reg is not used, but Reg must not be garbage
+%% exit_not_used - the value of Reg is not used, but must not be garbage
+%% because the stack will be scanned because an
+%% exit BIF will raise an exception
%% used - Reg is used
+check_liveness({fr,_}, _, St) ->
+ %% Conservatively always consider the floating point register used.
+ {used,St};
check_liveness(R, [{block,Blk}|Is], St0) ->
case check_liveness_block(R, Blk, St0) of
{transparent,St1} ->
check_liveness(R, Is, St1);
+ {alloc_used,St1} ->
+ %% Used by an allocating instruction, but value not referenced.
+ %% Must check the rest of the instructions.
+ not_used(check_liveness(R, Is, St1));
{Other,_}=Res when is_atom(Other) ->
Res
end;
@@ -303,6 +379,8 @@ check_liveness(R, [{test,_,{f,Fail},As}|Is], St0) ->
case check_liveness_at(R, Fail, St0) of
{killed,St1} ->
check_liveness(R, Is, St1);
+ {exit_not_used,St1} ->
+ not_used(check_liveness(R, Is, St1));
{not_used,St1} ->
not_used(check_liveness(R, Is, St1));
{used,_}=Used ->
@@ -320,12 +398,14 @@ check_liveness(R, [{select,_,_,Fail,Branches}|_], St) ->
check_liveness_everywhere(R, [Fail|Branches], St);
check_liveness(R, [{jump,{f,F}}|_], St) ->
check_liveness_at(R, F, St);
-check_liveness(R, [{case_end,Used}|_], St) ->
- check_liveness_ret(R, Used, St);
+check_liveness(R, [{case_end,Used}|_], St) ->
+ check_liveness_exit(R, Used, St);
+check_liveness(R, [{try_case_end,Used}|_], St) ->
+ check_liveness_exit(R, Used, St);
check_liveness(R, [{badmatch,Used}|_], St) ->
- check_liveness_ret(R, Used, St);
-check_liveness(_, [if_end|_], St) ->
- {killed,St};
+ check_liveness_exit(R, Used, St);
+check_liveness(R, [if_end|_], St) ->
+ check_liveness_exit(R, ignore, St);
check_liveness(R, [{func_info,_,_,Ar}|_], St) ->
case R of
{x,X} when X < Ar -> {used,St};
@@ -348,17 +428,27 @@ check_liveness(R, [{bs_init,_,_,none,Ss,Dst}|Is], St) ->
check_liveness(R, [{bs_init,_,_,Live,Ss,Dst}|Is], St) ->
case R of
{x,X} ->
- case X < Live orelse member(R, Ss) of
- true -> {used,St};
- false -> {killed,St}
+ case member(R, Ss) of
+ true ->
+ {used,St};
+ false ->
+ if
+ X < Live ->
+ not_used(check_liveness(R, Is, St));
+ true ->
+ {killed,St}
+ end
end;
{y,_} ->
case member(R, Ss) of
true -> {used,St};
false ->
+ %% If the exception is taken, the stack may
+ %% be scanned. Therefore the register is not
+ %% guaranteed to be killed.
if
- R =:= Dst -> {killed,St};
- true -> check_liveness(R, Is, St)
+ R =:= Dst -> {not_used,St};
+ true -> not_used(check_liveness(R, Is, St))
end
end
end;
@@ -392,7 +482,7 @@ check_liveness(R, [{call_ext,Live,_}=I|Is], St) ->
%% We must make sure we don't check beyond this
%% instruction or we will fall through into random
%% unrelated code and get stuck in a loop.
- {killed,St}
+ {exit_not_used,St}
end
end;
check_liveness(R, [{call_fun,Live}|Is], St) ->
@@ -440,16 +530,12 @@ check_liveness(R, [{make_fun2,_,_,_,NumFree}|Is], St) ->
{x,_} -> {killed,St};
{y,_} -> not_used(check_liveness(R, Is, St))
end;
-check_liveness({x,_}=R, [{'catch',_,_}|Is], St) ->
- %% All x registers will be killed if an exception occurs.
- %% Therefore we only need to check the liveness for the
- %% instructions following the catch instruction.
- check_liveness(R, Is, St);
-check_liveness({x,_}=R, [{'try',_,_}|Is], St) ->
- %% All x registers will be killed if an exception occurs.
- %% Therefore we only need to check the liveness for the
- %% instructions inside the 'try' block.
- check_liveness(R, Is, St);
+check_liveness(R, [{'catch'=Op,Y,Fail}|Is], St) ->
+ Set = {set,[Y],[],{try_catch,Op,Fail}},
+ check_liveness(R, [{block,[Set]}|Is], St);
+check_liveness(R, [{'try'=Op,Y,Fail}|Is], St) ->
+ Set = {set,[Y],[],{try_catch,Op,Fail}},
+ check_liveness(R, [{block,[Set]}|Is], St);
check_liveness(R, [{try_end,Y}|Is], St) ->
case R of
Y ->
@@ -510,15 +596,34 @@ check_liveness(R, [{get_map_elements,{f,Fail},S,{list,L}}|Is], St0) ->
check_liveness(R, [{put_map,F,Op,S,D,Live,{list,Puts}}|Is], St) ->
Set = {set,[D],[S|Puts],{alloc,Live,{put_map,Op,F}}},
check_liveness(R, [{block,[Set]}||Is], St);
+check_liveness(R, [{put_tuple,Ar,D}|Is], St) ->
+ Set = {set,[D],[],{put_tuple,Ar}},
+ check_liveness(R, [{block,[Set]}||Is], St);
+check_liveness(R, [{put_list,S1,S2,D}|Is], St) ->
+ Set = {set,[D],[S1,S2],put_list},
+ check_liveness(R, [{block,[Set]}||Is], St);
check_liveness(R, [{test_heap,N,Live}|Is], St) ->
I = {block,[{set,[],[],{alloc,Live,{nozero,nostack,N,[]}}}]},
check_liveness(R, [I|Is], St);
check_liveness(R, [{allocate_zero,N,Live}|Is], St) ->
I = {block,[{set,[],[],{alloc,Live,{zero,N,0,[]}}}]},
check_liveness(R, [I|Is], St);
-check_liveness(R, [{get_list,S,D1,D2}|Is], St) ->
- I = {block,[{set,[D1,D2],[S],get_list}]},
+check_liveness(R, [{get_hd,S,D}|Is], St) ->
+ I = {block,[{set,[D],[S],get_hd}]},
+ check_liveness(R, [I|Is], St);
+check_liveness(R, [{get_tl,S,D}|Is], St) ->
+ I = {block,[{set,[D],[S],get_tl}]},
check_liveness(R, [I|Is], St);
+check_liveness(R, [remove_message|Is], St) ->
+ check_liveness(R, Is, St);
+check_liveness({x,X}, [build_stacktrace|_], St) when X > 0 ->
+ {killed,St};
+check_liveness(R, [{recv_mark,_}|Is], St) ->
+ check_liveness(R, Is, St);
+check_liveness(R, [{recv_set,_}|Is], St) ->
+ check_liveness(R, Is, St);
+check_liveness(R, [{'%',_}|Is], St) ->
+ check_liveness(R, Is, St);
check_liveness(_R, Is, St) when is_list(Is) ->
%% Not implemented. Conservatively assume that the register is used.
{used,St}.
@@ -553,14 +658,15 @@ check_liveness_at(R, Lbl, #live{lbl=Ll,res=ResMemorized}=St0) ->
{Res,St#live{res=gb_trees:insert(Lbl, Res, St#live.res)}}
end.
-not_used({killed,St}) -> {not_used,St};
-not_used({_,_}=Res) -> Res.
+not_used({used,_}=Res) -> Res;
+not_used({_,St}) -> {not_used,St}.
-check_liveness_ret(R, R, St) -> {used,St};
-check_liveness_ret(_, _, St) -> {killed,St}.
+check_liveness_exit(R, R, St) -> {used,St};
+check_liveness_exit({x,_}, _, St) -> {killed,St};
+check_liveness_exit({y,_}, _, St) -> {exit_not_used,St}.
%% check_liveness_block(Reg, [Instruction], State) ->
-%% {killed | not_used | used | transparent,State'}
+%% {killed | not_used | used | alloc_used | transparent,State'}
%% Finds out how Reg is used in the instruction sequence inside a block.
%% Returns one of:
%% killed - Reg is assigned a new value or killed by an
@@ -568,9 +674,10 @@ check_liveness_ret(_, _, St) -> {killed,St}.
%% not_used - The value is not used, but the register is referenced
%% e.g. by an allocation instruction
%% transparent - Reg is neither used nor killed
+%% alloc_used - Used only in an allocate instruction
%% used - Reg is explicitly used by an instruction
%%
-%% '%live' annotations are not allowed.
+%% Annotations are not allowed.
%%
%% (Unknown instructions will cause an exception.)
@@ -580,13 +687,30 @@ check_liveness_block({x,X}=R, [{set,Ds,Ss,{alloc,Live,Op}}|Is], St0) ->
{killed,St0};
true ->
case check_liveness_block_1(R, Ss, Ds, Op, Is, St0) of
- {killed,St} -> {not_used,St};
- {transparent,St} -> {not_used,St};
- {_,_}=Res -> Res
+ {transparent,St} -> {alloc_used,St};
+ {_,_}=Res -> not_used(Res)
end
end;
-check_liveness_block({y,_}=R, [{set,Ds,Ss,{alloc,_Live,Op}}|Is], St) ->
- check_liveness_block_1(R, Ss, Ds, Op, Is, St);
+check_liveness_block({y,_}=R, [{set,Ds,Ss,{alloc,_Live,Op}}|Is], St0) ->
+ case check_liveness_block_1(R, Ss, Ds, Op, Is, St0) of
+ {transparent,St} -> {alloc_used,St};
+ {_,_}=Res -> not_used(Res)
+ end;
+check_liveness_block({y,_}=R, [{set,Ds,Ss,{try_catch,_,Op}}|Is], St0) ->
+ case Ds of
+ [R] ->
+ {killed,St0};
+ _ ->
+ case check_liveness_block_1(R, Ss, Ds, Op, Is, St0) of
+ {exit_not_used,St} ->
+ {used,St};
+ {transparent,St} ->
+ %% Conservatively assumed that it is used.
+ {used,St};
+ {_,_}=Res ->
+ Res
+ end
+ end;
check_liveness_block(R, [{set,Ds,Ss,Op}|Is], St) ->
check_liveness_block_1(R, Ss, Ds, Op, Is, St);
check_liveness_block(_, [], St) -> {transparent,St}.
@@ -602,6 +726,11 @@ check_liveness_block_1(R, Ss, Ds, Op, Is, St0) ->
true -> {killed,St};
false -> check_liveness_block(R, Is, St)
end;
+ {exit_not_used,St} ->
+ case member(R, Ds) of
+ true -> {exit_not_used,St};
+ false -> check_liveness_block(R, Is, St)
+ end;
{not_used,St} ->
not_used(case member(R, Ds) of
true -> {killed,St};
@@ -612,8 +741,8 @@ check_liveness_block_1(R, Ss, Ds, Op, Is, St0) ->
end
end.
-check_liveness_block_2(R, {gc_bif,_Op,{f,Lbl}}, _Ss, St) ->
- check_liveness_block_3(R, Lbl, St);
+check_liveness_block_2(R, {gc_bif,Op,{f,Lbl}}, Ss, St) ->
+ check_liveness_block_3(R, Lbl, {Op,length(Ss)}, St);
check_liveness_block_2(R, {bif,Op,{f,Lbl}}, Ss, St) ->
Arity = length(Ss),
case erl_internal:comp_op(Op, Arity) orelse
@@ -621,16 +750,23 @@ check_liveness_block_2(R, {bif,Op,{f,Lbl}}, Ss, St) ->
true ->
{killed,St};
false ->
- check_liveness_block_3(R, Lbl, St)
+ check_liveness_block_3(R, Lbl, {Op,length(Ss)}, St)
end;
check_liveness_block_2(R, {put_map,_Op,{f,Lbl}}, _Ss, St) ->
- check_liveness_block_3(R, Lbl, St);
+ check_liveness_block_3(R, Lbl, {unsafe,0}, St);
check_liveness_block_2(_, _, _, St) ->
{killed,St}.
-check_liveness_block_3(_, 0, St) ->
+check_liveness_block_3({x,_}, 0, _FA, St) ->
{killed,St};
-check_liveness_block_3(R, Lbl, St0) ->
+check_liveness_block_3({y,_}, 0, {F,A}, St) ->
+ %% If the exception is thrown, the stack may be scanned,
+ %% thus implicitly using the y register.
+ case erl_bifs:is_safe(erlang, F, A) of
+ true -> {killed,St};
+ false -> {used,St}
+ end;
+check_liveness_block_3(R, Lbl, _FA, St0) ->
check_liveness_at(R, Lbl, St0).
index_labels_1([{label,Lbl}|Is0], Acc) ->
@@ -643,22 +779,74 @@ index_labels_1([], Acc) -> gb_trees:from_orddict(sort(Acc)).
drop_labels([{label,_}|Is]) -> drop_labels(Is);
drop_labels(Is) -> Is.
-%% Help functions for combine_heap_needs.
-combine_alloc_lists(Al1, Al2) ->
- combine_alloc_lists_1(sort(Al1++Al2)).
+replace_labels_1([{test,Test,{f,Lbl},Ops}|Is], Acc, D, Fb) ->
+ replace_labels_1(Is, [{test,Test,{f,label(Lbl, D, Fb)},Ops}|Acc], D, Fb);
+replace_labels_1([{test,Test,{f,Lbl},Live,Ops,Dst}|Is], Acc, D, Fb) ->
+ replace_labels_1(Is, [{test,Test,{f,label(Lbl, D, Fb)},Live,Ops,Dst}|Acc], D, Fb);
+replace_labels_1([{select,I,R,{f,Fail0},Vls0}|Is], Acc, D, Fb) ->
+ Vls = map(fun ({f,L}) -> {f,label(L, D, Fb)};
+ (Other) -> Other
+ end, Vls0),
+ Fail = label(Fail0, D, Fb),
+ replace_labels_1(Is, [{select,I,R,{f,Fail},Vls}|Acc], D, Fb);
+replace_labels_1([{'try',R,{f,Lbl}}|Is], Acc, D, Fb) ->
+ replace_labels_1(Is, [{'try',R,{f,label(Lbl, D, Fb)}}|Acc], D, Fb);
+replace_labels_1([{'catch',R,{f,Lbl}}|Is], Acc, D, Fb) ->
+ replace_labels_1(Is, [{'catch',R,{f,label(Lbl, D, Fb)}}|Acc], D, Fb);
+replace_labels_1([{jump,{f,Lbl}}|Is], Acc, D, Fb) ->
+ replace_labels_1(Is, [{jump,{f,label(Lbl, D, Fb)}}|Acc], D, Fb);
+replace_labels_1([{loop_rec,{f,Lbl},R}|Is], Acc, D, Fb) ->
+ replace_labels_1(Is, [{loop_rec,{f,label(Lbl, D, Fb)},R}|Acc], D, Fb);
+replace_labels_1([{loop_rec_end,{f,Lbl}}|Is], Acc, D, Fb) ->
+ replace_labels_1(Is, [{loop_rec_end,{f,label(Lbl, D, Fb)}}|Acc], D, Fb);
+replace_labels_1([{wait,{f,Lbl}}|Is], Acc, D, Fb) ->
+ replace_labels_1(Is, [{wait,{f,label(Lbl, D, Fb)}}|Acc], D, Fb);
+replace_labels_1([{wait_timeout,{f,Lbl},To}|Is], Acc, D, Fb) ->
+ replace_labels_1(Is, [{wait_timeout,{f,label(Lbl, D, Fb)},To}|Acc], D, Fb);
+replace_labels_1([{recv_mark=Op,{f,Lbl}}|Is], Acc, D, Fb) ->
+ replace_labels_1(Is, [{Op,{f,label(Lbl, D, Fb)}}|Acc], D, Fb);
+replace_labels_1([{recv_set=Op,{f,Lbl}}|Is], Acc, D, Fb) ->
+ replace_labels_1(Is, [{Op,{f,label(Lbl, D, Fb)}}|Acc], D, Fb);
+replace_labels_1([{bif,Name,{f,Lbl},As,R}|Is], Acc, D, Fb) when Lbl =/= 0 ->
+ replace_labels_1(Is, [{bif,Name,{f,label(Lbl, D, Fb)},As,R}|Acc], D, Fb);
+replace_labels_1([{gc_bif,Name,{f,Lbl},Live,As,R}|Is], Acc, D, Fb) when Lbl =/= 0 ->
+ replace_labels_1(Is, [{gc_bif,Name,{f,label(Lbl, D, Fb)},Live,As,R}|Acc], D, Fb);
+replace_labels_1([{call,Ar,{f,Lbl}}|Is], Acc, D, Fb) ->
+ replace_labels_1(Is, [{call,Ar,{f,label(Lbl, D, Fb)}}|Acc], D, Fb);
+replace_labels_1([{make_fun2,{f,Lbl},U1,U2,U3}|Is], Acc, D, Fb) ->
+ replace_labels_1(Is, [{make_fun2,{f,label(Lbl, D, Fb)},U1,U2,U3}|Acc], D, Fb);
+replace_labels_1([{bs_init,{f,Lbl},Info,Live,Ss,Dst}|Is], Acc, D, Fb) when Lbl =/= 0 ->
+ replace_labels_1(Is, [{bs_init,{f,label(Lbl, D, Fb)},Info,Live,Ss,Dst}|Acc], D, Fb);
+replace_labels_1([{bs_put,{f,Lbl},Info,Ss}|Is], Acc, D, Fb) when Lbl =/= 0 ->
+ replace_labels_1(Is, [{bs_put,{f,label(Lbl, D, Fb)},Info,Ss}|Acc], D, Fb);
+replace_labels_1([{put_map=I,{f,Lbl},Op,Src,Dst,Live,List}|Is], Acc, D, Fb)
+ when Lbl =/= 0 ->
+ replace_labels_1(Is, [{I,{f,label(Lbl, D, Fb)},Op,Src,Dst,Live,List}|Acc], D, Fb);
+replace_labels_1([{get_map_elements=I,{f,Lbl},Src,List}|Is], Acc, D, Fb) when Lbl =/= 0 ->
+ replace_labels_1(Is, [{I,{f,label(Lbl, D, Fb)},Src,List}|Acc], D, Fb);
+replace_labels_1([I|Is], Acc, D, Fb) ->
+ replace_labels_1(Is, [I|Acc], D, Fb);
+replace_labels_1([], Acc, _, _) -> Acc.
+
+label(Old, D, Fb) ->
+ case D of
+ #{Old := New} -> New;
+ _ -> Fb(Old)
+ end.
+
+%% Help function for combine_heap_needs.
-combine_alloc_lists_1([{words,W1},{words,W2}|T])
- when is_integer(W1), is_integer(W2) ->
- [{words,W1+W2}|combine_alloc_lists_1(T)];
-combine_alloc_lists_1([{floats,F1},{floats,F2}|T])
- when is_integer(F1), is_integer(F2) ->
- [{floats,F1+F2}|combine_alloc_lists_1(T)];
-combine_alloc_lists_1([{words,_}=W|T]) ->
- [W|combine_alloc_lists_1(T)];
-combine_alloc_lists_1([{floats,_}=F|T]) ->
- [F|combine_alloc_lists_1(T)];
-combine_alloc_lists_1([]) -> [].
+combine_alloc_lists(Al0) ->
+ Al1 = flatmap(fun(Words) when is_integer(Words) ->
+ [{words,Words}];
+ ({alloc,List}) ->
+ List
+ end, Al0),
+ Al2 = sofs:relation(Al1),
+ Al3 = sofs:relation_to_family(Al2),
+ Al4 = sofs:to_external(Al3),
+ [{Tag,lists:sum(L)} || {Tag,L} <- Al4].
%% live_opt/4.
@@ -697,10 +885,14 @@ live_opt([{test,bs_start_match2,Fail,Live,[Src,_],_}=I|Is], _, D, Acc) ->
%% Other instructions.
live_opt([{block,Bl0}|Is], Regs0, D, Acc) ->
- Live0 = {'%live',live_regs(Regs0),Regs0},
+ Live0 = make_anno({used,Regs0}),
{Bl,Regs} = live_opt_block(reverse(Bl0), Regs0, D, [Live0]),
- Live = {'%live',live_regs(Regs),Regs},
+ Live = make_anno({used,Regs}),
live_opt(Is, Regs, D, [{block,[Live|Bl]}|Acc]);
+live_opt([build_stacktrace=I|Is], _, D, Acc) ->
+ live_opt(Is, live_call(1), D, [I|Acc]);
+live_opt([raw_raise=I|Is], _, D, Acc) ->
+ live_opt(Is, live_call(3), D, [I|Acc]);
live_opt([{label,L}=I|Is], Regs, D0, Acc) ->
D = gb_trees:insert(L, Regs, D0),
live_opt(Is, Regs, D, [I|Acc]);
@@ -742,12 +934,19 @@ live_opt([{test,_,Fail,Live,Ss,_}=I|Is], _, D, Acc) ->
Regs1 = x_live(Ss, Regs0),
Regs = live_join_label(Fail, D, Regs1),
live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{select,_,Src,Fail,List}=I|Is], Regs0, D, Acc) ->
+live_opt([{select,_,Src,Fail,List}=I|Is], _, D, Acc) ->
+ Regs0 = 0,
Regs1 = x_live([Src], Regs0),
Regs = live_join_labels([Fail|List], D, Regs1),
live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{try_case,_}=I|Is], _, D, Acc) ->
- live_opt(Is, live_call(1), D, [I|Acc]);
+live_opt([{try_case,Y}=I|Is], Regs0, D, Acc) ->
+ Regs = live_call(1),
+ case Regs0 of
+ 0 ->
+ live_opt(Is, Regs, D, [{try_end,Y}|Acc]);
+ _ ->
+ live_opt(Is, live_call(1), D, [I|Acc])
+ end;
live_opt([{loop_rec,_Fail,_Dst}=I|Is], _, D, Acc) ->
live_opt(Is, 0, D, [I|Acc]);
live_opt([timeout=I|Is], _, D, Acc) ->
@@ -759,6 +958,25 @@ live_opt([{get_map_elements,Fail,Src,{list,List}}=I|Is], Regs0, D, Acc) ->
Regs1 = x_live([Src|Ss], x_dead(Ds, Regs0)),
Regs = live_join_label(Fail, D, Regs1),
live_opt(Is, Regs, D, [I|Acc]);
+live_opt([{gc_bif,N,F,R,As,Dst}=I|Is], Regs0, D, Acc) ->
+ Bl = [{set,[Dst],As,{alloc,R,{gc_bif,N,F}}}],
+ {_,Regs} = live_opt_block(Bl, Regs0, D, []),
+ live_opt(Is, Regs, D, [I|Acc]);
+live_opt([{bif,N,F,As,Dst}=I|Is], Regs0, D, Acc) ->
+ Bl = [{set,[Dst],As,{bif,N,F}}],
+ {_,Regs} = live_opt_block(Bl, Regs0, D, []),
+ live_opt(Is, Regs, D, [I|Acc]);
+live_opt([{get_tuple_element,Src,Idx,Dst}=I|Is], Regs0, D, Acc) ->
+ Bl = [{set,[Dst],[Src],{get_tuple_element,Idx}}],
+ {_,Regs} = live_opt_block(Bl, Regs0, D, []),
+ live_opt(Is, Regs, D, [I|Acc]);
+live_opt([{move,Src,Dst}=I|Is], Regs0, D, Acc) ->
+ Regs = x_live([Src], x_dead([Dst], Regs0)),
+ live_opt(Is, Regs, D, [I|Acc]);
+live_opt([{put_map,F,Op,S,Dst,R,{list,Puts}}=I|Is], Regs0, D, Acc) ->
+ Bl = [{set,[Dst],[S|Puts],{alloc,R,{put_map,Op,F}}}],
+ {_,Regs} = live_opt_block(Bl, Regs0, D, []),
+ live_opt(Is, Regs, D, [I|Acc]);
%% Transparent instructions - they neither use nor modify x registers.
live_opt([{deallocate,_}=I|Is], Regs, D, Acc) ->
@@ -775,6 +993,10 @@ live_opt([{wait_timeout,_,{Tag,_}}=I|Is], Regs, D, Acc) when Tag =/= x ->
live_opt(Is, Regs, D, [I|Acc]);
live_opt([{line,_}=I|Is], Regs, D, Acc) ->
live_opt(Is, Regs, D, [I|Acc]);
+live_opt([{'catch',_,_}=I|Is], Regs, D, Acc) ->
+ live_opt(Is, Regs, D, [I|Acc]);
+live_opt([{'try',_,_}=I|Is], Regs, D, Acc) ->
+ live_opt(Is, Regs, D, [I|Acc]);
%% The following instructions can occur if the "compilation" has been
%% started from a .S file using the 'from_asm' option.
@@ -789,39 +1011,53 @@ live_opt([{recv_mark,_}=I|Is], Regs, D, Acc) ->
live_opt([], _, _, Acc) -> Acc.
-live_opt_block([{set,Ds,Ss,Op}=I0|Is], Regs0, D, Acc) ->
- Regs1 = x_live(Ss, x_dead(Ds, Regs0)),
- {I,Regs} = case Op of
- {alloc,Live0,Alloc} ->
- %% The life-time analysis used by the code generator
- %% is sometimes too conservative, so it may be
- %% possible to lower the number of live registers
- %% based on the exact liveness information.
- %% The main benefit is that more optimizations that
- %% depend on liveness information (such as the
- %% beam_bool and beam_dead passes) may be applied.
- Live = live_regs(Regs1),
- true = Live =< Live0, %Assertion.
- I1 = {set,Ds,Ss,{alloc,Live,Alloc}},
- {I1,live_call(Live)};
- _ ->
- {I0,Regs1}
- end,
- case Ds of
- [{x,X}] ->
- case (not is_live(X, Regs0)) andalso Op =:= move of
- true ->
- live_opt_block(Is, Regs0, D, Acc);
- false ->
- live_opt_block(Is, Regs, D, [I|Acc])
- end;
- _ ->
- live_opt_block(Is, Regs, D, [I|Acc])
+live_opt_block([{set,[{x,X}]=Ds,Ss,move}=I|Is], Regs0, D, Acc) ->
+ Regs = x_live(Ss, x_dead(Ds, Regs0)),
+ case is_live(X, Regs0) of
+ true ->
+ live_opt_block(Is, Regs, D, [I|Acc]);
+ false ->
+ %% Useless move, will never be used.
+ live_opt_block(Is, Regs, D, Acc)
end;
-live_opt_block([{'%live',_,_}|Is], Regs, D, Acc) ->
+live_opt_block([{set,Ds,Ss,{alloc,Live0,AllocOp}}|Is], Regs0, D, Acc) ->
+ %% Calculate liveness from the point of view of the GC.
+ %% There will never be a GC if the instruction fails, so we should
+ %% ignore the failure branch.
+ GcRegs1 = x_dead(Ds, Regs0),
+ GcRegs = x_live(Ss, GcRegs1),
+ Live = live_regs(GcRegs),
+
+ %% The life-time analysis used by the code generator is sometimes too
+ %% conservative, so it may be possible to lower the number of live
+ %% registers based on the exact liveness information. The main benefit is
+ %% that more optimizations that depend on liveness information (such as the
+ %% beam_dead pass) may be applied.
+ true = Live =< Live0, %Assertion.
+ I = {set,Ds,Ss,{alloc,Live,AllocOp}},
+
+ %% Calculate liveness from the point of view of the preceding instruction.
+ %% The liveness is the union of live registers in the GC and the live
+ %% registers at the failure label.
+ Regs1 = live_call(Live),
+ Regs = live_join_alloc(AllocOp, D, Regs1),
+ live_opt_block(Is, Regs, D, [I|Acc]);
+live_opt_block([{set,Ds,Ss,{bif,_,Fail}}=I|Is], Regs0, D, Acc) ->
+ Regs1 = x_dead(Ds, Regs0),
+ Regs2 = x_live(Ss, Regs1),
+ Regs = live_join_label(Fail, D, Regs2),
+ live_opt_block(Is, Regs, D, [I|Acc]);
+live_opt_block([{set,Ds,Ss,_}=I|Is], Regs0, D, Acc) ->
+ Regs = x_live(Ss, x_dead(Ds, Regs0)),
+ live_opt_block(Is, Regs, D, [I|Acc]);
+live_opt_block([{'%anno',_}|Is], Regs, D, Acc) ->
live_opt_block(Is, Regs, D, Acc);
live_opt_block([], Regs, _, Acc) -> {Acc,Regs}.
+live_join_alloc({Kind,_Name,Fail}, D, Regs) when Kind =:= gc_bif; Kind =:= put_map ->
+ live_join_label(Fail, D, Regs);
+live_join_alloc(_, _, Regs) -> Regs.
+
live_join_labels([{f,L}|T], D, Regs0) when L =/= 0 ->
Regs = gb_trees:get(L, D) bor Regs0,
live_join_labels(T, D, Regs);
@@ -856,3 +1092,224 @@ split_even([], Ss, Ds) ->
{reverse(Ss),reverse(Ds)};
split_even([S,D|Rs], Ss, Ds) ->
split_even(Rs, [S|Ss], [D|Ds]).
+
+%%%
+%%% Add annotations for defined registers.
+%%%
+%%% This analysis is done by scanning the instructions in
+%%% execution order.
+%%%
+
+defs([{apply,_}=I|Is], _Regs, D) ->
+ [I|defs(Is, 1, D)];
+defs([{bif,_,{f,Fail},_Src,Dst}=I|Is], Regs0, D) ->
+ Regs = def_regs([Dst], Regs0),
+ [I|defs(Is, Regs, update_regs(Fail, Regs0, D))];
+defs([{block,Block0}|Is], Regs0, D0) ->
+ {Block,Regs,D} = defs_list(Block0, Regs0, D0),
+ [{block,[make_anno({def,Regs0})|Block]}|defs(Is, Regs, D)];
+defs([{bs_init,{f,L},_,Live,_,Dst}=I|Is], Regs0, D) ->
+ Regs1 = case Live of
+ none -> Regs0;
+ _ -> init_def_regs(Live)
+ end,
+ Regs = def_regs([Dst], Regs1),
+ [I|defs(Is, Regs, update_regs(L, Regs, D))];
+defs([{bs_put,{f,L},_,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, update_regs(L, Regs, D))];
+defs([build_stacktrace=I|Is], _Regs, D) ->
+ [I|defs(Is, 1, D)];
+defs([{call,_,_}=I|Is], _Regs, D) ->
+ [I|defs(Is, 1, D)];
+defs([{call_ext,_,{extfunc,M,F,A}}=I|Is], _Regs, D) ->
+ case erl_bifs:is_exit_bif(M, F, A) of
+ false ->
+ [I|defs(Is, 1, D)];
+ true ->
+ [I|defs_unreachable(Is, D)]
+ end;
+defs([{call_ext,_,_}=I|Is], _Regs, D) ->
+ [I|defs(Is, 1, D)];
+defs([{call_fun,_}=I|Is], _Regs, D) ->
+ [I|defs(Is, 1, D)];
+defs([{'catch',_,{f,L}}=I|Is], Regs, D) ->
+ RegsAtLabel = init_def_regs(1),
+ [I|defs(Is, Regs, update_regs(L, RegsAtLabel, D))];
+defs([{catch_end,_}=I|Is], _Regs, D) ->
+ Regs = init_def_regs(1),
+ [I|defs(Is, Regs, D)];
+defs([{gc_bif,_,{f,Fail},Live,_Src,Dst}=I|Is], Regs0, D) ->
+ true = all_defined(Live, Regs0), %Assertion.
+ Regs = def_regs([Dst], init_def_regs(Live)),
+ [I|defs(Is, Regs, update_regs(Fail, Regs0, D))];
+defs([{get_map_elements,{f,L},_Src,{list,DstList}}=I|Is], Regs0, D) ->
+ {_,Ds} = beam_utils:split_even(DstList),
+ Regs = def_regs(Ds, Regs0),
+ [I|defs(Is, Regs, update_regs(L, Regs0, D))];
+defs([{get_tuple_element,_,_,Dst}=I|Is], Regs0, D) ->
+ Regs = def_regs([Dst], Regs0),
+ [I|defs(Is, Regs, D)];
+defs([{jump,{f,L}}=I|Is], Regs, D) ->
+ [I|defs_unreachable(Is, update_regs(L, Regs, D))];
+defs([{label,L}=I|Is], Regs0, D) ->
+ case D of
+ #{L:=Regs1} ->
+ Regs = Regs0 band Regs1,
+ [I|defs(Is, Regs, D)];
+ #{} ->
+ [I|defs(Is, Regs0, D)]
+ end;
+defs([{loop_rec,{f,L},{x,0}}=I|Is], _Regs, D0) ->
+ RegsAtLabel = init_def_regs(0),
+ D = update_regs(L, RegsAtLabel, D0),
+ [I|defs(Is, init_def_regs(1), D)];
+defs([{loop_rec_end,_}=I|Is], _Regs, D) ->
+ [I|defs_unreachable(Is, D)];
+defs([{make_fun2,_,_,_,_}=I|Is], _Regs, D) ->
+ [I|defs(Is, 1, D)];
+defs([{move,_,Dst}=I|Is], Regs0, D) ->
+ Regs = def_regs([Dst], Regs0),
+ [I|defs(Is, Regs, D)];
+defs([{put_map,{f,Fail},_,_,Dst,_,_}=I|Is], Regs0, D) ->
+ Regs = def_regs([Dst], Regs0),
+ [I|defs(Is, Regs, update_regs(Fail, Regs0, D))];
+defs([raw_raise=I|Is], _Regs, D) ->
+ [I|defs(Is, 1, D)];
+defs([return=I|Is], _Regs, D) ->
+ [I|defs_unreachable(Is, D)];
+defs([{select,_,_Src,Fail,List}=I|Is], Regs, D0) ->
+ D = update_list([Fail|List], Regs, D0),
+ [I|defs_unreachable(Is, D)];
+defs([{test,_,{f,L},_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, update_regs(L, Regs, D))];
+defs([{test,_,{f,L},Live,_,Dst}=I|Is], Regs0, D) ->
+ true = all_defined(Live, Regs0), %Assertion.
+ Regs = def_regs([Dst], init_def_regs(Live)),
+ [I|defs(Is, Regs, update_regs(L, Regs0, D))];
+defs([{'try',_,{f,L}}=I|Is], Regs, D) ->
+ RegsAtLabel = init_def_regs(3),
+ [I|defs(Is, Regs, update_regs(L, RegsAtLabel, D))];
+defs([{try_case,_}=I|Is], _Regs, D) ->
+ [I|defs(Is, init_def_regs(3), D)];
+defs([{wait,_}=I|Is], _Regs, D) ->
+ [I|defs_unreachable(Is, D)];
+defs([{wait_timeout,_,_}=I|Is], _Regs, D) ->
+ [I|defs(Is, 0, D)];
+
+%% Exceptions.
+defs([{badmatch,_}=I|Is], _Regs, D) ->
+ [I|defs_unreachable(Is, D)];
+defs([{case_end,_}=I|Is], _Regs, D) ->
+ [I|defs_unreachable(Is, D)];
+defs([if_end=I|Is], _Regs, D) ->
+ [I|defs_unreachable(Is, D)];
+defs([{try_case_end,_}=I|Is], _Regs, D) ->
+ [I|defs_unreachable(Is, D)];
+
+%% Neutral instructions
+defs([{bs_context_to_binary,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{bs_restore2,_,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{bs_save2,_,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{deallocate,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{kill,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{line,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{recv_mark,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{recv_set,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([timeout=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{trim,_,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{try_end,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{'%',_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([], _, _) -> [].
+
+defs_unreachable([{label,L}=I|Is], D) ->
+ case D of
+ #{L:=Regs} ->
+ [I|defs(Is, Regs, D)];
+ #{} ->
+ defs_unreachable(Is, D)
+ end;
+defs_unreachable([_|Is], D) ->
+ defs_unreachable(Is, D);
+defs_unreachable([], _D) -> [].
+
+defs_list(Is, Regs, D) ->
+ defs_list(Is, Regs, D, []).
+
+defs_list([{set,Ds,_,{alloc,Live,Info}}=I|Is], Regs0, D0, Acc) ->
+ true = all_defined(Live, Regs0), %Assertion.
+ D = case Info of
+ {gc_bif,_,{f,Fail}} ->
+ update_regs(Fail, Regs0, D0);
+ {put_map,_,{f,Fail}} ->
+ update_regs(Fail, Regs0, D0);
+ _ ->
+ D0
+ end,
+ Regs = def_regs(Ds, init_def_regs(Live)),
+ defs_list(Is, Regs, D, [I|Acc]);
+defs_list([{set,Ds,_,Info}=I|Is], Regs0, D0, Acc) ->
+ D = case Info of
+ {bif,_,{f,Fail}} ->
+ update_regs(Fail, Regs0, D0);
+ {try_catch,'catch',{f,Fail}} ->
+ update_regs(Fail, init_def_regs(1), D0);
+ {try_catch,'try',{f,Fail}} ->
+ update_regs(Fail, init_def_regs(3), D0);
+ _ ->
+ D0
+ end,
+ Regs = def_regs(Ds, Regs0),
+ defs_list(Is, Regs, D, [I|Acc]);
+defs_list([], Regs, D, Acc) ->
+ {reverse(Acc),Regs,D}.
+
+init_def_regs(Arity) ->
+ (1 bsl Arity) - 1.
+
+def_regs([{x,X}|T], Regs) ->
+ def_regs(T, Regs bor (1 bsl X));
+def_regs([_|T], Regs) ->
+ def_regs(T, Regs);
+def_regs([], Regs) -> Regs.
+
+update_list([{f,L}|T], Regs, D0) ->
+ D = update_regs(L, Regs, D0),
+ update_list(T, Regs, D);
+update_list([_|T], Regs, D) ->
+ update_list(T, Regs, D);
+update_list([], _Regs, D) -> D.
+
+update_regs(L, Regs0, D) ->
+ case D of
+ #{L:=Regs1} ->
+ Regs = Regs0 band Regs1,
+ D#{L:=Regs};
+ #{} ->
+ D#{L=>Regs0}
+ end.
+
+all_defined(Live, Regs) ->
+ All = (1 bsl Live) - 1,
+ Regs band All =:= All.
+
+%%%
+%%% Utilities.
+%%%
+
+%% make_anno(Anno) -> WrappedAnno.
+%% Wrap an annotation term.
+
+make_anno(Anno) ->
+ {'%anno',Anno}.
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index f726625510..fb2e7df65c 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,9 +27,7 @@
%% Interface for compiler.
-export([module/2, format_error/1]).
--include("beam_disasm.hrl").
-
--import(lists, [reverse/1,foldl/3,foreach/2,dropwhile/2]).
+-import(lists, [any/2,dropwhile/2,foldl/3,foreach/2,reverse/1]).
%% To be called by the compiler.
@@ -85,8 +83,6 @@ format_error(Error) ->
%%% Things currently not checked. XXX
%%%
%%% - Heap allocation for binaries.
-%%% - That put_tuple is followed by the correct number of
-%%% put instructions.
%%%
%% validate(Module, [Function]) -> [] | [Error]
@@ -130,9 +126,8 @@ validate_0(Module, [{function,Name,Ar,Entry,Code}|Fs], Ft) ->
throw:Error ->
%% Controlled error.
[Error|validate_0(Module, Fs, Ft)];
- Class:Error ->
+ Class:Error:Stack ->
%% Crash.
- Stack = erlang:get_stacktrace(),
io:fwrite("Function: ~w/~w\n", [Name,Ar]),
erlang:raise(Class, Error, Stack)
end.
@@ -149,7 +144,8 @@ validate_0(Module, [{function,Name,Ar,Entry,Code}|Fs], Ft) ->
hf=0, %Available heap size for floats.
fls=undefined, %Floating point state.
ct=[], %List of hot catch/try labels
- setelem=false %Previous instruction was setelement/3.
+ setelem=false, %Previous instruction was setelement/3.
+ puts_left=none %put/1 instructions left.
}).
-type label() :: integer().
@@ -271,13 +267,17 @@ valfun_1(_I, #vst{current=none}=Vst) ->
Vst;
valfun_1({badmatch,Src}, Vst) ->
assert_term(Src, Vst),
+ verify_y_init(Vst),
kill_state(Vst);
valfun_1({case_end,Src}, Vst) ->
assert_term(Src, Vst),
+ verify_y_init(Vst),
kill_state(Vst);
valfun_1(if_end, Vst) ->
+ verify_y_init(Vst),
kill_state(Vst);
valfun_1({try_case_end,Src}, Vst) ->
+ verify_y_init(Vst),
assert_term(Src, Vst),
kill_state(Vst);
%% Instructions that can not cause exceptions
@@ -294,6 +294,8 @@ valfun_1({bs_context_to_binary,Ctx}, #vst{current=#st{x=Xs}}=Vst) ->
end;
valfun_1(bs_init_writable=I, Vst) ->
call(I, 1, Vst);
+valfun_1(build_stacktrace=I, Vst) ->
+ call(I, 1, Vst);
valfun_1({move,{y,_}=Src,{y,_}=Dst}, Vst) ->
%% The stack trimming optimization may generate a move from an initialized
%% but unassigned Y register to another Y register.
@@ -339,11 +341,25 @@ valfun_1({put_list,A,B,Dst}, Vst0) ->
Vst = eat_heap(2, Vst0),
set_type_reg(cons, Dst, Vst);
valfun_1({put_tuple,Sz,Dst}, Vst0) when is_integer(Sz) ->
+ Vst1 = eat_heap(1, Vst0),
+ Vst = set_type_reg(tuple_in_progress, Dst, Vst1),
+ #vst{current=St0} = Vst,
+ St = St0#st{puts_left={Sz,{Dst,{tuple,Sz}}}},
+ Vst#vst{current=St};
+valfun_1({put,Src}, Vst0) ->
+ assert_term(Src, Vst0),
Vst = eat_heap(1, Vst0),
- set_type_reg({tuple,Sz}, Dst, Vst);
-valfun_1({put,Src}, Vst) ->
- assert_term(Src, Vst),
- eat_heap(1, Vst);
+ #vst{current=St0} = Vst,
+ case St0 of
+ #st{puts_left=none} ->
+ error(not_building_a_tuple);
+ #st{puts_left={1,{Dst,Type}}} ->
+ St = St0#st{puts_left=none},
+ set_type_reg(Type, Dst, Vst#vst{current=St});
+ #st{puts_left={PutsLeft,Info}} when is_integer(PutsLeft) ->
+ St = St0#st{puts_left={PutsLeft-1,Info}},
+ Vst#vst{current=St}
+ end;
%% Instructions for optimization of selective receives.
valfun_1({recv_mark,{f,Fail}}, Vst) when is_integer(Fail) ->
Vst;
@@ -351,7 +367,9 @@ valfun_1({recv_set,{f,Fail}}, Vst) when is_integer(Fail) ->
Vst;
%% Misc.
valfun_1(remove_message, Vst) ->
- Vst;
+ %% The message term is no longer fragile. It can be used
+ %% without restrictions.
+ remove_fragility(Vst);
valfun_1({'%',_}, Vst) ->
Vst;
valfun_1({line,_}, Vst) ->
@@ -361,6 +379,9 @@ valfun_1({call_ext,Live,Func}=I, Vst) ->
case return_type(Func, Vst) of
exception ->
verify_live(Live, Vst),
+ %% The stack will be scanned, so Y registers
+ %% must be initialized.
+ verify_y_init(Vst),
kill_state(Vst);
_ ->
valfun_2(I, Vst)
@@ -430,6 +451,19 @@ valfun_1({try_case,Reg}, #vst{current=#st{ct=[Fail|Fails]}}=Vst0) ->
Type ->
error({bad_type,Type})
end;
+valfun_1({get_list,Src,D1,D2}, Vst0) ->
+ assert_type(cons, Src, Vst0),
+ Vst = set_type_reg(term, Src, D1, Vst0),
+ set_type_reg(term, Src, D2, Vst);
+valfun_1({get_hd,Src,Dst}, Vst) ->
+ assert_type(cons, Src, Vst),
+ set_type_reg(term, Src, Dst, Vst);
+valfun_1({get_tl,Src,Dst}, Vst) ->
+ assert_type(cons, Src, Vst),
+ set_type_reg(term, Src, Dst, Vst);
+valfun_1({get_tuple_element,Src,I,Dst}, Vst) ->
+ assert_type({tuple_element,I+1}, Src, Vst),
+ set_type_reg(term, Src, Dst, Vst);
valfun_1(I, Vst) ->
valfun_2(I, Vst).
@@ -519,23 +553,40 @@ valfun_4({bif,element,{f,Fail},[Pos,Tuple],Dst}, Vst0) ->
Vst1 = branch_state(Fail, Vst0),
TupleType = upgrade_tuple_type({tuple,[get_tuple_size(PosType)]}, TupleType0),
Vst = set_type(TupleType, Tuple, Vst1),
- set_type_reg(term, Dst, Vst);
+ set_type_reg(term, Tuple, Dst, Vst);
valfun_4({bif,raise,{f,0},Src,_Dst}, Vst) ->
validate_src(Src, Vst),
kill_state(Vst);
+valfun_4(raw_raise=I, Vst) ->
+ call(I, 3, Vst);
+valfun_4({bif,map_get,{f,Fail},[_Key,Map]=Src,Dst}, Vst0) ->
+ validate_src(Src, Vst0),
+ Vst1 = branch_state(Fail, Vst0),
+ Vst = set_type(map, Map, Vst1),
+ Type = propagate_fragility(term, Src, Vst),
+ set_type_reg(Type, Dst, Vst);
+valfun_4({bif,is_map_key,{f,Fail},[_Key,Map]=Src,Dst}, Vst0) ->
+ validate_src(Src, Vst0),
+ Vst1 = branch_state(Fail, Vst0),
+ Vst = set_type(map, Map, Vst1),
+ Type = propagate_fragility(bool, Src, Vst),
+ set_type_reg(Type, Dst, Vst);
valfun_4({bif,Op,{f,Fail},Src,Dst}, Vst0) ->
validate_src(Src, Vst0),
Vst = branch_state(Fail, Vst0),
- Type = bif_type(Op, Src, Vst),
+ Type0 = bif_type(Op, Src, Vst),
+ Type = propagate_fragility(Type0, Src, Vst),
set_type_reg(Type, Dst, Vst);
valfun_4({gc_bif,Op,{f,Fail},Live,Src,Dst}, #vst{current=St0}=Vst0) ->
+ verify_live(Live, Vst0),
+ verify_y_init(Vst0),
St = kill_heap_allocation(St0),
Vst1 = Vst0#vst{current=St},
- verify_live(Live, Vst1),
Vst2 = branch_state(Fail, Vst1),
Vst = prune_x_regs(Live, Vst2),
validate_src(Src, Vst),
- Type = bif_type(Op, Src, Vst),
+ Type0 = bif_type(Op, Src, Vst),
+ Type = propagate_fragility(Type0, Src, Vst),
set_type_reg(Type, Dst, Vst);
valfun_4(return, #vst{current=#st{numy=none}}=Vst) ->
assert_term({x,0}, Vst),
@@ -546,13 +597,20 @@ valfun_4({jump,{f,Lbl}}, Vst) ->
kill_state(branch_state(Lbl, Vst));
valfun_4({loop_rec,{f,Fail},Dst}, Vst0) ->
Vst = branch_state(Fail, Vst0),
- set_type_reg(term, Dst, Vst);
+ %% This term may not be part of the root set until
+ %% remove_message/0 is executed. If control transfers
+ %% to the loop_rec_end/1 instruction, no part of
+ %% this term must be stored in a Y register.
+ set_type_reg({fragile,term}, Dst, Vst);
valfun_4({wait,_}, Vst) ->
+ verify_y_init(Vst),
kill_state(Vst);
valfun_4({wait_timeout,_,Src}, Vst) ->
assert_term(Src, Vst),
- Vst;
+ verify_y_init(Vst),
+ prune_x_regs(0, Vst);
valfun_4({loop_rec_end,_}, Vst) ->
+ verify_y_init(Vst),
kill_state(Vst);
valfun_4(timeout, #vst{current=St}=Vst) ->
Vst#vst{current=St#st{x=init_regs(0, term)}};
@@ -570,13 +628,6 @@ valfun_4({select_val,Src,{f,Fail},{list,Choices}}, Vst) ->
valfun_4({select_tuple_arity,Tuple,{f,Fail},{list,Choices}}, Vst) ->
assert_type(tuple, Tuple, Vst),
kill_state(branch_arities(Choices, Tuple, branch_state(Fail, Vst)));
-valfun_4({get_list,Src,D1,D2}, Vst0) ->
- assert_type(cons, Src, Vst0),
- Vst = set_type_reg(term, D1, Vst0),
- set_type_reg(term, D2, Vst);
-valfun_4({get_tuple_element,Src,I,Dst}, Vst) ->
- assert_type({tuple_element,I+1}, Src, Vst),
- set_type_reg(term, Dst, Vst);
%% New bit syntax matching instructions.
valfun_4({test,bs_start_match2,{f,Fail},Live,[Ctx,NeedSlots],Ctx}, Vst0) ->
@@ -584,6 +635,7 @@ valfun_4({test,bs_start_match2,{f,Fail},Live,[Ctx,NeedSlots],Ctx}, Vst0) ->
%% is OK as input.
CtxType = get_move_term_type(Ctx, Vst0),
verify_live(Live, Vst0),
+ verify_y_init(Vst0),
Vst1 = prune_x_regs(Live, Vst0),
BranchVst = case CtxType of
#ms{} ->
@@ -600,9 +652,10 @@ valfun_4({test,bs_start_match2,{f,Fail},Live,[Ctx,NeedSlots],Ctx}, Vst0) ->
valfun_4({test,bs_start_match2,{f,Fail},Live,[Src,Slots],Dst}, Vst0) ->
assert_term(Src, Vst0),
verify_live(Live, Vst0),
+ verify_y_init(Vst0),
Vst1 = prune_x_regs(Live, Vst0),
Vst = branch_state(Fail, Vst1),
- set_type_reg(bsm_match_state(Slots), Dst, Vst);
+ set_type_reg(bsm_match_state(Slots), Src, Dst, Vst);
valfun_4({test,bs_match_string,{f,Fail},[Ctx,_,_]}, Vst) ->
bsm_validate_context(Ctx, Vst),
branch_state(Fail, Vst);
@@ -627,7 +680,8 @@ valfun_4({test,bs_get_integer2,{f,Fail},Live,[Ctx,_,_,_],Dst}, Vst) ->
valfun_4({test,bs_get_float2,{f,Fail},Live,[Ctx,_,_,_],Dst}, Vst) ->
validate_bs_get(Fail, Ctx, Live, {float, []}, Dst, Vst);
valfun_4({test,bs_get_binary2,{f,Fail},Live,[Ctx,_,_,_],Dst}, Vst) ->
- validate_bs_get(Fail, Ctx, Live, term, Dst, Vst);
+ Type = propagate_fragility(term, [Ctx], Vst),
+ validate_bs_get(Fail, Ctx, Live, Type, Dst, Vst);
valfun_4({test,bs_get_utf8,{f,Fail},Live,[Ctx,_],Dst}, Vst) ->
validate_bs_get(Fail, Ctx, Live, {integer, []}, Dst, Vst);
valfun_4({test,bs_get_utf16,{f,Fail},Live,[Ctx,_],Dst}, Vst) ->
@@ -685,6 +739,7 @@ valfun_4({bs_utf16_size,{f,Fail},A,Dst}, Vst) ->
set_type_reg({integer,[]}, Dst, branch_state(Fail, Vst));
valfun_4({bs_init2,{f,Fail},Sz,Heap,Live,_,Dst}, Vst0) ->
verify_live(Live, Vst0),
+ verify_y_init(Vst0),
if
is_integer(Sz) ->
ok;
@@ -697,6 +752,7 @@ valfun_4({bs_init2,{f,Fail},Sz,Heap,Live,_,Dst}, Vst0) ->
set_type_reg(binary, Dst, Vst);
valfun_4({bs_init_bits,{f,Fail},Sz,Heap,Live,_,Dst}, Vst0) ->
verify_live(Live, Vst0),
+ verify_y_init(Vst0),
if
is_integer(Sz) ->
ok;
@@ -709,6 +765,7 @@ valfun_4({bs_init_bits,{f,Fail},Sz,Heap,Live,_,Dst}, Vst0) ->
set_type_reg(binary, Dst, Vst);
valfun_4({bs_append,{f,Fail},Bits,Heap,Live,_Unit,Bin,_Flags,Dst}, Vst0) ->
verify_live(Live, Vst0),
+ verify_y_init(Vst0),
assert_term(Bits, Vst0),
assert_term(Bin, Vst0),
Vst1 = heap_alloc(Heap, Vst0),
@@ -764,7 +821,7 @@ verify_get_map(Fail, Src, List, Vst0) ->
Vst2 = branch_state(Fail, Vst1),
Keys = extract_map_keys(List),
assert_unique_map_keys(Keys),
- verify_get_map_pair(List,Vst0,Vst2).
+ verify_get_map_pair(List, Src, Vst0, Vst2).
extract_map_vals([_Key,Val|T]) ->
[Val|extract_map_vals(T)];
@@ -774,10 +831,11 @@ extract_map_keys([Key,_Val|T]) ->
[Key|extract_map_keys(T)];
extract_map_keys([]) -> [].
-verify_get_map_pair([],_,Vst) -> Vst;
-verify_get_map_pair([Src,Dst|Vs],Vst0,Vsti) ->
+verify_get_map_pair([Src,Dst|Vs], Map, Vst0, Vsti0) ->
assert_term(Src, Vst0),
- verify_get_map_pair(Vs,Vst0,set_type_reg(term,Dst,Vsti)).
+ Vsti = set_type_reg(term, Map, Dst, Vsti0),
+ verify_get_map_pair(Vs, Map, Vst0, Vsti);
+verify_get_map_pair([], _Map, _Vst0, Vst) -> Vst.
verify_put_map(Fail, Src, Dst, Live, List, Vst0) ->
assert_type(map, Src, Vst0),
@@ -797,6 +855,7 @@ verify_put_map(Fail, Src, Dst, Live, List, Vst0) ->
validate_bs_get(Fail, Ctx, Live, Type, Dst, Vst0) ->
bsm_validate_context(Ctx, Vst0),
verify_live(Live, Vst0),
+ verify_y_init(Vst0),
Vst1 = prune_x_regs(Live, Vst0),
Vst = branch_state(Fail, Vst1),
set_type_reg(Type, Dst, Vst).
@@ -806,6 +865,7 @@ validate_bs_get(Fail, Ctx, Live, Type, Dst, Vst0) ->
%%
validate_bs_skip_utf(Fail, Ctx, Live, Vst0) ->
bsm_validate_context(Ctx, Vst0),
+ verify_y_init(Vst0),
verify_live(Live, Vst0),
Vst = prune_x_regs(Live, Vst0),
branch_state(Fail, Vst).
@@ -928,9 +988,9 @@ verify_call_match_context(Lbl, Ctx, #vst{ft=Ft}) ->
error({unsuitable_bs_start_match2,I})
end.
-allocate(Zero, Stk, Heap, Live, #vst{current=#st{numy=none}=St}=Vst0) ->
+allocate(Zero, Stk, Heap, Live, #vst{current=#st{numy=none}}=Vst0) ->
verify_live(Live, Vst0),
- Vst = prune_x_regs(Live, Vst0),
+ Vst = #vst{current=St} = prune_x_regs(Live, Vst0),
Ys = init_regs(Stk, case Zero of
true -> initialized;
false -> uninitialized
@@ -944,6 +1004,7 @@ deallocate(#vst{current=St}=Vst) ->
test_heap(Heap, Live, Vst0) ->
verify_live(Live, Vst0),
+ verify_y_init(Vst0),
Vst = prune_x_regs(Live, Vst0),
heap_alloc(Heap, Vst).
@@ -1066,10 +1127,11 @@ bsm_validate_context(Reg, Vst) ->
bsm_get_context({x,X}=Reg, #vst{current=#st{x=Xs}}=_Vst) when is_integer(X) ->
case gb_trees:lookup(X, Xs) of
{value,#ms{}=Ctx} -> Ctx;
+ {value,{fragile,#ms{}=Ctx}} -> Ctx;
_ -> error({no_bsm_context,Reg})
end;
bsm_get_context(Reg, _) -> error({bad_source,Reg}).
-
+
bsm_save(Reg, {atom,start}, Vst) ->
%% Save point refering to where the match started.
%% It is always valid. But don't forget to validate the context register.
@@ -1106,13 +1168,34 @@ set_type(Type, {x,_}=Reg, Vst) -> set_type_reg(Type, Reg, Vst);
set_type(Type, {y,_}=Reg, Vst) -> set_type_y(Type, Reg, Vst);
set_type(_, _, #vst{}=Vst) -> Vst.
-set_type_reg(Type, {x,X}=Reg, #vst{current=#st{x=Xs}=St}=Vst)
- when is_integer(X), 0 =< X ->
- check_limit(Reg),
- Vst#vst{current=St#st{x=gb_trees:enter(X, Type, Xs)}};
+set_type_reg(Type, Src, Dst, Vst) ->
+ case get_term_type_1(Src, Vst) of
+ {fragile,_} ->
+ set_type_reg(make_fragile(Type), Dst, Vst);
+ _ ->
+ set_type_reg(Type, Dst, Vst)
+ end.
+
+set_type_reg(Type, {x,_}=Reg, Vst) ->
+ set_type_x(Type, Reg, Vst);
set_type_reg(Type, Reg, Vst) ->
set_type_y(Type, Reg, Vst).
+set_type_x(Type, {x,X}=Reg, #vst{current=#st{x=Xs0}=St}=Vst)
+ when is_integer(X), 0 =< X ->
+ check_limit(Reg),
+ Xs = case gb_trees:lookup(X, Xs0) of
+ none ->
+ gb_trees:insert(X, Type, Xs0);
+ {value,{fragile,_}} ->
+ gb_trees:update(X, make_fragile(Type), Xs0);
+ {value,_} ->
+ gb_trees:update(X, Type, Xs0)
+ end,
+ Vst#vst{current=St#st{x=Xs}};
+set_type_x(Type, Reg, #vst{}) ->
+ error({invalid_store,Reg,Type}).
+
set_type_y(Type, {y,Y}=Reg, #vst{current=#st{y=Ys0}=St}=Vst)
when is_integer(Y), 0 =< Y ->
check_limit(Reg),
@@ -1126,13 +1209,40 @@ set_type_y(Type, {y,Y}=Reg, #vst{current=#st{y=Ys0}=St}=Vst)
{value,_} ->
gb_trees:update(Y, Type, Ys0)
end,
+ check_try_catch_tags(Type, Y, Ys0),
Vst#vst{current=St#st{y=Ys}};
set_type_y(Type, Reg, #vst{}) -> error({invalid_store,Reg,Type}).
+make_fragile({fragile,_}=Type) -> Type;
+make_fragile(Type) -> {fragile,Type}.
+
set_catch_end({y,Y}, #vst{current=#st{y=Ys0}=St}=Vst) ->
Ys = gb_trees:update(Y, initialized, Ys0),
Vst#vst{current=St#st{y=Ys}}.
+check_try_catch_tags(Type, LastY, Ys) ->
+ case is_try_catch_tag(Type) of
+ false ->
+ ok;
+ true ->
+ %% Every catch or try/catch must use a lower Y register
+ %% number than any enclosing catch or try/catch. That will
+ %% ensure that when the stack is scanned when an
+ %% exception occurs, the innermost try/catch tag is found
+ %% first.
+ Bad = [{{y,Y},Tag} || {Y,Tag} <- gb_trees:to_list(Ys),
+ Y < LastY, is_try_catch_tag(Tag)],
+ case Bad of
+ [] ->
+ ok;
+ [_|_] ->
+ error({bad_try_catch_nesting,{y,LastY},Bad})
+ end
+ end.
+
+is_try_catch_tag({catchtag,_}) -> true;
+is_try_catch_tag({trytag,_}) -> true;
+is_try_catch_tag(_) -> false.
is_reg_defined({x,_}=Reg, Vst) -> is_type_defined_x(Reg, Vst);
is_reg_defined({y,_}=Reg, Vst) -> is_type_defined_y(Reg, Vst);
@@ -1206,9 +1316,26 @@ assert_term(Src, Vst) ->
%%
%% map Map.
%%
+%%
+%%
+%% FRAGILITY
+%% ---------
+%%
+%% The loop_rec/2 instruction may return a reference to a term that is
+%% not part of the root set. That term or any part of it must not be
+%% included in a garbage collection. Therefore, the term (or any part
+%% of it) must not be stored in an Y register.
+%%
+%% Such terms are wrapped in a {fragile,Type} tuple, where Type is one
+%% of the types described above.
assert_type(WantedType, Term, Vst) ->
- assert_type(WantedType, get_term_type(Term, Vst)).
+ case get_term_type(Term, Vst) of
+ {fragile,Type} ->
+ assert_type(WantedType, Type);
+ Type ->
+ assert_type(WantedType, Type)
+ end.
assert_type(Correct, Correct) -> ok;
assert_type(float, {float,_}) -> ok;
@@ -1234,14 +1361,19 @@ assert_type(Needed, Actual) ->
%% is inconsistent, and we know that some instructions will never
%% be executed at run-time.
-upgrade_tuple_type({tuple,[Sz]}, {tuple,[OldSz]}=T) when Sz < OldSz ->
+upgrade_tuple_type(NewType, {fragile,OldType}) ->
+ make_fragile(upgrade_tuple_type_1(NewType, OldType));
+upgrade_tuple_type(NewType, OldType) ->
+ upgrade_tuple_type_1(NewType, OldType).
+
+upgrade_tuple_type_1({tuple,[Sz]}, {tuple,[OldSz]}=T) when Sz < OldSz ->
%% The old type has a higher value for the least tuple size.
T;
-upgrade_tuple_type({tuple,[Sz]}, {tuple,OldSz}=T)
+upgrade_tuple_type_1({tuple,[Sz]}, {tuple,OldSz}=T)
when is_integer(Sz), is_integer(OldSz), Sz =< OldSz ->
%% The old size is exact, and the new size is smaller than the old size.
T;
-upgrade_tuple_type({tuple,_}=T, _) ->
+upgrade_tuple_type_1({tuple,_}=T, _) ->
%% The new type information is exact or has a higher value for
%% the least tuple size.
%% Note that inconsistencies are also handled in this
@@ -1266,6 +1398,7 @@ get_move_term_type(Src, Vst) ->
initialized -> error({unassigned,Src});
{catchtag,_} -> error({catchtag,Src});
{trytag,_} -> error({trytag,Src});
+ tuple_in_progress -> error({tuple_in_progress,Src});
Type -> Type
end.
@@ -1274,10 +1407,7 @@ get_move_term_type(Src, Vst) ->
%% a standard Erlang type (no catch/try tags or match contexts).
get_term_type(Src, Vst) ->
- case get_term_type_1(Src, Vst) of
- initialized -> error({unassigned,Src});
- {catchtag,_} -> error({catchtag,Src});
- {trytag,_} -> error({trytag,Src});
+ case get_move_term_type(Src, Vst) of
#ms{} -> error({match_context,Src});
Type -> Type
end.
@@ -1324,7 +1454,12 @@ branch_arities([Sz,{f,L}|T], Tuple, #vst{current=St}=Vst0)
Vst = branch_state(L, Vst1),
branch_arities(T, Tuple, Vst#vst{current=St}).
-branch_state(0, #vst{}=Vst) -> Vst;
+branch_state(0, #vst{}=Vst) ->
+ %% If the instruction fails, the stack may be scanned
+ %% looking for a catch tag. Therefore the Y registers
+ %% must be initialized at this point.
+ verify_y_init(Vst),
+ Vst;
branch_state(L, #vst{current=St,branched=B}=Vst) ->
Vst#vst{
branched=case gb_trees:is_defined(L, B) of
@@ -1405,6 +1540,14 @@ merge_y_regs_1(_, _, Regs) -> Regs.
%% merge_types(Type1, Type2) -> Type
%% Return the most specific type possible.
%% Note: Type1 must NOT be the same as Type2.
+merge_types({fragile,Same}=Type, Same) ->
+ Type;
+merge_types({fragile,T1}, T2) ->
+ make_fragile(merge_types(T1, T2));
+merge_types(Same, {fragile,Same}=Type) ->
+ Type;
+merge_types(T1, {fragile,T2}) ->
+ make_fragile(merge_types(T1, T2));
merge_types(uninitialized=I, _) -> I;
merge_types(_, uninitialized=I) -> I;
merge_types(initialized=I, _) -> I;
@@ -1430,13 +1573,13 @@ merge_types(bool, {atom,A}) ->
merge_bool(A);
merge_types({atom,A}, bool) ->
merge_bool(A);
-merge_types(#ms{id=Id,valid=B0,slots=Slots}=M,
- #ms{id=Id,valid=B1,slots=Slots}) ->
- M#ms{valid=B0 bor B1,slots=Slots};
-merge_types(#ms{}=M, _) ->
- M;
-merge_types(_, #ms{}=M) ->
- M;
+merge_types(#ms{id=Id1,valid=B1,slots=Slots1},
+ #ms{id=Id2,valid=B2,slots=Slots2}) ->
+ Id = if
+ Id1 =:= Id2 -> Id1;
+ true -> make_ref()
+ end,
+ #ms{id=Id,valid=B1 band B2,slots=min(Slots1, Slots2)};
merge_types(T1, T2) when T1 =/= T2 ->
%% Too different. All we know is that the type is a 'term'.
term.
@@ -1455,6 +1598,10 @@ verify_y_init(#vst{current=#st{y=Ys}}) ->
verify_y_init_1([]) -> ok;
verify_y_init_1([{Y,uninitialized}|_]) ->
error({uninitialized_reg,{y,Y}});
+verify_y_init_1([{Y,{fragile,_}}|_]) ->
+ %% Unsafe. This term may be outside any heap belonging
+ %% to the process and would be corrupted by a GC.
+ error({fragile_message_reference,{y,Y}});
verify_y_init_1([{_,_}|Ys]) ->
verify_y_init_1(Ys).
@@ -1500,6 +1647,27 @@ eat_heap_float(#vst{current=#st{hf=HeapFloats0}=St}=Vst) ->
Vst#vst{current=St#st{hf=HeapFloats}}
end.
+remove_fragility(#vst{current=#st{x=Xs0,y=Ys0}=St0}=Vst) ->
+ F = fun(_, {fragile,Type}) -> Type;
+ (_, Type) -> Type
+ end,
+ Xs = gb_trees:map(F, Xs0),
+ Ys = gb_trees:map(F, Ys0),
+ St = St0#st{x=Xs,y=Ys},
+ Vst#vst{current=St}.
+
+propagate_fragility(Type, Ss, Vst) ->
+ F = fun(S) ->
+ case get_term_type_1(S, Vst) of
+ {fragile,_} -> true;
+ _ -> false
+ end
+ end,
+ case any(F, Ss) of
+ true -> make_fragile(Type);
+ false -> Type
+ end.
+
bif_type('-', Src, Vst) ->
arith_type(Src, Vst);
bif_type('+', Src, Vst) ->
diff --git a/lib/compiler/src/beam_z.erl b/lib/compiler/src/beam_z.erl
index 787e33c142..1c9d762eb1 100644
--- a/lib/compiler/src/beam_z.erl
+++ b/lib/compiler/src/beam_z.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-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.
@@ -24,22 +24,23 @@
-export([module/2]).
--import(lists, [dropwhile/2]).
+-import(lists, [dropwhile/2,map/2]).
-spec module(beam_utils:module_code(), [compile:option()]) ->
{'ok',beam_asm:module_code()}.
-module({Mod,Exp,Attr,Fs0,Lc}, _Opt) ->
- Fs = [function(F) || F <- Fs0],
+module({Mod,Exp,Attr,Fs0,Lc}, Opts) ->
+ NoGetHdTl = proplists:get_bool(no_get_hd_tl, Opts),
+ Fs = [function(F, NoGetHdTl) || F <- Fs0],
{ok,{Mod,Exp,Attr,Fs,Lc}}.
-function({function,Name,Arity,CLabel,Is0}) ->
+function({function,Name,Arity,CLabel,Is0}, NoGetHdTl) ->
try
- Is = undo_renames(Is0),
+ Is1 = undo_renames(Is0),
+ Is = maybe_eliminate_get_hd_tl(Is1, NoGetHdTl),
{function,Name,Arity,CLabel,Is}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
@@ -66,6 +67,10 @@ undo_renames([{bif,raise,_,_,_}=I|Is0]) ->
(_) -> true
end, Is0),
[I|undo_renames(Is)];
+undo_renames([{get_hd,Src,Dst1},{get_tl,Src,Dst2}|Is]) ->
+ [{get_list,Src,Dst1,Dst2}|undo_renames(Is)];
+undo_renames([{get_tl,Src,Dst2},{get_hd,Src,Dst1}|Is]) ->
+ [{get_list,Src,Dst1,Dst2}|undo_renames(Is)];
undo_renames([I|Is]) ->
[undo_rename(I)|undo_renames(Is)];
undo_renames([]) -> [].
@@ -108,3 +113,17 @@ undo_rename({get_map_elements,Fail,Src,{list,List}}) ->
undo_rename({select,I,Reg,Fail,List}) ->
{I,Reg,Fail,{list,List}};
undo_rename(I) -> I.
+
+%%%
+%%% Eliminate get_hd/get_tl instructions if requested by
+%%% the no_get_hd_tl option.
+%%%
+
+maybe_eliminate_get_hd_tl(Is, true) ->
+ map(fun({get_hd,Cons,Hd}) ->
+ {get_list,Cons,Hd,{x,1022}};
+ ({get_tl,Cons,Tl}) ->
+ {get_list,Cons,{x,1022},Tl};
+ (I) -> I
+ end, Is);
+maybe_eliminate_get_hd_tl(Is, false) -> Is.
diff --git a/lib/compiler/src/cerl.erl b/lib/compiler/src/cerl.erl
index 6b936a7687..fce23bfd68 100644
--- a/lib/compiler/src/cerl.erl
+++ b/lib/compiler/src/cerl.erl
@@ -433,6 +433,8 @@ is_literal_term(T) when is_tuple(T) ->
is_literal_term(B) when is_bitstring(B) -> true;
is_literal_term(M) when is_map(M) ->
is_literal_term_list(maps:to_list(M));
+is_literal_term(F) when is_function(F) ->
+ erlang:fun_info(F, type) =:= {type,external};
is_literal_term(_) ->
false.
diff --git a/lib/compiler/src/cerl_clauses.erl b/lib/compiler/src/cerl_clauses.erl
index 7d6518c3c6..fa5104c01b 100644
--- a/lib/compiler/src/cerl_clauses.erl
+++ b/lib/compiler/src/cerl_clauses.erl
@@ -353,6 +353,8 @@ match(P, E, Bs) ->
map ->
%% The most we can do is to say "definitely no match" if a
%% map pattern is matched against non-map data.
+ %% (Note: See the document internal_doc/cerl-notes.md for
+ %% information why we don't try to do more here.)
case E of
any ->
{false, Bs};
diff --git a/lib/compiler/src/cerl_inline.erl b/lib/compiler/src/cerl_inline.erl
index f5afa75b16..caff47dbcb 100644
--- a/lib/compiler/src/cerl_inline.erl
+++ b/lib/compiler/src/cerl_inline.erl
@@ -1822,6 +1822,14 @@ new_var(Env) ->
Name = env__new_vname(Env),
c_var(Name).
+%% The way a template variable is used makes it necessary
+%% to make sure that it is unique in the entire function.
+%% Therefore, template variables are atoms with the prefix "@i".
+
+new_template_var(Env) ->
+ Name = env__new_tname(Env),
+ c_var(Name).
+
residualize_var(R, S) ->
S1 = count_size(weight(var), S),
{ref_to_var(R), st__set_var_referenced(R#ref.loc, S1)}.
@@ -2183,7 +2191,7 @@ make_template(E, Vs0, Env0) ->
T = make_data_skel(data_type(E), Ts),
E1 = update_data(E, data_type(E),
[hd(get_ann(T)) || T <- Ts]),
- V = new_var(Env1),
+ V = new_template_var(Env1),
Env2 = env__bind(var_name(V), E1, Env1),
{set_ann(T, [V]), [V | Vs1], Env2};
false ->
@@ -2198,7 +2206,7 @@ make_template(E, Vs0, Env0) ->
Env2 = env__bind(V, E1, Env1),
{T, Vs1, Env2};
_ ->
- V = new_var(Env0),
+ V = new_template_var(Env0),
Env1 = env__bind(var_name(V), E, Env0),
{set_ann(V, [V]), [V | Vs0], Env1}
end
@@ -2564,6 +2572,11 @@ env__is_defined(Key, Env) ->
env__new_vname(Env) ->
rec_env:new_key(Env).
+env__new_tname(Env) ->
+ rec_env:new_key(fun(I) ->
+ list_to_atom("@i"++integer_to_list(I))
+ end, Env).
+
env__new_fname(A, N, Env) ->
rec_env:new_key(fun (X) ->
S = integer_to_list(X),
diff --git a/lib/compiler/src/cerl_trees.erl b/lib/compiler/src/cerl_trees.erl
index f30a0b33ac..533c984221 100644
--- a/lib/compiler/src/cerl_trees.erl
+++ b/lib/compiler/src/cerl_trees.erl
@@ -22,7 +22,8 @@
-module(cerl_trees).
-export([depth/1, fold/3, free_variables/1, get_label/1, label/1, label/2,
- map/2, mapfold/3, mapfold/4, size/1, variables/1]).
+ map/2, mapfold/3, mapfold/4, next_free_variable_name/1,
+ size/1, variables/1]).
-import(cerl, [alias_pat/1, alias_var/1, ann_c_alias/3, ann_c_apply/3,
ann_c_binary/2, ann_c_bitstr/6, ann_c_call/4,
@@ -350,10 +351,9 @@ mapfold(F, S0, T) ->
mapfold(fun(T0, A) -> {T0, A} end, F, S0, T).
-%% @spec mapfold(Pre, Post, Initial::term(), Tree::cerl()) ->
-%% {cerl(), term()}
-%%
-%% Pre = Post = (cerl(), term()) -> {cerl(), term()}
+%% @spec mapfold(Pre, Post, Initial::term(), Tree::cerl()) -> {cerl(), term()}
+%% Pre = (cerl(), term()) -> {cerl(), term()}
+%% Post = (cerl(), term()) -> {cerl(), term()}
%%
%% @doc Does a combined map/fold operation on the nodes of the
%% tree. It begins by calling <code>Pre</code> on the tree, using the
@@ -507,6 +507,7 @@ mapfold_pairs(_, _, S, []) ->
%% well-formed Core Erlang syntax tree.
%%
%% @see free_variables/1
+%% @see next_free_variable_name/1
-spec variables(cerl:cerl()) -> [cerl:var_name()].
@@ -519,6 +520,7 @@ variables(T) ->
%% @doc Like <code>variables/1</code>, but only includes variables
%% that are free in the tree.
%%
+%% @see next_free_variable_name/1
%% @see variables/1
-spec free_variables(cerl:cerl()) -> [cerl:var_name()].
@@ -678,6 +680,110 @@ var_list_names([V | Vs], A) ->
var_list_names([], A) ->
A.
+%% ---------------------------------------------------------------------
+
+%% @spec next_free_variable_name(Tree::cerl()) -> var_name()
+%%
+%% var_name() = integer()
+%%
+%% @doc Returns a integer variable name higher than any other integer
+%% variable name in the syntax tree. An exception is thrown if
+%% <code>Tree</code> does not represent a well-formed Core Erlang
+%% syntax tree.
+%%
+%% @see variables/1
+%% @see free_variables/1
+
+-spec next_free_variable_name(cerl:cerl()) -> integer().
+
+next_free_variable_name(T) ->
+ 1 + next_free(T, -1).
+
+next_free(T, Max) ->
+ case type(T) of
+ literal ->
+ Max;
+ var ->
+ case var_name(T) of
+ Int when is_integer(Int) ->
+ max(Int, Max);
+ _ ->
+ Max
+ end;
+ values ->
+ next_free_in_list(values_es(T), Max);
+ cons ->
+ next_free(cons_hd(T), next_free(cons_tl(T), Max));
+ tuple ->
+ next_free_in_list(tuple_es(T), Max);
+ map ->
+ next_free_in_list([map_arg(T)|map_es(T)], Max);
+ map_pair ->
+ next_free_in_list([map_pair_op(T),map_pair_key(T),
+ map_pair_val(T)], Max);
+ 'let' ->
+ Max1 = next_free(let_body(T), Max),
+ Max2 = next_free_in_list(let_vars(T), Max1),
+ next_free(let_arg(T), Max2);
+ seq ->
+ next_free(seq_arg(T),
+ next_free(seq_body(T), Max));
+ apply ->
+ next_free(apply_op(T),
+ next_free_in_list(apply_args(T), Max));
+ call ->
+ next_free(call_module(T),
+ next_free(call_name(T),
+ next_free_in_list(
+ call_args(T), Max)));
+ primop ->
+ next_free_in_list(primop_args(T), Max);
+ 'case' ->
+ next_free(case_arg(T),
+ next_free_in_list(case_clauses(T), Max));
+ clause ->
+ Max1 = next_free(clause_guard(T),
+ next_free(clause_body(T), Max)),
+ next_free_in_list(clause_pats(T), Max1);
+ alias ->
+ next_free(alias_var(T),
+ next_free(alias_pat(T), Max));
+ 'fun' ->
+ next_free(fun_body(T),
+ next_free_in_list(fun_vars(T), Max));
+ 'receive' ->
+ Max1 = next_free_in_list(receive_clauses(T),
+ next_free(receive_timeout(T), Max)),
+ next_free(receive_action(T), Max1);
+ 'try' ->
+ Max1 = next_free(try_body(T), Max),
+ Max2 = next_free_in_list(try_vars(T), Max1),
+ Max3 = next_free(try_handler(T), Max2),
+ Max4 = next_free_in_list(try_evars(T), Max3),
+ next_free(try_arg(T), Max4);
+ 'catch' ->
+ next_free(catch_body(T), Max);
+ binary ->
+ next_free_in_list(binary_segments(T), Max);
+ bitstr ->
+ next_free(bitstr_val(T), next_free(bitstr_size(T), Max));
+ letrec ->
+ Max1 = next_free_in_defs(letrec_defs(T), Max),
+ Max2 = next_free(letrec_body(T), Max1),
+ next_free_in_list(letrec_vars(T), Max2);
+ module ->
+ next_free_in_defs(module_defs(T), Max)
+ end.
+
+next_free_in_list([H | T], Max) ->
+ next_free_in_list(T, next_free(H, Max));
+next_free_in_list([], Max) ->
+ Max.
+
+next_free_in_defs([{_, Post} | Ds], Max) ->
+ next_free_in_defs(Ds, next_free(Post, Max));
+next_free_in_defs([], Max) ->
+ Max.
%% ---------------------------------------------------------------------
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index aa2d224bb4..6510571441 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -203,7 +203,12 @@ expand_opts(Opts0) ->
{_,_,undefined} -> [debug_info|Opts0];
{_,_,_} -> Opts0
end,
- foldr(fun expand_opt/2, [], Opts).
+ %% iff,unless processing is to complex...
+ Opts1 = case proplists:is_defined(makedep_side_effect,Opts) of
+ true -> proplists:delete(makedep,Opts);
+ false -> Opts
+ end,
+ foldr(fun expand_opt/2, [], Opts1).
expand_opt(basic_validation, Os) ->
[no_code_generation,to_pp,binary|Os];
@@ -214,13 +219,15 @@ expand_opt(report, Os) ->
expand_opt(return, Os) ->
[return_errors,return_warnings|Os];
expand_opt(r16, Os) ->
- [no_record_opt,no_utf8_atoms|Os];
+ [no_get_hd_tl,no_record_opt,no_utf8_atoms|Os];
expand_opt(r17, Os) ->
- [no_record_opt,no_utf8_atoms|Os];
+ [no_get_hd_tl,no_record_opt,no_utf8_atoms|Os];
expand_opt(r18, Os) ->
- [no_record_opt,no_utf8_atoms|Os];
+ [no_get_hd_tl,no_record_opt,no_utf8_atoms|Os];
expand_opt(r19, Os) ->
- [no_record_opt,no_utf8_atoms|Os];
+ [no_get_hd_tl,no_record_opt,no_utf8_atoms|Os];
+expand_opt(r20, Os) ->
+ [no_get_hd_tl,no_record_opt,no_utf8_atoms|Os];
expand_opt({debug_info_key,_}=O, Os) ->
[encrypt_debug_info,O|Os];
expand_opt(no_float_opt, Os) ->
@@ -288,7 +295,7 @@ format_error_reason({Reason, Stack}) when is_list(Stack) ->
end,
FormatFun = fun (Term, _) -> io_lib:format("~tp", [Term]) end,
[io_lib:format("~tp", [Reason]),"\n\n",
- lib:format_stacktrace(1, Stack, StackFun, FormatFun)];
+ erl_error:format_stacktrace(1, Stack, StackFun, FormatFun)];
format_error_reason(Reason) ->
io_lib:format("~tp", [Reason]).
@@ -674,6 +681,7 @@ select_list_passes_1([], _, Acc) ->
standard_passes() ->
[?pass(transform_module),
+ {iff,makedep_side_effect,?pass(makedep_and_output)},
{iff,makedep,[
?pass(makedep),
{unless,binary,?pass(makedep_output)}
@@ -706,14 +714,16 @@ core_passes() ->
[{unless,no_copt,
[{core_old_inliner,fun test_old_inliner/1,fun core_old_inliner/2},
{iff,doldinline,{listing,"oldinline"}},
- {pass,sys_core_fold},
+ {unless,no_fold,{pass,sys_core_fold}},
{iff,dcorefold,{listing,"corefold"}},
{core_inline_module,fun test_core_inliner/1,fun core_inline_module/2},
{iff,dinline,{listing,"inline"}},
{core_fold_after_inlining,fun test_any_inliner/1,
fun core_fold_module_after_inlining/2},
+ {iff,dcopt,{listing,"copt"}},
+ {unless,no_alias,{pass,sys_core_alias}},
+ {iff,dalias,{listing,"core_alias"}},
?pass(core_transforms)]},
- {iff,dcopt,{listing,"copt"}},
{iff,'to_core',{done,"core"}}]}
| kernel_passes()].
@@ -731,8 +741,6 @@ kernel_passes() ->
?pass(v3_kernel),
{iff,dkern,{listing,"kernel"}},
{iff,'to_kernel',{done,"kernel"}},
- {pass,v3_life},
- {iff,dlife,{listing,"life"}},
{pass,v3_codegen},
{iff,dcg,{listing,"codegen"}}
| asm_passes()].
@@ -769,6 +777,8 @@ asm_passes() ->
{iff,drecv,{listing,"recv"}},
{unless,no_record_opt,{pass,beam_record}},
{iff,drecord,{listing,"record"}},
+ {unless,no_blk2,?pass(block2)},
+ {iff,dblk2,{listing,"block2"}},
{unless,no_stack_trimming,{pass,beam_trim}},
{iff,dtrim,{listing,"trim"}},
{pass,beam_flatten}]},
@@ -787,8 +797,10 @@ asm_passes() ->
| binary_passes()].
binary_passes() ->
- [{native_compile,fun test_native/1,fun native_compile/2},
- {unless,binary,?pass(save_binary,not_werror)}].
+ [{iff,'to_dis',?pass(to_dis)},
+ {native_compile,fun test_native/1,fun native_compile/2},
+ {unless,binary,?pass(save_binary,not_werror)}
+ ].
%%%
%%% Compiler passes.
@@ -919,11 +931,17 @@ parse_module(_Code, St0) ->
end.
do_parse_module(DefEncoding, #compile{ifile=File,options=Opts,dir=Dir}=St) ->
+ SourceName0 = proplists:get_value(source, Opts, File),
+ SourceName = case member(deterministic, Opts) of
+ true -> filename:basename(SourceName0);
+ false -> SourceName0
+ end,
R = epp:parse_file(File,
- [{includes,[".",Dir|inc_paths(Opts)]},
- {macros,pre_defs(Opts)},
- {default_encoding,DefEncoding},
- extra]),
+ [{includes,[".",Dir|inc_paths(Opts)]},
+ {source_name, SourceName},
+ {macros,pre_defs(Opts)},
+ {default_encoding,DefEncoding},
+ extra]),
case R of
{ok,Forms,Extra} ->
Encoding = proplists:get_value(encoding, Extra),
@@ -1126,6 +1144,16 @@ core_lint_module(Code, St) ->
errors=St#compile.errors ++ Es}}
end.
+%% makedep + output and continue
+makedep_and_output(Code0, St) ->
+ {ok,DepCode,St1} = makedep(Code0,St),
+ case makedep_output(DepCode, St1) of
+ {ok,_IgnoreCode,St2} ->
+ {ok,Code0,St2};
+ {error,St2} ->
+ {error,St2}
+ end.
+
makedep(Code0, #compile{ifile=Ifile,ofile=Ofile,options=Opts}=St) ->
%% Get the target of the Makefile rule.
@@ -1332,6 +1360,10 @@ v3_kernel(Code0, #compile{options=Opts,warnings=Ws0}=St) ->
{ok,Code,St}
end.
+block2(Code0, #compile{options=Opts}=St) ->
+ {ok,Code} = beam_block:module(Code0, [no_blockify|Opts]),
+ {ok,Code,St}.
+
test_old_inliner(#compile{options=Opts}) ->
%% The point of this test is to avoid loading the old inliner
%% if we know that it will not be used.
@@ -1406,16 +1438,30 @@ encrypt_debug_info(DebugInfo, Key, Opts) ->
end.
cleanup_compile_options(Opts) ->
- lists:filter(fun keep_compile_option/1, Opts).
-
+ IsDeterministic = lists:member(deterministic, Opts),
+ lists:filter(fun(Opt) ->
+ keep_compile_option(Opt, IsDeterministic)
+ end, Opts).
+
+%% Include paths and current directory don't affect compilation, but they might
+%% be helpful so we include them unless we're doing a deterministic build.
+keep_compile_option({i, _}, Deterministic) ->
+ not Deterministic;
+keep_compile_option({cwd, _}, Deterministic) ->
+ not Deterministic;
%% We are storing abstract, not asm or core.
-keep_compile_option(from_asm) -> false;
-keep_compile_option(from_core) -> false;
+keep_compile_option(from_asm, _Deterministic) ->
+ false;
+keep_compile_option(from_core, _Deterministic) ->
+ false;
%% Parse transform and macros have already been applied.
-keep_compile_option({parse_transform, _}) -> false;
-keep_compile_option({d, _, _}) -> false;
+keep_compile_option({parse_transform, _}, _Deterministic) ->
+ false;
+keep_compile_option({d, _, _}, _Deterministic) ->
+ false;
%% Do not affect compilation result on future calls.
-keep_compile_option(Option) -> effects_code_generation(Option).
+keep_compile_option(Option, _Deterministic) ->
+ effects_code_generation(Option).
start_crypto() ->
try crypto:start() of
@@ -1446,15 +1492,33 @@ save_core_code(Code, St) ->
beam_asm(Code0, #compile{ifile=File,extra_chunks=ExtraChunks,options=CompilerOpts}=St) ->
case debug_info(St) of
{ok,DebugInfo,Opts0} ->
- Source = paranoid_absname(File),
Opts1 = [O || O <- Opts0, effects_code_generation(O)],
Chunks = [{<<"Dbgi">>, DebugInfo} | ExtraChunks],
- {ok,Code} = beam_asm:module(Code0, Chunks, Source, Opts1, CompilerOpts),
+ CompileInfo = compile_info(File, CompilerOpts, Opts1),
+ {ok,Code} = beam_asm:module(Code0, Chunks, CompileInfo, CompilerOpts),
{ok,Code,St#compile{abstract_code=[]}};
{error,Es} ->
{error,St#compile{errors=St#compile.errors ++ [{File,Es}]}}
end.
+compile_info(File, CompilerOpts, Opts) ->
+ IsSlim = member(slim, CompilerOpts),
+ IsDeterministic = member(deterministic, CompilerOpts),
+ Info0 = proplists:get_value(compile_info, Opts, []),
+ Info1 =
+ case paranoid_absname(File) of
+ [_|_] = Source when not IsSlim, not IsDeterministic ->
+ [{source,Source} | Info0];
+ _ ->
+ Info0
+ end,
+ Info2 =
+ case IsDeterministic of
+ false -> [{options,proplists:delete(compile_info, Opts)} | Info1];
+ true -> Info1
+ end,
+ Info2.
+
paranoid_absname(""=File) ->
File;
paranoid_absname(File) ->
@@ -1510,15 +1574,14 @@ native_compile_1(Code, St) ->
{error,St#compile{errors=St#compile.errors ++ Es}}
end
catch
- Class:R ->
- Stk = erlang:get_stacktrace(),
+ Class:R:Stack ->
case IgnoreErrors of
true ->
Ws = [{St#compile.ifile,
- [{none,?MODULE,{native_crash,R,Stk}}]}],
+ [{none,?MODULE,{native_crash,R,Stack}}]}],
{ok,St#compile{warnings=St#compile.warnings ++ Ws}};
false ->
- erlang:raise(Class, R, Stk)
+ erlang:raise(Class, R, Stack)
end
end.
@@ -1746,6 +1809,21 @@ listing(LFun, Ext, Code, St) ->
{error,St#compile{errors=St#compile.errors ++ Es}}
end.
+to_dis(Code, #compile{module=Module,ofile=Outfile}=St) ->
+ Loaded = code:is_loaded(Module),
+ Sticky = code:is_sticky(Module),
+ _ = [code:unstick_mod(Module) || Sticky],
+
+ {module,Module} = code:load_binary(Module, "", Code),
+ DestDir = filename:dirname(Outfile),
+ DisFile = filename:join(DestDir, atom_to_list(Module) ++ ".dis"),
+ ok = erts_debug:dis_to_file(Module, DisFile),
+
+ %% Restore loaded module
+ _ = [{module, Module} = code:load_file(Module) || Loaded =/= false],
+ [code:stick_mod(Module) || Sticky],
+ {ok,Code,St}.
+
output_encoding(F, #compile{encoding = none}) ->
ok = io:setopts(F, [{encoding, epp:default_encoding()}]);
output_encoding(F, #compile{encoding = Encoding}) ->
@@ -1921,12 +1999,12 @@ pre_load() ->
erl_lint,
erl_parse,
erl_scan,
+ sys_core_alias,
sys_core_bsm,
sys_core_dsetel,
sys_core_fold,
v3_codegen,
v3_core,
- v3_kernel,
- v3_life],
+ v3_kernel],
_ = code:ensure_modules_loaded(L),
ok.
diff --git a/lib/compiler/src/compiler.app.src b/lib/compiler/src/compiler.app.src
index 3139d68902..cf32fd251c 100644
--- a/lib/compiler/src/compiler.app.src
+++ b/lib/compiler/src/compiler.app.src
@@ -58,6 +58,7 @@
core_lib,
erl_bifs,
rec_env,
+ sys_core_alias,
sys_core_bsm,
sys_core_dsetel,
sys_core_fold,
@@ -67,8 +68,7 @@
v3_codegen,
v3_core,
v3_kernel,
- v3_kernel_pp,
- v3_life
+ v3_kernel_pp
]},
{registered, []},
{applications, [kernel, stdlib]},
diff --git a/lib/compiler/src/core_lint.erl b/lib/compiler/src/core_lint.erl
index 7d3513c0ba..3f69cb03a9 100644
--- a/lib/compiler/src/core_lint.erl
+++ b/lib/compiler/src/core_lint.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -353,12 +353,6 @@ expr(#c_case{arg=Arg,clauses=Cs}, Def, Rt, St0) ->
Pc = case_patcount(Cs),
St1 = body(Arg, Def, Pc, St0),
clauses(Cs, Def, Pc, Rt, St1);
-expr(#c_receive{clauses=Cs,timeout=#c_literal{val=infinity},
- action=#c_literal{}},
- Def, Rt, St) ->
- %% If the timeout is 'infinity', the after code can never
- %% be reached. We don't care if the return count is wrong.
- clauses(Cs, Def, 1, Rt, St);
expr(#c_receive{clauses=Cs,timeout=T,action=A}, Def, Rt, St0) ->
St1 = expr(T, Def, 1, St0),
St2 = body(A, Def, Rt, St1),
@@ -497,8 +491,10 @@ pattern(#c_tuple{es=Es}, Def, Ps, St) ->
pattern_list(Es, Def, Ps, St);
pattern(#c_map{es=Es}, Def, Ps, St) ->
pattern_list(Es, Def, Ps, St);
-pattern(#c_map_pair{op=#c_literal{val=exact},key=K,val=V},Def,Ps,St) ->
- pattern_list([K,V],Def,Ps,St);
+pattern(#c_map_pair{op=#c_literal{val=exact},key=K,val=V}, Def, Ps, St) ->
+ %% The key is an input.
+ pat_map_expr(K, Def, St),
+ pattern_list([V],Def,Ps,St);
pattern(#c_binary{segments=Ss}, Def, Ps, St0) ->
St = pat_bin_tail_check(Ss, St0),
pat_bin(Ss, Def, Ps, St);
@@ -561,6 +557,10 @@ pat_bit_expr(#c_binary{}, _, _Def, St) ->
pat_bit_expr(_, _, _, St) ->
add_error({illegal_expr,St#lint.func}, St).
+pat_map_expr(#c_var{name=N}, Def, St) -> expr_var(N, Def, St);
+pat_map_expr(#c_literal{}, _Def, St) -> St;
+pat_map_expr(_, _, St) -> add_error({illegal_expr,St#lint.func}, St).
+
%% pattern_list([Var], Defined, State) -> {[PatVar],State}.
%% pattern_list([Var], Defined, [PatVar], State) -> {[PatVar],State}.
diff --git a/lib/compiler/src/core_parse.yrl b/lib/compiler/src/core_parse.yrl
index 79a7cccd98..10d8c44dd3 100644
--- a/lib/compiler/src/core_parse.yrl
+++ b/lib/compiler/src/core_parse.yrl
@@ -1,7 +1,7 @@
%% -*-Erlang-*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,7 +36,7 @@ other_pattern atomic_pattern tuple_pattern cons_pattern tail_pattern
binary_pattern segment_patterns segment_pattern
expression single_expression
-literal literals atomic_literal tuple_literal cons_literal tail_literal
+literal literals atomic_literal tuple_literal cons_literal tail_literal fun_literal
nil tuple cons tail
binary segments segment
@@ -267,6 +267,7 @@ single_expression -> cons : '$1'.
single_expression -> binary : '$1'.
single_expression -> variable : '$1'.
single_expression -> function_name : '$1'.
+single_expression -> fun_literal : '$1'.
single_expression -> fun_expr : '$1'.
single_expression -> let_expr : '$1'.
single_expression -> letrec_expr : '$1'.
@@ -303,6 +304,9 @@ tail_literal -> ']' : #c_literal{val=[]}.
tail_literal -> '|' literal ']' : '$2'.
tail_literal -> ',' literal tail_literal : c_cons('$2', '$3').
+fun_literal -> 'fun' atom ':' atom '/' integer :
+ #c_literal{val = erlang:make_fun(tok_val('$2'), tok_val('$4'), tok_val('$6'))}.
+
tuple -> '{' '}' : c_tuple([]).
tuple -> '{' anno_expressions '}' : c_tuple('$2').
@@ -496,7 +500,7 @@ make_lit_bin(Acc, [#c_bitstr{val=I0,size=Sz0,unit=U0,type=Type0,flags=F0}|T]) ->
throw(impossible)
end,
if
- Sz =< 8, T =:= [] ->
+ 0 =< Sz, Sz =< 8, T =:= [] ->
<<Acc/binary,I:Sz>>;
Sz =:= 8 ->
make_lit_bin(<<Acc/binary,I:8>>, T);
diff --git a/lib/compiler/src/core_pp.erl b/lib/compiler/src/core_pp.erl
index cff6c7098b..cb3f24fd08 100644
--- a/lib/compiler/src/core_pp.erl
+++ b/lib/compiler/src/core_pp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -136,6 +136,11 @@ format_1(#c_literal{anno=A,val=M},Ctxt) when is_map(M) ->
key=#c_literal{val=K},
val=#c_literal{val=V}} || {K,V} <- Pairs],
format_1(#c_map{anno=A,arg=#c_literal{val=#{}},es=Cpairs},Ctxt);
+format_1(#c_literal{val=F},_Ctxt) when is_function(F) ->
+ {module,M} = erlang:fun_info(F, module),
+ {name,N} = erlang:fun_info(F, name),
+ {arity,A} = erlang:fun_info(F, arity),
+ ["fun ",core_atom(M),$:,core_atom(N),$/,integer_to_list(A)];
format_1(#c_var{name={I,A}}, _) ->
[core_atom(I),$/,integer_to_list(A)];
format_1(#c_var{name=V}, _) ->
@@ -464,7 +469,7 @@ indent(#ctxt{indent=N}) ->
N =< 0 ->
"";
true ->
- string:chars($\t, N div ?TAB_WIDTH, spaces(N rem ?TAB_WIDTH))
+ lists:duplicate(N div ?TAB_WIDTH, $\t) ++ spaces(N rem ?TAB_WIDTH)
end.
nl_indent(Ctxt) -> [$\n|indent(Ctxt)].
@@ -541,4 +546,3 @@ segs_from_bitstring(Bitstring) ->
unit=#c_literal{val=1},
type=#c_literal{val=integer},
flags=#c_literal{val=[unsigned,big]}}].
-
diff --git a/lib/compiler/src/core_scan.erl b/lib/compiler/src/core_scan.erl
index 9f0676538f..a50a2ffa8d 100644
--- a/lib/compiler/src/core_scan.erl
+++ b/lib/compiler/src/core_scan.erl
@@ -200,8 +200,8 @@ pre_string(eof, Q, _, Sp, SoFar, Pos) ->
pre_string_error(Q, Sp, SoFar, Pos).
pre_string_error(Q, Sp, SoFar, Pos) ->
- S = reverse(string:substr(SoFar, 1, string:chr(SoFar, Q)-1)),
- pre_error({string,Q,string:substr(S, 1, 16)}, Sp, Pos).
+ [S,_] = string:split(SoFar, [Q]),
+ pre_error({string,Q,string:slice(string:reverse(S), 0, 16)}, Sp, Pos).
pre_char([C|Cs], SoFar) -> pre_char(C, Cs, SoFar);
pre_char([], _) -> more;
diff --git a/lib/compiler/src/erl_bifs.erl b/lib/compiler/src/erl_bifs.erl
index bafa9d75b7..68489a0122 100644
--- a/lib/compiler/src/erl_bifs.erl
+++ b/lib/compiler/src/erl_bifs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -94,6 +94,7 @@ is_pure(erlang, is_function, 1) -> true;
is_pure(erlang, is_integer, 1) -> true;
is_pure(erlang, is_list, 1) -> true;
is_pure(erlang, is_map, 1) -> true;
+is_pure(erlang, is_map_key, 2) -> true;
is_pure(erlang, is_number, 1) -> true;
is_pure(erlang, is_pid, 1) -> true;
is_pure(erlang, is_port, 1) -> true;
@@ -109,6 +110,8 @@ is_pure(erlang, list_to_integer, 1) -> true;
is_pure(erlang, list_to_pid, 1) -> true;
is_pure(erlang, list_to_tuple, 1) -> true;
is_pure(erlang, max, 2) -> true;
+is_pure(erlang, make_fun, 3) -> true;
+is_pure(erlang, map_get, 2) -> true;
is_pure(erlang, min, 2) -> true;
is_pure(erlang, phash, 2) -> false;
is_pure(erlang, pid_to_list, 1) -> true;
@@ -196,6 +199,7 @@ is_safe(erlang, is_port, 1) -> true;
is_safe(erlang, is_reference, 1) -> true;
is_safe(erlang, is_tuple, 1) -> true;
is_safe(erlang, make_ref, 0) -> true;
+is_safe(erlang, make_fun, 3) -> true;
is_safe(erlang, max, 2) -> true;
is_safe(erlang, min, 2) -> true;
is_safe(erlang, node, 0) -> true;
diff --git a/lib/compiler/src/genop.tab b/lib/compiler/src/genop.tab
index b5688de339..02dead9e92 100755
--- a/lib/compiler/src/genop.tab
+++ b/lib/compiler/src/genop.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1998-2017. All Rights Reserved.
+# Copyright Ericsson AB 1998-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -545,3 +545,32 @@ BEAM_FORMAT_NUMBER=0
## Test the arity of Reg and jumps to Lbl if it is not N.
## Test the first element of the tuple and jumps to Lbl if it is not Atom.
159: is_tagged_tuple/4
+
+# OTP 21
+
+## @spec build_stacktrace
+## @doc Given the raw stacktrace in x(0), build a cooked stacktrace suitable
+## for human consumption. Store it in x(0). Destroys all other registers.
+## Do a garbage collection if necessary to allocate space on the heap
+## for the result.
+160: build_stacktrace/0
+
+## @spec raw_raise
+## @doc This instruction works like the erlang:raise/3 BIF, except that the
+## stacktrace in x(2) must be a raw stacktrace.
+## x(0) is the class of the exception (error, exit, or throw),
+## x(1) is the exception term, and x(2) is the raw stackframe.
+## If x(0) is not a valid class, the instruction will not throw an
+## exception, but store the atom 'badarg' in x(0) and execute the
+## next instruction.
+161: raw_raise/0
+
+## @spec get_hd Source Head
+## @doc Get the head (or car) part of a list (a cons cell) from Source and
+## put it into the register Head.
+162: get_hd/2
+
+## @spec get_tl Source Tail
+## @doc Get the tail (or cdr) part of a list (a cons cell) from Source and
+## put it into the register Tail.
+163: get_tl/2
diff --git a/lib/compiler/src/sys_core_alias.erl b/lib/compiler/src/sys_core_alias.erl
new file mode 100644
index 0000000000..3326c6a2a8
--- /dev/null
+++ b/lib/compiler/src/sys_core_alias.erl
@@ -0,0 +1,307 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%% Purpose : Replace values by aliases from patterns optimisation for Core
+
+%% Replace expressions by aliases from patterns. For example:
+%%
+%% example({ok, Val}) ->
+%% {ok, Val}.
+%%
+%% will become:
+%%
+%% example({ok, Val} = Tuple) ->
+%% Tuple.
+%%
+%% Currently this pass aliases tuple and cons nodes made of literals,
+%% variables and other cons. The tuple/cons may appear anywhere in the
+%% pattern and it will be aliased if used later on.
+%%
+%% Notice a tuple/cons made only of literals is not aliased as it may
+%% be part of the literal pool.
+
+-module(sys_core_alias).
+
+-export([module/2]).
+
+-include("core_parse.hrl").
+
+-define(NOTSET, 0).
+
+-record(sub, {p=#{} :: #{term() => ?NOTSET | atom()}, %% Found pattern substitutions
+ v=cerl_sets:new() :: cerl_sets:set(cerl:var_name()), %% Variables used by patterns
+ t=undefined :: term()}). %% Temporary information from pre to post
+
+-type sub() :: #sub{}.
+
+-spec module(cerl:c_module(), [compile:option()]) ->
+ {'ok',cerl:c_module(),[]}.
+
+module(#c_module{defs=Ds0}=Mod, _Opts) ->
+ Ds1 = [def(D) || D <- Ds0],
+ {ok,Mod#c_module{defs=Ds1},[]}.
+
+def({#c_var{name={F,Arity}}=Name,B0}) ->
+ try
+ put(new_var_num, 0),
+ {B1,_} = cerl_trees:mapfold(fun pre/2, fun post/2, sub_new(undefined), B0),
+ erase(new_var_num),
+ {Name,B1}
+ catch
+ Class:Error:Stack ->
+ io:fwrite("Function: ~w/~w\n", [F,Arity]),
+ erlang:raise(Class, Error, Stack)
+ end.
+
+pre(#c_let{vars=Vars}=Node, Sub) ->
+ {Node,sub_fold(get_variables(Vars), Sub)};
+
+pre(#c_fun{vars=Vars}=Node, Sub) ->
+ {Node,sub_fold(get_variables(Vars), Sub)};
+
+pre(#c_clause{pats=Pats}=Node, Sub0) ->
+ VarNames = get_variables(Pats),
+ Sub1 = sub_fold(VarNames, Sub0),
+ Keys = get_pattern_keys(Pats),
+ Sub2 = sub_add_keys(Keys, Sub1),
+
+ #sub{v=SubNames,t=Temp} = Sub2,
+ Sub3 = Sub2#sub{v=merge_variables(VarNames, SubNames),
+ t={clause,Pats,Keys,SubNames,Temp}},
+
+ {Node#c_clause{pats=[]},Sub3};
+
+pre(Node, Sub0) ->
+ %% We cache only tuples and cons.
+ case cerl:is_data(Node) andalso not cerl:is_literal(Node) of
+ false ->
+ {Node,Sub0};
+ true ->
+ Kind = cerl:data_type(Node),
+ Es = cerl:data_es(Node),
+ case sub_cache_nodes(Kind, Es, Sub0) of
+ {Name,Sub1} ->
+ {cerl:ann_c_var(cerl:get_ann(Node), Name),Sub1};
+ error ->
+ {Node,Sub0}
+ end
+ end.
+
+post(#c_let{}=Node, Sub) ->
+ {Node,sub_unfold(Sub)};
+
+post(#c_fun{}=Node, Sub) ->
+ {Node,sub_unfold(Sub)};
+
+post(#c_clause{}=Node, #sub{t={clause,Pats0,Keys,V,T}}=Sub0) ->
+ {Sub1,PostKeys} = sub_take_keys(Keys, Sub0),
+ Pats1 = put_pattern_keys(Pats0, PostKeys),
+ Sub2 = sub_unfold(Sub1#sub{v=V,t=T}),
+ {Node#c_clause{pats=Pats1},Sub2};
+
+post(Node, Sub) ->
+ {Node,Sub}.
+
+%% sub_new/1
+%% sub_add_keys/2
+%% sub_take_keys/3
+%% sub_cache_nodes/3
+%%
+%% Manages the substitutions record.
+
+%% Builds a new sub.
+-spec sub_new(term()) -> sub().
+sub_new(Temp) ->
+ #sub{t=Temp}.
+
+%% Folds the sub into a new one if the variables in nodes are not disjoint
+sub_fold(VarNames, #sub{v=SubNames}=Sub) ->
+ case is_disjoint_variables(VarNames, SubNames) of
+ true -> Sub#sub{t={temp,Sub#sub.t}};
+ false -> sub_new({sub,Sub})
+ end.
+
+%% Unfolds the sub in case one was folded in the previous step
+sub_unfold(#sub{t={temp,Temp}}=Sub) ->
+ Sub#sub{t=Temp};
+sub_unfold(#sub{t={sub,Sub}}) ->
+ Sub.
+
+%% Adds the keys extracted from patterns to the state.
+-spec sub_add_keys([term()], sub()) -> sub().
+sub_add_keys(Keys, #sub{p=Pat0}=Sub) ->
+ Pat1 =
+ lists:foldl(fun(Key, Acc) ->
+ false = maps:is_key(Key, Acc), %Assertion.
+ maps:put(Key, ?NOTSET, Acc)
+ end, Pat0, Keys),
+ Sub#sub{p=Pat1}.
+
+%% Take the keys from the map taking into account the keys
+%% that have changed as those must become aliases in the pattern.
+-spec sub_take_keys([term()], sub()) -> {sub(), [{term(), atom()}]}.
+sub_take_keys(Keys, #sub{p=Pat0}=Sub) ->
+ {Pat1,Acc} = sub_take_keys(Keys, Pat0, []),
+ {Sub#sub{p=Pat1},Acc}.
+
+sub_take_keys([K|T], Sub0, Acc) ->
+ case maps:take(K, Sub0) of
+ {?NOTSET,Sub1} ->
+ sub_take_keys(T, Sub1, Acc);
+ {Name,Sub1} ->
+ sub_take_keys(T, Sub1, [{K,Name}|Acc])
+ end;
+sub_take_keys([], Sub, Acc) ->
+ {Sub,Acc}.
+
+%% Check if the node can be cached based on the state information.
+%% If it can be cached and it does not have an alias for it, we
+%% build one.
+-spec sub_cache_nodes(atom(), [cerl:cerl()], sub()) -> {atom(), sub()} | error.
+sub_cache_nodes(Kind, Nodes, #sub{p=Pat}=Sub) ->
+ case nodes_to_key(Kind, Nodes) of
+ {ok, Key} ->
+ case Pat of
+ #{Key := ?NOTSET} ->
+ new_var_name(Key, Sub);
+ #{Key := Name} ->
+ {Name,Sub};
+ #{} ->
+ error
+ end;
+ error ->
+ error
+ end.
+
+new_var_name(Key, #sub{p=Pat}=Sub) ->
+ Counter = get(new_var_num),
+ Name = list_to_atom("@r" ++ integer_to_list(Counter)),
+ put(new_var_num, Counter + 1),
+ {Name,Sub#sub{p=maps:put(Key, Name, Pat)}}.
+
+%% get_variables/1
+%% is_disjoint_variables/2
+%% merge_variables/2
+
+get_variables(NodesList) ->
+ cerl_sets:from_list([Var || Node <- NodesList, Var <- cerl_trees:variables(Node)]).
+
+is_disjoint_variables(Vars1, Vars2) ->
+ cerl_sets:is_disjoint(Vars1, Vars2).
+
+merge_variables(Vars1, Vars2) ->
+ cerl_sets:union(Vars1, Vars2).
+
+%% get_pattern_keys/2
+%% put_pattern_keys/2
+%%
+%% Gets keys from patterns or add them as aliases.
+
+get_pattern_keys(Patterns) ->
+ lists:foldl(fun get_pattern_keys/2, [], Patterns).
+
+get_pattern_keys(#c_tuple{es=Es}, Acc0) ->
+ Acc1 = accumulate_pattern_keys(tuple, Es, Acc0),
+ lists:foldl(fun get_pattern_keys/2, Acc1, Es);
+get_pattern_keys(#c_cons{hd=Hd,tl=Tl}, Acc0) ->
+ Acc1 = accumulate_pattern_keys(cons, [Hd, Tl], Acc0),
+ get_pattern_keys(Tl, get_pattern_keys(Hd, Acc1));
+get_pattern_keys(#c_alias{pat=Pat}, Acc0) ->
+ get_pattern_keys(Pat, Acc0);
+get_pattern_keys(#c_map{es=Es}, Acc0) ->
+ lists:foldl(fun get_pattern_keys/2, Acc0, Es);
+get_pattern_keys(#c_map_pair{val=Val}, Acc0) ->
+ get_pattern_keys(Val, Acc0);
+get_pattern_keys(_, Acc) ->
+ Acc.
+
+accumulate_pattern_keys(Kind, Nodes, Acc) ->
+ case nodes_to_key(Kind, Nodes) of
+ {ok,Key} -> [Key|Acc];
+ error -> Acc
+ end.
+
+put_pattern_keys(Patterns, []) ->
+ Patterns;
+put_pattern_keys(Patterns, Keys) ->
+ {NewPatterns,Map} =
+ lists:mapfoldl(fun alias_pattern_keys/2, maps:from_list(Keys), Patterns),
+ %% Check all aliases have been consumed from the map.
+ 0 = map_size(Map),
+ NewPatterns.
+
+alias_pattern_keys(#c_tuple{anno=Anno,es=Es0}=Node, Acc0) ->
+ {Es1,Acc1} = lists:mapfoldl(fun alias_pattern_keys/2, Acc0, Es0),
+ nodes_to_alias(tuple, Es0, Anno, Node#c_tuple{es=Es1}, Acc1);
+alias_pattern_keys(#c_cons{anno=Anno,hd=Hd0,tl=Tl0}=Node, Acc0) ->
+ {Hd1,Acc1} = alias_pattern_keys(Hd0, Acc0),
+ {Tl1,Acc2} = alias_pattern_keys(Tl0, Acc1),
+ nodes_to_alias(cons, [Hd0, Tl0], Anno, Node#c_cons{hd=Hd1,tl=Tl1}, Acc2);
+alias_pattern_keys(#c_alias{pat=Pat0}=Node, Acc0) ->
+ {Pat1,Acc1} = alias_pattern_keys(Pat0, Acc0),
+ {Node#c_alias{pat=Pat1}, Acc1};
+alias_pattern_keys(#c_map{es=Es0}=Node, Acc0) ->
+ {Es1,Acc1} = lists:mapfoldl(fun alias_pattern_keys/2, Acc0, Es0),
+ {Node#c_map{es=Es1}, Acc1};
+alias_pattern_keys(#c_map_pair{val=Val0}=Node, Acc0) ->
+ {Val1,Acc1} = alias_pattern_keys(Val0, Acc0),
+ {Node#c_map_pair{val=Val1}, Acc1};
+alias_pattern_keys(Pattern, Acc) ->
+ {Pattern,Acc}.
+
+%% Check if a node must become an alias because
+%% its pattern was used later on as an expression.
+nodes_to_alias(Kind, Inner, Anno, Node, Keys0) ->
+ case nodes_to_key(Kind, Inner) of
+ {ok,Key} ->
+ case maps:take(Key, Keys0) of
+ {Name,Keys1} ->
+ Var = cerl:ann_c_var(Anno, Name),
+ {cerl:ann_c_alias(Anno, Var, Node), Keys1};
+ error ->
+ {Node,Keys0}
+ end;
+ error ->
+ {Node,Keys0}
+ end.
+
+%% Builds the key used to check if a value can be
+%% replaced by an alias. It considers literals,
+%% aliases, variables, tuples and cons recursively.
+nodes_to_key(Kind, Nodes) ->
+ nodes_to_key(Nodes, [], Kind).
+
+nodes_to_key([#c_alias{var=Var}|T], Acc, Kind) ->
+ nodes_to_key([Var|T], Acc, Kind);
+nodes_to_key([#c_var{name=Name}|T], Acc, Kind) ->
+ nodes_to_key(T, [[var,Name]|Acc], Kind);
+nodes_to_key([Node|T], Acc0, Kind) ->
+ case cerl:is_data(Node) of
+ false ->
+ error;
+ true ->
+ case nodes_to_key(cerl:data_es(Node), [], cerl:data_type(Node)) of
+ {ok,Key} ->
+ nodes_to_key(T, [Key|Acc0], Kind);
+ error ->
+ error
+ end
+ end;
+nodes_to_key([], Acc, Kind) ->
+ {ok,[Kind|Acc]}.
diff --git a/lib/compiler/src/sys_core_bsm.erl b/lib/compiler/src/sys_core_bsm.erl
index 3e04cc33df..62657933ee 100644
--- a/lib/compiler/src/sys_core_bsm.erl
+++ b/lib/compiler/src/sys_core_bsm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@
-export([module/2,format_error/1]).
-include("core_parse.hrl").
--import(lists, [member/2,nth/2,reverse/1,usort/1]).
+-import(lists, [member/2,reverse/1,usort/1]).
-spec module(cerl:c_module(), [compile:option()]) -> {'ok', cerl:c_module()}.
@@ -44,8 +44,15 @@ function([{#c_var{name={F,Arity}}=Name,B0}|Fs], FsAcc, Ws0) ->
{B,Ws} ->
function(Fs, [{Name,B}|FsAcc], Ws)
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ throw:unsafe_bs_context_to_binary ->
+ %% Unsafe bs_context_to_binary (in the sense that the
+ %% contents of the binary will probably be wrong).
+ %% Disable binary optimizations for the entire function.
+ %% We don't generate an INFO message, because this happens
+ %% very infrequently and it would be hard to explain in
+ %% a comprehensible way in an INFO message.
+ function(Fs, [{Name,B0}|FsAcc], Ws0);
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [F,Arity]),
erlang:raise(Class, Error, Stack)
end;
@@ -60,13 +67,6 @@ format_error(bin_opt_alias) ->
format_error(bin_partition) ->
"INFO: matching non-variables after a previous clause matching a variable "
"will prevent delayed sub binary optimization";
-format_error(bin_left_var_used_in_guard) ->
- "INFO: a variable to the left of the binary pattern is used in a guard; "
- "will prevent delayed sub binary optimization";
-format_error(bin_argument_order) ->
- "INFO: matching anything else but a plain variable to the left of "
- "binary pattern will prevent delayed sub binary optimization; "
- "SUGGEST changing argument order";
format_error(bin_var_used) ->
"INFO: using a matched out sub binary will prevent "
"delayed sub binary optimization";
@@ -97,46 +97,95 @@ bsm_an(#c_case{arg=#c_values{es=Es}}=Case) ->
bsm_an(Other) ->
{ok,Other}.
-bsm_an_1(Vs, #c_case{clauses=Cs}=Case) ->
- case bsm_leftmost(Cs) of
- none -> {ok,Case};
- Pos -> bsm_an_2(Vs, Cs, Case, Pos)
- end.
-
-bsm_an_2(Vs, Cs, Case, Pos) ->
- case bsm_nonempty(Cs, Pos) of
- true -> bsm_an_3(Vs, Cs, Case, Pos);
- false -> {ok,Case}
+bsm_an_1(Vs0, #c_case{clauses=Cs0}=Case) ->
+ case bsm_leftmost(Cs0) of
+ none ->
+ {ok,Case};
+ 1 ->
+ bsm_an_2(Vs0, Cs0, Case);
+ Pos ->
+ Vs = move_from_col(Pos, Vs0),
+ Cs = [C#c_clause{pats=move_from_col(Pos, Ps)} ||
+ #c_clause{pats=Ps}=C <- Cs0],
+ bsm_an_2(Vs, Cs, Case)
end.
-bsm_an_3(Vs, Cs, Case, Pos) ->
+bsm_an_2(Vs, Cs, Case) ->
try
- bsm_ensure_no_partition(Cs, Pos),
- {ok,bsm_do_an(Vs, Pos, Cs, Case)}
+ bsm_ensure_no_partition(Cs),
+ {ok,bsm_do_an(Vs, Cs, Case)}
catch
- throw:{problem,Where,What} ->
- {ok,Case,{Where,What}}
+ throw:{problem,Where,What} ->
+ {ok,Case,{Where,What}}
end.
-bsm_do_an(Vs0, Pos, Cs0, Case) ->
- case nth(Pos, Vs0) of
- #c_var{name=Vname}=V0 ->
- Cs = bsm_do_an_var(Vname, Pos, Cs0, []),
- V = bsm_annotate_for_reuse(V0),
- Bef = lists:sublist(Vs0, Pos-1),
- Aft = lists:nthtail(Pos, Vs0),
- case Bef ++ [V|Aft] of
- [_] ->
- Case#c_case{arg=V,clauses=Cs};
- Vs ->
- Case#c_case{arg=#c_values{es=Vs},clauses=Cs}
- end;
- _ ->
- Case
- end.
+move_from_col(Pos, L) ->
+ {First,[Col|Rest]} = lists:split(Pos - 1, L),
+ [Col|First] ++ Rest.
+
+bsm_do_an([#c_var{name=Vname}=V0|Vs0], Cs0, Case) ->
+ bsm_inner_context_to_binary(Cs0),
+ Cs = bsm_do_an_var(Vname, Cs0),
+ V = bsm_annotate_for_reuse(V0),
+ Vs = core_lib:make_values([V|Vs0]),
+ Case#c_case{arg=Vs,clauses=Cs};
+bsm_do_an(_Vs, _Cs, Case) -> Case.
+
+bsm_inner_context_to_binary([#c_clause{body=B}|Cs]) ->
+ %% Consider:
+ %%
+ %% foo(<<Length, Data/binary>>) -> %Line 1
+ %% case {Data, Length} of %Line 2
+ %% {_, 0} -> Data; %Line 3
+ %% {<<...>>, 4} -> ... %Line 4
+ %% end.
+ %%
+ %% No sub binary will be created for Data in line 1. The match
+ %% context will be passed on to the `case` in line 2. In line 3,
+ %% this pass inserts a `bs_context_to_binary` instruction to
+ %% convert the match context representing Data to a binary before
+ %% returning it. The problem is that the binary created will be
+ %% the original binary (including the matched out Length field),
+ %% not the tail of the binary as it is supposed to be.
+ %%
+ %% Here follows a heuristic to disable the binary optimizations
+ %% for the entire function if this code kind of code is found.
+
+ case cerl_trees:free_variables(B) of
+ [] ->
+ %% Since there are no free variables in the body of
+ %% this clause, there can't be any troublesome
+ %% bs_context_to_binary instructions.
+ bsm_inner_context_to_binary(Cs);
+ [_|_]=Free ->
+ %% One of the free variables could refer to a match context
+ %% created by the outer binary match.
+ F = fun(#c_primop{name=#c_literal{val=bs_context_to_binary},
+ args=[#c_var{name=V}]}, _) ->
+ case member(V, Free) of
+ true ->
+ %% This bs_context_to_binary instruction will
+ %% make a binary of the match context from an
+ %% outer binary match. It is very likely that
+ %% the contents of the binary will be wrong
+ %% (the original binary as opposed to only
+ %% the tail binary).
+ throw(unsafe_bs_context_to_binary);
+ false ->
+ %% Safe. This bs_context_to_binary instruction
+ %% will make a binary from a match context
+ %% defined in the body of the clause.
+ ok
+ end;
+ (_, _) ->
+ ok
+ end,
+ cerl_trees:fold(F, ok, B)
+ end;
+bsm_inner_context_to_binary([]) -> ok.
-bsm_do_an_var(V, S, [#c_clause{pats=Ps,guard=G,body=B0}=C0|Cs], Acc) ->
- case nth(S, Ps) of
+bsm_do_an_var(V, [#c_clause{pats=[P|_],guard=G,body=B0}=C0|Cs]) ->
+ case P of
#c_var{name=VarName} ->
case core_lib:is_var_used(V, G) of
true -> bsm_problem(C0, orig_bin_var_used_in_guard);
@@ -149,23 +198,23 @@ bsm_do_an_var(V, S, [#c_clause{pats=Ps,guard=G,body=B0}=C0|Cs], Acc) ->
B1 = bsm_maybe_ctx_to_binary(VarName, B0),
B = bsm_maybe_ctx_to_binary(V, B1),
C = C0#c_clause{body=B},
- bsm_do_an_var(V, S, Cs, [C|Acc]);
- #c_alias{}=P ->
+ [C|bsm_do_an_var(V, Cs)];
+ #c_alias{} ->
case bsm_could_match_binary(P) of
false ->
- bsm_do_an_var(V, S, Cs, [C0|Acc]);
+ [C0|bsm_do_an_var(V, Cs)];
true ->
bsm_problem(C0, bin_opt_alias)
end;
- P ->
+ _ ->
case bsm_could_match_binary(P) andalso bsm_is_var_used(V, G, B0) of
false ->
- bsm_do_an_var(V, S, Cs, [C0|Acc]);
+ [C0|bsm_do_an_var(V, Cs)];
true ->
bsm_problem(C0, bin_var_used)
end
end;
-bsm_do_an_var(_, _, [], Acc) -> reverse(Acc).
+bsm_do_an_var(_, []) -> [].
bsm_annotate_for_reuse(#c_var{anno=Anno}=Var) ->
Var#c_var{anno=[reuse_for_context|Anno]}.
@@ -193,131 +242,82 @@ previous_ctx_to_binary(V, Core) ->
end.
%% bsm_leftmost(Cs) -> none | ArgumentNumber
-%% Find the leftmost argument that does binary matching. Return
-%% the number of the argument (1-N).
+%% Find the leftmost argument that matches a nonempty binary.
+%% Return either 'none' or the argument number (1-N).
bsm_leftmost(Cs) ->
bsm_leftmost_1(Cs, none).
+bsm_leftmost_1([_|_], 1) ->
+ 1;
bsm_leftmost_1([#c_clause{pats=Ps}|Cs], Pos) ->
bsm_leftmost_2(Ps, Cs, 1, Pos);
bsm_leftmost_1([], Pos) -> Pos.
bsm_leftmost_2(_, Cs, Pos, Pos) ->
bsm_leftmost_1(Cs, Pos);
-bsm_leftmost_2([#c_binary{}|_], Cs, N, _) ->
+bsm_leftmost_2([#c_binary{segments=[_|_]}|_], Cs, N, _) ->
bsm_leftmost_1(Cs, N);
bsm_leftmost_2([_|Ps], Cs, N, Pos) ->
bsm_leftmost_2(Ps, Cs, N+1, Pos);
bsm_leftmost_2([], Cs, _, Pos) ->
bsm_leftmost_1(Cs, Pos).
-%% bsm_nonempty(Cs, Pos) -> true|false
-%% Check if at least one of the clauses matches a non-empty
-%% binary in the given argument position.
+%% bsm_ensure_no_partition(Cs) -> ok (exception if problem)
+%% There must only be a single bs_start_match2 instruction if we
+%% are to reuse the binary variable for the match context.
+%%
+%% To make sure that there is only a single bs_start_match2
+%% instruction, we will check for partitions such as:
%%
-bsm_nonempty([#c_clause{pats=Ps}|Cs], Pos) ->
- case nth(Pos, Ps) of
- #c_binary{segments=[_|_]} ->
- true;
- _ ->
- bsm_nonempty(Cs, Pos)
- end;
-bsm_nonempty([], _ ) -> false.
-
-%% bsm_ensure_no_partition(Cs, Pos) -> ok (exception if problem)
-%% We must make sure that matching is not partitioned between
-%% variables like this:
%% foo(<<...>>) -> ...
%% foo(<Variable>) when ... -> ...
-%% foo(<Any non-variable pattern>) ->
-%% If there is such partition, we are not allowed to reuse the binary variable
-%% for the match context.
+%% foo(<Non-variable pattern>) ->
%%
-%% Also, arguments to the left of the argument that is matched
-%% against a binary, are only allowed to be simple variables, not
-%% used in guards. The reason is that we must know that the binary is
-%% only matched in one place (i.e. there must be only one bs_start_match2
-%% instruction emitted).
+%% If there is such partition, we reject the optimization.
-bsm_ensure_no_partition(Cs, Pos) ->
- bsm_ensure_no_partition_1(Cs, Pos, before).
+bsm_ensure_no_partition(Cs) ->
+ bsm_ensure_no_partition_1(Cs, before).
%% Loop through each clause.
-bsm_ensure_no_partition_1([#c_clause{pats=Ps,guard=G}|Cs], Pos, State0) ->
- State = bsm_ensure_no_partition_2(Ps, Pos, G, simple_vars, State0),
+bsm_ensure_no_partition_1([#c_clause{pats=Ps,guard=G}|Cs], State0) ->
+ State = bsm_ensure_no_partition_2(Ps, G, State0),
case State of
'after' ->
- bsm_ensure_no_partition_after(Cs, Pos);
+ bsm_ensure_no_partition_after(Cs);
_ ->
ok
end,
- bsm_ensure_no_partition_1(Cs, Pos, State);
-bsm_ensure_no_partition_1([], _, _) -> ok.
+ bsm_ensure_no_partition_1(Cs, State);
+bsm_ensure_no_partition_1([], _) -> ok.
-%% Loop through each pattern for this clause.
-bsm_ensure_no_partition_2([#c_binary{}=Where|_], 1, _, Vstate, State) ->
- case State of
- before when Vstate =:= simple_vars -> within;
- before -> bsm_problem(Where, Vstate);
- within when Vstate =:= simple_vars -> within;
- within -> bsm_problem(Where, Vstate)
- end;
-bsm_ensure_no_partition_2([#c_alias{}=Alias|_], 1, N, Vstate, State) ->
+bsm_ensure_no_partition_2([#c_binary{}|_], _, _State) ->
+ within;
+bsm_ensure_no_partition_2([#c_alias{}=Alias|_], N, State) ->
%% Retrieve the real pattern that the alias refers to and check that.
P = bsm_real_pattern(Alias),
- bsm_ensure_no_partition_2([P], 1, N, Vstate, State);
-bsm_ensure_no_partition_2([_|_], 1, _, _Vstate, before=State) ->
+ bsm_ensure_no_partition_2([P], N, State);
+bsm_ensure_no_partition_2([_|_], _, before=State) ->
%% No binary matching yet - therefore no partition.
State;
-bsm_ensure_no_partition_2([P|_], 1, _, Vstate, State) ->
+bsm_ensure_no_partition_2([P|_], _, State) ->
case bsm_could_match_binary(P) of
false ->
- %% If clauses can be freely arranged (Vstate =:= simple_vars),
- %% a clause that cannot match a binary will not partition the clause.
- %% Example:
- %%
- %% a(Var, <<>>) -> ...
- %% a(Var, []) -> ...
- %% a(Var, <<B>>) -> ...
- %%
- %% But if the clauses can't be freely rearranged, as in
- %%
- %% b(Var, <<X>>) -> ...
- %% b(1, 2) -> ...
- %%
- %% we do have a problem.
- %%
- case Vstate of
- simple_vars -> State;
- _ -> bsm_problem(P, Vstate)
- end;
+ State;
true ->
%% The pattern P *may* match a binary, so we must update the state.
%% (P must be a variable.)
- case State of
- within -> 'after';
- 'after' -> 'after'
- end
- end;
-bsm_ensure_no_partition_2([#c_var{name=V}|Ps], N, G, Vstate, S) ->
- case core_lib:is_var_used(V, G) of
- false ->
- bsm_ensure_no_partition_2(Ps, N-1, G, Vstate, S);
- true ->
- bsm_ensure_no_partition_2(Ps, N-1, G, bin_left_var_used_in_guard, S)
- end;
-bsm_ensure_no_partition_2([_|Ps], N, G, _, S) ->
- bsm_ensure_no_partition_2(Ps, N-1, G, bin_argument_order, S).
+ 'after'
+ end.
-bsm_ensure_no_partition_after([#c_clause{pats=Ps}=C|Cs], Pos) ->
- case nth(Pos, Ps) of
- #c_var{} ->
- bsm_ensure_no_partition_after(Cs, Pos);
- _ ->
- bsm_problem(C, bin_partition)
+bsm_ensure_no_partition_after([#c_clause{pats=Ps}=C|Cs]) ->
+ case Ps of
+ [#c_var{}|_] ->
+ bsm_ensure_no_partition_after(Cs);
+ _ ->
+ bsm_problem(C, bin_partition)
end;
-bsm_ensure_no_partition_after([], _) -> ok.
+bsm_ensure_no_partition_after([]) -> ok.
bsm_could_match_binary(#c_alias{pat=P}) -> bsm_could_match_binary(P);
bsm_could_match_binary(#c_cons{}) -> false;
diff --git a/lib/compiler/src/sys_core_dsetel.erl b/lib/compiler/src/sys_core_dsetel.erl
index bd3eeae238..9ab83c210f 100644
--- a/lib/compiler/src/sys_core_dsetel.erl
+++ b/lib/compiler/src/sys_core_dsetel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -81,8 +81,7 @@ visit_module_1([{Name,F0}|Fs], Env, Acc) ->
{F,_} ->
visit_module_1(Fs, Env, [{Name,F}|Acc])
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
#c_var{name={Func,Arity}} = Name,
io:fwrite("Function: ~w/~w\n", [Func,Arity]),
erlang:raise(Class, Error, Stack)
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index e0cd6da06f..3a65b40fa5 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -108,25 +108,29 @@
module(#c_module{defs=Ds0}=Mod, Opts) ->
put(no_inline_list_funcs, not member(inline_list_funcs, Opts)),
- case get(new_var_num) of
- undefined -> put(new_var_num, 0);
- _ -> ok
- end,
init_warnings(),
Ds1 = [function_1(D) || D <- Ds0],
+ erase(new_var_num),
erase(no_inline_list_funcs),
{ok,Mod#c_module{defs=Ds1},get_warnings()}.
function_1({#c_var{name={F,Arity}}=Name,B0}) ->
try
+ %% Find a suitable starting value for the variable
+ %% counter. Note that this pass assumes that new_var_name/1
+ %% returns a variable name distinct from any variable used in
+ %% the entire body of the function. We use integers as
+ %% variable names to avoid filling up the atom table when
+ %% compiling huge functions.
+ Count = cerl_trees:next_free_variable_name(B0),
+ put(new_var_num, Count),
B = find_fixpoint(fun(Core) ->
%% This must be a fun!
expr(Core, value, sub_new())
end, B0, 20),
{Name,B}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [F,Arity]),
erlang:raise(Class, Error, Stack)
end.
@@ -146,14 +150,9 @@ find_fixpoint(OptFun, Core0, Max) ->
body(Body, Sub) ->
body(Body, value, Sub).
-body(#c_values{anno=A,es=Es0}, Ctxt, Sub) ->
- Es1 = expr_list(Es0, Ctxt, Sub),
- case Ctxt of
- value ->
- #c_values{anno=A,es=Es1};
- effect ->
- make_effect_seq(Es1, Sub)
- end;
+body(#c_values{anno=A,es=Es0}, value, Sub) ->
+ Es1 = expr_list(Es0, value, Sub),
+ #c_values{anno=A,es=Es1};
body(E, Ctxt, Sub) ->
?ASSERT(verify_scope(E, Sub)),
expr(E, Ctxt, Sub).
@@ -208,6 +207,8 @@ opt_guard_try(#c_case{clauses=Cs}=Term) ->
Term#c_case{clauses=opt_guard_try_list(Cs)};
opt_guard_try(#c_clause{body=B0}=Term) ->
Term#c_clause{body=opt_guard_try(B0)};
+opt_guard_try(#c_let{vars=[],arg=#c_values{es=[]},body=B}) ->
+ B;
opt_guard_try(#c_let{arg=Arg,body=B0}=Term) ->
case opt_guard_try(B0) of
#c_literal{}=B ->
@@ -314,9 +315,15 @@ expr(#c_seq{arg=Arg0,body=B0}=Seq0, Ctxt, Sub) ->
false ->
%% Arg cannot be "values" here - only a single value
%% make sense here.
- case is_safe_simple(Arg, Sub) of
- true -> B1;
- false -> Seq0#c_seq{arg=Arg,body=B1}
+ case {Ctxt,is_safe_simple(Arg, Sub)} of
+ {effect,true} -> B1;
+ {effect,false} ->
+ case is_safe_simple(B1, Sub) of
+ true -> Arg;
+ false -> Seq0#c_seq{arg=Arg,body=B1}
+ end;
+ {value,true} -> B1;
+ {value,false} -> Seq0#c_seq{arg=Arg,body=B1}
end
end;
expr(#c_let{}=Let0, Ctxt, Sub) ->
@@ -338,7 +345,12 @@ expr(#c_letrec{body=#c_var{}}=Letrec, effect, _Sub) ->
void();
expr(#c_letrec{defs=Fs0,body=B0}=Letrec, Ctxt, Sub) ->
Fs1 = map(fun ({Name,Fb}) ->
- {Name,expr(Fb, {letrec,Ctxt}, Sub)}
+ case Ctxt =:= effect andalso is_fun_effect_safe(Name, B0) of
+ true ->
+ {Name,expr(Fb, {letrec, effect}, Sub)};
+ false ->
+ {Name,expr(Fb, {letrec, value}, Sub)}
+ end
end, Fs0),
B1 = body(B0, Ctxt, Sub),
Letrec#c_letrec{defs=Fs1,body=B1};
@@ -380,10 +392,7 @@ expr(#c_case{}=Case0, Ctxt, Sub) ->
Case = Case1#c_case{arg=Arg2,clauses=Cs2},
warn_no_clause_match(Case1, Case),
Expr = eval_case(Case, Sub),
- case move_case_into_arg(Case, Sub) of
- impossible -> Expr;
- Other -> Other
- end;
+ move_case_into_arg(Expr, Sub);
Other ->
expr(Other, Ctxt, Sub)
end;
@@ -392,14 +401,15 @@ expr(#c_receive{clauses=Cs0,timeout=T0,action=A0}=Recv, Ctxt, Sub) ->
T1 = expr(T0, value, Sub),
A1 = body(A0, Ctxt, Sub),
Recv#c_receive{clauses=Cs1,timeout=T1,action=A1};
-expr(#c_apply{anno=Anno,op=Op0,args=As0}=App, _, Sub) ->
+expr(#c_apply{anno=Anno,op=Op0,args=As0}=Apply0, _, Sub) ->
Op1 = expr(Op0, value, Sub),
As1 = expr_list(As0, value, Sub),
- case Op1 of
- #c_var{} ->
- App#c_apply{op=Op1,args=As1};
- _ ->
- add_warning(App, invalid_call),
+ case cerl:is_data(Op1) andalso not is_literal_fun(Op1) of
+ false ->
+ Apply = Apply0#c_apply{op=Op1,args=As1},
+ fold_apply(Apply, Op1, As1);
+ true ->
+ add_warning(Apply0, invalid_call),
Err = #c_call{anno=Anno,
module=#c_literal{val=erlang},
name=#c_literal{val=error},
@@ -415,9 +425,20 @@ expr(#c_call{module=M0,name=N0}=Call0, Ctxt, Sub) ->
no -> call(Call, M1, N1, Sub);
{yes,Seq} -> expr(Seq, Ctxt, Sub)
end;
+expr(#c_primop{name=#c_literal{val=build_stacktrace}}, effect, _Sub) ->
+ void();
expr(#c_primop{args=As0}=Prim, _, Sub) ->
As1 = expr_list(As0, value, Sub),
Prim#c_primop{args=As1};
+expr(#c_catch{anno=Anno,body=B}, effect, Sub) ->
+ %% When the return value of the 'catch' is ignored, we can replace it
+ %% with a try/catch to avoid building a stack trace when an exception
+ %% occurs.
+ Var = #c_var{name='catch_value'},
+ Evs = [#c_var{name='Class'},#c_var{name='Reason'},#c_var{name='Stk'}],
+ Try = #c_try{anno=Anno,arg=B,vars=[Var],body=Var,
+ evars=Evs,handler=void()},
+ expr(Try, effect, Sub);
expr(#c_catch{body=B0}=Catch, _, Sub) ->
%% We can remove catch if the value is simple
B1 = body(B0, value, Sub),
@@ -460,6 +481,86 @@ expr(#c_try{anno=A,arg=E0,vars=Vs0,body=B0,evars=Evs0,handler=H0}=Try, _, Sub0)
Try#c_try{arg=E1,vars=Vs1,body=B1,evars=Evs1,handler=H1}
end.
+
+%% If a fun or its application is used as an argument, then it's unsafe to
+%% handle it in effect context as the side-effects may rely on its return
+%% value. The following is a minimal example of where it can go wrong:
+%%
+%% do letrec 'f'/0 = fun () -> ... whatever ...
+%% in call 'side':'effect'(apply 'f'/0())
+%% 'ok'
+%%
+%% This function returns 'true' if Body definitely does not rely on a
+%% value produced by FVar, or 'false' if Body depends on or might depend on
+%% a value produced by FVar.
+
+is_fun_effect_safe(#c_var{}=FVar, Body) ->
+ ifes_1(FVar, Body, true).
+
+ifes_1(FVar, #c_alias{pat=Pat}, _Safe) ->
+ ifes_1(FVar, Pat, false);
+ifes_1(FVar, #c_apply{op=Op,args=Args}, Safe) ->
+ %% FVar(...) is safe as long its return value is ignored, but it's never
+ %% okay to pass FVar as an argument.
+ ifes_list(FVar, Args, false) andalso ifes_1(FVar, Op, Safe);
+ifes_1(FVar, #c_binary{segments=Segments}, _Safe) ->
+ ifes_list(FVar, Segments, false);
+ifes_1(FVar, #c_bitstr{val=Val,size=Size,unit=Unit}, _Safe) ->
+ ifes_list(FVar, [Val, Size, Unit], false);
+ifes_1(FVar, #c_call{args=Args}, _Safe) ->
+ ifes_list(FVar, Args, false);
+ifes_1(FVar, #c_case{arg=Arg,clauses=Clauses}, Safe) ->
+ ifes_1(FVar, Arg, false) andalso ifes_list(FVar, Clauses, Safe);
+ifes_1(FVar, #c_catch{body=Body}, _Safe) ->
+ ifes_1(FVar, Body, false);
+ifes_1(FVar, #c_clause{pats=Pats,guard=Guard,body=Body}, Safe) ->
+ ifes_list(FVar, Pats, false) andalso
+ ifes_1(FVar, Guard, false) andalso
+ ifes_1(FVar, Body, Safe);
+ifes_1(FVar, #c_cons{hd=Hd,tl=Tl}, _Safe) ->
+ ifes_1(FVar, Hd, false) andalso ifes_1(FVar, Tl, false);
+ifes_1(FVar, #c_fun{body=Body}, _Safe) ->
+ ifes_1(FVar, Body, false);
+ifes_1(FVar, #c_let{arg=Arg,body=Body}, Safe) ->
+ ifes_1(FVar, Arg, false) andalso ifes_1(FVar, Body, Safe);
+ifes_1(FVar, #c_letrec{defs=Defs,body=Body}, Safe) ->
+ Funs = [Fun || {_,Fun} <- Defs],
+ ifes_list(FVar, Funs, false) andalso ifes_1(FVar, Body, Safe);
+ifes_1(_FVar, #c_literal{}, _Safe) ->
+ true;
+ifes_1(FVar, #c_map{arg=Arg,es=Elements}, _Safe) ->
+ ifes_1(FVar, Arg, false) andalso ifes_list(FVar, Elements, false);
+ifes_1(FVar, #c_map_pair{key=Key,val=Val}, _Safe) ->
+ ifes_1(FVar, Key, false) andalso ifes_1(FVar, Val, false);
+ifes_1(FVar, #c_primop{args=Args}, _Safe) ->
+ ifes_list(FVar, Args, false);
+ifes_1(FVar, #c_receive{timeout=Timeout,action=Action,clauses=Clauses}, Safe) ->
+ ifes_1(FVar, Timeout, false) andalso
+ ifes_1(FVar, Action, Safe) andalso
+ ifes_list(FVar, Clauses, Safe);
+ifes_1(FVar, #c_seq{arg=Arg,body=Body}, Safe) ->
+ %% Arg of a #c_seq{} has no effect so it's okay to use FVar there even if
+ %% Safe=false.
+ ifes_1(FVar, Arg, true) andalso ifes_1(FVar, Body, Safe);
+ifes_1(FVar, #c_try{arg=Arg,handler=Handler,body=Body}, Safe) ->
+ ifes_1(FVar, Arg, false) andalso
+ ifes_1(FVar, Handler, Safe) andalso
+ ifes_1(FVar, Body, Safe);
+ifes_1(FVar, #c_tuple{es=Elements}, _Safe) ->
+ ifes_list(FVar, Elements, false);
+ifes_1(FVar, #c_values{es=Elements}, _Safe) ->
+ ifes_list(FVar, Elements, false);
+ifes_1(#c_var{name=Name}, #c_var{name=Name}, Safe) ->
+ %% It's safe to return FVar if it's unused.
+ Safe;
+ifes_1(_FVar, #c_var{}, _Safe) ->
+ true.
+
+ifes_list(FVar, [E|Es], Safe) ->
+ ifes_1(FVar, E, Safe) andalso ifes_list(FVar, Es, Safe);
+ifes_list(_FVar, [], _Safe) ->
+ true.
+
expr_list(Es, Ctxt, Sub) ->
[expr(E, Ctxt, Sub) || E <- Es].
@@ -479,6 +580,9 @@ bitstr_list(Es, Sub) ->
bitstr(#c_bitstr{val=Val,size=Size}=BinSeg, Sub) ->
BinSeg#c_bitstr{val=expr(Val, Sub),size=expr(Size, value, Sub)}.
+is_literal_fun(#c_literal{val=F}) -> is_function(F);
+is_literal_fun(_) -> false.
+
%% is_safe_simple(Expr, Sub) -> true | false.
%% A safe simple cannot fail with badarg and is safe to use
%% in a guard.
@@ -743,6 +847,25 @@ make_effect_seq([H|T], Sub) ->
end;
make_effect_seq([], _) -> void().
+%% fold_apply(Apply, LiteraFun, Args) -> Apply.
+%% Replace an apply of a literal external fun with a call.
+
+fold_apply(Apply, #c_literal{val=Fun}, Args) when is_function(Fun) ->
+ {module,Mod} = erlang:fun_info(Fun, module),
+ {name,Name} = erlang:fun_info(Fun, name),
+ {arity,Arity} = erlang:fun_info(Fun, arity),
+ if
+ Arity =:= length(Args) ->
+ #c_call{anno=Apply#c_apply.anno,
+ module=#c_literal{val=Mod},
+ name=#c_literal{val=Name},
+ args=Args};
+ true ->
+ Apply
+ end;
+fold_apply(Apply, _, _) -> Apply.
+
+
%% Handling remote calls. The module/name fields have been processed.
call(#c_call{args=As}=Call, #c_literal{val=M}=M0, #c_literal{val=N}=N0, Sub) ->
@@ -780,6 +903,8 @@ fold_call(Call, #c_literal{val=M}, #c_literal{val=F}, Args, Sub) ->
fold_call_1(Call, M, F, Args, Sub);
fold_call(Call, _M, _N, _Args, _Sub) -> Call.
+fold_call_1(Call, erlang, apply, [Fun,Args], _) ->
+ simplify_fun_apply(Call, Fun, Args);
fold_call_1(Call, erlang, apply, [Mod,Func,Args], _) ->
simplify_apply(Call, Mod, Func, Args);
fold_call_1(Call, Mod, Name, Args, Sub) ->
@@ -1088,24 +1213,38 @@ eval_failure(Call, Reason) ->
%% Simplify an apply/3 to a call if the number of arguments
%% are known at compile time.
-simplify_apply(Call, Mod, Func, Args) ->
+simplify_apply(Call, Mod, Func, Args0) ->
case is_atom_or_var(Mod) andalso is_atom_or_var(Func) of
- true -> simplify_apply_1(Args, Call, Mod, Func, []);
- false -> Call
+ true ->
+ case get_fixed_args(Args0, []) of
+ error ->
+ Call;
+ {ok,Args} ->
+ Call#c_call{module=Mod,name=Func,args=Args}
+ end;
+ false ->
+ Call
end.
-
-simplify_apply_1(#c_literal{val=MoreArgs0}, Call, Mod, Func, Args)
- when length(MoreArgs0) >= 0 ->
- MoreArgs = [#c_literal{val=Arg} || Arg <- MoreArgs0],
- Call#c_call{module=Mod,name=Func,args=reverse(Args, MoreArgs)};
-simplify_apply_1(#c_cons{hd=Arg,tl=T}, Call, Mod, Func, Args) ->
- simplify_apply_1(T, Call, Mod, Func, [Arg|Args]);
-simplify_apply_1(_, Call, _, _, _) -> Call.
-
is_atom_or_var(#c_literal{val=Atom}) when is_atom(Atom) -> true;
is_atom_or_var(#c_var{}) -> true;
is_atom_or_var(_) -> false.
+simplify_fun_apply(#c_call{anno=Anno}=Call, Fun, Args0) ->
+ case get_fixed_args(Args0, []) of
+ error ->
+ Call;
+ {ok,Args} ->
+ #c_apply{anno=Anno,op=Fun,args=Args}
+ end.
+
+get_fixed_args(#c_literal{val=MoreArgs0}, Args)
+ when length(MoreArgs0) >= 0 ->
+ MoreArgs = [#c_literal{val=Arg} || Arg <- MoreArgs0],
+ {ok,reverse(Args, MoreArgs)};
+get_fixed_args(#c_cons{hd=Arg,tl=T}, Args) ->
+ get_fixed_args(T, [Arg|Args]);
+get_fixed_args(_, _) -> error.
+
%% clause(Clause, Cepxr, Context, Sub) -> Clause.
clause(#c_clause{pats=Ps0}=Cl, Cexpr, Ctxt, Sub0) ->
@@ -1214,13 +1353,18 @@ let_subst_list([], [], _) -> {[],[],[]}.
%%pattern(Pat, Sub) -> pattern(Pat, Sub, Sub).
pattern(#c_var{}=Pat, Isub, Osub) ->
- case sub_is_val(Pat, Isub) of
+ case sub_is_in_scope(Pat, Isub) of
true ->
+ %% This variable either has a substitution or is used in
+ %% the variable list of an enclosing `let`. In either
+ %% case, it must be renamed to an unused name to avoid
+ %% name capture problems.
V1 = make_var_name(),
Pat1 = #c_var{name=V1},
{Pat1,sub_set_var(Pat, Pat1, sub_add_scope([V1], Osub))};
false ->
- {Pat,sub_del_var(Pat, Osub)}
+ %% This variable has never been used. Add it to the scope.
+ {Pat,sub_add_scope([Pat#c_var.name], Osub)}
end;
pattern(#c_literal{}=Pat, _, Osub) -> {Pat,Osub};
pattern(#c_cons{anno=Anno,hd=H0,tl=T0}, Isub, Osub0) ->
@@ -1399,8 +1543,8 @@ is_subst(_) -> false.
%% sub_set_name(Name, Value, #sub{}) -> #sub{}.
%% sub_del_var(Var, #sub{}) -> #sub{}.
%% sub_subst_var(Var, Value, #sub{}) -> [{Name,Value}].
-%% sub_is_val(Var, #sub{}) -> boolean().
-%% sub_add_scope(#sub{}) -> #sub{}
+%% sub_is_in_scope(Var, #sub{}) -> boolean().
+%% sub_add_scope([Var], #sub{}) -> #sub{}
%% sub_subst_scope(#sub{}) -> #sub{}
%%
%% We use the variable name as key so as not have problems with
@@ -1435,18 +1579,6 @@ sub_set_name(V, Val, #sub{v=S,s=Scope,t=Tdb0}=Sub) ->
Tdb = copy_type(V, Val, Tdb1),
Sub#sub{v=orddict:store(V, Val, S),s=cerl_sets:add_element(V, Scope),t=Tdb}.
-sub_del_var(#c_var{name=V}, #sub{v=S,s=Scope,t=Tdb}=Sub) ->
- %% Profiling shows that for programs with many record operations,
- %% sub_del_var/2 is a bottleneck. Since the scope contains all
- %% variables that are live, we know that V cannot be present in S
- %% if it is not in the scope.
- case cerl_sets:is_element(V, Scope) of
- false ->
- Sub#sub{s=cerl_sets:add_element(V, Scope)};
- true ->
- Sub#sub{v=orddict:erase(V, S),t=kill_types(V, Tdb)}
- end.
-
sub_subst_var(#c_var{name=V}, Val, #sub{v=S0}) ->
%% Fold chained substitutions.
[{V,Val}] ++ [ {K,Val} || {K,#c_var{name=V1}} <- S0, V1 =:= V].
@@ -1472,16 +1604,8 @@ sub_subst_scope_1([H|T], Key, Acc) ->
sub_subst_scope_1(T, Key-1, [{Key,#c_var{name=H}}|Acc]);
sub_subst_scope_1([], _, Acc) -> Acc.
-sub_is_val(#c_var{name=V}, #sub{v=S,s=Scope}) ->
- %% When the bottleneck in sub_del_var/2 was eliminated, this
- %% became the new bottleneck. Since the scope contains all
- %% live variables, a variable V can only be the target for
- %% a substitution if it is in the scope.
- cerl_sets:is_element(V, Scope) andalso v_is_value(V, S).
-
-v_is_value(Var, [{_,#c_var{name=Var}}|_]) -> true;
-v_is_value(Var, [_|T]) -> v_is_value(Var, T);
-v_is_value(_, []) -> false.
+sub_is_in_scope(#c_var{name=V}, #sub{s=Scope}) ->
+ cerl_sets:is_element(V, Scope).
%% warn_no_clause_match(CaseOrig, CaseOpt) -> ok
%% Generate a warning if none of the user-specified clauses
@@ -2146,7 +2270,7 @@ make_var(A) ->
make_var_name() ->
N = get(new_var_num),
put(new_var_num, N+1),
- list_to_atom("@f"++integer_to_list(N)).
+ N.
letify(Bs, Body) ->
Ann = cerl:get_ann(Body),
@@ -2422,16 +2546,10 @@ move_let_into_expr(#c_let{vars=InnerVs0,body=InnerBody0}=Inner,
Outer#c_let{vars=OuterVs,arg=Arg,
body=Inner#c_let{vars=InnerVs,arg=OuterBody,body=InnerBody}};
move_let_into_expr(#c_let{vars=Lvs0,body=Lbody0}=Let,
- #c_case{arg=Cexpr0,clauses=[Ca0,Cb0|Cs]}=Case, Sub0) ->
- %% Test if there are no more clauses than Ca0 and Cb0, or if
- %% Cb0 is guaranteed to match.
- TwoClauses = Cs =:= [] orelse
- case Cb0 of
- #c_clause{pats=[#c_var{}],guard=#c_literal{val=true}} -> true;
- _ -> false
- end,
- case {TwoClauses,is_failing_clause(Ca0),is_failing_clause(Cb0)} of
- {true,false,true} ->
+ #c_case{arg=Cexpr0,clauses=[Ca0|Cs0]}=Case, Sub0) ->
+ case not is_failing_clause(Ca0) andalso
+ are_all_failing_clauses(Cs0) of
+ true ->
%% let <Lvars> = case <Case-expr> of
%% <Cpats> -> <Clause-body>;
%% <OtherCpats> -> erlang:error(...)
@@ -2467,8 +2585,8 @@ move_let_into_expr(#c_let{vars=Lvs0,body=Lbody0}=Let,
body=Lbody},
Ca = Ca0#c_clause{pats=CaPats,guard=G,body=B},
- Cb = clause(Cb0, Cexpr, value, Sub0),
- Case#c_case{arg=Cexpr,clauses=[Ca,Cb]}
+ Cs = [clause(C, Cexpr, value, Sub0) || C <- Cs0],
+ Case#c_case{arg=Cexpr,clauses=[Ca|Cs]}
catch
nomatch ->
%% This is not a defeat. The code will eventually
@@ -2476,7 +2594,7 @@ move_let_into_expr(#c_let{vars=Lvs0,body=Lbody0}=Let,
%% optimizations done in this module.
impossible
end;
- {_,_,_} -> impossible
+ false -> impossible
end;
move_let_into_expr(#c_let{vars=Lvs0,body=Lbody0}=Let,
#c_seq{arg=Sarg0,body=Sbody0}=Seq, Sub0) ->
@@ -2499,9 +2617,78 @@ move_let_into_expr(#c_let{vars=Lvs0,body=Lbody0}=Let,
body=Lbody}};
move_let_into_expr(_Let, _Expr, _Sub) -> impossible.
+are_all_failing_clauses(Cs) ->
+ all(fun is_failing_clause/1, Cs).
+
is_failing_clause(#c_clause{body=B}) ->
will_fail(B).
+%% opt_build_stacktrace(Let) -> Core.
+%% If the stacktrace is *only* used in a call to erlang:raise/3,
+%% there is no need to build a cooked stackframe using build_stacktrace/1.
+
+opt_build_stacktrace(#c_let{vars=[#c_var{name=Cooked}],
+ arg=#c_primop{name=#c_literal{val=build_stacktrace},
+ args=[RawStk]},
+ body=Body}=Let) ->
+ case Body of
+ #c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=raise},
+ args=[Class,Exp,#c_var{name=Cooked}]} ->
+ %% The stacktrace is only used in a call to erlang:raise/3.
+ %% There is no need to build the stacktrace. Replace the
+ %% call to erlang:raise/3 with the the raw_raise/3 instruction,
+ %% which will use a raw stacktrace.
+ #c_primop{name=#c_literal{val=raw_raise},
+ args=[Class,Exp,RawStk]};
+ #c_let{vars=[#c_var{name=V}],arg=Arg,body=B0} when V =/= Cooked ->
+ case core_lib:is_var_used(Cooked, Arg) of
+ false ->
+ %% The built stacktrace is not used in the argument,
+ %% so we can sink the building of the stacktrace into
+ %% the body of the let.
+ B = opt_build_stacktrace(Let#c_let{body=B0}),
+ Body#c_let{body=B};
+ true ->
+ Let
+ end;
+ #c_seq{arg=Arg,body=B0} ->
+ case core_lib:is_var_used(Cooked, Arg) of
+ false ->
+ %% The built stacktrace is not used in the argument,
+ %% so we can sink the building of the stacktrace into
+ %% the body of the sequence.
+ B = opt_build_stacktrace(Let#c_let{body=B0}),
+ Body#c_seq{body=B};
+ true ->
+ Let
+ end;
+ #c_case{arg=Arg,clauses=Cs0} ->
+ case core_lib:is_var_used(Cooked, Arg) orelse
+ is_used_in_any_guard(Cooked, Cs0) of
+ false ->
+ %% The built stacktrace is not used in the argument,
+ %% so we can sink the building of the stacktrace into
+ %% each arm of the case.
+ Cs = [begin
+ B = opt_build_stacktrace(Let#c_let{body=B0}),
+ C#c_clause{body=B}
+ end || #c_clause{body=B0}=C <- Cs0],
+ Body#c_case{clauses=Cs};
+ true ->
+ Let
+ end;
+ _ ->
+ Let
+ end;
+opt_build_stacktrace(Expr) ->
+ Expr.
+
+is_used_in_any_guard(V, Cs) ->
+ any(fun(#c_clause{guard=G}) ->
+ core_lib:is_var_used(V, G)
+ end, Cs).
+
%% opt_case_in_let(Let) -> Let'
%% Try to avoid building tuples that are immediately matched.
%% A common pattern is:
@@ -2616,9 +2803,13 @@ delay_build_expr_1(#c_receive{clauses=Cs0,
timeout=Timeout,
action=A0}=Rec, TypeSig) ->
Cs = delay_build_cs(Cs0, TypeSig),
- A = case Timeout of
- #c_literal{val=infinity} -> A0;
- _ -> delay_build_expr(A0, TypeSig)
+ A = case {Timeout,A0} of
+ {#c_literal{val=infinity},#c_literal{}} ->
+ {_Type,Arity} = TypeSig,
+ Es = lists:duplicate(Arity, A0),
+ core_lib:make_values(Es);
+ _ ->
+ delay_build_expr(A0, TypeSig)
end,
Rec#c_receive{clauses=Cs,action=A};
delay_build_expr_1(#c_seq{body=B0}=Seq, TypeSig) ->
@@ -2653,53 +2844,94 @@ opt_simple_let_1(#c_let{vars=Vs0,body=B0}=Let, Arg0, Ctxt, Sub0) ->
%% Optimise let and add new substitutions.
{Vs,Args,Sub1} = let_substs(Vs0, Arg0, Sub0),
BodySub = update_let_types(Vs, Args, Sub1),
+ Sub = Sub1#sub{v=[],s=cerl_sets:new()},
B = body(B0, Ctxt, BodySub),
Arg = core_lib:make_values(Args),
- opt_simple_let_2(Let, Vs, Arg, B, B0, Ctxt, Sub1).
+ opt_simple_let_2(Let, Vs, Arg, B, B0, Sub).
+
-opt_simple_let_2(Let0, Vs0, Arg0, Body, PrevBody, Ctxt, Sub) ->
+%% opt_simple_let_2(Let0, Vs0, Arg0, Body, PrevBody, Ctxt, Sub) -> Core.
+%% Do final simplifications of the let.
+%%
+%% Note that the substitutions and scope in Sub have been cleared
+%% and should not be used.
+
+opt_simple_let_2(Let0, Vs0, Arg0, Body, PrevBody, Sub) ->
case {Vs0,Arg0,Body} of
- {[#c_var{name=N1}],Arg1,#c_var{name=N2}} ->
- case N1 =:= N2 of
- true ->
- %% let <Var> = Arg in <Var> ==> Arg
- Arg1;
- false ->
- %% let <Var> = Arg in <OtherVar> ==> seq Arg OtherVar
- Arg = maybe_suppress_warnings(Arg1, Vs0, PrevBody),
- #c_seq{arg=Arg,body=Body}
- end;
+ {[#c_var{name=V}],Arg1,#c_var{name=V}} ->
+ %% let <Var> = Arg in <Var> ==> Arg
+ Arg1;
{[],#c_values{es=[]},_} ->
%% No variables left.
Body;
- {Vs,Arg1,#c_literal{}} ->
- Arg = maybe_suppress_warnings(Arg1, Vs, PrevBody),
- case Ctxt of
- effect ->
- %% Throw away the literal body.
- Arg;
- value ->
- %% Since the variable is not used in the body, we
- %% can rewrite the let to a sequence.
- %% let <Var> = Arg in Literal ==> seq Arg Literal
- #c_seq{arg=Arg,body=Body}
- end;
- {Vs,Arg1,Body} ->
- %% If none of the variables are used in the body, we can
- %% rewrite the let to a sequence:
- %% let <Var> = Arg in BodyWithoutVar ==>
- %% seq Arg BodyWithoutVar
- case is_any_var_used(Vs, Body) of
- false ->
- Arg = maybe_suppress_warnings(Arg1, Vs, PrevBody),
- #c_seq{arg=Arg,body=Body};
- true ->
- Let1 = Let0#c_let{vars=Vs,arg=Arg1,body=Body},
- opt_bool_case_in_let(Let1, Sub)
+ {[#c_var{name=V}=Var|Vars]=Vars0,Arg1,Body} ->
+ case core_lib:is_var_used(V, Body) of
+ false when Vars =:= [] ->
+ %% If the variable is not used in the body, we can
+ %% rewrite the let to a sequence:
+ %% let <Var> = Arg in BodyWithoutVar ==>
+ %% seq Arg BodyWithoutVar
+ Arg = maybe_suppress_warnings(Arg1, Var, PrevBody),
+ #c_seq{arg=Arg,body=Body};
+ false ->
+ %% There are multiple values returned by the argument
+ %% and the first value is not used (this is a 'case'
+ %% with exported variables, but the return value is
+ %% ignored). We can remove the first variable and the
+ %% the first value returned from the 'let' argument.
+ Arg2 = remove_first_value(Arg1, Sub),
+ Let1 = Let0#c_let{vars=Vars,arg=Arg2,body=Body},
+ post_opt_let(Let1, Sub);
+ true ->
+ Let1 = Let0#c_let{vars=Vars0,arg=Arg1,body=Body},
+ post_opt_let(Let1, Sub)
end
end.
-%% maybe_suppress_warnings(Arg, [#c_var{}], PreviousBody) -> Arg'
+%% post_opt_let(Let, Sub)
+%% Final optimizations of the let.
+%%
+%% Note that the substitutions and scope in Sub have been cleared
+%% and should not be used.
+
+post_opt_let(Let0, Sub) ->
+ Let1 = opt_bool_case_in_let(Let0, Sub),
+ opt_build_stacktrace(Let1).
+
+
+%% remove_first_value(Core0, Sub) -> Core.
+%% Core0 is an expression that returns at least two values.
+%% Remove the first value returned from Core0.
+
+remove_first_value(#c_values{es=[V|Vs]}, Sub) ->
+ Values = core_lib:make_values(Vs),
+ case is_safe_simple(V, Sub) of
+ false ->
+ #c_seq{arg=V,body=Values};
+ true ->
+ Values
+ end;
+remove_first_value(#c_case{clauses=Cs0}=Core, Sub) ->
+ Cs = remove_first_value_cs(Cs0, Sub),
+ Core#c_case{clauses=Cs};
+remove_first_value(#c_receive{clauses=Cs0,action=Act0}=Core, Sub) ->
+ Cs = remove_first_value_cs(Cs0, Sub),
+ Act = remove_first_value(Act0, Sub),
+ Core#c_receive{clauses=Cs,action=Act};
+remove_first_value(#c_let{body=B}=Core, Sub) ->
+ Core#c_let{body=remove_first_value(B, Sub)};
+remove_first_value(#c_seq{body=B}=Core, Sub) ->
+ Core#c_seq{body=remove_first_value(B, Sub)};
+remove_first_value(#c_primop{}=Core, _Sub) ->
+ Core;
+remove_first_value(#c_call{}=Core, _Sub) ->
+ Core.
+
+remove_first_value_cs(Cs, Sub) ->
+ [C#c_clause{body=remove_first_value(B, Sub)} ||
+ #c_clause{body=B}=C <- Cs].
+
+%% maybe_suppress_warnings(Arg, #c_var{}, PreviousBody) -> Arg'
%% Try to suppress false warnings when a variable is not used.
%% For instance, we don't expect a warning for useless building in:
%%
@@ -2710,12 +2942,12 @@ opt_simple_let_2(Let0, Vs0, Arg0, Body, PrevBody, Ctxt, Sub) ->
%% referenced in the original unoptimized code. If they were, we will
%% consider the warning false and suppress it.
-maybe_suppress_warnings(Arg, Vs, PrevBody) ->
+maybe_suppress_warnings(Arg, #c_var{name=V}, PrevBody) ->
case should_suppress_warning(Arg) of
true ->
Arg; %Already suppressed.
false ->
- case is_any_var_used(Vs, PrevBody) of
+ case core_lib:is_var_used(V, PrevBody) of
true ->
suppress_warning([Arg]);
false ->
@@ -2804,7 +3036,7 @@ move_case_into_arg(#c_case{arg=#c_case{arg=OuterArg,
Outer#c_case{arg=OuterArg,
clauses=[OuterCa,OuterCb]};
false ->
- impossible
+ Inner0
end;
move_case_into_arg(#c_case{arg=#c_seq{arg=OuterArg,body=InnerArg}=Outer,
clauses=InnerClauses}=Inner, _Sub) ->
@@ -2820,15 +3052,8 @@ move_case_into_arg(#c_case{arg=#c_seq{arg=OuterArg,body=InnerArg}=Outer,
%%
Outer#c_seq{arg=OuterArg,
body=Inner#c_case{arg=InnerArg,clauses=InnerClauses}};
-move_case_into_arg(_, _) ->
- impossible.
-
-is_any_var_used([#c_var{name=V}|Vs], Expr) ->
- case core_lib:is_var_used(V, Expr) of
- false -> is_any_var_used(Vs, Expr);
- true -> true
- end;
-is_any_var_used([], _) -> false.
+move_case_into_arg(Expr, _) ->
+ Expr.
%%%
%%% Retrieving information about types.
diff --git a/lib/compiler/src/sys_core_inline.erl b/lib/compiler/src/sys_core_inline.erl
index 8c1f69d5de..5a6cc45e4a 100644
--- a/lib/compiler/src/sys_core_inline.erl
+++ b/lib/compiler/src/sys_core_inline.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -143,7 +143,7 @@ inline_inline(#ifun{body=B,weight=Iw}=If, Is) ->
case find_inl(F, A, Is) of
#ifun{vars=Vs,body=B2,weight=W} when W < Iw ->
#c_let{vars=Vs,
- arg=core_lib:make_values(As),
+ arg=kill_id_anns(core_lib:make_values(As)),
body=kill_id_anns(B2)};
_Other -> Call
end;
@@ -160,7 +160,7 @@ inline_func(#fstat{def={Name,F0}}=Fstat, Is) ->
case find_inl(F, A, Is) of
#ifun{vars=Vs,body=B} ->
{#c_let{vars=Vs,
- arg=core_lib:make_values(As),
+ arg=kill_id_anns(core_lib:make_values(As)),
body=kill_id_anns(B)},
true}; %Have modified
_Other -> {Call,Mod}
diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl
index 47c1567f10..e9152ba88f 100644
--- a/lib/compiler/src/v3_codegen.erl
+++ b/lib/compiler/src/v3_codegen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,25 +19,6 @@
%%
%% Purpose : Code generator for Beam.
-%% The following assumptions have been made:
-%%
-%% 1. Matches, i.e. things with {match,M,Ret} wrappers, only return
-%% values; no variables are exported. If the match would have returned
-%% extra variables then these have been transformed to multiple return
-%% values.
-%%
-%% 2. All BIF's called in guards are gc-safe so there is no need to
-%% put thing on the stack in the guard. While this would in principle
-%% work it would be difficult to keep track of the stack depth when
-%% trimming.
-%%
-%% The code generation uses variable lifetime information added by
-%% the v3_life module to save variables, allocate registers and
-%% move registers to the stack when necessary.
-%%
-%% We try to use a consistent variable name scheme throughout. The
-%% StackReg record is always called Bef,Int<n>,Aft.
-
-module(v3_codegen).
%% The main interface.
@@ -45,12 +26,14 @@
-import(lists, [member/2,keymember/3,keysort/2,keydelete/3,
append/1,flatmap/2,filter/2,foldl/3,foldr/3,mapfoldl/3,
- sort/1,reverse/1,reverse/2]).
--import(v3_life, [vdb_find/2]).
+ sort/1,reverse/1,reverse/2,map/2]).
+-import(ordsets, [add_element/2,intersection/2,union/2]).
-%%-compile([export_all]).
+-include("v3_kernel.hrl").
--include("v3_life.hrl").
+%% These are not defined in v3_kernel.hrl.
+get_kanno(Kthing) -> element(2, Kthing).
+set_kanno(Kthing, Anno) -> setelement(2, Kthing, Anno).
%% Main codegen structure.
-record(cg, {lcount=1, %Label counter
@@ -61,38 +44,400 @@
functable=#{}, %Map of local functions: {Name,Arity}=>Label
in_catch=false, %Inside a catch or not.
need_frame, %Need a stack frame.
- ultimate_failure %Label for ultimate match failure.
- }).
+ ultimate_failure, %Label for ultimate match failure.
+ ctx %Match context.
+ }).
%% Stack/register state record.
-record(sr, {reg=[], %Register table
stk=[], %Stack table
- res=[]}). %Reserved regs: [{reserved,I,V}]
+ res=[]}). %Registers to reserve
+
+%% Internal records.
+-record(cg_need_heap, {anno=[] :: term(),
+ h=0 :: integer()}).
+-record(cg_block, {anno=[] :: term(),
+ es=[] :: [term()]}).
--type life_module() :: {module(),_,_,[_]}.
+-type vdb_entry() :: {atom(),non_neg_integer(),non_neg_integer()}.
--spec module(life_module(), [compile:option()]) -> {'ok',beam_asm:module_code()}.
+-record(l, {i=0 :: non_neg_integer(), %Op number
+ vdb=[] :: [vdb_entry()], %Variable database
+ a=[] :: [term()]}). %Core annotation
-module({Mod,Exp,Attr,Forms}, _Options) ->
- {Fs,St} = functions(Forms, {atom,Mod}),
- {ok,{Mod,Exp,Attr,Fs,St#cg.lcount}}.
+-spec module(#k_mdef{}, [compile:option()]) -> {'ok',beam_asm:module_code()}.
+
+module(#k_mdef{name=Mod,exports=Es,attributes=Attr,body=Forms}, _Opts) ->
+ {Asm,St} = functions(Forms, {atom,Mod}),
+ {ok,{Mod,Es,Attr,Asm,St#cg.lcount}}.
functions(Forms, AtomMod) ->
mapfoldl(fun (F, St) -> function(F, AtomMod, St) end, #cg{lcount=1}, Forms).
-function({function,Name,Arity,Asm0,Vb,Vdb,Anno}, AtomMod, St0) ->
+function(#k_fdef{anno=#k{a=Anno},func=Name,arity=Arity,
+ vars=As,body=Kb}, AtomMod, St0) ->
+ try
+ #k_match{} = Kb, %Assertion.
+
+ %% Try to suppress the stack frame unless it is
+ %% really needed.
+ Body0 = avoid_stack_frame(Kb),
+
+ %% Annotate kernel records with variable usage.
+ Vdb0 = init_vars(As),
+ {Body,_,Vdb} = body(Body0, 1, Vdb0),
+
+ %% Generate the BEAM assembly code.
+ {Asm,EntryLabel,St} = cg_fun(Body, As, Vdb, AtomMod,
+ {Name,Arity}, Anno, St0),
+ Func = {function,Name,Arity,EntryLabel,Asm},
+ {Func,St}
+ catch
+ Class:Error:Stack ->
+ io:fwrite("Function: ~w/~w\n", [Name,Arity]),
+ erlang:raise(Class, Error, Stack)
+ end.
+
+
+%% avoid_stack_frame(Kernel) -> Kernel'
+%% If possible, avoid setting up a stack frame. Functions
+%% that only do matching, calls to guard BIFs, and tail-recursive
+%% calls don't need a stack frame.
+
+avoid_stack_frame(#k_match{body=Body}=M) ->
try
- {Asm,EntryLabel,St} = cg_fun(Vb, Asm0, Vdb, AtomMod,
- {Name,Arity}, Anno, St0),
- Func = {function,Name,Arity,EntryLabel,Asm},
- {Func,St}
+ M#k_match{body=avoid_stack_frame_1(Body)}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
- io:fwrite("Function: ~w/~w\n", [Name,Arity]),
- erlang:raise(Class, Error, Stack)
+ impossible ->
+ M
end.
+avoid_stack_frame_1(#k_alt{first=First0,then=Then0}=Alt) ->
+ First = avoid_stack_frame_1(First0),
+ Then = avoid_stack_frame_1(Then0),
+ Alt#k_alt{first=First,then=Then};
+avoid_stack_frame_1(#k_bif{op=Op}=Bif) ->
+ case Op of
+ #k_internal{} ->
+ %% Most internal BIFs clobber the X registers.
+ throw(impossible);
+ _ ->
+ Bif
+ end;
+avoid_stack_frame_1(#k_break{anno=Anno,args=Args}) ->
+ #k_guard_break{anno=Anno,args=Args};
+avoid_stack_frame_1(#k_guard_break{}=Break) ->
+ Break;
+avoid_stack_frame_1(#k_enter{}=Enter) ->
+ %% Tail-recursive calls don't need a stack frame.
+ Enter;
+avoid_stack_frame_1(#k_guard{clauses=Cs0}=Guard) ->
+ Cs = avoid_stack_frame_list(Cs0),
+ Guard#k_guard{clauses=Cs};
+avoid_stack_frame_1(#k_guard_clause{guard=G0,body=B0}=C) ->
+ G = avoid_stack_frame_1(G0),
+ B = avoid_stack_frame_1(B0),
+ C#k_guard_clause{guard=G,body=B};
+avoid_stack_frame_1(#k_match{anno=A,vars=Vs,body=B0,ret=Ret}) ->
+ %% Use #k_guard_match{} instead to avoid saving the X registers
+ %% to the stack before matching.
+ B = avoid_stack_frame_1(B0),
+ #k_guard_match{anno=A,vars=Vs,body=B,ret=Ret};
+avoid_stack_frame_1(#k_guard_match{body=B0}=M) ->
+ B = avoid_stack_frame_1(B0),
+ M#k_guard_match{body=B};
+avoid_stack_frame_1(#k_protected{arg=Arg0}=Prot) ->
+ Arg = avoid_stack_frame_1(Arg0),
+ Prot#k_protected{arg=Arg};
+avoid_stack_frame_1(#k_put{}=Put) ->
+ Put;
+avoid_stack_frame_1(#k_return{}=Ret) ->
+ Ret;
+avoid_stack_frame_1(#k_select{var=#k_var{anno=Vanno},types=Types0}=Select) ->
+ case member(reuse_for_context, Vanno) of
+ false ->
+ Types = avoid_stack_frame_list(Types0),
+ Select#k_select{types=Types};
+ true ->
+ %% Including binary patterns that overwrite the register containing
+ %% the binary with the match context may not be safe. For example,
+ %% bs_match_SUITE:bin_tail_e/1 with inlining will be rejected by
+ %% beam_validator.
+ %%
+ %% Essentially the following code is produced:
+ %%
+ %% bs_match {x,0} => {x,0}
+ %% ...
+ %% bs_match {x,0} => {x,1} %% ILLEGAL
+ %%
+ %% A bs_match instruction will only accept a match context as the
+ %% source operand if the source and destination registers are the
+ %% the same (as in the first bs_match instruction above).
+ %% The second bs_match instruction is therefore illegal.
+ %%
+ %% This situation is avoided if there is a stack frame:
+ %%
+ %% move {x,0} => {y,0}
+ %% bs_match {x,0} => {x,0}
+ %% ...
+ %% bs_match {y,0} => {x,1} %% LEGAL
+ %%
+ throw(impossible)
+ end;
+avoid_stack_frame_1(#k_seq{arg=#k_call{anno=Anno,op=Op}=Call,
+ body=#k_break{args=BrArgs0}}=Seq) ->
+ case Op of
+ #k_remote{mod=#k_atom{val=Mod},
+ name=#k_atom{val=Name},
+ arity=Arity} ->
+ case erl_bifs:is_exit_bif(Mod, Name, Arity) of
+ false ->
+ %% Will clobber X registers. Must have a stack frame.
+ throw(impossible);
+ true ->
+ %% The call to this BIF will never return. It is safe
+ %% to suppress the stack frame.
+ Bif = #k_bif{anno=Anno,
+ op=#k_internal{name=guard_error,arity=1},
+ args=[Call],ret=[]},
+ BrArgs = lists:duplicate(length(BrArgs0), #k_nil{}),
+ GB = #k_guard_break{anno=#k{us=[],ns=[],a=[]},args=BrArgs},
+ Seq#k_seq{arg=Bif,body=GB}
+ end;
+ _ ->
+ %% Will clobber X registers. Must have a stack frame.
+ throw(impossible)
+ end;
+avoid_stack_frame_1(#k_seq{arg=A0,body=B0}=Seq) ->
+ A = avoid_stack_frame_1(A0),
+ B = avoid_stack_frame_1(B0),
+ Seq#k_seq{arg=A,body=B};
+avoid_stack_frame_1(#k_test{}=Test) ->
+ Test;
+avoid_stack_frame_1(#k_type_clause{values=Values0}=TC) ->
+ Values = avoid_stack_frame_list(Values0),
+ TC#k_type_clause{values=Values};
+avoid_stack_frame_1(#k_val_clause{body=B0}=VC) ->
+ B = avoid_stack_frame_1(B0),
+ VC#k_val_clause{body=B};
+avoid_stack_frame_1(_Body) ->
+ throw(impossible).
+
+avoid_stack_frame_list([H|T]) ->
+ [avoid_stack_frame_1(H)|avoid_stack_frame_list(T)];
+avoid_stack_frame_list([]) -> [].
+
+
+%% This pass creates beam format annotated with variable lifetime
+%% information. Each thing is given an index and for each variable we
+%% store the first and last index for its occurrence. The variable
+%% database, VDB, attached to each thing is only relevant internally
+%% for that thing.
+%%
+%% For nested things like matches the numbering continues locally and
+%% the VDB for that thing refers to the variable usage within that
+%% thing. Variables which live through a such a thing are internally
+%% given a very large last index. Internally the indexes continue
+%% after the index of that thing. This creates no problems as the
+%% internal variable info never escapes and externally we only see
+%% variable which are alive both before or after.
+%%
+%% This means that variables never "escape" from a thing and the only
+%% way to get values from a thing is to "return" them, with 'break' or
+%% 'return'. Externally these values become the return values of the
+%% thing. This is no real limitation as most nested things have
+%% multiple threads so working out a common best variable usage is
+%% difficult.
+
+%% body(Kbody, I, Vdb) -> {[Expr],MaxI,Vdb}.
+%% Handle a body.
+
+body(#k_seq{arg=Ke,body=Kb}, I, Vdb0) ->
+ %%ok = io:fwrite("life ~w:~p~n", [?LINE,{Ke,I,Vdb0}]),
+ A = get_kanno(Ke),
+ Vdb1 = use_vars(union(A#k.us, A#k.ns), I, Vdb0),
+ {Es,MaxI,Vdb2} = body(Kb, I+1, Vdb1),
+ E = expr(Ke, I, Vdb2),
+ {[E|Es],MaxI,Vdb2};
+body(Ke, I, Vdb0) ->
+ %%ok = io:fwrite("life ~w:~p~n", [?LINE,{Ke,I,Vdb0}]),
+ A = get_kanno(Ke),
+ Vdb1 = use_vars(union(A#k.us, A#k.ns), I, Vdb0),
+ E = expr(Ke, I, Vdb1),
+ {[E],I,Vdb1}.
+
+%% expr(Kexpr, I, Vdb) -> Expr.
+
+expr(#k_test{anno=A}=Test, I, _Vdb) ->
+ Test#k_test{anno=#l{i=I,a=A#k.a}};
+expr(#k_call{anno=A}=Call, I, _Vdb) ->
+ Call#k_call{anno=#l{i=I,a=A#k.a}};
+expr(#k_enter{anno=A}=Enter, I, _Vdb) ->
+ Enter#k_enter{anno=#l{i=I,a=A#k.a}};
+expr(#k_bif{anno=A}=Bif, I, _Vdb) ->
+ Bif#k_bif{anno=#l{i=I,a=A#k.a}};
+expr(#k_match{anno=A,body=Kb,ret=Rs}, I, Vdb) ->
+ %% Work out imported variables which need to be locked.
+ Mdb = vdb_sub(I, I+1, Vdb),
+ M = match(Kb, A#k.us, I+1, Mdb),
+ L = #l{i=I,vdb=use_vars(A#k.us, I+1, Mdb),a=A#k.a},
+ #k_match{anno=L,body=M,ret=Rs};
+expr(#k_guard_match{anno=A,body=Kb,ret=Rs}, I, Vdb) ->
+ %% Work out imported variables which need to be locked.
+ Mdb = vdb_sub(I, I+1, Vdb),
+ M = match(Kb, A#k.us, I+1, Mdb),
+ L = #l{i=I,vdb=use_vars(A#k.us, I+1, Mdb),a=A#k.a},
+ #k_guard_match{anno=L,body=M,ret=Rs};
+expr(#k_protected{}=Protected, I, Vdb) ->
+ protected(Protected, I, Vdb);
+expr(#k_try{anno=A,arg=Ka,vars=Vs,body=Kb,evars=Evs,handler=Kh}=Try, I, Vdb) ->
+ %% Lock variables that are alive before the catch and used afterwards.
+ %% Don't lock variables that are only used inside the try.
+ Tdb0 = vdb_sub(I, I+1, Vdb),
+ %% This is the tricky bit. Lock variables in Arg that are used in
+ %% the body and handler. Add try tag 'variable'.
+ Ab = get_kanno(Kb),
+ Ah = get_kanno(Kh),
+ Tdb1 = use_vars(union(Ab#k.us, Ah#k.us), I+3, Tdb0),
+ Tdb2 = vdb_sub(I, I+2, Tdb1),
+ Vnames = fun (Kvar) -> Kvar#k_var.name end, %Get the variable names
+ {Aes,_,Adb} = body(Ka, I+2, add_var({catch_tag,I+1}, I+1, locked, Tdb2)),
+ {Bes,_,Bdb} = body(Kb, I+4, new_vars(sort(map(Vnames, Vs)), I+3, Tdb2)),
+ {Hes,_,Hdb} = body(Kh, I+4, new_vars(sort(map(Vnames, Evs)), I+3, Tdb2)),
+ L = #l{i=I,vdb=Tdb1,a=A#k.a},
+ Try#k_try{anno=L,
+ arg=#cg_block{es=Aes,anno=#l{i=I+1,vdb=Adb,a=[]}},
+ vars=Vs,body=#cg_block{es=Bes,anno=#l{i=I+3,vdb=Bdb,a=[]}},
+ evars=Evs,handler=#cg_block{es=Hes,anno=#l{i=I+3,vdb=Hdb,a=[]}}};
+expr(#k_try_enter{anno=A,arg=Ka,vars=Vs,body=Kb,evars=Evs,handler=Kh}, I, Vdb) ->
+ %% Lock variables that are alive before the catch and used afterwards.
+ %% Don't lock variables that are only used inside the try.
+ Tdb0 = vdb_sub(I, I+1, Vdb),
+ %% This is the tricky bit. Lock variables in Arg that are used in
+ %% the body and handler. Add try tag 'variable'.
+ Ab = get_kanno(Kb),
+ Ah = get_kanno(Kh),
+ Tdb1 = use_vars(union(Ab#k.us, Ah#k.us), I+3, Tdb0),
+ Tdb2 = vdb_sub(I, I+2, Tdb1),
+ Vnames = fun (Kvar) -> Kvar#k_var.name end, %Get the variable names
+ {Aes,_,Adb} = body(Ka, I+2, add_var({catch_tag,I+1}, I+1, 1000000, Tdb2)),
+ {Bes,_,Bdb} = body(Kb, I+4, new_vars(sort(map(Vnames, Vs)), I+3, Tdb2)),
+ {Hes,_,Hdb} = body(Kh, I+4, new_vars(sort(map(Vnames, Evs)), I+3, Tdb2)),
+ L = #l{i=I,vdb=Tdb1,a=A#k.a},
+ #k_try_enter{anno=L,
+ arg=#cg_block{es=Aes,anno=#l{i=I+1,vdb=Adb,a=[]}},
+ vars=Vs,body=#cg_block{es=Bes,anno=#l{i=I+3,vdb=Bdb,a=[]}},
+ evars=Evs,handler=#cg_block{es=Hes,anno=#l{i=I+3,vdb=Hdb,a=[]}}};
+expr(#k_catch{anno=A,body=Kb}=Catch, I, Vdb) ->
+ %% Lock variables that are alive before the catch and used afterwards.
+ %% Don't lock variables that are only used inside the catch.
+ %% Add catch tag 'variable'.
+ Cdb0 = vdb_sub(I, I+1, Vdb),
+ {Es,_,Cdb1} = body(Kb, I+1, add_var({catch_tag,I}, I, locked, Cdb0)),
+ L = #l{i=I,vdb=Cdb1,a=A#k.a},
+ Catch#k_catch{anno=L,body=#cg_block{es=Es}};
+expr(#k_receive{anno=A,var=V,body=Kb,action=Ka}=Recv, I, Vdb) ->
+ %% Work out imported variables which need to be locked.
+ Rdb = vdb_sub(I, I+1, Vdb),
+ M = match(Kb, add_element(V#k_var.name, A#k.us), I+1,
+ new_vars([V#k_var.name], I, Rdb)),
+ {Tes,_,Adb} = body(Ka, I+1, Rdb),
+ Le = #l{i=I,vdb=use_vars(A#k.us, I+1, Vdb),a=A#k.a},
+ Recv#k_receive{anno=Le,body=M,
+ action=#cg_block{anno=#l{i=I+1,vdb=Adb,a=[]},es=Tes}};
+expr(#k_receive_accept{anno=A}, I, _Vdb) ->
+ #k_receive_accept{anno=#l{i=I,a=A#k.a}};
+expr(#k_receive_next{anno=A}, I, _Vdb) ->
+ #k_receive_next{anno=#l{i=I,a=A#k.a}};
+expr(#k_put{anno=A}=Put, I, _Vdb) ->
+ Put#k_put{anno=#l{i=I,a=A#k.a}};
+expr(#k_break{anno=A}=Break, I, _Vdb) ->
+ Break#k_break{anno=#l{i=I,a=A#k.a}};
+expr(#k_guard_break{anno=A}=Break, I, _Vdb) ->
+ Break#k_guard_break{anno=#l{i=I,a=A#k.a}};
+expr(#k_return{anno=A}=Ret, I, _Vdb) ->
+ Ret#k_return{anno=#l{i=I,a=A#k.a}}.
+
+%% protected(Kprotected, I, Vdb) -> Protected.
+%% Only used in guards.
+
+protected(#k_protected{anno=A,arg=Ts}=Prot, I, Vdb) ->
+ %% Lock variables that are alive before try and used afterwards.
+ %% Don't lock variables that are only used inside the protected
+ %% expression.
+ Pdb0 = vdb_sub(I, I+1, Vdb),
+ {T,MaxI,Pdb1} = body(Ts, I+1, Pdb0),
+ Pdb2 = use_vars(A#k.ns, MaxI+1, Pdb1), %Save "return" values
+ Prot#k_protected{arg=T,anno=#l{i=I,a=A#k.a,vdb=Pdb2}}.
+
+%% match(Kexpr, [LockVar], I, Vdb) -> Expr.
+%% Convert match tree to old format.
+
+match(#k_alt{anno=A,first=Kf,then=Kt}, Ls, I, Vdb0) ->
+ Vdb1 = use_vars(union(A#k.us, Ls), I, Vdb0),
+ F = match(Kf, Ls, I+1, Vdb1),
+ T = match(Kt, Ls, I+1, Vdb1),
+ #k_alt{anno=[],first=F,then=T};
+match(#k_select{anno=A,types=Kts}=Select, Ls, I, Vdb0) ->
+ Vdb1 = use_vars(union(A#k.us, Ls), I, Vdb0),
+ Ts = [type_clause(Tc, Ls, I+1, Vdb1) || Tc <- Kts],
+ Select#k_select{anno=[],types=Ts};
+match(#k_guard{anno=A,clauses=Kcs}, Ls, I, Vdb0) ->
+ Vdb1 = use_vars(union(A#k.us, Ls), I, Vdb0),
+ Cs = [guard_clause(G, Ls, I+1, Vdb1) || G <- Kcs],
+ #k_guard{anno=[],clauses=Cs};
+match(Other, Ls, I, Vdb0) ->
+ Vdb1 = use_vars(Ls, I, Vdb0),
+ {B,_,Vdb2} = body(Other, I+1, Vdb1),
+ Le = #l{i=I,vdb=Vdb2,a=[]},
+ #cg_block{anno=Le,es=B}.
+
+type_clause(#k_type_clause{anno=A,type=T,values=Kvs}, Ls, I, Vdb0) ->
+ %%ok = io:format("life ~w: ~p~n", [?LINE,{T,Kvs}]),
+ Vdb1 = use_vars(union(A#k.us, Ls), I+1, Vdb0),
+ Vs = [val_clause(Vc, Ls, I+1, Vdb1) || Vc <- Kvs],
+ #k_type_clause{anno=[],type=T,values=Vs}.
+
+val_clause(#k_val_clause{anno=A,val=V,body=Kb}, Ls0, I, Vdb0) ->
+ New = (get_kanno(V))#k.ns,
+ Bus = (get_kanno(Kb))#k.us,
+ %%ok = io:format("Ls0 = ~p, Used=~p\n New=~p, Bus=~p\n", [Ls0,Used,New,Bus]),
+ Ls1 = union(intersection(New, Bus), Ls0), %Lock for safety
+ Vdb1 = use_vars(union(A#k.us, Ls1), I+1, new_vars(New, I, Vdb0)),
+ B = match(Kb, Ls1, I+1, Vdb1),
+ Le = #l{i=I,vdb=use_vars(Bus, I+1, Vdb1),a=A#k.a},
+ #k_val_clause{anno=Le,val=V,body=B}.
+
+guard_clause(#k_guard_clause{anno=A,guard=Kg,body=Kb}, Ls, I, Vdb0) ->
+ Vdb1 = use_vars(union(A#k.us, Ls), I+2, Vdb0),
+ Gdb = vdb_sub(I+1, I+2, Vdb1),
+ G = protected(Kg, I+1, Gdb),
+ B = match(Kb, Ls, I+2, Vdb1),
+ Le = #l{i=I,vdb=use_vars((get_kanno(Kg))#k.us, I+2, Vdb1),a=A#k.a},
+ #k_guard_clause{anno=Le,guard=G,body=B}.
+
+
+%% Here follows the code generator pass.
+%%
+%% The following assumptions have been made:
+%%
+%% 1. Matches, i.e. things with {match,M,Ret} wrappers, only return
+%% values; no variables are exported. If the match would have returned
+%% extra variables then these have been transformed to multiple return
+%% values.
+%%
+%% 2. All BIF's called in guards are gc-safe so there is no need to
+%% put thing on the stack in the guard. While this would in principle
+%% work it would be difficult to keep track of the stack depth when
+%% trimming.
+%%
+%% The code generation uses variable lifetime information added by
+%% the previous pass to save variables, allocate registers and
+%% move registers to the stack when necessary.
+%%
+%% We try to use a consistent variable name scheme throughout. The
+%% StackReg record is always called Bef,Int<n>,Aft.
+
%% cg_fun([Lkexpr], [HeadVar], Vdb, State) -> {[Ainstr],State}
cg_fun(Les, Hvs, Vdb, AtomMod, NameArity, Anno, St0) ->
@@ -114,18 +459,18 @@ cg_fun(Les, Hvs, Vdb, AtomMod, NameArity, Anno, St0) ->
%% Note that and 'if_end' instruction does not need any
%% live x registers, so it will always be safe to jump to
%% it. (We never ever expect the jump to be taken, and in
- %% must functions there will never be any references to
+ %% most functions there will never be any references to
%% the label in the first place.)
%%
{UltimateMatchFail,St3} = new_label(St2),
%% Create initial stack/register state, clear unused arguments.
- Bef = clear_dead(#sr{reg=foldl(fun ({var,V}, Reg) ->
+ Bef = clear_dead(#sr{reg=foldl(fun (#k_var{name=V}, Reg) ->
put_reg(V, Reg)
end, [], Hvs),
stk=[]}, 0, Vdb),
- {B,_Aft,St} = cg_list(Les, 0, Vdb, Bef,
+ {B,_Aft,St} = cg_list(Les, Vdb, Bef,
St3#cg{bfail=0,
ultimate_failure=UltimateMatchFail,
is_top_block=true}),
@@ -136,66 +481,64 @@ cg_fun(Les, Hvs, Vdb, AtomMod, NameArity, Anno, St0) ->
%% cg(Lkexpr, Vdb, StackReg, State) -> {[Ainstr],StackReg,State}.
%% Generate code for a kexpr.
-%% Split function into two steps for clarity, not efficiency.
-cg(Le, Vdb, Bef, St) ->
- cg(Le#l.ke, Le, Vdb, Bef, St).
-
-cg({block,Es}, Le, Vdb, Bef, St) ->
+cg(#cg_block{anno=Le,es=Es}, Vdb, Bef, St) ->
block_cg(Es, Le, Vdb, Bef, St);
-cg({match,M,Rs}, Le, Vdb, Bef, St) ->
+cg(#k_match{anno=Le,body=M,ret=Rs}, Vdb, Bef, St) ->
match_cg(M, Rs, Le, Vdb, Bef, St);
-cg({guard_match,M,Rs}, Le, Vdb, Bef, St) ->
+cg(#k_guard_match{anno=Le,body=M,ret=Rs}, Vdb, Bef, St) ->
guard_match_cg(M, Rs, Le, Vdb, Bef, St);
-cg({call,Func,As,Rs}, Le, Vdb, Bef, St) ->
+cg(#k_call{anno=Le,op=Func,args=As,ret=Rs}, Vdb, Bef, St) ->
call_cg(Func, As, Rs, Le, Vdb, Bef, St);
-cg({enter,Func,As}, Le, Vdb, Bef, St) ->
+cg(#k_enter{anno=Le,op=Func,args=As}, Vdb, Bef, St) ->
enter_cg(Func, As, Le, Vdb, Bef, St);
-cg({bif,Bif,As,Rs}, Le, Vdb, Bef, St) ->
- bif_cg(Bif, As, Rs, Le, Vdb, Bef, St);
-cg({gc_bif,Bif,As,Rs}, Le, Vdb, Bef, St) ->
- gc_bif_cg(Bif, As, Rs, Le, Vdb, Bef, St);
-cg({internal,Bif,As,Rs}, Le, Vdb, Bef, St) ->
- internal_cg(Bif, As, Rs, Le, Vdb, Bef, St);
-cg({receive_loop,Te,Rvar,Rm,Tes,Rs}, Le, Vdb, Bef, St) ->
+cg(#k_bif{anno=Le}=Bif, Vdb, Bef, St) ->
+ bif_cg(Bif, Le, Vdb, Bef, St);
+cg(#k_receive{anno=Le,timeout=Te,var=Rvar,body=Rm,action=Tes,ret=Rs},
+ Vdb, Bef, St) ->
recv_loop_cg(Te, Rvar, Rm, Tes, Rs, Le, Vdb, Bef, St);
-cg(receive_next, Le, Vdb, Bef, St) ->
+cg(#k_receive_next{anno=Le}, Vdb, Bef, St) ->
recv_next_cg(Le, Vdb, Bef, St);
-cg(receive_accept, _Le, _Vdb, Bef, St) -> {[remove_message],Bef,St};
-cg({'try',Ta,Vs,Tb,Evs,Th,Rs}, Le, Vdb, Bef, St) ->
+cg(#k_receive_accept{}, _Vdb, Bef, St) ->
+ {[remove_message],Bef,St};
+cg(#k_try{anno=Le,arg=Ta,vars=Vs,body=Tb,evars=Evs,handler=Th,ret=Rs},
+ Vdb, Bef, St) ->
try_cg(Ta, Vs, Tb, Evs, Th, Rs, Le, Vdb, Bef, St);
-cg({try_enter,Ta,Vs,Tb,Evs,Th}, Le, Vdb, Bef, St) ->
+cg(#k_try_enter{anno=Le,arg=Ta,vars=Vs,body=Tb,evars=Evs,handler=Th},
+ Vdb, Bef, St) ->
try_enter_cg(Ta, Vs, Tb, Evs, Th, Le, Vdb, Bef, St);
-cg({'catch',Cb,R}, Le, Vdb, Bef, St) ->
+cg(#k_catch{anno=Le,body=Cb,ret=[R]}, Vdb, Bef, St) ->
catch_cg(Cb, R, Le, Vdb, Bef, St);
-cg({set,Var,Con}, Le, Vdb, Bef, St) ->
- set_cg(Var, Con, Le, Vdb, Bef, St);
-cg({return,Rs}, Le, Vdb, Bef, St) -> return_cg(Rs, Le, Vdb, Bef, St);
-cg({break,Bs}, Le, Vdb, Bef, St) -> break_cg(Bs, Le, Vdb, Bef, St);
-cg({guard_break,Bs,N}, Le, Vdb, Bef, St) ->
- guard_break_cg(Bs, N, Le, Vdb, Bef, St);
-cg({need_heap,H}, _Le, _Vdb, Bef, St) ->
+cg(#k_put{anno=Le,arg=Con,ret=Var}, Vdb, Bef, St) ->
+ put_cg(Var, Con, Le, Vdb, Bef, St);
+cg(#k_return{anno=Le,args=Rs}, Vdb, Bef, St) ->
+ return_cg(Rs, Le, Vdb, Bef, St);
+cg(#k_break{anno=Le,args=Bs}, Vdb, Bef, St) ->
+ break_cg(Bs, Le, Vdb, Bef, St);
+cg(#k_guard_break{anno=Le,args=Bs}, Vdb, Bef, St) ->
+ guard_break_cg(Bs, Le, Vdb, Bef, St);
+cg(#cg_need_heap{h=H}, _Vdb, Bef, St) ->
{[{test_heap,H,max_reg(Bef#sr.reg)}],Bef,St}.
%% cg_list([Kexpr], FirstI, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
-cg_list(Kes, I, Vdb, Bef, St0) ->
+cg_list(Kes, Vdb, Bef, St0) ->
{Keis,{Aft,St1}} =
flatmapfoldl(fun (Ke, {Inta,Sta}) ->
{Keis,Intb,Stb} = cg(Ke, Vdb, Inta, Sta),
{Keis,{Intb,Stb}}
- end, {Bef,St0}, need_heap(Kes, I)),
+ end, {Bef,St0}, need_heap(Kes)),
{Keis,Aft,St1}.
%% need_heap([Lkexpr], I, St) -> [Lkexpr].
%% Insert need_heap instructions in Kexpr list. Try to be smart and
%% collect them together as much as possible.
-need_heap(Kes0, I) ->
+need_heap(Kes0) ->
{Kes,H} = need_heap_0(reverse(Kes0), 0, []),
%% Prepend need_heap if necessary.
- need_heap_need(I, H) ++ Kes.
+ need_heap_need(H) ++ Kes.
need_heap_0([Ke|Kes], H0, Acc) ->
{Ns,H} = need_heap_1(Ke, H0),
@@ -203,27 +546,56 @@ need_heap_0([Ke|Kes], H0, Acc) ->
need_heap_0([], H, Acc) ->
{Acc,H}.
-need_heap_1(#l{ke={set,_,{binary,_}},i=I}, H) ->
- {need_heap_need(I, H),0};
-need_heap_1(#l{ke={set,_,{map,_,_,_}},i=I}, H) ->
- {need_heap_need(I, H),0};
-need_heap_1(#l{ke={set,_,Val}}, H) ->
+need_heap_1(#k_put{arg=#k_binary{}}, H) ->
+ {need_heap_need(H),0};
+need_heap_1(#k_put{arg=#k_map{}}, H) ->
+ {need_heap_need(H),0};
+need_heap_1(#k_put{arg=Val}, H) ->
%% Just pass through adding to needed heap.
{[],H + case Val of
- {cons,_} -> 2;
- {tuple,Es} -> 1 + length(Es);
+ #k_cons{} -> 2;
+ #k_tuple{es=Es} -> 1 + length(Es);
_Other -> 0
end};
-need_heap_1(#l{ke={bif,_Bif,_As,_Rs}}, H) ->
- {[],H};
-need_heap_1(#l{i=I}, H) ->
+need_heap_1(#k_bif{}=Bif, H) ->
+ case is_gc_bif(Bif) of
+ false ->
+ {[],H};
+ true ->
+ {need_heap_need(H),0}
+ end;
+need_heap_1(_Ke, H) ->
%% Call or call-like instruction such as set_tuple_element/3.
- {need_heap_need(I, H),0}.
-
-need_heap_need(_I, 0) -> [];
-need_heap_need(I, H) -> [#l{ke={need_heap,H},i=I}].
-
-%% match_cg(Match, [Ret], Le, Vdb, StackReg, State) ->
+ {need_heap_need(H),0}.
+
+need_heap_need(0) -> [];
+need_heap_need(H) -> [#cg_need_heap{h=H}].
+
+%% is_gc_bif(#k_bif{}) -> true|false.
+%% is_gc_bif(Name, Arity) -> true|false.
+%% Determines whether the BIF Name/Arity might do a GC.
+
+is_gc_bif(#k_bif{op=#k_remote{name=#k_atom{val=Name}},args=Args}) ->
+ is_gc_bif(Name, length(Args));
+is_gc_bif(#k_bif{op=#k_internal{}}) ->
+ true.
+
+is_gc_bif(hd, 1) -> false;
+is_gc_bif(tl, 1) -> false;
+is_gc_bif(self, 0) -> false;
+is_gc_bif(node, 0) -> false;
+is_gc_bif(node, 1) -> false;
+is_gc_bif(element, 2) -> false;
+is_gc_bif(get, 1) -> false;
+is_gc_bif(tuple_size, 1) -> false;
+is_gc_bif(map_get, 2) -> false;
+is_gc_bif(is_map_key, 2) -> false;
+is_gc_bif(Bif, Arity) ->
+ not (erl_internal:bool_op(Bif, Arity) orelse
+ erl_internal:new_type_test(Bif, Arity) orelse
+ erl_internal:comp_op(Bif, Arity)).
+
+%% match_cg(Matc, [Ret], Le, Vdb, StackReg, State) ->
%% {[Ainstr],StackReg,State}.
%% Generate code for a match. First save all variables on the stack
%% that are to survive after the match. We leave saved variables in
@@ -244,7 +616,10 @@ match_cg(M, Rs, Le, Vdb, Bef, St0) ->
guard_match_cg(M, Rs, Le, Vdb, Bef, St0) ->
I = Le#l.i,
{B,St1} = new_label(St0),
- #cg{bfail=Fail} = St1,
+ Fail = case St0 of
+ #cg{bfail=0,ultimate_failure=Fail0} -> Fail0;
+ #cg{bfail=Fail0} -> Fail0
+ end,
{Mis,Aft,St2} = match_cg(M, Fail, Bef, St1#cg{break=B}),
%% Update the register descriptors for the return registers.
Reg = guard_match_regs(Aft#sr.reg, Rs),
@@ -252,7 +627,7 @@ guard_match_cg(M, Rs, Le, Vdb, Bef, St0) ->
clear_dead(Aft#sr{reg=Reg}, I, Vdb),
St2#cg{break=St1#cg.break}}.
-guard_match_regs([{I,gbreakvar}|Rs], [{var,V}|Vs]) ->
+guard_match_regs([{I,gbreakvar}|Rs], [#k_var{name=V}|Vs]) ->
[{I,V}|guard_match_regs(Rs, Vs)];
guard_match_regs([R|Rs], Vs) ->
[R|guard_match_regs(Rs, Vs)];
@@ -264,17 +639,14 @@ guard_match_regs([], []) -> [].
%% down as each level which uses this takes its own internal Vdb not
%% the outer one.
-match_cg(Le, Fail, Bef, St) ->
- match_cg(Le#l.ke, Le, Fail, Bef, St).
-
-match_cg({alt,F,S}, _Le, Fail, Bef, St0) ->
+match_cg(#k_alt{first=F,then=S}, Fail, Bef, St0) ->
{Tf,St1} = new_label(St0),
{Fis,Faft,St2} = match_cg(F, Tf, Bef, St1),
{Sis,Saft,St3} = match_cg(S, Fail, Bef, St2),
Aft = sr_merge(Faft, Saft),
{Fis ++ [{label,Tf}] ++ Sis,Aft,St3};
-match_cg({select,{var,Vname}=V,Scs0}, #l{a=Anno}, Fail, Bef, St) ->
- ReuseForContext = member(reuse_for_context, Anno) andalso
+match_cg(#k_select{var=#k_var{anno=Vanno,name=Vname}=V,types=Scs0}, Fail, Bef, St) ->
+ ReuseForContext = member(reuse_for_context, Vanno) andalso
find_reg(Vname, Bef#sr.reg) =/= error,
Scs = case ReuseForContext of
false -> Scs0;
@@ -283,10 +655,10 @@ match_cg({select,{var,Vname}=V,Scs0}, #l{a=Anno}, Fail, Bef, St) ->
match_fmf(fun (S, F, Sta) ->
select_cg(S, V, F, Fail, Bef, Sta) end,
Fail, St, Scs);
-match_cg({guard,Gcs}, _Le, Fail, Bef, St) ->
+match_cg(#k_guard{clauses=Gcs}, Fail, Bef, St) ->
match_fmf(fun (G, F, Sta) -> guard_clause_cg(G, F, Bef, Sta) end,
Fail, St, Gcs);
-match_cg({block,Es}, Le, _Fail, Bef, St) ->
+match_cg(#cg_block{anno=Le,es=Es}, _Fail, Bef, St) ->
%% Must clear registers and stack of dead variables.
Int = clear_dead(Bef, Le#l.i, Le#l.vdb),
block_cg(Es, Le, Int, St).
@@ -294,8 +666,8 @@ match_cg({block,Es}, Le, _Fail, Bef, St) ->
%% bsm_rename_ctx([Clause], Var) -> [Clause]
%% We know from an annotation that the register for a binary can
%% be reused for the match context because the two are not truly
-%% alive at the same time (even though the conservative life time
-%% information calculated by v3_life says so).
+%% alive at the same time (even though the life time information
+%% says so).
%%
%% The easiest way to have those variables share the same register is
%% to rename the variable with the shortest life-span (the match
@@ -306,12 +678,14 @@ match_cg({block,Es}, Le, _Fail, Bef, St) ->
%% We must also remove all information about the match context
%% variable from all life-time information databases (Vdb).
-bsm_rename_ctx([#l{ke={type_clause,binary,
- [#l{ke={val_clause,{binary,{var,Old}},Ke0}}=L2]}}=L1|Cs], New) ->
+bsm_rename_ctx([#k_type_clause{type=k_binary,values=Vcs}=TC|Cs], New) ->
+ [#k_val_clause{val=#k_binary{segs=#k_var{name=Old}}=Bin,
+ body=Ke0}=VC0] = Vcs,
Ke = bsm_rename_ctx(Ke0, Old, New, false),
- [L1#l{ke={type_clause,binary,
- [L2#l{ke={val_clause,{binary,{var,New}},Ke}}]}}|bsm_rename_ctx(Cs, New)];
-bsm_rename_ctx([C|Cs], New) ->
+ VC = VC0#k_val_clause{val=Bin#k_binary{segs=#k_var{name=New}},
+ body=Ke},
+ [TC#k_type_clause{values=[VC]}|bsm_rename_ctx(Cs, New)];
+bsm_rename_ctx([C|Cs], New) ->
[C|bsm_rename_ctx(Cs, New)];
bsm_rename_ctx([], _) -> [].
@@ -321,34 +695,24 @@ bsm_rename_ctx([], _) -> [].
%% only complicatate things to recurse into blocks not in a protected
%% (the match context variable is not live inside them).
-bsm_rename_ctx(#l{ke={select,{var,V},Cs0}}=L, Old, New, InProt) ->
+bsm_rename_ctx(#k_select{var=#k_var{name=V},types=Cs0}=Sel,
+ Old, New, InProt) ->
Cs = bsm_rename_ctx_list(Cs0, Old, New, InProt),
- L#l{ke={select,{var,bsm_rename_var(V, Old, New)},Cs}};
-bsm_rename_ctx(#l{ke={type_clause,Type,Cs0}}=L, Old, New, InProt) ->
+ Sel#k_select{var=#k_var{name=bsm_rename_var(V, Old, New)},types=Cs};
+bsm_rename_ctx(#k_type_clause{values=Cs0}=TC, Old, New, InProt) ->
Cs = bsm_rename_ctx_list(Cs0, Old, New, InProt),
- L#l{ke={type_clause,Type,Cs}};
-bsm_rename_ctx(#l{ke={val_clause,{bin_end,V},Ke0}}=L, Old, New, InProt) ->
+ TC#k_type_clause{values=Cs};
+bsm_rename_ctx(#k_val_clause{body=Ke0}=VC, Old, New, InProt) ->
Ke = bsm_rename_ctx(Ke0, Old, New, InProt),
- L#l{ke={val_clause,{bin_end,bsm_rename_var(V, Old, New)},Ke}};
-bsm_rename_ctx(#l{ke={val_clause,{bin_seg,V,Sz,U,Type,Fl,Vs},Ke0}}=L,
- Old, New, InProt) ->
- Ke = bsm_rename_ctx(Ke0, Old, New, InProt),
- L#l{ke={val_clause,{bin_seg,bsm_rename_var(V, Old, New),Sz,U,Type,Fl,Vs},Ke}};
-bsm_rename_ctx(#l{ke={val_clause,{bin_int,V,Sz,U,Fl,Val,Vs},Ke0}}=L,
- Old, New, InProt) ->
- Ke = bsm_rename_ctx(Ke0, Old, New, InProt),
- L#l{ke={val_clause,{bin_int,bsm_rename_var(V, Old, New),Sz,U,Fl,Val,Vs},Ke}};
-bsm_rename_ctx(#l{ke={val_clause,Val,Ke0}}=L, Old, New, InProt) ->
- Ke = bsm_rename_ctx(Ke0, Old, New, InProt),
- L#l{ke={val_clause,Val,Ke}};
-bsm_rename_ctx(#l{ke={alt,F0,S0}}=L, Old, New, InProt) ->
+ VC#k_val_clause{body=Ke};
+bsm_rename_ctx(#k_alt{first=F0,then=S0}=Alt, Old, New, InProt) ->
F = bsm_rename_ctx(F0, Old, New, InProt),
S = bsm_rename_ctx(S0, Old, New, InProt),
- L#l{ke={alt,F,S}};
-bsm_rename_ctx(#l{ke={guard,Gcs0}}=L, Old, New, InProt) ->
+ Alt#k_alt{first=F,then=S};
+bsm_rename_ctx(#k_guard{clauses=Gcs0}=Guard, Old, New, InProt) ->
Gcs = bsm_rename_ctx_list(Gcs0, Old, New, InProt),
- L#l{ke={guard,Gcs}};
-bsm_rename_ctx(#l{ke={guard_clause,G0,B0}}=L, Old, New, InProt) ->
+ Guard#k_guard{clauses=Gcs};
+bsm_rename_ctx(#k_guard_clause{guard=G0,body=B0}=GC, Old, New, InProt) ->
G = bsm_rename_ctx(G0, Old, New, InProt),
B = bsm_rename_ctx(B0, Old, New, InProt),
%% A guard clause may cause unsaved variables to be saved on the stack.
@@ -356,49 +720,45 @@ bsm_rename_ctx(#l{ke={guard_clause,G0,B0}}=L, Old, New, InProt) ->
%% same register), it is neither in the stack nor register descriptor
%% lists and we would crash when we didn't find it unless we remove
%% it from the database.
- bsm_forget_var(L#l{ke={guard_clause,G,B}}, Old);
-bsm_rename_ctx(#l{ke={protected,Ts0,Rs}}=L, Old, New, _InProt) ->
+ bsm_forget_var(GC#k_guard_clause{guard=G,body=B}, Old);
+bsm_rename_ctx(#k_protected{arg=Ts0}=Prot, Old, New, _InProt) ->
InProt = true,
Ts = bsm_rename_ctx_list(Ts0, Old, New, InProt),
- bsm_forget_var(L#l{ke={protected,Ts,Rs}}, Old);
-bsm_rename_ctx(#l{ke={match,Ms0,Rs}}=L, Old, New, InProt) ->
+ bsm_forget_var(Prot#k_protected{arg=Ts}, Old);
+bsm_rename_ctx(#k_guard_match{body=Ms0}=Match, Old, New, InProt) ->
Ms = bsm_rename_ctx(Ms0, Old, New, InProt),
- L#l{ke={match,Ms,Rs}};
-bsm_rename_ctx(#l{ke={guard_match,Ms0,Rs}}=L, Old, New, InProt) ->
- Ms = bsm_rename_ctx(Ms0, Old, New, InProt),
- L#l{ke={guard_match,Ms,Rs}};
-bsm_rename_ctx(#l{ke={test,_,_,_}}=L, _, _, _) -> L;
-bsm_rename_ctx(#l{ke={bif,_,_,_}}=L, _, _, _) -> L;
-bsm_rename_ctx(#l{ke={gc_bif,_,_,_}}=L, _, _, _) -> L;
-bsm_rename_ctx(#l{ke={set,_,_}}=L, _, _, _) -> L;
-bsm_rename_ctx(#l{ke={call,_,_,_}}=L, _, _, _) -> L;
-bsm_rename_ctx(#l{ke={block,_}}=L, Old, _, false) ->
+ Match#k_guard_match{body=Ms};
+bsm_rename_ctx(#k_test{}=Test, _, _, _) -> Test;
+bsm_rename_ctx(#k_bif{}=Bif, _, _, _) -> Bif;
+bsm_rename_ctx(#k_put{}=Put, _, _, _) -> Put;
+bsm_rename_ctx(#k_call{}=Call, _, _, _) -> Call;
+bsm_rename_ctx(#cg_block{}=Block, Old, _, false) ->
%% This block is not inside a protected. The match context variable cannot
%% possibly be live inside the block.
- bsm_forget_var(L, Old);
-bsm_rename_ctx(#l{ke={block,Bl0}}=L, Old, New, true) ->
+ bsm_forget_var(Block, Old);
+bsm_rename_ctx(#cg_block{es=Es0}=Block, Old, New, true) ->
%% A block in a protected. We must recursively rename the variable
%% inside the block.
- Bl = bsm_rename_ctx_list(Bl0, Old, New, true),
- bsm_forget_var(L#l{ke={block,Bl}}, Old);
-bsm_rename_ctx(#l{ke={guard_break,Bs,Locked0}}=L0, Old, _New, _InProt) ->
- Locked = Locked0 -- [Old],
- L = L0#l{ke={guard_break,Bs,Locked}},
- bsm_forget_var(L, Old).
+ Es = bsm_rename_ctx_list(Es0, Old, New, true),
+ bsm_forget_var(Block#cg_block{es=Es}, Old);
+bsm_rename_ctx(#k_guard_break{}=Break, Old, _New, _InProt) ->
+ bsm_forget_var(Break, Old).
bsm_rename_ctx_list([C|Cs], Old, New, InProt) ->
[bsm_rename_ctx(C, Old, New, InProt)|
bsm_rename_ctx_list(Cs, Old, New, InProt)];
bsm_rename_ctx_list([], _, _, _) -> [].
-
+
bsm_rename_var(Old, Old, New) -> New;
bsm_rename_var(V, _, _) -> V.
%% bsm_forget_var(#l{}, Variable) -> #l{}
%% Remove a variable from the variable life-time database.
-bsm_forget_var(#l{vdb=Vdb}=L, V) ->
- L#l{vdb=keydelete(V, 1, Vdb)}.
+bsm_forget_var(Ke, V) ->
+ #l{vdb=Vdb} = L0 = get_kanno(Ke),
+ L = L0#l{vdb=keydelete(V, 1, Vdb)},
+ set_kanno(Ke, L).
%% block_cg([Kexpr], Le, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
%% block_cg([Kexpr], Le, StackReg, St) -> {[Ainstr],StackReg,St}.
@@ -407,158 +767,227 @@ block_cg(Es, Le, _Vdb, Bef, St) ->
block_cg(Es, Le, Bef, St).
block_cg(Es, Le, Bef, #cg{is_top_block=false}=St) ->
- cg_block(Es, Le#l.i, Le#l.vdb, Bef, St);
-block_cg(Es, Le, Bef, St0) ->
- {Is0,Aft,St} = cg_block(Es, Le#l.i, Le#l.vdb, Bef,
- St0#cg{is_top_block=false,need_frame=false}),
- Is = top_level_block(Is0, Aft, max_reg(Bef#sr.reg), St),
- {Is,Aft,St#cg{is_top_block=true}}.
-
-cg_block([], _I, _Vdb, Bef, St0) ->
+ cg_block(Es, Le#l.vdb, Bef, St);
+block_cg(Es, Le, Bef, #cg{is_top_block=true}=St0) ->
+ %% No stack frame has been established yet. Do we need one?
+ case need_stackframe(Es) of
+ true ->
+ %% We need a stack frame. Generate the code and add the
+ %% code for creating and deallocating the stack frame.
+ {Is0,Aft,St} = cg_block(Es, Le#l.vdb, Bef,
+ St0#cg{is_top_block=false,need_frame=false}),
+ Is = top_level_block(Is0, Aft, max_reg(Bef#sr.reg), St),
+ {Is,Aft,St#cg{is_top_block=true}};
+ false ->
+ %% This sequence of instructions ending in a #k_match{} (a
+ %% 'case' or 'if') in the Erlang code does not need a
+ %% stack frame yet. Delay the creation (if a stack frame
+ %% is needed at all, it will be created inside the
+ %% #k_match{}).
+ cg_list(Es, Le#l.vdb, Bef, St0)
+ end.
+
+%% need_stackframe([Kexpr]) -> true|false.
+%% Does this list of instructions need a stack frame?
+%%
+%% A sequence of instructions that don't clobber the X registers
+%% followed by a single #k_match{} doesn't need a stack frame.
+
+need_stackframe([H|T]) ->
+ case H of
+ #k_bif{op=#k_internal{}} -> true;
+ #k_put{arg=#k_binary{}} -> true;
+ #k_bif{} -> need_stackframe(T);
+ #k_put{} -> need_stackframe(T);
+ #k_guard_match{} -> need_stackframe(T);
+ #k_match{} when T =:= [] -> false;
+ _ -> true
+ end;
+need_stackframe([]) -> false.
+
+cg_block([], _Vdb, Bef, St0) ->
{[],Bef,St0};
-cg_block(Kes0, I, Vdb, Bef, St0) ->
+cg_block(Kes0, Vdb, Bef, St0) ->
{Kes2,Int1,St1} =
case basic_block(Kes0) of
{Kes1,LastI,Args,Rest} ->
- Ke = hd(Kes1),
- Fb = Ke#l.i,
- cg_basic_block(Kes1, Fb, LastI, Args, Vdb, Bef, St0);
+ cg_basic_block(Kes1, LastI, Args, Vdb, Bef, St0);
{Kes1,Rest} ->
- cg_list(Kes1, I, Vdb, Bef, St0)
+ cg_list(Kes1, Vdb, Bef, St0)
end,
- {Kes3,Int2,St2} = cg_block(Rest, I, Vdb, Int1, St1),
+ {Kes3,Int2,St2} = cg_block(Rest, Vdb, Int1, St1),
{Kes2 ++ Kes3,Int2,St2}.
basic_block(Kes) -> basic_block(Kes, []).
-basic_block([Le|Les], Acc) ->
- case collect_block(Le#l.ke) of
- include -> basic_block(Les, [Le|Acc]);
+basic_block([Ke|Kes], Acc) ->
+ case collect_block(Ke) of
+ include -> basic_block(Kes, [Ke|Acc]);
{block_end,As} ->
case Acc of
[] ->
- %% If the basic block does not contain any set instructions,
+ %% If the basic block does not contain any #k_put{} instructions,
%% it serves no useful purpose to do basic block optimizations.
- {[Le],Les};
+ {[Ke],Kes};
_ ->
- {reverse(Acc, [Le]),Le#l.i,As,Les}
+ #l{i=I} = get_kanno(Ke),
+ {reverse(Acc, [Ke]),I,As,Kes}
end;
- no_block -> {reverse(Acc, [Le]),Les}
+ no_block -> {reverse(Acc, [Ke]),Kes}
end.
-%% sets that may garbage collect are not allowed in basic blocks.
-
-collect_block({set,_,{binary,_}}) -> no_block;
-collect_block({set,_,{map,_,_,_}}) -> no_block;
-collect_block({set,_,_}) -> include;
-collect_block({call,{var,_}=Var,As,_Rs}) -> {block_end,As++[Var]};
-collect_block({call,Func,As,_Rs}) -> {block_end,As++func_vars(Func)};
-collect_block({enter,{var,_}=Var,As})-> {block_end,As++[Var]};
-collect_block({enter,Func,As}) -> {block_end,As++func_vars(Func)};
-collect_block({return,Rs}) -> {block_end,Rs};
-collect_block({break,Bs}) -> {block_end,Bs};
-collect_block(_) -> no_block.
-
-func_vars({remote,M,F}) when element(1, M) =:= var;
- element(1, F) =:= var ->
+collect_block(#k_put{arg=Arg}) ->
+ %% #k_put{} instructions that may garbage collect are not allowed
+ %% in basic blocks.
+ case Arg of
+ #k_binary{} -> no_block;
+ #k_map{} -> no_block;
+ _ -> include
+ end;
+collect_block(#k_call{op=Func,args=As}) ->
+ {block_end,As++func_vars(Func)};
+collect_block(#k_enter{op=Func,args=As}) ->
+ {block_end,As++func_vars(Func)};
+collect_block(#k_return{args=Rs}) ->
+ {block_end,Rs};
+collect_block(#k_break{args=Bs}) ->
+ {block_end,Bs};
+collect_block(_) -> no_block.
+
+func_vars(#k_var{}=Var) ->
+ [Var];
+func_vars(#k_remote{mod=M,name=F})
+ when is_record(M, k_var); is_record(F, k_var) ->
[M,F];
func_vars(_) -> [].
-%% cg_basic_block([Kexpr], FirstI, LastI, As, Vdb, StackReg, State) ->
+%% cg_basic_block([Kexpr], FirstI, LastI, Arguments, Vdb, StackReg, State) ->
%% {[Ainstr],StackReg,State}.
-
-cg_basic_block(Kes, Fb, Lf, As, Vdb, Bef, St0) ->
- Res = make_reservation(As, 0),
- Regs0 = reserve(Res, Bef#sr.reg, Bef#sr.stk),
- Stk = extend_stack(Bef, Lf, Lf+1, Vdb),
- Int0 = Bef#sr{reg=Regs0,stk=Stk,res=Res},
- X0_v0 = x0_vars(As, Fb, Lf, Vdb),
- {Keis,{Aft,_,St1}} =
+%%
+%% Do a specialized code generation for a basic block of #put{}
+%% instructions (that don't do any garbage collection) followed by a
+%% call, break, or return.
+%%
+%% 'Arguments' is a list of the variables that must be loaded into
+%% consecutive X registers before the last instruction in the block.
+%% The point of this specialized code generation is to try put the
+%% all of the variables in 'Arguments' into the correct X register
+%% to begin with, instead of putting them into the first available
+%% X register and having to move them to the correct X register
+%% later.
+%%
+%% To achieve that, we attempt to reserve the X registers that the
+%% variables in 'Arguments' will need to be in when the block ends.
+%%
+%% To make it more likely that reservations will be successful, we
+%% will try to save variables that need to be saved to the stack as
+%% early as possible (if an X register needed by a variable in
+%% Arguments is occupied by another variable, the value in the
+%% X register can be evicted if it is saved on the stack).
+%%
+%% We will take care not to increase the size of stack frame compared
+%% to what the standard code generator would have done (that is, to
+%% save all X registers at the last possible moment). We will do that
+%% by extending the stack frame to the minimal size needed to save
+%% all that needs to be saved using extend_stack/4, and use
+%% save_carefully/4 during code generation to only save the variables
+%% that can be saved without growing the stack frame.
+
+cg_basic_block(Kes, Lf, As, Vdb, Bef, St0) ->
+ Int0 = reserve_arg_regs(As, Bef),
+ Int = extend_stack(Int0, Lf, Lf+1, Vdb),
+ {Keis,{Aft,St1}} =
flatmapfoldl(fun(Ke, St) -> cg_basic_block(Ke, St, Lf, Vdb) end,
- {Int0,X0_v0,St0}, need_heap(Kes, Fb)),
+ {Int,St0}, need_heap(Kes)),
{Keis,Aft,St1}.
-cg_basic_block(#l{ke={need_heap,_}}=Ke, {Inta,X0v,Sta}, _Lf, Vdb) ->
- {Keis,Intb,Stb} = cg(Ke, Vdb, Inta, Sta),
- {Keis, {Intb,X0v,Stb}};
-cg_basic_block(Ke, {Inta,X0_v1,Sta}, Lf, Vdb) ->
- {Sis,Intb} = save_carefully(Inta, Ke#l.i, Lf+1, Vdb),
- {X0_v2,Intc} = allocate_x0(X0_v1, Ke#l.i, Intb),
- Intd = reserve(Intc),
- {Keis,Inte,Stb} = cg(Ke, Vdb, Intd, Sta),
- {Sis ++ Keis, {Inte,X0_v2,Stb}}.
-
-make_reservation([], _) -> [];
-make_reservation([{var,V}|As], I) -> [{I,V}|make_reservation(As, I+1)];
-make_reservation([A|As], I) -> [{I,A}|make_reservation(As, I+1)].
-
-reserve(Sr) -> Sr#sr{reg=reserve(Sr#sr.res, Sr#sr.reg, Sr#sr.stk)}.
-
-reserve([{I,V}|Rs], [free|Regs], Stk) -> [{reserved,I,V}|reserve(Rs, Regs, Stk)];
-reserve([{I,V}|Rs], [{I,V}|Regs], Stk) -> [{I,V}|reserve(Rs, Regs, Stk)];
-reserve([{I,V}|Rs], [{I,Var}|Regs], Stk) ->
+cg_basic_block(#cg_need_heap{}=Ke, {Bef,St0}, _Lf, Vdb) ->
+ {Keis,Aft,St1} = cg(Ke, Vdb, Bef, St0),
+ {Keis,{Aft,St1}};
+cg_basic_block(Ke, {Bef,St0}, Lf, Vdb) ->
+ #l{i=I} = get_kanno(Ke),
+
+ %% Save all we can to increase the possibility that reserving
+ %% registers will succeed.
+ {Sis,Int0} = save_carefully(Bef, I, Lf+1, Vdb),
+ Int1 = reserve(Int0),
+ {Keis,Aft,St1} = cg(Ke, Vdb, Int1, St0),
+ {Sis ++ Keis,{Aft,St1}}.
+
+%% reserve_arg_regs([Argument], Bef) -> Aft.
+%% Try to reserve the X registers for all arguments. All registers
+%% that we wish to reserve will be saved in Bef#sr.res.
+
+reserve_arg_regs(As, Bef) ->
+ Res = reserve_arg_regs_1(As, 0),
+ reserve(Bef#sr{res=Res}).
+
+reserve_arg_regs_1([#k_var{name=V}|As], I) ->
+ [{I,V}|reserve_arg_regs_1(As, I+1)];
+reserve_arg_regs_1([A|As], I) ->
+ [{I,A}|reserve_arg_regs_1(As, I+1)];
+reserve_arg_regs_1([], _) -> [].
+
+%% reserve(Bef) -> Aft.
+%% Try to reserve more registers. The registers we wish to reserve
+%% are found in Bef#sr.res.
+
+reserve(#sr{reg=Regs,stk=Stk,res=Res}=Sr) ->
+ Sr#sr{reg=reserve_1(Res, Regs, Stk)}.
+
+reserve_1([{I,V}|Rs], [free|Regs], Stk) ->
+ [{reserved,I,V}|reserve_1(Rs, Regs, Stk)];
+reserve_1([{I,V}|Rs], [{I,V}|Regs], Stk) ->
+ [{I,V}|reserve_1(Rs, Regs, Stk)];
+reserve_1([{I,V}|Rs], [{I,Var}|Regs], Stk) ->
case on_stack(Var, Stk) of
- true -> [{reserved,I,V}|reserve(Rs, Regs, Stk)];
- false -> [{I,Var}|reserve(Rs, Regs, Stk)]
+ true -> [{reserved,I,V}|reserve_1(Rs, Regs, Stk)];
+ false -> [{I,Var}|reserve_1(Rs, Regs, Stk)]
end;
-reserve([{I,V}|Rs], [{reserved,I,_}|Regs], Stk) ->
- [{reserved,I,V}|reserve(Rs, Regs, Stk)];
-%reserve([{I,V}|Rs], [Other|Regs], Stk) -> [Other|reserve(Rs, Regs, Stk)];
-reserve([{I,V}|Rs], [], Stk) -> [{reserved,I,V}|reserve(Rs, [], Stk)];
-reserve([], Regs, _) -> Regs.
-
-extend_stack(Bef, Fb, Lf, Vdb) ->
- Stk0 = clear_dead_stk(Bef#sr.stk, Fb, Vdb),
- Saves = [V || {V,F,L} <- Vdb,
- F < Fb,
- L >= Lf,
- not on_stack(V, Stk0)],
- Stk1 = foldl(fun (V, Stk) -> put_stack(V, Stk) end, Stk0, Saves),
- Bef#sr.stk ++ lists:duplicate(length(Stk1) - length(Bef#sr.stk), free).
-
-save_carefully(Bef, Fb, Lf, Vdb) ->
- Stk = Bef#sr.stk,
- %% New variables that are in use but not on stack.
- New = [VFL || {V,F,L} = VFL <- Vdb,
- F < Fb,
- L >= Lf,
- not on_stack(V, Stk)],
- Saves = [V || {V,_,_} <- keysort(2, New)],
- save_carefully(Saves, Bef, []).
-
-save_carefully([], Bef, Acc) -> {reverse(Acc),Bef};
-save_carefully([V|Vs], Bef, Acc) ->
- case put_stack_carefully(V, Bef#sr.stk) of
- error -> {reverse(Acc),Bef};
+reserve_1([{I,V}|Rs], [{reserved,I,_}|Regs], Stk) ->
+ [{reserved,I,V}|reserve_1(Rs, Regs, Stk)];
+reserve_1([{I,V}|Rs], [], Stk) ->
+ [{reserved,I,V}|reserve_1(Rs, [], Stk)];
+reserve_1([], Regs, _) -> Regs.
+
+%% extend_stack(Bef, FirstBefore, LastFrom, Vdb) -> Aft.
+%% Extend the stack enough to fit all variables alive past LastFrom
+%% and not already on the stack.
+
+extend_stack(#sr{stk=Stk0}=Bef, Fb, Lf, Vdb) ->
+ Stk1 = clear_dead_stk(Stk0, Fb, Vdb),
+ New = new_not_on_stack(Stk1, Fb, Lf, Vdb),
+ Stk2 = foldl(fun ({V,_,_}, Stk) -> put_stack(V, Stk) end, Stk1, New),
+ Stk = Stk0 ++ lists:duplicate(length(Stk2) - length(Stk0), free),
+ Bef#sr{stk=Stk}.
+
+%% save_carefully(Bef, FirstBefore, LastFrom, Vdb) -> {[SaveVar],Aft}.
+%% Save variables which are used past current point and which are not
+%% already on the stack, but only if the variables can be saved without
+%% growing the stack frame.
+
+save_carefully(#sr{stk=Stk}=Bef, Fb, Lf, Vdb) ->
+ New0 = new_not_on_stack(Stk, Fb, Lf, Vdb),
+ New = keysort(2, New0),
+ save_carefully_1(New, Bef, []).
+
+save_carefully_1([{V,_,_}|Vs], #sr{reg=Regs,stk=Stk0}=Bef, Acc) ->
+ case put_stack_carefully(V, Stk0) of
+ error ->
+ {reverse(Acc),Bef};
Stk1 ->
- SrcReg = fetch_reg(V, Bef#sr.reg),
+ SrcReg = fetch_reg(V, Regs),
Move = {move,SrcReg,fetch_stack(V, Stk1)},
{x,_} = SrcReg, %Assertion - must be X register.
- save_carefully(Vs, Bef#sr{stk=Stk1}, [Move|Acc])
- end.
+ save_carefully_1(Vs, Bef#sr{stk=Stk1}, [Move|Acc])
+ end;
+save_carefully_1([], Bef, Acc) ->
+ {reverse(Acc),Bef}.
-x0_vars([], _Fb, _Lf, _Vdb) -> [];
-x0_vars([{var,V}|_], Fb, _Lf, Vdb) ->
- {V,F,_L} = VFL = vdb_find(V, Vdb),
- x0_vars1([VFL], Fb, F, Vdb);
-x0_vars([X0|_], Fb, Lf, Vdb) ->
- x0_vars1([{X0,Lf,Lf}], Fb, Lf, Vdb).
-
-x0_vars1(X0, Fb, Xf, Vdb) ->
- Vs0 = [VFL || {_V,F,L}=VFL <- Vdb,
- F >= Fb,
- L < Xf],
- Vs1 = keysort(3, Vs0),
- keysort(2, X0++Vs1).
-
-allocate_x0([], _, Bef) -> {[],Bef#sr{res=[]}};
-allocate_x0([{_,_,L}|Vs], I, Bef) when L =< I ->
- allocate_x0(Vs, I, Bef);
-allocate_x0([{V,_F,_L}=VFL|Vs], _, Bef) ->
- {[VFL|Vs],Bef#sr{res=reserve_x0(V, Bef#sr.res)}}.
-
-reserve_x0(V, [_|Res]) -> [{0,V}|Res];
-reserve_x0(V, []) -> [{0,V}].
+%% top_level_block([Instruction], Bef, MaxRegs, St) -> [Instruction].
+%% For the top-level block, allocate a stack frame a necessary,
+%% adjust Y register numbering and instructions that return
+%% from the function.
top_level_block(Keis, #sr{stk=[]}, _MaxRegs, #cg{need_frame=false}) ->
Keis;
@@ -640,21 +1069,27 @@ turn_yreg(Other, _MaxY) ->
%% wrong. These are different as in the second case there is no need
%% to try the next type, it will always fail.
-select_cg(#l{ke={type_clause,cons,[S]}}, {var,V}, Tf, Vf, Bef, St) ->
+select_cg(#k_type_clause{type=Type,values=Vs}, Var, Tf, Vf, Bef, St) ->
+ #k_var{name=V} = Var,
+ select_cg(Type, Vs, V, Tf, Vf, Bef, St).
+
+select_cg(k_cons, [S], V, Tf, Vf, Bef, St) ->
select_cons(S, V, Tf, Vf, Bef, St);
-select_cg(#l{ke={type_clause,nil,[S]}}, {var,V}, Tf, Vf, Bef, St) ->
+select_cg(k_nil, [S], V, Tf, Vf, Bef, St) ->
select_nil(S, V, Tf, Vf, Bef, St);
-select_cg(#l{ke={type_clause,binary,[S]}}, {var,V}, Tf, Vf, Bef, St) ->
+select_cg(k_binary, [S], V, Tf, Vf, Bef, St) ->
select_binary(S, V, Tf, Vf, Bef, St);
-select_cg(#l{ke={type_clause,bin_seg,S}}, {var,V}, Tf, _Vf, Bef, St) ->
+select_cg(k_bin_seg, S, V, Tf, _Vf, Bef, St) ->
select_bin_segs(S, V, Tf, Bef, St);
-select_cg(#l{ke={type_clause,bin_int,S}}, {var,V}, Tf, _Vf, Bef, St) ->
+select_cg(k_bin_int, S, V, Tf, _Vf, Bef, St) ->
select_bin_segs(S, V, Tf, Bef, St);
-select_cg(#l{ke={type_clause,bin_end,[S]}}, {var,V}, Tf, _Vf, Bef, St) ->
+select_cg(k_bin_end, [S], V, Tf, _Vf, Bef, St) ->
select_bin_end(S, V, Tf, Bef, St);
-select_cg(#l{ke={type_clause,map,S}}, {var,V}, Tf, Vf, Bef, St) ->
+select_cg(k_map, S, V, Tf, Vf, Bef, St) ->
select_map(S, V, Tf, Vf, Bef, St);
-select_cg(#l{ke={type_clause,Type,Scs}}, {var,V}, Tf, Vf, Bef, St0) ->
+select_cg(k_literal, S, V, Tf, Vf, Bef, St) ->
+ select_literal(S, V, Tf, Vf, Bef, St);
+select_cg(Type, Scs, V, Tf, Vf, Bef, St0) ->
{Vis,{Aft,St1}} =
mapfoldl(fun (S, {Int,Sta}) ->
{Val,Is,Inta,Stb} = select_val(S, V, Vf, Bef, Sta),
@@ -664,22 +1099,29 @@ select_cg(#l{ke={type_clause,Type,Scs}}, {var,V}, Tf, Vf, Bef, St0) ->
{Vls,Sis,St2} = select_labels(OptVls, St1, [], []),
{select_val_cg(Type, fetch_var(V, Bef), Vls, Tf, Vf, Sis), Aft, St2}.
-select_val_cg(tuple, R, [Arity,{f,Lbl}], Tf, Vf, [{label,Lbl}|Sis]) ->
+select_val_cg(k_tuple, R, [Arity,{f,Lbl}], Tf, Vf, [{label,Lbl}|Sis]) ->
[{test,is_tuple,{f,Tf},[R]},{test,test_arity,{f,Vf},[R,Arity]}|Sis];
-select_val_cg(tuple, R, Vls, Tf, Vf, Sis) ->
+select_val_cg(k_tuple, R, Vls, Tf, Vf, Sis) ->
[{test,is_tuple,{f,Tf},[R]},{select_tuple_arity,R,{f,Vf},{list,Vls}}|Sis];
select_val_cg(Type, R, [Val, {f,Lbl}], Fail, Fail, [{label,Lbl}|Sis]) ->
- [{test,is_eq_exact,{f,Fail},[R,{Type,Val}]}|Sis];
+ [{test,is_eq_exact,{f,Fail},[R,{type(Type),Val}]}|Sis];
select_val_cg(Type, R, [Val, {f,Lbl}], Tf, Vf, [{label,Lbl}|Sis]) ->
[{test,select_type_test(Type),{f,Tf},[R]},
- {test,is_eq_exact,{f,Vf},[R,{Type,Val}]}|Sis];
+ {test,is_eq_exact,{f,Vf},[R,{type(Type),Val}]}|Sis];
select_val_cg(Type, R, Vls0, Tf, Vf, Sis) ->
- Vls1 = [case Value of {f,_Lbl} -> Value; _ -> {Type,Value} end || Value <- Vls0],
+ Vls1 = [case Value of
+ {f,_Lbl} -> Value;
+ _ -> {type(Type),Value}
+ end || Value <- Vls0],
[{test,select_type_test(Type),{f,Tf},[R]}, {select_val,R,{f,Vf},{list,Vls1}}|Sis].
-
-select_type_test(integer) -> is_integer;
-select_type_test(atom) -> is_atom;
-select_type_test(float) -> is_float.
+
+type(k_atom) -> atom;
+type(k_float) -> float;
+type(k_int) -> integer.
+
+select_type_test(k_int) -> is_integer;
+select_type_test(k_atom) -> is_atom;
+select_type_test(k_float) -> is_float.
combine([{Is,Vs1}, {Is,Vs2}|Vis]) -> combine([{Is,Vs1 ++ Vs2}|Vis]);
combine([V|Vis]) -> [V|combine(Vis)];
@@ -695,36 +1137,50 @@ add_vls([V|Vs], Lbl, Acc) ->
add_vls(Vs, Lbl, [V, {f,Lbl}|Acc]);
add_vls([], _, Acc) -> Acc.
-select_cons(#l{ke={val_clause,{cons,Es},B},i=I,vdb=Vdb}, V, Tf, Vf, Bef, St0) ->
+select_literal(S, V, Tf, Vf, Bef, St) ->
+ Reg = fetch_var(V, Bef),
+ F = fun(ValClause, Fail, St0) ->
+ {Val,Is,Aft,St1} = select_val(ValClause, V, Vf, Bef, St0),
+ Test = {test,is_eq_exact,{f,Fail},[Reg,{literal,Val}]},
+ {[Test|Is],Aft,St1}
+ end,
+ match_fmf(F, Tf, St, S).
+
+select_cons(#k_val_clause{val=#k_cons{hd=Hd,tl=Tl},body=B,anno=#l{i=I,vdb=Vdb}},
+ V, Tf, Vf, Bef, St0) ->
+ Es = [Hd,Tl],
{Eis,Int,St1} = select_extract_cons(V, Es, I, Vdb, Bef, St0),
{Bis,Aft,St2} = match_cg(B, Vf, Int, St1),
{[{test,is_nonempty_list,{f,Tf},[fetch_var(V, Bef)]}] ++ Eis ++ Bis,Aft,St2}.
-select_nil(#l{ke={val_clause,nil,B}}, V, Tf, Vf, Bef, St0) ->
+select_nil(#k_val_clause{val=#k_nil{},body=B}, V, Tf, Vf, Bef, St0) ->
{Bis,Aft,St1} = match_cg(B, Vf, Bef, St0),
{[{test,is_nil,{f,Tf},[fetch_var(V, Bef)]}] ++ Bis,Aft,St1}.
-select_binary(#l{ke={val_clause,{binary,{var,V}},B},i=I,vdb=Vdb},
- V, Tf, Vf, Bef, St0) ->
+select_binary(#k_val_clause{val=#k_binary{segs=#k_var{name=V}},body=B,
+ anno=#l{i=I,vdb=Vdb}}, V, Tf, Vf, Bef, St0) ->
+ #cg{ctx=OldCtx} = St0,
Int0 = clear_dead(Bef#sr{reg=Bef#sr.reg}, I, Vdb),
- {Bis0,Aft,St1} = match_cg(B, Vf, Int0, St0),
+ {Bis0,Aft,St1} = match_cg(B, Vf, Int0, St0#cg{ctx=V}),
CtxReg = fetch_var(V, Int0),
Live = max_reg(Bef#sr.reg),
- Bis1 = [{test,bs_start_match2,{f,Tf},Live,[CtxReg,V],CtxReg},
+ Bis1 = [{test,bs_start_match2,{f,Tf},Live,[CtxReg,{context,V}],CtxReg},
{bs_save2,CtxReg,{V,V}}|Bis0],
Bis = finish_select_binary(Bis1),
- {Bis,Aft,St1};
-select_binary(#l{ke={val_clause,{binary,{var,Ivar}},B},i=I,vdb=Vdb},
- V, Tf, Vf, Bef, St0) ->
+ {Bis,Aft,St1#cg{ctx=OldCtx}};
+select_binary(#k_val_clause{val=#k_binary{segs=#k_var{name=Ivar}},body=B,
+ anno=#l{i=I,vdb=Vdb}}, V, Tf, Vf, Bef, St0) ->
+ #cg{ctx=OldCtx} = St0,
Regs = put_reg(Ivar, Bef#sr.reg),
Int0 = clear_dead(Bef#sr{reg=Regs}, I, Vdb),
- {Bis0,Aft,St1} = match_cg(B, Vf, Int0, St0),
+ {Bis0,Aft,St1} = match_cg(B, Vf, Int0, St0#cg{ctx=Ivar}),
CtxReg = fetch_var(Ivar, Int0),
Live = max_reg(Bef#sr.reg),
- Bis1 = [{test,bs_start_match2,{f,Tf},Live,[fetch_var(V, Bef),Ivar],CtxReg},
+ Bis1 = [{test,bs_start_match2,{f,Tf},Live,
+ [fetch_var(V, Bef),{context,Ivar}],CtxReg},
{bs_save2,CtxReg,{Ivar,Ivar}}|Bis0],
Bis = finish_select_binary(Bis1),
- {Bis,Aft,St1}.
+ {Bis,Aft,St1#cg{ctx=OldCtx}}.
finish_select_binary([{bs_save2,R,Point}=I,{bs_restore2,R,Point}|Is]) ->
[I|finish_select_binary(Is)];
@@ -746,9 +1202,16 @@ select_bin_segs(Scs, Ivar, Tf, Bef, St) ->
select_bin_seg(S, Ivar, Fail, Bef, Sta) end,
Tf, St, Scs).
-select_bin_seg(#l{ke={val_clause,{bin_seg,Ctx,Size,U,T,Fs0,Es},B},i=I,vdb=Vdb,a=A},
- Ivar, Fail, Bef, St0) ->
+select_bin_seg(#k_val_clause{val=#k_bin_seg{size=Size,unit=U,type=T,
+ seg=Seg,flags=Fs0,next=Next},
+ body=B,
+ anno=#l{i=I,vdb=Vdb,a=A}}, Ivar, Fail, Bef, St0) ->
+ Ctx = St0#cg.ctx,
Fs = [{anno,A}|Fs0],
+ Es = case Next of
+ [] -> [Seg];
+ _ -> [Seg,Next]
+ end,
{Mis,Int,St1} = select_extract_bin(Es, Size, U, T, Fs, Fail,
I, Vdb, Bef, Ctx, B, St0),
{Bis,Aft,St2} = match_cg(B, Fail, Int, St1),
@@ -761,9 +1224,12 @@ select_bin_seg(#l{ke={val_clause,{bin_seg,Ctx,Size,U,T,Fs0,Es},B},i=I,vdb=Vdb,a=
[{bs_restore2,CtxReg,{Ctx,Ivar}}|Mis++Bis]
end,
{Is,Aft,St2};
-select_bin_seg(#l{ke={val_clause,{bin_int,Ctx,Sz,U,Fs,Val,Es},B},i=I,vdb=Vdb},
- Ivar, Fail, Bef, St0) ->
- {Mis,Int,St1} = select_extract_int(Es, Val, Sz, U, Fs, Fail,
+select_bin_seg(#k_val_clause{val=#k_bin_int{size=Sz,unit=U,flags=Fs,
+ val=Val,next=Next},
+ body=B,
+ anno=#l{i=I,vdb=Vdb}}, Ivar, Fail, Bef, St0) ->
+ Ctx = St0#cg.ctx,
+ {Mis,Int,St1} = select_extract_int(Next, Val, Sz, U, Fs, Fail,
I, Vdb, Bef, Ctx, St0),
{Bis,Aft,St2} = match_cg(B, Fail, Int, St1),
CtxReg = fetch_var(Ctx, Bef),
@@ -784,7 +1250,7 @@ select_bin_seg(#l{ke={val_clause,{bin_int,Ctx,Sz,U,Fs,Val,Es},B},i=I,vdb=Vdb},
end,
{[{bs_restore2,CtxReg,{Ctx,Ivar}}|Is],Aft,St2}.
-select_extract_int([{var,Tl}], Val, {integer,Sz}, U, Fs, Vf,
+select_extract_int(#k_var{name=Tl}, Val, #k_int{val=Sz}, U, Fs, Vf,
I, Vdb, Bef, Ctx, St) ->
Bits = U*Sz,
Bin = case member(big, Fs) of
@@ -805,7 +1271,7 @@ select_extract_int([{var,Tl}], Val, {integer,Sz}, U, Fs, Vf,
end,
{Is,clear_dead(Bef, I, Vdb),St}.
-select_extract_bin([{var,Hd},{var,Tl}], Size0, Unit, Type, Flags, Vf,
+select_extract_bin([#k_var{name=Hd},#k_var{name=Tl}], Size0, Unit, Type, Flags, Vf,
I, Vdb, Bef, Ctx, _Body, St) ->
SizeReg = get_bin_size_reg(Size0, Bef),
{Es,Aft} =
@@ -828,11 +1294,11 @@ select_extract_bin([{var,Hd},{var,Tl}], Size0, Unit, Type, Flags, Vf,
{bs_save2,CtxReg,{Ctx,Tl}}],Int1}
end,
{Es,clear_dead(Aft, I, Vdb),St};
-select_extract_bin([{var,Hd}], Size, Unit, binary, Flags, Vf,
+select_extract_bin([#k_var{name=Hd}], Size, Unit, binary, Flags, Vf,
I, Vdb, Bef, Ctx, Body, St) ->
%% Match the last segment of a binary. We KNOW that the size
%% must be 'all'.
- Size = {atom,all}, %Assertion.
+ #k_atom{val=all} = Size, %Assertion.
{Es,Aft} =
case vdb_find(Hd, Vdb) of
{_,_,Lhd} when Lhd =< I ->
@@ -857,7 +1323,7 @@ select_extract_bin([{var,Hd}], Size, Unit, binary, Flags, Vf,
Name = bs_get_binary2,
Live = max_reg(Bef#sr.reg),
{[{test,Name,{f,Vf},Live,
- [CtxReg,Size,Unit,{field_flags,Flags}],Rhd}],
+ [CtxReg,atomic(Size),Unit,{field_flags,Flags}],Rhd}],
Int1};
true ->
%% Since the matching context will not be used again,
@@ -872,36 +1338,42 @@ select_extract_bin([{var,Hd}], Size, Unit, binary, Flags, Vf,
Name = bs_get_binary2,
Live = max_reg(Int1#sr.reg),
{[{test,Name,{f,Vf},Live,
- [CtxReg,Size,Unit,{field_flags,Flags}],CtxReg}],
+ [CtxReg,atomic(Size),Unit,{field_flags,Flags}],CtxReg}],
Int1}
end
end,
{Es,clear_dead(Aft, I, Vdb),St}.
%% is_context_unused(Ke) -> true | false
-%% Simple heurististic to determine whether the code that follows will
-%% use the current matching context again. (The information of liveness
-%% calculcated by v3_life is too conservative to be useful for this purpose.)
-%% 'true' means that the code that follows will definitely not use the context
-%% again (because it is a block, not guard or matching code); 'false' that we
-%% are not sure (there is either a guard, or more matching, either which may
-%% reference the context again).
-
-is_context_unused(#l{ke=Ke}) -> is_context_unused(Ke);
-is_context_unused({block,_}) -> true;
-is_context_unused(_) -> false.
-
-select_bin_end(#l{ke={val_clause,{bin_end,Ctx},B}},
- Ivar, Tf, Bef, St0) ->
+%% Simple heurististic to determine whether the code that follows
+%% will use the current matching context again. (The liveness
+%% information is too conservative to be useful for this purpose.)
+%% 'true' means that the code that follows will definitely not use
+%% the context again (because it is a block, not guard or matching
+%% code); 'false' that we are not sure (there could be more
+%% matching).
+
+is_context_unused(#k_alt{then=Then}) ->
+ %% #k_alt{} can be used for different purposes. If the Then part
+ %% is a block, it means that matching has finished and is used for a guard
+ %% to choose between the matched clauses.
+ is_context_unused(Then);
+is_context_unused(#cg_block{}) ->
+ true;
+is_context_unused(_) ->
+ false.
+
+select_bin_end(#k_val_clause{val=#k_bin_end{},body=B}, Ivar, Tf, Bef, St0) ->
+ Ctx = St0#cg.ctx,
{Bis,Aft,St2} = match_cg(B, Tf, Bef, St0),
CtxReg = fetch_var(Ctx, Bef),
{[{bs_restore2,CtxReg,{Ctx,Ivar}},
{test,bs_test_tail2,{f,Tf},[CtxReg,0]}|Bis],Aft,St2}.
-get_bin_size_reg({var,V}, Bef) ->
+get_bin_size_reg(#k_var{name=V}, Bef) ->
fetch_var(V, Bef);
get_bin_size_reg(Literal, _Bef) ->
- Literal.
+ atomic(Literal).
build_bs_instr(Type, Vf, CtxReg, Live, SizeReg, Unit, Flags, Rhd) ->
{Format,Name} = case Type of
@@ -935,11 +1407,18 @@ build_skip_instr(Type, Vf, CtxReg, Live, SizeReg, Unit, Flags) ->
{test,Name,{f,Vf},[CtxReg,Live,{field_flags,Flags}]}
end.
-select_val(#l{ke={val_clause,{tuple,Es},B},i=I,vdb=Vdb}, V, Vf, Bef, St0) ->
+select_val(#k_val_clause{val=#k_tuple{es=Es},body=B,anno=#l{i=I,vdb=Vdb}},
+ V, Vf, Bef, St0) ->
{Eis,Int,St1} = select_extract_tuple(V, Es, I, Vdb, Bef, St0),
{Bis,Aft,St2} = match_cg(B, Vf, Int, St1),
{length(Es),Eis ++ Bis,Aft,St2};
-select_val(#l{ke={val_clause,{_,Val},B}}, _V, Vf, Bef, St0) ->
+select_val(#k_val_clause{val=Val0,body=B}, _V, Vf, Bef, St0) ->
+ Val = case Val0 of
+ #k_atom{val=Lit} -> Lit;
+ #k_float{val=Lit} -> Lit;
+ #k_int{val=Lit} -> Lit;
+ #k_literal{val=Lit} -> Lit
+ end,
{Bis,Aft,St1} = match_cg(B, Vf, Bef, St0),
{Val,Bis,Aft,St1}.
@@ -948,7 +1427,7 @@ select_val(#l{ke={val_clause,{_,Val},B}}, _V, Vf, Bef, St0) ->
%% Extract tuple elements, but only if they do not immediately die.
select_extract_tuple(Src, Vs, I, Vdb, Bef, St) ->
- F = fun ({var,V}, {Int0,Elem}) ->
+ F = fun (#k_var{name=V}, {Int0,Elem}) ->
case vdb_find(V, Vdb) of
{V,_,L} when L =< I -> {[], {Int0,Elem+1}};
_Other ->
@@ -965,9 +1444,10 @@ select_extract_tuple(Src, Vs, I, Vdb, Bef, St) ->
select_map(Scs, V, Tf, Vf, Bef, St0) ->
Reg = fetch_var(V, Bef),
{Is,Aft,St1} =
- match_fmf(fun(#l{ke={val_clause,{map,exact,_,Es},B},i=I,vdb=Vdb}, Fail, St1) ->
- select_map_val(V, Es, B, Fail, I, Vdb, Bef, St1)
- end, Vf, St0, Scs),
+ match_fmf(fun(#k_val_clause{val=#k_map{op=exact,es=Es},
+ body=B,anno=#l{i=I,vdb=Vdb}}, Fail, St1) ->
+ select_map_val(V, Es, B, Fail, I, Vdb, Bef, St1)
+ end, Vf, St0, Scs),
{[{test,is_map,{f,Tf},[Reg]}|Is],Aft,St1}.
select_map_val(V, Es, B, Fail, I, Vdb, Bef, St0) ->
@@ -984,29 +1464,32 @@ select_extract_map(Src, Vs, Fail, I, Vdb, Bef, St) ->
%% Assume keys are term-sorted
Rsrc = fetch_var(Src, Bef),
- {{HasKs,GetVs,HasVarKs,GetVarVs},Aft} = lists:foldr(fun
- ({map_pair,{var,K},{var,V}},{{HasKsi,GetVsi,HasVarVsi,GetVarVsi},Int0}) ->
- case vdb_find(V, Vdb) of
- {V,_,L} when L =< I ->
- RK = fetch_var(K,Int0),
- {{HasKsi,GetVsi,[RK|HasVarVsi],GetVarVsi},Int0};
- _Other ->
- Reg1 = put_reg(V, Int0#sr.reg),
- Int1 = Int0#sr{reg=Reg1},
- RK = fetch_var(K,Int0),
- RV = fetch_reg(V,Reg1),
- {{HasKsi,GetVsi,HasVarVsi,[[RK,RV]|GetVarVsi]},Int1}
- end;
- ({map_pair,Key,{var,V}},{{HasKsi,GetVsi,HasVarVsi,GetVarVsi},Int0}) ->
- case vdb_find(V, Vdb) of
- {V,_,L} when L =< I ->
- {{[Key|HasKsi],GetVsi,HasVarVsi,GetVarVsi},Int0};
- _Other ->
- Reg1 = put_reg(V, Int0#sr.reg),
- Int1 = Int0#sr{reg=Reg1},
- {{HasKsi,[Key,fetch_reg(V, Reg1)|GetVsi],HasVarVsi,GetVarVsi},Int1}
- end
- end, {{[],[],[],[]},Bef}, Vs),
+ {{HasKs,GetVs,HasVarKs,GetVarVs},Aft} =
+ foldr(fun(#k_map_pair{key=#k_var{name=K},val=#k_var{name=V}},
+ {{HasKsi,GetVsi,HasVarVsi,GetVarVsi},Int0}) ->
+ case vdb_find(V, Vdb) of
+ {V,_,L} when L =< I ->
+ RK = fetch_var(K,Int0),
+ {{HasKsi,GetVsi,[RK|HasVarVsi],GetVarVsi},Int0};
+ _Other ->
+ Reg1 = put_reg(V, Int0#sr.reg),
+ Int1 = Int0#sr{reg=Reg1},
+ RK = fetch_var(K,Int0),
+ RV = fetch_reg(V,Reg1),
+ {{HasKsi,GetVsi,HasVarVsi,[[RK,RV]|GetVarVsi]},Int1}
+ end;
+ (#k_map_pair{key=Key,val=#k_var{name=V}},
+ {{HasKsi,GetVsi,HasVarVsi,GetVarVsi},Int0}) ->
+ case vdb_find(V, Vdb) of
+ {V,_,L} when L =< I ->
+ {{[atomic(Key)|HasKsi],GetVsi,HasVarVsi,GetVarVsi},Int0};
+ _Other ->
+ Reg1 = put_reg(V, Int0#sr.reg),
+ Int1 = Int0#sr{reg=Reg1},
+ {{HasKsi,[atomic(Key),fetch_reg(V, Reg1)|GetVsi],
+ HasVarVsi,GetVarVsi},Int1}
+ end
+ end, {{[],[],[],[]},Bef}, Vs),
Code = [{test,has_map_fields,{f,Fail},Rsrc,{list,HasKs}} || HasKs =/= []] ++
[{test,has_map_fields,{f,Fail},Rsrc,{list,[K]}} || K <- HasVarKs] ++
@@ -1015,30 +1498,36 @@ select_extract_map(Src, Vs, Fail, I, Vdb, Bef, St) ->
{Code, Aft, St}.
-select_extract_cons(Src, [{var,Hd}, {var,Tl}], I, Vdb, Bef, St) ->
- {Es,Aft} = case {vdb_find(Hd, Vdb), vdb_find(Tl, Vdb)} of
- {{_,_,Lhd}, {_,_,Ltl}} when Lhd =< I, Ltl =< I ->
- %% Both head and tail are dead. No need to generate
- %% any instruction.
- {[], Bef};
- _ ->
- %% At least one of head and tail will be used,
- %% but we must always fetch both. We will call
- %% clear_dead/2 to allow reuse of the register
- %% in case only of them is used.
-
- Reg0 = put_reg(Tl, put_reg(Hd, Bef#sr.reg)),
- Int0 = Bef#sr{reg=Reg0},
- Rsrc = fetch_var(Src, Int0),
- Rhd = fetch_reg(Hd, Reg0),
- Rtl = fetch_reg(Tl, Reg0),
- Int1 = clear_dead(Int0, I, Vdb),
- {[{get_list,Rsrc,Rhd,Rtl}], Int1}
- end,
- {Es,Aft,St}.
-
+select_extract_cons(Src, [#k_var{name=Hd},#k_var{name=Tl}], I, Vdb, Bef, St) ->
+ Rsrc = fetch_var(Src, Bef),
+ Int = clear_dead(Bef, I, Vdb),
+ {{_,_,Lhd},{_,_,Ltl}} = {vdb_find(Hd, Vdb),vdb_find(Tl, Vdb)},
+ case {Lhd =< I, Ltl =< I} of
+ {true,true} ->
+ %% Both dead.
+ {[],Bef,St};
+ {true,false} ->
+ %% Head dead.
+ Reg0 = put_reg(Tl, Bef#sr.reg),
+ Aft = Int#sr{reg=Reg0},
+ Rtl = fetch_reg(Tl, Reg0),
+ {[{get_tl,Rsrc,Rtl}],Aft,St};
+ {false,true} ->
+ %% Tail dead.
+ Reg0 = put_reg(Hd, Bef#sr.reg),
+ Aft = Int#sr{reg=Reg0},
+ Rhd = fetch_reg(Hd, Reg0),
+ {[{get_hd,Rsrc,Rhd}],Aft,St};
+ {false,false} ->
+ %% Both used.
+ Reg0 = put_reg(Tl, put_reg(Hd, Bef#sr.reg)),
+ Aft = Bef#sr{reg=Reg0},
+ Rhd = fetch_reg(Hd, Reg0),
+ Rtl = fetch_reg(Tl, Reg0),
+ {[{get_hd,Rsrc,Rhd},{get_tl,Rsrc,Rtl}],Aft,St}
+ end.
-guard_clause_cg(#l{ke={guard_clause,G,B},vdb=Vdb}, Fail, Bef, St0) ->
+guard_clause_cg(#k_guard_clause{anno=#l{vdb=Vdb},guard=G,body=B}, Fail, Bef, St0) ->
{Gis,Int,St1} = guard_cg(G, Fail, Vdb, Bef, St0),
{Bis,Aft,St} = match_cg(B, Fail, Int, St1),
{Gis ++ Bis,Aft,St}.
@@ -1051,11 +1540,11 @@ guard_clause_cg(#l{ke={guard_clause,G,B},vdb=Vdb}, Fail, Bef, St0) ->
%% the correct exit point. Primops and tests all go to the next
%% instruction on success or jump to a failure label.
-guard_cg(#l{ke={protected,Ts,Rs},i=I,vdb=Pdb}, Fail, _Vdb, Bef, St) ->
- protected_cg(Ts, Rs, Fail, I, Pdb, Bef, St);
-guard_cg(#l{ke={block,Ts},i=I,vdb=Bdb}, Fail, _Vdb, Bef, St) ->
- guard_cg_list(Ts, Fail, I, Bdb, Bef, St);
-guard_cg(#l{ke={test,Test,As,Inverted},i=I,vdb=_Tdb}, Fail, Vdb, Bef, St0) ->
+guard_cg(#k_protected{arg=Ts,ret=Rs,anno=#l{vdb=Pdb}}, Fail, _Vdb, Bef, St) ->
+ protected_cg(Ts, Rs, Fail, Pdb, Bef, St);
+guard_cg(#k_test{anno=#l{i=I},op=Test0,args=As,inverted=Inverted},
+ Fail, Vdb, Bef, St0) ->
+ #k_remote{mod=#k_atom{val=erlang},name=#k_atom{val=Test}} = Test0,
case Inverted of
false ->
test_cg(Test, As, Fail, I, Vdb, Bef, St0);
@@ -1070,6 +1559,18 @@ guard_cg(G, _Fail, Vdb, Bef, St) ->
%%ok = io:fwrite("cg ~w: ~p~n", [?LINE,{Aft}]),
{Gis,Aft,St1}.
+%% guard_cg_list([Kexpr], Fail, I, Vdb, StackReg, St) ->
+%% {[Ainstr],StackReg,St}.
+
+guard_cg_list(Kes, Fail, Vdb, Bef, St0) ->
+ {Keis,{Aft,St1}} =
+ flatmapfoldl(fun (Ke, {Inta,Sta}) ->
+ {Keis,Intb,Stb} =
+ guard_cg(Ke, Fail, Vdb, Inta, Sta),
+ {Keis,{Intb,Stb}}
+ end, {Bef,St0}, need_heap(Kes)),
+ {Keis,Aft,St1}.
+
%% protected_cg([Kexpr], [Ret], Fail, I, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
%% Do a protected. Protecteds without return values are just done
%% for effect, the return value is not checked, success passes on to
@@ -1077,19 +1578,18 @@ guard_cg(G, _Fail, Vdb, Bef, St) ->
%% return values then these must be set to 'false' on failure,
%% control always passes to the next instruction.
-protected_cg(Ts, [], Fail, I, Vdb, Bef, St0) ->
+protected_cg(Ts, [], Fail, Vdb, Bef, St0) ->
%% Protect these calls, revert when done.
- {Tis,Aft,St1} = guard_cg_list(Ts, Fail, I, Vdb, Bef,
- St0#cg{bfail=Fail}),
+ {Tis,Aft,St1} = guard_cg_list(Ts, Fail, Vdb, Bef, St0#cg{bfail=Fail}),
{Tis,Aft,St1#cg{bfail=St0#cg.bfail}};
-protected_cg(Ts, Rs, _Fail, I, Vdb, Bef, St0) ->
+protected_cg(Ts, Rs, _Fail, Vdb, Bef, St0) ->
{Pfail,St1} = new_label(St0),
{Psucc,St2} = new_label(St1),
- {Tis,Aft,St3} = guard_cg_list(Ts, Pfail, I, Vdb, Bef,
+ {Tis,Aft,St3} = guard_cg_list(Ts, Pfail, Vdb, Bef,
St2#cg{bfail=Pfail}),
%%ok = io:fwrite("cg ~w: ~p~n", [?LINE,{Rs,I,Vdb,Aft}]),
%% Set return values to false.
- Mis = [{move,{atom,false},fetch_var(V,Aft)}||{var,V} <- Rs],
+ Mis = [{move,{atom,false},fetch_var(V,Aft)}||#k_var{name=V} <- Rs],
{Tis ++ [{jump,{f,Psucc}},
{label,Pfail}] ++ Mis ++ [{label,Psucc}],
Aft,St3#cg{bfail=St0#cg.bfail}}.
@@ -1114,7 +1614,7 @@ test_cg(is_map, [A], Fail, I, Vdb, Bef, St) ->
Arg = cg_reg_arg_prefer_y(A, Bef),
Aft = clear_dead(Bef, I, Vdb),
{[{test,is_map,{f,Fail},[Arg]}],Aft,St};
-test_cg(is_boolean, [{atom,Val}], Fail, I, Vdb, Bef, St) ->
+test_cg(is_boolean, [#k_atom{val=Val}], Fail, I, Vdb, Bef, St) ->
Aft = clear_dead(Bef, I, Vdb),
Is = case is_boolean(Val) of
true -> [];
@@ -1126,18 +1626,6 @@ test_cg(Test, As, Fail, I, Vdb, Bef, St) ->
Aft = clear_dead(Bef, I, Vdb),
{[beam_utils:bif_to_test(Test, Args, {f,Fail})],Aft,St}.
-%% guard_cg_list([Kexpr], Fail, I, Vdb, StackReg, St) ->
-%% {[Ainstr],StackReg,St}.
-
-guard_cg_list(Kes, Fail, I, Vdb, Bef, St0) ->
- {Keis,{Aft,St1}} =
- flatmapfoldl(fun (Ke, {Inta,Sta}) ->
- {Keis,Intb,Stb} =
- guard_cg(Ke, Fail, Vdb, Inta, Sta),
- {Keis,{Intb,Stb}}
- end, {Bef,St0}, need_heap(Kes, I)),
- {Keis,Aft,St1}.
-
%% match_fmf(Fun, LastFail, State, [Clause]) -> {Is,Aft,State}.
%% This is a special flatmapfoldl for match code gen where we
%% generate a "failure" label for each clause. The last clause uses
@@ -1160,7 +1648,7 @@ match_fmf(F, LastFail, St0, [H|T]) ->
%% frame size. Finally the actual call is made. Call then needs the
%% return values filled in.
-call_cg({var,_V} = Var, As, Rs, Le, Vdb, Bef, St0) ->
+call_cg(#k_var{}=Var, As, Rs, Le, Vdb, Bef, St0) ->
{Sis,Int} = cg_setup_call(As++[Var], Bef, Le#l.i, Vdb),
%% Put return values in registers.
Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
@@ -1169,9 +1657,8 @@ call_cg({var,_V} = Var, As, Rs, Le, Vdb, Bef, St0) ->
{Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
{Sis ++ Frees ++ [line(Le),{call_fun,Arity}],Aft,
need_stack_frame(St0)};
-call_cg({remote,Mod,Name}, As, Rs, Le, Vdb, Bef, St0)
- when element(1, Mod) =:= var;
- element(1, Name) =:= var ->
+call_cg(#k_remote{mod=Mod,name=Name}, As, Rs, Le, Vdb, Bef, St0)
+ when is_record(Mod, k_var); is_record(Name, k_var) ->
{Sis,Int} = cg_setup_call(As++[Mod,Name], Bef, Le#l.i, Vdb),
%% Put return values in registers.
Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
@@ -1189,8 +1676,9 @@ call_cg(Func, As, Rs, Le, Vdb, Bef, St0) ->
%%
%% move {atom,ok} DestReg
%% jump FailureLabel
- {remote,{atom,erlang},{atom,error}} = Func, %Assertion.
- [{var,DestVar}] = Rs,
+ #k_remote{mod=#k_atom{val=erlang},
+ name=#k_atom{val=error}} = Func, %Assertion.
+ [#k_var{name=DestVar}] = Rs,
Int0 = clear_dead(Bef, Le#l.i, Vdb),
Reg = put_reg(DestVar, Int0#sr.reg),
Int = Int0#sr{reg=Reg},
@@ -1209,11 +1697,11 @@ call_cg(Func, As, Rs, Le, Vdb, Bef, St0) ->
{Sis ++ Frees ++ [line(Le)|Call],Aft,St1}
end.
-build_call({remote,{atom,erlang},{atom,'!'}}, 2, St0) ->
+build_call(#k_remote{mod=#k_atom{val=erlang},name=#k_atom{val='!'}}, 2, St0) ->
{[send],need_stack_frame(St0)};
-build_call({remote,{atom,Mod},{atom,Name}}, Arity, St0) ->
+build_call(#k_remote{mod=#k_atom{val=Mod},name=#k_atom{val=Name}}, Arity, St0) ->
{[{call_ext,Arity,{extfunc,Mod,Name,Arity}}],need_stack_frame(St0)};
-build_call(Name, Arity, St0) when is_atom(Name) ->
+build_call(#k_local{name=Name}, Arity, St0) when is_atom(Name) ->
{Lbl,St1} = local_func_label(Name, Arity, need_stack_frame(St0)),
{[{call,Arity,{f,Lbl}}],St1}.
@@ -1229,16 +1717,15 @@ free_dead([Any|Stk], Y, Instr, StkAcc) ->
free_dead(Stk, Y+1, Instr, [Any|StkAcc]);
free_dead([], _, Instr, StkAcc) -> {Instr,reverse(StkAcc)}.
-enter_cg({var,_V} = Var, As, Le, Vdb, Bef, St0) ->
+enter_cg(#k_var{} = Var, As, Le, Vdb, Bef, St0) ->
{Sis,Int} = cg_setup_call(As++[Var], Bef, Le#l.i, Vdb),
%% Build complete code and final stack/register state.
Arity = length(As),
{Sis ++ [line(Le),{call_fun,Arity},return],
clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
need_stack_frame(St0)};
-enter_cg({remote,Mod,Name}, As, Le, Vdb, Bef, St0)
- when element(1, Mod) =:= var;
- element(1, Name) =:= var ->
+enter_cg(#k_remote{mod=Mod,name=Name}, As, Le, Vdb, Bef, St0)
+ when is_record(Mod, k_var); is_record(Name, k_var) ->
{Sis,Int} = cg_setup_call(As++[Mod,Name], Bef, Le#l.i, Vdb),
%% Build complete code and final stack/register state.
Arity = length(As),
@@ -1256,19 +1743,19 @@ enter_cg(Func, As, Le, Vdb, Bef, St0) ->
clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
St1}.
-build_enter({remote,{atom,erlang},{atom,'!'}}, 2, St0) ->
+build_enter(#k_remote{mod=#k_atom{val=erlang},name=#k_atom{val='!'}}, 2, St0) ->
{[send,return],need_stack_frame(St0)};
-build_enter({remote,{atom,Mod},{atom,Name}}, Arity, St0) ->
+build_enter(#k_remote{mod=#k_atom{val=Mod},name=#k_atom{val=Name}}, Arity, St0) ->
St1 = case trap_bif(Mod, Name, Arity) of
true -> need_stack_frame(St0);
false -> St0
end,
{[{call_ext_only,Arity,{extfunc,Mod,Name,Arity}}],St1};
-build_enter(Name, Arity, St0) when is_atom(Name) ->
+build_enter(#k_local{name=Name}, Arity, St0) when is_atom(Name) ->
{Lbl,St1} = local_func_label(Name, Arity, St0),
{[{call_only,Arity,{f,Lbl}}],St1}.
-enter_line({remote,{atom,Mod},{atom,Name}}, Arity, Le) ->
+enter_line(#k_remote{mod=#k_atom{val=Mod},name=#k_atom{val=Name}}, Arity, Le) ->
case erl_bifs:is_safe(Mod, Name, Arity) of
false ->
%% Tail-recursive call, possibly to a BIF.
@@ -1316,17 +1803,28 @@ trap_bif(erlang, group_leader, 2) -> true;
trap_bif(erlang, exit, 2) -> true;
trap_bif(_, _, _) -> false.
+%% bif_cg(#k_bif{}, Le, Vdb, StackReg, State) ->
+%% {[Ainstr],StackReg,State}.
+%% Generate code a BIF.
+
+bif_cg(#k_bif{op=#k_internal{name=Name},args=As,ret=Rs}, Le, Vdb, Bef, St) ->
+ internal_cg(Name, As, Rs, Le, Vdb, Bef, St);
+bif_cg(#k_bif{op=#k_remote{mod=#k_atom{val=erlang},name=#k_atom{val=Name}},
+ args=As,ret=Rs}, Le, Vdb, Bef, St) ->
+ Ar = length(As),
+ case is_gc_bif(Name, Ar) of
+ false ->
+ bif_cg(Name, As, Rs, Le, Vdb, Bef, St);
+ true ->
+ gc_bif_cg(Name, As, Rs, Le, Vdb, Bef, St)
+ end.
+
%% internal_cg(Bif, [Arg], [Ret], Le, Vdb, StackReg, State) ->
%% {[Ainstr],StackReg,State}.
internal_cg(bs_context_to_binary=Instr, [Src0], [], Le, Vdb, Bef, St0) ->
[Src] = cg_reg_args([Src0], Bef),
- case is_register(Src) of
- false ->
- {[],clear_dead(Bef, Le#l.i, Vdb), St0};
- true ->
- {[{Instr,Src}],clear_dead(Bef, Le#l.i, Vdb), St0}
- end;
+ {[{Instr,Src}],clear_dead(Bef, Le#l.i, Vdb), St0};
internal_cg(dsetelement, [Index0,Tuple0,New0], _Rs, Le, Vdb, Bef, St0) ->
[New,Tuple,{integer,Index1}] = cg_reg_args([New0,Tuple0,Index0], Bef),
Index = Index1-1,
@@ -1334,8 +1832,8 @@ internal_cg(dsetelement, [Index0,Tuple0,New0], _Rs, Le, Vdb, Bef, St0) ->
clear_dead(Bef, Le#l.i, Vdb), St0};
internal_cg(make_fun, [Func0,Arity0|As], Rs, Le, Vdb, Bef, St0) ->
%% This behaves more like a function call.
- {atom,Func} = Func0,
- {integer,Arity} = Arity0,
+ #k_atom{val=Func} = Func0,
+ #k_int{val=Arity} = Arity0,
{Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
{FuncLbl,St1} = local_func_label(Func, Arity, St0),
@@ -1348,14 +1846,35 @@ internal_cg(bs_init_writable=I, As, Rs, Le, Vdb, Bef, St) ->
{Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
{Sis++[I],clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb),St};
+internal_cg(build_stacktrace=I, As, Rs, Le, Vdb, Bef, St) ->
+ %% This behaves like a function call.
+ {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
+ Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
+ {Sis++[I],clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb),St};
internal_cg(raise, As, Rs, Le, Vdb, Bef, St) ->
%% raise can be treated like a guard BIF.
- bif_cg(raise, As, Rs, Le, Vdb, Bef, St).
+ bif_cg(raise, As, Rs, Le, Vdb, Bef, St);
+internal_cg(guard_error, [ExitCall], _Rs, Le, Vdb, Bef, St) ->
+ %% A call an exit BIF from inside a #k_guard_match{}.
+ %% Generate a standard call, but leave the register descriptors
+ %% alone, effectively pretending that there was no call.
+ #k_call{op=#k_remote{mod=#k_atom{val=Mod},name=#k_atom{val=Name}},
+ args=As} = ExitCall,
+ Arity = length(As),
+ {Ms,_} = cg_call_args(As, Bef, Le#l.i, Vdb),
+ Call = {call_ext,Arity,{extfunc,Mod,Name,Arity}},
+ Is = Ms++[line(Le),Call],
+ {Is,Bef,St};
+internal_cg(raw_raise=I, As, Rs, Le, Vdb, Bef, St) ->
+ %% This behaves like a function call.
+ {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
+ Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
+ {Sis++[I],clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb),St}.
%% bif_cg(Bif, [Arg], [Ret], Le, Vdb, StackReg, State) ->
%% {[Ainstr],StackReg,State}.
-bif_cg(Bif, As, [{var,V}], Le, Vdb, Bef, St0) ->
+bif_cg(Bif, As, [#k_var{name=V}], Le, Vdb, Bef, St0) ->
Ars = cg_reg_args(As, Bef),
%% If we are inside a catch and in a body (not in guard) and the
@@ -1393,7 +1912,7 @@ bif_cg(Bif, As, [{var,V}], Le, Vdb, Bef, St0) ->
%% gc_bif_cg(Bif, [Arg], [Ret], Le, Vdb, StackReg, State) ->
%% {[Ainstr],StackReg,State}.
-gc_bif_cg(Bif, As, [{var,V}], Le, Vdb, Bef, St0) ->
+gc_bif_cg(Bif, As, [#k_var{name=V}], Le, Vdb, Bef, St0) ->
Ars = cg_reg_args(As, Bef),
%% If we are inside a catch and in a body (not in guard) and the
@@ -1439,7 +1958,7 @@ recv_loop_cg(Te, Rvar, Rm, Tes, Rs, Le, Vdb, Bef, St0) ->
%% cg_recv_mesg( ) -> {[Ainstr],Aft,St}.
-cg_recv_mesg({var,R}, Rm, Tl, Bef, St0) ->
+cg_recv_mesg(#k_var{name=R}, Rm, Tl, Bef, St0) ->
Int0 = Bef#sr{reg=put_reg(R, Bef#sr.reg)},
Ret = fetch_reg(R, Int0#sr.reg),
%% Int1 = clear_dead(Int0, I, Rm#l.vdb),
@@ -1449,22 +1968,22 @@ cg_recv_mesg({var,R}, Rm, Tl, Bef, St0) ->
%% cg_recv_wait(Te, Tes, I, Vdb, Int2, St3) -> {[Ainstr],Aft,St}.
-cg_recv_wait({atom,infinity}, Tes, I, Bef, St0) ->
+cg_recv_wait(#k_atom{val=infinity}, #cg_block{anno=Le,es=Tes}, I, Bef, St0) ->
%% We know that the 'after' body will never be executed.
%% But to keep the stack and register information up to date,
%% we will generate the code for the 'after' body, and then discard it.
- Int1 = clear_dead(Bef, I, Tes#l.vdb),
- {_,Int2,St1} = cg_block(Tes#l.ke, Tes#l.i, Tes#l.vdb,
- Int1#sr{reg=clear_regs(Int1#sr.reg)}, St0),
+ Int1 = clear_dead(Bef, I, Le#l.vdb),
+ {_,Int2,St1} = cg_block(Tes, Le#l.vdb,
+ Int1#sr{reg=clear_regs(Int1#sr.reg)}, St0),
{[{wait,{f,St1#cg.recv}}],Int2,St1};
-cg_recv_wait({integer,0}, Tes, _I, Bef, St0) ->
- {Tis,Int,St1} = cg_block(Tes#l.ke, Tes#l.i, Tes#l.vdb, Bef, St0),
+cg_recv_wait(#k_int{val=0}, #cg_block{anno=Le,es=Tes}, _I, Bef, St0) ->
+ {Tis,Int,St1} = cg_block(Tes, Le#l.vdb, Bef, St0),
{[timeout|Tis],Int,St1};
-cg_recv_wait(Te, Tes, I, Bef, St0) ->
+cg_recv_wait(Te, #cg_block{anno=Le,es=Tes}, I, Bef, St0) ->
Reg = cg_reg_arg(Te, Bef),
%% Must have empty registers here! Bug if anything in registers.
- Int0 = clear_dead(Bef, I, Tes#l.vdb),
- {Tis,Int,St1} = cg_block(Tes#l.ke, Tes#l.i, Tes#l.vdb,
+ Int0 = clear_dead(Bef, I, Le#l.vdb),
+ {Tis,Int,St1} = cg_block(Tes, Le#l.vdb,
Int0#sr{reg=clear_regs(Int0#sr.reg)}, St0),
{[{wait_timeout,{f,St1#cg.recv},Reg},timeout] ++ Tis,Int,St1}.
@@ -1482,7 +2001,7 @@ try_cg(Ta, Vs, Tb, Evs, Th, Rs, Le, Vdb, Bef, St0) ->
{B,St1} = new_label(St0), %Body label
{H,St2} = new_label(St1), %Handler label
{E,St3} = new_label(St2), %End label
- TryTag = Ta#l.i,
+ #l{i=TryTag} = get_kanno(Ta),
Int1 = Bef#sr{stk=put_catch(TryTag, Bef#sr.stk)},
TryReg = fetch_stack({catch_tag,TryTag}, Int1#sr.stk),
{Ais,Int2,St4} = cg(Ta, Vdb, Int1, St3#cg{break=B,in_catch=true}),
@@ -1502,7 +2021,7 @@ try_cg(Ta, Vs, Tb, Evs, Th, Rs, Le, Vdb, Bef, St0) ->
try_enter_cg(Ta, Vs, Tb, Evs, Th, Le, Vdb, Bef, St0) ->
{B,St1} = new_label(St0), %Body label
{H,St2} = new_label(St1), %Handler label
- TryTag = Ta#l.i,
+ #l{i=TryTag} = get_kanno(Ta),
Int1 = Bef#sr{stk=put_catch(TryTag, Bef#sr.stk)},
TryReg = fetch_stack({catch_tag,TryTag}, Int1#sr.stk),
{Ais,Int2,St3} = cg(Ta, Vdb, Int1, St2#cg{break=B,in_catch=true}),
@@ -1520,12 +2039,12 @@ try_enter_cg(Ta, Vs, Tb, Evs, Th, Le, Vdb, Bef, St0) ->
%% catch_cg(CatchBlock, Ret, Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
-catch_cg(C, {var,R}, Le, Vdb, Bef, St0) ->
+catch_cg(#cg_block{es=C}, #k_var{name=R}, Le, Vdb, Bef, St0) ->
{B,St1} = new_label(St0),
CatchTag = Le#l.i,
Int1 = Bef#sr{stk=put_catch(CatchTag, Bef#sr.stk)},
CatchReg = fetch_stack({catch_tag,CatchTag}, Int1#sr.stk),
- {Cis,Int2,St2} = cg_block(C, Le#l.i, Le#l.vdb, Int1,
+ {Cis,Int2,St2} = cg_block(C, Le#l.vdb, Int1,
St1#cg{break=B,in_catch=true}),
[] = Int2#sr.reg, %Assertion.
Aft = Int2#sr{reg=[{0,R}],stk=drop_catch(CatchTag, Int2#sr.stk)},
@@ -1534,8 +2053,8 @@ catch_cg(C, {var,R}, Le, Vdb, Bef, St0) ->
clear_dead(Aft, Le#l.i, Vdb),
St2#cg{break=St1#cg.break,in_catch=St1#cg.in_catch}}.
-%% set_cg([Var], Constr, Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
-%% We have to be careful how a 'set' works. First the structure is
+%% put_cg([Var], Constr, Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
+%% We have to be careful how a 'put' works. First the structure is
%% built, then it is filled and finally things can be cleared. The
%% annotation must reflect this and make sure that the return
%% variable is allocated first.
@@ -1543,13 +2062,14 @@ catch_cg(C, {var,R}, Le, Vdb, Bef, St0) ->
%% put_list and put_map are atomic instructions, both of
%% which can safely resuse one of the source registers as target.
-set_cg([{var,R}], {cons,Es}, Le, Vdb, Bef, St) ->
- [S1,S2] = cg_reg_args(Es, Bef),
+put_cg([#k_var{name=R}], #k_cons{hd=Hd,tl=Tl}, Le, Vdb, Bef, St) ->
+ [S1,S2] = cg_reg_args([Hd,Tl], Bef),
Int0 = clear_dead(Bef, Le#l.i, Vdb),
Int1 = Int0#sr{reg=put_reg(R, Int0#sr.reg)},
Ret = fetch_reg(R, Int1#sr.reg),
{[{put_list,S1,S2,Ret}], Int1, St};
-set_cg([{var,R}], {binary,Segs}, Le, Vdb, Bef, #cg{bfail=Bfail}=St) ->
+put_cg([#k_var{name=R}], #k_binary{segs=Segs}, Le, Vdb, Bef,
+ #cg{bfail=Bfail}=St) ->
%% At run-time, binaries are constructed in three stages:
%% 1) First the size of the binary is calculated.
%% 2) Then the binary is allocated.
@@ -1577,7 +2097,9 @@ set_cg([{var,R}], {binary,Segs}, Le, Vdb, Bef, #cg{bfail=Bfail}=St) ->
{Sis++Code,Aft,St};
%% Map: single variable key.
-set_cg([{var,R}], {map,Op,Map,[{map_pair,{var,_}=K,V}]}, Le, Vdb, Bef, St0) ->
+put_cg([#k_var{name=R}], #k_map{op=Op,var=Map,
+ es=[#k_map_pair{key=#k_var{}=K,val=V}]},
+ Le, Vdb, Bef, St0) ->
{Sis,Int0} = maybe_adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb, St0),
SrcReg = cg_reg_arg_prefer_y(Map, Int0),
@@ -1592,22 +2114,23 @@ set_cg([{var,R}], {map,Op,Map,[{map_pair,{var,_}=K,V}]}, Le, Vdb, Bef, St0) ->
Aft = Aft0#sr{reg=put_reg(R, Aft0#sr.reg)},
Target = fetch_reg(R, Aft#sr.reg),
- {Is,St1} = set_cg_map(Line, Op, SrcReg, Target, Live, List, St0),
+ {Is,St1} = put_cg_map(Line, Op, SrcReg, Target, Live, List, St0),
{Sis++Is,Aft,St1};
%% Map: (possibly) multiple literal keys.
-set_cg([{var,R}], {map,Op,Map,Es}, Le, Vdb, Bef, St0) ->
+put_cg([#k_var{name=R}], #k_map{op=Op,var=Map,es=Es}, Le, Vdb, Bef, St0) ->
%% assert key literals
- [] = [Var||{map_pair,{var,_}=Var,_} <- Es],
+ [] = [Var || #k_map_pair{key=#k_var{}=Var} <- Es],
{Sis,Int0} = maybe_adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb, St0),
SrcReg = cg_reg_arg_prefer_y(Map, Int0),
Line = line(Le#l.a),
%% fetch registers for values to be put into the map
- Pairs = [{K,V} || {_,K,V} <- Es],
- List = flatmap(fun({K,V}) -> [K,cg_reg_arg(V,Int0)] end, Pairs),
+ List = flatmap(fun(#k_map_pair{key=K,val=V}) ->
+ [atomic(K),cg_reg_arg(V, Int0)]
+ end, Es),
Live = max_reg(Bef#sr.reg),
@@ -1616,16 +2139,16 @@ set_cg([{var,R}], {map,Op,Map,Es}, Le, Vdb, Bef, St0) ->
Aft = Aft0#sr{reg=put_reg(R, Aft0#sr.reg)},
Target = fetch_reg(R, Aft#sr.reg),
- {Is,St1} = set_cg_map(Line, Op, SrcReg, Target, Live, List, St0),
+ {Is,St1} = put_cg_map(Line, Op, SrcReg, Target, Live, List, St0),
{Sis++Is,Aft,St1};
%% Everything else.
-set_cg([{var,R}], Con, Le, Vdb, Bef, St) ->
+put_cg([#k_var{name=R}], Con, Le, Vdb, Bef, St) ->
%% Find a place for the return register first.
Int = Bef#sr{reg=put_reg(R, Bef#sr.reg)},
Ret = fetch_reg(R, Int#sr.reg),
Ais = case Con of
- {tuple,Es} ->
+ #k_tuple{es=Es} ->
[{put_tuple,length(Es),Ret}] ++ cg_build_args(Es, Bef);
Other ->
[{move,cg_reg_arg(Other, Int),Ret}]
@@ -1633,7 +2156,7 @@ set_cg([{var,R}], Con, Le, Vdb, Bef, St) ->
{Ais,clear_dead(Int, Le#l.i, Vdb),St}.
-set_cg_map(Line, Op0, SrcReg, Target, Live, List, St0) ->
+put_cg_map(Line, Op0, SrcReg, Target, Live, List, St0) ->
Bfail = St0#cg.bfail,
Fail = {f,St0#cg.bfail},
Op = case Op0 of
@@ -1811,24 +2334,44 @@ cg_gen_binsize([], _, _, _, _, Acc) -> Acc.
%% cg_bin_opt(Code0) -> Code
%% Optimize the size calculations for binary construction.
-cg_bin_opt([{move,Size,D},{bs_append,Fail,D,Extra,Regs,U,Bin,Flags,D}|Is]) ->
- cg_bin_opt([{bs_append,Fail,Size,Extra,Regs,U,Bin,Flags,D}|Is]);
-cg_bin_opt([{move,Size,D},{bs_private_append,Fail,D,U,Bin,Flags,D}|Is]) ->
- cg_bin_opt([{bs_private_append,Fail,Size,U,Bin,Flags,D}|Is]);
-cg_bin_opt([{move,{integer,0},D},{bs_add,_,[D,{integer,_}=S,1],Dst}|Is]) ->
- cg_bin_opt([{move,S,Dst}|Is]);
-cg_bin_opt([{move,{integer,0},D},{bs_add,Fail,[D,S,U],Dst}|Is]) ->
- cg_bin_opt([{bs_add,Fail,[{integer,0},S,U],Dst}|Is]);
-cg_bin_opt([{move,{integer,Bytes},D},{Op,Fail,D,Extra,Regs,Flags,D}|Is])
+cg_bin_opt([{move,S1,{x,X}=D},{gc_bif,Op,Fail,Live0,As,Dst}|Is]) ->
+ Live = if
+ X + 1 =:= Live0 -> X;
+ true -> Live0
+ end,
+ [{gc_bif,Op,Fail,Live,As,D}|cg_bin_opt([{move,S1,Dst}|Is])];
+cg_bin_opt([{move,_,_}=I1,{Op,_,_,_}=I2|Is])
+ when Op =:= bs_utf8_size orelse Op =:= bs_utf16_size ->
+ [I2|cg_bin_opt([I1|Is])];
+cg_bin_opt([{bs_add,_,[{integer,0},Src,1],Dst}|Is]) ->
+ cg_bin_opt_1([{move,Src,Dst}|Is]);
+cg_bin_opt([{bs_add,_,[Src,{integer,0},_],Dst}|Is]) ->
+ cg_bin_opt_1([{move,Src,Dst}|Is]);
+cg_bin_opt(Is) ->
+ cg_bin_opt_1(Is).
+
+cg_bin_opt_1([{move,Size,D},{bs_append,Fail,D,Extra,Regs,U,Bin,Flags,D}|Is]) ->
+ [{bs_append,Fail,Size,Extra,Regs,U,Bin,Flags,D}|cg_bin_opt(Is)];
+cg_bin_opt_1([{move,Size,D},{bs_private_append,Fail,D,U,Bin,Flags,D}|Is]) ->
+ [{bs_private_append,Fail,Size,U,Bin,Flags,D}|cg_bin_opt(Is)];
+cg_bin_opt_1([{move,Size,D},{Op,Fail,D,Extra,Regs,Flags,D}|Is])
when Op =:= bs_init2; Op =:= bs_init_bits ->
- cg_bin_opt([{Op,Fail,Bytes,Extra,Regs,Flags,D}|Is]);
-cg_bin_opt([{move,Src1,Dst},{bs_add,Fail,[Dst,Src2,U],Dst}|Is]) ->
- cg_bin_opt([{bs_add,Fail,[Src1,Src2,U],Dst}|Is]);
-cg_bin_opt([I|Is]) ->
+ Bytes = case Size of
+ {integer,Int} -> Int;
+ _ -> Size
+ end,
+ [{Op,Fail,Bytes,Extra,Regs,Flags,D}|cg_bin_opt(Is)];
+cg_bin_opt_1([{move,S1,D},{bs_add,Fail,[D,S2,U],Dst}|Is]) ->
+ cg_bin_opt([{bs_add,Fail,[S1,S2,U],Dst}|Is]);
+cg_bin_opt_1([{move,S1,D},{bs_add,Fail,[S2,D,U],Dst}|Is]) ->
+ cg_bin_opt([{bs_add,Fail,[S2,S1,U],Dst}|Is]);
+cg_bin_opt_1([I|Is]) ->
[I|cg_bin_opt(Is)];
-cg_bin_opt([]) -> [].
+cg_bin_opt_1([]) ->
+ [].
-cg_bin_put({bin_seg,[],S0,U,T,Fs,[E0,Next]}, Fail, Bef) ->
+cg_bin_put(#k_bin_seg{size=S0,unit=U,type=T,flags=Fs,seg=E0,next=Next},
+ Fail, Bef) ->
S1 = cg_reg_arg(S0, Bef),
E1 = cg_reg_arg(E0, Bef),
{Format,Op} = case T of
@@ -1845,7 +2388,7 @@ cg_bin_put({bin_seg,[],S0,U,T,Fs,[E0,Next]}, Fail, Bef) ->
utf ->
[{Op,Fail,{field_flags,Fs},E1}|cg_bin_put(Next, Fail, Bef)]
end;
-cg_bin_put({bin_end,[]}, _, _) -> [].
+cg_bin_put(#k_bin_end{}, _, _) -> [].
cg_build_args(As, Bef) ->
[{put,cg_reg_arg(A, Bef)} || A <- As].
@@ -1865,13 +2408,12 @@ break_cg(Bs, Le, Vdb, Bef, St) ->
{Ms ++ [{jump,{f,St#cg.break}}],
Int#sr{reg=clear_regs(Int#sr.reg)},St}.
-guard_break_cg(Bs, Locked, #l{i=I}, Vdb, #sr{reg=Reg0}=Bef, St) ->
- RegLocked = get_locked_regs(Reg0, Locked),
- #sr{reg=Reg1} = Int = clear_dead(Bef#sr{reg=RegLocked}, I, Vdb),
+guard_break_cg(Bs, #l{i=I}, Vdb, #sr{reg=Reg0}=Bef, St) ->
+ #sr{reg=Reg1} = Int = clear_dead(Bef, I, Vdb),
Reg2 = trim_free(Reg1),
NumLocked = length(Reg2),
Moves0 = gen_moves(Bs, Bef, NumLocked, []),
- Moves = order_moves(Moves0, find_scratch_reg(RegLocked)),
+ Moves = order_moves(Moves0, find_scratch_reg(Reg0)),
{BreakVars,_} = mapfoldl(fun(_, RegNum) ->
{{RegNum,gbreakvar},RegNum+1}
end, length(Reg2), Bs),
@@ -1879,31 +2421,17 @@ guard_break_cg(Bs, Locked, #l{i=I}, Vdb, #sr{reg=Reg0}=Bef, St) ->
Aft = Int#sr{reg=Reg},
{Moves ++ [{jump,{f,St#cg.break}}],Aft,St}.
-get_locked_regs([R|Rs0], Preserve) ->
- case {get_locked_regs(Rs0, Preserve),R} of
- {[],{_,V}} ->
- case lists:member(V, Preserve) of
- true -> [R];
- false -> []
- end;
- {[],_} ->
- [];
- {Rs,_} ->
- [R|Rs]
- end;
-get_locked_regs([], _) -> [].
-
%% cg_reg_arg(Arg0, Info) -> Arg
%% cg_reg_args([Arg0], Info) -> [Arg]
%% Convert argument[s] into registers. Literal values are returned unchanged.
cg_reg_args(As, Bef) -> [cg_reg_arg(A, Bef) || A <- As].
-cg_reg_arg({var,V}, Bef) -> fetch_var(V, Bef);
-cg_reg_arg(Literal, _) -> Literal.
+cg_reg_arg(#k_var{name=V}, Bef) -> fetch_var(V, Bef);
+cg_reg_arg(Literal, _) -> atomic(Literal).
-cg_reg_arg_prefer_y({var,V}, Bef) -> fetch_var_prefer_y(V, Bef);
-cg_reg_arg_prefer_y(Literal, _) -> Literal.
+cg_reg_arg_prefer_y(#k_var{name=V}, Bef) -> fetch_var_prefer_y(V, Bef);
+cg_reg_arg_prefer_y(Literal, _) -> atomic(Literal).
%% cg_setup_call([Arg], Bef, Cur, Vdb) -> {[Instr],Aft}.
%% Do the complete setup for a call/enter.
@@ -1941,9 +2469,9 @@ cg_call_args(As, Bef, I, Vdb) ->
load_arg_regs(Regs, As) -> load_arg_regs(Regs, As, 0).
-load_arg_regs([_|Rs], [{var,V}|As], I) -> [{I,V}|load_arg_regs(Rs, As, I+1)];
+load_arg_regs([_|Rs], [#k_var{name=V}|As], I) -> [{I,V}|load_arg_regs(Rs, As, I+1)];
load_arg_regs([_|Rs], [A|As], I) -> [{I,A}|load_arg_regs(Rs, As, I+1)];
-load_arg_regs([], [{var,V}|As], I) -> [{I,V}|load_arg_regs([], As, I+1)];
+load_arg_regs([], [#k_var{name=V}|As], I) -> [{I,V}|load_arg_regs([], As, I+1)];
load_arg_regs([], [A|As], I) -> [{I,A}|load_arg_regs([], As, I+1)];
load_arg_regs(Rs, [], _) -> Rs.
@@ -1979,12 +2507,13 @@ move_unsaved([], _, Regs, Acc) -> {Acc,Regs}.
gen_moves(As, Sr) -> gen_moves(As, Sr, 0, []).
-gen_moves([{var,V}|As], Sr, I, Acc) ->
+gen_moves([#k_var{name=V}|As], Sr, I, Acc) ->
case fetch_var(V, Sr) of
{x,I} -> gen_moves(As, Sr, I+1, Acc);
Reg -> gen_moves(As, Sr, I+1, [{move,Reg,{x,I}}|Acc])
end;
-gen_moves([A|As], Sr, I, Acc) ->
+gen_moves([A0|As], Sr, I, Acc) ->
+ A = atomic(A0),
gen_moves(As, Sr, I+1, [{move,A,{x,I}}|Acc]);
gen_moves([], _, _, Acc) -> lists:keysort(3, Acc).
@@ -2032,21 +2561,21 @@ break_up_cycle1(Dst, [M|Path], LastMove) ->
%% clear_dead(Sr, Until, Vdb) -> Aft.
%% Remove all variables in Sr which have died AT ALL so far.
-clear_dead(Sr, Until, Vdb) ->
- Sr#sr{reg=clear_dead_reg(Sr, Until, Vdb),
- stk=clear_dead_stk(Sr#sr.stk, Until, Vdb)}.
+clear_dead(#sr{stk=Stk}=Sr0, Until, Vdb) ->
+ Sr = Sr0#sr{reg=clear_dead_reg(Sr0, Until, Vdb),
+ stk=clear_dead_stk(Stk, Until, Vdb)},
+ reserve(Sr).
clear_dead_reg(Sr, Until, Vdb) ->
- Reg = [case R of
- {_I,V} = IV ->
- case vdb_find(V, Vdb) of
- {V,_,L} when L > Until -> IV;
- _ -> free %Remove anything else
- end;
- {reserved,_I,_V} = Reserved -> Reserved;
- free -> free
- end || R <- Sr#sr.reg],
- reserve(Sr#sr.res, Reg, Sr#sr.stk).
+ [case R of
+ {_I,V} = IV ->
+ case vdb_find(V, Vdb) of
+ {V,_,L} when L > Until -> IV;
+ _ -> free %Remove anything else
+ end;
+ {reserved,_I,_V}=Reserved -> Reserved;
+ free -> free
+ end || R <- Sr#sr.reg].
clear_dead_stk(Stk, Until, Vdb) ->
[case S of
@@ -2118,16 +2647,25 @@ adjust_stack(Bef, Fb, Lf, Vdb) ->
save_stack(Stk0, Fb, Lf, Vdb) ->
%% New variables that are in use but not on stack.
- New = [VFL || {V,F,L} = VFL <- Vdb,
- F < Fb,
- L >= Lf,
- not on_stack(V, Stk0)],
+ New = new_not_on_stack(Stk0, Fb, Lf, Vdb),
+
%% Add new variables that are not just dropped immediately.
%% N.B. foldr works backwards from the end!!
Saves = [V || {V,_,_} <- keysort(3, New)],
Stk1 = foldr(fun (V, Stk) -> put_stack(V, Stk) end, Stk0, Saves),
{Stk1,Saves}.
+%% new_not_on_stack(Stack, FirstBefore, LastFrom, Vdb) ->
+%% [{Variable,First,Last}]
+%% Return information about all variables that are used past current
+%% point and that are not already on the stack.
+
+new_not_on_stack(Stk, Fb, Lf, Vdb) ->
+ [VFL || {V,F,L} = VFL <- Vdb,
+ F < Fb,
+ L >= Lf,
+ not on_stack(V, Stk)].
+
%% saves([SaveVar], Reg, Stk) -> [{move,Reg,Stk}].
%% Generate move instructions to save variables onto stack. The
%% stack/reg info used is that after the new stack has been made.
@@ -2153,7 +2691,7 @@ fetch_var_prefer_y(V, #sr{reg=Reg,stk=Stk}) ->
end.
load_vars(Vs, Regs) ->
- foldl(fun ({var,V}, Rs) -> put_reg(V, Rs) end, Regs, Vs).
+ foldl(fun (#k_var{name=V}, Rs) -> put_reg(V, Rs) end, Regs, Vs).
%% put_reg(Val, Regs) -> Regs.
%% find_reg(Val, Regs) -> {ok,r{R}} | error.
@@ -2233,10 +2771,6 @@ find_stack(_, [], _) -> error.
on_stack(V, Stk) -> keymember(V, 1, Stk).
-is_register({x,_}) -> true;
-is_register({yy,_}) -> true;
-is_register(_) -> false.
-
%% put_catch(CatchTag, Stack) -> Stack'
%% drop_catch(CatchTag, Stack) -> Stack'
%% Special interface for putting and removing catch tags, to ensure that
@@ -2254,6 +2788,16 @@ put_catch(Tag, [Other|Stk], Acc) ->
drop_catch(Tag, [{{catch_tag,Tag}}|Stk]) -> [free|Stk];
drop_catch(Tag, [Other|Stk]) -> [Other|drop_catch(Tag, Stk)].
+%% atomic(Klit) -> Lit.
+%% atomic_list([Klit]) -> [Lit].
+
+atomic(#k_literal{val=V}) -> {literal,V};
+atomic(#k_int{val=I}) -> {integer,I};
+atomic(#k_float{val=F}) -> {float,F};
+atomic(#k_atom{val=A}) -> {atom,A};
+%%atomic(#k_char{val=C}) -> {char,C};
+atomic(#k_nil{}) -> nil.
+
%% new_label(St) -> {L,St}.
new_label(#cg{lcount=Next}=St) ->
@@ -2296,3 +2840,86 @@ flatmapfoldl(F, Accu0, [Hd|Tail]) ->
{Rs,Accu2} = flatmapfoldl(F, Accu1, Tail),
{R++Rs,Accu2};
flatmapfoldl(_, Accu, []) -> {[],Accu}.
+
+%% Keep track of life time for variables.
+%%
+%% init_vars([{var,VarName}]) -> Vdb.
+%% new_vars([VarName], I, Vdb) -> Vdb.
+%% use_vars([VarName], I, Vdb) -> Vdb.
+%% add_var(VarName, F, L, Vdb) -> Vdb.
+%%
+%% The list of variable names for new_vars/3 and use_vars/3
+%% must be sorted.
+
+init_vars(Vs) ->
+ vdb_new(Vs).
+
+new_vars([], _, Vdb) -> Vdb;
+new_vars([V], I, Vdb) -> vdb_store_new(V, {V,I,I}, Vdb);
+new_vars(Vs, I, Vdb) -> vdb_update_vars(Vs, Vdb, I).
+
+use_vars([], _, Vdb) ->
+ Vdb;
+use_vars([V], I, Vdb) ->
+ case vdb_find(V, Vdb) of
+ {V,F,L} when I > L -> vdb_update(V, {V,F,I}, Vdb);
+ {V,_,_} -> Vdb;
+ error -> vdb_store_new(V, {V,I,I}, Vdb)
+ end;
+use_vars(Vs, I, Vdb) -> vdb_update_vars(Vs, Vdb, I).
+
+add_var(V, F, L, Vdb) ->
+ vdb_store_new(V, {V,F,L}, Vdb).
+
+%% vdb
+
+vdb_new(Vs) ->
+ ordsets:from_list([{V,0,0} || #k_var{name=V} <- Vs]).
+
+-type var() :: atom().
+
+-spec vdb_find(var(), [vdb_entry()]) -> 'error' | vdb_entry().
+
+vdb_find(V, Vdb) ->
+ case lists:keyfind(V, 1, Vdb) of
+ false -> error;
+ Vd -> Vd
+ end.
+
+vdb_update(V, Update, [{V,_,_}|Vdb]) ->
+ [Update|Vdb];
+vdb_update(V, Update, [Vd|Vdb]) ->
+ [Vd|vdb_update(V, Update, Vdb)].
+
+vdb_store_new(V, New, [{V1,_,_}=Vd|Vdb]) when V > V1 ->
+ [Vd|vdb_store_new(V, New, Vdb)];
+vdb_store_new(V, New, [{V1,_,_}|_]=Vdb) when V < V1 ->
+ [New|Vdb];
+vdb_store_new(_, New, []) -> [New].
+
+vdb_update_vars([V|_]=Vs, [{V1,_,_}=Vd|Vdb], I) when V > V1 ->
+ [Vd|vdb_update_vars(Vs, Vdb, I)];
+vdb_update_vars([V|Vs], [{V1,_,_}|_]=Vdb, I) when V < V1 ->
+ %% New variable.
+ [{V,I,I}|vdb_update_vars(Vs, Vdb, I)];
+vdb_update_vars([V|Vs], [{_,F,L}=Vd|Vdb], I) ->
+ %% Existing variable.
+ if
+ I > L -> [{V,F,I}|vdb_update_vars(Vs, Vdb, I)];
+ true -> [Vd|vdb_update_vars(Vs, Vdb, I)]
+ end;
+vdb_update_vars([V|Vs], [], I) ->
+ %% New variable.
+ [{V,I,I}|vdb_update_vars(Vs, [], I)];
+vdb_update_vars([], Vdb, _) -> Vdb.
+
+%% vdb_sub(Min, Max, Vdb) -> Vdb.
+%% Extract variables which are used before and after Min. Lock
+%% variables alive after Max.
+
+vdb_sub(Min, Max, Vdb) ->
+ [ if L >= Max -> {V,F,locked};
+ true -> Vd
+ end || {V,F,L}=Vd <- Vdb,
+ F < Min,
+ L >= Min ].
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index ae650546e5..c9517c3e51 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -328,14 +328,16 @@ gexpr({protect,Line,Arg}, Bools0, St0) ->
Anno = lineno_anno(Line, St),
{#iprotect{anno=#a{anno=Anno},body=Eps++[E]},[],Bools0,St}
end;
-gexpr({op,L,'andalso',E1,E2}, Bools, St0) ->
+gexpr({op,_,'andalso',_,_}=E0, Bools, St0) ->
+ {op,L,'andalso',E1,E2} = right_assoc(E0, 'andalso', St0),
Anno = lineno_anno(L, St0),
{#c_var{name=V0},St} = new_var(Anno, St0),
V = {var,L,V0},
False = {atom,L,false},
E = make_bool_switch_guard(L, E1, V, E2, False),
gexpr(E, Bools, St);
-gexpr({op,L,'orelse',E1,E2}, Bools, St0) ->
+gexpr({op,_,'orelse',_,_}=E0, Bools, St0) ->
+ {op,L,'orelse',E1,E2} = right_assoc(E0, 'orelse', St0),
Anno = lineno_anno(L, St0),
{#c_var{name=V0},St} = new_var(Anno, St0),
V = {var,L,V0},
@@ -920,8 +922,9 @@ try_exception(Ecs0, St0) ->
%% Note that Tag is not needed for rethrow - it is already in Info.
{Evs,St1} = new_vars(3, St0), % Tag, Value, Info
{Ecs1,Ceps,St2} = clauses(Ecs0, St1),
+ Ecs2 = try_build_stacktrace(Ecs1, hd(Evs)),
[_,Value,Info] = Evs,
- LA = case Ecs1 of
+ LA = case Ecs2 of
[] -> [];
[C|_] -> get_lineno_anno(C)
end,
@@ -930,7 +933,7 @@ try_exception(Ecs0, St0) ->
body=[#iprimop{anno=#a{}, %Must have an #a{}
name=#c_literal{val=raise},
args=[Info,Value]}]},
- Hs = [#icase{anno=#a{anno=LA},args=[c_tuple(Evs)],clauses=Ecs1,fc=Ec}],
+ Hs = [#icase{anno=#a{anno=LA},args=[c_tuple(Evs)],clauses=Ecs2,fc=Ec}],
{Evs,Ceps++Hs,St2}.
try_after(As, St0) ->
@@ -946,6 +949,25 @@ try_after(As, St0) ->
Hs = [#icase{anno=#a{},args=[c_tuple(Evs)],clauses=[],fc=Ec}],
{Evs,Hs,St1}.
+try_build_stacktrace([#iclause{pats=Ps0,body=B0}=C0|Cs], RawStk) ->
+ [#c_tuple{es=[Class,Exc,Stk]}=Tup] = Ps0,
+ case Stk of
+ #c_var{name='_'} ->
+ %% Stacktrace variable is not used. Nothing to do.
+ [C0|try_build_stacktrace(Cs, RawStk)];
+ _ ->
+ %% Add code to build the stacktrace.
+ Ps = [Tup#c_tuple{es=[Class,Exc,RawStk]}],
+ Call = #iprimop{anno=#a{},
+ name=#c_literal{val=build_stacktrace},
+ args=[RawStk]},
+ Iset = #iset{var=Stk,arg=Call},
+ B = [Iset|B0],
+ C = C0#iclause{pats=Ps,body=B},
+ [C|try_build_stacktrace(Cs, RawStk)]
+ end;
+try_build_stacktrace([], _) -> [].
+
%% expr_bin([ArgExpr], St) -> {[Arg],[PreExpr],St}.
%% Flatten the arguments of a bin. Do this straight left to right!
%% Note that ibinary needs to have its annotation wrapped in a #a{}
@@ -1132,7 +1154,7 @@ fun_tq(Cs0, L, St0, NameInfo) ->
%% lc_tq(Line, Exp, [Qualifier], Mc, State) -> {LetRec,[PreExp],State}.
%% This TQ from Simon PJ pp 127-138.
-lc_tq(Line, E, [#igen{anno=GAnno,ceps=Ceps,
+lc_tq(Line, E, [#igen{anno=#a{anno=GA}=GAnno,ceps=Ceps,
acc_pat=AccPat,acc_guard=AccGuard,
skip_pat=SkipPat,tail=Tail,tail_pat=TailPat,
arg={Pre,Arg}}|Qs], Mc, St0) ->
@@ -1142,7 +1164,7 @@ lc_tq(Line, E, [#igen{anno=GAnno,ceps=Ceps,
F = #c_var{anno=LA,name={Name,1}},
Nc = #iapply{anno=GAnno,op=F,args=[Tail]},
{Var,St2} = new_var(St1),
- Fc = function_clause([Var], LA, {Name,1}),
+ Fc = function_clause([Var], GA, {Name,1}),
TailClause = #iclause{anno=LAnno,pats=[TailPat],guard=[],body=[Mc]},
Cs0 = case {AccPat,AccGuard} of
{SkipPat,[]} ->
@@ -1165,9 +1187,9 @@ lc_tq(Line, E, [#igen{anno=GAnno,ceps=Ceps,
body=Lps ++ [Lc]}|Cs0],
St3}
end,
- Fun = #ifun{anno=LAnno,id=[],vars=[Var],clauses=Cs,fc=Fc},
- {#iletrec{anno=LAnno#a{anno=[list_comprehension|LA]},defs=[{{Name,1},Fun}],
- body=Pre ++ [#iapply{anno=LAnno,op=F,args=[Arg]}]},
+ Fun = #ifun{anno=GAnno,id=[],vars=[Var],clauses=Cs,fc=Fc},
+ {#iletrec{anno=GAnno#a{anno=[list_comprehension|GA]},defs=[{{Name,1},Fun}],
+ body=Pre ++ [#iapply{anno=GAnno,op=F,args=[Arg]}]},
Ceps,St4};
lc_tq(Line, E, [#ifilter{}=Filter|Qs], Mc, St) ->
filter_tq(Line, E, Filter, Mc, St, Qs, fun lc_tq/5);
@@ -1481,7 +1503,7 @@ bc_initial_size(E0, Q, St0) ->
end.
bc_elem_size({bin,_,El}, St0) ->
- case bc_elem_size_1(El, 0, []) of
+ case bc_elem_size_1(El, ordsets:new(), 0, []) of
{Bits,[]} ->
{#c_literal{val=Bits},[],[],St0};
{Bits,Vars0} ->
@@ -1495,19 +1517,33 @@ bc_elem_size(_, _) ->
throw(impossible).
bc_elem_size_1([{bin_element,_,{string,_,String},{integer,_,N},_}=El|Es],
- Bits, Vars) ->
- U = get_unit(El),
- bc_elem_size_1(Es, Bits+U*N*length(String), Vars);
-bc_elem_size_1([{bin_element,_,_,{integer,_,N},_}=El|Es], Bits, Vars) ->
+ DefVars, Bits, SizeVars) ->
U = get_unit(El),
- bc_elem_size_1(Es, Bits+U*N, Vars);
-bc_elem_size_1([{bin_element,_,_,{var,_,Var},_}=El|Es], Bits, Vars) ->
+ bc_elem_size_1(Es, DefVars, Bits+U*N*length(String), SizeVars);
+bc_elem_size_1([{bin_element,_,Expr,{integer,_,N},_}=El|Es],
+ DefVars0, Bits, SizeVars) ->
U = get_unit(El),
- bc_elem_size_1(Es, Bits, [{U,#c_var{name=Var}}|Vars]);
-bc_elem_size_1([_|_], _, _) ->
+ DefVars = bc_elem_size_def_var(Expr, DefVars0),
+ bc_elem_size_1(Es, DefVars, Bits+U*N, SizeVars);
+bc_elem_size_1([{bin_element,_,Expr,{var,_,Src},_}=El|Es],
+ DefVars0, Bits, SizeVars) ->
+ case ordsets:is_element(Src, DefVars0) of
+ false ->
+ U = get_unit(El),
+ DefVars = bc_elem_size_def_var(Expr, DefVars0),
+ bc_elem_size_1(Es, DefVars, Bits, [{U,#c_var{name=Src}}|SizeVars]);
+ true ->
+ throw(impossible)
+ end;
+bc_elem_size_1([_|_], _, _, _) ->
throw(impossible);
-bc_elem_size_1([], Bits, Vars) ->
- {Bits,Vars}.
+bc_elem_size_1([], _DefVars, Bits, SizeVars) ->
+ {Bits,SizeVars}.
+
+bc_elem_size_def_var({var,_,Var}, DefVars) ->
+ ordsets:add_element(Var, DefVars);
+bc_elem_size_def_var(_Expr, DefVars) ->
+ DefVars.
bc_elem_size_combine([{U,V}|T], U, UVars, Acc) ->
bc_elem_size_combine(T, U, [V|UVars], Acc);
@@ -1985,7 +2021,7 @@ new_fun_name(Type, #core{fcount=C}=St) ->
%% new_var_name(State) -> {VarName,State}.
new_var_name(#core{vcount=C}=St) ->
- {list_to_atom("@c" ++ integer_to_list(C)),St#core{vcount=C + 1}}.
+ {C,St#core{vcount=C + 1}}.
%% new_var(State) -> {{var,Name},State}.
%% new_var(LineAnno, State) -> {{var,Name},State}.
@@ -2020,6 +2056,19 @@ fail_clause(Pats, Anno, Arg) ->
body=[#iprimop{anno=#a{anno=Anno},name=#c_literal{val=match_fail},
args=[Arg]}]}.
+%% Optimization for Dialyzer.
+right_assoc(E, Op, St) ->
+ case member(dialyzer, St#core.opts) of
+ true ->
+ right_assoc2(E, Op);
+ false ->
+ E
+ end.
+
+right_assoc2({op,L1,Op,{op,L2,Op,E1,E2},E3}, Op) ->
+ right_assoc2({op,L2,Op,E1,{op,L1,Op,E2,E3}}, Op);
+right_assoc2(E, _Op) -> E.
+
annotate_tuple(A, Es, St) ->
case member(dialyzer, St#core.opts) of
true ->
@@ -2462,9 +2511,11 @@ cexpr(#icase{anno=A,args=Largs,clauses=Lcs,fc=Lfc}, As, St0) ->
cexpr(#ireceive1{anno=A,clauses=Lcs}, As, St0) ->
Exp = intersection(A#a.ns, As), %Exports
{Ccs,St1} = cclauses(Lcs, Exp, St0),
+ True = #c_literal{val=true},
+ Action = core_lib:make_values(lists:duplicate(1+length(Exp), True)),
{#c_receive{anno=A#a.anno,
clauses=Ccs,
- timeout=#c_literal{val=infinity},action=#c_literal{val=true}},
+ timeout=#c_literal{val=infinity},action=Action},
Exp,A#a.us,St1};
cexpr(#ireceive2{anno=A,clauses=Lcs,timeout=Lto,action=Les}, As, St0) ->
Exp = intersection(A#a.ns, As), %Exports
@@ -2505,8 +2556,46 @@ cexpr(#ifun{anno=#a{us=Us0}=A0,name={named,Name},fc=#iclause{pats=Ps}}=Fun0,
end;
cexpr(#iapply{anno=A,op=Op,args=Args}, _As, St) ->
{#c_apply{anno=A#a.anno,op=Op,args=Args},[],A#a.us,St};
-cexpr(#icall{anno=A,module=Mod,name=Name,args=Args}, _As, St) ->
- {#c_call{anno=A#a.anno,module=Mod,name=Name,args=Args},[],A#a.us,St};
+cexpr(#icall{anno=A,module=Mod,name=Name,args=Args}, _As, St0) ->
+ Anno = A#a.anno,
+ case (not cerl:is_c_atom(Mod)) andalso member(tuple_calls, St0#core.opts) of
+ true ->
+ GenAnno = [compiler_generated|Anno],
+
+ %% Generate the clause that matches on the tuple
+ {TupleVar,St1} = new_var(GenAnno, St0),
+ {TupleSizeVar, St2} = new_var(GenAnno, St1),
+ {TupleModVar, St3} = new_var(GenAnno, St2),
+ {TupleArgsVar, St4} = new_var(GenAnno, St3),
+ TryVar = cerl:c_var('Try'),
+
+ TupleGuardExpr =
+ cerl:c_let([TupleSizeVar],
+ c_call_erl(tuple_size, [TupleVar]),
+ c_call_erl('>', [TupleSizeVar, cerl:c_int(0)])),
+
+ TupleGuard =
+ cerl:c_try(TupleGuardExpr, [TryVar], TryVar,
+ [cerl:c_var('T'),cerl:c_var('R')], cerl:c_atom(false)),
+
+ TupleApply =
+ cerl:c_let([TupleModVar],
+ c_call_erl(element, [cerl:c_int(1),TupleVar]),
+ cerl:c_let([TupleArgsVar],
+ cerl:make_list(Args ++ [TupleVar]),
+ c_call_erl(apply, [TupleModVar,Name,TupleArgsVar]))),
+
+ TupleClause = cerl:ann_c_clause(GenAnno, [TupleVar], TupleGuard, TupleApply),
+
+ %% Generate the fallback clause
+ {OtherVar,St5} = new_var(GenAnno, St4),
+ OtherApply = cerl:ann_c_call(GenAnno, OtherVar, Name, Args),
+ OtherClause = cerl:ann_c_clause(GenAnno, [OtherVar], OtherApply),
+
+ {cerl:ann_c_case(GenAnno, Mod, [TupleClause,OtherClause]),[],A#a.us,St5};
+ false ->
+ {#c_call{anno=Anno,module=Mod,name=Name,args=Args},[],A#a.us,St0}
+ end;
cexpr(#iprimop{anno=A,name=Name,args=Args}, _As, St) ->
{#c_primop{anno=A#a.anno,name=Name,args=Args},[],A#a.us,St};
cexpr(#iprotect{anno=A,body=Es}, _As, St0) ->
@@ -2536,6 +2625,9 @@ cfun(#ifun{anno=A,id=Id,vars=Args,clauses=Lcs,fc=Lfc}, _As, St0) ->
clauses=Ccs ++ [Cfc]}},
[],A#a.us,St2}.
+c_call_erl(Fun, Args) ->
+ cerl:c_call(cerl:c_atom(erlang), cerl:c_atom(Fun), Args).
+
%% lit_vars(Literal) -> [Var].
lit_vars(Lit) -> lit_vars(Lit, []).
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index 1fc05109c5..aef0b6cc9f 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -82,7 +82,8 @@
-export([module/2,format_error/1]).
-import(lists, [map/2,foldl/3,foldr/3,mapfoldl/3,splitwith/2,member/2,
- keymember/3,keyfind/3,partition/2,droplast/1,last/1,sort/1]).
+ keymember/3,keyfind/3,partition/2,droplast/1,last/1,sort/1,
+ reverse/1]).
-import(ordsets, [add_element/2,del_element/2,union/2,union/1,subtract/2]).
-import(cerl, [c_tuple/1]).
@@ -107,6 +108,7 @@ copy_anno(Kdst, Ksrc) ->
-record(iclause, {anno=[],isub,osub,pats,guard,body}).
-record(ireceive_accept, {anno=[],arg}).
-record(ireceive_next, {anno=[],arg}).
+-record(ignored, {anno=[]}).
-type warning() :: term(). % XXX: REFINE
@@ -155,20 +157,23 @@ include_attribute(_) -> true.
function({#c_var{name={F,Arity}=FA},Body}, St0) ->
%%io:format("~w/~w~n", [F,Arity]),
try
- St1 = St0#kern{func=FA,ff=undefined,vcount=0,fcount=0,ds=cerl_sets:new()},
+ %% Find a suitable starting value for the variable counter. Note
+ %% that this pass assumes that new_var_name/1 returns a variable
+ %% name distinct from any variable used in the entire body of
+ %% the function. We use integers as variable names to avoid
+ %% filling up the atom table when compiling huge functions.
+ Count = cerl_trees:next_free_variable_name(Body),
+ St1 = St0#kern{func=FA,ff=undefined,vcount=Count,fcount=0,ds=cerl_sets:new()},
{#ifun{anno=Ab,vars=Kvs,body=B0},[],St2} = expr(Body, new_sub(), St1),
{B1,_,St3} = ubody(B0, return, St2),
%%B1 = B0, St3 = St2, %Null second pass
- {#k_fdef{anno=#k{us=[],ns=[],a=Ab},
- func=F,arity=Arity,vars=Kvs,body=B1},St3}
+ {make_fdef(#k{us=[],ns=[],a=Ab}, F, Arity, Kvs, B1),St3}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [F,Arity]),
erlang:raise(Class, Error, Stack)
end.
-
%% body(Cexpr, Sub, State) -> {Kexpr,[PreKepxr],State}.
%% Do the main sequence of a body. A body ends in an atomic value or
%% values. Must check if vector first so do expr.
@@ -489,7 +494,7 @@ make_alt(First0, Then0) ->
Then1 = pre_seq(droplast(Then0), last(Then0)),
First2 = make_protected(First1),
Then2 = make_protected(Then1),
- Body = #k_atom{val=ignored},
+ Body = #ignored{},
First3 = #k_guard_clause{guard=First2,body=Body},
Then3 = #k_guard_clause{guard=Then2,body=Body},
First = #k_guard{clauses=[First3]},
@@ -1356,7 +1361,7 @@ new_fun_name(Type, #kern{func={F,Arity},fcount=C}=St) ->
%% new_var_name(State) -> {VarName,State}.
new_var_name(#kern{vcount=C}=St) ->
- {list_to_atom("@k" ++ integer_to_list(C)),St#kern{vcount=C+1}}.
+ {C,St#kern{vcount=C+1}}.
%% new_var(State) -> {#k_var{},State}.
@@ -1589,23 +1594,18 @@ match_var([U|Us], Cs0, Def, St) ->
%% according to type, the order is really irrelevant but tries to be
%% smart.
-match_con(Us, [C], Def, St) ->
- %% There is only one clause. We can keep literal tuples and
- %% lists, but we must convert []/integer/float/atom literals
- %% to the proper record (#k_nil{} and so on).
- Cs = [expand_pat_lit_clause(C, false)],
- match_con_1(Us, Cs, Def, St);
match_con(Us, Cs0, Def, St) ->
- %% More than one clause. Remove literals at the top level.
- Cs = [expand_pat_lit_clause(C, true) || C <- Cs0],
+ %% Expand literals at the top level.
+ Cs = [expand_pat_lit_clause(C) || C <- Cs0],
match_con_1(Us, Cs, Def, St).
match_con_1([U|_Us] = L, Cs, Def, St0) ->
%% Extract clauses for different constructors (types).
%%ok = io:format("match_con ~p~n", [Cs]),
- Ttcs = select_types([k_binary], Cs) ++ select_bin_con(Cs) ++
- select_types([k_cons,k_tuple,k_map,k_atom,k_float,k_int,
- k_nil,k_literal], Cs),
+ Ttcs0 = select_types([k_binary], Cs) ++ select_bin_con(Cs) ++
+ select_types([k_cons,k_tuple,k_map,k_atom,k_float,
+ k_int,k_nil], Cs),
+ Ttcs = opt_single_valued(Ttcs0),
%%ok = io:format("ttcs = ~p~n", [Ttcs]),
{Scs,St1} =
mapfoldl(fun ({T,Tcs}, St) ->
@@ -1618,28 +1618,14 @@ match_con_1([U|_Us] = L, Cs, Def, St0) ->
select_types(Types, Cs) ->
[{T,Tcs} || T <- Types, begin Tcs = select(T, Cs), Tcs =/= [] end].
-
-expand_pat_lit_clause(#iclause{pats=[#ialias{pat=#k_literal{anno=A,val=Val}}=Alias|Ps]}=C, B) ->
- P = case B of
- true -> expand_pat_lit(Val, A);
- false -> literal(Val, A)
- end,
+
+expand_pat_lit_clause(#iclause{pats=[#ialias{pat=#k_literal{anno=A,val=Val}}=Alias|Ps]}=C) ->
+ P = expand_pat_lit(Val, A),
C#iclause{pats=[Alias#ialias{pat=P}|Ps]};
-expand_pat_lit_clause(#iclause{pats=[#k_literal{anno=A,val=Val}|Ps]}=C, B) ->
- P = case B of
- true -> expand_pat_lit(Val, A);
- false -> literal(Val, A)
- end,
+expand_pat_lit_clause(#iclause{pats=[#k_literal{anno=A,val=Val}|Ps]}=C) ->
+ P = expand_pat_lit(Val, A),
C#iclause{pats=[P|Ps]};
-expand_pat_lit_clause(#iclause{pats=[#k_binary{anno=A,segs=#k_bin_end{}}|Ps]}=C, B) ->
- case B of
- true ->
- C;
- false ->
- P = #k_literal{anno=A,val = <<>>},
- C#iclause{pats=[P|Ps]}
- end;
-expand_pat_lit_clause(C, _) -> C.
+expand_pat_lit_clause(C) -> C.
expand_pat_lit([H|T], A) ->
#k_cons{anno=A,hd=literal(H, A),tl=literal(T, A)};
@@ -1659,6 +1645,107 @@ literal(Val, A) when is_atom(Val) ->
literal(Val, A) when is_list(Val); is_tuple(Val) ->
#k_literal{anno=A,val=Val}.
+%% opt_singled_valued([{Type,Clauses}]) -> [{Type,Clauses}].
+%% If a type only has one clause and if the pattern is literal,
+%% the matching can be done more efficiently by directly comparing
+%% with the literal (that is especially true for binaries).
+
+opt_single_valued(Ttcs) ->
+ opt_single_valued(Ttcs, [], []).
+
+opt_single_valued([{_,[#iclause{pats=[P0|Ps]}=Tc]}=Ttc|Ttcs], TtcAcc, LitAcc) ->
+ try combine_lit_pat(P0) of
+ P ->
+ LitTtc = Tc#iclause{pats=[P|Ps]},
+ opt_single_valued(Ttcs, TtcAcc, [LitTtc|LitAcc])
+ catch
+ not_possible ->
+ opt_single_valued(Ttcs, [Ttc|TtcAcc], LitAcc)
+ end;
+opt_single_valued([Ttc|Ttcs], TtcAcc, LitAcc) ->
+ opt_single_valued(Ttcs, [Ttc|TtcAcc], LitAcc);
+opt_single_valued([], TtcAcc, []) ->
+ reverse(TtcAcc);
+opt_single_valued([], TtcAcc, LitAcc) ->
+ Literals = {k_literal,reverse(LitAcc)},
+ %% Test the literals as early as possible.
+ case reverse(TtcAcc) of
+ [{k_binary,_}=Bin|Ttcs] ->
+ %% The delayed creation of sub binaries requires
+ %% bs_start_match2 to be the first instruction in the
+ %% function.
+ [Bin,Literals|Ttcs];
+ Ttcs ->
+ [Literals|Ttcs]
+ end.
+
+combine_lit_pat(#ialias{pat=Pat0}=Alias) ->
+ Pat = combine_lit_pat(Pat0),
+ Alias#ialias{pat=Pat};
+combine_lit_pat(Pat) ->
+ case do_combine_lit_pat(Pat) of
+ #k_literal{val=Val} when is_atom(Val) ->
+ throw(not_possible);
+ #k_literal{val=Val} when is_number(Val) ->
+ throw(not_possible);
+ #k_literal{val=[]} ->
+ throw(not_possible);
+ #k_literal{}=Lit ->
+ Lit
+ end.
+
+do_combine_lit_pat(#k_atom{anno=A,val=Val}) ->
+ #k_literal{anno=A,val=Val};
+do_combine_lit_pat(#k_float{anno=A,val=Val}) ->
+ #k_literal{anno=A,val=Val};
+do_combine_lit_pat(#k_int{anno=A,val=Val}) ->
+ #k_literal{anno=A,val=Val};
+do_combine_lit_pat(#k_nil{anno=A}) ->
+ #k_literal{anno=A,val=[]};
+do_combine_lit_pat(#k_binary{anno=A,segs=Segs}) ->
+ Bin = combine_bin_segs(Segs),
+ #k_literal{anno=A,val=Bin};
+do_combine_lit_pat(#k_cons{anno=A,hd=Hd0,tl=Tl0}) ->
+ #k_literal{val=Hd} = do_combine_lit_pat(Hd0),
+ #k_literal{val=Tl} = do_combine_lit_pat(Tl0),
+ #k_literal{anno=A,val=[Hd|Tl]};
+do_combine_lit_pat(#k_literal{}=Lit) ->
+ Lit;
+do_combine_lit_pat(#k_tuple{anno=A,es=Es0}) ->
+ Es = [begin
+ #k_literal{val=Lit} = do_combine_lit_pat(El),
+ Lit
+ end || El <- Es0],
+ #k_literal{anno=A,val=list_to_tuple(Es)};
+do_combine_lit_pat(_) ->
+ throw(not_possible).
+
+combine_bin_segs(#k_bin_seg{size=Size0,unit=Unit,type=integer,
+ flags=[unsigned,big],seg=Seg,next=Next}) ->
+ #k_literal{val=Size1} = do_combine_lit_pat(Size0),
+ #k_literal{val=Int} = do_combine_lit_pat(Seg),
+ Size = Size1 * Unit,
+ if
+ 0 < Size, Size < 64 ->
+ Bin = <<Int:Size>>,
+ case Bin of
+ <<Int:Size>> ->
+ NextBin = combine_bin_segs(Next),
+ <<Bin/bits,NextBin/bits>>;
+ _ ->
+ %% The integer Int does not fit in the segment,
+ %% thus it will not match.
+ throw(not_possible)
+ end;
+ true ->
+ %% Avoid creating huge binary literals.
+ throw(not_possible)
+ end;
+combine_bin_segs(#k_bin_end{}) ->
+ <<>>;
+combine_bin_segs(_) ->
+ throw(not_possible).
+
%% select_bin_con([Clause]) -> [{Type,[Clause]}].
%% Extract clauses for the k_bin_seg constructor. As k_bin_seg
%% matching can overlap, the k_bin_seg constructors cannot be
@@ -2143,7 +2230,9 @@ ubody(E, return, St0) ->
{Ea,Pa,St1} = force_atomic(E, St0),
ubody(pre_seq(Pa, #ivalues{args=[Ea]}), return, St1)
end;
-ubody(E, {break,_Rs} = Break, St0) ->
+ubody(#ignored{}, {break,_} = Break, St) ->
+ ubody(#ivalues{args=[]}, Break, St);
+ubody(E, {break,[_]} = Break, St0) ->
%%ok = io:fwrite("ubody ~w:~p~n", [?LINE,{E,Br}]),
%% Exiting expressions need no trailing break.
case is_exit_expr(E) of
@@ -2151,6 +2240,16 @@ ubody(E, {break,_Rs} = Break, St0) ->
false ->
{Ea,Pa,St1} = force_atomic(E, St0),
ubody(pre_seq(Pa, #ivalues{args=[Ea]}), Break, St1)
+ end;
+ubody(E, {break,Rs}=Break, St0) ->
+ case is_exit_expr(E) of
+ true ->
+ uexpr(E, return, St0);
+ false ->
+ {Vs,St1} = new_vars(length(Rs), St0),
+ Iset = #iset{vars=Vs,arg=E},
+ PreSeq = pre_seq([Iset], #ivalues{args=Vs}),
+ ubody(PreSeq, Break, St1)
end.
iletrec_funs(#iletrec{defs=Fs}, St0) ->
@@ -2179,9 +2278,8 @@ iletrec_funs_gen(Fs, FreeVs, St) ->
Arity0 = length(Vs),
{Fb1,_,Lst1} = ubody(Fb0, return, Lst0#kern{ff={N,Arity0}}),
Arity = Arity0 + length(FreeVs),
- Fun = #k_fdef{anno=#k{us=[],ns=[],a=Fa},
- func=N,arity=Arity,
- vars=Vs ++ FreeVs,body=Fb1},
+ Fun = make_fdef(#k{us=[],ns=[],a=Fa}, N, Arity,
+ Vs++FreeVs, Fb1),
Lst1#kern{funs=[Fun|Lst1#kern.funs]}
end, St, Fs).
@@ -2284,12 +2382,11 @@ uexpr(#k_try{anno=A,arg=A0,vars=Vs,body=B0,evars=Evs,handler=H0},
{A1,Au,St2} = ubody(A0, {break,Avs}, St1),
{B1,Bu,St3} = ubody(B0, Br, St2),
{H1,Hu,St4} = ubody(H0, Br, St3),
- {Rs1,St5} = ensure_return_vars(Rs0, St4),
Used = union([Au,subtract(Bu, lit_list_vars(Vs)),
subtract(Hu, lit_list_vars(Evs))]),
- {#k_try{anno=#k{us=Used,ns=lit_list_vars(Rs1),a=A},
- arg=A1,vars=Vs,body=B1,evars=Evs,handler=H1,ret=Rs1},
- Used,St5}
+ {#k_try{anno=#k{us=Used,ns=lit_list_vars(Rs0),a=A},
+ arg=A1,vars=Vs,body=B1,evars=Evs,handler=H1,ret=Rs0},
+ Used,St4}
end;
uexpr(#k_try{anno=A,arg=A0,vars=Vs,body=B0,evars=Evs,handler=H0},
return, St0) ->
@@ -2297,13 +2394,11 @@ uexpr(#k_try{anno=A,arg=A0,vars=Vs,body=B0,evars=Evs,handler=H0},
{A1,Au,St2} = ubody(A0, {break,Avs}, St1), %Must break to clean up here!
{B1,Bu,St3} = ubody(B0, return, St2),
{H1,Hu,St4} = ubody(H0, return, St3),
- NumNew = 1,
- {Ns,St5} = new_vars(NumNew, St4),
Used = union([Au,subtract(Bu, lit_list_vars(Vs)),
subtract(Hu, lit_list_vars(Evs))]),
- {#k_try_enter{anno=#k{us=Used,ns=Ns,a=A},
+ {#k_try_enter{anno=#k{us=Used,ns=[],a=A},
arg=A1,vars=Vs,body=B1,evars=Evs,handler=H1},
- Used,St5};
+ Used,St4};
uexpr(#k_catch{anno=A,body=B0}, {break,Rs0}, St0) ->
{Rb,St1} = new_var(St0),
{B1,Bu,St2} = ubody(B0, {break,[Rb]}, St1),
@@ -2325,8 +2420,7 @@ uexpr(#ifun{anno=A,vars=Vs,body=B0}, {break,Rs}, St0) ->
%% No id annotation. Must invent a fun name.
new_fun_name(St1)
end,
- Fun = #k_fdef{anno=#k{us=[],ns=[],a=A},func=Fname,arity=Arity,
- vars=Vs ++ Fvs,body=B1},
+ Fun = make_fdef(#k{us=[],ns=[],a=A}, Fname, Arity, Vs++Fvs, B1),
{#k_bif{anno=#k{us=Free,ns=lit_list_vars(Rs),a=A},
op=#k_internal{name=make_fun,arity=length(Free)+2},
args=[#k_atom{val=Fname},#k_int{val=Arity}|Fvs],
@@ -2343,6 +2437,16 @@ uexpr(Lit, {break,Rs0}, St0) ->
add_local_function(_, #kern{funs=ignore}=St) -> St;
add_local_function(F, #kern{funs=Funs}=St) -> St#kern{funs=[F|Funs]}.
+%% Make a #k_fdef{}, making sure that the body is always a #k_match{}.
+make_fdef(Anno, Name, Arity, Vs, #k_match{}=Body) ->
+ #k_fdef{anno=Anno,func=Name,arity=Arity,vars=Vs,body=Body};
+make_fdef(Anno, Name, Arity, Vs, Body) ->
+ Ka = get_kanno(Body),
+ Match = #k_match{anno=#k{us=Ka#k.us,ns=[],a=Ka#k.a},
+ vars=Vs,body=Body,ret=[]},
+ #k_fdef{anno=Anno,func=Name,arity=Arity,vars=Vs,body=Match}.
+
+
%% handle_reuse_annos([#k_var{}], State) -> State.
%% In general, it is only safe to reuse a variable for a match context
%% if the original value of the variable will no longer be needed.
diff --git a/lib/compiler/src/v3_kernel.hrl b/lib/compiler/src/v3_kernel.hrl
index 7cd30b25a8..e6f0d3c1f7 100644
--- a/lib/compiler/src/v3_kernel.hrl
+++ b/lib/compiler/src/v3_kernel.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/compiler/src/v3_kernel_pp.erl b/lib/compiler/src/v3_kernel_pp.erl
index 53097d0d7d..c12c301ee2 100644
--- a/lib/compiler/src/v3_kernel_pp.erl
+++ b/lib/compiler/src/v3_kernel_pp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -248,7 +248,7 @@ format_1(#k_put{arg=A,ret=Rs}, Ctxt) ->
[format(A, Ctxt),
format_ret(Rs, ctxt_bump_indent(Ctxt, 1))
];
-format_1(#k_try{arg=A,vars=Vs,body=B,evars=Evs,handler=H}, Ctxt) ->
+format_1(#k_try{arg=A,vars=Vs,body=B,evars=Evs,handler=H,ret=Rs}, Ctxt) ->
Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.body_indent),
["try",
nl_indent(Ctxt1),
@@ -264,7 +264,8 @@ format_1(#k_try{arg=A,vars=Vs,body=B,evars=Evs,handler=H}, Ctxt) ->
nl_indent(Ctxt1),
format(H, Ctxt1),
nl_indent(Ctxt),
- "end"
+ "end",
+ format_ret(Rs, Ctxt)
];
format_1(#k_try_enter{arg=A,vars=Vs,body=B,evars=Evs,handler=H}, Ctxt) ->
Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.body_indent),
@@ -491,7 +492,7 @@ indent(Ctxt) -> indent(Ctxt#ctxt.indent, Ctxt).
indent(N, _Ctxt) when N =< 0 -> "";
indent(N, Ctxt) ->
T = Ctxt#ctxt.tab_width,
- string:chars($\t, N div T, string:chars($\s, N rem T)).
+ lists:duplicate(N div T, $\t) ++ lists:duplicate(N rem T, $\s).
nl_indent(Ctxt) -> [$\n|indent(Ctxt)].
@@ -508,7 +509,7 @@ unindent([$\t|T], N, Ctxt, C) ->
if N >= Tab ->
unindent(T, N - Tab, Ctxt, C);
true ->
- unindent([string:chars($\s, Tab - N)|T], 0, Ctxt, C)
+ unindent([lists:duplicate(Tab - N, $\s)|T], 0, Ctxt, C)
end;
unindent([L|T], N, Ctxt, C) when is_list(L) ->
unindent(L, N, Ctxt, [T|C]);
diff --git a/lib/compiler/src/v3_life.erl b/lib/compiler/src/v3_life.erl
deleted file mode 100644
index be3ade47ff..0000000000
--- a/lib/compiler/src/v3_life.erl
+++ /dev/null
@@ -1,468 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%% Purpose : Convert annotated kernel expressions to annotated beam format.
-
-%% This module creates beam format annotated with variable lifetime
-%% information. Each thing is given an index and for each variable we
-%% store the first and last index for its occurrence. The variable
-%% database, VDB, attached to each thing is only relevant internally
-%% for that thing.
-%%
-%% For nested things like matches the numbering continues locally and
-%% the VDB for that thing refers to the variable usage within that
-%% thing. Variables which live through a such a thing are internally
-%% given a very large last index. Internally the indexes continue
-%% after the index of that thing. This creates no problems as the
-%% internal variable info never escapes and externally we only see
-%% variable which are alive both before or after.
-%%
-%% This means that variables never "escape" from a thing and the only
-%% way to get values from a thing is to "return" them, with 'break' or
-%% 'return'. Externally these values become the return values of the
-%% thing. This is no real limitation as most nested things have
-%% multiple threads so working out a common best variable usage is
-%% difficult.
-
--module(v3_life).
-
--export([module/2]).
-
--export([vdb_find/2]).
-
--import(lists, [member/2,map/2,reverse/1,sort/1]).
--import(ordsets, [add_element/2,intersection/2,union/2]).
-
--include("v3_kernel.hrl").
--include("v3_life.hrl").
-
--type fa() :: {atom(),arity()}.
-
-%% These are not defined in v3_kernel.hrl.
-get_kanno(Kthing) -> element(2, Kthing).
-%%set_kanno(Kthing, Anno) -> setelement(2, Kthing, Anno).
-
--spec module(#k_mdef{}, [compile:option()]) ->
- {'ok',{module(),[fa()],[_],[_]}}.
-
-module(#k_mdef{name=M,exports=Es,attributes=As,body=Fs0}, _Opts) ->
- Fs1 = functions(Fs0, []),
- {ok,{M,Es,As,Fs1}}.
-
-functions([F|Fs], Acc) ->
- functions(Fs, [function(F)|Acc]);
-functions([], Acc) -> reverse(Acc).
-
-%% function(Kfunc) -> Func.
-
-function(#k_fdef{anno=#k{a=Anno},func=F,arity=Ar,vars=Vs,body=Kb}) ->
- try
- As = var_list(Vs),
- Vdb0 = init_vars(As),
- %% Force a top-level match!
- B0 = case Kb of
- #k_match{} -> Kb;
- _ ->
- Ka = get_kanno(Kb),
- #k_match{anno=#k{us=Ka#k.us,ns=[],a=Ka#k.a},
- vars=Vs,body=Kb,ret=[]}
- end,
- {B1,_,Vdb1} = body(B0, 1, Vdb0),
- {function,F,Ar,As,B1,Vdb1,Anno}
- catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
- io:fwrite("Function: ~w/~w\n", [F,Ar]),
- erlang:raise(Class, Error, Stack)
- end.
-
-%% body(Kbody, I, Vdb) -> {[Expr],MaxI,Vdb}.
-%% Handle a body.
-
-body(#k_seq{arg=Ke,body=Kb}, I, Vdb0) ->
- %%ok = io:fwrite("life ~w:~p~n", [?LINE,{Ke,I,Vdb0}]),
- A = get_kanno(Ke),
- Vdb1 = use_vars(union(A#k.us, A#k.ns), I, Vdb0),
- {Es,MaxI,Vdb2} = body(Kb, I+1, Vdb1),
- E = expr(Ke, I, Vdb2),
- {[E|Es],MaxI,Vdb2};
-body(Ke, I, Vdb0) ->
- %%ok = io:fwrite("life ~w:~p~n", [?LINE,{Ke,I,Vdb0}]),
- A = get_kanno(Ke),
- Vdb1 = use_vars(union(A#k.us, A#k.ns), I, Vdb0),
- E = expr(Ke, I, Vdb1),
- {[E],I,Vdb1}.
-
-%% protected(Kprotected, I, Vdb) -> Protected.
-%% Only used in guards.
-
-protected(#k_protected{anno=A,arg=Ts,ret=Rs}, I, Vdb) ->
- %% Lock variables that are alive before try and used afterwards.
- %% Don't lock variables that are only used inside the protected
- %% expression.
- Pdb0 = vdb_sub(I, I+1, Vdb),
- {T,MaxI,Pdb1} = body(Ts, I+1, Pdb0),
- Pdb2 = use_vars(A#k.ns, MaxI+1, Pdb1), %Save "return" values
- #l{ke={protected,T,var_list(Rs)},i=I,a=A#k.a,vdb=Pdb2}.
-
-%% expr(Kexpr, I, Vdb) -> Expr.
-
-expr(#k_test{anno=A,op=Op,args=As,inverted=Inverted}, I, _Vdb) ->
- #l{ke={test,test_op(Op),atomic_list(As),Inverted},i=I,a=A#k.a};
-expr(#k_call{anno=A,op=Op,args=As,ret=Rs}, I, _Vdb) ->
- #l{ke={call,call_op(Op),atomic_list(As),var_list(Rs)},i=I,a=A#k.a};
-expr(#k_enter{anno=A,op=Op,args=As}, I, _Vdb) ->
- #l{ke={enter,call_op(Op),atomic_list(As)},i=I,a=A#k.a};
-expr(#k_bif{anno=A,op=Op,args=As,ret=Rs}, I, _Vdb) ->
- Bif = k_bif(A, Op, As, Rs),
- #l{ke=Bif,i=I,a=A#k.a};
-expr(#k_match{anno=A,body=Kb,ret=Rs}, I, Vdb) ->
- %% Work out imported variables which need to be locked.
- Mdb = vdb_sub(I, I+1, Vdb),
- M = match(Kb, A#k.us, I+1, [], Mdb),
- #l{ke={match,M,var_list(Rs)},i=I,vdb=use_vars(A#k.us, I+1, Mdb),a=A#k.a};
-expr(#k_guard_match{anno=A,body=Kb,ret=Rs}, I, Vdb) ->
- %% Work out imported variables which need to be locked.
- Mdb = vdb_sub(I, I+1, Vdb),
- M = match(Kb, A#k.us, I+1, [], Mdb),
- #l{ke={guard_match,M,var_list(Rs)},i=I,vdb=use_vars(A#k.us, I+1, Mdb),a=A#k.a};
-expr(#k_try{}=Try, I, Vdb) ->
- body_try(Try, I, Vdb);
-expr(#k_protected{}=Protected, I, Vdb) ->
- protected(Protected, I, Vdb);
-expr(#k_try_enter{anno=A,arg=Ka,vars=Vs,body=Kb,evars=Evs,handler=Kh}, I, Vdb) ->
- %% Lock variables that are alive before the catch and used afterwards.
- %% Don't lock variables that are only used inside the try.
- Tdb0 = vdb_sub(I, I+1, Vdb),
- %% This is the tricky bit. Lock variables in Arg that are used in
- %% the body and handler. Add try tag 'variable'.
- Ab = get_kanno(Kb),
- Ah = get_kanno(Kh),
- Tdb1 = use_vars(union(Ab#k.us, Ah#k.us), I+3, Tdb0),
- Tdb2 = vdb_sub(I, I+2, Tdb1),
- Vnames = fun (Kvar) -> Kvar#k_var.name end, %Get the variable names
- {Aes,_,Adb} = body(Ka, I+2, add_var({catch_tag,I+1}, I+1, 1000000, Tdb2)),
- {Bes,_,Bdb} = body(Kb, I+4, new_vars(sort(map(Vnames, Vs)), I+3, Tdb2)),
- {Hes,_,Hdb} = body(Kh, I+4, new_vars(sort(map(Vnames, Evs)), I+3, Tdb2)),
- #l{ke={try_enter,#l{ke={block,Aes},i=I+1,vdb=Adb,a=[]},
- var_list(Vs),#l{ke={block,Bes},i=I+3,vdb=Bdb,a=[]},
- var_list(Evs),#l{ke={block,Hes},i=I+3,vdb=Hdb,a=[]}},
- i=I,vdb=Tdb1,a=A#k.a};
-expr(#k_catch{anno=A,body=Kb,ret=[R]}, I, Vdb) ->
- %% Lock variables that are alive before the catch and used afterwards.
- %% Don't lock variables that are only used inside the catch.
- %% Add catch tag 'variable'.
- Cdb0 = vdb_sub(I, I+1, Vdb),
- {Es,_,Cdb1} = body(Kb, I+1, add_var({catch_tag,I}, I, locked, Cdb0)),
- #l{ke={'catch',Es,variable(R)},i=I,vdb=Cdb1,a=A#k.a};
-expr(#k_receive{anno=A,var=V,body=Kb,timeout=T,action=Ka,ret=Rs}, I, Vdb) ->
- %% Work out imported variables which need to be locked.
- Rdb = vdb_sub(I, I+1, Vdb),
- M = match(Kb, add_element(V#k_var.name, A#k.us), I+1, [],
- new_vars([V#k_var.name], I, Rdb)),
- {Tes,_,Adb} = body(Ka, I+1, Rdb),
- #l{ke={receive_loop,atomic(T),variable(V),M,
- #l{ke=Tes,i=I+1,vdb=Adb,a=[]},var_list(Rs)},
- i=I,vdb=use_vars(A#k.us, I+1, Vdb),a=A#k.a};
-expr(#k_receive_accept{anno=A}, I, _Vdb) ->
- #l{ke=receive_accept,i=I,a=A#k.a};
-expr(#k_receive_next{anno=A}, I, _Vdb) ->
- #l{ke=receive_next,i=I,a=A#k.a};
-expr(#k_put{anno=A,arg=Arg,ret=Rs}, I, _Vdb) ->
- #l{ke={set,var_list(Rs),literal(Arg, [])},i=I,a=A#k.a};
-expr(#k_break{anno=A,args=As}, I, _Vdb) ->
- #l{ke={break,atomic_list(As)},i=I,a=A#k.a};
-expr(#k_guard_break{anno=A,args=As}, I, Vdb) ->
- Locked = [V || {V,_,_} <- Vdb],
- #l{ke={guard_break,atomic_list(As),Locked},i=I,a=A#k.a};
-expr(#k_return{anno=A,args=As}, I, _Vdb) ->
- #l{ke={return,atomic_list(As)},i=I,a=A#k.a}.
-
-body_try(#k_try{anno=A,arg=Ka,vars=Vs,body=Kb,evars=Evs,handler=Kh,ret=Rs},
- I, Vdb) ->
- %% Lock variables that are alive before the catch and used afterwards.
- %% Don't lock variables that are only used inside the try.
- Tdb0 = vdb_sub(I, I+1, Vdb),
- %% This is the tricky bit. Lock variables in Arg that are used in
- %% the body and handler. Add try tag 'variable'.
- Ab = get_kanno(Kb),
- Ah = get_kanno(Kh),
- Tdb1 = use_vars(union(Ab#k.us, Ah#k.us), I+3, Tdb0),
- Tdb2 = vdb_sub(I, I+2, Tdb1),
- Vnames = fun (Kvar) -> Kvar#k_var.name end, %Get the variable names
- {Aes,_,Adb} = body(Ka, I+2, add_var({catch_tag,I+1}, I+1, locked, Tdb2)),
- {Bes,_,Bdb} = body(Kb, I+4, new_vars(sort(map(Vnames, Vs)), I+3, Tdb2)),
- {Hes,_,Hdb} = body(Kh, I+4, new_vars(sort(map(Vnames, Evs)), I+3, Tdb2)),
- #l{ke={'try',#l{ke={block,Aes},i=I+1,vdb=Adb,a=[]},
- var_list(Vs),#l{ke={block,Bes},i=I+3,vdb=Bdb,a=[]},
- var_list(Evs),#l{ke={block,Hes},i=I+3,vdb=Hdb,a=[]},
- var_list(Rs)},
- i=I,vdb=Tdb1,a=A#k.a}.
-
-%% call_op(Op) -> Op.
-%% test_op(Op) -> Op.
-%% Do any necessary name translations here to munge into beam format.
-
-call_op(#k_local{name=N}) -> N;
-call_op(#k_remote{mod=M,name=N}) -> {remote,atomic(M),atomic(N)};
-call_op(Other) -> variable(Other).
-
-test_op(#k_remote{mod=#k_atom{val=erlang},name=#k_atom{val=N}}) -> N.
-
-%% k_bif(Anno, Op, [Arg], [Ret], Vdb) -> Expr.
-%% Build bifs.
-
-k_bif(_A, #k_internal{name=Name}, As, Rs) ->
- {internal,Name,atomic_list(As),var_list(Rs)};
-k_bif(_A, #k_remote{mod=#k_atom{val=erlang},name=#k_atom{val=Name}}, As, Rs) ->
- Ar = length(As),
- case is_gc_bif(Name, Ar) of
- false ->
- {bif,Name,atomic_list(As),var_list(Rs)};
- true ->
- {gc_bif,Name,atomic_list(As),var_list(Rs)}
- end.
-
-%% match(Kexpr, [LockVar], I, Vdb) -> Expr.
-%% Convert match tree to old format.
-
-match(#k_alt{anno=A,first=Kf,then=Kt}, Ls, I, Ctxt, Vdb0) ->
- Vdb1 = use_vars(union(A#k.us, Ls), I, Vdb0),
- F = match(Kf, Ls, I+1, Ctxt, Vdb1),
- T = match(Kt, Ls, I+1, Ctxt, Vdb1),
- #l{ke={alt,F,T},i=I,vdb=Vdb1,a=A#k.a};
-match(#k_select{anno=A,var=V,types=Kts}, Ls0, I, Ctxt, Vdb0) ->
- Vanno = get_kanno(V),
- Ls1 = case member(no_usage, Vanno) of
- false -> add_element(V#k_var.name, Ls0);
- true -> Ls0
- end,
- Anno = case member(reuse_for_context, Vanno) of
- true -> [reuse_for_context|A#k.a];
- false -> A#k.a
- end,
- Vdb1 = use_vars(union(A#k.us, Ls1), I, Vdb0),
- Ts = [type_clause(Tc, Ls1, I+1, Ctxt, Vdb1) || Tc <- Kts],
- #l{ke={select,literal(V, Ctxt),Ts},i=I,vdb=Vdb1,a=Anno};
-match(#k_guard{anno=A,clauses=Kcs}, Ls, I, Ctxt, Vdb0) ->
- Vdb1 = use_vars(union(A#k.us, Ls), I, Vdb0),
- Cs = [guard_clause(G, Ls, I+1, Ctxt, Vdb1) || G <- Kcs],
- #l{ke={guard,Cs},i=I,vdb=Vdb1,a=A#k.a};
-match(Other, Ls, I, _Ctxt, Vdb0) ->
- Vdb1 = use_vars(Ls, I, Vdb0),
- {B,_,Vdb2} = body(Other, I+1, Vdb1),
- #l{ke={block,B},i=I,vdb=Vdb2,a=[]}.
-
-type_clause(#k_type_clause{anno=A,type=T,values=Kvs}, Ls, I, Ctxt, Vdb0) ->
- %%ok = io:format("life ~w: ~p~n", [?LINE,{T,Kvs}]),
- Vdb1 = use_vars(union(A#k.us, Ls), I+1, Vdb0),
- Vs = [val_clause(Vc, Ls, I+1, Ctxt, Vdb1) || Vc <- Kvs],
- #l{ke={type_clause,type(T),Vs},i=I,vdb=Vdb1,a=A#k.a}.
-
-val_clause(#k_val_clause{anno=A,val=V,body=Kb}, Ls0, I, Ctxt0, Vdb0) ->
- New = (get_kanno(V))#k.ns,
- Bus = (get_kanno(Kb))#k.us,
- %%ok = io:format("Ls0 = ~p, Used=~p\n New=~p, Bus=~p\n", [Ls0,Used,New,Bus]),
- Ls1 = union(intersection(New, Bus), Ls0), %Lock for safety
- Vdb1 = use_vars(union(A#k.us, Ls1), I+1, new_vars(New, I, Vdb0)),
- Ctxt = case V of
- #k_binary{segs=#k_var{name=C0}} -> C0;
- _ -> Ctxt0
- end,
- B = match(Kb, Ls1, I+1, Ctxt, Vdb1),
- #l{ke={val_clause,literal(V, Ctxt),B},i=I,vdb=use_vars(Bus, I+1, Vdb1),a=A#k.a}.
-
-guard_clause(#k_guard_clause{anno=A,guard=Kg,body=Kb}, Ls, I, Ctxt, Vdb0) ->
- Vdb1 = use_vars(union(A#k.us, Ls), I+2, Vdb0),
- Gdb = vdb_sub(I+1, I+2, Vdb1),
- G = protected(Kg, I+1, Gdb),
- B = match(Kb, Ls, I+2, Ctxt, Vdb1),
- #l{ke={guard_clause,G,B},
- i=I,vdb=use_vars((get_kanno(Kg))#k.us, I+2, Vdb1),
- a=A#k.a}.
-
-%% type(Ktype) -> Type.
-
-type(k_literal) -> literal;
-type(k_int) -> integer;
-%%type(k_char) -> integer; %Hhhmmm???
-type(k_float) -> float;
-type(k_atom) -> atom;
-type(k_nil) -> nil;
-type(k_cons) -> cons;
-type(k_tuple) -> tuple;
-type(k_binary) -> binary;
-type(k_bin_seg) -> bin_seg;
-type(k_bin_int) -> bin_int;
-type(k_bin_end) -> bin_end;
-type(k_map) -> map.
-
-%% variable(Klit) -> Lit.
-%% var_list([Klit]) -> [Lit].
-
-variable(#k_var{name=N}) -> {var,N}.
-
-var_list(Ks) -> [variable(K) || K <- Ks].
-
-%% atomic(Klit) -> Lit.
-%% atomic_list([Klit]) -> [Lit].
-
-atomic(#k_literal{val=V}) -> {literal,V};
-atomic(#k_var{name=N}) -> {var,N};
-atomic(#k_int{val=I}) -> {integer,I};
-atomic(#k_float{val=F}) -> {float,F};
-atomic(#k_atom{val=N}) -> {atom,N};
-%%atomic(#k_char{val=C}) -> {char,C};
-atomic(#k_nil{}) -> nil.
-
-atomic_list(Ks) -> [atomic(K) || K <- Ks].
-
-%% literal(Klit) -> Lit.
-%% literal_list([Klit]) -> [Lit].
-
-literal(#k_var{name=N}, _) -> {var,N};
-literal(#k_literal{val=I}, _) -> {literal,I};
-literal(#k_int{val=I}, _) -> {integer,I};
-literal(#k_float{val=F}, _) -> {float,F};
-literal(#k_atom{val=N}, _) -> {atom,N};
-%%literal(#k_char{val=C}, _) -> {char,C};
-literal(#k_nil{}, _) -> nil;
-literal(#k_cons{hd=H,tl=T}, Ctxt) ->
- {cons,[literal(H, Ctxt),literal(T, Ctxt)]};
-literal(#k_binary{segs=V}, Ctxt) ->
- {binary,literal(V, Ctxt)};
-literal(#k_bin_seg{size=S,unit=U,type=T,flags=Fs,seg=Seg,next=[]}, Ctxt) ->
- %% Only occurs in patterns.
- {bin_seg,Ctxt,literal(S, Ctxt),U,T,Fs,[literal(Seg, Ctxt)]};
-literal(#k_bin_seg{size=S,unit=U,type=T,flags=Fs,seg=Seg,next=N}, Ctxt) ->
- {bin_seg,Ctxt,literal(S, Ctxt),U,T,Fs,
- [literal(Seg, Ctxt),literal(N, Ctxt)]};
-literal(#k_bin_int{size=S,unit=U,flags=Fs,val=Int,next=N}, Ctxt) ->
- %% Only occurs in patterns.
- {bin_int,Ctxt,literal(S, Ctxt),U,Fs,Int,
- [literal(N, Ctxt)]};
-literal(#k_bin_end{}, Ctxt) ->
- {bin_end,Ctxt};
-literal(#k_tuple{es=Es}, Ctxt) ->
- {tuple,literal_list(Es, Ctxt)};
-literal(#k_map{op=Op,var=Var,es=Es0}, Ctxt) ->
- {map,Op,literal(Var, Ctxt),literal_list(Es0, Ctxt)};
-literal(#k_map_pair{key=K,val=V}, Ctxt) ->
- {map_pair,literal(K, Ctxt),literal(V, Ctxt)}.
-
-literal_list(Ks, Ctxt) ->
- [literal(K, Ctxt) || K <- Ks].
-
-
-%% is_gc_bif(Name, Arity) -> true|false
-%% Determines whether the BIF Name/Arity might do a GC.
-
-is_gc_bif(hd, 1) -> false;
-is_gc_bif(tl, 1) -> false;
-is_gc_bif(self, 0) -> false;
-is_gc_bif(node, 0) -> false;
-is_gc_bif(node, 1) -> false;
-is_gc_bif(element, 2) -> false;
-is_gc_bif(get, 1) -> false;
-is_gc_bif(tuple_size, 1) -> false;
-is_gc_bif(Bif, Arity) ->
- not (erl_internal:bool_op(Bif, Arity) orelse
- erl_internal:new_type_test(Bif, Arity) orelse
- erl_internal:comp_op(Bif, Arity)).
-
-%% Keep track of life time for variables.
-%%
-%% init_vars([{var,VarName}]) -> Vdb.
-%% new_vars([VarName], I, Vdb) -> Vdb.
-%% use_vars([VarName], I, Vdb) -> Vdb.
-%% add_var(VarName, F, L, Vdb) -> Vdb.
-%%
-%% The list of variable names for new_vars/3 and use_vars/3
-%% must be sorted.
-
-init_vars(Vs) ->
- vdb_new(Vs).
-
-new_vars([], _, Vdb) -> Vdb;
-new_vars([V], I, Vdb) -> vdb_store_new(V, {V,I,I}, Vdb);
-new_vars(Vs, I, Vdb) -> vdb_update_vars(Vs, Vdb, I).
-
-use_vars([], _, Vdb) ->
- Vdb;
-use_vars([V], I, Vdb) ->
- case vdb_find(V, Vdb) of
- {V,F,L} when I > L -> vdb_update(V, {V,F,I}, Vdb);
- {V,_,_} -> Vdb;
- error -> vdb_store_new(V, {V,I,I}, Vdb)
- end;
-use_vars(Vs, I, Vdb) -> vdb_update_vars(Vs, Vdb, I).
-
-add_var(V, F, L, Vdb) ->
- vdb_store_new(V, {V,F,L}, Vdb).
-
-%% vdb
-
-vdb_new(Vs) ->
- sort([{V,0,0} || {var,V} <- Vs]).
-
--type var() :: atom().
-
--spec vdb_find(var(), [vdb_entry()]) -> 'error' | vdb_entry().
-
-vdb_find(V, Vdb) ->
- case lists:keyfind(V, 1, Vdb) of
- false -> error;
- Vd -> Vd
- end.
-
-vdb_update(V, Update, [{V,_,_}|Vdb]) ->
- [Update|Vdb];
-vdb_update(V, Update, [Vd|Vdb]) ->
- [Vd|vdb_update(V, Update, Vdb)].
-
-vdb_store_new(V, New, [{V1,_,_}=Vd|Vdb]) when V > V1 ->
- [Vd|vdb_store_new(V, New, Vdb)];
-vdb_store_new(V, New, [{V1,_,_}|_]=Vdb) when V < V1 ->
- [New|Vdb];
-vdb_store_new(_, New, []) -> [New].
-
-vdb_update_vars([V|_]=Vs, [{V1,_,_}=Vd|Vdb], I) when V > V1 ->
- [Vd|vdb_update_vars(Vs, Vdb, I)];
-vdb_update_vars([V|Vs], [{V1,_,_}|_]=Vdb, I) when V < V1 ->
- %% New variable.
- [{V,I,I}|vdb_update_vars(Vs, Vdb, I)];
-vdb_update_vars([V|Vs], [{_,F,L}=Vd|Vdb], I) ->
- %% Existing variable.
- if
- I > L -> [{V,F,I}|vdb_update_vars(Vs, Vdb, I)];
- true -> [Vd|vdb_update_vars(Vs, Vdb, I)]
- end;
-vdb_update_vars([V|Vs], [], I) ->
- %% New variable.
- [{V,I,I}|vdb_update_vars(Vs, [], I)];
-vdb_update_vars([], Vdb, _) -> Vdb.
-
-%% vdb_sub(Min, Max, Vdb) -> Vdb.
-%% Extract variables which are used before and after Min. Lock
-%% variables alive after Max.
-
-vdb_sub(Min, Max, Vdb) ->
- [ if L >= Max -> {V,F,locked};
- true -> Vd
- end || {V,F,L}=Vd <- Vdb, F < Min, L >= Min ].
diff --git a/lib/compiler/src/v3_life.hrl b/lib/compiler/src/v3_life.hrl
deleted file mode 100644
index 5c76312067..0000000000
--- a/lib/compiler/src/v3_life.hrl
+++ /dev/null
@@ -1,29 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%% This record contains variable life-time annotation for a
-%% kernel expression. Added by v3_life, used by v3_codegen.
-
--type vdb_entry() :: {atom(),non_neg_integer(),non_neg_integer()}.
-
--record(l, {ke, %Kernel expression
- i=0 :: non_neg_integer(), %Op number
- vdb=[] :: [vdb_entry()], %Variable database
- a=[] :: [term()]}). %Core annotation
-
diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile
index 63763f31b2..da5d207db9 100644
--- a/lib/compiler/test/Makefile
+++ b/lib/compiler/test/Makefile
@@ -22,6 +22,7 @@ MODULES= \
bs_construct_SUITE \
bs_match_SUITE \
bs_utf_SUITE \
+ core_alias_SUITE \
core_fold_SUITE \
compile_SUITE \
compilation_SUITE \
diff --git a/lib/compiler/test/andor_SUITE.erl b/lib/compiler/test/andor_SUITE.erl
index 05c087104d..5c463063c1 100644
--- a/lib/compiler/test/andor_SUITE.erl
+++ b/lib/compiler/test/andor_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -38,6 +37,7 @@ groups() ->
combined,in_case,slow_compilation]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/apply_SUITE.erl b/lib/compiler/test/apply_SUITE.erl
index cca92e4713..0f82a56fb7 100644
--- a/lib/compiler/test/apply_SUITE.erl
+++ b/lib/compiler/test/apply_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,13 +29,13 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[mfa, fun_apply].
groups() ->
[].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/beam_block_SUITE.erl b/lib/compiler/test/beam_block_SUITE.erl
index 55d5f2dbe8..40a30b65d7 100644
--- a/lib/compiler/test/beam_block_SUITE.erl
+++ b/lib/compiler/test/beam_block_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@
-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1,
init_per_group/2,end_per_group/2,
get_map_elements/1,otp_7345/1,move_opt_across_gc_bif/1,
- erl_202/1,repro/1]).
+ erl_202/1,repro/1,local_cse/1,second_block_pass/1]).
%% The only test for the following functions is that
%% the code compiles and is accepted by beam_validator.
@@ -31,7 +31,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -40,10 +39,13 @@ groups() ->
otp_7345,
move_opt_across_gc_bif,
erl_202,
- repro
+ repro,
+ local_cse,
+ second_block_pass
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -237,6 +239,72 @@ find_operands(Cfg,XsiGraph,ActiveList,Count) ->
[Count+1, length(NewActiveList), length(digraph:vertices(XsiGraph))],
find_operands(NewCfg,XsiGraph,NewActiveList,Count+1).
+%% Some tests of local common subexpression elimination (CSE).
+
+local_cse(_Config) ->
+ {Self,{ok,Self}} = local_cse_1(),
+
+ local_cse_2([]),
+ local_cse_2(lists:seq(1, 512)),
+ local_cse_2(?MODULE:module_info()),
+
+ {[b],[a,b]} = local_cse_3(a, b),
+
+ {2000,Self,{Self,write_cache}} = local_cse_4(),
+
+ ok.
+
+local_cse_1() ->
+ %% Cover handling of unsafe tuple construction in
+ %% eliminate_use_of_from_reg/4. It became necessary to handle
+ %% unsafe tuples when local CSE was introduced.
+
+ {self(),{ok,self()}}.
+
+local_cse_2(Term) ->
+ case cse_make_binary(Term) of
+ <<Size:8,BinTerm:Size/binary>> ->
+ Term = binary_to_term(BinTerm);
+ <<Size:8,SizeTerm:Size/binary,BinTerm/binary>> ->
+ {'$size',TermSize} = binary_to_term(SizeTerm),
+ TermSize = byte_size(BinTerm),
+ Term = binary_to_term(BinTerm)
+ end.
+
+%% Copy of observer_backend:ttb_make_binary/1. During development of
+%% the local CSE optimization this function was incorrectly optimized.
+
+cse_make_binary(Term) ->
+ B = term_to_binary(Term),
+ SizeB = byte_size(B),
+ if SizeB > 255 ->
+ SB = term_to_binary({'$size',SizeB}),
+ <<(byte_size(SB)):8, SB/binary, B/binary>>;
+ true ->
+ <<SizeB:8, B/binary>>
+ end.
+
+local_cse_3(X, Y) ->
+ %% The following expression was incorrectly transformed to {[X,Y],[X,Y]}
+ %% during development of the local CSE optimization.
+
+ {[Y],[X,Y]}.
+
+local_cse_4() ->
+ do_local_cse_4(2000, self(), {self(), write_cache}).
+
+do_local_cse_4(X, Y, Z) ->
+ {X,Y,Z}.
+
+%% Tests previously found bugs when running beam_block the second time.
+
+second_block_pass(_Config) ->
+ [#{dts:=5.0}] = second_1([#{dts => 10.0}], 2.0),
+ ok.
+
+second_1(Fs, TS) ->
+ [F#{dts=>DTS / TS} || #{dts:=DTS} = F <- Fs].
+
%%%
%%% Common functions.
%%%
diff --git a/lib/compiler/test/beam_except_SUITE.erl b/lib/compiler/test/beam_except_SUITE.erl
index 47367d6eab..2b4a780899 100644
--- a/lib/compiler/test/beam_except_SUITE.erl
+++ b/lib/compiler/test/beam_except_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -35,6 +34,7 @@ groups() ->
coverage]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/beam_jump_SUITE.erl b/lib/compiler/test/beam_jump_SUITE.erl
index 088f63606c..c61e4ab65c 100644
--- a/lib/compiler/test/beam_jump_SUITE.erl
+++ b/lib/compiler/test/beam_jump_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2016. All Rights Reserved.
+%% Copyright Ericsson AB 2016-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,7 +27,6 @@ suite() ->
[{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -37,6 +36,7 @@ groups() ->
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/beam_reorder_SUITE.erl b/lib/compiler/test/beam_reorder_SUITE.erl
index 27ce51eec3..c8a4f9a75f 100644
--- a/lib/compiler/test/beam_reorder_SUITE.erl
+++ b/lib/compiler/test/beam_reorder_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -36,6 +35,7 @@ groups() ->
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl
index 86146c614f..061076b3ff 100644
--- a/lib/compiler/test/beam_type_SUITE.erl
+++ b/lib/compiler/test/beam_type_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,12 +22,12 @@
-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1,
init_per_group/2,end_per_group/2,
integers/1,coverage/1,booleans/1,setelement/1,cons/1,
- tuple/1,record_float/1,binary_float/1,float_compare/1]).
+ tuple/1,record_float/1,binary_float/1,float_compare/1,
+ arity_checks/1,elixir_binaries/1,find_best/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -40,10 +40,14 @@ groups() ->
tuple,
record_float,
binary_float,
- float_compare
+ float_compare,
+ arity_checks,
+ elixir_binaries,
+ find_best
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -64,6 +68,15 @@ integers(_Config) ->
college = do_integers_3(),
+ zero = do_integers_4(<<0:1>>, 0),
+ one = do_integers_4(<<1:1>>, 0),
+ other = do_integers_4(<<1:1>>, 2),
+
+ zero = do_integers_5(0, 0),
+ one = do_integers_5(0, 1),
+ two = do_integers_5(0, 2),
+ three = do_integers_5(0, 3),
+
ok.
do_integers_1(B0) ->
@@ -86,7 +99,31 @@ do_integers_3() ->
1 -> 0
end.
-coverage(_Config) ->
+do_integers_4(<<X:1,T/bits>>, C) ->
+ %% Binary matching gives the range 0-1 for X.
+ %% The range for `X bor C` is unknown. It must not be inherited
+ %% from X. (`X bor C` will reuse the register used for X.)
+ case X bor C of
+ 0 -> do_integers_4(T, C, zero);
+ 1 -> do_integers_4(T, C, one);
+ _ -> do_integers_4(T, C, other)
+ end.
+
+do_integers_4(_, _, Res) ->
+ Res.
+
+do_integers_5(X0, Y0) ->
+ %% X and Y will use the same register.
+ X = X0 band 1,
+ Y = Y0 band 3,
+ case Y of
+ 0 -> zero;
+ 1 -> one;
+ 2 -> two;
+ 3 -> three
+ end.
+
+coverage(Config) ->
{'EXIT',{badarith,_}} = (catch id(1) bsl 0.5),
{'EXIT',{badarith,_}} = (catch id(2.0) bsl 2),
{'EXIT',{badarith,_}} = (catch a + 0.5),
@@ -97,6 +134,29 @@ coverage(_Config) ->
id(id(42) band 387439739874298734983787934283479243879),
id(-1 band id(13)),
+ error = if
+ is_map(Config), is_integer(Config) -> ok;
+ true -> error
+ end,
+ error = if
+ is_map(Config), is_atom(Config) -> ok;
+ true -> error
+ end,
+ error = if
+ is_map(Config), is_tuple(Config) -> ok;
+ true -> error
+ end,
+ error = if
+ is_integer(Config), is_bitstring(Config) -> ok;
+ true -> error
+ end,
+
+ ok = case Config of
+ <<_>> when is_binary(Config) ->
+ impossible;
+ [_|_] ->
+ ok
+ end,
ok.
booleans(_Config) ->
@@ -171,6 +231,95 @@ do_float_compare(X) ->
_T -> Y > 0
end.
+arity_checks(_Config) ->
+ %% ERL-549: an unsafe optimization removed a test_arity instruction,
+ %% causing the following to return 'broken' instead of 'ok'.
+ ok = do_record_arity_check({rgb, 255, 255, 255, 1}),
+ ok = do_tuple_arity_check({255, 255, 255, 1}).
+
+-record(rgb, {r = 255, g = 255, b = 255}).
+
+do_record_arity_check(RGB) when
+ (element(2, RGB) >= 0), (element(2, RGB) =< 255),
+ (element(3, RGB) >= 0), (element(3, RGB) =< 255),
+ (element(4, RGB) >= 0), (element(4, RGB) =< 255) ->
+ if
+ element(1, RGB) =:= rgb, is_record(RGB, rgb) -> broken;
+ true -> ok
+ end.
+
+do_tuple_arity_check(RGB) when is_tuple(RGB),
+ (element(1, RGB) >= 0), (element(1, RGB) =< 255),
+ (element(2, RGB) >= 0), (element(2, RGB) =< 255),
+ (element(3, RGB) >= 0), (element(3, RGB) =< 255) ->
+ case RGB of
+ {255, _, _} -> broken;
+ _ -> ok
+ end.
+
+elixir_binaries(_Config) ->
+ <<"foo blitzky baz">> = elixir_binary_1(<<"blitzky">>),
+ <<"foo * baz">> = elixir_binary_2($*),
+ <<7:4,755:10>> = elixir_bitstring_3(<<755:10>>),
+ ok.
+
+elixir_binary_1(Bar) when is_binary(Bar) ->
+ <<"foo ",
+ case Bar of
+ Rewrite when is_binary(Rewrite) ->
+ Rewrite;
+ Rewrite ->
+ list_to_binary(Rewrite)
+ end/binary,
+ " baz">>.
+
+elixir_binary_2(Arg) ->
+ Bin = <<Arg>>,
+ <<"foo ",
+ case Bin of
+ Rewrite when is_binary(Rewrite) ->
+ Rewrite;
+ Rewrite ->
+ list_to_binary:to_string(Rewrite)
+ end/binary,
+ " baz">>.
+
+elixir_bitstring_3(Bar) when is_bitstring(Bar) ->
+ <<7:4,
+ case Bar of
+ Rewrite when is_bitstring(Rewrite) ->
+ Rewrite;
+ Rewrite ->
+ list_to_bitstring(Rewrite)
+ end/bitstring>>.
+
+find_best(_Config) ->
+ ok = find_best([a], nil),
+ ok = find_best([<<"a">>], nil),
+ {error,_} = find_best([], nil),
+ ok.
+
+%% Failed because beam_type assumed that the operand
+%% for bs_context_binary must be a binary. Not true!
+find_best([a|Tail], Best) ->
+ find_best(Tail,
+ case Best of
+ X when X =:= nil orelse X =:= false -> a;
+ X -> X
+ end);
+find_best([<<"a">>|Tail], Best) ->
+ find_best(Tail,
+ case Best of
+ X when X =:= nil orelse X =:= false -> <<"a">>;
+ X -> X
+ end);
+find_best([], a) ->
+ ok;
+find_best([], <<"a">>) ->
+ ok;
+find_best([], nil) ->
+ {error,<<"should not get here">>}.
+
id(I) ->
I.
diff --git a/lib/compiler/test/beam_utils_SUITE.erl b/lib/compiler/test/beam_utils_SUITE.erl
index a3f1bb93fe..ac19305d69 100644
--- a/lib/compiler/test/beam_utils_SUITE.erl
+++ b/lib/compiler/test/beam_utils_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,13 +24,14 @@
apply_fun/1,apply_mf/1,bs_init/1,bs_save/1,
is_not_killed/1,is_not_used_at/1,
select/1,y_catch/1,otp_8949_b/1,liveopt/1,coverage/1,
- y_registers/1]).
+ y_registers/1,user_predef/1,scan_f/1,cafu/1,
+ receive_label/1,read_size_file_version/1,not_used/1,
+ is_used_fr/1]).
-export([id/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -46,10 +47,17 @@ groups() ->
otp_8949_b,
liveopt,
coverage,
- y_registers
+ y_registers,
+ user_predef,
+ scan_f,
+ cafu,
+ read_size_file_version,
+ not_used,
+ is_used_fr
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -117,6 +125,24 @@ bs_init(_Config) ->
{'EXIT',{badarg,_}} = (catch do_bs_init_2([0.5])),
{'EXIT',{badarg,_}} = (catch do_bs_init_2([-1])),
{'EXIT',{badarg,_}} = (catch do_bs_init_2([1 bsl 32])),
+
+ <<>> = do_bs_init_3({tag,0}, 0, 0),
+ <<0>> = do_bs_init_3({tag,0}, 2, 1),
+
+ <<"_build/shared">> = do_bs_init_4([], false),
+ <<"abc/shared">> = do_bs_init_4(<<"abc">>, false),
+ <<"foo/foo">> = do_bs_init_4(<<"foo">>, true),
+ error = do_bs_init_4([], not_boolean),
+
+ Id = 17575,
+ Domain = -8798798,
+ [<<10,1:16,Id:16/signed>>,<<8,2:16,Domain:32/signed>>] =
+ do_bs_init_5(#{tag=>value,id=>Id,domain=>Domain}),
+ {'EXIT',{{required,id},[_|_]}} =
+ (catch do_bs_init_5(#{tag=>value,id=>nil,domain=>Domain})),
+ {'EXIT',{{required,domain},[_|_]}} =
+ (catch do_bs_init_5(#{tag=>value,id=>Id,domain=>nil})),
+
ok.
do_bs_init_1([?MODULE], Sz) ->
@@ -134,6 +160,59 @@ do_bs_init_2(SigNos) ->
erlang:error(badarg)
>>.
+do_bs_init_3({tag,Pos}, Offset, Len) ->
+ N0 = Offset - Pos,
+ N = if N0 > Len -> Len;
+ true -> N0
+ end,
+ <<0:N/unit:8>>.
+
+do_bs_init_4(Arg1, Arg2) ->
+ Build =
+ case id(Arg1) of
+ X when X =:= [] orelse X =:= false -> <<"_build">>;
+ X -> X
+ end,
+ case id(Arg2) of
+ true ->
+ id(<<case Build of
+ Rewrite when is_binary(Rewrite) ->
+ Rewrite;
+ Rewrite ->
+ id(Rewrite)
+ end/binary,
+ "/",
+ case id(<<"foo">>) of
+ Rewrite when is_binary(Rewrite) ->
+ Rewrite;
+ Rewrite ->
+ id(Rewrite)
+ end/binary>>);
+ false ->
+ id(<<case Build of
+ Rewrite when is_binary(Rewrite) ->
+ Rewrite;
+ Rewrite ->
+ id(Rewrite)
+ end/binary,
+ "/shared">>);
+ Other ->
+ error
+ end.
+
+do_bs_init_5(#{tag := value, id := Id, domain := Domain}) ->
+ [case Id of
+ nil ->
+ error(id({required, id}));
+ _ ->
+ <<10, 1:16/signed, Id:16/signed>>
+ end,
+ case Domain of
+ nil ->
+ error(id({required, domain}));
+ _ ->
+ <<8, 2:16/signed, Domain:32/signed>>
+ end].
bs_save(_Config) ->
{a,30,<<>>} = do_bs_save(<<1:1,30:5>>),
@@ -260,6 +339,14 @@ otp_8949_b(A, B) ->
liveopt(_Config) ->
F = liveopt_fun(42, pebkac, user),
void = F(42, #alarmInfo{type=sctp,cause=pebkac,origin=user}),
+
+
+ A = {#alarmInfo{cause = {abc, def}}, ghi},
+ A = liveopt_guard_bif(A),
+
+ B = {#alarmInfo{cause = {abc}}, def},
+ {#alarmInfo{cause = {{abc}}}, def} = liveopt_guard_bif(B),
+
ok.
liveopt_fun(Peer, Cause, Origin) ->
@@ -271,6 +358,15 @@ liveopt_fun(Peer, Cause, Origin) ->
void
end.
+liveopt_guard_bif({#alarmInfo{cause=F}=R, X}=A) ->
+ %% ERIERL-48
+ if
+ is_tuple(F), tuple_size(F) == 2 -> A;
+ true ->
+ R2 = R#alarmInfo{cause={F}},
+ {R2,X}
+ end.
+
%% Thanks to QuickCheck.
coverage(_Config) ->
42+7 = merchant([[],7,false]),
@@ -359,5 +455,121 @@ do(A, B) -> {A,B}.
appointment(#{"resolution" := Url}) ->
do(receive _ -> Url end, #{true => Url}).
+%% From epp.erl.
+user_predef(_Config) ->
+ #{key:="value"} = user_predef({key,"value"}, #{}),
+ #{key:="value"} = user_predef({key,"value"}, #{key=>defined}),
+ error = user_predef({key,"value"}, #{key=>[defined]}),
+ ok.
+
+user_predef({M,Val}, Ms) ->
+ case Ms of
+ #{M:=Defs} when is_list(Defs) ->
+ error;
+ _ ->
+ Ms#{M=>Val}
+ end.
+
+%% From disk_log_1.erl.
+scan_f(_Config) ->
+ {1,<<>>,[]} = scan_f(<<1:32>>, 1, []),
+ {1,<<>>,[<<156>>]} = scan_f(<<1:32,156,1:32>>, 1, []),
+ ok.
+
+scan_f(<<Size:32,Tail/binary>>, FSz, Acc) when Size =< FSz ->
+ case Tail of
+ <<BinTerm:Size/binary,Tail2/binary>> ->
+ scan_f(Tail2, FSz, [BinTerm | Acc]);
+ _ ->
+ {Size,Tail,Acc}
+ end.
+
+%% From file_io_server.erl.
+cafu(_Config) ->
+ error = cafu(<<42:32>>, -1, 0, {utf32,big}),
+ error = cafu(<<42:32>>, 10, 0, {utf32,big}),
+ error = cafu(<<42:32>>, -1, 0, {utf32,little}),
+ ok.
+
+cafu(<<_/big-utf32,Rest/binary>>, N, Count, {utf32,big}) when N < 0 ->
+ cafu(Rest, -1, Count+1, {utf32,big});
+cafu(<<_/big-utf32,Rest/binary>>, N, Count, {utf32,big}) ->
+ cafu(Rest, N-1, Count+1, {utf32,big});
+cafu(<<_/little-utf32,Rest/binary>>, N, Count, {utf32,little}) when N < 0 ->
+ cafu(Rest, -1, Count+1, {utf32,little});
+cafu(_, _, _, _) ->
+ error.
+
+-record(rec_label, {bool}).
+
+receive_label(_Config) ->
+ Pid = spawn_link(fun() -> do_receive_label(#rec_label{bool=true}) end),
+ Msg = {a,b,c},
+ Pid ! {self(),Msg},
+ receive
+ {ok,Msg} ->
+ unlink(Pid),
+ exit(Pid, die),
+ ok
+ end.
+
+do_receive_label(Rec) ->
+ receive
+ {From,Message} when Rec#rec_label.bool ->
+ From ! {ok,Message},
+ do_receive_label(Rec)
+ end.
+
+read_size_file_version(_Config) ->
+ ok = do_read_size_file_version({ok,<<42>>}),
+ {ok,7777} = do_read_size_file_version({ok,<<7777:32>>}),
+ ok.
+
+do_read_size_file_version(E) ->
+ case E of
+ {ok,<<Version>>} when Version =:= 42 ->
+ ok;
+ {ok,<<MaxFiles:32>>} ->
+ {ok,MaxFiles}
+ end.
+
+-record(s, { a, b }).
+-record(k, { v }).
+
+not_used(_Config) ->
+ [] = not_used_p(any, #s{b=true}, #k{}, ignored),
+ #k{v=42} = not_used_p(any, #s{b=false}, #k{v=42}, ignored),
+ #k{v=42} = not_used_p(any, #s{b=bad}, #k{v=42}, ignored),
+ ok.
+
+not_used_p(_C, S, K, L) when is_record(K, k) ->
+ if ((S#s.b) and
+ (S#s.b)) ->
+ [];
+ true ->
+ id(L),
+ id(K#k.v),
+ id(K)
+ end.
+
+is_used_fr(Config) ->
+ 1 = is_used_fr(self(), self()),
+ 1 = is_used_fr(self(), other),
+ receive 1 -> ok end,
+ receive 1 -> ok end,
+ receive 1 -> ok end,
+ receive 1 -> ok end,
+ ok.
+
+is_used_fr(X, Y) ->
+ %% beam_utils:is_used({fr,R}, Code) would crash.
+ _ = 0 / (X ! 1),
+ _ = case Y of
+ X -> ok;
+ _ -> error
+ end,
+ X ! 1.
+
+
%% The identity function.
id(I) -> I.
diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl
index c23514b36b..d3e544a9cc 100644
--- a/lib/compiler/test/beam_validator_SUITE.erl
+++ b/lib/compiler/test/beam_validator_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,8 +33,9 @@
state_after_fault_in_catch/1,no_exception_in_catch/1,
undef_label/1,illegal_instruction/1,failing_gc_guard_bif/1,
map_field_lists/1,cover_bin_opt/1,
- val_dsetel/1]).
-
+ val_dsetel/1,bad_tuples/1,bad_try_catch_nesting/1,
+ receive_stacked/1]).
+
-include_lib("common_test/include/ct.hrl").
init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
@@ -48,7 +49,6 @@ suite() ->
{timetrap,{minutes,10}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -61,9 +61,12 @@ groups() ->
freg_state,bad_bin_match,bad_dsetel,
state_after_fault_in_catch,no_exception_in_catch,
undef_label,illegal_instruction,failing_gc_guard_bif,
- map_field_lists,cover_bin_opt,val_dsetel]}].
+ map_field_lists,cover_bin_opt,val_dsetel,
+ bad_tuples,bad_try_catch_nesting,
+ receive_stacked]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -154,8 +157,8 @@ call_last(Config) when is_list(Config) ->
merge_undefined(Config) when is_list(Config) ->
Errors = do_val(merge_undefined, Config),
[{{t,handle_call,2},
- {{call_ext,2,{extfunc,debug,filter,2}},
- 22,
+ {{call_ext,1,{extfunc,erlang,exit,1}},
+ 10,
{uninitialized_reg,{y,0}}}}] = Errors,
ok.
@@ -421,9 +424,9 @@ try_bin_opt(Mod) ->
try
do_bin_opt(Mod)
catch
- Class:Error ->
+ Class:Error:Stk ->
io:format("~p: ~p ~p\n~p\n",
- [Mod,Class,Error,erlang:get_stacktrace()]),
+ [Mod,Class,Error,Stk]),
error
end.
@@ -509,6 +512,73 @@ destroy_reg({Tag,N}) ->
{y,N+1}
end.
+bad_tuples(Config) ->
+ Errors = do_val(bad_tuples, Config),
+ [{{bad_tuples,heap_overflow,1},
+ {{put,{x,0}},8,{heap_overflow,{left,0},{wanted,1}}}},
+ {{bad_tuples,long,2},
+ {{put,{atom,too_long}},8,not_building_a_tuple}},
+ {{bad_tuples,self_referential,1},
+ {{put,{x,1}},7,{tuple_in_progress,{x,1}}}},
+ {{bad_tuples,short,1},
+ {{move,{x,1},{x,0}},7,{tuple_in_progress,{x,1}}}}] = Errors,
+
+ ok.
+
+bad_try_catch_nesting(Config) ->
+ Errors = do_val(bad_try_catch_nesting, Config),
+ [{{bad_try_catch_nesting,main,2},
+ {{'try',{y,2},{f,3}},
+ 7,
+ {bad_try_catch_nesting,{y,2},[{{y,1},{trytag,[5]}}]}}}] = Errors,
+ ok.
+
+receive_stacked(Config) ->
+ Mod = ?FUNCTION_NAME,
+ Errors = do_val(Mod, Config),
+ [{{receive_stacked,f1,0},
+ {{loop_rec_end,{f,3}},
+ 17,
+ {fragile_message_reference,{y,0}}}},
+ {{receive_stacked,f2,0},
+ {{test_heap,3,0},10,{fragile_message_reference,{y,1}}}},
+ {{receive_stacked,f3,0},
+ {{test_heap,3,0},10,{fragile_message_reference,{y,1}}}},
+ {{receive_stacked,f4,0},
+ {{test_heap,3,0},10,{fragile_message_reference,{y,1}}}},
+ {{receive_stacked,f5,0},
+ {{loop_rec_end,{f,23}},
+ 23,
+ {fragile_message_reference,{y,1}}}},
+ {{receive_stacked,f6,0},
+ {{gc_bif,byte_size,{f,29},0,[{y,0}],{x,0}},
+ 12,
+ {fragile_message_reference,{y,0}}}},
+ {{receive_stacked,f7,0},
+ {{loop_rec_end,{f,33}},
+ 20,
+ {fragile_message_reference,{y,0}}}},
+ {{receive_stacked,f8,0},
+ {{loop_rec_end,{f,38}},
+ 20,
+ {fragile_message_reference,{y,0}}}},
+ {{receive_stacked,m1,0},
+ {{loop_rec_end,{f,43}},
+ 19,
+ {fragile_message_reference,{y,0}}}},
+ {{receive_stacked,m2,0},
+ {{loop_rec_end,{f,48}},
+ 33,
+ {fragile_message_reference,{y,0}}}}] = Errors,
+
+ %% Compile the original source code as a smoke test.
+ Data = proplists:get_value(data_dir, Config),
+ Base = atom_to_list(Mod),
+ File = filename:join(Data, Base),
+ {ok,Mod,_} = compile:file(File, [binary]),
+
+ ok.
+
%%%-------------------------------------------------------------------------
transform_remove(Remove, Module) ->
diff --git a/lib/compiler/test/beam_validator_SUITE_data/bad_try_catch_nesting.S b/lib/compiler/test/beam_validator_SUITE_data/bad_try_catch_nesting.S
new file mode 100644
index 0000000000..9f1b21a17b
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/bad_try_catch_nesting.S
@@ -0,0 +1,64 @@
+{module, bad_try_catch_nesting}. %% version = 0
+
+{exports, [{main,2},{module_info,0},{module_info,1}]}.
+
+{attributes, []}.
+
+{labels, 11}.
+
+
+{function, main, 2, 2}.
+ {label,1}.
+ {line,[{location,"bad_try_catch_nesting.erl",4}]}.
+ {func_info,{atom,bad_try_catch_nesting},{atom,main},2}.
+ {label,2}.
+ {allocate_zero,3,2}.
+ {'try',{y,1},{f,5}}.
+ {move,{x,1},{y,0}}.
+ {'try',{y,2},{f,3}}.
+ {line,[{location,"bad_try_catch_nesting.erl",7}]}.
+ {call_fun,0}.
+ {try_end,{y,2}}.
+ {jump,{f,4}}.
+ {label,3}.
+ {try_case,{y,2}}.
+ {test,is_ne_exact,{f,4},[{x,0},{atom,error}]}.
+ {line,[]}.
+ {bif,raise,{f,0},[{x,2},{x,1}],{x,0}}.
+ {label,4}.
+ {move,{y,0},{x,0}}.
+ {kill,{y,0}}.
+ {line,[{location,"bad_try_catch_nesting.erl",12}]}.
+ {call_fun,0}.
+ {try_end,{y,1}}.
+ {deallocate,3}.
+ return.
+ {label,5}.
+ {try_case,{y,1}}.
+ {test,is_eq_exact,{f,6},[{x,0},{atom,throw}]}.
+ {deallocate,3}.
+ return.
+ {label,6}.
+ {line,[]}.
+ {bif,raise,{f,0},[{x,2},{x,1}],{x,0}}.
+
+
+{function, module_info, 0, 8}.
+ {label,7}.
+ {line,[]}.
+ {func_info,{atom,bad_try_catch_nesting},{atom,module_info},0}.
+ {label,8}.
+ {move,{atom,bad_try_catch_nesting},{x,0}}.
+ {line,[]}.
+ {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
+
+
+{function, module_info, 1, 10}.
+ {label,9}.
+ {line,[]}.
+ {func_info,{atom,bad_try_catch_nesting},{atom,module_info},1}.
+ {label,10}.
+ {move,{x,0},{x,1}}.
+ {move,{atom,bad_try_catch_nesting},{x,0}}.
+ {line,[]}.
+ {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/bad_tuples.S b/lib/compiler/test/beam_validator_SUITE_data/bad_tuples.S
new file mode 100644
index 0000000000..7980241c37
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/bad_tuples.S
@@ -0,0 +1,88 @@
+{module, bad_tuples}. %% version = 0
+
+{exports, [{heap_overflow,1},
+ {long,2},
+ {module_info,0},
+ {module_info,1},
+ {self_referential,1},
+ {short,1}]}.
+
+{attributes, []}.
+
+{labels, 13}.
+
+
+{function, short, 1, 2}.
+ {label,1}.
+ {line,[{location,"bad_tuples.erl",4}]}.
+ {func_info,{atom,bad_tuples},{atom,short},1}.
+ {label,2}.
+ {test_heap,3,1}.
+ {put_tuple,2,{x,1}}.
+ {put,{atom,ok}}.
+ {move,{x,1},{x,0}}.
+ return.
+
+
+{function, long, 2, 4}.
+ {label,3}.
+ {line,[{location,"bad_tuples.erl",7}]}.
+ {func_info,{atom,bad_tuples},{atom,long},2}.
+ {label,4}.
+ {test_heap,6,2}.
+ {put_tuple,2,{x,2}}.
+ {put,{x,0}}.
+ {put,{x,1}}.
+ {put,{atom,too_long}}.
+ {put_tuple,2,{x,0}}.
+ {put,{atom,ok}}.
+ {put,{x,2}}.
+ return.
+
+
+{function, heap_overflow, 1, 6}.
+ {label,5}.
+ {line,[{location,"bad_tuples.erl",10}]}.
+ {func_info,{atom,bad_tuples},{atom,heap_overflow},1}.
+ {label,6}.
+ {test_heap,3,1}.
+ {put_tuple,2,{x,1}}.
+ {put,{atom,ok}}.
+ {put,{x,0}}.
+ {put,{x,0}}.
+ {move,{x,1},{x,0}}.
+ return.
+
+
+{function, self_referential, 1, 8}.
+ {label,7}.
+ {line,[{location,"bad_tuples.erl",13}]}.
+ {func_info,{atom,bad_tuples},{atom,self_referential},1}.
+ {label,8}.
+ {test_heap,3,1}.
+ {put_tuple,2,{x,1}}.
+ {put,{atom,ok}}.
+ {put,{x,1}}.
+ {move,{x,1},{x,0}}.
+ return.
+
+
+{function, module_info, 0, 10}.
+ {label,9}.
+ {line,[]}.
+ {func_info,{atom,bad_tuples},{atom,module_info},0}.
+ {label,10}.
+ {move,{atom,bad_tuples},{x,0}}.
+ {line,[]}.
+ {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
+
+
+{function, module_info, 1, 12}.
+ {label,11}.
+ {line,[]}.
+ {func_info,{atom,bad_tuples},{atom,module_info},1}.
+ {label,12}.
+ {move,{x,0},{x,1}}.
+ {move,{atom,bad_tuples},{x,0}}.
+ {line,[]}.
+ {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/receive_stacked.S b/lib/compiler/test/beam_validator_SUITE_data/receive_stacked.S
new file mode 100644
index 0000000000..cca052a9c4
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/receive_stacked.S
@@ -0,0 +1,390 @@
+{module, receive_stacked}. %% version = 0
+
+{exports, [{f1,0},
+ {f2,0},
+ {f3,0},
+ {f4,0},
+ {f5,0},
+ {f6,0},
+ {f7,0},
+ {f8,0},
+ {id,1},
+ {m1,0},
+ {m2,0},
+ {module_info,0},
+ {module_info,1}]}.
+
+{attributes, []}.
+
+{labels, 57}.
+
+
+{function, f1, 0, 2}.
+ {label,1}.
+ {line,[{location,"receive_stacked.erl",15}]}.
+ {func_info,{atom,receive_stacked},{atom,f1},0}.
+ {label,2}.
+ {allocate_zero,1,0}.
+ {label,3}.
+ {loop_rec,{f,5},{x,0}}.
+ {move,{x,0},{y,0}}.
+ {test,is_integer,{f,4},[{y,0}]}.
+ remove_message.
+ {move,{integer,42},{x,0}}.
+ {line,[{location,"receive_stacked.erl",18}]}.
+ {call,1,{f,52}}.
+ {move,{y,0},{x,0}}.
+ {deallocate,1}.
+ return.
+ {label,4}.
+ {loop_rec_end,{f,3}}.
+ {label,5}.
+ {wait,{f,3}}.
+
+
+{function, f2, 0, 7}.
+ {label,6}.
+ {line,[{location,"receive_stacked.erl",22}]}.
+ {func_info,{atom,receive_stacked},{atom,f2},0}.
+ {label,7}.
+ {allocate_zero,2,0}.
+ {label,8}.
+ {loop_rec,{f,10},{x,0}}.
+ {test,is_nonempty_list,{f,9},[{x,0}]}.
+ {get_list,{x,0},{y,1},{x,0}}.
+ {test,is_nil,{f,9},[{x,0}]}.
+ {test_heap,3,0}.
+ remove_message.
+ {put_tuple,2,{y,0}}.
+ {put,{atom,ok}}.
+ {put,{y,1}}.
+ {move,{integer,42},{x,0}}.
+ {line,[{location,"receive_stacked.erl",26}]}.
+ {call,1,{f,52}}.
+ {test_heap,3,0}.
+ {put_tuple,2,{x,0}}.
+ {put,{y,0}}.
+ {put,{y,1}}.
+ {deallocate,2}.
+ return.
+ {label,9}.
+ {loop_rec_end,{f,8}}.
+ {label,10}.
+ {wait,{f,8}}.
+
+
+{function, f3, 0, 12}.
+ {label,11}.
+ {line,[{location,"receive_stacked.erl",30}]}.
+ {func_info,{atom,receive_stacked},{atom,f3},0}.
+ {label,12}.
+ {allocate_zero,2,0}.
+ {label,13}.
+ {loop_rec,{f,15},{x,0}}.
+ {test,is_nonempty_list,{f,14},[{x,0}]}.
+ {get_hd,{x,0},{y,1}}.
+ {test,is_integer,{f,14},[{y,1}]}.
+ {test_heap,3,0}.
+ remove_message.
+ {put_tuple,2,{y,0}}.
+ {put,{atom,ok}}.
+ {put,{y,1}}.
+ {move,{integer,42},{x,0}}.
+ {line,[{location,"receive_stacked.erl",34}]}.
+ {call,1,{f,52}}.
+ {test_heap,3,0}.
+ {put_tuple,2,{x,0}}.
+ {put,{y,0}}.
+ {put,{y,1}}.
+ {deallocate,2}.
+ return.
+ {label,14}.
+ {loop_rec_end,{f,13}}.
+ {label,15}.
+ {wait,{f,13}}.
+
+
+{function, f4, 0, 17}.
+ {label,16}.
+ {line,[{location,"receive_stacked.erl",38}]}.
+ {func_info,{atom,receive_stacked},{atom,f4},0}.
+ {label,17}.
+ {allocate_zero,2,0}.
+ {label,18}.
+ {loop_rec,{f,20},{x,0}}.
+ {test,is_nonempty_list,{f,19},[{x,0}]}.
+ {get_tl,{x,0},{y,1}}.
+ {test,is_list,{f,19},[{y,1}]}.
+ {test_heap,3,0}.
+ remove_message.
+ {put_tuple,2,{y,0}}.
+ {put,{atom,ok}}.
+ {put,{y,1}}.
+ {move,{integer,42},{x,0}}.
+ {line,[{location,"receive_stacked.erl",42}]}.
+ {call,1,{f,52}}.
+ {test_heap,3,0}.
+ {put_tuple,2,{x,0}}.
+ {put,{y,0}}.
+ {put,{y,1}}.
+ {deallocate,2}.
+ return.
+ {label,19}.
+ {loop_rec_end,{f,18}}.
+ {label,20}.
+ {wait,{f,18}}.
+
+
+{function, f5, 0, 22}.
+ {label,21}.
+ {line,[{location,"receive_stacked.erl",46}]}.
+ {func_info,{atom,receive_stacked},{atom,f5},0}.
+ {label,22}.
+ {allocate_zero,2,0}.
+ {label,23}.
+ {loop_rec,{f,25},{x,0}}.
+ {test,is_tuple,{f,24},[{x,0}]}.
+ {test,test_arity,{f,24},[{x,0},1]}.
+ {get_tuple_element,{x,0},0,{y,1}}.
+ {test,is_integer,{f,24},[{y,1}]}.
+ remove_message.
+ {put_map_assoc,{f,0},{literal,#{}},{y,0},0,{list,[{atom,key},{y,1}]}}.
+ {move,{integer,42},{x,0}}.
+ {line,[{location,"receive_stacked.erl",50}]}.
+ {call,1,{f,52}}.
+ {test_heap,3,0}.
+ {put_tuple,2,{x,0}}.
+ {put,{y,0}}.
+ {put,{y,1}}.
+ {deallocate,2}.
+ return.
+ {label,24}.
+ {loop_rec_end,{f,23}}.
+ {label,25}.
+ {wait,{f,23}}.
+
+
+{function, f6, 0, 27}.
+ {label,26}.
+ {line,[{location,"receive_stacked.erl",54}]}.
+ {func_info,{atom,receive_stacked},{atom,f6},0}.
+ {label,27}.
+ {allocate_zero,1,0}.
+ {label,28}.
+ {loop_rec,{f,30},{x,0}}.
+ {test,bs_start_match2,{f,29},1,[{x,0},0],{x,0}}.
+ {test,bs_get_integer2,
+ {f,29},
+ 1,
+ [{x,0},
+ {integer,8},
+ 1,
+ {field_flags,[{anno,[56,{file,"receive_stacked.erl"}]},
+ unsigned,big]}],
+ {x,1}}.
+ {test,bs_get_binary2,
+ {f,29},
+ 1,
+ [{x,0},
+ {atom,all},
+ 8,
+ {field_flags,[{anno,[56,{file,"receive_stacked.erl"}]},
+ unsigned,big]}],
+ {y,0}}.
+ {'%',
+ {no_bin_opt,
+ {binary_used_in,{gc_bif,byte_size,{f,29},0,[{y,0}],{x,0}}},
+ [56,{file,"receive_stacked.erl"}]}}.
+ {line,[{location,"receive_stacked.erl",56}]}.
+ {gc_bif,byte_size,{f,29},0,[{y,0}],{x,0}}.
+ {test,is_lt,{f,29},[{integer,8},{x,0}]}.
+ remove_message.
+ {move,{integer,42},{x,0}}.
+ {line,[{location,"receive_stacked.erl",57}]}.
+ {call,1,{f,52}}.
+ {move,{y,0},{x,0}}.
+ {deallocate,1}.
+ return.
+ {label,29}.
+ {loop_rec_end,{f,28}}.
+ {label,30}.
+ {wait,{f,28}}.
+
+
+{function, f7, 0, 32}.
+ {label,31}.
+ {line,[{location,"receive_stacked.erl",61}]}.
+ {func_info,{atom,receive_stacked},{atom,f7},0}.
+ {label,32}.
+ {allocate_zero,1,0}.
+ {label,33}.
+ {loop_rec,{f,35},{x,0}}.
+ {test,bs_start_match2,{f,34},1,[{x,0},0],{x,0}}.
+ {test,bs_get_integer2,
+ {f,34},
+ 1,
+ [{x,0},
+ {integer,8},
+ 1,
+ {field_flags,[{anno,[63,{file,"receive_stacked.erl"}]},
+ unsigned,big]}],
+ {x,1}}.
+ {test,bs_get_binary2,
+ {f,34},
+ 1,
+ [{x,0},
+ {atom,all},
+ 8,
+ {field_flags,[{anno,[63,{file,"receive_stacked.erl"}]},
+ unsigned,big]}],
+ {y,0}}.
+ {'%',{no_bin_opt,{binary_used_in,{test,is_binary,{f,34},[{y,0}]}},
+ [63,{file,"receive_stacked.erl"}]}}.
+ {test,is_binary,{f,34},[{y,0}]}.
+ remove_message.
+ {move,{integer,42},{x,0}}.
+ {line,[{location,"receive_stacked.erl",64}]}.
+ {call,1,{f,52}}.
+ {move,{y,0},{x,0}}.
+ {deallocate,1}.
+ return.
+ {label,34}.
+ {loop_rec_end,{f,33}}.
+ {label,35}.
+ {wait,{f,33}}.
+
+
+{function, f8, 0, 37}.
+ {label,36}.
+ {line,[{location,"receive_stacked.erl",68}]}.
+ {func_info,{atom,receive_stacked},{atom,f8},0}.
+ {label,37}.
+ {allocate_zero,1,0}.
+ {label,38}.
+ {loop_rec,{f,40},{x,0}}.
+ {test,bs_start_match2,{f,39},1,[{x,0},0],{x,1}}.
+ {test,bs_get_integer2,
+ {f,39},
+ 2,
+ [{x,1},
+ {integer,8},
+ 1,
+ {field_flags,[{anno,[70,{file,"receive_stacked.erl"}]},
+ unsigned,big]}],
+ {x,2}}.
+ {test,bs_get_binary2,
+ {f,39},
+ 2,
+ [{x,1},
+ {atom,all},
+ 8,
+ {field_flags,[{anno,[70,{file,"receive_stacked.erl"}]},
+ unsigned,big]}],
+ {y,0}}.
+ {'%',{no_bin_opt,{[{x,1},{y,0}],{loop_rec_end,{f,38}},not_handled},
+ [70,{file,"receive_stacked.erl"}]}}.
+ {test,is_binary,{f,39},[{x,0}]}.
+ remove_message.
+ {move,{integer,42},{x,0}}.
+ {line,[{location,"receive_stacked.erl",71}]}.
+ {call,1,{f,52}}.
+ {move,{y,0},{x,0}}.
+ {deallocate,1}.
+ return.
+ {label,39}.
+ {loop_rec_end,{f,38}}.
+ {label,40}.
+ {wait,{f,38}}.
+
+
+{function, m1, 0, 42}.
+ {label,41}.
+ {line,[{location,"receive_stacked.erl",75}]}.
+ {func_info,{atom,receive_stacked},{atom,m1},0}.
+ {label,42}.
+ {allocate_zero,1,0}.
+ {label,43}.
+ {loop_rec,{f,45},{x,0}}.
+ {test,is_map,{f,44},[{x,0}]}.
+ {get_map_elements,{f,44},{x,0},{list,[{atom,key},{y,0}]}}.
+ {test,is_integer,{f,44},[{y,0}]}.
+ remove_message.
+ {move,{integer,42},{x,0}}.
+ {line,[{location,"receive_stacked.erl",78}]}.
+ {call,1,{f,52}}.
+ {test_heap,2,0}.
+ {put_list,{y,0},nil,{x,0}}.
+ {deallocate,1}.
+ return.
+ {label,44}.
+ {loop_rec_end,{f,43}}.
+ {label,45}.
+ {wait,{f,43}}.
+
+
+{function, m2, 0, 47}.
+ {label,46}.
+ {line,[{location,"receive_stacked.erl",82}]}.
+ {func_info,{atom,receive_stacked},{atom,m2},0}.
+ {label,47}.
+ {allocate_zero,4,0}.
+ {move,{atom,key1},{x,0}}.
+ {line,[{location,"receive_stacked.erl",83}]}.
+ {call,1,{f,52}}.
+ {move,{x,0},{y,3}}.
+ {move,{atom,key2},{x,0}}.
+ {line,[{location,"receive_stacked.erl",84}]}.
+ {call,1,{f,52}}.
+ {move,{x,0},{y,2}}.
+ {label,48}.
+ {loop_rec,{f,50},{x,0}}.
+ {test,is_map,{f,49},[{x,0}]}.
+ {get_map_elements,{f,49},{x,0},{list,[{y,3},{y,1}]}}.
+ {get_map_elements,{f,49},{x,0},{list,[{y,2},{y,0}]}}.
+ {test,is_integer,{f,49},[{y,1}]}.
+ {test,is_integer,{f,49},[{y,0}]}.
+ remove_message.
+ {kill,{y,2}}.
+ {kill,{y,3}}.
+ {move,{integer,42},{x,0}}.
+ {line,[{location,"receive_stacked.erl",87}]}.
+ {call,1,{f,52}}.
+ {test_heap,3,0}.
+ {put_tuple,2,{x,0}}.
+ {put,{y,1}}.
+ {put,{y,0}}.
+ {deallocate,4}.
+ return.
+ {label,49}.
+ {loop_rec_end,{f,48}}.
+ {label,50}.
+ {wait,{f,48}}.
+
+
+{function, id, 1, 52}.
+ {label,51}.
+ {line,[{location,"receive_stacked.erl",91}]}.
+ {func_info,{atom,receive_stacked},{atom,id},1}.
+ {label,52}.
+ return.
+
+
+{function, module_info, 0, 54}.
+ {label,53}.
+ {line,[]}.
+ {func_info,{atom,receive_stacked},{atom,module_info},0}.
+ {label,54}.
+ {move,{atom,receive_stacked},{x,0}}.
+ {line,[]}.
+ {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
+
+
+{function, module_info, 1, 56}.
+ {label,55}.
+ {line,[]}.
+ {func_info,{atom,receive_stacked},{atom,module_info},1}.
+ {label,56}.
+ {move,{x,0},{x,1}}.
+ {move,{atom,receive_stacked},{x,0}}.
+ {line,[]}.
+ {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
diff --git a/lib/compiler/test/beam_validator_SUITE_data/receive_stacked.erl b/lib/compiler/test/beam_validator_SUITE_data/receive_stacked.erl
new file mode 100644
index 0000000000..b95fa9ca62
--- /dev/null
+++ b/lib/compiler/test/beam_validator_SUITE_data/receive_stacked.erl
@@ -0,0 +1,92 @@
+-module(receive_stacked).
+-compile([export_all,nowarn_export_all]).
+
+%% Messages may be stored outside any process heap until they
+%% have been accepted by the 'remove_message' instruction.
+%% When matching of a message fails, it is not allowed to
+%% leave references to the message or any part of it in
+%% the Y registers. An experimental code generator could
+%% do that, causing an emulator crash if there happenened to
+%% be a garbage collection.
+%%
+%% The 'S' file corresponding to this file was compiled with
+%% that experimental code generator.
+
+f1() ->
+ receive
+ X when is_integer(X) ->
+ id(42),
+ X
+ end.
+
+f2() ->
+ receive
+ [X] ->
+ Res = {ok,X},
+ id(42),
+ {Res,X}
+ end.
+
+f3() ->
+ receive
+ [H|_] when is_integer(H) ->
+ Res = {ok,H},
+ id(42),
+ {Res,H}
+ end.
+
+f4() ->
+ receive
+ [_|T] when is_list(T) ->
+ Res = {ok,T},
+ id(42),
+ {Res,T}
+ end.
+
+f5() ->
+ receive
+ {X} when is_integer(X) ->
+ Res = #{key=>X},
+ id(42),
+ {Res,X}
+ end.
+
+f6() ->
+ receive
+ <<_:8,T/binary>> when byte_size(T) > 8 ->
+ id(42),
+ T
+ end.
+
+f7() ->
+ receive
+ <<_:8,T/binary>> when is_binary(T) ->
+ id(42),
+ T
+ end.
+
+f8() ->
+ receive
+ <<_:8,T/binary>> = Bin when is_binary(Bin) ->
+ id(42),
+ T
+ end.
+
+m1() ->
+ receive
+ #{key:=V} when is_integer(V) ->
+ id(42),
+ [V]
+ end.
+
+m2() ->
+ K1 = id(key1),
+ K2 = id(key2),
+ receive
+ #{K1:=V1,K2:=V2} when is_integer(V1), is_integer(V2) ->
+ id(42),
+ {V1,V2}
+ end.
+
+id(I) ->
+ I.
diff --git a/lib/compiler/test/bif_SUITE.erl b/lib/compiler/test/bif_SUITE.erl
index bba2058f2f..42ba5d5365 100644
--- a/lib/compiler/test/bif_SUITE.erl
+++ b/lib/compiler/test/bif_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2016. All Rights Reserved.
+%% Copyright Ericsson AB 2016-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,6 @@ suite() ->
[{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -40,6 +39,7 @@ groups() ->
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/bs_bincomp_SUITE.erl b/lib/compiler/test/bs_bincomp_SUITE.erl
index dd1d245f88..0419b16eea 100644
--- a/lib/compiler/test/bs_bincomp_SUITE.erl
+++ b/lib/compiler/test/bs_bincomp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,22 +26,22 @@
init_per_group/2,end_per_group/2,
byte_aligned/1,bit_aligned/1,extended_byte_aligned/1,
extended_bit_aligned/1,mixed/1,filters/1,trim_coverage/1,
- nomatch/1,sizes/1,general_expressions/1]).
+ nomatch/1,sizes/1,general_expressions/1,matched_out_size/1]).
-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[byte_aligned, bit_aligned, extended_byte_aligned,
extended_bit_aligned, mixed, filters, trim_coverage,
- nomatch, sizes, general_expressions].
+ nomatch, sizes, general_expressions, matched_out_size].
groups() ->
[].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -338,6 +338,13 @@ general_expressions(_) ->
-undef(BAD).
+matched_out_size(Config) when is_list(Config) ->
+ <<1, 2>> = matched_out_size_1(<<4, 1:4, 4, 2:4>>),
+ ok.
+
+matched_out_size_1(Binary) ->
+ << <<X>> || <<S, X:S>> <= Binary>>.
+
cs_init() ->
erts_debug:set_internal_state(available_internal_state, true),
ok.
diff --git a/lib/compiler/test/bs_bit_binaries_SUITE.erl b/lib/compiler/test/bs_bit_binaries_SUITE.erl
index 208d8c5487..526769f3a6 100644
--- a/lib/compiler/test/bs_bit_binaries_SUITE.erl
+++ b/lib/compiler/test/bs_bit_binaries_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,7 +34,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -43,9 +42,10 @@ groups() ->
asymmetric_tests,big_asymmetric_tests,
binary_to_and_from_list,big_binary_to_and_from_list,
send_and_receive,send_and_receive_alot]}].
-
+
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/bs_construct_SUITE.erl b/lib/compiler/test/bs_construct_SUITE.erl
index da99aba346..ccc49df005 100644
--- a/lib/compiler/test/bs_construct_SUITE.erl
+++ b/lib/compiler/test/bs_construct_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -38,11 +38,10 @@ suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap,{minutes,1}}].
-all() ->
- test_lib:recompile(?MODULE),
+all() ->
[{group,p}].
-groups() ->
+groups() ->
[{p,[parallel],
[two,test1,fail,float_bin,in_guard,in_catch,
nasty_literals,side_effect,opt,otp_7556,float_arith,
@@ -50,6 +49,7 @@ groups() ->
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -303,7 +303,14 @@ fail(Config) when is_list(Config) ->
{'EXIT',{badarg,_}} = (catch <<42.0/integer>>),
{'EXIT',{badarg,_}} = (catch <<42/binary>>),
{'EXIT',{badarg,_}} = (catch <<an_atom/integer>>),
-
+
+ %% Bad literal sizes
+ Bin = i(<<>>),
+ {'EXIT',{badarg,_}} = (catch <<0:(-1)>>),
+ {'EXIT',{badarg,_}} = (catch <<Bin/binary,0:(-1)>>),
+ {'EXIT',{badarg,_}} = (catch <<0:(-(1 bsl 100))>>),
+ {'EXIT',{badarg,_}} = (catch <<Bin/binary,0:(-(1 bsl 100))>>),
+
ok.
float_bin(Config) when is_list(Config) ->
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index 0ec05456ec..e97dbac8a6 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -39,7 +39,8 @@
match_string_opt/1,select_on_integer/1,
map_and_binary/1,unsafe_branch_caching/1,
bad_literals/1,good_literals/1,constant_propagation/1,
- parse_xml/1,get_payload/1]).
+ parse_xml/1,get_payload/1,escape/1,num_slots_different/1,
+ beam_bsm/1,guard/1,is_ascii/1,non_opt_eq/1,erl_689/1]).
-export([coverage_id/1,coverage_external_ignore/2]).
@@ -52,7 +53,6 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -71,10 +71,12 @@ groups() ->
match_string_opt,select_on_integer,
map_and_binary,unsafe_branch_caching,
bad_literals,good_literals,constant_propagation,parse_xml,
- get_payload]}].
+ get_payload,escape,num_slots_different,
+ beam_bsm,guard,is_ascii,non_opt_eq,erl_689]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -328,6 +330,11 @@ save_restore(Config) when is_list(Config) ->
{"-",<<"x">>} = nnn(C),
{"-",<<"x">>} = ooo(C),
+ a = multiple_matches(<<777:16>>, <<777:16>>),
+ b = multiple_matches(<<777:16>>, <<999:16>>),
+ c = multiple_matches(<<777:16>>, <<57:8>>),
+ d = multiple_matches(<<17:8>>, <<1111:16>>),
+
Bin = <<-1:64>>,
case bad_float_unpack_match(Bin) of
-1 -> ok;
@@ -355,6 +362,11 @@ nnn(<<Char, Tail/binary>>) -> {[Char],Tail}. %% Buggy Tail!
ooo(<<" - ", Tail/binary>>) -> Tail;
ooo(<<Char, Tail/binary>>) -> {[Char],Tail}.
+multiple_matches(<<Y:16>>, <<Y:16>>) -> a;
+multiple_matches(<<_:16>>, <<_:16>>) -> b;
+multiple_matches(<<_:16>>, <<_:8>>) -> c;
+multiple_matches(<<_:8>>, <<_:16>>) -> d.
+
bad_float_unpack_match(<<F:64/float>>) -> F;
bad_float_unpack_match(<<I:64/integer-signed>>) -> I.
@@ -676,6 +688,10 @@ coverage(Config) when is_list(Config) ->
<<>> = coverage_per_key(<<4:32>>),
<<$a,$b,$c>> = coverage_per_key(<<7:32,"abc">>),
+ binary = coverage_bitstring(<<>>),
+ binary = coverage_bitstring(<<7>>),
+ bitstring = coverage_bitstring(<<7:4>>),
+ other = coverage_bitstring([a]),
ok.
coverage_fold(Fun, Acc, <<H,T/binary>>) ->
@@ -766,6 +782,10 @@ coverage_per_key(<<BinSize:32,Bin/binary>> = B) ->
true = (byte_size(B) =:= BinSize),
Bin.
+coverage_bitstring(Bin) when is_binary(Bin) -> binary;
+coverage_bitstring(<<_/bitstring>>) -> bitstring;
+coverage_bitstring(_) -> other.
+
multiple_uses(Config) when is_list(Config) ->
{344,62879,345,<<245,159,1,89>>} = multiple_uses_1(<<1,88,245,159,1,89>>),
true = multiple_uses_2(<<0,0,197,18>>),
@@ -799,7 +819,7 @@ multiple_uses_cmp(<<_:16>>, <<_:16>>) -> false.
first_after(Data, Offset) ->
case byte_size(Data) > Offset of
false ->
- {First, Rest} = {ok, ok},
+ {_First, _Rest} = {ok, ok},
ok;
true ->
<<_:Offset/binary, Rest/binary>> = Data,
@@ -1513,7 +1533,7 @@ is_next_char_whitespace(<<C/utf8,_/binary>>) ->
{this_hdr = 17,
ext_hdr_opts}).
-get_payload(Config) ->
+get_payload(_Config) ->
<<3445:48>> = do_get_payload(#ext_header{ext_hdr_opts = <<3445:48>>}),
{'EXIT',_} = (catch do_get_payload(#ext_header{})),
ok.
@@ -1524,6 +1544,211 @@ do_get_payload(ExtHdr) ->
<<_:13,_:35>> = ExtHdr#ext_header.ext_hdr_opts,
ExtHdrOptions.
+escape(_Config) ->
+ 0 = escape(<<>>, 0),
+ 1 = escape(<<128>>, 0),
+ 2 = escape(<<128,255>>, 0),
+ 42 = escape(<<42>>, 0),
+ 50 = escape(<<42,8>>, 0),
+ ok.
+
+escape(<<Byte, Rest/bits>>, Pos) when Byte >= 127 ->
+ escape(Rest, Pos + 1);
+escape(<<Byte, Rest/bits>>, Pos) ->
+ escape(Rest, Pos + Byte);
+escape(<<_Rest/bits>>, Pos) ->
+ Pos.
+
+%% ERL-490
+num_slots_different(_Config) ->
+ Ts = [{<<"de">>, <<"default">>, <<"Remove">>, <<"a">>},
+ {<<"de">>, <<"default">>, <<"Remove from list">>, <<"a">>},
+ {<<"de">>, <<"default">>, <<"Remove from the list">>, <<"a">>},
+ {<<"de">>, <<"default">>, <<"Results">>, <<"Ergebnisse">>},
+ {<<"de">>, <<"default">>, <<"Reservatio">>, <<"a">>},
+ {<<"de">>, <<"navigation">>, <<"Results">>, <<"Ergebnisse">>},
+ {<<"de">>, <<"navigation">>, <<"Resources">>, <<"Ressourcen">>}],
+ _ = [{ok,Res} = lgettext(A, B, C) || {A,B,C,Res} <- Ts],
+
+ {'EXIT',_} = (catch lgettext(<<"d">>, <<"default">>, <<"Remove">>)),
+ {'EXIT',_} = (catch lgettext("", <<"default">>, <<"Remove">>)),
+ {'EXIT',_} = (catch lgettext(<<"de">>, <<"def">>, <<"Remove">>)),
+ {'EXIT',_} = (catch lgettext(<<"de">>, <<"default">>, <<"Res">>)),
+ ok.
+
+
+lgettext(<<"de">>, <<"default">>, <<"Remove">>) ->
+ {ok, <<"a">>};
+lgettext(<<"de">>, <<"default">>, <<"Remove from list">>) ->
+ {ok, <<"a">>};
+lgettext(<<"de">>, <<"default">>, <<"Remove from the list">>) ->
+ {ok, <<"a">>};
+lgettext(<<"de">>, <<"default">>, <<"Results">>) ->
+ {ok, <<"Ergebnisse">>};
+lgettext(<<"de">>, <<"default">>, <<"Reservatio">>) ->
+ {ok, <<"a">>};
+lgettext(<<"de">>, <<"navigation">>, <<"Results">>) ->
+ {ok, <<"Ergebnisse">>};
+lgettext(<<"de">>, <<"navigation">>, <<"Resources">>) ->
+ {ok, <<"Ressourcen">>}.
+
+%% Test more code in beam_bsm.
+beam_bsm(_Config) ->
+ true = check_bitstring_list(<<1:1,0:1,1:1,1:1>>, [1,0,1,1]),
+ false = check_bitstring_list(<<1:1,0:1,1:1,1:1>>, [0]),
+
+ true = bsm_validate_scheme(<<>>),
+ true = bsm_validate_scheme(<<5,10>>),
+ false = bsm_validate_scheme(<<5,10,11,12>>),
+ true = bsm_validate_scheme([]),
+ true = bsm_validate_scheme([5,10]),
+ false = bsm_validate_scheme([5,6,7]),
+
+ <<1,2,3>> = bsm_must_save_and_not_save(<<1,2,3>>, []),
+ D = fun(N) -> 2*N end,
+ [2,4|<<3>>] = bsm_must_save_and_not_save(<<1,2,3>>, [D,D]),
+
+ ok.
+
+check_bitstring_list(<<H:1,T1/bitstring>>, [H|T2]) ->
+ check_bitstring_list(T1, T2);
+check_bitstring_list(<<>>, []) ->
+ true;
+check_bitstring_list(_, _) ->
+ false.
+
+bsm_validate_scheme([]) -> true;
+bsm_validate_scheme([H|T]) ->
+ case bsm_is_scheme(H) of
+ true -> bsm_validate_scheme(T);
+ false -> false
+ end;
+bsm_validate_scheme(<<>>) -> true;
+bsm_validate_scheme(<<H, Rest/binary>>) ->
+ case bsm_is_scheme(H) of
+ true -> bsm_validate_scheme(Rest);
+ false -> false
+ end.
+
+bsm_is_scheme(Int) ->
+ Int rem 5 =:= 0.
+
+%% NOT OPTIMIZED: different control paths use different positions in the binary
+bsm_must_save_and_not_save(Bin, []) ->
+ Bin;
+bsm_must_save_and_not_save(<<H,T/binary>>, [F|Fs]) ->
+ [F(H)|bsm_must_save_and_not_save(T, Fs)];
+bsm_must_save_and_not_save(<<>>, []) ->
+ [].
+
+guard(_Config) ->
+ _Tuple = id({a,b}),
+ ok = guard_1(<<1,2,3>>, {1,2,3}),
+ ok = guard_2(<<42>>, #{}),
+ ok.
+
+%% Cover handling of #k_put{} in v3_codegen:bsm_rename_ctx/4.
+guard_1(<<A,B,C>>, Tuple) when Tuple =:= {A,B,C} ->
+ ok.
+
+%% Cover handling of #k_call{} in v3_codegen:bsm_rename_ctx/4.
+guard_2(<<_>>, Healing) when Healing#{[] => Healing} =:= #{[] => #{}} ->
+ ok.
+
+is_ascii(_Config) ->
+ true = do_is_ascii(<<>>),
+ true = do_is_ascii(<<"string">>),
+ false = do_is_ascii(<<1024/utf8>>),
+ {'EXIT',{function_clause,_}} = (catch do_is_ascii(<<$A,0:3>>)),
+ {'EXIT',{function_clause,_}} = (catch do_is_ascii(<<16#80,0:3>>)),
+ ok.
+
+do_is_ascii(<<>>) ->
+ true;
+do_is_ascii(<<C,_/binary>>) when C >= 16#80 ->
+ %% This clause must fail to match if the size of the argument in
+ %% bits is not divisible by 8. Beware of unsafe optimizations.
+ false;
+do_is_ascii(<<_, T/binary>>) ->
+ do_is_ascii(T).
+
+non_opt_eq(_Config) ->
+ true = non_opt_eq([], <<>>),
+ true = non_opt_eq([$a], <<$a>>),
+ false = non_opt_eq([$a], <<$b>>),
+ ok.
+
+%% An example from the Efficiency Guide. It used to be not optimized,
+%% but now it can be optimized.
+
+non_opt_eq([H|T1], <<H,T2/binary>>) ->
+ non_opt_eq(T1, T2);
+non_opt_eq([_|_], <<_,_/binary>>) ->
+ false;
+non_opt_eq([], <<>>) ->
+ true.
+
+%% ERL-689
+
+erl_689(_Config) ->
+ {{0, 0, 0}, <<>>} = do_erl_689_1(<<0>>, ?MODULE),
+ {{2018, 8, 7}, <<>>} = do_erl_689_1(<<4,2018:16/little,8,7>>, ?MODULE),
+ {{0, 0, 0}, <<>>} = do_erl_689_2(?MODULE, <<0>>),
+ {{2018, 8, 7}, <<>>} = do_erl_689_2(?MODULE, <<4,2018:16/little,8,7>>),
+ ok.
+
+do_erl_689_1(Arg1, Arg2) ->
+ Res = do_erl_689_1a(Arg1, Arg2),
+ Res = do_erl_689_1b(Arg1, Arg2).
+
+do_erl_689_2(Arg1, Arg2) ->
+ Res = do_erl_689_2a(Arg1, Arg2),
+ Res = do_erl_689_2b(Arg1, Arg2).
+
+do_erl_689_1a(<<Length, Data/binary>>, _) ->
+ case {Data, Length} of
+ {_, 0} ->
+ %% bs_context_to_binary would incorrectly set Data to the original
+ %% binary (before matching in the function head).
+ {{0, 0, 0}, Data};
+ {<<Y:16/little, M, D, Rest/binary>>, 4} ->
+ {{Y, M, D}, Rest}
+ end.
+
+do_erl_689_1b(<<Length, Data/binary>>, _) ->
+ case {Data, Length} of
+ {_, 0} ->
+ %% bs_context_to_binary would incorrectly set Data to the original
+ %% binary (before matching in the function head).
+ id(0),
+ {{0, 0, 0}, Data};
+ {<<Y:16/little, M, D, Rest/binary>>, 4} ->
+ id(1),
+ {{Y, M, D}, Rest}
+ end.
+
+do_erl_689_2a(_, <<Length, Data/binary>>) ->
+ case {Length, Data} of
+ {0, _} ->
+ %% bs_context_to_binary would incorrectly set Data to the original
+ %% binary (before matching in the function head).
+ {{0, 0, 0}, Data};
+ {4, <<Y:16/little, M, D, Rest/binary>>} ->
+ {{Y, M, D}, Rest}
+ end.
+
+do_erl_689_2b(_, <<Length, Data/binary>>) ->
+ case {Length, Data} of
+ {0, _} ->
+ %% bs_context_to_binary would incorrectly set Data to the original
+ %% binary (before matching in the function head).
+ id(0),
+ {{0, 0, 0}, Data};
+ {4, <<Y:16/little, M, D, Rest/binary>>} ->
+ id(1),
+ {{Y, M, D}, Rest}
+ end.
+
check(F, R) ->
R = F().
diff --git a/lib/compiler/test/bs_utf_SUITE.erl b/lib/compiler/test/bs_utf_SUITE.erl
index ef3fc54b37..8ea4a849ec 100644
--- a/lib/compiler/test/bs_utf_SUITE.erl
+++ b/lib/compiler/test/bs_utf_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,7 +31,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[utf8_roundtrip, unused_utf_char, utf16_roundtrip,
utf32_roundtrip, guard, extreme_tripping, literals,
coverage].
@@ -40,6 +39,7 @@ groups() ->
[].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl
index a4de125d32..139f7af0d4 100644
--- a/lib/compiler/test/compilation_SUITE.erl
+++ b/lib/compiler/test/compilation_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -66,7 +66,6 @@ suite() ->
{timetrap,{minutes,10}}].
all() ->
- test_lib:recompile(?MODULE),
[self_compile_old_inliner,self_compile,
{group,p}].
@@ -88,6 +87,7 @@ groups() ->
string_table,otp_8949_a,split_cases]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/compilation_SUITE_data/opt_crash.erl b/lib/compiler/test/compilation_SUITE_data/opt_crash.erl
index f1607cca68..4643ce61f6 100644
--- a/lib/compiler/test/compilation_SUITE_data/opt_crash.erl
+++ b/lib/compiler/test/compilation_SUITE_data/opt_crash.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@ test() ->
{userinfo,nil},
fun() -> nil end},
nil},
- {'query',nil}}},
+ {query,nil}}},
{absoluteURI,
{scheme,_},
@@ -43,7 +43,7 @@ test() ->
{userinfo,nil},
HostportBefore},
nil},
- {'query',nil}}} = URI_Before,
+ {query,nil}}} = URI_Before,
%% ... some funky code ommitted, not relevant ...
@@ -55,7 +55,7 @@ test() ->
{userinfo,nil},
HostportAfter},
nil},
- {'query',nil}}} = URI_Before,
+ {query,nil}}} = URI_Before,
%% NOTE: I intended to write URI_After instead of URI_Before
%% but the accident revealed that when you add the line below,
%% it causes internal error in v3_codegen on compilation
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index f647a4030d..6b230710b3 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,16 +27,16 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
app_test/1,appup_test/1,
- debug_info/4, custom_debug_info/1,
+ debug_info/4, custom_debug_info/1, custom_compile_info/1,
file_1/1, forms_2/1, module_mismatch/1, big_file/1, outdir/1,
binary/1, makedep/1, cond_and_ifdef/1, listings/1, listings_big/1,
other_output/1, kernel_listing/1, encrypted_abstr/1,
strict_record/1, utf8_atoms/1, utf8_functions/1, extra_chunks/1,
- cover/1, env/1, core_pp/1,
+ cover/1, env/1, core_pp/1, tuple_calls/1,
core_roundtrip/1, asm/1, optimized_guards/1,
sys_pre_attributes/1, dialyzer/1,
warnings/1, pre_load_check/1, env_compiler_options/1,
- bc_options/1
+ bc_options/1, deterministic_include/1, deterministic_paths/1
]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -46,19 +46,20 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
-spec all() -> all_return_type().
all() ->
- test_lib:recompile(?MODULE),
[app_test, appup_test, file_1, forms_2, module_mismatch, big_file, outdir,
binary, makedep, cond_and_ifdef, listings, listings_big,
- other_output, kernel_listing, encrypted_abstr,
+ other_output, kernel_listing, encrypted_abstr, tuple_calls,
strict_record, utf8_atoms, utf8_functions, extra_chunks,
cover, env, core_pp, core_roundtrip, asm, optimized_guards,
sys_pre_attributes, dialyzer, warnings, pre_load_check,
- env_compiler_options, custom_debug_info, bc_options].
+ env_compiler_options, custom_debug_info, bc_options,
+ custom_compile_info, deterministic_include, deterministic_paths].
groups() ->
[].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -119,9 +120,19 @@ file_1(Config) when is_list(Config) ->
true = exists(Target),
passed = run(Target, test, []),
+ %% Test option 'deterministic' as a compiler attribute.
+ Det = deterministic_module,
+ {DetPath, DetTarget} = get_files(Config, Det, "det_target"),
+ {ok,Det,DetCode} = compile:file(DetPath, [binary]),
+ {module,Det} = code:load_binary(Det, "", DetCode),
+ [{version,_}] = Det:module_info(compile),
+ true = code:delete(Det),
+ false = code:purge(Det),
+
%% Cleanup.
ok = file:delete(Target),
ok = file:del_dir(filename:dirname(Target)),
+ ok = file:del_dir(filename:dirname(DetTarget)),
%% There should not be any messages in the messages.
receive
@@ -374,7 +385,6 @@ do_file_listings(DataDir, PrivDir, [File|Files]) ->
do_listing(Simple, TargetDir, dcbsm, ".core_bsm"),
do_listing(Simple, TargetDir, dsetel, ".dsetel"),
do_listing(Simple, TargetDir, dkern, ".kernel"),
- do_listing(Simple, TargetDir, dlife, ".life"),
do_listing(Simple, TargetDir, dcg, ".codegen"),
do_listing(Simple, TargetDir, dblk, ".block"),
do_listing(Simple, TargetDir, dexcept, ".except"),
@@ -398,6 +408,7 @@ do_file_listings(DataDir, PrivDir, [File|Files]) ->
ok = file:delete(filename:join(Listings, File ++ ".core")),
do_listing(Simple, TargetDir, to_core, ".core"),
do_listing(Simple, TargetDir, to_kernel, ".kernel"),
+ do_listing(Simple, TargetDir, to_dis, ".dis"),
%% Final clean up.
lists:foreach(fun(F) -> ok = file:delete(F) end,
@@ -413,6 +424,7 @@ listings_big(Config) when is_list(Config) ->
do_listing(Big, TargetDir, 'E'),
do_listing(Big, TargetDir, 'P'),
do_listing(Big, TargetDir, dkern, ".kernel"),
+ do_listing(Big, TargetDir, to_dis, ".dis"),
TargetNoext = filename:rootname(Target, code:objfile_extension()),
{ok,big} = compile:file(TargetNoext, [from_asm,{outdir,TargetDir}]),
@@ -488,9 +500,8 @@ do_kernel_listing({M,A}) ->
io:format("*** compilation failure '~p' for module ~s\n",
[Error,M]),
error;
- Class:Error ->
- io:format("~p: ~p ~p\n~p\n",
- [M,Class,Error,erlang:get_stacktrace()]),
+ Class:Error:Stk ->
+ io:format("~p: ~p ~p\n~p\n", [M,Class,Error,Stk]),
error
end.
@@ -649,6 +660,23 @@ custom_debug_info(Config) when is_list(Config) ->
{ok,{simple,[{debug_info,{debug_info_v1,?MODULE,error}}]}} =
beam_lib:chunks(ErrorBin, [debug_info]).
+custom_compile_info(Config) when is_list(Config) ->
+ Anno = erl_anno:new(1),
+ Forms = [{attribute,Anno,module,custom_compile_info}],
+ Opts = [binary,{compile_info,[{another,version}]}],
+
+ {ok,custom_compile_info,Bin} = compile:forms(Forms, Opts),
+ {ok,{custom_compile_info,[{compile_info,CompileInfo}]}} =
+ beam_lib:chunks(Bin, [compile_info]),
+ version = proplists:get_value(another, CompileInfo),
+ CompileOpts = proplists:get_value(options, CompileInfo),
+ undefined = proplists:get_value(compile_info, CompileOpts),
+
+ {ok,custom_compile_info,DetBin} = compile:forms(Forms, [deterministic|Opts]),
+ {ok,{custom_compile_info,[{compile_info,DetInfo}]}} =
+ beam_lib:chunks(DetBin, [compile_info]),
+ version = proplists:get_value(another, DetInfo).
+
cover(Config) when is_list(Config) ->
io:format("~p\n", [compile:options()]),
ok.
@@ -781,6 +809,37 @@ extra_chunks(Config) when is_list(Config) ->
{ok,{extra_chunks,[{"ExCh",<<"Contents">>}]}} =
beam_lib:chunks(ExtraChunksBinary, ["ExCh"]).
+tuple_calls(Config) when is_list(Config) ->
+ Anno = erl_anno:new(1),
+ Forms = [{attribute,Anno,export,[{size,1},{store,1}]},
+ {function,Anno,size,1,
+ [{clause,Anno,[{var,[],mod}],[],
+ [{call,[],{remote,[],{var,[],mod},{atom,[],size}},[]}]}]},
+ {function,Anno,store,1,
+ [{clause,Anno,[{var,[],mod}],[],
+ [{call,[],{remote,[],{var,[],mod},{atom,[],store}},[{atom,[],key},{atom,[],value}]}]}]}],
+
+ TupleCallsFalse = [{attribute,Anno,module,tuple_calls_false}|Forms],
+ {ok,_,TupleCallsFalseBinary} = compile:forms(TupleCallsFalse, [binary]),
+ code:load_binary(tuple_calls_false, "compile_SUITE.erl", TupleCallsFalseBinary),
+ {'EXIT',{badarg,_}} = (catch tuple_calls_false:store(dict())),
+ {'EXIT',{badarg,_}} = (catch tuple_calls_false:size(dict())),
+ {'EXIT',{badarg,_}} = (catch tuple_calls_false:size(empty_tuple())),
+
+ TupleCallsTrue = [{attribute,Anno,module,tuple_calls_true}|Forms],
+ {ok,_,TupleCallsTrueBinary} = compile:forms(TupleCallsTrue, [binary,tuple_calls]),
+ code:load_binary(tuple_calls_true, "compile_SUITE.erl", TupleCallsTrueBinary),
+ Dict = tuple_calls_true:store(dict()),
+ 1 = tuple_calls_true:size(Dict),
+ {'EXIT',{badarg,_}} = (catch tuple_calls_true:size(empty_tuple())),
+
+ ok.
+
+dict() ->
+ dict:new().
+empty_tuple() ->
+ {}.
+
env(Config) when is_list(Config) ->
{Simple,Target} = get_files(Config, simple, env),
{ok,Cwd} = file:get_cwd(),
@@ -842,9 +901,8 @@ do_core_pp({M,A}, Outdir) ->
io:format("*** compilation failure '~p' for module ~s\n",
[Error,M]),
error;
- Class:Error ->
- io:format("~p: ~p ~p\n~p\n",
- [M,Class,Error,erlang:get_stacktrace()]),
+ Class:Error:Stk ->
+ io:format("~p: ~p ~p\n~p\n", [M,Class,Error,Stk]),
error
end.
@@ -901,9 +959,8 @@ do_core_roundtrip(Beam, Outdir) ->
io:format("*** compilation failure '~p' for file ~s\n",
[Error,Beam]),
error;
- Class:Error ->
- io:format("~p: ~p ~p\n~p\n",
- [Beam,Class,Error,erlang:get_stacktrace()]),
+ Class:Error:Stk ->
+ io:format("~p: ~p ~p\n~p\n", [Beam,Class,Error,Stk]),
error
end.
@@ -1054,10 +1111,30 @@ remove_compiler_gen(M) ->
remove_compiler_gen_1(Pair) ->
Op0 = cerl:map_pair_op(Pair),
Op = cerl:set_ann(Op0, []),
- K = cerl:map_pair_key(Pair),
- V = cerl:map_pair_val(Pair),
+ K = map_var(cerl:map_pair_key(Pair)),
+ V = map_var(cerl:map_pair_val(Pair)),
cerl:update_c_map_pair(Pair, Op, K, V).
+map_var(Var) ->
+ case cerl:is_c_var(Var) of
+ true ->
+ case cerl:var_name(Var) of
+ Name when is_atom(Name) ->
+ L = atom_to_list(Name),
+ try list_to_integer(L) of
+ Int ->
+ cerl:update_c_var(Var, Int)
+ catch
+ error:_ ->
+ Var
+ end;
+ _ ->
+ Var
+ end;
+ false ->
+ Var
+ end.
+
%% Compile to Beam assembly language (.S) and then try to
%% run .S through the compiler again.
@@ -1088,9 +1165,8 @@ do_asm(Beam, Outdir) ->
[Other,AsmFile]),
error
end
- catch Class:Error ->
- io:format("~p: ~p ~p\n~p\n",
- [M,Class,Error,erlang:get_stacktrace()]),
+ catch Class:Error:Stk ->
+ io:format("~p: ~p ~p\n~p\n", [M,Class,Error,Stk]),
error
end.
@@ -1107,9 +1183,8 @@ do_opt_guards(Beam) ->
try
{ok,M,Asm} = compile:forms(A, ['S']),
do_opt_guards_mod(Asm)
- catch Class:Error ->
- io:format("~p: ~p ~p\n~p\n",
- [M,Class,Error,erlang:get_stacktrace()]),
+ catch Class:Error:Stk ->
+ io:format("~p: ~p ~p\n~p\n", [M,Class,Error,Stk]),
error
end.
@@ -1270,10 +1345,13 @@ do_warnings_2([], Next, F) ->
%% pre-loads the modules that are used by a typical compilation.
pre_load_check(Config) ->
- case test_server:is_cover() of
- true ->
+ case {test_server:is_cover(),code:module_info(native)} of
+ {true,_} ->
{skip,"Cover is running"};
- false ->
+ {false,true} ->
+ %% Tracing won't work.
+ {skip,"'code' is native-compiled"};
+ {false,false} ->
try
do_pre_load_check(Config)
after
@@ -1397,19 +1475,21 @@ env_compiler_options(_Config) ->
bc_options(Config) ->
DataDir = proplists:get_value(data_dir, Config),
- 101 = highest_opcode(DataDir, small_float, [no_line_info]),
+ 101 = highest_opcode(DataDir, small_float, [no_get_hd_tl,no_line_info]),
103 = highest_opcode(DataDir, big,
- [no_record_opt,no_line_info,no_stack_trimming]),
+ [no_get_hd_tl,no_record_opt,
+ no_line_info,no_stack_trimming]),
- 125 = highest_opcode(DataDir, small_float, [no_line_info,no_float_opt]),
+ 125 = highest_opcode(DataDir, small_float,
+ [no_get_hd_tl,no_line_info,no_float_opt]),
132 = highest_opcode(DataDir, small,
- [no_record_opt,no_float_opt,no_line_info]),
+ [no_get_hd_tl,no_record_opt,no_float_opt,no_line_info]),
- 136 = highest_opcode(DataDir, big, [no_record_opt,no_line_info]),
+ 136 = highest_opcode(DataDir, big, [no_get_hd_tl,no_record_opt,no_line_info]),
- 153 = highest_opcode(DataDir, big, [no_record_opt]),
+ 153 = highest_opcode(DataDir, big, [no_get_hd_tl,no_record_opt]),
153 = highest_opcode(DataDir, big, [r16]),
153 = highest_opcode(DataDir, big, [r17]),
153 = highest_opcode(DataDir, big, [r18]),
@@ -1420,9 +1500,10 @@ bc_options(Config) ->
158 = highest_opcode(DataDir, small_maps, [r17]),
158 = highest_opcode(DataDir, small_maps, [r18]),
158 = highest_opcode(DataDir, small_maps, [r19]),
+ 158 = highest_opcode(DataDir, small_maps, [r20]),
158 = highest_opcode(DataDir, small_maps, []),
- 159 = highest_opcode(DataDir, big, []),
+ 163 = highest_opcode(DataDir, big, []),
ok.
@@ -1433,6 +1514,47 @@ highest_opcode(DataDir, Mod, Opt) ->
<<16:32,0:32,HighestOpcode:32,_/binary>> = Code,
HighestOpcode.
+deterministic_include(Config) when is_list(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ Simple = filename:join(DataDir, "simple"),
+
+ %% Files without +deterministic should differ if their include paths do,
+ %% as their debug info will be different.
+ {ok,_,NonDetA} = compile:file(Simple, [binary, {i,"gurka"}]),
+ {ok,_,NonDetB} = compile:file(Simple, [binary, {i,"gaffel"}]),
+ true = NonDetA =/= NonDetB,
+
+ %% ... but files with +deterministic shouldn't.
+ {ok,_,DetC} = compile:file(Simple, [binary, deterministic, {i,"gurka"}]),
+ {ok,_,DetD} = compile:file(Simple, [binary, deterministic, {i,"gaffel"}]),
+ true = DetC =:= DetD,
+
+ ok.
+
+deterministic_paths(Config) when is_list(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+
+ %% Files without +deterministic should differ if they were compiled from a
+ %% different directory.
+ true = deterministic_paths_1(DataDir, "simple", []),
+
+ %% ... but files with +deterministic shouldn't.
+ false = deterministic_paths_1(DataDir, "simple", [deterministic]),
+
+ ok.
+
+deterministic_paths_1(DataDir, Name, Opts) ->
+ Simple = filename:join(DataDir, "simple"),
+ {ok, Cwd} = file:get_cwd(),
+ try
+ {ok,_,A} = compile:file(Simple, [binary | Opts]),
+ ok = file:set_cwd(DataDir),
+ {ok,_,B} = compile:file(Name, [binary | Opts]),
+ A =/= B
+ after
+ file:set_cwd(Cwd)
+ end.
+
%%%
%%% Utilities.
%%%
diff --git a/lib/compiler/test/compile_SUITE_data/big.erl b/lib/compiler/test/compile_SUITE_data/big.erl
index 2e54ee8660..765c71c07d 100644
--- a/lib/compiler/test/compile_SUITE_data/big.erl
+++ b/lib/compiler/test/compile_SUITE_data/big.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -741,3 +741,7 @@ snmp_access(suite) ->
debug_support(suite) ->
[ info, schema, schema, kill, lkill ].
+%% Cover translation of get_hd/2 to get_list/3 when option no_get_hd_tl
+%% is given.
+cover_get_hd([Hd|_]) ->
+ Hd.
diff --git a/lib/compiler/test/compile_SUITE_data/deterministic_module.erl b/lib/compiler/test/compile_SUITE_data/deterministic_module.erl
new file mode 100644
index 0000000000..5e0e29c25e
--- /dev/null
+++ b/lib/compiler/test/compile_SUITE_data/deterministic_module.erl
@@ -0,0 +1,21 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(deterministic_module).
+-compile([deterministic]).
diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl
index f8839da42f..e5611e99d1 100644
--- a/lib/compiler/test/core_SUITE.erl
+++ b/lib/compiler/test/core_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,7 +28,8 @@
map_core_test/1,eval_case/1,bad_boolean_guard/1,
bs_shadowed_size_var/1,
cover_v3_kernel_1/1,cover_v3_kernel_2/1,cover_v3_kernel_3/1,
- cover_v3_kernel_4/1,cover_v3_kernel_5/1]).
+ cover_v3_kernel_4/1,cover_v3_kernel_5/1,
+ non_variable_apply/1,name_capture/1,fun_letrec_effect/1]).
-include_lib("common_test/include/ct.hrl").
@@ -46,7 +47,6 @@ suite() ->
{timetrap,{minutes,5}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -56,11 +56,13 @@ groups() ->
map_core_test,eval_case,bad_boolean_guard,
bs_shadowed_size_var,
cover_v3_kernel_1,cover_v3_kernel_2,cover_v3_kernel_3,
- cover_v3_kernel_4,cover_v3_kernel_5
+ cover_v3_kernel_4,cover_v3_kernel_5,
+ non_variable_apply,name_capture,fun_letrec_effect
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -90,7 +92,9 @@ end_per_group(_GroupName, Config) ->
?comp(cover_v3_kernel_3).
?comp(cover_v3_kernel_4).
?comp(cover_v3_kernel_5).
-
+?comp(non_variable_apply).
+?comp(name_capture).
+?comp(fun_letrec_effect).
try_it(Mod, Conf) ->
Src = filename:join(proplists:get_value(data_dir, Conf),
diff --git a/lib/compiler/test/core_SUITE_data/fun_letrec_effect.core b/lib/compiler/test/core_SUITE_data/fun_letrec_effect.core
new file mode 100644
index 0000000000..ab6f5b7940
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/fun_letrec_effect.core
@@ -0,0 +1,25 @@
+module 'fun_letrec_effect' ['fun_letrec_effect'/0, 'ok'/0, 'wat'/0]
+attributes []
+
+'fun_letrec_effect'/0 =
+ fun () ->
+ do apply 'wat'/0()
+ receive
+ <'bar'> when 'true' -> 'ok'
+ <_0> when 'true' -> 'failed'
+ after 'infinity' ->
+ 'true'
+
+%% The return value (bar) of the fun was optimized away because the result of
+%% the `letrec ... in` was unused, despite the fun's return value being
+%% relevant for the side-effect of the expression.
+'wat'/0 =
+ fun () ->
+ let <Self> = call 'erlang':'self'() in
+ do letrec 'f'/0 = fun () ->
+ do call 'maps':'put'('foo', 'bar', ~{}~)
+ 'bar'
+ in call 'erlang':'send'(Self, apply 'f'/0())
+ 'undefined'
+
+end
diff --git a/lib/compiler/test/core_SUITE_data/name_capture.core b/lib/compiler/test/core_SUITE_data/name_capture.core
new file mode 100644
index 0000000000..0969f95b72
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/name_capture.core
@@ -0,0 +1,110 @@
+module 'name_capture' ['module_info'/0,
+ 'module_info'/1,
+ 'name_capture'/0]
+ attributes ['compile' =
+ [{'inline',[{'badarg_exit',2}]}]]
+'name_capture'/0 =
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ let <_0> =
+ catch
+ apply 'first'/1
+ ('badarg')
+ in case _0 of
+ <{'EXIT',{'badarg',_7}}> when 'true' ->
+ let <Seq> =
+ call 'lists':'seq'
+ (7, 17)
+ in case apply 'first'/1
+ ({'ok',Seq}) of
+ <_8>
+ when call 'erlang':'=:='
+ (_8,
+ Seq) ->
+ let <SomeOtherTerm> =
+ {'some','other','term'}
+ in let <_5> =
+ catch
+ apply 'first'/1
+ (SomeOtherTerm)
+ in case _5 of
+ <{'EXIT',_9}>
+ when call 'erlang':'=:='
+ (_9,
+ SomeOtherTerm) ->
+ 'ok'
+ <_6> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_6})
+ end
+ <_3> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_3})
+ end
+ <_1> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_1})
+ end
+ <> when 'true' ->
+ primop 'match_fail'
+ ({'function_clause'})
+ end
+'first'/1 =
+ fun (_0) ->
+ case _0 of
+ <Tab> when 'true' ->
+ let <_1> =
+ apply 'treq'/2
+ (Tab, 'first')
+ %% The _1 variable in the `let` must be renamed
+ %% to avoid a name capture problem.
+ in let <_0,_1> =
+ <_1,[Tab|[]]>
+ in case <_0,_1> of
+ <'badarg',A> when 'true' ->
+ call 'erlang':'error'
+ ('badarg', A)
+ <{'ok',Reply},_X_A> when 'true' ->
+ Reply
+ <Reply,_X_A> when 'true' ->
+ call 'erlang':'exit'
+ (Reply)
+ <_3,_2> when 'true' ->
+ primop 'match_fail'
+ ({'function_clause',_3,_2})
+ end
+ <_2> when 'true' ->
+ primop 'match_fail'
+ ({'function_clause',_2})
+ end
+'treq'/2 =
+ fun (_0,_1) ->
+ case <_0,_1> of
+ <Action,_4> when 'true' ->
+ Action
+ <_3,_2> when 'true' ->
+ primop 'match_fail'
+ ({'function_clause',_3,_2})
+ end
+'module_info'/0 =
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ call 'erlang':'get_module_info'
+ ('name_capture')
+ <> when 'true' ->
+ primop 'match_fail'
+ ({'function_clause'})
+ end
+'module_info'/1 =
+ fun (_0) ->
+ case _0 of
+ <X> when 'true' ->
+ call 'erlang':'get_module_info'
+ ('name_capture', X)
+ <_1> when 'true' ->
+ primop 'match_fail'
+ ({'function_clause',_1})
+ end
+end
diff --git a/lib/compiler/test/core_SUITE_data/non_variable_apply.core b/lib/compiler/test/core_SUITE_data/non_variable_apply.core
new file mode 100644
index 0000000000..d9322cc455
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/non_variable_apply.core
@@ -0,0 +1,80 @@
+module 'non_variable_apply' ['module_info'/0,
+ 'module_info'/1,
+ 'non_variable_apply'/0]
+ attributes []
+
+'non_variable_apply'/0 =
+ %% Line 4
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ let <OkFun> =
+ fun (_@c0) ->
+ %% Line 5
+ case _@c0 of
+ <'ok'> when 'true' ->
+ 'ok'
+ ( <_@c1> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_@c1})
+ -| [{'function_name',{'-non_variable_apply/0-fun-0-',1}}] )
+ -| ['compiler_generated'] )
+ end
+ in let <F> =
+ fun (_@c5,_@c4) ->
+ %% Line 6
+ case <_@c5,_@c4> of
+ <F,X> when 'true' ->
+ apply apply 'id'/1 (F) (X)
+ ( <_@c7,_@c6> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_@c7,_@c6})
+ -| [{'function_name',{'-non_variable_apply/0-fun-1-',2}}] )
+ -| ['compiler_generated'] )
+ end
+ in %% Line 9
+ apply F
+ (OkFun, 'ok')
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'non_variable_apply',0}}] )
+ -| ['compiler_generated'] )
+ end
+'id'/1 =
+ %% Line 11
+ fun (_@c0) ->
+ case _@c0 of
+ <I> when 'true' ->
+ I
+ ( <_@c1> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_@c1})
+ -| [{'function_name',{'id',1}}] )
+ -| ['compiler_generated'] )
+ end
+'module_info'/0 =
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ call 'erlang':'get_module_info'
+ ('non_variable_apply')
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'module_info',0}}] )
+ -| ['compiler_generated'] )
+ end
+'module_info'/1 =
+ fun (_@c0) ->
+ case _@c0 of
+ <X> when 'true' ->
+ call 'erlang':'get_module_info'
+ ('non_variable_apply', X)
+ ( <_@c1> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_@c1})
+ -| [{'function_name',{'module_info',1}}] )
+ -| ['compiler_generated'] )
+ end
+end
diff --git a/lib/compiler/test/core_alias_SUITE.erl b/lib/compiler/test/core_alias_SUITE.erl
new file mode 100644
index 0000000000..737b1567d4
--- /dev/null
+++ b/lib/compiler/test/core_alias_SUITE.erl
@@ -0,0 +1,195 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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(core_alias_SUITE).
+
+-export([all/0, suite/0, groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2, end_per_group/2,
+ tuples/1, cons/1]).
+
+-include_lib("common_test/include/ct.hrl").
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [{group,p}].
+
+groups() ->
+ [{p,[parallel],
+ [tuples, cons]}].
+
+init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+id(X) -> X.
+
+tuples(Config) when is_list(Config) ->
+ Tuple = {ok,id(value)},
+
+ true = erts_debug:same(Tuple, simple_tuple(Tuple)),
+ true = erts_debug:same(Tuple, simple_tuple_in_map(#{hello => Tuple})),
+ true = erts_debug:same(Tuple, simple_tuple_case_repeated(Tuple, Tuple)),
+ true = erts_debug:same(Tuple, simple_tuple_fun_repeated(Tuple, Tuple)),
+ true = erts_debug:same(Tuple, simple_tuple_twice_head(Tuple, Tuple)),
+
+ {Tuple1, Tuple2} = simple_tuple_twice_body(Tuple),
+ true = erts_debug:same(Tuple, Tuple1),
+ true = erts_debug:same(Tuple, Tuple2),
+
+ Nested = {nested,Tuple},
+ true = erts_debug:same(Tuple, nested_tuple_part(Nested)),
+ true = erts_debug:same(Nested, nested_tuple_whole(Nested)),
+ true = erts_debug:same(Nested, nested_tuple_with_alias(Nested)),
+
+ true = erts_debug:same(Tuple, tuple_rebinding_after(Tuple)),
+
+ Tuple = unaliased_tuple_rebinding_before(Tuple),
+ false = erts_debug:same(Tuple, unaliased_tuple_rebinding_before(Tuple)),
+ Nested = unaliased_literal_tuple_head(Nested),
+ false = erts_debug:same(Nested, unaliased_literal_tuple_head(Nested)),
+ Nested = unaliased_literal_tuple_body(Nested),
+ false = erts_debug:same(Nested, unaliased_literal_tuple_body(Nested)),
+ Nested = unaliased_different_var_tuple(Nested, Tuple),
+ false = erts_debug:same(Nested, unaliased_different_var_tuple(Nested, Tuple)).
+
+simple_tuple({ok,X}) ->
+ {ok,X}.
+simple_tuple_twice_head({ok,X}, {ok,X}) ->
+ {ok,X}.
+simple_tuple_twice_body({ok,X}) ->
+ {{ok,X},{ok,X}}.
+simple_tuple_in_map(#{hello := {ok,X}}) ->
+ {ok,X}.
+simple_tuple_fun_repeated({ok,X}, Y) ->
+ io:format("~p~n", [X]),
+ (fun({ok,X}) -> {ok,X} end)(Y).
+simple_tuple_case_repeated({ok,X}, Y) ->
+ io:format("~p~n", [X]),
+ case Y of {ok,X} -> {ok,X} end.
+
+nested_tuple_part({nested,{ok,X}}) ->
+ {ok,X}.
+nested_tuple_whole({nested,{ok,X}}) ->
+ {nested,{ok,X}}.
+nested_tuple_with_alias({nested,{ok,_}=Y}) ->
+ {nested,Y}.
+
+tuple_rebinding_after(Y) ->
+ (fun(X) -> {ok,X} end)(Y),
+ case Y of {ok,X} -> {ok,X} end.
+unaliased_tuple_rebinding_before({ok,X}) ->
+ io:format("~p~n", [X]),
+ (fun(X) -> {ok,X} end)(value).
+unaliased_literal_tuple_head({nested,{ok,value}=X}) ->
+ io:format("~p~n", [X]),
+ {nested,{ok,value}}.
+unaliased_literal_tuple_body({nested,{ok,value}=X}) ->
+ Res = {nested,Y={ok,value}},
+ io:format("~p~n", [[X,Y]]),
+ Res.
+unaliased_different_var_tuple({nested,{ok,value}=X}, Y) ->
+ io:format("~p~n", [X]),
+ {nested,Y}.
+
+cons(Config) when is_list(Config) ->
+ Cons = [ok|id(value)],
+
+ true = erts_debug:same(Cons, simple_cons(Cons)),
+ true = erts_debug:same(Cons, simple_cons_in_map(#{hello => Cons})),
+ true = erts_debug:same(Cons, simple_cons_case_repeated(Cons, Cons)),
+ true = erts_debug:same(Cons, simple_cons_fun_repeated(Cons, Cons)),
+ true = erts_debug:same(Cons, simple_cons_twice_head(Cons, Cons)),
+
+ {Cons1,Cons2} = simple_cons_twice_body(Cons),
+ true = erts_debug:same(Cons, Cons1),
+ true = erts_debug:same(Cons, Cons2),
+
+ Nested = [nested,Cons],
+ true = erts_debug:same(Cons, nested_cons_part(Nested)),
+ true = erts_debug:same(Nested, nested_cons_whole(Nested)),
+ true = erts_debug:same(Nested, nested_cons_with_alias(Nested)),
+ true = erts_debug:same(Cons, cons_rebinding_after(Cons)),
+
+ Unstripped = id([a,b]),
+ Stripped = cons_with_binary([<<>>|Unstripped]),
+ true = erts_debug:same(Unstripped, Stripped),
+
+ Cons = unaliased_cons_rebinding_before(Cons),
+ false = erts_debug:same(Cons, unaliased_cons_rebinding_before(Cons)),
+ Nested = unaliased_literal_cons_head(Nested),
+ false = erts_debug:same(Nested, unaliased_literal_cons_head(Nested)),
+ Nested = unaliased_literal_cons_body(Nested),
+ false = erts_debug:same(Nested, unaliased_literal_cons_body(Nested)),
+ Nested = unaliased_different_var_cons(Nested, Cons),
+ false = erts_debug:same(Nested, unaliased_different_var_cons(Nested, Cons)).
+
+simple_cons([ok|X]) ->
+ [ok|X].
+simple_cons_twice_head([ok|X], [ok|X]) ->
+ [ok|X].
+simple_cons_twice_body([ok|X]) ->
+ {[ok|X],[ok|X]}.
+simple_cons_in_map(#{hello := [ok|X]}) ->
+ [ok|X].
+simple_cons_fun_repeated([ok|X], Y) ->
+ io:format("~p~n", [X]),
+ (fun([ok|X]) -> [ok|X] end)(Y).
+simple_cons_case_repeated([ok|X], Y) ->
+ io:format("~p~n", [X]),
+ case Y of [ok|X] -> [ok|X] end.
+
+nested_cons_part([nested,[ok|X]]) ->
+ [ok|X].
+nested_cons_whole([nested,[ok|X]]) ->
+ [nested,[ok|X]].
+nested_cons_with_alias([nested,[ok|_]=Y]) ->
+ [nested,Y].
+
+cons_with_binary([<<>>,X|Y]) ->
+ cons_with_binary([X|Y]);
+cons_with_binary(A) ->
+ A.
+
+cons_rebinding_after(Y) ->
+ (fun(X) -> [ok|X] end)(Y),
+ case Y of [ok|X] -> [ok|X] end.
+unaliased_cons_rebinding_before([ok|X]) ->
+ io:format("~p~n", [X]),
+ (fun(X) -> [ok|X] end)(value).
+unaliased_literal_cons_head([nested,[ok|value]=X]) ->
+ io:format("~p~n", [X]),
+ [nested,[ok|value]].
+unaliased_literal_cons_body([nested,[ok|value]=X]) ->
+ Res = [nested,Y=[ok|value]],
+ io:format("~p~n", [[X, Y]]),
+ Res.
+unaliased_different_var_cons([nested,[ok|value]=X], Y) ->
+ io:format("~p~n", [X]),
+ [nested,Y].
diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl
index 0097e28d4d..47606014c3 100644
--- a/lib/compiler/test/core_fold_SUITE.erl
+++ b/lib/compiler/test/core_fold_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,9 @@
unused_multiple_values_error/1,unused_multiple_values/1,
multiple_aliases/1,redundant_boolean_clauses/1,
mixed_matching_clauses/1,unnecessary_building/1,
- no_no_file/1,configuration/1,supplies/1]).
+ no_no_file/1,configuration/1,supplies/1,
+ redundant_stack_frame/1,export_from_case/1,
+ empty_values/1,cover_letrec_effect/1]).
-export([foo/0,foo/1,foo/2,foo/3]).
@@ -35,7 +37,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -45,10 +46,13 @@ groups() ->
unused_multiple_values_error,unused_multiple_values,
multiple_aliases,redundant_boolean_clauses,
mixed_matching_clauses,unnecessary_building,
- no_no_file,configuration,supplies]}].
+ no_no_file,configuration,supplies,
+ redundant_stack_frame,export_from_case,
+ empty_values,cover_letrec_effect]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -527,4 +531,92 @@ supplies(_Config) ->
do_supplies(#{1 := Value}) when byte_size(Value), byte_size(kg) -> working.
+redundant_stack_frame(_Config) ->
+ {1,2} = do_redundant_stack_frame(#{x=>1,y=>2}),
+ {'EXIT',{{badkey,_,x},_}} = (catch do_redundant_stack_frame(#{y=>2})),
+ {'EXIT',{{badkey,_,y},_}} = (catch do_redundant_stack_frame(#{x=>1})),
+ ok.
+
+do_redundant_stack_frame(Map) ->
+ %% There should not be a stack frame for this function.
+ X = case Map of
+ #{x := X0} ->
+ X0;
+ #{} ->
+ erlang:error({badkey, Map, x})
+ end,
+ Y = case Map of
+ #{y := Y0} ->
+ Y0;
+ #{} ->
+ erlang:error({badkey, Map, y})
+ end,
+ {X, Y}.
+
+%% Cover some clauses in sys_core_fold:remove_first_value/2.
+
+-record(export_from_case, {val}).
+
+export_from_case(_Config) ->
+ a = export_from_case_1(true),
+ b = export_from_case_1(false),
+
+ R = #export_from_case{val=0},
+ {ok,R} = export_from_case_2(false, R),
+ {ok,#export_from_case{val=42}} = export_from_case_2(true, R),
+
+ ok.
+
+export_from_case_1(Bool) ->
+ case Bool of
+ true ->
+ id(42),
+ Result = a;
+ false ->
+ Result = b
+ end,
+ id(Result).
+
+export_from_case_2(Bool, Rec) ->
+ case Bool of
+ false ->
+ Result = Rec;
+ true ->
+ Result = Rec#export_from_case{val=42}
+ end,
+ {ok,Result}.
+
+empty_values(_Config) ->
+ case ?MODULE of
+ core_fold_inline_SUITE ->
+ {'EXIT',_} = (catch do_empty_values());
+ _ ->
+ {'EXIT',{function_clause,_}} = (catch do_empty_values())
+ end,
+ ok.
+
+do_empty_values() when (#{})#{} ->
+ c.
+
+cover_letrec_effect(_Config) ->
+ self() ! {tag,42},
+ _ = try
+ try
+ ignore
+ after
+ receive
+ {tag,Int}=Term ->
+ Res = #{k => {Term,<<Int:16>>}},
+ self() ! Res
+ end
+ end
+ after
+ ok
+ end,
+ receive
+ Any ->
+ #{k := {{tag,42},<<42:16>>}} = Any
+ end,
+ ok.
+
id(I) -> I.
diff --git a/lib/compiler/test/error_SUITE.erl b/lib/compiler/test/error_SUITE.erl
index 01c779b181..8b9dbe4aa0 100644
--- a/lib/compiler/test/error_SUITE.erl
+++ b/lib/compiler/test/error_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,7 +31,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -40,6 +39,7 @@ groups() ->
transforms,maps_warnings,bad_utf8]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/float_SUITE.erl b/lib/compiler/test/float_SUITE.erl
index 08c3dd8593..012810aba2 100644
--- a/lib/compiler/test/float_SUITE.erl
+++ b/lib/compiler/test/float_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,7 +27,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[pending, bif_calls, math_functions,
mixed_float_and_int].
@@ -35,6 +34,7 @@ groups() ->
[].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/fun_SUITE.erl b/lib/compiler/test/fun_SUITE.erl
index 16474adf5b..e00885fcd6 100644
--- a/lib/compiler/test/fun_SUITE.erl
+++ b/lib/compiler/test/fun_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -41,6 +40,7 @@ groups() ->
eep37_dup,badarity,badfun]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -194,6 +194,17 @@ external(Config) when is_list(Config) ->
?APPLY2(ListsMod, ListsMap, 2),
?APPLY2(ListsMod, ListsMap, ListsArity),
+ 42 = (fun erlang:abs/1)(-42),
+ 42 = (id(fun erlang:abs/1))(-42),
+ 42 = apply(fun erlang:abs/1, [-42]),
+ 42 = apply(id(fun erlang:abs/1), [-42]),
+ 6 = (fun lists:sum/1)([1,2,3]),
+ 6 = (id(fun lists:sum/1))([1,2,3]),
+
+ {'EXIT',{{badarity,_},_}} = (catch (fun lists:sum/1)(1, 2, 3)),
+ {'EXIT',{{badarity,_},_}} = (catch (id(fun lists:sum/1))(1, 2, 3)),
+ {'EXIT',{{badarity,_},_}} = (catch apply(fun lists:sum/1, [1,2,3])),
+
ok.
call_me(I) ->
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
index ccb9b58225..6ad73b46f7 100644
--- a/lib/compiler/test/guard_SUITE.erl
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,12 +35,12 @@
basic_andalso_orelse/1,traverse_dcd/1,
check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1,
bad_constants/1,bad_guards/1,
- guard_in_catch/1,beam_bool_SUITE/1]).
+ guard_in_catch/1,beam_bool_SUITE/1,
+ cover_beam_dead/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -54,9 +54,11 @@ groups() ->
rel_ops,rel_op_combinations,
literal_type_tests,basic_andalso_orelse,traverse_dcd,
check_qlc_hrl,andalso_semi,t_tuple_size,binary_part,
- bad_constants,bad_guards,guard_in_catch,beam_bool_SUITE]}].
+ bad_constants,bad_guards,guard_in_catch,beam_bool_SUITE,
+ cover_beam_dead]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -1291,6 +1293,10 @@ rel_ops(Config) when is_list(Config) ->
true = any_atom /= id(42),
true = [] /= id(42),
+ %% Coverage of beam_utils:bif_to_test/3
+ Empty = id([]),
+ ?T(==, [], Empty),
+
ok.
-undef(TestOp).
@@ -1615,7 +1621,9 @@ type_tests() ->
is_reference,
is_port,
is_binary,
- is_function].
+ is_bitstring,
+ is_function,
+ is_map].
basic_andalso_orelse(Config) when is_list(Config) ->
T = id({type,integers,23,42}),
@@ -2198,7 +2206,31 @@ maps() ->
evidence(#{0 := Charge}) when 0; #{[] => Charge} == #{[] => 42} ->
ok.
+cover_beam_dead(_Config) ->
+ Mod = ?FUNCTION_NAME,
+ Attr = [],
+ Fs = [{function,test,1,2,
+ [{label,1},
+ {line,[]},
+ {func_info,{atom,Mod},{atom,test},1},
+ {label,2},
+ %% Cover beam_dead:turn_op/1 using swapped operand order.
+ {test,is_ne_exact,{f,3},[{integer,1},{x,0}]},
+ {test,is_eq_exact,{f,1},[{atom,a},{x,0}]},
+ {label,3},
+ {move,{atom,ok},{x,0}},
+ return]}],
+ Exp = [{test,1}],
+ Asm = {Mod,Exp,Attr,Fs,3},
+ {ok,Mod,Beam} = compile:forms(Asm, [from_asm,binary,report]),
+ {module,Mod} = code:load_binary(Mod, Mod, Beam),
+ ok = Mod:test(1),
+ ok = Mod:test(a),
+ {'EXIT',_} = (catch Mod:test(other)),
+ true = code:delete(Mod),
+ _ = code:purge(Mod),
+ ok.
%% Call this function to turn off constant propagation.
id(I) -> I.
diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl
index ae59cc8026..dcc703c3e1 100644
--- a/lib/compiler/test/inline_SUITE.erl
+++ b/lib/compiler/test/inline_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,6 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -42,6 +41,7 @@ groups() ->
coverage]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Pa = "-pa " ++ filename:dirname(code:which(?MODULE)),
{ok,Node} = start_node(compiler, Pa),
[{testing_node,Node}|Config].
diff --git a/lib/compiler/test/lc_SUITE.erl b/lib/compiler/test/lc_SUITE.erl
index 9ad417b09b..c80b7cc59e 100644
--- a/lib/compiler/test/lc_SUITE.erl
+++ b/lib/compiler/test/lc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,7 +33,6 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -48,6 +47,7 @@ groups() ->
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -107,6 +107,31 @@ basic(Config) when is_list(Config) ->
[] = [X || X <- L1, X+1 < 2],
{'EXIT',_} = (catch [X || X <- L1, odd(X)]),
fc([x], catch [E || E <- id(x)]),
+
+ %% Make sure that line numbers point out the generator.
+ case ?MODULE of
+ lc_inline_SUITE ->
+ ok;
+ _ ->
+ {'EXIT',{function_clause,
+ [{?MODULE,_,_,
+ [{file,"bad_lc.erl"},{line,4}]}|_]}} =
+ (catch bad_generator(a)),
+ {'EXIT',{function_clause,
+ [{?MODULE,_,_,
+ [{file,"bad_lc.erl"},{line,4}]}|_]}} =
+ (catch bad_generator([a|b])),
+ {'EXIT',{badarg,
+ [{erlang,length,_,_},
+ {?MODULE,bad_generator_bc,1,
+ [{file,"bad_lc.erl"},{line,7}]}|_]}} =
+ (catch bad_generator_bc(a)),
+ {'EXIT',{badarg,
+ [{erlang,length,_,_},
+ {?MODULE,bad_generator_bc,1,
+ [{file,"bad_lc.erl"},{line,7}]}|_]}} =
+ (catch bad_generator_bc([a|b]))
+ end,
ok.
tuple_list() ->
@@ -249,3 +274,11 @@ fc(Args, {'EXIT',{function_clause,[{?MODULE,_,Arity,_}|_]}})
fc(Args, {'EXIT',{{case_clause,ActualArgs},_}})
when ?MODULE =:= lc_inline_SUITE ->
Args = tuple_to_list(ActualArgs).
+
+-file("bad_lc.erl", 1).
+bad_generator(List) -> %Line 2
+ [I || %Line 3
+ I <- List]. %Line 4
+bad_generator_bc(List) -> %Line 5
+ << <<I:4>> || %Line 6
+ I <- List>>. %Line 7
diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl
index 5e90b79aa2..3e0ab78390 100644
--- a/lib/compiler/test/map_SUITE.erl
+++ b/lib/compiler/test/map_SUITE.erl
@@ -36,7 +36,7 @@
t_guard_fun/1,
t_list_comprehension/1,
t_map_sort_literals/1,
- t_map_size/1,
+ t_map_size/1, t_map_get/1,
t_build_and_match_aliasing/1,
t_is_map/1,
@@ -67,14 +67,15 @@
%% errors in 18
t_register_corruption/1,
- t_bad_update/1
+ t_bad_update/1,
+ %% new in OTP 21
+ t_reused_key_variable/1
]).
suite() -> [].
all() ->
- test_lib:recompile(?MODULE),
[
%% literals
t_build_and_match_literals, t_build_and_match_literals_large,
@@ -89,7 +90,7 @@ all() ->
t_guard_receive, t_guard_receive_large,
t_guard_fun, t_list_comprehension,
t_map_sort_literals,
- t_map_size,
+ t_map_size, t_map_get,
t_build_and_match_aliasing,
t_is_map,
@@ -120,13 +121,20 @@ all() ->
%% errors in 18
t_register_corruption,
- t_bad_update
+ t_bad_update,
+
+ %% new in OTP 21
+ t_reused_key_variable
].
groups() -> [].
-init_per_suite(Config) -> Config.
-end_per_suite(_Config) -> ok.
+init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
init_per_group(_GroupName, Config) -> Config.
end_per_group(_GroupName, Config) -> Config.
@@ -686,6 +694,32 @@ t_map_size(Config) when is_list(Config) ->
map_is_size(M,N) when map_size(M) =:= N -> true;
map_is_size(_,_) -> false.
+t_map_get(Config) when is_list(Config) ->
+ 1 = map_get(a, id(#{a=>1})),
+
+ {'EXIT',{{badkey,a},_}} = (catch map_get(a, #{})),
+ {'EXIT',{{badkey,a},_}} = (catch map_get(a, #{b=>1})),
+
+ M = #{"a"=>1, "b" => 2},
+ true = check_map_value(M, "a", 1),
+ false = check_map_value(M, "b", 1),
+ true = check_map_value(M#{"c"=>2}, "c", 2),
+ false = check_map_value(M#{"a"=>5}, "a", 1),
+
+ {'EXIT',{{badmap,[]},_}} = (catch map_get(a, [])),
+ {'EXIT',{{badmap,<<1,2,3>>},_}} = (catch map_get(a, <<1,2,3>>)),
+ {'EXIT',{{badmap,1},_}} = (catch map_get(a, 1)),
+
+ %% Test that beam_validator understands that NewMap is
+ %% a map after seeing map_get(a, NewMap).
+ NewMap = id(#{a=>b}),
+ b = map_get(a, NewMap),
+ #{a:=z} = NewMap#{a:=z},
+ ok.
+
+check_map_value(Map, Key, Value) when map_get(Key, Map) =:= Value -> true;
+check_map_value(_, _, _) -> false.
+
t_is_map(Config) when is_list(Config) ->
true = is_map(#{}),
true = is_map(#{a=>1}),
@@ -695,8 +729,28 @@ t_is_map(Config) when is_list(Config) ->
if is_map(#{b=>1}) -> ok end,
if not is_map([1,2,3]) -> ok end,
if not is_map(x) -> ok end,
+
+ ok = do_t_is_map(map, #{}),
+ error = do_t_is_map(map, {a,b,c}),
+ ok = do_t_is_map(number, 42),
+ ok = do_t_is_map(number, 42.0),
+ error = do_t_is_map(number, {a,b,c}),
ok.
+do_t_is_map(What, X) ->
+ B = case What of
+ map ->
+ %% Cover conversion of is_map/1 BIF to test instruction
+ %% in beam_utils:bif_to_test/3.
+ is_map(X);
+ number ->
+ is_number(X)
+ end,
+ case B of
+ true -> ok;
+ false -> error
+ end.
+
% test map updates without matching
t_update_literals(Config) when is_list(Config) ->
Map = #{x=>1,y=>2,z=>3,q=>4},
@@ -1158,12 +1212,84 @@ t_guard_bifs(Config) when is_list(Config) ->
true = map_guard_empty_2(),
true = map_guard_head(#{a=>1}),
false = map_guard_head([]),
+
+ true = map_get_head(#{a=>1}),
+ false = map_get_head(#{}),
+ false = map_get_head([]),
+
+ true = map_get_head_not(#{a=>false}),
+ false = map_get_head_not(#{a=>true}),
+ false = map_get_head(#{}),
+ false = map_get_head([]),
+
+ true = map_is_key_head(#{a=>1}),
+ false = map_is_key_head(#{}),
+ false = map_is_key_head(not_a_map),
+
+ false = map_is_key_head_not(#{a=>1}),
+ true = map_is_key_head_not(#{b=>1}),
+ true = map_is_key_head_not(#{}),
+ false = map_is_key_head_not(not_a_map),
+
true = map_guard_body(#{a=>1}),
false = map_guard_body({}),
true = map_guard_pattern(#{a=>1, <<"hi">> => "hi" }),
false = map_guard_pattern("list"),
true = map_guard_tautology(),
true = map_guard_ill_map_size(),
+ true = map_field_check_sequence(#{a=>1}),
+ false = map_field_check_sequence(#{}),
+
+ %% The guard BIFs used in a body.
+
+ v = map_get(a, id(#{a=>v})),
+ {'EXIT',{{badkey,a},_}} =
+ (catch map_get(a, id(#{}))),
+ {'EXIT',{{badmap,not_a_map},_}} =
+ (catch map_get(a, id(not_a_map))),
+
+ true = is_map_key(a, id(#{a=>1})),
+ false = is_map_key(b, id(#{a=>1})),
+ false = is_map_key(b, id(#{})),
+ {'EXIT',{{badmap,not_a_map},_}} =
+ (catch is_map_key(b, id(not_a_map))),
+
+ {true,v} = erl_699(#{k=>v}),
+ {'EXIT',{{badkey,k},_}} = (catch erl_699(#{})),
+ {'EXIT',{{badmap,not_a_map},_}} = (catch erl_699(not_a_map)),
+
+ %% Cover optimizations in beam_dead.
+
+ ok = beam_dead_1(#{a=>any,k=>true}),
+ error = beam_dead_1(#{a=>any,k=>false}),
+ error = beam_dead_1(#{a=>any}),
+ error = beam_dead_1(#{}),
+
+ ok = beam_dead_2(#{a=>any,k=>true}),
+ error = beam_dead_2(#{a=>any,k=>false}),
+ error = beam_dead_2(#{a=>any}),
+ error = beam_dead_2(#{}),
+
+ ok = beam_dead_3(#{k=>true}),
+ error = beam_dead_3(#{k=>false}),
+ error = beam_dead_3(#{}),
+
+ ok = beam_dead_4(#{k=>true}),
+ error = beam_dead_4(#{k=>false}),
+ error = beam_dead_4(#{}),
+ error = beam_dead_4(not_a_map),
+
+ ok = beam_dead_5(#{k=>true}),
+ error = beam_dead_5(#{k=>false}),
+ error = beam_dead_3(#{}),
+
+ %% Test is_map_key/2 followed by map update.
+
+ Used0 = map_usage(var, #{other=>value}),
+ Used0 = #{other=>value,var=>dead},
+ Used1 = map_usage(var, #{var=>live}),
+ Used1 = #{var=>live},
+
ok.
map_guard_empty() when is_map(#{}); false -> true.
@@ -1173,6 +1299,18 @@ map_guard_empty_2() when true; #{} andalso false -> true.
map_guard_head(M) when is_map(M) -> true;
map_guard_head(_) -> false.
+map_get_head(M) when map_get(a, M) =:= 1 -> true;
+map_get_head(_) -> false.
+
+map_get_head_not(M) when not map_get(a, M) -> true;
+map_get_head_not(_) -> false.
+
+map_is_key_head(M) when is_map_key(a, M) -> true;
+map_is_key_head(_) -> false.
+
+map_is_key_head_not(M) when not is_map_key(a, M) -> true;
+map_is_key_head_not(_) -> false.
+
map_guard_body(M) -> is_map(M).
map_guard_pattern(#{}) -> true;
@@ -1182,6 +1320,58 @@ map_guard_tautology() when #{} =:= #{}; true -> true.
map_guard_ill_map_size() when true; map_size(0) -> true.
+map_field_check_sequence(M)
+ when is_map(M) andalso is_map_key(a, M) andalso (map_get(a, M) == 1) ->
+ true;
+map_field_check_sequence(_) ->
+ false.
+
+erl_699(M) ->
+ %% Used to cause an internal consistency failure.
+ {is_map_key(k, M),maps:get(k, M)}.
+
+beam_dead_1(#{a:=_,k:=_}=M) when map_get(k, M) ->
+ ok;
+beam_dead_1(#{}) ->
+ error.
+
+beam_dead_2(M) ->
+ case M of
+ #{a:=_,k:=_} when map_get(k, M) ->
+ ok;
+ #{} ->
+ error
+ end.
+
+beam_dead_3(M) ->
+ case M of
+ #{k:=_} when map_get(k, M) ->
+ ok;
+ #{} ->
+ error
+ end.
+
+beam_dead_4(M) ->
+ case M of
+ #{} when map_get(k, M) ->
+ ok;
+ _ ->
+ error
+ end.
+
+beam_dead_5(#{}=M) when map_get(k, M) ->
+ ok;
+beam_dead_5(#{}) ->
+ error.
+
+%% Test is_map_key/2, followed by an update of the map.
+map_usage(Def, Used) ->
+ case is_map_key(Def, Used) of
+ true -> Used;
+ false -> Used#{Def=>dead}
+ end.
+
+
t_guard_sequence(Config) when is_list(Config) ->
{1, "a"} = map_guard_sequence_1(#{seq=>1,val=>id("a")}),
{2, "b"} = map_guard_sequence_1(#{seq=>2,val=>id("b")}),
@@ -1960,6 +2150,16 @@ properly(Item) ->
increase(Allows) ->
catch fun() -> Allows end#{[] => +Allows, "warranty" => fun id/1}.
+t_reused_key_variable(Config) when is_list(Config) ->
+ Key = id(key),
+ Map1 = id(#{Key=>Config}),
+ Map2 = id(#{Key=>Config}),
+ case {Map1,Map2} of
+ %% core_lint treated Key as pattern variables, not input variables,
+ %% and complained about the variable being duplicated.
+ {#{Key:=Same},#{Key:=Same}} ->
+ ok
+ end.
%% aux
diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl
index 52b2da05f7..e3f842b668 100644
--- a/lib/compiler/test/match_SUITE.erl
+++ b/lib/compiler/test/match_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,27 +23,28 @@
init_per_group/2,end_per_group/2,
pmatch/1,mixed/1,aliases/1,non_matching_aliases/1,
match_in_call/1,untuplify/1,shortcut_boolean/1,letify_guard/1,
- selectify/1,underscore/1,match_map/1,map_vars_used/1,
- coverage/1,grab_bag/1,literal_binary/1]).
+ selectify/1,deselectify/1,underscore/1,match_map/1,map_vars_used/1,
+ coverage/1,grab_bag/1,literal_binary/1,
+ unary_op/1]).
-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
[{p,[parallel],
[pmatch,mixed,aliases,non_matching_aliases,
match_in_call,untuplify,
- shortcut_boolean,letify_guard,selectify,
+ shortcut_boolean,letify_guard,selectify,deselectify,
underscore,match_map,map_vars_used,coverage,
- grab_bag,literal_binary]}].
+ grab_bag,literal_binary,unary_op]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -466,6 +467,66 @@ sel_same_value2(V) when V =:= 42; V =:= 43 ->
sel_same_value2(_) ->
error.
+%% Test deconstruction of select_val instructions in beam_peep into
+%% regular tests with just one possible value left. Hitting proper cases
+%% in beam_peep relies on unification of labels by beam_jump.
+
+deselectify(Config) when is_list(Config) ->
+ one_or_other = desel_tuple_arity({1}),
+ two = desel_tuple_arity({1,1}),
+ one_or_other = desel_tuple_arity({1,1,1}),
+
+ one_or_other = dsel_integer(1),
+ two = dsel_integer(2),
+ one_or_other = dsel_integer(3),
+
+ one_or_other = dsel_integer_typecheck(1),
+ two = dsel_integer_typecheck(2),
+ one_or_other = dsel_integer_typecheck(3),
+
+ one_or_other = dsel_atom(one),
+ two = dsel_atom(two),
+ one_or_other = dsel_atom(three),
+
+ one_or_other = dsel_atom_typecheck(one),
+ two = dsel_atom_typecheck(two),
+ one_or_other = dsel_atom_typecheck(three).
+
+desel_tuple_arity(Tuple) when is_tuple(Tuple) ->
+ case Tuple of
+ {_} -> one_or_other;
+ {_,_} -> two;
+ _ -> one_or_other
+ end.
+
+dsel_integer(Val) ->
+ case Val of
+ 1 -> one_or_other;
+ 2 -> two;
+ _ -> one_or_other
+ end.
+
+dsel_integer_typecheck(Val) when is_integer(Val) ->
+ case Val of
+ 1 -> one_or_other;
+ 2 -> two;
+ _ -> one_or_other
+ end.
+
+dsel_atom(Val) ->
+ case Val of
+ one -> one_or_other;
+ two -> two;
+ _ -> one_or_other
+ end.
+
+dsel_atom_typecheck(Val) when is_atom(Val) ->
+ case Val of
+ one -> one_or_other;
+ two -> two;
+ _ -> one_or_other
+ end.
+
underscore(Config) when is_list(Config) ->
case Config of
[] ->
@@ -557,6 +618,10 @@ grab_bag(_Config) ->
{bad,16#555555555555555555555555555555555555555555555555555}],
ok = grab_bag_remove_failure(L, unit, 0),
+ {42,<<43,44>>} = grab_bag_single_valued(<<42,43,44>>),
+ empty_list = grab_bag_single_valued([]),
+ empty_tuple = grab_bag_single_valued({}),
+
ok.
grab_bag_remove_failure([], _Unit, _MaxFailure) ->
@@ -574,6 +639,12 @@ grab_bag_remove_failure([{stretch,_,Mi}=Stretch | Specs], Unit, _MaxFailure) ->
ok
end.
+%% Cover a line v3_kernel that places binary matching first.
+grab_bag_single_valued(<<H,T/bytes>>) -> {H,T};
+grab_bag_single_valued([]) -> empty_list;
+grab_bag_single_valued({}) -> empty_tuple.
+
+
%% Regression in 19.0, reported by Alexei Sholik
literal_binary(_Config) ->
3 = literal_binary_match(bar, <<"y">>),
@@ -592,5 +663,74 @@ literal_binary_match(_, <<"x">>) -> 2;
literal_binary_match(_, <<"y">>) -> 3;
literal_binary_match(_, _) -> fail.
+unary_op(Config) ->
+ %% ERL-514. This test case only verifies that the code
+ %% calculates the correct result, not that the generated
+ %% code is optimial.
+
+ {non_associative,30} = unary_op_1('&'),
+ {non_associative,300} = unary_op_1('^'),
+ {non_associative,300} = unary_op_1('not'),
+ {non_associative,300} = unary_op_1('+'),
+ {non_associative,300} = unary_op_1('-'),
+ {non_associative,300} = unary_op_1('~~~'),
+ {non_associative,300} = unary_op_1('!'),
+ {non_associative,320} = unary_op_1('@'),
+
+ error = unary_op_1(Config),
+ error = unary_op_1(abc),
+ error = unary_op_1(42),
+
+ ok.
+
+unary_op_1(Vop@1) ->
+ %% If all optimizations are working as they should, there should
+ %% be no stack frame and all '=:=' tests should be coalesced into
+ %% a single select_val instruction.
+
+ case Vop@1 =:= '&' of
+ true ->
+ {non_associative,30};
+ false ->
+ case
+ case Vop@1 =:= '^' of
+ true ->
+ true;
+ false ->
+ case Vop@1 =:= 'not' of
+ true ->
+ true;
+ false ->
+ case Vop@1 =:= '+' of
+ true ->
+ true;
+ false ->
+ case Vop@1 =:= '-' of
+ true ->
+ true;
+ false ->
+ case Vop@1 =:= '~~~' of
+ true ->
+ true;
+ false ->
+ Vop@1 =:= '!'
+ end
+ end
+ end
+ end
+ end
+ of
+ true ->
+ {non_associative,300};
+ false ->
+ case Vop@1 =:= '@' of
+ true ->
+ {non_associative,320};
+ false ->
+ error
+ end
+ end
+ end.
+
id(I) -> I.
diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl
index 4bd884d86b..a1d931b994 100644
--- a/lib/compiler/test/misc_SUITE.erl
+++ b/lib/compiler/test/misc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -61,7 +61,6 @@ suite() ->
-spec all() -> misc_SUITE_test_cases().
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -70,6 +69,7 @@ groups() ->
confused_literals,integer_encoding,override_bif]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -161,16 +161,17 @@ md5_1(Beam) ->
%% Cover some code that handles internal errors.
silly_coverage(Config) when is_list(Config) ->
- %% sys_core_fold, sys_core_bsm, sys_core_setel, v3_kernel
+ %% sys_core_fold, sys_core_alias, sys_core_bsm, sys_core_setel, v3_kernel
BadCoreErlang = {c_module,[],
name,[],[],
[{{c_var,[],{foo,2}},seriously_bad_body}]},
expect_error(fun() -> sys_core_fold:module(BadCoreErlang, []) end),
+ expect_error(fun() -> sys_core_alias:module(BadCoreErlang, []) end),
expect_error(fun() -> sys_core_bsm:module(BadCoreErlang, []) end),
expect_error(fun() -> sys_core_dsetel:module(BadCoreErlang, []) end),
expect_error(fun() -> v3_kernel:module(BadCoreErlang, []) end),
- %% v3_life
+ %% v3_codegen
BadKernel = {k_mdef,[],?MODULE,
[{foo,0}],
[],
@@ -178,11 +179,7 @@ silly_coverage(Config) when is_list(Config) ->
{k,[],[],[]},
f,0,[],
seriously_bad_body}]},
- expect_error(fun() -> v3_life:module(BadKernel, []) end),
-
- %% v3_codegen
- CodegenInput = {?MODULE,[{foo,0}],[],[{function,foo,0,[a|b],a,b,[]}]},
- expect_error(fun() -> v3_codegen:module(CodegenInput, []) end),
+ expect_error(fun() -> v3_codegen:module(BadKernel, []) end),
%% beam_a
BeamAInput = {?MODULE,[{foo,0}],[],
@@ -321,8 +318,7 @@ expect_error(Fun) ->
io:format("~p", [Any]),
ct:fail(call_was_supposed_to_fail)
catch
- Class:Reason ->
- Stk = erlang:get_stacktrace(),
+ Class:Reason:Stk ->
io:format("~p:~p\n~p\n", [Class,Reason,Stk]),
case {Class,Reason} of
{error,undef} ->
@@ -363,9 +359,7 @@ integer_encoding_1(Config) ->
io:put_chars(Src, "t(Last) ->[\n"),
io:put_chars(Data, "[\n"),
- do_integer_encoding(-(id(1) bsl 10000), Src, Data),
- do_integer_encoding(id(1) bsl 10000, Src, Data),
- do_integer_encoding(1024, 0, Src, Data),
+ do_integer_encoding(137, 0, Src, Data),
_ = [begin
B = 1 bsl I,
do_integer_encoding(-B-1, Src, Data),
@@ -374,7 +368,7 @@ integer_encoding_1(Config) ->
do_integer_encoding(B-1, Src, Data),
do_integer_encoding(B, Src, Data),
do_integer_encoding(B+1, Src, Data)
- end || I <- lists:seq(1, 128)],
+ end || I <- lists:seq(1, 130)],
io:put_chars(Src, "Last].\n\n"),
ok = file:close(Src),
io:put_chars(Data, "0].\n\n"),
@@ -388,8 +382,6 @@ integer_encoding_1(Config) ->
%% Compare lists.
List = Mod:t(0),
{ok,[List]} = file:consult(DataFile),
- OneBsl10000 = id(1) bsl 10000,
- [-(1 bsl 10000),OneBsl10000|_] = List,
%% Cleanup.
file:delete(SrcFile),
@@ -408,7 +400,3 @@ do_integer_encoding(I, Src, Data) ->
Str = integer_to_list(I),
io:put_chars(Src, [Str,",\n"]),
io:put_chars(Data, [Str,",\n"]).
-
-
-id(I) -> I.
-
diff --git a/lib/compiler/test/overridden_bif_SUITE.erl b/lib/compiler/test/overridden_bif_SUITE.erl
index ce18916515..6b8a9591c9 100644
--- a/lib/compiler/test/overridden_bif_SUITE.erl
+++ b/lib/compiler/test/overridden_bif_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,7 +36,6 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -45,6 +44,7 @@ groups() ->
]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl
index 8304672558..4219768d6f 100644
--- a/lib/compiler/test/receive_SUITE.erl
+++ b/lib/compiler/test/receive_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
export/1,recv/1,coverage/1,otp_7980/1,ref_opt/1,
- wait/1]).
+ wait/1,recv_in_try/1,double_recv/1]).
-include_lib("common_test/include/ct.hrl").
@@ -40,15 +40,16 @@ suite() ->
{timetrap,{minutes,2}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
[{p,test_lib:parallel(),
- [recv,coverage,otp_7980,ref_opt,export,wait]}].
+ [recv,coverage,otp_7980,ref_opt,export,wait,
+ recv_in_try,double_recv]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -222,9 +223,8 @@ do_ref_opt(Source, PrivDir) ->
collect_recv_opt_instrs(Code)
end,
ok
- catch Class:Error ->
- io:format("~s: ~p ~p\n~p\n",
- [Source,Class,Error,erlang:get_stacktrace()]),
+ catch Class:Error:Stk ->
+ io:format("~s: ~p ~p\n~p\n", [Source,Class,Error,Stk]),
error
end.
@@ -265,6 +265,10 @@ export(Config) when is_list(Config) ->
self() ! {result,Ref,42},
42 = export_1(Ref),
{error,timeout} = export_1(Ref),
+
+ self() ! {result,Ref},
+ {ok,Ref} = export_2(),
+
ok.
export_1(Reference) ->
@@ -281,6 +285,10 @@ export_1(Reference) ->
id({build,self()}),
Result.
+export_2() ->
+ receive {result,Result} -> ok end,
+ {ok,Result}.
+
wait(Config) when is_list(Config) ->
self() ! <<42>>,
<<42>> = wait_1(r, 1, 2),
@@ -298,4 +306,76 @@ wait_1(r, _, _) ->
wait_1(A, B, C) ->
{A,B,C}.
+recv_in_try(_Config) ->
+ self() ! {ok,fh}, {ok,fh} = recv_in_try(infinity, native),
+ self() ! {ok,ignored}, {ok,42} = recv_in_try(infinity, plain),
+ self() ! {error,ignored}, nok = recv_in_try(infinity, plain),
+ timeout = recv_in_try(1, plain),
+ ok.
+
+recv_in_try(Timeout, Format) ->
+ try
+ receive
+ {Status,History} ->
+ %% {test,is_tuple,{f,148},[{x,0}]}.
+ %% {test,test_arity,{f,148},[{x,0},2]}.
+ %% {get_tuple_element,{x,0},0,{y,1}}. %y1 is fragile.
+ %%
+ %% %% Here the fragility of y1 would be be progated to
+ %% %% the 'catch' below. Incorrect, since get_tuple_element
+ %% %% can't fail.
+ %% {get_tuple_element,{x,0},1,{x,2}}.
+ %%
+ %% remove_message. %y1 fragility cleared.
+ FH = case Format of
+ native ->
+ id(History);
+ plain ->
+ id(42)
+ end,
+ case Status of
+ ok ->
+ {ok,FH};
+ error ->
+ nok
+ end
+ after Timeout ->
+ timeout
+ end
+ catch
+ %% The fragility of y1 incorrectly propagated to here.
+ %% beam_validator would complain.
+ throw:{error,Reason} ->
+ {nok,Reason}
+ end.
+
+%% ERL-703. The compiler would crash because beam_utils:anno_defs/1
+%% failed to take into account that code after loop_rec_end is
+%% unreachable.
+
+double_recv(_Config) ->
+ self() ! {more,{a,term}},
+ ok = do_double_recv({more,{a,term}}, any),
+ self() ! message,
+ ok = do_double_recv(whatever, message),
+
+ error = do_double_recv({more,42}, whatever),
+ error = do_double_recv(whatever, whatever),
+ ok.
+
+do_double_recv({more, Rest}, _Msg) ->
+ receive
+ {more, Rest} ->
+ ok
+ after 0 ->
+ error
+ end;
+do_double_recv(_, Msg) ->
+ receive
+ Msg ->
+ ok
+ after 0 ->
+ error
+ end.
+
id(I) -> I.
diff --git a/lib/compiler/test/record_SUITE.erl b/lib/compiler/test/record_SUITE.erl
index 5546765f26..4ed7f39780 100644
--- a/lib/compiler/test/record_SUITE.erl
+++ b/lib/compiler/test/record_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -41,7 +41,6 @@ suite() ->
{timetrap,{minutes,2}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -52,6 +51,7 @@ groups() ->
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/regressions_SUITE.erl b/lib/compiler/test/regressions_SUITE.erl
index 7a6fe08c73..9b0b9b0c38 100644
--- a/lib/compiler/test/regressions_SUITE.erl
+++ b/lib/compiler/test/regressions_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,13 +21,29 @@
-module(regressions_SUITE).
-include_lib("common_test/include/ct.hrl").
--export([all/0,groups/0,init_per_testcase/2,end_per_testcase/2,suite/0]).
+-export([all/0,groups/0,init_per_testcase/2,end_per_testcase/2,
+ init_per_group/2,end_per_group/2,
+ init_per_testcase/2,end_per_testcase/2,
+ suite/0]).
-export([maps/1]).
groups() ->
[{p,test_lib:parallel(),
[maps]}].
+init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
init_per_testcase(_Case, Config) ->
Config.
@@ -39,7 +55,6 @@ suite() ->
{timetrap,{minutes,2}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
%%% test cases
diff --git a/lib/compiler/test/trycatch_SUITE.erl b/lib/compiler/test/trycatch_SUITE.erl
index a591d6cc93..1b7ef4ddb0 100644
--- a/lib/compiler/test/trycatch_SUITE.erl
+++ b/lib/compiler/test/trycatch_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,14 +26,14 @@
nested_of/1,nested_catch/1,nested_after/1,
nested_horrid/1,last_call_optimization/1,bool/1,
plain_catch_coverage/1,andalso_orelse/1,get_in_try/1,
- hockey/1,handle_info/1,catch_in_catch/1,grab_bag/1]).
+ hockey/1,handle_info/1,catch_in_catch/1,grab_bag/1,
+ stacktrace/1,nested_stacktrace/1,raise/1]).
-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -42,10 +42,12 @@ groups() ->
after_oops,eclectic,rethrow,nested_of,nested_catch,
nested_after,nested_horrid,last_call_optimization,
bool,plain_catch_coverage,andalso_orelse,get_in_try,
- hockey,handle_info,catch_in_catch,grab_bag]}].
+ hockey,handle_info,catch_in_catch,grab_bag,
+ stacktrace,nested_stacktrace,raise]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -115,6 +117,16 @@ basic(Conf) when is_list(Conf) ->
catch nisse -> erro
end,
+ %% Unmatchable clauses.
+ try
+ throw(thrown)
+ catch
+ {a,b}={a,b,c} -> %Intentionally no match.
+ ok;
+ thrown ->
+ ok
+ end,
+
ok.
after_call() ->
@@ -324,11 +336,11 @@ eclectic(Conf) when is_list(Conf) ->
{{error,{exit,V},{'EXIT',V}},V} =
eclectic_1({foo,{error,{exit,V}}}, error, {value,V}),
{{value,{value,V},V},
- {'EXIT',{badarith,[{?MODULE,my_add,2,_}|_]}}} =
+ {'EXIT',{badarith,[{erlang,'+',[0,a],_},{?MODULE,my_add,2,_}|_]}}} =
eclectic_1({foo,{value,{value,V}}}, undefined, {'add',{0,a}}),
{{'EXIT',V},V} =
eclectic_1({catch_foo,{exit,V}}, undefined, {throw,V}),
- {{error,{'div',{1,0}},{'EXIT',{badarith,[{?MODULE,my_div,2,_}|_]}}},
+ {{error,{'div',{1,0}},{'EXIT',{badarith,[{erlang,'div',[1,0],_},{?MODULE,my_div,2,_}|_]}}},
{'EXIT',V}} =
eclectic_1({foo,{error,{'div',{1,0}}}}, error, {exit,V}),
{{{error,V},{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},
@@ -345,7 +357,7 @@ eclectic(Conf) when is_list(Conf) ->
eclectic_2({error,{value,V}}, throw, {error,V}),
{{caught,{'EXIT',{badarg,[{erlang,abs,[V],_}|_]}}},V} =
eclectic_2({value,{'abs',V}}, undefined, {value,V}),
- {{caught,{'EXIT',{badarith,[{?MODULE,my_add,2,_}|_]}}},V} =
+ {{caught,{'EXIT',{badarith,[{erlang,'+',[0,a],_},{?MODULE,my_add,2,_}|_]}}},V} =
eclectic_2({exit,{'add',{0,a}}}, exit, {value,V}),
{{caught,{'EXIT',V}},undefined} =
eclectic_2({value,{error,V}}, undefined, {exit,V}),
@@ -1039,5 +1051,217 @@ grab_bag(_Config) ->
ok.
+stacktrace(_Config) ->
+ V = [make_ref()|self()],
+ case ?MODULE:module_info(native) of
+ false ->
+ {value2,{caught1,badarg,[{erlang,abs,[V],_}|_]}} =
+ stacktrace_1({'abs',V}, error, {value,V}),
+ {caught2,{error,badarith},[{erlang,'+',[0,a],_},
+ {?MODULE,my_add,2,_}|_]} =
+ stacktrace_1({'div',{1,0}}, error, {'add',{0,a}});
+ true ->
+ {value2,{caught1,badarg,[{?MODULE,my_abs,1,_}|_]}} =
+ stacktrace_1({'abs',V}, error, {value,V}),
+ {caught2,{error,badarith},[{?MODULE,my_add,2,_}|_]} =
+ stacktrace_1({'div',{1,0}}, error, {'add',{0,a}})
+ end,
+ {caught2,{error,{try_clause,V}},[{?MODULE,stacktrace_1,3,_}|_]} =
+ stacktrace_1({value,V}, error, {value,V}),
+ {caught2,{throw,V},[{?MODULE,foo,1,_}|_]} =
+ stacktrace_1({value,V}, error, {throw,V}),
+
+ try
+ stacktrace_2()
+ catch
+ error:{badmatch,_}:Stk2 ->
+ [{?MODULE,stacktrace_2,0,_},
+ {?MODULE,stacktrace,1,_}|_] = Stk2,
+ Stk2 = erlang:get_stacktrace(),
+ ok
+ end,
+
+ try
+ stacktrace_3(a, b)
+ catch
+ error:function_clause:Stk3 ->
+ Stk3 = erlang:get_stacktrace(),
+ case lists:module_info(native) of
+ false ->
+ [{lists,prefix,[a,b],_}|_] = Stk3;
+ true ->
+ [{lists,prefix,2,_}|_] = Stk3
+ end
+ end,
+
+ try
+ throw(x)
+ catch
+ throw:x:IntentionallyUnused ->
+ ok
+ end.
+
+stacktrace_1(X, C1, Y) ->
+ try try foo(X) of
+ C1 -> value1
+ catch
+ C1:D1:Stk1 ->
+ Stk1 = erlang:get_stacktrace(),
+ {caught1,D1,Stk1}
+ after
+ foo(Y)
+ end of
+ V2 -> {value2,V2}
+ catch
+ C2:D2:Stk2 -> {caught2,{C2,D2},Stk2=erlang:get_stacktrace()}
+ end.
+
+stacktrace_2() ->
+ ok = erlang:process_info(self(), current_function),
+ ok.
+
+stacktrace_3(A, B) ->
+ {ok,lists:prefix(A, B)}.
+
+nested_stacktrace(_Config) ->
+ V = [{make_ref()}|[self()]],
+ value1 = nested_stacktrace_1({{value,{V,x1}},void,{V,x1}},
+ {void,void,void}),
+ case ?MODULE:module_info(native) of
+ false ->
+ {caught1,
+ [{erlang,'+',[V,x1],_},{?MODULE,my_add,2,_}|_],
+ value2} =
+ nested_stacktrace_1({{'add',{V,x1}},error,badarith},
+ {{value,{V,x2}},void,{V,x2}}),
+ {caught1,
+ [{erlang,'+',[V,x1],_},{?MODULE,my_add,2,_}|_],
+ {caught2,[{erlang,abs,[V],_}|_]}} =
+ nested_stacktrace_1({{'add',{V,x1}},error,badarith},
+ {{'abs',V},error,badarg});
+ true ->
+ {caught1,
+ [{?MODULE,my_add,2,_}|_],
+ value2} =
+ nested_stacktrace_1({{'add',{V,x1}},error,badarith},
+ {{value,{V,x2}},void,{V,x2}}),
+ {caught1,
+ [{?MODULE,my_add,2,_}|_],
+ {caught2,[{?MODULE,my_abs,1,_}|_]}} =
+ nested_stacktrace_1({{'add',{V,x1}},error,badarith},
+ {{'abs',V},error,badarg})
+ end,
+ ok.
+
+nested_stacktrace_1({X1,C1,V1}, {X2,C2,V2}) ->
+ try foo(X1) of
+ V1 -> value1
+ catch
+ C1:V1:S1 ->
+ S1 = erlang:get_stacktrace(),
+ T2 = try foo(X2) of
+ V2 -> value2
+ catch
+ C2:V2:S2 ->
+ S2 = erlang:get_stacktrace(),
+ {caught2,S2}
+ end,
+ {caught1,S1,T2}
+ end.
+
+raise(_Config) ->
+ test_raise(fun() -> exit({exit,tuple}) end),
+ test_raise(fun() -> abs(id(x)) end),
+ test_raise(fun() -> throw({was,thrown}) end),
+
+ badarg = bad_raise(fun() -> abs(id(x)) end),
+
+ ok.
+
+bad_raise(Expr) ->
+ try
+ Expr()
+ catch
+ _:E:Stk ->
+ erlang:raise(bad_class, E, Stk)
+ end.
+
+test_raise(Expr) ->
+ test_raise_1(Expr),
+ test_raise_2(Expr),
+ test_raise_3(Expr).
+
+test_raise_1(Expr) ->
+ erase(exception),
+ try
+ do_test_raise_1(Expr)
+ catch
+ C:E:Stk ->
+ {C,E,Stk} = erase(exception)
+ end.
+
+do_test_raise_1(Expr) ->
+ try
+ Expr()
+ catch
+ C:E:Stk ->
+ %% Here the stacktrace must be built.
+ put(exception, {C,E,Stk}),
+ erlang:raise(C, E, Stk)
+ end.
+
+test_raise_2(Expr) ->
+ erase(exception),
+ try
+ do_test_raise_2(Expr)
+ catch
+ C:E:Stk ->
+ {C,E} = erase(exception),
+ try
+ Expr()
+ catch
+ _:_:S ->
+ [StkTop|_] = S,
+ [StkTop|_] = Stk
+ end
+ end.
+
+do_test_raise_2(Expr) ->
+ try
+ Expr()
+ catch
+ C:E:Stk ->
+ %% Here it is possible to replace erlang:raise/3 with
+ %% the raw_raise/3 instruction since the stacktrace is
+ %% not actually used.
+ put(exception, {C,E}),
+ erlang:raise(C, E, Stk)
+ end.
+
+test_raise_3(Expr) ->
+ try
+ do_test_raise_3(Expr)
+ catch
+ exit:{exception,C,E}:Stk ->
+ try
+ Expr()
+ catch
+ C:E:S ->
+ [StkTop|_] = S,
+ [StkTop|_] = Stk
+ end
+ end.
+
+do_test_raise_3(Expr) ->
+ try
+ Expr()
+ catch
+ C:E:Stk ->
+ %% Here it is possible to replace erlang:raise/3 with
+ %% the raw_raise/3 instruction since the stacktrace is
+ %% not actually used.
+ erlang:raise(exit, {exception,C,E}, Stk)
+ end.
+
id(I) -> I.
diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl
index 857995b6a6..33d55996ad 100644
--- a/lib/compiler/test/warnings_SUITE.erl
+++ b/lib/compiler/test/warnings_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -55,7 +55,6 @@ suite() ->
{timetrap,{minutes,2}}].
all() ->
- test_lib:recompile(?MODULE),
[{group,p}].
groups() ->
@@ -68,6 +67,7 @@ groups() ->
underscore,no_warnings,bit_syntax,inlining]}].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
diff --git a/lib/compiler/test/z_SUITE.erl b/lib/compiler/test/z_SUITE.erl
index d864184f4c..bfa8e279e8 100644
--- a/lib/compiler/test/z_SUITE.erl
+++ b/lib/compiler/test/z_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,13 +26,13 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- test_lib:recompile(?MODULE),
[loaded].
groups() ->
[].
init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
Config.
end_per_suite(_Config) ->
@@ -54,8 +54,7 @@ do_loaded([{M,_}|Ms], E0) ->
_ = M:module_info(functions),
E0
catch
- C:Error ->
- Stk = erlang:get_stacktrace(),
+ C:Error:Stk ->
io:format("~p:~p\n~p\n", [C,Error,Stk]),
E0 + 1
end,
diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk
index 463c264a5f..c7e7fb6754 100644
--- a/lib/compiler/vsn.mk
+++ b/lib/compiler/vsn.mk
@@ -1 +1 @@
-COMPILER_VSN = 7.1
+COMPILER_VSN = 7.2.5
diff --git a/lib/cosEvent/AUTHORS b/lib/cosEvent/AUTHORS
deleted file mode 100644
index 624d275f78..0000000000
--- a/lib/cosEvent/AUTHORS
+++ /dev/null
@@ -1,5 +0,0 @@
-Original Authors:
-Niclas Eklund
-
-Contributors:
-
diff --git a/lib/cosEvent/Makefile b/lib/cosEvent/Makefile
deleted file mode 100644
index 276b7bd865..0000000000
--- a/lib/cosEvent/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include vsn.mk
-VSN=$(COSEVENT_VSN)
-
-# ----------------------------------------------------
-# Common Macros
-# ----------------------------------------------------
-
-SUB_DIRECTORIES = src doc/src
-
-SPECIAL_TARGETS =
-
-# ----------------------------------------------------
-# Default Subdir Targets
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_subdir.mk
-
diff --git a/lib/cosEvent/doc/src/CosEventChannelAdmin.xml b/lib/cosEvent/doc/src/CosEventChannelAdmin.xml
deleted file mode 100644
index 29336c1878..0000000000
--- a/lib/cosEvent/doc/src/CosEventChannelAdmin.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosEventChannelAdmin</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>1997-11-13</date>
- <rev>PA1</rev>
- <file>CosEventChannelAdmin.xml</file>
- </header>
- <module>CosEventChannelAdmin</module>
- <modulesummary>The CosEventChannelAdmin defines a set if event service interfaces that enables decoupled asynchronous communication between objects and implements generic (untyped) version of the OMG COSS standard event service.</modulesummary>
- <description>
- <p>The event service defines two roles for objects: the supplier role and
- the consumer role. Suppliers supply event data to the event channel and
- consumers receive event data from the channel. Suppliers do not need to
- know the identity of the consumers, and vice versa. Consumers and
- suppliers are connected to the event channel via proxies, which are managed
- by ConsumerAdmin and SupplierAdmin objects.</p>
- <p>There are four general models of communication. These are: </p>
- <list type="bulleted">
- <item>The canonical push model. It allows the suppliers of events to initiate the
- transfer of event data to consumers. Event channels play the role of
- <c><![CDATA[Notifier]]></c>. Active suppliers use event channel to push data to
- passive consumers registered with the event channel.</item>
- <item>The canonical pull model. It allows consumers to request events from
- suppliers. Event channels play the role of <c><![CDATA[Procure]]></c> since they
- procure events on behalf of consumers. Active consumers can explicitly
- pull data from passive suppliers via the event channels.</item>
- <item>The hybrid push/pull model. It allows consumers request events queued at
- a channel by suppliers. Event channels play the role of <c><![CDATA[Queue]]></c>.
- Active consumers explicitly pull data deposited by active suppliers via
- the event channels.</item>
- <item>The hybrid pull/push model. It allows the channel to pull events from
- suppliers and push them to consumers. Event channels play the role of
- <c><![CDATA[Intelligent agent]]></c>. Active event channels can pull data from
- passive suppliers to push it to passive consumers.</item>
- </list>
- <p>To get access to all definitions, e.g., exceptions,
- include necessary <c><![CDATA[hrl]]></c> files by using:<br></br><c><![CDATA[-include_lib("cosEvent/include/*.hrl").]]></c></p>
- <p>There are seven different interfaces supported in the service:</p>
- <list type="bulleted">
- <item>ProxyPushConsumer</item>
- <item>ProxyPullSupplier</item>
- <item>ProxyPullConsumer</item>
- <item>ProxyPushSupplier</item>
- <item>ConsumerAdmin</item>
- <item>SupplierAdmin</item>
- <item>EventChannel</item>
- </list>
- </description>
-
-</erlref>
-
diff --git a/lib/cosEvent/doc/src/CosEventChannelAdmin_ConsumerAdmin.xml b/lib/cosEvent/doc/src/CosEventChannelAdmin_ConsumerAdmin.xml
deleted file mode 100644
index 80d36ba5c5..0000000000
--- a/lib/cosEvent/doc/src/CosEventChannelAdmin_ConsumerAdmin.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosEventChannelAdmin_ConsumerAdmin</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>1997-11-13</date>
- <rev>PA1</rev>
- <file>CosEventChannelAdmin_ConsumerAdmin.xml</file>
- </header>
- <module>CosEventChannelAdmin_ConsumerAdmin</module>
- <modulesummary>This module implements a ConsumerAdmin interface, which allows consumers to be connected to the event channel.</modulesummary>
- <description>
- <p>The ConsumerAdmin interface defines the first step for connecting consumers
- to the event channel. It acts as a factory for creating proxy suppliers.
- Both consumer administration and supplier administration are defined as separate
- objects so that the creator of the channel can control the addition of
- suppliers and consumers. </p>
- <p>To get access to all definitions include necessary <c><![CDATA[hrl]]></c> files by using:<br></br><c><![CDATA[-include_lib("cosEvent/include/*.hrl").]]></c></p>
- </description>
- <funcs>
- <func>
- <name>obtain_push_supplier(Object) -> Return</name>
- <fsummary>Create a ProxyPushSupplier object</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Return = #objref</v>
- </type>
- <desc>
- <p>This operation returns a ProxyPushSupplier object reference.</p>
- </desc>
- </func>
- <func>
- <name>obtain_pull_supplier(Object) -> Return</name>
- <fsummary>Create a ProxyPullSupplier object</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Return = #objref</v>
- </type>
- <desc>
- <p>This operation returns a ProxyPullSupplier object reference.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosEvent/doc/src/CosEventChannelAdmin_EventChannel.xml b/lib/cosEvent/doc/src/CosEventChannelAdmin_EventChannel.xml
deleted file mode 100644
index f32e742240..0000000000
--- a/lib/cosEvent/doc/src/CosEventChannelAdmin_EventChannel.xml
+++ /dev/null
@@ -1,95 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosEventChannelAdmin_EventChannel</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>1997-11-13</date>
- <rev>PA1</rev>
- <file>CosEventChannelAdmin_EventChannel.xml</file>
- </header>
- <module>CosEventChannelAdmin_EventChannel</module>
- <modulesummary>This module implements an Event Channel interface, which plays the role of a mediator between consumers and suppliers.</modulesummary>
- <description>
- <p>An event channel is an object that allows multiple suppliers to communicate
- with multiple consumers in a highly decoupled, asynchronous manner. The event
- channel is built up incrementally. When an event channel is
- created no suppliers or consumers are connected to it. Event Channel can
- implement group communication by serving as a replicator, broadcaster, or
- multicaster that forward events from one or more suppliers to multiple
- consumers.</p>
- <p>It is up to the user to decide when an event channel is created and how
- references to the event channel are obtained. By representing the event
- channel as an object, it has all of the properties that apply to objects.
- One way to manage an event channel is to register it in a naming context,
- or export it through an operation on an object.</p>
- <p>To get access to all definitions include necessary <c><![CDATA[hrl]]></c> files by using:<br></br><c><![CDATA[-include_lib("cosEvent/include/*.hrl").]]></c></p>
- <p>Any object that possesses an object reference that supports the ProxyPullConsumer
- interface can perform the following operations:</p>
- </description>
- <funcs>
- <func>
- <name>for_consumers(Object) -> Return</name>
- <fsummary>Return a ConsumerAdmin object</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Return = #objref</v>
- </type>
- <desc>
- <p>This operation returns a ConsumerAdmin object reference. If ConsumerAdmin
- object does not exist already it creates one.</p>
- </desc>
- </func>
- <func>
- <name>for_suppliers(Object) -> Return</name>
- <fsummary>Return a SupplierAdmin object</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Return = #objref</v>
- </type>
- <desc>
- <p>This operation returns a SupplierAdmin object reference. If SupplierAdmin
- object does not exist already it creates one.</p>
- </desc>
- </func>
- <func>
- <name>destroy(Object) -> Return</name>
- <fsummary>Destroy the event channel</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Return = #objref</v>
- </type>
- <desc>
- <p></p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPullConsumer.xml b/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPullConsumer.xml
deleted file mode 100644
index 83bf8acbf2..0000000000
--- a/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPullConsumer.xml
+++ /dev/null
@@ -1,85 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosEventChannelAdmin_ProxyPullConsumer</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>1997-11-13</date>
- <rev>PA1</rev>
- <file>CosEventChannelAdmin_ProxyPullConsumer.xml</file>
- </header>
- <module>CosEventChannelAdmin_ProxyPullConsumer</module>
- <modulesummary>This module implements a ProxyPullConsumer interface which acts as a middleman between pull supplier and the event channel.</modulesummary>
- <description>
- <p>The ProxyPullConsumer interface defines the second step for connecting pull
- suppliers to the event channel. A proxy consumer is similar to a normal consumer,
- but includes an additional method for connecting a supplier to the proxy
- consumer.</p>
- <p>To get access to all definitions, e.g., exceptions,
- include necessary <c><![CDATA[hrl]]></c> files by using:<br></br><c><![CDATA[-include_lib("cosEvent/include/*.hrl").]]></c></p>
- <p>Any object that possesses an object reference that supports the ProxyPullConsumer
- interface can perform the following operations:</p>
- </description>
- <funcs>
- <func>
- <name>connect_pull_supplier(Object, PullSupplier) -> Return</name>
- <fsummary>Connect the pull supplier to the proxy pull consumer</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>PullSupplier = #objref of PullSupplier type</v>
- <v>Return = ok | {'EXCEPTION', E}</v>
- <v>E = #'CosEventChannelAdmin_AlreadyConnected'{} | #'CosEventChannelAdmin_TypeError'{}</v>
- </type>
- <desc>
- <p>This operation connects PullSupplier object to the ProxyPullConsumer object.
- If a nil object reference is passed CORBA standard <c><![CDATA[BAD_PARAM]]></c> exception
- is raised. If the ProxyPullConsumer is already connected to a PullSupplier,
- then the <c><![CDATA[CosEventChannelAdmin_AlreadyConnected]]></c> exception is raised.
- Implementations of ProxyPullConsumers may require additional interface
- functionality; if these requirements are not met the
- <c><![CDATA[CosEventChannelAdmin_TypeError]]></c> exception will be raised.</p>
- </desc>
- </func>
- <func>
- <name>disconnect_pull_consumer(Object) -> Return</name>
- <fsummary>Disconnect the ProxyPullConsumer object from the event channel.</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>This operation disconnects proxy pull consumer from the event channel and
- sends a notification about the loss of the connection to the pull supplier
- attached to it.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPullSupplier.xml b/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPullSupplier.xml
deleted file mode 100644
index 0060e71e2b..0000000000
--- a/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPullSupplier.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosEventChannelAdmin_ProxyPullSupplier</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved>Lars Thors</approved>
- <checked></checked>
- <date>1997-11-13</date>
- <rev>PA1</rev>
- <file>CosEventChannelAdmin_ProxyPullSupplier.xml</file>
- </header>
- <module>CosEventChannelAdmin_ProxyPullSupplier</module>
- <modulesummary>This module implements a ProxyPullSupplier interface which acts as a middleman between pull consumer and the event channel.</modulesummary>
- <description>
- <p>The ProxyPullSupplier interface defines the second step for connecting pull consumers to the event channel. A proxy supplier is similar to a normal supplier,
- but includes an additional method for connecting a consumer to the proxy
- supplier.</p>
- <p>To get access to all definitions, e.g., exceptions,
- include necessary <c><![CDATA[hrl]]></c> files by using:<br></br><c><![CDATA[-include_lib("cosEvent/include/*.hrl").]]></c></p>
- <p>Any object that possesses an object reference that supports the ProxyPullSupplier
- interface can perform the following operations:</p>
- </description>
- <funcs>
- <func>
- <name>connect_pull_consumer(Object, PullConsumer) -> Return</name>
- <fsummary>Connect the pull consumer to the proxy pull supplier</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>PullConsumer = #objref of PullConsumer type</v>
- <v>Return = ok | {'EXCEPTION', #'CosEventChannelAdmin_AlreadyConnected'{}}</v>
- </type>
- <desc>
- <p>This operation connects PullConsumer object to the ProxyPullSupplier object.
- A nil object reference can be passed to this operation. If so a channel
- cannot invoke the disconnect_pull_consumer operation on the consumer;
- the consumer may be disconnected from the channel without being
- informed. If the ProxyPullSupplier is already connected to a
- PullConsumer, then the <c><![CDATA[CosEventChannelAdmin_AlreadyConnected]]></c>
- exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>disconnect_pull_supplier(Object) -> Return</name>
- <fsummary>Disconnect the ProxyPullSupplier object from the event channel.</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>This operation disconnects proxy pull supplier from the event channel.
- It sends a notification about the loss of the connection to the pull consumer
- attached to it, unless nil object reference was passed at the connection
- time.</p>
- </desc>
- </func>
- <func>
- <name>pull(Object) -> Return</name>
- <fsummary>Transmit data from suppliers to consumers.</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Return = any</v>
- </type>
- <desc>
- <p>This operation blocks until the event data is available or the
- <c><![CDATA[CosEventComm_Disconnected]]></c> exception is raised.
- It returns the event data to the consumer.</p>
- </desc>
- </func>
- <func>
- <name>try_pull(Object) -> Return</name>
- <fsummary>Transmit data from suppliers to consumers.</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Return = {any, bool()}</v>
- </type>
- <desc>
- <p>This operation does not block: if the event data is available, it returns
- the event data and sets the data availability flag to true; otherwise
- it returns a long with an undefined value and sets the data availability to
- false. If the event communication has already been disconnected, the
- <c><![CDATA[CosEventComm_Disconnected]]></c> exception is raised.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPushConsumer.xml b/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPushConsumer.xml
deleted file mode 100644
index 9f19d001f9..0000000000
--- a/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPushConsumer.xml
+++ /dev/null
@@ -1,99 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosEventChannelAdmin_ProxyPushConsumer</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>1997-11-13</date>
- <rev>PA1</rev>
- <file>CosEventChannelAdmin_ProxyPushConsumer.xml</file>
- </header>
- <module>CosEventChannelAdmin_ProxyPushConsumer</module>
- <modulesummary>This module implements a ProxyPushConsumer interface which acts as a middleman between push supplier and the event channel.</modulesummary>
- <description>
- <p>The ProxyPushConsumer interface defines the second step for connecting push
- suppliers to the event channel. A proxy consumer is similar to a normal consumer,
- but includes an additional method for connecting a supplier to the proxy
- consumer.</p>
- <p>To get access to all definitions, e.g., exceptions,
- include necessary <c><![CDATA[hrl]]></c> files by using:<br></br><c><![CDATA[-include_lib("cosEvent/include/*.hrl").]]></c></p>
- <p>Any object that possesses an object reference that supports the ProxyPushConsumer
- interface can perform the following operations:</p>
- </description>
- <funcs>
- <func>
- <name>connect_push_supplier(Object, PushSupplier) -> Return</name>
- <fsummary>Connect the push supplier to the proxy push consumer</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>PushSupplier = #objref of PushSupplier type</v>
- <v>Return = ok | {'EXCEPTION', #'CosEventChannelAdmin_AlreadyConnected'{}}</v>
- </type>
- <desc>
- <p>This operation connects PushSupplier object to the ProxyPushConsumer object.
- A nil object reference can be passed to this operation. If so a channel
- cannot invoke the disconnect_push_supplier operation on the supplier;
- the supplier may be disconnected from the channel without being
- informed. If the ProxyPushConsumer is already connected to a
- PushSupplier, then the <c><![CDATA[CosEventChannelAdmin_AlreadyConnected]]></c>
- exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>disconnect_push_consumer(Object) -> Return</name>
- <fsummary>Disconnect the ProxyPushConsumer object from the event channel.</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>This operation disconnects proxy push consumer from the event channel.
- Sends a notification about the loss of the connection to the push supplier
- attached to it, unless nil object reference was passed at the connection
- time.</p>
- </desc>
- </func>
- <func>
- <name>push(Object, Data) -> Return</name>
- <fsummary>Communicate event data to the consumers.</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Data = any</v>
- <v>Return = ok | {'EXCEPTION', #'CosEventComm_Disconnected'{}}</v>
- </type>
- <desc>
- <p>This operation sends event data to all connected consumers via the
- event channel. If the event communication has already been disconnected,
- the <c><![CDATA[CosEventComm_Disconnected]]></c> is raised.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPushSupplier.xml b/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPushSupplier.xml
deleted file mode 100644
index 2b1098b9a7..0000000000
--- a/lib/cosEvent/doc/src/CosEventChannelAdmin_ProxyPushSupplier.xml
+++ /dev/null
@@ -1,85 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosEventChannelAdmin_ProxyPushSupplier</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>1997-11-13</date>
- <rev>PA1</rev>
- <file>CosEventChannelAdmin_ProxyPushSupplier.xml</file>
- </header>
- <module>CosEventChannelAdmin_ProxyPushSupplier</module>
- <modulesummary>This module implements a ProxyPushSupplier interface which acts as a middleman between push consumer and the event channel.</modulesummary>
- <description>
- <p>The ProxyPushSupplier interface defines the second step for connecting push
- consumers to the event channel. A proxy supplier is similar to a normal supplier,
- but includes an additional method for connecting a consumer to the proxy
- supplier.</p>
- <p>To get access to all definitions, e.g., exceptions,
- include necessary <c><![CDATA[hrl]]></c> files by using:<br></br><c><![CDATA[-include_lib("cosEvent/include/*.hrl").]]></c></p>
- <p>Any object that possesses an object reference that supports the ProxyPushSupplier
- interface can perform the following operations:</p>
- </description>
- <funcs>
- <func>
- <name>connect_push_consumer(Object, PushConsumer) -> Return</name>
- <fsummary>Connect the push consumer to the proxy push supplier</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>PushConsumer = #objref of PushConsumer type</v>
- <v>Return = ok | {'EXCEPTION', E}</v>
- <v>E = #'CosEventChannelAdmin_AlreadyConnected'{} | #'CosEventChannelAdmin_TypeError'{}</v>
- </type>
- <desc>
- <p>This operation connects PushConsumer object to the ProxyPushSupplier object.
- If a nil object reference is passed CORBA standard <c><![CDATA[BAD_PARAM]]></c> exception
- is raised. If the ProxyPushSupplier is already connected to a PushConsumer,
- then the <c><![CDATA[CosEventChannelAdmin_AlreadyConnected]]></c> exception is raised.
- Implementations of ProxyPushSuppliers may require additional interface
- functionality; if these requirements are not met the
- <c><![CDATA[CosEventChannelAdmin_TypeError]]></c> exception will be raised.</p>
- </desc>
- </func>
- <func>
- <name>disconnect_push_supplier(Object) -> Return</name>
- <fsummary>Disconnect the ProxyPushSupplier object from the event channel.</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>This operation disconnects proxy push supplier from the event channel and
- sends a notification about the loss of the connection to the push consumer
- attached to it.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosEvent/doc/src/CosEventChannelAdmin_SupplierAdmin.xml b/lib/cosEvent/doc/src/CosEventChannelAdmin_SupplierAdmin.xml
deleted file mode 100644
index 2a58c0a873..0000000000
--- a/lib/cosEvent/doc/src/CosEventChannelAdmin_SupplierAdmin.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosEventChannelAdmin_SupplierAdmin</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>1997-11-13</date>
- <rev>PA1</rev>
- <file>CosEventChannelAdmin_SupplierAdmin.xml</file>
- </header>
- <module>CosEventChannelAdmin_SupplierAdmin</module>
- <modulesummary>This module implements a SupplierAdmin interface, which allows suppliers to be connected to the event channel.</modulesummary>
- <description>
- <p>The SupplierAdmin interface defines the first step for connecting suppliers
- to the event channel. It acts as a factory for creating proxy consumers.
- Both consumer administration and supplier administration are defined as separate
- objects so that the creator of the channel can control the addition of
- suppliers and consumers.</p>
- <p>To get access to all definitions include necessary <c><![CDATA[hrl]]></c> files by using:<br></br><c><![CDATA[-include_lib("cosEvent/include/*.hrl").]]></c></p>
- </description>
- <funcs>
- <func>
- <name>obtain_push_consumer(Object) -> Return</name>
- <fsummary>Create a ProxyPushConsumer object</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Return = #objref</v>
- </type>
- <desc>
- <p>This operation returns a ProxyPushConsumer object reference.</p>
- </desc>
- </func>
- <func>
- <name>obtain_pull_consumer(Object) -> Return</name>
- <fsummary>Create a ProxyPullConsumer object</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Return = #objref</v>
- </type>
- <desc>
- <p>This operation returns a ProxyPullConsumer object reference.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosEvent/doc/src/Makefile b/lib/cosEvent/doc/src/Makefile
deleted file mode 100644
index ba505d6f7b..0000000000
--- a/lib/cosEvent/doc/src/Makefile
+++ /dev/null
@@ -1,150 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(COSEVENT_VSN)
-APPLICATION=cosEvent
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = \
- CosEventChannelAdmin.xml \
- CosEventChannelAdmin_ConsumerAdmin.xml \
- CosEventChannelAdmin_SupplierAdmin.xml \
- CosEventChannelAdmin_EventChannel.xml \
- CosEventChannelAdmin_ProxyPullConsumer.xml \
- CosEventChannelAdmin_ProxyPullSupplier.xml \
- CosEventChannelAdmin_ProxyPushConsumer.xml \
- CosEventChannelAdmin_ProxyPushSupplier.xml \
- cosEventApp.xml
-
-XML_PART_FILES = \
- part.xml \
- part_notes.xml
-XML_CHAPTER_FILES = \
- ch_contents.xml \
- ch_introduction.xml \
- ch_event_service.xml \
- notes.xml
-
-BOOK_FILES = book.xml
-
-XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \
- $(XML_PART_FILES) $(XML_CHAPTER_FILES)
-
-TECHNICAL_DESCR_FILES =
-
-GIF_FILES = \
- book.gif \
- notes.gif \
- ref_man.gif \
- user_guide.gif \
- e_s_components.gif \
- e_s_models.gif
-
-
-PS_FILES =
-
-
-# ----------------------------------------------------
-
-INTERNAL_HTML_FILES = $(TECHNICAL_DESCR_FILES:%.xml=$(HTMLDIR)/%.html)
-
-HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
-
-INFO_FILE = ../../info
-EXTRA_FILES = summary.html.src \
- $(DEFAULT_GIF_FILES) \
- $(DEFAULT_HTML_FILES) \
- $(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html)
-
-MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-
-HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
-
-TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-$(HTMLDIR)/%.gif: %.gif
- $(INSTALL_DATA) $< $@
-
-docs: pdf html man
-
-$(TOP_PDF_FILE): $(XML_FILES)
-
-pdf: $(TOP_PDF_FILE)
-
-html: gifs $(HTML_REF_MAN_FILE)
-
-clean clean_docs:
- rm -rf $(HTMLDIR)/*
- rm -f $(MAN3DIR)/*
- rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
- rm -f $(JD_HTML) $(JD_PACK)
-
-man: $(MAN3_FILES)
-
-gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-
-$(INDEX_TARGET): $(INDEX_SRC)
- sed -e 's;%VSN%;$(VSN);' $(INDEX_SRC) > $(INDEX_TARGET)
-
-debug opt:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_docs_spec: docs
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(HTMLDIR)/* \
- "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
- $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
-
-release_spec:
diff --git a/lib/cosEvent/doc/src/book.gif b/lib/cosEvent/doc/src/book.gif
deleted file mode 100644
index 94b3868792..0000000000
--- a/lib/cosEvent/doc/src/book.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosEvent/doc/src/book.xml b/lib/cosEvent/doc/src/book.xml
deleted file mode 100644
index 5c0172b4cd..0000000000
--- a/lib/cosEvent/doc/src/book.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book xmlns:xi="http://www.w3.org/2001/XInclude">
- <header titlestyle="normal">
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosEvent</title>
- <prepared></prepared>
- <docno></docno>
- <date>1998-04-25</date>
- <rev>1.0</rev>
- <file>book.xml</file>
- </header>
- <insidecover>
- </insidecover>
- <pagetext>cosEvent</pagetext>
- <preamble>
- <contents level="2"></contents>
- </preamble>
- <parts lift="no">
- <xi:include href="part.xml"/>
- </parts>
- <applications>
- <xi:include href="ref_man.xml"/>
- </applications>
- <releasenotes>
- <xi:include href="notes.xml"/>
- </releasenotes>
- <listofterms></listofterms>
- <index></index>
-</book>
-
diff --git a/lib/cosEvent/doc/src/ch_contents.xml b/lib/cosEvent/doc/src/ch_contents.xml
deleted file mode 100644
index 07773877ea..0000000000
--- a/lib/cosEvent/doc/src/ch_contents.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1999</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>The cosEvent Application</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>1999-09-17</date>
- <rev>B</rev>
- <file>ch_contents.xml</file>
- </header>
-
- <section>
- <title>Content Overview</title>
- <p>The cosEvent documentation is divided into three sections:
- </p>
- <list type="bulleted">
- <item>
- <p>PART ONE - The User's Guide
- <br></br>Description of the cosEvent Application including
- services and a small tutorial demonstrating
- the development of a simple service.</p>
- </item>
- <item>
- <p>PART TWO - Release Notes
- <br></br>A concise history of cosEvent.</p>
- </item>
- <item>
- <p>PART THREE - The Reference Manual
- <br></br> A quick reference guide, including a
- brief description, to all the functions available in cosEvent.</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Brief Description of the User's Guide</title>
- <p>The User's Guide contains the following parts:</p>
- <list type="bulleted">
- <item>
- <p>CosEvent overview</p>
- </item>
- <item>
- <p>CosEvent installation and examples</p>
- </item>
- </list>
- </section>
-</chapter>
-
diff --git a/lib/cosEvent/doc/src/ch_event_service.xml b/lib/cosEvent/doc/src/ch_event_service.xml
deleted file mode 100644
index 3a783234af..0000000000
--- a/lib/cosEvent/doc/src/ch_event_service.xml
+++ /dev/null
@@ -1,222 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Event Service</title>
- <prepared></prepared>
- <docno></docno>
- <date>97-11-19</date>
- <rev>A</rev>
- <file>ch_es_intro.xml</file>
- </header>
-
- <section>
- <title>Overview of the CosEvent Service</title>
- <p>The Event service allows programmers to subscribe to
- information channels. Suppliers can generate events without knowing the
- consumer identities and the consumer can receive events without knowing
- the supplier identity. Both push and pull event delivery are supported.
- The Event service will queue information and processes.
- </p>
- <p>The CORBA Event service provides a flexible model for
- asynchronous, decoupled communication between objects. This
- chapter outlines communication models and the roles and
- relationships of key components in the CosEvent service. It
- shows a simple example on use of this service.</p>
- </section>
-
- <section>
- <title>Event Service Components</title>
- <p>There are five components in the OMG CosEvent service architecture. These
- are described below:</p>
- <marker id="e_s_components"></marker>
- <image file="e_s_components.gif">
- <icaption>
-Figure 1: Event service Components</icaption>
- </image>
- <list type="bulleted">
- <item><em>Suppliers and consumers:</em> Consumers are the ultimate targets of
- events generated by suppliers. Consumers and suppliers can both play active
- and
- passive roles. There could be two types of consumers and suppliers: push
- or pull. A PushSupplier object can actively push an event to a passive
- PushConsumer object. Likewise, a PullSupplier object can passively
- wait for a PullConsumer object to actively pull an event from it.</item>
- <item><em>EventChannel:</em> The central abstraction in the CosEvent service is the
- EventChannel which plays the role of a mediator between consumers and
- suppliers. Consumers and suppliers register their interest with the
- EventChannel. It can provide many-to-many communication. The channel
- consumes events from one or more suppliers, and supplies events to one
- or more consumers. An EventChannel can support consumers and suppliers
- using different communication models.</item>
- <item><em>ProxySuppliers and ProxyConsumers:</em> ProxySuppliers act as middlemen
- between consumers and the EventChannel. A ProxySupplier is similar to
- a normal supplier, but includes an additional method for connecting a
- consumer to the ProxySupplier. Likewise, ProxyConsumers act as
- middlemen between suppliers and the EventChannel. A ProxyConsumer is
- similar to a normal consumer, but includes an additional method for
- connecting a supplier to the ProxyConsumer.</item>
- <item><em>Supplier and consumer administrations:</em> Consumer administration acts as
- a factory for creating ProxySuppliers. Supplier administration acts as
- a factory for creating ProxyConsumers.</item>
- </list>
- </section>
-
- <section>
- <title>Event Service Communication Models</title>
- <p>There are four general models of component collaboration in the OMG CosEvent service
- architecture. The following describes these models:
- (Please note that proxies are not shown in the diagrams for simplicity).</p>
- <marker id="e_s_models"></marker>
- <image file="e_s_models.gif">
- <icaption>
-Figure 2: Event service Communication Models</icaption>
- </image>
- <list type="bulleted">
- <item><em>The Canonical Push Model:</em> The Canonical push model shown in figure 2(A) allows
- the suppliers of events to initiate the transfer of event data to consumers.
- In this model, suppliers are active initiators and consumers are the passive
- targets of the requests. EventChannels play the role of <c><![CDATA[Notifier]]></c>.
- Thus, active suppliers use EventChannels to push data to passive consumers that
- have registered with the EventChannels.</item>
- <item><em>The Canonical Pull Model:</em>The Canonical pull model shown
- in figure 2(B)
- allows consumers to request events from suppliers. In this model,
- Consumers are
- active initiators and suppliers are the passive targets of the pull
- requests.
- EventChannel plays the role of <c><![CDATA[Procurer]]></c> since it procures
- events
- on behalf of consumers. Thus, active consumers can explicitly pull
- data
- from passive suppliers via the EventChannels.</item>
- <item><em>The Hybrid Push/Pull Model:</em> The push/pull model shown in figure 2(C) is a
- hybrid that allows consumers to request events queued at an EventChannel
- by suppliers. In this model, both suppliers and consumers are active
- initiators of the requests. EventChannels play the role of <c><![CDATA[Queue]]></c>.
- Thus, active consumers can explicitly pull data deposited by active
- suppliers via the EventChannels.</item>
- <item><em>The Hybrid Pull/Push Model:</em> The pull/push model shown in figure 2(D) is another
- hybrid that allows the channel to pull events from suppliers and push them
- to consumers. In this model, suppliers are passive targets of pull requests
- and consumers are passive targets of pushes. EventChannels play the role of
- <c><![CDATA[Intelligent Agent]]></c>. Thus, active EventChannels can pull data from
- passive suppliers and push that data to passive consumers.</item>
- </list>
- </section>
-
- <section>
- <title>A Tutorial on How to Create a Simple Service</title>
- <p>To be able to use the cosEvent application supplier and consumer objects
- must be implemented, which must inherit from the appropriate interface
- defined in the <em>CosEventComm.idl</em> specification.</p>
- <p>We start by creating an interface which inherits from the correct interface,
- e.g., CosEventComm::PushConsumer. Hence, we must also implement all
- operations defined in the PushConsumer interface. The IDL-file could look like:
- </p>
- <code type="c"><![CDATA[
-#ifndef _MYCLIENT_IDL
-#define _MYCLIENT_IDL
-#include <CosEventComm.idl>
-
-module myClientImpl {
-
- interface ownInterface:CosEventComm::PushConsumer {
-
- void ownFunctions(in any NeededArguments)
- raises(OwnExceptions);
-
- };
-};
-
-#endif
- ]]></code>
- <p>Run the IDL compiler on this file by calling the <c><![CDATA[ic:gen/1]]></c> function.
- This will produce the API named <c><![CDATA[myClientImpl_ownInterface.erl]]></c>.
- After generating the API stubs and the server skeletons it is time to
- implement the servers and if no special options are sent
- to the IDl compiler the file name is <c><![CDATA[myClientImpl_ownInterface_impl.erl]]></c>.</p>
- </section>
-
- <section>
- <title>How to Run Everything</title>
- <p>Below is a short transcript on how to run cosEvent. </p>
- <code type="none"><![CDATA[
-
-%% Start Mnesia and Orber
-mnesia:delete_schema([node()]),
-mnesia:create_schema([node()]),
-orber:install([node()]),
-mnesia:start(),
-orber:start(),
-
-%% Install cosEvent in the IFR.
-cosEventApp:install(),
-
-%% Register the application specific Client implementations
-%% in the IFR.
-'oe_myClientImpl':'oe_register'(),
-
-%% Start the cosEvent application.
-cosEventApp:start(),
-
-%% Start a channel using the default configuration
-Ch = cosEventApp:start_channel(),
-%% ... or use configuration parameters.
-Ch = cosEventApp:start_channel([{pull_interval, 10}, {maxEvents, 50}]),
-
-%% Retrieve a SupplierAdmin and a ConsumerAdmin.
-AdminSupplier = 'CosEventChannelAdmin_EventChannel':for_suppliers(Ch),
-AdminConsumer = 'CosEventChannelAdmin_EventChannel':for_consumers(Ch),
-
-%% Use the corresponding Admin object to get access to wanted Proxies
-
-%% Create a Push Consumer Proxy, which the Client Push Supplier will push
-%% events to.
-ProxyPushConsumer =
- 'CosEventChannelAdmin_SupplierAdmin':obtain_push_consumer(AdminSupplier),
-
-%% Create a Push Supplier Proxy, which will push events to the registered
-%% Push Consumer.
-ProxyPushSupplier =
- 'CosEventChannelAdmin_ConsumerAdmin':obtain_push_supplier(AdminConsumer),
-
-
-%% Create application Clients. We can, for example, start the Clients
-%% our selves or look them up in the naming service. This is application
-%% specific.
-Consumer = myClientImpl_ownInterface:oe_create(),
-Supplier = ...
-
-%% Connect each Client to the corresponding Proxy.
-'CosEventChannelAdmin_ProxyPushConsumer':
- connect_push_supplier(ProxyPushConsumer, Supplier),
-'CosEventChannelAdmin_ProxyPushSupplier':
- connect_push_consumer(ProxyPushSupplier, Consumer),
- ]]></code>
- <p>The example above, exemplifies a event system, i.e., the <em>Canonical Push Model</em>, where the Supplier client in some way generates event
- and pushes them to the proxy. The push supplier proxies will eventually
- push the events to each Consumer client.</p>
- </section>
-</chapter>
-
diff --git a/lib/cosEvent/doc/src/ch_introduction.xml b/lib/cosEvent/doc/src/ch_introduction.xml
deleted file mode 100644
index c88e96e40d..0000000000
--- a/lib/cosEvent/doc/src/ch_introduction.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1999</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Introduction to cosEvent</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>1999-09-17</date>
- <rev></rev>
- <file>ch_introduction.xml</file>
- </header>
-
- <section>
- <title>Overview</title>
- <p>The cosEvent application is a Event Service compliant with the <url href="http://www.omg.org">OMG</url>
- Event Service CosEvent.
- </p>
-
- <section>
- <title>Purpose and Dependencies</title>
- <p>CosEvent is dependent on <em>Orber</em>, which provides CORBA functionality in an Erlang environment.</p>
- </section>
-
- <section>
- <title>Prerequisites</title>
- <p>To fully understand the concepts presented in the
- documentation, it is recommended that the user is familiar
- with distributed programming and CORBA.
- </p>
- <p>Recommended reading includes <em>CORBA, Fundamentals and Programming - Jon Siegel</em> and <em>Open Telecom Platform Documentation Set</em>. It is also helpful to have read
- <em>Concurrent Programming in Erlang</em>.</p>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosEvent/doc/src/cosEventApp.xml b/lib/cosEvent/doc/src/cosEventApp.xml
deleted file mode 100644
index d26512e0c3..0000000000
--- a/lib/cosEvent/doc/src/cosEventApp.xml
+++ /dev/null
@@ -1,169 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2001</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>cosEventApp</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2000-01-31</date>
- <rev>PA1</rev>
- <file>cosEventApp.xml</file>
- </header>
- <module>cosEventApp</module>
- <modulesummary>The main module of the cosEvent application.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use:<br></br><c><![CDATA[-include_lib("cosEvent/include/*.hrl").]]></c></p>
- <p>This module contains the functions for starting and stopping the application.</p>
- </description>
- <funcs>
- <func>
- <name>install() -> Return</name>
- <fsummary>Install the cosEvent application</fsummary>
- <type>
- <v>Return = ok | {'EXCEPTION', E} | {'EXIT', R}</v>
- </type>
- <desc>
- <p>This operation installs the cosEvent application.</p>
- </desc>
- </func>
- <func>
- <name>uninstall() -> Return</name>
- <fsummary>Uninstall the cosEvent application</fsummary>
- <type>
- <v>Return = ok | {'EXCEPTION', E} | {'EXIT', R}</v>
- </type>
- <desc>
- <p>This operation uninstalls the cosEvent application.</p>
- </desc>
- </func>
- <func>
- <name>start() -> Return</name>
- <fsummary>Start the cosEvent application</fsummary>
- <type>
- <v>Return = ok | {error, Reason}</v>
- </type>
- <desc>
- <p>This operation starts the cosEvent application.</p>
- </desc>
- </func>
- <func>
- <name>stop() -> Return</name>
- <fsummary>Stop the cosEvent application</fsummary>
- <type>
- <v>Return = ok | {error, Reason}</v>
- </type>
- <desc>
- <p>This operation stops the cosEvent application.</p>
- </desc>
- </func>
- <func>
- <name>start_channel() -> Channel</name>
- <fsummary>Start a channel with default settings</fsummary>
- <type>
- <v>Channel = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new instance of a
- <seealso marker="CosEventChannelAdmin_EventChannel">Event Channel</seealso>
- using the default settings.</p>
- </desc>
- </func>
- <func>
- <name>start_channel(Options) -> Channel</name>
- <fsummary>Start a channel with settings defined by the given options</fsummary>
- <type>
- <v>Options = [Option]</v>
- <v>Option = {pull_interval, Seconds} | {typecheck, Boolean} | {maxEvents, Integer} | {blocking, Boolean}</v>
- <v>Channel = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new instance of a
- <seealso marker="CosEventChannelAdmin_EventChannel">Event Channel</seealso></p>
- <p></p>
- <list type="bulleted">
- <item><c><![CDATA[{pull_interval, Seconds}]]></c> - determine how often Proxy Pull
- Consumers will check for new events with the client application. The
- default value is 20 seconds.</item>
- <item><c><![CDATA[{typecheck, Boolean}]]></c> - if this option is set to true the
- proxies will check if the supplied client object is of correct type.
- The default value is false.</item>
- <item><c><![CDATA[{maxEvents, Integer}]]></c> - this option determine how many events
- the <c><![CDATA[ProxyPullSuppliers]]></c> will store before discarding events.
- If the limit is reached events will be discarded in any order.
- The default value is 300.</item>
- <item><c><![CDATA[{blocking, Boolean}]]></c> - this option determine the behavior of
- the channel when handling events internally. If set to <c><![CDATA[true]]></c> the
- risk of a single event supplier floods the system is reduced, but
- the performance may also be reduced.
- The default value is <c><![CDATA[true]]></c>.</item>
- </list>
- </desc>
- </func>
- <func>
- <name>start_channel_link() -> Channel</name>
- <fsummary>Start a channel, which is linked to the invoking process, with default settings</fsummary>
- <type>
- <v>Channel = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new instance of a
- <seealso marker="CosEventChannelAdmin_EventChannel">Event Channel</seealso>,
- which is linked to the invoking process, using the default settings.</p>
- </desc>
- </func>
- <func>
- <name>start_channel_link(Options) -> Channel</name>
- <fsummary>Start a channel, which is linked to the invoking process, with settings defined by the given options</fsummary>
- <type>
- <v>Options = [Option]</v>
- <v>Option = {pull_interval, Seconds} | {typecheck, Boolean} | {maxEvents, Integer} | {blocking, Boolean}</v>
- <v>Channel = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new instance of a
- <seealso marker="CosEventChannelAdmin_EventChannel">Event Channel</seealso>,
- which is linked to the invoking process, with settings defined by the
- given options. Allowed options are the same as for
- <c><![CDATA[cosEventApp:start_channel/1]]></c>.</p>
- </desc>
- </func>
- <func>
- <name>stop_channel(Channel) -> Reply</name>
- <fsummary>Terminate the target object</fsummary>
- <type>
- <v>Channel = #objref</v>
- <v>Reply = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This operation stop the target event channel.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosEvent/doc/src/e_s_components.gif b/lib/cosEvent/doc/src/e_s_components.gif
deleted file mode 100644
index a448c14ce0..0000000000
--- a/lib/cosEvent/doc/src/e_s_components.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosEvent/doc/src/e_s_models.gif b/lib/cosEvent/doc/src/e_s_models.gif
deleted file mode 100644
index 329b0858d1..0000000000
--- a/lib/cosEvent/doc/src/e_s_models.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosEvent/doc/src/fascicules.xml b/lib/cosEvent/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/cosEvent/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/cosEvent/doc/src/notes.gif b/lib/cosEvent/doc/src/notes.gif
deleted file mode 100644
index e000cca26a..0000000000
--- a/lib/cosEvent/doc/src/notes.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosEvent/doc/src/notes.xml b/lib/cosEvent/doc/src/notes.xml
deleted file mode 100644
index fe94cb64d3..0000000000
--- a/lib/cosEvent/doc/src/notes.xml
+++ /dev/null
@@ -1,333 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosEvent Release Notes</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>99-02-12</date>
- <rev>A</rev>
- <file>notes.xml</file>
- </header>
-
- <section><title>cosEvent 2.2.1</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Internal changes</p>
- <p>
- Own Id: OTP-13551</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosEvent 2.2</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> Remove the usage of erlang:now() from all Corba
- applications and use the new rand module instead of
- random. </p>
- <p>
- Own Id: OTP-12687</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosEvent 2.1.15</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> The default encoding of Erlang files has been changed
- from ISO-8859-1 to UTF-8. </p> <p> The encoding of XML
- files has also been changed to UTF-8. </p>
- <p>
- Own Id: OTP-10907</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosEvent 2.1.14</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> Postscript files no longer needed for the generation
- of PDF files have been removed. </p>
- <p>
- Own Id: OTP-11016</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosEvent 2.1.13</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Misc build updates</p>
- <p>
- Own Id: OTP-10784</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosEvent 2.1.12</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>Erlang/OTP can now be built using parallel make if you
- limit the number of jobs, for instance using '<c>make
- -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
- work at the moment because of some missing
- dependencies.</p>
- <p>
- Own Id: OTP-9451</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section>
- <title>cosEvent 2.1.11</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Removed superfluous usage of shy in the documentation since it can cause problem if
- a buggy tool is used.</p>
- <p>
- Own Id: OTP-9319 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEvent 2.1.10</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Eliminated Dialyzer warnings when using exit or throw.</p>
- <p>
- Own Id: OTP-9050 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEvent 2.1.9</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Test suites published.</p>
- <p>
- Own Id: OTP-8543 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEvent 2.1.8</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Removed the usage of the codeinclude tag in the documentation.</p>
- <p>
- Own Id: OTP-8409 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEvent 2.1.7</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- The documentation is now built with open source tools (xsltproc and fop)
- that exists on most platforms. One visible change is that the frames are removed.</p>
- <p>
- Own Id: OTP-8201 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEvent 2.1.6</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Obsolete guards, e.g. record vs is_record, has been changed
- to avoid compiler warnings.</p>
- <p>Own id: OTP-7987</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEvent 2.1.5</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Updated file headers.</p>
- <p>Own id: OTP-7837</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEvent 2.1.4</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Documentation source included in open source releases.</p>
- <p>Own id: OTP-7595</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEvent 2.1.3</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Updated file headers.</p>
- <p>Own id: OTP-7011</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEvent 2.1.2</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The documentation source has been converted from SGML to XML.</p>
- <p>Own id: OTP-6754</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEvent 2.1.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Minor Makefile changes.</p>
- <p>Own id: OTP-6701</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEvent 2.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The stub/skeleton-files generated by IC have been improved,
- i.e., depending on the IDL-files, reduced the size of the
- erl- and beam-files and decreased dependencies off Orber's
- Interface Repository. It is necessary to re-compile all IDL-files
- and use COS-applications, including Orber, compiled with
- IC-4.2.</p>
- <p>Own id: OTP-4576</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEvent 2.0</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>This version is a completely new version of the cosEvent
- application; older versions was <em>not</em> compliant with the OMG
- specification. The <c><![CDATA[look and feel]]></c> have been changed
- to be more uniform with the other COS-services.</p>
- </item>
- </list>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosEvent/doc/src/part.xml b/lib/cosEvent/doc/src/part.xml
deleted file mode 100644
index 5e32455ebb..0000000000
--- a/lib/cosEvent/doc/src/part.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosEvent User's Guide</title>
- <prepared></prepared>
- <docno></docno>
- <date>1998-04-26</date>
- <rev>1.0</rev>
- <file>part.xml</file>
- </header>
- <description>
- <p>The <em>cosEvent</em> application is an Erlang implementation of a
- CORBA Service CosEvent.</p>
- </description>
- <xi:include href="ch_contents.xml"/>
- <xi:include href="ch_introduction.xml"/>
- <xi:include href="ch_event_service.xml"/>
-</part>
-
diff --git a/lib/cosEvent/doc/src/part_notes.xml b/lib/cosEvent/doc/src/part_notes.xml
deleted file mode 100644
index 37103a5592..0000000000
--- a/lib/cosEvent/doc/src/part_notes.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosEvent Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date>1999-04-20</date>
- <rev>1.0</rev>
- <file>part_notes.xml</file>
- </header>
- <description>
- <p>The cosEvent Application is an Erlang implementation of a CORBA Service
- CosEvent.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/cosEvent/doc/src/ref_man.gif b/lib/cosEvent/doc/src/ref_man.gif
deleted file mode 100644
index b13c4efd53..0000000000
--- a/lib/cosEvent/doc/src/ref_man.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosEvent/doc/src/ref_man.xml b/lib/cosEvent/doc/src/ref_man.xml
deleted file mode 100644
index 5db5626478..0000000000
--- a/lib/cosEvent/doc/src/ref_man.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE application SYSTEM "application.dtd">
-
-<application xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosEvent Reference Manual</title>
- <prepared></prepared>
- <docno></docno>
- <date>1998-05-05</date>
- <rev>2.0</rev>
- <file>ref_man.xml</file>
- </header>
- <description>
- <p>The <em>cosEvent</em> application is an Erlang implementation of
- a CORBA Service CosEvent.</p>
- </description>
- <xi:include href="cosEventApp.xml"/>
- <xi:include href="CosEventChannelAdmin.xml"/>
- <xi:include href="CosEventChannelAdmin_ConsumerAdmin.xml"/>
- <xi:include href="CosEventChannelAdmin_SupplierAdmin.xml"/>
- <xi:include href="CosEventChannelAdmin_EventChannel.xml"/>
- <xi:include href="CosEventChannelAdmin_ProxyPullConsumer.xml"/>
- <xi:include href="CosEventChannelAdmin_ProxyPushConsumer.xml"/>
- <xi:include href="CosEventChannelAdmin_ProxyPullSupplier.xml"/>
- <xi:include href="CosEventChannelAdmin_ProxyPushSupplier.xml"/>
-</application>
-
diff --git a/lib/cosEvent/doc/src/summary.html.src b/lib/cosEvent/doc/src/summary.html.src
deleted file mode 100644
index 6196223480..0000000000
--- a/lib/cosEvent/doc/src/summary.html.src
+++ /dev/null
@@ -1 +0,0 @@
-Orber OMG Event Service \ No newline at end of file
diff --git a/lib/cosEvent/doc/src/user_guide.gif b/lib/cosEvent/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/cosEvent/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosEvent/info b/lib/cosEvent/info
deleted file mode 100644
index dc9f7b7404..0000000000
--- a/lib/cosEvent/info
+++ /dev/null
@@ -1,2 +0,0 @@
-group: orb
-short: Orber OMG Event Service
diff --git a/lib/cosEvent/src/CosEventChannelAdmin.cfg b/lib/cosEvent/src/CosEventChannelAdmin.cfg
deleted file mode 100644
index 0de579bd6f..0000000000
--- a/lib/cosEvent/src/CosEventChannelAdmin.cfg
+++ /dev/null
@@ -1,6 +0,0 @@
-{this, "CosEventChannelAdmin::SupplierAdmin"}.
-{{handle_info, "CosEventChannelAdmin::SupplierAdmin"}, true}.
-{this, "CosEventChannelAdmin::ProxyPushConsumer"}.
-{{handle_info, "CosEventChannelAdmin::ProxyPushConsumer"}, true}.
-{this, "CosEventChannelAdmin::ProxyPullConsumer"}.
-{{handle_info, "CosEventChannelAdmin::ProxyPullConsumer"}, true}.
diff --git a/lib/cosEvent/src/CosEventChannelAdmin.idl b/lib/cosEvent/src/CosEventChannelAdmin.idl
deleted file mode 100644
index d5cb92c4e0..0000000000
--- a/lib/cosEvent/src/CosEventChannelAdmin.idl
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef _COSEVENTCHANELADMIN_IDL
-#define _COSEVENTCHANELADMIN_IDL
-
-#include "CosEventComm.idl"
-
-#pragma prefix "omg.org"
-
-module CosEventChannelAdmin
-{
- exception AlreadyConnected{};
- exception TypeError{};
-
- interface ProxyPushConsumer: CosEventComm::PushConsumer
- {
- void connect_push_supplier(in CosEventComm::
- PushSupplier push_supplier)
- raises (AlreadyConnected);
- };
-
- interface ProxyPullSupplier: CosEventComm::PullSupplier
- {
- void connect_pull_consumer(in CosEventComm::
- PullConsumer pull_consumer)
- raises (AlreadyConnected);
- };
-
- interface ProxyPullConsumer: CosEventComm::PullConsumer
- {
- void connect_pull_supplier(in CosEventComm::
- PullSupplier pull_supplier)
- raises (AlreadyConnected, TypeError);
- };
-
- interface ProxyPushSupplier: CosEventComm::PushSupplier
- {
- void connect_push_consumer(in CosEventComm::
- PushConsumer push_consumer)
- raises (AlreadyConnected, TypeError);
- };
-
- interface ConsumerAdmin
- {
- ProxyPushSupplier obtain_push_supplier();
- ProxyPullSupplier obtain_pull_supplier();
- };
-
- interface SupplierAdmin
- {
- ProxyPushConsumer obtain_push_consumer();
- ProxyPullConsumer obtain_pull_consumer();
- };
-
- interface EventChannel
- {
- ConsumerAdmin for_consumers();
- SupplierAdmin for_suppliers();
- void destroy();
- };
-
-};
-
-#endif
-
-
-
-
diff --git a/lib/cosEvent/src/CosEventChannelAdmin_ProxyPullConsumer_impl.erl b/lib/cosEvent/src/CosEventChannelAdmin_ProxyPullConsumer_impl.erl
deleted file mode 100644
index cb9bb4f4a4..0000000000
--- a/lib/cosEvent/src/CosEventChannelAdmin_ProxyPullConsumer_impl.erl
+++ /dev/null
@@ -1,206 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosEventChannelAdmin_ProxyPullConsumer_impl.erl
-%% Description :
-%%
-%%----------------------------------------------------------------------
--module('CosEventChannelAdmin_ProxyPullConsumer_impl').
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include("CosEventChannelAdmin.hrl").
--include("CosEventComm.hrl").
--include("cosEventApp.hrl").
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
-%% Mandatory
--export([init/1,
- terminate/2,
- code_change/3,
- handle_info/2]).
-
-%% Interface functions
--export([connect_pull_supplier/3]).
-
-%% Exports from "CosEventComm::PullConsumer"
--export([disconnect_pull_consumer/2]).
-
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {admin, admin_pid, channel, client,
- typecheck, pull_interval, timer_ref}).
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%----------------------------------------------------------------------
-init([Admin, AdminPid, Channel, TypeCheck, PullInterval]) ->
- process_flag(trap_exit, true),
- Secs = timer:seconds(PullInterval),
- timer:start(),
- {ok, #state{admin = Admin, admin_pid = AdminPid, channel = Channel,
- typecheck = TypeCheck, pull_interval = Secs}}.
-
-%%----------------------------------------------------------------------
-%% Function : terminate/2
-%% Returns : any (ignored by gen_server)
-%% Description: Shutdown the server
-%%----------------------------------------------------------------------
-terminate(_Reason, #state{client = undefined}) ->
- ?DBG("Terminating ~p; no client connected.~n", [_Reason]),
- ok;
-terminate(_Reason, #state{client = Client} = State) ->
- stop_timer(State),
- ?DBG("Terminating ~p~n", [_Reason]),
- cosEventApp:disconnect('CosEventComm_PullSupplier',
- disconnect_pull_supplier, Client),
- ok.
-
-%%----------------------------------------------------------------------
-%% Function : code_change/3
-%% Returns : {ok, NewState}
-%% Description: Convert process state when code is changed
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%---------------------------------------------------------------------%
-%% function : handle_info
-%% Arguments:
-%% Returns : {noreply, State} |
-%% {stop, Reason, State}
-%% Effect : If the Parent Admin or the Channel terminates so must this object.
-%%----------------------------------------------------------------------
-handle_info({'EXIT', Pid, Reason}, #state{admin_pid = Pid} = State) ->
- ?DBG("Parent Admin terminated ~p~n", [Reason]),
- orber:dbg("[~p] CosEventChannelAdmin_ProxyPullConsumer:handle_info(~p);~n"
- "My Admin terminated and so will I.", [?LINE, Reason], ?DEBUG_LEVEL),
- {stop, Reason, State};
-handle_info(try_pull_event, State) ->
- try_pull_event(State);
-handle_info(_Info, State) ->
- ?DBG("Unknown Info ~p~n", [_Info]),
- {noreply, State}.
-
-%%----------------------------------------------------------------------
-%% Function : connect_pull_supplier
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-connect_pull_supplier(_OE_This, #state{client = undefined,
- typecheck = TypeCheck} = State, NewClient) ->
- case corba_object:is_nil(NewClient) of
- true ->
- ?DBG("A NIL client supplied.~n", []),
- orber:dbg("[~p] CosEventChannelAdmin_ProxyPullConsumer:connect_pull_supplier(..);~n"
- "Supplied a NIL reference which is not allowed.",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status = ?COMPLETED_NO});
- false ->
- cosEventApp:type_check(NewClient, 'CosEventComm_PullSupplier', TypeCheck),
- NewState = start_timer(State),
- {reply, ok, NewState#state{client = NewClient}}
- end;
-connect_pull_supplier(_, _, _) ->
- corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{}).
-
-
-%%----------------------------------------------------------------------
-%% Function : disconnect_pull_consumer
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-disconnect_pull_consumer(_OE_This, State) ->
- NewState = stop_timer(State),
- ?DBG("Disconnect invoked ~p~n", [NewState]),
- {stop, normal, ok, NewState#state{client = undefined}}.
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-%% Start timer which send a message each time we should pull for new events.
-start_timer(State) ->
- case catch timer:send_interval(State#state.pull_interval, try_pull_event) of
- {ok,PullTRef} ->
- ?DBG("Started timer: ~p~n", [State#state.pull_interval]),
- State#state{timer_ref = PullTRef};
- _ ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-stop_timer(#state{timer_ref = undefined} = State) ->
- ?DBG("No timer to stop~n",[]),
- State;
-stop_timer(State) ->
- ?DBG("Stopped timer~n",[]),
- timer:cancel(State#state.timer_ref),
- State#state{timer_ref = undefined}.
-
-
-try_pull_event(State) ->
- case catch 'CosEventComm_PullSupplier':try_pull(State#state.client) of
- {_,false} ->
- ?DBG("Client did not supply event~n", []),
- {noreply, State};
- {Any, true} ->
- 'oe_CosEventComm_Channel':send_sync(State#state.channel, Any),
- ?DBG("Received Event ~p and forwarded it successfully.~n", [Any]),
- {noreply, State};
- {'EXCEPTION', #'CosEventComm_Disconnected'{}} ->
- ?DBG("Client claims we are disconnectedwhen trying to pull event.~n", []),
- orber:dbg("[~p] CosEventChannelAdmin_ProxyPullConsumer:try_pull_event();~n"
- "Client claims we are disconnected when trying to pull event so I terminate.",
- [?LINE], ?DEBUG_LEVEL),
- {stop, normal, State#state{client = undefined}};
- What ->
- orber:dbg("[~p] CosEventChannelAdmin_ProxyPullConsumer:try_pull_event(~p);~n"
- "My Client behaves badly so I terminate.",
- [?LINE, What], ?DEBUG_LEVEL),
- {stop, normal, State}
- end.
-
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
diff --git a/lib/cosEvent/src/CosEventChannelAdmin_ProxyPushConsumer_impl.erl b/lib/cosEvent/src/CosEventChannelAdmin_ProxyPushConsumer_impl.erl
deleted file mode 100644
index 4c2b8629f2..0000000000
--- a/lib/cosEvent/src/CosEventChannelAdmin_ProxyPushConsumer_impl.erl
+++ /dev/null
@@ -1,170 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosEventChannelAdmin_ProxyPushConsumer_impl.erl
-%% Description :
-%%
-%%----------------------------------------------------------------------
--module('CosEventChannelAdmin_ProxyPushConsumer_impl').
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include("CosEventChannelAdmin.hrl").
--include("CosEventComm.hrl").
--include("cosEventApp.hrl").
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
-%% Mandatory
--export([init/1,
- terminate/2,
- code_change/3,
- handle_info/2]).
-
-%% Exports from "CosEventChannelAdmin::ProxyPushConsumer"
--export([connect_push_supplier/3]).
-
-%% Exports from "CosEventComm::PushConsumer"
--export([push/3,
- disconnect_push_consumer/2]).
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {admin, admin_pid, channel, client, typecheck}).
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%----------------------------------------------------------------------
-init([Admin, AdminPid, Channel, TypeCheck]) ->
- process_flag(trap_exit, true),
- {ok, #state{admin = Admin, admin_pid = AdminPid, channel = Channel,
- typecheck = TypeCheck}}.
-
-%%----------------------------------------------------------------------
-%% Function : terminate/2
-%% Returns : any (ignored by gen_server)
-%% Description: Shutdown the server
-%%----------------------------------------------------------------------
-terminate(_Reason, #state{client = undefined}) ->
- ?DBG("Terminating ~p; no client connected.~n", [_Reason]),
- ok;
-terminate(_Reason, #state{client = Client} = _State) ->
- ?DBG("Terminating ~p~n", [_Reason]),
- cosEventApp:disconnect('CosEventComm_PushSupplier',
- disconnect_push_supplier, Client),
- ok.
-
-%%----------------------------------------------------------------------
-%% Function : code_change/3
-%% Returns : {ok, NewState}
-%% Description: Convert process state when code is changed
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%---------------------------------------------------------------------%
-%% function : handle_info
-%% Arguments:
-%% Returns : {noreply, State} |
-%% {stop, Reason, State}
-%% Effect : If the Parnet Admin or the Channel terminates so must this object.
-%%----------------------------------------------------------------------
-handle_info({'EXIT', Pid, Reason}, #state{admin_pid = Pid} = State) ->
- ?DBG("Parent Admin terminated ~p~n", [Reason]),
- orber:dbg("[~p] CosEventChannelAdmin_ProxyPushConsumer:handle_info(~p);~n"
- "My Admin terminated and so will I.",
- [?LINE, Reason], ?DEBUG_LEVEL),
- {stop, Reason, State};
-handle_info(_Info, State) ->
- ?DBG("Unknown Info ~p~n", [_Info]),
- {noreply, State}.
-
-%%----------------------------------------------------------------------
-%% Function : connect_push_supplier
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-connect_push_supplier(_OE_This, #state{client = undefined,
- typecheck = TypeCheck} = State, NewClient) ->
- case corba_object:is_nil(NewClient) of
- true ->
- ?DBG("A NIL client supplied.~n", []),
- {reply, ok, State};
- false ->
- cosEventApp:type_check(NewClient, 'CosEventComm_PushSupplier', TypeCheck),
- ?DBG("Connected to client.~n", []),
- {reply, ok, State#state{client = NewClient}}
- end;
-connect_push_supplier(_, _, _) ->
- corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{}).
-
-
-%%----------------------------------------------------------------------
-%% Function : push
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-push(_OE_This, State, Any) ->
- %% We should not use corba:reply here since if we block incoming
- %% events this will prevent producers to flood the system.
- ?DBG("Received Event ~p and forwarded it successfully.~n", [Any]),
- 'oe_CosEventComm_Channel':send_sync(State#state.channel, Any),
- {reply, ok, State}.
-
-%%----------------------------------------------------------------------
-%% Function : disconnect_push_consumer
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-disconnect_push_consumer(_OE_This, State) ->
- ?DBG("Disconnect invoked ~p~n", [State]),
- {stop, normal, ok, State#state{client = undefined}}.
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
diff --git a/lib/cosEvent/src/CosEventChannelAdmin_SupplierAdmin_impl.erl b/lib/cosEvent/src/CosEventChannelAdmin_SupplierAdmin_impl.erl
deleted file mode 100644
index fb5304292b..0000000000
--- a/lib/cosEvent/src/CosEventChannelAdmin_SupplierAdmin_impl.erl
+++ /dev/null
@@ -1,160 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosEventChannelAdmin_SupplierAdmin_impl.erl
-%% Created : 21 Mar 2001
-%% Description :
-%%
-%%----------------------------------------------------------------------
--module('CosEventChannelAdmin_SupplierAdmin_impl').
-
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include("cosEventApp.hrl").
-
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
-%% Mandatory
--export([init/1,
- terminate/2,
- code_change/3,
- handle_info/2]).
-
-%% Exports from "CosEventChannelAdmin::SupplierAdmin"
--export([obtain_push_consumer/2,
- obtain_pull_consumer/2]).
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {channel, channel_pid, typecheck, pull_interval, server_options}).
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%----------------------------------------------------------------------
-init([Channel, ChannelPid, TypeCheck, PullInterval, ServerOpts]) ->
- process_flag(trap_exit, true),
- {ok, #state{channel = Channel, channel_pid = ChannelPid, typecheck = TypeCheck,
- pull_interval = PullInterval, server_options = ServerOpts}}.
-
-%%----------------------------------------------------------------------
-%% Function : terminate/2
-%% Returns : any (ignored by gen_server)
-%% Description: Shutdown the server
-%%----------------------------------------------------------------------
-terminate(_Reason, _State) ->
- ?DBG("Terminating ~p~n", [_Reason]),
- ok.
-
-%%----------------------------------------------------------------------
-%% Function : code_change/3
-%% Returns : {ok, NewState}
-%% Description: Convert process state when code is changed
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%---------------------------------------------------------------------%
-%% function : handle_info
-%% Arguments:
-%% Returns : {noreply, State} |
-%% {stop, Reason, State}
-%% Effect : Functions demanded by the gen_server module.
-%%----------------------------------------------------------------------
-handle_info({'EXIT', Pid, Reason}, #state{channel_pid = Pid} = State) ->
- ?DBG("Parent Channel terminated ~p~n", [Reason]),
- orber:dbg("[~p] CosEventChannelAdmin_SupplierAdmin:handle_info(~p);~n"
- "My Channel terminated and so will I.",
- [?LINE, Reason], ?DEBUG_LEVEL),
- {stop, Reason, State};
-handle_info(_Info, State) ->
- ?DBG("Unknown Info ~p~n", [_Info]),
- {noreply, State}.
-
-
-%%----------------------------------------------------------------------
-%% Function : obtain_push_consumer
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-obtain_push_consumer(OE_This, #state{channel = Channel,
- channel_pid = _ChannelPid,
- typecheck = TypeCheck,
- server_options = ServerOpts} = State) ->
- ?DBG("Starting a new CosEventChannelAdmin_ProxyPushConsumer.~n", []),
- {reply,
- 'CosEventChannelAdmin_ProxyPushConsumer':oe_create_link([OE_This,
- self(),
- Channel,
- TypeCheck],
- ServerOpts),
- State}.
-
-%%----------------------------------------------------------------------
-%% Function : obtain_pull_consumer
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-obtain_pull_consumer(OE_This, #state{channel = Channel,
- channel_pid = _ChannelPid,
- typecheck = TypeCheck,
- pull_interval= PullInterval,
- server_options = ServerOpts} = State) ->
- ?DBG("Starting a new CosEventChannelAdmin_ProxyPullConsumer.~n", []),
- {reply,
- 'CosEventChannelAdmin_ProxyPullConsumer':oe_create_link([OE_This,
- self(),
- Channel,
- TypeCheck,
- PullInterval],
- ServerOpts),
- State}.
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
diff --git a/lib/cosEvent/src/CosEventComm.idl b/lib/cosEvent/src/CosEventComm.idl
deleted file mode 100644
index bb0c107394..0000000000
--- a/lib/cosEvent/src/CosEventComm.idl
+++ /dev/null
@@ -1,37 +0,0 @@
-
-#ifndef _COSEVENTCOMM_IDL
-#define _COSEVENTCOMM_IDL
-
-#pragma prefix "omg.org"
-
-module CosEventComm
-{
- exception Disconnected{};
-
- interface PushConsumer
- {
- void push(in any data) raises (Disconnected);
- void disconnect_push_consumer();
- };
-
-
- interface PushSupplier
- {
- void disconnect_push_supplier();
- };
-
- interface PullSupplier
- {
- any pull() raises(Disconnected);
- any try_pull(out boolean has_event) raises(Disconnected);
- void disconnect_pull_supplier();
- };
-
- interface PullConsumer
- {
- void disconnect_pull_consumer();
- };
-};
-
-#endif
-
diff --git a/lib/cosEvent/src/Makefile b/lib/cosEvent/src/Makefile
deleted file mode 100644
index 29d6223005..0000000000
--- a/lib/cosEvent/src/Makefile
+++ /dev/null
@@ -1,217 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-ifeq ($(TYPE),debug)
-ERL_COMPILE_FLAGS += -Ddebug -W
-endif
-EBIN=../ebin
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(COSEVENT_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/cosEvent-$(VSN)
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES = \
- CosEventChannelAdmin_ProxyPullConsumer_impl \
- CosEventChannelAdmin_ProxyPushConsumer_impl \
- CosEventChannelAdmin_SupplierAdmin_impl \
- oe_CosEventComm_CAdmin_impl \
- oe_CosEventComm_Channel_impl \
- oe_CosEventComm_PullerS_impl \
- oe_CosEventComm_PusherS_impl \
- cosEventApp
-
-
-
-ERL_FILES = $(MODULES:%=%.erl)
-HRL_FILES = cosEventApp.hrl
-
-
-GEN_ERL_FILES1 = \
- oe_CosEventChannelAdmin.erl \
- CosEventChannelAdmin_ConsumerAdmin.erl \
- CosEventChannelAdmin_EventChannel.erl \
- CosEventChannelAdmin_ProxyPullConsumer.erl \
- CosEventChannelAdmin_ProxyPullSupplier.erl \
- CosEventChannelAdmin_ProxyPushConsumer.erl \
- CosEventChannelAdmin_ProxyPushSupplier.erl \
- CosEventChannelAdmin_SupplierAdmin.erl \
- CosEventChannelAdmin_AlreadyConnected.erl \
- CosEventChannelAdmin_TypeError.erl
-
-GEN_ERL_FILES2 = \
- oe_CosEventComm_CAdmin.erl \
- oe_CosEventComm_Channel.erl \
- oe_CosEventComm_Event.erl \
- oe_CosEventComm_PullerS.erl \
- oe_CosEventComm_PusherS.erl \
- oe_cosEventApp.erl
-
-GEN_ERL_FILES3 = \
- oe_CosEventComm.erl \
- CosEventComm_Disconnected.erl \
- CosEventComm_PullConsumer.erl \
- CosEventComm_PullSupplier.erl \
- CosEventComm_PushConsumer.erl \
- CosEventComm_PushSupplier.erl
-
-GEN_ERL_FILES = \
- $(GEN_ERL_FILES1) $(GEN_ERL_FILES2) $(GEN_ERL_FILES3)
-
-EXTERNAL_INC_PATH = ../include
-
-GEN_HRL_FILES1 = \
- oe_CosEventChannelAdmin.hrl \
- CosEventChannelAdmin.hrl \
- CosEventChannelAdmin_ConsumerAdmin.hrl \
- CosEventChannelAdmin_EventChannel.hrl \
- CosEventChannelAdmin_ProxyPullConsumer.hrl \
- CosEventChannelAdmin_ProxyPullSupplier.hrl \
- CosEventChannelAdmin_ProxyPushConsumer.hrl \
- CosEventChannelAdmin_ProxyPushSupplier.hrl \
- CosEventChannelAdmin_SupplierAdmin.hrl
-
-EXTERNAL_GEN_HRL_FILES1 = $(GEN_HRL_FILES1:%=$(EXTERNAL_INC_PATH)/%)
-
-GEN_HRL_FILES2 = \
- oe_CosEventComm_PullerS.hrl \
- oe_CosEventComm_CAdmin.hrl \
- oe_CosEventComm_PusherS.hrl \
- oe_CosEventComm_Channel.hrl \
- oe_cosEventApp.hrl \
- oe_CosEventComm_Event.hrl
-
-GEN_HRL_FILES3 = \
- oe_CosEventComm.hrl \
- CosEventComm.hrl \
- CosEventComm_PullConsumer.hrl \
- CosEventComm_PullSupplier.hrl \
- CosEventComm_PushConsumer.hrl \
- CosEventComm_PushSupplier.hrl
-
-EXTERNAL_GEN_HRL_FILES3 = $(GEN_HRL_FILES3:%=$(EXTERNAL_INC_PATH)/%)
-
-GEN_HRL_FILES = \
- $(EXTERNAL_GEN_HRL_FILES1) $(GEN_HRL_FILES2) $(EXTERNAL_GEN_HRL_FILES3)
-
-TARGET_FILES = \
- $(GEN_ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR)) \
- $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-GEN_FILES = $(GEN_HRL_FILES) $(GEN_ERL_FILES)
-
-IDL_FILES = \
- CosEventChannelAdmin.idl \
- CosEventComm.idl \
- cosEventApp.idl
-
-APPUP_FILE = cosEvent.appup
-APPUP_SRC = $(APPUP_FILE).src
-APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
-
-APP_FILE = cosEvent.app
-APP_SRC = $(APP_FILE).src
-APP_TARGET = $(EBIN)/$(APP_FILE)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/cosEvent/ebin -pa $(ERL_TOP)/lib/ic/ebin
-# The -pa option is just used temporary until erlc can handle
-# includes from other directories than ../include .
-ERL_COMPILE_FLAGS += \
- $(ERL_IDL_FLAGS) \
- -I$(ERL_TOP)/lib/orber/include \
- -I$(ERL_TOP)/lib/cosEvent/include \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,app_vsn,"cosEvent_$(COSEVENT_VSN)"}'
-
-YRL_FLAGS =
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
-
-debug:
- @${MAKE} TYPE=debug opt
-
-clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
- rm -f errs core *~
-
-$(APP_TARGET): $(APP_SRC)
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $(APP_SRC) > $(APP_TARGET)
-$(APPUP_TARGET): $(APPUP_SRC)
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $(APPUP_SRC) > $(APPUP_TARGET)
-
-docs:
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-IDL-GENERATED: CosEventChannelAdmin.idl cosEventApp.idl CosEventComm.idl
- $(gen_verbose)erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosEventChannelAdmin.cfg"}' CosEventChannelAdmin.idl
- $(V_at)mv $(GEN_HRL_FILES1) $(EXTERNAL_INC_PATH)
- $(V_at)erlc $(ERL_IDL_FLAGS) +'{cfgfile,"cosEventApp.cfg"}' cosEventApp.idl
- $(V_at)erlc $(ERL_IDL_FLAGS) CosEventComm.idl
- $(V_at)mv $(GEN_HRL_FILES3) $(EXTERNAL_INC_PATH)
- $(V_at)>IDL-GENERATED
-
-$(GEN_FILES): IDL-GENERATED
-
-$(TARGET_FILES): IDL-GENERATED
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DATA) ../info "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
- $(INSTALL_DIR) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILES) "$(RELSYSDIR)/src"
- $(INSTALL_DIR) "$(RELSYSDIR)/include"
- $(INSTALL_DATA) $(GEN_HRL_FILES) "$(RELSYSDIR)/include"
-
-
-release_docs_spec:
-
-
-
-
-
-
diff --git a/lib/cosEvent/src/cosEvent.app.src b/lib/cosEvent/src/cosEvent.app.src
deleted file mode 100644
index 5ffd12bc6b..0000000000
--- a/lib/cosEvent/src/cosEvent.app.src
+++ /dev/null
@@ -1,46 +0,0 @@
-{application, cosEvent,
- [{description, "The Erlang CosEvent application"},
- {vsn, "%VSN%"},
- {modules,
- [
- 'CosEventChannelAdmin_ProxyPullConsumer_impl',
- 'CosEventChannelAdmin_ProxyPushConsumer_impl',
- 'CosEventChannelAdmin_SupplierAdmin_impl',
- 'oe_CosEventComm_CAdmin_impl',
- 'oe_CosEventComm_Channel_impl',
- 'oe_CosEventComm_PullerS_impl',
- 'oe_CosEventComm_PusherS_impl',
- 'cosEventApp',
- 'oe_CosEventChannelAdmin',
- 'CosEventChannelAdmin_AlreadyConnected',
- 'CosEventChannelAdmin_ConsumerAdmin',
- 'CosEventChannelAdmin_EventChannel',
- 'CosEventChannelAdmin_ProxyPullConsumer',
- 'CosEventChannelAdmin_ProxyPullSupplier',
- 'CosEventChannelAdmin_ProxyPushConsumer',
- 'CosEventChannelAdmin_ProxyPushSupplier',
- 'CosEventChannelAdmin_SupplierAdmin',
- 'CosEventChannelAdmin_TypeError',
- 'oe_CosEventComm_CAdmin',
- 'oe_CosEventComm_Channel',
- 'oe_CosEventComm_Event',
- 'oe_CosEventComm_PullerS',
- 'oe_CosEventComm_PusherS',
- 'oe_cosEventApp',
- 'oe_CosEventComm',
- 'CosEventComm_PushSupplier',
- 'CosEventComm_PushConsumer',
- 'CosEventComm_PullSupplier',
- 'CosEventComm_PullConsumer',
- 'CosEventComm_Disconnected'
- ]
- },
- {registered, []},
- {applications, [orber, stdlib, kernel]},
- {env, []},
- {mod, {cosEventApp, []}},
- {runtime_dependencies, ["stdlib-2.0","orber-3.6.27","kernel-3.0","erts-7.0"]}
-]}.
-
-
-
diff --git a/lib/cosEvent/src/cosEvent.appup.src b/lib/cosEvent/src/cosEvent.appup.src
deleted file mode 100644
index d69b2ef20c..0000000000
--- a/lib/cosEvent/src/cosEvent.appup.src
+++ /dev/null
@@ -1,6 +0,0 @@
-{"%VSN%",
- [
- ],
- [
- ]
-}
diff --git a/lib/cosEvent/src/cosEventApp.cfg b/lib/cosEvent/src/cosEventApp.cfg
deleted file mode 100644
index bbacd134f7..0000000000
--- a/lib/cosEvent/src/cosEventApp.cfg
+++ /dev/null
@@ -1,15 +0,0 @@
-{this, "oe_CosEventComm::Event"}.
-{from, "oe_CosEventComm::Event"}.
-{{handle_info, "oe_CosEventComm::Event"}, true}.
-{this, "oe_CosEventComm::Channel"}.
-{from, "oe_CosEventComm::Channel"}.
-{{handle_info, "oe_CosEventComm::Channel"}, true}.
-{this, "oe_CosEventComm::CAdmin"}.
-{from, "oe_CosEventComm::CAdmin"}.
-{{handle_info, "oe_CosEventComm::CAdmin"}, true}.
-{this, "oe_CosEventComm::PullerS"}.
-{from, "oe_CosEventComm::PullerS"}.
-{{handle_info, "oe_CosEventComm::PullerS"}, true}.
-{this, "oe_CosEventComm::PusherS"}.
-{from, "oe_CosEventComm::PusherS"}.
-{{handle_info, "oe_CosEventComm::PusherS"}, true}.
diff --git a/lib/cosEvent/src/cosEventApp.erl b/lib/cosEvent/src/cosEventApp.erl
deleted file mode 100644
index b3c38cef0e..0000000000
--- a/lib/cosEvent/src/cosEventApp.erl
+++ /dev/null
@@ -1,301 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : cosEventApp.erl
-%% Description :
-%%
-%%----------------------------------------------------------------------
--module(cosEventApp).
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include("cosEventApp.hrl").
-
-
-%%--------------- EXPORTS-------------------------------------
-%% cosEvent API external
--export([start/0, stop/0, install/0, uninstall/0, start_channel/0, start_channel/1,
- start_channel_link/0, start_channel_link/1, stop_channel/1]).
-
-%% cosEvent API internal
--export([create_link/3, get_option/2, type_check/3, disconnect/3, do_disconnect/3]).
-
-%% Application callbacks
--export([start/2, init/1, stop/1]).
-
-%%--------------- DEFINES ------------------------------------
--define(IDL_MODULES, ['oe_CosEventComm',
- 'oe_CosEventChannelAdmin',
- 'oe_cosEventApp']).
-
--define(SUPERVISOR_NAME, oe_cosEventSup).
--define(SUP_FLAG, {simple_one_for_one,50,10}).
-
--define(SUP_SPEC(Name, Args),
- ['CosEventChannel_EventChannel',Args,
- [{sup_child, true}, {regname, {global, Name}}]]).
--define(SUP_CHILD,
- {"oe_EventChild",
- {cosEventApp,create_link, []},
- transient,100000,worker,
- ['CosEventChannel_EventChannel']}).
-
-
-%%-----------------------------------------------------------%
-%% function : install
-%% Arguments: -
-%% Returns : ok | EXIT | EXCEPTION
-%% Effect : Install necessary data in the IFR DB
-%%------------------------------------------------------------
-install() ->
- case install_loop(?IDL_MODULES, []) of
- ok ->
- ok;
- {error, Reason} ->
- exit(Reason)
- end.
-
-install_loop([], _) ->
- ok;
-install_loop([H|T], Accum) ->
- case catch H:'oe_register'() of
- {'EXIT',{unregistered,App}} ->
- ?write_ErrorMsg("Unable to register '~p'; application ~p not registered.\n"
- "Trying to unregister ~p~n", [H,App,Accum]),
- uninstall_loop(Accum, {exit, register});
- {'EXCEPTION',_} ->
- ?write_ErrorMsg("Unable to register '~p'; propably already registered.\n"
- "You are adviced to confirm this.\n"
- "Trying to unregister ~p~n", [H,Accum]),
- uninstall_loop(Accum, {exit, register});
- ok ->
- install_loop(T, [H|Accum]);
- _ ->
- ?write_ErrorMsg("Unable to register '~p'; reason unknown.\n"
- "Trying to unregister ~p~n", [H,Accum]),
- uninstall_loop(Accum, {exit, register})
- end.
-
-%%-----------------------------------------------------------%
-%% function : uninstall
-%% Arguments: -
-%% Returns : ok | EXIT | EXCEPTION
-%% Effect : Remove data related to cosEvent from the IFR DB
-%%------------------------------------------------------------
-uninstall() ->
- case uninstall_loop(lists:reverse(?IDL_MODULES), ok) of
- ok ->
- ok;
- {error, Reason} ->
- exit(Reason)
- end.
-
-uninstall_loop([],ok) ->
- ok;
-uninstall_loop([],{exit, register}) ->
- {error, {?MODULE, "oe_register failed"}};
-uninstall_loop([],{exit, unregister}) ->
- {error, {?MODULE, "oe_unregister failed"}};
-uninstall_loop([],{exit, both}) ->
- {error, {?MODULE, "oe_register and, for some of those already registered, oe_unregister failed"}};
-uninstall_loop([H|T], Status) ->
- case catch H:'oe_unregister'() of
- ok ->
- uninstall_loop(T, Status);
- _ when Status == ok ->
- ?write_ErrorMsg("Unable to unregister '~p'; propably already unregistered.\n"
- "You are adviced to confirm this.\n",[H]),
- uninstall_loop(T, {exit, unregister});
- _ ->
- ?write_ErrorMsg("Unable to unregister '~p'; propably already unregistered.\n"
- "You are adviced to confirm this.\n",[H]),
- uninstall_loop(T, {exit, both})
- end.
-
-%%-----------------------------------------------------------%
-%% function : start/stop
-%% Arguments:
-%% Returns :
-%% Effect : Starts or stops the cosTime application.
-%%------------------------------------------------------------
-
-start() ->
- application:start(cosEvent).
-stop() ->
- application:stop(cosEvent).
-
-%%-----------------------------------------------------------%
-%% function : start
-%% Arguments: Type - see module application
-%% Arg - see module application
-%% Returns :
-%% Effect : Module callback for application
-%%------------------------------------------------------------
-
-start(_, _) ->
- supervisor:start_link({local, ?SUPERVISOR_NAME}, cosEventApp, app_init).
-
-
-%%-----------------------------------------------------------%
-%% function : stop
-%% Arguments: Arg - see module application
-%% Returns :
-%% Effect : Module callback for application
-%%------------------------------------------------------------
-
-stop(_) ->
- ok.
-
-%%-----------------------------------------------------------%
-%% function : start_channel
-%% Arguments: -
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-start_channel() ->
- start_channel(?DEFAULT_OPTIONS).
-
-start_channel(Options) when is_list(Options) ->
- ServerOpts = get_option(?SERVER, Options),
- 'oe_CosEventComm_Channel':oe_create([Options, ServerOpts], ServerOpts);
-start_channel(Options) ->
- orber:dbg("[~p] cosEventApp:start_channel(~p);~n"
- "Options not correct.", [?LINE, Options], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------%
-%% function : start_channel
-%% Arguments: -
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-start_channel_link() ->
- start_channel_link(?DEFAULT_OPTIONS).
-
-start_channel_link(Options) when is_list(Options) ->
- ServerOpts = get_option(?SERVER, Options),
- 'oe_CosEventComm_Channel':oe_create_link([Options, ServerOpts], ServerOpts);
-start_channel_link(Options) ->
- orber:dbg("[~p] cosEventApp:start_channel_link(~p);~n"
- "Options not correct.", [?LINE, Options], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------%
-%% function : stop_factory
-%% Arguments: ChannelObj
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-stop_channel(ChannelObj) ->
- corba:dispose(ChannelObj).
-
-%%-----------------------------------------------------------%
-%% function : init
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-
-%% Starting using create_factory/X
-init(own_init) ->
- {ok,{?SUP_FLAG, [?SUP_CHILD]}};
-%% When starting as an application.
-init(app_init) ->
- {ok,{?SUP_FLAG, [?SUP_CHILD]}}.
-
-%%-----------------------------------------------------------%
-%% function : create_link
-%% Arguments: Module - which Module to call
-%% Env/ArgList - ordinary oe_create arguments.
-%% Returns :
-%% Exception:
-%% Effect : Necessary since we want the supervisor to be a
-%% 'simple_one_for_one'. Otherwise, using for example,
-%% 'one_for_one', we have to call supervisor:delete_child
-%% to remove the childs startspecification from the
-%% supervisors internal state.
-%%------------------------------------------------------------
-create_link(Module, Env, ArgList) ->
- Module:oe_create_link(Env, ArgList).
-
-
-%%-----------------------------------------------------------%
-%% function : get_option
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-get_option(Key, OptionList) ->
- case lists:keysearch(Key, 1, OptionList) of
- {value,{Key,Value}} ->
- Value;
- _ ->
- case lists:keysearch(Key, 1, ?DEFAULT_OPTIONS) of
- {value,{Key,Value}} ->
- Value;
- _->
- {error, "Invalid option"}
- end
- end.
-
-%%-----------------------------------------------------------%
-%% function : type_check
-%% Arguments: Obj - objectrefernce to test.
-%% Mod - Module which contains typeID/0.
-%% Returns : 'ok' or raises exception.
-%% Effect :
-%%------------------------------------------------------------
-type_check(_Obj, _Mod, false) ->
- ok;
-type_check(Obj, Mod, _) ->
- case catch corba_object:is_a(Obj, Mod:typeID()) of
- true ->
- ok;
- _ ->
- orber:dbg("[~p] cosEventApp:type_check(~p) failed; Should be ~p",
- [?LINE, Obj, Mod], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end.
-
-%%-----------------------------------------------------------%
-%% function : disconnect
-%% Arguments: Module - one of the interfaces defined in CosEventComm.
-%% Function - the appropriate disconnect function.
-%% Object - the client object reference.
-%% Returns : ok
-%% Exception:
-%% Effect : If the process would try to diconnect itself it could
-%% result in a deadlock. Hence, we spawn a new process to do it.
-%%------------------------------------------------------------
-disconnect(Module, Function, Object) ->
- spawn(cosEventApp, do_disconnect, [Module, Function, Object]),
- ok.
-
-do_disconnect(Module, Function, Object) ->
- catch Module:Function(Object),
- ?DBG("Disconnect ~p:~p(..).~n", [Module, Function]),
- ok.
-
-%%--------------- END OF MODULE ------------------------------
-
-
diff --git a/lib/cosEvent/src/cosEventApp.hrl b/lib/cosEvent/src/cosEventApp.hrl
deleted file mode 100644
index d801e83530..0000000000
--- a/lib/cosEvent/src/cosEventApp.hrl
+++ /dev/null
@@ -1,63 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : cosEventApp.hrl
-%% Description :
-%%
-%%----------------------------------------------------------------------
-
-%%--------------- INCLUDES -----------------------------------
-%% External
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-
--define(write_ErrorMsg(Txt, Arg),
-error_logger:error_msg("================ CosEvent =================~n"
- Txt
- "===========================================~n",
- Arg)).
-
-
--define(PULL_INTERVAL, pull_interval).
--define(TYPECHECK, typecheck).
--define(MAXEVENTS, maxEvents).
--define(BLOCKING, blocking).
--define(SERVER, server_options).
--define(DEFAULT_OPTIONS, [{?PULL_INTERVAL, 20},
- {?BLOCKING, true},
- {?TYPECHECK, false},
- {?MAXEVENTS, 300},
- {?SERVER, []}]).
-
--define(DEBUG_LEVEL, 3).
-
--ifdef(debug).
--define(DBG(F,A),
- io:format("[~p (~p)] "++F,[?MODULE, ?LINE]++A)).
--else.
--define(DBG(F,A), ok).
--endif.
-
-
-
-
-%%--------------- END OF MODULE ----------------------------------------
diff --git a/lib/cosEvent/src/cosEventApp.idl b/lib/cosEvent/src/cosEventApp.idl
deleted file mode 100644
index e5a134685f..0000000000
--- a/lib/cosEvent/src/cosEventApp.idl
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef _COS_EVENT_APP_IDL_
-#define _COS_EVENT_APP_IDL_
-
-#include<CosEventChannelAdmin.idl>
-
-
-module oe_CosEventComm {
-
-
- interface Event {
- oneway void send(in any event);
- void send_sync(in any event);
- };
-
- interface Channel : CosEventChannelAdmin::EventChannel, Event {};
-
- interface CAdmin : CosEventChannelAdmin::ConsumerAdmin, Event {};
-
- interface PullerS : CosEventChannelAdmin::ProxyPullSupplier, Event {};
-
- interface PusherS : CosEventChannelAdmin::ProxyPushSupplier, Event {};
-
-};
-
-
-#endif
diff --git a/lib/cosEvent/src/oe_CosEventComm_CAdmin_impl.erl b/lib/cosEvent/src/oe_CosEventComm_CAdmin_impl.erl
deleted file mode 100644
index 728c4cc5ab..0000000000
--- a/lib/cosEvent/src/oe_CosEventComm_CAdmin_impl.erl
+++ /dev/null
@@ -1,234 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : oe_CosEventComm_CAdmin_impl.erl
-%% Description :
-%%
-%%----------------------------------------------------------------------
--module(oe_CosEventComm_CAdmin_impl).
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include_lib("orber/include/corba.hrl").
--include("cosEventApp.hrl").
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
--export([init/1,
- terminate/2,
- code_change/3,
- handle_info/2]).
-
-%% Exports from "CosEventChannelAdmin::ConsumerAdmin"
--export([obtain_push_supplier/3,
- obtain_pull_supplier/3]).
-
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
-%% Exports from "oe_CosEventComm::Event"
--export([send/3, send_sync/4]).
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {channel_pid, typecheck, maxevents, proxies = [],
- server_options}).
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
-
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%----------------------------------------------------------------------
-init([ChannelPid, TypeCheck, MaxEvents, ServerOpts]) ->
- process_flag(trap_exit, true),
- {ok, #state{channel_pid = ChannelPid, typecheck = TypeCheck,
- maxevents = MaxEvents, server_options = ServerOpts}}.
-
-%%----------------------------------------------------------------------
-%% Function : terminate/2
-%% Returns : any (ignored by gen_server)
-%% Description: Shutdown the server
-%%----------------------------------------------------------------------
-terminate(_Reason, _State) ->
- ?DBG("Terminating ~p~n", [_Reason]),
- ok.
-
-%%----------------------------------------------------------------------
-%% Function : code_change/3
-%% Returns : {ok, NewState}
-%% Description: Convert process state when code is changed
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%---------------------------------------------------------------------%
-%% function : handle_info
-%% Arguments:
-%% Returns : {noreply, State} |
-%% {stop, Reason, State}
-%% Effect : Functions demanded by the gen_server module.
-%%----------------------------------------------------------------------
-handle_info({'EXIT', Pid, Reason}, #state{channel_pid = Pid} = State) ->
- ?DBG("Parent Channel terminated ~p~n", [Reason]),
- orber:dbg("[~p] oe_CosEventComm_PullerS_impl:handle_info(~p);~n"
- "My Channel terminated and so will I which will cause"
- " my children to do the same thing.",
- [?LINE, Reason], ?DEBUG_LEVEL),
- {stop, Reason, State};
-handle_info({'EXIT', Pid, _Reason}, #state{proxies = Proxies} = State) ->
- %% A child terminated which is normal. Hence, no logging.
- ?DBG("Probably a child terminated ~p~n", [_Reason]),
- {noreply, State#state{proxies = lists:keydelete(Pid, 2, Proxies)}};
-handle_info(_Info, State) ->
- ?DBG("Unknown Info ~p~n", [_Info]),
- {noreply, State}.
-
-%%----------------------------------------------------------------------
-%% Function : obtain_push_supplier
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-obtain_push_supplier(_, _, #state{server_options = ServerOpts} = State) ->
- case catch 'oe_CosEventComm_PusherS':oe_create_link([self(),
- State#state.typecheck],
- [{sup_child, true}|ServerOpts]) of
- {ok, Pid, Proxy} ->
- ?DBG("Started a new oe_CosEventComm_PusherS.~n", []),
- {reply, Proxy, State#state{proxies = [{Proxy, Pid}|State#state.proxies]}};
- Other ->
- orber:dbg("[~p] oe_CosEventComm_CAdmin:obtain_push_supplier();~nError: ~p",
- [?LINE, Other], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : obtain_pull_supplier
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-obtain_pull_supplier(_, _, #state{server_options = ServerOpts} = State) ->
- case catch 'oe_CosEventComm_PullerS':oe_create_link([self(),
- State#state.typecheck,
- State#state.maxevents],
- [{sup_child, true}|ServerOpts]) of
- {ok, Pid, Proxy} ->
- ?DBG("Started a new oe_CosEventComm_PullerS.~n", []),
- {reply, Proxy, State#state{proxies = [{Proxy, Pid}|State#state.proxies]}};
- Other ->
- orber:dbg("[~p] oe_CosEventComm_CAdmin:obtain_pull_supplier();~nError: ~p",
- [?LINE, Other], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-
-%%----------------------------------------------------------------------
-%% Function : send
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-send(_, #state{proxies = Proxies} = State, Any) ->
- ?DBG("Received Event ~p~n", [Any]),
- case send_helper(Proxies, Any, [], false) of
- ok ->
- ?DBG("Received Event and forwarded it successfully.~n", []),
- {noreply, State};
- {error, Dropped} ->
- ?DBG("Received Event but forward failed to: ~p~n", [Dropped]),
- RemainingProxies = delete_proxies(Dropped, Proxies),
- {noreply, State#state{proxies = RemainingProxies}}
- end.
-
-%%----------------------------------------------------------------------
-%% Function : send_sync
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-send_sync(_, OE_From, #state{proxies = Proxies} = State, Any) ->
- ?DBG("Received Event ~p~n", [Any]),
- corba:reply(OE_From, ok),
- case send_helper(Proxies, Any, [], true) of
- ok ->
- ?DBG("Received Event and forwarded (sync) it successfully.~n", []),
- {noreply, State};
- {error, Dropped} ->
- ?DBG("Received Event but forward (sync) failed to: ~p~n", [Dropped]),
- RemainingProxies = delete_proxies(Dropped, Proxies),
- {noreply, State#state{proxies = RemainingProxies}}
- end.
-
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-send_helper([], _, [], _) ->
- ok;
-send_helper([], _, Dropped, _) ->
- {error, Dropped};
-send_helper([{ObjRef, Pid}|T], Event, Dropped, false) ->
- case catch 'oe_CosEventComm_Event':send(ObjRef, Event) of
- ok ->
- send_helper(T, Event, Dropped, false);
- What ->
- orber:dbg("[~p] oe_CosEventComm_CAdmin:send_helper(~p, ~p);~n"
- "Bad return value ~p. Closing connection.",
- [?LINE, ObjRef, Event, What], ?DEBUG_LEVEL),
- send_helper(T, Event, [{ObjRef, Pid}|Dropped], false)
- end;
-send_helper([{ObjRef, Pid}|T], Event, Dropped, Sync) ->
- case catch 'oe_CosEventComm_Event':send_sync(ObjRef, Event) of
- ok ->
- send_helper(T, Event, Dropped, Sync);
- What ->
- orber:dbg("[~p] oe_CosEventComm_CAdmin:send_helper(~p, ~p);~n"
- "Bad return value ~p. Closing connection.",
- [?LINE, ObjRef, Event, What], ?DEBUG_LEVEL),
- send_helper(T, Event, [{ObjRef, Pid}|Dropped], Sync)
- end.
-
-delete_proxies([], RemainingProxies) ->
- RemainingProxies;
-delete_proxies([{_,Pid}|T], Proxies) ->
- Rest = lists:keydelete(Pid, 2, Proxies),
- delete_proxies(T, Rest).
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
diff --git a/lib/cosEvent/src/oe_CosEventComm_Channel_impl.erl b/lib/cosEvent/src/oe_CosEventComm_Channel_impl.erl
deleted file mode 100644
index 4f53ca6164..0000000000
--- a/lib/cosEvent/src/oe_CosEventComm_Channel_impl.erl
+++ /dev/null
@@ -1,247 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : oe_CosEventComm_Channel_impl.erl
-%% Description :
-%%
-%%----------------------------------------------------------------------
--module(oe_CosEventComm_Channel_impl).
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include_lib("orber/include/corba.hrl").
--include("cosEventApp.hrl").
-
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
-%% Mandatory
--export([init/1,
- terminate/2,
- code_change/3,
- handle_info/2]).
-
-%% Exports from "CosEventChannelAdmin::EventChannel"
--export([for_consumers/3,
- for_suppliers/3,
- destroy/3]).
-
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
-%% Exports from "oe_CosEventComm::Event"
--export([send/3, send_sync/4]).
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {typecheck, pull_interval, maxevents, blocking, cadmins = [],
- server_options}).
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%----------------------------------------------------------------------
-init([Options, ServerOpts]) ->
- process_flag(trap_exit, true),
- PullI = cosEventApp:get_option(?PULL_INTERVAL, Options),
- TC = cosEventApp:get_option(?TYPECHECK, Options),
- Max = cosEventApp:get_option(?MAXEVENTS, Options),
- Blocking = cosEventApp:get_option(?BLOCKING, Options),
- {ok, #state{typecheck = TC, pull_interval = PullI, maxevents = Max,
- blocking = Blocking, server_options = ServerOpts}}.
-
-%%----------------------------------------------------------------------
-%% Function : terminate/2
-%% Returns : any (ignored by gen_server)
-%% Description: Shutdown the server
-%%----------------------------------------------------------------------
-terminate(_Reason, _State) ->
- ?DBG("Terminating ~p~n", [_Reason]),
- ok.
-
-%%----------------------------------------------------------------------
-%% Function : code_change/3
-%% Returns : {ok, NewState}
-%% Description: Convert process state when code is changed
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%---------------------------------------------------------------------%
-%% function : handle_info
-%% Arguments:
-%% Returns : {noreply, State} |
-%% {stop, Reason, State}
-%% Effect : Functions demanded by the gen_server module.
-%%----------------------------------------------------------------------
-handle_info({'EXIT', Pid, _Reason}, #state{cadmins = CAdmins} = State) ->
- ?DBG("Probably a child terminated with Reason: ~p~n", [_Reason]),
- {noreply, State#state{cadmins = lists:keydelete(Pid, 2, CAdmins)}};
-handle_info(_Info, State) ->
- ?DBG("Unknown Info ~p~n", [_Info]),
- {noreply, State}.
-
-
-%%----------------------------------------------------------------------
-%% Function : for_consumers
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-for_consumers(_, _, #state{server_options = ServerOpts} = State) ->
- case catch 'oe_CosEventComm_CAdmin':oe_create_link([self(),
- State#state.typecheck,
- State#state.maxevents,
- ServerOpts],
- [{sup_child, true}|ServerOpts]) of
- {ok, Pid, AdminCo} ->
- ?DBG("Created a new oe_CosEventComm_CAdmin.~n", []),
- {reply, AdminCo,
- State#state{cadmins = [{AdminCo, Pid}|State#state.cadmins]}};
- Other ->
- orber:dbg("[~p] oe_CosEventComm_Channel:for_consumers(); Error: ~p",
- [?LINE, Other], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : for_suppliers
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-for_suppliers(OE_This, _, #state{server_options = ServerOpts} = State) ->
- case catch 'CosEventChannelAdmin_SupplierAdmin':oe_create_link([OE_This, self(),
- State#state.typecheck,
- State#state.pull_interval,
- ServerOpts],
- [{sup_child, true}|ServerOpts]) of
- {ok, _Pid, AdminSu} ->
- ?DBG("Created a new CosEventChannelAdmin_SupplierAdmin.~n", []),
- {reply, AdminSu, State};
- Other ->
- orber:dbg("[~p] oe_CosEventComm_Channel:for_suppliers();~nError: ~p",
- [?LINE, Other], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : destroy
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-destroy(_, _, State) ->
- ?DBG("Destroy invoked.", []),
- {stop, normal, ok, State}.
-
-%%----------------------------------------------------------------------
-%% Function : send
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-send(_OE_This, #state{cadmins = CAdmins} = State, Any) ->
- ?DBG("Received Event ~p~n", [Any]),
- case send_helper(CAdmins, Any, [], false) of
- ok ->
- ?DBG("Received Event and forwarded it successfully.~n", []),
- {noreply, State};
- {error, Dropped} ->
- ?DBG("Received Event but forward failed for: ~p~n", [Dropped]),
- RemainingAdmins = delete_cadmin(Dropped, CAdmins),
- {noreply, State#state{cadmins = RemainingAdmins}}
- end.
-
-%%----------------------------------------------------------------------
-%% Function : send_sync
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-send_sync(_OE_This, OE_From, #state{cadmins = CAdmins, blocking = BL} = State, Any) ->
- ?DBG("Received Event ~p~n", [Any]),
- corba:reply(OE_From, ok),
- case send_helper(CAdmins, Any, [], BL) of
- ok ->
- ?DBG("Received Event and forwarded (sync) it successfully.~n", []),
- {reply, ok, State};
- {error, Dropped} ->
- ?DBG("Received Event but forward (sync) failed for: ~p~n", [Dropped]),
- RemainingAdmins = delete_cadmin(Dropped, CAdmins),
- {reply, ok, State#state{cadmins = RemainingAdmins}}
- end.
-
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-send_helper([], _, [], _) ->
- ok;
-send_helper([], _, Dropped, _) ->
- {error, Dropped};
-send_helper([{ObjRef, Pid}|T], Event, Dropped, false) ->
- case catch 'oe_CosEventComm_CAdmin':send(ObjRef, Event) of
- ok ->
- send_helper(T, Event, Dropped, false);
- What ->
- orber:dbg("[~p] oe_CosEventComm_Channel:send_helper(~p, ~p);~n"
- "Bad return value ~p. Closing connection.",
- [?LINE, ObjRef, Event, What], ?DEBUG_LEVEL),
- send_helper(T, Event, [{ObjRef, Pid}|Dropped], false)
- end;
-send_helper([{ObjRef, Pid}|T], Event, Dropped, Sync) ->
- case catch 'oe_CosEventComm_CAdmin':send_sync(ObjRef, Event) of
- ok ->
- send_helper(T, Event, Dropped, Sync);
- What ->
- orber:dbg("[~p] oe_CosEventComm_Channel:send_helper(~p, ~p);~n"
- "Bad return value ~p. Closing connection.",
- [?LINE, ObjRef, Event, What], ?DEBUG_LEVEL),
- send_helper(T, Event, [{ObjRef, Pid}|Dropped], Sync)
- end.
-
-
-delete_cadmin([], RemainingAdmins) ->
- RemainingAdmins;
-delete_cadmin([{_,Pid}|T], CAdmins) ->
- Rest = lists:keydelete(Pid, 2, CAdmins),
- delete_cadmin(T, Rest).
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
diff --git a/lib/cosEvent/src/oe_CosEventComm_PullerS_impl.erl b/lib/cosEvent/src/oe_CosEventComm_PullerS_impl.erl
deleted file mode 100644
index b431296624..0000000000
--- a/lib/cosEvent/src/oe_CosEventComm_PullerS_impl.erl
+++ /dev/null
@@ -1,282 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : oe_CosEventComm_PullerS_impl.erl
-%% Description :
-%%
-%%----------------------------------------------------------------------
--module(oe_CosEventComm_PullerS_impl).
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include_lib("orber/include/corba.hrl").
--include("CosEventChannelAdmin.hrl").
--include("CosEventComm.hrl").
--include("cosEventApp.hrl").
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
--export([init/1,
- terminate/2,
- code_change/3,
- handle_info/2]).
-%% Exports from "CosEventChannelAdmin::ProxyPullSupplier"
--export([connect_pull_consumer/4]).
-
-%% Exports from "CosEventComm::PullSupplier"
--export([pull/3,
- try_pull/3,
- disconnect_pull_supplier/3]).
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
-%% Exports from "oe_CosEventComm::Event
--export([send/3, send_sync/4]).
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {admin_pid, client, db, respond_to, typecheck, maxevents}).
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%---------------------------------------------------------------------%
-%% Function : init/1
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%----------------------------------------------------------------------
-init([AdminPid, TypeCheck, MaxEvents]) ->
- process_flag(trap_exit, true),
- {ok, #state{admin_pid = AdminPid,
- db = ets:new(oe_ets, [set, private, ordered_set]),
- typecheck = TypeCheck, maxevents = MaxEvents}}.
-
-%%---------------------------------------------------------------------%
-%% function : handle_info
-%% Arguments:
-%% Returns : {noreply, State} |
-%% {stop, Reason, State}
-%% Effect : Functions demanded by the gen_server module.
-%% The CosEvent specification states:
-%% "A nil object reference may be passed to the connect_pull_consumer operation;
-%% if so a channel cannot invoke a disconnect_pull_consumer operation on the
-%% consumer; the consumer may be disconnected from the channel without being
-%% informed."
-%% If we would invoke the disconnect_pull_consumer operation
-%% at the same time as the client tries to pull an event it
-%% would cause a dead-lock. We can solve this by spawning a process
-%% but as is the client will discover that the object no longer exists
-%% the next time it tries to pull an event.
-%%----------------------------------------------------------------------
-handle_info({'EXIT', Pid, Reason}, #state{admin_pid = Pid} = State) ->
- orber:dbg("[~p] oe_CosEventComm_PullerS_impl:handle_info(~p);~n"
- "My Admin terminated and so will I.",
- [?LINE, Reason], ?DEBUG_LEVEL),
- {stop, Reason, State};
-handle_info(_Info, State) ->
- ?DBG("Unknown Info ~p~n", [_Info]),
- {noreply, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : terminate/2
-%% Returns : any (ignored by gen_server)
-%% Description: Shutdown the server
-%%----------------------------------------------------------------------
-terminate(_Reason, #state{client = undefined, respond_to = undefined, db = DB}) ->
- ?DBG("Terminating ~p; no client connected and no pending pull's.~n", [_Reason]),
- ets:delete(DB),
- ok;
-terminate(_Reason, #state{client = undefined, respond_to = ReplyTo, db = DB}) ->
- ?DBG("Terminating ~p; no client connected but a pending pull.~n", [_Reason]),
- corba:reply(ReplyTo, {'EXCEPTION', #'CosEventComm_Disconnected'{}}),
- ets:delete(DB),
- ok;
-terminate(_Reason, #state{client = Client, respond_to = undefined, db = DB}) ->
- ?DBG("Terminating ~p; no pending pull~n", [_Reason]),
- cosEventApp:disconnect('CosEventComm_PullConsumer',
- disconnect_pull_consumer, Client),
- ets:delete(DB),
- ok;
-terminate(_Reason, #state{client = Client, respond_to = ReplyTo, db = DB}) ->
- ?DBG("Terminating ~p; pending pull~n", [_Reason]),
- corba:reply(ReplyTo, {'EXCEPTION', #'CosEventComm_Disconnected'{}}),
- cosEventApp:disconnect('CosEventComm_PullConsumer',
- disconnect_pull_consumer, Client),
- ets:delete(DB),
- ok.
-
-%%---------------------------------------------------------------------%
-%% Function : code_change/3
-%% Returns : {ok, NewState}
-%% Description: Convert process state when code is changed
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_pull_consumer
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-connect_pull_consumer(_OE_This, _OE_From, #state{client = undefined,
- typecheck = TypeCheck} = State,
- NewClient) ->
- case corba_object:is_nil(NewClient) of
- true ->
- ?DBG("A NIL client supplied.~n", []),
- {reply, ok, State};
- false ->
- cosEventApp:type_check(NewClient, 'CosEventComm_PullConsumer', TypeCheck),
- ?DBG("Connected to client.~n", []),
- {reply, ok, State#state{client = NewClient}}
- end;
-connect_pull_consumer(_, _, _, _) ->
- corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{}).
-
-
-%%---------------------------------------------------------------------%
-%% Function : pull
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-pull(_OE_This, OE_From, State) ->
- case get_event(State#state.db) of
- false ->
- ?DBG("pull invoked but no event stored; put the client on hold.~n", []),
- {noreply, State#state{respond_to = OE_From}};
- Event ->
- ?DBG("pull invoked and returned: ~p~n", [Event]),
- {reply, Event, State}
- end.
-
-%%---------------------------------------------------------------------%
-%% Function : try_pull
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-try_pull(_OE_This, _OE_From, State) ->
- case get_event(State#state.db) of
- false ->
- ?DBG("try_pull invoked but no event stored.~n", []),
- {reply, {any:create(orber_tc:long(), 0), false}, State};
- Event ->
- ?DBG("try_pull invoked and returned: ~p~n", [Event]),
- {reply, {Event, true}, State}
- end.
-
-%%---------------------------------------------------------------------%
-%% Function : disconnect_pull_supplier
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-disconnect_pull_supplier(_OE_This, _OE_From, State) ->
- ?DBG("Disconnect invoked ~p ~n", [State]),
- {stop, normal, ok, State#state{client = undefined}}.
-
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-%%---------------------------------------------------------------------%
-%% Function : send
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-send(_OE_This, #state{respond_to = undefined} = State, Any) ->
- ?DBG("Received event ~p and stored it.~n", [Any]),
- store_event(State#state.db, State#state.maxevents, Any),
- {noreply, State};
-send(_OE_This, State, Any) ->
- ?DBG("Received event ~p and sent it to pending client.~n", [Any]),
- corba:reply(State#state.respond_to, Any),
- {noreply, State#state{respond_to = undefined}}.
-
-%%---------------------------------------------------------------------%
-%% Function : send_sync
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-send_sync(_OE_This, _OE_From, #state{respond_to = undefined} = State, Any) ->
- ?DBG("Received event ~p and stored it (sync).~n", [Any]),
- store_event(State#state.db, State#state.maxevents, Any),
- {reply, ok, State};
-send_sync(_OE_This, _OE_From, State, Any) ->
- ?DBG("Received event ~p and sent it to pending client (sync).~n", [Any]),
- corba:reply(State#state.respond_to, Any),
- {reply, ok, State#state{respond_to = undefined}}.
-
-
-%%---------------------------------------------------------------------%
-%% Function : store_event
-%% Arguments : DB - ets reference
-%% Event - CORBA::Any
-%% Returns : true
-%% Description: Insert the event in FIFO order.
-%%----------------------------------------------------------------------
-store_event(DB, Max, Event) ->
- case ets:info(DB, size) of
- CurrentSize when CurrentSize < Max ->
- ets:insert(DB, {{erlang:system_time(), erlang:unique_integer([positive])},
- Event});
- _ ->
- orber:dbg("[~p] oe_CosEventComm_PullerS:store_event(~p); DB full drop event.",
- [?LINE, Event], ?DEBUG_LEVEL),
- true
- end.
-
-%%---------------------------------------------------------------------%
-%% Function : get_event
-%% Arguments : DB - ets reference
-%% Event - CORBA::Any
-%% Returns : false | Event (CORBA::Any)
-%% Description: Lookup event in FIFO order; return false if no event exists.
-%%----------------------------------------------------------------------
-get_event(DB) ->
- case ets:first(DB) of
- '$end_of_table' ->
- false;
- Key ->
- [{_, Event}] = ets:lookup(DB, Key),
- ets:delete(DB, Key),
- Event
- end.
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
diff --git a/lib/cosEvent/src/oe_CosEventComm_PusherS_impl.erl b/lib/cosEvent/src/oe_CosEventComm_PusherS_impl.erl
deleted file mode 100644
index ac23412000..0000000000
--- a/lib/cosEvent/src/oe_CosEventComm_PusherS_impl.erl
+++ /dev/null
@@ -1,218 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : oe_CosEventComm_PusherS_impl.erl
-%% Description :
-%%
-%%----------------------------------------------------------------------
--module(oe_CosEventComm_PusherS_impl).
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include_lib("orber/include/corba.hrl").
--include("CosEventChannelAdmin.hrl").
--include("CosEventComm.hrl").
--include("cosEventApp.hrl").
-
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
--export([init/1,
- terminate/2,
- code_change/3,
- handle_info/2]).
-
-%% Exports from "CosEventChannelAdmin::ProxyPushSupplier"
--export([connect_push_consumer/4]).
-
-%% Exports from "CosEventComm::PushSupplier"
--export([disconnect_push_supplier/3]).
-
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
-%% Exports from "oe_CosEventComm::Event"
--export([send/3, send_sync/4]).
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {admin_pid, client, typecheck}).
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%----------------------------------------------------------------------
-init([AdminPid, TypeCheck]) ->
- process_flag(trap_exit, true),
- {ok, #state{admin_pid = AdminPid, typecheck = TypeCheck}}.
-
-%%----------------------------------------------------------------------
-%% Function : terminate/2
-%% Returns : any (ignored by gen_server)
-%% Description: Shutdown the server
-%%----------------------------------------------------------------------
-terminate(_Reason, #state{client = undefined}) ->
- ?DBG("Terminating ~p; no client connected.~n", [_Reason]),
- ok;
-terminate(_Reason, #state{client = Client} = _State) ->
- ?DBG("Terminating ~p~n", [_Reason]),
- cosEventApp:disconnect('CosEventComm_PushConsumer',
- disconnect_push_consumer, Client),
- ok.
-
-%%----------------------------------------------------------------------
-%% Function : code_change/3
-%% Returns : {ok, NewState}
-%% Description: Convert process state when code is changed
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%---------------------------------------------------------------------%
-%% function : handle_info
-%% Arguments:
-%% Returns : {noreply, State} |
-%% {stop, Reason, State}
-%% Effect : Functions demanded by the gen_server module.
-%%----------------------------------------------------------------------
-handle_info({'EXIT', Pid, Reason}, #state{admin_pid = Pid} = State) ->
- ?DBG("Parent Admin terminated ~p~n", [Reason]),
- orber:dbg("[~p] oe_CosEventComm_PusherS_impl:handle_info(~p);~n"
- "My Admin terminated and so will I.",
- [?LINE, Reason], ?DEBUG_LEVEL),
- {stop, Reason, State};
-handle_info(_Info, State) ->
- ?DBG("Unknown Info ~p~n", [_Info]),
- {noreply, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_push_consumer
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-connect_push_consumer(_OE_This, _, #state{client = undefined,
- typecheck = TypeCheck} = State, NewClient) ->
- case corba_object:is_nil(NewClient) of
- true ->
- orber:dbg("[~p] oe_CosEventComm_PusherS_impl:connect_push_consumer(..);~n"
- "Supplied a NIL reference which is not allowed.",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status = ?COMPLETED_NO});
- false ->
- cosEventApp:type_check(NewClient, 'CosEventComm_PushConsumer', TypeCheck),
- ?DBG("Connected to client.~n", []),
- {reply, ok, State#state{client = NewClient}}
- end;
-connect_push_consumer(_, _, _, _) ->
- corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{}).
-
-
-%%---------------------------------------------------------------------%
-%% Function : disconnect_push_supplier
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-disconnect_push_supplier(_OE_This, _, State) ->
- ?DBG("Disconnect invoked ~p ~n", [State]),
- {stop, normal, ok, State#state{client = undefined}}.
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : send
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-send(_OE_This, #state{client = undefined} = State, _Any) ->
- %% No consumer connected.
- ?DBG("Received event ~p but have no client.~n", [_Any]),
- {noreply, State};
-send(_OE_This, #state{client = Client} = State, Any) ->
- %% Push Data
- case catch 'CosEventComm_PushConsumer':push(Client, Any) of
- ok ->
- ?DBG("Received event ~p and delivered it client.~n", [Any]),
- {noreply, State};
- {'EXCEPTION', #'CosEventComm_Disconnected'{}} ->
- ?DBG("Received event ~p but failed to deliver it since the client claims we are disconnected.~n", [Any]),
- {stop, normal, State#state{client = undefined}};
- Other ->
- ?DBG("Received event ~p but failed to deliver it to client.~n", [Any]),
- orber:dbg("[~p] oe_CosEventComm_PusherS_impl:send(~p);~n"
- "My Client behaves badly, returned ~p, so I will terminate.",
- [?LINE, Any, Other], ?DEBUG_LEVEL),
- {stop, normal, State}
- end.
-
-
-%%----------------------------------------------------------------------
-%% Function : send_sync
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-send_sync(_OE_This, _OE_From, #state{client = undefined} = State, _Any) ->
- %% No consumer connected.
- ?DBG("Received event ~p but have no client.~n", [_Any]),
- {reply, ok, State};
-send_sync(_OE_This, OE_From, #state{client = Client} = State, Any) ->
- corba:reply(OE_From, ok),
- %% Push Data
- case catch 'CosEventComm_PushConsumer':push(Client, Any) of
- ok ->
- ?DBG("Received event ~p and delivered (sync) it client.~n", [Any]),
- {noreply, State};
- {'EXCEPTION', #'CosEventComm_Disconnected'{}} ->
- ?DBG("Received event ~p but failed to deliver (sync) it since the client claims we are disconnected.~n", [Any]),
- {stop, normal, State#state{client = undefined}};
- Other ->
- ?DBG("Received event ~p but failed to deliver (sync) it to client.~n", [Any]),
- orber:dbg("[~p] oe_CosEventComm_PusherS_impl:send_sync(~p);~n"
- "My Client behaves badly, returned ~p, so I will terminate.",
- [?LINE, Any, Other], ?DEBUG_LEVEL),
- {stop, normal, State}
- end.
-
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
-
diff --git a/lib/cosEvent/test/Makefile b/lib/cosEvent/test/Makefile
deleted file mode 100644
index 878e1c8a4c..0000000000
--- a/lib/cosEvent/test/Makefile
+++ /dev/null
@@ -1,150 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(COSEVENT_VSN)
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/cosEvent_test
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-TEST_SPEC_FILE = cosEvent.spec
-COVER_FILE = cosEvent.cover
-
-
-IDL_FILES = \
- event_test_server.idl \
-
-IDLOUTDIR = idl_output
-
-MODULES = \
- event_test_PushC_impl \
- event_test_PullC_impl \
- event_test_PushS_impl \
- event_test_PullS_impl \
- event_channel_SUITE \
- generated_SUITE
-
-GEN_MOD_COS = \
- event_test_PullC \
- event_test_PushS \
- event_test_PullS \
- oe_event_test_server \
- event_test_PushC
-
-GEN_HRL_COS = \
- event_test.hrl \
- event_test_PushC.hrl \
- event_test_PullC.hrl \
- event_test_PushS.hrl \
- event_test_PullS.hrl \
- oe_event_test_server.hrl
-
-
-GEN_MODULES = $(GEN_MOD_COS)
-
-ERL_FILES = $(MODULES:%=%.erl)
-
-HRL_FILES =
-
-GEN_HRL_FILES = $(GEN_HRL_COS)
-
-GEN_FILES = \
- $(GEN_HRL_FILES:%=$(IDLOUTDIR)/%) \
- $(GEN_MODULES:%=$(IDLOUTDIR)/%.erl)
-
-GEN_TARGET_FILES = $(GEN_MODULES:%=$(IDLOUTDIR)/%.$(EMULATOR))
-
-SUITE_TARGET_FILES = $(MODULES:%=%.$(EMULATOR))
-
-TARGET_FILES = \
- $(GEN_TARGET_FILES) \
- $(SUITE_TARGET_FILES)
-
-# ----------------------------------------------------
-# PROGRAMS
-# ----------------------------------------------------
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/orber/ebin -pa $(ERL_TOP)/lib/ic/ebin
-
-ERL_COMPILE_FLAGS += $(ERL_IDL_FLAGS) \
- -pa $(ERL_TOP)/lib/cosEvent/ebin \
- -pa $(ERL_TOP)/lib/cosEvent/test/idl_output \
- -I$(ERL_TOP)/lib/cosEvent \
- -I$(ERL_TOP)/lib/cosEvent/test/$(IDLOUTDIR)
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-tests debug opt: $(TARGET_FILES)
-
-clean:
- rm -f idl_output/*
- rm -rf java_initial_reference_idl java_cos_naming_idl
- rm -rf java_iiop_module_idl java_output/*
- rm -f $(TARGET_FILES)
- rm -f errs core *~
-
-
-docs:
-
-# ----------------------------------------------------
-# Special Targets
-# ----------------------------------------------------
-
-IDL-GENERATED: event_test_server.idl
- erlc $(ERL_IDL_FLAGS) -o$(IDLOUTDIR) event_test_server.idl
- >IDL-GENERATED
-
-$(GEN_FILES): IDL-GENERATED
-
-$(TARGET_FILES): IDL-GENERATED
-
-# ----------------------------------------------------
-# Release Targets
-# ----------------------------------------------------
-# We don't copy generated intermediate erlang and hrl files
-
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec:
-
-release_docs_spec:
-
-release_tests_spec: tests
- $(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) \
- $(COVER_FILE) $(ERL_FILES) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(SUITE_TARGET_FILES) "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELSYSDIR)/$(IDLOUTDIR)"
- $(INSTALL_DATA) $(GEN_TARGET_FILES) $(GEN_FILES) \
- "$(RELSYSDIR)/$(IDLOUTDIR)"
-
diff --git a/lib/cosEvent/test/cosEvent.cover b/lib/cosEvent/test/cosEvent.cover
deleted file mode 100644
index df12ea3ca9..0000000000
--- a/lib/cosEvent/test/cosEvent.cover
+++ /dev/null
@@ -1,2 +0,0 @@
-{incl_app,cosEvent,details}.
-
diff --git a/lib/cosEvent/test/cosEvent.spec b/lib/cosEvent/test/cosEvent.spec
deleted file mode 100644
index f793693779..0000000000
--- a/lib/cosEvent/test/cosEvent.spec
+++ /dev/null
@@ -1 +0,0 @@
-{suites,"../cosEvent_test",all}.
diff --git a/lib/cosEvent/test/event_channel_SUITE.erl b/lib/cosEvent/test/event_channel_SUITE.erl
deleted file mode 100644
index bbae8d782a..0000000000
--- a/lib/cosEvent/test/event_channel_SUITE.erl
+++ /dev/null
@@ -1,326 +0,0 @@
-%%-----------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-
--module(event_channel_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
-
--define(default_timeout, test_server:minutes(5)).
-
-
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
- event_objects_api/1, events_api/1, events_sync_api/1,
- cases/0, init_per_suite/1, end_per_suite/1,
- init_per_testcase/2, end_per_testcase/2, app_test/1]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-cases() ->
- [events_api, events_sync_api, event_objects_api,
- app_test].
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) when is_list(Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- mnesia:delete_schema([node()]),
- mnesia:create_schema([node()]),
- orber:install([node()]),
- application:start(mnesia),
- application:start(orber),
- cosEventApp:install(),
- cosEventApp:start(),
- oe_event_test_server:oe_register(),
- Config.
-
-end_per_suite(Config) when is_list(Config) ->
- oe_event_test_server:oe_unregister(),
- cosEventApp:stop(),
- cosEventApp:uninstall(),
- application:stop(orber),
- application:stop(mnesia),
- mnesia:delete_schema([node()]),
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- Config.
-
-%%-----------------------------------------------------------------
-%% Tests app file
-%%-----------------------------------------------------------------
-app_test(doc) -> [];
-app_test(suite) -> [];
-app_test(_Config) ->
- ok=test_server:app_test(cosEvent),
- ok.
-
-
-
-%% Testing the CosEvent API to setup a complete service
-event_objects_api(_Config) ->
-
- Ch = ?match({_,key,_,_,_,_}, cosEventApp:start_channel([{typecheck, true},
- {pull_interval, 300}])),
-
- AC=?match({_,key,_,_,_,_},
- 'CosEventChannelAdmin_EventChannel':for_consumers(Ch)),
- AS=?match({_,key,_,_,_,_},
- 'CosEventChannelAdmin_EventChannel':for_suppliers(Ch)),
-
- PPushS=?match({_,key,_,_,_,_},
- 'CosEventChannelAdmin_ConsumerAdmin':obtain_push_supplier(AC)),
- PPullS=?match({_,key,_,_,_,_},
- 'CosEventChannelAdmin_ConsumerAdmin':obtain_pull_supplier(AC)),
-
- PPushC=?match({_,key,_,_,_,_},
- 'CosEventChannelAdmin_SupplierAdmin':obtain_push_consumer(AS)),
- PPullC=?match({_,key,_,_,_,_},
- 'CosEventChannelAdmin_SupplierAdmin':obtain_pull_consumer(AS)),
-
- PushC=?match({_,key,_,_,_,_},
- 'event_test_PushC':oe_create([])),
- PullC=?match({_,key,_,_,_,_},
- 'event_test_PullC':oe_create(PPullC)),
-
- PushS=?match({_,key,_,_,_,_},
- 'event_test_PushS':oe_create(PPushC)),
-
- PullS=?match({_,key,_,_,_,_},
- 'event_test_PullS':oe_create([])),
-
- NIL = corba:create_nil_objref(),
-
- ?match({'EXCEPTION',{'BAD_PARAM',_,_,_}},
- 'CosEventChannelAdmin_ProxyPushSupplier':connect_push_consumer(PPushS, NIL)),
- ?match({'EXCEPTION',{'BAD_PARAM',_,_,_}},
- 'CosEventChannelAdmin_ProxyPushSupplier':connect_push_consumer(PPushS, PullS)),
- ?match(ok, 'CosEventChannelAdmin_ProxyPushSupplier':connect_push_consumer(PPushS, PushC)),
- ?match({'EXCEPTION',{'CosEventChannelAdmin_AlreadyConnected',_}},
- 'CosEventChannelAdmin_ProxyPushSupplier':connect_push_consumer(PPushS, PushC)),
-
- ?match(ok, 'CosEventChannelAdmin_ProxyPullSupplier':connect_pull_consumer(PPullS, NIL)),
- ?match({'EXCEPTION',{'BAD_PARAM',_,_,_}},
- 'CosEventChannelAdmin_ProxyPullSupplier':connect_pull_consumer(PPullS, PullS)),
- ?match(ok, 'CosEventChannelAdmin_ProxyPullSupplier':connect_pull_consumer(PPullS, PullC)),
- ?match({'EXCEPTION',{'CosEventChannelAdmin_AlreadyConnected',_}},
- 'CosEventChannelAdmin_ProxyPullSupplier':connect_pull_consumer(PPullS, PullC)),
-
- ?match(ok, 'CosEventChannelAdmin_ProxyPushConsumer':connect_push_supplier(PPushC, NIL)),
- ?match({'EXCEPTION',{'BAD_PARAM',_,_,_}},
- 'CosEventChannelAdmin_ProxyPushConsumer':connect_push_supplier(PPushC, PullS)),
- ?match(ok, 'CosEventChannelAdmin_ProxyPushConsumer':connect_push_supplier(PPushC, PushS)),
- ?match({'EXCEPTION',{'CosEventChannelAdmin_AlreadyConnected',_}},
- 'CosEventChannelAdmin_ProxyPushConsumer':connect_push_supplier(PPushC, PushS)),
-
- ?match({'EXCEPTION',{'BAD_PARAM',_,_,_}},
- 'CosEventChannelAdmin_ProxyPullConsumer':connect_pull_supplier(PPullC, NIL)),
- ?match({'EXCEPTION',{'BAD_PARAM',_,_,_}},
- 'CosEventChannelAdmin_ProxyPullConsumer':connect_pull_supplier(PPullC, PushS)),
- ?match(ok, 'CosEventChannelAdmin_ProxyPullConsumer':connect_pull_supplier(PPullC, PullS)),
- ?match({'EXCEPTION',{'CosEventChannelAdmin_AlreadyConnected',_}},
- 'CosEventChannelAdmin_ProxyPullConsumer':connect_pull_supplier(PPullC, PullS)),
-
-
- catch corba:dispose(AC),
- %% Wait a couple of seconds to be sure all data removed from DB.
- timer:sleep(2000),
-
- %% Since we terminated ConsumerAdmin only the Supplier Proxies should be terminated.
- ?match(true, corba_object:non_existent(AC)),
- ?match(true, corba_object:non_existent(PPushS)),
- ?match(true, corba_object:non_existent(PPullS)),
-
- ?match(false, corba_object:non_existent(Ch)),
- ?match(false, corba_object:non_existent(AS)),
- ?match(false, corba_object:non_existent(PPullC)),
- ?match(false, corba_object:non_existent(PPushC)),
-
- %% Terminate a proxy and check that its admin is unaffected.
- catch corba:dispose(PPullC),
- timer:sleep(2000),
- ?match(false, corba_object:non_existent(AS)),
- ?match(true, corba_object:non_existent(PPullC)),
-
- catch corba:dispose(Ch),
- timer:sleep(2000),
-
- ?match(true, corba_object:non_existent(Ch)),
- ?match(true, corba_object:non_existent(AS)),
- ?match(true, corba_object:non_existent(PPullC)),
- ?match(true, corba_object:non_existent(PPushC)),
-
- %% The client should be notified; wait for a couple of seconds and check it.
- timer:sleep(2000),
- ?match(true, corba_object:non_existent(PushC)),
- ?match(true, corba_object:non_existent(PullC)),
- ?match(true, corba_object:non_existent(PushS)),
- ?match(true, corba_object:non_existent(PullS)),
-
- ok.
-
-%% Testing the CosEvent API for sending events asynchronous
-events_api(_Config) ->
-
- Ch = ?match({_,key,_,_,_,_}, cosEventApp:start_channel([{typecheck, true},
- {pull_interval, 2},
- {blocking, false}])),
- event_sender(Ch).
-
-
-%% Testing the CosEvent API for sending events synchronous
-events_sync_api(_Config) ->
-
- Ch = ?match({_,key,_,_,_,_}, cosEventApp:start_channel([{typecheck, true},
- {pull_interval, 2},
- {blocking, true}])),
- event_sender(Ch).
-
-event_sender(Ch) ->
- Event1 = #any{typecode=tk_long, value = 1},
- Event2 = #any{typecode=tk_long, value = 2},
- Event3 = #any{typecode=tk_long, value = 3},
- Event4 = #any{typecode=tk_long, value = 4},
- Event5 = #any{typecode=tk_long, value = 5},
- Event6 = #any{typecode=tk_long, value = 6},
-
- AC=?match({_,key,_,_,_,_},
- 'CosEventChannelAdmin_EventChannel':for_consumers(Ch)),
- AS=?match({_,key,_,_,_,_},
- 'CosEventChannelAdmin_EventChannel':for_suppliers(Ch)),
-
- PPushS=?match({_,key,_,_,_,_},
- 'CosEventChannelAdmin_ConsumerAdmin':obtain_push_supplier(AC)),
- PPullS=?match({_,key,_,_,_,_},
- 'CosEventChannelAdmin_ConsumerAdmin':obtain_pull_supplier(AC)),
-
- PPushC=?match({_,key,_,_,_,_},
- 'CosEventChannelAdmin_SupplierAdmin':obtain_push_consumer(AS)),
- PPullC=?match({_,key,_,_,_,_},
- 'CosEventChannelAdmin_SupplierAdmin':obtain_pull_consumer(AS)),
-
- PushC=?match({_,key,_,_,_,_}, 'event_test_PushC':oe_create([])),
- PullC=?match({_,key,_,_,_,_}, 'event_test_PullC':oe_create(PPullS)),
-
- PushS=?match({_,key,_,_,_,_}, 'event_test_PushS':oe_create(PPushC)),
-
- PullS=?match({_,key,_,_,_,_}, 'event_test_PullS':oe_create([])),
-
- ?match(ok, 'CosEventChannelAdmin_ProxyPushSupplier':connect_push_consumer(PPushS, PushC)),
- ?match(ok, 'CosEventChannelAdmin_ProxyPullSupplier':connect_pull_consumer(PPullS, PullC)),
- ?match(ok, 'CosEventChannelAdmin_ProxyPushConsumer':connect_push_supplier(PPushC, PushS)),
- ?match(ok, 'CosEventChannelAdmin_ProxyPullConsumer':connect_pull_supplier(PPullC, PullS)),
-
- %% No events should be available at the consumer side at this point.
- ?match({_, false}, event_test_PullC:do_try_pull(PullC)),
- ?match([], event_test_PushC:get_data(PushC)),
-
- %% Push an event and wait to be sure it have reached the destination.
- ?match(ok, event_test_PushS:do_push(PushS, Event1)),
- ?match(ok, event_test_PushS:do_push(PushS, Event2)),
- ?match(ok, event_test_PushS:do_push(PushS, Event3)),
- timer:sleep(2000),
- ?match({Event1, true}, event_test_PullC:do_try_pull(PullC)),
- ?match({Event2, true}, event_test_PullC:do_try_pull(PullC)),
- ?match({Event3, true}, event_test_PullC:do_try_pull(PullC)),
- ?match({_, false}, event_test_PullC:do_try_pull(PullC)),
- ?match([Event1, Event2, Event3], event_test_PushC:get_data(PushC)),
-
- ?match(ok, event_test_PullS:add_event(PullS, Event4)),
- ?match(ok, event_test_PullS:add_event(PullS, Event5)),
- ?match(ok, event_test_PullS:add_event(PullS, Event6)),
-
- %% Since the pull operation is blocking we do not need to "sleep".
- %% The ProxyPullConsumer will pull for events according to the pull_interval
- %% parameter given when started the channel.
- ?match(Event4, event_test_PullC:do_pull(PullC)),
- ?match(Event5, event_test_PullC:do_pull(PullC)),
- ?match(Event6, event_test_PullC:do_pull(PullC)),
-
- timer:sleep(2000),
- ?match([Event4, Event5, Event6], event_test_PushC:get_data(PushC)),
-
-
- catch corba:dispose(Ch),
- %% The client should be notified; wait for a couple of seconds and check it.
- timer:sleep(2000),
- ?match(true, corba_object:non_existent(PushC)),
- ?match(true, corba_object:non_existent(PullC)),
- ?match(true, corba_object:non_existent(PushS)),
- ?match(true, corba_object:non_existent(PullS)),
-
- ok.
diff --git a/lib/cosEvent/test/event_test_PullC_impl.erl b/lib/cosEvent/test/event_test_PullC_impl.erl
deleted file mode 100644
index fb72d2e595..0000000000
--- a/lib/cosEvent/test/event_test_PullC_impl.erl
+++ /dev/null
@@ -1,44 +0,0 @@
-%%------------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%------------------------------------------------------------------------
-%% Description: a very simple implementation of PullConsumer interface
-%%------------------------------------------------------------------------
--module(event_test_PullC_impl).
-
--export([init/1, terminate/2, disconnect_pull_consumer/1, do_pull/1, do_try_pull/1]).
-
-init(Proxy) ->
- {ok, Proxy}.
-
-terminate(_From, _Reason) ->
- ok.
-
-disconnect_pull_consumer(Proxy) ->
- io:format("event_test_PullC terminates~n",[]),
- {stop, normal, ok, Proxy}.
-
-do_pull(Proxy) ->
- {reply, 'CosEventComm_PullSupplier':pull(Proxy), Proxy}.
-
-do_try_pull(Proxy) ->
- {reply, 'CosEventComm_PullSupplier':try_pull(Proxy), Proxy}.
-
diff --git a/lib/cosEvent/test/event_test_PullS_impl.erl b/lib/cosEvent/test/event_test_PullS_impl.erl
deleted file mode 100644
index de59b251da..0000000000
--- a/lib/cosEvent/test/event_test_PullS_impl.erl
+++ /dev/null
@@ -1,58 +0,0 @@
-%%------------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%------------------------------------------------------------------------
-%% Description: a very simple implementation of Pull Supplier interface
-%%------------------------------------------------------------------------
--module(event_test_PullS_impl).
-
--include_lib("orber/include/corba.hrl").
-
--export([init/1, terminate/2, pull/1, try_pull/1, disconnect_pull_supplier/1,
- add_event/2]).
-
-init(_) ->
- {ok, []}.
-
-terminate(_From, _Reason) ->
- ok.
-
-pull([]) ->
- corba:raise(#'INTERNAL'{completion_status = ?COMPLETED_NO});
-pull([Event|Events]) ->
- {reply, Event, Events}.
-
-try_pull([]) ->
- {reply, {#any{typecode=tk_null, value = null}, false}, []};
-try_pull([Event|Events]) ->
- {reply, {Event, true}, Events}.
-
-disconnect_pull_supplier(Events) ->
- io:format("event_test_PullS terminates ~p~n", [Events]),
- {stop, normal, ok, Events}.
-
-
-add_event(Events, Event) ->
- %% Store in FIFO order; don't really care if we use '++' since
- %% this operation is used in tests only.
- {reply, ok, Events ++ [Event]}.
-
-
diff --git a/lib/cosEvent/test/event_test_PushC_impl.erl b/lib/cosEvent/test/event_test_PushC_impl.erl
deleted file mode 100644
index 98e4d611fc..0000000000
--- a/lib/cosEvent/test/event_test_PushC_impl.erl
+++ /dev/null
@@ -1,47 +0,0 @@
-%%------------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%------------------------------------------------------------------------
-%% Description: a very simple implementation of Push Consumer interface
-%%------------------------------------------------------------------------
-
--module(event_test_PushC_impl).
-
--export([init/1, terminate/2, push/2, disconnect_push_consumer/1, get_data/1]).
-
-init(_) ->
- {ok, []}.
-
-terminate(_From, _Reason) ->
- ok.
-
-push(Events, Event) ->
- {reply, ok, [Event|Events]}.
-
-disconnect_push_consumer(Events) ->
- io:format("event_test_PushC terminates: ~p~n", [Events]),
- {stop, normal, ok, Events}.
-
-
-get_data(Events) ->
- %% Returns Events in FIFO order and reset state.
- {reply, lists:reverse(Events), []}.
-
diff --git a/lib/cosEvent/test/event_test_PushS_impl.erl b/lib/cosEvent/test/event_test_PushS_impl.erl
deleted file mode 100644
index 062ee8a311..0000000000
--- a/lib/cosEvent/test/event_test_PushS_impl.erl
+++ /dev/null
@@ -1,42 +0,0 @@
-%%------------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%------------------------------------------------------------------------
-%% Description: a very simple implementation of Push Supplier interface
-%%------------------------------------------------------------------------
-
--module(event_test_PushS_impl).
-
--export([init/1, terminate/2, disconnect_push_supplier/1, do_push/2]).
-
-init(Proxy) ->
- {ok, Proxy}.
-
-terminate(_From, _Reason) ->
- ok.
-
-disconnect_push_supplier(Proxy) ->
- io:format("event_test_PullC terminates~n",[]),
- {stop, normal, ok, Proxy}.
-
-do_push(Proxy, Event) ->
- {reply, 'CosEventComm_PushConsumer':push(Proxy, Event), Proxy}.
-
diff --git a/lib/cosEvent/test/event_test_server.idl b/lib/cosEvent/test/event_test_server.idl
deleted file mode 100644
index f76ac085e1..0000000000
--- a/lib/cosEvent/test/event_test_server.idl
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 2001-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-//
-
-#ifndef _EVENT_TEST_SERVER_IDL
-#define _EVENT_TEST_SERVER_IDL
-
-#include <../src/CosEventComm.idl>
-
-module event_test {
-
- interface PushC : CosEventComm::PushConsumer {
- typedef sequence<any> AnySeq;
- AnySeq get_data();
- };
- interface PullC : CosEventComm::PullConsumer {
- any do_pull();
- any do_try_pull(out boolean has_event);
- };
-
- interface PushS : CosEventComm::PushSupplier {
- void do_push(in any Event);
- };
- interface PullS : CosEventComm::PullSupplier {
- void add_event(in any Event);
- };
-
-};
-
-#endif
-
-
diff --git a/lib/cosEvent/test/generated_SUITE.erl b/lib/cosEvent/test/generated_SUITE.erl
deleted file mode 100644
index 86794023af..0000000000
--- a/lib/cosEvent/test/generated_SUITE.erl
+++ /dev/null
@@ -1,473 +0,0 @@
-%%-----------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File : generated_SUITE.erl
-%% Purpose :
-%%-----------------------------------------------------------------
-
--module(generated_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
-
--define(default_timeout, test_server:minutes(3)).
-
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
--define(nomatch(Not, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- Not ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS);
- _ ->
- AcTuAlReS
- end
- end()).
-
-
--define(checktc(_Op),
- fun(TC) ->
- case orber_tc:check_tc(TC) of
- false ->
- io:format("###### ERROR ERROR ######~n~p - ~p~n", [Op, TC]),
- exit(TC);
- true ->
- true
- end
- end).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- ['CosEventChannelAdmin_AlreadyConnected',
- 'CosEventChannelAdmin_TypeError',
- 'CosEventComm_Disconnected',
- 'CosEventChannelAdmin_ConsumerAdmin',
- 'CosEventChannelAdmin_EventChannel',
- 'CosEventChannelAdmin_ProxyPullConsumer',
- 'CosEventChannelAdmin_ProxyPullSupplier',
- 'CosEventChannelAdmin_ProxyPushConsumer',
- 'CosEventChannelAdmin_ProxyPushSupplier',
- 'CosEventChannelAdmin_SupplierAdmin',
- oe_CosEventComm_CAdmin, oe_CosEventComm_Channel,
- oe_CosEventComm_Event, oe_CosEventComm_PullerS,
- oe_CosEventComm_PusherS, 'CosEventComm_PullConsumer',
- 'CosEventComm_PullSupplier',
- 'CosEventComm_PushConsumer',
- 'CosEventComm_PushSupplier'].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventChannelAdmin_AlreadyConnected'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventChannelAdmin_AlreadyConnected'(_) ->
- ?match(true, orber_tc:check_tc('CosEventChannelAdmin_AlreadyConnected':tc())),
- ?match("IDL:omg.org/CosEventChannelAdmin/AlreadyConnected:1.0",
- 'CosEventChannelAdmin_AlreadyConnected':id()),
- ?match("CosEventChannelAdmin_AlreadyConnected",
- 'CosEventChannelAdmin_AlreadyConnected':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventChannelAdmin_TypeError'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventChannelAdmin_TypeError'(_) ->
- ?match(true, orber_tc:check_tc('CosEventChannelAdmin_TypeError':tc())),
- ?match("IDL:omg.org/CosEventChannelAdmin/TypeError:1.0",
- 'CosEventChannelAdmin_TypeError':id()),
- ?match("CosEventChannelAdmin_TypeError",
- 'CosEventChannelAdmin_TypeError':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventComm_Disconnected'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventComm_Disconnected'(_) ->
- ?match(true, orber_tc:check_tc('CosEventComm_Disconnected':tc())),
- ?match("IDL:omg.org/CosEventComm/Disconnected:1.0",
- 'CosEventComm_Disconnected':id()),
- ?match("CosEventComm_Disconnected", 'CosEventComm_Disconnected':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventChannelAdmin_ConsumerAdmin'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventChannelAdmin_ConsumerAdmin'(_) ->
- ?nomatch(undefined, 'CosEventChannelAdmin_ConsumerAdmin':oe_tc(obtain_push_supplier)),
- ?nomatch(undefined, 'CosEventChannelAdmin_ConsumerAdmin':oe_tc(obtain_pull_supplier)),
- ?match(undefined, 'CosEventChannelAdmin_ConsumerAdmin':oe_tc(undefined)),
- ?match([_|_], 'CosEventChannelAdmin_ConsumerAdmin':oe_get_interface()),
- ?match("IDL:omg.org/CosEventChannelAdmin/ConsumerAdmin:1.0",
- 'CosEventChannelAdmin_ConsumerAdmin':typeID()),
- check_tc('CosEventChannelAdmin_ConsumerAdmin':oe_get_interface()),
- ?match(true, 'CosEventChannelAdmin_ConsumerAdmin':oe_is_a('CosEventChannelAdmin_ConsumerAdmin':typeID())),
- ?match(false, 'CosEventChannelAdmin_ConsumerAdmin':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventChannelAdmin_EventChannel'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventChannelAdmin_EventChannel'(_) ->
- ?nomatch(undefined, 'CosEventChannelAdmin_EventChannel':oe_tc(for_consumers)),
- ?nomatch(undefined, 'CosEventChannelAdmin_EventChannel':oe_tc(for_suppliers)),
- ?nomatch(undefined, 'CosEventChannelAdmin_EventChannel':oe_tc(destroy)),
- ?match(undefined, 'CosEventChannelAdmin_EventChannel':oe_tc(undefined)),
- ?match([_|_], 'CosEventChannelAdmin_EventChannel':oe_get_interface()),
- ?match("IDL:omg.org/CosEventChannelAdmin/EventChannel:1.0",
- 'CosEventChannelAdmin_EventChannel':typeID()),
- check_tc('CosEventChannelAdmin_EventChannel':oe_get_interface()),
- ?match(true, 'CosEventChannelAdmin_EventChannel':oe_is_a('CosEventChannelAdmin_EventChannel':typeID())),
- ?match(false, 'CosEventChannelAdmin_EventChannel':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventChannelAdmin_ProxyPullConsumer'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventChannelAdmin_ProxyPullConsumer'(_) ->
- ?nomatch(undefined, 'CosEventChannelAdmin_ProxyPullConsumer':oe_tc(connect_pull_supplier)),
- ?nomatch(undefined, 'CosEventChannelAdmin_ProxyPullConsumer':oe_tc(disconnect_pull_consumer)),
- ?match(undefined, 'CosEventChannelAdmin_ProxyPullConsumer':oe_tc(undefined)),
- ?match([_|_], 'CosEventChannelAdmin_ProxyPullConsumer':oe_get_interface()),
- ?match("IDL:omg.org/CosEventChannelAdmin/ProxyPullConsumer:1.0",
- 'CosEventChannelAdmin_ProxyPullConsumer':typeID()),
- check_tc('CosEventChannelAdmin_ProxyPullConsumer':oe_get_interface()),
- ?match(true, 'CosEventChannelAdmin_ProxyPullConsumer':oe_is_a('CosEventChannelAdmin_ProxyPullConsumer':typeID())),
- ?match(true, 'CosEventChannelAdmin_ProxyPullConsumer':oe_is_a('CosEventComm_PullConsumer':typeID())),
- ?match(false, 'CosEventChannelAdmin_ProxyPullConsumer':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventChannelAdmin_ProxyPullSupplier'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventChannelAdmin_ProxyPullSupplier'(_) ->
- ?nomatch(undefined, 'CosEventChannelAdmin_ProxyPullSupplier':oe_tc(connect_pull_consumer)),
- ?nomatch(undefined, 'CosEventChannelAdmin_ProxyPullSupplier':oe_tc(pull)),
- ?nomatch(undefined, 'CosEventChannelAdmin_ProxyPullSupplier':oe_tc(try_pull)),
- ?nomatch(undefined, 'CosEventChannelAdmin_ProxyPullSupplier':oe_tc(disconnect_pull_supplier)),
- ?match(undefined, 'CosEventChannelAdmin_ProxyPullSupplier':oe_tc(undefined)),
- ?match([_|_], 'CosEventChannelAdmin_ProxyPullSupplier':oe_get_interface()),
- ?match("IDL:omg.org/CosEventChannelAdmin/ProxyPullSupplier:1.0",
- 'CosEventChannelAdmin_ProxyPullSupplier':typeID()),
- check_tc('CosEventChannelAdmin_ProxyPullSupplier':oe_get_interface()),
- ?match(true, 'CosEventChannelAdmin_ProxyPullSupplier':oe_is_a('CosEventChannelAdmin_ProxyPullSupplier':typeID())),
- ?match(true, 'CosEventChannelAdmin_ProxyPullSupplier':oe_is_a('CosEventComm_PullSupplier':typeID())),
- ?match(false, 'CosEventChannelAdmin_ProxyPullSupplier':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventChannelAdmin_ProxyPushConsumer'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventChannelAdmin_ProxyPushConsumer'(_) ->
- ?nomatch(undefined, 'CosEventChannelAdmin_ProxyPushConsumer':oe_tc(connect_push_supplier)),
- ?nomatch(undefined, 'CosEventChannelAdmin_ProxyPushConsumer':oe_tc(push)),
- ?nomatch(undefined, 'CosEventChannelAdmin_ProxyPushConsumer':oe_tc(disconnect_push_consumer)),
- ?match(undefined, 'CosEventChannelAdmin_ProxyPushConsumer':oe_tc(undefined)),
- ?match([_|_], 'CosEventChannelAdmin_ProxyPushConsumer':oe_get_interface()),
- ?match("IDL:omg.org/CosEventChannelAdmin/ProxyPushConsumer:1.0",
- 'CosEventChannelAdmin_ProxyPushConsumer':typeID()),
- check_tc('CosEventChannelAdmin_ProxyPushConsumer':oe_get_interface()),
- ?match(true, 'CosEventChannelAdmin_ProxyPushConsumer':oe_is_a('CosEventChannelAdmin_ProxyPushConsumer':typeID())),
- ?match(true, 'CosEventChannelAdmin_ProxyPushConsumer':oe_is_a('CosEventComm_PushConsumer':typeID())),
- ?match(false, 'CosEventChannelAdmin_ProxyPushConsumer':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventChannelAdmin_ProxyPushSupplier'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventChannelAdmin_ProxyPushSupplier'(_) ->
- ?nomatch(undefined, 'CosEventChannelAdmin_ProxyPushSupplier':oe_tc(connect_push_consumer)),
- ?nomatch(undefined, 'CosEventChannelAdmin_ProxyPushSupplier':oe_tc(disconnect_push_supplier)),
- ?match(undefined, 'CosEventChannelAdmin_ProxyPushSupplier':oe_tc(undefined)),
- ?match([_|_], 'CosEventChannelAdmin_ProxyPushSupplier':oe_get_interface()),
- ?match("IDL:omg.org/CosEventChannelAdmin/ProxyPushSupplier:1.0",
- 'CosEventChannelAdmin_ProxyPushSupplier':typeID()),
- check_tc('CosEventChannelAdmin_ProxyPushSupplier':oe_get_interface()),
- ?match(true, 'CosEventChannelAdmin_ProxyPushSupplier':oe_is_a('CosEventChannelAdmin_ProxyPushSupplier':typeID())),
- ?match(true, 'CosEventChannelAdmin_ProxyPushSupplier':oe_is_a('CosEventComm_PushSupplier':typeID())),
- ?match(false, 'CosEventChannelAdmin_ProxyPushSupplier':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventChannelAdmin_SupplierAdmin'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventChannelAdmin_SupplierAdmin'(_) ->
- ?nomatch(undefined, 'CosEventChannelAdmin_SupplierAdmin':oe_tc(obtain_push_consumer)),
- ?nomatch(undefined, 'CosEventChannelAdmin_SupplierAdmin':oe_tc(obtain_pull_consumer)),
- ?match(undefined, 'CosEventChannelAdmin_SupplierAdmin':oe_tc(undefined)),
- ?match([_|_], 'CosEventChannelAdmin_SupplierAdmin':oe_get_interface()),
- ?match("IDL:omg.org/CosEventChannelAdmin/SupplierAdmin:1.0",
- 'CosEventChannelAdmin_SupplierAdmin':typeID()),
- check_tc('CosEventChannelAdmin_SupplierAdmin':oe_get_interface()),
- ?match(true, 'CosEventChannelAdmin_SupplierAdmin':oe_is_a('CosEventChannelAdmin_SupplierAdmin':typeID())),
- ?match(false, 'CosEventChannelAdmin_SupplierAdmin':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'oe_CosEventComm_CAdmin'
-%% Description:
-%%-----------------------------------------------------------------
-'oe_CosEventComm_CAdmin'(_) ->
- ?nomatch(undefined, 'oe_CosEventComm_CAdmin':oe_tc(obtain_push_supplier)),
- ?nomatch(undefined, 'oe_CosEventComm_CAdmin':oe_tc(obtain_pull_supplier)),
- ?nomatch(undefined, 'oe_CosEventComm_CAdmin':oe_tc(send)),
- ?nomatch(undefined, 'oe_CosEventComm_CAdmin':oe_tc(send_sync)),
- ?match(undefined, 'oe_CosEventComm_CAdmin':oe_tc(undefined)),
- ?match([_|_], 'oe_CosEventComm_CAdmin':oe_get_interface()),
- ?match("IDL:oe_CosEventComm/CAdmin:1.0",
- 'oe_CosEventComm_CAdmin':typeID()),
- check_tc('oe_CosEventComm_CAdmin':oe_get_interface()),
- ?match(true, 'oe_CosEventComm_CAdmin':oe_is_a('oe_CosEventComm_CAdmin':typeID())),
- ?match(true, 'oe_CosEventComm_CAdmin':oe_is_a('CosEventChannelAdmin_ConsumerAdmin':typeID())),
- ?match(true, 'oe_CosEventComm_CAdmin':oe_is_a('oe_CosEventComm_Event':typeID())),
- ?match(false, 'oe_CosEventComm_CAdmin':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'oe_CosEventComm_Channel'
-%% Description:
-%%-----------------------------------------------------------------
-'oe_CosEventComm_Channel'(_) ->
- ?nomatch(undefined, 'oe_CosEventComm_Channel':oe_tc(for_consumers)),
- ?nomatch(undefined, 'oe_CosEventComm_Channel':oe_tc(for_suppliers)),
- ?nomatch(undefined, 'oe_CosEventComm_Channel':oe_tc(destroy)),
- ?nomatch(undefined, 'oe_CosEventComm_Channel':oe_tc(send)),
- ?nomatch(undefined, 'oe_CosEventComm_Channel':oe_tc(send_sync)),
- ?match(undefined, 'oe_CosEventComm_Channel':oe_tc(undefined)),
- ?match([_|_], 'oe_CosEventComm_Channel':oe_get_interface()),
- ?match("IDL:oe_CosEventComm/Channel:1.0",
- 'oe_CosEventComm_Channel':typeID()),
- check_tc('oe_CosEventComm_Channel':oe_get_interface()),
- ?match(true, 'oe_CosEventComm_Channel':oe_is_a('oe_CosEventComm_Channel':typeID())),
- ?match(true, 'oe_CosEventComm_Channel':oe_is_a('CosEventChannelAdmin_EventChannel':typeID())),
- ?match(true, 'oe_CosEventComm_Channel':oe_is_a('oe_CosEventComm_Event':typeID())),
- ?match(false, 'oe_CosEventComm_Channel':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'oe_CosEventComm_Event'
-%% Description:
-%%-----------------------------------------------------------------
-'oe_CosEventComm_Event'(_) ->
- ?nomatch(undefined, 'oe_CosEventComm_Event':oe_tc(send)),
- ?nomatch(undefined, 'oe_CosEventComm_Event':oe_tc(send_sync)),
- ?match(undefined, 'oe_CosEventComm_Event':oe_tc(undefined)),
- ?match([_|_], 'oe_CosEventComm_Event':oe_get_interface()),
- ?match("IDL:oe_CosEventComm/Event:1.0",
- 'oe_CosEventComm_Event':typeID()),
- check_tc('oe_CosEventComm_Event':oe_get_interface()),
- ?match(true, 'oe_CosEventComm_Event':oe_is_a('oe_CosEventComm_Event':typeID())),
- ?match(false, 'oe_CosEventComm_Event':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'oe_CosEventComm_PullerS'
-%% Description:
-%%-----------------------------------------------------------------
-'oe_CosEventComm_PullerS'(_) ->
- ?nomatch(undefined, 'oe_CosEventComm_PullerS':oe_tc(connect_pull_consumer)),
- ?nomatch(undefined, 'oe_CosEventComm_PullerS':oe_tc(pull)),
- ?nomatch(undefined, 'oe_CosEventComm_PullerS':oe_tc(try_pull)),
- ?nomatch(undefined, 'oe_CosEventComm_PullerS':oe_tc(disconnect_pull_supplier)),
- ?nomatch(undefined, 'oe_CosEventComm_PullerS':oe_tc(send)),
- ?nomatch(undefined, 'oe_CosEventComm_PullerS':oe_tc(send_sync)),
- ?match(undefined, 'oe_CosEventComm_PullerS':oe_tc(undefined)),
- ?match([_|_], 'oe_CosEventComm_PullerS':oe_get_interface()),
- ?match("IDL:oe_CosEventComm/PullerS:1.0",
- 'oe_CosEventComm_PullerS':typeID()),
- check_tc('oe_CosEventComm_PullerS':oe_get_interface()),
- ?match(true, 'oe_CosEventComm_PullerS':oe_is_a('oe_CosEventComm_PullerS':typeID())),
- ?match(true, 'oe_CosEventComm_PullerS':oe_is_a('CosEventChannelAdmin_ProxyPullSupplier':typeID())),
- ?match(true, 'oe_CosEventComm_PullerS':oe_is_a('CosEventComm_PullSupplier':typeID())),
- ?match(true, 'oe_CosEventComm_PullerS':oe_is_a('oe_CosEventComm_Event':typeID())),
- ?match(false, 'oe_CosEventComm_PullerS':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'oe_CosEventComm_PusherS'
-%% Description:
-%%-----------------------------------------------------------------
-'oe_CosEventComm_PusherS'(_) ->
- ?nomatch(undefined, 'oe_CosEventComm_PusherS':oe_tc(connect_push_consumer)),
- ?nomatch(undefined, 'oe_CosEventComm_PusherS':oe_tc(disconnect_push_supplier)),
- ?nomatch(undefined, 'oe_CosEventComm_PusherS':oe_tc(send)),
- ?nomatch(undefined, 'oe_CosEventComm_PusherS':oe_tc(send_sync)),
- ?match(undefined, 'oe_CosEventComm_PusherS':oe_tc(undefined)),
- ?match([_|_], 'oe_CosEventComm_PusherS':oe_get_interface()),
- ?match("IDL:oe_CosEventComm/PusherS:1.0",
- 'oe_CosEventComm_PusherS':typeID()),
- check_tc('oe_CosEventComm_PusherS':oe_get_interface()),
- ?match(true, 'oe_CosEventComm_PusherS':oe_is_a('oe_CosEventComm_PusherS':typeID())),
- ?match(true, 'oe_CosEventComm_PusherS':oe_is_a('CosEventChannelAdmin_ProxyPushSupplier':typeID())),
- ?match(true, 'oe_CosEventComm_PusherS':oe_is_a('CosEventComm_PushSupplier':typeID())),
- ?match(true, 'oe_CosEventComm_PusherS':oe_is_a('oe_CosEventComm_Event':typeID())),
- ?match(false, 'oe_CosEventComm_PusherS':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventComm_PullConsumer'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventComm_PullConsumer'(_) ->
- ?nomatch(undefined, 'CosEventComm_PullConsumer':oe_tc(disconnect_pull_consumer)),
- ?match(undefined, 'CosEventComm_PullConsumer':oe_tc(undefined)),
- ?match([_|_], 'CosEventComm_PullConsumer':oe_get_interface()),
- ?match("IDL:omg.org/CosEventComm/PullConsumer:1.0",
- 'CosEventComm_PullConsumer':typeID()),
- check_tc('CosEventComm_PullConsumer':oe_get_interface()),
- ?match(true, 'CosEventComm_PullConsumer':oe_is_a('CosEventComm_PullConsumer':typeID())),
- ?match(false, 'CosEventComm_PullConsumer':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventComm_PullSupplier'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventComm_PullSupplier'(_) ->
- ?nomatch(undefined, 'CosEventComm_PullSupplier':oe_tc(pull)),
- ?nomatch(undefined, 'CosEventComm_PullSupplier':oe_tc(try_pull)),
- ?nomatch(undefined, 'CosEventComm_PullSupplier':oe_tc(disconnect_pull_supplier)),
- ?match(undefined, 'CosEventComm_PullSupplier':oe_tc(undefined)),
- ?match([_|_], 'CosEventComm_PullSupplier':oe_get_interface()),
- ?match("IDL:omg.org/CosEventComm/PullSupplier:1.0",
- 'CosEventComm_PullSupplier':typeID()),
- check_tc('CosEventComm_PullSupplier':oe_get_interface()),
- ?match(true, 'CosEventComm_PullSupplier':oe_is_a('CosEventComm_PullSupplier':typeID())),
- ?match(false, 'CosEventComm_PullSupplier':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventComm_PushConsumer'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventComm_PushConsumer'(_) ->
- ?nomatch(undefined, 'CosEventComm_PushConsumer':oe_tc(push)),
- ?nomatch(undefined, 'CosEventComm_PushConsumer':oe_tc(disconnect_push_consumer)),
- ?match(undefined, 'CosEventComm_PushConsumer':oe_tc(undefined)),
- ?match([_|_], 'CosEventComm_PushConsumer':oe_get_interface()),
- ?match("IDL:omg.org/CosEventComm/PushConsumer:1.0",
- 'CosEventComm_PushConsumer':typeID()),
- check_tc('CosEventComm_PushConsumer':oe_get_interface()),
- ?match(true, 'CosEventComm_PushConsumer':oe_is_a('CosEventComm_PushConsumer':typeID())),
- ?match(false, 'CosEventComm_PushConsumer':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventComm_PushSupplier'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventComm_PushSupplier'(_) ->
- ?nomatch(undefined, 'CosEventComm_PushSupplier':oe_tc(disconnect_push_supplier)),
- ?match(undefined, 'CosEventComm_PushSupplier':oe_tc(undefined)),
- ?match([_|_], 'CosEventComm_PushSupplier':oe_get_interface()),
- ?match("IDL:omg.org/CosEventComm/PushSupplier:1.0",
- 'CosEventComm_PushSupplier':typeID()),
- check_tc('CosEventComm_PushSupplier':oe_get_interface()),
- ?match(true, 'CosEventComm_PushSupplier':oe_is_a('CosEventComm_PushSupplier':typeID())),
- ?match(false, 'CosEventComm_PushSupplier':oe_is_a("wrong")),
- ok.
-
-
-
-%%-----------------------------------------------------------------
-%% MISC functions
-%%-----------------------------------------------------------------
-check_tc([]) ->
- ok;
-check_tc([{Op, {RetType, InParameters, OutParameters}}|T]) ->
- io:format("checked - ~s~n", [Op]),
- lists:all(?checktc(Op), [RetType|InParameters]),
- lists:all(?checktc(Op), OutParameters),
- check_tc(T).
-
-
diff --git a/lib/cosEvent/vsn.mk b/lib/cosEvent/vsn.mk
deleted file mode 100644
index c39bed9fe4..0000000000
--- a/lib/cosEvent/vsn.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-COSEVENT_VSN = 2.2.1
-
diff --git a/lib/cosEventDomain/AUTHORS b/lib/cosEventDomain/AUTHORS
deleted file mode 100644
index 6d03df4c5a..0000000000
--- a/lib/cosEventDomain/AUTHORS
+++ /dev/null
@@ -1,4 +0,0 @@
-Original Authors:
-Niclas Eklund
-
-Contributors:
diff --git a/lib/cosEventDomain/Makefile b/lib/cosEventDomain/Makefile
deleted file mode 100644
index 8e8ae7e4da..0000000000
--- a/lib/cosEventDomain/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2001-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include vsn.mk
-VSN=$(COSEVENTDOMAIN_VSN)
-
-# ----------------------------------------------------
-# Common Macros
-# ----------------------------------------------------
-
-SUB_DIRECTORIES = src doc/src
-
-SPECIAL_TARGETS =
-
-# ----------------------------------------------------
-# Default Subdir Targets
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_subdir.mk
-
diff --git a/lib/cosEventDomain/doc/pdf/.gitignore b/lib/cosEventDomain/doc/pdf/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosEventDomain/doc/pdf/.gitignore
+++ /dev/null
diff --git a/lib/cosEventDomain/doc/src/CosEventDomainAdmin.xml b/lib/cosEventDomain/doc/src/CosEventDomainAdmin.xml
deleted file mode 100644
index 6931059e67..0000000000
--- a/lib/cosEventDomain/doc/src/CosEventDomainAdmin.xml
+++ /dev/null
@@ -1,93 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2002</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosEventDomainAdmin</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2001-08-20</date>
- <rev>PA1</rev>
- </header>
- <module>CosEventDomainAdmin</module>
- <modulesummary>This module export functions which return QoS and Admin Properties constants.</modulesummary>
- <description>
- <p>To get access to all definitions include necessary <c><![CDATA[hrl]]></c> files by using:<br></br><c><![CDATA[-include_lib("cosEventDomain/include/*.hrl").]]></c></p>
- </description>
- <funcs>
- <func>
- <name>'CycleDetection'() -> string()</name>
- <fsummary>Return the CycleDetection identifier required when defining QoS Properties</fsummary>
- <desc>
- <p>This function returns the CycleDetection identifier; required when
- defining QoS Properties.</p>
- </desc>
- </func>
- <func>
- <name>'AuthorizeCycles'() -> short()</name>
- <fsummary>Return the AuthorizeCycles value; required when defining QoS Properties</fsummary>
- <desc>
- <p>This function returns the AuthorizeCycles value; required when
- defining QoS Properties.</p>
- </desc>
- </func>
- <func>
- <name>'ForbidCycles'() -> short()</name>
- <fsummary>Return the ForbidCycles value; required when defining QoS Properties</fsummary>
- <desc>
- <p>This function returns the ForbidCycles value; required when
- defining QoS Properties.</p>
- </desc>
- </func>
- <func>
- <name>'DiamondDetection'() -> string()</name>
- <fsummary>Return the DiamondDetection identifier required when defining QoS Properties</fsummary>
- <desc>
- <p>This function returns the DiamondDetection identifier; required when
- defining QoS Properties.</p>
- </desc>
- </func>
- <func>
- <name>'AuthorizeDiamonds'() -> short()</name>
- <fsummary>Return the AuthorizeDiamonds value; required when defining QoS Properties</fsummary>
- <desc>
- <p>This function returns the AuthorizeDiamonds value; required when
- defining QoS Properties.</p>
- </desc>
- </func>
- <func>
- <name>'ForbidDiamonds'() -> short()</name>
- <fsummary>Return the ForbidDiamonds value; required when defining QoS Properties</fsummary>
- <desc>
- <p>This function returns the ForbidDiamonds value; required when
- defining QoS Properties.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosEventDomain/doc/src/CosEventDomainAdmin_EventDomain.xml b/lib/cosEventDomain/doc/src/CosEventDomainAdmin_EventDomain.xml
deleted file mode 100644
index e99c8d380b..0000000000
--- a/lib/cosEventDomain/doc/src/CosEventDomainAdmin_EventDomain.xml
+++ /dev/null
@@ -1,627 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2001</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosEventDomainAdmin_EventDomain</title>
- <prepared></prepared>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2001-08-20</date>
- <rev>PA1</rev>
- </header>
- <module>CosEventDomainAdmin_EventDomain</module>
- <modulesummary>This module implements the Event Domain interface.</modulesummary>
- <description>
- <p>To get access to all definitions include necessary <c><![CDATA[hrl]]></c> files by using:<br></br><c><![CDATA[-include_lib("cosEventDomain/include/*.hrl").]]></c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item><em>CosNotification_QoSAdmin</em></item>
- <item><em>CosNotification_AdminPropertiesAdmin</em></item>
- </list>
- </description>
- <funcs>
- <func>
- <name>add_channel(EventDomain, Channel) -> MemberID</name>
- <fsummary>Add a new channel to the EventDomain</fsummary>
- <type>
- <v>EventDomain = Channel = #objref</v>
- <v>MemberID = long()</v>
- </type>
- <desc>
- <p>Adds the given channel to the target domain. The channel
- must be a <c><![CDATA[CosNotifyChannelAdmin::EventChannel]]></c>.</p>
- </desc>
- </func>
- <func>
- <name>get_all_channels(EventDomain) -> MemberIDSeq</name>
- <fsummary>Return all channel id's associated with target object</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>MemberIDSeq = [long()]</v>
- </type>
- <desc>
- <p>Returns a a sequence of all channels associated with
- the target object.</p>
- </desc>
- </func>
- <func>
- <name>get_channel(EventDomain, MemberID) -> Reply</name>
- <fsummary>Return the channel associated with the given id</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>MemberID = long()</v>
- <v>Reply = Channel | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- <v>Channel = #objref</v>
- </type>
- <desc>
- <p>If the target domain have a <c><![CDATA[CosNotifyChannelAdmin::EventChannel]]></c>
- represented by the given id this channel is returned. Otherwise,
- an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>remove_channel(EventDomain, MemberID) -> Reply</name>
- <fsummary>Remove the channel associated with the given id and remove all connections of that channel</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>MemberID = long()</v>
- <v>Reply = ok | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a <c><![CDATA[CosNotifyChannelAdmin::EventChannel]]></c> with the
- <c><![CDATA[MemberID]]></c> exists it will removed and all its <c><![CDATA[Connections]]></c>
- terminated. Otherwise an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>add_connection(EventDomain, Connection) -> Reply</name>
- <fsummary>If possible, setup a connection described by the <c><![CDATA[#'CosEventDomainAdmin_Connection'{}]]></c>struct</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Connection = 'CosEventDomainAdmin_Connection'{supplier_id=MemberID, consumer_id=MemberID, ctype=Type, notification_style=Style}</v>
- <v>MemberID = long()</v>
- <v>Type = 'ANY_EVENT' | 'STRUCTURED_EVENT' | 'SEQUENCE_EVENT'</v>
- <v>Style = 'Pull' | 'Push'</v>
- <v>Reply = ConnectionID | {'EXCEPTION', Exc}</v>
- <v>ConnectionID = long()</v>
- <v>Exc = #'CosNotifyChannelAdmin_ChannelNotFound'{} | #'CosNotifyChannelAdmin_TypeError'{} | #'CosEventDomainAdmin_AlreadyExists'{} | #'CosEventDomainAdmin_DiamondCreationForbidden'{diam=RouteSeq} | #'CosEventDomainAdmin_CycleCreationForbidden'{cyc=MemberIDSeq}</v>
- <v>RouteSeq = [MemberIDSeq]</v>
- <v>MemberIDSeq = [long()]</v>
- </type>
- <desc>
- <p>The Connection parameter must contain valid data to enable
- the target domain to setup a connection between two channels.
- The struct members <c><![CDATA[supplier_id]]></c> and <c><![CDATA[consumer_id]]></c>
- determines which channel should produce and consume events.
- which type of events and if the supplier should push or the
- consumer pull events is determined by <c><![CDATA[ctype]]></c> and
- <c><![CDATA[notification_style]]></c> respectively.</p>
- <p>If the target domain is not able to setup the connection
- the appropriate exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>get_all_connections(EventDomain) -> ConnectionIDSeq</name>
- <fsummary>Return a sequence of all connections within the target domain</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>ConnectionIDSeq = [long()]</v>
- </type>
- <desc>
- <p>This operation returns a sequence of all connections within
- the target domain.</p>
- </desc>
- </func>
- <func>
- <name>get_connection(EventDomain, ConnectionID) -> Reply</name>
- <fsummary>Return a <c><![CDATA[#'CosEventDomainAdmin_Connection'{}]]></c>struct describing the connection associated with the given id within the target domain</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>ConnectionID = long()</v>
- <v>Reply = Connection | {'EXCEPTION', #'CosEventDomainAdmin_ConnectionNotFound'{}}</v>
- <v>Connection = 'CosEventDomainAdmin_Connection'{supplier_id=MemberID, consumer_id=MemberID, ctype=Type, notification_style=Style}</v>
- <v>MemberID = long()</v>
- <v>Type = 'ANY_EVENT' | 'STRUCTURED_EVENT' | 'SEQUENCE_EVENT'</v>
- <v>Style = 'Pull' | 'Push'</v>
- </type>
- <desc>
- <p>If a connection identified by the given id exists within the
- target domain, a <c><![CDATA[#'CosEventDomainAdmin_Connection'{}]]></c> which
- describe the connection is returned. Otherwise, an exception
- is raised.</p>
- </desc>
- </func>
- <func>
- <name>remove_connection(EventDomain, ConnectionID) -> Reply</name>
- <fsummary>Remove the connection identified by the given id from the target domain</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>ConnectionID = long()</v>
- <v>Reply = ok | {'EXCEPTION', #'CosEventDomainAdmin_ConnectionNotFound'{}}</v>
- </type>
- <desc>
- <p>If the supplied connection id exists, the connection the
- id represents is terminated. Otherwise, an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>get_offer_channels(EventDomain, MemberID) -> Reply</name>
- <fsummary>Return all id's of the channels which produce events received by the channel identified by the given id</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>MemberID = long()</v>
- <v>Reply = MemberIDSeq | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>This operation returns a sequence, containing the member id's
- of all channels within the target domain which will supply events
- to the channel identified by the given id. But, if no such
- id exists in this domain, an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>get_subscription_channels(EventDomain, MemberID) -> Reply</name>
- <fsummary>Return all id's of the channels which consume events supplied by the channel identified by the given id</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Reply = MemberIDSeq | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>This operations behaves like <c><![CDATA[get_subscription_channels]]></c>;
- the difference is that the id's returned identifies channels
- which will consume events supplied by the channel associated
- with the given id.</p>
- </desc>
- </func>
- <func>
- <name>destroy(EventDomain) -> ok</name>
- <fsummary>Destroy the event domain and all connections within it</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- </type>
- <desc>
- <p>Calling this operation will terminate all connections
- within the target domain. The domain will terminate but
- all channels will not be affected.</p>
- </desc>
- </func>
- <func>
- <name>get_cycles(EventDomain) -> RouteSeq</name>
- <fsummary>Return a list of all cycles which exists within the target domain</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>RouteSeq = [MemberIDSeq]</v>
- <v>MemberIDSeq = [long()]</v>
- </type>
- <desc>
- <p>Returns a list of all cycles within the target domain.</p>
- </desc>
- </func>
- <func>
- <name>get_diamonds(EventDomain) -> DiamondSeq</name>
- <fsummary>Return a list of all diamonds which exists within the target domain</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>DiamondSeq = [RouteSeq]</v>
- <v>RouteSeq = [MemberIDSeq]</v>
- <v>MemberIDSeq = [long()]</v>
- </type>
- <desc>
- <p>Returns a list of all diamonds within the target domain</p>
- </desc>
- </func>
- <func>
- <name>set_default_consumer_channel(EventDomain, MemberID) -> Reply</name>
- <fsummary>Set the channel represented by the given id as default for supplier clients</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Reply = MemberID | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- <v>MemberID = long()</v>
- </type>
- <desc>
- <p>If the given id represents a channel within the target domain,
- this channel will be used when connection a supplier client
- without specifying a certain channel. If no such channel exists
- an exceptions is raised.</p>
- </desc>
- </func>
- <func>
- <name>set_default_supplier_channel(EventDomain, MemberID) -> Reply</name>
- <fsummary>Set the channel represented by the given id as default for supplier clients</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Reply = MemberID | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- <v>MemberID = long()</v>
- </type>
- <desc>
- <p>If the given id represents a channel within the target domain,
- this channel will be used when connection a consumer client
- without specifying a certain channel. If no such channel exists
- an exceptions is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_push_consumer(EventDomain, Consumer) -> Reply</name>
- <fsummary>Connect the PushConsumer to the default Channel</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Consumer = CosEventComm::PushConsumer</v>
- <v>Reply = CosNotifyChannelAdmin::ProxyPushSupplier | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a default Channel have been set, this operation connects the given
- PushConsumer to it. Otherwise, the
- <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_pull_consumer(EventDomain, Consumer) -> Reply</name>
- <fsummary>Connect the PullConsumer to the default Channel</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Consumer = CosEventComm::PullConsumer</v>
- <v>Reply = CosNotifyChannelAdmin::ProxyPullSupplier | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a default Channel have been set, this operation connects the given
- PullConsumer to it. Otherwise, the
- <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_push_supplier(EventDomain, Supplier) -> Reply</name>
- <fsummary>Connect the PushSupplier to the default Channel</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Supplier = CosEventComm::PushSupplier</v>
- <v>Reply = CosNotifyChannelAdmin::ProxyPushConsumer | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a default Channel have been set, this operation connects the given
- PushSupplier to it. Otherwise, the
- <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_pull_supplier(EventDomain, Supplier) -> Reply</name>
- <fsummary>Connect the PullSupplier to the default Channel</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Supplier = CosEventComm::PullSupplier</v>
- <v>Reply = CosNotifyChannelAdmin::ProxyPushConsumer | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a default Channel have been set, this operation connects the given
- PullSupplier to it. Otherwise, the
- <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_structured_push_consumer(EventDomain, Consumer) -> Reply</name>
- <fsummary>Connect the StructuredPushConsumer to the default Channel</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Consumer = CosNotifyComm::StructuredPushConsumer</v>
- <v>Reply = CosNotifyChannelAdmin::StructuredProxyPushSupplier | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a default Channel have been set, this operation connects the given
- StructuredPushConsumer to it. Otherwise, the
- <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_structured_pull_consumer(EventDomain, Consumer) -> Reply</name>
- <fsummary>Connect the StructuredPullConsumer to the default Channel</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Consumer = CosNotifyComm::StructuredPullConsumer</v>
- <v>Reply = CosNotifyChannelAdmin::StructuredProxyPullSupplier | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a default Channel have been set, this operation connects the given
- StructuredPullConsumer to it. Otherwise, the
- <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_structured_push_supplier(EventDomain, Supplier) -> Reply</name>
- <fsummary>Connect the StructuredPushSupplier to the default Channel</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Supplier = CosNotifyComm::StructuredPushSupplier</v>
- <v>Reply = CosNotifyChannelAdmin::StructuredProxyPushConsumer | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a default Channel have been set, this operation connects the given
- StructuredPushSupplier to it. Otherwise, the
- <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_structured_pull_supplier(EventDomain, Supplier) -> Reply</name>
- <fsummary>Connect the StructuredPullSupplier to the default Channel</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Supplier = CosNotifyComm::StructuredPullSupplier</v>
- <v>Reply = CosNotifyChannelAdmin::StructuredProxyPullConsume | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a default Channel have been set, this operation connects the given
- StructuredPullSupplier to it. Otherwise, the
- <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_sequence_push_consumer(EventDomain, Consumer) -> Reply</name>
- <fsummary>Connect the SequencePushConsumer to the default Channel</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Consumer = CosNotifyComm::SequencePushConsumer</v>
- <v>Reply = CosNotifyChannelAdmin::SequenceProxyPushSupplier | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a default Channel have been set, this operation connects the given
- SequencePushConsumer to it. Otherwise, the
- <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_sequence_pull_consumer(EventDomain, Consumer) -> Reply</name>
- <fsummary>Connect the SequencePullConsumer to the default Channel</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Consumer = CosNotifyComm::SequencePullConsumer</v>
- <v>Reply = CosNotifyChannelAdmin::SequenceProxyPullSupplier | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a default Channel have been set, this operation connects the given
- SequencePullConsumer to it. Otherwise, the
- <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_sequence_push_supplier(EventDomain, Supplier) -> Reply</name>
- <fsummary>Connect the SequencePushSupplier to the default Channel</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Supplier = CosNotifyComm::SequencePushSupplier</v>
- <v>Reply = CosNotifyChannelAdmin::SequenceProxyPushConsumer | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a default Channel have been set, this operation connects the given
- SequencePushSupplier to it. Otherwise, the
- <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_sequence_pull_supplier(EventDomain, Supplier) -> Reply</name>
- <fsummary>Connect the SequencePullSupplier to the default Channel</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Supplier = CosNotifyComm::SequencePullSupplier</v>
- <v>Reply = CosNotifyChannelAdmin::SequenceProxyPullConsumer | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a default Channel have been set, this operation connects the given
- SequencePullSupplier to it. Otherwise, the
- <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_push_consumer_with_id(EventDomain, Consumer, MemberID) -> Reply</name>
- <fsummary>Connect the PushConsumer to the Channel with the given MemberID</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Consumer = CosEventComm::PushConsumer</v>
- <v>MemberID = long()</v>
- <v>Reply = CosNotifyChannelAdmin::ProxyPushSupplier | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a Channel associated with the given MemberID exists within the
- target Domain, this operation connects the given PushConsumer
- to it. Otherwise, the <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c>
- exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_pull_consumer_with_id(EventDomain, Consumer, MemberID) -> Reply</name>
- <fsummary>Connect the PullConsumer to the Channel with the given MemberID</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Consumer = CosEventComm::PullConsumer</v>
- <v>MemberID = long()</v>
- <v>Reply = CosNotifyChannelAdmin::ProxyPullSupplier | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a Channel associated with the given MemberID exists within the
- target Domain, this operation connects the given PullConsumer
- to it. Otherwise, the <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c>
- exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_push_supplier_with_id(EventDomain, Supplier, MemberID) -> Reply</name>
- <fsummary>Connect the PushSupplier to the Channel with the given MemberID</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Supplier = CosEventComm::PushSupplier</v>
- <v>MemberID = long()</v>
- <v>Reply = CosNotifyChannelAdmin::ProxyPushConsumer | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a Channel associated with the given MemberID exists within the
- target Domain, this operation connects the given PushSupplier
- to it. Otherwise, the <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c>
- exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_pull_supplier_with_id(EventDomain, Supplier, MemberID) -> Reply</name>
- <fsummary>Connect the PullSupplier to the Channel with the given MemberID</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Supplier = CosEventComm::PullSupplier</v>
- <v>MemberID = long()</v>
- <v>Reply = CosNotifyChannelAdmin::ProxyPushConsumer | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a Channel associated with the given MemberID exists within the
- target Domain, this operation connects the given PullSupplier
- to it. Otherwise, the <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c>
- exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_structured_push_consumer_with_id(EventDomain, Consumer, MemberID) -> Reply</name>
- <fsummary>Connect the StructuredPushConsumer to the Channel with the given MemberID</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Consumer = CosNotifyComm::StructuredPushConsumer</v>
- <v>MemberID = long()</v>
- <v>Reply = CosNotifyChannelAdmin::StructuredProxyPushSupplier | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a Channel associated with the given MemberID exists within the
- target Domain, this operation connects the given StructuredPushConsumer
- to it. Otherwise, the <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c>
- exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_structured_pull_consumer_with_id(EventDomain, Consumer, MemberID) -> Reply</name>
- <fsummary>Connect the StructuredPullConsumer to the Channel with the given MemberID</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Consumer = CosNotifyComm::StructuredPullConsumer</v>
- <v>MemberID = long()</v>
- <v>Reply = CosNotifyChannelAdmin::StructuredProxyPullSupplier | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a Channel associated with the given MemberID exists within the
- target Domain, this operation connects the given StructuredPullConsumer
- to it. Otherwise, the <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c>
- exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_structured_push_supplier_with_id(EventDomain, Supplier, MemberID) -> Reply</name>
- <fsummary>Connect the StructuredPushSupplier to the Channel with the given MemberID</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Supplier = CosNotifyComm::StructuredPushSupplier</v>
- <v>MemberID = long()</v>
- <v>Reply = CosNotifyChannelAdmin::StructuredProxyPushConsumer | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a Channel associated with the given MemberID exists within the
- target Domain, this operation connects the given StructuredPushSupplier
- to it. Otherwise, the <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c>
- exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_structured_pull_supplier_with_id(EventDomain, Supplier, MemberID) -> Reply</name>
- <fsummary>Connect the StructuredPullSupplier to the Channel with the given MemberID</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Supplier = CosNotifyComm::StructuredPullSupplier</v>
- <v>MemberID = long()</v>
- <v>Reply = CosNotifyChannelAdmin::StructuredProxyPullConsumer | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a Channel associated with the given MemberID exists within the
- target Domain, this operation connects the given StructuredPullSupplier
- to it. Otherwise, the <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c>
- exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_sequence_push_consumer_with_id(EventDomain, Consumer, MemberID) -> Reply</name>
- <fsummary>Connect the SequencePushConsumer to the Channel with the given MemberID</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Consumer = CosNotifyComm::SequencePushConsumer</v>
- <v>MemberID = long()</v>
- <v>Reply = CosNotifyChannelAdmin::SequenceProxyPushSupplier | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a Channel associated with the given MemberID exists within the
- target Domain, this operation connects the given SequencePushConsumer
- to it. Otherwise, the <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c>
- exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_sequence_pull_consumer_with_id(EventDomain, Consumer, MemberID) -> Reply</name>
- <fsummary>Connect the SequencePullConsumer to the Channel with the given MemberID</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Consumer = CosNotifyComm::SequencePullConsumer</v>
- <v>MemberID = long()</v>
- <v>Reply = CosNotifyChannelAdmin::SequenceProxyPullSupplier | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a Channel associated with the given MemberID exists within the
- target Domain, this operation connects the given SequencePullConsumer
- to it. Otherwise, the <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c>
- exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_sequence_push_supplier_with_id(EventDomain, Supplier, MemberID) -> Reply</name>
- <fsummary>Connect the SequencePushSupplier to the Channel with the given MemberID</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Supplier = CosNotifyComm::SequencePushSupplier</v>
- <v>MemberID = long()</v>
- <v>Reply = CosNotifyChannelAdmin::SequenceProxyPushConsumer | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a Channel associated with the given MemberID exists within the
- target Domain, this operation connects the given SequencePushSupplier
- to it. Otherwise, the <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c>
- exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>connect_sequence_pull_supplier_with_id(EventDomain, Supplier, MemberID) -> Reply</name>
- <fsummary>Connect the SequencePullSupplier to the Channel with the given MemberID</fsummary>
- <type>
- <v>EventDomain = #objref</v>
- <v>Supplier = CosNotifyComm::SequencePullSupplier</v>
- <v>MemberID = long()</v>
- <v>Reply = CosNotifyChannelAdmin::SequenceProxyPullConsumer | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- </type>
- <desc>
- <p>If a Channel associated with the given MemberID exists within the
- target Domain, this operation connects the given SequencePullSupplier
- to it. Otherwise, the <c><![CDATA[#'CosNotifyChannelAdmin_ChannelNotFound'{}]]></c>
- exception is raised.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosEventDomain/doc/src/CosEventDomainAdmin_EventDomainFactory.xml b/lib/cosEventDomain/doc/src/CosEventDomainAdmin_EventDomainFactory.xml
deleted file mode 100644
index 602e0e5fb0..0000000000
--- a/lib/cosEventDomain/doc/src/CosEventDomainAdmin_EventDomainFactory.xml
+++ /dev/null
@@ -1,88 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2001</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosEventDomainAdmin_EventDomainFactory</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2001-08-20</date>
- <rev>PA1</rev>
- </header>
- <module>CosEventDomainAdmin_EventDomainFactory</module>
- <modulesummary>This module implements an Event Domain Factory interface, which is used to create new Event Domain instances.</modulesummary>
- <description>
- <p>To get access to all definitions include necessary <c><![CDATA[hrl]]></c> files by using:<br></br><c><![CDATA[-include_lib("cosEventDomain/include/*.hrl").]]></c></p>
- </description>
- <funcs>
- <func>
- <name>create_event_domain(Factory, QoS, Admin) -> Reply</name>
- <fsummary>Create a new ConsumerAdmin object</fsummary>
- <type>
- <v>Factory = #objref</v>
- <v>QoS = CosNotification::QoSProperties</v>
- <v>Admin = CosNotification::AdminProperties</v>
- <v>Reply = {EventDomain, DomainID} | {'EXCEPTION', #'CosNotification_UnsupportedQoS'{}} | {'EXCEPTION', #'CosNotification_UnsupportedAdmin'{}}</v>
- <v>EventDomain = #objref</v>
- </type>
- <desc>
- <p>To create a new EventDomain this operation is used. If it is not
- possible to support the given <c><![CDATA[QoSProperties]]></c> or <c><![CDATA[AdminProperties]]></c>
- an exception is raised, which list the properties not supported. For more
- information see the <c><![CDATA[cosNotification]]></c> user's guide.</p>
- </desc>
- </func>
- <func>
- <name>get_all_domains(Factory) -> DomainIDSeq</name>
- <fsummary>Return a DomainID sequence of all domains associated with the target object</fsummary>
- <type>
- <v>Factory = #objref</v>
- <v>DomainIDSeq = [long()]</v>
- </type>
- <desc>
- <p>This function returns a DomainID sequence of all domains associated with the
- target object.</p>
- </desc>
- </func>
- <func>
- <name>get_event_domain(Factory, DomainID) -> Reply</name>
- <fsummary>Return the domain associated with the given id</fsummary>
- <type>
- <v>Factory = #objref</v>
- <v>DomainID = long()</v>
- <v>Reply = EventDomain | {'EXCEPTION', #'CosEventDomainAdmin_DomainNotFound'{}}</v>
- <v>EventDomain = #objref</v>
- </type>
- <desc>
- <p>This operation returns the EventDomain object associated with the
- given DomainID. If no such binding exists an exception is raised.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosEventDomain/doc/src/Makefile b/lib/cosEventDomain/doc/src/Makefile
deleted file mode 100644
index 0f18e43547..0000000000
--- a/lib/cosEventDomain/doc/src/Makefile
+++ /dev/null
@@ -1,144 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2001-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(COSEVENTDOMAIN_VSN)
-APPLICATION=cosEventDomain
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = \
- CosEventDomainAdmin_EventDomainFactory.xml \
- CosEventDomainAdmin_EventDomain.xml \
- CosEventDomainAdmin.xml \
- cosEventDomainApp.xml
-
-XML_PART_FILES = \
- part.xml \
- part_notes.xml
-XML_CHAPTER_FILES = \
- ch_contents.xml \
- ch_introduction.xml \
- ch_QoS.xml \
- ch_event_domain_service.xml \
- notes.xml
-
-BOOK_FILES = book.xml
-
-XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \
- $(XML_PART_FILES) $(XML_CHAPTER_FILES)
-
-TECHNICAL_DESCR_FILES =
-
-GIF_FILES = \
- book.gif \
- notes.gif \
- ref_man.gif \
- user_guide.gif
-
-
-PS_FILES =
-
-
-# ----------------------------------------------------
-
-INTERNAL_HTML_FILES = $(TECHNICAL_DESCR_FILES:%.xml=$(HTMLDIR)/%.html)
-
-HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
-
-INFO_FILE = ../../info
-EXTRA_FILES = summary.html.src \
- $(DEFAULT_GIF_FILES) \
- $(DEFAULT_HTML_FILES) \
- $(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html)
-
-MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-
-HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
-
-TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-$(HTMLDIR)/%.gif: %.gif
- $(INSTALL_DATA) $< $@
-
-docs: pdf html man
-
-$(TOP_PDF_FILE): $(XML_FILES)
-
-pdf: $(TOP_PDF_FILE)
-
-html: gifs $(HTML_REF_MAN_FILE)
-
-clean clean_docs:
- rm -rf $(HTMLDIR)/*
- rm -f $(MAN3DIR)/*
- rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
- rm -f $(JD_HTML) $(JD_PACK)
-
-man: $(MAN3_FILES)
-
-gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-
-$(INDEX_TARGET): $(INDEX_SRC)
- sed -e 's;%VSN%;$(VSN);' $(INDEX_SRC) > $(INDEX_TARGET)
-
-debug opt:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_docs_spec: docs
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(HTMLDIR)/* \
- "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
- $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
-
-release_spec:
diff --git a/lib/cosEventDomain/doc/src/book.gif b/lib/cosEventDomain/doc/src/book.gif
deleted file mode 100644
index 94b3868792..0000000000
--- a/lib/cosEventDomain/doc/src/book.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosEventDomain/doc/src/book.xml b/lib/cosEventDomain/doc/src/book.xml
deleted file mode 100644
index b073e5edc0..0000000000
--- a/lib/cosEventDomain/doc/src/book.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book xmlns:xi="http://www.w3.org/2001/XInclude">
- <header titlestyle="normal">
- <copyright>
- <year>2001</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosEventDomain</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2001-08-20</date>
- <rev>1.0</rev>
- </header>
- <insidecover>
- </insidecover>
- <pagetext>cosEventDomain</pagetext>
- <preamble>
- <contents level="2"></contents>
- </preamble>
- <parts lift="no">
- <xi:include href="part.xml"/>
- </parts>
- <applications>
- <xi:include href="ref_man.xml"/>
- </applications>
- <releasenotes>
- <xi:include href="notes.xml"/>
- </releasenotes>
- <listofterms></listofterms>
- <index></index>
-</book>
-
diff --git a/lib/cosEventDomain/doc/src/ch_QoS.xml b/lib/cosEventDomain/doc/src/ch_QoS.xml
deleted file mode 100644
index c356e38752..0000000000
--- a/lib/cosEventDomain/doc/src/ch_QoS.xml
+++ /dev/null
@@ -1,118 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2002</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Quality Of Service and Admin Properties</title>
- <prepared></prepared>
- <docno></docno>
- <date>2000-05-29</date>
- <rev></rev>
- <file>ch_QoS.xml</file>
- </header>
-
- <section>
- <title>Quality Of Service and Admin Properties</title>
- <p>This chapter explains the allowed properties it is possible to set for this
- application. </p>
-
- <section>
- <title>Quality Of Service</title>
- <p>The cosEventDomain application supports the following QoS settings:</p>
- <table>
- <row>
- <cell align="center" valign="middle"><em>QoS</em></cell>
- <cell align="center" valign="middle"><em>Range</em></cell>
- <cell align="center" valign="middle"><em>Default</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">CycleDetection</cell>
- <cell align="left" valign="middle">AuthorizeCycles/ForbidCycles</cell>
- <cell align="left" valign="middle">ForbidCycles</cell>
- </row>
- <row>
- <cell align="left" valign="middle">DiamondDetection</cell>
- <cell align="left" valign="middle">AuthorizeDiamonds/ForbidDiamonds</cell>
- <cell align="left" valign="middle">ForbidDiamonds</cell>
- </row>
- <tcaption>Supported QoS settings</tcaption>
- </table>
-<br></br><br></br><br></br><br></br> <p><em>Comments on the table 'Supported QoS Settings':</em></p>
- <taglist>
- <tag><em>CycleDetection</em></tag>
- <item>If a cycle is created, the user <em>must</em> be aware of the fact
- that unless they set timeout on events, events that are not filtered
- will loop endlessly through the topology.</item>
- <tag><em>DiamondDetection</em></tag>
- <item>A Diamond in this context, means that the same
- event may reach a point in the graph by more than one route
- (i.e. transitive). Hence, it is possible that multiple copies
- are delivered.</item>
- </taglist>
- </section>
-
- <section>
- <title>Setting Quality Of Service</title>
- <p>Assume we have a Consumer Admin object which we want to change
- the current Quality of Service. Typical usage:</p>
- <code type="none"><![CDATA[
-QoS =
- [#'CosNotification_Property'
- {name='CosEventDomainAdmin':'DiamondDetection'(),
- value=any:create(orber_tc:short(),
- 'CosEventDomainAdmin':'AuthorizeDiamonds'())},
- #'CosNotification_Property'
- {name='CosEventDomainAdmin':'CycleDetection'(),
- value=any:create(orber_tc:short(),
- 'CosEventDomainAdmin':'ForbidCycles'())}],
-'CosEventDomainAdmin_EventDomain':set_qos(ED, QoS),
- ]]></code>
- <p>If it is not possible to set the requested QoS the <c><![CDATA[UnsupportedQoS]]></c>
- exception is raised, which includes a sequence of <c><![CDATA[PropertyError]]></c>'s
- describing which QoS, possible range and why is not allowed. The error
- codes are:</p>
- <list type="bulleted">
- <item>UNSUPPORTED_PROPERTY - QoS not supported for this type of target object.</item>
- <item>UNAVAILABLE_PROPERTY - due to current QoS settings the given property
- is not allowed.</item>
- <item>UNSUPPORTED_VALUE - property value out of range; valid range is returned.</item>
- <item>UNAVAILABLE_VALUE - due to current QoS settings the given value is
- not allowed; valid range is returned.</item>
- <item>BAD_PROPERTY - unrecognized property.</item>
- <item>BAD_TYPE - type of supplied property is incorrect.</item>
- <item>BAD_VALUE - illegal value.</item>
- </list>
- <p>The CosEventDomainAdmin_EventDomain interface also supports an operation
- called <c><![CDATA[validate_qos/2]]></c>. The purpose of this operations is to check
- if a QoS setting is supported by the target object and if so, the operation
- returns additional properties which could be optionally added as well.</p>
- </section>
-
- <section>
- <title>Admin Properties</title>
- <p>The OMG specification do not contain any definitions of Admin Properties.
- Hence, the cosEventDomain application currently does not support any Admin
- Properties.</p>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosEventDomain/doc/src/ch_contents.xml b/lib/cosEventDomain/doc/src/ch_contents.xml
deleted file mode 100644
index b8fefecf44..0000000000
--- a/lib/cosEventDomain/doc/src/ch_contents.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2001</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>The cosEventDomain Application</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2001-08-20</date>
- <rev>B</rev>
- <file>ch_contents.xml</file>
- </header>
-
- <section>
- <title>Content Overview</title>
- <p>The cosEventDomain documentation is divided into three sections:
- </p>
- <list type="bulleted">
- <item>
- <p>PART ONE - The User's Guide
- <br></br>Description of the cosEventDomain Application including
- services and a small tutorial demonstrating
- the development of a simple service.</p>
- </item>
- <item>
- <p>PART TWO - Release Notes
- <br></br>A concise history of cosEventDomain.</p>
- </item>
- <item>
- <p>PART THREE - The Reference Manual
- <br></br> A quick reference guide, including a
- brief description, to all the functions available in cosEventDomain.</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Brief Description of the User's Guide</title>
- <p>The User's Guide contains the following parts:</p>
- <list type="bulleted">
- <item>
- <p>CosEventDomain overview</p>
- </item>
- <item>
- <p>CosEventDomain installation and examples</p>
- </item>
- </list>
- </section>
-</chapter>
-
diff --git a/lib/cosEventDomain/doc/src/ch_event_domain_service.xml b/lib/cosEventDomain/doc/src/ch_event_domain_service.xml
deleted file mode 100644
index a0ecf20415..0000000000
--- a/lib/cosEventDomain/doc/src/ch_event_domain_service.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2001</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Event Domain Service</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2001-08-20</date>
- <rev>A</rev>
- <file>ch_event_domain_service.xml</file>
- </header>
-
- <section>
- <title>Overview of the CosEventDomain Service</title>
- <p>The Event Domain service allows programmers to manage a cluster
- of information channels.</p>
-
- <section>
- <title>Event Domain Service Components</title>
- <p>There are two components in the OMG CosEventDomainAdmin service architecture:</p>
- <list type="bulleted">
- <item><em>EventDomainFactory:</em> a factory for creating EventDomains.</item>
- <item><em>EventDomain:</em> supplies a tool, which makes it easy to create
- topologies of interconnected channels (i.e. a directed graph).</item>
- </list>
- </section>
-
- <section>
- <title>A Tutorial on How to Create a Simple Service</title>
- <p>To be able to use the cosEventDomain application, the cosNotification
- and, possibly, the cosTime application must be installed.</p>
- </section>
-
- <section>
- <title>How to Run Everything</title>
- <p>Below is a short transcript on how to run cosEventDomain. </p>
- <code type="none"><![CDATA[
-
-%% Start Mnesia and Orber
-mnesia:delete_schema([node()]),
-mnesia:create_schema([node()]),
-orber:install([node()]),
-mnesia:start(),
-orber:start(),
-
-%% Install and start cosNotification.
-cosNotificationApp:install(),
-cosNotificationApp:start(),
-
-%% Install and start cosEventDomain.
-cosEventDomainApp:install(),
-cosEventDomainApp:start(),
-
-%% Start a CosEventDomainAdmin factory.
-AdminFac = cosEventDomainApp:start_factory(),
-
-%% Define the desired QoS settings:
-QoS =
- [#'CosNotification_Property'
- {name='CosEventDomainAdmin':'DiamondDetection'(),
- value=any:create(orber_tc:short(),
- 'CosEventDomainAdmin':'AuthorizeDiamonds'())},
- #'CosNotification_Property'
- {name='CosEventDomainAdmin':'CycleDetection'(),
- value=any:create(orber_tc:short(),
- 'CosEventDomainAdmin':'ForbidCycles'())}],
-
-%% Create a new EventDomain:
-{ED, EDId} = 'CosEventDomainAdmin_EventDomainFactory':
- create_event_domain(Fac, QoS, []),
-
-%% Now we can add Notification Channels to the Domain. How this
-%% is done, see the cosNotification documentation. Let us assume
-%% that we have gained access to two Channel Objects; add them to the
-%% domain:
-ID1 = 'CosEventDomainAdmin_EventDomain':add_channel(ED, Ch1),
-ID2 = 'CosEventDomainAdmin_EventDomain':add_channel(ED, Ch2),
-
-%% To connect them, we must first define a connection struct:
-C1 = #'CosEventDomainAdmin_Connection'{supplier_id=ID1,
- consumer_id=ID2,
- ctype='STRUCTURED_EVENT',
- notification_style='Pull'},
-
-%% Connect them:
-'CosEventDomainAdmin_EventDomain':add_connection(ED, C1),
- ]]></code>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosEventDomain/doc/src/ch_introduction.xml b/lib/cosEventDomain/doc/src/ch_introduction.xml
deleted file mode 100644
index f7a3426673..0000000000
--- a/lib/cosEventDomain/doc/src/ch_introduction.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2001</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Introduction to cosEventDomain</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2001-08-20</date>
- <rev></rev>
- <file>ch_introduction.xml</file>
- </header>
-
- <section>
- <title>Overview</title>
- <p>The cosEventDomain application is a Event Domain Service compliant with the <url href="http://www.omg.org">OMG</url>
- Service CosEventDomainAdmin.
- </p>
-
- <section>
- <title>Purpose and Dependencies</title>
- <p>CosEventDomain is dependent on <em>Orber</em>, which provides CORBA functionality in an Erlang environment.</p>
- </section>
-
- <section>
- <title>Prerequisites</title>
- <p>To fully understand the concepts presented in the
- documentation, it is recommended that the user is familiar
- with distributed programming and CORBA.
- </p>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosEventDomain/doc/src/cosEventDomainApp.xml b/lib/cosEventDomain/doc/src/cosEventDomainApp.xml
deleted file mode 100644
index c75ee05512..0000000000
--- a/lib/cosEventDomain/doc/src/cosEventDomainApp.xml
+++ /dev/null
@@ -1,150 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2001</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>cosEventDomainApp</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2001-08-20</date>
- <rev>PA1</rev>
- </header>
- <module>cosEventDomainApp</module>
- <modulesummary>The main module of the cosEventDomain application.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use:<br></br><c><![CDATA[-include_lib("cosEventDomain/include/*.hrl").]]></c></p>
- <p>This module contains the functions for starting and stopping the application.</p>
- </description>
- <funcs>
- <func>
- <name>install() -> Return</name>
- <fsummary>Install the cosEventDomain application</fsummary>
- <type>
- <v>Return = ok | {'EXCEPTION', E} | {'EXIT', R}</v>
- </type>
- <desc>
- <p>This operation installs the cosEventDomain application.</p>
- </desc>
- </func>
- <func>
- <name>uninstall() -> Return</name>
- <fsummary>Uninstall the cosEventDomain application</fsummary>
- <type>
- <v>Return = ok | {'EXCEPTION', E} | {'EXIT', R}</v>
- </type>
- <desc>
- <p>This operation uninstalls the cosEventDomain application.</p>
- </desc>
- </func>
- <func>
- <name>start() -> Return</name>
- <fsummary>Start the cosEventDomain application</fsummary>
- <type>
- <v>Return = ok | {error, Reason}</v>
- </type>
- <desc>
- <p>This operation starts the cosEventDomain application.</p>
- </desc>
- </func>
- <func>
- <name>stop() -> Return</name>
- <fsummary>Stop the cosEventDomain application</fsummary>
- <type>
- <v>Return = ok | {error, Reason}</v>
- </type>
- <desc>
- <p>This operation stops the cosEventDomain application.</p>
- </desc>
- </func>
- <func>
- <name>start_factory() -> Factory</name>
- <fsummary>Start a factory with default settings</fsummary>
- <type>
- <v>Factory = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new instance of a
- <seealso marker="CosEventDomainAdmin_EventDomainFactory">Event Domain Factory</seealso>
- using the default settings.</p>
- </desc>
- </func>
- <func>
- <name>start_factory(Options) -> Factory</name>
- <fsummary>Start a factory with settings defined by the given options</fsummary>
- <type>
- <v>Options = [Option]</v>
- <v>Option = currently no options defined.</v>
- <v>Factory = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new instance of a
- <seealso marker="CosEventDomainAdmin_EventDomainFactory">Event Domain Factory</seealso></p>
- </desc>
- </func>
- <func>
- <name>start_factory_link() -> Factory</name>
- <fsummary>Start a factory, which is linked to the invoking process, with default settings</fsummary>
- <type>
- <v>Factory = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new instance of a
- <seealso marker="CosEventDomainAdmin_EventDomainFactory">Event Domain Factory</seealso>,
- which is linked to the invoking process, using the default settings.</p>
- </desc>
- </func>
- <func>
- <name>start_factory_link(Options) -> Factory</name>
- <fsummary>Start a factory, which is linked to the invoking process, with settings defined by the given options</fsummary>
- <type>
- <v>Options = [Option]</v>
- <v>Option = currently no options defined.</v>
- <v>Factory = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new instance of a
- <seealso marker="CosEventDomainAdmin_EventDomainFactory">Event Domain Factory</seealso>,
- which is linked to the invoking process, with settings defined by the
- given options. Allowed options are the same as for
- <c><![CDATA[cosEventDomainApp:start_factory/1]]></c>.</p>
- </desc>
- </func>
- <func>
- <name>stop_factory(Factory) -> Reply</name>
- <fsummary>Terminate the target object</fsummary>
- <type>
- <v>Factory = #objref</v>
- <v>Reply = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This operation stop the target factory.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosEventDomain/doc/src/fascicules.xml b/lib/cosEventDomain/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/cosEventDomain/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/cosEventDomain/doc/src/notes.gif b/lib/cosEventDomain/doc/src/notes.gif
deleted file mode 100644
index e000cca26a..0000000000
--- a/lib/cosEventDomain/doc/src/notes.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosEventDomain/doc/src/notes.xml b/lib/cosEventDomain/doc/src/notes.xml
deleted file mode 100644
index 5e5bb2c33e..0000000000
--- a/lib/cosEventDomain/doc/src/notes.xml
+++ /dev/null
@@ -1,316 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2001</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosEventDomain Release Notes</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2001-08-20</date>
- <rev>A</rev>
- <file>notes.xml</file>
- </header>
-
- <section><title>cosEventDomain 1.2.1</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Internal changes</p>
- <p>
- Own Id: OTP-13551</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosEventDomain 1.2</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> Remove the usage of erlang:now() from all Corba
- applications and use the new rand module instead of
- random. </p>
- <p>
- Own Id: OTP-12687</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosEventDomain 1.1.14</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> The default encoding of Erlang files has been changed
- from ISO-8859-1 to UTF-8. </p> <p> The encoding of XML
- files has also been changed to UTF-8. </p>
- <p>
- Own Id: OTP-10907</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosEventDomain 1.1.13</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Misc build updates</p>
- <p>
- Own Id: OTP-10784</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosEventDomain 1.1.12</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>Erlang/OTP can now be built using parallel make if you
- limit the number of jobs, for instance using '<c>make
- -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
- work at the moment because of some missing
- dependencies.</p>
- <p>
- Own Id: OTP-9451</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section>
- <title>cosEventDomain 1.1.11</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Removed superfluous usage of shy in the documentation since it can cause problem if
- a buggy tool is used.</p>
- <p>
- Own Id: OTP-9319 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEventDomain 1.1.10</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Eliminated Dialyzer warnings when using exit or throw.</p>
- <p>
- Own Id: OTP-9050 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEventDomain 1.1.9</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Test suites published.</p>
- <p>
- Own Id: OTP-8543 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEventDomain 1.1.8</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>Removed superfluous VT in the documentation.</p>
- <p>Own id: OTP-8353 Aux Id:</p>
- </item>
- <item>
- <p>The documentation EIX file was not generated.</p>
- <p>Own id: OTP-8355 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEventDomain 1.1.7</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- The documentation is now built with open source tools (xsltproc and fop)
- that exists on most platforms. One visible change is that the frames are removed.</p>
- <p>
- Own Id: OTP-8201 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEventDomain 1.1.6</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Obsolete guards, e.g. record vs is_record, has been changed
- to avoid compiler warnings.</p>
- <p>Own id: OTP-7987</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEventDomain 1.1.5</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Updated file headers.</p>
- <p>Own id: OTP-7837</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEventDomain 1.1.4</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Documentation source included in open source releases.</p>
- <p>Own id: OTP-7595</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEventDomain 1.1.3</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Updated file headers.</p>
- <p>Own id: OTP-7011</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEventDomain 1.1.2</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The documentation source has been converted from SGML to XML.</p>
- <p>Own id: OTP-6754</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEventDomain 1.1.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Minor Makefile changes.</p>
- <p>Own id: OTP-6701</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEventDomain 1.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The stub/skeleton-files generated by IC have been improved,
- i.e., depending on the IDL-files, reduced the size of the
- erl- and beam-files and decreased dependencies off Orber's
- Interface Repository. It is necessary to re-compile all IDL-files
- and use COS-applications, including Orber, compiled with
- IC-4.2.</p>
- <p>Own id: OTP-4576</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosEventDomain 1.0</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>First release of the cosEventDomain application.</p>
- </item>
- </list>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosEventDomain/doc/src/part.xml b/lib/cosEventDomain/doc/src/part.xml
deleted file mode 100644
index 328fdfc20f..0000000000
--- a/lib/cosEventDomain/doc/src/part.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2001</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosEventDomain User's Guide</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2001-08-20</date>
- <rev>1.0</rev>
- </header>
- <description>
- <p>The <em>cosEventDomain</em> application is an Erlang implementation of a
- CORBA Service CosEventDomainAdmin.</p>
- </description>
- <xi:include href="ch_contents.xml"/>
- <xi:include href="ch_introduction.xml"/>
- <xi:include href="ch_QoS.xml"/>
- <xi:include href="ch_event_domain_service.xml"/>
-</part>
-
diff --git a/lib/cosEventDomain/doc/src/part_notes.xml b/lib/cosEventDomain/doc/src/part_notes.xml
deleted file mode 100644
index af6864decf..0000000000
--- a/lib/cosEventDomain/doc/src/part_notes.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2001</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosEventDomain Release Notes</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2001-08-20</date>
- <rev>1.0</rev>
- </header>
- <description>
- <p>The cosEventDomain Application is an Erlang implementation of a CORBA Service
- CosEventDomainAdmin.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/cosEventDomain/doc/src/ref_man.gif b/lib/cosEventDomain/doc/src/ref_man.gif
deleted file mode 100644
index b13c4efd53..0000000000
--- a/lib/cosEventDomain/doc/src/ref_man.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosEventDomain/doc/src/ref_man.xml b/lib/cosEventDomain/doc/src/ref_man.xml
deleted file mode 100644
index 14b826e4f9..0000000000
--- a/lib/cosEventDomain/doc/src/ref_man.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE application SYSTEM "application.dtd">
-
-<application xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2001</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosEventDomain Reference Manual</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2001-08-20</date>
- <rev>1.0</rev>
- </header>
- <description>
- <p>The <em>cosEventDomain</em> application is an Erlang implementation of
- a CORBA Service CosEventDomainAdmin.</p>
- </description>
- <xi:include href="cosEventDomainApp.xml"/>
- <xi:include href="CosEventDomainAdmin.xml"/>
- <xi:include href="CosEventDomainAdmin_EventDomainFactory.xml"/>
- <xi:include href="CosEventDomainAdmin_EventDomain.xml"/>
-</application>
-
diff --git a/lib/cosEventDomain/doc/src/summary.html.src b/lib/cosEventDomain/doc/src/summary.html.src
deleted file mode 100644
index 922c956633..0000000000
--- a/lib/cosEventDomain/doc/src/summary.html.src
+++ /dev/null
@@ -1 +0,0 @@
-Orber OMG Event Domain Service \ No newline at end of file
diff --git a/lib/cosEventDomain/doc/src/user_guide.gif b/lib/cosEventDomain/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/cosEventDomain/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosEventDomain/ebin/.gitignore b/lib/cosEventDomain/ebin/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosEventDomain/ebin/.gitignore
+++ /dev/null
diff --git a/lib/cosEventDomain/example/.gitignore b/lib/cosEventDomain/example/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosEventDomain/example/.gitignore
+++ /dev/null
diff --git a/lib/cosEventDomain/include/.gitignore b/lib/cosEventDomain/include/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosEventDomain/include/.gitignore
+++ /dev/null
diff --git a/lib/cosEventDomain/info b/lib/cosEventDomain/info
deleted file mode 100644
index 46ecf9504d..0000000000
--- a/lib/cosEventDomain/info
+++ /dev/null
@@ -1,2 +0,0 @@
-group: orb
-short: Orber OMG Event Domain Service
diff --git a/lib/cosEventDomain/src/CosEventDomainAdmin.cfg b/lib/cosEventDomain/src/CosEventDomainAdmin.cfg
deleted file mode 100644
index 75a2720088..0000000000
--- a/lib/cosEventDomain/src/CosEventDomainAdmin.cfg
+++ /dev/null
@@ -1,4 +0,0 @@
-{this, "CosEventDomainAdmin::EventDomain"}.
-{{handle_info, "CosEventDomainAdmin::EventDomain"}, true}.
-{this, "CosEventDomainAdmin::EventDomainFactory"}.
-{{handle_info, "CosEventDomainAdmin::EventDomainFactory"}, true}.
diff --git a/lib/cosEventDomain/src/CosEventDomainAdmin.idl b/lib/cosEventDomain/src/CosEventDomainAdmin.idl
deleted file mode 100644
index 2ecd935c67..0000000000
--- a/lib/cosEventDomain/src/CosEventDomainAdmin.idl
+++ /dev/null
@@ -1,280 +0,0 @@
-#ifndef _COS_EVENT_DOMAIN_ADMIN_IDL_
-#define _COS_EVENT_DOMAIN_ADMIN_IDL_
-
-#pragma prefix "omg.org"
-
-// Event Domain Interface
-#include "CosNotification.idl"
-#include "CosEventComm.idl"
-#include "CosNotifyComm.idl"
-#include "CosNotifyChannelAdmin.idl"
-
-
-module CosEventDomainAdmin {
-
- // The following constant declarations define the Event Domain
- // QoS property names and the associated values each property can
- // take on. The name/value pairs for each Event Domain property
- // are grouped, beginning with a string constant defined for the
- // property name, followed by the values the property can take on.
-
- const string CycleDetection = "CycleDetection";
- const short AuthorizeCycles = 0; // Default value
- const short ForbidCycles = 1;
-
- const string DiamondDetection = "DiamondDetection";
- const short AuthorizeDiamonds = 0; // Default value
- const short ForbidDiamonds = 1;
-
-
- // The following enum declaration defines the types that a channel
- // can be of. It is used to specify channel types while externalizing
- // and instantiating topologies.
- enum ChannelType
- {
- CHANNEL,
- TYPED_CHANNEL,
- LOG_CHANNEL,
- TYPED_LOG_CHANNEL
- };
-
- enum NotificationStyle {
- Push,
- Pull
- };
-
- typedef long MemberID;
- typedef sequence <MemberID> MemberIDSeq;
- typedef long ConnectionID;
- typedef sequence <ConnectionID> ConnectionIDSeq;
-
- struct Connection {
- MemberID supplier_id;
- MemberID consumer_id;
- CosNotifyChannelAdmin::ClientType ctype;
- NotificationStyle notification_style;
- };
-
-
- typedef MemberIDSeq Route;
- typedef sequence<Route> RouteSeq;
-
- typedef Route Cycle;
- typedef sequence<Cycle> CycleSeq;
-
- typedef RouteSeq Diamond;
- typedef sequence<Diamond> DiamondSeq;
-
- exception CycleCreationForbidden
- {
- Cycle cyc;
- };
-
- exception DiamondCreationForbidden
- {
- Diamond diam;
- };
-
- // Forward declarations
- interface ConsumerAdmin;
- interface SupplierAdmin;
-
-
- typedef long DomainID;
- typedef sequence <DomainID> DomainIDSeq;
- typedef long ItemID;
-
-
- // EventDomain administrates EventChannels that reside in the same
- // administrative domain
- exception ConnectionNotFound {};
- exception AlreadyExists {};
-
-
- interface EventDomain :
- CosNotification::QoSAdmin ,
- CosNotification::AdminPropertiesAdmin {
-
- MemberID add_channel ( in CosNotifyChannelAdmin::EventChannel channel );
-
- MemberIDSeq get_all_channels ();
-
- CosNotifyChannelAdmin::EventChannel get_channel ( in MemberID channel )
- raises ( CosNotifyChannelAdmin::ChannelNotFound );
-
- void remove_channel ( in MemberID channel)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- ConnectionID add_connection ( in Connection connection)
- raises (CosNotifyChannelAdmin::ChannelNotFound,
- CosEventChannelAdmin::TypeError,
- AlreadyExists,
- CycleCreationForbidden,
- DiamondCreationForbidden);
-
- ConnectionIDSeq get_all_connections ();
-
- Connection get_connection ( in ConnectionID connection )
- raises ( ConnectionNotFound );
-
- void remove_connection ( in ConnectionID connection )
- raises ( ConnectionNotFound );
-
- CosNotifyChannelAdmin::ChannelIDSeq get_offer_channels ( in MemberID channel )
- raises ( CosNotifyChannelAdmin::ChannelNotFound );
-
- CosNotifyChannelAdmin::ChannelIDSeq get_subscription_channels ( in MemberID channel )
- raises ( CosNotifyChannelAdmin::ChannelNotFound );
-
- void destroy();
-
- // Cycle and diamond configurations listing
- CycleSeq get_cycles();
-
- DiamondSeq get_diamonds();
-
-
- // Connection of clients to the domain
- // - using no specific information
- // - for any clients
- void set_default_consumer_channel(in MemberID channel)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- void set_default_supplier_channel(in MemberID channel)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::ProxyPushSupplier
- connect_push_consumer(in CosEventComm::PushConsumer client)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::ProxyPullSupplier
- connect_pull_consumer(in CosEventComm::PullConsumer client)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::ProxyPushConsumer
- connect_push_supplier(in CosEventComm::PushSupplier client)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::ProxyPullConsumer
- connect_pull_supplier(in CosEventComm::PullSupplier client)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- // - for structured clients
- CosNotifyChannelAdmin::StructuredProxyPushSupplier
- connect_structured_push_consumer(in CosNotifyComm::StructuredPushConsumer client)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::StructuredProxyPullSupplier
- connect_structured_pull_consumer(in CosNotifyComm::StructuredPullConsumer client)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::StructuredProxyPushConsumer
- connect_structured_push_supplier(in CosNotifyComm::StructuredPushSupplier client)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::StructuredProxyPullConsumer
- connect_structured_pull_supplier(in CosNotifyComm::StructuredPullSupplier client)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- // - for sequence clients
- CosNotifyChannelAdmin::SequenceProxyPushSupplier
- connect_sequence_push_consumer(in CosNotifyComm::SequencePushConsumer client)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::SequenceProxyPullSupplier
- connect_sequence_pull_consumer(in CosNotifyComm::SequencePullConsumer client)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::SequenceProxyPushConsumer
- connect_sequence_push_supplier(in CosNotifyComm::SequencePushSupplier client)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::SequenceProxyPullConsumer
- connect_sequence_pull_supplier(in CosNotifyComm::SequencePullSupplier client)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- // - using a channel id
- // - for any clients
- CosNotifyChannelAdmin::ProxyPushSupplier
- connect_push_consumer_with_id(in CosEventComm::PushConsumer client,
- in MemberID channel)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::ProxyPullSupplier
- connect_pull_consumer_with_id(in CosEventComm::PullConsumer client,
- in MemberID channel)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::ProxyPushConsumer
- connect_push_supplier_with_id(in CosEventComm::PushSupplier client,
- in MemberID channel)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::ProxyPullConsumer
- connect_pull_supplier_with_id(in CosEventComm::PullSupplier client,
- in MemberID channel)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- // - for structured clients
- CosNotifyChannelAdmin::StructuredProxyPushSupplier
- connect_structured_push_consumer_with_id(in CosNotifyComm::StructuredPushConsumer client,
- in MemberID channel)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::StructuredProxyPullSupplier
- connect_structured_pull_consumer_with_id(in CosNotifyComm::StructuredPullConsumer client,
- in MemberID channel)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::StructuredProxyPushConsumer
- connect_structured_push_supplier_with_id(in CosNotifyComm::StructuredPushSupplier client,
- in MemberID channel)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::StructuredProxyPullConsumer
- connect_structured_pull_supplier_with_id(in CosNotifyComm::StructuredPullSupplier client,
- in MemberID channel)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- // - for sequence clients
- CosNotifyChannelAdmin::SequenceProxyPushSupplier
- connect_sequence_push_consumer_with_id(in CosNotifyComm::SequencePushConsumer client,
- in MemberID channel)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::SequenceProxyPullSupplier
- connect_sequence_pull_consumer_with_id(in CosNotifyComm::SequencePullConsumer client,
- in MemberID channel)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::SequenceProxyPushConsumer
- connect_sequence_push_supplier_with_id(in CosNotifyComm::SequencePushSupplier client,
- in MemberID channel)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
-
- CosNotifyChannelAdmin::SequenceProxyPullConsumer
- connect_sequence_pull_supplier_with_id(in CosNotifyComm::SequencePullSupplier client,
- in MemberID channel)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
- };
-
- exception DomainNotFound {};
-
- interface EventDomainFactory {
-
- EventDomain create_event_domain( in CosNotification::QoSProperties initialQoS ,
- in CosNotification::AdminProperties initialAdmin,
- out DomainID id )
- raises ( CosNotification::UnsupportedQoS,
- CosNotification::UnsupportedAdmin );
-
- DomainIDSeq get_all_domains ();
-
- EventDomain get_event_domain (
- in DomainID id )
- raises ( DomainNotFound );
- };
-};
-
-#endif // _COS_EVENT_DOMAIN_ADMIN_IDL_
-
diff --git a/lib/cosEventDomain/src/CosEventDomainAdmin_EventDomainFactory_impl.erl b/lib/cosEventDomain/src/CosEventDomainAdmin_EventDomainFactory_impl.erl
deleted file mode 100644
index 75ff81196c..0000000000
--- a/lib/cosEventDomain/src/CosEventDomainAdmin_EventDomainFactory_impl.erl
+++ /dev/null
@@ -1,183 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosEventDomainAdmin_EventDomainFactory_impl.erl
-%% Description :
-%%
-%%----------------------------------------------------------------------
--module('CosEventDomainAdmin_EventDomainFactory_impl').
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
--include_lib("cosNotification/include/CosNotification.hrl").
-
--include("CosEventDomainAdmin.hrl").
--include("cosEventDomainApp.hrl").
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
--export([init/1,
- terminate/2,
- code_change/3,
- handle_info/2]).
-
--export([create_event_domain/4,
- get_all_domains/2,
- get_event_domain/3]).
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
--export([]).
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {current_id = -1, domains = []}).
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%----------------------------------------------------------------------
-init([]) ->
- process_flag(trap_exit, true),
- {ok, #state{}}.
-
-%%----------------------------------------------------------------------
-%% Function : terminate/2
-%% Returns : any (ignored by gen_server)
-%% Description: Shutdown the server
-%%----------------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-%%----------------------------------------------------------------------
-%% Function : code_change/3
-%% Returns : {ok, NewState}
-%% Description: Convert process state when code is changed
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%----------------------------------------------------------------------
-%% Function : handle_info/2
-%% Returns : {noreply, State} |
-%% {stop, Reason, State}
-%% Description: Handle, for example, exit signals.
-%%----------------------------------------------------------------------
-handle_info({'EXIT', Pid, _Reason}, State) ->
- {noreply, State#state{domains=delete_domain(State#state.domains, Pid, [])}};
-handle_info(_Info, State) ->
- {noreply, State}.
-
-
-%%----------------------------------------------------------------------
-%% Function : create_event_domain
-%% Arguments : InitialQoS - CosNotification::QoSProperties
-%% InitialAdmin - CosNotification::AdminProperties
-%% Returns : CosEventDomainAdmin::EventDomain |
-%% {'EXCEPTION', #'CosNotification_UnsupportedQoS'{}} |
-%% {'EXCEPTION', #'CosNotification_UnsupportedAdmin'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-create_event_domain(_OE_This, State, InitialQoS, InitialAdmin) ->
- Id = cosEventDomainApp:create_id(State#state.current_id),
- Admin = cosEventDomainApp:get_admin(InitialAdmin),
- QoS = cosEventDomainApp:get_qos(InitialQoS),
- case catch 'CosEventDomainAdmin_EventDomain':oe_create_link([self(), Id,
- QoS, Admin],
- [{sup_child, true}]) of
- {ok, Pid, ED} ->
- {reply, {ED, Id}, State#state{current_id = Id,
- domains = [{Id, ED, Pid}|State#state.domains]}};
- What ->
- orber:dbg("[~p] CosEventDomainAdmin_EventDomainFactory:"
- "create_event_domain();~n"
- "Failed creatin a new EventDomain due to: ~p",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : get_all_domains
-%% Arguments : -
-%% Returns : CosEventDomainAdmin::DomainIDSeq - [long()]
-%% Description:
-%%----------------------------------------------------------------------
-get_all_domains(_OE_This, State) ->
- {reply, get_all_domains_helper(State#state.domains, []), State}.
-
-get_all_domains_helper([], Acc) ->
- Acc;
-get_all_domains_helper([{Id, _, _}|T], Acc) ->
- get_all_domains_helper(T, [Id|Acc]).
-
-
-%%----------------------------------------------------------------------
-%% Function : get_event_domain
-%% Arguments : CosEventDomainAdmin::DomainID - long()
-%% Returns : CosEventDomainAdmin::EventDomain |
-%% {'EXCEPTION', #'CosEventDomainAdmin_DomainNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-get_event_domain(_OE_This, State, DomainID) ->
- {reply, get_event_domain_helper(State#state.domains, DomainID), State}.
-
-get_event_domain_helper([], _) ->
- corba:raise(#'CosEventDomainAdmin_DomainNotFound'{});
-get_event_domain_helper([{Id, ED, _}|_], Id) ->
- ED;
-get_event_domain_helper([_|T], Id) ->
- get_event_domain_helper(T, Id).
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-delete_domain([], _, Acc) ->
- %% The domain didn't exist.
- Acc;
-delete_domain([{_Id, _, Pid}], Pid, Acc) ->
- Acc;
-delete_domain([{_Id, _, Pid}|T], Pid, Acc) ->
- T++Acc;
-delete_domain([H|T], Pid, Acc) ->
- delete_domain(T, Pid, [H|Acc]).
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
-
diff --git a/lib/cosEventDomain/src/CosEventDomainAdmin_EventDomain_impl.erl b/lib/cosEventDomain/src/CosEventDomainAdmin_EventDomain_impl.erl
deleted file mode 100644
index a31a70acc2..0000000000
--- a/lib/cosEventDomain/src/CosEventDomainAdmin_EventDomain_impl.erl
+++ /dev/null
@@ -1,1426 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosEventDomainAdmin_EventDomain_impl.erl
-%% Description :
-%%
-%%----------------------------------------------------------------------
--module('CosEventDomainAdmin_EventDomain_impl').
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
--include_lib("cosNotification/include/CosNotifyChannelAdmin.hrl").
--include_lib("cosNotification/include/CosNotification.hrl").
-
--include("cosEventDomainApp.hrl").
--include("CosEventDomainAdmin.hrl").
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
--export([init/1,
- terminate/2,
- code_change/3,
- handle_info/2]).
-
-%%------------------ CosEventDomainAdmin::EventDomain ------------------
--export([add_channel/3,
- get_all_channels/2,
- get_channel/3,
- remove_channel/3,
- add_connection/3,
- get_all_connections/2,
- get_connection/3,
- remove_connection/3,
- get_offer_channels/3,
- get_subscription_channels/3,
- destroy/2,
- get_cycles/2,
- get_diamonds/2,
- set_default_consumer_channel/3,
- set_default_supplier_channel/3,
- connect_push_consumer/3,
- connect_pull_consumer/3,
- connect_push_supplier/3,
- connect_pull_supplier/3,
- connect_structured_push_consumer/3,
- connect_structured_pull_consumer/3,
- connect_structured_push_supplier/3,
- connect_structured_pull_supplier/3,
- connect_sequence_push_consumer/3,
- connect_sequence_pull_consumer/3,
- connect_sequence_push_supplier/3,
- connect_sequence_pull_supplier/3,
- connect_push_consumer_with_id/4,
- connect_pull_consumer_with_id/4,
- connect_push_supplier_with_id/4,
- connect_pull_supplier_with_id/4,
- connect_structured_push_consumer_with_id/4,
- connect_structured_pull_consumer_with_id/4,
- connect_structured_push_supplier_with_id/4,
- connect_structured_pull_supplier_with_id/4,
- connect_sequence_push_consumer_with_id/4,
- connect_sequence_pull_consumer_with_id/4,
- connect_sequence_push_supplier_with_id/4,
- connect_sequence_pull_supplier_with_id/4]).
-
-%%------------------ CosNotification::QoSAdmin -------------------------
--export([get_qos/2,
- set_qos/3,
- validate_qos/3]).
-
-%%------------------ CosNotification::AdminPropertiesAdmin -------------
--export([get_admin/2,
- set_admin/3]).
-
-
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
--export([]).
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {parent_pid, id, graph, ch_counter=-1,
- co_counter=-1, def_supplier, def_consumer, diamonds, cyclic}).
-
--record(connection, {supplier, consumer, data}).
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%----------------------------------------------------------------------
-init([ParentPid, MyId, QoS, _Admin]) ->
- process_flag(trap_exit, true),
- Diamonds = case lists:keysearch(?DiamondDetection, 1, QoS) of
- false ->
- ?ForbidDiamonds;
- {value, {_, Value}} ->
- Value
- end,
- case lists:keysearch(?CycleDetection, 1, QoS) of
- {value, {_, ?AuthorizeCycles}} ->
- {ok, #state{parent_pid = ParentPid, id = MyId,
- graph = digraph:new([private]),
- diamonds = Diamonds, cyclic = ?AuthorizeCycles}};
- _ ->
- {ok, #state{parent_pid = ParentPid, id = MyId,
- graph = digraph:new([acyclic, private]),
- diamonds = Diamonds, cyclic = ?ForbidCycles}}
- end.
-
-%%----------------------------------------------------------------------
-%% Function : terminate/2
-%% Returns : any (ignored by gen_server)
-%% Description: Shutdown the server
-%%----------------------------------------------------------------------
-terminate(_Reason, #state{graph = DG} = _State) ->
- Connections = digraph:edges(DG),
- close_connections(DG, Connections),
- digraph:delete(DG),
- ok.
-
-%%----------------------------------------------------------------------
-%% Function : code_change/3
-%% Returns : {ok, NewState}
-%% Description: Convert process state when code is changed
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%----------------------------------------------------------------------
-%% Function : handle_info/2
-%% Returns : {noreply, State} |
-%% {stop, Reason, State}
-%% Description: Handle, for example, exit signals.
-%%----------------------------------------------------------------------
-handle_info({'EXIT', Pid, Reason}, #state{parent_pid = Pid} = State) ->
- {stop, Reason, State};
-handle_info(_Info, State) ->
- {noreply, State}.
-
-%%----------------------------------------------------------------------
-%%------------------ CosEventDomainAdmin::EventDomain ------------------
-%%---------------------------------------------------------------------%
-%% Function : add_channel
-%% Arguments : Channel - CosNotifyChannelAdmin::EventChannel
-%% Returns : MemberId - long()
-%% Description:
-%%----------------------------------------------------------------------
-add_channel(_OE_This, #state{ch_counter=C, graph = DG} = State, Channel) ->
- type_check(Channel, 'CosNotifyChannelAdmin_EventChannel'),
- Id = cosEventDomainApp:create_id(C),
- digraph:add_vertex(DG, Id, Channel),
- {reply, Id, State#state{ch_counter=Id}}.
-
-%%---------------------------------------------------------------------%
-%% Function : get_all_channels
-%% Arguments : -
-%% Returns : CosEventDomainAdmin::MemberIDSeq ([long()])
-%% Description:
-%%----------------------------------------------------------------------
-get_all_channels(_OE_This, #state{graph = DG} = State) ->
- {reply, digraph:vertices(DG), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : get_channel
-%% Arguments : Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : CosNotifyChannelAdmin::EventChannel |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}
-%% Description:
-%%----------------------------------------------------------------------
-get_channel(_OE_This, #state{graph = DG} = State, Id) ->
- {reply, lookup_channel(DG, Id), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : remove_channel
-%% Arguments : Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : ok |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}
-%% Description:
-%%----------------------------------------------------------------------
-remove_channel(_OE_This, #state{graph = DG} = State, Id) ->
- lookup_channel(DG, Id),
- close_connections(DG, digraph:edges(DG, Id)),
- digraph:del_vertex(DG, Id),
- {reply, ok, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : add_connection
-%% Arguments : Connection - CosEventDomainAdmin::Connection
-%% Returns : ConnectionID |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_TypeError'{}} |
-%% {'EXCEPTION', #'CosEventDomainAdmin_AlreadyExists'{}} |
-%% {'EXCEPTION', #'CosEventDomainAdmin_CycleCreationForbidden'{cyc}} |
-%% {'EXCEPTION', #'CosEventDomainAdmin_DiamondCreationForbidden'{diam}}
-%% Description:
-%%----------------------------------------------------------------------
-add_connection(_OE_This, #state{graph = DG, co_counter = C} = State,
- Connection) when is_record(Connection,
- 'CosEventDomainAdmin_Connection') ->
- SId = Connection#'CosEventDomainAdmin_Connection'.supplier_id,
- SChannel = lookup_channel(DG, SId),
- CId = Connection#'CosEventDomainAdmin_Connection'.consumer_id,
- CChannel = lookup_channel(DG, CId),
- case lists:member(CId, digraph:out_neighbours(DG, SId)) of
- false ->
- Id = cosEventDomainApp:create_id(C),
- %% Try to insert the new connection before we actually setup a connection.
- %% Note that #connection is NOT complete, hence, we must update it later.
- case digraph:add_edge(DG, Id, SId, CId, #connection{data=Connection}) of
- {error, {bad_edge, Path}} ->
- corba:raise(#'CosEventDomainAdmin_CycleCreationForbidden'{cyc=Path});
- Id when State#state.diamonds == ?AuthorizeDiamonds ->
- case catch setup_connection(Connection, SChannel, CChannel) of
- {ok, SProxy, CProxy} ->
- %% Now we can update the connection with complete data.
- digraph:add_edge(DG, Id, SId, CId, #connection{supplier=SProxy,
- consumer=CProxy,
- data=Connection}),
- {reply, Id, State#state{co_counter = Id}};
- {'EXCEPTION', E} ->
- digraph:del_edge(DG, Id),
- corba:raise(E);
- What ->
- digraph:del_edge(DG, Id),
- orber:dbg("[~p] CosEventDomainAdmin_EventDomain:"
- "add_connection(~p);~nFailed setting up"
- " connection due to: ~p",
- [?LINE, Connection, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_MAYBE})
- end;
- Id ->
- case get_diamonds_helper(State, false, SId) of
- [] ->
- case catch setup_connection(Connection, SChannel, CChannel) of
- {ok, SProxy, CProxy} ->
- %% Now we can update the connection with complete data.
- digraph:add_edge(DG, Id, SId, CId, #connection{supplier=SProxy,
- consumer=CProxy,
- data=Connection}),
- {reply, Id, State#state{co_counter = Id}};
- {'EXCEPTION', E} ->
- digraph:del_edge(DG, Id),
- corba:raise(E);
- What ->
- digraph:del_edge(DG, Id),
- orber:dbg("[~p] CosEventDomainAdmin_EventDomain:"
- "add_connection(~p);~nFailed setting"
- " up connection due to: ~p",
- [?LINE, Connection, What],
- ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_MAYBE})
- end;
- Diamond ->
- %% Since no diamonds should exist the returned list can
- %% only describe the diamond we just created.
- digraph:del_edge(DG, Id),
- corba:raise(#'CosEventDomainAdmin_DiamondCreationForbidden'
- {diam=Diamond})
- end
- end;
- true ->
- corba:raise(#'CosEventDomainAdmin_AlreadyExists'{})
- end.
-
-
-%%---------------------------------------------------------------------%
-%% Function : get_all_connections
-%% Arguments : -
-%% Returns : CosEventDomainAdmin::ConnectionIDSeq - [long()]
-%% Description:
-%%----------------------------------------------------------------------
-get_all_connections(_OE_This, #state{graph = DG} = State) ->
- {reply, digraph:edges(DG), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : get_connection
-%% Arguments : Id - CosEventDomainAdmin::ConnectionID (long())
-%% Returns : CosEventDomainAdmin::Connection |
-%% {'EXCEPTION', #'CosEventDomainAdmin_ConnectionNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-get_connection(_OE_This, #state{graph = DG} = State, Id) ->
- {reply, lookup_connection_data(DG, Id), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : remove_connection
-%% Arguments : Id - CosEventDomainAdmin::ConnectionID (long())
-%% Returns : ok |
-%% {'EXCEPTION', #'CosEventDomainAdmin_ConnectionNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-remove_connection(_OE_This, #state{graph = DG} = State, Id) ->
- #connection{supplier=S, consumer=C, data=Connection} =
- lookup_connection(DG, Id),
- close_connection(Connection, S, C),
- digraph:del_edge(DG, Id),
- {reply, ok, State}.
-
-
-%%---------------------------------------------------------------------%
-%% Function : get_offer_channels
-%% Arguments : Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : CosNotifyChannelAdmin::ChannelIDSeq |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-get_offer_channels(_OE_This, #state{graph = DG, cyclic = Cyclic} = State, Id) ->
- lookup_channel(DG, Id),
- case digraph:vertex(DG, Id) of
- {Id, _Channel} when Cyclic == ?ForbidCycles ->
- {reply, digraph_utils:reaching_neighbours([Id], DG), State};
- {Id, _Channel} ->
- %% If cyclic graphs is allowed 'Id' will appear in the returned list.
- %% Hence, we must delete it.
- {reply,lists:delete(Id, digraph_utils:reaching_neighbours([Id], DG)),
- State};
- false ->
- corba:raise(#'CosNotifyChannelAdmin_ChannelNotFound'{})
- end.
-
-%%---------------------------------------------------------------------%
-%% Function : get_subscription_channels
-%% Arguments : Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : CosNotifyChannelAdmin::ChannelIDSeq |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-get_subscription_channels(_OE_This, #state{graph = DG, cyclic = Cyclic} = State, Id) ->
- lookup_channel(DG, Id),
- case digraph:vertex(DG, Id) of
- {Id, _Channel} when Cyclic == ?ForbidCycles ->
- {reply, digraph_utils:reachable_neighbours([Id], DG), State};
- {Id, _Channel} ->
- %% If cyclic graphs is allowed 'Id' will appear in the returned list.
- %% Hence, we must delete it.
- {reply, lists:delete(Id, digraph_utils:reachable_neighbours([Id], DG)),
- State};
- false ->
- corba:raise(#'CosNotifyChannelAdmin_ChannelNotFound'{})
- end.
-
-%%---------------------------------------------------------------------%
-%% Function : destroy
-%% Arguments : -
-%% Returns : ok
-%% Description:
-%%----------------------------------------------------------------------
-destroy(_OE_This, #state{graph = _DG} = State) ->
- {stop, normal, ok, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : get_cycles
-%% Arguments : -
-%% Returns : CosEventDomainAdmin::CycleSeq
-%% Description:
-%%----------------------------------------------------------------------
-get_cycles(_OE_This, #state{cyclic = ?ForbidCycles} = State) ->
- {reply, [], State};
-get_cycles(_OE_This, #state{graph = DG} = State) ->
- {reply, digraph_utils:cyclic_strong_components(DG), State}.
-
-%%----------------------------------------------------------------------
-%% Function : get_diamonds
-%% Arguments : -
-%% Returns : CosEventDomainAdmin::DiamondSeq
-%% Description:
-%%----------------------------------------------------------------------
-get_diamonds(_OE_This, #state{diamonds = ?ForbidDiamonds} = State) ->
- {reply, [], State};
-get_diamonds(_OE_This, State) ->
- {reply, get_diamonds_helper(State, true), State}.
-
-get_diamonds_helper(#state{graph = DG} = _State, FindAll) ->
- case find_candidates(DG) of
- {[], _, _} ->
- [];
- {_, [], _} ->
- [];
- {COut, CIn, Max} ->
- %% In this case we cannot tell if a diamond exists. Got to
- %% check the paths between the candidates.
- evaluate_candidates(DG, COut, CIn, [], Max, FindAll)
- end.
-
-get_diamonds_helper(#state{graph = DG} = _State, FindAll, Vertex) ->
- case find_candidates(DG, Vertex) of
- {[], _, _} ->
- [];
- {_, [], _} ->
- [];
- {COut, CIn, Max} ->
- %% In this case we cannot tell if a diamond exists. Got to
- %% check the paths between the candidates.
- evaluate_candidates(DG, COut, CIn, [], Max, FindAll)
- end.
-
-%%---------------------------------------------------------------------%
-%% Function : set_default_consumer_channel
-%% Arguments : Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : ok |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-set_default_consumer_channel(_OE_This, #state{graph = DG} = State, Id) ->
- lookup_channel(DG, Id),
- {reply, ok, State#state{def_consumer=Id}}.
-
-%%---------------------------------------------------------------------%
-%% Function : set_default_supplier_channel
-%% Arguments : Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : ok |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-set_default_supplier_channel(_OE_This, #state{graph = DG} = State, Id) ->
- lookup_channel(DG, Id),
- {reply, ok, State#state{def_supplier=Id}}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_push_consumer
-%% Arguments : PC - CosEventComm::PushConsumer
-%% Returns : CosNotifyChannelAdmin::ProxyPushSupplier |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_push_consumer(_OE_This, #state{def_supplier = Ch} = State, PC) ->
- type_check(PC, 'CosEventComm_PushConsumer'),
- Proxy = connect_a_push_consumer(Ch, PC, 'ANY_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_pull_consumer
-%% Arguments : PC - CosEventComm::PullConsumer
-%% Returns : CosNotifyChannelAdmin::ProxyPullSupplier |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_pull_consumer(_OE_This, #state{def_consumer = Ch} = State, PC) ->
- Proxy = connect_a_pull_consumer(Ch, PC, 'ANY_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_push_supplier
-%% Arguments : PS - CosEventComm::PushSupplier
-%% Returns : CosNotifyChannelAdmin::ProxyPushConsumer |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_push_supplier(_OE_This, #state{def_supplier = Ch} = State, PS) ->
- Proxy = connect_a_push_supplier(Ch, PS, 'ANY_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_pull_supplier
-%% Arguments : PS - CosEventComm::PullSupplier
-%% Returns : CosNotifyChannelAdmin::ProxyPullConsumer
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_pull_supplier(_OE_This, #state{def_consumer = Ch} = State, PS) ->
- type_check(PS, 'CosEventComm_PullSupplier'),
- Proxy = connect_a_pull_supplier(Ch, PS, 'ANY_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_structured_push_consumer
-%% Arguments : PC - CosNotifyComm::StructuredPushConsumer
-%% Returns : CosNotifyChannelAdmin::StructuredProxyPushSupplier |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_structured_push_consumer(_OE_This, #state{def_supplier = Ch} = State, PC) ->
- type_check(PC, 'CosNotifyComm_StructuredPushConsumer'),
- Proxy = connect_a_push_consumer(Ch, PC, 'STRUCTURED_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_structured_pull_consumer
-%% Arguments : PC - CosNotifyComm::StructuredPullConsumer
-%% Returns : CosNotifyChannelAdmin::StructuredProxyPullSupplier |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_structured_pull_consumer(_OE_This, #state{def_supplier = Ch} = State, PC) ->
- Proxy = connect_a_pull_consumer(Ch, PC, 'STRUCTURED_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_structured_push_supplier
-%% Arguments : PS - CosNotifyComm::StructuredPushSupplier
-%% Returns : CosNotifyChannelAdmin::StructuredProxyPushConsumer |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_structured_push_supplier(_OE_This, #state{def_consumer = Ch} = State, PS) ->
- Proxy = connect_a_push_supplier(Ch, PS, 'STRUCTURED_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_structured_pull_supplier
-%% Arguments : PS - CosNotifyComm::StructuredPullSupplier
-%% Returns : CosNotifyChannelAdmin::StructuredProxyPullConsumer |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_structured_pull_supplier(_OE_This, #state{def_consumer = Ch} = State, PS) ->
- type_check(PS, 'CosNotifyComm_StructuredPullSupplier'),
- Proxy = connect_a_pull_supplier(Ch, PS, 'STRUCTURED_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_sequence_push_consumer
-%% Arguments : PC - CosNotifyComm::SequencePushConsumer
-%% Returns : CosNotifyChannelAdmin::SequenceProxyPushSupplier |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_sequence_push_consumer(_OE_This, #state{def_supplier = Ch} = State, PC) ->
- type_check(PC, 'CosNotifyComm_SequencePushConsumer'),
- Proxy = connect_a_push_consumer(Ch, PC, 'SEQUENCE_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_sequence_pull_consumer
-%% Arguments : PC - CosNotifyComm::SequencePullConsumer
-%% Returns : CosNotifyChannelAdmin::SequenceProxyPullSupplier |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_sequence_pull_consumer(_OE_This, #state{def_supplier = Ch} = State, PC) ->
- Proxy = connect_a_pull_consumer(Ch, PC, 'SEQUENCE_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_sequence_push_supplier
-%% Arguments : PS - CosNotifyComm::SequencePushSupplier
-%% Returns : CosNotifyChannelAdmin::SequenceProxyPushConsumer |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_sequence_push_supplier(_OE_This, #state{def_consumer = Ch} = State, PS) ->
- Proxy = connect_a_push_supplier(Ch, PS, 'SEQUENCE_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_sequence_pull_supplier
-%% Arguments : PS - CosNotifyComm::SequencePullSupplier
-%% Returns : CosNotifyChannelAdmin::SequenceProxyPullConsumer |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_sequence_pull_supplier(_OE_This, #state{def_consumer = Ch} = State, PS) ->
- type_check(PS, 'CosNotifyComm_SequencePullSupplier'),
- Proxy = connect_a_pull_supplier(Ch, PS, 'SEQUENCE_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_push_consumer_with_id
-%% Arguments : PC - CosEventComm::PushConsumer
-%% Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : CosNotifyChannelAdmin::ProxyPushSupplier |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_push_consumer_with_id(_OE_This, #state{graph = DG} = State, PC, Id) ->
- type_check(PC, 'CosEventComm_PushConsumer'),
- Channel = lookup_channel(DG, Id),
- Proxy = connect_a_push_consumer(Channel, PC, 'ANY_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_pull_consumer_with_id
-%% Arguments : PC - CosEventComm::PullConsumer
-%% Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : CosNotifyChannelAdmin::ProxyPullSupplier |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_pull_consumer_with_id(_OE_This, #state{graph = DG} = State, PC, Id) ->
- Channel = lookup_channel(DG, Id),
- Proxy = connect_a_pull_consumer(Channel, PC, 'ANY_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_push_supplier_with_id
-%% Arguments : PS - CosEventComm::PushSupplier
-%% Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : CosNotifyChannelAdmin::ProxyPushConsumer |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_push_supplier_with_id(_OE_This, #state{graph = DG} = State, PS, Id) ->
- Channel = lookup_channel(DG, Id),
- Proxy = connect_a_push_supplier(Channel, PS, 'ANY_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_pull_supplier_with_id
-%% Arguments : PS - CosEventComm::PullSupplier
-%% Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : CosNotifyChannelAdmin::ProxyPullConsumer |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_pull_supplier_with_id(_OE_This, #state{graph = DG} = State, PS, Id) ->
- type_check(PS, 'CosEventComm_PullSupplier'),
- Channel = lookup_channel(DG, Id),
- Proxy = connect_a_pull_supplier(Channel, PS, 'ANY_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_structured_push_consumer_with_id
-%% Arguments : PC - CosNotifyComm::StructuredPushConsumer
-%% Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : CosNotifyChannelAdmin::StructuredProxyPushSupplier |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_structured_push_consumer_with_id(_OE_This, #state{graph = DG} = State, PC, Id) ->
- type_check(PC, 'CosNotifyComm_StructuredPushConsumer'),
- Channel = lookup_channel(DG, Id),
- Proxy = connect_a_push_consumer(Channel, PC, 'STRUCTURED_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_structured_pull_consumer_with_id
-%% Arguments : PC - CosNotifyComm::StructuredPullConsumer
-%% Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : CosNotifyChannelAdmin::StructuredProxyPullSupplier |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_structured_pull_consumer_with_id(_OE_This, #state{graph = DG} = State, PC, Id) ->
- Channel = lookup_channel(DG, Id),
- Proxy = connect_a_pull_consumer(Channel, PC, 'STRUCTURED_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_structured_push_supplier_with_id
-%% Arguments : PS - CosNotifyComm::StructuredPushSupplier
-%% Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : CosNotifyChannelAdmin::StructuredProxyPushConsumer |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_structured_push_supplier_with_id(_OE_This, #state{graph = DG} = State, PS, Id) ->
- Channel = lookup_channel(DG, Id),
- Proxy = connect_a_push_supplier(Channel, PS, 'STRUCTURED_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_structured_pull_supplier_with_id
-%% Arguments : PS - CosNotifyComm::StructuredPullSupplier
-%% Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : CosNotifyChannelAdmin::StructuredProxyPullConsumer |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_structured_pull_supplier_with_id(_OE_This, #state{graph = DG} = State, PS, Id) ->
- type_check(PS, 'CosNotifyComm_StructuredPullSupplier'),
- Channel = lookup_channel(DG, Id),
- Proxy = connect_a_pull_supplier(Channel, PS, 'STRUCTURED_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_sequence_push_consumer_with_id
-%% Arguments : PC - CosNotifyComm::SequencePushConsumer
-%% Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : CosNotifyChannelAdmin::SequenceProxyPushSupplier |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_sequence_push_consumer_with_id(_OE_This, #state{graph = DG} = State, PC, Id) ->
- type_check(PC, 'CosNotifyComm_SequencePushConsumer'),
- Channel = lookup_channel(DG, Id),
- Proxy = connect_a_push_consumer(Channel, PC, 'SEQUENCE_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_sequence_pull_consumer_with_id
-%% Arguments : PC - CosNotifyComm::SequencePullConsumer
-%% Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : CosNotifyChannelAdmin::SequenceProxyPullSupplier |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_sequence_pull_consumer_with_id(_OE_This, #state{graph = DG} = State, PC, Id) ->
- Channel = lookup_channel(DG, Id),
- Proxy = connect_a_pull_consumer(Channel, PC, 'SEQUENCE_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_sequence_push_supplier_with_id
-%% Arguments : PS - CosNotifyComm::SequencePushSupplier
-%% Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : CosNotifyChannelAdmin::SequenceProxyPushConsumer |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_sequence_push_supplier_with_id(_OE_This, #state{graph = DG} = State, PS, Id) ->
- Channel = lookup_channel(DG, Id),
- Proxy = connect_a_push_supplier(Channel, PS, 'SEQUENCE_EVENT'),
- {reply, Proxy, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : connect_sequence_pull_supplier_with_id
-%% Arguments : PS - CosNotifyComm::SequencePullSupplier
-%% Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : CosNotifyChannelAdmin::SequenceProxyPullConsumer |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}} |
-%% Description:
-%%----------------------------------------------------------------------
-connect_sequence_pull_supplier_with_id(_OE_This, #state{graph = DG} = State, PS, Id) ->
- type_check(PS, 'CosNotifyComm_SequencePullSupplier'),
- Channel = lookup_channel(DG, Id),
- Proxy = connect_a_pull_supplier(Channel, PS, 'SEQUENCE_EVENT'),
- {reply, Proxy, State}.
-
-
-%%----------------------------------------------------------------------
-%%------------------ CosNotification::QoSAdmin -------------------------
-%%---------------------------------------------------------------------%
-%% Function : get_qos
-%% Arguments : -
-%% Returns : CosNotification::QoSProperties
-%% Description:
-%%----------------------------------------------------------------------
-get_qos(_OE_This, #state{cyclic = Cyclic, diamonds = Diamonds} = State) ->
- {reply, [#'CosNotification_Property'
- {name = ?DiamondDetection,
- value = any:create(orber_tc:short(), Diamonds)},
- #'CosNotification_Property'
- {name = ?CycleDetection,
- value = any:create(orber_tc:short(), Cyclic)}], State}.
-
-%%---------------------------------------------------------------------%
-%% Function : set_qos
-%% Arguments : NewQoS - CosNotification::QoSProperties
-%% Returns : ok |
-%% {'EXCEPTION', #'CosNotification_UnsupportedQoS{}}
-%% Description:
-%%----------------------------------------------------------------------
-set_qos(_OE_This, State, NewQoS) ->
- QoS = cosEventDomainApp:get_qos(NewQoS),
- case set_qos_helper(QoS, State, []) of
- {ok, NewState} ->
- {reply, ok, NewState};
- {error, Errors} ->
- corba:raise(#'CosNotification_UnsupportedQoS'{qos_err = Errors})
- end.
-
-set_qos_helper([], State, []) ->
- {ok, State}; %{reply, ok, State};
-set_qos_helper([], _, Errors) ->
- {error, Errors};
-set_qos_helper([{?DiamondDetection, Diamonds}|T], #state{diamonds = Diamonds} = State,
- Errors) ->
- set_qos_helper(T, State, Errors);
-set_qos_helper([{?CycleDetection, Cyclic}|T], #state{cyclic = Cyclic} = State,
- Errors) ->
- set_qos_helper(T, State, Errors);
-set_qos_helper([{?DiamondDetection, ?AuthorizeDiamonds}|T], State, Errors) ->
- %% Diamonds have not been allowed so far so it's safe to allow it.
- set_qos_helper(T, State#state{diamonds = ?AuthorizeDiamonds}, Errors);
-set_qos_helper([{?DiamondDetection, ?ForbidDiamonds}|T], State, Errors) ->
- %% If any diamonds already exists we cannot allow this. Hence, now we must check
- %% if we can update the QoS.
- case get_diamonds_helper(State, false) of
- [] ->
- set_qos_helper(T, State#state{diamonds = ?ForbidDiamonds}, Errors);
- _ ->
- set_qos_helper(T, State,
- [#'CosNotification_PropertyError'
- {code = 'UNAVAILABLE_VALUE',
- name = ?DiamondDetection,
- available_range = #'CosNotification_PropertyRange'
- {low_val=any:create(orber_tc:short(), ?AuthorizeDiamonds),
- high_val=any:create(orber_tc:short(), ?AuthorizeDiamonds)}}|Errors])
- end;
-set_qos_helper([{?CycleDetection, _}|T], #state{cyclic = Cyclic} = State, Errors) ->
- %% Currently we do not support changing the Cycle schema. If we want to,
- %% we must copy the graph to a new instance of the correct type.
- set_qos_helper(T, State,
- [#'CosNotification_PropertyError'
- {code = 'UNAVAILABLE_VALUE',
- name = ?CycleDetection,
- available_range = #'CosNotification_PropertyRange'
- {low_val=any:create(orber_tc:short(), Cyclic),
- high_val=any:create(orber_tc:short(), Cyclic)}}|Errors]).
-
-%%---------------------------------------------------------------------%
-%% Function : validate_qos
-%% Arguments : WantedQoS - CosNotification::QoSProperties
-%% Returns : {ok, CosNotification::NamedPropertyRangeSeq} |
-%% {'EXCEPTION', #'CosNotification_UnsupportedQoS{}}
-%% Description: NamedPropertyRangeSeq is of out-type
-%%----------------------------------------------------------------------
-validate_qos(_OE_This, State, WantedQoS) ->
- QoS = cosEventDomainApp:get_qos(WantedQoS),
- case validate_qos_helper(QoS, State, [], []) of
- {ok, Properties} ->
- {reply, {ok, Properties}, State};
- {error, Errors} ->
- corba:raise(#'CosNotification_UnsupportedQoS'{qos_err = Errors})
- end.
-
-validate_qos_helper([], _, Properties, []) ->
- {ok, Properties};
-validate_qos_helper([], _, _, Errors) ->
- {error, Errors};
-validate_qos_helper([{?DiamondDetection, ?ForbidDiamonds}|T], State, Properties,
- Errors) ->
- case get_diamonds_helper(State, false) of
- [] ->
- Property =
- #'CosNotification_NamedPropertyRange'
- {name = ?DiamondDetection,
- range = #'CosNotification_PropertyRange'
- {low_val=any:create(orber_tc:short(), ?AuthorizeDiamonds),
- high_val=any:create(orber_tc:short(), ?ForbidDiamonds)}},
- validate_qos_helper(T, State, [Property|Properties], Errors);
- _ ->
- Error =
- #'CosNotification_PropertyError'
- {code = 'UNAVAILABLE_VALUE',
- name = ?DiamondDetection,
- available_range = #'CosNotification_PropertyRange'
- {low_val=any:create(orber_tc:short(), ?AuthorizeDiamonds),
- high_val=any:create(orber_tc:short(), ?AuthorizeDiamonds)}},
- validate_qos_helper(T, State, Properties, [Error|Errors])
- end;
-validate_qos_helper([{?DiamondDetection, ?AuthorizeDiamonds}|T], State, Properties,
- Errors) ->
- Property =
- #'CosNotification_NamedPropertyRange'
- {name = ?DiamondDetection,
- range = #'CosNotification_PropertyRange'
- {low_val=any:create(orber_tc:short(), ?AuthorizeDiamonds),
- high_val=any:create(orber_tc:short(), ?ForbidDiamonds)}},
- validate_qos_helper(T, State, [Property|Properties], Errors);
-validate_qos_helper([{?CycleDetection, Cyclic}|T], #state{cyclic = Cyclic} = State,
- Properties, Errors) ->
- validate_qos_helper(T, State, Properties, Errors);
-validate_qos_helper([{?CycleDetection, _}|T], #state{cyclic = Cyclic} = State,
- Properties, Errors) ->
- Error =
- #'CosNotification_PropertyError'
- {code = 'UNAVAILABLE_VALUE',
- name = ?CycleDetection,
- available_range = #'CosNotification_PropertyRange'
- {low_val=any:create(orber_tc:short(), Cyclic),
- high_val=any:create(orber_tc:short(), Cyclic)}},
- validate_qos_helper(T, State, Properties, [Error|Errors]).
-
-
-%%----------------------------------------------------------------------
-%%------------------ CosNotification::AdminPropertiesAdmin -------------
-%%---------------------------------------------------------------------%
-%% Function : get_admin
-%% Arguments : -
-%% Returns : CosNotification::AdminProperties
-%% Description: No Admins currently supported
-%%----------------------------------------------------------------------
-get_admin(_OE_This, State) ->
- {reply, [], State}.
-
-%%---------------------------------------------------------------------%
-%% Function : set_admin
-%% Arguments : NewAdmins - CosNotification::AdminProperties
-%% Returns : ok |
-%% {'EXCEPTION', #'CosNotification_UnsupportedAdmin{}}
-%% Description: No Admins currently supported
-%%----------------------------------------------------------------------
-set_admin(_OE_This, State, NewAdmins) ->
- cosEventDomainApp:get_admin(NewAdmins),
- {reply, ok, State}.
-
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-%%---------------------------------------------------------------------%
-%% Function : find_candidates
-%% Arguments : Digraph reference
-%% (Vertex - if we're interested in a specific vertex.
-%% Returns : {[SourceVertices], [SinkVertices], Max}
-%% SourceVertices - {Vertice, [ReachableVertices]}
-%% SinkVertices - {Vertice, [ReachingVertices]}
-%% Max - number of edges in the graph.
-%% Description: To be a part of a diamond ("transitive" relation xRy, yRz => xRz;
-%% in comparison with discrete mathematics we do not require that the
-%% entire graph is transitive) a vertex must have more than one
-%% outgoing and/or incoming. Hence, a digraph must contain at least
-%% one vertex with more than one outgoing edges and at least
-%% one with more than one incoming edges for a diamond to exist.
-%% Hence, the purpose of this function is to find vertices that
-%% look like:
-%%
-%% Vout->V1 V6->Vin
-%% \ and ^
-%% +->V2 |
-%% V8--+
-%%----------------------------------------------------------------------
-find_candidates(DG) ->
- Edges = digraph:edges(DG),
- {COut, CIn, Max} = find_candidates_helper(Edges, [], [], DG, 0),
- {filter_candidates(COut), filter_candidates(CIn), Max}.
-
-
-find_candidates(DG, _Vertex) ->
- %% We should use the fact that we know one of the vertices.
- Edges = digraph:edges(DG),
- {COut, CIn, Max} = find_candidates_helper(Edges, [], [], DG, 0),
- {filter_candidates(COut), filter_candidates(CIn), Max}.
-
-find_candidates_helper([], AccOut, AccIn, _, Counter) ->
- {lists:sort(AccOut), lists:sort(AccIn), Counter};
-find_candidates_helper([H|T], AccOut, AccIn, DG, Counter) ->
- {H, V1, V2, _Label} = digraph:edge(DG, H),
- find_candidates_helper(T, [{V1, V2}|AccOut], [{V2,V1}|AccIn], DG, Counter+1).
-
-filter_candidates([]) ->
- [];
-filter_candidates([{V1, V2}|T]) ->
- filter_candidates([{V1, V2}|T], V1, [], []).
-filter_candidates([], _V, [_Acc1], Acc2) ->
- %% Only one in/out connection. Hence, cannot be start- or end-point
- %% of a diamond.
- lists:reverse(Acc2);
-filter_candidates([], V, Acc1, Acc2) ->
- lists:reverse([{V, lists:reverse(Acc1)}|Acc2]);
-filter_candidates([{V1, V2}|T], V1, Acc1, Acc2) ->
- filter_candidates(T, V1, [V2|Acc1], Acc2);
-filter_candidates([{V1, V2}|T], _V, [_Acc1], Acc2) ->
- %% Only one in/out connection. Hence, cannot be start- or end-point
- %% of a diamond.
- filter_candidates(T, V1, [V2], Acc2);
-filter_candidates([{V1, V2}|T], V, Acc1, Acc2) ->
- filter_candidates(T, V1, [V2], [{V, lists:reverse(Acc1)}|Acc2]).
-
-%%---------------------------------------------------------------------%
-%% Function : evaluate_candidates
-%% Arguments : -
-%% Returns : [Diamond]
-%% Description: There are several scenarios but they can be categorized as:
-%% (1) (2) (3) (4)
-%% 2 2 2-..-56
-%% / \ / \ / \
-%% 1---4 1---4 1---4 1 4
-%% \ / \ / \ /
-%% 3 3 3-..-11
-%%
-%% The purpose of this function is to find these in the cheapest
-%% way possible. For complex diamonds (may also include cycles)
-%% duplicates may be generated. For example, #2/#3 is a sub-set of #1
-%% but they are as well diamonds.
-%%----------------------------------------------------------------------
-evaluate_candidates(_DG, [], _, Acc, _Max, _) ->
- Acc;
-evaluate_candidates(DG, [{V, OutV}|T], CIn, Acc, Max, FindAll) ->
- case evaluate_candidates_helper(DG, V, OutV, CIn, [], FindAll) of
- [] ->
- evaluate_candidates(DG, T, CIn, Acc, Max, FindAll);
- Diamonds when FindAll == true ->
- %% May be more than one diamond.
- evaluate_candidates(DG, T, CIn, Diamonds ++ Acc, Max, FindAll);
- Diamond ->
- Diamond
- end.
-
-evaluate_candidates_helper(_, _, _, _, [Diamond], false) ->
- Diamond;
-evaluate_candidates_helper(_, _, _, [], Diamonds, _) ->
- Diamonds;
-evaluate_candidates_helper(DG, V1, OutV, [{V1, _InV}|T], Diamonds, FindAll) ->
- evaluate_candidates_helper(DG, V1, OutV, T, Diamonds, FindAll);
-evaluate_candidates_helper(DG, V1, OutV, [{V2, InV}|T], Diamonds, FindAll) ->
- case double_match(OutV, InV, [], V1, V2) of
- [] ->
- case is_member(InV, V1) of
- true ->
- %% At this point we know that we have:
- %% x -> y
- %% For this pair to be a part of a diamond we have two options:
- %% (1) x - y (2) x ---- y
- %% \ / or \ / or a additional path besides z1-zN,
- %% z z1-zN
- case double_match_exclude(OutV, InV, [], V1, V2) of
- [] ->
- %% Nope it's not #1.
- case digraph_match(OutV, V2, V1, DG, 1) of
- false ->
- evaluate_candidates_helper(DG, V1, OutV, T,
- Diamonds, FindAll);
- Diamond ->
- evaluate_candidates_helper(DG, V1, OutV, T,
- [[[V1, V2]|Diamond]|Diamonds],
- FindAll)
- end;
- Diamond ->
- %% We've found a diamond looking like:
- %% x - y xRy, yRz => xRz
- %% \ /
- %% z
- evaluate_candidates_helper(DG, V1, OutV, T,
- [[[V1, V2]|Diamond]|Diamonds],
- FindAll)
- end;
- false ->
- case digraph_match(OutV, V2, V1, DG) of
- false ->
- evaluate_candidates_helper(DG, V1, OutV, T,
- Diamonds, FindAll);
- Diamond ->
- evaluate_candidates_helper(DG, V1, OutV, T,
- [Diamond|Diamonds], FindAll)
- end
- end;
- Diamond ->
- %% We've found a diamond looking something like:
- %% 2
- %% / \
- %% 1-5-4 V1 eq. 1, V2 eq 4.
- %% \ /
- %% 3
- evaluate_candidates_helper(DG, V1, OutV, T, [Diamond|Diamonds],
- FindAll)
- end.
-
-is_member([], _) ->
- false;
-is_member([H|_], H) ->
- true;
-is_member([H|_], H2) when H > H2 ->
- %% Since it's a sorted list no need to look any further.
- false;
-is_member([_|T], H) ->
- is_member(T, H).
-
-double_match([], _, [_Matched], _, _) ->
- [];
-double_match([], _, Matched, _, _) ->
- Matched;
-double_match(_, [], [_Matched], _, _) ->
- [];
-double_match(_, [], Matched, _, _) ->
- Matched;
-double_match([H|T1], [H|T2], Matched, V1, V2) ->
- double_match(T1, T2, [[V1,H,V2] | Matched], V1, V2);
-double_match([H1|T1], [H2|T2], Matched, V1, V2) when H1 > H2 ->
- double_match([H1|T1], T2, Matched, V1, V2);
-double_match([_H1|T1], [H2|T2], Matched, V1, V2) ->
- double_match(T1, [H2|T2], Matched, V1, V2).
-
-double_match_exclude([], _, Matched, _, _) ->
- Matched;
-double_match_exclude(_, [], Matched, _, _) ->
- Matched;
-%% exclude it
-double_match_exclude([V2|T1], CIn, Matched, V1, V2) ->
- double_match_exclude(T1, CIn, Matched, V1, V2);
-%% exclude it
-double_match_exclude(COut, [V1|T2], Matched, V1, V2) ->
- double_match_exclude(COut, T2, Matched, V1, V2);
-%% Found match
-double_match_exclude([H|T1], [H|T2], Matched, V1, V2) ->
- double_match_exclude(T1, T2, [[V1,H,V2] | Matched], V1, V2);
-double_match_exclude([H1|T1], [H2|T2], Matched, V1, V2) when H1 > H2 ->
- double_match_exclude([H1|T1], T2, Matched, V1, V2);
-double_match_exclude([_H1|T1], [H2|T2], Matched, V1, V2) ->
- double_match_exclude(T1, [H2|T2], Matched, V1, V2).
-
-
-digraph_match(OutV, V2, V1, DG) ->
- digraph_match(OutV, V2, V1, DG, [], 0).
-
-digraph_match(OutV, V2, V1, DG, Counter) ->
- digraph_match(OutV, V2, V1, DG, [], Counter).
-
-digraph_match([], _, _, _, _, Counter) when Counter < 2 ->
- false;
-digraph_match([], _, _, _, Acc, _) ->
- Acc;
-digraph_match([Vin|T], Vin, Vout, DG, Acc, Counter) ->
- digraph_match(T, Vin, Vout, DG, Acc, Counter);
-digraph_match([H|T], Vin, Vout, DG, Acc, Counter) ->
- case get_path(DG, H, Vin, H, Vout) of
- false ->
- digraph_match(T, Vin, Vout, DG, Acc, Counter);
- Path ->
- %% Found one path; now me must se if there are one more.
- digraph_match(T, Vin, Vout, DG, [[Vout|lists:reverse(Path)] | Acc],
- Counter+1)
- end.
-
-get_path(G, V1, V2, E1, E2) ->
- one_path(digraph:out_neighbours(G, V1), V2, [], [V1], [V1], G, E1, E2).
-
-one_path([E1|_Vs], W, Cont, Xs, Ps, G, E1, E2) ->
- one_path([], W, Cont, Xs, Ps, G, E1, E2);
-one_path([E2|_Vs], W, Cont, Xs, Ps, G, E1, E2) ->
- one_path([], W, Cont, Xs, Ps, G, E1, E2);
-one_path([W|_Ws], W, _Cont, _Xs, Ps, _G, _E1, _E2) ->
- [W|Ps];
-one_path([V|Vs], W, Cont, Xs, Ps, G, E1, E2) ->
- case lists:member(V, Xs) of
- true -> one_path(Vs, W, Cont, Xs, Ps, G, E1, E2);
- false -> one_path(digraph:out_neighbours(G, V), W,
- [{Vs,Ps} | Cont], [V|Xs], [V|Ps], G, E1, E2)
- end;
-one_path([], W, [{Vs,Ps}|Cont], Xs, _, G, E1, E2) ->
- one_path(Vs, W, Cont, Xs, Ps, G, E1, E2);
-one_path([], _, [], _, _, _, _, _) -> false.
-
-%%---------------------------------------------------------------------%
-%% function : type_check
-%% Arguments: Obj - objectrefernce to test.
-%% Mod - Module which contains typeID/0.
-%% Returns : 'ok' or raises exception.
-%% Effect :
-%%----------------------------------------------------------------------
-type_check(Obj, Mod) ->
- case catch corba_object:is_a(Obj,Mod:typeID()) of
- true ->
- ok;
- What ->
- orber:dbg("[~p] CosEventDomainAdmin:type_check();~n"
- "Object of incorrect type supplied; should be: ~p~n"
- "Failed due to: ~p", [?LINE, Mod, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{minor=507, completion_status=?COMPLETED_NO})
- end.
-
-%%---------------------------------------------------------------------%
-%% function : lookup_channel
-%% Arguments: DG - digraph reference
-%% Id - CosEventDomainAdmin::MemberID (long())
-%% Returns : CosNotifyChannelAdmin::EventChannel |
-%% {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}
-%% Effect :
-%%----------------------------------------------------------------------
-lookup_channel(DG, Id) ->
- case digraph:vertex(DG, Id) of
- {Id, Channel} ->
- Channel;
- false ->
- corba:raise(#'CosNotifyChannelAdmin_ChannelNotFound'{})
- end.
-
-
-%%---------------------------------------------------------------------%
-%% function : lookup_connection
-%% Arguments: DG - digraph reference
-%% Id - CosEventDomainAdmin::ConnectionID (long())
-%% Returns : #connectio{} |
-%% {'EXCEPTION', #'CosEventDomainAdmin_ConnectionNotFound'{}}
-%% Effect :
-%%----------------------------------------------------------------------
-lookup_connection(DG, Id) ->
- case digraph:edge(DG, Id) of
- {Id, _SId, _CId, Connection} ->
- Connection;
- false ->
- corba:raise(#'CosEventDomainAdmin_ConnectionNotFound'{})
- end.
-
-%%---------------------------------------------------------------------%
-%% function : lookup_connection_data
-%% Arguments: DG - digraph reference
-%% Id - CosEventDomainAdmin::ConnectionID (long())
-%% Returns : CosEventDomainAdmin::Connection |
-%% {'EXCEPTION', #'CosEventDomainAdmin_ConnectionNotFound'{}}
-%% Effect :
-%%----------------------------------------------------------------------
-lookup_connection_data(DG, Id) ->
- case digraph:edge(DG, Id) of
- {Id, _SId, _CId, #connection{data = Connection}} ->
- Connection;
- false ->
- corba:raise(#'CosEventDomainAdmin_ConnectionNotFound'{})
- end.
-
-%%---------------------------------------------------------------------%
-%% function : close_connections
-%% Arguments: DG -digraph reference
-%% [CosEventDomainAdmin::ConnectionID] - [long()]
-%% Returns : ok
-%% Effect :
-%%----------------------------------------------------------------------
-close_connections(_DG, []) ->
- ok;
-close_connections(DG, [H|T]) ->
- #connection{supplier=S, consumer=C, data=Connection} =
- lookup_connection(DG, H),
- close_connection(Connection, S, C),
- digraph:del_edge(DG, H),
- close_connections(DG, T).
-
-%%---------------------------------------------------------------------%
-%% function : close_connection
-%% Arguments: CosEventDomainAdmin::Connection
-%% S - SupplierProxy
-%% C - ConsumerProxy
-%% Returns : ok
-%% Effect :
-%%----------------------------------------------------------------------
-close_connection(#'CosEventDomainAdmin_Connection'{ctype=Type,
- notification_style = Style},
- S, C) ->
- case {Type, Style} of
- {'ANY_EVENT', 'Push'} ->
- catch 'CosNotifyChannelAdmin_ProxyPushSupplier':disconnect_push_supplier(S),
- catch 'CosNotifyChannelAdmin_ProxyPushConsumer':disconnect_push_consumer(C);
- {'ANY_EVENT', 'Pull'} ->
- catch 'CosNotifyChannelAdmin_ProxyPullSupplier':disconnect_pull_supplier(S),
- catch 'CosNotifyChannelAdmin_ProxyPullConsumer':disconnect_pull_consumer(C);
- {'STRUCTURED_EVENT', 'Push'} ->
- catch 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':disconnect_structured_push_supplier(S),
- catch 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':disconnect_structured_push_consumer(C);
- {'STRUCTURED_EVENT', 'Pull'} ->
- catch 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':disconnect_structured_pull_supplier(S),
- catch 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':disconnect_structured_pull_consumer(C);
- {'SEQUENCE_EVENT', 'Push'} ->
- catch 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':disconnect_sequence_push_supplier(S),
- catch 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':disconnect_sequence_push_consumer(C);
- {'SEQUENCE_EVENT', 'Pull'}->
- catch 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':disconnect_sequence_pull_supplier(S),
- catch 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':disconnect_sequence_pull_consumer(C)
- end,
- ok.
-
-%%---------------------------------------------------------------------%
-%% function : setup_connection
-%% Arguments: CosEventDomainAdmin::Connection
-%% S - SupplierProxy
-%% C - ConsumerProxy
-%% Returns : {ok, SupplierProxy, ConsumerProxy};
-%% Effect :
-%%----------------------------------------------------------------------
-setup_connection(#'CosEventDomainAdmin_Connection'{ctype=Type,
- notification_style = Style},
- S, C) ->
- Admin =
- 'CosNotifyChannelAdmin_EventChannel':'_get_default_consumer_admin'(S),
- case Style of
- 'Push' ->
- {Proxy, _Id} =
- 'CosNotifyChannelAdmin_ConsumerAdmin':
- obtain_notification_push_supplier(Admin, Type),
- CProxy = connect_a_push_supplier(C, Proxy, Type),
- case Type of
- 'ANY_EVENT' ->
- 'CosNotifyChannelAdmin_ProxyPushSupplier':
- connect_any_push_consumer(Proxy, CProxy);
- 'STRUCTURED_EVENT' ->
- 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':
- connect_structured_push_consumer(Proxy, CProxy);
- 'SEQUENCE_EVENT' ->
- 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':
- connect_sequence_push_consumer(Proxy, CProxy)
- end,
- {ok, Proxy, CProxy};
- 'Pull' ->
- {Proxy, _Id} =
- 'CosNotifyChannelAdmin_ConsumerAdmin':
- obtain_notification_pull_supplier(Admin, Type),
- CProxy = connect_a_pull_supplier(C, Proxy, Type),
- case Type of
- 'ANY_EVENT' ->
- 'CosNotifyChannelAdmin_ProxyPullSupplier':
- connect_any_pull_consumer(Proxy, CProxy);
- 'STRUCTURED_EVENT' ->
- 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':
- connect_structured_pull_consumer(Proxy, CProxy);
- 'SEQUENCE_EVENT' ->
- 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':
- connect_sequence_pull_consumer(Proxy, CProxy)
- end,
- {ok, Proxy, CProxy}
- end.
-
-%%---------------------------------------------------------------------%
-%% function : connect_a_pull_consumer
-%% Arguments: Channel - CosNotifyChannelAdmin::EventChannel | undefined
-%% PC - a PullConsumer
-%% Type - 'ANY_EVENT' | 'STRUCTURED_EVENT' | 'SEQUENCE_EVENT'
-%% Returns :
-%% Effect :
-%%----------------------------------------------------------------------
-connect_a_pull_consumer(undefined, _, _) ->
- corba:raise(#'CosNotifyChannelAdmin_ChannelNotFound'{});
-connect_a_pull_consumer(Channel, PC, Type) ->
- Admin =
- 'CosNotifyChannelAdmin_EventChannel':'_get_default_consumer_admin'(Channel),
- {Proxy, _Id} =
- 'CosNotifyChannelAdmin_ConsumerAdmin':obtain_notification_pull_supplier(Admin,
- Type),
- case Type of
- 'ANY_EVENT' ->
- 'CosNotifyChannelAdmin_ProxyPullSupplier':connect_any_pull_consumer(Proxy, PC);
- 'STRUCTURED_EVENT' ->
- 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':connect_structured_pull_consumer(Proxy, PC);
- 'SEQUENCE_EVENT' ->
- 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':connect_sequence_pull_consumer(Proxy, PC)
- end,
- Proxy.
-
-%%---------------------------------------------------------------------%
-%% function : connect_a_push_consumer
-%% Arguments: Channel - CosNotifyChannelAdmin::EventChannel | undefined
-%% PC - a PushConsumer
-%% Type - 'ANY_EVENT' | 'STRUCTURED_EVENT' | 'SEQUENCE_EVENT'
-%% Returns :
-%% Effect :
-%%----------------------------------------------------------------------
-connect_a_push_consumer(undefined, _, _) ->
- corba:raise(#'CosNotifyChannelAdmin_ChannelNotFound'{});
-connect_a_push_consumer(Channel, PC, Type) ->
- Admin =
- 'CosNotifyChannelAdmin_EventChannel':'_get_default_consumer_admin'(Channel),
- {Proxy, _Id} =
- 'CosNotifyChannelAdmin_ConsumerAdmin':obtain_notification_push_supplier(Admin,
- Type),
- case Type of
- 'ANY_EVENT' ->
- 'CosNotifyChannelAdmin_ProxyPushSupplier':connect_any_push_consumer(Proxy, PC);
- 'STRUCTURED_EVENT' ->
- 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':connect_structured_push_consumer(Proxy, PC);
- 'SEQUENCE_EVENT' ->
- 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':connect_sequence_push_consumer(Proxy, PC)
- end,
- Proxy.
-
-%%---------------------------------------------------------------------%
-%% function : connect_a_pull_supplier
-%% Arguments: Channel - CosNotifyChannelAdmin::EventChannel | undefined
-%% PC - a PullSupplier
-%% Type - 'ANY_EVENT' | 'STRUCTURED_EVENT' | 'SEQUENCE_EVENT'
-%% Returns :
-%% Effect :
-%%----------------------------------------------------------------------
-connect_a_pull_supplier(undefined, _, _) ->
- corba:raise(#'CosNotifyChannelAdmin_ChannelNotFound'{});
-connect_a_pull_supplier(Channel, PS, Type) ->
- Admin =
- 'CosNotifyChannelAdmin_EventChannel':'_get_default_supplier_admin'(Channel),
- {Proxy, _Id} =
- 'CosNotifyChannelAdmin_SupplierAdmin':obtain_notification_pull_consumer(Admin,
- Type),
- case Type of
- 'ANY_EVENT' ->
- 'CosNotifyChannelAdmin_ProxyPullConsumer':connect_any_pull_supplier(Proxy, PS);
- 'STRUCTURED_EVENT' ->
- 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':connect_structured_pull_supplier(Proxy, PS);
- 'SEQUENCE_EVENT' ->
- 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':connect_sequence_pull_supplier(Proxy, PS)
- end,
- Proxy.
-
-%%---------------------------------------------------------------------%
-%% function : connect_a_push_supplier
-%% Arguments: Channel - CosNotifyChannelAdmin::EventChannel | undefined
-%% PC - a PushSupplier
-%% Type - 'ANY_EVENT' | 'STRUCTURED_EVENT' | 'SEQUENCE_EVENT'
-%% Returns :
-%% Effect :
-%%----------------------------------------------------------------------
-connect_a_push_supplier(undefined, _, _) ->
- corba:raise(#'CosNotifyChannelAdmin_ChannelNotFound'{});
-connect_a_push_supplier(Channel, PS, Type) ->
- Admin =
- 'CosNotifyChannelAdmin_EventChannel':'_get_default_supplier_admin'(Channel),
- {Proxy, _Id} =
- 'CosNotifyChannelAdmin_SupplierAdmin':obtain_notification_push_consumer(Admin,
- Type),
- case Type of
- 'ANY_EVENT' ->
- 'CosNotifyChannelAdmin_ProxyPushConsumer':connect_any_push_supplier(Proxy, PS);
- 'STRUCTURED_EVENT' ->
- 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':connect_structured_push_supplier(Proxy, PS);
- 'SEQUENCE_EVENT' ->
- 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':connect_sequence_push_supplier(Proxy, PS)
- end,
- Proxy.
-
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
-
diff --git a/lib/cosEventDomain/src/Makefile b/lib/cosEventDomain/src/Makefile
deleted file mode 100644
index cdaf9e5f1f..0000000000
--- a/lib/cosEventDomain/src/Makefile
+++ /dev/null
@@ -1,185 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2001-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-ifeq ($(TYPE),debug)
-ERL_COMPILE_FLAGS += -Ddebug -W
-endif
-EBIN=../ebin
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(COSEVENTDOMAIN_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/cosEventDomain-$(VSN)
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES = \
- CosEventDomainAdmin_EventDomainFactory_impl \
- CosEventDomainAdmin_EventDomain_impl \
- cosEventDomainApp
-
-ERL_FILES = $(MODULES:%=%.erl)
-HRL_FILES = cosEventDomainApp.hrl
-
-EXTERNAL_INC_PATH = ../include
-
-GEN_ERL_FILES = \
- oe_CosEventDomainAdmin.erl \
- CosEventDomainAdmin.erl \
- CosEventDomainAdmin_DiamondSeq.erl \
- CosEventDomainAdmin_AlreadyExists.erl \
- CosEventDomainAdmin_DomainIDSeq.erl \
- CosEventDomainAdmin_Connection.erl \
- CosEventDomainAdmin_ConnectionIDSeq.erl \
- CosEventDomainAdmin_ConnectionNotFound.erl \
- CosEventDomainAdmin_CycleCreationForbidden.erl \
- CosEventDomainAdmin_CycleSeq.erl \
- CosEventDomainAdmin_DiamondCreationForbidden.erl \
- CosEventDomainAdmin_DomainNotFound.erl \
- CosEventDomainAdmin_EventDomain.erl \
- CosEventDomainAdmin_EventDomainFactory.erl \
- CosEventDomainAdmin_MemberIDSeq.erl \
- CosEventDomainAdmin_RouteSeq.erl
-
-
-
-GEN_HRL_FILES = \
- oe_CosEventDomainAdmin.hrl \
- CosEventDomainAdmin.hrl \
- CosEventDomainAdmin_EventDomainFactory.hrl \
- CosEventDomainAdmin_EventDomain.hrl
-
-EXTERNAL_GEN_HRL_FILES = \
- $(GEN_HRL_FILES:%=$(EXTERNAL_INC_PATH)/%)
-
-
-TARGET_FILES = \
- $(GEN_ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR)) \
- $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-GEN_FILES = $(GEN_HRL_FILES) $(GEN_ERL_FILES)
-
-IDL_FILES = \
- CosEventDomainAdmin.idl
-
-APPUP_FILE = cosEventDomain.appup
-APPUP_SRC = $(APPUP_FILE).src
-APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
-
-APP_FILE = cosEventDomain.app
-APP_SRC = $(APP_FILE).src
-APP_TARGET = $(EBIN)/$(APP_FILE)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += \
- -pa $(ERL_TOP)/lib/cosEventDomain/ebin \
- -pa $(ERL_TOP)/lib/cosEventDomain/include \
- -pa $(ERL_TOP)/lib/cosNotification/include \
- -pa $(ERL_TOP)/lib/cosNotification/ebin \
- -pa $(ERL_TOP)/lib/ic/ebin \
- -I$(ERL_TOP)/lib/cosNotification/include \
- -I$(ERL_TOP)/lib/cosNotification/ebin \
- -I$(ERL_TOP)/lib/cosNotification/src \
- -I$(ERL_TOP)/lib/cosEvent/src \
- -I$(ERL_TOP)/lib/cosEventDomain/include
-# The -pa option is just used temporary until erlc can handle
-# includes from other directories than ../include .
-ERL_COMPILE_FLAGS += \
- $(ERL_IDL_FLAGS) \
- -pa $(ERL_TOP)/lib/cosEventDomain/include \
- -pa $(ERL_TOP)/lib/cosNotification/ebin \
- -pa $(ERL_TOP)/lib/cosNotification/include \
- -pa $(ERL_TOP)/lib/cosNotification/src \
- -I$(ERL_TOP)/lib/cosEventDomain/include \
- -I$(ERL_TOP)/lib/cosNotification/ebin \
- -I$(ERL_TOP)/lib/cosNotification/include \
- -I$(ERL_TOP)/lib/cosNotification/src \
- -I$(ERL_TOP)/lib/cosEvent/src \
- -I$(ERL_TOP)/lib/cosEvent/include \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,app_vsn,"cosEventDomain_$(COSEVENTDOMAIN_VSN)"}'
-
-YRL_FLAGS =
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
-
-debug:
- @${MAKE} TYPE=debug opt
-
-clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
- rm -f errs core *~
-
-$(APP_TARGET): $(APP_SRC)
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $(APP_SRC) > $(APP_TARGET)
-$(APPUP_TARGET): $(APPUP_SRC)
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $(APPUP_SRC) > $(APPUP_TARGET)
-
-docs:
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-IDL-GENERATED: CosEventDomainAdmin.idl
- $(gen_verbose)erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosEventDomainAdmin.cfg"}' CosEventDomainAdmin.idl
- $(V_at)mv $(GEN_HRL_FILES) $(EXTERNAL_INC_PATH)
- $(V_at)>IDL-GENERATED
-
-$(GEN_FILES): IDL-GENERATED
-
-$(TARGET_FILES): IDL-GENERATED
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DATA) ../info "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
- $(INSTALL_DIR) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILES) "$(RELSYSDIR)/src"
- $(INSTALL_DIR) "$(RELSYSDIR)/include"
- $(INSTALL_DATA) $(EXTERNAL_GEN_HRL_FILES) "$(RELSYSDIR)/include"
-
-
-release_docs_spec:
-
-
-
-
-
diff --git a/lib/cosEventDomain/src/cosEventDomain.app.src b/lib/cosEventDomain/src/cosEventDomain.app.src
deleted file mode 100644
index f218ac853e..0000000000
--- a/lib/cosEventDomain/src/cosEventDomain.app.src
+++ /dev/null
@@ -1,33 +0,0 @@
-{application, cosEventDomain,
- [{description, "The Erlang CosEventDomain application"},
- {vsn, "%VSN%"},
- {modules,
- [
- 'CosEventDomainAdmin_EventDomainFactory_impl',
- 'CosEventDomainAdmin_EventDomain_impl',
- 'cosEventDomainApp',
- 'oe_CosEventDomainAdmin',
- 'CosEventDomainAdmin',
- 'CosEventDomainAdmin_DiamondSeq',
- 'CosEventDomainAdmin_AlreadyExists',
- 'CosEventDomainAdmin_DomainIDSeq',
- 'CosEventDomainAdmin_Connection',
- 'CosEventDomainAdmin_ConnectionIDSeq',
- 'CosEventDomainAdmin_ConnectionNotFound',
- 'CosEventDomainAdmin_CycleCreationForbidden',
- 'CosEventDomainAdmin_CycleSeq',
- 'CosEventDomainAdmin_DiamondCreationForbidden',
- 'CosEventDomainAdmin_DomainNotFound',
- 'CosEventDomainAdmin_EventDomain',
- 'CosEventDomainAdmin_EventDomainFactory',
- 'CosEventDomainAdmin_MemberIDSeq',
- 'CosEventDomainAdmin_RouteSeq'
- ]
- },
- {registered, []},
- {applications, [orber, stdlib, kernel]},
- {env, []},
- {mod, {cosEventDomainApp, []}},
- {runtime_dependencies, ["stdlib-2.0","orber-3.6.27","kernel-3.0","erts-7.0",
- "cosNotification-1.1.21"]}
-]}.
diff --git a/lib/cosEventDomain/src/cosEventDomain.appup.src b/lib/cosEventDomain/src/cosEventDomain.appup.src
deleted file mode 100644
index d69b2ef20c..0000000000
--- a/lib/cosEventDomain/src/cosEventDomain.appup.src
+++ /dev/null
@@ -1,6 +0,0 @@
-{"%VSN%",
- [
- ],
- [
- ]
-}
diff --git a/lib/cosEventDomain/src/cosEventDomainApp.erl b/lib/cosEventDomain/src/cosEventDomainApp.erl
deleted file mode 100644
index be7c2f518a..0000000000
--- a/lib/cosEventDomain/src/cosEventDomainApp.erl
+++ /dev/null
@@ -1,341 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%--------------------------------------------------------------------
-%% File : cosEventDomainApp.erl
-%% Purpose :
-%%--------------------------------------------------------------------
-
--module(cosEventDomainApp).
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
--include_lib("cosNotification/include/CosNotification.hrl").
-%% Application files
--include("cosEventDomainApp.hrl").
--include("CosEventDomainAdmin.hrl").
-
-%%--------------- EXPORTS ------------------------------------
-%% External MISC
--export([get_option/3,
- create_id/1,
- is_debug_compiled/0,
- install/0,
- uninstall/0,
- start_factory/0,
- start_factory/1,
- start_factory_link/0,
- start_factory_link/1,
- stop_factory/1,
- start/0,
- stop/0,
- create_link/3,
- get_qos/1,
- get_admin/1]).
-
-%% Application callbacks
--export([start/2, init/1, stop/1]).
-
-%%--------------- DEFINES ------------------------------------
-
--define(SUPERVISOR_NAME, oe_cosEventDomainSup).
--define(SUP_FLAG, {simple_one_for_one,50,10}).
-
--define(SUP_SPEC(Name, Args),
- ['CosEventDomainAdmin_EventDomain',Args,
- [{sup_child, true}, {regname, {global, Name}}]]).
--define(SUP_CHILD,
- {"oe_EventDomainChild",
- {cosEventDomainApp,create_link, []},
- transient,100000,worker,
- ['CosEventDomainAdmin_EventDomain']}).
-
-
--define(DEFAULT_OPTIONS, []).
-
-%%--------------- DEFINITIONS OF CONSTANTS -------------------
-%%--------------- EXTERNAL MISC FUNCTIONS --------------------
-%%-----------------------------------------------------------%
-%% function : install
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-install() ->
- oe_CosEventDomainAdmin:oe_register().
-
-%%-----------------------------------------------------------%
-%% function : uninstall
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-uninstall() ->
- oe_CosEventDomainAdmin:oe_unregister().
-
-%%-----------------------------------------------------------%
-%% function : start/stop
-%% Arguments:
-%% Returns :
-%% Effect : Starts or stops the cosTime application.
-%%------------------------------------------------------------
-
-start() ->
- application:start(cosEventDomain).
-stop() ->
- application:stop(cosEventDomain).
-
-%%-----------------------------------------------------------%
-%% function : start
-%% Arguments: Type - see module application
-%% Arg - see module application
-%% Returns :
-%% Effect : Module callback for application
-%%------------------------------------------------------------
-
-start(_, _) ->
- supervisor:start_link({local, ?SUPERVISOR_NAME}, cosEventDomainApp, app_init).
-
-
-%%-----------------------------------------------------------%
-%% function : stop
-%% Arguments: Arg - see module application
-%% Returns :
-%% Effect : Module callback for application
-%%------------------------------------------------------------
-
-stop(_) ->
- ok.
-
-%%-----------------------------------------------------------%
-%% function : start_channel
-%% Arguments: -
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-start_factory() ->
- start_factory(?DEFAULT_OPTIONS).
-
-start_factory(Options) when is_list(Options) ->
- 'CosEventDomainAdmin_EventDomainFactory':oe_create(Options);
-start_factory(Options) ->
- orber:dbg("[~p] cosEventDomainApp:start_factory(~p);~n"
- "Options not correct.",
- [?LINE, Options], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------%
-%% function : start_channel
-%% Arguments: -
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-start_factory_link() ->
- start_factory_link(?DEFAULT_OPTIONS).
-
-start_factory_link(Options) when is_list(Options) ->
- 'CosEventDomainAdmin_EventDomainFactory':oe_create_link(Options);
-start_factory_link(Options) ->
- orber:dbg("[~p] cosEventDomainApp:start_factory_link(~p);~n"
- "Options not correct.",
- [?LINE, Options], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------%
-%% function : stop_factory
-%% Arguments: ChannelObj
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-stop_factory(ChannelObj) ->
- corba:dispose(ChannelObj).
-
-%%-----------------------------------------------------------%
-%% function : init
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-
-%% Starting using create_factory/X
-init(own_init) ->
- {ok,{?SUP_FLAG, [?SUP_CHILD]}};
-%% When starting as an application.
-init(app_init) ->
- {ok,{?SUP_FLAG, [?SUP_CHILD]}}.
-
-
-%%------------------------------------------------------------
-%% function : create_link
-%% Arguments: Module - which Module to call
-%% Env/ArgList - ordinary oe_create arguments.
-%% Returns :
-%% Exception:
-%% Effect : Necessary since we want the supervisor to be a
-%% 'simple_one_for_one'. Otherwise, using for example,
-%% 'one_for_one', we have to call supervisor:delete_child
-%% to remove the childs startspecification from the
-%% supervisors internal state.
-%%------------------------------------------------------------
-create_link(Module, Env, ArgList) ->
- Module:oe_create_link(Env, ArgList).
-
-%%-----------------------------------------------------------%
-%% function : get_option
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-get_option(Key, OptionList, DefaultList) ->
- case lists:keysearch(Key, 1, OptionList) of
- {value,{Key,Value}} ->
- Value;
- _ ->
- case lists:keysearch(Key, 1, DefaultList) of
- {value,{Key,Value}} ->
- Value;
- _->
- {error, "Invalid option"}
- end
- end.
-
-%%------------------------------------------------------------
-%% function : create_id/1
-%% Arguments: CosEventDomainAdmin::DomainID (long)
-%% Returns : CosEventDomainAdmin::DomainID (long)
-%% Exception:
-%% Purpose :
-%%------------------------------------------------------------
-create_id(2147483647) ->
- -2147483648;
-create_id(OldID) ->
- OldID+1.
-
-%%------------------------------------------------------------
-%% function : get_qos
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-get_qos([]) ->
- [];
-get_qos(Properties) ->
- case get_qos(Properties, [], []) of
- {ok, Supported} ->
- Supported;
- {error, Unsupported} ->
- corba:raise(#'CosNotification_UnsupportedQoS'{qos_err = Unsupported})
- end.
-
-get_qos([], Supported, []) ->
- {ok, Supported};
-get_qos([], _, Unsupported) ->
- {error, Unsupported};
-get_qos([#'CosNotification_Property'{name = ?CycleDetection,
- value= #any{value = ?AuthorizeCycles}}|T],
- Supported, Unsupported) ->
- get_qos(T, [{?CycleDetection, ?AuthorizeCycles}|Supported], Unsupported);
-get_qos([#'CosNotification_Property'{name = ?CycleDetection,
- value= #any{value = ?ForbidCycles}}|T],
- Supported, Unsupported) ->
- get_qos(T, [{?CycleDetection, ?ForbidCycles}|Supported], Unsupported);
-get_qos([#'CosNotification_Property'{name = ?CycleDetection}|T],
- Supported, Unsupported) ->
- %% Illegal value supplied.
- get_qos(T, Supported,
- [#'CosNotification_PropertyError'
- {code = 'UNSUPPORTED_VALUE',
- name = ?CycleDetection,
- available_range = #'CosNotification_PropertyRange'
- {low_val=any:create(orber_tc:short(), ?AuthorizeCycles),
- high_val=any:create(orber_tc:short(), ?ForbidCycles)}}|Unsupported]);
-get_qos([#'CosNotification_Property'{name = ?DiamondDetection,
- value= #any{value = ?AuthorizeDiamonds}}|T],
- Supported, Unsupported) ->
- get_qos(T, [{?DiamondDetection, ?AuthorizeDiamonds}|Supported], Unsupported);
-get_qos([#'CosNotification_Property'{name = ?DiamondDetection,
- value= #any{value = ?ForbidDiamonds}}|T],
- Supported, Unsupported) ->
- get_qos(T, [{?DiamondDetection, ?ForbidDiamonds}|Supported], Unsupported);
-get_qos([#'CosNotification_Property'{name = ?DiamondDetection}|T],
- Supported, Unsupported) ->
- %% Illegal value supplied.
- get_qos(T, Supported,
- [#'CosNotification_PropertyError'
- {code = 'UNSUPPORTED_VALUE',
- name = ?DiamondDetection,
- available_range = #'CosNotification_PropertyRange'
- {low_val=any:create(orber_tc:short(), ?AuthorizeDiamonds),
- high_val=any:create(orber_tc:short(), ?ForbidDiamonds)
- }} | Unsupported]);
-get_qos([#'CosNotification_Property'{name = Name}|T], Supported, Unsupported) ->
- %% Unknown QoS supplied.
- get_qos(T, Supported,
- [#'CosNotification_PropertyError'
- {code = 'BAD_PROPERTY',
- name = Name,
- available_range = #'CosNotification_PropertyRange'
- {low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)}} | Unsupported]).
-
-%%------------------------------------------------------------
-%% function : get_admin
-%% Arguments:
-%% Returns : {"EXCEPTION', #'CosNotification_PropertyError'{}}
-%% Exception:
-%% Effect : No Admin supported.
-%%------------------------------------------------------------
-get_admin([]) ->
- [];
-get_admin(Properties) ->
- get_admin(Properties, []).
-
-get_admin([], Unsupported) ->
- corba:raise(#'CosNotification_UnsupportedAdmin'{admin_err = Unsupported});
-get_admin([#'CosNotification_Property'{name = Name}|T], Unsupported) ->
- %% Unknown QoS supplied.
- get_admin(T, [#'CosNotification_PropertyError'
- {code = 'BAD_PROPERTY',
- name = Name,
- available_range = #'CosNotification_PropertyRange'
- {low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)}} | Unsupported]).
-
-
-%%------------------------------------------------------------
-%% function : is_debug_compiled
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
--ifdef(debug).
- is_debug_compiled() -> true.
--else.
- is_debug_compiled() -> false.
--endif.
-
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosEventDomain/src/cosEventDomainApp.hrl b/lib/cosEventDomain/src/cosEventDomainApp.hrl
deleted file mode 100644
index 6df20692be..0000000000
--- a/lib/cosEventDomain/src/cosEventDomainApp.hrl
+++ /dev/null
@@ -1,70 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : cosEventDomainApp.hrl
-%% Purpose :
-%%----------------------------------------------------------------------
-
-
-%%--------------- INCLUDES -----------------------------------
-%% External
-
-%% Local
-
--define(write_ErrorMsg(Txt, Arg),
-error_logger:error_msg("============== CosEventDomain =============~n"
- Txt
- "===========================================~n",
- Arg)).
-
--define(DEBUG_LEVEL, 3).
-
--ifdef(debug).
--define(DBG(F,A),
- io:format("[LINE: ~p MODULE: ~p] "++F,[?LINE, ?MODULE]++A)).
--else.
--define(DBG(F,A), ok).
--endif.
-
-%%%%%% WARNING! These definitions are defined in the CosEventDomainAdmin.idl
-%%%%%% file. If the specification is changed so must the definitions!!
-%%%%%% We use this approach to be able to use them as guards.
-
-%%%% Constant: 'CycleDetection'
--define(CycleDetection, "CycleDetection").
-
-%%%% Constant: 'AuthorizeCycles'
--define(AuthorizeCycles, 0).
-
-%%%% Constant: 'ForbidCycles'
--define(ForbidCycles, 1).
-
-%%%% Constant: 'DiamondDetection'
--define(DiamondDetection, "DiamondDetection").
-
-%%%% Constant: 'AuthorizeDiamonds'
--define(AuthorizeDiamonds, 0).
-
-%%%% Constant: 'ForbidDiamonds'
--define(ForbidDiamonds, 1).
-
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosEventDomain/test/Makefile b/lib/cosEventDomain/test/Makefile
deleted file mode 100644
index 1841676be7..0000000000
--- a/lib/cosEventDomain/test/Makefile
+++ /dev/null
@@ -1,104 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2001-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(COSEVENTDOMAIN_VSN)
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/cosEventDomain_test
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-TEST_SPEC_FILE = cosEventDomain.spec
-COVER_FILE = cosEventDomain.cover
-
-
-MODULES = \
- event_domain_SUITE \
- generated_SUITE
-
-ERL_FILES = $(MODULES:%=%.erl)
-
-HRL_FILES =
-
-SUITE_TARGET_FILES = $(MODULES:%=%.$(EMULATOR))
-
-TARGET_FILES = \
- $(SUITE_TARGET_FILES)
-
-# ----------------------------------------------------
-# PROGRAMS
-# ----------------------------------------------------
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/orber/ebin -pa $(ERL_TOP)/lib/ic/ebin
-
-ERL_COMPILE_FLAGS += \
- $(ERL_IDL_FLAGS) \
- -pa $(ERL_TOP)/lib/cosEventDomain/ebin \
- -pa $(ERL_TOP)/lib/cosEventDomain/include \
- -pa $(ERL_TOP)/lib/cosNotification/ebin \
- -pa $(ERL_TOP)/lib/cosNotification/include \
- -I$(ERL_TOP)/lib/cosEventDomain/include \
- -I$(ERL_TOP)/lib/cosNotification/include \
- -I$(ERL_TOP)/lib/cosNotification/ebin
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-tests debug opt: $(TARGET_FILES)
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f errs core *~
-
-
-docs:
-
-# ----------------------------------------------------
-# Special Targets
-# ----------------------------------------------------
-
-# ----------------------------------------------------
-# Release Targets
-# ----------------------------------------------------
-# We don't copy generated intermediate erlang and hrl files
-
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec:
-
-release_docs_spec:
-
-release_tests_spec: tests
- $(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(TEST_SPEC_FILE) \
- $(COVER_FILE) $(ERL_FILES) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(SUITE_TARGET_FILES) "$(RELSYSDIR)"
-
diff --git a/lib/cosEventDomain/test/cosEventDomain.cover b/lib/cosEventDomain/test/cosEventDomain.cover
deleted file mode 100644
index f87f6d97bf..0000000000
--- a/lib/cosEventDomain/test/cosEventDomain.cover
+++ /dev/null
@@ -1,2 +0,0 @@
-{incl_app,cosEventDomain,details}.
-
diff --git a/lib/cosEventDomain/test/cosEventDomain.spec b/lib/cosEventDomain/test/cosEventDomain.spec
deleted file mode 100644
index bcee74c5f1..0000000000
--- a/lib/cosEventDomain/test/cosEventDomain.spec
+++ /dev/null
@@ -1 +0,0 @@
-{suites,"../cosEventDomain_test",all}.
diff --git a/lib/cosEventDomain/test/event_domain_SUITE.erl b/lib/cosEventDomain/test/event_domain_SUITE.erl
deleted file mode 100644
index 031b7726c5..0000000000
--- a/lib/cosEventDomain/test/event_domain_SUITE.erl
+++ /dev/null
@@ -1,464 +0,0 @@
-%%-----------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-
--module(event_domain_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("cosNotification/include/CosNotifyChannelAdmin.hrl").
--include_lib("cosNotification/include/CosNotification.hrl").
-
--include_lib("cosEventDomain/include/CosEventDomainAdmin.hrl").
--include_lib("cosEventDomain/src/cosEventDomainApp.hrl").
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
-
--define(default_timeout, test_server:minutes(5)).
-
-
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
- event_domain_api/1, event_domain_factory_api/1,
- cases/0, init_per_suite/1, end_per_suite/1,
- init_per_testcase/2, end_per_testcase/2, app_test/1]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-cases() ->
- [event_domain_api, event_domain_factory_api, app_test].
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) when is_list(Config) ->
- mnesia:delete_schema([node()]),
- mnesia:create_schema([node()]),
- ok = corba:orb_init([{flags, 16#02},
- {orber_debug_level, 10}]),
- orber:install([node()]),
- application:start(mnesia),
- application:start(orber),
- cosEventApp:install(),
- cosEventApp:start(),
- cosNotificationApp:install(),
- cosNotificationApp:start(),
- cosEventDomainApp:install(),
- cosEventDomainApp:start(),
- Config.
-
-end_per_suite(Config) when is_list(Config) ->
- cosEventDomainApp:stop(),
- cosEventDomainApp:uninstall(),
- cosNotificationApp:stop(),
- cosNotificationApp:uninstall(),
- cosEventApp:stop(),
- cosEventApp:uninstall(),
- application:stop(orber),
- application:stop(mnesia),
- mnesia:delete_schema([node()]),
- Config.
-
-%%-----------------------------------------------------------------
-%% Tests app file
-%%-----------------------------------------------------------------
-app_test(_Config) ->
- ok=test_server:app_test(cosEventDomain),
- ok.
-
-
-%% Testing the CosEventDomain Domain API
-event_domain_api(_Config) ->
-
- %% We will setup a cluster looking like:
- %% 7-8--->
- %% /
- %% 2 - 4 6->
- %% \ /
- %% 5---9-1-3
-
- %% 2-4
- %% 4-1
- %% 1-3
- %% 3-6
- %% 5-9
- %% 9-1
- %% 4-7
- %% 7-8
-
-
- ChFac = ?match({_,key,_,_,_,_},
- cosNotificationApp:start_global_factory([{pullInterval,1}])),
- {Ch0,_} = ?match({{_,key,_,_,_,_}, _},
- 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(ChFac, [], [])),
- Fac = ?match({_,key,_,_,_,_},
- cosEventDomainApp:start_factory()),
- {ED, _} = ?match({{_,key,_,_,_,_}, _},
- 'CosEventDomainAdmin_EventDomainFactory':create_event_domain(Fac, [], [])),
- ID0 = 'CosEventDomainAdmin_EventDomain':add_channel(ED, Ch0),
- ?match(Ch0, 'CosEventDomainAdmin_EventDomain':get_channel(ED, ID0)),
- ?match([0], 'CosEventDomainAdmin_EventDomain':get_all_channels(ED)),
- ?match({'EXCEPTION',{'CosNotifyChannelAdmin_ChannelNotFound',_}},
- 'CosEventDomainAdmin_EventDomain':get_channel(ED, 100)),
- ?match({'EXCEPTION',{'CosNotifyChannelAdmin_ChannelNotFound',_}},
- 'CosEventDomainAdmin_EventDomain':remove_channel(ED, 100)),
- ?match(ok, 'CosEventDomainAdmin_EventDomain':remove_channel(ED, 0)),
- ?match([], 'CosEventDomainAdmin_EventDomain':get_all_channels(ED)),
- ?match({'EXCEPTION',{'CosNotifyChannelAdmin_ChannelNotFound',_}},
- 'CosEventDomainAdmin_EventDomain':remove_channel(ED, 0)),
-
- %% Create a new event channel.
- {Ch1,_} = ?match({{_,key,_,_,_,_}, _},
- 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(ChFac, [], [])),
- {Ch2,_} = ?match({{_,key,_,_,_,_}, _},
- 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(ChFac, [], [])),
- {Ch3,_} = ?match({{_,key,_,_,_,_}, _},
- 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(ChFac, [], [])),
- {Ch4,_} = ?match({{_,key,_,_,_,_}, _},
- 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(ChFac, [], [])),
- {Ch5,_} = ?match({{_,key,_,_,_,_}, _},
- 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(ChFac, [], [])),
- {Ch6,_} = ?match({{_,key,_,_,_,_}, _},
- 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(ChFac, [], [])),
- {Ch7,_} = ?match({{_,key,_,_,_,_}, _},
- 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(ChFac, [], [])),
- {Ch8,_} = ?match({{_,key,_,_,_,_}, _},
- 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(ChFac, [], [])),
- {Ch9,_} = ?match({{_,key,_,_,_,_}, _},
- 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(ChFac, [], [])),
-
- ID1 = 'CosEventDomainAdmin_EventDomain':add_channel(ED, Ch1),
- ID2 = 'CosEventDomainAdmin_EventDomain':add_channel(ED, Ch2),
- ID3 = 'CosEventDomainAdmin_EventDomain':add_channel(ED, Ch3),
- ID4 = 'CosEventDomainAdmin_EventDomain':add_channel(ED, Ch4),
- ID5 = 'CosEventDomainAdmin_EventDomain':add_channel(ED, Ch5),
- ID6 = 'CosEventDomainAdmin_EventDomain':add_channel(ED, Ch6),
- ID7 = 'CosEventDomainAdmin_EventDomain':add_channel(ED, Ch7),
- ID8 = 'CosEventDomainAdmin_EventDomain':add_channel(ED, Ch8),
- ID9 = 'CosEventDomainAdmin_EventDomain':add_channel(ED, Ch9),
- ?match([_,_,_,_,_,_,_,_,_],
- 'CosEventDomainAdmin_EventDomain':get_all_channels(ED)),
-
- ?match([], 'CosEventDomainAdmin_EventDomain':get_all_connections(ED)),
- C1 = #'CosEventDomainAdmin_Connection'{supplier_id=ID2,
- consumer_id=ID4,
- ctype='STRUCTURED_EVENT',
- notification_style='Pull'},
- C2 = #'CosEventDomainAdmin_Connection'{supplier_id=ID4,
- consumer_id=ID1,
- ctype='ANY_EVENT',
- notification_style='Push'},
- C3 = #'CosEventDomainAdmin_Connection'{supplier_id=ID1,
- consumer_id=ID3,
- ctype='ANY_EVENT',
- notification_style='Pull'},
- C4 = #'CosEventDomainAdmin_Connection'{supplier_id=ID3,
- consumer_id=ID6,
- ctype='STRUCTURED_EVENT',
- notification_style='Push'},
- C5 = #'CosEventDomainAdmin_Connection'{supplier_id=ID5,
- consumer_id=ID9,
- ctype='ANY_EVENT',
- notification_style='Pull'},
- C6 = #'CosEventDomainAdmin_Connection'{supplier_id=ID9,
- consumer_id=ID1,
- ctype='ANY_EVENT',
- notification_style='Push'},
- C7 = #'CosEventDomainAdmin_Connection'{supplier_id=ID4,
- consumer_id=ID7,
- ctype='STRUCTURED_EVENT',
- notification_style='Pull'},
- C8 = #'CosEventDomainAdmin_Connection'{supplier_id=ID7,
- consumer_id=ID8,
- ctype='ANY_EVENT',
- notification_style='Push'},
- C9 = #'CosEventDomainAdmin_Connection'{supplier_id=ID8,
- consumer_id=ID4,
- ctype='ANY_EVENT',
- notification_style='Pull'},
- C10 = #'CosEventDomainAdmin_Connection'{supplier_id=ID5,
- consumer_id=ID4,
- ctype='ANY_EVENT',
- notification_style='Pull'},
- C11 = #'CosEventDomainAdmin_Connection'{supplier_id=ID4,
- consumer_id=ID6,
- ctype='ANY_EVENT',
- notification_style='Pull'},
- C12 = #'CosEventDomainAdmin_Connection'{supplier_id=ID8,
- consumer_id=ID6,
- ctype='ANY_EVENT',
- notification_style='Pull'},
-
- CID1 = 'CosEventDomainAdmin_EventDomain':add_connection(ED, C1),
- ?match([CID1], 'CosEventDomainAdmin_EventDomain':get_all_connections(ED)),
- _CID2 = 'CosEventDomainAdmin_EventDomain':add_connection(ED, C2),
- ?match([_,_],
- 'CosEventDomainAdmin_EventDomain':get_all_connections(ED)),
- _CID3 = 'CosEventDomainAdmin_EventDomain':add_connection(ED, C3),
- ?match([_,_,_],
- 'CosEventDomainAdmin_EventDomain':get_all_connections(ED)),
- _CID4 = 'CosEventDomainAdmin_EventDomain':add_connection(ED, C4),
- ?match([_,_,_,_],
- 'CosEventDomainAdmin_EventDomain':get_all_connections(ED)),
- _CID5 = 'CosEventDomainAdmin_EventDomain':add_connection(ED, C5),
- ?match([_,_,_,_,_],
- 'CosEventDomainAdmin_EventDomain':get_all_connections(ED)),
- _CID6 = 'CosEventDomainAdmin_EventDomain':add_connection(ED, C6),
- ?match([_,_,_,_,_,_],
- 'CosEventDomainAdmin_EventDomain':get_all_connections(ED)),
- CID7 = 'CosEventDomainAdmin_EventDomain':add_connection(ED, C7),
- ?match([_,_,_,_,_,_,_],
- 'CosEventDomainAdmin_EventDomain':get_all_connections(ED)),
- _CID8 = 'CosEventDomainAdmin_EventDomain':add_connection(ED, C8),
- ?match([_,_,_,_,_,_,_,_],
- 'CosEventDomainAdmin_EventDomain':get_all_connections(ED)),
-
- ?match({'EXCEPTION',{'CosEventDomainAdmin_AlreadyExists', _}},
- 'CosEventDomainAdmin_EventDomain':add_connection(ED, C8)),
- %% No cycles should exist.
- ?match([], 'CosEventDomainAdmin_EventDomain':get_cycles(ED)),
-
- ?match([_, _], 'CosEventDomainAdmin_EventDomain':get_qos(ED)),
- AllowCyclic = #'CosNotification_Property'{name=?CycleDetection,
- value=any:create(orber_tc:short(),
- ?AuthorizeCycles)},
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosEventDomainAdmin_EventDomain':set_qos(ED, [AllowCyclic])),
- ForbidCyclic = #'CosNotification_Property'{name=?CycleDetection,
- value=any:create(orber_tc:short(),
- ?ForbidCycles)},
- %% The same as before; must work.
- ?match(ok, 'CosEventDomainAdmin_EventDomain':set_qos(ED, [ForbidCyclic])),
-
- AllowDiamonds = #'CosNotification_Property'{name=?DiamondDetection,
- value=any:create(orber_tc:short(),
- ?AuthorizeDiamonds)},
- %% Since no diamonds allowed before this is always ok.
- ?match(ok, 'CosEventDomainAdmin_EventDomain':set_qos(ED, [AllowDiamonds])),
-
- ?match([_, _], 'CosEventDomainAdmin_EventDomain':get_qos(ED)),
-
- ForbidDiamonds = #'CosNotification_Property'{name=?DiamondDetection,
- value=any:create(orber_tc:short(),
- ?ForbidDiamonds)},
- %% No diamonds created before. Hence, will work.
- ?match(ok, 'CosEventDomainAdmin_EventDomain':set_qos(ED, [ForbidDiamonds])),
-
- ?match([_, _], 'CosEventDomainAdmin_EventDomain':get_qos(ED)),
-
- ?match({ok, [_]}, 'CosEventDomainAdmin_EventDomain':validate_qos(ED,
- [ForbidDiamonds,
- ForbidCyclic])),
- %% No diamonds exists, hence, this is ok.
- ?match({ok, [_]}, 'CosEventDomainAdmin_EventDomain':validate_qos(ED,
- [AllowDiamonds,
- ForbidCyclic])),
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosEventDomainAdmin_EventDomain':validate_qos(ED, [ForbidDiamonds,
- AllowCyclic])),
-
- %% Since the ED is started is asyclic we may not succeed with this invokation.
- ?match({'EXCEPTION',{'CosEventDomainAdmin_CycleCreationForbidden',_,_}},
- 'CosEventDomainAdmin_EventDomain':add_connection(ED, C9)),
- ?match([], 'CosEventDomainAdmin_EventDomain':get_offer_channels(ED, ID2)),
-
- ?match([2], 'CosEventDomainAdmin_EventDomain':get_offer_channels(ED, ID4)),
- ?match([_,_,_], 'CosEventDomainAdmin_EventDomain':get_offer_channels(ED, ID8)),
- ?match({'EXCEPTION',{'CosNotifyChannelAdmin_ChannelNotFound',_}},
- 'CosEventDomainAdmin_EventDomain':get_offer_channels(ED, 100)),
- ?match([], 'CosEventDomainAdmin_EventDomain':get_subscription_channels(ED, ID8)),
- ?match([_,_,_,_,_],
- 'CosEventDomainAdmin_EventDomain':get_subscription_channels(ED, ID4)),
- ?match([_,_,_,_,_,_],
- 'CosEventDomainAdmin_EventDomain':get_subscription_channels(ED, ID2)),
- ?match({'EXCEPTION',{'CosNotifyChannelAdmin_ChannelNotFound',_}},
- 'CosEventDomainAdmin_EventDomain':get_subscription_channels(ED, 100)),
- Nil = corba:create_nil_objref(),
-
- P2=?match({_,key,_,_,_,_},
- 'CosEventDomainAdmin_EventDomain':connect_push_supplier_with_id(ED, Nil, ID2)),
- P7=?match({_,key,_,_,_,_},
- 'CosEventDomainAdmin_EventDomain':connect_push_supplier_with_id(ED, Nil, ID7)),
- P8=?match({_,key,_,_,_,_},
- 'CosEventDomainAdmin_EventDomain':connect_pull_consumer_with_id(ED, Nil, ID8)),
- P6=?match({_,key,_,_,_,_},
- 'CosEventDomainAdmin_EventDomain':connect_pull_consumer_with_id(ED, Nil, ID6)),
- E1 = #any{typecode=tk_long, value=1},
- E2 = #any{typecode=tk_long, value=2},
-
- ?match(ok, 'CosNotifyChannelAdmin_ProxyPushConsumer':push(P2, E1)),
- ?match(E1, 'CosNotifyChannelAdmin_ProxyPullSupplier':pull(P8)),
- ?match(E1, 'CosNotifyChannelAdmin_ProxyPullSupplier':pull(P6)),
- ?match(ok, 'CosNotifyChannelAdmin_ProxyPushConsumer':push(P7, E2)),
- ?match(E2, 'CosNotifyChannelAdmin_ProxyPullSupplier':pull(P8)),
- timer:sleep(10000),
- ?match({_,false}, 'CosNotifyChannelAdmin_ProxyPullSupplier':try_pull(P6)),
-
- ?match(ok, 'CosEventDomainAdmin_EventDomain':remove_connection(ED, CID7)),
-
- ?match({'EXCEPTION',{'CosEventDomainAdmin_ConnectionNotFound',_}},
- 'CosEventDomainAdmin_EventDomain':remove_connection(ED, CID7)),
-
- ?match({'EXCEPTION',{'CosEventDomainAdmin_ConnectionNotFound',_}},
- 'CosEventDomainAdmin_EventDomain':remove_connection(ED, 100)),
-
- ?match([], 'CosEventDomainAdmin_EventDomain':get_offer_channels(ED, ID7)),
- ?match([2], 'CosEventDomainAdmin_EventDomain':get_offer_channels(ED, ID4)),
-
- ?match([8], 'CosEventDomainAdmin_EventDomain':get_subscription_channels(ED, ID7)),
- ?match([_,_,_], 'CosEventDomainAdmin_EventDomain':get_subscription_channels(ED, ID4)),
-
- CID10 = ?match(8, 'CosEventDomainAdmin_EventDomain':add_connection(ED, C7)),
-
- %% Now we'll check diamond management.
- %% Currently it should not be possible to create a diamond (due to QoS-setting).
- ?match({'EXCEPTION',{'CosEventDomainAdmin_DiamondCreationForbidden',_,_}},
- 'CosEventDomainAdmin_EventDomain':add_connection(ED, C11)),
- ?match({'EXCEPTION',{'CosEventDomainAdmin_DiamondCreationForbidden',_,_}},
- 'CosEventDomainAdmin_EventDomain':add_connection(ED, C10)),
- ?match({'EXCEPTION',{'CosEventDomainAdmin_DiamondCreationForbidden',_,_}},
- 'CosEventDomainAdmin_EventDomain':add_connection(ED, C12)),
- ?match(ok, 'CosEventDomainAdmin_EventDomain':set_qos(ED, [AllowDiamonds])),
-
- CID11 = ?match(9, 'CosEventDomainAdmin_EventDomain':add_connection(ED, C10)),
- ?match([_,_,_,_,_,_,_,_,_],
- 'CosEventDomainAdmin_EventDomain':get_all_connections(ED)),
- ?match([_], 'CosEventDomainAdmin_EventDomain':get_diamonds(ED)),
-
- CID12 = ?match(10, 'CosEventDomainAdmin_EventDomain':add_connection(ED, C11)),
- ?match([_, _, _], 'CosEventDomainAdmin_EventDomain':get_diamonds(ED)),
-
- CID13 = ?match(11, 'CosEventDomainAdmin_EventDomain':add_connection(ED, C12)),
-
- ?match([_, _, _], 'CosEventDomainAdmin_EventDomain':get_diamonds(ED)),
-
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosEventDomainAdmin_EventDomain':set_qos(ED, [ForbidDiamonds])),
-
- ?match(ok, 'CosEventDomainAdmin_EventDomain':remove_connection(ED, CID10)),
- ?match(ok, 'CosEventDomainAdmin_EventDomain':remove_connection(ED, CID11)),
- ?match(ok, 'CosEventDomainAdmin_EventDomain':remove_connection(ED, CID12)),
- ?match(ok, 'CosEventDomainAdmin_EventDomain':remove_connection(ED, CID13)),
- ?match(ok, 'CosEventDomainAdmin_EventDomain':set_qos(ED, [ForbidDiamonds])),
- ?match([_, _], 'CosEventDomainAdmin_EventDomain':get_qos(ED)),
- ?match({'EXCEPTION',{'CosEventDomainAdmin_DiamondCreationForbidden',_,_}},
- 'CosEventDomainAdmin_EventDomain':add_connection(ED, C10)),
-
- ?match(ok, 'CosEventDomainAdmin_EventDomain':destroy(ED)),
-
- ok.
-
-%% Testing the CosEventDomain Factory API
-event_domain_factory_api(_Config) ->
-
- Cyclic = #'CosNotification_Property'{name=?CycleDetection,
- value=any:create(orber_tc:short(),
- ?ForbidCycles)},
-
- BadProp = #'CosNotification_Property'{name="Wrong",
- value=any:create(orber_tc:short(),
- ?ForbidCycles)},
-
- BadQoSVal = #'CosNotification_Property'{name=?CycleDetection,
- value=any:create(orber_tc:short(),
- 10)},
-
- Fac = ?match({_,key,_,_,_,_},
- cosEventDomainApp:start_factory()),
- ?match([], 'CosEventDomainAdmin_EventDomainFactory':get_all_domains(Fac)),
- ?match({'EXCEPTION',{'CosEventDomainAdmin_DomainNotFound',_}},
- 'CosEventDomainAdmin_EventDomainFactory':get_event_domain(Fac, 0)),
- {ED,_} = 'CosEventDomainAdmin_EventDomainFactory':create_event_domain(Fac, [Cyclic], []),
- ?match([0], 'CosEventDomainAdmin_EventDomainFactory':get_all_domains(Fac)),
- ED = 'CosEventDomainAdmin_EventDomainFactory':get_event_domain(Fac, 0),
- ?match({'EXCEPTION',{'CosEventDomainAdmin_DomainNotFound',_}},
- 'CosEventDomainAdmin_EventDomainFactory':get_event_domain(Fac, 1)),
- corba:dispose(ED),
- timer:sleep(3000),
- ?match([], 'CosEventDomainAdmin_EventDomainFactory':get_all_domains(Fac)),
- ?match({'EXCEPTION',{'CosEventDomainAdmin_DomainNotFound',_}},
- 'CosEventDomainAdmin_EventDomainFactory':get_event_domain(Fac, 0)),
- {ED2,_} = ?match({{_,key,_,_,_,_}, _},
- 'CosEventDomainAdmin_EventDomainFactory':create_event_domain(Fac, [], [])),
- ?match([1], 'CosEventDomainAdmin_EventDomainFactory':get_all_domains(Fac)),
- ?match(ED2, 'CosEventDomainAdmin_EventDomainFactory':get_event_domain(Fac, 1)),
- corba:dispose(ED2),
-
- ?match({'EXCEPTION', {'CosNotification_UnsupportedQoS',_,_}},
- 'CosEventDomainAdmin_EventDomainFactory':create_event_domain(Fac, [BadProp], [])),
- ?match({'EXCEPTION',{'CosNotification_UnsupportedAdmin',_,_}},
- 'CosEventDomainAdmin_EventDomainFactory':create_event_domain(Fac, [], [BadProp])),
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosEventDomainAdmin_EventDomainFactory':create_event_domain(Fac, [BadQoSVal], [])),
- ?match({'EXCEPTION',{'CosNotification_UnsupportedAdmin',_,_}},
- 'CosEventDomainAdmin_EventDomainFactory':create_event_domain(Fac, [], [BadQoSVal])),
-
- corba:dispose(Fac),
- ok.
diff --git a/lib/cosEventDomain/test/generated_SUITE.erl b/lib/cosEventDomain/test/generated_SUITE.erl
deleted file mode 100644
index 172465da2f..0000000000
--- a/lib/cosEventDomain/test/generated_SUITE.erl
+++ /dev/null
@@ -1,384 +0,0 @@
-%%-----------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File : generated_SUITE.erl
-%% Purpose :
-%%-----------------------------------------------------------------
-
--module(generated_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
-
--define(default_timeout, test_server:minutes(3)).
-
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
--define(nomatch(Not, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- Not ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS);
- _ ->
- AcTuAlReS
- end
- end()).
-
-
--define(checktc(_Op),
- fun(TC) ->
- case orber_tc:check_tc(TC) of
- false ->
- io:format("###### ERROR ERROR ######~n~p - ~p~n", [Op, TC]),
- exit(TC);
- true ->
- true
- end
- end).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- ['CosEventDomainAdmin',
- 'CosEventDomainAdmin_DiamondSeq',
- 'CosEventDomainAdmin_AlreadyExists',
- 'CosEventDomainAdmin_DomainIDSeq',
- 'CosEventDomainAdmin_Connection',
- 'CosEventDomainAdmin_ConnectionIDSeq',
- 'CosEventDomainAdmin_ConnectionNotFound',
- 'CosEventDomainAdmin_CycleCreationForbidden',
- 'CosEventDomainAdmin_CycleSeq',
- 'CosEventDomainAdmin_DiamondCreationForbidden',
- 'CosEventDomainAdmin_DomainNotFound',
- 'CosEventDomainAdmin_MemberIDSeq',
- 'CosEventDomainAdmin_RouteSeq',
- 'CosEventDomainAdmin_EventDomainFactory',
- 'CosEventDomainAdmin_EventDomain'].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventDomainAdmin'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventDomainAdmin'(_) ->
- ?match("CycleDetection", 'CosEventDomainAdmin':'CycleDetection'()),
- ?match(0, 'CosEventDomainAdmin':'AuthorizeCycles'()),
- ?match(1, 'CosEventDomainAdmin':'ForbidCycles'()),
- ?match("DiamondDetection", 'CosEventDomainAdmin':'DiamondDetection'()),
- ?match(0, 'CosEventDomainAdmin':'AuthorizeDiamonds'()),
- ?match(1, 'CosEventDomainAdmin':'ForbidDiamonds'()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventDomainAdmin_DiamondSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventDomainAdmin_DiamondSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosEventDomainAdmin_DiamondSeq':tc())),
- ?match("IDL:omg.org/CosEventDomainAdmin/DiamondSeq:1.0",
- 'CosEventDomainAdmin_DiamondSeq':id()),
- ?match("CosEventDomainAdmin_DiamondSeq",
- 'CosEventDomainAdmin_DiamondSeq':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventDomainAdmin_AlreadyExists'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventDomainAdmin_AlreadyExists'(_) ->
- ?match(true, orber_tc:check_tc('CosEventDomainAdmin_AlreadyExists':tc())),
- ?match("IDL:omg.org/CosEventDomainAdmin/AlreadyExists:1.0",
- 'CosEventDomainAdmin_AlreadyExists':id()),
- ?match("CosEventDomainAdmin_AlreadyExists",
- 'CosEventDomainAdmin_AlreadyExists':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventDomainAdmin_DomainIDSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventDomainAdmin_DomainIDSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosEventDomainAdmin_DomainIDSeq':tc())),
- ?match("IDL:omg.org/CosEventDomainAdmin/DomainIDSeq:1.0",
- 'CosEventDomainAdmin_DomainIDSeq':id()),
- ?match("CosEventDomainAdmin_DomainIDSeq",
- 'CosEventDomainAdmin_DomainIDSeq':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventDomainAdmin_Connection'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventDomainAdmin_Connection'(_) ->
- ?match(true, orber_tc:check_tc('CosEventDomainAdmin_Connection':tc())),
- ?match("IDL:omg.org/CosEventDomainAdmin/Connection:1.0",
- 'CosEventDomainAdmin_Connection':id()),
- ?match("CosEventDomainAdmin_Connection",
- 'CosEventDomainAdmin_Connection':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventDomainAdmin_ConnectionIDSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventDomainAdmin_ConnectionIDSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosEventDomainAdmin_ConnectionIDSeq':tc())),
- ?match("IDL:omg.org/CosEventDomainAdmin/ConnectionIDSeq:1.0",
- 'CosEventDomainAdmin_ConnectionIDSeq':id()),
- ?match("CosEventDomainAdmin_ConnectionIDSeq",
- 'CosEventDomainAdmin_ConnectionIDSeq':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventDomainAdmin_ConnectionNotFound'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventDomainAdmin_ConnectionNotFound'(_) ->
- ?match(true, orber_tc:check_tc('CosEventDomainAdmin_ConnectionNotFound':tc())),
- ?match("IDL:omg.org/CosEventDomainAdmin/ConnectionNotFound:1.0",
- 'CosEventDomainAdmin_ConnectionNotFound':id()),
- ?match("CosEventDomainAdmin_ConnectionNotFound",
- 'CosEventDomainAdmin_ConnectionNotFound':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventDomainAdmin_CycleCreationForbidden'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventDomainAdmin_CycleCreationForbidden'(_) ->
- ?match(true, orber_tc:check_tc('CosEventDomainAdmin_CycleCreationForbidden':tc())),
- ?match("IDL:omg.org/CosEventDomainAdmin/CycleCreationForbidden:1.0",
- 'CosEventDomainAdmin_CycleCreationForbidden':id()),
- ?match("CosEventDomainAdmin_CycleCreationForbidden",
- 'CosEventDomainAdmin_CycleCreationForbidden':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventDomainAdmin_CycleSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventDomainAdmin_CycleSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosEventDomainAdmin_CycleSeq':tc())),
- ?match("IDL:omg.org/CosEventDomainAdmin/CycleSeq:1.0",
- 'CosEventDomainAdmin_CycleSeq':id()),
- ?match("CosEventDomainAdmin_CycleSeq",
- 'CosEventDomainAdmin_CycleSeq':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventDomainAdmin_DiamondCreationForbidden'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventDomainAdmin_DiamondCreationForbidden'(_) ->
- ?match(true, orber_tc:check_tc('CosEventDomainAdmin_DiamondCreationForbidden':tc())),
- ?match("IDL:omg.org/CosEventDomainAdmin/DiamondCreationForbidden:1.0",
- 'CosEventDomainAdmin_DiamondCreationForbidden':id()),
- ?match("CosEventDomainAdmin_DiamondCreationForbidden",
- 'CosEventDomainAdmin_DiamondCreationForbidden':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventDomainAdmin_DomainNotFound'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventDomainAdmin_DomainNotFound'(_) ->
- ?match(true, orber_tc:check_tc('CosEventDomainAdmin_DomainNotFound':tc())),
- ?match("IDL:omg.org/CosEventDomainAdmin/DomainNotFound:1.0",
- 'CosEventDomainAdmin_DomainNotFound':id()),
- ?match("CosEventDomainAdmin_DomainNotFound",
- 'CosEventDomainAdmin_DomainNotFound':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventDomainAdmin_MemberIDSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventDomainAdmin_MemberIDSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosEventDomainAdmin_MemberIDSeq':tc())),
- ?match("IDL:omg.org/CosEventDomainAdmin/MemberIDSeq:1.0",
- 'CosEventDomainAdmin_MemberIDSeq':id()),
- ?match("CosEventDomainAdmin_MemberIDSeq",
- 'CosEventDomainAdmin_MemberIDSeq':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventDomainAdmin_RouteSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventDomainAdmin_RouteSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosEventDomainAdmin_RouteSeq':tc())),
- ?match("IDL:omg.org/CosEventDomainAdmin/RouteSeq:1.0",
- 'CosEventDomainAdmin_RouteSeq':id()),
- ?match("CosEventDomainAdmin_RouteSeq",
- 'CosEventDomainAdmin_RouteSeq':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventDomainAdmin_EventDomainFactory'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventDomainAdmin_EventDomainFactory'(_) ->
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomainFactory':oe_tc(create_event_domain)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomainFactory':oe_tc(get_all_domains)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomainFactory':oe_tc(get_event_domain)),
- ?match(undefined, 'CosEventDomainAdmin_EventDomainFactory':oe_tc(undefined)),
- ?match([_|_], 'CosEventDomainAdmin_EventDomainFactory':oe_get_interface()),
- ?match("IDL:omg.org/CosEventDomainAdmin/EventDomainFactory:1.0",
- 'CosEventDomainAdmin_EventDomainFactory':typeID()),
- check_tc('CosEventDomainAdmin_EventDomainFactory':oe_get_interface()),
- ?match(true, 'CosEventDomainAdmin_EventDomainFactory':oe_is_a('CosEventDomainAdmin_EventDomainFactory':typeID())),
- ?match(false, 'CosEventDomainAdmin_EventDomainFactory':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosEventDomainAdmin_EventDomain'
-%% Description:
-%%-----------------------------------------------------------------
-'CosEventDomainAdmin_EventDomain'(_) ->
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(add_channel)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(get_all_channels)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(get_channel)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(remove_channel)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(add_connection)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(get_all_connections)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(get_connection)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(remove_connection)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(get_offer_channels)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(get_subscription_channels)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(destroy)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(get_cycles)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(get_diamonds)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(set_default_consumer_channel)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(set_default_supplier_channel)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_push_consumer)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_pull_consumer)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_push_supplier)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_pull_supplier)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_structured_push_consumer)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_structured_pull_consumer)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_structured_push_supplier)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_structured_pull_supplier)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_sequence_push_consumer)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_sequence_pull_consumer)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_sequence_push_supplier)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_sequence_pull_supplier)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_push_consumer_with_id)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_pull_consumer_with_id)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_push_supplier_with_id)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_pull_supplier_with_id)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_structured_push_consumer_with_id)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_structured_pull_consumer_with_id)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_structured_push_supplier_with_id)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_structured_pull_supplier_with_id)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_sequence_push_consumer_with_id)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_sequence_pull_consumer_with_id)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_sequence_push_supplier_with_id)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(connect_sequence_pull_supplier_with_id)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(validate_qos)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(get_admin)),
- ?nomatch(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(set_admin)),
- ?match(undefined, 'CosEventDomainAdmin_EventDomain':oe_tc(undefined)),
- ?match([_|_], 'CosEventDomainAdmin_EventDomain':oe_get_interface()),
- ?match("IDL:omg.org/CosEventDomainAdmin/EventDomain:1.0",
- 'CosEventDomainAdmin_EventDomain':typeID()),
- check_tc('CosEventDomainAdmin_EventDomain':oe_get_interface()),
- ?match(true, 'CosEventDomainAdmin_EventDomain':oe_is_a('CosEventDomainAdmin_EventDomain':typeID())),
- ?match(true, 'CosEventDomainAdmin_EventDomain':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(true, 'CosEventDomainAdmin_EventDomain':oe_is_a('CosNotification_AdminPropertiesAdmin':typeID())),
- ?match(false, 'CosEventDomainAdmin_EventDomain':oe_is_a("wrong")),
- ok.
-
-
-
-%%-----------------------------------------------------------------
-%% MISC functions
-%%-----------------------------------------------------------------
-check_tc([]) ->
- ok;
-check_tc([{Op, {RetType, InParameters, OutParameters}}|T]) ->
- io:format("checked - ~s~n", [Op]),
- lists:all(?checktc(Op), [RetType|InParameters]),
- lists:all(?checktc(Op), OutParameters),
- check_tc(T).
-
-
diff --git a/lib/cosEventDomain/vsn.mk b/lib/cosEventDomain/vsn.mk
deleted file mode 100644
index 4e10d6ac60..0000000000
--- a/lib/cosEventDomain/vsn.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-COSEVENTDOMAIN_VSN = 1.2.1
-
diff --git a/lib/cosFileTransfer/AUTHORS b/lib/cosFileTransfer/AUTHORS
deleted file mode 100644
index 55d8059989..0000000000
--- a/lib/cosFileTransfer/AUTHORS
+++ /dev/null
@@ -1,4 +0,0 @@
-Original Authors:
-Niclas Eklund
-
-Contributors:
diff --git a/lib/cosFileTransfer/Makefile b/lib/cosFileTransfer/Makefile
deleted file mode 100644
index c9c07dcdad..0000000000
--- a/lib/cosFileTransfer/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include vsn.mk
-VSN=$(COSFILETRANSFER_VSN)
-
-# ----------------------------------------------------
-# Common Macros
-# ----------------------------------------------------
-# SUB_DIRECTORIES = src test examples doc/src
-# At the moment we don't have any example programs.
-SUB_DIRECTORIES = src doc/src
-
-SPECIAL_TARGETS =
-
-# ----------------------------------------------------
-# Default Subdir Targets
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_subdir.mk
diff --git a/lib/cosFileTransfer/doc/html/.gitignore b/lib/cosFileTransfer/doc/html/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosFileTransfer/doc/html/.gitignore
+++ /dev/null
diff --git a/lib/cosFileTransfer/doc/man3/.gitignore b/lib/cosFileTransfer/doc/man3/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosFileTransfer/doc/man3/.gitignore
+++ /dev/null
diff --git a/lib/cosFileTransfer/doc/man6/.gitignore b/lib/cosFileTransfer/doc/man6/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosFileTransfer/doc/man6/.gitignore
+++ /dev/null
diff --git a/lib/cosFileTransfer/doc/pdf/.gitignore b/lib/cosFileTransfer/doc/pdf/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosFileTransfer/doc/pdf/.gitignore
+++ /dev/null
diff --git a/lib/cosFileTransfer/doc/src/CosFileTransfer.gif b/lib/cosFileTransfer/doc/src/CosFileTransfer.gif
deleted file mode 100644
index 16970ad5ad..0000000000
--- a/lib/cosFileTransfer/doc/src/CosFileTransfer.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosFileTransfer/doc/src/CosFileTransfer_Directory.xml b/lib/cosFileTransfer/doc/src/CosFileTransfer_Directory.xml
deleted file mode 100644
index da5810521a..0000000000
--- a/lib/cosFileTransfer/doc/src/CosFileTransfer_Directory.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosFileTransfer_Directory</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>2000-11-09</date>
- <rev>PA1</rev>
- </header>
- <module>CosFileTransfer_Directory</module>
- <modulesummary>This module implements the OMG CosFileTransfer::Directory interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosFileTransfer/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosFileTransfer_File">CosFileTransfer_File</seealso></p>
- </item>
- <item>
- <p>CosPropertyService_PropertySetDef in the cosProperty application.</p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>list(Directory, Max) -> Return</name>
- <fsummary>Return a list, of length <c>Max</c>or less, containing Object References representing files or directories contained within the target Directory and a <c>FileIterator</c>or a <c>NIL</c>object</fsummary>
- <type>
- <v>Directory = #objref</v>
- <v>Return = {ok, FileList, FileIterator}</v>
- <v>FileList = [File]</v>
- <v>File = FileIterator = #objref</v>
- </type>
- <desc>
- <p>This operation returns a list, of length <c>Max</c> or less, containing
- Object References representing files or directories contained within
- the target Directory. If the amount of objects found is less than <c>Max</c>
- the returned Iterator will be a <c>NIL</c> object.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosFileTransfer/doc/src/CosFileTransfer_File.xml b/lib/cosFileTransfer/doc/src/CosFileTransfer_File.xml
deleted file mode 100644
index 373c14d1f1..0000000000
--- a/lib/cosFileTransfer/doc/src/CosFileTransfer_File.xml
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosFileTransfer_File</title>
- <prepared></prepared>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-11-09</date>
- <rev>PA1</rev>
- </header>
- <module>CosFileTransfer_File</module>
- <modulesummary>This module implements the OMG CosFileTransfer::File interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosFileTransfer/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p>CosPropertyService_PropertySetDef in the cosProperty application.</p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>'_get_name'(File) -> string()</name>
- <fsummary>Return the target object's associated name</fsummary>
- <type>
- <v>File = #objref</v>
- </type>
- <desc>
- <p>This read only attribute represents the target object's associated name.</p>
- </desc>
- </func>
- <func>
- <name>'_get_complete_file_name'(File) -> string()</name>
- <fsummary>Return the target object's associated absolute name.</fsummary>
- <type>
- <v>File = #objref</v>
- </type>
- <desc>
- <p>This read only attribute represents the target object's associated
- absolute name.</p>
- </desc>
- </func>
- <func>
- <name>'_get_parent'(File) -> Directory</name>
- <fsummary>Return the target object's container.</fsummary>
- <type>
- <v>File = Directory = #objref</v>
- </type>
- <desc>
- <p>This read only attribute represents the target object's container.
- In some cases a <c>NIL</c> object will be returned.</p>
- </desc>
- </func>
- <func>
- <name>'_get_associated_session'(File) -> FileTransferSession</name>
- <fsummary>Return the target object's associated <c>FileTransferSession</c></fsummary>
- <type>
- <v>File = FileTransferSession = #objref</v>
- </type>
- <desc>
- <p>This read only attribute represents the target object's associated
- <c>FileTransferSession</c>.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosFileTransfer/doc/src/CosFileTransfer_FileIterator.xml b/lib/cosFileTransfer/doc/src/CosFileTransfer_FileIterator.xml
deleted file mode 100644
index f5c219b9c1..0000000000
--- a/lib/cosFileTransfer/doc/src/CosFileTransfer_FileIterator.xml
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosFileTransfer_FileIterator</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>2000-11-09</date>
- <rev>PA1</rev>
- </header>
- <module>CosFileTransfer_FileIterator</module>
- <modulesummary>This module implements the OMG CosFileTransfer::FileIterator interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosFileTransfer/include/*.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>next_one(Iterator) -> Return</name>
- <fsummary>Return the next <c>FileWrapper</c>and a boolean which indicate whether the <c>FileWrapper</c>is valid or not.</fsummary>
- <type>
- <v>Iterator = #objref</v>
- <v>Return = {boolean(), #'CosFileTransfer_FileWrapper'{the_file = File file_type = Type}}</v>
- <v>File = #objref</v>
- <v>Type = nfile | ndirectory</v>
- </type>
- <desc>
- <p>This operation returns true if a <c>FileWrapper</c> exists at the
- current position and the out parameter contains a valid <c>File</c>
- reference. If false is returned the out parameter is a non-valid
- <c>FileWrapper</c>.</p>
- </desc>
- </func>
- <func>
- <name>next_n(Iterator, Max) -> Return</name>
- <fsummary>Return a list, of length <c>Max</c>or less, containing <c>FileWrappers</c>and a boolean which indicates if more <c>FileWrappers</c>exists</fsummary>
- <type>
- <v>Iterator = #objref</v>
- <v>Max = unsigned long()</v>
- <v>Return = {boolean(), FileList}</v>
- <v>FileList = [#'CosFileTransfer_FileWrapper'{the_file = File file_type = Type}]</v>
- <v>File = #objref</v>
- <v>Type = nfile | ndirectory</v>
- </type>
- <desc>
- <p>This operation returns true if the requested number of <c>FileWrappers</c>
- can be delivered and there are additional <c>FileWrappers</c>. If false is
- returned a list, of length <c>Max</c> or less, containing the last valid
- <c>FileWrappers</c> associated with the target object.</p>
- </desc>
- </func>
- <func>
- <name>destroy(Iterator) -> ok</name>
- <fsummary>Terminate the target object</fsummary>
- <type>
- <v>Iterator = #objref</v>
- </type>
- <desc>
- <p>This operation terminates the target object.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosFileTransfer/doc/src/CosFileTransfer_FileTransferSession.xml b/lib/cosFileTransfer/doc/src/CosFileTransfer_FileTransferSession.xml
deleted file mode 100644
index 312af3b8c2..0000000000
--- a/lib/cosFileTransfer/doc/src/CosFileTransfer_FileTransferSession.xml
+++ /dev/null
@@ -1,191 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosFileTransfer_FileTransferSession</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>2000-11-09</date>
- <rev>PA1</rev>
- </header>
- <module>CosFileTransfer_FileTransferSession</module>
- <modulesummary>This module implements the OMG CosFileTransfer::FileTransferSession interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosFileTransfer/include/*.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>'_get_protocols_supported'(FTS) -> Return</name>
- <fsummary>Return the protocols supported by the target object</fsummary>
- <type>
- <v>FTS = #objref</v>
- <v>Return = [#'CosFileTransfer_ProtocolSupport'{protocol_name=Type, addresses=[Address]}]</v>
- <v>Type = Address = string()</v>
- </type>
- <desc>
- <p>This read only attribute returns the protocols supported by the
- target object.</p>
- </desc>
- </func>
- <func>
- <name>set_directory(FTS, Directory) -> Return</name>
- <fsummary>Change the current working directory of the target object's associated file system</fsummary>
- <type>
- <v>FTS = Directory = #objref</v>
- <v>Return = ok | {'EXCEPTION, E}</v>
- </type>
- <desc>
- <p>Invoking this operation will change the current working directory of
- the target object's associated file system. If fail to do so the
- appropriate exception is raised. </p>
- </desc>
- </func>
- <func>
- <name>create_file(FTS, FileNameList) -> Return</name>
- <fsummary>Create a <c>File</c>Object representing a file which may or may not exist</fsummary>
- <type>
- <v>FTS = #objref</v>
- <v>FileNameList = [string()]</v>
- <v>Return = File | {'EXCEPTION, E}</v>
- <v>File = #objref</v>
- </type>
- <desc>
- <p>This operation creates a <c>File</c> Object representing a file which
- may or may not exist.
- For this operation to be independent of the working directory the
- supplied <c>FileNameList</c> must represent the absolute name.</p>
- </desc>
- </func>
- <func>
- <name>create_directory(FTS, FileNameList) -> Return</name>
- <fsummary>Create a new directory in the target objects associated file systems domain</fsummary>
- <type>
- <v>FTS = #objref</v>
- <v>FileNameList = [string()]</v>
- <v>Return = Directory | {'EXCEPTION, E}</v>
- <v>Directory = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new directory in the target objects associated
- file systems domain. If fail to do so an exception is raised but,
- if successful, a <c>Directory</c> object representing the new
- directory is returned.</p>
- </desc>
- </func>
- <func>
- <name>get_file(FTS, FileNameList) -> Return</name>
- <fsummary>Create a <c>FileWrapper</c>which represents a file or directory</fsummary>
- <type>
- <v>FTS = #objref</v>
- <v>FileNameList = [string()]</v>
- <v>Return = FileWrapper | {'EXCEPTION, E}</v>
- <v>FileWrapper = #'CosFileTransfer_FileWrapper'{the_file = File file_type = Type}</v>
- <v>File = #objref</v>
- <v>Type = nfile | ndirectory</v>
- </type>
- <desc>
- <p>This operation, creates a <c>FileWrapper</c> which represents a file or directory, and
- should be independent of the working Directory,
- i.e., a full path name must be supplied. Furthermore, the file or
- directory represented by the <c>FileNameList</c> must exist.</p>
- </desc>
- </func>
- <func>
- <name>delete(FTS, File) -> Return</name>
- <fsummary>Delete the file or directory, represented by the <c>File</c>object, from the target objects associated file system</fsummary>
- <type>
- <v>FTS = File = #objref</v>
- <v>Return = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This operation removes the file or directory, represented by the <c>File</c>
- object, from the target objects associated file system. If it is a non-empty
- directory or non-existing file or directory an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>transfer(FTS, SourceFile, DestinationFile) -> Return</name>
- <fsummary>Copy the file represented by the <c>SourceFile</c>from the target object's file system to a file in the destination <c>FileTransferSession's</c>file system</fsummary>
- <type>
- <v>FTS = SourceFile = DestinationFile = #objref</v>
- <v>Return = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>If the target object's and the <c>DestinationFile's</c> associated
- <c>FileTransferSession's</c> support the same protocol(s) this operation
- will copy the file represented by the <c>SourceFile</c> from the target
- object's file system to a file in the destination
- <c>FileTransferSession's</c> file system. The file is represented by the
- <c>DestinationFile</c> object and may not exist.
- This operation must be invoked on the <c>FileTransferSession</c>
- associated with the <c>SourceFile</c> object.</p>
- </desc>
- </func>
- <func>
- <name>append(FTS, SourceFile, DestinationFile) -> Return</name>
- <fsummary>Append the file represented by the <c>SourceFile</c>from the target object's file system to a file in the destination <c>FileTransferSession's</c>file system</fsummary>
- <type>
- <v>FTS = SourceFile = DestinationFile = #objref</v>
- <v>Return = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This operation behaves almost like the <c>transfer/3</c> operation. The
- difference is that the <c>DestinationFile</c> must exist since the
- <c>SourceFile</c> will be appended to the <c>DestinationFile</c>.</p>
- <p>Currently, it is not possible to use this operation when the target
- object represents FTP.</p>
- </desc>
- </func>
- <func>
- <name>insert(FTS, SourceFile, DestinationFile, Offset) -> Return</name>
- <fsummary>Insert the <c>SourceFile</c>into the <c>DestinationFile</c> <c>Offset</c>bytes from the start of the file</fsummary>
- <type>
- <v>FTS = SourceFile = DestinationFile = #objref</v>
- <v>Offset = long()</v>
- <v>Return = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This operation behaves almost like the <c>append/3</c> operation. The
- difference is that the <c>SourceFile</c> will be inserted into the
- <c>DestinationFile</c> <c>Offset</c> bytes from the start of the file.</p>
- <p>Currently, it is not possible to use this operation when the target
- object represents FTP.</p>
- </desc>
- </func>
- <func>
- <name>logout(FTS) -> ok</name>
- <fsummary>Terminate the target object and close the connection to the file system it represents</fsummary>
- <type>
- <v>FTS = #objref</v>
- </type>
- <desc>
- <p>This operation terminates the target object and closes the connection
- to the file system it represents.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosFileTransfer/doc/src/CosFileTransfer_VirtualFileSystem.xml b/lib/cosFileTransfer/doc/src/CosFileTransfer_VirtualFileSystem.xml
deleted file mode 100644
index 701e56e660..0000000000
--- a/lib/cosFileTransfer/doc/src/CosFileTransfer_VirtualFileSystem.xml
+++ /dev/null
@@ -1,83 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosFileTransfer_VirtualFileSystem</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>2000-11-09</date>
- <rev>PA1</rev>
- </header>
- <module>CosFileTransfer_VirtualFileSystem</module>
- <modulesummary>This module implements the OMG CosFileTransfer::VirtualFileSystem interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosFileTransfer/include/*.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>'_get_file_system_type'(VFS) -> Return</name>
- <fsummary>Return the target object's associated file system</fsummary>
- <type>
- <v>VFS = #objref</v>
- <v>Return = 'FTP' | 'NATIVE'</v>
- </type>
- <desc>
- <p>This read only attribute represents the target object's associated
- file system.</p>
- </desc>
- </func>
- <func>
- <name>'_get_supported_content_types'(VFS) -> Return</name>
- <fsummary>Return the target object's supported content types.</fsummary>
- <type>
- <v>VFS = #objref</v>
- <v>Return = </v>
- </type>
- <desc>
- <p>This read only attribute represents the target object's supported
- content types.</p>
- </desc>
- </func>
- <func>
- <name>login(VFS, User, Password, Account) -> Return</name>
- <fsummary>Create a new instance of a <c>FileTransferSession</c>and a <c>Directory</c></fsummary>
- <type>
- <v>VFS = #objref</v>
- <v>User = Password = Account = string()</v>
- <v>Return = {FileTransferSession, Directory} | {'EXCEPTION', E}</v>
- <v>FileTransferSession = Directory = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new instance of a <c>FileTransferSession</c>
- and a <c>Directory</c>. The later represents the current working
- directory of the returned <c>FileTransferSession</c>.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosFileTransfer/doc/src/Makefile b/lib/cosFileTransfer/doc/src/Makefile
deleted file mode 100644
index 8d8c736f1b..0000000000
--- a/lib/cosFileTransfer/doc/src/Makefile
+++ /dev/null
@@ -1,147 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(COSFILETRANSFER_VSN)
-APPLICATION=cosFileTransfer
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = \
- cosFileTransferApp.xml \
- CosFileTransfer_Directory.xml \
- CosFileTransfer_File.xml \
- CosFileTransfer_VirtualFileSystem.xml \
- CosFileTransfer_FileTransferSession.xml \
- CosFileTransfer_FileIterator.xml
-
-XML_PART_FILES = \
- part.xml \
- part_notes.xml
-XML_CHAPTER_FILES = \
- ch_contents.xml \
- ch_introduction.xml \
- ch_install.xml \
- ch_system.xml \
- ch_example.xml \
- notes.xml
-
-BOOK_FILES = book.xml
-
-XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \
- $(XML_PART_FILES) $(XML_CHAPTER_FILES)
-
-TECHNICAL_DESCR_FILES =
-
-GIF_FILES = \
- book.gif \
- notes.gif \
- ref_man.gif \
- user_guide.gif \
- CosFileTransfer.gif
-
-PS_FILES =
-
-# ----------------------------------------------------
-
-INTERNAL_HTML_FILES = $(TECHNICAL_DESCR_FILES:%.xml=$(HTMLDIR)/%.html)
-
-HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
-
-
-INFO_FILE = ../../info
-
-EXTRA_FILES = summary.html.src \
- $(DEFAULT_GIF_FILES) \
- $(DEFAULT_HTML_FILES) \
- $(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html)
-
-MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-
-HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
-
-TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-$(HTMLDIR)/%.gif: %.gif
- $(INSTALL_DATA) $< $@
-
-docs: pdf html man
-
-$(TOP_PDF_FILE): $(XML_FILES)
-
-pdf: $(TOP_PDF_FILE)
-
-html: gifs $(HTML_REF_MAN_FILE)
-
-clean clean_docs:
- rm -rf $(HTMLDIR)/*
- rm -f $(MAN3DIR)/*
- rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
-
-man: $(MAN3_FILES)
-
-gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-
-$(INDEX_TARGET): $(INDEX_SRC)
- sed -e 's;%VSN%;$(VSN);' $(INDEX_SRC) > $(INDEX_TARGET)
-
-debug opt:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_docs_spec: docs
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(HTMLDIR)/* \
- "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
- $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
-
-release_spec:
diff --git a/lib/cosFileTransfer/doc/src/book.gif b/lib/cosFileTransfer/doc/src/book.gif
deleted file mode 100644
index 94b3868792..0000000000
--- a/lib/cosFileTransfer/doc/src/book.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosFileTransfer/doc/src/book.xml b/lib/cosFileTransfer/doc/src/book.xml
deleted file mode 100644
index 9a9ec3d0a2..0000000000
--- a/lib/cosFileTransfer/doc/src/book.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book xmlns:xi="http://www.w3.org/2001/XInclude">
- <header titlestyle="normal">
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosFileTransfer</title>
- <prepared></prepared>
- <docno></docno>
- <date>2000-08-24</date>
- <rev>1.0</rev>
- </header>
- <insidecover>
- </insidecover>
- <pagetext>cosFileTransfer</pagetext>
- <preamble>
- <contents level="2"></contents>
- </preamble>
- <parts lift="no">
- <xi:include href="part.xml"/>
- </parts>
- <applications>
- <xi:include href="ref_man.xml"/>
- </applications>
- <releasenotes>
- <xi:include href="notes.xml"/>
- </releasenotes>
- <listofterms></listofterms>
- <index></index>
-</book>
-
diff --git a/lib/cosFileTransfer/doc/src/ch_contents.xml b/lib/cosFileTransfer/doc/src/ch_contents.xml
deleted file mode 100644
index bd4ed5116f..0000000000
--- a/lib/cosFileTransfer/doc/src/ch_contents.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>The cosFileTransfer Application</title>
- <prepared></prepared>
- <docno></docno>
- <date>2000-08-24</date>
- <rev>1.0</rev>
- <file>ch_contents.xml</file>
- </header>
-
- <section>
- <title>Content Overview</title>
- <p>The cosFileTransfer documentation is divided into three sections:
- </p>
- <list type="bulleted">
- <item>
- <p>PART ONE - The User's Guide
- <br></br>
-Description of the cosFileTransfer Application including
- services and a small tutorial demonstrating
- the development of a simple service.</p>
- </item>
- <item>
- <p>PART TWO - Release Notes
- <br></br>
-A concise history of cosFileTransfer.</p>
- </item>
- <item>
- <p>PART THREE - The Reference Manual
- <br></br>
- A quick reference guide, including a
- brief description, to all the functions available in cosFileTransfer.</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Brief description of the User's Guide</title>
- <p>The User's Guide contains the following parts:</p>
- <list type="bulleted">
- <item>
- <p>cosFileTransfer overview</p>
- </item>
- <item>
- <p>cosFileTransfer installation</p>
- </item>
- <item>
- <p>A tutorial example</p>
- </item>
- </list>
- </section>
-</chapter>
-
diff --git a/lib/cosFileTransfer/doc/src/ch_example.xml b/lib/cosFileTransfer/doc/src/ch_example.xml
deleted file mode 100644
index 7e3c65eedd..0000000000
--- a/lib/cosFileTransfer/doc/src/ch_example.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosFileTransfer Examples</title>
- <prepared></prepared>
- <docno></docno>
- <date>2000-08-24</date>
- <rev>A</rev>
- <file>ch_example.xml</file>
- </header>
-
- <section>
- <title>A tutorial on how to create a simple service</title>
-
- <section>
- <title>Initiate the application</title>
- <p>To use the complete cosFileTransfer application cosProperty
- must be installed.</p>
- </section>
-
- <section>
- <title>How to run everything</title>
- <p>Below is a short transcript on how to run cosFileTransfer. </p>
- <code type="none">
-
-%% Start Mnesia and Orber
-mnesia:delete_schema([node()]),
-mnesia:create_schema([node()]),
-orber:install([node()]),
-mnesia:start(),
-orber:start(),
-
-%% The File Transfer Service depends on the cosProperty
-%% application. Hence, we must install cosProperty first.
-%% It's NOT necessary to invoke cosProperty:install_db().
-cosProperty:install(),
-
-%% Install File Transfer Service in the IFR.
-cosFileTransfer:install(),
-
-%% Now start the application and necessary services.
-cosFileTransfer:start(),
-
-%% Create two Virtual File Systems respectively representing an FTP-
-%% and the local NFS file system.
-VFSFTP = cosFileTransferApp:create_VFS('FTP', [], FTPHost, 21),
-VFSNATIVE = cosFileTransferApp:
- create_VFS({'NATIVE', 'cosFileTransferNATIVE_file'},
- [], MyLocalHost, 0),
-
-%% Login to each system.
-{FSFTP, DirFTP} = 'CosFileTransfer_VirtualFileSystem':
- login(VFSFTP, "myId", "myPwd", "myAccount"),
-{FSNATIVE, DirNATIVE} = 'CosFileTransfer_VirtualFileSystem':
- login(VFSNATIVE, "myId", "myPwd", "myAccount"),
-
-%% If we want to copy a file from the NFS to the FTP we must first
-%% create a File object which contains its attributes.
-Target = 'CosFileTransfer_FileTransferSession':create_file(FSFTP,
- ["/", "ftp", "incoming", "targetFile"])),
-
- #'CosFileTransfer_FileWrapper'{the_file = Dir} =
-%% Lookup the file we want to copy.
-FileWrapper = 'CosFileTransfer_FileTransferSession':get_file(FSNATIVE,
- ["/", "home", "myId", "sourceFile"]),
-Source = FileWrapper#'CosFileTransfer_FileWrapper'.the_file,
-
-%% Now we are ready to transfer the file. Please note that we most
-%% call the source Session object.
-'CosFileTransfer_FileTransferSession':transfer(FSNATIVE, Source, Target),
- </code>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosFileTransfer/doc/src/ch_install.xml b/lib/cosFileTransfer/doc/src/ch_install.xml
deleted file mode 100644
index 9681f98b45..0000000000
--- a/lib/cosFileTransfer/doc/src/ch_install.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Installing cosFileTransfer</title>
- <prepared></prepared>
- <docno></docno>
- <date>2000-08-24</date>
- <rev></rev>
- <file>ch_install.xml</file>
- </header>
-
- <section>
- <title>Installation Process </title>
- <p>This chapter describes how to install
- <seealso marker="cosFileTransferApp">cosFileTransferApp</seealso> in an Erlang Environment.
- </p>
-
- <section>
- <title>Preparation</title>
- <p>Before starting the installation process for cosFileTransfer,
- the application <c>Orber</c> must be running and <c>cosProperty</c> installed by
- using <c>cosProperty:install()</c>. Please note that it is <em>NOT</em> necessary
- to use <c>cosProperty:install_db()</c> for running the cosFileTransfer application.</p>
- </section>
-
- <section>
- <title>Configuration</title>
- <p>When starting the cosFileTransfer application the following configuration parameters
- can be used:</p>
- <list type="bulleted">
- <item><em>buffert_size</em> - default is 64000. This option determine
- how many bytes will be read at a time when transferring files.</item>
- </list>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosFileTransfer/doc/src/ch_introduction.xml b/lib/cosFileTransfer/doc/src/ch_introduction.xml
deleted file mode 100644
index 67616b0a39..0000000000
--- a/lib/cosFileTransfer/doc/src/ch_introduction.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Introduction to cosFileTransfer</title>
- <prepared></prepared>
- <docno></docno>
- <date>2000-08-24</date>
- <rev></rev>
- <file>ch_introduction.xml</file>
- </header>
-
- <section>
- <title>Overview</title>
- <p>The cosFileTransfer application is a FileTransfer Service compliant with the
- <url href="http://www.omg.org">OMG</url> Service CosFileTransfer.
- </p>
-
- <section>
- <title>Purpose and Dependencies</title>
- <p>If a Virtual File System is started as 'FTP', the inets-2.5.4 application,
- or later, must be installed.</p>
- <p><em>cosFileTransfer</em> is dependent on <em>Orber</em>, which provides CORBA functionality in an Erlang environment,
- and <em>cosProperty</em>.</p>
- </section>
-
- <section>
- <title>Prerequisites</title>
- <p>To fully understand the concepts presented in the
- documentation, it is recommended that the user is familiar
- with distributed programming, CORBA, the Orber and cosProperty applications.
- </p>
- <p>Recommended reading includes <em>CORBA, Fundamentals and Programming - Jon Siegel</em> and <em>Open Telecom Platform Documentation Set</em>. It is also helpful to have read <em>Concurrent Programming in Erlang</em>.</p>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosFileTransfer/doc/src/ch_system.xml b/lib/cosFileTransfer/doc/src/ch_system.xml
deleted file mode 100644
index 377ec1fa49..0000000000
--- a/lib/cosFileTransfer/doc/src/ch_system.xml
+++ /dev/null
@@ -1,138 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2001</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Using the File Transfer Service</title>
- <prepared></prepared>
- <docno></docno>
- <date>2001-08-07</date>
- <rev></rev>
- <file>ch_system.xml</file>
- </header>
-
- <section>
- <title>Overview</title>
- <p>This chapter describes how two File Transfer Service applications interact.</p>
-
- <section>
- <title>Components</title>
- <p>There are several ways the OMG File Transfer Service can be used.
- Below one scenario is visualized: </p>
- <marker id="CosFileTransfer"></marker>
- <image file="CosFileTransfer.gif">
- <icaption>Figure 1: The File Transfer Service Components.</icaption>
- </image>
- <list type="bulleted">
- <item><em>Source ORB:</em> this is the ORB we want to transfer a file from/via and it holds
- an object reference to a
- <seealso marker="CosFileTransfer_VirtualFileSystem">Virtual File System (VFS)</seealso> which,
- in this example, represents an FTP server.</item>
- <item><em>Target ORB:</em> the goal may be, for example, to transfer a new file or append to an
- existing file placed at the location that this ORB's <c>VFS</c> represents.
- In this scenario it is the local disk or the NFS.</item>
- <item><em>Transport Protocol:</em> initially the ORB's, i.e., target and source, communicate via
- normal <c>CORBA</c> requests to determine whether or not they can communicate. If the
- File Transfer Service's have one, or more, <c>Transport Protocol</c> in common the data
- will be streamed using this protocol. The cosFileTransfer application currently supports
- <c>TCP/IP</c> and <c>SSL</c>.</item>
- </list>
- <p>Which type of file system the <c>VFS</c> is supposed to represent is determined
- by the options given when creating it, which is also how one determine which
- <c>Transport Protocol</c> to use. Hence, the source and target <c>VFS</c> described above
- can be started by invoking, respectively, the following operations:</p>
- <code type="none">
-1> SVFS = cosFileTransferApp:create_VFS('FTP', [], Host, 21, [{protocol, tcp}]),
-2> TVFS = cosFileTransferApp:create_VFS({'NATIVE', 'cosFileTransferNATIVE_file'},
- [], OtherHost, 0, [{protocol, tcp}]),
- </code>
- <p>Naturally can any combination of <c>VFS</c>-types be used and it is also possible
- to use own drivers, i.e., <c>{'NATIVE', 'MyDriver'}</c>.</p>
- <p>After creating necessary <c>VFS's</c> we can login in and perform operations
- on files and directories residing on each file system.</p>
- </section>
-
- <section>
- <title>How To Use SSL</title>
- <p>To be able to use <c>SSL</c> as transport protocol a few configuration
- parameters must be set. The required parameters depend on if Orber is
- the target or/and the source ORB. However, the SSL_CERT_FILE variable
- must be defined in both cases.</p>
- <p>Setting of a CA certificate file with an option does not work due to
- weaknesses in the SSLeay package. A work-around in the ssl application is
- to set the OS environment variable SSL_CERT_FILE before SSL is started.
- However, then the CA certificate file will be global for all connections
- (both incoming and outgoing calls).</p>
-
- <section>
- <title>Configurations when cosFileTransfer is Used as Target</title>
- <p>The following three configuration variables can be used to configure
- cosFileTransfer's SSL target behavior.</p>
- <list type="bulleted">
- <item><em>ssl_server_certfile</em> which is a path to a file containing a
- chain of PEM encoded certificates for cosFileTransfer as target.</item>
- <item><em>ssl_server_verify</em> which specifies type of verification:
- 0 = do not verify peer; 1 = verify peer, verify client once, 2 =
- verify peer, verify client once, fail if no peer certificate.
- The default value is 0.</item>
- <item><em>ssl_server_depth</em> which specifies verification depth, i.e.
- how far in a chain of certificates the verification process shall
- proceed before the verification is considered successful. The
- default value is 1. </item>
- </list>
- <p>There also exist a number of API functions for accessing the values of
- these variables:</p>
- <list type="bulleted">
- <item>cosFileTransferApp:ssl_server_certfile/0</item>
- <item>cosFileTransferApp:ssl_server_verify/0</item>
- <item>cosFileTransferApp:ssl_server_depth/0</item>
- </list>
- </section>
-
- <section>
- <title>Configurations when cosFileTransfer is used as Source</title>
- <p>Below is the list of configuration variables used when cosFileTransfer
- act as the source application.</p>
- <list type="bulleted">
- <item><em>ssl_client_certfile</em> which is a path to a file containing a
- chain of PEM encoded certificates used in outgoing calls.</item>
- <item><em>ssl_client_verify</em> which specifies type of verification:
- 0 = do not verify peer; 1 = verify peer, verify client once, 2 =
- verify peer, verify client once, fail if no peer certificate.
- The default value is 0.</item>
- <item><em>ssl_client_depth</em> which specifies verification depth, i.e.
- how far in a chain of certificates the verification process shall
- proceed before the verification is considered successful. The
- default value is 1. </item>
- </list>
- <p>There also exist a number of API functions for accessing the values of
- these variables in the client processes:</p>
- <list type="bulleted">
- <item>cosFileTransferApp:ssl_client_certfile/0</item>
- <item>cosFileTransferApp:ssl_client_verify/0</item>
- <item>cosFileTransferApp:ssl_client_depth/0</item>
- </list>
- </section>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosFileTransfer/doc/src/cosFileTransferApp.xml b/lib/cosFileTransfer/doc/src/cosFileTransferApp.xml
deleted file mode 100644
index ae7b4f1ec5..0000000000
--- a/lib/cosFileTransfer/doc/src/cosFileTransferApp.xml
+++ /dev/null
@@ -1,173 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosFileTransferApp</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>2000-08-24</date>
- <rev>PA1</rev>
- </header>
- <module>cosFileTransferApp</module>
- <modulesummary>The main module of the cosFileTransfer application.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosFileTransfer/include/*.hrl").</c></p>
- <p>This module contains the functions for starting and stopping the application.</p>
- </description>
- <funcs>
- <func>
- <name>install() -> Return</name>
- <fsummary>Install the cosFileTransfer application</fsummary>
- <type>
- <v>Return = ok | {'EXIT', Reason}</v>
- </type>
- <desc>
- <p>This operation installs the cosFileTransfer application. Note, the
- <c>cosProperty</c> application must be installed prior to invoking this
- operation.</p>
- </desc>
- </func>
- <func>
- <name>uninstall() -> Return</name>
- <fsummary>Uninstall the cosFileTransfer application</fsummary>
- <type>
- <v>Return = ok | {'EXIT', Reason}</v>
- </type>
- <desc>
- <p>This operation uninstalls the cosFileTransfer application.</p>
- </desc>
- </func>
- <func>
- <name>start() -> Return</name>
- <fsummary>Start the cosFileTransfer application</fsummary>
- <type>
- <v>Return = ok | {error, Reason}</v>
- </type>
- <desc>
- <p>This operation starts the cosFileTransfer application.</p>
- </desc>
- </func>
- <func>
- <name>stop() -> Return</name>
- <fsummary>Stop the cosFileTransfer application</fsummary>
- <type>
- <v>Return = ok | {error, Reason}</v>
- </type>
- <desc>
- <p>This operation stops the cosFileTransfer application.</p>
- </desc>
- </func>
- <func>
- <name>create_VFS(Type, Content, Host, Port [,Options]) -> Return</name>
- <fsummary>Create a new instance of a Virtual File System</fsummary>
- <type>
- <v>Type = 'FTP' | {'NATIVE', 'cosFileTransferNATIVE_file'} | {'NATIVE', MyModule}</v>
- <v>Content = []</v>
- <v>Host = string(), e.g. "myHost@myServer" or "012.345.678.910"</v>
- <v>Port = integer()</v>
- <v>Options = [Option]</v>
- <v>Option = {protocol, Protocol} | {connect_timeout, Seconds}</v>
- <v>Protocol = tcp | ssl</v>
- <v>Return = VFS | {'EXCEPTION, E}</v>
- <v>VFS = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new instance of a Virtual File System. The
- <c>Type</c> parameter determines which type we want the VFS to represent.
- 'FTP' maps to the <c>INETS</c> ftp implementation, while
- {'NATIVE', 'cosFileTransferNATIVE_file'} uses the <c>file</c> module.
- It is also possible to implement own mappings which are activated by
- supplying {'NATIVE', MyModule}. The MyModule module must export the same
- functions and behave in the same way as the INETS ftp module, and
- an operation named <c>open(Host, Port)</c>, which shall return
- <c>{ok, Pid}</c> or <c>{error, Reason}</c>.</p>
- <p>If no <c>Options</c> are supplied the default setting will be
- used, i.e., tcp and 60 seconds.</p>
- <p>The <c>Content</c> parameter is currently ignored by must be supplied
- as an empty list.</p>
- </desc>
- </func>
- <func>
- <name>ssl_server_certfile() -> string()</name>
- <fsummary>Display the path to the target certificate</fsummary>
- <desc>
- <p>This function returns a path to a file containing a chain of PEM encoded
- certificates for the cosFileTransfer as target.
- This is configured by setting the application variable
- <em>ssl_server_certfile</em>.</p>
- </desc>
- </func>
- <func>
- <name>ssl_client_certfile() -> string()</name>
- <fsummary>Display the path to the client certificate</fsummary>
- <desc>
- <p>This function returns a path to a file containing a chain of PEM encoded
- certificates used in outgoing calls.
- The default value is configured by setting the application variable
- <em>ssl_client_certfile</em>.</p>
- </desc>
- </func>
- <func>
- <name>ssl_server_verify() -> 0 | 1 | 2</name>
- <fsummary>Display the SSL verification type for incoming calls</fsummary>
- <desc>
- <p>This function returns the type of verification used by SSL during authentication of the other
- peer for incoming calls.
- It is configured by setting the application variable
- <em>ssl_server_verify</em>.</p>
- </desc>
- </func>
- <func>
- <name>ssl_client_verify() -> 0 | 1 | 2</name>
- <fsummary>Display the SSL verification type for outgoing calls</fsummary>
- <desc>
- <p>This function returns the type of verification used by SSL during authentication of the other
- peer for outgoing calls.
- The default value is configured by setting the application variable
- <em>ssl_client_verify</em>.</p>
- </desc>
- </func>
- <func>
- <name>ssl_server_depth() -> int()</name>
- <fsummary>Display the SSL verification depth for incoming calls</fsummary>
- <desc>
- <p>This function returns the SSL verification depth for incoming calls.
- It is configured by setting the application variable
- <em>ssl_server_depth</em>.</p>
- </desc>
- </func>
- <func>
- <name>ssl_client_depth() -> int()</name>
- <fsummary>Display the SSL verification depth for outgoing calls</fsummary>
- <desc>
- <p>This function returns the SSL verification depth for outgoing calls.
- The default value is configured by setting the application variable
- <em>ssl_client_depth</em>.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosFileTransfer/doc/src/fascicules.xml b/lib/cosFileTransfer/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/cosFileTransfer/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/cosFileTransfer/doc/src/notes.gif b/lib/cosFileTransfer/doc/src/notes.gif
deleted file mode 100644
index e000cca26a..0000000000
--- a/lib/cosFileTransfer/doc/src/notes.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosFileTransfer/doc/src/notes.xml b/lib/cosFileTransfer/doc/src/notes.xml
deleted file mode 100644
index 58ab087014..0000000000
--- a/lib/cosFileTransfer/doc/src/notes.xml
+++ /dev/null
@@ -1,364 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosFileTransfer Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>2000-08-24</date>
- <rev>A</rev>
- <file>notes.xml</file>
- </header>
-
- <section><title>cosFileTransfer 1.2.1</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Internal changes</p>
- <p>
- Own Id: OTP-13551</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosFileTransfer 1.2</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> Remove the usage of erlang:now() from all Corba
- applications and use the new rand module instead of
- random. </p>
- <p>
- Own Id: OTP-12687</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosFileTransfer 1.1.16</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> The default encoding of Erlang files has been changed
- from ISO-8859-1 to UTF-8. </p> <p> The encoding of XML
- files has also been changed to UTF-8. </p>
- <p>
- Own Id: OTP-10907</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosFileTransfer 1.1.15</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> Postscript files no longer needed for the generation
- of PDF files have been removed. </p>
- <p>
- Own Id: OTP-11016</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosFileTransfer 1.1.14</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Misc build updates</p>
- <p>
- Own Id: OTP-10784</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosFileTransfer 1.1.13</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>Erlang/OTP can now be built using parallel make if you
- limit the number of jobs, for instance using '<c>make
- -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
- work at the moment because of some missing
- dependencies.</p>
- <p>
- Own Id: OTP-9451</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosFileTransfer 1.1.12</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p> XML files have been corrected. </p>
- <p>
- Own Id: OTP-9550 Aux Id: OTP-9541 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section>
- <title>cosFileTransfer 1.1.11</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Removed superfluous usage of shy in the documentation since it can cause problem if
- a buggy tool is used.</p>
- <p>
- Own Id: OTP-9319 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosFileTransfer 1.1.10</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Removed obsolete SSL dependency.</p>
- <p>
- Own Id: OTP-8374 Aux Id:</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The documentation EIX file was not generated.</p>
- <p>Own id: OTP-8355 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosFileTransfer 1.1.9</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- The documentation is now built with open source tools (xsltproc and fop)
- that exists on most platforms. One visible change is that the frames are removed.</p>
- <p>
- Own Id: OTP-8201 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosFileTransfer 1.1.8</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Obsolete guards, e.g. record vs is_record, has been changed
- to avoid compiler warnings.</p>
- <p>Own id: OTP-7987</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosFileTransfer 1.1.7</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Updated file headers.</p>
- <p>Own id: OTP-7837</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosFileTransfer 1.1.6</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Documentation source included in open source releases.</p>
- <p>Own id: OTP-7595</p>
- </item>
- </list>
- </section>
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>When using predefined native file copy the return values from
- file operation was not handled correctly.</p>
- <p>Own id: OTP-7599</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosFileTransfer 1.1.5</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>CosFileTransfer now uses the changed Inets API.</p>
- <p>Own id: OTP-7020</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosFileTransfer 1.1.4</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The documentation source has been converted from SGML to XML.</p>
- <p>Own id: OTP-6754</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosFileTransfer 1.1.3</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Minor Makefile changes.</p>
- <p>Own id: OTP-6701</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosFileTransfer 1.1.2</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Due to changed behavior of the ftp client a few changes
- has been made.</p>
- <p>Own id: OTP-5135</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosFileTransfer 1.1.1</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>Depending on which ftp server is used, the operation
- CosFileTransfer::Directory::list could fail.</p>
- <p>Own id: OTP-4954</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosFileTransfer 1.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The stub/skeleton-files generated by IC have been improved,
- i.e., depending on the IDL-files, reduced the size of the
- erl- and beam-files and decreased dependencies off Orber's
- Interface Repository. It is necessary to re-compile all IDL-files
- and use COS-applications, including Orber, compiled with
- IC-4.2.</p>
- <p>Own id: OTP-4576</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosFileTransfer 1.0.2</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>First release of the cosFileTransfer application. Please note that
- the OMG specification was not finalized when this version
- was released. Hence, the API may be changed in way which is not
- compatible with this version. Contact support if you are in doubt.</p>
- <p>Own Id: -</p>
- </item>
- </list>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosFileTransfer/doc/src/part.xml b/lib/cosFileTransfer/doc/src/part.xml
deleted file mode 100644
index b4e6f573dd..0000000000
--- a/lib/cosFileTransfer/doc/src/part.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosFileTransfer User's Guide</title>
- <prepared></prepared>
- <docno></docno>
- <date>2000-08-24</date>
- <rev>1.0</rev>
- </header>
- <description>
- <p>The cosFileTransfer Application is an Erlang implementation of the OMG
- CORBA FileTransfer Service.</p>
- </description>
- <xi:include href="ch_contents.xml"/>
- <xi:include href="ch_introduction.xml"/>
- <xi:include href="ch_install.xml"/>
- <xi:include href="ch_system.xml"/>
- <xi:include href="ch_example.xml"/>
-</part>
-
diff --git a/lib/cosFileTransfer/doc/src/part_notes.xml b/lib/cosFileTransfer/doc/src/part_notes.xml
deleted file mode 100644
index d91de39b1f..0000000000
--- a/lib/cosFileTransfer/doc/src/part_notes.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosFileTransfer Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date>2000-08-24</date>
- <rev>1.0</rev>
- </header>
- <description>
- <p>The cosFileTransfer Application is an Erlang implementation of the OMG
- CORBA FileTransfer Service.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/cosFileTransfer/doc/src/ref_man.gif b/lib/cosFileTransfer/doc/src/ref_man.gif
deleted file mode 100644
index b13c4efd53..0000000000
--- a/lib/cosFileTransfer/doc/src/ref_man.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosFileTransfer/doc/src/ref_man.xml b/lib/cosFileTransfer/doc/src/ref_man.xml
deleted file mode 100644
index ce050128e6..0000000000
--- a/lib/cosFileTransfer/doc/src/ref_man.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE application SYSTEM "application.dtd">
-
-<application xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosFileTransfer Reference Manual</title>
- <prepared></prepared>
- <docno></docno>
- <date>2000-08-24</date>
- <rev>1.0</rev>
- </header>
- <description>
- <p>The cosFileTransfer Application is an Erlang implementation of the OMG
- CORBA File Transfer Service.</p>
- </description>
- <xi:include href="cosFileTransferApp.xml"/>>
- <xi:include href="CosFileTransfer_File.xml"/>>
- <xi:include href="CosFileTransfer_Directory.xml"/>>
- <xi:include href="CosFileTransfer_FileIterator.xml"/>>
- <xi:include href="CosFileTransfer_VirtualFileSystem.xml"/>>
- <xi:include href="CosFileTransfer_FileTransferSession.xml"/>>
-</application>
-
diff --git a/lib/cosFileTransfer/doc/src/summary.html.src b/lib/cosFileTransfer/doc/src/summary.html.src
deleted file mode 100644
index 4c66e147e9..0000000000
--- a/lib/cosFileTransfer/doc/src/summary.html.src
+++ /dev/null
@@ -1 +0,0 @@
-Orber OMG File Transfer Service.
diff --git a/lib/cosFileTransfer/doc/src/user_guide.gif b/lib/cosFileTransfer/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/cosFileTransfer/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosFileTransfer/ebin/.gitignore b/lib/cosFileTransfer/ebin/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosFileTransfer/ebin/.gitignore
+++ /dev/null
diff --git a/lib/cosFileTransfer/examples/.gitignore b/lib/cosFileTransfer/examples/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosFileTransfer/examples/.gitignore
+++ /dev/null
diff --git a/lib/cosFileTransfer/include/.gitignore b/lib/cosFileTransfer/include/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosFileTransfer/include/.gitignore
+++ /dev/null
diff --git a/lib/cosFileTransfer/info b/lib/cosFileTransfer/info
deleted file mode 100644
index e5ca860f1c..0000000000
--- a/lib/cosFileTransfer/info
+++ /dev/null
@@ -1,3 +0,0 @@
-group: orb
-short: Orber OMG File Transfer Service
-
diff --git a/lib/cosFileTransfer/priv/.gitignore b/lib/cosFileTransfer/priv/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosFileTransfer/priv/.gitignore
+++ /dev/null
diff --git a/lib/cosFileTransfer/src/CosFileTransfer.cfg b/lib/cosFileTransfer/src/CosFileTransfer.cfg
deleted file mode 100644
index a98f102e73..0000000000
--- a/lib/cosFileTransfer/src/CosFileTransfer.cfg
+++ /dev/null
@@ -1,10 +0,0 @@
-{this, "CosFileTransfer::Directory"}.
-{{handle_info, "CosFileTransfer::Directory"}, true}.
-{this, "CosFileTransfer::File"}.
-{{handle_info, "CosFileTransfer::File"}, true}.
-{this, "CosFileTransfer::VirtualFileSystem"}.
-{{handle_info, "CosFileTransfer::VirtualFileSystem"}, true}.
-{this, "CosFileTransfer::FileTransferSession"}.
-{{handle_info, "CosFileTransfer::FileTransferSession"}, true}.
-{this, "CosFileTransfer::FileIterator"}.
-{{handle_info, "CosFileTransfer::FileIterator"}, true}.
diff --git a/lib/cosFileTransfer/src/CosFileTransfer.idl b/lib/cosFileTransfer/src/CosFileTransfer.idl
deleted file mode 100644
index 2eb310478a..0000000000
--- a/lib/cosFileTransfer/src/CosFileTransfer.idl
+++ /dev/null
@@ -1,157 +0,0 @@
-//File: CosFileTransfer.idl
-#ifndef _COS_FILE_TRANSFER_IDL_
-#define _COS_FILE_TRANSFER_IDL_
-
-#include <CosProperty.idl>
-#pragma prefix "omg.org"
-
-module CosFileTransfer {
-
- typedef string Istring;
- typedef Istring ProtocolAddress;
- typedef long ContentType;
-
- const ContentType FTAM_1 = 1;
- const ContentType FTAM_2 = 2;
- const ContentType FTAM_3 = 3;
- const ContentType FTAM_4 = 4;
- const ContentType FTAM_5 = 5;
- const ContentType NBS_9 = 6;
- const ContentType INTAP_1 = 7;
-
- exception CommandNotImplementedException { Istring reason; };
- exception SessionException { Istring reason; };
- exception TransferException { Istring reason; };
- exception FileNotFoundException { Istring reason; };
- exception RequestFailureException { Istring reason; };
- exception IllegalOperationException { Istring reason; };
-
- interface VirtualFileSystem;
-
- struct AccessLevel {
- boolean read;
- boolean insert;
- boolean replace;
- boolean extend;
- boolean erase;
- boolean read_attr;
- boolean change_attr;
- boolean delete;
- };
-
- typedef sequence<ProtocolAddress> ProtocolAddressList;
-
- struct ProtocolSupport {
- Istring protocol_name;
- ProtocolAddressList addresses;
- };
-
- typedef sequence<ProtocolSupport> SupportedProtocolAddresses;
-
- interface Directory;
- interface FileTransferSession;
-
- typedef Istring FileName;
- typedef sequence<FileName> FileNameList;
-
- interface File:CosPropertyService::PropertySetDef {
-
- readonly attribute FileName name;
- readonly attribute FileNameList complete_file_name;
- readonly attribute Directory parent;
- readonly attribute FileTransferSession associated_session;
-
- };
-
- enum FileType {nfile, ndirectory};
-
- struct FileWrapper {
- File the_file;
- FileType file_type;
- };
-
- typedef sequence<FileWrapper> FileList;
-
- interface FileIterator;
- interface Directory : File {
-
- void list(in unsigned long how_many, out FileList fl, out FileIterator fi);
-
- };
-
- interface FileIterator {
-
- boolean next_one(out FileWrapper f);
- boolean next_n(in unsigned long how_many, out FileList fl);
-
- void destroy();
- };
-
- interface FileTransferSession {
-
- readonly attribute SupportedProtocolAddresses protocols_supported;
-
- void set_directory(in Directory new_directory)
- raises(SessionException, FileNotFoundException, RequestFailureException,
- IllegalOperationException);
-
- File create_file(in FileNameList name)
- raises(SessionException, FileNotFoundException, RequestFailureException,
- IllegalOperationException);
-
- Directory create_directory(in FileNameList name)
- raises(SessionException, FileNotFoundException, RequestFailureException,
- IllegalOperationException);
-
- FileWrapper get_file(in FileNameList complete_file_name)
- raises(SessionException, FileNotFoundException, RequestFailureException,
- IllegalOperationException);
-
- void delete(in File file)
- raises(SessionException, FileNotFoundException, RequestFailureException,
- IllegalOperationException);
-
- void transfer(in File src, in File dest)
- raises(SessionException, TransferException, FileNotFoundException,
- RequestFailureException, IllegalOperationException);
-
- void append(in File src, in File dest)
- raises(CommandNotImplementedException, SessionException, TransferException,
- FileNotFoundException, RequestFailureException,
- IllegalOperationException);
-
- void insert(in File src, in File dest, in long offset)
- raises(CommandNotImplementedException, SessionException, TransferException,
- FileNotFoundException, RequestFailureException,
- IllegalOperationException);
-
- void logout();
-
- // WARNING!!!
- // Theses are Orber specific operations and may only be used internally!!
- // Maybe removed, altered and changed in any way without warning!!
- Directory oe_orber_create_directory_current()
- raises(SessionException, FileNotFoundException, IllegalOperationException);
- FileList oe_orber_get_content(in FileNameList complete_file_name,
- in Directory parent);
- long oe_orber_count_children(in FileNameList complete_file_name);
-
- };
-
- interface VirtualFileSystem {
-
- enum NativeFileSystemType { FTAM, FTP, NATIVE };
-
- readonly attribute NativeFileSystemType file_system_type;
-
- typedef sequence<ContentType> ContentList;
-
- readonly attribute ContentList supported_content_types;
-
- FileTransferSession login(in Istring username, in Istring password,
- in Istring account, out Directory root)
- raises(SessionException, FileNotFoundException, IllegalOperationException);
- };
-};
-
-#endif //_COS_FILE_TRANSFER_IDL_
diff --git a/lib/cosFileTransfer/src/CosFileTransfer_Directory_impl.erl b/lib/cosFileTransfer/src/CosFileTransfer_Directory_impl.erl
deleted file mode 100644
index 8ce6cebf77..0000000000
--- a/lib/cosFileTransfer/src/CosFileTransfer_Directory_impl.erl
+++ /dev/null
@@ -1,453 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosFileTransfer_Directory_impl
-%% Description :
-%%
-%% Created : 12 Sept 2000
-%%----------------------------------------------------------------------
--module('CosFileTransfer_Directory_impl').
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
--include_lib("cosProperty/include/CosPropertyService.hrl").
-
--include("cosFileTransferApp.hrl").
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
--export([init/1,
- terminate/2]).
-
-%% Interface functions
--export([list/3]).
-
-%% Inherited CosFileTransfer::File
--export(['_get_name'/2,
- '_get_complete_file_name'/2,
- '_get_parent'/2,
- '_get_associated_session'/2]).
-
-%% Inherited CosPropertyService::PropertySetDef
--export([get_allowed_property_types/2,
- get_allowed_properties/2,
- define_property_with_mode/5,
- define_properties_with_modes/3,
- get_property_mode/3,
- get_property_modes/3,
- set_property_mode/4,
- set_property_modes/3]).
-
-%% Inherited CosPropertyService::PropertySet
--export([define_property/4,
- define_properties/3,
- get_number_of_properties/2,
- get_all_property_names/3,
- get_property_value/3,
- get_properties/3,
- get_all_properties/3,
- delete_property/3,
- delete_properties/3,
- delete_all_properties/2,
- is_property_defined/3]).
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {property,
- name,
- completeName,
- parent,
- assocSession}).
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
--define(create_InitState(Pr, N, C, Pa, A),
- #state{property = Pr,
- name = N,
- completeName = C,
- parent = Pa,
- assocSession = A}).
-
--define(get_PropertyRef(S), S#state.property).
--define(get_Name(S), S#state.name).
--define(get_CompleteName(S), S#state.completeName).
--define(get_Parent(S), S#state.parent).
--define(get_AssocSession(S), S#state.assocSession).
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%----------------------------------------------------------------------
-init([Name, CompleteName, Parent, AssocSession]) ->
- PropTypes = [tk_long, tk_boolean],
- %% WARNING if the order of the properties is changed so must
- %% get_all_properties/3 in this module be as well!
- PropDefs = [#'CosPropertyService_PropertyDef'
- {property_name = "num_children",
- property_value = #any{typecode=tk_long, value=0},
- property_mode = fixed_readonly},
- #'CosPropertyService_PropertyDef'
- {property_name = "is_directory",
- property_value = #any{typecode=tk_boolean, value=true},
- property_mode = fixed_readonly}],
- Prop = cosProperty:create_static_SetDef(PropTypes, PropDefs),
- {ok, ?create_InitState(Prop, Name, CompleteName, Parent, AssocSession)}.
-
-%%----------------------------------------------------------------------
-%% Function : terminate/2
-%% Returns : any (ignored by gen_server)
-%% Description: Shutdown the server
-%%----------------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-%%======================================================================
-%% CosFileTransfer::Directory
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : list
-%% Arguments : Max - ulong()
-%% Returns : {ok, FileList, FileIterator}
-%% Description:
-%%----------------------------------------------------------------------
-list(OE_This, State, Max) ->
- case 'CosFileTransfer_FileTransferSession':
- oe_orber_get_content(?get_AssocSession(State), ?get_CompleteName(State),
- OE_This) of
- [] ->
- {reply, {ok, [], corba:create_nil_objref()}, State};
- FileList when length(FileList) > Max ->
- {reply,
- {ok, lists:sublist(FileList, Max),
- 'CosFileTransfer_FileIterator':oe_create([lists:nthtail(Max,
- FileList)])},
- State};
- FileList ->
- {reply, {ok, FileList, corba:create_nil_objref()}, State}
- end.
-
-%%======================================================================
-%% CosFileTransfer::File
-%%======================================================================
-%%---------------------------------------------------------------------%
-%% Function : '_get_name'
-%% Arguments : -
-%% Returns : CosFileTransfer::FileName - string
-%% Description:
-%%----------------------------------------------------------------------
-'_get_name'(_OE_This, State) ->
- {reply, ?get_Name(State), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : '_get_complete_file_name'
-%% Arguments : -
-%% Returns : CosFileTransfer::FileNameList - a list of strings's
-%% Description:
-%%----------------------------------------------------------------------
-'_get_complete_file_name'(_OE_This, State) ->
- {reply, ?get_CompleteName(State), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : '_get_parent'
-%% Arguments : -
-%% Returns : CosFileTransfer::Directory
-%% Description:
-%%----------------------------------------------------------------------
-'_get_parent'(_OE_This, State) ->
- {reply, ?get_Parent(State), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : '_get_associated_session'
-%% Arguments : -
-%% Returns : CosFileTransfer::FileTransferSession
-%% Description:
-%%----------------------------------------------------------------------
-'_get_associated_session'(_OE_This, State) ->
- {reply, ?get_AssocSession(State), State}.
-
-%%======================================================================
-%% CosPropertyService::PropertySetDef
-%%======================================================================
-%%---------------------------------------------------------------------%
-%% Function : get_allowed_property_types
-%% Arguments : -
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-get_allowed_property_types(_OE_This, State) ->
- {reply, 'CosPropertyService_PropertySetDef':
- get_allowed_property_types(?get_PropertyRef(State)), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : get_allowed_properties
-%% Arguments : -
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-get_allowed_properties(_OE_This, State) ->
- {reply, 'CosPropertyService_PropertySetDef':
- get_allowed_properties(?get_PropertyRef(State)), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : define_property_with_mode
-%% Arguments : Name - string()
-%% Value - #any{}
-%% Mode - normal | read_only | fixed_normal | fixed_readonly
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-define_property_with_mode(_OE_This, State, Name, Value, Mode) ->
- {reply, 'CosPropertyService_PropertySetDef':
- define_property_with_mode(?get_PropertyRef(State), Name, Value, Mode), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : define_properties_with_modes
-%% Arguments : PropertyDefs - list of #'CosPropertyService_PropertyDef'{}
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-define_properties_with_modes(_OE_This, State, PropertyDefs) ->
- {reply, 'CosPropertyService_PropertySetDef':
- define_properties_with_modes(?get_PropertyRef(State), PropertyDefs), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : get_property_mode
-%% Arguments : Name - string()
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-get_property_mode(_OE_This, State, Name) ->
- {reply, 'CosPropertyService_PropertySetDef':
- get_property_mode(?get_PropertyRef(State), Name), State}.
-
-
-%%---------------------------------------------------------------------%
-%% Function : get_property_modes
-%% Arguments : Names - a list of Name (i.e. string()'s).
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-get_property_modes(_OE_This, State, Names) ->
- {reply, 'CosPropertyService_PropertySetDef':
- get_property_modes(?get_PropertyRef(State), Names), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : set_property_mode
-%% Arguments : Name - string()
-%% Mode - normal | read_only | fixed_normal | fixed_readonly
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-set_property_mode(_OE_This, State, Name, Mode) ->
- {reply, 'CosPropertyService_PropertySetDef':
- set_property_mode(?get_PropertyRef(State), Name, Mode), State}.
-
-
-%%---------------------------------------------------------------------%
-%% Function : set_property_modes
-%% Arguments : Modes - a list of #'CosPropertyService_PropertyModes'{}
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-set_property_modes(_OE_This, State, PropertyModes) ->
- {reply, 'CosPropertyService_PropertySetDef':
- set_property_modes(?get_PropertyRef(State), PropertyModes), State}.
-
-%%======================================================================
-%% CosPropertyService::PropertySet
-%%======================================================================
-%%---------------------------------------------------------------------%
-%% Function : define_property
-%% Arguments : Name - string()
-%% Value - #any{}
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-define_property(_OE_This, State, Name, Value) ->
- {reply, 'CosPropertyService_PropertySet':
- define_property(?get_PropertyRef(State), Name, Value), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : define_properties
-%% Arguments : Properties - a list of #'CosPropertyService_Property'{}
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-define_properties(_OE_This, State, Properties) ->
- {reply, 'CosPropertyService_PropertySet':
- define_properties(?get_PropertyRef(State), Properties), State}.
-
-
-%%---------------------------------------------------------------------%
-%% Function : get_number_of_properties
-%% Arguments : -
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-get_number_of_properties(_OE_This, State) ->
- {reply, 'CosPropertyService_PropertySet':
- get_number_of_properties(?get_PropertyRef(State)), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : get_all_property_names
-%% Arguments : Max - ulong()
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-get_all_property_names(_OE_This, State, Max) ->
- {reply, 'CosPropertyService_PropertySet':
- get_all_property_names(?get_PropertyRef(State), Max), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : get_property_value
-%% Arguments : Name - string()
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-get_property_value(_OE_This, State, "num_children") ->
- Count = 'CosFileTransfer_FileTransferSession':
- oe_orber_count_children(?get_AssocSession(State), ?get_CompleteName(State)),
- {reply, #any{typecode=tk_long, value=Count}, State};
-get_property_value(_OE_This, State, Name) ->
- {reply, 'CosPropertyService_PropertySet':
- get_property_value(?get_PropertyRef(State), Name), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : get_properties
-%% Arguments : Names - a list of Name (i.e. string()'s)
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-get_properties(_OE_This, State, Names) ->
- {Bool, Props} =
- 'CosPropertyService_PropertySet':get_properties(?get_PropertyRef(State),
- Names),
- NewProps = change_property(Props, [], State),
- {reply, {Bool, NewProps}, State}.
-
-change_property([], Acc, _State) ->
- Acc;
-change_property([H|T], Acc, State) ->
- NewAcc =
- case H of
- #'CosPropertyService_Property'{property_name = "num_children"} ->
- Count = 'CosFileTransfer_FileTransferSession':
- oe_orber_count_children(?get_AssocSession(State),
- ?get_CompleteName(State)),
- [H#'CosPropertyService_Property'
- {property_value = #any{typecode=tk_long, value=Count}}|Acc];
- _ ->
- [H|Acc]
- end,
- change_property(T, NewAcc, State).
-
-%%---------------------------------------------------------------------%
-%% Function : get_all_properties
-%% Arguments : Max - ulong()
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-get_all_properties(_OE_This, State, 0) ->
- %% WARNING if we start supporting more than 10 Properties the next line must
- %% be updated!
- {ok, Props, _Iterator} =
- 'CosPropertyService_PropertySet':get_all_properties(?get_PropertyRef(State),
- 10),
- NewProps = change_property(Props, [], State),
- %% WARNING if the cosProperty:start_PropertiesIterator/1 is updated
- %% it must be done hear as well.
- {reply, {ok, [], cosProperty:start_PropertiesIterator(NewProps)}, State};
-get_all_properties(_OE_This, State, Max) ->
- {ok, Props, Iterator} =
- 'CosPropertyService_PropertySet':get_all_properties(?get_PropertyRef(State),
- Max),
- NewProps = change_property(Props, [], State),
- {reply, {ok, NewProps, Iterator}, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : delete_property
-%% Arguments : Name - string()
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-delete_property(_OE_This, State, Name) ->
- {reply, 'CosPropertyService_PropertySet':
- delete_property(?get_PropertyRef(State), Name), State}.
-
-
-%%---------------------------------------------------------------------%
-%% Function : delete_properties
-%% Arguments : Names - a list of Name (i.e. string()'s)
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-delete_properties(_OE_This, State, Names) ->
- {reply, 'CosPropertyService_PropertySet':
- delete_properties(?get_PropertyRef(State), Names), State}.
-
-
-%%---------------------------------------------------------------------%
-%% Function : delete_all_properties
-%% Arguments : -
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-delete_all_properties(_OE_This, State) ->
- {reply, 'CosPropertyService_PropertySet':
- delete_all_properties(?get_PropertyRef(State)), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : is_property_defined
-%% Arguments : Name - string()
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-is_property_defined(_OE_This, State, Name) ->
- {reply, 'CosPropertyService_PropertySet':
- is_property_defined(?get_PropertyRef(State), Name), State}.
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
-
diff --git a/lib/cosFileTransfer/src/CosFileTransfer_FileIterator_impl.erl b/lib/cosFileTransfer/src/CosFileTransfer_FileIterator_impl.erl
deleted file mode 100644
index d824129147..0000000000
--- a/lib/cosFileTransfer/src/CosFileTransfer_FileIterator_impl.erl
+++ /dev/null
@@ -1,158 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosFileTransfer_FileIterator_impl.erl
-%% Description :
-%%
-%% Created : 12 Sept 2000
-%%----------------------------------------------------------------------
--module('CosFileTransfer_FileIterator_impl').
-
-
-
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include("cosFileTransferApp.hrl").
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
--export([init/1,
- terminate/2,
- code_change/3,
- handle_info/2]).
-
-%% Interface functions
--export([next_one/2,
- next_n/3,
- destroy/2]).
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
--export([]).
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%----------------------------------------------------------------------
-init([FileList]) ->
- {ok, FileList}.
-
-%%----------------------------------------------------------------------
-%% Function : terminate/2
-%% Returns : any (ignored by gen_server)
-%% Description: Shutdown the server
-%%----------------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-%%----------------------------------------------------------------------
-%% Function : code_change/3
-%% Returns : {ok, NewState}
-%% Description: Convert process state when code is changed
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%---------------------------------------------------------------------%
-%% function : handle_info/2
-%% Arguments:
-%% Returns :
-%% Effect :
-%%----------------------------------------------------------------------
-handle_info(Info, State) ->
- case Info of
- {'EXIT', _Pid, Reason} ->
- {stop, Reason, State};
- _Other ->
- {noreply, State}
- end.
-
-%%======================================================================
-%% CosFileTransfer::FileIterator
-%%======================================================================
-%%---------------------------------------------------------------------%
-%% Function : next_one
-%% Arguments :
-%% Returns : {boolean(), FileWrapper}
-%% Description:
-%%----------------------------------------------------------------------
-next_one(_OE_This, []) ->
- {reply, {false,
- #'CosFileTransfer_FileWrapper'{the_file = corba:create_nil_objref(),
- file_type = nfile}}, []};
-next_one(_OE_This, [FileWrapper]) ->
- {reply, {true, FileWrapper}, []};
-next_one(_OE_This, [FileWrapper|Rest]) ->
- {reply, {true, FileWrapper}, Rest}.
-
-%%---------------------------------------------------------------------%
-%% Function : next_n
-%% Arguments : HowMany - ulong()
-%% Returns : {boolean(), FileWrapperList}
-%% Description:
-%%----------------------------------------------------------------------
-next_n(_OE_This, [], _) ->
- {reply, {false, []}, []};
-next_n(_OE_This, FileWrapperList, HowMany) when HowMany > length(FileWrapperList) ->
- {reply, {true, FileWrapperList}, []};
-next_n(_OE_This, FileWrapperList, HowMany) ->
- {reply, {true, lists:sublist(FileWrapperList, HowMany)},
- lists:nthtail(HowMany, FileWrapperList)}.
-
-%%---------------------------------------------------------------------%
-%% Function : destroy
-%% Arguments : -
-%% Returns : -
-%% Description:
-%%----------------------------------------------------------------------
-destroy(_OE_This, State) ->
- {stop, normal, ok, State}.
-
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-
-
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
diff --git a/lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl b/lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl
deleted file mode 100644
index 3a8285f092..0000000000
--- a/lib/cosFileTransfer/src/CosFileTransfer_FileTransferSession_impl.erl
+++ /dev/null
@@ -1,1061 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosFileTransfer_FileTransferSession_impl.erl
-%% Description :
-%%
-%% Created : 12 Sept 2000
-%%----------------------------------------------------------------------
--module('CosFileTransfer_FileTransferSession_impl').
-
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
--include("cosFileTransferApp.hrl").
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
--export([init/1,
- terminate/2,
- code_change/3,
- handle_info/2]).
-
-%% Interface functions
--export(['_get_protocols_supported'/2,
- set_directory/3,
- create_file/3,
- create_directory/3,
- get_file/3,
- delete/3,
- transfer/4,
- append/4,
- insert/5,
- logout/2]).
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
--export([oe_orber_create_directory_current/2, oe_orber_get_content/4,
- oe_orber_count_children/3]).
--export([invoke_call/3]).
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {protocols, server, type, current, module, connection, mytype,
- connection_timeout}).
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
--define(create_InitState(P, S, T, C, M, Co, Ty, CT),
- #state{protocols=P, server=S, type=T, current=C, module=M, connection=Co,
- mytype=Ty, connection_timeout=CT}).
-
--define(get_Protocols(S), S#state.protocols).
--define(get_Server(S), S#state.server).
--define(get_CurrentDir(S), S#state.current).
--define(get_Module(S), S#state.module).
--define(get_Connection(S), S#state.connection).
--define(get_MyType(S), S#state.mytype).
--define(get_ConnectionTimeout(S), S#state.connection_timeout).
--define(set_CurrentDir(S, C), S#state{current=C}).
-
--define(is_FTP(S), S#state.type=='FTP').
--define(is_FTAM(S), S#state.type=='FTAM').
--define(is_NATIVE(S), S#state.type=='NATIVE').
--define(is_ORBER_NATIVE(S), S#state.module==cosFileTransferNATIVE_file).
-
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%----------------------------------------------------------------------
-init(['FTP', Host, Port, User, Password, _Account, Protocol, Timeout]) ->
- {ok, Pid} = inets:start(ftpc, [{host, Host}, {port, Port}], stand_alone),
- ok = ftp:user(Pid, User, Password),
- {ok, PWD} = ftp:pwd(Pid),
- {Connection, ProtocolSupport} = setup_local(Protocol),
- {ok, ?create_InitState(ProtocolSupport, Pid, 'FTP',
- PWD, ftp, Connection, Protocol, Timeout)};
-init([{'NATIVE', Mod}, Host, Port, User, Password, _Account, Protocol, Timeout]) ->
- {ok, Pid} = Mod:open(Host, Port),
- ok = Mod:user(Pid, User, Password),
- {ok, PWD} = Mod:pwd(Pid),
- {Connection, ProtocolSupport} = setup_local(Protocol),
- {ok, ?create_InitState(ProtocolSupport, Pid, 'NATIVE',
- PWD, Mod, Connection, Protocol, Timeout)}.
-
-
-%%----------------------------------------------------------------------
-%% Function : terminate/2
-%% Returns : any (ignored by gen_server)
-%% Description: Shutdown the server
-%%----------------------------------------------------------------------
-terminate(_Reason, #state{type = Type, server = Server, module = Mod} = State) ->
- case ?get_MyType(State) of
- ssl ->
- catch ssl:close(?get_Connection(State));
- _ ->
- catch gen_tcp:close(?get_Connection(State))
- end,
- case Type of
- 'FTP' ->
- inets:stop(ftpc, Server);
- 'NATIVE' ->
- Mod:close(Server);
- _ ->
- ok
- end,
- ok.
-
-%%----------------------------------------------------------------------
-%% Function : code_change/3
-%% Returns : {ok, NewState}
-%% Description: Convert process state when code is changed
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%---------------------------------------------------------------------%
-%% function : handle_info/2
-%% Arguments:
-%% Returns :
-%% Effect :
-%%----------------------------------------------------------------------
-handle_info(Info, State) ->
- case Info of
- {'EXIT', _Pid, Reason} ->
- {stop, Reason, State};
- _Other ->
- {noreply, State}
- end.
-
-%%======================================================================
-%% CosFileTransfer::FileTransferSession
-%%======================================================================
-%%---------------------------------------------------------------------%
-%% Function : _get_protocols_supported
-%% Arguments :
-%% Returns : A list of CosFileTransfer::ProtocolSupport, i.e.,
-%% struct ProtocolSupport {
-%% Istring protocol_name;
-%% ProtocolAddressList addresses; %% eq a list of strings.
-%% };
-%% Description:
-%%----------------------------------------------------------------------
-'_get_protocols_supported'(_OE_This, State) ->
- {reply, ?get_Protocols(State), State}.
-
-%%----------------------------------------------------------------------
-%% Function : set_directory
-%% Arguments : Directory - CosFileTransfer::Directory
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-set_directory(_OE_This, State, Directory) when ?is_FTP(State); ?is_NATIVE(State) ->
- Mod = ?get_Module(State),
- Path = filename:join('CosFileTransfer_Directory':
- '_get_complete_file_name'(Directory)),
- case catch Mod:cd(?get_Server(State), Path) of
- ok ->
- {reply, ok, ?set_CurrentDir(State, Path)};
- {error, epath} ->
- corba:raise(#'CosFileTransfer_FileNotFoundException'
- {reason="Directory not found."});
- {error, elogin} ->
- corba:raise(#'CosFileTransfer_SessionException'
- {reason="User not loggen in."});
- {error, econn} ->
- corba:raise(#'CosFileTransfer_RequestFailureException'
- {reason="Premature connection ending."});
- _ ->
- corba:raise(#'CosFileTransfer_RequestFailureException'
- {reason = "Unexpected error."})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : create_file
-%% Arguments : FileNameList
-%% Returns : File
-%% Description: This operation creates a File Object representing a
-%% file which may or may not exist. Typically used as
-%% argument when invoking transfer/3. See also get_file/2.
-%%----------------------------------------------------------------------
-create_file(OE_This, State, FileNameList) ->
- {reply, cosFileTransferApp:create_file(OE_This, FileNameList), State}.
-
-%%----------------------------------------------------------------------
-%% Function : create_directory
-%% Arguments : FileNameList - full path name.
-%% Returns : Directory
-%% Description:
-%%----------------------------------------------------------------------
-create_directory(OE_This, State, FileNameList) when ?is_FTP(State);
- ?is_NATIVE(State) ->
- Mod = ?get_Module(State),
- case Mod:mkdir(?get_Server(State), filename:join(FileNameList)) of
- ok ->
- {reply, cosFileTransferApp:create_dir(OE_This, FileNameList), State};
- {error, epath} ->
- corba:raise(#'CosFileTransfer_FileNotFoundException'
- {reason="Directory not found."});
- {error, elogin} ->
- corba:raise(#'CosFileTransfer_SessionException'
- {reason="User not loggen in."});
- {error, econn} ->
- corba:raise(#'CosFileTransfer_RequestFailureException'
- {reason="Premature connection ending."});
- _ ->
- corba:raise(#'CosFileTransfer_RequestFailureException'
- {reason="Unknown error."})
- end.
-
-
-%%----------------------------------------------------------------------
-%% Function : get_file
-%% Arguments : FileNameList
-%% Returns : FileWrapper
-%% Description: This operation should be independent of the working Directory,
-%% i.e., a full path name must be supplied. The file or
-%% directory the returned object is supposed to represent
-%% MUST(!!!!) exist.
-%%----------------------------------------------------------------------
-get_file(OE_This, State, FileNameList) when ?is_FTP(State);
- ?is_NATIVE(State) ->
- case check_type(OE_This, State, filename:join(FileNameList)) of
- {ndirectory, _Listing} ->
- {reply,
- #'CosFileTransfer_FileWrapper'{the_file =
- cosFileTransferApp:
- create_dir(OE_This,
- FileNameList),
- file_type = ndirectory},
- State};
- nfile ->
- {reply,
- #'CosFileTransfer_FileWrapper'{the_file =
- cosFileTransferApp:
- create_file(OE_This,
- FileNameList),
- file_type = nfile},
- State};
- Other ->
- %% If we want to return {stop, ....}
- Other
- end.
-
-%%----------------------------------------------------------------------
-%% Function : delete
-%% Arguments : File
-%% Returns : -
-%% Description:
-%%----------------------------------------------------------------------
-delete(_OE_This, State, File) when ?is_FTP(State); ?is_NATIVE(State) ->
- Mod = ?get_Module(State),
- Result =
- case 'CosPropertyService_PropertySet':
- get_property_value(File, "is_directory") of
- #any{value=false} ->
- Mod:delete(?get_Server(State),
- filename:join('CosFileTransfer_File':
- '_get_complete_file_name'(File)));
- #any{value=true} ->
- Mod:rmdir(?get_Server(State),
- filename:join('CosFileTransfer_File':
- '_get_complete_file_name'(File)));
- Other ->
- Other
- end,
- case Result of
- ok ->
- {reply, ok, State};
- {error, epath} ->
- corba:raise(#'CosFileTransfer_FileNotFoundException'
- {reason="File or Directory not found."});
- {error, elogin} ->
- corba:raise(#'CosFileTransfer_SessionException'
- {reason="User not loggen in."});
- {error, econn} ->
- corba:raise(#'CosFileTransfer_RequestFailureException'
- {reason="Premature connection ending."});
- _ ->
- corba:raise(#'CosFileTransfer_RequestFailureException'
- {reason="Unknown error."})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : transfer
-%% Arguments : SrcFile eq DestFile eq CosFileTransfer::File
-%% Returns : -
-%% Description: DestFile must be a newly created File object, using create_file()
-%% on the Target FileTransferSession, prior to calling transfer().
-%%----------------------------------------------------------------------
-transfer(OE_This, State, SrcFile, DestFile) when ?is_ORBER_NATIVE(State) ->
- case which_FTS_type(OE_This, SrcFile, DestFile) of
- {source, TargetFTS} ->
- %% The source FTS is supposed to be the active one, set up a connection.
- Protocols = 'CosFileTransfer_FileTransferSession':
- '_get_protocols_supported'(TargetFTS),
- SrcName = 'CosFileTransfer_File':'_get_complete_file_name'(SrcFile),
- Pid = spawn(?MODULE, invoke_call, [self(), transfer,
- [TargetFTS, SrcFile, DestFile]]),
- send_file(Protocols, ?get_MyType(State), ?get_ConnectionTimeout(State),
- filename:join(SrcName)),
- check_reply(Pid),
- {reply, ok, State};
- {target, _SourceFTS} ->
- DestName = 'CosFileTransfer_File':'_get_complete_file_name'(DestFile),
- receive_file(?get_MyType(State), ?get_Connection(State),
- ?get_ConnectionTimeout(State),
- filename:join(DestName), write),
- {reply, ok, State}
- end;
-transfer(OE_This, State, SrcFile, DestFile) when ?is_FTP(State); ?is_NATIVE(State) ->
- case which_FTS_type(OE_This, SrcFile, DestFile) of
- {source, TargetFTS} ->
- source_FTS_operation(State, SrcFile, DestFile, transfer, 0, TargetFTS);
- {target, _SourceFTS} ->
- target_FTS_operation(State, SrcFile, DestFile, send, 0)
- end.
-
-
-%%----------------------------------------------------------------------
-%% Function : append
-%% Arguments : SrcFile eq DestFile eq CosFileTransfer::File
-%% Returns : -
-%% Description:
-%%----------------------------------------------------------------------
-append(OE_This, State, SrcFile, DestFile) when ?is_ORBER_NATIVE(State) ->
- case which_FTS_type(OE_This, SrcFile, DestFile) of
- {source, TargetFTS} ->
- SrcName = filename:join('CosFileTransfer_File':
- '_get_complete_file_name'(SrcFile)),
- check_type(OE_This, State, SrcName),
- %% The source FTS is supposed to be the active one, set up a connection.
- Protocols = 'CosFileTransfer_FileTransferSession':
- '_get_protocols_supported'(TargetFTS),
- Pid = spawn(?MODULE, invoke_call, [self(), append,
- [TargetFTS, SrcFile, DestFile]]),
- send_file(Protocols, ?get_MyType(State), ?get_ConnectionTimeout(State),
- SrcName),
- check_reply(Pid),
- {reply, ok, State};
- {target, _SourceFTS} ->
- DestName = filename:join('CosFileTransfer_File':
- '_get_complete_file_name'(DestFile)),
- check_type(OE_This, State, DestName),
- receive_file(?get_MyType(State), ?get_Connection(State),
- ?get_ConnectionTimeout(State), DestName, append),
- {reply, ok, State}
- end;
-append(OE_This, State, SrcFile, DestFile) when ?is_NATIVE(State) ->
- case which_FTS_type(OE_This, SrcFile, DestFile) of
- {source, TargetFTS} ->
- source_FTS_operation(State, SrcFile, DestFile, append, 0, TargetFTS);
- {target, _SourceFTS} ->
- target_FTS_operation(State, SrcFile, DestFile, append, 0)
- end;
-append(_OE_This, _State, _SrcFile, _DestFile) ->
- corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}).
-
-
-%%----------------------------------------------------------------------
-%% Function : insert
-%% Arguments : SrcFile eq DestFile eq CosFileTransfer::File
-%% Offset - long
-%% Returns : -
-%% Description:
-%%----------------------------------------------------------------------
-insert(OE_This, State, SrcFile, DestFile, Offset) when ?is_NATIVE(State) ->
- case which_FTS_type(OE_This, SrcFile, DestFile) of
- {source, TargetFTS} when ?is_ORBER_NATIVE(State) ->
- SrcName = 'CosFileTransfer_File':'_get_complete_file_name'(SrcFile),
- check_type(OE_This, State, filename:join(SrcName)),
- %% The source FTS is supposed to be the active one, set up a connection.
- Protocols = 'CosFileTransfer_FileTransferSession':
- '_get_protocols_supported'(TargetFTS),
- Pid = spawn(?MODULE, invoke_call, [self(), insert,
- [TargetFTS, SrcFile,
- DestFile, Offset]]),
- send_file(Protocols, ?get_MyType(State), ?get_ConnectionTimeout(State),
- filename:join(SrcName)),
- check_reply(Pid),
- {reply, ok, State};
- {source, TargetFTS} ->
- source_FTS_operation(State, SrcFile, DestFile, insert, Offset, TargetFTS);
- {target, _SourceFTS} ->
- target_FTS_operation(State, SrcFile, DestFile, insert, Offset)
- end;
-insert(_OE_This, _State, _SrcFile, _DestFile, _Offset) ->
- corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}).
-
-
-%%----------------------------------------------------------------------
-%% Function : logout
-%% Arguments : -
-%% Returns : -
-%% Description:
-%%----------------------------------------------------------------------
-logout(_OE_This, State) when ?is_FTP(State); ?is_NATIVE(State) ->
- Mod = ?get_Module(State),
- catch Mod:close(?get_Server(State)),
- {stop, normal, ok, State}.
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : oe_orber_create_directory_current
-%% Arguments : -
-%% Returns : Directory
-%% Description: Creates a Directory describing the working directory
-%% of the remote server, e.g., an FTP-server.
-%%----------------------------------------------------------------------
-oe_orber_create_directory_current(OE_This, State) when ?is_FTP(State);
- ?is_NATIVE(State) ->
- Mod = ?get_Module(State),
- FileNameList = filename:split(?get_CurrentDir(State)),
- case Mod:nlist(?get_Server(State), ?get_CurrentDir(State)) of
- {ok, _Listing} ->
- {reply, cosFileTransferApp:create_dir(OE_This, FileNameList),
- State};
- {error, epath} ->
- corba:raise(#'CosFileTransfer_FileNotFoundException'
- {reason="Directory not found."});
- {error, elogin} ->
- corba:raise(#'CosFileTransfer_SessionException'
- {reason="User not loggen in."});
- {error, econn} ->
- corba:raise(#'CosFileTransfer_RequestFailureException'
- {reason="Premature connection ending."});
- _ ->
- corba:raise(#'CosFileTransfer_RequestFailureException'
- {reason="Unknown error."})
- end.
-%%----------------------------------------------------------------------
-%% Function : oe_orber_get_content
-%% Arguments : -
-%% Returns : string
-%% Description:
-%%----------------------------------------------------------------------
-oe_orber_get_content(OE_This, State, FileNameList, Parent) when ?is_FTP(State);
- ?is_NATIVE(State) ->
- Mod = ?get_Module(State),
- case Mod:nlist(?get_Server(State), filename:join(FileNameList)) of
- {ok, Listing} ->
- create_content(Listing, OE_This, State, Parent, FileNameList);
- {error, epath} ->
- {reply, [], State};
- _ ->
- corba:raise(#'CosFileTransfer_FileNotFoundException'
- {reason="Directory not found."})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : oe_orber_count_children
-%% Arguments : -
-%% Returns : string
-%% Description:
-%%----------------------------------------------------------------------
-oe_orber_count_children(OE_This, State, FileNameList) when ?is_FTP(State);
- ?is_NATIVE(State) ->
- case catch check_type(OE_This, State, filename:join(FileNameList)) of
- {ndirectory, Members} ->
- {reply, length(Members), State};
- {stop, normal, _, _} ->
- {stop, normal,
- {'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}},
- State};
- _->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : delete_tmp_file
-%% Arguments : -
-%% Returns : ok | {'EXCEPTION', E}
-%% Description:
-%%----------------------------------------------------------------------
-delete_tmp_file(TmpFileName, ErrorMsg) ->
- case file:delete(TmpFileName) of
- ok ->
- ok;
- _ ->
- corba:raise(#'CosFileTransfer_RequestFailureException'{reason=ErrorMsg})
- end.
-
-
-%%----------------------------------------------------------------------
-%% Function : invoke_call
-%% Arguments : -
-%% Returns : ok | {'EXCEPTION', E}
-%% Description:
-%%----------------------------------------------------------------------
-invoke_call(Pid, Op, Args) ->
- Result = (catch apply('CosFileTransfer_FileTransferSession', Op, Args)),
- Pid ! {transfer_result, self(), Result},
- ok.
-
-%%----------------------------------------------------------------------
-%% Function : check_reply
-%% Arguments : Pid - the pid of the spawned process.
-%% Returns : ok | {'EXCEPTION', E}
-%% Description:
-%%----------------------------------------------------------------------
-check_reply(Pid) ->
- receive
- {transfer_result, Pid, ok} ->
- ok;
- {transfer_result, Pid, {'EXCEPTION', E}} ->
- orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:check_reply();
-Raised exception: ", [?LINE, E], ?DEBUG_LEVEL),
- corba:raise(E);
- {transfer_result, Pid, {'EXIT', Reason}} ->
- orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:check_reply();
-Got EXIT-signal with reason: ", [?LINE, Reason], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{minor=199,
- completion_status=?COMPLETED_NO})
- after infinity ->
- %% Should we add an exception here or do we reuse the iiop_timeout?
- %% For now keep as is.
- corba:raise(#'INTERNAL'{minor=199,
- completion_status=?COMPLETED_NO})
- end.
-
-
-%%----------------------------------------------------------------------
-%% Function : which_FTS_type
-%% Arguments : -
-%% Returns : {source, FTS} | {target, FTS} | {'EXCEPTION', #'BAD_PARAM'{}}
-%% Description: Used to determine if the target FTS is supposed to act
-%% as sender or receiver and also return the counter part FTS.
-%% An exception is raised if the user supplied incorrect parameters.
-%%----------------------------------------------------------------------
-which_FTS_type(OE_This, SrcFile, DestFile) ->
- TargetFTS = 'CosFileTransfer_File':'_get_associated_session'(DestFile),
- SourceFTS = 'CosFileTransfer_File':'_get_associated_session'(SrcFile),
- case corba_object:is_equivalent(OE_This, TargetFTS) of
- true ->
- {target, SourceFTS};
- false ->
- case corba_object:is_equivalent(OE_This, SourceFTS) of
- true ->
- {source, TargetFTS};
- false ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end
- end.
-
-
-%%----------------------------------------------------------------------
-%% Function : setup_connection
-%% Arguments : A list of #'CosFileTransfer_ProtocolSupport'{}
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-setup_connection([], Protocol, _) ->
- orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:setup_connection(~p);
-The Protocols listed are not supported.", [?LINE, Protocol], ?DEBUG_LEVEL),
- corba:raise(#'CosFileTransfer_TransferException'{reason="Unsupported protocol"});
-setup_connection([#'CosFileTransfer_ProtocolSupport'{protocol_name="TCP/IP",
- addresses=Addr}|_],
- tcp, Timeout) ->
- setup_connection_helper(Addr, gen_tcp, [], Timeout);
-setup_connection([#'CosFileTransfer_ProtocolSupport'{protocol_name="SSL",
- addresses=Addr}|_],
- ssl, Timeout) ->
- Options = [{certfile, cosFileTransferApp:ssl_client_certfile()},
- {verify, cosFileTransferApp:ssl_client_verify()},
- {depth, cosFileTransferApp:ssl_client_depth()}] ++
- ssl_client_cacertfile_option(),
- setup_connection_helper(Addr, ssl, Options, Timeout);
-setup_connection([_|T], Type, Timeout) ->
- setup_connection(T, Type, Timeout).
-
-setup_connection_helper([], _, _, _) ->
- corba:raise(#'CosFileTransfer_RequestFailureException'
- {reason="Unable to contact remote server."});
-setup_connection_helper([H|T], Driver, Options, Timeout) ->
- case string:tokens(H, ":") of
- [Host, Port] when Driver == gen_tcp ->
- case gen_tcp:connect(Host, list_to_integer(Port),
- [binary,
- {packet, raw},
- {reuseaddr, true},
- {nodelay, true}|Options], Timeout) of
- {ok, Sock} ->
- {gen_tcp, Sock};
- _->
- %% No response.
- setup_connection_helper(T, Driver, Options, Timeout)
- end;
- [Host, Port] when Driver == ssl ->
- case ssl:connect(Host, list_to_integer(Port),
- [binary,
- {packet, 0},
- {active, false}|Options], Timeout) of
- {ok, Sock} ->
- {ssl, Sock};
- _->
- %% No response.
- setup_connection_helper(T, Driver, Options, Timeout)
- end;
- _ ->
- %% Badly configured address.
- setup_connection_helper(T, Driver, Options, Timeout)
- end.
-
-ssl_client_cacertfile_option() ->
- case cosFileTransferApp:ssl_client_cacertfile() of
- [] ->
- [];
- X when is_list(X) ->
- {cacertfile, X};
- _ ->
- []
- end.
-
-%%----------------------------------------------------------------------
-%% Function : create_content
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-create_content(Listing, OE_This, State, Parent, PathList) ->
- create_content(string:tokens(Listing, ?SEPARATOR), OE_This,
- State, Parent, PathList, []).
-
-create_content([], _OE_This, State, _Parent, _PathList, Acc) ->
- {reply, Acc, State};
-create_content([H|T], OE_This, State, Parent, PathList, Acc) ->
- FullPathList = PathList ++[filename:basename(H)],
- case check_type(OE_This, State, filename:join(FullPathList)) of
- nfile ->
- create_content(T, OE_This, State, Parent, PathList,
- [#'CosFileTransfer_FileWrapper'
- {the_file = cosFileTransferApp:create_file(OE_This,
- FullPathList,
- Parent),
- file_type = nfile}|Acc]);
- {ndirectory, _Members} ->
- create_content(T, OE_This, State, Parent, PathList,
- [#'CosFileTransfer_FileWrapper'
- {the_file = cosFileTransferApp:create_dir(OE_This,
- FullPathList,
- Parent),
- file_type = ndirectory}|Acc]);
- Other ->
- Other
- end.
-
-
-%%----------------------------------------------------------------------
-%% Function : MISC functions
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-setup_local(tcp) ->
- {ok,Socket}=gen_tcp:listen(0, [binary,
- {packet, 0},
- {backlog,1},
- {active, false}]),
- {ok, Port} = inet:port(Socket),
- {Socket, [#'CosFileTransfer_ProtocolSupport'{protocol_name="TCP/IP",
- addresses = [local_address(Port)]}]};
-setup_local(ssl) ->
- Options = [{certfile, cosFileTransferApp:ssl_server_certfile()},
- {verify, cosFileTransferApp:ssl_server_verify()},
- {depth, cosFileTransferApp:ssl_server_depth()}] ++
- ssl_server_cacertfile_option(),
- {ok,Socket}=ssl:listen(0, [binary,
- {packet, 0},
- {backlog,1},
- {active, false}|Options]),
- {ok, {_Address, Port}} = ssl:sockname(Socket),
- {Socket, [#'CosFileTransfer_ProtocolSupport'{protocol_name="SSL",
- addresses = [local_address(Port)]}]}.
-
-local_address(Port) ->
- {ok, Hostname} = inet:gethostname(),
- {ok, {A1, A2, A3, A4}} = inet:getaddr(Hostname, inet),
- integer_to_list(A1) ++ "." ++ integer_to_list(A2) ++ "." ++ integer_to_list(A3)
- ++ "." ++ integer_to_list(A4)++":"++integer_to_list(Port).
-
-ssl_server_cacertfile_option() ->
- case cosFileTransferApp:ssl_server_cacertfile() of
- [] ->
- [];
- X when is_list(X) ->
- [{cacertfile, X}];
- _ ->
- []
- end.
-
-%%----------------------------------------------------------------------
-%% Function : source_file_operation
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-source_FTS_operation(State, SrcFile, DestFile, Op, Offset, FTS) ->
- Mod = ?get_Module(State),
- %% The source FTS is supposed to be the active one, set up a connection.
- Protocols = 'CosFileTransfer_FileTransferSession':'_get_protocols_supported'(FTS),
- SrcName = 'CosFileTransfer_File':'_get_complete_file_name'(SrcFile),
- TempName = cosFileTransferApp:create_name("TemporarySrcFile"),
- case Mod:recv(?get_Server(State), filename:join(SrcName), TempName) of
- ok when Op == insert ->
- %% Downloaded the File, we are now ready to transmit.
- Pid = spawn(?MODULE, invoke_call, [self(), insert,
- [FTS, SrcFile, DestFile, Offset]]),
- send_file(Protocols, ?get_MyType(State), ?get_ConnectionTimeout(State),
- TempName),
- %% Delete the temporary local copy.
- delete_tmp_file(TempName,
- "Transfer completed but failed to remove temporary local copy."),
- check_reply(Pid),
- {reply, ok, State};
- ok ->
- %% Downloaded the File, we are now ready to transmit.
- Pid = spawn(?MODULE, invoke_call, [self(), Op, [FTS, SrcFile, DestFile]]),
- send_file(Protocols, ?get_MyType(State), ?get_ConnectionTimeout(State),
- TempName),
- %% Delete the temporary local copy.
- delete_tmp_file(TempName,
- "Transfer completed but failed to remove temporary local copy."),
- check_reply(Pid),
- {reply, ok, State};
- {error, epath} ->
- corba:raise(#'CosFileTransfer_FileNotFoundException'
- {reason="File not found."});
- {error, elogin} ->
- corba:raise(#'CosFileTransfer_SessionException'
- {reason="User not loggen in."});
- {error, econn} ->
- corba:raise(#'CosFileTransfer_RequestFailureException'
- {reason="Premature connection ending."})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : target_file_operation
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-target_FTS_operation(State, _SrcFile, DestFile, Op, Offset) ->
- Mod = ?get_Module(State),
- DestName = 'CosFileTransfer_File':'_get_complete_file_name'(DestFile),
- TempName = cosFileTransferApp:create_name("TemporaryDestFile"),
- receive_file(?get_MyType(State), ?get_Connection(State),
- ?get_ConnectionTimeout(State), TempName, write),
- Result =
- if
- Op == insert ->
- Mod:insert(?get_Server(State), TempName, filename:join(DestName), Offset);
- true ->
- Mod:Op(?get_Server(State), TempName, filename:join(DestName))
- end,
- case Result of
- ok ->
- %% Delete the temporary local copy.
- delete_tmp_file(TempName,
- "Transfer completed but failed to remove temporary local copy."),
- %% Completed the transfer successfully.
- {reply, ok, State};
- {error, epath} ->
- delete_tmp_file(TempName,
- "IllegalOperationException and not able to remove temporary local copy."),
- corba:raise(#'CosFileTransfer_IllegalOperationException'
- {reason="Not allowed by destination."});
- {error, elogin} ->
- delete_tmp_file(TempName,
- "SessionException and not able to remove temporary local copy."),
- corba:raise(#'CosFileTransfer_SessionException'
- {reason="User not logged in."});
- {error, econn} ->
- delete_tmp_file(TempName,
- "TransferException and not able to remove temporary local copy."),
- corba:raise(#'CosFileTransfer_TransferException'
- {reason="Premature connection ending."});
- {error, etnospc} ->
- delete_tmp_file(TempName,
- "RequestFailureException and not able to remove temporary local copy."),
- corba:raise(#'CosFileTransfer_RequestFailureException'
- {reason="Premature connection ending."});
- {error, efnamena} ->
- delete_tmp_file(TempName,
- "IllegalOperationException and not able to remove temporary local copy."),
- corba:raise(#'CosFileTransfer_IllegalOperationException'
- {reason="Not allowed by destination."})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : receive_file
-%% Arguments : Driver - currently only gen_tcp supported.
-%% LSocket - which socket to use.
-%% FileName - an absolute file name representing the
-%% file we want to create or append to.
-%% Type - 'read', 'write', 'append'.
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-receive_file(tcp, LSock, Timeout, FileName, Type) ->
- %% The Type can be the ones allowed by the file-module, i.e.,
- %% 'read', 'write' or 'append'
- FD = file_open(FileName, Type),
- case gen_tcp:accept(LSock, Timeout) of
- {ok, Sock} ->
- receive_file_helper(gen_tcp, Sock, FD);
- {error, timeout} ->
- orber:dbg("[~p] CosFileTransfer_FileTransferSession:receive_file();~n"
- "gen_tcp:accept(~p) timed out", [?LINE, Timeout], ?DEBUG_LEVEL),
- corba:raise(#'CosFileTransfer_RequestFailureException'
- {reason="TCP accept timed out.."});
- {error, Why} ->
- orber:dbg("[~p] CosFileTransfer_FileTransferSession:receive_file();~n"
- "gen_tcp:accept(~p) failed: ~p", [?LINE, Timeout, Why], ?DEBUG_LEVEL),
- corba:raise(#'CosFileTransfer_RequestFailureException'
- {reason="TCP accept failed."})
- end;
-receive_file(ssl, LSock, Timeout, FileName, Type) ->
- %% The Type can be the ones allowed by the file-module, i.e.,
- %% 'read', 'write' or 'append'
- FD = file_open(FileName, Type),
- case ssl:transport_accept(LSock, Timeout) of
- {ok, Sock} ->
- case ssl:ssl_accept(Sock, Timeout) of
- ok ->
- receive_file_helper(ssl, Sock, FD);
- {error, Error} ->
- orber:dbg("[~p] CosFileTransfer_FileTransferSession:receive_file();~n"
- "ssl:ssl_accept(~p) failed: ~p",
- [?LINE, Timeout, Error], ?DEBUG_LEVEL),
- corba:raise(#'CosFileTransfer_RequestFailureException'
- {reason="TCP accept failed."})
- end;
- {error, timeout} ->
- orber:dbg("[~p] CosFileTransfer_FileTransferSession:receive_file();~n"
- "ssl:transport_accept(~p) timed out",
- [?LINE, Timeout], ?DEBUG_LEVEL),
- corba:raise(#'CosFileTransfer_RequestFailureException'
- {reason="TCP accept timed out.."});
- {error, Why} ->
- orber:dbg("[~p] CosFileTransfer_FileTransferSession:receive_file();~n"
- "ssl:transport_accept(~p) failed: ~p",
- [?LINE, Timeout, Why], ?DEBUG_LEVEL),
- corba:raise(#'CosFileTransfer_RequestFailureException'
- {reason="TCP accept failed."})
- end.
-
-receive_file_helper(Driver, Sock, FD) ->
- case Driver:recv(Sock, 0) of
- {ok, Bin} ->
- file:write(FD, Bin),
- receive_file_helper(Driver, Sock, FD);
- {error, closed} ->
- file:close(FD);
- What ->
- orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:receive_file(~p);
-Error occured when receiving data: ~p", [?LINE, Driver, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : send_file
-%% Arguments : Driver - currently only gen_tcp supported.
-%% Sock - which socket to use.
-%% FileName - an absolute file name representing the
-%% file we want to send.
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-send_file(Protocols, Type, Timeout, FileName) ->
- {Driver, Sock} = setup_connection(Protocols, Type, Timeout),
- FD = file_open(FileName, read),
- BuffSize = cosFileTransferApp:get_buffert_size(),
- send_file_helper(Driver, Sock, FD, BuffSize).
-
-send_file_helper(Driver, Sock, FD, BuffSize) ->
- case file:read(FD, BuffSize) of
- eof ->
- file:close(FD),
- Driver:close(Sock);
- {ok, Bin} ->
- case Driver:send(Sock, Bin) of
- ok ->
- send_file_helper(Driver, Sock, FD, BuffSize);
- What ->
- orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:send_file_helper(~p);
-Error occured when sending data: ~p", [?LINE, Driver, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end
- end.
-
-
-file_open(File, Type) ->
- case file:open(File, [raw, binary, Type]) of
- {ok, FD} ->
- FD;
- {error, What} ->
- orber:debug_level_print("[~p] CosFileTransfer_FileTransferSession:file_open(~p);
-Failed to open the file due to: ~p", [?LINE, File, What], ?DEBUG_LEVEL),
- corba:raise(#'CosFileTransfer_RequestFailureException'
- {reason="Unable to open given file."})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : check_type
-%% Arguments : FullName - an absolute file name representing the
-%% file or directory we want to evaluate.
-%% Returns :
-%% Description:
-%% When communcating with FTP-servers on different platforms a variety of
-%% answers can be returned. A few examples:
-%%
-%% ### ftp:nlist on an empty directory ###
-%% {ok, ""}, {error, epath}
-%%
-%% ### ftp:nlist on a non-existing directory or file ###
-%% {ok, "XXX: No such file or directory}, {error, epath}
-%%
-%% ### ftp:nlist on an existing directory with one contained item ###
-%% {ok, "Item"}
-%%
-%% Comparing the above we see that it's virtually impossible to tell apart
-%% {ok, "XXX: No such file or directory} and {ok, "Item"}.
-%% Hence, it's easier to test if it's possible to do ftp:cd instead.
-%% Ugly, but rather effective. If we look at the bright side, it's only
-%% necessary when we try to lookup:
-%% * non-existing item
-%% * A directory with one member only.
-%% * An empty directory.
-%%
-%% Furthermore, no need for traversing Listings etc.
-%%----------------------------------------------------------------------
-check_type(_OE_This, State, FullName) when ?is_FTP(State); ?is_NATIVE(State) ->
- Mod = ?get_Module(State),
- Result =
- case Mod:nlist(?get_Server(State), FullName) of
- {ok, Listing} when length(Listing) > 0->
- case string:tokens(Listing, ?SEPARATOR) of
- [FullName] ->
- nfile;
- Members when length(Members) > 1 ->
- %% Must test if more than one member since sometimes
- %% this operation returns for example:
- %% {ok, "XXX No such file or drectory"}
- {ndirectory, Members};
- Member ->
- case Mod:cd(?get_Server(State), FullName) of
- ok ->
- case Mod:cd(?get_Server(State),
- ?get_CurrentDir(State)) of
- ok ->
- {ndirectory, Member};
- _ ->
- %% Failed, we cannot continue since the
- %% FTS now pointso an incorrect Directory.
- %% Hence, we must terminate.
- {stop, normal,
- {'EXCEPTION',
- #'CosFileTransfer_RequestFailureException'
- {reason="Unknown error."}}, State}
- end;
- {error, E} ->
- {error, E};
- _ ->
- nfile
- end
- end;
- {error, epath} ->
- %% Might be a file.
- DirName = filename:dirname(FullName),
- case Mod:nlist(?get_Server(State), DirName) of
- {ok, Listing} when length(Listing) > 0->
- Members = string:tokens(Listing, ?SEPARATOR),
- case lists:member(FullName, Members) of
- true ->
- nfile;
- _ ->
- BName = filename:basename(FullName),
- case lists:member(BName, Members) of
- true ->
- nfile;
- _ ->
- {error, epath}
- end
- end;
- _ ->
- {error, epath}
- end;
- _ ->
- case Mod:cd(?get_Server(State), FullName) of
- ok ->
- case Mod:cd(?get_Server(State), ?get_CurrentDir(State)) of
- ok ->
- {ndirectory, []};
- _ ->
- %% Failed, we cannot continue since the
- %% FTS now pointso an incorrect Directory.
- %% Hence, we must terminate.
- {stop, normal,
- {'EXCEPTION',
- #'CosFileTransfer_RequestFailureException'
- {reason="Unknown error."}}, State}
- end;
- _ ->
- {error, epath}
- end
- end,
- case Result of
- {error, epath} ->
- corba:raise(#'CosFileTransfer_FileNotFoundException'
- {reason="File or Directory not found."});
- {error, elogin} ->
- corba:raise(#'CosFileTransfer_SessionException'
- {reason="User not logged in."});
- {error, econn} ->
- corba:raise(#'CosFileTransfer_RequestFailureException'
- {reason="Premature connection ending."});
- Other ->
- Other
- end.
-
-
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
diff --git a/lib/cosFileTransfer/src/CosFileTransfer_File_impl.erl b/lib/cosFileTransfer/src/CosFileTransfer_File_impl.erl
deleted file mode 100644
index 263255413e..0000000000
--- a/lib/cosFileTransfer/src/CosFileTransfer_File_impl.erl
+++ /dev/null
@@ -1,385 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosFileTransfer_File_impl.erl
-%% Description :
-%%
-%% Created : 5 Feb 2001
-%%----------------------------------------------------------------------
--module('CosFileTransfer_File_impl').
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
--include_lib("cosProperty/include/CosPropertyService.hrl").
-
--include("cosFileTransferApp.hrl").
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
--export([init/1,
- terminate/2]).
-
-%% Interface functions
--export(['_get_name'/2,
- '_get_complete_file_name'/2,
- '_get_parent'/2,
- '_get_associated_session'/2]).
-
-%% Inherited CosPropertyService::PropertySetDef
--export([get_allowed_property_types/2,
- get_allowed_properties/2,
- define_property_with_mode/5,
- define_properties_with_modes/3,
- get_property_mode/3,
- get_property_modes/3,
- set_property_mode/4,
- set_property_modes/3]).
-
-%% Inherited CosPropertyService::PropertySet
--export([define_property/4,
- define_properties/3,
- get_number_of_properties/2,
- get_all_property_names/3,
- get_property_value/3,
- get_properties/3,
- get_all_properties/3,
- delete_property/3,
- delete_properties/3,
- delete_all_properties/2,
- is_property_defined/3]).
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {property,
- name,
- completeName,
- parent,
- assocSession}).
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
--define(create_InitState(Pr, N, C, Pa, A),
- #state{property = Pr,
- name = N,
- completeName = C,
- parent = Pa,
- assocSession = A}).
-
--define(get_PropertyRef(S), S#state.property).
--define(get_Name(S), S#state.name).
--define(get_CompleteName(S), S#state.completeName).
--define(get_Parent(S), S#state.parent).
--define(get_AssocSession(S), S#state.assocSession).
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%----------------------------------------------------------------------
-init([Name, CompleteName, Parent, AssocSession]) ->
- PropTypes = [tk_boolean],
- PropDefs = [#'CosPropertyService_PropertyDef'
- {property_name = "is_directory",
- property_value = #any{typecode=tk_boolean, value=false},
- property_mode = fixed_readonly}],
- Prop = cosProperty:create_static_SetDef(PropTypes, PropDefs),
- {ok, ?create_InitState(Prop, Name, CompleteName, Parent, AssocSession)}.
-
-%%----------------------------------------------------------------------
-%% Function : terminate/2
-%% Returns : any (ignored by gen_server)
-%% Description: Shutdown the server
-%%----------------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-%%======================================================================
-%% CosFileTransfer::File
-%%======================================================================
-%%---------------------------------------------------------------------%
-%% Function : '_get_name'
-%% Arguments : -
-%% Returns : CosFileTransfer::FileName - string
-%% Description:
-%%----------------------------------------------------------------------
-'_get_name'(_OE_This, State) ->
- {reply, ?get_Name(State), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : '_get_complete_file_name'
-%% Arguments : -
-%% Returns : CosFileTransfer::FileNameList - a list of strings's
-%% Description:
-%%----------------------------------------------------------------------
-'_get_complete_file_name'(_OE_This, State) ->
- {reply, ?get_CompleteName(State), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : '_get_parent'
-%% Arguments : -
-%% Returns : CosFileTransfer::Directory
-%% Description:
-%%----------------------------------------------------------------------
-'_get_parent'(_OE_This, State) ->
- {reply, ?get_Parent(State), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : '_get_associated_session'
-%% Arguments : -
-%% Returns : CosFileTransfer::FileTransferSession
-%% Description:
-%%----------------------------------------------------------------------
-'_get_associated_session'(_OE_This, State) ->
- {reply, ?get_AssocSession(State), State}.
-
-%%======================================================================
-%% CosPropertyService::PropertySetDef
-%%======================================================================
-%%---------------------------------------------------------------------%
-%% Function : get_allowed_property_types
-%% Arguments : -
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-get_allowed_property_types(_OE_This, State) ->
- {reply, 'CosPropertyService_PropertySetDef':
- get_allowed_property_types(?get_PropertyRef(State)), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : get_allowed_properties
-%% Arguments : -
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-get_allowed_properties(_OE_This, State) ->
- {reply, 'CosPropertyService_PropertySetDef':
- get_allowed_properties(?get_PropertyRef(State)), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : define_property_with_mode
-%% Arguments : Name - string()
-%% Value - #any{}
-%% Mode - normal | read_only | fixed_normal | fixed_readonly
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-define_property_with_mode(_OE_This, State, Name, Value, Mode) ->
- {reply, 'CosPropertyService_PropertySetDef':
- define_property_with_mode(?get_PropertyRef(State), Name, Value, Mode), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : define_properties_with_modes
-%% Arguments : PropertyDefs - list of #'CosPropertyService_PropertyDef'{}
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-define_properties_with_modes(_OE_This, State, PropertyDefs) ->
- {reply, 'CosPropertyService_PropertySetDef':
- define_properties_with_modes(?get_PropertyRef(State), PropertyDefs), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : get_property_mode
-%% Arguments : Name - string()
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-get_property_mode(_OE_This, State, Name) ->
- {reply, 'CosPropertyService_PropertySetDef':
- get_property_mode(?get_PropertyRef(State), Name), State}.
-
-
-%%---------------------------------------------------------------------%
-%% Function : get_property_modes
-%% Arguments : Names - a list of Name (i.e. string()'s).
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-get_property_modes(_OE_This, State, Names) ->
- {reply, 'CosPropertyService_PropertySetDef':
- get_property_modes(?get_PropertyRef(State), Names), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : set_property_mode
-%% Arguments : Name - string()
-%% Mode - normal | read_only | fixed_normal | fixed_readonly
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-set_property_mode(_OE_This, State, Name, Mode) ->
- {reply, 'CosPropertyService_PropertySetDef':
- set_property_mode(?get_PropertyRef(State), Name, Mode), State}.
-
-
-%%---------------------------------------------------------------------%
-%% Function : set_property_modes
-%% Arguments : Modes - a list of #'CosPropertyService_PropertyModes'{}
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-set_property_modes(_OE_This, State, PropertyModes) ->
- {reply, 'CosPropertyService_PropertySetDef':
- set_property_modes(?get_PropertyRef(State), PropertyModes), State}.
-
-%%======================================================================
-%% CosPropertyService::PropertySet
-%%======================================================================
-%%---------------------------------------------------------------------%
-%% Function : define_property
-%% Arguments : Name - string()
-%% Value - #any{}
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-define_property(_OE_This, State, Name, Value) ->
- {reply, 'CosPropertyService_PropertySet':
- define_property(?get_PropertyRef(State), Name, Value), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : define_properties
-%% Arguments : Properties - a list of #'CosPropertyService_Property'{}
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-define_properties(_OE_This, State, Properties) ->
- {reply, 'CosPropertyService_PropertySet':
- define_properties(?get_PropertyRef(State), Properties), State}.
-
-
-%%---------------------------------------------------------------------%
-%% Function : get_number_of_properties
-%% Arguments : -
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-get_number_of_properties(_OE_This, State) ->
- {reply, 'CosPropertyService_PropertySet':
- get_number_of_properties(?get_PropertyRef(State)), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : get_all_property_names
-%% Arguments : Max - ulong()
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-get_all_property_names(_OE_This, State, Max) ->
- {reply, 'CosPropertyService_PropertySet':
- get_all_property_names(?get_PropertyRef(State), Max), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : get_property_value
-%% Arguments : Name - string()
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-get_property_value(_OE_This, State, Name) ->
- {reply, 'CosPropertyService_PropertySet':
- get_property_value(?get_PropertyRef(State), Name), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : get_properties
-%% Arguments : Names - a list of Name (i.e. string()'s)
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-get_properties(_OE_This, State, Names) ->
- {reply, 'CosPropertyService_PropertySet':
- get_properties(?get_PropertyRef(State), Names), State}.
-
-
-%%---------------------------------------------------------------------%
-%% Function : get_all_properties
-%% Arguments : Max - ulong()
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-get_all_properties(_OE_This, State, Max) ->
- {reply, 'CosPropertyService_PropertySet':
- get_all_properties(?get_PropertyRef(State), Max), State}.
-
-
-%%---------------------------------------------------------------------%
-%% Function : delete_property
-%% Arguments : Name - string()
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-delete_property(_OE_This, State, Name) ->
- {reply, 'CosPropertyService_PropertySet':
- delete_property(?get_PropertyRef(State), Name), State}.
-
-
-%%---------------------------------------------------------------------%
-%% Function : delete_properties
-%% Arguments : Names - a list of Name (i.e. string()'s)
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-delete_properties(_OE_This, State, Names) ->
- {reply, 'CosPropertyService_PropertySet':
- delete_properties(?get_PropertyRef(State), Names), State}.
-
-
-%%---------------------------------------------------------------------%
-%% Function : delete_all_properties
-%% Arguments : -
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-delete_all_properties(_OE_This, State) ->
- {reply, 'CosPropertyService_PropertySet':
- delete_all_properties(?get_PropertyRef(State)), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : is_property_defined
-%% Arguments : Name - string()
-%% Returns : See cosProperty application.
-%% Description:
-%%----------------------------------------------------------------------
-is_property_defined(_OE_This, State, Name) ->
- {reply, 'CosPropertyService_PropertySet':
- is_property_defined(?get_PropertyRef(State), Name), State}.
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
-
diff --git a/lib/cosFileTransfer/src/CosFileTransfer_VirtualFileSystem_impl.erl b/lib/cosFileTransfer/src/CosFileTransfer_VirtualFileSystem_impl.erl
deleted file mode 100644
index 7440498a23..0000000000
--- a/lib/cosFileTransfer/src/CosFileTransfer_VirtualFileSystem_impl.erl
+++ /dev/null
@@ -1,217 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosFileTransfer_VirtualFileSystem_impl.erl
-%% Description :
-%%
-%% Created : 12 Sept 2000
-%%----------------------------------------------------------------------
--module('CosFileTransfer_VirtualFileSystem_impl').
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
--include_lib("cosFileTransfer/include/CosFileTransfer.hrl").
--include("cosFileTransferApp.hrl").
-
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
--export([init/1,
- terminate/2,
- code_change/3,
- handle_info/2]).
-
-%% Interface functions
--export(['_get_file_system_type'/2,
- '_get_supported_content_types'/2,
- login/5]).
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
--export([]).
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {type, content, host, port, protocol, timeout, module}).
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
--define(create_InitState(T, C, H, P, Pr, TO),
- #state{type=T,
- content=C,
- host=H,
- port=P,
- protocol=Pr,
- timeout=TO}).
--define(create_NativeInitState(T, C, H, P, Pr, TO, M),
- #state{type=T,
- content=C,
- host=H,
- port=P,
- protocol=Pr,
- timeout=TO,
- module=M}).
-
--define(get_Type(S), S#state.type).
--define(get_Content(S), S#state.content).
--define(get_Host(S), S#state.host).
--define(get_Port(S), S#state.port).
--define(get_StartDir(S), S#state.startdir).
--define(get_Module(S), S#state.module).
--define(get_Protocol(S), S#state.protocol).
--define(get_Timeout(S), S#state.timeout).
-
--define(is_FTP(S), S#state.type == 'FTP').
--define(is_FTAM(S), S#state.type == 'FTAM').
--define(is_NATIVE(S), S#state.type == 'NATIVE').
-
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%----------------------------------------------------------------------
-init([{Type, Mod}, Content, Host, Port, Options]) ->
- Prot = cosFileTransferApp:get_option(protocol, Options, ?DEFAULT_CONFIG),
- Time = timer:seconds(cosFileTransferApp:get_option(connect_timeout, Options,
- ?DEFAULT_CONFIG)),
- {ok, ?create_NativeInitState(Type, Content, Host, Port, Prot, Time, Mod)};
-init([Type, Content, Host, Port, Options]) ->
- Prot = cosFileTransferApp:get_option(protocol, Options, ?DEFAULT_CONFIG),
- Time = timer:seconds(cosFileTransferApp:get_option(connect_timeout, Options,
- ?DEFAULT_CONFIG)),
- {ok, ?create_InitState(Type, Content, Host, Port, Prot, Time)}.
-
-%%----------------------------------------------------------------------
-%% Function : terminate/2
-%% Returns : any (ignored by gen_server)
-%% Description: Shutdown the server
-%%----------------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-%%----------------------------------------------------------------------
-%% Function : code_change/3
-%% Returns : {ok, NewState}
-%% Description: Convert process state when code is changed
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%---------------------------------------------------------------------%
-%% function : handle_info/2
-%% Arguments:
-%% Returns :
-%% Effect :
-%%----------------------------------------------------------------------
-handle_info(_Info, State) ->
- {noreply, State}.
-
-%%======================================================================
-%% CosFileTransfer::VirtualFileSystem
-%%======================================================================
-%%---------------------------------------------------------------------%
-%% Function : '_get_file_system_type'
-%% Arguments : -
-%% Returns : CosFileTransfer::NativeFileSystemType, i.e., 'FTP', 'FTAM',
-%% or 'NATIVE'. Currently only 'FTP' is allowed.
-%% Description:
-%%----------------------------------------------------------------------
-'_get_file_system_type'(_OE_This, State) ->
- {reply, ?get_Type(State), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : '_get_supported_content_types'
-%% Arguments :
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-'_get_supported_content_types'(_OE_This, State) ->
- {reply, ?get_Content(State), State}.
-
-%%----------------------------------------------------------------------
-%% Function : login
-%% Arguments : User - string()
-%% Password - string()
-%% Account - string()
-%% Returns : FileTransferSession object and Directory object (out-type).
-%% Description:
-%%----------------------------------------------------------------------
-login(_OE_This, State, User, Password, Account) when ?is_FTP(State) ->
- case catch 'CosFileTransfer_FileTransferSession':
- oe_create(['FTP', ?get_Host(State), ?get_Port(State), User, Password, Account,
- ?get_Protocol(State), ?get_Timeout(State)],
- [{sup_child, true}]) of
- {ok, _Pid, FTS} ->
- Dir = 'CosFileTransfer_FileTransferSession':
- oe_orber_create_directory_current(FTS),
- {reply, {FTS, Dir}, State};
- What ->
- orber:debug_level_print("[~p] CosFileTransfer_VirtualFileSystem:login(~p ~p ~p ~p);
-Unable to create a FileTransferSession: ~p",
- [?LINE, ?get_Host(State), ?get_Port(State), User,
- ?get_Protocol(State), What],
- ?DEBUG_LEVEL),
- corba:raise(#'CosFileTransfer_SessionException'{reason="Failed creating a FTS"})
- end;
-login(_OE_This, State, User, Password, Account) when ?is_NATIVE(State) ->
- case catch 'CosFileTransfer_FileTransferSession':
- oe_create([{'NATIVE', ?get_Module(State)}, ?get_Host(State),
- ?get_Port(State), User, Password, Account,
- ?get_Protocol(State), ?get_Timeout(State)],
- [{sup_child, true}]) of
- {ok, _Pid, FTS} ->
- Dir = 'CosFileTransfer_FileTransferSession':
- oe_orber_create_directory_current(FTS),
- {reply, {FTS, Dir}, State};
- What ->
- orber:debug_level_print("[~p] CosFileTransfer_VirtualFileSystem:login(~p ~p ~p ~p);
-Unable to create a FileTransferSession: ~p",
- [?LINE, ?get_Host(State), ?get_Port(State), User,
- ?get_Protocol(State), What],
- ?DEBUG_LEVEL),
- corba:raise(#'CosFileTransfer_SessionException'{reason="Failed creating a FTS"})
- end.
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-
-
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
diff --git a/lib/cosFileTransfer/src/Makefile b/lib/cosFileTransfer/src/Makefile
deleted file mode 100644
index b3967101e9..0000000000
--- a/lib/cosFileTransfer/src/Makefile
+++ /dev/null
@@ -1,188 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-
-ifeq ($(TYPE),debug)
-ERL_COMPILE_FLAGS += -Ddebug -W
-endif
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(COSFILETRANSFER_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/cosFileTransfer-$(VSN)
-
-EXTERNAL_INC_PATH = ../include
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES = \
- cosFileTransferApp \
- CosFileTransfer_Directory_impl \
- CosFileTransfer_File_impl \
- CosFileTransfer_VirtualFileSystem_impl \
- CosFileTransfer_FileTransferSession_impl \
- CosFileTransfer_FileIterator_impl \
- cosFileTransferNATIVE_file \
-
-ERL_FILES = $(MODULES:%=%.erl)
-HRL_FILES = \
- cosFileTransferApp.hrl \
-
-GEN_ERL_FILES = \
- oe_CosFileTransfer.erl \
- CosFileTransfer.erl \
- CosFileTransfer_AccessLevel.erl \
- CosFileTransfer_CommandNotImplementedException.erl \
- CosFileTransfer_Directory.erl \
- CosFileTransfer_File.erl \
- CosFileTransfer_FileIterator.erl \
- CosFileTransfer_FileList.erl \
- CosFileTransfer_FileNameList.erl \
- CosFileTransfer_FileNotFoundException.erl \
- CosFileTransfer_FileTransferSession.erl \
- CosFileTransfer_FileWrapper.erl \
- CosFileTransfer_IllegalOperationException.erl \
- CosFileTransfer_ProtocolAddressList.erl \
- CosFileTransfer_ProtocolSupport.erl \
- CosFileTransfer_RequestFailureException.erl \
- CosFileTransfer_SessionException.erl \
- CosFileTransfer_SupportedProtocolAddresses.erl \
- CosFileTransfer_TransferException.erl \
- CosFileTransfer_VirtualFileSystem.erl \
- CosFileTransfer_VirtualFileSystem_ContentList.erl \
-
-LOCAL_HRL_FILES = \
- oe_CosFileTransfer.hrl \
- CosFileTransfer.hrl \
- CosFileTransfer_Directory.hrl \
- CosFileTransfer_File.hrl \
- CosFileTransfer_FileIterator.hrl \
- CosFileTransfer_FileTransferSession.hrl \
- CosFileTransfer_VirtualFileSystem.hrl \
-
-GEN_HRL_FILES = $(LOCAL_HRL_FILES:%=$(EXTERNAL_INC_PATH)/%)
-
-GEN_FILES = \
- $(GEN_HRL_FILES) \
- $(GEN_ERL_FILES)
-
-TARGET_FILES = \
- $(GEN_ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR)) \
- $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-IDL_FILES = \
- CosFileTransfer.idl
-
-APPUP_FILE = cosFileTransfer.appup
-APPUP_SRC = $(APPUP_FILE).src
-APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
-
-APP_FILE = cosFileTransfer.app
-APP_SRC = $(APP_FILE).src
-APP_TARGET = $(EBIN)/$(APP_FILE)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/cosFileTransfer/ebin \
- -pa $(ERL_TOP)/lib/cosProperty/ebin \
- -pa $(ERL_TOP)/lib/cosProperty/src \
- -I$(ERL_TOP)/lib/cosProperty/src \
- -pa $(ERL_TOP)/lib/ic/ebin \
- -pa $(ERL_TOP)/lib/orber/ebin
-
-# The -pa option is just used temporary until erlc can handle
-# includes from other directories than ../include .
-ERL_COMPILE_FLAGS += \
- $(ERL_IDL_FLAGS) \
- -pa $(ERL_TOP)/lib/orber/include \
- -pa $(ERL_TOP)/lib/cosFileTransfer/include \
- -pa $(ERL_TOP)/lib/cosProperty/include \
- -pa $(ERL_TOP)/lib/cosProperty/src \
- -I$(ERL_TOP)/lib/orber/include \
- -I$(ERL_TOP)/lib/cosFileTransfer/include \
- -I$(ERL_TOP)/lib/cosProperty/include \
- -I$(ERL_TOP)/lib/cosProperty/src \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,app_vsn,"cosFileTransfer_$(COSFILETRANSFER_VSN)"}'
-
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
-
-debug:
- @${MAKE} TYPE=debug opt
-
-cleanb:
- rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
- rm -f errs core *~
-
-clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
- rm -f errs core *~
-
-$(APP_TARGET): $(APP_SRC)
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
-
-$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
-
-docs:
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-IDL-GENERATED: CosFileTransfer.idl
- $(gen_verbose)erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosFileTransfer.cfg"}' CosFileTransfer.idl
- $(V_at)mv $(LOCAL_HRL_FILES) $(EXTERNAL_INC_PATH)
- $(V_at)>IDL-GENERATED
-
-$(GEN_FILES): IDL-GENERATED
-
-$(TARGET_FILES): IDL-GENERATED
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
- $(INSTALL_DIR) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(GEN_FILES) $(IDL_FILES) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILES) "$(RELSYSDIR)/src"
- $(INSTALL_DIR) "$(RELSYSDIR)/include"
- $(INSTALL_DATA) $(GEN_HRL_FILES) "$(RELSYSDIR)/include"
-
-release_docs_spec:
diff --git a/lib/cosFileTransfer/src/cosFileTransfer.app.src b/lib/cosFileTransfer/src/cosFileTransfer.app.src
deleted file mode 100644
index 033eec9700..0000000000
--- a/lib/cosFileTransfer/src/cosFileTransfer.app.src
+++ /dev/null
@@ -1,43 +0,0 @@
-{application, cosFileTransfer,
- [{description, "The Erlang CosFileTransfer application"},
- {vsn, "%VSN%"},
- {modules,
- [
- 'cosFileTransferApp',
- 'CosFileTransfer_Directory_impl',
- 'CosFileTransfer_File_impl',
- 'CosFileTransfer_VirtualFileSystem_impl',
- 'CosFileTransfer_FileTransferSession_impl',
- 'CosFileTransfer_FileIterator_impl',
- 'cosFileTransferNATIVE_file',
- 'oe_CosFileTransfer',
- 'CosFileTransfer',
- 'CosFileTransfer_AccessLevel',
- 'CosFileTransfer_CommandNotImplementedException',
- 'CosFileTransfer_Directory',
- 'CosFileTransfer_File',
- 'CosFileTransfer_FileIterator',
- 'CosFileTransfer_FileList',
- 'CosFileTransfer_FileNameList',
- 'CosFileTransfer_FileNotFoundException',
- 'CosFileTransfer_FileTransferSession',
- 'CosFileTransfer_FileWrapper',
- 'CosFileTransfer_IllegalOperationException',
- 'CosFileTransfer_ProtocolAddressList',
- 'CosFileTransfer_ProtocolSupport',
- 'CosFileTransfer_RequestFailureException',
- 'CosFileTransfer_SessionException',
- 'CosFileTransfer_SupportedProtocolAddresses',
- 'CosFileTransfer_TransferException',
- 'CosFileTransfer_VirtualFileSystem',
- 'CosFileTransfer_VirtualFileSystem_ContentList'
- ]
- },
- {registered, []},
- {applications, [orber, stdlib, kernel]},
- {env, []},
- {mod, {cosFileTransferApp, []}},
- {runtime_dependencies, ["stdlib-2.0","ssl-5.3.4","orber-3.6.27","kernel-3.0",
- "inets-5.10","erts-7.0","cosProperty-1.1.17"]}
-]}.
-
diff --git a/lib/cosFileTransfer/src/cosFileTransfer.appup.src b/lib/cosFileTransfer/src/cosFileTransfer.appup.src
deleted file mode 100644
index 6c3b2833b7..0000000000
--- a/lib/cosFileTransfer/src/cosFileTransfer.appup.src
+++ /dev/null
@@ -1,7 +0,0 @@
-{"%VSN%",
- [
- ],
- [
- ]
-}.
-
diff --git a/lib/cosFileTransfer/src/cosFileTransferApp.erl b/lib/cosFileTransfer/src/cosFileTransferApp.erl
deleted file mode 100644
index 29a7237d70..0000000000
--- a/lib/cosFileTransfer/src/cosFileTransferApp.erl
+++ /dev/null
@@ -1,471 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2015. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : cosFileTransferApp.erl
-%% Purpose :
-%% Created : 25 Aug 2000
-%%----------------------------------------------------------------------
--module(cosFileTransferApp).
-
-
-%%--------------- INCLUDES -----------------------------------
--include("cosFileTransferApp.hrl").
-
-%%--------------- EXPORTS-------------------------------------
-%% cosFileTransferApp API external
--export([start/0, stop/0, install/0, uninstall/0, create_VFS/4, create_VFS/5,
- get_buffert_size/0]).
-
-%% cosFileTransferApp API internal
--export([create_link/3, get_option/3, type_check/2, configure/2]).
-
-%% Application callbacks
--export([start/2, init/1, stop/1]).
-
-%% INTERNAL EXPORTS!! DO NOT USE THESE!!
--export([create_dir/2, create_dir/3, create_file/2, create_file/3, split_paths/1,
- create_name/1]).
-
--export([ssl_server_certfile/0, ssl_client_certfile/0, ssl_port/0,
- ssl_server_verify/0,
- ssl_client_verify/0,
- ssl_server_depth/0, ssl_client_depth/0,
- ssl_server_cacertfile/0,
- ssl_client_cacertfile/0]).
-
-
-%%--------------- DEFINES ------------------------------------
--define(SUPERVISOR_NAME, oe_cosFileTransferSup).
--define(SUP_FLAG, {simple_one_for_one,50,10}).
--define(SUP_DIRECTORY_SPEC(Name, Args),
- ['CosFileTransfer_Directory',Args,
- [{sup_child, true}, {regname, {global, Name}}]]).
--define(SUP_CHILD,
- {"oe_FileTransferChild",
- {cosFileTransfer,create_link, []},
- transient,100000,worker,
- []}).
-
-%%------------------------------------------------------------
-%% function : install
-%% Arguments: -
-%% Returns : ok | EXIT | EXCEPTION
-%% Effect : Install necessary data in the IFR DB
-%%------------------------------------------------------------
-install() ->
- oe_CosFileTransfer:oe_register().
-
-%%------------------------------------------------------------
-%% function : uninstall
-%% Arguments: -
-%% Returns : ok | EXIT | EXCEPTION
-%% Effect : Remove data related to cosFileTransfer from the IFR DB
-%%------------------------------------------------------------
-uninstall() ->
- oe_CosFileTransfer:oe_unregister().
-
-
-%%------------------------------------------------------------
-%% function : start/stop
-%% Arguments:
-%% Returns :
-%% Effect : Starts or stops the cosFileTransfer application.
-%%------------------------------------------------------------
-start() ->
- application:start(cosFileTransfer).
-stop() ->
- application:stop(cosFileTransfer).
-
-%%------------------------------------------------------------
-%% function : start
-%% Arguments: Type - see module application
-%% Arg - see module application
-%% Returns :
-%% Effect : Module callback for application
-%%------------------------------------------------------------
-start(_, _) ->
- supervisor:start_link({local, ?SUPERVISOR_NAME}, cosFileTransferApp, app_init).
-
-
-%%------------------------------------------------------------
-%% function : stop
-%% Arguments: Arg - see module application
-%% Returns :
-%% Effect : Module callback for application
-%%------------------------------------------------------------
-stop(_) ->
- ok.
-
-%%-----------------------------------------------------------%
-%% function : init
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-%% Starting using create_factory/X
-init(own_init) ->
- {ok,{?SUP_FLAG, [?SUP_CHILD]}};
-%% When starting as an application.
-init(app_init) ->
- {ok,{?SUP_FLAG, [?SUP_CHILD]}}.
-
-%%------------------------------------------------------------
-%% function : create_VFS
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-create_VFS(Type, Content, Host, Port) ->
- create_VFS(Type, Content, Host, Port, []).
-
-create_VFS('FTP', Content, Host, Port, Options)
- when is_list(Host) andalso is_integer(Port) andalso is_list(Options) ->
- 'CosFileTransfer_VirtualFileSystem':oe_create(['FTP', Content, Host, Port,
- Options],
- [{pseudo, true}]);
-create_VFS({'NATIVE', Mod}, Content, Host, Port, Options)
- when is_list(Host) andalso is_integer(Port) andalso is_list(Options) ->
- 'CosFileTransfer_VirtualFileSystem':oe_create([{'NATIVE', Mod}, Content,
- Host, Port, Options],
- [{pseudo, true}]);
-create_VFS(_, _, _, _, _) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------%
-%% function : create_link
-%% Arguments: Module - which Module to call
-%% Env/ArgList - ordinary oe_create arguments.
-%% Returns :
-%% Exception:
-%% Effect : Necessary since we want the supervisor to be a
-%% 'simple_one_for_one'. Otherwise, using for example,
-%% 'one_for_one', we have to call supervisor:delete_child
-%% to remove the childs startspecification from the
-%% supervisors internal state.
-%%------------------------------------------------------------
-create_link(Module, Env, ArgList) ->
- Module:oe_create_link(Env, ArgList).
-
-%%-----------------------------------------------------------%
-%% function : get_option
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-get_option(Key, OptionList, DefaultList) ->
- case lists:keysearch(Key, 1, OptionList) of
- {value,{Key,Value}} ->
- Value;
- _ ->
- case lists:keysearch(Key, 1, DefaultList) of
- {value,{Key,Value}} ->
- Value;
- _->
- {error, "Invalid option"}
- end
- end.
-
-%%-----------------------------------------------------------%
-%% function : type_check
-%% Arguments: Obj - objectrefernce to test.
-%% Mod - Module which contains typeID/0.
-%% Returns : 'ok' or raises exception.
-%% Effect :
-%%------------------------------------------------------------
-type_check(Obj, Mod) ->
- case catch corba_object:is_a(Obj,Mod:typeID()) of
- true ->
- ok;
- _ ->
- corba:raise(#'BAD_PARAM'{minor=700, completion_status=?COMPLETED_NO})
- end.
-
-
-%%-----------------------------------------------------------%
-%% function : create_name/1
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-create_name(Type) ->
- Time = erlang:system_time(),
- Unique = erlang:unique_integer([positive]),
- lists:concat(['oe_',node(),'_',Type,'_',Time,'_',Unique]).
-
-
-%%-----------------------------------------------------------%
-%% function : get_buffert_size/0
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect : Lookup the configuration variable 'buffert_size'
-%%------------------------------------------------------------
-get_buffert_size() ->
- case application:get_env(cosFileTransfer, buffert_size) of
- {ok, Size} when is_integer(Size) ->
- Size;
- _ ->
- ?DEFAULT_BUFSIZE
- end.
-
-%%-----------------------------------------------------------%
-%% function : configure/1
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-configure(buffert_size, Value) when is_integer(Value) ->
- do_configure(buffert_size, Value);
-configure(ssl_port, Value) when is_integer(Value) ->
- do_safe_configure(ssl_port, Value);
-configure(ssl_server_certfile, Value) when is_list(Value) ->
- do_safe_configure(ssl_server_certfile, Value);
-configure(ssl_server_certfile, Value) when is_atom(Value) ->
- do_safe_configure(ssl_server_certfile, atom_to_list(Value));
-configure(ssl_client_certfile, Value) when is_list(Value) ->
- do_safe_configure(ssl_client_certfile, Value);
-configure(ssl_client_certfile, Value) when is_atom(Value) ->
- do_safe_configure(ssl_client_certfile, atom_to_list(Value));
-configure(ssl_server_verify, Value) when is_integer(Value) ->
- do_safe_configure(ssl_server_verify, Value);
-configure(ssl_client_verify, Value) when is_integer(Value) ->
- do_safe_configure(ssl_client_verify, Value);
-configure(ssl_server_depth, Value) when is_integer(Value) ->
- do_safe_configure(ssl_server_depth, Value);
-configure(ssl_client_depth, Value) when is_integer(Value) ->
- do_safe_configure(ssl_client_depth, Value);
-configure(ssl_server_cacertfile, Value) when is_list(Value) ->
- do_safe_configure(ssl_server_cacertfile, Value);
-configure(ssl_server_cacertfile, Value) when is_atom(Value) ->
- do_safe_configure(ssl_server_cacertfile, atom_to_list(Value));
-configure(ssl_client_cacertfile, Value) when is_list(Value) ->
- do_safe_configure(ssl_client_cacertfile, Value);
-configure(ssl_client_cacertfile, Value) when is_atom(Value) ->
- do_safe_configure(ssl_client_cacertfile, atom_to_list(Value));
-configure(_, _) ->
- exit({error, "Bad configure parameter(s)"}).
-
-%% This function may be used as long as it is safe to change a value at any time.
-do_configure(Key, Value) ->
- case is_loaded() of
- false ->
- application:load(cosFileTransfer),
- application_controller:set_env(cosFileTransfer, Key, Value);
- true ->
- application_controller:set_env(cosFileTransfer, Key, Value)
- end.
-
-
-%% This function MUST(!!) be used when we cannot change a value if cosFileTransfer
-%% is running.
-do_safe_configure(Key, Value) ->
- case is_loaded() of
- false ->
- application:load(cosFileTransfer),
- application_controller:set_env(cosFileTransfer, Key, Value);
- true ->
- case is_running() of
- false ->
- application_controller:set_env(cosFileTransfer, Key, Value);
- true ->
- exit("cosFileTransfer already running, the given key may not be updated!")
- end
- end.
-
-%%-----------------------------------------------------------%
-%% function : SSL parameter access functions
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-ssl_port() ->
- case application:get_env(cosFileTransfer, ssl_port) of
- {ok, Port} when is_integer(Port) ->
- Port;
- _ ->
- -1
- end.
-
-ssl_server_certfile() ->
- case application:get_env(cosFileTransfer, ssl_server_certfile) of
- {ok, V1} when is_list(V1) ->
- V1;
- {ok, V2} when is_atom(V2) ->
- atom_to_list(V2);
- _What ->
- {ok, Cwd} = file:get_cwd(),
- filename:join(Cwd,"ssl_server_cert.pem")
- end.
-
-
-ssl_client_certfile() ->
- case application:get_env(cosFileTransfer, ssl_client_certfile) of
- {ok, V1} when is_list(V1) ->
- V1;
- {ok, V2} when is_atom(V2) ->
- atom_to_list(V2);
- _ ->
- {ok, Cwd} = file:get_cwd(),
- filename:join(Cwd,"ssl_client_cert.pem")
- end.
-
-ssl_server_verify() ->
- Verify = case application:get_env(cosFileTransfer, ssl_server_verify) of
- {ok, V} when is_integer(V) ->
- V;
- _ ->
- 0
- end,
- if
- Verify =< 2, Verify >= 0 ->
- Verify;
- true ->
- 0
- end.
-
-ssl_client_verify() ->
- Verify = case application:get_env(cosFileTransfer, ssl_client_verify) of
- {ok, V1} when is_integer(V1) ->
- V1;
- _ ->
- 0
- end,
- if
- Verify =< 2, Verify >= 0 ->
- Verify;
- true ->
- 0
- end.
-
-ssl_server_depth() ->
- case application:get_env(cosFileTransfer, ssl_server_depth) of
- {ok, V1} when is_integer(V1) ->
- V1;
- _ ->
- 1
- end.
-
-ssl_client_depth() ->
- case application:get_env(cosFileTransfer, ssl_client_depth) of
- {ok, V1} when is_integer(V1) ->
- V1;
- _ ->
- 1
- end.
-
-
-ssl_server_cacertfile() ->
- case application:get_env(cosFileTransfer, ssl_server_cacertfile) of
- {ok, V1} when is_list(V1) ->
- V1;
- {ok, V2} when is_atom(V2) ->
- atom_to_list(V2);
- _ ->
- []
- end.
-
-ssl_client_cacertfile() ->
- case application:get_env(cosFileTransfer, ssl_client_cacertfile) of
- {ok, V1} when is_list(V1) ->
- V1;
- {ok, V2} when is_atom(V2) ->
- atom_to_list(V2);
- _ ->
- []
- end.
-
-
-%%============================================================
-%% Internal functions
-%%============================================================
-%%-----------------------------------------------------------%
-%% function : is_loaded/0
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect : Check if the application is loaded
-%%------------------------------------------------------------
-is_loaded() ->
- is_loaded(application:loaded_applications()).
-
-is_running() ->
- is_loaded(application:which_applications()).
-
-is_loaded([]) ->
- false;
-is_loaded([{cosFileTransfer, _, _} |_As]) ->
- true;
-is_loaded([_ |As]) ->
- is_loaded(As).
-
-
-
-
-%%-----------------------------------------------------------%
-%% function : create_dir/3/4
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-create_dir(Session, FileNameList) ->
- create_dir(Session, FileNameList, corba:create_nil_objref()).
-create_dir(Session, FileNameList, Parent) ->
- 'CosFileTransfer_Directory':oe_create([lists:last(FileNameList), FileNameList,
- Parent, Session],
- [{pseudo, true}]).
-
-%%-----------------------------------------------------------%
-%% function : create_file/2/3
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-create_file(Session, FileNameList) ->
- create_file(Session, FileNameList, corba:create_nil_objref()).
-create_file(Session, FileNameList, Parent) ->
- 'CosFileTransfer_File':oe_create([lists:last(FileNameList), FileNameList,
- Parent, Session], [{pseudo, true}]).
-
-%%-----------------------------------------------------------%
-%% function : split_paths
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-split_paths(Listing) ->
- split_paths(string:tokens(Listing, ?SEPARATOR), []).
-split_paths([], Acc) ->
- Acc;
-split_paths([H|T], Acc) ->
- split_paths(T, [filename:split(H)|Acc]).
-
-
-%%--------------- END OF MODULE ------------------------------
-
-
diff --git a/lib/cosFileTransfer/src/cosFileTransferApp.hrl b/lib/cosFileTransfer/src/cosFileTransferApp.hrl
deleted file mode 100644
index 037be7a4af..0000000000
--- a/lib/cosFileTransfer/src/cosFileTransferApp.hrl
+++ /dev/null
@@ -1,69 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : cosFileTransferApp.hrl
-%% Purpose :
-%% Created : 10 Feb 2000
-%%----------------------------------------------------------------------
-
-
-%%--------------- INCLUDES -----------------------------------
-%% External
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
--include_lib("cosProperty/include/CosPropertyService.hrl").
-
-%% Local
--include_lib("cosFileTransfer/include/CosFileTransfer.hrl").
-
--define(write_ErrorMsg(Txt, Arg),
-error_logger:error_msg("============= CosFileTransfer =============~n"
- Txt
- "===========================================~n",
- Arg)).
-
--define(FTP_PORT_INT, 21).
--define(FTP_PORT_STR, "21").
--define(TCP_ID, "TCP").
--define(FTP_ID, "FTP").
--define(FTAM_ID, "FTAM").
--define(NATIVE_ID, "NATIVE").
--define(SUPPURTED_PROTOCOLS, ["TCP/IP", "SSL"]).
-
--define(DEFAULT_CONFIG, [{protocol, tcp}, {connect_timeout, 60}]).
-
--define(SEPARATOR, "\r\n").
-
--define(DEFAULT_BUFSIZE, 64000).
-
--define(DEBUG_LEVEL, 3).
-
--ifdef(debug).
--define(debug_print(F,A),
- io:format("[LINE: ~p MODULE: ~p] "++F,[?LINE, ?MODULE]++A)).
--define(ft_TypeCheck(O,M), 'cosFileTransferApp':type_check(O,M)).
--else.
--define(debug_print(F,A), ok).
--define(ft_TypeCheck(O,I), ok).
--endif.
-
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosFileTransfer/src/cosFileTransferNATIVE_file.erl b/lib/cosFileTransfer/src/cosFileTransferNATIVE_file.erl
deleted file mode 100644
index 2969e61a2b..0000000000
--- a/lib/cosFileTransfer/src/cosFileTransferNATIVE_file.erl
+++ /dev/null
@@ -1,359 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : cosFileTransferNATIVE_file.erl
-%% Description :
-%%
-%% Created : 9 Nov 2000
-%%----------------------------------------------------------------------
--module('cosFileTransferNATIVE_file').
-
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include("cosFileTransferApp.hrl").
--include_lib("kernel/include/file.hrl").
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
--export([open/1,
- open/2,
- open/3,
- user/3,
- pwd/1,
- cd/2,
- mkdir/2,
- rmdir/2,
- nlist/1,
- nlist/2,
- delete/2,
- recv/2,
- recv/3,
- send/2,
- send/3,
- close/1,
- insert/4]).
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
--export([]).
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% function : open
-%% Arguments:
-%% Returns : {ok, Ref} | {error, ehost} for future use
-%% Effect :
-%%----------------------------------------------------------------------
-open(_Host) ->
- {ok, 'NATIVE'}.
-open(_Host, _Port) ->
- {ok, 'NATIVE'}.
-open(_Host, _Port, _Flags) ->
- {ok, 'NATIVE'}.
-
-%%----------------------------------------------------------------------
-%% function : user
-%% Arguments: Ref - what's returned by open/1/2
-%% User = Password = string()
-%% Returns : ok | {error, euser | econn} for future use
-%% Effect :
-%%----------------------------------------------------------------------
-user(_Ref, _User, _Password) ->
- ok.
-
-%%----------------------------------------------------------------------
-%% function : pwd
-%% Arguments: Ref - what's returned by open/1/2
-%% Returns : {ok, string()} | {error, elogin | econn}
-%% Effect :
-%%----------------------------------------------------------------------
-pwd(_Ref) ->
- case file:get_cwd() of
- {ok, Cwd} ->
- {ok, Cwd};
- _ ->
- {error, econn}
- end.
-
-%%----------------------------------------------------------------------
-%% function : cd
-%% Arguments: Ref - what's returned by open/1/2
-%% Dir - string()
-%% Returns : ok | {error, epath | elogin | econn}
-%% Effect :
-%%----------------------------------------------------------------------
-cd(_Ref, Dir) ->
- case file:set_cwd(Dir) of
- ok ->
- ok;
- {error, _} ->
- {error, epath}
- end.
-
-%%----------------------------------------------------------------------
-%% function : mkdir
-%% Arguments: Ref - what's returned by open/1/2
-%% Dir - string()
-%% Returns : ok | {error, epath}
-%% Effect :
-%%----------------------------------------------------------------------
-mkdir(_Ref, Dir) ->
- case file:make_dir(Dir) of
- ok ->
- ok;
- {error, _Reason} ->
- {error, epath}
- end.
-
-%%----------------------------------------------------------------------
-%% function : rmdir
-%% Arguments: Ref - what's returned by open/1/2
-%% Dir - string()
-%% Returns : ok | {error, epath}
-%% Effect :
-%%----------------------------------------------------------------------
-rmdir(_Ref, Dir) ->
- case file:del_dir(Dir) of
- ok ->
- ok;
- {error, _Reason} ->
- {error, epath}
- end.
-
-%%----------------------------------------------------------------------
-%% function : nlist
-%% Arguments: Ref - what's returned by open/1/2
-%% Dir - string()
-%% Returns : {ok, Listing} | {error, epath | elogin | econn}
-%% Effect :
-%%----------------------------------------------------------------------
-nlist(_Ref) ->
- case file:get_cwd() of
- {ok, Cwd} ->
- %% Here we can assume that it's a Directory is tested.
- convert_to_nlist(file:list_dir(Cwd));
- _ ->
- {error, epath}
- end.
-nlist(_Ref, Dir) ->
- case file:list_dir(Dir) of
- {error, _} ->
- %% Might be a File
- case file:read_file_info(Dir) of
- {ok, _} ->
- convert_to_nlist_helper([Dir], []);
- _ ->
- {error, epath}
- end;
- {ok, Content} ->
- convert_to_nlist_helper(Content, [])
- end.
-
-convert_to_nlist({error, _}) ->
- {error, epath};
-convert_to_nlist({ok, Content}) ->
- convert_to_nlist_helper(Content, []).
-
-convert_to_nlist_helper([], Acc) ->
- {ok, lists:concat(Acc)};
-convert_to_nlist_helper([H|T], Acc) ->
- convert_to_nlist_helper(T, [H, "\r\n"|Acc]).
-
-%%----------------------------------------------------------------------
-%% function : delete
-%% Arguments: Ref - what's returned by open/1/2
-%% File - string()
-%% Returns : ok | {error, epath}
-%% Effect :
-%%----------------------------------------------------------------------
-delete(_Ref, File) ->
- case file:delete(File) of
- ok ->
- ok;
- {error, _Reason} ->
- {error, epath}
- end.
-
-%%----------------------------------------------------------------------
-%% function : recv
-%% Arguments: Ref - what's returned by open/1/2
-%% Returns : ok | {error, epath | elogin | econn}
-%% Effect :
-%%----------------------------------------------------------------------
-recv(_Ref, _Remote) ->
- ok.
-recv(_Ref, Remote, Local) ->
- copy_file(Remote, Local).
-
-%%----------------------------------------------------------------------
-%% function : send
-%% Arguments: Ref - what's returned by open/1/2
-%% Returns : ok | {error, epath | elogin | econn | etnospc | epnospc | efnamena}
-%% Effect :
-%%----------------------------------------------------------------------
-send(_Ref, _Local) ->
- ok.
-send(_Ref, Local, Remote) ->
- copy_file(Local, Remote).
-
-%%----------------------------------------------------------------------
-%% function : close
-%% Arguments: Ref - what's returned by open/1/2
-%% Returns : ok
-%% Effect : Currently none.
-%%----------------------------------------------------------------------
-close(_) ->
- ok.
-
-
-%%----------------------------------------------------------------------
-%% function : insert
-%% Arguments: Ref - what's returned by open/1/2
-%% Local - absolute file name
-%% Remote - absolute file name
-%% Offset - long()
-%% Returns : ok
-%% Effect :
-%%----------------------------------------------------------------------
-insert(_Ref, Source, Target, Offset) ->
- case file:open(Source, [raw, binary, read]) of
- {ok, SourceDev} ->
- case file:open(Target, [raw, binary, read, write]) of
- {ok, TargetDev} ->
- {ok, #file_info{size=SSize}} =
- file:read_file_info(Source),
- {ok, #file_info{size=TSize}} =
- file:read_file_info(Target),
- insert_file_helper(SourceDev, TargetDev, SSize, TSize, Offset);
- Reason ->
- file:close(SourceDev),
- convert_error(Reason)
- end;
- Reason ->
- convert_error(Reason)
- end.
-
-
-insert_file_helper(SourceDev, TargetDev, SSize, TSize, Offset) ->
- BuffSize = cosFileTransferApp:get_buffert_size(),
- move_data(TargetDev, TSize, SSize+TSize, TSize-Offset, BuffSize),
- insert_data(SourceDev, TargetDev, 0, Offset, BuffSize),
- file:close(SourceDev),
- file:close(TargetDev).
-move_data(_F, _RLocation, _WLocation, Counter, _BuffSize) when Counter == 0 ->
- ok;
-move_data(F, RLocation, WLocation, Counter, BuffSize) when Counter =< BuffSize ->
- case file:pread(F, RLocation-Counter, Counter) of
- {ok, Bin} ->
- file:pwrite(F, WLocation-Counter, Bin);
- eof ->
- ok
- end;
-move_data(F, RLocation, WLocation, Counter, BuffSize) ->
- NewRLC = RLocation-BuffSize,
- NewWLC = WLocation-BuffSize,
- case file:pread(F, NewRLC, BuffSize) of
- {ok, Bin} ->
- file:pwrite(F, NewWLC, Bin),
- move_data(F, NewRLC, NewWLC, Counter-BuffSize, BuffSize);
- eof ->
- ok
- end.
-
-insert_data(FSRC, FTGT, RLocation, WLocation, BuffSize) ->
- case file:pread(FSRC, RLocation, BuffSize) of
- {ok, Bin} ->
- file:pwrite(FTGT, WLocation, Bin),
- insert_data(FSRC, FTGT, RLocation+BuffSize, WLocation+BuffSize, BuffSize);
- eof ->
- ok
- end.
-
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-copy_file(Source, Target) ->
- case file:open(Source, [raw, binary, read]) of
- {ok, SourceDev} ->
- case file:open(Target, [raw, binary, append]) of
- {ok, TargetDev} ->
- BuffSize = cosFileTransferApp:get_buffert_size(),
- copy_file_helper(SourceDev, TargetDev, BuffSize);
- Reason ->
- file:close(SourceDev),
- convert_error(Reason)
- end;
- Reason ->
- convert_error(Reason)
- end.
-
-copy_file_helper(SourceDev, TargetDev, BuffSize) ->
- case file:read(SourceDev, BuffSize) of
- eof ->
- file:close(SourceDev),
- file:close(TargetDev);
- {ok, Bin} ->
- case file:write(TargetDev, Bin) of
- ok ->
- copy_file_helper(SourceDev, TargetDev, BuffSize);
- Reason ->
- file:close(SourceDev),
- file:close(TargetDev),
- convert_error(Reason)
- end;
- {error, Reason} ->
- file:close(SourceDev),
- file:close(TargetDev),
- convert_error(Reason)
- end.
-
-convert_error({error, eacces}) ->
- {error, elogin};
-convert_error({error, enoent}) ->
- {error, epath};
-convert_error({error, enotdir}) ->
- {error, epath};
-convert_error({error, eidir}) ->
- {error, epath};
-convert_error({error, enospc}) ->
- {error, etnospc};
-convert_error(_) ->
- {error, epath}.
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
diff --git a/lib/cosFileTransfer/test/Makefile b/lib/cosFileTransfer/test/Makefile
deleted file mode 100644
index 45c67a95dd..0000000000
--- a/lib/cosFileTransfer/test/Makefile
+++ /dev/null
@@ -1,132 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(COSFILETRANSFER_VSN)
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/cosFileTransfer_test
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-TEST_SPEC_FILE = cosFileTransfer.spec
-COVER_FILE = cosFileTransfer.cover
-
-
-IDL_FILES =
-
-IDLOUTDIR = idl_output
-
-MODULES = \
- fileTransfer_SUITE \
-
-GEN_MODULES = \
-
-GEN_HRL_FILES = \
-
-ERL_FILES = $(MODULES:%=%.erl)
-
-HRL_FILES =
-
-GEN_FILES = \
- $(GEN_HRL_FILES:%=$(IDLOUTDIR)/%) \
- $(GEN_MODULES:%=$(IDLOUTDIR)/%.erl)
-
-GEN_TARGET_FILES = $(GEN_MODULES:%=$(IDLOUTDIR)/%.$(EMULATOR))
-
-SUITE_TARGET_FILES = $(MODULES:%=%.$(EMULATOR))
-
-TARGET_FILES = \
- $(GEN_TARGET_FILES) \
- $(SUITE_TARGET_FILES)
-
-
-# ----------------------------------------------------
-# PROGRAMS
-# ----------------------------------------------------
-LOCAL_CLASSPATH = $(ERL_TOP)lib/cosFileTransfer/priv:$(ERL_TOP)lib/cosFileTransfer/test
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/cosFileTransfer/ebin \
- -pa $(ERL_TOP)/lib/cosFileTransfer/src \
- -pa $(ERL_TOP)/lib/cosFileTransfer/include \
- -pa $(ERL_TOP)/lib/cosProperty/ebin \
- -pa $(ERL_TOP)/lib/cosProperty/include \
- -pa $(ERL_TOP)/lib/orber/ebin \
- -pa $(ERL_TOP)/lib/ic/ebin
-
-ERL_COMPILE_FLAGS += \
- $(ERL_IDL_FLAGS) \
- -pa $(ERL_TOP)/lib/orber/include \
- -pa $(ERL_TOP)/lib/cosProperty/include \
- -pa $(ERL_TOP)/lib/cosFileTransfer/ebin \
- -pa $(ERL_TOP)/lib/cosFileTransfer/include \
- -pa $(ERL_TOP)/lib/cosFileTransfer/test/idl_output \
- -I$(ERL_TOP)/lib/orber/include \
- -I$(ERL_TOP)/lib/cosProperty/include \
- -I$(ERL_TOP)/lib/cosFileTransfer/src \
- -I$(ERL_TOP)/lib/cosFileTransfer/include \
- -I$(ERL_TOP)/lib/cosFileTransfer \
- -I$(ERL_TOP)/lib/cosFileTransfer/test/$(IDLOUTDIR)
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-
-tests debug opt: $(TARGET_FILES)
-
-clean:
- rm -f idl_output/*
- rm -f $(TARGET_FILES)
- rm -f errs core *~
-
-docs:
-
-# ----------------------------------------------------
-# Special Targets
-# ----------------------------------------------------
-
-# ----------------------------------------------------
-# Release Targets
-# ----------------------------------------------------
-# We don't copy generated intermediate erlang and hrl files
-
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec:
-
-release_docs_spec:
-
-release_tests_spec: tests
- $(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) \
- $(COVER_FILE) $(ERL_FILES) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(SUITE_TARGET_FILES) "$(RELSYSDIR)"
- chmod -R u+w "$(RELSYSDIR)"
diff --git a/lib/cosFileTransfer/test/cosFileTransfer.cover b/lib/cosFileTransfer/test/cosFileTransfer.cover
deleted file mode 100644
index 063dd66990..0000000000
--- a/lib/cosFileTransfer/test/cosFileTransfer.cover
+++ /dev/null
@@ -1,2 +0,0 @@
-{incl_app,cosFileTransfer,details}.
-
diff --git a/lib/cosFileTransfer/test/cosFileTransfer.spec b/lib/cosFileTransfer/test/cosFileTransfer.spec
deleted file mode 100644
index 290b27d048..0000000000
--- a/lib/cosFileTransfer/test/cosFileTransfer.spec
+++ /dev/null
@@ -1 +0,0 @@
-{suites,"../cosFileTransfer_test", all}.
diff --git a/lib/cosFileTransfer/test/fileTransfer_SUITE.erl b/lib/cosFileTransfer/test/fileTransfer_SUITE.erl
deleted file mode 100644
index 12aef2913a..0000000000
--- a/lib/cosFileTransfer/test/fileTransfer_SUITE.erl
+++ /dev/null
@@ -1,938 +0,0 @@
-%%-----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : fileTransfer_SUITE.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module(fileTransfer_SUITE).
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("cosFileTransfer/src/cosFileTransferApp.hrl").
-
--include_lib("common_test/include/ct.hrl").
-
-%%--------------- DEFINES ------------------------------------
--define(default_timeout, test_server:minutes(20)).
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
--define(matchnopr(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT (~p) ------~n", [?LINE]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
-
-
-
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0,suite/0,groups/0,
- init_per_group/2,end_per_group/2,
- cases/0,
- init_per_suite/1,
- end_per_suite/1,
- fileIterator_api/1,
- fts_ftp_file_api/1,
- fts_ftp_file_ssl_api/1,
- fts_ftp_dir_api/1,
- fts_native_file_api/1,
- fts_native_file_ssl_api/1,
- fts_native_dir_api/1,
- init_per_testcase/2,
- end_per_testcase/2,
- install_data/2,
- uninstall_data/1,
- slave_sup/0,
- app_test/1]).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() ->
- [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-cases() ->
- [fts_ftp_dir_api, fts_ftp_file_api,
- fts_ftp_file_ssl_api, fts_native_dir_api,
- fts_native_file_api, fts_native_file_ssl_api,
- fileIterator_api, app_test].
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) ->
- case crypto_works() of
- false ->
- {skip,"Could not start crypto!"};
- true ->
- orber:jump_start(),
- cosProperty:install(),
- cosProperty:start(),
- Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
- %% Client
- cosFileTransferApp:configure(ssl_client_certfile,
- filename:join([Dir, "client", "cert.pem"])),
- cosFileTransferApp:configure(ssl_client_cacertfile,
- filename:join([Dir, "client", "cacerts.pem"])),
- cosFileTransferApp:configure(ssl_client_verify, 1),
- cosFileTransferApp:configure(ssl_client_depth, 0),
- %% Server
- cosFileTransferApp:configure(ssl_server_certfile,
- filename:join([Dir, "server", "cert.pem"])),
- cosFileTransferApp:configure(ssl_server_cacertfile,
- filename:join([Dir, "server", "cacerts.pem"])),
- cosFileTransferApp:configure(ssl_server_verify, 1),
- cosFileTransferApp:configure(ssl_server_depth, 0),
- crypto:start(),
- ssl:start(),
- cosFileTransferApp:install(),
- cosFileTransferApp:start(),
- if
- is_list(Config) ->
- Config;
- true ->
- exit("Config not a list")
- end
- end.
-
-crypto_works() ->
- try crypto:start() of
- {error,{already_started,crypto}} -> true;
- ok -> true
- catch
- error:_ ->
- false
- end.
-
-end_per_suite(Config) ->
- ssl:stop(),
- crypto:stop(),
- cosFileTransferApp:stop(),
- cosProperty:stop(),
- cosProperty:uninstall(),
- cosFileTransferApp:uninstall(),
- orber:jump_stop(),
- Config.
-
-%%-----------------------------------------------------------------
-%% Local definitions
-%%-----------------------------------------------------------------
--define(FTP_USER, "anonymous").
--define(FTP_PASS, "fileTransfer_SUITE@localhost").
--define(TEST_DIR,["/", "incoming"]).
-
--define(FTP_PORT, 21).
--define(FTP_ACC, "anonymous").
-
--define(BAD_HOST, "badhostname").
--define(BAD_USER, "baduser").
--define(BAD_DIR, "baddirectory").
-
--define(TEST_FILE_DATA, "If this file exists after a completed test an error occurred.").
--define(TEST_FILE_DATA2, "1234567890123").
-
-%%-----------------------------------------------------------------
-%% aoo-file test
-%%-----------------------------------------------------------------
-app_test(_Config) ->
- ok=?t:app_test(cosFileTransfer),
- ok.
-
-%%-----------------------------------------------------------------
-%% FileIterator API tests
-%%-----------------------------------------------------------------
-fileIterator_api(Config) ->
- case ftp_host(Config) of
- {skipped, SkippedReason} ->
- {skipped, SkippedReason};
- Host ->
-
- {ok, Node} = create_node("fileIterator_api", 4008, normal),
- ?match(ok, remote_apply(Node, ?MODULE, install_data,
- [tcp, {{'NATIVE',
- 'cosFileTransferNATIVE_file'}, Host,
- "fileIterator_api"}])),
-
- %% Create a Virtual File System.
-%% VFS = ?match({_,_,_,_,_,_},
-%% cosFileTransferApp:create_VFS({'NATIVE',
-%% 'cosFileTransferNATIVE_file'},
-%% [], Host, ?FTP_PORT)),
- VFS = ?matchnopr({'IOP_IOR',"IDL:omg.org/CosFileTransfer/VirtualFileSystem:1.0",_},
- corba:string_to_object("corbaname::1.2@localhost:4008/NameService#fileIterator_api")),
-
- %% Start two File Transfer Sessions (Source and Target).
- {FS, Dir} = ?matchnopr({{_,_,_},{_,_,_}},
- 'CosFileTransfer_VirtualFileSystem':login(VFS,
- ?FTP_USER,
- ?FTP_PASS,
- ?FTP_ACC)),
-
- %% Do some basic test on one of the Directories attributes.
- ?match([_H|_], 'CosFileTransfer_Directory':'_get_name'(Dir)),
- ?match([_H|_], 'CosFileTransfer_Directory':'_get_complete_file_name'(Dir)),
- ?match({'IOP_IOR',[],[]}, 'CosFileTransfer_Directory':'_get_parent'(Dir)),
- ?matchnopr(FS, 'CosFileTransfer_Directory':'_get_associated_session'(Dir)),
- {ok,[],FileIter} = ?match({ok,[],_}, 'CosFileTransfer_Directory':list(Dir, 0)),
- %% Usually the working directory for the test is not empty so no need for
- %% creating files of our own?!
- #any{value=Children} = ?match({any, _, _},
- 'CosPropertyService_PropertySet':
- get_property_value(Dir, "num_children")),
-
- if
- Children > 5 ->
- ?matchnopr({true, _}, 'CosFileTransfer_FileIterator':next_one(FileIter)),
- ?matchnopr({true, _}, 'CosFileTransfer_FileIterator':next_n(FileIter, 3)),
- ?matchnopr({true, _}, 'CosFileTransfer_FileIterator':next_n(FileIter,
- Children)),
- ?matchnopr({false, _}, 'CosFileTransfer_FileIterator':next_one(FileIter)),
- ?match({false, []}, 'CosFileTransfer_FileIterator':next_n(FileIter, 1)),
- ok;
- true ->
- ok
- end,
- ?match(ok, 'CosFileTransfer_FileIterator':destroy(FileIter)),
- ?match(false, corba_object:non_existent(FS)),
- ?match(ok, 'CosFileTransfer_FileTransferSession':logout(FS)),
- %% To make sure Orber can remove it from mnesia.
- timer:sleep(1000),
- ?match(true, corba_object:non_existent(FS)),
- ?match(ok, remote_apply(Node, ?MODULE, uninstall_data, ["fileIterator_api"])),
- stop_orber_remote(Node, normal),
- ok
- end.
-
-
-%%-----------------------------------------------------------------
-%% FileTransferSession API tests
-%%-----------------------------------------------------------------
-fts_ftp_file_api(Config) ->
- {ok, Node} = create_node("ftp_file_api", 4004, normal),
- file_helper(Config, 'FTP', ?TEST_DIR, Node, 4004, "ftp_file_api", tcp).
-
-fts_ftp_file_ssl_api(Config) ->
- {ok, Node} = create_node("ftp_file_api_ssl", {4005, 1}, ssl),
- file_helper(Config, 'FTP', ?TEST_DIR, Node, 4005, "ftp_file_api_ssl", ssl).
-
-fts_native_file_api(Config) ->
- {ok, Node} = create_node("native_file_api", 4006, normal),
- {ok, Pwd} = file:get_cwd(),
- file_helper(Config,{'NATIVE', 'cosFileTransferNATIVE_file'},filename:split(Pwd),
- Node, 4006, "native_file_api", tcp).
-
-fts_native_file_ssl_api(Config) ->
- {ok, Node} = create_node("native_file_ssl_api", {4007, 1}, ssl),
- {ok, Pwd} = file:get_cwd(),
- file_helper(Config,{'NATIVE', 'cosFileTransferNATIVE_file'},filename:split(Pwd),
- Node, 4007, "native_file_ssl_api", ssl).
-
-
-file_helper(Config, WhichType, TEST_DIR, Node, Port, Name, Type) ->
- case ftp_host(Config) of
- {skipped, SkippedReason} ->
- {skipped, SkippedReason};
- Host ->
- TEST_SOURCE = TEST_DIR ++ [create_name(remove_me_source)],
- TEST_SOURCE2 = TEST_DIR ++ [create_name(remove_me_source)],
- TEST_TARGET = TEST_DIR ++ [create_name(remove_me_target)],
-
- io:format("<<<<<< CosFileTransfer Testing Configuration >>>>>>~n",[]),
- io:format("Source: ~p~nTarget: ~p~n", [TEST_SOURCE, TEST_TARGET]),
-
- ?match(ok, remote_apply(Node, ?MODULE, install_data,
- [Type, {WhichType, Host, Name}])),
-
- VFST = ?match({'IOP_IOR',"IDL:omg.org/CosFileTransfer/VirtualFileSystem:1.0",_},
- corba:string_to_object("corbaname::1.2@localhost:"++integer_to_list(Port)++"/NameService#"++Name)),
-
-
- %% Create a Virtual File System.
- VFS = ?match({_,_,_,_,_,_},
- cosFileTransferApp:create_VFS(WhichType, [], Host, ?FTP_PORT,
- [{protocol, Type}])),
- %% Start two File Transfer Sessions (Source and Target).
- {FST, _DirT} = ?match({{_,_,_},{_,_,_}},
- 'CosFileTransfer_VirtualFileSystem':login(VFST,
- ?FTP_USER,
- ?FTP_PASS,
- ?FTP_ACC)),
- {FSS, DirS} = ?match({{_,_,_,_,_,_},{_,_,_,_,_,_}},
- 'CosFileTransfer_VirtualFileSystem':login(VFS,
- ?FTP_USER,
- ?FTP_PASS,
- ?FTP_ACC)),
-
- %% Do some basic test on one of the Directories attributes.
- ?match([_H|_], 'CosFileTransfer_Directory':'_get_name'(DirS)),
- ?match([_H|_], 'CosFileTransfer_Directory':'_get_complete_file_name'(DirS)),
- ?match({'IOP_IOR',[],[]}, 'CosFileTransfer_Directory':'_get_parent'(DirS)),
- ?match(FSS, 'CosFileTransfer_Directory':'_get_associated_session'(DirS)),
-
- %% Get a FileList before we create any new Files
- #'CosFileTransfer_FileWrapper'{the_file = Dir} =
- ?match({'CosFileTransfer_FileWrapper', _, ndirectory},
- 'CosFileTransfer_FileTransferSession':get_file(FSS, TEST_DIR)),
- {ok,FileList, Iter1} = ?match({ok,_,_}, 'CosFileTransfer_Directory':list(Dir, 10)),
- loop_files(FileList),
-
- case Iter1 of
- {'IOP_IOR',[],[]} ->
- ok;
- _->
- ?match(ok, 'CosFileTransfer_FileIterator':destroy(Iter1))
- end,
-
- #any{value=Count1} = ?match({any, _, _}, 'CosPropertyService_PropertySet':
- get_property_value(Dir, "num_children")),
-
- %% Now we want to transfer a file from source to target. First, we'll create
- %% a a file to work with.
- create_file_on_source_node(WhichType, Config, Host,
- filename:join(TEST_SOURCE), TEST_DIR,
- ?TEST_FILE_DATA),
- create_file_on_source_node(WhichType, Config, Host,
- filename:join(TEST_SOURCE2), TEST_DIR,
- ?TEST_FILE_DATA2),
-
- #'CosFileTransfer_FileWrapper'{the_file = FileS} =
- ?matchnopr({'CosFileTransfer_FileWrapper', _, nfile},
- 'CosFileTransfer_FileTransferSession':get_file(FSS, TEST_SOURCE)),
- #'CosFileTransfer_FileWrapper'{the_file = FileS2} =
- ?matchnopr({'CosFileTransfer_FileWrapper', _, nfile},
- 'CosFileTransfer_FileTransferSession':get_file(FSS, TEST_SOURCE2)),
-
- #any{value=Count2} = ?match({any, _, _}, 'CosPropertyService_PropertySet':
- get_property_value(Dir, "num_children")),
- timer:sleep(2000),
- ?match(true, (Count1+2 == Count2)),
-
- %% Create a target File
- FileT = ?matchnopr({_,_,_},
- 'CosFileTransfer_FileTransferSession':create_file(FST, TEST_TARGET)),
- %% Try to delete the non-existing file.
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_FileTransferSession':delete(FST, FileT)),
-
- ?match(ok, 'CosFileTransfer_FileTransferSession':transfer(FSS, FileS, FileT)),
-
- %% Remove this test when ftp supports append.
- case WhichType of
- {'NATIVE', 'cosFileTransferNATIVE_file'} ->
- ?match(ok, 'CosFileTransfer_FileTransferSession':append(FSS, FileS, FileT)),
- ?match(ok, 'CosFileTransfer_FileTransferSession':insert(FSS, FileS2, FileT, 7));
- _->
- ok
- end,
-
- %% Delete source and target files
- ?match(ok, 'CosFileTransfer_FileTransferSession':delete(FSS, FileS)),
- ?match(ok, 'CosFileTransfer_FileTransferSession':delete(FSS, FileS2)),
- ?match(ok, 'CosFileTransfer_FileTransferSession':delete(FST, FileT)),
-
- %% Should be back where we started.
- timer:sleep(2000),
- #any{value=Count3} = ?match({any, _, _}, 'CosPropertyService_PropertySet':
- get_property_value(Dir, "num_children")),
- ?match(true, (Count1 == Count3)),
-
-
- ?match(false, corba_object:non_existent(FSS)),
- ?match(false, corba_object:non_existent(FST)),
- ?match(ok, 'CosFileTransfer_FileTransferSession':logout(FSS)),
- ?match(ok, 'CosFileTransfer_FileTransferSession':logout(FST)),
- %% To make sure Orber can remove it from mnesia.
- timer:sleep(2000),
- ?match(true, corba_object:non_existent(FSS)),
- ?match(true, corba_object:non_existent(FST)),
- ?match(ok, remote_apply(Node, ?MODULE, uninstall_data, [Name])),
- stop_orber_remote(Node, normal),
- ok
- end.
-
-%%-----------------------------------------------------------------
-%% FileTransferSession API tests
-%%-----------------------------------------------------------------
-fts_ftp_dir_api(Config) ->
- {ok, Node} = create_node("ftp_dir_api", 4009, normal),
- dir_helper(Config, 'FTP', ?TEST_DIR, Node, 4009, "ftp_dir_api").
-
-fts_native_dir_api(Config) ->
- {ok, Node} = create_node("native_dir_api", 4010, normal),
- {ok, Pwd} = file:get_cwd(),
- dir_helper(Config, {'NATIVE', 'cosFileTransferNATIVE_file'},
- filename:split(Pwd), Node, 4010, "native_dir_api").
-
-dir_helper(Config, WhichType, TEST_DIR, Node, Port, Name) ->
- case ftp_host(Config) of
- {skipped, SkippedReason} ->
- {skipped, SkippedReason};
- Host ->
- TEST_DIR_LEVEL1 = TEST_DIR ++ [create_name(remove_me_dir1)],
- TEST_DIR_LEVEL2 = TEST_DIR_LEVEL1 ++ [create_name(remove_me_dir2)],
-
- io:format("<<<<<< CosFileTransfer Testing Configuration >>>>>>~n",[]),
- io:format("Top Dir: ~p~nLevel2 Dir: ~p~n", [TEST_DIR_LEVEL1, TEST_DIR_LEVEL2]),
-
- ?match(ok, remote_apply(Node, ?MODULE, install_data,
- [tcp, {WhichType, Host, Name}])),
-
- VFS = ?matchnopr({'IOP_IOR',"IDL:omg.org/CosFileTransfer/VirtualFileSystem:1.0",_},
- corba:string_to_object("corbaname::1.2@localhost:"++integer_to_list(Port)++"/NameService#"++Name)),
-
- %% Start two File Transfer Sessions (Source and Target).
- {FS, DirS} = ?matchnopr({{'IOP_IOR',_,_}, _},
- 'CosFileTransfer_VirtualFileSystem':login(VFS,
- ?FTP_USER,
- ?FTP_PASS,
- ?FTP_ACC)),
-
- %% Do some basic test on one of the Directories attributes.
- ?match([_H|_], 'CosFileTransfer_Directory':'_get_name'(DirS)),
- ?match([_H|_], 'CosFileTransfer_Directory':'_get_complete_file_name'(DirS)),
- ?match({'IOP_IOR',[],[]}, 'CosFileTransfer_Directory':'_get_parent'(DirS)),
- ?matchnopr(FS, 'CosFileTransfer_Directory':'_get_associated_session'(DirS)),
-
- %% Create a Root Directory. Currently we only need to create one but
- %% later on, when supporting other protocols than FTP it's not enough.
- Dir1 = 'CosFileTransfer_FileTransferSession':create_directory(FS,
- TEST_DIR_LEVEL1),
- io:format("<<<<<< CosFileTransfer Testing Properties >>>>>>~n",[]),
- ?match({ok, [tk_long, tk_boolean]},
- 'CosFileTransfer_Directory':get_allowed_property_types(Dir1)),
- ?match({ok, [_,_]},
- 'CosFileTransfer_Directory':get_allowed_properties(Dir1)),
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':define_property_with_mode(Dir1,
- "num_children",
- #any{typecode=tk_long, value=0},
- fixed_readonly)),
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':define_property_with_mode(Dir1,
- "wrong",
- #any{typecode=tk_long, value=0},
- fixed_readonly)),
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':define_property_with_mode(Dir1,
- "num_children",
- #any{typecode=tk_short, value=0},
- fixed_readonly)),
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':define_property_with_mode(Dir1,
- "num_children",
- #any{typecode=tk_long, value=0},
- fixed_normal)),
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':define_properties_with_modes(Dir1,
- [#'CosPropertyService_PropertyDef'
- {property_name = "num_children",
- property_value = #any{typecode=tk_long, value=0},
- property_mode = fixed_readonly}])),
- ?match(fixed_readonly,
- 'CosFileTransfer_Directory':get_property_mode(Dir1, "num_children")),
- ?match({true,
- [#'CosPropertyService_PropertyMode'{property_name = "num_children",
- property_mode = fixed_readonly}]},
- 'CosFileTransfer_Directory':get_property_modes(Dir1, ["num_children"])),
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':set_property_mode(Dir1, "num_children", fixed_readonly)),
-
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':
- set_property_modes(Dir1,
- [#'CosPropertyService_PropertyMode'
- {property_name = "num_children",
- property_mode = fixed_readonly}])),
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':
- set_property_modes(Dir1,
- [#'CosPropertyService_PropertyMode'
- {property_name = "wrong",
- property_mode = fixed_readonly}])),
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':
- set_property_modes(Dir1,
- [#'CosPropertyService_PropertyMode'
- {property_name = "num_children",
- property_mode = fixed_normal}])),
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':define_property(Dir1,
- "num_children",
- #any{typecode=tk_long, value=0})),
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':define_property(Dir1,
- "wrong",
- #any{typecode=tk_long, value=0})),
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':define_property(Dir1,
- "num_children",
- #any{typecode=tk_short, value=0})),
-
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':define_property(Dir1,
- "num_children",
- #any{typecode=tk_long, value=0})),
-
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':
- define_properties(Dir1,
- [#'CosPropertyService_Property'
- {property_name = "num_children",
- property_value = #any{typecode=tk_long,
- value=0}}])),
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':
- define_properties(Dir1,
- [#'CosPropertyService_Property'
- {property_name = "wrong",
- property_value = #any{typecode=tk_long,
- value=0}}])),
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':
- define_properties(Dir1,
- [#'CosPropertyService_Property'
- {property_name = "num_children",
- property_value = #any{typecode=tk_short,
- value=0}}])),
- ?match(2, 'CosFileTransfer_Directory':get_number_of_properties(Dir1)),
-
- ?match({ok, ["num_children", "is_directory"], {'IOP_IOR',[],[]}},
- 'CosFileTransfer_Directory':get_all_property_names(Dir1, 2)),
- ?match({ok, ["is_directory"], _},
- 'CosFileTransfer_Directory':get_all_property_names(Dir1, 1)),
-
- ?match(#any{},
- 'CosFileTransfer_Directory':get_property_value(Dir1, "num_children")),
- ?match(#any{},
- 'CosFileTransfer_Directory':get_property_value(Dir1, "is_directory")),
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':get_property_value(Dir1, "wrong")),
-
- ?match({true,
- [#'CosPropertyService_Property'{property_name = "num_children"}]},
- 'CosFileTransfer_Directory':get_properties(Dir1, ["num_children"])),
- ?match({false,
- [#'CosPropertyService_Property'{property_name = "wrong"}]},
- 'CosFileTransfer_Directory':get_properties(Dir1, ["wrong"])),
-
- ?match({ok, [_],_},
- 'CosFileTransfer_Directory':get_all_properties(Dir1, 1)),
- ?match({ok, [_,_], {'IOP_IOR',[],[]}},
- 'CosFileTransfer_Directory':get_all_properties(Dir1, 2)),
-
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':delete_property(Dir1, "num_children")),
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':delete_property(Dir1, "wrong")),
-
-
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':delete_properties(Dir1, ["num_children"])),
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_Directory':delete_properties(Dir1, ["wrong"])),
- ?match(false, 'CosFileTransfer_Directory':delete_all_properties(Dir1)),
- ?match(true,
- 'CosFileTransfer_Directory':is_property_defined(Dir1, "num_children")),
- ?match(false,
- 'CosFileTransfer_Directory':is_property_defined(Dir1, "wrong")),
-
- %% The Top Dir should be empty and ...
- ?match({ok,[],_}, 'CosFileTransfer_Directory':list(Dir1, 1000)),
- ?match( #any{value=0},
- 'CosPropertyService_PropertySet':get_property_value(Dir1, "num_children")),
- %% Create a sub-directory.
- Dir2 = 'CosFileTransfer_FileTransferSession':create_directory(FS,
- TEST_DIR_LEVEL2),
- ?match( #any{value=1},
- 'CosPropertyService_PropertySet':get_property_value(Dir1, "num_children")),
-
- ?match({ok, [_,_], {'IOP_IOR',[],[]}},
- 'CosFileTransfer_Directory':get_all_properties(Dir1, 2)),
- {_,_,Iterator1} = ?match({ok, [_], _},
- 'CosFileTransfer_Directory':get_all_properties(Dir1, 1)),
- ?match({false, [_]},
- 'CosPropertyService_PropertiesIterator':next_n(Iterator1,4)),
-
- {_,_,Iterator0} = ?match({ok, [], _},
- 'CosFileTransfer_Directory':get_all_properties(Dir1, 0)),
-
- ?match({false, [_, {'CosPropertyService_Property',
- "num_children",{any,tk_long,1}}]},
- 'CosPropertyService_PropertiesIterator':next_n(Iterator0,4)),
-
- ?match({true,
- [#'CosPropertyService_Property'{property_name = "num_children"}]},
- 'CosFileTransfer_Directory':get_properties(Dir1, ["num_children"])),
-
- %% The Top Directory is not emtpy any more and ...
- {ok,[#'CosFileTransfer_FileWrapper'{the_file = DirRef}],_} =
- ?matchnopr({ok,[{'CosFileTransfer_FileWrapper', _, ndirectory}],_},
- 'CosFileTransfer_Directory':list(Dir1, 1000)),
- %% ... its name eq. to 'TEST_DIR_LEVEL2'
- ?match(TEST_DIR_LEVEL2,
- 'CosFileTransfer_Directory':'_get_complete_file_name'(DirRef)),
-
- #'CosFileTransfer_FileWrapper'{the_file = Dir3} =
- ?matchnopr({'CosFileTransfer_FileWrapper', _, ndirectory},
- 'CosFileTransfer_FileTransferSession':get_file(FS, TEST_DIR_LEVEL1)),
-
- %% Must get the same result for the 'get_file' operation.
- {ok,[#'CosFileTransfer_FileWrapper'{the_file = DirRef2}],_} =
- ?matchnopr({ok,[{'CosFileTransfer_FileWrapper', _, ndirectory}],_},
- 'CosFileTransfer_Directory':list(Dir3,1000)),
- ?match(TEST_DIR_LEVEL2,
- 'CosFileTransfer_Directory':'_get_complete_file_name'(DirRef2)),
-
- %% Since the top directory isn't empty deleting it must fail.
- ?match({'EXCEPTION', _},
- 'CosFileTransfer_FileTransferSession':delete(FS, Dir1)),
-
- %% Delete the sub-directory and ...
- ?match(ok, 'CosFileTransfer_FileTransferSession':delete(FS, Dir2)),
- %% ... see if the top directory realyy is empty.
- ?match({ok,[],_}, 'CosFileTransfer_Directory':list(Dir1, 1000)),
-
- ?match(ok, 'CosFileTransfer_FileTransferSession':delete(FS, Dir1)),
- %% Test if the top directory been removed as intended.
- ?match({'EXCEPTION', {'CosFileTransfer_FileNotFoundException', _, _}},
- 'CosFileTransfer_FileTransferSession':get_file(FS, TEST_DIR_LEVEL1)),
-
- ?match(false, corba_object:non_existent(FS)),
- ?match(ok, 'CosFileTransfer_FileTransferSession':logout(FS)),
- %% To make sure Orber can remove it from mnesia.
- timer:sleep(1000),
- ?match(true, corba_object:non_existent(FS)),
- ?match(ok, remote_apply(Node, ?MODULE, uninstall_data, [Name])),
- stop_orber_remote(Node, normal),
- ok
- end.
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-ftp_host(Config) ->
- case ?config(ftp_remote_host, Config) of
- undefined ->
- {skipped, "The configuration parameter 'ftp_remote_host' not defined."};
- Host ->
- Host
- end.
-
-loop_files([]) ->
- io:format("@@@ DONE @@@~n", []);
-loop_files([#'CosFileTransfer_FileWrapper'{the_file = H}|T]) ->
- FullName = 'CosFileTransfer_File':'_get_complete_file_name'(H),
- Name = 'CosFileTransfer_File':'_get_name'(H),
- io:format("FULL NAME: ~p SHORT NAME: ~p~n", [FullName, Name]),
- loop_files(T).
-
-
-create_file_on_source_node('FTP', _Config, Host, FileName, Path, Data) ->
- io:format("<<<<<< CosFileTransfer Testing File >>>>>>~n",[]),
- io:format("Host: ~p~nPath: ~p~nFile: ~p~n", [Host, Path, FileName]),
- {ok, Pid} = ?match({ok, _}, inets:start(ftpc, [{host, Host}], stand_alone)),
- ?match(ok, ftp:user(Pid, ?FTP_USER, ?FTP_PASS)),
- ?match(ok, ftp:cd(Pid, Path)),
- ?match(ok, ftp:send_bin(Pid, list_to_binary(Data), FileName)),
- ?match(ok, inets:stop(ftpc, Pid));
-create_file_on_source_node({'NATIVE', _}, _Config, Host, FileName, Path, Data) ->
- io:format("<<<<<< CosFileTransfer Testing File >>>>>>~n",[]),
- io:format("Host: ~p~nPath: ~p~nFile: ~p~n", [Host, Path, FileName]),
- ?match(ok, file:write_file(FileName, list_to_binary(Data))).
-
-create_name(Type) ->
- Time = erlang:system_time(),
- Unique = erlang:unique_integer([positive]),
- lists:concat([Type, '_', Time, '_', Unique]).
-
-
-
-
-%%------------------------------------------------------------
-%% function : create_node/4
-%% Arguments: Name - the name of the new node (atom())
-%% Port - which iiop_port (integer())
-%% Domain - which domain.
-%% Type - if /4 used the types defines the extra arguments
-%% to be used.
-%% Returns : {ok, Node} | {error, _}
-%% Effect : Starts a new slave-node with given (optinally)
-%% extra arguments. If fails it retries 'Retries' times.
-%%------------------------------------------------------------
-create_node(Name, Port, normal) ->
- Args = basic_args(Name),
- create_node(Name, Port, 10, normal, Args, []);
-create_node(Name, {Port, _Depth}, ssl) ->
- Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
- Args = basic_args(Name),
- {ok, Node} = create_node(list_to_atom(Name), Port, 10, ssl, Args, []),
- %% Client
- rpc:call(Node, application, set_env, [cosFileTransfer, ssl_client_certfile,
- filename:join([Dir, "client", "cert.pem"])]),
- rpc:call(Node, application, set_env, [cosFileTransfer, ssl_client_cacertfile,
- filename:join([Dir, "client", "cacerts.pem"])]),
- rpc:call(Node, application, set_env, [cosFileTransfer, ssl_client_keyfile,
- filename:join([Dir, "client", "key.pem"])]),
- rpc:call(Node, application, set_env, [cosFileTransfer, ssl_client_verify, 1]),
- rpc:call(Node, application, set_env, [cosFileTransfer, ssl_client_depth, 0]),
-
- %% Server
- rpc:call(Node, application, set_env, [cosFileTransfer, ssl_server_certfile,
- filename:join([Dir, "server", "cert.pem"])]),
- rpc:call(Node, application, set_env, [cosFileTransfer, ssl_server_cacertfile,
- filename:join([Dir, "server", "cacerts.pem"])]),
- rpc:call(Node, application, set_env, [cosFileTransfer, ssl_server_keyfile,
- filename:join([Dir, "server", "key.pem"])]),
- rpc:call(Node, application, set_env, [cosFileTransfer, ssl_server_verify, 1]),
- rpc:call(Node, application, set_env, [cosFileTransfer, ssl_server_depth, 0]),
- {ok, Node}.
-
-%create_node(Name, {Port, Depth}, ssl) ->
-% TestLibs = filename:join(filename:dirname(code:which(?MODULE)), "ssl_data"),
-% Args = basic_args(Name),
-% SArgs = basic_ssl_args(TestLibs, Args),
-% LArgs = level_based_ssl(Depth, TestLibs, SArgs),
-% create_node(list_to_atom(Name), Port, 10, ssl, LArgs, [{sslpath, TestLibs}]).
-
-create_node(Name, Port, Retries, Type, Args, Options) ->
- [_, Host] = ?match([_,_],string:tokens(atom_to_list(node()), [$@])),
- case starter(Host, Name, Args) of
- {ok, NewNode} ->
- ?match(pong, net_adm:ping(NewNode)),
- {ok, Cwd} = file:get_cwd(),
- Path = code:get_path(),
- ?match(ok, rpc:call(NewNode, file, set_cwd, [Cwd])),
- true = rpc:call(NewNode, code, set_path, [Path]),
- ?match(ok, start_orber_remote(NewNode, Type, Options, Port)),
- spawn_link(NewNode, ?MODULE, slave_sup, []),
- rpc:multicall([node() | nodes()], global, sync, []),
- {ok, NewNode};
- {error, Reason} when Retries == 0->
- {error, Reason};
- {error, Reason} ->
- io:format("Could not start slavenode ~p ~p retrying~n",
- [{Host, Name, Args}, Reason]),
- timer:sleep(500),
- create_node(Name, Port, Retries - 1, Type, Args, Options)
- end.
-
-starter(Host, Name, Args) ->
- slave:start(Host, Name, Args).
-
-slave_sup() ->
- process_flag(trap_exit, true),
- receive
- {'EXIT', _, _} ->
- ignore
- end.
-
-
-%%------------------------------------------------------------
-%% function : destroy_node
-%% Arguments: Node - which node to destroy.
-%% Type - normal | ssl
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
--ifdef(false).
-destroy_node(Node, Type) ->
- stopper(Node, Type).
-
-stopper(Node, Type) ->
- catch stop_orber_remote(Node, Type),
- slave:stop(Node).
--endif.
-
-%%------------------------------------------------------------
-%% function : remote_apply
-%% Arguments: N - Node, M - Module,
-%% F - Function, A - Arguments (list)
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-remote_apply(N, M,F,A) ->
- case rpc:call(N, M, F, A) of
- {badrpc, Reason} ->
- exit(Reason);
- Other ->
- Other
- end.
-
-%%------------------------------------------------------------
-%% function : stop_orber_remote
-%% Arguments: Node - which node to stop orber on.
-%% Type - normal | ssl | light | .......
-%% Returns : ok
-%% Effect : Stops orber on given node and, if specified,
-%% other applications or programs.
-%%------------------------------------------------------------
-stop_orber_remote(Node, ssl) ->
- rpc:call(Node, ssl, stop, []),
- rpc:call(Node, crypto, stop, []),
- orb_rpc_blast(Node, ssl);
-stop_orber_remote(Node, Type) ->
- orb_rpc_blast(Node, Type).
-
-orb_rpc_blast(Node, _) ->
- rpc:call(Node, cosFileTransferApp, stop, []),
- rpc:call(Node, cosProperty, stop, []),
- rpc:call(Node, cosFileTransferApp, uninstall, []),
- rpc:call(Node, cosProperty, uninstall, []),
- rpc:call(Node, orber, jump_stop, []).
-
-%%------------------------------------------------------------
-%% function : start_orber_remote
-%% Arguments: Node - which node to start orber on.
-%% Type - normal | ssl | light | .......
-%% Returns : ok
-%% Effect : Starts orber on given node and, if specified,
-%% other applications or programs.
-%%------------------------------------------------------------
-start_orber_remote(Node, ssl, _Options, Port) ->
- rpc:call(Node, ssl, start, []),
- rpc:call(Node, crypto, start, []),
- rpc:call(Node, ssl, seed, ["testing"]),
- orb_rpc_setup(Node, ssl, Port);
-start_orber_remote(Node, Type, _, Port) ->
- orb_rpc_setup(Node, Type, Port).
-
-orb_rpc_setup(Node, _, Port) ->
- rpc:call(Node, orber, jump_start, [Port]),
- rpc:call(Node, cosProperty, install, []),
- rpc:call(Node, cosProperty, start, []),
- rpc:call(Node, cosFileTransferApp, install, []).
-
-%%--------------- MISC FUNCTIONS -----------------------------
-basic_args(_Name) ->
- TestLibs = filename:dirname(code:which(?MODULE)),
- " -orber orber_debug_level 10" ++
- " -pa " ++
- TestLibs ++
- " -pa " ++
- filename:join(TestLibs, "all_SUITE_data") ++
- " -pa " ++
- filename:dirname(code:which(cosFileTransferApp)).
-
--ifdef(false).
-basic_ssl_args(TestLibs, Args) ->
-% Args ++
-% " -cosFileTransfer ssl_client_certfile \\\"" ++
-% filename:join(TestLibs, "ssl_client_cert.pem") ++
-% "\\\" -cosFileTransfer ssl_server_certfile \\\""++
-% filename:join(TestLibs, "ssl_server_cert.pem")++"\\\"".
-
- io:format("<<<<<< SSL LIBS ~p >>>>>>~n",[TestLibs]),
- NewArgs = Args ++
- " -cosFileTransfer ssl_client_certfile \\\"" ++
- filename:join(TestLibs, "ssl_client_cert.pem") ++
- "\\\" -cosFileTransfer ssl_server_certfile \\\""++
- filename:join(TestLibs, "ssl_server_cert.pem")++"\\\"",
- io:format("<<<<<< SSL LIBS ARGS ~p >>>>>>~n",[NewArgs]),
- NewArgs.
-
-level_based_ssl(1, _TestLibs, Args) ->
- Args;
-level_based_ssl(2, _TestLibs, Args) ->
- Args.% ++
-% " -cosFileTransfer ssl_server_depth 2 " ++
-% " -cosFileTransfer ssl_client_depth 2 " ++
-% " -cosFileTransfer ssl_server_verify " ++
-% " -cosFileTransfer ssl_client_verify " ++
-% " -cosFileTransfer ssl_server_cacertfile " ++
-% " -cosFileTransfer ssl_client_cacertfile " ++
-
--endif.
-
-install_data(Protocol, {WhichType, Host, Name}) ->
- io:format("<<<<<< Starting ~p/~p VFS at ~p/~p>>>>>>~n",
- [Protocol, WhichType, Host, Name]),
- %% Create a Virtual File System.
- VFS = ?match({_,_,_,_,_,_},
- cosFileTransferApp:create_VFS(WhichType, [], Host, ?FTP_PORT,
- [{protocol, Protocol}])),
- NS = corba:resolve_initial_references("NameService"),
- NC1 = lname_component:set_id(lname_component:create(), Name),
- N = lname:insert_component(lname:create(), 1, NC1),
- 'CosNaming_NamingContext':rebind(NS, N, VFS).
-
-uninstall_data(Name) ->
- VFS = ?match({_,_,_,_,_,_},
- corba:string_to_object("corbaname:rir:/NameService#"++Name)),
- ?match(ok, corba:dispose(VFS)),
- ok.
-
-
-
-%%------------------- EOF MODULE-----------------------------------
diff --git a/lib/cosFileTransfer/vsn.mk b/lib/cosFileTransfer/vsn.mk
deleted file mode 100644
index e271c05242..0000000000
--- a/lib/cosFileTransfer/vsn.mk
+++ /dev/null
@@ -1 +0,0 @@
-COSFILETRANSFER_VSN = 1.2.1
diff --git a/lib/cosNotification/AUTHORS b/lib/cosNotification/AUTHORS
deleted file mode 100644
index 55d8059989..0000000000
--- a/lib/cosNotification/AUTHORS
+++ /dev/null
@@ -1,4 +0,0 @@
-Original Authors:
-Niclas Eklund
-
-Contributors:
diff --git a/lib/cosNotification/Makefile b/lib/cosNotification/Makefile
deleted file mode 100644
index 0408417a3b..0000000000
--- a/lib/cosNotification/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include vsn.mk
-VSN=$(COSNOTIFICATION_VSN)
-
-# ----------------------------------------------------
-# Common Macros
-# ----------------------------------------------------
-# SUB_DIRECTORIES = src test examples doc/src
-# At the moment we don't have any example programs.
-SUB_DIRECTORIES = src doc/src
-
-SPECIAL_TARGETS =
-
-# ----------------------------------------------------
-# Default Subdir Targets
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_subdir.mk
diff --git a/lib/cosNotification/doc/html/.gitignore b/lib/cosNotification/doc/html/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosNotification/doc/html/.gitignore
+++ /dev/null
diff --git a/lib/cosNotification/doc/man3/.gitignore b/lib/cosNotification/doc/man3/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosNotification/doc/man3/.gitignore
+++ /dev/null
diff --git a/lib/cosNotification/doc/man6/.gitignore b/lib/cosNotification/doc/man6/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosNotification/doc/man6/.gitignore
+++ /dev/null
diff --git a/lib/cosNotification/doc/pdf/.gitignore b/lib/cosNotification/doc/pdf/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosNotification/doc/pdf/.gitignore
+++ /dev/null
diff --git a/lib/cosNotification/doc/src/CosNotification.xml b/lib/cosNotification/doc/src/CosNotification.xml
deleted file mode 100644
index 6aac312d5e..0000000000
--- a/lib/cosNotification/doc/src/CosNotification.xml
+++ /dev/null
@@ -1,235 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2002</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotification</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2002-02-05</date>
- <rev>PA1</rev>
- </header>
- <module>CosNotification</module>
- <modulesummary>This module export functions which return QoS and Admin Properties constants.</modulesummary>
- <description>
- <p>To get access to all definitions include necessary <c>hrl</c> files by using: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>'EventReliability'() -> string()</name>
- <fsummary>Return the EventReliability QoS identifier</fsummary>
- <desc>
- <p>This function returns the EventReliability QoS identifier</p>
- </desc>
- </func>
- <func>
- <name>'BestEffort'() -> short()</name>
- <fsummary>Return the BestEffort QoS value</fsummary>
- <desc>
- <p>This function returns the BestEffort QoS value.</p>
- </desc>
- </func>
- <func>
- <name>'Persistent'() -> short()</name>
- <fsummary>Return the Persistent QoS value</fsummary>
- <desc>
- <p>This function returns the Persistent QoS value.</p>
- </desc>
- </func>
- <func>
- <name>'ConnectionReliability'() -> string()</name>
- <fsummary>Return the ConnectionReliability QoS identifier</fsummary>
- <desc>
- <p>This function returns the ConnectionReliability QoS identifier.</p>
- </desc>
- </func>
- <func>
- <name>'Priority'() -> string()</name>
- <fsummary>Return the Priority QoS identifier</fsummary>
- <desc>
- <p>This function returns the Priority QoS identifier.</p>
- </desc>
- </func>
- <func>
- <name>'LowestPriority'() -> short()</name>
- <fsummary>Return the LowestPriority QoS value</fsummary>
- <desc>
- <p>This function returns the LowestPriority QoS value.</p>
- </desc>
- </func>
- <func>
- <name>'HighestPriority'() -> short()</name>
- <fsummary>Return the HighestPriority QoS value</fsummary>
- <desc>
- <p>This function returns the HighestPriority QoS value.</p>
- </desc>
- </func>
- <func>
- <name>'DefaultPriority'() -> short()</name>
- <fsummary>Return the DefaultPriority QoS value</fsummary>
- <desc>
- <p>This function returns the DefaultPriority QoS value.</p>
- </desc>
- </func>
- <func>
- <name>'StartTime'() -> string()</name>
- <fsummary>Return the StartTime QoS identifier</fsummary>
- <desc>
- <p>This function returns the StartTime QoS identifier.</p>
- </desc>
- </func>
- <func>
- <name>'StopTime'() -> string()</name>
- <fsummary>Return the StopTime QoS identifier</fsummary>
- <desc>
- <p>This function returns the StopTime QoS identifier.</p>
- </desc>
- </func>
- <func>
- <name>'Timeout'() -> string()</name>
- <fsummary>Return the Timeout QoS identifier</fsummary>
- <desc>
- <p>This function returns the Timeout QoS identifier.</p>
- </desc>
- </func>
- <func>
- <name>'OrderPolicy'() -> string()</name>
- <fsummary>Return the OrderPolicy QoS identifier</fsummary>
- <desc>
- <p>This function returns the OrderPolicy QoS identifier.</p>
- </desc>
- </func>
- <func>
- <name>'AnyOrder'() -> short()</name>
- <fsummary>Return the AnyOrder QoS value</fsummary>
- <desc>
- <p>This function returns the AnyOrder QoS value.</p>
- </desc>
- </func>
- <func>
- <name>'FifoOrder'() -> short()</name>
- <fsummary>Return the FifoOrder QoS value</fsummary>
- <desc>
- <p>This function returns the FifoOrder QoS value.</p>
- </desc>
- </func>
- <func>
- <name>'PriorityOrder'() -> short()</name>
- <fsummary>Return the PriorityOrder QoS value</fsummary>
- <desc>
- <p>This function returns the PriorityOrder QoS value.</p>
- </desc>
- </func>
- <func>
- <name>'DeadlineOrder'() -> short()</name>
- <fsummary>Return the DeadlineOrder QoS value</fsummary>
- <desc>
- <p>This function returns the DeadlineOrder QoS value.</p>
- </desc>
- </func>
- <func>
- <name>'DiscardPolicy'() -> string()</name>
- <fsummary>Return the DiscardPolicy QoS identifier</fsummary>
- <desc>
- <p>This function returns the DiscardPolicy QoS identifier.</p>
- </desc>
- </func>
- <func>
- <name>'LifoOrder'() -> short()</name>
- <fsummary>Return the LifoOrder QoS value</fsummary>
- <desc>
- <p>This function returns the LifoOrder QoS value.</p>
- </desc>
- </func>
- <func>
- <name>'RejectNewEvents'() -> short()</name>
- <fsummary>Return the RejectNewEvents QoS value</fsummary>
- <desc>
- <p>This function returns the RejectNewEvents QoS value.</p>
- </desc>
- </func>
- <func>
- <name>'MaximumBatchSize'() -> string()</name>
- <fsummary>Return the MaximumBatchSize QoS identifier</fsummary>
- <desc>
- <p>This function returns the MaximumBatchSize QoS identifier.</p>
- </desc>
- </func>
- <func>
- <name>'PacingInterval'() -> string()</name>
- <fsummary>Return the PacingInterval QoS identifier</fsummary>
- <desc>
- <p>This function returns the PacingInterval QoS identifier.</p>
- </desc>
- </func>
- <func>
- <name>'StartTimeSupported'() -> string()</name>
- <fsummary>Return the StartTimeSupported QoS identifier</fsummary>
- <desc>
- <p>This function returns the StartTimeSupported QoS identifier.</p>
- </desc>
- </func>
- <func>
- <name>'StopTimeSupported'() -> string()</name>
- <fsummary>Return the StopTimeSupported QoS identifier</fsummary>
- <desc>
- <p>This function returns the StopTimeSupported QoS identifier.</p>
- </desc>
- </func>
- <func>
- <name>'MaxEventsPerConsumer'() -> string()</name>
- <fsummary>Return the MaxEventsPerConsumer QoS identifier</fsummary>
- <desc>
- <p>This function returns the MaxEventsPerConsumer QoS identifier.</p>
- </desc>
- </func>
- <func>
- <name>'MaxQueueLength'() -> string()</name>
- <fsummary>Return the MaxQueueLength Admin identifier</fsummary>
- <desc>
- <p>This function returns the MaxQueueLength Admin identifier.</p>
- </desc>
- </func>
- <func>
- <name>'MaxConsumers'() -> string()</name>
- <fsummary>Return the MaxConsumers Admin identifier</fsummary>
- <desc>
- <p>This function returns the MaxConsumers Admin identifier.</p>
- </desc>
- </func>
- <func>
- <name>'MaxSuppliers'() -> string()</name>
- <fsummary>Return the MaxSuppliers Admin identifier</fsummary>
- <desc>
- <p>This function returns the MaxSuppliers Admin identifier.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotification_AdminPropertiesAdmin.xml b/lib/cosNotification/doc/src/CosNotification_AdminPropertiesAdmin.xml
deleted file mode 100644
index 6086402f1a..0000000000
--- a/lib/cosNotification/doc/src/CosNotification_AdminPropertiesAdmin.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotification_AdminPropertiesAdmin</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotification_AdminPropertiesAdmin</module>
- <modulesummary>This module implements the OMG CosNotification::AdminPropertiesAdmin interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>All objects, which inherit this interface, export functions described in this module.</p>
- </description>
- <funcs>
- <func>
- <name>get_admin(Object) -> AdminProperties</name>
- <fsummary>Return a list of <c>AdminProperties</c>associated with the target object</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>AdminProperties = [AdminProperty]</v>
- <v>AdminProperty = #'CosNotification_Property'{name, value}</v>
- <v>name = string()</v>
- <v>value = #any</v>
- </type>
- <desc>
- <p>This operation returns sequence of name-value pairs which encapsulates the
- current administrative properties of the target object.</p>
- </desc>
- </func>
- <func>
- <name>set_admin(Object, AdminProperties) -> Reply</name>
- <fsummary>Update the <c>AdminProperties</c>for the target object</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>AdminProperties = [AdminProperty]</v>
- <v>AdminProperty = #'CosNotification_Property'{name, value}</v>
- <v>name = string()</v>
- <v>value = #any</v>
- <v>Reply = ok | {'EXCEPTION', CosNotification_UnsupportedAdmin}</v>
- </type>
- <desc>
- <p>As input, this operation accepts a sequence of name-value pairs encapsulating the
- desired administrative settings for the target object. If it is not possible to
- set the given properties the exception <c>UnsupportedAdmin</c> will be raised.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotification_QoSAdmin.xml b/lib/cosNotification/doc/src/CosNotification_QoSAdmin.xml
deleted file mode 100644
index 7774652e60..0000000000
--- a/lib/cosNotification/doc/src/CosNotification_QoSAdmin.xml
+++ /dev/null
@@ -1,107 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosNotification_QoSAdmin</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotification_QoSAdmin</module>
- <modulesummary>This module implements the OMG CosNotification::QoSAdmin interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>All objects, which inherit this interface, export functions described in this module.</p>
- </description>
- <funcs>
- <func>
- <name>get_qos(Object) -> Reply</name>
- <fsummary>Return a list of name-value pairs which encapsulates the current QoS settings for the target object</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Reply = [QoSProperty]</v>
- <v>QoSProperty = #'CosNotification_Property'{name, value}</v>
- <v>name = string()</v>
- <v>value = #any</v>
- </type>
- <desc>
- <p>This operation returns a list of name-value pairs which encapsulates the current QoS settings
- for the target object.</p>
- </desc>
- </func>
- <func>
- <name>set_qos(Object, QoS) -> Reply</name>
- <fsummary>Change the QoS settings for the target object</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>QoS = [QoSProperty]</v>
- <v>QoSProperty = #'CosNotification_Property'{name, value}</v>
- <v>name = string()</v>
- <v>value = #any</v>
- <v>Reply = ok | {'EXCEPTION', #'CosNotification_UnsupportedQoS'{qos_err}}</v>
- <v>qos_err = PropertyErrorSeq</v>
- <v>PropertyErrorSeq = [PropertyError]</v>
- <v>PropertyError = #'CosNotification_PropertyError'{code, name, available_range}</v>
- <v>code = 'UNSUPPORTED_PROPERTY' | 'UNAVAILABLE_PROPERTY' | 'UNSUPPORTED_VALUE' | 'UNAVAILABLE_VALUE' | 'BAD_PROPERTY' | 'BAD_TYPE' | 'BAD_VALUE'</v>
- <v>name = string()</v>
- <v>available_range = PropertyRange</v>
- <v>PropertyRange = #CosNotification_PropertyRange{low_val, high_val}</v>
- <v>low_val = high_val = #any</v>
- </type>
- <desc>
- <p>To alter the current QoS settings for the target object this function must be used.
- If it is not possible to set the requested QoS the <c>UnsupportedQoS</c>
- exception is raised, which includes a sequence of <c>PropertyError</c>'s
- describing which QoS, possible range and why is not allowed.</p>
- </desc>
- </func>
- <func>
- <name>validate_qos(Object, QoS) -> Reply</name>
- <fsummary>Validate if the supplied QoS properties is valid for the target object </fsummary>
- <type>
- <v>Object = #objref</v>
- <v>QoS = [QoSProperty]</v>
- <v>QoSProperty = #'Property'{name, value}</v>
- <v>name = string()</v>
- <v>value = #any</v>
- <v>Reply = {ok, NamedPropertyRangeSeq} | {'EXCEPTION', CosNotification_UnsupportedQoS{}}</v>
- <v>NamedPropertyRangeSeq = [NamedPropertyRange]</v>
- <v>NamedPropertyRange = #CosNotification_NamedPropertyRange{name, range}</v>
- <v>name = string()</v>
- <v>range = #CosNotification_PropertyRange{low_val, high_val}</v>
- <v>low_val = #any</v>
- <v>high_val = #any</v>
- </type>
- <desc>
- <p>The purpose of this operations is to check if a QoS setting is supported
- by the target object and if so, the operation returns additional properties
- which could be optionally added as well.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ConsumerAdmin.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ConsumerAdmin.xml
deleted file mode 100644
index cbe22ce7cd..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ConsumerAdmin.xml
+++ /dev/null
@@ -1,242 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyChannelAdmin_ConsumerAdmin</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyChannelAdmin_ConsumerAdmin</module>
- <modulesummary>This module implements the OMG CosNotifyChannelAdmin::ConsumerAdmin interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosNotification_QoSAdmin">CosNotification_QoSAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyComm_NotifySubscribe">CosNotifyComm_NotifySubscribe</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyFilter_FilterAdmin">CosNotifyFilter_FilterAdmin</seealso></p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>_get_MyID(ConsumerAdmin) -> AdminID</name>
- <fsummary>Return the target object's Id</fsummary>
- <type>
- <v>ConsumerAdmin = #objref</v>
- <v>AdminID = long()</v>
- </type>
- <desc>
- <p>The ID returned by the creating channel is equal to the value encapsulated by
- this readonly attribute.</p>
- </desc>
- </func>
- <func>
- <name>_get_MyChannel(ConsumerAdmin) -> Channel</name>
- <fsummary>Return the ancestor channel</fsummary>
- <type>
- <v>ConsumerAdmin = #objref</v>
- <v>Channel = #objref</v>
- </type>
- <desc>
- <p>The creating channel's reference is maintained by this readonly attribute.</p>
- </desc>
- </func>
- <func>
- <name>_get_MyOperator(ConsumerAdmin) -> OpType</name>
- <fsummary>Return the filtering schema used by the target object</fsummary>
- <type>
- <v>ConsumerAdmin = #objref</v>
- <v>OpType = 'AND_OP' | 'OR_OP'</v>
- </type>
- <desc>
- <p>When <c>ConsumerAdmin's</c> are created an operation type,
- i.e., <c>'AND_OP'</c> or <c>'OR_OP'</c>, is supplied, which determines
- the semantics used by the target object concerning evaluation against
- any associated <c>Filter</c> objects.</p>
- </desc>
- </func>
- <func>
- <name>_get_priority_filter(ConsumerAdmin) -> MappingFilter</name>
- <fsummary>Return the associated priority <c>MappingFilter</c></fsummary>
- <type>
- <v>ConsumerAdmin = MappingFilter = #objref</v>
- </type>
- <desc>
- <p>If set, this operation returns the associated priority <c>MappingFilter</c>, otherwise
- a <c>NIL</c> object reference is returned.</p>
- </desc>
- </func>
- <func>
- <name>_set_priority_filter(ConsumerAdmin, MappingFilter) -> ok</name>
- <fsummary>Set the priority <c>MappingFilter</c></fsummary>
- <type>
- <v>ConsumerAdmin = MappingFilter = #objref</v>
- </type>
- <desc>
- <p>To associate a priority <c>MappingFilter</c> with the target object this operation
- must be used.</p>
- </desc>
- </func>
- <func>
- <name>_get_lifetime_filter(ConsumerAdmin) -> MappingFilter</name>
- <fsummary>Return the associated lifetime <c>MappingFilter</c></fsummary>
- <type>
- <v>ConsumerAdmin = MappingFilter = #objref</v>
- </type>
- <desc>
- <p>Unless a lifetime <c>MappingFilter</c> have been associated with the target object
- a <c>NIL</c> object reference is returned by this operation.</p>
- </desc>
- </func>
- <func>
- <name>_set_lifetime_filter(ConsumerAdmin, MappingFilter) -> ok</name>
- <fsummary>Set the lifetime <c>MappingFilter</c></fsummary>
- <type>
- <v>ConsumerAdmin = MappingFilter = #objref</v>
- </type>
- <desc>
- <p>This operation associate a lifetime <c>MappingFilter</c> with the target object.</p>
- </desc>
- </func>
- <func>
- <name>_get_pull_suppliers(ConsumerAdmin) -> ProxyIDSeq</name>
- <fsummary>Return a list of all associated pull supplier Id:s</fsummary>
- <type>
- <v>ConsumerAdmin = #objref</v>
- <v>ProxyIDSeq = [ProxyID]</v>
- <v>ProxyID = long()</v>
- </type>
- <desc>
- <p>This readonly attribute maintains the Id's for all <c>PullProxies</c> created
- by the target object and still alive.</p>
- </desc>
- </func>
- <func>
- <name>_get_push_suppliers(ConsumerAdmin) -> ProxyIDSeq</name>
- <fsummary>Return a list of all associated push supplier Id:s</fsummary>
- <type>
- <v>ConsumerAdmin = #objref</v>
- <v>ProxyIDSeq = [ProxyID]</v>
- <v>ProxyID = long()</v>
- </type>
- <desc>
- <p>This attribute is similar to the <c>_get_pull_suppliers</c> attribute but maintains
- the Id's for all <c>PushProxies</c> created by the target object and still alive.</p>
- </desc>
- </func>
- <func>
- <name>get_proxy_supplier(ConsumerAdmin, ProxyID) -> Reply</name>
- <fsummary>Return the proxy supplier with matching Id</fsummary>
- <type>
- <v>ConsumerAdmin = #objref</v>
- <v>ProxyID = long()</v>
- <v>Reply = Proxy | {'EXCEPTION', #'CosNotifyChannelAdmin_ProxyNotFound'{}}</v>
- <v>Proxy = #objref</v>
- </type>
- <desc>
- <p>If a proxy with the given Id exists the reference to the object is returned, but if
- the object have terminated, or an incorrect Id is supplied, an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>obtain_notification_pull_supplier(ConsumerAdmin, ConsumerType) -> Reply</name>
- <fsummary>Create a supplier proxy</fsummary>
- <type>
- <v>ConsumerAdmin = #objref</v>
- <v>ConsumerType = 'ANY_EVENT' | 'STRUCTURED_EVENT' | 'SEQUENCE_EVENT'</v>
- <v>Reply = {Proxy, ProxyID}</v>
- <v>Proxy = #objref</v>
- <v>ProxyID = long()</v>
- </type>
- <desc>
- <p>Determined by the parameter <c>ConsumerType</c>, a proxy which will
- accept events of the defined type is created. Along with the object reference an
- Id is returned. </p>
- </desc>
- </func>
- <func>
- <name>obtain_pull_supplier(ConsumerAdmin) -> Proxy</name>
- <fsummary>Create a supplier proxy</fsummary>
- <type>
- <v>ConsumerAdmin = #objref</v>
- <v>Proxy = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new proxy which accepts <c>#any{}</c> events.</p>
- </desc>
- </func>
- <func>
- <name>obtain_notification_push_supplier(ConsumerAdmin, ConsumerType) -> Reply</name>
- <fsummary>Create a supplier proxy</fsummary>
- <type>
- <v>ConsumerAdmin = #objref</v>
- <v>ConsumerType = 'ANY_EVENT' | 'STRUCTURED_EVENT' | 'SEQUENCE_EVENT'</v>
- <v>Reply = {Proxy, ProxyID}</v>
- <v>Proxy = #objref</v>
- <v>ProxyID = long()</v>
- </type>
- <desc>
- <p>A proxy which accepts events of the type described by the parameter <c>ConsumerType</c>
- is created by this operation. A unique Id is returned as an out parameter.</p>
- </desc>
- </func>
- <func>
- <name>obtain_push_supplier(ConsumerAdmin) -> Proxy</name>
- <fsummary>Create a supplier proxy</fsummary>
- <type>
- <v>ConsumerAdmin = #objref</v>
- <v>Proxy = #objref</v>
- </type>
- <desc>
- <p>The object created by this function is a proxy which accepts <c>#any{}</c> events.</p>
- </desc>
- </func>
- <func>
- <name>destroy(ConsumerAdmin) -> ok</name>
- <fsummary>Terminate the target object and all its children</fsummary>
- <type>
- <v>ConsumerAdmin = #objref</v>
- </type>
- <desc>
- <p>To terminate the target object this operation should be used. The associated
- <c>Channel</c> will be notified.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_EventChannel.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_EventChannel.xml
deleted file mode 100644
index 7696e6a26c..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_EventChannel.xml
+++ /dev/null
@@ -1,226 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosNotifyChannelAdmin_EventChannel</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyChannelAdmin_EventChannel</module>
- <modulesummary>This module implements the OMG CosNotifyChannelAdmin::EventChannel interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosNotification_QoSAdmin">CosNotification_QoSAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotification_AdminPropertiesAdmin">CosNotification_AdminPropertiesAdmin</seealso></p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>_get_MyFactory(Channel) -> ChannelFactory</name>
- <fsummary>Return the factory object which created the target object</fsummary>
- <type>
- <v>Channel = #objref</v>
- <v>ChannelFactory = #objref</v>
- </type>
- <desc>
- <p>This readonly attribute maintains the reference of the event channel
- factory that created the target channel.</p>
- </desc>
- </func>
- <func>
- <name>_get_default_consumer_admin(Channel) -> ConsumerAdmin</name>
- <fsummary>Return the default consumer admin associated with the target object</fsummary>
- <type>
- <v>Channel = #objref</v>
- <v>ConsumerAdmin = #objref</v>
- </type>
- <desc>
- <p>This is a readonly attribute which maintains a reference to a default
- <c>ConsumerAdmin</c> object associated with the target object.</p>
- </desc>
- </func>
- <func>
- <name>_get_default_supplier_admin(Channel) -> SupplierAdmin</name>
- <fsummary>Return the default supplier admin associated with the target object</fsummary>
- <type>
- <v>Channel = #objref</v>
- <v>SupplierAdmin = #objref</v>
- </type>
- <desc>
- <p>This is a readonly attribute which maintains a reference to a default
- <c>SupplierAdmin</c> object associated with the target object.</p>
- </desc>
- </func>
- <func>
- <name>_get_default_filter_factory(Channel) -> FilterFactory</name>
- <fsummary>Return the default filter factory associated with the target object</fsummary>
- <type>
- <v>Channel = #objref</v>
- <v>FilterFactory = #objref</v>
- </type>
- <desc>
- <p>The default <c>FilterFactory</c> associated with the target channel
- is maintained by this readonly attribute.</p>
- </desc>
- </func>
- <func>
- <name>new_for_consumers(Channel, OpType) -> Return</name>
- <fsummary>Create a new <c>ConsumerAdmin</c>object</fsummary>
- <type>
- <v>Channel = #objref</v>
- <v>OpType = 'AND_OP' | 'OR_OP'</v>
- <v>Return = {ConsumerAdmin, AdminID}</v>
- <v>ConsumerAdmin = #objref</v>
- <v>AdminID = long()</v>
- </type>
- <desc>
- <p>This operation creates a new instance of a <c>ConsumerAdmin</c> and supplies
- an Id which may be used when invoking other operations exported by this module.
- The returned object will inherit the Quality of Service properties of the
- target channel.</p>
- </desc>
- </func>
- <func>
- <name>for_consumers(Channel) -> ConsumerAdmin</name>
- <fsummary>Create a new <c>ConsumerAdmin</c>object</fsummary>
- <type>
- <v>Channel = #objref</v>
- <v>ConsumerAdmin = #objref</v>
- </type>
- <desc>
- <p>A new new instance of a <c>ConsumerAdmin</c> object is created but no
- Id is returned. The returned object's operation type, i.e., <c>'AND_OP'</c> or <c>'OR_OP'</c>,
- will be set to the value of the configuration parameter <c>filterOp</c>.
- The target object's Quality of Service properties will be inherited by the
- returned <c>ConsumerAdmin</c>.</p>
- </desc>
- </func>
- <func>
- <name>new_for_suppliers(Channel, OpType) -> Return</name>
- <fsummary>Create a new <c>SupplierAdmin</c>object</fsummary>
- <type>
- <v>Channel = #objref</v>
- <v>OpType = 'AND_OP' | 'OR_OP'</v>
- <v>Return = {SupplierAdmin, AdminID}</v>
- <v>SupplierAdmin = #objref</v>
- <v>AdminID = long()</v>
- </type>
- <desc>
- <p>Enables us to create a new instance of a <c>SupplierAdmin</c>. An Id, which
- may be used when invoking other operations exported by this module, is also
- returned. The current Quality of Service settings associated with the target
- object will be inherited by the <c>SupplierAdmin</c>.</p>
- </desc>
- </func>
- <func>
- <name>for_suppliers(Channel) -> SupplierAdmin</name>
- <fsummary>Create a new <c>SupplierAdmin</c>object</fsummary>
- <type>
- <v>Channel = #objref</v>
- <v>SupplierAdmin = #objref</v>
- </type>
- <desc>
- <p>To create a new <c>SupplierAdmin</c> with the target object's current
- Quality of Service settings we can use this function. The returned object's
- operation type (<c>'AND_OP'</c> or <c>'OR_OP'</c>) will be determined by the
- configuration variable <c>filterOp</c>.</p>
- </desc>
- </func>
- <func>
- <name>get_consumeradmin(Channel, AdminID) -> ConsumerAdmin</name>
- <fsummary>Return the <c>ConsumerAdmin</c>matching AdminID</fsummary>
- <type>
- <v>Channel = #objref</v>
- <v>AdminID = long()</v>
- <v>ConsumerAdmin = #objref | {'EXCEPTION', #'CosNotifyChannelAdmin_AdminNotFound'{}}</v>
- </type>
- <desc>
- <p>If the given Id is associated with a <c>ConsumerAdmin</c> the object reference
- is returned. If such association never existed or the <c>ConsumerAdmin</c>
- have terminated an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>get_supplieradmin(Channel, AdminID) -> SupplierAdmin</name>
- <fsummary>Return the <c>SupplierAdmin</c>matching AdminID</fsummary>
- <type>
- <v>Channel = #objref</v>
- <v>AdminID = long()</v>
- <v>SupplierAdmin = #objref | {'EXCEPTION', #'CosNotifyChannelAdmin_AdminNotFound'{}}</v>
- </type>
- <desc>
- <p>Equal to the operation <c>get_consumeradmin/2</c> but a reference to
- a <c>SupplierAdmin</c> is returned.</p>
- </desc>
- </func>
- <func>
- <name>get_all_consumeradmins(Channel) -> Reply</name>
- <fsummary>Return a list of all <c>ConsumerAdmins</c>, currently active, Id:s</fsummary>
- <type>
- <v>Channel = #objref</v>
- <v>Reply = [AdminID]</v>
- <v>AdminID = long()</v>
- </type>
- <desc>
- <p>To get access to all <c>ConsumerAdmin</c> Id's created by the target object, and still
- alive, this operation could be invoked.</p>
- </desc>
- </func>
- <func>
- <name>get_all_supplieradmins(Channel) -> Reply</name>
- <fsummary>Return a list of all <c>SupplierAdmins</c>, currently active, Id:s</fsummary>
- <type>
- <v>Channel = #objref</v>
- <v>Reply = [AdminID]</v>
- <v>AdminID = long()</v>
- </type>
- <desc>
- <p>Equal to the operation <c>get_all_consumeradmins/1</c> but returns
- a list of all <c>SupplierAdmin</c> object ID's.</p>
- </desc>
- </func>
- <func>
- <name>destroy(Channel) -> ok</name>
- <fsummary>Terminate the channel and all its children</fsummary>
- <type>
- <v>Channel = #objref</v>
- </type>
- <desc>
- <p>The <c>destroy</c> operation will terminate the target channel and
- all associated Admin objects.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_EventChannelFactory.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_EventChannelFactory.xml
deleted file mode 100644
index 552ea182c0..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_EventChannelFactory.xml
+++ /dev/null
@@ -1,89 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosNotifyChannelAdmin_EventChannelFactory</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyChannelAdmin_EventChannelFactory</module>
- <modulesummary>This module implements the OMG CosNotifyChannelAdmin::EventChannelFactory interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>create_channel(ChannelFactory, InitialQoS, InitialAdmin) -> Return</name>
- <fsummary>Create a new channel</fsummary>
- <type>
- <v>ChannelFactory = #objref</v>
- <v>InitialQoS = CosNotification::QoSProperties</v>
- <v>InitialAdmin = CosNotification::AdminProperties</v>
- <v>Return = {EventChannel, ChannelID}</v>
- <v>EventChannel = #objref</v>
- <v>ChannelID = long()</v>
- </type>
- <desc>
- <p>This operation creates a new event channel. Along with the channel
- reference an id is returned which can be used when invoking other
- operations exported by this module. The Quality of Service argument
- supplied will be inherited by objects created by the channel. For more
- information about QoS settings see the <c>User's Guide</c>.</p>
- <p>If no QoS- and/or Admin-properties are supplied (i.e. empty list),
- the <em>default</em> settings will be used. For more information, see the
- User's Guide.</p>
- </desc>
- </func>
- <func>
- <name>get_all_channels(ChannelFactory) -> ChannelIDSeq</name>
- <fsummary>Return all Id:s for channels, currently alive, created by the target object</fsummary>
- <type>
- <v>ChannelFactory = #objref</v>
- <v>ChannelIDSeq = [long()]</v>
- </type>
- <desc>
- <p>This operation returns a id sequence of all channel's created by this ChannelFactory.</p>
- </desc>
- </func>
- <func>
- <name>get_event_channel(ChannelFactory, ChannelID) -> Return</name>
- <fsummary>Return the channel object associated with the given Id</fsummary>
- <type>
- <v>ChannelFactory = #objref</v>
- <v>ChannelID = long()</v>
- <v>Retrurn = EventChannel | {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}</v>
- <v>EventChannel = #objref</v>
- </type>
- <desc>
- <p>This operation returns the EventChannel associated with the given id. If no channel is
- associated with the id, i.e., never existed or have been terminated, an exception is raised.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyConsumer.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyConsumer.xml
deleted file mode 100644
index 3d61893162..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyConsumer.xml
+++ /dev/null
@@ -1,128 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyChannelAdmin_ProxyConsumer</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyChannelAdmin_ProxyConsumer</module>
- <modulesummary>This module implements the OMG CosNotifyChannelAdmin::ProxyConsumer interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosNotification_QoSAdmin">CosNotification_QoSAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyFilter_FilterAdmin">CosNotifyFilter_FilterAdmin</seealso></p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>_get_MyType(ProxyConsumer) -> ProxyType</name>
- <fsummary>Return the proxy type</fsummary>
- <type>
- <v>ProxyConsumer = #objref</v>
- <v>ProxyType = 'PUSH_ANY' | 'PULL_ANY' | 'PUSH_STRUCTURED' | 'PULL_STRUCTURED' | 'PUSH_SEQUENCE' | 'PULL_SEQUENCE'</v>
- </type>
- <desc>
- <p>This readonly attribute maintains the enumerant describing the which type the target object
- is. </p>
- </desc>
- </func>
- <func>
- <name>_get_MyAdmin(ProxyConsumer) -> AdminObject</name>
- <fsummary>return the associated <c>Admin</c>object</fsummary>
- <type>
- <v>ProxyConsumer = AdminObject = #objref</v>
- </type>
- <desc>
- <p>This readonly attribute maintains the admin's reference which created the target object.</p>
- </desc>
- </func>
- <func>
- <name>obtain_subscription_types(ProxyConsumer, ObtainInfoMode) -> EventTypeSeq</name>
- <fsummary>Administer subscription types</fsummary>
- <type>
- <v>ProxyConsumer = #objref</v>
- <v>ObtainInfoMode = 'ALL_NOW_UPDATES_OFF' | 'ALL_NOW_UPDATES_ON' | 'NONE_NOW_UPDATES_OFF' | 'NONE_NOW_UPDATES_ON'</v>
- <v>EventTypeSeq = [EventType]</v>
- <v>EventType = #'CosNotification_EventType'{domain_name, type_name}</v>
- <v>domain_name = type_name = string()</v>
- </type>
- <desc>
- <p>Depending on the input parameter <c>ObtainInfoMode</c>, this operation may return a
- sequence of the <c>EventTypes</c> the target object is interested in receiving.
- If <c>'ALL_NOW_UPDATES_OFF'</c> or <c>'ALL_NOW_UPDATES_ON'</c> is given a sequence will
- be returned, otherwise not. If <c>'ALL_NOW_UPDATES_OFF'</c> or <c>'NONE_NOW_UPDATES_OFF'</c>
- are issued the target object will not inform the associated <c>NotifySubscribe</c> object
- when an update occurs. <c>'ALL_NOW_UPDATES_ON'</c> or <c>'NONE_NOW_UPDATES_ON'</c> will
- result in that update information will be sent.</p>
- </desc>
- </func>
- <func>
- <name>validate_event_qos(ProxyConsumer, QoSProperties) -> Reply</name>
- <fsummary>Check if certain Quality of Service properties can be added to events in the current context of the target object</fsummary>
- <type>
- <v>ProxyConsumer = #objref</v>
- <v>QoSProperties = [QoSProperty]</v>
- <v>QoSProperty = #'CosNotification_Property'{name, value}</v>
- <v>name = string()</v>
- <v>value = #any</v>
- <v>Reply = {ok, NamedPropertyRangeSeq} | {'EXCEPTION', CosNotification_UnsupportedQoS{qos_err}}</v>
- <v>NamedPropertyRangeSeq = [NamedPropertyRange]</v>
- <v>NamedPropertyRange = #CosNotification_NamedPropertyRange{name, range}</v>
- <v>name = string()</v>
- <v>range = #CosNotification_PropertyRange{low_val, high_val}</v>
- <v>low_val = #any</v>
- <v>high_val = #any</v>
- <v>qos_err = PropertyErrorSeq</v>
- <v>PropertyErrorSeq = [PropertyError]</v>
- <v>PropertyError = #'CosNotification_PropertyError'{code, name, available_range}</v>
- <v>code = 'UNSUPPORTED_PROPERTY' | 'UNAVAILABLE_PROPERTY' | 'UNSUPPORTED_VALUE' | 'UNAVAILABLE_VALUE' | 'BAD_PROPERTY' | 'BAD_TYPE' | 'BAD_VALUE'</v>
- <v>name = string()</v>
- <v>available_range = PropertyRange</v>
- <v>PropertyRange = #CosNotification_PropertyRange{low_val, high_val}</v>
- <v>low_val = high_val = #any</v>
- </type>
- <desc>
- <p>To check if certain Quality of Service properties can be added to events in
- the current context of the target object this operation should be used. If we
- cannot support the required settings an exception describing why will be raised.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPullConsumer.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPullConsumer.xml
deleted file mode 100644
index caf572dee8..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPullConsumer.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyChannelAdmin_ProxyPullConsumer</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyChannelAdmin_ProxyPullConsumer</module>
- <modulesummary>This module implements the OMG CosNotifyChannelAdmin::ProxyPullConsumer interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosNotifyComm_NotifyPublish">CosNotifyComm_NotifyPublish</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotification_QoSAdmin">CosNotification_QoSAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyFilter_FilterAdmin">CosNotifyFilter_FilterAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyChannelAdmin_ProxyConsumer">CosNotifyChannelAdmin_ProxyConsumer</seealso></p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>connect_any_pull_supplier(ProxyPullConsumer, PullSupplier) -> Reply</name>
- <fsummary>Connect a supplier to the proxy</fsummary>
- <type>
- <v>ProxyPullConsumer = #objref</v>
- <v>PullSupplier = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosEventChannelAdmin_AlreadyConnected'{}} | {'EXCEPTION', #'CosEventChannelAdmin_TypeError'{}}</v>
- </type>
- <desc>
- <p>This operation connects the given <c>PullSupplier</c> to the target object.
- If a client is already connected the <c>AlreadyConnected</c> exception
- will be raised. The client must support the operations <c>pull</c> and
- <c>try_pull</c>, otherwise the <c>TypeError</c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>suspend_connection(ProxyPullConsumer) -> Reply</name>
- <fsummary>Suspend the connection between the client and the proxy</fsummary>
- <type>
- <v>ProxyPullConsumer = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosNotifyChannelAdmin_ConnectionAlreadyInactive'{}} | {'EXCEPTION', #'CosNotifyChannelAdmin_NotConnected'{}}</v>
- </type>
- <desc>
- <p>If we want to temporarily suspend the connection with the target object this
- operation must be sued. If the connection already have been suspended or
- no client have been connected an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>resume_connection(ProxyPullConsumer) -> Reply</name>
- <fsummary>Resume a previously suspended connection with the proxy</fsummary>
- <type>
- <v>ProxyPullConsumer = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosNotifyChannelAdmin_ConnectionAlreadyActive'{}} | {'EXCEPTION', #'CosNotifyChannelAdmin_NotConnected'{}}</v>
- </type>
- <desc>
- <p>If The connection have been suspended earlier we can invoke this operation to
- reinstate the connection. If the connection already is active or no client
- have been connected to the target object an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>disconnect_pull_consumer(ProxyPullConsumer) -> ok</name>
- <fsummary>Close the connection and terminate the proxy</fsummary>
- <type>
- <v>ProxyPullConsumer = #objref</v>
- </type>
- <desc>
- <p>Invoking this operation disconnects the client from the target object which
- then terminates and inform its administrative parent.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPullSupplier.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPullSupplier.xml
deleted file mode 100644
index 42aaaec319..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPullSupplier.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyChannelAdmin_ProxyPullSupplier</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyChannelAdmin_ProxyPullSupplier</module>
- <modulesummary>This module implements the OMG CosNotifyChannelAdmin::ProxyPullSupplier interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosNotifyComm_NotifySubscribe">CosNotifyComm_NotifySubscribe</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotification_QoSAdmin">CosNotification_QoSAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyFilter_FilterAdmin">CosNotifyFilter_FilterAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyChannelAdmin_ProxySupplier">CosNotifyChannelAdmin_ProxySupplier</seealso></p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>connect_any_pull_consumer(ProxyPullSupplier, PullConsumer) -> Reply</name>
- <fsummary>Connect a consumer to the proxy</fsummary>
- <type>
- <v>ProxyPullSupplier = #objref</v>
- <v>PullConsumer = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosEventChannelAdmin_AlreadyConnected'{}}</v>
- </type>
- <desc>
- <p>This operation connects the given <c>PullConsumer</c> to the target object.
- If a connection already exists the <c>AlreadyConnected</c> exception is
- raised.</p>
- </desc>
- </func>
- <func>
- <name>pull(ProxyPullSupplier) -> Reply</name>
- <fsummary>Pull an Any event from the proxy</fsummary>
- <type>
- <v>ProxyPullSupplier = #objref</v>
- <v>Reply = #any | {'EXCEPTION', #'CosEventChannelAdmin_Disconnected'{}}</v>
- </type>
- <desc>
- <p>This operation pulls next <c>#any{}</c> event, and blocks, if the target object
- have no events to forward, until an event can be delivered. If no client have
- been connected the <c>Disconnected</c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>try_pull(ProxyPullSupplier) -> Reply</name>
- <fsummary>Try and pull an Any event from the proxy</fsummary>
- <type>
- <v>ProxyPullSupplier = #objref</v>
- <v>Reply = {#any, HasEvent} | {'EXCEPTION', #'CosEventChannelAdmin_Disconnected'{}}</v>
- <v>HasEvent = boolean()</v>
- </type>
- <desc>
- <p>This operation pulls next event, but do not block if the target object
- have no event to forward. If no client have
- been connected the <c>Disconnected</c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>disconnect_pull_supplier(ProxyPullSupplier) -> ok</name>
- <fsummary>Close the connection and terminate the proxy</fsummary>
- <type>
- <v>ProxyPullSupplier = #objref</v>
- </type>
- <desc>
- <p>Invoking this operation will cause the target object to close the connection and terminate.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPushConsumer.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPushConsumer.xml
deleted file mode 100644
index 9808b460c7..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPushConsumer.xml
+++ /dev/null
@@ -1,98 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyChannelAdmin_ProxyPushConsumer</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyChannelAdmin_ProxyPushConsumer</module>
- <modulesummary>This module implements the OMG CosNotifyChannelAdmin::ProxyPushConsumer interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosNotifyComm_NotifyPublish">CosNotifyComm_NotifyPublish</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotification_QoSAdmin">CosNotification_QoSAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyFilter_FilterAdmin">CosNotifyFilter_FilterAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyChannelAdmin_ProxyConsumer">CosNotifyChannelAdmin_ProxyConsumer</seealso></p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>connect_any_push_supplier(ProxyPushConsumer, PushSupplier) -> Reply</name>
- <fsummary>Connect a supplier to the proxy</fsummary>
- <type>
- <v>ProxyPushConsumer = #objref</v>
- <v>PushSupplier = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosEventChannelAdmin_AlreadyConnected'{}}</v>
- </type>
- <desc>
- <p>This operation connects a <c>PushSupplier</c> to the target object. If
- a connection already exists the <c>AlreadyConnected</c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>push(ProxyPushConsumer, Event) -> Reply</name>
- <fsummary>Push an Any event to the proxy</fsummary>
- <type>
- <v>ProxyPushConsumer = #objref</v>
- <v>Event = #any</v>
- <v>Reply = ok | {'EXCEPTION', #'CosEventChannelAdmin_Disconnected'{}}</v>
- </type>
- <desc>
- <p>This operation pushes an <c>#any{}</c> event to the target object. If no client
- have been connected the <c>Disconnected</c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>disconnect_push_consumer(ProxyPushConsumer) -> ok</name>
- <fsummary>Close the connection and terminate the proxy</fsummary>
- <type>
- <v>ProxyPushConsumer = #objref</v>
- </type>
- <desc>
- <p>Invoking this operation will cause the target object to close the connection and
- terminate.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPushSupplier.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPushSupplier.xml
deleted file mode 100644
index 6f85de114a..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxyPushSupplier.xml
+++ /dev/null
@@ -1,110 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyChannelAdmin_ProxyPushSupplier</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyChannelAdmin_ProxyPushSupplier</module>
- <modulesummary>This module implements the OMG CosNotifyChannelAdmin::ProxyPushSupplier interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosNotifyComm_NotifySubscribe">CosNotifyComm_NotifySubscribe</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotification_QoSAdmin">CosNotification_QoSAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyFilter_FilterAdmin">CosNotifyFilter_FilterAdmi</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyChannelAdmin_ProxySupplier">CosNotifyChannelAdmin_ProxySupplier</seealso></p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>connect_any_push_consumer(ProxyPushSupplier, PushConsumer) -> Reply</name>
- <fsummary>Connect a consumer to the proxy</fsummary>
- <type>
- <v>ProxyPushSupplier = #objref</v>
- <v>PushConsumer = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosEventChannelAdmin_AlreadyConnected'{}} | {'EXCEPTION', #'CosEventChannelAdmin_TypeError'{}}</v>
- </type>
- <desc>
- <p>This operation connects a <c>PushConsumer</c> to the target object. If
- a connection already exists or the given client does not support
- the operation <c>push</c> an exception, <c>AlreadyConnected</c> and
- <c>TypeError</c> respectively, is raised.</p>
- </desc>
- </func>
- <func>
- <name>suspend_connection(ProxyPushSupplier) -> Reply</name>
- <fsummary>Suspend the connection between the proxy and the client</fsummary>
- <type>
- <v>ProxyPushSupplier = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosNotifyChannelAdmin_ConnectionAlreadyInactive'{}} | {'EXCEPTION', #'CosNotifyChannelAdmin_NotConnected'{}}</v>
- </type>
- <desc>
- <p>This operation suspends the connection with the client object. If the connection
- already is suspended or no client have been associated an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>resume_connection(ProxyPushSupplier) -> Reply</name>
- <fsummary>Resume a previously suspended connection with the proxy</fsummary>
- <type>
- <v>ProxyPullConsumer = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosNotifyChannelAdmin_ConnectionAlreadyInactive'{}} | {'EXCEPTION', #'CosNotifyChannelAdmin_NotConnected'{}}</v>
- </type>
- <desc>
- <p>If a connection have been suspended earlier, calling this operation will resume the connection.
- If the connection already is active or no client have been connected an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>disconnect_push_supplier(ProxyPushSupplier) -> ok</name>
- <fsummary>Close the connection and terminate the proxy</fsummary>
- <type>
- <v>ProxyPushSupplier = #objref</v>
- </type>
- <desc>
- <p>This operation cause the target object to close the connection and terminate.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxySupplier.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxySupplier.xml
deleted file mode 100644
index 69013fdb1e..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_ProxySupplier.xml
+++ /dev/null
@@ -1,175 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyChannelAdmin_ProxySupplier</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyChannelAdmin_ProxySupplier</module>
- <modulesummary>This module implements the OMG CosNotifyChannelAdmin::ProxySupplier interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosNotification_QoSAdmin">CosNotification_QoSAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyFilter_FilterAdmin">CosNotifyFilter_FilterAdmin</seealso></p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>_get_MyType(ProxySupplier) -> ProxyType</name>
- <fsummary>Return the proxy type</fsummary>
- <type>
- <v>ProxySupplier = #objref</v>
- <v>ProxyType = 'PUSH_ANY' | 'PULL_ANY' | 'PUSH_STRUCTURED' | 'PULL_STRUCTURED' | 'PUSH_SEQUENCE' | 'PULL_SEQUENCE'</v>
- </type>
- <desc>
- <p>This readonly attribute maintains the enumerant describing the which type the target object
- is.</p>
- </desc>
- </func>
- <func>
- <name>_get_MyAdmin(ProxySupplier) -> AdminObject</name>
- <fsummary>Return the target object's associated <c>Admin</c>object</fsummary>
- <type>
- <v>ProxySupplier = #objref</v>
- <v>AdminObject = #objref</v>
- </type>
- <desc>
- <p>This readonly attribute maintains the admin's reference which created the target object.</p>
- </desc>
- </func>
- <func>
- <name>_get_priority_filter(ProxySupplier) -> MappingFilter</name>
- <fsummary>Return the target object's associated priority <c>MappingFilter</c></fsummary>
- <type>
- <v>ProxySupplier = #objref</v>
- <v>MappingFilter = #objref</v>
- </type>
- <desc>
- <p>This operation returns the associated priority MappingFilter.
- If no such object exist a <c>NIL</c> reference is returned.</p>
- </desc>
- </func>
- <func>
- <name>_set_priority_filter(ProxySupplier, MappingFilter) -> ok</name>
- <fsummary>Set the target object's associated priority <c>MappingFilter</c></fsummary>
- <type>
- <v>ProxySupplier = #objref</v>
- <v>MappingFilter = #objref</v>
- </type>
- <desc>
- <p>This operation associate a new priority MappingFilter with the target object.</p>
- </desc>
- </func>
- <func>
- <name>_get_lifetime_filter(ProxySupplier) -> MappingFilter</name>
- <fsummary>Return the target object's associated lifetime <c>MappingFilter</c></fsummary>
- <type>
- <v>ProxySupplier = #objref</v>
- <v>MappingFilter = #objref</v>
- </type>
- <desc>
- <p>This operation returns the associated lifetime MappingFilter.
- If no such object exist a <c>NIL</c> reference is returned.</p>
- </desc>
- </func>
- <func>
- <name>_set_lifetime_filter(ProxySupplier, MappingFilter) -> ok</name>
- <fsummary>Set the target object's associated lifetime <c>MappingFilter</c></fsummary>
- <type>
- <v>ProxySupplier = #objref</v>
- <v>MappingFilter = #objref</v>
- </type>
- <desc>
- <p>This operation associate a new lifetime MappingFilter with the target object.</p>
- </desc>
- </func>
- <func>
- <name>obtain_offered_types(ProxySupplier, ObtainInfoMode) -> EventTypeSeq</name>
- <fsummary>Administer the type of events the proxy supplies</fsummary>
- <type>
- <v>ProxySupplier = #objref</v>
- <v>ObtainInfoMode = 'ALL_NOW_UPDATES_OFF' | 'ALL_NOW_UPDATES_ON' | 'NONE_NOW_UPDATES_OFF' | 'NONE_NOW_UPDATES_ON'</v>
- <v>EventTypeSeq = [EventType]</v>
- <v>EventType = #'CosNotification_EventType'{domain_name, type_name}</v>
- <v>domain_name = type_name = string()</v>
- </type>
- <desc>
- <p>Depending on the input parameter <c>ObtainInfoMode</c>, this operation may return a
- sequence of the <c>EventTypes</c> the target object is interested in receiving.
- If <c>'ALL_NOW_UPDATES_OFF'</c> or <c>'ALL_NOW_UPDATES_ON'</c> is given a sequence will
- be returned, otherwise not. If <c>'ALL_NOW_UPDATES_OFF'</c> or <c>'NONE_NOW_UPDATES_OFF'</c>
- are issued the target object will not inform the associated <c>NotifySubscribe</c> object
- when an update occurs. <c>'ALL_NOW_UPDATES_ON'</c> or <c>'NONE_NOW_UPDATES_ON'</c> will
- result in that update information will be sent.</p>
- </desc>
- </func>
- <func>
- <name>validate_event_qos(ProxySupplier, QoSProperties) -> Reply</name>
- <fsummary>Check if the QoS properties can be set</fsummary>
- <type>
- <v>ProxySupplier = #objref</v>
- <v>QoSProperties = [QoSProperty]</v>
- <v>QoSProperty = #'CosNotification_Property'{name, value}</v>
- <v>name = string()</v>
- <v>value = #any</v>
- <v>Reply = {ok, NamedPropertyRangeSeq} | {'EXCEPTION', CosNotification_UnsupportedQoS{qos_err}}</v>
- <v>NamedPropertyRangeSeq = [NamedPropertyRange]</v>
- <v>NamedPropertyRange = #CosNotification_NamedPropertyRange{name, range}</v>
- <v>name = string()</v>
- <v>range = #CosNotification_PropertyRange{low_val, high_val}</v>
- <v>low_val = #any</v>
- <v>high_val = #any</v>
- <v>qos_err = PropertyErrorSeq</v>
- <v>PropertyErrorSeq = [PropertyError]</v>
- <v>PropertyError = #'CosNotification_PropertyError'{code, name, available_range}</v>
- <v>code = 'UNSUPPORTED_PROPERTY' | 'UNAVAILABLE_PROPERTY' | 'UNSUPPORTED_VALUE' | 'UNAVAILABLE_VALUE' | 'BAD_PROPERTY' | 'BAD_TYPE' | 'BAD_VALUE'</v>
- <v>name = string()</v>
- <v>available_range = PropertyRange</v>
- <v>PropertyRange = #CosNotification_PropertyRange{low_val, high_val}</v>
- <v>low_val = high_val = #any</v>
- </type>
- <desc>
- <p>To check if certain Quality of Service properties can be added to events in
- the current context of the target object this operation should be used. If we
- cannot support the required settings an exception describing why will be raised.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPullConsumer.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPullConsumer.xml
deleted file mode 100644
index 043472df55..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPullConsumer.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyChannelAdmin_SequenceProxyPullConsumer</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyChannelAdmin_SequenceProxyPullConsumer</module>
- <modulesummary>This module implements the OMG CosNotifyChannelAdmin::SequenceProxyPullConsumer interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosNotifyComm_NotifyPublish">CosNotifyComm_NotifyPublish</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotification_QoSAdmin">CosNotification_QoSAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyFilter_FilterAdmin">CosNotifyFilter_FilterAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyChannelAdmin_ProxyConsumer">CosNotifyChannelAdmin_ProxyConsumer</seealso></p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>connect_sequence_pull_supplier(SequenceProxyPullConsumer, PullSupplier) -> Reply</name>
- <fsummary>Connect a supplier to the proxy</fsummary>
- <type>
- <v>SequenceProxyPullConsumer = #objref</v>
- <v>PullSupplier = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosEventChannelAdmin_AlreadyConnected'{}} | {'EXCEPTION', #'CosEventChannelAdmin_TypeError'{}}</v>
- </type>
- <desc>
- <p>This operation connects a <c>PullSupplier</c> to the target object. If a
- connection already exists or the supplied client does not support the functions
- <c>pull_structured_events</c> and <c>try_pull_structured_events</c> an exception
- is raised.</p>
- </desc>
- </func>
- <func>
- <name>suspend_connection(SequenceProxyPullConsumer) -> Reply</name>
- <fsummary>Suspend the connection with the proxy</fsummary>
- <type>
- <v>SequenceProxyPullConsumer = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosNotifyChannelAdmin_ConnectionAlreadyInactive'{}} | {'EXCEPTION', #'CosNotifyChannelAdmin_NotConnected'{}}</v>
- </type>
- <desc>
- <p>If a connection exist, invoking this operation will suspend the connection
- until instructed otherwise. Otherwise, no client have been connected or this operation
- already have been invoked an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>resume_connection(SequenceProxyPullConsumer) -> Reply</name>
- <fsummary>Resume a previously suspended connection with the proxy</fsummary>
- <type>
- <v>SequenceProxyPullConsumer = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosNotifyChannelAdmin_ConnectionAlreadyInactive'{}} | {'EXCEPTION', #'CosNotifyChannelAdmin_NotConnected'{}}</v>
- </type>
- <desc>
- <p>If an connection have been suspended this operation must be used to resume the
- connection. If the connection already is active or no client have been connected an
- exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>disconnect_sequence_pull_consumer(SequenceProxyPullConsumer) -> ok</name>
- <fsummary>Close connection and terminate the proxy</fsummary>
- <type>
- <v>SequenceProxyPullConsumer = #objref</v>
- </type>
- <desc>
- <p>This operation close the connection to the client and terminates the target object.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPullSupplier.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPullSupplier.xml
deleted file mode 100644
index a0040a50d7..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPullSupplier.xml
+++ /dev/null
@@ -1,146 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyChannelAdmin_SequenceProxyPullSupplier</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyChannelAdmin_SequenceProxyPullSupplier</module>
- <modulesummary>This module implements the OMG CosNotifyChannelAdmin::SequenceProxyPullSupplier interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosNotifyComm_NotifySubscribe">CosNotifyComm_NotifySubscribe</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotification_QoSAdmin">CosNotification_QoSAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyFilter_FilterAdmin">CosNotifyFilter_FilterAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyChannelAdmin_ProxySupplier">CosNotifyChannelAdmin_ProxySupplier</seealso></p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>connect_sequence_pull_consumer(SequenceProxyPullSupplier, PullConsumer) -> Reply</name>
- <fsummary>Connect a consumer to the proxy</fsummary>
- <type>
- <v>SequenceProxyPullSupplier = #objref</v>
- <v>PullConsumer = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosEventChannelAdmin_AlreadyConnected'{}}</v>
- </type>
- <desc>
- <p>This operation connects a <c>PullConsumer</c> to the target object. If a connection
- already exists an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>pull_structured_events(SequenceProxyPullSupplier, MaxEvents) -> Reply</name>
- <fsummary>Pull structured events from the proxy</fsummary>
- <type>
- <v>SequenceProxyPullSupplier = #objref</v>
- <v>MaxEvents = long()</v>
- <v>Reply = EventBatch | {'EXCEPTION', #'CosEventChannelAdmin_Disconnected'{}}</v>
- <v>EventBatch = [StructuredEvent]</v>
- <v>StructuredEvent = #'CosNotification_StructuredEvent'{header, filterable_data, remainder_of_body}</v>
- <v>header = EventHeader</v>
- <v>filterable_data = [#'CosNotification_Property'{name, value}]</v>
- <v>name = string()</v>
- <v>value = #any</v>
- <v>remainder_of_body = #any</v>
- <v>EventHeader = #'CosNotification_EventHeader'{fixed_header, variable_header}</v>
- <v>fixed_header = FixedEventHeader</v>
- <v>variable_header = OptionalHeaderFields</v>
- <v>FixedEventHeader = #'CosNotification_FixedEventHeader'{event_type, event_name}</v>
- <v>event_type = EventType</v>
- <v>event_name = string()</v>
- <v>EventType = #'CosNotification_EventType'{domain_name, type_name}</v>
- <v>domain_name = type_name = string()</v>
- <v>OptionalHeaderFields = [#'CosNotification_Property'{name, value}]</v>
- </type>
- <desc>
- <p>A client use this operation to pull next event sequence of maximum length
- <c>MaxEvents</c>. This operation is blocking and will not reply until the
- requested amount of events can be delivered or the QoS property <c>PacingInterval</c>
- is reached. For more information see the <c>User's Guide</c>.</p>
- </desc>
- </func>
- <func>
- <name>try_pull_structured_events(SequenceProxyPullSupplier, MaxEvents) -> Reply</name>
- <fsummary>Try to pull structured events from the proxy</fsummary>
- <type>
- <v>SequenceProxyPullSupplier = #objref</v>
- <v>MaxEvents = long()</v>
- <v>Reply = {EventBatch, HasEvent} | {'EXCEPTION', #'CosEventChannelAdmin_Disconnected'{}}</v>
- <v>HasEvent = boolean()</v>
- <v>EventBatch = [StructuredEvent]</v>
- <v>StructuredEvent = #'CosNotification_StructuredEvent'{header, filterable_data, remainder_of_body}</v>
- <v>header = EventHeader</v>
- <v>filterable_data = [#'CosNotification_Property'{name, value}]</v>
- <v>name = string()</v>
- <v>value = #any</v>
- <v>remainder_of_body = #any</v>
- <v>EventHeader = #'CosNotification_EventHeader'{fixed_header, variable_header}</v>
- <v>fixed_header = FixedEventHeader</v>
- <v>variable_header = OptionalHeaderFields</v>
- <v>FixedEventHeader = #'CosNotification_FixedEventHeader'{event_type, event_name}</v>
- <v>event_type = EventType</v>
- <v>event_name = string()</v>
- <v>EventType = #'CosNotification_EventType'{domain_name, type_name}</v>
- <v>domain_name = type_name = string()</v>
- <v>OptionalHeaderFields = [#'CosNotification_Property'{name, value}]</v>
- </type>
- <desc>
- <p>This operation pulls an event sequence of the maximum length <c>MaxEvents</c>,
- but do not block if the target object have no events to forward. The outparameter,
- <c>HasEvent</c> is true if the sequence contain any events.</p>
- </desc>
- </func>
- <func>
- <name>disconnect_sequence_pull_supplier(SequenceProxyPullSupplier) -> ok</name>
- <fsummary>Close the connection and terminate the proxy</fsummary>
- <type>
- <v>SequenceProxyPullSupplier = #objref</v>
- </type>
- <desc>
- <p>This operation cause the target object to close the connection and terminate.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPushConsumer.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPushConsumer.xml
deleted file mode 100644
index efec1f99cc..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPushConsumer.xml
+++ /dev/null
@@ -1,109 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosNotifyChannelAdmin_SequenceProxyPushConsumer</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyChannelAdmin_SequenceProxyPushConsumer</module>
- <modulesummary>This module implements the OMG CosNotifyChannelAdmin::SequenceProxyPushConsumer interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosNotifyComm_NotifyPublish">CosNotifyComm_NotifyPublish</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotification_QoSAdmin">CosNotification_QoSAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyFilter_FilterAdmin">CosNotifyFilter_FilterAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyChannelAdmin_ProxyConsumer">CosNotifyChannelAdmin_ProxyConsumer</seealso></p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>connect_sequence_push_supplier(SequenceProxyPushConsumer, PushSupplier) -> Reply</name>
- <fsummary>Connect a supplier to the proxy</fsummary>
- <type>
- <v>SequenceProxyPushConsumer = #objref</v>
- <v>PushSupplier = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosEventChannelAdmin_AlreadyConnected'{}}</v>
- </type>
- <desc>
- <p>This operation connects a <c>PushSupplier</c> to the target object. If a
- connection already exists the <c>AlreadyConnected</c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>push_structured_events(SequenceProxyPushConsumer, EventBatch) -> Reply</name>
- <fsummary>Push a structured event to the proxy</fsummary>
- <type>
- <v>SequenceProxyPushConsumer = #objref</v>
- <v>EventBatch = [StructuredEvent]</v>
- <v>StructuredEvent = #'CosNotification_StructuredEvent'{header, filterable_data, remainder_of_body}</v>
- <v>header = EventHeader</v>
- <v>filterable_data = [#'CosNotification_Property'{name, value}]</v>
- <v>name = string()</v>
- <v>value = #any</v>
- <v>remainder_of_body = #any</v>
- <v>EventHeader = #'CosNotification_EventHeader'{fixed_header, variable_header}</v>
- <v>fixed_header = FixedEventHeader</v>
- <v>variable_header = OptionalHeaderFields</v>
- <v>FixedEventHeader = #'CosNotification_FixedEventHeader'{event_type, event_name}</v>
- <v>event_type = EventType</v>
- <v>event_name = string()</v>
- <v>EventType = #'CosNotification_EventType'{domain_name, type_name}</v>
- <v>domain_name = type_name = string()</v>
- <v>OptionalHeaderFields = [#'CosNotification_Property'{name, value}]</v>
- <v>Reply = ok | {'EXCEPTION', #'CosEventChannelAdmin_Disconnected'{}}</v>
- </type>
- <desc>
- <p>A client must use this operation when it wishes to push a new sequence of events
- to the target object. If no connection exists the <c>Disconnected</c> exception
- is raised.</p>
- </desc>
- </func>
- <func>
- <name>disconnect_sequence_push_consumer(SequenceProxyPushConsumer) -> ok</name>
- <fsummary>Close connection and terminate the proxy</fsummary>
- <type>
- <v>SequenceProxyPushConsumer = #objref</v>
- </type>
- <desc>
- <p>This operation cause the target object to close the connection and terminate.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPushSupplier.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPushSupplier.xml
deleted file mode 100644
index 229d3667c5..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SequenceProxyPushSupplier.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyChannelAdmin_SequenceProxyPushSupplier</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyChannelAdmin_SequenceProxyPushSupplier</module>
- <modulesummary>This module implements the OMG CosNotifyChannelAdmin::SequenceProxyPushSupplier interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosNotifyComm_NotifySubscribe">CosNotifyComm_NotifySubscribe</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotification_QoSAdmin">CosNotification_QoSAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyFilter_FilterAdmin">CosNotifyFilter_FilterAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyChannelAdmin_ProxySupplier">CosNotifyChannelAdmin_ProxySupplier</seealso></p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>connect_sequence_push_consumer(SequenceProxyPushSupplier, PushConsumer) -> Reply</name>
- <fsummary>Connect a consumer to the proxy</fsummary>
- <type>
- <v>SequenceProxyPushSupplier = #objref</v>
- <v>PushConsumer = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosEventChannelAdmin_AlreadyConnected'{}} | {'EXCEPTION', #'CosEventChannelAdmin_TypeError'{}}</v>
- </type>
- <desc>
- <p>This operation connects a <c>PushConsumer</c> to the target object. If a
- connection already exists or the function <c>psuh_structured_events</c>
- is not supported the exceptions <c>AlreadyConnected</c> or
- <c>TypeError</c> will be raised respectively.</p>
- </desc>
- </func>
- <func>
- <name>suspend_connection(SequenceProxyPushSupplier) -> Reply</name>
- <fsummary>Suspend the connection between the client and the target object</fsummary>
- <type>
- <v>SequenceProxyPushSupplier = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosNotifyChannelAdmin_ConnectionAlreadyInactive'{}} | {'EXCEPTION', #'CosNotifyChannelAdmin_NotConnected'{}}</v>
- </type>
- <desc>
- <p>This operation suspends the connection between the client and the target object.
- If no connection exists or the connection is already suspended an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>resume_connection(SequenceProxyPushSupplier) -> Reply</name>
- <fsummary>Resume a previously suspended connection with the proxy</fsummary>
- <type>
- <v>SequenceProxyPullConsumer = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosNotifyChannelAdmin_ConnectionAlreadyInactive'{}} | {'EXCEPTION', #'CosNotifyChannelAdmin_NotConnected'{}}</v>
- </type>
- <desc>
- <p>If the connection have previously been suspended this operation must used
- if we want to resume the connection. If no object have been connected or the connection
- already is active an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>disconnect_sequence_push_supplier(SequenceProxyPushSupplier) -> ok</name>
- <fsummary>Close the connection and terminate the proxy</fsummary>
- <type>
- <v>SequenceProxyPushSupplier = #objref</v>
- </type>
- <desc>
- <p>This operation cause the target object to close the connection and terminate.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPullConsumer.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPullConsumer.xml
deleted file mode 100644
index 5a86cb84da..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPullConsumer.xml
+++ /dev/null
@@ -1,110 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyChannelAdmin_StructuredProxyPullConsumer</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyChannelAdmin_StructuredProxyPullConsumer</module>
- <modulesummary>This module implements the OMG CosNotifyChannelAdmin::StructuredProxyPullConsumer interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosNotifyComm_NotifyPublish">CosNotifyComm_NotifyPublish</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotification_QoSAdmin">CosNotification_QoSAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyFilter_FilterAdmin">CosNotifyFilter_FilterAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyChannelAdmin_ProxyConsumer">CosNotifyChannelAdmin_ProxyConsumer</seealso></p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>connect_structured_pull_supplier(StructuredProxyPullConsumer, PullSupplier) -> Reply</name>
- <fsummary>Connect a supplier to the proxy</fsummary>
- <type>
- <v>StructuredProxyPullConsumer = #objref</v>
- <v>PullSupplier = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosEventChannelAdmin_AlreadyConnected'{}} | {'EXCEPTION', #'CosEventChannelAdmin_TypeError'{}}</v>
- </type>
- <desc>
- <p>This operation connects a <c>PullSupplier</c> to the target object. If a connection
- already exists or the given client object does not support the functions
- <c>pull_structured_event</c> and <c>try_pull_structured_event</c> an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>suspend_connection(StructuredProxyPullConsumer) -> Reply</name>
- <fsummary>Suspend the connection between the target object and its client</fsummary>
- <type>
- <v>StructuredProxyPullConsumer = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosNotifyChannelAdmin_ConnectionAlreadyInactive'{}} | {'EXCEPTION', #'CosNotifyChannelAdmin_NotConnected'{}}</v>
- </type>
- <desc>
- <p>This operation suspends the connection between the target object and its client.
- If no connection exists or already suspended an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>resume_connection(StructuredProxyPullConsumer) -> Reply</name>
- <fsummary>Resume a previously suspended connection with the proxy</fsummary>
- <type>
- <v>StructuredProxyPullConsumer = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosNotifyChannelAdmin_ConnectionAlreadyInactive'{}} | {'EXCEPTION', #'CosNotifyChannelAdmin_NotConnected'{}}</v>
- </type>
- <desc>
- <p>If the connection have been suspended this operation must be used if we want
- to resume the connection. If the connection already are active or no connection
- have been created an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>disconnect_structured_pull_consumer(StructuredProxyPullConsumer) -> ok</name>
- <fsummary>Close the connection and terminate the proxy</fsummary>
- <type>
- <v>StructuredProxyPullConsumer = #objref</v>
- </type>
- <desc>
- <p>This operation cause the target object to close the connection and terminate.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPullSupplier.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPullSupplier.xml
deleted file mode 100644
index 1ca7c2d7df..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPullSupplier.xml
+++ /dev/null
@@ -1,140 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyChannelAdmin_StructuredProxyPullSupplier</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyChannelAdmin_StructuredProxyPullSupplier</module>
- <modulesummary>This module implements the OMG CosNotifyChannelAdmin::StructuredProxyPullSupplier interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosNotifyComm_NotifySubscribe">CosNotifyComm_NotifySubscribe</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotification_QoSAdmin">CosNotification_QoSAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyFilter_FilterAdmin">CosNotifyFilter_FilterAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyChannelAdmin_ProxySupplier">CosNotifyChannelAdmin_ProxySupplier</seealso></p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>connect_structured_pull_consumer(StructuredProxyPullSupplier, PullConsumer) -> Reply</name>
- <fsummary>Connect a consumer to the proxy</fsummary>
- <type>
- <v>StructuredProxyPullSupplier = #objref</v>
- <v>PullConsumer = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosEventChannelAdmin_AlreadyConnected'{}}</v>
- </type>
- <desc>
- <p>This operation connects a <c>PullConsumer</c> to the target object. If a connection
- already exists the <c>AlreadyConnected</c> exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>pull_structured_event(StructuredProxyPullSupplier) -> Reply</name>
- <fsummary>Pull a structured event from the proxy</fsummary>
- <type>
- <v>StructuredProxyPullSupplier = #objref</v>
- <v>Reply = StructuredEvent | {'EXCEPTION', #'CosEventChannelAdmin_Disconnected'{}}</v>
- <v>StructuredEvent = #'CosNotification_StructuredEvent'{header, filterable_data, remainder_of_body}</v>
- <v>header = EventHeader</v>
- <v>filterable_data = [#'CosNotification_Property'{name, value}]</v>
- <v>name = string()</v>
- <v>value = #any</v>
- <v>remainder_of_body = #any</v>
- <v>EventHeader = #'CosNotification_EventHeader'{fixed_header, variable_header}</v>
- <v>fixed_header = FixedEventHeader</v>
- <v>variable_header = OptionalHeaderFields</v>
- <v>FixedEventHeader = #'CosNotification_FixedEventHeader'{event_type, event_name}</v>
- <v>event_type = EventType</v>
- <v>event_name = string()</v>
- <v>EventType = #'CosNotification_EventType'{domain_name, type_name}</v>
- <v>domain_name = type_name = string()</v>
- <v>OptionalHeaderFields = [#'CosNotification_Property'{name, value}]</v>
- </type>
- <desc>
- <p>This operation pulls next event from the target object; if an event cannot
- be delivered this function blocks until an event arrives.</p>
- </desc>
- </func>
- <func>
- <name>try_pull_structured_event(StructuredProxyPullSupplier) -> Reply</name>
- <fsummary>Try to pull a structured event from the proxy</fsummary>
- <type>
- <v>StructuredProxyPullSupplier = #objref</v>
- <v>Reply = {StructuredEvent, HasEvent} | {'EXCEPTION', #'CosEventChannelAdmin_Disconnected'{}}</v>
- <v>HasEvent = boolean()</v>
- <v>StructuredEvent = #'CosNotification_StructuredEvent'{header, filterable_data, remainder_of_body}</v>
- <v>header = EventHeader</v>
- <v>filterable_data = [#'CosNotification_Property'{name, value}]</v>
- <v>name = string()</v>
- <v>value = #any</v>
- <v>remainder_of_body = #any</v>
- <v>EventHeader = #'CosNotification_EventHeader'{fixed_header, variable_header}</v>
- <v>fixed_header = FixedEventHeader</v>
- <v>variable_header = OptionalHeaderFields</v>
- <v>FixedEventHeader = #'CosNotification_FixedEventHeader'{event_type, event_name}</v>
- <v>event_type = EventType</v>
- <v>event_name = string()</v>
- <v>EventType = #'CosNotification_EventType'{domain_name, type_name}</v>
- <v>domain_name = type_name = string()</v>
- <v>OptionalHeaderFields = [#'CosNotification_Property'{name, value}]</v>
- </type>
- <desc>
- <p>This operation try to pull next event from the target object. If no event have arrived
- an empty event is returned and the out parameter <c>HasEvent</c> is set to false. Otherwise,
- the boolean flag is set to true and an valid event is returned.</p>
- </desc>
- </func>
- <func>
- <name>disconnect_structured_pull_supplier(StructuredProxyPullSupplier) -> ok</name>
- <fsummary>Close connection and terminate the proxy</fsummary>
- <type>
- <v>StructuredProxyPullSupplier = #objref</v>
- </type>
- <desc>
- <p>This operation cause the target object to close the connection and terminate.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPushConsumer.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPushConsumer.xml
deleted file mode 100644
index 63bcdf120c..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPushConsumer.xml
+++ /dev/null
@@ -1,110 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyChannelAdmin_StructuredProxyPushConsumer</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyChannelAdmin_StructuredProxyPushConsumer</module>
- <modulesummary>This module implements the OMG CosNotifyChannelAdmin::StructuredProxyPushConsumer interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosNotifyComm_NotifyPublish">CosNotifyComm_NotifyPublish</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotification_QoSAdmin">CosNotification_QoSAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyFilter_FilterAdmin">CosNotifyFilter_FilterAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyChannelAdmin_ProxyConsumer">CosNotifyChannelAdmin_ProxyConsumer</seealso></p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>connect_structured_push_supplier(StructuredProxyPushConsumer, PushSupplier) -> Reply</name>
- <fsummary>Connect a supplier to the proxy</fsummary>
- <type>
- <v>StructuredProxyPushConsumer = #objref</v>
- <v>PushSupplier = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosEventChannelAdmin_AlreadyConnected'{}}</v>
- </type>
- <desc>
- <p>This operation connects a <c>PushSupplier</c> to the target object. If a connection
- already exists an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>push_structured_event(StructuredProxyPushConsumer, StructuredEvent) -> Reply</name>
- <fsummary>Push a structured event to the proxy</fsummary>
- <type>
- <v>StructuredProxyPushConsumer = #objref</v>
- <v>StructuredEvent = #'CosNotification_StructuredEvent'{header, filterable_data, remainder_of_body}</v>
- <v>header = EventHeader</v>
- <v>filterable_data = [#'CosNotification_Property'{name, value}]</v>
- <v>name = string()</v>
- <v>value = #any</v>
- <v>remainder_of_body = #any</v>
- <v>EventHeader = #'CosNotification_EventHeader'{fixed_header, variable_header}</v>
- <v>fixed_header = FixedEventHeader</v>
- <v>variable_header = OptionalHeaderFields</v>
- <v>FixedEventHeader = #'CosNotification_FixedEventHeader'{event_type, event_name}</v>
- <v>event_type = EventType</v>
- <v>event_name = string()</v>
- <v>EventType = #'CosNotification_EventType'{domain_name, type_name}</v>
- <v>domain_name = type_name = string()</v>
- <v>OptionalHeaderFields = [#'CosNotification_Property'{name, value}]</v>
- <v>Reply = ok | {'EXCEPTION', #'CosEventChannelAdmin_Disconnected'{}}</v>
- </type>
- <desc>
- <p>When a client want to push a new event to the target object this operation must be used.</p>
- </desc>
- </func>
- <func>
- <name>disconnect_structured_push_consumer(StructuredProxyPushConsumer) -> ok</name>
- <fsummary>Close the connection and terminate the proxy</fsummary>
- <type>
- <v>StructuredProxyPushConsumer = #objref</v>
- </type>
- <desc>
- <p>This operation cause the target object to close the connection and terminate.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPushSupplier.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPushSupplier.xml
deleted file mode 100644
index 9ba5497fd8..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_StructuredProxyPushSupplier.xml
+++ /dev/null
@@ -1,110 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyChannelAdmin_StructuredProxyPushSupplier</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyChannelAdmin_StructuredProxyPushSupplier</module>
- <modulesummary>This module implements the OMG CosNotifyChannelAdmin::StructuredProxyPushSupplier interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosNotifyComm_NotifySubscribe">CosNotifyComm_NotifySubscribe</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotification_QoSAdmin">CosNotification_QoSAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyFilter_FilterAdmin">CosNotifyFilter_FilterAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyChannelAdmin_ProxySupplier">CosNotifyChannelAdmin_ProxySupplier</seealso></p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>connect_structured_push_consumer(StructuredProxyPushSupplier, PushConsumer) -> Reply</name>
- <fsummary>Connect a consumer to the proxy</fsummary>
- <type>
- <v>StructuredProxyPushSupplier = #objref</v>
- <v>PushConsumer = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosEventChannelAdmin_AlreadyConnected'{}} | {'EXCEPTION', #'CosEventChannelAdmin_TypeError'{}}</v>
- </type>
- <desc>
- <p>This operation connects a <c>PushConsumer</c> to the target object. If
- a connection already exists or the function <c>push_structured_event</c>
- is not supported by the client object an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>suspend_connection(StructuredProxyPushSupplier) -> Reply</name>
- <fsummary>Suspend the connection with the target object</fsummary>
- <type>
- <v>StructuredProxyPushSupplier = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosNotifyChannelAdmin_ConnectionAlreadyInactive'{}} | {'EXCEPTION', #'CosNotifyChannelAdmin_NotConnected'{}}</v>
- </type>
- <desc>
- <p>This operation suspends the connection with the target object. If no connection
- exists or the connection already is suspended an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>resume_connection(StructuredProxyPushSupplier) -> Reply</name>
- <fsummary>Resume a previously suspended connection</fsummary>
- <type>
- <v>StructuredProxyPullConsumer = #objref</v>
- <v>Reply = ok | {'EXCEPTION', #'CosNotifyChannelAdmin_ConnectionAlreadyInactive'{}} | {'EXCEPTION', #'CosNotifyChannelAdmin_NotConnected'{}}</v>
- </type>
- <desc>
- <p>If the connection with the target object have been suspended this function
- must be used to resume the connection. If no client have been connected or
- the connection is active an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>disconnect_structured_push_supplier(StructuredProxyPushSupplier) -> ok</name>
- <fsummary>Close the connection and terminate the target object</fsummary>
- <type>
- <v>StructuredProxyPushSupplier = #objref</v>
- </type>
- <desc>
- <p>This operation cause the target object to close the connection and terminate.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SupplierAdmin.xml b/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SupplierAdmin.xml
deleted file mode 100644
index 540edaff3f..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyChannelAdmin_SupplierAdmin.xml
+++ /dev/null
@@ -1,195 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyChannelAdmin_SupplierAdmin</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyChannelAdmin_SupplierAdmin</module>
- <modulesummary>This module implements the OMG CosNotifyChannelAdmin::SupplierAdmin interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosNotification_QoSAdmin">CosNotification_QoSAdmin</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyComm_NotifySubscribe">CosNotifyComm_NotifyPublish</seealso></p>
- </item>
- <item>
- <p><seealso marker="CosNotifyFilter_FilterAdmin">CosNotifyFilter_FilterAdmin</seealso></p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>_get_MyID(SupplierAdmin) -> AdminID</name>
- <fsummary>Return the objects Id</fsummary>
- <type>
- <v>SupplierAdmin = #objref</v>
- <v>AdminID = long()</v>
- </type>
- <desc>
- <p>When a <c>SupplierAdmin</c> object is created it is given a unique Id
- by the creating channel. This readonly attribute maintains this Id.</p>
- </desc>
- </func>
- <func>
- <name>_get_MyChannel(SupplierAdmin) -> Channel</name>
- <fsummary>Return the objects associated channel</fsummary>
- <type>
- <v>SupplierAdmin = #objref</v>
- <v>Channel = #objref</v>
- </type>
- <desc>
- <p>The creating channel's reference is maintained by this readonly attribute.</p>
- </desc>
- </func>
- <func>
- <name>_get_MyOperator(SupplierAdmin) -> OpType</name>
- <fsummary>Return the filter scheme</fsummary>
- <type>
- <v>SupplierAdmin = #objref</v>
- <v>OpType = 'AND_OP' | 'OR_OP'</v>
- </type>
- <desc>
- <p>The Operation Type, which determines the semantics the target object will
- use for any associated <c>Filters</c>, is maintained by this readonly attribute.</p>
- </desc>
- </func>
- <func>
- <name>_get_pull_consumers(SupplierAdmin) -> ProxyIDSeq</name>
- <fsummary>Return all associated pull consumers Id:s</fsummary>
- <type>
- <v>SupplierAdmin = #objref</v>
- <v>ProxyIDSeq = [ProxyID]</v>
- <v>ProxyID = long()</v>
- </type>
- <desc>
- <p>A sequence of all associated <c>PullProxy</c> Id's is maintained by this
- readonly attribute.</p>
- </desc>
- </func>
- <func>
- <name>_get_push_consumers(SupplierAdmin) -> ProxyIDSeq</name>
- <fsummary>Return all associated push consumers Id:s</fsummary>
- <type>
- <v>SupplierAdmin = #objref</v>
- <v>ProxyIDSeq = [ProxyID]</v>
- <v>ProxyID = long()</v>
- </type>
- <desc>
- <p>This operation returns all <c>PushProxy</c> Id's created by the target
- object.</p>
- </desc>
- </func>
- <func>
- <name>get_proxy_consumer(SupplierAdmin, ProxyID) -> Reply</name>
- <fsummary>Return the Proxy which corresponds to the given Id</fsummary>
- <type>
- <v>SupplierAdmin = #objref</v>
- <v>ProxyID = long()</v>
- <v>Reply = Proxy | {'EXCEPTION', #'CosNotifyChannelAdmin_ProxyNotFound'{}}</v>
- <v>Proxy = #objref</v>
- </type>
- <desc>
- <p>The Proxy which corresponds to the given Id is returned by this operation.</p>
- </desc>
- </func>
- <func>
- <name>obtain_notification_pull_consumer(SupplierAdmin, SupplierType) -> Reply</name>
- <fsummary>Create a new proxy</fsummary>
- <type>
- <v>SupplierAdmin = #objref</v>
- <v>SupplierType = 'ANY_EVENT' | 'STRUCTURED_EVENT' | 'SEQUENCE_EVENT'</v>
- <v>Reply = {Proxy, ProxyID}</v>
- <v>Proxy = #objref</v>
- <v>ProxyID = long()</v>
- </type>
- <desc>
- <p>This operation creates a new proxy and returns its object reference along with its ID.
- The <c>SupplierType</c> parameter determines the event type accepted by the proxy.</p>
- </desc>
- </func>
- <func>
- <name>obtain_pull_consumer(SupplierAdmin) -> Proxy</name>
- <fsummary>Create a new proxy</fsummary>
- <type>
- <v>SupplierAdmin = #objref</v>
- <v>Proxy = #objref</v>
- </type>
- <desc>
- <p>A proxy which accepts <c>#any{}</c> events is created by this operation.</p>
- </desc>
- </func>
- <func>
- <name>obtain_notification_push_consumer(SupplierAdmin, SupplierType) -> Reply</name>
- <fsummary>Create a new proxy</fsummary>
- <type>
- <v>SupplierAdmin = #objref</v>
- <v>SupplierType = 'ANY_EVENT' | 'STRUCTURED_EVENT' | 'SEQUENCE_EVENT'</v>
- <v>Reply = {Proxy, ProxyID}</v>
- <v>Proxy = #objref</v>
- <v>ProxyID = long()</v>
- </type>
- <desc>
- <p>Determined by the <c>SupplierType</c> parameter a compliant proxy is created and
- its object reference along with its Id is returned by this operation.</p>
- </desc>
- </func>
- <func>
- <name>obtain_push_consumer(SupplierAdmin) -> Proxy</name>
- <fsummary>Create a new proxy</fsummary>
- <type>
- <v>SupplierAdmin = #objref</v>
- <v>Proxy = #objref</v>
- </type>
- <desc>
- <p>A proxy which accepts <c>#any{}</c> events is created by this operation.</p>
- </desc>
- </func>
- <func>
- <name>destroy(SupplierAdmin) -> ok</name>
- <fsummary>Terminate the target object</fsummary>
- <type>
- <v>SupplierAdmin = #objref</v>
- </type>
- <desc>
- <p>This operation terminates the SupplierAdmin object and notifies the creating channel
- that the target object no longer is active.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyComm_NotifyPublish.xml b/lib/cosNotification/doc/src/CosNotifyComm_NotifyPublish.xml
deleted file mode 100644
index a41319cb5c..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyComm_NotifyPublish.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyComm_NotifyPublish</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyComm_NotifyPublish</module>
- <modulesummary>This module implements the OMG CosNotifyComm::NotifyPublish interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>All objects, which inherit this interface, export functions described in this module.</p>
- </description>
- <funcs>
- <func>
- <name>offer_change(Object, Added, Removed) -> Reply</name>
- <fsummary>Inform the target object which type of events the supplier will deliver</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Added = Removed = EventTypeSeq</v>
- <v>EventTypeSeq = [type]</v>
- <v>Reply = ok | {'EXCEPTION', CosNotifyComm_InvalidEventType{type}}</v>
- <v>type = #'CosNotification_EventType'{domain_name, type_name}</v>
- <v>domain_name = type_name = string()</v>
- </type>
- <desc>
- <p>Objects supporting this interface can be informed by supplier objects about
- which type of events that will be delivered in the future. This operation
- accepts two parameters describing new and old event types respectively.
- If any of the supplied event type names is syntactically incorrect an exception
- is raised.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyComm_NotifySubscribe.xml b/lib/cosNotification/doc/src/CosNotifyComm_NotifySubscribe.xml
deleted file mode 100644
index 277c666459..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyComm_NotifySubscribe.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyComm_NotifySubscribe</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyComm_NotifySubscribe</module>
- <modulesummary>This module implements the OMG CosNotifyComm::NotifySubscribe interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>All objects, which inherit this interface, export functions described in this module.</p>
- </description>
- <funcs>
- <func>
- <name>subscription_change(Object, Added, Removed) -> Reply</name>
- <fsummary>Inform the target object which event types the client will and will not accept in the future</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Added = Removed = EventTypeSeq</v>
- <v>EventTypeSeq = [type]</v>
- <v>Reply = ok | {'EXCEPTION', CosNotifyComm_InvalidEventType{type}}</v>
- <v>type = #'CosNotification_EventType'{domain_name, type_name}</v>
- <v>domain_name = type_name = string()</v>
- </type>
- <desc>
- <p>This operation takes as input two sequences of event type names
- specifying events the client will and will not accept in the future
- respectively.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyFilter_Filter.xml b/lib/cosNotification/doc/src/CosNotifyFilter_Filter.xml
deleted file mode 100644
index a953540849..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyFilter_Filter.xml
+++ /dev/null
@@ -1,223 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosNotifyFilter_Filter</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyFilter_Filter</module>
- <modulesummary>This module implements the OMG CosNotifyFilter::Filter interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>_get_constraint_grammar(Filter) -> Grammar</name>
- <fsummary>Return which type of Grammar the Filter uses</fsummary>
- <type>
- <v>Filter = #objref</v>
- <v>Grammar = string()</v>
- </type>
- <desc>
- <p>This operation returns which type of Grammar the Filter uses. Currently, only <c>"EXTENDED_TCL"</c> is supported.</p>
- </desc>
- </func>
- <func>
- <name>add_constraints(Filter, ConstraintExpSeq) -> Reply</name>
- <fsummary>Add new constraints to the filter</fsummary>
- <type>
- <v>Filter = #objref</v>
- <v>ConstraintExpSeq = [Constraint]</v>
- <v>ConstraintExp = #'CosNotifyFilter_ConstraintExp'{event_types, constraint_expr}</v>
- <v>event_types = #'CosNotification_EventTypeSeq'{}</v>
- <v>constraint_expr = string()</v>
- <v>Reply = ConstraintInfoSeq | {'EXCEPTION', #'CosNotifyFilter_InvalidConstraint'{constr}}</v>
- <v>constr = ConstraintExp</v>
- <v>ConstraintInfoSeq = [ConstraintInfo]</v>
- <v>ConstraintInfo = #'CosNotifyFilter_ConstraintInfo'{constraint_expression, constraint_id}</v>
- <v>constraint_expression = ConstraintExp</v>
- <v>constraint_id = long()</v>
- </type>
- <desc>
- <p>Initially, Filters do not contain any constraints, hence, all events will be forwarded.
- The <c>add_constraints/2</c> operation allow us to add constraints to the target object.</p>
- </desc>
- </func>
- <func>
- <name>modify_constraints(Filter, ConstraintIDSeq, ConstraintInfoSeq) -> Reply</name>
- <fsummary>Modify existing constraints</fsummary>
- <type>
- <v>Filter = #objref</v>
- <v>ConstraintIDSeq = [ConstraintID]</v>
- <v>ConstraintID = long()</v>
- <v>ConstraintInfoSeq = [ConstraintInfo]</v>
- <v>ConstraintInfo = #'CosNotifyFilter_ConstraintInfo'{constraint_expression, constraint_id}</v>
- <v>constraint_expression = ConstraintExp</v>
- <v>constraint_id = long()</v>
- <v>Reply = ok | {'EXCEPTION', #'CosNotifyFilter_InvalidConstraint'{constr}} | {'EXCEPTION', #'CosNotifyFilter_ConstraintNotFound'{id}}</v>
- <v>constr = ConstraintExp</v>
- <v>id = long()</v>
- <v>ConstraintExp = #'CosNotifyFilter_ConstraintExp'{event_types, constraint_expr}</v>
- <v>event_types = #'CosNotification_EventTypeSeq'{}</v>
- <v>constraint_expr = string()</v>
- </type>
- <desc>
- <p>This operation is invoked by a client in order to modify the constraints associated
- with the target object. The constraints related to the Id's in the parameter sequence
- <c>ConstraintIDSeq</c> will, if all values are valid, be deleted. The <c>ConstraintInfoSeq</c>
- parameter contains of Id-Expression pairs and a constraint matching one of the unique
- Id's will, if all input values are correct, be updated. If the parameters contain incorrect
- data en exception will be raised.</p>
- </desc>
- </func>
- <func>
- <name>get_constraints(Filter, ConstraintIDSeq) -> Reply</name>
- <fsummary>Return all constraints which match the supplied Ids</fsummary>
- <type>
- <v>Filter = #objref</v>
- <v>ConstraintIDSeq = [ConstraintID]</v>
- <v>ConstraintID = long()</v>
- <v>Reply = ConstraintInfoSeq | {'EXCEPTION', #'CosNotifyFilter_ConstraintNotFound'{id}}</v>
- <v>ConstraintInfoSeq = [ConstraintInfo]</v>
- <v>ConstraintInfo = #'CosNotifyFilter_ConstraintInfo'{constraint_expression, constraint_id}</v>
- <v>constraint_expression = ConstraintExp</v>
- <v>constraint_id = id = long()</v>
- </type>
- <desc>
- <p>This operation return a sequence of ConstraintInfo's, related to the given ConstraintID's,
- associated with the target object.</p>
- </desc>
- </func>
- <func>
- <name>get_all_constraints(Filter) -> ConstraintInfoSeq</name>
- <fsummary>Return all constraints associated with the target object</fsummary>
- <type>
- <v>Filter = #objref</v>
- <v>ConstraintInfoSeq = [ConstraintInfo]</v>
- <v>ConstraintInfo = #'CosNotifyFilter_ConstraintInfo'{constraint_expression, constraint_id}</v>
- <v>constraint_expression = ConstraintExp</v>
- <v>constraint_id = long()</v>
- </type>
- <desc>
- <p>All constraints, and their unique Id, associated with the target object will be returned by this operation.</p>
- </desc>
- </func>
- <func>
- <name>remove_all_constraints(Filter) -> ok</name>
- <fsummary>Remove all constraints associated with the target object</fsummary>
- <type>
- <v>Filter = #objref</v>
- </type>
- <desc>
- <p>All constraints associated with the target object are removed by this operation and, since
- the the target object no longer contain any constraints, true will always be the result of
- any match operation.</p>
- </desc>
- </func>
- <func>
- <name>destroy(Filter) -> ok</name>
- <fsummary>Terminate the target object</fsummary>
- <type>
- <v>Filter = #objref</v>
- </type>
- <desc>
- <p>This operation terminates the target object.</p>
- </desc>
- </func>
- <func>
- <name>match(Filter, Event) -> Reply</name>
- <fsummary>Match the Any event if it satisfies at least one constraint</fsummary>
- <type>
- <v>Filter = #objref</v>
- <v>Event = #any</v>
- <v>Reply = boolean() | {'EXCEPTION', #'CosNotifyFilter_UnsupportedFilterableData'{}}</v>
- </type>
- <desc>
- <p>This operation accepts an <c>#any{}</c> event and returns <c>true</c> if it satisfies
- at least one constraint. If the event contains data of the wrong type, e.g., should be
- a string() but in fact i a short(), an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>match_structured(Filter, Event) -> Reply</name>
- <fsummary>Match the structured event if it satisfies at least one constraint</fsummary>
- <type>
- <v>Filter = #objref</v>
- <v>Event = #'CosNotification_StructuredEvent'{}</v>
- <v>Reply = boolean() | {'EXCEPTION', #'CosNotifyFilter_UnsupportedFilterableData'{}}</v>
- </type>
- <desc>
- <p>This operation is similar to the <c>match</c> operation but accepts structured
- events instead.</p>
- </desc>
- </func>
- <func>
- <name>attach_callback(Filter, NotifySubscribe) -> CallbackID</name>
- <fsummary>Connect NotifySubscribe object, which should be informed when the target object's constraints are updated</fsummary>
- <type>
- <v>Filter = #objref</v>
- <v>NotifySubscribe = #objref</v>
- <v>CallbackID = long()</v>
- </type>
- <desc>
- <p>This operation connects a NotifySubscribe object, which should be informed
- when the target object's constraints are updated. A unique Id is returned
- which must be stored if we ever want to detach the callback object in the future.</p>
- </desc>
- </func>
- <func>
- <name>detach_callback(Filter, CallbackID) -> Reply</name>
- <fsummary>Disconnect the NotifySubscribe object with the given Id</fsummary>
- <type>
- <v>Filter = #objref</v>
- <v>CallbackID = long()</v>
- <v>Reply = ok | {'EXCEPTION', #'CosNotifyFilter_CallbackNotFound'{}}</v>
- </type>
- <desc>
- <p>If the target object has an associated callback that matches the supplied
- Id it will be removed and longer informed of any updates. If no object
- with a matching Id is found an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>get_callbacks(Filter) -> CallbackIDSeq</name>
- <fsummary>Return all NotifySubscribe Id's associated with the target object</fsummary>
- <type>
- <v>Filter = #objref</v>
- <v>CallbackIDSeq = [CallbackID]</v>
- <v>CallbackID = long()</v>
- </type>
- <desc>
- <p>This operation returns a sequence of all connected NotifySubscribe object Id's.
- If no callbacks are associated with the target object the list will be empty.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyFilter_FilterAdmin.xml b/lib/cosNotification/doc/src/CosNotifyFilter_FilterAdmin.xml
deleted file mode 100644
index 5cb56963f1..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyFilter_FilterAdmin.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyFilter_FilterAdmin</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyFilter_FilterAdmin</module>
- <modulesummary>This module implements the OMG CosNotifyFilter::FilterAdmin interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>All objects, which inherit this interface, export functions described in this module.</p>
- </description>
- <funcs>
- <func>
- <name>add_filter(Object, Filter) -> FilterID</name>
- <fsummary>Add a new filter to the target object</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Filter = #objref</v>
- <v>FilterID = long()</v>
- </type>
- <desc>
- <p>This operation connects a new <c>Filter</c> to the target object. This <c>Filter</c> will, together
- with other associated <c>Filters</c>, be used to select events to forward. A unique Id is
- returned and should be used if we no longer want to consult the given <c>Filter</c>.</p>
- </desc>
- </func>
- <func>
- <name>remove_filter(Object, FilterID) -> ok</name>
- <fsummary>Remove a filter associated with the target object</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>FilterID = long()</v>
- </type>
- <desc>
- <p>If a certain <c>Filter</c> no longer should be associated with the target object
- this operation must be used. Events will no longer be tested against the <c>Filter</c>
- associated with the given Id.</p>
- </desc>
- </func>
- <func>
- <name>get_filter(Object, FilterID) -> Reply</name>
- <fsummary>Return the filter with the given Id</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>FilterID = long()</v>
- <v>Reply = Filter | {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}</v>
- <v>Filter = #objref</v>
- </type>
- <desc>
- <p>If the target object is associated with a <c>Filter</c> matching the given Id the
- reference will be returned. If no such <c>Filter</c> is known by the target object
- an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>get_all_filters(Object) -> FilterIDSeq</name>
- <fsummary>Return a list of all filter Id:s associated with the target object</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>FilterIDSeq = [FilterID]</v>
- <v>FilterID = long()</v>
- </type>
- <desc>
- <p>Id's for all <c>Filter</c> objects associated with the target object is
- returned by this operation.</p>
- </desc>
- </func>
- <func>
- <name>remove_all_filters(Object) -> ok</name>
- <fsummary>Remove all filters from the target object</fsummary>
- <type>
- <v>Object = #objref</v>
- </type>
- <desc>
- <p>If we want to remove all <c>Filters</c> associated with the target object we can use this function.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyFilter_FilterFactory.xml b/lib/cosNotification/doc/src/CosNotifyFilter_FilterFactory.xml
deleted file mode 100644
index adacbc3281..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyFilter_FilterFactory.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNotifyFilter_FilterFactory</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyFilter_FilterFactory</module>
- <modulesummary>This module implements the OMG CosNotifyFilter::FilterFactory interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>create_filter(FilterFactory, Grammar) -> Reply</name>
- <fsummary>Create a <c>Filter</c>object</fsummary>
- <type>
- <v>FilterFactory = #objref</v>
- <v>Grammar = string()</v>
- <v>Reply = Filter | {'EXCEPTION', #'CosNotifyFilter_InvalidGrammar'{}}</v>
- <v>Filter = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new Filter object, under the condition
- that Grammar given is supported. Currently, only <c>"EXTENDED_TCL"</c> is supported.</p>
- </desc>
- </func>
- <func>
- <name>create_mapping_filter(FilterFactory, Grammar) -> Reply</name>
- <fsummary>Create a <c>MappingFilter</c>object</fsummary>
- <type>
- <v>FilterFactory = #objref</v>
- <v>Grammar = string()</v>
- <v>Reply = MappingFilter | {'EXCEPTION', #'CosNotifyFilter_InvalidGrammar'{}}</v>
- <v>Filter = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new MappingFilter object, under the condition
- that Grammar given is supported. Currently, only <c>"EXTENDED_TCL"</c> is supported.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/CosNotifyFilter_MappingFilter.xml b/lib/cosNotification/doc/src/CosNotifyFilter_MappingFilter.xml
deleted file mode 100644
index c0db8c1ae0..0000000000
--- a/lib/cosNotification/doc/src/CosNotifyFilter_MappingFilter.xml
+++ /dev/null
@@ -1,228 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosNotifyFilter_MappingFilter</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosNotifyFilter_MappingFilter</module>
- <modulesummary>This module implements the OMG CosNotifyFilter::MappingFilter interface.</modulesummary>
- <description>
- <p>The main purpose of this module is to match events against associated
- constraints and return the value for the first constraint that returns
- true for the given event. If all constraints return false the default value
- will be returned.</p>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>_get_constraint_grammar(MappingFilter) -> Grammar</name>
- <fsummary>Return which type of Grammar the MappingFilter uses</fsummary>
- <type>
- <v>MappingFilter = #objref</v>
- <v>Grammar = string()</v>
- </type>
- <desc>
- <p>This operation returns which type of Grammar the MappingFilter uses.
- Currently, only <c>"EXTENDED_TCL"</c> is supported.</p>
- </desc>
- </func>
- <func>
- <name>_get_value_type(MappingFilter) -> CORBA::TypeCode</name>
- <fsummary>Return the <c>CORBA::TypeCode</c>of the default value associated with the target object</fsummary>
- <type>
- <v>MappingFilter = #objref</v>
- </type>
- <desc>
- <p>This readonly attribute maintains the <c>CORBA::TypeCode</c> of the default value
- associated with the target object.</p>
- </desc>
- </func>
- <func>
- <name>_get_default_value(MappingFilter) -> #any</name>
- <fsummary>Return the <c>#any{}</c> default value associated with the target object</fsummary>
- <type>
- <v>MappingFilter = #objref</v>
- </type>
- <desc>
- <p>This readonly attribute maintains the <c>#any{}</c> default value associated with
- the target object.</p>
- </desc>
- </func>
- <func>
- <name>add_mapping_constraints(MappingFilter, MappingConstraintPairSeq) -> Reply</name>
- <fsummary>Add new mapping constraints</fsummary>
- <type>
- <v>MappingFilter = #objref</v>
- <v>MappingConstraintPairSeq = [MappingConstraintPair]</v>
- <v>MappingConstraintPair = #'CosNotifyFilter_MappingConstraintPair'{constraint_expression, result_to_set}</v>
- <v>constraint_expression = #'CosNotifyFilter_ConstraintExp'{event_types, constraint_expr}</v>
- <v>event_types = #'CosNotification_EventTypeSeq'{}</v>
- <v>constraint_expr = string()</v>
- <v>result_to_set = #any</v>
- <v>Reply = MappingConstraintInfoSeq | {'EXCEPTION', #'CosNotifyFilter_InvalidConstraint'{constr}} | {'EXCEPTION', #'CosNotifyFilter_InvalidValue'{constr, value}}</v>
- <v>constr = ConstraintExp</v>
- <v>ConstraintExp = #'CosNotifyFilter_ConstraintExp'{event_types, constraint_expr}</v>
- <v>event_types = #'CosNotification_EventTypeSeq'{}</v>
- <v>constraint_expr = string()</v>
- <v>MappingConstraintInfoSeq = [MappingConstraintInfo]</v>
- <v>MappingConstraintInfo = #'CosNotifyFilter_MappingConstraintInfo'{constraint_expression, constraint_id, value}</v>
- <v>constraint_expression = ConstraintExp</v>
- <v>constraint_id = long()</v>
- <v>value = #any</v>
- </type>
- <desc>
- <p>This operation add new mapping constraints, which will be used when trying to override
- Quality of Service settings defined in the given event. If a constraint return true the
- associated value will be returned, otherwise the default value.</p>
- </desc>
- </func>
- <func>
- <name>modify_constraints(MappingFilter, ConstraintIDSeq, MappingConstraintInfoSeq) -> Reply</name>
- <fsummary>Modify the constraints associated with the target object</fsummary>
- <type>
- <v>MappingFilter = #objref</v>
- <v>ConstraintIDSeq = [ConstraintID]</v>
- <v>ConstraintID = long()</v>
- <v>MappingConstraintInfoSeq = [MappingConstraintInfo]</v>
- <v>MappingConstraintInfo = #'CosNotifyFilter_MappingConstraintInfo'{constraint_expression, constraint_id, value}</v>
- <v>constraint_expression = ConstraintExp</v>
- <v>constraint_id = long()</v>
- <v>value = #any</v>
- <v>ConstraintInfoSeq = [ConstraintInfo]</v>
- <v>ConstraintInfo = #'CosNotifyFilter_ConstraintInfo'{constraint_expression, constraint_id}</v>
- <v>constraint_expression = ConstraintExp</v>
- <v>constraint_id = long()</v>
- <v>Reply = ok | {'EXCEPTION', #'CosNotifyFilter_InvalidConstraint'{constr}} | {'EXCEPTION', #'CosNotifyFilter_ConstraintNotFound'{id}} | {'EXCEPTION', #'CosNotifyFilter_InvalidValue'{constr, value}}</v>
- <v>constr = ConstraintExp</v>
- <v>id = long()</v>
- <v>value = #any</v>
- <v>ConstraintExp = #'CosNotifyFilter_ConstraintExp'{event_types, constraint_expr}</v>
- <v>event_types = #'CosNotification_EventTypeSeq'{}</v>
- <v>constraint_expr = string()</v>
- </type>
- <desc>
- <p>The <c>ConstraintIDSeq</c> supplied should relate to constraints the caller wishes to
- remove. If any of the supplied Id's are not found an exception will be raised. This
- operation also accepts a sequence of <c>MappingConstraintInfo</c> which will be added.
- If the target object cannot modify the constraints as requested an exception is raised
- describing which constraint, and why, could not be updated.</p>
- </desc>
- </func>
- <func>
- <name>get_mapping_constraints(MappingFilter, ConstraintIDSeq) -> Reply</name>
- <fsummary>Return the target object's associated constraints with given ID:s</fsummary>
- <type>
- <v>MappingFilter = #objref</v>
- <v>ConstraintIDSeq = [ConstraintID]</v>
- <v>ConstraintID = long()</v>
- <v>Reply = MappingConstraintInfoSeq | {'EXCEPTION', #'CosNotifyFilter_ConstraintNotFound'{id}}</v>
- <v>MappingConstraintInfoSeq = [MappingConstraintInfo]</v>
- <v>MappingConstraintInfo = #'CosNotifyFilter_MappingConstraintInfo'{constraint_expression, constraint_id, value}</v>
- <v>constraint_expression = ConstraintExp</v>
- <v>ConstraintExp = #'CosNotifyFilter_ConstraintExp'{event_types, constraint_expr}</v>
- <v>event_types = #'CosNotification_EventTypeSeq'{}</v>
- <v>constraint_expr = string()</v>
- <v>constraint_id = id = long()</v>
- <v>value = #any</v>
- </type>
- <desc>
- <p>When adding a new constraint a unique Id is returned, which is accepted as input for this
- operation. The associated constraint is returned, but if no such Id exists an exception is raised. </p>
- </desc>
- </func>
- <func>
- <name>get_all_mapping_constraints(MappingFilter) -> MappingConstraintInfoSeq</name>
- <fsummary>Return the target object's all associated constraints</fsummary>
- <type>
- <v>MappingFilter = #objref</v>
- <v>MappingConstraintInfoSeq = [MappingConstraintInfo]</v>
- <v>MappingConstraintInfo = #'CosNotifyFilter_MappingConstraintInfo'{constraint_expression, constraint_id, value}</v>
- <v>constraint_expression = ConstraintExp</v>
- <v>ConstraintExp = #'CosNotifyFilter_ConstraintExp'{event_types, constraint_expr}</v>
- <v>event_types = #'CosNotification_EventTypeSeq'{}</v>
- <v>constraint_expr = string()</v>
- <v>constraint_id = long()</v>
- <v>value = #any</v>
- </type>
- <desc>
- <p>This operation returns a sequence of all unique Id's associated with the target object.
- If no constraint have been added the sequence will be empty.</p>
- </desc>
- </func>
- <func>
- <name>remove_all_mapping_constraints(MappingFilter) -> ok</name>
- <fsummary>Remove all constraints associated with the target object</fsummary>
- <type>
- <v>MappingFilter = #objref</v>
- </type>
- <desc>
- <p>This operation removes all constraints associated with the target object.</p>
- </desc>
- </func>
- <func>
- <name>destroy(MappingFilter) -> ok</name>
- <fsummary>Terminate the target object</fsummary>
- <type>
- <v>MappingFilter = #objref</v>
- </type>
- <desc>
- <p>This operation terminates the target object. Remember to remove
- this Filter from the objects it have been associated with.</p>
- </desc>
- </func>
- <func>
- <name>match(MappingFilter, Event) -> Reply</name>
- <fsummary>Evaluate the given Any event with the Filter's constraints</fsummary>
- <type>
- <v>MappingFilter = #objref</v>
- <v>Event = #any</v>
- <v>Reply = {boolean(), #any} | {'EXCEPTION', #'CosNotifyFilter_UnsupportedFilterableData'{}}</v>
- </type>
- <desc>
- <p>This operation evaluates <c>Any</c> events with the Filter's constraints,
- and returns the value to use. The value is the default value if all constraints
- returns false and the value associated with the first constraint returning true.</p>
- </desc>
- </func>
- <func>
- <name>match_structured(MappingFilter, Event) -> Reply</name>
- <fsummary>Evaluate the given structured event with the Filter's constraints</fsummary>
- <type>
- <v>MappingFilter = #objref</v>
- <v>Event = #'CosNotification_StructuredEvent'{}</v>
- <v>Reply = {boolean(), #any} | {'EXCEPTION', #'CosNotifyFilter_UnsupportedFilterableData'{}}</v>
- </type>
- <desc>
- <p>Similar to <c>match/2</c> but accepts a structured event as input.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/Makefile b/lib/cosNotification/doc/src/Makefile
deleted file mode 100644
index 6207290101..0000000000
--- a/lib/cosNotification/doc/src/Makefile
+++ /dev/null
@@ -1,172 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(COSNOTIFICATION_VSN)
-APPLICATION=cosNotification
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = \
- cosNotificationApp.xml \
- CosNotifyChannelAdmin_EventChannelFactory.xml \
- CosNotifyChannelAdmin_EventChannel.xml \
- CosNotification.xml \
- CosNotification_QoSAdmin.xml \
- CosNotification_AdminPropertiesAdmin.xml \
- CosNotifyChannelAdmin_ConsumerAdmin.xml \
- CosNotifyChannelAdmin_SupplierAdmin.xml \
- CosNotifyComm_NotifyPublish.xml \
- CosNotifyComm_NotifySubscribe.xml \
- CosNotifyFilter_FilterAdmin.xml \
- CosNotifyFilter_FilterFactory.xml \
- CosNotifyFilter_Filter.xml \
- CosNotifyFilter_MappingFilter.xml \
- CosNotifyChannelAdmin_ProxyConsumer.xml \
- CosNotifyChannelAdmin_ProxySupplier.xml \
- CosNotifyChannelAdmin_ProxyPullConsumer.xml \
- CosNotifyChannelAdmin_ProxyPullSupplier.xml \
- CosNotifyChannelAdmin_ProxyPushConsumer.xml \
- CosNotifyChannelAdmin_ProxyPushSupplier.xml \
- CosNotifyChannelAdmin_SequenceProxyPullConsumer.xml \
- CosNotifyChannelAdmin_SequenceProxyPullSupplier.xml \
- CosNotifyChannelAdmin_SequenceProxyPushConsumer.xml \
- CosNotifyChannelAdmin_SequenceProxyPushSupplier.xml \
- CosNotifyChannelAdmin_StructuredProxyPullConsumer.xml \
- CosNotifyChannelAdmin_StructuredProxyPullSupplier.xml \
- CosNotifyChannelAdmin_StructuredProxyPushConsumer.xml \
- CosNotifyChannelAdmin_StructuredProxyPushSupplier.xml \
-
-
-
-XML_PART_FILES = \
- part.xml \
- part_notes.xml
-XML_CHAPTER_FILES = \
- ch_contents.xml \
- ch_introduction.xml \
- ch_install.xml \
- ch_system.xml \
- ch_BNF.xml \
- ch_QoS.xml \
- ch_example.xml \
- notes.xml
-
-BOOK_FILES = book.xml
-
-XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \
- $(XML_PART_FILES) $(XML_CHAPTER_FILES)
-
-TECHNICAL_DESCR_FILES =
-
-GIF_FILES = \
- book.gif \
- notes.gif \
- ref_man.gif \
- user_guide.gif \
- eventstructure.gif \
- notificationFlow.gif
-
-PS_FILES =
-
-# ----------------------------------------------------
-
-INTERNAL_HTML_FILES = $(TECHNICAL_DESCR_FILES:%.xml=$(HTMLDIR)/%.html)
-
-HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
-
-INFO_FILE = ../../info
-EXTRA_FILES = summary.html.src \
- $(DEFAULT_GIF_FILES) \
- $(DEFAULT_HTML_FILES) \
- $(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html)
-
-MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-
-HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
-
-TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-$(HTMLDIR)/%.gif: %.gif
- $(INSTALL_DATA) $< $@
-
-docs: pdf html man
-
-$(TOP_PDF_FILE): $(XML_FILES)
-
-pdf: $(TOP_PDF_FILE)
-
-html: gifs $(HTML_REF_MAN_FILE)
-
-clean clean_docs:
- rm -rf $(HTMLDIR)/*
- rm -f $(MAN3DIR)/*
- rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
-
-man: $(MAN3_FILES)
-
-gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-
-$(INDEX_TARGET): $(INDEX_SRC)
- sed -e 's;%VSN%;$(VSN);' $(INDEX_SRC) > $(INDEX_TARGET)
-
-debug opt:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_docs_spec: docs
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(HTMLDIR)/* \
- "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
- $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
-
-release_spec:
diff --git a/lib/cosNotification/doc/src/book.gif b/lib/cosNotification/doc/src/book.gif
deleted file mode 100644
index 94b3868792..0000000000
--- a/lib/cosNotification/doc/src/book.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosNotification/doc/src/book.xml b/lib/cosNotification/doc/src/book.xml
deleted file mode 100644
index 3151abceaa..0000000000
--- a/lib/cosNotification/doc/src/book.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book xmlns:xi="http://www.w3.org/2001/XInclude">
- <header titlestyle="normal">
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosNotification</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-01-31</date>
- <rev>1.0</rev>
- </header>
- <insidecover>
- </insidecover>
- <pagetext>cosNotification</pagetext>
- <preamble>
- <contents level="2"></contents>
- </preamble>
- <parts lift="no">
- <xi:include href="part.xml"/>
- </parts>
- <applications>
- <xi:include href="ref_man.xml"/>
- </applications>
- <releasenotes>
- <xi:include href="notes.xml"/>
- </releasenotes>
- <listofterms></listofterms>
- <index></index>
-</book>
-
diff --git a/lib/cosNotification/doc/src/ch_BNF.xml b/lib/cosNotification/doc/src/ch_BNF.xml
deleted file mode 100644
index 9763c0c4ca..0000000000
--- a/lib/cosNotification/doc/src/ch_BNF.xml
+++ /dev/null
@@ -1,457 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Filters and the Constraint Language BNF</title>
- <prepared></prepared>
- <docno></docno>
- <date>2000-04-13</date>
- <rev></rev>
- <file>ch_BNF.xml</file>
- </header>
-
- <section>
- <title>Filters and the Constraint Language BNF</title>
- <p>This chapter describes, the grammar supported by
- <seealso marker="CosNotifyFilter_Filter">CosNotifyFilter_Filter</seealso> and
- <seealso marker="CosNotifyFilter_MappingFilter">CosNotifyFilter_MappingFilter</seealso>,
- and how to create and use filter objects.
- </p>
-
- <section>
- <title>How to create filter objects</title>
- <p>To be able to filter events we must create a filter and associate
- it with one, or more, of the administrative or proxy objects. In the example
- below, we choose to associate the filter with a ConsumerAdmin object.</p>
- <code type="none">
-FilterFactory = cosNotificationApp:start_filter_factory(),
-Filter = 'CosNotifyFilter_FilterFactory':
- create_filter(FilterFactory,"EXTENDED_TCL"),
-ConstraintInfoSeq = 'CosNotifyFilter_Filter':
- add_constraints(Filter, ConstraintExpSeq),
-FilterID = 'CosNotifyChannelAdmin_ConsumerAdmin':
- add_filter(AdminConsumer, Filter),
- </code>
- <p><c>"EXTENDED_TCL"</c> is the only grammar supported by Orber Notification
- Service.</p>
- <p>Depending on which operation type the Admin object uses, i.e.,
- <c>'AND_OP'</c> or <c>'OR_OP'</c>, events will be tested using the
- associated filter. The operation properties are:</p>
- <p></p>
- <list type="bulleted">
- <item>
- <p>'AND_OP' - must be approved by the proxy's <em>and</em> its parent admin's
- filters. If all filters associated with an object (Admin or Proxy)
- return false the event will be discarded. In this situation it is pointless
- to try and verify with the other object's associated filters since the outcome
- still would be the same.</p>
- </item>
- <item>
- <p>'OR_OP' - if one of the object's (Admin or Proxy) filters return true, the event
- will not be checked against any other filter associated with a proxy or its
- parent admin. If a object's associated filters all return false,
- the event will be forwarded to related proxies/admins, and
- tested against any associated filters.</p>
- </item>
- </list>
- <p>Initially, filters are empty and will always return true. Hence, we must
- add constraints by using <c>'CosNotifyFilter_Filter':add_constraints/2</c>.
- As input, the second argument must be a sequence of:</p>
- <code type="none">
-#'CosNotifyFilter_ConstraintExp'{
- event_types = [#'CosNotification_EventType'{
- domain_name = string(),
- type_name = string()}],
- constraint_expr = string()}
- </code>
- <p>The <c>event_types</c> describes which types of events that should be matched using
- the associated <c>constraint_expr</c>.</p>
- <p>If a constraint expression is supposed to apply for all events, then the <c>type_name</c> can
- be set to the special event type <c>%ALL</c> in a constraint's event type sequence. The
- <c>domain_name</c> should be <c>""</c> or <c>"*"</c>.</p>
- <p>In the following sections we will take a closer look on how to write
- constraint expressions.</p>
- </section>
-
- <section>
- <title>The CosNotification Constraint Language</title>
- <p>The constraint language supported by the Notification Service is:</p>
- <code type="none"><![CDATA[
-<constraint> := /* empty */
- | <bool>
-
-<bool> := <bool_or>
-
-<bool_or> := <bool_or> or <bool_and>
- | <bool_and>
-
-<bool_and> := <bool_and> and <bool_compare>
- | <bool_compare>
-
-<bool_compare> := <expr_in> == <expr_in>
- | <expr_in> != <expr_in>
- | <expr_in> < <expr_in>
- | <expr_in> <= <expr_in>
- | <expr_in> > <expr_in>
- | <expr_in> >= <expr_in>
- | <expr_in>
-
-<expr_in> := <expr_twiddle> in <Ident> /* sequence only */
- | <expr_twiddle>
- | <expr_twiddle> in $ <Component> /* sequence only */
-
-<expr_twiddle> := <expr> ~ <expr> /* string data types only */
- | <expr>
-
-<expr> := <expr> + <term>
- | <expr> - <term>
- | <term>
-
-<term> := <term> * <factor_not>
- | <term> / <factor_not>
- | <factor_not>
-
-<factor_not> := not <factor>
- | <factor>
-
-<factor> := ( <bool_or> )
- | exist <Ident>
- | <Ident>
- | <Number>
- | - <Number>
- | <String>
- | TRUE
- | FALSE
- | + <Number>
- | exist $ <Component>
- | $ <Component>
- | default $ <Component> /* discriminated unions only */
-
-<Component> := /* empty */
- | . <CompDot>
- | <CompArray>
- | <CompAssoc>
- | <Ident> <CompExt> /* run-time variable */
-
-<CompExt> := /* empty */
- | . <CompDot>
- | <CompArray>
- | <CompAssoc>
-
-<CompDot> := <Ident> <CompExt>
- | <CompPos>
- | <UnionPos>
- | _length /* only valid for arrays or sequences */
- | _d /* discriminated unions only */
- | _type_id /* only valid if possible to obtain */
- | _repos_id /* only valid if possible to obtain */
-
-<CompArray> := [ <Digits> ] <CompExt>
-
-<CompAssoc> := ( <Ident> ) <CompExt>
-
-<CompPos> := <Digits> <CompExt>
-
-<UnionPos> := ( <UnionVal> ) <CompExt>
-
-<UnionVal> := /* empty */
- | <Digits>
- | - <Digits>
- | + <Digits>
- | <String>
-
-/* Character set issues */
-<Ident> :=<Leader> <FollowSeq>
- | \ < Leader> <FollowSeq>
-
-<FollowSeq> := /* <empty> */
- | <FollowSeq> <Follow>
-
-<Number> := <Mantissa>
- | <Mantissa> <Exponent>
-
-<Mantissa> := <Digits>
- | <Digits> .
- | . <Digits>
- | <Digits> . <Digits>
-
-<Exponent> := <Exp> <Sign> <Digits>
-
-<Sign> := +
- | -
-
-<Exp> := E
- | e
-
-<Digits> := <Digits> <Digit>
- | <Digit>
-
-<String> := ' <TextChars> '
-
-<TextChars> := /* <empty> */
- | <TextChars> <TextChar>
-
-<TextChar> := <Alpha>
- | <Digit>
- | <Other>
- | <Special>
-
-<Special> := \\
- | \'
-
-<Leader> := <Alpha>
-
-<Follow> := <Alpha>
- | <Digit>
- | _
-
-<Alpha> is the set of alphabetic characters [A-Za-z]
-<Digit> is the set of digits [0-9]
-<Other> is the set of ASCII characters that are not <Alpha>, <Digit>, or <Special>
- ]]></code>
- <p>In the absence of parentheses, the following precedence relations hold :</p>
- <list type="ordered">
- <item><c>()</c>, <c>exist</c>, <c>default</c>, <c>unary-sign</c></item>
- <item><c>not</c></item>
- <item><c>*</c>, <c>/</c></item>
- <item><c>+</c>, <c>-</c></item>
- <item><c>~</c></item>
- <item><c>in</c></item>
- <item><c>==</c>, <c>!=</c>, <c><![CDATA[<]]></c>, <c><![CDATA[<=]]></c>, <c>></c>, <c>>=</c></item>
- <item><c>and</c></item>
- <item><c>or</c></item>
- </list>
- </section>
-
- <section>
- <title>The Constraint Language Data Types</title>
- <p>The Notification Service Constraint Language, defines how to write
- constraint expressions, which can be used to filter events. The
- representation does, however, differ slightly from ordinary Erlang terms.</p>
- <p>When creating a <c>ConstraintExp</c>, the field <c>constraint_expr</c> must be
- set to contain a string, e.g., <c><![CDATA["1 < 2"]]></c>. The Notification Service Constraint
- Language, is designed to be able to filter structured and unstructured events
- using the same constraint expression. The Constraint Language Types and Operations
- can be divided into two sub-groups:</p>
- <list type="bulleted">
- <item>
- <p>Basic - arithmetics, strings, constants, numbers etc.</p>
- </item>
- <item>
- <p>Complex - accessing members of complex data types, such as unions.</p>
- </item>
- </list>
- <p>Some of the basic types, e.g., integer, are self explanatory. Hence, they are not described further.</p>
- <table>
- <row>
- <cell align="center" valign="middle"><em>Type/Operation</em></cell>
- <cell align="center" valign="middle"><em>Examples</em></cell>
- <cell align="center" valign="middle"><em>Description</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle"><c>string</c></cell>
- <cell align="left" valign="middle"><c>"'MyString'"</c></cell>
- <cell align="left" valign="middle">Strings are represented as a sequence of zero or more <c><![CDATA[<TextChar>]]></c>s enclosed in single quotes, e.g., <c>'string'</c>.</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><c>~</c></cell>
- <cell align="left" valign="middle"><c>"'Sring1' ~ 'String2'"</c></cell>
- <cell align="left" valign="middle">The operator <c>~</c>is called the substring operator and mean "String1 is contained within String2".</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><c>boolean</c></cell>
- <cell align="left" valign="middle"><c>"TRUE == (('lang' ~ 'Erlang' + 'fun' ~ 'functional') >= 2)"</c></cell>
- <cell align="left" valign="middle">Booleans may only be TRUE or FALSE, i.e., only capital letters. Expressions which evaluate to TRUE or FALSE can be summed up and matched, where TRUE equals 1 and FALSE 0.</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><c>sequence</c></cell>
- <cell align="left" valign="middle"><c>"myIntegerSequence[2]"</c></cell>
- <cell align="left" valign="middle">The BNF use C/C++ notation, i.e., the example will return the <em>third</em>element.</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><c>_length</c></cell>
- <cell align="left" valign="middle"><c>"myIntegerSequence._length"</c></cell>
- <cell align="left" valign="middle">Returns the length of an sequence or array.</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><c>in</c></cell>
- <cell align="left" valign="middle"><c>"'Erlang' in $.FunctionalLanguagesStringSeq"</c></cell>
- <cell align="left" valign="middle">Returns <c>TRUE</c>if a given element is found in the given sequence. The element must be of a simple type and the same as the sequence is defined to contain.</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><c>$</c></cell>
- <cell align="left" valign="middle"><c>"$ == 40"</c></cell>
- <cell align="left" valign="middle">Denote the current event as well as any run-time variables. If the event is unstructured and its contained value 40, the example will return <c>TRUE</c>.</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><c>.</c></cell>
- <cell align="left" valign="middle"><c>"$.MyStructMember == 40"</c></cell>
- <cell align="left" valign="middle">The structure member operator <c>.</c>may be used to reference its members when the data refers to a named structure, discriminated union, or CORBA::Any data structure.</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><c>_type_id</c></cell>
- <cell align="left" valign="middle"><c>"$._type_id == 'MyStruct'"</c></cell>
- <cell align="left" valign="middle">Returns the unscoped IDL type name of the component. This operation is only valid if said information can be obtained.</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><c>_repos_id</c></cell>
- <cell align="left" valign="middle"><c>"$._repos_id == 'IDL:MyModule/MyStruct:1.0'"</c></cell>
- <cell align="left" valign="middle">Returns the RepositoryId of the component. This operation is only valid if said information can be obtained.</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><c>_d</c></cell>
- <cell align="left" valign="middle"><c>"$.eventUnion._d"</c></cell>
- <cell align="left" valign="middle">May only be used when accessing discriminated unions and refers to the discriminator.</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><c>exist</c></cell>
- <cell align="left" valign="middle"><c>"exist $.eventUnion._d and $.eventUnion._d == 10"</c></cell>
- <cell align="left" valign="middle">To avoid that a filtering of an event fails due to that, for example, we try to compare a union discriminator which does not exist, we can use this operator.</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><c>default</c></cell>
- <cell align="left" valign="middle"><c>"default $.eventUnion._d"</c></cell>
- <cell align="left" valign="middle">If the <c>_d</c>operation is in conjunction with the <c>default</c>operation, TRUE will be returned if the union has a default member that is active.</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><c>union</c></cell>
- <cell align="left" valign="middle"><c>"$.(0) == 5"</c>eq. <c>"$.('zero') == 5"</c></cell>
- <cell align="left" valign="middle">When the component refers to a union, with one of the cases defined as <c>case 0: short zero;</c>, we use <c>0</c>or <c>'zero'</c>. The result of the example is <c>TRUE</c>if the union has a discriminator set to <c>0</c>and the value <c>5</c>. If more than one case is defined to be<c>'zero'</c>, <c>$.('zero')</c>accepts both; <c>$.(0)</c>only returns <c>TRUE</c>if the discriminator is set to <c>0</c>. Leaving out the identifier, i.e., <c>$.()</c>, refers to the default value.</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><c>name-value pairs</c></cell>
- <cell align="left" valign="middle"><c>"$.NameValueSeq('myID') == 5"</c>eq.<c>"$.NameValueSeq[1].name == 'myID' and $.NameValueSeq[1].value == 5"</c></cell>
- <cell align="left" valign="middle">The Notification service makes extensive use of <c>name-value pairs</c>sequences within structured events, which allow us to via the identifier <c>name</c>access its <c>value</c>, as shown in the example.</cell>
- </row>
- <tcaption>Table 1: Type and Operator Examples</tcaption>
- </table>
- <p>In the next section we will take a closer look at how it is possible to write constraints using
- different types of notation etc.</p>
- </section>
-
- <section>
- <title>Accessing Data In Events</title>
- <p>To filter events, the supplied constraints must describe the contents of
- the events and desired values. We can, for example, state that we are only
- interested in receiving events which are of type <em>CommunicationsAlarm</em>.
- To be able to achieve this, the constraint must contain information
- that points out which fields to compare with. Figure one illustrates a conceptual overview of a
- structured event. The exact definition is found in the <c>CosNotification.idl</c> file.</p>
- <marker id="eventstructure"></marker>
- <image file="eventstructure.gif">
- <icaption>
-Figure 1: The structure of a structured event.</icaption>
- </image>
- <p>The Notification Service supports different constraint expressions
- notation:</p>
- <list type="bulleted">
- <item>
- <p>Fully scoped, e.g., "$.header.fixed_header.event_type.type_name == 'CommunicationsAlarm'"</p>
- </item>
- <item>
- <p>Short hand, e.g., "$type_name == 'CommunicationsAlarm'"</p>
- </item>
- <item>
- <p>Positional Notation, e.g., "$.0.0.0.1 == 'CommunicationsAlarm'"</p>
- </item>
- </list>
- <note>
- <p>Which notation to use is up to the user, however, the fully scoped may
- be easier to understand, but in some cases, if received from an ORB that do not populate ID:s of
- named parts, the positional notation is the only option.</p>
- </note>
- <note>
- <p>If a constraint, which access fields in a structured event structure,
- is supposed to handle unstructured events as well, the CORBA::Any must contain
- the same type of members.</p>
- </note>
- <p>How to filter against the fixed header fields, is described in the
- table below.</p>
- <table>
- <row>
- <cell align="center" valign="middle">Field</cell>
- <cell align="center" valign="middle">Fully Scoped Constraint</cell>
- <cell align="center" valign="middle">Short Hand Constraint</cell>
- </row>
- <row>
- <cell align="left" valign="middle">type_name</cell>
- <cell align="left" valign="middle">"$.header.fixed_header.event_type.type_name == 'Type'"</cell>
- <cell align="left" valign="middle">"$type_name == 'Type'"</cell>
- </row>
- <row>
- <cell align="left" valign="middle">domain_name</cell>
- <cell align="left" valign="middle">"$.header.fixed_header.event_type.domain_name == 'Domain'"</cell>
- <cell align="left" valign="middle">"$domain_name == 'Domain'"</cell>
- </row>
- <row>
- <cell align="left" valign="middle">event_name</cell>
- <cell align="left" valign="middle">"$.header.fixed_header.event_name == 'Event'"</cell>
- <cell align="left" valign="middle">"$event_name == 'Event'"</cell>
- </row>
- <tcaption>Table 2: Fixed Header Constraint Examples</tcaption>
- </table>
- <p>If we are only interested in receiving events regarding 'Domain', 'Event'
- and 'Type', the constraint can look like
- <c>"$domain_name == 'Domain' and $event_name == 'Event' and $type_name == 'Type'"</c>.</p>
- <p>The variable event header consists of a sequence of <em>name-value pairs</em>. One way to filter on these are to use a constraint that looks
- like <c>"($.header.variable_header[1].name == 'priority' and $.header.variable_header[1].value > 0)"</c>. An easier way to
- accomplish the same result is to use a constraint that treats the name-value
- pair as an associative array, i.e., when given a name the corresponding
- value is returned. Hence, instead we can use
- <c>"$.header.variable_header(priority) > 0"</c>.</p>
- <p>Accessing the event body is done in the same way as for the event header
- fields. The user must, however, be aware of, that if a run-time variable
- (<c>$variable</c>) is used data in the event header may take precedence.
- The order of precedence is:</p>
- <list type="ordered">
- <item>Reserved, e.g., <c>$curtime</c></item>
- <item>A simple-typed member of <c>$.header.fixed_header</c>.</item>
- <item>Properties in <c>$.header.variable_header</c>.</item>
- <item>Properties in <c>$.filterable_data</c>.</item>
- <item>If no match is found it is translated to <c>$.variable</c>.</item>
- </list>
- </section>
-
- <section>
- <title>Mapping Filters</title>
- <p>Mapping Filters may only be associated with Consumer Administrators or Proxy
- Suppliers. The purpose of a Mapping Filter is to override Quality of Service
- settings.</p>
- <p>Initially, Mapping Filters are empty and will always return true. Hence, we must
- add constraints by using <c>'CosNotifyFilter_MappingFilter':add_mapping_constraints/2</c>.
- If a constraint matches, the associated value will be used instead of the
- related Quality of Service system settings.</p>
- <p>As input, the second argument must be a sequence of:</p>
- <code type="none">
-#'CosNotifyFilter_MappingConstraintPair'{
- constraint_expression = #'CosNotifyFilter_ConstraintExp'{
- event_types = [#'CosNotification_EventType'{
- domain_name = string(),
- type_name = string()}],
- constraint_expr = string()},
- result_to_set = any()}
- </code>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosNotification/doc/src/ch_QoS.xml b/lib/cosNotification/doc/src/ch_QoS.xml
deleted file mode 100644
index 7f7a26f69a..0000000000
--- a/lib/cosNotification/doc/src/ch_QoS.xml
+++ /dev/null
@@ -1,252 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Quality Of Service and Admin Properties</title>
- <prepared></prepared>
- <docno></docno>
- <date>2000-05-29</date>
- <rev></rev>
- <file>ch_QoS.xml</file>
- </header>
-
- <section>
- <title>Quality Of Service and Admin Properties</title>
- <p>This chapter explains the allowed properties for
- <seealso marker="CosNotification_QoSAdmin">CosNotification_QoSAdmin</seealso> and
- <seealso marker="CosNotification_AdminPropertiesAdmin">CosNotification_AdminPropertiesAdmin</seealso>.
- </p>
-
- <section>
- <title>Quality Of Service</title>
- <p>The cosNotification application supports the following QoS settings:</p>
- <table>
- <row>
- <cell align="center" valign="middle"><em>QoS</em></cell>
- <cell align="center" valign="middle"><em>Range</em></cell>
- <cell align="center" valign="middle"><em>Default</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">EventReliability</cell>
- <cell align="left" valign="middle">BestEffort/Persistent</cell>
- <cell align="left" valign="middle">BestEffort</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ConnectionReliability</cell>
- <cell align="left" valign="middle">BestEffort/Persistent</cell>
- <cell align="left" valign="middle">BestEffort</cell>
- </row>
- <row>
- <cell align="left" valign="middle">Priority</cell>
- <cell align="left" valign="middle">+/-32767</cell>
- <cell align="left" valign="middle">0</cell>
- </row>
- <row>
- <cell align="left" valign="middle">OrderPolicy</cell>
- <cell align="left" valign="middle">Any-, Fifo-, Priority- and Deadline-Order</cell>
- <cell align="left" valign="middle">PriorityOrder</cell>
- </row>
- <row>
- <cell align="left" valign="middle">DiscardPolicy</cell>
- <cell align="left" valign="middle">RejectNewEvents, Any-, Fifo-, Lifo-, Priority- and Deadline-Order</cell>
- <cell align="left" valign="middle">RejectNewEvents</cell>
- </row>
- <row>
- <cell align="left" valign="middle">MaximumBatchSize</cell>
- <cell align="left" valign="middle">long() > 0</cell>
- <cell align="left" valign="middle">1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">PacingInterval</cell>
- <cell align="left" valign="middle">TimeBase::TimeT (see cosTime)</cell>
- <cell align="left" valign="middle">0</cell>
- </row>
- <row>
- <cell align="left" valign="middle">StartTimeSupported</cell>
- <cell align="left" valign="middle">boolean</cell>
- <cell align="left" valign="middle">false</cell>
- </row>
- <row>
- <cell align="left" valign="middle">StopTimeSupported</cell>
- <cell align="left" valign="middle">boolean</cell>
- <cell align="left" valign="middle">false</cell>
- </row>
- <row>
- <cell align="left" valign="middle">MaxEventsPerConsumer</cell>
- <cell align="left" valign="middle">long() > 0</cell>
- <cell align="left" valign="middle">100</cell>
- </row>
- <row>
- <cell align="left" valign="middle">Timeout</cell>
- <cell align="left" valign="middle">TimeBase::TimeT (see cosTime)</cell>
- <cell align="left" valign="middle">No timeout</cell>
- </row>
- <tcaption>Table 1: Supported QoS Settings</tcaption>
- </table>
- <br></br>
- <br></br>
- <br></br>
- <br></br>
- <p><em>Comments on the table 'Supported QoS Settings':</em></p>
- <taglist>
- <tag><em>EventReliability</em></tag>
- <item>To allow full Persistent EventReliability, every event must
- be stored in a stable storage which would create a relatively
- huge overhead. Hence, only lightweight version of the Persistent
- QoS is supported. The configuration parameters <c>max_events</c>,
- <c>interval_events</c> and <c>timeout_events</c> determine
- the behavior of this setting.</item>
- <tag><em>ConnectionReliability</em></tag>
- <item>If this QoS is set to BestEffort and a client object returns anything
- other than <c>ok</c> to its associated Proxy, the Proxy will discard
- all events and terminate. Using Persistent and anything other than <c>ok</c>
- is returned, events will be dropped but the proxy will retry later when
- next delivery is due. A child may not have Persistent while its parent
- has BestEffort QoS set, e.g., Proxy vs. Admin. If <c>OBJECT_NOT_EXIST</c>,
- <c>NO_PERMISSION</c> or <c>CosEventComm_Disconnected</c> is thrown,
- the associated object will terminate even if this parameter is
- set to Persistent.</item>
- <tag><em>Priority</em></tag>
- <item>This QoS will treat all events as if they have the Priority equal to
- current value, unless the event itself contains a Priority setting,
- this event will be treated accordingly. Note: for this property to
- have any effect, the DiscardPolicy and/or OrderPolicy must be set
- to PriorityOrder.</item>
- <tag><em>OrderPolicy</em></tag>
- <item>If set to PriorityOrder, events with the highest Priority will be
- delivered first. Deadline order will forward events with shortest
- expiry time first. If two events have the same priority, they will be
- delivered in FIFO-order.</item>
- <tag><em>DiscardPolicy</em></tag>
- <item>If set to PriorityOrder and MaxEventsPerConsumer limit is
- reached, events
- with the lowest Priority will be discarded first. Deadline order will
- discard events with shortest expiry time first.</item>
- <tag><em>MaximumBatchSize</em></tag>
- <item>Only valid if the object is supposed to handle a sequence of structured
- events and determines the largest amount of events that may be passed
- each time.</item>
- <tag><em>PacingInterval</em></tag>
- <item>Determines how long an object will wait before forwarding a structured
- event sequence of length equal to, or less than MaximumBatchSize.
- If set to 0, which is the default behavior, no timeout is used and
- the events are forwarded when the MaximumBatchSize is reached.</item>
- <tag><em>StartTimeSupported</em></tag>
- <item>If set to true events which contains the QoS Property <c>StartTime</c>
- (TimeBase::UtcT - absolute time) will not be delivered until the
- StartTime value have been exceeded. See also the <c>cosTime</c> application.</item>
- <tag><em>StopTimeSupported</em></tag>
- <item>If set to true, events which contain the QoS Properties <c>StopTime</c>
- (TimeBase::UtcT - absolute time) or <c>Timeout</c> (TimeBase::TimeT -
- relative time) will be discarded if the object has not been able to
- deliver the event in time. See also the <c>cosTime</c> application.</item>
- <tag><em>MaxEventsPerConsumer</em></tag>
- <item>The maximum number of events the associated object may store before discarding
- events in the way described by the DiscardPolicy.</item>
- <tag><em>Timeout</em></tag>
- <item>If this QoS property is not included in the event, and the Property
- <c>StopTimeSupported</c> equals true, this setting will be applied
- if events cannot be delivered within its time limit.</item>
- </taglist>
- <warning>
- <p>Several of the above QoS Properties can be changed during run-time but we strongly advice
- not to since, if a relatively large amount of events are waiting for delivery, some of the
- QoS settings would require a total reorder of the events. The QoS property <c>ConnectioReliability</c>
- may <em>never</em> be updated during run-time since it may cause deadlock. Run-time, in this case,
- means activating the Channel by sending the first event.</p>
- </warning>
- </section>
-
- <section>
- <title>Setting Quality Of Service</title>
- <p>Assume we have a Consumer Admin object which we want to change
- the current Quality of Service. Typical usage:</p>
- <code type="none">
-QoSPersistent =
- [#'CosNotification_Property'
- {name='CosNotification':'ConnectionReliability'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'Persistent'())}],
-'CosNotification_QoSAdmin':set_qos(Ch, QoSPersistent),
- </code>
- <p>If it is not possible to set the requested QoS the <c>UnsupportedQoS</c>
- exception is raised, which includes a sequence of <c>PropertyError</c>'s
- describing which QoS, possible range and why is not allowed. The error
- codes are:</p>
- <list type="bulleted">
- <item>UNSUPPORTED_PROPERTY - QoS not supported for this type of target object.</item>
- <item>UNAVAILABLE_PROPERTY - due to current QoS settings the given property
- is not allowed.</item>
- <item>UNSUPPORTED_VALUE - property value out of range; valid range is returned.</item>
- <item>UNAVAILABLE_VALUE - due to current QoS settings the given value is
- not allowed; valid range is returned.</item>
- <item>BAD_PROPERTY - unrecognized property.</item>
- <item>BAD_TYPE - type of supplied property is incorrect.</item>
- <item>BAD_VALUE - illegal value.</item>
- </list>
- <p>The CosNotification_QoSAdmin interface also supports an operation
- called <c>validate_qos/2</c>. The purpose of this operations is to check
- if a QoS setting is supported by the target object and if so, the operation
- returns additional properties which could be optionally added as well.</p>
- </section>
-
- <section>
- <title>Admin Properties</title>
- <p>The cosNotification application supports the following Admin Properties:</p>
- <table>
- <row>
- <cell align="center" valign="middle"><em>Property</em></cell>
- <cell align="center" valign="middle"><em>Range</em></cell>
- <cell align="center" valign="middle"><em>Default</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">MaxQueueLength</cell>
- <cell align="left" valign="middle">0</cell>
- <cell align="left" valign="middle">0</cell>
- </row>
- <row>
- <cell align="left" valign="middle">MaxConsumers</cell>
- <cell align="left" valign="middle">long() >= 0</cell>
- <cell align="left" valign="middle">0</cell>
- </row>
- <row>
- <cell align="left" valign="middle">MaxSuppliers</cell>
- <cell align="left" valign="middle">long() >= 0</cell>
- <cell align="left" valign="middle">0</cell>
- </row>
- <tcaption>Table 2: Supported Admin Properties</tcaption>
- </table>
- <p>According to the OMG specification the default values for Admin Properties
- is supposed to be <c>0</c>, which means that no limit applies to these
- properties.</p>
- <note>
- <p>Admin Properties can only be set on a Channel Object level, i.e.,
- they will not have an impact on any Admin or Proxy Objects. Currently,
- setting the Admin Property <c>MaxQueueLength</c> have no effect since
- we cannot discard events accordingly to the Quality of Service Property
- <c>DiscardPolicy</c>.</p>
- </note>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosNotification/doc/src/ch_contents.xml b/lib/cosNotification/doc/src/ch_contents.xml
deleted file mode 100644
index 11014f693b..0000000000
--- a/lib/cosNotification/doc/src/ch_contents.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>The cosNotification Application</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-01-31</date>
- <rev>1.0</rev>
- <file>ch-contents.xml</file>
- </header>
-
- <section>
- <title>Content Overview</title>
- <p>The cosNotification documentation is divided into three sections:
- </p>
- <list type="bulleted">
- <item>
- <p>PART ONE - The User's Guide
- <br></br>
-Description of the cosNotification Application including
- services and a small tutorial demonstrating
- the development of a simple service.</p>
- </item>
- <item>
- <p>PART TWO - Release Notes
- <br></br>
-A concise history of cosNotification.</p>
- </item>
- <item>
- <p>PART THREE - The Reference Manual
- <br></br>
- A quick reference guide, including a
- brief description, to all the functions available in cosNotification.</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Brief Description of the User's Guide</title>
- <p>The User's Guide contains the following parts:</p>
- <list type="bulleted">
- <item>
- <p>cosNotification overview</p>
- </item>
- <item>
- <p>cosNotification installation</p>
- </item>
- <item>
- <p>A tutorial example</p>
- </item>
- </list>
- </section>
-</chapter>
-
diff --git a/lib/cosNotification/doc/src/ch_example.xml b/lib/cosNotification/doc/src/ch_example.xml
deleted file mode 100644
index a86aaccc82..0000000000
--- a/lib/cosNotification/doc/src/ch_example.xml
+++ /dev/null
@@ -1,170 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosNotification Examples</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-01-31</date>
- <rev>A</rev>
- <file>ch_example.xml</file>
- </header>
-
- <section>
- <title>A Tutorial on How to Create a Simple Service</title>
-
- <section>
- <title>Interface Design</title>
- <p>To use the cosNotification application <em>clients</em> must be implemented.
- There are twelve types of clients: </p>
- <list type="bulleted">
- <item>Structured Push Consumer</item>
- <item>Sequence Push Consumer </item>
- <item>Any Push Consumer</item>
- <item>Structured Pull Consumer</item>
- <item>Sequence Pull Consumer</item>
- <item>Any Pull Consumer</item>
- <item>Structured Push Supplier</item>
- <item>Sequence Push Supplier</item>
- <item>Any Push Supplier</item>
- <item>Structured Pull Supplier</item>
- <item>Sequence Pull Supplier</item>
- <item>Any Pull Supplier</item>
- </list>
- <p>The interfaces for these participants are defined in <em>CosNotification.idl</em>
- and <em>CosNotifyComm.idl</em>.</p>
- </section>
-
- <section>
- <title>Generating a Client Interface</title>
- <p>We start by creating an interface which inherits from the correct interface, e.g., <em>CosNotifyComm::SequencePushConsumer</em>. Hence,
- we must also implement all operations defined in the SequencePushConsumer interface. The IDL-file could look like: </p>
- <code type="c"><![CDATA[
-#ifndef _MYCLIENT_IDL
-#define _MYCLIENT_IDL
-#include <CosNotification.idl>
-#include <CosNotifyComm.idl>
-
-module myClientImpl {
-
- interface ownInterface:CosNotifyComm::SequencePushConsumer {
-
- void ownFunctions(in any NeededArguments)
- raises(Systemexceptions,OwnExceptions);
-
- };
-};
-
-#endif
- ]]></code>
- <p>Run the IDL compiler on this file by calling the <c>ic:gen/1</c> function.
- This will produce the API named <c>myClientImpl_ownInterface.erl</c>.
- After generating the API stubs and the server skeletons it is time to
- implement the servers and if no special options are sent
- to the IDl compiler the file name is <c>myClientImpl_ownInterface_impl.erl</c>.</p>
- <p>The callback module must contain the necessary functions inherited from
- <em>CosNotification.idl</em> and <em>CosNotifyComm.idl</em>.</p>
- </section>
-
- <section>
- <title>How to Run Everything</title>
- <p>Below is a short transcript on how to run cosNotification. </p>
- <code type="none">
-
-%% Start Mnesia and Orber
-mnesia:delete_schema([node()]),
-mnesia:create_schema([node()]),
-orber:install([node()]),
-mnesia:start(),
-orber:start(),
-
-%% If cosEvent not installed before it is necessary to do it now.
-cosEventApp:install(),
-
-%% Install cosNotification in the IFR.
-cosNotificationApp:install(30),
-
-%% Register the application specific Client implementations
-%% in the IFR.
-'oe_myClientImpl':'oe_register'(),
-
-%% Start the cosNotification application.
-cosNotificationApp:start(),
-
-%% Start a factory using the default configuration
-ChFac = cosNotificationApp:start_factory(),
-%% ... or use configuration parameters.
-ChFac = cosNotificationApp:start_factory([]),
-
-%% Create a new event channel. Note, if no QoS- anr/or Admin-properties
-%% are supplied (i.e. empty list) the default settings are used.
-{Ch, ChID} = 'CosNotifyChannelAdmin_EventChannelFactory':
- create_channel(ChFac, DefaultQoS, DefaultAdmin),
-
-%% Retrieve a SupplierAdmin and a Consumer Admin.
-{AdminSupplier, ASID}=
- 'CosNotifyChannelAdmin_EventChannel':new_for_suppliers(Ch, 'OR_OP'),
-{AdminConsumer, ACID}=
- 'CosNotifyChannelAdmin_EventChannel':new_for_consumers(Ch,'OR_OP'),
-
-%% Use the corresponding Admin object to get access to wanted Proxies
-
-%% Create a Push Consumer Proxie, i.e., the Client Push Supplier will
-%% push events to this Proxy.
-{StructuredProxyPushConsumer,ID11}= 'CosNotifyChannelAdmin_SupplierAdmin':
- obtain_notification_push_consumer(AdminSupplier, 'STRUCTURED_EVENT')),
-
-%% Create Push Suppliers Proxies, i.e., the Proxy will push events to the
-%% registered Push Consumers.
-{ProxyPushSupplier,I4D}='CosNotifyChannelAdmin_ConsumerAdmin':
- obtain_notification_push_supplier(AdminConsumer, 'ANY_EVENT'),
-{StructuredProxyPushSupplier,ID5}='CosNotifyChannelAdmin_ConsumerAdmin':
- obtain_notification_push_supplier(AdminConsumer, 'STRUCTURED_EVENT'),
-{SequenceProxyPushSupplier,ID6}='CosNotifyChannelAdmin_ConsumerAdmin':
- obtain_notification_push_supplier(AdminConsumer, 'SEQUENCE_EVENT'),
-
-%% Create application Clients. We can, for example, start the Clients
-%% our selves or look them up in the naming service. This is application
-%% specific.
-SupplierClient = ...
-ConsumerClient1 = ...
-ConsumerClient2 = ...
-ConsumerClient3 = ...
-
-%% Connect each Client to corresponding Proxy.
-'CosNotifyChannelAdmin_StructuredProxyPushConsumer':
- connect_structured_push_supplier(StructuredProxyPushConsumer, SupplierClient),
-'CosNotifyChannelAdmin_ProxyPushSupplier':
- connect_any_push_consumer(ProxyPushSupplier, ConsumerClient1),
-'CosNotifyChannelAdmin_StructuredProxyPushSupplier':
- connect_structured_push_consumer(StructuredProxyPushSupplier, ConsumerClient2),
-'CosNotifyChannelAdmin_SequenceProxyPushSupplier':
- connect_sequence_push_consumer(SequenceProxyPushSupplier, ConsumerClient3),
- </code>
- <p>The example above, exemplifies a notification system where the SupplierClient
- in some way generates event and pushes them to the proxy. The push supplier
- proxies will eventually push the events to each ConsumerClient.</p>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosNotification/doc/src/ch_install.xml b/lib/cosNotification/doc/src/ch_install.xml
deleted file mode 100644
index c76c68cb42..0000000000
--- a/lib/cosNotification/doc/src/ch_install.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Installing cosNotification</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-01-31</date>
- <rev></rev>
- <file>ch-install.xml</file>
- </header>
-
- <section>
- <title>Installation Process </title>
- <p>This chapter describes how to install <seealso marker="cosNotificationApp">cosNotificationApp</seealso>
- in an Erlang Environment.
- </p>
-
- <section>
- <title>Preparation</title>
- <p>Before starting the installation process for cosNotification,
- the application Orber must be running.</p>
- </section>
-
- <section>
- <title>Configuration</title>
- <p>When using the Notification Service the <c>cosNotification</c> application
- first must be installed using <c>cosNotificationApp:install()</c> or
- <c>cosNotificationApp:install(Seconds)</c>, followed by <c>cosNotificationApp:start()</c>.</p>
- <p>Then the <seealso marker="CosNotifyChannelAdmin_EventChannelFactory">Event Channel Factory</seealso>
- must be started:</p>
- <list type="bulleted">
- <item><c>cosNotificationApp:start_global_factory()</c> - starts and returns a reference to a factory using default configuration parameters.
- This operation should be used for a multi-node Orber.</item>
- <item><c>cosNotificationApp:start_global_factory(Options)</c> - starts and returns a reference to a factory using given configuration parameters.
- This operation should be used for a multi-node Orber.</item>
- <item><c>cosNotificationApp:start_factory()</c> - starts and returns a reference to a factory using default configuration parameters.</item>
- <item><c>cosNotificationApp:start_factory(Options)</c> - starts and returns a reference to a factory using given configuration parameters.</item>
- </list>
- <p>The following options exist:</p>
- <list type="bulleted">
- <item><c>{pullInterval, Seconds}</c> - determine how often Proxy Pull
- Consumers will check for new events with the client application. The
- default value is 20 seconds.</item>
- <item><c>{filterOp, OperationType}</c> - determine which type of Administrator
- objects should be started, i.e., <c>'OR_OP'</c> or <c>'AND_OP'</c>.
- The default value is <c>'OR_OP'</c>.</item>
- <item><c>{timeService, TimeServiceObj | 'undefined'}</c> - to be able to use
- Start and/or Stop QoS this option must be used. See the function <c>start_time_service/2</c>
- in the <c>cosTime</c> application. The default value is <c>'undefined'</c>.</item>
- <item><c>{filterOp, OperationType}</c> - determine which type of Administrator
- objects should be started, i.e., <c>'OR_OP'</c> or <c>'AND_OP'</c>.
- The default value is <c>'OR_OP'</c>.</item>
- <item><c>{gcTime, Seconds}</c> - this option determines how often, for example, proxies
- will garbage collect expired events. The default value is 60.</item>
- <item><c>{gcLimit, Amount}</c> - determines how many events will be stored before, for
- example, proxies will garbage collect expired events. The default value is 50. This
- option is tightly coupled with the QoS property <c>MaxEventsPerConsumer</c>, i.e.,
- the <c>gcLimit</c> should be less than <c>MaxEventsPerConsumer</c> and greater than 0.</item>
- </list>
- <p>It is possible to define a set of global configuration parameters:</p>
- <table>
- <row>
- <cell align="center" valign="middle"><em>Key</em></cell>
- <cell align="center" valign="middle"><em>Range</em></cell>
- <cell align="center" valign="middle"><em>Default</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">type_check</cell>
- <cell align="left" valign="middle">true | false</cell>
- <cell align="left" valign="middle">true</cell>
- </row>
- <row>
- <cell align="left" valign="middle">notify</cell>
- <cell align="left" valign="middle">atom() | false</cell>
- <cell align="left" valign="middle">false</cell>
- </row>
- <row>
- <cell align="left" valign="middle">max_events</cell>
- <cell align="left" valign="middle">integer() > 0</cell>
- <cell align="left" valign="middle">50</cell>
- </row>
- <row>
- <cell align="left" valign="middle">interval_events</cell>
- <cell align="left" valign="middle">integer() > 0</cell>
- <cell align="left" valign="middle">10000 milliseconds</cell>
- </row>
- <row>
- <cell align="left" valign="middle">timeout_events</cell>
- <cell align="left" valign="middle">integer() > interval_events</cell>
- <cell align="left" valign="middle">3000000 milliseconds</cell>
- </row>
- <tcaption>Global Configuration Parameters</tcaption>
- </table>
- <p><em>Comments on the table 'Global Configuration Parameters':</em></p>
- <taglist>
- <tag><em>type_check</em></tag>
- <item>Determine if supplied IOR:s shall be type checked, i.e. invoking
- corba_object:is_a/2, or not.</item>
- <tag><em>notify</em></tag>
- <item>The given value shall point to an existing module exporting
- a function (arity 1) called <em>terminated</em>. This operation
- is invoked when a proxy terminates and the argument is a list
- containing <c>{proxy, IOR}</c>, <c>{client, IOR}</c> and
- <c>{reason, term()}</c>. The return value is ignored.</item>
- <tag><em>max_events</em></tag>
- <item>If a supplier proxy has not been able to push events to a
- consumer and the queue exceeds this limit, then the proxy will
- terminate. For this option to have any effect, the
- <c>EventReliability</c> and <c>ConnectionReliability</c> QoS
- parameters must be set to <c>Persistent</c>. For more information,
- see also the <seealso marker="ch_QoS">QoS</seealso> chapter.</item>
- <tag><em>interval_events</em></tag>
- <item>The same requirements as for <c>max_events</c>. When a supplier
- proxy detects problems when trying to push events, this parameter
- determines how often it should try to call the consumer.</item>
- <tag><em>timeout_events</em></tag>
- <item>The same requirements as for <c>max_events</c>. If the
- proxy has not been able to contact the consumer and this
- time-limit is reached, then the proxy will terminate.</item>
- </taglist>
- <p>The Factory is now ready to use. For a more detailed description see
- <seealso marker="ch_example">Examples</seealso>.</p>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosNotification/doc/src/ch_introduction.xml b/lib/cosNotification/doc/src/ch_introduction.xml
deleted file mode 100644
index 39cd12f1e6..0000000000
--- a/lib/cosNotification/doc/src/ch_introduction.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Introduction to cosNotification</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-01-31</date>
- <rev></rev>
- <file>ch_introduction.xml</file>
- </header>
-
- <section>
- <title>Overview</title>
- <p>The cosNotification application is a Notification Service compliant with the <url href="http://www.omg.org">OMG</url>
- Notification Service CosNotification.
- </p>
-
- <section>
- <title>Purpose and Dependencies</title>
- <p><em>cosNotification</em> is dependent on <em>Orber-3.1.7</em> or later,
- which provides CORBA functionality in an Erlang environment,
- <em>cosTime-1.0.1</em> or later and IDL-files to be compiled using <em>IC-4.0.4</em> or later.</p>
- </section>
-
- <section>
- <title>Prerequisites</title>
- <p>To fully understand the concepts presented in the
- documentation, it is recommended that the user is familiar
- with distributed programming, CORBA and the Orber application.
- </p>
- <p>Recommended reading includes books recommended by the <em>OMG</em>
- and <em>Open Telecom Platform Documentation Set</em>. It is also
- helpful to have read <em>Concurrent Programming in Erlang</em>.</p>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosNotification/doc/src/ch_system.xml b/lib/cosNotification/doc/src/ch_system.xml
deleted file mode 100644
index 91375088a0..0000000000
--- a/lib/cosNotification/doc/src/ch_system.xml
+++ /dev/null
@@ -1,84 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>The Notification Service Components</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-04-13</date>
- <rev></rev>
- <file>ch_system.xml</file>
- </header>
-
- <section>
- <title>The Notification Service Components</title>
- <p>This chapter describes the Notification Service Components and how they
- interact.</p>
-
- <section>
- <title>Components</title>
- <p>There are seven components in the OMG Notification Service architecture.
- These are described below: </p>
- <marker id="notificationFlow"></marker>
- <image file="notificationFlow.gif">
- <icaption>
-Figure 1: The Notification Service Components.</icaption>
- </image>
- <list type="bulleted">
- <item><em>Event Channel:</em> acts as a factory for Administrator objects.
- Allows clients to set Administrative Properties.</item>
- <item><em>Supplier Administrators:</em> acts as a factory for Proxy Consumers.
- Administrators are started as <c>'AND_OP'-</c> or <c>'OR_OP'-</c>type,
- which determines if events must be validated using both the Administrators
- associated Filter and/or its Proxy children Filters.</item>
- <item><em>Consumer Administrators:</em> acts in the same way as Supplier Administrators
- but handle Proxy Suppliers.</item>
- <item><em>Consumer Proxy:</em> is connected to a client application. Can be
- started as <c>Pull</c> or <c>Push</c> object. If the proxy is Push style
- the client application must push events to the Proxy, otherwise the Proxy is
- supposed to Pull events. The <c>CosNotification::AdminProperties</c> is
- used to set the pacing interval.</item>
- <item><em>Supplier Proxy:</em> Acts in a similar way as the Consumer Proxy, but
- if started as a <c>Push</c> proxy it will push events to the client
- application.</item>
- <item><em>Filters:</em> used to filter events. May be associated with Proxies
- and Administrators.</item>
- <item><em>Mapping Filters:</em> used to override events Quality of Service
- settings. Can only be associated with Consumer Administrators and
- Proxy Suppliers.</item>
- </list>
- <p>When a Proxy is started it is set to accept <c>CORBA::Any</c>,
- <c>CosNotification::StructuredEvent</c> or <c>CosNotification::EventBatch</c>
- (a sequence of structured events).</p>
- <p>If a Proxy is supposed to deliver structured events to a client application
- and receives an <c>CORBA::Any</c> event, the event is converted to a
- structured event with <c>type_name</c> set to <c>"%ANY"</c> and the
- event is stored in <c>remainder_of_body</c>.</p>
- <p>If a Proxy is supposed to deliver <c>CORBA::Any</c> events to a client application
- and receives a structured event, the event is stored in an Any type. The
- Any Type Code will be equal to the <c>CosNotification::StructuredEvent</c>
- Type Code.</p>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosNotification/doc/src/cosNotificationApp.xml b/lib/cosNotification/doc/src/cosNotificationApp.xml
deleted file mode 100644
index 4f662a5dc4..0000000000
--- a/lib/cosNotification/doc/src/cosNotificationApp.xml
+++ /dev/null
@@ -1,309 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosNotificationApp</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2000-01-31</date>
- <rev>PA1</rev>
- </header>
- <module>cosNotificationApp</module>
- <modulesummary>The main module of the cosNotification application.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosNotification/include/*.hrl").</c></p>
- <p>This module contains the functions for starting and stopping the application.</p>
- </description>
- <funcs>
- <func>
- <name>install() -> Return</name>
- <fsummary>Install the cosNotification application</fsummary>
- <type>
- <v>Return = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This operation installs the cosNotification application.</p>
- </desc>
- </func>
- <func>
- <name>install(Seconds) -> Return</name>
- <fsummary>Install the cosNotification application</fsummary>
- <type>
- <v>Return = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This operation installs the cosNotification application using <c>Seconds</c>
- delay between each block, currently 6, of IFR-registrations. This approach
- spreads the IFR database access over a period of time to allow other
- applications to run smother.</p>
- </desc>
- </func>
- <func>
- <name>install_event() -> Return</name>
- <fsummary>Install the necessary cosEvent interfaces</fsummary>
- <type>
- <v>Return = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This operation, which may <em>only</em> be used if it is impossible to
- upgrade to <em>cosEvent-2.0</em> or later, installs the necessary
- cosEvent interfaces. If cosEvent-2.0 is available, use
- <c>cosEventApp:install()</c> instead.</p>
- </desc>
- </func>
- <func>
- <name>install_event(Seconds) -> Return</name>
- <fsummary>Install the necessary cosEvent interfaces</fsummary>
- <type>
- <v>Return = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This operation, which may <em>only</em> be used if it is impossible to
- upgrade to <em>cosEvent-2.0</em> or later, installs the necessary cosEvent
- interfaces using <c>Seconds</c> delay between each block of
- IFR-registrations. If cosEvent-2.0 is available, use
- <c>cosEventApp:install()</c> instead.</p>
- </desc>
- </func>
- <func>
- <name>uninstall() -> Return</name>
- <fsummary>Uninstall the cosNotification application</fsummary>
- <type>
- <v>Return = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This operation uninstalls the cosNotification application.</p>
- </desc>
- </func>
- <func>
- <name>uninstall(Seconds) -> Return</name>
- <fsummary>Uninstall the cosNotification application</fsummary>
- <type>
- <v>Return = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This operation uninstalls the cosNotification application using <c>Seconds</c>
- delay between each block, currently 6, of IFR-unregistrations. This approach
- spreads the IFR database access over a period of time to allow other
- applications to run smother.</p>
- </desc>
- </func>
- <func>
- <name>uninstall_event() -> Return</name>
- <fsummary>Uninstall the inherited cosEvent interfaces</fsummary>
- <type>
- <v>Return = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This operation uninstalls the inherited cosEvent interfaces. If cosEvent
- is in use this function may not be used. This function may only be used if
- <c>cosNotificationApp:install_event/1/2</c> was used. If not, use
- <c>cosEventApp:uninstall()</c> instead.</p>
- </desc>
- </func>
- <func>
- <name>uninstall_event(Seconds) -> Return</name>
- <fsummary>Uninstall the inherited cosEvent interfaces</fsummary>
- <type>
- <v>Return = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This operation uninstalls the inherited cosEvent interfaces, using <c>Seconds</c>
- delay between each block of IFR-unregistrations. If cosEvent
- is in use this function may not be used. This function may only be used if
- <c>cosNotificationApp:install_event/1/2</c> was used. If not, use
- <c>cosEventApp:uninstall()</c> instead.</p>
- </desc>
- </func>
- <func>
- <name>start() -> Return</name>
- <fsummary>Start the cosNotification application</fsummary>
- <type>
- <v>Return = ok | {error, Reason}</v>
- </type>
- <desc>
- <p>This operation starts the cosNotification application.</p>
- </desc>
- </func>
- <func>
- <name>stop() -> Return</name>
- <fsummary>Stop the cosNotification application</fsummary>
- <type>
- <v>Return = ok | {error, Reason}</v>
- </type>
- <desc>
- <p>This operation stops the cosNotification application.</p>
- </desc>
- </func>
- <func>
- <name>start_global_factory() -> ChannelFactory</name>
- <fsummary>Start a global channel factory as default</fsummary>
- <type>
- <v>ChannelFactory = #objref</v>
- </type>
- <desc>
- <p>This operation creates a
- <seealso marker="CosNotifyChannelAdmin_EventChannelFactory">Event Channel Factory</seealso>
- should be used for a multi-node Orber.
- The Factory is used to create a new
- <seealso marker="CosNotifyChannelAdmin_EventChannel">channel</seealso>. </p>
- </desc>
- </func>
- <func>
- <name>start_global_factory(Options) -> ChannelFactory</name>
- <fsummary>Start a global channel factory with options</fsummary>
- <type>
- <v>Options = [Option]</v>
- <v>Option = {pullInterval, Seconds} | {filterOp, Op} | {gcTime, Seconds} | {gcLimit, Anount} | {timeService, #objref}</v>
- <v>ChannelFactory = #objref</v>
- </type>
- <desc>
- <p>This operation creates a
- <seealso marker="CosNotifyChannelAdmin_EventChannelFactory">Event Channel Factory</seealso> and
- should be used for a multi-node Orber.
- The Factory is used to create a new
- <seealso marker="CosNotifyChannelAdmin_EventChannel">channel</seealso>. </p>
- <p></p>
- <list type="bulleted">
- <item><c>{pullInterval, Seconds}</c> - determine how often Proxy Pull
- Consumers will check for new events with the client application. The
- default value is 20 seconds.</item>
- <item><c>{filterOp, OperationType}</c> - determine which type of Administrator
- objects should be started, i.e., <c>'OR_OP'</c> or <c>'AND_OP'</c>.
- The default value is <c>'OR_OP'</c>.</item>
- <item><c>{timeService, TimeServiceObj | 'undefined'}</c> - to be able to use
- Start and/or Stop QoS this option must be used. See the function <c>start_time_service/2</c>
- in the <c>cosTime</c> application. The default value is <c>'undefined'</c>.</item>
- <item><c>{filterOp, OperationType}</c> - determine which type of Administrator
- objects should be started, i.e., <c>'OR_OP'</c> or <c>'AND_OP'</c>.
- The default value is <c>'OR_OP'</c>.</item>
- <item><c>{gcTime, Seconds}</c> - this option determines how often, for example, proxies
- will garbage collect expired events. The default value is 60.</item>
- <item><c>{gcLimit, Amount}</c> - determines how many events will be stored before, for
- example, proxies will garbage collect expired events. The default value is 50. This
- option is tightly coupled with the QoS property <c>MaxEventsPerConsumer</c>, i.e.,
- the <c>gcLimit</c> should be less than <c>MaxEventsPerConsumer</c> and greater than 0.</item>
- </list>
- </desc>
- </func>
- <func>
- <name>start_factory() -> ChannelFactory</name>
- <fsummary>Start a channel factory as default</fsummary>
- <type>
- <v>ChannelFactory = #objref</v>
- </type>
- <desc>
- <p>This operation creates a
- <seealso marker="CosNotifyChannelAdmin_EventChannelFactory">Event Channel Factory</seealso>.
- The Factory is used to create a new
- <seealso marker="CosNotifyChannelAdmin_EventChannel">channel</seealso>. </p>
- </desc>
- </func>
- <func>
- <name>start_factory(Options) -> ChannelFactory</name>
- <fsummary>Start a channel factory with options</fsummary>
- <type>
- <v>Options = [Option]</v>
- <v>Option = {pullInterval, Seconds} | {filterOp, Op} | {gcTime, Seconds} | {gcLimit, Amount} | {timeService, #objref}</v>
- <v>ChannelFactory = #objref</v>
- </type>
- <desc>
- <p>This operation creates a
- <seealso marker="CosNotifyChannelAdmin_EventChannelFactory">Event Channel Factory</seealso>.
- The Factory is used to create a new
- <seealso marker="CosNotifyChannelAdmin_EventChannel">channel</seealso>. </p>
- </desc>
- </func>
- <func>
- <name>stop_factory(ChannelFactory) -> Reply</name>
- <fsummary>Terminate the target object</fsummary>
- <type>
- <v>ChannelFactory = #objref</v>
- <v>Reply = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This operation stop the target channel factory.</p>
- </desc>
- </func>
- <func>
- <name>start_filter_factory() -> FilterFactory</name>
- <fsummary>Start a filter factory</fsummary>
- <type>
- <v>FilterFactory = #objref</v>
- </type>
- <desc>
- <p>This operation creates a
- <seealso marker="CosNotifyFilter_FilterFactory">Filter Factory</seealso>.
- The Factory is used to create a new
- <seealso marker="CosNotifyFilter_Filter">Filter's</seealso> and
- <seealso marker="CosNotifyFilter_MappingFilter">MappingFilter's</seealso>. </p>
- </desc>
- </func>
- <func>
- <name>stop_filter_factory(FilterFactory) -> Reply</name>
- <fsummary>Terminate the target object</fsummary>
- <type>
- <v>FilterFactory = #objref</v>
- <v>Reply = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This operation stop the target filter factory.</p>
- </desc>
- </func>
- <func>
- <name>create_structured_event(Domain, Type, Event, VariableHeader, FilterableBody, BodyRemainder) -> Reply</name>
- <fsummary>Create a structured event</fsummary>
- <type>
- <v>Domain = string()</v>
- <v>Type = string()</v>
- <v>Event = string()</v>
- <v>VariableHeader = [CosNotification::Property]</v>
- <v>FilterableBody = [CosNotification::Property]</v>
- <v>BodyRemainder = #any data-type</v>
- <v>Reply = CosNotification::StructuredEvent | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>An easy way to create a structured event is to use this function.
- Simple typechecks are performed and if one of the arguments is not
- correct a 'BAD_PARAM' exception is thrown.</p>
- </desc>
- </func>
- <func>
- <name>type_check() -> Reply</name>
- <fsummary>Return the value of the configuration parameter type_check</fsummary>
- <type>
- <v>Reply = true | false</v>
- </type>
- <desc>
- <p>This operation returns the value of the configuration parameter
- <c>type_check</c>.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosNotification/doc/src/eventstructure.gif b/lib/cosNotification/doc/src/eventstructure.gif
deleted file mode 100644
index 879c96f980..0000000000
--- a/lib/cosNotification/doc/src/eventstructure.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosNotification/doc/src/fascicules.xml b/lib/cosNotification/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/cosNotification/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/cosNotification/doc/src/notes.gif b/lib/cosNotification/doc/src/notes.gif
deleted file mode 100644
index e000cca26a..0000000000
--- a/lib/cosNotification/doc/src/notes.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosNotification/doc/src/notes.xml b/lib/cosNotification/doc/src/notes.xml
deleted file mode 100644
index 1237000153..0000000000
--- a/lib/cosNotification/doc/src/notes.xml
+++ /dev/null
@@ -1,617 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosNotification Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-01-31</date>
- <rev>A</rev>
- <file>notes.xml</file>
- </header>
-
- <section><title>cosNotification 1.2.2</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Internal changes</p>
- <p>
- Own Id: OTP-13551</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosNotification 1.2.1</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> Suppress Dialyzer warnings. </p>
- <p>
- Own Id: OTP-12862</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosNotification 1.2</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> Remove the usage of erlang:now() from all Corba
- applications and use the new rand module instead of
- random. </p>
- <p>
- Own Id: OTP-12687</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosNotification 1.1.21</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> The default encoding of Erlang files has been changed
- from ISO-8859-1 to UTF-8. </p> <p> The encoding of XML
- files has also been changed to UTF-8. </p>
- <p>
- Own Id: OTP-10907</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosNotification 1.1.20</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> Postscript files no longer needed for the generation
- of PDF files have been removed. </p>
- <p>
- Own Id: OTP-11016</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosNotification 1.1.19</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Misc build updates</p>
- <p>
- Own Id: OTP-10784</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosNotification 1.1.18</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>Erlang/OTP can now be built using parallel make if you
- limit the number of jobs, for instance using '<c>make
- -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
- work at the moment because of some missing
- dependencies.</p>
- <p>
- Own Id: OTP-9451</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosNotification 1.1.17</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Removed superfluous usage of shy in the documentation since it can cause problem if
- a buggy tool is used.</p>
- <p>
- Own Id: OTP-9319 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section><title>cosNotification 1.1.16</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Eliminated Dialyzer warnings when using exit or throw.</p>
- <p>
- Own Id: OTP-9050</p>
- </item>
- </list>
- </section>
-</section>
-
- <section><title>cosNotification 1.1.15</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Switched from using the deprecated regexp to re instead.</p>
- <p>
- Own Id: OTP-8846</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section>
- <title>cosNotification 1.1.14</title>
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Test suites published.</p>
- <p>
- Own Id: OTP-8543 Aux Id:</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>Added missing trailing bracket to define in hrl-file.</p>
- <p>Own Id: OTP-8489 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.1.14</title>
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Test suites published.</p>
- <p>
- Own Id: OTP-8543 Aux Id:</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>Added missing trailing bracket to define in hrl-file.</p>
- <p>Own id: OTP-8489 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.1.13</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>Removed superfluous VT in the documentation.</p>
- <p>Own Id: OTP-8353 Aux Id:</p>
- </item>
- <item>
- <p>Removed superfluous backslash in the documentation.</p>
- <p>Own Id: OTP-8354 Aux Id:</p>
- </item>
- <item>
- <p>The documentation EIX file was not generated.</p>
- <p>Own Id: OTP-8355 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.1.12</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- The documentation is now built with open source tools (xsltproc and fop)
- that exists on most platforms. One visible change is that the frames are removed.</p>
- <p>
- Own Id: OTP-8201 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.1.11</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Obsolete guards, e.g. record vs is_record, has been changed
- to avoid compiler warnings.</p>
- <p>Own Id: OTP-7987</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.1.10</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>Updated file headers.</p>
- <p>Own Id: OTP-7837 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.1.9</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>Documentation source included in open source releases.</p>
- <p>Own Id: OTP-7595 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.1.8</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The CosNotification proxy objects ignored the gcLimit option, instead
- the gcTime value was used.</p>
- <p>Own Id: OTP-7553 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.1.7</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Updated file headers.</p>
- <p>Own Id: OTP-7011</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.1.6</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The documentation source has been converted from SGML to XML.</p>
- <p>Own Id: OTP-6754</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.1.5</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Minor Makefile changes.</p>
- <p>Own Id: OTP-6701</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.1.4</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Removed some unused code.</p>
- <p>Own Id: OTP-6527</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.1.3</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>A user can now define the QoS EventReliability to be
- Persistent. Note, this is only a lightweight version
- and events will be lost if a proxy is terminated.</p>
- <p>Own Id: OTP-5923</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.1.2</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Possible to configure cosNotification not to type check,
- by invoking corba_object:is_a/2, supplied IOR:s. When
- a type check fails, the feedback has been improved.</p>
- <p>Own Id: OTP-5823 Aux Id: seq10143</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.1.1</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The app-file contained duplicated modules.</p>
- <p>Own Id: OTP-4976</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The stub/skeleton-files generated by IC have been improved,
- i.e., depending on the IDL-files, reduced the size of the
- erl- and beam-files and decreased dependencies off Orber's
- Interface Repository. It is necessary to re-compile all IDL-files
- and use COS-applications, including Orber, compiled with
- IC-4.2.</p>
- <p>Own Id: OTP-4576</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.0.6</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The exception CosNotifyFilter::InvalidValue, raised by the operation
- CosNotifyFilter::MappingFilter::add_mapping_constraints, did not contain
- correct data in the body. Hence, it was not possible to pass this
- exception to another ORB.</p>
- <p>Own Id: OTP-4412</p>
- </item>
- <item>
- <p>It was not possible to set the QoS property PacingInterval to zero and
- the default value was not compliant with the OMG specification. The
- default value for MaximumBatchSize have also been changed du to the
- same reason.</p>
- <p>Own Id: OTP-4413, OTP-4414</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <list type="bulleted">
- <item>
- <p>The default value, for the QoS properties PacingInterval and MaximumBatchSize,
- have been changed to zero (i.e. no timeout) and 1 respectively, which is
- compliant with the OMG specification.</p>
- <p>Own Id: OTP-4413, OTP-4414</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.0.5</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>If one tries to set an unavailable/incorrect property or property value, an
- exception is thrown. In some cases the exception was not correct, which
- would cause problems if communicating via IIOP.</p>
- <p>Own Id: OTP-4340</p>
- </item>
- <item>
- <p>When using Filter's, with the QoS OrderPolicy set to FifoOrder,
- and passing a sequence of structured events, they could be
- delivered in the wrong order.</p>
- <p>Own Id: OTP-4272</p>
- </item>
- <item>
- <p>If Filter's where attached to Supplier proxies it could cause
- the Proxy to terminate.</p>
- <p>Own Id: OTP-4272</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.0.4</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>When passing event sequences, the PushSuppliers and PullSuppliers
- could crash if the objects had Filter objects associated and
- only a subset of the sequences where approved. </p>
- <p>Own Id: OTP-4099</p>
- </item>
- <item>
- <p>SupplierAdmin's did not filter any events, even though Filter objects
- had been attached to the SupplierAdmin.</p>
- <p>Own Id: OTP-4098</p>
- </item>
- <item>
- <p>If one used the '_get_default_supplier_admin'/1, exported by the
- CosNotifyChannelAdmin_EventChannel-module, it resulted in a loop
- which overloaded the channel. This is no longer the case.</p>
- <p>Own Id: OTP-4086</p>
- </item>
- <item>
- <p>If one used the '_get_default_filter_factory'/1, exported by the
- CosNotifyChannelAdmin_EventChannel-module, a new instance was created
- each time. Now fixed.</p>
- <p>Own Id: OTP-4092</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <list type="bulleted">
- <item>
- <p>The include paths for <c>CosNotification.idl</c> have been changed.
- Hence, if you include this file in your own IDL-files you must
- update your paths to also point to where the cosEvent IDL-files are
- stored.</p>
- <p>Own Id: OTP-4093</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.0.3</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>It is now possible to start global channel factories.</p>
- <p>Own Id: OTP-4078</p>
- </item>
- <item>
- <p>The Orber, version 3.2.5 or later, configuration parameter
- orber_debug_level can now be used to generate reports when abnormal
- situations occurs. For more information consult the Orber User's Guide.
- Note, it is not recommended to use this option for delivered systems
- since some of the reports is not to be considered as errors.
- The value of orber_debug_level must be 3, or higher, for reports to
- be generated.</p>
- <p>Own Id: OTP-4077, OTP-3962</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>When using the cosEvent API accessing a cosNotification admins
- the objects returned by the functions obtain_push_supplier,
- obtain_pull_supplier, obtain_push_consumer and obtain_pull_consumer
- was not of the correct type. Due to the interface change
- it is not possible to upgrade during runtime.</p>
- <p>Own Id: OTP-4079</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosNotification 1.0.2</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>First release of the cosNotification application.</p>
- <p>Own Id: -</p>
- </item>
- </list>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosNotification/doc/src/notificationFlow.gif b/lib/cosNotification/doc/src/notificationFlow.gif
deleted file mode 100644
index 31d6ee97fb..0000000000
--- a/lib/cosNotification/doc/src/notificationFlow.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosNotification/doc/src/part.xml b/lib/cosNotification/doc/src/part.xml
deleted file mode 100644
index 9cc5a8a95a..0000000000
--- a/lib/cosNotification/doc/src/part.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosNotification User's Guide</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-01-31</date>
- <rev>1.0</rev>
- </header>
- <description>
- <p>The <em>cosNotification</em> application is an Erlang implementation
- of the OMG CORBA Notification Service.</p>
- </description>
- <xi:include href="ch_contents.xml"/>
- <xi:include href="ch_introduction.xml"/>
- <xi:include href="ch_install.xml"/>
- <xi:include href="ch_system.xml"/>
- <xi:include href="ch_BNF.xml"/>
- <xi:include href="ch_QoS.xml"/>
- <xi:include href="ch_example.xml"/>
-</part>
-
diff --git a/lib/cosNotification/doc/src/part_notes.xml b/lib/cosNotification/doc/src/part_notes.xml
deleted file mode 100644
index c999d885c1..0000000000
--- a/lib/cosNotification/doc/src/part_notes.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosNotification Release Notes</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-01-31</date>
- <rev>1.0</rev>
- </header>
- <description>
- <p>The cosNotification Application is an Erlang implementation of the OMG
- CORBA Notification Service.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/cosNotification/doc/src/ref_man.gif b/lib/cosNotification/doc/src/ref_man.gif
deleted file mode 100644
index b13c4efd53..0000000000
--- a/lib/cosNotification/doc/src/ref_man.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosNotification/doc/src/ref_man.xml b/lib/cosNotification/doc/src/ref_man.xml
deleted file mode 100644
index 58fb4febd2..0000000000
--- a/lib/cosNotification/doc/src/ref_man.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE application SYSTEM "application.dtd">
-
-<application xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosNotification Reference Manual</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-01-31</date>
- <rev>1.0</rev>
- </header>
- <description>
- <p>The <em>cosNotification</em> application is an Erlang implementation
- of the OMG CORBA Notification Service.</p>
- </description>
- <xi:include href="cosNotificationApp.xml"/>
- <xi:include href="CosNotifyChannelAdmin_EventChannelFactory.xml"/>
- <xi:include href="CosNotifyChannelAdmin_EventChannel.xml"/>
- <xi:include href="CosNotification.xml"/>
- <xi:include href="CosNotification_QoSAdmin.xml"/>
- <xi:include href="CosNotification_AdminPropertiesAdmin.xml"/>
- <xi:include href="CosNotifyChannelAdmin_ConsumerAdmin.xml"/>
- <xi:include href="CosNotifyChannelAdmin_SupplierAdmin.xml"/>
- <xi:include href="CosNotifyComm_NotifyPublish.xml"/>
- <xi:include href="CosNotifyComm_NotifySubscribe.xml"/>
- <xi:include href="CosNotifyFilter_FilterAdmin.xml"/>
- <xi:include href="CosNotifyFilter_FilterFactory.xml"/>
- <xi:include href="CosNotifyFilter_Filter.xml"/>
- <xi:include href="CosNotifyFilter_MappingFilter.xml"/>
- <xi:include href="CosNotifyChannelAdmin_ProxyConsumer.xml"/>
- <xi:include href="CosNotifyChannelAdmin_ProxySupplier.xml"/>
- <xi:include href="CosNotifyChannelAdmin_ProxyPullConsumer.xml"/>
- <xi:include href="CosNotifyChannelAdmin_ProxyPullSupplier.xml"/>
- <xi:include href="CosNotifyChannelAdmin_ProxyPushConsumer.xml"/>
- <xi:include href="CosNotifyChannelAdmin_ProxyPushSupplier.xml"/>
- <xi:include href="CosNotifyChannelAdmin_SequenceProxyPullConsumer.xml"/>
- <xi:include href="CosNotifyChannelAdmin_SequenceProxyPullSupplier.xml"/>
- <xi:include href="CosNotifyChannelAdmin_SequenceProxyPushConsumer.xml"/>
- <xi:include href="CosNotifyChannelAdmin_SequenceProxyPushSupplier.xml"/>
- <xi:include href="CosNotifyChannelAdmin_StructuredProxyPullConsumer.xml"/>
- <xi:include href="CosNotifyChannelAdmin_StructuredProxyPullSupplier.xml"/>
- <xi:include href="CosNotifyChannelAdmin_StructuredProxyPushConsumer.xml"/>
- <xi:include href="CosNotifyChannelAdmin_StructuredProxyPushSupplier.xml"/>
-</application>
-
diff --git a/lib/cosNotification/doc/src/summary.html.src b/lib/cosNotification/doc/src/summary.html.src
deleted file mode 100644
index 92ade4f9cd..0000000000
--- a/lib/cosNotification/doc/src/summary.html.src
+++ /dev/null
@@ -1 +0,0 @@
-Orber OMG Notification Service \ No newline at end of file
diff --git a/lib/cosNotification/doc/src/user_guide.gif b/lib/cosNotification/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/cosNotification/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosNotification/ebin/.gitignore b/lib/cosNotification/ebin/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosNotification/ebin/.gitignore
+++ /dev/null
diff --git a/lib/cosNotification/examples/.gitignore b/lib/cosNotification/examples/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosNotification/examples/.gitignore
+++ /dev/null
diff --git a/lib/cosNotification/include/.gitignore b/lib/cosNotification/include/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosNotification/include/.gitignore
+++ /dev/null
diff --git a/lib/cosNotification/info b/lib/cosNotification/info
deleted file mode 100644
index 1b634eb124..0000000000
--- a/lib/cosNotification/info
+++ /dev/null
@@ -1,3 +0,0 @@
-group: orb
-short: Orber OMG Notification Service
-
diff --git a/lib/cosNotification/priv/.gitignore b/lib/cosNotification/priv/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosNotification/priv/.gitignore
+++ /dev/null
diff --git a/lib/cosNotification/src/CosEvent.cfg b/lib/cosNotification/src/CosEvent.cfg
deleted file mode 100644
index e3399139a4..0000000000
--- a/lib/cosNotification/src/CosEvent.cfg
+++ /dev/null
@@ -1,20 +0,0 @@
-{this, "CosEventChannelAdmin::EventChannel"}.
-{{handle_info, "CosEventChannelAdmin::EventChannel"}, true}.
-{this, "CosEventChannelAdmin::EventChannelFactory"}.
-{{handle_info, "CosEventChannelAdmin::EventChannelFactory"}, true}.
-{this, "CosEventChannelAdmin::SupplierAdmin"}.
-{{handle_info, "CosEventChannelAdmin::SupplierAdmin"}, true}.
-{this, "CosEventChannelAdmin::ConsumerAdmin"}.
-{{handle_info, "CosEventChannelAdmin::ConsumerAdmin"}, true}.
-{this, "CosEventChannelAdmin::ProxyPushSupplier"}.
-{{handle_info, "CosEventChannelAdmin::ProxyPushSupplier"}, true}.
-{{impl, "CosEventChannelAdmin::ProxyPushSupplier"}, "PusherSupplier_impl"}.
-{this, "CosEventChannelAdmin::ProxyPullSupplier"}.
-{{handle_info, "CosEventChannelAdmin::ProxyPullSupplier"}, true}.
-{{impl, "CosEventChannelAdmin::ProxyPullSupplier"}, "PullerSupplier_impl"}.
-{this, "CosEventChannelAdmin::ProxyPushConsumer"}.
-{{handle_info, "CosEventChannelAdmin::ProxyPushConsumer"}, true}.
-{{impl, "CosEventChannelAdmin::ProxyPushConsumer"}, "PusherConsumer_impl"}.
-{this, "CosEventChannelAdmin::ProxyPullConsumer"}.
-{{handle_info, "CosEventChannelAdmin::ProxyPullConsumer"}, true}.
-{{impl, "CosEventChannelAdmin::ProxyPullConsumer"}, "PullerConsumer_impl"}.
diff --git a/lib/cosNotification/src/CosNotification.cfg b/lib/cosNotification/src/CosNotification.cfg
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosNotification/src/CosNotification.cfg
+++ /dev/null
diff --git a/lib/cosNotification/src/CosNotification.idl b/lib/cosNotification/src/CosNotification.idl
deleted file mode 100644
index e080b44b0c..0000000000
--- a/lib/cosNotification/src/CosNotification.idl
+++ /dev/null
@@ -1,146 +0,0 @@
-#ifndef _COS_NOTIFICATION_IDL_
-#define _COS_NOTIFICATION_IDL_
-
-#pragma prefix "omg.org"
-
-#include"CosEventChannelAdmin.idl"
-#include"CosEventComm.idl"
-
-module CosNotification {
- typedef string Istring;
- typedef Istring PropertyName;
- typedef any PropertyValue;
- struct Property {
- PropertyName name;
- PropertyValue value;
- };
- typedef sequence<Property> PropertySeq;
- // The following are the same, but serve different purposes.
- typedef PropertySeq OptionalHeaderFields;
- typedef PropertySeq FilterableEventBody;
- typedef PropertySeq QoSProperties;
- typedef PropertySeq AdminProperties;
- struct EventType {
- string domain_name;
- string type_name;
- };
- typedef sequence<EventType> EventTypeSeq;
- struct PropertyRange {
- PropertyValue low_val;
- PropertyValue high_val;
- };
- struct NamedPropertyRange {
- PropertyName name;
- PropertyRange range;
- };
-
- typedef sequence<NamedPropertyRange> NamedPropertyRangeSeq;
-
- enum QoSError_code {
- UNSUPPORTED_PROPERTY,
- UNAVAILABLE_PROPERTY,
- UNSUPPORTED_VALUE,
- UNAVAILABLE_VALUE,
- BAD_PROPERTY,
- BAD_TYPE,
- BAD_VALUE
- };
-
- struct PropertyError {
- QoSError_code code;
- PropertyName name;
- PropertyRange available_range;
- };
-
- typedef sequence<PropertyError> PropertyErrorSeq;
- exception UnsupportedQoS { PropertyErrorSeq qos_err; };
- exception UnsupportedAdmin { PropertyErrorSeq admin_err; };
-
- // Define the Structured Event structure
- struct FixedEventHeader {
- EventType event_type;
- string event_name;
- };
- struct EventHeader {
- FixedEventHeader fixed_header;
- OptionalHeaderFields variable_header;
- };
-
- struct StructuredEvent {
- EventHeader header;
- FilterableEventBody filterable_data;
- any remainder_of_body;
- }; // StructuredEvent
-
- typedef sequence<StructuredEvent> EventBatch;
-
- // The following constant declarations define the standard
- // QoS property names and the associated values each property
- // can take on. The name/value pairs for each standard property
- // are grouped, beginning with a string constant defined for the
- // property name, followed by the values the property can take on.
- const string EventReliability = "EventReliability";
- const short BestEffort = 0;
- const short Persistent = 1;
- const string ConnectionReliability = "ConnectionReliability";
-
- // Can take on the same values as EventReliability
- const string Priority = "Priority";
- const short LowestPriority = -32767;
- const short HighestPriority = 32767;
- const short DefaultPriority = 0;
- const string StartTime = "StartTime";
-
- // StartTime takes a value of type TimeBase::UtcT.
- const string StopTime = "StopTime";
- // StopTime takes a value of type TimeBase::UtcT.
- const string Timeout = "Timeout";
- // Timeout takes on a value of type TimeBase::TimeT
- const string OrderPolicy = "OrderPolicy";
- const short AnyOrder = 0;
- const short FifoOrder = 1;
- const short PriorityOrder = 2;
- const short DeadlineOrder = 3;
- const string DiscardPolicy = "DiscardPolicy";
- // DiscardPolicy takes on the same values as OrderPolicy, plus
- const short LifoOrder = 4;
- const short RejectNewEvents = 5;
- const string MaximumBatchSize = "MaximumBatchSize";
- // MaximumBatchSize takes on a value of type long
- const string PacingInterval = "PacingInterval";
- // PacingInterval takes on a value of type TimeBase::TimeT
- const string StartTimeSupported = "StartTimeSupported";
- // StartTimeSupported takes on a boolean value
- const string StopTimeSupported = "StopTimeSupported";
- // StopTimeSupported takes on a boolean value
- const string MaxEventsPerConsumer = "MaxEventsPerConsumer";
- // MaxEventsPerConsumer takes on a value of type long
-
- interface QoSAdmin {
- QoSProperties get_qos();
- void set_qos ( in QoSProperties qos)
- raises ( UnsupportedQoS );
- void validate_qos (in QoSProperties required_qos,
- out NamedPropertyRangeSeq available_qos )
- raises ( UnsupportedQoS );
- }; // QosAdmin
-
- // Admin properties are defined in similar manner as QoS
- // properties. The only difference is that these properties
- // are related to channel administration policies, as opposed
- // message quality of service
- const string MaxQueueLength = "MaxQueueLength";
- // MaxQueueLength takes on a value of type long
- const string MaxConsumers = "MaxConsumers";
- // MaxConsumers takes on a value of type long
- const string MaxSuppliers = "MaxSuppliers";
- // MaxSuppliers takes on a value of type long
- interface AdminPropertiesAdmin {
- AdminProperties get_admin();
- void set_admin (in AdminProperties admin)
- raises ( UnsupportedAdmin);
- };// AdminPropertiesAdmin
-}; // CosNotification
-
-#endif /* ifndef _COS_NOTIFICATION_IDL_ */
-
diff --git a/lib/cosNotification/src/CosNotification_Common.erl b/lib/cosNotification/src/CosNotification_Common.erl
deleted file mode 100644
index 530641b7a5..0000000000
--- a/lib/cosNotification/src/CosNotification_Common.erl
+++ /dev/null
@@ -1,1240 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2015. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%--------------------------------------------------------------------
-%% File : CosNotification_Common.erl
-%% Purpose :
-%%--------------------------------------------------------------------
-
--module('CosNotification_Common').
-
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
-%% Application files
--include("CosNotification.hrl").
--include("CosNotifyChannelAdmin.hrl").
--include("CosNotifyComm.hrl").
--include("CosNotifyFilter.hrl").
-
--include("CosNotification_Definitions.hrl").
-
-%%--------------- EXPORTS ------------------------------------
-%% External MISC
--export([get_option/3,
- create_name/0,
- create_name/1,
- create_name/2,
- create_id/0,
- create_id/1,
- is_debug_compiled/0,
- type_check/2,
- send_stubborn/5,
- create_link/3,
- disconnect/3,
- do_disconnect/3,
- notify/1]).
-
-%% Internal AdminProperties
--export([init_adm/1,
- set_adm/2,
- 'MaxQueueLength'/6,
- 'MaxConsumers'/6,
- 'MaxSuppliers'/6]).
-%% Internal QoS
--export([init_qos/1,
- set_qos/5,
- validate_qos/5,
- validate_event_qos/2,
- 'EventReliability'/6,
- 'ConnectionReliability'/6,
- 'Priority'/6,
- 'StartTimeSupported'/6,
- 'StopTimeSupported'/6,
- 'Timeout'/6,
- 'OrderPolicy'/6,
- 'DiscardPolicy'/6,
- 'MaximumBatchSize'/6,
- 'PacingInterval'/6,
- 'MaxEventsPerConsumer'/6]).
-
-%%--------------- DEFINITIONS OF CONSTANTS -------------------
-%%--------------- EXTERNAL MISC FUNCTIONS --------------------
-%%------------------------------------------------------------
-%% function : create_link
-%% Arguments: Module - which Module to call
-%% Env/ArgList - ordinary oe_create arguments.
-%% Returns :
-%% Exception:
-%% Effect : Necessary since we want the supervisor to be a
-%% 'simple_one_for_one'. Otherwise, using for example,
-%% 'one_for_one', we have to call supervisor:delete_child
-%% to remove the childs startspecification from the
-%% supervisors internal state.
-%%------------------------------------------------------------
-create_link(Module, Env, ArgList) ->
- Module:oe_create_link(Env, ArgList).
-
-%%-----------------------------------------------------------%
-%% function : get_option
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-get_option(Key, OptionList, DefaultList) ->
- case lists:keysearch(Key, 1, OptionList) of
- {value,{Key,Value}} ->
- Value;
- _ ->
- case lists:keysearch(Key, 1, DefaultList) of
- {value,{Key,Value}} ->
- Value;
- _->
- {error, "Invalid option"}
- end
- end.
-
-%%------------------------------------------------------------
-%% function : create_name
-%% Arguments:
-%% Returns :
-%% Effect : Create a unique name to use when, for eaxmple, starting
-%% a new server.
-%%------------------------------------------------------------
-create_name() ->
- Time = erlang:system_time(),
- Unique = erlang:unique_integer([positive]),
- lists:concat(['oe_',node(),'_',Time,'_',Unique]).
-
-
-%%-----------------------------------------------------------%
-%% function : create_name/1
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-create_name(Type) ->
- Time = erlang:system_time(),
- Unique = erlang:unique_integer([positive]),
- lists:concat(['oe_',node(),'_',Type,'_',Time,'_',Unique]).
-
-%%-----------------------------------------------------------%
-%% function : create_name/2
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-create_name(Name,Type) ->
- Time = erlang:system_time(),
- Unique = erlang:unique_integer([positive]),
- lists:concat(['oe_',node(),'_',Type,'_',Name,'_',Time,'_',Unique]).
-
-%%------------------------------------------------------------
-%% function : create_id/0
-%% Arguments: -
-%% Returns : id (long) =/= 0
-%% Both default Admin:s have the unique id 0 (OMG spec, 98-11-01,
-%% Notification p 148), hence, we may not return 0.
-%% Exception:
-%% Purpose : Throughout the CosNotification service we use,
-%% according to the OMG specification, id:s (long),
-%% which must be "unique", to retrieve object references.
-%% For example: CosNotifyChannelAdmin::ChannelId/AdminID.
-%%------------------------------------------------------------
-create_id(-1) ->
- 1;
-create_id(2147483647) ->
- -2147483648;
-create_id(OldID) ->
- OldID+1.
-
-create_id() ->
- {_A,_B,C}=erlang:timestamp(),
- C.
-
-%%------------------------------------------------------------
-%% function : type_check
-%% Arguments: Obj - objectrefernce to test.
-%% Mod - Module which contains typeID/0.
-%% Returns : 'ok' or raises exception.
-%% Effect :
-%%------------------------------------------------------------
-type_check(Obj, Mod) ->
- case cosNotificationApp:type_check() of
- false ->
- ok;
- _ ->
- case catch corba_object:is_a(Obj,Mod:typeID()) of
- true ->
- ok;
- false ->
- orber:dbg("[~p] CosNotification_Common:type_check(~p);~n"
- "The supplied Object is not or does not inherrit from: ~p",
- [?LINE, Obj, Mod], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO});
- {'EXCEPTION', E} ->
- orber:dbg("[~p] CosNotification_Common:type_check(~p, ~p);~n"
- "Failed due to: ~p",
- [?LINE, Obj, Mod, E], ?DEBUG_LEVEL),
- corba:raise(E);
- What ->
- orber:dbg("[~p] CosNotification_Common:type_check(~p, ~p);~n"
- "Failed due to: ~p",
- [?LINE, Obj, Mod, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end
- end.
-
-
-%%-----------------------------------------------------------%
-%% function : notify
-%% Arguments: Items - [Item]
-%% Item - {proxy, IOR} | {client, IOR} | {reason, term()}
-%% Returns : 'ok' or raises exception.
-%% Effect :
-%%------------------------------------------------------------
-notify(Items) ->
- case cosNotificationApp:notify() of
- false ->
- ok;
- Module ->
- catch Module:terminated(Items),
- ok
- end.
-
-
-%%------------------------------------------------------------
-%% function : send_stubborn
-%% Arguments: M - module
-%% F - function
-%% A - arguments
-%% MaxR - Maximum no retries
-%% Wait - sleep Wait seconds before next try.
-%% Returns : see effect
-%% Exception:
-%% Effect : Retries repeatidly untill anything else besides
-%% 'EXIT', 'COMM_FAILURE' or 'OBJECT_NOT_EXIST'
-%%------------------------------------------------------------
-
-send_stubborn(M, F, A, MaxR, Wait) when is_list(A) ->
- send_stubborn(M, F, A, MaxR, Wait, 0);
-send_stubborn(M, F, A, MaxR, Wait) ->
- send_stubborn(M, F, [A], MaxR, Wait, 0).
-send_stubborn(M, F, A, MaxR, _Wait, MaxR) ->
- orber:dbg("[~p] CosNotification_Common:send_stubborn( ~p ~p ~p ~p).~n"
- "Failed to deliver the event.~n", [?LINE, M,F,A,MaxR], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO});
-send_stubborn(M, F, A, MaxR, Wait, Times) ->
- ?debug_print("~p:~p(~p) # of retries: ~p~n", [M,F,A, Times]),
- case catch apply(M,F,A) of
- {'EXCEPTION', E} when is_record(E, 'COMM_FAILURE')->
- NewTimes = Times +1,
- timer:sleep(Wait),
- send_stubborn(M, F, A, MaxR, Wait, NewTimes);
- {'EXIT', _} ->
- NewTimes = Times +1,
- timer:sleep(Wait),
- send_stubborn(M, F, A, MaxR, Wait, NewTimes);
- Other ->
- Other
- end.
-
-
-%%-----------------------------------------------------------%
-%% function : disconnect
-%% Arguments: Module - one of the interfaces defined in CosEventComm.
-%% Function - the appropriate disconnect function.
-%% Object - the client object reference.
-%% Returns : ok
-%% Exception:
-%% Effect : If the process would try to diconnect itself it could
-%% result in a deadlock. Hence, we spawn a new process to do it.
-%%------------------------------------------------------------
-disconnect(Module, Function, Object) ->
- spawn(?MODULE, do_disconnect, [Module, Function, Object]),
- ok.
-
-do_disconnect(Module, Function, Object) ->
- catch Module:Function(Object),
- ?DBG("Disconnect ~p:~p(..).~n", [Module, Function]),
- ok.
-
-
-
-%%------------------------------------------------------------
-%% function : is_debug_compiled
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-
--ifdef(debug).
- is_debug_compiled() -> true.
--else.
- is_debug_compiled() -> false.
--endif.
-
-
-%%------------------------------------------------------------
-%%--------------- AdminPropertiesAdmin -----------------------
-%%------------------------------------------------------------
-%%------------------------------------------------------------
-%% function : init_adm
-%% Arguments: Wanted - requested Admins to be set.
-%% Returns : #'CosNotification_UnsupportedAdmin'{} |
-%% {NewAdmProperties, [MaxQ, MaxC, MaxS]}
-%% Effect : may only be used when creating a channel!!!!!!!!
-%%------------------------------------------------------------
-init_adm(Wanted) ->
- {NewA,_} = set_properties(Wanted, ?not_DEFAULT_ADMINPROPERTIES, channelAdm,
- ?not_SUPPORTED_ADMINPROPERTIES, [], [],
- false, false, false),
- {NewA, [extract_value(NewA, ?not_MaxQueueLength),
- extract_value(NewA, ?not_MaxConsumers),
- extract_value(NewA, ?not_MaxSuppliers)]}.
-
-set_adm(Wanted, Current) ->
- {NewA,_} = set_properties(Wanted, Current, channelAdm,
- ?not_SUPPORTED_ADMINPROPERTIES,
- [], [], false, false, false),
- {NewA, [extract_value(NewA, ?not_MaxQueueLength),
- extract_value(NewA, ?not_MaxConsumers),
- extract_value(NewA, ?not_MaxSuppliers)]}.
-
-'MaxQueueLength'(Req,channelAdm,_, _, _, _) -> admin_ok(Req).
-'MaxConsumers'(Req,channelAdm,_, _, _, _)-> admin_ok(Req).
-'MaxSuppliers'(Req,channelAdm,_, _, _, _)-> admin_ok(Req).
-
-admin_ok(Req) ->
- case any:get_value(Req#'CosNotification_Property'.value) of
- Val when is_integer(Val) andalso Val >= 0 ->
- {ok, Req};
- _ ->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_TYPE',
- name = Req#'CosNotification_Property'.name,
- available_range = #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)
- }
- }
- }
- end.
-
-
-%%------------------------------------------------------------
-%%--------------- QOS FUNCTIONS ------------------------------
-%%------------------------------------------------------------
-%%------------------------------------------------------------
-%% function : init_qos
-%% Arguments: Wanted - requested QoS to be set.
-%% Returns : see set_properties/9
-%% Effect : may only be used when creating a channel!!!!!!!!
-%%------------------------------------------------------------
-init_qos(Wanted) ->
- LQS = set_local_qos(?not_DEFAULT_QOS, ?not_CreateInitQoS()),
- set_properties(Wanted, ?not_DEFAULT_QOS, channel, ?not_SUPPORTED_QOS,
- [], [], false, [], LQS).
-
-%%------------------------------------------------------------
-%% function : set_qos/5
-%% Arguments: Wanted - requested QoS to be set.
-%% Current - current QoS OMG style
-%% LQS - local representation of QoS.
-%% Type - channel | admin | proxy
-%% Parent - Factory if Channel, Channel if Admin etc
-%% Childs - Admins if Channel etc
-%% Returns : see set_properties/9
-%%------------------------------------------------------------
-set_qos(Wanted, {Current, LQS}, proxy, Parent, _) ->
- set_properties(Wanted, Current, proxy, ?not_SUPPORTED_QOS, [], [], Parent, false,LQS);
-set_qos(Wanted, {Current, LQS}, admin, Parent, Childs) ->
- set_properties(Wanted, Current, admin, ?not_SUPPORTED_QOS, [], [], Parent, Childs,LQS);
-set_qos(Wanted, {Current, LQS}, channel, _, Childs) ->
- set_properties(Wanted, Current, channel, ?not_SUPPORTED_QOS, [], [], false, Childs,LQS).
-
-%%------------------------------------------------------------
-%% function :
-%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
-%% Type - Requestee, channel | admin | proxy
-%% Curr - Current QoS, #'CosNotification_Property'{}
-%% Parent - false | ObjRef
-%% Childs - false | [ObjRef1, .., ObjRefN]
-%% LQS - #qos{} defined in CosNotification_Definitions.hrl
-%% Returns : ok - if requested equal to current value.
-%% {ok, Req, LQS} - if new and allowed QoS
-%% {unsupported,#'CosNotification_PropertyError'{}} otherwise.
-%% Effect :
-%%------------------------------------------------------------
-'EventReliability'(Req,channel, _Curr, _Parent, _Childs, LQS) ->
- case {any:get_value(Req#'CosNotification_Property'.value),
- ?not_GetConnectionReliability(LQS), ?not_BestEffort, ?not_Persistent} of
- {Val, Val, _, _} ->
- %% Is the value requested.
- ok;
- {Val, _, Val, _} ->
- {ok, Req, LQS};
- {Val, _, _, Val} ->
- {ok, Req, LQS};
- _->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_TYPE',
- name = Req#'CosNotification_Property'.name,
- available_range = #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)
- }
- }
- }
- end;
-'EventReliability'(Req,_,_,_,_,_) ->
- %% only valid to set this QoS for channels (or per-event).
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'UNAVAILABLE_PROPERTY',
- name = Req#'CosNotification_Property'.name,
- available_range = #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)
- }
- }
- }.
-
-%%------------------------------------------------------------
-%% function : 'ConnectionReliability'/6
-%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
-%% Type - Requestee, channel | admin | proxy
-%% Curr - Current QoS, #'CosNotification_Property'{}
-%% Parent - false | ObjRef
-%% Childs - false | [ObjRef1, .., ObjRefN]
-%% LQS - #qos{} defined in CosNotification_Definitions.hrl
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-%% The most complex QoS to set is ConnectionReliability, and the reason for this
-%% is that we cannot set the Channel to offer best effort while its children
-%% offer persistent. A child may only offer Persistent if its parent do, which
-%% is why we must check the following:
-%%
-%% # Persistent Change to Best Effort
-%% _____
-%% | | (1) -> Check if children BE
-%% |Chann| (2) ok <-
-%% -----
-%% |
-%% _____
-%% | | (3) -> Check if children BE
-%% |Admin| (4) Check if parent Pers. <-
-%% -----
-%% |
-%% _____
-%% | | (5) -> ok
-%% |Proxy| (6) Check if parent Pers. <-
-%% -----
-%% NOTE: a parent always exists but we may change the QoS before creating any
-%% childrens. The cases (2) and (5) is always ok, i.e., no need to confirm
-%% with parent or children.
-%%------------------------------------------------------------
-'ConnectionReliability'(Req, channel, _Curr, _Parent, Childs, LQS) ->
- case {any:get_value(Req#'CosNotification_Property'.value),
- ?not_GetConnectionReliability(LQS), ?not_BestEffort, ?not_Persistent} of
- {Val, Val, _, _} ->
- %% Is the value requested.
- ok;
- {Val, P, Val, P} ->
- %% Requested is BestEffort, Current Persistent => (1)
- check_with_relatives(Childs, Req, LQS);
- {Val, B, B, Val} ->
- %% Requested is Persistent, Current BestEffort => (2)
- {ok, Req, LQS};
- _->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_TYPE',
- name = Req#'CosNotification_Property'.name,
- available_range = #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)
- }
- }
- }
- end;
-'ConnectionReliability'(Req, admin, _Curr, Parent, Childs, LQS) ->
- case {any:get_value(Req#'CosNotification_Property'.value),
- ?not_GetConnectionReliability(LQS), ?not_BestEffort, ?not_Persistent} of
- {Val, Val, _, _} ->
- %% Is the value requested.
- ok;
- {Val, P, Val, P} ->
- %% Requested is BestEffort, Current Persistent => (3)
- check_with_relatives(Childs, Req, LQS);
- {Val, B, B, Val} ->
- %% Requested is Persistent, Current BestEffort => (4)
- check_with_relatives([Parent], Req, LQS);
- _->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_TYPE',
- name = Req#'CosNotification_Property'.name,
- available_range = #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)
- }
- }
- }
- end;
-'ConnectionReliability'(Req, proxy, _Curr, Parent, _Childs, LQS) ->
- case {any:get_value(Req#'CosNotification_Property'.value),
- ?not_GetConnectionReliability(LQS), ?not_BestEffort, ?not_Persistent} of
- {Val, Val, _, _} ->
- %% Is the value requested.
- ok;
- {Val, P, Val, P} ->
- %% Requested is BestEffort, Current Persistent => (5)
- {ok, Req, LQS};
- {Val, B, B, Val} ->
- %% Requested is Persistent, Current BestEffort => (6)
- check_with_relatives([Parent], Req, LQS);
- _->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_TYPE',
- name = Req#'CosNotification_Property'.name,
- available_range = #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)
- }
- }
- }
- end.
-
-%%------------------------------------------------------------
-%% function : 'Priority'/6
-%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
-%% Type - Requestee, channel | admin | proxy
-%% Curr - Current QoS, #'CosNotification_Property'{}
-%% Parent - false | ObjRef
-%% Childs - false | [ObjRef1, .., ObjRefN]
-%% LQS - #qos{} defined in CosNotification_Definitions.hrl
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-'Priority'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
- case {any:get_value(Req#'CosNotification_Property'.value),
- ?not_GetPriority(LQS), ?not_HighestPriority, ?not_LowestPriority} of
- {Val, Val, _, _} ->
- ok;
- {Val, _, H, L} when Val =< H, Val >= L ->
- {ok, Req, LQS};
- {_, _, H, L} ->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_VALUE',
- name = Req#'CosNotification_Property'.name,
- available_range =
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:short(), L),
- high_val=any:create(orber_tc:short(), H)
- }
- }
- }
- end.
-
-%%------------------------------------------------------------
-%% function : 'StartTimeSupported'/6
-%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
-%% Type - Requestee, channel | admin | proxy
-%% Curr - Current QoS, #'CosNotification_Property'{}
-%% Parent - false | ObjRef
-%% Childs - false | [ObjRef1, .., ObjRefN]
-%% LQS - #qos{} defined in CosNotification_Definitions.hrl
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-'StartTimeSupported'(Req, _Type, _Curr, _, _, LQS) ->
- case {any:get_value(Req#'CosNotification_Property'.value),
- ?not_GetStartTimeSupported(LQS)} of
- {Val, Val} ->
- ok;
- {Val, _} when Val =/= true, Val =/= false ->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_VALUE',
- name = Req#'CosNotification_Property'.name,
- available_range =
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:boolean(), false),
- high_val=any:create(orber_tc:boolean(), true)
- }
- }
- };
- _->
- {ok, Req, LQS}
- end.
-
-%%------------------------------------------------------------
-%% function : 'StopTimeSupported'/6
-%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
-%% Type - Requestee, channel | admin | proxy
-%% Curr - Current QoS, #'CosNotification_Property'{}
-%% Parent - false | ObjRef
-%% Childs - false | [ObjRef1, .., ObjRefN]
-%% LQS - #qos{} defined in CosNotification_Definitions.hrl
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-'StopTimeSupported'(Req, _Type, _Curr, _, _, LQS) ->
- case {any:get_value(Req#'CosNotification_Property'.value),
- ?not_GetStopTimeSupported(LQS)} of
- {Val, Val} ->
- ok;
- {Val, _} when Val =/= true, Val =/= false ->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_VALUE',
- name = Req#'CosNotification_Property'.name,
- available_range =
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:boolean(), false),
- high_val=any:create(orber_tc:boolean(), true)
- }
- }
- };
- _->
- {ok, Req, LQS}
- end.
-
-%%------------------------------------------------------------
-%% function : 'Timeout'/6
-%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
-%% Type - Requestee, channel | admin | proxy
-%% Curr - Current QoS, #'CosNotification_Property'{}
-%% Parent - false | ObjRef
-%% Childs - false | [ObjRef1, .., ObjRefN]
-%% LQS - #qos{} defined in CosNotification_Definitions.hrl
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-'Timeout'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
- case {any:get_value(Req#'CosNotification_Property'.value),
- ?not_GetTimeout(LQS)} of
- {Val, Val} ->
- ok;
- {Val, _} when Val >= ?not_MinTimeout, Val =< ?not_MaxTimeout ->
- {ok, Req, LQS};
- {Val, _} when is_integer(Val) ->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_VALUE',
- name = Req#'CosNotification_Property'.name,
- available_range =
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:unsigned_long_long(), ?not_MinTimeout),
- high_val=any:create(orber_tc:unsigned_long_long(), ?not_MaxTimeout)
- }
- }
- };
- _->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_TYPE',
- name = Req#'CosNotification_Property'.name,
- available_range = #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)
- }
- }
- }
- end.
-
-%%------------------------------------------------------------
-%% function : 'OrderPolicy'/6
-%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
-%% Type - Requestee, channel | admin | proxy
-%% Curr - Current QoS, #'CosNotification_Property'{}
-%% Parent - false | ObjRef
-%% Childs - false | [ObjRef1, .., ObjRefN]
-%% LQS - #qos{} defined in CosNotification_Definitions.hrl
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-'OrderPolicy'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
- case {any:get_value(Req#'CosNotification_Property'.value),
- ?not_GetOrderPolicy(LQS), 'CosNotification':'AnyOrder'(),
- 'CosNotification':'PriorityOrder'()} of
- {Val, Val,_,_} ->
- ok;
- {Val, _, L, H} when Val >= L, Val =< H ->
- {ok, Req, LQS};
- {Val, _, L, H} when is_integer(Val) ->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_VALUE',
- name = Req#'CosNotification_Property'.name,
- available_range =
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:short(), L),
- high_val=any:create(orber_tc:short(), H)
- }
- }
- };
- _->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_TYPE',
- name = Req#'CosNotification_Property'.name,
- available_range = #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)
- }
- }
- }
- end.
-
-
-%%------------------------------------------------------------
-%% function : 'DiscardPolicy'/6
-%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
-%% Type - Requestee, channel | admin | proxy
-%% Curr - Current QoS, #'CosNotification_Property'{}
-%% Parent - false | ObjRef
-%% Childs - false | [ObjRef1, .., ObjRefN]
-%% LQS - #qos{} defined in CosNotification_Definitions.hrl
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-'DiscardPolicy'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
- case {any:get_value(Req#'CosNotification_Property'.value),
- ?not_GetDiscardPolicy(LQS), ?not_AnyOrder, ?not_PriorityOrder} of
- {Val, Val,_,_} ->
- ok;
- {Val, _, L, H} when Val >= L, Val =< H ->
- {ok, Req, LQS};
- {Val, _, L, H} when is_integer(Val) ->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_VALUE',
- name = Req#'CosNotification_Property'.name,
- available_range =
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:short(), L),
- high_val=any:create(orber_tc:short(), H)
- }
- }
- };
- _->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_TYPE',
- name = Req#'CosNotification_Property'.name,
- available_range = #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)
- }
- }
- }
- end.
-
-%%------------------------------------------------------------
-%% function : 'DiscardPolicy'/6
-%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
-%% Type - Requestee, channel | admin | proxy
-%% Curr - Current QoS, #'CosNotification_Property'{}
-%% Parent - false | ObjRef
-%% Childs - false | [ObjRef1, .., ObjRefN]
-%% LQS - #qos{} defined in CosNotification_Definitions.hrl
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-'MaximumBatchSize'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
- case {any:get_value(Req#'CosNotification_Property'.value),
- ?not_GetMaximumBatchSize(LQS)} of
- {Val, Val} ->
- ok;
- {Val, _} when Val >= ?not_MinBatchSize, Val =< ?not_MaxBatchSize ->
- {ok, Req, LQS};
- {Val, _} when is_integer(Val) ->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_VALUE',
- name = Req#'CosNotification_Property'.name,
- available_range =
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:unsigned_long_long(), ?not_MinBatchSize),
- high_val=any:create(orber_tc:unsigned_long_long(), ?not_MaxBatchSize)
- }
- }
- };
- _->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'UNSUPPORTED_VALUE',
- name = Req#'CosNotification_Property'.name,
- available_range =
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:long(), ?not_MinBatchSize),
- high_val=any:create(orber_tc:long(), ?not_MaxBatchSize)
- }
- }
- }
- end.
-
-%%------------------------------------------------------------
-%% function : 'PacingInterval'/6
-%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
-%% Type - Requestee, channel | admin | proxy
-%% Curr - Current QoS, #'CosNotification_Property'{}
-%% Parent - false | ObjRef
-%% Childs - false | [ObjRef1, .., ObjRefN]
-%% LQS - #qos{} defined in CosNotification_Definitions.hrl
-%% Returns :
-%% Comment : PacingInterval is defined to be:
-%% * TimeBase::UtcT (p 57, 2.5.5, OMG TC Document telecom/98-11-01)
-%% * TimeBase::TimeT (p 189, appendix B, OMG TC Document telecom/98-11-01)
-%% This implementation use TimeBase::TimeT, especially since
-%% TimeBase::UtcT contains information which are of no importance.
-%% When writing this, the OMG homepage contained no information
-%% regarding this.
-%%------------------------------------------------------------
-'PacingInterval'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
- case {any:get_value(Req#'CosNotification_Property'.value),
- ?not_GetPacingInterval(LQS)} of
- {Val, Val} ->
- ok;
- {Val, _} when Val >= ?not_MinPacing, Val =< ?not_MaxPacing ->
- {ok, Req, LQS};
- {Val, _} when is_integer(Val) ->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_VALUE',
- name = Req#'CosNotification_Property'.name,
- available_range =
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:unsigned_long_long(), ?not_MinPacing),
- high_val=any:create(orber_tc:unsigned_long_long(), ?not_MaxPacing)
- }
- }
- };
- _->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_TYPE',
- name = Req#'CosNotification_Property'.name,
- available_range = #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)
- }
- }
- }
- end.
-
-%%------------------------------------------------------------
-%% function : 'MaxEventsPerConsumer'/6
-%% Arguments: Req - Requested QoS, #'CosNotification_Property'{}
-%% Type - Requestee, channel | admin | proxy
-%% Curr - Current QoS, #'CosNotification_Property'{}
-%% Parent - false | ObjRef
-%% Childs - false | [ObjRef1, .., ObjRefN]
-%% LQS - #qos{} defined in CosNotification_Definitions.hrl
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-'MaxEventsPerConsumer'(Req, _Type, _Curr, _Parent, _Childs, LQS) ->
- case {any:get_value(Req#'CosNotification_Property'.value),
- ?not_GetMaxEventsPerConsumer(LQS)} of
- {Val, Val} ->
- ok;
- {Val, _} when is_integer(Val) andalso
- Val >= ?not_MinConsumerEvents andalso
- Val =< ?not_MaxConsumerEvents ->
- {ok, Req, LQS};
- {Val, _} when is_integer(Val) ->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_VALUE',
- name = Req#'CosNotification_Property'.name,
- available_range =
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:unsigned_long_long(), ?not_MinConsumerEvents),
- high_val=any:create(orber_tc:unsigned_long_long(), ?not_MaxConsumerEvents)
- }
- }
- };
- _->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'UNSUPPORTED_VALUE',
- name = Req#'CosNotification_Property'.name,
- available_range =
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:long(), ?not_MinConsumerEvents),
- high_val=any:create(orber_tc:long(), ?not_MaxConsumerEvents)
- }
- }
- }
- end.
-
-%%------------------------------------------------------------
-%% function : validate_qos/5
-%% Arguments: Wanted - requested QoS to be set.
-%% Curr - current QoS OMG style and LQS, local
-%% representation of QoS, grouped as {OMGQ, LQS}
-%% Type - channel | admin | proxy
-%% Parent - Factory if Channel, Channel if Admin etc
-%% Childs - Admins if Channel etc
-%% Returns : NamedPropertySeq | #'CosNotification_UnsupportedQoS'{}
-%% case 1 if all supported, case 2 if at least 1 QoS not
-%% supported.
-%% See also p59, 2.5.6.4, OMG TC Document telecom/98-11-01. Quote:
-%% "If the supplied QoS is supported, it returns additional QoS
-%% properties which could be optionally added as well."
-%%------------------------------------------------------------
-validate_qos(Wanted, Curr, Type, Parent, Childs) ->
- %% If not supported this function will raise an exception, which we should
- %% not catch, but all we need to is to raise the exception as it is.
- {_, LQS}=set_qos(Wanted, Curr, Type, Parent, Childs),
- NewNPR = check_limits(LQS, ?not_QOS_LIMITS),
- remove_qos(Wanted, LQS, NewNPR).
-
-remove_qos([], _, NPR) ->
- NPR;
-remove_qos([H|T], LQS, NPR) ->
- NewNPR=remove(NPR, H#'CosNotification_Property'.name),
- remove_qos(T, LQS, NewNPR).
-
-check_limits(LQS, NPR) ->
- case {?not_GetEventReliability(LQS), ?not_GetConnectionReliability(LQS),
- ?not_Persistent, ?not_BestEffort} of
- {P,P,P,_B} ->
- New = #'CosNotification_NamedPropertyRange'
- {name=?not_EventReliability,
- range=
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:short(), ?not_BestEffort),
- high_val=any:create(orber_tc:short(), ?not_BestEffort)
- }},
- NewNPR=change(NPR, ?not_EventReliability, New),
- remove(NewNPR, ?not_ConnectionReliability);
- {_,B,_P,B} ->
- remove(NPR, ?not_EventReliability);
- {B,P,P,B} ->
- New = #'CosNotification_NamedPropertyRange'
- {name=?not_ConnectionReliability,
- range=
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:short(), ?not_BestEffort),
- high_val=any:create(orber_tc:short(), ?not_BestEffort)
- }},
- change(NPR, ?not_ConnectionReliability, New)
- end.
-
-%%------------------------------------------------------------
-%% function : validate_event_qos/2
-%% Arguments: Wanted - requested QoS to be set.
-%% Curr - LQS, local representation of QoS
-%% Returns : NamedPropertySeq | #'CosNotification_UnsupportedQoS'{}
-%% case 1 if all supported, case 2 if at least 1 QoS not
-%% supported.
-%%------------------------------------------------------------
-validate_event_qos(Wanted, Curr) ->
- case v_e_q_helper(Wanted, Curr, []) of
- ok ->
- [];
- {error, Unsupp} ->
- corba:raise(#'CosNotification_UnsupportedQoS'{qos_err = Unsupp})
- end.
-
-v_e_q_helper([], _Curr, []) ->
- %% Parsed all and found no conflicts.
- ok;
-v_e_q_helper([], _Curr, Unsupp) ->
- %% Not possible to use these requested QoS.
- {error, Unsupp};
-
-%%--- EventReliability ---%%
-v_e_q_helper([#'CosNotification_Property'{name=?not_EventReliability,
- value=#any{value=?not_BestEffort}}|T], Curr, Unsupp) ->
- %% Always ok.
- v_e_q_helper(T, Curr, Unsupp);
-v_e_q_helper([#'CosNotification_Property'{name=?not_EventReliability,
- value=#any{value=?not_Persistent}}|T], Curr, Unsupp)
- when ?not_GetConnectionReliability(Curr) =/= ?not_BestEffort,
- ?not_GetEventReliability(Curr) =/= ?not_BestEffort,
- ?not_GetStopTimeSupported(Curr) =/= true ->
- v_e_q_helper(T, Curr, Unsupp);
-v_e_q_helper([#'CosNotification_Property'{name=?not_EventReliability}|T],
- Curr, Unsupp) ->
- %% Impossible to set to Persistent if the connection reliability is best effort.
- v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
- {code = 'UNAVAILABLE_VALUE', name = ?not_EventReliability,
- available_range =
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)}}|Unsupp]);
-
-%%--- Priority ---%%
-v_e_q_helper([#'CosNotification_Property'{name=?not_Priority, value=#any{value=V}}|T], Curr,
- Unsupp) ->
- if
- ?not_GetOrderPolicy(Curr) =/= ?not_AnyOrder,
- ?not_GetOrderPolicy(Curr) =/= ?not_Priority,
- ?not_GetDiscardPolicy(Curr) =/= ?not_Priority ->
- %% No use setting Priority since it's not currently used.
- v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
- {code = 'UNAVAILABLE_VALUE', name = ?not_Priority,
- available_range = #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)
- }}|Unsupp]);
- V =< ?not_HighestPriority, V >= ?not_LowestPriority ->
- v_e_q_helper(T, Curr, Unsupp);
- true ->
- v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
- {code = 'BAD_VALUE', name = ?not_Priority,
- available_range =
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:short(),
- ?not_LowestPriority),
- high_val=any:create(orber_tc:short(),
- ?not_HighestPriority)}}|Unsupp])
- end;
-
-%%--- StartTime ---%%
-v_e_q_helper([#'CosNotification_Property'{name=?not_StartTime}|T], Curr, Unsupp)
- when ?not_GetStartTimeSupported(Curr) =/= false,
- ?not_GetEventReliability(Curr) =/= ?not_Persistent ->
- v_e_q_helper(T, Curr, Unsupp);
-v_e_q_helper([#'CosNotification_Property'{name=?not_StartTime}|T], Curr, Unsupp) ->
- v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
- {code = 'UNAVAILABLE_VALUE', name = ?not_StartTime,
- available_range = #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)
- }}|Unsupp]);
-
-%%--- StopTime ---%%
-v_e_q_helper([#'CosNotification_Property'{name=?not_StopTime}|T], Curr, Unsupp)
- when ?not_GetStopTimeSupported(Curr) =/= false,
- ?not_GetEventReliability(Curr) =/= ?not_Persistent ->
- v_e_q_helper(T, Curr, Unsupp);
-v_e_q_helper([#'CosNotification_Property'{name=?not_StopTime}|T], Curr, Unsupp) ->
- v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
- {code = 'UNAVAILABLE_VALUE', name = ?not_StopTime,
- available_range = #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)
- }}|Unsupp]);
-
-%%--- Timeout ---%%
-v_e_q_helper([#'CosNotification_Property'{name=?not_Timeout}|T], Curr, Unsupp)
- when ?not_GetStopTimeSupported(Curr) =/= false,
- ?not_GetEventReliability(Curr) =/= ?not_Persistent ->
- v_e_q_helper(T, Curr, Unsupp);
-v_e_q_helper([#'CosNotification_Property'{name=?not_Timeout}|T], Curr, Unsupp) ->
- v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
- {code = 'UNAVAILABLE_VALUE', name = ?not_Timeout,
- available_range = #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)
- }}|Unsupp]);
-
-%%--- Unknown Event QoS ---%%
-v_e_q_helper([#'CosNotification_Property'{name=Name}|T], Curr, Unsupp) ->
- %% Unsupported property.
- v_e_q_helper(T, Curr, [#'CosNotification_PropertyError'
- {code = 'BAD_PROPERTY', name = Name,
- available_range = #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)
- }}|Unsupp]);
-v_e_q_helper(What, _, _) ->
- %% Not a Property struct.
- orber:dbg("[~p] CosNotification_Common:v_e_q_helper(~p);~n"
- "Not a CosNotification_Property struct.",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%-------------- QOS HELP FUNCTIONS --------------------------
-%%------------------------------------------------------------
-%% function : set_properties/9
-%% Arguments: Wanted - requested QoS to be set.
-%% Current - current QoS OMG style
-%% Type - channel | admin | proxy
-%% Supported - List of supported QoS
-%% Unsupp - acc
-%% NewQoS - acc
-%% Parent - Factory if Channel, Channel if Admin etc
-%% Childs - Admins if Channel etc
-%% LQS - local representation of QoS.
-%% Returns : {NewOMGStyleQoS, NewLocalQoS} | #'CosNotification_UnsupportedQoS'{}
-%%------------------------------------------------------------
-set_properties(Wanted, Current, Type, Supported, Unsupp, NewQoS, Parent, Childs, LQS) ->
- case do_set_properties(Wanted, Current, Type, Supported, Unsupp, NewQoS, Parent, Childs, LQS) of
- {error, Exc} ->
- corba:raise(Exc);
- Result ->
- Result
- end.
-
-do_set_properties([], Curr, channelAdm, _, [], NewQoS,_,_,LAS) ->
- merge_properties(NewQoS, Curr, LAS);
-do_set_properties([], Curr, _, _, [], NewQoS,_,_,LQS) ->
- %% set_local_qos and merge_properties are help functions found at the end of QoS
- %% functions.
- NewLQS = set_local_qos(NewQoS, LQS),
- merge_properties(NewQoS, Curr, NewLQS);
-do_set_properties([], _, channelAdm, _, Unsupp, _,_,_,_) ->
- {error, #'CosNotification_UnsupportedAdmin'{admin_err = Unsupp}};
-do_set_properties([], _, _, _, Unsupp, _,_,_,_) ->
- {error, #'CosNotification_UnsupportedQoS'{qos_err = Unsupp}};
-
-do_set_properties([Req|Tail], Curr, Type, Supported, Unsupp, NewQoS, Parent, Childs,LQS) ->
- %% set_values and is_supported are help functions found at the end of QoS
- %% functions.
- case set_values(is_supported(Supported, Req), Req, Type, Curr, Parent, Childs,LQS) of
- {unsupported, U} ->
- do_set_properties(Tail, Curr, Type, Supported, [U|Unsupp], NewQoS, Parent, Childs,LQS);
- {ok, S, NewLQS} ->
- do_set_properties(Tail, Curr, Type, Supported, Unsupp, [S|NewQoS], Parent, Childs,NewLQS);
- {ok, S} ->
- do_set_properties(Tail, Curr, Type, Supported, Unsupp, [S|NewQoS], Parent, Childs,LQS);
- ok ->
- do_set_properties(Tail, Curr, Type, Supported, Unsupp, NewQoS, Parent, Childs,LQS)
- end.
-
-
-set_values(unsupported,Req,_,_,_,_,_) ->
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'BAD_PROPERTY',
- name = Req#'CosNotification_Property'.name,
- available_range = #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)
- }
- }
- };
-set_values({ok, Func}, Req, Type, Curr, Parent, Childs, LQS) ->
- ?MODULE:Func(Req, Type, Curr, Parent, Childs, LQS).
-
-%% Update OMG style QoS list with new values.
-merge_properties([], NewCurrQoS, LQS) ->
- {NewCurrQoS, LQS};
-merge_properties([H|T], Curr, LQS) ->
- merge_properties(T, lists:keyreplace(H#'CosNotification_Property'.name, %% get key.
- #'CosNotification_Property'.name, %% get index.
- Curr, H), LQS).
-
-%% Is the Property S among our supported QoS?
-is_supported([], _) ->
- unsupported;
-is_supported([{Name, Func}|_], #'CosNotification_Property'{name=Name}) ->
- {ok, Func};
-is_supported([_|T], S) ->
- is_supported(T, S).
-
-%% Find matching S-Property from a list of OMG style QoS
-extract([], _) -> unsupported;
-extract([H|_T], S) when H#'CosNotification_Property'.name==
- S#'CosNotification_Property'.name ->
- {ok, H};
-extract([_|T], S) -> extract(T,S).
-
-%% Find matching Property name from a list of OMG style QoS
-extract_value([], _) -> unsupported;
-extract_value([H|_T], Key) when H#'CosNotification_Property'.name== Key ->
- {ok, any:get_value(H#'CosNotification_Property'.value)};
-extract_value([_|T], Key) -> extract(T,Key).
-
-%% Remove matching S-QoS from a list of OMG style QoS
-remove(List, Key) ->
- lists:keydelete(Key,
- #'CosNotification_NamedPropertyRange'.name, %% get index.
- List).
-
-change(List, Key, New) ->
- lists:keyreplace(Key,
- #'CosNotification_NamedPropertyRange'.name, %% get index.
- List, New).
-%% Get QoS from supplied objects and check if it's the same as S.
-check_with_relatives([], S, LQS) ->
- {ok, S, LQS};
-check_with_relatives([undefined|T], S, LQS) ->
- check_with_relatives(T, S, LQS);
-check_with_relatives([H|T], S, LQS) ->
- case catch extract('CosNotification_QoSAdmin':get_qos(H), S) of
- {ok, S} ->
- check_with_relatives(T, S, LQS);
- _->
- %% Varioues reasons for this case (Object not responding, not supported)
- {unsupported,
- #'CosNotification_PropertyError'{
- code = 'UNAVAILABLE_PROPERTY',
- name = S#'CosNotification_Property'.name,
- available_range = #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:null(), null),
- high_val=any:create(orber_tc:null(), null)
- }
- }
- }
- end.
-
-%% Set new values to locally defined representation of QoS. Using this approach is
-%% necessary since we must state the record-field at compile-time.
-set_local_qos([], LQS) -> LQS;
-set_local_qos([#'CosNotification_Property'{name=N,value=V}|T], LQS) ->
- NewLQS =
- case N of
- "EventReliability" ->
- ?not_SetEventReliability(LQS, any:get_value(V));
- "ConnectionReliability" ->
- ?not_SetConnectionReliability(LQS, any:get_value(V));
- "Priority" ->
- ?not_SetPriority(LQS, any:get_value(V));
- "Timeout" ->
- ?not_SetTimeout(LQS, any:get_value(V));
- "OrderPolicy" ->
- ?not_SetOrderPolicy(LQS, any:get_value(V));
- "DiscardPolicy" ->
- ?not_SetDiscardPolicy(LQS, any:get_value(V));
- "MaximumBatchSize" ->
- ?not_SetMaximumBatchSize(LQS, any:get_value(V));
- "PacingInterval" ->
- ?not_SetPacingInterval(LQS, any:get_value(V));
- "StartTimeSupported" ->
- ?not_SetStartTimeSupported(LQS, any:get_value(V));
- "StopTimeSupported" ->
- ?not_SetStopTimeSupported(LQS, any:get_value(V));
- "MaxEventsPerConsumer" ->
- ?not_SetMaxEventsPerConsumer(LQS, any:get_value(V))
- end,
- set_local_qos(T, NewLQS).
-
-%%%%%%%%%%%%%%%%% END QOS FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/CosNotification_Definitions.hrl b/lib/cosNotification/src/CosNotification_Definitions.hrl
deleted file mode 100644
index 5d85c77a22..0000000000
--- a/lib/cosNotification/src/CosNotification_Definitions.hrl
+++ /dev/null
@@ -1,343 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2015. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosNotification_Definitions.hrl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--ifndef(COSNOTIFICATION_DEFINITIONS_HRL).
--define(COSNOTIFICATION_DEFINITIONS_HRL, true).
-
-%% ---------------- General comment ------------------------------------
-%% ******* README ********
-%% The prefix 'not' is short for notification, and is used to separate locally
-%% defined macros from the global ones, i.e., do NOT confuse this with a negation!!
-%%
-%% In this file you find globally used data structures, constants etc.
-%%
-
-%%--------------- INCLUDES ---------------------------------------------
-
-%%-------- Constants -------------------------------------------------
--define(not_SupportedGrammars, ["EXTENDED_TCL"]).
-
-%% !!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-%%
-%% If OMG redefines the values for the constants the definitions
-%% below must be redefined!!
-%%
-%% !!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
--define(not_BestEffort, 0).
--define(not_Persistent, 1).
--define(not_EventReliability, "EventReliability").
--define(not_ConnectionReliability, "ConnectionReliability").
--define(not_Priority, "Priority").
--define(not_LowestPriority, -32767).
--define(not_HighestPriority, 32767).
--define(not_DefaultPriority, 0).
--define(not_StartTime, "StartTime").
--define(not_StopTime, "StopTime").
--define(not_Timeout, "Timeout").
--define(not_OrderPolicy, "OrderPolicy").
--define(not_AnyOrder, 0).
--define(not_FifoOrder, 1).
--define(not_PriorityOrder, 2).
--define(not_DeadlineOrder, 3).
--define(not_DiscardPolicy, "DiscardPolicy").
--define(not_LifoOrder, 4).
--define(not_RejectNewEvents, 5).
--define(not_MaximumBatchSize, "MaximumBatchSize").
--define(not_PacingInterval, "PacingInterval").
--define(not_StartTimeSupported, "StartTimeSupported").
--define(not_StopTimeSupported, "StopTimeSupported").
--define(not_MaxEventsPerConsumer, "MaxEventsPerConsumer").
--define(not_MaxQueueLength, "MaxQueueLength").
--define(not_MaxConsumers, "MaxConsumers").
--define(not_MaxSuppliers, "MaxSuppliers").
-
-%%--------------- QOS DEFINITIONS ----------------------------
-%% Limits for QoS. These are our own limits.
--define(not_MaxBatchSize, 10000).
--define(not_MinBatchSize, 1).
--define(not_MinTimeout, 0).
--define(not_MaxTimeout, 100000000000).
--define(not_MinPacing, 0).
--define(not_MaxPacing, 100000000000).
--define(not_MinConsumerEvents, 1).
--define(not_MaxConsumerEvents, 10000).
-
--define(not_QOS_LIMITS,
-[#'CosNotification_NamedPropertyRange'
- {name=?not_EventReliability,
- range=
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:short(), ?not_BestEffort),
- high_val=any:create(orber_tc:short(), ?not_Persistent)
- }},
- #'CosNotification_NamedPropertyRange'
- {name=?not_ConnectionReliability,
- range=
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:short(), ?not_BestEffort),
- high_val=any:create(orber_tc:short(), ?not_Persistent)
- }},
- #'CosNotification_NamedPropertyRange'
- {name=?not_Priority,
- range=
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:short(), ?not_LowestPriority),
- high_val=any:create(orber_tc:short(), ?not_HighestPriority)
- }},
- #'CosNotification_NamedPropertyRange'
- {name=?not_StartTimeSupported,
- range=
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:boolean(), false),
- high_val=any:create(orber_tc:boolean(), true)
- }},
- #'CosNotification_NamedPropertyRange'
- {name=?not_StopTimeSupported,
- range=
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:boolean(), false),
- high_val=any:create(orber_tc:boolean(), true)
- }},
- #'CosNotification_NamedPropertyRange'
- {name=?not_Timeout,
- range=
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:unsigned_long_long(), ?not_MinTimeout),
- high_val=any:create(orber_tc:unsigned_long_long(), ?not_MaxTimeout)
- }},
- #'CosNotification_NamedPropertyRange'
- {name=?not_OrderPolicy,
- range=
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:short(), ?not_AnyOrder),
- high_val=any:create(orber_tc:short(), ?not_PriorityOrder)
- }},
- #'CosNotification_NamedPropertyRange'
- {name=?not_DiscardPolicy,
- range=
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:short(), ?not_AnyOrder),
- high_val=any:create(orber_tc:short(), ?not_PriorityOrder)
- }},
- #'CosNotification_NamedPropertyRange'
- {name=?not_MaximumBatchSize,
- range=
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:long(), ?not_MinBatchSize),
- high_val=any:create(orber_tc:long(), ?not_MaxBatchSize)
- }},
- #'CosNotification_NamedPropertyRange'
- {name=?not_PacingInterval,
- range=
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:unsigned_long_long(), ?not_MinPacing),
- high_val=any:create(orber_tc:unsigned_long_long(), ?not_MaxPacing)
- }},
- #'CosNotification_NamedPropertyRange'
- {name=?not_MaxEventsPerConsumer,
- range=
- #'CosNotification_PropertyRange'{
- low_val=any:create(orber_tc:long(), ?not_MinConsumerEvents),
- high_val=any:create(orber_tc:long(), ?not_MaxConsumerEvents)
- }}
-]).
-
-
-
-%% Local record used internally, and the reason for this is we get faster
-%% access to QoS settings.
--record(qos, {'EventReliability',
- 'ConnectionReliability',
- 'Priority',
- 'StartTimeSupported',
- 'StopTimeSupported',
- 'Timeout',
- 'OrderPolicy',
- 'DiscardPolicy',
- 'MaximumBatchSize',
- 'PacingInterval',
- 'MaxEventsPerConsumer'}).
-
-%% Global (OMG) representation of QoS.
--define(not_DEFAULT_QOS,
-[#'CosNotification_Property'{name=?not_MaximumBatchSize,
- value=any:create(orber_tc:long(), 1)},
- #'CosNotification_Property'{name=?not_PacingInterval,
- value=any:create(orber_tc:unsigned_long_long(), 0)},
- #'CosNotification_Property'{name=?not_Timeout,
- value=any:create(orber_tc:unsigned_long_long(), 0)},
- #'CosNotification_Property'{name=?not_MaxEventsPerConsumer,
- value=any:create(orber_tc:long(), 100)},
- #'CosNotification_Property'{name=?not_OrderPolicy,
- value=any:create(orber_tc:short(),
- ?not_PriorityOrder)},
- #'CosNotification_Property'{name=?not_EventReliability,
- value=any:create(orber_tc:short(),
- ?not_BestEffort)},
- #'CosNotification_Property'{name=?not_ConnectionReliability,
- value=any:create(orber_tc:short(),
- ?not_BestEffort)},
- #'CosNotification_Property'{name=?not_DiscardPolicy,
- value=any:create(orber_tc:short(),
- ?not_RejectNewEvents)},
- #'CosNotification_Property'{name=?not_StartTimeSupported,
- value=any:create(orber_tc:boolean(), false)},
- #'CosNotification_Property'{name=?not_StopTimeSupported,
- value=any:create(orber_tc:boolean(), false)},
- #'CosNotification_Property'{name=?not_Priority,
- value=any:create(orber_tc:short(), ?not_DefaultPriority)}]).
-
-%%--------------- QOS CREATORS -------------------------------
--define(not_CreateInitQoS(), #qos{}).
-
-%%--------------- QOS DESTRUCTORS ----------------------------
--define(not_DestroyQoS(Q), ok).
-
-%%--------------- QOS SELECTORS ------------------------------
--define(not_GetEventReliability(Q), Q#qos.'EventReliability').
--define(not_GetConnectionReliability(Q), Q#qos.'ConnectionReliability').
--define(not_GetPriority(Q), Q#qos.'Priority').
--define(not_GetStartTimeSupported(Q), Q#qos.'StartTimeSupported').
--define(not_GetStopTimeSupported(Q), Q#qos.'StopTimeSupported').
--define(not_GetTimeout(Q), Q#qos.'Timeout').
--define(not_GetOrderPolicy(Q), Q#qos.'OrderPolicy').
--define(not_GetDiscardPolicy(Q), Q#qos.'DiscardPolicy').
--define(not_GetMaximumBatchSize(Q), Q#qos.'MaximumBatchSize').
--define(not_GetPacingInterval(Q), Q#qos.'PacingInterval').
--define(not_GetMaxEventsPerConsumer(Q), Q#qos.'MaxEventsPerConsumer').
-
-%%--------------- QOS MODIFIERS ------------------------------
--define(not_SetEventReliability(Q,D), Q#qos{'EventReliability'=D}).
--define(not_SetConnectionReliability(Q,D), Q#qos{'ConnectionReliability'=D}).
--define(not_SetPriority(Q,D), Q#qos{'Priority'=D}).
--define(not_SetStartTimeSupported(Q,D), Q#qos{'StartTimeSupported'=D}).
--define(not_SetStopTimeSupported(Q,D), Q#qos{'StopTimeSupported'=D}).
--define(not_SetTimeout(Q,D), Q#qos{'Timeout'=D}).
--define(not_SetOrderPolicy(Q,D), Q#qos{'OrderPolicy'=D}).
--define(not_SetDiscardPolicy(Q,D), Q#qos{'DiscardPolicy'=D}).
--define(not_SetMaximumBatchSize(Q,D), Q#qos{'MaximumBatchSize'=D}).
--define(not_SetPacingInterval(Q,D), Q#qos{'PacingInterval'=D}).
--define(not_SetMaxEventsPerConsumer(Q,D), Q#qos{'MaxEventsPerConsumer'=D}).
-
-%%--------------- StructuredEvent CREATORS -------------------
--define(not_CreateSE(StrD,StrT,StrE,PSeqV,PSeqF,AnyR),
-#'CosNotification_StructuredEvent'{header =
- #'CosNotification_EventHeader'{fixed_header =
- #'CosNotification_FixedEventHeader'{event_type =
- #'CosNotification_EventType'{domain_name=StrD,
- type_name=StrT},
- event_name = StrE},
- variable_header = PSeqV},
- filterable_data = PSeqF,
- remainder_of_body = AnyR}).
-%% Can be used in guards.
--define(not_isConvertedAny(E),
- (((E#'CosNotification_StructuredEvent'.header)
- #'CosNotification_EventHeader'.fixed_header)
- #'CosNotification_FixedEventHeader'.event_type)
- #'CosNotification_EventType'.type_name == "%ANY").
-%% Can NOT be used in guards!!!!!
--define(not_isConvertedStructured(E),
- any:get_typecode(E) == 'CosNotification_StructuredEvent':tc()).
-
-%%--------------- StructuredEvent DESTRUCTORS ----------------
--define(not_DestroySE(E), ok).
-
-%%--------------- StructuredEvent SELECTORS ------------------
--define(not_GetSEHeader(E), E#'StructuredEvent'.header).
--define(not_GetSEFixedHeader(E), E#'StructuredEvent'.header).
-
-%%--------------- StructuredEvent MODIFIERS ------------------
-
-%%-------- QoS support -----------------------------------------------
--define(not_SUPPORTED_QOS,
-[{?not_EventReliability, 'EventReliability'},
- {?not_ConnectionReliability, 'ConnectionReliability'},
- {?not_Priority, 'Priority'},
- {?not_StartTimeSupported, 'StartTimeSupported'},
- {?not_StopTimeSupported, 'StopTimeSupported'},
- {?not_Timeout, 'Timeout'},
- {?not_OrderPolicy, 'OrderPolicy'},
- {?not_DiscardPolicy, 'DiscardPolicy'},
- {?not_MaximumBatchSize, 'MaximumBatchSize'},
- {?not_PacingInterval, 'PacingInterval'},
- {?not_MaxEventsPerConsumer, 'MaxEventsPerConsumer'}]).
-
-%%-------- ADMINPROPERTIESADMIN --------------------------------------
-
-%% According to the OMG TC Document telecom/98-11-01, p 63 (section 2.5.7), the
-%% default-value for these 3 admin properties is zero, which means that no limit
-%% applies to that property.
--define(not_DEFAULT_ADMINPROPERTIES,
-[#'CosNotification_Property'{name=?not_MaxQueueLength,
- value=any:create(orber_tc:long(), 0)},
- #'CosNotification_Property'{name=?not_MaxConsumers,
- value=any:create(orber_tc:long(), 0)},
- #'CosNotification_Property'{name=?not_MaxSuppliers,
- value=any:create(orber_tc:long(), 0)}]).
-
--define(not_SUPPORTED_ADMINPROPERTIES,
-[{?not_MaxQueueLength, 'MaxQueueLength'},
- {?not_MaxConsumers, 'MaxConsumers'},
- {?not_MaxSuppliers, 'MaxSuppliers'}]).
-
-
-%%-------- MISC --------------------------------------------------------
-
--define(not_DEFAULT_SETTINGS, [{pullInterval, 20},
- {filterOp, 'OR_OP'},
- {gcTime, 60},
- {gcLimit, 50},
- {timeService, undefined},
- {typecheck, true},
- {tty, false},
- {logfile, false},
- {server_options, []}]).
--define(not_CreateDBKey, term_to_binary({{erlang:system_time(),
- erlang:unique_integer()},
- node()})).
-
--define(DEBUG_LEVEL, 3).
-
--ifdef(debug).
-
--define(debug_print(F,A), io:format("[~p(~p)] "++F,[?MODULE, ?LINE]++A)).
--define(DBG(F,A), io:format("[~p(~p)] "++F,[?MODULE, ?LINE]++A)).
--define(not_TypeCheck(O,I), ok).
-%-define(not_TypeCheck(O,M), 'CosNotification_Common':type_check(O,M)).
-
--else.
-
--define(debug_print(F,A), ok).
--define(DBG(F,A), ok).
--define(not_TypeCheck(O,I), ok).
-
--endif.
-
-
-
--endif.
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/CosNotifyChannelAdmin.cfg b/lib/cosNotification/src/CosNotifyChannelAdmin.cfg
deleted file mode 100644
index 8647b281a2..0000000000
--- a/lib/cosNotification/src/CosNotifyChannelAdmin.cfg
+++ /dev/null
@@ -1,60 +0,0 @@
-{this, "CosNotifyChannelAdmin::EventChannel"}.
-{from, "CosNotifyChannelAdmin::EventChannel"}.
-{{handle_info, "CosNotifyChannelAdmin::EventChannel"}, true}.
-{this, "CosNotifyChannelAdmin::EventChannelFactory"}.
-{from, "CosNotifyChannelAdmin::EventChannelFactory"}.
-{{handle_info, "CosNotifyChannelAdmin::EventChannelFactory"}, true}.
-{this, "CosNotifyChannelAdmin::SupplierAdmin"}.
-{from, "CosNotifyChannelAdmin::SupplierAdmin"}.
-{{handle_info, "CosNotifyChannelAdmin::SupplierAdmin"}, true}.
-{this, "CosNotifyChannelAdmin::ConsumerAdmin"}.
-{from, "CosNotifyChannelAdmin::ConsumerAdmin"}.
-{{handle_info, "CosNotifyChannelAdmin::ConsumerAdmin"}, true}.
-{this, "CosNotifyChannelAdmin::StructuredProxyPushSupplier"}.
-{from, "CosNotifyChannelAdmin::StructuredProxyPushSupplier"}.
-{{handle_info, "CosNotifyChannelAdmin::StructuredProxyPushSupplier"}, true}.
-{{impl, "CosNotifyChannelAdmin::StructuredProxyPushSupplier"}, "PusherSupplier_impl"}.
-{this, "CosNotifyChannelAdmin::StructuredProxyPullSupplier"}.
-{from, "CosNotifyChannelAdmin::StructuredProxyPullSupplier"}.
-{{handle_info, "CosNotifyChannelAdmin::StructuredProxyPullSupplier"}, true}.
-{{impl, "CosNotifyChannelAdmin::StructuredProxyPullSupplier"}, "PullerSupplier_impl"}.
-{this, "CosNotifyChannelAdmin::ProxyPushSupplier"}.
-{from, "CosNotifyChannelAdmin::ProxyPushSupplier"}.
-{{handle_info, "CosNotifyChannelAdmin::ProxyPushSupplier"}, true}.
-{{impl, "CosNotifyChannelAdmin::ProxyPushSupplier"}, "PusherSupplier_impl"}.
-{this, "CosNotifyChannelAdmin::ProxyPullSupplier"}.
-{from, "CosNotifyChannelAdmin::ProxyPullSupplier"}.
-{{handle_info, "CosNotifyChannelAdmin::ProxyPullSupplier"}, true}.
-{{impl, "CosNotifyChannelAdmin::ProxyPullSupplier"}, "PullerSupplier_impl"}.
-{this, "CosNotifyChannelAdmin::SequenceProxyPushSupplier"}.
-{from, "CosNotifyChannelAdmin::SequenceProxyPushSupplier"}.
-{{handle_info, "CosNotifyChannelAdmin::SequenceProxyPushSupplier"}, true}.
-{{impl, "CosNotifyChannelAdmin::SequenceProxyPushSupplier"}, "PusherSupplier_impl"}.
-{this, "CosNotifyChannelAdmin::SequenceProxyPullSupplier"}.
-{from, "CosNotifyChannelAdmin::SequenceProxyPullSupplier"}.
-{{handle_info, "CosNotifyChannelAdmin::SequenceProxyPullSupplier"}, true}.
-{{impl, "CosNotifyChannelAdmin::SequenceProxyPullSupplier"}, "PullerSupplier_impl"}.
-{this, "CosNotifyChannelAdmin::StructuredProxyPushConsumer"}.
-{from, "CosNotifyChannelAdmin::StructuredProxyPushConsumer"}.
-{{handle_info, "CosNotifyChannelAdmin::StructuredProxyPushConsumer"}, true}.
-{{impl, "CosNotifyChannelAdmin::StructuredProxyPushConsumer"}, "PusherConsumer_impl"}.
-{this, "CosNotifyChannelAdmin::StructuredProxyPullConsumer"}.
-{from, "CosNotifyChannelAdmin::StructuredProxyPullConsumer"}.
-{{handle_info, "CosNotifyChannelAdmin::StructuredProxyPullConsumer"}, true}.
-{{impl, "CosNotifyChannelAdmin::StructuredProxyPullConsumer"}, "PullerConsumer_impl"}.
-{this, "CosNotifyChannelAdmin::ProxyPushConsumer"}.
-{from, "CosNotifyChannelAdmin::ProxyPushConsumer"}.
-{{handle_info, "CosNotifyChannelAdmin::ProxyPushConsumer"}, true}.
-{{impl, "CosNotifyChannelAdmin::ProxyPushConsumer"}, "PusherConsumer_impl"}.
-{this, "CosNotifyChannelAdmin::ProxyPullConsumer"}.
-{from, "CosNotifyChannelAdmin::ProxyPullConsumer"}.
-{{handle_info, "CosNotifyChannelAdmin::ProxyPullConsumer"}, true}.
-{{impl, "CosNotifyChannelAdmin::ProxyPullConsumer"}, "PullerConsumer_impl"}.
-{this, "CosNotifyChannelAdmin::SequenceProxyPushConsumer"}.
-{from, "CosNotifyChannelAdmin::SequenceProxyPushConsumer"}.
-{{handle_info, "CosNotifyChannelAdmin::SequenceProxyPushConsumer"}, true}.
-{{impl, "CosNotifyChannelAdmin::SequenceProxyPushConsumer"}, "PusherConsumer_impl"}.
-{this, "CosNotifyChannelAdmin::SequenceProxyPullConsumer"}.
-{from, "CosNotifyChannelAdmin::SequenceProxyPullConsumer"}.
-{{handle_info, "CosNotifyChannelAdmin::SequenceProxyPullConsumer"}, true}.
-{{impl, "CosNotifyChannelAdmin::SequenceProxyPullConsumer"}, "PullerConsumer_impl"}.
diff --git a/lib/cosNotification/src/CosNotifyChannelAdmin.idl b/lib/cosNotification/src/CosNotifyChannelAdmin.idl
deleted file mode 100644
index b345ff5423..0000000000
--- a/lib/cosNotification/src/CosNotifyChannelAdmin.idl
+++ /dev/null
@@ -1,275 +0,0 @@
-#ifndef _COS_NOTIFYCHANNELADMIN_IDL_
-#define _COS_NOTIFYCHANNELADMIN_IDL_
-
-#pragma prefix "omg.org"
-
-#include<cosNotificationAppComm.idl>
-#include<CosNotifyFilter.idl>
-#include<CosNotifyComm.idl>
-#include<CosNotification.idl>
-
-module CosNotifyChannelAdmin {
- exception ConnectionAlreadyActive {};
- exception ConnectionAlreadyInactive {};
- exception NotConnected {};
- // Forward declarations
- interface ConsumerAdmin;
- interface SupplierAdmin;
- interface EventChannel;
- interface EventChannelFactory;
-
- enum ProxyType {
- PUSH_ANY,
- PULL_ANY,
- PUSH_STRUCTURED,
- PULL_STRUCTURED,
- PUSH_SEQUENCE,
- PULL_SEQUENCE};
-
- enum ObtainInfoMode {
- ALL_NOW_UPDATES_OFF,
- ALL_NOW_UPDATES_ON,
- NONE_NOW_UPDATES_OFF,
- NONE_NOW_UPDATES_ON};
-
- interface ProxyConsumer : CosNotification::QoSAdmin, CosNotifyFilter::FilterAdmin {
- readonly attribute ProxyType MyType;
- readonly attribute SupplierAdmin MyAdmin;
-
- CosNotification::EventTypeSeq obtain_subscription_types(in ObtainInfoMode mode);
-
- void validate_event_qos (in CosNotification::QoSProperties required_qos,
- out CosNotification::NamedPropertyRangeSeq available_qos)
- raises (CosNotification::UnsupportedQoS);
- }; // ProxyConsumer
-
- interface ProxySupplier : CosNotification::QoSAdmin, CosNotifyFilter::FilterAdmin {
- readonly attribute ProxyType MyType;
- readonly attribute ConsumerAdmin MyAdmin;
- attribute CosNotifyFilter::MappingFilter priority_filter;
- attribute CosNotifyFilter::MappingFilter lifetime_filter;
-
- CosNotification::EventTypeSeq obtain_offered_types(in ObtainInfoMode mode);
-
- void validate_event_qos (in CosNotification::QoSProperties required_qos,
- out CosNotification::NamedPropertyRangeSeq available_qos)
- raises (CosNotification::UnsupportedQoS);
- }; // ProxySupplier
-
- interface ProxyPushConsumer : ProxyConsumer, CosNotifyComm::PushConsumer,
- CosEventChannelAdmin::ProxyPushConsumer {
- void connect_any_push_supplier (in CosEventComm::PushSupplier push_supplier)
- raises(CosEventChannelAdmin::AlreadyConnected);
- }; // ProxyPushConsumer
-
- interface StructuredProxyPushConsumer : ProxyConsumer, CosNotifyComm::StructuredPushConsumer {
- void connect_structured_push_supplier (in CosNotifyComm::StructuredPushSupplier push_supplier)
- raises(CosEventChannelAdmin::AlreadyConnected);
- }; // StructuredProxyPushConsumer
-
- interface SequenceProxyPushConsumer : ProxyConsumer, CosNotifyComm::SequencePushConsumer {
- void connect_sequence_push_supplier (in CosNotifyComm::SequencePushSupplier push_supplier)
- raises(CosEventChannelAdmin::AlreadyConnected);
- }; // SequenceProxyPushConsumer
-
- interface ProxyPullSupplier : ProxySupplier, CosNotifyComm::PullSupplier,
- CosEventChannelAdmin::ProxyPullSupplier, oe_CosNotificationComm::Event {
- void connect_any_pull_consumer (in CosEventComm::PullConsumer pull_consumer)
- raises(CosEventChannelAdmin::AlreadyConnected);
- }; // ProxyPullSupplier
-
- interface StructuredProxyPullSupplier : ProxySupplier, CosNotifyComm::StructuredPullSupplier,
- oe_CosNotificationComm::Event {
- void connect_structured_pull_consumer (in CosNotifyComm::StructuredPullConsumer pull_consumer)
- raises(CosEventChannelAdmin::AlreadyConnected);
- }; // StructuredProxyPullSupplier
-
- interface SequenceProxyPullSupplier : ProxySupplier, CosNotifyComm::SequencePullSupplier,
- oe_CosNotificationComm::Event {
- void connect_sequence_pull_consumer (in CosNotifyComm::SequencePullConsumer pull_consumer)
- raises(CosEventChannelAdmin::AlreadyConnected);
- }; // SequenceProxyPullSupplier
-
- interface ProxyPullConsumer : ProxyConsumer, CosNotifyComm::PullConsumer,
- CosEventChannelAdmin::ProxyPullConsumer {
- void connect_any_pull_supplier (in CosEventComm::PullSupplier pull_supplier)
- raises(CosEventChannelAdmin::AlreadyConnected, CosEventChannelAdmin::TypeError);
-
- void suspend_connection()
- raises(ConnectionAlreadyInactive, NotConnected);
-
- void resume_connection()
- raises(ConnectionAlreadyActive, NotConnected);
- }; // ProxyPullConsumer
-
- interface StructuredProxyPullConsumer : ProxyConsumer, CosNotifyComm::StructuredPullConsumer {
- void connect_structured_pull_supplier (in CosNotifyComm::StructuredPullSupplier pull_supplier)
- raises(CosEventChannelAdmin::AlreadyConnected, CosEventChannelAdmin::TypeError);
-
- void suspend_connection()
- raises(ConnectionAlreadyInactive, NotConnected);
-
- void resume_connection()
- raises(ConnectionAlreadyActive, NotConnected);
- }; // StructuredProxyPullConsumer
-
- interface SequenceProxyPullConsumer : ProxyConsumer, CosNotifyComm::SequencePullConsumer {
- void connect_sequence_pull_supplier (in CosNotifyComm::SequencePullSupplier pull_supplier)
- raises(CosEventChannelAdmin::AlreadyConnected, CosEventChannelAdmin::TypeError);
-
- void suspend_connection()
- raises(ConnectionAlreadyInactive, NotConnected);
-
- void resume_connection()
- raises(ConnectionAlreadyActive, NotConnected);
- }; // SequenceProxyPullConsumer
-
- interface ProxyPushSupplier : ProxySupplier, CosNotifyComm::PushSupplier,
- CosEventChannelAdmin::ProxyPushSupplier, oe_CosNotificationComm::Event {
- void connect_any_push_consumer (in CosEventComm::PushConsumer push_consumer)
- raises(CosEventChannelAdmin::AlreadyConnected, CosEventChannelAdmin::TypeError);
-
- void suspend_connection()
- raises(ConnectionAlreadyInactive, NotConnected);
-
- void resume_connection()
- raises(ConnectionAlreadyActive, NotConnected);
- }; // ProxyPushSupplier
-
- interface StructuredProxyPushSupplier : ProxySupplier, CosNotifyComm::StructuredPushSupplier,
- oe_CosNotificationComm::Event {
- void connect_structured_push_consumer (in CosNotifyComm::StructuredPushConsumer push_consumer)
- raises(CosEventChannelAdmin::AlreadyConnected, CosEventChannelAdmin::TypeError);
-
- void suspend_connection()
- raises(ConnectionAlreadyInactive, NotConnected);
-
- void resume_connection()
- raises(ConnectionAlreadyActive, NotConnected);
- }; // StructuredProxyPushSupplier
-
- interface SequenceProxyPushSupplier : ProxySupplier, CosNotifyComm::SequencePushSupplier,
- oe_CosNotificationComm::Event {
- void connect_sequence_push_consumer (in CosNotifyComm::SequencePushConsumer push_consumer)
- raises(CosEventChannelAdmin::AlreadyConnected, CosEventChannelAdmin::TypeError);
-
- void suspend_connection()
- raises(ConnectionAlreadyInactive, NotConnected);
-
- void resume_connection()
- raises(ConnectionAlreadyActive, NotConnected);
- }; // SequenceProxyPushSupplier
-
-
- typedef long ProxyID;
- typedef sequence <ProxyID> ProxyIDSeq;
-
- enum ClientType {
- ANY_EVENT,
- STRUCTURED_EVENT,
- SEQUENCE_EVENT};
-
- enum InterFilterGroupOperator {
- AND_OP,
- OR_OP };
-
- typedef long AdminID;
- typedef sequence<AdminID> AdminIDSeq;
-
- exception AdminNotFound {};
- exception ProxyNotFound {};
-
- struct AdminLimit {
- CosNotification::PropertyName name;
- CosNotification::PropertyValue value;
- };
-
- exception AdminLimitExceeded { AdminLimit admin_property_err; };
-
- interface ConsumerAdmin : CosNotification::QoSAdmin, CosNotifyComm::NotifySubscribe,
- CosNotifyFilter::FilterAdmin, CosEventChannelAdmin::ConsumerAdmin,
- oe_CosNotificationComm::Event {
- readonly attribute AdminID MyID;
- readonly attribute EventChannel MyChannel;
- readonly attribute InterFilterGroupOperator MyOperator;
- attribute CosNotifyFilter::MappingFilter priority_filter;
- attribute CosNotifyFilter::MappingFilter lifetime_filter;
- readonly attribute ProxyIDSeq pull_suppliers;
- readonly attribute ProxyIDSeq push_suppliers;
-
- ProxySupplier get_proxy_supplier (in ProxyID proxy_id)
- raises (ProxyNotFound);
-
- ProxySupplier obtain_notification_pull_supplier (in ClientType ctype, out ProxyID proxy_id)
- raises (AdminLimitExceeded);
-
- ProxySupplier obtain_notification_push_supplier (in ClientType ctype, out ProxyID proxy_id)
- raises (AdminLimitExceeded);
-
- void destroy();
- }; // ConsumerAdmin
-
- interface SupplierAdmin : CosNotification::QoSAdmin, CosNotifyComm::NotifyPublish,
- CosNotifyFilter::FilterAdmin, CosEventChannelAdmin::SupplierAdmin ,
- oe_CosNotificationComm::Event {
- readonly attribute AdminID MyID;
- readonly attribute EventChannel MyChannel;
- readonly attribute InterFilterGroupOperator MyOperator;
- readonly attribute ProxyIDSeq pull_consumers;
- readonly attribute ProxyIDSeq push_consumers;
-
- ProxyConsumer get_proxy_consumer (in ProxyID proxy_id)
- raises (ProxyNotFound);
-
- ProxyConsumer obtain_notification_pull_consumer (in ClientType ctype, out ProxyID proxy_id)
- raises (AdminLimitExceeded);
-
- ProxyConsumer obtain_notification_push_consumer (in ClientType ctype, out ProxyID proxy_id)
- raises (AdminLimitExceeded);
-
- void destroy();
- }; // SupplierAdmin
-
- interface EventChannel : CosNotification::QoSAdmin, CosNotification::AdminPropertiesAdmin,
- CosEventChannelAdmin::EventChannel,
- oe_CosNotificationComm::Event {
- readonly attribute EventChannelFactory MyFactory;
- readonly attribute ConsumerAdmin default_consumer_admin;
- readonly attribute SupplierAdmin default_supplier_admin;
- readonly attribute CosNotifyFilter::FilterFactory default_filter_factory;
-
- ConsumerAdmin new_for_consumers(in InterFilterGroupOperator op, out AdminID id);
-
- SupplierAdmin new_for_suppliers(in InterFilterGroupOperator op, out AdminID id);
-
- ConsumerAdmin get_consumeradmin (in AdminID id)
- raises (AdminNotFound);
-
- SupplierAdmin get_supplieradmin (in AdminID id)
- raises (AdminNotFound);
-
- AdminIDSeq get_all_consumeradmins();
-
- AdminIDSeq get_all_supplieradmins();
- }; // EventChannel
-
- typedef long ChannelID;
- typedef sequence<ChannelID> ChannelIDSeq;
- exception ChannelNotFound {};
-
- interface EventChannelFactory {
- EventChannel create_channel (in CosNotification::QoSProperties initial_qos,
- in CosNotification::AdminProperties initial_admin,
- out ChannelID id)
- raises(CosNotification::UnsupportedQoS, CosNotification::UnsupportedAdmin);
-
- ChannelIDSeq get_all_channels();
-
- EventChannel get_event_channel (in ChannelID id)
- raises (ChannelNotFound);
- }; // EventChannelFactory
-}; // CosNotifyChannelAdmin
-
-
-#endif /* ifndef _COS_NOTIFYCHANNELADMIN_IDL_ */
-
diff --git a/lib/cosNotification/src/CosNotifyChannelAdmin_ConsumerAdmin_impl.erl b/lib/cosNotification/src/CosNotifyChannelAdmin_ConsumerAdmin_impl.erl
deleted file mode 100644
index e7a6a35ea7..0000000000
--- a/lib/cosNotification/src/CosNotifyChannelAdmin_ConsumerAdmin_impl.erl
+++ /dev/null
@@ -1,671 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-------------------------------------------------------------------
-%% File : CosNotifyChannelAdmin_ConsumerAdmin_impl.erl
-%% Purpose :
-%%-------------------------------------------------------------------
-
--module('CosNotifyChannelAdmin_ConsumerAdmin_impl').
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-%% Application files
--include("CosNotification.hrl").
--include("CosNotifyChannelAdmin.hrl").
--include("CosNotifyComm.hrl").
--include("CosNotifyFilter.hrl").
--include("CosNotification_Definitions.hrl").
-
-%%--------------- EXPORTS ------------------------------------
-%%--------------- External -----------------------------------
-%%----- CosNotifyChannelAdmin::ConsumerAdmin -----------------
--export([get_proxy_supplier/4,
- obtain_notification_pull_supplier/4,
- obtain_notification_push_supplier/4,
- destroy/3]).
-
-%%----- Inherit from CosNotification::QoSAdmin ---------------
--export([get_qos/3,
- set_qos/4,
- validate_qos/4]).
-
-%%----- Inherit from CosNotifyComm::NotifySubscribe ----------
--export([subscription_change/5]).
-
-%%----- Inherit from CosNotifyFilter::FilterAdmin ------------
--export([add_filter/4,
- remove_filter/4,
- get_filter/4,
- get_all_filters/3,
- remove_all_filters/3]).
-
-%%----- Inherit from CosEventChannelAdmin::ConsumerAdmin -----
--export([obtain_push_supplier/3,
- obtain_pull_supplier/3]).
-
-%% Attributes (external)
--export(['_get_MyID'/3,
- '_get_MyChannel'/3,
- '_get_MyOperator'/3,
- '_get_priority_filter'/3,
- '_set_priority_filter'/4,
- '_get_lifetime_filter'/3,
- '_set_lifetime_filter'/4,
- '_get_pull_suppliers'/3,
- '_get_push_suppliers'/3]).
-
-%%--------------- Internal -----------------------------------
-%%----- Inherit from cosNotificationComm ---------------------
--export([callAny/5,
- callSeq/5]).
-
-%%--------------- gen_server specific exports ----------------
--export([handle_info/2, code_change/3]).
--export([init/1, terminate/2]).
-
-%%--------------- LOCAL DEFINITIONS --------------------------
-%% Data structures
--record(state, {myId,
- myChannel,
- myChannelPid,
- myOperator,
- myFilters = [],
- mySuppliers = [],
- idCounter = 0,
- priorityFilter,
- lifetimeFilter,
- etsR,
- qosGlobal,
- qosLocal,
- options}).
-
-%% Data structures constructors
--define(get_InitState(_MyID, _MyCh, _MyChP, _MyOp, _PFil, _LFil, _QoS, _LQS, _O),
- #state{myId = _MyID,
- myChannel = _MyCh,
- myChannelPid = _MyChP,
- myOperator = _MyOp,
- priorityFilter = _PFil,
- lifetimeFilter = _LFil,
- qosGlobal = _QoS,
- qosLocal = _LQS,
- options = _O,
- etsR = ets:new(oe_ets, [set, protected])}).
-
-%% Data structures selectors
--define(get_PushSupplierIDs(S), find_ids(S#state.mySuppliers, pusher)).
--define(get_PullSupplierIDs(S), find_ids(S#state.mySuppliers, puller)).
--define(get_AllSuppliers(S), S#state.mySuppliers).
--define(get_AllSupplierRefs(S), find_refs(S#state.mySuppliers)).
--define(get_Supplier(S, I), find_obj(lists:keysearch(I,1,S#state.mySuppliers),
- supplier)).
-
--define(get_MyID(S), S#state.myId).
--define(get_MyChannel(S), S#state.myChannel).
--define(get_MyChannelPid(S), S#state.myChannelPid).
--define(get_MyOperator(S), S#state.myOperator).
--define(get_PrioFilter(S), S#state.priorityFilter).
--define(get_LifeFilter(S), S#state.lifetimeFilter).
--define(get_GlobalQoS(S), S#state.qosGlobal).
--define(get_LocalQoS(S), S#state.qosLocal).
--define(get_BothQoS(S), {S#state.qosGlobal, S#state.qosLocal}).
--define(get_Filter(S, I), find_obj(lists:keysearch(I, 1, S#state.myFilters),
- filter)).
--define(get_AllFilter(S), S#state.myFilters).
--define(get_AllFilterID(S), find_ids(S#state.myFilters)).
--define(get_Options(S), S#state.options).
--define(get_IdCounter(S), S#state.idCounter).
-
-%% Data structures modifiers
--define(set_PrioFilter(S,D), S#state{priorityFilter=D}).
--define(set_LifeFilter(S,D), S#state{lifetimeFilter=D}).
--define(set_LocalQoS(S,D), S#state{qosLocal=D}).
--define(set_GlobalQoS(S,D), S#state{qosGlobal=D}).
--define(set_BothQoS(S,GD,LD), S#state{qosGlobal=GD, qosLocal=LD}).
--define(add_PushSupplier(S,I,R,P),S#state{mySuppliers=[{I,R,P,pusher}|S#state.mySuppliers]}).
--define(add_PullSupplier(S,I,R,P),S#state{mySuppliers=[{I,R,P,puller}|S#state.mySuppliers]}).
--define(del_Supplier(S,I), S#state{mySuppliers=
- lists:keydelete(I, 1,
- S#state.mySuppliers)}).
--define(del_SupplierRef(S,O), S#state{mySuppliers=
- lists:keydelete(O, 2,
- S#state.mySuppliers)}).
--define(del_SupplierPid(S,P), S#state{mySuppliers=
- lists:keydelete(P, 3,
- S#state.mySuppliers)}).
--define(add_Filter(S,I,O), S#state{myFilters=[{I,O}|S#state.myFilters]}).
--define(del_Filter(S,I), S#state{myFilters=
- delete_filter(lists:keydelete(I, 1,
- S#state.myFilters),
- S#state.myFilters)}).
--define(del_AllFilter(S), S#state{myFilters=[]}).
--define(set_IdCounter(S,V), S#state{idCounter=V}).
--define(new_Id(S), 'CosNotification_Common':create_id(
- S#state.idCounter)).
-
-%% MISC
--define(is_PersistentConnection(S),
- ?not_GetConnectionReliability((S#state.qosLocal)) == ?not_Persistent).
--define(is_PersistentEvent(S),
- ?not_GetEventReliability((S#state.qosLocal)) == ?not_Persistent).
--define(is_ANDOP(S), S#state.myOperator == 'AND_OP').
-
-%%----------------------------------------------------------%
-%% function : handle_info, code_change
-%% Arguments:
-%% Returns :
-%% Effect : Functions demanded by the gen_server module.
-%%-----------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-handle_info(Info, State) ->
- case Info of
- {'EXIT', Pid, Reason} when ?get_MyChannelPid(State) == Pid ->
- ?DBG("PARENT CHANNEL: ~p TERMINATED.~n",[Reason]),
- {stop, Reason, State};
- {'EXIT', Pid, normal} ->
- {noreply, ?del_SupplierPid(State, Pid)};
- _Other ->
- {noreply, State}
- end.
-
-%%----------------------------------------------------------%
-%% function : init, terminate
-%% Arguments:
-%%-----------------------------------------------------------
-
-init([MyId, MyChannel, MyChannelPid, MyOperator, InitQoS, LQS, Options]) ->
- process_flag(trap_exit, true),
- PriorityFilter = corba:create_nil_objref(),
- LifeTimeFilter = corba:create_nil_objref(),
- {ok, ?get_InitState(MyId, MyChannel, MyChannelPid, MyOperator,
- PriorityFilter, LifeTimeFilter, InitQoS, LQS, Options)}.
-
-terminate(_Reason, _State) ->
- ok.
-
-%%-----------------------------------------------------------
-%%----- CosNotifyChannelAdmin_ConsumerAdmin attributes ------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% Attribute: '_get_MyID'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_MyID'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_MyID(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_MyChannel'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_MyChannel'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_MyChannel(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_MyOperator'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_MyOperator'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_MyOperator(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_priority_filter'
-%% Type : read and write
-%% Returns :
-%%-----------------------------------------------------------
-'_get_priority_filter'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_PrioFilter(State), State}.
-
-'_set_priority_filter'(_OE_THIS, _OE_FROM, State, PrioFilter) ->
- {reply, ok, ?set_PrioFilter(State, PrioFilter)}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_lifetime_filter'
-%% Type : read and write
-%% Returns :
-%%-----------------------------------------------------------
-'_get_lifetime_filter'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_LifeFilter(State), State}.
-'_set_lifetime_filter'(_OE_THIS, _OE_FROM, State, LifeFilter) ->
- {reply, ok, ?set_LifeFilter(State, LifeFilter)}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_pull_suppliers'
-%% Type : readonly
-%% Returns : ProxyIDSeq
-%%-----------------------------------------------------------
-'_get_pull_suppliers'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_PullSupplierIDs(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_push_suppliers'
-%% Type : readonly
-%% Returns : ProxyIDSeq
-%%-----------------------------------------------------------
-'_get_push_suppliers'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_PushSupplierIDs(State), State}.
-
-%%-----------------------------------------------------------
-%%------- Exported external functions -----------------------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% function : get_proxy_supplier
-%% Arguments: ProxyID - unique identifier (long)
-%% Returns : ObjRef | {'EXCEPTION', #'ProxyNotFound'{}}
-%%-----------------------------------------------------------
-get_proxy_supplier(_OE_THIS, _OE_FROM, State, Proxy_id) ->
- {reply, ?get_Supplier(State, Proxy_id), State}.
-
-%%----------------------------------------------------------%
-%% function : obtain_notification_pull_supplier
-%% Arguments: Ctype - 'ANY_EVENT' | 'STRUCTURED_EVENT' | 'SEQUENCE_EVENT'
-%% Returns : A Proxy of the requested type.
-%%-----------------------------------------------------------
-obtain_notification_pull_supplier(OE_THIS, _OE_FROM, State, Ctype) ->
- %% Choose which module to use.
- {Mod, Type} =
- case Ctype of
- 'ANY_EVENT' ->
- {'CosNotifyChannelAdmin_ProxyPullSupplier', 'PULL_ANY'};
- 'STRUCTURED_EVENT' ->
- {'CosNotifyChannelAdmin_StructuredProxyPullSupplier', 'PULL_STRUCTURED'};
- 'SEQUENCE_EVENT' ->
- {'CosNotifyChannelAdmin_SequenceProxyPullSupplier', 'PULL_SEQUENCE'};
- _ ->
- orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:"
- "obtain_notification_pull_supplier(~p);~n"
- "Incorrect enumerant",
- [?LINE, Ctype], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end,
- SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- case Mod:oe_create_link([Type, OE_THIS, self(), ?get_GlobalQoS(State),
- ?get_LocalQoS(State), ?get_MyChannel(State),
- ?get_Options(State), ?get_MyOperator(State)],
- [{sup_child, true}|SO]) of
- {ok, Pid, PrRef} ->
- ProxyID = ?new_Id(State),
- NewState = ?add_PullSupplier(State, ProxyID, PrRef, Pid),
- {reply, {PrRef, ProxyID}, ?set_IdCounter(NewState, ProxyID)};
- What ->
- orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:"
- "obtain_notification_pull_supplier();~n"
- "Unable to create: ~p/~p~n"
- "Reason: ~p", [?LINE, Mod, Type, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------%
-%% function : obtain_notification_push_supplier
-%% Arguments: Ctype - 'ANY_EVENT' | 'STRUCTURED_EVENT' | 'SEQUENCE_EVENT'
-%% Returns : A Proxy of the requested type.
-%%-----------------------------------------------------------
-obtain_notification_push_supplier(OE_THIS, _OE_FROM, State, Ctype) ->
- %% Choose which module to use.
- {Mod, Type} =
- case Ctype of
- 'ANY_EVENT' ->
- {'CosNotifyChannelAdmin_ProxyPushSupplier', 'PUSH_ANY'};
- 'STRUCTURED_EVENT' ->
- {'CosNotifyChannelAdmin_StructuredProxyPushSupplier', 'PUSH_STRUCTURED'};
- 'SEQUENCE_EVENT' ->
- {'CosNotifyChannelAdmin_SequenceProxyPushSupplier', 'PUSH_SEQUENCE'};
- _ ->
- orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:"
- "obtain_notification_push_supplier(~p);~n"
- "Incorrect enumerant", [?LINE, Ctype], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end,
- SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- case Mod:oe_create_link([Type, OE_THIS, self(), ?get_GlobalQoS(State),
- ?get_LocalQoS(State), ?get_MyChannel(State),
- ?get_Options(State), ?get_MyOperator(State)],
- [{sup_child, true}|SO]) of
- {ok, Pid, PrRef} ->
- ProxyID = ?new_Id(State),
- NewState = ?add_PushSupplier(State, ProxyID, PrRef, Pid),
- {reply, {PrRef, ProxyID}, ?set_IdCounter(NewState, ProxyID)};
- What ->
- orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:obtain_notification_push_supplier();~n"
- "Unable to create: ~p/~p~n"
- "Reason: ~p",
- [?LINE, Mod, Type, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-
-%%----------------------------------------------------------%
-%% function : destroy
-%% Arguments: -
-%% Returns : ok
-%%------------------------------------------------------------
-destroy(_OE_THIS, _OE_FROM, State) ->
- {stop, normal, ok, State}.
-
-%%----- Inherit from CosNotification::QoSAdmin --------------
-%%----------------------------------------------------------%
-%% function : get_qos
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-get_qos(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_GlobalQoS(State), State}.
-
-%%----------------------------------------------------------%
-%% function : set_qos
-%% Arguments: QoS - CosNotification::QoSProperties, i.e.,
-%% [#'Property'{name, value}, ...] where name eq. string()
-%% and value eq. any().
-%% Returns : ok | {'EXCEPTION', CosNotification::UnsupportedQoS}
-%%-----------------------------------------------------------
-set_qos(_OE_THIS, _OE_FROM, State, QoS) ->
- {NewQoS, LQS} = 'CosNotification_Common':set_qos(QoS, ?get_BothQoS(State),
- admin, ?get_MyChannel(State),
- ?get_AllSupplierRefs(State)),
- {reply, ok, ?set_BothQoS(State, NewQoS, LQS)}.
-
-%%----------------------------------------------------------%
-%% function : validate_qos
-%% Arguments: Required_qos - CosNotification::QoSProperties
-%% [#'Property'{name, value}, ...] where name eq. string()
-%% and value eq. any().
-%% Returns : {'EXCEPTION', CosNotification::UnsupportedQoS}
-%%-----------------------------------------------------------
-validate_qos(_OE_THIS, _OE_FROM, State, Required_qos) ->
- QoS = 'CosNotification_Common':validate_qos(Required_qos, ?get_BothQoS(State),
- admin, ?get_MyChannel(State),
- ?get_AllSupplierRefs(State)),
- {reply, {ok, QoS}, State}.
-
-%%----- Inherit from CosNotifyComm::NotifySubscribe ---------
-%%----------------------------------------------------------*
-%% function : subscription_change
-%% Arguments:
-%% Returns : ok |
-%% {'EXCEPTION', #'CosNotifyComm_InvalidEventType'{type}}
-%%-----------------------------------------------------------
-subscription_change(_OE_THIS, _OE_FROM, State, _Added, _Removed) ->
- ?DBG("CALLBACK INFORMED: ~p ~p~n",[_Added, _Removed]),
- {reply, ok, State}.
-
-%%----- Inherit from CosNotifyFilter::FilterAdmin -----------
-%%----------------------------------------------------------%
-%% function : add_filter
-%% Arguments: Filter - CosNotifyFilter::Filter
-%% Returns : FilterID - long
-%%-----------------------------------------------------------
-add_filter(_OE_THIS, _OE_FROM, State, Filter) ->
- 'CosNotification_Common':type_check(Filter, 'CosNotifyFilter_Filter'),
- FilterID = ?new_Id(State),
- NewState = ?set_IdCounter(State, FilterID),
- {reply, FilterID, ?add_Filter(NewState, FilterID, Filter)}.
-
-%%----------------------------------------------------------%
-%% function : remove_filter
-%% Arguments: FilterID - long
-%% Returns : ok
-%%-----------------------------------------------------------
-remove_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
- {reply, ok, ?del_Filter(State, FilterID)};
-remove_filter(_,_,_,_) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : get_filter
-%% Arguments: FilterID - long
-%% Returns : Filter - CosNotifyFilter::Filter |
-%% {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}
-%%-----------------------------------------------------------
-get_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
- {reply, ?get_Filter(State, FilterID), State};
-get_filter(_,_,_,_) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : get_all_filters
-%% Arguments: -
-%% Returns : Filter - CosNotifyFilter::FilterIDSeq
-%%-----------------------------------------------------------
-get_all_filters(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_AllFilterID(State), State}.
-
-%%----------------------------------------------------------%
-%% function : remove_all_filters
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-remove_all_filters(_OE_THIS, _OE_FROM, State) ->
- {reply, ok, ?del_AllFilter(State)}.
-
-%%----- Inherit from CosEventChannelAdmin::ConsumerAdmin ----
-%%----------------------------------------------------------%
-%% function : obtain_push_supplier
-%% Arguments: -
-%% Returns : ProxyPushSupplier
-%%-----------------------------------------------------------
-obtain_push_supplier(OE_THIS, _OE_FROM, State) ->
- SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- case 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_create_link(['PUSH_ANY', OE_THIS,
- self(),
- ?get_GlobalQoS(State),
- ?get_LocalQoS(State),
- ?get_MyChannel(State),
- ?get_Options(State),
- ?get_MyOperator(State)],
- [{sup_child, true}|SO]) of
- {ok, Pid, PrRef} ->
- ProxyID = ?new_Id(State),
- NewState = ?add_PushSupplier(State, ProxyID, PrRef, Pid),
- {reply, PrRef, ?set_IdCounter(NewState, ProxyID)};
- What ->
- orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:obtain_push_supplier();~n"
- "Unable to create: CosNotifyChannelAdmin_ProxyPushSupplier~n"
- "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------%
-%% function : obtain_pull_supplier
-%% Arguments: -
-%% Returns : ProxyPullSupplier
-%%-----------------------------------------------------------
-obtain_pull_supplier(OE_THIS, _OE_FROM, State) ->
- SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- case 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_create_link(['PULL_ANY', OE_THIS,
- self(),
- ?get_GlobalQoS(State),
- ?get_LocalQoS(State),
- ?get_MyChannel(State),
- ?get_Options(State),
- ?get_MyOperator(State)],
- [{sup_child, true}|SO]) of
- {ok, Pid, PrRef} ->
- ProxyID = ?new_Id(State),
- NewState = ?add_PullSupplier(State, ProxyID, PrRef, Pid),
- {reply, PrRef, ?set_IdCounter(NewState, ProxyID)};
- What ->
- orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:obtain_pull_supplier();~n"
- "Unable to create: CosNotifyChannelAdmin_ProxyPullSupplier~n"
- "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-%% To match suppliers
-find_obj({value, {_,Obj,_,_}},_) -> Obj;
-%% To match filters
-find_obj({value, {_,Obj}},_) -> Obj;
-find_obj(_, supplier) -> {'EXCEPTION', #'CosNotifyChannelAdmin_ProxyNotFound'{}};
-find_obj(_, filter) -> {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}.
-
-find_ids(List) ->
- find_ids(List, [], false).
-find_ids(List, Type) ->
- find_ids(List, [], Type).
-
-find_ids([], Acc, _) ->
- Acc;
-find_ids([{I,_}|T], Acc, Type) ->
- find_ids(T, [I|Acc], Type);
-find_ids([{I,_,_,Type}|T], Acc, Type) ->
- find_ids(T, [I|Acc], Type);
-find_ids([{_I,_,_,_}|T], Acc, Type) ->
- find_ids(T, Acc, Type);
-find_ids(What, _, _) ->
- orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:find_ids();~n"
- "Id corrupt: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
-
-find_refs(List) ->
- find_refs(List, []).
-
-find_refs([], Acc) ->
- Acc;
-find_refs([{_,R,_,_}|T], Acc) ->
- find_refs(T, [R|Acc]);
-find_refs(What, _) ->
- orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:find_refs();~n"
- "Reference corrupt: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
-
-%% Delete a single filter.
-%% The list do not differ, i.e., no filter removed, raise exception.
-delete_filter(List,List) -> corba:raise(#'CosNotifyFilter_FilterNotFound'{});
-delete_filter(List, _) -> List.
-
-
-%%-----------------------------------------------------------
-%% function : callSeq
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-callSeq(_OE_THIS, OE_FROM, State, Events, _Status) ->
- corba:reply(OE_FROM, ok),
- case cosNotification_eventDB:filter_events(Events, ?get_AllFilter(State)) of
- {[], _} when ?is_ANDOP(State) ->
- %% Since AND it doesn't matter what the proxies 'think'. Done.
- {noreply, State};
- {[], Failed} ->
- %% Is OR but the Proxy may allow the events; pass on.
- forward(seq, State, Failed, 'MATCH');
- {Passed, _} when ?is_ANDOP(State) ->
- %% Since AND we only forward those who passed this objects filters.
- forward(seq, State, Passed, 'MATCH');
- {Passed, []} ->
- %% Since OR we forward and tell the proxy to do no filtering.
- forward(seq, State, Passed, 'MATCHED');
- {Passed, Failed} ->
- %% Since OR we forward both and instruct the proxy to check only
- %% the ones that failed.
- forward(seq, State, Passed, 'MATCHED'),
- forward(seq, State, Failed, 'MATCH')
- end.
-
-
-%%-----------------------------------------------------------
-%% function : callAny
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-callAny(_OE_THIS, OE_FROM, State, Event, _Status) ->
- corba:reply(OE_FROM, ok),
- case cosNotification_eventDB:filter_events([Event], ?get_AllFilter(State)) of
- {[], _} when ?is_ANDOP(State) ->
- %% Since AND it doesn't matter what the proxies 'think'. Done.
- {noreply, State};
- {[], [Failed]} ->
- %% Is OR but the Proxy may allow the event; pass on.
- forward(any, State, Failed, 'MATCH');
- {[Passed], _} when ?is_ANDOP(State) ->
- %% Since AND we only forward those who passed this objects filters.
- forward(any, State, Passed, 'MATCH');
- {[Passed], _} ->
- %% Since OR we forward and instruct the proxy to do no checks.
- forward(any, State, Passed, 'MATCHED')
- end.
-
-
-
-%% Forward events
-forward(Type, State, Event, Status) ->
- forward(Type, ?get_AllSuppliers(State), State, Event, Status).
-forward(_, [], State, _, _) ->
- {noreply, State};
-forward(any, [{_,H,_,_}|T], State, Event, Status) ->
- case catch oe_CosNotificationComm_Event:callAny(H, Event, Status) of
- ok ->
- ?DBG("CONSUMERADM FORWARD ANY: ~p~n",[Event]),
- forward(any, T, State, Event, Status);
- {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') ->
- orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:forward();~n"
- "Proxy no longer exists; dropping it: ~p",
- [?LINE, H], ?DEBUG_LEVEL),
- NewState = ?del_SupplierRef(State,H),
- forward(any, T, NewState, Event, Status);
- R when ?is_PersistentConnection(State) ->
- orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:forward();~n"
- "Proxy behaves badly: ~p/~p",
- [?LINE, R, H], ?DEBUG_LEVEL),
- forward(any, T, State, Event, Status);
- R ->
- orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:forward();~n"
- "Proxy behaves badly: ~p~n"
- "Dropping it: ~p", [?LINE, R, H], ?DEBUG_LEVEL),
- NewState = ?del_SupplierRef(State, H),
- forward(any, T, NewState, Event, Status)
- end;
-forward(seq, [{_,H,_,_}|T], State, Event, Status) ->
- case catch oe_CosNotificationComm_Event:callSeq(H, Event, Status) of
- ok ->
- ?DBG("CONSUMERADM FORWARD SEQUENCE: ~p~n",[Event]),
- forward(seq, T, State, Event, Status);
- {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') ->
- orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:forward();~n"
- "Proxy no longer exists; dropping it: ~p",
- [?LINE, H], ?DEBUG_LEVEL),
- NewState = ?del_SupplierRef(State,H),
- forward(seq, T, NewState, Event, Status);
- R when ?is_PersistentConnection(State) ->
- orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:forward();~n"
- "Proxy behaves badly: ~p/~p", [?LINE, R, H], ?DEBUG_LEVEL),
- forward(seq, T, State, Event, Status);
- R ->
- orber:dbg("[~p] CosNotifyChannelAdmin_ConsumerAdmin:forward();~n"
- "Proxy behaves badly: ~p~n"
- "Dropping it: ~p", [?LINE, R, H], ?DEBUG_LEVEL),
- NewState = ?del_SupplierRef(State, H),
- forward(seq, T, NewState, Event, Status)
- end.
-
-
-%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/CosNotifyChannelAdmin_EventChannelFactory_impl.erl b/lib/cosNotification/src/CosNotifyChannelAdmin_EventChannelFactory_impl.erl
deleted file mode 100644
index eb3fb4a6a3..0000000000
--- a/lib/cosNotification/src/CosNotifyChannelAdmin_EventChannelFactory_impl.erl
+++ /dev/null
@@ -1,143 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-------------------------------------------------------------------
-%% File : CosNotifyChannelAdmin_EventChannelFactory_impl.erl
-%% Purpose :
-%%-------------------------------------------------------------------
-
--module('CosNotifyChannelAdmin_EventChannelFactory_impl').
-
-%%--------------- INCLUDES -----------------------------------
-%% Application files
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-%% Application files
--include("CosNotification.hrl").
--include("CosNotifyChannelAdmin.hrl").
--include("CosNotifyComm.hrl").
--include("CosNotifyFilter.hrl").
--include("CosNotification_Definitions.hrl").
-
-%%--------------- IMPORTS ------------------------------------
-
-%%--------------- EXPORTS ------------------------------------
-%% External
--export([create_channel/5,
- get_all_channels/3,
- get_event_channel/4]).
-
-%%--------------- gen_server specific exports ----------------
--export([handle_info/2, code_change/3]).
--export([init/1, terminate/2]).
-
-%%--------------- LOCAL DEFINITIONS --------------------------
-%% Data structures
--record(state, {adminProp,
- idCounter = 0,
- options,
- etsR,
- server_options}).
-
-%%-----------------------------------------------------------%
-%% function : handle_info, code_change
-%% Arguments: See gen_server documentation.
-%% Effect : Functions demanded by the gen_server module.
-%%------------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-handle_info(Info, State) ->
- ?debug_print("INFO: ~p~n", [Info]),
- case Info of
- {'EXIT', Pid, normal} ->
- ets:match_delete(State#state.etsR, {'_','_',Pid}),
- {noreply, State};
- _Other ->
- ?debug_print("TERMINATED: ~p~n",[_Other]),
- {noreply, State}
- end.
-
-%%----------------------------------------------------------%
-%% function : init, terminate
-%% Arguments:
-%%-----------------------------------------------------------
-
-init(Options) ->
- process_flag(trap_exit, true),
- SO = 'CosNotification_Common':get_option(server_options, Options, ?not_DEFAULT_SETTINGS),
- {ok, #state{options = Options,
- etsR = ets:new(oe_ets, [set, protected]),
- server_options = SO}}.
-
-terminate(_Reason, _State) ->
- ok.
-
-%%-----------------------------------------------------------
-%%------- Exported external functions -----------------------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% function : create_channel
-%% Arguments: InitQoS
-%% InitAdmin
-%% Returns : Ch - Channel obj ref
-%% Id - Channel Id (out-type)
-%%-----------------------------------------------------------
-create_channel(OE_THIS, _OE_FROM, State, InitQoS, InitAdmin) ->
- {QoS, LQoS} = 'CosNotification_Common':init_qos(InitQoS),
- {IAdm, LAdm} = 'CosNotification_Common':init_adm(InitAdmin),
- Id = 'CosNotification_Common':create_id(State#state.idCounter),
- case 'CosNotifyChannelAdmin_EventChannel':oe_create_link([OE_THIS, QoS, IAdm,
- LQoS, LAdm,
- State#state.options],
- [{sup_child, true}|State#state.server_options]) of
- {ok, Pid, Ch} ->
- ets:insert(State#state.etsR, {Id,Ch,Pid}),
- {reply, {Ch, Id}, State#state{idCounter=Id}};
- _ ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------%
-%% function : get_all_channels
-%% Arguments: -
-%% Returns : ChannelIDSeq - List of alive channels created
-%% by this factory.
-%%-----------------------------------------------------------
-get_all_channels(_OE_THIS, _OE_FROM, State) ->
- {reply, lists:flatten(ets:match(State#state.etsR, {'$1','_','_'})), State}.
-
-%%----------------------------------------------------------%
-%% function : get_event_channel
-%% Arguments: ChannelId
-%% Returns : ChannelRef | 'CosNotifyChannelAdmin_ChannelNotFound'
-%%-----------------------------------------------------------
-get_event_channel(_OE_THIS, _OE_FROM, State, Id) ->
- {reply, find_obj(ets:lookup(State#state.etsR, Id)), State}.
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-find_obj([]) -> {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}};
-find_obj([{_, Obj,_}]) -> Obj;
-find_obj(_) -> {'EXCEPTION', #'CosNotifyChannelAdmin_ChannelNotFound'{}}.
-
-%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/CosNotifyChannelAdmin_EventChannel_impl.erl b/lib/cosNotification/src/CosNotifyChannelAdmin_EventChannel_impl.erl
deleted file mode 100644
index 485c9aeef4..0000000000
--- a/lib/cosNotification/src/CosNotifyChannelAdmin_EventChannel_impl.erl
+++ /dev/null
@@ -1,722 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-------------------------------------------------------------------
-%% File : CosNotifyChannelAdmin_EventChannel_impl.erl
-%% Purpose :
-%% Created : 28 Sep 1999
-%%-------------------------------------------------------------------
-
--module('CosNotifyChannelAdmin_EventChannel_impl').
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-%% Application files
--include("CosNotification.hrl").
--include("CosNotifyChannelAdmin.hrl").
--include("CosNotifyComm.hrl").
--include("CosNotifyFilter.hrl").
--include("CosNotification_Definitions.hrl").
-
-%%--------------- EXPORTS ------------------------------------
-%%--------------- External -----------------------------------
-%%----- CosNotifyChannelAdmin::EventChannel ------------------
--export([new_for_consumers/4,
- new_for_suppliers/4,
- get_consumeradmin/4,
- get_supplieradmin/4,
- get_all_consumeradmins/3,
- get_all_supplieradmins/3]).
-
-%% Attributes (external)
--export(['_get_MyFactory'/3,
- '_get_default_consumer_admin'/3,
- '_get_default_supplier_admin'/3,
- '_get_default_filter_factory'/3]).
-
-%%----- Inherit from CosNotification::QoSAdmin ---------------
--export([get_qos/3,
- set_qos/4,
- validate_qos/4]).
-
-%%----- Inherit from CosNotification::AdminPropertiesAdmin ---
--export([get_admin/3,
- set_admin/4]).
-
-%%----- Inherit from CosEventChannelAdmin::EventChannel ------
--export([for_consumers/3,
- for_suppliers/3,
- destroy/3]).
-%%--------------- Internal -----------------------------------
-%%----- Inherit from cosNotificationComm ---------------------
--export([callAny/5,
- callSeq/5]).
-
-%%--------------- gen_server specific exports ----------------
--export([handle_info/2, code_change/3]).
--export([init/1, terminate/2]).
-
-%% Data structures
--record(state, {myFac,
- myConsumers = [],
- defConsumerAdmin,
- defSupplierAdmin,
- defConsumerAdminPid,
- defSupplierAdminPid,
- defFilterFac,
- defFilterFacPid,
- etsR,
- qosLocal,
- qosGlobal,
- admGlobal,
- options,
- idCounter = 0,
- 'MaxQueueLength',
- 'MaxConsumers',
- 'MaxSuppliers'}).
-%% Data structures constructors
--define(get_InitState(My, Fil, FilPid, QoS, LQoS, GA, MQ, MC, MS, O),
- #state{myFac = My,
- defFilterFac = Fil,
- defFilterFacPid = FilPid,
- etsR = ets:new(oe_ets, [set, protected]),
- qosLocal = LQoS,
- qosGlobal = QoS,
- admGlobal = GA,
- options = O,
- 'MaxQueueLength' = MQ,
- 'MaxConsumers' = MC,
- 'MaxSuppliers' = MS}).
-
-%% NOTE!!!
-%% When forwarding events, the objects we will contact is ONLY ConsumerAdmins!!
-%% Hence, we will store SupplierAdmins and ConsumerAdmins differently. SupplierAdmins
-%% we store in our ets-table while the ConsumerAdmins will be stored on the local
-%% State.
-
-%% Data structures selectors
--define(get_supplierAdmins(S), [S#state.defSupplierAdmin|
- lists:flatten(ets:match(S#state.etsR,
- {'_','$1','_'}))]).
--define(get_consumerAdmins(S), [{0, S#state.defConsumerAdmin,S#state.defConsumerAdminPid}
- |S#state.myConsumers]).
--define(get_allAdmins(S), [S#state.defSupplierAdmin,
- S#state.defConsumerAdmin|
- lists:flatten(ets:match(S#state.etsR,
- {'_','$1','_'}))++
- find_field(S#state.myConsumers, 2)]).
--define(get_consumerAdmIDs(S), [0|find_field(S#state.myConsumers, 1)]).
--define(get_supplierAdmIDs(S), [0|lists:flatten(ets:match(S#state.etsR,
- {'$1','_','_'}))]).
-
--define(get_supplierAdmin(S, I), find_obj(ets:lookup(S#state.etsR, I))).
--define(get_consumerAdmin(S, I), find_obj(lists:keysearch(I,1,S#state.myConsumers))).
--define(get_supplierAmount(S), ets:info(S#state.etsR, size)).
--define(get_consumerAmount(S), length(S#state.myConsumers)).
-
--define(get_MyFactory(S), S#state.myFac).
--define(get_defConsumerAdm(S), S#state.defConsumerAdmin).
--define(get_defSupplierAdm(S), S#state.defSupplierAdmin).
--define(get_defConsumerAdmPid(S), S#state.defConsumerAdminPid).
--define(get_defSupplierAdmPid(S), S#state.defSupplierAdminPid).
--define(get_defFilterFac(S), S#state.defFilterFac).
--define(get_defFilterFacPid(S), S#state.defFilterFacPid).
--define(get_GlobalQoS(S), S#state.qosGlobal).
--define(get_LocalQoS(S), S#state.qosLocal).
--define(get_BothQoS(S), {S#state.qosGlobal, S#state.qosLocal}).
--define(get_GlobalAdm(S), S#state.admGlobal).
--define(get_Options(S), S#state.options).
--define(get_MaxQueueLength(S), S#state.'MaxQueueLength').
--define(get_MaxConsumers(S), S#state.'MaxConsumers').
--define(get_MaxSuppliers(S), S#state.'MaxSuppliers').
--define(get_IdCounter(S), S#state.idCounter).
-
-%% Data structures modifiers
--define(set_GlobalQoS(S,D), S#state{qosGlobal=D}).
--define(set_BothQoS(S,GD,LD), S#state{qosGlobal=GD, qosLocal=LD}).
--define(set_GlobalAdm(S,D), S#state{admGlobal=D}).
--define(set_AllAdminP(S,GD, MQ, MC, MS),
- S#state{admGlobal=GD,'MaxQueueLength'=MQ,
- 'MaxConsumers'=MC, 'MaxSuppliers'=MS}).
--define(set_MaxQueueLength(S,D), S#state{'MaxQueueLength'=D}).
--define(set_MaxConsumers(S,D), S#state{'MaxConsumers'=D}).
--define(set_MaxSuppliers(S,D), S#state{'MaxSuppliers'=D}).
--define(set_defConsumerAdm(S,D,P), S#state{defConsumerAdmin=D, defConsumerAdminPid=P}).
--define(set_defSupplierAdm(S,D,P), S#state{defSupplierAdmin=D, defSupplierAdminPid=P}).
--define(set_defFilterFac(S,D,P), S#state{defFilterFac=D, defFilterFacPid=P}).
--define(add_supplierAdmin(S,I,O,P), ets:insert(S#state.etsR, {I,O,P})).
--define(add_consumerAdmin(S,I,O,P), S#state{myConsumers= [{I,O,P}|S#state.myConsumers]}).
--define(del_supplierAdmin(S,I), ets:delete(S#state.etsR, I)).
--define(del_consumerAdmin(S,I), S#state{myConsumers=
- lists:keydelete(I, 1,
- S#state.myConsumers)}).
--define(del_consumerAdminRef(S,O), S#state{myConsumers=
- lists:keydelete(O, 2,
- S#state.myConsumers)}).
--define(del_AdminPid(S,P), delete_obj(S, P)).
--define(set_IdCounter(S,V), S#state{idCounter=V}).
--define(new_Id(S), 'CosNotification_Common':create_id(S#state.idCounter)).
-%% MISC
--define(is_UndefDefConsAdm(S), S#state.defConsumerAdmin == undefined).
--define(is_UndefDefSuppAdm(S), S#state.defSupplierAdmin == undefined).
--define(is_UndefDefFilterFac(S), S#state.defFilterFac == undefined).
--define(is_PersistentConnection(S),
- ?not_GetConnectionReliability((S#state.qosLocal)) == ?not_Persistent).
--define(is_PersistentEvent(S),
- ?not_GetEventReliability((S#state.qosLocal)) == ?not_Persistent).
-
-%%-----------------------------------------------------------%
-%% function : handle_info, code_change
-%% Arguments:
-%% Returns :
-%% Effect : Functions demanded by the gen_server module.
-%%------------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-handle_info(Info, State) ->
- ?DBG("INFO: ~p~n", [Info]),
- case Info of
- {'EXIT', Pid, _Reason} when ?get_defConsumerAdmPid(State) == Pid ->
- {noreply, ?set_defConsumerAdm(State, undefined, undefined)};
- {'EXIT', Pid, _Reason} when ?get_defSupplierAdmPid(State) == Pid ->
- {noreply, ?set_defSupplierAdm(State, undefined, undefined)};
- {'EXIT', Pid, _Reason} when ?get_defFilterFacPid(State) == Pid ->
- {noreply, ?set_defFilterFac(State, undefined, undefined)};
- {'EXIT', Pid, normal} ->
- {noreply, ?del_AdminPid(State, Pid)};
- _Other ->
- ?DBG("TERMINATED: ~p~n",[_Other]),
- {noreply, State}
- end.
-
-%%----------------------------------------------------------%
-%% function : init, terminate
-%% Arguments:
-%%-----------------------------------------------------------
-
-init([MyFac, InitQoS, InitAdmin, LocalQoS, [MaxQ, MaxC, MaxS|_], Options]) ->
- process_flag(trap_exit, true),
- SO = 'CosNotification_Common':get_option(server_options, Options,
- ?not_DEFAULT_SETTINGS),
-
- ?DBG("CHANNEL INIT STATE:~n~p~n~p~n~p ~p ~p ~p~n~p~n",
- [InitQoS, InitAdmin, LocalQoS,MaxQ, MaxC, MaxS, Options]),
-
- %% Both default Admin:s have the unique id 0 (OMG spec, 98-11-01,
- %% Notification p 148), hence, no need to create a unique id.
- %% We don't have acces to OE_THIS in this stage so we cannot create the objects
- %% now, even though the specification states that.
- %% DefConAdm = 'CosNotifyChannelAdmin_ConsumerAdmin':oe_create_link([0],[]),
- %% DefSupAdm = 'CosNotifyChannelAdmin_SupplierAdmin':oe_create_link([0],[]),
-
- case 'CosNotifyFilter_FilterFactory':oe_create_link([], [{sup_child, true}|SO]) of
- {ok, Pid, DefFiFac} ->
- {ok, ?get_InitState(MyFac, DefFiFac, Pid, InitQoS, LocalQoS,
- InitAdmin, MaxQ, MaxC, MaxS, Options)};
- Reason ->
- {stop, Reason}
- end.
-
-terminate(_Reason, _State) ->
- ok.
-
-%%-----------------------------------------------------------
-%%----- CosNotifyChannelAdmin_EventChannel attributes -------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% Attribute: '_get_MyFactory'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_MyFactory'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_MyFactory(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_default_consumer_admin'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_default_consumer_admin'(OE_THIS, _OE_FROM, State)
- when ?is_UndefDefConsAdm(State) ->
- Op = 'CosNotification_Common':get_option(filterOp, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- case catch 'CosNotifyChannelAdmin_ConsumerAdmin':oe_create_link([0, OE_THIS,
- self(), Op,
- ?get_GlobalQoS(State),
- ?get_LocalQoS(State),
- ?get_Options(State)],
- [{sup_child, true}|SO]) of
- {ok, Pid, DefConAdm} ->
- {reply, DefConAdm, ?set_defConsumerAdm(State, DefConAdm, Pid)};
- What ->
- orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:_get_default_consumer_admin();~n"
- "Unable to create: CosNotifyChannelAdmin_ConsumerAdmin.~n"
- "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
-'_get_default_consumer_admin'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_defConsumerAdm(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_default_supplier_admin'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_default_supplier_admin'(OE_THIS, _OE_FROM, State)
- when ?is_UndefDefSuppAdm(State) ->
- Op = 'CosNotification_Common':get_option(filterOp, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- case catch 'CosNotifyChannelAdmin_SupplierAdmin':oe_create_link([0, OE_THIS,
- self(), Op,
- ?get_GlobalQoS(State),
- ?get_LocalQoS(State),
- ?get_Options(State)],
- [{sup_child, true}|SO]) of
- {ok, Pid, DefSupAdm} ->
- {reply, DefSupAdm, ?set_defSupplierAdm(State, DefSupAdm, Pid)};
- What ->
- orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:_get_default_supplier_admin();~n"
- "Unable to create: CosNotifyChannelAdmin_SupplierAdmin.~n"
- "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
-'_get_default_supplier_admin'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_defSupplierAdm(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_default_filter_factory'
-%% Type : readonly
-%% Returns :
-%%----------------------------------------------------------
-'_get_default_filter_factory'(_OE_THIS, _OE_FROM, State)
- when ?is_UndefDefFilterFac(State) ->
- SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- case catch 'CosNotifyFilter_FilterFactory':oe_create_link([], [{sup_child, true}|SO]) of
- {ok, Pid, DefFiFac} ->
- {reply, DefFiFac, ?set_defFilterFac(State, DefFiFac, Pid)};
- What ->
- orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:_get_default_filter_factory();~n"
- "Unable to create: CosNotifyChannelAdmin_FilterFactory.~n"
- "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
-'_get_default_filter_factory'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_defFilterFac(State), State}.
-
-%%-----------------------------------------------------------
-%%------- Exported external functions -----------------------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% function : new_for_consumers
-%% Arguments: Op - InterFilterGroupOperator: 'AND_OP' | 'OR_OP'
-%% Determines if the Admin:s proxy-children will
-%% use AND or OR when checking Filters.
-%% Returns : ConsAdm
-%% AdminId (out)
-%%-----------------------------------------------------------
-new_for_consumers(OE_THIS, _OE_FROM, State, Op) ->
- is_admin_limit_reached(?get_MaxConsumers(State), ?get_consumerAmount(State)),
- AdminId = ?new_Id(State),
- SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- case catch 'CosNotifyChannelAdmin_ConsumerAdmin':oe_create_link([AdminId, OE_THIS,
- self(), Op,
- ?get_GlobalQoS(State),
- ?get_LocalQoS(State),
- ?get_Options(State)],
- [{sup_child, true}|SO]) of
- {ok, Pid, AdminCo} ->
- %% Due to different storage, adding a new consumer is NOT done in the
- %% same way as for suppliers.
- NewState = ?add_consumerAdmin(State, AdminId, AdminCo, Pid),
- {reply, {AdminCo, AdminId}, ?set_IdCounter(NewState, AdminId)};
- What ->
- orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:nef_for_consumers();~n"
- "Unable to create: CosNotifyChannelAdmin_ConsumerAdmin.~n"
- "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------%
-%% function : new_for_suppliers
-%% Arguments: Op - InterFilterGroupOperator: 'AND_OP' | 'OR_OP'
-%% Determines if the Admin:s proxy-children will
-%% use AND or OR when checking Filters.
-%% Returns : SuppAdm
-%% AdminId (out)
-%%-----------------------------------------------------------
-new_for_suppliers(OE_THIS, _OE_FROM, State, Op) ->
- is_admin_limit_reached(?get_MaxSuppliers(State), ?get_supplierAmount(State)),
- AdminId = ?new_Id(State),
- SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- case catch 'CosNotifyChannelAdmin_SupplierAdmin':oe_create_link([AdminId, OE_THIS,
- self(), Op,
- ?get_GlobalQoS(State),
- ?get_LocalQoS(State),
- ?get_Options(State)],
- [{sup_child, true}|SO]) of
- {ok, Pid, AdminSu} ->
- %% Due to different storage, adding a new supplier is NOT done in the
- %% same way as for consumers.
- ?add_supplierAdmin(State, AdminId, AdminSu, Pid),
- {reply, {AdminSu, AdminId}, ?set_IdCounter(State, AdminId)};
- What ->
- orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:new_for_suppliers();~n"
- "Unable to create: CosNotifyChannelAdmin_SupplierAdmin.~n"
- "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------%
-%% function : get_consumeradmin
-%% Arguments: AdminId
-%% Returns : ConsAdmin
-%%-----------------------------------------------------------
-get_consumeradmin(OE_THIS, _OE_FROM, State, 0) when ?is_UndefDefConsAdm(State) ->
- Op = 'CosNotification_Common':get_option(filterOp, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- case catch 'CosNotifyChannelAdmin_ConsumerAdmin':oe_create_link([0, OE_THIS,
- self(), Op,
- ?get_GlobalQoS(State),
- ?get_LocalQoS(State),
- ?get_Options(State)],
- [{sup_child, true}|SO]) of
- {ok, Pid, DefConAdm} ->
- {reply, DefConAdm, ?set_defConsumerAdm(State, DefConAdm, Pid)};
- What ->
- orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:get_consumer_admin();~n"
- "Unable to create: CosNotifyChannelAdmin_ConsumerAdmin.~n"
- "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
-get_consumeradmin(_OE_THIS, _OE_FROM, State, 0) ->
- {reply, ?get_defConsumerAdm(State), State};
-get_consumeradmin(_OE_THIS, _OE_FROM, State, AdminId) when is_integer(AdminId) ->
- {reply, ?get_consumerAdmin(State, AdminId), State};
-get_consumeradmin(_, _, _, What) ->
- orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:get_consumeradmin(~p);~n"
- "Not an integer", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : get_supplieradmin
-%% Arguments: AdminId
-%% Returns :
-%%-----------------------------------------------------------
-get_supplieradmin(OE_THIS, _OE_FROM, State, 0) when ?is_UndefDefSuppAdm(State) ->
- Op = 'CosNotification_Common':get_option(filterOp, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- case catch 'CosNotifyChannelAdmin_SupplierAdmin':oe_create_link([0, OE_THIS,
- self(), Op,
- ?get_GlobalQoS(State),
- ?get_LocalQoS(State),
- ?get_Options(State)],
- [{sup_child, true}|SO]) of
- {ok, Pid, DefSupAdm} ->
- {reply, DefSupAdm, ?set_defSupplierAdm(State, DefSupAdm, Pid)};
- What ->
- orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:get_supplieradmin();~n"
- "Unable to create: CosNotifyChannelAdmin_SupplierAdmin.~n"
- "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
-get_supplieradmin(_OE_THIS, _OE_FROM, State, 0) ->
- {reply, ?get_defSupplierAdm(State), State};
-get_supplieradmin(_OE_THIS, _OE_FROM, State, AdminId) when is_integer(AdminId) ->
- {reply, ?get_supplierAdmin(State, AdminId), State};
-get_supplieradmin(_, _, _, What) ->
- orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:get_supplieradmin(~p);~n"
- "Not an integer", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : get_all_consumeradmins
-%% Arguments: -
-%% Returns : AdminIDSeq - a list of all unique ID:s.
-%%-----------------------------------------------------------
-get_all_consumeradmins(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_consumerAdmIDs(State), State}.
-
-%%----------------------------------------------------------%
-%% function : get_all_supplieradmins
-%% Arguments: -
-%% Returns : AdminIDSeq - a list of all unique ID:s.
-%%-----------------------------------------------------------
-get_all_supplieradmins(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_supplierAdmIDs(State), State}.
-
-
-%%----- Inherit from CosNotification::QoSAdmin --------------
-%%----------------------------------------------------------%
-%% function : get_qos
-%% Arguments: -
-%% Returns : CosNotification::QoSProperties
-%% [#'Property'{name, value}, ...] where name eq. string()
-%% and value eq. any().
-%%-----------------------------------------------------------
-get_qos(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_GlobalQoS(State), State}.
-
-%%----------------------------------------------------------%
-%% function : set_qos
-%% Arguments: QoS - CosNotification::QoSProperties, i.e.,
-%% [#'Property'{name, value}, ...] where name eq. string()
-%% and value eq. any().
-%% Returns : ok | {'EXCEPTION', CosNotification::UnsupportedQoS}
-%%-----------------------------------------------------------
-set_qos(_OE_THIS, _OE_FROM, State, QoS) ->
- {GQoS,LQoS} = 'CosNotification_Common':set_qos(QoS, ?get_BothQoS(State),
- channel, false,
- ?get_allAdmins(State)),
- {reply, ok, ?set_BothQoS(State, GQoS,LQoS)}.
-
-%%----------------------------------------------------------%
-%% function : validate_qos
-%% Arguments: Required_qos - CosNotification::QoSProperties
-%% [#'Property'{name, value}, ...] where name eq. string()
-%% and value eq. any().
-%% Returns : {'EXCEPTION', CosNotification::UnsupportedQoS} |
-%% {ok, CosNotification::NamedPropertyRangeSeq}
-%%-----------------------------------------------------------
-validate_qos(_OE_THIS, _OE_FROM, State, Required_qos) ->
- QoS = 'CosNotification_Common':validate_qos(Required_qos, ?get_BothQoS(State),
- channel, false,
- ?get_allAdmins(State)),
- {reply, {ok, QoS}, State}.
-
-%%----- Inherit from CosNotification::AdminPropertiesAdmin --
-%%-----------------------------------------------------------%
-%% function : get_admin
-%% Arguments: -
-%% Returns : AdminProperties
-%%-----------------------------------------------------------
-get_admin(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_GlobalAdm(State), State}.
-
-%%----------------------------------------------------------%
-%% function : set_admin
-%% Arguments: Admin
-%% Returns :
-%%-----------------------------------------------------------
-set_admin(_OE_THIS, _OE_FROM, State, Admin) ->
- {GAdm,[MaxQ, MaxC, MaxS|_]} =
- 'CosNotification_Common':set_adm(Admin, ?get_GlobalAdm(State)),
- {reply, ok, ?set_AllAdminP(State, GAdm, MaxQ, MaxC, MaxS)}.
-
-%%----- Inherit from CosEventChannelAdmin::EventChannel -----
-%%----------------------------------------------------------%
-%% function : for_consumers
-%% Arguments: -
-%% Returns : ConsAdm
-%%-----------------------------------------------------------
-for_consumers(OE_THIS, _OE_FROM, State) ->
- is_admin_limit_reached(?get_MaxConsumers(State), ?get_consumerAmount(State)),
- AdminId = ?new_Id(State),
- SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- case catch 'CosNotifyChannelAdmin_ConsumerAdmin':oe_create_link([AdminId, OE_THIS,
- self(), 'AND_OP',
- ?get_GlobalQoS(State),
- ?get_LocalQoS(State),
- ?get_Options(State)],
- [{sup_child, true}|SO]) of
- {ok, Pid, AdminCo} ->
- %% Due to different storage, adding a new consumer is NOT done in the
- %% same way as for suppliers.
- NewState = ?add_consumerAdmin(State, AdminId, AdminCo, Pid),
- {reply, AdminCo, ?set_IdCounter(NewState, AdminId)};
- What ->
- orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:for_consumers();~n"
- "Unable to create: CosNotifyChannelAdmin_ConsumerAdmin.~n"
- "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------%
-%% function : for_suppliers
-%% Arguments: -
-%% Returns : SuppAdm
-%%-----------------------------------------------------------
-for_suppliers(OE_THIS, _OE_FROM, State) ->
- is_admin_limit_reached(?get_MaxSuppliers(State), ?get_supplierAmount(State)),
- AdminId = ?new_Id(State),
- SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- case catch 'CosNotifyChannelAdmin_SupplierAdmin':oe_create_link([AdminId, OE_THIS,
- self(), 'AND_OP',
- ?get_GlobalQoS(State),
- ?get_LocalQoS(State),
- ?get_Options(State)],
- [{sup_child, true}|SO]) of
- {ok, Pid, AdminSu} ->
- %% Due to different storage, adding a new supplier is NOT done in the
- %% same way as for consumers.
- ?add_supplierAdmin(State, AdminId, AdminSu, Pid),
- {reply, AdminSu, ?set_IdCounter(State, AdminId)};
- What ->
- orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:for_suppliers();~n"
- "Unable to create: CosNotifyChannelAdmin_SupplierAdmin.~n"
- "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%-----------------------------------------------------------%
-%% function : destroy
-%% Arguments: -
-%% Returns : ok
-%%------------------------------------------------------------
-destroy(_OE_THIS, _OE_FROM, State) ->
- {stop, normal, ok, State}.
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-find_obj([]) -> {'EXCEPTION', #'CosNotifyChannelAdmin_AdminNotFound'{}};
-find_obj([{_, Obj,_}]) -> Obj;
-find_obj({value, {_, Obj,_}}) -> Obj;
-find_obj(_) -> {'EXCEPTION', #'CosNotifyChannelAdmin_AdminNotFound'{}}.
-
-
-find_field(List, Field) ->
- find_field(List, Field, []).
-
-find_field([], _, Acc) ->
- Acc;
-find_field([{I,_,_}|T], 1, Acc) ->
- find_field(T, 1, [I|Acc]);
-find_field([{_,O,_}|T], 2, Acc) ->
- find_field(T, 2, [O|Acc]);
-% Left out for now to avoid dialyzer warning.
-%find_field([{_,_,P}|T], 3, Acc) ->
-% find_field(T, 3, [P|Acc]);
-find_field(What, _, _) ->
- orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:find_field();~n"
- "Data corrupt: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
-
-delete_obj(State, Pid) ->
- case ets:match_object(State#state.etsR, {'_', '_', Pid}) of
- [] ->
- State#state{myConsumers=lists:keydelete(Pid, 3, State#state.myConsumers)};
- [{Id,_Obj,Pid}] ->
- ets:delete(State#state.etsR, Id),
- State
- end.
-
-%% Test if we have reached limit for Admin objects.
-is_admin_limit_reached(0, _) ->
- %% When set to zero it means that there is no limit.
- ok;
-is_admin_limit_reached(Max, Current) when Current >= Max ->
- %% The Current value do not include the default Admin objects, hence
- %% we use >= instead of >.
- corba:raise(#'IMP_LIMIT'{completion_status=?COMPLETED_NO});
-is_admin_limit_reached(_, _) ->
- ok.
-
-%%-----------------------------------------------------------
-%% function : callSeq
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-callSeq(_OE_THIS, OE_FROM, State, Event, Status) ->
- corba:reply(OE_FROM, ok),
- forward(seq, State, Event, Status).
-
-%%-----------------------------------------------------------
-%% function : callAny
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-callAny(_OE_THIS, OE_FROM, State, Event, Status) ->
- corba:reply(OE_FROM, ok),
- forward(any, State, Event, Status).
-
-%% Forward events
-forward(Type, State, Event, Status) ->
- forward(Type, ?get_consumerAdmins(State), State, Event, Status).
-
-forward(_, [], State, _, _) ->
- {noreply, State};
-forward(Type, [{_,undefined,_}|T], State, Event, Status) ->
- %% Match if no default objects associated.
- forward(Type, T, State, Event, Status);
-forward(any, [{_,H,_}|T], State, Event, Status) ->
- case catch oe_CosNotificationComm_Event:callAny(H, Event, Status) of
- ok ->
- ?DBG("CHANNEL FORWARD ANY: ~p~n",[Event]),
- forward(any, T, State, Event, Status);
- {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') ->
- orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:forward();~n"
- "Admin no longer exists; dropping it: ~p",
- [?LINE, H], ?DEBUG_LEVEL),
- NewState = ?del_consumerAdminRef(State,H),
- forward(any, T, NewState, Event, Status);
- R when ?is_PersistentConnection(State) ->
- orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:forward();~n"
- "Admin behaves badly: ~p/~p",
- [?LINE, R, H], ?DEBUG_LEVEL),
- forward(any, T, State, Event, Status);
- R ->
- orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:forward();~n"
- "Admin behaves badly: ~p~n"
- "Dropping it: ~p", [?LINE, R, H], ?DEBUG_LEVEL),
- NewState = ?del_consumerAdminRef(State, H),
- forward(any, T, NewState, Event, Status)
- end;
-forward(seq, [{_,H,_}|T], State, Event, Status) ->
- case catch oe_CosNotificationComm_Event:callSeq(H, Event, Status) of
- ok ->
- ?DBG("CHANNEL FORWARD SEQUENCE: ~p~n",[Event]),
- forward(seq, T, State, Event, Status);
- {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') ->
- orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:forward();~n"
- "Admin no longer exists; dropping it: ~p",
- [?LINE, H], ?DEBUG_LEVEL),
- NewState = ?del_consumerAdminRef(State,H),
- forward(seq, T, NewState, Event, Status);
- R when ?is_PersistentConnection(State) ->
- orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:forward();~n"
- "Admin behaves badly: ~p/~p",
- [?LINE, R, H], ?DEBUG_LEVEL),
- forward(seq, T, State, Event, Status);
- R ->
- orber:dbg("[~p] CosNotifyChannelAdmin_EventChannel:forward();~n"
- "Admin behaves badly: ~p~n"
- "Dropping it: ~p", [?LINE, R, H], ?DEBUG_LEVEL),
- NewState = ?del_consumerAdminRef(State,H),
- forward(seq, T, NewState, Event, Status)
- end.
-
-
-%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/CosNotifyChannelAdmin_SupplierAdmin_impl.erl b/lib/cosNotification/src/CosNotifyChannelAdmin_SupplierAdmin_impl.erl
deleted file mode 100644
index 2810bef93d..0000000000
--- a/lib/cosNotification/src/CosNotifyChannelAdmin_SupplierAdmin_impl.erl
+++ /dev/null
@@ -1,580 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-------------------------------------------------------------------
-%% File : CosNotifyChannelAdmin_SupplierAdmin_impl.erl
-%% Purpose :
-%%-------------------------------------------------------------------
-
--module('CosNotifyChannelAdmin_SupplierAdmin_impl').
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-%% Application files
--include("CosNotification.hrl").
--include("CosNotifyChannelAdmin.hrl").
--include("CosNotifyComm.hrl").
--include("CosNotifyFilter.hrl").
--include("CosNotification_Definitions.hrl").
-
-%%--------------- EXPORTS ------------------------------------
-%%--------------- External -----------------------------------
-%%----- CosNotifyChannelAdmin::SupplierAdmin -----------------
--export([get_proxy_consumer/4,
- obtain_notification_pull_consumer/4,
- obtain_notification_push_consumer/4,
- destroy/3]).
-
-%%----- Inherit from CosNotification::QoSAdmin ---------------
--export([get_qos/3,
- set_qos/4,
- validate_qos/4]).
-
-%%----- Inherit from CosNotifyComm::NotifyPublish ------------
--export([offer_change/5]).
-
-%%----- Inherit from CosNotifyFilter::FilterAdmin ------------
--export([add_filter/4,
- remove_filter/4,
- get_filter/4,
- get_all_filters/3,
- remove_all_filters/3]).
-
-%%----- Inherit from CosEventChannelAdmin::SupplierAdmin -----
--export([obtain_push_consumer/3,
- obtain_pull_consumer/3]).
-
-%% Attributes (external)
--export(['_get_MyID'/3,
- '_get_MyChannel'/3,
- '_get_MyOperator'/3,
- '_get_pull_consumers'/3,
- '_get_push_consumers'/3]).
-
-%%--------------- Internal -----------------------------------
-%%----- Inherit from cosNotificationComm ---------------------
--export([callAny/5,
- callSeq/5]).
-
-%%--------------- gen_server specific exports ----------------
--export([handle_info/2, code_change/3]).
--export([init/1, terminate/2]).
-
-%%--------------- LOCAL DEFINITIONS --------------------------
-%% Data structures
--record(state, {myId,
- myChannel,
- myChannelPid,
- myOperator,
- myFilters = [],
- idCounter = 0,
- etsR,
- qosGlobal,
- qosLocal,
- options}).
-
-%% Data structures constructors
--define(get_InitState(_MyID, _MyCh, _MyChP, _MyOp, _QoS, _LQS, _O),
- #state{myId = _MyID,
- myChannel = _MyCh,
- myChannelPid = _MyChP,
- myOperator = _MyOp,
- qosGlobal = _QoS,
- qosLocal = _LQS,
- options = _O,
- etsR = ets:new(oe_ets, [set, protected])}).
-
-%% Data structures selectors
--define(get_PushConsumers(S), lists:flatten(ets:match(S#state.etsR,
- {'_','$1','_',pusher}))).
--define(get_PullConsumers(S), lists:flatten(ets:match(S#state.etsR,
- {'_','$1','_',puller}))).
--define(get_AllConsumers(S), lists:flatten(ets:match(S#state.etsR,
- {'_','$1','_','_'}))).
--define(get_PushConsumerIDs(S), lists:flatten(ets:match(S#state.etsR,
- {'$1','_','_',pusher}))).
--define(get_PullConsumerIDs(S), lists:flatten(ets:match(S#state.etsR,
- {'$1','_','_',puller}))).
-
--define(get_Consumer(S, I), find_obj(ets:lookup(S#state.etsR, I), consumer)).
-
--define(get_MyID(S), S#state.myId).
--define(get_MyChannel(S), S#state.myChannel).
--define(get_MyChannelPid(S), S#state.myChannelPid).
--define(get_MyOperator(S), S#state.myOperator).
--define(get_GlobalQoS(S), S#state.qosGlobal).
--define(get_LocalQoS(S), S#state.qosLocal).
--define(get_BothQoS(S), {S#state.qosGlobal, S#state.qosLocal}).
--define(get_Filter(S, I), find_obj(lists:keysearch(I, 1, S#state.myFilters),
- filter)).
--define(get_AllFilter(S), S#state.myFilters).
--define(get_AllFilterID(S), find_ids(S#state.myFilters)).
--define(get_Options(S), S#state.options).
--define(get_IdCounter(S), S#state.idCounter).
-
-%% Data structures modifiers
--define(set_LocalQoS(S,D), S#state{qosLocal=D}).
--define(set_GlobalQoS(S,D), S#state{qosGlobal=D}).
--define(set_BothQoS(S,GD,LD), S#state{qosGlobal=GD, qosLocal=LD}).
--define(add_PushConsumer(S,I,R,P),ets:insert(State#state.etsR, {I,R,P,pusher})).
--define(add_PullConsumer(S,I,R,P),ets:insert(State#state.etsR, {I,R,P,puller})).
--define(del_Consumer(S,I), ets:delete(S#state.etsR, I)).
--define(del_ConsumerPid(S,P), ets:match_delete(S#state.etsR, {'_','_',P,'_'})).
--define(add_Filter(S,I,O), S#state{myFilters=[{I,O}|S#state.myFilters]}).
--define(del_Filter(S,I), S#state{myFilters=
- delete_filter(lists:keydelete(I, 1,
- S#state.myFilters),
- S#state.myFilters)}).
--define(del_AllFilter(S), S#state{myFilters=[]}).
--define(set_IdCounter(S,V), S#state{idCounter=V}).
--define(new_Id(S), 'CosNotification_Common':create_id(S#state.idCounter)).
-
-%% MISC
--define(is_PersistentEvent(S),
- ?not_GetEventReliability((S#state.qosLocal)) == ?not_Persistent).
--define(is_PersistentConnection(S),
- ?not_GetConnectionReliability((S#state.qosLocal)) == ?not_Persistent).
-
-%%----------------------------------------------------------%
-%% function : handle_info, code_change
-%% Arguments:
-%% Returns :
-%% Effect : Functions demanded by the gen_server module.
-%%-----------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-handle_info(Info, State) ->
- case Info of
- {'EXIT', Pid, Reason} when ?get_MyChannelPid(State) == Pid ->
- ?DBG("PARENT CHANNEL: ~p TERMINATED.~n",[Reason]),
- {stop, Reason, State};
- {'EXIT', Pid, normal} ->
- ?del_ConsumerPid(State, Pid),
- {noreply, State};
- _Other ->
- {noreply, State}
- end.
-
-%%----------------------------------------------------------%
-%% function : init, terminate
-%% Arguments:
-%%-----------------------------------------------------------
-
-init([MyId, MyChannel, MyChannelPid, MyOperator, InitQoS, LQS, Options]) ->
- process_flag(trap_exit, true),
- {ok, ?get_InitState(MyId, MyChannel, MyChannelPid, MyOperator, InitQoS, LQS, Options)}.
-
-terminate(_Reason, _State) ->
- ok.
-
-%%-----------------------------------------------------------
-%%----- CosNotifyChannelAdmin_ConsumerAdmin attributes ------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% Attribute: '_get_MyID'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_MyID'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_MyID(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_MyChannel'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_MyChannel'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_MyChannel(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_MyOperator'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_MyOperator'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_MyOperator(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_pull_consumers'
-%% Type : readonly
-%% Returns : ProxyIDSeq
-%%-----------------------------------------------------------
-'_get_pull_consumers'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_PullConsumerIDs(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_push_consumers'
-%% Type : readonly
-%% Returns : ProxyIDSeq
-%%-----------------------------------------------------------
-'_get_push_consumers'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_PushConsumerIDs(State), State}.
-
-%%-----------------------------------------------------------
-%%------- Exported external functions -----------------------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% function : get_proxy_consumer
-%% Arguments: ProxyId - unique identifier (long)
-%% Returns : ObjRef | {'EXCEPTION', #'ProxyNotFound'{}}
-%%-----------------------------------------------------------
-get_proxy_consumer(_OE_THIS, _OE_FROM, State, ProxyId) ->
- {reply, ?get_Consumer(State, ProxyId), State}.
-
-%%----------------------------------------------------------%
-%% function : obtain_notification_pull_consumer
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-obtain_notification_pull_consumer(OE_THIS, _OE_FROM, State, Ctype) ->
- %% Choose which module to use.
- {Mod, Type} =
- case Ctype of
- 'ANY_EVENT' ->
- {'CosNotifyChannelAdmin_ProxyPullConsumer', 'PULL_ANY'};
- 'STRUCTURED_EVENT' ->
- {'CosNotifyChannelAdmin_StructuredProxyPullConsumer', 'PULL_STRUCTURED'};
- 'SEQUENCE_EVENT' ->
- {'CosNotifyChannelAdmin_SequenceProxyPullConsumer', 'PULL_SEQUENCE'};
- _ ->
- orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:"
- "obtain_notification_pull_consumer(~p);~n"
- "Incorrect enumerant",
- [?LINE, Ctype], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end,
- SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- case catch Mod:oe_create_link([Type, OE_THIS, self(), ?get_GlobalQoS(State),
- ?get_LocalQoS(State), ?get_MyChannel(State),
- ?get_Options(State), ?get_MyOperator(State)],
- [{sup_child, true}|SO]) of
- {ok, Pid, Proxy} ->
- ProxyID = ?new_Id(State),
- ?add_PullConsumer(State, ProxyID, Proxy, Pid),
- {reply, {Proxy, ProxyID}, ?set_IdCounter(State, ProxyID)};
- What ->
- orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:"
- "obtain_notification_pull_consumer();~n"
- "Unable to create: ~p/~p~n"
- "Reason: ~p", [?LINE, Mod, Type, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------%
-%% function : obtain_notification_push_supplier
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-obtain_notification_push_consumer(OE_THIS, _OE_FROM, State, Ctype) ->
- %% Choose which module to use.
- {Mod, Type} =
- case Ctype of
- 'ANY_EVENT' ->
- {'CosNotifyChannelAdmin_ProxyPushConsumer', 'PUSH_ANY'};
- 'STRUCTURED_EVENT' ->
- {'CosNotifyChannelAdmin_StructuredProxyPushConsumer', 'PUSH_STRUCTURED'};
- 'SEQUENCE_EVENT' ->
- {'CosNotifyChannelAdmin_SequenceProxyPushConsumer', 'PUSH_SEQUENCE'};
- _ ->
- orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:"
- "obtain_notification_push_consumer(~p);~n"
- "Incorrect enumerant", [?LINE, Ctype], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end,
- SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- case catch Mod:oe_create_link([Type, OE_THIS, self(), ?get_GlobalQoS(State),
- ?get_LocalQoS(State), ?get_MyChannel(State),
- ?get_Options(State), ?get_MyOperator(State)],
- [{sup_child, true}|SO]) of
- {ok, Pid, Proxy} ->
- ProxyID = ?new_Id(State),
- ?add_PushConsumer(State, ProxyID, Proxy, Pid),
- {reply, {Proxy, ProxyID}, ?set_IdCounter(State, ProxyID)};
- What ->
- orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:"
- "obtain_notification_push_consumer();~n"
- "Unable to create: ~p/~p~n"
- "Reason: ~p", [?LINE, Mod, Type, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------%
-%% function : destroy
-%% Arguments: -
-%% Returns : ok
-%%------------------------------------------------------------
-destroy(_OE_THIS, _OE_FROM, State) ->
- {stop, normal, ok, State}.
-
-%%----- Inherit from CosNotification::QoSAdmin --------------
-%%----------------------------------------------------------%
-%% function : get_qos
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-get_qos(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_GlobalQoS(State), State}.
-
-%%----------------------------------------------------------%
-%% function : set_qos
-%% Arguments: QoS - CosNotification::QoSProperties, i.e.,
-%% [#'Property'{name, value}, ...] where name eq. string()
-%% and value eq. any().
-%% Returns : ok | {'EXCEPTION', CosNotification::UnsupportedQoS}
-%%-----------------------------------------------------------
-set_qos(_OE_THIS, _OE_FROM, State, QoS) ->
- {NewQoS, LQS} = 'CosNotification_Common':set_qos(QoS, ?get_BothQoS(State),
- admin, ?get_MyChannel(State),
- ?get_AllConsumers(State)),
- {reply, ok, ?set_BothQoS(State, NewQoS, LQS)}.
-
-%%----------------------------------------------------------%
-%% function : validate_qos
-%% Arguments: Required_qos - CosNotification::QoSProperties
-%% [#'Property'{name, value}, ...] where name eq. string()
-%% and value eq. any().
-%% Returns : {'EXCEPTION', CosNotification::UnsupportedQoS}
-%% {ok, CosNotification::NamedPropertyRangeSeq}
-%%-----------------------------------------------------------
-validate_qos(_OE_THIS, _OE_FROM, State, Required_qos) ->
- QoS = 'CosNotification_Common':validate_qos(Required_qos, ?get_BothQoS(State),
- admin, ?get_MyChannel(State),
- ?get_AllConsumers(State)),
- {reply, {ok, QoS}, State}.
-
-%%----- Inherit from CosNotifyComm::NotifyPublish -----------
-%%----------------------------------------------------------*
-%% function : offer_change
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-offer_change(_OE_THIS, _OE_FROM, State, _Added, _Removed) ->
- {reply, ok, State}.
-
-%%----- Inherit from CosNotifyFilter::FilterAdmin -----------
-%%----------------------------------------------------------%
-%% function : add_filter
-%% Arguments: Filter - CosNotifyFilter::Filter
-%% Returns : FilterID - long
-%%-----------------------------------------------------------
-add_filter(_OE_THIS, _OE_FROM, State, Filter) ->
- 'CosNotification_Common':type_check(Filter, 'CosNotifyFilter_Filter'),
- FilterID = ?new_Id(State),
- NewState = ?set_IdCounter(State, FilterID),
- {reply, FilterID, ?add_Filter(NewState, FilterID, Filter)}.
-
-%%----------------------------------------------------------%
-%% function : remove_filter
-%% Arguments: FilterID - long
-%% Returns : ok
-%%-----------------------------------------------------------
-remove_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
- {reply, ok, ?del_Filter(State, FilterID)};
-remove_filter(_,_,_,What) ->
- orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:remove_filter(~p);~n"
- "Not an integer", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : get_filter
-%% Arguments: FilterID - long
-%% Returns : Filter - CosNotifyFilter::Filter |
-%% {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}
-%%-----------------------------------------------------------
-get_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
- {reply, ?get_Filter(State, FilterID), State};
-get_filter(_,_,_,What) ->
- orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:get_filter(~p);~n"
- "Not an integer", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : get_all_filters
-%% Arguments: -
-%% Returns : Filter - CosNotifyFilter::FilterIDSeq
-%%-----------------------------------------------------------
-get_all_filters(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_AllFilterID(State), State}.
-
-%%----------------------------------------------------------%
-%% function : remove_all_filters
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-remove_all_filters(_OE_THIS, _OE_FROM, State) ->
- {reply, ok, ?del_AllFilter(State)}.
-
-%%----- Inherit from CosEventChannelAdmin::SupplierAdmin ----
-%%----------------------------------------------------------%
-%% function : obtain_push_consumer
-%% Arguments: -
-%% Returns : ProxyPushConsumer
-%%-----------------------------------------------------------
-obtain_push_consumer(OE_THIS, _OE_FROM, State) ->
- SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- case catch 'CosNotifyChannelAdmin_ProxyPushConsumer':
- oe_create_link(['PUSH_ANY', OE_THIS, self(), ?get_GlobalQoS(State),
- ?get_LocalQoS(State), ?get_MyChannel(State),
- ?get_Options(State), ?get_MyOperator(State)],
- [{sup_child, true}|SO]) of
- {ok, Pid, Proxy} ->
- ProxyID = ?new_Id(State),
- ?add_PushConsumer(State, ProxyID, Proxy, Pid),
- {reply, Proxy, ?set_IdCounter(State, ProxyID)};
- What ->
- orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:obtain_push_consumer();~n"
- "Unable to create: CosNotifyChannelAdmin_ProxyPushConsumer~n"
- "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------%
-%% function : obtain_pull_consumer
-%% Arguments: -
-%% Returns : ProxyPullConsumer
-%%-----------------------------------------------------------
-obtain_pull_consumer(OE_THIS, _OE_FROM, State) ->
- SO = 'CosNotification_Common':get_option(server_options, ?get_Options(State),
- ?not_DEFAULT_SETTINGS),
- case catch 'CosNotifyChannelAdmin_ProxyPullConsumer':
- oe_create_link(['PULL_ANY', OE_THIS, self(), ?get_GlobalQoS(State),
- ?get_LocalQoS(State), ?get_MyChannel(State),
- ?get_Options(State), ?get_MyOperator(State)],
- [{sup_child, true}|SO]) of
- {ok, Pid, Proxy} ->
- ProxyID = ?new_Id(State),
- ?add_PullConsumer(State, ProxyID, Proxy, Pid),
- {reply, Proxy, ?set_IdCounter(State, ProxyID)};
- What ->
- orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:obtain_push_consumer();~n"
- "Unable to create: CosNotifyChannelAdmin_ProxyPullConsumer~n"
- "Reason: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-find_obj([], consumer) -> {'EXCEPTION', #'CosNotifyChannelAdmin_ProxyNotFound'{}};
-find_obj([], filter) -> {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}};
-%% To match consumers
-find_obj([{_,Obj,_,_}],_) -> Obj;
-%% To match filters
-find_obj({value, {_,Obj}},_) -> Obj;
-find_obj(_,consumer) -> {'EXCEPTION', #'CosNotifyChannelAdmin_ProxyNotFound'{}};
-find_obj(_,filter) -> {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}.
-
-find_ids(List) -> find_ids(List, []).
-find_ids([], Acc) -> Acc;
-find_ids([{I,_}|T], Acc) -> find_ids(T, [I|Acc]);
-find_ids(What, _) ->
- orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:find_ids();~n"
- "Id corrupt: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
-
-%% Delete a single filter.
-%% The list do not differ, i.e., no filter removed, raise exception.
-delete_filter(List,List) -> corba:raise(#'CosNotifyFilter_FilterNotFound'{});
-delete_filter(List, _) -> List.
-
-%%-----------------------------------------------------------
-%% function : callSeq
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-callSeq(_OE_THIS, OE_FROM, State, Events, _Status) ->
- corba:reply(OE_FROM, ok),
- case cosNotification_eventDB:filter_events(Events, ?get_AllFilter(State)) of
- {[], _} ->
- {noreply, State};
- {Passed, _} ->
- forward(seq, State, Passed, 'MATCHED')
- end.
-
-%%-----------------------------------------------------------
-%% function : callAny
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-callAny(_OE_THIS, OE_FROM, State, Event, _Status) ->
- corba:reply(OE_FROM, ok),
- case cosNotification_eventDB:filter_events([Event], ?get_AllFilter(State)) of
- {[], _} ->
- {noreply, State};
- {[Passed], _} ->
- forward(any, State, Passed, 'MATCHED')
- end.
-
-%% Forward events
-forward(any, State, Event, Status) ->
- case catch oe_CosNotificationComm_Event:callAny(?get_MyChannel(State),
- Event, Status) of
- ok ->
- ?DBG("SUPPLIERADM FORWARD ANY: ~p~n",[Event]),
- {noreply, State};
- {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') ->
- orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:forward();~n"
- "Channel no longer exists; terminating and dropping: ~p",
- [?LINE, Event], ?DEBUG_LEVEL),
- {stop, normal, State};
- R when ?is_PersistentConnection(State) ->
- orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:forward();~n"
- "Channel respond incorrect: ~p~n"
- "Dropping: ~p", [?LINE, R, Event], ?DEBUG_LEVEL),
- {noreply, State};
- R ->
- orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:forward();~n"
- "Channel respond incorrect: ~p~n"
- "Terminating and dropping: ~p",
- [?LINE, R, Event], ?DEBUG_LEVEL),
- {stop, normal, State}
- end;
-forward(seq, State, Event, Status) ->
- case catch oe_CosNotificationComm_Event:callSeq(?get_MyChannel(State),
- Event, Status) of
- ok ->
- ?DBG("SUPPLIERADM FORWARD SEQUENCE: ~p~n",[Event]),
- {noreply, State};
- {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') ->
- orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:forward();~n"
- "Channel no longer exists; terminating and dropping: ~p",
- [?LINE, Event], ?DEBUG_LEVEL),
- {stop, normal, State};
- R when ?is_PersistentConnection(State) ->
- orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:forward();~n"
- "Channel respond incorrect: ~p~n"
- "Dropping: ~p", [?LINE, R, Event], ?DEBUG_LEVEL),
- {noreply, State};
- R ->
- orber:dbg("[~p] CosNotifyChannelAdmin_SupplierAdmin:forward();~n"
- "Channel respond incorrect: ~p~n"
- "Terminating and dropping: ~p",
- [?LINE, R, Event], ?DEBUG_LEVEL),
- {stop, normal, State}
- end.
-
-
-%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/CosNotifyComm.cfg b/lib/cosNotification/src/CosNotifyComm.cfg
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosNotification/src/CosNotifyComm.cfg
+++ /dev/null
diff --git a/lib/cosNotification/src/CosNotifyComm.idl b/lib/cosNotification/src/CosNotifyComm.idl
deleted file mode 100644
index f0386f0982..0000000000
--- a/lib/cosNotification/src/CosNotifyComm.idl
+++ /dev/null
@@ -1,83 +0,0 @@
-#ifndef _COS_NOTIFYCOMM_IDL_
-#define _COS_NOTIFYCOMM_IDL_
-
-#pragma prefix "omg.org"
-
-
-#include<CosNotification.idl>
-
-module CosNotifyComm {
- exception InvalidEventType { CosNotification::EventType type; };
-
- interface NotifyPublish {
- void offer_change (in CosNotification::EventTypeSeq added,
- in CosNotification::EventTypeSeq removed)
- raises (InvalidEventType);
- }; // NotifyPublish
-
- interface NotifySubscribe {
- void subscription_change(in CosNotification::EventTypeSeq added,
- in CosNotification::EventTypeSeq removed)
- raises (InvalidEventType);
- }; // NotifySubscribe
-
- interface PushConsumer : NotifyPublish, CosEventComm::PushConsumer { }; // PushConsumer
-
- interface PullConsumer : NotifyPublish, CosEventComm::PullConsumer { }; // PullConsumer
-
- interface PullSupplier : NotifySubscribe, CosEventComm::PullSupplier { }; // PullSupplier
-
- interface PushSupplier : NotifySubscribe, CosEventComm::PushSupplier { };
-
- interface StructuredPushConsumer : NotifyPublish {
- void push_structured_event(in CosNotification::StructuredEvent notification)
- raises(CosEventComm::Disconnected);
-
- void disconnect_structured_push_consumer();
- }; // StructuredPushConsumer
-
- interface StructuredPullConsumer : NotifyPublish {
- void disconnect_structured_pull_consumer();
- }; // StructuredPullConsumer
-
- interface StructuredPullSupplier : NotifySubscribe {
- CosNotification::StructuredEvent pull_structured_event()
- raises(CosEventComm::Disconnected);
-
- CosNotification::StructuredEvent try_pull_structured_event(out boolean has_event)
- raises(CosEventComm::Disconnected);
-
- void disconnect_structured_pull_supplier();
- }; // StructuredPullSupplier
-
- interface StructuredPushSupplier : NotifySubscribe {
- void disconnect_structured_push_supplier();
- }; // StructuredPushSupplier
-
- interface SequencePushConsumer : NotifyPublish {
- void push_structured_events(in CosNotification::EventBatch notifications)
- raises(CosEventComm::Disconnected);
-
- void disconnect_sequence_push_consumer();
- }; // SequencePushConsumer
-
- interface SequencePullConsumer : NotifyPublish {
- void disconnect_sequence_pull_consumer();
- }; // SequencePullConsumer
-
- interface SequencePullSupplier : NotifySubscribe {
- CosNotification::EventBatch pull_structured_events(in long max_number)
- raises(CosEventComm::Disconnected);
- CosNotification::EventBatch try_pull_structured_events(in long max_number, out boolean has_event)
- raises(CosEventComm::Disconnected);
-
- void disconnect_sequence_pull_supplier();
- }; // SequencePullSupplier
-
- interface SequencePushSupplier : NotifySubscribe {
- void disconnect_sequence_push_supplier();
- }; // SequencePushSupplier
-}; // CosNotifyComm
-
-#endif /* ifndef _COS_NOTIFYCOMM_IDL_ */
-
diff --git a/lib/cosNotification/src/CosNotifyFilter.cfg b/lib/cosNotification/src/CosNotifyFilter.cfg
deleted file mode 100644
index 167550e0f5..0000000000
--- a/lib/cosNotification/src/CosNotifyFilter.cfg
+++ /dev/null
@@ -1,6 +0,0 @@
-{this, "CosNotifyFilter::Filter"}.
-{{handle_info, "CosNotifyFilter::Filter"}, true}.
-{this, "CosNotifyFilter::MappingFilter"}.
-{{handle_info, "CosNotifyFilter::MappingFilter"}, true}.
-{this, "CosNotifyFilter::FilterFactory"}.
-{{handle_info, "CosNotifyFilter::FilterFactory"}, true}.
diff --git a/lib/cosNotification/src/CosNotifyFilter.idl b/lib/cosNotification/src/CosNotifyFilter.idl
deleted file mode 100644
index c6498ddcd0..0000000000
--- a/lib/cosNotification/src/CosNotifyFilter.idl
+++ /dev/null
@@ -1,140 +0,0 @@
-#ifndef _COS_NOTIFYFILTER_IDL_
-#define _COS_NOTIFYFILTER_IDL_
-
-#pragma prefix "omg.org"
-
-#include<CosNotifyComm.idl>
-#include<CosNotification.idl>
-
-module CosNotifyFilter {
- typedef long ConstraintID;
- struct ConstraintExp {
- CosNotification::EventTypeSeq event_types;
- string constraint_expr;
- };
-
- typedef sequence<ConstraintID> ConstraintIDSeq;
- typedef sequence<ConstraintExp> ConstraintExpSeq;
- struct ConstraintInfo {
- ConstraintExp constraint_expression;
- ConstraintID constraint_id;
- };
- typedef sequence<ConstraintInfo> ConstraintInfoSeq;
- struct MappingConstraintPair {
- ConstraintExp constraint_expression;
- any result_to_set;
- };
- typedef sequence<MappingConstraintPair> MappingConstraintPairSeq;
- struct MappingConstraintInfo {
- ConstraintExp constraint_expression;
- ConstraintID constraint_id;
- any value;
- };
- typedef sequence<MappingConstraintInfo> MappingConstraintInfoSeq;
- typedef long CallbackID;
- typedef sequence<CallbackID> CallbackIDSeq;
- exception UnsupportedFilterableData {};
- exception InvalidGrammar {};
- exception InvalidConstraint {ConstraintExp constr;};
- exception DuplicateConstraintID {ConstraintID id;};
- exception ConstraintNotFound {ConstraintID id;};
- exception CallbackNotFound {};
- exception InvalidValue {ConstraintExp constr; any value;};
- interface Filter {
- readonly attribute string constraint_grammar;
- ConstraintInfoSeq add_constraints (in ConstraintExpSeq constraint_list)
- raises (InvalidConstraint);
-
- void modify_constraints (in ConstraintIDSeq del_list,
- in ConstraintInfoSeq modify_list)
- raises (InvalidConstraint, ConstraintNotFound);
-
- ConstraintInfoSeq get_constraints(in ConstraintIDSeq id_list)
- raises (ConstraintNotFound);
-
- ConstraintInfoSeq get_all_constraints();
-
- void remove_all_constraints();
- void destroy();
- boolean match (in any filterable_data)
- raises (UnsupportedFilterableData);
-
- boolean match_structured (in CosNotification::StructuredEvent filterable_data)
- raises (UnsupportedFilterableData);
-
- boolean match_typed (in CosNotification::PropertySeq filterable_data)
- raises (UnsupportedFilterableData);
-
- CallbackID attach_callback (in CosNotifyComm::NotifySubscribe callback);
-
- void detach_callback (in CallbackID callback)
- raises ( CallbackNotFound );
-
- CallbackIDSeq get_callbacks();
- }; // Filter
-
- interface MappingFilter {
- readonly attribute string constraint_grammar;
-
- readonly attribute CORBA::TypeCode value_type;
-
- readonly attribute any default_value;
-
- MappingConstraintInfoSeq add_mapping_constraints (in MappingConstraintPairSeq pair_list)
- raises (InvalidConstraint, InvalidValue);
-
- void modify_mapping_constraints (in ConstraintIDSeq del_list,
- in MappingConstraintInfoSeq modify_list)
- raises (InvalidConstraint, InvalidValue, ConstraintNotFound);
-
- MappingConstraintInfoSeq get_mapping_constraints (in ConstraintIDSeq id_list)
- raises (ConstraintNotFound);
-
- MappingConstraintInfoSeq get_all_mapping_constraints();
-
- void remove_all_mapping_constraints();
-
- void destroy();
-
- boolean match (in any filterable_data, out any result_to_set)
- raises (UnsupportedFilterableData);
-
- boolean match_structured (in CosNotification::StructuredEvent filterable_data, out any result_to_set)
- raises (UnsupportedFilterableData);
-
- boolean match_typed (in CosNotification::PropertySeq filterable_data, out any result_to_set)
- raises (UnsupportedFilterableData);
- }; // MappingFilter
-
-
- interface FilterFactory {
-
- Filter create_filter (in string constraint_grammar)
- raises (InvalidGrammar);
-
- MappingFilter create_mapping_filter (in string constraint_grammar, in any default_value)
- raises(InvalidGrammar);
- }; // FilterFactory
-
- typedef long FilterID;
- typedef sequence<FilterID> FilterIDSeq;
- exception FilterNotFound {};
-
- interface FilterAdmin {
- FilterID add_filter (in Filter new_filter);
-
- void remove_filter (in FilterID filter)
- raises (FilterNotFound);
-
- Filter get_filter (in FilterID filter)
- raises (FilterNotFound);
-
- FilterIDSeq get_all_filters();
-
- void remove_all_filters();
- }; // FilterAdmin
-}; // CosNotifyFilter
-
-
-#endif /* ifndef _COS_NOTIFYFILTER_IDL_ */
-
diff --git a/lib/cosNotification/src/CosNotifyFilter_FilterFactory_impl.erl b/lib/cosNotification/src/CosNotifyFilter_FilterFactory_impl.erl
deleted file mode 100644
index 760dcf40b8..0000000000
--- a/lib/cosNotification/src/CosNotifyFilter_FilterFactory_impl.erl
+++ /dev/null
@@ -1,126 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosNotifyFilter_FilterFactory_impl.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module('CosNotifyFilter_FilterFactory_impl').
-
-
-%%--------------- INCLUDES -----------------------------------
-%% Application files
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-%% Application files
--include("CosNotification.hrl").
--include("CosNotifyChannelAdmin.hrl").
--include("CosNotifyComm.hrl").
--include("CosNotifyFilter.hrl").
--include("CosNotification_Definitions.hrl").
-
-%%--------------- IMPORTS ------------------------------------
-
-%%--------------- EXPORTS ------------------------------------
-%% External
--export([create_filter/3,
- create_mapping_filter/4]).
-
-%%--------------- gen_server specific exports ----------------
--export([handle_info/2, code_change/3]).
--export([init/1, terminate/2]).
-
-%%--------------- LOCAL DEFINITIONS --------------------------
-%% Data structures
--record(state, {adminProp,
- etsR,
- options}).
-
-%%-----------------------------------------------------------%
-%% function : handle_info, code_change
-%% Arguments: See gen_server documentation.
-%% Effect : Functions demanded by the gen_server module.
-%%------------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-handle_info(_Info, State) ->
- ?debug_print("INFO: ~p DATA: ~p~n", [State, _Info]),
- {noreply, State}.
-
-%%----------------------------------------------------------%
-%% function : init, terminate
-%% Arguments:
-%%-----------------------------------------------------------
-
-init(Options) ->
- process_flag(trap_exit, true),
- {ok, #state{options = Options}}.
-
-terminate(_Reason, _State) ->
- ok.
-
-%%-----------------------------------------------------------
-%%------- Exported external functions -----------------------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% function : create_filter
-%% Arguments: InitGrammar - string()
-%% Returns : CosNotifyFilter::Filter |
-%% {'EXCEPTION', InvalidGrammar}
-%%-----------------------------------------------------------
-create_filter(OE_THIS, State, InitGrammar) ->
- case lists:member(InitGrammar, ?not_SupportedGrammars) of
- true ->
- SO = 'CosNotification_Common':get_option(server_options, State#state.options,
- ?not_DEFAULT_SETTINGS),
- Fi='CosNotifyFilter_Filter':oe_create_link([OE_THIS, self(),
- InitGrammar],
- SO),
- {reply, Fi, State};
- _ ->
- corba:raise(#'CosNotifyFilter_InvalidGrammar'{})
- end.
-
-%%----------------------------------------------------------%
-%% function : create_mapping_filter
-%% Arguments: InitGrammar - string()
-%% Returns : CosNotifyFilter::Filter |
-%% {'EXCEPTION', InvalidGrammar}
-%%-----------------------------------------------------------
-create_mapping_filter(OE_THIS, State, InitGrammar, DefVal) ->
- case lists:member(InitGrammar, ?not_SupportedGrammars) of
- true ->
- SO = 'CosNotification_Common':get_option(server_options, State#state.options,
- ?not_DEFAULT_SETTINGS),
- Fi='CosNotifyFilter_MappingFilter':oe_create_link([OE_THIS, self(),
- InitGrammar, DefVal],
- SO),
- {reply, Fi, State};
- _ ->
- corba:raise(#'CosNotifyFilter_InvalidGrammar'{})
- end.
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/CosNotifyFilter_Filter_impl.erl b/lib/cosNotification/src/CosNotifyFilter_Filter_impl.erl
deleted file mode 100644
index 0f997049e0..0000000000
--- a/lib/cosNotification/src/CosNotifyFilter_Filter_impl.erl
+++ /dev/null
@@ -1,672 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosNotifyFilter_Filter_impl.erl
-%% Purpose :
-%% Note : For an event to be forwarded it's sufficient that at least
-%% one of the constraints return 'true'.
-%% ALL functions in this module are internal. May NOT be used
-%% externally in ANY WAY; only CosNotification system modules.
-%%----------------------------------------------------------------------
-
--module('CosNotifyFilter_Filter_impl').
-
-%%--------------- INCLUDES -----------------------------------
-%% Application files
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-%% Application files
--include("CosNotification.hrl").
--include("CosNotifyChannelAdmin.hrl").
--include("CosNotifyComm.hrl").
--include("CosNotifyFilter.hrl").
--include("CosNotification_Definitions.hrl").
-
-%%--------------- IMPORTS ------------------------------------
-
-%%--------------- EXPORTS ------------------------------------
-%% External Attributes
--export(['_get_constraint_grammar'/2]).
-%% External Functions
--export([add_constraints/3,
- modify_constraints/4,
- get_constraints/3,
- get_all_constraints/2,
- remove_all_constraints/2,
- destroy/2,
- match/3,
- match_structured/3,
- match_typed/3,
- attach_callback/3,
- detach_callback/3,
- get_callbacks/2]).
-
-%%--------------- gen_server specific exports ----------------
--export([handle_info/2, code_change/3]).
--export([init/1, terminate/2]).
-
-%%--------------- LOCAL DEFINITIONS --------------------------
-%%######### MISC ##########
--define(create_ConstraintInfo(_Types, _Con, _ID),
- #'CosNotifyFilter_ConstraintInfo'{
- constraint_expression =
- #'CosNotifyFilter_ConstraintExp'{
- event_types = _Types,
- constraint_expr = _Con},
- constraint_id = _ID
- }).
-
-%%#### Data structures ####
--record(state, {constraint_grammar,
- constraints = [],
- filters = [],
- callbacks = [],
- idCounter = 0,
- filterFactory,
- factoryPid,
- etsR}).
-
-%% Data structures constructors
--define(get_InitState(Fac, Pid, Gr),
- #state{constraint_grammar=Gr,
- filterFactory=Fac,
- factoryPid=Pid,
- etsR = ets:new(oe_ets, [bag, protected])}).
-
-%%------------------- Data structures selectors -------------------
-%% Grammar
--define(get_Grammar(S), S#state.constraint_grammar).
-%% Callbacks
-% Left out for now to avoid dialyzer warning.
-%-define(get_Callback(S,I), find_obj(lists:keysearch(I, 1, S#state.callbacks),
-% callback)).
--define(get_AllCallback(S), lists:map(fun({_V, C}) -> C end,
- S#state.callbacks)).
--define(get_AllCallbackID(S), lists:map(fun({V, _C}) -> V end,
- S#state.callbacks)).
-%% ID:s
--define(get_IdCounter(S), S#state.idCounter).
-
-%% Constraints
--define(get_Constraint(S,I), find_obj(lists:keysearch(I, 1, S#state.constraints),
- constraint)).
--define(get_AllConstraints(S), lists:map(fun({I, C, _W, _WC, _K, T}) ->
- ?create_ConstraintInfo(T, C, I)
- end,
- S#state.constraints)).
--define(get_ConstraintAllData(S), S#state.constraints).
--define(get_ConstraintData(S,I), lists:keysearch(I, 1, S#state.constraints)).
--define(match_Type(S,I,ET), ets:lookup(S#state.etsR, {I, ET})).
-%% Parse Tree
--define(get_ParseTree(S,K), find_obj(ets:lookup(S#state.etsR, K), tree)).
-
-%%------------------- Data structures modifiers -------------------
-%% Callbacks
--define(del_Callback(S,I), S#state{callbacks =
- delete_obj(lists:keydelete(I,1,
- S#state.callbacks),
- S#state.callbacks, callback)}).
--define(del_AllCallbacks(S), S#state{callbacks=[]}).
--define(add_Callback(S,V,C), S#state{idCounter=V,
- callbacks = [{V,C}|S#state.callbacks]}).
-%% ID:s
--define(set_IdCounter(S,V), S#state{idCounter=V}).
--define(new_Id(S), 'CosNotification_Common':create_id(S#state.idCounter)).
-
-%% Constraints
--define(del_Constraint(S, I), match_delete(S, S#state.constraints, I)).
--define(del_AllConstraints(S), clear_DB(S)).
--define(add_Constraint(S,I,C,W,_WC,K,T), S#state{constraints =
- [{I, C, W, _WC, K, T}|S#state.constraints]}).
--define(set_Constraints(S,C), S#state{constraints = C}).
-
--define(del_AllTypes(S), ets:match_delete(S#state.etsR, {'_','_',types})).
--define(del_Type(S,I), ets:match_delete(S#state.etsR, {{I, '_'}, '_', types})).
--define(add_Type(S,I,ET,K), ets:insert(S#state.etsR, {{I, ET}, K, types})).
-
-%% Parse Tree
--define(add_ParseTree(S,K,T), ets:insert(S#state.etsR, {K, T, tree})).
--define(del_ParseTree(S,K), ets:delete(S#state.etsR, K)).
--define(del_AllParseTress(S), ets:match_delete(S#state.etsR, {'_','_',tree})).
-
-%%------------------- MISC ----------------------------------------
--define(is_EmptyFilter(S), S#state.constraints==[]).
-
--define(InfoSeq2EventTypeSeq(L), lists:flatten(
- lists:map(fun(#'CosNotifyFilter_ConstraintInfo'
- {constraint_expression=
- #'CosNotifyFilter_ConstraintExp'
- {event_types = ET}}) ->
- ET
- end,
- L))).
-
-%%-----------------------------------------------------------%
-%% Function : handle_info, code_change
-%% Arguments: See gen_server documentation.
-%% Effect : Functions demanded by the gen_server module.
-%%------------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-handle_info(Info, State) ->
- ?debug_print("INFO: ~p DATA: ~p~n", [State, Info]),
- case Info of
- {'EXIT', _Pid, _Reason} ->
- {noreply, State};
- _ ->
- {noreply, State}
- end.
-
-%%----------------------------------------------------------%
-%% Function : init, terminate
-%% Arguments:
-%%-----------------------------------------------------------
-
-init([FiFac, FacPid, ConstraintGr]) ->
- process_flag(trap_exit, true),
- {ok, ?get_InitState(FiFac, FacPid, ConstraintGr)}.
-
-terminate(_Reason, _State) ->
- ok.
-
-%%-----------------------------------------------------------
-%%------- Exported external attributes ----------------------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% Function : '_get_constraint_grammar'/2
-%% Type : readonly
-%% Returns : Grammar - string()
-%%-----------------------------------------------------------
-'_get_constraint_grammar'(_OE_THIS, State) ->
- {reply, ?get_Grammar(State), State}.
-
-%%-----------------------------------------------------------
-%%------- Exported external functions -----------------------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% Function : add_constraints/3
-%% Arguments: CL - CosNotifyFilter::ConstraintExpSeq
-%% Returns : CosNotifyFilter::ConstraintInfoSeq |
-%% {'EXCEPTION', CosNotifyFilter::InvalidConstraint}
-%%-----------------------------------------------------------
-add_constraints(_OE_THIS, State, CL) ->
- {NewState, Filters, Info, EventTSeq} = try_create_filters(State, CL),
- NewState2=store_filters(NewState, Filters),
- inform_callbacks(?get_AllCallback(NewState2), EventTSeq, []),
- {reply, Info, NewState2}.
-
-%%----------------------------------------------------------%
-%% Function : modify_constraints/4
-%% Arguments: IDs - CosNotifyFilter::ConstraintIDSeq
-%% AddConstraintInfoSeq - CosNotifyFilter::ConstraintInfoSeq
-%% Returns : ok |
-%% {'EXCEPTION', CosNotifyFilter::InvalidConstraint} |
-%% {'EXCEPTION', CosNotifyFilter::ConstraintNotFound}
-%%-----------------------------------------------------------
-%% The OMG specification (TC Document telecom/98-11-01, chapter
-%% 3.2.1.3) states (concerning IDs):
-%%
-%% "If all input values supplied within a particular invocation
-%% of this operation are valid, then the specific constraints
-%% identified by the values contained in the first input parameter
-%% will be deleted from the list of those encapsulated by the target
-%% filter object."
-%%
-%% Hence, first we must check if all ID's exists before deleting.
-modify_constraints(_OE_THIS, State, IDs, AddConstraintInfoSeq) ->
- %% The following functions are 'safe', i.e., they do not alter any data.
- RemoveConstraintInfoSeq = lookup_constraints(IDs, State),
- lookup_constraints(AddConstraintInfoSeq, State),
- {NewState, Filters, _Info, AddedEventTSeq} =
- try_create_filters(State, AddConstraintInfoSeq),
- RemovedEventTSeq = ?InfoSeq2EventTypeSeq(RemoveConstraintInfoSeq),
-
- %% We cannot change anything before our checks (see above). Hence,
- %% do NOT move the following lines above this point.
- NewState2 = delete_constraints(IDs, NewState),
-
-%% The OMG specification (TC Document telecom/98-11-01, chapter
-%% 3.2.1.3) states (concerning AddConstraintInfoSeq):
-%%
-%% "If all input values supplied within a particular invocation of this
-%% operation are valid, then the constraint expression associated with the
-%% already encapsulated constraint identified by the numeric value contained
-%% within each element of the input sequence will be modified to the new
-%% constraint expression that is contained within the same sequence element."
-%%
-%% This, our interpretation, implies that ALL previous data related
-%% to each unique ID should be removed and replaced by the new data.
-
- NewState3 = delete_constraints(AddConstraintInfoSeq, NewState2),
- NewState4 = store_filters(NewState3, Filters),
- inform_callbacks(?get_AllCallback(NewState4),
- AddedEventTSeq, RemovedEventTSeq),
- {reply, ok, NewState4}.
-
-%%----------------------------------------------------------%
-%% Function : get_constraints/3
-%% Arguments: IDs - CosNotifyFilter::ConstraintIDSeq
-%% Returns : CosNotifyFilter::ConstraintInfoSeq |
-%% {'EXCEPTION', CosNotifyFilter::ConstraintNotFound}
-%%-----------------------------------------------------------
-get_constraints(_OE_THIS, State, IDs) ->
- {reply, lookup_constraints(IDs, State), State}.
-
-%%----------------------------------------------------------%
-%% Function : get_all_constraints/2
-%% Arguments: -
-%% Returns : CosNotifyFilter::ConstraintInfoSeq
-%%-----------------------------------------------------------
-get_all_constraints(_OE_THIS, State) ->
- {reply, ?get_AllConstraints(State), State}.
-
-%%----------------------------------------------------------%
-%% Function : remove_all_constraints/2
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-remove_all_constraints(_OE_THIS, State) ->
- {reply, ok, ?del_AllConstraints(State)}.
-
-%%----------------------------------------------------------%
-%% Function : destroy/2
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-destroy(_OE_THIS, State) ->
- {stop, normal, ok, State}.
-
-%%----------------------------------------------------------%
-%% Function : match/3
-%% Arguments: Event - #any{}
-%% Returns : boolean() |
-%% {'EXCEPTION', CosNotifyFilter::UnsupportedFilterableData}
-%%-----------------------------------------------------------
-
-match(_OE_THIS, State, Event) when is_record(Event,'any'), ?is_EmptyFilter(State) ->
- {reply, true, State};
-match(_OE_THIS, State, Event) when is_record(Event,'any') ->
- match_any_event(State, Event, ?get_ConstraintAllData(State));
-match(_,_,What) ->
- orber:dbg("[~p] CosNotifyFilter_Filter:match(~p);~n"
- "Not an CORBA::Any", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% Function : match_structured/3
-%% Arguments: Event - CosNotification::StructuredEvent
-%% Returns : boolean() |
-%% {'EXCEPTION', CosNotifyFilter::UnsupportedFilterableData}
-%%-----------------------------------------------------------
-match_structured(_OE_THIS, State, Event) when
- is_record(Event,'CosNotification_StructuredEvent') andalso ?is_EmptyFilter(State) ->
- {reply, true, State};
-match_structured(_OE_THIS, State, Event) when
- is_record(Event,'CosNotification_StructuredEvent') ->
- match_str_event(State, Event, ?get_ConstraintAllData(State));
-match_structured(_,_,What) ->
- orber:dbg("[~p] CosNotifyFilter_Filter:match_structured(~p);~n"
- "Not a StructuredEvent", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------*
-%% Function : match_typed/3
-%% Arguments: Data - CosNotification::PropertySeq
-%% Returns : boolean() |
-%% {'EXCEPTION', CosNotifyFilter::UnsupportedFilterableData}
-%%-----------------------------------------------------------
--spec match_typed(_, _, _) -> no_return().
-match_typed(_OE_THIS, _State, _Data) ->
- corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% Function : attach_callback/3
-%% Arguments: CB - CosNotifyComm::NotifySubscribe
-%% Returns : ID - CosNotifyFilter::CallbackID
-%%-----------------------------------------------------------
-attach_callback(_OE_THIS, State, CB) ->
- 'CosNotification_Common':type_check(CB, 'CosNotifyComm_NotifySubscribe'),
- CBID = ?new_Id(State),
- {reply, CBID, ?add_Callback(State, CBID, CB)}.
-
-%%----------------------------------------------------------%
-%% Function : detach_callback/3
-%% Arguments: ID - CosNotifyFilter::CallbackID
-%% Returns : ok | {'EXCEPTION', CosNotifyFilter::CallbackNotFound}
-%%-----------------------------------------------------------
-detach_callback(_OE_THIS, State, ID) when is_integer(ID) ->
- {reply, ok, ?del_Callback(State, ID)};
-detach_callback(_,_,What) ->
- orber:dbg("[~p] CosNotifyFilter_Filter:detach_callback(~p);~n"
- "Not an integer", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% Function : get_callbacks/2
-%% Arguments: -
-%% Returns : CosNotifyFilter::CallbackIDSeq
-%%-----------------------------------------------------------
-get_callbacks(_OE_THIS, State) ->
- {reply, ?get_AllCallbackID(State), State}.
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-%% To match callbacks
-find_obj({value, {_, Obj}},_) -> Obj;
-%% To match constraints
-find_obj({value, {Id, Con, _, _, _, Types}}, _) ->
- ?create_ConstraintInfo(Types, Con, Id);
-find_obj([{_, Tree, tree}|_], tree) -> Tree;
-% Left out for now to avoid dialyzer warning.
-%find_obj(_,callback) -> {'EXCEPTION', #'CosNotifyFilter_CallbackNotFound'{}};
-find_obj(_,tree) -> undefined;
-find_obj(_,constraint) -> error.
-
-%% Delete a single object.
-delete_obj(List,List,callback) -> corba:raise(#'CosNotifyFilter_CallbackNotFound'{});
-delete_obj(List,_,_) -> List.
-
-%% Delete given object from list and all related objects in DB (parse tree and types).
-match_delete(State, Constraints, ID) ->
- match_delete(State, Constraints, ID, []).
-match_delete(_, [], _, _) ->
- error;
-match_delete(State, [{ID, _Con, _Which, _WC, Key, _Types}|T], ID, Acc) ->
- ?del_Type(State, ID),
- ?del_ParseTree(State, Key),
- {ok, ?set_Constraints(State, Acc++T)};
-match_delete(State, [H|T], ID, Acc) ->
- match_delete(State, T, ID, [H|Acc]).
-
-%% Remove all data related with constraints; for now, since no other data
-%% stored in DB, we do in a rather brutal way.
-clear_DB(State) ->
- catch ets:delete(State#state.etsR),
- State#state{etsR = ets:new(oe_ets, [bag, protected]), constraints=[]}.
-
-%% Given a list of Constrain IDs we want to find the related constraints.
-%% !!!!!! This function may not alter any data in DB in any way !!!!!!!!!!
-lookup_constraints(IDs, State) ->
- lookup_constraints(IDs, State, []).
-lookup_constraints([], _State, Accum) ->
- Accum;
-lookup_constraints([H|T], State, Accum)
- when is_record(H, 'CosNotifyFilter_ConstraintInfo') ->
- case ?get_Constraint(State, H#'CosNotifyFilter_ConstraintInfo'.constraint_id) of
- error ->
- corba:raise(#'CosNotifyFilter_ConstraintNotFound'
- {id = H#'CosNotifyFilter_ConstraintInfo'.constraint_id});
- _Con ->
- %% We don't need to collect the result since the input already is of
- %% the correct type, i.e., ConstraintInfoSeq
- lookup_constraints(T, State, Accum)
- end;
-lookup_constraints([H|T], State, Accum) when is_integer(H) ->
- case ?get_Constraint(State,H) of
- error ->
- corba:raise(#'CosNotifyFilter_ConstraintNotFound'{id=H});
- Con ->
- lookup_constraints(T, State, [Con|Accum])
- end;
-lookup_constraints(_, _, _) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%% Given a list of Constrain IDs we want to delet the related constraints.
-%% We need also to return the ConstraintInfoSeq described related to the
-%% given ID's.
-delete_constraints([], State) ->
- State;
-delete_constraints([H|T], State)
- when is_record(H, 'CosNotifyFilter_ConstraintInfo') ->
- case catch ?del_Constraint(State,
- H#'CosNotifyFilter_ConstraintInfo'.constraint_id) of
- {ok, NewState} ->
- delete_constraints(T, NewState);
- Reason ->
- orber:dbg("[~p] 'CosNotifyFilter_Filter':modify_constraints().~n"
- "Unable to remove: ~p~n"
- "Reason: ~p~n",
- [?LINE, H, Reason], ?DEBUG_LEVEL),
- delete_constraints(T, State)
- end;
-delete_constraints([H|T], State) ->
- case catch ?del_Constraint(State,H) of
- {ok, NewState} ->
- delete_constraints(T, NewState);
- Reason ->
- orber:dbg("[~p] 'CosNotifyFilter_Filter':modify_constraints().~n"
- "Unable to remove: ~p~n"
- "Reason: ~p~n",
- [?LINE, H, Reason], ?DEBUG_LEVEL),
- delete_constraints(T, State)
- end.
-
-%% Inform all registered callbacks that the constraints have changed.
-%% Added and Removed must be a CosNotification::EventTypeSeq
-inform_callbacks([],_,_) ->
- ok;
-inform_callbacks([H|T], Added, Removed) ->
- case catch 'CosNotifyComm_NotifySubscribe':subscription_change(H, Added, Removed) of
- ok ->
- ?debug_print("INFORMED CALLBACK: ~p ADDED: ~p REMOVED: ~p",
- [H, Added, Removed]),
- inform_callbacks(T, Added, Removed);
- Other ->
- orber:dbg("[~p] 'CosNotifyComm_NotifySubscribe':subscription_change().~n"
- "Unable to inform callback: ~p~n"
- "Reason: ~p~n",
- [?LINE, H, Other], ?DEBUG_LEVEL),
- inform_callbacks(T, Added, Removed)
- end.
-
-%%-----------------------------------------------------------
-%% Function : try_create_filters/2
-%% Arguments: CL - #'CosNotifyFilter_ConstraintExp'{
-%% event_types = [#'CosNotification_EventType'{
-%% domain_name = Str, type_name = Str}]
-%% constraint_expr = Str}
-%% Returns : {State, AccumList}
-%%-----------------------------------------------------------
-%% !!!!!! This function may not alter any data in DB in any way !!!!!!!!!!
-try_create_filters(State, CL) ->
- try_create_filters(State, CL, [], [], []).
-try_create_filters(State, [], Accum, InfoSeq, EventTSeq) ->
- {State, Accum, InfoSeq, EventTSeq};
-try_create_filters(State, [#'CosNotifyFilter_ConstraintExp'{event_types = Types,
- constraint_expr = Con}|T],
- Accum, InfoSeq, EventTSeq) ->
- case catch cosNotification_Filter:create_filter(Con) of
- {ok, Tree} ->
- case catch cosNotification_Filter:check_types(Types) of
- true ->
- ID = ?new_Id(State),
- Key = ?not_CreateDBKey,
- NewETSeq = Types ++ EventTSeq,
- try_create_filters(?set_IdCounter(State, ID), T,
- [{ID, true, [], Key, Types, Con, Tree}|Accum],
- [?create_ConstraintInfo(Types, Con, ID)|InfoSeq],
- NewETSeq);
- {ok, Which, WC} ->
- ID = ?new_Id(State),
- Key = ?not_CreateDBKey,
- NewETSeq = Types ++ EventTSeq,
- try_create_filters(?set_IdCounter(State, ID), T,
- [{ID, Which, WC, Key, Types, Con, Tree}|Accum],
- [?create_ConstraintInfo(Types, Con, ID)|InfoSeq],
- NewETSeq);
- _ ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end;
- _ ->
- corba:raise(#'CosNotifyFilter_InvalidConstraint'
- {constr = #'CosNotifyFilter_ConstraintExp'
- {event_types = Types, constraint_expr = Con}})
- end;
-try_create_filters(State, [#'CosNotifyFilter_ConstraintInfo'
- {constraint_expression = #'CosNotifyFilter_ConstraintExp'
- {event_types = Types, constraint_expr = Con},
- constraint_id=ID}|T], Accum, InfoSeq, EventTSeq) ->
- case catch cosNotification_Filter:create_filter(Con) of
- {ok, Tree} ->
- case catch cosNotification_Filter:check_types(Types) of
- true ->
- Key = ?not_CreateDBKey,
- NewETSeq = Types ++ EventTSeq,
- try_create_filters(State, T,
- [{ID, true, [], Key, Types, Con, Tree}|Accum],
- [?create_ConstraintInfo(Types, Con, ID)|InfoSeq],
- NewETSeq);
- {ok, Which, WC} ->
- Key = ?not_CreateDBKey,
- NewETSeq = Types ++ EventTSeq,
- try_create_filters(State, T,
- [{ID, Which, WC, Key, Types, Con, Tree}|Accum],
- [?create_ConstraintInfo(Types, Con, ID)|InfoSeq],
- NewETSeq);
- _ ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end;
- _ ->
- corba:raise(#'CosNotifyFilter_InvalidConstraint'
- {constr = #'CosNotifyFilter_ConstraintExp'
- {event_types = Types, constraint_expr = Con}})
- end;
-try_create_filters(_,_,_,_,_) ->
- %% The list contained something else but ConstraintExp.
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------
-%% Function : store_filters/4
-%% Arguments: Filters - a list of filters.
-%% Returns :
-%%-----------------------------------------------------------
-
-store_filters(State, []) ->
- State;
-store_filters(State, [{ID, Which, WC, Key, Types, Con, Tree}|T]) ->
- ?add_ParseTree(State, Key, Tree),
- write_types(State, Types, ID, Key),
- store_filters(?add_Constraint(State, ID, Con, Which, WC, Key, Types), T).
-
-
-write_types(_State, [],_, _) ->
- ok;
-write_types(State, [EventType|T], ID, Key) ->
- ?add_Type(State, ID, EventType, Key),
- ?debug_print("FILTER: ~p ~p ~p~n", [ID, Key, EventType]),
- write_types(State, T, ID, Key).
-
-%%-----------------------------------------------------------
-%% Function : match_any_event
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-match_any_event(State, _Event, []) ->
- ?debug_print("FILTER REJECTED: ~p~n", [_Event]),
- {reply, false, State};
-match_any_event(State, Event, [{_, _, _, _, Key, _}|T]) ->
- case catch cosNotification_Filter:eval(?get_ParseTree(State,Key), Event) of
- true ->
- ?debug_print("FILTER APPROVED (WC): ~p~n", [Event]),
- {reply, true, State};
- _ ->
- match_any_event(State, Event, T)
- end.
-
-
-%%-----------------------------------------------------------
-%% Function : match_str_event
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-
-match_str_event(State, _Event, []) ->
- ?debug_print("FILTER REJECTED: ~p~n", [_Event]),
- {reply, false, State};
-match_str_event(State, Event, [{ID, _Con, Which, WC, Key, _Types}|T]) ->
- ET = ((Event#'CosNotification_StructuredEvent'.header)
- #'CosNotification_EventHeader'.fixed_header)
- #'CosNotification_FixedEventHeader'.event_type,
- CheckList =
- case Which of
- both ->
- [ET];
- domain ->
- [ET,
- ET#'CosNotification_EventType'{type_name=""},
- ET#'CosNotification_EventType'{type_name="*"}];
- type ->
- [ET,
- ET#'CosNotification_EventType'{domain_name=""},
- ET#'CosNotification_EventType'{domain_name="*"}];
- _ ->
- [ET,
- ET#'CosNotification_EventType'{type_name=""},
- ET#'CosNotification_EventType'{type_name="*"},
- ET#'CosNotification_EventType'{domain_name=""},
- ET#'CosNotification_EventType'{domain_name="*"}]
- end,
- case check_DB(State, ID, CheckList) of
- false ->
- %% No match, may have used wildcards, e.g., "dom*".
- case catch cosNotification_Filter:match_types(
- ET#'CosNotification_EventType'.domain_name,
- ET#'CosNotification_EventType'.type_name,
- WC) of
- true ->
- case catch cosNotification_Filter:eval(?get_ParseTree(State,Key),
- Event) of
- true ->
- ?debug_print("FILTER APPROVED (WC): ~p~n", [Event]),
- {reply, true, State};
- _ ->
- match_str_event(State, Event, T)
- end;
- _->
- match_str_event(State, Event, T)
- end;
- Key ->
- case catch cosNotification_Filter:eval(?get_ParseTree(State,Key),
- Event) of
- true ->
- ?debug_print("FILTER APPROVED: ~p~n", [Event]),
- {reply, true, State};
- _ ->
- match_str_event(State, Event, T)
- end
- end.
-
-check_DB(_, _, []) ->
- false;
-check_DB(State, ID, [H|T]) ->
- case ?match_Type(State, ID, H) of
- [] ->
- check_DB(State, ID, T);
- [{_, K, types}|_] ->
- K
- end.
-
-
-%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
-%%--------------- END OF MODULE ------------------------------
-
diff --git a/lib/cosNotification/src/CosNotifyFilter_MappingFilter_impl.erl b/lib/cosNotification/src/CosNotifyFilter_MappingFilter_impl.erl
deleted file mode 100644
index 03c0e03be6..0000000000
--- a/lib/cosNotification/src/CosNotifyFilter_MappingFilter_impl.erl
+++ /dev/null
@@ -1,580 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosNotifyFilter_MappingFilter_impl.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module('CosNotifyFilter_MappingFilter_impl').
-
-%%--------------- INCLUDES -----------------------------------
-%% Application files
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-%% Application files
--include("CosNotification.hrl").
--include("CosNotifyChannelAdmin.hrl").
--include("CosNotifyComm.hrl").
--include("CosNotifyFilter.hrl").
--include("CosNotification_Definitions.hrl").
-
-%%--------------- IMPORTS ------------------------------------
-
-%%--------------- EXPORTS ------------------------------------
-%% External Attributes
--export(['_get_constraint_grammar'/2,
- '_get_value_type'/2,
- '_get_default_value'/2]).
-%% External Functions
--export([add_mapping_constraints/3,
- modify_mapping_constraints/4,
- get_mapping_constraints/3,
- get_all_mapping_constraints/2,
- remove_all_mapping_constraints/2,
- destroy/2,
- match/3,
- match_structured/3,
- match_typed/3]).
-
-%%--------------- gen_server specific exports ----------------
--export([handle_info/2, code_change/3]).
--export([init/1, terminate/2]).
-
-%%--------------- LOCAL DEFINITIONS --------------------------
-%%######### MISC ##########
--define(create_MappingInfo(_Types, _Con, _ID, _A),
- #'CosNotifyFilter_MappingConstraintInfo'{
- constraint_expression =
- #'CosNotifyFilter_ConstraintExp'{
- event_types = _Types,
- constraint_expr = _Con},
- constraint_id = _ID,
- value = _A
- }).
-%%#### Data structures ####
--record(state, {constraint_grammar,
- value,
- typeC,
- constraints = [],
- filters = [],
- idCounter = 0,
- filterFactory,
- factoryPid,
- etsR}).
-
-%% Data structures constructors
--define(get_InitState(Gr, DVal, FF, FP),
- #state{constraint_grammar=Gr,
- value = DVal,
- typeC = any:get_typecode(DVal),
- filterFactory = FF,
- factoryPid = FP,
- etsR = ets:new(oe_ets, [bag, protected])}).
-
-%%------------------- Data structures selectors -------------------
-%% Attributes
--define(get_Grammar(S), S#state.constraint_grammar).
--define(get_DefVal(S), S#state.value).
--define(get_DefTC(S), S#state.typeC).
--define(get_DefAny(S), S#state.value).
-
-%% ID:s
--define(get_IdCounter(S), S#state.idCounter).
-
-%% Constraints
--define(get_Constraint(S,I), find_obj(lists:keysearch(I, 1, S#state.constraints),
- constraint)).
--define(get_AllConstraints(S), lists:map(fun({I, C, _W, _WC, _K, T, A}) ->
- ?create_MappingInfo(T, C, I, A)
- end,
- S#state.constraints)).
--define(get_ConstraintAllData(S), S#state.constraints).
--define(get_ConstraintData(S,I), lists:keysearch(I, 1, S#state.constraints)).
--define(match_Type(S,I,ET), ets:lookup(S#state.etsR, {I, ET})).
-%% Parse Tree
--define(get_ParseTree(S,K), find_obj(ets:lookup(S#state.etsR, K), tree)).
-
-%%------------------- Data structures modifiers -------------------
-%% ID:s
--define(set_IdCounter(S,V), S#state{idCounter=V}).
--define(new_Id(S), 'CosNotification_Common':create_id(S#state.idCounter)).
-
-%% Constraints
--define(del_Constraint(S, I), match_delete(S, S#state.constraints, I)).
--define(del_AllConstraints(S), clear_DB(S)).
--define(add_Constraint(S,I,C,W,_WC,K,T,A), S#state{constraints =
- [{I, C, W, _WC, K, T, A}|S#state.constraints]}).
--define(set_Constraints(S,C), S#state{constraints = C}).
-
--define(del_AllTypes(S), ets:match_delete(S#state.etsR, {'_','_',types})).
--define(del_Type(S,I), ets:match_delete(S#state.etsR, {{I, '_'}, '_', types})).
--define(add_Type(S,I,ET,K), ets:insert(S#state.etsR, {{I, ET}, K, types})).
-
-%% Parse Tree
--define(add_ParseTree(S,K,T), ets:insert(S#state.etsR, {K, T, tree})).
--define(del_ParseTree(S,K), ets:delete(S#state.etsR, K)).
--define(del_AllParseTress(S), ets:match_delete(S#state.etsR, {'_','_',tree})).
-
-%%------------------- MISC ----------------------------------------
--define(is_EmptyFilter(S), S#state.constraints==[]).
--define(is_EqualType(S,T), S#state.typeC==any:get_typecode(T)).
-
-%%-----------------------------------------------------------%
-%% function : handle_info, code_change
-%% Arguments: See gen_server documentation.
-%% Effect : Functions demanded by the gen_server module.
-%%------------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-handle_info(Info, State) ->
- ?debug_print("INFO: ~p DATA: ~p~n", [State, Info]),
- case Info of
- {'EXIT', _Pid, _Reason} ->
- {noreply, State};
- _ ->
- {noreply, State}
- end.
-
-%%----------------------------------------------------------%
-%% function : init, terminate
-%% Arguments:
-%%-----------------------------------------------------------
-
-init([FiFac, FacPid, InitGr, DefVal]) ->
- process_flag(trap_exit, true),
- {ok, ?get_InitState(InitGr, DefVal, FiFac, FacPid)}.
-
-terminate(_Reason, _State) ->
- ok.
-
-%%-----------------------------------------------------------
-%%------- Exported external attributes ----------------------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% Function : '_get_constraint_grammar'/2
-%% Type : readonly
-%% Returns : string()
-%%-----------------------------------------------------------
-'_get_constraint_grammar'(_OE_THIS, State) ->
- {reply, ?get_Grammar(State), State}.
-%%----------------------------------------------------------%
-%% Function : '_get_value_type'/2
-%% Type : readonly
-%% Returns : CORBA::TypeCode
-%%-----------------------------------------------------------
-'_get_value_type'(_OE_THIS, State) ->
- {reply, ?get_DefTC(State), State}.
-%%----------------------------------------------------------%
-%% Function : '_get_default_value'/2
-%% Type : readonly
-%% Returns : #any{}
-%%-----------------------------------------------------------
-'_get_default_value'(_OE_THIS, State) ->
- {reply, ?get_DefVal(State), State}.
-
-%%-----------------------------------------------------------
-%%------- Exported external functions -----------------------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% Function : add_mapping_constraints/3
-%% Arguments: Pairs - CosNotifyFilter::MappingConstraintPairSeq
-%% Returns : CosNotifyFilter::MappingConstraintInfoSeq |
-%% {'EXCEPTION', CosNotifyFilter::InvalidConstraint} |
-%% {'EXCEPTION', CosNotifyFilter::InvalidValue}
-%%-----------------------------------------------------------
-add_mapping_constraints(_OE_THIS, State, Pairs) ->
- {NewState, Filters, Info} = try_create_filters(State, Pairs),
- NewState2=store_filters(NewState, Filters),
- {reply, Info, NewState2}.
-
-%%----------------------------------------------------------%
-%% Function : modify_mapping_constraints/4
-%% Arguments: IDs - CosNotifyFilter::ConstraintIDSeq
-%% Info - CosNotifyFilter::MappingConstraintInfoSeq
-%% Returns : ok |
-%% {'EXCEPTION', CosNotifyFilter::InvalidConstraint} |
-%% {'EXCEPTION', CosNotifyFilter::InvalidValue} |
-%% {'EXCEPTION', CosNotifyFilter::ConstraintNotFound}
-%%-----------------------------------------------------------
-modify_mapping_constraints(_OE_THIS, State, IDs, InfoSeq) ->
- lookup_constraints(IDs, State),
- lookup_constraints(InfoSeq, State),
- {NewState, Filters, _Info} = try_create_filters(State, InfoSeq),
-
- %% We cannot change anything before our checks (see above). Hence,
- %% do NOT move the following lines above this point.
-
- NewState2 = delete_constraints(IDs, NewState),
- NewState3 = delete_constraints(InfoSeq, NewState2),
- NewState4 = store_filters(NewState3, Filters),
- {reply, ok, NewState4}.
-
-%%----------------------------------------------------------%
-%% Function : get_mapping_constraints/3
-%% Arguments: IDs - CosNotifyFilter::ConstraintIDSeq
-%% Returns : CosNotifyFilter::MappingConstraintInfoSeq |
-%% {'EXCEPTION', CosNotifyFilter::ConstraintNotFound}
-%%-----------------------------------------------------------
-get_mapping_constraints(_OE_THIS, State, IDs) ->
- {reply, lookup_constraints(IDs, State), State}.
-
-%%----------------------------------------------------------%
-%% Function : get_all_mapping_constraints/2
-%% Arguments: -
-%% Returns : CosNotifyFilter::MappingConstraintInfoSeq
-%%-----------------------------------------------------------
-get_all_mapping_constraints(_OE_THIS, State) ->
- {reply, ?get_AllConstraints(State), State}.
-
-%%----------------------------------------------------------%
-%% Function : remove_all_mapping_constraints/2
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-remove_all_mapping_constraints(_OE_THIS, State) ->
- {reply, ok, ?del_AllConstraints(State)}.
-
-%%----------------------------------------------------------%
-%% Function : destroy/2
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-destroy(_OE_THIS, State) ->
- {stop, normal, ok, State}.
-
-%%----------------------------------------------------------%
-%% Function : match/3
-%% Arguments: Event - #any{}
-%% Returns : boolean(), #any{} (out-type) |
-%% {'EXCEPTION', CosNotifyFilter::UnsupportedFilterableData}
-%%-----------------------------------------------------------
-match(_OE_THIS, State, Event) when is_record(Event,'any') andalso ?is_EmptyFilter(State) ->
- {reply, {false, ?get_DefAny(State)}, State};
-match(_OE_THIS, State, Event) when is_record(Event,'any') ->
- match_any_event(State, Event, ?get_ConstraintAllData(State));
-match(_,_,_) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-
-%%----------------------------------------------------------%
-%% Function : match_structured/3
-%% Arguments: Event - CosNotification::StructuredEvent
-%% Returns : boolean(), #any{} (out-type) |
-%% {'EXCEPTION', CosNotifyFilter::UnsupportedFilterableData}
-%%-----------------------------------------------------------
-match_structured(_OE_THIS, State, Event) when
- is_record(Event,'CosNotification_StructuredEvent') andalso ?is_EmptyFilter(State) ->
- {reply, {false, ?get_DefAny(State)}, State};
-match_structured(_OE_THIS, State, Event) when
- is_record(Event,'CosNotification_StructuredEvent') ->
- match_str_event(State, Event, ?get_ConstraintAllData(State));
-match_structured(_,_,_) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------*
-%% Function : match_typed/3
-%% Arguments: Data - CosNotification::PropertySeq
-%% Returns : boolean() , #any{} (out-type) |
-%% {'EXCEPTION', CosNotifyFilter::UnsupportedFilterableData}
-%%-----------------------------------------------------------
--spec match_typed(_, _, _) -> no_return().
-match_typed(_OE_THIS, _State, _Data) ->
- corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}).
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-%% To match constraints
-find_obj({value, {Id, Con, _, _, _, Types, Any}}, _) ->
- ?create_MappingInfo(Types, Con, Id, Any);
-find_obj([{_, Tree, tree}|_], tree) -> Tree;
-find_obj(_,tree) -> undefined;
-find_obj(_,constraint) -> error.
-
-%% Delete given object from list and all related objects in DB (parse tree and types).
-match_delete(State, Constraints, ID) ->
- match_delete(State, Constraints, ID, []).
-match_delete(_, [], _, _) ->
- error;
-match_delete(State, [{ID, _Con, _Which, _WC, Key, _Types, _Any}|T], ID, Acc) ->
- ?del_Type(State, ID),
- ?del_ParseTree(State, Key),
- {ok, ?set_Constraints(State, Acc++T)};
-match_delete(State, [H|T], ID, Acc) ->
- match_delete(State, T, ID, [H|Acc]).
-
-%% Remove all data related with constraints; for now, since no other data
-%% stored in DB, we do in a rather brutal way.
-clear_DB(State) ->
- catch ets:delete(State#state.etsR),
- State#state{etsR = ets:new(oe_ets, [bag, protected]), constraints=[]}.
-
-%% Given a list of Constrain IDs we want to find the related constraints.
-%% !!!!!! This function may not alter any data in DB in any way !!!!!!!!!!
-lookup_constraints(IDs, State) ->
- lookup_constraints(IDs, State, []).
-lookup_constraints([], _State, Accum) ->
- Accum;
-lookup_constraints([H|T], State, Accum)
- when is_record(H, 'CosNotifyFilter_MappingConstraintInfo') ->
- case ?get_Constraint(State, H#'CosNotifyFilter_MappingConstraintInfo'.constraint_id) of
- error ->
- corba:raise(#'CosNotifyFilter_ConstraintNotFound'
- {id = H#'CosNotifyFilter_MappingConstraintInfo'.constraint_id});
- _Con ->
- %% We don't need to collect the result since the input already is of
- %% the correct type, i.e., ConstraintInfoSeq
- lookup_constraints(T, State, Accum)
- end;
-lookup_constraints([H|T], State, Accum) when is_integer(H) ->
- case ?get_Constraint(State,H) of
- error ->
- corba:raise(#'CosNotifyFilter_ConstraintNotFound'{id=H});
- Con ->
- lookup_constraints(T, State, [Con|Accum])
- end;
-lookup_constraints(_, _, _) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%% Given a list of Constrain IDs we want to delet the related constraints.
-%% We need also to return the ConstraintInfoSeq described related to the
-%% given ID's.
-delete_constraints([], State) ->
- State;
-delete_constraints([H|T], State)
- when is_record(H, 'CosNotifyFilter_MappingConstraintInfo') ->
- case catch ?del_Constraint(State,
- H#'CosNotifyFilter_MappingConstraintInfo'.constraint_id) of
- {ok, NewState} ->
- delete_constraints(T, NewState);
- Reason ->
- orber:dbg("[~p] 'CosNotifyFilter_MappingFilter':modify_mapping_constraints().~n"
- "Unable to remove: ~p~n"
- "Reason: ~p~n",
- [?LINE, H, Reason], ?DEBUG_LEVEL),
- delete_constraints(T, State)
- end;
-delete_constraints([H|T], State) ->
- case catch ?del_Constraint(State,H) of
- {ok, NewState} ->
- delete_constraints(T, NewState);
- Reason ->
- orber:dbg("[~p] 'CosNotifyFilter_MappingFilter':modify_mapping_constraints().~n"
- "Unable to remove: ~p~n"
- "Reason: ~p~n",
- [?LINE, H, Reason], ?DEBUG_LEVEL),
- delete_constraints(T, State)
- end.
-
-%%-----------------------------------------------------------
-%% Function : try_create_filters/2
-%% Arguments: CL - #'CosNotifyFilter_MappingConstraintPair{
-%% constraint_expression =
-%% #'CosNotifyFilter_ConstraintExp'{
-%% event_types =
-%% [#'CosNotification_EventType'{
-%% domain_name = Str, type_name = Str}]
-%% constraint_expr = Str},
-%% result_to_set = Any}
-%% Returns : {State, AccumList}
-%%-----------------------------------------------------------
-%% !!!!!! This function may not alter any data in DB in any way !!!!!!!!!!
-try_create_filters(State, CL) ->
- try_create_filters(State, CL, [], []).
-try_create_filters(State, [], Accum, InfoSeq) ->
- {State, Accum, InfoSeq};
-try_create_filters(State, [#'CosNotifyFilter_MappingConstraintPair'
- {constraint_expression =
- #'CosNotifyFilter_ConstraintExp'{event_types = Types,
- constraint_expr = Con},
- result_to_set=Any}|T], Accum, InfoSeq) ->
- case catch {?is_EqualType(State,Any), cosNotification_Filter:create_filter(Con)} of
- {false, _} ->
- corba:raise(#'CosNotifyFilter_InvalidValue'
- {constr = #'CosNotifyFilter_ConstraintExp'
- {event_types = Types, constraint_expr = Con},
- value=Any});
- {_, {ok, Tree}} ->
- case catch cosNotification_Filter:check_types(Types) of
- true ->
- ID = ?new_Id(State),
- Key = ?not_CreateDBKey,
- try_create_filters(?set_IdCounter(State, ID), T,
- [{ID, true, [], Key, Types, Con, Tree, Any}|Accum],
- [?create_MappingInfo(Types, Con, ID, Any)|InfoSeq]);
- {ok, Which, WC} ->
- ID = ?new_Id(State),
- Key = ?not_CreateDBKey,
- try_create_filters(?set_IdCounter(State, ID), T,
- [{ID, Which, WC, Key, Types, Con, Tree, Any}|Accum],
- [?create_MappingInfo(Types, Con, ID, Any)|InfoSeq]);
- _ ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end;
- _ ->
- corba:raise(#'CosNotifyFilter_InvalidConstraint'
- {constr = #'CosNotifyFilter_ConstraintExp'
- {event_types = Types, constraint_expr = Con}})
- end;
-try_create_filters(State, [#'CosNotifyFilter_MappingConstraintInfo'
- {constraint_expression = #'CosNotifyFilter_ConstraintExp'
- {event_types = Types, constraint_expr = Con},
- constraint_id=ID,
- value=Any}|T], Accum, InfoSeq) ->
- case catch cosNotification_Filter:create_filter(Con) of
- {ok, Tree} ->
- case catch cosNotification_Filter:check_types(Types) of
- true ->
- Key = ?not_CreateDBKey,
- try_create_filters(State, T,
- [{ID, true, [], Key, Types, Con, Tree, Any}|Accum],
- [?create_MappingInfo(Types, Con, ID, Any)|InfoSeq]);
- {ok, Which, WC} ->
- Key = ?not_CreateDBKey,
- try_create_filters(State, T,
- [{ID, Which, WC, Key, Types, Con, Tree, Any}|Accum],
- [?create_MappingInfo(Types, Con, ID, Any)|InfoSeq]);
- _ ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end;
- _ ->
- corba:raise(#'CosNotifyFilter_InvalidConstraint'
- {constr = #'CosNotifyFilter_ConstraintExp'
- {event_types = Types, constraint_expr = Con}})
- end;
-try_create_filters(_,_,_,_) ->
- %% The list contained something else but ConstraintExp.
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------
-%% Function : store_filters/4
-%% Arguments: Filters - a list of filters.
-%% Returns :
-%%-----------------------------------------------------------
-
-store_filters(State, []) ->
- State;
-store_filters(State, [{ID, Which, WC, Key, Types, Con, Tree, Any}|T]) ->
- ?add_ParseTree(State, Key, Tree),
- write_types(State, Types, ID, Key),
- store_filters(?add_Constraint(State, ID, Con, Which, WC, Key, Types, Any), T).
-
-
-write_types(_State, [],_, _) ->
- ok;
-write_types(State, [EventType|T], ID, Key) ->
- ?add_Type(State, ID, EventType, Key),
- ?debug_print("FILTER: ~p ~p ~p~n", [ID, Key, EventType]),
- write_types(State, T, ID, Key).
-
-%%-----------------------------------------------------------
-%% Function : match_any_event
-%% Arguments: Event - #any{}
-%% Returns :
-%%-----------------------------------------------------------
-match_any_event(State, _Event, []) ->
- ?debug_print("FILTER REJECTED: ~p~n", [_Event]),
- {reply, {false, ?get_DefAny(State)}, State};
-match_any_event(State, Event, [{_, _, _, _, Key, Any}|T]) ->
- case catch cosNotification_Filter:eval(?get_ParseTree(State,Key), Event) of
- true ->
- ?debug_print("FILTER APPROVED (WC): ~p~n", [Event]),
- {reply, {true, Any}, State};
- _ ->
- match_any_event(State, Event, T)
- end.
-
-
-%%-----------------------------------------------------------
-%% Function : match_str_event
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-
-match_str_event(State, _Event, []) ->
- ?debug_print("FILTER REJECTED: ~p~n", [_Event]),
- {reply, {false, ?get_DefAny(State)}, State};
-match_str_event(State, Event, [{ID, _Con, Which, WC, Key, _Types, Any}|T]) ->
- ET = ((Event#'CosNotification_StructuredEvent'.header)
- #'CosNotification_EventHeader'.fixed_header)
- #'CosNotification_FixedEventHeader'.event_type,
- CheckList =
- case Which of
- both ->
- [ET];
- domain ->
- [ET,
- ET#'CosNotification_EventType'{type_name=""},
- ET#'CosNotification_EventType'{type_name="*"}];
- type ->
- [ET,
- ET#'CosNotification_EventType'{domain_name=""},
- ET#'CosNotification_EventType'{domain_name="*"}];
- _ ->
- [ET,
- ET#'CosNotification_EventType'{type_name=""},
- ET#'CosNotification_EventType'{type_name="*"},
- ET#'CosNotification_EventType'{domain_name=""},
- ET#'CosNotification_EventType'{domain_name="*"}]
- end,
- case check_DB(State, ID, CheckList) of
- false ->
- %% No match, may have used wildcards, e.g., "dom*".
- case catch cosNotification_Filter:match_types(
- ET#'CosNotification_EventType'.domain_name,
- ET#'CosNotification_EventType'.type_name,
- WC) of
- true ->
- case catch cosNotification_Filter:eval(?get_ParseTree(State,Key),
- Event) of
- true ->
- ?debug_print("FILTER APPROVED (WC): ~p~n", [Event]),
- {reply, {true, Any}, State};
- _ ->
- match_str_event(State, Event, T)
- end;
- _->
- match_str_event(State, Event, T)
- end;
- Key ->
- case catch cosNotification_Filter:eval(?get_ParseTree(State,Key),
- Event) of
- true ->
- ?debug_print("FILTER APPROVED: ~p~n", [Event]),
- {reply, {true, Any}, State};
- _ ->
- match_str_event(State, Event, T)
- end
- end.
-
-check_DB(_, _, []) ->
- false;
-check_DB(State, ID, [H|T]) ->
- case ?match_Type(State, ID, H) of
- [] ->
- check_DB(State, ID, T);
- [{_, K, types}|_] ->
- K
- end.
-%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
-%%--------------- END OF MODULE ------------------------------
-
diff --git a/lib/cosNotification/src/CosTypedEvent.idl b/lib/cosNotification/src/CosTypedEvent.idl
deleted file mode 100644
index d77c37731a..0000000000
--- a/lib/cosNotification/src/CosTypedEvent.idl
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef _COS_TYPED_EVENT_IDL_
-#define _COS_TYPED_EVENT_IDL_
-
-#pragma prefix "omg.org"
-
-#include<CosEvent.idl>
-
-module CosTypedEventComm {
-
- interface TypedPushConsumer : CosEventComm::PushConsumer {
- Object get_typed_consumer();
- };
-
- interface TypedPullSupplier : CosEventComm::PullSupplier {
- Object get_typed_supplier();
- };
-};
-
-module CosTypedEventChannelAdmin {
-
- exception InterfaceNotSupported {};
- exception NoSuchImplementation {};
- typedef string Key;
-
-
- interface TypedProxyPushConsumer :
- CosEventChannelAdmin::ProxyPushConsumer,
- CosTypedEventComm::TypedPushConsumer { };
-
- interface TypedProxyPullSupplier :
- CosEventChannelAdmin::ProxyPullSupplier,
- CosTypedEventComm::TypedPullSupplier { };
-
- interface TypedSupplierAdmin :
- CosEventChannelAdmin::SupplierAdmin {
- TypedProxyPushConsumer obtain_typed_push_consumer(in Key supported_interface)
- raises(InterfaceNotSupported);
- CosEventChannelAdmin::ProxyPullConsumer obtain_typed_pull_consumer (in Key uses_interface)
- raises(NoSuchImplementation);
- };
-
- interface TypedConsumerAdmin :
- CosEventChannelAdmin::ConsumerAdmin {
- TypedProxyPullSupplier obtain_typed_pull_supplier(in Key supported_interface)
- raises (InterfaceNotSupported);
- CosEventChannelAdmin::ProxyPushSupplier obtain_typed_push_supplier(in Key uses_interface)
- raises(NoSuchImplementation);
- };
-
- interface TypedEventChannel {
- TypedConsumerAdmin for_consumers();
- TypedSupplierAdmin for_suppliers();
- void destroy ();
- };
-};
-
-#endif /* ifndef _COS_TYPED_EVENT_IDL_ */
diff --git a/lib/cosNotification/src/CosTypedNotification.idl b/lib/cosNotification/src/CosTypedNotification.idl
deleted file mode 100644
index 882cde16e0..0000000000
--- a/lib/cosNotification/src/CosTypedNotification.idl
+++ /dev/null
@@ -1,109 +0,0 @@
-#ifndef _COS_TYPED_NOTIFICATION_IDL_
-#define _COS_TYPED_NOTIFICATION_IDL_
-
-#pragma prefix "omg.org"
-
-#include<CosNotifyChannelAdmin.idl>
-#include<CosTypedEvent.idl>
-#include<CosNotification.idl>
-
-module CosTypedNotifyComm {
- interface TypedPushConsumer : CosTypedEventComm::TypedPushConsumer, CosNotifyComm::NotifyPublish { }; // TypedPushConsumer
-
- interface TypedPullSupplier : CosTypedEventComm::TypedPullSupplier, CosNotifyComm::NotifySubscribe { }; // TypedPullSupplier
-}; // CosTypedNotifyComm
-
-
-module CosTypedNotifyChannelAdmin {
- // Forward declaration
- interface TypedEventChannelFactory;
- typedef string Key;
- interface TypedProxyPushConsumer : CosNotifyChannelAdmin::ProxyConsumer, CosTypedNotifyComm::TypedPushConsumer {
- void connect_typed_push_supplier (in CosEventComm::PushSupplier push_supplier)
- raises (CosEventChannelAdmin::AlreadyConnected);
- }; // TypedProxyPushConsumer
-
- interface TypedProxyPullSupplier : CosNotifyChannelAdmin::ProxySupplier, CosTypedNotifyComm::TypedPullSupplier {
- void connect_typed_pull_consumer (in CosEventComm::PullConsumer pull_consumer)
- raises (CosEventChannelAdmin::AlreadyConnected);
- }; // TypedProxyPullSupplier
-
- interface TypedProxyPullConsumer : CosNotifyChannelAdmin::ProxyConsumer, CosNotifyComm::PullConsumer {
- void connect_typed_pull_supplier (in CosTypedEventComm::TypedPullSupplier pull_supplier)
- raises (CosEventChannelAdmin::AlreadyConnected, CosEventChannelAdmin::TypeError);
-
- void suspend_connection()
- raises (CosNotifyChannelAdmin::ConnectionAlreadyInactive, CosNotifyChannelAdmin::NotConnected);
-
- void resume_connection()
- raises (CosNotifyChannelAdmin::ConnectionAlreadyActive, CosNotifyChannelAdmin::NotConnected);
- }; // TypedProxyPullConsumer
-
- interface TypedProxyPushSupplier : CosNotifyChannelAdmin::ProxySupplier, CosNotifyComm::PushSupplier {
- void connect_typed_push_consumer (in CosTypedEventComm::TypedPushConsumer push_consumer)
- raises (CosEventChannelAdmin::AlreadyConnected, CosEventChannelAdmin::TypeError);
-
- void suspend_connection()
- raises (CosNotifyChannelAdmin::ConnectionAlreadyInactive, CosNotifyChannelAdmin::NotConnected);
-
- void resume_connection()
- raises (CosNotifyChannelAdmin::ConnectionAlreadyActive, CosNotifyChannelAdmin::NotConnected);
- }; // TypedProxyPushSupplier
-
- interface TypedConsumerAdmin : CosNotifyChannelAdmin::ConsumerAdmin, CosTypedEventChannelAdmin::TypedConsumerAdmin {
- TypedProxyPullSupplier obtain_typed_notification_pull_supplier(in Key supported_interface,
- out CosNotifyChannelAdmin::ProxyID proxy_id)
- raises( CosTypedEventChannelAdmin::InterfaceNotSupported, CosNotifyChannelAdmin::AdminLimitExceeded );
-
- TypedProxyPushSupplier obtain_typed_notification_push_supplier(in Key uses_interface,
- out CosNotifyChannelAdmin::ProxyID proxy_id)
- raises(CosTypedEventChannelAdmin::NoSuchImplementation, CosNotifyChannelAdmin::AdminLimitExceeded);
- }; // TypedConsumerAdmin
-
- interface TypedSupplierAdmin : CosNotifyChannelAdmin::SupplierAdmin, CosTypedEventChannelAdmin::TypedSupplierAdmin {
- TypedProxyPushConsumer obtain_typed_notification_push_consumer(in Key supported_interface,
- out CosNotifyChannelAdmin::ProxyID proxy_id)
- raises( CosTypedEventChannelAdmin::InterfaceNotSupported, CosNotifyChannelAdmin::AdminLimitExceeded);
- TypedProxyPullConsumer obtain_typed_notification_pull_consumer(in Key uses_interface,
- out CosNotifyChannelAdmin::ProxyID proxy_id )
- raises(CosTypedEventChannelAdmin::NoSuchImplementation, CosNotifyChannelAdmin::AdminLimitExceeded);
- }; // TypedSupplierAdmin
-
- interface TypedEventChannel : CosNotification::QoSAdmin, CosNotification::AdminPropertiesAdmin,
- CosTypedEventChannelAdmin::TypedEventChannel {
- readonly attribute TypedEventChannelFactory MyFactory;
- readonly attribute TypedConsumerAdmin default_consumer_admin;
- readonly attribute TypedSupplierAdmin default_supplier_admin;
- readonly attribute CosNotifyFilter::FilterFactory default_filter_factory;
-
- TypedConsumerAdmin new_for_typed_notification_consumers(in CosNotifyChannelAdmin::InterFilterGroupOperator op,
- out CosNotifyChannelAdmin::AdminID id);
-
- TypedSupplierAdmin new_for_typed_notification_suppliers(in CosNotifyChannelAdmin::InterFilterGroupOperator op,
- out CosNotifyChannelAdmin::AdminID id);
-
- TypedConsumerAdmin get_consumeradmin (in CosNotifyChannelAdmin::AdminID id )
- raises (CosNotifyChannelAdmin::AdminNotFound);
-
- TypedSupplierAdmin get_supplieradmin (in CosNotifyChannelAdmin::AdminID id)
- raises (CosNotifyChannelAdmin::AdminNotFound);
-
- CosNotifyChannelAdmin::AdminIDSeq get_all_consumeradmins();
-
- CosNotifyChannelAdmin::AdminIDSeq get_all_supplieradmins();
- }; // TypedEventChannel
-
- interface TypedEventChannelFactory {
- TypedEventChannel create_typed_channel (in CosNotification::QoSProperties initial_QoS,
- in CosNotification::AdminProperties initial_admin,
- out CosNotifyChannelAdmin::ChannelID id)
- raises( CosNotification::UnsupportedQoS, CosNotification::UnsupportedAdmin);
-
- CosNotifyChannelAdmin::ChannelIDSeq get_all_typed_channels();
-
- TypedEventChannel get_typed_event_channel (in CosNotifyChannelAdmin::ChannelID id)
- raises (CosNotifyChannelAdmin::ChannelNotFound);
- }; // TypedEventChannelFactory
-}; // CosTypedNotifyChannelAdmin
-
-#endif /* ifndef _COS_TYPED_NOTIFICATION_IDL_ */
diff --git a/lib/cosNotification/src/Makefile b/lib/cosNotification/src/Makefile
deleted file mode 100644
index 009c6be4a5..0000000000
--- a/lib/cosNotification/src/Makefile
+++ /dev/null
@@ -1,379 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-
-ifeq ($(TYPE),debug)
-ERL_COMPILE_FLAGS += -Ddebug -W
-endif
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(COSNOTIFICATION_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/cosNotification-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES = \
- CosNotification_Common \
- CosNotifyChannelAdmin_ConsumerAdmin_impl \
- CosNotifyChannelAdmin_EventChannelFactory_impl \
- CosNotifyChannelAdmin_EventChannel_impl \
- CosNotifyChannelAdmin_SupplierAdmin_impl \
- CosNotifyFilter_Filter_impl \
- CosNotifyFilter_MappingFilter_impl \
- CosNotifyFilter_FilterFactory_impl \
- PullerConsumer_impl \
- PullerSupplier_impl \
- PusherConsumer_impl \
- PusherSupplier_impl \
- cosNotificationApp \
- cosNotification_Scanner \
- cosNotification_Filter \
- cosNotification_eventDB
-
-ERL_FILES = $(MODULES:%=%.erl)
-HRL_FILES = \
- CosNotification_Definitions.hrl
-
-YECC_FILES = cosNotification_Grammar.yrl
-
-GEN_YECC_ERL_FILES = cosNotification_Grammar.erl
-
-GEN_YECC_HRL_FILES =
-
-GEN_NOTIFICATION_ERL_FILES = \
- oe_CosNotification.erl \
- CosNotification.erl \
- CosNotification_AdminPropertiesAdmin.erl \
- CosNotification_EventHeader.erl \
- CosNotification_EventType.erl \
- CosNotification_FixedEventHeader.erl \
- CosNotification_NamedPropertyRange.erl \
- CosNotification_Property.erl \
- CosNotification_PropertyError.erl \
- CosNotification_PropertyRange.erl \
- CosNotification_QoSAdmin.erl \
- CosNotification_StructuredEvent.erl \
- CosNotification_UnsupportedAdmin.erl \
- CosNotification_UnsupportedQoS.erl \
- CosNotification_EventBatch.erl \
- CosNotification_EventTypeSeq.erl \
- CosNotification_NamedPropertyRangeSeq.erl \
- CosNotification_PropertyErrorSeq.erl \
- CosNotification_PropertySeq.erl
-
-GEN_CHANNELADMIN_ERL_FILES = \
- oe_CosNotifyChannelAdmin.erl \
- CosNotifyChannelAdmin_AdminLimit.erl \
- CosNotifyChannelAdmin_AdminLimitExceeded.erl \
- CosNotifyChannelAdmin_AdminNotFound.erl \
- CosNotifyChannelAdmin_ChannelNotFound.erl \
- CosNotifyChannelAdmin_ConnectionAlreadyActive.erl \
- CosNotifyChannelAdmin_ConnectionAlreadyInactive.erl \
- CosNotifyChannelAdmin_ConsumerAdmin.erl \
- CosNotifyChannelAdmin_EventChannel.erl \
- CosNotifyChannelAdmin_EventChannelFactory.erl \
- CosNotifyChannelAdmin_NotConnected.erl \
- CosNotifyChannelAdmin_ProxyConsumer.erl \
- CosNotifyChannelAdmin_ProxyNotFound.erl \
- CosNotifyChannelAdmin_ProxyPullConsumer.erl \
- CosNotifyChannelAdmin_ProxyPullSupplier.erl \
- CosNotifyChannelAdmin_ProxyPushConsumer.erl \
- CosNotifyChannelAdmin_ProxyPushSupplier.erl \
- CosNotifyChannelAdmin_ProxySupplier.erl \
- CosNotifyChannelAdmin_SequenceProxyPullConsumer.erl \
- CosNotifyChannelAdmin_SequenceProxyPullSupplier.erl \
- CosNotifyChannelAdmin_SequenceProxyPushConsumer.erl \
- CosNotifyChannelAdmin_SequenceProxyPushSupplier.erl \
- CosNotifyChannelAdmin_StructuredProxyPullConsumer.erl \
- CosNotifyChannelAdmin_StructuredProxyPullSupplier.erl \
- CosNotifyChannelAdmin_StructuredProxyPushConsumer.erl \
- CosNotifyChannelAdmin_StructuredProxyPushSupplier.erl \
- CosNotifyChannelAdmin_SupplierAdmin.erl \
- CosNotifyChannelAdmin_AdminIDSeq.erl \
- CosNotifyChannelAdmin_ChannelIDSeq.erl \
- CosNotifyChannelAdmin_ProxyIDSeq.erl
-
-GEN_NOTIFYFILTER_ERL_FILES = \
- oe_CosNotifyFilter.erl \
- CosNotifyFilter_CallbackNotFound.erl \
- CosNotifyFilter_ConstraintExp.erl \
- CosNotifyFilter_ConstraintInfo.erl \
- CosNotifyFilter_ConstraintNotFound.erl \
- CosNotifyFilter_DuplicateConstraintID.erl \
- CosNotifyFilter_Filter.erl \
- CosNotifyFilter_FilterAdmin.erl \
- CosNotifyFilter_FilterFactory.erl \
- CosNotifyFilter_FilterNotFound.erl \
- CosNotifyFilter_InvalidConstraint.erl \
- CosNotifyFilter_InvalidGrammar.erl \
- CosNotifyFilter_InvalidValue.erl \
- CosNotifyFilter_MappingConstraintInfo.erl \
- CosNotifyFilter_MappingConstraintPair.erl \
- CosNotifyFilter_MappingFilter.erl \
- CosNotifyFilter_UnsupportedFilterableData.erl \
- CosNotifyFilter_CallbackIDSeq.erl \
- CosNotifyFilter_ConstraintExpSeq.erl \
- CosNotifyFilter_ConstraintIDSeq.erl \
- CosNotifyFilter_ConstraintInfoSeq.erl \
- CosNotifyFilter_FilterIDSeq.erl \
- CosNotifyFilter_MappingConstraintInfoSeq.erl \
- CosNotifyFilter_MappingConstraintPairSeq.erl
-
-GEN_NOTIFYCOMM_ERL_FILES = \
- oe_CosNotifyComm.erl \
- CosNotifyComm_InvalidEventType.erl \
- CosNotifyComm_NotifyPublish.erl \
- CosNotifyComm_NotifySubscribe.erl \
- CosNotifyComm_PullConsumer.erl \
- CosNotifyComm_PullSupplier.erl \
- CosNotifyComm_PushConsumer.erl \
- CosNotifyComm_PushSupplier.erl \
- CosNotifyComm_SequencePullConsumer.erl \
- CosNotifyComm_SequencePullSupplier.erl \
- CosNotifyComm_SequencePushConsumer.erl \
- CosNotifyComm_SequencePushSupplier.erl \
- CosNotifyComm_StructuredPullConsumer.erl \
- CosNotifyComm_StructuredPullSupplier.erl \
- CosNotifyComm_StructuredPushConsumer.erl \
- CosNotifyComm_StructuredPushSupplier.erl \
-
-GEN_OE_EVENTCOMM_ERL_FILES = \
- oe_cosNotificationAppComm.erl \
- oe_CosNotificationComm_Event.erl
-
-EXTERNAL_INC_PATH = ../include
-
-GEN_NOTIFICATION_HRL_FILES = \
- oe_CosNotification.hrl \
- CosNotification.hrl \
- CosNotification_AdminPropertiesAdmin.hrl \
- CosNotification_QoSAdmin.hrl \
-
-EXTERNAL_GEN_NOTIFICATION_HRL_FILES = \
- $(GEN_NOTIFICATION_HRL_FILES:%=$(EXTERNAL_INC_PATH)/%)
-
-GEN_CHANNELADMIN_HRL_FILES = \
- oe_CosNotifyChannelAdmin.hrl \
- CosNotifyChannelAdmin.hrl \
- CosNotifyChannelAdmin_ConsumerAdmin.hrl \
- CosNotifyChannelAdmin_EventChannel.hrl \
- CosNotifyChannelAdmin_EventChannelFactory.hrl \
- CosNotifyChannelAdmin_ProxyConsumer.hrl \
- CosNotifyChannelAdmin_ProxyPullConsumer.hrl \
- CosNotifyChannelAdmin_ProxyPullSupplier.hrl \
- CosNotifyChannelAdmin_ProxyPushConsumer.hrl \
- CosNotifyChannelAdmin_ProxyPushSupplier.hrl \
- CosNotifyChannelAdmin_ProxySupplier.hrl \
- CosNotifyChannelAdmin_SequenceProxyPullConsumer.hrl \
- CosNotifyChannelAdmin_SequenceProxyPullSupplier.hrl \
- CosNotifyChannelAdmin_SequenceProxyPushConsumer.hrl \
- CosNotifyChannelAdmin_SequenceProxyPushSupplier.hrl \
- CosNotifyChannelAdmin_StructuredProxyPullConsumer.hrl \
- CosNotifyChannelAdmin_StructuredProxyPullSupplier.hrl \
- CosNotifyChannelAdmin_StructuredProxyPushConsumer.hrl \
- CosNotifyChannelAdmin_StructuredProxyPushSupplier.hrl \
- CosNotifyChannelAdmin_SupplierAdmin.hrl \
-
-EXTERNAL_GEN_CHANNELADMIN_HRL_FILES = \
- $(GEN_CHANNELADMIN_HRL_FILES:%=$(EXTERNAL_INC_PATH)/%)
-
-GEN_NOTIFYFILTER_HRL_FILES = \
- oe_CosNotifyFilter.hrl \
- CosNotifyFilter.hrl \
- CosNotifyFilter_Filter.hrl \
- CosNotifyFilter_FilterAdmin.hrl \
- CosNotifyFilter_FilterFactory.hrl \
- CosNotifyFilter_MappingFilter.hrl
-
-EXTERNAL_GEN_NOTIFYFILTER_HRL_FILES = \
- $(GEN_NOTIFYFILTER_HRL_FILES:%=$(EXTERNAL_INC_PATH)/%)
-
-GEN_NOTIFYCOMM_HRL_FILES = \
- oe_CosNotifyComm.hrl \
- CosNotifyComm.hrl \
- CosNotifyComm_NotifyPublish.hrl \
- CosNotifyComm_NotifySubscribe.hrl \
- CosNotifyComm_PullConsumer.hrl \
- CosNotifyComm_PullSupplier.hrl \
- CosNotifyComm_PushConsumer.hrl \
- CosNotifyComm_PushSupplier.hrl \
- CosNotifyComm_SequencePullConsumer.hrl \
- CosNotifyComm_SequencePullSupplier.hrl \
- CosNotifyComm_SequencePushConsumer.hrl \
- CosNotifyComm_SequencePushSupplier.hrl \
- CosNotifyComm_StructuredPullConsumer.hrl \
- CosNotifyComm_StructuredPullSupplier.hrl \
- CosNotifyComm_StructuredPushConsumer.hrl \
- CosNotifyComm_StructuredPushSupplier.hrl \
-
-EXTERNAL_GEN_NOTIFYCOMM_HRL_FILES = \
- $(GEN_NOTIFYCOMM_HRL_FILES:%=$(EXTERNAL_INC_PATH)/%)
-
-GEN_OE_EVENTCOMM_HRL_FILES = \
- oe_cosNotificationAppComm.hrl \
- oe_CosNotificationComm.hrl \
- oe_CosNotificationComm_Event.hrl
-
-IDL_GEN_ERL_FILES = \
- $(GEN_NOTIFICATION_ERL_FILES) \
- $(GEN_OE_EVENTCOMM_ERL_FILES) \
- $(GEN_NOTIFYCOMM_ERL_FILES) \
- $(GEN_NOTIFYFILTER_ERL_FILES) \
- $(GEN_CHANNELADMIN_ERL_FILES)
-
-IDL_GEN_HRL_FILES = \
- $(EXTERNAL_GEN_NOTIFICATION_HRL_FILES) \
- $(GEN_OE_EVENTCOMM_HRL_FILES) \
- $(EXTERNAL_GEN_NOTIFYCOMM_HRL_FILES) \
- $(EXTERNAL_GEN_NOTIFYFILTER_HRL_FILES) \
- $(EXTERNAL_GEN_CHANNELADMIN_HRL_FILES)
-
-GEN_ERL_FILES = \
- $(IDL_GEN_ERL_FILES) \
- $(GEN_YECC_ERL_FILES)
-
-GEN_HRL_FILES = \
- $(IDL_GEN_HRL_FILES) \
- $(GEN_YECC_HRL_FILES)
-
-
-GEN_FILES = \
- $(GEN_HRL_FILES) \
- $(GEN_ERL_FILES)
-
-TARGET_FILES = \
- $(GEN_ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR)) \
- $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-IDL_FILES = \
- CosNotification.idl \
- CosNotifyChannelAdmin.idl \
- CosNotifyFilter.idl \
- CosNotifyComm.idl \
- cosNotificationAppComm.idl
-
-APPUP_FILE = cosNotification.appup
-APPUP_SRC = $(APPUP_FILE).src
-APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
-
-APP_FILE = cosNotification.app
-APP_SRC = $(APP_FILE).src
-APP_TARGET = $(EBIN)/$(APP_FILE)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/cosNotification/ebin \
- -pa $(ERL_TOP)/lib/ic/ebin\
- -pa $(ERL_TOP)/lib/orber/ebin \
- -pa $(ERL_TOP)/lib/cosEvent/ebin \
- -pa $(ERL_TOP)/lib/cosTime/ebin \
- -I$(ERL_TOP)/lib/cosEvent/src
-
-# The -pa option is just used temporary until erlc can handle
-# includes from other directories than ../include .
-ERL_COMPILE_FLAGS += \
- $(ERL_IDL_FLAGS) \
- -pa $(ERL_TOP)/lib/orber/include \
- -pa $(ERL_TOP)/lib/cosNotification/include \
- -pa $(ERL_TOP)/lib/cosEvent/include \
- -pa $(ERL_TOP)/lib/cosTime/include \
- -I$(ERL_TOP)/lib/orber/include \
- -I$(ERL_TOP)/lib/cosNotification/include \
- -I$(ERL_TOP)/lib/cosEvent/include \
- -I$(ERL_TOP)/lib/cosTime/include \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,app_vsn,"cosNotification_$(COSNOTIFICATION_VSN)"}'
-
-YECC_COMPILE_FLAGS =
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
-
-debug:
- @${MAKE} TYPE=debug
-
-cleanb:
- rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
- rm -f errs core *~
-
-clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
- rm -f errs core *~
-
-$(APP_TARGET): $(APP_SRC)
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
-
-$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
-
-docs:
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-IDL-GENERATED: CosNotification.idl CosNotifyChannelAdmin.idl \
- CosNotifyFilter.idl cosNotificationAppComm.idl CosNotifyComm.idl
- $(gen_verbose)erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosNotification.cfg"}' CosNotification.idl
- $(V_at)mv $(GEN_NOTIFICATION_HRL_FILES) $(EXTERNAL_INC_PATH)
- $(V_at)erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosNotifyChannelAdmin.cfg"}' CosNotifyChannelAdmin.idl
- $(V_at)mv $(GEN_CHANNELADMIN_HRL_FILES) $(EXTERNAL_INC_PATH)
- $(V_at)erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosNotifyFilter.cfg"}' CosNotifyFilter.idl
- $(V_at)mv $(GEN_NOTIFYFILTER_HRL_FILES) $(EXTERNAL_INC_PATH)
- $(V_at)erlc $(ERL_IDL_FLAGS) +'{cfgfile,"cosNotificationComm.cfg"}' cosNotificationAppComm.idl
- $(V_at)erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosNotifyComm.cfg"}' CosNotifyComm.idl
- $(V_at)mv $(GEN_NOTIFYCOMM_HRL_FILES) $(EXTERNAL_INC_PATH)
- $(V_at)>IDL-GENERATED
-
-$(IDL_GEN_ERL_FILES) $(IDL_GEN_HRL_FILES): IDL-GENERATED
-
-$(TARGET_FILES): IDL-GENERATED
-
-$(GEN_YECC_ERL_FILES) $(GEN_YECC_HRL_FILES): cosNotification_Grammar.yrl
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
- $(INSTALL_DIR) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(GEN_FILES) $(IDL_FILES) $(YECC_FILES) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(IDL_FILES) $(YECC_FILES) "$(RELSYSDIR)/src"
- $(INSTALL_DIR) "$(RELSYSDIR)/include"
- $(INSTALL_DATA) $(GEN_HRL_FILES) "$(RELSYSDIR)/include"
-
-release_docs_spec:
diff --git a/lib/cosNotification/src/PullerConsumer_impl.erl b/lib/cosNotification/src/PullerConsumer_impl.erl
deleted file mode 100644
index 52bd13918f..0000000000
--- a/lib/cosNotification/src/PullerConsumer_impl.erl
+++ /dev/null
@@ -1,774 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : PullerConsumer_impl.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module('PullerConsumer_impl').
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-%% cosEvent files.
--include_lib("cosEvent/include/CosEventChannelAdmin.hrl").
--include_lib("cosEvent/include/CosEventComm.hrl").
-%% Application files
--include("CosNotification.hrl").
--include("CosNotifyChannelAdmin.hrl").
--include("CosNotifyComm.hrl").
--include("CosNotifyFilter.hrl").
--include("CosNotification_Definitions.hrl").
-
-%%--------------- EXPORTS ------------------------------------
-%%--------------- External -----------------------------------
-%%----- CosNotifyChannelAdmin::ProxyPullConsumer -------------
--export([connect_any_pull_supplier/4]).
-
-%%----- CosNotifyChannelAdmin::SequenceProxyPullConsumer -----
--export([connect_sequence_pull_supplier/4]).
-
-%%----- CosNotifyChannelAdmin::StructuredProxyPullConsumer ---
--export([connect_structured_pull_supplier/4]).
-
-%%----- CosNotifyChannelAdmin::*ProxyPullConsumer ------------
--export([suspend_connection/3,
- resume_connection/3]).
-
-%%----- Inherit from CosNotifyChannelAdmin::ProxyConsumer ----
--export([obtain_subscription_types/4,
- validate_event_qos/4]).
-
-%%----- Inherit from CosNotification::QoSAdmin ---------------
--export([get_qos/3,
- set_qos/4,
- validate_qos/4]).
-
-%%----- Inherit from CosNotifyComm::NotifyPublish ------------
--export([offer_change/5]).
-
-%%----- Inherit from CosNotifyFilter::FilterAdmin ------------
--export([add_filter/4,
- remove_filter/4,
- get_filter/4,
- get_all_filters/3,
- remove_all_filters/3]).
-
-%%----- Inherit from CosEventComm::PullConsumer -------------
--export([disconnect_pull_consumer/3]).
-
-%%----- Inherit from CosNotifyComm::SequencePullConsumer ----
--export([disconnect_sequence_pull_consumer/3]).
-
-%%----- Inherit from CosNotifyComm::StructuredPullConsumer --
--export([disconnect_structured_pull_consumer/3]).
-
-%%----- Inherit from CosEventChannelAdmin::ProxyPullConsumer
--export([connect_pull_supplier/4]).
-
-
-%% Attributes (external) CosNotifyChannelAdmin::ProxySupplier
--export(['_get_MyType'/3,
- '_get_MyAdmin'/3]).
-
-%%--------------- gen_server specific exports ----------------
--export([handle_info/2, code_change/3]).
--export([init/1, terminate/2]).
-
-%%--------------- LOCAL DEFINITIONS --------------------------
-%% Data structures
--record(state, {myType,
- myAdmin,
- myAdminPid,
- myChannel,
- myFilters = [],
- myOperator,
- idCounter = 0,
- client,
- qosGlobal,
- qosLocal,
- suspended = false,
- pullTimer,
- pullInterval,
- publishType = false,
- etsR,
- eventCounter = 0,
- eventDB,
- this}).
-
-%% Data structures constructors
--define(get_InitState(_MyT, _MyA, _MyAP, _QS, _LQS, _Ch, _PI, _MyOP, _GT, _GL, _TR),
- #state{myType = _MyT,
- myAdmin = _MyA,
- myAdminPid = _MyAP,
- myChannel = _Ch,
- myOperator = _MyOP,
- qosGlobal = _QS,
- qosLocal = _LQS,
- pullInterval = _PI,
- etsR = ets:new(oe_ets, [set, protected]),
- eventDB = cosNotification_eventDB:create_db(_LQS, _GT, _GL, _TR)}).
-
-%%-------------- Data structures selectors -----------------
-%% Attributes
--define(get_MyType(S), S#state.myType).
--define(get_MyAdmin(S), S#state.myAdmin).
--define(get_MyAdminPid(S), S#state.myAdminPid).
--define(get_MyChannel(S), S#state.myChannel).
--define(get_MyOperator(S), S#state.myOperator).
-%% Client Object
--define(get_Client(S), S#state.client).
-%% QoS
--define(get_GlobalQoS(S), S#state.qosGlobal).
--define(get_LocalQoS(S), S#state.qosLocal).
--define(get_BothQoS(S), {S#state.qosGlobal, S#state.qosLocal}).
-%% Filters
--define(get_Filter(S, I), find_obj(lists:keysearch(I, 1, S#state.myFilters))).
--define(get_AllFilter(S), S#state.myFilters).
--define(get_AllFilterID(S), find_ids(S#state.myFilters)).
-%% Admin
--define(get_PullInterval(S), S#state.pullInterval).
--define(get_PullTimer(S), S#state.pullTimer).
--define(get_PacingInterval(S), round(?not_GetPacingInterval((S#state.qosLocal))/10000000)).
--define(get_BatchLimit(S), ?not_GetMaximumBatchSize((S#state.qosLocal))).
-%% Publish
--define(get_AllPublish(S), lists:flatten(ets:match(S#state.etsR,
- {'$1',publish}))).
--define(get_PublishType(S), S#state.publishType).
-%% ID
--define(get_IdCounter(S), S#state.idCounter).
-%% Event
--define(get_Event(S), cosNotification_eventDB:get_event(S#state.eventDB)).
--define(get_Events(S,M), cosNotification_eventDB:get_events(S#state.eventDB, M)).
--define(get_EventCounter(S), S#state.eventCounter).
-
-%%-------------- Data structures modifiers -----------------
-%% Client Object
--define(set_Client(S,D), S#state{client=D}).
--define(del_Client(S), S#state{client=undefined}).
--define(set_Suspended(S), S#state{client=true}).
--define(set_NotSuspended(S), S#state{client=false}).
--define(set_Unconnected(S), S#state{client=undefined}).
-%% QoS
--define(set_LocalQoS(S,D), S#state{qosLocal=D}).
--define(set_GlobalQoS(S,D), S#state{qosGlobal=D}).
--define(set_BothQoS(S,GD,LD), S#state{qosGlobal=GD, qosLocal=LD}).
-%% Filters
--define(add_Filter(S,I,O), S#state{myFilters=[{I,O}|S#state.myFilters]}).
--define(del_Filter(S,I), S#state{myFilters=
- delete_obj(lists:keydelete(I, 1, S#state.myFilters),
- S#state.myFilters)}).
--define(del_AllFilter(S), S#state{myFilters=[]}).
-%% Admin
--define(set_PullInterval(S,V), S#state{pullInterval=V}).
--define(set_PullTimer(S,T), S#state{pullTimer=T}).
-%% Publish
--define(add_Publish(S,E), ets:insert(S#state.etsR, {E, publish})).
--define(del_Publish(S,E), ets:delete(S#state.etsR, E)).
--define(set_PublishType(S,T), S#state{publishType=T}).
-%% ID
--define(set_IdCounter(S,V), S#state{idCounter=V}).
--define(new_Id(S), 'CosNotification_Common':create_id(S#state.idCounter)).
-%% Event
--define(add_Event(S,E), cosNotification_eventDB:add_event(S#state.eventDB, E)).
--define(update_EventDB(S,Q), S#state{eventDB=
- cosNotification_eventDB:update(S#state.eventDB, Q)}).
-
--define(set_EventCounter(S,V), S#state{eventCounter=V}).
--define(add_to_EventCounter(S,V),S#state{eventCounter=S#state.eventCounter+V}).
--define(reset_EventCounter(S), S#state{eventCounter=0}).
--define(increase_EventCounter(S),S#state{eventCounter=(S#state.eventCounter+1)}).
--define(decrease_EventCounter(S),S#state{eventCounter=S#state.eventCounter-1}).
--define(add_ToEventCounter(S,A), S#state{eventCounter=(S#state.eventCounter+A)}).
--define(sub_FromEventCounter(S,_A), S#state{eventCounter=(S#state.eventCounter-_A)}).
--define(set_EventCounterTo(S,V), S#state{eventCounter=V}).
-
-%%-------------- MISC ----------------------------------------
--define(is_ANY(S), S#state.myType == 'PULL_ANY').
--define(is_STRUCTURED(S), S#state.myType == 'PULL_STRUCTURED').
--define(is_SEQUENCE(S), S#state.myType == 'PULL_SEQUENCE').
--define(is_ANDOP(S), S#state.myOperator == 'AND_OP').
--define(is_UnConnected(S), S#state.client == undefined).
--define(is_Connected(S), S#state.client =/= undefined).
--define(is_Suspended(S), S#state.suspended == true).
--define(is_NotSuspended(S), S#state.suspended == false).
--define(is_PersistentConnection(S),
- ?not_GetConnectionReliability((S#state.qosLocal)) == ?not_Persistent).
--define(is_PersistentEvent(S),
- ?not_GetEventReliability((S#state.qosLocal)) == ?not_Persistent).
-
-%%-----------------------------------------------------------%
-%% function : handle_info, code_change
-%% Arguments:
-%% Returns :
-%% Effect : Functions demanded by the gen_server module.
-%%------------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-handle_info(Info, State) ->
- ?DBG("INFO: ~p~n", [Info]),
- case Info of
- {'EXIT', Pid, Reason} when ?get_MyAdminPid(State) == Pid->
- ?DBG("PARENT ADMIN: ~p TERMINATED.~n",[Reason]),
- {stop, Reason, State};
- {'EXIT', _Pid, _Reason} ->
- ?DBG("PROXYPUSHSUPPLIER: ~p TERMINATED.~n",[_Reason]),
- {noreply, State};
- pull ->
- try_pull_events(State);
- _ ->
- {noreply, State}
- end.
-
-%%----------------------------------------------------------%
-%% function : init, terminate
-%% Arguments:
-%%-----------------------------------------------------------
-
-init([MyType, MyAdmin, MyAdminPid, InitQoS, LQS, MyChannel, Options, Operator]) ->
- process_flag(trap_exit, true),
- Secs = timer:seconds('CosNotification_Common':get_option(pullInterval,
- Options,
- ?not_DEFAULT_SETTINGS)),
- GCTime = 'CosNotification_Common':get_option(gcTime, Options,
- ?not_DEFAULT_SETTINGS),
- GCLimit = 'CosNotification_Common':get_option(gcLimit, Options,
- ?not_DEFAULT_SETTINGS),
- TimeRef = 'CosNotification_Common':get_option(timeService, Options,
- ?not_DEFAULT_SETTINGS),
- timer:start(),
- {ok, ?get_InitState(MyType, MyAdmin, MyAdminPid, InitQoS,
- LQS, MyChannel, Secs, Operator, GCTime,
- GCLimit, TimeRef)}.
-
-terminate(_Reason, State) when ?is_UnConnected(State) ->
- %% We are currently not connected to a client. Hence, no need for sending
- %% a disconnect request.
- stop_timer(State),
- ok;
-terminate(_Reason, State) when ?is_ANY(State) ->
- stop_timer(State),
- 'CosNotification_Common':disconnect('CosEventComm_PullSupplier',
- disconnect_pull_supplier,
- ?get_Client(State));
-terminate(_Reason, State) when ?is_SEQUENCE(State) ->
- stop_timer(State),
- 'CosNotification_Common':disconnect('CosNotifyComm_SequencePullSupplier',
- disconnect_sequence_pull_supplier,
- ?get_Client(State));
-terminate(_Reason, State) when ?is_STRUCTURED(State) ->
- stop_timer(State),
- 'CosNotification_Common':disconnect('CosNotifyComm_StructuredPullSupplier',
- disconnect_structured_pull_supplier,
- ?get_Client(State)).
-
-%%-----------------------------------------------------------
-%%----- CosNotifyChannelAdmin_ProxyConsumer attributes ------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% Attribute: '_get_MyType'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_MyType'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_MyType(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_MyAdmin'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_MyAdmin'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_MyAdmin(State), State}.
-
-%%-----------------------------------------------------------
-%%------- Exported external functions -----------------------
-%%-----------------------------------------------------------
-%%----- CosEventChannelAdmin::ProxyPullConsumer -------------
-%%----------------------------------------------------------%
-%% function : connect_pull_supplier
-%% Arguments: Client - CosEventComm::PullSupplier
-%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
-%% {'EXCEPTION', #'TypeError'{}} |
-%% {'EXCEPTION', #'BAD_OPERATION'{}}
-%% Both exceptions from CosEventChannelAdmin!!!
-%%-----------------------------------------------------------
-connect_pull_supplier(OE_THIS, OE_FROM, State, Client) ->
- connect_any_pull_supplier(OE_THIS, OE_FROM, State, Client).
-
-%%----- CosNotifyChannelAdmin::ProxyPullConsumer ------------
-%%----------------------------------------------------------%
-%% function : connect_any_pull_supplier
-%% Arguments: Client - CosEventComm::PullSupplier
-%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
-%% {'EXCEPTION', #'TypeError'{}} |
-%% {'EXCEPTION', #'BAD_OPERATION'{}}
-%% Both exceptions from CosEventChannelAdmin!!!
-%%-----------------------------------------------------------
-connect_any_pull_supplier(OE_THIS, _OE_FROM, State, Client) when ?is_ANY(State) ->
- 'CosNotification_Common':type_check(Client, 'CosEventComm_PullSupplier'),
- if
- ?is_Connected(State) ->
- corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
- true ->
- NewState = start_timer(State),
- {reply, ok, NewState#state{client = Client, this = OE_THIS}}
- end;
-connect_any_pull_supplier(_, _, _,_) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----- CosNotifyChannelAdmin::SequenceProxyPullConsumer ----
-%%----------------------------------------------------------%
-%% function : connect_sequence_pull_supplier
-%% Arguments: Client - CosNotifyComm::SequencePullSupplier
-%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
-%% {'EXCEPTION', #'TypeError'{}} |
-%% {'EXCEPTION', #'BAD_OPERATION'{}}
-%%-----------------------------------------------------------
-connect_sequence_pull_supplier(OE_THIS, _OE_FROM, State, Client) when ?is_SEQUENCE(State) ->
- 'CosNotification_Common':type_check(Client, 'CosNotifyComm_SequencePullSupplier'),
- if
- ?is_Connected(State) ->
- corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
- true ->
- NewState = start_timer(State),
- {reply, ok, NewState#state{client = Client, this = OE_THIS}}
- end;
-connect_sequence_pull_supplier(_, _, _, _) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----- CosNotifyChannelAdmin::StructuredProxyPullConsumer --
-%%----------------------------------------------------------%
-%% function : connect_structured_pull_supplier
-%% Arguments: Client - CosNotifyComm::StructuredPullSupplier
-%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
-%% {'EXCEPTION', #'TypeError'{}} |
-%% {'EXCEPTION', #'BAD_OPERATION'{}}
-%%-----------------------------------------------------------
-connect_structured_pull_supplier(OE_THIS, _OE_FROM, State, Client) when ?is_STRUCTURED(State) ->
- 'CosNotification_Common':type_check(Client, 'CosNotifyComm_StructuredPullSupplier'),
- if
- ?is_Connected(State) ->
- corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
- true ->
- NewState = start_timer(State),
- {reply, ok, NewState#state{client = Client, this = OE_THIS}}
- end;
-connect_structured_pull_supplier(_, _, _, _) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----- CosNotifyChannelAdmin::*ProxyPullConsumer -----------
-%%----------------------------------------------------------%
-%% function : suspend_connection
-%% Arguments:
-%% Returns : ok | {'EXCEPTION', #'ConnectionAlreadyInactive'{}} |
-%% {'EXCEPTION', #'NotConneced'{}}
-%%-----------------------------------------------------------
-suspend_connection(_OE_THIS, _OE_FROM, State) when ?is_Connected(State) ->
- if
- ?is_Suspended(State) ->
- corba:raise(#'CosNotifyChannelAdmin_ConnectionAlreadyInactive'{});
- true ->
- stop_timer(State),
- {reply, ok, ?set_Suspended(State)}
- end;
-suspend_connection(_, _, _) ->
- corba:raise(#'CosNotifyChannelAdmin_NotConnected'{}).
-
-%%----------------------------------------------------------%
-%% function : resume_connection
-%% Arguments:
-%% Returns : ok | {'EXCEPTION', #'ConnectionAlreadyActive'{}} |
-%% {'EXCEPTION', #'NotConneced'{}}
-%%-----------------------------------------------------------
-resume_connection(_OE_THIS, _OE_FROM, State) when ?is_Connected(State) ->
- if
- ?is_NotSuspended(State) ->
- corba:raise(#'CosNotifyChannelAdmin_ConnectionAlreadyActive'{});
- true ->
- NewState = start_timer(State),
- {reply, ok, ?set_NotSuspended(NewState)}
- end;
-resume_connection(_, _, _) ->
- corba:raise(#'CosNotifyChannelAdmin_NotConnected'{}).
-
-%%----- Inherit from CosNotifyChannelAdmin::ProxyConsumer ---
-%%----------------------------------------------------------%
-%% function : obtain_subscription_types
-%% Arguments: Mode - enum 'ObtainInfoMode' (CosNotifyChannelAdmin)
-%% Returns : CosNotification::EventTypeSeq
-%%-----------------------------------------------------------
-obtain_subscription_types(_OE_THIS, _OE_FROM, State, 'ALL_NOW_UPDATES_OFF') ->
- {reply, ?get_AllPublish(State), ?set_PublishType(State, false)};
-obtain_subscription_types(_OE_THIS, _OE_FROM, State, 'ALL_NOW_UPDATES_ON') ->
- {reply, ?get_AllPublish(State), ?set_PublishType(State, true)};
-obtain_subscription_types(_OE_THIS, _OE_FROM, State, 'NONE_NOW_UPDATES_OFF') ->
- {reply, [], ?set_PublishType(State, false)};
-obtain_subscription_types(_OE_THIS, _OE_FROM, State, 'NONE_NOW_UPDATES_ON') ->
- {reply, [], ?set_PublishType(State, true)};
-obtain_subscription_types(_,_,_,What) ->
- orber:dbg("[~p] PullerConsumer:obtain_subscription_types(~p);~n"
- "Incorrect enumerant", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : validate_event_qos
-%% Arguments: RequiredQoS - CosNotification::QoSProperties
-%% Returns : ok | {'EXCEPTION', #'UnsupportedQoS'{}}
-%% AvilableQoS - CosNotification::NamedPropertyRangeSeq (out)
-%%-----------------------------------------------------------
-validate_event_qos(_OE_THIS, _OE_FROM, State, RequiredQoS) ->
- AvilableQoS = 'CosNotification_Common':validate_event_qos(RequiredQoS,
- ?get_LocalQoS(State)),
- {reply, {ok, AvilableQoS}, State}.
-
-%%----- Inherit from CosNotification::QoSAdmin --------------
-%%----------------------------------------------------------%
-%% function : get_qos
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-get_qos(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_GlobalQoS(State), State}.
-
-%%----------------------------------------------------------%
-%% function : set_qos
-%% Arguments: QoS - CosNotification::QoSProperties, i.e.,
-%% [#'Property'{name, value}, ...] where name eq. string()
-%% and value eq. any().
-%% Returns : ok | {'EXCEPTION', CosNotification::UnsupportedQoS}
-%%-----------------------------------------------------------
-set_qos(_OE_THIS, _OE_FROM, State, QoS) ->
- {NewQoS, LQS} = 'CosNotification_Common':set_qos(QoS, ?get_BothQoS(State),
- proxy, ?get_MyAdmin(State),
- false),
- NewState = ?update_EventDB(State, LQS),
- {reply, ok, ?set_BothQoS(NewState, NewQoS, LQS)}.
-
-%%----------------------------------------------------------%
-%% function : validate_qos
-%% Arguments: Required_qos - CosNotification::QoSProperties
-%% [#'Property'{name, value}, ...] where name eq. string()
-%% and value eq. any().
-%% Returns : {'EXCEPTION', CosNotification::UnsupportedQoS}
-%% {ok, CosNotification::NamedPropertyRangeSeq}
-%%-----------------------------------------------------------
-validate_qos(_OE_THIS, _OE_FROM, State, Required_qos) ->
- QoS = 'CosNotification_Common':validate_qos(Required_qos, ?get_BothQoS(State),
- proxy, ?get_MyAdmin(State),
- false),
- {reply, {ok, QoS}, State}.
-
-%%----- Inherit from CosNotifyComm::NotifyPublish -----------
-%%----------------------------------------------------------%
-%% function : offer_change
-%% Arguments: Added - #'CosNotification_EventType'{}
-%% Removed - #'CosNotification_EventType'{}
-%% Returns : ok |
-%% {'EXCEPTION', #'CosNotifyComm_InvalidEventType'{}}
-%%-----------------------------------------------------------
-offer_change(_OE_THIS, _OE_FROM, State, Added, Removed) ->
- cosNotification_Filter:validate_types(Added),
- cosNotification_Filter:validate_types(Removed),
- %% On this "side" we don't really care about which
- %% type of events the client will supply.
- %% Perhaps, later on, if we want to check this against Filters
- %% associated with this object we may change this approach, i.e., if
- %% the filter will not allow passing certain event types. But the
- %% user should see to that that situation never occurs. It would add
- %% extra overhead. Also see PusherSupplier- and PullerSuppler-
- %% 'subscription_change'.
- update_publish(add, State, Added),
- update_publish(remove, State, Removed),
- case ?get_PublishType(State) of
- true ->
- %% Perhaps we should handle exception here?!
- %% Probably not. Better to stay "on-line".
- catch 'CosNotifyComm_NotifySubscribe':
- subscription_change(?get_Client(State), Added, Removed),
- ok;
- _->
- ok
- end,
- {reply, ok, State}.
-
-update_publish(_, _, [])->
- ok;
-update_publish(add, State, [H|T]) ->
- ?add_Publish(State, H),
- update_publish(add, State, T);
-update_publish(remove, State, [H|T]) ->
- ?del_Publish(State, H),
- update_publish(remove, State, T).
-
-%%----- Inherit from CosNotifyFilter::FilterAdmin -----------
-%%----------------------------------------------------------%
-%% function : add_filter
-%% Arguments: Filter - CosNotifyFilter::Filter
-%% Returns : FilterID - long
-%%-----------------------------------------------------------
-add_filter(_OE_THIS, _OE_FROM, State, Filter) ->
- 'CosNotification_Common':type_check(Filter, 'CosNotifyFilter_Filter'),
- FilterID = ?new_Id(State),
- NewState = ?set_IdCounter(State, FilterID),
- {reply, FilterID, ?add_Filter(NewState, FilterID, Filter)}.
-
-%%----------------------------------------------------------%
-%% function : remove_filter
-%% Arguments: FilterID - long
-%% Returns : ok
-%%-----------------------------------------------------------
-remove_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
- {reply, ok, ?del_Filter(State, FilterID)};
-remove_filter(_,_,_,What) ->
- orber:dbg("[~p] PullerConsumer:remove_filter(~p); Not an integer",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : get_filter
-%% Arguments: FilterID - long
-%% Returns : Filter - CosNotifyFilter::Filter |
-%% {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}
-%%-----------------------------------------------------------
-get_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
- {reply, ?get_Filter(State, FilterID), State};
-get_filter(_,_,_,What) ->
- orber:dbg("[~p] PullerConsumer:get_filter(~p); Not an integer",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : get_all_filters
-%% Arguments: -
-%% Returns : Filter - CosNotifyFilter::FilterIDSeq
-%%-----------------------------------------------------------
-get_all_filters(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_AllFilterID(State), State}.
-
-%%----------------------------------------------------------%
-%% function : remove_all_filters
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-remove_all_filters(_OE_THIS, _OE_FROM, State) ->
- {reply, ok, ?del_AllFilter(State)}.
-
-%%----- Inherit from CosEventComm::PullConsumer -------------
-%%----------------------------------------------------------%
-%% function : disconnect_pull_consumer
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-disconnect_pull_consumer(_OE_THIS, _OE_FROM, State) ->
- {stop, normal, ok, ?set_Unconnected(State)}.
-
-%%----- Inherit from CosNotifyComm::SequencePullConsumer ----
-%%----------------------------------------------------------%
-%% function : disconnect_sequence_pull_consumer
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-disconnect_sequence_pull_consumer(_OE_THIS, _OE_FROM, State) ->
- {stop, normal, ok, ?set_Unconnected(State)}.
-
-%%----- Inherit from CosNotifyComm::StructuredPullConsumer ----
-%%----------------------------------------------------------%
-%% function : disconnect_structured_pull_consumer
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-disconnect_structured_pull_consumer(_OE_THIS, _OE_FROM, State) ->
- {stop, normal, ok, ?set_Unconnected(State)}.
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-find_obj({value, {_, Obj}}) -> Obj;
-find_obj(_) -> {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}.
-
-find_ids(List) -> find_ids(List, []).
-find_ids([], Acc) -> Acc;
-find_ids([{I,_}|T], Acc) -> find_ids(T, [I|Acc]);
-find_ids(What, _) ->
- orber:dbg("[~p] PullerConsumer:find_ids();~n"
- "Id corrupt: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
-
-%% Delete a single object.
-%% The list don not differ, i.e., no filter removed, raise exception.
-delete_obj(List,List) -> corba:raise(#'CosNotifyFilter_FilterNotFound'{});
-delete_obj(List,_) -> List.
-
-%% Start timer which send a message each time we should pull for new events.
-start_timer(State) ->
- case catch timer:send_interval(?get_PullInterval(State), pull) of
- {ok,PullTRef} ->
- ?DBG("PULL CONSUMER STARTED PULL TIMER ~p~n",
- [?get_PullInterval(State)]),
- ?set_PullTimer(State, PullTRef);
- What ->
- orber:dbg("[~p] PullerConsumer:start_timer();~n"
- "Unable to invoke timer:send_interval/2: ~p",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-stop_timer(State) ->
- ?DBG("PULL CONSUMER STOPPED TIMER~n",[]),
- timer:cancel(?get_PullTimer(State)).
-
-%% Try pull event(s); which method is determined by which type this proxy is.
-try_pull_events(State) when ?is_ANY(State) ->
- case catch 'CosEventComm_PullSupplier':try_pull(?get_Client(State)) of
- {_,false} ->
- {noreply, State};
- {Event, true} ->
- case ?not_isConvertedStructured(Event) of
- true ->
- forward(seq, State,
- cosNotification_eventDB:filter_events([any:get_value(Event)],
- ?get_AllFilter(State)));
- _ ->
- forward(any, State,
- cosNotification_eventDB:filter_events([Event],
- ?get_AllFilter(State)))
- end;
- _->
- {noreply, State}
- end;
-try_pull_events(State) when ?is_SEQUENCE(State) ->
- case catch 'CosNotifyComm_SequencePullSupplier':
- try_pull_structured_events(?get_Client(State), ?get_BatchLimit(State)) of
- {_,false} ->
- {noreply, State};
- {EventSeq, true} ->
- %% We cannot convert parts of the sequence to any, event though they
- %% are converted from any to structured. Would be 'impossible' to send.
- forward(seq, State,
- cosNotification_eventDB:filter_events(EventSeq,
- ?get_AllFilter(State)));
- _->
- {noreply, State}
- end;
-try_pull_events(State) when ?is_STRUCTURED(State) ->
- case catch 'CosNotifyComm_StructuredPullSupplier':
- try_pull_structured_event(?get_Client(State)) of
- {_,false} ->
- {noreply, State};
- {Event, true} when ?not_isConvertedAny(Event) ->
- forward(any, State,
- cosNotification_eventDB:filter_events([Event#'CosNotification_StructuredEvent'.remainder_of_body],
- ?get_AllFilter(State)));
- {Event, true} ->
- forward(seq, State,
- cosNotification_eventDB:filter_events([Event],
- ?get_AllFilter(State)));
- _->
- {noreply, State}
- end.
-
-
-
-%% Forward events
-forward(_, State, {[], _}) when ?is_ANDOP(State) ->
- %% Did not pass filtering. Since AND no need to pass on.
- {noreply, State};
-forward(Type, State, {[], Failed}) ->
- %% Did not pass filtering, but since OR it may pass Admin filters, hence, pass
- %% on to Admin
- forward(Type, State, Failed, ?get_MyAdmin(State), 'MATCH');
-forward(Type, State, {Passed, _}) when ?is_ANDOP(State) ->
- %% Did pass filtering, but since AND we must pass it to Admin to check against
- %% its Filters. Just ignore the ones that failed.
- forward(Type, State, Passed, ?get_MyAdmin(State), 'MATCH');
-forward(Type, State, {Passed, []}) ->
- %% Did pass filtering, and since OR we can pass it to the Channel directly.
- forward(Type, State, Passed, ?get_MyChannel(State), 'MATCHED');
-forward(Type, State, {Passed, Failed}) ->
- %% Some passed filtering, and since OR we can pass the ones that passed directly
- %% to the channel and the other ones via the admin.
- forward(Type, State, Passed, ?get_MyChannel(State), 'MATCHED'),
- forward(Type, State, Failed, ?get_MyAdmin(State), 'MATCH').
-
-forward(any, State, [Event], SendTo, Status) ->
- case catch oe_CosNotificationComm_Event:callAny(SendTo, Event, Status) of
- ok ->
- ?DBG("PROXY FORWARD ANY: ~p~n",[Event]),
- {noreply, State};
- {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') orelse
- is_record(E, 'NO_PERMISSION') orelse
- is_record(E, 'CosEventComm_Disconnected') ->
- orber:dbg("[~p] PullerConsumer:forward();~n"
- "Admin/Channel no longer exists; terminating and dropping: ~p",
- [?LINE, Event], ?DEBUG_LEVEL),
- 'CosNotification_Common':notify([{proxy, State#state.this},
- {client, ?get_Client(State)},
- {reason, {'EXCEPTION', E}}]),
- {stop, normal, State};
- R when ?is_PersistentConnection(State) ->
- orber:dbg("[~p] PullerConsumer:forward();~n"
- "Admin/Channel respond incorrect: ~p~n"
- "Dropping: ~p", [?LINE, R, Event], ?DEBUG_LEVEL),
- {noreply, State};
- R ->
- orber:dbg("[~p] PullerConsumer:forward();~n"
- "Admin/Channel respond incorrect: ~p~n"
- "Terminating and dropping: ~p",
- [?LINE, R, Event], ?DEBUG_LEVEL),
- 'CosNotification_Common':notify([{proxy, State#state.this},
- {client, ?get_Client(State)},
- {reason, R}]),
- {stop, normal, State}
- end;
-forward(seq, State, Event, SendTo, Status) ->
- case catch oe_CosNotificationComm_Event:callSeq(SendTo, Event, Status) of
- ok ->
- ?DBG("PROXY FORWARD SEQUENCE: ~p~n",[Event]),
- {noreply, State};
- {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') orelse
- is_record(E, 'NO_PERMISSION') orelse
- is_record(E, 'CosEventComm_Disconnected') ->
- orber:dbg("[~p] PullerConsumer:forward();~n"
- "Admin/Channel no longer exists; terminating and dropping: ~p",
- [?LINE, Event], ?DEBUG_LEVEL),
- 'CosNotification_Common':notify([{proxy, State#state.this},
- {client, ?get_Client(State)},
- {reason, {'EXCEPTION', E}}]),
- {stop, normal, State};
- R when ?is_PersistentConnection(State) ->
- orber:dbg("[~p] PullerConsumer:forward();~n"
- "Admin/Channel respond incorrect: ~p~n"
- "Dropping: ~p", [?LINE, R, Event], ?DEBUG_LEVEL),
- {noreply, State};
- R ->
- orber:dbg("[~p] PullerConsumer:forward();~n"
- "Admin/Channel respond incorrect: ~p~n"
- "Terminating and dropping: ~p",
- [?LINE, R, Event], ?DEBUG_LEVEL),
- 'CosNotification_Common':notify([{proxy, State#state.this},
- {client, ?get_Client(State)},
- {reason, R}]),
- {stop, normal, State}
- end.
-
-%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/PullerSupplier_impl.erl b/lib/cosNotification/src/PullerSupplier_impl.erl
deleted file mode 100644
index e1956cff28..0000000000
--- a/lib/cosNotification/src/PullerSupplier_impl.erl
+++ /dev/null
@@ -1,915 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2015. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : PullerSupplier_impl.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module('PullerSupplier_impl').
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-%% cosEvent files.
--include_lib("cosEvent/include/CosEventChannelAdmin.hrl").
-%% Application files
--include("CosNotification.hrl").
--include("CosNotifyChannelAdmin.hrl").
--include("CosNotifyComm.hrl").
--include("CosNotifyFilter.hrl").
-
--include("CosNotification_Definitions.hrl").
-
-%%--------------- EXPORTS ------------------------------------
-%%--------------- External -----------------------------------
-%%----- CosNotifyChannelAdmin::ProxyPullSupplier -------------
--export([connect_any_pull_consumer/4]).
-
-%%----- CosNotifyChannelAdmin::SequenceProxyPullSupplier -----
--export([connect_sequence_pull_consumer/4]).
-
-%%----- CosNotifyChannelAdmin::StructuredProxyPullSupplier ---
--export([connect_structured_pull_consumer/4]).
-
-%%----- Inherit from CosNotifyChannelAdmin::ProxySupplier ----
--export([obtain_offered_types/4,
- validate_event_qos/4]).
-
-%%----- Inherit from CosNotification::QoSAdmin ---------------
--export([get_qos/3,
- set_qos/4,
- validate_qos/4]).
-
-%%----- Inherit from CosNotifyComm::NotifySubscribe ----------
--export([subscription_change/5]).
-
-%%----- Inherit from CosNotifyFilter::FilterAdmin ------------
--export([add_filter/4,
- remove_filter/4,
- get_filter/4,
- get_all_filters/3,
- remove_all_filters/3]).
-
-%%----- Inherit from CosEventComm::PullSupplier -------------
--export([pull/3,
- try_pull/3,
- disconnect_pull_supplier/3]).
-
-%%----- Inherit from CosNotifyComm::SequencePullSupplier --
--export([pull_structured_events/4,
- try_pull_structured_events/4,
- disconnect_sequence_pull_supplier/3]).
-
-%%----- Inherit from CosNotifyComm::StructuredPullSupplier --
--export([pull_structured_event/3,
- try_pull_structured_event/3,
- disconnect_structured_pull_supplier/3]).
-
-%%----- Inherit from CosEventChannelAdmin::ProxyPullSupplier
--export([connect_pull_consumer/4]).
-
-%% Attributes (external) CosNotifyChannelAdmin::ProxySupplier
--export(['_get_MyType'/3,
- '_get_MyAdmin'/3,
- '_get_priority_filter'/3,
- '_set_priority_filter'/4,
- '_get_lifetime_filter'/3,
- '_set_lifetime_filter'/4]).
-
-%%--------------- Internal -----------------------------------
-%%----- Inherit from cosNotificationComm --------------------
--export([callAny/5,
- callSeq/5]).
-
-%%--------------- gen_server specific exports ----------------
--export([handle_info/2, code_change/3]).
--export([init/1, terminate/2]).
-
-%%--------------- LOCAL DEFINITIONS --------------------------
-%% Data structures
--record(state, {myType,
- myAdmin,
- myAdminPid,
- myChannel,
- myFilters = [],
- myOperator,
- idCounter = 0,
- prioFil,
- lifetFil,
- client,
- qosGlobal,
- qosLocal,
- pacingTimer,
- respondTo,
- subscribeType = false,
- subscribeData = true,
- etsR,
- eventDB}).
-
-%% Data structures constructors
--define(get_InitState(_MyT, _MyA, _MyAP, _QS, _LQS, _Ch, _MyOp, _GT, _GL, _TR),
- #state{myType = _MyT,
- myAdmin = _MyA,
- myAdminPid= _MyAP,
- myChannel = _Ch,
- myOperator= _MyOp,
- qosGlobal = _QS,
- qosLocal = _LQS,
- etsR = ets:new(oe_ets, [set, protected]),
- eventDB = cosNotification_eventDB:create_db(_LQS, _GT, _GL, _TR)}).
-
-
-%% Data structures selectors
-%% Attributes
--define(get_MyType(S), S#state.myType).
--define(get_MyAdmin(S), S#state.myAdmin).
--define(get_MyAdminPid(S), S#state.myAdmin).
--define(get_MyChannel(S), S#state.myChannel).
--define(get_MyOperator(S), S#state.myOperator).
--define(get_PrioFil(S), S#state.prioFil).
--define(get_LifeTFil(S), S#state.lifetFil).
-%% Client Object
--define(get_Client(S), S#state.client).
-%% QoS
--define(get_GlobalQoS(S), S#state.qosGlobal).
--define(get_LocalQoS(S), S#state.qosLocal).
--define(get_BothQoS(S), {S#state.qosGlobal, S#state.qosLocal}).
-%% Filters
--define(get_Filter(S, I), find_obj(lists:keysearch(I, 1, S#state.myFilters))).
--define(get_AllFilter(S), S#state.myFilters).
--define(get_AllFilterID(S), find_ids(S#state.myFilters)).
-%% Event
--define(get_Event(S), cosNotification_eventDB:get_event(S#state.eventDB)).
--define(get_Events(S,M), cosNotification_eventDB:get_events(S#state.eventDB, M)).
--define(get_RespondTo(S), S#state.respondTo).
-%% Amin
--define(get_PacingTimer(S), S#state.pacingTimer).
--define(get_PacingInterval(S), round(?not_GetPacingInterval((S#state.qosLocal))/10000000)).
--define(get_BatchLimit(S), ?not_GetMaximumBatchSize((S#state.qosLocal))).
-%% Subscribe
--define(get_AllSubscribe(S), lists:flatten(ets:match(S#state.etsR,
- {'$1',subscribe}))).
--define(get_SubscribeType(S), S#state.subscribeType).
--define(get_SubscribeData(S), S#state.subscribeData).
-%% ID
--define(get_IdCounter(S), S#state.idCounter).
--define(get_SubscribeDB(S), S#state.etsR).
-
-%% Data structures modifiers
-%% Attributes
--define(set_PrioFil(S,D), S#state{prioFil=D}).
--define(set_LifeTFil(S,D), S#state{lifetFil=D}).
-%% Client Object
--define(set_Client(S,D), S#state{client=D}).
--define(del_Client(S), S#state{client=undefined}).
-%% QoS
--define(set_LocalQoS(S,D), S#state{qosLocal=D}).
--define(set_GlobalQoS(S,D), S#state{qosGlobal=D}).
--define(set_BothQoS(S,GD,LD), S#state{qosGlobal=GD, qosLocal=LD}).
--define(update_EventDB(S,Q), S#state{eventDB=
- cosNotification_eventDB:update(S#state.eventDB, Q)}).
-%% Filters
--define(add_Filter(S,I,O), S#state{myFilters=[{I,O}|S#state.myFilters]}).
--define(del_Filter(S,I), S#state{myFilters=
- delete_obj(lists:keydelete(I, 1, S#state.myFilters),
- S#state.myFilters)}).
--define(del_AllFilter(S), S#state{myFilters=[]}).
--define(set_Unconnected(S), S#state{client=undefined}).
--define(reset_RespondTo(S), S#state{respondTo=undefined}).
--define(set_RespondTo(S,F), S#state{respondTo=F}).
-%% Event
--define(add_Event(S,E), catch cosNotification_eventDB:
- add_event(S#state.eventDB, E, S#state.lifetFil, S#state.prioFil)).
--define(addAndGet_Event(S,E), catch cosNotification_eventDB:
- add_and_get_event(S#state.eventDB, E, S#state.lifetFil, S#state.prioFil)).
-%% Admin
--define(set_PacingTimer(S,T), S#state{pacingTimer=T}).
-%% Subscribe
--define(add_Subscribe(S,E), ets:insert(S#state.etsR, {E, subscribe})).
--define(del_Subscribe(S,E), ets:delete(S#state.etsR, E)).
--define(set_SubscribeType(S,T), S#state{subscribeType=T}).
--define(set_SubscribeData(S,D), S#state{subscribeData=D}).
-%% ID
--define(set_IdCounter(S,V), S#state{idCounter=V}).
--define(new_Id(S), 'CosNotification_Common':create_id(S#state.idCounter)).
-
-%% MISC
--define(is_ANY(S), S#state.myType == 'PULL_ANY').
--define(is_STRUCTURED(S), S#state.myType == 'PULL_STRUCTURED').
--define(is_SEQUENCE(S), S#state.myType == 'PULL_SEQUENCE').
--define(is_ANDOP(S), S#state.myOperator == 'AND_OP').
--define(is_UnConnected(S), S#state.client == undefined).
--define(is_Connected(S), S#state.client =/= undefined).
--define(is_Waiting(S), S#state.respondTo =/= undefined).
--define(is_SubscribedFor(S,K), ets:lookup(S#state.etsR, K) =/= []).
--define(is_BatchLimitReached(S,M), cosNotification_eventDB:
- status(S#state.eventDB, {batchLimit,
- ?not_GetMaximumBatchSize((S#state.qosLocal)), M})).
-
-%%----------------------------------------------------------%
-%% function : handle_info, code_change
-%% Arguments:
-%% Returns :
-%% Effect : Functions demanded by the gen_server module.
-%%-----------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-handle_info(Info, State) ->
- ?DBG("INFO: ~p~n", [Info]),
- case Info of
- {'EXIT', Pid, Reason} when ?get_MyAdminPid(State)==Pid->
- ?DBG("PARENT ADMIN: ~p TERMINATED.~n",[Reason]),
- {stop, Reason, State};
- {'EXIT', _Pid, _Reason} ->
- ?DBG("PROXYPUSHSUPPLIER: ~p TERMINATED.~n",[_Reason]),
- {noreply, State};
- {pacing, TS} when ?is_Waiting(State) ->
- case ?get_PacingTimer(State) of
- {_, TS} ->
- ?DBG("PULL SUPPLIER PACING LIMIT REACHED~n",[]),
- {RespondTo, Max} = ?get_RespondTo(State),
- {EventSeq, _} = ?get_Events(State, Max),
- corba:reply(RespondTo, EventSeq),
- {noreply, ?reset_RespondTo(State)};
- _ ->
- %% Must have been an old timer event, i.e., we reached the
- %% Batch Limit before Pace limit and we were not able
- %% to stop the timer before it triggered an event.
- ?DBG("PULL SUPPLIER OLD PACING LIMIT REACHED~n",[]),
- {noreply, State}
- end;
- {pacing, _} ->
- ?DBG("PULL SUPPLIER PACING LIMIT REACHED BUT NO CLIENT; IMPOSSIBLE!!!~n",[]),
- {noreply, State};
- _ ->
- {noreply, State}
- end.
-
-%%----------------------------------------------------------%
-%% function : init, terminate
-%% Arguments:
-%%-----------------------------------------------------------
-
-init([MyType, MyAdmin, MyAdminPid, InitQoS, LQS, MyChannel, Options, Operator]) ->
- process_flag(trap_exit, true),
- GCTime = 'CosNotification_Common':get_option(gcTime, Options,
- ?not_DEFAULT_SETTINGS),
- GCLimit = 'CosNotification_Common':get_option(gcLimit, Options,
- ?not_DEFAULT_SETTINGS),
- TimeRef = 'CosNotification_Common':get_option(timeService, Options,
- ?not_DEFAULT_SETTINGS),
- {ok, ?get_InitState(MyType, MyAdmin, MyAdminPid, InitQoS, LQS, MyChannel,
- Operator, GCTime, GCLimit, TimeRef)}.
-
-terminate(_Reason, State) when ?is_UnConnected(State) ->
- ok;
-terminate(_Reason, State) ->
- Client = ?get_Client(State),
- case catch corba_object:is_nil(Client) of
- false when ?is_ANY(State) ->
- 'CosNotification_Common':disconnect('CosEventComm_PullConsumer',
- disconnect_pull_consumer,
- Client);
- false when ?is_SEQUENCE(State) ->
- 'CosNotification_Common':disconnect('CosNotifyComm_SequencePullConsumer',
- disconnect_sequence_pull_consumer,
- Client);
- false when ?is_STRUCTURED(State) ->
- 'CosNotification_Common':disconnect('CosNotifyComm_StructuredPullConsumer',
- disconnect_structured_pull_consumer,
- Client);
- _ ->
- ok
- end.
-
-%%-----------------------------------------------------------
-%%----- CosNotifyChannelAdmin_ProxySupplier attributes ------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% Attribute: '_get_MyType'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_MyType'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_MyType(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_MyAdmin'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_MyAdmin'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_MyAdmin(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_*et_priority_filter'
-%% Type : read/write
-%% Returns :
-%%-----------------------------------------------------------
-'_get_priority_filter'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_PrioFil(State), State}.
-'_set_priority_filter'(_OE_THIS, _OE_FROM, State, PrioF) ->
- {reply, ok, ?set_PrioFil(State, PrioF)}.
-
-
-%%----------------------------------------------------------%
-%% Attribute: '_*et_lifetime_filter'
-%% Type : read/write
-%% Returns :
-%%-----------------------------------------------------------
-'_get_lifetime_filter'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_LifeTFil(State), State}.
-'_set_lifetime_filter'(_OE_THIS, _OE_FROM, State, LifeTF) ->
- {reply, ok, ?set_LifeTFil(State, LifeTF)}.
-
-%%-----------------------------------------------------------
-%%------- Exported external functions -----------------------
-%%-----------------------------------------------------------
-%%----- CosEventChannelAdmin::ProxyPullSupplier -------------
-%%----------------------------------------------------------%
-%% function : connect_pull_consumer
-%% Arguments: Client - CosEventComm::PullConsumer
-%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
-%% {'EXCEPTION', #'TypeError'{}} |
-%% {'EXCEPTION', #'BAD_OPERATION'{}}
-%% Both exceptions from CosEventChannelAdmin!!!
-%%-----------------------------------------------------------
-connect_pull_consumer(OE_THIS, OE_FROM, State, Client) ->
- connect_any_pull_consumer(OE_THIS, OE_FROM, State, Client).
-
-%%----- CosNotifyChannelAdmin::ProxyPullSupplier ------------
-%%----------------------------------------------------------%
-%% function : connect_any_pull_consumer
-%% Arguments: Client - CosEventComm::PullConsumer
-%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
-%% {'EXCEPTION', #'TypeError'{}} |
-%% {'EXCEPTION', #'BAD_OPERATION'{}}
-%% Both exceptions from CosEventChannelAdmin!!!
-%%-----------------------------------------------------------
-connect_any_pull_consumer(_OE_THIS, _OE_FROM, State, Client) when ?is_ANY(State) ->
- ?not_TypeCheck(Client, 'CosEventComm_PullConsumer'),
- if
- ?is_Connected(State) ->
- corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
- true ->
- {reply, ok, ?set_Client(State, Client)}
- end;
-connect_any_pull_consumer(_, _, _, _) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----- CosNotifyChannelAdmin::SequenceProxyPullSupplier ----
-%%----------------------------------------------------------%
-%% function : connect_sequence_pull_consumer
-%% Arguments: Client - CosNotifyComm::SequencePullConsumer
-%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
-%% {'EXCEPTION', #'TypeError'{}} |
-%% {'EXCEPTION', #'BAD_OPERATION'{}}
-%%-----------------------------------------------------------
-connect_sequence_pull_consumer(_OE_THIS, _OE_FROM, State, Client) when ?is_SEQUENCE(State) ->
- ?not_TypeCheck(Client, 'CosNotifyComm_SequencePullConsumer'),
- if
- ?is_Connected(State) ->
- corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
- true ->
- {reply, ok, ?set_Client(State, Client)}
- end;
-connect_sequence_pull_consumer(_, _, _, _) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----- CosNotifyChannelAdmin::StructuredProxyPullSupplier --
-%%----------------------------------------------------------%
-%% function : connect_structured_pull_consumer
-%% Arguments: Client - CosNotifyComm::StructuredPullConsumer
-%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
-%% {'EXCEPTION', #'TypeError'{}} |
-%% {'EXCEPTION', #'BAD_OPERATION'{}}
-%%-----------------------------------------------------------
-connect_structured_pull_consumer(_OE_THIS, _OE_FROM, State, Client) when ?is_STRUCTURED(State) ->
- ?not_TypeCheck(Client, 'CosNotifyComm_StructuredPullConsumer'),
- if
- ?is_Connected(State) ->
- corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
- true ->
- {reply, ok, ?set_Client(State, Client)}
- end;
-connect_structured_pull_consumer(_, _, _, _) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----- Inherit from CosNotifyChannelAdmin::ProxySupplier ---
-%%----------------------------------------------------------%
-%% function : obtain_offered_types
-%% Arguments: Mode - enum 'ObtainInfoMode' (CosNotifyChannelAdmin)
-%% Returns : CosNotification::EventTypeSeq
-%%-----------------------------------------------------------
-obtain_offered_types(_OE_THIS, _OE_FROM, State, 'ALL_NOW_UPDATES_OFF') ->
- {reply, ?get_AllSubscribe(State), ?set_SubscribeType(State, false)};
-obtain_offered_types(_OE_THIS, _OE_FROM, State, 'ALL_NOW_UPDATES_ON') ->
- {reply, ?get_AllSubscribe(State), ?set_SubscribeType(State, true)};
-obtain_offered_types(_OE_THIS, _OE_FROM, State, 'NONE_NOW_UPDATES_OFF') ->
- {reply, [], ?set_SubscribeType(State, false)};
-obtain_offered_types(_OE_THIS, _OE_FROM, State, 'NONE_NOW_UPDATES_ON') ->
- {reply, [], ?set_SubscribeType(State, true)};
-obtain_offered_types(_,_,_,What) ->
- orber:dbg("[~p] PullerSupplier:obtain_offered_types(~p);~n"
- "Incorrect enumerant", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : validate_event_qos
-%% Arguments: RequiredQoS - CosNotification::QoSProperties
-%% Returns : ok | {'EXCEPTION', #'UnsupportedQoS'{}}
-%% AvilableQoS - CosNotification::NamedPropertyRangeSeq (out)
-%%-----------------------------------------------------------
-validate_event_qos(_OE_THIS, _OE_FROM, State, RequiredQoS) ->
- AvilableQoS = 'CosNotification_Common':validate_event_qos(RequiredQoS,
- ?get_LocalQoS(State)),
- {reply, {ok, AvilableQoS}, State}.
-
-%%----- Inherit from CosNotification::QoSAdmin --------------
-%%----------------------------------------------------------%
-%% function : get_qos
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-get_qos(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_GlobalQoS(State), State}.
-
-%%----------------------------------------------------------%
-%% function : set_qos
-%% Arguments: QoS - CosNotification::QoSProperties, i.e.,
-%% [#'Property'{name, value}, ...] where name eq. string()
-%% and value eq. any().
-%% Returns : ok | {'EXCEPTION', CosNotification::UnsupportedQoS}
-%%-----------------------------------------------------------
-set_qos(_OE_THIS, _OE_FROM, State, QoS) ->
- {NewQoS, LQS} = 'CosNotification_Common':set_qos(QoS, ?get_BothQoS(State),
- proxy, ?get_MyAdmin(State),
- false),
- NewState = ?update_EventDB(State, LQS),
- {reply, ok, ?set_BothQoS(NewState, NewQoS, LQS)}.
-
-%%----------------------------------------------------------%
-%% function : validate_qos
-%% Arguments: Required_qos - CosNotification::QoSProperties
-%% [#'Property'{name, value}, ...] where name eq. string()
-%% and value eq. any().
-%% Returns : {'EXCEPTION', CosNotification::UnsupportedQoS}
-%% {ok, CosNotification::NamedPropertyRangeSeq}
-%%-----------------------------------------------------------
-validate_qos(_OE_THIS, _OE_FROM, State, Required_qos) ->
- QoS = 'CosNotification_Common':validate_qos(Required_qos, ?get_BothQoS(State),
- proxy, ?get_MyAdmin(State),
- false),
- {reply, {ok, QoS}, State}.
-
-%%----- Inherit from CosNotifyComm::NotifySubscribe ---------
-%%----------------------------------------------------------%
-%% function : subscription_change
-%% Arguments: Added - Removed - CosNotification::EventTypeSeq
-%% Returns : ok
-%%-----------------------------------------------------------
-subscription_change(_OE_THIS, _OE_FROM, State, Added, Removed) ->
- cosNotification_Filter:validate_types(Added),
- cosNotification_Filter:validate_types(Removed),
- %% On this "side", we care about which type of events the client
- %% will require, since the client (or an agent) clearly stated
- %% that it's only interested in these types of events.
- %% Also see PusherConsumer- and PullerConsumer-'offer_change'.
- update_subscribe(remove, State, Removed),
- CurrentSub = ?get_AllSubscribe(State),
- NewState =
- case cosNotification_Filter:check_types(Added++CurrentSub) of
- true ->
- %% Types supplied does in some way cause all events to be valid.
- %% Smart? Would have been better to not supply any at all.
- ?set_SubscribeData(State, true);
- {ok, Which, WC} ->
- ?set_SubscribeData(State, {Which, WC})
- end,
- update_subscribe(add, NewState, Added),
- case ?get_SubscribeType(NewState) of
- true ->
- %% Perhaps we should handle exception here?!
- %% Probably not. Better to stay "on-line".
- catch 'CosNotifyComm_NotifyPublish':
- offer_change(?get_Client(NewState), Added, Removed),
- ok;
- _->
- ok
- end,
- {reply, ok, NewState}.
-
-update_subscribe(_, _, [])->
- ok;
-update_subscribe(add, State, [H|T]) ->
- ?add_Subscribe(State, H),
- update_subscribe(add, State, T);
-update_subscribe(remove, State, [H|T]) ->
- ?del_Subscribe(State, H),
- update_subscribe(remove, State, T).
-
-%%----- Inherit from CosNotifyFilter::FilterAdmin -----------
-%%----------------------------------------------------------%
-%% function : add_filter
-%% Arguments: Filter - CosNotifyFilter::Filter
-%% Returns : FilterID - long
-%%-----------------------------------------------------------
-add_filter(_OE_THIS, _OE_FROM, State, Filter) ->
- 'CosNotification_Common':type_check(Filter, 'CosNotifyFilter_Filter'),
- FilterID = ?new_Id(State),
- NewState = ?set_IdCounter(State, FilterID),
- {reply, FilterID, ?add_Filter(NewState, FilterID, Filter)}.
-
-%%----------------------------------------------------------%
-%% function : remove_filter
-%% Arguments: FilterID - long
-%% Returns : ok
-%%-----------------------------------------------------------
-remove_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
- {reply, ok, ?del_Filter(State, FilterID)};
-remove_filter(_,_,_,What) ->
- orber:dbg("[~p] PullerSupplier:remove_filter(~p); Not an integer",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : get_filter
-%% Arguments: FilterID - long
-%% Returns : Filter - CosNotifyFilter::Filter |
-%% {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}
-%%-----------------------------------------------------------
-get_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
- {reply, ?get_Filter(State, FilterID), State};
-get_filter(_,_,_,What) ->
- orber:dbg("[~p] PullerSupplier:get_filter(~p); Not an integer",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : get_all_filters
-%% Arguments: -
-%% Returns : Filter - CosNotifyFilter::FilterIDSeq
-%%-----------------------------------------------------------
-get_all_filters(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_AllFilterID(State), State}.
-
-%%----------------------------------------------------------%
-%% function : remove_all_filters
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-remove_all_filters(_OE_THIS, _OE_FROM, State) ->
- {reply, ok, ?del_AllFilter(State)}.
-
-%%----- Inherit from CosEventComm::PullSupplier -------------
-%%----------------------------------------------------------%
-%% function : disconnect_pull_supplier
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-disconnect_pull_supplier(_OE_THIS, _OE_FROM, State) ->
- {stop, normal, ok, ?set_Unconnected(State)}.
-
-%%----------------------------------------------------------%
-%% function : pull
-%% Arguments: -
-%% Returns : any - CORBA::ANY
-%%-----------------------------------------------------------
-pull(_OE_THIS, OE_FROM, State) when ?is_ANY(State) ->
- case ?get_Event(State) of
- {[], _} ->
- {noreply, ?set_RespondTo(State, OE_FROM)};
- {Event,_} ->
- {reply, Event, State}
- end;
-pull(_,_,_) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : try_pull
-%% Arguments: -
-%% Returns : any - CORBA::ANY
-%% HasEvent - boolean (out-type)
-%%-----------------------------------------------------------
-try_pull(_OE_THIS, _OE_FROM, State) when ?is_ANY(State) ->
- case ?get_Event(State) of
- {[], _} ->
- {reply, {any:create(orber_tc:null(), null), false}, State};
- {Event, Bool} ->
- {reply, {Event, Bool}, State}
- end;
-try_pull(_,_,_) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----- Inherit from CosNotifyComm::SequencePullSupplier ----
-%%----------------------------------------------------------%
-%% function : disconnect_sequence_pull_supplier
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-disconnect_sequence_pull_supplier(_OE_THIS, _OE_FROM, State) ->
- {stop, normal, ok, ?set_Unconnected(State)}.
-
-%%----------------------------------------------------------%
-%% function : pull_structured_events
-%% Arguments: Max - long()
-%% Returns : [StructuredEvent, ..]
-%%-----------------------------------------------------------
-pull_structured_events(_OE_THIS, OE_FROM, State, Max) when ?is_SEQUENCE(State) ->
- case ?is_BatchLimitReached(State, Max) of
- true ->
- %% This test is not fool-proof; if Events have been stored
- %% using StartTime they will still be there but we cannot
- %% deliver them anyway. To solve this "problem" would cost!
- %% Hence, since it works fine otherwise it will do.
- case ?get_Events(State, Max) of
- {[], false} ->
- NewState = start_timer(State),
- {noreply, ?set_RespondTo(NewState, {OE_FROM, Max})};
- {Event,_} ->
- {reply, Event, State}
- end;
- _->
- NewState = start_timer(State),
- {noreply, ?set_RespondTo(NewState, {OE_FROM, Max})}
- end;
-pull_structured_events(_,_,_,_) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : try_pull_structured_events
-%% Arguments: Max - long()
-%% Returns : [StructuredEvent, ..]
-%% HasEvent - Boolean()
-%%-----------------------------------------------------------
-try_pull_structured_events(_OE_THIS, _OE_FROM, State, Max) when ?is_SEQUENCE(State) ->
- {reply, ?get_Events(State, Max), State};
-try_pull_structured_events(_,_,_,_) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----- Inherit from CosNotifyComm::StructuredPullSupplier --
-%%----------------------------------------------------------%
-%% function : disconnect_structured_pull_supplier
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-disconnect_structured_pull_supplier(_OE_THIS, _OE_FROM, State) ->
- {stop, normal, ok, ?set_Unconnected(State)}.
-
-%%----------------------------------------------------------%
-%% function : pull_structured_event
-%% Arguments: -
-%% Returns :
-%%-----------------------------------------------------------
-pull_structured_event(_OE_THIS, OE_FROM, State) when ?is_STRUCTURED(State) ->
- case ?get_Event(State) of
- {[], _} ->
- {noreply, ?set_RespondTo(State, OE_FROM)};
- {Event,_} ->
- {reply, Event, State}
- end;
-pull_structured_event(_,_,_) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : try_pull_structured_event
-%% Arguments: -
-%% Returns :
-%%-----------------------------------------------------------
-try_pull_structured_event(_OE_THIS, _OE_FROM, State) when ?is_STRUCTURED(State) ->
- case ?get_Event(State) of
- {[], _} ->
- {reply,
- {?not_CreateSE("","","",[],[],any:create(orber_tc:null(), null)), false},
- State};
- {Event, Bool} ->
- {reply, {Event, Bool}, State}
- end;
-try_pull_structured_event(_,_,_) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-find_obj({value, {_, Obj}}) -> Obj;
-find_obj(_) -> {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}.
-
-find_ids(List) -> find_ids(List, []).
-find_ids([], Acc) -> Acc;
-find_ids([{I,_}|T], Acc) -> find_ids(T, [I|Acc]);
-find_ids(_, _) -> corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
-
-%% Delete a single object.
-%% The list do not differ, i.e., no filter removed, raise exception.
-delete_obj(List,List) -> corba:raise(#'CosNotifyFilter_FilterNotFound'{});
-delete_obj(List,_) -> List.
-
-
-%%-----------------------------------------------------------
-%% function : callSeq
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-callSeq(_OE_THIS, OE_FROM, State, EventsIn, Status) ->
- %% We should do something here, i.e., see what QoS this Object offers and
- %% act accordingly.
- corba:reply(OE_FROM, ok),
- case cosNotification_eventDB:validate_event(?get_SubscribeData(State), EventsIn,
- ?get_AllFilter(State),
- ?get_SubscribeDB(State),
- Status) of
- {[], _} ->
- ?DBG("PROXY NOSUBSCRIPTION SEQUENCE/STRUCTURED: ~p~n",[EventsIn]),
- {noreply, State};
- %% Just one event and we got a client waiting => there is no need to store
- %% the event, just transform it and pass it on.
- {[Event], _} when ?is_ANY(State), ?is_Waiting(State) ->
- ?DBG("PROXY RECEIVED SEQUENCE[1]==>ANY: ~p~n",[Event]),
- AnyEvent = any:create('CosNotification_StructuredEvent':tc(),Event),
- case ?addAndGet_Event(State, AnyEvent) of
- {[], _} ->
- ?DBG("PROXY RECEIVED UNDELIVERABLE SEQUENCE[1]: ~p~n",
- [Event]),
- %% Cannot deliver the event at the moment; perhaps Starttime
- %% set or Deadline passed.
- {noreply, State};
- {PossiblyOtherEvent, _} ->
- ?DBG("PROXY RECEIVED SEQUENCE[1] ~p; DELIVER: ~p~n",
- [Event, PossiblyOtherEvent]),
- corba:reply(?get_RespondTo(State), PossiblyOtherEvent),
- {noreply, ?reset_RespondTo(State)}
- end;
- {[Event],_} when ?is_STRUCTURED(State), ?is_Waiting(State) ->
- case ?addAndGet_Event(State, Event) of
- {[], _} ->
- ?DBG("PROXY RECEIVED UNDELIVERABLE SEQUENCE[1]: ~p~n",
- [Event]),
- %% Cannot deliver the event at the moment; perhaps Starttime
- %% set or Deadline passed.
- {noreply, State};
- {PossiblyOtherEvent, _} ->
- ?DBG("PROXY RECEIVED SEQUENCE[1] ~p; DELIVER: ~p~n",
- [Event, PossiblyOtherEvent]),
- corba:reply(?get_RespondTo(State), PossiblyOtherEvent),
- {noreply, ?reset_RespondTo(State)}
- end;
- %% A sequence of events => store them and extract the first (according to QoS)
- %% event and forward it.
- {Events,_} when ?is_ANY(State), ?is_Waiting(State) ->
- ?DBG("PROXY RECEIVED SEQUENCE==>ANY: ~p~n",[Events]),
- store_events(State, Events),
- case ?get_Event(State) of
- {[], _} ->
- {noreply, State};
- {AnyEvent, _} ->
- corba:reply(?get_RespondTo(State), AnyEvent),
- {noreply, ?reset_RespondTo(State)}
- end;
- {Events, _} when ?is_STRUCTURED(State), ?is_Waiting(State) ->
- ?DBG("PROXY RECEIVED SEQUENCE: ~p~n",[Events]),
- store_events(State, Events),
- case ?get_Event(State) of
- {[], _} ->
- {noreply, State};
- {_StrEvent, _} ->
- corba:reply(?get_RespondTo(State), Events),
- {noreply, ?reset_RespondTo(State)}
- end;
- {Events, _} when ?is_SEQUENCE(State), ?is_Waiting(State) ->
- ?DBG("PROXY RECEIVED SEQUENCE: ~p~n",[Events]),
- %% Store them first and extract Max events in QoS order.
- store_events(State, Events),
- {RespondTo, Max} = ?get_RespondTo(State),
- case ?is_BatchLimitReached(State, Max) of
- true ->
- {EventSeq, _} = ?get_Events(State, Max),
- corba:reply(RespondTo, EventSeq),
- stop_timer(State),
- {noreply, ?reset_RespondTo(State)};
- _->
- {noreply, State}
- end;
- %% No client waiting. Store the event(s).
- {Events, _} ->
- ?DBG("PROXY RECEIVED SEQUENCE: ~p~n",[Events]),
- store_events(State, Events),
- {noreply, State}
- end.
-
-store_events(_State, []) ->
- ok;
-store_events(State, [Event|Rest]) when ?is_ANY(State) ->
- AnyEvent = any:create('CosNotification_StructuredEvent':tc(),Event),
- ?add_Event(State,AnyEvent),
- store_events(State, Rest);
-store_events(State, [Event|Rest]) ->
- ?add_Event(State,Event),
- store_events(State, Rest).
-
-%%-----------------------------------------------------------
-%% function : callAny
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-callAny(_OE_THIS, OE_FROM, State, EventIn, Status) ->
- corba:reply(OE_FROM, ok),
- case cosNotification_eventDB:validate_event(?get_SubscribeData(State), EventIn,
- ?get_AllFilter(State),
- ?get_SubscribeDB(State),
- Status) of
- {[],_} ->
- ?DBG("PROXY NOSUBSCRIPTION ANY: ~p~n",[EventIn]),
- {noreply, State};
- {Event,_} when ?is_ANY(State), ?is_Waiting(State) ->
- ?DBG("PROXY RECEIVED ANY: ~p~n",[Event]),
- case ?addAndGet_Event(State, Event) of
- {[],_} ->
- %% Unable to deliver the event (Starttime, Deadline etc).
- {noreply, State};
- {MaybeOtherEvent , _} ->
- corba:reply(?get_RespondTo(State), MaybeOtherEvent),
- {noreply, ?reset_RespondTo(State)}
- end;
- {Event,_} when ?is_ANY(State) ->
- ?DBG("PROXY RECEIVED ANY: ~p~n",[Event]),
- ?add_Event(State,Event),
- {noreply, State};
- {Event,_} when ?is_STRUCTURED(State), ?is_Waiting(State) ->
- ?DBG("PROXY RECEIVED ANY==>STRUCTURED: ~p~n",[Event]),
- case ?addAndGet_Event(State, ?not_CreateSE("","%ANY","",[],[],Event)) of
- {[],_} ->
- %% Unable to deliver the event (Starttime, Deadline etc).
- {noreply, State};
- {MaybeOtherEvent , _} ->
- corba:reply(?get_RespondTo(State), MaybeOtherEvent),
- {noreply, ?reset_RespondTo(State)}
- end;
- {Event,_} when ?is_SEQUENCE(State), ?is_Waiting(State) ->
- ?DBG("PROXY RECEIVED ANY==>SEQUENCE[1]: ~p~n",[Event]),
- ?add_Event(State,?not_CreateSE("","%ANY","",[],[],Event)),
- {RespondTo, Max} = ?get_RespondTo(State),
- case ?is_BatchLimitReached(State, Max) of
- true ->
- {EventSeq, _} = ?get_Events(State, Max),
- corba:reply(RespondTo, EventSeq),
- stop_timer(State),
- {noreply, ?reset_RespondTo(State)};
- _ ->
- {noreply, State}
- end;
- {Event,_} ->
- ?DBG("PROXY RECEIVED ANY==>STRUCTURED/SEQUENCE: ~p~n",[Event]),
- ?add_Event(State,?not_CreateSE("","%ANY","",[],[],Event)),
- {noreply, State}
- end.
-
-
-
-%% Start timers which send a message each time we should push events. Only used
-%% when this objects is defined to supply sequences.
-start_timer(State) ->
- TS = erlang:timestamp(),
- case catch timer:send_after(timer:seconds(?get_PacingInterval(State)),
- {pacing, TS}) of
- {ok,PacTRef} ->
- ?DBG("PULL SUPPLIER STARTED TIMER, BATCH LIMIT: ~p~n",
- [?get_BatchLimit(State)]),
- ?set_PacingTimer(State, {PacTRef, TS});
- What ->
- orber:dbg("[~p] PullerSupplier:start_timer();~n"
- "Unable to invoke timer:send_interval/2: ~p",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-stop_timer(State) ->
- case ?get_PacingTimer(State) of
- undefined ->
- ok;
- {Timer, _} ->
- ?DBG("PULL SUPPLIER STOPPED TIMER~n",[]),
- timer:cancel(Timer)
- end.
-
-%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/PusherConsumer_impl.erl b/lib/cosNotification/src/PusherConsumer_impl.erl
deleted file mode 100644
index f82f9d8bbd..0000000000
--- a/lib/cosNotification/src/PusherConsumer_impl.erl
+++ /dev/null
@@ -1,730 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : PusherConsumer_impl.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module('PusherConsumer_impl').
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-%% cosEvent files.
--include_lib("cosEvent/include/CosEventChannelAdmin.hrl").
--include_lib("cosEvent/include/CosEventComm.hrl").
-%% Application files
--include("CosNotification.hrl").
--include("CosNotifyChannelAdmin.hrl").
--include("CosNotifyComm.hrl").
--include("CosNotifyFilter.hrl").
-
--include("CosNotification_Definitions.hrl").
-
-%%--------------- EXPORTS ------------------------------------
-%%--------------- External -----------------------------------
-%%----- CosNotifyChannelAdmin::ProxyPushConsumer -------------
--export([connect_any_push_supplier/4]).
-
-%%----- CosNotifyChannelAdmin::SequenceProxyPushConsumer -----
--export([connect_sequence_push_supplier/4]).
-
-%%----- CosNotifyChannelAdmin::StructuredProxyPushConsumer ---
--export([connect_structured_push_supplier/4]).
-
-%%----- Inherit from CosNotifyChannelAdmin::ProxyConsumer ----
--export([obtain_subscription_types/4,
- validate_event_qos/4]).
-
-%%----- Inherit from CosNotification::QoSAdmin ---------------
--export([get_qos/3,
- set_qos/4,
- validate_qos/4]).
-
-%%----- Inherit from CosNotifyComm::NotifyPublish ------------
--export([offer_change/5]).
-
-%%----- Inherit from CosNotifyFilter::FilterAdmin ------------
--export([add_filter/4,
- remove_filter/4,
- get_filter/4,
- get_all_filters/3,
- remove_all_filters/3]).
-
-%%----- Inherit from CosEventComm::PushConsumer -------------
--export([push/4,
- disconnect_push_consumer/3]).
-
-%%----- Inherit from CosNotifyComm::SequencePushConsumer ----
--export([push_structured_events/4,
- disconnect_sequence_push_consumer/3]).
-
-%%----- Inherit from CosNotifyComm::StructuredPushConsumer --
--export([push_structured_event/4,
- disconnect_structured_push_consumer/3]).
-
-%%----- Inherit from CosEventChannelAdmin::ProxyPushConsumer
--export([connect_push_supplier/4]).
-
-%% Attributes (external) CosNotifyChannelAdmin::ProxySupplier
--export(['_get_MyType'/3,
- '_get_MyAdmin'/3]).
-
-%%--------------- gen_server specific exports ----------------
--export([handle_info/2, code_change/3]).
--export([init/1, terminate/2]).
-
-%%--------------- LOCAL DEFINITIONS --------------------------
-%% Data structures
--record(state, {myType,
- myAdmin,
- myAdminPid,
- myChannel,
- myFilters = [],
- myOperator,
- idCounter = 0,
- client,
- qosGlobal,
- qosLocal,
- publishType = false,
- etsR,
- eventDB}).
-
-%% Data structures constructors
--define(get_InitState(_MyT, _MyA, _MyAP, _QS, _LQS, _Ch, _EDB, _MyOP),
- #state{myType = _MyT,
- myAdmin = _MyA,
- myAdminPid= _MyAP,
- myChannel = _Ch,
- myOperator= _MyOP,
- qosGlobal = _QS,
- qosLocal = _LQS,
- etsR = ets:new(oe_ets, [set, protected]),
- eventDB = _EDB}).
-
-%%-------------- Data structures selectors -----------------
-%% Attributes
--define(get_MyType(S), S#state.myType).
--define(get_MyAdmin(S), S#state.myAdmin).
--define(get_MyAdminPid(S), S#state.myAdminPid).
--define(get_MyChannel(S), S#state.myChannel).
--define(get_MyOperator(S), S#state.myOperator).
-%% Client Object
--define(get_Client(S), S#state.client).
-%% QoS
--define(get_GlobalQoS(S), S#state.qosGlobal).
--define(get_LocalQoS(S), S#state.qosLocal).
--define(get_BothQoS(S), {S#state.qosGlobal, S#state.qosLocal}).
-%% Filters
--define(get_Filter(S, I), find_obj(lists:keysearch(I, 1, S#state.myFilters))).
--define(get_AllFilter(S), S#state.myFilters).
--define(get_AllFilterID(S), find_ids(S#state.myFilters)).
-%% Publish
--define(get_AllPublish(S), lists:flatten(ets:match(S#state.etsR,
- {'$1',publish}))).
--define(get_PublishType(S), S#state.publishType).
-%% ID
--define(get_IdCounter(S), S#state.idCounter).
-%% Event
--define(get_Event(S), cosNotification_eventDB:get_event(S#state.eventDB)).
--define(get_Events(S,M), cosNotification_eventDB:get_events(S#state.eventDB, M)).
-
--define(get_EventCounter(S), S#state.eventCounter).
-%% Admin
--define(get_BatchLimit(S), ?not_GetMaximumBatchSize((S#state.qosLocal))).
-
-%%-------------- Data structures modifiers -----------------
-%% Client Object
--define(set_Client(S,D), S#state{client=D}).
--define(del_Client(S), S#state{client=undefined}).
--define(set_Unconnected(S), S#state{client=undefined}).
-%% QoS
--define(set_LocalQoS(S,D), S#state{qosLocal=D}).
--define(set_GlobalQoS(S,D), S#state{qosGlobal=D}).
--define(set_BothQoS(S,GD,LD), S#state{qosGlobal=GD, qosLocal=LD}).
-%% Filters
--define(add_Filter(S,I,O), S#state{myFilters=[{I,O}|S#state.myFilters]}).
--define(del_Filter(S,I), S#state{myFilters=
- delete_obj(lists:keydelete(I, 1, S#state.myFilters),
- S#state.myFilters)}).
--define(del_AllFilter(S), S#state{myFilters=[]}).
-%% Publish
--define(add_Publish(S,E), ets:insert(S#state.etsR, {E, publish})).
--define(del_Publish(S,E), ets:delete(S#state.etsR, E)).
--define(set_PublishType(S,T), S#state{publishType=T}).
-%% ID
--define(set_IdCounter(S,V), S#state{idCounter=V}).
--define(new_Id(S), 'CosNotification_Common':create_id(S#state.idCounter)).
-%% Event
--define(add_Event(S,E), cosNotification_eventDB:add_event(S#state.eventDB, E)).
--define(update_EventDB(S,Q), S#state{eventDB=
- cosNotification_eventDB:update(S#state.eventDB, Q)}).
-
--define(set_EventCounter(S,V), S#state{eventCounter=V}).
--define(add_to_EventCounter(S,V),S#state{eventCounter=S#state.eventCounter+V}).
--define(reset_EventCounter(S), S#state{eventCounter=0}).
--define(increase_EventCounter(S),S#state{eventCounter=(S#state.eventCounter+1)}).
--define(decrease_EventCounter(S),S#state{eventCounter=S#state.eventCounter-1}).
--define(add_ToEventCounter(S,A), S#state{eventCounter=(S#state.eventCounter+A)}).
--define(sub_FromEventCounter(S,_A), S#state{eventCounter=(S#state.eventCounter-_A)}).
--define(set_EventCounterTo(S,V), S#state{eventCounter=V}).
-
-%% MISC
--define(is_ANY(S), S#state.myType == 'PUSH_ANY').
--define(is_STRUCTURED(S), S#state.myType == 'PUSH_STRUCTURED').
--define(is_SEQUENCE(S), S#state.myType == 'PUSH_SEQUENCE').
--define(is_ANDOP(S), S#state.myOperator == 'AND_OP').
--define(is_UnConnected(S), S#state.client == undefined).
--define(is_Connected(S), S#state.client =/= undefined).
--define(is_PersistentConnection(S),
- ?not_GetConnectionReliability((S#state.qosLocal)) == ?not_Persistent).
--define(is_PersistentEvent(S),
- ?not_GetEventReliability((S#state.qosLocal)) == ?not_Persistent).
--define(is_BatchLimitReached(S), S#state.eventCounter >=
- ?not_GetMaximumBatchSize((S#state.qosLocal))).
-
-
-%%----------------------------------------------------------%
-%% function : handle_info, code_change
-%% Arguments:
-%% Returns :
-%% Effect : Functions demanded by the gen_server module.
-%%-----------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-handle_info(Info, State) ->
- ?DBG("INFO: ~p~n", [Info]),
- case Info of
- {'EXIT', Pid, Reason} when ?get_MyAdminPid(State)==Pid->
- ?DBG("PARENT ADMIN: ~p TERMINATED.~n",[Reason]),
- {stop, Reason, State};
- {'EXIT', _Pid, _Reason} ->
- ?DBG("PROXYPUSHCONSUMER: ~p TERMINATED.~n",[_Reason]),
- {noreply, State};
- _ ->
- {noreply, State}
- end.
-
-%%----------------------------------------------------------%
-%% function : init, terminate
-%% Arguments:
-%%-----------------------------------------------------------
-
-init(['PUSH_SEQUENCE', MyAdmin, MyAdminPid, InitQoS, LQS,
- MyChannel, Options, Operator]) ->
- process_flag(trap_exit, true),
- %% Only if MyType is 'PUSH_SEQUENCE' we need an ets to store events in.
- %% Otherwise we'll forward them at once. Why? We don't know when the next event
- %% is due.
- GCTime = 'CosNotification_Common':get_option(gcTime, Options,
- ?not_DEFAULT_SETTINGS),
- GCLimit = 'CosNotification_Common':get_option(gcLimit, Options,
- ?not_DEFAULT_SETTINGS),
- TimeRef = 'CosNotification_Common':get_option(timeService, Options,
- ?not_DEFAULT_SETTINGS),
- {ok, ?get_InitState('PUSH_SEQUENCE', MyAdmin, MyAdminPid, InitQoS, LQS, MyChannel,
- cosNotification_eventDB:create_db(LQS, GCTime, GCLimit, TimeRef),
- Operator)};
-init([MyType, MyAdmin, MyAdminPid, InitQoS, LQS, MyChannel, _Options, Operator]) ->
- process_flag(trap_exit, true),
- {ok, ?get_InitState(MyType, MyAdmin, MyAdminPid, InitQoS, LQS, MyChannel,
- undefined, Operator)}.
-
-terminate(_Reason, State) when ?is_UnConnected(State) ->
- ok;
-terminate(_Reason, State) ->
- Client = ?get_Client(State),
- case catch corba_object:is_nil(Client) of
- false when ?is_ANY(State) ->
- 'CosNotification_Common':disconnect('CosEventComm_PushSupplier',
- disconnect_push_supplier,
- Client);
- false when ?is_SEQUENCE(State) ->
- 'CosNotification_Common':disconnect('CosNotifyComm_SequencePushSupplier',
- disconnect_sequence_push_supplier,
- Client);
- false when ?is_STRUCTURED(State) ->
- 'CosNotification_Common':disconnect('CosNotifyComm_StructuredPushSupplier',
- disconnect_structured_push_supplier,
- Client);
- _ ->
- ok
- end.
-
-%%-----------------------------------------------------------
-%%----- CosNotifyChannelAdmin_ProxyConsumer attributes ------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% Attribute: '_get_MyType'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_MyType'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_MyType(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_MyAdmin'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_MyAdmin'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_MyAdmin(State), State}.
-
-%%-----------------------------------------------------------
-%%------- Exported external functions -----------------------
-%%-----------------------------------------------------------
-%%----- CosEventChannelAdmin::ProxyPushConsumer -------------
-%%----------------------------------------------------------%
-%% function : connect_push_supplier
-%% Arguments: Client - CosEventComm::PushSupplier
-%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
-%% {'EXCEPTION', #'TypeError'{}}
-%% Both exceptions from CosEventChannelAdmin!!!
-%%-----------------------------------------------------------
-connect_push_supplier(OE_THIS, OE_FROM, State, Client) ->
- connect_any_push_supplier(OE_THIS, OE_FROM, State, Client).
-
-%%----- CosNotifyChannelAdmin::ProxyPushConsumer ------------
-%%----------------------------------------------------------%
-%% function : connect_any_push_supplier
-%% Arguments: Client - CosEventComm::PushSupplier
-%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
-%% {'EXCEPTION', #'TypeError'{}}
-%% Both exceptions from CosEventChannelAdmin!!!
-%%-----------------------------------------------------------
-connect_any_push_supplier(_OE_THIS, _OE_FROM, State, Client) when ?is_ANY(State) ->
- ?not_TypeCheck(Client, 'CosEventComm_PushSupplier'),
- if
- ?is_Connected(State) ->
- corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
- true ->
- {reply, ok, ?set_Client(State, Client)}
- end;
-connect_any_push_supplier(_, _, _, _) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----- CosNotifyChannelAdmin::SequenceProxyPushConsumer ----
-%%----------------------------------------------------------%
-%% function : connect_sequence_push_supplier
-%% Arguments: Client - CosNotifyComm::SequencePushSupplier
-%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
-%% {'EXCEPTION', #'TypeError'{}}
-%%-----------------------------------------------------------
-connect_sequence_push_supplier(_OE_THIS, _OE_FROM, State, Client) when ?is_SEQUENCE(State) ->
- ?not_TypeCheck(Client, 'CosNotifyComm_SequencePushSupplier'),
- if
- ?is_Connected(State) ->
- corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
- true ->
- {reply, ok, ?set_Client(State, Client)}
- end;
-connect_sequence_push_supplier(_, _, _, _) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----- CosNotifyChannelAdmin::StructuredProxyPushConsumer --
-%%----------------------------------------------------------%
-%% function : connect_structured_push_supplier
-%% Arguments: Client - CosNotifyComm::StructuredPushSupplier
-%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
-%% {'EXCEPTION', #'TypeError'{}}
-%%-----------------------------------------------------------
-connect_structured_push_supplier(_OE_THIS, _OE_FROM, State, Client) when ?is_STRUCTURED(State) ->
- ?not_TypeCheck(Client, 'CosNotifyComm_StructuredPushSupplier'),
- if
- ?is_Connected(State) ->
- corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
- true ->
- {reply, ok, ?set_Client(State, Client)}
- end;
-connect_structured_push_supplier(_, _, _, _) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----- Inherit from CosNotifyChannelAdmin::ProxyConsumer ---
-%%----------------------------------------------------------%
-%% function : obtain_subscription_types
-%% Arguments: Mode - enum 'ObtainInfoMode' (CosNotifyChannelAdmin)
-%% Returns : CosNotification::EventTypeSeq
-%%-----------------------------------------------------------
-obtain_subscription_types(_OE_THIS, _OE_FROM, State, 'ALL_NOW_UPDATES_OFF') ->
- {reply, ?get_AllPublish(State), ?set_PublishType(State, false)};
-obtain_subscription_types(_OE_THIS, _OE_FROM, State, 'ALL_NOW_UPDATES_ON') ->
- {reply, ?get_AllPublish(State), ?set_PublishType(State, true)};
-obtain_subscription_types(_OE_THIS, _OE_FROM, State, 'NONE_NOW_UPDATES_OFF') ->
- {reply, [], ?set_PublishType(State, false)};
-obtain_subscription_types(_OE_THIS, _OE_FROM, State, 'NONE_NOW_UPDATES_ON') ->
- {reply, [], ?set_PublishType(State, true)};
-obtain_subscription_types(_,_,_,What) ->
- orber:dbg("[~p] PusherConsumer:obtain_subscription_types(~p);~n"
- "Incorrect enumerant", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : validate_event_qos
-%% Arguments: RequiredQoS - CosNotification::QoSProperties
-%% Returns : ok | {'EXCEPTION', #'UnsupportedQoS'{}}
-%% AvilableQoS - CosNotification::NamedPropertyRangeSeq (out)
-%%-----------------------------------------------------------
-validate_event_qos(_OE_THIS, _OE_FROM, State, RequiredQoS) ->
- AvilableQoS = 'CosNotification_Common':validate_event_qos(RequiredQoS,
- ?get_LocalQoS(State)),
- {reply, {ok, AvilableQoS}, State}.
-
-%%----- Inherit from CosNotification::QoSAdmin --------------
-%%----------------------------------------------------------%
-%% function : get_qos
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-get_qos(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_GlobalQoS(State), State}.
-
-%%----------------------------------------------------------%
-%% function : set_qos
-%% Arguments: QoS - CosNotification::QoSProperties, i.e.,
-%% [#'Property'{name, value}, ...] where name eq. string()
-%% and value eq. any().
-%% Returns : ok | {'EXCEPTION', CosNotification::UnsupportedQoS}
-%%-----------------------------------------------------------
-set_qos(_OE_THIS, _OE_FROM, State, QoS) ->
- {NewQoS, LQS} = 'CosNotification_Common':set_qos(QoS, ?get_BothQoS(State),
- proxy, ?get_MyAdmin(State),
- false),
- NewState = ?update_EventDB(State, LQS),
- {reply, ok, ?set_BothQoS(NewState, NewQoS, LQS)}.
-
-%%----------------------------------------------------------%
-%% function : validate_qos
-%% Arguments: Required_qos - CosNotification::QoSProperties
-%% [#'Property'{name, value}, ...] where name eq. string()
-%% and value eq. any().
-%% Returns : {'EXCEPTION', CosNotification::UnsupportedQoS}
-%% {ok, CosNotification::NamedPropertyRangeSeq}
-%%-----------------------------------------------------------
-validate_qos(_OE_THIS, _OE_FROM, State, Required_qos) ->
- QoS = 'CosNotification_Common':validate_qos(Required_qos, ?get_BothQoS(State),
- proxy, ?get_MyAdmin(State),
- false),
- {reply, {ok, QoS}, State}.
-
-%%----- Inherit from CosNotifyComm::NotifyPublish -----------
-%%----------------------------------------------------------%
-%% function : offer_change
-%% Arguments: Added - #'CosNotification_EventType'{}
-%% Removed - #'CosNotification_EventType'{}
-%% Returns : ok |
-%% {'EXCEPTION', #'CosNotifyComm_InvalidEventType'{}}
-%%-----------------------------------------------------------
-offer_change(_OE_THIS, _OE_FROM, State, Added, Removed) ->
- cosNotification_Filter:validate_types(Added),
- cosNotification_Filter:validate_types(Removed),
- %% On this "side" we don't really care about which
- %% type of events the client will supply.
- %% Perhaps, later on, if we want to check this against Filters
- %% associated with this object we may change this approach, i.e., if
- %% the filter will not allow passing certain event types. But the
- %% user should see to that that situation never occurs. It would add
- %% extra overhead. Also see PusherSupplier- and PullerSuppler-
- %% 'subscription_change'.
- update_publish(add, State, Added),
- update_publish(remove, State, Removed),
- case ?get_PublishType(State) of
- true ->
- %% Perhaps we should handle exception here?!
- %% Probably not. Better to stay "on-line".
- catch 'CosNotifyComm_NotifySubscribe':
- subscription_change(?get_Client(State), Added, Removed),
- ok;
- _->
- ok
- end,
- {reply, ok, State}.
-
-update_publish(_, _, [])->
- ok;
-update_publish(add, State, [H|T]) ->
- ?add_Publish(State, H),
- update_publish(add, State, T);
-update_publish(remove, State, [H|T]) ->
- ?del_Publish(State, H),
- update_publish(remove, State, T).
-
-%%----- Inherit from CosNotifyFilter::FilterAdmin -----------
-%%----------------------------------------------------------%
-%% function : add_filter
-%% Arguments: Filter - CosNotifyFilter::Filter
-%% Returns : FilterID - long
-%%-----------------------------------------------------------
-add_filter(_OE_THIS, _OE_FROM, State, Filter) ->
- 'CosNotification_Common':type_check(Filter, 'CosNotifyFilter_Filter'),
- FilterID = ?new_Id(State),
- NewState = ?set_IdCounter(State, FilterID),
- {reply, FilterID, ?add_Filter(NewState, FilterID, Filter)}.
-
-%%----------------------------------------------------------%
-%% function : remove_filter
-%% Arguments: FilterID - long
-%% Returns : ok
-%%-----------------------------------------------------------
-remove_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
- {reply, ok, ?del_Filter(State, FilterID)};
-remove_filter(_,_,_,What) ->
- orber:dbg("[~p] PusherConsumer:remove_filter(~p); Not an integer",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : get_filter
-%% Arguments: FilterID - long
-%% Returns : Filter - CosNotifyFilter::Filter |
-%% {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}
-%%-----------------------------------------------------------
-get_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
- {reply, ?get_Filter(State, FilterID), State};
-get_filter(_,_,_,What) ->
- orber:dbg("[~p] PusherConsumer:get_filter(~p); Not an integer",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : get_all_filters
-%% Arguments: -
-%% Returns : Filter - CosNotifyFilter::FilterIDSeq
-%%-----------------------------------------------------------
-get_all_filters(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_AllFilterID(State), State}.
-
-%%----------------------------------------------------------%
-%% function : remove_all_filters
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-remove_all_filters(_OE_THIS, _OE_FROM, State) ->
- {reply, ok, ?del_AllFilter(State)}.
-
-%%----- Inherit from CosEventComm::PushConsumer -------------
-%%----------------------------------------------------------%
-%% function : disconnect_push_consumer
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-disconnect_push_consumer(_OE_THIS, _OE_FROM, State) ->
- {stop, normal, ok, ?set_Unconnected(State)}.
-
-%%----------------------------------------------------------%
-%% function : push
-%% Arguments: AnyEvent
-%% Returns : ok |
-%%-----------------------------------------------------------
-push(OE_THIS, OE_FROM, State, Event) when ?is_ANY(State) ->
- corba:reply(OE_FROM, ok),
- case {?not_isConvertedStructured(Event),
- cosNotification_eventDB:filter_events([Event], ?get_AllFilter(State))} of
- {_, {[],_}} when ?is_ANDOP(State) ->
- {noreply, State};
- {true, {[],[_]}} ->
- %% Is OR and converted, change back and forward to Admin
- forward(seq, ?get_MyAdmin(State), State, [any:get_value(Event)],
- 'MATCH', OE_THIS);
- {_, {[],[_]}} ->
- %% Is OR and not converted, forward to Admin
- forward(any, ?get_MyAdmin(State), State, Event, 'MATCH', OE_THIS);
- {true, {[_],_}} when ?is_ANDOP(State) ->
- %% Is AND and converted, change back and forward to Admin
- forward(seq, ?get_MyAdmin(State), State, [any:get_value(Event)],
- 'MATCH', OE_THIS);
- {true, {[_],_}} ->
- %% Is OR and converted, change back and forward to Channel
- forward(seq, ?get_MyChannel(State), State, [any:get_value(Event)],
- 'MATCHED', OE_THIS);
- {_, {[_],_}} when ?is_ANDOP(State) ->
- %% Is AND and not converted, forward to Admin
- forward(any, ?get_MyAdmin(State), State, Event, 'MATCH', OE_THIS);
- _ ->
- %% Is OR and not converted, forward to Channel
- forward(any, ?get_MyChannel(State), State, Event, 'MATCHED', OE_THIS)
- end;
-push(_, _, _, _) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----- Inherit from CosNotifyComm::SequencePushConsumer ----
-%%----------------------------------------------------------%
-%% function : disconnect_sequence_push_consumer
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-disconnect_sequence_push_consumer(_OE_THIS, _OE_FROM, State) ->
- {stop, normal, ok, ?set_Unconnected(State)}.
-
-%%----------------------------------------------------------%
-%% function : push_structured_events
-%% Arguments: CosNotification::EventBatch
-%% Returns : ok |
-%%-----------------------------------------------------------
-push_structured_events(OE_THIS, OE_FROM, State, Events) when ?is_SEQUENCE(State) ->
- corba:reply(OE_FROM, ok),
- %% We cannot convert parts of the sequence to any, event though they
- %% are converted from any to structured. Would be 'impossible' to send.
- case cosNotification_eventDB:filter_events(Events, ?get_AllFilter(State)) of
- {[],_} when ?is_ANDOP(State) ->
- {noreply, State};
- {[],Failed} ->
- forward(seq, ?get_MyAdmin(State), State, Failed, 'MATCH', OE_THIS);
- {Passed, _} when ?is_ANDOP(State) ->
- forward(seq, ?get_MyAdmin(State), State, Passed, 'MATCH', OE_THIS);
- {Passed, []} ->
- forward(seq, ?get_MyChannel(State), State, Passed, 'MATCHED', OE_THIS);
- {Passed, Failed} ->
- %% Is OR, send Passed to channel and Failed to Admin.
- forward(seq, ?get_MyChannel(State), State, Passed, 'MATCHED', OE_THIS),
- forward(seq, ?get_MyAdmin(State), State, Failed, 'MATCH', OE_THIS)
- end;
-push_structured_events(_,_,_,_) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----- Inherit from CosNotifyComm::StructuredPushConsumer --
-%%----------------------------------------------------------%
-%% function : disconnect_structured_push_consumer
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-disconnect_structured_push_consumer(_OE_THIS, _OE_FROM, State) ->
- {stop, normal, ok, ?set_Unconnected(State)}.
-
-%%----------------------------------------------------------%
-%% function : push_structured_event
-%% Arguments: CosNotification::StructuredEvent
-%% Returns : ok |
-%%-----------------------------------------------------------
-push_structured_event(OE_THIS, OE_FROM, State, Event) when ?is_STRUCTURED(State) ->
- corba:reply(OE_FROM, ok),
- case {?not_isConvertedAny(Event),
- cosNotification_eventDB:filter_events([Event], ?get_AllFilter(State))} of
- {_, {[],_}} when ?is_ANDOP(State) ->
- {noreply, State};
- {true, {[],[_]}} ->
- %% Is OR and converted, change back and forward to Admin
- forward(any, ?get_MyAdmin(State), State,
- Event#'CosNotification_StructuredEvent'.remainder_of_body,
- 'MATCH', OE_THIS);
- {_, {[],[_]}} ->
- %% Is OR and not converted, forward to Admin
- forward(seq, ?get_MyAdmin(State), State, [Event], 'MATCH', OE_THIS);
- {true, {[_],_}} when ?is_ANDOP(State) ->
- %% Is AND and converted, change back and forward to Admin
- forward(any, ?get_MyAdmin(State), State,
- Event#'CosNotification_StructuredEvent'.remainder_of_body,
- 'MATCH', OE_THIS);
- {true, {[_],_}} ->
- %% Is OR and converted, change back and forward to Channel
- forward(any, ?get_MyChannel(State), State,
- Event#'CosNotification_StructuredEvent'.remainder_of_body,
- 'MATCHED', OE_THIS);
- {_, {[_],_}} when ?is_ANDOP(State) ->
- %% Is AND and not converted, forward to Admin
- forward(seq, ?get_MyAdmin(State), State, [Event], 'MATCH', OE_THIS);
- _ ->
- %% Is OR and not converted, forward to Channel
- forward(seq, ?get_MyChannel(State), State, [Event], 'MATCHED', OE_THIS)
- end;
-push_structured_event(_,_,_,_) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-find_obj({value, {_, Obj}}) -> Obj;
-find_obj(_) -> {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}.
-
-find_ids(List) -> find_ids(List, []).
-find_ids([], Acc) -> Acc;
-find_ids([{I,_}|T], Acc) -> find_ids(T, [I|Acc]);
-find_ids(What, _) ->
- orber:dbg("[~p] PusherConsumer:find_ids();~n"
- "Id corrupt: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
-
-%% Delete a single object.
-%% The list don not differ, i.e., no filter removed, raise exception.
-delete_obj(List,List) -> corba:raise(#'CosNotifyFilter_FilterNotFound'{});
-delete_obj(List,_) -> List.
-
-%% Forward events
-forward(any, SendTo, State, Event, Status, OE_THIS) ->
- case catch oe_CosNotificationComm_Event:callAny(SendTo, Event, Status) of
- ok ->
- ?DBG("PROXY FORWARD ANY: ~p~n",[Event]),
- {noreply, State};
- {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') orelse
- is_record(E, 'NO_PERMISSION') orelse
- is_record(E, 'CosEventComm_Disconnected') ->
- orber:dbg("[~p] PusherConsumer:forward();~n"
- "Admin/Channel no longer exists; terminating and dropping: ~p",
- [?LINE, Event], ?DEBUG_LEVEL),
- 'CosNotification_Common':notify([{proxy, OE_THIS},
- {client, ?get_Client(State)},
- {reason, {'EXCEPTION', E}}]),
- {stop, normal, State};
- R when ?is_PersistentConnection(State) ->
- orber:dbg("[~p] PusherConsumer:forward();~n"
- "Admin/Channel respond incorrect: ~p~n"
- "Dropping: ~p", [?LINE, R, Event], ?DEBUG_LEVEL),
- {noreply, State};
- R ->
- orber:dbg("[~p] PusherConsumer:forward();~n"
- "Admin/Channel respond incorrect: ~p~n"
- "Terminating and dropping: ~p",
- [?LINE, R, Event], ?DEBUG_LEVEL),
- 'CosNotification_Common':notify([{proxy, OE_THIS},
- {client, ?get_Client(State)},
- {reason, R}]),
- {stop, normal, State}
- end;
-forward(seq, SendTo, State, Event, Status, OE_THIS) ->
- case catch oe_CosNotificationComm_Event:callSeq(SendTo, Event, Status) of
- ok ->
- {noreply, State};
- {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') orelse
- is_record(E, 'NO_PERMISSION') orelse
- is_record(E, 'CosEventComm_Disconnected') ->
- ?DBG("ADMIN NO LONGER EXIST; DROPPING: ~p~n", [Event]),
- 'CosNotification_Common':notify([{proxy, OE_THIS},
- {client, ?get_Client(State)},
- {reason, {'EXCEPTION', E}}]),
- {stop, normal, State};
- R when ?is_PersistentConnection(State) ->
- orber:dbg("[~p] PusherConsumer:forward();~n"
- "Admin/Channel respond incorrect: ~p~n"
- "Dropping: ~p", [?LINE, R, Event], ?DEBUG_LEVEL),
- {noreply, State};
- R ->
- orber:dbg("[~p] PusherConsumer:forward();~n"
- "Admin/Channel respond incorrect: ~p~n"
- "Terminating and dropping: ~p",
- [?LINE, R, Event], ?DEBUG_LEVEL),
- 'CosNotification_Common':notify([{proxy, OE_THIS},
- {client, ?get_Client(State)},
- {reason, R}]),
- {stop, normal, State}
- end.
-
-%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/PusherSupplier_impl.erl b/lib/cosNotification/src/PusherSupplier_impl.erl
deleted file mode 100644
index d3e44f3ef9..0000000000
--- a/lib/cosNotification/src/PusherSupplier_impl.erl
+++ /dev/null
@@ -1,1053 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : PusherSupplier_impl.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module('PusherSupplier_impl').
-
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-%% cosEvent files.
--include_lib("cosEvent/include/CosEventChannelAdmin.hrl").
--include_lib("cosEvent/include/CosEventComm.hrl").
-%% Application files
--include("CosNotification.hrl").
--include("CosNotifyChannelAdmin.hrl").
--include("CosNotifyComm.hrl").
--include("CosNotifyFilter.hrl").
-
--include("CosNotification_Definitions.hrl").
-
-%%--------------- EXPORTS ------------------------------------
-%%--------------- External -----------------------------------
-%%----- CosNotifyChannelAdmin::ProxyPushSupplier -------------
--export([connect_any_push_consumer/4]).
-
-%%----- CosNotifyChannelAdmin::StructuredProxyPushSupplier ---
--export([connect_structured_push_consumer/4]).
-
-%%----- CosNotifyChannelAdmin::SequenceProxyPushSupplier -----
--export([connect_sequence_push_consumer/4]).
-
-%%----- CosNotifyChannelAdmin::*ProxyPushSupplier ------------
--export([suspend_connection/3,
- resume_connection/3]).
-
-%%----- Inherit from CosNotifyChannelAdmin::ProxySupplier ----
--export([obtain_offered_types/4,
- validate_event_qos/4]).
-
-%%----- Inherit from CosNotification::QoSAdmin ---------------
--export([get_qos/3,
- set_qos/4,
- validate_qos/4]).
-
-%%----- Inherit from CosNotifyComm::NotifySubscribe ----------
--export([subscription_change/5]).
-
-%%----- Inherit from CosNotifyFilter::FilterAdmin ------------
--export([add_filter/4,
- remove_filter/4,
- get_filter/4,
- get_all_filters/3,
- remove_all_filters/3]).
-
-%%----- Inherit from CosEventComm::PushSupplier -------------
--export([disconnect_push_supplier/3]).
-
-%%----- Inherit from CosNotifyComm::StructuredPushSupplier --
--export([disconnect_structured_push_supplier/3]).
-
-%%----- Inherit from CosNotifyComm::SequencePushSupplier ----
--export([disconnect_sequence_push_supplier/3]).
-
-%%----- Inherit from CosEventChannelAdmin::ProxyPushSupplier
--export([connect_push_consumer/4]).
-
-%% Attributes (external) CosNotifyChannelAdmin::ProxySupplier
--export(['_get_MyType'/3,
- '_get_MyAdmin'/3,
- '_get_priority_filter'/3,
- '_set_priority_filter'/4,
- '_get_lifetime_filter'/3,
- '_set_lifetime_filter'/4]).
-
-%%--------------- Internal -----------------------------------
-%%----- Inherit from cosNotificationComm ---------------------
--export([callAny/5,
- callSeq/5]).
-
-%%--------------- gen_server specific exports ----------------
--export([handle_info/2, code_change/3]).
--export([init/1, terminate/2]).
-
-%%--------------- LOCAL DEFINITIONS --------------------------
-%% Data structures
--record(state, {myType,
- myAdmin,
- myAdminPid,
- myChannel,
- myFilters = [],
- myOperator,
- idCounter = 0,
- prioFil,
- lifetFil,
- client,
- qosGlobal,
- qosLocal,
- suspended = false,
- pacingTimer,
- subscribeType = false,
- subscribeData = true,
- etsR,
- eventDB,
- this,
- maxCache,
- cacheTimeout,
- cacheInterval}).
-
-%% Data structures constructors
--define(get_InitState(_MyT, _MyA, _MyAP, _QS, _LQS, _Ch, _MyOp, _GT, _GL, _TR),
- #state{myType = _MyT,
- myAdmin = _MyA,
- myAdminPid= _MyAP,
- qosGlobal = _QS,
- qosLocal = _LQS,
- myChannel = _Ch,
- myOperator=_MyOp,
- etsR = ets:new(oe_ets, [set, protected]),
- eventDB = cosNotification_eventDB:create_db(_LQS, _GT, _GL, _TR),
- maxCache = cosNotificationApp:max_events()}).
-
-%% Data structures selectors
-%%-------------- Data structures selectors -----------------
-%% Attributes
--define(get_MyType(S), S#state.myType).
--define(get_MyAdmin(S), S#state.myAdmin).
--define(get_MyAdminPid(S), S#state.myAdminPid).
--define(get_MyChannel(S), S#state.myChannel).
--define(get_MyOperator(S), S#state.myOperator).
--define(get_PrioFil(S), S#state.prioFil).
--define(get_LifeTFil(S), S#state.lifetFil).
-%% Client Object
--define(get_Client(S), S#state.client).
-%% QoS
--define(get_GlobalQoS(S), S#state.qosGlobal).
--define(get_LocalQoS(S), S#state.qosLocal).
--define(get_BothQoS(S), {S#state.qosGlobal, S#state.qosLocal}).
-%% Filters
--define(get_Filter(S, I), find_obj(lists:keysearch(I, 1, S#state.myFilters))).
--define(get_AllFilter(S), S#state.myFilters).
--define(get_AllFilterID(S), find_ids(S#state.myFilters)).
-%% Amin
--define(get_PacingTimer(S), S#state.pacingTimer).
--define(get_PacingInterval(S), round(?not_GetPacingInterval((S#state.qosLocal))/10000000)).
--define(get_BatchLimit(S), ?not_GetMaximumBatchSize((S#state.qosLocal))).
-%% Subscribe
--define(get_AllSubscribe(S), lists:flatten(ets:match(S#state.etsR,
- {'$1',subscribe}))).
--define(get_SubscribeType(S), S#state.subscribeType).
--define(get_SubscribeData(S), S#state.subscribeData).
-%% ID
--define(get_IdCounter(S), S#state.idCounter).
--define(get_SubscribeDB(S), S#state.etsR).
-%% Event
--define(is_PersistentConnection(S),
- (?not_GetConnectionReliability((S#state.qosLocal)) == ?not_Persistent)).
--define(is_PersistentEvent(S),
- (?not_GetEventReliability((S#state.qosLocal)) == ?not_Persistent)).
-
--define(get_Event(S), cosNotification_eventDB:get_event(S#state.eventDB,
- false)).
-% (not ?is_PersistentEvent(S)))).
--define(get_Events(S,M), cosNotification_eventDB:get_events(S#state.eventDB, M, false)).
-% (not ?is_PersistentEvent(S)))).
-
-%%-------------- Data structures modifiers -----------------
-%% Attributes
--define(set_PrioFil(S,D), S#state{prioFil=D}).
--define(set_LifeTFil(S,D), S#state{lifetFil=D}).
-%% Client Object
--define(set_Client(S,D), S#state{client=D}).
--define(del_Client(S), S#state{client=undefined}).
--define(set_Unconnected(S), S#state{client=undefined}).
--define(set_Suspended(S), S#state{suspended=true}).
--define(set_NotSuspended(S), S#state{suspended=false}).
-%% QoS
--define(set_LocalQoS(S,D), S#state{qosLocal=D}).
--define(set_GlobalQoS(S,D), S#state{qosGlobal=D}).
--define(set_BothQoS(S,GD,LD), S#state{qosGlobal=GD, qosLocal=LD}).
-%% Filters
--define(add_Filter(S,I,O), S#state{myFilters=[{I,O}|S#state.myFilters]}).
--define(del_Filter(S,I), S#state{myFilters=
- delete_obj(lists:keydelete(I, 1, S#state.myFilters),
- S#state.myFilters)}).
--define(del_AllFilter(S), S#state{myFilters=[]}).
-%% Admin
--define(set_PacingTimer(S,T), S#state{pacingTimer=T}).
-%% Publish
-%% Subscribe
--define(add_Subscribe(S,E), ets:insert(S#state.etsR, {E, subscribe})).
--define(del_Subscribe(S,E), ets:delete(S#state.etsR, E)).
--define(set_SubscribeType(S,T), S#state{subscribeType=T}).
--define(set_SubscribeData(S,D), S#state{subscribeData=D}).
-%% ID
--define(set_IdCounter(S,V), S#state{idCounter=V}).
--define(new_Id(S), 'CosNotification_Common':create_id(S#state.idCounter)).
-%% Events
--define(add_Event(S,E), catch cosNotification_eventDB:
- add_event(S#state.eventDB, E, S#state.lifetFil, S#state.prioFil)).
--define(addAndGet_Event(S,E), catch cosNotification_eventDB:
- add_and_get_event(S#state.eventDB, E, S#state.lifetFil, S#state.prioFil,
- false)).
-% ?is_PersistentEvent(S))).
--define(update_EventDB(S,Q), S#state{eventDB=
- cosNotification_eventDB:update(S#state.eventDB, Q)}).
-
-
-%%-------------- MISC ----------------------------------------
--define(is_ANY(S), S#state.myType == 'PUSH_ANY').
--define(is_STRUCTURED(S), S#state.myType == 'PUSH_STRUCTURED').
--define(is_SEQUENCE(S), S#state.myType == 'PUSH_SEQUENCE').
--define(is_ANDOP(S), S#state.myOperator == 'AND_OP').
--define(is_UnConnected(S), S#state.client == undefined).
--define(is_Connected(S), S#state.client =/= undefined).
--define(is_Suspended(S), S#state.suspended == true).
--define(is_NotSuspended(S), S#state.suspended == false).
--define(is_BatchLimitReached(S), cosNotification_eventDB:status(S#state.eventDB,
- {batchLimit,
- ?not_GetMaximumBatchSize((S#state.qosLocal))})).
--define(has_Filters(S), S#state.myFilters =/= []).
-
-%%----------------------------------------------------------%
-%% function : handle_info, code_change
-%% Arguments:
-%% Returns :
-%% Effect : Functions demanded by the gen_server module.
-%%-----------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-handle_info(Info, #state{cacheTimeout = Timeout,
- cacheInterval = Interval} = State) ->
- ?DBG("INFO: ~p~n", [Info]),
- case Info of
- {'EXIT', Pid, Reason} when ?get_MyAdminPid(State)==Pid ->
- ?DBG("PARENT ADMIN: ~p TERMINATED.~n",[Reason]),
- {stop, Reason, State};
- {'EXIT', _Pid, _Reason} ->
- ?DBG("PROXYPUSHSUPPLIER: ~p TERMINATED.~n",[_Reason]),
- {noreply, State};
- pacing ->
- lookup_and_push(State, true);
- cacheInterval ->
- lookup_and_push(State, true);
- cacheTimeout when Timeout == undefined, Interval == undefined ->
- %% Late message, do not terminate
- {noreply, State};
- cacheTimeout ->
- 'CosNotification_Common':notify([{proxy, State#state.this},
- {client, State#state.client},
- {reason,
- {timer, "Reached upper limit"}}]),
- {stop, normal, State};
- _ ->
- {noreply, State}
- end.
-
-%%----------------------------------------------------------%
-%% function : init, terminate
-%% Arguments:
-%%-----------------------------------------------------------
-
-init([MyType, MyAdmin, MyAdminPid, InitQoS, LQS, MyChannel, Options, Operator]) ->
- process_flag(trap_exit, true),
- GCTime = 'CosNotification_Common':get_option(gcTime, Options,
- ?not_DEFAULT_SETTINGS),
- GCLimit = 'CosNotification_Common':get_option(gcLimit, Options,
- ?not_DEFAULT_SETTINGS),
- TimeRef = 'CosNotification_Common':get_option(timeService, Options,
- ?not_DEFAULT_SETTINGS),
- timer:start(),
- {ok, ?get_InitState(MyType, MyAdmin, MyAdminPid,
- InitQoS, LQS, MyChannel, Operator, GCTime, GCLimit, TimeRef)}.
-
-terminate(_Reason, State) when ?is_UnConnected(State) ->
- stop_timer(State#state.cacheTimeout),
- stop_timer(State#state.cacheInterval),
- stop_timer(State#state.pacingTimer),
- %% We are not connected to a Client. Hence, no need to invoke disconnect.
- ok;
-terminate(_Reason, State) when ?is_ANY(State) ->
- stop_timer(State#state.cacheTimeout),
- stop_timer(State#state.cacheInterval),
- stop_timer(State#state.pacingTimer),
- 'CosNotification_Common':disconnect('CosEventComm_PushConsumer',
- disconnect_push_consumer,
- ?get_Client(State));
-terminate(_Reason, State) when ?is_SEQUENCE(State) ->
- stop_timer(State#state.cacheTimeout),
- stop_timer(State#state.cacheInterval),
- stop_timer(State#state.pacingTimer),
- 'CosNotification_Common':disconnect('CosNotifyComm_SequencePushConsumer',
- disconnect_sequence_push_consumer,
- ?get_Client(State));
-terminate(_Reason, State) when ?is_STRUCTURED(State) ->
- stop_timer(State#state.cacheTimeout),
- stop_timer(State#state.cacheInterval),
- stop_timer(State#state.pacingTimer),
- 'CosNotification_Common':disconnect('CosNotifyComm_StructuredPushConsumer',
- disconnect_structured_push_consumer,
- ?get_Client(State)).
-
-%%-----------------------------------------------------------
-%%----- CosNotifyChannelAdmin_ProxySupplier attributes ------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% Attribute: '_get_MyType'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_MyType'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_MyType(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_MyAdmin'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_MyAdmin'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_MyAdmin(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_*et_priority_filter'
-%% Type : read/write
-%% Returns :
-%%-----------------------------------------------------------
-'_get_priority_filter'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_PrioFil(State), State}.
-'_set_priority_filter'(_OE_THIS, _OE_FROM, State, PrioF) ->
- {reply, ok, ?set_PrioFil(State, PrioF)}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_*et_lifetime_filter'
-%% Type : read/write
-%% Returns :
-%%-----------------------------------------------------------
-'_get_lifetime_filter'(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_LifeTFil(State), State}.
-'_set_lifetime_filter'(_OE_THIS, _OE_FROM, State, LifeTF) ->
- {reply, ok, ?set_LifeTFil(State, LifeTF)}.
-
-%%-----------------------------------------------------------
-%%------- Exported external functions -----------------------
-%%-----------------------------------------------------------
-%%----- CosEventChannelAdmin::ProxyPushSupplier -------------
-%%----------------------------------------------------------%
-%% function : connect_push_consumer
-%% Arguments: Client - CosEventComm::PushConsumer
-%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
-%% {'EXCEPTION', #'TypeError'{}}
-%% Both exceptions from CosEventChannelAdmin!!!!
-%%-----------------------------------------------------------
-connect_push_consumer(OE_THIS, OE_FROM, State, Client) ->
- connect_any_push_consumer(OE_THIS, OE_FROM, State, Client).
-
-%%----- CosNotifyChannelAdmin::ProxyPushSupplier ------------
-%%----------------------------------------------------------%
-%% function : connect_any_push_consumer
-%% Arguments: Client - CosEventComm::PushConsumer
-%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
-%% {'EXCEPTION', #'TypeError'{}}
-%% Both exceptions from CosEventChannelAdmin!!!!
-%%-----------------------------------------------------------
-connect_any_push_consumer(OE_THIS, _OE_FROM, State, Client) when ?is_ANY(State) ->
- 'CosNotification_Common':type_check(Client, 'CosEventComm_PushConsumer'),
- if
- ?is_Connected(State) ->
- corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
- true ->
- {reply, ok, State#state{client = Client, this = OE_THIS}}
- end;
-connect_any_push_consumer(_, _, _, _) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----- CosNotifyChannelAdmin::SequenceProxyPushSupplier ----
-%%----------------------------------------------------------%
-%% function : connect_sequence_push_consumer
-%% Arguments: Client - CosNotifyComm::SequencePushConsumer
-%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
-%% {'EXCEPTION', #'TypeError'{}}
-%%-----------------------------------------------------------
-connect_sequence_push_consumer(OE_THIS, _OE_FROM, State, Client) when ?is_SEQUENCE(State) ->
- 'CosNotification_Common':type_check(Client,
- 'CosNotifyComm_SequencePushConsumer'),
- if
- ?is_Connected(State) ->
- corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
- true ->
- NewState = start_timer(State),
- {reply, ok, NewState#state{client = Client, this = OE_THIS}}
- end;
-connect_sequence_push_consumer(_, _, _, _) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----- CosNotifyChannelAdmin::StructuredProxyPushSupplier ---
-%%----------------------------------------------------------%
-%% function : connect_structured_push_consumer
-%% Arguments: Client - CosNotifyComm::StructuredPushConsumer
-%% Returns : ok | {'EXCEPTION', #'AlreadyConnected'{}} |
-%% {'EXCEPTION', #'TypeError'{}}
-%%-----------------------------------------------------------
-connect_structured_push_consumer(OE_THIS, _OE_FROM, State, Client) when ?is_STRUCTURED(State) ->
- 'CosNotification_Common':type_check(Client,
- 'CosNotifyComm_StructuredPushConsumer'),
- if
- ?is_Connected(State) ->
- corba:raise(#'CosEventChannelAdmin_AlreadyConnected'{});
- true ->
- {reply, ok, State#state{client = Client, this = OE_THIS}}
- end;
-connect_structured_push_consumer(_, _, _, _) ->
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----- CosNotifyChannelAdmin::*ProxyPushSupplier -----------
-%%----------------------------------------------------------%
-%% function : suspend_connection
-%% Arguments:
-%% Returns : ok | {'EXCEPTION', #'ConnectionAlreadyInactive'{}} |
-%% {'EXCEPTION', #'NotConneced'{}}
-%%-----------------------------------------------------------
-suspend_connection(_OE_THIS, _OE_FROM, State) when ?is_Connected(State) ->
- if
- ?is_Suspended(State) ->
- corba:raise(#'CosNotifyChannelAdmin_ConnectionAlreadyInactive'{});
- true ->
- stop_timer(State#state.pacingTimer),
- {reply, ok, State#state{pacingTimer = undefined,
- suspended=true}}
- end;
-suspend_connection(_,_,_)->
- corba:raise(#'CosNotifyChannelAdmin_NotConnected'{}).
-
-%%----------------------------------------------------------%
-%% function : resume_connection
-%% Arguments:
-%% Returns : ok | {'EXCEPTION', #'ConnectionAlreadyActive'{}} |
-%% {'EXCEPTION', #'NotConneced'{}}
-%%-----------------------------------------------------------
-resume_connection(_OE_THIS, OE_FROM, State) when ?is_Connected(State) ->
- if
- ?is_NotSuspended(State) ->
- corba:raise(#'CosNotifyChannelAdmin_ConnectionAlreadyActive'{});
- true ->
- corba:reply(OE_FROM, ok),
- if
- ?is_SEQUENCE(State) ->
- start_timer(State);
- true ->
- ok
- end,
- lookup_and_push(?set_NotSuspended(State))
- end;
-resume_connection(_,_,_) ->
- corba:raise(#'CosNotifyChannelAdmin_NotConnected'{}).
-
-%%----- Inherit from CosNotifyChannelAdmin::ProxySupplier ---
-%%----------------------------------------------------------%
-%% function : obtain_offered_types
-%% Arguments: Mode - enum 'ObtainInfoMode' (CosNotifyChannelAdmin)
-%% Returns : CosNotification::EventTypeSeq
-%%-----------------------------------------------------------
-obtain_offered_types(_OE_THIS, _OE_FROM, State, 'ALL_NOW_UPDATES_OFF') ->
- {reply, ?get_AllSubscribe(State), ?set_SubscribeType(State, false)};
-obtain_offered_types(_OE_THIS, _OE_FROM, State, 'ALL_NOW_UPDATES_ON') ->
- {reply, ?get_AllSubscribe(State), ?set_SubscribeType(State, true)};
-obtain_offered_types(_OE_THIS, _OE_FROM, State, 'NONE_NOW_UPDATES_OFF') ->
- {reply, [], ?set_SubscribeType(State, false)};
-obtain_offered_types(_OE_THIS, _OE_FROM, State, 'NONE_NOW_UPDATES_ON') ->
- {reply, [], ?set_SubscribeType(State, true)};
-obtain_offered_types(_,_,_,What) ->
- orber:dbg("[~p] PusherSupplier:obtain_offered_types(~p);~n"
- "Bad enumerant", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_OPERATION'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : validate_event_qos
-%% Arguments: RequiredQoS - CosNotification::QoSProperties
-%% Returns : ok | {'EXCEPTION', #'UnsupportedQoS'{}}
-%% AvilableQoS - CosNotification::NamedPropertyRangeSeq (out)
-%%-----------------------------------------------------------
-validate_event_qos(_OE_THIS, _OE_FROM, State, RequiredQoS) ->
- AvilableQoS = 'CosNotification_Common':validate_event_qos(RequiredQoS,
- ?get_LocalQoS(State)),
- {reply, {ok, AvilableQoS}, State}.
-
-%%----- Inherit from CosNotification::QoSAdmin --------------
-%%----------------------------------------------------------%
-%% function : get_qos
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-get_qos(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_GlobalQoS(State), State}.
-
-%%----------------------------------------------------------%
-%% function : set_qos
-%% Arguments: QoS - CosNotification::QoSProperties, i.e.,
-%% [#'Property'{name, value}, ...] where name eq. string()
-%% and value eq. any().
-%% Returns : ok | {'EXCEPTION', CosNotification::UnsupportedQoS}
-%%-----------------------------------------------------------
-set_qos(_OE_THIS, _OE_FROM, State, QoS) ->
- {NewQoS, LQS} = 'CosNotification_Common':set_qos(QoS, ?get_BothQoS(State),
- proxy, ?get_MyAdmin(State),
- false),
- NewState = ?update_EventDB(State, LQS),
- {reply, ok, ?set_BothQoS(NewState, NewQoS, LQS)}.
-
-%%----------------------------------------------------------%
-%% function : validate_qos
-%% Arguments: Required_qos - CosNotification::QoSProperties
-%% [#'Property'{name, value}, ...] where name eq. string()
-%% and value eq. any().
-%% Returns : {'EXCEPTION', CosNotification::UnsupportedQoS}
-%% {ok, CosNotification::NamedPropertyRangeSeq}
-%%-----------------------------------------------------------
-validate_qos(_OE_THIS, _OE_FROM, State, Required_qos) ->
- QoS = 'CosNotification_Common':validate_qos(Required_qos, ?get_BothQoS(State),
- proxy, ?get_MyAdmin(State),
- false),
- {reply, {ok, QoS}, State}.
-
-%%----- Inherit from CosNotifyComm::NotifySubscribe ---------
-%%----------------------------------------------------------%
-%% function : subscription_change
-%% Arguments: Added - #'CosNotification_EventType'{}
-%% Removed - #'CosNotification_EventType'{}
-%% Returns : ok |
-%% {'EXCEPTION', #'CosNotifyComm_InvalidEventType'{}}
-%%-----------------------------------------------------------
-subscription_change(_OE_THIS, _OE_FROM, State, Added, Removed) ->
- cosNotification_Filter:validate_types(Added),
- cosNotification_Filter:validate_types(Removed),
- %% On this "side", we care about which type of events the client
- %% will require, since the client (or an agent) clearly stated
- %% that it's only interested in these types of events.
- %% Also see PusherConsumer- and PullerConsumer-'offer_change'.
- update_subscribe(remove, State, Removed),
- CurrentSub = ?get_AllSubscribe(State),
- NewState =
- case cosNotification_Filter:check_types(Added++CurrentSub) of
- true ->
- %% Types supplied does in some way cause all events to be valid.
- %% Smart? Would have been better to not supply any at all.
- ?set_SubscribeData(State, true);
- {ok, Which, WC} ->
- ?set_SubscribeData(State, {Which, WC})
- end,
- update_subscribe(add, NewState, Added),
- case ?get_SubscribeType(NewState) of
- true ->
- %% Perhaps we should handle exception here?!
- %% Probably not. Better to stay "on-line".
- catch 'CosNotifyComm_NotifyPublish':
- offer_change(?get_Client(NewState), Added, Removed),
- ok;
- _->
- ok
- end,
- {reply, ok, NewState}.
-
-update_subscribe(_, _, [])->
- ok;
-update_subscribe(add, State, [H|T]) ->
- ?add_Subscribe(State, H),
- update_subscribe(add, State, T);
-update_subscribe(remove, State, [H|T]) ->
- ?del_Subscribe(State, H),
- update_subscribe(remove, State, T).
-
-%%----- Inherit from CosNotifyFilter::FilterAdmin -----------
-%%----------------------------------------------------------%
-%% function : add_filter
-%% Arguments: Filter - CosNotifyFilter::Filter
-%% Returns : FilterID - long
-%%-----------------------------------------------------------
-add_filter(_OE_THIS, _OE_FROM, State, Filter) ->
- 'CosNotification_Common':type_check(Filter, 'CosNotifyFilter_Filter'),
- FilterID = ?new_Id(State),
- NewState = ?set_IdCounter(State, FilterID),
- {reply, FilterID, ?add_Filter(NewState, FilterID, Filter)}.
-
-%%----------------------------------------------------------%
-%% function : remove_filter
-%% Arguments: FilterID - long
-%% Returns : ok
-%%-----------------------------------------------------------
-remove_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
- {reply, ok, ?del_Filter(State, FilterID)};
-remove_filter(_,_,_,What) ->
- orber:dbg("[~p] PusherSupplier:remove_filter(~p); Not an integer",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : get_filter
-%% Arguments: FilterID - long
-%% Returns : Filter - CosNotifyFilter::Filter |
-%% {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}
-%%-----------------------------------------------------------
-get_filter(_OE_THIS, _OE_FROM, State, FilterID) when is_integer(FilterID) ->
- {reply, ?get_Filter(State, FilterID), State};
-get_filter(_,_,_,What) ->
- orber:dbg("[~p] PusherSupplier:get_filter(~p); Not an integer",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : get_all_filters
-%% Arguments: -
-%% Returns : Filter - CosNotifyFilter::FilterIDSeq
-%%-----------------------------------------------------------
-get_all_filters(_OE_THIS, _OE_FROM, State) ->
- {reply, ?get_AllFilterID(State), State}.
-
-%%----------------------------------------------------------%
-%% function : remove_all_filters
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-remove_all_filters(_OE_THIS, _OE_FROM, State) ->
- {reply, ok, ?del_AllFilter(State)}.
-
-
-%%----- Inherit from CosEventComm::PushSupplier -------------
-%%----------------------------------------------------------%
-%% function : disconnect_push_supplier
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-disconnect_push_supplier(_OE_THIS, _OE_FROM, State) ->
- {stop, normal, ok, ?set_Unconnected(State)}.
-
-%%----- Inherit from CosNotifyComm::StructuredPushSupplier --
-%%----------------------------------------------------------%
-%% function : disconnect_structured_push_supplier
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-disconnect_structured_push_supplier(_OE_THIS, _OE_FROM, State) ->
- {stop, normal, ok, ?set_Unconnected(State)}.
-
-%%----- Inherit from CosNotifyComm::SequencePushSupplier ----
-%%----------------------------------------------------------%
-%% function : disconnect_sequence_push_supplier
-%% Arguments: -
-%% Returns : ok
-%%-----------------------------------------------------------
-disconnect_sequence_push_supplier(_OE_THIS, _OE_FROM, State) ->
- {stop, normal, ok, ?set_Unconnected(State)}.
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-find_obj({value, {_, Obj}}) -> Obj;
-find_obj(_) -> {'EXCEPTION', #'CosNotifyFilter_FilterNotFound'{}}.
-
-find_ids(List) -> find_ids(List, []).
-find_ids([], Acc) -> Acc;
-find_ids([{I,_}|T], Acc) -> find_ids(T, [I|Acc]);
-find_ids(What, _) ->
- orber:dbg("[~p] PusherSupplier:find_ids();~n"
- "Id corrupt: ~p", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
-
-%% Delete a single object.
-%% The list do not differ, i.e., no filter removed, raise exception.
-delete_obj(List,List) -> corba:raise(#'CosNotifyFilter_FilterNotFound'{});
-delete_obj(List,_) -> List.
-
-%%-----------------------------------------------------------
-%% function : callSeq
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-callSeq(_OE_THIS, OE_FROM, State, EventsIn, Status) ->
- corba:reply(OE_FROM, ok),
- case cosNotification_eventDB:validate_event(?get_SubscribeData(State), EventsIn,
- ?get_AllFilter(State),
- ?get_SubscribeDB(State),
- Status) of
- {[],_} ->
- ?DBG("PROXY NOSUBSCRIPTION SEQUENCE/STRUCTURED: ~p~n",[EventsIn]),
- {noreply, State};
- {Events,_} when ?is_Suspended(State) ->
- store_events(State, Events),
- {noreply, State};
- {Events,_} when ?is_UnConnected(State) ->
- orber:dbg("[~p] PusherSupplier:callAny();~n"
- "Not connected, dropping event(s): ~p",
- [?LINE, Events], ?DEBUG_LEVEL),
- {noreply, State};
- {[Event],_} when ?is_STRUCTURED(State) ->
- ?DBG("PROXY RECEIVED SEQUENCE: ~p~n",[Event]),
- empty_db(State, ?addAndGet_Event(State, Event));
- {[Event],_} when ?is_ANY(State) ->
- ?DBG("PROXY RECEIVED SEQUENCE: ~p~n",[Event]),
- AnyEvent = any:create('CosNotification_StructuredEvent':tc(),Event),
- empty_db(State, ?addAndGet_Event(State, AnyEvent));
- {Events,_} ->
- ?DBG("PROXY RECEIVED SEQUENCE: ~p~n",[Events]),
- store_events(State, Events),
- lookup_and_push(State)
- end.
-
-%%-----------------------------------------------------------
-%% function : callAny
-%% Arguments:
-%% Returns :
-%%-----------------------------------------------------------
-callAny(_OE_THIS, OE_FROM, State, EventIn, Status) ->
- corba:reply(OE_FROM, ok),
- case cosNotification_eventDB:validate_event(?get_SubscribeData(State), EventIn,
- ?get_AllFilter(State),
- ?get_SubscribeDB(State),
- Status) of
- {[],_} ->
- ?DBG("PROXY NOSUBSCRIPTION ANY: ~p~n",[EventIn]),
- %% To be on the safe side, test if there are any events that not
- %% have been forwarded (should only be possible if StartTime is used).
- lookup_and_push(State);
- {Event,_} when ?is_Suspended(State), ?is_ANY(State) ->
- ?add_Event(State, Event),
- {noreply, State};
- {Event,_} when ?is_Suspended(State) ->
- ?add_Event(State, ?not_CreateSE("","%ANY","",[],[],Event)),
- {noreply, State};
- {Event,_} when ?is_UnConnected(State) ->
- orber:dbg("[~p] PusherSupplier:callAny();~n"
- "Not connected, dropping event: ~p",
- [?LINE, Event], ?DEBUG_LEVEL),
- {noreply, State};
- {Event,_} when ?is_ANY(State) ->
- ?DBG("PROXY RECEIVED ANY: ~p~n",[Event]),
- %% We must store the event since there may be other events that should
- %% be delivered first, e.g., higher priority.
- empty_db(State, ?addAndGet_Event(State, Event));
- {Event,_} when ?is_SEQUENCE(State) ->
- ?DBG("PROXY RECEIVED ANY==>SEQUENCE: ~p~n",[Event]),
- StrEvent = ?not_CreateSE("","%ANY","",[],[],Event),
- ?add_Event(State, StrEvent),
- lookup_and_push(State);
- {Event,_} ->
- ?DBG("PROXY RECEIVED ANY==>STRUCTURED: ~p~n",[Event]),
- StrEvent = ?not_CreateSE("","%ANY","",[],[],Event),
- empty_db(State, ?addAndGet_Event(State, StrEvent))
- end.
-
-%% Lookup and push "the correct" amount of events.
-lookup_and_push(State) ->
- %% The boolean indicates, if false, that we will only push events if we have
- %% passed the BatchLimit. If true we will ignore this limit and push events
- %% anyway (typcially invoked when pacing limit passed).
- lookup_and_push(State, false).
-lookup_and_push(State, false) when ?is_SEQUENCE(State) ->
- case ?is_BatchLimitReached(State) of
- true ->
- case ?get_Events(State, ?get_BatchLimit(State)) of
- {[], _, _} ->
- ?DBG("BATCHLIMIT (~p) REACHED BUT NO EVENTS FOUND~n",
- [?get_BatchLimit(State)]),
- {noreply, State};
- {Events, _, Keys} ->
- ?DBG("BATCHLIMIT (~p) REACHED, EVENTS FOUND: ~p~n",
- [?get_BatchLimit(State), Events]),
- case catch 'CosNotifyComm_SequencePushConsumer':
- push_structured_events(?get_Client(State), Events) of
- ok ->
- cosNotification_eventDB:delete_events(Keys),
- lookup_and_push(reset_cache(State), false);
- {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') orelse
- is_record(E, 'NO_PERMISSION') orelse
- is_record(E, 'CosEventComm_Disconnected') ->
- ?DBG("PUSH SUPPLIER CLIENT NO LONGER EXIST~n", []),
- 'CosNotification_Common':notify([{proxy, State#state.this},
- {client, ?get_Client(State)},
- {reason, {'EXCEPTION', E}}]),
- {stop, normal, State};
- What when ?is_PersistentEvent(State),
- ?is_PersistentConnection(State) ->
- orber:dbg("[~p] PusherSupplier:lookup_and_push();~n"
- "Client respond incorrect: ~p",
- [?LINE, What], ?DEBUG_LEVEL),
- check_cache(State);
- What when ?is_PersistentConnection(State) ->
- %% Here we should do something when we want to handle
- %% Persistent EventReliability.
- orber:dbg("[~p] PusherSupplier:lookup_and_push();~n"
- "Client respond incorrect: ~p~n"
- "Dropping events: ~p",
- [?LINE, What, Events], ?DEBUG_LEVEL),
- cosNotification_eventDB:delete_events(Keys),
- {noreply, State};
- WhatII ->
- orber:dbg("[~p] PusherSupplier:lookup_and_push();~n"
- "Client respond incorrect: ~p~n"
- "Terminating and dropping events: ~p",
- [?LINE, WhatII, Events], ?DEBUG_LEVEL),
- 'CosNotification_Common':notify([{proxy, State#state.this},
- {client, ?get_Client(State)},
- {reason, WhatII}]),
- {stop, normal, State}
- end
- end;
- _ ->
- ?DBG("BATCHLIMIT (~p) NOT REACHED~n",[?get_BatchLimit(State)]),
- {noreply, State}
- end;
-lookup_and_push(State, true) when ?is_SEQUENCE(State) ->
- case ?get_Events(State, ?get_BatchLimit(State)) of
- {[], _, _} ->
- ?DBG("PACELIMIT REACHED BUT NO EVENTS FOUND~n", []),
- {noreply, State};
- {Events, _, Keys} ->
- ?DBG("PACELIMIT REACHED, EVENTS FOUND: ~p~n", [Events]),
- case catch 'CosNotifyComm_SequencePushConsumer':
- push_structured_events(?get_Client(State), Events) of
- ok ->
- cosNotification_eventDB:delete_events(Keys),
- lookup_and_push(reset_cache(State), false);
- {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') orelse
- is_record(E, 'NO_PERMISSION') orelse
- is_record(E, 'CosEventComm_Disconnected') ->
- orber:dbg("[~p] PusherSupplier:lookup_and_push();~n"
- "Client no longer exists; terminating and dropping events: ~p",
- [?LINE, Events], ?DEBUG_LEVEL),
- 'CosNotification_Common':notify([{proxy, State#state.this},
- {client, ?get_Client(State)},
- {reason, {'EXCEPTION', E}}]),
- {stop, normal, State};
- What when ?is_PersistentEvent(State),
- ?is_PersistentConnection(State) ->
- orber:dbg("[~p] PusherSupplier:lookup_and_push();~n"
- "Client respond incorrect: ~p",
- [?LINE, What], ?DEBUG_LEVEL),
- check_cache(State);
- What when ?is_PersistentConnection(State) ->
- %% Here we should do something when we want to handle
- %% Persistent EventReliability.
- orber:dbg("[~p] PusherSupplier:lookup_and_push();~n"
- "Client respond incorrect: ~p~n"
- "Dropping events: ~p",
- [?LINE, What, Events], ?DEBUG_LEVEL),
- cosNotification_eventDB:delete_events(Keys),
- {noreply, State};
- WhatII ->
- orber:dbg("[~p] PusherSupplier:lookup_and_push();~n"
- "Client respond incorrect: ~p~n"
- "Terminating and dropping events: ~p",
- [?LINE, WhatII, Events], ?DEBUG_LEVEL),
- 'CosNotification_Common':notify([{proxy, State#state.this},
- {client, ?get_Client(State)},
- {reason, WhatII}]),
- {stop, normal, State}
- end
- end;
-lookup_and_push(State, _) ->
- empty_db(State, ?get_Event(State)).
-
-
-%% Push all events stored while not connected or received in sequence.
-empty_db(State, {[], _, _}) ->
- {noreply, State};
-empty_db(State, {Event, _, Keys}) when ?is_STRUCTURED(State) ->
- case catch 'CosNotifyComm_StructuredPushConsumer':
- push_structured_event(?get_Client(State), Event) of
- ok ->
- cosNotification_eventDB:delete_events(Keys),
- NewState = reset_cache(State),
- empty_db(NewState, ?get_Event(NewState));
- {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') orelse
- is_record(E, 'NO_PERMISSION') orelse
- is_record(E, 'CosEventComm_Disconnected') ->
- orber:dbg("[~p] PusherSupplier:empty_db();~n"
- "Client no longer exists; terminating and dropping: ~p",
- [?LINE, Event], ?DEBUG_LEVEL),
- 'CosNotification_Common':notify([{proxy, State#state.this},
- {client, ?get_Client(State)},
- {reason, {'EXCEPTION', E}}]),
- {stop, normal, State};
- What when ?is_PersistentEvent(State),
- ?is_PersistentConnection(State) ->
- orber:dbg("[~p] PusherSupplier:lookup_and_push();~n"
- "Client respond incorrect: ~p",
- [?LINE, What], ?DEBUG_LEVEL),
- check_cache(State);
- What when ?is_PersistentConnection(State) ->
- %% Here we should do something when we want to handle
- %% Persistent EventReliability.
- orber:dbg("[~p] PusherSupplier:empty_db();~n"
- "Client respond incorrect: ~p~n"
- "Dropping event: ~p",
- [?LINE, What, Event], ?DEBUG_LEVEL),
- cosNotification_eventDB:delete_events(Keys),
- {noreply, State};
- WhatII ->
- orber:dbg("[~p] PusherSupplier:empty_db();~n"
- "Client respond incorrect: ~p~n"
- "Terminating and dropping: ~p",
- [?LINE, WhatII, Event], ?DEBUG_LEVEL),
- 'CosNotification_Common':notify([{proxy, State#state.this},
- {client, ?get_Client(State)},
- {reason, WhatII}]),
- {stop, normal, State}
- end;
-empty_db(State, {Event, _, Keys}) when ?is_ANY(State) ->
- case catch 'CosEventComm_PushConsumer':push(?get_Client(State), Event) of
- ok ->
- cosNotification_eventDB:delete_events(Keys),
- NewState = reset_cache(State),
- empty_db(NewState, ?get_Event(NewState));
- {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') orelse
- is_record(E, 'NO_PERMISSION') orelse
- is_record(E, 'CosEventComm_Disconnected') ->
- orber:dbg("[~p] PusherSupplier:empty_db();~n"
- "Client no longer exists; terminating and dropping: ~p",
- [?LINE, Event], ?DEBUG_LEVEL),
- 'CosNotification_Common':notify([{proxy, State#state.this},
- {client, ?get_Client(State)},
- {reason, {'EXCEPTION', E}}]),
- {stop, normal, State};
- What when ?is_PersistentEvent(State),
- ?is_PersistentConnection(State) ->
- orber:dbg("[~p] PusherSupplier:lookup_and_push();~n"
- "Client respond incorrect: ~p",
- [?LINE, What], ?DEBUG_LEVEL),
- check_cache(State);
- What when ?is_PersistentConnection(State) ->
- %% Here we should do something when we want to handle
- %% Persistent EventReliability.
- orber:dbg("[~p] PusherSupplier:empty_db();~n"
- "Client respond incorrect: ~p~n"
- "Dropping Event: ~p",
- [?LINE, What, Event], ?DEBUG_LEVEL),
- cosNotification_eventDB:delete_events(Keys),
- {noreply, State};
- WhatII ->
- orber:dbg("[~p] PusherSupplier:empty_db();~n"
- "Client respond incorrect: ~p~n"
- "Terminating and dropping: ~p",
- [?LINE, WhatII, Event], ?DEBUG_LEVEL),
- 'CosNotification_Common':notify([{proxy, State#state.this},
- {client, ?get_Client(State)},
- {reason, WhatII}]),
- {stop, normal, State}
- end.
-
-reset_cache(#state{cacheTimeout = undefined,
- cacheInterval = undefined} = State) ->
- State;
-reset_cache(State) ->
- stop_timer(State#state.cacheTimeout),
- stop_timer(State#state.cacheInterval),
- State#state{cacheTimeout = undefined,
- cacheInterval = undefined}.
-
-check_cache(#state{maxCache = Max, cacheTimeout = Timeout,
- cacheInterval = Interval} = State) ->
- case cosNotification_eventDB:status(State#state.eventDB, eventCounter) of
- Count when Count > Max ->
- %% Reached the upper limit, terminate.
- 'CosNotification_Common':notify([{proxy, State#state.this},
- {client, State#state.client},
- {reason, {max_events, Max}}]),
- {stop, normal, State};
- _ when Timeout == undefined, Interval == undefined ->
- case {timer:send_interval(cosNotificationApp:interval_events(),
- cacheInterval),
- timer:send_after(cosNotificationApp:timeout_events(),
- cacheTimeout)} of
- {{ok, IntervalRef}, {ok, TimeoutRef}} ->
- {noreply, State#state{cacheTimeout = TimeoutRef,
- cacheInterval = IntervalRef}};
- Error ->
- orber:dbg("[~p] PusherSupplier:check_cache();~n"
- "Unable to start timers: ~p",
- [?LINE, Error], ?DEBUG_LEVEL),
- 'CosNotification_Common':notify([{proxy, State#state.this},
- {client, State#state.client},
- {reason, {timer, Error}}]),
- {stop, normal, State}
- end;
- _ ->
- %% Timers already started.
- {noreply, State}
- end.
-
-store_events(_State, []) ->
- ok;
-store_events(State, [Event|Rest]) when ?is_ANY(State) ->
- AnyEvent = any:create('CosNotification_StructuredEvent':tc(),Event),
- ?add_Event(State, AnyEvent),
- store_events(State, Rest);
-store_events(State, [Event|Rest]) ->
- ?add_Event(State, Event),
- store_events(State, Rest).
-
-%% Start timers which send a message each time we should push events. Only used
-%% when this objects is defined to supply sequences.
-start_timer(State) ->
- case ?get_PacingInterval(State) of
- 0 ->
- ?DBG("PUSH SUPPLIER STARTED NO TIMER (0), BATCH LIMIT: ~p~n",
- [?get_BatchLimit(State)]),
-
- State;
- PacInt ->
- case catch timer:send_interval(timer:seconds(PacInt), pacing) of
- {ok,PacTRef} ->
- ?DBG("PUSH SUPPLIER STARTED TIMER, BATCH LIMIT: ~p~n",
- [?get_BatchLimit(State)]),
- ?set_PacingTimer(State, PacTRef);
- What ->
- orber:dbg("[~p] PusherSupplier:start_timer();~n"
- "Unable to invoke timer:send_interval/2: ~p",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end
- end.
-
-stop_timer(undefined) ->
- ?DBG("PUSH SUPPLIER HAVE NO TIMER TO STOP~n",[]),
- ok;
-stop_timer(Timer) ->
- ?DBG("PUSH SUPPLIER STOPPED TIMER~n",[]),
- timer:cancel(Timer),
- ok.
-
-
-%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/cosNotification.app.src b/lib/cosNotification/src/cosNotification.app.src
deleted file mode 100644
index 52ce164d46..0000000000
--- a/lib/cosNotification/src/cosNotification.app.src
+++ /dev/null
@@ -1,122 +0,0 @@
-{application, cosNotification,
- [{description, "The Erlang CosNotification application"},
- {vsn, "%VSN%"},
- {modules,
- [
- 'CosNotification_Common',
- 'CosNotifyChannelAdmin_ConsumerAdmin_impl',
- 'CosNotifyChannelAdmin_EventChannelFactory_impl',
- 'CosNotifyChannelAdmin_EventChannel_impl',
- 'CosNotifyChannelAdmin_SupplierAdmin_impl',
- 'PullerConsumer_impl',
- 'PullerSupplier_impl',
- 'PusherConsumer_impl',
- 'PusherSupplier_impl',
- 'cosNotificationApp',
- 'CosNotifyFilter_Filter_impl',
- 'CosNotifyFilter_MappingFilter_impl',
- 'CosNotifyFilter_FilterFactory_impl',
- 'cosNotification_Scanner',
- 'cosNotification_Grammar',
- 'cosNotification_Filter',
- 'cosNotification_eventDB',
- 'oe_CosNotification',
- 'oe_cosNotificationAppComm',
- 'oe_CosNotificationComm_Event',
- 'CosNotification',
- 'CosNotification_AdminPropertiesAdmin',
- 'CosNotification_EventHeader',
- 'CosNotification_EventType',
- 'CosNotification_FixedEventHeader',
- 'CosNotification_NamedPropertyRange',
- 'CosNotification_Property',
- 'CosNotification_PropertyError',
- 'CosNotification_PropertyRange',
- 'CosNotification_QoSAdmin',
- 'CosNotification_StructuredEvent',
- 'CosNotification_UnsupportedAdmin',
- 'CosNotification_UnsupportedQoS',
- 'CosNotification_EventBatch',
- 'CosNotification_EventTypeSeq',
- 'CosNotification_NamedPropertyRangeSeq',
- 'CosNotification_PropertyErrorSeq',
- 'CosNotification_PropertySeq',
- 'oe_CosNotifyChannelAdmin',
- 'CosNotifyChannelAdmin_AdminLimit',
- 'CosNotifyChannelAdmin_AdminLimitExceeded',
- 'CosNotifyChannelAdmin_AdminNotFound',
- 'CosNotifyChannelAdmin_ChannelNotFound',
- 'CosNotifyChannelAdmin_ConnectionAlreadyActive',
- 'CosNotifyChannelAdmin_ConnectionAlreadyInactive',
- 'CosNotifyChannelAdmin_ConsumerAdmin',
- 'CosNotifyChannelAdmin_EventChannel',
- 'CosNotifyChannelAdmin_EventChannelFactory',
- 'CosNotifyChannelAdmin_NotConnected',
- 'CosNotifyChannelAdmin_ProxyConsumer',
- 'CosNotifyChannelAdmin_ProxyNotFound',
- 'CosNotifyChannelAdmin_ProxyPullConsumer',
- 'CosNotifyChannelAdmin_ProxyPullSupplier',
- 'CosNotifyChannelAdmin_ProxyPushConsumer',
- 'CosNotifyChannelAdmin_ProxyPushSupplier',
- 'CosNotifyChannelAdmin_ProxySupplier',
- 'CosNotifyChannelAdmin_SequenceProxyPullConsumer',
- 'CosNotifyChannelAdmin_SequenceProxyPullSupplier',
- 'CosNotifyChannelAdmin_SequenceProxyPushConsumer',
- 'CosNotifyChannelAdmin_SequenceProxyPushSupplier',
- 'CosNotifyChannelAdmin_StructuredProxyPullConsumer',
- 'CosNotifyChannelAdmin_StructuredProxyPullSupplier',
- 'CosNotifyChannelAdmin_StructuredProxyPushConsumer',
- 'CosNotifyChannelAdmin_StructuredProxyPushSupplier',
- 'CosNotifyChannelAdmin_SupplierAdmin',
- 'CosNotifyChannelAdmin_AdminIDSeq',
- 'CosNotifyChannelAdmin_ChannelIDSeq',
- 'CosNotifyChannelAdmin_ProxyIDSeq',
- 'oe_CosNotifyComm',
- 'CosNotifyComm_InvalidEventType',
- 'CosNotifyComm_NotifyPublish',
- 'CosNotifyComm_NotifySubscribe',
- 'CosNotifyComm_PullConsumer',
- 'CosNotifyComm_PullSupplier',
- 'CosNotifyComm_PushConsumer',
- 'CosNotifyComm_PushSupplier',
- 'CosNotifyComm_SequencePullConsumer',
- 'CosNotifyComm_SequencePullSupplier',
- 'CosNotifyComm_SequencePushConsumer',
- 'CosNotifyComm_SequencePushSupplier',
- 'CosNotifyComm_StructuredPullConsumer',
- 'CosNotifyComm_StructuredPullSupplier',
- 'CosNotifyComm_StructuredPushConsumer',
- 'CosNotifyComm_StructuredPushSupplier',
- 'oe_CosNotifyFilter',
- 'CosNotifyFilter_CallbackNotFound',
- 'CosNotifyFilter_ConstraintExp',
- 'CosNotifyFilter_ConstraintInfo',
- 'CosNotifyFilter_ConstraintNotFound',
- 'CosNotifyFilter_DuplicateConstraintID',
- 'CosNotifyFilter_Filter',
- 'CosNotifyFilter_FilterAdmin',
- 'CosNotifyFilter_FilterFactory',
- 'CosNotifyFilter_FilterNotFound',
- 'CosNotifyFilter_InvalidConstraint',
- 'CosNotifyFilter_InvalidGrammar',
- 'CosNotifyFilter_InvalidValue',
- 'CosNotifyFilter_MappingConstraintInfo',
- 'CosNotifyFilter_MappingConstraintPair',
- 'CosNotifyFilter_MappingFilter',
- 'CosNotifyFilter_UnsupportedFilterableData',
- 'CosNotifyFilter_CallbackIDSeq',
- 'CosNotifyFilter_ConstraintExpSeq',
- 'CosNotifyFilter_ConstraintIDSeq',
- 'CosNotifyFilter_ConstraintInfoSeq',
- 'CosNotifyFilter_FilterIDSeq',
- 'CosNotifyFilter_MappingConstraintInfoSeq',
- 'CosNotifyFilter_MappingConstraintPairSeq'
- ]
- },
- {registered, [cosNotificationSup, oe_cosNotificationFactory]},
- {applications, [orber, stdlib, kernel]},
- {env, []},
- {mod, {cosNotificationApp, []}},
- {runtime_dependencies, ["stdlib-2.5","orber-3.6.27","kernel-3.0","erts-7.0",
- "cosTime-1.1.14","cosEvent-2.1.15"]}
-]}.
diff --git a/lib/cosNotification/src/cosNotification.appup.src b/lib/cosNotification/src/cosNotification.appup.src
deleted file mode 100644
index 6c3b2833b7..0000000000
--- a/lib/cosNotification/src/cosNotification.appup.src
+++ /dev/null
@@ -1,7 +0,0 @@
-{"%VSN%",
- [
- ],
- [
- ]
-}.
-
diff --git a/lib/cosNotification/src/cosNotificationApp.erl b/lib/cosNotification/src/cosNotificationApp.erl
deleted file mode 100644
index f6231ed47e..0000000000
--- a/lib/cosNotification/src/cosNotificationApp.erl
+++ /dev/null
@@ -1,436 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2015. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : cosNotificationApp.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module(cosNotificationApp).
-
-%%--------------- INCLUDES -----------------------------------
-%% Local
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-%% Application files
--include("CosNotification.hrl").
--include("CosNotifyChannelAdmin.hrl").
--include("CosNotifyComm.hrl").
--include("CosNotifyFilter.hrl").
-
--include("CosNotification_Definitions.hrl").
-%%--------------- EXPORTS-------------------------------------
-%% cosNotification API external
--export([start/0, stop/0,
- start_factory/1, start_factory/0, stop_factory/1,
- start_global_factory/0, start_global_factory/1,
- start_filter_factory/1, start_filter_factory/0, stop_filter_factory/1,
- install/0, install/1, uninstall/0, uninstall/1,
- install_event/0, install_event/1, uninstall_event/0, uninstall_event/1,
- install_typed/0, install_typed/1, uninstall_typed/0, uninstall_typed/1,
- create_structured_event/6, type_check/0, notify/0, max_events/0,
- timeout_events/0, interval_events/0]).
-
-%% Application callbacks
--export([start/2, init/1, stop/1]).
-
-%%--------------- DEFINES ------------------------------------
--define(IDL_MODULES, ['oe_CosNotification',
- 'oe_cosNotificationAppComm',
- 'oe_CosNotifyComm',
- 'oe_CosNotifyFilter',
- 'oe_CosNotifyChannelAdmin']).
--define(EVENT_IDL_MODULES, ['oe_CosEventComm',
- 'oe_CosEventChannelAdmin']).
--define(TYPED_IDL_MODULES, ['oe_CosTypedEvent',
- 'oe_CosTypedNotification']).
-
--define(FACTORY_NAME, oe_cosNotificationFactory).
--define(SUPERVISOR_NAME, cosNotificationSup).
-
-
-%%------------------------------------------------------------
-%% function : install/X
-%% Arguments: - | Time (seconds)
-%% Returns : ok | EXIT | EXCEPTION
-%% Effect : Install necessary data in the IFR DB
-%%------------------------------------------------------------
-
-install() ->
- install(0).
-
-install(Time) when is_integer(Time) ->
- install_loop(?IDL_MODULES, timer:seconds(Time));
-install(_Time) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%------------------------------------------------------------
-%% function : install_event/X
-%% Arguments: - | Time (seconds)
-%% Returns : ok | EXIT | EXCEPTION
-%% Effect : Install necessary data in the IFR DB
-%%------------------------------------------------------------
-
-install_event() ->
- install_event(0).
-
-install_event(Time) when is_integer(Time) ->
- install_loop(?EVENT_IDL_MODULES, timer:seconds(Time));
-install_event(_Time) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%------------------------------------------------------------
-%% function : install_typed/X
-%% Arguments: - | Time (seconds)
-%% Returns : ok | EXIT | EXCEPTION
-%% Effect : Install necessary data in the IFR DB
-%%------------------------------------------------------------
-
-install_typed() ->
- install_typed(0).
-
-install_typed(Time) when is_integer(Time) ->
- install_loop(?TYPED_IDL_MODULES, timer:seconds(Time));
-install_typed(_Time) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-install_loop([], _) ->
- ok;
-install_loop([H|T], Time) ->
- H:'oe_register'(),
- timer:sleep(Time),
- install_loop(T, Time).
-
-%%------------------------------------------------------------
-%% function : uninstall/X
-%% Arguments: - | Time (seconds)
-%% Returns : ok | EXIT | EXCEPTION
-%% Effect : Remove data related to cosNotificationin from the IFR DB
-%%------------------------------------------------------------
-
-uninstall() ->
- uninstall(0).
-
-uninstall(Time) when is_integer(Time) ->
- uninstall_loop(lists:reverse(?IDL_MODULES), timer:seconds(Time));
-uninstall(_Time) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%------------------------------------------------------------
-%% function : uninstall_event/X
-%% Arguments: - | Time (seconds)
-%% Returns : ok | EXIT | EXCEPTION
-%% Effect : Remove data related to cosNotificationin from the IFR DB
-%%------------------------------------------------------------
-
-uninstall_event() ->
- uninstall_event(0).
-
-uninstall_event(Time) when is_integer(Time) ->
- uninstall_loop(lists:reverse(?EVENT_IDL_MODULES), timer:seconds(Time));
-uninstall_event(_Time) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%------------------------------------------------------------
-%% function : uninstall_typed/X
-%% Arguments: - | Time (seconds)
-%% Returns : ok | EXIT | EXCEPTION
-%% Effect : Remove data related to cosNotificationin from the IFR DB
-%%------------------------------------------------------------
-
-uninstall_typed() ->
- uninstall_typed(0).
-
-uninstall_typed(Time) when is_integer(Time) ->
- uninstall_loop(lists:reverse(?TYPED_IDL_MODULES), timer:seconds(Time));
-uninstall_typed(_Time) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-uninstall_loop([], _) ->
- ok;
-uninstall_loop([H|T], Time) ->
- H:'oe_unregister'(),
- timer:sleep(Time),
- uninstall_loop(T, Time).
-
-
-%%------------------------------------------------------------
-%% function : start/stop
-%% Arguments:
-%% Returns :
-%% Effect : Starts or stops the cosTRansaction application.
-%%------------------------------------------------------------
-
-start() ->
- application:start(cosNotification).
-stop() ->
- application:stop(cosNotification).
-
-%%------------------------------------------------------------
-%% function : start_factory
-%% Arguments: none or an argumentlist whith default values.
-%% Returns : ObjectRef | {'EXCEPTION', _} | {'EXIT', Reason}
-%% Effect : Starts a CosNotifyChannelAdmin_EventChannelFactory
-%%------------------------------------------------------------
-start_factory() ->
- start_factory(?not_DEFAULT_SETTINGS).
-
-start_factory(Args) when is_list(Args) ->
- SO = 'CosNotification_Common':get_option(server_options, Args, ?not_DEFAULT_SETTINGS),
- SPEC = ['CosNotifyChannelAdmin_EventChannelFactory',Args,
- [{sup_child, true},
- {regname, {local, oe_cosNotificationFactory}}|SO]],
- case supervisor:start_child(?SUPERVISOR_NAME, SPEC) of
- {ok, Pid, Obj} when is_pid(Pid) ->
- Obj;
- Other->
- orber:dbg("[~p] cosNotificationApp:start_factory( ~p ).~n"
- "Reason: ~p~n", [?LINE, Args, Other], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end;
-start_factory(Args) ->
- orber:dbg("[~p] cosNotificationApp:start_factory( ~p ).~n"
- "Bad parameters~n", [?LINE, Args], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%------------------------------------------------------------
-%% function : start_global_factory
-%% Arguments: none or an argumentlist whith default values.
-%% Returns : ObjectRef | {'EXCEPTION', _} | {'EXIT', Reason}
-%% Effect : Starts a CosNotifyChannelAdmin_EventChannelFactory
-%%------------------------------------------------------------
-start_global_factory() ->
- start_global_factory(?not_DEFAULT_SETTINGS).
-
-start_global_factory(Args) when is_list(Args) ->
- SO = 'CosNotification_Common':get_option(server_options, Args, ?not_DEFAULT_SETTINGS),
- Name = 'CosNotification_Common':create_name(),
- SPEC = ['CosNotifyChannelAdmin_EventChannelFactory',Args,
- [{sup_child, true},
- {regname, {global, Name}}|SO]],
- case supervisor:start_child(?SUPERVISOR_NAME, SPEC) of
- {ok, Pid, Obj} when is_pid(Pid) ->
- Obj;
- Other->
- orber:dbg("[~p] cosNotificationApp:start_global_factory( ~p ).~n"
- "Reason: ~p~n", [?LINE, Args, Other], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end;
-start_global_factory(Args) ->
- orber:dbg("[~p] cosNotificationApp:start_global_factory( ~p ).~n"
- "Bad parameters~n", [?LINE, Args], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-
-%%------------------------------------------------------------
-%% function : stop_factory
-%% Arguments: Factory Object Reference
-%% Returns : ok | {'EXCEPTION', _}
-%% Effect :
-%%------------------------------------------------------------
-
-stop_factory(Fac)->
- corba:dispose(Fac).
-
-%%------------------------------------------------------------
-%% function : start_filter_factory
-%% Arguments: none or an argumentlist which by default is defined
-%% in CosNotification_Definitions.hrl, i.e., '?not_FILTERFAC_DEF'
-%% Returns : ObjectRef | {'EXCEPTION', _} | {'EXIT', Reason}
-%% Effect : Starts a CosNotifyChannelAdmin_EventChannelFactory
-%%------------------------------------------------------------
-start_filter_factory() ->
- start_filter_factory([{typecheck, true},
- {tty, false},
- {logfile, false},
- {server_options, []}]).
-start_filter_factory(Args) when is_list(Args) ->
- SO = 'CosNotification_Common':get_option(server_options, Args,
- ?not_DEFAULT_SETTINGS),
- SPEC = ['CosNotifyFilter_FilterFactory',Args, [{sup_child, true}|SO]],
- case supervisor:start_child(?SUPERVISOR_NAME, SPEC) of
- {ok, Pid, Obj} when is_pid(Pid) ->
- Obj;
- Other->
- orber:dbg("[~p] cosNotificationApp:start_filter_factory( ~p ).~n"
- "Reason: ~p~n", [?LINE, Args, Other], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end;
-start_filter_factory(Args) ->
- orber:dbg("[~p] cosNotificationApp:start_filter_factory( ~p ).~n"
- "Bad parameters~n", [?LINE, Args], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-
-%%------------------------------------------------------------
-%% function : stop_filter_factory
-%% Arguments: FilterFactory Object Reference
-%% Returns : ok | {'EXCEPTION', _}
-%% Effect :
-%%------------------------------------------------------------
-
-stop_filter_factory(Fac)->
- corba:dispose(Fac).
-
-
-%%------------------------------------------------------------
-%% function : create_structured_event
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-create_structured_event(StrD,StrT,StrE,PSeqV,PSeqF,AnyR)
- when is_list(StrD) andalso is_list(StrT) andalso is_list(StrE)
- andalso is_list(PSeqV) andalso is_list(PSeqF) andalso
- is_record(AnyR, any) ->
-#'CosNotification_StructuredEvent'{header =
- #'CosNotification_EventHeader'{fixed_header =
- #'CosNotification_FixedEventHeader'{event_type =
- #'CosNotification_EventType'{domain_name=StrD,
- type_name=StrT},
- event_name = StrE},
- variable_header = PSeqV},
- filterable_data = PSeqF,
- remainder_of_body = AnyR};
-create_structured_event(_StrD,_StrT,_StrE,_PSeqV,_PSeqF,_AnyR) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-
-%%------------------------------------------------------------
-%% function : type_check
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-type_check() ->
- case application:get_env(cosNotification, type_check) of
- {ok, Boolean} when is_atom(Boolean) ->
- Boolean;
- _ ->
- true
- end.
-
-%%------------------------------------------------------------
-%% function : notify
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-notify() ->
- case application:get_env(cosNotification, notify) of
- {ok, Module} when is_atom(Module) ->
- Module;
- _ ->
- false
- end.
-
-%%------------------------------------------------------------
-%% function : max_events
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-max_events() ->
- case application:get_env(cosNotification, max_events) of
- {ok, Max} when is_integer(Max) ->
- Max;
- _ ->
- 50
- end.
-
-%%------------------------------------------------------------
-%% function : timeout_events
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-timeout_events() ->
- case application:get_env(cosNotification, timeout_events) of
- {ok, Max} when is_integer(Max) ->
- Max;
- _ ->
- 3000000 %% 5 minutes
- end.
-
-
-%%------------------------------------------------------------
-%% function : interval_events
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-interval_events() ->
- case application:get_env(cosNotification, interval_events) of
- {ok, Max} when is_integer(Max) ->
- Max;
- _ ->
- 10000 %% 10 seconds
- end.
-
-
-%%------------------------------------------------------------
-%% function : start
-%% Arguments: Type - see module application
-%% Arg - see module application
-%% Returns :
-%% Effect : Module callback for application
-%%------------------------------------------------------------
-
-start(_, _) ->
- supervisor:start_link({local, ?SUPERVISOR_NAME}, cosNotificationApp, app_init).
-
-
-%%------------------------------------------------------------
-%% function : stop
-%% Arguments: Arg - see module application
-%% Returns :
-%% Effect : Module callback for application
-%%------------------------------------------------------------
-
-stop(_) ->
- ok.
-
-%%------------------------------------------------------------
-%% function : init
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-
-%% Starting using create_factory/X
-init(own_init) ->
- {ok,{{simple_one_for_one,50,10},
- [{"oe_NotChild",
- {'CosNotification_Common',create_link, []},
- transient,100000,worker,
- ['CosNotifyChannelAdmin_EventChannel',
- 'CosNotifyChannelAdmin_EventChannel_impl']}]}};
-%% When starting as an application.
-init(app_init) ->
- {ok,{{simple_one_for_one,50,10},
- [{"oe_NotChild",
- {'CosNotification_Common',create_link, []},
- transient,100000,worker,
- ['CosNotifyChannelAdmin_EventChannel',
- 'CosNotifyChannelAdmin_EventChannel_impl']}]}}.
-
-
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/cosNotificationAppComm.idl b/lib/cosNotification/src/cosNotificationAppComm.idl
deleted file mode 100644
index 09e0af2568..0000000000
--- a/lib/cosNotification/src/cosNotificationAppComm.idl
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _OE_COSNOTIFICATIONCOMM_IDL_
-#define _OE_COSNOTIFICATIONCOMM_IDL_
-
-#include<CosNotification.idl>
-
-module oe_CosNotificationComm {
-
- interface Event {
-
- enum status {MATCH, MATCHED};
- void callSeq(in CosNotification::EventBatch events, in status stat);
- void callAny(in any event, in status stat);
- };
-
-};
-#endif /* ifndef _OE_COSNOTIFICATIONCOMM_IDL_ */
-
diff --git a/lib/cosNotification/src/cosNotificationComm.cfg b/lib/cosNotification/src/cosNotificationComm.cfg
deleted file mode 100644
index 89d207528d..0000000000
--- a/lib/cosNotification/src/cosNotificationComm.cfg
+++ /dev/null
@@ -1,3 +0,0 @@
-{this, "oe_CosNotificationComm::Event"}.
-{from, "oe_CosNotificationComm::Event"}.
-{{handle_info, "oe_CosNotificationComm::Event"}, true}.
diff --git a/lib/cosNotification/src/cosNotification_Filter.erl b/lib/cosNotification/src/cosNotification_Filter.erl
deleted file mode 100644
index a92c9b8d41..0000000000
--- a/lib/cosNotification/src/cosNotification_Filter.erl
+++ /dev/null
@@ -1,965 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : cosNotification_Filter.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module(cosNotification_Filter).
-
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-%% Application files
--include("CosNotification.hrl").
--include("CosNotifyChannelAdmin.hrl").
--include("CosNotifyComm.hrl").
--include("CosNotifyFilter.hrl").
-
--include("CosNotification_Definitions.hrl").
-
-%%--------------- EXPORTS ------------------------------------
-%% Internal Filter Functions
--export([eval/1,
- eval/2,
- create_filter/1,
- check_types/1,
- match_types/3,
- validate_types/1]).
-
-%%--------------- DEFINES ------------------------------------
--define(EVENT_PATH, [{dotid,"header"}, {dotid,"fixed_header"},
- {dotid,"event_name"}]).
--define(DOMAIN_PATH, [{dotid,"header"}, {dotid,"fixed_header"},
- {dotid,"event_type"}, {dotid,"domain_name"}]).
--define(TYPE_PATH, [{dotid,"header"}, {dotid,"fixed_header"},
- {dotid,"event_type"}, {dotid,"type_name"}]).
--define(VARIABLE_PATH(I), [{dotid,"header"}, {dotid,"variable_header"}, {dotid,I}]).
--define(FILTERABLE_PATH(I), [{dotid,"filterable_data"}, {dotid,I}]).
-
-
-%%------------------------------------------------------------
-%%--------------- FILTER FUNCTIONS ---------------------------
-%%------------------------------------------------------------
-%%------------------------------------------------------------
-%% function : create_filter/1
-%% Arguments: String - Filter grammar
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-create_filter(Str) ->
- {ok, Tokens} = cosNotification_Scanner:scan(Str),
- case cosNotification_Grammar:parse(Tokens) of
- {ok, Filter} ->
- {ok, Filter};
- _->
- corba:raise(#'CosNotifyFilter_InvalidConstraint'{constr = Str})
- end.
-
-%%------------------------------------------------------------
-%% function : eval
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-
-eval('$empty') -> true;
-eval(Tree) -> eval(Tree, []).
-
-
-%% Leaf expressions (literals and idents).
-eval('$empty', _) -> true;
-eval(Lit, _Env) when is_number(Lit) -> Lit;
-eval(Lit, _Env) when is_list(Lit) -> Lit; %list == string
-eval(Lit, _Env) when is_atom(Lit) -> Lit; %atom == bool
-eval({component, V}, []) ->
- %% Cannot evaluate variables at this stage.
- throw({error, {unbound_variable, V}});
-eval({component, V}, Env) ->
- case catch lookup(V, Env, undefined) of
- {ok, Val} ->
- Val;
- _X ->
- {error, {unbound_variable, V}}
- end;
-
-%% CORBA2.3-15/26 states:
-%% "The name parameters in tk_objref, tk_struct, tk_union, tk_enum, tk_alias,
-%% tk_value, tk_value_box, tk_abstract_interface, tk_native and tk_except TypeCodes
-%% and the member name parameters in tk_struct, tk_union, tk_enum, tk_value and
-%% tk_except TypeCodes are not specified by (or significant in) GIOP. Agents should
-%% not make assumptions about type equivalence based on these name values; only the
-%% structural information (including RepositoryId values, if provided) is
-%% significant. If provided, the strings should be the simple, unscoped names
-%% supplied in the OMG IDL definition text. If omitted, they are encoded as empty
-%% strings."
-%% Makes it rather hard to follow the grammar 100 %.
-eval({default_component, V}, Env) ->
- case catch lookup(V, Env, default_component) of
- {ok, false} ->
- false;
- {ok, true} ->
- true;
- _X ->
- {error, {unbound_variable, V}}
- end;
-eval({exist_component, V}, Env) ->
- case catch lookup(V, Env, exist_component) of
- {ok, false} ->
- false;
- {ok, _} ->
- true;
- {error, _} ->
- false;
- _X ->
- {error, {unbound_variable, V}}
- end;
-%% Arithmetic expressions.
-eval({'*', X, Y}, Env) ->
- eval_arith({fun(_X, _Y) -> _X*_Y end, X, Y}, Env);
-eval({'/', X, Y}, Env) ->
- eval_arith({fun(_X, _Y) -> _X/_Y end, X, Y}, Env);
-eval({'+', X, Y}, Env) ->
- eval_arith({fun(_X, _Y) -> _X+_Y end, X, Y}, Env);
-eval({'-', X, Y}, Env) ->
- eval_arith({fun(_X, _Y) -> _X-_Y end, X, Y}, Env);
-eval({'u-', X}, Env) ->
- eval_arith({fun(_X) -> -_X end, X}, Env);
-%% Relational expressions.
-eval({'==', X, Y}, Env) ->
- eval_rel({fun(_X, _Y) -> _X == _Y end, X, Y}, Env);
-eval({'!=', X, Y}, Env) ->
- eval_rel({fun(_X, _Y) -> _X /= _Y end, X, Y}, Env);
-eval({'<', X, Y}, Env) ->
- eval_rel({fun(_X, _Y) -> _X < _Y end, X, Y}, Env);
-eval({'<=', X, Y}, Env) ->
- eval_rel({fun(_X, _Y) -> _X =< _Y end, X, Y}, Env);
-eval({'>', X, Y}, Env) ->
- eval_rel({fun(_X, _Y) -> _X > _Y end, X, Y}, Env);
-eval({'>=', X, Y}, Env) ->
- eval_rel({fun(_X, _Y) -> _X >= _Y end, X, Y}, Env);
-eval({'~', Needle, Haystack}, Env) -> %substring match
- N = eval(Needle, Env),
- H = eval(Haystack, Env),
- if
- is_list(N) andalso is_list(H) ->
- string:str(H, N) /= 0;
- true ->
- throw({error, {bad_type, Needle, Haystack}})
- end;
-eval({'in', Needle, Haystack}, Env) -> %set membership
- N = eval(Needle, Env),
- H = eval(Haystack, Env),
- if
- is_list(H) ->
- lists:member(N, H);
- true ->
- throw({error, {bad_type, Needle, Haystack}})
- end;
-%% Boolean expressions.
-eval({'and', false, _Y}, _Env) ->
- false;
-eval({'and', _X, false}, _Env) ->
- false;
-eval({'and', X, Y}, Env) ->
- eval_and_bool({fun(_X, _Y) -> _X and _Y end, X, Y}, Env);
-
-eval({'or', true, _Y}, _Env) ->
- true;
-eval({'or', _X, true}, _Env) ->
- true;
-eval({'or', X, Y}, Env) ->
- eval_or_bool({fun(_X, _Y) -> _X or _Y end, X, Y}, Env);
-eval({'not', X}, Env) ->
- eval_bool({fun(_X) -> not _X end, X}, Env);
-%% Catch-all
-eval(_T, _Env) ->
- throw({error, internal}).
-
-eval_bool({Fun, X}, Env) ->
- Xe = eval(X, Env),
- if
- is_atom(Xe) ->
- Fun(Xe);
- true ->
- throw({error, {bad_type, X}})
- end.
-eval_and_bool({Fun, X, Y}, Env) ->
- case eval(X, Env) of
- false ->
- %% No need for evaluating the other expression.
- false;
- Xe ->
- Ye = eval(Y, Env),
- if
- is_atom(Xe) andalso is_atom(Ye) ->
- Fun(Xe, Ye);
- true ->
- throw({error, {bad_type, X, Y}})
- end
- end.
-eval_or_bool({Fun, X, Y}, Env) ->
- case eval(X, Env) of
- true ->
- %% No need for evaluating the other expression.
- true;
- Xe ->
- Ye = eval(Y, Env),
- if
- is_atom(Xe) andalso is_atom(Ye) ->
- Fun(Xe, Ye);
- true ->
- throw({error, {bad_type, X, Y}})
- end
- end.
-
-
-%% According to issue 2203, OMG stated that arithmetic operations involving booleans
-%% is allowed. TRUE equals 1 and FALSE 0. They refer to:
-
-%% "We at NEC like this feature, and feel it is both required and
-%% standard with the way CORBA treats boolean values. We feel it's
-%% required because it allows the constraint grammar to handle
-%% expressions that combine the results of boolean comparisons,
-%% which we feel is typically expected of a constraint grammar
-%% (e.g., ($.fruit == apples) + ($.color == red) + ($.kind == macintosh) > 2)
-%% Furthermore, while we have no fundamental opposition to explicitly
-%% stating that TRUE=1 and FALSE=0, we don't necessarily feel it's
-%% necessary because section 12.3.1 of CORBA alread states that
-%% "Boolean values are encoded as single octets, where TRUE is the
-%% value 1, and FALSE is 0." Essentially, we feel CORBA already
-%% defines TRUE to be 1 and FALSE to be 0, however we are not
-%% opposed to adding such a statement into Notification if folks
-%% feel it's necessary."
-%% If still valid, see: ftp://ftp.omg.org/pub/docs/telecom/99-07-06.txt
-
-%% The section they refer to (CORBA-2.0) merely states that TRUE and FALSE are
-%% encoded as 1 and 0 in GIOP. Does not imply that booleans may be used as numeric.
-%% But, they have stated that this should be the case so.....
-
-remap_bool(Num) when is_number(Num) -> Num;
-remap_bool(true) -> 1;
-remap_bool(false) -> 0;
-remap_bool(X) -> throw({error, {bad_type, X}}).
-
-eval_arith({Fun, X}, Env) ->
- Xe = remap_bool(eval(X, Env)),
- Fun(Xe);
-eval_arith({Fun, X, Y}, Env) ->
- Xe = remap_bool(eval(X, Env)),
- Ye = remap_bool(eval(Y, Env)),
- Fun(Xe, Ye).
-
-eval_rel({Fun, X, Y}, Env) ->
- Xe = eval(X, Env),
- Ye = eval(Y, Env),
- if
- is_number(Xe) andalso is_number(Ye) ->
- Fun(Xe, Ye);
- is_list(Xe) andalso is_list(Ye) ->
- Fun(Xe, Ye);
- is_atom(Xe) andalso is_atom(Ye) ->
- Fun(Xe, Ye);
- true ->
- throw({error, {bad_type, X, Y}})
- end.
-
-%%------------------------------------------------------------
-%% function : get_variable
-%% Arguments: A sequence of CosNotification::Property{}, i.e.,
-%% name-value pairs.
-%% ID - name in the Property
-%% Any - remainder of body
-%% Returns : Value in the Property | false
-%% Comment : When searching for a variable we must start with
-%% 'variable_header' followed by 'filterable_body'.
-%% If not found we will then look in the 'remainder_of_body'
-%%------------------------------------------------------------
-
-get_variable([], ID, Any) when is_record(Any, any) ->
- case {any:get_value(Any), any:get_typecode(Any)} of
- {#'CosNotification_Property'{name=ID, value=A}, _} ->
- any:get_value(A);
- {_, TC} when is_atom(TC) ->
- %% Since TC atom it must be a simple type, which don't have members.
- throw({error, {bad_id, ID}});
- {Value, {tk_alias,_,ID,_}} when is_record(Value, any) ->
- %% {tk_alias, IFRId, ID, TypeCode}
- any:get_value(Value);
- {Value, {tk_alias,_,ID,_}} ->
- %% {tk_alias, IFRId, ID, TypeCode}
- Value;
- {Value, _TC} ->
- get_variable([],ID, Value)
- end;
-get_variable([], ID, #'CosNotification_Property'{name=ID, value=Any}) ->
- any:get_value(Any);
-get_variable([], ID, [#'CosNotification_Property'{name=ID, value=Any}|_]) ->
- any:get_value(Any);
-get_variable([], ID, [H|T]) when is_record(H, 'CosNotification_Property') ->
- get_variable([], ID, T);
-get_variable([], ID, false) ->
- throw({error, {bad_id, ID}});
-get_variable([], ID, Value) ->
- M = element(1, Value),
- case catch M:tc() of
- {tk_struct,_,_,SList} ->
- %% {tk_struct, Id, Name, ElementList}.
- Field = get_field(ID, SList),
- element(Field, Value);
- {tk_union,_,_,_, DefNo, UList} ->
- %% {tk_union, Id, Name, DiscrTC, Default, ElementList}
- case id2switch(UList, ID) of
- [default] when DefNo >= 0 ->
- element(3, Value);
- [default] ->
- throw({error, {bad_id, "Bad Union ID supplied"}});
- Found ->
- case catch lists:member(element(2, Value), Found) of
- true ->
- element(3, Value);
- _ ->
- throw({error, {bad_id, "Bad Union ID supplied"}})
- end
- end;
- _->
- throw({error, {bad_id, ID}})
- end;
-get_variable([#'CosNotification_Property'{name=ID, value=A}|_], ID, _) ->
- any:get_value(A);
-get_variable([_|T], ID, Any) ->
- get_variable(T, ID, Any).
-
-%%------------------------------------------------------------
-%% function : lookup
-%% Arguments: T - A parse tree representing the grammar.
-%% S - The event we want to extract data from
-%% Op - which type of lookup should be done on this
-%% component, e.g., 'default' or 'exist'.
-%% Returns : {ok, boolean()} |
-%% {error, _}
-%% Comment : WARNING!!!!
-%% This function uses some Orber core information to
-%% extract data, e.g., TypeCode representation. Why?
-%% We don't want to see the performance take a plunge
-%% due to that users write constraints which they
-%% can/may not know is slow. The alternative would be
-%% to use the IFR. However, these shortcuts aren't
-%% that frequent and we can easily update the code.
-%% To update, investigate:
-%% * lookup/3 cases related to '_type_id'
-%% * lookup/3 cases related to unions
-%% * get_variable/3
-%% * id2switch/2
-%% * switch2alias/2
-%%------------------------------------------------------------
-%% Done parsing, return the result.
-lookup([],S,_) -> {ok, S};
-lookup('$empty', #'CosNotification_StructuredEvent'{remainder_of_body = Any},_) ->
- {ok, any:get_value(Any)};
-lookup('$empty',S,_) when is_record(S, any) ->
- {ok, any:get_value(S)};
-
-%%------- varid --------
-%% CosNotification-revision-98-11-01/46 states:
-%% "The following rules govern translation of a run-time variable, $variable ,
-%% into a specific event field. If the run-time variable is reserved
-%% (e.g., $curtime) this translation takes precedence. Next, the first matching
-%% translation is chosen respectively from:
-%% * a simple-typed member of $.header.fixed_header,
-%% * properties in $.header.variable_header,
-%% and properties in $.header.filterable_data.
-%% If no match is found, the translation defaults to $.variable.
-%% Given these rules, an unstructured event with a $.priority member and a
-%% structured event using $.header.variable_header(priority) can be specified
-%% in a generic constraint using the run-time variable $priority .
-%% Alternatively, a constraint can be written specifically for a structured or
-%% unstructured event by avoiding the use of run-time variables."
-
-%% The above contains one error; $.header.filterable_data is not a part of the
-%% header, but contained in the event body.
-
-%% For any events we must first verify that a path exist, e.g.,
-%% "header"->"fixed_header"->"event_type"->"domain_name", otherwise we will
-%% use {dotid, "xxx"}.
-lookup([{varid, "type_name"}|T],
- #'CosNotification_StructuredEvent'
- {header = #'CosNotification_EventHeader'
- {fixed_header = #'CosNotification_FixedEventHeader'
- {event_type = #'CosNotification_EventType'{type_name=TN}}}}, Op) ->
- lookup(T, TN, Op);
-lookup([{varid, "type_name"}|T], Any, Op) when is_record(Any, any) ->
- case locate_var([?TYPE_PATH, ?VARIABLE_PATH("type_name"),
- ?FILTERABLE_PATH("type_name")], Any, Op) of
- {ok, Val} ->
- lookup(T, Val, Op);
- _ ->
- lookup(T, get_variable([], "type_name", Any), Op)
- end;
-lookup([{varid, "domain_name"}|T],
- #'CosNotification_StructuredEvent'
- {header = #'CosNotification_EventHeader'
- {fixed_header = #'CosNotification_FixedEventHeader'
- {event_type = #'CosNotification_EventType'{domain_name=DN}}}}, Op) ->
- lookup(T, DN, Op);
-lookup([{varid, "domain_name"}|T], Any, Op) when is_record(Any, any) ->
- case locate_var([?DOMAIN_PATH, ?VARIABLE_PATH("domain_name"),
- ?FILTERABLE_PATH("domain_name")], Any, Op) of
- {ok, Val} ->
- lookup(T, Val, Op);
- _ ->
- lookup(T, get_variable([], "domain_name", Any), Op)
- end;
-lookup([{varid, "event_name"}|T],
- #'CosNotification_StructuredEvent'
- {header = #'CosNotification_EventHeader'
- {fixed_header = #'CosNotification_FixedEventHeader'
- {event_name = EN}}}, Op) ->
- lookup(T, EN, Op);
-lookup([{varid, "event_name"}|T], Any, Op) when is_record(Any, any) ->
- case locate_var([?EVENT_PATH, ?VARIABLE_PATH("event_name"),
- ?FILTERABLE_PATH("event_name")], Any, Op) of
- {ok, Val} ->
- lookup(T, Val, Op);
- _ ->
- lookup(T, get_variable([], "event_name", Any), Op)
- end;
-
-lookup([{varid, ID}|T],
- #'CosNotification_StructuredEvent'{header =
- #'CosNotification_EventHeader'{variable_header = VS},
- filterable_data = FS,
- remainder_of_body = Any}, Op) ->
- lookup(T, get_variable(VS++FS, ID, Any), Op);
-lookup([{varid, ID}|T], Any, Op) ->
- case locate_var([?VARIABLE_PATH(ID), ?FILTERABLE_PATH(ID)], Any, Op) of
- {ok, Val} ->
- lookup(T, Val, Op);
- _ ->
- lookup(T, get_variable([], ID, Any), Op)
- end;
-
-%%------- dotid --------
-%% First level
-lookup([{dotid, "header"}|T],
- #'CosNotification_StructuredEvent'{header = S}, Op) ->
- lookup(T, S, Op);
-lookup([{dotid, "filterable_data"}|T],
- #'CosNotification_StructuredEvent'{filterable_data = S}, Op) ->
- lookup(T, S, Op);
-
-lookup([{dotid, remainder_of_body}|T],
- #'CosNotification_StructuredEvent'{remainder_of_body = S}, Op) ->
- lookup(T, S, Op);
-%% Second level. Previous token must have been header
-lookup([{dotid, "fixed_header"}|T],
- #'CosNotification_EventHeader'{fixed_header = S}, Op) ->
- lookup(T, S, Op);
-lookup([{dotid, "variable_header"}|T],
- #'CosNotification_EventHeader'{variable_header = S}, Op) ->
- lookup(T, S, Op);
-%% Third level. Previous token must have been fixed_header.
-lookup([{dotid, "event_type"}|T],
- #'CosNotification_FixedEventHeader'{event_type = S}, Op) ->
- lookup(T, S, Op);
-lookup([{dotid, "event_name"}|T],
- #'CosNotification_FixedEventHeader'{event_name = S}, Op) ->
- lookup(T, S, Op);
-%% Fourth level. Previous token must have been event_type
-lookup([{dotid, "domain_name"}|T], #'CosNotification_EventType'{domain_name = S}, Op) ->
- lookup(T, S, Op);
-lookup([{dotid, "type_name"}|T], #'CosNotification_EventType'{type_name = S}, Op) ->
- lookup(T, S, Op);
-
-%% Leaf expressions
-lookup([{dotid, "name"}|T], #'CosNotification_Property'{name=S}, Op) ->
- lookup(T, S, Op);
-lookup([{dotid, "value"}|T], #'CosNotification_Property'{value=S}, Op) ->
- lookup(T, S, Op);
-
-lookup([{dotid, ID}|T],
- #'CosNotification_StructuredEvent'{remainder_of_body = Any}, Op) ->
- lookup(T, get_variable([], ID, Any), Op);
-lookup([{dotid, ID}|T], Any, Op) ->
- lookup(T, get_variable([], ID, Any), Op);
-
-lookup([{associd, ID}|T], S, Op) when is_list(S) ->
- %% Refers to an associative array, i.e., a list of
- %% #'CosNotification_Property'{name=ID, value=A}
- lookup(T, get_variable(S, ID, false), Op);
-
-lookup([{dotint, Position}|T], S, Op) when is_record(S, any) ->
- lookup(T, element(Position+2, any:get_value(S)), Op);
-lookup([{dotint, Position}|T], S, Op) ->
- lookup(T, element(Position+2, S), Op);
-
-lookup([{uint, ID}|T], S, Op) when is_record(S, any) ->
- lookup([{uint, ID}|T], any:get_value(S), Op);
-lookup([{uint, ID} |T], S, Op) when is_tuple(S) ->
- case catch element(2, S) of
- ID ->
- %% The supplied union do contain the requested discriminator.
- lookup(T, element(3, S), Op);
- _Other when Op == exist_component ->
- throw({error, {bad_id, "Bad Union ID"}});
- Other ->
- %% Check if default is allowed.
- M = element(1, S),
- case catch M:tc() of
- {tk_union,_,_,_,DefNo, UList} ->
- %% {tk_union, Id, Name, DiscrTC, Default, ElementList}
- case switch2alias(UList, ID) of
- {ok, [], _} ->
- throw({error, {bad_id, "Bad Union ID"}});
- {ok, default, _} when DefNo >= 0 ->
- lookup(T, element(3, S), Op);
- {ok, List, _} ->
- case lists:member(Other, List) of
- true ->
- lookup(T, element(3, S), Op);
- _->
- throw({error, {bad_id, "Bad Union ID"}})
- end
- end
- end
- end;
-lookup([{ustr, ID}|T], S, Op) when is_record(S, any) ->
- lookup([{ustr, ID}|T], any:get_value(S), Op);
-lookup([{ustr, ID}|T], S, Op) when is_tuple(S) ->
- M = element(1, S),
- case catch M:tc() of
- {tk_union,_,_,_,DefNo, UList} ->
- case id2switch(UList, ID) of
- [default] when DefNo >= 0 ->
- lookup(T, element(3, S), Op);
- [default] ->
- throw({error, {bad_id, "Bad Union ID supplied"}});
- Found ->
- case catch lists:member(element(2, S), Found) of
- true ->
- lookup(T, element(3, S), Op);
- _ ->
- throw({error, {bad_id, "Bad Union ID supplied"}})
- end
- end
- end;
-lookup([default|T], S, Op) when is_record(S, any) ->
- lookup([default|T], any:get_value(S), Op);
-lookup([default|T], S, Op) when is_tuple(S) ->
- M = element(1, S),
- case catch M:tc() of
- {tk_union,_,_,_,DefNo, _UList} when DefNo < 0 ->
- %% {tk_union, Id, Name, DiscrTC, Default, ElementList}
- throw({error, {bad_id, "No default discriminator"}});
- {tk_union,_,_,_,_DefNo, UList} ->
- %% {tk_union, Id, Name, DiscrTC, Default, ElementList}
- %% Check if the label really is default.
- case lists:keymember(element(2, S), 1, UList) of
- false ->
- lookup(T, element(3, S), Op);
- _->
- throw({error, {bad_id, "Bad Union"}})
- end;
- _->
- throw({error, {bad_id, "Bad Union"}})
- end;
-
-lookup([{arrindex, Index}|T], S, Op) when is_tuple(S) ->
- %% The OMG uses c/c++ index. We must add one.
- lookup(T, element(Index+1,S), Op);
-
-%%%%%%%%%%%%%%%%%%%%%%% LEAF EXPRESSIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% got '$._length', which maps to the 'remainder_of_body'
-lookup(['_length'],
- #'CosNotification_StructuredEvent'{remainder_of_body = Any}, _Op) ->
- {ok, length(any:get_value(Any))};
-lookup(['_length'], S, _Op) when is_record(S, any) ->
- {ok, length(any:get_value(S))};
-lookup(['_length'], S, _Op) when is_list(S) ->
- {ok, length(S)};
-lookup(['_length'], S, _Op) when is_tuple(S) ->
- {ok, length(tuple_to_list(S))};
-
-%% got '$._d', which maps to the 'remainder_of_body'
-%% The discriminator may, accordiong to the CORBA specification, be (2.3/p3-37):
-%% * integer_type
-%% * char_type
-%% * boolean_type
-%% * enum_type
-%% * scoped_name
-lookup(['_d'],
- #'CosNotification_StructuredEvent'{remainder_of_body = Any},
- default_component) ->
- lookup(['_d'], any:get_value(Any), default_component);
-lookup(['_d'], S, default_component) when is_record(S, any) ->
- lookup(['_d'], any:get_value(S), default_component);
-lookup(['_d'], S, default_component) ->
- M = element(1, S),
- case catch M:tc() of
- {tk_union,_,_,_,DefNo,_} when DefNo < 0 ->
- %% '-1' indicates that no default value may exist.
- {ok, false};
- {tk_union,_,_,_,_,UList} ->
- %% May be using the default setting; check if the Value is in the list.
- {ok, not lists:keymember(element(2, S), 1, UList)};
- _ ->
- {ok, false}
- end;
-lookup(['_d'],
- #'CosNotification_StructuredEvent'{remainder_of_body = Any}, _Op) ->
- {ok, element(2, any:get_value(Any))};
-lookup(['_d'], S, _Op) when is_record(S, any) ->
- {ok, element(2, any:get_value(S))};
-lookup(['_d'], S, _Op) ->
- {ok, element(2, S)};
-
-
-lookup(['_type_id'], S, _Op) when is_record(S,'CosNotification_StructuredEvent') ->
- {ok, "StructuredEvent"};
-lookup(['_type_id'], S, _Op) when is_record(S,'CosNotification_EventHeader') ->
- {ok, "EventHeader"};
-lookup(['_type_id'], S, _Op) when is_record(S,'CosNotification_FixedEventHeader') ->
- {ok, "FixedEventHeader"};
-lookup(['_type_id'], S, _Op) when is_record(S,'CosNotification_EventType') ->
- {ok, "EventType"};
-lookup(['_type_id'], S, _Op) when is_record(S,'CosNotification_Property') ->
- {ok, "Property"};
-lookup(['_type_id'], S, _Op) when is_tuple(S) ->
- M=element(1, S),
- Name = case catch M:tc() of
- {tk_union,_,ID,_,_,_} ->
- ID;
- {tk_enum, _, ID, _} ->
- ID;
- {tk_exception, _, ID, _} ->
- ID;
- {tk_alias, _, ID, _} ->
- ID;
- {tk_struct,_,ID,_} ->
- ID
- end,
- {ok, Name};
-
-lookup(['_repos_id'], S, _Op) when is_record(S,'CosNotification_StructuredEvent') ->
- {ok, 'CosNotification_StructuredEvent':id()};
-lookup(['_repos_id'], S, _Op) when is_record(S,'CosNotification_EventHeader') ->
- {ok, 'CosNotification_EventHeader':id()};
-lookup(['_repos_id'], S, _Op) when is_record(S,'CosNotification_FixedEventHeader') ->
- {ok, 'CosNotification_FixedEventHeader':id()};
-lookup(['_repos_id'], S, _Op) when is_record(S,'CosNotification_EventType') ->
- {ok, 'CosNotification_EventType':id()};
-lookup(['_repos_id'], S, _Op) when is_record(S,'CosNotification_Property') ->
- {ok, 'CosNotification_Property':id()};
-lookup(['_repos_id'], S, _Op) when is_tuple(S) ->
- M = element(1, S),
- {ok, M:id()};
-
-lookup(_, _, _) ->
- error.
-
-
-%%------------------------------------------------------------
-%% function : locate_var
-%% Arguments: Paths - A list of path-lists which tells us where
-%% to search for runtime variables and in which
-%% order.
-%% S - Data
-%% Op - se lookup/3
-%% Returns : {error, _} |
-%% {ok, Val}
-%%------------------------------------------------------------
-locate_var([], _S, _) ->
- {error, "not found"};
-locate_var([H|T], S, Op) ->
- case catch lookup(H, S, Op) of
- {ok, Val} ->
- {ok,Val};
- _ ->
- locate_var(T, S, Op)
- end.
-
-%%------------------------------------------------------------
-%% function : id2switch
-%% Arguments: UList - The list of elements contained in the
-%% Union TypeCode.
-%% ID - string() eq name of element.
-%% Returns : Acc - A list of switches related to given ID.
-%%------------------------------------------------------------
-id2switch(UList, ID) ->
- id2switch(UList, ID, [], false).
-id2switch([], _, Acc, _) ->
- Acc;
-id2switch([{Sw, ID, _}|T], ID, Acc, _) ->
- id2switch(T, ID, [Sw|Acc], true);
-id2switch([_|_T], _ID, Acc, true) ->
- Acc;
-id2switch([_|T], ID, Acc, Found) ->
- id2switch(T, ID, Acc, Found).
-
-%%------------------------------------------------------------
-%% function : switch2alias
-%% Arguments: UList - The list of elements contained in the
-%% Union TypeCode.
-%% Switch - the union discriminator.
-%% Returns : Acc - A list of switches that are defined with the same
-%% ID - The switches common ID.
-%% Comment : A union IDL code can look like:
-%% union Union switch(long) {
-%% case 1:
-%% case 2: long ID; };
-%% In this case supplying Switch == 1 (or) the result
-%% should be {ok, [1,2], "ID"}
-%%------------------------------------------------------------
-switch2alias([], _Switch) ->
- %% Is it really possible to define an empty union??
- {ok, [], undefined};
-switch2alias([{Sw, ID, TC}|UList], Switch) ->
- switch2alias([{Sw, ID, TC}|UList], Switch, [], ID, false).
-
-
-switch2alias([{default, ID, _}], _, _, _, false) ->
- {ok, default, ID};
-switch2alias([], _, _Acc, _, false) ->
- {ok, [], undefined};
-switch2alias([], _, Acc, PreviousID, _) ->
- {ok, Acc, PreviousID};
-
-%% Seen the ID before but just found the correct switch, e.g.,
-%% [... {0,"K",{tk_string,0}}, {2,"K",{tk_string,0}}...] and switch eq '2'
-switch2alias([{Switch, PreviousID, _}|T], Switch, Acc, PreviousID, _Found) ->
- switch2alias(T, Switch, [Switch|Acc], PreviousID, true);
-
-%% First time for this ID and found the correct switch
-switch2alias([{Switch, ID, _}|T], Switch, _Acc, _PreviousID, false) ->
- switch2alias(T, Switch, [Switch], ID, true);
-
-%% Seen this ID and found the correct switch before.
-switch2alias([{Sw, PreviousID, _}|T], Switch, Acc, PreviousID, true) ->
- switch2alias(T, Switch, [Sw|Acc], PreviousID, true);
-
-%% Seen this ID but not found the correct switch.
-switch2alias([{Sw, PreviousID, _}|T], Switch, Acc, PreviousID, false) ->
- switch2alias(T, Switch, [Sw|Acc], PreviousID, false);
-
-%% No more of the correct ID/Switch. Done.
-switch2alias([{_, _ID, _}|_], _, Acc, PreviousID, true) ->
- {ok, Acc, PreviousID};
-%% Not found correct switch and ID is updated.
-switch2alias([{Sw, ID, _}|T], Switch, _Acc, _PreviousID, Found) ->
- switch2alias(T, Switch, [Sw], ID, Found).
-
-
-%%------------------------------------------------------------
-%% function : get_field
-%% Arguments: ID - element name
-%% List - The list of elements contained in the
-%% TypeCode.
-%% Returns : false |
-%% offset
-%%------------------------------------------------------------
-get_field(ID, List) ->
- get_field(ID, List, 2).
-get_field(_ID, [], _) ->
- false;
-get_field(ID, [ID|_], I) ->
- %% Memberlists in enum.
- I;
-get_field(ID, [{ID,_}|_], I) ->
- %% Memberlists in structs.
- I;
-get_field(ID, [_|T], I) ->
- get_field(ID, T, I+1).
-
-%%------------------------------------------------------------
-%% function : check_types
-%% Arguments: A sequence of CosNotification::EventType{}, i.e.,
-%% name-value pairs.
-%% Returns : {ok, WhichType, WC}
-%% WhichType - type/domain/both
-%% WC - [Types using wildcard]
-%%------------------------------------------------------------
-%% With check_types we try to determin if one or more EventTypes force us to check
-%% all events against this constraint. For example:
-%% EventType A1 has domain_name="car",type_name = "*"
-%% EventType A2 has domain_name="*",type_name = "DodgeViper"
-%% Since A1 says that we must test against any type_name and A2
-%% against any domain_name, we must test all events using these permutations.
-%% It's better to do these test now instead of when we are up and running. But
-%% if a client change the constraints VERY often it's up to them and they have
-%% to accept the delay.
-%%------------------------------------------------------------
-
-%% If types is an empty list it means that this constraint must be used
-%% for all events.
-check_types([]) -> true;
-check_types(Types) -> check_types(Types, both, []).
-check_types([], Which, WildCard) -> {ok, Which, WildCard};
-%% The following cases means that all events matches.
-check_types([#'CosNotification_EventType'{domain_name="",type_name = ""}|_T],_,_) ->
- true;
-check_types([#'CosNotification_EventType'{domain_name="",type_name = "*"}|_T],_,_) ->
- true;
-check_types([#'CosNotification_EventType'{domain_name="*",type_name = ""}|_T],_,_) ->
- true;
-check_types([#'CosNotification_EventType'{domain_name="*",type_name = "*"}|_T],_,_) ->
- true;
-%% The following cases means that all events must be tested using this constraint.
-check_types([#'CosNotification_EventType'{domain_name="",type_name = Ty}|T], domain,WC) when is_list(Ty) ->
- check_wildcard(T, all, WC, "", Ty);
-check_types([#'CosNotification_EventType'{domain_name="*",type_name = Ty}|T], domain, WC) when is_list(Ty) ->
- check_wildcard(T, all, WC, "", Ty);
-check_types([#'CosNotification_EventType'{domain_name=Do,type_name = ""}|T], type,WC) when is_list(Do) ->
- check_wildcard(T, all, WC, Do, "");
-check_types([#'CosNotification_EventType'{domain_name=Do,type_name = "*"}|T], type,WC) when is_list(Do) ->
- check_wildcard(T, all, WC, Do, "");
-%% The following cases is used to prevent other cases from converting,
-%% for example, all->type.
-check_types([#'CosNotification_EventType'{domain_name="",type_name = Ty}|T], all,WC) when is_list(Ty) ->
- check_wildcard(T, all, WC, "", Ty);
-check_types([#'CosNotification_EventType'{domain_name="*",type_name = Ty}|T], all,WC) when is_list(Ty) ->
- check_wildcard(T, all, WC, "", Ty);
-check_types([#'CosNotification_EventType'{domain_name=Do,type_name = ""}|T], all,WC) when is_list(Do) ->
- check_wildcard(T, all, WC, Do, "");
-check_types([#'CosNotification_EventType'{domain_name=Do,type_name = "*"}|T], all,WC) when is_list(Do) ->
- check_wildcard(T, all, WC, Do, "");
-%% The following cases means that all events with matching Type must be
-%% tested using this constraint.
-check_types([#'CosNotification_EventType'{domain_name="",type_name = Ty}|T], _W,WC) when is_list(Ty) ->
- check_wildcard(T, type, WC, "", Ty);
-check_types([#'CosNotification_EventType'{domain_name="*",type_name = Ty}|T], _W,WC) when is_list(Ty) ->
- check_wildcard(T, type, WC, "", Ty);
-%% The following cases means that all events with matching Domain must be
-%% tested using this constraint.
-check_types([#'CosNotification_EventType'{domain_name=Do,type_name = ""}|T], _W,WC) when is_list(Do) ->
- check_wildcard(T, domain, WC, Do, "");
-check_types([#'CosNotification_EventType'{domain_name=Do,type_name = "*"}|T], _W,WC) when is_list(Do) ->
- check_wildcard(T, domain, WC, Do, "");
-%% Sorry, no shortcuts.
-check_types([#'CosNotification_EventType'{domain_name=Do,type_name=Ty}|T], W,WC) when is_list(Do) andalso is_list(Ty) ->
- check_wildcard(T, W, WC, Do, Ty);
-check_types([H|_], _,_) when is_record(H, 'CosNotification_EventType') ->
- %% Not valid.
- corba:raise(#'CosNotifyComm_InvalidEventType'{type=H});
-check_types(_,_,_) ->
- %% Wasn't even a correct input.
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-check_wildcard(Types, Which, WC, Domain, Type) ->
- NewWC =
- case {string:chr(Domain, $*), string:chr(Type, $*)} of
- {0, 0} ->
- WC;
- {0, _}->
- [{type, Domain, convert_wildcard(Type, [])}|WC];
- {_, 0}->
- [{domain, convert_wildcard(Domain, []), Type}|WC];
- _->
- [{both, convert_wildcard(Domain, []), convert_wildcard(Type, [])}|WC]
- end,
- check_types(Types, Which, NewWC).
-
-%% Change '*' to '.*', see re:compile/1 documentation.
-convert_wildcard([], Acc) ->
- case re:compile(lists:reverse(Acc)) of
- {ok, Expr} ->
- Expr;
- _ ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end;
-convert_wildcard([$*|T], Acc) ->
- convert_wildcard(T, [$*, $.|Acc]);
-convert_wildcard([H|T], Acc) ->
- convert_wildcard(T, [H|Acc]).
-
-%%------------------------------------------------------------
-%% function : match_types
-%% Arguments: A sequence of {Which, Domain, Type}, i.e., the same as
-%% returned from cosNotification_Filter:check_types/3
-%% Returns : bolean()
-%%------------------------------------------------------------
-match_types(_, _, []) ->
- false;
-match_types(Domain, Type, [{domain, WCDomain, Type}|T]) ->
- L=length(Domain),
- case catch re:run(Domain, WCDomain) of
- nomatch ->
- match_types(Domain, Type, T);
- {match, [{0, L}]} ->
- true;
- _->
- match_types(Domain, Type, T)
- end;
-match_types(Domain, Type, [{type, Domain, WCType}|T]) ->
- L=length(Type),
- case catch re:run(Type, WCType) of
- nomatch ->
- match_types(Domain, Type, T);
- {match, [{0, L}]} ->
- true;
- _->
- match_types(Domain, Type, T)
- end;
-match_types(Domain, Type, [{both, WCDomain, WCType}|T]) ->
- L1=length(Domain),
- case catch re:run(Domain, WCDomain) of
- nomatch ->
- match_types(Domain, Type, T);
- {match, [{0, L1}]} ->
- L2=length(Type),
- case catch re:run(Type, WCType) of
- nomatch ->
- match_types(Domain, Type, T);
- {match, [{0, L2}]} ->
- true;
- _ ->
- match_types(Domain, Type, T)
- end;
- _->
- match_types(Domain, Type, T)
- end;
-match_types(Domain, Type, [_|T]) ->
- match_types(Domain, Type, T).
-
-%%------------------------------------------------------------
-%% function : validate_types
-%% Arguments: A sequence of CosNotification::EventType{}, i.e.,
-%% name-value pairs.
-%% Returns : ok |
-%% {'EXCEPTION', #'CosNotifyComm_InvalidEventType'{}}
-%%------------------------------------------------------------
-
-validate_types([]) ->
- ok;
-validate_types([#'CosNotification_EventType'{domain_name=Do,type_name=Ty}|T])
- when is_list(Do) andalso is_list(Ty) ->
- validate_types(T);
-validate_types([H|_])
- when is_record(H, 'CosNotification_EventType') ->
- %% Not valid.
- corba:raise(#'CosNotifyComm_InvalidEventType'{type=H});
-validate_types(_) ->
- %% Wasn't even a correct input.
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/src/cosNotification_Grammar.yrl b/lib/cosNotification/src/cosNotification_Grammar.yrl
deleted file mode 100644
index f4a42d022e..0000000000
--- a/lib/cosNotification/src/cosNotification_Grammar.yrl
+++ /dev/null
@@ -1,168 +0,0 @@
-%%--------------------------------------------------------------------
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%--------------------------------------------------------------------
-%% File : cosNotification_Grammar.yrl
-%% Purpose : Implement the constraint grammar for CosNotification filters.
-%%--------------------------------------------------------------------
-
-Nonterminals
- '<toplevel>' '<constraint>' '<expr>' '<bool>' '<bool_or>' '<Ident>'
- '<bool_and>' '<bool_compare>' '<expr_in>' '<expr_twiddle>' '<term>'
- '<factor_not>' '<factor>' '<Component>' '<CompExt>' '<CompDot>' '<UnionVal>'.
-
-Terminals
-% 'dbslsh' 'bslshd'
- 'bslsh' 'ident' 'string'
- '_length' '_d''_type_id' '_repos_id'
- 'not' 'or' 'and' 'num'
- 'in' '~' '.' 'dollar'
- 'ADDOP' 'RELOP' 'MULOP' 'default' 'exist'
- 'TRUE' 'FALSE'
- '(' ')' '[' ']' 'int'.
-
-Left 100 'or'.
-Left 200 'and'.
-%Nonassoc 300 'RELOP'. % '==', '!=', '<', '>', '<=', '=>'
-Left 300 'RELOP'.
-%Nonassoc 400 'in'.
-Left 400 'in'.
-%Nonassoc 500 '~'.
-Left 500 '~'.
-Left 600 'ADDOP'. % '+', '-'
-Left 700 'MULOP'. % '*', '/'
-Unary 800 'not'.
-Unary 900 'exist'.
-Unary 900 'default'.
-%Unary 900 'u-'. % unary minus
-
-Rootsymbol '<toplevel>'.
-Endsymbol '$end'.
-
-'<toplevel>' -> '$empty' : '$empty'.
-'<toplevel>' -> '<constraint>' : '$1'.
-
-'<constraint>' -> '<bool>' : '$1'.
-
-'<bool>' -> '<bool_or>' : '$1'.
-
-'<bool_or>' -> '<bool_or>' 'or' '<bool_and>' : {'or', '$1', '$3'}.
-'<bool_or>' -> '<bool_and>' : '$1'.
-
-'<bool_and>' -> '<bool_and>' 'and' '<bool_compare>' : {'and', '$1', '$3'}.
-'<bool_and>' -> '<bool_compare>' : '$1'.
-
-'<bool_compare>' -> '<expr_in>' 'RELOP' '<expr_in>' : {element(2, '$2'), '$1', '$3'}.
-'<bool_compare>' -> '<expr_in>' : '$1'.
-
-'<expr_in>' -> '<expr_twiddle>' : '$1'.
-'<expr_in>' -> '<expr_twiddle>' 'in' '<Ident>' : {'in', '$1', '$3'}.
-'<expr_in>' -> '<expr_twiddle>' 'in' 'dollar' '<Component>' : {'in', '$1', examin_comp({'component', '$4'})}.
-
-'<expr_twiddle>' -> '<expr>' : '$1'.
-'<expr_twiddle>' -> '<expr>' '~' '<expr>' : {'~', '$1', '$3'}.
-
-'<expr>' -> '<term>' : '$1'.
-'<expr>' -> '<expr>' 'ADDOP' '<term>' : {element(2, '$2'), '$1', '$3'}.
-
-'<term>' -> '<factor_not>' : '$1'.
-'<term>' -> '<term>' 'MULOP' '<factor_not>' : {element(2, '$2'), '$1', '$3'}.
-
-'<factor_not>' -> '<factor>' : '$1'.
-'<factor_not>' -> 'not' '<factor>' : {'not', '$2'}.
-
-'<factor>' -> '(' '<bool_or>' ')' : '$2'.
-'<factor>' -> 'num' : element(2, '$1').
-'<factor>' -> 'int' : element(2, '$1').
-'<factor>' -> 'string' : element(2, '$1').
-'<factor>' -> 'TRUE' : 'true'.
-'<factor>' -> 'FALSE' : 'false'.
-'<factor>' -> 'ADDOP' 'num' : create_unary(element(2, '$1'), element(2, '$2')).
-'<factor>' -> 'ADDOP' 'int' : create_unary(element(2, '$1'), element(2, '$2')).
-'<factor>' -> '<Ident>' : list_to_atom('$1').
-'<factor>' -> 'dollar' '<Component>' : examin_comp({component, '$2'}).
-'<factor>' -> 'default' 'dollar' '<Component>' : examin_comp({'default_component', '$3'}).
-'<factor>' -> 'exist' 'dollar' '<Component>' : examin_comp({'exist_component', '$3'}).
-
-%% The following rules are used to create Components. The format used is:
-%% [...]
-'<Component>' -> '.' '<CompDot>' : '$2'.
-'<Component>' -> '[' 'int' ']' '<CompExt>' : [{'arrindex', element(2, '$2')} | '$4']. %% CompArray
-'<Component>' -> '(' '<Ident>' ')' '<CompExt>' : [{'associd', '$2'} | '$4']. %%CompAssoc
-'<Component>' -> '<Ident>' '<CompExt>' : [{'varid', '$1'} | '$2']. %% run-time variable
-'<Component>' -> '$empty' : [].
-
-'<CompExt>' -> '.' '<CompDot>' : '$2'.
-'<CompExt>' -> '[' 'int' ']' '<CompExt>' : [{'arrindex', element(2, '$2')} | '$4']. %% CompArray
-'<CompExt>' -> '(' '<Ident>' ')' '<CompExt>' : [{'associd', '$2'} | '$4']. %%CompAssoc
-'<CompExt>' -> '$empty' : [].
-
-'<CompDot>' -> '<Ident>' '<CompExt>' : [{'dotid', '$1'} | '$2'].
-'<CompDot>' -> 'int' '<CompExt>' : [{'dotint', element(2, '$1')} | '$2']. %% ComPos
-'<CompDot>' -> '(' '<UnionVal>' ')' '<CompExt>' : ['$2' | '$4']. %% UnionPos
-'<CompDot>' -> '_length' : ['_length']. %% arrays or sequences ONLY
-'<CompDot>' -> '_d' : ['_d']. %% discriminated unions ONLY
-'<CompDot>' -> '_type_id' : ['_type_id']. %% ok if info can be obtained
-'<CompDot>' -> '_repos_id' : ['_repos_id']. %% ok if info can be obtained
-
-'<Ident>' -> 'ident' : element(2, '$1').
-'<Ident>' -> 'bslsh' 'ident' : element(2, '$2').
-
-'<UnionVal>' -> 'int' : {'uint', element(2, '$1')}.
-'<UnionVal>' -> 'ADDOP' 'int' : {'uint', create_unary(element(2, '$1'), element(2, '$2'))}.
-'<UnionVal>' -> 'string' : {'ustr', element(2, '$1')}.
-'<UnionVal>' -> '$empty': 'default'.
-
-Erlang code.
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2009. 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%
-%%
-%%----------------------------------------------------------------------
-%% File : cosNotification_Grammar.erl
-%% Purpose : THIS FILE HAS BEEN GENERATED. DO NOT EDIT!!!!
-%%----------------------------------------------------------------------
-
--include("CosNotification_Definitions.hrl").
-
-create_unary('+', Val) when is_number(Val) -> Val;
-create_unary('-', Val) when is_number(Val) -> -Val;
-create_unary(_, _) -> return_error(0, "syntax error").
-
-examin_comp({T, []}) ->
- {T, '$empty'};
-examin_comp(V) ->
- V.
-
diff --git a/lib/cosNotification/src/cosNotification_Scanner.erl b/lib/cosNotification/src/cosNotification_Scanner.erl
deleted file mode 100644
index 31f27a8d78..0000000000
--- a/lib/cosNotification/src/cosNotification_Scanner.erl
+++ /dev/null
@@ -1,269 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : cosNotification_Scanner.erl
-%% Purpose : Scan and pre-process a grammar.
-%%----------------------------------------------------------------------
-
--module('cosNotification_Scanner').
-
--export([scan/1]).
-
-scan(Str) ->
- RSL = scan(Str, 1, [], any),
- {ok, lists:reverse(RSL)}.
-
-
-%% Guard macros used at top scan functions only
--define(is_number(X), X >= $0, X =< $9).
--define(is_upper(X), X >= $A, X =< $Z).
--define(is_lower(X), X >= $a, X =< $z).
-
-%%----------------------------------------------------------------------
-%% scan
-%%
-%% A-Z
-scan([X|Str], Line, Out, Type) when ?is_upper(X) ->
- scan_name(Str, [X], Line, Out, Type);
-%% a-z
-scan([X|Str], Line, Out, Type) when ?is_lower(X) ->
- scan_name(Str, [X], Line, Out, Type);
-%% 0-9
-scan([X|Str], Line, Out, Type) when ?is_number(X) ->
- scan_number(Str, [X], Line, Out, Type);
-
-%% RELOP:s == != <= >= > <
-scan([$=,$= | Str], Line, Out, _Type) ->
- scan(Str, Line, [{'RELOP', '=='} | Out], any);
-scan([$!,$= | Str], Line, Out, _Type) ->
- scan(Str, Line, [{'RELOP', '!='} | Out], any);
-scan([$<,$= | Str], Line, Out, _Type) ->
- scan(Str, Line, [{'RELOP', '<='} | Out], any);
-scan([$>,$= | Str], Line, Out, _Type) ->
- scan(Str, Line, [{'RELOP', '>='} | Out], any);
-scan([$> | Str], Line, Out, _Type) ->
- scan(Str, Line, [{'RELOP', '>'} | Out], any);
-scan([$< | Str], Line, Out, _Type) ->
- scan(Str, Line, [{'RELOP', '<'} | Out], any);
-
-%% ADDOP:s + -
-scan([$+ | Str], Line, Out, Type) ->
- scan(Str, Line, [{'ADDOP', '+'} | Out], Type);
-scan([$- | Str], Line, Out, Type) ->
- scan(Str, Line, [{'ADDOP', '-'} | Out], Type);
-
-%% MULOP:s * /
-scan([$* | Str], Line, Out, _Type) ->
- scan(Str, Line, [{'MULOP', '*'} | Out], any);
-scan([$/ | Str], Line, Out, _Type) ->
- scan(Str, Line, [{'MULOP', '/'} | Out], any);
-
-%% TAB
-scan([9| T], Line, Out, Type) -> scan(T, Line, Out, Type);
-%% SP
-scan([32| T], Line, Out, Type) -> scan(T, Line, Out, Type);
-%% CR
-scan([$\r|Str], Line, Out, Type) ->
- scan(Str, Line, Out, Type);
-%% LF
-scan([$\n|Str], Line, Out, Type) ->
- scan(Str, Line+1, Out, Type);
-%% \\
-scan([92, 92 | Str], Line, Out, Type) ->
- scan(Str, Line, [{'dbslsh', Line} | Out], Type);
-%% \'
-scan([92, 39 | Str], Line, Out, Type) ->
- scan(Str, Line, [{'bslshd', Line} | Out], Type);
-%% '\'
-scan([92 | Str], Line, Out, Type) ->
- scan(Str, Line, [{'bslsh', Line} | Out], Type);
-%% '_'
-scan([$_ | Str], Line, Out, dollar) ->
- scan_name(Str, [$_], Line, Out, dollar);
-%% '$'
-scan([$$, 92 | Str], Line, Out, _Type) ->
- scan(Str, Line, [{'bslsh', Line}, {'dollar', Line} | Out], dollar);
-scan([$$ | Str], Line, Out, _Type) ->
- scan(Str, Line, [{'dollar', Line} | Out], dollar);
-scan([$"|Str], Line, Out, Type) ->
- scan_const(char, Str, [], Line, Out, Type);
-scan([$'|Str], Line, Out, Type) ->
- scan_const(string, Str, [], Line, Out, Type);
-
-%% Writing '+.<CompDot>' is not allowed ('+' or '-' are only allowed
-%% as unary for <UnionVal> (within a component) which must be en integer).
-scan([$. | Str], Line, [{'ADDOP', Op}|Out], _) ->
- scan_frac(Str, [$.], Line, [{'ADDOP', Op}|Out], any);
-%% Must be a <CompDot>
-scan([$. | Str], Line, Out, dollar) ->
- scan(Str, Line, [{'.',Line} | Out], dollar);
-%% Number
-scan([$. | Str], Line, Out, Type) ->
- scan_frac(Str, [$.], Line, Out, Type);
-scan([C|Str], Line, Out, Type) ->
- scan(Str, Line, [{list_to_atom([C]), Line} | Out], Type);
-
-scan([], _Line, Out, _Type) ->
- Out.
-
-%%----------------------------------------------------------------------
-%% scan_name
-%%
-
-scan_number([X|Str], Accum, Line, Out, Type) when ?is_number(X) ->
- scan_number(Str, [X|Accum], Line, Out, Type);
-scan_number([X|Str], Accum, Line, Out, dollar) when X==$. ->
- scan(Str, Line, [{'.', Line},
- {'int', list_to_integer(lists:reverse(Accum))} | Out], dollar);
-scan_number([X|Str], Accum, Line, Out, Type) when X==$. ->
- scan_frac(Str, [X|Accum], Line, Out, Type);
-scan_number([X|Str], Accum, Line, Out, Type) when X==$e ->
- scan_exp(Str, [X|Accum], Line, Out, Type);
-scan_number([X|Str], Accum, Line, Out, Type) when X==$E ->
- scan_exp(Str, [X|Accum], Line, Out, Type);
-scan_number(Str, Accum, Line, Out, Type) ->
- scan(Str, Line, [{'int', list_to_integer(lists:reverse(Accum))} | Out], Type).
-
-
-%% Floating point number scan.
-%%
-%% Non trivial scan. A float consists of an integral part, a
-%% decimal point, a fraction part, an e or E and a signed integer
-%% exponent. Either the integer part or the fraction part but not
-%% both may be missing, and either the decimal point or the
-%% exponent part but not both may be missing. The exponent part
-%% must consist of an e or E and a possibly signed exponent.
-%%
-%% Analysis shows that "1." ".7" "1e2" ".5e-3" "1.7e2" "1.7e-2"
-%% is allowed and "1" ".e9" is not. The sign is only allowed just
-%% after an e or E. The scanner reads a number as an integer
-%% until it encounters a "." so the integer part only error case
-%% will not be caught in the scanner (but rather in expression
-%% evaluation)
-
-scan_frac([$e | _Str], [$.], _Line, _Out, _Type) ->
- {error, "illegal_float"};
-scan_frac([$E | _Str], [$.], _Line, _Out, _Type) ->
- {error, "illegal_float"};
-scan_frac(Str, Accum, Line, Out, Type) ->
- scan_frac2(Str, Accum, Line, Out, Type).
-
-scan_frac2([X|Str], Accum, Line, Out, Type) when ?is_number(X) ->
- scan_frac2(Str, [X|Accum], Line, Out, Type);
-scan_frac2([X|Str], Accum, Line, Out, Type) when X==$e ->
- scan_exp(Str, [X|Accum], Line, Out, Type);
-scan_frac2([X|Str], Accum, Line, Out, Type) when X==$E ->
- scan_exp(Str, [X|Accum], Line, Out, Type);
-%% Since '.2' is allowed, we add '0' in front to be sure (erlang do not allow
-%% list_to_float(".2") and list_to_float("0.2") eq. list_to_float("00.2")).
-scan_frac2(Str, Accum, Line, Out, Type) ->
- scan(Str, Line, [{'num', list_to_float([$0|lists:reverse(Accum)])} | Out], Type).
-
-scan_exp([X|Str], Accum, Line, Out, Type) when X==$- ->
- scan_exp2(Str, [X|Accum], Line, Out, Type);
-scan_exp(Str, Accum, Line, Out, Type) ->
- scan_exp2(Str, Accum, Line, Out, Type).
-
-scan_exp2([X|Str], Accum, Line, Out, Type) when ?is_number(X) ->
- scan_exp2(Str, [X|Accum], Line, Out, Type);
-%% Since '.2' is allowed, we add '0' in front to be sure (erlang do not allow
-%% list_to_float(".2")).
-scan_exp2(Str, Accum, Line, Out, Type) ->
- scan(Str, Line, [{'num', list_to_float([$0|lists:reverse(Accum)])} | Out], Type).
-
-
-scan_name([X|Str], Accum, Line, Out, Type) when ?is_upper(X) ->
- scan_name(Str, [X|Accum], Line, Out, Type);
-scan_name([X|Str], Accum, Line, Out, Type) when ?is_lower(X) ->
- scan_name(Str, [X|Accum], Line, Out, Type);
-scan_name([X|Str], Accum, Line, Out, Type) when ?is_number(X) ->
- scan_name(Str, [X|Accum], Line, Out, Type);
-scan_name([$_|Str], Accum, Line, Out, dollar) ->
- scan_name(Str, [$_|Accum], Line, Out, dollar);
-scan_name(S, Accum, Line, [{bslsh,LL} | Out], Type) ->
- %% An escaped identifier.
- L = lists:reverse(Accum),
- scan(S, Line, [{'ident', L}, {bslsh,LL} | Out], Type);
-scan_name(S, Accum, Line, Out, Type) ->
- L = lists:reverse(Accum),
- {X, NewType} = case check_name(L) of
- false ->
- {{'ident', L}, Type};
- _ ->
- {{list_to_atom(L), Line}, any}
- end,
- scan(S, Line, [X | Out], NewType).
-
-%% Shall scan a constant
-scan_const(char, [$" | Rest], Accum, Line, Out, Type) ->
- scan(Rest, Line,
- [{'ident', list_to_atom(lists:reverse(Accum))} | Out], Type);
-scan_const(char, [], _Accum, _Line, Out, _Type) -> %% Bad string
-% {error, "bad_string"};
- Out;
-scan_const(string, [$' | Rest], Accum, Line, Out, Type) ->
- scan(Rest, Line,
- [{'string', lists:reverse(Accum)} | Out], Type);
-scan_const(Mode, [$\\, C | Rest], Accum, Line, Out, Type) ->
- case escaped_char(C) of
- error ->
- %% Bad escape character
- %% {error, "bad_escape_character"};
- scan_const(Mode, Rest, [C | Accum], Line, Out, Type);
- EC ->
- scan_const(Mode, Rest, [EC | Accum], Line, Out, Type)
- end;
-scan_const(Mode, [C | Rest], Accum, Line, Out, Type) ->
- scan_const(Mode, Rest, [C | Accum], Line, Out, Type).
-
-%% Escaped character. Escaped chars are repr as two characters in the
-%% input list of letters and this is translated into one char.
-escaped_char($n) -> $\n;
-escaped_char($t) -> $\t;
-escaped_char($v) -> $\v;
-escaped_char($b) -> $\b;
-escaped_char($r) -> $ ;
-escaped_char($f) -> $\f;
-escaped_char($a) -> $\a;
-escaped_char($\\) -> $\\;
-escaped_char($?) -> $?;
-escaped_char($') -> $';
-escaped_char($") -> $";
-%% Error
-escaped_char(_Other) -> error.
-
-
-check_name("exist") -> true;
-check_name("default") -> true;
-check_name("_length") -> true;
-check_name("_d") -> true;
-check_name("_type_id") -> true;
-check_name("_repos_id") -> true;
-check_name("not") -> true;
-check_name("or") -> true;
-check_name("and") -> true;
-check_name("FALSE") -> true;
-check_name("TRUE") -> true;
-check_name("in") -> true;
-check_name(_) -> false.
-
-
diff --git a/lib/cosNotification/src/cosNotification_eventDB.erl b/lib/cosNotification/src/cosNotification_eventDB.erl
deleted file mode 100644
index cd3c74d617..0000000000
--- a/lib/cosNotification/src/cosNotification_eventDB.erl
+++ /dev/null
@@ -1,1351 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2015. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : cosNotification_eventDB.erl
-%% Purpose :
-%% Purpose : This module is supposed to centralize Event storage.
-%% Comments:
-%% * Setting Order Policy to AnyOrder eq. Priority order
-%%
-%% * Setting Discard Policy to AnyOrder eq. RejectNewEvents.
-%%
-%% * DB ordering: Since the deliver- and discard-order may differ we need
-%% two ets-tables, both of type 'ordered_set'. They contain:
-%% - table 1 (T1): deliver order key and the associated event.
-%% - table 2 (T2): discard order key.
-%%
-%% When adding a new event we add, if necessary, related keys in T2.
-%% For example, if we should discard events in FIFO order, the delivery
-%% order may be set to Priority order. If the Max Event limit is reached
-%% we first look in T2 to find out which event to discard by using and
-%% reorder the key elements. T2 gives {TimeStamp, Priority}, which is used
-%% to lookup in T1 as {Priority, TimeStamp}.
-%% A TimeStamp is always included in the DB keys, even if FIFO or LIFO
-%% is used, since lots of events probably will have the same prioity and
-%% with a little bit of bad luck some events will never be delivered.
-%%
-%% Note: deliver order AnyOrder and PriorityOrder is equal since the later
-%% is defined as default.
-%% discard order AnyOrder and RejectNewEvents is equal since the later
-%% is defined as default.
-%% The keys used is ('-' indicates T2 is not needed and, thus, not instantiated):
-%%
-%% T1 policy T1 Key T2 Policy T2 Key
-%% ------------------------------------------------------------------
-%% DeadlineOrder {DL, Key, Prio} PriorityOrder {Prio, Key, DL}
-%% DeadlineOrder {DL, Key} FifoOrder {Key, DL}
-%% DeadlineOrder {DL, Key} LifoOrder {Key, DL}
-%% DeadlineOrder {DL, Key} RejectNewEvents -
-%% DeadlineOrder {DL, Key} DeadlineOrder -
-%% FifoOrder {Key, DL} DeadlineOrder {DL, Key}
-%% FifoOrder {Key, Prio} PriorityOrder {Prio, Key}
-%% FifoOrder Key RejectNewEvents -
-%% FifoOrder Key Fifo -
-%% FifoOrder Key Lifo -
-%% PriorityOrder {Prio, Key, DL} DeadlineOrder {DL, Key, Prio}
-%% PriorityOrder {Prio, Key} Fifo {Key, Prio}
-%% PriorityOrder {Prio, Key} Lifo {Key, Prio}
-%% PriorityOrder {Prio, Key} RejectNewEvents -
-%% ------------------------------------------------------------------
-%% DL == Deadline, Key == TimeStamp, Prio == Priority
-%%
-%% NOTE: If defined, the Discard DB Keys are the same as in Event DB, except
-%% that the first and last Key change place. {K1,K2}<->{K2,K1} and
-%% {K1,K2,K3}<->{K3,K2,K1}.
-%%----------------------------------------------------------------------
--module(cosNotification_eventDB).
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
--include_lib("cosTime/include/TimeBase.hrl").
-
-%% Application files
--include("CosNotification.hrl").
--include("CosNotifyChannelAdmin.hrl").
--include("CosNotifyComm.hrl").
--include("CosNotifyFilter.hrl").
-
--include("CosNotification_Definitions.hrl").
-
-%%--------------- EXPORTS ------------------------------------
-%% Internal Filter Functions
--export([validate_event/5,
- create_db/4,
- destroy_db/1,
- get_event/1,
- get_event/2,
- get_events/2,
- get_events/3,
- delete_events/1,
- update/2,
- update/4,
- add_event/2,
- add_event/4,
- add_and_get_event/2,
- add_and_get_event/3,
- add_and_get_event/4,
- add_and_get_event/5,
- gc_events/2,
- gc_events_local/4,
- gc_start/2,
- filter_events/2,
- filter_events/3,
- status/2]).
-
-%%--------------- DATA STRUCTURES ----------------------------
--record(dbRef, {orderRef, discardRef, orderPolicy, discardPolicy,
- defPriority, maxEvents, defStopT, startTsupport,
- stopTsupport, gcTime, gcLimit, timeRef}).
-
-
-
-%%--------------- DEFINES ------------------------------------
-
--define(CreateRef(OR, DR, O, D, DP, ME, DS, StaT, StoT, GT, GL, TR),
- #dbRef{orderRef=OR, discardRef=DR, orderPolicy=O, discardPolicy=D,
- defPriority=DP, maxEvents=ME, defStopT=DS, startTsupport=StaT,
- stopTsupport=StoT, gcTime=GT, gcLimit=round(ME*GL/100),
- timeRef=TR}).
-
-
--define(get_OrderP(DR), DR#dbRef.orderPolicy).
--define(get_DiscardP(DR), DR#dbRef.discardPolicy).
--define(get_OrderRef(DR), DR#dbRef.orderRef).
--define(get_DiscardRef(DR), DR#dbRef.orderRef).
--define(get_DefPriority(DR), DR#dbRef.defPriority).
--define(get_MaxEvents(DR), DR#dbRef.maxEvents).
--define(get_DefStopT(DR), DR#dbRef.defStopT).
--define(get_StartTsupport(DR), DR#dbRef.startTsupport).
--define(get_StopTsupport(DR), DR#dbRef.stopTsupport).
--define(get_GCTime(DR), DR#dbRef.gcTime).
--define(get_GCLimit(DR), DR#dbRef.gcLimit).
--define(get_TimeRef(DR), DR#dbRef.timeRef).
-
--define(set_OrderP(DR, O), DR#dbRef{orderPolicy = O}).
--define(set_DiscardP(DR, D), DR#dbRef{discardPolicy = D}).
--define(set_OrderRef(DR, E), DR#dbRef{orderRef = E}).
--define(set_DiscardRef(DR, E), DR#dbRef{orderRef = E}).
--define(set_DefPriority(DR, DP), DR#dbRef{defPriority = DP}).
--define(set_MaxEvents(DR, ME), DR#dbRef{maxEvents = ME}).
--define(set_DefStopT(DR, DS), DR#dbRef{defStopT = DS}).
--define(set_StartTsupport(DR, B), DR#dbRef{startTsupport = B}).
--define(set_StopTsupport(DR, B), DR#dbRef{stopTsupport = B}).
-
--define(is_StartTNotSupported(DR), DR#dbRef.startTsupport == false).
--define(is_StopTNotSupported(DR), DR#dbRef.stopTsupport == false).
--define(is_TimeoutNotUsed(DR), DR#dbRef.defStopT == 0).
-
-
-%%------------------------------------------------------------
-%% function : status
-%% Arguments: DBRef
-%% Key - which information we want.
-%% Returns : Data related to the Key.
-%%------------------------------------------------------------
-status(DBRef, eventCounter) ->
- ets:info(?get_OrderRef(DBRef), size);
-status(DBRef, {batchLimit, Limit}) ->
- case ets:info(?get_OrderRef(DBRef), size) of
- Current when is_integer(Current) andalso Current >= Limit ->
- ?debug_print("BATCH LIMIT (~p) REACHED, CONTAINS: ~p~n", [Limit, Current]),
- true;
- _Other ->
- ?debug_print("BATCH LIMIT (~p) NOT REACHED, CONTAINS: ~p~n",
- [Limit, _Other]),
- false
- end;
-status(DBRef, {batchLimit, Limit, TemporaryMax}) ->
- case ets:info(?get_OrderRef(DBRef), size) of
- Current when is_integer(Current) andalso Current >= TemporaryMax ->
- ?debug_print("MAX LIMIT (~p) REACHED, CONTAINS: ~p~n",
- [TemporaryMax, Current]),
- true;
- Current when is_integer(Current) andalso Current >= Limit ->
- ?debug_print("BATCH LIMIT (~p) REACHED, CONTAINS: ~p~n", [Limit, Current]),
- true;
- _Other ->
- ?debug_print("BATCH LIMIT (~p) NOT REACHED, CONTAINS: ~p~n",
- [Limit, _Other]),
- false
- end;
-status(_, _) ->
- error.
-
-
-%%------------------------------------------------------------
-%% function : gc_events_local
-%% Arguments: DBRef
-%% Returns :
-%% Comment : This function is intended for "emergency" GC, i.e.,
-%% when the DB must discard events we should first try
-%% to remove events with expired deadlines.
-%%------------------------------------------------------------
-gc_events_local(_, _, false, _) ->
- ok;
-gc_events_local(_, _, _, 0) ->
- ok;
-gc_events_local(ORef, DRef, _, _) ->
- gc_loop(ets:first(ORef), ORef, DRef).
-
-%%------------------------------------------------------------
-%% function : gc_events
-%% Arguments: DBRef
-%% Priority - 'low', 'medium' or 'high'; will determine
-%% how important a fast gc is.
-%% Returns :
-%% Comment : This function is intended for background GC.
-%%------------------------------------------------------------
-gc_events(DBRef, _Priority) when ?is_TimeoutNotUsed(DBRef) ->
- ok;
-gc_events(DBRef, _Priority) when ?is_StopTNotSupported(DBRef) ->
- ok;
-gc_events(DBRef, Priority) ->
- TS = erlang:monotonic_time(),
- {resolution, TR} = lists:keyfind(resolution, 1, erlang:system_info(os_monotonic_time_source)),
- case get(oe_GC_timestamp) of
- Num when TS > Num ->
- put(oe_GC_timestamp, TS + ?get_GCTime(DBRef) * TR),
- spawn_link(?MODULE, gc_start, [DBRef, Priority]);
- _->
- ok
- end.
-
-%%------------------------------------------------------------
-%% function : gc_start
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-gc_start(#dbRef{orderRef = ORef, discardRef = DRef}, Priority) ->
- process_flag(priority, Priority),
- gc_loop(ets:first(ORef), ORef, DRef).
-
-gc_loop('$end_of_table', _, _) ->
- ok;
-gc_loop(Key, ORef, DRef) ->
- [{Keys,DL,_,_,_}]=ets:lookup(ORef, Key),
- case check_deadline(DL) of
- true when DRef == undefined ->
- ets:delete(ORef, Key);
- true ->
- ets:delete(ORef, Key),
- gc_discard_DB(Keys, DRef);
- _ ->
- ok
- end,
- gc_loop(ets:next(ORef, Key), ORef, DRef).
-
-gc_discard_DB({Key1, Key2}, DRef) ->
- ets:delete(DRef, {Key2, Key1});
-gc_discard_DB({Key1, Key2, Key3}, DRef) ->
- ets:delete(DRef, {Key3, Key2, Key1}).
-
-%%------------------------------------------------------------
-%% function : create_FIFO_Key
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-create_FIFO_Key() ->
- {M, S, U} = erlang:timestamp(),
- -M*1000000000000 - S*1000000 - U.
-
-%%------------------------------------------------------------
-%% function : convert_FIFO_Key
-%% Arguments:
-%% Returns : A timestamp tuple
-%% Comment : Used when we must reuse a timestamp, i.e., only
-%% when we must reorder the DB.
-%%------------------------------------------------------------
-convert_FIFO_Key(Key) ->
- K = abs(Key),
- Secs = trunc(K/1000000),
- M = trunc(K/1000000000000),
- S = Secs-M*1000000,
- U = K - S*1000000-M*1000000000000,
- {M, S, U}.
-
-%%------------------------------------------------------------
-%% function : extract_priority
-%% Arguments: Event
-%% Defalt Value
-%% Mapping Filter Value
-%% - false value not needed (depends on QoS type)
-%% - undefined value needed but no filter associated.
-%% Returns :
-%%------------------------------------------------------------
-extract_priority(_, _, false) ->
- false;
-extract_priority(#'CosNotification_StructuredEvent'
- {header = #'CosNotification_EventHeader'
- {variable_header = VH}}, DefPriority, undefined) ->
- extract_value(VH, ?not_Priority, DefPriority);
-%% Maybe a unstructured event.
-extract_priority(_, DefPriority, undefined) ->
- DefPriority;
-extract_priority(_, _, PriorityOverride) ->
- %% Must have an associated MappingFilter for Priority.
- PriorityOverride.
-
-%%------------------------------------------------------------
-%% function : extract_start_time
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-extract_start_time(_, false, _) ->
- false;
-extract_start_time(#'CosNotification_StructuredEvent'
- {header = #'CosNotification_EventHeader'
- {variable_header = VH}}, _, TRef) ->
- ST = case extract_value(VH, ?not_StartTime, undefined) of
- UTC when is_record(UTC, 'TimeBase_UtcT') ->
- UTC;
- _ ->
- false
- end,
- convert_time(ST, TRef, erlang:timestamp());
-extract_start_time(_, _, _) ->
- false.
-
-%%------------------------------------------------------------
-%% function : extract_deadline
-%% Arguments: Structured Event
-%% Default Timeout Value - TimeT or UtcT (see cosTime).
-%% StopTSupported - boolean().
-%% TRef - reference to TimeService
-%% Mapping Filter Value
-%% - false eq. value not needed (depends on QoS type)
-%% - undefined eq. value needed but no filter associated.
-%% Now - used when we want to reuse old TimeStamp which
-%% must be done when changing QoS.
-%% Returns : A modified return from erlang:timestamp().
-%%------------------------------------------------------------
-extract_deadline(_, _, _, _, false) ->
- false;
-extract_deadline(Event, DefaultT, StopTSupported, TRef, MappingVal) ->
- extract_deadline(Event, DefaultT, StopTSupported, TRef, MappingVal, erlang:timestamp()).
-
-extract_deadline(_, _, _, _, false, _) ->
- false;
-extract_deadline(#'CosNotification_StructuredEvent'
- {header = #'CosNotification_EventHeader'
- {variable_header = VH}}, DefaultT, StopTSupported,
- TRef, undefined, Now) ->
- DL = case extract_value(VH, ?not_Timeout, undefined) of
- undefined when StopTSupported == true, TRef =/= undefined ->
- case extract_value(VH, ?not_StopTime, undefined) of
- undefined ->
- DefaultT;
- DefinedTime ->
- DefinedTime
- end;
- undefined ->
- DefaultT;
- DefinedTime ->
- DefinedTime
- end,
- convert_time(DL, TRef, Now);
-%% Maybe a unstructured event.
-extract_deadline(_, Time, _, TRef, undefined, Now) ->
- convert_time(Time, TRef, Now);
-extract_deadline(_, _, _, TRef, DOverride, Now) ->
- %% Must have an associated MappingFilter defining a Deadline.
- convert_time(DOverride, TRef, Now).
-
-convert_time(0, _, _) ->
- false;
-convert_time(UTC, TRef, {M,S,U}) when is_record(UTC, 'TimeBase_UtcT') ->
- case catch get_time_diff(UTC, TRef) of
- {'EXCEPTION', _} ->
- false;
- {'EXIT', _} ->
- false;
- DL ->
- MicroSecs = round(DL/10),
- Secs = round(MicroSecs/1000000),
- MegaSecs = round(Secs/1000000),
- {-M-MegaSecs, -S-Secs+MegaSecs, -U-MicroSecs+Secs}
- end;
-convert_time(DL, _, {M,S,U}) when is_integer(DL) ->
- MicroSecs = round(DL/10),
- Secs = round(MicroSecs/1000000),
- MegaSecs = round(Secs/1000000),
- {-M-MegaSecs, -S-Secs+MegaSecs, -U-MicroSecs+Secs};
-convert_time(_, _, _) ->
- false.
-
-
-get_time_diff(UTC, TRef) ->
- UTO = 'CosTime_TimeService':universal_time(TRef),
- UTO2 = 'CosTime_TimeService':uto_from_utc(TRef, UTC),
- TIO = 'CosTime_UTO':time_to_interval(UTO, UTO2),
- #'TimeBase_IntervalT'{lower_bound=LB, upper_bound = UB} =
- 'CosTime_TIO':'_get_time_interval'(TIO),
- UB-LB.
-
-check_deadline(DL) when is_tuple(DL) ->
- {M,S,U} = erlang:timestamp(),
- DL >= {-M,-S,-U};
-check_deadline(_DL) ->
- %% This case will cover if no timeout is set.
- false.
-
-check_start_time(ST) when is_tuple(ST) ->
- {M,S,U} = erlang:timestamp(),
- ST >= {-M,-S,-U};
-check_start_time(_ST) ->
- %% This case will cover if no earliest delivery time is set.
- true.
-
-%%------------------------------------------------------------
-%% function : extract_value
-%% Arguments: A Property Sequence
-%% ID - wanted property string()
-%% Other - default-value.
-%% Returns : Value associated with given ID or default value.
-%%------------------------------------------------------------
-extract_value([], _, Other) ->
- Other;
-extract_value([#'CosNotification_Property'{name=ID, value=V}|_], ID, _) ->
- any:get_value(V);
-extract_value([_H|T], ID, Other) ->
- extract_value(T, ID, Other).
-
-%%------------------------------------------------------------
-%% function : get_event
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-get_event(DBRef) ->
- get_event(DBRef, true).
-get_event(DBRef, Delete) ->
- case get_events(DBRef, 1, Delete) of
- {[], false} ->
- {[], false};
- {[], false, Keys} ->
- {[], false, Keys};
- {[Event], Bool} ->
- {Event, Bool};
- {[Event], Bool, Keys} ->
- {Event, Bool, Keys}
- end.
-
-%%------------------------------------------------------------
-%% function : get_events
-%% Arguments:
-%% Returns : A list of events (possibly empty) and a boolean
-%% indicating if event found.
-%% Comments : Try to extract Max events from the database.
-%%------------------------------------------------------------
-get_events(#dbRef{orderRef = ORef, discardRef = DRef}, Max) ->
- event_loop(ets:last(ORef), ORef, DRef, Max, [], [], true).
-
-get_events(#dbRef{orderRef = ORef, discardRef = DRef}, Max, Delete) ->
- event_loop(ets:last(ORef), ORef, DRef, Max, [], [], Delete).
-
-event_loop('$end_of_table', _, _, _, [], _, true) ->
- {[], false};
-event_loop('$end_of_table', _, _, _, [], [], _) ->
- {[], false, []};
-event_loop('$end_of_table', _ORef, _, _, Accum, _Keys, true) ->
- {lists:reverse(Accum), true};
-event_loop('$end_of_table', _ORef, _, _, Accum, Keys, _) ->
- {lists:reverse(Accum), true, Keys};
-event_loop(_, _ORef, _, 0, [], _Keys, true) ->
- %% Only possible if some tries to pull a sequence of 0 events.
- %% Should we really test for this case?
- {[], false};
-event_loop(_, _ORef, _, 0, [], Keys, _) ->
- {[], false, Keys};
-event_loop(_, _ORef, _, 0, Accum, _Keys, true) ->
- {lists:reverse(Accum), true};
-event_loop(_, _ORef, _, 0, Accum, Keys, _) ->
- {lists:reverse(Accum), true, Keys};
-event_loop(Key, ORef, undefined, Left, Accum, Keys, Delete) ->
- [{_,DL,ST,_PO,Event}]=ets:lookup(ORef, Key),
- case check_deadline(DL) of
- true ->
- ets:delete(ORef, Key),
- event_loop(ets:prev(ORef, Key), ORef, undefined,
- Left, Accum, Keys, Delete);
- false ->
- case check_start_time(ST) of
- true when Delete == true ->
- ets:delete(ORef, Key),
- event_loop(ets:prev(ORef, Key), ORef, undefined,
- Left-1, [Event|Accum], Keys, Delete);
- true ->
- event_loop(ets:prev(ORef, Key), ORef, undefined,
- Left-1, [Event|Accum], [{ORef, Key}|Keys], Delete);
- false ->
- event_loop(ets:prev(ORef, Key), ORef, undefined,
- Left, Accum, Keys, Delete)
- end
- end;
-event_loop({Key1, Key2}, ORef, DRef, Left, Accum, Keys, Delete) ->
- [{_,DL,ST,_PO,Event}]=ets:lookup(ORef, {Key1, Key2}),
- case check_deadline(DL) of
- true ->
- ets:delete(ORef, {Key1, Key2}),
- ets:delete(DRef, {Key2, Key1}),
- event_loop(ets:prev(ORef, {Key1, Key2}), ORef, DRef,
- Left, Accum, Keys, Delete);
- false ->
- case check_start_time(ST) of
- true when Delete == true ->
- ets:delete(ORef, {Key1, Key2}),
- ets:delete(DRef, {Key2, Key1}),
- event_loop(ets:prev(ORef, {Key1, Key2}), ORef, DRef,
- Left-1, [Event|Accum], Keys, Delete);
- true ->
- event_loop(ets:prev(ORef, {Key1, Key2}), ORef, DRef,
- Left-1, [Event|Accum],
- [{ORef, {Key1, Key2}}, {DRef, {Key2, Key1}}|Keys],
- Delete);
- false ->
- event_loop(ets:prev(ORef, {Key1, Key2}), ORef, DRef,
- Left, Accum, Keys, Delete)
- end
- end;
-event_loop({Key1, Key2, Key3}, ORef, DRef, Left, Accum, Keys, Delete) ->
- [{_,DL,ST,_PO,Event}]=ets:lookup(ORef, {Key1, Key2, Key3}),
- case check_deadline(DL) of
- true ->
- ets:delete(ORef, {Key1, Key2, Key3}),
- ets:delete(DRef, {Key3, Key2, Key1}),
- event_loop(ets:prev(ORef, {Key1, Key2, Key3}), ORef, DRef,
- Left, Accum, Keys, Delete);
- false ->
- case check_start_time(ST) of
- true when Delete == true ->
- ets:delete(ORef, {Key1, Key2, Key3}),
- ets:delete(DRef, {Key3, Key2, Key1}),
- event_loop(ets:prev(ORef, {Key1, Key2, Key3}), ORef, DRef,
- Left-1, [Event|Accum], Keys, Delete);
- true ->
- event_loop(ets:prev(ORef, {Key1, Key2, Key3}), ORef, DRef,
- Left-1, [Event|Accum],
- [{ORef, {Key1, Key2, Key3}},
- {DRef, {Key3, Key2, Key1}}|Keys], Delete);
- false ->
- event_loop(ets:prev(ORef, {Key1, Key2, Key3}), ORef, DRef,
- Left, Accum, Keys, Delete)
- end
- end.
-
-%%------------------------------------------------------------
-%% function : delete_events
-%% Arguments: EventList - what's returned by get_event, get_events
-%% and add_and_get_event.
-%% Returns :
-%% Comment : Shall be invoked when it's safe to premanently remove
-%% the events found in the EventList.
-%%
-%%------------------------------------------------------------
-delete_events([]) ->
- ok;
-delete_events([{DB, Key}|T]) ->
- ets:delete(DB, Key),
- delete_events(T).
-
-%%------------------------------------------------------------
-%% function : update
-%% Arguments:
-%% Returns :
-%% Comment : As default we shall deliver Events in Priority order.
-%% Hence, if AnyOrder set we will still deliver in
-%% Priority order.
-%%------------------------------------------------------------
-update(undefined, _QoS) ->
- ok;
-update(DBRef, QoS) ->
- update(DBRef, QoS, undefined, undefined).
-
-update(DBRef, QoS, LifeFilter, PrioFilter) ->
- case updated_order(DBRef, ?not_GetOrderPolicy(QoS)) of
- false ->
- case updated_discard(DBRef, ?not_GetDiscardPolicy(QoS)) of
- false ->
- DBR2 = ?set_DefPriority(DBRef, ?not_GetPriority(QoS)),
- DBR3 = ?set_MaxEvents(DBR2, ?not_GetMaxEventsPerConsumer(QoS)),
- DBR4 = ?set_DefStopT(DBR3, ?not_GetTimeout(QoS)),
- DBR5 = ?set_StartTsupport(DBR4, ?not_GetStartTimeSupported(QoS)),
- DBR6 = ?set_StopTsupport(DBR5, ?not_GetStopTimeSupported(QoS)),
- case ets:info(?get_OrderRef(DBR6), size) of
- N when N =< ?get_MaxEvents(DBR6) ->
- %% Even if the QoS MaxEvents have been changed
- %% we don't reach the limit.
- DBR6;
- N ->
- %% The QoS MaxEvents must have been decreased.
- discard_events(DBR6, N-?get_MaxEvents(DBR6)),
- DBR6
- end;
- true ->
- destroy_discard_db(DBRef),
- NewDBRef = create_db(QoS, ?get_GCTime(DBRef), ?get_GCLimit(DBRef),
- ?get_TimeRef(DBRef)),
- move_events(DBRef, NewDBRef, ets:first(?get_OrderRef(DBRef)),
- LifeFilter, PrioFilter)
- end;
- true ->
- destroy_discard_db(DBRef),
- NewDBRef = create_db(QoS, ?get_GCTime(DBRef), ?get_GCLimit(DBRef),
- ?get_TimeRef(DBRef)),
- move_events(DBRef, NewDBRef, ets:first(?get_OrderRef(DBRef)),
- LifeFilter, PrioFilter)
- end.
-
-updated_order(#dbRef{orderPolicy = Equal}, Equal) -> false;
-updated_order(#dbRef{orderPolicy = ?not_PriorityOrder}, ?not_AnyOrder) -> false;
-updated_order(#dbRef{orderPolicy = ?not_AnyOrder}, ?not_PriorityOrder) -> false;
-updated_order(_, _) -> true.
-
-updated_discard(#dbRef{discardPolicy = Equal}, Equal) -> false;
-updated_discard(#dbRef{discardPolicy = ?not_RejectNewEvents}, ?not_AnyOrder) -> false;
-updated_discard(#dbRef{discardPolicy = ?not_AnyOrder}, ?not_RejectNewEvents) -> false;
-updated_discard(_, _) -> true.
-
-move_events(DBRef, NewDBRef, '$end_of_table', _, _) ->
- destroy_order_db(DBRef),
- case ets:info(?get_OrderRef(NewDBRef), size) of
- N when N =< ?get_MaxEvents(NewDBRef) ->
- %% Even if the QoS MaxEvents have been changed
- %% we don't reach the limit.
- NewDBRef;
- N ->
- %% The QoS MaxEvents must have been decreased.
- discard_events(DBRef, N-?get_MaxEvents(NewDBRef)),
- NewDBRef
- end;
-move_events(DBRef, NewDBRef, Key, LifeFilter, PrioFilter) ->
- [{Keys, DeadLine, StartTime, PriorityOverride, Event}] =
- ets:lookup(?get_OrderRef(DBRef), Key),
- case check_deadline(DeadLine) of
- true ->
- ok;
- _->
- write_event(?get_OrderP(DBRef),
- {Keys, DeadLine, StartTime, PriorityOverride, Event},
- DBRef, NewDBRef, Key, LifeFilter, PrioFilter)
- end,
- ets:delete(?get_OrderRef(DBRef), Key),
- move_events(DBRef, NewDBRef, ets:next(?get_OrderRef(DBRef), Key),
- LifeFilter, PrioFilter).
-
-%% We cannot use do_add_event directly since we MUST lookup the timestamp (TS).
-write_event(?not_DeadlineOrder, {{_, TS, _Prio}, DL, ST, PO, Event}, _DBRef, NewDBRef,
- _Key, _LifeFilter, _PrioFilter) ->
- StartT = update_starttime(NewDBRef, Event, ST),
- %% Deadline and Priority previously extracted.
- do_add_event(NewDBRef, Event, TS, DL, StartT, PO);
-write_event(?not_DeadlineOrder, {{_, TS}, DL, _ST, PO, Event}, _DBRef, NewDBRef,
- _Key, _LifeFilter, PrioFilter) ->
- %% Priority not previously extracted.
- POverride = update_priority(NewDBRef, PrioFilter, Event, PO),
- StartT = extract_start_time(Event, ?get_StartTsupport(NewDBRef),
- ?get_TimeRef(NewDBRef)),
- do_add_event(NewDBRef, Event, TS, DL, StartT, POverride);
-write_event(?not_FifoOrder, {{TS, _PorD}, DL, ST, PO, Event}, _DBRef, NewDBRef,
- _Key, LifeFilter, PrioFilter) ->
- %% Priority or Deadline have been extracted before but we cannot tell which.
- POverride = update_priority(NewDBRef, PrioFilter, Event, PO),
- DeadL = update_deadline(NewDBRef, LifeFilter, Event, TS, DL),
- StartT = update_starttime(NewDBRef, Event, ST),
- do_add_event(NewDBRef, Event, TS, DeadL, StartT, POverride);
-write_event(?not_FifoOrder, {TS, DL, ST, PO, Event}, _DBRef, NewDBRef,
- _Key, LifeFilter, PrioFilter) ->
- %% Priority and Deadline not extracetd before. Do it now.
- POverride = update_priority(NewDBRef, PrioFilter, Event, PO),
- DeadL = update_deadline(NewDBRef, LifeFilter, Event, TS, DL),
- StartT = update_starttime(NewDBRef, Event, ST),
- do_add_event(NewDBRef, Event, TS, DeadL, StartT, POverride);
-%% Order Policy must be AnyOrder or PriorityOrder.
-write_event(_, {{_Prio, TS}, DL, ST, PO, Event}, _DBRef, NewDBRef,
- _Key, LifeFilter, _PrioFilter) ->
- DeadL = update_deadline(NewDBRef, LifeFilter, Event, TS, DL),
- StartT = update_starttime(NewDBRef, Event, ST),
- do_add_event(NewDBRef, Event, TS, DeadL, StartT, PO);
-write_event(_, {{_Prio, TS, DL}, DL, ST, PO, Event}, _DBRef, NewDBRef, _Key, _, _) ->
- %% Both Deadline and Priority have been extracetd before.
- StartT = update_starttime(NewDBRef, Event, ST),
- do_add_event(NewDBRef, Event, TS, DL, StartT, PO).
-
-
-%%------------------------------------------------------------
-%% function : update_priority
-%% Arguments:
-%% Returns :
-%% Comment : The purpose with this function is to avoid
-%% calling MappingFilter priority again, especially
-%% deadline again (we especially want to avoid calling
-%% since it may require intra-ORB communication.
-%% Use only when doing an update.
-%%------------------------------------------------------------
-update_priority(DBRef, PrioFilter, Event, OldPrio) when is_atom(OldPrio) ->
- get_prio_mapping_value(DBRef, PrioFilter, Event);
-update_priority(_DBRef, _PrioFilter, _Event, OldPrio) ->
- OldPrio.
-
-%%------------------------------------------------------------
-%% function : update_deadline
-%% Arguments:
-%% Returns :
-%% Comment : The purpose with this function is to avoid
-%% calling MappingFilter or parsing the events for
-%% deadline again (we especially want to avoid calling
-%% the MappingFilter since it may require intra-ORB
-%% communication. Use only when doing an update.
-%%------------------------------------------------------------
-update_deadline(DBRef, _LifeFilter, _Event, _TS, _OldDeadL) when
- ?get_DiscardP(DBRef) =/= ?not_DeadlineOrder,
- ?get_OrderP(DBRef) =/= ?not_DeadlineOrder,
- ?is_StopTNotSupported(DBRef) ->
- %% We do not need to extract the Deadline since it will not be used.
- false;
-update_deadline(DBRef, LifeFilter, Event, TS, OldDeadL) when is_atom(OldDeadL) ->
- %% We need the Deadline and it have not been extracetd before.
- DOverride = get_life_mapping_value(DBRef, LifeFilter, Event),
- %% We must find out when the event was delivered; setting a deadline using
- %% a new timestamp would not be accurate since we cannot tell for how long
- %% the event have been waiting.
- OldNow = convert_FIFO_Key(TS),
- extract_deadline(Event, ?get_DefStopT(DBRef), ?get_StopTsupport(DBRef),
- ?get_TimeRef(DBRef), DOverride, OldNow);
-update_deadline(_DBRef, _LifeFilter, _Event, _TS, OldDeadL) ->
- %% We need the Deadline and it have been extracetd before.
- OldDeadL.
-
-%%------------------------------------------------------------
-%% function : update_starttime
-%% Arguments:
-%% Returns :
-%% Comment : The purpose with this function is to avoid
-%% parsing the events for starttime again.
-%% Use only when doing an update.
-%%------------------------------------------------------------
-update_starttime(DBRef, Event, OldStartT) when is_atom(OldStartT) ->
- %% Probably not previously extracted; try to get it.
- extract_start_time(Event, ?get_StartTsupport(DBRef), ?get_TimeRef(DBRef));
-update_starttime(_DBRef, _Event, OldStartT) ->
- %% Previously extracted.
- OldStartT.
-
-%%------------------------------------------------------------
-%% function : discard_events
-%% Arguments: DBRef
-%% N - number of events we must discard.
-%% Returns :
-%% Comment : As default we shall Reject New Events when the limit
-%% is reached. Any discard order will do the same.
-%%
-%% This function can only be used for the discard policies
-%% Fifo, Priority and Deadline. Any or RejectNewEvents
-%% will not allow events to be stored at all, i.e., no events
-%% to discard. Lifo will not be stored either since when
-%% trying to add an event it is definitely the last event in.
-%%------------------------------------------------------------
-%% Since no Discard DB must the same Order policy.
-discard_events(#dbRef{orderRef = ORef, discardRef = undefined,
- discardPolicy = ?not_DeadlineOrder}, N) ->
- ?debug_print("Discarding ~p events Deadline Order.",[N]),
- index_loop_backward(ets:last(ORef), undefined, ORef, N);
-discard_events(#dbRef{orderRef = ORef, discardRef = DRef,
- discardPolicy = ?not_DeadlineOrder}, N) ->
- ?debug_print("Discarding ~p events Deadline Order.",[N]),
- index_loop_backward(ets:last(DRef), DRef, ORef, N);
-%% Fifo.
-discard_events(#dbRef{orderRef = ORef, discardRef = undefined,
- discardPolicy = ?not_FifoOrder}, N) ->
- ?debug_print("Discarding ~p events Fifo Order.",[N]),
- index_loop_backward(ets:last(ORef), undefined, ORef, N);
-discard_events(#dbRef{orderRef = ORef, discardRef = DRef,
- discardPolicy = ?not_FifoOrder}, N) ->
- ?debug_print("Discarding ~p events Fifo Order.",[N]),
- index_loop_backward(ets:last(DRef), DRef, ORef, N);
-%% Lifo- or Priority-Order
-discard_events(#dbRef{orderRef = ORef, discardRef = undefined}, N) ->
- ?debug_print("Discarding ~p events Lifo- or Priority-Order.",[N]),
- index_loop_forward(ets:first(ORef), undefined, ORef, N);
-discard_events(#dbRef{orderRef = ORef, discardRef = DRef}, N) ->
- ?debug_print("Discarding ~p events Lifo- or Priority-Order.",[N]),
- index_loop_forward(ets:first(DRef), DRef, ORef, N).
-
-
-index_loop_forward('$end_of_table', _, _, _Left) ->
- ok;
-index_loop_forward(_, _, _, 0) ->
- ok;
-index_loop_forward(Key, undefined, ORef, Left) ->
- ets:delete(ORef, Key),
- NewKey=ets:next(ORef, Key),
- index_loop_forward(NewKey, undefined, ORef, Left-1);
-
-index_loop_forward({Key1, Key2, Key3}, DRef, ORef, Left) ->
- ets:delete(DRef, {Key1, Key2, Key3}),
- ets:delete(ORef, {Key3, Key2, Key1}),
- NewKey=ets:next(DRef, {Key1, Key2, Key3}),
- index_loop_forward(NewKey, DRef, ORef, Left-1);
-
-index_loop_forward({Key1, Key2}, DRef, ORef, Left) ->
- ets:delete(DRef, {Key1, Key2}),
- ets:delete(ORef, {Key2, Key1}),
- NewKey=ets:next(DRef, {Key1, Key2}),
- index_loop_forward(NewKey, DRef, ORef, Left-1).
-
-index_loop_backward('$end_of_table', _, _, _) ->
- ok;
-index_loop_backward(_, _, _, 0) ->
- ok;
-index_loop_backward(Key, undefined, ORef, Left) ->
- ets:delete(ORef, Key),
- NewKey=ets:prev(ORef, Key),
- index_loop_backward(NewKey, undefined, ORef, Left-1);
-index_loop_backward({Key1, Key2}, DRef, ORef, Left) ->
- ets:delete(DRef, {Key1, Key2}),
- ets:delete(ORef, {Key2, Key1}),
- NewKey=ets:prev(DRef, {Key1, Key2}),
- index_loop_backward(NewKey, DRef, ORef, Left-1);
-index_loop_backward({Key1, Key2, Key3}, DRef, ORef, Left) ->
- ets:delete(DRef, {Key1, Key2, Key3}),
- ets:delete(ORef, {Key3, Key2, Key1}),
- NewKey=ets:prev(DRef, {Key1, Key2, Key3}),
- index_loop_backward(NewKey, DRef, ORef, Left-1).
-
-%%------------------------------------------------------------
-%% function : add_and_get_event
-%% Arguments: DBRef and Event
-%% Returns : {[], bool()} | {Event, bool()}
-%% Comment : This function is a mixture of ad anf get events.
-%% The intended use to avoid storing an event when
-%% not necessary.
-%%------------------------------------------------------------
-add_and_get_event(DBRef, Event) ->
- add_and_get_event(DBRef, Event, undefined, undefined, true).
-
-add_and_get_event(DBRef, Event, Delete) ->
- add_and_get_event(DBRef, Event, undefined, undefined, Delete).
-
-add_and_get_event(DBRef, Event, LifeFilter, PrioFilter) ->
- add_and_get_event(DBRef, Event, LifeFilter, PrioFilter, true).
-
-add_and_get_event(DBRef, Event, LifeFilter, PrioFilter, Delete) ->
- case ets:info(?get_OrderRef(DBRef), size) of
- 0 when ?is_StartTNotSupported(DBRef), ?is_StopTNotSupported(DBRef),
- Delete == true ->
- %% No stored events and no timeouts used; just return the event.
- {Event, false};
- 0 when ?is_StartTNotSupported(DBRef), ?is_StopTNotSupported(DBRef) ->
- %% No stored events and no timeouts used; just return the event.
- {Event, false, []};
- 0 when ?is_StartTNotSupported(DBRef) ->
- %% Only deadline supported, lookup values and cehck if ok.
- DOverride = get_life_mapping_value(DBRef, LifeFilter, Event),
- DL = extract_deadline(Event, ?get_DefStopT(DBRef),
- ?get_StopTsupport(DBRef), ?get_TimeRef(DBRef),
- DOverride),
- case check_deadline(DL) of
- true when Delete == true ->
- %% Expired, just discard the event.
- {[], false};
- true ->
- {[], false, []};
- _ when Delete == true ->
- %% Not expired, we can safely return the event.
- {Event, false};
- _ ->
- %% Not expired, we can safely return the event.
- {Event, false, []}
- end;
- 0 when ?is_StopTNotSupported(DBRef) ->
- %% Only starttime allowed, test if we can deliver the event now.
- ST = extract_start_time(Event, ?get_StartTsupport(DBRef),
- ?get_TimeRef(DBRef)),
- case check_start_time(ST) of
- false when Delete == true ->
- DOverride = get_life_mapping_value(DBRef, LifeFilter, Event),
- POverride = get_prio_mapping_value(DBRef, PrioFilter, Event),
- DL = extract_deadline(Event, ?get_DefStopT(DBRef),
- ?get_StopTsupport(DBRef),
- ?get_TimeRef(DBRef), DOverride),
- do_add_event(DBRef, Event, create_FIFO_Key(), DL, ST, POverride),
- {[], true};
- false ->
- DOverride = get_life_mapping_value(DBRef, LifeFilter, Event),
- POverride = get_prio_mapping_value(DBRef, PrioFilter, Event),
- DL = extract_deadline(Event, ?get_DefStopT(DBRef),
- ?get_StopTsupport(DBRef),
- ?get_TimeRef(DBRef), DOverride),
- do_add_event(DBRef, Event, create_FIFO_Key(), DL, ST, POverride),
- {[], true, []};
- _ when Delete == true ->
- %% Starttime ok, just return the event.
- {Event, false};
- _ ->
- %% Starttime ok, just return the event.
- {Event, false, []}
- end;
- _->
- %% Event already stored, just have to accept the overhead.
- ST = extract_start_time(Event, ?get_StartTsupport(DBRef),
- ?get_TimeRef(DBRef)),
- DOverride = get_life_mapping_value(DBRef, LifeFilter, Event),
- POverride = get_prio_mapping_value(DBRef, PrioFilter, Event),
- DL = extract_deadline(Event, ?get_DefStopT(DBRef),
- ?get_StopTsupport(DBRef),
- ?get_TimeRef(DBRef), DOverride),
- do_add_event(DBRef, Event, create_FIFO_Key(), DL, ST, POverride),
- get_event(DBRef, Delete)
- end.
-
-%%------------------------------------------------------------
-%% function : add_event
-%% Arguments: DBRef and Event
-%% Returns : true (or whatever 'ets:insert' returns) |
-%% {'EXCEPTION', #'IMP_LIMIT'{}}
-%% Comment : As default we shall deliver Events in Priority order.
-%% Hence, if AnyOrder set we will still deliver in
-%% Priority order. But we cannot use only the Priority
-%% value since if "all" events have the same priority
-%% there is a risk that some never will be delivered if
-%% the EventDB always contain events.
-%%
-%% When discard and order policy is equal we only use one
-%% DB since all we have to do is to "read from the other
-%% end" to discard the correct event(s).
-%%
-%% In the discard DB we must also store keys necessary to
-%% lookup the event in the order DB.
-%%
-%% If event limit reached 'IMPL_LIMIT' is raised if
-%% the discard policy is RejectNewEvents or AnyOrder.
-%% Theses two policies we currently define to be equal.
-%%------------------------------------------------------------
-
-add_event(DBRef, Event) ->
- %% Save overhead by first checking if we really need to extract
- %% Deadline and/or Priority.
- Deadline = get_life_mapping_value(DBRef, undefined, Event),
- Priority = get_prio_mapping_value(DBRef, undefined, Event),
- add_event_helper(DBRef, Event, Deadline, Priority).
-
-add_event(DBRef, Event, LifeFilter, PrioFilter) ->
- %% Save overhead by first checking if we really need to extract
- %% Deadline and/or Priority.
- Deadline = get_life_mapping_value(DBRef, LifeFilter, Event),
- Priority = get_prio_mapping_value(DBRef, PrioFilter, Event),
- add_event_helper(DBRef, Event, Deadline, Priority).
-
-add_event_helper(DBRef, Event, DOverride, POverride) ->
- case ets:info(?get_OrderRef(DBRef), size) of
- N when N < ?get_MaxEvents(DBRef), N > ?get_GCLimit(DBRef) ->
- gc_events(DBRef, low),
- DL = extract_deadline(Event, ?get_DefStopT(DBRef),
- ?get_StopTsupport(DBRef), ?get_TimeRef(DBRef),
- DOverride),
- case check_deadline(DL) of
- true ->
- true;
- _ ->
- ST = extract_start_time(Event, ?get_StartTsupport(DBRef),
- ?get_TimeRef(DBRef)),
- do_add_event(DBRef, Event, create_FIFO_Key(), DL, ST, POverride)
- end;
- N when N < ?get_MaxEvents(DBRef) ->
- DL = extract_deadline(Event, ?get_DefStopT(DBRef),
- ?get_StopTsupport(DBRef), ?get_TimeRef(DBRef),
- DOverride),
- case check_deadline(DL) of
- true ->
- true;
- _ ->
- ST = extract_start_time(Event, ?get_StartTsupport(DBRef),
- ?get_TimeRef(DBRef)),
- do_add_event(DBRef, Event, create_FIFO_Key(), DL, ST, POverride)
- end;
- _N when ?get_DiscardP(DBRef) == ?not_RejectNewEvents ->
- gc_events(DBRef, low),
- corba:raise(#'IMP_LIMIT'{completion_status=?COMPLETED_NO});
- _N when ?get_DiscardP(DBRef) == ?not_AnyOrder ->
- gc_events(DBRef, low),
- corba:raise(#'IMP_LIMIT'{completion_status=?COMPLETED_NO});
- _N when ?get_DiscardP(DBRef) == ?not_LifoOrder ->
- gc_events(DBRef, low),
- corba:raise(#'IMP_LIMIT'{completion_status=?COMPLETED_NO});
- _N ->
- gc_events(DBRef, low),
- %% Other discard policy; we must first store the event
- %% and the look up in the Discard DB which event we
- %% should remove.
- DL = extract_deadline(Event, ?get_DefStopT(DBRef),
- ?get_StopTsupport(DBRef), ?get_TimeRef(DBRef),
- DOverride),
- case check_deadline(DL) of
- true ->
- true;
- _ ->
- ST = extract_start_time(Event, ?get_StartTsupport(DBRef),
- ?get_TimeRef(DBRef)),
- do_add_event(DBRef, Event, create_FIFO_Key(), DL, ST, POverride),
- discard_events(DBRef, 1)
- end
- end.
-
-
-do_add_event(#dbRef{orderRef = ORef, orderPolicy = ?not_DeadlineOrder,
- discardRef = DRef, discardPolicy = ?not_PriorityOrder,
- defPriority = DefPrio, defStopT = _DefStopT}, Event, Key, DL, ST, PO) ->
- Prio = extract_priority(Event, DefPrio, PO),
- ets:insert(ORef, {{DL, Key, Prio}, DL, ST, PO, Event}),
- ets:insert(DRef, {{Prio, Key, DL}});
-do_add_event(#dbRef{orderRef = ORef, orderPolicy = ?not_DeadlineOrder,
- discardRef = DRef, discardPolicy = ?not_FifoOrder,
- defStopT = _DefStopT}, Event, Key, DL, ST, PO) ->
- ets:insert(ORef, {{DL, Key}, DL, ST, PO, Event}),
- ets:insert(DRef, {{Key, DL}});
-do_add_event(#dbRef{orderRef = ORef, orderPolicy = ?not_DeadlineOrder,
- discardRef = DRef, discardPolicy = ?not_LifoOrder,
- defStopT = _DefStopT}, Event, Key, DL, ST, PO) ->
- ets:insert(ORef, {{DL, Key}, DL, ST, PO, Event}),
- ets:insert(DRef, {{Key, DL}});
-%% Either the same (DeadlineOrder), RejectNewEvents or AnyOrder. No need
-%% to store anything in the discard policy, i.e., if the same we'll just
-%% read "from the other end" and AnyOrder and RejectNewEvents is equal.
-do_add_event(#dbRef{orderRef = ORef, orderPolicy = ?not_DeadlineOrder,
- defStopT = _DefStopT}, Event, Key, DL, ST, PO) ->
- ets:insert(ORef, {{DL, Key}, DL, ST, PO, Event});
-
-
-do_add_event(#dbRef{orderRef = ORef, orderPolicy = ?not_FifoOrder,
- discardRef = DRef, discardPolicy = ?not_DeadlineOrder,
- defStopT = _DefStopT}, Event, Key, DL, ST, PO) ->
- ets:insert(ORef, {{Key, DL}, DL, ST, PO, Event}),
- ets:insert(DRef, {{DL, Key}});
-do_add_event(#dbRef{orderRef = ORef, orderPolicy = ?not_FifoOrder,
- discardRef = DRef, discardPolicy = ?not_PriorityOrder,
- defPriority = DefPrio}, Event, Key, DL, ST, PO) ->
- Prio = extract_priority(Event, DefPrio, PO),
- ets:insert(ORef, {{Key, Prio}, DL, ST, PO, Event}),
- ets:insert(DRef, {{Prio, Key}});
-%% The discard policy must RejectNewEvents, AnyOrder, Fifo or Lifo order.
-do_add_event(#dbRef{orderRef = ORef, orderPolicy = ?not_FifoOrder,
- discardRef = _DRef}, Event, Key, DL, ST, PO) ->
- ets:insert(ORef, {Key, DL, ST, PO, Event});
-
-%% Order Policy must be AnyOrder or PriorityOrder.
-do_add_event(#dbRef{orderRef = ORef,
- discardRef = DRef, discardPolicy = ?not_DeadlineOrder,
- defPriority = DefPrio, defStopT = _DefStopT}, Event, Key, DL, ST, PO) ->
- Prio = extract_priority(Event, DefPrio, PO),
- ets:insert(ORef, {{Prio, Key, DL}, DL, ST, PO, Event}),
- ets:insert(DRef, {{DL, Key, Prio}});
-do_add_event(#dbRef{orderRef = ORef,
- discardRef = DRef, discardPolicy = ?not_FifoOrder,
- defPriority = DefPrio}, Event, Key, DL, ST, PO) ->
- Prio = extract_priority(Event, DefPrio, PO),
- ets:insert(ORef, {{Prio, Key}, DL, ST, PO, Event}),
- ets:insert(DRef, {{Key, Prio}});
-
-do_add_event(#dbRef{orderRef = ORef,
- discardRef = DRef, discardPolicy = ?not_LifoOrder,
- defPriority = DefPrio}, Event, Key, DL, ST, PO) ->
- Prio = extract_priority(Event, DefPrio, PO),
- ets:insert(ORef, {{Prio, Key}, DL, ST, PO, Event}),
- ets:insert(DRef, {{Key, Prio}});
-
-%% Order Policy must be AnyOrder or PriorityOrder and Discard Policy must be
-%% AnyOrder or RejectNewEvents
-do_add_event(#dbRef{orderRef = ORef, defPriority = DefPrio}, Event, Key, DL, ST, PO) ->
- Prio = extract_priority(Event, DefPrio, PO),
- ets:insert(ORef, {{Prio, Key}, DL, ST, PO, Event}).
-
-%%------------------------------------------------------------
-%% function : destroy_db
-%% Arguments: A DB reference
-%% Returns :
-%%------------------------------------------------------------
-destroy_db(#dbRef{orderRef = ORef, discardRef = undefined}) ->
- ets:delete(ORef);
-destroy_db(#dbRef{orderRef = ORef, discardRef = DRef}) ->
- ets:delete(ORef),
- ets:delete(DRef).
-
-%%------------------------------------------------------------
-%% function : destroy_discard_db
-%% Arguments: A DB reference
-%% Returns :
-%%------------------------------------------------------------
-destroy_discard_db(#dbRef{discardRef = undefined}) ->
- ok;
-destroy_discard_db(#dbRef{discardRef = DRef}) ->
- ets:delete(DRef).
-
-%%------------------------------------------------------------
-%% function : destroy_order_db
-%% Arguments: A DB reference
-%% Returns :
-%%------------------------------------------------------------
-destroy_order_db(#dbRef{orderRef = ORef}) ->
- ets:delete(ORef).
-
-%%------------------------------------------------------------
-%% function : create_db
-%% Arguments: QoS (local representation).
-%% Returns : A DB reference
-%%------------------------------------------------------------
-create_db(QoS, GCTime, GCLimit, TimeRef) ->
- DiscardRef =
- case {?not_GetDiscardPolicy(QoS), ?not_GetOrderPolicy(QoS)} of
- {Equal, Equal} ->
- undefined;
- {?not_PriorityOrder, ?not_AnyOrder} ->
- %% NOTE: Any- and Priority-Order delivery policy is equal.
- undefined;
- {?not_RejectNewEvents, _} ->
- undefined;
- {?not_AnyOrder, _} ->
- undefined;
- {?not_LifoOrder, ?not_FifoOrder} ->
- undefined;
- _ ->
- ets:new(oe_ets, [set, public, ordered_set])
- end,
- DBRef = ?CreateRef(ets:new(oe_ets, [set, public, ordered_set]),
- DiscardRef,
- ?not_GetOrderPolicy(QoS), ?not_GetDiscardPolicy(QoS),
- ?not_GetPriority(QoS), ?not_GetMaxEventsPerConsumer(QoS),
- ?not_GetTimeout(QoS), ?not_GetStartTimeSupported(QoS),
- ?not_GetStopTimeSupported(QoS), GCTime, GCLimit, TimeRef),
- if
- ?is_TimeoutNotUsed(DBRef), ?is_StopTNotSupported(DBRef) ->
- ok;
- true ->
- TS = erlang:monotonic_time(),
- {resolution, TR} = lists:keyfind(resolution, 1,
- erlang:system_info(os_monotonic_time_source)),
- put(oe_GC_timestamp, TS+GCTime*TR)
- end,
- DBRef.
-
-%%------------------------------------------------------------
-%% function : get_prio_mapping_value
-%% Arguments: A MappingFilter reference | undefined
-%% Event (Any or Structured)
-%% Returns : undefined | Data
-%%------------------------------------------------------------
-get_prio_mapping_value(DBRef, _, _) when ?get_DiscardP(DBRef) =/= ?not_PriorityOrder,
- ?get_OrderP(DBRef) =/= ?not_AnyOrder,
- ?get_OrderP(DBRef) =/= ?not_PriorityOrder ->
- false;
-get_prio_mapping_value(_, undefined, _) ->
- undefined;
-get_prio_mapping_value(_, MFilter, Event) when is_record(Event, 'any') ->
- case catch 'CosNotifyFilter_MappingFilter':match(MFilter, Event) of
- {false, DefVal} when is_record(DefVal, 'any') ->
- any:get_value(DefVal);
- {true, Matched} when is_record(Matched, 'any') ->
- any:get_value(Matched);
- _ ->
- undefined
- end;
-get_prio_mapping_value(_, MFilter, Event) ->
- case catch 'CosNotifyFilter_MappingFilter':match_structured(MFilter, Event) of
- {false, DefVal} when is_record(DefVal, 'any') ->
- any:get_value(DefVal);
- {true, Matched} when is_record(Matched, 'any') ->
- any:get_value(Matched);
- _ ->
- undefined
- end.
-
-%%------------------------------------------------------------
-%% function : get_life_mapping_value
-%% Arguments: A MappingFilter reference | undefined
-%% Event (Any or Structured)
-%% Returns : undefined | Data
-%%------------------------------------------------------------
-get_life_mapping_value(DBRef, _, _) when ?get_DiscardP(DBRef) =/= ?not_DeadlineOrder,
- ?get_OrderP(DBRef) =/= ?not_DeadlineOrder,
- ?is_StopTNotSupported(DBRef) ->
- false;
-get_life_mapping_value(_, undefined, _) ->
- undefined;
-get_life_mapping_value(_, MFilter, Event) when is_record(Event, 'any') ->
- case catch 'CosNotifyFilter_MappingFilter':match(MFilter, Event) of
- {false, DefVal} when is_record(DefVal, 'any') ->
- any:get_value(DefVal);
- {true, Matched} when is_record(Matched, 'any') ->
- any:get_value(Matched);
- _ ->
- undefined
- end;
-get_life_mapping_value(_, MFilter, Event) ->
- case catch 'CosNotifyFilter_MappingFilter':match_structured(MFilter, Event) of
- {false, DefVal} when is_record(DefVal, 'any') ->
- any:get_value(DefVal);
- {true, Matched} when is_record(Matched, 'any') ->
- any:get_value(Matched);
- _ ->
- undefined
- end.
-
-%%------------------------------------------------------------
-%% function : validate_event
-%% Arguments: Subscribe data
-%% A sequence of Events, 'structured' or an 'any' record
-%% A list of filter references
-%% Status, i.e., do we have to filter the events or just check subscr.
-%% Returns : A tuple of two lists; list1 the events that passed
-%% and list2 the events that didn't pass.
-%%------------------------------------------------------------
-validate_event(true, Events, Filters, _, 'MATCH') ->
- filter_events(Events, Filters, false);
-validate_event(true, Events, _Filters, _, _) ->
- {Events, []};
-validate_event({_Which, _WC}, Event, Filters, _, 'MATCH') when is_record(Event, any) ->
- filter_events(Event, Filters, false);
-validate_event({_Which, _WC}, Event, _Filters, _, _) when is_record(Event, any) ->
- {Event, []};
-validate_event({Which, WC}, Events, Filters, DBRef, 'MATCH') ->
- Passed=validate_event2(DBRef, Events, Which, WC, []),
- filter_events(Passed, Filters, true);
-validate_event({Which, WC}, Events, _Filters, DBRef, _) ->
- Passed=validate_event2(DBRef, Events, Which, WC, []),
- {lists:reverse(Passed), []}.
-
-validate_event2(_, [], _, _, []) ->
- [];
-validate_event2(_, [], _, _, Acc) ->
- Acc;
-validate_event2(DBRef, [Event|T], Which, WC, Acc) ->
- ET = ((Event#'CosNotification_StructuredEvent'.header)
- #'CosNotification_EventHeader'.fixed_header)
- #'CosNotification_FixedEventHeader'.event_type,
- CheckList =
- case Which of
- both ->
- [ET];
- domain ->
- [ET,
- ET#'CosNotification_EventType'{type_name=""},
- ET#'CosNotification_EventType'{type_name="*"}];
- type ->
- [ET,
- ET#'CosNotification_EventType'{domain_name=""},
- ET#'CosNotification_EventType'{domain_name="*"}];
- _ ->
- [ET,
- ET#'CosNotification_EventType'{type_name=""},
- ET#'CosNotification_EventType'{type_name="*"},
- ET#'CosNotification_EventType'{domain_name=""},
- ET#'CosNotification_EventType'{domain_name="*"}]
- end,
- case check_subscription(DBRef, CheckList) of
- true ->
- validate_event2(DBRef, T, Which, WC, [Event|Acc]);
- _->
- case catch cosNotification_Filter:match_types(
- ET#'CosNotification_EventType'.domain_name,
- ET#'CosNotification_EventType'.type_name,
- WC) of
- true ->
- validate_event2(DBRef, T, Which, WC, [Event|Acc]);
- _->
- validate_event2(DBRef, T, Which, WC, Acc)
- end
- end.
-
-check_subscription(_, []) ->
- false;
-check_subscription(DBRef, [H|T]) ->
- case ets:lookup(DBRef, H) of
- [] ->
- check_subscription(DBRef, T);
- _ ->
- true
- end.
-
-
-%%------------------------------------------------------------
-%% function : filter_events
-%% Arguments: A sequence of structured Events or #any
-%% Returns : A tuple of two lists; list1 the events that passed
-%% and list2 the events that didn't pass.
-%%------------------------------------------------------------
-
-filter_events(Events, []) ->
- {Events, []};
-filter_events(Events, Filters) ->
- filter_events(Events, Filters, [], [], false).
-
-filter_events(Events, [], false) ->
- {Events, []};
-filter_events(Events, [], _) ->
- {lists:reverse(Events), []};
-filter_events(Events, Filters, Reversed) ->
- filter_events(Events, Filters, [], [], Reversed).
-
-filter_events([], _, AccPassed, AccFailed, false) ->
- {lists:reverse(AccPassed), lists:reverse(AccFailed)};
-filter_events([], _, AccPassed, AccFailed, _) ->
- {AccPassed, AccFailed};
-filter_events([H|T], Filters, AccPassed, AccFailed, Reversed) ->
- case call_filters(Filters, H) of
- true ->
- filter_events(T, Filters, [H|AccPassed], AccFailed, Reversed);
- _ ->
- filter_events(T, Filters, AccPassed, [H|AccFailed], Reversed)
- end;
-filter_events(Any, Filters, _AccPassed, _AccFailed, _Reversed) ->
- case call_filters(Filters, Any) of
- true ->
- {Any, []};
- _ ->
- {[], Any}
- end.
-
-call_filters([], _) ->
- false;
-call_filters([{_,H}|T], Event) when is_record(Event, any) ->
- case catch 'CosNotifyFilter_Filter':match(H, Event) of
- true ->
- true;
- _->
- call_filters(T, Event)
- end;
-call_filters([{_,H}|T], Event) when ?not_isConvertedAny(Event) ->
- case catch 'CosNotifyFilter_Filter':match(H,
- Event#'CosNotification_StructuredEvent'.remainder_of_body) of
- true ->
- true;
- _->
- call_filters(T, Event)
- end;
-call_filters([{_,H}|T], Event) ->
- case catch 'CosNotifyFilter_Filter':match_structured(H, Event) of
- true ->
- true;
- _->
- call_filters(T, Event)
- end.
-
-
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosNotification/test/Makefile b/lib/cosNotification/test/Makefile
deleted file mode 100644
index 583cca1f42..0000000000
--- a/lib/cosNotification/test/Makefile
+++ /dev/null
@@ -1,192 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(COSNOTIFICATION_VSN)
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/cosNotification_test
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-TEST_SPEC_FILE = cosNotification.spec
-COVER_FILE = cosNotification.cover
-
-
-IDL_FILES =
-
-IDLOUTDIR = idl_output
-
-MODULES = \
- notification_SUITE \
- grammar_SUITE \
- eventDB_SUITE \
- generated_SUITE \
- notify_test_impl
-
-GEN_MODULES = \
- oe_notify_test_server \
- notify_test_data \
- notify_test_computer \
- notify_test_studies \
- notify_test_ShortArray \
- notify_test_uni1 \
- notify_test_uni2 \
- notify_test_X \
- notify_test_K \
- notify_test_SeqPushC \
- notify_test_StrPushC \
- notify_test_AnyPushC \
- notify_test_SeqPullC \
- notify_test_StrPullC \
- notify_test_AnyPullC \
- notify_test_SeqPushS \
- notify_test_StrPushS \
- notify_test_AnyPushS \
- notify_test_SeqPullS \
- notify_test_StrPullS \
- notify_test_AnyPullS \
- notify_test_funcs
-
-GEN_HRL_FILES = \
- oe_notify_test_server.hrl \
- notify_test_SeqPushC.hrl \
- notify_test_StrPushC.hrl \
- notify_test_AnyPushC.hrl \
- notify_test_SeqPullC.hrl \
- notify_test_StrPullC.hrl \
- notify_test_AnyPullC.hrl \
- notify_test_SeqPushS.hrl \
- notify_test_StrPushS.hrl \
- notify_test_AnyPushS.hrl \
- notify_test_SeqPullS.hrl \
- notify_test_StrPullS.hrl \
- notify_test_AnyPullS.hrl \
- notify_test.hrl \
- notify_test_funcs.hrl
-
-ERL_FILES = $(MODULES:%=%.erl)
-
-HRL_FILES =
-
-GEN_FILES = \
- $(GEN_HRL_FILES:%=$(IDLOUTDIR)/%) \
- $(GEN_MODULES:%=$(IDLOUTDIR)/%.erl)
-
-GEN_TARGET_FILES = $(GEN_MODULES:%=$(IDLOUTDIR)/%.$(EMULATOR))
-
-SUITE_TARGET_FILES = $(MODULES:%=%.$(EMULATOR))
-
-TARGET_FILES = \
- $(GEN_TARGET_FILES) \
- $(SUITE_TARGET_FILES)
-
-
-# ----------------------------------------------------
-# PROGRAMS
-# ----------------------------------------------------
-LOCAL_CLASSPATH = $(ERL_TOP)lib/cosNotification/priv:$(ERL_TOP)lib/cosNotification/test
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += \
- -pa $(ERL_TOP)/lib/cosNotification/ebin \
- -pa $(ERL_TOP)/lib/cosNotification/src \
- -pa $(ERL_TOP)/lib/cosTime/ebin \
- -pa $(ERL_TOP)/lib/cosTime/include \
- -pa $(ERL_TOP)/lib/orber/ebin \
- -pa $(ERL_TOP)/lib/ic/ebin \
- -pa $(ERL_TOP)/lib/cosNotification/include \
- -I$(ERL_TOP)/lib/cosEvent/src \
- -I$(ERL_TOP)/lib/cosNotification/include \
-
-ERL_COMPILE_FLAGS += \
- $(ERL_IDL_FLAGS) \
- -pa $(ERL_TOP)/lib/orber/include \
- -pa $(ERL_TOP)/lib/cosEvent/ebin \
- -pa $(ERL_TOP)/lib/cosNotification/ebin \
- -pa $(ERL_TOP)/lib/cosNotification/test/idl_output \
- -pa $(ERL_TOP)/lib/cosTime/ebin \
- -pa $(ERL_TOP)/lib/cosTime/include \
- -pa $(ERL_TOP)/lib/cosNotification/include \
- -pa $(ERL_TOP)/lib/ic/ebin \
- -I$(ERL_TOP)/lib/cosTime/ebin \
- -I$(ERL_TOP)/lib/cosTime/include \
- -I$(ERL_TOP)/lib/orber/include \
- -I$(ERL_TOP)/lib/cosNotification/src \
- -I$(ERL_TOP)/lib/cosNotification/include \
- -I$(ERL_TOP)/lib/cosNotification \
- -I$(ERL_TOP)/lib/cosNotification/test/$(IDLOUTDIR)
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-
-tests debug opt: $(TARGET_FILES)
-
-clean:
- rm -f idl_output/*
- rm -f $(TARGET_FILES)
- rm -f errs core *~
-
-docs:
-
-# ----------------------------------------------------
-# Special Targets
-# ----------------------------------------------------
-
-IDL-GENERATED: notify_test_server.idl
- erlc $(ERL_COMPILE_FLAGS) -o$(IDLOUTDIR) \
- +'{cfgfile,"notify_test_server.cfg"}' notify_test_server.idl
- >IDL-GENERATED
-
-$(GEN_FILES): IDL-GENERATED
-
-$(TARGET_FILES): IDL-GENERATED
-
-# ----------------------------------------------------
-# Release Targets
-# ----------------------------------------------------
-# We don't copy generated intermediate erlang and hrl files
-
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec:
-
-release_docs_spec:
-
-release_tests_spec: tests
- $(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) \
- $(COVER_FILE) $(ERL_FILES) "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELSYSDIR)/$(IDLOUTDIR)"
- $(INSTALL_DATA) $(GEN_TARGET_FILES) $(GEN_FILES) \
- "$(RELSYSDIR)/$(IDLOUTDIR)"
- $(INSTALL_DATA) $(SUITE_TARGET_FILES) "$(RELSYSDIR)"
-
diff --git a/lib/cosNotification/test/cosNotification.cover b/lib/cosNotification/test/cosNotification.cover
deleted file mode 100644
index 604f313521..0000000000
--- a/lib/cosNotification/test/cosNotification.cover
+++ /dev/null
@@ -1,2 +0,0 @@
-{incl_app,cosNotification,details}.
-
diff --git a/lib/cosNotification/test/cosNotification.spec b/lib/cosNotification/test/cosNotification.spec
deleted file mode 100644
index 8ec1baca33..0000000000
--- a/lib/cosNotification/test/cosNotification.spec
+++ /dev/null
@@ -1 +0,0 @@
-{suites,"../cosNotification_test",all}.
diff --git a/lib/cosNotification/test/eventDB_SUITE.erl b/lib/cosNotification/test/eventDB_SUITE.erl
deleted file mode 100644
index a0c47ad4c7..0000000000
--- a/lib/cosNotification/test/eventDB_SUITE.erl
+++ /dev/null
@@ -1,896 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%--------------------------------------------------------------------
-%% File : eventDB_SUITE.erl
-%% Purpose :
-%%--------------------------------------------------------------------
-
--module(eventDB_SUITE).
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-%% cosEvent files.
--include_lib("cosEvent/include/CosEventChannelAdmin.hrl").
-%% cosTime files.
--include_lib("cosTime/include/TimeBase.hrl").
-%% Application files
--include_lib("cosNotification/include/CosNotification.hrl").
--include_lib("cosNotification/include/CosNotifyChannelAdmin.hrl").
--include_lib("cosNotification/include/CosNotifyComm.hrl").
--include_lib("cosNotification/include/CosNotifyFilter.hrl").
-
--include_lib("cosNotification/src/CosNotification_Definitions.hrl").
-
--include("idl_output/notify_test.hrl").
-
--include_lib("common_test/include/ct.hrl").
-
-%%--------------- DEFINES ------------------------------------
--define(default_timeout, test_server:minutes(20)).
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
-
--define(EVENT1, ?not_CreateSE("","event1","",
- [#'CosNotification_Property'
- {name="Priority",
- value=any:create(orber_tc:short(), 0)},
- #'CosNotification_Property'
- {name="StartTime",
- value=any:create('TimeBase_UtcT':tc(),
- #'TimeBase_UtcT'
- {time=900000000,
- inacclo=0, inacchi=0, tdf=2})},
- #'CosNotification_Property'
- {name="StopTime",
- value=any:create('TimeBase_UtcT':tc(),
- #'TimeBase_UtcT'
- {time=900000000,
- inacclo=0, inacchi=0, tdf=2})},
- #'CosNotification_Property'
- {name="Timeout",
- value=any:create(orber_tc:unsigned_long_long(), 900000000)}],
- [], any:create(orber_tc:null(), null))).
--define(EVENT2, ?not_CreateSE("","event2","",
- [#'CosNotification_Property'
- {name="Priority",
- value=any:create(orber_tc:short(), 0)},
- #'CosNotification_Property'
- {name="StartTime",
- value=any:create('TimeBase_UtcT':tc(),
- #'TimeBase_UtcT'
- {time=800000000,
- inacclo=0, inacchi=0, tdf=2})},
- #'CosNotification_Property'
- {name="StopTime",
- value=any:create('TimeBase_UtcT':tc(),
- #'TimeBase_UtcT'
- {time=800000000,
- inacclo=0, inacchi=0, tdf=2})},
- #'CosNotification_Property'
- {name="Timeout",
- value=any:create(orber_tc:unsigned_long_long(), 800000000)}],
- [], any:create(orber_tc:null(), null))).
--define(EVENT3, ?not_CreateSE("","event3","",
- [#'CosNotification_Property'
- {name="Priority",
- value=any:create(orber_tc:short(), 0)},
- #'CosNotification_Property'
- {name="StartTime",
- value=any:create('TimeBase_UtcT':tc(),
- #'TimeBase_UtcT'
- {time=700000000,
- inacclo=0, inacchi=0, tdf=2})},
- #'CosNotification_Property'
- {name="StopTime",
- value=any:create('TimeBase_UtcT':tc(),
- #'TimeBase_UtcT'
- {time=700000000,
- inacclo=0, inacchi=0, tdf=2})},
- #'CosNotification_Property'
- {name="Timeout",
- value=any:create(orber_tc:unsigned_long_long(), 700000000)}],
- [], any:create(orber_tc:null(), null))).
--define(EVENT4, ?not_CreateSE("","event4","",
- [#'CosNotification_Property'
- {name="Priority",
- value=any:create(orber_tc:short(), 2)},
- #'CosNotification_Property'
- {name="StartTime",
- value=any:create('TimeBase_UtcT':tc(),
- #'TimeBase_UtcT'
- {time=300000000,
- inacclo=0, inacchi=0, tdf=2})},
- #'CosNotification_Property'
- {name="StopTime",
- value=any:create('TimeBase_UtcT':tc(),
- #'TimeBase_UtcT'
- {time=300000000,
- inacclo=0, inacchi=0, tdf=2})},
- #'CosNotification_Property'
- {name="Timeout",
- value=any:create(orber_tc:unsigned_long_long(), 300000000)}],
- [], any:create(orber_tc:null(), null))).
--define(EVENT5, ?not_CreateSE("","event5","",
- [#'CosNotification_Property'
- {name="Priority",
- value=any:create(orber_tc:short(), 2)},
- #'CosNotification_Property'
- {name="StartTime",
- value=any:create('TimeBase_UtcT':tc(),
- #'TimeBase_UtcT'
- {time=200000000,
- inacclo=0, inacchi=0, tdf=2})},
- #'CosNotification_Property'
- {name="StopTime",
- value=any:create('TimeBase_UtcT':tc(),
- #'TimeBase_UtcT'
- {time=200000000,
- inacclo=0, inacchi=0, tdf=2})},
- #'CosNotification_Property'
- {name="Timeout",
- value=any:create(orber_tc:unsigned_long_long(), 200000000)}],
- [], any:create(orber_tc:null(), null))).
--define(EVENT6, ?not_CreateSE("","event6","",
- [#'CosNotification_Property'
- {name="Priority",
- value=any:create(orber_tc:short(), 0)},
- #'CosNotification_Property'
- {name="StartTime",
- value=any:create('TimeBase_UtcT':tc(),
- #'TimeBase_UtcT'
- {time=500000000,
- inacclo=0, inacchi=0, tdf=2})},
- #'CosNotification_Property'
- {name="StopTime",
- value=any:create('TimeBase_UtcT':tc(),
- #'TimeBase_UtcT'
- {time=500000000,
- inacclo=0, inacchi=0, tdf=2})},
- #'CosNotification_Property'
- {name="Timeout",
- value=any:create(orber_tc:unsigned_long_long(), 500000000)}],
- [], any:create(orber_tc:null(), null))).
--define(EVENT7, ?not_CreateSE("","event7","",
- [#'CosNotification_Property'
- {name="Priority",
- value=any:create(orber_tc:short(), -1)},
- #'CosNotification_Property'
- {name="StartTime",
- value=any:create('TimeBase_UtcT':tc(),
- #'TimeBase_UtcT'
- {time=400000000,
- inacclo=0, inacchi=0, tdf=2})},
- #'CosNotification_Property'
- {name="StopTime",
- value=any:create('TimeBase_UtcT':tc(),
- #'TimeBase_UtcT'
- {time=400000000,
- inacclo=0, inacchi=0, tdf=2})},
- #'CosNotification_Property'
- {name="Timeout",
- value=any:create(orber_tc:unsigned_long_long(), 400000000)}],
- [], any:create(orber_tc:null(), null))).
--define(EVENT8, ?not_CreateSE("","event8","",
- [#'CosNotification_Property'
- {name="Priority",
- value=any:create(orber_tc:short(), -1)},
- #'CosNotification_Property'
- {name="StartTime",
- value=any:create('TimeBase_UtcT':tc(),
- #'TimeBase_UtcT'
- {time=600000000,
- inacclo=0, inacchi=0, tdf=2})},
- #'CosNotification_Property'
- {name="StopTime",
- value=any:create('TimeBase_UtcT':tc(),
- #'TimeBase_UtcT'
- {time=600000000,
- inacclo=0, inacchi=0, tdf=2})},
- #'CosNotification_Property'
- {name="Timeout",
- value=any:create(orber_tc:unsigned_long_long(), 600000000)}],
- [], any:create(orber_tc:null(), null))).
--define(EVENT9, ?not_CreateSE("","event9","",
- [#'CosNotification_Property'
- {name="Priority",
- value=any:create(orber_tc:short(), 0)},
- #'CosNotification_Property'
- {name="StartTime",
- value=any:create('TimeBase_UtcT':tc(),
- #'TimeBase_UtcT'
- {time=100000000,
- inacclo=0, inacchi=0, tdf=2})},
- #'CosNotification_Property'
- {name="StopTime",
- value=any:create('TimeBase_UtcT':tc(),
- #'TimeBase_UtcT'
- {time=100000000,
- inacclo=0, inacchi=0, tdf=2})},
- #'CosNotification_Property'
- {name="Timeout",
- value=any:create(orber_tc:unsigned_long_long(), 100000000)}],
- [], any:create(orber_tc:null(), null))).
-
--define(EVENTS, [?EVENT1, ?EVENT2, ?EVENT3, ?EVENT4, ?EVENT5, ?EVENT6, ?EVENT7,
- ?EVENT8, ?EVENT9]).
-
-
--define(PRIOORDER, [?EVENT4, ?EVENT5, ?EVENT1, ?EVENT2, ?EVENT3, ?EVENT6, ?EVENT9,
- ?EVENT7, ?EVENT8]).
-
--define(FIFOORDER, ?EVENTS).
-
--define(DEADLINEORDER, [?EVENT9, ?EVENT5, ?EVENT4, ?EVENT7, ?EVENT6, ?EVENT8, ?EVENT3,
- ?EVENT2, ?EVENT1]).
-
--define(NO_OF_EVENTS, 9).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
- cases/0, init_per_suite/1, end_per_suite/1, reorder_api/1,
- lookup_api/1,
- discard_api/1, max_events_api/1, gc_api/1, auto_gc_api/1,
- start_stop_time_api/1, mapping_filter_api/1, persisten_event_api/1,
- init_per_testcase/2, end_per_testcase/2]).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-cases() ->
- [persisten_event_api, start_stop_time_api,
- mapping_filter_api, max_events_api, discard_api,
- reorder_api, lookup_api, gc_api, auto_gc_api].
-
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- orber:jump_start(),
- cosTime:install_time(),
- cosTime:start(),
- if
- is_list(Config) ->
- Config;
- true ->
- exit("Config not a list")
- end.
-
-end_per_suite(Config) ->
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- cosTime:stop(),
- cosTime:uninstall_time(),
- orber:jump_stop(),
- Config.
-
-
-%%-----------------------------------------------------------------
-%% cosNotification_eventDB lookup API tests
-%%-----------------------------------------------------------------
-%% The event DB is used to store events which cannot be
-%% delivered at once. This case is supposed to test
-%% that the events are delivered in the correct order
-%% if a MappingFilter have benn associated.
-mapping_filter_api(_Config) ->
- InitQoS = ?not_CreateInitQoS(),
- InitQoS2 = ?not_SetMaxEventsPerConsumer(InitQoS,100),
- InitQoS3 = ?not_SetStartTimeSupported(InitQoS2, false),
- InitQoS4 = ?not_SetStopTimeSupported(InitQoS3, true),
- QoS = ?not_SetDiscardPolicy(InitQoS4, ?not_AnyOrder),
-
- PriorityQoS = ?not_SetOrderPolicy(QoS, ?not_PriorityOrder),
- DeadlineQoS = ?not_SetOrderPolicy(QoS, ?not_DeadlineOrder),
-
- %% "Calculate" data once:
- %% NOTE! Even though the an Event do not match any of the constarints the
- %% default value will be used. Hence, the events will not be stored in the
- %% way described in the definitions above. For example, when using deadline order
- %% all the events will be stored in FIFO order since the usag of a MappingFilter
- %% all evnts will have the same deadline (except event6).
- Events = ?EVENTS,
- PrioOrder = [?EVENT6, ?EVENT1, ?EVENT2, ?EVENT3, ?EVENT4, ?EVENT5, ?EVENT7,
- ?EVENT8, ?EVENT9],
- DeadlineOrder = [?EVENT1, ?EVENT2, ?EVENT3, ?EVENT4, ?EVENT5, ?EVENT7, ?EVENT8,
- ?EVENT9],
-
-
- FiFac = 'CosNotifyFilter_FilterFactory':oe_create(),
- ?match({_,key,_,_,_,_}, FiFac),
-
- PrioFilter = 'CosNotifyFilter_FilterFactory':
- create_mapping_filter(FiFac, "EXTENDED_TCL", any:create(orber_tc:short(), 0)),
- DLFilter = 'CosNotifyFilter_FilterFactory':
- create_mapping_filter(FiFac, "EXTENDED_TCL", any:create(orber_tc:unsigned_long_long(), 1000000000)),
-
- ?match([_],
- 'CosNotifyFilter_MappingFilter':add_mapping_constraints(PrioFilter,
- [#'CosNotifyFilter_MappingConstraintPair'
- {constraint_expression = #'CosNotifyFilter_ConstraintExp'
- {event_types = [#'CosNotification_EventType'
- {domain_name = "",
- type_name = "event6"}],
- constraint_expr = "2==2"},
- result_to_set = any:create(orber_tc:short(), 10)}])),
- ?match([_],
- 'CosNotifyFilter_MappingFilter':add_mapping_constraints(DLFilter,
- [#'CosNotifyFilter_MappingConstraintPair'
- {constraint_expression = #'CosNotifyFilter_ConstraintExp'
- {event_types = [#'CosNotification_EventType'
- {domain_name = "",
- type_name = "event6"}],
- constraint_expr = "2==2"},
- result_to_set = any:create(orber_tc:unsigned_long_long(), 200000000)}])),
-
-
- do_lookup(PriorityQoS, Events, PrioOrder, "Priority Order", undefined, PrioFilter, 0),
- do_lookup(DeadlineQoS, Events, DeadlineOrder, "Deadline Order", DLFilter, undefined, 23000),
- ok.
-
-do_lookup(QoS, Events, Return, Txt, DLFilter, PrioFilter, Timeout) ->
- io:format("#################### ~s ###################~n", [Txt]),
- Ref = cosNotification_eventDB:create_db(QoS, 60, 50, undefined),
- create_loop(Events, Ref, DLFilter, PrioFilter),
- timer:sleep(Timeout),
- ?match({Return,_}, cosNotification_eventDB:get_events(Ref, ?NO_OF_EVENTS)),
- cosNotification_eventDB:destroy_db(Ref).
-
-%%-----------------------------------------------------------------
-%% cosNotification_eventDB discard API tests
-%%-----------------------------------------------------------------
-%% The event DB is used to store events which cannot be
-%% delivered at once. If MaxEvents limit is reached there
-%% different ways we can discard the. This case will test
-%% all permutations of order and discard policies.
-discard_api(_Config) ->
- InitQoS1 = ?not_CreateInitQoS(),
- InitQoS2 = ?not_SetPriority(InitQoS1, 10),
- InitQoS3 = ?not_SetStartTimeSupported(InitQoS2, false),
- QoS = ?not_SetMaxEventsPerConsumer(InitQoS3, 5),
- %% The different order policies. To each order we must apply every possible
- %% discard policy to each order policy setting. We also have to test and
- %% change the policies for each setting.
- AnyQoS = ?not_SetOrderPolicy(QoS, ?not_AnyOrder),
- PriorityQoS = ?not_SetOrderPolicy(QoS, ?not_PriorityOrder),
- FifoQoS = ?not_SetOrderPolicy(QoS, ?not_FifoOrder),
- DeadlineQoS = ?not_SetOrderPolicy(QoS, ?not_DeadlineOrder),
-
- Events = ?EVENTS,
-
- %% Test using Any discard policy
- do_discard(Events, ?not_SetDiscardPolicy(AnyQoS, ?not_AnyOrder),
- [?EVENT4, ?EVENT5, ?EVENT1, ?EVENT2, ?EVENT3],
- "Discard and Order eq. Any"),
- do_discard(Events, ?not_SetDiscardPolicy(PriorityQoS, ?not_AnyOrder),
- [?EVENT4, ?EVENT5, ?EVENT1, ?EVENT2, ?EVENT3],
- "Discard Any and Order Priority"),
- do_discard(Events, ?not_SetDiscardPolicy(FifoQoS, ?not_AnyOrder),
- [?EVENT1, ?EVENT2, ?EVENT3, ?EVENT4, ?EVENT5],
- "Discard Any and Order Fifo"),
- do_discard(Events, ?not_SetDiscardPolicy(DeadlineQoS, ?not_AnyOrder),
- [?EVENT5, ?EVENT4, ?EVENT3, ?EVENT2, ?EVENT1],
- "Discard Any and Order Deadline"),
-
- %% Test using RejectNewEvents discard policy
- do_discard(Events, ?not_SetDiscardPolicy(AnyQoS, ?not_RejectNewEvents),
- [?EVENT4, ?EVENT5, ?EVENT1, ?EVENT2, ?EVENT3],
- "Discard RejectNewEvents and Order Any"),
- do_discard(Events, ?not_SetDiscardPolicy(PriorityQoS, ?not_RejectNewEvents),
- [?EVENT4, ?EVENT5, ?EVENT1, ?EVENT2, ?EVENT3],
- "Discard RejectNewEvents and Order Priority"),
- do_discard(Events, ?not_SetDiscardPolicy(FifoQoS, ?not_RejectNewEvents),
- [?EVENT1, ?EVENT2, ?EVENT3, ?EVENT4, ?EVENT5],
- "Discard RejectNewEvents and Order Fifo"),
- do_discard(Events, ?not_SetDiscardPolicy(DeadlineQoS, ?not_RejectNewEvents),
- [?EVENT5, ?EVENT4, ?EVENT3, ?EVENT2, ?EVENT1],
- "Discard RejectNewEvents and Order Deadline"),
-
- %% Test using Lifo discard policy
- do_discard(Events, ?not_SetDiscardPolicy(AnyQoS, ?not_LifoOrder),
- [?EVENT4, ?EVENT5, ?EVENT1, ?EVENT2, ?EVENT3],
- "Discard Lifo and Order Any"),
- do_discard(Events, ?not_SetDiscardPolicy(PriorityQoS, ?not_LifoOrder),
- [?EVENT4, ?EVENT5, ?EVENT1, ?EVENT2, ?EVENT3],
- "Discard Lifo and Order Priority"),
- do_discard(Events, ?not_SetDiscardPolicy(FifoQoS, ?not_LifoOrder),
- [?EVENT1, ?EVENT2, ?EVENT3, ?EVENT4, ?EVENT5],
- "Discard Lifo and Order Fifo"),
- do_discard(Events, ?not_SetDiscardPolicy(DeadlineQoS, ?not_LifoOrder),
- [?EVENT5, ?EVENT4, ?EVENT3, ?EVENT2, ?EVENT1],
- "Discard Lifo and Order Deadline"),
-
- %% Test using Fifo discard policy
- do_discard(Events, ?not_SetDiscardPolicy(AnyQoS, ?not_FifoOrder),
- [?EVENT5, ?EVENT6, ?EVENT9, ?EVENT7, ?EVENT8],
- "Discard Fifo and Order Any"),
- do_discard(Events, ?not_SetDiscardPolicy(PriorityQoS, ?not_FifoOrder),
- [?EVENT5, ?EVENT6, ?EVENT9, ?EVENT7, ?EVENT8],
- "Discard Fifo and Order Priority"),
- do_discard(Events, ?not_SetDiscardPolicy(FifoQoS, ?not_FifoOrder),
- [?EVENT5, ?EVENT6, ?EVENT7, ?EVENT8, ?EVENT9],
- "Discard Fifo and Order Fifo"),
- do_discard(Events, ?not_SetDiscardPolicy(DeadlineQoS, ?not_FifoOrder),
- [?EVENT9, ?EVENT5, ?EVENT7, ?EVENT6, ?EVENT8],
- "Discard Fifo and Order Deadline"),
-
- %% Test using Priority discard policy
- do_discard(Events, ?not_SetDiscardPolicy(AnyQoS, ?not_PriorityOrder),
- [?EVENT4, ?EVENT5, ?EVENT1, ?EVENT2, ?EVENT3],
- "Discard Priority and Order Any"),
- do_discard(Events, ?not_SetDiscardPolicy(PriorityQoS, ?not_PriorityOrder),
- [?EVENT4, ?EVENT5, ?EVENT1, ?EVENT2, ?EVENT3],
- "Discard Priority and Order Priority"),
- do_discard(Events, ?not_SetDiscardPolicy(FifoQoS, ?not_PriorityOrder),
- [?EVENT1, ?EVENT2, ?EVENT3, ?EVENT4, ?EVENT5],
- "Discard Priority and Order Fifo"),
- do_discard(Events, ?not_SetDiscardPolicy(DeadlineQoS, ?not_PriorityOrder),
- [?EVENT5, ?EVENT4, ?EVENT3, ?EVENT2, ?EVENT1],
- "Discard Priority and Order Deadline"),
-
- %% Test using Deadline discard policy
- do_discard(Events, ?not_SetDiscardPolicy(AnyQoS, ?not_DeadlineOrder),
- [?EVENT1, ?EVENT2, ?EVENT3, ?EVENT6, ?EVENT8],
- "Discard Deadline and Order Any"),
- do_discard(Events, ?not_SetDiscardPolicy(PriorityQoS, ?not_DeadlineOrder),
- [?EVENT1, ?EVENT2, ?EVENT3, ?EVENT6, ?EVENT8],
- "Discard Deadline and Order Priority"),
- do_discard(Events, ?not_SetDiscardPolicy(FifoQoS, ?not_DeadlineOrder),
- [?EVENT1, ?EVENT2, ?EVENT3, ?EVENT6, ?EVENT8],
- "Discard Deadline and Order Fifo"),
- do_discard(Events, ?not_SetDiscardPolicy(DeadlineQoS, ?not_DeadlineOrder),
- [?EVENT6, ?EVENT8, ?EVENT3, ?EVENT2, ?EVENT1],
- "Discard Deadline and Order Deadline"),
-
- ok.
-
-do_discard(Events, QoS, Reply, Txt) ->
- io:format("################# ~s #################~n", [Txt]),
- Ref = cosNotification_eventDB:create_db(QoS, 60, 50, undefined),
- create_loop(Events, Ref),
- ?match({Reply,_}, cosNotification_eventDB:get_events(Ref, ?NO_OF_EVENTS)),
- cosNotification_eventDB:destroy_db(Ref).
-
-
-%%-----------------------------------------------------------------
-%% cosNotification_eventDB lookup API tests
-%%-----------------------------------------------------------------
-%% The event DB is used to store events which cannot be
-%% delivered at once. This case is supposed to test
-%% that the events are delivered in the correct order.
-lookup_api(_Config) ->
- InitQoS = ?not_CreateInitQoS(),
- InitQoS2 = ?not_SetMaxEventsPerConsumer(InitQoS,100),
- InitQoS3 = ?not_SetStartTimeSupported(InitQoS2, false),
- QoS = ?not_SetDiscardPolicy(InitQoS3, ?not_AnyOrder),
-
- AnyQoS = ?not_SetOrderPolicy(QoS, ?not_AnyOrder),
- PriorityQoS = ?not_SetOrderPolicy(QoS, ?not_PriorityOrder),
- FifoQoS = ?not_SetOrderPolicy(QoS, ?not_FifoOrder),
- DeadlineQoS = ?not_SetOrderPolicy(QoS, ?not_DeadlineOrder),
-
- %% "Calculate" data once:
- Events = ?EVENTS,
- PrioOrder = ?PRIOORDER,
- FifoOrder = ?FIFOORDER,
- DeadlineOrder = ?DEADLINEORDER,
-
- do_lookup(PriorityQoS, Events, PrioOrder, "Priority Order"),
- do_lookup(FifoQoS, Events, FifoOrder, "Fifo Order"),
- do_lookup(DeadlineQoS, Events, DeadlineOrder, "Deadline Order"),
- do_lookup(AnyQoS, Events, PrioOrder, "Any Order"),
- ok.
-
-do_lookup(QoS, Events, Return, Txt) ->
- io:format("#################### ~s ###################~n", [Txt]),
- Ref = cosNotification_eventDB:create_db(QoS, 60, 50, undefined),
- create_loop(Events, Ref),
- ?match({Return,_}, cosNotification_eventDB:get_events(Ref, ?NO_OF_EVENTS)),
- cosNotification_eventDB:destroy_db(Ref).
-
-
-%%-----------------------------------------------------------------
-%% cosNotification_eventDB max events API tests
-%%-----------------------------------------------------------------
-%% The event DB is used to store events which cannot be
-%% delivered at once. If the MaxEvents QoS is updated we must be
-%% able to reduce the amount of stored events.
-max_events_api(_Config) ->
-
- QoS1 = ?not_CreateInitQoS(),
- QoS2 = ?not_SetOrderPolicy(QoS1, ?not_FifoOrder),
- QoS3 = ?not_SetDiscardPolicy(QoS2, ?not_RejectNewEvents),
- QoS4 = ?not_SetStartTimeSupported(QoS3, false),
- QoS_NO_OF_EVENTS = ?not_SetMaxEventsPerConsumer(QoS4, ?NO_OF_EVENTS),
- QoS_5_EVENTS = ?not_SetMaxEventsPerConsumer(QoS4, 5),
-
- Events = ?EVENTS,
- Events5 = [?EVENT1, ?EVENT2, ?EVENT3, ?EVENT4, ?EVENT5],
-
- %% Initiate DB and 'NO_OF_EVENTS' events.
- Ref1 = cosNotification_eventDB:create_db(QoS_NO_OF_EVENTS, 60, 50, undefined),
- create_loop(Events, Ref1),
-
- %% Reduce the limit to 5 and extract all and see if it's ok.
- Ref2 = cosNotification_eventDB:update(Ref1, QoS_5_EVENTS),
- ?match({Events5, true}, cosNotification_eventDB:get_events(Ref2, ?NO_OF_EVENTS)),
-
- %% Add 'NO_OF_EVENTS' events. Since the only allow 5 events the DB will only
- %% contain 5 events.
- create_loop(Events, Ref2),
- Ref3 = cosNotification_eventDB:update(Ref2, QoS_NO_OF_EVENTS),
-
- ?match({Events5, true}, cosNotification_eventDB:get_events(Ref3, ?NO_OF_EVENTS)),
- create_loop(Events, Ref3),
- ?match({Events, true}, cosNotification_eventDB:get_events(Ref3, ?NO_OF_EVENTS)),
- cosNotification_eventDB:destroy_db(Ref3),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% cosNotification_eventDB persisten events API tests
-%%-----------------------------------------------------------------
-%% The event DB is used to store events which cannot be
-%% delivered at once.
-persisten_event_api(_Config) ->
-
- QoS1 = ?not_CreateInitQoS(),
- QoS2 = ?not_SetOrderPolicy(QoS1, ?not_FifoOrder),
- QoS3 = ?not_SetDiscardPolicy(QoS2, ?not_RejectNewEvents),
- QoS4 = ?not_SetStartTimeSupported(QoS3, false),
- QoS = ?not_SetMaxEventsPerConsumer(QoS4, ?NO_OF_EVENTS),
-
- Event1 = ?EVENT1,
-
- Ref = cosNotification_eventDB:create_db(QoS, 60, 50, undefined),
- %% Clean DB, should be empty
- ?match(0, cosNotification_eventDB:status(Ref, eventCounter)),
- cosNotification_eventDB:add_event(Ref, Event1),
- ?match(1, cosNotification_eventDB:status(Ref, eventCounter)),
- %% Get event without removing it. Should still be one event stored
- ?match({[Event1], _, _}, cosNotification_eventDB:get_events(Ref, 2, false)),
- ?match(1, cosNotification_eventDB:status(Ref, eventCounter)),
- {_, _, Keys} =
- ?match({Event1, _, _}, cosNotification_eventDB:get_event(Ref, false)),
- ?match(1, cosNotification_eventDB:status(Ref, eventCounter)),
- %% Clear the events and check that the DB is empty.
- cosNotification_eventDB:delete_events(Keys),
- ?match(0, cosNotification_eventDB:status(Ref, eventCounter)),
- ?match({[], _, []}, cosNotification_eventDB:get_event(Ref, false)),
- ?match({[], _, []}, cosNotification_eventDB:get_events(Ref, 2, false)),
-
- cosNotification_eventDB:destroy_db(Ref),
- ok.
-
-%%-----------------------------------------------------------------
-%% cosNotification_eventDB gc API tests
-%%-----------------------------------------------------------------
-%% The event DB is used to store events which cannot be
-%% delivered at once. If Deadline defined the events that
-%% are older must be discarded.
-gc_api(_Config) ->
-
- QoS1 = ?not_CreateInitQoS(),
- QoS2 = ?not_SetOrderPolicy(QoS1, ?not_FifoOrder),
- QoS3 = ?not_SetDiscardPolicy(QoS2, ?not_RejectNewEvents),
- QoS4 = ?not_SetStartTimeSupported(QoS3, false),
- QoS_NO_OF_EVENTS = ?not_SetMaxEventsPerConsumer(QoS4, ?NO_OF_EVENTS),
-
- Events = ?EVENTS,
- Events6 = [?EVENT1, ?EVENT2, ?EVENT3, ?EVENT4, ?EVENT6, ?EVENT7, ?EVENT8],
- %% Initiate DB and 'NO_OF_EVENTS' events.
- Ref = cosNotification_eventDB:create_db(QoS_NO_OF_EVENTS, 60, 50, undefined),
- create_loop(Events, Ref),
-
- %% Sleep so some events will get 'old'.
- timer:sleep(23000),
-
- %% Reduce the limit to 5 and extract all and see if it's ok.
- cosNotification_eventDB:gc_events(Ref, high),
-
- %% Since gc is done by another process we must wait so it will have a chance
- %% to complete the job.
- timer:sleep(2000),
-
- ?match({Events6, true}, cosNotification_eventDB:get_events(Ref, ?NO_OF_EVENTS)),
-
- create_loop(Events, Ref),
- timer:sleep(23000),
- ?match({Events6, true}, cosNotification_eventDB:get_events(Ref, ?NO_OF_EVENTS)),
- cosNotification_eventDB:destroy_db(Ref),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% cosNotification_eventDB gc API tests
-%%-----------------------------------------------------------------
-%% The event DB is used to store events which cannot be
-%% delivered at once. If Deadline defined the events that
-%% are older must be discarded.
-auto_gc_api(_Config) ->
-
- QoS1 = ?not_CreateInitQoS(),
- QoS2 = ?not_SetOrderPolicy(QoS1, ?not_FifoOrder),
- QoS3 = ?not_SetDiscardPolicy(QoS2, ?not_RejectNewEvents),
- QoS4 = ?not_SetStopTimeSupported(QoS3, true),
- QoS5 = ?not_SetStartTimeSupported(QoS4, false),
- QoS_NO_OF_EVENTS = ?not_SetMaxEventsPerConsumer(QoS5, ?NO_OF_EVENTS),
-
- Events6 = [?EVENT1, ?EVENT2, ?EVENT3, ?EVENT7, ?EVENT8, ?EVENT9],
- %% Initiate DB
- Ref = cosNotification_eventDB:create_db(QoS_NO_OF_EVENTS, 50, 50, undefined),
- create_loop([?EVENT1, ?EVENT2, ?EVENT3, ?EVENT4, ?EVENT6], Ref),
-
- %% Sleep so some events will get 'old'.
- timer:sleep(60000),
- create_loop([?EVENT7, ?EVENT8, ?EVENT9], Ref),
-
- %% Since gc is done by another process we must wait so it will have a chance
- %% to complete the job.
- timer:sleep(2000),
-
- ?match({Events6, true}, cosNotification_eventDB:get_events(Ref, ?NO_OF_EVENTS)),
-
- cosNotification_eventDB:destroy_db(Ref),
-
- ok.
-
-
-%%-----------------------------------------------------------------
-%% cosNotification_eventDB start- and stop-time API tests
-%%-----------------------------------------------------------------
-%% The event DB is used to store events which cannot be
-%% delivered at once. If Deadline defined the events that
-%% are older must be discarded.
-start_stop_time_api(_Config) ->
-
- QoS1 = ?not_CreateInitQoS(),
- QoS2 = ?not_SetOrderPolicy(QoS1, ?not_FifoOrder),
- QoS3 = ?not_SetDiscardPolicy(QoS2, ?not_RejectNewEvents),
- QoS4 = ?not_SetStopTimeSupported(QoS3, true),
- QoS5 = ?not_SetStartTimeSupported(QoS4, true),
- QoS_NO_OF_EVENTS = ?not_SetMaxEventsPerConsumer(QoS5, ?NO_OF_EVENTS),
-
- %% Initiate DB
- TimeService = cosTime:start_time_service(2, 0),
- Ref = cosNotification_eventDB:create_db(QoS_NO_OF_EVENTS, 50, 50, TimeService),
-
- T1 = 'CosTime_UTO':'_get_utc_time'('CosTime_UTO':
- absolute_time('CosTime_TimeService':
- new_universal_time(TimeService,
- 100000000, 0, 2))),
- T2 = 'CosTime_UTO':'_get_utc_time'('CosTime_UTO':
- absolute_time('CosTime_TimeService':
- new_universal_time(TimeService,
- 200000000, 0, 2))),
- T3 = 'CosTime_UTO':'_get_utc_time'('CosTime_UTO':
- absolute_time('CosTime_TimeService':
- new_universal_time(TimeService,
- 300000000, 0, 2))),
- T4 = 'CosTime_UTO':'_get_utc_time'('CosTime_UTO':
- absolute_time('CosTime_TimeService':
- new_universal_time(TimeService,
- 400000000, 0, 2))),
- %% Delivered after 10 seconds discarded after 20.
- EVENT1 = ?not_CreateSE("","event1","",
- [#'CosNotification_Property'
- {name="Priority",
- value=any:create(orber_tc:short(), 1)},
- #'CosNotification_Property'
- {name="StartTime",
- value=any:create('TimeBase_UtcT':tc(), T1)},
- #'CosNotification_Property'
- {name="StopTime",
- value=any:create('TimeBase_UtcT':tc(), T2)}],
- [], any:create(orber_tc:null(), null)),
-
- %% Delivered after 30 seconds discarded after 10, i.e., always discarded.
- EVENT2 = ?not_CreateSE("","event2","",
- [#'CosNotification_Property'
- {name="Priority",
- value=any:create(orber_tc:short(), 3)},
- #'CosNotification_Property'
- {name="StartTime",
- value=any:create('TimeBase_UtcT':tc(), T3)},
- #'CosNotification_Property'
- {name="StopTime",
- value=any:create('TimeBase_UtcT':tc(), T1)}],
- [], any:create(orber_tc:null(), null)),
-
- %% Delivered after 20 seconds discarded after 40
- EVENT3 = ?not_CreateSE("","event3","",
- [#'CosNotification_Property'
- {name="Priority",
- value=any:create(orber_tc:short(), 2)},
- #'CosNotification_Property'
- {name="StartTime",
- value=any:create('TimeBase_UtcT':tc(), T2)},
- #'CosNotification_Property'
- {name="StopTime",
- value=any:create('TimeBase_UtcT':tc(), T4)}],
- [], any:create(orber_tc:null(), null)),
-
-
-
-
- create_loop([EVENT1, EVENT2, EVENT3], Ref),
-
- ?match({[], false}, cosNotification_eventDB:get_events(Ref, ?NO_OF_EVENTS)),
-
- %% Sleep so some events will get 'old'.
- timer:sleep(12000),
-
- ?match({[EVENT1], true}, cosNotification_eventDB:get_events(Ref, ?NO_OF_EVENTS)),
-
- ?match({[], false}, cosNotification_eventDB:get_events(Ref, ?NO_OF_EVENTS)),
-
- timer:sleep(10000),
-
- ?match({[EVENT3], true}, cosNotification_eventDB:get_events(Ref, ?NO_OF_EVENTS)),
-
- timer:sleep(20000),
-
- %% See if EVENT2 really have been discarded.
- ?match({[], false}, cosNotification_eventDB:get_events(Ref, ?NO_OF_EVENTS)),
-
- cosNotification_eventDB:destroy_db(Ref),
-
- cosTime:stop_time_service(TimeService),
-
- ok.
-
-
-%%-----------------------------------------------------------------
-%% cosNotification_eventDB order API tests
-%%-----------------------------------------------------------------
-%% The event DB is used to store events which cannot be
-%% delivered at once. If the QoS is updated we must be
-%% able to change the ordering of events as the discard
-%% and order policies tells us.
-reorder_api(_Config) ->
- %% We need to test switching between:
- %% * Priority -> Fifo
- %% * Priority -> Deadline
- %% * Fifo -> Priority
- %% * Fifo -> Deadline
- %% * Deadline -> Priority
- %% * Deadline -> Fifo
- QoS = ?not_CreateInitQoS(),
- QoS2 = ?not_SetMaxEventsPerConsumer(QoS,100),
- QoS3 = ?not_SetPriority(QoS2, 10),
- QoS4 = ?not_SetStartTimeSupported(QoS3, false),
- QoS5 = ?not_SetOrderPolicy(QoS4, ?not_AnyOrder),
-
-
- %% Test all order policies using Any order discard policy.
- reorder_helper(?not_SetDiscardPolicy(QoS5, ?not_AnyOrder), "Discard Any"),
- reorder_helper(?not_SetDiscardPolicy(QoS5, ?not_PriorityOrder), "Discard Priority"),
- reorder_helper(?not_SetDiscardPolicy(QoS5, ?not_DeadlineOrder), "Discard Deadline"),
- reorder_helper(?not_SetDiscardPolicy(QoS5, ?not_FifoOrder), "Discard Fifo"),
- reorder_helper(?not_SetDiscardPolicy(QoS5, ?not_LifoOrder), "Discard Lifo"),
- reorder_helper(?not_SetDiscardPolicy(QoS5, ?not_RejectNewEvents), "Reject New Events"),
-
- ok.
-
-
-reorder_helper(QoS, Txt) ->
- io:format("$$$$$$$$$$$$$$$$$$$$ ~s $$$$$$$$$$$$$$$$$$$~n", [Txt]),
- %% Create a DB with the above settings.
- Ref = cosNotification_eventDB:create_db(QoS, 60, 50, undefined),
-
- Events = ?EVENTS,
- PrioOrder = ?PRIOORDER,
- FifoOrder = ?FIFOORDER,
- DeadlineOrder = ?DEADLINEORDER,
-
- %% Test all order policies using Any order discard policy.
- Ref2 = do_reorder(Ref, Events, ?not_SetOrderPolicy(QoS, ?not_FifoOrder),
- FifoOrder, "Priority -> Fifo"),
- Ref3 = do_reorder(Ref2, Events, ?not_SetOrderPolicy(QoS, ?not_PriorityOrder),
- PrioOrder, "Fifo -> Priority"),
- Ref4 = do_reorder(Ref3, Events, ?not_SetOrderPolicy(QoS, ?not_DeadlineOrder),
- DeadlineOrder, "Priority -> Deadline"),
-
- Ref5 = do_reorder(Ref4, Events, ?not_SetOrderPolicy(QoS, ?not_PriorityOrder),
- PrioOrder, "Deadline -> Priority"),
-
- Ref6 = do_reorder(Ref5, Events, ?not_SetOrderPolicy(QoS, ?not_FifoOrder),
- FifoOrder, "Priority -> Fifo"),
-
- Ref7 = do_reorder(Ref6, Events, ?not_SetOrderPolicy(QoS, ?not_DeadlineOrder),
- DeadlineOrder, "Fifo -> Deadline"),
-
- Ref8 = do_reorder(Ref7, Events, ?not_SetOrderPolicy(QoS, ?not_FifoOrder),
- FifoOrder, "Deadline -> Fifo"),
- cosNotification_eventDB:destroy_db(Ref8),
- ok.
-
-
-
-do_reorder(Ref, Events, QoS, Reply, Txt) ->
- create_loop(Events, Ref),
- io:format("################# ~s #################~n", [Txt]),
- NewRef = cosNotification_eventDB:update(Ref, QoS),
- ?match({Reply,_}, cosNotification_eventDB:get_events(NewRef, ?NO_OF_EVENTS)),
- NewRef.
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-%% This functions takes as argument a list of structured events.
-create_loop([], _Ref) ->
- ok;
-create_loop([H|T], Ref) ->
- catch cosNotification_eventDB:add_event(Ref, H),
- create_loop(T, Ref).
-
-create_loop([], _Ref, _Life, _Prio) ->
- ok;
-create_loop([H|T], Ref, Life, Prio) ->
- catch cosNotification_eventDB:add_event(Ref, H, Life, Prio),
- create_loop(T, Ref, Life, Prio).
-
-%%-------------------- End of Module ------------------------------
diff --git a/lib/cosNotification/test/generated_SUITE.erl b/lib/cosNotification/test/generated_SUITE.erl
deleted file mode 100644
index 8e3ccbd90e..0000000000
--- a/lib/cosNotification/test/generated_SUITE.erl
+++ /dev/null
@@ -1,1928 +0,0 @@
-%%-----------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File : generated_SUITE.erl
-%% Purpose :
-%%-----------------------------------------------------------------
-
--module(generated_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
-
--define(default_timeout, test_server:minutes(3)).
-
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
--define(nomatch(Not, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- Not ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS);
- _ ->
- AcTuAlReS
- end
- end()).
-
-
--define(checktc(_Op),
- fun(TC) ->
- case orber_tc:check_tc(TC) of
- false ->
- io:format("###### ERROR ERROR ######~n~p - ~p~n", [Op, TC]),
- exit(TC);
- true ->
- true
- end
- end).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- ['CosNotification',
- 'CosNotification_AdminPropertiesAdmin',
- 'CosNotification_EventHeader',
- 'CosNotification_EventType',
- 'CosNotification_FixedEventHeader',
- 'CosNotification_NamedPropertyRange',
- 'CosNotification_Property',
- 'CosNotification_PropertyError',
- 'CosNotification_PropertyRange',
- 'CosNotification_QoSAdmin',
- 'CosNotification_StructuredEvent',
- 'CosNotification_UnsupportedAdmin',
- 'CosNotification_UnsupportedQoS',
- 'CosNotification_EventBatch',
- 'CosNotification_EventTypeSeq',
- 'CosNotification_NamedPropertyRangeSeq',
- 'CosNotification_PropertyErrorSeq',
- 'CosNotifyChannelAdmin_AdminLimit',
- 'CosNotifyChannelAdmin_AdminNotFound',
- 'CosNotifyChannelAdmin_ChannelNotFound',
- 'CosNotifyChannelAdmin_ConnectionAlreadyActive',
- 'CosNotifyChannelAdmin_ConnectionAlreadyInactive',
- 'CosNotifyChannelAdmin_NotConnected',
- 'CosNotifyChannelAdmin_AdminIDSeq',
- 'CosNotifyChannelAdmin_ChannelIDSeq',
- 'CosNotifyChannelAdmin_ProxyIDSeq',
- 'CosNotifyFilter_CallbackNotFound',
- 'CosNotifyFilter_ConstraintExp',
- 'CosNotifyFilter_ConstraintInfo',
- 'CosNotifyFilter_ConstraintNotFound',
- 'CosNotifyFilter_DuplicateConstraintID',
- 'CosNotifyFilter_FilterNotFound',
- 'CosNotifyFilter_InvalidConstraint',
- 'CosNotifyFilter_InvalidGrammar',
- 'CosNotifyFilter_InvalidValue',
- 'CosNotifyFilter_MappingConstraintInfo',
- 'CosNotifyFilter_MappingConstraintPair',
- 'CosNotifyFilter_UnsupportedFilterableData',
- 'CosNotifyFilter_CallbackIDSeq',
- 'CosNotifyFilter_ConstraintExpSeq',
- 'CosNotifyFilter_ConstraintIDSeq',
- 'CosNotifyFilter_ConstraintInfoSeq',
- 'CosNotifyFilter_FilterIDSeq',
- 'CosNotifyFilter_MappingConstraintInfoSeq',
- 'CosNotifyFilter_MappingConstraintPairSeq',
- 'CosNotifyComm_InvalidEventType',
- 'CosNotifyChannelAdmin_ConsumerAdmin',
- 'CosNotifyChannelAdmin_EventChannel',
- 'CosNotifyChannelAdmin_EventChannelFactory',
- 'CosNotifyChannelAdmin_ProxyConsumer',
- 'CosNotifyChannelAdmin_ProxyNotFound',
- 'CosNotifyChannelAdmin_ProxyPullConsumer',
- 'CosNotifyChannelAdmin_ProxyPullSupplier',
- 'CosNotifyChannelAdmin_ProxyPushConsumer',
- 'CosNotifyChannelAdmin_ProxyPushSupplier',
- 'CosNotifyChannelAdmin_ProxySupplier',
- 'CosNotifyChannelAdmin_SequenceProxyPullConsumer',
- 'CosNotifyChannelAdmin_SequenceProxyPullSupplier',
- 'CosNotifyChannelAdmin_SequenceProxyPushConsumer',
- 'CosNotifyChannelAdmin_SequenceProxyPushSupplier',
- 'CosNotifyChannelAdmin_StructuredProxyPullConsumer',
- 'CosNotifyChannelAdmin_StructuredProxyPullSupplier',
- 'CosNotifyChannelAdmin_StructuredProxyPushConsumer',
- 'CosNotifyChannelAdmin_StructuredProxyPushSupplier',
- 'CosNotifyChannelAdmin_SupplierAdmin',
- 'CosNotifyFilter_Filter', 'CosNotifyFilter_FilterAdmin',
- 'CosNotifyFilter_FilterFactory',
- 'CosNotifyFilter_MappingFilter',
- 'CosNotifyComm_NotifyPublish',
- 'CosNotifyComm_NotifySubscribe',
- 'CosNotifyComm_PullConsumer',
- 'CosNotifyComm_PullSupplier',
- 'CosNotifyComm_PushConsumer',
- 'CosNotifyComm_PushSupplier',
- 'CosNotifyComm_SequencePullConsumer',
- 'CosNotifyComm_SequencePullSupplier',
- 'CosNotifyComm_SequencePushConsumer',
- 'CosNotifyComm_SequencePushSupplier',
- 'CosNotifyComm_StructuredPullConsumer',
- 'CosNotifyComm_StructuredPullSupplier',
- 'CosNotifyComm_StructuredPushConsumer',
- 'CosNotifyComm_StructuredPushSupplier',
- oe_CosNotificationComm_Event,
- 'CosNotification_PropertySeq'].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotification'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotification'(_) ->
- ?match("EventReliability", 'CosNotification':'EventReliability'()),
- ?match(0, 'CosNotification':'BestEffort'()),
- ?match(1, 'CosNotification':'Persistent'()),
- ?match("ConnectionReliability", 'CosNotification':'ConnectionReliability'()),
- ?match("Priority", 'CosNotification':'Priority'()),
- ?match(-32767, 'CosNotification':'LowestPriority'()),
- ?match(32767, 'CosNotification':'HighestPriority'()),
- ?match(0, 'CosNotification':'DefaultPriority'()),
- ?match("StartTime", 'CosNotification':'StartTime'()),
- ?match("StopTime", 'CosNotification':'StopTime'()),
- ?match("Timeout", 'CosNotification':'Timeout'()),
- ?match("OrderPolicy", 'CosNotification':'OrderPolicy'()),
- ?match(0, 'CosNotification':'AnyOrder'()),
- ?match(1, 'CosNotification':'FifoOrder'()),
- ?match(2, 'CosNotification':'PriorityOrder'()),
- ?match(3, 'CosNotification':'DeadlineOrder'()),
- ?match("DiscardPolicy", 'CosNotification':'DiscardPolicy'()),
- ?match(4, 'CosNotification':'LifoOrder'()),
- ?match(5, 'CosNotification':'RejectNewEvents'()),
- ?match("MaximumBatchSize", 'CosNotification':'MaximumBatchSize'()),
- ?match("PacingInterval", 'CosNotification':'PacingInterval'()),
- ?match("StartTimeSupported", 'CosNotification':'StartTimeSupported'()),
- ?match("StopTimeSupported", 'CosNotification':'StopTimeSupported'()),
- ?match("MaxEventsPerConsumer", 'CosNotification':'MaxEventsPerConsumer'()),
- ?match("MaxQueueLength", 'CosNotification':'MaxQueueLength'()),
- ?match("MaxConsumers", 'CosNotification':'MaxConsumers'()),
- ?match("MaxSuppliers", 'CosNotification':'MaxSuppliers'()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotification_EventHeader'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotification_EventHeader'(_) ->
- ?match(true, orber_tc:check_tc('CosNotification_EventHeader':tc())),
- ?match("IDL:omg.org/CosNotification/EventHeader:1.0",
- 'CosNotification_EventHeader':id()),
- ?match("CosNotification_EventHeader",
- 'CosNotification_EventHeader':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotification_EventType'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotification_EventType'(_) ->
- ?match(true, orber_tc:check_tc('CosNotification_EventType':tc())),
- ?match("IDL:omg.org/CosNotification/EventType:1.0",
- 'CosNotification_EventType':id()),
- ?match("CosNotification_EventType",
- 'CosNotification_EventType':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotification_FixedEventHeader'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotification_FixedEventHeader'(_) ->
- ?match(true, orber_tc:check_tc('CosNotification_FixedEventHeader':tc())),
- ?match("IDL:omg.org/CosNotification/FixedEventHeader:1.0",
- 'CosNotification_FixedEventHeader':id()),
- ?match("CosNotification_FixedEventHeader",
- 'CosNotification_FixedEventHeader':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotification_NamedPropertyRange'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotification_NamedPropertyRange'(_) ->
- ?match(true, orber_tc:check_tc('CosNotification_NamedPropertyRange':tc())),
- ?match("IDL:omg.org/CosNotification/NamedPropertyRange:1.0",
- 'CosNotification_NamedPropertyRange':id()),
- ?match("CosNotification_NamedPropertyRange",
- 'CosNotification_NamedPropertyRange':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotification_Property'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotification_Property'(_) ->
- ?match(true, orber_tc:check_tc('CosNotification_Property':tc())),
- ?match("IDL:omg.org/CosNotification/Property:1.0",
- 'CosNotification_Property':id()),
- ?match("CosNotification_Property",
- 'CosNotification_Property':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotification_PropertyError'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotification_PropertyError'(_) ->
- ?match(true, orber_tc:check_tc('CosNotification_PropertyError':tc())),
- ?match("IDL:omg.org/CosNotification/PropertyError:1.0",
- 'CosNotification_PropertyError':id()),
- ?match("CosNotification_PropertyError",
- 'CosNotification_PropertyError':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotification_PropertyRange'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotification_PropertyRange'(_) ->
- ?match(true, orber_tc:check_tc('CosNotification_PropertyRange':tc())),
- ?match("IDL:omg.org/CosNotification/PropertyRange:1.0",
- 'CosNotification_PropertyRange':id()),
- ?match("CosNotification_PropertyRange",
- 'CosNotification_PropertyRange':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotification_StructuredEvent'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotification_StructuredEvent'(_) ->
- ?match(true, orber_tc:check_tc('CosNotification_StructuredEvent':tc())),
- ?match("IDL:omg.org/CosNotification/StructuredEvent:1.0",
- 'CosNotification_StructuredEvent':id()),
- ?match("CosNotification_StructuredEvent",
- 'CosNotification_StructuredEvent':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotification_UnsupportedAdmin'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotification_UnsupportedAdmin'(_) ->
- ?match(true, orber_tc:check_tc('CosNotification_UnsupportedAdmin':tc())),
- ?match("IDL:omg.org/CosNotification/UnsupportedAdmin:1.0",
- 'CosNotification_UnsupportedAdmin':id()),
- ?match("CosNotification_UnsupportedAdmin",
- 'CosNotification_UnsupportedAdmin':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotification_UnsupportedQoS'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotification_UnsupportedQoS'(_) ->
- ?match(true, orber_tc:check_tc('CosNotification_UnsupportedQoS':tc())),
- ?match("IDL:omg.org/CosNotification/UnsupportedQoS:1.0",
- 'CosNotification_UnsupportedQoS':id()),
- ?match("CosNotification_UnsupportedQoS",
- 'CosNotification_UnsupportedQoS':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotification_EventBatch'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotification_EventBatch'(_) ->
- ?match(true, orber_tc:check_tc('CosNotification_EventBatch':tc())),
- ?match("IDL:omg.org/CosNotification/EventBatch:1.0",
- 'CosNotification_EventBatch':id()),
- ?match("CosNotification_EventBatch",
- 'CosNotification_EventBatch':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotification_EventTypeSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotification_EventTypeSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosNotification_EventTypeSeq':tc())),
- ?match("IDL:omg.org/CosNotification/EventTypeSeq:1.0",
- 'CosNotification_EventTypeSeq':id()),
- ?match("CosNotification_EventTypeSeq",
- 'CosNotification_EventTypeSeq':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotification_NamedPropertyRangeSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotification_NamedPropertyRangeSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosNotification_NamedPropertyRangeSeq':tc())),
- ?match("IDL:omg.org/CosNotification/NamedPropertyRangeSeq:1.0",
- 'CosNotification_NamedPropertyRangeSeq':id()),
- ?match("CosNotification_NamedPropertyRangeSeq",
- 'CosNotification_NamedPropertyRangeSeq':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotification_PropertyErrorSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotification_PropertyErrorSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosNotification_PropertyErrorSeq':tc())),
- ?match("IDL:omg.org/CosNotification/PropertyErrorSeq:1.0",
- 'CosNotification_PropertyErrorSeq':id()),
- ?match("CosNotification_PropertyErrorSeq",
- 'CosNotification_PropertyErrorSeq':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotification_PropertySeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotification_PropertySeq'(_) ->
- ?match(true, orber_tc:check_tc('CosNotification_PropertySeq':tc())),
- ?match("IDL:omg.org/CosNotification/PropertySeq:1.0",
- 'CosNotification_PropertySeq':id()),
- ?match("CosNotification_PropertySeq",
- 'CosNotification_PropertySeq':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_AdminLimit'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_AdminLimit'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyChannelAdmin_AdminLimit':tc())),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/AdminLimit:1.0",
- 'CosNotifyChannelAdmin_AdminLimit':id()),
- ?match("CosNotifyChannelAdmin_AdminLimit",
- 'CosNotifyChannelAdmin_AdminLimit':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_AdminLimitExceeded'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_AdminLimitExceeded'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyChannelAdmin_AdminLimitExceeded':tc())),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/AdminLimitExceeded:1.0",
- 'CosNotifyChannelAdmin_AdminLimitExceeded':id()),
- ?match("CosNotifyChannelAdmin_AdminLimitExceeded",
- 'CosNotifyChannelAdmin_AdminLimitExceeded':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_AdminNotFound'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_AdminNotFound'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyChannelAdmin_AdminNotFound':tc())),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/AdminNotFound:1.0",
- 'CosNotifyChannelAdmin_AdminNotFound':id()),
- ?match("CosNotifyChannelAdmin_AdminNotFound",
- 'CosNotifyChannelAdmin_AdminNotFound':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_ChannelNotFound'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_ChannelNotFound'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyChannelAdmin_ChannelNotFound':tc())),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/ChannelNotFound:1.0",
- 'CosNotifyChannelAdmin_ChannelNotFound':id()),
- ?match("CosNotifyChannelAdmin_ChannelNotFound",
- 'CosNotifyChannelAdmin_ChannelNotFound':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_ConnectionAlreadyActive'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_ConnectionAlreadyActive'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyChannelAdmin_ConnectionAlreadyActive':tc())),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/ConnectionAlreadyActive:1.0",
- 'CosNotifyChannelAdmin_ConnectionAlreadyActive':id()),
- ?match("CosNotifyChannelAdmin_ConnectionAlreadyActive",
- 'CosNotifyChannelAdmin_ConnectionAlreadyActive':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_ConnectionAlreadyInactive'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_ConnectionAlreadyInactive'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyChannelAdmin_ConnectionAlreadyInactive':tc())),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/ConnectionAlreadyInactive:1.0",
- 'CosNotifyChannelAdmin_ConnectionAlreadyInactive':id()),
- ?match("CosNotifyChannelAdmin_ConnectionAlreadyInactive",
- 'CosNotifyChannelAdmin_ConnectionAlreadyInactive':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_NotConnected'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_NotConnected'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyChannelAdmin_NotConnected':tc())),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/NotConnected:1.0",
- 'CosNotifyChannelAdmin_NotConnected':id()),
- ?match("CosNotifyChannelAdmin_NotConnected",
- 'CosNotifyChannelAdmin_NotConnected':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_AdminIDSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_AdminIDSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyChannelAdmin_AdminIDSeq':tc())),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/AdminIDSeq:1.0",
- 'CosNotifyChannelAdmin_AdminIDSeq':id()),
- ?match("CosNotifyChannelAdmin_AdminIDSeq",
- 'CosNotifyChannelAdmin_AdminIDSeq':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_ChannelIDSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_ChannelIDSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyChannelAdmin_ChannelIDSeq':tc())),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/ChannelIDSeq:1.0",
- 'CosNotifyChannelAdmin_ChannelIDSeq':id()),
- ?match("CosNotifyChannelAdmin_ChannelIDSeq",
- 'CosNotifyChannelAdmin_ChannelIDSeq':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_ProxyIDSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_ProxyIDSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyChannelAdmin_ProxyIDSeq':tc())),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/ProxyIDSeq:1.0",
- 'CosNotifyChannelAdmin_ProxyIDSeq':id()),
- ?match("CosNotifyChannelAdmin_ProxyIDSeq",
- 'CosNotifyChannelAdmin_ProxyIDSeq':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_CallbackNotFound'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_CallbackNotFound'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_CallbackNotFound':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/CallbackNotFound:1.0",
- 'CosNotifyFilter_CallbackNotFound':id()),
- ?match("CosNotifyFilter_CallbackNotFound",
- 'CosNotifyFilter_CallbackNotFound':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_ConstraintExp'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_ConstraintExp'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_ConstraintExp':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/ConstraintExp:1.0",
- 'CosNotifyFilter_ConstraintExp':id()),
- ?match("CosNotifyFilter_ConstraintExp",
- 'CosNotifyFilter_ConstraintExp':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_ConstraintInfo'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_ConstraintInfo'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_ConstraintInfo':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/ConstraintInfo:1.0",
- 'CosNotifyFilter_ConstraintInfo':id()),
- ?match("CosNotifyFilter_ConstraintInfo",
- 'CosNotifyFilter_ConstraintInfo':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_ConstraintNotFound'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_ConstraintNotFound'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_ConstraintNotFound':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/ConstraintNotFound:1.0",
- 'CosNotifyFilter_ConstraintNotFound':id()),
- ?match("CosNotifyFilter_ConstraintNotFound",
- 'CosNotifyFilter_ConstraintNotFound':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_DuplicateConstraintID'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_DuplicateConstraintID'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_DuplicateConstraintID':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/DuplicateConstraintID:1.0",
- 'CosNotifyFilter_DuplicateConstraintID':id()),
- ?match("CosNotifyFilter_DuplicateConstraintID",
- 'CosNotifyFilter_DuplicateConstraintID':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_FilterNotFound'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_FilterNotFound'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_FilterNotFound':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/FilterNotFound:1.0",
- 'CosNotifyFilter_FilterNotFound':id()),
- ?match("CosNotifyFilter_FilterNotFound",
- 'CosNotifyFilter_FilterNotFound':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_InvalidConstraint'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_InvalidConstraint'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_InvalidConstraint':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/InvalidConstraint:1.0",
- 'CosNotifyFilter_InvalidConstraint':id()),
- ?match("CosNotifyFilter_InvalidConstraint",
- 'CosNotifyFilter_InvalidConstraint':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_InvalidGrammar'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_InvalidGrammar'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_InvalidGrammar':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/InvalidGrammar:1.0",
- 'CosNotifyFilter_InvalidGrammar':id()),
- ?match("CosNotifyFilter_InvalidGrammar",
- 'CosNotifyFilter_InvalidGrammar':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_InvalidValue'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_InvalidValue'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_InvalidValue':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/InvalidValue:1.0",
- 'CosNotifyFilter_InvalidValue':id()),
- ?match("CosNotifyFilter_InvalidValue",
- 'CosNotifyFilter_InvalidValue':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_MappingConstraintInfo'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_MappingConstraintInfo'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_MappingConstraintInfo':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/MappingConstraintInfo:1.0",
- 'CosNotifyFilter_MappingConstraintInfo':id()),
- ?match("CosNotifyFilter_MappingConstraintInfo",
- 'CosNotifyFilter_MappingConstraintInfo':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_MappingConstraintPair'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_MappingConstraintPair'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_MappingConstraintPair':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/MappingConstraintPair:1.0",
- 'CosNotifyFilter_MappingConstraintPair':id()),
- ?match("CosNotifyFilter_MappingConstraintPair",
- 'CosNotifyFilter_MappingConstraintPair':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_UnsupportedFilterableData'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_UnsupportedFilterableData'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_UnsupportedFilterableData':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/UnsupportedFilterableData:1.0",
- 'CosNotifyFilter_UnsupportedFilterableData':id()),
- ?match("CosNotifyFilter_UnsupportedFilterableData",
- 'CosNotifyFilter_UnsupportedFilterableData':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_CallbackIDSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_CallbackIDSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_CallbackIDSeq':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/CallbackIDSeq:1.0",
- 'CosNotifyFilter_CallbackIDSeq':id()),
- ?match("CosNotifyFilter_CallbackIDSeq",
- 'CosNotifyFilter_CallbackIDSeq':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_ConstraintExpSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_ConstraintExpSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_ConstraintExpSeq':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/ConstraintExpSeq:1.0",
- 'CosNotifyFilter_ConstraintExpSeq':id()),
- ?match("CosNotifyFilter_ConstraintExpSeq",
- 'CosNotifyFilter_ConstraintExpSeq':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_ConstraintIDSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_ConstraintIDSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_ConstraintIDSeq':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/ConstraintIDSeq:1.0",
- 'CosNotifyFilter_ConstraintIDSeq':id()),
- ?match("CosNotifyFilter_ConstraintIDSeq",
- 'CosNotifyFilter_ConstraintIDSeq':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_ConstraintInfoSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_ConstraintInfoSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_ConstraintInfoSeq':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/ConstraintInfoSeq:1.0",
- 'CosNotifyFilter_ConstraintInfoSeq':id()),
- ?match("CosNotifyFilter_ConstraintInfoSeq",
- 'CosNotifyFilter_ConstraintInfoSeq':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_FilterIDSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_FilterIDSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_FilterIDSeq':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/FilterIDSeq:1.0",
- 'CosNotifyFilter_FilterIDSeq':id()),
- ?match("CosNotifyFilter_FilterIDSeq",
- 'CosNotifyFilter_FilterIDSeq':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_MappingConstraintInfoSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_MappingConstraintInfoSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_MappingConstraintInfoSeq':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/MappingConstraintInfoSeq:1.0",
- 'CosNotifyFilter_MappingConstraintInfoSeq':id()),
- ?match("CosNotifyFilter_MappingConstraintInfoSeq",
- 'CosNotifyFilter_MappingConstraintInfoSeq':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_MappingConstraintPairSeq'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_MappingConstraintPairSeq'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyFilter_MappingConstraintPairSeq':tc())),
- ?match("IDL:omg.org/CosNotifyFilter/MappingConstraintPairSeq:1.0",
- 'CosNotifyFilter_MappingConstraintPairSeq':id()),
- ?match("CosNotifyFilter_MappingConstraintPairSeq",
- 'CosNotifyFilter_MappingConstraintPairSeq':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyComm_InvalidEventType'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyComm_InvalidEventType'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyComm_InvalidEventType':tc())),
- ?match("IDL:omg.org/CosNotifyComm/InvalidEventType:1.0",
- 'CosNotifyComm_InvalidEventType':id()),
- ?match("CosNotifyComm_InvalidEventType",
- 'CosNotifyComm_InvalidEventType':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_ProxyNotFound'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_ProxyNotFound'(_) ->
- ?match(true, orber_tc:check_tc('CosNotifyChannelAdmin_ProxyNotFound':tc())),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/ProxyNotFound:1.0",
- 'CosNotifyChannelAdmin_ProxyNotFound':id()),
- ?match("CosNotifyChannelAdmin_ProxyNotFound",
- 'CosNotifyChannelAdmin_ProxyNotFound':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotification_AdminPropertiesAdmin'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotification_AdminPropertiesAdmin'(_) ->
- ?nomatch(undefined, 'CosNotification_AdminPropertiesAdmin':oe_tc(get_admin)),
- ?nomatch(undefined, 'CosNotification_AdminPropertiesAdmin':oe_tc(set_admin)),
- ?match(undefined, 'CosNotification_AdminPropertiesAdmin':oe_tc(undefined)),
- ?match([_|_], 'CosNotification_AdminPropertiesAdmin':oe_get_interface()),
- ?match("IDL:omg.org/CosNotification/AdminPropertiesAdmin:1.0",
- 'CosNotification_AdminPropertiesAdmin':typeID()),
- check_tc('CosNotification_AdminPropertiesAdmin':oe_get_interface()),
- ?match(true, 'CosNotification_AdminPropertiesAdmin':oe_is_a('CosNotification_AdminPropertiesAdmin':typeID())),
- ?match(false, 'CosNotification_AdminPropertiesAdmin':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotification_QoSAdmin'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotification_QoSAdmin'(_) ->
- ?nomatch(undefined, 'CosNotification_QoSAdmin':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosNotification_QoSAdmin':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosNotification_QoSAdmin':oe_tc(validate_qos)),
- ?match(undefined, 'CosNotification_QoSAdmin':oe_tc(undefined)),
- ?match([_|_], 'CosNotification_QoSAdmin':oe_get_interface()),
- ?match("IDL:omg.org/CosNotification/QoSAdmin:1.0",
- 'CosNotification_QoSAdmin':typeID()),
- check_tc('CosNotification_QoSAdmin':oe_get_interface()),
- ?match(true, 'CosNotification_QoSAdmin':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(false, 'CosNotification_QoSAdmin':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_ConsumerAdmin'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_ConsumerAdmin'(_) ->
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc('_get_MyID')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc('_get_MyChannel')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc('_get_MyOperator')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc('_get_priority_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc('_set_priority_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc('_get_lifetime_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc('_set_lifetime_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc('_get_pull_suppliers')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc('_get_push_suppliers')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc(get_proxy_supplier)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc(obtain_notification_pull_supplier)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc(obtain_notification_push_supplier)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc(destroy)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc(validate_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc(subscription_change)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc(add_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc(remove_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc(get_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc(get_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc(remove_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc(obtain_push_supplier)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc(obtain_pull_supplier)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc(callSeq)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc(callAny)),
- ?match(undefined, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyChannelAdmin_ConsumerAdmin':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/ConsumerAdmin:1.0",
- 'CosNotifyChannelAdmin_ConsumerAdmin':typeID()),
- check_tc('CosNotifyChannelAdmin_ConsumerAdmin':oe_get_interface()),
- ?match(true, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_is_a('CosNotifyChannelAdmin_ConsumerAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_is_a('CosNotifyComm_NotifySubscribe':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_is_a('CosNotifyFilter_FilterAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_is_a('CosEventChannelAdmin_ConsumerAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_is_a('oe_CosNotificationComm_Event':typeID())),
- ?match(false, 'CosNotifyChannelAdmin_ConsumerAdmin':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_EventChannel'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_EventChannel'(_) ->
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc('_get_MyFactory')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc('_get_default_consumer_admin')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc('_get_default_supplier_admin')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc('_get_default_filter_factory')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc(new_for_consumers)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc(new_for_suppliers)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc(get_consumeradmin)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc(get_supplieradmin)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc(get_all_consumeradmins)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc(get_all_supplieradmins)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc(validate_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc(get_admin)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc(set_admin)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc(for_consumers)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc(for_suppliers)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc(destroy)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc(callSeq)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc(callAny)),
- ?match(undefined, 'CosNotifyChannelAdmin_EventChannel':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyChannelAdmin_EventChannel':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/EventChannel:1.0",
- 'CosNotifyChannelAdmin_EventChannel':typeID()),
- check_tc('CosNotifyChannelAdmin_EventChannel':oe_get_interface()),
- ?match(true, 'CosNotifyChannelAdmin_EventChannel':oe_is_a('CosNotifyChannelAdmin_EventChannel':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_EventChannel':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_EventChannel':oe_is_a('CosNotification_AdminPropertiesAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_EventChannel':oe_is_a('CosEventChannelAdmin_EventChannel':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_EventChannel':oe_is_a('oe_CosNotificationComm_Event':typeID())),
- ?match(false, 'CosNotifyChannelAdmin_EventChannel':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_EventChannelFactory'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_EventChannelFactory'(_) ->
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannelFactory':oe_tc(create_channel)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannelFactory':oe_tc(get_all_channels)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_EventChannelFactory':oe_tc(get_event_channel)),
- ?match(undefined, 'CosNotifyChannelAdmin_EventChannelFactory':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyChannelAdmin_EventChannelFactory':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/EventChannelFactory:1.0",
- 'CosNotifyChannelAdmin_EventChannelFactory':typeID()),
- check_tc('CosNotifyChannelAdmin_EventChannelFactory':oe_get_interface()),
- ?match(true, 'CosNotifyChannelAdmin_EventChannelFactory':oe_is_a('CosNotifyChannelAdmin_EventChannelFactory':typeID())),
- ?match(false, 'CosNotifyChannelAdmin_EventChannelFactory':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_ProxyConsumer'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_ProxyConsumer'(_) ->
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyConsumer':oe_tc('_get_MyType')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyConsumer':oe_tc('_get_MyAdmin')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyConsumer':oe_tc(obtain_subscription_types)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyConsumer':oe_tc(validate_event_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyConsumer':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyConsumer':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyConsumer':oe_tc(validate_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyConsumer':oe_tc(add_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyConsumer':oe_tc(remove_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyConsumer':oe_tc(get_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyConsumer':oe_tc(get_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyConsumer':oe_tc(remove_all_filters)),
- ?match(undefined, 'CosNotifyChannelAdmin_ProxyConsumer':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyChannelAdmin_ProxyConsumer':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/ProxyConsumer:1.0",
- 'CosNotifyChannelAdmin_ProxyConsumer':typeID()),
- check_tc('CosNotifyChannelAdmin_ProxyConsumer':oe_get_interface()),
- ?match(true, 'CosNotifyChannelAdmin_ProxyConsumer':oe_is_a('CosNotifyChannelAdmin_ProxyConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyConsumer':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyConsumer':oe_is_a('CosNotifyFilter_FilterAdmin':typeID())),
- ?match(false, 'CosNotifyChannelAdmin_ProxyConsumer':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_ProxyPullConsumer'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_ProxyPullConsumer'(_) ->
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc(connect_any_pull_supplier)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc(suspend_connection)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc(resume_connection)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc('_get_MyType')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc('_get_MyAdmin')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc(obtain_subscription_types)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc(validate_event_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc(validate_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc(add_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc(remove_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc(get_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc(get_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc(remove_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc(offer_change)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc(disconnect_pull_consumer)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc(connect_pull_supplier)),
- ?match(undefined, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/ProxyPullConsumer:1.0",
- 'CosNotifyChannelAdmin_ProxyPullConsumer':typeID()),
- check_tc('CosNotifyChannelAdmin_ProxyPullConsumer':oe_get_interface()),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_is_a('CosNotifyChannelAdmin_ProxyPullConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_is_a('CosNotifyChannelAdmin_ProxyConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_is_a('CosNotifyFilter_FilterAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_is_a('CosNotifyComm_PullConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_is_a('CosNotifyComm_NotifyPublish':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_is_a('CosEventComm_PullConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_is_a('CosEventChannelAdmin_ProxyPullConsumer':typeID())),
- ?match(false, 'CosNotifyChannelAdmin_ProxyPullConsumer':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_ProxyPullSupplier'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_ProxyPullSupplier'(_) ->
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc('_get_MyType')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc('_get_MyAdmin')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc('_get_priority_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc('_set_priority_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc('_get_lifetime_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc('_set_lifetime_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc(obtain_offered_types)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc(validate_event_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc(validate_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc(add_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc(remove_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc(get_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc(get_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc(remove_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc(subscription_change)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc(pull)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc(try_pull)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc(disconnect_pull_supplier)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc(connect_pull_consumer)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc(callSeq)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc(callAny)),
- ?match(undefined, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/ProxyPullSupplier:1.0",
- 'CosNotifyChannelAdmin_ProxyPullSupplier':typeID()),
- check_tc('CosNotifyChannelAdmin_ProxyPullSupplier':oe_get_interface()),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_is_a('CosNotifyChannelAdmin_ProxyPullSupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_is_a('CosNotifyChannelAdmin_ProxySupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_is_a('CosNotifyFilter_FilterAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_is_a('CosNotifyComm_PullSupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_is_a('CosNotifyComm_NotifySubscribe':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_is_a('CosEventComm_PullSupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_is_a('CosEventChannelAdmin_ProxyPullSupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_is_a('oe_CosNotificationComm_Event':typeID())),
- ?match(false, 'CosNotifyChannelAdmin_ProxyPullSupplier':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_ProxyPushConsumer'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_ProxyPushConsumer'(_) ->
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_tc(connect_any_push_supplier)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_tc('_get_MyType')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_tc('_get_MyAdmin')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_tc(obtain_subscription_types)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_tc(validate_event_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_tc(validate_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_tc(add_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_tc(remove_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_tc(get_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_tc(get_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_tc(remove_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_tc(offer_change)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_tc(push)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_tc(disconnect_push_consumer)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_tc(connect_push_supplier)),
- ?match(undefined, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/ProxyPushConsumer:1.0",
- 'CosNotifyChannelAdmin_ProxyPushConsumer':typeID()),
- check_tc('CosNotifyChannelAdmin_ProxyPushConsumer':oe_get_interface()),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_is_a('CosNotifyChannelAdmin_ProxyPushConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_is_a('CosNotifyChannelAdmin_ProxyConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_is_a('CosNotifyFilter_FilterAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_is_a('CosNotifyComm_PushConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_is_a('CosNotifyComm_NotifyPublish':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_is_a('CosEventComm_PushConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_is_a('CosEventChannelAdmin_ProxyPushConsumer':typeID())),
- ?match(false, 'CosNotifyChannelAdmin_ProxyPushConsumer':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_ProxyPushSupplier'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_ProxyPushSupplier'(_) ->
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(connect_any_push_consumer)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(suspend_connection)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(resume_connection)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc('_get_MyType')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc('_get_MyAdmin')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc('_get_priority_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc('_set_priority_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc('_get_lifetime_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc('_set_lifetime_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(obtain_offered_types)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(validate_event_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(validate_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(add_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(remove_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(get_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(get_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(remove_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(subscription_change)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(disconnect_push_supplier)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(connect_push_consumer)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(callSeq)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(callAny)),
- ?match(undefined, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/ProxyPushSupplier:1.0",
- 'CosNotifyChannelAdmin_ProxyPushSupplier':typeID()),
- check_tc('CosNotifyChannelAdmin_ProxyPushSupplier':oe_get_interface()),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_is_a('CosNotifyChannelAdmin_ProxyPushSupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_is_a('CosNotifyChannelAdmin_ProxySupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_is_a('CosNotifyFilter_FilterAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_is_a('CosNotifyComm_PushSupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_is_a('CosNotifyComm_NotifySubscribe':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_is_a('CosEventComm_PushSupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_is_a('CosEventChannelAdmin_ProxyPushSupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_is_a('oe_CosNotificationComm_Event':typeID())),
- ?match(false, 'CosNotifyChannelAdmin_ProxyPushSupplier':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_ProxySupplier'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_ProxySupplier'(_) ->
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxySupplier':oe_tc('_get_MyType')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxySupplier':oe_tc('_get_MyAdmin')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxySupplier':oe_tc('_get_priority_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxySupplier':oe_tc('_set_priority_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxySupplier':oe_tc('_get_lifetime_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxySupplier':oe_tc('_set_lifetime_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxySupplier':oe_tc(obtain_offered_types)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxySupplier':oe_tc(validate_event_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxySupplier':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxySupplier':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxySupplier':oe_tc(validate_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxySupplier':oe_tc(add_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxySupplier':oe_tc(remove_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxySupplier':oe_tc(get_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxySupplier':oe_tc(get_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_ProxySupplier':oe_tc(remove_all_filters)),
- ?match(undefined, 'CosNotifyChannelAdmin_ProxySupplier':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyChannelAdmin_ProxySupplier':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/ProxySupplier:1.0",
- 'CosNotifyChannelAdmin_ProxySupplier':typeID()),
- check_tc('CosNotifyChannelAdmin_ProxySupplier':oe_get_interface()),
- ?match(true, 'CosNotifyChannelAdmin_ProxySupplier':oe_is_a('CosNotifyChannelAdmin_ProxySupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxySupplier':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_ProxySupplier':oe_is_a('CosNotifyFilter_FilterAdmin':typeID())),
- ?match(false, 'CosNotifyChannelAdmin_ProxySupplier':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_SequenceProxyPullConsumer'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_SequenceProxyPullConsumer'(_) ->
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_tc(connect_sequence_pull_supplier)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_tc(suspend_connection)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_tc(resume_connection)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_tc('_get_MyType')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_tc('_get_MyAdmin')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_tc(obtain_subscription_types)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_tc(validate_event_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_tc(validate_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_tc(add_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_tc(remove_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_tc(get_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_tc(get_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_tc(remove_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_tc(disconnect_sequence_pull_consumer)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_tc(offer_change)),
- ?match(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/SequenceProxyPullConsumer:1.0",
- 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':typeID()),
- check_tc('CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_get_interface()),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_is_a('CosNotifyChannelAdmin_SequenceProxyPullConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_is_a('CosNotifyChannelAdmin_ProxyConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_is_a('CosNotifyFilter_FilterAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_is_a('CosNotifyComm_SequencePullConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_is_a('CosNotifyComm_NotifyPublish':typeID())),
- ?match(false, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_SequenceProxyPullSupplier'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_SequenceProxyPullSupplier'(_) ->
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc(connect_sequence_pull_consumer)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc('_get_MyType')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc('_get_MyAdmin')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc('_get_priority_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc('_set_priority_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc('_get_lifetime_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc('_set_lifetime_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc(obtain_offered_types)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc(validate_event_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc(validate_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc(add_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc(remove_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc(get_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc(get_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc(remove_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc(pull_structured_events)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc(try_pull_structured_events)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc(disconnect_sequence_pull_supplier)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc(subscription_change)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc(callSeq)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc(callAny)),
- ?match(undefined, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/SequenceProxyPullSupplier:1.0",
- 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':typeID()),
- check_tc('CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_get_interface()),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_is_a('CosNotifyChannelAdmin_SequenceProxyPullSupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_is_a('CosNotifyChannelAdmin_ProxySupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_is_a('CosNotifyFilter_FilterAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_is_a('CosNotifyComm_SequencePullSupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_is_a('CosNotifyComm_NotifySubscribe':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_is_a('oe_CosNotificationComm_Event':typeID())),
- ?match(false, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_SequenceProxyPushConsumer'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_SequenceProxyPushConsumer'(_) ->
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_tc(connect_sequence_push_supplier)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_tc('_get_MyType')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_tc('_get_MyAdmin')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_tc(obtain_subscription_types)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_tc(validate_event_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_tc(validate_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_tc(add_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_tc(remove_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_tc(get_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_tc(get_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_tc(remove_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_tc(push_structured_events)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_tc(disconnect_sequence_push_consumer)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_tc(offer_change)),
- ?match(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/SequenceProxyPushConsumer:1.0",
- 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':typeID()),
- check_tc('CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_get_interface()),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_is_a('CosNotifyChannelAdmin_SequenceProxyPushConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_is_a('CosNotifyChannelAdmin_ProxyConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_is_a('CosNotifyFilter_FilterAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_is_a('CosNotifyComm_SequencePushConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_is_a('CosNotifyComm_NotifyPublish':typeID())),
- ?match(false, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_SequenceProxyPushSupplier'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_SequenceProxyPushSupplier'(_) ->
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc(connect_sequence_push_consumer)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc(suspend_connection)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc(resume_connection)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc('_get_MyType')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc('_get_MyAdmin')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc('_get_priority_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc('_set_priority_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc('_get_lifetime_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc('_set_lifetime_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc(obtain_offered_types)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc(validate_event_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc(validate_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc(add_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc(remove_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc(get_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc(get_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc(remove_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc(disconnect_sequence_push_supplier)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc(subscription_change)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc(callSeq)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc(callAny)),
- ?match(undefined, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/SequenceProxyPushSupplier:1.0",
- 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':typeID()),
- check_tc('CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_get_interface()),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_is_a('CosNotifyChannelAdmin_SequenceProxyPushSupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_is_a('CosNotifyChannelAdmin_ProxySupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_is_a('CosNotifyFilter_FilterAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_is_a('CosNotifyComm_SequencePushSupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_is_a('CosNotifyComm_NotifySubscribe':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_is_a('oe_CosNotificationComm_Event':typeID())),
- ?match(false, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_StructuredProxyPullConsumer'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_StructuredProxyPullConsumer'(_) ->
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_tc(connect_structured_pull_supplier)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_tc(suspend_connection)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_tc(resume_connection)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_tc('_get_MyType')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_tc('_get_MyAdmin')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_tc(obtain_subscription_types)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_tc(validate_event_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_tc(validate_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_tc(add_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_tc(remove_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_tc(get_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_tc(get_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_tc(remove_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_tc(disconnect_structured_pull_consumer)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_tc(offer_change)),
- ?match(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/StructuredProxyPullConsumer:1.0",
- 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':typeID()),
- check_tc('CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_get_interface()),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_is_a('CosNotifyChannelAdmin_StructuredProxyPullConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_is_a('CosNotifyChannelAdmin_ProxyConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_is_a('CosNotifyFilter_FilterAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_is_a('CosNotifyComm_StructuredPullConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_is_a('CosNotifyComm_NotifyPublish':typeID())),
- ?match(false, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_StructuredProxyPullSupplier'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_StructuredProxyPullSupplier'(_) ->
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc(connect_structured_pull_consumer)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc('_get_MyType')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc('_get_MyAdmin')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc('_get_priority_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc('_set_priority_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc('_get_lifetime_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc('_set_lifetime_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc(obtain_offered_types)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc(validate_event_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc(validate_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc(add_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc(remove_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc(get_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc(get_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc(remove_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc(pull_structured_event)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc(try_pull_structured_event)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc(disconnect_structured_pull_supplier)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc(subscription_change)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc(callSeq)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc(callAny)),
- ?match(undefined, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/StructuredProxyPullSupplier:1.0",
- 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':typeID()),
- check_tc('CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_get_interface()),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_is_a('CosNotifyChannelAdmin_StructuredProxyPullSupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_is_a('CosNotifyChannelAdmin_ProxySupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_is_a('CosNotifyFilter_FilterAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_is_a('CosNotifyComm_StructuredPullSupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_is_a('CosNotifyComm_NotifySubscribe':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_is_a('oe_CosNotificationComm_Event':typeID())),
- ?match(false, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_StructuredProxyPushConsumer'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_StructuredProxyPushConsumer'(_) ->
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_tc(connect_structured_push_supplier)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_tc('_get_MyType')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_tc('_get_MyAdmin')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_tc(obtain_subscription_types)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_tc(validate_event_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_tc(validate_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_tc(add_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_tc(remove_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_tc(get_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_tc(get_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_tc(remove_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_tc(push_structured_event)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_tc(disconnect_structured_push_consumer)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_tc(offer_change)),
- ?match(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/StructuredProxyPushConsumer:1.0",
- 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':typeID()),
- check_tc('CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_get_interface()),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_is_a('CosNotifyChannelAdmin_StructuredProxyPushConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_is_a('CosNotifyChannelAdmin_ProxyConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_is_a('CosNotifyFilter_FilterAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_is_a('CosNotifyComm_StructuredPushConsumer':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_is_a('CosNotifyComm_NotifyPublish':typeID())),
- ?match(false, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_StructuredProxyPushSupplier'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_StructuredProxyPushSupplier'(_) ->
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc(connect_structured_push_consumer)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc(suspend_connection)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc(resume_connection)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc('_get_MyType')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc('_get_MyAdmin')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc('_get_priority_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc('_set_priority_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc('_get_lifetime_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc('_set_lifetime_filter')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc(obtain_offered_types)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc(validate_event_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc(validate_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc(add_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc(remove_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc(get_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc(get_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc(remove_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc(disconnect_structured_push_supplier)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc(subscription_change)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc(callSeq)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc(callAny)),
- ?match(undefined, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/StructuredProxyPushSupplier:1.0",
- 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':typeID()),
- check_tc('CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_get_interface()),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_is_a('CosNotifyChannelAdmin_StructuredProxyPushSupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_is_a('CosNotifyChannelAdmin_ProxySupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_is_a('CosNotifyFilter_FilterAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_is_a('CosNotifyComm_StructuredPushSupplier':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_is_a('CosNotifyComm_NotifySubscribe':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_is_a('oe_CosNotificationComm_Event':typeID())),
- ?match(false, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyChannelAdmin_SupplierAdmin'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyChannelAdmin_SupplierAdmin'(_) ->
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc('_get_MyID')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc('_get_MyChannel')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc('_get_MyOperator')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc('_get_pull_consumers')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc('_get_push_consumers')),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc(get_proxy_consumer)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc(obtain_notification_pull_consumer)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc(obtain_notification_push_consumer)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc(destroy)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc(get_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc(set_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc(validate_qos)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc(offer_change)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc(add_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc(remove_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc(get_filter)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc(get_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc(remove_all_filters)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc(obtain_push_consumer)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc(obtain_pull_consumer)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc(callSeq)),
- ?nomatch(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc(callAny)),
- ?match(undefined, 'CosNotifyChannelAdmin_SupplierAdmin':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyChannelAdmin_SupplierAdmin':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyChannelAdmin/SupplierAdmin:1.0",
- 'CosNotifyChannelAdmin_SupplierAdmin':typeID()),
- check_tc('CosNotifyChannelAdmin_SupplierAdmin':oe_get_interface()),
- ?match(true, 'CosNotifyChannelAdmin_SupplierAdmin':oe_is_a('CosNotifyChannelAdmin_SupplierAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SupplierAdmin':oe_is_a('CosNotification_QoSAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SupplierAdmin':oe_is_a('CosNotifyComm_NotifyPublish':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SupplierAdmin':oe_is_a('CosNotifyFilter_FilterAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SupplierAdmin':oe_is_a('CosEventChannelAdmin_SupplierAdmin':typeID())),
- ?match(true, 'CosNotifyChannelAdmin_SupplierAdmin':oe_is_a('oe_CosNotificationComm_Event':typeID())),
- ?match(false, 'CosNotifyChannelAdmin_SupplierAdmin':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_Filter'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_Filter'(_) ->
- ?nomatch(undefined, 'CosNotifyFilter_Filter':oe_tc('_get_constraint_grammar')),
- ?nomatch(undefined, 'CosNotifyFilter_Filter':oe_tc(add_constraints)),
- ?nomatch(undefined, 'CosNotifyFilter_Filter':oe_tc(modify_constraints)),
- ?nomatch(undefined, 'CosNotifyFilter_Filter':oe_tc(get_constraints)),
- ?nomatch(undefined, 'CosNotifyFilter_Filter':oe_tc(get_all_constraints)),
- ?nomatch(undefined, 'CosNotifyFilter_Filter':oe_tc(remove_all_constraints)),
- ?nomatch(undefined, 'CosNotifyFilter_Filter':oe_tc(destroy)),
- ?nomatch(undefined, 'CosNotifyFilter_Filter':oe_tc(match)),
- ?nomatch(undefined, 'CosNotifyFilter_Filter':oe_tc(match_structured)),
- ?nomatch(undefined, 'CosNotifyFilter_Filter':oe_tc(match_typed)),
- ?nomatch(undefined, 'CosNotifyFilter_Filter':oe_tc(attach_callback)),
- ?nomatch(undefined, 'CosNotifyFilter_Filter':oe_tc(detach_callback)),
- ?nomatch(undefined, 'CosNotifyFilter_Filter':oe_tc(get_callbacks)),
- ?match(undefined, 'CosNotifyFilter_Filter':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyFilter_Filter':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyFilter/Filter:1.0",
- 'CosNotifyFilter_Filter':typeID()),
- check_tc('CosNotifyFilter_Filter':oe_get_interface()),
- ?match(true, 'CosNotifyFilter_Filter':oe_is_a('CosNotifyFilter_Filter':typeID())),
- ?match(false, 'CosNotifyFilter_Filter':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_FilterAdmin'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_FilterAdmin'(_) ->
- ?nomatch(undefined, 'CosNotifyFilter_FilterAdmin':oe_tc(add_filter)),
- ?nomatch(undefined, 'CosNotifyFilter_FilterAdmin':oe_tc(remove_filter)),
- ?nomatch(undefined, 'CosNotifyFilter_FilterAdmin':oe_tc(get_filter)),
- ?nomatch(undefined, 'CosNotifyFilter_FilterAdmin':oe_tc(get_all_filters)),
- ?nomatch(undefined, 'CosNotifyFilter_FilterAdmin':oe_tc(remove_all_filters)),
- ?match(undefined, 'CosNotifyFilter_FilterAdmin':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyFilter_FilterAdmin':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyFilter/FilterAdmin:1.0",
- 'CosNotifyFilter_FilterAdmin':typeID()),
- check_tc('CosNotifyFilter_FilterAdmin':oe_get_interface()),
- ?match(true, 'CosNotifyFilter_FilterAdmin':oe_is_a('CosNotifyFilter_FilterAdmin':typeID())),
- ?match(false, 'CosNotifyFilter_FilterAdmin':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_FilterFactory'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_FilterFactory'(_) ->
- ?nomatch(undefined, 'CosNotifyFilter_FilterFactory':oe_tc(create_filter)),
- ?nomatch(undefined, 'CosNotifyFilter_FilterFactory':oe_tc(create_mapping_filter)),
- ?match(undefined, 'CosNotifyFilter_FilterFactory':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyFilter_FilterFactory':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyFilter/FilterFactory:1.0",
- 'CosNotifyFilter_FilterFactory':typeID()),
- check_tc('CosNotifyFilter_FilterFactory':oe_get_interface()),
- ?match(true, 'CosNotifyFilter_FilterFactory':oe_is_a('CosNotifyFilter_FilterFactory':typeID())),
- ?match(false, 'CosNotifyFilter_FilterFactory':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyFilter_MappingFilter'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyFilter_MappingFilter'(_) ->
- ?nomatch(undefined, 'CosNotifyFilter_MappingFilter':oe_tc('_get_constraint_grammar')),
- ?nomatch(undefined, 'CosNotifyFilter_MappingFilter':oe_tc('_get_value_type')),
- ?nomatch(undefined, 'CosNotifyFilter_MappingFilter':oe_tc('_get_default_value')),
- ?nomatch(undefined, 'CosNotifyFilter_MappingFilter':oe_tc(add_mapping_constraints)),
- ?nomatch(undefined, 'CosNotifyFilter_MappingFilter':oe_tc(modify_mapping_constraints)),
- ?nomatch(undefined, 'CosNotifyFilter_MappingFilter':oe_tc(get_mapping_constraints)),
- ?nomatch(undefined, 'CosNotifyFilter_MappingFilter':oe_tc(get_all_mapping_constraints)),
- ?nomatch(undefined, 'CosNotifyFilter_MappingFilter':oe_tc(remove_all_mapping_constraints)),
- ?nomatch(undefined, 'CosNotifyFilter_MappingFilter':oe_tc(destroy)),
- ?nomatch(undefined, 'CosNotifyFilter_MappingFilter':oe_tc(match)),
- ?nomatch(undefined, 'CosNotifyFilter_MappingFilter':oe_tc(match_structured)),
- ?nomatch(undefined, 'CosNotifyFilter_MappingFilter':oe_tc(match_typed)),
- ?match(undefined, 'CosNotifyFilter_MappingFilter':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyFilter_MappingFilter':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyFilter/MappingFilter:1.0",
- 'CosNotifyFilter_MappingFilter':typeID()),
- check_tc('CosNotifyFilter_MappingFilter':oe_get_interface()),
- ?match(true, 'CosNotifyFilter_MappingFilter':oe_is_a('CosNotifyFilter_MappingFilter':typeID())),
- ?match(false, 'CosNotifyFilter_MappingFilter':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyComm_NotifyPublish'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyComm_NotifyPublish'(_) ->
- ?nomatch(undefined, 'CosNotifyComm_NotifyPublish':oe_tc(offer_change)),
- ?match(undefined, 'CosNotifyComm_NotifyPublish':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyComm_NotifyPublish':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyComm/NotifyPublish:1.0",
- 'CosNotifyComm_NotifyPublish':typeID()),
- check_tc('CosNotifyComm_NotifyPublish':oe_get_interface()),
- ?match(true, 'CosNotifyComm_NotifyPublish':oe_is_a('CosNotifyComm_NotifyPublish':typeID())),
- ?match(false, 'CosNotifyComm_NotifyPublish':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyComm_NotifySubscribe'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyComm_NotifySubscribe'(_) ->
- ?nomatch(undefined, 'CosNotifyComm_NotifySubscribe':oe_tc(subscription_change)),
- ?match(undefined, 'CosNotifyComm_NotifySubscribe':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyComm_NotifySubscribe':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyComm/NotifySubscribe:1.0",
- 'CosNotifyComm_NotifySubscribe':typeID()),
- check_tc('CosNotifyComm_NotifySubscribe':oe_get_interface()),
- ?match(true, 'CosNotifyComm_NotifySubscribe':oe_is_a('CosNotifyComm_NotifySubscribe':typeID())),
- ?match(false, 'CosNotifyComm_NotifySubscribe':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyComm_PullConsumer'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyComm_PullConsumer'(_) ->
- ?nomatch(undefined, 'CosNotifyComm_PullConsumer':oe_tc(offer_change)),
- ?nomatch(undefined, 'CosNotifyComm_PullConsumer':oe_tc(disconnect_pull_consumer)),
- ?match(undefined, 'CosNotifyComm_PullConsumer':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyComm_PullConsumer':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyComm/PullConsumer:1.0",
- 'CosNotifyComm_PullConsumer':typeID()),
- check_tc('CosNotifyComm_PullConsumer':oe_get_interface()),
- ?match(true, 'CosNotifyComm_PullConsumer':oe_is_a('CosNotifyComm_PullConsumer':typeID())),
- ?match(true, 'CosNotifyComm_PullConsumer':oe_is_a('CosNotifyComm_NotifyPublish':typeID())),
- ?match(true, 'CosNotifyComm_PullConsumer':oe_is_a('CosEventComm_PullConsumer':typeID())),
- ?match(false, 'CosNotifyComm_PullConsumer':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyComm_PullSupplier'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyComm_PullSupplier'(_) ->
- ?nomatch(undefined, 'CosNotifyComm_PullSupplier':oe_tc(subscription_change)),
- ?nomatch(undefined, 'CosNotifyComm_PullSupplier':oe_tc(pull)),
- ?nomatch(undefined, 'CosNotifyComm_PullSupplier':oe_tc(try_pull)),
- ?nomatch(undefined, 'CosNotifyComm_PullSupplier':oe_tc(disconnect_pull_supplier)),
- ?match(undefined, 'CosNotifyComm_PullSupplier':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyComm_PullSupplier':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyComm/PullSupplier:1.0",
- 'CosNotifyComm_PullSupplier':typeID()),
- check_tc('CosNotifyComm_PullSupplier':oe_get_interface()),
- ?match(true, 'CosNotifyComm_PullSupplier':oe_is_a('CosNotifyComm_PullSupplier':typeID())),
- ?match(true, 'CosNotifyComm_PullSupplier':oe_is_a('CosNotifyComm_NotifySubscribe':typeID())),
- ?match(true, 'CosNotifyComm_PullSupplier':oe_is_a('CosEventComm_PullSupplier':typeID())),
- ?match(false, 'CosNotifyComm_PullSupplier':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyComm_PushConsumer'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyComm_PushConsumer'(_) ->
- ?nomatch(undefined, 'CosNotifyComm_PushConsumer':oe_tc(offer_change)),
- ?nomatch(undefined, 'CosNotifyComm_PushConsumer':oe_tc(push)),
- ?nomatch(undefined, 'CosNotifyComm_PushConsumer':oe_tc(disconnect_push_consumer)),
- ?match(undefined, 'CosNotifyComm_PushConsumer':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyComm_PushConsumer':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyComm/PushConsumer:1.0",
- 'CosNotifyComm_PushConsumer':typeID()),
- check_tc('CosNotifyComm_PushConsumer':oe_get_interface()),
- ?match(true, 'CosNotifyComm_PushConsumer':oe_is_a('CosNotifyComm_PushConsumer':typeID())),
- ?match(true, 'CosNotifyComm_PushConsumer':oe_is_a('CosNotifyComm_NotifyPublish':typeID())),
- ?match(true, 'CosNotifyComm_PushConsumer':oe_is_a('CosEventComm_PushConsumer':typeID())),
- ?match(false, 'CosNotifyComm_PushConsumer':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyComm_PushSupplier'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyComm_PushSupplier'(_) ->
- ?nomatch(undefined, 'CosNotifyComm_PushSupplier':oe_tc(subscription_change)),
- ?nomatch(undefined, 'CosNotifyComm_PushSupplier':oe_tc(disconnect_push_supplier)),
- ?match(undefined, 'CosNotifyComm_PushSupplier':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyComm_PushSupplier':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyComm/PushSupplier:1.0",
- 'CosNotifyComm_PushSupplier':typeID()),
- check_tc('CosNotifyComm_PushSupplier':oe_get_interface()),
- ?match(true, 'CosNotifyComm_PushSupplier':oe_is_a('CosNotifyComm_PushSupplier':typeID())),
- ?match(true, 'CosNotifyComm_PushSupplier':oe_is_a('CosNotifyComm_NotifySubscribe':typeID())),
- ?match(true, 'CosNotifyComm_PushSupplier':oe_is_a('CosEventComm_PushSupplier':typeID())),
- ?match(false, 'CosNotifyComm_PushSupplier':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyComm_SequencePullConsumer'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyComm_SequencePullConsumer'(_) ->
- ?nomatch(undefined, 'CosNotifyComm_SequencePullConsumer':oe_tc(disconnect_sequence_pull_consumer)),
- ?nomatch(undefined, 'CosNotifyComm_SequencePullConsumer':oe_tc(offer_change)),
- ?match(undefined, 'CosNotifyComm_SequencePullConsumer':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyComm_SequencePullConsumer':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyComm/SequencePullConsumer:1.0",
- 'CosNotifyComm_SequencePullConsumer':typeID()),
- check_tc('CosNotifyComm_SequencePullConsumer':oe_get_interface()),
- ?match(true, 'CosNotifyComm_SequencePullConsumer':oe_is_a('CosNotifyComm_SequencePullConsumer':typeID())),
- ?match(true, 'CosNotifyComm_SequencePullConsumer':oe_is_a('CosNotifyComm_NotifyPublish':typeID())),
- ?match(false, 'CosNotifyComm_SequencePullConsumer':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyComm_SequencePullSupplier'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyComm_SequencePullSupplier'(_) ->
- ?nomatch(undefined, 'CosNotifyComm_SequencePullSupplier':oe_tc(pull_structured_events)),
- ?nomatch(undefined, 'CosNotifyComm_SequencePullSupplier':oe_tc(try_pull_structured_events)),
- ?nomatch(undefined, 'CosNotifyComm_SequencePullSupplier':oe_tc(disconnect_sequence_pull_supplier)),
- ?nomatch(undefined, 'CosNotifyComm_SequencePullSupplier':oe_tc(subscription_change)),
- ?match(undefined, 'CosNotifyComm_SequencePullSupplier':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyComm_SequencePullSupplier':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyComm/SequencePullSupplier:1.0",
- 'CosNotifyComm_SequencePullSupplier':typeID()),
- check_tc('CosNotifyComm_SequencePullSupplier':oe_get_interface()),
- ?match(true, 'CosNotifyComm_SequencePullSupplier':oe_is_a('CosNotifyComm_SequencePullSupplier':typeID())),
- ?match(true, 'CosNotifyComm_SequencePullSupplier':oe_is_a('CosNotifyComm_NotifySubscribe':typeID())),
- ?match(false, 'CosNotifyComm_SequencePullSupplier':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyComm_SequencePushConsumer'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyComm_SequencePushConsumer'(_) ->
- ?nomatch(undefined, 'CosNotifyComm_SequencePushConsumer':oe_tc(push_structured_events)),
- ?nomatch(undefined, 'CosNotifyComm_SequencePushConsumer':oe_tc(disconnect_sequence_push_consumer)),
- ?nomatch(undefined, 'CosNotifyComm_SequencePushConsumer':oe_tc(offer_change)),
- ?match(undefined, 'CosNotifyComm_SequencePushConsumer':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyComm_SequencePushConsumer':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyComm/SequencePushConsumer:1.0",
- 'CosNotifyComm_SequencePushConsumer':typeID()),
- check_tc('CosNotifyComm_SequencePushConsumer':oe_get_interface()),
- ?match(true, 'CosNotifyComm_SequencePushConsumer':oe_is_a('CosNotifyComm_SequencePushConsumer':typeID())),
- ?match(true, 'CosNotifyComm_SequencePushConsumer':oe_is_a('CosNotifyComm_NotifyPublish':typeID())),
- ?match(false, 'CosNotifyComm_SequencePushConsumer':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyComm_SequencePushSupplier'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyComm_SequencePushSupplier'(_) ->
- ?nomatch(undefined, 'CosNotifyComm_SequencePushSupplier':oe_tc(disconnect_sequence_push_supplier)),
- ?nomatch(undefined, 'CosNotifyComm_SequencePushSupplier':oe_tc(subscription_change)),
- ?match(undefined, 'CosNotifyComm_SequencePushSupplier':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyComm_SequencePushSupplier':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyComm/SequencePushSupplier:1.0",
- 'CosNotifyComm_SequencePushSupplier':typeID()),
- check_tc('CosNotifyComm_SequencePushSupplier':oe_get_interface()),
- ?match(true, 'CosNotifyComm_SequencePushSupplier':oe_is_a('CosNotifyComm_SequencePushSupplier':typeID())),
- ?match(true, 'CosNotifyComm_SequencePushSupplier':oe_is_a('CosNotifyComm_NotifySubscribe':typeID())),
- ?match(false, 'CosNotifyComm_SequencePushSupplier':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyComm_StructuredPullConsumer'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyComm_StructuredPullConsumer'(_) ->
- ?nomatch(undefined, 'CosNotifyComm_StructuredPullConsumer':oe_tc(disconnect_structured_pull_consumer)),
- ?nomatch(undefined, 'CosNotifyComm_StructuredPullConsumer':oe_tc(offer_change)),
- ?match(undefined, 'CosNotifyComm_StructuredPullConsumer':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyComm_StructuredPullConsumer':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyComm/StructuredPullConsumer:1.0",
- 'CosNotifyComm_StructuredPullConsumer':typeID()),
- check_tc('CosNotifyComm_StructuredPullConsumer':oe_get_interface()),
- ?match(true, 'CosNotifyComm_StructuredPullConsumer':oe_is_a('CosNotifyComm_StructuredPullConsumer':typeID())),
- ?match(true, 'CosNotifyComm_StructuredPullConsumer':oe_is_a('CosNotifyComm_NotifyPublish':typeID())),
- ?match(false, 'CosNotifyComm_StructuredPullConsumer':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyComm_StructuredPullSupplier'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyComm_StructuredPullSupplier'(_) ->
- ?nomatch(undefined, 'CosNotifyComm_StructuredPullSupplier':oe_tc(pull_structured_event)),
- ?nomatch(undefined, 'CosNotifyComm_StructuredPullSupplier':oe_tc(try_pull_structured_event)),
- ?nomatch(undefined, 'CosNotifyComm_StructuredPullSupplier':oe_tc(disconnect_structured_pull_supplier)),
- ?nomatch(undefined, 'CosNotifyComm_StructuredPullSupplier':oe_tc(subscription_change)),
- ?match(undefined, 'CosNotifyComm_StructuredPullSupplier':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyComm_StructuredPullSupplier':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyComm/StructuredPullSupplier:1.0",
- 'CosNotifyComm_StructuredPullSupplier':typeID()),
- check_tc('CosNotifyComm_StructuredPullSupplier':oe_get_interface()),
- ?match(true, 'CosNotifyComm_StructuredPullSupplier':oe_is_a('CosNotifyComm_StructuredPullSupplier':typeID())),
- ?match(true, 'CosNotifyComm_StructuredPullSupplier':oe_is_a('CosNotifyComm_NotifySubscribe':typeID())),
- ?match(false, 'CosNotifyComm_StructuredPullSupplier':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyComm_StructuredPushConsumer'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyComm_StructuredPushConsumer'(_) ->
- ?nomatch(undefined, 'CosNotifyComm_StructuredPushConsumer':oe_tc(push_structured_event)),
- ?nomatch(undefined, 'CosNotifyComm_StructuredPushConsumer':oe_tc(disconnect_structured_push_consumer)),
- ?nomatch(undefined, 'CosNotifyComm_StructuredPushConsumer':oe_tc(offer_change)),
- ?match(undefined, 'CosNotifyComm_StructuredPushConsumer':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyComm_StructuredPushConsumer':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyComm/StructuredPushConsumer:1.0",
- 'CosNotifyComm_StructuredPushConsumer':typeID()),
- check_tc('CosNotifyComm_StructuredPushConsumer':oe_get_interface()),
- ?match(true, 'CosNotifyComm_StructuredPushConsumer':oe_is_a('CosNotifyComm_StructuredPushConsumer':typeID())),
- ?match(true, 'CosNotifyComm_StructuredPushConsumer':oe_is_a('CosNotifyComm_NotifyPublish':typeID())),
- ?match(false, 'CosNotifyComm_StructuredPushConsumer':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNotifyComm_StructuredPushSupplier'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNotifyComm_StructuredPushSupplier'(_) ->
- ?nomatch(undefined, 'CosNotifyComm_StructuredPushSupplier':oe_tc(disconnect_structured_push_supplier)),
- ?nomatch(undefined, 'CosNotifyComm_StructuredPushSupplier':oe_tc(subscription_change)),
- ?match(undefined, 'CosNotifyComm_StructuredPushSupplier':oe_tc(undefined)),
- ?match([_|_], 'CosNotifyComm_StructuredPushSupplier':oe_get_interface()),
- ?match("IDL:omg.org/CosNotifyComm/StructuredPushSupplier:1.0",
- 'CosNotifyComm_StructuredPushSupplier':typeID()),
- check_tc('CosNotifyComm_StructuredPushSupplier':oe_get_interface()),
- ?match(true, 'CosNotifyComm_StructuredPushSupplier':oe_is_a('CosNotifyComm_StructuredPushSupplier':typeID())),
- ?match(true, 'CosNotifyComm_StructuredPushSupplier':oe_is_a('CosNotifyComm_NotifySubscribe':typeID())),
- ?match(false, 'CosNotifyComm_StructuredPushSupplier':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'oe_CosNotificationComm_Event'
-%% Description:
-%%-----------------------------------------------------------------
-'oe_CosNotificationComm_Event'(_) ->
- ?nomatch(undefined, 'oe_CosNotificationComm_Event':oe_tc(callSeq)),
- ?nomatch(undefined, 'oe_CosNotificationComm_Event':oe_tc(callAny)),
- ?match(undefined, 'oe_CosNotificationComm_Event':oe_tc(undefined)),
- ?match([_|_], 'oe_CosNotificationComm_Event':oe_get_interface()),
- ?match("IDL:oe_CosNotificationComm/Event:1.0",
- 'oe_CosNotificationComm_Event':typeID()),
- check_tc('oe_CosNotificationComm_Event':oe_get_interface()),
- ?match(true, 'oe_CosNotificationComm_Event':oe_is_a('oe_CosNotificationComm_Event':typeID())),
- ?match(false, 'oe_CosNotificationComm_Event':oe_is_a("wrong")),
- ok.
-
-
-
-
-%%-----------------------------------------------------------------
-%% MISC functions
-%%-----------------------------------------------------------------
-check_tc([]) ->
- ok;
-check_tc([{Op, {RetType, InParameters, OutParameters}}|T]) ->
- io:format("checked - ~s~n", [Op]),
- lists:all(?checktc(Op), [RetType|InParameters]),
- lists:all(?checktc(Op), OutParameters),
- check_tc(T).
-
-
diff --git a/lib/cosNotification/test/grammar_SUITE.erl b/lib/cosNotification/test/grammar_SUITE.erl
deleted file mode 100644
index 536292fdee..0000000000
--- a/lib/cosNotification/test/grammar_SUITE.erl
+++ /dev/null
@@ -1,1091 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%--------------------------------------------------------------------
-%% File : grammar_SUITE.erl
-%% Purpose : Testing the CosNotification BNF grammar.
-%%--------------------------------------------------------------------
-
--module(grammar_SUITE).
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-%% cosEvent files.
--include_lib("cosEvent/include/CosEventChannelAdmin.hrl").
-%% Application files
--include_lib("cosNotification/include/CosNotification.hrl").
--include_lib("cosNotification/include/CosNotifyChannelAdmin.hrl").
--include_lib("cosNotification/include/CosNotifyComm.hrl").
--include_lib("cosNotification/include/CosNotifyFilter.hrl").
-
--include_lib("cosNotification/src/CosNotification_Definitions.hrl").
-
--include("idl_output/notify_test.hrl").
-
--include_lib("common_test/include/ct.hrl").
-
-%%--------------- DEFINES ------------------------------------
--define(default_timeout, test_server:minutes(20)).
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
- cases/0, init_per_suite/1, end_per_suite/1,
- union_api/1, enum_api/1, simple_types_api/1,
- components_api/1, positional_api/1, variable_api/1,
- init_per_testcase/2, end_per_testcase/2]).
-
--import(cosNotification_Filter, [create_filter/1, eval/2]).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-cases() ->
- [variable_api, union_api, enum_api, simple_types_api,
- components_api, positional_api].
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- if
- is_list(Config) ->
- Config;
- true ->
- exit("Config not a list")
- end.
-
-end_per_suite(Config) ->
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- Config.
-
-
-%%-----------------------------------------------------------------
-%% simple types grammar tests
-%%-----------------------------------------------------------------
-simple_types_api(_Config) ->
- %% Will always be true, no matter what kind of event we receive.
- {ok,T1} = ?match({ok, _}, create_filter("2==2 and 3<4")),
- ?match(true, eval(T1, ?not_CreateSE("DomainName","TypeName","EventName",
- [],[], any:create(orber_tc:null(), null)))),
-
- %% Will always be true, no matter what kind of event we receive.
- {ok,T2} = ?match({ok, _}, create_filter("")),
- ?match(true, eval(T2, ?not_CreateSE("DomainName","TypeName","EventName",
- [],[], any:create(orber_tc:null(), null)))),
-
- %% Check if $variable works
- {ok,T3} = ?match({ok, _}, create_filter("$city == \'Berlin\'")),
- ?match(true, eval(T3, ?not_CreateSE("DomainName","TypeName","EventName",
- [#'CosNotification_Property'{name="city",
- value=any:create(orber_tc:string(0), "Berlin")}],
- [], any:create(orber_tc:null(), null)))),
- ?match(false, eval(T3, ?not_CreateSE("DomainName","TypeName", "EventName",
- [#'CosNotification_Property'{name="city",
- value=any:create(orber_tc:string(0), "Dallas")}],
-
- [], any:create(orber_tc:null(), null)))),
-
-
- {ok,T4} = ?match({ok, _}, create_filter("$zip == 44")),
- ?match(true, eval(T4, ?not_CreateSE("DomainName","TypeName", "EventName",
- [#'CosNotification_Property'{name="zip",
- value=any:create(orber_tc:short(), 44)}],
-
- [], any:create(orber_tc:null(), null)))),
- ?match(true, eval(T4, ?not_CreateSE("DomainName","TypeName", "EventName",
- [],[],
- any:create('CosNotification_Property':tc(),
- #'CosNotification_Property'
- {name="zip",
- value=any:create(orber_tc:short(),
- 44)})))),
- ?match(false, eval(T4, ?not_CreateSE("DomainName","TypeName", "EventName",
- [#'CosNotification_Property'{name="zip",
- value=any:create(orber_tc:short(), 33)}],
-
- [], any:create(orber_tc:null(), null)))),
-
- %% Will always be true, no matter what kind of event we receive.
- {ok,T5} = ?match({ok, _}, create_filter("\'oo'\~\'foobar\'")),
- ?match(true, eval(T5, ?not_CreateSE("DomainName","TypeName","EventName",
- [],[], any:create(orber_tc:null(), null)))),
- %% Will always be false, no matter what kind of event we receive.
- {ok,T6} = ?match({ok, _}, create_filter("\'o1'\~\'foobar\'")),
- ?match(false, eval(T6, ?not_CreateSE("DomainName","TypeName","EventName",
- [],[], any:create(orber_tc:null(), null)))),
-
- %% Can we apply the ~ operation as above using a variable
- {ok,T7} = ?match({ok, _}, create_filter("$str~\'foobar\'")),
- ?match(true, eval(T7, ?not_CreateSE("DomainName","TypeName","EventName",
- [#'CosNotification_Property'{name="str",
- value=any:create(orber_tc:string(0), "oo")}],
- [], any:create(orber_tc:null(), null)))),
- ?match(false, eval(T7, ?not_CreateSE("DomainName","TypeName","EventName",
- [#'CosNotification_Property'{name="str",
- value=any:create(orber_tc:string(0), "ok")}],
- [], any:create(orber_tc:null(), null)))),
-
-
-
- {ok,_T8} = ?match({ok, _}, create_filter("$\\zip == 44444")),
-
- ok.
-
-%%-----------------------------------------------------------------
-%% enum grammar tests
-%%-----------------------------------------------------------------
-enum_api(_Config) ->
- %% Accept events whose 'in' enum is set to the value 'HOUSE' or 'CAR'.
- {ok,T1} = ?match({ok, _}, create_filter("$.\\in == HOUSE or $.\\in == CAR")),
-
- ?match(true, eval(T1, any:create(orber_tc:alias("IFRId","in",tk_any),
- any:create({tk_enum, "IFRId", "in", ["HOUSE", "CAR"]},
- 'HOUSE')))),
- ?match(false, eval(T1, any:create(orber_tc:alias("IFRId","in",tk_any),
- any:create({tk_enum, "IFRId", "in", ["HOUSE", "CAR"]},
- 'GARAGE')))),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Union grammar tests
-%%-----------------------------------------------------------------
-union_api(_Config) ->
- {ok,T1} = ?match({ok, _}, create_filter("exist $.uni1._d and $.uni1._d == 1 and $.uni1.(1) == 10")),
- {ok,T2} = ?match({ok, _}, create_filter("default $.uni1._d and $.uni1.() == 10")),
- {ok,T3} = ?match({ok, _}, create_filter("default $.uni1._d and $.uni1.(999) == 10")),
- ?match(true, eval(T1, ?not_CreateSE("DomainName","CommunicationsAlarm",
- "EventName",[],[],
- any:create(orber_tc:alias("IDL:notify_test/namedAny:1.0",
- "uni1",
- tk_any),
- any:create(notify_test_uni1:tc(),
- #notify_test_uni1{label= 1,
- value=10}))))),
- ?match(true, eval(T2, ?not_CreateSE("DomainName","CommunicationsAlarm",
- "EventName",[],[],
- any:create(orber_tc:alias("IDL:notify_test/namedAny:1.0",
- "uni1",
- tk_any),
- any:create(notify_test_uni1:tc(),
- #notify_test_uni1{label= 100,
- value=10}))))),
- ?match(true, eval(T3, ?not_CreateSE("DomainName","CommunicationsAlarm",
- "EventName",[],[],
- any:create(orber_tc:alias("IDL:notify_test/namedAny:1.0",
- "uni1",
- tk_any),
- any:create(notify_test_uni1:tc(),
- #notify_test_uni1{label= 100,
- value=10}))))),
- ?match(true, eval(T1, any:create(orber_tc:alias("IDL:notify_test/namedAny:1.0",
- "uni1",
- tk_any),
- any:create(notify_test_uni1:tc(),
- #notify_test_uni1{label= 1,
- value=10})))),
- ?match(false, eval(T2, any:create(orber_tc:alias("IDL:notify_test/namedAny:1.0",
- "uni1",
- tk_any),
- any:create(notify_test_uni1:tc(),
- #notify_test_uni1{label= 1,
- value=10})))),
- ?match(false, eval(T3, any:create(orber_tc:alias("IDL:notify_test/namedAny:1.0",
- "uni1",
- tk_any),
- any:create(notify_test_uni1:tc(),
- #notify_test_uni1{label= 1,
- value=10})))),
- ?match(true, eval(T1, ?not_CreateSE("DomainName","CommunicationsAlarm",
- "EventName",[],[],
- any:create(notify_test_studies:tc(), #notify_test_studies
- {uni1 = #notify_test_uni1{label= 1, value=10},
- gpa = 90,
- tests = [#'CosNotification_Property'
- {name="midterm", value=any:create(orber_tc:short(), 70)},
- #'CosNotification_Property'
- {name="final", value=any:create(orber_tc:short(), 60)}],
- monthly_attendance = {0,1,2,10}})))),
- ?match(false, eval(T2, ?not_CreateSE("DomainName","CommunicationsAlarm",
- "EventName",[],[],
- any:create(notify_test_studies:tc(), #notify_test_studies
- {uni1 = #notify_test_uni1{label= 1, value=10},
- gpa = 90,
- tests = [#'CosNotification_Property'
- {name="midterm", value=any:create(orber_tc:short(), 70)},
- #'CosNotification_Property'
- {name="final", value=any:create(orber_tc:short(), 60)}],
- monthly_attendance = {0,1,2,10}})))),
- ?match(false, eval(T3, ?not_CreateSE("DomainName","CommunicationsAlarm",
- "EventName",[],[],
- any:create(notify_test_studies:tc(), #notify_test_studies
- {uni1 = #notify_test_uni1{label= 1, value=10},
- gpa = 90,
- tests = [#'CosNotification_Property'
- {name="midterm", value=any:create(orber_tc:short(), 70)},
- #'CosNotification_Property'
- {name="final", value=any:create(orber_tc:short(), 60)}],
- monthly_attendance = {0,1,2,10}})))),
- ?match(true, eval(T1, any:create(notify_test_studies:tc(), #notify_test_studies
- {uni1 = #notify_test_uni1{label= 1, value=10},
- gpa = 90,
- tests = [#'CosNotification_Property'
- {name="midterm", value=any:create(orber_tc:short(), 70)},
- #'CosNotification_Property'
- {name="final", value=any:create(orber_tc:short(), 60)}],
- monthly_attendance = {0,1,2,10}}))),
- ?match(false, eval(T2, any:create(notify_test_studies:tc(), #notify_test_studies
- {uni1 = #notify_test_uni1{label= 1, value=10},
- gpa = 90,
- tests = [#'CosNotification_Property'
- {name="midterm", value=any:create(orber_tc:short(), 70)},
- #'CosNotification_Property'
- {name="final", value=any:create(orber_tc:short(), 60)}],
- monthly_attendance = {0,1,2,10}}))),
- ?match(false, eval(T3, any:create(notify_test_studies:tc(), #notify_test_studies
- {uni1 = #notify_test_uni1{label= 1, value=10},
- gpa = 90,
- tests = [#'CosNotification_Property'
- {name="midterm", value=any:create(orber_tc:short(), 70)},
- #'CosNotification_Property'
- {name="final", value=any:create(orber_tc:short(), 60)}],
- monthly_attendance = {0,1,2,10}}))),
-
- {ok,T4} = ?match({ok, _}, create_filter("exist $.alias.uni1._d and $.alias.uni1._d == 1 and $.alias.uni1.(1) == 10")),
- ?match(true, eval(T4, ?not_CreateSE("DomainName","CommunicationsAlarm",
- "EventName",[],[],
- any:create(orber_tc:alias(notify_test_studies:id(),
- "alias",
- notify_test_studies:tc()),
- #notify_test_studies
- {uni1 = #notify_test_uni1{label= 1, value=10},
- gpa = 90, tests = [],
- monthly_attendance = {0,1,2,10}})))),
- ?match(true, eval(T4, any:create(orber_tc:alias(notify_test_studies:id(),
- "alias",
- notify_test_studies:tc()),
- #notify_test_studies
- {uni1 = #notify_test_uni1{label= 1, value=10},
- gpa = 90, tests = [],
- monthly_attendance = {0,1,2,10}}))),
- %% Accept events with a default union discriminator set to the value 2.
- {ok,T5} = ?match({ok, _}, create_filter("default $._d and $.defvalue == 2")),
- ?match(true, eval(T5, any:create(notify_test_uni1:tc(),
- #notify_test_uni1{label= 100, value=2}))),
- %% label not default.
- ?match(false, eval(T5, any:create(notify_test_uni1:tc(),
- #notify_test_uni1{label= 2, value=2}))),
- %% Default does not exist (nor the component defvalue)
- ?match(false, eval(T5, any:create(notify_test_uni2:tc(),
- #notify_test_uni2{label= 100, value=2}))),
- %% Both wrong
- ?match(false, eval(T5, any:create(notify_test_uni2:tc(),
- #notify_test_uni2{label= 2, value=2}))),
-
- {ok,T6} = ?match({ok, _}, create_filter("default $._d and $.(-8) == 2")),
- ?match(true, eval(T6, any:create(notify_test_uni1:tc(),
- #notify_test_uni1{label= 100, value=2}))),
- %% label not default.
- ?match(false, eval(T6, any:create(notify_test_uni1:tc(),
- #notify_test_uni1{label= 2, value=2}))),
- %% Default does not exist (nor the component defvalue)
- ?match(false, eval(T6, any:create(notify_test_uni2:tc(),
- #notify_test_uni2{label= 100, value=2}))),
- %% Both wrong
- ?match(false, eval(T6, any:create(notify_test_uni2:tc(),
- #notify_test_uni2{label= 2, value=2}))),
- %% the same as the above, but we try to access a label that is not default
- {ok,T7} = ?match({ok, _}, create_filter("default $._d and $.(2) == 2")),
- ?match({error, _}, eval(T7, any:create(notify_test_uni1:tc(),
- #notify_test_uni1{label= 100, value=2}))),
-
- %% Must be a default-union with its 'defvalue' set to 2.
- {ok,T8} = ?match({ok, _}, create_filter("default $._d and $.('defvalue') == 2")),
- ?match(true, eval(T8, any:create(notify_test_uni1:tc(),
- #notify_test_uni1{label= 100, value=2}))),
- %% label not default.
- ?match(false, eval(T8, any:create(notify_test_uni1:tc(),
- #notify_test_uni1{label= 2, value=2}))),
- %% Default does not exist (nor the component defvalue)
- ?match(false, eval(T8, any:create(notify_test_uni2:tc(),
- #notify_test_uni2{label= 100, value=2}))),
- %% Both wrong
- ?match(false, eval(T8, any:create(notify_test_uni2:tc(),
- #notify_test_uni2{label= 2, value=2}))),
-
- %% Must be a default-union with its value set to 2.
- {ok,T9} = ?match({ok, _}, create_filter("default $._d and $.(+100) == 2")),
- ?match(true, eval(T9, any:create(notify_test_uni1:tc(),
- #notify_test_uni1{label= 100, value=2}))),
- %% label not default.
- ?match(false, eval(T9, any:create(notify_test_uni1:tc(),
- #notify_test_uni1{label= 2, value=2}))),
- %% Default does not exist (nor the component defvalue)
- ?match(false, eval(T9, any:create(notify_test_uni2:tc(),
- #notify_test_uni2{label= 100, value=2}))),
- %% Both wrong
- ?match(false, eval(T9, any:create(notify_test_uni2:tc(),
- #notify_test_uni2{label= 2, value=2}))),
-
- %% So far, we have only tested to access the union itself. No will use more
- %% complex union members.
- %% T10 and T11 is "equal"
- {ok,T10} = ?match({ok, _}, create_filter("$.M < 54")),
- {ok,T11} = ?match({ok, _}, create_filter("$.(5) < 54")),
- ?match(false, eval(T10, any:create(notify_test_K:tc(),
- #notify_test_K{label= 5, value=54}))),
- ?match(false, eval(T11, any:create(notify_test_K:tc(),
- #notify_test_K{label= 5, value=54}))),
- ?match(true, eval(T10, any:create(notify_test_K:tc(),
- #notify_test_K{label= 5, value=50}))),
- ?match(true, eval(T11, any:create(notify_test_K:tc(),
- #notify_test_K{label= 5, value=50}))),
- ?match({error,_}, eval(T10, any:create(notify_test_K:tc(),
- #notify_test_K{label= -1, value=50}))),
- ?match({error,_}, eval(T11, any:create(notify_test_K:tc(),
- #notify_test_K{label= -1, value=50}))),
-
- %% T12 and T13 is "equal"
- {ok,T12} = ?match({ok, _}, create_filter("$.L.C < 128")),
- {ok,T13} = ?match({ok, _}, create_filter("$.(3).2 < 128")),
- ?match(true, eval(T12, any:create(notify_test_K:tc(),
- #notify_test_K{label= 3, value=
- #notify_test_X{'A' = 1,
- 'B' = "string",
- 'C' = 120}}))),
- ?match(true, eval(T13, any:create(notify_test_K:tc(),
- #notify_test_K{label= 3, value=
- #notify_test_X{'A' = 1,
- 'B' = "string",
- 'C' = 120}}))),
- ?match(false, eval(T12, any:create(notify_test_K:tc(),
- #notify_test_K{label= 3, value=
- #notify_test_X{'A' = 1,
- 'B' = "string",
- 'C' = 200}}))),
- ?match(false, eval(T13, any:create(notify_test_K:tc(),
- #notify_test_K{label= 3, value=
- #notify_test_X{'A' = 1,
- 'B' = "string",
- 'C' = 200}}))),
-
- %% Test if 'putty' is a substring of K
- {ok,T15} = ?match({ok, _}, create_filter("'putty' ~ $.(2)")),
- {ok,T16} = ?match({ok, _}, create_filter("'putty' ~ $.K")),
- ?match(true, eval(T15, any:create(notify_test_K:tc(),
- #notify_test_K{label= 2, value= "isputtyok"}))),
- ?match(true, eval(T16, any:create(notify_test_K:tc(),
- #notify_test_K{label= 2, value= "isputtyok"}))),
- ?match(false, eval(T15, any:create(notify_test_K:tc(),
- #notify_test_K{label= 2, value= "notputtok"}))),
- ?match(false, eval(T16, any:create(notify_test_K:tc(),
- #notify_test_K{label= 2, value= "notputtok"}))),
-
- {ok,_T17} = ?match({ok, _}, create_filter("'putty' ~ $.(3).1")),
- {ok,_T18} = ?match({ok, _}, create_filter("'putty' ~ $.L.B")),
- ?match(true, eval(T12, any:create(notify_test_K:tc(),
- #notify_test_K{label= 3, value=
- #notify_test_X{'A' = 1,
- 'B' = "isputtyok",
- 'C' = 120}}))),
- ?match(true, eval(T13, any:create(notify_test_K:tc(),
- #notify_test_K{label= 3, value=
- #notify_test_X{'A' = 1,
- 'B' = "isputtyok",
- 'C' = 120}}))),
- ?match(false, eval(T12, any:create(notify_test_K:tc(),
- #notify_test_K{label= 3, value=
- #notify_test_X{'A' = 1,
- 'B' = "notputtok",
- 'C' = 200}}))),
- ?match(false, eval(T13, any:create(notify_test_K:tc(),
- #notify_test_K{label= 3, value=
- #notify_test_X{'A' = 1,
- 'B' = "notputtok",
- 'C' = 200}}))),
-
- %% Please observe that the switch 0 and 2 is defined to be equivalent.
- {ok,T19} = ?match({ok, _}, create_filter("$._d == 2 and $.(0) != 'hoob'")),
- {ok,T20} = ?match({ok, _}, create_filter("$._d == 2 and $.(2) != 'hoob'")),
- ?match(true, eval(T19, any:create(notify_test_K:tc(),
- #notify_test_K{label= 2, value= "nothoob"}))),
- ?match(true, eval(T20, any:create(notify_test_K:tc(),
- #notify_test_K{label= 2, value= "nothoob"}))),
- ?match(false, eval(T19, any:create(notify_test_K:tc(),
- #notify_test_K{label= 2, value= "hoob"}))),
- ?match(false, eval(T20, any:create(notify_test_K:tc(),
- #notify_test_K{label= 2, value= "hoob"}))),
-
- ?match(false, eval(T19, any:create(notify_test_K:tc(),
- #notify_test_K{label= 5, value= 55}))),
- ?match(false, eval(T20, any:create(notify_test_K:tc(),
- #notify_test_K{label= 5, value= 55}))),
-
- ?match(false, eval(T19, any:create(notify_test_K:tc(),
- #notify_test_K{label= 100, value= "nothoob"}))),
- ?match(false, eval(T20, any:create(notify_test_K:tc(),
- #notify_test_K{label= 100, value= "nothoob"}))),
-
- {ok,T21} = ?match({ok, _}, create_filter("exist $.K")),
- {ok,T22} = ?match({ok, _}, create_filter("exist $.(0) or exist $.(2)")),
- ?match(true, eval(T21, any:create(notify_test_K:tc(),
- #notify_test_K{label= 0, value= "hoob"}))),
- ?match(true, eval(T22, any:create(notify_test_K:tc(),
- #notify_test_K{label= 0, value= "hoob"}))),
- ?match(true, eval(T21, any:create(notify_test_K:tc(),
- #notify_test_K{label= 2, value= "hoob"}))),
- ?match(true, eval(T22, any:create(notify_test_K:tc(),
- #notify_test_K{label= 2, value= "hoob"}))),
- ?match(false, eval(T21, any:create(notify_test_K:tc(),
- #notify_test_K{label= 5, value= 55}))),
- ?match(false, eval(T22, any:create(notify_test_K:tc(),
- #notify_test_K{label= 5, value= 55}))),
-
-
- %% Please observe that the switch 0 and 2 is defined to be equivalent.
- {ok,T23} = ?match({ok, _}, create_filter("exist $.(2)")),
- {ok,T24} = ?match({ok, _}, create_filter("exist $.(0)")),
- ?match(true, eval(T23, any:create(notify_test_K:tc(),
- #notify_test_K{label= 2, value= "hoob"}))),
- ?match(false, eval(T24, any:create(notify_test_K:tc(),
- #notify_test_K{label= 2, value= "hoob"}))),
- ?match(false, eval(T23, any:create(notify_test_K:tc(),
- #notify_test_K{label= 0, value= "hoob"}))),
- ?match(true, eval(T24, any:create(notify_test_K:tc(),
- #notify_test_K{label= 0, value= "hoob"}))),
- ?match(false, eval(T23, any:create(notify_test_K:tc(),
- #notify_test_K{label= 5, value= 55}))),
- ?match(false, eval(T24, any:create(notify_test_K:tc(),
- #notify_test_K{label= 5, value= 55}))),
-
- ok.
-
-%%-----------------------------------------------------------------
-%% Variables grammar tests
-%%-----------------------------------------------------------------
-variable_api(_Config) ->
- %% Accept all "CommunicationsAlarm" events
- {ok,T0} = ?match({ok, _}, create_filter("$type_name == 'CommunicationsAlarm'")),
-
- ?match(true, eval(T0, ?not_CreateSE("DomainName","CommunicationsAlarm",
- "EventName",[],[],
- any:create(orber_tc:null(), null)))),
- ?match(false, eval(T0, ?not_CreateSE("DomainName","CommunicationsOK",
- "EventName", [],[],
- any:create(orber_tc:null(), null)))),
- ?match(true, eval(T0, ?not_CreateSE("DomainName","CommunicationsAlarm",
- "EventName", [],[],
- any:create(orber_tc:alias("IFRId", "type_name",
- orber_tc:string(0)),
- "CommunicationsOK")))),
-
- ?match(true, eval(T0, any:create(orber_tc:alias("IFRId", "type_name",
- orber_tc:string(0)),
- "CommunicationsAlarm"))),
- ?match(false, eval(T0, any:create(orber_tc:alias("IFRId", "type_name",
- orber_tc:string(0)),
- "CommunicationsOK"))),
-
-
- %% Accept all "CommunicationsAlarm" events but no "lost_packet" messages.
- {ok,T1} = ?match({ok, _}, create_filter("$type_name == 'CommunicationsAlarm' and not ($event_name == 'lost_packet')")),
-
- ?match(true, eval(T1, ?not_CreateSE("DomainName","CommunicationsAlarm",
- "EventName",[],[],
- any:create(orber_tc:null(), null)))),
- ?match(false, eval(T1, ?not_CreateSE("DomainName","CommunicationsAlarm",
- "lost_packet", [],[],
- any:create(orber_tc:null(), null)))),
- ?match(true,
- eval(T1, any:create(orber_tc:sequence('CosNotification_Property':tc(),0),
- [#'CosNotification_Property'{name="type_name",
- value=any:create(orber_tc:string(0), "CommunicationsAlarm")},
- #'CosNotification_Property'{name="event_name",
- value=any:create(orber_tc:string(0), "EventName")}]))),
- ?match(false,
- eval(T1, any:create(orber_tc:sequence('CosNotification_Property':tc(),0),
- [#'CosNotification_Property'{name="type_name",
- value=any:create(orber_tc:string(0), "CommunicationsAlarm")},
- #'CosNotification_Property'{name="event_name",
- value=any:create(orber_tc:string(0), "lost_packet")}]))),
-
-
- %% Accept "CommunicationsAlarm" events with priorities ranging from 1 to 5.
- {ok,T2} = ?match({ok, _}, create_filter("$type_name == 'CommunicationsAlarm' and $priority >= 1 and $priority <= 5")),
- ?match(true, eval(T2, ?not_CreateSE("DomainName","CommunicationsAlarm",
- "EventName",
- [#'CosNotification_Property'{name="priority",
- value=any:create(orber_tc:short(), 2)}],
- [], any:create(orber_tc:null(), null)))),
- ?match(false, eval(T2, ?not_CreateSE("DomainName","CommunicationsAlarm",
- "EventName",
- [#'CosNotification_Property'{name="priority",
- value=any:create(orber_tc:short(), 20)}],
- [], any:create(orber_tc:null(), null)))),
-
- %% Select "MOVIE" events featuring at least 3 of the Marx Brothers.
- {ok,T3} = ?match({ok, _}, create_filter("$type_name == 'MOVIE' and (('groucho' in $starlist) + ('chico' in $starlist) + ('harpo' in $starlist) + ('zeppo' in $starlist) + ('gummo' in $starlist)) > 2")),
- ?match(true, eval(T3, ?not_CreateSE("DomainName","MOVIE",
- "EventName",
- [#'CosNotification_Property'{name="starlist",
- value=any:create(orber_tc:sequence(orber_tc:string(0),0),
- ["groucho", "harpo", "sam", "gummo"])}],
- [], any:create(orber_tc:null(), null)))),
- ?match(false, eval(T3, ?not_CreateSE("DomainName","MOVIE",
- "EventName",
- [#'CosNotification_Property'{name="starlist",
- value=any:create(orber_tc:sequence(orber_tc:string(0),0),
- ["frodo", "bilbo", "sam", "gummo"])}],
- [], any:create(orber_tc:null(), null)))),
- %% Accept students that took all 3 tests and had an average score of at least 80%.
- {ok,T4} = ?match({ok, _}, create_filter("$test._length == 3 and ($test[0].score + $test[1].score + $test[2].score)/3 >=80")),
- ?match(true, eval(T4, ?not_CreateSE("DomainName","TypeName",
- "EventName", [],
- [#'CosNotification_Property'{name="test",
- value=any:create(orber_tc:array(notify_test_data:tc(),0),
- {#notify_test_data{score=75},
- #notify_test_data{score=80},
- #notify_test_data{score=85}})}],
- any:create(orber_tc:null(), null)))),
- ?match(false, eval(T4, ?not_CreateSE("DomainName","TypeName",
- "EventName", [],
- [#'CosNotification_Property'{name="test",
- value=any:create(orber_tc:array(notify_test_data:tc(),0),
- {#notify_test_data{score=75},
- #notify_test_data{score=80},
- #notify_test_data{score=80}})}],
- any:create(orber_tc:null(), null)))),
- ?match(false, eval(T4, ?not_CreateSE("DomainName","TypeName",
- "EventName", [],
- [#'CosNotification_Property'{name="test",
- value=any:create(orber_tc:array(notify_test_data:tc(),0),
- {#notify_test_data{score=75},
- #notify_test_data{score=85}})}],
- any:create(orber_tc:null(), null)))),
- %% Select processes that exceed a certain usage threshold.
- {ok,T5} = ?match({ok, _}, create_filter("$memsize / 5.5 + $cputime * 1275.0 + $filesize * 1.25 > 500000.0")),
- ?match(true, eval(T5, ?not_CreateSE("DomainName","TypeName",
- "EventName", [],
- [#'CosNotification_Property'{name="memsize",
- value=any:create(orber_tc:float(), 5.5)},
- #'CosNotification_Property'{name="cputime",
- value=any:create(orber_tc:float(), 0.00078431137)},
- #'CosNotification_Property'{name="filesize",
- value=any:create(orber_tc:float(), 500000)}],
- any:create(orber_tc:null(), null)))),
- ?match(false, eval(T5, ?not_CreateSE("DomainName","TypeName",
- "EventName", [],
- [#'CosNotification_Property'{name="memsize",
- value=any:create(orber_tc:float(), 5.5)},
- #'CosNotification_Property'{name="cputime",
- value=any:create(orber_tc:float(), 0.00078431137)},
- #'CosNotification_Property'{name="filesize",
- value=any:create(orber_tc:float(), 500)}],
- any:create(orber_tc:null(), null)))),
- ?match({error, _}, eval(T5, ?not_CreateSE("DomainName","TypeName",
- "EventName", [],
- [#'CosNotification_Property'{name="memsize",
- value=any:create(orber_tc:float(), 5.5)},
- #'CosNotification_Property'{name="filesize",
- value=any:create(orber_tc:float(), 500)}],
- any:create(orber_tc:null(), null)))),
-
- ?match(true, eval(T5, ?not_CreateSE("DomainName","TypeName",
- "EventName", [], [],
- any:create(orber_tc:sequence('CosNotification_Property':tc(),0),
- [#'CosNotification_Property'{name="memsize",
- value=any:create(orber_tc:float(), 5.5)},
- #'CosNotification_Property'{name="cputime",
- value=any:create(orber_tc:float(), 0.00078431137)},
- #'CosNotification_Property'{name="filesize",
- value=any:create(orber_tc:float(), 500000)}])))),
- ?match(false, eval(T5, ?not_CreateSE("DomainName","TypeName",
- "EventName", [], [],
- any:create(orber_tc:sequence('CosNotification_Property':tc(),0),
- [#'CosNotification_Property'{name="memsize",
- value=any:create(orber_tc:float(), 5.5)},
- #'CosNotification_Property'{name="cputime",
- value=any:create(orber_tc:float(), 0.00078431137)},
- #'CosNotification_Property'{name="filesize",
- value=any:create(orber_tc:float(), 500)}])))),
- ?match({error, _}, eval(T5, ?not_CreateSE("DomainName","TypeName",
- "EventName", [], [],
- any:create(orber_tc:sequence('CosNotification_Property':tc(),0),
- [#'CosNotification_Property'{name="memsize",
- value=any:create(orber_tc:float(), 5.5)},
- #'CosNotification_Property'{name="filesize",
- value=any:create(orber_tc:float(), 500)}])))),
-
- ?match(true, eval(T5, any:create(orber_tc:sequence('CosNotification_Property':tc(),0),
- [#'CosNotification_Property'{name="memsize",
- value=any:create(orber_tc:float(), 5.5)},
- #'CosNotification_Property'{name="cputime",
- value=any:create(orber_tc:float(), 0.00078431137)},
- #'CosNotification_Property'{name="filesize",
- value=any:create(orber_tc:float(), 500000)}]))),
- ?match(false, eval(T5, any:create(orber_tc:sequence('CosNotification_Property':tc(),0),
- [#'CosNotification_Property'{name="memsize",
- value=any:create(orber_tc:float(), 5.5)},
- #'CosNotification_Property'{name="cputime",
- value=any:create(orber_tc:float(), 0.00078431137)},
- #'CosNotification_Property'{name="filesize",
- value=any:create(orber_tc:float(), 500)}]))),
- ?match({error, _}, eval(T5, any:create(orber_tc:sequence('CosNotification_Property':tc(),0),
- [#'CosNotification_Property'{name="memsize",
- value=any:create(orber_tc:float(), 5.5)},
- #'CosNotification_Property'{name="filesize",
- value=any:create(orber_tc:float(), 500)}]))),
-
- %% Accept events where a threshold has the unscoped type name 'data'.
- {ok,T6} = ?match({ok, _}, create_filter("exist $threshold._type_id and $threshold._type_id == 'data'")),
- ?match(true, eval(T6, any:create(orber_tc:alias(notify_test_data:id(),
- "threshold",
- notify_test_data:tc()),
- #notify_test_data{score = 10, name = "Erlang"}))),
-
-
-
- ?match(true, eval(T6, ?not_CreateSE("DomainName","TypeName",
- "EventName", [],
- [#'CosNotification_Property'
- {name="threshold",
- value=any:create(notify_test_data:tc(),
- #notify_test_data
- {score = 10,
- name = "Erlang"})}],
- any:create(orber_tc:null(), null)))),
-
-
- ?match(true, eval(T6, ?not_CreateSE("DomainName","TypeName",
- "EventName", [],
- [#'CosNotification_Property'
- {name="NotThreshold",
- value=any:create(notify_test_data:tc(),
- #notify_test_data
- {score = 10,
- name = "Erlang"})}],
- any:create(orber_tc:alias(notify_test_data:id(),
- "threshold",
- notify_test_data:tc()),
- #notify_test_data{score = 10, name = "Erlang"})))),
-
-
-
- %% Accept events with a serviceUser property of the correct standard type.
- {ok,T7} = ?match({ok, _}, create_filter("$violation(TestData)._repos_id == 'IDL:notify_test/data:1.0'")),
- ?match(true, eval(T7, ?not_CreateSE("DomainName","TypeName",
- "EventName", [],
- [#'CosNotification_Property'
- {name="violation",
- value=any:create(orber_tc:array('CosNotification_Property':tc(),0),
- [#'CosNotification_Property'
- {name="TestData",
- value=any:create(notify_test_data:tc(),
- #notify_test_data
- {score=100,
- name="perfect score"})}])}],
- any:create(orber_tc:null(), null)))),
-
- {ok,T8} = ?match({ok, _}, create_filter("$type_name == 'CommunicationsAlarm' and $event_name == 'lost_packet' and $priority < 2")),
- %% All correct
- Event1 = ?not_CreateSE("DomainName","CommunicationsAlarm",
- "lost_packet",
- [#'CosNotification_Property'{name="priority",
- value=any:create(orber_tc:short(), 1)}],
- [], any:create(orber_tc:null(), null)),
- %% Priority to high
- Event2 = ?not_CreateSE("DomainName","CommunicationsAlarm",
- "lost_packet",
- [#'CosNotification_Property'{name="priority",
- value=any:create(orber_tc:short(), 2)}],
- [], any:create(orber_tc:null(), null)),
- %% Misspell event_name, i.e., lost_packets instead of lost_packet
- Event3 = ?not_CreateSE("DomainName","CommunicationsAlarm",
- "lost_packets",
- [#'CosNotification_Property'{name="priority",
- value=any:create(orber_tc:short(), 1)}],
- [], any:create(orber_tc:null(), null)),
- %% Another type_name
- Event4 = ?not_CreateSE("DomainName","TemperatureAlarm",
- "lost_packets",
- [#'CosNotification_Property'{name="priority",
- value=any:create(orber_tc:short(), 1)}],
- [], any:create(orber_tc:null(), null)),
-
- ?match(true, eval(T8, Event1)),
- ?match(false, eval(T8, Event2)),
- ?match(false, eval(T8, Event3)),
- ?match(false, eval(T8, Event4)),
-
- {ok,T9} = ?match({ok, _}, create_filter("$gpa < 80 or $tests(midterm) > $tests(final) or $monthly_attendance[3] < 10")),
-
- %% midterm > final yields true, the others false
- Event5 = ?not_CreateSE("DomainName","TypeName",
- "EventName", [],
- [#'CosNotification_Property'
- {name="tests",
- value=any:create(orber_tc:array('CosNotification_Property':tc(),0),
- [#'CosNotification_Property'{name="midterm",
- value=any:create(orber_tc:short(), 70)},
- #'CosNotification_Property'{name="final",
- value=any:create(orber_tc:short(), 60)}])},
- #'CosNotification_Property'{name="monthly_attendance",
- value=any:create(orber_tc:array(orber_tc:short(), 0),
- {0,1,2,10})},
- #'CosNotification_Property'{name="gpa",
- value=any:create(orber_tc:short(), 90)}],
- any:create(orber_tc:null(), null)),
-
- %% monthly_attendance[3] < 10 yields true, the others false
- Event6 = ?not_CreateSE("DomainName","TypeName",
- "EventName", [],
- [#'CosNotification_Property'{name="tests",
- value=any:create(orber_tc:array('CosNotification_Property':tc(),0),
- [#'CosNotification_Property'{name="midterm",
- value=any:create(orber_tc:short(), 70)},
- #'CosNotification_Property'{name="final",
- value=any:create(orber_tc:short(), 80)}])},
- #'CosNotification_Property'{name="monthly_attendance",
- value=any:create(orber_tc:array(orber_tc:short(), 0),
- {0,1,2,9})},
- #'CosNotification_Property'{name="gpa",
- value=any:create(orber_tc:short(), 90)}],
- any:create(orber_tc:null(), null)),
-
- %% gpa < 80 true, rest false.
- Event7 = ?not_CreateSE("DomainName","TypeName",
- "EventName", [],
- [#'CosNotification_Property'{name="tests",
- value=any:create(orber_tc:array('CosNotification_Property':tc(),0),
- [#'CosNotification_Property'{name="midterm",
- value=any:create(orber_tc:short(), 70)},
- #'CosNotification_Property'{name="final",
- value=any:create(orber_tc:short(), 80)}])},
- #'CosNotification_Property'{name="monthly_attendance",
- value=any:create(orber_tc:array(orber_tc:short(), 0),
- {0,1,2,10})},
- #'CosNotification_Property'{name="gpa",
- value=any:create(orber_tc:short(), 70)}],
- any:create(orber_tc:null(), null)),
-
- %% All false
- Event8 = ?not_CreateSE("DomainName","TypeName",
- "EventName", [],
- [#'CosNotification_Property'{name="tests",
- value=any:create(orber_tc:array('CosNotification_Property':tc(),0),
- [#'CosNotification_Property'{name="midterm",
- value=any:create(orber_tc:short(), 70)},
- #'CosNotification_Property'{name="final",
- value=any:create(orber_tc:short(), 80)}])},
- #'CosNotification_Property'{name="monthly_attendance",
- value=any:create(orber_tc:array(orber_tc:short(), 0),
- {0,1,2,10})},
- #'CosNotification_Property'{name="gpa",
- value=any:create(orber_tc:short(), 80)}],
- any:create(orber_tc:null(), null)),
-
- ?match(true, eval(T9, Event5)),
- ?match(true, eval(T9, Event6)),
- ?match(true, eval(T9, Event7)),
- ?match(false, eval(T9, Event8)),
- ok.
-
-%%-----------------------------------------------------------------
-%% Misc grammar tests
-%%-----------------------------------------------------------------
-positional_api(_Config) ->
- {ok,T1} = ?match({ok, _}, create_filter("$.3 < 80 or $.1(midterm) > $.1(final) or $.2[3] < 10")),
-
- %% midterm > final yields true, the others false
- Event1 = any:create(notify_test_studies:tc(), #notify_test_studies
- {gpa = 90,
- tests = [#'CosNotification_Property'
- {name="midterm", value=any:create(orber_tc:short(), 70)},
- #'CosNotification_Property'
- {name="final", value=any:create(orber_tc:short(), 60)}],
- monthly_attendance = {0,1,2,10}}),
- %% monthly_attendance[3] < 10 yields true, the others false
- Event2 = any:create(notify_test_studies:tc(), #notify_test_studies
- {gpa = 90,
- tests = [#'CosNotification_Property'
- {name="midterm", value=any:create(orber_tc:short(), 70)},
- #'CosNotification_Property'
- {name="final", value=any:create(orber_tc:short(), 80)}],
- monthly_attendance = {0,1,2,9}}),
- %% gpa < 80 true, rest false.
- Event3 = any:create(notify_test_studies:tc(), #notify_test_studies
- {gpa = 70,
- tests = [#'CosNotification_Property'
- {name="midterm", value=any:create(orber_tc:short(), 70)},
- #'CosNotification_Property'
- {name="final", value=any:create(orber_tc:short(), 80)}],
- monthly_attendance = {0,1,2,10}}),
- %% All false
- Event4 = any:create(notify_test_studies:tc(), #notify_test_studies
- {gpa = 80,
- tests = [#'CosNotification_Property'
- {name="midterm", value=any:create(orber_tc:short(), 70)},
- #'CosNotification_Property'
- {name="final", value=any:create(orber_tc:short(), 80)}],
- monthly_attendance = {0,1,2,10}}),
-
- ?match(true, eval(T1, Event1)),
- ?match(true, eval(T1, Event2)),
- ?match(true, eval(T1, Event3)),
- ?match(false, eval(T1, Event4)),
-
- {ok,T2} = ?match({ok, _}, create_filter("$.0.0.0.1 == 'CommunicationsAlarm'")),
-
- Event5 = ?not_CreateSE("DomainName","CommunicationsAlarm",
- "lost_packet", [], [],
- any:create(orber_tc:null(), null)),
-
- ?match(true, eval(T2, Event5)),
-
- ok.
-
-%%-----------------------------------------------------------------
-%% Components grammar tests
-%%-----------------------------------------------------------------
-components_api(_Config) ->
- {ok,T1} = ?match({ok, _}, create_filter("$ == 2")),
- ?match(true, eval(T1, ?not_CreateSE("DomainName","TypeName","EventName",
- [],[], any:create(orber_tc:short(), 2)))),
- ?match(true, eval(T1, any:create(orber_tc:short(), 2))),
- ?match(false, eval(T1, ?not_CreateSE("DomainName","TypeName","EventName",
- [],[], any:create(orber_tc:short(), 3)))),
- ?match(false, eval(T1, any:create(orber_tc:short(), 3))),
-
- %% Select "MOVIE" events featuring at least 3 of the Marx Brothers.
- {ok,T2} = ?match({ok, _}, create_filter("$type_name == 'MOVIE' and (('groucho' in $.starlist) + ('chico' in $.starlist) + ('harpo' in $.starlist) + ('zeppo' in $.starlist) + ('gummo' in $.starlist)) > 2")),
- ?match(true, eval(T2, ?not_CreateSE("DomainName","MOVIE", "EventName", [], [],
- any:create(orber_tc:alias("IFRId","starlist",tk_any),
- any:create(orber_tc:sequence(orber_tc:string(0),0),
- ["groucho", "harpo", "sam", "gummo"]))))),
- ?match(false, eval(T2, ?not_CreateSE("DomainName","MOVIE", "EventName", [], [],
- any:create(orber_tc:alias("IFRId","starlist",tk_any),
- any:create(orber_tc:sequence(orber_tc:string(0),0),
- ["frodo", "bilbo", "sam", "gummo"]))))),
-
- %% Accept only recent events (e.g., generated within the last 15 minutes or so).
- {ok,_T3} = ?match({ok, _}, create_filter("$origination_timestamp.high + 2 < $curtime.high")),
-
-
- %% Accept students that took all 3 tests and had an average score of at least 80%.
- {ok,T4} = ?match({ok, _}, create_filter("$.test._length == 3 and ($.test[0].score + $.test[1].score + $.test[2].score)/3 >=80")),
- ?match(true, eval(T4, ?not_CreateSE("DomainName","TypeName", "EventName", [], [],
- any:create(orber_tc:alias("IFRId","test",tk_any),
- any:create(orber_tc:array(notify_test_data:tc(),0),
- {#notify_test_data{score=75},
- #notify_test_data{score=80},
- #notify_test_data{score=85}}))))),
- ?match(false, eval(T4, ?not_CreateSE("DomainName","TypeName", "EventName", [], [],
- any:create(orber_tc:alias("IFRId","test",tk_any),
- any:create(orber_tc:array(notify_test_data:tc(),0),
- {#notify_test_data{score=75},
- #notify_test_data{score=80},
- #notify_test_data{score=80}}))))),
- ?match(false, eval(T4, ?not_CreateSE("DomainName","TypeName", "EventName", [], [],
- any:create(orber_tc:alias("IFRId","test",tk_any),
- any:create(orber_tc:array(notify_test_data:tc(),0),
- {#notify_test_data{score=75},
- #notify_test_data{score=80}}))))),
-
- %% Select processes that exceed a certain usage threshold.
- {ok,T5} = ?match({ok, _}, create_filter("$.memsize / 5.5 + $.cputime * 1275.0 + $.filesize * 1.25 > 500000.0")),
- ?match(true, eval(T5, ?not_CreateSE("DomainName","TypeName", "EventName", [], [],
- any:create(notify_test_computer:tc(),
- #notify_test_computer
- {memsize=5.5,
- cputime = 0.00078431137,
- filesize = 500000})))),
- ?match(false, eval(T5, ?not_CreateSE("DomainName","TypeName", "EventName", [], [],
- any:create(notify_test_computer:tc(),
- #notify_test_computer
- {memsize=5.5,
- cputime = 0.00078431137,
- filesize = 500})))),
- ?match({error,_}, eval(T5, ?not_CreateSE("DomainName","TypeName", "EventName", [], [],
- any:create(notify_test_computer:tc(),
- #notify_test_computer
- {memsize=5.5,
- cputime = 0.00078431137})))),
-
- %% Accept only Notification Service structured events.
- {ok,T6} = ?match({ok, _}, create_filter("$._repos_id == 'IDL:omg.org/CosNotification/StructuredEvent:1.0'")),
- ?match(true, eval(T6, ?not_CreateSE("DomainName","CommunicationsAlarm",
- "EventName",
- [], [], any:create(orber_tc:null(), null)))),
-
-
-
- %% Accept only those events that have a specified security "rights list".
- {ok,T7} = ?match({ok, _}, create_filter("exist $.header.variable_header(required_rights)")),
- ?match(false, eval(T7, ?not_CreateSE("DomainName","CommunicationsAlarm",
- "lost_packet",
- [#'CosNotification_Property'{name="priority",
- value=any:create(orber_tc:short(), 1)}],
- [], any:create(orber_tc:null(), null)))),
- ?match(true, eval(T7, ?not_CreateSE("DomainName","CommunicationsAlarm",
- "lost_packet",
- [#'CosNotification_Property'{name="required_rights",
- value=any:create(orber_tc:short(), 1)}],
- [], any:create(orber_tc:null(), null)))),
-
-
- {ok,T8} = ?match({ok, _}, create_filter("$.header.fixed_header.event_type.type_name == 'CommunicationsAlarm' and $.header.fixed_header.event_name == 'lost_packet' and $.header.variable_header(priority) < 2")),
- %% All correct
- Event1 = ?not_CreateSE("DomainName","CommunicationsAlarm",
- "lost_packet",
- [#'CosNotification_Property'{name="priority",
- value=any:create(orber_tc:short(), 1)}],
- [], any:create(orber_tc:null(), null)),
- %% Priority to high
- Event2 = ?not_CreateSE("DomainName","CommunicationsAlarm",
- "lost_packet",
- [#'CosNotification_Property'{name="priority",
- value=any:create(orber_tc:short(), 2)}],
- [], any:create(orber_tc:null(), null)),
- %% Misspell event_name, i.e., lost_packets instead of lost_packet
- Event3 = ?not_CreateSE("DomainName","CommunicationsAlarm",
- "lost_packets",
- [#'CosNotification_Property'{name="priority",
- value=any:create(orber_tc:short(), 1)}],
- [], any:create(orber_tc:null(), null)),
- %% Another type_name
- Event4 = ?not_CreateSE("DomainName","TemperatureAlarm",
- "lost_packets",
- [#'CosNotification_Property'{name="priority",
- value=any:create(orber_tc:short(), 1)}],
- [], any:create(orber_tc:null(), null)),
-
- ?match(true, eval(T8, Event1)),
- ?match(false, eval(T8, Event2)),
- ?match(false, eval(T8, Event3)),
- ?match(false, eval(T8, Event4)),
-
-
- {ok,T9} = ?match({ok, _}, create_filter("$.gpa < 80 or $.tests(midterm) > $.tests(final) or $.monthly_attendance[3] < 10")),
-
- %% midterm > final yields true, the others false
- Event5 = ?not_CreateSE("DomainName","TypeName",
- "EventName", [], [],
- any:create(notify_test_studies:tc(), #notify_test_studies
- {gpa = 90,
- tests = [#'CosNotification_Property'
- {name="midterm", value=any:create(orber_tc:short(), 70)},
- #'CosNotification_Property'
- {name="final", value=any:create(orber_tc:short(), 60)}],
- monthly_attendance = {0,1,2,10}})),
- %% monthly_attendance[3] < 10 yields true, the others false
- Event6 = ?not_CreateSE("DomainName","TypeName",
- "EventName", [], [],
- any:create(notify_test_studies:tc(), #notify_test_studies
- {gpa = 90,
- tests = [#'CosNotification_Property'
- {name="midterm", value=any:create(orber_tc:short(), 70)},
- #'CosNotification_Property'
- {name="final", value=any:create(orber_tc:short(), 80)}],
- monthly_attendance = {0,1,2,9}})),
- %% gpa < 80 true, rest false.
- Event7 = ?not_CreateSE("DomainName","TypeName",
- "EventName", [], [],
- any:create(notify_test_studies:tc(), #notify_test_studies
- {gpa = 70,
- tests = [#'CosNotification_Property'
- {name="midterm", value=any:create(orber_tc:short(), 70)},
- #'CosNotification_Property'
- {name="final", value=any:create(orber_tc:short(), 80)}],
- monthly_attendance = {0,1,2,10}})),
- %% All false
- Event8 = ?not_CreateSE("DomainName","TypeName",
- "EventName", [], [],
- any:create(notify_test_studies:tc(), #notify_test_studies
- {gpa = 80,
- tests = [#'CosNotification_Property'
- {name="midterm", value=any:create(orber_tc:short(), 70)},
- #'CosNotification_Property'
- {name="final", value=any:create(orber_tc:short(), 80)}],
- monthly_attendance = {0,1,2,10}})),
-
- ?match(true, eval(T9, Event5)),
- ?match(true, eval(T9, Event6)),
- ?match(true, eval(T9, Event7)),
- ?match(false, eval(T9, Event8)),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-
-%%-------------------- End of Module ------------------------------
diff --git a/lib/cosNotification/test/notification_SUITE.erl b/lib/cosNotification/test/notification_SUITE.erl
deleted file mode 100644
index 624a76c64a..0000000000
--- a/lib/cosNotification/test/notification_SUITE.erl
+++ /dev/null
@@ -1,2163 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%--------------------------------------------------------------------
-%% File : notification_SUITE.erl
-%% Purpose :
-%%--------------------------------------------------------------------
-
--module(notification_SUITE).
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-%% cosEvent files.
--include_lib("cosEvent/include/CosEventChannelAdmin.hrl").
-%% Application files
--include_lib("cosNotification/include/CosNotification.hrl").
--include_lib("cosNotification/include/CosNotifyChannelAdmin.hrl").
--include_lib("cosNotification/include/CosNotifyComm.hrl").
--include_lib("cosNotification/include/CosNotifyFilter.hrl").
-
--include_lib("cosNotification/src/CosNotification_Definitions.hrl").
-
--include("idl_output/notify_test.hrl").
-
--include_lib("common_test/include/ct.hrl").
-
-%%--------------- DEFINES ------------------------------------
--define(default_timeout, test_server:minutes(20)).
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
--define(defaultQoS,
- [#'CosNotification_Property'{name='CosNotification':'MaximumBatchSize'(),
- value=any:create(orber_tc:long(), 100)},
- #'CosNotification_Property'{name='CosNotification':'PacingInterval'(),
- value=any:create(orber_tc:unsigned_long_long(),
- 20000000)},
- #'CosNotification_Property'{name='CosNotification':'OrderPolicy'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'AnyOrder'())},
- #'CosNotification_Property'{name='CosNotification':'EventReliability'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'BestEffort'())},
- #'CosNotification_Property'{name='CosNotification':'ConnectionReliability'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'BestEffort'())},
- #'CosNotification_Property'{name='CosNotification':'DiscardPolicy'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'AnyOrder'())},
- #'CosNotification_Property'{name='CosNotification':'StartTimeSupported'(),
- value=any:create(orber_tc:boolean(), false)},
- #'CosNotification_Property'{name='CosNotification':'StopTimeSupported'(),
- value=any:create(orber_tc:boolean(), false)},
- #'CosNotification_Property'{name='CosNotification':'Priority'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'DefaultPriority'())}]).
--define(defaultQoS2,
- [#'CosNotification_Property'{name='CosNotification':'MaximumBatchSize'(),
- value=any:create(orber_tc:long(), 1)},
- #'CosNotification_Property'{name='CosNotification':'PacingInterval'(),
- value=any:create(orber_tc:unsigned_long_long(),
- 0)},
- #'CosNotification_Property'{name='CosNotification':'OrderPolicy'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'AnyOrder'())},
- #'CosNotification_Property'{name='CosNotification':'EventReliability'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'BestEffort'())},
- #'CosNotification_Property'{name='CosNotification':'ConnectionReliability'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'BestEffort'())},
- #'CosNotification_Property'{name='CosNotification':'DiscardPolicy'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'AnyOrder'())},
- #'CosNotification_Property'{name='CosNotification':'StartTimeSupported'(),
- value=any:create(orber_tc:boolean(), false)},
- #'CosNotification_Property'{name='CosNotification':'StopTimeSupported'(),
- value=any:create(orber_tc:boolean(), false)},
- #'CosNotification_Property'{name='CosNotification':'Priority'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'DefaultPriority'())}]).
--define(defaultAdm,
- [#'CosNotification_Property'{name='CosNotification':'MaxQueueLength'(),
- value=any:create(orber_tc:long(), 100)},
- #'CosNotification_Property'{name='CosNotification':'MaxConsumers'(),
- value=any:create(orber_tc:long(), 100)},
- #'CosNotification_Property'{name='CosNotification':'MaxSuppliers'(),
- value=any:create(orber_tc:long(), 100)}]).
-
--define(FAC_OPT, []).
-
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, cases/0,
- init_per_suite/1, end_per_suite/1, qos_api/1, adm_api/1,
- cosevent_api/1, filter_adm_api/1, events_api/1, events2_api/1,
- event_qos_api/1, filter_api/1, mapping_filter_api/1, subscription_api/1,
- init_per_testcase/2, end_per_testcase/2, persistent_max_events_api/1,
- persistent_timeout_events_api/1, persistent_recover_events_api/1,
- app_test/1]).
-
--export([terminated/1]).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-cases() ->
- [persistent_max_events_api,
- persistent_timeout_events_api,
- persistent_recover_events_api, mapping_filter_api,
- filter_api, filter_adm_api, event_qos_api, qos_api,
- adm_api, cosevent_api, subscription_api, events_api,
- events2_api, app_test].
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- ok = corba:orb_init([{flags, 16#02}, {orber_debug_level, 10}]),
- orber:jump_start(),
- cosNotificationApp:install_event(),
- cosNotificationApp:install(),
- 'oe_notify_test_server':'oe_register'(),
- cosNotificationApp:start(),
- if
- is_list(Config) ->
- Config;
- true ->
- exit("Config not a list")
- end.
-
-end_per_suite(Config) ->
- cosNotificationApp:stop(),
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- 'oe_notify_test_server':'oe_unregister'(),
- cosNotificationApp:uninstall(),
- cosNotificationApp:uninstall_event(),
- orber:jump_stop(),
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Tests app file
-%%-----------------------------------------------------------------
-app_test(_Config) ->
- ok=test_server:app_test(cosNotification),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Persistent events max limit
-%%-----------------------------------------------------------------
-persistent_max_events_api(_Config) ->
- QoSPersistent =
- [#'CosNotification_Property'{name='CosNotification':'ConnectionReliability'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'Persistent'())}],
- QoSEventPersistent =
- [#'CosNotification_Property'{name='CosNotification':'EventReliability'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'Persistent'())}],
- application:set_env(cosNotification, notify, ?MODULE),
- application:set_env(cosNotification, max_events, 2),
- application:set_env(cosNotification, timeout_events, 300000),
- application:set_env(cosNotification, interval_events, 10000),
- %% Initialize the application.
- Fac = (catch cosNotificationApp:start_global_factory(?FAC_OPT)),
- ?match({_,key,_,_,_,_}, Fac),
- {Ch, _Id1} = (catch 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(Fac, ?defaultQoS2, ?defaultAdm)),
- ?match({_,key,_,_,_,_}, Ch),
-
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(Ch, QoSEventPersistent)),
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(Ch, QoSPersistent)),
-
- %% Create the Admin objects
- {AdminSupplier, _ASID}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_EventChannel':new_for_suppliers(Ch,'AND_OP')),
- {AdminConsumer, _ACID}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_EventChannel':new_for_consumers(Ch,'AND_OP')),
-
- %% Create Proxies and clients
- {SequenceProxyPushSupplier,_ID}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_ConsumerAdmin':obtain_notification_push_supplier(AdminConsumer, 'SEQUENCE_EVENT')),
- PushSeqC=?match({_,key,_,_,_,_}, 'notify_test_SeqPushC':oe_create(['PUSH_SEQUENCE',SequenceProxyPushSupplier],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':connect_sequence_push_consumer(SequenceProxyPushSupplier, PushSeqC)),
-
- {SequenceProxyPushConsumer,_ID}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_SupplierAdmin':obtain_notification_push_consumer(AdminSupplier, 'SEQUENCE_EVENT')),
- PushSeqS=?match({_,key,_,_,_,_}, 'notify_test_SeqPushS':oe_create(['PUSH_SEQUENCE',SequenceProxyPushConsumer],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':connect_sequence_push_supplier(SequenceProxyPushConsumer, PushSeqS)),
-
- %% Create a couple of Events to test with.
- Event = ?not_CreateSE("DomainName","CommunicationsAlarm",
- "lost_packet",
- [#'CosNotification_Property'{name="priority",
- value=any:create(orber_tc:short(), 1)}],
- [], any:create(orber_tc:null(), null)),
-
- ?match(ok, 'notify_test_SeqPushC':doAction(PushSeqC, {action, action})),
-
- %% Push and check the state.
- ?match(ok,'CosNotifyChannelAdmin_SequenceProxyPushConsumer':push_structured_events(SequenceProxyPushConsumer, [Event])),
- ?match([], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
- ?match(false, corba_object:non_existent(SequenceProxyPushSupplier)),
-
- ?match(ok,'CosNotifyChannelAdmin_SequenceProxyPushConsumer':push_structured_events(SequenceProxyPushConsumer, [Event])),
- ?match([], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
- ?match(false, corba_object:non_existent(SequenceProxyPushSupplier)),
- %% Now we've reached the limit. This call will terminate the proxy.
- %% We cannot check for data at this point since the broken connection
- %% will result in that the client terminates.
- ?match(ok,'CosNotifyChannelAdmin_SequenceProxyPushConsumer':push_structured_events(SequenceProxyPushConsumer, [Event])),
- timer:sleep(5000),
- ?match(true, corba_object:non_existent(SequenceProxyPushSupplier)),
- ?match(true, corba_object:non_existent(PushSeqC)),
-
-
- catch corba:dispose(SequenceProxyPushConsumer),
- catch corba:dispose(SequenceProxyPushSupplier),
- catch corba:dispose(AdminConsumer),
- catch corba:dispose(AdminSupplier),
- catch corba:dispose(Ch),
- catch cosNotificationApp:stop_factory(Fac),
- catch corba:dispose(PushSeqS),
- catch corba:dispose(PushSeqC),
- application:set_env(cosNotification, notify, undefined),
- application:set_env(cosNotification, max_events, undefined),
- application:set_env(cosNotification, timeout_events, undefined),
- application:set_env(cosNotification, interval_events, undefined),
- ok.
-
-terminated(Items) ->
- io:format("Proxy terminated due to: ~p~n", [Items]).
-
-%%-----------------------------------------------------------------
-%% Persistent events timeout
-%%-----------------------------------------------------------------
-persistent_timeout_events_api(_Config) ->
- QoSPersistent =
- [#'CosNotification_Property'{name='CosNotification':'ConnectionReliability'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'Persistent'())}],
- QoSEventPersistent =
- [#'CosNotification_Property'{name='CosNotification':'EventReliability'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'Persistent'())}],
- application:set_env(cosNotification, notify, ?MODULE),
- application:set_env(cosNotification, max_events, 1000),
- application:set_env(cosNotification, timeout_events, 4000),
- application:set_env(cosNotification, interval_events, 1000),
- %% Initialize the application.
- Fac = (catch cosNotificationApp:start_global_factory(?FAC_OPT)),
- ?match({_,key,_,_,_,_}, Fac),
- {Ch, _Id1} = (catch 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(Fac, ?defaultQoS2, ?defaultAdm)),
- ?match({_,key,_,_,_,_}, Ch),
-
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(Ch, QoSEventPersistent)),
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(Ch, QoSPersistent)),
-
- %% Create the Admin objects
- {AdminSupplier, _ASID}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_EventChannel':new_for_suppliers(Ch,'AND_OP')),
- {AdminConsumer, _ACID}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_EventChannel':new_for_consumers(Ch,'AND_OP')),
-
- %% Create Proxies and clients
- {SequenceProxyPushSupplier,_ID}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_ConsumerAdmin':obtain_notification_push_supplier(AdminConsumer, 'SEQUENCE_EVENT')),
- PushSeqC=?match({_,key,_,_,_,_}, 'notify_test_SeqPushC':oe_create(['PUSH_SEQUENCE',SequenceProxyPushSupplier],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':connect_sequence_push_consumer(SequenceProxyPushSupplier, PushSeqC)),
-
- {SequenceProxyPushConsumer,_ID}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_SupplierAdmin':obtain_notification_push_consumer(AdminSupplier, 'SEQUENCE_EVENT')),
- PushSeqS=?match({_,key,_,_,_,_}, 'notify_test_SeqPushS':oe_create(['PUSH_SEQUENCE',SequenceProxyPushConsumer],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':connect_sequence_push_supplier(SequenceProxyPushConsumer, PushSeqS)),
-
- %% Create a couple of Events to test with.
- Event = ?not_CreateSE("DomainName","CommunicationsAlarm",
- "lost_packet",
- [#'CosNotification_Property'{name="priority",
- value=any:create(orber_tc:short(), 1)}],
- [], any:create(orber_tc:null(), null)),
-
- ?match(ok, 'notify_test_SeqPushC':doAction(PushSeqC, {action, action})),
-
- %% Push and check the state.
- ?match(ok,'CosNotifyChannelAdmin_SequenceProxyPushConsumer':push_structured_events(SequenceProxyPushConsumer, [Event])),
- ?match([], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
- ?match(false, corba_object:non_existent(SequenceProxyPushSupplier)),
-
- %% Now we've reached the limit. This call will terminate the proxy.
- %% We cannot check for data at this point since the broken connection
- %% will result in that the client terminates.
- ?match(ok,'CosNotifyChannelAdmin_SequenceProxyPushConsumer':push_structured_events(SequenceProxyPushConsumer, [Event])),
- timer:sleep(10000),
- ?match(true, corba_object:non_existent(SequenceProxyPushSupplier)),
- ?match(true, corba_object:non_existent(PushSeqC)),
-
-
- catch corba:dispose(SequenceProxyPushConsumer),
- catch corba:dispose(SequenceProxyPushSupplier),
- catch corba:dispose(AdminConsumer),
- catch corba:dispose(AdminSupplier),
- catch corba:dispose(Ch),
- catch cosNotificationApp:stop_factory(Fac),
- catch corba:dispose(PushSeqS),
- catch corba:dispose(PushSeqC),
- application:set_env(cosNotification, notify, undefined),
- application:set_env(cosNotification, max_events, undefined),
- application:set_env(cosNotification, timeout_events, undefined),
- application:set_env(cosNotification, interval_events, undefined),
- ok.
-
-%%-----------------------------------------------------------------
-%% Persistent events max limit
-%%-----------------------------------------------------------------
-persistent_recover_events_api(_Config) ->
- QoSPersistent =
- [#'CosNotification_Property'{name='CosNotification':'ConnectionReliability'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'Persistent'())}],
- QoSEventPersistent =
- [#'CosNotification_Property'{name='CosNotification':'EventReliability'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'Persistent'())}],
- application:set_env(cosNotification, notify, ?MODULE),
- application:set_env(cosNotification, max_events, 1000),
- application:set_env(cosNotification, timeout_events, 100000),
- application:set_env(cosNotification, interval_events, 1000),
- %% Initialize the application.
- Fac = (catch cosNotificationApp:start_global_factory(?FAC_OPT)),
- ?match({_,key,_,_,_,_}, Fac),
- {Ch, _Id1} = (catch 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(Fac, ?defaultQoS2, ?defaultAdm)),
- ?match({_,key,_,_,_,_}, Ch),
-
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(Ch, QoSEventPersistent)),
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(Ch, QoSPersistent)),
-
- %% Create the Admin objects
- {AdminSupplier, _ASID}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_EventChannel':new_for_suppliers(Ch,'AND_OP')),
- {AdminConsumer, _ACID}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_EventChannel':new_for_consumers(Ch,'AND_OP')),
-
- %% Create Proxies and clients
- {SequenceProxyPushSupplier,_ID}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_ConsumerAdmin':obtain_notification_push_supplier(AdminConsumer, 'SEQUENCE_EVENT')),
- PushSeqC=?match({_,key,_,_,_,_}, 'notify_test_SeqPushC':oe_create(['PUSH_SEQUENCE',SequenceProxyPushSupplier],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':connect_sequence_push_consumer(SequenceProxyPushSupplier, PushSeqC)),
-
- {SequenceProxyPushConsumer,_ID}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_SupplierAdmin':obtain_notification_push_consumer(AdminSupplier, 'SEQUENCE_EVENT')),
- PushSeqS=?match({_,key,_,_,_,_}, 'notify_test_SeqPushS':oe_create(['PUSH_SEQUENCE',SequenceProxyPushConsumer],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':connect_sequence_push_supplier(SequenceProxyPushConsumer, PushSeqS)),
-
- %% Create a couple of Events to test with.
- Event = ?not_CreateSE("DomainName","CommunicationsAlarm",
- "lost_packet",
- [#'CosNotification_Property'{name="priority",
- value=any:create(orber_tc:short(), 1)}],
- [], any:create(orber_tc:null(), null)),
-
- ?match(ok, 'notify_test_SeqPushC':doAction(PushSeqC, {action, action})),
-
- %% Push and check the state.
- ?match(ok,'CosNotifyChannelAdmin_SequenceProxyPushConsumer':push_structured_events(SequenceProxyPushConsumer, [Event])),
- ?match([], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
- ?match(false, corba_object:non_existent(SequenceProxyPushSupplier)),
- %% Allow the proxy to try a few times and then change the client behavior
- timer:sleep(4000),
- ?match(ok, 'notify_test_SeqPushC':doAction(PushSeqC, {action, undefined})),
- %% Wait some time so that the proxy timeout has kicked in.
- timer:sleep(4000),
-
- %% Now the communication should work again.
- ?match([Event], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
- ?match(false, corba_object:non_existent(SequenceProxyPushSupplier)),
-
- ?match(ok,'CosNotifyChannelAdmin_SequenceProxyPushConsumer':push_structured_events(SequenceProxyPushConsumer, [Event])),
- timer:sleep(4000),
- ?match([Event], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
-
- catch corba:dispose(SequenceProxyPushConsumer),
- catch corba:dispose(SequenceProxyPushSupplier),
- catch corba:dispose(AdminConsumer),
- catch corba:dispose(AdminSupplier),
- catch corba:dispose(Ch),
- catch cosNotificationApp:stop_factory(Fac),
- catch corba:dispose(PushSeqS),
- catch corba:dispose(PushSeqC),
- application:set_env(cosNotification, notify, undefined),
- application:set_env(cosNotification, max_events, undefined),
- application:set_env(cosNotification, timeout_events, undefined),
- application:set_env(cosNotification, interval_events, undefined),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% CosNotifyFilter::Filter API tests
-%%-----------------------------------------------------------------
-mapping_filter_api(_Config) ->
- FiFac = 'CosNotifyFilter_FilterFactory':oe_create(),
- ?match({_,key,_,_,_,_}, FiFac),
-
- Filter = 'CosNotifyFilter_FilterFactory':create_mapping_filter(FiFac,
- "EXTENDED_TCL",
- any:create(orber_tc:short(), 10)),
- ?match({_,key,_,_,_,_}, Filter),
-
- ?match("EXTENDED_TCL", 'CosNotifyFilter_MappingFilter':'_get_constraint_grammar'(Filter)),
-
- %% Test before we add any constarints.
- ?match([], 'CosNotifyFilter_MappingFilter':get_all_mapping_constraints(Filter)),
- ?match({'EXCEPTION', {'CosNotifyFilter_ConstraintNotFound', _, 1}},
- 'CosNotifyFilter_MappingFilter':get_mapping_constraints(Filter, [1])),
- ?match(ok, 'CosNotifyFilter_MappingFilter':remove_all_mapping_constraints(Filter)),
-
- %% Try adding an incorrect constraint_expr
- ?match({'EXCEPTION',{'CosNotifyFilter_InvalidConstraint',_,_}},
- 'CosNotifyFilter_MappingFilter':add_mapping_constraints(Filter,
- [#'CosNotifyFilter_MappingConstraintPair'
- {constraint_expression = #'CosNotifyFilter_ConstraintExp'
- {event_types = [#'CosNotification_EventType'
- {domain_name = "name",
- type_name = "type"}],
- constraint_expr = "2==2 and 3<"},
- result_to_set = any:create(orber_tc:short(), 10)}])),
- %% Try adding two correct constraint_expr
- [{_,_,CID1,_},{_,_,CID2,_}]=
- ?match([{'CosNotifyFilter_MappingConstraintInfo',_,_,_}, {'CosNotifyFilter_MappingConstraintInfo',_,_,_}],
- 'CosNotifyFilter_MappingFilter':add_mapping_constraints(Filter,
- [#'CosNotifyFilter_MappingConstraintPair'
- {constraint_expression = #'CosNotifyFilter_ConstraintExp'
- {event_types = [#'CosNotification_EventType'
- {domain_name = "name",
- type_name = "type"}],
- constraint_expr = "2==2 and 3<4"},
- result_to_set = any:create(orber_tc:short(), 10)},
- #'CosNotifyFilter_MappingConstraintPair'
- {constraint_expression = #'CosNotifyFilter_ConstraintExp'
- {event_types = [#'CosNotification_EventType'
- {domain_name = "name2",
- type_name = "type2"}],
- constraint_expr = "$.test._length == 3 and ($.test[0].score + $.test[1].score + $.test[2].score)/3 >=80"},
- result_to_set = any:create(orber_tc:short(), 10)}])),
-
- ?match([{'CosNotifyFilter_MappingConstraintInfo',_,CID2,_}, {'CosNotifyFilter_MappingConstraintInfo',_,CID1,_}],
- 'CosNotifyFilter_MappingFilter':get_all_mapping_constraints(Filter)),
- ?match([{'CosNotifyFilter_MappingConstraintInfo',_,CID1,_}],
- 'CosNotifyFilter_MappingFilter':get_mapping_constraints(Filter, [CID1])),
- ?match(ok, 'CosNotifyFilter_MappingFilter':remove_all_mapping_constraints(Filter)),
- ?match([], 'CosNotifyFilter_MappingFilter':get_all_mapping_constraints(Filter)),
-
- %% Try adding a constraint_expr with using invalid value, i.e., not short.
- ?match({'EXCEPTION',{'CosNotifyFilter_InvalidValue',_,_,_}},
- 'CosNotifyFilter_MappingFilter':add_mapping_constraints(Filter,
- [#'CosNotifyFilter_MappingConstraintPair'
- {constraint_expression = #'CosNotifyFilter_ConstraintExp'
- {event_types = [#'CosNotification_EventType'
- {domain_name = "name",
- type_name = "type"}],
- constraint_expr = "2==2 and 3<8"},
- result_to_set = any:create(orber_tc:long(), 10)}])),
-
- %% Try adding one correct and one incorrect constraint_expr
- ?match({'EXCEPTION',{'CosNotifyFilter_InvalidConstraint',_,_}},
- 'CosNotifyFilter_MappingFilter':add_mapping_constraints(Filter,
- [#'CosNotifyFilter_MappingConstraintPair'
- {constraint_expression = #'CosNotifyFilter_ConstraintExp'
- {event_types = [#'CosNotification_EventType'
- {domain_name = "name",
- type_name = "type"}],
- constraint_expr = "2==2 and 3<"},
- result_to_set = any:create(orber_tc:short(), 10)},
- #'CosNotifyFilter_MappingConstraintPair'
- {constraint_expression = #'CosNotifyFilter_ConstraintExp'
- {event_types = [#'CosNotification_EventType'
- {domain_name = "name2",
- type_name = "type2"}],
- constraint_expr = "$.test._length == 3 and ($.test[0].score + $.test[1].score + $.test[2].score)/3 >=80"},
- result_to_set = any:create(orber_tc:short(), 10)}])),
-
- %% Following testcases test different domain_name and type_name, e.g.,
- %% wildcards etc.
- [{_,ConInfoData,CID3,_}] =
- ?match([{'CosNotifyFilter_MappingConstraintInfo',_,_,_}],
- 'CosNotifyFilter_MappingFilter':add_mapping_constraints(Filter,
- [#'CosNotifyFilter_MappingConstraintPair'
- {constraint_expression = #'CosNotifyFilter_ConstraintExp'
- {event_types = [#'CosNotification_EventType'
- {domain_name = "domain",
- type_name = ""},
- #'CosNotification_EventType'
- {domain_name = "*",
- type_name = "type"}],
- constraint_expr = "2==2 and 3<4"},
- result_to_set = any:create(orber_tc:short(), 10)}])),
-
- %% Try removing a constraint
- ?match(ok, 'CosNotifyFilter_MappingFilter':modify_mapping_constraints(Filter,[CID3],[])),
- ?match([], 'CosNotifyFilter_MappingFilter':get_all_mapping_constraints(Filter)),
-
- %% Add e new constraint
- [{_,_,CID4,_}] =
- ?match([{'CosNotifyFilter_MappingConstraintInfo',_,_,_}],
- 'CosNotifyFilter_MappingFilter':add_mapping_constraints(Filter,
- [#'CosNotifyFilter_MappingConstraintPair'
- {constraint_expression = #'CosNotifyFilter_ConstraintExp'
- {event_types = [#'CosNotification_EventType'
- {domain_name = "domain1",
- type_name = ""},
- #'CosNotification_EventType'
- {domain_name = "domain2",
- type_name = "*"}],
- constraint_expr = "2==2 and 3<4"},
- result_to_set = any:create(orber_tc:short(), 10)}])),
-
- %% Try to update the constraint associated with CID4 to equal CID3.
- ?match(ok, 'CosNotifyFilter_MappingFilter':modify_mapping_constraints(Filter,[],
- [#'CosNotifyFilter_MappingConstraintInfo'
- {constraint_expression=
- #'CosNotifyFilter_ConstraintExp'
- {event_types =[#'CosNotification_EventType'
- {domain_name = "domain",
- type_name = ""},
- #'CosNotification_EventType'
- {domain_name = "*",
- type_name = "type"}],
- constraint_expr = "2==2 and 3<4"},
- constraint_id=CID4,
- value = any:create(orber_tc:short(), 10)}])),
-
- ?match([{_,ConInfoData,CID4,_}], 'CosNotifyFilter_MappingFilter':get_all_mapping_constraints(Filter)),
-
- ?match({'EXCEPTION', {'CosNotifyFilter_ConstraintNotFound', _, CID3}},
- 'CosNotifyFilter_MappingFilter':get_mapping_constraints(Filter, [CID3])),
- ?match(ok, 'CosNotifyFilter_MappingFilter':remove_all_mapping_constraints(Filter)),
- ?match([], 'CosNotifyFilter_MappingFilter':get_all_mapping_constraints(Filter)),
-
- ?match([{'CosNotifyFilter_MappingConstraintInfo',_,_,_}],
- 'CosNotifyFilter_MappingFilter':add_mapping_constraints(Filter,
- [#'CosNotifyFilter_MappingConstraintPair'
- {constraint_expression = #'CosNotifyFilter_ConstraintExp'
- {event_types = [#'CosNotification_EventType'
- {domain_name = "",
- type_name = "type1"},
- #'CosNotification_EventType'
- {domain_name = "*",
- type_name = "type2"}],
- constraint_expr = "2==2 and 3<4"},
- result_to_set = any:create(orber_tc:short(), 10)}])),
-
- ?match([{'CosNotifyFilter_MappingConstraintInfo',_,_,_}],
- 'CosNotifyFilter_MappingFilter':add_mapping_constraints(Filter,
- [#'CosNotifyFilter_MappingConstraintPair'
- {constraint_expression = #'CosNotifyFilter_ConstraintExp'
- {event_types = [#'CosNotification_EventType'
- {domain_name = "domain1",
- type_name = "type1"},
- #'CosNotification_EventType'
- {domain_name = "domain2",
- type_name = "type2"}],
- constraint_expr = "2==2 and 3<4"},
- result_to_set = any:create(orber_tc:short(), 10)}])),
-
- ?match([{'CosNotifyFilter_MappingConstraintInfo',_,_,_}],
- 'CosNotifyFilter_MappingFilter':add_mapping_constraints(Filter,
- [#'CosNotifyFilter_MappingConstraintPair'
- {constraint_expression = #'CosNotifyFilter_ConstraintExp'
- {event_types = [#'CosNotification_EventType'
- {domain_name = "dom*",
- type_name = "type1"},
- #'CosNotification_EventType'
- {domain_name = "domain2",
- type_name = "typ*"}],
- constraint_expr = "2==2 and 3<4"},
- result_to_set = any:create(orber_tc:short(), 10)}])),
-
- ?match([{'CosNotifyFilter_MappingConstraintInfo',_,_,_}],
- 'CosNotifyFilter_MappingFilter':add_mapping_constraints(Filter,
- [#'CosNotifyFilter_MappingConstraintPair'
- {constraint_expression = #'CosNotifyFilter_ConstraintExp'
- {event_types = [#'CosNotification_EventType'
- {domain_name = "dom*1",
- type_name = "type1"},
- #'CosNotification_EventType'
- {domain_name = "domain2",
- type_name = "typ*2"}],
- constraint_expr = "2==2 and 3<4"},
- result_to_set = any:create(orber_tc:short(), 10)}])),
-
- catch corba:dispose(FiFac),
- catch corba:dispose(Filter),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% CosNotifyFilter::Filter API tests
-%%-----------------------------------------------------------------
-filter_api(_Config) ->
- Fac = cosNotificationApp:start_global_factory(?FAC_OPT),
- ?match({_,key,_,_,_,_}, Fac),
- {Ch, _Id1} = 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(Fac, ?defaultQoS, ?defaultAdm),
- AC= 'CosNotifyChannelAdmin_EventChannel':for_consumers(Ch),
-
- FiFac = 'CosNotifyFilter_FilterFactory':oe_create(),
- ?match({_,key,_,_,_,_}, FiFac),
-
- Filter = 'CosNotifyFilter_FilterFactory':create_filter(FiFac,"EXTENDED_TCL"),
- ?match({_,key,_,_,_,_}, Filter),
-
- ?match("EXTENDED_TCL", 'CosNotifyFilter_Filter':'_get_constraint_grammar'(Filter)),
-
- %% Test Callback management.
- ?match({'EXCEPTION',{'BAD_PARAM',_,_,_}},
- 'CosNotifyFilter_Filter':attach_callback(Filter, Ch)),
- ?match([], 'CosNotifyFilter_Filter':get_callbacks(Filter)),
- ?match({'EXCEPTION',{'CosNotifyFilter_CallbackNotFound',_}},
- 'CosNotifyFilter_Filter':detach_callback(Filter, 0)),
- ID='CosNotifyFilter_Filter':attach_callback(Filter, AC),
- ?match([ID], 'CosNotifyFilter_Filter':get_callbacks(Filter)),
- ?match(ok, 'CosNotifyFilter_Filter':detach_callback(Filter, ID)),
- ?match([], 'CosNotifyFilter_Filter':get_callbacks(Filter)),
-
- %% This callback is just attached so we can test that we can call notify_subscribe.
- _ID2='CosNotifyFilter_Filter':attach_callback(Filter, AC),
-
- %% Test before we add any constarints.
- ?match([], 'CosNotifyFilter_Filter':get_all_constraints(Filter)),
- ?match({'EXCEPTION', {'CosNotifyFilter_ConstraintNotFound', _, 1}},
- 'CosNotifyFilter_Filter':get_constraints(Filter, [1])),
- ?match(ok, 'CosNotifyFilter_Filter':remove_all_constraints(Filter)),
-
- %% Try adding an incorrect constraint_expr
- ?match({'EXCEPTION',{'CosNotifyFilter_InvalidConstraint',_,_}},
- 'CosNotifyFilter_Filter':add_constraints(Filter,
- [#'CosNotifyFilter_ConstraintExp'{event_types =
- [#'CosNotification_EventType'{
- domain_name = "name",
- type_name = "type"}],
- constraint_expr = "2==2 and 3<"}])),
- %% Try adding two correct constraint_expr
- [{_,_,CID1},{_,_,CID2}]=
- ?match([{'CosNotifyFilter_ConstraintInfo',_,_}, {'CosNotifyFilter_ConstraintInfo',_,_}],
- 'CosNotifyFilter_Filter':add_constraints(Filter,
- [#'CosNotifyFilter_ConstraintExp'{event_types =
- [#'CosNotification_EventType'{
- domain_name = "name",
- type_name = "type"}],
- constraint_expr = "2==2 and 3<4"},
- #'CosNotifyFilter_ConstraintExp'{event_types =
- [#'CosNotification_EventType'{
- domain_name = "name2",
- type_name = "type2"}],
- constraint_expr = "$.test._length == 3 and ($.test[0].score + $.test[1].score + $.test[2].score)/3 >=80"}])),
-
- ?match([{'CosNotifyFilter_ConstraintInfo',_,CID2}, {'CosNotifyFilter_ConstraintInfo',_,CID1}],
- 'CosNotifyFilter_Filter':get_all_constraints(Filter)),
- ?match([{'CosNotifyFilter_ConstraintInfo',_,CID1}],
- 'CosNotifyFilter_Filter':get_constraints(Filter, [CID1])),
- ?match(ok, 'CosNotifyFilter_Filter':remove_all_constraints(Filter)),
- ?match([], 'CosNotifyFilter_Filter':get_all_constraints(Filter)),
-
- %% Try adding one correct and one incorrect constraint_expr
- ?match({'EXCEPTION',{'CosNotifyFilter_InvalidConstraint',_,_}},
- 'CosNotifyFilter_Filter':add_constraints(Filter,
- [#'CosNotifyFilter_ConstraintExp'{event_types =
- [#'CosNotification_EventType'{
- domain_name = "name",
- type_name = "type"}],
- constraint_expr = "2==2 and 3<"},
- #'CosNotifyFilter_ConstraintExp'{event_types =
- [#'CosNotification_EventType'{
- domain_name = "name2",
- type_name = "type2"}],
- constraint_expr = "$.test._length == 3 and ($.test[0].score + $.test[1].score + $.test[2].score)/3 >=80"}])),
-
- %% Following testcases test different domain_name and type_name, e.g.,
- %% wildcards etc.
- [{_,ConInfoData,CID3}] =
- ?match([{'CosNotifyFilter_ConstraintInfo',_,_}],
- 'CosNotifyFilter_Filter':add_constraints(Filter,
- [#'CosNotifyFilter_ConstraintExp'{event_types =
- [#'CosNotification_EventType'{
- domain_name = "domain",
- type_name = ""},
- #'CosNotification_EventType'{
- domain_name = "*",
- type_name = "type"}],
- constraint_expr = "2==2 and 3<4"}])),
-
- %% Try removing a constraint
- ?match(ok, 'CosNotifyFilter_Filter':modify_constraints(Filter,[CID3],[])),
- ?match([], 'CosNotifyFilter_Filter':get_all_constraints(Filter)),
-
- %% Add e new constraint
- [{_,_,CID4}] =
- ?match([{'CosNotifyFilter_ConstraintInfo',_,_}],
- 'CosNotifyFilter_Filter':add_constraints(Filter,
- [#'CosNotifyFilter_ConstraintExp'{event_types =
- [#'CosNotification_EventType'{
- domain_name = "domain1",
- type_name = ""},
- #'CosNotification_EventType'{
- domain_name = "domain2",
- type_name = "*"}],
- constraint_expr = "2==2 and 3<4"}])),
-
- %% Try to update the constraint associated with CID4 to equal CID3.
- ?match(ok, 'CosNotifyFilter_Filter':modify_constraints(Filter,[],
- [#'CosNotifyFilter_ConstraintInfo'{constraint_expression=
- #'CosNotifyFilter_ConstraintExp'{event_types =
- [#'CosNotification_EventType'{
- domain_name = "domain",
- type_name = ""},
- #'CosNotification_EventType'{
- domain_name = "*",
- type_name = "type"}],
- constraint_expr = "2==2 and 3<4"},
- constraint_id=CID4}])),
-
- ?match([{_,ConInfoData,CID4}], 'CosNotifyFilter_Filter':get_all_constraints(Filter)),
-
- ?match({'EXCEPTION', {'CosNotifyFilter_ConstraintNotFound', _, CID3}},
- 'CosNotifyFilter_Filter':get_constraints(Filter, [CID3])),
- ?match(ok, 'CosNotifyFilter_Filter':remove_all_constraints(Filter)),
- ?match([], 'CosNotifyFilter_Filter':get_all_constraints(Filter)),
-
- ?match([{'CosNotifyFilter_ConstraintInfo',_,_}],
- 'CosNotifyFilter_Filter':add_constraints(Filter,
- [#'CosNotifyFilter_ConstraintExp'{event_types =
- [#'CosNotification_EventType'{
- domain_name = "",
- type_name = "type1"},
- #'CosNotification_EventType'{
- domain_name = "*",
- type_name = "type2"}],
- constraint_expr = "2==2 and 3<4"}])),
-
- ?match([{'CosNotifyFilter_ConstraintInfo',_,_}],
- 'CosNotifyFilter_Filter':add_constraints(Filter,
- [#'CosNotifyFilter_ConstraintExp'{event_types =
- [#'CosNotification_EventType'{
- domain_name = "domain1",
- type_name = "type1"},
- #'CosNotification_EventType'{
- domain_name = "domain2",
- type_name = "type2"}],
- constraint_expr = "2==2 and 3<4"}])),
-
- ?match([{'CosNotifyFilter_ConstraintInfo',_,_}],
- 'CosNotifyFilter_Filter':add_constraints(Filter,
- [#'CosNotifyFilter_ConstraintExp'{event_types =
- [#'CosNotification_EventType'{
- domain_name = "dom*",
- type_name = "type1"},
- #'CosNotification_EventType'{
- domain_name = "domain2",
- type_name = "typ*"}],
- constraint_expr = "2==2 and 3<4"}])),
-
- ?match([{'CosNotifyFilter_ConstraintInfo',_,_}],
- 'CosNotifyFilter_Filter':add_constraints(Filter,
- [#'CosNotifyFilter_ConstraintExp'{event_types =
- [#'CosNotification_EventType'{
- domain_name = "dom*1",
- type_name = "type1"},
- #'CosNotification_EventType'{
- domain_name = "domain2",
- type_name = "typ*2"}],
- constraint_expr = "2==2 and 3<4"}])),
-
- catch corba:dispose(FiFac),
- catch corba:dispose(Filter),
- catch corba:dispose(AC),
- catch corba:dispose(Ch),
- catch corba:dispose(Fac),
- ok.
-
-%%-----------------------------------------------------------------
-%% Subscription handling API tests
-%%-----------------------------------------------------------------
-subscription_api(_Config) ->
- %% Initialize the application.
- Fac = (catch cosNotificationApp:start_global_factory(?FAC_OPT)),
- ?match({_,key,_,_,_,_}, Fac),
- {Ch, _Id1} = (catch 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(Fac, ?defaultQoS, ?defaultAdm)),
- ?match({_,key,_,_,_,_}, Ch),
-
- %% Create the Admin objects
- {AdminSupplier, _ASID}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_EventChannel':new_for_suppliers(Ch,'OR_OP')),
- {AdminConsumer, _ACID}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_EventChannel':new_for_consumers(Ch,'OR_OP')),
-
- %% Create Suppliers Proxies
- {StructuredProxyPullSupplier,_}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_ConsumerAdmin':obtain_notification_pull_supplier(AdminConsumer, 'STRUCTURED_EVENT')),
- {StructuredProxyPushSupplier,_}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_ConsumerAdmin':obtain_notification_push_supplier(AdminConsumer, 'STRUCTURED_EVENT')),
-
- %% Now we must create a Client for each proxy and connect them.
- PushStrC=?match({_,key,_,_,_,_}, 'notify_test_StrPushC':oe_create(['PUSH_STRUCTURED',StructuredProxyPushSupplier],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':connect_structured_push_consumer(StructuredProxyPushSupplier, PushStrC)),
- PullStrC=?match({_,key,_,_,_,_}, 'notify_test_StrPullC':oe_create(['PULL_STRUCTURED',StructuredProxyPullSupplier],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':connect_structured_pull_consumer(StructuredProxyPullSupplier, PullStrC)),
-
- %% Create Consumers Proxies
- {StructuredProxyPullConsumer,_}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_SupplierAdmin':obtain_notification_pull_consumer(AdminSupplier, 'STRUCTURED_EVENT')),
- {StructuredProxyPushConsumer,_}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_SupplierAdmin':obtain_notification_push_consumer(AdminSupplier, 'STRUCTURED_EVENT')),
-
- %% Now we must create a Client for each proxy and connect them.
- PushStrS=?match({_,key,_,_,_,_}, 'notify_test_StrPushS':oe_create(['PUSH_STRUCTURED',StructuredProxyPushConsumer],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':connect_structured_push_supplier(StructuredProxyPushConsumer, PushStrS)),
-
- PullStrS=?match({_,key,_,_,_,_}, 'notify_test_StrPullS':oe_create(['PULL_STRUCTURED',StructuredProxyPullConsumer],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':connect_structured_pull_supplier(StructuredProxyPullConsumer, PullStrS)),
-
- ES1=[#'CosNotification_EventType'{domain_name = "name1", type_name = "type1"},
- #'CosNotification_EventType'{domain_name = "name2", type_name = "type2"}],
- ES2=[#'CosNotification_EventType'{domain_name = "name3", type_name = "type3"},
- #'CosNotification_EventType'{domain_name = "name4", type_name = "type4"}],
-
- %% Initially it should have no associated types. Test that and set that
- %% all updates should be forwarded to client.
- ?match([], 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':
- obtain_subscription_types(StructuredProxyPushConsumer,
- 'ALL_NOW_UPDATES_ON')),
- ?match([], 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':
- obtain_subscription_types(StructuredProxyPullConsumer,
- 'ALL_NOW_UPDATES_ON')),
-
- %% Update the offered types.
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':
- offer_change(StructuredProxyPushConsumer, ES1, [])),
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':
- offer_change(StructuredProxyPullConsumer, ES1, [])),
-
- %% To be sure, wait a couple of seconds.
- timer:sleep(5000),
- ?match([{'CosNotification_EventType',_,_},
- {'CosNotification_EventType',_,_}],
- 'notify_test_StrPushC':doAction(PushStrS, return_data)),
- ?match([{'CosNotification_EventType',_,_},
- {'CosNotification_EventType',_,_}],
- 'notify_test_StrPullC':doAction(PullStrS, return_data)),
-
- %% Update the offered types. Remove ES1 and add ES2.
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':
- offer_change(StructuredProxyPushConsumer, ES2, ES1)),
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':
- offer_change(StructuredProxyPullConsumer, ES2, ES1)),
-
- %% To be sure, wait a couple of seconds.
- timer:sleep(5000),
- ?match([{'CosNotification_EventType',_,_},
- {'CosNotification_EventType',_,_}],
- 'notify_test_StrPushC':doAction(PushStrS, return_data)),
- ?match([{'CosNotification_EventType',_,_},
- {'CosNotification_EventType',_,_}],
- 'notify_test_StrPullC':doAction(PullStrS, return_data)),
-
- %% Now, the objects should only contain 'ES2'. Test it.
- ?match([{'CosNotification_EventType',_,_},
- {'CosNotification_EventType',_,_}],
- 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':
- obtain_subscription_types(StructuredProxyPushConsumer,
- 'ALL_NOW_UPDATES_ON')),
- ?match([{'CosNotification_EventType',_,_},
- {'CosNotification_EventType',_,_}],
- 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':
- obtain_subscription_types(StructuredProxyPullConsumer,
- 'ALL_NOW_UPDATES_ON')),
-
- %% Now we will use wildcards, empty strings and test if they really
- %% are ignored if so requested.
- ES3=[#'CosNotification_EventType'{domain_name = "name1", type_name = "*"},
- #'CosNotification_EventType'{domain_name = "*", type_name = "type2"}],
- ES4=[#'CosNotification_EventType'{domain_name = "name1", type_name = "*"},
- #'CosNotification_EventType'{domain_name = "name2", type_name = ""}],
- ES5=[#'CosNotification_EventType'{domain_name = "na*", type_name = "type1"}],
- ES6=[#'CosNotification_EventType'{domain_name = "n*1", type_name = "type1"}],
- ES7=[#'CosNotification_EventType'{domain_name = "*1", type_name = "type1"}],
- ES8=[#'CosNotification_EventType'{domain_name = "n*m*1", type_name = "type1"}],
- ES9=[#'CosNotification_EventType'{domain_name = "n**1", type_name = "type1"}],
- ES10=[#'CosNotification_EventType'{domain_name = "nam*1", type_name = "type1"}],
-
- Event1 = ?not_CreateSE("name1","type1",
- "event_name",
- [#'CosNotification_Property'{name="property_name",
- value=any:create(orber_tc:short(), 1)}],
- [], any:create(orber_tc:null(), null)),
- Event2 = ?not_CreateSE("name2","type1",
- "event_name",
- [#'CosNotification_Property'{name="property_name",
- value=any:create(orber_tc:short(), 1)}],
- [], any:create(orber_tc:null(), null)),
- Event3 = ?not_CreateSE("mame1","type1",
- "event_name",
- [#'CosNotification_Property'{name="property_name",
- value=any:create(orber_tc:short(), 1)}],
- [], any:create(orber_tc:null(), null)),
- Event4 = ?not_CreateSE("naame1","type1",
- "event_name",
- [#'CosNotification_Property'{name="property_name",
- value=any:create(orber_tc:short(), 1)}],
- [], any:create(orber_tc:null(), null)),
- Event5 = ?not_CreateSE("nname1","type1",
- "event_name",
- [#'CosNotification_Property'{name="property_name",
- value=any:create(orber_tc:short(), 1)}],
- [], any:create(orber_tc:null(), null)),
- Event6 = ?not_CreateSE("name12","type1",
- "event_name",
- [#'CosNotification_Property'{name="property_name",
- value=any:create(orber_tc:short(), 1)}],
- [], any:create(orber_tc:null(), null)),
-
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':
- subscription_change(StructuredProxyPullSupplier, ES3, [])),
-
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, Event1)),
-
- ?match(Event1, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
-
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':
- subscription_change(StructuredProxyPullSupplier, ES4, ES3)),
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, Event1)),
- ?match(Event1, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
-
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':
- subscription_change(StructuredProxyPullSupplier, ES5, ES4)),
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, Event1)),
- ?match(Event1, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
-
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':
- subscription_change(StructuredProxyPullSupplier, ES6, ES5)),
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, Event1)),
- ?match(Event1, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
-
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':
- subscription_change(StructuredProxyPullSupplier, ES7, ES6)),
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, Event1)),
- ?match(Event1, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
-
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':
- subscription_change(StructuredProxyPullSupplier, ES8, ES7)),
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, Event1)),
- ?match(Event1, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
-
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':
- subscription_change(StructuredProxyPullSupplier, ES9, ES8)),
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, Event1)),
- ?match(Event1, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
-
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, Event2)),
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, Event3)),
-
- timer:sleep(5000),
- ?match({_NilStrEvent,false}, 'notify_test_StrPullC':doAction(PullStrC, try_pull_str)),
-
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':
- subscription_change(StructuredProxyPullSupplier, ES10, ES9)),
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, Event1)),
- ?match(Event1, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
-
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, Event4)),
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, Event5)),
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, Event6)),
-
- timer:sleep(5000),
- ?match({_NilStrEvent,false}, 'notify_test_StrPullC':doAction(PullStrC, try_pull_str)),
-
-
- catch corba:dispose(StructuredProxyPushConsumer),
- catch corba:dispose(StructuredProxyPullConsumer),
- catch corba:dispose(StructuredProxyPushSupplier),
- catch corba:dispose(StructuredProxyPullSupplier),
- catch corba:dispose(AdminConsumer),
- catch corba:dispose(AdminSupplier),
- catch corba:dispose(Ch),
- catch cosNotificationApp:stop_factory(Fac),
-
- timer:sleep(5000),
- ?match(true, corba_object:non_existent(PullStrS)),
- ?match(true, corba_object:non_existent(PushStrS)),
- ?match(true, corba_object:non_existent(PullStrC)),
- ?match(true, corba_object:non_existent(PushStrC)),
-
- ok.
-
-%%-----------------------------------------------------------------
-%% Filter admin API tests
-%%-----------------------------------------------------------------
-filter_adm_api(_Config) ->
- Fac = (catch cosNotificationApp:start_global_factory(?FAC_OPT)),
- ?match({_,key,_,_,_,_}, Fac),
- {Ch, _Id1} = (catch 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(Fac, ?defaultQoS, ?defaultAdm)),
- ?match({_,key,_,_,_,_}, Ch),
-
- FiFac = 'CosNotifyFilter_FilterFactory':oe_create(),
- ?match({_,key,_,_,_,_}, FiFac),
-
- Filter = 'CosNotifyFilter_FilterFactory':create_filter(FiFac,"EXTENDED_TCL"),
- ?match({_,key,_,_,_,_}, Filter),
-
- AC=?match({_,key,_,_,_,_},
- 'CosNotifyChannelAdmin_EventChannel':for_consumers(Ch)),
- filter_tests('CosNotifyChannelAdmin_ConsumerAdmin', AC, Filter, Ch),
-
- AS=?match({_,key,_,_,_,_},
- 'CosNotifyChannelAdmin_EventChannel':for_suppliers(Ch)),
- filter_tests('CosNotifyChannelAdmin_SupplierAdmin', AS, Filter, Ch),
-
- PushS=?match({_,key,_,_,_,_},
- 'CosNotifyChannelAdmin_ConsumerAdmin':obtain_push_supplier(AC)),
- filter_tests('CosNotifyChannelAdmin_ProxyPushSupplier', PushS, Filter, Ch),
-
- PullS=?match({_,key,_,_,_,_},
- 'CosNotifyChannelAdmin_ConsumerAdmin':obtain_pull_supplier(AC)),
- filter_tests('CosNotifyChannelAdmin_ProxyPullSupplier', PullS, Filter, Ch),
-
- PushC=?match({_,key,_,_,_,_},
- 'CosNotifyChannelAdmin_SupplierAdmin':obtain_push_consumer(AS)),
- filter_tests('CosNotifyChannelAdmin_ProxyPushConsumer', PushC, Filter, Ch),
-
- PullC=?match({_,key,_,_,_,_},
- 'CosNotifyChannelAdmin_SupplierAdmin':obtain_pull_consumer(AS)),
- filter_tests('CosNotifyChannelAdmin_ProxyPullConsumer', PullC, Filter, Ch),
-
- catch corba:dispose(FiFac),
- catch corba:dispose(Filter),
- catch corba:dispose(PushS),
- catch corba:dispose(PullS),
- catch corba:dispose(PushC),
- catch corba:dispose(PullC),
- catch corba:dispose(AC),
- catch corba:dispose(AS),
- catch corba:dispose(Ch),
- catch cosNotificationApp:stop_factory(Fac),
- ok.
-
-filter_tests(Mod, Obj, Filter, Ch) ->
- io:format("############ TESTING MODULE ~p FILTER ############~n", [Mod]),
- %% No filter added.
- ?match([], Mod:get_all_filters(Obj)),
- ?match(ok, Mod:remove_all_filters(Obj)),
- ?match({'EXCEPTION',{'CosNotifyFilter_FilterNotFound',_}},
- Mod:get_filter(Obj, 0)),
- %% Try add a Filter which is not a filter.
- ?match({'EXCEPTION',{'BAD_PARAM',_,_,_}}, Mod:add_filter(Obj, Ch)),
- %% Try to remove a single filter.
- ?match({'EXCEPTION',{'CosNotifyFilter_FilterNotFound',_}},
- Mod:remove_filter(Obj, 0)),
- ID = Mod:add_filter(Obj, Filter),
- ?match([ID], Mod:get_all_filters(Obj)),
- ?match(Filter, Mod:get_filter(Obj, ID)),
- ?match(ok, Mod:remove_filter(Obj, ID)),
- ?match([], Mod:get_all_filters(Obj)),
- ID2 = Mod:add_filter(Obj, Filter),
- ?match([ID2], Mod:get_all_filters(Obj)),
- ?match(ok, Mod:remove_all_filters(Obj)),
- ?match([], Mod:get_all_filters(Obj)),
- ok.
-
-%%-----------------------------------------------------------------
-%% Creating different event pushing and pulling API tests
-%%-----------------------------------------------------------------
-events_api(_Config) ->
- %% Initialize the application.
- Fac = (catch cosNotificationApp:start_global_factory(?FAC_OPT)),
- ?match({_,key,_,_,_,_}, Fac),
- {Ch, Id1} = (catch 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(Fac, ?defaultQoS, ?defaultAdm)),
- ?match({_,key,_,_,_,_}, Ch),
- events_api_helper(Fac, Ch, Id1).
-
-events2_api(doc) -> ["CosNotification event pushing and pulling tests II", ""];
-events2_api(suite) -> [];
-events2_api(_Config) ->
- %% Initialize the application.
- Fac = (catch cosNotificationApp:start_global_factory(?FAC_OPT)),
- ?match({_,key,_,_,_,_}, Fac),
- {Ch, Id1} = (catch 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(Fac, ?defaultQoS2, ?defaultAdm)),
- ?match({_,key,_,_,_,_}, Ch),
- events_api_helper(Fac, Ch, Id1).
-
-events_api_helper(Fac, Ch, _Id1) ->
- %% Now we will set up a test environment, with the following structure:
- %%
- %% Channel
- %% / \
- %% Supplier Adm Consumer Adm
- %% / \
- %% 1 proxy of each possible type
- %% To each proxy we will connect a test client
- %% The events will flow in ===>> direction.
- %%
- %% For the supplier Admins this include:
- %% - ProxyPushConsumer
- %% - SequenceProxyPushConsumer
- %% - StructuredProxyPushConsumer
- %% - ProxyPullConsumer
- %% - SequenceProxyPullConsumer
- %% - StructuredProxyPullConsumer
- %%
- %% For the consumer Admins this include:
- %% - ProxyPushSupplier
- %% - SequenceProxyPushSupplier
- %% - StructuredProxyPushSupplier
- %% - ProxyPullSupplier
- %% - SequenceProxyPullSupplier
- %% - StructuredProxyPullSupplier
- %%
- %%
- %% We will not use any Filters to begin with, just want to make sure we can
- %% deliver events from all start- to end-points.
-
- %% Create the Admin objects
- {AdminSupplier, _ASID}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_EventChannel':new_for_suppliers(Ch,'AND_OP')),
- {AdminConsumer, _ACID}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_EventChannel':new_for_consumers(Ch,'AND_OP')),
-
- %% Create Suppliers Proxies
- {ProxyPullSupplier,_ID1}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_ConsumerAdmin':obtain_notification_pull_supplier(AdminConsumer, 'ANY_EVENT')),
- {StructuredProxyPullSupplier,_ID2}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_ConsumerAdmin':obtain_notification_pull_supplier(AdminConsumer, 'STRUCTURED_EVENT')),
- {SequenceProxyPullSupplier,_ID3}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_ConsumerAdmin':obtain_notification_pull_supplier(AdminConsumer, 'SEQUENCE_EVENT')),
-
- {ProxyPushSupplier,_I4D}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_ConsumerAdmin':obtain_notification_push_supplier(AdminConsumer, 'ANY_EVENT')),
- {StructuredProxyPushSupplier,_ID5}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_ConsumerAdmin':obtain_notification_push_supplier(AdminConsumer, 'STRUCTURED_EVENT')),
- {SequenceProxyPushSupplier,_ID6}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_ConsumerAdmin':obtain_notification_push_supplier(AdminConsumer, 'SEQUENCE_EVENT')),
-
- %% Now we must create a Client for each proxy and connect them.
- PushAnyC=?match({_,key,_,_,_,_}, 'notify_test_AnyPushC':oe_create(['PUSH_ANY', ProxyPushSupplier],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_ProxyPushSupplier':connect_any_push_consumer(ProxyPushSupplier, PushAnyC)),
-
- PushStrC=?match({_,key,_,_,_,_}, 'notify_test_StrPushC':oe_create(['PUSH_STRUCTURED',StructuredProxyPushSupplier],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPushSupplier':connect_structured_push_consumer(StructuredProxyPushSupplier, PushStrC)),
-
- PushSeqC=?match({_,key,_,_,_,_}, 'notify_test_SeqPushC':oe_create(['PUSH_SEQUENCE',SequenceProxyPushSupplier],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_SequenceProxyPushSupplier':connect_sequence_push_consumer(SequenceProxyPushSupplier, PushSeqC)),
-
- PullAnyC=?match({_,key,_,_,_,_}, 'notify_test_AnyPullC':oe_create(['PULL_ANY', ProxyPullSupplier],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_ProxyPullSupplier':connect_any_pull_consumer(ProxyPullSupplier, PullAnyC)),
-
- PullStrC=?match({_,key,_,_,_,_}, 'notify_test_StrPullC':oe_create(['PULL_STRUCTURED',StructuredProxyPullSupplier],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPullSupplier':connect_structured_pull_consumer(StructuredProxyPullSupplier, PullStrC)),
-
- PullSeqC=?match({_,key,_,_,_,_}, 'notify_test_SeqPullC':oe_create(['PULL_SEQUENCE',SequenceProxyPullSupplier],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_SequenceProxyPullSupplier':connect_sequence_pull_consumer(SequenceProxyPullSupplier, PullSeqC)),
-
-
- %% Create Consumers Proxies
- {ProxyPullConsumer,_ID7}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_SupplierAdmin':obtain_notification_pull_consumer(AdminSupplier, 'ANY_EVENT')),
- {StructuredProxyPullConsumer,_ID8}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_SupplierAdmin':obtain_notification_pull_consumer(AdminSupplier, 'STRUCTURED_EVENT')),
- {SequenceProxyPullConsumer,_ID9}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_SupplierAdmin':obtain_notification_pull_consumer(AdminSupplier, 'SEQUENCE_EVENT')),
-
- {ProxyPushConsumer,_ID10}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_SupplierAdmin':obtain_notification_push_consumer(AdminSupplier, 'ANY_EVENT')),
- {StructuredProxyPushConsumer,_ID11}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_SupplierAdmin':obtain_notification_push_consumer(AdminSupplier, 'STRUCTURED_EVENT')),
- {SequenceProxyPushConsumer,_ID12}=?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_SupplierAdmin':obtain_notification_push_consumer(AdminSupplier, 'SEQUENCE_EVENT')),
-
- %% Now we must create a Client for each proxy and connect them.
- PushAnyS=?match({_,key,_,_,_,_}, 'notify_test_AnyPushS':oe_create(['PUSH_ANY', ProxyPushConsumer],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_ProxyPushConsumer':connect_any_push_supplier(ProxyPushConsumer, PushAnyS)),
-
- PushStrS=?match({_,key,_,_,_,_}, 'notify_test_StrPushS':oe_create(['PUSH_STRUCTURED',StructuredProxyPushConsumer],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':connect_structured_push_supplier(StructuredProxyPushConsumer, PushStrS)),
-
- PushSeqS=?match({_,key,_,_,_,_}, 'notify_test_SeqPushS':oe_create(['PUSH_SEQUENCE',SequenceProxyPushConsumer],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_SequenceProxyPushConsumer':connect_sequence_push_supplier(SequenceProxyPushConsumer, PushSeqS)),
-
- PullAnyS=?match({_,key,_,_,_,_}, 'notify_test_AnyPullS':oe_create(['PULL_ANY', ProxyPullConsumer],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_ProxyPullConsumer':connect_any_pull_supplier(ProxyPullConsumer, PullAnyS)),
-
- PullStrS=?match({_,key,_,_,_,_}, 'notify_test_StrPullS':oe_create(['PULL_STRUCTURED',StructuredProxyPullConsumer],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPullConsumer':connect_structured_pull_supplier(StructuredProxyPullConsumer, PullStrS)),
-
- PullSeqS=?match({_,key,_,_,_,_}, 'notify_test_SeqPullS':oe_create(['PULL_SEQUENCE',SequenceProxyPullConsumer],
- [{local_typecheck, false}])),
- ?match(ok, 'CosNotifyChannelAdmin_SequenceProxyPullConsumer':connect_sequence_pull_supplier(SequenceProxyPullConsumer, PullSeqS)),
-
-
- %% Create a couple of Events to test with.
- Event = ?not_CreateSE("DomainName","CommunicationsAlarm",
- "lost_packet",
- [#'CosNotification_Property'{name="priority",
- value=any:create(orber_tc:short(), 1)}],
- [], any:create(orber_tc:null(), null)),
-
- Event2 = ?not_CreateSE("DomainName","TemperatureAlarm",
- "over_heated",
- [#'CosNotification_Property'{name="priority",
- value=any:create(orber_tc:short(), 10)}],
- [], any:create(orber_tc:null(), null)),
-
-
- AnyEvent = any:create(orber_tc:long(), 100),
-
- StrEvent = ?not_CreateSE("","%ANY","",[],[],AnyEvent),
- NilAnyEvent = any:create(orber_tc:null(), null),
- NilStrEvent = ?not_CreateSE("","","",[],[],NilAnyEvent),
-
- ConvertedStr = any:create('CosNotification_StructuredEvent':tc(), Event),
-
- io:format("###################### PUSH STRUCTURED ########################"),
-
- %% Test with pushing a structured event.
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, Event)),
-
- %% Wait for a while so we are sure that all events have been delivered as far
- %% as the Notification service can automatically.
- timer:sleep(5000),
-
- %% Check if the Clients have received and stored the events.
- ?match([{any,_,Event}], 'notify_test_AnyPushC':doAction(PushAnyC, return_data)),
- ?match([Event], 'notify_test_StrPushC':doAction(PushStrC, return_data)),
- ?match([Event], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
-
- %% Instruct the Clients to pull the events and check if they match.
- ?match({any,_,Event}, 'notify_test_AnyPullC':doAction(PullAnyC, pull_any)),
- ?match(Event, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
- ?match([Event], 'notify_test_SeqPullC':doAction(PullSeqC, {pull_seq,1})),
-
- io:format("###################### PUSH SEQUENCE ########################"),
-
- %% Create an Event Sequence and push it.
- EventSeq = [Event, Event2],
-
- %% Test with pushing a event sequence.
- ?match(ok,'CosNotifyChannelAdmin_SequenceProxyPushConsumer':push_structured_events(SequenceProxyPushConsumer, EventSeq)),
-
- %% Wait for a while so we are sure that all events have been delivered as far
- %% as the Notification service can automatically.
- timer:sleep(5000),
-
- %% Instruct the Clients to pull the events and check if they match.
- ?match({any,_,Event}, 'notify_test_AnyPullC':doAction(PullAnyC, pull_any)),
- ?match(Event, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
- ?match([Event,Event2], 'notify_test_SeqPullC':doAction(PullSeqC, {pull_seq,2})),
- ?match({any,_,Event2}, 'notify_test_AnyPullC':doAction(PullAnyC, pull_any)),
- ?match(Event2, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
-
- %% Check if the Push Clients have received and stored the events.
- ?match([{any,_,Event}, {any,_,Event2}], 'notify_test_AnyPushC':doAction(PushAnyC, return_data)),
- ?match([Event, Event2], 'notify_test_StrPushC':doAction(PushStrC, return_data)),
- ?match([Event, Event2], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
-
- io:format("###################### PUSH ANY ########################"),
-
- %% Test with pushing an any event.
- ?match(ok,'CosEventChannelAdmin_ProxyPushConsumer':push(ProxyPushConsumer, AnyEvent)),
-
- %% Wait for a while so we are sure that all events have been delivered as far
- %% as the Notification service can automatically.
- timer:sleep(5000),
-
- %% Check if the Clients have received and stored the events.
- ?match([AnyEvent], 'notify_test_AnyPushC':doAction(PushAnyC, return_data)),
- ?match([StrEvent], 'notify_test_StrPushC':doAction(PushStrC, return_data)),
- ?match([StrEvent], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
-
- %% Instruct the Clients to pull the events and check if they match.
- ?match(AnyEvent, 'notify_test_AnyPullC':doAction(PullAnyC, pull_any)),
- ?match(StrEvent, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
- ?match([StrEvent], 'notify_test_SeqPullC':doAction(PullSeqC, {pull_seq,10})),
-
-
-
- io:format("###################### PUSH CONVERTED ANY #############"),
-
- %% Test with pushing a structured event.
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, StrEvent)),
-
- %% Wait for a while so we are sure that all events have been delivered as far
- %% as the Notification service can automatically.
- timer:sleep(5000),
-
- %% Check if the Clients have received and stored the events.
- ?match([AnyEvent], 'notify_test_AnyPushC':doAction(PushAnyC, return_data)),
- ?match([StrEvent], 'notify_test_StrPushC':doAction(PushStrC, return_data)),
- ?match([StrEvent], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
-
- %% Instruct the Clients to pull the events and check if they match.
- ?match(AnyEvent, 'notify_test_AnyPullC':doAction(PullAnyC, pull_any)),
- ?match(StrEvent, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
- ?match([StrEvent], 'notify_test_SeqPullC':doAction(PullSeqC, {pull_seq,1})),
-
-
- io:format("###################### PUSH CONVERTED STRUCTURED ########"),
-
- %% Test with pushing an any event.
- ?match(ok,'CosEventChannelAdmin_ProxyPushConsumer':push(ProxyPushConsumer, ConvertedStr)),
-
- %% Wait for a while so we are sure that all events have been delivered as far
- %% as the Notification service can automatically.
- timer:sleep(5000),
-
- %% Check if the Clients have received and stored the events.
- ?match([ConvertedStr], 'notify_test_AnyPushC':doAction(PushAnyC, return_data)),
- ?match([Event], 'notify_test_StrPushC':doAction(PushStrC, return_data)),
- ?match([Event], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
-
- %% Instruct the Clients to pull the events and check if they match.
- ?match(ConvertedStr, 'notify_test_AnyPullC':doAction(PullAnyC, pull_any)),
- ?match(Event, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
- ?match([Event], 'notify_test_SeqPullC':doAction(PullSeqC, {pull_seq,10})),
-
-
- io:format("###################### TRY PULL ########################"),
-
- %% Now we will push an any event after a delay. This means that try_pull-functions,
- %% since it's not blocking, will return, [], NilAny or NilStructured events and
- %% the Boolean false.
- spawn(notify_test_impl, delay, [ProxyPushConsumer, AnyEvent, 20000,
- 'CosEventChannelAdmin_ProxyPushConsumer',push]),
- ?match([], 'notify_test_AnyPushC':doAction(PushAnyC, return_data)),
- ?match([], 'notify_test_StrPushC':doAction(PushStrC, return_data)),
- ?match([], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
-
- %% Instruct the Clients to pull the events and check if they match.
- ?match({NilAnyEvent,false}, 'notify_test_AnyPullC':doAction(PullAnyC, try_pull_any)),
- ?match({NilStrEvent,false}, 'notify_test_StrPullC':doAction(PullStrC, try_pull_str)),
- ?match({[],false}, 'notify_test_SeqPullC':doAction(PullSeqC, {try_pull_seq,10})),
-
-
- %% Instruct the Clients to pull the events and check if they match.
- %% Pull is blocking so in the print-out we should see that nothing
- %% is returned until the pushed event reaches the end proxies.
- ?match(AnyEvent, 'notify_test_AnyPullC':doAction(PullAnyC, pull_any)),
- ?match(StrEvent, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
- ?match([StrEvent], 'notify_test_SeqPullC':doAction(PullSeqC, {pull_seq,1})),
-
- %% To make sure there are no other circumstanses which lead to a delay we
- %% hold for some time.
- timer:sleep(5000),
- %% Check if the Clients have received and stored the events.
- ?match([AnyEvent], 'notify_test_AnyPushC':doAction(PushAnyC, return_data)),
- ?match([StrEvent], 'notify_test_StrPushC':doAction(PushStrC, return_data)),
- ?match([StrEvent], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
-
- %% Test with pushing a event sequence but only pull sequences of length 1.
- ?match(ok,'CosNotifyChannelAdmin_SequenceProxyPushConsumer':push_structured_events(SequenceProxyPushConsumer, EventSeq)),
-
- %% Wait for a while so we are sure that all events have been delivered as far
- %% as the Notification service can automatically.
- timer:sleep(5000),
- %% Pull 1 event at a time.
- ?match([Event], 'notify_test_SeqPullC':doAction(PullSeqC, {pull_seq,1})),
- ?match([Event2], 'notify_test_SeqPullC':doAction(PullSeqC, {pull_seq,1})),
-
- %% Following cases already tested; done for clean up.
- ?match({any,_,Event}, 'notify_test_AnyPullC':doAction(PullAnyC, pull_any)),
- ?match(Event, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
- ?match({any,_,Event2}, 'notify_test_AnyPullC':doAction(PullAnyC, pull_any)),
- ?match(Event2, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
- ?match([{any,_,Event}, {any,_,Event2}], 'notify_test_AnyPushC':doAction(PushAnyC, return_data)),
- ?match([Event, Event2], 'notify_test_StrPushC':doAction(PushStrC, return_data)),
- ?match([Event, Event2], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
- %% clean up done
-
-
- io:format("###################### PROXY PULLER ########################"),
-
- %% Now we will just add Events to a cleint and wait for the Notification service
- %% to pull the events and forward them to the consumer clients.
- ?match(ok, 'notify_test_SeqPushC':doAction(PullAnyS, {set_data, [AnyEvent]})),
-
-
- %% Instruct the Clients to pull the events and check if they match.
- %% Pull is blocking so in the print-out we should see that nothing
- %% is returned until the pushed event reaches the end proxies.
- ?match(AnyEvent, 'notify_test_AnyPullC':doAction(PullAnyC, pull_any)),
- ?match(StrEvent, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
- ?match([StrEvent], 'notify_test_SeqPullC':doAction(PullSeqC, {pull_seq,10})),
-
- %% To make sure there are no other circumstanses which lead to a delay we
- %% hold for some time.
- timer:sleep(5000),
- %% Check if the Clients have received and stored the events.
- ?match([AnyEvent], 'notify_test_AnyPushC':doAction(PushAnyC, return_data)),
- ?match([StrEvent], 'notify_test_StrPushC':doAction(PushStrC, return_data)),
- ?match([StrEvent], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
-
- io:format("###################### SUSPENDED CONNECTION ################"),
-
-
- %% Suspend the connections
- ?match(ok,'CosNotifyChannelAdmin_SequenceProxyPushSupplier':suspend_connection(SequenceProxyPushSupplier)),
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushSupplier':suspend_connection(StructuredProxyPushSupplier)),
-
- %% Test with pushing a event sequence.
- ?match(ok,'CosNotifyChannelAdmin_SequenceProxyPushConsumer':push_structured_events(SequenceProxyPushConsumer, EventSeq)),
-
- %% Wait for a while so we are sure that all events have been delivered as far
- %% as the Notification service can automatically.
- timer:sleep(5000),
-
- %% Instruct the Clients to pull the events and check if they match.
- ?match({any,_,Event}, 'notify_test_AnyPullC':doAction(PullAnyC, pull_any)),
- ?match(Event, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
- ?match([Event,Event2], 'notify_test_SeqPullC':doAction(PullSeqC, {pull_seq,2})),
- ?match({any,_,Event2}, 'notify_test_AnyPullC':doAction(PullAnyC, pull_any)),
- ?match(Event2, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
-
- %% Check if the Any Client have received and stored the events.
- ?match([{any,_,Event}, {any,_,Event2}], 'notify_test_AnyPushC':doAction(PushAnyC, return_data)),
-
- %% Check if the other Clients have received any events. Error if have.
- ?match([], 'notify_test_StrPushC':doAction(PushStrC, return_data)),
- ?match([], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
-
- ?match(ok,'CosNotifyChannelAdmin_SequenceProxyPushSupplier':resume_connection(SequenceProxyPushSupplier)),
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushSupplier':resume_connection(StructuredProxyPushSupplier)),
-
- %% To be sure the test case don't fail due to time-race, sleep.
- timer:sleep(5000),
-
- ?match([Event, Event2], 'notify_test_StrPushC':doAction(PushStrC, return_data)),
- ?match([Event, Event2], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
-
-
- io:format("###################### FILTER EVENTS #######################"),
-
- %% Now we will add filters and see if the system behaves correctly.
- FiFac = 'CosNotifyFilter_FilterFactory':oe_create(),
- Filter = 'CosNotifyFilter_FilterFactory':create_filter(FiFac,"EXTENDED_TCL"),
- %% Add constraints to the Filter
- [{_,_,CID1},{_,_,CID2}]=
- ?match([{'CosNotifyFilter_ConstraintInfo',_,_}, {'CosNotifyFilter_ConstraintInfo',_,_}],
- 'CosNotifyFilter_Filter':add_constraints(Filter,
- [#'CosNotifyFilter_ConstraintExp'{event_types =
- [#'CosNotification_EventType'{
- domain_name = "Spare*",
- type_name = "MOVIE"}],
- constraint_expr = "$type_name == 'MOVIE' and (('groucho' in $starlist) + ('chico' in $starlist) + ('harpo' in $starlist) + ('zeppo' in $starlist) + ('gummo' in $starlist)) > 2"},
- #'CosNotifyFilter_ConstraintExp'{event_types =
- [#'CosNotification_EventType'{
- domain_name = "*",
- type_name = "TestResults"}],
- constraint_expr = "$test._length == 3 and ($test[0].score + $test[1].score + $test[2].score)/3 >=80"}])),
-
- ?match([{'CosNotifyFilter_ConstraintInfo',_,CID2}, {'CosNotifyFilter_ConstraintInfo',_,CID1}],
- 'CosNotifyFilter_Filter':get_all_constraints(Filter)),
- ?match([{'CosNotifyFilter_ConstraintInfo',_,CID1}],
- 'CosNotifyFilter_Filter':get_constraints(Filter, [CID1])),
-
- %% Associate the Filter with different objects.
- %% Since we use the same filter for both objects the events will never reach the admin.
- _FilterID = 'CosNotifyChannelAdmin_ConsumerAdmin':add_filter(AdminConsumer, Filter),
-
- _FilterID2 = 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':add_filter(StructuredProxyPushConsumer, Filter),
- event_filtering(FiFac, Filter, AdminConsumer, StructuredProxyPushConsumer, PushAnyC,
- PushStrC, PushSeqC, PullAnyC, PullStrC, PullSeqC),
- %% Remove the proxy filter so we can check if the events are filtered correctly by the admin.
- ?match(ok, 'CosNotifyChannelAdmin_StructuredProxyPushConsumer':remove_all_filters(StructuredProxyPushConsumer)),
- event_filtering(FiFac, Filter, AdminConsumer, StructuredProxyPushConsumer, PushAnyC,
- PushStrC, PushSeqC, PullAnyC, PullStrC, PullSeqC),
-
-
- catch corba:dispose(Filter),
- catch corba:dispose(FiFac),
- catch corba:dispose(SequenceProxyPushConsumer),
- catch corba:dispose(StructuredProxyPushConsumer),
- catch corba:dispose(ProxyPushConsumer),
- catch corba:dispose(SequenceProxyPullConsumer),
- catch corba:dispose(StructuredProxyPullConsumer),
- catch corba:dispose(ProxyPullConsumer),
- catch corba:dispose(SequenceProxyPushSupplier),
- catch corba:dispose(StructuredProxyPushSupplier),
- catch corba:dispose(ProxyPushSupplier),
- catch corba:dispose(SequenceProxyPullSupplier),
- catch corba:dispose(StructuredProxyPullSupplier),
- catch corba:dispose(ProxyPullSupplier),
- catch corba:dispose(AdminConsumer),
- catch corba:dispose(AdminSupplier),
- catch corba:dispose(Ch),
- catch cosNotificationApp:stop_factory(Fac),
- %% The Clients should have terminated by now. Check if it is so.
- timer:sleep(5000),
- ?match(true, corba_object:non_existent(PullSeqS)),
- ?match(true, corba_object:non_existent(PullStrS)),
- ?match(true, corba_object:non_existent(PullAnyS)),
- ?match(true, corba_object:non_existent(PushSeqS)),
- ?match(true, corba_object:non_existent(PushStrS)),
- ?match(true, corba_object:non_existent(PushAnyS)),
- ?match(true, corba_object:non_existent(PullSeqC)),
- ?match(true, corba_object:non_existent(PullStrC)),
- ?match(true, corba_object:non_existent(PullAnyC)),
- ?match(true, corba_object:non_existent(PushSeqC)),
- ?match(true, corba_object:non_existent(PushStrC)),
- ?match(true, corba_object:non_existent(PushAnyC)),
- ok.
-
-event_filtering(_FiFac, _Filter, _AdminConsumer, StructuredProxyPushConsumer, PushAnyC, PushStrC, PushSeqC, PullAnyC, PullStrC, PullSeqC) ->
- NilAnyEvent = any:create(orber_tc:null(), null),
- NilStrEvent = ?not_CreateSE("","","",[],[],NilAnyEvent),
-
- TrueEvent1 = ?not_CreateSE("SpareTime","MOVIE",
- "EventName",
- [#'CosNotification_Property'{name="starlist",
- value=any:create(orber_tc:sequence(orber_tc:string(0),0),
- ["groucho", "harpo", "sam", "gummo"])}],
- [], any:create(orber_tc:null(), null)),
- TrueEvent2 = ?not_CreateSE("Studies","TestResults",
- "EventName", [],
- [#'CosNotification_Property'{name="test",
- value=any:create(orber_tc:array(notify_test_data:tc(),3),
- {#notify_test_data{score=75,
- name="name"},
- #notify_test_data{score=80,
- name="name"},
- #notify_test_data{score=85,
- name="name"}})}],
- any:create(orber_tc:null(), null)),
-
- FalseEvent1 = ?not_CreateSE("SpareTime","MOVIE",
- "EventName",
- [#'CosNotification_Property'{name="starlist",
- value=any:create(orber_tc:sequence(orber_tc:string(0),0),
- ["frodo", "bilbo", "sam", "gummo"])}],
- [], any:create(orber_tc:null(), null)),
- FalseEvent2 = ?not_CreateSE("Studies","TestResults",
- "EventName", [],
- [#'CosNotification_Property'{name="test",
- value=any:create(orber_tc:array(notify_test_data:tc(),3),
- {#notify_test_data{score=75,
- name="name"},
- #notify_test_data{score=80,
- name="name"},
- #notify_test_data{score=80,
- name="name"}})}],
- any:create(orber_tc:null(), null)),
- %% Test with pushing the first structured event that should not be filtered away.
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, TrueEvent1)),
-
- %% Wait for a while so we are sure that all events have been delivered as far
- %% as the Notification service can automatically.
- timer:sleep(5000),
-
- %% Check if the Clients have received and stored the events.
- ?match([{any,_,TrueEvent1}], 'notify_test_AnyPushC':doAction(PushAnyC, return_data)),
- ?match([TrueEvent1], 'notify_test_StrPushC':doAction(PushStrC, return_data)),
- ?match([TrueEvent1], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
-
- %% Instruct the Clients to pull the events and check if they match.
- ?match({any,_,TrueEvent1}, 'notify_test_AnyPullC':doAction(PullAnyC, pull_any)),
- ?match(TrueEvent1, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
- ?match([TrueEvent1], 'notify_test_SeqPullC':doAction(PullSeqC, {pull_seq,1})),
-
- %% Test with pushing the second structured event that should not be filtered away.
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, TrueEvent2)),
-
- %% Wait for a while so we are sure that all events have been delivered as far
- %% as the Notification service can automatically.
- timer:sleep(5000),
-
- %% Check if the Clients have received and stored the events.
- ?match([{any,_,TrueEvent2}], 'notify_test_AnyPushC':doAction(PushAnyC, return_data)),
- ?match([TrueEvent2], 'notify_test_StrPushC':doAction(PushStrC, return_data)),
- ?match([TrueEvent2], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
-
- %% Instruct the Clients to pull the events and check if they match.
- ?match({any,_,TrueEvent2}, 'notify_test_AnyPullC':doAction(PullAnyC, pull_any)),
- ?match(TrueEvent2, 'notify_test_StrPullC':doAction(PullStrC, pull_str)),
- ?match([TrueEvent2], 'notify_test_SeqPullC':doAction(PullSeqC, {pull_seq,1})),
-
- %% Test with pushing the first structured event that should be filtered away.
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, FalseEvent1)),
-
- %% Wait for a while so we are sure that all events have been delivered as far
- %% as the Notification service can automatically.
- timer:sleep(5000),
-
- %% Check if the Clients have received and stored the events.
- ?match([], 'notify_test_AnyPushC':doAction(PushAnyC, return_data)),
- ?match([], 'notify_test_StrPushC':doAction(PushStrC, return_data)),
- ?match([], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
-
- %% Instruct the Clients to pull the events and check if they match.
- ?match({NilAnyEvent,false}, 'notify_test_AnyPullC':doAction(PullAnyC, try_pull_any)),
- ?match({NilStrEvent,false}, 'notify_test_StrPullC':doAction(PullStrC, try_pull_str)),
- ?match({[],false}, 'notify_test_SeqPullC':doAction(PullSeqC, {try_pull_seq,10})),
-
- %% Test with pushing the second structured event that should be filtered away.
- ?match(ok,'CosNotifyChannelAdmin_StructuredProxyPushConsumer':push_structured_event(StructuredProxyPushConsumer, FalseEvent2)),
-
- %% Wait for a while so we are sure that all events have been delivered as far
- %% as the Notification service can automatically.
- timer:sleep(5000),
-
- %% Check if the Clients have received and stored the events.
- ?match([], 'notify_test_AnyPushC':doAction(PushAnyC, return_data)),
- ?match([], 'notify_test_StrPushC':doAction(PushStrC, return_data)),
- ?match([], 'notify_test_SeqPushC':doAction(PushSeqC, return_data)),
-
- %% Instruct the Clients to pull the events and check if they match.
- ?match({NilAnyEvent,false}, 'notify_test_AnyPullC':doAction(PullAnyC, try_pull_any)),
- ?match({NilStrEvent,false}, 'notify_test_StrPullC':doAction(PullStrC, try_pull_str)),
- ?match({[],false}, 'notify_test_SeqPullC':doAction(PullSeqC, {try_pull_seq,10})).
-
-
-
-%%-----------------------------------------------------------------
-%% Creating different cosEvent API tests
-%%-----------------------------------------------------------------
-cosevent_api(_Config) ->
- Fac = (catch cosNotificationApp:start_global_factory(?FAC_OPT)),
- ?match({_,key,_,_,_,_}, Fac),
- {Ch, _Id1} = (catch 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(Fac, ?defaultQoS, ?defaultAdm)),
- ?match({_,key,_,_,_,_}, Ch),
- AC=?match({_,key,_,_,_,_},
- 'CosEventChannelAdmin_EventChannel':for_consumers(Ch)),
- AS=?match({_,key,_,_,_,_},
- 'CosEventChannelAdmin_EventChannel':for_suppliers(Ch)),
-
- PushS=?match({_,key,_,_,_,_},
- 'CosEventChannelAdmin_ConsumerAdmin':obtain_push_supplier(AC)),
- PullS=?match({_,key,_,_,_,_},
- 'CosEventChannelAdmin_ConsumerAdmin':obtain_pull_supplier(AC)),
-
- PushC=?match({_,key,_,_,_,_},
- 'CosEventChannelAdmin_SupplierAdmin':obtain_push_consumer(AS)),
- PullC=?match({_,key,_,_,_,_},
- 'CosEventChannelAdmin_SupplierAdmin':obtain_pull_consumer(AS)),
-
- PushAnyC=?match({_,key,_,_,_,_},
- 'notify_test_AnyPushC':oe_create(['PUSH_ANY', PushC],
- [{local_typecheck, false}])),
- PushStrC=?match({_,key,_,_,_,_},
- 'notify_test_StrPushC':oe_create(['PUSH_STRUCTURED',false],
- [{local_typecheck, false}])),
- PushSeqC=?match({_,key,_,_,_,_},
- 'notify_test_SeqPushC':oe_create(['PUSH_SEQUENCE',false],
- [{local_typecheck, false}])),
-
- PullAnyC=?match({_,key,_,_,_,_},
- 'notify_test_AnyPullC':oe_create(['PULL_ANY', PullC],
- [{local_typecheck, false}])),
- PullStrC=?match({_,key,_,_,_,_},
- 'notify_test_StrPullC':oe_create(['PULL_STRUCTURED',false],
- [{local_typecheck, false}])),
- PullSeqC=?match({_,key,_,_,_,_},
- 'notify_test_SeqPullC':oe_create(['PULL_SEQUENCE',false],
- [{local_typecheck, false}])),
-
- PushAnyS=?match({_,key,_,_,_,_},
- 'notify_test_AnyPushS':oe_create(['PUSH_ANY', PushC],
- [{local_typecheck, false}])),
- PushStrS=?match({_,key,_,_,_,_},
- 'notify_test_StrPushS':oe_create(['PUSH_STRUCTURED',false],
- [{local_typecheck, false}])),
- PushSeqS=?match({_,key,_,_,_,_},
- 'notify_test_SeqPushS':oe_create(['PUSH_SEQUENCE',false],
- [{local_typecheck, false}])),
-
- PullAnyS=?match({_,key,_,_,_,_},
- 'notify_test_AnyPullS':oe_create(['PULL_ANY', PullS],
- [{local_typecheck, false}])),
- PullStrS=?match({_,key,_,_,_,_},
- 'notify_test_StrPullS':oe_create(['PULL_STRUCTURED',false],
- [{local_typecheck, false}])),
- PullSeqS=?match({_,key,_,_,_,_},
- 'notify_test_SeqPullS':oe_create(['PULL_SEQUENCE',false],
- [{local_typecheck, false}])),
-
- %% In the OMG specification Proxies do not inherrit from CosEvent. Must use
- %% Notify interface.
- ?match({'EXCEPTION',{'BAD_PARAM',_,_,_}},
- 'CosEventChannelAdmin_ProxyPullConsumer':connect_pull_supplier(PullC, PushStrS)),
-
- ?match(ok,
- 'CosEventChannelAdmin_ProxyPushSupplier':connect_push_consumer(PushS, PushAnyC)),
- ?match(ok,
- 'CosEventChannelAdmin_ProxyPullSupplier':connect_pull_consumer(PullS, PullAnyC)),
-
- ?match(ok,
- 'CosEventChannelAdmin_ProxyPushConsumer':connect_push_supplier(PushC, PushAnyS)),
- ?match(ok,
- 'CosEventChannelAdmin_ProxyPullConsumer':connect_pull_supplier(PullC, PullAnyS)),
-
- ?match({'EXCEPTION',{'CosEventChannelAdmin_AlreadyConnected',_}},
- 'CosEventChannelAdmin_ProxyPullConsumer':connect_pull_supplier(PullC, PullAnyS)),
-
- ?match({'EXCEPTION',{'CosEventChannelAdmin_AlreadyConnected',_}},
- 'CosNotifyChannelAdmin_ProxyPullConsumer':connect_pull_supplier(PullC, PullAnyS)),
-
- ?match(true, corba_object:is_a(PushS, "IDL:omg.org/CosNotifyChannelAdmin/ProxyPushSupplier:1.0")),
- ?match(true, corba_object:is_a(PushS, "IDL:omg.org/CosEventChannelAdmin/ProxyPushSupplier:1.0")),
-
- catch corba:dispose(PushStrC),
- catch corba:dispose(PushSeqC),
- catch corba:dispose(PullStrC),
- catch corba:dispose(PullSeqC),
- catch corba:dispose(PushStrS),
- catch corba:dispose(PushSeqS),
- catch corba:dispose(PullStrS),
- catch corba:dispose(PullSeqS),
- catch corba:dispose(PushS),
- catch corba:dispose(PullS),
- catch corba:dispose(PushC),
- catch corba:dispose(PullC),
- catch corba:dispose(AC),
- catch corba:dispose(AS),
- catch corba:dispose(Ch),
- catch cosNotificationApp:stop_factory(Fac),
-
- %% The Clients should have terminated by now. Check if it is so.
- timer:sleep(5000),
- ?match(true, corba_object:non_existent(PullAnyS)),
- ?match(true, corba_object:non_existent(PushAnyS)),
- ?match(true, corba_object:non_existent(PullAnyC)),
- ?match(true, corba_object:non_existent(PushAnyC)),
-
-
- ok.
-
-%%-----------------------------------------------------------------
-%% AdminPropertiesAdmin API tests
-%%-----------------------------------------------------------------
-adm_api(_Config) ->
- Fac = (catch cosNotificationApp:start_global_factory(?FAC_OPT)),
- ?match({_,key,_,_,_,_}, Fac),
-
- %% We need a few AdminProp:s to "play" with.
- MQ0 = [#'CosNotification_Property'{name='CosNotification':'MaxQueueLength'(),
- value=any:create(orber_tc:long(), 0)}],
- MC0 = [#'CosNotification_Property'{name='CosNotification':'MaxConsumers'(),
- value=any:create(orber_tc:long(), 0)}],
- MS0 = [#'CosNotification_Property'{name='CosNotification':'MaxSuppliers'(),
- value=any:create(orber_tc:long(), 0)}],
- MQError1 = [#'CosNotification_Property'{name='CosNotification':'MaxQueueLength'(),
- value=any:create(orber_tc:'float'(), 1.5)}],
- MQError2 = [#'CosNotification_Property'{name='CosNotification':'MaxQueueLength'(),
- value=any:create(orber_tc:long(), -1)}],
-
- {Ch, _Id1} = (catch 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(Fac, ?defaultQoS, ?defaultAdm)),
- ?match({_,key,_,_,_,_}, Ch),
-
- %% Set new admin
- ?match(ok, 'CosNotification_AdminPropertiesAdmin':set_admin(Ch, MQ0)),
- %% It should be a list of three items. If we support more admin:s this
- %% must be updated.
- ?match([_,_,_], 'CosNotification_AdminPropertiesAdmin':get_admin(Ch)),
-
- %% Try to set admin with an uncorrect value, i.e., not integer >= 0.
- ?match({'EXCEPTION',{'CosNotification_UnsupportedAdmin',_,_}},
- 'CosNotification_AdminPropertiesAdmin':set_admin(Ch, MQError1)),
- ?match({'EXCEPTION',{'CosNotification_UnsupportedAdmin',_,_}},
- 'CosNotification_AdminPropertiesAdmin':set_admin(Ch, MQError2)),
-
- %% Try setting the other two admins and chech if the value is correct.
- ?match(ok, 'CosNotification_AdminPropertiesAdmin':set_admin(Ch, MC0)),
- ?match([_,_,_], 'CosNotification_AdminPropertiesAdmin':get_admin(Ch)),
-
- ?match(ok, 'CosNotification_AdminPropertiesAdmin':set_admin(Ch, MS0)),
- ?match([_,_,_], 'CosNotification_AdminPropertiesAdmin':get_admin(Ch)),
-
- catch corba:dispose(Ch),
- catch cosNotificationApp:stop_factory(Fac),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% QoSAdm API tests
-%%-----------------------------------------------------------------
-qos_api(_Config) ->
- Fac = (catch cosNotificationApp:start_global_factory(?FAC_OPT)),
- ?match({_,key,_,_,_,_}, Fac),
-
- {Ch, _Id1} = (catch 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(Fac, ?defaultQoS, ?defaultAdm)),
- ?match({_,key,_,_,_,_}, Ch),
-
-
- QoSPersistent = [#'CosNotification_Property'{name='CosNotification':'ConnectionReliability'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'Persistent'())}],
- QoSBestEffort = [#'CosNotification_Property'{name='CosNotification':'ConnectionReliability'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'BestEffort'())}],
-
- QoSEventPersistent = [#'CosNotification_Property'{name='CosNotification':'EventReliability'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'Persistent'())}],
- QoSEventBestEffort = [#'CosNotification_Property'{name='CosNotification':'EventReliability'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'BestEffort'())}],
-
- QoSOKMaxBatchSize = [#'CosNotification_Property'{name='CosNotification':'MaximumBatchSize'(),
- value=any:create(orber_tc:long(), 200)}],
- QoSToHighMaxBatchSize = [#'CosNotification_Property'{name='CosNotification':'MaximumBatchSize'(),
- value=any:create(orber_tc:long(), 100000000)}],
-
- QoSToLowMaxBatchSize = [#'CosNotification_Property'{name='CosNotification':'MaximumBatchSize'(),
- value=any:create(orber_tc:long(), -1)}],
-
- QoSOKStopTimeSupp = [#'CosNotification_Property'{name='CosNotification':'StopTimeSupported'(),
- value=any:create(orber_tc:boolean(), true)}],
- QoSWrongStopTimeSupp = [#'CosNotification_Property'{name="StopTimeSupp",
- value=any:create(orber_tc:boolean(), true)}],
-
- QoSOKStartTimeSupp = [#'CosNotification_Property'{name='CosNotification':'StartTimeSupported'(),
- value=any:create(orber_tc:boolean(), true)}],
- QoSWrongStartTimeSupp = [#'CosNotification_Property'{name="StartTimeSupp",
- value=any:create(orber_tc:boolean(), true)}],
- QoSOKTimout = [#'CosNotification_Property'{name='CosNotification':'Timeout'(),
- value=any:create(orber_tc:unsigned_long_long(), 100)}],
-
-
- %% The most complex QoS to set is ConnectionReliability, and the reason for this
- %% is that we cannot set the Channel to offer best effort while its children
- %% offer persistent. A child may only offer Persistent if its parent do, which
- %% is why we must check the following:
- %%
- %% # Persistent Change to Best Effort
- %% _____
- %% | | (1) -> Check if children BE
- %% |Chann| (2) ok <-
- %% -----
- %% |
- %% _____
- %% | | (3) -> Check if children BE
- %% |Admin| (4) Check if parent Pers. <-
- %% -----
- %% |
- %% _____
- %% | | (5) -> ok
- %% |Proxy| (6) Check if parent Pers. <-
- %% -----
- %% NOTE: a parent always exists but we may change the QoS before creating any
- %% childrens. The cases (2) and (5) is always ok, i.e., no need to confirm
- %% with parent or children.
-
- %% We only have a channel. At the moment we can set ConnectionReliability
- %% without asking anyone.
- Q1='CosNotification_QoSAdmin':get_qos(Ch),
- ?match({ok, _}, 'CosNotification_QoSAdmin':validate_qos(Ch, QoSBestEffort)),
-
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(Ch, QoSPersistent)),
- %% Match if no problems occur if we try to set QoS as is.
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(Ch, QoSPersistent)),
-
- %% Check validate.
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(Ch, QoSEventPersistent)),
- ?match({ok, _}, 'CosNotification_QoSAdmin':validate_qos(Ch, QoSOKTimout)),
- ?match({ok, _}, 'CosNotification_QoSAdmin':validate_qos(Ch, QoSEventBestEffort)),
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(Ch, QoSEventBestEffort)),
- ?match({ok, _}, 'CosNotification_QoSAdmin':validate_qos(Ch, QoSOKTimout)),
-
- Q2='CosNotification_QoSAdmin':get_qos(Ch),
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(Ch, QoSBestEffort)),
- ?match(Q1, 'CosNotification_QoSAdmin':get_qos(Ch)),
-
- %% Now we add an Admin object. An Admin object cannot switch ConnectionReliability
- %% to BestEffort without checking with its children or Persistent without
- %% confirming this with its Parent. At the moment, however, we only have a parent.
- {CAdm, Id2} = 'CosNotifyChannelAdmin_EventChannel':new_for_consumers(Ch, 'AND_OP'),
- ?match(Q1,'CosNotification_QoSAdmin':get_qos(CAdm)),
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosNotification_QoSAdmin':set_qos(CAdm, QoSPersistent)),
- ?match(Q1, 'CosNotification_QoSAdmin':get_qos(CAdm)),
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(CAdm, QoSBestEffort)),
- ?match(Q1, 'CosNotification_QoSAdmin':get_qos(CAdm)),
-
- %% Check if we can extract the Admin from the channel correctly.
- ?match([0,Id2],'CosNotifyChannelAdmin_EventChannel':get_all_consumeradmins(Ch)),
- ?match(CAdm,'CosNotifyChannelAdmin_EventChannel':get_consumeradmin(Ch, Id2)),
- ?match(Ch, 'CosNotifyChannelAdmin_ConsumerAdmin':'_get_MyChannel'(CAdm)),
- ?match(Id2, 'CosNotifyChannelAdmin_ConsumerAdmin':'_get_MyID'(CAdm)),
-
- %% Change the channel to provide Persistent service. Now we can set the
- %% Admin service to Persistent to. (4)
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(Ch, QoSPersistent)),
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(CAdm, QoSPersistent)),
- ?match(Q2, 'CosNotification_QoSAdmin':get_qos(CAdm)),
-
- %% Since the Admin object now provide Persistent the Channel cannot switch
- %% to BestEffort. (1)
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosNotification_QoSAdmin':set_qos(Ch, QoSBestEffort)),
- %% Should still match Persistent.
- ?match(Q2, 'CosNotification_QoSAdmin':get_qos(Ch)),
- {PSup, _Id3} = 'CosNotifyChannelAdmin_ConsumerAdmin':obtain_notification_push_supplier(CAdm, 'ANY_EVENT'),
- ?match(Q2, 'CosNotification_QoSAdmin':get_qos(CAdm)),
- ?match('PUSH_ANY', 'CosNotifyChannelAdmin_ProxyPushConsumer':'_get_MyType'(PSup)),
- ?match(CAdm, 'CosNotifyChannelAdmin_ProxyPushConsumer':'_get_MyAdmin'(PSup)),
- ?match(Q2, 'CosNotification_QoSAdmin':get_qos(PSup)),
-
- %% At this point they all offer persistent connection, which means we have
- %% to start with the proxy if we want to change to Best Effort. Hence,
- %% the following two cases will fail.
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosNotification_QoSAdmin':set_qos(Ch, QoSBestEffort)),
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosNotification_QoSAdmin':set_qos(CAdm, QoSBestEffort)),
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(PSup, QoSBestEffort)),
- %% Still not possible to change channel to Best Effort.
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosNotification_QoSAdmin':set_qos(Ch, QoSBestEffort)),
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(CAdm, QoSBestEffort)),
- %% Now we change the channel to Best Effort.
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(Ch, QoSBestEffort)),
-
- %% Test if really are Best Effort
- ?match(Q1, 'CosNotification_QoSAdmin':get_qos(Ch)),
- ?match(Q1, 'CosNotification_QoSAdmin':get_qos(CAdm)),
- ?match(Q1, 'CosNotification_QoSAdmin':get_qos(PSup)),
-
- %% Testing MaximumBatchSize (The highest value is defined in
- %% CosNotification_Common.erl
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(Ch, QoSOKMaxBatchSize)),
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosNotification_QoSAdmin':set_qos(Ch, QoSToHighMaxBatchSize)),
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosNotification_QoSAdmin':set_qos(Ch, QoSToLowMaxBatchSize)),
-
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(Ch, QoSOKStartTimeSupp)),
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(Ch, QoSOKStopTimeSupp)),
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosNotification_QoSAdmin':set_qos(Ch, QoSWrongStartTimeSupp)),
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosNotification_QoSAdmin':set_qos(Ch, QoSWrongStopTimeSupp)),
-
- catch corba:dispose(CAdm),
- catch corba:dispose(PSup),
- catch corba:dispose(Ch),
- cosNotificationApp:stop_factory(Fac),
- ok.
-
-%%-----------------------------------------------------------------
-%% QoSAdm API tests
-%%-----------------------------------------------------------------
-event_qos_api(_Config) ->
- Fac = (catch cosNotificationApp:start_global_factory(?FAC_OPT)),
- ?match({_,key,_,_,_,_}, Fac),
-
- %% Create some objects to test with. We start with default settings.
- {Ch, _Id1} = (catch 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(Fac, ?defaultQoS, ?defaultAdm)),
- {CAdm, _Id2} = 'CosNotifyChannelAdmin_EventChannel':new_for_consumers(Ch, 'AND_OP'),
- {PSup, _Id3} = 'CosNotifyChannelAdmin_ConsumerAdmin':obtain_notification_push_supplier(CAdm, 'ANY_EVENT'),
-
- %% Try setting an unsupported QoS.
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosNotifyChannelAdmin_ProxyConsumer':
- validate_event_qos(PSup,
- [#'CosNotification_Property'{name="Unsupported QoS",
- value=any:create(orber_tc:short(), 1)}])),
- %% Try setting min and max priority.
- ?match({ok, _}, 'CosNotifyChannelAdmin_ProxyConsumer':
- validate_event_qos(PSup,
- [#'CosNotification_Property'{name=?not_Priority,
- value=any:create(orber_tc:short(),
- ?not_LowestPriority)},
- #'CosNotification_Property'{name=?not_Priority,
- value=any:create(orber_tc:short(),
- ?not_HighestPriority)}])),
- %% Try setting priority values which are 1 to high and 1 to low respectively.
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- 'CosNotifyChannelAdmin_ProxyConsumer':
- validate_event_qos(PSup,
- [#'CosNotification_Property'{name=?not_Priority,
- value=any:create(orber_tc:short(),
- ?not_LowestPriority-1)},
- #'CosNotification_Property'{name=?not_Priority,
- value=any:create(orber_tc:short(),
- ?not_HighestPriority+1)}])),
- %% Try setting start- and stop-time (false default). Note the value associated
- %% with this property is not really a short but that is not what we are testing
- %% here so...
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosNotifyChannelAdmin_ProxyConsumer':
- validate_event_qos(PSup,
- [#'CosNotification_Property'{name=?not_StartTime,
- value=any:create(orber_tc:short(), 0)}])),
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosNotifyChannelAdmin_ProxyConsumer':
- validate_event_qos(PSup,
- [#'CosNotification_Property'{name=?not_StopTime,
- value=any:create(orber_tc:short(), 0)}])),
- %% Allow StopTime
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(PSup, [#'CosNotification_Property'{name='CosNotification':'StopTimeSupported'(),
- value=any:create(orber_tc:boolean(), true)}])),
- ?match({ok,_},
- 'CosNotifyChannelAdmin_ProxyConsumer':
- validate_event_qos(PSup,
- [#'CosNotification_Property'{name=?not_StopTime,
- value=any:create(orber_tc:short(), 0)}])),
- %% Allow StartTime
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(PSup, [#'CosNotification_Property'{name='CosNotification':'StartTimeSupported'(),
- value=any:create(orber_tc:boolean(), true)}])),
- ?match({ok,_},
- 'CosNotifyChannelAdmin_ProxyConsumer':
- validate_event_qos(PSup,
- [#'CosNotification_Property'{name=?not_StopTime,
- value=any:create(orber_tc:short(), 0)},
- #'CosNotification_Property'{name=?not_StartTime,
- value=any:create(orber_tc:short(), 0)}])),
-
- %% We must reset StopTime since we cannot guarantee that an event will be delivered
- %% if risk beeing discarded due to a delay.
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(PSup, [#'CosNotification_Property'{name='CosNotification':'StopTimeSupported'(),
- value=any:create(orber_tc:boolean(), false)}])),
- %% Does it accept Best Effort EventReliability? Must always be true.
- ?match({ok,_},
- 'CosNotifyChannelAdmin_ProxyConsumer':
- validate_event_qos(PSup,
- [#'CosNotification_Property'{name=?not_EventReliability,
- value=any:create(orber_tc:short(), ?not_BestEffort)}])),
- %% Default is Best Effort; test if we can set Persistent EventReliability.
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosNotifyChannelAdmin_ProxyConsumer':
- validate_event_qos(PSup,
- [#'CosNotification_Property'{name=?not_EventReliability,
- value=any:create(orber_tc:short(), ?not_Persistent)}])),
-
- %% Set Persistent
- QoSPersistent = [#'CosNotification_Property'{name='CosNotification':'ConnectionReliability'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'Persistent'())}],
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(Ch, QoSPersistent)),
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(CAdm, QoSPersistent)),
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(PSup, QoSPersistent)),
-
- %% Does it accept Best Effort EventReliability? Must always be true.
- ?match({ok, _},
- 'CosNotifyChannelAdmin_ProxyConsumer':
- validate_event_qos(PSup,
- [#'CosNotification_Property'{name=?not_EventReliability,
- value=any:create(orber_tc:short(), ?not_BestEffort)}])),
- %% Test if we can use Persistent EventReliability.
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosNotifyChannelAdmin_ProxyConsumer':
- validate_event_qos(PSup,
- [#'CosNotification_Property'{name=?not_EventReliability,
- value=any:create(orber_tc:short(), ?not_Persistent)}])),
- QoSEventPersistent = [#'CosNotification_Property'{name='CosNotification':'EventReliability'(),
- value=any:create(orber_tc:short(),
- 'CosNotification':'Persistent'())}],
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(Ch, QoSEventPersistent)),
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosNotification_QoSAdmin':set_qos(CAdm, QoSEventPersistent)),
- ?match({'EXCEPTION',{'CosNotification_UnsupportedQoS',_,_}},
- 'CosNotification_QoSAdmin':set_qos(PSup, QoSEventPersistent)),
-
- ?match(ok, 'CosNotification_QoSAdmin':set_qos(PSup, [#'CosNotification_Property'{name='CosNotification':'StopTimeSupported'(),
- value=any:create(orber_tc:boolean(), true)}])),
- ?match({ok,_},
- 'CosNotifyChannelAdmin_ProxyConsumer':
- validate_event_qos(PSup,
- [#'CosNotification_Property'{name=?not_StopTime,
- value=any:create(orber_tc:short(), 0)},
- #'CosNotification_Property'{name=?not_StartTime,
- value=any:create(orber_tc:short(), 0)}])),
- catch corba:dispose(CAdm),
- catch corba:dispose(PSup),
- catch corba:dispose(Ch),
- cosNotificationApp:stop_factory(Fac),
- ok.
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-
-%%-------------------- End of Module ------------------------------
diff --git a/lib/cosNotification/test/notify_test_impl.erl b/lib/cosNotification/test/notify_test_impl.erl
deleted file mode 100644
index 6c833f4915..0000000000
--- a/lib/cosNotification/test/notify_test_impl.erl
+++ /dev/null
@@ -1,300 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : notify_test_impl.erl
-%%----------------------------------------------------------------------
-
--module(notify_test_impl).
-
--include_lib("orber/include/corba.hrl").
--include("idl_output/notify_test.hrl").
-
-%%--------------- specified functions ------------------------
--export([stop_normal/2,
- stop_brutal/2,
- print/2,
- doAction/3,
- delay/5,
- %% Exports from CosNotifyComm::StructuredPushConsumer
- push_structured_event/3, disconnect_structured_push_consumer/2,
- %% Exports from "CosNotifyComm::SequencePushConsumer"
- push_structured_events/3, disconnect_sequence_push_consumer/2,
- %% Exports from CosEventComm::PushConsumer
- push/3, disconnect_push_consumer/2,
- %% Exports from CosNotifyComm::NotifyPublish
- disconnect_sequence_pull_consumer/2,
- %% Exports from CosNotifyComm::StructuredPullConsumer
- disconnect_structured_pull_consumer/2,
- %% Exports from CosEventComm::PullConsumer
- disconnect_pull_consumer/2,
- %% Exports from CosNotifyComm::SequencePushSupplier
- disconnect_sequence_push_supplier/2,
- %% Exports from CosNotifyComm::StructuredPushSupplier
- disconnect_structured_push_supplier/2,
- %% Exports from CosEventComm::PushSupplier
- disconnect_push_supplier/2,
- %% Exports from CosNotifyComm::SequencePullSupplier
- pull_structured_events/3,
- try_pull_structured_events/3,
- disconnect_sequence_pull_supplier/2,
- %% Exports from CosNotifyComm::StructuredPullSupplier
- pull_structured_event/2,
- try_pull_structured_event/2,
- disconnect_structured_pull_supplier/2,
- %% Exports from CosEventComm::PullSupplier
- pull/2,
- try_pull/2,
- disconnect_pull_supplier/2,
- %% Exports from CosNotifyComm::SequencePullConsumer
- offer_change/4,
- %% Exports from CosNotifyComm::NotifySubscribe
- subscription_change/4]).
-
-%%--------------- gen_server specific ------------------------
--export([init/1, terminate/2]).
--export([handle_call/3, handle_cast/2, handle_info/2, code_change/3]).
-%% Data structures
--record(state, {myType, proxy, data, action}).
-
-%%--------------- LOCAL DATA ---------------------------------
-
-%%------------------------------------------------------------
-%% function : init, terminate
-%%------------------------------------------------------------
-init([MyType, Proxy]) ->
- process_flag(trap_exit,true),
- {ok, #state{myType=MyType, proxy=Proxy, data=[]}}.
-
-terminate(Reason, State) ->
- io:format("notify_test:terminate(~p ~p)~n",[Reason, State#state.myType]),
- ok.
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-handle_call(_,_, State) ->
- {noreply, State}.
-handle_cast(_, State) ->
- {noreply, State}.
-handle_info(_Info, State) ->
- {noreply, State}.
-
-%%--------------- SERVER FUNCTIONS ---------------------------
-
-print(Self, State) ->
- io:format("notify_test:print(~p ~p)~n",[Self, State]),
- {reply, ok, State}.
-
-doAction(_Self, State, {set_data, Data}) ->
- io:format("notify_test:doAction(add_data) ~p~n",[Data]),
- {reply, ok, State#state{data=Data}};
-doAction(_Self, State, {add_data, Data}) ->
- io:format("notify_test:doAction(add_data) ~p~n",[Data]),
- {reply, ok, State#state{data=State#state.data++Data}};
-doAction(_Self, State, return_data) ->
- io:format("notify_test:doAction(return_data)~n",[]),
- {reply, State#state.data, State#state{data=[]}};
-doAction(_Self, State, clear_data) ->
- io:format("notify_test:doAction(return_data)~n",[]),
- {reply, ok, State#state{data=[]}};
-doAction(_Self, State, pull_any) ->
- io:format("notify_test:doAction(pull_any)~n",[]),
- Event='CosNotifyChannelAdmin_ProxyPullSupplier':pull(State#state.proxy),
- {reply, Event, State};
-doAction(_Self, State, {pull_seq, Max}) ->
- io:format("notify_test:doAction(pull_sequence)~n",[]),
- Event='CosNotifyChannelAdmin_SequenceProxyPullSupplier':pull_structured_events(State#state.proxy, Max),
- {reply, Event, State};
-doAction(_Self, State, pull_str) ->
- Event='CosNotifyChannelAdmin_StructuredProxyPullSupplier':pull_structured_event(State#state.proxy),
- io:format("notify_test:doAction(pull_structured)~n",[]),
- {reply, Event, State};
-doAction(_Self, State, try_pull_any) ->
- io:format("notify_test:doAction(try_pull_any)~n",[]),
- Event='CosNotifyChannelAdmin_ProxyPullSupplier':try_pull(State#state.proxy),
- {reply, Event, State};
-doAction(_Self, State, {try_pull_seq, Max}) ->
- io:format("notify_test:doAction(try_pull_sequence)~n",[]),
- Event='CosNotifyChannelAdmin_SequenceProxyPullSupplier':try_pull_structured_events(State#state.proxy, Max),
- {reply, Event, State};
-doAction(_Self, State, try_pull_str) ->
- Event='CosNotifyChannelAdmin_StructuredProxyPullSupplier':try_pull_structured_event(State#state.proxy),
- io:format("notify_test:doAction(try_pull_structured)~n",[]),
- {reply, Event, State};
-doAction(_Self, State, {action, Action}) ->
- io:format("notify_test:doAction(~p)~n",[Action]),
- {reply, ok, State#state{action = Action}};
-
-doAction(_, State, _) ->
- {reply, nop, State}.
-
-stop_normal(_Self, State) ->
- {stop, normal, ok, State}.
-
-stop_brutal(_Self, _State) ->
- exit("killed_brutal").
-
-
-
-%%--------------- CosNotifyComm::NotifyPublish --------
-offer_change(_Self, State, Added, Removed) ->
- ND=loop(Removed, State#state.data),
- ND2=Added++ND,
- {reply, ok, State#state{data=ND2}}.
-
-loop([],Data) ->
- Data;
-loop([H|T], Data) ->
- ND=lists:delete(H,Data),
- loop(T, ND).
-
-%%--------------- CosNotifyComm::NotifySubscribe --------
-subscription_change(_Self, State, Added, Removed) ->
- ND=loop(Removed, State#state.data),
- ND2=Added++ND,
- {reply, ok, State#state{data=ND2}}.
-
-%%--------------- CosNotifyComm::SequencePushConsumer --------
-push_structured_events(_Self, #state{action = undefined} = State, Event) ->
- io:format("notify_test:push_structured_events(~p)~n",[Event]),
- {reply, ok, State#state{data=State#state.data++Event}};
-push_structured_events(_Self, #state{action = Action} = State, Event) ->
- io:format("notify_test:push_structured_events(~p)~nAction: ~p~n",
- [Event, Action]),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}),
- {reply, ok, State#state{data=State#state.data++Event}}.
-disconnect_sequence_push_consumer(_Self, State) ->
- io:format("disconnect_sequence_push_consumer~n",[]),
- {stop, normal, ok, State}.
-
-%%--------------- CosNotifyComm::StructuredPushConsumer --------
-push_structured_event(_Self, State, Event) ->
- io:format("notify_test:push_structured_event(~p)~n",[Event]),
- {reply, ok, State#state{data=State#state.data++[Event]}}.
-disconnect_structured_push_consumer(_Self, State) ->
- io:format("disconnect_structured_push_consumer~n",[]),
- {stop, normal, ok, State}.
-
-%%--------------- CosEventComm::PushConsumer --------
-push(_Self, State, Event) ->
- io:format("notify_test:push(~p)~n",[Event]),
- {reply, ok, State#state{data=State#state.data++[Event]}}.
-disconnect_push_consumer(_Self, State) ->
- io:format("disconnect_push_consumer~n",[]),
- {stop, normal, ok, State}.
-
-%%--------------- CosNotifyComm::SequencePullConsumer --------
-disconnect_sequence_pull_consumer(_Self, State) ->
- io:format("disconnect_sequence_pull_consumer~n",[]),
- {stop, normal, ok, State}.
-
-%%--------------- CosNotifyComm::StructuredPullConsumer --------
-disconnect_structured_pull_consumer(_Self, State) ->
- io:format("disconnect_structured_pull_consumer~n",[]),
- {stop, normal, ok, State}.
-
-%%--------------- CosEventComm::PullConsumer --------
-disconnect_pull_consumer(_Self, State) ->
- io:format("disconnect_pull_consumer~n",[]),
- {stop, normal, ok, State}.
-
-%%--------------- CosNotifyComm::SequencePushSupplier --------
-disconnect_sequence_push_supplier(_Self, State) ->
- io:format("disconnect_sequence_push_supplier~n",[]),
- {stop, normal, ok, State}.
-
-%%--------------- CosNotifyComm::StructuredPushSupplier --------
-disconnect_structured_push_supplier(_Self, State) ->
- io:format("disconnect_structured_push_supplier~n",[]),
- {stop, normal, ok, State}.
-
-%%--------------- CosEventComm::PushSupplier --------
-disconnect_push_supplier(_Self, State) ->
- io:format("disconnect_push_supplier~n",[]),
- {stop, normal, ok, State}.
-
-%%--------------- CosNotifyComm::SequencePullSupplier --------
-pull_structured_events(_Self, State, _Max) ->
- io:format("notify_test:pullstructured_events()~n",[]),
- {reply, ok, State}.
-try_pull_structured_events(_Self, State, Max) ->
- io:format("notify_test:try_pull_structured_events()~n",[]),
- case State#state.data of
- [] ->
- {reply, {[],false}, State};
- List ->
- R = split(List,Max),
- {reply, {lists:sublist(List, Max), true}, State#state{data=R}}
- end.
-
-split([],_) ->
- [];
-split(R,0) ->
- R;
-split([_H|T],Max) ->
- split(T, Max-1).
-
-disconnect_sequence_pull_supplier(_Self, State) ->
- io:format("disconnect_sequence_pull_supplier~n",[]),
- {stop, normal, ok, State}.
-
-%%--------------- CosNotifyComm::StructuredPullSupplier --------
-pull_structured_event(_Self, State) ->
- io:format("notify_test:pull_structured_event()~n",[]),
- {reply, ok, State}.
-try_pull_structured_event(_Self, State) ->
- io:format("notify_test:try_pull_structured_event()~n",[]),
- case State#state.data of
- [] ->
- {reply, {[],false}, State};
- [H|T] ->
- {reply, {H, true}, State#state{data=T}}
- end.
-disconnect_structured_pull_supplier(_Self, State) ->
- io:format("disconnect_structured_pull_supplier~n",[]),
- {stop, normal, ok, State}.
-
-%%--------------- CosEventComm::PullSupplier --------
-pull(_Self, State) ->
- io:format("notify_test:pull()~n",[]),
- {reply, 'CosEventComm_PullSupplier':pull(State#state.proxy), State}.
-try_pull(_Self, State) ->
- io:format("notify_test:try_pull()~n",[]),
- case State#state.data of
- [] ->
- {reply, {[],false}, State};
- [H|T] ->
- {reply, {H, true}, State#state{data=T}}
- end.
-disconnect_pull_supplier(_Self, State) ->
- io:format("disconnect_pull_supplier~n",[]),
- {stop, normal, ok, State}.
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-
-delay(Obj, Event, Time, Mod, F) ->
- io:format("notify_test:delay(~p) TIME: ~p~n",[Event, erlang:timestamp()]),
- timer:sleep(Time),
- Mod:F(Obj, Event),
- io:format("notify_test:delay() DONE: ~p~n",[erlang:timestamp()]),
- ok.
-
-%%--------------- END OF MODULE ------------------------------
-
diff --git a/lib/cosNotification/test/notify_test_server.cfg b/lib/cosNotification/test/notify_test_server.cfg
deleted file mode 100644
index 60f50b23bb..0000000000
--- a/lib/cosNotification/test/notify_test_server.cfg
+++ /dev/null
@@ -1,55 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-{this, "notify_test::SeqPushC"}.
-{{handle_info, "notify_test::SeqPushC"}, true}.
-{{impl, "notify_test::SeqPushC"}, "notify_test_impl"}.
-{this, "notify_test::StrPushC"}.
-{{handle_info, "notify_test::StrPushC"}, true}.
-{{impl, "notify_test::StrPushC"}, "notify_test_impl"}.
-{this, "notify_test::AnyPushC"}.
-{{handle_info, "notify_test::AnyPushC"}, true}.
-{{impl, "notify_test::AnyPushC"}, "notify_test_impl"}.
-{this, "notify_test::SeqPullC"}.
-{{handle_info, "notify_test::SeqPullC"}, true}.
-{{impl, "notify_test::SeqPullC"}, "notify_test_impl"}.
-{this, "notify_test::StrPullC"}.
-{{handle_info, "notify_test::StrPullC"}, true}.
-{{impl, "notify_test::StrPullC"}, "notify_test_impl"}.
-{this, "notify_test::AnyPullC"}.
-{{handle_info, "notify_test::AnyPullC"}, true}.
-{{impl, "notify_test::AnyPullC"}, "notify_test_impl"}.
-{this, "notify_test::SeqPushS"}.
-{{handle_info, "notify_test::SeqPushS"}, true}.
-{{impl, "notify_test::SeqPushS"}, "notify_test_impl"}.
-{this, "notify_test::StrPushS"}.
-{{handle_info, "notify_test::StrPushS"}, true}.
-{{impl, "notify_test::StrPushS"}, "notify_test_impl"}.
-{this, "notify_test::AnyPushS"}.
-{{handle_info, "notify_test::AnyPushS"}, true}.
-{{impl, "notify_test::AnyPushS"}, "notify_test_impl"}.
-{this, "notify_test::SeqPullS"}.
-{{handle_info, "notify_test::SeqPullS"}, true}.
-{{impl, "notify_test::SeqPullS"}, "notify_test_impl"}.
-{this, "notify_test::StrPullS"}.
-{{handle_info, "notify_test::StrPullS"}, true}.
-{{impl, "notify_test::StrPullS"}, "notify_test_impl"}.
-{this, "notify_test::AnyPullS"}.
-{{handle_info, "notify_test::AnyPullS"}, true}.
-{{impl, "notify_test::AnyPullS"}, "notify_test_impl"}.
diff --git a/lib/cosNotification/test/notify_test_server.idl b/lib/cosNotification/test/notify_test_server.idl
deleted file mode 100644
index 0334d67717..0000000000
--- a/lib/cosNotification/test/notify_test_server.idl
+++ /dev/null
@@ -1,114 +0,0 @@
-//
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1999-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-//
-
-#ifndef _NOTIFY_TEST_SERVER_IDL
-#define _NOTIFY_TEST_SERVER_IDL
-
-#include <CosNotification.idl>
-#include <CosNotifyComm.idl>
-
-module notify_test {
-
- enum action {PULL_SEQ, PULL_STR, PULL_ANY, PUSH_SEQ, PUSH_STR, PUSH_ANY};
-
- struct data {
- short score;
- string name;
- };
-
- struct computer {
- float memsize;
- float cputime;
- float filesize;
- };
-
- struct X {
- long A;
- string B;
- short C;
- };
-
-
- union K switch(short) {
- case -1: short neg;
- case 0:
- case 2: string K;
- case 3: X L;
- case 5: long M;
- default: short N;
- };
-
- union uni1 switch(long) {
- case 1:
- case 2: long lo;
- case 3: short sh;
- default: short defvalue;
- };
-
- union uni2 switch(long) {
- case 1:
- case 2: long lo;
- case 3: short sh;
- };
-
- typedef any namedAny;
- typedef short ShortArray[4];
- struct studies {
- uni1 uni1;
- CosNotification::PropertySeq tests;
- ShortArray monthly_attendance;
- short gpa;
- };
-
- interface funcs {
- void print();
- void doAction(in action Act);
- };
-
- // interface server
- interface SeqPushC : funcs, CosNotifyComm::SequencePushConsumer {
- };
- interface StrPushC : funcs, CosNotifyComm::StructuredPushConsumer {
- };
- interface AnyPushC : funcs, CosEventComm::PushConsumer {
- };
- interface SeqPullC : funcs, CosNotifyComm::SequencePullConsumer {
- };
- interface StrPullC : funcs, CosNotifyComm::StructuredPullConsumer {
- };
- interface AnyPullC : funcs, CosEventComm::PullConsumer {
- };
-
- interface SeqPushS : funcs, CosNotifyComm::SequencePushSupplier {
- };
- interface StrPushS : funcs, CosNotifyComm::StructuredPushSupplier {
- };
- interface AnyPushS : funcs, CosEventComm::PushSupplier {
- };
- interface SeqPullS : funcs, CosNotifyComm::SequencePullSupplier {
- };
- interface StrPullS : funcs, CosNotifyComm::StructuredPullSupplier {
- };
- interface AnyPullS : funcs, CosEventComm::PullSupplier {
- };
-
-};
-
-#endif
diff --git a/lib/cosNotification/vsn.mk b/lib/cosNotification/vsn.mk
deleted file mode 100644
index 0d95ab4853..0000000000
--- a/lib/cosNotification/vsn.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-COSNOTIFICATION_VSN = 1.2.2
-
diff --git a/lib/cosProperty/AUTHORS b/lib/cosProperty/AUTHORS
deleted file mode 100644
index 55d8059989..0000000000
--- a/lib/cosProperty/AUTHORS
+++ /dev/null
@@ -1,4 +0,0 @@
-Original Authors:
-Niclas Eklund
-
-Contributors:
diff --git a/lib/cosProperty/Makefile b/lib/cosProperty/Makefile
deleted file mode 100644
index 44d1aafade..0000000000
--- a/lib/cosProperty/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include vsn.mk
-VSN=$(COSPROPERTY_VSN)
-
-# ----------------------------------------------------
-# Common Macros
-# ----------------------------------------------------
-# SUB_DIRECTORIES = src test examples doc/src
-# At the moment we don't have any example programs.
-SUB_DIRECTORIES = src doc/src
-
-SPECIAL_TARGETS =
-
-# ----------------------------------------------------
-# Default Subdir Targets
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_subdir.mk
diff --git a/lib/cosProperty/doc/html/.gitignore b/lib/cosProperty/doc/html/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosProperty/doc/html/.gitignore
+++ /dev/null
diff --git a/lib/cosProperty/doc/man3/.gitignore b/lib/cosProperty/doc/man3/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosProperty/doc/man3/.gitignore
+++ /dev/null
diff --git a/lib/cosProperty/doc/man6/.gitignore b/lib/cosProperty/doc/man6/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosProperty/doc/man6/.gitignore
+++ /dev/null
diff --git a/lib/cosProperty/doc/pdf/.gitignore b/lib/cosProperty/doc/pdf/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosProperty/doc/pdf/.gitignore
+++ /dev/null
diff --git a/lib/cosProperty/doc/src/CosPropertyService_PropertiesIterator.xml b/lib/cosProperty/doc/src/CosPropertyService_PropertiesIterator.xml
deleted file mode 100644
index 62a1732e99..0000000000
--- a/lib/cosProperty/doc/src/CosPropertyService_PropertiesIterator.xml
+++ /dev/null
@@ -1,95 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosPropertyService_PropertiesIterator</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>2000-07-25</date>
- <rev>1.0</rev>
- </header>
- <module>CosPropertyService_PropertiesIterator</module>
- <modulesummary>This module implements the OMG CosPropertyService::PropertiesIterator interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosProperty/include/CosPropertyService.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>reset(Iterator) -> ok</name>
- <fsummary>Reset the position to the first property</fsummary>
- <type>
- <v>Iterator = #objref</v>
- </type>
- <desc>
- <p>This operation resets the position to the first property. </p>
- </desc>
- </func>
- <func>
- <name>next_one(Iterator) -> Reply</name>
- <fsummary>Return true if a Property exists at the current position and the out parameter is a valid Property. Otherwise false and a non-valid property</fsummary>
- <type>
- <v>Iterator = #objref</v>
- <v>Reply = {boolean(), #'CosPropertyService_Property'{property_name = Name, property_value = Value}}</v>
- <v>Name = string()</v>
- <v>Value = #any</v>
- </type>
- <desc>
- <p>This operation returns true . If false is returned the out
- parameter is a non-valid Property.</p>
- </desc>
- </func>
- <func>
- <name>next_n(Iterator, HowMany) -> Reply</name>
- <fsummary>Return true if the requested number of properties can be delivered and there are additional properties. Otherwise false is returned and a sequence of max <c>HowMany</c>properties</fsummary>
- <type>
- <v>Iterator = #objref</v>
- <v>HowMany = long()</v>
- <v>Reply = {boolean(), Properties}</v>
- <v>Properties = [#'CosPropertyService_Property'{property_name = Name, property_value = Value}]</v>
- <v>Name = string()</v>
- <v>Value = #any</v>
- </type>
- <desc>
- <p>This operation returns true if the requested number of properties can be
- delivered and there are additional properties. If false is returned and a
- sequence of max <c>HowMany</c> properties will be returned and no more
- properties can be delivered. </p>
- </desc>
- </func>
- <func>
- <name>destroy(Iterator) -> ok</name>
- <fsummary>Terminate the target object</fsummary>
- <type>
- <v>Iterator = #objref</v>
- </type>
- <desc>
- <p>This operation will terminate the Iterator and all subsequent calls
- will fail. </p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosProperty/doc/src/CosPropertyService_PropertyNamesIterator.xml b/lib/cosProperty/doc/src/CosPropertyService_PropertyNamesIterator.xml
deleted file mode 100644
index 5948490547..0000000000
--- a/lib/cosProperty/doc/src/CosPropertyService_PropertyNamesIterator.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosPropertyService_PropertyNamesIterator</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-07-25</date>
- <rev>1.0</rev>
- </header>
- <module>CosPropertyService_PropertyNamesIterator</module>
- <modulesummary>This module implements the OMG CosPropertyService::PropertyNamesIterator interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosProperty/include/CosPropertyService.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>reset(Iterator) -> ok</name>
- <fsummary>Reset the position to the first property name</fsummary>
- <type>
- <v>Iterator = #objref</v>
- </type>
- <desc>
- <p>This operation resets the position to the first property name. </p>
- </desc>
- </func>
- <func>
- <name>next_one(Iterator) -> Reply</name>
- <fsummary>Return true if a Property Name exists at the current position and the out parameter is a valid Property Name. Otherwise false and a non-valid Property Name</fsummary>
- <type>
- <v>Iterator = #objref</v>
- <v>Reply = {boolean(), Name}</v>
- <v>Name = string()</v>
- </type>
- <desc>
- <p>This operation returns true if a Property Name exists at the current
- position and the out parameter is a valid Property Name.
- If false is returned the out parameter is a non-valid Property Name.</p>
- </desc>
- </func>
- <func>
- <name>next_n(Iterator, HowMany) -> Reply</name>
- <fsummary>Return <c>HowMany</c>Property Names and a boolean which is true if additional Property Names exists</fsummary>
- <type>
- <v>Iterator = #objref</v>
- <v>HowMany = long()</v>
- <v>Reply = {boolean(), [Name]}</v>
- <v>Name = string()</v>
- </type>
- <desc>
- <p>This operation returns true if the requested number of Property Names can be
- delivered and there are additional property names. If false is returned a
- sequence of max <c>HowMany</c> property names will be returned and no
- more Property Names can be delivered. </p>
- </desc>
- </func>
- <func>
- <name>destroy(Iterator) -> ok</name>
- <fsummary>Terminate the target object</fsummary>
- <type>
- <v>Iterator = #objref</v>
- </type>
- <desc>
- <p>This operation will terminate the Iterator and all subsequent calls
- will fail. </p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosProperty/doc/src/CosPropertyService_PropertySet.xml b/lib/cosProperty/doc/src/CosPropertyService_PropertySet.xml
deleted file mode 100644
index 8e7fbbd80a..0000000000
--- a/lib/cosProperty/doc/src/CosPropertyService_PropertySet.xml
+++ /dev/null
@@ -1,201 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosPropertyService_PropertySet</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-07-25</date>
- <rev>1.0</rev>
- </header>
- <module>CosPropertyService_PropertySet</module>
- <modulesummary>This module implements the OMG CosPropertyService::PropertySet interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosProperty/include/CosPropertyService.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>define_property(PropertySet, Name, Value) -> Reply</name>
- <fsummary>Add a new property to the target object</fsummary>
- <type>
- <v>PropertySet = #objref</v>
- <v>Name = non-empty string()</v>
- <v>Value = #any</v>
- <v>Reply = ok | {'EXCEPTION', #CosPropertyService_InvalidPropertyName{}} | {'EXCEPTION', #CosPropertyService_ConflictingProperty{}} | {'EXCEPTION', #CosPropertyService_UnsupportedTypeCode{}} | {'EXCEPTION', #CosPropertyService_UnsupportedProperty{}} | {'EXCEPTION', #CosPropertyService_ReadOnlyProperty{}}</v>
- </type>
- <desc>
- <p>This operation adds a new property to the given object. Depending on
- which initial arguments was supplied when starting the object several
- exceptions may be raised.</p>
- </desc>
- </func>
- <func>
- <name>define_properties(PropertySet, Properties) -> Reply</name>
- <fsummary>Add new properties to the target object</fsummary>
- <type>
- <v>PropertySet = #objref</v>
- <v>Properties = [#'CosPropertyService_Property'{property_name = Name, property_value = Value}]</v>
- <v>Name = string()</v>
- <v>Value = #any</v>
- <v>Reply = ok | {'EXCEPTION', #CosPropertyService_MultipleExceptions{exceptions = Excs}}</v>
- <v>Excs = [#'CosPropertyService_PropertyException{reason = Reason, failing_property_name = Name}]</v>
- <v>Reason = invalid_property_name | conflicting_property | property_not_found | unsupported_type_code | unsupported_property | unsupported_mode | fixed_property | read_only_property</v>
- </type>
- <desc>
- <p>This operation adds several new properties to the given object. Depending on
- which initial arguments was supplied when starting the object an
- exceptions may be raised listing the properties failing.</p>
- </desc>
- </func>
- <func>
- <name>get_number_of_properties(PropertySet) -> ulong()</name>
- <fsummary>Get the number of properties associated with the target object</fsummary>
- <type>
- <v>PropertySet = #objref</v>
- </type>
- <desc>
- <p>This operation returns the number of properties associated with the target
- object.</p>
- </desc>
- </func>
- <func>
- <name>get_all_property_names(PropertySet, Max) -> Reply</name>
- <fsummary>Get <c>Max</c>property names. If the target object have additional associated properties they will be put in the returned Iterator</fsummary>
- <type>
- <v>PropertySet = NamesIterator = #objref</v>
- <v>Max = ulong()</v>
- <v>Reply = {ok, Names, NamesIterator}</v>
- <v>Names = [string()]</v>
- </type>
- <desc>
- <p>This operation returns up to <c>Max</c> property names. If the target
- object have additional associated properties they will be put in the
- returned Iterator, otherwise the Iterator will be a <c>NIL</c> object.</p>
- </desc>
- </func>
- <func>
- <name>get_property_value(PropertySet, Name) -> Reply</name>
- <fsummary>Return the property value associated with given name</fsummary>
- <type>
- <v>PropertySet = #objref</v>
- <v>Name = string()</v>
- <v>Reply = #any | {'EXCEPTION', #CosPropertyService_PropertyNotFound{}} | {'EXCEPTION', #CosPropertyService_InvalidPropertyName{}}</v>
- </type>
- <desc>
- <p>This operation returns the property value associated with given name. If no such property
- exists or the given name is an empty string an exception will be raised.</p>
- </desc>
- </func>
- <func>
- <name>get_properties(PropertySet, Names) -> Reply</name>
- <fsummary>Return all properties associated with given names</fsummary>
- <type>
- <v>PropertySet = #objref</v>
- <v>Names = [string()]</v>
- <v>Reply = {boolean(), Properties}</v>
- <v>Properties = [#'CosPropertyService_Property'{property_name = Name, property_value = Value}]</v>
- </type>
- <desc>
- <p>This operation returns all properties associated with given names. If the
- boolean flag is true all properties where retrieved correctly, otherwise,
- all properties with the type <c>tk_void</c> was not found.</p>
- </desc>
- </func>
- <func>
- <name>get_all_properties(PropertySet, Max) -> Reply</name>
- <fsummary>Return a list <c>Max</c>properties or less. If more properties are associated with the target object they will be put in the<c>PropertiesIterator</c>.</fsummary>
- <type>
- <v>PropertySet = PropertiesIterator = #objref</v>
- <v>Reply = {ok, Properties, PropertiesIterator}</v>
- <v>Properties = [#'CosPropertyService_Property'{property_name = Name, property_value = Value}]</v>
- </type>
- <desc>
- <p>This operation return a list <c>Max</c> properties or less. If more
- properties are associated with the target object they will be put in the
- <c>PropertiesIterator</c>. If the object had less than <c>Max</c>
- associated properties the Iterator will be a <c>NIL</c> object.</p>
- </desc>
- </func>
- <func>
- <name>delete_property(PropertySet, Name) -> Reply</name>
- <fsummary>Delete the property with given Name</fsummary>
- <type>
- <v>PropertySet = #objref</v>
- <v>Name = string()</v>
- <v>Reply = ok | {'EXCEPTION', #CosPropertyService_FixedProperty{}} | {'EXCEPTION', #CosPropertyService_PropertyNotFound{}} | {'EXCEPTION', #CosPropertyService_InvalidPropertyName{}}</v>
- </type>
- <desc>
- <p>This operation tries to delete the property with given Name. An exception
- which indicates why it failed is raised if so needed.</p>
- </desc>
- </func>
- <func>
- <name>delete_properties(PropertySet, Names) -> Reply</name>
- <fsummary>Delete all properties with given Names</fsummary>
- <type>
- <v>PropertySet = #objref</v>
- <v>Names = [string()]</v>
- <v>Reply = ok | {'EXCEPTION', #CosPropertyService_MultipleExceptions{exceptions = Excs}}</v>
- <v>Excs = [#'CosPropertyService_PropertyException{reason = Reason, failing_property_name = Name}]</v>
- <v>Reason = invalid_property_name | conflicting_property | property_not_found | unsupported_type_code | unsupported_property | unsupported_mode | fixed_property | read_only_property</v>
- </type>
- <desc>
- <p>This operation tries to delete all given Properties. If one or more removal
- fails an exception is raised which describe why.</p>
- </desc>
- </func>
- <func>
- <name>delete_all_properties(PropertySet) -> boolean()</name>
- <fsummary>Delete all properties</fsummary>
- <type>
- <v>PropertySet = #objref</v>
- </type>
- <desc>
- <p>This operation deletes all properties. The boolean flag, if set to false,
- indicates that it was not possible to remove one or more properties, e.g.,
- may be read only.</p>
- </desc>
- </func>
- <func>
- <name>is_property_defined(PropertySet, Name) -> Reply</name>
- <fsummary>Return true if the target have an associated property with given name</fsummary>
- <type>
- <v>PropertySet = #objref</v>
- <v>Name = non-empty string()</v>
- <v>Reply = boolean() | {'EXCEPTION', #CosPropertyService_InvalidPropertyName{}}</v>
- </type>
- <desc>
- <p>This operation returns true if the target have an associated property with
- given name.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosProperty/doc/src/CosPropertyService_PropertySetDef.xml b/lib/cosProperty/doc/src/CosPropertyService_PropertySetDef.xml
deleted file mode 100644
index 2cbf2fc4f9..0000000000
--- a/lib/cosProperty/doc/src/CosPropertyService_PropertySetDef.xml
+++ /dev/null
@@ -1,168 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosPropertyService_PropertySetDef</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>2000-07-25</date>
- <rev>1.0</rev>
- </header>
- <module>CosPropertyService_PropertySetDef</module>
- <modulesummary>This module implements the OMG CosPropertyService::PropertySetDef interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosProperty/include/CosPropertyService.hrl").</c></p>
- <p>This module also exports the functions described in</p>
- <p><seealso marker="CosPropertyService_PropertySet">CosPropertyService_PropertySet</seealso></p>
- </description>
- <funcs>
- <func>
- <name>get_allowed_property_types(PropertySetDef) -> Reply</name>
- <fsummary>Return allowed TypeCodes for the target object</fsummary>
- <type>
- <v>PropertySetDef = #objref</v>
- <v>Reply = {ok, PropertyTypes}</v>
- <v>PropertyTypes = [CORBA::TypeCode]</v>
- </type>
- <desc>
- <p>This operation return the TypeCodes which we are allowed to use when adding
- new properties.</p>
- </desc>
- </func>
- <func>
- <name>get_allowed_properties(PropertySetDef) -> Reply</name>
- <fsummary>Return a sequence of the allowed properties</fsummary>
- <type>
- <v>PropertySetDef = #objref</v>
- <v>Reply = {ok, PropertyDefs}</v>
- <v>PropertyDefs = [#'CosPropertyService_PropertyDef'{property_name = Name, property_value = Value, property_mode = Mode}]</v>
- <v>Name = string()</v>
- <v>Value = #any</v>
- <v>Mode = normal | read_only | fixed_normal | fixed_readonly | undefined</v>
- </type>
- <desc>
- <p>This operation a sequence of the allowed properties we may alter; depends on
- which mode associated with a certain property.</p>
- </desc>
- </func>
- <func>
- <name>define_property_with_mode(PropertySetDef, Name, Value, Mode) -> Reply</name>
- <fsummary>Associate a new property with the target object</fsummary>
- <type>
- <v>PropertySetDef = #objref</v>
- <v>Name = non-empty string()</v>
- <v>Value = #any</v>
- <v>Mode = normal | read_only | fixed_normal | fixed_readonly | undefined</v>
- <v>Reply = ok | {'EXCEPTION', #CosPropertyService_InvalidPropertyName{}} | {'EXCEPTION', #CosPropertyService_ConflictingProperty{}} | {'EXCEPTION', #CosPropertyService_UnsupportedTypeCode{}} | {'EXCEPTION', #CosPropertyService_UnsupportedProperty{}} | {'EXCEPTION', #CosPropertyService_UnsupportedMode{}} | {'EXCEPTION', #CosPropertyService_ReadOnlyProperty{}}</v>
- </type>
- <desc>
- <p>This operation attempts to associate a new property with the target object.
- If we fail to do so the appropriate exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>define_properties_with_modes(PropertySetDef, PropertyDefs) -> Reply</name>
- <fsummary>Associate the given Property Definitions with the target object</fsummary>
- <type>
- <v>PropertySetDef = #objref</v>
- <v>PropertyDefs = [#'CosPropertyService_PropertyDef'{property_name = Name, property_value = Value, property_mode = Mode}]</v>
- <v>Name = string()</v>
- <v>Value = #any</v>
- <v>Mode = normal | read_only | fixed_normal | fixed_readonly | undefined</v>
- <v>Reply = ok | {'EXCEPTION', #CosPropertyService_MultipleExceptions{exceptions = Excs}}</v>
- <v>Excs = [#'CosPropertyService_PropertyException{reason = Reason, failing_property_name = Name}]</v>
- <v>Reason = invalid_property_name | conflicting_property | property_not_found | unsupported_type_code | unsupported_property | unsupported_mode | fixed_property | read_only_property</v>
- </type>
- <desc>
- <p>This operation attempts to associate the given Property Definitions with the
- target object. If one or more attempts fail an exception is raised
- describing which properties we where not able to create.</p>
- </desc>
- </func>
- <func>
- <name>get_property_mode(PropertySetDef, Name) -> Reply</name>
- <fsummary>Return the mode of the given property</fsummary>
- <type>
- <v>PropertySetDef = #objref</v>
- <v>Name = string()</v>
- <v>Reply = Mode | {'EXCEPTION', #CosPropertyService_InvalidPropertyName{}} | {'EXCEPTION', #CosPropertyService_PropertyNotFound{}}</v>
- <v>Mode = normal | read_only | fixed_normal | fixed_readonly | undefined</v>
- </type>
- <desc>
- <p>This operation returns the type of the given property.</p>
- </desc>
- </func>
- <func>
- <name>get_property_modes(PropertySetDef, Names) -> Reply</name>
- <fsummary>Return the modes of the given properties</fsummary>
- <type>
- <v>PropertySetDef = #objref</v>
- <v>Names = [string()]</v>
- <v>Reply = {boolean(), PropertyModes}</v>
- <v>PropertyModes = [#'CosPropertyService_PropertyMode'{property_name = Name, property_mode = Mode}]</v>
- <v>Name = string()</v>
- <v>Mode = normal | read_only | fixed_normal | fixed_readonly | undefined</v>
- </type>
- <desc>
- <p>This operation returns the modes of the listed properties. If the boolean
- flag is false, all properties with mode <c>undefined</c> this operation
- failed to comply.</p>
- </desc>
- </func>
- <func>
- <name>set_property_mode(PropertySetDef, Name, Mode) -> Reply</name>
- <fsummary>Change the given property's mode</fsummary>
- <type>
- <v>PropertySetDef = #objref</v>
- <v>Name = string()</v>
- <v>Mode = normal | read_only | fixed_normal | fixed_readonly | undefined</v>
- <v>Reply = ok | {'EXCEPTION', #CosPropertyService_InvalidPropertyName{}} | {'EXCEPTION', #CosPropertyService_UnsupportedMode{}} | {'EXCEPTION', #CosPropertyService_PropertyNotFound{}}</v>
- </type>
- <desc>
- <p>This operation changes the given property's mode. Return the appropriate
- exception if not able to fulfill the request.</p>
- </desc>
- </func>
- <func>
- <name>set_property_modes(PropertySetDef, PropertyModes) -> Reply</name>
- <fsummary>Change the listed properties mode's</fsummary>
- <type>
- <v>PropertySetDef = #objref</v>
- <v>PropertyModes = [#'CosPropertyService_PropertyMode'{property_name = Name, property_mode = Mode}]</v>
- <v>Name = string()</v>
- <v>Mode = normal | read_only | fixed_normal | fixed_readonly | undefined</v>
- <v>Reply = ok | {'EXCEPTION', #CosPropertyService_MultipleExceptions{exceptions = Excs}}</v>
- <v>Excs = [#'CosPropertyService_PropertyException{reason = Reason, failing_property_name = Name}]</v>
- <v>Reason = invalid_property_name | conflicting_property | property_not_found | unsupported_type_code | unsupported_property | unsupported_mode | fixed_property | read_only_property</v>
- </type>
- <desc>
- <p>This operation attempts to update the listed properties mode's. Raises an
- exception which describe which and why an operation failed.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosProperty/doc/src/CosPropertyService_PropertySetDefFactory.xml b/lib/cosProperty/doc/src/CosPropertyService_PropertySetDefFactory.xml
deleted file mode 100644
index d6425db9cf..0000000000
--- a/lib/cosProperty/doc/src/CosPropertyService_PropertySetDefFactory.xml
+++ /dev/null
@@ -1,95 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosPropertyService_PropertySetDefFactory</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2000-07-25</date>
- <rev>1.0</rev>
- </header>
- <module>CosPropertyService_PropertySetDefFactory</module>
- <modulesummary>This module implements the OMG CosPropertyService::PropertySetDefFactory interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosProperty/include/CosPropertyService.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>create_propertysetdef(Factory) -> </name>
- <fsummary>Create a new <c>PropertySetDef</c>with no predefined settings</fsummary>
- <type>
- <v>Factory = PropertySetDef = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new <c>PropertySetDef</c> with no predefined
- settings.</p>
- </desc>
- </func>
- <func>
- <name>create_constrained_propertysetdef(Factory, PropertyTypes, PropertyDefs) -> Reply</name>
- <fsummary>Create a new <c>PropertySetDef</c>with specified constraints</fsummary>
- <type>
- <v>Factory = PropertySetDef = #objref</v>
- <v>PropertyTypes = [CORBA::TypeCode]</v>
- <v>PropertyDefs = [#'CosPropertyService_PropertyDef'{property_name = Name, property_value = Value, property_mode = Mode}]</v>
- <v>Name = string()</v>
- <v>Value = #any</v>
- <v>Mode = normal | read_only | fixed_normal | fixed_readonly | undefined</v>
- <v>Reply = {'EXCEPTION', #CosPropertyService_ConstraintNotSupported{}} | PropertySetDef</v>
- <v>PropertySetDef = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new <c>PropertySetDef</c> with specific
- constraints. PropertyTypes states allowed TypeCode's and PropertyDefs valid
- <c>CosPropertyService::PropertyDef</c> data.</p>
- </desc>
- </func>
- <func>
- <name>create_initial_propertysetdef(Factory, PropertyDefs) -> Reply</name>
- <fsummary>Create a new <c>PropertySetDef</c>with specified initial properties</fsummary>
- <type>
- <v>Factory = PropertySetDef = #objref</v>
- <v>PropertyDefs = [#'CosPropertyService_PropertyDef'{property_name = Name, property_value = Value, property_mode = Mode}]</v>
- <v>Name = string()</v>
- <v>Value = #any</v>
- <v>Mode = normal | read_only | fixed_normal | fixed_readonly | undefined</v>
- <v>Reply = {'EXCEPTION', #CosPropertyService_MultipleExceptions{exceptions = Excs}} | PropertySetDef</v>
- <v>Excs = [#'CosPropertyService_PropertyException{reason = Reason, failing_property_name = Name}]</v>
- <v>Reason = invalid_property_name | conflicting_property | property_not_found | unsupported_type_code | unsupported_property | unsupported_mode | fixed_property | read_only_property</v>
- <v>PropertySetDef = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new <c>PropertySetDef</c> with specific
- initial properties.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosProperty/doc/src/CosPropertyService_PropertySetFactory.xml b/lib/cosProperty/doc/src/CosPropertyService_PropertySetFactory.xml
deleted file mode 100644
index 0aa22dd716..0000000000
--- a/lib/cosProperty/doc/src/CosPropertyService_PropertySetFactory.xml
+++ /dev/null
@@ -1,93 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosPropertyService_PropertySetFactory</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-07-25</date>
- <rev>1.0</rev>
- </header>
- <module>CosPropertyService_PropertySetFactory</module>
- <modulesummary>This module implements the OMG CosPropertyService::PropertySetFactory interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosProperty/include/CosPropertyService.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>create_propertyset(Factory) -> PropertySet</name>
- <fsummary>Create a new <c>PropertySe</c>t with no predefined properties</fsummary>
- <type>
- <v>Factory = PropertySet = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new <c>PropertySe</c>t with no predefined
- properties.</p>
- </desc>
- </func>
- <func>
- <name>create_constrained_propertyset(Factory, PropertyTypes, Properties) -> Reply</name>
- <fsummary>Create a new <c>PropertySet</c>with specified constraints</fsummary>
- <type>
- <v>Factory = #objref</v>
- <v>PropertyTypes = [CORBA::TypeCode]</v>
- <v>Properties = [#'CosPropertyService_Property'{property_name = Name, property_value = Value}]</v>
- <v>Name = string()</v>
- <v>Value = #any</v>
- <v>Reply = {'EXCEPTION', #CosPropertyService_ConstraintNotSupported{}} | PropertySet</v>
- <v>PropertySet = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new <c>PropertySet</c> with specific constraints.
- PropertyTypes states allowed TypeCode's and Properties valid
- <c>CosPropertyService::Property</c> data.</p>
- </desc>
- </func>
- <func>
- <name>create_initial_propertyset(Factory, Properties) -> Reply</name>
- <fsummary>Create a new <c>PropertySet</c>with specified initial properties</fsummary>
- <type>
- <v>Factory = #objref</v>
- <v>Properties = [#'CosPropertyService_Property'{property_name = Name, property_value = Value}]</v>
- <v>Name = string()</v>
- <v>Value = #any</v>
- <v>Reply = {'EXCEPTION', #CosPropertyService_MultipleExceptions{exceptions = Excs}} | PropertySet</v>
- <v>Excs = [#'CosPropertyService_PropertyException{reason = Reason, failing_property_name = Name}]</v>
- <v>Reason = invalid_property_name | conflicting_property | property_not_found | unsupported_type_code | unsupported_property | unsupported_mode | fixed_property | read_only_property</v>
- <v>PropertySet = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new <c>PropertySet</c> with specific
- initial properties.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosProperty/doc/src/Makefile b/lib/cosProperty/doc/src/Makefile
deleted file mode 100644
index 6b210500f9..0000000000
--- a/lib/cosProperty/doc/src/Makefile
+++ /dev/null
@@ -1,149 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(COSPROPERTY_VSN)
-APPLICATION=cosProperty
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = \
- cosProperty.xml \
- CosPropertyService_PropertySetFactory.xml \
- CosPropertyService_PropertySetDefFactory.xml \
- CosPropertyService_PropertySet.xml \
- CosPropertyService_PropertySetDef.xml \
- CosPropertyService_PropertiesIterator.xml \
- CosPropertyService_PropertyNamesIterator.xml
-
-XML_REF6_FILES =
-
-XML_PART_FILES = \
- part.xml \
- part_notes.xml
-XML_CHAPTER_FILES = \
- ch_contents.xml \
- ch_introduction.xml \
- ch_install.xml \
- ch_example.xml \
- notes.xml
-
-BOOK_FILES = book.xml
-
-XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \
- $(XML_PART_FILES) $(XML_CHAPTER_FILES)
-
-TECHNICAL_DESCR_FILES =
-
-GIF_FILES = \
- book.gif \
- notes.gif \
- ref_man.gif \
- user_guide.gif
-
-PS_FILES =
-
-# ----------------------------------------------------
-
-INTERNAL_HTML_FILES = $(TECHNICAL_DESCR_FILES:%.xml=$(HTMLDIR)/%.html)
-
-HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
-
-INFO_FILE = ../../info
-
-EXTRA_FILES = summary.html.src \
- $(DEFAULT_GIF_FILES) \
- $(DEFAULT_HTML_FILES) \
- $(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_REF6_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html)
-
-MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-MAN6_FILES = $(XML_REF6_FILES:%.xml=$(MAN6DIR)/%.6)
-
-HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
-
-TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-$(HTMLDIR)/%.gif: %.gif
- $(INSTALL_DATA) $< $@
-
-docs: pdf html man
-
-$(TOP_PDF_FILE): $(XML_FILES)
-
-pdf: $(TOP_PDF_FILE)
-
-html: gifs $(HTML_REF_MAN_FILE)
-
-clean clean_docs:
- rm -rf $(HTMLDIR)/*
- rm -f $(MAN3DIR)/*
- rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
-
-man: $(MAN3_FILES) $(MAN6_FILES)
-
-gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-
-$(INDEX_TARGET): $(INDEX_SRC)
- sed -e 's;%VSN%;$(VSN);' $(INDEX_SRC) > $(INDEX_TARGET)
-
-debug opt:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_docs_spec: docs
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(HTMLDIR)/* \
- "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
- $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
-
-release_spec:
diff --git a/lib/cosProperty/doc/src/book.gif b/lib/cosProperty/doc/src/book.gif
deleted file mode 100644
index 94b3868792..0000000000
--- a/lib/cosProperty/doc/src/book.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosProperty/doc/src/book.xml b/lib/cosProperty/doc/src/book.xml
deleted file mode 100644
index 9ee681b057..0000000000
--- a/lib/cosProperty/doc/src/book.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book xmlns:xi="http://www.w3.org/2001/XInclude">
- <header titlestyle="normal">
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosProperty</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-06-07</date>
- <rev>1.0</rev>
- </header>
- <insidecover>
- </insidecover>
- <pagetext>cosProperty</pagetext>
- <preamble>
- <contents level="2"></contents>
- </preamble>
- <parts lift="no">
- <xi:include href="part.xml"/>
- </parts>
- <applications>
- <xi:include href="ref_man.xml"/>
- </applications>
- <releasenotes>
- <xi:include href="notes.xml"/>
- </releasenotes>
- <listofterms></listofterms>
- <index></index>
-</book>
-
diff --git a/lib/cosProperty/doc/src/ch_contents.xml b/lib/cosProperty/doc/src/ch_contents.xml
deleted file mode 100644
index 5c3112a644..0000000000
--- a/lib/cosProperty/doc/src/ch_contents.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>The cosProperty Application</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-06-07</date>
- <rev>1.0</rev>
- <file>ch_contents.xml</file>
- </header>
-
- <section>
- <title>Content Overview</title>
- <p>The cosProperty documentation is divided into three sections:
- </p>
- <list type="bulleted">
- <item>
- <p>PART ONE - The User's Guide
- <br></br>
-Description of the cosProperty Application including
- services and a small tutorial demonstrating
- the development of a simple service.</p>
- </item>
- <item>
- <p>PART TWO - Release Notes
- <br></br>
-A concise history of cosProperty.</p>
- </item>
- <item>
- <p>PART THREE - The Reference Manual
- <br></br>
- A quick reference guide, including a
- brief description, to all the functions available in cosProperty.</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Brief description of the User's Guide</title>
- <p>The User's Guide contains the following parts:</p>
- <list type="bulleted">
- <item>
- <p>cosProperty overview</p>
- </item>
- <item>
- <p>cosProperty installation</p>
- </item>
- <item>
- <p>A tutorial example</p>
- </item>
- </list>
- </section>
-</chapter>
-
diff --git a/lib/cosProperty/doc/src/ch_example.xml b/lib/cosProperty/doc/src/ch_example.xml
deleted file mode 100644
index da13af2312..0000000000
--- a/lib/cosProperty/doc/src/ch_example.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosProperty Examples</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-06-07</date>
- <rev>A</rev>
- <file>ch_example.xml</file>
- </header>
-
- <section>
- <title>A tutorial on how to create a simple service</title>
-
- <section>
- <title>Initiate the application</title>
- <p>To use the cosProperty application Orber must be running.</p>
- </section>
-
- <section>
- <title>How to run everything</title>
- <p>Below is a short transcript on how to run cosProperty. </p>
- <code type="none">
-
-%% Start Mnesia and Orber
-mnesia:delete_schema([node()]),
-mnesia:create_schema([node()]),
-orber:install([node()]),
-mnesia:start(),
-orber:start(),
-
-%% Install Property Service in the IFR.
-cosProperty:install(),
-
-%% Install Property Service in mnesia.
-cosProperty:install_db(),
-
-%% Now start the application.
-cosProperty:start(),
-
-%% To be able to create Property objects we must first a Factory
-%% of our preferred type.
-Fac = cosProperty:start_SetDefFactory(),
-
-%% Now we can create a Property object.
-'CosPropertyService_PropertySetDefFactory':
- create_propertysetdef(Fac),
-
-%% Now we can create any allowed properties. There are many
-%% options which are all described further in the documentation.
- </code>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosProperty/doc/src/ch_install.xml b/lib/cosProperty/doc/src/ch_install.xml
deleted file mode 100644
index a1aa2914b4..0000000000
--- a/lib/cosProperty/doc/src/ch_install.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Installing cosProperty</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-06-07</date>
- <rev></rev>
- <file>ch-install.xml</file>
- </header>
-
- <section>
- <title>Installation Process</title>
- <p>This chapter describes how to install
- <seealso marker="cosProperty">cosProperty</seealso> in an Erlang Environment.
- </p>
-
- <section>
- <title>Preparation</title>
- <p>Before starting the installation process for cosProperty,
- the application Orber must be running.</p>
- </section>
-
- <section>
- <title>Configuration</title>
- <p>First the cosProperty application must be installed by using
- <c>cosProperty:install()</c> and, if requested, <c>cosProperty:install_db()</c>,
- followed by <c>cosProperty:start()</c>.
- Now we can start the desired Factory type by using either
- <c>cosProperty:start_SetFactory()</c> or
- <c>cosProperty:start_SetDefFactory()</c>.</p>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosProperty/doc/src/ch_introduction.xml b/lib/cosProperty/doc/src/ch_introduction.xml
deleted file mode 100644
index 03ef6f619c..0000000000
--- a/lib/cosProperty/doc/src/ch_introduction.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Introduction to cosProperty</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-06-07</date>
- <rev></rev>
- <file>ch_introduction.xml</file>
- </header>
-
- <section>
- <title>Overview</title>
- <p>The cosProperty application is compliant with the <url href="http://www.omg.org">OMG</url>
- Service CosProperty Service.
- </p>
-
- <section>
- <title>Purpose and Dependencies</title>
- <p><em>cosProperty</em> is dependent on <em>Orber</em>, which provides CORBA functionality in an Erlang environment.</p>
- </section>
-
- <section>
- <title>Prerequisites</title>
- <p>To fully understand the concepts presented in the
- documentation, it is recommended that the user is familiar
- with distributed programming, CORBA and the Orber application.
- </p>
- <p>Recommended reading includes <em>CORBA, Fundamentals and Programming - Jon Siegel</em> and <em>Open Telecom Platform Documentation Set</em>. It is also helpful to have read <em>Concurrent Programming in Erlang</em>.</p>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosProperty/doc/src/cosProperty.xml b/lib/cosProperty/doc/src/cosProperty.xml
deleted file mode 100644
index d9310b3113..0000000000
--- a/lib/cosProperty/doc/src/cosProperty.xml
+++ /dev/null
@@ -1,150 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosProperty</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>2000-06-07</date>
- <rev>PA1</rev>
- </header>
- <module>cosProperty</module>
- <modulesummary>The main module of the cosProperty application</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosProperty/include/*.hrl").</c></p>
- <p>This module contains the functions for starting and stopping the application.</p>
- </description>
- <funcs>
- <func>
- <name>install() -> Return</name>
- <fsummary>Install the cosProperty application in the IFR</fsummary>
- <type>
- <v>Return = ok | {'EXIT', Reason}</v>
- </type>
- <desc>
- <p>This operation installs the cosProperty application in the IFR.</p>
- </desc>
- </func>
- <func>
- <name>install_db() -> Return</name>
- <fsummary>Install data in mnesia necessary for running the cosProperty application</fsummary>
- <type>
- <v>Return = ok | {'EXIT', Reason}</v>
- </type>
- <desc>
- <p>This operation installs data in mnesia necessary for running the
- cosProperty application.</p>
- </desc>
- </func>
- <func>
- <name>uninstall() -> Return</name>
- <fsummary>Remove all data in the IFR related to the cosProperty application</fsummary>
- <type>
- <v>Return = ok | {'EXIT', Reason}</v>
- </type>
- <desc>
- <p>This operation removes all data in the IFR related to the cosProperty
- application.</p>
- </desc>
- </func>
- <func>
- <name>uninstall_db() -> Return</name>
- <fsummary>Remove all data from mnesia related to the cosProperty application</fsummary>
- <type>
- <v>Return = ok | {'EXIT', Reason}</v>
- </type>
- <desc>
- <p>This operation removes all data from mnesia related to the cosProperty
- application.</p>
- </desc>
- </func>
- <func>
- <name>start() -> Return</name>
- <fsummary>Start the cosProperty application</fsummary>
- <type>
- <v>Return = ok | {error, Reason}</v>
- </type>
- <desc>
- <p>This operation starts the cosProperty application.</p>
- </desc>
- </func>
- <func>
- <name>start_SetDefFactory() -> Return</name>
- <fsummary>Start a PropertySetDef Factory</fsummary>
- <type>
- <v>Return = Factory | {'EXCEPTION', E}</v>
- <v>Factory = CosPropertyService::PropertySetDefFactory reference.</v>
- </type>
- <desc>
- <p>This operation starts a PropertySetDef Factory.</p>
- </desc>
- </func>
- <func>
- <name>start_SetFactory() -> Return</name>
- <fsummary>Start a PropertySet Factory</fsummary>
- <type>
- <v>Return = Factory | {'EXCEPTION', E}</v>
- <v>Factory = CosPropertyService::PropertySetDefFactory reference.</v>
- </type>
- <desc>
- <p>This operation starts a PropertySet Factory.</p>
- </desc>
- </func>
- <func>
- <name>stop_SetDefFactory(Factory) -> Return</name>
- <fsummary>Stop the given PropertySetDef Factory</fsummary>
- <type>
- <v>Factory = CosPropertyService::PropertySetDefFactory reference.</v>
- <v>Return = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This operation stops the supplied PropertySetDef Factory.</p>
- </desc>
- </func>
- <func>
- <name>stop_SetFactory(Factory) -> Return</name>
- <fsummary>Stop the given PropertySet Factory</fsummary>
- <type>
- <v>Factory = CosPropertyService::PropertySetFactory reference.</v>
- <v>Return = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This operation stops the supplied PropertySet Factory.</p>
- </desc>
- </func>
- <func>
- <name>stop() -> Return</name>
- <fsummary>Stop the cosProperty application</fsummary>
- <type>
- <v>Return = ok | {error, Reason}</v>
- </type>
- <desc>
- <p>This operation stops the cosProperty application.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosProperty/doc/src/fascicules.xml b/lib/cosProperty/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/cosProperty/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/cosProperty/doc/src/notes.gif b/lib/cosProperty/doc/src/notes.gif
deleted file mode 100644
index e000cca26a..0000000000
--- a/lib/cosProperty/doc/src/notes.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosProperty/doc/src/notes.xml b/lib/cosProperty/doc/src/notes.xml
deleted file mode 100644
index e5d22982c5..0000000000
--- a/lib/cosProperty/doc/src/notes.xml
+++ /dev/null
@@ -1,362 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosProperty Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-06-07</date>
- <rev>A</rev>
- <file>notes.xml</file>
- </header>
-
-
- <section><title>cosProperty 1.2.2</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Fix dialyzer warnings.</p>
- <p>
- Own Id: OTP-14006</p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>cosProperty 1.2.1</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Internal changes</p>
- <p>
- Own Id: OTP-13551</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosProperty 1.2</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> Remove the usage of erlang:now() from all Corba
- applications and use the new rand module instead of
- random. </p>
- <p>
- Own Id: OTP-12687</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosProperty 1.1.17</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> The default encoding of Erlang files has been changed
- from ISO-8859-1 to UTF-8. </p> <p> The encoding of XML
- files has also been changed to UTF-8. </p>
- <p>
- Own Id: OTP-10907</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosProperty 1.1.16</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Misc build updates</p>
- <p>
- Own Id: OTP-10784</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosProperty 1.1.15</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>Erlang/OTP can now be built using parallel make if you
- limit the number of jobs, for instance using '<c>make
- -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
- work at the moment because of some missing
- dependencies.</p>
- <p>
- Own Id: OTP-9451</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section>
- <title>cosProperty 1.1.14</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Removed superfluous usage of shy in the documentation since it can cause problem if
- a buggy tool is used.</p>
- <p>
- Own Id: OTP-9319 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosProperty 1.1.13</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Eliminated Dialyzer warnings when using exit or throw.</p>
- <p>Own id: OTP-9050 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosProperty 1.1.12</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>Test suites published.</p>
- <p>Own id: OTP-8543 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosProperty 1.1.11</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The documentation EIX file was not generated.</p>
- <p>Own id: OTP-8355 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosProperty 1.1.10</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- The documentation is now built with open source tools (xsltproc and fop)
- that exists on most platforms. One visible change is that the frames are removed.</p>
- <p>
- Own Id: OTP-8201 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosProperty 1.1.9</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Obsolete guards, e.g. record vs is_record, has been changed
- to avoid compiler warnings.</p>
- <p>Own id: OTP-7987</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosProperty 1.1.8</title>
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Updated file headers.</p>
- <p>Own id: OTP-7837</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosProperty 1.1.7</title>
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Documentation source included in open source releases.</p>
- <p>Own id: OTP-7595</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosProperty 1.1.6</title>
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Updated file headers.</p>
- <p>Own id: OTP-7011</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosProperty 1.1.5</title>
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The documentation source has been converted from SGML to XML.</p>
- <p>Own Id: OTP-6754 Aux Id: </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosProperty 1.1.4</title>
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Minor Makefile changes.</p>
- <p>Own Id: OTP-6701 Aux Id: </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosProperty 1.1.3</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The appup source file was missing a trailing newline.</p>
- <p>Own id: OTP-6626</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosProperty 1.1.2</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Removed some unused code.</p>
- <p>Own Id: OTP-6527 Aux Id: </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosProperty 1.1.1</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The app-file contained duplicated modules.</p>
- <p>Own id: OTP-4976</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosProperty 1.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The stub/skeleton-files generated by IC have been improved,
- i.e., depending on the IDL-files, reduced the size of the
- erl- and beam-files and decreased dependencies off Orber's
- Interface Repository. It is necessary to re-compile all IDL-files
- and use COS-applications, including Orber, compiled with
- IC-4.2.</p>
- <p>Own id: OTP-4576</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosProperty 1.0.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>First release of the cosProperty application.</p>
- <p>Own Id: -</p>
- </item>
- </list>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosProperty/doc/src/part.xml b/lib/cosProperty/doc/src/part.xml
deleted file mode 100644
index 9d28c6dda4..0000000000
--- a/lib/cosProperty/doc/src/part.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosProperty User's Guide</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-06-07</date>
- <rev>1.0</rev>
- </header>
- <description>
- <p>The cosProperty Application is an Erlang implementation of the OMG
- CORBA Property Service.</p>
- </description>
- <xi:include href="ch_contents.xml"/>
- <xi:include href="ch_introduction.xml"/>
- <xi:include href="ch_install.xml"/>
- <xi:include href="ch_example.xml"/>
-</part>
-
diff --git a/lib/cosProperty/doc/src/part_notes.xml b/lib/cosProperty/doc/src/part_notes.xml
deleted file mode 100644
index bb3221e41c..0000000000
--- a/lib/cosProperty/doc/src/part_notes.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosProperty Release Notes</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-06-07</date>
- <rev>1.0</rev>
- </header>
- <description>
- <p>The cosProperty Application is an Erlang implementation of the OMG
- CORBA Property Service.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/cosProperty/doc/src/ref_man.gif b/lib/cosProperty/doc/src/ref_man.gif
deleted file mode 100644
index b13c4efd53..0000000000
--- a/lib/cosProperty/doc/src/ref_man.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosProperty/doc/src/ref_man.xml b/lib/cosProperty/doc/src/ref_man.xml
deleted file mode 100644
index a315c0285f..0000000000
--- a/lib/cosProperty/doc/src/ref_man.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE application SYSTEM "application.dtd">
-
-<application xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosProperty Reference Manual</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-06-07</date>
- <rev>1.0</rev>
- </header>
- <description>
- <p>The cosProperty Application is an Erlang implementation of the OMG
- CORBA Property Service.</p>
- </description>
- <xi:include href="cosProperty.xml"/>
- <xi:include href="CosPropertyService_PropertySetFactory.xml"/>
- <xi:include href="CosPropertyService_PropertySetDefFactory.xml"/>
- <xi:include href="CosPropertyService_PropertySet.xml"/>
- <xi:include href="CosPropertyService_PropertySetDef.xml"/>
- <xi:include href="CosPropertyService_PropertiesIterator.xml"/>
- <xi:include href="CosPropertyService_PropertyNamesIterator.xml"/>
-</application>
-
diff --git a/lib/cosProperty/doc/src/summary.html.src b/lib/cosProperty/doc/src/summary.html.src
deleted file mode 100644
index 87370c659c..0000000000
--- a/lib/cosProperty/doc/src/summary.html.src
+++ /dev/null
@@ -1 +0,0 @@
-Orber OMG Property Service. \ No newline at end of file
diff --git a/lib/cosProperty/doc/src/user_guide.gif b/lib/cosProperty/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/cosProperty/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosProperty/ebin/.gitignore b/lib/cosProperty/ebin/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosProperty/ebin/.gitignore
+++ /dev/null
diff --git a/lib/cosProperty/examples/.gitignore b/lib/cosProperty/examples/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosProperty/examples/.gitignore
+++ /dev/null
diff --git a/lib/cosProperty/include/.gitignore b/lib/cosProperty/include/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosProperty/include/.gitignore
+++ /dev/null
diff --git a/lib/cosProperty/info b/lib/cosProperty/info
deleted file mode 100644
index 67c56e92ed..0000000000
--- a/lib/cosProperty/info
+++ /dev/null
@@ -1,2 +0,0 @@
-group: orb
-short: Orber OMG Property Service
diff --git a/lib/cosProperty/priv/.gitignore b/lib/cosProperty/priv/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosProperty/priv/.gitignore
+++ /dev/null
diff --git a/lib/cosProperty/src/CosProperty.cfg b/lib/cosProperty/src/CosProperty.cfg
deleted file mode 100644
index f10bf843d6..0000000000
--- a/lib/cosProperty/src/CosProperty.cfg
+++ /dev/null
@@ -1,5 +0,0 @@
-{this, "CosPropertyService::PropertySet"}.
-{this, "CosPropertyService::PropertySetDef"}.
-{this, "CosPropertyService::PropertySetDefFactory"}.
-{this, "CosPropertyService::PropertySetFactory"}.
-
diff --git a/lib/cosProperty/src/CosProperty.idl b/lib/cosProperty/src/CosProperty.idl
deleted file mode 100644
index 156fb37ccc..0000000000
--- a/lib/cosProperty/src/CosProperty.idl
+++ /dev/null
@@ -1,192 +0,0 @@
-#ifndef _COSPROPERTY_IDL
-#define _COSPROPERTY_IDL
-
-#pragma prefix "omg.org"
-
-module CosPropertyService {
- /*****************************************************/
- /* Data Types */
- /*****************************************************/
- typedef string PropertyName;
-
- struct Property {
- PropertyName property_name;
- any property_value;
- };
-
- enum PropertyModeType {
- normal, read_only, fixed_normal, fixed_readonly, undefined };
-
- struct PropertyDef {
- PropertyName property_name;
- any property_value;
- PropertyModeType property_mode;
- };
-
- struct PropertyMode {
- PropertyName property_name;
- PropertyModeType property_mode;
- };
-
- typedef sequence<PropertyName> PropertyNames;
- typedef sequence<Property> Properties;
- typedef sequence<PropertyDef> PropertyDefs;
- typedef sequence<PropertyMode> PropertyModes;
- typedef sequence<CORBA::TypeCode> PropertyTypes;
-
- interface PropertyNamesIterator;
- interface PropertiesIterator;
- interface PropertySetFactory;
- interface PropertySetDef;
- interface PropertySet;
-
- /*****************************************************/
- /* Exceptions */
- /*****************************************************/
- exception ConstraintNotSupported{};
- exception InvalidPropertyName {};
- exception ConflictingProperty {};
- exception PropertyNotFound {};
- exception UnsupportedTypeCode {};
- exception UnsupportedProperty {};
- exception UnsupportedMode {};
- exception FixedProperty {};
- exception ReadOnlyProperty {};
-
- enum ExceptionReason { invalid_property_name, conflicting_property,
- property_not_found, unsupported_type_code,
- unsupported_property, unsupported_mode,
- fixed_property, read_only_property };
-
- struct PropertyException {
- ExceptionReason reason;
- PropertyName failing_property_name;
- };
-
- typedef sequence<PropertyException> PropertyExceptions;
- exception MultipleExceptions { PropertyExceptions exceptions; };
-
- /*****************************************************/
- /* Interface Definitions */
- /*****************************************************/
- interface PropertySetFactory {
- PropertySet create_propertyset();
-
- PropertySet create_constrained_propertyset( in PropertyTypes allowed_property_types,
- in Properties allowed_properties)
- raises(ConstraintNotSupported);
-
- PropertySet create_initial_propertyset( in Properties initial_properties)
- raises(MultipleExceptions); };
-
- /*---------------------------------------------------*/
- interface PropertySetDefFactory {
- PropertySetDef create_propertysetdef();
-
- PropertySetDef create_constrained_propertysetdef( in PropertyTypes allowed_property_types,
- in PropertyDefs allowed_property_defs)
- raises(ConstraintNotSupported);
-
- PropertySetDef create_initial_propertysetdef( in PropertyDefs initial_property_defs)
- raises(MultipleExceptions);
- };
-
- /*---------------------------------------------------*/
- interface PropertySet {
- /* Support for defining and modifying properties */
- void define_property( in PropertyName property_name, in any property_value)
- raises(InvalidPropertyName, ConflictingProperty, UnsupportedTypeCode,
- UnsupportedProperty, ReadOnlyProperty);
-
- void define_properties( in Properties nproperties)
- raises(MultipleExceptions);
-
- /* Support for Getting Properties and their Names */
- unsigned long get_number_of_properties();
-
- void get_all_property_names( in unsigned long how_many,
- out PropertyNames property_names,
- out PropertyNamesIterator rest);
-
- any get_property_value( in PropertyName property_name)
- raises(PropertyNotFound, InvalidPropertyName);
-
- boolean get_properties( in PropertyNames property_names,
- out Properties nproperties);
-
- void get_all_properties( in unsigned long how_many,
- out Properties nproperties,
- out PropertiesIterator rest);
-
- /* Support for Deleting Properties */
- void delete_property( in PropertyName property_name)
- raises(PropertyNotFound, InvalidPropertyName, FixedProperty);
-
- void delete_properties( in PropertyNames property_names)
- raises(MultipleExceptions);
-
- boolean delete_all_properties();
-
- /* Support for Existence Check */
- boolean is_property_defined( in PropertyName property_name)
- raises(InvalidPropertyName);
- };
-
- /*---------------------------------------------------*/
- interface PropertySetDef:PropertySet {
- /* Support for retrieval of PropertySet constraints*/
- void get_allowed_property_types( out PropertyTypes property_types);
-
- void get_allowed_properties( out PropertyDefs property_defs);
-
- /* Support for defining and modifying properties */
- void define_property_with_mode( in PropertyName property_name,
- in any property_value,
- in PropertyModeType property_mode)
- raises(InvalidPropertyName, ConflictingProperty, UnsupportedTypeCode,
- UnsupportedProperty, UnsupportedMode, ReadOnlyProperty);
-
- void define_properties_with_modes( in PropertyDefs property_defs)
- raises(MultipleExceptions);
-
- /* Support for Getting and Setting Property Modes */
- PropertyModeType get_property_mode( in PropertyName property_name)
- raises(PropertyNotFound, InvalidPropertyName);
-
- boolean get_property_modes( in PropertyNames property_names,
- out PropertyModes property_modes);
-
- void set_property_mode( in PropertyName property_name,
- in PropertyModeType property_mode)
- raises(InvalidPropertyName, PropertyNotFound, UnsupportedMode);
-
- void set_property_modes( in PropertyModes property_modes)
- raises(MultipleExceptions);
- };
-
- /*---------------------------------------------------*/
- interface PropertyNamesIterator{
- void reset();
-
- boolean next_one( out PropertyName property_name);
-
- boolean next_n ( in unsigned long how_many,
- out PropertyNames property_names);
-
- void destroy();
- };
-
- /*---------------------------------------------------*/
- interface PropertiesIterator {
- void reset();
-
- boolean next_one( out Property aproperty);
-
- boolean next_n( in unsigned long how_many,
- out Properties nproperties);
-
- void destroy();
- };
-};
-
-#endif
diff --git a/lib/cosProperty/src/CosPropertyService_PropertiesIterator_impl.erl b/lib/cosProperty/src/CosPropertyService_PropertiesIterator_impl.erl
deleted file mode 100644
index 5972e8f4d2..0000000000
--- a/lib/cosProperty/src/CosPropertyService_PropertiesIterator_impl.erl
+++ /dev/null
@@ -1,167 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosPropertyService_PropertiesIterator_impl.erl
-%% Description :
-%%
-%%----------------------------------------------------------------------
--module('CosPropertyService_PropertiesIterator_impl').
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include("CosPropertyService.hrl").
--include("cosProperty.hrl").
-
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
-%% Mandatory server functions
--export([init/1,
- terminate/2,
- code_change/3]).
-
--export([reset/1,
- next_one/1,
- next_n/2,
- destroy/1]).
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
--export([
- ]).
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {properties, counter=1, length}).
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
--define(CreateInitState(L), #state{properties = L, length = length(L)}).
--define(get_Properties(S), S#state.properties).
--define(get_Counter(S), S#state.counter).
--define(get_Length(S), S#state.length).
-
--define(set_Properties(S, P), S#state{properties = P}).
--define(set_Counter(S, C), S#state{counter = C}).
--define(set_Length(S, L), S#state{length = L}).
-
--define(increment_Counter(S), S#state{counter = S#state.counter+1}).
--define(decrement_Counter(S), S#state{counter = S#state.counter-1}).
--define(addto_Counter(S, N), S#state{counter = S#state.counter+N}).
--define(subfrom_Counter(S, N), S#state{counter = S#state.counter-N}).
-
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Description: Initiates the server
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%%----------------------------------------------------------------------
-init(Properties) ->
- {ok, ?CreateInitState(Properties)}.
-
-%%----------------------------------------------------------------------
-%% Function : terminate/2
-%% Description: Shutdown the server
-%% Returns : any (ignored by gen_server)
-%%----------------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-%%----------------------------------------------------------------------
-%% Function : code_change/3
-%% Description: Convert process state when code is changed
-%% Returns : {ok, NewState}
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : reset
-%% Arguments : -
-%% Description:
-%% Returns : {ok, NewState}
-%%----------------------------------------------------------------------
-reset(State) ->
- {reply, ok, ?set_Counter(State, 1)}.
-
-%%----------------------------------------------------------------------
-%% Function : next_one
-%% Arguments : -
-%% Description:
-%% Returns : {ok, {bool(), PropertyList}, NewState}
-%%----------------------------------------------------------------------
-next_one(State) when ?get_Counter(State) > ?get_Length(State) ->
- {reply, {false,
- #'CosPropertyService_Property'
- {property_name = "",
- property_value = any:create(orber_tc:null(), null)}},
- State};
-next_one(State) ->
- {reply, {true, lists:nth(?get_Counter(State), ?get_Properties(State))},
- ?set_Counter(State, 1+?get_Counter(State))}.
-
-%%----------------------------------------------------------------------
-%% Function : next_n
-%% Arguments : N - how many properties we should return.
-%% Description:
-%% Returns : {ok, {bool(), PropertyList}, NewState}
-%%----------------------------------------------------------------------
-next_n(State, N) ->
- case lists:sublist(?get_Properties(State),
- ?get_Counter(State),
- N) of
- Properties when N+?get_Counter(State) < ?get_Length(State) ->
- {reply, {true, Properties}, ?set_Counter(State, N+?get_Counter(State))};
- Properties ->
- {reply, {false, Properties}, ?set_Counter(State, ?get_Length(State))}
- end.
-
-%%---------------------------------------------------------------------%
-%% Function : destroy
-%% Arguments : -
-%% Description: Terminate the object
-%% Returns : {ok, NewState}
-%%----------------------------------------------------------------------
-destroy(State) ->
- {stop, normal, ok, State}.
-
-%%======================================================================
-%% Internal functions
-%%=====================================================================
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
-
diff --git a/lib/cosProperty/src/CosPropertyService_PropertyNamesIterator_impl.erl b/lib/cosProperty/src/CosPropertyService_PropertyNamesIterator_impl.erl
deleted file mode 100644
index 7ce4f6b303..0000000000
--- a/lib/cosProperty/src/CosPropertyService_PropertyNamesIterator_impl.erl
+++ /dev/null
@@ -1,159 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosPropertyService_PropertyNamesIterator_impl.erl
-%% Description :
-%%
-%%----------------------------------------------------------------------
--module('CosPropertyService_PropertyNamesIterator_impl').
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include("CosPropertyService.hrl").
--include("cosProperty.hrl").
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
-%% Mandatory server functions
--export([init/1,
- terminate/2,
- code_change/3]).
-
--export([reset/1,
- next_one/1,
- next_n/2,
- destroy/1]).
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
--export([
- ]).
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {properties, counter=1, length}).
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
--define(CreateInitState(L), #state{properties = L, length = length(L)}).
--define(get_Properties(S), S#state.properties).
--define(get_Counter(S), S#state.counter).
--define(get_Length(S), S#state.length).
-
--define(set_Properties(S, P), S#state{properties = P}).
--define(set_Counter(S, C), S#state{counter = C}).
--define(set_Length(S, L), S#state{length = L}).
-
--define(increment_Counter(S), S#state{counter = S#state.counter+1}).
--define(decrement_Counter(S), S#state{counter = S#state.counter-1}).
--define(addto_Counter(S, N), S#state{counter = S#state.counter+N}).
--define(subfrom_Counter(S, N), S#state{counter = S#state.counter-N}).
-
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Description: Initiates the server
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%%----------------------------------------------------------------------
-init(Properties) ->
- {ok, ?CreateInitState(Properties)}.
-
-%%----------------------------------------------------------------------
-%% Function : terminate/2
-%% Description: Shutdown the server
-%% Returns : any (ignored by gen_server)
-%%----------------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-%%----------------------------------------------------------------------
-%% Function : code_change/3
-%% Description: Convert process state when code is changed
-%% Returns : {ok, NewState}
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : reset
-%% Arguments : -
-%% Description:
-%% Returns : {ok, NewState}
-%%----------------------------------------------------------------------
-reset(State) ->
- {reply, ok, ?set_Counter(State, 1)}.
-
-%%---------------------------------------------------------------------%
-%% Function : next_one
-%% Arguments : -
-%% Description:
-%% Returns : {ok, {bool(), PropertyName}, NewState}
-%%----------------------------------------------------------------------
-next_one(State) when ?get_Counter(State) > ?get_Length(State) ->
- {reply, {false, ""}, State};
-next_one(State) ->
- {reply, {true, lists:nth(?get_Counter(State), ?get_Properties(State))},
- ?set_Counter(State, 1+?get_Counter(State))}.
-
-%%---------------------------------------------------------------------%
-%% Function : next_n
-%% Arguments : N - how many properties we should return.
-%% Description:
-%% Returns : {ok, {bool(), PropertyNameList}, NewState}
-%%----------------------------------------------------------------------
-next_n(State, N) ->
- case lists:sublist(?get_Properties(State), ?get_Counter(State), N) of
- Properties when N+?get_Counter(State) < ?get_Length(State) ->
- {reply, {true, Properties}, ?set_Counter(State, N+?get_Counter(State))};
- Properties ->
- {reply, {false, Properties}, ?set_Counter(State, ?get_Length(State))}
- end.
-
-%%---------------------------------------------------------------------%
-%% Function : destroy
-%% Arguments : -
-%% Description: Terminate the object
-%% Returns : {ok, NewState}
-%%----------------------------------------------------------------------
-destroy(State) ->
- {stop, normal, ok, State}.
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
diff --git a/lib/cosProperty/src/CosPropertyService_PropertySetDefFactory_impl.erl b/lib/cosProperty/src/CosPropertyService_PropertySetDefFactory_impl.erl
deleted file mode 100644
index 722bb45eb7..0000000000
--- a/lib/cosProperty/src/CosPropertyService_PropertySetDefFactory_impl.erl
+++ /dev/null
@@ -1,186 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosPropertyService_PropertySetDefFactory_impl.erl
-%% Description :
-%%
-%%----------------------------------------------------------------------
--module('CosPropertyService_PropertySetDefFactory_impl').
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include("CosPropertyService.hrl").
--include("cosProperty.hrl").
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
--export([init/1,
- terminate/2,
- code_change/3]).
-
--export([create_propertysetdef/2,
- create_constrained_propertysetdef/4,
- create_initial_propertysetdef/3]).
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
--export([]).
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {}).
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
--define(checkTCfun, fun(TC) -> orber_tc:check_tc(TC) end).
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%----------------------------------------------------------------------
-init([]) ->
- {ok, #state{}}.
-
-%%----------------------------------------------------------------------
-%% Function : terminate/2
-%% Returns : any (ignored by gen_server)
-%% Description: Shutdown the server
-%%----------------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-%%----------------------------------------------------------------------
-%% Function : code_change/3
-%% Returns : {ok, NewState}
-%% Description: Convert process state when code is changed
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : create_propertysetdef
-%% Arguments :
-%% Returns : CosPropertyService::PropertySetDef reference.
-%% Description:
-%%----------------------------------------------------------------------
-create_propertysetdef(_OE_This, State) ->
- {reply,
- 'CosPropertyService_PropertySetDef':
- oe_create({normal, [], [], [], ?PropertySetDef}, [{pseudo, true}]),
- State}.
-
-%%---------------------------------------------------------------------%
-%% Function : create_constrained_propertysetdef
-%% Arguments : PropTypes - list of property types.
-%% PropDefs - list of property defs.
-%% Returns : CosPropertyService::PropertySetDef |
-%% {'EXCEPTION', CosPropertyService::ConstraintNotSupported}
-%% Description:
-%%----------------------------------------------------------------------
-create_constrained_propertysetdef(_OE_This, State, PropTypes, PropDefs) ->
- case lists:all(?checkTCfun, PropTypes) of
- true ->
- crosscheckTC(PropDefs, PropTypes),
- {reply,
- 'CosPropertyService_PropertySetDef':
- oe_create({normal, PropTypes, PropDefs, [], ?PropertySetDef}, [{pseudo, true}]),
- State};
- false ->
- corba:raise(#'CosPropertyService_ConstraintNotSupported'{})
- end.
-
-crosscheckTC([], _) ->
- ok;
-crosscheckTC([#'CosPropertyService_PropertyDef'
- {property_name = Name,
- property_value = Value,
- property_mode = _Mode}|T], TCs) ->
- case lists:member(any:get_typecode(Value), TCs) of
- true when Name =/= "" ->
- crosscheckTC(T, TCs);
- _ ->
- corba:raise(#'CosPropertyService_ConstraintNotSupported'{})
- end.
-
-%%---------------------------------------------------------------------%
-%% Function : create_initial_propertysetdef
-%% Arguments :
-%% Returns : CosPropertyService::PropertySetDef |
-%% {'EXCEPTION', CosPropertyService::MultipleExceptions}
-%% Description:
-%%----------------------------------------------------------------------
-create_initial_propertysetdef(_OE_This, State, PropDefs) ->
- InitProps = evaluate_propertysetdef(PropDefs),
- {reply,
- 'CosPropertyService_PropertySetDef':
- oe_create({normal, [], [], InitProps, ?PropertySetDef}, [{pseudo, true}]),
- State}.
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-evaluate_propertysetdef(SetDefs) ->
- case evaluate_propertysetdef(SetDefs, [], []) of
- {ok, NewProperties} ->
- NewProperties;
- {error, Exc} ->
- corba:raise(#'CosPropertyService_MultipleExceptions'{exceptions = Exc})
- end.
-
-evaluate_propertysetdef([], NewProperties, []) ->
- %% No exceptions found.
- {ok, NewProperties};
-evaluate_propertysetdef([], _, Exc) ->
- {error, Exc};
-evaluate_propertysetdef([#'CosPropertyService_PropertyDef'
- {property_name = Name,
- property_value = Value,
- property_mode = Mode}|T], X, Exc) ->
- case orber_tc:check_tc(any:get_typecode(Value)) of
- true ->
- evaluate_propertysetdef(T, [{Name, Value, Mode}|X], Exc);
- false ->
- evaluate_propertysetdef(T, X, [#'CosPropertyService_PropertyException'
- {reason = unsupported_type_code,
- failing_property_name = Name}|Exc])
- end.
-
-
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
-
diff --git a/lib/cosProperty/src/CosPropertyService_PropertySetDef_impl.erl b/lib/cosProperty/src/CosPropertyService_PropertySetDef_impl.erl
deleted file mode 100644
index cc67daa9e0..0000000000
--- a/lib/cosProperty/src/CosPropertyService_PropertySetDef_impl.erl
+++ /dev/null
@@ -1,1042 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2017. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: CosPropertyService_PropertySetDef_impl.erl
-%% Modified:
-%%
-%%-----------------------------------------------------------------
-%% README:
-%% (1) The OMG specification states that a property name may not
-%% be an empty string (""). We may restrict this further
-%% but there is no reason for that.
-%%-----------------------------------------------------------------
--module('CosPropertyService_PropertySetDef_impl').
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("cosProperty/include/CosPropertyService.hrl").
--include("cosProperty.hrl").
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
-%% Mandatory callbacks
--export([init/1,
- terminate/2,
- code_change/3]).
-
-%% Inherrit from CosPropertyService::PropertySet
--export([define_property/4,
- define_properties/3,
- get_number_of_properties/2,
- get_all_property_names/3,
- get_property_value/3,
- get_properties/3,
- get_all_properties/3,
- delete_property/3,
- delete_properties/3,
- delete_all_properties/2,
- is_property_defined/3]).
-
-%% CosPropertyService::PropertySetDef
--export([get_allowed_property_types/2,
- get_allowed_properties/2,
- define_property_with_mode/5,
- define_properties_with_modes/3,
- get_property_mode/3,
- get_property_modes/3,
- set_property_mode/4,
- set_property_modes/3]).
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
--export([dump/0]).
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {dbKey, defaultMode, okTypes, okProperties, myType}).
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
-
--define(create_InitState(K, D, AT, AP, MT), #state{dbKey = K, defaultMode = D,
- okTypes = AT, okProperties = AP,
- myType = MT}).
-%% Selectors
--define(get_DBKey(S), S#state.dbKey).
--define(get_DefaultMode(S), S#state.defaultMode).
--define(get_okTypes(S), S#state.okTypes).
--define(get_okProperties(S), S#state.okProperties).
-%% MISC
--define(is_NotSetDef(S), S#state.myType =/= ?PropertySetDef).
--define(no_PropertyLimits(S), S#state.okProperties == []).
--define(no_TypeLimits(S), S#state.okTypes == []).
--define(is_NotStatic(S), is_binary(S#state.dbKey)).
-
-%% Fun:s
--define(Local2Property, fun({N,V,_M}) ->
- #'CosPropertyService_Property'{property_name = N,
- property_value = V}
- end).
--define(Local2Names, fun({N,_V,_M}) ->
- N
- end).
--define(MemberName(N), fun(R) ->
- case R of
- Property when is_record(R, 'CosPropertyService_Property') ->
- Property#'CosPropertyService_Property'.property_name == N;
- PropertyDef when is_record(R, 'CosPropertyService_PropertyDef') ->
- PropertyDef#'CosPropertyService_PropertyDef'.property_name == N;
- _->
- false
- end
- end).
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Description: Initiates the server
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%%----------------------------------------------------------------------
-init({DefMode, AllowedTypes, AllowedProperties, InitProperties, MyType}) ->
- Key = term_to_binary({{erlang:system_time(),
- erlang:unique_integer()},
- node()}),
- _F = ?write_function(#oe_CosPropertyService{key=Key,
- properties=InitProperties}),
- write_result(mnesia:transaction(_F)),
- {ok, ?create_InitState(Key, DefMode, AllowedTypes, AllowedProperties, MyType)};
-init({static, DefMode, AllowedTypes, AllowedProperties, InitProperties, MyType}) ->
- {ok, ?create_InitState(InitProperties, DefMode, AllowedTypes,
- AllowedProperties, MyType)}.
-
-%%---------------------------------------------------------------------%
-%% Function : terminate
-%% Description: Shutdown the server
-%% Returns : any (ignored by gen_server)
-%%----------------------------------------------------------------------
-terminate(_Reason, State) when ?is_NotStatic(State) ->
- _DF = ?delete_function({oe_CosPropertyService, ?get_DBKey(State)}),
- catch write_result(mnesia:transaction(_DF)),
- ok;
-terminate(_Reason, _State) ->
- ok.
-
-%%---------------------------------------------------------------------%
-%% Function : code_change
-%% Description: Convert process state when code is changed
-%% Returns : {ok, State}
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-
-%%----------------------------------------------------------------------
-%% Interface CosPropertyService::PropertySet
-%%----------------------------------------------------------------------
-%%---------------------------------------------------------------------%
-%% Function : define_property
-%% Arguments :
-%% Description:
-%% Returns : {ok, State}
-%%----------------------------------------------------------------------
-define_property(_, _, "", _) ->
- corba:raise(#'CosPropertyService_InvalidPropertyName'{});
-define_property(_OE_This, State, Name, Value) when ?is_NotStatic(State) ->
- evaluate_property_data(State, Value, Name),
- _DF =
- fun() ->
- case mnesia_read(State) of
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- X ->
- case catch update_property(X, Name, value, Value,
- ?get_DefaultMode(State)) of
- {'EXCEPTION', E} when
- is_record(E, 'CosPropertyService_PropertyNotFound') ->
- mnesia_write(State, [{Name, Value, ?get_DefaultMode(State)}|X]);
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- NewProperties ->
- mnesia_write(State, NewProperties)
- end
- end
- end,
- {reply, mnesia_transaction(_DF), State};
-define_property(_OE_This, State, Name, Value) ->
- evaluate_property_data(State, Value, Name),
- X = ?get_DBKey(State),
- case catch update_property(X, Name, value, Value, ?get_DefaultMode(State)) of
- {'EXCEPTION', E} when is_record(E, 'CosPropertyService_PropertyNotFound') ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO});
- {'EXCEPTION', E} ->
- corba:raise(E);
- _NewProperties ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-
-%%---------------------------------------------------------------------%
-%% Function : get_property_value
-%% Arguments :
-%% Description:
-%% Returns : {ok, State}
-%%----------------------------------------------------------------------
-get_property_value(_, _, "") ->
- corba:raise(#'CosPropertyService_InvalidPropertyName'{});
-get_property_value(_OE_THIS, State, Name) ->
- X = lookup_table(?get_DBKey(State)),
- {reply, find_property(X, Name, value), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : delete_property
-%% Arguments :
-%% Description:
-%% Returns : {ok, State}
-%%----------------------------------------------------------------------
-delete_property(_, _, "") ->
- corba:raise(#'CosPropertyService_InvalidPropertyName'{});
-delete_property(_OE_THIS, State, Name) when ?is_NotStatic(State) ->
- _DF =
- fun() ->
- case mnesia_read(State) of
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- X ->
- case catch remove_property(X, Name) of
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- NewProperties ->
- mnesia_write(State, NewProperties)
- end
- end
- end,
- {reply, mnesia_transaction(_DF), State};
-delete_property(_OE_THIS, State, Name) ->
- X = lookup_table(?get_DBKey(State)),
- %% Check the properties; must raise an exception.
- remove_property(X, Name),
- %% Something is not correct.
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
-
-
-%%---------------------------------------------------------------------%
-%% Function : define_properties
-%% Arguments :
-%% Description:
-%% Returns : {ok, State}
-%%----------------------------------------------------------------------
-define_properties(_OE_THIS, State, PropertySeq) when ?is_NotStatic(State) ->
- {OKProperties, Exc} = evaluate_properties_data(State, PropertySeq),
- _DF =
- fun() ->
- case mnesia_read(State) of
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- X ->
- case catch define_properties_helper(State,
- OKProperties, X, Exc) of
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- NewProperties ->
- mnesia_write(State, NewProperties)
- end
- end
- end,
- {reply, mnesia_transaction(_DF), State};
-define_properties(_OE_THIS, State, PropertySeq) ->
- {OKProperties, Exc} = evaluate_properties_data(State, PropertySeq),
- X = lookup_table(?get_DBKey(State)),
- case define_properties_helper(State, OKProperties, X, Exc) of
- {'EXCEPTION', E} ->
- corba:raise(E);
- _ ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-define_properties_helper(_State, [], NewProperties, []) ->
- %% No exceptions, insert the properties.
- NewProperties;
-define_properties_helper(_State, [], _, MultipleExceptions) ->
- {'EXCEPTION', #'CosPropertyService_MultipleExceptions'{exceptions = MultipleExceptions}};
-define_properties_helper(State, [#'CosPropertyService_Property'
- {property_name = Name,
- property_value = Value}|T], Properties, Exc) ->
- case catch update_property(Properties, Name, value, Value, ?get_DefaultMode(State)) of
- {'EXCEPTION', E} when is_record(E, 'CosPropertyService_PropertyNotFound') ->
- define_properties_helper(State, T, [{Name, Value, ?get_DefaultMode(State)}|Properties], Exc);
- {'EXCEPTION', E} ->
- define_properties_helper(State, T, Properties,
- [#'CosPropertyService_PropertyException'
- {reason = remap_exception(E),
- failing_property_name = Name}|Exc]);
- NewProperties ->
- define_properties_helper(State, T, NewProperties, Exc)
- end.
-
-%%---------------------------------------------------------------------%
-%% Function : get_number_of_properties
-%% Arguments : -
-%% Description: Returns the number of properties currently associated
-%% with this object.
-%% Returns : {ok, ulong(), State}
-%%----------------------------------------------------------------------
-get_number_of_properties(_OE_THIS, State) ->
- X = lookup_table(?get_DBKey(State)),
- {reply, length(X), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : get_all_property_names
-%% Arguments :
-%% Description:
-%% Returns : {ok, State}
-%%----------------------------------------------------------------------
-get_all_property_names(_OE_THIS, State, Max) ->
- X = lookup_table(?get_DBKey(State)),
- {reply, get_all_property_names_helper(X, [], Max), State}.
-
-get_all_property_names_helper([], Acc, _) ->
- %% There are no more properties; return a nil-object refernce.
- {ok, Acc, corba:create_nil_objref()};
-get_all_property_names_helper(Left, Acc, 0) ->
- %% There are more properties; create Name Iterartor.
- PropertyNames = lists:map(?Local2Names, Left),
- {ok, Acc, cosProperty:start_PropertyNamesIterator(PropertyNames)};
-get_all_property_names_helper([{Name, _, _}|T], Acc, No) ->
- get_all_property_names_helper(T, [Name|Acc], No-1).
-
-
-%%---------------------------------------------------------------------%
-%% Function : get_properties
-%% Arguments : A list of property names, i.e., string()
-%% Description:
-%% Returns : {ok, State}
-%%----------------------------------------------------------------------
-get_properties(_OE_THIS, State, PropertyNames) ->
- X = lookup_table(?get_DBKey(State)),
- {reply, locate_names(PropertyNames, X, true, []), State}.
-
-locate_names([], _, AllOK, Acc) ->
- {AllOK, Acc};
-locate_names([""|T], X, _AllOK, Acc) ->
- locate_names(T, X, false, [#'CosPropertyService_Property'
- {property_name = "",
- property_value =
- any:create(tk_void, ok)}|Acc]);
-locate_names([H|T], X, AllOK, Acc) ->
- case catch find_property(X, H, value) of
- {'EXCEPTION', _} ->
- locate_names(T, X, false, [#'CosPropertyService_Property'
- {property_name = H,
- property_value =
- any:create(tk_void, ok)}|Acc]);
- Val ->
- locate_names(T, X, AllOK, [#'CosPropertyService_Property'
- {property_name = H,
- property_value = Val}|Acc])
- end.
-
-%%---------------------------------------------------------------------%
-%% Function : get_all_properties
-%% Arguments :
-%% Description:
-%% Returns : {ok, State}
-%%----------------------------------------------------------------------
-get_all_properties(_OE_THIS, State, Max) ->
- X = lookup_table(?get_DBKey(State)),
- {reply, get_all_properties_helper(X, [], Max), State}.
-
-get_all_properties_helper([], Acc, _) ->
-%% There are no more properties; return a nil-object refernce.
- {ok, Acc, corba:create_nil_objref()};
-get_all_properties_helper(Left, Acc, 0) ->
- %% There are more properties; create Iterartor.
- Properties = lists:map(?Local2Property, Left),
- {ok, Acc, cosProperty:start_PropertiesIterator(Properties)};
-get_all_properties_helper([{Name, Val, _}|T], Acc, No) ->
- get_all_properties_helper(T, [#'CosPropertyService_Property'
- {property_name = Name,
- property_value = Val}|Acc], No-1).
-
-%%---------------------------------------------------------------------%
-%% Function : delete_properties
-%% Arguments :
-%% Description:
-%% Returns : {ok, State}
-%%----------------------------------------------------------------------
-delete_properties(_OE_THIS, State, []) ->
- {reply, ok, State};
-delete_properties(_OE_THIS, State, PropertyNames) when ?is_NotStatic(State) ->
- _DF =
- fun() ->
- case mnesia_read(State) of
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- X ->
- case catch delete_properties_helper(X, [], [],
- PropertyNames, State,
- length(X)) of
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- {{'EXCEPTION', E}, NotDeleted} ->
- ok = mnesia_write(State, NotDeleted),
- {'EXCEPTION', E};
- {ok, NotDeleted} ->
- mnesia_write(State, NotDeleted)
- end
- end
- end,
- {reply, mnesia_transaction(_DF), State};
-delete_properties(_OE_THIS, State, PropertyNames) ->
- X = lookup_table(?get_DBKey(State)),
- case delete_properties_helper(X, [], [], PropertyNames, State, length(X)) of
- {'EXCEPTION', E} ->
- corba:raise(E);
- _->
- %% Not acceptable if it was possible to delete one or more Properties.
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-delete_properties_helper([], [], NotDeleted, [], _State, _Len) ->
- %% Since there are no exceptions we have been able to delete all
- %% properties.
- {ok, NotDeleted};
-delete_properties_helper([], MultipleExc, NotDeleted, Names, _State, Len) ->
- %% Write remaining events to DB.
- case length(NotDeleted) of
- Len ->
- {'EXCEPTION', #'CosPropertyService_MultipleExceptions'
- {exceptions = add_not_found(Names, MultipleExc)}};
- _->
- {{'EXCEPTION', #'CosPropertyService_MultipleExceptions'
- {exceptions = add_not_found(Names, MultipleExc)}},
- NotDeleted}
- end;
-delete_properties_helper([{Name, Val, Mode}|T], MultipleExc, NotDeleted,
- Names, State, Len) ->
- case lists:member(Name, Names) of
- true when Mode =/= fixed_normal, Mode =/= fixed_readonly ->
- delete_properties_helper(T, MultipleExc, NotDeleted,
- lists:delete(Name, Names), State, Len);
- true ->
- delete_properties_helper(T, [#'CosPropertyService_PropertyException'
- {reason = fixed_property,
- failing_property_name = Name}|MultipleExc],
- [{Name, Val, Mode}|NotDeleted],
- lists:delete(Name, Names), State, Len);
- false ->
- delete_properties_helper(T, MultipleExc, [{Name, Val, Mode}|NotDeleted],
- Names, State, Len)
- end.
-
-add_not_found([], MultipleExc) ->
- MultipleExc;
-add_not_found([Name|T], MultipleExc) ->
- add_not_found(T, [#'CosPropertyService_PropertyException'
- {reason = property_not_found,
- failing_property_name = Name}|MultipleExc]).
-
-
-
-%%---------------------------------------------------------------------%
-%% Function : delete_all_properties
-%% Arguments :
-%% Description:
-%% Returns : {ok, State}
-%%----------------------------------------------------------------------
-delete_all_properties(_OE_THIS, State) when ?is_NotStatic(State) ->
- _DF =
- fun() ->
- case mnesia_read(State) of
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- X ->
- case catch delete_all_properties_helper(X, [], State,
- length(X)) of
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- true ->
- ok = mnesia_write(State, []),
- true;
- false ->
- false;
- {false, NotDeleted} ->
- ok = mnesia_write(State, NotDeleted),
- false
- end
- end
- end,
- {reply, mnesia_transaction(_DF), State};
-delete_all_properties(_OE_THIS, State) ->
- X = lookup_table(?get_DBKey(State)),
- case delete_all_properties_helper(X, [], State, length(X)) of
- false ->
- {reply, false, State};
- _->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-delete_all_properties_helper([], [], _State, _) ->
- %% Was able to delete all properties.
- true;
-delete_all_properties_helper([], NotDeleted, _State, Len) ->
- %% Write remaining events to DB.
- case length(NotDeleted) of
- Len ->
- false;
- _->
- {false, NotDeleted}
- end;
-delete_all_properties_helper([{Name, Val, fixed_normal}|T], NotDeleted, State, Len) ->
- delete_all_properties_helper(T, [{Name, Val, fixed_normal}|NotDeleted], State, Len);
-delete_all_properties_helper([{Name, Val, fixed_readonly}|T], NotDeleted, State, Len) ->
- delete_all_properties_helper(T, [{Name, Val, fixed_readonly}|NotDeleted], State, Len);
-delete_all_properties_helper([_|T], NotDeleted, State, Len) ->
- delete_all_properties_helper(T, NotDeleted, State, Len).
-
-%%---------------------------------------------------------------------%
-%% Function : is_property_defined
-%% Arguments :
-%% Description:
-%% Returns : {ok, State}
-%%----------------------------------------------------------------------
-is_property_defined(_, _, "") ->
- corba:raise(#'CosPropertyService_InvalidPropertyName'{});
-is_property_defined(_OE_THIS, State, Name) ->
- X = lookup_table(?get_DBKey(State)),
- {reply, lists:keymember(Name, 1, X), State}.
-
-%%----------------------------------------------------------------------
-%% Interface CosPropertyService::PropertySetDef
-%%----------------------------------------------------------------------
-%%---------------------------------------------------------------------%
-%% Function : get_allowed_property_types
-%% Arguments : -
-%% Description: Returns the initially supplied restrictions. An empty
-%% list means no restrictions.
-%% Returns : {ok, TypeCodeList,State}
-%%----------------------------------------------------------------------
-get_allowed_property_types(_OE_THIS, State) when ?is_NotSetDef(State) ->
- corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO});
-get_allowed_property_types(_OE_THIS, State) ->
- {reply, {ok, ?get_okTypes(State)}, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : get_allowed_properties
-%% Arguments :
-%% Description: Returns the initially supplied restrictions. An empty
-%% list means no restrictions.
-%% Returns : {ok, PropertyDefList, State}
-%%----------------------------------------------------------------------
-get_allowed_properties(_OE_THIS, State) when ?is_NotSetDef(State) ->
- corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO});
-get_allowed_properties(_OE_THIS, State) ->
- {reply, {ok, ?get_okProperties(State)}, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : define_property_with_mode
-%% Arguments :
-%% Description:
-%% Returns : {ok, State}
-%%----------------------------------------------------------------------
-define_property_with_mode(_OE_THIS, State, _, _, _) when ?is_NotSetDef(State) ->
- corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO});
-define_property_with_mode(_, _, "", _, _) ->
- corba:raise(#'CosPropertyService_InvalidPropertyName'{});
-define_property_with_mode(_OE_THIS, State, Name, Value, Mode)
- when ?is_NotStatic(State) ->
- evaluate_property_data(State, Value, Name),
- _DF =
- fun() ->
- case mnesia_read(State) of
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- X ->
- case catch update_property(X, Name, both, Value, Mode) of
- {'EXCEPTION', E}
- when is_record(E, 'CosPropertyService_PropertyNotFound') ->
- mnesia_write(State, [{Name, Value, Mode}|X]);
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- NewProperties ->
- mnesia_write(State, NewProperties)
- end
- end
- end,
- {reply, mnesia_transaction(_DF), State};
-define_property_with_mode(_OE_THIS, State, Name, Value, Mode) ->
- evaluate_property_data(State, Value, Name),
- X = lookup_table(?get_DBKey(State)),
- case catch update_property(X, Name, both, Value, Mode) of
- {'EXCEPTION', E} when is_record(E, 'CosPropertyService_PropertyNotFound') ->
- %% Should get not allowed exception.
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO});
- {'EXCEPTION', E} ->
- corba:raise(E);
- _ ->
- %% Should be impossible.
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%---------------------------------------------------------------------%
-%% Function : define_properties_with_modes
-%% Arguments :
-%% Description:
-%% Returns : {ok, State}
-%%----------------------------------------------------------------------
-define_properties_with_modes(_OE_THIS, State, _) when ?is_NotSetDef(State) ->
- corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO});
-define_properties_with_modes(_OE_THIS, State, PropertyDefSeq)
- when ?is_NotStatic(State)->
- {OKProperteDefs, Exc} = evaluate_properties_data(State, PropertyDefSeq),
- _DF =
- fun() ->
- case mnesia_read(State) of
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- X ->
- case catch define_properties_with_modes_helper(OKProperteDefs,
- X, Exc, State) of
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- NewProperties ->
- mnesia_write(State, NewProperties)
- end
- end
- end,
- {reply, mnesia_transaction(_DF), State};
-define_properties_with_modes(_OE_THIS, State, PropertyDefSeq) ->
- {OKProperteDefs, Exc} = evaluate_properties_data(State, PropertyDefSeq),
- X = lookup_table(?get_DBKey(State)),
- case define_properties_with_modes_helper(OKProperteDefs, X, Exc, State) of
- {'EXCEPTION', E} ->
- corba:raise(E);
- _ ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-
-define_properties_with_modes_helper([], NewPropertyDefs, [], _State) ->
- %% No exceptions found.
- NewPropertyDefs;
-define_properties_with_modes_helper([], _, Exc, _) ->
- {'EXCEPTION', #'CosPropertyService_MultipleExceptions'{exceptions = Exc}};
-define_properties_with_modes_helper([#'CosPropertyService_PropertyDef'
- {property_name = Name,
- property_value = Value,
- property_mode = Mode}|T], X, Exc, State) ->
- case catch update_property(X, Name, both, Value, Mode) of
- {'EXCEPTION', E} when is_record(E, 'CosPropertyService_PropertyNotFound') ->
- define_properties_with_modes_helper(T, [{Name, Value, Mode}|X], Exc, State);
- {'EXCEPTION', E} ->
- define_properties_with_modes_helper(T, X,
- [#'CosPropertyService_PropertyException'
- {reason = remap_exception(E),
- failing_property_name = Name}|Exc],
- State);
- NewX ->
- define_properties_with_modes_helper(T, NewX, Exc, State)
- end.
-
-%%---------------------------------------------------------------------%
-%% Function : get_property_mode
-%% Arguments :
-%% Description:
-%% Returns : {ok, State}
-%%----------------------------------------------------------------------
-get_property_mode(_OE_THIS, State, _) when ?is_NotSetDef(State) ->
- corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO});
-get_property_mode(_, _, "") ->
- corba:raise(#'CosPropertyService_InvalidPropertyName'{});
-get_property_mode(_OE_THIS, State, Name) ->
- X = lookup_table(?get_DBKey(State)),
- {reply, find_property(X, Name, mode), State}.
-
-%%---------------------------------------------------------------------%
-%% Function : get_property_modes
-%% Arguments :
-%% Description:
-%% Returns : {ok, State}
-%%----------------------------------------------------------------------
-get_property_modes(_OE_THIS, State, _) when ?is_NotSetDef(State) ->
- corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO});
-get_property_modes(_OE_THIS, State, PropertyNames) ->
- X = lookup_table(?get_DBKey(State)),
- {reply, get_property_modes_helper(PropertyNames, X, [], true), State}.
-
-get_property_modes_helper([], _, Acc, Bool) ->
- {Bool, Acc};
-get_property_modes_helper([""|T], Properties, Acc, _) ->
- get_property_modes_helper(T, Properties,
- [#'CosPropertyService_PropertyMode'
- {property_name = "",
- property_mode = undefined}|Acc], false);
-get_property_modes_helper([Name|T], Properties, Acc, Bool) ->
- case lists:keysearch(Name, 1, Properties) of
- {value, {Name, _, Mode}} ->
- get_property_modes_helper(T, Properties,
- [#'CosPropertyService_PropertyMode'
- {property_name = Name,
- property_mode = Mode}|Acc], Bool);
- false ->
- get_property_modes_helper(T, Properties,
- [#'CosPropertyService_PropertyMode'
- {property_name = Name,
- property_mode = undefined}|Acc], false)
- end.
-
-%%---------------------------------------------------------------------%
-%% Function : set_property_mode
-%% Arguments :
-%% Description:
-%% Returns : {ok, State}
-%%----------------------------------------------------------------------
-set_property_mode(_OE_THIS, State, _, _) when ?is_NotSetDef(State) ->
- corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO});
-set_property_mode(_, _, "", _) ->
- corba:raise(#'CosPropertyService_InvalidPropertyName'{});
-set_property_mode(_OE_THIS, State, Name, Mode) when ?is_NotStatic(State) ->
- _DF =
- fun() ->
- case mnesia_read(State) of
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- X ->
- case catch update_property(X, Name, mode, undefined, Mode) of
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- NewProperties ->
- mnesia_write(State, NewProperties)
- end
- end
- end,
- {reply, mnesia_transaction(_DF), State};
-set_property_mode(_OE_THIS, State, Name, Mode) ->
- X = lookup_table(?get_DBKey(State)),
- update_property(X, Name, mode, undefined, Mode),
- %% Something is not correct, shouldn't be allowed to update a property when
- %% static.
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
-
-%%---------------------------------------------------------------------%
-%% Function : set_property_modes
-%% Arguments :
-%% Description:
-%% Returns : {ok, State}
-%%----------------------------------------------------------------------
-set_property_modes(_OE_THIS, State, _) when ?is_NotSetDef(State) ->
- corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO});
-set_property_modes(_OE_THIS, State, PropertyModes) when ?is_NotStatic(State) ->
- _DF =
- fun() ->
- case mnesia_read(State) of
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- X ->
- case catch set_property_modes_helper(PropertyModes, X, [],
- State) of
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- NewProperties ->
- mnesia_write(State, NewProperties)
- end
- end
- end,
- {reply, mnesia_transaction(_DF), State};
-set_property_modes(_OE_THIS, State, PropertyModes) ->
- X = lookup_table(?get_DBKey(State)),
- case set_property_modes_helper(PropertyModes, X, [], State) of
- {'EXCEPTION', E} ->
- corba:raise(E);
- _ ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-set_property_modes_helper([], NewProperties, [], _State) ->
- %% No exceptions, write to DB.
- NewProperties;
-set_property_modes_helper([], _, Exc, _) ->
- {'EXCEPTION', #'CosPropertyService_MultipleExceptions'{exceptions = Exc}};
-set_property_modes_helper([#'CosPropertyService_PropertyMode'
- {property_name = Name,
- property_mode = Mode}|T], X, Exc, State) ->
- case catch update_property(X, Name, mode, undefined, Mode) of
- {'EXCEPTION', E} ->
- set_property_modes_helper(T, X,
- [#'CosPropertyService_PropertyException'
- {reason = remap_exception(E),
- failing_property_name = Name}|Exc],
- State);
- NewX ->
- set_property_modes_helper(T, NewX, Exc, State)
- end.
-
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-
-remap_exception(#'CosPropertyService_ConflictingProperty'{}) -> conflicting_property;
-remap_exception(#'CosPropertyService_FixedProperty'{}) -> fixed_property;
-remap_exception(#'CosPropertyService_InvalidPropertyName'{}) -> invalid_property_name;
-remap_exception(#'CosPropertyService_PropertyNotFound'{}) -> property_not_found;
-remap_exception(#'CosPropertyService_UnsupportedTypeCode'{}) -> unsupported_type_code;
-remap_exception(#'CosPropertyService_UnsupportedProperty'{}) -> unsupported_property;
-remap_exception(#'CosPropertyService_ReadOnlyProperty'{}) -> read_only_property;
-remap_exception(#'CosPropertyService_UnsupportedMode'{}) -> unsupported_mode.
-
-find_property([], _, _) ->
- corba:raise(#'CosPropertyService_PropertyNotFound'{});
-find_property([{Name, Value, _}|_], Name, value) ->
- Value;
-find_property([{Name, _, Mode}|_], Name, mode) ->
- Mode;
-% Left out for now to avoid dialyzer warning.
-%find_property([{Name, Value, Mode}|_], Name, all) ->
-% {Name, Value, Mode};
-find_property([_|T], Name, Which) ->
- find_property(T, Name, Which).
-
-remove_property(PropertList, Name) ->
- remove_property(PropertList, Name, []).
-remove_property([], _, _) ->
- corba:raise(#'CosPropertyService_PropertyNotFound'{});
-remove_property([{Name, _, fixed_normal}|_T], Name, _) ->
- corba:raise(#'CosPropertyService_FixedProperty'{});
-remove_property([{Name, _, fixed_readonly}|_T], Name, _) ->
- corba:raise(#'CosPropertyService_FixedProperty'{});
-remove_property([{Name, _, _}|T], Name, Acc) ->
- T++Acc;
-remove_property([H|T], Name, Acc) ->
- remove_property(T, Name, [H|Acc]).
-
-
-update_property(_, "", _, _, _) ->
- corba:raise(#'CosPropertyService_InvalidPropertyName'{});
-update_property(PropertyList, Name, Which, Value, Mode) ->
- update_property(PropertyList, Name, Which, Value, Mode, []).
-
-update_property([], _, _, _, _, _) ->
- corba:raise(#'CosPropertyService_PropertyNotFound'{});
-update_property([{Name, _, fixed_readonly}|_], Name, value, _, _, _) ->
- corba:raise(#'CosPropertyService_FixedProperty'{});
-update_property([{Name, _, fixed_normal}|_], Name, both, _, _, _) ->
- corba:raise(#'CosPropertyService_FixedProperty'{});
-update_property([{Name, _, fixed_readonly}|_], Name, both, _, _, _) ->
- corba:raise(#'CosPropertyService_FixedProperty'{});
-update_property([{Name, #any{typecode = TC}, Mode}|T], Name,
- value, #any{typecode = TC, value = Value}, _Mod, Acc) ->
- [{Name, #any{typecode = TC, value = Value}, Mode}|T]++Acc;
-update_property([{Name, #any{typecode = TC}, _Mode}|T], Name,
- both, #any{typecode = TC, value = Value}, Mod, Acc) ->
- [{Name, #any{typecode = TC, value = Value}, Mod}|T]++Acc;
-update_property([{Name, _, _}|_], Name, value, _, _, _) ->
- corba:raise(#'CosPropertyService_ConflictingProperty'{});
-update_property([{Name, _, _}|_], Name, both, _, _, _) ->
- corba:raise(#'CosPropertyService_ConflictingProperty'{});
-%% Normally we don't need to raise an exception for the two following cases but
-%% to be able to manage static Properties we must raise an exception. Well,
-%% on the other hand, why should a user try to change a mode to the same value?!
-%% But we have no other option.
-update_property([{Name, _Value, fixed_normal}|_T], Name, mode, _, fixed_normal, _Acc) ->
- corba:raise(#'CosPropertyService_FixedProperty'{});
-update_property([{Name, _Value, fixed_readonly}|_T], Name, mode, _, fixed_readonly, _Acc) ->
- corba:raise(#'CosPropertyService_FixedProperty'{});
-update_property([{Name, _Value, fixed_normal}|_T], Name, mode, _, _Mode, _Acc) ->
- corba:raise(#'CosPropertyService_UnsupportedMode'{});
-update_property([{Name, _Value, fixed_readonly}|_T], Name, mode, _, _Mode, _Acc) ->
- corba:raise(#'CosPropertyService_UnsupportedMode'{});
-update_property([{Name, Value, _}|T], Name, mode, _, Mode, Acc) ->
- [{Name, Value, Mode}|T]++Acc;
-update_property([H|T], Name, Which, Value, Mode, Acc) ->
- update_property(T, Name, Which, Value, Mode, [H|Acc]).
-
-
-lookup_table(Key) when is_binary(Key) ->
- _RF = ?read_function({oe_CosPropertyService, Key}),
- case mnesia:transaction(_RF) of
- {atomic, [#oe_CosPropertyService{properties=Properties}]} ->
- Properties;
- {atomic, []} ->
- corba:raise(#'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO});
- _Other ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
-lookup_table(Key) when is_list(Key) ->
- Key;
-lookup_table(_) ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
-
-mnesia_transaction(Fun) ->
- case mnesia:transaction(Fun) of
- {atomic, {'EXCEPTION', E}} ->
- corba:raise(E);
- {atomic, ok} ->
- ok;
- {atomic, Reply} ->
- Reply;
- _Other ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-mnesia_read(State) ->
- case mnesia:wread({oe_CosPropertyService, ?get_DBKey(State)}) of
- [#oe_CosPropertyService{properties = X}] ->
- X;
- _Other ->
- {'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}}
- end.
-
-mnesia_write(State, X) ->
- mnesia:write(#oe_CosPropertyService{key = ?get_DBKey(State), properties = X}).
-
-%% Check a write transaction
-write_result({atomic,ok}) -> ok;
-write_result(_Foo) ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
-
-evaluate_properties_data(State, PropertySeq) ->
- evaluate_properties_data(State, PropertySeq, [], []).
-
-evaluate_properties_data(_State, [], OKProperties, Exc) ->
- {OKProperties, Exc};
-
-evaluate_properties_data(State, [#'CosPropertyService_Property'
- {property_name = Name,
- property_value = Value}|T], Acc, Exc) ->
- case catch evaluate_property_data(State, Value, Name) of
- ok ->
- evaluate_properties_data(State, T, [#'CosPropertyService_Property'
- {property_name = Name,
- property_value = Value}|Acc], Exc);
- {'EXCEPTION', E} when is_record(E, 'CosPropertyService_UnsupportedTypeCode') ->
- evaluate_properties_data(State, T, Acc,
- [#'CosPropertyService_PropertyException'
- {reason = unsupported_type_code,
- failing_property_name = Name}|Exc]);
- {'EXCEPTION', E} when is_record(E, 'CosPropertyService_UnsupportedProperty') ->
- evaluate_properties_data(State, T, Acc,
- [#'CosPropertyService_PropertyException'
- {reason = unsupported_property,
- failing_property_name = Name}|Exc])
- end;
-evaluate_properties_data(State, [#'CosPropertyService_PropertyDef'
- {property_name = Name,
- property_value = Value,
- property_mode = Mode}|T], Acc, Exc) ->
- case catch evaluate_property_data(State, Value, Name) of
- ok ->
- evaluate_properties_data(State, T, [#'CosPropertyService_PropertyDef'
- {property_name = Name,
- property_value = Value,
- property_mode = Mode}|Acc], Exc);
- {'EXCEPTION', E} when is_record(E, 'CosPropertyService_UnsupportedTypeCode') ->
- evaluate_properties_data(State, T, Acc,
- [#'CosPropertyService_PropertyException'
- {reason = unsupported_type_code,
- failing_property_name = Name}|Exc]);
- {'EXCEPTION', E} when is_record(E, 'CosPropertyService_UnsupportedProperty') ->
- evaluate_properties_data(State, T, Acc,
- [#'CosPropertyService_PropertyException'
- {reason = unsupported_property,
- failing_property_name = Name}|Exc])
- end;
-evaluate_properties_data(_, _, _, _) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-evaluate_property_data(State, _, _) when ?no_PropertyLimits(State),
- ?no_TypeLimits(State) ->
- ok;
-evaluate_property_data(State, Value, _Name) when ?no_PropertyLimits(State) ->
- case lists:member(any:get_typecode(Value), ?get_okTypes(State)) of
- true ->
- ok;
- _ ->
- corba:raise(#'CosPropertyService_UnsupportedTypeCode'{})
- end;
-evaluate_property_data(State, _Value, Name) when ?no_TypeLimits(State) ->
- case lists:any(?MemberName(Name), ?get_okProperties(State)) of
- true ->
- ok;
- _ ->
- corba:raise(#'CosPropertyService_UnsupportedProperty'{})
- end;
-evaluate_property_data(State, Value, Name) ->
- case lists:any(?MemberName(Name), ?get_okProperties(State)) of
- true ->
- case lists:member(any:get_typecode(Value), ?get_okTypes(State)) of
- true ->
- ok;
- _ ->
- corba:raise(#'CosPropertyService_UnsupportedTypeCode'{})
- end;
- _ ->
- corba:raise(#'CosPropertyService_UnsupportedProperty'{})
- end.
-
-
-%%----------------------------------------------------------------------
-%% Debugging functions
-%%----------------------------------------------------------------------
-dump() ->
- case catch mnesia:dirty_first('oe_CosPropertyService') of
- {'EXIT', R} ->
- io:format("Exited with ~p\n",[R]);
- Key ->
- dump_print(Key),
- dump_loop(Key)
- end.
-
-dump_loop(PreviousKey) ->
- case catch mnesia:dirty_next('oe_CosPropertyService', PreviousKey) of
- {'EXIT', R} ->
- io:format("Exited with ~p\n",[R]);
- '$end_of_table' ->
- ok;
- Key ->
- dump_print(Key),
- dump_loop(Key)
- end.
-
-dump_print(Key) ->
- case catch mnesia:dirty_read({'oe_CosPropertyService', Key}) of
- {'EXIT', R} ->
- io:format("Exited with ~p\n",[R]);
- [{_,_,X}] ->
- io:format("Property: ~p~n", [X]);
- _ ->
- ok
- end.
-
-
-%%-------------------------- END OF MODULE -----------------------------
diff --git a/lib/cosProperty/src/CosPropertyService_PropertySetFactory_impl.erl b/lib/cosProperty/src/CosPropertyService_PropertySetFactory_impl.erl
deleted file mode 100644
index bc6572b634..0000000000
--- a/lib/cosProperty/src/CosPropertyService_PropertySetFactory_impl.erl
+++ /dev/null
@@ -1,183 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosPropertyService_PropertySetFactory_impl.erl
-%% Description :
-%%
-%%----------------------------------------------------------------------
--module('CosPropertyService_PropertySetFactory_impl').
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include("CosPropertyService.hrl").
--include("cosProperty.hrl").
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
--export([init/1,
- terminate/2,
- code_change/3]).
-
--export([create_propertyset/2,
- create_constrained_propertyset/4,
- create_initial_propertyset/3]).
-
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
--export([]).
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {}).
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
--define(checkTCfun, fun(TC) -> orber_tc:check_tc(TC) end).
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%----------------------------------------------------------------------
-init([]) ->
- {ok, #state{}}.
-
-%%----------------------------------------------------------------------
-%% Function : terminate/2
-%% Returns : any (ignored by gen_server)
-%% Description: Shutdown the server
-%%----------------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-%%----------------------------------------------------------------------
-%% Function : code_change/3
-%% Returns : {ok, NewState}
-%% Description: Convert process state when code is changed
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%----------------------------------------------------------------------
-%% Function : create_propertyset
-%% Arguments :
-%% Returns : CosPropertyService::PropertySet reference.
-%% Description:
-%%----------------------------------------------------------------------
-create_propertyset(_OE_This, State) ->
- {reply,
- 'CosPropertyService_PropertySetDef':
- oe_create({normal, [], [], [], ?PropertySet}, [{pseudo, true}]),
- State}.
-
-%%----------------------------------------------------------------------
-%% Function : create_constrained_propertyset
-%% Arguments : PropTypes - list of property types.
-%% Properties - list of properties.
-%% Returns : CosPropertyService::PropertySet |
-%% {'EXCEPTION', CosPropertyService::ConstraintNotSupported}
-%% Description:
-%%----------------------------------------------------------------------
-create_constrained_propertyset(_OE_This, State, PropTypes, Properties) ->
- case lists:all(?checkTCfun, PropTypes) of
- true ->
- crosscheckTC(Properties, PropTypes),
- {reply,
- 'CosPropertyService_PropertySetDef':
- oe_create({normal, PropTypes, Properties, [], ?PropertySet},
- [{pseudo, true}]),
- State};
- false ->
- corba:raise(#'CosPropertyService_ConstraintNotSupported'{})
- end.
-
-crosscheckTC([], _) ->
- ok;
-crosscheckTC([#'CosPropertyService_Property'
- {property_name = Name,
- property_value = Value}|T], TCs) ->
- case lists:member(any:get_typecode(Value), TCs) of
- true when Name =/= "" ->
- crosscheckTC(T, TCs);
- _ ->
- corba:raise(#'CosPropertyService_ConstraintNotSupported'{})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : create_initial_propertyset
-%% Arguments : Properties - list of properties.
-%% Returns : CosPropertyService::PropertySetDef |
-%% {'EXCEPTION', CosPropertyService::MultipleExceptions}
-%% Description:
-%%----------------------------------------------------------------------
-create_initial_propertyset(_OE_This, State, Properties) ->
- InitProps = evaluate_propertyset(Properties),
- {reply,
- 'CosPropertyService_PropertySetDef':
- oe_create({normal, [], [], InitProps, ?PropertySet}, [{pseudo, true}]),
- State}.
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-evaluate_propertyset(Sets) ->
- case evaluate_propertyset(Sets, [], []) of
- {ok, NewProperties} ->
- NewProperties;
- {error, Exc} ->
- corba:raise(#'CosPropertyService_MultipleExceptions'{exceptions = Exc})
- end.
-
-evaluate_propertyset([], NewProperties, []) ->
- %% No exceptions found.
- {ok, NewProperties};
-evaluate_propertyset([], _, Exc) ->
- {error, Exc};
-evaluate_propertyset([#'CosPropertyService_Property'
- {property_name = Name,
- property_value = Value}|T], X, Exc) ->
- case orber_tc:check_tc(any:get_typecode(Value)) of
- true ->
- evaluate_propertyset(T, [{Name, Value, normal}|X], Exc);
- false ->
- evaluate_propertyset(T, X, [#'CosPropertyService_PropertyException'
- {reason = unsupported_type_code,
- failing_property_name = Name}|Exc])
- end.
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
diff --git a/lib/cosProperty/src/Makefile b/lib/cosProperty/src/Makefile
deleted file mode 100644
index 1fdc258a6d..0000000000
--- a/lib/cosProperty/src/Makefile
+++ /dev/null
@@ -1,188 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-
-ifeq ($(TYPE),debug)
-ERL_COMPILE_FLAGS += -Ddebug -W
-endif
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(COSPROPERTY_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/cosProperty-$(VSN)
-
-EXTERNAL_INC_PATH = ../include
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES = \
- cosProperty \
- CosPropertyService_PropertySetDefFactory_impl \
- CosPropertyService_PropertySetDef_impl \
- CosPropertyService_PropertySetFactory_impl \
- CosPropertyService_PropertiesIterator_impl \
- CosPropertyService_PropertyNamesIterator_impl
-
-
-ERL_FILES = $(MODULES:%=%.erl)
-HRL_FILES = \
- cosProperty.hrl \
-
-GEN_ERL_FILES = \
- oe_CosProperty.erl \
- CosPropertyService_ConflictingProperty.erl \
- CosPropertyService_ConstraintNotSupported.erl \
- CosPropertyService_FixedProperty.erl \
- CosPropertyService_InvalidPropertyName.erl \
- CosPropertyService_MultipleExceptions.erl \
- CosPropertyService_Properties.erl \
- CosPropertyService_PropertiesIterator.erl \
- CosPropertyService_Property.erl \
- CosPropertyService_PropertyDef.erl \
- CosPropertyService_PropertyDefs.erl \
- CosPropertyService_PropertyException.erl \
- CosPropertyService_PropertyExceptions.erl \
- CosPropertyService_PropertyMode.erl \
- CosPropertyService_PropertyModes.erl \
- CosPropertyService_PropertyNames.erl \
- CosPropertyService_PropertyNamesIterator.erl \
- CosPropertyService_PropertyNotFound.erl \
- CosPropertyService_PropertySet.erl \
- CosPropertyService_PropertySetDef.erl \
- CosPropertyService_PropertySetDefFactory.erl \
- CosPropertyService_PropertySetFactory.erl \
- CosPropertyService_PropertyTypes.erl \
- CosPropertyService_ReadOnlyProperty.erl \
- CosPropertyService_UnsupportedMode.erl \
- CosPropertyService_UnsupportedProperty.erl \
- CosPropertyService_UnsupportedTypeCode.erl
-
-LOCAL_HRL_FILES = \
- oe_CosProperty.hrl \
- CosPropertyService.hrl \
- CosPropertyService_PropertiesIterator.hrl \
- CosPropertyService_PropertyNamesIterator.hrl \
- CosPropertyService_PropertySet.hrl \
- CosPropertyService_PropertySetDef.hrl \
- CosPropertyService_PropertySetDefFactory.hrl \
- CosPropertyService_PropertySetFactory.hrl
-
-GEN_HRL_FILES = $(LOCAL_HRL_FILES:%=$(EXTERNAL_INC_PATH)/%)
-
-GEN_FILES = \
- $(GEN_HRL_FILES) \
- $(GEN_ERL_FILES)
-
-TARGET_FILES = \
- $(GEN_ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR)) \
- $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-IDL_FILES = \
- CosProperty.idl
-
-APPUP_FILE = cosProperty.appup
-APPUP_SRC = $(APPUP_FILE).src
-APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
-
-APP_FILE = cosProperty.app
-APP_SRC = $(APP_FILE).src
-APP_TARGET = $(EBIN)/$(APP_FILE)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/cosProperty/ebin \
- -pa $(ERL_TOP)/lib/ic/ebin\
- -pa $(ERL_TOP)/lib/orber/ebin
-
-# The -pa option is just used temporary until erlc can handle
-# includes from other directories than ../include .
-ERL_COMPILE_FLAGS += \
- $(ERL_IDL_FLAGS) \
- -pa $(ERL_TOP)/lib/orber/include \
- -pa $(ERL_TOP)/lib/cosProperty/include \
- -I$(ERL_TOP)/lib/cosProperty/include \
- -I$(ERL_TOP)/lib/orber/include \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,app_vsn,"cosProperty_$(COSPROPERTY_VSN)"}'
-
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
-
-debug:
- @${MAKE} TYPE=debug opt
-
-cleanb:
- rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
- rm -f errs core *~
-
-clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
- rm -f errs core *~
-
-$(APP_TARGET): $(APP_SRC)
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
-
-$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
-
-docs:
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-IDL-GENERATED: CosProperty.idl
- $(gen_verbose)erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosProperty.cfg"}' CosProperty.idl
- $(V_at)mv $(LOCAL_HRL_FILES) $(EXTERNAL_INC_PATH)
- $(V_at)>IDL-GENERATED
-
-$(GEN_FILES): IDL-GENERATED
-
-$(TARGET_FILES): IDL-GENERATED
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
- $(INSTALL_DIR) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(GEN_FILES) $(IDL_FILES) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILES) "$(RELSYSDIR)/src"
- $(INSTALL_DIR) "$(RELSYSDIR)/include"
- $(INSTALL_DATA) $(GEN_HRL_FILES) "$(RELSYSDIR)/include"
-
-release_docs_spec:
diff --git a/lib/cosProperty/src/cosProperty.app.src b/lib/cosProperty/src/cosProperty.app.src
deleted file mode 100644
index 7fad7a602a..0000000000
--- a/lib/cosProperty/src/cosProperty.app.src
+++ /dev/null
@@ -1,47 +0,0 @@
-{application, cosProperty,
- [{description, "The Erlang CosProperty application"},
- {vsn, "%VSN%"},
- {modules,
- [
- 'cosProperty',
- 'CosPropertyService_PropertySetDefFactory_impl',
- 'CosPropertyService_PropertySetDef_impl',
- 'CosPropertyService_PropertySetFactory_impl',
- 'CosPropertyService_PropertiesIterator_impl',
- 'CosPropertyService_PropertyNamesIterator_impl',
- 'oe_CosProperty',
- 'CosPropertyService_ConflictingProperty',
- 'CosPropertyService_ConstraintNotSupported',
- 'CosPropertyService_FixedProperty',
- 'CosPropertyService_InvalidPropertyName',
- 'CosPropertyService_MultipleExceptions',
- 'CosPropertyService_Properties',
- 'CosPropertyService_PropertiesIterator',
- 'CosPropertyService_Property',
- 'CosPropertyService_PropertyDef',
- 'CosPropertyService_PropertyDefs',
- 'CosPropertyService_PropertyException',
- 'CosPropertyService_PropertyExceptions',
- 'CosPropertyService_PropertyMode',
- 'CosPropertyService_PropertyModes',
- 'CosPropertyService_PropertyNames',
- 'CosPropertyService_PropertyNamesIterator',
- 'CosPropertyService_PropertyNotFound',
- 'CosPropertyService_PropertySet',
- 'CosPropertyService_PropertySetDef',
- 'CosPropertyService_PropertySetDefFactory',
- 'CosPropertyService_PropertySetFactory',
- 'CosPropertyService_PropertyTypes',
- 'CosPropertyService_ReadOnlyProperty',
- 'CosPropertyService_UnsupportedMode',
- 'CosPropertyService_UnsupportedProperty',
- 'CosPropertyService_UnsupportedTypeCode'
- ]
- },
- {registered, [oe_cosPropertySup]},
- {applications, [orber, stdlib, kernel]},
- {env, []},
- {mod, {cosProperty, []}},
- {runtime_dependencies, ["stdlib-2.0","orber-3.6.27","mnesia-4.12",
- "kernel-3.0","erts-7.0"]}
-]}.
diff --git a/lib/cosProperty/src/cosProperty.appup.src b/lib/cosProperty/src/cosProperty.appup.src
deleted file mode 100644
index f3eead4a0c..0000000000
--- a/lib/cosProperty/src/cosProperty.appup.src
+++ /dev/null
@@ -1,6 +0,0 @@
-{"%VSN%",
- [
- ],
- [
- ]
-}.
diff --git a/lib/cosProperty/src/cosProperty.erl b/lib/cosProperty/src/cosProperty.erl
deleted file mode 100644
index e94d200c2f..0000000000
--- a/lib/cosProperty/src/cosProperty.erl
+++ /dev/null
@@ -1,416 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2015. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : cosProperty.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module(cosProperty).
-
-%%--------------- INCLUDES -----------------------------------
--include("cosProperty.hrl").
--include_lib("cosProperty/include/CosPropertyService.hrl").
-
-%%--------------- EXPORTS-------------------------------------
-%% cosProperty API external
--export([start/0,
- start_SetDefFactory/0,
- start_SetFactory/0,
- stop_SetDefFactory/1,
- stop_SetFactory/1,
- stop/0,
- install/0,
- install/1,
- install_db/0,
- install_db/1,
- install_db/2,
- uninstall/0,
- uninstall/1,
- uninstall_db/0]).
-
-%% cosProperty API internal
--export([create_link/3,
- get_option/3,
- type_check/2,
- query_result/1,
- start_PropertiesIterator/1,
- start_PropertyNamesIterator/1,
- create_static_SetDef/2]).
-
-%% Application callbacks
--export([start/2, init/1, stop/1]).
-
-%%--------------- DEFINES ------------------------------------
-
--define(SUPERVISOR_NAME, oe_cosPropertySup).
--define(SUP_FLAG, {simple_one_for_one,50,10}).
--define(SUP_PROP_SPEC(T,I),
- ['CosPropertyService_PropertiesIterator',I,
- [{sup_child, true}, {regname, {global, T}}]]).
--define(SUP_NAMES_SPEC(T,I),
- ['CosPropertyService_PropertyNamesIterator',I,
- [{sup_child, true}, {regname, {global, T}}]]).
--define(SUP_CHILD,
- {"oe_PropertyChild",
- {cosProperty,create_link, []},
- transient,100000,worker,
- []}).
-
-%%------------------------------------------------------------
-%% function : install
-%% Arguments: -
-%% Returns : ok | EXIT | EXCEPTION
-%% Effect : Install necessary data in the IFR DB
-%%------------------------------------------------------------
-install() ->
- install([]).
-install(_Options) ->
- case catch oe_CosProperty:'oe_register'() of
- ok ->
- ok;
- {'EXIT',{unregistered,App}} ->
- ?write_ErrorMsg("Unable to register cosProperty; application ~p not registered.~n",
- [App]),
- exit({unregistered,App});
- {'EXCEPTION',_} ->
- ?write_ErrorMsg("Unable to register cosProperty; propably already registered.
-You are adviced to confirm this.~n", []),
- exit({error, "Register in the IFR failed."});
- Reason ->
- ?write_ErrorMsg("Unable to register cosProperty; reason ~p", [Reason]),
- exit({error, "Register in the IFR failed."})
- end.
-
-%%------------------------------------------------------------
-%% function : install_db
-%% Arguments: -
-%% Returns : ok | EXIT | EXCEPTION
-%% Effect : Install necessary data in the IFR DB
-%%------------------------------------------------------------
-install_db() ->
- install_db(infinity, []).
-install_db(Timeout) ->
- install_db(Timeout, []).
-install_db(Timeout, Options) ->
- case install_table(Timeout, Options) of
- ok ->
- ok;
- {error, [DB_tables_created, Wait]} ->
- ?write_ErrorMsg("Able to register cosProperty but failed adding table in mnesia (~p, ~p)",
- [DB_tables_created, Wait]),
- exit({error, "Adding data in mnesia failed."});
- Why ->
- ?write_ErrorMsg("Able to register cosProperty but failed adding table in mnesia with reason ~p",
- [Why]),
- exit({error, "Adding data in mnesia failed."})
- end.
-
-%%------------------------------------------------------------
-%% function : install_table
-%% Arguments: -
-%% Returns : ok | {error, Data}
-%% Effect : Install necessary data in mnesia
-%%------------------------------------------------------------
-install_table(Timeout, Options) ->
- %% Fetch a list of the defined tables to see if 'oe_CosPropertyService'
- %% is defined.
- AllTabs = mnesia:system_info(tables),
- DB_tables_created =
- case lists:member('oe_CosPropertyService', AllTabs) of
- true ->
- case lists:member({local_content, true},
- Options) of
- true->
- mnesia:add_table_copy('oe_CosPropertyService',
- node(),
- ram_copies);
- _->
- mnesia:create_table('oe_CosPropertyService',[{attributes,
- record_info(fields,
- 'oe_CosPropertyService')}
- |Options])
- end;
- _ ->
- mnesia:create_table('oe_CosPropertyService',[{attributes,
- record_info(fields,
- 'oe_CosPropertyService')}
- |Options])
- end,
- Wait = mnesia:wait_for_tables(['oe_CosPropertyService'], Timeout),
- %% Check if any error has occured yet. If there are errors, return them.
- if
- DB_tables_created == {atomic, ok},
- Wait == ok ->
- ok;
- true ->
- {error, [DB_tables_created, Wait]}
- end.
-
-
-%%------------------------------------------------------------
-%% function : query_result
-%% Arguments: -
-%% Returns : error | Data
-%% Effect : Check a read transaction
-%%------------------------------------------------------------
-query_result(Qres) ->
- case Qres of
- {atomic, [Hres]} ->
- Hres#oe_CosPropertyService.properties;
- {atomic, [_Hres | _Tres]} ->
- error;
- {atomic, []} ->
- error;
- _Other ->
- error
- end.
-
-%%------------------------------------------------------------
-%% function : uninstall
-%% Arguments: -
-%% Returns : ok | EXIT | EXCEPTION
-%% Effect : Remove data related to cosProperty from the IFR DB
-%%------------------------------------------------------------
-uninstall() ->
- uninstall([]).
-uninstall(_Options) ->
- application:stop(cosProperty),
- oe_CosProperty:oe_unregister().
-
-%%------------------------------------------------------------
-%% function : uninstall
-%% Arguments: -
-%% Returns : ok | EXIT | EXCEPTION
-%% Effect : Remove data related to cosProperty from the IFR DB
-%%------------------------------------------------------------
-uninstall_db() ->
- application:stop(cosProperty),
- case mnesia:delete_table('oe_CosPropertyService') of
- {atomic, ok} ->
- ok;
- {aborted, _Reason} ->
- exit({error, "Removing data from mnesia failed."})
- end.
-
-%%------------------------------------------------------------
-%% function : create_static_SetDef
-%% Arguments:
-%% Returns :
-%% Effect : Starts or stops the cosProperty application.
-%%------------------------------------------------------------
-create_static_SetDef(PropTypes, PropDefs) ->
- InitProps = propertyDef2local(PropDefs, []),
- 'CosPropertyService_PropertySetDef':oe_create({static, fixed_readonly, PropTypes,
- PropDefs, InitProps,
- ?PropertySetDef},
- [{pseudo, true}]).
-propertyDef2local([#'CosPropertyService_PropertyDef'
- {property_name = Name,
- property_value = Value,
- property_mode = fixed_readonly}|T], Acc) ->
- propertyDef2local(T, [{Name, Value, fixed_readonly}|Acc]);
-propertyDef2local([], Acc) ->
- Acc;
-propertyDef2local(_, _) ->
- exit({error, "Bad Mode type supplied. Must be fixed_readonly"}).
-
-%%------------------------------------------------------------
-%% function : start/stop
-%% Arguments:
-%% Returns :
-%% Effect : Starts or stops the cosProperty application.
-%%------------------------------------------------------------
-start() ->
- application:start(cosProperty).
-stop() ->
- application:stop(cosProperty).
-
-
-
-%%-----------------------------------------------------------%
-%% function : start_SetDefFactory
-%% Arguments: -
-%% Returns : A PropertySetDefFactory reference.
-%% Effect :
-%%------------------------------------------------------------
-start_SetDefFactory() ->
- 'CosPropertyService_PropertySetDefFactory':oe_create([], [{pseudo, true}]).
-
-%%-----------------------------------------------------------%
-%% function : start_SetFactory
-%% Arguments: -
-%% Returns : A PropertySetFactory reference.
-%% Effect :
-%%------------------------------------------------------------
-start_SetFactory() ->
- 'CosPropertyService_PropertySetFactory':oe_create([], [{pseudo, true}]).
-
-%%-----------------------------------------------------------%
-%% function : stop_SetDefFactory
-%% Arguments: Factory - A PropertySetDefFactory reference.
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-stop_SetDefFactory(Factory) ->
- corba:dispose(Factory).
-
-%%-----------------------------------------------------------%
-%% function : stop_SetFactory
-%% Arguments: Factory - A PropertySetFactory reference.
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-stop_SetFactory(Factory) ->
- corba:dispose(Factory).
-
-%%------------------------------------------------------------
-%% function : start
-%% Arguments: Type - see module application
-%% Arg - see module application
-%% Returns :
-%% Effect : Module callback for application
-%%------------------------------------------------------------
-start(_, _) ->
- supervisor:start_link({local, ?SUPERVISOR_NAME}, cosProperty, app_init).
-
-
-%%------------------------------------------------------------
-%% function : stop
-%% Arguments: Arg - see module application
-%% Returns :
-%% Effect : Module callback for application
-%%------------------------------------------------------------
-stop(_) ->
- ok.
-
-%%-----------------------------------------------------------%
-%% function : init
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-%% Starting using create_factory/X
-init(own_init) ->
- {ok,{?SUP_FLAG, [?SUP_CHILD]}};
-%% When starting as an application.
-init(app_init) ->
- {ok,{?SUP_FLAG, [?SUP_CHILD]}}.
-
-%%-----------------------------------------------------------%
-%% function : create_link
-%% Arguments: Module - which Module to call
-%% Env/ArgList - ordinary oe_create arguments.
-%% Returns :
-%% Exception:
-%% Effect : Necessary since we want the supervisor to be a
-%% 'simple_one_for_one'. Otherwise, using for example,
-%% 'one_for_one', we have to call supervisor:delete_child
-%% to remove the childs startspecification from the
-%% supervisors internal state.
-%%------------------------------------------------------------
-create_link(Module, Env, ArgList) ->
- Module:oe_create_link(Env, ArgList).
-
-%%-----------------------------------------------------------%
-%% function : start_PropertiesIterator
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-start_PropertiesIterator(Args) ->
- Name = create_name(propertiesIterator),
- case supervisor:start_child(?SUPERVISOR_NAME, ?SUP_PROP_SPEC(Name, Args)) of
- {ok, Pid, Obj} when is_pid(Pid) ->
- Obj;
- _Other->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%-----------------------------------------------------------%
-%% function : start_PropertyNamesIterator
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-start_PropertyNamesIterator(Args) ->
- Name = create_name(propertiesIterator),
- case supervisor:start_child(?SUPERVISOR_NAME, ?SUP_NAMES_SPEC(Name, Args)) of
- {ok, Pid, Obj} when is_pid(Pid) ->
- Obj;
- _Other->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-
-%%-----------------------------------------------------------%
-%% function : get_option
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-get_option(Key, OptionList, DefaultList) ->
- case lists:keysearch(Key, 1, OptionList) of
- {value,{Key,Value}} ->
- Value;
- _ ->
- case lists:keysearch(Key, 1, DefaultList) of
- {value,{Key,Value}} ->
- Value;
- _->
- {error, "Invalid option"}
- end
- end.
-
-%%-----------------------------------------------------------%
-%% function : type_check
-%% Arguments: Obj - objectrefernce to test.
-%% Mod - Module which contains typeID/0.
-%% Returns : 'ok' or raises exception.
-%% Effect :
-%%------------------------------------------------------------
-type_check(Obj, Mod) ->
- case catch corba_object:is_a(Obj,Mod:typeID()) of
- true ->
- ok;
- _ ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end.
-
-
-%%-----------------------------------------------------------%
-%% function : create_name/1
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-create_name(Type) ->
- Time = erlang:system_time(),
- Unique = erlang:unique_integer([positive]),
- lists:concat(['oe_',node(),'_',Type,'_',Time,'_',Unique]).
-
-%%--------------- END OF MODULE ------------------------------
-
-
diff --git a/lib/cosProperty/src/cosProperty.hrl b/lib/cosProperty/src/cosProperty.hrl
deleted file mode 100644
index 0225a43ebd..0000000000
--- a/lib/cosProperty/src/cosProperty.hrl
+++ /dev/null
@@ -1,82 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : cosProperty.hrl
-%% Purpose :
-%%----------------------------------------------------------------------
-
-
-%%--------------- INCLUDES -----------------------------------
-%% External
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-
-%%-----------------------------------------------------------------
-%% Mnesia Table definition record
-%%-----------------------------------------------------------------
--record('oe_CosPropertyService', {key, properties}).
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
--define(PropertySet, 0).
--define(PropertySetDef, 1).
-
-%% This macro returns a read fun suitable for evaluation in a transaction
--define(read_function(Objkey),
- fun() ->
- mnesia:read(Objkey)
- end).
-
-%% This macro returns a write fun suitable for evaluation in a transaction
--define(write_function(R),
- fun() ->
- mnesia:write(R)
- end).
-
-%% This macro returns a delete fun suitable for evaluation in a transaction
--define(delete_function(R),
- fun() ->
- mnesia:delete(R)
- end).
-
--define(query_check(Q_res), {atomic, Q_res}).
-
-
--define(write_ErrorMsg(Txt, Arg),
-error_logger:error_msg("================ CosProperty ==============~n"
- Txt
- "===========================================~n",
- Arg)).
-
-
-
--ifdef(debug).
--define(debug_print(F,A),
- io:format("[LINE: ~p MODULE: ~p] "++F,[?LINE, ?MODULE]++A)).
--define(property_TypeCheck(O,M), 'cosProperty':type_check(O,M)).
--else.
--define(debug_print(F,A), ok).
--define(property_TypeCheck(O,I), ok).
--endif.
-
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosProperty/test/Makefile b/lib/cosProperty/test/Makefile
deleted file mode 100644
index 5f599c9621..0000000000
--- a/lib/cosProperty/test/Makefile
+++ /dev/null
@@ -1,129 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(COSPROPERTY_VSN)
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/cosProperty_test
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-TEST_SPEC_FILE = cosProperty.spec
-COVER_FILE = cosProperty.cover
-
-
-IDL_FILES =
-
-IDLOUTDIR = idl_output
-
-MODULES = \
- property_SUITE \
- generated_SUITE
-
-GEN_MODULES = \
-
-GEN_HRL_FILES = \
-
-ERL_FILES = $(MODULES:%=%.erl)
-
-HRL_FILES =
-
-GEN_FILES = \
- $(GEN_HRL_FILES:%=$(IDLOUTDIR)/%) \
- $(GEN_MODULES:%=$(IDLOUTDIR)/%.erl)
-
-GEN_TARGET_FILES = $(GEN_MODULES:%=$(IDLOUTDIR)/%.$(EMULATOR))
-
-SUITE_TARGET_FILES = $(MODULES:%=%.$(EMULATOR))
-
-TARGET_FILES = \
- $(GEN_TARGET_FILES) \
- $(SUITE_TARGET_FILES)
-
-
-# ----------------------------------------------------
-# PROGRAMS
-# ----------------------------------------------------
-LOCAL_CLASSPATH = $(ERL_TOP)lib/cosProperty/priv:$(ERL_TOP)lib/cosProperty/test
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/cosProperty/ebin \
- -pa $(ERL_TOP)/lib/cosProperty/src \
- -pa $(ERL_TOP)/lib/orber/ebin \
- -pa $(ERL_TOP)/lib/ic/ebin
-
-ERL_COMPILE_FLAGS += \
- $(ERL_IDL_FLAGS) \
- -pa $(ERL_TOP)/lib/orber/include \
- -pa $(ERL_TOP)/lib/cosProperty/ebin \
- -pa $(ERL_TOP)/lib/cosProperty/test/idl_output \
- -I$(ERL_TOP)/lib/orber/include \
- -I$(ERL_TOP)/lib/cosProperty/src \
- -I$(ERL_TOP)/lib/cosProperty \
- -I$(ERL_TOP)/lib/cosProperty/test/$(IDLOUTDIR)
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-
-tests debug opt: $(TARGET_FILES)
-
-clean:
- rm -f idl_output/*
- rm -f $(TARGET_FILES)
- rm -f errs core *~
-
-docs:
-
-# ----------------------------------------------------
-# Special Targets
-# ----------------------------------------------------
-
-# ----------------------------------------------------
-# Release Targets
-# ----------------------------------------------------
-# We don't copy generated intermediate erlang and hrl files
-
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec:
-
-release_docs_spec:
-
-release_tests_spec: tests
- $(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) \
- $(COVER_FILE) $(ERL_FILES) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(SUITE_TARGET_FILES) "$(RELSYSDIR)"
-# $(INSTALL_DIR) "$(RELSYSDIR)/$(IDLOUTDIR)"
-# $(INSTALL_DATA) $(GEN_TARGET_FILES) $(GEN_FILES) \
-# "$(RELSYSDIR)/$(IDLOUTDIR)"
-
diff --git a/lib/cosProperty/test/cosProperty.cover b/lib/cosProperty/test/cosProperty.cover
deleted file mode 100644
index a0f5f17671..0000000000
--- a/lib/cosProperty/test/cosProperty.cover
+++ /dev/null
@@ -1,2 +0,0 @@
-{incl_app,cosProperty,details}.
-
diff --git a/lib/cosProperty/test/cosProperty.spec b/lib/cosProperty/test/cosProperty.spec
deleted file mode 100644
index d3d44321c8..0000000000
--- a/lib/cosProperty/test/cosProperty.spec
+++ /dev/null
@@ -1 +0,0 @@
-{suites,"../cosProperty_test",all}.
diff --git a/lib/cosProperty/test/generated_SUITE.erl b/lib/cosProperty/test/generated_SUITE.erl
deleted file mode 100644
index 313f5bf8f9..0000000000
--- a/lib/cosProperty/test/generated_SUITE.erl
+++ /dev/null
@@ -1,546 +0,0 @@
-%%-----------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File : generated_SUITE.erl
-%% Purpose :
-%%-----------------------------------------------------------------
-
--module(generated_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
-
--define(default_timeout, test_server:minutes(3)).
-
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
--define(nomatch(Not, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- Not ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS);
- _ ->
- AcTuAlReS
- end
- end()).
-
-
--define(checktc(_Op),
- fun(TC) ->
- case orber_tc:check_tc(TC) of
- false ->
- io:format("###### ERROR ERROR ######~n~p - ~p~n", [Op, TC]),
- exit(TC);
- true ->
- true
- end
- end).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- ['CosPropertyService_ConflictingProperty',
- 'CosPropertyService_ConstraintNotSupported',
- 'CosPropertyService_FixedProperty',
- 'CosPropertyService_InvalidPropertyName',
- 'CosPropertyService_MultipleExceptions',
- 'CosPropertyService_Properties',
- 'CosPropertyService_Property',
- 'CosPropertyService_PropertyDef',
- 'CosPropertyService_PropertyDefs',
- 'CosPropertyService_PropertyException',
- 'CosPropertyService_PropertyExceptions',
- 'CosPropertyService_PropertyMode',
- 'CosPropertyService_PropertyModes',
- 'CosPropertyService_PropertyNames',
- 'CosPropertyService_PropertyNotFound',
- 'CosPropertyService_PropertyTypes',
- 'CosPropertyService_ReadOnlyProperty',
- 'CosPropertyService_UnsupportedMode',
- 'CosPropertyService_UnsupportedProperty',
- 'CosPropertyService_UnsupportedTypeCode',
- 'CosPropertyService_PropertyNamesIterator',
- 'CosPropertyService_PropertiesIterator',
- 'CosPropertyService_PropertySet',
- 'CosPropertyService_PropertySetDef',
- 'CosPropertyService_PropertySetDefFactory',
- 'CosPropertyService_PropertySetFactory'].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_ConflictingProperty'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_ConflictingProperty'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_ConflictingProperty':tc())),
- ?match("IDL:omg.org/CosPropertyService/ConflictingProperty:1.0",
- 'CosPropertyService_ConflictingProperty':id()),
- ?match("CosPropertyService_ConflictingProperty",
- 'CosPropertyService_ConflictingProperty':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_ConstraintNotSupported'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_ConstraintNotSupported'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_ConstraintNotSupported':tc())),
- ?match("IDL:omg.org/CosPropertyService/ConstraintNotSupported:1.0",
- 'CosPropertyService_ConstraintNotSupported':id()),
- ?match("CosPropertyService_ConstraintNotSupported",
- 'CosPropertyService_ConstraintNotSupported':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_FixedProperty'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_FixedProperty'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_FixedProperty':tc())),
- ?match("IDL:omg.org/CosPropertyService/FixedProperty:1.0",
- 'CosPropertyService_FixedProperty':id()),
- ?match("CosPropertyService_FixedProperty",
- 'CosPropertyService_FixedProperty':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_InvalidPropertyName'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_InvalidPropertyName'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_InvalidPropertyName':tc())),
- ?match("IDL:omg.org/CosPropertyService/InvalidPropertyName:1.0",
- 'CosPropertyService_InvalidPropertyName':id()),
- ?match("CosPropertyService_InvalidPropertyName",
- 'CosPropertyService_InvalidPropertyName':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_MultipleExceptions'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_MultipleExceptions'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_MultipleExceptions':tc())),
- ?match("IDL:omg.org/CosPropertyService/MultipleExceptions:1.0",
- 'CosPropertyService_MultipleExceptions':id()),
- ?match("CosPropertyService_MultipleExceptions",
- 'CosPropertyService_MultipleExceptions':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_Properties'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_Properties'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_Properties':tc())),
- ?match("IDL:omg.org/CosPropertyService/Properties:1.0",
- 'CosPropertyService_Properties':id()),
- ?match("CosPropertyService_Properties",
- 'CosPropertyService_Properties':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_Property'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_Property'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_Property':tc())),
- ?match("IDL:omg.org/CosPropertyService/Property:1.0",
- 'CosPropertyService_Property':id()),
- ?match("CosPropertyService_Property",
- 'CosPropertyService_Property':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_PropertyDef'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_PropertyDef'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_PropertyDef':tc())),
- ?match("IDL:omg.org/CosPropertyService/PropertyDef:1.0",
- 'CosPropertyService_PropertyDef':id()),
- ?match("CosPropertyService_PropertyDef",
- 'CosPropertyService_PropertyDef':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_PropertyDefs'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_PropertyDefs'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_PropertyDefs':tc())),
- ?match("IDL:omg.org/CosPropertyService/PropertyDefs:1.0",
- 'CosPropertyService_PropertyDefs':id()),
- ?match("CosPropertyService_PropertyDefs",
- 'CosPropertyService_PropertyDefs':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_PropertyException'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_PropertyException'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_PropertyException':tc())),
- ?match("IDL:omg.org/CosPropertyService/PropertyException:1.0",
- 'CosPropertyService_PropertyException':id()),
- ?match("CosPropertyService_PropertyException",
- 'CosPropertyService_PropertyException':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_PropertyExceptions'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_PropertyExceptions'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_PropertyExceptions':tc())),
- ?match("IDL:omg.org/CosPropertyService/PropertyExceptions:1.0",
- 'CosPropertyService_PropertyExceptions':id()),
- ?match("CosPropertyService_PropertyExceptions",
- 'CosPropertyService_PropertyExceptions':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_PropertyMode'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_PropertyMode'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_PropertyMode':tc())),
- ?match("IDL:omg.org/CosPropertyService/PropertyMode:1.0",
- 'CosPropertyService_PropertyMode':id()),
- ?match("CosPropertyService_PropertyMode",
- 'CosPropertyService_PropertyMode':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_PropertyModes'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_PropertyModes'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_PropertyModes':tc())),
- ?match("IDL:omg.org/CosPropertyService/PropertyModes:1.0",
- 'CosPropertyService_PropertyModes':id()),
- ?match("CosPropertyService_PropertyModes",
- 'CosPropertyService_PropertyModes':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_PropertyNames'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_PropertyNames'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_PropertyNames':tc())),
- ?match("IDL:omg.org/CosPropertyService/PropertyNames:1.0",
- 'CosPropertyService_PropertyNames':id()),
- ?match("CosPropertyService_PropertyNames",
- 'CosPropertyService_PropertyNames':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_PropertyNotFound'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_PropertyNotFound'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_PropertyNotFound':tc())),
- ?match("IDL:omg.org/CosPropertyService/PropertyNotFound:1.0",
- 'CosPropertyService_PropertyNotFound':id()),
- ?match("CosPropertyService_PropertyNotFound",
- 'CosPropertyService_PropertyNotFound':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_PropertyTypes'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_PropertyTypes'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_PropertyTypes':tc())),
- ?match("IDL:omg.org/CosPropertyService/PropertyTypes:1.0",
- 'CosPropertyService_PropertyTypes':id()),
- ?match("CosPropertyService_PropertyTypes",
- 'CosPropertyService_PropertyTypes':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_ReadOnlyProperty'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_ReadOnlyProperty'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_ReadOnlyProperty':tc())),
- ?match("IDL:omg.org/CosPropertyService/ReadOnlyProperty:1.0",
- 'CosPropertyService_ReadOnlyProperty':id()),
- ?match("CosPropertyService_ReadOnlyProperty",
- 'CosPropertyService_ReadOnlyProperty':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_UnsupportedMode'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_UnsupportedMode'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_UnsupportedMode':tc())),
- ?match("IDL:omg.org/CosPropertyService/UnsupportedMode:1.0",
- 'CosPropertyService_UnsupportedMode':id()),
- ?match("CosPropertyService_UnsupportedMode",
- 'CosPropertyService_UnsupportedMode':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_UnsupportedProperty'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_UnsupportedProperty'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_UnsupportedProperty':tc())),
- ?match("IDL:omg.org/CosPropertyService/UnsupportedProperty:1.0",
- 'CosPropertyService_UnsupportedProperty':id()),
- ?match("CosPropertyService_UnsupportedProperty",
- 'CosPropertyService_UnsupportedProperty':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_UnsupportedTypeCode'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_UnsupportedTypeCode'(_) ->
- ?match(true, orber_tc:check_tc('CosPropertyService_UnsupportedTypeCode':tc())),
- ?match("IDL:omg.org/CosPropertyService/UnsupportedTypeCode:1.0",
- 'CosPropertyService_UnsupportedTypeCode':id()),
- ?match("CosPropertyService_UnsupportedTypeCode",
- 'CosPropertyService_UnsupportedTypeCode':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_PropertyNamesIterator'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_PropertyNamesIterator'(_) ->
- ?nomatch(undefined, 'CosPropertyService_PropertyNamesIterator':oe_tc(reset)),
- ?nomatch(undefined, 'CosPropertyService_PropertyNamesIterator':oe_tc(next_one)),
- ?nomatch(undefined, 'CosPropertyService_PropertyNamesIterator':oe_tc(next_n)),
- ?nomatch(undefined, 'CosPropertyService_PropertyNamesIterator':oe_tc(destroy)),
- ?match(undefined, 'CosPropertyService_PropertyNamesIterator':oe_tc(undefined)),
- ?match([_|_], 'CosPropertyService_PropertyNamesIterator':oe_get_interface()),
- ?match("IDL:omg.org/CosPropertyService/PropertyNamesIterator:1.0",
- 'CosPropertyService_PropertyNamesIterator':typeID()),
- check_tc('CosPropertyService_PropertyNamesIterator':oe_get_interface()),
- ?match(true, 'CosPropertyService_PropertyNamesIterator':oe_is_a('CosPropertyService_PropertyNamesIterator':typeID())),
- ?match(false, 'CosPropertyService_PropertyNamesIterator':oe_is_a("wrong")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_PropertiesIterator'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_PropertiesIterator'(_) ->
- ?nomatch(undefined, 'CosPropertyService_PropertiesIterator':oe_tc(reset)),
- ?nomatch(undefined, 'CosPropertyService_PropertiesIterator':oe_tc(next_one)),
- ?nomatch(undefined, 'CosPropertyService_PropertiesIterator':oe_tc(next_n)),
- ?nomatch(undefined, 'CosPropertyService_PropertiesIterator':oe_tc(destroy)),
- ?match(undefined, 'CosPropertyService_PropertiesIterator':oe_tc(undefined)),
- ?match([_|_], 'CosPropertyService_PropertiesIterator':oe_get_interface()),
- ?match("IDL:omg.org/CosPropertyService/PropertiesIterator:1.0",
- 'CosPropertyService_PropertiesIterator':typeID()),
- check_tc('CosPropertyService_PropertiesIterator':oe_get_interface()),
- ?match(true, 'CosPropertyService_PropertiesIterator':oe_is_a('CosPropertyService_PropertiesIterator':typeID())),
- ?match(false, 'CosPropertyService_PropertiesIterator':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_PropertySet'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_PropertySet'(_) ->
- ?nomatch(undefined, 'CosPropertyService_PropertySet':oe_tc(define_property)),
- ?nomatch(undefined, 'CosPropertyService_PropertySet':oe_tc(define_properties)),
- ?nomatch(undefined, 'CosPropertyService_PropertySet':oe_tc(get_number_of_properties)),
- ?nomatch(undefined, 'CosPropertyService_PropertySet':oe_tc(get_all_property_names)),
- ?nomatch(undefined, 'CosPropertyService_PropertySet':oe_tc(get_property_value)),
- ?nomatch(undefined, 'CosPropertyService_PropertySet':oe_tc(get_properties)),
- ?nomatch(undefined, 'CosPropertyService_PropertySet':oe_tc(get_all_properties)),
- ?nomatch(undefined, 'CosPropertyService_PropertySet':oe_tc(delete_property)),
- ?nomatch(undefined, 'CosPropertyService_PropertySet':oe_tc(delete_properties)),
- ?nomatch(undefined, 'CosPropertyService_PropertySet':oe_tc(delete_all_properties)),
- ?nomatch(undefined, 'CosPropertyService_PropertySet':oe_tc(is_property_defined)),
- ?match(undefined, 'CosPropertyService_PropertySet':oe_tc(undefined)),
- ?match([_|_], 'CosPropertyService_PropertySet':oe_get_interface()),
- ?match("IDL:omg.org/CosPropertyService/PropertySet:1.0",
- 'CosPropertyService_PropertySet':typeID()),
- check_tc('CosPropertyService_PropertySet':oe_get_interface()),
- ?match(true, 'CosPropertyService_PropertySet':oe_is_a('CosPropertyService_PropertySet':typeID())),
- ?match(false, 'CosPropertyService_PropertySet':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_PropertySetDef'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_PropertySetDef'(_) ->
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(get_allowed_property_types)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(get_allowed_properties)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(define_property_with_mode)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(define_properties_with_modes)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(get_property_mode)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(get_property_modes)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(set_property_mode)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(set_property_modes)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(define_property)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(define_properties)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(get_number_of_properties)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(get_all_property_names)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(get_property_value)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(get_properties)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(get_all_properties)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(delete_property)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(delete_properties)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(delete_all_properties)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDef':oe_tc(is_property_defined)),
- ?match(undefined, 'CosPropertyService_PropertySetDef':oe_tc(undefined)),
- ?match([_|_], 'CosPropertyService_PropertySetDef':oe_get_interface()),
- ?match("IDL:omg.org/CosPropertyService/PropertySetDef:1.0",
- 'CosPropertyService_PropertySetDef':typeID()),
- check_tc('CosPropertyService_PropertySetDef':oe_get_interface()),
- ?match(true, 'CosPropertyService_PropertySetDef':oe_is_a('CosPropertyService_PropertySetDef':typeID())),
- ?match(true, 'CosPropertyService_PropertySetDef':oe_is_a('CosPropertyService_PropertySet':typeID())),
- ?match(false, 'CosPropertyService_PropertySetDef':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_PropertySetDefFactory'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_PropertySetDefFactory'(_) ->
- ?nomatch(undefined, 'CosPropertyService_PropertySetDefFactory':oe_tc(create_propertysetdef)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDefFactory':oe_tc(create_constrained_propertysetdef)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetDefFactory':oe_tc(create_initial_propertysetdef)),
- ?match(undefined, 'CosPropertyService_PropertySetDefFactory':oe_tc(undefined)),
- ?match([_|_], 'CosPropertyService_PropertySetDefFactory':oe_get_interface()),
- ?match("IDL:omg.org/CosPropertyService/PropertySetDefFactory:1.0",
- 'CosPropertyService_PropertySetDefFactory':typeID()),
- check_tc('CosPropertyService_PropertySetDefFactory':oe_get_interface()),
- ?match(true, 'CosPropertyService_PropertySetDefFactory':oe_is_a('CosPropertyService_PropertySetDefFactory':typeID())),
- ?match(false, 'CosPropertyService_PropertySetDefFactory':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosPropertyService_PropertySetFactory'
-%% Description:
-%%-----------------------------------------------------------------
-'CosPropertyService_PropertySetFactory'(_) ->
- ?nomatch(undefined, 'CosPropertyService_PropertySetFactory':oe_tc(create_propertyset)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetFactory':oe_tc(create_constrained_propertyset)),
- ?nomatch(undefined, 'CosPropertyService_PropertySetFactory':oe_tc(create_initial_propertyset)),
- ?match(undefined, 'CosPropertyService_PropertySetFactory':oe_tc(undefined)),
- ?match([_|_], 'CosPropertyService_PropertySetFactory':oe_get_interface()),
- ?match("IDL:omg.org/CosPropertyService/PropertySetFactory:1.0",
- 'CosPropertyService_PropertySetFactory':typeID()),
- check_tc('CosPropertyService_PropertySetFactory':oe_get_interface()),
- ?match(true, 'CosPropertyService_PropertySetFactory':oe_is_a('CosPropertyService_PropertySetFactory':typeID())),
- ?match(false, 'CosPropertyService_PropertySetFactory':oe_is_a("wrong")),
- ok.
-
-
-
-%%-----------------------------------------------------------------
-%% MISC functions
-%%-----------------------------------------------------------------
-check_tc([]) ->
- ok;
-check_tc([{Op, {RetType, InParameters, OutParameters}}|T]) ->
- io:format("checked - ~s~n", [Op]),
- lists:all(?checktc(Op), [RetType|InParameters]),
- lists:all(?checktc(Op), OutParameters),
- check_tc(T).
-
-
diff --git a/lib/cosProperty/test/property_SUITE.erl b/lib/cosProperty/test/property_SUITE.erl
deleted file mode 100644
index 77f35c319a..0000000000
--- a/lib/cosProperty/test/property_SUITE.erl
+++ /dev/null
@@ -1,736 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : property_SUITE.erl
-%% Description :
-%%
-%%----------------------------------------------------------------------
--module(property_SUITE).
-
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("cosProperty/src/cosProperty.hrl").
--include_lib("cosProperty/include/CosPropertyService.hrl").
-
--include_lib("common_test/include/ct.hrl").
-
-%%--------------- DEFINES ------------------------------------
--define(default_timeout, test_server:minutes(20)).
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
--define(match_inverse(NotExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- NotExpectedRes ->
- io:format("###### ERROR ERROR ######~n ~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS);
- _ ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS
- end
- end()).
-
-
--define(val1, #any{typecode=tk_short, value=1}).
--define(val2, #any{typecode=tk_short, value=2}).
--define(val3, #any{typecode=tk_short, value=3}).
--define(val4, #any{typecode=tk_short, value=4}).
--define(val5, #any{typecode=tk_long, value=5}).
--define(badval, #any{typecode=tk_shirt, value=5}).
-
--define(id1, "id1").
--define(id2, "id2").
--define(id3, "id3").
--define(id4, "id4").
--define(id5, "id5").
--define(badid, "").
-
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
-%% Fixed exports
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, cases/0,
- init_per_suite/1, end_per_suite/1,
- init_per_testcase/2, end_per_testcase/2]).
-%% Test cases
--export([create_setdef_api/1, create_set_api/1, define_with_mode_api/1,
- define_api/1, names_iterator_api/1, properties_iterator_api/1,
- app_test/1]).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-cases() ->
- [create_setdef_api, create_set_api,
- define_with_mode_api, define_api, names_iterator_api,
- properties_iterator_api, app_test].
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- orber:jump_start(),
- cosProperty:install(),
- cosProperty:install_db(),
- ?match(ok, application:start(cosProperty)),
- if
- is_list(Config) ->
- Config;
- true ->
- exit("Config not a list")
- end.
-
-end_per_suite(Config) ->
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- application:stop(cosProperty),
- cosProperty:uninstall_db(),
- cosProperty:uninstall(),
- orber:jump_stop(),
- Config.
-
-%%-----------------------------------------------------------------
-%% Tests app file
-%%-----------------------------------------------------------------
-app_test(_Config) ->
- ok=test_server:app_test(cosProperty),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% CosPropertyService_PropertySetDefFactory API tests
-%%-----------------------------------------------------------------
-create_setdef_api(_Config) ->
-
- ValidDefs = [#'CosPropertyService_PropertyDef'
- {property_name = ?id1,
- property_value = ?val1,
- property_mode = normal},
- #'CosPropertyService_PropertyDef'
- {property_name = ?id2,
- property_value = ?val2,
- property_mode = normal}],
- InvalidDefs = [#'CosPropertyService_PropertyDef'
- {property_name = ?id1,
- property_value = ?val1,
- property_mode = normal},
- #'CosPropertyService_PropertyDef'
- {property_name = ?badid,
- property_value = ?badval,
- property_mode = normal}],
-
- Fac = ?match({_,pseudo,_,_,_,_}, cosProperty:start_SetDefFactory()),
-
- Obj1 = ?match({_,pseudo,_,_,_,_}, 'CosPropertyService_PropertySetDefFactory':
- create_propertysetdef(Fac)),
- 'CosPropertyService_PropertySetDef_impl':dump(),
- corba:dispose(Obj1),
-
-
- Obj2 = ?match({_,pseudo,_,_,_,_}, 'CosPropertyService_PropertySetDefFactory':
- create_constrained_propertysetdef(Fac, [tk_short], ValidDefs)),
- 'CosPropertyService_PropertySetDef_impl':dump(),
- corba:dispose(Obj2),
-
- %% Both arguments correct but 'ValidDefs' contain other TC:s than
- %% tk_null.
- ?match({'EXCEPTION', _}, 'CosPropertyService_PropertySetDefFactory':
- create_constrained_propertysetdef(Fac, [tk_null], ValidDefs)),
- 'CosPropertyService_PropertySetDef_impl':dump(),
-
- ?match({'EXCEPTION', _}, 'CosPropertyService_PropertySetDefFactory':
- create_constrained_propertysetdef(Fac, [tk_null], InvalidDefs)),
- 'CosPropertyService_PropertySetDef_impl':dump(),
-
- %% The allowed TC not supported.
- ?match({'EXCEPTION', _}, 'CosPropertyService_PropertySetDefFactory':
- create_constrained_propertysetdef(Fac, [tk_noll], ValidDefs)),
- 'CosPropertyService_PropertySetDef_impl':dump(),
-
- Obj4 = ?match({_,pseudo,_,_,_,_}, 'CosPropertyService_PropertySetDefFactory':
- create_initial_propertysetdef(Fac, ValidDefs)),
- 'CosPropertyService_PropertySetDef_impl':dump(),
- corba:dispose(Obj4),
-
- ?match({'EXCEPTION', _}, 'CosPropertyService_PropertySetDefFactory':
- create_initial_propertysetdef(Fac, InvalidDefs)),
-
- ?match(ok, cosProperty:stop_SetDefFactory(Fac)),
-
- ok.
-
-
-%%-----------------------------------------------------------------
-%% CosPropertyService_PropertySetFactory API tests
-%%-----------------------------------------------------------------
-create_set_api(_Config) ->
- Valid = [#'CosPropertyService_Property'
- {property_name = ?id1,
- property_value = ?val1},
- #'CosPropertyService_Property'
- {property_name = ?id2,
- property_value = ?val2}],
- Invalid = [#'CosPropertyService_Property'
- {property_name = ?id1,
- property_value = ?val1},
- #'CosPropertyService_Property'
- {property_name = ?badid,
- property_value = ?badval}],
-
- Fac = ?match({_,pseudo,_,_,_,_}, cosProperty:start_SetFactory()),
- Obj1 = ?match({_,pseudo,_,_,_,_}, 'CosPropertyService_PropertySetFactory':
- create_propertyset(Fac)),
- 'CosPropertyService_PropertySetDef_impl':dump(),
- corba:dispose(Obj1),
-
-
- Obj2 = ?match({_,pseudo,_,_,_,_}, 'CosPropertyService_PropertySetFactory':
- create_constrained_propertyset(Fac, [tk_short], Valid)),
- 'CosPropertyService_PropertySetDef_impl':dump(),
- corba:dispose(Obj2),
-
- %% Both arguments correct but 'Valid' contain other TC:s than
- %% tk_null.
- ?match({'EXCEPTION', _}, 'CosPropertyService_PropertySetFactory':
- create_constrained_propertyset(Fac, [tk_null], Valid)),
- 'CosPropertyService_PropertySetDef_impl':dump(),
-
- ?match({'EXCEPTION', _}, 'CosPropertyService_PropertySetFactory':
- create_constrained_propertyset(Fac, [tk_null], Invalid)),
- 'CosPropertyService_PropertySetDef_impl':dump(),
-
- %% The allowed TC not supported.
- ?match({'EXCEPTION', _}, 'CosPropertyService_PropertySetFactory':
- create_constrained_propertyset(Fac, [tk_noll], Valid)),
- 'CosPropertyService_PropertySetDef_impl':dump(),
-
- Obj4 = ?match({_,pseudo,_,_,_,_}, 'CosPropertyService_PropertySetFactory':
- create_initial_propertyset(Fac, Valid)),
- 'CosPropertyService_PropertySetDef_impl':dump(),
- corba:dispose(Obj4),
-
- ?match({'EXCEPTION', _}, 'CosPropertyService_PropertySetFactory':
- create_initial_propertyset(Fac, Invalid)),
- ?match(ok, cosProperty:stop_SetFactory(Fac)),
- ok.
-
-%%-----------------------------------------------------------------
-%% CosPropertyService_PropertySetDef API tests
-%%-----------------------------------------------------------------
-define_api(_Config) ->
- ValidDefs = [#'CosPropertyService_Property'
- {property_name = ?id1,
- property_value = ?val1},
- #'CosPropertyService_Property'
- {property_name = ?id2,
- property_value = ?val2},
- #'CosPropertyService_Property'
- {property_name = ?id3,
- property_value = ?val3}],
-
- Fac = ?match({_,pseudo,_,_,_,_}, cosProperty:start_SetFactory()),
-
- io:format("@@@@ Testing PropertySet returned by the factory operation create_propertyset/1 @@@@", []),
- Obj = ?match({_,pseudo,_,_,_,_}, 'CosPropertyService_PropertySetFactory':
- create_propertyset(Fac)),
- ?match(ok, 'CosPropertyService_PropertySet':define_property(Obj, ?id1, ?val1)),
- ?match(ok, 'CosPropertyService_PropertySet':define_property(Obj, ?id1, ?val1)),
-
- ?match(1, 'CosPropertyService_PropertySet':get_number_of_properties(Obj)),
- ?match(ok, 'CosPropertyService_PropertySet':
- define_properties(Obj, [#'CosPropertyService_Property'{property_name = ?id2,
- property_value = ?val2},
- #'CosPropertyService_Property'{property_name = ?id3,
- property_value = ?val3}])),
-
- ?match(3, 'CosPropertyService_PropertySet':get_number_of_properties(Obj)),
-
- ?match({true, [_]}, 'CosPropertyService_PropertySet':get_properties(Obj, [?id1])),
- ?match({true, [_, _, _]}, 'CosPropertyService_PropertySet':get_properties(Obj, [?id1, ?id2, ?id3])),
- ?match({false,[_, _, _]}, 'CosPropertyService_PropertySet':get_properties(Obj, [?id1, "wrong", ?id3])),
-
- ?match(?val2, 'CosPropertyService_PropertySet':get_property_value(Obj, ?id2)),
- ?match(ok, 'CosPropertyService_PropertySet':delete_property(Obj, ?id1)),
-
- ?match(2, 'CosPropertyService_PropertySet':get_number_of_properties(Obj)),
-
- ?match(ok, 'CosPropertyService_PropertySet':define_property(Obj, ?id1, ?val1)),
- ?match(ok, 'CosPropertyService_PropertySet':define_property(Obj, ?id2, ?val2)),
- ?match(ok, 'CosPropertyService_PropertySet':define_property(Obj, ?id3, ?val3)),
-
- ?match(true, 'CosPropertyService_PropertySet':delete_all_properties(Obj)),
- ?match(0, 'CosPropertyService_PropertySet':get_number_of_properties(Obj)),
-
- ?match(ok, 'CosPropertyService_PropertySet':
- define_properties(Obj, [#'CosPropertyService_Property'{property_name = ?id1,
- property_value = ?val1},
- #'CosPropertyService_Property'{property_name = ?id2,
- property_value = ?val2},
- #'CosPropertyService_Property'{property_name = ?id3,
- property_value = ?val3}])),
-
- ?match(3, 'CosPropertyService_PropertySet':get_number_of_properties(Obj)),
- ?match(?val2, 'CosPropertyService_PropertySet':get_property_value(Obj, ?id2)),
-
- ?match({'EXCEPTION',{'CosPropertyService_PropertyNotFound',_}},
- 'CosPropertyService_PropertySet':get_property_value(Obj, "wrongID")),
- ?match({'EXCEPTION',{'CosPropertyService_InvalidPropertyName',_}},
- 'CosPropertyService_PropertySet':get_property_value(Obj, "")),
- ?match({'EXCEPTION',{'CosPropertyService_InvalidPropertyName',_}},
- 'CosPropertyService_PropertySet':is_property_defined(Obj, "")),
- ?match(false, 'CosPropertyService_PropertySet':is_property_defined(Obj, "wrongID")),
- ?match(true, 'CosPropertyService_PropertySet':is_property_defined(Obj, ?id1)),
-
- %% This function is not supported by PropertySet.
- ?match({'EXCEPTION',{'NO_IMPLEMENT',_,_,_}},
- 'CosPropertyService_PropertySetDef':get_property_modes(Obj, [?id1, ?id2, ?id3])),
-
- ?match({'EXCEPTION',{'CosPropertyService_MultipleExceptions',_,_}},
- 'CosPropertyService_PropertySet':delete_properties(Obj, [?id1, ?id2, ?id3, "wrongID"])),
- ?match(0, 'CosPropertyService_PropertySet':get_number_of_properties(Obj)),
- corba:dispose(Obj),
-
- io:format("@@@@ Testing PropertySet returned by the factory operation create_constrained_propertyset/3 @@@@", []),
- Obj2 = ?match({_,pseudo,_,_,_,_}, 'CosPropertyService_PropertySetFactory':
- create_constrained_propertyset(Fac, [tk_short], ValidDefs)),
-
- ?match(0, 'CosPropertyService_PropertySet':get_number_of_properties(Obj2)),
- ?match({'EXCEPTION', {'CosPropertyService_UnsupportedProperty',_}},
- 'CosPropertyService_PropertySet':define_property(Obj2, ?id4, ?val4)),
- ?match({'EXCEPTION', {'CosPropertyService_UnsupportedTypeCode',_}},
- 'CosPropertyService_PropertySet':define_property(Obj2, ?id1, ?val5)),
- ?match(ok, 'CosPropertyService_PropertySet':define_property(Obj2, ?id1, ?val1)),
- ?match(1, 'CosPropertyService_PropertySet':get_number_of_properties(Obj2)),
- ?match({'EXCEPTION',{'CosPropertyService_MultipleExceptions',_,_}},
- 'CosPropertyService_PropertySet':
- define_properties(Obj2, [#'CosPropertyService_Property'{property_name = ?id2,
- property_value = ?val2},
- #'CosPropertyService_Property'{property_name = ?id3,
- property_value = ?val3},
- #'CosPropertyService_Property'{property_name = "wrongId",
- property_value = ?val2}])),
- ?match(ok,'CosPropertyService_PropertySet':
- define_properties(Obj2, [#'CosPropertyService_Property'{property_name = ?id2,
- property_value = ?val2},
- #'CosPropertyService_Property'{property_name = ?id3,
- property_value = ?val3}])),
- ?match(3, 'CosPropertyService_PropertySet':get_number_of_properties(Obj2)),
- ?match({'EXCEPTION',{'CosPropertyService_PropertyNotFound',_}},
- 'CosPropertyService_PropertySet':get_property_value(Obj2, "wrongID")),
- ?match(?val2, 'CosPropertyService_PropertySet':get_property_value(Obj2, ?id2)),
- ?match({'EXCEPTION',{'CosPropertyService_InvalidPropertyName',_}},
- 'CosPropertyService_PropertySet':get_property_value(Obj2, "")),
- ?match({'EXCEPTION',{'CosPropertyService_InvalidPropertyName',_}},
- 'CosPropertyService_PropertySet':is_property_defined(Obj2, "")),
- ?match(false, 'CosPropertyService_PropertySet':is_property_defined(Obj2, "wrongID")),
- ?match(true, 'CosPropertyService_PropertySet':is_property_defined(Obj2, ?id1)),
-
-
- ?match({'EXCEPTION',{'CosPropertyService_PropertyNotFound',_}},
- 'CosPropertyService_PropertySet':delete_property(Obj2, "wrongID")),
- ?match(3, 'CosPropertyService_PropertySet':get_number_of_properties(Obj2)),
- ?match(ok, 'CosPropertyService_PropertySet':delete_property(Obj2, ?id1)),
- ?match(2, 'CosPropertyService_PropertySet':get_number_of_properties(Obj2)),
-
- ?match(ok, 'CosPropertyService_PropertySet':delete_properties(Obj2, [?id2])),
- ?match(1, 'CosPropertyService_PropertySet':get_number_of_properties(Obj2)),
-
- ?match({'EXCEPTION',{'CosPropertyService_MultipleExceptions',_,_}},
- 'CosPropertyService_PropertySet':delete_properties(Obj2, [?id3, "wrongID"])),
- ?match(0, 'CosPropertyService_PropertySet':get_number_of_properties(Obj2)),
- corba:dispose(Obj2),
-
- io:format("@@@@ Testing PropertySet returned by the factory operation create_initial_propertyset/2 @@@@", []),
- Obj3 = ?match({_,pseudo,_,_,_,_}, 'CosPropertyService_PropertySetFactory':
- create_initial_propertyset(Fac, ValidDefs)),
- ?match(3, 'CosPropertyService_PropertySet':get_number_of_properties(Obj3)),
-
- ?match(ok, 'CosPropertyService_PropertySet':define_property(Obj3, ?id4, ?val4)),
- ?match(4, 'CosPropertyService_PropertySet':get_number_of_properties(Obj3)),
-
- ?match(ok,'CosPropertyService_PropertySet':
- define_properties(Obj3, [#'CosPropertyService_Property'{property_name = ?id5,
- property_value = ?val5}])),
-
- ?match(5, 'CosPropertyService_PropertySet':get_number_of_properties(Obj3)),
-
- ?match({'EXCEPTION',{'CosPropertyService_PropertyNotFound',_}},
- 'CosPropertyService_PropertySet':get_property_value(Obj3, "wrongID")),
- ?match(?val2, 'CosPropertyService_PropertySet':get_property_value(Obj3, ?id2)),
- ?match({'EXCEPTION',{'CosPropertyService_InvalidPropertyName',_}},
- 'CosPropertyService_PropertySet':get_property_value(Obj3, "")),
- ?match({'EXCEPTION',{'CosPropertyService_InvalidPropertyName',_}},
- 'CosPropertyService_PropertySet':is_property_defined(Obj3, "")),
- ?match(false, 'CosPropertyService_PropertySet':is_property_defined(Obj3, "wrongID")),
- ?match(true, 'CosPropertyService_PropertySet':is_property_defined(Obj3, ?id1)),
-
- ?match({'EXCEPTION',{'CosPropertyService_PropertyNotFound',_}},
- 'CosPropertyService_PropertySet':delete_property(Obj3, "wrongId")),
- ?match(ok, 'CosPropertyService_PropertySet':delete_property(Obj3, ?id5)),
- ?match(4, 'CosPropertyService_PropertySet':get_number_of_properties(Obj3)),
-
- ?match({'EXCEPTION',{'CosPropertyService_MultipleExceptions',_,_}},
- 'CosPropertyService_PropertySet':delete_properties(Obj3, [?id1, ?id2, ?id3, "wrongID"])),
- ?match(1, 'CosPropertyService_PropertySet':get_number_of_properties(Obj3)),
-
- ?match(true, 'CosPropertyService_PropertySet':delete_all_properties(Obj3)),
- ?match(0, 'CosPropertyService_PropertySet':get_number_of_properties(Obj3)),
-
- corba:dispose(Obj3),
- ?match(ok, cosProperty:stop_SetFactory(Fac)),
-
- ok.
-
-%%-----------------------------------------------------------------
-%% CosPropertyService_PropertySetDef API tests
-%%-----------------------------------------------------------------
-define_with_mode_api(_Config) ->
- ValidDefs = [#'CosPropertyService_PropertyDef'
- {property_name = ?id1,
- property_value = ?val1,
- property_mode = normal},
- #'CosPropertyService_PropertyDef'
- {property_name = ?id2,
- property_value = ?val2,
- property_mode = normal},
- #'CosPropertyService_PropertyDef'
- {property_name = ?id3,
- property_value = ?val3,
- property_mode = normal}],
-
- Fac = ?match({_,pseudo,_,_,_,_}, cosProperty:start_SetDefFactory()),
-
- io:format("@@@@ Testing PropertySetDef returned by the factory operation create_propertysetdef/1 @@@@", []),
- Obj = ?match({_,pseudo,_,_,_,_}, 'CosPropertyService_PropertySetDefFactory':
- create_propertysetdef(Fac)),
-
- %% Initally no prop's created and no restrictions at all
- ?match(0, 'CosPropertyService_PropertySetDef':get_number_of_properties(Obj)),
- ?match({ok, []}, 'CosPropertyService_PropertySetDef':get_allowed_property_types(Obj)),
- ?match({ok, []}, 'CosPropertyService_PropertySetDef':get_allowed_properties(Obj)),
-
- %% Add two properties.
- ?match(ok, 'CosPropertyService_PropertySetDef':define_property_with_mode(Obj, ?id4, ?val4, read_only)),
- ?match(ok, 'CosPropertyService_PropertySetDef':define_property_with_mode(Obj, ?id5, ?val5, normal)),
- %% Try to add the same property again (shouldn't add another since using the sam Id).
- ?match(ok, 'CosPropertyService_PropertySetDef':define_property_with_mode(Obj, ?id5, ?val5, normal)),
-
- %% Try to add another identical proprty with wrong TC.
- ?match({'EXCEPTION',{'CosPropertyService_ConflictingProperty',_}},
- 'CosPropertyService_PropertySetDef':define_property_with_mode(Obj, ?id5, ?val4, normal)),
-
-
- %% Should be two now.
- ?match(2, 'CosPropertyService_PropertySetDef':get_number_of_properties(Obj)),
-
- ?match(read_only, 'CosPropertyService_PropertySetDef':get_property_mode(Obj, ?id4)),
- ?match(normal, 'CosPropertyService_PropertySetDef':get_property_mode(Obj, ?id5)),
- ?match(ok, 'CosPropertyService_PropertySetDef':
- define_properties_with_modes(Obj,
- [#'CosPropertyService_PropertyDef'{property_name = ?id1,
- property_value = ?val1,
- property_mode = normal},
- #'CosPropertyService_PropertyDef'{property_name = ?id2,
- property_value = ?val2,
- property_mode = normal},
- #'CosPropertyService_PropertyDef'{property_name = ?id3,
- property_value = ?val3,
- property_mode = normal}])),
- %% Should be five now.
- ?match(5, 'CosPropertyService_PropertySetDef':get_number_of_properties(Obj)),
- ?match({true, [_,_]}, 'CosPropertyService_PropertySetDef':get_property_modes(Obj, [?id1, ?id3])),
- ?match({false, [_,_,_]}, 'CosPropertyService_PropertySetDef':get_property_modes(Obj, [?id1, ?id3, "wrongID"])),
-
- ?match(ok, 'CosPropertyService_PropertySetDef':set_property_mode(Obj, ?id1, read_only)),
- ?match(read_only, 'CosPropertyService_PropertySetDef':get_property_mode(Obj, ?id1)),
-
- ?match({'EXCEPTION',{'CosPropertyService_PropertyNotFound',_}},
- 'CosPropertyService_PropertySetDef':set_property_mode(Obj, "wrongID", read_only)),
-
- ?match({'EXCEPTION',{'CosPropertyService_MultipleExceptions',_,_}},
- 'CosPropertyService_PropertySetDef':
- set_property_modes(Obj,
- [#'CosPropertyService_PropertyMode'{property_name = ?id2,
- property_mode = read_only},
- #'CosPropertyService_PropertyMode'{property_name = ?id3,
- property_mode = read_only},
- #'CosPropertyService_PropertyMode'{property_name = "wrongID",
- property_mode = read_only}])),
- ?match(normal, 'CosPropertyService_PropertySetDef':get_property_mode(Obj, ?id2)),
- ?match(ok,
- 'CosPropertyService_PropertySetDef':
- set_property_modes(Obj,
- [#'CosPropertyService_PropertyMode'{property_name = ?id2,
- property_mode = read_only},
- #'CosPropertyService_PropertyMode'{property_name = ?id3,
- property_mode = read_only}])),
- ?match(read_only, 'CosPropertyService_PropertySetDef':get_property_mode(Obj, ?id2)),
-
- corba:dispose(Obj),
-
-
- io:format("@@@@ Testing PropertySetDef returned by the factory operation create_constrained_propertysetdef/3 @@@@", []),
- Obj2 = ?match({_,pseudo,_,_,_,_}, 'CosPropertyService_PropertySetDefFactory':
- create_constrained_propertysetdef(Fac, [tk_short], ValidDefs)),
-
- %% Initally no prop's created and the restrictions that only Properties eq. to ValidDefs
- %% may be handled.
- ?match(0, 'CosPropertyService_PropertySetDef':get_number_of_properties(Obj2)),
- ?match({ok, [tk_short]}, 'CosPropertyService_PropertySetDef':get_allowed_property_types(Obj2)),
- %% We cannot be sure in which order it's returned. Hmm, that's not really true but it
- %% may change in the future.
- ?match({ok, [_,_,_]}, 'CosPropertyService_PropertySetDef':get_allowed_properties(Obj2)),
- %% Try to add a Property with and Id not eq. to ?id1, ?id2 or ?id3; must fail.
- ?match({'EXCEPTION', {'CosPropertyService_UnsupportedProperty',_}},
- 'CosPropertyService_PropertySetDef':define_property_with_mode(Obj2, ?id4, ?val4, read_only)),
- %% To be sure that nothing was updated.
- ?match(0, 'CosPropertyService_PropertySetDef':get_number_of_properties(Obj2)),
- %% Add a valid Property.
- ?match(ok, 'CosPropertyService_PropertySetDef':define_property_with_mode(Obj2, ?id1, ?val1, normal)),
- ?match(1, 'CosPropertyService_PropertySetDef':get_number_of_properties(Obj2)),
- %% Add a sequence of 1 valid and one invalid Prop's
- ?match({'EXCEPTION', {'CosPropertyService_MultipleExceptions',_,_}},
- 'CosPropertyService_PropertySetDef':
- define_properties_with_modes(Obj2,
- [#'CosPropertyService_PropertyDef'{property_name = ?id2,
- property_value = ?val2,
- property_mode = normal},
- #'CosPropertyService_PropertyDef'{property_name = "wrongID",
- property_value = ?val2,
- property_mode = normal}])),
- %% One should be added.
- ?match(1, 'CosPropertyService_PropertySetDef':get_number_of_properties(Obj2)),
- ?match(ok, 'CosPropertyService_PropertySetDef':
- define_properties_with_modes(Obj2,
- [#'CosPropertyService_PropertyDef'{property_name = ?id3,
- property_value = ?val3,
- property_mode = normal}])),
- %% Add a sequence of 1 valid Prop.
- ?match(2, 'CosPropertyService_PropertySetDef':get_number_of_properties(Obj2)),
- ?match(normal, 'CosPropertyService_PropertySetDef':get_property_mode(Obj2, ?id1)),
- ?match(normal, 'CosPropertyService_PropertySetDef':get_property_mode(Obj2, ?id3)),
-
-
- ?match({true, [_,_]}, 'CosPropertyService_PropertySetDef':get_property_modes(Obj2, [?id1, ?id3])),
- ?match({false, [_,_,_]}, 'CosPropertyService_PropertySetDef':get_property_modes(Obj2, [?id1, ?id3, "wrongID"])),
-
- ?match(ok, 'CosPropertyService_PropertySetDef':set_property_mode(Obj2, ?id1, read_only)),
- ?match(read_only, 'CosPropertyService_PropertySetDef':get_property_mode(Obj2, ?id1)),
- ?match(ok, 'CosPropertyService_PropertySetDef':
- set_property_modes(Obj2,
- [#'CosPropertyService_PropertyMode'{property_name = ?id1,
- property_mode = read_only},
- #'CosPropertyService_PropertyMode'{property_name = ?id3,
- property_mode = read_only}])),
- ?match(read_only, 'CosPropertyService_PropertySetDef':get_property_mode(Obj2, ?id1)),
- ?match(read_only, 'CosPropertyService_PropertySetDef':get_property_mode(Obj2, ?id3)),
- ?match({'EXCEPTION',{'CosPropertyService_MultipleExceptions',_,_}},
- 'CosPropertyService_PropertySetDef':
- set_property_modes(Obj2,
- [#'CosPropertyService_PropertyMode'{property_name = ?id1,
- property_mode = normal},
- #'CosPropertyService_PropertyMode'{property_name = ?id3,
- property_mode = normal},
- #'CosPropertyService_PropertyMode'{property_name = "wrongID",
- property_mode = normal}])),
-
- ?match(read_only, 'CosPropertyService_PropertySetDef':get_property_mode(Obj2, ?id1)),
- ?match(read_only, 'CosPropertyService_PropertySetDef':get_property_mode(Obj2, ?id3)),
- corba:dispose(Obj2),
-
- io:format("@@@@ Testing PropertySetDef returned by the factory operation create_initial_propertysetdef/2 @@@@", []),
- Obj3 = ?match({_,pseudo,_,_,_,_}, 'CosPropertyService_PropertySetDefFactory':
- create_initial_propertysetdef(Fac, ValidDefs)),
-
- %% Initally the supplied prop's are created and no restrictions.
- ?match(3, 'CosPropertyService_PropertySetDef':get_number_of_properties(Obj3)),
- ?match({ok, []}, 'CosPropertyService_PropertySetDef':get_allowed_property_types(Obj3)),
- ?match({ok, []}, 'CosPropertyService_PropertySetDef':get_allowed_properties(Obj3)),
-
- %% Add a new properties an test if they have been inserted.
- ?match(ok, 'CosPropertyService_PropertySetDef':define_property_with_mode(Obj3, ?id4, ?val4, read_only)),
- ?match(4, 'CosPropertyService_PropertySetDef':get_number_of_properties(Obj3)),
- ?match(ok, 'CosPropertyService_PropertySetDef':define_property_with_mode(Obj3, ?id5, ?val5, read_only)),
- ?match(5, 'CosPropertyService_PropertySetDef':get_number_of_properties(Obj3)),
-
- %% Lookup each Property's mode.
- ?match(normal, 'CosPropertyService_PropertySetDef':get_property_mode(Obj3, ?id1)),
- ?match(normal, 'CosPropertyService_PropertySetDef':get_property_mode(Obj3, ?id2)),
- ?match(normal, 'CosPropertyService_PropertySetDef':get_property_mode(Obj3, ?id3)),
- ?match(read_only, 'CosPropertyService_PropertySetDef':get_property_mode(Obj3, ?id4)),
- ?match(read_only, 'CosPropertyService_PropertySetDef':get_property_mode(Obj3, ?id5)),
-
- ?match({true, [_,_,_,_,_]},
- 'CosPropertyService_PropertySetDef':get_property_modes(Obj3, [?id1, ?id2, ?id3, ?id4, ?id5])),
- ?match({false, [_,_]},
- 'CosPropertyService_PropertySetDef':get_property_modes(Obj3, [?id1, "wrongID"])),
- ?match(ok, 'CosPropertyService_PropertySetDef':set_property_mode(Obj3, ?id4, normal)),
- ?match(normal, 'CosPropertyService_PropertySetDef':get_property_mode(Obj3, ?id4)),
-
- ?match(ok, 'CosPropertyService_PropertySetDef':
- set_property_modes(Obj3,
- [#'CosPropertyService_PropertyMode'{property_name = ?id1,
- property_mode = read_only},
- #'CosPropertyService_PropertyMode'{property_name = ?id2,
- property_mode = read_only}])),
- ?match(read_only, 'CosPropertyService_PropertySetDef':get_property_mode(Obj3, ?id1)),
- ?match(read_only, 'CosPropertyService_PropertySetDef':get_property_mode(Obj3, ?id2)),
- ?match({'EXCEPTION',{'CosPropertyService_MultipleExceptions',_,_}},
- 'CosPropertyService_PropertySetDef':
- set_property_modes(Obj3,
- [#'CosPropertyService_PropertyMode'{property_name = ?id3,
- property_mode = read_only},
- #'CosPropertyService_PropertyMode'{property_name = ?id4,
- property_mode = read_only},
- #'CosPropertyService_PropertyMode'{property_name = "wrongID",
- property_mode = read_only}])),
-
- ?match(normal, 'CosPropertyService_PropertySetDef':get_property_mode(Obj3, ?id3)),
- ?match(normal, 'CosPropertyService_PropertySetDef':get_property_mode(Obj3, ?id4)),
-
- corba:dispose(Obj3),
-
- ?match(ok, cosProperty:stop_SetDefFactory(Fac)),
-
- ok.
-
-
-
-%%-----------------------------------------------------------------
-%% CosPropertyService_PropertyNamesIterator API tests
-%%-----------------------------------------------------------------
-names_iterator_api(_Config) ->
- Fac = ?match({_,pseudo,_,_,_,_}, cosProperty:start_SetFactory()),
- Obj = ?match({_,pseudo,_,_,_,_}, 'CosPropertyService_PropertySetFactory':
- create_propertyset(Fac)),
- ?match(ok, 'CosPropertyService_PropertySet':
- define_properties(Obj, [#'CosPropertyService_Property'{property_name = ?id1,
- property_value = ?val1},
- #'CosPropertyService_Property'{property_name = ?id2,
- property_value = ?val2},
- #'CosPropertyService_Property'{property_name = ?id3,
- property_value = ?val3}])),
-
- ?match(3, 'CosPropertyService_PropertySetDef':get_number_of_properties(Obj)),
- {_, _,ItObj} = ?match({ok, [], _}, 'CosPropertyService_PropertySetDef':get_all_property_names(Obj, 0)),
- ?match({false, [_,_,_]}, 'CosPropertyService_PropertyNamesIterator':next_n(ItObj,3)),
- ?match(ok, 'CosPropertyService_PropertyNamesIterator':reset(ItObj)),
- ?match({false, [_,_,_]}, 'CosPropertyService_PropertyNamesIterator':next_n(ItObj,4)),
- ?match(ok, 'CosPropertyService_PropertyNamesIterator':reset(ItObj)),
- ?match({true, [_]}, 'CosPropertyService_PropertyNamesIterator':next_n(ItObj,1)),
- ?match({true, _}, 'CosPropertyService_PropertyNamesIterator':next_one(ItObj)),
- ?match({true, _}, 'CosPropertyService_PropertyNamesIterator':next_one(ItObj)),
- ?match({false, _}, 'CosPropertyService_PropertyNamesIterator':next_one(ItObj)),
- ?match(ok, 'CosPropertyService_PropertyNamesIterator':destroy(ItObj)),
-
- corba:dispose(Obj),
- ok.
-
-%%-----------------------------------------------------------------
-%% CosPropertyService_PropertiesIterator API tests
-%%-----------------------------------------------------------------
-properties_iterator_api(_Config) ->
- Fac = ?match({_,pseudo,_,_,_,_}, cosProperty:start_SetFactory()),
- Obj = ?match({_,pseudo,_,_,_,_}, 'CosPropertyService_PropertySetFactory':
- create_propertyset(Fac)),
-
- ?match(ok, 'CosPropertyService_PropertySet':
- define_properties(Obj, [#'CosPropertyService_Property'{property_name = ?id1,
- property_value = ?val1},
- #'CosPropertyService_Property'{property_name = ?id2,
- property_value = ?val2},
- #'CosPropertyService_Property'{property_name = ?id3,
- property_value = ?val3}])),
-
- ?match(3, 'CosPropertyService_PropertySetDef':get_number_of_properties(Obj)),
- {_, _,ItObj} = ?match({ok, [], _},
- 'CosPropertyService_PropertySetDef':get_all_properties(Obj, 0)),
- ?match({false, [_,_,_]}, 'CosPropertyService_PropertiesIterator':next_n(ItObj,3)),
- ?match(ok, 'CosPropertyService_PropertiesIterator':reset(ItObj)),
- ?match({false, [_,_,_]}, 'CosPropertyService_PropertiesIterator':next_n(ItObj,4)),
- ?match(ok, 'CosPropertyService_PropertiesIterator':reset(ItObj)),
- ?match({true, [_]}, 'CosPropertyService_PropertiesIterator':next_n(ItObj,1)),
- ?match({true, {'CosPropertyService_Property',_,_}},
- 'CosPropertyService_PropertiesIterator':next_one(ItObj)),
- ?match({true, {'CosPropertyService_Property',_,_}},
- 'CosPropertyService_PropertiesIterator':next_one(ItObj)),
- ?match({false, {'CosPropertyService_Property',_,_}},
- 'CosPropertyService_PropertiesIterator':next_one(ItObj)),
- ?match(ok, 'CosPropertyService_PropertiesIterator':destroy(ItObj)),
- corba:dispose(Obj),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% END OF MODULE
-%%-----------------------------------------------------------------
diff --git a/lib/cosProperty/vsn.mk b/lib/cosProperty/vsn.mk
deleted file mode 100644
index 78ba88445d..0000000000
--- a/lib/cosProperty/vsn.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-COSPROPERTY_VSN = 1.2.2
-
diff --git a/lib/cosTime/AUTHORS b/lib/cosTime/AUTHORS
deleted file mode 100644
index 55d8059989..0000000000
--- a/lib/cosTime/AUTHORS
+++ /dev/null
@@ -1,4 +0,0 @@
-Original Authors:
-Niclas Eklund
-
-Contributors:
diff --git a/lib/cosTime/Makefile b/lib/cosTime/Makefile
deleted file mode 100644
index e1b0b27284..0000000000
--- a/lib/cosTime/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include vsn.mk
-VSN=$(COSTIME_VSN)
-
-# ----------------------------------------------------
-# Common Macros
-# ----------------------------------------------------
-# SUB_DIRECTORIES = src test examples doc/src
-# At the moment we don't have any example programs.
-SUB_DIRECTORIES = src doc/src
-
-SPECIAL_TARGETS =
-
-# ----------------------------------------------------
-# Default Subdir Targets
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_subdir.mk
diff --git a/lib/cosTime/doc/html/.gitignore b/lib/cosTime/doc/html/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosTime/doc/html/.gitignore
+++ /dev/null
diff --git a/lib/cosTime/doc/man3/.gitignore b/lib/cosTime/doc/man3/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosTime/doc/man3/.gitignore
+++ /dev/null
diff --git a/lib/cosTime/doc/man6/.gitignore b/lib/cosTime/doc/man6/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosTime/doc/man6/.gitignore
+++ /dev/null
diff --git a/lib/cosTime/doc/pdf/.gitignore b/lib/cosTime/doc/pdf/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosTime/doc/pdf/.gitignore
+++ /dev/null
diff --git a/lib/cosTime/doc/src/CosTime_TIO.xml b/lib/cosTime/doc/src/CosTime_TIO.xml
deleted file mode 100644
index c01154a2c5..0000000000
--- a/lib/cosTime/doc/src/CosTime_TIO.xml
+++ /dev/null
@@ -1,109 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosTime_TIO</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosTime_TIO</module>
- <modulesummary>This module implements the OMG CosTime::TIO interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosTime/include/*.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>'_get_time_interval'(TIO) -> TimeInterval</name>
- <fsummary>Return the interval associated with the target object</fsummary>
- <type>
- <v>TIO = #objref</v>
- <v>TimeInterval = #'TimeBase_IntervalT{lower_bound, upper_bound}</v>
- <v>lower_bound = upper_bound = ulonglong</v>
- </type>
- <desc>
- <p>This operation returns the interval associated with the target object.</p>
- </desc>
- </func>
- <func>
- <name>spans(TIO, UTO) -> Reply</name>
- <fsummary>Return an OverlapType which describe how the interval in the target object and the timerange represented by the UTO object overlap</fsummary>
- <type>
- <v>TIO = UTO = OtherTIO = #objref</v>
- <v>Reply = {OverlapType, OtherTIO}</v>
- <v>OverlapType = 'OTContainer' | 'OTContained' | 'OTOverlap' | 'OTNoOverlap'</v>
- </type>
- <desc>
- <p>This operation returns a <em>OverlapType</em> depending on how the interval
- in the target object and the timerange represented by the UTO object
- overlap. If the OverlapType is 'OTNoOverlap' the out parameter represents
- the gap between the two intervals. If OverlapType is one of the others, the
- out parameter represents the overlap interval.
- The definitions of the OverlapType's are:</p>
- <p></p>
- <list type="bulleted">
- <item>'OTContainer' - target objects lower and upper limits are,
- respectively, less or equal to and greater or equal to given object's.</item>
- <item>'OTContained' - target objects lower and upper limits are,
- respectively, greater or equal to and less or equal to given object's.</item>
- <item>'OTOverlap' - target objects interval overlap given object's.</item>
- <item>'OTNoOverlap' - target objects interval do not overlap given object's.</item>
- </list>
- </desc>
- </func>
- <func>
- <name>overlaps(TIO, OtherTIO) -> Reply</name>
- <fsummary>Return an OverlapType which describe how the interval in the target object and the timerange represented by the TIO object overlap</fsummary>
- <type>
- <v>TIO = OtherTIO = AnotherTIO = #objref</v>
- <v>Reply = {OverlapType, AnotherTIO}</v>
- <v>OverlapType = 'OTContainer' | 'OTContained' | 'OTOverlap' | 'OTNoOverlap'</v>
- </type>
- <desc>
- <p>This operation returns a <em>OverlapType</em> depending on how the interval
- in the target object and the timerange represented by the TIO object
- overlap. The OverlapType's are described under spans/2.</p>
- </desc>
- </func>
- <func>
- <name>time(TIO) -> UTO</name>
- <fsummary>Return a UTO in which the interval equals the time interval in the target object and time value is the midpoint of the interval</fsummary>
- <type>
- <v>TIO = UTO = #objref</v>
- </type>
- <desc>
- <p>This operation returns a UTO in which the interval equals the time interval
- in the target object and time value is the midpoint of the interval.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosTime/doc/src/CosTime_TimeService.xml b/lib/cosTime/doc/src/CosTime_TimeService.xml
deleted file mode 100644
index b578128277..0000000000
--- a/lib/cosTime/doc/src/CosTime_TimeService.xml
+++ /dev/null
@@ -1,104 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosTime_TimeService</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosTime_TimeService</module>
- <modulesummary>This module implements the OMG CosTime::TimeService interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosTime/include/*.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>universal_time(TimeService) -> Reply</name>
- <fsummary>Return the current time and the Inaccuracy given when starting this application in a UTO</fsummary>
- <type>
- <v>TimeService = #objref</v>
- <v>Reply = UTO | {'EXCEPTION", #'TimerService_TimeUnavailable'{}}</v>
- <v>UTO = #objref</v>
- </type>
- <desc>
- <p>This operation returns the current time and the Inaccuracy given
- when starting this application in a UTO. The time base is
- <em>15 october 1582 00:00</em>. Comparing two time objects which use
- different time base is, by obvious reasons, pointless.</p>
- </desc>
- </func>
- <func>
- <name>new_universal_time(TimeService, Time, Inaccuracy, Tdf) -> UTO</name>
- <fsummary>Create a new UTO object representing the time parameters given</fsummary>
- <type>
- <v>TimeService = UTO = #objref</v>
- <v>Time = Inaccuracy = ulonglong()</v>
- <v>Tdf = short()</v>
- </type>
- <desc>
- <p>This operation creates a new UTO object representing the time
- parameters given. This is the only way to create a UTO with an
- arbitrary time from its components. This is useful when using the
- Timer Event Service.</p>
- </desc>
- </func>
- <func>
- <name>uto_from_utc(TimeService, Utc) -> UTO</name>
- <fsummary>Create a UTO representing the given time in Utc form</fsummary>
- <type>
- <v>TimeService = UTO = #objref</v>
- <v>Utc = #'TimeBase_UtcT'{time, inacclo, inacchi, tdf}</v>
- <v>time = ulonglong()</v>
- <v>inacclo = ulong()</v>
- <v>inacchi = ushort()</v>
- <v>tdf = short()</v>
- </type>
- <desc>
- <p>This operation is used to create a UTO given a time in the Utc form.</p>
- </desc>
- </func>
- <func>
- <name>new_interval(TimeService, Lower, Upper) -> TIO</name>
- <fsummary>Create a new TIO object representing the input parameters</fsummary>
- <type>
- <v>TimeService = TIO = #objref</v>
- <v>Lower = Upper = ulonglong()</v>
- </type>
- <desc>
- <p>This operation is used to create a new TIO object, representing
- the input parameters. If <em>Lower</em> is greater than Upper
- BAD_PARAM is raised.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosTime/doc/src/CosTime_UTO.xml b/lib/cosTime/doc/src/CosTime_UTO.xml
deleted file mode 100644
index 432d9d92f9..0000000000
--- a/lib/cosTime/doc/src/CosTime_UTO.xml
+++ /dev/null
@@ -1,156 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosTime_UTO</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosTime_UTO</module>
- <modulesummary>This module implements the OMG CosTime::UTO interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosTime/include/*.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>'_get_time'(UTO) -> ulonglong()</name>
- <fsummary>Return the time associated with the target object</fsummary>
- <type>
- <v>UTO = #objref</v>
- </type>
- <desc>
- <p>This operation returns the time associated with the target object.</p>
- </desc>
- </func>
- <func>
- <name>'_get_inaccuracy'(UTO) -> ulonglong()</name>
- <fsummary>Return the inaccuracy associated with the target object</fsummary>
- <type>
- <v>UTO = #objref</v>
- </type>
- <desc>
- <p>This operation returns the inaccuracy associated with the target object.</p>
- </desc>
- </func>
- <func>
- <name>'_get_tdf'(UTO) -> short()</name>
- <fsummary>Return the time displacement factor associated with the target object</fsummary>
- <type>
- <v>UTO = #objref</v>
- </type>
- <desc>
- <p>This operation returns the time displacement factor associated with
- the target object.</p>
- </desc>
- </func>
- <func>
- <name>'_get_utc_time'(UTO) -> UtcT</name>
- <fsummary>Return the data associated with the target object in Utc form</fsummary>
- <type>
- <v>UTO = #objref</v>
- <v>Utc = #'TimeBase_UtcT'{time, inacclo, inacchi, tdf}</v>
- <v>time = ulonglong()</v>
- <v>inacclo = ulong()</v>
- <v>inacchi = ushort()</v>
- <v>tdf = short()</v>
- </type>
- <desc>
- <p>This operation returns the data associated with the target object in
- Utc form.</p>
- </desc>
- </func>
- <func>
- <name>absolute_time(UTO) -> OtherUTO</name>
- <fsummary>Create a new UTO object representing the time in the target object added to current time (UTC)</fsummary>
- <type>
- <v>UTO = OtherUTO = #objref</v>
- </type>
- <desc>
- <p>This operation create a new UTO object representing the time in the target
- object added to current time (UTC). The time base is
- <em>15 october 1582 00:00</em>. Comparing two time objects which use
- different time base is, by obvious reasons, pointless.
- Raises DATA_CONVERSION if causes an overflow. This operation is only useful
- if the target object represents a relative time.</p>
- </desc>
- </func>
- <func>
- <name>compare_time(UTO, ComparisonType, OtherUTO) -> Reply</name>
- <fsummary>Compare the time associated with the target object and the given UTO object</fsummary>
- <type>
- <v>UTO = OtherUTO = #objref</v>
- <v>ComparisonType = 'IntervalC' | 'MidC'</v>
- <v>Reply = 'TCEqualTo' | 'TCLessThan' | 'TCGreaterThan' | 'TCIndeterminate'</v>
- </type>
- <desc>
- <p>This operation compares the time associated with the target object and the
- given UTO object. The different <c>ComparisonType</c> are:</p>
- <p></p>
- <list type="bulleted">
- <item>'MidC' - only compare the time represented by each object. Furthermore,
- the target object is always used as the first parameter in the
- comparison, i.e., if the target object's time is larger
- 'TCGreaterThan' will be returned.</item>
- <item>'IntervalC' - also takes the inaccuracy into consideration, i.e.,
- if the two objects interval overlaps 'TCIndeterminate' is returned,
- otherwise the as for 'MidC'.</item>
- </list>
- </desc>
- </func>
- <func>
- <name>time_to_interval(UTO, OtherUTO) -> TIO</name>
- <fsummary>Create a TIO representing the interval between the target object and the given UTO midpoint times</fsummary>
- <type>
- <v>UTO = OtherUTO = TIO = #objref</v>
- </type>
- <desc>
- <p>This operation returns a TIO representing the interval between the target
- object and the given UTO midpoint times. The inaccuracy in the objects are
- not taken into consideration.</p>
- </desc>
- </func>
- <func>
- <name>interval(UTO) -> TIO</name>
- <fsummary>Create a TIO object representing the error interval around the time value represented by the target object</fsummary>
- <type>
- <v>UTO = TIO = #objref</v>
- </type>
- <desc>
- <p>This operation creates a TIO object representing the error interval
- around the time value represented by the target object, i.e.,
- <c>TIO.upper_bound = UTO.time+UTO.inaccuracy</c> and
- <c>TIO.lower_bound = UTO.time-UTO.inaccuracy</c>.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosTime/doc/src/CosTimerEvent_TimerEventHandler.xml b/lib/cosTime/doc/src/CosTimerEvent_TimerEventHandler.xml
deleted file mode 100644
index 4b43b0b12e..0000000000
--- a/lib/cosTime/doc/src/CosTimerEvent_TimerEventHandler.xml
+++ /dev/null
@@ -1,125 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosTimerEvent_TimerEventHandler</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosTimerEvent_TimerEventHandler</module>
- <modulesummary>This module implements the OMG CosTimerEvent::TimerEventHandler interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosTime/include/*.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>'_get_status'(TimerEventHandler) -> Reply</name>
- <fsummary>Return the status of the target object</fsummary>
- <type>
- <v>TimerEventHandler = #objref</v>
- <v>Reply = 'ESTimeSet' | 'ESTimeCleared' | 'ESTriggered' | 'ESFailedTrigger'</v>
- </type>
- <desc>
- <p>This operation returns the status of the target object. </p>
- <list type="bulleted">
- <item>'ESTimeSet' - timer is set to trigger event(s).</item>
- <item>'ESTimeCleared' - no time set or the timer have been reset.</item>
- <item>'ESTriggered' - event has already been sent.</item>
- <item>'ESFailedTrigger' - tried to, but failed, sending the event.</item>
- </list>
- <p>If the target object is of type 'TTPeriodic' the status value
- 'ESTriggered' is not valid.</p>
- </desc>
- </func>
- <func>
- <name>time_set(TimerEventHandler) -> Reply</name>
- <fsummary>Return <c>true</c>if the time has been set for an event that is yet to be triggered, <c>false</c>otherwise. The outparameter represents the current time value of the target object</fsummary>
- <type>
- <v>TimerEventHandler = #objref</v>
- <v>Reply = {boolean(), UTO}</v>
- <v>UTO = #objref</v>
- </type>
- <desc>
- <p>This operation returns <c>true</c> if the time has been set for an event that
- is yet to be triggered, <c>false</c> otherwise. The outparameter represents
- the current time value of the target object.</p>
- </desc>
- </func>
- <func>
- <name>set_timer(TimerEventHandler, TimeType, TriggerTime) -> void()</name>
- <fsummary>Terminate terminate any previous set trigger, and set a new trigger specified by the <c>TimeType</c>and <c>UTO</c>objects</fsummary>
- <type>
- <v>TimerEventHandler = #objref</v>
- <v>TimeType = 'TTAbsolute' | 'TTRelative' | 'TTPeriodic'</v>
- <v>TriggerTime = UTO</v>
- <v>UTO = #objref</v>
- </type>
- <desc>
- <p>This operation terminates any previous set trigger, and set a new trigger
- specified by the <c>TimeType</c> and <c>UTO</c> objects.</p>
- <p>The relation between the UTO object and the TimeTypes are:</p>
- <list type="bulleted">
- <item>'TTAbsolute' - the UTO object must represent absolute time, i.e.,
- number of 100 nanoseconds passed since 15 october
- 1582 00:00.</item>
- <item>'TTRelative' - the UTO object must represent the from now until when
- the event should be triggered, e.g., within 30*10^7 nanoseconds.</item>
- <item>'TTPeriodic' - the same as for 'TTRelative', but this option
- will trigger an event periodically until timer cancelled.</item>
- </list>
- </desc>
- </func>
- <func>
- <name>cancel_timer(TimerEventHandler) -> boolean()</name>
- <fsummary>Cancel, if possible, triggering of event(s). Return<c>true</c>if an event is actually cancelled, <c>false</c>otherwise</fsummary>
- <type>
- <v>TimerEventHandler = #objref</v>
- </type>
- <desc>
- <p>This operation cancel, if possible, the triggering of event(s). Returns
- <c>true</c> if an event is actually cancelled, <c>false</c> otherwise.</p>
- </desc>
- </func>
- <func>
- <name>set_data(TimerEventHandler, EventData) -> ok</name>
- <fsummary>Change the event data sent when triggered</fsummary>
- <type>
- <v>TimerEventHandler = #objref</v>
- <v>EventData = #any</v>
- </type>
- <desc>
- <p>This operation changes the event data sent when triggered.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosTime/doc/src/CosTimerEvent_TimerEventService.xml b/lib/cosTime/doc/src/CosTimerEvent_TimerEventService.xml
deleted file mode 100644
index 1db4760c81..0000000000
--- a/lib/cosTime/doc/src/CosTimerEvent_TimerEventService.xml
+++ /dev/null
@@ -1,84 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosTimerEvent_TimerEventService</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2000-02-01</date>
- <rev>1.0</rev>
- </header>
- <module>CosTimerEvent_TimerEventService</module>
- <modulesummary>This module implements the OMG CosTimerEvent::TimerEventService interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosTime/include/*.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>register(TimerEventService, CosEventCommPushConsumer, Data) -> TimerEventHandler</name>
- <fsummary>Create a new <c>TimerEventHandler</c>object which push the given<c>Data</c>to given <c>CosEventCommPushConsumer</c>after the timer have been set</fsummary>
- <type>
- <v>TimerEventService = CosEventCommPushConsumer = TimerEventHandler = #objref</v>
- <v>Data = #any</v>
- </type>
- <desc>
- <p>This operation will create a new <c>TimerEventHandler</c> object which
- will push given <c>Data</c> to given <c>CosEventCommPushConsumer</c> after
- the timer have been set.</p>
- </desc>
- </func>
- <func>
- <name>unregister(TimerEventService, TimerEventHandler) -> ok</name>
- <fsummary>Terminate the target TimerEventHandler object</fsummary>
- <type>
- <v>TimerEventService = TimerEventHandler = #objref</v>
- </type>
- <desc>
- <p>This operation will terminate the given TimerEventHandler.</p>
- </desc>
- </func>
- <func>
- <name>event_time(TimerEventService, TimerEvent) -> UTO</name>
- <fsummary>Return a UTO containing the time at which the associated event was triggered</fsummary>
- <type>
- <v>TimerEventService = #objref</v>
- <v>TimerEvent = #'CosTimerEvent_TimerEvent'{utc, event_data}</v>
- <v>utc = </v>
- <v>event_data = #any}</v>
- <v>UTO = #objref</v>
- </type>
- <desc>
- <p>This operation returns a UTO containing the time at which the associated
- event was triggered.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosTime/doc/src/Makefile b/lib/cosTime/doc/src/Makefile
deleted file mode 100644
index f3fdafa58a..0000000000
--- a/lib/cosTime/doc/src/Makefile
+++ /dev/null
@@ -1,143 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(COSTIME_VSN)
-APPLICATION=cosTime
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = \
- cosTime.xml \
- CosTime_TIO.xml \
- CosTime_TimeService.xml \
- CosTime_UTO.xml \
- CosTimerEvent_TimerEventHandler.xml \
- CosTimerEvent_TimerEventService.xml \
-
-XML_PART_FILES = \
- part.xml \
- part_notes.xml
-XML_CHAPTER_FILES = \
- ch_contents.xml \
- ch_introduction.xml \
- ch_install.xml \
- ch_example.xml \
- notes.xml
-
-BOOK_FILES = book.xml
-
-XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \
- $(XML_PART_FILES) $(XML_CHAPTER_FILES)
-
-TECHNICAL_DESCR_FILES =
-
-GIF_FILES = \
- book.gif \
- notes.gif \
- ref_man.gif \
- user_guide.gif
-
-PS_FILES =
-
-# ----------------------------------------------------
-
-INTERNAL_HTML_FILES = $(TECHNICAL_DESCR_FILES:%.xml=$(HTMLDIR)/%.html)
-
-HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
-
-INFO_FILE = ../../info
-EXTRA_FILES = summary.html.src \
- $(DEFAULT_GIF_FILES) \
- $(DEFAULT_HTML_FILES) \
- $(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html)
-
-MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-
-HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
-
-TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-$(HTMLDIR)/%.gif: %.gif
- $(INSTALL_DATA) $< $@
-
-docs: pdf html man
-
-$(TOP_PDF_FILE): $(XML_FILES)
-
-pdf: $(TOP_PDF_FILE)
-
-html: gifs $(HTML_REF_MAN_FILE)
-
-clean clean_docs:
- rm -rf $(HTMLDIR)/*
- rm -f $(MAN3DIR)/*
- rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
-
-man: $(MAN3_FILES)
-
-gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-
-$(INDEX_TARGET): $(INDEX_SRC)
- sed -e 's;%VSN%;$(VSN);' $(INDEX_SRC) > $(INDEX_TARGET)
-
-debug opt:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_docs_spec: docs
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(HTMLDIR)/* \
- "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
- $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
-
-release_spec:
diff --git a/lib/cosTime/doc/src/book.gif b/lib/cosTime/doc/src/book.gif
deleted file mode 100644
index 94b3868792..0000000000
--- a/lib/cosTime/doc/src/book.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosTime/doc/src/book.xml b/lib/cosTime/doc/src/book.xml
deleted file mode 100644
index a89b005e84..0000000000
--- a/lib/cosTime/doc/src/book.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book xmlns:xi="http://www.w3.org/2001/XInclude">
- <header titlestyle="normal">
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosTime</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-01-31</date>
- <rev>1.0</rev>
- </header>
- <insidecover>
- </insidecover>
- <pagetext>cosTime</pagetext>
- <preamble>
- <contents level="2"></contents>
- </preamble>
- <parts lift="no">
- <xi:include href="part.xml"/>
- </parts>
- <applications>
- <xi:include href="ref_man.xml"/>
- </applications>
- <releasenotes>
- <xi:include href="notes.xml"/>
- </releasenotes>
- <listofterms></listofterms>
- <index></index>
-</book>
-
diff --git a/lib/cosTime/doc/src/ch_contents.xml b/lib/cosTime/doc/src/ch_contents.xml
deleted file mode 100644
index 8b1c9dd646..0000000000
--- a/lib/cosTime/doc/src/ch_contents.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>The cosTime Application</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-01-31</date>
- <rev>1.0</rev>
- <file>ch_contents.xml</file>
- </header>
-
- <section>
- <title>Content Overview</title>
- <p>The cosTime documentation is divided into three sections:
- </p>
- <list type="bulleted">
- <item>
- <p>PART ONE - The User's Guide
- <br></br>
-Description of the cosTime Application including
- services and a small tutorial demonstrating
- the development of a simple service.</p>
- </item>
- <item>
- <p>PART TWO - Release Notes
- <br></br>
-A concise history of cosTime.</p>
- </item>
- <item>
- <p>PART THREE - The Reference Manual
- <br></br>
- A quick reference guide, including a
- brief description, to all the functions available in cosTime.</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Brief Description of the User's Guide</title>
- <p>The User's Guide contains the following parts:</p>
- <list type="bulleted">
- <item>
- <p>cosTime overview</p>
- </item>
- <item>
- <p>cosTime installation</p>
- </item>
- <item>
- <p>A tutorial example</p>
- </item>
- </list>
- </section>
-</chapter>
-
diff --git a/lib/cosTime/doc/src/ch_example.xml b/lib/cosTime/doc/src/ch_example.xml
deleted file mode 100644
index 690fba8d93..0000000000
--- a/lib/cosTime/doc/src/ch_example.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosTime Examples</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-01-31</date>
- <rev>A</rev>
- <file>ch_example.xml</file>
- </header>
-
- <section>
- <title>A Tutorial on How to Create a Simple Service</title>
-
- <section>
- <title>Initiate the Application</title>
- <p>To use the complete cosTime application Time and Timer Event Services
- must be installed. The application is then started by using
- <c>cosTime:start()</c>. To get access to Time Service or Timer Event Service,
- use <c>start_time_service/2</c> or <c>start_timerevent_service/1.</c></p>
- <p>The Time Service are global, i.e., there may only exist one instance per
- Orber domain.</p>
- <p>The Timer Event Service is locally registered, i.e., there may only exist
- one instance per node.</p>
- <note>
- <p>The Time and Timer Event Service use the time base
- <em>15 october 1582 00:00</em>. Performing operations using other time
- bases will not yield correct result. Furthermore, time and inaccuracy
- must be expressed in 100 nano seconds.</p>
- </note>
- </section>
-
- <section>
- <title>How to Run Everything</title>
- <p>Below is a short transcript on how to run cosTime. </p>
- <code type="none">
-
-%% Start Mnesia and Orber
-mnesia:delete_schema([node()]),
-mnesia:create_schema([node()]),
-orber:install([node()]),
-mnesia:start(),
-orber:start(),
-
-%% Install Time Service in the IFR.
-cosTime:install_time(),
-
-%% Install Timer Event Service in the IFR. Which, require
-%% the Time Service and cosEvent or cosNotification
-%% application to be installed.
-cosNotification:install(),
-cosTime:install_timerevent(),
-
-%% Now start the application and necessary services.
-cosTime:start(),
-%% Tdf == Time displacement factor
-%% Inaccuracy measured in 100 nano seconds
-TS=cosTime:start_time_service(TDF, Inaccuracy),
-TES=cosTime:start_timerevent_service(TS),
-
-%% Access a cosNotification Proxy Push Consumer. How this is
-%% done is implementation specific.
-ProxyPushConsumer = ....
-
-%% How we construct the event is also implementation specific.
-AnyEvent = ....
-
-%% Create a new relative universal time.
-%% Time measured in 100 nano seconds.
-UTO='CosTime_TimeService':
- new_universal_time(TS, Time, Inaccuracy, TDF),
-EH='CosTimerEvent_TimerEventService':
- register(TES, ProxyPushConsumer, AnyEvent),
-
-%% If we want to trigger one event Time*10^-7 seconds from now:
-'CosTimerEvent_TimerEventHandler':set_timer(EH, 'TTRelative', UTO),
-
-%% If we want to trigger an event every Time*10^-7 seconds, starting
-%% Time*10^-7 seconds from now:
-'CosTimerEvent_TimerEventHandler':set_timer(EH, 'TTPeriodic', UTO),
-
-%% If we want to use absolute time we must retrieve such an object.
-%% One way is to convert the one we got, UTO, by using:
-UTO2='CosTime_UTO':absolute_time(UTO),
-%% If any other way is used, the correct time base MUST be used, i.e.,
-%% 15 october 1582 00:00.
-'CosTimerEvent_TimerEventHandler':set_timer(EH, 'TTAbsolute', UTO2),
- </code>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosTime/doc/src/ch_install.xml b/lib/cosTime/doc/src/ch_install.xml
deleted file mode 100644
index 9d819a7be7..0000000000
--- a/lib/cosTime/doc/src/ch_install.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Installing cosTime</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-01-31</date>
- <rev></rev>
- <file>ch_install.xml</file>
- </header>
-
- <section>
- <title>Installation Process </title>
- <p>This chapter describes how to install
- <seealso marker="cosTime">cosTime</seealso> in an Erlang Environment.
- </p>
-
- <section>
- <title>Preparation</title>
- <p>Before starting the installation process for cosTime,
- the application Orber must be running.</p>
- </section>
-
- <section>
- <title>Configuration</title>
- <p>When using both the Time and TimerEvent Services the <c>cosTime</c> application
- first must be installed using <c>cosTime:install_time()</c> and
- <c>cosTime:install_timerevent()</c>, followed by <c>cosTime:start()</c>.
- Now we can choose which can start the servers by using
- <c>cosTime:start_time_service(Tdf, Inaccuracy)</c>
- and <c>cosTime:start_timerevent_service(TimeService)</c>.</p>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosTime/doc/src/ch_introduction.xml b/lib/cosTime/doc/src/ch_introduction.xml
deleted file mode 100644
index 1a11606716..0000000000
--- a/lib/cosTime/doc/src/ch_introduction.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Introduction to cosTime</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-01-31</date>
- <rev></rev>
- <file>ch_introduction.xml</file>
- </header>
-
- <section>
- <title>Overview</title>
- <p>The cosTime application is Time and TimerEvent Services compliant with the <url href="http://www.omg.org">OMG</url>
- Services CosTime and CosTimerEvent.
- </p>
-
- <section>
- <title>Purpose and Dependencies</title>
- <p>This application use <c>calender:now_to_universal_time(Now)</c> to create a
- UTC. Hence, the underlying OS must deliver a correct result when calling
- <c>erlang:now()</c>.</p>
- <p><em>cosTime</em> is dependent on <em>Orber</em>, which provides CORBA functionality in an Erlang environment.</p>
- <p><em>cosTimerEvent</em> is dependent on <em>Orber</em> and <em>cosNotification</em>,
- which provides CORBA functionality and Event handling in an Erlang environment.</p>
- </section>
-
- <section>
- <title>Prerequisites</title>
- <p>To fully understand the concepts presented in the
- documentation, it is recommended that the user is familiar
- with distributed programming, CORBA, the Orber and cosNotification applications.
- </p>
- <p>Recommended reading includes <em>CORBA, Fundamentals and Programming - Jon Siegel</em> and <em>Open Telecom Platform Documentation Set</em>. It is also helpful to have read <em>Concurrent Programming in Erlang</em>.</p>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosTime/doc/src/cosTime.xml b/lib/cosTime/doc/src/cosTime.xml
deleted file mode 100644
index 02aef1401c..0000000000
--- a/lib/cosTime/doc/src/cosTime.xml
+++ /dev/null
@@ -1,175 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>cosTime</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>2000-01-31</date>
- <rev>PA1</rev>
- </header>
- <module>cosTime</module>
- <modulesummary>The main module of the cosTime application</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosTime/include/*.hrl").</c></p>
- <p>This module contains the functions for starting and stopping the application.</p>
- <p>This application use the time base <em>15 october 1582 00:00</em>.
- Performing operations using other time bases will not yield correct result.</p>
- <p>The OMG CosTime specification defines the operation
- <c>secure_universal_time</c>. As of today we cannot provide this functionality
- considering the criteria demanded to fulfill the OMG specification.</p>
- <p>When using this application, time and inaccuracy supplied by the user must
- be given in number of <em>100 nano seconds</em>. The
- <em>Time Displacement Factor</em> is positive east of the meridian, while
- those to the west are negative.</p>
- <p>This application use <c>calender:now_to_universal_time(Now)</c> to create a
- UTC. Hence, the underlying OS must deliver a correct result when calling
- <c>erlang:now()</c>.</p>
- <p>When determining the inaccuracy of the system, the user should consider the
- way the time objects will be used. Communicating with other ORB's, add a
- substantial overhead and should be taken into consideration.</p>
- </description>
- <funcs>
- <func>
- <name>install_time() -> Return</name>
- <fsummary>Install the cosTime Time Service part application</fsummary>
- <type>
- <v>Return = ok | {'EXIT', Reason}</v>
- </type>
- <desc>
- <p>This operation installs the cosTime Time Service part application.</p>
- </desc>
- </func>
- <func>
- <name>uninstall_time() -> Return</name>
- <fsummary>Uninstall the cosTime Time Service part application</fsummary>
- <type>
- <v>Return = ok | {'EXIT', Reason}</v>
- </type>
- <desc>
- <p>This operation uninstalls the cosTime Time Service part application.</p>
- </desc>
- </func>
- <func>
- <name>install_timerevent() -> Return</name>
- <fsummary>Install the cosTime Timer Event Service part application</fsummary>
- <type>
- <v>Return = ok | {'EXIT', Reason}</v>
- </type>
- <desc>
- <p>This operation installs the cosTime Timer Event Service part application.</p>
- <note>
- <p>The Timer Event Service part requires <em>Time Service</em> part and
- <em>cosEvent</em> or the <em>cosNotification</em> application to be installed
- first.</p>
- </note>
- </desc>
- </func>
- <func>
- <name>uninstall_timerevent() -> Return</name>
- <fsummary>Uninstall the cosTime Timer Event Service part application</fsummary>
- <type>
- <v>Return = ok | {'EXIT', Reason}</v>
- </type>
- <desc>
- <p>This operation uninstalls the cosTime Timer Event Service part application.</p>
- </desc>
- </func>
- <func>
- <name>start() -> Return</name>
- <fsummary>Start the cosTime application</fsummary>
- <type>
- <v>Return = ok | {error, Reason}</v>
- </type>
- <desc>
- <p>This operation starts the cosTime application.</p>
- </desc>
- </func>
- <func>
- <name>stop() -> Return</name>
- <fsummary>Stop the cosTime application</fsummary>
- <type>
- <v>Return = ok | {error, Reason}</v>
- </type>
- <desc>
- <p>This operation stops the cosTime application.</p>
- </desc>
- </func>
- <func>
- <name>start_time_service(Tdf, Inaccuracy) -> Return</name>
- <fsummary>Start a Time Service object</fsummary>
- <type>
- <v>Tdf = short()</v>
- <v>Inaccuracy = ulonglong(), eq. #100 nano seconds</v>
- <v>Return = ok | {'EXCEPTION', #'BAD_PARAM'{}}</v>
- </type>
- <desc>
- <p>This operation starts a Time Service server. Please note that there
- may only be exactly one Time Service active at a time. The <c>Inaccuracy</c>
- parameter defines the inaccuracy the underlying OS will introduce. Remember
- to take into account latency when passing time object between nodes.</p>
- </desc>
- </func>
- <func>
- <name>stop_time_service(TimeService) -> ok</name>
- <fsummary>Stop the target Time Service object</fsummary>
- <type>
- <v>TimeService = #objref</v>
- </type>
- <desc>
- <p>This operation stops the Time Service object.</p>
- </desc>
- </func>
- <func>
- <name>start_timerevent_service(TimeService) -> ok</name>
- <fsummary>Start a Timer Event Service object</fsummary>
- <type>
- <v>TimeService = #objref</v>
- </type>
- <desc>
- <p>This operation starts a Timer Event Service server. Please note that there
- may only be exactly one Timer Event Service per node active at a time. The
- supplied TimeServcie reference will be the object Timer Event Service
- contacts to get access to a new UTC.</p>
- </desc>
- </func>
- <func>
- <name>stop_timerevent_service(TimerEventService) -> ok</name>
- <fsummary>Stop the target Timer Event Service object</fsummary>
- <type>
- <v>TimerEventService = #objref</v>
- </type>
- <desc>
- <p>This operation stops the Timer Event Service object.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosTime/doc/src/fascicules.xml b/lib/cosTime/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/cosTime/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/cosTime/doc/src/notes.gif b/lib/cosTime/doc/src/notes.gif
deleted file mode 100644
index e000cca26a..0000000000
--- a/lib/cosTime/doc/src/notes.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosTime/doc/src/notes.xml b/lib/cosTime/doc/src/notes.xml
deleted file mode 100644
index 686d9e6add..0000000000
--- a/lib/cosTime/doc/src/notes.xml
+++ /dev/null
@@ -1,345 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosTime Release Notes</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2000-01-31</date>
- <rev>A</rev>
- <file>notes.xml</file>
- </header>
-
- <section><title>cosTime 1.2.2</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Internal changes</p>
- <p>
- Own Id: OTP-13551</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosTime 1.2.1</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> Suppress Dialyzer warnings. </p>
- <p>
- Own Id: OTP-12862</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosTime 1.2</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> Remove the usage of erlang:now() from all Corba
- applications and use the new rand module instead of
- random. </p>
- <p>
- Own Id: OTP-12687</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosTime 1.1.14</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> The default encoding of Erlang files has been changed
- from ISO-8859-1 to UTF-8. </p> <p> The encoding of XML
- files has also been changed to UTF-8. </p>
- <p>
- Own Id: OTP-10907</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosTime 1.1.13</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Misc build updates</p>
- <p>
- Own Id: OTP-10784</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosTime 1.1.12</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>Erlang/OTP can now be built using parallel make if you
- limit the number of jobs, for instance using '<c>make
- -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
- work at the moment because of some missing
- dependencies.</p>
- <p>
- Own Id: OTP-9451</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section>
- <title>cosTime 1.1.11</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Removed superfluous usage of shy in the documentation since it can cause problem if
- a buggy tool is used.</p>
- <p>
- Own Id: OTP-9319 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTime 1.1.10</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Eliminated Dialyzer warnings when using exit or throw.</p>
- <p>
- Own Id: OTP-9050 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTime 1.1.9</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Test suites published.</p>
- <p>
- Own Id: OTP-8543 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTime 1.1.8</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The documentation EIX file was not generated.</p>
- <p>Own id: OTP-8355 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTime 1.1.7</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- The documentation is now built with open source tools (xsltproc and fop)
- that exists on most platforms. One visible change is that the frames are removed.</p>
- <p>
- Own Id: OTP-8201 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTime 1.1.6</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Obsolete guards, e.g. record vs is_record, has been changed
- to avoid compiler warnings.</p>
- <p>Own id: OTP-7987</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTime 1.1.5</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Updated file headers.</p>
- <p>Own id: OTP-7837</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTime 1.1.4</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Documentation source included in open source releases.</p>
- <p>Own id: OTP-7595</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTime 1.1.3</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Updated file headers.</p>
- <p>Own id: OTP-7011</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTime 1.1.2</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The documentation source has been converted from SGML to XML.</p>
- <p>Own id: OTP-6754</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTime 1.1.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Minor Makefile changes.</p>
- <p>Own id: OTP-6701</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTime 1.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The stub/skeleton-files generated by IC have been improved,
- i.e., depending on the IDL-files, reduced the size of the
- erl- and beam-files and decreased dependencies off Orber's
- Interface Repository. It is necessary to re-compile all IDL-files
- and use COS-applications, including Orber, compiled with
- IC-4.2.</p>
- <p>Own id: OTP-4576</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTime 1.0.1.1</title>
-
- <section>
- <title>Incompatibilities</title>
- <list type="bulleted">
- <item>
- <p>An includepath in <c>CosTimerEvent.idl</c> have been
- changed. Hence, if you include this file you should check
- your include paths for your IDL-file(s), i.e., add
- the path to CosEventComm.idl.</p>
- <p>Own Id: OTP-4093</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTime 1.0.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>First release of the cosTime application.</p>
- <p>Own Id: -</p>
- </item>
- </list>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosTime/doc/src/part.xml b/lib/cosTime/doc/src/part.xml
deleted file mode 100644
index f0b26d4a56..0000000000
--- a/lib/cosTime/doc/src/part.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosTime User's Guide</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-01-31</date>
- <rev>1.0</rev>
- </header>
- <description>
- <p>The <em>cosTime</em> application is an Erlang implementation of the OMG
- CORBA Time and TimerEvent Services.</p>
- </description>
- <xi:include href="ch_contents.xml"/>
- <xi:include href="ch_introduction.xml"/>
- <xi:include href="ch_install.xml"/>
- <xi:include href="ch_example.xml"/>
-</part>
-
diff --git a/lib/cosTime/doc/src/part_notes.xml b/lib/cosTime/doc/src/part_notes.xml
deleted file mode 100644
index dbc9185038..0000000000
--- a/lib/cosTime/doc/src/part_notes.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosTime Release Notes</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-01-31</date>
- <rev>1.0</rev>
- </header>
- <description>
- <p>The cosTime Application is an Erlang implementation of the OMG
- CORBA Time and TimerEvent Services.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/cosTime/doc/src/ref_man.gif b/lib/cosTime/doc/src/ref_man.gif
deleted file mode 100644
index b13c4efd53..0000000000
--- a/lib/cosTime/doc/src/ref_man.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosTime/doc/src/ref_man.xml b/lib/cosTime/doc/src/ref_man.xml
deleted file mode 100644
index 66bca4af0e..0000000000
--- a/lib/cosTime/doc/src/ref_man.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE application SYSTEM "application.dtd">
-
-<application xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosTime Reference Manual</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2000-01-31</date>
- <rev>1.0</rev>
- </header>
- <description>
- <p>The <em>cosTime</em> application is an Erlang implementation of the OMG
- CORBA Time and TimerEvent Services.</p>
- </description>
- <xi:include href="cosTime.xml"/>
- <xi:include href="CosTime_TIO.xml"/>
- <xi:include href="CosTime_TimeService.xml"/>
- <xi:include href="CosTime_UTO.xml"/>
- <xi:include href="CosTimerEvent_TimerEventHandler.xml"/>
- <xi:include href="CosTimerEvent_TimerEventService.xml"/>
-</application>
-
diff --git a/lib/cosTime/doc/src/summary.html.src b/lib/cosTime/doc/src/summary.html.src
deleted file mode 100644
index 78e383d275..0000000000
--- a/lib/cosTime/doc/src/summary.html.src
+++ /dev/null
@@ -1 +0,0 @@
-Orber OMG Timer and TimerEvent Services.
diff --git a/lib/cosTime/doc/src/user_guide.gif b/lib/cosTime/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/cosTime/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosTime/ebin/.gitignore b/lib/cosTime/ebin/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosTime/ebin/.gitignore
+++ /dev/null
diff --git a/lib/cosTime/examples/.gitignore b/lib/cosTime/examples/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosTime/examples/.gitignore
+++ /dev/null
diff --git a/lib/cosTime/include/.gitignore b/lib/cosTime/include/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosTime/include/.gitignore
+++ /dev/null
diff --git a/lib/cosTime/info b/lib/cosTime/info
deleted file mode 100644
index 7820f3fdaa..0000000000
--- a/lib/cosTime/info
+++ /dev/null
@@ -1,12 +0,0 @@
-group: orb
-short: Orber OMG Timer and TimerEvent Services
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/cosTime/priv/.gitignore b/lib/cosTime/priv/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosTime/priv/.gitignore
+++ /dev/null
diff --git a/lib/cosTime/src/CosTime.cfg b/lib/cosTime/src/CosTime.cfg
deleted file mode 100644
index 1aad9ebb94..0000000000
--- a/lib/cosTime/src/CosTime.cfg
+++ /dev/null
@@ -1,6 +0,0 @@
-{this, "CosTime::UTO"}.
-{{handle_info, "CosTime::UTO"}, true}.
-{this, "CosTime::TIO"}.
-{{handle_info, "CosTime::TIO"}, true}.
-{this, "CosTime::TimeService"}.
-{{handle_info, "CosTime::TimeService"}, true}.
diff --git a/lib/cosTime/src/CosTime.idl b/lib/cosTime/src/CosTime.idl
deleted file mode 100644
index 2bf32681c1..0000000000
--- a/lib/cosTime/src/CosTime.idl
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef _COS_TIME_IDL_
-#define _COS_TIME_IDL_
-
-#pragma prefix "omg.org"
-
-#include<TimeBase.idl>
-
-module CosTime {
- enum TimeComparison {
- TCEqualTo,
- TCLessThan,
- TCGreaterThan,
- TCIndeterminate
- };
- enum ComparisonType{
- IntervalC,
- MidC };
- enum OverlapType {
- OTContainer,
- OTContained,
- OTOverlap,
- OTNoOverlap
- };
-
- exception TimeUnavailable {};
- interface TIO; // forward declaration
-
- interface UTO {
- readonly attribute TimeBase::TimeT time;
- readonly attribute TimeBase::InaccuracyT inaccuracy;
- readonly attribute TimeBase::TdfT tdf;
- readonly attribute TimeBase::UtcT utc_time;
-
- UTO absolute_time();
- TimeComparison compare_time( in ComparisonType comparison_type, in UTO uto );
- TIO time_to_interval( in UTO uto );
- TIO interval();
- };
-
- interface TIO {
- readonly attribute TimeBase::IntervalT time_interval;
-
- OverlapType spans ( in UTO time, out TIO overlap );
- OverlapType overlaps ( in TIO interval, out TIO overlap );
- UTO time ();
- };
-
- interface TimeService {
- UTO universal_time()
- raises(TimeUnavailable );
- UTO secure_universal_time()
- raises(TimeUnavailable );
- UTO new_universal_time( in TimeBase::TimeT time, in TimeBase::InaccuracyT inaccuracy, in TimeBase::TdfT tdf );
- UTO uto_from_utc( in TimeBase::UtcT utc );
- TIO new_interval( in TimeBase::TimeT lower, in TimeBase::TimeT upper );
- };
-};
-
-#endif
diff --git a/lib/cosTime/src/CosTime_TIO_impl.erl b/lib/cosTime/src/CosTime_TIO_impl.erl
deleted file mode 100644
index 6d4046d428..0000000000
--- a/lib/cosTime/src/CosTime_TIO_impl.erl
+++ /dev/null
@@ -1,201 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosTime_TIO_impl.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module('CosTime_TIO_impl').
-
-%%--------------- INCLUDES -----------------------------------
--include("cosTimeApp.hrl").
-
-%%--------------- EXPORTS ------------------------------------
-%%--------------- External -----------------------------------
-%% Attributes (external)
--export(['_get_time_interval'/2]).
-
-%% Interface functions
--export([spans/3, overlaps/3, time/2]).
-
-%%--------------- gen_server specific exports ----------------
--export([handle_info/2, code_change/3]).
--export([init/1, terminate/2]).
-
-
-%% Data structures
--record(state, {interval,
- tdf,
- timer}).
-%% Data structures constructors
--define(get_InitState(I,T,TO),
- #state{interval = I,
- tdf = T,
- timer = TO}).
-
-%% Data structures selectors
--define(get_IntervalT(S), S#state.interval).
--define(get_Lower(S), (S#state.interval)#'TimeBase_IntervalT'.lower_bound).
--define(get_Upper(S), (S#state.interval)#'TimeBase_IntervalT'.upper_bound).
--define(get_Tdf(S), S#state.tdf).
--define(get_TimerObj(S), S#state.timer).
-
-%%-----------------------------------------------------------%
-%% function : handle_info, code_change
-%% Arguments:
-%% Returns :
-%% Effect : Functions demanded by the gen_server module.
-%%------------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-handle_info(_Info, State) ->
- {noreply, State}.
-
-%%----------------------------------------------------------%
-%% function : init, terminate
-%% Arguments:
-%%-----------------------------------------------------------
-
-init([Interval, Tdf, Timer]) ->
- {ok, ?get_InitState(Interval, Tdf, Timer)}.
-
-terminate(_Reason, _State) ->
- ok.
-
-%%-----------------------------------------------------------
-%%------------------------ attributes -----------------------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% Attribute: '_get_time_interval'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_time_interval'(_OE_THIS, State) ->
- {reply, ?get_IntervalT(State), State}.
-
-%%-----------------------------------------------------------
-%%------- Exported external functions -----------------------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% function : spans
-%% Arguments: Time - UTO
-%% Returns : CosTime::OverLapType - enum()
-%% TIO - out-parameter.
-%%-----------------------------------------------------------
-spans(_OE_THIS, State, Time) ->
- ?time_TypeCheck(Time, 'CosTime_UTO'),
- case catch 'CosTime_UTO':'_get_utc_time'(Time) of
- #'TimeBase_UtcT'{time = Btime, inacclo = InaccL, inacchi=InaccH} ->
- Inaccuarcy = ?concat_TimeT(InaccH, InaccL),
- BL = Btime - Inaccuarcy,
- BU = Btime + Inaccuarcy,
- L = ?get_Lower(State),
- U = ?get_Upper(State),
- {Type, NewL, NewU} =
- if
- L=<BL, U>=BU ->
- {'OTContainer',BL,BU};
- L>=BL, U=<BU ->
- {'OTContained',L,U};
- L<BL, U=<BU, U>=BL ->
- {'OTOverlap',BL,U};
- L>=BL, L=<BU, U>BU ->
- {'OTOverlap',L,BU};
- L>BU ->
- {'OTNoOverlap',BU,L};
- true ->
- {'OTNoOverlap',U,BL}
- end,
- {reply,
- {Type,
- 'CosTime_TIO':oe_create([#'TimeBase_IntervalT'{lower_bound=NewL,
- upper_bound=NewU},
- ?get_Tdf(State),
- ?get_TimerObj(State)],
- [{pseudo,true}|?CREATE_OPTS])},
- State};
- _ ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end.
-
-
-%%----------------------------------------------------------%
-%% function : overlaps
-%% Arguments: Interval - TIO
-%% Returns : CosTime::OverLapType - enum()
-%% TIO - out-parameter.
-%%-----------------------------------------------------------
-overlaps(_OE_THIS, State, Interval) ->
- ?time_TypeCheck(Interval, 'CosTime_TIO'),
- case catch 'CosTime_TIO':'_get_time_interval'(Interval) of
- #'TimeBase_IntervalT'{lower_bound=BL, upper_bound=BU} ->
- L = ?get_Lower(State),
- U = ?get_Upper(State),
- {Type, NewL, NewU} =
- if
- L=<BL, U>=BU ->
- {'OTContainer',BL,BU};
- L>=BL, U=<BU ->
- {'OTContained',L,U};
- L<BL, U=<BU, U>=BL ->
- {'OTOverlap',BL,U};
- L>=BL, L=<BU, U>BU ->
- {'OTOverlap',L,BU};
- L>BU ->
- {'OTNoOverlap',BU,L};
- true ->
- {'OTNoOverlap',U,BL}
- end,
- {reply,
- {Type,
- 'CosTime_TIO':oe_create([#'TimeBase_IntervalT'{lower_bound=NewL,
- upper_bound=NewU},
- ?get_Tdf(State),
- ?get_TimerObj(State)],
- [{pseudo,true}|?CREATE_OPTS])},
- State};
- _ ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------%
-%% function : time
-%% Arguments: -
-%% Returns : UTO
-%%-----------------------------------------------------------
-time(_OE_THIS, State) ->
- L = ?get_Lower(State),
- H = ?get_Upper(State),
- Utc = #'TimeBase_UtcT'{time=(erlang:trunc(((H-L)/2))+L),
- inacclo=L,
- inacchi=H,
- tdf=?get_Tdf(State)},
- {reply,
- 'CosTime_UTO':oe_create([Utc, ?get_TimerObj(State)], [{pseudo,true}|?CREATE_OPTS]),
- State}.
-
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-
-%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosTime/src/CosTime_TimeService_impl.erl b/lib/cosTime/src/CosTime_TimeService_impl.erl
deleted file mode 100644
index 72c65757ad..0000000000
--- a/lib/cosTime/src/CosTime_TimeService_impl.erl
+++ /dev/null
@@ -1,182 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosTime_TimeService_impl.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module('CosTime_TimeService_impl').
-
-%%--------------- INCLUDES -----------------------------------
--include("cosTimeApp.hrl").
-
-%%--------------- EXPORTS ------------------------------------
-%%--------------- External -----------------------------------
-%% Interface functions
--export([universal_time/2, secure_universal_time/2, new_universal_time/5]).
--export([uto_from_utc/3, new_interval/4]).
-
-%%--------------- gen_server specific exports ----------------
--export([handle_info/2, code_change/3]).
--export([init/1, terminate/2]).
-
-
-%% Data structures
--record(state,
- {tdf,
- inaccuracy}).
-%% Data structures constructors
--define(get_InitState(T,I),
- #state{tdf = T,
- inaccuracy = I}).
-
-%% Data structures selectors
--define(get_Inaccuracy(S), S#state.inaccuracy).
--define(get_Tdf(S), S#state.tdf).
-
-%% Data structures modifiers
-
-%% MISC
-
-%%-----------------------------------------------------------%
-%% function : handle_info, code_change
-%% Arguments:
-%% Returns :
-%% Effect : Functions demanded by the gen_server module.
-%%------------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-handle_info(_Info, State) ->
- ?debug_print("INFO: ~p~n", [_Info]),
- {noreply, State}.
-
-%%----------------------------------------------------------%
-%% function : init, terminate
-%% Arguments:
-%%-----------------------------------------------------------
-
-init([Tdf, Inaccuracy]) ->
- process_flag(trap_exit, true),
- {ok, ?get_InitState(Tdf, Inaccuracy)}.
-
-terminate(_Reason, _State) ->
- ok.
-
-%%-----------------------------------------------------------
-%%------- Exported external functions -----------------------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% function : universal_time
-%% Arguments: -
-%% Returns : CosTime::UTO |
-%% {'EXCEPTION", #'CosTime_TimeUnavailable'{}}
-%% NOTE : cosTime:create_universal_time will raise the correct
-%% exception.
-%%-----------------------------------------------------------
-universal_time(OE_THIS, State) ->
- {ok, Time} = create_universal_time(),
- Inaccuracy = ?get_Inaccuracy(State),
- Utc = #'TimeBase_UtcT'{time=Time, inacclo = ?low_TimeT(Inaccuracy),
- inacchi = ?high_TimeT(Inaccuracy),
- tdf = ?get_Tdf(State)},
- {reply, 'CosTime_UTO':oe_create([Utc, OE_THIS], [{pseudo,true}|?CREATE_OPTS]), State}.
-
-%%----------------------------------------------------------%
-%% function : secure_universal_time
-%% Arguments:
-%% Returns : {'EXCEPTION", #'CosTime_TimeUnavailable'{}}
-%%-----------------------------------------------------------
--spec secure_universal_time(_, _) -> no_return().
-secure_universal_time(_OE_THIS, _State) ->
- corba:raise(#'CosTime_TimeUnavailable'{}).
-
-%%----------------------------------------------------------%
-%% function : new_universal_time
-%% Arguments: Time - TimeBase::TimeT
-%% Inaccuracy - TimeBase::InaccuracyT inaccuracy
-%% Tdf - TimeBase::TdfT
-%% Returns : CosTime::UTO
-%%-----------------------------------------------------------
-new_universal_time(OE_THIS, State, Time, Inaccuracy, Tdf) when
- is_integer(Time) andalso is_integer(Inaccuracy) andalso is_integer(Tdf) andalso
- Tdf=<12 andalso Inaccuracy=<?max_Inaccuracy andalso Time=<?max_TimeT ->
- Utc = #'TimeBase_UtcT'{time=Time, inacclo = ?low_TimeT(Inaccuracy),
- inacchi = ?high_TimeT(Inaccuracy), tdf = Tdf},
- {reply, 'CosTime_UTO':oe_create([Utc, OE_THIS], [{pseudo,true}|?CREATE_OPTS]), State};
-new_universal_time(_, _, _, _, _) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : uto_from_utc
-%% Arguments: Utc - TimeBase::UtcT
-%% Returns : CosTime::UTO
-%%-----------------------------------------------------------
-uto_from_utc(OE_THIS, State, Utc) when is_record(Utc, 'TimeBase_UtcT') ->
- {reply, 'CosTime_UTO':oe_create([Utc, OE_THIS],[{pseudo,true}|?CREATE_OPTS]),State};
-uto_from_utc(_, _, _) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : new_interval
-%% Arguments: Lower - TimeBase::TimeT
-%% Upper - TimeBase::TimeT
-%% Returns : CosTime::TIO
-%%-----------------------------------------------------------
-new_interval(OE_THIS, State, Lower, Upper) when is_integer(Lower) andalso is_integer(Upper) andalso
- Lower=<Upper ->
- {reply, 'CosTime_TIO':oe_create([#'TimeBase_IntervalT'{lower_bound=Lower,
- upper_bound=Upper},
- ?get_Tdf(State),
- OE_THIS],
- [{pseudo,true}|?CREATE_OPTS]), State};
-new_interval(_, _, _, _) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-%%-----------------------------------------------------------%
-%% function : create_universal_utc
-%% Arguments: -
-%% Returns : TimeT or raises exception.
-%% Effect : Creates a universal time; if time unavailable we
-%% must raise CosTime_TimeUnavailable.
-%% NOTE : 'datetime_to_gregorian_seconds' use year 0 as time
-%% base. We want to use 15 october 1582, 00:00 as base.
-%%------------------------------------------------------------
-
-create_universal_time() ->
- %% Time is supposed to be #100 nano-secs passed.
- %% We add micro secs for a greater precision.
- {MS,S,US} = erlang:timestamp(),
- case catch calendar:datetime_to_gregorian_seconds(
- calendar:now_to_universal_time({MS,S,US})) of
- Secs when is_integer(Secs) ->
- {ok, (Secs-?ABSOLUTE_TIME_DIFF)*10000000 + US*10};
- _ ->
- corba:raise(#'CosTime_TimeUnavailable'{})
- end.
-
-%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
-%%--------------- END OF MODULE ------------------------------
-
diff --git a/lib/cosTime/src/CosTime_UTO_impl.erl b/lib/cosTime/src/CosTime_UTO_impl.erl
deleted file mode 100644
index 09f3eb2fdb..0000000000
--- a/lib/cosTime/src/CosTime_UTO_impl.erl
+++ /dev/null
@@ -1,242 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosTime_UTO_impl.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module('CosTime_UTO_impl').
-
-%%--------------- INCLUDES -----------------------------------
--include("cosTimeApp.hrl").
-
-
-%%--------------- EXPORTS ------------------------------------
-%%--------------- External -----------------------------------
-%% Attributes (external)
--export(['_get_time'/2,
- '_get_inaccuracy'/2,
- '_get_tdf'/2,
- '_get_utc_time'/2]).
-
-%% Interface functions
--export([absolute_time/2, compare_time/4]).
--export([time_to_interval/3, interval/2]).
-
-%%--------------- gen_server specific exports ----------------
--export([handle_info/2, code_change/3]).
--export([init/1, terminate/2]).
-
-
-%% Data structures
--record(state, {timer, utc}).
-%% Data structures constructors
--define(get_InitState(U, T), #state{timer = T, utc = U}).
-
-%% Data structures selectors
--define(get_Time(S), (S#state.utc)#'TimeBase_UtcT'.time).
--define(get_Inaccuracy(S), ?concat_TimeT((S#state.utc)#'TimeBase_UtcT'.inacchi,
- (S#state.utc)#'TimeBase_UtcT'.inacclo)).
--define(get_Tdf(S), (S#state.utc)#'TimeBase_UtcT'.tdf).
--define(get_Utc(S), S#state.utc).
--define(get_TimeObj(S), S#state.timer).
-
-
-%%-----------------------------------------------------------%
-%% function : handle_info, code_change
-%% Arguments:
-%% Returns :
-%% Effect : Functions demanded by the gen_server module.
-%%------------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-handle_info(_Info, State) ->
- {noreply, State}.
-
-%%----------------------------------------------------------%
-%% function : init, terminate
-%% Arguments:
-%%-----------------------------------------------------------
-
-init([Utc, TimeObj]) ->
- {ok, ?get_InitState(Utc, TimeObj)}.
-
-terminate(_Reason, _State) ->
- ok.
-
-%%-----------------------------------------------------------
-%%------------------------ attributes -----------------------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% Attribute: '_get_time'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_time'(_OE_THIS, State) ->
- {reply, ?get_Time(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_inaccuracy'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_inaccuracy'(_OE_THIS, State) ->
- {reply, ?get_Inaccuracy(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_tdf'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_tdf'(_OE_THIS, State) ->
- {reply, ?get_Tdf(State), State}.
-
-%%----------------------------------------------------------%
-%% Attribute: '_get_utc_time'
-%% Type : readonly
-%% Returns :
-%%-----------------------------------------------------------
-'_get_utc_time'(_OE_THIS, State) ->
- {reply, ?get_Utc(State), State}.
-
-%%-----------------------------------------------------------
-%%------- Exported external functions -----------------------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% function : absolute_time
-%% Arguments: -
-%% Returns : UTO
-%% NOTE : Return the base time to the relative time in the object.
-%%-----------------------------------------------------------
-absolute_time(_OE_THIS, State) ->
- case catch 'CosTime_UTO':'_get_time'(
- 'CosTime_TimeService':universal_time(?get_TimeObj(State)))+
- ?get_Time(State) of
- UniTime when is_integer(UniTime) andalso UniTime =< ?max_TimeT ->
- Utc=?get_Utc(State),
- {reply, 'CosTime_UTO':oe_create([Utc#'TimeBase_UtcT'{time=UniTime},
- ?get_TimeObj(State)],
- [{pseudo,true}|?CREATE_OPTS]), State};
- UniTime when is_integer(UniTime) ->
- %% Oopss, overflow!
- corba:raise(#'DATA_CONVERSION'{completion_status=?COMPLETED_NO});
- _ ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------%
-%% function : compare_time
-%% Arguments: Comparison_type - CosTime::ComparisonType
-%% Uto - ObjRef
-%% Returns : TimeComparison - 'TCEqualTo' | 'TCLessThan' |
-%% 'TCGreaterThan' | 'TCIndeterminate'
-%%-----------------------------------------------------------
-compare_time(_OE_THIS, State, 'IntervalC', Uto) ->
- ?time_TypeCheck(Uto, 'CosTime_UTO'),
- case catch {'CosTime_UTO':'_get_time'(Uto),
- 'CosTime_UTO':'_get_inaccuracy'(Uto)} of
- {Time,Inaccuracy} when is_integer(Time) andalso is_integer(Inaccuracy) ->
- OwnInacc = ?get_Inaccuracy(State),
- if
- ?get_Time(State)+OwnInacc < Time-Inaccuracy ->
- {reply, 'TCLessThan', State};
- ?get_Time(State)-OwnInacc > Time+Inaccuracy ->
- {reply, 'TCGreaterThan', State};
- ?get_Time(State) == Time, Inaccuracy==0, OwnInacc==0 ->
- %% TimeService specification (july 1997, p14-7:2) states
- %% that they are only equal if both UTO's Inaccuracy
- %% equals zero.
- {reply, 'TCEqualTo', State};
- true ->
- {reply, 'TCIndeterminate', State}
- end;
- _ ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end;
-compare_time(_OE_THIS, State, 'MidC', Uto) ->
- ?time_TypeCheck(Uto, 'CosTime_UTO'),
- case catch 'CosTime_UTO':'_get_time'(Uto) of
- Time when is_integer(Time) ->
- if
- ?get_Time(State) < Time ->
- {reply, 'TCLessThan', State};
- ?get_Time(State) > Time ->
- {reply, 'TCGreaterThan', State};
- true ->
- {reply, 'TCEqualTo', State}
- end;
- _ ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end;
-compare_time(_OE_THIS, _State, _, _) ->
- %% Comparison_type given not correct?!
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : time_to_interval
-%% Arguments:
-%% Returns : TIO
-%%-----------------------------------------------------------
-time_to_interval(_OE_THIS, State, Uto) ->
- ?time_TypeCheck(Uto, 'CosTime_UTO'),
- case catch 'CosTime_UTO':'_get_time'(Uto) of
- Time when is_integer(Time) ->
- OwnTime = ?get_Time(State),
- if
- Time > OwnTime ->
- {reply, 'CosTime_TIO':oe_create([#'TimeBase_IntervalT'{lower_bound=OwnTime,
- upper_bound=Time},
- ?get_Tdf(State),
- ?get_TimeObj(State)],
- [{pseudo,true}|?CREATE_OPTS]), State};
- true ->
- {reply, 'CosTime_TIO':oe_create([#'TimeBase_IntervalT'{lower_bound=Time,
- upper_bound=OwnTime},
- ?get_Tdf(State),
- ?get_TimeObj(State)],
- [{pseudo,true}|?CREATE_OPTS]), State}
- end;
- _ ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------%
-%% function : interval
-%% Arguments:
-%% Returns : TIO
-%%-----------------------------------------------------------
-interval(_OE_THIS, State) ->
- Lower = ?get_Time(State) - ?get_Inaccuracy(State),
- Upper = ?get_Time(State) + ?get_Inaccuracy(State),
- {reply, 'CosTime_TIO':oe_create([#'TimeBase_IntervalT'{lower_bound=Lower,
- upper_bound=Upper},
- ?get_Tdf(State),
- ?get_TimeObj(State)],
- [{pseudo,true}|?CREATE_OPTS]), State}.
-
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-
-%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
-%%--------------- END OF MODULE ------------------------------
-
diff --git a/lib/cosTime/src/CosTimerEvent.cfg b/lib/cosTime/src/CosTimerEvent.cfg
deleted file mode 100644
index 7f16197168..0000000000
--- a/lib/cosTime/src/CosTimerEvent.cfg
+++ /dev/null
@@ -1,4 +0,0 @@
-{this, "CosTimerEvent::TimerEventHandler"}.
-{{handle_info, "CosTimerEvent::TimerEventHandler"}, true}.
-{this, "CosTimerEvent::TimerEventService"}.
-{{handle_info, "CosTimerEvent::TimerEventService"}, true}.
diff --git a/lib/cosTime/src/CosTimerEvent.idl b/lib/cosTime/src/CosTimerEvent.idl
deleted file mode 100644
index b845862f98..0000000000
--- a/lib/cosTime/src/CosTimerEvent.idl
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef _COS_TIMEREVENT_IDL_
-#define _COS_TIMEREVENT_IDL_
-
-#pragma prefix "omg.org"
-
-#include"CosEventComm.idl"
-#include<CosTime.idl>
-#include<TimeBase.idl>
-
-module CosTimerEvent{
-
- enum TimeType {
- TTAbsolute,
- TTRelative,
- TTPeriodic
- };
- enum EventStatus {
- ESTimeSet,
- ESTimeCleared,
- ESTriggered,
- ESFailedTrigger
- };
-
- struct TimerEventT {
- TimeBase::UtcT utc;
- any event_data;
- };
-
- interface TimerEventHandler {
- readonly attribute EventStatus status;
- boolean time_set( out CosTime::UTO uto );
- void set_timer( in TimeType time_type, in CosTime::UTO trigger_time );
- boolean cancel_timer();
- void set_data( in any event_data );
- };
-
- interface TimerEventService {
-
- TimerEventHandler register( in CosEventComm::PushConsumer event_interface, in any data );
- void unregister( in TimerEventHandler timer_event_handler );
- CosTime::UTO event_time( in TimerEventT timer_event );
- };
-};
-
-#endif
diff --git a/lib/cosTime/src/CosTimerEvent_TimerEventHandler_impl.erl b/lib/cosTime/src/CosTimerEvent_TimerEventHandler_impl.erl
deleted file mode 100644
index 5bc751dfb1..0000000000
--- a/lib/cosTime/src/CosTimerEvent_TimerEventHandler_impl.erl
+++ /dev/null
@@ -1,305 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosTimerEvent_TimerEventHandler_impl.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module('CosTimerEvent_TimerEventHandler_impl').
-
-%%--------------- INCLUDES -----------------------------------
--include("cosTimeApp.hrl").
-
-
-%%--------------- EXPORTS ------------------------------------
-%%--------------- External -----------------------------------
-%% Attributes (external)
--export(['_get_status'/2]).
-%% Interface functions
--export([time_set/2, set_timer/4]).
--export([cancel_timer/2, set_data/3]).
-
-%%--------------- gen_server specific exports ----------------
--export([handle_info/2, code_change/3]).
--export([init/1, terminate/2]).
-
-
-%% Data structures
--record(state, {parent,
- parentPid,
- event,
- status = 'ESTimeCleared',
- timer,
- time,
- timeObj,
- myType,
- pushConsumer,
- uto}).
-%% Data structures constructors
--define(get_InitState(P,PP,E,PC,TO),
- #state{parent=P,
- parentPid=PP,
- event=E,
- pushConsumer=PC,
- timeObj=TO}).
-
-%% Data structures selectors
--define(get_Status(S), S#state.status).
--define(get_ParentPid(S), S#state.parentPid).
--define(get_Parent(S), S#state.parent).
--define(get_Event(S), S#state.event).
--define(get_Timer(S), S#state.timer).
--define(get_Time(S), S#state.time).
--define(get_TimeObj(S), S#state.timeObj).
--define(get_MyType(S), S#state.myType).
--define(get_PushConsumer(S), S#state.pushConsumer).
--define(get_Uto(S), S#state.uto).
-
-%% Data structures modifiers
--define(set_Status(S,V), S#state{status=V}).
--define(set_ParentPid(S,PP), S#state{parentPid=PP}).
--define(set_Parent(S,P), S#state{parent=P}).
--define(set_Event(S,E), S#state{event=E}).
--define(set_Timer(S,T), S#state{timer=T}).
--define(set_Time(S,T), S#state{time=T}).
--define(set_MyType(S,Ty), S#state{myType=Ty}).
--define(set_PushConsumer(S,P), S#state{pushConsumer=P}).
--define(set_Uto(S,U,Type), S#state{uto=U, myType=Type}).
--define(set_TimeData(S,U,Ty,Ti),S#state{uto=U, myType=Ty, time=Ti}).
-
-%% MISC
--define(not_Cancelled(S), S#state.status =/= 'ESTimeCleared').
--define(is_TimeSet(S), S#state.status == 'ESTimeSet').
--define(is_UtoSet(S), S#state.uto =/= undefined).
--define(is_NotAbsolute(S), S#state.myType =/= 'TTAbsolute').
-
-%%-----------------------------------------------------------%
-%% function : handle_info, code_change
-%% Arguments:
-%% Returns :
-%% Effect : Functions demanded by the gen_server module.
-%%------------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-handle_info(Info, State) ->
- ?debug_print("INFO: ~p~n", [Info]),
- case Info of
- {'EXIT', Pid, _Reason} when Pid == ?get_ParentPid(State) ->
- ?debug_print("PARENT TERMINATED with reason: ~p~n",[_Reason]),
- {noreply, State};
- oe_event when ?not_Cancelled(State) ->
- %% Push event
- case catch 'CosEventComm_PushConsumer':push(?get_PushConsumer(State),
- ?get_Event(State)) of
- ok ->
- ?debug_print("PUSHED: ~p~n", [?get_Event(State)]),
- {noreply, ?set_Status(State, 'ESTriggered')};
- _Other->
- ?debug_print("FAILED PUSH: ~p ~p~n", [?get_Event(State), _Other]),
- {noreply, ?set_Status(State, 'ESFailedTrigger')}
- end;
- oe_periodic_event when ?not_Cancelled(State) ->
- %% Push event
- catch 'CosEventComm_PushConsumer':push(?get_PushConsumer(State),
- ?get_Event(State)),
- {noreply, State};
- _ ->
- {noreply, State}
- end.
-
-%%----------------------------------------------------------%
-%% function : init, terminate
-%% Arguments:
-%%-----------------------------------------------------------
-
-init([Parent, ParentPid, PushConsumer, Event, TimeObj]) ->
- process_flag(trap_exit, true),
- {ok, ?get_InitState(Parent, ParentPid, Event, PushConsumer, TimeObj)}.
-
-terminate(_Reason, State) ->
- clear_timer(State),
- ok.
-
-%%-----------------------------------------------------------
-%%------------------------ attributes -----------------------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% Attribute: '_get_status'
-%% Type : readonly
-%% Returns : 'ESTimeSet' | 'ESTimeCleared' | 'ESTriggered' |
-%% 'ESFailedTrigger'
-%%-----------------------------------------------------------
-'_get_status'(_OE_THIS, State) ->
- {reply, ?get_Status(State), State}.
-
-%%-----------------------------------------------------------
-%%------- Exported external functions -----------------------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% function : time_set
-%% Arguments: -
-%% Returns : {boolean(), CosTime::UTO}
-%%-----------------------------------------------------------
-time_set(_OE_THIS, State) when ?is_UtoSet(State) ->
- {reply, {?is_TimeSet(State), ?get_Uto(State)}, State};
-time_set(_OE_THIS, State) ->
- Utc = #'TimeBase_UtcT'{time=0, inacclo = 0,inacchi = 0, tdf = 0},
- {reply,
- {?is_TimeSet(State),
- 'CosTime_UTO':oe_create([Utc, ?get_TimeObj(State)], [{pseudo,true}|?CREATE_OPTS])},
- State}.
-
-
-%%-----------------------------------------------------------
-%% function : set_timer
-%% Arguments: TimeType - 'TTAbsolute' | 'TTRelative' | 'TTPeriodic'
-%% TriggerTime - CosTime::UTO
-%% Returns : ok
-%%-----------------------------------------------------------
-set_timer(_OE_THIS, State, 'TTAbsolute', TriggerTime) ->
- NewState = clear_timer(State),
- ?time_TypeCheck(TriggerTime, 'CosTime_UTO'),
- case catch {'CosTime_UTO':'_get_time'(TriggerTime),
- 'CosTime_UTO':'_get_time'(
- 'CosTime_TimeService':universal_time(?get_TimeObj(State)))} of
- {Time, CurrentTime} when is_integer(Time) andalso is_integer(CurrentTime) andalso
- Time > CurrentTime ->
- %% Set a timer to send a message in (Time-CurrentTime)*10^-7 secs.
- case timer:send_after(?convert_TimeT2TimerT(Time-CurrentTime), oe_event) of
- {ok, TRef} ->
- NewState1 = ?set_Timer(NewState, TRef),
- NewState2 = ?set_Uto(NewState1, TriggerTime, 'TTAbsolute'),
- ?debug_print("TIMER SET: ~p~n", [?convert_TimeT2TimerT(Time-CurrentTime)]),
- {reply, ok, ?set_Status(NewState2, 'ESTimeSet')};
- _->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
- {Time, CurrentTime} when is_integer(Time) andalso is_integer(CurrentTime) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO});
- _->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
-set_timer(_OE_THIS, State, 'TTRelative', TriggerTime) ->
- NewState = clear_timer(State),
- ?time_TypeCheck(TriggerTime, 'CosTime_UTO'),
- case catch {'CosTime_UTO':'_get_time'(TriggerTime), ?get_Time(State)} of
- {0,OldTime} when ?is_NotAbsolute(NewState) andalso is_integer(OldTime) ->
- %% Set a timer to send a message within Time*10^-7 secs
- case timer:send_after(OldTime, oe_event) of
- {ok, TRef} ->
- NewState1 = ?set_Timer(NewState, TRef),
- NewState2 = ?set_Uto(NewState1, TriggerTime, 'TTRelative'),
- ?debug_print("TIMER SET: ~p~n", [?convert_TimeT2TimerT(OldTime)]),
- {reply, ok, ?set_Status(NewState2, 'ESTimeSet')};
- _->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
- {UtoTime,_} when is_integer(UtoTime) ->
- %% Set a timer to send a message within Time*10^-7 secs
- Time = ?convert_TimeT2TimerT(UtoTime),
- case timer:send_after(Time, oe_event) of
- {ok, TRef} ->
- NewState1 = ?set_Timer(NewState, TRef),
- NewState2 = ?set_TimeData(NewState1, TriggerTime,
- 'TTRelative', Time),
- ?debug_print("TIMER SET: ~p~n", [?convert_TimeT2TimerT(Time)]),
- {reply, ok, ?set_Status(NewState2, 'ESTimeSet')};
- _->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
-
- _->
- {reply, {'EXCEPTION', #'BAD_PARAM'{completion_status=?COMPLETED_NO}}, NewState}
- end;
-set_timer(_OE_THIS, State, 'TTPeriodic', TriggerTime) ->
- NewState = clear_timer(State),
- ?time_TypeCheck(TriggerTime, 'CosTime_UTO'),
- case catch {'CosTime_UTO':'_get_time'(TriggerTime), ?get_Time(State)} of
- {0,OldTime} when ?is_NotAbsolute(NewState) andalso is_integer(OldTime) ->
- %% Set a timer to send a message within Time*10^-7 secs
- case timer:send_interval(OldTime, oe_periodic_event) of
- {ok, TRef} ->
- NewState1 = ?set_Timer(NewState, TRef),
- NewState2 = ?set_Uto(NewState1, TriggerTime, 'TTPeriodic'),
- ?debug_print("TIMER SET: ~p~n", [?convert_TimeT2TimerT(OldTime)]),
- {reply, ok, ?set_Status(NewState2, 'ESTimeSet')};
- _->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
- {UtoTime,_} when is_integer(UtoTime) ->
- %% Set a timer to send a message within Time*10^-7 secs
- Time = ?convert_TimeT2TimerT(UtoTime),
- case timer:send_interval(Time, oe_periodic_event) of
- {ok, TRef} ->
- NewState1 = ?set_Timer(NewState, TRef),
- NewState2 = ?set_TimeData(NewState1, TriggerTime,
- 'TTPeriodic', Time),
- ?debug_print("TIMER SET: ~p~n", [?convert_TimeT2TimerT(Time)]),
- {reply, ok, ?set_Status(NewState2, 'ESTimeSet')};
- _->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
-
- _->
- {reply, {'EXCEPTION', #'BAD_PARAM'{completion_status=?COMPLETED_NO}}, NewState}
- end;
-set_timer(_OE_THIS, _State, _, _) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------%
-%% function : cancel_timer
-%% Arguments: -
-%% Returns : boolean()
-%%-----------------------------------------------------------
-cancel_timer(_OE_THIS, State) ->
- NewState=clear_timer(State),
- case ?get_Status(NewState) of
- 'ESTriggered' ->
- {reply, false, NewState};
- 'ESFailedTrigger' ->
- {reply, false, NewState};
- _ ->
- {reply, true, ?set_Status(NewState, 'ESTimeCleared')}
- end.
-
-%%----------------------------------------------------------%
-%% function : set_data
-%% Arguments: EventData - any#
-%% Returns : ok
-%%-----------------------------------------------------------
-set_data(_OE_THIS, State, EventData) when is_record(EventData, any) ->
- {reply, ok, ?set_Event(State, EventData)};
-set_data(_OE_THIS, _State, _EventData) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-clear_timer(State) when ?get_Timer(State) == undefined ->
- State;
-clear_timer(State) ->
- catch timer:cancel(?get_Timer(State)),
- ?set_Timer(State, undefined).
-
-%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosTime/src/CosTimerEvent_TimerEventService_impl.erl b/lib/cosTime/src/CosTimerEvent_TimerEventService_impl.erl
deleted file mode 100644
index 59552e4b1b..0000000000
--- a/lib/cosTime/src/CosTimerEvent_TimerEventService_impl.erl
+++ /dev/null
@@ -1,119 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosTimerEvent_TimerEventService_impl.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module('CosTimerEvent_TimerEventService_impl').
-
-%%--------------- INCLUDES -----------------------------------
--include("cosTimeApp.hrl").
-
-
-%%--------------- EXPORTS ------------------------------------
-%%--------------- External -----------------------------------
-%% Interface functions
--export([register/4, unregister/3, event_time/3]).
-
-%%--------------- gen_server specific exports ----------------
--export([handle_info/2, code_change/3]).
--export([init/1, terminate/2]).
-
-
-%% Data structures
--record(state, {timer}).
-%% Data structures constructors
--define(get_InitState(T),
- #state{timer=T}).
-
-%% Data structures selectors
--define(get_TimerObj(S), S#state.timer).
-
-%% Data structures modifiers
-
-%% MISC
-
-%%-----------------------------------------------------------%
-%% function : handle_info, code_change
-%% Arguments:
-%% Returns :
-%% Effect : Functions demanded by the gen_server module.
-%%------------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-handle_info(_Info, State) ->
- ?debug_print("INFO: ~p~n", [_Info]),
- {noreply, State}.
-
-%%----------------------------------------------------------%
-%% function : init, terminate
-%% Arguments:
-%%-----------------------------------------------------------
-
-init([Timer]) ->
- process_flag(trap_exit, true),
- timer:start(),
- {ok, ?get_InitState(Timer)}.
-
-terminate(_Reason, _State) ->
- ok.
-
-%%-----------------------------------------------------------
-%%------- Exported external functions -----------------------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% function : register
-%% Arguments: EventInterface - CosEventComm::PushConsumer
-%% Data - #any
-%% Returns : TimerEventHandler - objref#
-%%-----------------------------------------------------------
-register(OE_THIS, State, EventInterface, Data) ->
- {reply,
- cosTime:start_event_handler([OE_THIS, self(),EventInterface, Data,
- ?get_TimerObj(State)]),
- State}.
-
-%%----------------------------------------------------------%
-%% function : unregister
-%% Arguments: TimerEventHandler - objref#
-%% Returns : ok
-%%-----------------------------------------------------------
-unregister(_OE_THIS, State, TimerEventHandler) ->
- catch corba:dispose(TimerEventHandler),
- {reply, ok, State}.
-
-%%----------------------------------------------------------%
-%% function : event_time
-%% Arguments: TimerEvent - #'CosTimerEvent_TimerEventT'{utc, event_data}
-%% Returns : CosTime::UTO
-%%-----------------------------------------------------------
-event_time(_OE_THIS, State, #'CosTimerEvent_TimerEventT'{utc=Utc}) ->
- {reply, 'CosTime_UTO':oe_create([Utc],[{pseudo,true}]), State}.
-
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-
-%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosTime/src/Makefile b/lib/cosTime/src/Makefile
deleted file mode 100644
index 55d59baea3..0000000000
--- a/lib/cosTime/src/Makefile
+++ /dev/null
@@ -1,207 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-
-ifeq ($(TYPE),debug)
-ERL_COMPILE_FLAGS += -Ddebug -W
-endif
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(COSTIME_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/cosTime-$(VSN)
-
-EXTERNAL_INC_PATH = ../include
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES = \
- cosTime \
- CosTime_TIO_impl \
- CosTime_TimeService_impl \
- CosTime_UTO_impl \
- CosTimerEvent_TimerEventHandler_impl \
- CosTimerEvent_TimerEventService_impl \
-
-ERL_FILES = $(MODULES:%=%.erl)
-HRL_FILES = \
- cosTimeApp.hrl \
-
-GEN_TIMEBASE_ERL_FILES = \
- oe_TimeBase.erl \
- TimeBase_IntervalT.erl \
- TimeBase_UtcT.erl
-
-GEN_COSTIME_ERL_FILES = \
- oe_CosTime.erl \
- CosTime_TIO.erl \
- CosTime_TimeService.erl \
- CosTime_TimeUnavailable.erl \
- CosTime_UTO.erl \
-
-GEN_COSTIMEREVENT_ERL_FILES = \
- oe_CosTimerEvent.erl \
- CosTimerEvent_TimerEventHandler.erl \
- CosTimerEvent_TimerEventService.erl \
- CosTimerEvent_TimerEventT.erl \
-
-GEN_TIMEBASE_HRL_FILES = \
- oe_TimeBase.hrl \
- TimeBase.hrl \
-
-EXTERNAL_TIMEBASE_HRL_FILES = $(GEN_TIMEBASE_HRL_FILES:%=$(EXTERNAL_INC_PATH)/%)
-
-GEN_COSTIME_HRL_FILES = \
- oe_CosTime.hrl \
- CosTime.hrl \
- CosTime_TIO.hrl \
- CosTime_TimeService.hrl \
- CosTime_UTO.hrl
-
-EXTERNAL_COSTIME_HRL_FILES = $(GEN_COSTIME_HRL_FILES:%=$(EXTERNAL_INC_PATH)/%)
-
-GEN_COSTIMEREVENT_HRL_FILES = \
- oe_CosTimerEvent.hrl \
- CosTimerEvent.hrl \
- CosTimerEvent_TimerEventHandler.hrl \
- CosTimerEvent_TimerEventService.hrl \
-
-EXTERNAL_COSTIMEREVENT_HRL_FILES = $(GEN_COSTIMEREVENT_HRL_FILES:%=$(EXTERNAL_INC_PATH)/%)
-
-
-GEN_ERL_FILES = \
- $(GEN_TIMEBASE_ERL_FILES) \
- $(GEN_COSTIME_ERL_FILES) \
- $(GEN_COSTIMEREVENT_ERL_FILES)
-
-GEN_HRL_FILES = \
- $(EXTERNAL_TIMEBASE_HRL_FILES) \
- $(EXTERNAL_COSTIME_HRL_FILES) \
- $(EXTERNAL_COSTIMEREVENT_HRL_FILES) \
-
-GEN_FILES = \
- $(GEN_HRL_FILES) \
- $(GEN_ERL_FILES)
-
-TARGET_FILES = \
- $(GEN_TIMEBASE_ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR)) \
- $(GEN_COSTIME_ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR)) \
- $(GEN_COSTIMEREVENT_ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR)) \
- $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-IDL_FILES = \
- TimeBase.idl \
- CosTime.idl \
- CosTimerEvent.idl
-
-APPUP_FILE = cosTime.appup
-APPUP_SRC = $(APPUP_FILE).src
-APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
-
-APP_FILE = cosTime.app
-APP_SRC = $(APP_FILE).src
-APP_TARGET = $(EBIN)/$(APP_FILE)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/cosTime/ebin \
- -pa $(ERL_TOP)/lib/ic/ebin\
- -pa $(ERL_TOP)/lib/orber/ebin \
- -I$(ERL_TOP)/lib/cosEvent/src
-
-# The -pa option is just used temporary until erlc can handle
-# includes from other directories than ../include .
-ERL_COMPILE_FLAGS += \
- $(ERL_IDL_FLAGS) \
- -pa $(ERL_TOP)/lib/orber/include \
- -pa $(ERL_TOP)/lib/cosTime/include \
- -I$(ERL_TOP)/lib/cosTime/include \
- -I$(ERL_TOP)/lib/orber/include \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,app_vsn,"cosTime_$(COSTIME_VSN)"}'
-
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
-
-debug:
- @${MAKE} TYPE=debug opt
-
-cleanb:
- rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
- rm -f errs core *~
-
-clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
- rm -f errs core *~
-
-$(APP_TARGET): $(APP_SRC)
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
-
-$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
-
-docs:
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-IDL-GENERATED: TimeBase.idl CosTime.idl CosTimerEvent.idl
- $(gen_verbose)erlc $(ERL_IDL_FLAGS) TimeBase.idl
- $(V_at)mv $(GEN_TIMEBASE_HRL_FILES) $(EXTERNAL_INC_PATH)
- $(V_at)erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosTime.cfg"}' CosTime.idl
- $(V_at)mv $(GEN_COSTIME_HRL_FILES) $(EXTERNAL_INC_PATH)
- $(V_at)erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosTimerEvent.cfg"}' CosTimerEvent.idl
- $(V_at)mv $(GEN_COSTIMEREVENT_HRL_FILES) $(EXTERNAL_INC_PATH)
- $(V_at)>IDL-GENERATED
-
-$(GEN_FILES): IDL-GENERATED
-
-$(TARGET_FILES): IDL-GENERATED
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
- $(INSTALL_DIR) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(GEN_FILES) $(IDL_FILES) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILES) "$(RELSYSDIR)/src"
- $(INSTALL_DIR) "$(RELSYSDIR)/include"
- $(INSTALL_DATA) $(GEN_HRL_FILES) "$(RELSYSDIR)/include"
-
-release_docs_spec:
diff --git a/lib/cosTime/src/TimeBase.idl b/lib/cosTime/src/TimeBase.idl
deleted file mode 100644
index 92a0c652d8..0000000000
--- a/lib/cosTime/src/TimeBase.idl
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef _TIMEBASE_IDL_
-#define _TIMEBASE_IDL_
-
-#pragma prefix "omg.org"
-
-module TimeBase {
- typedef unsigned long long TimeT;
- typedef TimeT InaccuracyT;
- typedef short TdfT;
- struct UtcT {
- TimeT time; // 8 octets
- unsigned long inacclo; // 4 octets
- unsigned short inacchi; // 2 octets
- TdfT tdf; // 2 octets // total 16 octets.
- };
- struct IntervalT {
- TimeT lower_bound;
- TimeT upper_bound;
- };
-};
-
-#endif
diff --git a/lib/cosTime/src/cosTime.app.src b/lib/cosTime/src/cosTime.app.src
deleted file mode 100644
index ac71fe1b29..0000000000
--- a/lib/cosTime/src/cosTime.app.src
+++ /dev/null
@@ -1,32 +0,0 @@
-{application, cosTime,
- [{description, "The Erlang CosTime application"},
- {vsn, "%VSN%"},
- {modules,
- [
- 'cosTime',
- 'oe_TimeBase',
- 'oe_CosTime',
- 'oe_CosTimerEvent',
- 'CosTime_TIO',
- 'CosTime_TimeService',
- 'CosTime_TimeUnavailable',
- 'CosTime_UTO',
- 'CosTimerEvent_TimerEventHandler',
- 'CosTimerEvent_TimerEventService',
- 'CosTimerEvent_TimerEventT',
- 'TimeBase_IntervalT',
- 'TimeBase_UtcT',
- 'CosTime_TIO_impl',
- 'CosTime_TimeService_impl',
- 'CosTime_UTO_impl',
- 'CosTimerEvent_TimerEventHandler_impl',
- 'CosTimerEvent_TimerEventService_impl'
- ]
- },
- {registered, [oe_cosTimeSup, oe_cosTimerEventService]},
- {applications, [orber, stdlib, kernel]},
- {env, []},
- {mod, {cosTime, []}},
- {runtime_dependencies, ["stdlib-2.0","orber-3.6.27","kernel-3.0","erts-7.0",
- "cosEvent-2.1.15"]}
-]}.
diff --git a/lib/cosTime/src/cosTime.appup.src b/lib/cosTime/src/cosTime.appup.src
deleted file mode 100644
index f3eead4a0c..0000000000
--- a/lib/cosTime/src/cosTime.appup.src
+++ /dev/null
@@ -1,6 +0,0 @@
-{"%VSN%",
- [
- ],
- [
- ]
-}.
diff --git a/lib/cosTime/src/cosTime.erl b/lib/cosTime/src/cosTime.erl
deleted file mode 100644
index a32e210a26..0000000000
--- a/lib/cosTime/src/cosTime.erl
+++ /dev/null
@@ -1,343 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : cosTime.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module(cosTime).
-
-%%--------------- INCLUDES -----------------------------------
--include("cosTimeApp.hrl").
-
-%%--------------- EXPORTS-------------------------------------
-%% cosTime API external
--export([start/0, stop/0,
- install_time/0, uninstall_time/0,
- install_timerevent/0, uninstall_timerevent/0,
- start_time_service/2, start_timerevent_service/1, stop_timerevent_service/1,
- stop_time_service/1]).
-
-%% cosTime API internal
--export([create_link/3, get_option/3, type_check/2, start_event_handler/1]).
-
-%% Application callbacks
--export([start/2, init/1, stop/1]).
-
-%%--------------- DEFINES ------------------------------------
--define(IDL_TIME_MODULES, ['oe_TimeBase',
- 'oe_CosTime']).
--define(IDL_TIMEREVENT_MODULES, ['oe_CosTimerEvent']).
--define(SUPERVISOR_NAME, oe_cosTimeSup).
--define(SUP_FLAG, {simple_one_for_one,50,10}).
--define(SUP_TIMESERVICE_SPEC(T,I),
- ['CosTime_TimeService',[T, I],
- [{sup_child, true}, {regname, {global, "oe_cosTimeService"}}]]).
--define(SUP_TIMEREVENTSERVICE_SPEC(Args),
- ['CosTimerEvent_TimerEventService', Args,
- [{sup_child, true}, {regname, {local, 'oe_cosTimerEventService'}}]]).
--define(SUP_TIMEREVENTHANDLER_SPEC(Name, Args),
- ['CosTimerEvent_TimerEventHandler',Args,
- [{sup_child, true}, {regname, {global, Name}}]]).
--define(SUP_CHILD,
- {"oe_TimeChild",
- {cosTime,create_link, []},
- transient,100000,worker,
- []}).
-
-%%------------------------------------------------------------
-%% function : install_*/X
-%% Arguments: - | Time (seconds)
-%% Returns : ok | EXIT | EXCEPTION
-%% Effect : Install necessary data in the IFR DB
-%%------------------------------------------------------------
-
-install_time() ->
- case install_loop(?IDL_TIME_MODULES,[]) of
- ok ->
- ok;
- {error, Reason} ->
- exit(Reason)
- end.
-
-install_timerevent() ->
- case install_loop(?IDL_TIMEREVENT_MODULES,[]) of
- ok ->
- ok;
- {error, Reason} ->
- exit(Reason)
- end.
-
-install_loop([], _) ->
- ok;
-install_loop([H|T], Accum) ->
- case catch H:'oe_register'() of
- {'EXIT',{unregistered,App}} ->
- ?write_ErrorMsg("Unable to register '~p'; application ~p not registered.\n"
- "Trying to unregister ~p\n", [H,App,Accum]),
- uninstall_loop(Accum, {exit, register});
- {'EXCEPTION',_} ->
- ?write_ErrorMsg("Unable to register '~p'; propably already registered.\n"
- "You are adviced to confirm this.\n"
- "Trying to unregister ~p\n", [H,Accum]),
- uninstall_loop(Accum, {exit, register});
- ok ->
- install_loop(T, [H|Accum]);
- _ ->
- ?write_ErrorMsg("Unable to register '~p'; reason unknown.\n"
- "Trying to unregister ~p\n", [H,Accum]),
- uninstall_loop(Accum, {exit, register})
- end.
-
-%%------------------------------------------------------------
-%% function : uninstall_*/X
-%% Arguments: - | Time (seconds)
-%% Returns : ok | EXIT | EXCEPTION
-%% Effect : Remove data related to cosTime from the IFR DB
-%%------------------------------------------------------------
-
-uninstall_time() ->
- case uninstall_loop(lists:reverse(?IDL_TIME_MODULES),ok) of
- ok ->
- ok;
- {error, Reason} ->
- exit(Reason)
- end.
-
-uninstall_timerevent() ->
- case uninstall_loop(lists:reverse(?IDL_TIMEREVENT_MODULES),ok) of
- ok ->
- ok;
- {error, Reason} ->
- exit(Reason)
- end.
-
-uninstall_loop([],ok) ->
- ok;
-uninstall_loop([],{exit, register}) ->
- {error, {?MODULE, "oe_register failed"}};
-uninstall_loop([],{exit, unregister}) ->
- {error, {?MODULE, "oe_unregister failed"}};
-uninstall_loop([],{exit, both}) ->
- {error, {?MODULE, "oe_register and, for some of those already registered, oe_unregister failed"}};
-uninstall_loop([H|T], Status) ->
- case catch H:'oe_unregister'() of
- ok ->
- uninstall_loop(T, Status);
- _ when Status == ok ->
- ?write_ErrorMsg("Unable to unregister '~p'; propably already unregistered.\n"
- "You are adviced to confirm this.~n",[H]),
- uninstall_loop(T, {exit, unregister});
- _ ->
- ?write_ErrorMsg("Unable to unregister '~p'; propably already unregistered.\n"
- "You are adviced to confirm this.~n",[H]),
- uninstall_loop(T, {exit, both})
- end.
-
-%%------------------------------------------------------------
-%% function : start/stop
-%% Arguments:
-%% Returns :
-%% Effect : Starts or stops the cosTime application.
-%%------------------------------------------------------------
-
-start() ->
- application:start(cosTime).
-stop() ->
- application:stop(cosTime).
-
-%%------------------------------------------------------------
-%% function : start
-%% Arguments: Type - see module application
-%% Arg - see module application
-%% Returns :
-%% Effect : Module callback for application
-%%------------------------------------------------------------
-
-start(_, _) ->
- supervisor:start_link({local, ?SUPERVISOR_NAME}, cosTime, app_init).
-
-
-%%------------------------------------------------------------
-%% function : stop
-%% Arguments: Arg - see module application
-%% Returns :
-%% Effect : Module callback for application
-%%------------------------------------------------------------
-
-stop(_) ->
- ok.
-
-%%------------------------------------------------------------
-%% function : start_time_service
-%% Arguments: Tdf - time difference to UTC
-%% Inaccuracy - ulonglong
-%% Upper - inaccuracy high
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-start_time_service(Tdf, Inaccuracy) when is_integer(Tdf) andalso is_integer(Inaccuracy) ->
- case supervisor:start_child(?SUPERVISOR_NAME,
- ?SUP_TIMESERVICE_SPEC(Tdf, Inaccuracy)) of
- {ok, Pid, Obj} when is_pid(Pid) ->
- Obj;
- _Other->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
-start_time_service(_Tdf, _Inaccuracy) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-
-%%------------------------------------------------------------
-%% function : stop_time_service
-%% Arguments: Obj - TimeService objref
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-stop_time_service(Obj) ->
- corba:dispose(Obj).
-
-%%------------------------------------------------------------
-%% function : start_timerevent_service
-%% Arguments: Timer - Timer Service Reference
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-start_timerevent_service(Timer) ->
- case supervisor:start_child(?SUPERVISOR_NAME,
- ?SUP_TIMEREVENTSERVICE_SPEC([Timer])) of
- {ok, Pid, Obj} when is_pid(Pid) ->
- Obj;
- _Other->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%-----------------------------------------------------------%
-%% function : stop_timerevent_service
-%% Arguments: Obj - TimerEventService objref
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-stop_timerevent_service(Obj) ->
- corba:dispose(Obj).
-
-%%-----------------------------------------------------------%
-%% function : init
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-
-%% Starting using create_factory/X
-init(own_init) ->
- {ok,{?SUP_FLAG, [?SUP_CHILD]}};
-%% When starting as an application.
-init(app_init) ->
- {ok,{?SUP_FLAG, [?SUP_CHILD]}}.
-
-%%-----------------------------------------------------------%
-%% function : create_link
-%% Arguments: Module - which Module to call
-%% Env/ArgList - ordinary oe_create arguments.
-%% Returns :
-%% Exception:
-%% Effect : Necessary since we want the supervisor to be a
-%% 'simple_one_for_one'. Otherwise, using for example,
-%% 'one_for_one', we have to call supervisor:delete_child
-%% to remove the childs startspecification from the
-%% supervisors internal state.
-%%------------------------------------------------------------
-create_link(Module, Env, ArgList) ->
- Module:oe_create_link(Env, ArgList).
-
-%%-----------------------------------------------------------%
-%% function : start_event_handler
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-
-start_event_handler(Args) ->
- Name = create_name(eventhandler),
- case supervisor:start_child(?SUPERVISOR_NAME, ?SUP_TIMEREVENTHANDLER_SPEC(Name,Args)) of
- {ok, Pid, Obj} when is_pid(Pid) ->
- Obj;
- _Other->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-
-%%-----------------------------------------------------------%
-%% function : get_option
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-
-get_option(Key, OptionList, DefaultList) ->
- case lists:keysearch(Key, 1, OptionList) of
- {value,{Key,Value}} ->
- Value;
- _ ->
- case lists:keysearch(Key, 1, DefaultList) of
- {value,{Key,Value}} ->
- Value;
- _->
- {error, "Invalid option"}
- end
- end.
-
-%%-----------------------------------------------------------%
-%% function : type_check
-%% Arguments: Obj - objectrefernce to test.
-%% Mod - Module which contains typeID/0.
-%% Returns : 'ok' or raises exception.
-%% Effect :
-%%------------------------------------------------------------
-
-type_check(Obj, Mod) ->
- case catch corba_object:is_a(Obj,Mod:typeID()) of
- true ->
- ok;
- _ ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end.
-
-
-%%-----------------------------------------------------------%
-%% function : create_name/1
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-
-create_name(Type) ->
- Time = erlang:system_time(),
- Unique = erlang:unique_integer([positive]),
- lists:concat(['oe_',node(),'_',Type,'_',Time,'_',Unique]).
-
-%%--------------- END OF MODULE ------------------------------
-
-
diff --git a/lib/cosTime/src/cosTimeApp.hrl b/lib/cosTime/src/cosTimeApp.hrl
deleted file mode 100644
index 7c084dc585..0000000000
--- a/lib/cosTime/src/cosTimeApp.hrl
+++ /dev/null
@@ -1,77 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : cosTimeApp.hrl
-%% Purpose :
-%%----------------------------------------------------------------------
-
-
-%%--------------- INCLUDES -----------------------------------
-%% External
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-
-%% Local
--include("CosTimerEvent.hrl").
--include("CosTime.hrl").
--include("CosTimerEvent.hrl").
--include("TimeBase.hrl").
-
--define(CREATE_OPTS, [{no_security, orber:partial_security()}]).
-
--define(max_Inaccuracy, 281474976710655).
--define(max_TimeT, 18446744073709551616).
-
-%% The calendar module uses year 0 as base for gregorian functions.
-%% 'ABSOULTE_TIME_DIFF' is #seconds from year 0 until 15 october 1582, 00:00.
--define(ABSOLUTE_TIME_DIFF, 49947926400).
-%% As above but diff year 0 to 00:00 GMT, January 1, 1970
--define(STANDARD_TIME_DIFF, 62167219200).
-
--define(split_TimeT(T), {((T band 16#0000ffff00000000) bsr 32),
- (T band 16#00000000ffffffff)}).
-
--define(high_TimeT(T), ((T band 16#0000ffff00000000) bsr 32)).
--define(low_TimeT(T), (T band 16#00000000ffffffff)).
-
--define(concat_TimeT(H,L), ((H bsl 32) + L)).
-
--define(convert_TimeT2TimerT(N), erlang:trunc(N*1.0e-4)).
-
--define(write_ErrorMsg(Txt, Arg),
-error_logger:error_msg("================ CosTime ==================~n"
- Txt
- "===========================================~n",
- Arg)).
-
-
-
--ifdef(debug).
--define(debug_print(F,A),
- io:format("[LINE: ~p MODULE: ~p] "++F,[?LINE, ?MODULE]++A)).
--define(time_TypeCheck(O,M), 'cosTime':type_check(O,M)).
--else.
--define(debug_print(F,A), ok).
--define(time_TypeCheck(O,I), ok).
--endif.
-
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosTime/test/Makefile b/lib/cosTime/test/Makefile
deleted file mode 100644
index 91d3eccf43..0000000000
--- a/lib/cosTime/test/Makefile
+++ /dev/null
@@ -1,135 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(COSTIME_VSN)
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/cosTime_test
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-TEST_SPEC_FILE = cosTime.spec
-COVER_FILE = cosTime.cover
-
-
-IDL_FILES =
-
-IDLOUTDIR = idl_output
-
-MODULES = \
- time_SUITE \
- generated_SUITE
-
-GEN_MODULES = \
-
-GEN_HRL_FILES = \
-
-ERL_FILES = $(MODULES:%=%.erl)
-
-HRL_FILES =
-
-GEN_FILES = \
- $(GEN_HRL_FILES:%=$(IDLOUTDIR)/%) \
- $(GEN_MODULES:%=$(IDLOUTDIR)/%.erl)
-
-GEN_TARGET_FILES = $(GEN_MODULES:%=$(IDLOUTDIR)/%.$(EMULATOR))
-
-SUITE_TARGET_FILES = $(MODULES:%=%.$(EMULATOR))
-
-TARGET_FILES = \
- $(GEN_TARGET_FILES) \
- $(SUITE_TARGET_FILES)
-
-
-# ----------------------------------------------------
-# PROGRAMS
-# ----------------------------------------------------
-LOCAL_CLASSPATH = $(ERL_TOP)lib/cosTime/priv:$(ERL_TOP)lib/cosTime/test
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/cosTime/ebin \
- -pa $(ERL_TOP)/lib/cosTime/src \
- -pa $(ERL_TOP)/lib/cosTime/include \
- -pa $(ERL_TOP)/lib/cosNotification/ebin \
- -pa $(ERL_TOP)/lib/orber/ebin \
- -pa $(ERL_TOP)/lib/ic/ebin
-
-ERL_COMPILE_FLAGS += \
- $(ERL_IDL_FLAGS) \
- -pa $(ERL_TOP)/lib/orber/include \
- -pa $(ERL_TOP)/lib/cosNotification/include \
- -pa $(ERL_TOP)/lib/cosTime/ebin \
- -pa $(ERL_TOP)/lib/cosTime/include \
- -pa $(ERL_TOP)/lib/cosTime/test/idl_output \
- -I$(ERL_TOP)/lib/orber/include \
- -I$(ERL_TOP)/lib/cosNotification/include \
- -I$(ERL_TOP)/lib/cosTime/src \
- -I$(ERL_TOP)/lib/cosTime/include \
- -I$(ERL_TOP)/lib/cosTime \
- -I$(ERL_TOP)/lib/cosTime/test/$(IDLOUTDIR)
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-
-tests debug opt: $(TARGET_FILES)
-
-clean:
- rm -f idl_output/*
- rm -f $(TARGET_FILES)
- rm -f errs core *~
-
-docs:
-
-# ----------------------------------------------------
-# Special Targets
-# ----------------------------------------------------
-
-# ----------------------------------------------------
-# Release Targets
-# ----------------------------------------------------
-# We don't copy generated intermediate erlang and hrl files
-
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec:
-
-release_docs_spec:
-
-release_tests_spec: tests
- $(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) \
- $(COVER_FILE) $(ERL_FILES) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(SUITE_TARGET_FILES) "$(RELSYSDIR)"
-# $(INSTALL_DIR) "$(RELSYSDIR)/$(IDLOUTDIR)"
-# $(INSTALL_DATA) $(GEN_TARGET_FILES) $(GEN_FILES) \
-# "$(RELSYSDIR)/$(IDLOUTDIR)"
-
diff --git a/lib/cosTime/test/cosTime.cover b/lib/cosTime/test/cosTime.cover
deleted file mode 100644
index 81a05b8cfd..0000000000
--- a/lib/cosTime/test/cosTime.cover
+++ /dev/null
@@ -1,2 +0,0 @@
-{incl_app,cosTime,details}.
-
diff --git a/lib/cosTime/test/cosTime.spec b/lib/cosTime/test/cosTime.spec
deleted file mode 100644
index 8bf6f740fe..0000000000
--- a/lib/cosTime/test/cosTime.spec
+++ /dev/null
@@ -1 +0,0 @@
-{suites,"../cosTime_test",all}.
diff --git a/lib/cosTime/test/generated_SUITE.erl b/lib/cosTime/test/generated_SUITE.erl
deleted file mode 100644
index b030155340..0000000000
--- a/lib/cosTime/test/generated_SUITE.erl
+++ /dev/null
@@ -1,289 +0,0 @@
-%%-----------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File : generated_SUITE.erl
-%% Purpose :
-%%-----------------------------------------------------------------
-
--module(generated_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
-
--define(default_timeout, test_server:minutes(3)).
-
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
--define(nomatch(Not, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- Not ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS);
- _ ->
- AcTuAlReS
- end
- end()).
-
-
--define(checktc(_Op),
- fun(TC) ->
- case orber_tc:check_tc(TC) of
- false ->
- io:format("###### ERROR ERROR ######~n~p - ~p~n", [Op, TC]),
- exit(TC);
- true ->
- true
- end
- end).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- ['TimeBase_IntervalT', 'TimeBase_UtcT',
- 'CosTime_TimeUnavailable', 'CosTimerEvent_TimerEventT',
- 'CosTime_TIO', 'CosTime_TimeService', 'CosTime_UTO',
- 'CosTimerEvent_TimerEventHandler',
- 'CosTimerEvent_TimerEventService'].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'TimeBase_IntervalT'
-%% Description:
-%%-----------------------------------------------------------------
-'TimeBase_IntervalT'(_) ->
- ?match(true, orber_tc:check_tc('TimeBase_IntervalT':tc())),
- ?match("IDL:omg.org/TimeBase/IntervalT:1.0",
- 'TimeBase_IntervalT':id()),
- ?match("TimeBase_IntervalT",
- 'TimeBase_IntervalT':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'TimeBase_UtcT'
-%% Description:
-%%-----------------------------------------------------------------
-'TimeBase_UtcT'(_) ->
- ?match(true, orber_tc:check_tc('TimeBase_UtcT':tc())),
- ?match("IDL:omg.org/TimeBase/UtcT:1.0",
- 'TimeBase_UtcT':id()),
- ?match("TimeBase_UtcT",
- 'TimeBase_UtcT':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTime_TimeUnavailable'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTime_TimeUnavailable'(_) ->
- ?match(true, orber_tc:check_tc('CosTime_TimeUnavailable':tc())),
- ?match("IDL:omg.org/CosTime/TimeUnavailable:1.0",
- 'CosTime_TimeUnavailable':id()),
- ?match("CosTime_TimeUnavailable",
- 'CosTime_TimeUnavailable':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTimerEvent_TimerEventT'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTimerEvent_TimerEventT'(_) ->
- ?match(true, orber_tc:check_tc('CosTimerEvent_TimerEventT':tc())),
- ?match("IDL:omg.org/CosTimerEvent/TimerEventT:1.0",
- 'CosTimerEvent_TimerEventT':id()),
- ?match("CosTimerEvent_TimerEventT",
- 'CosTimerEvent_TimerEventT':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTime_TIO'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTime_TIO'(_) ->
- ?nomatch(undefined, 'CosTime_TIO':oe_tc('_get_time_interval')),
- ?nomatch(undefined, 'CosTime_TIO':oe_tc(spans)),
- ?nomatch(undefined, 'CosTime_TIO':oe_tc(overlaps)),
- ?nomatch(undefined, 'CosTime_TIO':oe_tc(time)),
- ?match(undefined, 'CosTime_TIO':oe_tc(undefined)),
- ?match([_|_], 'CosTime_TIO':oe_get_interface()),
- ?match("IDL:omg.org/CosTime/TIO:1.0", 'CosTime_TIO':typeID()),
- check_tc('CosTime_TIO':oe_get_interface()),
- ?match(true, 'CosTime_TIO':oe_is_a('CosTime_TIO':typeID())),
- ?match(false, 'CosTime_TIO':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTime_TimeService'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTime_TimeService'(_) ->
- ?nomatch(undefined, 'CosTime_TimeService':oe_tc(universal_time)),
- ?nomatch(undefined, 'CosTime_TimeService':oe_tc(secure_universal_time)),
- ?nomatch(undefined, 'CosTime_TimeService':oe_tc(new_universal_time)),
- ?nomatch(undefined, 'CosTime_TimeService':oe_tc(uto_from_utc)),
- ?nomatch(undefined, 'CosTime_TimeService':oe_tc(new_interval)),
- ?match(undefined, 'CosTime_TimeService':oe_tc(undefined)),
- ?match([_|_], 'CosTime_TimeService':oe_get_interface()),
- ?match("IDL:omg.org/CosTime/TimeService:1.0",
- 'CosTime_TimeService':typeID()),
- check_tc('CosTime_TimeService':oe_get_interface()),
- ?match(true, 'CosTime_TimeService':oe_is_a('CosTime_TimeService':typeID())),
- ?match(false, 'CosTime_TimeService':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTime_UTO'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTime_UTO'(_) ->
- ?nomatch(undefined, 'CosTime_UTO':oe_tc('_get_time')),
- ?nomatch(undefined, 'CosTime_UTO':oe_tc('_get_inaccuracy')),
- ?nomatch(undefined, 'CosTime_UTO':oe_tc('_get_tdf')),
- ?nomatch(undefined, 'CosTime_UTO':oe_tc('_get_utc_time')),
- ?nomatch(undefined, 'CosTime_UTO':oe_tc(absolute_time)),
- ?nomatch(undefined, 'CosTime_UTO':oe_tc(compare_time)),
- ?nomatch(undefined, 'CosTime_UTO':oe_tc(time_to_interval)),
- ?nomatch(undefined, 'CosTime_UTO':oe_tc(interval)),
- ?match(undefined, 'CosTime_UTO':oe_tc(undefined)),
- ?match([_|_], 'CosTime_UTO':oe_get_interface()),
- ?match("IDL:omg.org/CosTime/UTO:1.0", 'CosTime_UTO':typeID()),
- check_tc('CosTime_UTO':oe_get_interface()),
- ?match(true, 'CosTime_UTO':oe_is_a('CosTime_UTO':typeID())),
- ?match(false, 'CosTime_UTO':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTimerEvent_TimerEventHandler'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTimerEvent_TimerEventHandler'(_) ->
- ?nomatch(undefined, 'CosTimerEvent_TimerEventHandler':oe_tc('_get_status')),
- ?nomatch(undefined, 'CosTimerEvent_TimerEventHandler':oe_tc(time_set)),
- ?nomatch(undefined, 'CosTimerEvent_TimerEventHandler':oe_tc(set_timer)),
- ?nomatch(undefined, 'CosTimerEvent_TimerEventHandler':oe_tc(cancel_timer)),
- ?nomatch(undefined, 'CosTimerEvent_TimerEventHandler':oe_tc(set_data)),
- ?match(undefined, 'CosTimerEvent_TimerEventHandler':oe_tc(undefined)),
- ?match([_|_], 'CosTimerEvent_TimerEventHandler':oe_get_interface()),
- ?match("IDL:omg.org/CosTimerEvent/TimerEventHandler:1.0",
- 'CosTimerEvent_TimerEventHandler':typeID()),
- check_tc('CosTimerEvent_TimerEventHandler':oe_get_interface()),
- ?match(true, 'CosTimerEvent_TimerEventHandler':oe_is_a('CosTimerEvent_TimerEventHandler':typeID())),
- ?match(false, 'CosTimerEvent_TimerEventHandler':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTimerEvent_TimerEventService'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTimerEvent_TimerEventService'(_) ->
- ?nomatch(undefined, 'CosTimerEvent_TimerEventService':oe_tc(register)),
- ?nomatch(undefined, 'CosTimerEvent_TimerEventService':oe_tc(unregister)),
- ?nomatch(undefined, 'CosTimerEvent_TimerEventService':oe_tc(event_time)),
- ?match(undefined, 'CosTimerEvent_TimerEventService':oe_tc(undefined)),
- ?match([_|_], 'CosTimerEvent_TimerEventService':oe_get_interface()),
- ?match("IDL:omg.org/CosTimerEvent/TimerEventService:1.0",
- 'CosTimerEvent_TimerEventService':typeID()),
- check_tc('CosTimerEvent_TimerEventService':oe_get_interface()),
- ?match(true, 'CosTimerEvent_TimerEventService':oe_is_a('CosTimerEvent_TimerEventService':typeID())),
- ?match(false, 'CosTimerEvent_TimerEventService':oe_is_a("wrong")),
- ok.
-
-
-
-
-%%-----------------------------------------------------------------
-%% MISC functions
-%%-----------------------------------------------------------------
-check_tc([]) ->
- ok;
-check_tc([{Op, {RetType, InParameters, OutParameters}}|T]) ->
- io:format("checked - ~s~n", [Op]),
- lists:all(?checktc(Op), [RetType|InParameters]),
- lists:all(?checktc(Op), OutParameters),
- check_tc(T).
-
-
diff --git a/lib/cosTime/test/time_SUITE.erl b/lib/cosTime/test/time_SUITE.erl
deleted file mode 100644
index f85f13badb..0000000000
--- a/lib/cosTime/test/time_SUITE.erl
+++ /dev/null
@@ -1,301 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : time_SUITE.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module(time_SUITE).
-
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("cosTime/src/cosTimeApp.hrl").
-
--include_lib("common_test/include/ct.hrl").
-
-%%--------------- DEFINES ------------------------------------
--define(default_timeout, test_server:minutes(20)).
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
--define(match_inverse(NotExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- NotExpectedRes ->
- io:format("###### ERROR ERROR ######~n ~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS);
- _ ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS
- end
- end()).
-
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, cases/0,
- init_per_suite/1, end_per_suite/1, time_api/1, timerevent_api/1,
- init_per_testcase/2, end_per_testcase/2,
- app_test/1]).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-cases() ->
- [time_api, timerevent_api, app_test].
-
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-
-init_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- mnesia:delete_schema([node()]),
- mnesia:create_schema([node()]),
- orber:install([node()]),
- application:start(mnesia),
- application:start(orber),
- cosNotificationApp:install_event(),
- cosNotificationApp:install(),
- cosTime:install_time(),
- cosTime:install_timerevent(),
- if
- is_list(Config) ->
- Config;
- true ->
- exit("Config not a list")
- end.
-
-end_per_suite(Config) ->
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- cosTime:uninstall_time(),
- cosTime:uninstall_timerevent(),
- cosNotificationApp:uninstall(),
- cosNotificationApp:uninstall_event(),
- application:stop(orber),
- application:stop(mnesia),
- mnesia:delete_schema([node()]),
- Config.
-
-%%-----------------------------------------------------------------
-%% Tests app file
-%%-----------------------------------------------------------------
-app_test(_Config) ->
- ok=test_server:app_test(cosTime),
- ok.
-
-%%-----------------------------------------------------------------
-%% CosTime API tests
-%%-----------------------------------------------------------------
-time_api(_Config) ->
- ?match(ok, application:start(cosTime)),
- TS=cosTime:start_time_service(0, 500),
- Time=calendar:datetime_to_gregorian_seconds({{1582,1,1},{0,0,0}}),
- Inaccuracy = 1000,
- Tdf =1,
- Utc = #'TimeBase_UtcT'{time=Time, inacclo = ?low_TimeT(Inaccuracy),
- inacchi = ?high_TimeT(Inaccuracy), tdf = Tdf},
- UTO1='CosTime_TimeService':new_universal_time(TS, Time, Inaccuracy, Tdf),
- UTO2='CosTime_TimeService':uto_from_utc(TS, Utc),
- ?match(Time, 'CosTime_UTO':'_get_time'(UTO1)),
- ?match(Inaccuracy, 'CosTime_UTO':'_get_inaccuracy'(UTO1)),
- ?match(Tdf, 'CosTime_UTO':'_get_tdf'(UTO1)),
- ?match(Utc, 'CosTime_UTO':'_get_utc_time'(UTO1)),
-
- ?match(Time, 'CosTime_UTO':'_get_time'(UTO2)),
- ?match(Inaccuracy, 'CosTime_UTO':'_get_inaccuracy'(UTO2)),
- ?match(Tdf, 'CosTime_UTO':'_get_tdf'(UTO2)),
- ?match(Utc, 'CosTime_UTO':'_get_utc_time'(UTO2)),
-
- TIO1='CosTime_TimeService':new_interval(TS, 2, 5),
- _TIO2='CosTime_TimeService':new_interval(TS, 3, 6),
- TIO3='CosTime_TimeService':new_interval(TS, 1, 3),
- TIO4='CosTime_TimeService':new_interval(TS, 3, 4),
- TIO5='CosTime_TimeService':new_interval(TS, 7, 8),
- TIO6='CosTime_TimeService':new_interval(TS, 2, 6),
- TIO7='CosTime_TimeService':new_interval(TS, 3, 7),
-
- {_,TIO8} = ?match({'OTContained', _}, 'CosTime_TIO':overlaps(TIO1, TIO6)),
- {_,TIO9} = ?match({'OTContainer', _}, 'CosTime_TIO':overlaps(TIO1, TIO1)),
- {_,TIO10} = ?match({'OTContainer', _}, 'CosTime_TIO':overlaps(TIO1, TIO4)),
- {_,TIO11} = ?match({'OTOverlap', _}, 'CosTime_TIO':overlaps(TIO1, TIO3)),
- {_,TIO12} = ?match({'OTOverlap', _}, 'CosTime_TIO':overlaps(TIO1, TIO7)),
- {_,TIO13} = ?match({'OTNoOverlap', _}, 'CosTime_TIO':overlaps(TIO1, TIO5)),
-
- ?match({'TimeBase_IntervalT',2,5},'CosTime_TIO':'_get_time_interval'(TIO8)),
- ?match({'TimeBase_IntervalT',2,5},'CosTime_TIO':'_get_time_interval'(TIO9)),
- ?match({'TimeBase_IntervalT',3,4},'CosTime_TIO':'_get_time_interval'(TIO10)),
- ?match({'TimeBase_IntervalT',2,3},'CosTime_TIO':'_get_time_interval'(TIO11)),
- ?match({'TimeBase_IntervalT',3,5},'CosTime_TIO':'_get_time_interval'(TIO12)),
- ?match({'TimeBase_IntervalT',5,7},'CosTime_TIO':'_get_time_interval'(TIO13)),
-
- UTO3='CosTime_TimeService':new_universal_time(TS, 4, 2, 0), %% 2-6
- UTO4='CosTime_TimeService':new_universal_time(TS, 2, 1, 0), %% 1-3
- UTO5='CosTime_TimeService':new_universal_time(TS, 3, 0, 0), %% 3-3
- UTO6='CosTime_TimeService':new_universal_time(TS, 9, 1, 0), %% 8-10
- UTO7='CosTime_TimeService':new_universal_time(TS, 4, 3, 0), %% 1-7
- UTO8='CosTime_TimeService':new_universal_time(TS, 5, 2, 0), %% 3-7
-
- {_,TIO14} = ?match({'OTContained', _}, 'CosTime_TIO':spans(TIO1, UTO7)),
- {_,TIO15} = ?match({'OTContainer', _}, 'CosTime_TIO':spans(TIO1, UTO5)),
- {_,TIO16} = ?match({'OTOverlap', _}, 'CosTime_TIO':spans(TIO1, UTO4)),
- {_,TIO17} = ?match({'OTOverlap', _}, 'CosTime_TIO':spans(TIO1, UTO8)),
- {_,TIO18} = ?match({'OTNoOverlap', _}, 'CosTime_TIO':spans(TIO1, UTO6)),
- {_,TIO19} = ?match({'OTContained', _}, 'CosTime_TIO':spans(TIO1, UTO3)),
-
- ?match({'TimeBase_IntervalT',2,5},'CosTime_TIO':'_get_time_interval'(TIO14)),
- ?match({'TimeBase_IntervalT',3,3},'CosTime_TIO':'_get_time_interval'(TIO15)),
- ?match({'TimeBase_IntervalT',2,3},'CosTime_TIO':'_get_time_interval'(TIO16)),
- ?match({'TimeBase_IntervalT',3,5},'CosTime_TIO':'_get_time_interval'(TIO17)),
- ?match({'TimeBase_IntervalT',5,8},'CosTime_TIO':'_get_time_interval'(TIO18)),
- ?match({'TimeBase_IntervalT',2,5},'CosTime_TIO':'_get_time_interval'(TIO19)),
-
-
- cosTime:stop_time_service(TS),
- application:stop(cosTime),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% CosTimerEvent API tests
-%%-----------------------------------------------------------------
-timerevent_api(_Config) ->
- %% Init cosTime apps.
- ?match(ok, application:start(cosTime)),
- TS=cosTime:start_time_service(0, 500),
- TES=cosTime:start_timerevent_service(TS),
-
- %%----- Initialize the cosNotification application. -----
- cosNotificationApp:start(),
- Fac = (catch cosNotificationApp:start_factory([])),
- {Ch, _Id1} = (catch 'CosNotifyChannelAdmin_EventChannelFactory':create_channel(Fac, [], [])),
- %% Create the Admin objects
- {AdminSupplier, _ASID}= ?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_EventChannel':new_for_suppliers(Ch,'OR_OP')),
- {AdminConsumer, _ACID}= ?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_EventChannel':new_for_consumers(Ch,'OR_OP')),
-
- %% Create a push consumer TimerEventService will push events to.
- {ProxyPushConsumer,_ID10}= ?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_SupplierAdmin':obtain_notification_push_consumer(AdminSupplier, 'ANY_EVENT')),
-
- %% Create a pull suppliers so we can check we actually got the event.
- {ProxyPullSupplier,_ID1} = ?match({{_,key,_,_,_,_},_},
- 'CosNotifyChannelAdmin_ConsumerAdmin':obtain_notification_pull_supplier(AdminConsumer, 'ANY_EVENT')),
-
- AnyEvent = any:create(orber_tc:long(), 100),
- UTO=?match({_,pseudo,_,_,_,_}, 'CosTime_TimeService':new_universal_time(TS, 10*10000000,1,1)),
- EH=?match({_,key,_,_,_,_}, 'CosTimerEvent_TimerEventService':register(TES, ProxyPushConsumer, AnyEvent)),
-
- ?match('ESTimeCleared','CosTimerEvent_TimerEventHandler':'_get_status'(EH)),
- ?match({false,_},'CosTimerEvent_TimerEventHandler':time_set(EH)),
- ?match(ok,'CosTimerEvent_TimerEventHandler':set_timer(EH, 'TTRelative', UTO)),
- ?match({true,_},'CosTimerEvent_TimerEventHandler':time_set(EH)),
- ?match('ESTimeSet','CosTimerEvent_TimerEventHandler':'_get_status'(EH)),
-
- ?match({{any,tk_null,null}, false},
- 'CosNotifyChannelAdmin_ProxyPullSupplier':try_pull(ProxyPullSupplier)),
-
- ?match(AnyEvent, 'CosNotifyChannelAdmin_ProxyPullSupplier':pull(ProxyPullSupplier)),
- ?match('ESTriggered','CosTimerEvent_TimerEventHandler':'_get_status'(EH)),
-
- %% It's allowed to send an UTO with time eq. to 0 if the server is TTRelative.
- %% When TTAbsolute BAD_PARAM is raised.
- UTO2=?match({_,pseudo,_,_,_,_}, 'CosTime_TimeService':new_universal_time(TS, 0,1,1)),
- ?match({'EXCEPTION',_},'CosTimerEvent_TimerEventHandler':set_timer(EH, 'TTAbsolute', UTO2)),
- ?match(ok,'CosTimerEvent_TimerEventHandler':set_timer(EH, 'TTRelative', UTO2)),
- ?match(AnyEvent, 'CosNotifyChannelAdmin_ProxyPullSupplier':pull(ProxyPullSupplier)),
-
- %% TTPeriodic is defined to be relative, i.e., we can use the tactic as above.
- ?match(ok,'CosTimerEvent_TimerEventHandler':set_timer(EH, 'TTPeriodic', UTO2)),
-
- %% Sleep for UTO*2+4 secs. At this point the Timer should have delivered 2 events.
- timer:sleep(24000),
- %% Cancel the timer so no more events will be delivered.
- ?match(true,'CosTimerEvent_TimerEventHandler':cancel_timer(EH)),
-
- ?match({AnyEvent, true}, 'CosNotifyChannelAdmin_ProxyPullSupplier':try_pull(ProxyPullSupplier)),
- ?match({AnyEvent, true}, 'CosNotifyChannelAdmin_ProxyPullSupplier':try_pull(ProxyPullSupplier)),
- ?match({{any,tk_null,null}, false},
- 'CosNotifyChannelAdmin_ProxyPullSupplier':try_pull(ProxyPullSupplier)),
-
-
-
- %% Clean up.
- cosNotificationApp:stop(),
- cosTime:stop_timerevent_service(TES),
- cosTime:stop_time_service(TS),
- application:stop(cosTime),
- ok.
-
-
diff --git a/lib/cosTime/vsn.mk b/lib/cosTime/vsn.mk
deleted file mode 100644
index 7c9cae2d2f..0000000000
--- a/lib/cosTime/vsn.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-COSTIME_VSN = 1.2.2
-
diff --git a/lib/cosTransactions/AUTHORS b/lib/cosTransactions/AUTHORS
deleted file mode 100644
index 6d03df4c5a..0000000000
--- a/lib/cosTransactions/AUTHORS
+++ /dev/null
@@ -1,4 +0,0 @@
-Original Authors:
-Niclas Eklund
-
-Contributors:
diff --git a/lib/cosTransactions/Makefile b/lib/cosTransactions/Makefile
deleted file mode 100644
index e8d0d1c0cd..0000000000
--- a/lib/cosTransactions/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include vsn.mk
-VSN=$(COSTRANSACTIONS_VSN)
-
-# ----------------------------------------------------
-# Common Macros
-# ----------------------------------------------------
-# SUB_DIRECTORIES = src test examples doc/src
-# At the moment we don't have any example programs.
-SUB_DIRECTORIES = src doc/src
-
-SPECIAL_TARGETS =
-
-# ----------------------------------------------------
-# Default Subdir Targets
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_subdir.mk
diff --git a/lib/cosTransactions/doc/html/.gitignore b/lib/cosTransactions/doc/html/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosTransactions/doc/html/.gitignore
+++ /dev/null
diff --git a/lib/cosTransactions/doc/man3/.gitignore b/lib/cosTransactions/doc/man3/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosTransactions/doc/man3/.gitignore
+++ /dev/null
diff --git a/lib/cosTransactions/doc/man6/.gitignore b/lib/cosTransactions/doc/man6/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosTransactions/doc/man6/.gitignore
+++ /dev/null
diff --git a/lib/cosTransactions/doc/pdf/.gitignore b/lib/cosTransactions/doc/pdf/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosTransactions/doc/pdf/.gitignore
+++ /dev/null
diff --git a/lib/cosTransactions/doc/src/CosTransactions_Control.xml b/lib/cosTransactions/doc/src/CosTransactions_Control.xml
deleted file mode 100644
index bf5e25a701..0000000000
--- a/lib/cosTransactions/doc/src/CosTransactions_Control.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1999</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosTransactions_Control</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>1999-04-12</date>
- <rev>PA1</rev>
- </header>
- <module>CosTransactions_Control</module>
- <modulesummary>This module implements the OMG CosTransactions::Control interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosTransactions/include/CosTransactions.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>get_coordinator(Control) -> Return</name>
- <fsummary>Return the Coordinator object associated with the target object</fsummary>
- <type>
- <v>Control = #objref</v>
- <v>Return = Coordinator | {'EXCEPTION', E}</v>
- <v>Coordinator = #objref</v>
- <v>E = #'CosTransactions_Unavailable' {}</v>
- </type>
- <desc>
- <p>This operation returns the Coordinator object associated with the target object.
- The Coordinator supports operations for termination of a transaction.</p>
- </desc>
- </func>
- <func>
- <name>get_terminator(Control) -> Return</name>
- <fsummary>Return the Terminator object associated with the target object</fsummary>
- <type>
- <v>Control = #objref</v>
- <v>Return = Terminator | {'EXCEPTION', E}</v>
- <v>Terminator = #objref</v>
- <v>E = #'CosTransactions_Unavailable' {}</v>
- </type>
- <desc>
- <p>This operation returns the Terminator object associated with the target object.
- The Terminator supports operations for termination of a transaction.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosTransactions/doc/src/CosTransactions_Coordinator.xml b/lib/cosTransactions/doc/src/CosTransactions_Coordinator.xml
deleted file mode 100644
index 006ba4cc29..0000000000
--- a/lib/cosTransactions/doc/src/CosTransactions_Coordinator.xml
+++ /dev/null
@@ -1,230 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosTransactions_Coordinator</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>1999-04-12</date>
- <rev>PA1</rev>
- </header>
- <module>CosTransactions_Coordinator</module>
- <modulesummary>This module implements the OMG CosTransactions::Coordinator interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosTransactions/include/CosTransactions.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>create_subtransaction(Coordinator) -> Control</name>
- <fsummary>Create a new subtransaction.</fsummary>
- <type>
- <v>Coordinator = #objref</v>
- <v>Control = #objref</v>
- </type>
- <desc>
- <p>A new subtransaction is created whose parent is the Coordinator argument.</p>
- <p>Raises exception:</p>
- <list type="bulleted">
- <item>'SubtransactionsUnavailable' - if nested transactions are not supported.</item>
- <item>'Inactive' - if target transaction has already been prepared.</item>
- </list>
- </desc>
- </func>
- <func>
- <name>get_transaction_name(Coordinator) -> Name</name>
- <fsummary>Return the name associated with the object.</fsummary>
- <type>
- <v>Coordinator = #objref</v>
- <v>Name = string() of type "oe_name@machine_type_timestamp"</v>
- </type>
- <desc>
- <p>Returns a printable string, which describe the transaction. The main purpose is to support debugging.</p>
- </desc>
- </func>
- <func>
- <name>get_parent_status(Coordinator) -> Status</name>
- <fsummary>Return the status of the parent transaction.</fsummary>
- <type>
- <v>Coordinator = #objref</v>
- <v>Status = atom()</v>
- </type>
- <desc>
- <p>Returns the status of the parent transaction
- associated with the target object. If the target object is a top-level
- transaction this operation is equivalent to <c>get_status/1</c> operation. </p>
- <p>Possible Status replies:</p>
- <list type="bulleted">
- <item>'StatusCommitted'</item>
- <item>'StatusCommitting'</item>
- <item>'StatusMarkedRollback'</item>
- <item>'StatusRollingBack'</item>
- <item>'StatusRolledBack'</item>
- <item>'StatusActive'</item>
- <item>'StatusPrepared'</item>
- <item>'StatusUnknown'</item>
- <item>'StatusNoTransaction'</item>
- <item>'StatusPreparing'</item>
- </list>
- </desc>
- </func>
- <func>
- <name>get_status(Coordinator) -> Status</name>
- <fsummary>Return the status of the transaction associated with the target object</fsummary>
- <type>
- <v>Coordinator = #objref</v>
- <v>Status = atom()</v>
- </type>
- <desc>
- <p>Returns the status of the transaction associated with the target object.</p>
- </desc>
- </func>
- <func>
- <name>get_top_level_status(Coordinator) -> Status</name>
- <fsummary>Return the status of the top-level transaction associated with the target object</fsummary>
- <type>
- <v>Coordinator = #objref</v>
- <v>Status = atom()</v>
- </type>
- <desc>
- <p>Returns the status of the top-level transaction associated with the target object.</p>
- </desc>
- </func>
- <func>
- <name>hash_top_level_tran(Coordinator) -> Return</name>
- <fsummary>Return a hash code for the top-level transaction associated with the target object</fsummary>
- <type>
- <v>Coordinator = #objref</v>
- <v>Return = integer()</v>
- </type>
- <desc>
- <p>Returns a hash code for the top-level transaction
- associated with the target object. Equals the operation
- <c>hash_transaction/1</c> if the target object is a top-level transaction.</p>
- </desc>
- </func>
- <func>
- <name>hash_transaction(Coordinator) -> Return</name>
- <fsummary>Return a hash code for the transaction associated with the target object.</fsummary>
- <type>
- <v>Coordinator = #objref</v>
- <v>Return = integer()</v>
- </type>
- <desc>
- <p>Returns a hash code for the transaction associated with the target object.</p>
- </desc>
- </func>
- <func>
- <name>is_descendant_transaction(Coordinator, OtherCoordinator) -> Return</name>
- <fsummary>Return a boolean which indicates whether the transaction associated with the target object is a descendant of the transaction associated with the parameter object</fsummary>
- <type>
- <v>Coordinator = #objref</v>
- <v>OtherCoordinator = #objref</v>
- <v>Return = Boolean</v>
- </type>
- <desc>
- <p>Returns true if the transaction associated with the target object is a
- descendant of the transaction associated with the parameter object.</p>
- </desc>
- </func>
- <func>
- <name>is_same_transaction(Coordinator, OtherCoordinator) -> Return</name>
- <fsummary>Return true if the transaction associated with the target object is related to the transaction associated with the parameter object</fsummary>
- <type>
- <v>Coordinator = #objref</v>
- <v>OtherCoordinator = #objref</v>
- <v>Return = Boolean</v>
- </type>
- <desc>
- <p>Returns true if the transaction associated with the target object is
- related to the transaction associated with the parameter object.</p>
- </desc>
- </func>
- <func>
- <name>is_top_level_transaction(Coordinator) -> Return</name>
- <fsummary>Return true if the transaction associated with the target object is a top-level transaction</fsummary>
- <type>
- <v>Coordinator = #objref</v>
- <v>Return = Boolean</v>
- </type>
- <desc>
- <p>Returns true if the transaction associated with the target object is
- a top-level transaction.</p>
- </desc>
- </func>
- <func>
- <name>register_resource(Coordinator, Resource) -> RecoveryCoordinator</name>
- <fsummary>Register the parameter <c>Resource</c>object as a participant in the transaction associated with the target object</fsummary>
- <type>
- <v>Coordinator = #objref</v>
- <v>Resource = #objref</v>
- <v>RecoveryCoordinator = #objref</v>
- </type>
- <desc>
- <p>This operation registers the parameter <c>Resource</c> object as a participant in the
- transaction associated with the target object. The <c>RecoveryCoordinator</c> returned
- by this operation can be used by this Resource during recovery.</p>
- <note>
- <p>The Resources will be called in FIFO-order when preparing or committing.
- Hence, be sure to register the Resources in the correct order.</p>
- </note>
- <p>Raises exception:</p>
- <list type="bulleted">
- <item>'Inactive' - if target transaction has already been prepared.</item>
- </list>
- </desc>
- </func>
- <func>
- <name>register_subtran_aware(Coordinator, SubtransactionAwareResource) -> Return</name>
- <fsummary>Register the parameter <c>SubtransactionAwareResource</c>object such that it will be notified when the transaction, associated wit the target object, has committed or rolled back</fsummary>
- <type>
- <v>Coordinator = #objref</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>This operation registers the parameter <c>SubtransactionAwareResource</c> object such that
- it will be notified when the transaction, associated wit the target object,
- has committed or rolled back.</p>
- <note>
- <p>The Resources will be called in FIFO-order.
- Hence, be sure to register the Resources in the correct order.</p>
- </note>
- </desc>
- </func>
- <func>
- <name>rollback_only(Coordinator) -> Return</name>
- <fsummary>Modify the transaction associated with the target object so the only possible outcome is to rollback the transaction</fsummary>
- <type>
- <v>Coordinator = #objref</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>The transaction associated with the target object is modified so the only
- possible outcome is to rollback the transaction.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosTransactions/doc/src/CosTransactions_RecoveryCoordinator.xml b/lib/cosTransactions/doc/src/CosTransactions_RecoveryCoordinator.xml
deleted file mode 100644
index 2d61f815a3..0000000000
--- a/lib/cosTransactions/doc/src/CosTransactions_RecoveryCoordinator.xml
+++ /dev/null
@@ -1,82 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosTransactions_RecoveryCoordinator</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>1999-04-12</date>
- <rev>PA1</rev>
- </header>
- <module>CosTransactions_RecoveryCoordinator</module>
- <modulesummary>This module implements the OMG CosTransactions::RecoveryCoordinator interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosTransactions/include/CosTransactions.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>replay_completion(RecoveryCoordinator, Timeout, Resource) -> Return</name>
- <fsummary>Return the current status of the transaction</fsummary>
- <type>
- <v>RecoveryCoordinator = #objref</v>
- <v>Timeout = integer(), milliseconds | 'infinity'</v>
- <v>Resource = #objref</v>
- <v>Return = Status | {'EXCEPTION', E}</v>
- <v>E = #'CosTransactions_NotPrepared'{}</v>
- <v>Status = atom()</v>
- </type>
- <desc>
- <p>The <c>RecoveryCoordinator</c> object is returned by the operation
- <c>CosTransactions_Coordinator:register_resource/3</c>. The <c>replay_completion/2</c>
- may only be used by the registered Resource and returns the current status
- of the transaction. The operation is used when recovering after a failure.</p>
- <p>Possible Status replies:</p>
- <list type="bulleted">
- <item>'StatusCommitted'</item>
- <item>'StatusCommitting'</item>
- <item>'StatusMarkedRollback'</item>
- <item>'StatusRollingBack'</item>
- <item>'StatusRolledBack'</item>
- <item>'StatusActive'</item>
- <item>'StatusPrepared'</item>
- <item>'StatusUnknown'</item>
- <item>'StatusNoTransaction'</item>
- <item>'StatusPreparing'</item>
- </list>
- <warning>
- <p><em>replay_completion/3</em> is blocking and may cause dead-lock if a child
- calls this function at the same time as its parent invokes an operation
- on the child. Dead-lock will not occur if the timeout has any value except 'infinity'.</p>
- <p>If the call is external incoming (intra-ORB) the timeout will not be activated.
- Hence, similar action must be taken if the Resource resides on another vendors ORB.</p>
- </warning>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosTransactions/doc/src/CosTransactions_Resource.xml b/lib/cosTransactions/doc/src/CosTransactions_Resource.xml
deleted file mode 100644
index 40006b55d9..0000000000
--- a/lib/cosTransactions/doc/src/CosTransactions_Resource.xml
+++ /dev/null
@@ -1,129 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosTransactions_Resource</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>1999-04-12</date>
- <rev>PA1</rev>
- </header>
- <module>CosTransactions_Resource</module>
- <modulesummary>This module implements the OMG CosTransactions::Resource interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosTransactions/include/CosTransactions.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>commit(Resource) -> Return</name>
- <fsummary>Instruct the target object to commit the transaction</fsummary>
- <type>
- <v>Resource = #objref</v>
- <v>Return = ok | {'EXCEPTION', E}</v>
- <v>E = #'CosTransactions_NotPrepared'{} | #'CosTransactions_HeuristicRollback'{} | #'CosTransactions_HeuristicMixed'{} | #'CosTransactions_HeuristicHazard'{}</v>
- </type>
- <desc>
- <p>This operation instructs the Resource to commit all changes made as a part of the transaction.</p>
- <p>The Resource can raise:</p>
- <list type="bulleted">
- <item>Heuristic Exception - if a Heuristic decision is made which differ
- from the true outcome of the transaction. The Resource must remember
- the Heuristic outcome until the <c>forget</c> operation is performed.</item>
- </list>
- </desc>
- </func>
- <func>
- <name>commit_one_phase(Resource) -> Return</name>
- <fsummary>Instruct the target object to commit the transaction</fsummary>
- <type>
- <v>Resource = #objref</v>
- <v>Return = ok | {'EXCEPTION', E}</v>
- <v>E = #'CosTransactions_HeuristicHazard'{} | #'CosTransactions_TransactionRolledBack'{}</v>
- </type>
- <desc>
- <p>If possible, the Resource should commit all changes made as part of the transaction,
- else it should raise the TRANSACTION_ROLLEDBACK exception.
- This operation can only be used if the Resource is the only child of its parent.</p>
- </desc>
- </func>
- <func>
- <name>forget(Resource) -> Return</name>
- <fsummary>Instruct the target object to forget any heuristic decisions</fsummary>
- <type>
- <v>Resource = #objref</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>This operation informs the Resource that it is safe to forget any Heuristic
- decisions and the knowledge of the transaction.</p>
- </desc>
- </func>
- <func>
- <name>prepare(Resource) -> Return</name>
- <fsummary>Instruct the target object to begin the two-phase commit protocol</fsummary>
- <type>
- <v>Resource = #objref</v>
- <v>Return = Vote | {'EXCEPTION', E}</v>
- <v>Vote = 'VoteReadOnly' | 'VoteCommit' | 'VoteRollback'</v>
- <v>E = #'CosTransactions_HeuristicMixed'{} | #'CosTransactions_HeuristicHazard'{}</v>
- </type>
- <desc>
- <p>This operation is invoked on the Resource to begin the two-phase commit protocol.</p>
- <p>The Resource can reply:</p>
- <list type="bulleted">
- <item>'VoteReadOnly' - if no persistent data has been modified by the transaction.
- The Resource can forget all knowledge of the transaction. </item>
- <item>'VoteCommit' - if the Resource has been prepared and is able to write all the
- data needed to commit the transaction to stable storage.</item>
- <item>'VoteRollback' - under any circumstances but must do so if none of the alternatives above
- are applicable.</item>
- <item>Heuristic Exception - if a Heuristic decision is made which differ
- from the true outcome of the transaction. The Resource must remember
- the Heuristic outcome until the <c>forget</c> operation is performed.</item>
- </list>
- </desc>
- </func>
- <func>
- <name>rollback(Resource) -> Return</name>
- <fsummary>Instruct the target object to rollback the transaction</fsummary>
- <type>
- <v>Resource = #objref</v>
- <v>Return = ok | {'EXCEPTION', E}</v>
- <v>E = #'CosTransactions_HeuristicCommit'{} | #'CosTransactions_HeuristicMixed'{} | #'CosTransactions_HeuristicHazard'{}</v>
- </type>
- <desc>
- <p>This operation instructs the Resource to rollback all changes made as a part of the transaction.</p>
- <p>The Resource can raise:</p>
- <list type="bulleted">
- <item>Heuristic Exception - if a Heuristic decision is made which differ
- from the true outcome of the transaction. The Resource must remember
- the Heuristic outcome until the <c>forget</c> operation is performed.</item>
- </list>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosTransactions/doc/src/CosTransactions_SubtransactionAwareResource.xml b/lib/cosTransactions/doc/src/CosTransactions_SubtransactionAwareResource.xml
deleted file mode 100644
index 30102d18d9..0000000000
--- a/lib/cosTransactions/doc/src/CosTransactions_SubtransactionAwareResource.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosTransactions_SubtransactionAwareResource</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>1999-04-12</date>
- <rev>PA1</rev>
- </header>
- <module>CosTransactions_SubtransactionAwareResource</module>
- <modulesummary>This module implements the OMG CosTransactions::SubtransactionAwareResource interface.</modulesummary>
- <description>
- <p>This interface inherits the CosTransactions::Resource interface. Hence,
- it must also support all operations defined in the Resource interface.</p>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosTransactions/include/CosTransactions.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>commit_subtransaction(SubtransactionAwareResource, Coordinator) -> Return</name>
- <fsummary>Notify the target object that the transaction has committed</fsummary>
- <type>
- <v>SubtransactionAwareResource = #objref</v>
- <v>Coordinator = #objref</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>If the <c>SubtransactionAwareResource</c> have been registered with a <em>subtransaction</em>
- using the operation <c>CosTransactions_Coordinator:register_subtran_aware/2</c>,
- it will be notified when the transaction has committed.</p>
- <note>
- <p>The results of a committed subtransaction are relative to the completion of its ancestor
- transactions, that is, these results can be undone if any ancestor transaction is rolled back.</p>
- </note>
- </desc>
- </func>
- <func>
- <name>rollback_subtransaction(SubtransactionAwareResource) -> Return</name>
- <fsummary>Notify the target object that the transaction has been rolled back</fsummary>
- <type>
- <v>SubtransactionAwareResource = #objref</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>If the <c>SubtransactionAwareResource</c> have been registered with a transactions
- using the operation <c>CosTransactions_Coordinator:register_subtran_aware/2</c>
- it will be notified when the transaction has rolled back.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosTransactions/doc/src/CosTransactions_Synchronization.xml b/lib/cosTransactions/doc/src/CosTransactions_Synchronization.xml
deleted file mode 100644
index c21e7c559d..0000000000
--- a/lib/cosTransactions/doc/src/CosTransactions_Synchronization.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1999</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosTransactions_Synchronization</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>1999-04-12</date>
- <rev>PA1</rev>
- </header>
- <module>CosTransactions_Synchronization</module>
- <modulesummary>This module implements the OMG CosTransactions::Synchronization interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosTransactions/CosTransactions.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>before_completion(Synchronization) -> Return</name>
- <fsummary>Notify the target object that the transaction is about to enter the prepare phase</fsummary>
- <type>
- <v>Synchronization = #objref</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>If the target object is a transaction using the operation <c>register_synchronization/2</c>
- it will be notified to perform necessary processing prior to the prepare phase.</p>
- </desc>
- </func>
- <func>
- <name>after_completion(Synchronization) -> Return</name>
- <fsummary>Notify the target object that the transaction is completed</fsummary>
- <type>
- <v>Synchronization = #objref</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>If the target object is a transaction using the operation <c>register_synchronization/2</c>
- it will be notified to perform necessary processing after terminating the transaction.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosTransactions/doc/src/CosTransactions_Terminator.xml b/lib/cosTransactions/doc/src/CosTransactions_Terminator.xml
deleted file mode 100644
index f75f4d912d..0000000000
--- a/lib/cosTransactions/doc/src/CosTransactions_Terminator.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1999</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosTransactions_Terminator</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>1999-04-12</date>
- <rev>PA1</rev>
- </header>
- <module>CosTransactions_Terminator</module>
- <modulesummary>This module implements the OMG CosTransactions::Terminator interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosTransactions/include/CosTransactions.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>commit(Terminator, ReportHeuristics) -> Return</name>
- <fsummary>Try to commit a transaction</fsummary>
- <type>
- <v>Terminator = #objref</v>
- <v>ReportHeuristics = boolean()</v>
- <v>Return = ok | {'EXCEPTION', E}</v>
- <v>E = #'CosTransactions_HeuristicMixed'{} | #'CosTransactions_HeuristicHazrd'{} | #'CosTransactions_TransactionRolledBack'{}</v>
- </type>
- <desc>
- <p>This operation initiates the two-phase commit protocol. If the transaction has not been marked
- <c>'rollback only'</c> and all the participants agree to commit, the operation terminates normally. Otherwise,
- the TransactionRolledBack is raised. If the parameter <c>ReportHeuristics</c> is true and inconsistent
- outcomes by raising an Heuristic Exception.</p>
- </desc>
- </func>
- <func>
- <name>rollback(Terminator) -> Return</name>
- <fsummary>Rollback a transaction</fsummary>
- <type>
- <v>Terminator = #objref</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>This operation roles back the transaction. </p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosTransactions/doc/src/CosTransactions_TransactionFactory.xml b/lib/cosTransactions/doc/src/CosTransactions_TransactionFactory.xml
deleted file mode 100644
index c4469ef850..0000000000
--- a/lib/cosTransactions/doc/src/CosTransactions_TransactionFactory.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1999</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosTransactions_TransactionFactory</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>1999-04-12</date>
- <rev>PA1</rev>
- </header>
- <module>CosTransactions_TransactionFactory</module>
- <modulesummary>This module implements the OMG CosTransactions::TransactionFactory interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosTransactions/include/CosTransactions.hrl").</c></p>
- </description>
- <funcs>
- <func>
- <name>create(TransactionFactory, Timeout) -> Control</name>
- <fsummary>Create a new top-level transaction</fsummary>
- <type>
- <v>TransactionFactory = #objref</v>
- <v>Timeout = integer()</v>
- <v>Control = #objref</v>
- </type>
- <desc>
- <p>This operation creates a new top-level transaction.</p>
- <p>The <c>Timeout</c> argument can be:</p>
- <list type="bulleted">
- <item>0 - no timeout.</item>
- <item>N (integer() > 0) - the transaction will be subject to being rolled back
- if it does not complete before N seconds have elapsed.</item>
- </list>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosTransactions/doc/src/CosTransactions_TransactionalObject.xml b/lib/cosTransactions/doc/src/CosTransactions_TransactionalObject.xml
deleted file mode 100644
index 319da2bd16..0000000000
--- a/lib/cosTransactions/doc/src/CosTransactions_TransactionalObject.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosTransactions_TransactionalObject</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>1999-04-12</date>
- <rev>PA1</rev>
- </header>
- <module>CosTransactions_TransactionalObject</module>
- <modulesummary>This module implements the OMG CosTransactions::TransactionalObject interface.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosTransactions/CosTransactions.hrl").</c></p>
- <p>The TransactionalObject interface is used by an object to indicate that it is transactional.
- By supporting this interface, an object indicates that it wants the transaction context associated with
- the client to be associated with all operation on its interface. No operations are defined.</p>
- </description>
-
-</erlref>
-
diff --git a/lib/cosTransactions/doc/src/Makefile b/lib/cosTransactions/doc/src/Makefile
deleted file mode 100644
index b70d7647b1..0000000000
--- a/lib/cosTransactions/doc/src/Makefile
+++ /dev/null
@@ -1,147 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(COSTRANSACTIONS_VSN)
-APPLICATION=cosTransactions
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = \
- cosTransactions.xml \
- CosTransactions_Control.xml \
- CosTransactions_Coordinator.xml \
- CosTransactions_RecoveryCoordinator.xml \
- CosTransactions_Resource.xml \
- CosTransactions_SubtransactionAwareResource.xml \
- CosTransactions_Terminator.xml \
- CosTransactions_TransactionFactory.xml
-# CosTransactions_Synchronization.xml
-
-XML_PART_FILES = \
- part.xml \
- part_notes.xml
-XML_CHAPTER_FILES = \
- ch_contents.xml \
- ch_introduction.xml \
- ch_install.xml \
- ch_example.xml \
- ch_skeletons.xml \
- notes.xml
-
-BOOK_FILES = book.xml
-
-XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \
- $(XML_PART_FILES) $(XML_CHAPTER_FILES)
-
-TECHNICAL_DESCR_FILES =
-
-GIF_FILES = \
- book.gif \
- notes.gif \
- ref_man.gif \
- user_guide.gif
-
-PS_FILES =
-
-# ----------------------------------------------------
-
-INTERNAL_HTML_FILES = $(TECHNICAL_DESCR_FILES:%.xml=$(HTMLDIR)/%.html)
-
-HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
-
-INFO_FILE = ../../info
-EXTRA_FILES = summary.html.src \
- $(DEFAULT_GIF_FILES) \
- $(DEFAULT_HTML_FILES) \
- $(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html)
-
-MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-
-HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
-
-TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-$(HTMLDIR)/%.gif: %.gif
- $(INSTALL_DATA) $< $@
-
-docs: pdf html man
-
-$(TOP_PDF_FILE): $(XML_FILES)
-
-pdf: $(TOP_PDF_FILE)
-
-html: gifs $(HTML_REF_MAN_FILE)
-
-clean clean_docs:
- rm -rf $(HTMLDIR)/*
- rm -f $(MAN3DIR)/*
- rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
-
-man: $(MAN3_FILES)
-
-gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-
-$(INDEX_TARGET): $(INDEX_SRC)
- sed -e 's;%VSN%;$(VSN);' $(INDEX_SRC) > $(INDEX_TARGET)
-
-debug opt:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_docs_spec: docs
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(HTMLDIR)/* \
- "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
- $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
-
-release_spec:
diff --git a/lib/cosTransactions/doc/src/book.gif b/lib/cosTransactions/doc/src/book.gif
deleted file mode 100644
index 94b3868792..0000000000
--- a/lib/cosTransactions/doc/src/book.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosTransactions/doc/src/book.xml b/lib/cosTransactions/doc/src/book.xml
deleted file mode 100644
index 33a8c323bb..0000000000
--- a/lib/cosTransactions/doc/src/book.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book xmlns:xi="http://www.w3.org/2001/XInclude">
- <header titlestyle="normal">
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosTransactions</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>1999-04-14</date>
- <rev>2.0</rev>
- </header>
- <insidecover>
- </insidecover>
- <pagetext>cosTransactions</pagetext>
- <preamble>
- <contents level="2"></contents>
- </preamble>
- <parts lift="no">
- <xi:include href="part.xml"/>
- </parts>
- <applications>
- <xi:include href="ref_man.xml"/>
- </applications>
- <releasenotes>
- <xi:include href="notes.xml"/>
- </releasenotes>
- <listofterms></listofterms>
- <index></index>
-</book>
-
diff --git a/lib/cosTransactions/doc/src/ch_contents.xml b/lib/cosTransactions/doc/src/ch_contents.xml
deleted file mode 100644
index 9b2832a032..0000000000
--- a/lib/cosTransactions/doc/src/ch_contents.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>The cosTransactions Application</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>1999-04-14</date>
- <rev>B</rev>
- <file>ch_contents.xml</file>
- </header>
-
- <section>
- <title>Content Overview</title>
- <p>The cosTransactions documentation is divided into three sections:
- </p>
- <list type="bulleted">
- <item>
- <p>PART ONE - The User's Guide
- <br></br>
-Description of the cosTransactions Application including
- services and a small tutorial demonstrating
- the development of a simple service.</p>
- </item>
- <item>
- <p>PART TWO - Release Notes
- <br></br>
-A concise history of cosTransactions.</p>
- </item>
- <item>
- <p>PART THREE - The Reference Manual
- <br></br>
- A quick reference guide, including a
- brief description, to all the functions available in cosTransactions.</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Brief Description of the User's Guide</title>
- <p>The User's Guide contains the following parts:</p>
- <list type="bulleted">
- <item>
- <p>cosTransactions overview</p>
- </item>
- <item>
- <p>cosTransactions installation</p>
- </item>
- <item>
- <p>A tutorial example</p>
- </item>
- </list>
- </section>
-</chapter>
-
diff --git a/lib/cosTransactions/doc/src/ch_example.xml b/lib/cosTransactions/doc/src/ch_example.xml
deleted file mode 100644
index a2451e5fbc..0000000000
--- a/lib/cosTransactions/doc/src/ch_example.xml
+++ /dev/null
@@ -1,283 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosTransactions Examples</title>
- <prepared></prepared>
- <docno></docno>
- <date>1999-04-27</date>
- <rev>A</rev>
- <file>ch_example.xml</file>
- </header>
-
- <section>
- <title>A Tutorial on How to Create a Simple Service</title>
-
- <section>
- <title>Interface design</title>
- <p>To use the cosTransactions application <em>participants</em> must be implemented.
- There are two types of participants: </p>
- <list type="bulleted">
- <item><seealso marker="CosTransactions_Resource">CosTransactions_Resource</seealso> - operations used to commit or rollback resources.</item>
- <item><seealso marker="CosTransactions_SubtransactionAwareResource">CosTransactions_SubtransactionAwareResource</seealso> -
- operations used when the resources want to be notified when a subtransaction commits.
- This interface inherits the CosTransactions_Resource</item>
- </list>
- <p>The interfaces for these participants are defined in <em>CosTransactions.idl</em></p>
- </section>
-
- <section>
- <title>Generating a Participant Interface</title>
- <p>We start by creating an interface which inherits from <em>CosTransactions::Resource</em>. Hence,
- we must also implement all operations defined in the Resource interface. The IDL-file could look like: </p>
- <code type="c"><![CDATA[
-#ifndef _OWNRESOURCEIMPL_IDL
-#define _OWNRESOURCEIMPL_IDL
-#include <CosTransactions.idl>
-
-module ownResourceImpl {
-
- interface ownInterface:CosTransactions::Resource {
-
- void ownFunctions(in any NeededArguments)
- raises(Systemexceptions,OwnExceptions);
-
- };
-};
-
-#endif
- ]]></code>
- <p>Run the IDL compiler on this file by calling the <c>ic:gen/1</c> function.
- This will produce the API named <c>ownResourceImpl_ownInterface.erl</c>.
- After generating the API stubs and the server skeletons it is time to
- implement the servers and if no special options are sent
- to the IDl compiler the file name is <c>ownResourceImpl_ownInterface_impl.erl</c>.</p>
- </section>
-
- <section>
- <title>Implementation of Participant interface</title>
- <p>If the participant is intended to be a plain Resource, we must implement the following operations:</p>
- <list type="bulleted">
- <item><c>prepare/1</c> - this operation is invoked on the Resource to begin the two-phase commit protocol.</item>
- <item><c>rollback/1</c> - this operation instructs the Resource to rollback all changes made as a part of the transaction. </item>
- <item><c>commit/1</c> - this operation instructs the Resource to commit all changes made as a part of the transaction.</item>
- <item><c>commit_one_phase/1</c> - if possible, the Resource should commit all changes made as part of the transaction.
- This operation can only be used if the Resource is the only child of its parent. </item>
- <item><c>forget/1</c> - this operation informs the Resource that it is safe to forget any
- <term id="Heuristic decisions"><termdef>Heuristic decisions is a unilateral decision by a participant to commit
- or rollback without receiving the true outcome of the transaction from its parent's coordinator.</termdef></term>
- and the knowledge of the transaction.</item>
- <item><c>ownFunctions</c> - all application specific operations.</item>
- </list>
- <p>If the participant wants to be notified when a subtransaction commits, we must also implement the following operations
- (besides the operations above):</p>
- <list type="bulleted">
- <item><c>commit_subtransaction/2</c> - if the <c>SubtransactionAwareResource</c> have been registered
- with a transactions using the operation <c>CosTransactions_Coordinator:register_subtran_aware/2</c> it will
- be notified when the transaction has
- committed. </item>
- <item><c>rollback_subtransaction/1</c> - if the <c>SubtransactionAwareResource</c> have been registered
- with a transactions using the operation <c>CosTransactions_Coordinator:register_subtran_aware/2</c>
- it will be notified when the transaction has
- rolled back. </item>
- </list>
- <note>
- <p>The results of a committed subtransaction are relative to the completion of its ancestor transactions,
- that is, these results can be undone if any ancestor transaction is rolled back. </p>
- </note>
- </section>
-
- <section>
- <title>Participant Operations Behavior</title>
- <p>Each application participant must behave in a certain way to ensure that the two-phase commit protocol
- can complete the transactions correctly.</p>
-
- <section>
- <title>prepare</title>
- <p>This operation ask the participant to vote on the outcome of the transaction. Possible replies are:</p>
- <list type="bulleted">
- <item><em>'VoteReadOnly'</em> - if no data associated with the transaction has been modified VoteReadOnly may be returned.
- The Resource can forget all knowledge of the transaction and terminate.</item>
- <item><em>'VoteCommit'</em> - if the Resource is able to write all the data needed to commit the transaction to a stable storage,
- VoteCommit may be returned. The Resource will then wait until it is informed of the outcome of the transaction.
- The Resource may, however, make a unilateral decision (Heuristic) to commit or rollback changes associated
- with the transaction. When the Resource is informed of the true outcome (rollback/commit) and it is equal to
- the Heuristic decision the Resource just return 'ok'. But, if there is a mismatch and the commit-operation is irreversible,
- the Resource must raise a <seealso marker="CosTransactions_Resource">Heuristic Exception</seealso> and wait
- until the <c>forget</c> operation is invoked. The Heuristic Decision must be recorded in stable storage.</item>
- <item><em>'VoteRollback'</em> - the Resource may vote VoteRollback under any circumstances.
- The Resource can forget all knowledge of the transaction and terminate.</item>
- </list>
- <note>
- <p>Before replying to the prepare operation, the Resource must record the prepare state, the reference of its
- superior <seealso marker="CosTransactions_RecoveryCoordinator">RecoveryCoordinator</seealso> in stable storage.
- The RecoveryCoordinator is obtained when registering as a participant in a transaction.</p>
- </note>
- </section>
-
- <section>
- <title>rollback</title>
- <p>The Resource should, if necessary, rollback all changes made as part of the transaction. If the Resource is not aware of the
- transaction it should do nothing, e.g., recovered after a failure and have no data in stable storage. Heuristic Decisions
- must be handled as described above.</p>
- </section>
-
- <section>
- <title>commit</title>
- <p>The Resource should, if necessary, commit all changes made as part of the transaction. If the Resource is not aware of the
- transaction it should do nothing, e.g., recovered after a failure and have no data in stable storage. Heuristic Decisions
- must be handled as described above.</p>
- </section>
-
- <section>
- <title>commit_one_phase</title>
- <p>If possible, the Resource should commit all changes made as part of the transaction. If it cannot, it should raise the
- TRANSACTION_ROLLEDBACK exception. This operation can only be used if the Resource is the only child of its parent.
- If a failure occurs the completion of the operation must be retried when the failure is repaired. Heuristic Decisions
- must be handled as described above.</p>
- </section>
-
- <section>
- <title>forget</title>
- <p>If the Resource raised a Heuristic Exception to <c>commit</c>, <c>rollback</c> or <c>commit_one_phase</c> this operation
- will be performed. The Resource can forget all knowledge of the transaction and terminate.</p>
- </section>
-
- <section>
- <title>commit_subtransaction</title>
- <p>If the <c>SubtransactionAwareResource</c> have been registered with a <em>subtransaction</em>
- using the operation <c>CosTransactions_Coordinator:register_subtran_aware/2</c>
- it will be notified when the transaction has committed. The Resource may raise the exception
- <c>'TRANSACTION_ROLLEDBACK'</c>.</p>
- <note>
- <p>The result of a committed subtransaction is relative to the completion of its ancestor
- transactions, that is, these results can be undone if any ancestor transaction is rolled back.</p>
- </note>
- </section>
-
- <section>
- <title>rollback_subtransaction</title>
- <p>If the <c>SubtransactionAwareResource</c> have been registered with a <em>subtransaction</em>
- using the operation <c>CosTransactions_Coordinator:register_subtran_aware/2</c>
- it will be notified when the subtransaction has rolled back.</p>
- </section>
- </section>
-
- <section>
- <title>How to Run Everything</title>
- <p>Below is a short transcript on how to run cosTransactions. </p>
- <code type="none">
-
-%% Start Mnesia and Orber
-mnesia:delete_schema([node()]),
-mnesia:create_schema([node()]),
-orber:install([node()]),
-application:start(mnesia),
-application:start(orber),
-
-%% Register CosTransactions in the IFR.
-'oe_CosTransactions':'oe_register'(),
-
-%% Register the application specific Resource implementations
-%% in the IFR.
-'oe_ownResourceImpl':'oe_register'(),
-
-%%-- Set parameters --
-%% Timeout can be either 0 (no timeout) or an integer N > 0.
-%% The later state that the transaction should be rolled
-%% back if the transaction have not completed within N seconds.
-TimeOut = 0,
-
-%% Do we want the transaction to report Heuristic Exceptions?
-%% This variable must be boolean and indicates the way the
-%% Terminator should behave.
-Heuristics = true,
-
-%% Start the cosTransactions application.
-cosTransactions:start(), %% or application:start(cosTransactions),
-
-%% Start a factory using the default configuration
-TrFac = cosTransactions:start_factory(),
-%% ... or use configuration parameters.
-TrFac = cosTransactions:start_factory([{typecheck, false}, {hash_max, 3013}]),
-
-%% Create a new top-level transaction.
-Control = 'CosTransactions_TransactionFactory':create(TrFac, TimeOut),
-
-%% Retrieve the Coordinator and Terminator object references from
-%% the Control Object.
-Term = 'CosTransactions_Control':get_terminator(Control),
-Coord = 'CosTransactions_Control':get_coordinator(Control),
-
-%% Create two SubTransactions with the root-Coordinator as parent.
-SubCont1 = 'CosTransactions_Coordinator':create_subtransaction(Coord),
-SubCont2 = 'CosTransactions_Coordinator':create_subtransaction(Coord),
-
-%% Retrieve the Coordinator references from the Control Objects.
-SubCoord1 = 'CosTransactions_Control':get_coordinator(SubCont1),
-SubCoord2 = 'CosTransactions_Control':get_coordinator(SubCont2),
-
-%% Create application Resources. We can, for example, start the Resources
-%% our selves or look them up in the naming service. This is application
-%% specific.
-Res1 = ...
-Res2 = ...
-Res3 = ...
-Res4 = ...
-
-%% Register Resources with respective Coordinator. Each call returns
-%% a RecoveryCoordinator object reference.
-RC1 = 'CosTransactions_Coordinator':register_resource(SubCoord1, Res1),
-RC2 = 'CosTransactions_Coordinator':register_resource(SubCoord1, Res2),
-RC3 = 'CosTransactions_Coordinator':register_resource(SubCoord2, Res3),
-RC4 = 'CosTransactions_Coordinator':register_resource(SubCoord2, Res4),
-
-%% Register Resource 4 with SubCoordinator 1 so that the Resource will be
-%% informed when the SubCoordinator commits or roll-back.
-'CosTransactions_Coordinator':register_subtran_aware(SubCoord1, Res4),
-
-%% We are now ready to try to commit the transaction. The second argument
-%% must be a boolean
-Outcome = (catch 'CosTransactions_Terminator':commit(Term, Heuristics)),
- </code>
- <note>
- <p>For the cosTransaction application to be able to recognize if a Resource is
- dead or in the process of restarting the Resource must be started as persistent,
- e.g., 'OwnResource':oe_create_link(Env, [{regname, {global, RegName}}, {persistent, true}]).
- For more information see the Orber documentation.</p>
- </note>
- <p>The outcome of the transaction can be:</p>
- <list type="bulleted">
- <item>ok - the transaction was successfully committed.</item>
- <item>{'EXCEPTION', HeuristicExc} - at least one participant made a
- Heuristic decision or, due to a failure, one or more participants
- where unreachable.</item>
- <item>{'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{}} -
- the transaction was successfully rolled back.</item>
- <item>Any system exception -
- the transaction failed with unknown reason.</item>
- </list>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosTransactions/doc/src/ch_install.xml b/lib/cosTransactions/doc/src/ch_install.xml
deleted file mode 100644
index 4270c320b5..0000000000
--- a/lib/cosTransactions/doc/src/ch_install.xml
+++ /dev/null
@@ -1,104 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Installing cosTransactions</title>
- <prepared></prepared>
- <docno></docno>
- <date>1999-04-20</date>
- <rev></rev>
- <file>ch_install.xml</file>
-</header>
-
- <section>
- <title>Installation Process </title>
- <p>This chapter describes how to install
- <seealso marker="cosTransactions">cosTransactions</seealso>
- in an Erlang Environment.
- </p>
-
- <section>
- <title>Preparation</title>
- <p>Before starting the installation process for cosTransactions,
- the application Orber must be running.</p>
- <p>The cosTransactions application must be able to log progress to disk. The log files are
- created in the current directory as "oe_name@machine_type_timestamp". Hence, <c>read</c> and
- <c>write</c> rights must be granted. If the transaction completes in an orderly fashion the
- logfiles are removed, but not if an error, which demands human intervention, occur.</p>
- </section>
-
- <section>
- <title>Configuration</title>
- <p>When using the Transaction Service the <c>cosTransactions</c> application
- must be started using either <c>cosTransactions:start()</c> or
- <c>application:start(cosTransactions)</c>.
- </p>
- <p>The following application configuration parameters exist:</p>
- <list type="bulleted">
- <item><c>maxRetries</c> - default is 40 times, i.e., if a transaction participant is unreachable
- the application will retry to contact it <c>N</c> times. Reaching the maximum is considered to be a disaster.</item>
- <item><c>comFailWait</c> - default is 5000 milliseconds, i.e., before the application
- retries to contact unreachable transaction participants the application wait <c>Time</c> milliseconds.</item>
- </list>
- <p>Then the <seealso marker="CosTransactions_TransactionFactory">Transaction Factory</seealso>
- must be started:</p>
- <list type="bulleted">
- <item><c>cosTransactions:start_factory()</c> - starts and returns a reference to a factory using default configuration parameters.</item>
- <item><c>cosTransactions:start_factory(Options)</c> - starts and returns a reference to a factory using given configuration parameters.</item>
- </list>
- <p>The following options exist:
- </p>
- <list type="bulleted">
- <item><c>{hash_max, HashValue}</c> -
- This value denotes the upper bound of the hash value the <seealso marker="CosTransactions_Coordinator">Coordinator</seealso> uses.
- Default is <c>1013</c>. HashValue must be an integer.</item>
- <item><c>{allow_subtr, Boolean}</c> -
- If set to true it is possible to create <seealso marker="CosTransactions_Coordinator">subtransactions</seealso>.
- Default is <c>true</c>.</item>
- <item><c>{typecheck, Boolean}</c> -
- If set to to true all transaction operation's arguments will be type-checked.
- Default is <c>true</c>.</item>
- <item><c>{tty, Boolean}</c> -
- Enables or disables error printouts to the tty.
- If Flag is false, all text that the error logger would have sent to the terminal is discarded.
- If Flag is true, error messages are sent to the terminal screen. </item>
- <item><c>{logfile, FileName}</c> -
- This function makes it possible to store all system information in <c>FileName</c> (string()).
- It can be used in combination with the tty(false) item to have a silent system,
- where all system information are logged to a file.
- As default no logfile is used.</item>
- <item><c>{maxRetries, Integer}</c> -
- default is 40 times, i.e., if a transaction participant is unreachable the application will
- retry to contact it <c>N</c> times. Reaching the maximum is considered to be a disaster.
- This option overrides the application configuration parameter.</item>
- <item><c>{comFailWait, Integer}</c> -
- default is 5000 milliseconds, i.e., before the application retries to contact unreachable
- transaction participants the application wait <c>Time</c> milliseconds.
- This option overrides the application configuration parameter.</item>
- </list>
- <p>The Factory is now ready to use. For a more detailed description see <seealso marker="ch_example">Examples</seealso>.
- </p>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosTransactions/doc/src/ch_introduction.xml b/lib/cosTransactions/doc/src/ch_introduction.xml
deleted file mode 100644
index 43d25360bc..0000000000
--- a/lib/cosTransactions/doc/src/ch_introduction.xml
+++ /dev/null
@@ -1,65 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Introduction to cosTransactions</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>1999-04-26</date>
- <rev></rev>
- <file>ch_introduction.xml</file>
-</header>
-
- <section>
- <title>Overview</title>
- <p>The cosTransactions application is a Transaction Service compliant with the <url href="http://www.omg.org">OMG</url>
- Transaction Service CosTransactions 1.1.
- </p>
-
- <section>
- <title>Purpose and Dependencies</title>
- <p><em>cosTransactions</em> is dependent on <em>Orber version 3.0.1</em> or later(see the Orber
- documentation), which provides CORBA functionality in an Erlang environment.</p>
- <p><em>cosTransactions</em> is dependent on <em>supervisor/stdlib-1.7</em> or later.</p>
- <p>Basically, cosTransaction implements a <em>two-phase commit protocol</em> and allows objects running
- on different platforms to participate in a transaction.</p>
- </section>
-
- <section>
- <title>Prerequisites</title>
- <p>To fully understand the concepts presented in the
- documentation, it is recommended that the user is familiar
- with distributed programming, CORBA and the Orber application.
- </p>
- <p>Recommended reading includes <em>CORBA, Fundamentals and Programming - Jon Siegel</em> and <em>Open Telecom Platform Documentation Set</em>. It is also helpful to have read
- <em>Concurrent Programming in Erlang</em> and, for example, <em>Transaction Processing: concepts and techniques - Jim Gray, Andreas Reuter</em>.</p>
- <note>
- <p>The cosTransaction application is compliant with the OMG CosTransactions specification 1.1. Using
- other vendors transaction service, compliant with the OMG CosTransactions specification 1.0, may
- not work since the <c>'TRANSACTION_REQUIRED', 'TRANSACTION_ROLLEDBACK'</c> and <c>'INVALID_TRANSACTION'</c>
- exceptions have been redefined to be system exceptions, i.e., used to be transaction-specific ('CosTransactions_Exc').</p>
- </note>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosTransactions/doc/src/ch_skeletons.xml b/lib/cosTransactions/doc/src/ch_skeletons.xml
deleted file mode 100644
index e101cff5da..0000000000
--- a/lib/cosTransactions/doc/src/ch_skeletons.xml
+++ /dev/null
@@ -1,214 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Resource Skeletons</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>1999-04-29</date>
- <rev></rev>
- <file>ch_skeletons.xml</file>
- </header>
-
- <section>
- <title>Resource Skeletons</title>
- <p>This chapter provides a skeleton for application Resources. For more information
- see the Orber documentation.</p>
- <code type="none">
-%%%-----------------------------------------------------------
-%%% File : Module_Interface_impl.erl
-%%% Author :
-%%% Purpose :
-%%% Created :
-%%%-----------------------------------------------------------
-
--module('Module_Interface_impl').
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("cosTransactions/include/CosTransactions.hrl").
-
-%%--------------- EXPORTS-------------------------------------
-%%- Inherit from CosTransactions::Resource -------------------
--export([prepare/2,
- rollback/2,
- commit/2,
- commit_one_phase/2,
- forget/2]).
-
-%%- Inherit from CosTransactions::SubtransactionAwareResource
--export([commit_subtransaction/3,
- rollback_subtransaction/2]).
-
-%%--------------- gen_server specific ------------------------
--export([init/1, terminate/2, code_change/3, handle_info/2]).
-
-%%------------------------------------------------------------
-%% function : gen_server specific
-%%------------------------------------------------------------
-init(Env) ->
- %% 'trap_exit' optional
- process_flag(trap_exit,true),
-
- %%--- Possible replies ---
- %% Reply and await next request
- {ok, State}.
-
- %% Reply and if no more requests within Time the special
- %% timeout message should be handled in the
- %% Module_Interface_impl:handle_info/2 call-back function (use the
- %% IC option {{handle_info, "Module::Interface"}, true}).
- {ok, State, TimeOut}.
-
- %% Return ignore in order to inform the parent, especially if it is a
- %% supervisor, that the server, as an example, did not start in
- %% accordance with the configuration data.
- ignore.
-
- %% If the initializing procedure fails, the reason
- %% is supplied as StopReason.
- {stop, StopReason}.
-
-
-terminate(Reason, State) ->
- ok.
-
-code_change(OldVsn, State, Extra) ->
- {ok, NewState}.
-
-%% If use IC option {{handle_info, "Module::Interface"}, true}
-handle_info(Info, State) ->
- %%--- Possible replies ---
- %% Await the next invocation.
- {noreply, State}.
- %% Stop with Reason.
- {stop, Reason, State}.
-
-
-%%- Inherit from CosTransactions::Resource -------------------
-prepare(State) ->
-
- %%% Do application specific actions here %%%
-
- %%-- Reply: --
- %% If no data related to the transaction changed.
- {reply, 'VoteReadOnly', State}
- %% .. or (for example):
- {stop, normal, 'VoteReadOnly', State}.
-
- %% If able to commit
- {reply, 'VoteCommit', State}
-
- %% If not able to commit
- {reply, 'VoteRollback', State}
- %% .. or (for example):
- {stop, normal, 'VoteRollback', State}.
-
-rollback(State) ->
-
- %%% Do application specific actions here %%%
-
- %%-- Reply: --
- %% If able to rollback successfully
- {reply, ok, State}
- %% .. or (for example):
- {stop, normal, ok, State}.
-
- %% If Heuristic Decision. Raise exception:
- corba:raise(#'CosTransactions_HeuristicMixed' {})
- corba:raise(#'CosTransactions_HeuristicHazard' {})
- corba:raise(#'CosTransactions_HeuristicCommit'{})
-
-
-commit(State) ->
-
- %%% Do application specific actions here %%%
-
- %%-- Reply: --
- %% If able to commit successfully
- {reply, ok, State}
- %% .. or (for example):
- {stop, normal, ok, State}.
-
- %% If the prepare operation never been invoked:
- corba:raise(#'CosTransactions_NotPrepared'{})
-
- %% If Heuristic Decision. Raise exception:
- corba:raise(#'CosTransactions_HeuristicMixed' {})
- corba:raise(#'CosTransactions_HeuristicHazard' {})
- corba:raise(#'CosTransactions_HeuristicRollback'{})
-
-
-commit_one_phase(State) ->
-
- %%% Do application specific actions here %%%
-
- %%-- Reply: --
- %% If able to commit successfully
- {reply, ok, State}
- %% .. or (for example):
- {stop, normal, ok, State}.
-
- %% If fails. Raise exception:
- corba:raise(#'CosTransactions_HeuristicHazard' {})
-
- %% If able to rollback successfully
- corba:raise(#'CosTransactions_TransactionRolledBack' {})
-
-
-forget(State) ->
-
- %%% Do application specific actions here %%%
-
- %%-- Reply: --
- {reply, ok, State}.
- %% .. or (for example):
- {stop, normal, ok, State}.
-
-
-
-%%%%%% If the Resource is also supposed to be a %%%%%%
-%%%%%% SubtransactionAwareResource implement these. %%%%%%
-
-%%- Inherit from CosTransactions::SubtransactionAwareResource
-commit_subtransaction(State, Parent) ->
- %%% Do application specific actions here %%%
-
- %%-- Reply: --
- {reply, ok, State}.
- %% .. or (for example):
- {stop, normal, ok, State}.
-
-rollback_subtransaction(State) ->
- %%% Do application specific actions here %%%
-
- %%-- Reply: --
- {reply, ok, State}.
- %% .. or (for example):
- {stop, normal, ok, State}.
-
-%%--------------- END OF MODULE ------------------------------
- </code>
- </section>
-</chapter>
-
diff --git a/lib/cosTransactions/doc/src/cosTransactions.xml b/lib/cosTransactions/doc/src/cosTransactions.xml
deleted file mode 100644
index 772baaf18a..0000000000
--- a/lib/cosTransactions/doc/src/cosTransactions.xml
+++ /dev/null
@@ -1,142 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1999</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>cosTransactions</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved>Niclas Eklund</approved>
- <checked></checked>
- <date>1999-04-23</date>
- <rev>PA1</rev>
- </header>
- <module>cosTransactions</module>
- <modulesummary>The main module of the cosTransactions application.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-<c>-include_lib("cosTransactions/include/CosTransactions.hrl").</c></p>
- <p>This module contains the functions for starting and stopping the application.
- If the application is started using <c>application:start(cosTransactions)</c> the
- default configuration is used (see listing below). The Factory reference is stored using the CosNaming Service
- under the id <c>"oe_cosTransactionsFac_IPNo"</c>.</p>
- <p>The following application configuration parameters exist:</p>
- <list type="bulleted">
- <item><em>maxRetries</em> - default is 40 times, i.e., if a transaction participant is unreachable
- the application will retry to contact it <c>N</c> times. Reaching the maximum is considered to be a disaster.</item>
- <item><em>comFailWait</em> - default is 5000 milliseconds, i.e., before the application
- retries to contact unreachable transaction participants the application wait <c>Time</c> milliseconds.</item>
- </list>
- </description>
- <funcs>
- <func>
- <name>start() -> Return</name>
- <fsummary>Start the cosTransactions application</fsummary>
- <type>
- <v>Return = ok | {error, Reason}</v>
- </type>
- <desc>
- <p>This operation starts the cosTransactions application.</p>
- </desc>
- </func>
- <func>
- <name>stop() -> Return</name>
- <fsummary>Stop the cosTransactions application</fsummary>
- <type>
- <v>Return = ok | {error, Reason}</v>
- </type>
- <desc>
- <p>This operation stops the cosTransactions application.</p>
- </desc>
- </func>
- <func>
- <name>start_factory() -> TransactionFactory</name>
- <fsummary>Start a <c>Transaction Factory</c></fsummary>
- <type>
- <v>TransactionFactory = #objref</v>
- </type>
- <desc>
- <p>This operation creates a <seealso marker="CosTransactions_TransactionFactory">Transaction Factory</seealso>.
- The Factory is used to create a new top-level <seealso marker="CosTransactions_Control">transaction</seealso> using default options (see listing below).</p>
- </desc>
- </func>
- <func>
- <name>start_factory(FacDef) -> TransactionFactory</name>
- <fsummary>Start a <c>Transaction Factory</c>with given options</fsummary>
- <type>
- <v>FacDef = [Options], see Option listing below.</v>
- <v>TransactionFactory = #objref</v>
- </type>
- <desc>
- <p>This operation creates a <seealso marker="CosTransactions_TransactionFactory">Transaction Factory</seealso>.
- The Factory is used to create a new top-level transaction. </p>
- <p>The FacDef list must be a list of {Item, Value} tuples,
- where the following values are allowed: </p>
- <list type="bulleted">
- <item>{hash_max, HashValue} -
- This value denotes the upper bound of the hash value the
- <seealso marker="CosTransactions_Coordinator">Coordinator</seealso> uses.
- Default is <c>1013</c>. HashValue must be an integer.</item>
- <item>{allow_subtr, Boolean} -
- If set to true it is possible to create <seealso marker="CosTransactions_Coordinator">subtransactions</seealso>.
- Default is <c>true</c>.</item>
- <item>{typecheck, Boolean} -
- If set to to true all transaction operation's arguments will be type-checked.
- Default is <c>true</c>.</item>
- <item>{tty, Boolean} -
- Enables or disables error printouts to the tty.
- If Flag is false, all text that the error logger would have sent to the terminal is discarded.
- If Flag is true, error messages are sent to the terminal screen. </item>
- <item>{logfile, FileName} -
- This function makes it possible to store all system information in <c>FileName</c> (string()).
- It can be used in combination with the tty(false) item in to have a silent system,
- where all system information are logged to a file.
- As default no logfile is used.</item>
- <item><c>{maxRetries, Integer}</c> -
- default is 40 times, i.e., if a transaction participant is unreachable the application will
- retry to contact it <c>N</c> times. Reaching the maximum is considered to be a disaster.
- This option overrides the application configuration parameter.</item>
- <item><c>{comFailWait, Integer}</c> -
- default is 5000 milliseconds, i.e., before the application retries to contact unreachable
- transaction participants the application wait <c>Time</c> milliseconds.
- This option overrides the application configuration parameter.</item>
- </list>
- </desc>
- </func>
- <func>
- <name>stop_factory(TransactionFactory) -> Reply</name>
- <fsummary>Terminate the target object</fsummary>
- <type>
- <v>TransactionFactory = #objref</v>
- <v>Reply = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This operation stop the target transaction factory.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/cosTransactions/doc/src/fascicules.xml b/lib/cosTransactions/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/cosTransactions/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/cosTransactions/doc/src/notes.gif b/lib/cosTransactions/doc/src/notes.gif
deleted file mode 100644
index e000cca26a..0000000000
--- a/lib/cosTransactions/doc/src/notes.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosTransactions/doc/src/notes.xml b/lib/cosTransactions/doc/src/notes.xml
deleted file mode 100644
index 85ace1208b..0000000000
--- a/lib/cosTransactions/doc/src/notes.xml
+++ /dev/null
@@ -1,392 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosTransactions Release Notes</title>
- <prepared>Niclas Eklund</prepared>
- <responsible>Niclas Eklund</responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>99-04-14</date>
- <rev>A</rev>
- <file>notes.xml</file>
- </header>
-
- <section><title>cosTransactions 1.3.2</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Internal changes</p>
- <p>
- Own Id: OTP-13551</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosTransactions 1.3.1</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> Suppress Dialyzer warnings. </p>
- <p>
- Own Id: OTP-12862</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosTransactions 1.3</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> Remove the usage of erlang:now() from all Corba
- applications and use the new rand module instead of
- random. </p>
- <p>
- Own Id: OTP-12687</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosTransactions 1.2.14</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> The default encoding of Erlang files has been changed
- from ISO-8859-1 to UTF-8. </p> <p> The encoding of XML
- files has also been changed to UTF-8. </p>
- <p>
- Own Id: OTP-10907</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosTransactions 1.2.13</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Misc build updates</p>
- <p>
- Own Id: OTP-10784</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>cosTransactions 1.2.12</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>Erlang/OTP can now be built using parallel make if you
- limit the number of jobs, for instance using '<c>make
- -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
- work at the moment because of some missing
- dependencies.</p>
- <p>
- Own Id: OTP-9451</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section>
- <title>cosTransactions 1.2.11</title>
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Removed superfluous usage of shy in the documentation since it can cause problem if
- a buggy tool is used.</p>
- <p>
- Own Id: OTP-9319 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTransactions 1.2.10</title>
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Test suites published.</p>
- <p>
- Own Id: OTP-8543 Aux Id:</p>
- </item>
- </list>
- </section>
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>Added missing trailing bracket to define in hrl-file.</p>
- <p>Own id: OTP-8489 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTransactions 1.2.9</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The documentation EIX file was not generated.</p>
- <p>Own id: OTP-8355 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTransactions 1.2.8</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- The documentation is now built with open source tools (xsltproc and fop)
- that exists on most platforms. One visible change is that the frames are removed.</p>
- <p>
- Own Id: OTP-8201 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTransactions 1.2.7</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Obsolete guards, e.g. record vs is_record, has been changed
- to avoid compiler warnings.</p>
- <p>Own id: OTP-7987</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTransactions 1.2.6</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Updated file headers.</p>
- <p>Own id: OTP-7837</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTransactions 1.2.5</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Documentation source included in open source releases.</p>
- <p>Own id: OTP-7595</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTransactions 1.2.4</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Updated file headers.</p>
- <p>Own id: OTP-7011</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTransactions 1.2.3</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The documentation source has been converted from SGML to XML.</p>
- <p>Own id: OTP-6754 Aux Id: </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTransactions 1.2.2</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Minor Makefile changes.</p>
- <p>Own id: OTP-6701 Aux Id: </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTransactions 1.2.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Removed some unused code.</p>
- <p>Own id: OTP-6527 Aux Id: </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTransactions 1.2</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The stub/skeleton-files generated by IC have been improved,
- i.e., depending on the IDL-files, reduced the size of the
- erl- and beam-files and decreased dependencies off Orber's
- Interface Repository. It is necessary to re-compile all IDL-files
- and use COS-applications, including Orber, compiled with
- IC-4.2.</p>
- <p>Own id: OTP-4576</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTransactions 1.1.2</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>To avoid un-necessary Heuristic decisions cosTransactions now
- recognize more systems exceptions.</p>
- <p>Own Id: OTP-4485</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTransactions 1.1.1.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Updated internal documentation.</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTransactions 1.1.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>cosTransactions is now able to handle upgrade properly.</p>
- <p>Own Id: -</p>
- </item>
- <item>
- <p>The cosTransactions factory now accepts <c>maxRetries</c> and
- <c>comFailWait</c> options, which overrides the configuration parameters.</p>
- <p>Own Id: -</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <list type="bulleted">
- <item>
- <p>The configuration parameters <c>comm_failure_wait</c> and <c>max_retries</c>
- changed to <c>maxRetries</c> and <c>comFailWait</c>. The default value for
- <c>maxRetries</c> have been raised from 20 to 40.</p>
- <p>Own Id: -</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>cosTransactions 1.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>First release of the cosTransactions application.</p>
- <p>Own Id: OTP-1741</p>
- </item>
- </list>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/cosTransactions/doc/src/part.xml b/lib/cosTransactions/doc/src/part.xml
deleted file mode 100644
index 6777d7d979..0000000000
--- a/lib/cosTransactions/doc/src/part.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosTransactions User's Guide</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>1999-04-20</date>
- <rev>2.2</rev>
- </header>
- <description>
- <p>The <em>cosTransactions</em> application is an Erlang implementation
- of the OMG CORBA Transaction Service.</p>
- </description>
- <xi:include href="ch_contents.xml"/>
- <xi:include href="ch_introduction.xml"/>
- <xi:include href="ch_install.xml"/>
- <xi:include href="ch_example.xml"/>
- <xi:include href="ch_skeletons.xml"/>
-</part>
-
diff --git a/lib/cosTransactions/doc/src/part_notes.xml b/lib/cosTransactions/doc/src/part_notes.xml
deleted file mode 100644
index 48cc04aa4c..0000000000
--- a/lib/cosTransactions/doc/src/part_notes.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosTransactions Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date>1999-04-14</date>
- <rev>2.0</rev>
- </header>
- <description>
- <p>The cosTransactions Application is an Erlang implementation of the OMG
- CORBA Transaction Service.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/cosTransactions/doc/src/ref_man.gif b/lib/cosTransactions/doc/src/ref_man.gif
deleted file mode 100644
index b13c4efd53..0000000000
--- a/lib/cosTransactions/doc/src/ref_man.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosTransactions/doc/src/ref_man.xml b/lib/cosTransactions/doc/src/ref_man.xml
deleted file mode 100644
index 9d296967b3..0000000000
--- a/lib/cosTransactions/doc/src/ref_man.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE application SYSTEM "application.dtd">
-
-<application xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>cosTransactions Reference Manual</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>1999-04-14</date>
- <rev>2.0</rev>
- </header>
- <description>
- <p>The <em>cosTransactions</em> application is an Erlang implementation
- of the OMG CORBA Transaction Service.</p>
- </description>
- <xi:include href="cosTransactions.xml"/>
- <xi:include href="CosTransactions_Control.xml"/>
- <xi:include href="CosTransactions_Coordinator.xml"/>
- <xi:include href="CosTransactions_RecoveryCoordinator.xml"/>
- <xi:include href="CosTransactions_Resource.xml"/>
- <xi:include href="CosTransactions_SubtransactionAwareResource.xml"/>
- <xi:include href="CosTransactions_Terminator.xml"/>
- <xi:include href="CosTransactions_TransactionFactory.xml"/>
-</application>
-
diff --git a/lib/cosTransactions/doc/src/summary.html.src b/lib/cosTransactions/doc/src/summary.html.src
deleted file mode 100644
index 8fb7d6ea20..0000000000
--- a/lib/cosTransactions/doc/src/summary.html.src
+++ /dev/null
@@ -1 +0,0 @@
-Orber OMG Transaction Service \ No newline at end of file
diff --git a/lib/cosTransactions/doc/src/user_guide.gif b/lib/cosTransactions/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/cosTransactions/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/cosTransactions/ebin/.gitignore b/lib/cosTransactions/ebin/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosTransactions/ebin/.gitignore
+++ /dev/null
diff --git a/lib/cosTransactions/examples/Makefile b/lib/cosTransactions/examples/Makefile
deleted file mode 100644
index 57a51f5932..0000000000
--- a/lib/cosTransactions/examples/Makefile
+++ /dev/null
@@ -1,158 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-
-EBIN= ../ebin
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(COSTRANSACTIONS_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/cosTransactions-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-INETRC_EXAMPLE = \
-# inetrc
-
-IDL_FILES = \
-# hotel.idl \
-# travelAgency.idl
-
-GEN_ERL_MODULES = \
-# oe_travelAgency \
-# travelAgency_book \
-
-MODULES= \
-# travelAgency_book_impl \
-
-GEN_HRL_FILES = \
-# oe_travelAgency.hrl \
-# travelAgency_book.hrl
-
-HRL_FILES=
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-JAVA_CLASSES = \
-# HotelResource
-
-JAVA_FILES= $(JAVA_CLASSES:%=%.java)
-CLASS_FILES= $(JAVA_CLASSES:%=%.class)
-
-TARGET_FILES = \
- $(GEN_ERL_MODULES:%=$(EBIN)/%.$(EMULATOR)) \
- $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-
-ifeq ($(findstring sparc-sun-solaris2, $(TARGET)),sparc-sun-solaris2)
- JAVA_TARGET=java
-endif
-
-# ----------------------------------------------------
-# PROGRAMS
-# ----------------------------------------------------
-JAVA_IDL = idl
-LOCAL_CLASSPATH = $(ERL_TOP)/lib/cosTransactions/priv:$(ERL_TOP)/lib/cosTransactions/examples/java_output:$(ERL_TOP)/lib/cosTransactions/src:$(ERL_TOP)/lib/cosTransactions/examples:$(ERL_TOP)/lib/cosTransactions/examples/java_output/hotel
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += -pa /clearcase/otp/libraries/cosTransactions/ebin -pa /clearcase/otp/libraries/ic/ebin
-# includes from other directories than ../include .
-ERL_COMPILE_FLAGS += \
- $(ERL_IDL_FLAGS) \
- -pa /clearcase/otp/libraries/cosTransactions -I/clearcase/otp/libraries/cosTransactions
-YRL_FLAGS =
-
-JAVA_OPTIONS = -classpath ../priv:/opt/local/pgm/OrbixWeb2.0.1
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-tests debug opt: $(TARGET_FILES) $(JAVA_TARGET)
-
-java: java_costransactions_idl java_objects
-# java_hotel_idl
-
-clean:
- rm -f $(TARGET_FILES) $(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES) $(CLASS_FILES)
- rm -rf java_costransactions_idl
- rm -rf java_output/*
- rm -f errs core *~
-# rm -rf java_hotel_idl
-
-docs:
-
-java_costransactions_idl:
- $(JAVA_IDL) ../src/CosTransactions.idl
- @if [ -d java_output ]; then \
- echo "compiling java classes for CosTransactions ... This will take a while!!"; \
- CLASSPATH="${CLASSPATH}:${LOCAL_CLASSPATH}"; \
- export CLASSPATH;\
- (cd java_output/CosTransactions; $(JAVA) *.java;); \
- fi
- @touch java_costransactions_idl
-
-#java_hotel_idl:
-# $(JAVA_IDL) hotel.idl
-# @if [ -d java_output ]; then \
-# echo "compiling java classes for hotel ..."; \
-# CLASSPATH="${CLASSPATH}:${LOCAL_CLASSPATH}"; \
-# export CLASSPATH;\
-# (cd java_output/hotel; $(JAVA) *.java;); \
-# fi
-# @touch java_hotel_idl
-
-#java_objects:
-# @if [ -d java_output ]; then \
-# echo "compiling java example files ..."; \
-# CLASSPATH="${CLASSPATH}:${LOCAL_CLASSPATH}"; \
-# export CLASSPATH;\
-# $(JAVA) *.java; \
-# fi
-# @touch java_hotel_resource
-
-#oe_travelAgency.erl: travelAgency.idl
-# erlc $(ERL_IDL_FLAGS) travelAgency.idl
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/examples"
- $(INSTALL_DATA) $(ERL_FILES) $(JAVA_FILES) $(IDL_FILES) "$(RELSYSDIR)/examples"
- $(INSTALL_DATA) $(INETRC_EXAMPLE) "$(RELSYSDIR)/examples"
- @tar cf - java_output | (cd $(RELSYSDIR); tar xf -)
-
-release_docs_spec:
diff --git a/lib/cosTransactions/include/.gitignore b/lib/cosTransactions/include/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosTransactions/include/.gitignore
+++ /dev/null
diff --git a/lib/cosTransactions/info b/lib/cosTransactions/info
deleted file mode 100644
index e5d7c53ac0..0000000000
--- a/lib/cosTransactions/info
+++ /dev/null
@@ -1,2 +0,0 @@
-group: orb
-short: Orber OMG Transaction Service
diff --git a/lib/cosTransactions/priv/.gitignore b/lib/cosTransactions/priv/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/cosTransactions/priv/.gitignore
+++ /dev/null
diff --git a/lib/cosTransactions/src/CosTransactions.cfg b/lib/cosTransactions/src/CosTransactions.cfg
deleted file mode 100644
index 05709d21cf..0000000000
--- a/lib/cosTransactions/src/CosTransactions.cfg
+++ /dev/null
@@ -1,15 +0,0 @@
-{this, "CosTransactions::Coordinator"}.
-{this, "CosTransactions::RecoveryCoordinator"}.
-{this, "CosTransactions::Terminator"}.
-{this, "CosTransactions::Control"}.
-{this, "CosTransactions::Resource"}.
-{this, "CosTransactions::TransactionFactory"}.
-{{handle_info, "CosTransactions::Terminator"}, true}.
-{{handle_info, "CosTransactions::TransactionFactory"}, true}.
-{this, "ETraP::Server"}.
-{{handle_info, "ETraP::Server"}, true}.
-{{impl, "CosTransactions::Coordinator"}, "ETraP_Server_impl"}.
-{{impl, "CosTransactions::RecoveryCoordinator"}, "ETraP_Server_impl"}.
-{{impl, "CosTransactions::Control"}, "ETraP_Server_impl"}.
-{{impl, "CosTransactions::Resource"}, "ETraP_Server_impl"}.
-{timeout,"CosTransactions::RecoveryCoordinator"}.
diff --git a/lib/cosTransactions/src/CosTransactions.idl b/lib/cosTransactions/src/CosTransactions.idl
deleted file mode 100644
index 11ec5cbf5b..0000000000
--- a/lib/cosTransactions/src/CosTransactions.idl
+++ /dev/null
@@ -1,193 +0,0 @@
-#ifndef _COSTRANSACTIONS_IDL
-#define _COSTRANSACTIONS_IDL
-
-#pragma prefix "omg.org"
-
-module CosTransactions {
-
-// DATATYPES
- enum Status {
- StatusActive,
- StatusMarkedRollback,
- StatusPrepared,
- StatusCommitted,
- StatusRolledBack,
- StatusUnknown,
- StatusNoTransaction,
- StatusPreparing,
- StatusCommitting,
- StatusRollingBack
- };
-
- enum Vote {
- VoteCommit,
- VoteRollback,
- VoteReadOnly
- };
-
- // Forward references for interfaces defined later in module
- interface Control;
- interface Terminator;
- interface Coordinator;
- interface Resource;
- interface RecoveryCoordinator;
- interface SubtransactionAwareResource;
- interface TransactionFactory;
- interface TransactionalObject;
- // interface Synchronization;
-
- // Structure definitions
- struct otid_t {
- long formatID; /*format identifier. 0 is OSI TP */
- long bqual_length;
- sequence <octet> tid;
- };
- struct TransIdentity {
- Coordinator coord;
- Terminator term;
- otid_t otid;
- };
- struct PropagationContext {
- unsigned long timeout;
- TransIdentity current;
- sequence <TransIdentity> parents;
- any implementation_specific_data;
- };
- // interface Current;
-
- // Standard exceptions
- // Defined in orber/include/corba.hrl
- // exception TransactionRequired {};
- // exception TransactionRolledBack {};
- // exception InvalidTransaction {};
-
- // Heuristic exceptions
- exception HeuristicRollback {};
- exception HeuristicCommit {};
- exception HeuristicMixed {};
- exception HeuristicHazard {};
-
- // Exception from Orb operations
- exception WrongTransaction {};
-
- // Other transaction-specific exceptions
- exception SubtransactionsUnavailable {};
- exception NotSubtransaction {};
- exception Inactive {};
- exception NotPrepared {};
- exception NoTransaction {};
- exception InvalidControl {};
- exception Unavailable {};
- exception SynchronizationUnavailable {};
-
- interface TransactionFactory {
- Control create(in unsigned long time_out);
- Control recreate(in PropagationContext ctx);
- };
-
- interface Control {
- Terminator get_terminator()
- raises(Unavailable);
- Coordinator get_coordinator()
- raises(Unavailable);
- };
-
- interface Terminator {
- void commit(in boolean report_heuristics)
- raises( HeuristicMixed,
- HeuristicHazard );
- void rollback();
- };
-
- interface Coordinator {
-
- Status get_status();
- Status get_parent_status();
- Status get_top_level_status();
-
- boolean is_same_transaction(in Coordinator tc);
- boolean is_related_transaction(in Coordinator tc);
- boolean is_ancestor_transaction(in Coordinator tc);
- boolean is_descendant_transaction(in Coordinator tc);
- boolean is_top_level_transaction();
-
- unsigned long hash_transaction();
- unsigned long hash_top_level_tran();
-
- RecoveryCoordinator register_resource(in Resource r)
- raises(Inactive);
-
-// void register_synchronization (in Synchronization sync)
-// raises(Inactive, SynchronizationUnavailable);
-
- void register_subtran_aware(in SubtransactionAwareResource r)
- raises(Inactive, NotSubtransaction);
-
- void rollback_only()
- raises(Inactive);
-
- string get_transaction_name();
- Control create_subtransaction()
- raises(SubtransactionsUnavailable, Inactive);
-
- PropagationContext get_txcontext ()
- raises(Unavailable);
- };
-
-
- interface RecoveryCoordinator {
- Status replay_completion(in Resource r)
- raises(NotPrepared);
- };
-
- interface Resource {
- Vote prepare()
- raises(HeuristicMixed,
- HeuristicHazard);
- void rollback()
- raises( HeuristicCommit,
- HeuristicMixed,
- HeuristicHazard );
- void commit()
- raises( NotPrepared,
- HeuristicRollback,
- HeuristicMixed,
- HeuristicHazard );
- void commit_one_phase()
- raises( HeuristicHazard,
- HeuristicRollback,
- HeuristicMixed);
- void forget();
- };
-
-// interface TransactionalObject {
-// };
-
-// interface Synchronization : TransactionalObject {
-// void before_completion();
-// void after_completion(in CosTransactions::Status status);
-// };
-
- interface SubtransactionAwareResource : Resource {
- void commit_subtransaction(in Coordinator parent);
- void rollback_subtransaction();
- };
-
-}; // End of CosTransactions Module
-
-module ETraP {
-
- // interface Server
- interface Server :
- CosTransactions::Coordinator, CosTransactions::Resource,
- CosTransactions::RecoveryCoordinator, CosTransactions::Control {
- };
-// interface Server :
-// CosTransactions::Coordinator, CosTransactions::Resource,
-// CosTransactions::RecoveryCoordinator, CosTransactions::Control,
-// CosTransactions::Synchronization {
-// };
-
-}; // End of ETraP Module
-
-#endif
diff --git a/lib/cosTransactions/src/CosTransactions_Terminator_impl.erl b/lib/cosTransactions/src/CosTransactions_Terminator_impl.erl
deleted file mode 100644
index d995eb64e4..0000000000
--- a/lib/cosTransactions/src/CosTransactions_Terminator_impl.erl
+++ /dev/null
@@ -1,363 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosTransactions_Terminator_impl.erl
-%% Purpose : Support operations to commit or roll-back a transaction.
-%%----------------------------------------------------------------------
-
--module('CosTransactions_Terminator_impl').
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
-%% Local
--include_lib("ETraP_Common.hrl").
--include_lib("CosTransactions.hrl").
-
-%%--------------- IMPORTS-------------------------------------
--import(etrap_logmgr, [log_safe/2, get_next/2]).
-
-%%--------------- EXPORTS-------------------------------------
-%%-compile(export_all).
--export([commit/3, rollback/2]).
--export([init/1, terminate/2]).
--export([handle_call/3, handle_cast/2, handle_info/2, code_change/3]).
-
-%%--------------- LOCAL DATA ---------------------------------
-%-record(terminator, {reg_resources, rollback_only, regname, coordinator}).
-
-%%------------------------------------------------------------
-%% function : init, terminate
-%% Arguments:
-%% Returns :
-%% Effect : Functions demanded by the module ic. Used to initiate
-%% and terminate a gen_server.
-%%------------------------------------------------------------
-
-init(State) ->
- process_flag(trap_exit,true),
- case catch start_object(State) of
- {'EXIT', Reason} ->
- %% Happens when, for example, we encounter an
- %% error when reading from the log file.
- {stop, Reason};
- Other ->
- Other
- end.
-
-start_object(State) ->
- case catch file:read_file_info(?tr_get_terminator(State)) of
- {error, enoent} ->
- %% File does not exist. It's the first time. No restart.
- ?debug_print("Terminator:init(~p)~n", [?tr_get_terminator(State)]),
- etrap_logmgr:start(?tr_get_terminator(State)),
- {ok, State, ?tr_get_timeout(State)};
- {error, Reason} -> % File exist but error occurred.
- ?tr_error_msg("CosTransactions_Terminator( ~p ) Cannot open log file: ~p~n",
- [?tr_get_terminator(State), Reason]),
- {stop, {error, "unable_to_open_log"}};
- _ -> % File exists, perform restart.
- etrap_logmgr:start(?tr_get_terminator(State)),
- ?debug_print("RESTART Terminator:init(~p)~n",
- [?tr_get_terminator(State)]),
- do_restart(State, get_next(?tr_get_terminator(State), start), init)
- end.
-
-
-terminate(Reason, State) ->
- ?debug_print("STOP ~p ~p~n", [?tr_get_terminator(State), Reason]),
- case Reason of
- normal ->
- %% normal termination. Transaction completed.
- log_safe(?tr_get_terminator(State), done),
- etrap_logmgr:stop(?tr_get_terminator(State)),
- file:delete(?tr_get_terminator(State)),
- ok;
- _ ->
- ok
- end.
-
-%%------------------------------------------------------------
-%% function : handle_call, handle_cast, handle_info, code_change
-%% Arguments:
-%% Returns :
-%% Effect : Functions demanded by the module ic.
-%%------------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-handle_call(_,_, State) ->
- {noreply, State}.
-
-
-handle_cast(_, State) ->
- {noreply, State}.
-
-
-handle_info(Info, State) ->
- ?debug_print("Terminator:handle_info(~p)~n", [Info]),
- Pid = self(),
- case Info of
- timeout ->
- ?tr_error_msg("Object( ~p ) timeout. Rolling back.~n",
- [?tr_get_terminator(State)]),
- {stop, normal, State};
- {suicide, Pid} ->
- {stop, normal, State};
- _->
- {noreply, State}
- end.
-
-%%------------------------------------------------------------
-%% function : commit
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% Heuristics - boolean; report heuristic decisions?
-%% Returns : ok - equal to void
-%% Effect :
-%% Exception: HeuristicMixed - Highest priority
-%% HeuristicHazard - Lowest priority
-%%------------------------------------------------------------
-
-commit(_Self, State, _Heuristics) when ?tr_is_retransmit(State) ->
- ?debug_print("Terminator:commit() recalled.~n", []),
- {stop, normal, ?tr_get_reportH(State), State};
-commit(Self, State, Heuristics) ->
- ?debug_print("Terminator:commit() called.~n", []),
- NewState = ?tr_set_reportH(State, Heuristics),
- log_safe(?tr_get_terminator(NewState), {init_commit, NewState}),
- transmit(Self, NewState, Heuristics).
-
-
-transmit(Self, State, Heuristics) ->
- case catch 'ETraP_Common':try_timeout(?tr_get_alarm(State)) of
- false ->
-% catch 'ETraP_Server':before_completion(?tr_get_etrap(State)),
- case catch 'CosTransactions_Resource':prepare(?tr_get_etrap(State)) of
- 'VoteCommit' ->
- evaluate_answer(Self, State, Heuristics,
- 'ETraP_Common':try_timeout(?tr_get_alarm(State)));
- 'VoteRollback' ->
- {stop, normal,
- {'EXCEPTION',
- #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
- State};
- 'VoteReadOnly' ->
- {stop, normal, ok, State};
- {'EXCEPTION', E} when is_record(E,'CosTransactions_HeuristicMixed'),
- Heuristics==true->
- catch 'ETraP_Server':forget(?tr_get_etrap(State)),
- {stop, normal, {'EXCEPTION', E}, State};
- {'EXCEPTION', E} when is_record(E,'CosTransactions_HeuristicHazard'),
- Heuristics==true->
- catch 'ETraP_Server':forget(?tr_get_etrap(State)),
- {stop, normal, {'EXCEPTION', E}, State};
- {'EXCEPTION', E} when is_record(E,'CosTransactions_HeuristicMixed') ->
- catch 'ETraP_Server':forget(?tr_get_etrap(State)),
- {stop, normal,
- {'EXCEPTION',#'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
- State};
- {'EXCEPTION', E} when is_record(E,'CosTransactions_HeuristicHazard') ->
- catch 'ETraP_Server':forget(?tr_get_etrap(State)),
- {stop, normal,
- {'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
- State};
- Other ->
- ?tr_error_msg("Coordinator:prepare( ~p ) failed. REASON ~p~n",
- [?tr_get_etrap(State), Other]),
- {stop, normal,
- {'EXCEPTION',
- #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
- State}
- end;
- _ ->
- %% Timeout, rollback.
- log_safe(?tr_get_terminator(State), rolled_back),
- catch 'ETraP_Server':rollback(?tr_get_etrap(State)),
-% catch 'ETraP_Server':after_completion(?tr_get_etrap(State),
-% 'StatusRolledBack'),
- {stop, normal,
- {'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
- State}
- end.
-
-evaluate_answer(Self, State, Heuristics, false) ->
- evaluate_answer(Self, State, Heuristics, commit);
-evaluate_answer(Self, State, Heuristics, true) ->
- evaluate_answer(Self, State, Heuristics, rollback);
-evaluate_answer(_Self, State, Heuristics, Vote) ->
- case catch 'ETraP_Common':send_stubborn('ETraP_Server', Vote,
- ?tr_get_etrap(State),
- ?tr_get_maxR(State),
- ?tr_get_maxW(State)) of
- ok ->
- ?eval_debug_fun({_Self, commit_ok1}, State),
- log_safe(?tr_get_terminator(State), committed),
- ?eval_debug_fun({_Self, commit_ok2}, State),
-% catch 'ETraP_Server':after_completion(?tr_get_etrap(State),
-% 'StatusCommitted'),
- {stop, normal, ok, State};
- {'EXCEPTION', E} when Heuristics == true andalso
- is_record(E,'CosTransactions_HeuristicMixed') ->
- log_safe(?tr_get_terminator(State), {heuristic, State, E}),
- ?eval_debug_fun({_Self, commit_heuristic1}, State),
- catch 'ETraP_Server':forget(?tr_get_etrap(State)),
-% catch 'ETraP_Server':after_completion(?tr_get_etrap(State),
-% 'StatusRolledBack'),
- {stop, normal, {'EXCEPTION', E}, State};
- {'EXCEPTION', E} when Heuristics == true andalso
- is_record(E, 'CosTransactions_HeuristicHazard') ->
- log_safe(?tr_get_terminator(State), {heuristic, State, E}),
- catch 'ETraP_Server':forget(?tr_get_etrap(State)),
-% catch 'ETraP_Server':after_completion(?tr_get_etrap(State),
-% 'StatusRolledBack'),
- {stop, normal, {'EXCEPTION', E}, State};
- {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') ->
- log_safe(?tr_get_terminator(State), rolled_back),
- {stop, normal, {'EXCEPTION', ?tr_hazard}, State};
- {'EXCEPTION', E} when is_record(E, 'TRANSACTION_ROLLEDBACK') ->
- log_safe(?tr_get_terminator(State), rolled_back),
-% catch 'ETraP_Server':after_completion(?tr_get_etrap(State),
-% 'StatusRolledBack'),
- {stop, normal, {'EXCEPTION', E}, State};
- {'EXCEPTION', E} when is_record(E, 'CosTransactions_HeuristicCommit') ->
- catch 'ETraP_Server':forget(?tr_get_etrap(State)),
-% catch 'ETraP_Server':after_completion(?tr_get_etrap(State),
-% 'StatusRolledBack'),
- {stop, normal, ok, State};
- {'EXCEPTION', E} when is_record(E, 'CosTransactions_HeuristicRollback') ->
- catch 'ETraP_Server':forget(?tr_get_etrap(State)),
-% catch 'ETraP_Server':after_completion(?tr_get_etrap(State),
-% 'StatusCommitted'),
- {stop, normal,
- {'EXCEPTION',
- #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
- State};
- _Other when Heuristics == true ->
- log_safe(?tr_get_terminator(State), rolled_back),
-% catch 'ETraP_Server':after_completion(?tr_get_etrap(State),
-% 'StatusRolledBack'),
- {stop, normal, {'EXCEPTION', ?tr_hazard}, State};
- _Other ->
- log_safe(?tr_get_terminator(State), rolled_back),
-% catch 'ETraP_Server':after_completion(?tr_get_etrap(State),
-% 'StatusRolledBack'),
- {stop, normal, ok, State}
- end.
-
-%%-----------------------------------------------------------%
-%% function : rollback
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% Returns : ok - equal to void
-%% Effect :
-%%------------------------------------------------------------
-
-rollback(_Self, State) ->
- ?debug_print("Terminator:rollback() called.~n", []),
- log_safe(?tr_get_terminator(State), rolled_back),
- catch 'ETraP_Server':rollback(?tr_get_etrap(State)),
- {stop, normal, ok, State}.
-
-%%-----------------------------------------------------------%
-%% function : do_restart
-%% Arguments: State - server context
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-
-%% No data in file. Commit never initiated so we rollback (presumed rollback.
-do_restart(State, eof, init) ->
- log_safe(?tr_get_terminator(State), rolled_back),
- catch 'ETraP_Server':rollback(?tr_get_etrap(State)),
-% catch 'ETraP_Server':after_completion(?tr_get_etrap(State), 'StatusRolledBack'),
- self() ! {suicide, self()},
- {ok, State};
-
-do_restart(State, {error, Reason}, _) ->
- ?tr_error_msg("CosTransactions_Terminator (~p) failed. Cannot read log file: ~p~n",
- [?tr_get_terminator(State), Reason]),
- {stop, Reason};
-do_restart(State, eof, Phase) ->
- ?debug_print("Terminator:do_restart(~p)~n", [Phase]),
- case Phase of
- committed ->
- {ok, ?tr_set_reportH(State, ok)};
- rolled_back ->
- self() ! {suicide, self()},
- {ok, State};
- init_commit ->
- case catch corba_object:non_existent(?tr_get_etrap(State)) of
- true ->
- self() ! {suicide, self()},
- {ok, State};
- _->
- case transmit(false, State, ?tr_get_reportH(State)) of
- {stop, normal, ok, NewState} ->
- {ok, NewState};
- {stop, normal,
- {'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
- NewState} ->
- self() ! {suicide, self()},
- {ok, NewState};
- {stop, normal, {'EXCEPTION', Exc}, NewState} ->
- if
- ?tr_dont_reportH(State) ->
- self() ! {suicide, self()},
- {ok, NewState};
- true ->
- {ok, ?tr_set_reportH(NewState, Exc)}
- end
- end
- end;
- {heuristic, Exc} ->
- catch 'ETraP_Server':forget(?tr_get_etrap(State)),
-% catch 'ETraP_Server':after_completion(?tr_get_etrap(State),
-% 'StatusRolledBack'),
- if
- ?tr_dont_reportH(State) ->
- self() ! {suicide, self()},
- {ok, State};
- true ->
- {ok, ?tr_set_reportH(State, {'EXCEPTION',Exc})}
- end
- end;
-%% All done.
-do_restart(State, {done, _Cursor}, _Phase) ->
- ?debug_print("Terminator:do_restart(~p)~n", [_Phase]),
- self() ! {suicide, self()},
- {ok, State};
-do_restart(State, {rolled_back, Cursor}, _Phase) ->
- ?debug_print("Terminator:do_restart(~p)~n", [_Phase]),
- do_restart(State, get_next(?tr_get_terminator(State), Cursor), rolled_back);
-do_restart(State, {committed, Cursor}, _Phase) ->
- ?debug_print("Terminator:do_restart(~p)~n", [_Phase]),
- do_restart(State, get_next(?tr_get_terminator(State), Cursor), committed);
-do_restart(State, {{heuristic, SavedState, Exc}, Cursor}, _Phase) ->
- ?debug_print("Terminator:do_restart(~p)~n", [_Phase]),
- do_restart(SavedState, get_next(?tr_get_terminator(State), Cursor),
- {heuristic, Exc});
-do_restart(State, {{init_commit, SavedState}, Cursor}, _) ->
- ?debug_print("Terminator:do_restart(~p)~n", [init_commit]),
- do_restart(SavedState, get_next(?tr_get_terminator(State), Cursor), init_commit).
-
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosTransactions/src/CosTransactions_TransactionFactory_impl.erl b/lib/cosTransactions/src/CosTransactions_TransactionFactory_impl.erl
deleted file mode 100644
index e24bcb9a04..0000000000
--- a/lib/cosTransactions/src/CosTransactions_TransactionFactory_impl.erl
+++ /dev/null
@@ -1,180 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : CosTransactions_TransactionFactory_impl.erl
-%% Purpose : Is provided to allow the transaction originator to begin
-%% a transaction.
-%%----------------------------------------------------------------------
-
--module('CosTransactions_TransactionFactory_impl').
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
-
-%% Local
--include_lib("ETraP_Common.hrl").
--include_lib("CosTransactions.hrl").
-%%--------------- IMPORTS-------------------------------------
--import('ETraP_Common', [get_option/3]).
-
-%%--------------- EXPORTS-------------------------------------
--export([create/3, recreate/3, init/1, terminate/2]).
--export([handle_call/3, handle_cast/2, handle_info/2, code_change/3]).
-
-%%--------------- LOCAL DATA ---------------------------------
--record(factory, {hashMax, subtrOK, typeCheck, maxRetries, comFailWait}).
-
-%%--------------- LOCAL DEFINITIONS --------------------------
-
-%%------------------------------------------------------------
-%% function : init
-%% Arguments:
-%% Returns :
-%% Effect : Functions demanded by the module ic. Used to initiate
-%% a gen_server.
-%%------------------------------------------------------------
-
-init(Options) when is_list(Options) ->
- ?debug_print("Factory:init(~p)~n", [Options]),
- process_flag(trap_exit,true),
- DefaultValues = [{maxRetries, ?tr_max_retries},
- {comFailWait, ?tr_comm_failure_wait}|?tr_FAC_DEF],
- Hash = get_option(hash_max, Options, DefaultValues),
- SubtrOK = get_option(allow_subtr, Options, DefaultValues),
- TypeCheck = get_option(typecheck, Options, DefaultValues),
- TTY = get_option(tty, Options, DefaultValues),
- LogFile = get_option(logfile, Options, DefaultValues),
- MaxRetries = get_option(maxRetries, Options, DefaultValues),
- ComFailWait = get_option(comFailWait, Options, DefaultValues),
- error_logger:tty(TTY),
- case LogFile of
- false ->
- ok;
- _->
- error_logger:logfile({open, LogFile})
- end,
- {ok, #factory{typeCheck = TypeCheck, hashMax = Hash, subtrOK = SubtrOK,
- maxRetries = MaxRetries, comFailWait = ComFailWait}};
-
-init(Options) ->
- ?tr_error_msg("TransactionFactory~nBad argument: ~p~n", [Options]),
- corba:raise(?tr_badparam).
-
-
-%%------------------------------------------------------------
-%% function : terminate
-%% Arguments:
-%% Returns :
-%% Effect : Function demanded by the module ic. Used to
-%% terminate a gen_server.
-%%------------------------------------------------------------
-
-terminate(_Reason, _State) ->
- ?debug_print("Factory:terminate(~p)~n", [_Reason]),
- ok.
-
-%%------------------------------------------------------------
-%% function : handle_call, handle_cast, handle_info, code_change
-%% Arguments:
-%% Returns :
-%% Effect : Functions demanded by the module ic.
-%%------------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-handle_call(_,_, State) ->
- {noreply, State}.
-
-
-handle_cast(_, State) ->
- {noreply, State}.
-
-
-handle_info({'EXIT',_From,shutdown}, State) ->
- ?debug_print("Factory:handle_info(~p)~n", [shutdown]),
- {stop, shutdown, State};
-handle_info(_Info, State) ->
- ?debug_print("Factory:handle_info(~p)~n", [_Info]),
- {noreply, State}.
-
-%%------------------------------------------------------------
-%% function : create
-%% Arguments: TimeOut - rollback the transaction after TimeOut
-%% seconds. If 0 no timeout.
-%% Returns : a Control object
-%% Effect : Creates a new top-level transaction. The Control
-%% can be used to manage or control participation
-%% in the new transaction. Used for direct context
-%% management.
-%%------------------------------------------------------------
-
-create(_Self, State, TimeOut) when is_integer(TimeOut) ->
- %% Generate objectnames.
- ETraPName = 'ETraP_Common':create_name("root"),
- TermName = 'ETraP_Common':create_name("term"),
- EState = ?tr_create_context(ETraPName, TermName,
- State#factory.typeCheck,
- State#factory.hashMax,
- State#factory.subtrOK,
- State#factory.maxRetries,
- State#factory.comFailWait),
-
- case TimeOut of
- 0 ->
- ETraP = ?tr_start_child(?SUP_ETRAP(EState)),
- {reply, ETraP, State};
- _ ->
- if
- TimeOut > 0 ->
- TimeStampSec = erlang:monotonic_time(seconds),
- EState2 = ?tr_set_alarm(EState, TimeStampSec+TimeOut),
- EState3 = ?tr_set_timeout(EState2, TimeOut*1000),
- ETraP = ?tr_start_child(?SUP_ETRAP(EState3)),
- {reply, ETraP, State};
- true ->
- ?tr_error_msg("TransactionFactory:create( Integer >= 0 )~nBad argument. Not an integer.~n", []),
- corba:raise(?tr_badparam)
- end
- end;
-
-create(_Self, _State, _TimeOut) ->
- ?tr_error_msg("TransactionFactory:create( Integer >= 0 )~nBad argument. Not an integer.~n", []),
- corba:raise(?tr_badparam).
-
-
-%%------------------------------------------------------------
-%% function : recreate
-%% Arguments: PropagationContext
-%% Returns : a Control object
-%% Effect :
-%%------------------------------------------------------------
-
--spec recreate(_, _, _) -> no_return().
-recreate(_Self, _State, #'CosTransactions_PropagationContext'{current = _C}) ->
- corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_YES}).
-%recreate(Self, State, #'CosTransactions_PropagationContext'{current = C}) ->
-% {reply, C#'CosTransactions_TransIdentity'.coord, State}.
-
-
-%%--------------- END OF MODULE ------------------------------
-
diff --git a/lib/cosTransactions/src/ETraP_Common.erl b/lib/cosTransactions/src/ETraP_Common.erl
deleted file mode 100644
index a5f2bf4831..0000000000
--- a/lib/cosTransactions/src/ETraP_Common.erl
+++ /dev/null
@@ -1,187 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2015. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : ETraP_Common.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module('ETraP_Common').
-
-%%--------------- INCLUDES ----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-%% Local
--include_lib("ETraP_Common.hrl").
--include_lib("CosTransactions.hrl").
-
-%%--------------- EXPORTS -----------------------------------
--export([try_timeout/1,
- get_option/3,
- create_name/2,
- create_name/1,
- is_debug_compiled/0,
- send_stubborn/5,
- create_link/3]).
-
-%%--------------- DEFINITIONS OF CONSTANTS ------------------
-%%------------------------------------------------------------
-%% function : create_link
-%% Arguments: Module - which Module to call
-%% Env/ARgList - ordinary oe_create arguments.
-%% Returns :
-%% Exception:
-%% Effect : Necessary since we want the supervisor to be a
-%% 'simple_one_for_one'. Otherwise, using for example,
-%% 'one_for_one', we have to call supervisor:delete_child
-%% to remove the childs startspecification from the
-%% supervisors internal state.
-%%------------------------------------------------------------
-create_link(Module, Env, ArgList) ->
- Module:oe_create_link(Env, ArgList).
-
-%%------------------------------------------------------------
-%% function : get_option
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-
-get_option(Key, OptionList, DefaultList) ->
- case lists:keysearch(Key, 1, OptionList) of
- {value,{Key,Value}} ->
- Value;
- _ ->
- case lists:keysearch(Key, 1, DefaultList) of
- {value,{Key,Value}} ->
- Value;
- _->
- {error, "Invalid option"}
- end
- end.
-%%------------------------------------------------------------
-%% function : create_name/2
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-
-create_name(Name,Type) ->
- Time = erlang:system_time(),
- Unique = erlang:unique_integer([positive]),
- lists:concat(['oe_',node(),'_',Type,'_',Name,'_',Time,'_',Unique]).
-
-%%------------------------------------------------------------
-%% function : create_name/1
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-
-create_name(Type) ->
- Time = erlang:system_time(),
- Unique = erlang:unique_integer([positive]),
- lists:concat(['oe_',node(),'_',Type,'_',Time,'_',Unique]).
-
-%%------------------------------------------------------------
-%% function : try_timeout
-%% Arguments: Id - name of the timeoutSrv server.
-%% Returns : Boolean
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-
-try_timeout(TimeoutAt) ->
- case TimeoutAt of
- infinity ->
- false;
- _->
- TimeSec = erlang:monotonic_time(seconds),
- if
- TimeSec < TimeoutAt ->
- false;
- true ->
- true
- end
- end.
-
-%%------------------------------------------------------------
-%% function : send_stubborn
-%% Arguments: M - module
-%% F - function
-%% A - arguments
-%% MaxR - Maximum no retries
-%% Wait - sleep Wait seconds before next try.
-%% Returns : see effect
-%% Exception:
-%% Effect : Retries repeatedly until anything else besides
-%% 'EXIT', 'COMM_FAILURE' or 'OBJECT_NOT_EXIST'
-%%------------------------------------------------------------
-
-send_stubborn(M, F, A, MaxR, Wait) when is_list(A) ->
- send_stubborn(M, F, A, MaxR, Wait, 0);
-send_stubborn(M, F, A, MaxR, Wait) ->
- send_stubborn(M, F, [A], MaxR, Wait, 0).
-send_stubborn(M, F, A, MaxR, _Wait, MaxR) ->
- ?tr_error_msg("~p:~p( ~p ) failed!! Tried ~p times.~n", [M,F,A,MaxR]),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO});
-send_stubborn(M, F, A, MaxR, Wait, Times) ->
- ?debug_print("~p:~p(~p) # of retries: ~p~n", [M,F,A, Times]),
- case catch apply(M,F,A) of
- {'EXCEPTION', E} when is_record(E, 'COMM_FAILURE')->
- NewTimes = Times +1,
- timer:sleep(Wait),
- send_stubborn(M, F, A, MaxR, Wait, NewTimes);
- {'EXCEPTION', E} when is_record(E, 'TRANSIENT')->
- NewTimes = Times +1,
- timer:sleep(Wait),
- send_stubborn(M, F, A, MaxR, Wait, NewTimes);
- {'EXCEPTION', E} when is_record(E, 'TIMEOUT')->
- NewTimes = Times +1,
- timer:sleep(Wait),
- send_stubborn(M, F, A, MaxR, Wait, NewTimes);
- {'EXIT', _} ->
- NewTimes = Times +1,
- timer:sleep(Wait),
- send_stubborn(M, F, A, MaxR, Wait, NewTimes);
- Other ->
- ?debug_print("~p:~p(~p) Resulted in: ~p~n", [M,F,A, Other]),
- Other
- end.
-
-%%------------------------------------------------------------
-%% function : is_debug_compiled
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-
--ifdef(debug).
- is_debug_compiled() -> true.
--else.
- is_debug_compiled() -> false.
--endif.
-
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosTransactions/src/ETraP_Common.hrl b/lib/cosTransactions/src/ETraP_Common.hrl
deleted file mode 100644
index 906e984a5b..0000000000
--- a/lib/cosTransactions/src/ETraP_Common.hrl
+++ /dev/null
@@ -1,341 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%---------------------------------------------------------------------
-%% File : ETraP_Common.hrl
-%% Purpose :
-%%---------------------------------------------------------------------
-
--ifndef(ETRAP_COMMON_HRL).
--define(ETRAP_COMMON_HRL, true).
-
-%%--------------- INCLUDES ---------------------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("cosTransactions/include/CosTransactions.hrl").
-
-%%-------- CONSTANTS ---------------------------------------------------
-%% Timeouts
--define(tr_comm_failure_wait,
- case catch application:get_env(cosTransactions, comFailWait) of
- {ok, _Time} when is_integer(_Time) ->
- _Time;
- _ ->
- 5000
- end).
-
--define(tr_max_retries,
- case catch application:get_env(cosTransactions, maxRetries) of
- {ok, _Max} when is_integer(_Max) ->
- _Max;
- _ ->
- 40
- end).
-
-%% Exceptions
-% Heuristic
--define(tr_mixed,
- #'CosTransactions_HeuristicMixed' {}).
--define(tr_hazard,
- #'CosTransactions_HeuristicHazard' {}).
--define(tr_commit,
- #'CosTransactions_HeuristicCommit' {}).
--define(tr_rollback,
- #'CosTransactions_HeuristicRollback' {}).
-%% Standard
--define(tr_subunavailable,
- #'CosTransactions_SubtransactionsUnavailable' {}).
--define(tr_unavailable,
- #'CosTransactions_Unavailable' {}).
--define(tr_unprepared,
- #'CosTransactions_NotPrepared' {}).
--define(tr_inactive,
- #'CosTransactions_Inactive' {}).
--define(tr_nosync,
- #'CosTransactions_SynchronizationUnavailable' {}).
--define(tr_badparam,
- #'BAD_PARAM'{completion_status=?COMPLETED_NO}).
--define(tr_NotSubtr,
- #'CosTransactions_NotSubtransaction' {}).
-
-%% TypeID:s
--define(tr_Terminator,
- 'CosTransactions_Terminator':typeID()).
--define(tr_Coordinator,
- 'CosTransactions_Coordinator':typeID()).
--define(tr_Control,
- 'CosTransactions_Control':typeID()).
--define(tr_RecoveryCoordinator,
- 'CosTransactions_RecoveryCoordinator':typeID()).
--define(tr_SubtransactionAwareResource,
- 'CosTransactions_SubtransactionAwareResource':typeID()).
--define(tr_Synchronization,
- 'CosTransactions_Synchronization':typeID()).
--define(tr_Resource,
- 'CosTransactions_Resource':typeID()).
--define(tr_ETraP,
- 'ETraP_Server':typeID()).
--define(tr_TransactionalObject,
- 'CosTransactions_TransactionalObject':typeID()).
-
-
-%%-------- MISC --------------------------------------------------------
-
--define(tr_error_msg(Txt, Arg),
-error_logger:error_msg("============ CosTransactions ==============~n"
- Txt
- "===========================================~n",
- Arg)).
-
-
--define(tr_NIL_OBJ_REF, corba:create_nil_objref()).
-
--define(tr_FAC_DEF, [{hash_max, 1013},
- {allow_subtr, true},
- {typecheck, true},
- {tty, false},
- {logfile, false}]).
-
-
-%%-------- Supervisor child-specs ------------------------------------
--define(FACTORY_NAME, oe_cosTransactionsFactory).
--define(SUPERVISOR_NAME, cosTransactions_sup).
--define(SUP_FLAG, {simple_one_for_one,50,10}).
-
--define(SUP_FAC(Env),
- ['CosTransactions_TransactionFactory',Env,
- [{sup_child, true}, {regname, {local, ?FACTORY_NAME}}]]).
-
--define(SUP_ETRAP(Env),
- ['ETraP_Server', Env,
- [{sup_child, true}, {persistent, true},
- {regname, {global, ?tr_get_etrap(Env)}}]]).
-
--define(SUP_TERMINATOR(Env),
- ['CosTransactions_Terminator', Env,
- [{sup_child, true}, {persistent, true},
- {regname, {global, ?tr_get_etrap(Env)}}]]).
-
--define(SUP_CHILD,
- {"oe_child",
- {'ETraP_Common',create_link, []},
- transient,100000,worker,
- ['ETraP_Common',
- 'ETraP_Server_impl',
- 'ETraP_Server',
- 'CosTransactions_Terminator_impl',
- 'CosTransactions_Terminator',
- 'CosTransactions_TransactionFactory_impl',
- 'CosTransactions_TransactionFactory']}).
-
-
--define(tr_start_child(SPEC),
- case supervisor:start_child(?SUPERVISOR_NAME, SPEC) of
- {ok, Pid, Obj} when is_pid(Pid) ->
- Obj;
- _Other->
- corba:raise(?tr_badparam)
- end).
-
--define(tr_start_child_pid(SPEC),
- supervisor:start_child(?SUPERVISOR_NAME, SPEC)).
-
--define(tr_terminate_child(Child),
- supervisor:terminate_child(?SUPERVISOR_NAME, Child)).
-
--define(tr_delete_child(Child),
- supervisor:delete_child(?SUPERVISOR_NAME, Child)).
-
-%%-------- DATASTRUCTURES ----------------------------------------------
-%% tr_*_*
--record(context, {terminator, etrap, recCoord, alarm = infinity,
- timeout = infinity, parents=[], trid, typeCheck,
- sub_tr_allowed, hashMax, local, rollback=false,
- reportH, maxRetries, comFailWait}).
-
-
-%%-------- FUNS --------------------------------------------------------
--define(tr_IS_MEMBER(Obj),
- fun(X) ->
- case catch corba_object:is_equivalent(Obj, X) of
- true ->
- true;
- _ ->
- false
- end
- end).
-
-%% Managing conditional debug functions
--define(is_debug_compiled, 'ETraP_Common':is_debug_compiled()).
--define(set_debug_context(L, C),
- etrap_test_lib:set_debug_context(L, C, ?FILE, ?LINE)).
-
-
--ifdef(debug).
--define(put_debug_data(Key, Data), erlang:put(Key, Data)).
--define(get_debug_data(Key), erlang:get(Key)).
--define(eval_debug_fun(I, E),
- etrap_test_lib:eval_debug_fun(I, E, ?FILE, ?LINE)).
--define(activate_debug_fun(I, F, C),
- etrap_test_lib:activate_debug_fun(I, F, C, ?FILE, ?LINE)).
--define(deactivate_debug_fun(I),
- etrap_test_lib:deactivate_debug_fun(I, ?FILE, ?LINE)).
--define(debug_print(F,A),
- io:format("[LINE: ~p] "++F,[?LINE]++A)).
--define(scratch_debug_fun,
- etrap_test_lib:scratch_debug_fun()).
--else.
--define(put_debug_data(Key, Data), ok).
--define(get_debug_data(Key), ok).
--define(eval_debug_fun(I, E), ok).
--define(activate_debug_fun(I, F, C), ok).
--define(deactivate_debug_fun(I), ok).
--define(debug_print(F,A), ok).
--define(scratch_debug_fun, ok).
--endif.
-
-
-%%-------- CONSTRUCTORS ------------------------------------------------
-
--define(tr_create_context(ETraP, Terminator, TypeCheck, HM, SubtrOK, MaxRetries,
- ComFailWait),
- #context{etrap = ETraP, terminator = Terminator, typeCheck = TypeCheck,
- hashMax = HM, sub_tr_allowed = SubtrOK, maxRetries = MaxRetries,
- comFailWait = ComFailWait}).
-
-
-%%-------- MISC --------------------------------------------------------
--define(tr_notimeout(Context),
- 'ETraP_Common':try_timeout(Context#context.alarm) == false).
--define(tr_is_root(Context), Context#context.parents == []).
--define(tr_dont_reportH(Context), Context#context.reportH == false).
--define(tr_is_retransmit(Context),
- Context#context.reportH =/= undefined,
- Context#context.reportH =/= true,
- Context#context.reportH =/= false).
-
-%%-------- SELECTORS ---------------------------------------------------
-
--define(tr_get_reportH(Context),
- Context#context.reportH).
-
--define(tr_get_rollback(Context),
- Context#context.rollback).
-
--define(tr_get_subTraOK(Context),
- Context#context.sub_tr_allowed).
-
--define(tr_get_hashMax(Context),
- Context#context.hashMax).
-
--define(tr_get_local(Context),
- Context#context.local).
-
--define(tr_get_trid(Context),
- Context#context.trid).
-
--define(tr_get_typeCheck(Context),
- Context#context.typeCheck).
-
--define(tr_get_recCoord(Context),
- Context#context.recCoord).
-
--define(tr_get_alarm(Context),
- Context#context.alarm).
-
--define(tr_get_timeout(Context),
- Context#context.timeout).
-
--define(tr_get_etrap(Context),
- Context#context.etrap).
-
--define(tr_get_terminator(Context),
- Context#context.terminator).
-
--define(tr_get_id(Context),
- Context#context.self).
-
--define(tr_get_maxW(Context),
- Context#context.comFailWait).
-
--define(tr_get_maxR(Context),
- Context#context.maxRetries).
-
--define(tr_get_parents(Context),
- Context#context.parents).
-
--define(tr_get_parent(Context),
- lists:nth(1, Context#context.parents)).
-
-%%-------- MODIFIERS ---------------------------------------------------
-
--define(tr_set_reportH(Context, Bool),
- Context#context{reportH = Bool}).
-
--define(tr_set_rollback(Context, Bool),
- Context#context{rollback = Bool}).
-
--define(tr_set_subTraOK(Context, Bool),
- Context#context{sub_tr_allowed = Bool}).
-
--define(tr_set_hashMax(Context, HM),
- Context#context{hashMax = HM}).
-
--define(tr_reset_local(Context),
- Context#context{local = undefined}).
-
--define(tr_set_local(Context, Local),
- Context#context{local = Local}).
-
--define(tr_set_trid(Context, TRID),
- Context#context{trid = TRID}).
-
--define(tr_set_typeCheck(Context, Bool),
- Context#context{typeCheck = Bool}).
-
--define(tr_set_id(Context, ID),
- Context#context{self = ID}).
-
--define(tr_set_parents(Context, Parents),
- Context#context{parents = Parents}).
-
--define(tr_add_parent(Context, Parent),
- Context#context{parents = [Parent] ++ Context#context.parents}).
-
--define(tr_set_recCoord(Context, R),
- Context#context{recCoord = R}).
-
--define(tr_set_alarm(Context, EC),
- Context#context{alarm = EC}).
-
--define(tr_set_timeout(Context, T),
- Context#context{timeout = T}).
-
--define(tr_set_etrap(Context, ETraP),
- Context#context{etrap = ETraP}).
-
--define(tr_set_terminator(Context, T),
- Context#context{terminator = T}).
-
--endif.
-
-%%-------------- EOF ---------------------------------------------------
-
-
diff --git a/lib/cosTransactions/src/ETraP_Server_impl.erl b/lib/cosTransactions/src/ETraP_Server_impl.erl
deleted file mode 100644
index 5c7b5f6350..0000000000
--- a/lib/cosTransactions/src/ETraP_Server_impl.erl
+++ /dev/null
@@ -1,1745 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : ETraP_Server_impl.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-%% GENERAL CODE COMMENTS:
-%% ######################
-%% TypeChecking incoming arguments:
-%% --------------------------------
-%% We allow the user to configure the system so that external calls
-%% (not CosTransactions calls) may be typechecked or not when calling
-%% for example 'replay_completion'. With typecheck the user will get
-%% instant feedback. But since 'is_a' add quiet a lot extra overhead
-%% if the object is located on a remote ORB. Hence, it is up to the
-%% user to decide; speed vs. "safety".
-%%
-%% Log behavior
-%% ------------
-%% Log files are created in the current directory, which is why the
-%% application requires read/write rights for current directory. The
-%% file name looks like:
-%% "oe_nonode@nohost_subc_1429872479809947099_438" (the two last parts are
-%% erlang:system_time() and erlang:unique_integer([positive]))
-%% It is equal to what the object is started as, i.e., {regname, {global, X}}.
-%%
-%% If the application is unable to read the log it will exit and the
-%% supervisor definitions (found in ETraP_Common.hrl) determines how
-%% many times we will retry. If it's impossible to read the log it's
-%% considered as a disaster, i.e., user intervention is needed.
-%%
-%% If an Object is unreachable when a Coordinator is trying to inform
-%% of the true outcome of the transaction the application will retry N
-%% times with T seconds wait in between. If it's still impossible to
-%% reach the object it's considered as a disaster, i.e., user
-%% intervention is needed.
-%%
-%%----------------------------------------------------------------------
-
--module('ETraP_Server_impl').
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
-
-%% Local
--include_lib("cosTransactions/src/ETraP_Common.hrl").
--include_lib("cosTransactions/include/CosTransactions.hrl").
-
-
-%%--------------- IMPORTS-------------------------------------
--import('ETraP_Common', [try_timeout/1]).
-
-%%--------------- EXPORTS-------------------------------------
-%%--------------- Inherit from CosTransactions::Resource ----
--export([prepare/2,
- rollback/2,
- commit/2,
- commit_one_phase/2,
- forget/2]).
-
-%%--------------- Inherit from CosTransactions::Control -----
--export([get_terminator/2,
- get_coordinator/2]).
-
-%%----- Inherit from CosTransactions::RecoveryCoordinator ---
--export([replay_completion/3]).
-
-%%--------------- Inherit from CosTransactions::Coordinator -
--export([create_subtransaction/2,
- get_txcontext/2,
- get_transaction_name/2,
- get_parent_status/2,
- get_status/2,
- get_top_level_status/2,
- hash_top_level_tran/2,
- hash_transaction/2,
- is_ancestor_transaction/3,
- is_descendant_transaction/3,
- is_related_transaction/3,
- is_same_transaction/3,
- is_top_level_transaction/2,
- register_resource/3,
- register_subtran_aware/3,
- register_synchronization/3,
- rollback_only/2]).
-
-%%--------- Inherit from CosTransactions::Synchronization ---
-%-export([before_completion/2,
-% after_completion/3]).
-
-
-%%--------------- gen_server specific ------------------------
--export([init/1, terminate/2]).
--export([handle_call/3, handle_cast/2, handle_info/2, code_change/3]).
-
-
-
-%%--------------- LOCAL DATA ---------------------------------
--record(exc,
- {rollback = false,
- mixed = false,
- hazard = false,
- unprepared = false,
- commit = false}).
-
-%%--------------- LOCAL DEFINITIONS --------------------------
-
-%%--------------- MISC MACROS --------------------------------
--define(etr_log(Log, Data), etrap_logmgr:log_safe(Log, Data)).
--define(etr_read(Log, Cursor), etrap_logmgr:get_next(Log, Cursor)).
-
--record(coord,
- {status, %% Status of the transaction.
- members = [], %% List of registred resources.
- votedCommit = [], %% List of the ones that voted commit.
- raisedHeuristic = [], %% The members which raised an Heur. exc.
- subAw = [], %% Resorces which want to be informed of outcome.
- sync = [],
- exc = void,
- self,
- etsR}).
-
-%% Selectors
--define(etr_get_status(L), L#coord.status).
--define(etr_get_members(L), lists:reverse(L#coord.members)).
--define(etr_get_vc(L), lists:reverse(L#coord.votedCommit)).
--define(etr_get_raisedH(L), lists:reverse(L#coord.raisedHeuristic)).
--define(etr_get_exc(L), L#coord.exc).
--define(etr_get_subAw(L), lists:reverse(L#coord.subAw)).
--define(etr_get_sync(L), lists:reverse(L#coord.sync)).
--define(etr_get_self(L), L#coord.self).
--define(etr_get_etsR(L), L#coord.etsR).
--define(etr_get_init(Env), #coord{}).
--define(etr_get_exc_init(), #exc{}).
-%% Modifiers
--define(etr_set_status(L, D), L#coord{status = D}).
--define(etr_set_members(L, D), L#coord{members = D}).
--define(etr_add_member(L, D), L#coord{members = [D|L#coord.members]}).
--define(etr_set_vc(L, D), L#coord{votedCommit = D}).
--define(etr_add_vc(L, D), L#coord{votedCommit = [D|L#coord.votedCommit]}).
--define(etr_remove_vc(L, D), L#coord{votedCommit =
- lists:delete(D, ?etr_get_vc(L))}).
--define(etr_set_raisedH(L, D), L#coord{raisedHeuristic = [D]}).
--define(etr_add_raisedH(L, D), L#coord{raisedHeuristic =
- [D|L#coord.raisedHeuristic]}).
--define(etr_remove_raisedH(L, D), L#coord{raisedHeuristic =
- lists:delete(D, ?etr_get_raisedH(L))}).
--define(etr_set_exc(L, D), L#coord{exc = D}).
--define(etr_set_subAw(L, D), L#coord{subAw = [D]}).
--define(etr_add_subAw(L, D), L#coord{subAw = [D|L#coord.subAw]}).
--define(etr_remove_subAw(L, D), L#coord{subAw =
- lists:delete(D,?etr_get_subAw(L))}).
--define(etr_set_sync(L, D), L#coord{sync = [D]}).
--define(etr_add_sync(L, D), L#coord{sync = [D|L#coord.sync]}).
--define(etr_remove_sync(L, D), L#coord{sync = lists:delete(D,?etr_get_sync(L))}).
--define(etr_set_self(L, D), L#coord{self = D}).
--define(etr_set_etsR(L, D), L#coord{etsR = D}).
-
-
-%%------------------------------------------------------------
-%% function : init, terminate
-%% Arguments:
-%% Returns :
-%% Effect : Functions demanded by the module ic.
-%%------------------------------------------------------------
-
-init(Env) ->
- process_flag(trap_exit,true),
- case catch start_object(Env) of
- {'EXIT', Reason} ->
- %% Happens when, for example, we encounter an
- %% error when reading from the log file.
- {stop, Reason};
- {'EXCEPTION', E} ->
- self() ! {suicide, self()},
- corba:raise(E);
- Other ->
- Other
- end.
-
-
-
-terminate(Reason, {Env, _Local}) ->
- ?debug_print("STOP ~p ~p~n", [?tr_get_etrap(Env), Reason]),
- case Reason of
- normal ->
- %% normal termination. Transaction completed.
- etrap_logmgr:stop(?tr_get_etrap(Env)),
- file:delete(?tr_get_etrap(Env)),
- ok;
- _ ->
- ?tr_error_msg("Object(~p) terminated abnormal.~n",[?tr_get_etrap(Env)]),
- ok
- end.
-
-
-%%------------------------------------------------------------
-%% function : handle_call, handle_cast, handle_info, code_change
-%% Arguments:
-%% Returns :
-%% Effect : Functions demanded by the gen_server module.
-%%------------------------------------------------------------
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-handle_call(_,_, State) ->
- {noreply, State}.
-
-handle_cast(_, State) ->
- {noreply, State}.
-
-
-handle_info(Info, {Env, Local}) ->
- ?debug_print("ETraP_Server:handle_info(~p)~n", [Info]),
- Pid = self(),
- case Info of
- timeout ->
- ?tr_error_msg("Object( ~p ) timeout. Rolling back.~n",
- [?tr_get_etrap(Env)]),
- {stop, normal, {Env, Local}};
- {suicide, Pid} ->
- {stop, normal, {Env, Local}};
- _->
- {noreply, {Env, Local}}
- end.
-
-
-%%--------------- Inherit from CosTransactions::Control -----
-%%-----------------------------------------------------------%
-%% function : get_terminator
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% Returns : a Terminator object reference.
-%% Effect : Supports operations for termination of a transaction
-%%------------------------------------------------------------
-
-get_terminator(Self, {Env, Local}) ->
- %% Only allows the root-coordinator to export the termonator.
- %% The reason for this is that only the root-coordinator is allowed
- %% to initiate termination of a transaction. This is however possible
- %% to change and add restictions elsewhere, i.e. to verify if the
- %% commit or rollback call is ok.
- case catch ?tr_get_parents(Env) of
- [] -> % No parents, it's a root-coordinator.
- % Create terminators environment.
- TEnv = ?tr_set_etrap(Env, Self),
- T = ?tr_start_child(?SUP_TERMINATOR(TEnv)),
- {reply, T, {Env, Local}, ?tr_get_timeout(TEnv)};
- _ ->
- corba:raise(?tr_unavailable)
- end.
-
-%%-----------------------------------------------------------%
-%% function : get_coordinator
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% Returns : a Coordinator object reference. The OMG specification
-%% states that a object reference must be returned.
-%% Effect : Supports operations needed by resources to participate
-%% in the transaction.
-%%------------------------------------------------------------
-
-get_coordinator(Self, State) ->
- {reply, Self, State}.
-
-%%----- Inherit from CosTransactions::RecoveryCoordinator ---
-%%-----------------------------------------------------------%
-%% function : replay_completion
-%% Arguments:
-%% Returns : Status
-%% Effect : Provides a hint to the Coordinator that the commit
-%% or rollback operations have not been performed on
-%% the resource.
-%%------------------------------------------------------------
-
-replay_completion(_Self, {Env, Local}, Resource) ->
- type_check(?tr_get_typeCheck(Env), ?tr_Resource,
- "RecoveryCoordinator:replay_completion", Resource),
- case ?etr_get_status(Local) of
- 'StatusActive' ->
- corba:raise(?tr_unprepared);
- Status ->
- case lists:any(?tr_IS_MEMBER(Resource), ?etr_get_members(Local)) of
- true ->
- {reply, Status, {Env, Local}};
- _ ->
- corba:raise(#'NO_PERMISSION'{completion_status=?COMPLETED_YES})
- end
- end.
-
-%%--------------- Inherit from CosTransactions::Resource ----
-%%-----------------------------------------------------------%
-%% function : prepare
-%% Arguments:
-%% Returns : a Vote
-%% Effect : Is invoked to begin the two-phase-commit on the
-%% resource.
-%%------------------------------------------------------------
-
-prepare(_Self, {Env, Local}) ->
- %% Set status as prepared. No new Resources are allowed to register.
- NewL = ?etr_set_status(Local, 'StatusPrepared'),
-
- ?eval_debug_fun({?tr_get_etrap(Env), root_delay}, Env),
-
- case catch send_prepare(?etr_get_members(NewL),
- ?tr_get_alarm(Env)) of
- readOnly ->
- %% All voted ReadOnly, done. No need to log.
- {stop, normal, 'VoteReadOnly', {Env, NewL}};
- %% Replace the reply above if allow synchronization
-% case ?etr_get_sync(Local) of
-% [] ->
-% {stop, normal, 'VoteReadOnly', {Env, NewL}};
-% _ ->
-% {reply, 'VoteReadOnly', {Env, NewL}}
-% end;
- {commit, VC} ->
- %% All voted Commit.
- NewL2 = ?etr_set_vc(NewL, VC),
- case catch try_timeout(?tr_get_alarm(Env)) of
- false ->
- case ?etr_log(?tr_get_etrap(Env), {pre_vote, commit, NewL2}) of
- ok ->
- ?eval_debug_fun({?tr_get_etrap(Env), prepare1}, Env),
- {reply, 'VoteCommit', {Env, NewL2}};
- _->
- %% Cannot log. Better to be safe than sorry; do rollback.
- %% However, try to log rollback.
- ?etr_log(?tr_get_etrap(Env),{pre_vote, rollback, NewL2}),
- send_decision({Env, NewL2}, 'VoteRollback', rollback)
- end;
- _->
- ?etr_log(?tr_get_etrap(Env),
- {pre_vote, rollback, NewL2}),
- %% timeout, reply rollback.
- send_decision({Env, NewL2}, 'VoteRollback', rollback)
- end;
- {rollback, VC} ->
- %% Rollback vote received.
- %% Send rollback to commit voters.
- N2 = ?etr_set_vc(NewL, VC),
- NewL2 = ?etr_set_status(N2,'StatusRolledBack'),
- ?etr_log(?tr_get_etrap(Env), {pre_vote, rollback, NewL2}),
- send_decision({Env, NewL2}, 'VoteRollback', rollback);
- {'EXCEPTION', E, VC, Obj} ->
- NewL2 = case is_heuristic(E) of
- true ->
- N2 = ?etr_set_vc(NewL, VC),
- N3 = ?etr_set_exc(N2, E),
- ?etr_set_raisedH(N3, Obj);
- _->
- ?etr_set_vc(NewL, VC)
- end,
- ?etr_log(?tr_get_etrap(Env),{pre_vote,rollback, NewL2}),
- ?eval_debug_fun({?tr_get_etrap(Env), prepare2}, Env),
- send_decision({Env, NewL2}, {'EXCEPTION', E}, rollback);
- {failed, VC} ->
- NewL2 = ?etr_set_vc(NewL, VC),
- ?etr_log(?tr_get_etrap(Env),{pre_vote, rollback, NewL2}),
- send_decision({Env, NewL2},
- {'EXCEPTION', ?tr_hazard}, rollback)
- end.
-
-
-%%-----------------------------------------------------------%
-%% function : rollback
-%% Arguments: Self - the servers own objref.
-%% {Env, Local} - the servers internal state.
-%% Returns : ok
-%% Effect : Rollback the transaction. If its status is
-%% "StatusRolledBack", this is not the first
-%% rollback call to this server. Might occur if
-%% the parent coordinator just recoeverd from a crasch.
-%% Exception: HeuristicCommit, HeuristicMixed, HeuristicHazard
-%%------------------------------------------------------------
-
-rollback(Self, {Env, Local}) ->
- case ?etr_get_status(Local) of
- 'StatusRolledBack' ->
- case ?etr_get_exc(Local) of
- void ->
- {stop, normal, ok, {Env, Local}};
- %% Replace the reply above if allow synchronization
- %% Rolled back successfullly earlier.
-% case ?etr_get_sync(Local) of
-% [] ->
-% {stop, normal, ok, {Env, Local}};
-% _ ->
-% {reply, ok, {Env, Local}}
-% end;
- E ->
- %% Already rolledback with heuristic decision
- corba:raise(E)
- end;
- 'StatusPrepared' ->
- NewL = ?etr_set_status(Local, 'StatusRolledBack'),
- ?eval_debug_fun({?tr_get_etrap(Env), rollback}, Env),
- ?etr_log(?tr_get_etrap(Env), rollback),
- ?eval_debug_fun({?tr_get_etrap(Env), rollback2}, Env),
- send_decision({Env, NewL}, ok, rollback);
- 'StatusActive' ->
- NewL = ?etr_set_status(Local, 'StatusRolledBack'),
- ?etr_log(?tr_get_etrap(Env), {rollback, NewL}),
- send_info(?etr_get_members(NewL), 'CosTransactions_Resource', rollback),
- notify_subtrAware(rollback, ?etr_get_subAw(NewL), Self),
- {stop, normal, ok, {Env, NewL}}
-%% Replace the reply above if allow synchronization
-% case ?etr_get_sync(Local) of
-% [] ->
-% {stop, normal, ok, {NewEnv, NewL}};
-% _ ->
-% {reply, ok, {NewEnv, NewL}}
-% end;
- end.
-
-
-%%-----------------------------------------------------------%
-%% function : commit
-%% Arguments: Self - the servers own objref.
-%% {Env, Local} - the servers internal state.
-%% Returns : ok
-%% Effect : Commit the transaction.
-%% Exception: HeuristicRollback, HeuristicMixed, HeuristicHazard,
-%% NotPrepared
-%%------------------------------------------------------------
-
-commit(_Self, {Env, Local}) ->
- case ?etr_get_status(Local) of
- 'StatusPrepared' ->
- ?eval_debug_fun({?tr_get_etrap(Env), commit}, Env),
- NewL = ?etr_set_status(Local, 'StatusCommitted'),
- ?etr_log(?tr_get_etrap(Env),commit),
- ?eval_debug_fun({?tr_get_etrap(Env), commit2}, Env),
- send_decision({Env, NewL}, ok, commit);
- 'StatusCommitted' ->
- case ?etr_get_exc(Local) of
- void ->
- {stop, normal, ok, {Env, Local}};
- %% Replace the reply above if allow synchronization
-% case ?etr_get_sync(Local) of
-% [] ->
-% {stop, normal, ok, {Env, Local}};
-% _ ->
-% {reply, ok, {Env, Local}}
-% end;
- E->
- corba:raise(E)
- end;
- _ ->
- corba:raise(?tr_unprepared)
- end.
-
-%%-----------------------------------------------------------%
-%% function : commit_one_phase
-%% Arguments: Self - the servers own objref.
-%% {Env, Local} - the servers internal state.
-%% Returns : ok
-%% Effect : Commit the transaction using one-phase commit.
-%% Use ONLY when there is only one registered Resource.
-%% Exception: HeuristicRollback, HeuristicMixed, HeuristicHazard,
-%% TRANSACTION_ROLLEDBACK
-%%------------------------------------------------------------
-
-commit_one_phase(_Self, {Env, Local}) ->
- case ?etr_get_members(Local) of
- [Resource] ->
- case ?etr_get_status(Local) of
- 'StatusActive' ->
- %% Set status as prepared. No new Resources are allowed to register.
- NewL = ?etr_set_status(Local, 'StatusPrepared'),
- ?eval_debug_fun({?tr_get_etrap(Env), onePC}, Env),
- case try_timeout(?tr_get_alarm(Env)) of
- false ->
- case catch 'CosTransactions_Resource':prepare(Resource) of
- 'VoteCommit' ->
- case try_timeout(?tr_get_alarm(Env)) of
- false ->
- send_decision({Env, NewL}, ok, commit, [Resource]);
- _->
- %% Timeout, rollback.
- send_decision({Env, NewL},
- {'EXCEPTION',
- #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
- rollback, [Resource])
- end;
- 'VoteRollback' ->
- {stop, normal,
- {'EXCEPTION',
- #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
- {Env, NewL}};
- 'VoteReadOnly' ->
- {stop, normal, ok, {Env, NewL}};
- {'EXCEPTION', E}
- when is_record(E, 'CosTransactions_HeuristicMixed') ->
- {reply, {'EXCEPTION', E}, {Env, NewL}};
- {'EXCEPTION', E}
- when is_record(E, 'CosTransactions_HeuristicHazard') ->
- {reply, {'EXCEPTION', E}, {Env, NewL}};
- Other ->
- ?tr_error_msg("Coordinator:prepare( ~p ) failed. REASON ~p~n",
- [Resource, Other]),
- {stop, normal,
- {'EXCEPTION',
- #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
- {Env, NewL}}
- end;
- _->
- NewL2 = ?etr_set_status(NewL, 'StatusRolledBack'),
- send_info(Resource, 'CosTransactions_Resource', rollback),
- {stop, normal,
- {'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
- {Env, NewL2}}
- %% Replace the reply above if allow synchronization
-% case ?etr_get_sync(NewL2) of
-% [] ->
-% send_info(Resource, 'CosTransactions_Resource', rollback),
-% {stop, normal,
-% {'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
-% {Env, NewL2}};
-% _ ->
-% send_info(Resource, 'CosTransactions_Resource', rollback),
-% {reply,
-% {'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
-% {Env, NewL2}}
-% end
- end;
- _ ->
- case evaluate_status(?etr_get_status(Local)) of
- commit ->
- test_exc(set_exception(?etr_get_exc_init(),
- ?etr_get_exc(Local)),
- commit, ok, {Env, Local});
- _->
- test_exc(set_exception(?etr_get_exc_init(),
- ?etr_get_exc(Local)),
- rollback,
- {'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
- {Env, Local})
- end
- end;
- _->
- {reply, {'EXCEPTION', #'NO_PERMISSION'{completion_status=?COMPLETED_NO}},
- {Env, Local}}
- end.
-
-%%-----------------------------------------------------------%
-%% function : forget
-%% Arguments: Self - the servers own objref.
-%% State - the servers internal state.
-%% Returns : ok
-%% Effect : The resource can forget all knowledge about the
-%% transaction. Terminate this server.
-%%------------------------------------------------------------
-
-forget(_Self, {Env, Local}) ->
- ?etr_log(?tr_get_etrap(Env), forget_phase),
- send_forget(?etr_get_raisedH(Local), ?tr_get_etrap(Env)),
- {stop, normal, ok, {Env, ?etr_set_exc(Local, void)}}.
-%% Replace the reply above if allow synchronization
-% case ?etr_get_sync(Local) of
-% [] ->
-% {stop, normal, ok, {Env, ?etr_set_exc(Local, void)}};
-% _ ->
-% {reply, ok, {Env, ?etr_set_exc(Local, void)}}
-% end.
-
-%%--------------- Inherrit from CosTransactions::Coordinator -
-
-%%-----------------------------------------------------------%
-%% function : get_status
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% Returns : Status
-%% Effect : Returns the status of the transaction associated
-%% with the target object.
-%%------------------------------------------------------------
-
-get_status(_Self, {Env, Local}) ->
- {reply, ?etr_get_status(Local), {Env, Local}}.
-
-
-%%-----------------------------------------------------------%
-%% function : get_parent_status
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% Returns : Status
-%% Effect : Returns the status of the parent transaction
-%% associated with the target object. If top-level
-%% transaction equal to get_status.
-%%------------------------------------------------------------
-
-get_parent_status(_Self, {Env, Local}) ->
- case catch ?tr_get_parents(Env) of
- [] ->
- {reply, ?etr_get_status(Local), {Env, Local}};
- [Parent|_] ->
- case catch 'CosTransactions_Coordinator':get_status(Parent) of
- {'EXCEPTION', _E} ->
- corba:raise(?tr_unavailable);
- {'EXIT', _} ->
- corba:raise(?tr_unavailable);
- Status ->
- {reply, Status, {Env, Local}}
- end
- end.
-
-
-%%-----------------------------------------------------------%
-%% function : get_top_level_status
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% Returns : Status
-%% Effect : Returns the status of the top-level transaction
-%% associated with the target object. If top-level
-%% transaction equal to get_status.
-%%------------------------------------------------------------
-
-get_top_level_status(_Self, {Env, Local}) ->
- case catch ?tr_get_parents(Env) of
- [] ->
- {reply, ?etr_get_status(Local), {Env, Local}};
- Ancestrors ->
- case catch 'CosTransactions_Coordinator':get_status(lists:last(Ancestrors)) of
- {'EXCEPTION', _E} ->
- corba:raise(?tr_unavailable);
- {'EXIT', _} ->
- corba:raise(?tr_unavailable);
- Status ->
- {reply, Status, {Env, Local}}
- end
- end.
-
-
-%%-----------------------------------------------------------%
-%% function : is_same_transaction
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% Coordinator object reference
-%% Returns : boolean
-%% Effect :
-%%------------------------------------------------------------
-
-is_same_transaction(Self, {Env, Local}, Coordinator) ->
- type_check(?tr_get_typeCheck(Env), ?tr_Coordinator,
- "Coordinator:is_same_transaction", Coordinator),
- {reply, corba_object:is_equivalent(Self, Coordinator), {Env, Local}}.
-
-%%------------------------------------------------------------
-%% function : is_related_transaction
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% Coordinator object reference
-%% Returns : boolean
-%% Effect :
-%%------------------------------------------------------------
-
--spec is_related_transaction(_, _, _) -> no_return().
-is_related_transaction(_Self, {_Env, _Local}, _Coordinator) ->
- corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_YES}).
-% type_check(?tr_get_typeCheck(Env), ?tr_Coordinator,
-% "Coordinator:is_related_transaction", Coordinator),
-% {reply, false, {Env, Local}}.
-
-
-%%------------------------------------------------------------
-%% function : is_ancestor_transaction
-%% Coordinator object reference
-%% Returns : boolean
-%% Effect :
-%%------------------------------------------------------------
-
--spec is_ancestor_transaction(_, _, _) -> no_return().
-is_ancestor_transaction(_Self, {_Env, _Local}, _Coordinator) ->
- corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_YES}).
-% type_check(?tr_get_typeCheck(Env), ?tr_Coordinator,
-% "Coordinator:is_ancestor_transaction", Coordinator),
-% {reply, false, {Env, Local}}.
-
-
-%%-----------------------------------------------------------%
-%% function : is_descendant_transaction
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% Coordinator object reference
-%% Returns : boolean
-%% Effect :
-%%------------------------------------------------------------
-
-is_descendant_transaction(Self, {Env, Local}, Coordinator) ->
- type_check(?tr_get_typeCheck(Env), ?tr_Coordinator,
- "Coordinator:is_descendant_transaction", Coordinator),
- {reply,
- lists:any(?tr_IS_MEMBER(Coordinator), [Self|?tr_get_parents(Env)]),
- {Env, Local}}.
-
-%%-----------------------------------------------------------%
-%% function : is_top_level_transaction
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% Returns : boolean
-%% Effect :
-%%------------------------------------------------------------
-
-is_top_level_transaction(_Self, {Env, Local}) ->
- case catch ?tr_get_parents(Env) of
- [] ->
- {reply, true, {Env, Local}};
- _ ->
- {reply, false, {Env, Local}}
- end.
-
-%%-----------------------------------------------------------%
-%% function : hash_transaction
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% Returns : hash code
-%% Effect : Returns a hash code for the transaction associated
-%% with the target object.
-%%------------------------------------------------------------
-
-hash_transaction(Self, {Env, Local}) ->
- {reply, corba_object:hash(Self, ?tr_get_hashMax(Env)), {Env, Local}}.
-
-
-%%-----------------------------------------------------------%
-%% function : hash_top_level_tran
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% Returns : hash code
-%% Effect : Returns a hash code for the top-level transaction
-%% associated with the target object. Equals
-%% hash_transaction if it's a top-level transaction.
-%%------------------------------------------------------------
-
-hash_top_level_tran(Self, {Env, Local}) ->
- case ?tr_get_parents(Env) of
- [] ->
- {reply,
- corba_object:hash(Self, ?tr_get_hashMax(Env)),
- {Env, Local}};
- Ancestrors ->
- case catch corba_object:hash(lists:last(Ancestrors),
- ?tr_get_hashMax(Env)) of
- {'EXCEPTION', _E} ->
- corba:raise(?tr_unavailable);
- Hash ->
- {reply, Hash, {Env, Local}}
- end
- end.
-
-
-
-%%-----------------------------------------------------------%
-%% function : register_resource
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% Resource object reference
-%% Returns : RecoveryCoordinator (can be used during recovery)
-%% Effect : Registers the specified resource as as participant
-%% in the transaction associated with the target object.
-%% Exception: Inactive - Is prepared or terminated.
-%%------------------------------------------------------------
-
-register_resource(Self, {Env, Local}, Resource) ->
- type_check(?tr_get_typeCheck(Env), ?tr_Resource,
- "Coordinator:register_resource", Resource),
- case ?etr_get_status(Local) of
- 'StatusActive' -> % ok to register the Resource.
- NewLocal = ?etr_add_member(Local, Resource),
- RecoveryCoord = corba:create_subobject_key(Self, ?tr_get_etrap(Env)),
- {reply, RecoveryCoord, {Env, NewLocal}, ?tr_get_timeout(Env)};
- _-> % Not active anymore. New members not ok.
- corba:raise(?tr_inactive)
- end.
-
-
-
-%%-----------------------------------------------------------%
-%% function : register_subtran_aware
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% SubTransactionAwareResource object reference
-%% Returns : -
-%% Effect : Registers the specified object such that it
-%% will be notified when the subtransaction has
-%% commited or rolled back.
-%%------------------------------------------------------------
-
-register_subtran_aware(Self, {Env, Local}, SubTrAwareResource) ->
- case ?tr_get_parents(Env) of
- [] ->
- corba:raise(?tr_NotSubtr);
- _->
- type_check(?tr_get_typeCheck(Env), ?tr_SubtransactionAwareResource,
- "Coordinator:register_subtran_aware", SubTrAwareResource),
- NewL = ?etr_add_subAw(Local, SubTrAwareResource),
- {reply, ok, {Env, ?etr_set_self(NewL, Self)},
- ?tr_get_timeout(Env)}
- end.
-
-%%-----------------------------------------------------------%
-%% function : register_synchronization
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% Synchronization
-%% Returns : -
-%% Effect :
-%%------------------------------------------------------------
-
--spec register_synchronization(_, _, _) -> no_return().
-register_synchronization(_Self, {_Env, _Local}, _Synchronization) ->
- corba:raise(#'CosTransactions_SynchronizationUnavailable'{}).
-
-%register_synchronization(Self, {Env, Local}, Synchronization) ->
-% type_check(?tr_get_typeCheck(Env), ?tr_Synchronization,
-% "Coordinator:register_synchronization", Synchronization),
-% case ?etr_get_status(Local) of
-% 'StatusActive' ->
-% case catch ?tr_get_parents(Env) of
-% [] ->
-% {reply, ok, {Env, ?etr_add_sync(Local, Synchronization)},
-% ?tr_get_timeout(Env)};
-% [Parent|_] ->
-% case catch 'ETraP_Server':register_synchronization(Parent, Self) of
-% {'EXCEPTION', E} ->
-% corba:raise(E);
-% ok ->
-% {reply, ok, {Env, ?etr_add_sync(Local, Synchronization)},
-% ?tr_get_timeout(Env)};
-% What ->
-% corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_MAYBE})
-% end
-% end;
-% _ ->
-% corba:raise(?tr_inactive)
-% end.
-
-%%-----------------------------------------------------------%
-%% function : rollback_only
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% Returns : -
-%% Effect : The transaction associated with the target object
-%% is modified so that rollback IS the result.
-%%------------------------------------------------------------
-
-rollback_only(Self, {Env, Local}) ->
- case ?etr_get_status(Local) of
- 'StatusActive' ->
- NewL = ?etr_set_status(Local, 'StatusRolledBack'),
- NewEnv = ?tr_set_rollback(Env, true),
- ?etr_log(?tr_get_etrap(Env),{rollback, NewL}),
- send_info(?etr_get_members(NewL), 'CosTransactions_Resource', rollback),
- notify_subtrAware(rollback, ?etr_get_subAw(NewL), Self),
- {stop, normal, ok, {NewEnv, NewL}};
-%% Replace the reply above if allow synchronization
-% case ?etr_get_sync(Local) of
-% [] ->
-% {stop, normal, ok, {NewEnv, NewL}};
-% _ ->
-% {reply, ok, {NewEnv, NewL}}
-% end;
- _ ->
- corba:raise(?tr_inactive)
- end.
-
-%%-----------------------------------------------------------%
-%% function : get_transaction_name
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% Returns : string - which describes the transaction associated
-%% with the target object.
-%% Effect : Intended for debugging.
-%%------------------------------------------------------------
-
-get_transaction_name(_Self, {Env, Local}) ->
- {reply, ?tr_get_etrap(Env), {Env, Local}}.
-
-%%-----------------------------------------------------------%
-%% function : create_subtransaction
-%% Arguments: Self - its own object reference.
-%% State - Gen-Server State
-%% Returns : A control object if subtransactions are allowed,
-%% otherwise an exception is raised.
-%% Effect : A new subtransaction is created whos parent is
-%% the transaction associated with the target object.
-%% Exception: SubtransactionUnavailabe - no support for nested
-%% transactions.
-%% Inactive - already been prepared.
-%%------------------------------------------------------------
-
-create_subtransaction(Self, {Env, Local}) ->
- case ?etr_get_status(Local) of
- 'StatusActive' ->
- case ?tr_get_subTraOK(Env) of
- true ->
- ETraPName = 'ETraP_Common':create_name("subc"),
- Tname = 'ETraP_Common':create_name("subt"),
-
- %% Create context for the new object.
- State = ?tr_create_context(ETraPName, Tname,
- ?tr_get_typeCheck(Env),
- ?tr_get_hashMax(Env),
- ?tr_get_subTraOK(Env),
- ?tr_get_maxR(Env),
- ?tr_get_maxW(Env)),
-
-
- State2 = ?tr_add_parent(State, Self),
-
- State3 = ?tr_set_alarm(State2, ?tr_get_alarm(Env)),
-
- State4 = ?tr_set_timeout(State3, ?tr_get_timeout(Env)),
-
- Control = ?tr_start_child(?SUP_ETRAP(State4)),
- %% Set the SubCoordinator object reference and register it as participant.
- SubCoord = 'CosTransactions_Control':get_coordinator(Control),
- NewLocal = ?etr_add_member(Local, SubCoord),
- {reply, Control, {Env, NewLocal}, ?tr_get_timeout(Env)};
- _ ->
- %% subtransactions not allowed, raise exception.
- corba:raise(?tr_subunavailable)
- end;
- _->
- corba:raise(?tr_inactive)
- end.
-
-%%-----------------------------------------------------------%
-%% function : get_txcontext
-%% Arguments:
-%% Returns : PropagationContext
-%% Effect :
-%%------------------------------------------------------------
-
--spec get_txcontext(_, _) -> no_return().
-get_txcontext(_Self, {_Env, _Local}) ->
- corba:raise(#'CosTransactions_Unavailable'{}).
-
-%get_txcontext(Self, {Env, Local}) ->
-% Otid = #'CosTransactions_otid_t'{formatID=0,
-% bqual_length=0,
-% tid=[corba_object:hash(Self,
-% ?tr_get_hashMax(Env))]},
-% TrIDs = create_TransIdentities(?tr_get_parents(Env), Env, [], Otid),
-% C=case ?tr_get_parents(Env) of
-% [] ->
-% #'CosTransactions_TransIdentity'{coord=Self,
-% term=?tr_get_terminator(Env),
-% otid=Otid};
-% _->
-% #'CosTransactions_TransIdentity'{coord=Self,
-% term=?tr_NIL_OBJ_REF,
-% otid=Otid}
-% end,
-% case ?tr_get_timeout(Env) of
-% infinity ->
-% #'CosTransactions_PropagationContext'{timeout=0,
-% current= C,
-% parents=TrIDs};
-% T ->
-% #'CosTransactions_PropagationContext'{timeout=T/1000,
-% current= C,
-% parents=TrIDs}
-% end.
-
-%create_TransIdentities([], _, Parents, _) -> Parents;
-%create_TransIdentities([Phead|Ptail], Env, Parents, Otid) ->
-% NO=Otid#'CosTransactions_TransIdentity'{otid=
-% corba_object:hash(Phead,
-% ?tr_get_hashMax(Env))},
-% create_TransIdentities([Phead|Ptail], Env, Parents++
-% [#'CosTransactions_TransIdentity'{coord=Phead,
-% term=?tr_NIL_OBJ_REF,
-% otid=NO}],
-% Otid).
-
-
-%%--------- Inherit from CosTransactions::Synchronization ---
-
-%%-----------------------------------------------------------%
-%% function : before_completion
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-
-%before_completion(Self, {Env, Local}) ->
-% send_info(?etr_get_sync(Local),
-% 'CosTransactions_Synchronization', before_completion),
-% {reply, ok, {Env, Local}}.
-
-%%-----------------------------------------------------------%
-%% function : after_completion
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-
-%after_completion(Self, {Env, Local}, Status) ->
-% send_info(?etr_get_sync(Local), Status,
-% 'CosTransactions_Synchronization', after_completion),
-% {stop, normal, ok, {Env, Local}}.
-
-%%--------------- IMPLEMENTATION SPECIFIC -------------------
-%%-----------------------------------------------------------%
-%% function : start_object
-%% Arguments:
-%% Returns : EXIT, EXCEPTION, or {ok, State}
-%% Effect : used by init/1 only.
-%%------------------------------------------------------------
-
-start_object(Env)->
- ?put_debug_data(self, Env),
- Local = ?etr_get_init(Env),
- LogName = ?tr_get_etrap(Env),
- case catch file:read_file_info(LogName) of
- {error, enoent} ->
- %% File does not exist. It's the first time. No restart.
- ?debug_print("ETraP_Server:init(~p)~n",[?tr_get_etrap(Env)]),
- etrap_logmgr:start(LogName),
- {ok,
- {Env, ?etr_set_status(Local, 'StatusActive')},
- ?tr_get_timeout(Env)};
- {error, Reason} ->
- %% File exist but error occurred.
- ?tr_error_msg("Control (~p) Cannot open log file: ~p~n",
- [LogName, Reason]),
- {stop, "unable_to_open_log"};
- _ ->
- %% File exists, perform restart.
- etrap_logmgr:start(LogName),
- ?debug_print("RESTART ~p~n", [?tr_get_etrap(Env)]),
- prepare_restart({Env, ?etr_set_status(Local, 'StatusUnknown')},
- ?etr_read(?tr_get_etrap(Env), start))
- end.
-
-
-%%-----------------------------------------------------------%
-%% function : send_prepare
-%% Arguments: List of registred resources.
-%% Returns : ok - equal to void
-%% Effect : calls send_prepare/3, which sends a prepare call
-%% to resources participating in the transaction and then collect
-%% their votes. send_prepare will block until
-%% it recieves a reply from the resource.
-%%------------------------------------------------------------
-
-send_prepare(RegResources, Alarm) ->
- send_prepare(RegResources, [], Alarm).
-
-% All voted ReadOnly. We are done.
-send_prepare([], [], _) ->
- readOnly;
-
-% All voted commit (VC) or ReadOnly.
-send_prepare([], VC, Alarm) ->
- case catch try_timeout(Alarm) of
- false ->
- {commit, VC};
- _->
- {rollback, VC}
- end;
-
-send_prepare([Rhead|Rtail], VC, Alarm) ->
- ?debug_print("send_prepare()~n",[]),
- case catch 'CosTransactions_Resource':prepare(Rhead) of
- 'VoteCommit' ->
- case catch try_timeout(Alarm) of
- false ->
- _Env = ?get_debug_data(self),
- ?eval_debug_fun({?tr_get_etrap(_Env), send_prepare}, _Env),
- send_prepare(Rtail, VC++[Rhead], Alarm);
- _->
- %% Timeout, rollback. However, the resource did vote
- %% commit. Add it to the list.
- send_info(Rtail, 'CosTransactions_Resource', rollback),
- {rollback, VC++[Rhead]}
- end;
- 'VoteRollback' ->
- %% Don't care about timeout since we voted rollback.
- %% A rollback received. No need for more prepare-calls.
- %% See OMG 10-51, Transaction Service:v1.0
- send_info(Rtail, 'CosTransactions_Resource', rollback),
- {rollback, VC};
- 'VoteReadOnly' ->
- case catch try_timeout(Alarm) of
- false ->
- send_prepare(Rtail, VC, Alarm);
- _->
- %% timeout, reply rollback.
- send_info(Rtail, 'CosTransactions_Resource', rollback),
- {rollback, VC}
- end;
- {'EXCEPTION',E} when is_record(E, 'TIMEOUT') ->
- ?tr_error_msg("Coordinator:prepare( ~p )~nObject unreachable.~n",
- [Rhead]),
- %% Since we use presumed abort we will rollback the transaction.
- send_info(Rtail, 'CosTransactions_Resource', rollback),
- {rollback, VC};
- {'EXCEPTION',E} when is_record(E, 'TRANSIENT') ->
- ?tr_error_msg("Coordinator:prepare( ~p )~nObject unreachable.~n",
- [Rhead]),
- %% Since we use presumed abort we will rollback the transaction.
- send_info(Rtail, 'CosTransactions_Resource', rollback),
- {rollback, VC};
- {'EXCEPTION',E} when is_record(E, 'COMM_FAILURE') ->
- ?tr_error_msg("Coordinator:prepare( ~p )~nObject unreachable.~n",
- [Rhead]),
- %% Since we use presumed abort we will rollback the transaction.
- send_info(Rtail, 'CosTransactions_Resource', rollback),
- {rollback, VC};
- {'EXCEPTION', E} when is_record(E, 'OBJECT_NOT_EXIST') ->
- ?tr_error_msg("Coordinator:prepare( ~p )~nObject unreachable.~n",
- [Rhead]),
- send_info(Rtail, 'CosTransactions_Resource', rollback),
- {rollback, VC};
- {'EXCEPTION', Exc} ->
- ?tr_error_msg("Coordinator:prepare( ~p )~nThe Object raised exception: ~p~n",
- [Rhead, Exc]),
- send_info(Rtail, 'CosTransactions_Resource', rollback),
- %% This can occur if a subtransaction get one or more
- %% "VoteCommit" followed by a "VoteRollback".
- %% The subtransaction then do a send_decision(rollback),
- %% which can generate Heuristic decisions. Must rollback
- %% since at least one participant voted rollback.
- {'EXCEPTION', Exc, VC, Rhead};
- Other ->
- ?tr_error_msg("Coordinator:prepare( ~p ) failed. REASON ~p~n",
- [Rhead, Other]),
- send_info(Rtail, 'CosTransactions_Resource', rollback),
- {failed, VC}
- end.
-
-%%-----------------------------------------------------------%
-%% function : type_check
-%% Arguments: Bool - perform typecheck?
-%% ID - Type it should be.
-%% Func - Name of the function (for error_msg)
-%% Obj - objectrefernce to test.
-%% Returns : 'ok' or raises exception.
-%% Effect :
-%%------------------------------------------------------------
-type_check(false, _, _, _) ->
- ok;
-type_check(_, ID, Func, Obj) ->
- case catch corba_object:is_a(Obj,ID) of
- true ->
- ok;
- _ ->
- ?tr_error_msg("~p( ~p ) Bad argument!!~n", [Func, Obj]),
- corba:raise(?tr_badparam)
- end.
-
-%%-----------------------------------------------------------%
-%% function : is_heuristic
-%% Arguments: Exception
-%% Returns : boolean
-%% Effect : Returns true if the exception is a heuristic exc.
-%%------------------------------------------------------------
-
-is_heuristic(E) when is_record(E, 'CosTransactions_HeuristicMixed') -> true;
-is_heuristic(E) when is_record(E, 'CosTransactions_HeuristicHazard') -> true;
-is_heuristic(E) when is_record(E, 'CosTransactions_HeuristicCommit') -> true;
-is_heuristic(E) when is_record(E, 'CosTransactions_HeuristicRollback') -> true;
-is_heuristic(_) -> false.
-
-%%-----------------------------------------------------------%
-%% function : exception_set
-%% Arguments: Genserver state
-%% Returns :
-%% Effect : Used when restarting.
-%%------------------------------------------------------------
-
-exception_set({Env,Local}) ->
- case ?etr_get_exc(Local) of
- void ->
- self() ! {suicide, self()},
- {ok, {Env, Local}};
- _ ->
- {ok, {Env, Local}}
- end.
-
-%%-----------------------------------------------------------%
-%% function : set_exception
-%% Arguments: Locally defined #exc{}
-%% Heuristic mixed or hazard Exeption
-%% Returns : Altered locally defined #exc{}
-%% Effect : Set the correct tuple member to true.
-%%------------------------------------------------------------
-
-set_exception(Exc, E) when is_record(E, 'CosTransactions_HeuristicMixed') ->
- Exc#exc{mixed = true};
-set_exception(Exc, E) when is_record(E, 'CosTransactions_HeuristicHazard') ->
- Exc#exc{hazard = true};
-set_exception(Exc, _) -> Exc.
-
-%%-----------------------------------------------------------%
-%% function : send_forget
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-
-send_forget([], _) -> ok;
-send_forget([Rhead|Rtail], LogName) ->
- ?debug_print("send_forget()~n",[]),
- _Env = ?get_debug_data(self),
- case catch 'CosTransactions_Resource':forget(Rhead) of
- ok ->
- ?eval_debug_fun({?tr_get_etrap(_Env), send_forget1}, _Env),
- ?etr_log(LogName, {forgotten, Rhead}),
- ?eval_debug_fun({?tr_get_etrap(_Env), send_forget2}, _Env),
- send_forget(Rtail, LogName);
- Other ->
- ?tr_error_msg("CosTransactions_Coordinator failed sending forget to ~p~nREASON: ~p~n",
- [Rhead, Other]),
- ?eval_debug_fun({?tr_get_etrap(_Env), send_forget3}, _Env),
- ?etr_log(LogName, {not_forgotten, Rhead}),
- ?eval_debug_fun({?tr_get_etrap(_Env), send_forget4}, _Env),
- send_forget(Rtail, LogName)
- end.
-
-%%-----------------------------------------------------------%
-%% function : send_decision
-%% Arguments: List of registred resources which vote commit.
-%% Vote - the outcome of the transaction.
-%% Returns : ok - equal to void
-%% Effect : Inform those who voted commit of the outcome.
-%% They who voted rollback already knows the outcome.
-%% They who voted ReadOnly are not affected.
-%%------------------------------------------------------------
-
-%%-- Adding extra parameters
-send_decision({Env, Local}, Reply, Vote) ->
- send_decision({Env, Local}, Reply, ?etr_get_vc(Local), Vote, #exc{}, [], 0).
-send_decision({Env, Local}, Reply, Vote, VC) ->
- send_decision({Env, Local}, Reply, VC, Vote, #exc{}, [], 0).
-send_decision(State, no_reply, VC, Vote, Exc) ->
- send_decision(State, no_reply, VC, Vote, Exc, [], 0).
-
-%%-- Decision sent to all members. Do not reply (used when restarting).
-send_decision({Env, Local}, no_reply, [], _, #exc{mixed = true}, [], _) ->
- {Env, ?etr_set_exc(Local, ?tr_mixed)};
-send_decision({Env, Local}, no_reply, [], _, #exc{hazard = true}, [], _) ->
- {Env, ?etr_set_exc(Local, ?tr_hazard)};
-send_decision({Env, Local}, no_reply, [], _, _, [], _) ->
- {Env, Local};
-send_decision({Env, Local}, no_reply, [], Vote, Exc, Failed, Times) ->
- case ?tr_get_maxR(Env) of
- Times ->
- ?tr_error_msg("MAJOR ERROR, failed sending commit decision to: ~p. Tried ~p times.", [Failed,Times]),
- {Env, ?etr_set_exc(Local, ?tr_hazard)};
- _->
- timer:sleep(?tr_get_maxW(Env)),
- NewTimes = Times+1,
- send_decision({Env, Local}, no_reply, Failed, Vote, Exc, [], NewTimes)
- end;
-%%-- end special cases.
-
-%% Decision sent to all members. Test exceptions.
-send_decision({Env, Local}, Reply, [], Vote, Exc, [], _) ->
- notify_subtrAware(Vote, ?etr_get_subAw(Local), ?etr_get_self(Local)),
- test_exc(Exc, Vote, Reply, {Env, Local});
-%% Decision not sent to all members (one or more failed). Retry.
-send_decision({Env, Local}, Reply, [], Vote, Exc, Failed, Times) ->
- case ?tr_get_maxR(Env) of
- Times ->
- ?tr_error_msg("MAJOR ERROR, failed sending commit decision to: ~p. Tried ~p times.", [Failed,Times]),
- notify_subtrAware(Vote, ?etr_get_subAw(Local), ?etr_get_self(Local)),
- test_exc(Exc#exc{hazard = true}, Vote, Reply, {Env, Local});
- _->
- NewTimes = Times+1,
- timer:sleep(?tr_get_maxW(Env)),
- send_decision({Env, Local}, Reply, Failed, Vote, Exc, [], NewTimes)
- end;
-
-send_decision({Env, Local}, Reply, [Rhead|Rtail], Vote, Exc, Failed, Times) ->
- ?debug_print("Coordinator:send_decision(~p) Try: ~p~n",[Vote, Times]),
- case catch 'CosTransactions_Resource':Vote(Rhead) of
- ok ->
- ?etr_log(?tr_get_etrap(Env),{sent, Rhead}),
- send_decision({Env, Local}, Reply, Rtail, Vote, Exc, Failed, Times);
- {'EXCEPTION', E} when Vote == commit andalso
- is_record(E, 'CosTransactions_NotPrepared') ->
- ?debug_print("send_decision resource unprepared~n",[]),
- case catch 'CosTransactions_Resource':prepare(Rhead) of
- 'VoteCommit' ->
- send_decision({Env, Local}, Reply, [Rhead|Rtail], Vote, Exc, Failed, Times);
- 'VoteRollback' ->
- send_decision({Env, Local}, Reply, Rtail, Vote, Exc#exc{mixed = true}, Failed, Times);
- {'EXCEPTION', E} ->
- {SetExc, NewL, DidFail} =
- evaluate_answer(E, Rhead, Vote, Exc,
- ?tr_get_etrap(Env), Local),
- send_decision({Env, NewL}, Reply, Rtail, Vote, SetExc, DidFail++Failed, Times)
- end;
- {'EXCEPTION', E} ->
- {SetExc, NewL, DidFail} =
- evaluate_answer(E, Rhead, Vote, Exc, ?tr_get_etrap(Env), Local),
- ?tr_error_msg("Resource:~p( ~p )~nRaised Exception: ~p~n",
- [Vote, Rhead, E]),
- send_decision({Env, NewL}, Reply, Rtail, Vote, SetExc, DidFail++Failed, Times);
- {'EXIT', _} ->
- send_decision({Env, Local}, Reply, Rtail,
- Vote, Exc, [Rhead|Failed], Times);
- Other ->
- ?tr_error_msg("Resource:~p( ~p ) failed.~nREASON: ~p~n",
- [Vote, Rhead, Other]),
- case catch corba_object:non_existent(Rhead) of
- true when Vote == commit ->
- %% Presumed rollback
- send_decision({Env, Local}, Reply, Rtail, Vote,
- Exc#exc{mixed = true}, Failed, Times);
- true ->
- %% Presumed rollback
- send_decision({Env, Local}, Reply, Rtail, Vote,
- Exc#exc{hazard = true}, Failed, Times);
- _ ->
- send_decision({Env, Local}, Reply, Rtail,
- Vote, Exc, [Rhead|Failed], Times)
- end
- end.
-
-%%-----------------------------------------------------------%
-%% function : notify_subtrAware,
-%% Arguments:
-%% Returns :
-%% Effect : Invoke an operation on a list of objects. We don't
-%% care about return values or exceptions.
-%%------------------------------------------------------------
-
-notify_subtrAware(commit, Resources, Self) ->
- send_info(Resources, Self,
- 'CosTransactions_SubtransactionAwareResource',
- commit_subtransaction);
-notify_subtrAware(_, Resources, _) ->
- send_info(Resources, 'CosTransactions_SubtransactionAwareResource',
- rollback_subtransaction).
-
-%%-----------------------------------------------------------%
-%% function : send_info
-%% Arguments: ObjectList - List of object refernces to call.
-%% M - Module
-%% F - Function
-%% (Arg - required arguments)
-%% Returns : ok
-%% Effect : A lightweight function to be used when we don't
-%% "care" about the return value.
-%%------------------------------------------------------------
-
-send_info([], _, _, _) ->
- ok;
-send_info([Rhead|Rtail], Arg, M, F) ->
- ?debug_print("~p( ~p )~n",[F, Arg]),
- case catch M:F(Rhead, Arg) of
- {'EXIT',R} ->
- ?tr_error_msg("~p:~p(~p, ~p) returned {'EXIT',~p}", [M,F,Rhead,Arg,R]);
- {'EXCEPTION',E} ->
- ?tr_error_msg("~p:~p(~p, ~p) returned {'EXCEPTION',~p}", [M,F,Rhead,Arg,E]);
- _->
- ok
- end,
- send_info(Rtail, Arg, M, F).
-
-send_info([], _, _) ->
- ok;
-send_info([Rhead|Rtail], M, F) ->
- ?debug_print("~p( )~n",[F]),
- case catch M:F(Rhead) of
- {'EXIT',R} ->
- ?tr_error_msg("~p:~p(~p) returned {'EXIT',~p}", [M,F,Rhead,R]);
- {'EXCEPTION',E} ->
- ?tr_error_msg("~p:~p(~p) returned {'EXCEPTION',~p}", [M,F,Rhead,E]);
- _->
- ok
- end,
- send_info(Rtail, M, F).
-
-%%-----------------------------------------------------------%
-%% function : evaluate_answer
-%% Arguments:
-%% Returns :
-%% Effect : Check what kind of exception we received.
-%%------------------------------------------------------------
-
-evaluate_answer(E, Rhead, _Vote, Exc, Log, Local)
- when is_record(E, 'CosTransactions_HeuristicMixed') ->
- ?etr_log(Log, {heuristic, {Rhead, E}}),
- {Exc#exc{mixed = true}, ?etr_add_raisedH(Local, Rhead), []};
-evaluate_answer(E, Rhead, _Vote, Exc, Log, Local)
- when is_record(E, 'CosTransactions_HeuristicHazard') ->
- ?etr_log(Log, {heuristic, {Rhead, E}}),
- {Exc#exc{hazard = true}, ?etr_add_raisedH(Local, Rhead), []};
-evaluate_answer(E, Rhead, Vote, Exc, Log, Local)
- when is_record(E, 'CosTransactions_HeuristicCommit') ->
- case Vote of
- commit ->
- ?etr_log(Log, {heuristic, {Rhead, E}}),
- {Exc, ?etr_add_raisedH(Local, Rhead), []};
- _->
- ?etr_log(Log, {heuristic, {Rhead, ?tr_mixed}}),
- {Exc#exc{mixed = true}, ?etr_add_raisedH(Local, Rhead), []}
- end;
-evaluate_answer(E, Rhead, Vote, Exc, Log, Local)
- when is_record(E, 'CosTransactions_HeuristicRollback')->
- case Vote of
- rollback ->
- ?etr_log(Log, {heuristic, {Rhead, ?tr_rollback}}),
- {Exc, ?etr_add_raisedH(Local, Rhead), []};
- _->
- ?etr_log(Log, {heuristic, {Rhead, ?tr_mixed}}),
- {Exc#exc{mixed = true}, ?etr_add_raisedH(Local, Rhead), []}
- end;
-evaluate_answer(E, Rhead, Vote, Exc, Log, Local)
- when Vote == commit andalso is_record(E, 'TRANSACTION_ROLLEDBACK') ->
- ?etr_log(Log, {heuristic, {Rhead, ?tr_mixed}}),
- {Exc#exc{mixed = true}, ?etr_add_raisedH(Local, Rhead), []};
-evaluate_answer(E, Rhead, Vote, Exc, Log, Local) when is_record(E, 'TIMEOUT') ->
- ?tr_error_msg("Coordinator:~p( ~p ) Object unreachable.~nReason: ~p~n",
- [Vote, Rhead, E]),
- case catch corba_object:non_existent(Rhead) of
- true ->
- %% Since we have presumed abort, the child will
- %% assume rollback if this server do not exist any more.
- ?etr_log(Log, {heuristic, {Rhead, ?tr_hazard}}),
- {Exc#exc{hazard = true}, Local, []};
- _ ->
- {Exc, Local, [Rhead]}
- end;
-evaluate_answer(E, Rhead, Vote, Exc, Log, Local) when is_record(E, 'TRANSIENT') ->
- ?tr_error_msg("Coordinator:~p( ~p ) Object unreachable.~nReason: ~p~n",
- [Vote, Rhead, E]),
- case catch corba_object:non_existent(Rhead) of
- true ->
- %% Since we have presumed abort, the child will
- %% assume rollback if this server do not exist any more.
- ?etr_log(Log, {heuristic, {Rhead, ?tr_hazard}}),
- {Exc#exc{hazard = true}, Local, []};
- _ ->
- {Exc, Local, [Rhead]}
- end;
-evaluate_answer(E, Rhead, Vote, Exc, Log, Local) when is_record(E, 'COMM_FAILURE') ->
- ?tr_error_msg("Coordinator:~p( ~p ) Object unreachable.~nReason: ~p~n",
- [Vote, Rhead, E]),
- case catch corba_object:non_existent(Rhead) of
- true ->
- %% Since we have presumed abort, the child will
- %% assume rollback if this server do not exist any more.
- ?etr_log(Log, {heuristic, {Rhead, ?tr_hazard}}),
- {Exc#exc{hazard = true}, Local, []};
- _ ->
- {Exc, Local, [Rhead]}
- end;
-evaluate_answer(E, Rhead, Vote, Exc, Log, Local)when is_record(E, 'OBJECT_NOT_EXIST') ->
- ?tr_error_msg("Coordinator:~p( ~p ) Object unreachable.~nReason: ~p~n",
- [Vote, Rhead, E]),
- %% Since we have presumed abort, the child will
- %% assume rollback if this server do not exist any more.
- ?etr_log(Log, {heuristic, {Rhead, ?tr_hazard}}),
- {Exc#exc{hazard = true}, Local, []};
-evaluate_answer(Unknown, Rhead, Vote, Exc, _Log, Local)->
- ?tr_error_msg("Coordinator:~p( ~p ). Unknown reply: ~p.~n",
- [Vote, Rhead, Unknown]),
- {Exc, Local, []}.
-
-
-%%-----------------------------------------------------------%
-%% function : test_exc
-%% Arguments: Exc - instance of #exc{} locally declared.
-%% Vote - 'rollback' or 'commit'
-%% Reply - If no exceptions this is the default reply.
-%% State - genserver state
-%% Returns :
-%% Effect : Raise the correct exception or simply reply to
-%% the genserver. NOTE that the testing for exceptions
-%% differs if we are performing a rollback or commit.
-%% Check if Mixed first; takes priority over Hazard.
-%% HeuristicRollback and VoteCommit together give
-%% HeuristicMixed
-%% HeuristicCommit and VoteRollback together give
-%% HeuristicMixed
-%%------------------------------------------------------------
-
-test_exc(#exc{mixed = true}, _, _, {Env, Local}) ->
- {reply, {'EXCEPTION', ?tr_mixed}, {Env, ?etr_set_exc(Local, ?tr_mixed)}};
-% Left out for now to avoid dialyzer warning.
-%test_exc(#exc{rollback = true}, commit, _, {Env, Local}) ->
-% {reply, {'EXCEPTION', ?tr_mixed}, {Env, ?etr_set_exc(Local, ?tr_mixed)}};
-% Left out for now to avoid dialyzer warning.
-%test_exc(#exc{commit = true}, rollback, _, {Env, Local}) ->
-% {reply, {'EXCEPTION', ?tr_mixed}, {Env, ?etr_set_exc(Local, ?tr_mixed)}};
-test_exc(#exc{hazard = true}, _, _, {Env, Local}) ->
- {reply, {'EXCEPTION', ?tr_hazard}, {Env, ?etr_set_exc(Local, ?tr_hazard)}};
-test_exc(_, _, {'EXCEPTION', E}, {Env, Local})
- when is_record(E, 'TRANSACTION_ROLLEDBACK')->
- {stop, normal, {'EXCEPTION', E}, {Env, Local}};
-%% Replace the case above if allow synchronization
-%test_exc(_, _, {'EXCEPTION', E}, {Env, Local})
-% when record(E, 'TRANSACTION_ROLLEDBACK')->
-% case ?etr_get_sync(Local) of
-% [] ->
-% {stop, normal, {'EXCEPTION', E}, {Env, Local}};
-% _->
-% {reply, {'EXCEPTION', E}, {Env, Local}}
-% end;
-test_exc(_, _, {'EXCEPTION', E}, State) ->
- {reply, {'EXCEPTION', E}, State};
-test_exc(_, _, Reply, {Env, Local}) ->
- {stop, normal, Reply, {Env, Local}}.
-%% Replace the case above if allow synchronization
-%test_exc(_, _, Reply, {Env, Local}) ->
-% case ?etr_get_sync(Local) of
-% [] ->
-% {stop, normal, Reply, {Env, Local}};
-% _ ->
-% {reply, Reply, {Env, Local}}
-% end.
-
-%%-----------------------------------------------------------%
-%% function : evaluate_status
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-
-evaluate_status(Status) ->
- case Status of
- 'StatusCommitted' -> commit;
- 'StatusCommitting' -> commit;
- 'StatusMarkedRollback' -> rollback;
- 'StatusRollingBack' -> rollback;
- 'StatusRolledBack' -> rollback;
- 'StatusActive' -> rollback;
- 'StatusPrepared' -> rollback;
- 'StatusUnknown' -> rollback;
- 'StatusNoTransaction' -> rollback;
- 'StatusPreparing' -> rollback;
- _-> rollback
- end.
-
-
-%%-----------------------------------------------------------%
-%% function : prepare_restart
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-
-%% The file contains no data. The coordinator crashed before
-%% a prepare-call was made. Presumed rollback.
-prepare_restart(State, eof) ->
- ?debug_print("prepare_restart: eof, init~n",[]),
- self() ! {suicide, self()},
- {ok, State};
-%% Collected all necessary votes. Do commit_restart.
-prepare_restart({Env, _}, {{pre_vote, _Vote, Data}, Cursor}) ->
- ?debug_print("prepare_restart: pre_vote( ~p )~n",[_Vote]),
- if
- ?tr_is_root(Env) ->
- commit_restart({Env, Data},
- ?etr_read(?tr_get_etrap(Env), Cursor), root);
- true ->
- commit_restart({Env, Data},
- ?etr_read(?tr_get_etrap(Env), Cursor), subCoord)
- end;
-%% 'rollback' called without 'prepare'. This case occurs if the Coordinator
-%% crashes when send_info or notify_subtrAware.
-prepare_restart({Env, _}, {{rollback, NewL}, _Cursor}) ->
- ?debug_print("prepare_restart: pre_vote( rollback )~n",[]),
- send_info(?etr_get_members(NewL), 'CosTransactions_Resource', rollback),
- notify_subtrAware(rollback, ?etr_get_subAw(NewL), ?etr_get_self(NewL)),
- self() ! {suicide, self()},
- {ok, {Env, NewL}};
-%% Something is wrong in the log.
-prepare_restart(_, _) ->
- ?tr_error_msg("Internal log read failed:~n", []),
- {stop, {error, "restart failed"}}.
-
-%%-----------------------------------------------------------%
-%% function : commit_restart
-%% Arguments: Env - server context
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-commit_restart({Env, Local}, Data, Phase) ->
- Exc = set_exception(#exc{}, ?etr_get_exc(Local)),
- commit_restart({Env, Local}, Data, Phase, Exc).
-
-%% Normal case. No errors no exceptions.
-commit_restart({Env, Local}, {{sent, Obj}, Cursor}, Vote, Exc) ->
- ?debug_print("commit_restart: sent~n",[]),
- commit_restart({Env, ?etr_remove_vc(Local, Obj)},
- ?etr_read(?tr_get_etrap(Env), Cursor), Vote, Exc);
-commit_restart({Env, Local}, {{heuristic, {Obj,E}}, Cursor}, Vote, Exc) ->
- ?debug_print("commit_restart: heuristic ~p~n",[E]),
- NewExc = set_exception(Exc, E),
- commit_restart({Env, ?etr_add_raisedH(Local, Obj)},
- ?etr_read(?tr_get_etrap(Env), Cursor), Vote, NewExc);
-
-
-%% --- cases which only can occure once in the log ------------
-
-%% The file contains no data. The coordinator crashed before
-%% a decision was made. Causes rollback.
-commit_restart({E, L}, eof, root, Exc) ->
- ?debug_print("commit_restart: eof init (root only)~n",[]),
- {Env, Local} = send_decision({E, L}, no_reply, ?etr_get_vc(L),
- rollback, Exc),
- exception_set({Env, Local});
-%% Replace the reply above if allow synchronization
-% case ?etr_get_sync(Local) of
-% [] ->
-% exception_set({Env, Local});
-% SynchObjs ->
-% {ok, {Env, Local}}
-% end;
-
-
-%% Passed the prepare_restart. Not received a commit decision from the
-%% parent.
-commit_restart({E, L}, eof, subCoord, Exc) ->
- ?debug_print("commit_restart: eof init (subcoord only)~n",[]),
- case catch corba_object:non_existent(?tr_get_parent(E)) of
- true ->
- %% Presumed rollback.
- {Env, Local} = send_decision({E, L}, no_reply, ?etr_get_vc(L),
- rollback, Exc),
- self() ! {suicide, self()},
- {ok, {Env, Local}};
-%% Replace the reply above if allow synchronization
-% case ?etr_get_sync(Local) of
-% [] ->
-% self() ! {suicide, self()},
-% {ok, {Env, Local}};
-% SynchObjs ->
-% case ?tr_get_parents(Env) of
-% [] ->
-% send_info(SynchObjs, ?etr_get_status(Local),
-% 'CosTransactions_Synchronization', after_completion);
-% _->
-% ok
-% end,
-% self() ! {suicide, self()},
-% {ok, {Env, Local}}
-% end;
- _->
- {ok, {E, L}}
- end;
-
-commit_restart({Env, Local}, eof, Vote, Exc) ->
- ?debug_print("commit_restart: eof VOTE: ~p~n",[Vote]),
- case ?etr_get_vc(Local) of
- [] ->
- ?debug_print("commit_restart: all sent, test exc~n",[]),
- exception_set({Env, Local});
- VC ->
- ?debug_print("commit_restart: note done. send more~n",[]),
- State = send_decision({Env, Local}, no_reply, VC, Vote, Exc),
- exception_set(State)
- end;
-
-%% Decision made, i.e. rollback or commit.
-commit_restart({Env, Local}, {rollback, Cursor}, _Phase, Exc) ->
- ?debug_print("commit_restart: decided rollback~n",[]),
- commit_restart({Env, ?etr_set_status(Local, 'StatusRolledBack')},
- ?etr_read(?tr_get_etrap(Env), Cursor), rollback, Exc);
-commit_restart({Env, Local}, {commit, Cursor}, _Phase, Exc) ->
- ?debug_print("commit_restart: decided commit~n",[]),
- commit_restart({Env, ?etr_set_status(Local, 'StatusCommitted')},
- ?etr_read(?tr_get_etrap(Env), Cursor), commit, Exc);
-commit_restart({Env, Local}, {forget_phase, Cursor}, _, _) ->
- ?debug_print("commit_restart: start sending forget~n",[]),
- forget_restart({Env, Local}, ?etr_read(?tr_get_etrap(Env), Cursor));
-
-commit_restart({_Env, _Local}, _R, _, _) ->
- ?debug_print("RESTART FAIL: ~p~n",[_R]),
- ?tr_error_msg("Internal log read failed:~n", []),
- exit("restart failed").
-
-%%-----------------------------------------------------------%
-%% function : forget_restart
-%% Arguments: {Env, Local} - server context
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-
-%% Exception logged. Test if we issued a 'forget()' to the Resource.
-forget_restart({Env, Local}, eof) ->
- case ?etr_get_raisedH(Local) of
- [] ->
- ?debug_print("forget_restart: all done~n",[]);
- Left ->
- ?debug_print("forget_restart: not done. send more~n",[]),
- send_forget(Left, ?tr_get_etrap(Env))
- end,
- self() ! {suicide, self()},
- {ok, {Env, Local}};
-%% Replace the reply above if allow synchronization
-% case ?etr_get_sync(Local) of
-% [] ->
-% self() ! {suicide, self()},
-% {ok, {Env, Local}};
-% SynchObjs ->
-% case ?tr_get_parents(Env) of
-% [] ->
-% send_info(SynchObjs, ?etr_get_status(Local),
-% 'CosTransactions_Synchronization', after_completion),
-% self() ! {suicide, self()},
-% {ok, {Env, Local}};
-% _->
-% {ok, {Env, Local}}
-% end
-% end;
-forget_restart({Env, Local}, {{forgotten, Obj}, Cursor}) ->
- ?debug_print("forget_restart: forgotten heuristic~n",[]),
- NewL = ?etr_remove_raisedH(Local, Obj),
- forget_restart({Env, NewL}, ?etr_read(?tr_get_etrap(Env), Cursor));
-forget_restart({Env, Local}, {{not_forgotten, Obj}, Cursor}) ->
- ?debug_print("forget_restart: not_forgotten~n",[]),
- NewL = ?etr_remove_raisedH(Local, Obj),
- send_forget([Obj], dummy),
- forget_restart({Env, NewL}, ?etr_read(?tr_get_etrap(Env), Cursor)).
-
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosTransactions/src/Makefile b/lib/cosTransactions/src/Makefile
deleted file mode 100644
index 4cc1e487c2..0000000000
--- a/lib/cosTransactions/src/Makefile
+++ /dev/null
@@ -1,181 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-EBIN=../ebin
-
-ifeq ($(TYPE),debug)
-ERL_COMPILE_FLAGS += -Ddebug -W
-endif
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(COSTRANSACTIONS_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/cosTransactions-$(VSN)
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES = \
- ETraP_Common \
- etrap_logmgr \
- ETraP_Server_impl \
- CosTransactions_Terminator_impl \
- CosTransactions_TransactionFactory_impl \
- cosTransactions
-
-ERL_FILES = $(MODULES:%=%.erl)
-HRL_FILES = \
- ETraP_Common.hrl
-
-GEN_ERL_FILES = \
- oe_CosTransactions.erl \
- CosTransactions_Control.erl \
- CosTransactions_Coordinator.erl \
- CosTransactions_HeuristicCommit.erl \
- CosTransactions_HeuristicHazard.erl \
- CosTransactions_HeuristicMixed.erl \
- CosTransactions_HeuristicRollback.erl \
- CosTransactions_Inactive.erl \
- CosTransactions_InvalidControl.erl \
- CosTransactions_NoTransaction.erl \
- CosTransactions_NotPrepared.erl \
- CosTransactions_NotSubtransaction.erl \
- CosTransactions_RecoveryCoordinator.erl \
- CosTransactions_Resource.erl \
- CosTransactions_SubtransactionAwareResource.erl \
- CosTransactions_SubtransactionsUnavailable.erl \
- CosTransactions_Terminator.erl \
- CosTransactions_TransactionFactory.erl \
- CosTransactions_Unavailable.erl \
- CosTransactions_SynchronizationUnavailable.erl \
- CosTransactions_TransIdentity.erl \
- CosTransactions_PropagationContext.erl \
- CosTransactions_otid_t.erl \
- CosTransactions_WrongTransaction.erl \
- ETraP_Server.erl
-# CosTransactions_Synchronization.erl \
-
-EXTERNAL_INC_PATH = ../include
-
-GEN_HRL_FILES = \
- oe_CosTransactions.hrl \
- CosTransactions.hrl \
- CosTransactions_Control.hrl \
- CosTransactions_Coordinator.hrl \
- CosTransactions_RecoveryCoordinator.hrl \
- CosTransactions_Resource.hrl \
- CosTransactions_SubtransactionAwareResource.hrl \
- CosTransactions_Terminator.hrl \
- CosTransactions_TransactionFactory.hrl \
- ETraP.hrl \
- ETraP_Server.hrl
-# CosTransactions_Synchronization.hrl \
-
-EXTERNAL_GEN_HRL_FILES = $(GEN_HRL_FILES:%=$(EXTERNAL_INC_PATH)/%)
-
-GEN_FILES = $(GEN_ERL_FILES) $(EXTERNAL_GEN_HRL_FILES)
-
-TARGET_FILES = \
- $(GEN_ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR)) \
- $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-IDL_FILE = \
- CosTransactions.idl
-
-APPUP_FILE = cosTransactions.appup
-APPUP_SRC = $(APPUP_FILE).src
-APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
-
-APP_FILE = cosTransactions.app
-APP_SRC = $(APP_FILE).src
-APP_TARGET = $(EBIN)/$(APP_FILE)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/cosTransactions/ebin \
- -pa $(ERL_TOP)/lib/ic/ebin\
- -pa $(ERL_TOP)/lib/orber/ebin
-
-# The -pa option is just used temporary until erlc can handle
-# includes from other directories than ../include .
-ERL_COMPILE_FLAGS += \
- $(ERL_IDL_FLAGS) \
- -I$(ERL_TOP)/lib/cosTransactions/include \
- -I$(ERL_TOP)/lib/orber/include \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,app_vsn,"cosTransactions_$(COSTRANSACTIONS_VSN)"}'
-
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
-
-debug:
- @${MAKE} TYPE=debug
-
-clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
- rm -f errs core *~
-
-$(APP_TARGET): $(APP_SRC)
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $(APP_SRC) > $(APP_TARGET)
-
-$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
-
-docs:
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-IDL-GENERATED: CosTransactions.idl
- $(gen_verbose)erlc $(ERL_IDL_FLAGS) +'{cfgfile,"CosTransactions.cfg"}' CosTransactions.idl
- $(V_at)mv $(GEN_HRL_FILES) $(EXTERNAL_INC_PATH)
- $(V_at)>IDL-GENERATED
-
-$(GEN_FILES): IDL-GENERATED
-
-$(TARGET_FILES): IDL-GENERATED
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
- $(INSTALL_DIR) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(GEN_ERL_FILES) $(IDL_FILE) "$(RELSYSDIR)/src"
- $(INSTALL_DIR) "$(RELSYSDIR)/include"
- $(INSTALL_DATA) $(EXTERNAL_GEN_HRL_FILES) "$(RELSYSDIR)/include"
-
-release_docs_spec:
diff --git a/lib/cosTransactions/src/cosTransactions.app.src b/lib/cosTransactions/src/cosTransactions.app.src
deleted file mode 100644
index 074d82f487..0000000000
--- a/lib/cosTransactions/src/cosTransactions.app.src
+++ /dev/null
@@ -1,44 +0,0 @@
-{application, cosTransactions,
- [{description, "The Erlang CosTransactions application"},
- {vsn, "%VSN%"},
- {modules,
- [
- etrap_logmgr,
- 'ETraP_Server_impl',
- 'CosTransactions_Terminator_impl',
- 'CosTransactions_TransactionFactory_impl',
- 'ETraP_Common',
- oe_CosTransactions,
- 'CosTransactions_Control',
- 'CosTransactions_Coordinator',
- 'CosTransactions_HeuristicCommit',
- 'CosTransactions_HeuristicHazard',
- 'CosTransactions_HeuristicMixed',
- 'CosTransactions_HeuristicRollback',
- 'CosTransactions_Inactive',
- 'CosTransactions_InvalidControl',
- 'CosTransactions_NoTransaction',
- 'CosTransactions_NotPrepared',
- 'CosTransactions_NotSubtransaction',
- 'CosTransactions_RecoveryCoordinator',
- 'CosTransactions_Resource',
- 'CosTransactions_SubtransactionAwareResource',
- 'CosTransactions_SubtransactionsUnavailable',
- 'CosTransactions_Terminator',
- 'CosTransactions_TransactionFactory',
- 'CosTransactions_Unavailable',
- 'CosTransactions_SynchronizationUnavailable',
- 'CosTransactions_TransIdentity',
- 'CosTransactions_PropagationContext',
- 'CosTransactions_otid_t',
- 'CosTransactions_WrongTransaction',
- 'ETraP_Server',
- cosTransactions
- ]
- },
- {registered, [cosTransactions_sup, oe_cosTransactionsFactory]},
- {applications, [orber, stdlib, kernel]},
- {env, []},
- {mod, {cosTransactions, []}},
- {runtime_dependencies, ["stdlib-2.0","orber-3.6.27","kernel-3.0","erts-7.0"]}
-]}.
diff --git a/lib/cosTransactions/src/cosTransactions.appup.src b/lib/cosTransactions/src/cosTransactions.appup.src
deleted file mode 100644
index f3eead4a0c..0000000000
--- a/lib/cosTransactions/src/cosTransactions.appup.src
+++ /dev/null
@@ -1,6 +0,0 @@
-{"%VSN%",
- [
- ],
- [
- ]
-}.
diff --git a/lib/cosTransactions/src/cosTransactions.erl b/lib/cosTransactions/src/cosTransactions.erl
deleted file mode 100644
index 60e5fff46d..0000000000
--- a/lib/cosTransactions/src/cosTransactions.erl
+++ /dev/null
@@ -1,116 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : cosTransactions.erl
-%% Purpose : Initialize the 'cosTransactions' application
-%%----------------------------------------------------------------------
-
--module(cosTransactions).
-
-%%--------------- INCLUDES -----------------------------------
-%% Local
--include_lib("ETraP_Common.hrl").
--include_lib("CosTransactions.hrl").
-%%--------------- EXPORTS-------------------------------------
-%% cosTransactions API external
--export([start/0, stop/0, start_factory/1, start_factory/0, stop_factory/1]).
-
-%% Application callbacks
--export([start/2, init/1, stop/1]).
-
-%%------------------------------------------------------------
-%% function : start/stop
-%% Arguments:
-%% Returns :
-%% Effect : Starts or stops the cosTRansaction application.
-%%------------------------------------------------------------
-
-start() ->
- application:start(cosTransactions).
-stop() ->
- application:stop(cosTransactions).
-
-%%------------------------------------------------------------
-%% function : start_factory
-%% Arguments: none or an argumentlist which by default is defined
-%% in ETraP_Common.hrl, i.e., '?tr_FAC_DEF'
-%% Returns : ObjectRef | {'EXCEPTION', _} | {'EXIT', Reason}
-%% Effect : Starts a CosTransactions_TransactionFactory
-%%------------------------------------------------------------
-
-start_factory() ->
- ?tr_start_child(?SUP_FAC(?tr_FAC_DEF)).
-
-start_factory(Args) when is_list(Args) ->
- ?tr_start_child(?SUP_FAC(Args));
-start_factory(Args) ->
- ?tr_error_msg("applications:start( ~p ) failed. Bad parameters~n", [Args]),
- exit("applications:start failed. Bad parameters").
-
-%%------------------------------------------------------------
-%% function : stop_factory
-%% Arguments: Factory Object Reference
-%% Returns : ok | {'EXCEPTION', _}
-%% Effect :
-%%------------------------------------------------------------
-
-stop_factory(Fac)->
- corba:dispose(Fac).
-
-%%------------------------------------------------------------
-%% function : start
-%% Arguments: Type - see module application
-%% Arg - see module application
-%% Returns :
-%% Effect : Module callback for application
-%%------------------------------------------------------------
-
-start(_, _) ->
- supervisor:start_link({local, ?SUPERVISOR_NAME}, cosTransactions, app_init).
-
-
-%%------------------------------------------------------------
-%% function : stop
-%% Arguments: Arg - see module application
-%% Returns :
-%% Effect : Module callback for application
-%%------------------------------------------------------------
-
-stop(_) ->
- ok.
-
-%%------------------------------------------------------------
-%% function : init
-%% Arguments:
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-
-%% Starting using create_factory/X
-init(own_init) ->
- {ok,{?SUP_FLAG, [?SUP_CHILD]}};
-%% When starting as an application.
-init(app_init) ->
- {ok,{?SUP_FLAG, [?SUP_CHILD]}}.
-
-
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosTransactions/src/etrap_logmgr.erl b/lib/cosTransactions/src/etrap_logmgr.erl
deleted file mode 100644
index a5d9affe7d..0000000000
--- a/lib/cosTransactions/src/etrap_logmgr.erl
+++ /dev/null
@@ -1,201 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : etrap_logmgr.erl
-%% Purpose : Make it easier to use disk_log.
-%%----------------------------------------------------------------------
-
--module(etrap_logmgr).
-
-%%--------------- INCLUDES -----------------------------------
-%% Local
--include_lib("ETraP_Common.hrl").
-%%--------------- IMPORTS-------------------------------------
-%%--------------- EXPORTS-------------------------------------
--export([start/1, stop/1, log_safe/2, log_lazy/2, get_next/2]).
-
-
-%%------------------------------------------------------------
-%% function : start
-%% Arguments: LogName - name of the disk_log.
-%% Returns :
-%% Effect : creating linked log
-%%------------------------------------------------------------
-
-start(LogName) ->
- case catch disk_log:open([{name, LogName},
- {file, LogName},
- {type, halt},
- {size, infinity}]) of
- {ok, LogName} ->
- ok;
- {error, Reason} ->
- ?tr_error_msg("Initiating internal log failed: ~p", [Reason]),
- exit({error, Reason});
- {repaired, LogName, {recovered, _Rec}, {badbytes, _Bad}} ->
- ok;
- Other ->
- ?tr_error_msg("Initiating internal log failed: ~p", [Other]),
- exit({error, Other})
- end.
-
-%%------------------------------------------------------------
-%% function : stop
-%% Arguments: LogName - name of the disk_log.
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-
-stop(LogName) ->
- case catch disk_log:close(LogName) of
- ok ->
- ok;
- {error, Reason} ->
- ?tr_error_msg("Stopping internal log failed: ~p", [Reason]),
- {error, Reason};
- Other ->
- ?tr_error_msg("Stopping internal log failed: ~p", [Other]),
- {error, Other}
- end.
-
-
-%%------------------------------------------------------------
-%% function : log_safe
-%% Arguments: LogName - name of the disk_log. If 'dummy' is
-%% used nothing should be logged. Reason, reuse code.
-%% LogRecord - record to store in the log.
-%% Returns :
-%% Effect : Writes a logrecord and synchronizes to make sure
-%% that the record is stored.
-%%------------------------------------------------------------
-
-log_safe(dummy, _) ->
- ok;
-log_safe(LogName, LogRecord) ->
- case write_safe(LogName, LogRecord) of
- ok ->
- ok;
- _ ->
- %% We have to catch the exit because in some cases
- %% it's not possible to abort action in the 2PC-protocol.
- case catch start(LogName) of
- ok ->
- write_safe(LogName, LogRecord);
- {'EXIT', Reason} ->
- {error, Reason}
- end
- end.
-
-
-write_safe(LogName, LogRecord) ->
- case catch disk_log:log(LogName, LogRecord) of
- ok -> % wrote to kernel successfully
- case catch disk_log:sync(LogName) of
- ok -> % Written to disk successfully
- ok;
- {error, Reason} ->
- ?tr_error_msg("Internal log write failed: ~p ~p",
- [Reason, LogName]),
- {error, Reason};
- Other ->
- ?tr_error_msg("Internal log write failed: ~p ~p",
- [Other, LogName]),
- {error, Other}
- end;
- {error, Reason} ->
- ?tr_error_msg("Internal log write failed: ~p ~p", [Reason, LogName]),
- {error, Reason};
- Other ->
- ?tr_error_msg("Internal log write failed: ~p ~p", [Other, LogName]),
- {error, Other}
- end.
-
-
-%%------------------------------------------------------------
-%% function : log_lazy
-%% Arguments: LogName - name of the disk_log. If 'dummy' is
-%% used nothing should be logged. Reason, reuse code.
-%% LogRecord - record to store in the log.
-%% Returns :
-%% Effect : Writes a logrecord. The record may be lost.
-%%------------------------------------------------------------
-
-log_lazy(dummy, _LogRecord) ->
- ok;
-log_lazy(LogName, LogRecord) ->
- case write_lazy(LogName, LogRecord) of
- ok ->
- ok;
- _ ->
- %% We have to catch the exit because in some cases
- %% it's not possible to abort action in the 2PC-protocol.
- case catch start(LogName) of
- ok ->
- write_lazy(LogName, LogRecord);
- {'EXIT', Reason} ->
- {error, Reason}
- end
- end.
-
-write_lazy(LogName, LogRecord) ->
- case catch disk_log:log(LogName, LogRecord) of
- ok ->
- %% wrote to kernel successfully
- ok;
- {error, Reason} ->
- %% Write to kernel failed with Reason
- ?tr_error_msg("Internal log write failed: ~p", [Reason]),
- {error, Reason};
- Other ->
- %% unknown message received.
- ?tr_error_msg("Internal log write failed: ~p", [Other]),
- {error, Other}
- end.
-
-
-%%------------------------------------------------------------
-%% function : get_next
-%% Arguments: LogName - name of the disk_log.
-%% Cursor - place to read from.
-%% Returns : {Cursor, LogRecs} - A cursor and up to N logrecords.
-%% eof - the atom 'eof', indicating logfile empty.
-%% {error, Reason} - error.
-%% Effect :
-%% Purpose : Used when performing a REDO scan
-%%------------------------------------------------------------
-
-get_next(LogName, Cursor) ->
- case catch disk_log:chunk(LogName, Cursor, 1) of
- {NewCursor, [Data]} ->
- {Data, NewCursor};
- eof ->
- eof;
- {error, Reason} ->
- ?tr_error_msg("Internal log '~p' read failed: ~p",
- [LogName, Reason]),
- exit({error, Reason});
- _Other ->
- ?tr_error_msg("Internal log '~p' read failed: 'log_corrupt'", [LogName]),
- exit({error, "log_corrupt"})
- end.
-
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/cosTransactions/test/Makefile b/lib/cosTransactions/test/Makefile
deleted file mode 100644
index 58199248d1..0000000000
--- a/lib/cosTransactions/test/Makefile
+++ /dev/null
@@ -1,151 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-#ifeq ($(TYPE),debug)
-#ERL_COMPILE_FLAGS += -Ddebug -W
-#endif
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(COSTRANSACTIONS_VSN)
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/cosTransactions_test
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-TEST_SPEC_FILE = cosTransactions.spec
-COVER_FILE = cosTransactions.cover
-
-
-IDL_FILES = \
- etrap_test.idl
-
-IDLOUTDIR = idl_output
-
-MODULES = \
- transactions_SUITE \
- etrap_test_server_impl \
- etrap_test_lib \
- generated_SUITE
-
-GEN_MODULES = \
- oe_etrap_test \
- etrap_test_server
-
-GEN_HRL_FILES = \
- oe_etrap_test.hrl \
- etrap_test_server.hrl
-
-ERL_FILES = $(MODULES:%=%.erl)
-
-HRL_FILES = \
- etrap_test_lib.hrl
-
-GEN_FILES = \
- $(GEN_HRL_FILES:%=$(IDLOUTDIR)/%) \
- $(GEN_MODULES:%=$(IDLOUTDIR)/%.erl)
-
-GEN_TARGET_FILES = $(GEN_MODULES:%=$(IDLOUTDIR)/%.$(EMULATOR))
-
-SUITE_TARGET_FILES = $(MODULES:%=%.$(EMULATOR))
-
-TARGET_FILES = \
- $(GEN_TARGET_FILES) \
- $(SUITE_TARGET_FILES)
-
-
-# ----------------------------------------------------
-# PROGRAMS
-# ----------------------------------------------------
-LOCAL_CLASSPATH = $(ERL_TOP)/lib/cosTransactions/priv:$(ERL_TOP)/lib/cosTransactions/test
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/cosTransactions/ebin\
- -pa $(ERL_TOP)/lib/orber/ebin \
- -pa $(ERL_TOP)/lib/ic/ebin
-
-ERL_COMPILE_FLAGS += \
- $(ERL_IDL_FLAGS) \
- -pa $(ERL_TOP)/lib/orber/include \
- -pa $(ERL_TOP)/lib/cosTransactions/ebin \
- -pa $(ERL_TOP)/lib/cosTransactions/test/idl_output \
- -I$(ERL_TOP)/lib/orber/include \
- -I$(ERL_TOP)/lib/cosTransactions \
- -I$(ERL_TOP)/lib/cosTransactions/test/$(IDLOUTDIR)
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-
-tests debug opt: $(TARGET_FILES)
-
-clean:
- rm -f idl_output/*
- rm -f $(TARGET_FILES)
- rm -f errs core *~
-
-#debug:
-# @${MAKE} TYPE=debug
-
-docs:
-
-# ----------------------------------------------------
-# Special Targets
-# ----------------------------------------------------
-
-IDL-GENERATED: etrap_test.idl
- erlc $(ERL_IDL_FLAGS) -o$(IDLOUTDIR) \
- +'{cfgfile,"etrap_test.cfg"}' etrap_test.idl
- >IDL-GENERATED
-
-$(GEN_FILES): IDL-GENERATED
-
-$(TARGET_FILES): IDL-GENERATED
-
-# ----------------------------------------------------
-# Release Targets
-# ----------------------------------------------------
-# We don't copy generated intermediate erlang and hrl files
-
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec:
-
-release_docs_spec:
-
-release_tests_spec: tests
- $(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) \
- $(COVER_FILE) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(SUITE_TARGET_FILES) "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELSYSDIR)/$(IDLOUTDIR)"
- $(INSTALL_DATA) $(GEN_TARGET_FILES) $(GEN_FILES) \
- "$(RELSYSDIR)/$(IDLOUTDIR)"
-
diff --git a/lib/cosTransactions/test/cosTransactions.cover b/lib/cosTransactions/test/cosTransactions.cover
deleted file mode 100644
index b27bae999d..0000000000
--- a/lib/cosTransactions/test/cosTransactions.cover
+++ /dev/null
@@ -1,2 +0,0 @@
-{incl_app,cosTransactions,details}.
-
diff --git a/lib/cosTransactions/test/cosTransactions.spec b/lib/cosTransactions/test/cosTransactions.spec
deleted file mode 100644
index 9918c8ca16..0000000000
--- a/lib/cosTransactions/test/cosTransactions.spec
+++ /dev/null
@@ -1 +0,0 @@
-{suites,"../cosTransactions_test",all}.
diff --git a/lib/cosTransactions/test/etrap_test.cfg b/lib/cosTransactions/test/etrap_test.cfg
deleted file mode 100644
index a2bc7d3fb7..0000000000
--- a/lib/cosTransactions/test/etrap_test.cfg
+++ /dev/null
@@ -1,21 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-{this, "etrap_test::server"}.
-{{handle_info, "etrap_test::server"}, true}.
diff --git a/lib/cosTransactions/test/etrap_test.idl b/lib/cosTransactions/test/etrap_test.idl
deleted file mode 100644
index 7379115be7..0000000000
--- a/lib/cosTransactions/test/etrap_test.idl
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1999-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-//
-
-#ifndef _TEST_IDL
-#define _TEST_IDL
-#include <../src/CosTransactions.idl>
-module etrap_test {
-
- // interface server
- interface server :
- CosTransactions::Coordinator, CosTransactions::SubtransactionAwareResource,
- CosTransactions::RecoveryCoordinator, CosTransactions::Control {
- };
-// interface Server :
-// CosTransactions::Coordinator, CosTransactions::SubtransactionAwareResource,
-// CosTransactions::RecoveryCoordinator, CosTransactions::Control,
-// CosTransactions::Synchronization {
-// };
-
-}; // End of test Module
-
-#endif
diff --git a/lib/cosTransactions/test/etrap_test_lib.erl b/lib/cosTransactions/test/etrap_test_lib.erl
deleted file mode 100644
index e8d8c3a429..0000000000
--- a/lib/cosTransactions/test/etrap_test_lib.erl
+++ /dev/null
@@ -1,126 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(etrap_test_lib).
-
-%%--------------- INCLUDES ---------------------------------------------
--include("etrap_test_lib.hrl").
--include_lib("cosTransactions/src/ETraP_Common.hrl").
-
-%%--------------- EXPORTS ----------------------------------------------
--export([scratch_debug_fun/0,
- activate_debug_fun/5,
- update_debug_info/1,
- deactivate_debug_fun/3,
- eval_debug_fun/4,
- set_debug_context/4]).
-
-%%--------------- CONSTANTS/DEFINITIONS --------------------------------
--define(DEBUG_TAB, etrap_debug).
--record(debug_info, {id, function, type, file, line}).
-
-%%--------------- DEBUG FUNCTIONS --------------------------------------
-%% Managing conditional debug functions
-%%
-%% The main idea with the debug_fun's is to allow test programs
-%% to control the internal behaviour of CosTransactions.
-%%
-%% First should calls to ?eval_debug_fun be inserted at well
-%% defined places in CosTransaction's code. E.g. in critical situations
-%% of startup, transaction commit, backups etc.
-%%
-%% Then compile CosTransactions with the compiler option 'debug'.
-%%
-%% In test programs ?activate_debug_fun should be called
-%% in order to bind a fun to the debug identifier stated
-%% in the call to ?eval_debug_fun.
-
-scratch_debug_fun() ->
- catch ets:delete(?DEBUG_TAB),
- ets:new(?DEBUG_TAB,
- [set, public, named_table, {keypos, 2}]).
-
-activate_debug_fun(FunId, Fun, Type, File, Line) ->
- io:format("Activiating ~p RETRIES: ~p WAIT: ~p~n",
- [FunId, ?tr_max_retries, ?tr_comm_failure_wait]),
- Info = #debug_info{id = FunId,
- function = Fun,
- type = Type,
- file = File,
- line = Line},
- update_debug_info(Info).
-
-update_debug_info(Info) ->
- case catch ets:insert(?DEBUG_TAB, Info) of
- {'EXIT', _} ->
- scratch_debug_fun(),
- ets:insert(?DEBUG_TAB, Info);
- _ ->
- ok
- end,
- ok.
-
-deactivate_debug_fun(FunId, _File, _Line) ->
- catch ets:delete(?DEBUG_TAB, FunId),
- ok.
-
-eval_debug_fun(FunId, Env, File, Line) ->
- case catch ets:lookup(?DEBUG_TAB, FunId) of
- [] ->
- ok;
- [Info] ->
- Fun = Info#debug_info.function,
- case Info#debug_info.type of
- transient ->
- deactivate_debug_fun(FunId, File, Line);
- _->
- ok
- end,
- io:format("Running debug fun ~p:~p (LINE: ~p)~n", [File, FunId, Line]),
- Fun(Env);
- {'EXIT', _R} ->
- ok
- end.
-
-
-set_debug_context([], [], _, _)-> ok;
-set_debug_context([], _, _, _)->
- ets:delete(?DEBUG_TAB),
- exit("failed transactions_SUITE. Bad configuration.");
-set_debug_context(_, [], _, _)->
- ets:delete(?DEBUG_TAB),
- exit("failed transactions_SUITE Bad configuration.");
-set_debug_context([RHead|RTail], [CHead|CTail], File, Line)->
- write_context(RHead, CHead, File, Line),
- set_debug_context(RTail, CTail, File, Line).
-
-write_context(_Resource, [], _, _)-> ok;
-write_context(Resource, [{Func, Fun, Type}|PTail], File, Line)->
- etrap_test_lib:activate_debug_fun({Resource, Func},
- Fun, Type,
- File, Line),
- write_context(Resource, PTail, File, Line);
-write_context(_,_, _, _) ->
- ets:delete(?DEBUG_TAB),
- exit("failed transactions_SUITE. Bad configuration.").
-
-
-%%--------------- END OF MODULE ----------------------------------------
diff --git a/lib/cosTransactions/test/etrap_test_lib.hrl b/lib/cosTransactions/test/etrap_test_lib.hrl
deleted file mode 100644
index 6fe61a4d45..0000000000
--- a/lib/cosTransactions/test/etrap_test_lib.hrl
+++ /dev/null
@@ -1,101 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--ifndef(ETRAP_TEST_LIB_HRL).
--define(ETRAP_TEST_LIB_HRL, true).
-
--define(match(ExpectedRes, Expr, Msg),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("~n------ CORRECT RESULT ------~n~p~n~p~n",
- [AcTuAlReS, Msg]),
- ok;
- _ ->
- io:format("~n###### ERROR ERROR ######~n~p~n~p~n",
- [AcTuAlReS, Msg]),
- exit(AcTuAlReS)
- end
- end()).
-
--define(match_inverse(NotExpectedRes, Expr, Msg),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- NotExpectedRes ->
- io:format("~n###### ERROR ERROR ######~n ~p~n~p~n",
- [AcTuAlReS, Msg]),
- exit(AcTuAlReS);
- _ ->
- io:format("~n------ CORRECT RESULT ------~n~p~n~p~n",
- [AcTuAlReS, Msg]),
- ok
- end
- end()).
-
-
--define(crash_and_recover, fun(_Env)-> exit(crash_and_burn) end).
-
--define(crash_no_recovery, fun(Env)-> throw({stop,normal,{Env,state}}) end).
-
--define(delay(Time), fun(_Id) -> timer:sleep(Time*1000) end).
-
--define(TIMEOUT, 4).
--define(SUP_TEST(Env, Name),
- ['etrap_test_server', Env,
- [{sup_child, true}, {persistent, true},
- {regname, {global, Name}}]]).
-
--define(no_context, [[],[],[], []]).
--define(nop, []).
--define(delay_transient(Tag, Ti),
- [{Tag, ?delay(Ti), transient}]).
--define(crash_transient(Tag),
- [{Tag, ?crash_and_recover, transient}]).
--define(crash_permanent(Tag),
- [{Tag, ?crash_no_recovery, permanent}]).
-
-%%-----------------------------------------------------------
-%% Definition of 'Resource' action.
-%% function action reply
-%%-----------------------------------------------------------
-%% raise #'CosTransactions_HeuristicMixed' {}
--define(rollback_mix, [{rollback, exc, ?tr_mixed}]).
--define(commit_mix, [{commit, exc, ?tr_mixed}]).
--define(prepare_mix, [{prepare, exc, ?tr_mixed}]).
-%% raise #'CosTransactions_HeuristicRollback' {}
--define(rollback_rb, [{rollback, exc, ?tr_rollback}]).
--define(commit_rb, [{commit, exc, ?tr_rollback}]).
-%% raise #'CosTransactions_HeuristicCommit' {}
--define(rollback_cm, [{rollback, exc, ?tr_commit}]).
--define(commit_cm, [{commit, exc, ?tr_commit}]).
-%% delay reply
--define(rollback_delay, [{rollback, delay, ?TIMEOUT*2}]).
--define(commit_delay, [{commit, delay, ?TIMEOUT*2}]).
--define(prepare_delay, [{prepare, delay, ?TIMEOUT*2}]).
-%% other reply than default
--define(prepare_commit, [{prepare, reply, 'VoteCommit'}]).
--define(prepare_rollback, [{prepare, stop_reply, 'VoteRollback'}]).
-
--endif.
-
-%%-------------- EOF ---------------------------------------------------
diff --git a/lib/cosTransactions/test/etrap_test_server_impl.erl b/lib/cosTransactions/test/etrap_test_server_impl.erl
deleted file mode 100644
index 8a244b42c7..0000000000
--- a/lib/cosTransactions/test/etrap_test_server_impl.erl
+++ /dev/null
@@ -1,211 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(etrap_test_server_impl).
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-%% Local
--include_lib("cosTransactions/src/ETraP_Common.hrl").
--include_lib("cosTransactions/include/CosTransactions.hrl").
-%%--------------- IMPORTS-------------------------------------
-%%--------------- EXPORTS-------------------------------------
--export([prepare/2,
- rollback/2,
- commit/2,
- commit_one_phase/2,
- forget/2,
-% before_completion/2,
-% after_completion/3,
- commit_subtransaction/3,
- rollback_subtransaction/2]).
-
-
-%%--------------- gen_server specific ------------------------
--export([init/1, terminate/2]).
--export([handle_call/3, handle_cast/2, handle_info/2, code_change/3]).
-
-%%------------------------------------------------------------
-%% function : init, terminate
-%%------------------------------------------------------------
-init(State) ->
- process_flag(trap_exit,true),
- io:format("etrap_test_server:init ~p~n", [State]),
- ?debug_print("STARTING etrap_test_server( ~p )~n", [State]),
- {ok, State}.
-
-terminate(Reason, _State) ->
- io:format("etrap_test_server:terminate ~p~n", [Reason]),
- ?debug_print("STOPREASON etrap_test_server( ~p )~n", [Reason]),
- ok.
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-handle_call(_,_, State) ->
- {noreply, State}.
-handle_cast(_, State) ->
- {noreply, State}.
-handle_info(_Info, State) ->
- {noreply, State}.
-
-%%-- Inherit from CosTransactions::SubtransactionAwareResource --
-prepare(_Self, State) ->
- case ?is_debug_compiled of
- true ->
- io:format("etrap_test_server:prepare ~p~n", [State]);
- _->
- ok
- end,
-% ?debug_print("etrap_test_server:prepare ~p~n", [State]),
- action(prepare, State, {reply, 'VoteCommit', State}).
-
-rollback(_Self, State) ->
- case ?is_debug_compiled of
- true ->
- io:format("etrap_test_server:rollback ~p~n", [State]);
- _->
- ok
- end,
-% ?debug_print("etrap_test_server:rollback ~p~n", [State]),
- case sync_test(State) of
- true ->
- action(rollback, State, {reply, ok, State});
- _->
- action(rollback, State, {stop, normal, ok, State})
- end.
-
-commit(_Self, State) ->
- case ?is_debug_compiled of
- true ->
- io:format("etrap_test_server:commit ~p~n", [State]);
- _->
- ok
- end,
-% ?debug_print("etrap_test_server:commit ~p~n", [State]),
- case sync_test(State) of
- true ->
- action(commit, State, {reply, ok, State});
- _->
- action(commit, State, {stop, normal, ok, State})
- end.
-
-commit_one_phase(_Self, State) ->
- case ?is_debug_compiled of
- true ->
- io:format("etrap_test_server:commit_one_phase ~p~n", [State]);
- _->
- ok
- end,
-% ?debug_print("etrap_test_server:commit_one_phase ~p~n", [State]),
- case sync_test(State) of
- true ->
- {reply, ok, State};
- _->
- {stop, normal, ok, State}
- end.
-
-forget(_Self, State) ->
- case ?is_debug_compiled of
- true ->
- io:format("etrap_test_server:forget ~p~n", [State]);
- _->
- ok
- end,
-% ?debug_print("etrap_test_server:forget ~p~n", [State]),
- case sync_test(State) of
- true ->
- {reply, ok, State};
- _->
- {stop, normal, ok, State}
- end.
-
-commit_subtransaction(_Self, State, Parent) ->
- case ?is_debug_compiled of
- true ->
- io:format("etrap_test_server:commit_subtransaction( ~p )~n", [Parent]);
- _->
- ok
- end,
-% ?debug_print("etrap_test_server:commit_subtransaction( ~p )~n", [Parent]),
- {reply, ok, State}.
-rollback_subtransaction(_Self, State) ->
- case ?is_debug_compiled of
- true ->
- io:format("etrap_test_server:rollback_subtransaction()~n", []);
- _->
- ok
- end,
-% ?debug_print("etrap_test_server:rollback_subtransaction()~n", []),
- {reply, ok, State}.
-
-%before_completion(_Self, State) ->
-% case ?is_debug_compiled of
-% true ->
-% io:format("etrap_test_server:before_completion()~n", []);
-% _->
-% ok
-% end,
-%% ?debug_print("etrap_test_server:before_completion()~n", []),
-% {reply, ok, State}.
-%after_completion(_Self, State, Status) ->
-% case ?is_debug_compiled of
-% true ->
-% io:format("etrap_test_server:after_completion( ~p )~n", [Status]);
-% _->
-% ok
-% end,
-%% ?debug_print("etrap_test_server:after_completion( ~p )~n", [Status]),
-% {stop, normal, ok, State}.
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-action(Key, State, Default) ->
- case catch lists:keysearch(Key, 1, State) of
- {value,{Key, stop_reply, R}} ->
- case sync_test(State) of
- true ->
- {reply, R, State};
- _->
- {stop, normal, R, State}
- end;
- {value,{Key, reply, R}} ->
- {reply, R, State};
- {value,{Key, exc, E}} ->
- corba:raise(E);
- {value,{Key, delay, Time}} ->
- timer:sleep(Time*1000),
- Default;
- {value,{Key,Value}} ->
- Value;
- _ ->
- Default
- end.
-
-sync_test(State) ->
- case catch lists:keysearch(sync, 1, State) of
- {value,{sync, true}} ->
- true;
- _ ->
- false
- end.
-
-
-%%--------------- END OF MODULE ------------------------------
-
diff --git a/lib/cosTransactions/test/generated_SUITE.erl b/lib/cosTransactions/test/generated_SUITE.erl
deleted file mode 100644
index 52b850b189..0000000000
--- a/lib/cosTransactions/test/generated_SUITE.erl
+++ /dev/null
@@ -1,543 +0,0 @@
-%%-----------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File : generated_SUITE.erl
-%% Purpose :
-%% Created : 27 Jan 2004
-%%-----------------------------------------------------------------
-
--module(generated_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
-
--define(default_timeout, test_server:minutes(3)).
-
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
--define(nomatch(Not, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- Not ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS);
- _ ->
- AcTuAlReS
- end
- end()).
-
-
--define(checktc(_Op),
- fun(TC) ->
- case orber_tc:check_tc(TC) of
- false ->
- io:format("###### ERROR ERROR ######~n~p - ~p~n", [Op, TC]),
- exit(TC);
- true ->
- true
- end
- end).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- ['CosTransactions_Control',
- 'CosTransactions_Coordinator',
- 'CosTransactions_HeuristicCommit',
- 'CosTransactions_HeuristicHazard',
- 'CosTransactions_HeuristicMixed',
- 'CosTransactions_HeuristicRollback',
- 'CosTransactions_Inactive',
- 'CosTransactions_InvalidControl',
- 'CosTransactions_NoTransaction',
- 'CosTransactions_NotPrepared',
- 'CosTransactions_NotSubtransaction',
- 'CosTransactions_RecoveryCoordinator',
- 'CosTransactions_Resource',
- 'CosTransactions_SubtransactionAwareResource',
- 'CosTransactions_SubtransactionsUnavailable',
- 'CosTransactions_Terminator',
- 'CosTransactions_TransactionFactory',
- 'CosTransactions_Unavailable',
- 'CosTransactions_SynchronizationUnavailable',
- 'CosTransactions_TransIdentity',
- 'CosTransactions_PropagationContext',
- 'CosTransactions_otid_t',
- 'CosTransactions_WrongTransaction', 'ETraP_Server'].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_HeuristicCommit'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_HeuristicCommit'(_) ->
- ?match(true, orber_tc:check_tc('CosTransactions_HeuristicCommit':tc())),
- ?match("IDL:omg.org/CosTransactions/HeuristicCommit:1.0",
- 'CosTransactions_HeuristicCommit':id()),
- ?match("CosTransactions_HeuristicCommit",
- 'CosTransactions_HeuristicCommit':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_HeuristicHazard'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_HeuristicHazard'(_) ->
- ?match(true, orber_tc:check_tc('CosTransactions_HeuristicHazard':tc())),
- ?match("IDL:omg.org/CosTransactions/HeuristicHazard:1.0",
- 'CosTransactions_HeuristicHazard':id()),
- ?match("CosTransactions_HeuristicHazard",
- 'CosTransactions_HeuristicHazard':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_HeuristicMixed'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_HeuristicMixed'(_) ->
- ?match(true, orber_tc:check_tc('CosTransactions_HeuristicMixed':tc())),
- ?match("IDL:omg.org/CosTransactions/HeuristicMixed:1.0",
- 'CosTransactions_HeuristicMixed':id()),
- ?match("CosTransactions_HeuristicMixed",
- 'CosTransactions_HeuristicMixed':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_HeuristicRollback'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_HeuristicRollback'(_) ->
- ?match(true, orber_tc:check_tc('CosTransactions_HeuristicRollback':tc())),
- ?match("IDL:omg.org/CosTransactions/HeuristicRollback:1.0",
- 'CosTransactions_HeuristicRollback':id()),
- ?match("CosTransactions_HeuristicRollback",
- 'CosTransactions_HeuristicRollback':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_Inactive'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_Inactive'(_) ->
- ?match(true, orber_tc:check_tc('CosTransactions_Inactive':tc())),
- ?match("IDL:omg.org/CosTransactions/Inactive:1.0",
- 'CosTransactions_Inactive':id()),
- ?match("CosTransactions_Inactive",
- 'CosTransactions_Inactive':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_InvalidControl'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_InvalidControl'(_) ->
- ?match(true, orber_tc:check_tc('CosTransactions_InvalidControl':tc())),
- ?match("IDL:omg.org/CosTransactions/InvalidControl:1.0",
- 'CosTransactions_InvalidControl':id()),
- ?match("CosTransactions_InvalidControl",
- 'CosTransactions_InvalidControl':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_NoTransaction'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_NoTransaction'(_) ->
- ?match(true, orber_tc:check_tc('CosTransactions_NoTransaction':tc())),
- ?match("IDL:omg.org/CosTransactions/NoTransaction:1.0",
- 'CosTransactions_NoTransaction':id()),
- ?match("CosTransactions_NoTransaction",
- 'CosTransactions_NoTransaction':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_NotPrepared'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_NotPrepared'(_) ->
- ?match(true, orber_tc:check_tc('CosTransactions_NotPrepared':tc())),
- ?match("IDL:omg.org/CosTransactions/NotPrepared:1.0",
- 'CosTransactions_NotPrepared':id()),
- ?match("CosTransactions_NotPrepared",
- 'CosTransactions_NotPrepared':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_NotSubtransaction'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_NotSubtransaction'(_) ->
- ?match(true, orber_tc:check_tc('CosTransactions_NotSubtransaction':tc())),
- ?match("IDL:omg.org/CosTransactions/NotSubtransaction:1.0",
- 'CosTransactions_NotSubtransaction':id()),
- ?match("CosTransactions_NotSubtransaction",
- 'CosTransactions_NotSubtransaction':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_SubtransactionsUnavailable'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_SubtransactionsUnavailable'(_) ->
- ?match(true, orber_tc:check_tc('CosTransactions_SubtransactionsUnavailable':tc())),
- ?match("IDL:omg.org/CosTransactions/SubtransactionsUnavailable:1.0",
- 'CosTransactions_SubtransactionsUnavailable':id()),
- ?match("CosTransactions_SubtransactionsUnavailable",
- 'CosTransactions_SubtransactionsUnavailable':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_Unavailable'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_Unavailable'(_) ->
- ?match(true, orber_tc:check_tc('CosTransactions_Unavailable':tc())),
- ?match("IDL:omg.org/CosTransactions/Unavailable:1.0",
- 'CosTransactions_Unavailable':id()),
- ?match("CosTransactions_Unavailable",
- 'CosTransactions_Unavailable':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_SynchronizationUnavailable'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_SynchronizationUnavailable'(_) ->
- ?match(true, orber_tc:check_tc('CosTransactions_SynchronizationUnavailable':tc())),
- ?match("IDL:omg.org/CosTransactions/SynchronizationUnavailable:1.0",
- 'CosTransactions_SynchronizationUnavailable':id()),
- ?match("CosTransactions_SynchronizationUnavailable",
- 'CosTransactions_SynchronizationUnavailable':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_TransIdentity'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_TransIdentity'(_) ->
- ?match(true, orber_tc:check_tc('CosTransactions_TransIdentity':tc())),
- ?match("IDL:omg.org/CosTransactions/TransIdentity:1.0",
- 'CosTransactions_TransIdentity':id()),
- ?match("CosTransactions_TransIdentity",
- 'CosTransactions_TransIdentity':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_PropagationContext'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_PropagationContext'(_) ->
- ?match(true, orber_tc:check_tc('CosTransactions_PropagationContext':tc())),
- ?match("IDL:omg.org/CosTransactions/PropagationContext:1.0",
- 'CosTransactions_PropagationContext':id()),
- ?match("CosTransactions_PropagationContext",
- 'CosTransactions_PropagationContext':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_otid_t'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_otid_t'(_) ->
- ?match(true, orber_tc:check_tc('CosTransactions_otid_t':tc())),
- ?match("IDL:omg.org/CosTransactions/otid_t:1.0",
- 'CosTransactions_otid_t':id()),
- ?match("CosTransactions_otid_t",
- 'CosTransactions_otid_t':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_WrongTransaction'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_WrongTransaction'(_) ->
- ?match(true, orber_tc:check_tc('CosTransactions_WrongTransaction':tc())),
- ?match("IDL:omg.org/CosTransactions/WrongTransaction:1.0",
- 'CosTransactions_WrongTransaction':id()),
- ?match("CosTransactions_WrongTransaction",
- 'CosTransactions_WrongTransaction':name()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_Control'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_Control'(_) ->
- ?nomatch(undefined, 'CosTransactions_Control':oe_tc(get_terminator)),
- ?nomatch(undefined, 'CosTransactions_Control':oe_tc(get_coordinator)),
- ?match(undefined, 'CosTransactions_Control':oe_tc(undefined)),
- ?match([_|_], 'CosTransactions_Control':oe_get_interface()),
- ?match("IDL:omg.org/CosTransactions/Control:1.0",
- 'CosTransactions_Control':typeID()),
- check_tc('CosTransactions_Control':oe_get_interface()),
- ?match(true, 'CosTransactions_Control':oe_is_a('CosTransactions_Control':typeID())),
- ?match(false, 'CosTransactions_Control':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_Coordinator'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_Coordinator'(_) ->
- ?nomatch(undefined, 'CosTransactions_Coordinator':oe_tc(get_status)),
- ?nomatch(undefined, 'CosTransactions_Coordinator':oe_tc(get_parent_status)),
- ?nomatch(undefined, 'CosTransactions_Coordinator':oe_tc(get_top_level_status)),
- ?nomatch(undefined, 'CosTransactions_Coordinator':oe_tc(is_same_transaction)),
- ?nomatch(undefined, 'CosTransactions_Coordinator':oe_tc(is_related_transaction)),
- ?nomatch(undefined, 'CosTransactions_Coordinator':oe_tc(is_ancestor_transaction)),
- ?nomatch(undefined, 'CosTransactions_Coordinator':oe_tc(is_descendant_transaction)),
- ?nomatch(undefined, 'CosTransactions_Coordinator':oe_tc(is_top_level_transaction)),
- ?nomatch(undefined, 'CosTransactions_Coordinator':oe_tc(hash_transaction)),
- ?nomatch(undefined, 'CosTransactions_Coordinator':oe_tc(hash_top_level_tran)),
- ?nomatch(undefined, 'CosTransactions_Coordinator':oe_tc(register_resource)),
- ?nomatch(undefined, 'CosTransactions_Coordinator':oe_tc(register_subtran_aware)),
- ?nomatch(undefined, 'CosTransactions_Coordinator':oe_tc(rollback_only)),
- ?nomatch(undefined, 'CosTransactions_Coordinator':oe_tc(get_transaction_name)),
- ?nomatch(undefined, 'CosTransactions_Coordinator':oe_tc(create_subtransaction)),
- ?nomatch(undefined, 'CosTransactions_Coordinator':oe_tc(get_txcontext)),
- ?match(undefined, 'CosTransactions_Coordinator':oe_tc(undefined)),
- ?match([_|_], 'CosTransactions_Coordinator':oe_get_interface()),
- ?match("IDL:omg.org/CosTransactions/Coordinator:1.0",
- 'CosTransactions_Coordinator':typeID()),
- check_tc('CosTransactions_Coordinator':oe_get_interface()),
- ?match(true, 'CosTransactions_Coordinator':oe_is_a('CosTransactions_Coordinator':typeID())),
- ?match(false, 'CosTransactions_Coordinator':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_RecoveryCoordinator'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_RecoveryCoordinator'(_) ->
- ?nomatch(undefined, 'CosTransactions_RecoveryCoordinator':oe_tc(replay_completion)),
- ?match(undefined, 'CosTransactions_RecoveryCoordinator':oe_tc(undefined)),
- ?match([_|_], 'CosTransactions_RecoveryCoordinator':oe_get_interface()),
- ?match("IDL:omg.org/CosTransactions/RecoveryCoordinator:1.0",
- 'CosTransactions_RecoveryCoordinator':typeID()),
- check_tc('CosTransactions_RecoveryCoordinator':oe_get_interface()),
- ?match(true, 'CosTransactions_RecoveryCoordinator':oe_is_a('CosTransactions_RecoveryCoordinator':typeID())),
- ?match(false, 'CosTransactions_RecoveryCoordinator':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_Resource'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_Resource'(_) ->
- ?nomatch(undefined, 'CosTransactions_Resource':oe_tc(prepare)),
- ?nomatch(undefined, 'CosTransactions_Resource':oe_tc(rollback)),
- ?nomatch(undefined, 'CosTransactions_Resource':oe_tc(commit)),
- ?nomatch(undefined, 'CosTransactions_Resource':oe_tc(commit_one_phase)),
- ?nomatch(undefined, 'CosTransactions_Resource':oe_tc(forget)),
- ?match(undefined, 'CosTransactions_Resource':oe_tc(undefined)),
- ?match([_|_], 'CosTransactions_Resource':oe_get_interface()),
- ?match("IDL:omg.org/CosTransactions/Resource:1.0",
- 'CosTransactions_Resource':typeID()),
- check_tc('CosTransactions_Resource':oe_get_interface()),
- ?match(true, 'CosTransactions_Resource':oe_is_a('CosTransactions_Resource':typeID())),
- ?match(false, 'CosTransactions_Resource':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_SubtransactionAwareResource'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_SubtransactionAwareResource'(_) ->
- ?nomatch(undefined, 'CosTransactions_SubtransactionAwareResource':oe_tc(commit_subtransaction)),
- ?nomatch(undefined, 'CosTransactions_SubtransactionAwareResource':oe_tc(rollback_subtransaction)),
- ?nomatch(undefined, 'CosTransactions_SubtransactionAwareResource':oe_tc(prepare)),
- ?nomatch(undefined, 'CosTransactions_SubtransactionAwareResource':oe_tc(rollback)),
- ?nomatch(undefined, 'CosTransactions_SubtransactionAwareResource':oe_tc(commit)),
- ?nomatch(undefined, 'CosTransactions_SubtransactionAwareResource':oe_tc(commit_one_phase)),
- ?nomatch(undefined, 'CosTransactions_SubtransactionAwareResource':oe_tc(forget)),
- ?match(undefined, 'CosTransactions_SubtransactionAwareResource':oe_tc(undefined)),
- ?match([_|_], 'CosTransactions_SubtransactionAwareResource':oe_get_interface()),
- ?match("IDL:omg.org/CosTransactions/SubtransactionAwareResource:1.0",
- 'CosTransactions_SubtransactionAwareResource':typeID()),
- check_tc('CosTransactions_SubtransactionAwareResource':oe_get_interface()),
- ?match(true, 'CosTransactions_SubtransactionAwareResource':oe_is_a('CosTransactions_SubtransactionAwareResource':typeID())),
- ?match(true, 'CosTransactions_SubtransactionAwareResource':oe_is_a('CosTransactions_Resource':typeID())),
- ?match(false, 'CosTransactions_SubtransactionAwareResource':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_Terminator'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_Terminator'(_) ->
- ?nomatch(undefined, 'CosTransactions_Terminator':oe_tc(commit)),
- ?nomatch(undefined, 'CosTransactions_Terminator':oe_tc(rollback)),
- ?match(undefined, 'CosTransactions_Terminator':oe_tc(undefined)),
- ?match([_|_], 'CosTransactions_Terminator':oe_get_interface()),
- ?match("IDL:omg.org/CosTransactions/Terminator:1.0",
- 'CosTransactions_Terminator':typeID()),
- check_tc('CosTransactions_Terminator':oe_get_interface()),
- ?match(true, 'CosTransactions_Terminator':oe_is_a('CosTransactions_Terminator':typeID())),
- ?match(false, 'CosTransactions_Terminator':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosTransactions_TransactionFactory'
-%% Description:
-%%-----------------------------------------------------------------
-'CosTransactions_TransactionFactory'(_) ->
- ?nomatch(undefined, 'CosTransactions_TransactionFactory':oe_tc(create)),
- ?nomatch(undefined, 'CosTransactions_TransactionFactory':oe_tc(recreate)),
- ?match(undefined, 'CosTransactions_TransactionFactory':oe_tc(undefined)),
- ?match([_|_], 'CosTransactions_TransactionFactory':oe_get_interface()),
- ?match("IDL:omg.org/CosTransactions/TransactionFactory:1.0",
- 'CosTransactions_TransactionFactory':typeID()),
- check_tc('CosTransactions_TransactionFactory':oe_get_interface()),
- ?match(true, 'CosTransactions_TransactionFactory':oe_is_a('CosTransactions_TransactionFactory':typeID())),
- ?match(false, 'CosTransactions_TransactionFactory':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'ETraP_Server'
-%% Description:
-%%-----------------------------------------------------------------
-'ETraP_Server'(_) ->
- ?nomatch(undefined, 'ETraP_Server':oe_tc(get_status)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(get_parent_status)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(get_top_level_status)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(is_same_transaction)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(is_related_transaction)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(is_ancestor_transaction)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(is_descendant_transaction)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(is_top_level_transaction)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(hash_transaction)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(hash_top_level_tran)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(register_resource)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(register_subtran_aware)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(rollback_only)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(get_transaction_name)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(create_subtransaction)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(get_txcontext)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(prepare)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(rollback)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(commit)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(commit_one_phase)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(forget)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(replay_completion)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(get_terminator)),
- ?nomatch(undefined, 'ETraP_Server':oe_tc(get_coordinator)),
- ?match(undefined, 'ETraP_Server':oe_tc(undefined)),
- ?match([_|_], 'ETraP_Server':oe_get_interface()),
- ?match("IDL:omg.org/ETraP/Server:1.0",
- 'ETraP_Server':typeID()),
- check_tc('ETraP_Server':oe_get_interface()),
- ?match(true, 'ETraP_Server':oe_is_a('ETraP_Server':typeID())),
- ?match(true, 'ETraP_Server':oe_is_a('CosTransactions_Coordinator':typeID())),
- ?match(true, 'ETraP_Server':oe_is_a('CosTransactions_Resource':typeID())),
- ?match(true, 'ETraP_Server':oe_is_a('CosTransactions_RecoveryCoordinator':typeID())),
- ?match(true, 'ETraP_Server':oe_is_a('CosTransactions_Control':typeID())),
- ?match(false, 'ETraP_Server':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% MISC functions
-%%-----------------------------------------------------------------
-check_tc([]) ->
- ok;
-check_tc([{Op, {RetType, InParameters, OutParameters}}|T]) ->
- io:format("checked - ~s~n", [Op]),
- lists:all(?checktc(Op), [RetType|InParameters]),
- lists:all(?checktc(Op), OutParameters),
- check_tc(T).
-
-
diff --git a/lib/cosTransactions/test/transactions_SUITE.erl b/lib/cosTransactions/test/transactions_SUITE.erl
deleted file mode 100644
index 00753a4e6e..0000000000
--- a/lib/cosTransactions/test/transactions_SUITE.erl
+++ /dev/null
@@ -1,396 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(transactions_SUITE).
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-
-%% Local
--include_lib("cosTransactions/src/ETraP_Common.hrl").
--include_lib("cosTransactions/include/CosTransactions.hrl").
--include("etrap_test_lib.hrl").
-
--include_lib("common_test/include/ct.hrl").
-
--define(default_timeout, test_server:minutes(20)).
-
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, cases/0,
- init_per_suite/1, end_per_suite/1, resource_api/1, etrap_api/1,
- init_per_testcase/2, end_per_testcase/2, app_test/1]).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-cases() ->
- [etrap_api, resource_api, app_test].
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- 'oe_CosTransactions':'oe_register'(),
- 'oe_etrap_test':'oe_register'(),
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- 'oe_etrap_test':'oe_unregister'(),
- 'oe_CosTransactions':'oe_unregister'(),
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) ->
- mnesia:delete_schema([node()]),
- mnesia:create_schema([node()]),
- orber:install([node()]),
- application:start(mnesia),
- application:start(orber),
- if
- is_list(Config) ->
- Config;
- true ->
- exit("Config not a list")
- end.
-
-end_per_suite(Config) ->
- application:stop(orber),
- application:stop(mnesia),
- mnesia:delete_schema([node()]),
- Config.
-
-%%-----------------------------------------------------------------
-%% Tests app file
-%%-----------------------------------------------------------------
-app_test(_Config) ->
- ok=test_server:app_test(cosTransactions),
- ok.
-
-%%-----------------------------------------------------------------
-%% API tests
-%%-----------------------------------------------------------------
-etrap_api(_Config) ->
- ?match(ok, application:start(cosTransactions),
- "Starting the cosTransactions application"),
- TrFac = cosTransactions:start_factory(),
- %% Start a new transaction:
- %% RootCoord
- %% / \
- %% SubCoord1 SubCoord2
- Control = 'CosTransactions_TransactionFactory':create(TrFac, 0),
- Term = 'CosTransactions_Control':get_terminator(Control),
- Coord = 'CosTransactions_Control':get_coordinator(Control),
- SubCont1 = 'CosTransactions_Coordinator':create_subtransaction(Coord),
- SubCont2 = 'CosTransactions_Coordinator':create_subtransaction(Coord),
- SubCoord1 = 'CosTransactions_Control':get_coordinator(SubCont1),
- SubCoord2 = 'CosTransactions_Control':get_coordinator(SubCont2),
-
-
- %%------ Test CosTransactions::Coordinator ------
- ?match(true,
- 'CosTransactions_Coordinator':is_same_transaction(Coord, Coord),
- "'CosTransactions_Coordinator':is_same_transaction"),
- ?match(false,
- 'CosTransactions_Coordinator':is_same_transaction(Coord, SubCoord1),
- "'CosTransactions_Coordinator':is_same_transaction"),
- ?match(true,
- 'CosTransactions_Coordinator':is_descendant_transaction(Coord, Coord),
- "'CosTransactions_Coordinator':is_descendant_transaction"),
- ?match(false,
- 'CosTransactions_Coordinator':is_descendant_transaction(Coord, SubCoord1),
- "'CosTransactions_Coordinator':is_descendant_transaction"),
- ?match(true,
- 'CosTransactions_Coordinator':is_descendant_transaction(SubCoord1, Coord),
- "'CosTransactions_Coordinator':is_descendant_transaction"),
- ?match(false,
- 'CosTransactions_Coordinator':is_descendant_transaction(SubCoord1, SubCoord2),
- "'CosTransactions_Coordinator':is_descendant_transaction"),
- ?match(true,
- 'CosTransactions_Coordinator':is_top_level_transaction(Coord),
- "'CosTransactions_Coordinator':is_top_level_transaction"),
- ?match(false,
- 'CosTransactions_Coordinator':is_top_level_transaction(SubCoord2),
- "'CosTransactions_Coordinator':is_top_level_transaction"),
-
- RootHash = 'CosTransactions_Coordinator':hash_transaction(Coord),
- RepeatHash= 'CosTransactions_Coordinator':hash_transaction(Coord),
- RootHash2 = 'CosTransactions_Coordinator':hash_top_level_tran(SubCoord1),
- RootHash3 = 'CosTransactions_Coordinator':hash_top_level_tran(Coord),
- _SubHash = 'CosTransactions_Coordinator':hash_transaction(SubCoord2),
- ?match(RootHash, RepeatHash,
- "'CosTransactions_Coordinator':hash_transaction"),
- ?match(RootHash, RootHash2,
- "'CosTransactions_Coordinator':hash_top_level_tran"),
- ?match(RootHash, RootHash3,
- "'CosTransactions_Coordinator':hash_top_level_tran"),
-% ?match_inverse(RootHash, SubHash,
-% "'CosTransactions_Coordinator':hash_transaction"),
-
- ?match('StatusActive',
- 'CosTransactions_Coordinator':get_status(Coord),
- "'CosTransactions_Coordinator':get_status"),
- ?match('StatusActive',
- 'CosTransactions_Coordinator':get_status(SubCoord1),
- "'CosTransactions_Coordinator':get_status"),
- ?match('StatusActive',
- 'CosTransactions_Coordinator':get_parent_status(Coord),
- "'CosTransactions_Coordinator':get_parent_status"),
- ?match('StatusActive',
- 'CosTransactions_Coordinator':get_parent_status(SubCoord1),
- "'CosTransactions_Coordinator':get_parent_status"),
- ?match('StatusActive',
- 'CosTransactions_Coordinator':get_top_level_status(Coord),
- "'CosTransactions_Coordinator':get_top_level_status"),
- ?match('StatusActive',
- 'CosTransactions_Coordinator':get_top_level_status(SubCoord1),
- "'CosTransactions_Coordinator':get_top_level_status"),
-
- %% Create a CosTransactions::Resource to experiments with.
- %% Start a new transaction:
- %% RootCoord
- %% / \
- %% SubCoord1 SubCoord2
- %% /
- %% Resource
- N1 = 'ETraP_Common':create_name("test"),
- O1 = etrap_test_server:oe_create(?nop, {global, N1}),
- _RC1 = 'CosTransactions_Coordinator':register_resource(SubCoord1, O1),
-% 'CosTransactions_Coordinator':register_synchronization(SubCoord1, O1),
-
- ?match('VoteCommit',
- 'CosTransactions_Resource':prepare(SubCoord1),
- "'CosTransactions_Coordinator':prepare"),
- %% The Transaction are no longer in 'StatusActive' state. No new
- %% "members" allowed.
- ?match('StatusPrepared',
- 'CosTransactions_Coordinator':get_status(SubCoord1),
- "'CosTransactions_Coordinator':get_status"),
-% ?match({'EXCEPTION', ?tr_inactive},
-% 'CosTransactions_Coordinator':register_synchronization(SubCoord1, O1),
-% "'CosTransactions_Coordinator':register_synchronization"),
- ?match({'EXCEPTION', ?tr_inactive},
- 'CosTransactions_Coordinator':register_resource(SubCoord1, O1),
- "'CosTransactions_Coordinator':register_resource"),
- ?match({'EXCEPTION', ?tr_inactive},
- 'CosTransactions_Coordinator':create_subtransaction(SubCoord1),
- "'CosTransactions_Coordinator':create_subtransaction"),
-
- catch corba:dispose(SubCoord1),
- catch corba:dispose(SubCoord2),
- catch corba:dispose(SubCont1),
- catch corba:dispose(SubCont2),
- catch corba:dispose(Term),
- catch corba:dispose(Control),
- catch corba:dispose(Coord),
- catch corba:dispose(O1),
-
- cosTransactions:stop_factory(TrFac),
- application:stop(cosTransactions),
- ok.
-
-%%-----------------------------------------------------------------
-%% API tests
-%%-----------------------------------------------------------------
-resource_api(_Config) ->
- ?match(ok, application:start(cosTransactions),
- "Starting the cosTransactions application"),
- TrFac = cosTransactions:start_factory([{typecheck, true}]),
-
- ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
- run(TrFac, 0, {?nop, ?nop, ?nop, ?prepare_rollback}),
- "TESTCASE #1: Prepare rollback Resource 4"),
- ?match({'EXCEPTION', ?tr_mixed},
- run(TrFac, 0, {?nop, ?nop, ?commit_mix, ?nop}),
- "TESTCASE #2: Heuristic Mixed exception Resource 3"),
- ?match(ok,
- run(TrFac, 0, {?nop, ?nop, ?nop, ?nop}),
- "TESTCASE #3: Normal completion. No errors."),
- ?match(ok,
- run(TrFac, 0, {?nop, ?nop, ?nop, ?commit_cm}),
- "TESTCASE #4: Heuristic Commit Exception Resource 4"),
- ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
- run(TrFac, 0, {?nop, ?rollback_rb, ?nop, ?prepare_rollback}),
- "TESTCASE #5: Heuristic Rollbac Resource 2, Resource 4 reply 'VoteRollback'"),
- ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
- run(TrFac, 0, {?nop, ?nop, ?prepare_rollback, ?rollback_rb}),
- "TESTCASE #6: Heuristic Rollbac Resource 4, Resource 3 reply 'VoteRollback'"),
- ?match(ok,
- run(TrFac, 0, {?nop, ?nop, ?commit_delay, ?nop}),
- "TESTCASE #7: Resource 3 delay during commit. No timeout."),
- ?match(ok,
- run(TrFac, 0, {?nop, ?nop, ?prepare_delay, ?nop}),
- "TESTCASE #8: Resource 3 delay during prepare. No timeout."),
- ?match(ok,
- run(TrFac, ?TIMEOUT, {?nop, ?commit_delay, ?nop, ?nop}),
- "TESTCASE #9: Resource 3 delay during commit. Timeout."),
- ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
- run(TrFac, ?TIMEOUT, {?nop, ?prepare_delay, ?nop, ?nop}),
- "TESTCASE #10: Resource 3 delay during prepare. Timeout."),
- case ?is_debug_compiled of
- true ->
- %% Testing the Coordinators (root and sub).
- ?match(ok,
- run(TrFac, 0, {?nop, ?nop, ?nop, ?nop, [?nop, ?nop,?crash_transient(commit), ?nop]}),
- "TESTCASE #11: SubCoord 3 crash transient during commit."),
- ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{}},
- run(TrFac, 0, {?nop, ?nop, ?nop, ?nop, [?nop, ?nop,?crash_transient(send_prepare), ?nop]}),
- "TESTCASE #12: SubCoord 3 crash transient during send prepare."),
- ?match({'EXCEPTION', ?tr_hazard},
- run(TrFac, 0, {?nop, ?nop, ?nop, ?nop, [?nop, ?nop,?crash_permanent(commit), ?nop]}),
- "TESTCASE #13: SubCoord 3 crash permanent during commit."),
- ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{}},
- run(TrFac, 0, {?nop, ?nop, ?nop, ?nop, [?nop, ?nop,?crash_permanent(send_prepare), ?nop]}),
- "TESTCASE #14: SubCoord 3 crash permanent during prepare."),
- ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{}},
- run(TrFac, 0, {?nop, ?nop, ?nop, ?nop, [?nop, ?crash_transient(send_prepare), ?crash_transient(commit), ?nop]}),
- "TESTCASE #15: SubCoord 2 crash transient during prepare. SubCoord 3 crash transient during commit"),
- ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
- run(TrFac, 0, {?nop, ?nop, ?nop, ?nop, [?crash_transient(send_prepare), ?nop, ?nop, ?nop]}),
- "TESTCASE #16: RootCoord crash transient during send prepare."),
- ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{}},
- run(TrFac, 0, {?nop, ?nop, ?nop, ?nop, [?nop, ?crash_transient(prepare1), ?nop, ?nop]}),
- "TESTCASE #17: SubCoord 1 crash transient during prepare1."),
- ?match({'EXCEPTION', ?tr_mixed},
- run(TrFac, 0, {?nop, ?prepare_mix, ?nop, ?nop, [?nop, ?nop, ?crash_transient(prepare2), ?nop]}),
- "TESTCASE #18: SubCoord 3 crash transient during prepare2. Resource 2 raise Heuristic Mixed during prepare"),
- ?match({'EXCEPTION', ?tr_mixed},
- run(TrFac, 0, {?nop, ?commit_mix, ?nop, ?nop, [?nop, ?nop, ?crash_transient(commit2), ?nop]}),
- "TESTCASE #19: Resource 2 raise Heurist mixed during commit. SubCoord crash transient commit2"),
- ?match({'EXCEPTION', ?tr_mixed},
- run(TrFac, 0, {?nop, ?rollback_cm, ?nop, ?prepare_rollback, [?nop, ?crash_transient(rollback2), ?nop, ?nop]}),
- "TESTCASE #20: Resource 2 raise Heuristic Commit during rollback. Resource 4 'VoteRollback'. SubCoord 2 crash transient rollback2."),
- ?match({'EXCEPTION', ?tr_mixed},
- run(TrFac, 0, {?nop, ?nop, ?nop, ?commit_mix, [?nop, ?nop, ?crash_transient(send_forget1), ?nop]}),
- "TESTCASE #21: Resource 4 raise Heuristic Mixed during commit. SubCoord 2 crash transient send_forget1."),
- ?match({'EXCEPTION', ?tr_mixed},
- run(TrFac, 0, {?nop, ?nop, ?nop, ?commit_mix, [?crash_transient(send_forget1), ?nop, ?nop, ?nop]}),
- "TESTCASE #22: Resource 4 raise Heuristic Mixed during commit. Root Coord crash transient send_forget1."),
- ?match({'EXCEPTION', ?tr_mixed},
- run(TrFac, 0, {?nop, ?nop, ?nop, ?commit_mix, [?crash_transient(send_forget3), ?nop, ?crash_transient(send_forget1), ?nop]}),
- "TESTCASE #23: Resource 4 raise Heuristic Mixed during commit. Root Coord crash transient send_forget3. SubCoord 3 crash transient send_forget1."),
- ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}},
- run(TrFac, ?TIMEOUT, {?nop, ?nop, ?nop, ?nop, [?delay_transient(root_delay, ?TIMEOUT*2), ?nop, ?nop, ?nop]}),
- "TESTCASE #24: Delay RootCoord. Timeout."),
- %% Testing the Terminator.
- ?match({'EXCEPTION', ?tr_mixed},
- run(TrFac, ?TIMEOUT, {?nop, ?prepare_mix, ?nop, ?nop, [?nop, ?nop, ?nop, ?crash_transient(commit_heuristic1)]}),
- "TESTCASE #25: Terminator crash transient after received and logged Heuristic mix."),
- ?match(ok,
- run(TrFac, ?TIMEOUT, {?nop, ?nop, ?nop, ?nop, [?nop, ?nop, ?nop, ?crash_transient(commit_ok2)]}),
- "TESTCASE #26: Terminator crash transient after received and logged 'ok'.");
- _ ->
- ok
- end,
-
- cosTransactions:stop_factory(TrFac),
- application:stop(cosTransactions),
- ok.
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-
-run(TrFac, Time, Spec) ->
- Control = 'CosTransactions_TransactionFactory':create(TrFac, Time),
- Term = 'CosTransactions_Control':get_terminator(Control),
- Coord = 'CosTransactions_Control':get_coordinator(Control),
- SubCont1 = 'CosTransactions_Coordinator':create_subtransaction(Coord),
- SubCont2 = 'CosTransactions_Coordinator':create_subtransaction(Coord),
- SubCoord1 = 'CosTransactions_Control':get_coordinator(SubCont1),
- SubCoord2 = 'CosTransactions_Control':get_coordinator(SubCont2),
- %% Start resources/participants.
- {O1, O2, O3, O4, Ctx} = start_resources(Spec),
-
- %% Get generated names to use for debugging.
- CoordN = 'CosTransactions_Coordinator':get_transaction_name(Coord),
- SubC1N = 'CosTransactions_Coordinator':get_transaction_name(SubCoord1),
- SubC2N = 'CosTransactions_Coordinator':get_transaction_name(SubCoord2),
-
- ?set_debug_context([CoordN, SubC1N, SubC2N, Term], Ctx),
-
- %% Register the resources as participants.
- _RC1 = 'CosTransactions_Coordinator':register_resource(SubCoord1, O1),
- _RC2 = 'CosTransactions_Coordinator':register_resource(SubCoord1, O2),
- _RC3 = 'CosTransactions_Coordinator':register_resource(SubCoord2, O3),
- _RC4 = 'CosTransactions_Coordinator':register_resource(SubCoord2, O4),
-
- 'CosTransactions_Coordinator':register_subtran_aware(SubCoord1, O4),
-% 'CosTransactions_Coordinator':register_synchronization(SubCoord1, O2),
-
-% Reply = (catch 'CosTransactions_Terminator':commit(Term, true)),
- Reply = (catch 'ETraP_Common':send_stubborn('CosTransactions_Terminator',
- commit, [Term, true],
- ?tr_max_retries,
- ?tr_comm_failure_wait)),
-
- catch corba:dispose(SubCoord1),
- catch corba:dispose(SubCoord2),
- catch corba:dispose(SubCont1),
- catch corba:dispose(SubCont2),
- catch corba:dispose(Term),
- catch corba:dispose(Control),
- catch corba:dispose(Coord),
- catch corba:dispose(O1),
- catch corba:dispose(O2),
- catch corba:dispose(O3),
- catch corba:dispose(O4),
- Reply.
-
-start_resources({A1, A2, A3, A4})->
- start_resources({A1, A2, A3, A4, ?no_context});
-start_resources({A1, A2, A3, A4, Ctx})->
- N1 = 'ETraP_Common':create_name("test"),
- N2 = 'ETraP_Common':create_name("test"),
- N3 = 'ETraP_Common':create_name("test"),
- N4 = 'ETraP_Common':create_name("test"),
- {_,_,O1} = supervisor:start_child(?SUPERVISOR_NAME, ?SUP_TEST(A1, N1)),
- {_,_,O2} = supervisor:start_child(?SUPERVISOR_NAME, ?SUP_TEST(A2, N2)),
-% {_,_,O2} = supervisor:start_child(?SUPERVISOR_NAME, ?SUP_TEST([{sync,true}|A2], N2)),
- {_,_,O3} = supervisor:start_child(?SUPERVISOR_NAME, ?SUP_TEST(A3, N3)),
- {_,_,O4} = supervisor:start_child(?SUPERVISOR_NAME, ?SUP_TEST(A4, N4)),
- {O1, O2, O3, O4, Ctx}.
diff --git a/lib/cosTransactions/vsn.mk b/lib/cosTransactions/vsn.mk
deleted file mode 100644
index ab163d83c2..0000000000
--- a/lib/cosTransactions/vsn.mk
+++ /dev/null
@@ -1 +0,0 @@
-COSTRANSACTIONS_VSN = 1.3.2
diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in
index af7c209c75..31124ba477 100644
--- a/lib/crypto/c_src/Makefile.in
+++ b/lib/crypto/c_src/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
+# Copyright Ericsson AB 1999-2017. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -78,12 +78,16 @@ CRYPTO_STATIC_OBJS = $(OBJDIR)/crypto_static$(TYPEMARKER).o\
NIF_ARCHIVE = $(LIBDIR)/crypto$(TYPEMARKER).a
+TEST_ENGINE_OBJS = $(OBJDIR)/otp_test_engine$(TYPEMARKER).o
+
ifeq ($(findstring win32,$(TARGET)), win32)
NIF_LIB = $(LIBDIR)/crypto$(TYPEMARKER).dll
CALLBACK_LIB = $(LIBDIR)/crypto_callback$(TYPEMARKER).dll
+TEST_ENGINE_LIB = $(LIBDIR)/otp_test_engine$(TYPEMARKER).dll
else
NIF_LIB = $(LIBDIR)/crypto$(TYPEMARKER).so
CALLBACK_LIB = $(LIBDIR)/crypto_callback$(TYPEMARKER).so
+TEST_ENGINE_LIB = $(LIBDIR)/otp_test_engine$(TYPEMARKER).so
endif
ifeq ($(HOST_OS),)
@@ -129,10 +133,22 @@ ALL_STATIC_CFLAGS = $(DED_STATIC_CFLAGS) $(INCLUDES)
_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
-debug opt valgrind: $(NIF_LIB) $(CALLBACK_LIB)
+debug opt valgrind: $(NIF_LIB) $(CALLBACK_LIB) $(TEST_ENGINE_LIB)
static_lib: $(NIF_ARCHIVE)
+$(OBJDIR)/otp_test_engine$(TYPEMARKER).o: otp_test_engine.c
+ $(V_at)$(INSTALL_DIR) $(OBJDIR)
+ $(V_CC) -c -o $@ $(ALL_CFLAGS) $<
+
+$(LIBDIR)/otp_test_engine$(TYPEMARKER).so: $(TEST_ENGINE_OBJS)
+ $(V_at)$(INSTALL_DIR) $(LIBDIR)
+ $(V_LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(CRYPTO_LINK_LIB)
+
+$(LIBDIR)/otp_test_engine$(TYPEMARKER).dll: $(TEST_ENGINE_OBJS)
+ $(V_at)$(INSTALL_DIR) $(LIBDIR)
+ $(V_LD) $(LDFLAGS) -o $@ $(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) $(TEST_ENGINE_OBJS) -l$(SSL_CRYPTO_LIBNAME) -l$(SSL_SSL_LIBNAME)
+
$(OBJDIR)/%$(TYPEMARKER).o: %.c
$(V_at)$(INSTALL_DIR) $(OBJDIR)
$(V_CC) -c -o $@ $(ALL_CFLAGS) $<
@@ -170,6 +186,7 @@ ifeq ($(findstring win32,$(TARGET)), win32)
rm -f $(LIBDIR)/crypto.debug.dll
rm -f $(LIBDIR)/crypto_callback.dll
rm -f $(LIBDIR)/crypto_callback.debug.dll
+ rm -f $(LIBDIR)/otp_test_engine.dll
else
rm -f $(LIBDIR)/crypto.so
rm -f $(LIBDIR)/crypto.debug.so
@@ -177,6 +194,7 @@ else
rm -f $(LIBDIR)/crypto_callback.so
rm -f $(LIBDIR)/crypto_callback.debug.so
rm -f $(LIBDIR)/crypto_callback.valgrind.so
+ rm -f $(LIBDIR)/otp_test_engine.so
endif
rm -f $(OBJDIR)/crypto.o
rm -f $(OBJDIR)/crypto_static.o
@@ -187,6 +205,7 @@ endif
rm -f $(OBJDIR)/crypto_callback.o
rm -f $(OBJDIR)/crypto_callback.debug.o
rm -f $(OBJDIR)/crypto_callback.valgrind.o
+ rm -f $(OBJDIR)/otp_test_engine.o
rm -f core *~
docs:
@@ -206,6 +225,8 @@ ifeq ($(DYNAMIC_CRYPTO_LIB),yes)
$(INSTALL_PROGRAM) $(CALLBACK_OBJS) "$(RELSYSDIR)/priv/obj"
$(INSTALL_PROGRAM) $(CALLBACK_LIB) "$(RELSYSDIR)/priv/lib"
endif
+ $(INSTALL_PROGRAM) $(TEST_ENGINE_OBJS) "$(RELSYSDIR)/priv/obj"
+ $(INSTALL_PROGRAM) $(TEST_ENGINE_LIB) "$(RELSYSDIR)/priv/lib"
release_docs_spec:
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 688ec339aa..d40d285f86 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -1,7 +1,7 @@
-/*
+/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2017. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,8 +19,8 @@
*/
/*
- * Purpose: Dynamically loadable NIF library for cryptography.
- * Based on OpenSSL.
+ * Purpose: Dynamically loadable NIF library for cryptography.
+ * Based on OpenSSL.
*/
#ifdef __WIN32__
@@ -60,6 +60,7 @@
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
+#include <openssl/err.h>
/* Helper macro to construct a OPENSSL_VERSION_NUMBER.
* See openssl/opensslv.h
@@ -79,9 +80,9 @@
*
* Therefor works tests like this as intendend:
* OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
- * (The test is for example "2.4.2" >= "1.0.0" although the test
+ * (The test is for example "2.4.2" >= "1.0.0" although the test
* with the cloned OpenSSL test would be "1.0.1" >= "1.0.0")
- *
+ *
* But tests like this gives wrong result:
* OPENSSL_VERSION_NUMBER < PACKED_OPENSSL_VERSION_PLAIN(1,1,0)
* (The test is false since "2.4.2" < "1.1.0". It should have been
@@ -100,8 +101,10 @@
# undef FIPS_SUPPORT
# endif
+# if LIBRESSL_VERSION_NUMBER < PACKED_OPENSSL_VERSION_PLAIN(2,7,0)
/* LibreSSL wants the 1.0.1 API */
# define NEED_EVP_COMPATIBILITY_FUNCTIONS
+# endif
#endif
@@ -110,6 +113,12 @@
#endif
+#ifndef HAS_LIBRESSL
+# if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+# define HAS_EVP_PKEY_CTX
+# endif
+#endif
+
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
#include <openssl/modes.h>
@@ -139,6 +148,23 @@
# define HAVE_DES_ede3_cfb_encrypt
#endif
+// SHA3:
+#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,1,1)
+// An error in beta releases of 1.1.1 fixed in production release
+# ifdef NID_sha3_224
+# define HAVE_SHA3_224
+# endif
+# ifdef NID_sha3_256
+# define HAVE_SHA3_256
+# endif
+#endif
+# ifdef NID_sha3_384
+# define HAVE_SHA3_384
+# endif
+# ifdef NID_sha3_512
+# define HAVE_SHA3_512
+# endif
+
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'o') \
&& !defined(OPENSSL_NO_EC) \
&& !defined(OPENSSL_NO_ECDH) \
@@ -146,13 +172,22 @@
# define HAVE_EC
#endif
+// (test for >= 1.1.1pre8)
+#if OPENSSL_VERSION_NUMBER >= (PACKED_OPENSSL_VERSION_PLAIN(1,1,1) - 7) \
+ && !defined(HAS_LIBRESSL) \
+ && defined(HAVE_EC)
+# define HAVE_ED_CURVE_DH
+#endif
+
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'c')
# define HAVE_AES_IGE
#endif
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,1)
# define HAVE_EVP_AES_CTR
+# define HAVE_AEAD
# define HAVE_GCM
+# define HAVE_CCM
# define HAVE_CMAC
# if OPENSSL_VERSION_NUMBER < PACKED_OPENSSL_VERSION(1,0,1,'d')
# define HAVE_GCM_EVP_DECRYPT_BUG
@@ -161,7 +196,16 @@
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,1,0)
# ifndef HAS_LIBRESSL
+# define HAVE_CHACHA20
# define HAVE_CHACHA20_POLY1305
+# define HAVE_RSA_OAEP_MD
+# endif
+#endif
+
+// OPENSSL_VERSION_NUMBER >= 1.1.1-pre8
+#if OPENSSL_VERSION_NUMBER >= (PACKED_OPENSSL_VERSION_PLAIN(1,1,1)-7)
+# ifndef HAS_LIBRESSL
+# define HAVE_POLY1305
# endif
#endif
@@ -169,6 +213,31 @@
# define HAVE_ECB_IVEC_BUG
#endif
+#ifndef HAS_LIBRESSL
+# ifdef RSA_SSLV23_PADDING
+# define HAVE_RSA_SSLV23_PADDING
+# endif
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+# ifdef RSA_PKCS1_PSS_PADDING
+# define HAVE_RSA_PKCS1_PSS_PADDING
+# endif
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'h') \
+ && defined(HAVE_EC)
+/* If OPENSSL_NO_EC is set, there will be an error in ec.h included from engine.h
+ So if EC is disabled, you can't use Engine either....
+*/
+# define HAS_ENGINE_SUPPORT
+#endif
+
+
+#if defined(HAS_ENGINE_SUPPORT)
+# include <openssl/engine.h>
+#endif
+
#if defined(HAVE_CMAC)
#include <openssl/cmac.h>
#endif
@@ -236,7 +305,7 @@
/* This shall correspond to the similar macro in crypto.erl */
/* Current value is: erlang:system_info(context_reductions) * 10 */
-#define MAX_BYTES_TO_NIF 20000
+#define MAX_BYTES_TO_NIF 20000
#define CONSUME_REDS(NifEnv, Ibin) \
do { \
@@ -273,7 +342,7 @@ static HMAC_CTX *HMAC_CTX_new()
static void HMAC_CTX_free(HMAC_CTX *ctx)
{
HMAC_CTX_cleanup(ctx);
- return CRYPTO_free(ctx);
+ CRYPTO_free(ctx);
}
#define EVP_MD_CTX_new() EVP_MD_CTX_create()
@@ -338,6 +407,10 @@ static INLINE void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const
static INLINE int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key);
static INLINE int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g);
+static INLINE void DSA_get0_pqg(const DSA *dsa,
+ const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
+static INLINE void DSA_get0_key(const DSA *dsa,
+ const BIGNUM **pub_key, const BIGNUM **priv_key);
static INLINE int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
{
@@ -354,6 +427,23 @@ static INLINE int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
return 1;
}
+static INLINE void
+DSA_get0_pqg(const DSA *dsa, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
+{
+ *p = dsa->p;
+ *q = dsa->q;
+ *g = dsa->g;
+}
+
+static INLINE void
+DSA_get0_key(const DSA *dsa, const BIGNUM **pub_key, const BIGNUM **priv_key)
+{
+ if (pub_key) *pub_key = dsa->pub_key;
+ if (priv_key) *priv_key = dsa->priv_key;
+}
+
+
+
static INLINE int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);
static INLINE int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);
static INLINE int DH_set_length(DH *dh, long length);
@@ -383,6 +473,8 @@ static INLINE int DH_set_length(DH *dh, long length)
return 1;
}
+
+
static INLINE void
DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
{
@@ -394,8 +486,8 @@ DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
static INLINE void
DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
{
- *pub_key = dh->pub_key;
- *priv_key = dh->priv_key;
+ if (pub_key) *pub_key = dh->pub_key;
+ if (priv_key) *priv_key = dh->priv_key;
}
#else /* End of compatibility definitions. */
@@ -433,39 +525,54 @@ static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NI
static ERL_NIF_TERM strong_rand_range_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM pkey_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM pkey_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM dh_generate_parameters_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM dh_check(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM srp_user_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM evp_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+
static ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
#ifdef HAVE_GCM_EVP_DECRYPT_BUG
static ERL_NIF_TERM aes_gcm_decrypt_NO_EVP(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
#endif
-static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM chacha20_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM chacha20_stream_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+
+static ERL_NIF_TERM poly1305_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+
+static ERL_NIF_TERM engine_by_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM engine_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM engine_finish_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM engine_free_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM engine_load_dynamic_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM engine_ctrl_cmd_strings_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM engine_register_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM engine_unregister_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM engine_add_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM engine_remove_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM engine_get_first_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM engine_get_next_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM engine_get_name_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM engine_get_all_methods_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
/* helpers */
static void init_algorithms_types(ErlNifEnv*);
@@ -478,7 +585,13 @@ static int term2point(ErlNifEnv* env, ERL_NIF_TERM term,
#endif
static ERL_NIF_TERM bin_from_bn(ErlNifEnv* env, const BIGNUM *bn);
+#ifdef HAS_ENGINE_SUPPORT
+static int get_engine_load_cmd_list(ErlNifEnv* env, const ERL_NIF_TERM term, char **cmds, int i);
+static int zero_terminate(ErlNifBinary bin, char **buf);
+#endif
+
static int library_refc = 0; /* number of users of this dynamic library */
+static int library_initialized = 0;
static ErlNifFunc nif_funcs[] = {
{"info_lib", 0, info_lib},
@@ -506,41 +619,58 @@ static ErlNifFunc nif_funcs[] = {
{"strong_rand_range_nif", 1, strong_rand_range_nif},
{"rand_uniform_nif", 2, rand_uniform_nif},
{"mod_exp_nif", 4, mod_exp_nif},
- {"dss_verify_nif", 4, dss_verify_nif},
- {"rsa_verify_nif", 4, rsa_verify_nif},
{"do_exor", 2, do_exor},
{"rc4_set_key", 1, rc4_set_key},
{"rc4_encrypt_with_state", 2, rc4_encrypt_with_state},
- {"rsa_sign_nif", 3, rsa_sign_nif},
- {"dss_sign_nif", 3, dss_sign_nif},
- {"rsa_public_crypt", 4, rsa_public_crypt},
- {"rsa_private_crypt", 4, rsa_private_crypt},
+ {"pkey_sign_nif", 5, pkey_sign_nif},
+ {"pkey_verify_nif", 6, pkey_verify_nif},
+ {"pkey_crypt_nif", 6, pkey_crypt_nif},
{"rsa_generate_key_nif", 2, rsa_generate_key_nif},
- {"dh_generate_parameters_nif", 2, dh_generate_parameters_nif},
- {"dh_check", 1, dh_check},
{"dh_generate_key_nif", 4, dh_generate_key_nif},
{"dh_compute_key_nif", 3, dh_compute_key_nif},
+
+ {"evp_compute_key_nif", 3, evp_compute_key_nif},
+ {"evp_generate_key_nif", 1, evp_generate_key_nif},
+
+ {"privkey_to_pubkey_nif", 2, privkey_to_pubkey_nif},
{"srp_value_B_nif", 5, srp_value_B_nif},
{"srp_user_secret_nif", 7, srp_user_secret_nif},
{"srp_host_secret_nif", 5, srp_host_secret_nif},
{"ec_key_generate", 2, ec_key_generate},
- {"ecdsa_sign_nif", 4, ecdsa_sign_nif},
- {"ecdsa_verify_nif", 5, ecdsa_verify_nif},
{"ecdh_compute_key_nif", 3, ecdh_compute_key_nif},
{"rand_seed_nif", 1, rand_seed_nif},
- {"aes_gcm_encrypt", 5, aes_gcm_encrypt},
- {"aes_gcm_decrypt", 5, aes_gcm_decrypt},
+ {"aead_encrypt", 6, aead_encrypt},
+ {"aead_decrypt", 6, aead_decrypt},
+
+ {"chacha20_stream_init", 2, chacha20_stream_init},
+ {"chacha20_stream_encrypt", 2, chacha20_stream_crypt},
+ {"chacha20_stream_decrypt", 2, chacha20_stream_crypt},
+
+ {"poly1305_nif", 2, poly1305_nif},
+
+ {"engine_by_id_nif", 1, engine_by_id_nif},
+ {"engine_init_nif", 1, engine_init_nif},
+ {"engine_finish_nif", 1, engine_finish_nif},
+ {"engine_free_nif", 1, engine_free_nif},
+ {"engine_load_dynamic_nif", 0, engine_load_dynamic_nif},
+ {"engine_ctrl_cmd_strings_nif", 3, engine_ctrl_cmd_strings_nif},
+ {"engine_register_nif", 2, engine_register_nif},
+ {"engine_unregister_nif", 2, engine_unregister_nif},
+ {"engine_add_nif", 1, engine_add_nif},
+ {"engine_remove_nif", 1, engine_remove_nif},
+ {"engine_get_first_nif", 0, engine_get_first_nif},
+ {"engine_get_next_nif", 1, engine_get_next_nif},
+ {"engine_get_id_nif", 1, engine_get_id_nif},
+ {"engine_get_name_nif", 1, engine_get_name_nif},
+ {"engine_get_all_methods_nif", 0, engine_get_all_methods_nif}
- {"chacha20_poly1305_encrypt", 4, chacha20_poly1305_encrypt},
- {"chacha20_poly1305_decrypt", 5, chacha20_poly1305_decrypt}
};
ERL_NIF_INIT(crypto,nif_funcs,load,NULL,upgrade,unload)
-
#define MD5_CTX_LEN (sizeof(MD5_CTX))
#define MD4_CTX_LEN (sizeof(MD4_CTX))
#define RIPEMD160_CTX_LEN (sizeof(RIPEMD160_CTX))
@@ -553,6 +683,7 @@ static ERL_NIF_TERM atom_error;
static ERL_NIF_TERM atom_rsa_pkcs1_padding;
static ERL_NIF_TERM atom_rsa_pkcs1_oaep_padding;
static ERL_NIF_TERM atom_rsa_no_padding;
+static ERL_NIF_TERM atom_signature_md;
static ERL_NIF_TERM atom_undefined;
static ERL_NIF_TERM atom_ok;
@@ -583,12 +714,80 @@ static ERL_NIF_TERM atom_onbasis;
static ERL_NIF_TERM atom_aes_cfb8;
static ERL_NIF_TERM atom_aes_cfb128;
+#ifdef HAVE_GCM
+static ERL_NIF_TERM atom_aes_gcm;
+#endif
+#ifdef HAVE_CCM
+static ERL_NIF_TERM atom_aes_ccm;
+#endif
+#ifdef HAVE_CHACHA20_POLY1305
+static ERL_NIF_TERM atom_chacha20_poly1305;
+#endif
#ifdef HAVE_ECB_IVEC_BUG
static ERL_NIF_TERM atom_aes_ecb;
static ERL_NIF_TERM atom_des_ecb;
static ERL_NIF_TERM atom_blowfish_ecb;
#endif
+static ERL_NIF_TERM atom_rsa;
+static ERL_NIF_TERM atom_dss;
+static ERL_NIF_TERM atom_ecdsa;
+
+#ifdef HAVE_ED_CURVE_DH
+static ERL_NIF_TERM atom_x25519;
+static ERL_NIF_TERM atom_x448;
+#endif
+
+static ERL_NIF_TERM atom_rsa_mgf1_md;
+static ERL_NIF_TERM atom_rsa_oaep_label;
+static ERL_NIF_TERM atom_rsa_oaep_md;
+static ERL_NIF_TERM atom_rsa_pad; /* backwards compatibility */
+static ERL_NIF_TERM atom_rsa_padding;
+static ERL_NIF_TERM atom_rsa_pkcs1_pss_padding;
+#ifdef HAVE_RSA_SSLV23_PADDING
+static ERL_NIF_TERM atom_rsa_sslv23_padding;
+#endif
+static ERL_NIF_TERM atom_rsa_x931_padding;
+static ERL_NIF_TERM atom_rsa_pss_saltlen;
+static ERL_NIF_TERM atom_sha224;
+static ERL_NIF_TERM atom_sha256;
+static ERL_NIF_TERM atom_sha384;
+static ERL_NIF_TERM atom_sha512;
+static ERL_NIF_TERM atom_sha3_224;
+static ERL_NIF_TERM atom_sha3_256;
+static ERL_NIF_TERM atom_sha3_384;
+static ERL_NIF_TERM atom_sha3_512;
+static ERL_NIF_TERM atom_md5;
+static ERL_NIF_TERM atom_ripemd160;
+
+#ifdef HAS_ENGINE_SUPPORT
+static ERL_NIF_TERM atom_bad_engine_method;
+static ERL_NIF_TERM atom_bad_engine_id;
+static ERL_NIF_TERM atom_ctrl_cmd_failed;
+static ERL_NIF_TERM atom_engine_init_failed;
+static ERL_NIF_TERM atom_register_engine_failed;
+static ERL_NIF_TERM atom_add_engine_failed;
+static ERL_NIF_TERM atom_remove_engine_failed;
+static ERL_NIF_TERM atom_engine_method_not_supported;
+
+static ERL_NIF_TERM atom_engine_method_rsa;
+static ERL_NIF_TERM atom_engine_method_dsa;
+static ERL_NIF_TERM atom_engine_method_dh;
+static ERL_NIF_TERM atom_engine_method_rand;
+static ERL_NIF_TERM atom_engine_method_ecdh;
+static ERL_NIF_TERM atom_engine_method_ecdsa;
+static ERL_NIF_TERM atom_engine_method_ciphers;
+static ERL_NIF_TERM atom_engine_method_digests;
+static ERL_NIF_TERM atom_engine_method_store;
+static ERL_NIF_TERM atom_engine_method_pkey_meths;
+static ERL_NIF_TERM atom_engine_method_pkey_asn1_meths;
+static ERL_NIF_TERM atom_engine_method_ec;
+
+static ERL_NIF_TERM atom_engine;
+static ERL_NIF_TERM atom_key_id;
+static ERL_NIF_TERM atom_password;
+#endif
+
static ErlNifResourceType* hmac_context_rtype;
struct hmac_context
{
@@ -643,6 +842,35 @@ static struct digest_type_t digest_types[] =
{NULL}
#endif
},
+ {{"sha3_224"},
+#ifdef HAVE_SHA3_224
+ {&EVP_sha3_224}
+#else
+ {NULL}
+#endif
+ },
+ {{"sha3_256"},
+#ifdef HAVE_SHA3_256
+ {&EVP_sha3_256}
+#else
+ {NULL}
+#endif
+ },
+ {{"sha3_384"},
+#ifdef HAVE_SHA3_384
+ {&EVP_sha3_384}
+#else
+ {NULL}
+#endif
+ },
+ {{"sha3_512"},
+#ifdef HAVE_SHA3_512
+ {&EVP_sha3_512}
+#else
+ {NULL}
+#endif
+ },
+
{{NULL}}
};
@@ -712,11 +940,13 @@ static struct cipher_type_t cipher_types[] =
static struct cipher_type_t* get_cipher_type(ERL_NIF_TERM type, size_t key_len);
+
/*
#define PRINTF_ERR0(FMT) enif_fprintf(stderr, FMT "\n")
#define PRINTF_ERR1(FMT, A1) enif_fprintf(stderr, FMT "\n", A1)
#define PRINTF_ERR2(FMT, A1, A2) enif_fprintf(stderr, FMT "\n", A1, A2)
*/
+
#define PRINTF_ERR0(FMT)
#define PRINTF_ERR1(FMT,A1)
#define PRINTF_ERR2(FMT,A1,A2)
@@ -742,6 +972,23 @@ static void evp_cipher_ctx_dtor(ErlNifEnv* env, struct evp_cipher_ctx* ctx) {
}
#endif
+// Engine
+#ifdef HAS_ENGINE_SUPPORT
+static ErlNifResourceType* engine_ctx_rtype;
+struct engine_ctx {
+ ENGINE *engine;
+ char *id;
+};
+static void engine_ctx_dtor(ErlNifEnv* env, struct engine_ctx* ctx) {
+ PRINTF_ERR0("engine_ctx_dtor");
+ if(ctx->id) {
+ PRINTF_ERR1(" non empty ctx->id=%s", ctx->id);
+ enif_free(ctx->id);
+ } else
+ PRINTF_ERR0(" empty ctx->id=NULL");
+}
+#endif
+
static int verify_lib_version(void)
{
const unsigned long libv = SSLeay();
@@ -777,7 +1024,7 @@ static char crypto_callback_name[] = "crypto_callback";
static int change_basename(ErlNifBinary* bin, char* buf, int bufsz, const char* newfile)
{
int i;
-
+
for (i = bin->size; i > 0; i--) {
if (bin->data[i-1] == '/')
break;
@@ -853,7 +1100,18 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info)
return __LINE__;
}
#endif
- if (library_refc > 0) {
+#ifdef HAS_ENGINE_SUPPORT
+ engine_ctx_rtype = enif_open_resource_type(env, NULL, "ENGINE_CTX",
+ (ErlNifResourceDtor*) engine_ctx_dtor,
+ ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER,
+ NULL);
+ if (!engine_ctx_rtype) {
+ PRINTF_ERR0("CRYPTO: Could not open resource type 'ENGINE_CTX'");
+ return __LINE__;
+ }
+#endif
+
+ if (library_initialized) {
/* Repeated loading of this library (module upgrade).
* Atoms and callbacks are already set, we are done.
*/
@@ -882,6 +1140,7 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info)
atom_rsa_pkcs1_padding = enif_make_atom(env,"rsa_pkcs1_padding");
atom_rsa_pkcs1_oaep_padding = enif_make_atom(env,"rsa_pkcs1_oaep_padding");
atom_rsa_no_padding = enif_make_atom(env,"rsa_no_padding");
+ atom_signature_md = enif_make_atom(env,"signature_md");
atom_undefined = enif_make_atom(env,"undefined");
atom_ok = enif_make_atom(env,"ok");
atom_not_prime = enif_make_atom(env,"not_prime");
@@ -904,6 +1163,15 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info)
#endif
atom_aes_cfb8 = enif_make_atom(env, "aes_cfb8");
atom_aes_cfb128 = enif_make_atom(env, "aes_cfb128");
+#ifdef HAVE_GCM
+ atom_aes_gcm = enif_make_atom(env, "aes_gcm");
+#endif
+#ifdef HAVE_CCM
+ atom_aes_ccm = enif_make_atom(env, "aes_ccm");
+#endif
+#ifdef HAVE_CHACHA20_POLY1305
+ atom_chacha20_poly1305 = enif_make_atom(env,"chacha20_poly1305");
+#endif
#ifdef HAVE_ECB_IVEC_BUG
atom_aes_ecb = enif_make_atom(env, "aes_ecb");
atom_des_ecb = enif_make_atom(env, "des_ecb");
@@ -916,10 +1184,62 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info)
#else
atom_not_supported = enif_make_atom(env,"not_supported");
#endif
+ atom_rsa = enif_make_atom(env,"rsa");
+ atom_dss = enif_make_atom(env,"dss");
+ atom_ecdsa = enif_make_atom(env,"ecdsa");
+#ifdef HAVE_ED_CURVE_DH
+ atom_x25519 = enif_make_atom(env,"x25519");
+ atom_x448 = enif_make_atom(env,"x448");
+#endif
+ atom_rsa_mgf1_md = enif_make_atom(env,"rsa_mgf1_md");
+ atom_rsa_oaep_label = enif_make_atom(env,"rsa_oaep_label");
+ atom_rsa_oaep_md = enif_make_atom(env,"rsa_oaep_md");
+ atom_rsa_pad = enif_make_atom(env,"rsa_pad"); /* backwards compatibility */
+ atom_rsa_padding = enif_make_atom(env,"rsa_padding");
+ atom_rsa_pkcs1_pss_padding = enif_make_atom(env,"rsa_pkcs1_pss_padding");
+#ifdef HAVE_RSA_SSLV23_PADDING
+ atom_rsa_sslv23_padding = enif_make_atom(env,"rsa_sslv23_padding");
+#endif
+ atom_rsa_x931_padding = enif_make_atom(env,"rsa_x931_padding");
+ atom_rsa_pss_saltlen = enif_make_atom(env,"rsa_pss_saltlen");
+ atom_sha224 = enif_make_atom(env,"sha224");
+ atom_sha256 = enif_make_atom(env,"sha256");
+ atom_sha384 = enif_make_atom(env,"sha384");
+ atom_sha512 = enif_make_atom(env,"sha512");
+ atom_sha3_224 = enif_make_atom(env,"sha3_224");
+ atom_sha3_256 = enif_make_atom(env,"sha3_256");
+ atom_sha3_384 = enif_make_atom(env,"sha3_384");
+ atom_sha3_512 = enif_make_atom(env,"sha3_512");
+ atom_md5 = enif_make_atom(env,"md5");
+ atom_ripemd160 = enif_make_atom(env,"ripemd160");
+
+#ifdef HAS_ENGINE_SUPPORT
+ atom_bad_engine_method = enif_make_atom(env,"bad_engine_method");
+ atom_bad_engine_id = enif_make_atom(env,"bad_engine_id");
+ atom_ctrl_cmd_failed = enif_make_atom(env,"ctrl_cmd_failed");
+ atom_engine_init_failed = enif_make_atom(env,"engine_init_failed");
+ atom_engine_method_not_supported = enif_make_atom(env,"engine_method_not_supported");
+ atom_add_engine_failed = enif_make_atom(env,"add_engine_failed");
+ atom_remove_engine_failed = enif_make_atom(env,"remove_engine_failed");
+
+ atom_engine_method_rsa = enif_make_atom(env,"engine_method_rsa");
+ atom_engine_method_dsa = enif_make_atom(env,"engine_method_dsa");
+ atom_engine_method_dh = enif_make_atom(env,"engine_method_dh");
+ atom_engine_method_rand = enif_make_atom(env,"engine_method_rand");
+ atom_engine_method_ecdh = enif_make_atom(env,"engine_method_ecdh");
+ atom_engine_method_ecdsa = enif_make_atom(env,"engine_method_ecdsa");
+ atom_engine_method_store = enif_make_atom(env,"engine_method_store");
+ atom_engine_method_ciphers = enif_make_atom(env,"engine_method_ciphers");
+ atom_engine_method_digests = enif_make_atom(env,"engine_method_digests");
+ atom_engine_method_pkey_meths = enif_make_atom(env,"engine_method_pkey_meths");
+ atom_engine_method_pkey_asn1_meths = enif_make_atom(env,"engine_method_pkey_asn1_meths");
+ atom_engine_method_ec = enif_make_atom(env,"engine_method_ec");
+
+ atom_engine = enif_make_atom(env,"engine");
+ atom_key_id = enif_make_atom(env,"key_id");
+ atom_password = enif_make_atom(env,"password");
+#endif
- init_digest_types(env);
- init_cipher_types(env);
- init_algorithms_types(env);
#ifdef HAVE_DYNAMIC_CRYPTO_LIB
{
@@ -938,24 +1258,24 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info)
#else /* !HAVE_DYNAMIC_CRYPTO_LIB */
funcp = &get_crypto_callbacks;
#endif
-
+
#ifdef OPENSSL_THREADS
enif_system_info(&sys_info, sizeof(sys_info));
if (sys_info.scheduler_threads > 1) {
- nlocks = CRYPTO_num_locks();
+ nlocks = CRYPTO_num_locks();
}
/* else no need for locks */
#endif
-
+
ccb = (*funcp)(nlocks);
-
+
if (!ccb || ccb->sizeof_me != sizeof(*ccb)) {
PRINTF_ERR0("Invalid 'crypto_callbacks'");
return __LINE__;
}
-
+
CRYPTO_set_mem_functions(ccb->crypto_alloc, ccb->crypto_realloc, ccb->crypto_free);
-
+
#ifdef OPENSSL_THREADS
if (nlocks > 0) {
CRYPTO_set_locking_callback(ccb->locking_function);
@@ -966,6 +1286,11 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info)
}
#endif /* OPENSSL_THREADS */
+ init_digest_types(env);
+ init_cipher_types(env);
+ init_algorithms_types(env);
+
+ library_initialized = 1;
return 0;
}
@@ -1005,11 +1330,17 @@ static void unload(ErlNifEnv* env, void* priv_data)
}
static int algo_hash_cnt, algo_hash_fips_cnt;
-static ERL_NIF_TERM algo_hash[8]; /* increase when extending the list */
+static ERL_NIF_TERM algo_hash[12]; /* increase when extending the list */
static int algo_pubkey_cnt, algo_pubkey_fips_cnt;
-static ERL_NIF_TERM algo_pubkey[7]; /* increase when extending the list */
+static ERL_NIF_TERM algo_pubkey[11]; /* increase when extending the list */
static int algo_cipher_cnt, algo_cipher_fips_cnt;
-static ERL_NIF_TERM algo_cipher[24]; /* increase when extending the list */
+static ERL_NIF_TERM algo_cipher[25]; /* increase when extending the list */
+static int algo_mac_cnt, algo_mac_fips_cnt;
+static ERL_NIF_TERM algo_mac[3]; /* increase when extending the list */
+static int algo_curve_cnt, algo_curve_fips_cnt;
+static ERL_NIF_TERM algo_curve[87]; /* increase when extending the list */
+static int algo_rsa_opts_cnt, algo_rsa_opts_fips_cnt;
+static ERL_NIF_TERM algo_rsa_opts[10]; /* increase when extending the list */
static void init_algorithms_types(ErlNifEnv* env)
{
@@ -1028,6 +1359,18 @@ static void init_algorithms_types(ErlNifEnv* env)
#ifdef HAVE_SHA512
algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha512");
#endif
+#ifdef HAVE_SHA3_224
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha3_224");
+#endif
+#ifdef HAVE_SHA3_256
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha3_256");
+#endif
+#ifdef HAVE_SHA3_384
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha3_384");
+#endif
+#ifdef HAVE_SHA3_512
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha3_512");
+#endif
// Non-validated algorithms follow
algo_hash_fips_cnt = algo_hash_cnt;
algo_hash[algo_hash_cnt++] = enif_make_atom(env, "md4");
@@ -1069,6 +1412,9 @@ static void init_algorithms_types(ErlNifEnv* env)
#if defined(HAVE_GCM)
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"aes_gcm");
#endif
+#if defined(HAVE_CCM)
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"aes_ccm");
+#endif
// Non-validated algorithms follow
algo_cipher_fips_cnt = algo_cipher_cnt;
#ifdef HAVE_AES_IGE
@@ -1092,10 +1438,153 @@ static void init_algorithms_types(ErlNifEnv* env)
#if defined(HAVE_CHACHA20_POLY1305)
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"chacha20_poly1305");
#endif
+#if defined(HAVE_CHACHA20)
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"chacha20");
+#endif
+
+ // Validated algorithms first
+ algo_mac_cnt = 0;
+ algo_mac[algo_mac_cnt++] = enif_make_atom(env,"hmac");
+#ifdef HAVE_CMAC
+ algo_mac[algo_mac_cnt++] = enif_make_atom(env,"cmac");
+#endif
+#ifdef HAVE_POLY1305
+ algo_mac[algo_mac_cnt++] = enif_make_atom(env,"poly1305");
+#endif
+ // Non-validated algorithms follow
+ algo_mac_fips_cnt = algo_mac_cnt;
+
+ // Validated algorithms first
+ algo_curve_cnt = 0;
+#if defined(HAVE_EC)
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp160k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp160r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp160r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp192r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp192k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp224k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp224r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp256k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp256r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp384r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp521r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime192v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime192v2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime192v3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime239v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime239v2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime239v3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime256v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls7");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls9");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls12");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP160r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP160t1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP192r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP192t1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP224r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP224t1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP256r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP256t1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP320r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP320t1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP384r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP384t1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP512r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP512t1");
+#if !defined(OPENSSL_NO_EC2M)
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect163k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect163r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect163r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect193r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect193r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect233k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect233r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect239k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect283k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect283r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect409k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect409r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect571k1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect571r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb163v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb163v2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb163v3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb176v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb191v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb191v2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb191v3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb208w1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb239v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb239v2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb239v3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb272w1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb304w1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb359v1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb368w1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb431r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls5");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls10");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls11");
+#endif
+#endif
+ // Non-validated algorithms follow
+ algo_curve_fips_cnt = algo_curve_cnt;
+#if defined(HAVE_EC)
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp112r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp112r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp128r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp128r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls6");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls8");
+#if !defined(OPENSSL_NO_EC2M)
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect113r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect113r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect131r1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect131r2");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls1");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls4");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"ipsec3");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"ipsec4");
+#endif
+#endif
+ //--
+#ifdef HAVE_ED_CURVE_DH
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"x25519");
+ algo_curve[algo_curve_cnt++] = enif_make_atom(env,"x448");
+#endif
+ // Validated algorithms first
+ algo_rsa_opts_cnt = 0;
+#ifdef HAS_EVP_PKEY_CTX
+# ifdef HAVE_RSA_PKCS1_PSS_PADDING
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_pkcs1_pss_padding");
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_pss_saltlen");
+# endif
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_mgf1_md");
+# ifdef HAVE_RSA_OAEP_MD
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_oaep_label");
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_oaep_md");
+# endif
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"signature_md");
+#endif
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_pkcs1_padding");
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_x931_padding");
+#ifdef HAVE_RSA_SSLV23_PADDING
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_sslv23_padding");
+#endif
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_no_padding");
+ algo_rsa_opts_fips_cnt = algo_rsa_opts_cnt;
+
+
+ // Check that the max number of algos is updated
ASSERT(algo_hash_cnt <= sizeof(algo_hash)/sizeof(ERL_NIF_TERM));
ASSERT(algo_pubkey_cnt <= sizeof(algo_pubkey)/sizeof(ERL_NIF_TERM));
ASSERT(algo_cipher_cnt <= sizeof(algo_cipher)/sizeof(ERL_NIF_TERM));
+ ASSERT(algo_mac_cnt <= sizeof(algo_mac)/sizeof(ERL_NIF_TERM));
+ ASSERT(algo_curve_cnt <= sizeof(algo_curve)/sizeof(ERL_NIF_TERM));
+ ASSERT(algo_rsa_opts_cnt <= sizeof(algo_rsa_opts)/sizeof(ERL_NIF_TERM));
}
static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -1105,15 +1594,25 @@ static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
int hash_cnt = fips_mode ? algo_hash_fips_cnt : algo_hash_cnt;
int pubkey_cnt = fips_mode ? algo_pubkey_fips_cnt : algo_pubkey_cnt;
int cipher_cnt = fips_mode ? algo_cipher_fips_cnt : algo_cipher_cnt;
+ int mac_cnt = fips_mode ? algo_mac_fips_cnt : algo_mac_cnt;
+ int curve_cnt = fips_mode ? algo_curve_fips_cnt : algo_curve_cnt;
+ int rsa_opts_cnt = fips_mode ? algo_rsa_opts_fips_cnt : algo_rsa_opts_cnt;
#else
int hash_cnt = algo_hash_cnt;
int pubkey_cnt = algo_pubkey_cnt;
int cipher_cnt = algo_cipher_cnt;
+ int mac_cnt = algo_mac_cnt;
+ int curve_cnt = algo_curve_cnt;
+ int rsa_opts_cnt = algo_rsa_opts_cnt;
#endif
- return enif_make_tuple3(env,
- enif_make_list_from_array(env, algo_hash, hash_cnt),
+ return enif_make_tuple6(env,
+ enif_make_list_from_array(env, algo_hash, hash_cnt),
enif_make_list_from_array(env, algo_pubkey, pubkey_cnt),
- enif_make_list_from_array(env, algo_cipher, cipher_cnt));
+ enif_make_list_from_array(env, algo_cipher, cipher_cnt),
+ enif_make_list_from_array(env, algo_mac, mac_cnt),
+ enif_make_list_from_array(env, algo_curve, curve_cnt),
+ enif_make_list_from_array(env, algo_rsa_opts, rsa_opts_cnt)
+ );
}
static ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -1135,11 +1634,11 @@ static ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
* Version string is still from library though.
*/
- memcpy(enif_make_new_binary(env, name_sz, &name_term), libname, name_sz);
+ memcpy(enif_make_new_binary(env, name_sz, &name_term), libname, name_sz);
memcpy(enif_make_new_binary(env, ver_sz, &ver_term), ver, ver_sz);
return enif_make_list1(env, enif_make_tuple3(env, name_term,
- enif_make_int(env, ver_num),
+ enif_make_int(env, ver_num),
ver_term));
}
@@ -1174,6 +1673,8 @@ static ERL_NIF_TERM enable_fips_mode(ErlNifEnv* env, int argc, const ERL_NIF_TER
}
}
+
+#if defined(HAVE_EC)
static ERL_NIF_TERM make_badarg_maybe(ErlNifEnv* env)
{
ERL_NIF_TERM reason;
@@ -1182,6 +1683,7 @@ static ERL_NIF_TERM make_badarg_maybe(ErlNifEnv* env)
else
return enif_make_badarg(env);
}
+#endif
static ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Type, Data) */
@@ -1530,6 +2032,7 @@ static ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
}
#endif /* OPENSSL_VERSION_NUMBER < 1.0 */
+
static ERL_NIF_TERM hmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Type, Key, Data) or (Type, Key, Data, MacSize) */
struct digest_type_t *digp = NULL;
@@ -1617,7 +2120,7 @@ static ERL_NIF_TERM hmac_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
{/* (Context, Data) */
ErlNifBinary data;
struct hmac_context* obj;
-
+
if (!enif_get_resource(env, argv[0], hmac_context_rtype, (void**)&obj)
|| !enif_inspect_iolist_as_binary(env, argv[1], &data)) {
return enif_make_badarg(env);
@@ -1653,13 +2156,13 @@ static ERL_NIF_TERM hmac_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
enif_mutex_unlock(obj->mtx);
return enif_make_badarg(env);
}
-
+
HMAC_Final(obj->ctx, mac_buf, &mac_len);
HMAC_CTX_free(obj->ctx);
obj->alive = 0;
enif_mutex_unlock(obj->mtx);
- if (argc == 2 && req_len < mac_len) {
+ if (argc == 2 && req_len < mac_len) {
/* Only truncate to req_len bytes if asked. */
mac_len = req_len;
}
@@ -1716,6 +2219,62 @@ static ERL_NIF_TERM cmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
#endif
}
+/* For OpenSSL >= 1.1.1 the hmac_nif and cmac_nif could be integrated into poly1305 (with 'type' as parameter) */
+static ERL_NIF_TERM poly1305_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, Text) */
+#ifdef HAVE_POLY1305
+ ErlNifBinary key_bin, text, ret_bin;
+ ERL_NIF_TERM ret = atom_error;
+ EVP_PKEY *key = NULL;
+ EVP_MD_CTX *mctx = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+ const EVP_MD *md = NULL;
+ size_t size;
+ int type;
+
+ type = EVP_PKEY_POLY1305;
+
+ if (!enif_inspect_binary(env, argv[0], &key_bin) ||
+ !(key_bin.size == 32) ) {
+ return enif_make_badarg(env);
+ }
+
+ if (!enif_inspect_binary(env, argv[1], &text) ) {
+ return enif_make_badarg(env);
+ }
+
+ key = EVP_PKEY_new_raw_private_key(type, /*engine*/ NULL, key_bin.data, key_bin.size);
+
+ if (!key ||
+ !(mctx = EVP_MD_CTX_new()) ||
+ !EVP_DigestSignInit(mctx, &pctx, md, /*engine*/ NULL, key) ||
+ !EVP_DigestSignUpdate(mctx, text.data, text.size)) {
+ goto err;
+ }
+
+ if (!EVP_DigestSignFinal(mctx, NULL, &size) ||
+ !enif_alloc_binary(size, &ret_bin) ||
+ !EVP_DigestSignFinal(mctx, ret_bin.data, &size)) {
+ goto err;
+ }
+
+ if ((size != ret_bin.size) &&
+ !enif_realloc_binary(&ret_bin, size)) {
+ goto err;
+ }
+
+ ret = enif_make_binary(env, &ret_bin);
+
+ err:
+ EVP_MD_CTX_free(mctx);
+ EVP_PKEY_free(key);
+ return ret;
+
+#else
+ return atom_notsup;
+#endif
+}
+
static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Type, Key, Ivec, Text, IsEncrypt) or (Type, Key, Text, IsEncrypt) */
struct cipher_type_t *cipherp = NULL;
@@ -1970,7 +2529,7 @@ static ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_
}
static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* ({Key, IVec, ECount, Num}, Data) */
+{/* ({Key, IVec, ECount, Num}, Data) */
ErlNifBinary key_bin, ivec_bin, text_bin, ecount_bin;
AES_KEY aes_key;
unsigned int num;
@@ -1991,14 +2550,14 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N
return enif_make_badarg(env);
}
- ivec2_buf = enif_make_new_binary(env, ivec_bin.size, &ivec2_term);
+ ivec2_buf = enif_make_new_binary(env, ivec_bin.size, &ivec2_term);
ecount2_buf = enif_make_new_binary(env, ecount_bin.size, &ecount2_term);
-
+
memcpy(ivec2_buf, ivec_bin.data, 16);
memcpy(ecount2_buf, ecount_bin.data, ecount_bin.size);
AES_ctr128_encrypt((unsigned char *) text_bin.data,
- enif_make_new_binary(env, text_bin.size, &cipher_term),
+ enif_make_new_binary(env, text_bin.size, &cipher_term),
text_bin.size, &aes_key, ivec2_buf, ecount2_buf, &num);
num2_term = enif_make_uint(env, num);
@@ -2009,66 +2568,102 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N
}
#endif /* !HAVE_EVP_AES_CTR */
-static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key,Iv,AAD,In) */
-#if defined(HAVE_GCM)
+static ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type,Key,Iv,AAD,In) */
+#if defined(HAVE_AEAD)
EVP_CIPHER_CTX *ctx;
const EVP_CIPHER *cipher = NULL;
ErlNifBinary key, iv, aad, in;
unsigned int tag_len;
unsigned char *outp, *tagp;
- ERL_NIF_TERM out, out_tag;
- int len;
+ ERL_NIF_TERM type, out, out_tag;
+ int len, ctx_ctrl_set_ivlen, ctx_ctrl_get_tag;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || (key.size != 16 && key.size != 24 && key.size != 32)
- || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0
- || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
- || !enif_inspect_iolist_as_binary(env, argv[3], &in)
- || !enif_get_uint(env, argv[4], &tag_len) || tag_len < 1 || tag_len > 16) {
+ type = argv[0];
+
+ if (!enif_is_atom(env, type)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &key)
+ || !enif_inspect_binary(env, argv[2], &iv)
+ || !enif_inspect_iolist_as_binary(env, argv[3], &aad)
+ || !enif_inspect_iolist_as_binary(env, argv[4], &in)
+ || !enif_get_uint(env, argv[5], &tag_len)) {
return enif_make_badarg(env);
}
- if (key.size == 16)
- cipher = EVP_aes_128_gcm();
- else if (key.size == 24)
- cipher = EVP_aes_192_gcm();
- else if (key.size == 32)
- cipher = EVP_aes_256_gcm();
-
+ /* Use cipher_type some day. Must check block_encrypt|decrypt first */
+#if defined(HAVE_GCM)
+ if (type == atom_aes_gcm) {
+ if ((iv.size > 0)
+ && (1 <= tag_len && tag_len <= 16)) {
+ ctx_ctrl_set_ivlen = EVP_CTRL_GCM_SET_IVLEN;
+ ctx_ctrl_get_tag = EVP_CTRL_GCM_GET_TAG;
+ if (key.size == 16) cipher = EVP_aes_128_gcm();
+ else if (key.size == 24) cipher = EVP_aes_192_gcm();
+ else if (key.size == 32) cipher = EVP_aes_256_gcm();
+ else enif_make_badarg(env);
+ } else
+ enif_make_badarg(env);
+ } else
+#endif
+#if defined(HAVE_CCM)
+ if (type == atom_aes_ccm) {
+ if ((7 <= iv.size && iv.size <= 13)
+ && (4 <= tag_len && tag_len <= 16)
+ && ((tag_len & 1) == 0)
+ ) {
+ ctx_ctrl_set_ivlen = EVP_CTRL_CCM_SET_IVLEN;
+ ctx_ctrl_get_tag = EVP_CTRL_CCM_GET_TAG;
+ if (key.size == 16) cipher = EVP_aes_128_ccm();
+ else if (key.size == 24) cipher = EVP_aes_192_ccm();
+ else if (key.size == 32) cipher = EVP_aes_256_ccm();
+ else enif_make_badarg(env);
+ } else
+ enif_make_badarg(env);
+ } else
+#endif
+#if defined(HAVE_CHACHA20_POLY1305)
+ if (type == atom_chacha20_poly1305) {
+ if ((key.size == 32)
+ && (1 <= iv.size && iv.size <= 16)
+ && (tag_len == 16)
+ ) {
+ ctx_ctrl_set_ivlen = EVP_CTRL_AEAD_SET_IVLEN;
+ ctx_ctrl_get_tag = EVP_CTRL_AEAD_GET_TAG,
+ cipher = EVP_chacha20_poly1305();
+ } else enif_make_badarg(env);
+ } else
+#endif
+ return enif_raise_exception(env, atom_notsup);
+
ctx = EVP_CIPHER_CTX_new();
+ if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) goto out_err;
+ if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, iv.size, NULL) != 1) goto out_err;
+
+#if defined(HAVE_CCM)
+ if (type == atom_aes_ccm) {
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag_len, NULL) != 1) goto out_err;
+ if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err;
+ if (EVP_EncryptUpdate(ctx, NULL, &len, NULL, in.size) != 1) goto out_err;
+ } else
+#endif
+ if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err;
- if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
- goto out_err;
-
- EVP_CIPHER_CTX_set_padding(ctx, 0);
-
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1)
- goto out_err;
- if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- goto out_err;
- if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
- goto out_err;
+ if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) goto out_err;
outp = enif_make_new_binary(env, in.size, &out);
- if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
- goto out_err;
- if (EVP_EncryptFinal_ex(ctx, outp+len, &len) != 1)
- goto out_err;
+ if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1) goto out_err;
+ if (EVP_EncryptFinal_ex(ctx, outp/*+len*/, &len) != 1) goto out_err;
tagp = enif_make_new_binary(env, tag_len, &out_tag);
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, tag_len, tagp) != 1)
- goto out_err;
+ if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_get_tag, tag_len, tagp) != 1) goto out_err;
EVP_CIPHER_CTX_free(ctx);
-
CONSUME_REDS(env, in);
-
return enif_make_tuple2(env, out, out_tag);
-out_err:
+out_err:
EVP_CIPHER_CTX_free(ctx);
return atom_error;
@@ -2077,58 +2672,103 @@ out_err:
#endif
}
-static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key,Iv,AAD,In,Tag) */
-#if defined(HAVE_GCM_EVP_DECRYPT_BUG)
- return aes_gcm_decrypt_NO_EVP(env, argc, argv);
-#elif defined(HAVE_GCM)
+static ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type,Key,Iv,AAD,In,Tag) */
+#if defined(HAVE_AEAD)
EVP_CIPHER_CTX *ctx;
const EVP_CIPHER *cipher = NULL;
ErlNifBinary key, iv, aad, in, tag;
unsigned char *outp;
- ERL_NIF_TERM out;
- int len;
+ ERL_NIF_TERM type, out;
+ int len, ctx_ctrl_set_ivlen, ctx_ctrl_set_tag;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || (key.size != 16 && key.size != 24 && key.size != 32)
- || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0
- || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
- || !enif_inspect_iolist_as_binary(env, argv[3], &in)
- || !enif_inspect_iolist_as_binary(env, argv[4], &tag)) {
+ type = argv[0];
+#if defined(HAVE_GCM_EVP_DECRYPT_BUG)
+ if (type == atom_aes_gcm)
+ return aes_gcm_decrypt_NO_EVP(env, argc, argv);
+#endif
+
+ if (!enif_is_atom(env, type)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &key)
+ || !enif_inspect_binary(env, argv[2], &iv)
+ || !enif_inspect_iolist_as_binary(env, argv[3], &aad)
+ || !enif_inspect_iolist_as_binary(env, argv[4], &in)
+ || !enif_inspect_iolist_as_binary(env, argv[5], &tag)) {
return enif_make_badarg(env);
}
- if (key.size == 16)
- cipher = EVP_aes_128_gcm();
- else if (key.size == 24)
- cipher = EVP_aes_192_gcm();
- else if (key.size == 32)
- cipher = EVP_aes_256_gcm();
+ /* Use cipher_type some day. Must check block_encrypt|decrypt first */
+#if defined(HAVE_GCM)
+ if (type == atom_aes_gcm) {
+ if (iv.size > 0) {
+ ctx_ctrl_set_ivlen = EVP_CTRL_GCM_SET_IVLEN;
+ ctx_ctrl_set_tag = EVP_CTRL_GCM_SET_TAG;
+ if (key.size == 16) cipher = EVP_aes_128_gcm();
+ else if (key.size == 24) cipher = EVP_aes_192_gcm();
+ else if (key.size == 32) cipher = EVP_aes_256_gcm();
+ else enif_make_badarg(env);
+ } else
+ enif_make_badarg(env);
+ } else
+#endif
+#if defined(HAVE_CCM)
+ if (type == atom_aes_ccm) {
+ if (iv.size > 0) {
+ ctx_ctrl_set_ivlen = EVP_CTRL_CCM_SET_IVLEN;
+ if (key.size == 16) cipher = EVP_aes_128_ccm();
+ else if (key.size == 24) cipher = EVP_aes_192_ccm();
+ else if (key.size == 32) cipher = EVP_aes_256_ccm();
+ else enif_make_badarg(env);
+ } else
+ enif_make_badarg(env);
+ } else
+#endif
+#if defined(HAVE_CHACHA20_POLY1305)
+ if (type == atom_chacha20_poly1305) {
+ if ((key.size == 32)
+ && (1 <= iv.size && iv.size <= 16)
+ && tag.size == 16
+ ) {
+ ctx_ctrl_set_ivlen = EVP_CTRL_AEAD_SET_IVLEN;
+ ctx_ctrl_set_tag = EVP_CTRL_AEAD_SET_TAG;
+ cipher = EVP_chacha20_poly1305();
+ } else enif_make_badarg(env);
+ } else
+#endif
+ return enif_raise_exception(env, atom_notsup);
+
+ outp = enif_make_new_binary(env, in.size, &out);
ctx = EVP_CIPHER_CTX_new();
+ if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) goto out_err;
+ if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, iv.size, NULL) != 1) goto out_err;
- if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
- goto out_err;
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1)
- goto out_err;
- if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- goto out_err;
- if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
- goto out_err;
+#if defined(HAVE_CCM)
+ if (type == atom_aes_ccm) {
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag.size, tag.data) != 1) goto out_err;
+ }
+#endif
- outp = enif_make_new_binary(env, in.size, &out);
+ if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err;
- if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
- goto out_err;
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag.size, tag.data) != 1)
- goto out_err;
- if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1)
- goto out_err;
+#if defined(HAVE_CCM)
+ if (type == atom_aes_ccm) {
+ if (1 != EVP_DecryptUpdate(ctx, NULL, &len, NULL, in.size)) goto out_err;
+ }
+#endif
+ if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) goto out_err;
+ if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1) goto out_err;
+
+#if defined(HAVE_GCM) || defined(HAVE_CHACHA20_POLY1305)
+ if (type == atom_aes_gcm) {
+ if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_tag, tag.size, tag.data) != 1) goto out_err;
+ if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1) goto out_err;
+ }
+#endif
EVP_CIPHER_CTX_free(ctx);
CONSUME_REDS(env, in);
-
return out;
out_err:
@@ -2141,19 +2781,19 @@ out_err:
#ifdef HAVE_GCM_EVP_DECRYPT_BUG
static ERL_NIF_TERM aes_gcm_decrypt_NO_EVP(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{
+{/* (Type,Key,Iv,AAD,In,Tag) */
GCM128_CONTEXT *ctx;
ErlNifBinary key, iv, aad, in, tag;
AES_KEY aes_key;
unsigned char *outp;
ERL_NIF_TERM out;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
+ if (!enif_inspect_iolist_as_binary(env, argv[1], &key)
|| AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0
- || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0
- || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
- || !enif_inspect_iolist_as_binary(env, argv[3], &in)
- || !enif_inspect_iolist_as_binary(env, argv[4], &tag)) {
+ || !enif_inspect_binary(env, argv[2], &iv) || iv.size == 0
+ || !enif_inspect_iolist_as_binary(env, argv[3], &aad)
+ || !enif_inspect_iolist_as_binary(env, argv[4], &in)
+ || !enif_inspect_iolist_as_binary(env, argv[5], &tag)) {
return enif_make_badarg(env);
}
@@ -2187,121 +2827,70 @@ out_err:
#endif /* HAVE_GCM_EVP_DECRYPT_BUG */
-static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key,Iv,AAD,In) */
-#if defined(HAVE_CHACHA20_POLY1305)
- EVP_CIPHER_CTX *ctx;
- const EVP_CIPHER *cipher = NULL;
- ErlNifBinary key, iv, aad, in;
- unsigned char *outp, *tagp;
- ERL_NIF_TERM out, out_tag;
- int len;
+static ERL_NIF_TERM chacha20_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, IV) */
+#if defined(HAVE_CHACHA20)
+ ErlNifBinary key_bin, ivec_bin;
+ struct evp_cipher_ctx *ctx;
+ const EVP_CIPHER *cipher;
+ ERL_NIF_TERM ret;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32
- || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 || iv.size > 16
- || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
- || !enif_inspect_iolist_as_binary(env, argv[3], &in)) {
- return enif_make_badarg(env);
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
+ || !enif_inspect_binary(env, argv[1], &ivec_bin)
+ || key_bin.size != 32
+ || ivec_bin.size != 16) {
+ return enif_make_badarg(env);
}
- cipher = EVP_chacha20_poly1305();
-
- ctx = EVP_CIPHER_CTX_new();
-
- if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
- goto out_err;
-
- EVP_CIPHER_CTX_set_padding(ctx, 0);
+ cipher = EVP_chacha20();
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, iv.size, NULL) != 1)
- goto out_err;
- if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- goto out_err;
- if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
- goto out_err;
-
- outp = enif_make_new_binary(env, in.size, &out);
-
- if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
- goto out_err;
- if (EVP_EncryptFinal_ex(ctx, outp+len, &len) != 1)
- goto out_err;
-
- tagp = enif_make_new_binary(env, 16, &out_tag);
-
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, tagp) != 1)
- goto out_err;
-
- EVP_CIPHER_CTX_free(ctx);
-
- CONSUME_REDS(env, in);
+ ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx));
+ ctx->ctx = EVP_CIPHER_CTX_new();
- return enif_make_tuple2(env, out, out_tag);
-out_err:
- EVP_CIPHER_CTX_free(ctx);
- return atom_error;
+ EVP_CipherInit_ex(ctx->ctx, cipher, NULL,
+ key_bin.data, ivec_bin.data, 1);
+ EVP_CIPHER_CTX_set_padding(ctx->ctx, 0);
+ ret = enif_make_resource(env, ctx);
+ enif_release_resource(ctx);
+ return ret;
#else
return enif_raise_exception(env, atom_notsup);
#endif
-}
+};
-static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key,Iv,AAD,In,Tag) */
-#if defined(HAVE_CHACHA20_POLY1305)
- EVP_CIPHER_CTX *ctx;
- const EVP_CIPHER *cipher = NULL;
- ErlNifBinary key, iv, aad, in, tag;
- unsigned char *outp;
- ERL_NIF_TERM out;
- int len;
+static ERL_NIF_TERM chacha20_stream_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (State, Data) */
+#if defined(HAVE_CHACHA20)
+ struct evp_cipher_ctx *ctx, *new_ctx;
+ ErlNifBinary data_bin;
+ ERL_NIF_TERM ret, cipher_term;
+ unsigned char *out;
+ int outl = 0;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32
- || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 || iv.size > 16
- || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
- || !enif_inspect_iolist_as_binary(env, argv[3], &in)
- || !enif_inspect_iolist_as_binary(env, argv[4], &tag) || tag.size != 16) {
- return enif_make_badarg(env);
+ if (!enif_get_resource(env, argv[0], evp_cipher_ctx_rtype, (void**)&ctx)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+ return enif_make_badarg(env);
}
+ new_ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx));
+ new_ctx->ctx = EVP_CIPHER_CTX_new();
+ EVP_CIPHER_CTX_copy(new_ctx->ctx, ctx->ctx);
+ out = enif_make_new_binary(env, data_bin.size, &cipher_term);
+ EVP_CipherUpdate(new_ctx->ctx, out, &outl, data_bin.data, data_bin.size);
+ ASSERT(outl == data_bin.size);
- cipher = EVP_chacha20_poly1305();
-
- ctx = EVP_CIPHER_CTX_new();
-
- if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
- goto out_err;
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, iv.size, NULL) != 1)
- goto out_err;
- if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- goto out_err;
- if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
- goto out_err;
-
- outp = enif_make_new_binary(env, in.size, &out);
-
- if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
- goto out_err;
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag.size, tag.data) != 1)
- goto out_err;
- if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1)
- goto out_err;
-
- EVP_CIPHER_CTX_free(ctx);
-
- CONSUME_REDS(env, in);
-
- return out;
-
-out_err:
- EVP_CIPHER_CTX_free(ctx);
- return atom_error;
+ ret = enif_make_tuple2(env, enif_make_resource(env, new_ctx), cipher_term);
+ enif_release_resource(new_ctx);
+ CONSUME_REDS(env,data_bin);
+ return ret;
#else
return enif_raise_exception(env, atom_notsup);
#endif
-}
+};
+
static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Bytes) */
+{/* (Bytes) */
unsigned bytes;
unsigned char* data;
ERL_NIF_TERM ret;
@@ -2395,7 +2984,7 @@ static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
bn_to = BN_new();
BN_sub(bn_to, bn_rand, bn_from);
- BN_pseudo_rand_range(bn_rand, bn_to);
+ BN_pseudo_rand_range(bn_rand, bn_to);
BN_add(bn_rand, bn_rand, bn_from);
dlen = BN_num_bytes(bn_rand);
data = enif_make_new_binary(env, dlen+4, &ret);
@@ -2413,7 +3002,7 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
BIGNUM *bn_base=NULL, *bn_exponent=NULL, *bn_modulo=NULL, *bn_result;
BN_CTX *bn_ctx;
unsigned char* ptr;
- unsigned dlen;
+ unsigned dlen;
unsigned bin_hdr; /* return type: 0=plain binary, 4: mpint */
unsigned extra_byte;
ERL_NIF_TERM ret;
@@ -2434,7 +3023,7 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
dlen = BN_num_bytes(bn_result);
extra_byte = bin_hdr && BN_is_bit_set(bn_result, dlen*8-1);
ptr = enif_make_new_binary(env, bin_hdr+extra_byte+dlen, &ret);
- if (bin_hdr) {
+ if (bin_hdr) {
put_int32(ptr, extra_byte+dlen);
ptr[4] = 0; /* extra zeroed byte to ensure a positive mpint */
ptr += bin_hdr + extra_byte;
@@ -2448,44 +3037,6 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
return ret;
}
-static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (sha, Digest, Signature,Key=[P, Q, G, Y]) */
- ErlNifBinary digest_bin, sign_bin;
- BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_y = NULL;
- ERL_NIF_TERM head, tail;
- DSA *dsa;
- int i;
-
- if (argv[0] != atom_sha
- || !enif_inspect_binary(env, argv[1], &digest_bin)
- || digest_bin.size != SHA_DIGEST_LENGTH
- || !enif_inspect_binary(env, argv[2], &sign_bin)
- || !enif_get_list_cell(env, argv[3], &head, &tail)
- || !get_bn_from_bin(env, head, &dsa_p)
- || !enif_get_list_cell(env, tail, &head, &tail)
- || !get_bn_from_bin(env, head, &dsa_q)
- || !enif_get_list_cell(env, tail, &head, &tail)
- || !get_bn_from_bin(env, head, &dsa_g)
- || !enif_get_list_cell(env, tail, &head, &tail)
- || !get_bn_from_bin(env, head, &dsa_y)
- || !enif_is_empty_list(env,tail)) {
-
- if (dsa_p) BN_free(dsa_p);
- if (dsa_q) BN_free(dsa_q);
- if (dsa_g) BN_free(dsa_g);
- if (dsa_y) BN_free(dsa_y);
- return enif_make_badarg(env);
- }
-
- dsa = DSA_new();
- DSA_set0_pqg(dsa, dsa_p, dsa_q, dsa_g);
- DSA_set0_key(dsa, dsa_y, NULL);
- i = DSA_verify(0, digest_bin.data, SHA_DIGEST_LENGTH,
- sign_bin.data, sign_bin.size, dsa);
- DSA_free(dsa);
- return(i > 0) ? atom_true : atom_false;
-}
-
static void init_digest_types(ErlNifEnv* env)
{
struct digest_type_t* p = digest_types;
@@ -2532,72 +3083,6 @@ static struct cipher_type_t* get_cipher_type(ERL_NIF_TERM type, size_t key_len)
return NULL;
}
-static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Digest, Signature, Key=[E,N]) */
- ErlNifBinary digest_bin, sign_bin;
- ERL_NIF_TERM head, tail, ret;
- int i;
- RSA *rsa;
-#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
- EVP_PKEY *pkey;
- EVP_PKEY_CTX *ctx;
-#endif
- const EVP_MD *md;
- const ERL_NIF_TERM type = argv[0];
- struct digest_type_t *digp = NULL;
- BIGNUM *rsa_e;
- BIGNUM *rsa_n;
-
- digp = get_digest_type(type);
- if (!digp) {
- return enif_make_badarg(env);
- }
- md = digp->md.p;
- if (!md) {
- return atom_notsup;
- }
-
- rsa = RSA_new();
-
- if (!enif_inspect_binary(env, argv[1], &digest_bin)
- || digest_bin.size != EVP_MD_size(md)
- || !enif_inspect_binary(env, argv[2], &sign_bin)
- || !enif_get_list_cell(env, argv[3], &head, &tail)
- || !get_bn_from_bin(env, head, &rsa_e)
- || !enif_get_list_cell(env, tail, &head, &tail)
- || !get_bn_from_bin(env, head, &rsa_n)
- || !enif_is_empty_list(env, tail)) {
-
- ret = enif_make_badarg(env);
- goto done;
- }
-
- (void) RSA_set0_key(rsa, rsa_n, rsa_e, NULL);
-
-#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
- pkey = EVP_PKEY_new();
- EVP_PKEY_set1_RSA(pkey, rsa);
-
- ctx = EVP_PKEY_CTX_new(pkey, NULL);
- EVP_PKEY_verify_init(ctx);
- EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING);
- EVP_PKEY_CTX_set_signature_md(ctx, md);
-
- i = EVP_PKEY_verify(ctx, sign_bin.data, sign_bin.size,
- digest_bin.data, digest_bin.size);
- EVP_PKEY_CTX_free(ctx);
- EVP_PKEY_free(pkey);
-#else
- i = RSA_verify(md->type, digest_bin.data, EVP_MD_size(md),
- sign_bin.data, sign_bin.size, rsa);
-#endif
-
- ret = (i==1 ? atom_true : atom_false);
-
-done:
- RSA_free(rsa);
- return ret;
-}
static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Data1, Data2) */
@@ -2632,7 +3117,7 @@ static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
return enif_make_badarg(env);
}
RC4_set_key((RC4_KEY*)enif_make_new_binary(env, sizeof(RC4_KEY), &ret),
- key.size, key.data);
+ key.size, key.data);
return ret;
#else
return enif_raise_exception(env, atom_notsup);
@@ -2702,100 +3187,33 @@ static int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, RSA *rsa)
return 1;
}
-static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Digest, Key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C]) */
- ErlNifBinary digest_bin, ret_bin;
-#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
- EVP_PKEY *pkey;
- EVP_PKEY_CTX *ctx;
- size_t rsa_s_len;
-#else
- unsigned rsa_s_len, len;
-#endif
- RSA *rsa;
- int i;
- struct digest_type_t *digp;
- const EVP_MD *md;
-
- digp = get_digest_type(argv[0]);
- if (!digp) {
- return enif_make_badarg(env);
- }
- md = digp->md.p;
- if (!md) {
- return atom_notsup;
- }
- if (!enif_inspect_binary(env,argv[1],&digest_bin)
- || digest_bin.size != EVP_MD_size(md)) {
- return enif_make_badarg(env);
- }
+static int get_rsa_public_key(ErlNifEnv* env, ERL_NIF_TERM key, RSA *rsa)
+{
+ /* key=[E,N] */
+ ERL_NIF_TERM head, tail;
+ BIGNUM *e, *n;
- rsa = RSA_new();
- if (!get_rsa_private_key(env, argv[2], rsa)) {
- RSA_free(rsa);
- return enif_make_badarg(env);
+ if (!enif_get_list_cell(env, key, &head, &tail)
+ || !get_bn_from_bin(env, head, &e)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+ || !get_bn_from_bin(env, head, &n)
+ || !enif_is_empty_list(env, tail)) {
+ return 0;
}
-
-#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
- pkey = EVP_PKEY_new();
- EVP_PKEY_set1_RSA(pkey, rsa);
- rsa_s_len=(size_t)EVP_PKEY_size(pkey);
- enif_alloc_binary(rsa_s_len, &ret_bin);
-
- ctx = EVP_PKEY_CTX_new(pkey, NULL);
- EVP_PKEY_sign_init(ctx);
- EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING);
- EVP_PKEY_CTX_set_signature_md(ctx, md);
-
- i = EVP_PKEY_sign(ctx, ret_bin.data, &rsa_s_len,
- digest_bin.data, digest_bin.size);
- ASSERT(i<=0 || rsa_s_len <= ret_bin.size);
- EVP_PKEY_CTX_free(ctx);
- EVP_PKEY_free(pkey);
-#else
- enif_alloc_binary(RSA_size(rsa), &ret_bin);
- len = EVP_MD_size(md);
-
- ERL_VALGRIND_ASSERT_MEM_DEFINED(digest_bin.data, len);
- i = RSA_sign(md->type, digest_bin.data, len,
- ret_bin.data, &rsa_s_len, rsa);
-#endif
-
- RSA_free(rsa);
- if (i > 0) {
- ERL_VALGRIND_MAKE_MEM_DEFINED(ret_bin.data, rsa_s_len);
- if (rsa_s_len != ret_bin.size) {
- enif_realloc_binary(&ret_bin, rsa_s_len);
- ERL_VALGRIND_ASSERT_MEM_DEFINED(ret_bin.data, rsa_s_len);
- }
- return enif_make_binary(env,&ret_bin);
- }
- else {
- enif_release_binary(&ret_bin);
- return atom_error;
- }
+ (void) RSA_set0_key(rsa, n, e, NULL);
+ return 1;
}
-
-static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (sha, Digest, Key=[P,Q,G,PrivKey]) */
- ErlNifBinary digest_bin, ret_bin;
+static int get_dss_private_key(ErlNifEnv* env, ERL_NIF_TERM key, DSA *dsa)
+{
+ /* key=[P,Q,G,KEY] */
ERL_NIF_TERM head, tail;
- unsigned int dsa_s_len;
- DSA* dsa;
BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL;
BIGNUM *dummy_pub_key, *priv_key = NULL;
- int i;
- if (argv[0] != atom_sha
- || !enif_inspect_binary(env, argv[1], &digest_bin)
- || digest_bin.size != SHA_DIGEST_LENGTH) {
- return enif_make_badarg(env);
- }
-
- if (!enif_get_list_cell(env, argv[2], &head, &tail)
+ if (!enif_get_list_cell(env, key, &head, &tail)
|| !get_bn_from_bin(env, head, &dsa_p)
|| !enif_get_list_cell(env, tail, &head, &tail)
|| !get_bn_from_bin(env, head, &dsa_q)
@@ -2808,7 +3226,7 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
if (dsa_q) BN_free(dsa_q);
if (dsa_g) BN_free(dsa_g);
if (priv_key) BN_free(priv_key);
- return enif_make_badarg(env);
+ return 0;
}
/* Note: DSA_set0_key() does not allow setting only the
@@ -2818,137 +3236,37 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
*/
dummy_pub_key = BN_dup(priv_key);
- dsa = DSA_new();
DSA_set0_pqg(dsa, dsa_p, dsa_q, dsa_g);
DSA_set0_key(dsa, dummy_pub_key, priv_key);
- enif_alloc_binary(DSA_size(dsa), &ret_bin);
- i = DSA_sign(NID_sha1, digest_bin.data, SHA_DIGEST_LENGTH,
- ret_bin.data, &dsa_s_len, dsa);
- DSA_free(dsa);
-
- if (i) {
- if (dsa_s_len != ret_bin.size) {
- enif_realloc_binary(&ret_bin, dsa_s_len);
- }
- return enif_make_binary(env, &ret_bin);
- }
- else {
- enif_release_binary(&ret_bin);
- return atom_error;
- }
+ return 1;
}
-static int rsa_pad(ERL_NIF_TERM term, int* padding)
+static int get_dss_public_key(ErlNifEnv* env, ERL_NIF_TERM key, DSA *dsa)
{
- if (term == atom_rsa_pkcs1_padding) {
- *padding = RSA_PKCS1_PADDING;
- }
- else if (term == atom_rsa_pkcs1_oaep_padding) {
- *padding = RSA_PKCS1_OAEP_PADDING;
- }
- else if (term == atom_rsa_no_padding) {
- *padding = RSA_NO_PADDING;
- }
- else {
- return 0;
- }
- return 1;
-}
-
-static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data, PublKey=[E,N], Padding, IsEncrypt) */
- ErlNifBinary data_bin, ret_bin;
+ /* key=[P, Q, G, Y] */
ERL_NIF_TERM head, tail;
- int padding, i;
- RSA* rsa;
- BIGNUM *e, *n;
-
- rsa = RSA_new();
+ BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_y = NULL;
- if (!enif_inspect_binary(env, argv[0], &data_bin)
- || !enif_get_list_cell(env, argv[1], &head, &tail)
- || !get_bn_from_bin(env, head, &e)
+ if (!enif_get_list_cell(env, key, &head, &tail)
+ || !get_bn_from_bin(env, head, &dsa_p)
|| !enif_get_list_cell(env, tail, &head, &tail)
- || !get_bn_from_bin(env, head, &n)
- || !enif_is_empty_list(env,tail)
- || !rsa_pad(argv[2], &padding)) {
-
- RSA_free(rsa);
- return enif_make_badarg(env);
- }
- (void) RSA_set0_key(rsa, n, e, NULL);
-
- enif_alloc_binary(RSA_size(rsa), &ret_bin);
-
- if (argv[3] == atom_true) {
- ERL_VALGRIND_ASSERT_MEM_DEFINED(data_bin.data,data_bin.size);
- i = RSA_public_encrypt(data_bin.size, data_bin.data,
- ret_bin.data, rsa, padding);
- if (i > 0) {
- ERL_VALGRIND_MAKE_MEM_DEFINED(ret_bin.data, i);
- }
- }
- else {
- i = RSA_public_decrypt(data_bin.size, data_bin.data,
- ret_bin.data, rsa, padding);
- if (i > 0) {
- ERL_VALGRIND_MAKE_MEM_DEFINED(ret_bin.data, i);
- enif_realloc_binary(&ret_bin, i);
- }
- }
- RSA_free(rsa);
- if (i > 0) {
- return enif_make_binary(env,&ret_bin);
- }
- else {
- enif_release_binary(&ret_bin);
- return atom_error;
- }
-}
-
-static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data, Key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C], Padding, IsEncrypt) */
- ErlNifBinary data_bin, ret_bin;
- int padding, i;
- RSA* rsa;
-
- rsa = RSA_new();
-
- if (!enif_inspect_binary(env, argv[0], &data_bin)
- || !get_rsa_private_key(env, argv[1], rsa)
- || !rsa_pad(argv[2], &padding)) {
-
- RSA_free(rsa);
- return enif_make_badarg(env);
+ || !get_bn_from_bin(env, head, &dsa_q)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+ || !get_bn_from_bin(env, head, &dsa_g)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+ || !get_bn_from_bin(env, head, &dsa_y)
+ || !enif_is_empty_list(env,tail)) {
+ if (dsa_p) BN_free(dsa_p);
+ if (dsa_q) BN_free(dsa_q);
+ if (dsa_g) BN_free(dsa_g);
+ if (dsa_y) BN_free(dsa_y);
+ return 0;
}
- enif_alloc_binary(RSA_size(rsa), &ret_bin);
-
- if (argv[3] == atom_true) {
- ERL_VALGRIND_ASSERT_MEM_DEFINED(data_bin.data,data_bin.size);
- i = RSA_private_encrypt(data_bin.size, data_bin.data,
- ret_bin.data, rsa, padding);
- if (i > 0) {
- ERL_VALGRIND_MAKE_MEM_DEFINED(ret_bin.data, i);
- }
- }
- else {
- i = RSA_private_decrypt(data_bin.size, data_bin.data,
- ret_bin.data, rsa, padding);
- if (i > 0) {
- ERL_VALGRIND_MAKE_MEM_DEFINED(ret_bin.data, i);
- enif_realloc_binary(&ret_bin, i);
- }
- }
- RSA_free(rsa);
- if (i > 0) {
- return enif_make_binary(env,&ret_bin);
- }
- else {
- enif_release_binary(&ret_bin);
- return atom_error;
- }
+ DSA_set0_pqg(dsa, dsa_p, dsa_q, dsa_g);
+ DSA_set0_key(dsa, dsa_y, NULL);
+ return 1;
}
/* Creates a term which can be parsed by get_rsa_private_key(). This is a list of plain integer binaries (not mpints). */
@@ -3064,184 +3382,189 @@ static ERL_NIF_TERM rsa_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF
rsa_generate_key, argc, argv);
}
-static ERL_NIF_TERM dh_generate_parameters_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (PrimeLen, Generator) */
- int prime_len, generator;
- DH* dh_params;
- int p_len, g_len;
- unsigned char *p_ptr, *g_ptr;
- ERL_NIF_TERM ret_p, ret_g;
- const BIGNUM *dh_p, *dh_q, *dh_g;
-
- if (!enif_get_int(env, argv[0], &prime_len)
- || !enif_get_int(env, argv[1], &generator)) {
-
- return enif_make_badarg(env);
- }
- dh_params = DH_generate_parameters(prime_len, generator, NULL, NULL);
- if (dh_params == NULL) {
- return atom_error;
- }
- DH_get0_pqg(dh_params, &dh_p, &dh_q, &dh_g);
- DH_free(dh_params);
- p_len = BN_num_bytes(dh_p);
- g_len = BN_num_bytes(dh_g);
- p_ptr = enif_make_new_binary(env, p_len, &ret_p);
- g_ptr = enif_make_new_binary(env, g_len, &ret_g);
- BN_bn2bin(dh_p, p_ptr);
- BN_bn2bin(dh_g, g_ptr);
- ERL_VALGRIND_MAKE_MEM_DEFINED(p_ptr, p_len);
- ERL_VALGRIND_MAKE_MEM_DEFINED(g_ptr, g_len);
- return enif_make_list2(env, ret_p, ret_g);
-}
-
-static ERL_NIF_TERM dh_check(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* ([PrimeLen, Generator]) */
- DH* dh_params;
- int i;
- ERL_NIF_TERM ret, head, tail;
- BIGNUM *dh_p, *dh_g;
-
- if (!enif_get_list_cell(env, argv[0], &head, &tail)
- || !get_bn_from_bin(env, head, &dh_p)
- || !enif_get_list_cell(env, tail, &head, &tail)
- || !get_bn_from_bin(env, head, &dh_g)
- || !enif_is_empty_list(env,tail)) {
-
- return enif_make_badarg(env);
- }
-
- dh_params = DH_new();
- DH_set0_pqg(dh_params, dh_p, NULL, dh_g);
- if (DH_check(dh_params, &i)) {
- if (i == 0) ret = atom_ok;
- else if (i & DH_CHECK_P_NOT_PRIME) ret = atom_not_prime;
- else if (i & DH_CHECK_P_NOT_SAFE_PRIME) ret = atom_not_strong_prime;
- else if (i & DH_UNABLE_TO_CHECK_GENERATOR) ret = atom_unable_to_check_generator;
- else if (i & DH_NOT_SUITABLE_GENERATOR) ret = atom_not_suitable_generator;
- else ret = enif_make_tuple2(env, atom_unknown, enif_make_uint(env, i));
- }
- else { /* Check Failed */
- ret = enif_make_tuple2(env, atom_error, atom_check_failed);
- }
- DH_free(dh_params);
- return ret;
-}
-
static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (PrivKey|undefined, DHParams=[P,G], Mpint, Len|0) */
- DH* dh_params;
- int pub_len, prv_len;
- unsigned char *pub_ptr, *prv_ptr;
- ERL_NIF_TERM ret, ret_pub, ret_prv, head, tail;
+ DH *dh_params = NULL;
int mpint; /* 0 or 4 */
- BIGNUM *priv_key = NULL;
- BIGNUM *dh_p = NULL, *dh_g = NULL;
- unsigned long len = 0;
- if (!(get_bn_from_bin(env, argv[0], &priv_key)
- || argv[0] == atom_undefined)
- || !enif_get_list_cell(env, argv[1], &head, &tail)
- || !get_bn_from_bin(env, head, &dh_p)
- || !enif_get_list_cell(env, tail, &head, &tail)
- || !get_bn_from_bin(env, head, &dh_g)
- || !enif_is_empty_list(env, tail)
- || !enif_get_int(env, argv[2], &mpint) || (mpint & ~4)
- || !enif_get_ulong(env, argv[3], &len) ) {
-
- if (priv_key) BN_free(priv_key);
- if (dh_p) BN_free(dh_p);
- if (dh_g) BN_free(dh_g);
- return enif_make_badarg(env);
+ {
+ ERL_NIF_TERM head, tail;
+ BIGNUM
+ *dh_p = NULL,
+ *dh_g = NULL,
+ *priv_key_in = NULL;
+ unsigned long
+ len = 0;
+
+ if (!(get_bn_from_bin(env, argv[0], &priv_key_in)
+ || argv[0] == atom_undefined)
+ || !enif_get_list_cell(env, argv[1], &head, &tail)
+ || !get_bn_from_bin(env, head, &dh_p)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+ || !get_bn_from_bin(env, head, &dh_g)
+ || !enif_is_empty_list(env, tail)
+ || !enif_get_int(env, argv[2], &mpint) || (mpint & ~4)
+ || !enif_get_ulong(env, argv[3], &len)
+
+ /* Load dh_params with values to use by the generator.
+ Mem mgmnt transfered from dh_p etc to dh_params */
+ || !(dh_params = DH_new())
+ || (priv_key_in && !DH_set0_key(dh_params, NULL, priv_key_in))
+ || !DH_set0_pqg(dh_params, dh_p, NULL, dh_g)
+ ) {
+ if (priv_key_in) BN_free(priv_key_in);
+ if (dh_p) BN_free(dh_p);
+ if (dh_g) BN_free(dh_g);
+ if (dh_params) DH_free(dh_params);
+ return enif_make_badarg(env);
+ }
+
+ if (len) {
+ if (len < BN_num_bits(dh_p))
+ DH_set_length(dh_params, len);
+ else {
+ if (priv_key_in) BN_free(priv_key_in);
+ if (dh_p) BN_free(dh_p);
+ if (dh_g) BN_free(dh_g);
+ if (dh_params) DH_free(dh_params);
+ return enif_make_badarg(env);
+ }
+ }
}
- dh_params = DH_new();
- DH_set0_key(dh_params, NULL, priv_key);
- DH_set0_pqg(dh_params, dh_p, NULL, dh_g);
+#ifdef HAS_EVP_PKEY_CTX
+ {
+ EVP_PKEY_CTX *ctx;
+ EVP_PKEY *dhkey, *params;
+ int success;
+
+ params = EVP_PKEY_new();
+ success = EVP_PKEY_set1_DH(params, dh_params); /* set the key referenced by params to dh_params... */
+ DH_free(dh_params); /* ...dh_params (and params) must be freed */
+ if (!success) return atom_error;
+
+ ctx = EVP_PKEY_CTX_new(params, NULL);
+ EVP_PKEY_free(params);
+ if (!ctx) {
+ return atom_error;
+ }
+
+ if (!EVP_PKEY_keygen_init(ctx)) {
+ /* EVP_PKEY_CTX_free(ctx); */
+ return atom_error;
+ }
- if (len) {
- if (len < BN_num_bits(dh_p))
- DH_set_length(dh_params, len);
- else {
- DH_free(dh_params);
- return enif_make_badarg(env);
+ dhkey = EVP_PKEY_new();
+ if (!EVP_PKEY_keygen(ctx, &dhkey)) { /* "performs a key generation operation, the ... */
+ /*... generated key is written to ppkey." (=last arg) */
+ /* EVP_PKEY_CTX_free(ctx); */
+ /* EVP_PKEY_free(dhkey); */
+ return atom_error;
}
- }
- if (DH_generate_key(dh_params)) {
- const BIGNUM *pub_key, *priv_key;
- DH_get0_key(dh_params, &pub_key, &priv_key);
- pub_len = BN_num_bytes(pub_key);
- prv_len = BN_num_bytes(priv_key);
- pub_ptr = enif_make_new_binary(env, pub_len+mpint, &ret_pub);
- prv_ptr = enif_make_new_binary(env, prv_len+mpint, &ret_prv);
- if (mpint) {
- put_int32(pub_ptr, pub_len); pub_ptr += 4;
- put_int32(prv_ptr, prv_len); prv_ptr += 4;
- }
- BN_bn2bin(pub_key, pub_ptr);
- BN_bn2bin(priv_key, prv_ptr);
- ERL_VALGRIND_MAKE_MEM_DEFINED(pub_ptr, pub_len);
- ERL_VALGRIND_MAKE_MEM_DEFINED(prv_ptr, prv_len);
- ret = enif_make_tuple2(env, ret_pub, ret_prv);
+ dh_params = EVP_PKEY_get1_DH(dhkey); /* return the referenced key. dh_params and dhkey must be freed */
+ EVP_PKEY_free(dhkey);
+ if (!dh_params) {
+ /* EVP_PKEY_CTX_free(ctx); */
+ return atom_error;
+ }
+ EVP_PKEY_CTX_free(ctx);
}
- else {
- ret = atom_error;
+#else
+ if (!DH_generate_key(dh_params)) return atom_error;
+#endif
+ {
+ unsigned char *pub_ptr, *prv_ptr;
+ int pub_len, prv_len;
+ ERL_NIF_TERM ret_pub, ret_prv;
+ const BIGNUM *pub_key_gen, *priv_key_gen;
+
+ DH_get0_key(dh_params,
+ &pub_key_gen, &priv_key_gen); /* Get pub_key_gen and priv_key_gen.
+ "The values point to the internal representation of
+ the public key and private key values. This memory
+ should not be freed directly." says man */
+ pub_len = BN_num_bytes(pub_key_gen);
+ prv_len = BN_num_bytes(priv_key_gen);
+ pub_ptr = enif_make_new_binary(env, pub_len+mpint, &ret_pub);
+ prv_ptr = enif_make_new_binary(env, prv_len+mpint, &ret_prv);
+ if (mpint) {
+ put_int32(pub_ptr, pub_len); pub_ptr += 4;
+ put_int32(prv_ptr, prv_len); prv_ptr += 4;
+ }
+ BN_bn2bin(pub_key_gen, pub_ptr);
+ BN_bn2bin(priv_key_gen, prv_ptr);
+ ERL_VALGRIND_MAKE_MEM_DEFINED(pub_ptr, pub_len);
+ ERL_VALGRIND_MAKE_MEM_DEFINED(prv_ptr, prv_len);
+
+ DH_free(dh_params);
+
+ return enif_make_tuple2(env, ret_pub, ret_prv);
}
- DH_free(dh_params);
- return ret;
}
static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (OthersPublicKey, MyPrivateKey, DHParams=[P,G]) */
- DH* dh_params;
- BIGNUM *dummy_pub_key = NULL, *priv_key = NULL;
- BIGNUM *other_pub_key;
- BIGNUM *dh_p = NULL, *dh_g = NULL;
- int i;
- ErlNifBinary ret_bin;
- ERL_NIF_TERM ret, head, tail;
+ BIGNUM *other_pub_key = NULL,
+ *dh_p = NULL,
+ *dh_g = NULL;
+ DH *dh_priv = DH_new();
- dh_params = DH_new();
+ /* Check the arguments and get
+ my private key (dh_priv),
+ the peer's public key (other_pub_key),
+ the parameters p & q
+ */
- if (!get_bn_from_bin(env, argv[0], &other_pub_key)
- || !get_bn_from_bin(env, argv[1], &priv_key)
- || !enif_get_list_cell(env, argv[2], &head, &tail)
- || !get_bn_from_bin(env, head, &dh_p)
- || !enif_get_list_cell(env, tail, &head, &tail)
- || !get_bn_from_bin(env, head, &dh_g)
- || !enif_is_empty_list(env, tail)) {
- if (dh_p) BN_free(dh_p);
- if (dh_g) BN_free(dh_g);
- ret = enif_make_badarg(env);
+ {
+ BIGNUM *dummy_pub_key = NULL,
+ *priv_key = NULL;
+ ERL_NIF_TERM head, tail;
+
+ if (!get_bn_from_bin(env, argv[0], &other_pub_key)
+ || !get_bn_from_bin(env, argv[1], &priv_key)
+ || !enif_get_list_cell(env, argv[2], &head, &tail)
+ || !get_bn_from_bin(env, head, &dh_p)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+ || !get_bn_from_bin(env, head, &dh_g)
+ || !enif_is_empty_list(env, tail)
+
+ /* Note: DH_set0_key() does not allow setting only the
+ * private key, although DH_compute_key() does not use the
+ * public key. Work around this limitation by setting
+ * the public key to a copy of the private key.
+ */
+ || !(dummy_pub_key = BN_dup(priv_key))
+ || !DH_set0_key(dh_priv, dummy_pub_key, priv_key)
+ || !DH_set0_pqg(dh_priv, dh_p, NULL, dh_g)
+ ) {
+ if (dh_p) BN_free(dh_p);
+ if (dh_g) BN_free(dh_g);
+ if (other_pub_key) BN_free(other_pub_key);
+ if (dummy_pub_key) BN_free(dummy_pub_key);
+ if (priv_key) BN_free(priv_key);
+ return enif_make_badarg(env);
+ }
}
- else {
- /* Note: DH_set0_key() does not allow setting only the
- * private key, although DH_compute_key() does not use the
- * public key. Work around this limitation by setting
- * the public key to a copy of the private key.
- */
- dummy_pub_key = BN_dup(priv_key);
- DH_set0_key(dh_params, dummy_pub_key, priv_key);
- DH_set0_pqg(dh_params, dh_p, NULL, dh_g);
- enif_alloc_binary(DH_size(dh_params), &ret_bin);
- i = DH_compute_key(ret_bin.data, other_pub_key, dh_params);
- if (i > 0) {
- if (i != ret_bin.size) {
- enif_realloc_binary(&ret_bin, i);
- }
- ret = enif_make_binary(env, &ret_bin);
- }
- else {
+ {
+ ErlNifBinary ret_bin;
+ int size;
+
+ enif_alloc_binary(DH_size(dh_priv), &ret_bin);
+ size = DH_compute_key(ret_bin.data, other_pub_key, dh_priv);
+ BN_free(other_pub_key);
+ DH_free(dh_priv);
+ if (size<=0) {
enif_release_binary(&ret_bin);
- ret = atom_error;
- }
+ return atom_error;
+ }
+
+ if (size != ret_bin.size) enif_realloc_binary(&ret_bin, size);
+ return enif_make_binary(env, &ret_bin);
}
- if (other_pub_key) BN_free(other_pub_key);
- DH_free(dh_params);
- return ret;
}
+
static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Multiplier, Verifier, Generator, Exponent, Prime) */
BIGNUM *bn_verifier = NULL;
@@ -3788,99 +4111,6 @@ badarg:
#endif
}
-static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Digest, Curve, Key) */
-#if defined(HAVE_EC)
- ErlNifBinary digest_bin, ret_bin;
- unsigned int dsa_s_len;
- EC_KEY* key = NULL;
- int i, len;
- struct digest_type_t *digp;
- const EVP_MD *md;
-
- digp = get_digest_type(argv[0]);
- if (!digp) {
- return enif_make_badarg(env);
- }
- md = digp->md.p;
- if (!md) {
- return atom_notsup;
- }
- len = EVP_MD_size(md);
-
- if (!enif_inspect_binary(env,argv[1],&digest_bin)
- || digest_bin.size != len
- || !get_ec_key(env, argv[2], argv[3], atom_undefined, &key))
- goto badarg;
-
- enif_alloc_binary(ECDSA_size(key), &ret_bin);
-
- i = ECDSA_sign(EVP_MD_type(md), digest_bin.data, len,
- ret_bin.data, &dsa_s_len, key);
-
- EC_KEY_free(key);
- if (i) {
- if (dsa_s_len != ret_bin.size) {
- enif_realloc_binary(&ret_bin, dsa_s_len);
- }
- return enif_make_binary(env, &ret_bin);
- }
- else {
- enif_release_binary(&ret_bin);
- return atom_error;
- }
-
-badarg:
- if (key)
- EC_KEY_free(key);
- return make_badarg_maybe(env);
-#else
- return atom_notsup;
-#endif
-}
-
-static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Digest, Signature, Curve, Key) */
-#if defined(HAVE_EC)
- ErlNifBinary digest_bin, sign_bin;
- int i, len;
- EC_KEY* key = NULL;
- const ERL_NIF_TERM type = argv[0];
- struct digest_type_t *digp = NULL;
- const EVP_MD *md;
-
- digp = get_digest_type(type);
- if (!digp) {
- return enif_make_badarg(env);
- }
- md = digp->md.p;
- if (!md) {
- return atom_notsup;
- }
- len = EVP_MD_size(md);
-
- if (!enif_inspect_binary(env, argv[1], &digest_bin)
- || digest_bin.size != len
- || !enif_inspect_binary(env, argv[2], &sign_bin)
- || !get_ec_key(env, argv[3], atom_undefined, argv[4], &key))
- goto badarg;
-
- i = ECDSA_verify(EVP_MD_type(md), digest_bin.data, len,
- sign_bin.data, sign_bin.size, key);
-
- EC_KEY_free(key);
-
- return (i==1 ? atom_true : atom_false);
-
-badarg:
- if (key)
- EC_KEY_free(key);
- return make_badarg_maybe(env);
-#else
- return atom_notsup;
-#endif
-}
-
/*
(_OthersPublicKey, _MyPrivateKey)
(_OthersPublicKey, _MyEC_Point)
@@ -3896,7 +4126,7 @@ static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF
int i;
EC_GROUP *group;
const BIGNUM *priv_key;
- EC_POINT *my_ecpoint;
+ EC_POINT *my_ecpoint = NULL;
EC_KEY *other_ecdh = NULL;
if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &key))
@@ -3939,6 +4169,1202 @@ out_err:
#endif
}
+static ERL_NIF_TERM evp_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ /* (Curve, PeerBin, MyBin) */
+{
+#ifdef HAVE_ED_CURVE_DH
+ int type;
+ EVP_PKEY_CTX *ctx;
+ ErlNifBinary peer_bin, my_bin, key_bin;
+ EVP_PKEY *peer_key, *my_key;
+ size_t max_size;
+
+ if (argv[0] == atom_x25519) type = EVP_PKEY_X25519;
+ else if (argv[0] == atom_x448) type = EVP_PKEY_X448;
+ else return enif_make_badarg(env);
+
+ if (!enif_inspect_binary(env, argv[1], &peer_bin) ||
+ !enif_inspect_binary(env, argv[2], &my_bin)) {
+ return enif_make_badarg(env);
+ }
+
+ if (!(my_key = EVP_PKEY_new_raw_private_key(type, NULL, my_bin.data, my_bin.size)) ||
+ !(ctx = EVP_PKEY_CTX_new(my_key, NULL))) {
+ return enif_make_badarg(env);
+ }
+
+ if (!EVP_PKEY_derive_init(ctx)) {
+ return enif_make_badarg(env);
+ }
+
+ if (!(peer_key = EVP_PKEY_new_raw_public_key(type, NULL, peer_bin.data, peer_bin.size)) ||
+ !EVP_PKEY_derive_set_peer(ctx, peer_key)) {
+ return enif_make_badarg(env);
+ }
+
+ if (!EVP_PKEY_derive(ctx, NULL, &max_size)) {
+ return enif_make_badarg(env);
+ }
+
+ if (!enif_alloc_binary(max_size, &key_bin) ||
+ !EVP_PKEY_derive(ctx, key_bin.data, &key_bin.size)) {
+ return enif_make_badarg(env);
+ }
+
+ if (key_bin.size < max_size) {
+ size_t actual_size = key_bin.size;
+ if (!enif_realloc_binary(&key_bin, actual_size)) {
+ return enif_make_badarg(env);
+ }
+ }
+
+ return enif_make_binary(env, &key_bin);
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+/* (Curve) */
+{
+#ifdef HAVE_ED_CURVE_DH
+ int type;
+ EVP_PKEY_CTX *ctx;
+ EVP_PKEY *pkey = NULL;
+ ERL_NIF_TERM ret_pub, ret_prv;
+ size_t key_len;
+
+ if (argv[0] == atom_x25519) type = EVP_PKEY_X25519;
+ else if (argv[0] == atom_x448) type = EVP_PKEY_X448;
+ else return enif_make_badarg(env);
+
+ if (!(ctx = EVP_PKEY_CTX_new_id(type, NULL))) return enif_make_badarg(env);
+
+ if (!EVP_PKEY_keygen_init(ctx)) return atom_error;
+ if (!EVP_PKEY_keygen(ctx, &pkey)) return atom_error;
+
+ if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &key_len)) return atom_error;
+ if (!EVP_PKEY_get_raw_public_key(pkey,
+ enif_make_new_binary(env, key_len, &ret_pub),
+ &key_len))
+ return atom_error;
+
+ if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &key_len)) return atom_error;
+ if (!EVP_PKEY_get_raw_private_key(pkey,
+ enif_make_new_binary(env, key_len, &ret_prv),
+ &key_len))
+ return atom_error;
+
+ return enif_make_tuple2(env, ret_pub, ret_prv);
+#else
+ return atom_notsup;
+#endif
+}
+
+/*================================================================*/
+#define PKEY_BADARG -1
+#define PKEY_NOTSUP 0
+#define PKEY_OK 1
+
+typedef struct PKeyCryptOptions {
+ const EVP_MD *rsa_mgf1_md;
+ ErlNifBinary rsa_oaep_label;
+ const EVP_MD *rsa_oaep_md;
+ int rsa_padding;
+ const EVP_MD *signature_md;
+} PKeyCryptOptions;
+
+typedef struct PKeySignOptions {
+ const EVP_MD *rsa_mgf1_md;
+ int rsa_padding;
+ int rsa_pss_saltlen;
+} PKeySignOptions;
+
+static int get_pkey_digest_type(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM type,
+ const EVP_MD **md)
+{
+ struct digest_type_t *digp = NULL;
+ *md = NULL;
+
+ if (type == atom_none && algorithm == atom_rsa) return PKEY_OK;
+
+ digp = get_digest_type(type);
+ if (!digp) return PKEY_BADARG;
+ if (!digp->md.p) return PKEY_NOTSUP;
+
+ *md = digp->md.p;
+ return PKEY_OK;
+}
+
+
+static int get_pkey_sign_digest(ErlNifEnv *env, ERL_NIF_TERM algorithm,
+ ERL_NIF_TERM type, ERL_NIF_TERM data,
+ unsigned char *md_value, const EVP_MD **mdp,
+ unsigned char **tbsp, size_t *tbslenp)
+{
+ int i;
+ const ERL_NIF_TERM *tpl_terms;
+ int tpl_arity;
+ ErlNifBinary tbs_bin;
+ EVP_MD_CTX *mdctx;
+ const EVP_MD *md = *mdp;
+ unsigned char *tbs = *tbsp;
+ size_t tbslen = *tbslenp;
+ unsigned int tbsleni;
+
+ if ((i = get_pkey_digest_type(env, algorithm, type, &md)) != PKEY_OK) {
+ return i;
+ }
+ if (enif_get_tuple(env, data, &tpl_arity, &tpl_terms)) {
+ if (tpl_arity != 2 || tpl_terms[0] != atom_digest
+ || !enif_inspect_binary(env, tpl_terms[1], &tbs_bin)
+ || (md != NULL && tbs_bin.size != EVP_MD_size(md))) {
+ return PKEY_BADARG;
+ }
+ /* We have a digest (= hashed text) in tbs_bin */
+ tbs = tbs_bin.data;
+ tbslen = tbs_bin.size;
+ } else if (md == NULL) {
+ if (!enif_inspect_binary(env, data, &tbs_bin)) {
+ return PKEY_BADARG;
+ }
+ /* md == NULL, that is no hashing because DigestType argument was atom_none */
+ tbs = tbs_bin.data;
+ tbslen = tbs_bin.size;
+ } else {
+ if (!enif_inspect_binary(env, data, &tbs_bin)) {
+ return PKEY_BADARG;
+ }
+ /* We have the cleartext in tbs_bin and the hash algo info in md */
+ tbs = md_value;
+ mdctx = EVP_MD_CTX_create();
+ if (!mdctx) {
+ return PKEY_BADARG;
+ }
+ /* Looks well, now hash the plain text into a digest according to md */
+ if (EVP_DigestInit_ex(mdctx, md, NULL) <= 0) {
+ EVP_MD_CTX_destroy(mdctx);
+ return PKEY_BADARG;
+ }
+ if (EVP_DigestUpdate(mdctx, tbs_bin.data, tbs_bin.size) <= 0) {
+ EVP_MD_CTX_destroy(mdctx);
+ return PKEY_BADARG;
+ }
+ if (EVP_DigestFinal_ex(mdctx, tbs, &tbsleni) <= 0) {
+ EVP_MD_CTX_destroy(mdctx);
+ return PKEY_BADARG;
+ }
+ tbslen = (size_t)(tbsleni);
+ EVP_MD_CTX_destroy(mdctx);
+ }
+
+ *mdp = md;
+ *tbsp = tbs;
+ *tbslenp = tbslen;
+
+ return PKEY_OK;
+}
+
+
+static int get_pkey_sign_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM options,
+ const EVP_MD *md, PKeySignOptions *opt)
+{
+ ERL_NIF_TERM head, tail;
+ const ERL_NIF_TERM *tpl_terms;
+ int tpl_arity;
+ const EVP_MD *opt_md;
+ int i;
+
+ if (!enif_is_list(env, options)) {
+ return PKEY_BADARG;
+ }
+
+ /* defaults */
+ if (algorithm == atom_rsa) {
+ opt->rsa_mgf1_md = NULL;
+ opt->rsa_padding = RSA_PKCS1_PADDING;
+ opt->rsa_pss_saltlen = -2;
+ }
+
+ if (enif_is_empty_list(env, options)) {
+ return PKEY_OK;
+ }
+
+ if (algorithm == atom_rsa) {
+ tail = options;
+ while (enif_get_list_cell(env, tail, &head, &tail)) {
+ if (enif_get_tuple(env, head, &tpl_arity, &tpl_terms) && tpl_arity == 2) {
+ if (tpl_terms[0] == atom_rsa_mgf1_md && enif_is_atom(env, tpl_terms[1])) {
+ i = get_pkey_digest_type(env, algorithm, tpl_terms[1], &opt_md);
+ if (i != PKEY_OK) {
+ return i;
+ }
+ opt->rsa_mgf1_md = opt_md;
+ } else if (tpl_terms[0] == atom_rsa_padding) {
+ if (tpl_terms[1] == atom_rsa_pkcs1_padding) {
+ opt->rsa_padding = RSA_PKCS1_PADDING;
+ } else if (tpl_terms[1] == atom_rsa_pkcs1_pss_padding) {
+#ifdef HAVE_RSA_PKCS1_PSS_PADDING
+ opt->rsa_padding = RSA_PKCS1_PSS_PADDING;
+ if (opt->rsa_mgf1_md == NULL) {
+ opt->rsa_mgf1_md = md;
+ }
+#else
+ return PKEY_NOTSUP;
+#endif
+ } else if (tpl_terms[1] == atom_rsa_x931_padding) {
+ opt->rsa_padding = RSA_X931_PADDING;
+ } else if (tpl_terms[1] == atom_rsa_no_padding) {
+ opt->rsa_padding = RSA_NO_PADDING;
+ } else {
+ return PKEY_BADARG;
+ }
+ } else if (tpl_terms[0] == atom_rsa_pss_saltlen) {
+ if (!enif_get_int(env, tpl_terms[1], &(opt->rsa_pss_saltlen))
+ || opt->rsa_pss_saltlen < -2) {
+ return PKEY_BADARG;
+ }
+ } else {
+ return PKEY_BADARG;
+ }
+ } else {
+ return PKEY_BADARG;
+ }
+ }
+ } else {
+ return PKEY_BADARG;
+ }
+
+ return PKEY_OK;
+}
+
+
+#ifdef HAS_ENGINE_SUPPORT
+static int get_engine_and_key_id(ErlNifEnv *env, ERL_NIF_TERM key, char ** id, ENGINE **e)
+{
+ ERL_NIF_TERM engine_res, key_id_term;
+ struct engine_ctx *ctx;
+ ErlNifBinary key_id_bin;
+
+ if (!enif_get_map_value(env, key, atom_engine, &engine_res) ||
+ !enif_get_resource(env, engine_res, engine_ctx_rtype, (void**)&ctx) ||
+ !enif_get_map_value(env, key, atom_key_id, &key_id_term) ||
+ !enif_inspect_binary(env, key_id_term, &key_id_bin)) {
+ return 0;
+ }
+ else {
+ *e = ctx->engine;
+ return zero_terminate(key_id_bin, id);
+ }
+}
+
+
+static char *get_key_password(ErlNifEnv *env, ERL_NIF_TERM key) {
+ ERL_NIF_TERM tmp_term;
+ ErlNifBinary pwd_bin;
+ char *pwd;
+ if (enif_get_map_value(env, key, atom_password, &tmp_term) &&
+ enif_inspect_binary(env, tmp_term, &pwd_bin) &&
+ zero_terminate(pwd_bin, &pwd)
+ ) return pwd;
+
+ return NULL;
+}
+
+static int zero_terminate(ErlNifBinary bin, char **buf) {
+ *buf = enif_alloc(bin.size+1);
+ if (!*buf)
+ return 0;
+ memcpy(*buf, bin.data, bin.size);
+ *(*buf+bin.size) = 0;
+ return 1;
+}
+#endif
+
+static int get_pkey_private_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM key, EVP_PKEY **pkey)
+{
+ if (enif_is_map(env, key)) {
+#ifdef HAS_ENGINE_SUPPORT
+ /* Use key stored in engine */
+ ENGINE *e;
+ char *id;
+ char *password;
+
+ if (!get_engine_and_key_id(env, key, &id, &e))
+ return PKEY_BADARG;
+ password = get_key_password(env, key);
+ *pkey = ENGINE_load_private_key(e, id, NULL, password);
+ if (!*pkey)
+ return PKEY_BADARG;
+ enif_free(id);
+#else
+ return PKEY_BADARG;
+#endif
+ }
+ else if (algorithm == atom_rsa) {
+ RSA *rsa = RSA_new();
+
+ if (!get_rsa_private_key(env, key, rsa)) {
+ RSA_free(rsa);
+ return PKEY_BADARG;
+ }
+
+ *pkey = EVP_PKEY_new();
+ if (!EVP_PKEY_assign_RSA(*pkey, rsa)) {
+ EVP_PKEY_free(*pkey);
+ RSA_free(rsa);
+ return PKEY_BADARG;
+ }
+ } else if (algorithm == atom_ecdsa) {
+#if defined(HAVE_EC)
+ EC_KEY *ec = NULL;
+ const ERL_NIF_TERM *tpl_terms;
+ int tpl_arity;
+
+ if (enif_get_tuple(env, key, &tpl_arity, &tpl_terms) && tpl_arity == 2
+ && enif_is_tuple(env, tpl_terms[0]) && enif_is_binary(env, tpl_terms[1])
+ && get_ec_key(env, tpl_terms[0], tpl_terms[1], atom_undefined, &ec)) {
+
+ *pkey = EVP_PKEY_new();
+ if (!EVP_PKEY_assign_EC_KEY(*pkey, ec)) {
+ EVP_PKEY_free(*pkey);
+ EC_KEY_free(ec);
+ return PKEY_BADARG;
+ }
+ } else {
+ return PKEY_BADARG;
+ }
+#else
+ return PKEY_NOTSUP;
+#endif
+ } else if (algorithm == atom_dss) {
+ DSA *dsa = DSA_new();
+
+ if (!get_dss_private_key(env, key, dsa)) {
+ DSA_free(dsa);
+ return PKEY_BADARG;
+ }
+
+ *pkey = EVP_PKEY_new();
+ if (!EVP_PKEY_assign_DSA(*pkey, dsa)) {
+ EVP_PKEY_free(*pkey);
+ DSA_free(dsa);
+ return PKEY_BADARG;
+ }
+ } else {
+ return PKEY_BADARG;
+ }
+
+ return PKEY_OK;
+}
+
+
+static int get_pkey_public_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM key,
+ EVP_PKEY **pkey)
+{
+ if (enif_is_map(env, key)) {
+#ifdef HAS_ENGINE_SUPPORT
+ /* Use key stored in engine */
+ ENGINE *e;
+ char *id;
+ char *password;
+
+ if (!get_engine_and_key_id(env, key, &id, &e))
+ return PKEY_BADARG;
+ password = get_key_password(env, key);
+ *pkey = ENGINE_load_public_key(e, id, NULL, password);
+ if (!pkey)
+ return PKEY_BADARG;
+ enif_free(id);
+#else
+ return PKEY_BADARG;
+#endif
+ } else if (algorithm == atom_rsa) {
+ RSA *rsa = RSA_new();
+
+ if (!get_rsa_public_key(env, key, rsa)) {
+ RSA_free(rsa);
+ return PKEY_BADARG;
+ }
+
+ *pkey = EVP_PKEY_new();
+ if (!EVP_PKEY_assign_RSA(*pkey, rsa)) {
+ EVP_PKEY_free(*pkey);
+ RSA_free(rsa);
+ return PKEY_BADARG;
+ }
+ } else if (algorithm == atom_ecdsa) {
+#if defined(HAVE_EC)
+ EC_KEY *ec = NULL;
+ const ERL_NIF_TERM *tpl_terms;
+ int tpl_arity;
+
+ if (enif_get_tuple(env, key, &tpl_arity, &tpl_terms) && tpl_arity == 2
+ && enif_is_tuple(env, tpl_terms[0]) && enif_is_binary(env, tpl_terms[1])
+ && get_ec_key(env, tpl_terms[0], atom_undefined, tpl_terms[1], &ec)) {
+
+ *pkey = EVP_PKEY_new();
+ if (!EVP_PKEY_assign_EC_KEY(*pkey, ec)) {
+ EVP_PKEY_free(*pkey);
+ EC_KEY_free(ec);
+ return PKEY_BADARG;
+ }
+ } else {
+ return PKEY_BADARG;
+ }
+#else
+ return PKEY_NOTSUP;
+#endif
+ } else if (algorithm == atom_dss) {
+ DSA *dsa = DSA_new();
+
+ if (!get_dss_public_key(env, key, dsa)) {
+ DSA_free(dsa);
+ return PKEY_BADARG;
+ }
+
+ *pkey = EVP_PKEY_new();
+ if (!EVP_PKEY_assign_DSA(*pkey, dsa)) {
+ EVP_PKEY_free(*pkey);
+ DSA_free(dsa);
+ return PKEY_BADARG;
+ }
+ } else {
+ return PKEY_BADARG;
+ }
+
+ return PKEY_OK;
+}
+
+static ERL_NIF_TERM pkey_sign_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
+{/* (Algorithm, Type, Data|{digest,Digest}, Key|#{}, Options) */
+ int i;
+ const EVP_MD *md = NULL;
+ unsigned char md_value[EVP_MAX_MD_SIZE];
+ EVP_PKEY *pkey;
+#ifdef HAS_EVP_PKEY_CTX
+ EVP_PKEY_CTX *ctx;
+ size_t siglen;
+#else
+ unsigned len, siglen;
+#endif
+ PKeySignOptions sig_opt;
+ ErlNifBinary sig_bin; /* signature */
+ unsigned char *tbs; /* data to be signed */
+ size_t tbslen;
+/*char buf[1024];
+enif_get_atom(env,argv[0],buf,1024,ERL_NIF_LATIN1); printf("algo=%s ",buf);
+enif_get_atom(env,argv[1],buf,1024,ERL_NIF_LATIN1); printf("hash=%s ",buf);
+printf("\r\n");
+*/
+
+#ifndef HAS_ENGINE_SUPPORT
+ if (enif_is_map(env, argv[3])) {
+ return atom_notsup;
+ }
+#endif
+
+ i = get_pkey_sign_digest(env, argv[0], argv[1], argv[2], md_value, &md, &tbs, &tbslen);
+ if (i != PKEY_OK) {
+ if (i == PKEY_NOTSUP)
+ return atom_notsup;
+ else
+ return enif_make_badarg(env);
+ }
+
+ i = get_pkey_sign_options(env, argv[0], argv[4], md, &sig_opt);
+ if (i != PKEY_OK) {
+ if (i == PKEY_NOTSUP)
+ return atom_notsup;
+ else
+ return enif_make_badarg(env);
+ }
+
+ if (get_pkey_private_key(env, argv[0], argv[3], &pkey) != PKEY_OK) {
+ return enif_make_badarg(env);
+ }
+
+#ifdef HAS_EVP_PKEY_CTX
+ ctx = EVP_PKEY_CTX_new(pkey, NULL);
+ if (!ctx) goto badarg;
+
+ if (EVP_PKEY_sign_init(ctx) <= 0) goto badarg;
+ if (md != NULL && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) goto badarg;
+
+ if (argv[0] == atom_rsa) {
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, sig_opt.rsa_padding) <= 0) goto badarg;
+#ifdef HAVE_RSA_PKCS1_PSS_PADDING
+ if (sig_opt.rsa_padding == RSA_PKCS1_PSS_PADDING) {
+ if (sig_opt.rsa_mgf1_md != NULL) {
+#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,1)
+ if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sig_opt.rsa_mgf1_md) <= 0) goto badarg;
+#else
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
+ return atom_notsup;
+#endif
+ }
+ if (sig_opt.rsa_pss_saltlen > -2
+ && EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, sig_opt.rsa_pss_saltlen) <= 0)
+ goto badarg;
+ }
+#endif
+ }
+
+ if (EVP_PKEY_sign(ctx, NULL, &siglen, tbs, tbslen) <= 0) goto badarg;
+ enif_alloc_binary(siglen, &sig_bin);
+
+ if (md != NULL) {
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, EVP_MD_size(md));
+ }
+ i = EVP_PKEY_sign(ctx, sig_bin.data, &siglen, tbs, tbslen);
+
+ EVP_PKEY_CTX_free(ctx);
+#else
+/*printf("Old interface\r\n");
+ */
+ if (argv[0] == atom_rsa) {
+ RSA *rsa = EVP_PKEY_get1_RSA(pkey);
+ enif_alloc_binary(RSA_size(rsa), &sig_bin);
+ len = EVP_MD_size(md);
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, len);
+ i = RSA_sign(md->type, tbs, len, sig_bin.data, &siglen, rsa);
+ RSA_free(rsa);
+ } else if (argv[0] == atom_dss) {
+ DSA *dsa = EVP_PKEY_get1_DSA(pkey);
+ enif_alloc_binary(DSA_size(dsa), &sig_bin);
+ len = EVP_MD_size(md);
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, len);
+ i = DSA_sign(md->type, tbs, len, sig_bin.data, &siglen, dsa);
+ DSA_free(dsa);
+ } else if (argv[0] == atom_ecdsa) {
+#if defined(HAVE_EC)
+ EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pkey);
+ enif_alloc_binary(ECDSA_size(ec), &sig_bin);
+ len = EVP_MD_size(md);
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, len);
+ i = ECDSA_sign(md->type, tbs, len, sig_bin.data, &siglen, ec);
+ EC_KEY_free(ec);
+#else
+ EVP_PKEY_free(pkey);
+ return atom_notsup;
+#endif
+ } else {
+ goto badarg;
+ }
+#endif
+
+ EVP_PKEY_free(pkey);
+ if (i == 1) {
+ ERL_VALGRIND_MAKE_MEM_DEFINED(sig_bin.data, siglen);
+ if (siglen != sig_bin.size) {
+ enif_realloc_binary(&sig_bin, siglen);
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(sig_bin.data, siglen);
+ }
+ return enif_make_binary(env, &sig_bin);
+ } else {
+ enif_release_binary(&sig_bin);
+ return atom_error;
+ }
+
+ badarg:
+#ifdef HAS_EVP_PKEY_CTX
+ EVP_PKEY_CTX_free(ctx);
+#endif
+ EVP_PKEY_free(pkey);
+ return enif_make_badarg(env);
+}
+
+
+static ERL_NIF_TERM pkey_verify_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
+{/* (Algorithm, Type, Data|{digest,Digest}, Signature, Key, Options) */
+ int i;
+ const EVP_MD *md = NULL;
+ unsigned char md_value[EVP_MAX_MD_SIZE];
+ EVP_PKEY *pkey;
+#ifdef HAS_EVP_PKEY_CTX
+ EVP_PKEY_CTX *ctx;
+#else
+#endif
+ PKeySignOptions sig_opt;
+ ErlNifBinary sig_bin; /* signature */
+ unsigned char *tbs; /* data to be signed */
+ size_t tbslen;
+
+#ifndef HAS_ENGINE_SUPPORT
+ if (enif_is_map(env, argv[4])) {
+ return atom_notsup;
+ }
+#endif
+
+ if (!enif_inspect_binary(env, argv[3], &sig_bin)) {
+ return enif_make_badarg(env);
+ }
+
+ i = get_pkey_sign_digest(env, argv[0], argv[1], argv[2], md_value, &md, &tbs, &tbslen);
+ if (i != PKEY_OK) {
+ if (i == PKEY_NOTSUP)
+ return atom_notsup;
+ else
+ return enif_make_badarg(env);
+ }
+
+ i = get_pkey_sign_options(env, argv[0], argv[5], md, &sig_opt);
+ if (i != PKEY_OK) {
+ if (i == PKEY_NOTSUP)
+ return atom_notsup;
+ else
+ return enif_make_badarg(env);
+ }
+
+ if (get_pkey_public_key(env, argv[0], argv[4], &pkey) != PKEY_OK) {
+ return enif_make_badarg(env);
+ }
+
+#ifdef HAS_EVP_PKEY_CTX
+/* printf("EVP interface\r\n");
+ */
+ ctx = EVP_PKEY_CTX_new(pkey, NULL);
+ if (!ctx) goto badarg;
+ if (EVP_PKEY_verify_init(ctx) <= 0) goto badarg;
+ if (md != NULL && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) goto badarg;
+
+ if (argv[0] == atom_rsa) {
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, sig_opt.rsa_padding) <= 0) goto badarg;
+ if (sig_opt.rsa_padding == RSA_PKCS1_PSS_PADDING) {
+ if (sig_opt.rsa_mgf1_md != NULL) {
+#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,1)
+ if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sig_opt.rsa_mgf1_md) <= 0) goto badarg;
+#else
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
+ return atom_notsup;
+#endif
+ }
+ if (sig_opt.rsa_pss_saltlen > -2
+ && EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, sig_opt.rsa_pss_saltlen) <= 0)
+ goto badarg;
+ }
+ }
+
+ if (md != NULL) {
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, EVP_MD_size(md));
+ }
+ i = EVP_PKEY_verify(ctx, sig_bin.data, sig_bin.size, tbs, tbslen);
+
+ EVP_PKEY_CTX_free(ctx);
+#else
+/*printf("Old interface\r\n");
+*/
+ if (argv[0] == atom_rsa) {
+ RSA *rsa = EVP_PKEY_get1_RSA(pkey);
+ i = RSA_verify(md->type, tbs, tbslen, sig_bin.data, sig_bin.size, rsa);
+ RSA_free(rsa);
+ } else if (argv[0] == atom_dss) {
+ DSA *dsa = EVP_PKEY_get1_DSA(pkey);
+ i = DSA_verify(0, tbs, tbslen, sig_bin.data, sig_bin.size, dsa);
+ DSA_free(dsa);
+ } else if (argv[0] == atom_ecdsa) {
+#if defined(HAVE_EC)
+ EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pkey);
+ i = ECDSA_verify(EVP_MD_type(md), tbs, tbslen, sig_bin.data, sig_bin.size, ec);
+ EC_KEY_free(ec);
+#else
+ EVP_PKEY_free(pkey);
+ return atom_notsup;
+#endif
+ } else {
+ goto badarg;
+ }
+#endif
+
+ EVP_PKEY_free(pkey);
+ if (i == 1) {
+ return atom_true;
+ } else {
+ return atom_false;
+ }
+
+ badarg:
+#ifdef HAS_EVP_PKEY_CTX
+ EVP_PKEY_CTX_free(ctx);
+#endif
+ EVP_PKEY_free(pkey);
+ return enif_make_badarg(env);
+}
+
+
+/*--------------------------------*/
+
+static int get_pkey_crypt_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM options,
+ PKeyCryptOptions *opt)
+{
+ ERL_NIF_TERM head, tail;
+ const ERL_NIF_TERM *tpl_terms;
+ int tpl_arity;
+ const EVP_MD *opt_md;
+ int i;
+
+ if (!enif_is_list(env, options)) {
+ return PKEY_BADARG;
+ }
+
+ /* defaults */
+ if (algorithm == atom_rsa) {
+ opt->rsa_mgf1_md = NULL;
+ opt->rsa_oaep_label.data = NULL;
+ opt->rsa_oaep_label.size = 0;
+ opt->rsa_oaep_md = NULL;
+ opt->rsa_padding = RSA_PKCS1_PADDING;
+ opt->signature_md = NULL;
+ }
+
+ if (enif_is_empty_list(env, options)) {
+ return PKEY_OK;
+ }
+
+ if (algorithm == atom_rsa) {
+ tail = options;
+ while (enif_get_list_cell(env, tail, &head, &tail)) {
+ if (enif_get_tuple(env, head, &tpl_arity, &tpl_terms) && tpl_arity == 2) {
+ if (tpl_terms[0] == atom_rsa_padding
+ || tpl_terms[0] == atom_rsa_pad /* Compatibility */
+ ) {
+ if (tpl_terms[1] == atom_rsa_pkcs1_padding) {
+ opt->rsa_padding = RSA_PKCS1_PADDING;
+ } else if (tpl_terms[1] == atom_rsa_pkcs1_oaep_padding) {
+ opt->rsa_padding = RSA_PKCS1_OAEP_PADDING;
+#ifdef HAVE_RSA_SSLV23_PADDING
+ } else if (tpl_terms[1] == atom_rsa_sslv23_padding) {
+ opt->rsa_padding = RSA_SSLV23_PADDING;
+#endif
+ } else if (tpl_terms[1] == atom_rsa_x931_padding) {
+ opt->rsa_padding = RSA_X931_PADDING;
+ } else if (tpl_terms[1] == atom_rsa_no_padding) {
+ opt->rsa_padding = RSA_NO_PADDING;
+ } else {
+ return PKEY_BADARG;
+ }
+ } else if (tpl_terms[0] == atom_signature_md && enif_is_atom(env, tpl_terms[1])) {
+ i = get_pkey_digest_type(env, algorithm, tpl_terms[1], &opt_md);
+ if (i != PKEY_OK) {
+ return i;
+ }
+ opt->signature_md = opt_md;
+ } else if (tpl_terms[0] == atom_rsa_mgf1_md && enif_is_atom(env, tpl_terms[1])) {
+#ifndef HAVE_RSA_OAEP_MD
+ if (tpl_terms[1] != atom_sha)
+ return PKEY_NOTSUP;
+#endif
+ i = get_pkey_digest_type(env, algorithm, tpl_terms[1], &opt_md);
+ if (i != PKEY_OK) {
+ return i;
+ }
+ opt->rsa_mgf1_md = opt_md;
+ } else if (tpl_terms[0] == atom_rsa_oaep_label
+ && enif_inspect_binary(env, tpl_terms[1], &(opt->rsa_oaep_label))) {
+#ifdef HAVE_RSA_OAEP_MD
+ continue;
+#else
+ return PKEY_NOTSUP;
+#endif
+ } else if (tpl_terms[0] == atom_rsa_oaep_md && enif_is_atom(env, tpl_terms[1])) {
+#ifndef HAVE_RSA_OAEP_MD
+ if (tpl_terms[1] != atom_sha)
+ return PKEY_NOTSUP;
+#endif
+ i = get_pkey_digest_type(env, algorithm, tpl_terms[1], &opt_md);
+ if (i != PKEY_OK) {
+ return i;
+ }
+ opt->rsa_oaep_md = opt_md;
+ } else {
+ return PKEY_BADARG;
+ }
+ } else {
+ return PKEY_BADARG;
+ }
+ }
+ } else {
+ return PKEY_BADARG;
+ }
+
+ return PKEY_OK;
+}
+
+static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
+{/* (Algorithm, Data, PublKey=[E,N]|[E,N,D]|[E,N,D,P1,P2,E1,E2,C], Options, IsPrivate, IsEncrypt) */
+ int i;
+ EVP_PKEY *pkey;
+#ifdef HAS_EVP_PKEY_CTX
+ EVP_PKEY_CTX *ctx;
+#else
+ RSA *rsa;
+#endif
+ PKeyCryptOptions crypt_opt;
+ ErlNifBinary in_bin, out_bin, tmp_bin;
+ size_t outlen;
+#ifdef HAVE_RSA_SSLV23_PADDING
+ size_t tmplen;
+#endif
+ int is_private = (argv[4] == atom_true),
+ is_encrypt = (argv[5] == atom_true);
+ int algo_init = 0;
+
+/* char algo[1024]; */
+
+#ifndef HAS_ENGINE_SUPPORT
+ if (enif_is_map(env, argv[2])) {
+ return atom_notsup;
+ }
+#endif
+
+ if (!enif_inspect_binary(env, argv[1], &in_bin)) {
+ return enif_make_badarg(env);
+ }
+
+ i = get_pkey_crypt_options(env, argv[0], argv[3], &crypt_opt);
+ if (i != PKEY_OK) {
+ if (i == PKEY_NOTSUP)
+ return atom_notsup;
+ else
+ return enif_make_badarg(env);
+ }
+
+ if (is_private) {
+ if (get_pkey_private_key(env, argv[0], argv[2], &pkey) != PKEY_OK) {
+ return enif_make_badarg(env);
+ }
+ } else {
+ if (get_pkey_public_key(env, argv[0], argv[2], &pkey) != PKEY_OK) {
+ return enif_make_badarg(env);
+ }
+ }
+
+ out_bin.data = NULL;
+ out_bin.size = 0;
+ tmp_bin.data = NULL;
+ tmp_bin.size = 0;
+
+#ifdef HAS_EVP_PKEY_CTX
+ ctx = EVP_PKEY_CTX_new(pkey, NULL);
+ if (!ctx) goto badarg;
+
+/* enif_get_atom(env,argv[0],algo,1024,ERL_NIF_LATIN1); */
+
+ if (is_private) {
+ if (is_encrypt) {
+ /* private encrypt */
+ if ((algo_init=EVP_PKEY_sign_init(ctx)) <= 0) {
+ /* fprintf(stderr,"BADARG %s private encrypt algo_init=%d %s:%d\r\n", algo, algo_init, __FILE__, __LINE__); */
+ goto badarg;
+ }
+ } else {
+ /* private decrypt */
+ if ((algo_init=EVP_PKEY_decrypt_init(ctx)) <= 0) {
+ /* fprintf(stderr,"BADARG %s private decrypt algo_init=%d %s:%d\r\n", algo, algo_init, __FILE__, __LINE__); */
+ goto badarg;
+ }
+ }
+ } else {
+ if (is_encrypt) {
+ /* public encrypt */
+ if ((algo_init=EVP_PKEY_encrypt_init(ctx)) <= 0) {
+ /* fprintf(stderr,"BADARG %s public encrypt algo_init=%d %s:%d\r\n", algo,algo_init,__FILE__, __LINE__); */
+ goto badarg;
+ }
+ } else {
+ /* public decrypt */
+ if ((algo_init=EVP_PKEY_verify_recover_init(ctx)) <= 0) {
+ /* fprintf(stderr,"BADARG %s public decrypt algo_init=%d %s:%d\r\n", algo,algo_init,__FILE__, __LINE__); */
+ goto badarg;
+ }
+ }
+ }
+
+ if (argv[0] == atom_rsa) {
+ if (crypt_opt.signature_md != NULL
+ && EVP_PKEY_CTX_set_signature_md(ctx, crypt_opt.signature_md) <= 0)
+ goto badarg;
+#ifdef HAVE_RSA_SSLV23_PADDING
+ if (crypt_opt.rsa_padding == RSA_SSLV23_PADDING) {
+ if (is_encrypt) {
+ RSA *rsa = EVP_PKEY_get1_RSA(pkey);
+ if (rsa == NULL) goto badarg;
+ tmplen = RSA_size(rsa);
+ if (!enif_alloc_binary(tmplen, &tmp_bin)) goto badarg;
+ if (RSA_padding_add_SSLv23(tmp_bin.data, tmplen, in_bin.data, in_bin.size) <= 0)
+ goto badarg;
+ in_bin = tmp_bin;
+ }
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) <= 0) goto badarg;
+ } else
+#endif
+ {
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, crypt_opt.rsa_padding) <= 0) goto badarg;
+ }
+#ifdef HAVE_RSA_OAEP_MD
+ if (crypt_opt.rsa_padding == RSA_PKCS1_OAEP_PADDING) {
+ if (crypt_opt.rsa_oaep_md != NULL
+ && EVP_PKEY_CTX_set_rsa_oaep_md(ctx, crypt_opt.rsa_oaep_md) <= 0)
+ goto badarg;
+ if (crypt_opt.rsa_mgf1_md != NULL
+ && EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, crypt_opt.rsa_mgf1_md) <= 0) goto badarg;
+ if (crypt_opt.rsa_oaep_label.data != NULL && crypt_opt.rsa_oaep_label.size > 0) {
+ unsigned char *label_copy;
+ label_copy = OPENSSL_malloc(crypt_opt.rsa_oaep_label.size);
+ if (label_copy == NULL) goto badarg;
+ memcpy((void *)(label_copy), (const void *)(crypt_opt.rsa_oaep_label.data),
+ crypt_opt.rsa_oaep_label.size);
+ if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label_copy,
+ crypt_opt.rsa_oaep_label.size) <= 0) {
+ OPENSSL_free(label_copy);
+ label_copy = NULL;
+ goto badarg;
+ }
+ }
+ }
+#endif
+ }
+
+ if (is_private) {
+ if (is_encrypt) {
+ /* private_encrypt */
+ i = EVP_PKEY_sign(ctx, NULL, &outlen, in_bin.data, in_bin.size);
+ } else {
+ /* private_decrypt */
+ i = EVP_PKEY_decrypt(ctx, NULL, &outlen, in_bin.data, in_bin.size);
+ }
+ } else {
+ if (is_encrypt) {
+ /* public_encrypt */
+ i = EVP_PKEY_encrypt(ctx, NULL, &outlen, in_bin.data, in_bin.size);
+ } else {
+ /* public_decrypt */
+ i = EVP_PKEY_verify_recover(ctx, NULL, &outlen, in_bin.data, in_bin.size);
+ }
+ }
+ /* fprintf(stderr,"i = %d %s:%d\r\n", i, __FILE__, __LINE__); */
+
+ if (i != 1) goto badarg;
+
+ enif_alloc_binary(outlen, &out_bin);
+
+ if (is_private) {
+ if (is_encrypt) {
+ /* private_encrypt */
+ i = EVP_PKEY_sign(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size);
+ } else {
+ /* private_decrypt */
+ i = EVP_PKEY_decrypt(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size);
+ }
+ } else {
+ if (is_encrypt) {
+ /* public_encrypt */
+ i = EVP_PKEY_encrypt(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size);
+ } else {
+ /* public_decrypt */
+ i = EVP_PKEY_verify_recover(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size);
+ }
+ }
+
+#else
+ /* Non-EVP cryptolib. Only support RSA */
+
+ if (argv[0] != atom_rsa) {
+ algo_init = -2; /* exitcode: notsup */
+ goto badarg;
+ }
+ rsa = EVP_PKEY_get1_RSA(pkey);
+ enif_alloc_binary(RSA_size(rsa), &out_bin);
+
+ if (is_private) {
+ if (is_encrypt) {
+ /* non-evp rsa private encrypt */
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(in_bin.data,in_bin.size);
+ i = RSA_private_encrypt(in_bin.size, in_bin.data,
+ out_bin.data, rsa, crypt_opt.rsa_padding);
+ if (i > 0) {
+ ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, i);
+ }
+ } else {
+ /* non-evp rsa private decrypt */
+ i = RSA_private_decrypt(in_bin.size, in_bin.data,
+ out_bin.data, rsa, crypt_opt.rsa_padding);
+ if (i > 0) {
+ ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, i);
+ enif_realloc_binary(&out_bin, i);
+ }
+ }
+ } else {
+ if (is_encrypt) {
+ /* non-evp rsa public encrypt */
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(in_bin.data,in_bin.size);
+ i = RSA_public_encrypt(in_bin.size, in_bin.data,
+ out_bin.data, rsa, crypt_opt.rsa_padding);
+ if (i > 0) {
+ ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, i);
+ }
+ } else {
+ /* non-evp rsa public decrypt */
+ i = RSA_public_decrypt(in_bin.size, in_bin.data,
+ out_bin.data, rsa, crypt_opt.rsa_padding);
+ if (i > 0) {
+ ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, i);
+ enif_realloc_binary(&out_bin, i);
+ }
+ }
+ }
+
+ outlen = i;
+ RSA_free(rsa);
+#endif
+
+ if ((i > 0) && argv[0] == atom_rsa && !is_encrypt) {
+#ifdef HAVE_RSA_SSLV23_PADDING
+ if (crypt_opt.rsa_padding == RSA_SSLV23_PADDING) {
+ RSA *rsa = EVP_PKEY_get1_RSA(pkey);
+ unsigned char *p;
+ if (rsa == NULL) goto badarg;
+ tmplen = RSA_size(rsa);
+ if (!enif_alloc_binary(tmplen, &tmp_bin)) {
+ RSA_free(rsa);
+ goto badarg;
+ }
+ p = out_bin.data;
+ p++;
+ i = RSA_padding_check_SSLv23(tmp_bin.data, tmplen, p, out_bin.size - 1, tmplen);
+ if (i >= 0) {
+ outlen = i;
+ in_bin = out_bin;
+ out_bin = tmp_bin;
+ tmp_bin = in_bin;
+ i = 1;
+ }
+ RSA_free(rsa);
+ }
+#endif
+ }
+
+ if (tmp_bin.data != NULL) {
+ enif_release_binary(&tmp_bin);
+ }
+
+#ifdef HAS_EVP_PKEY_CTX
+ EVP_PKEY_CTX_free(ctx);
+#else
+#endif
+ EVP_PKEY_free(pkey);
+ if (i > 0) {
+ ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, outlen);
+ if (outlen != out_bin.size) {
+ enif_realloc_binary(&out_bin, outlen);
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(out_bin.data, outlen);
+ }
+ return enif_make_binary(env, &out_bin);
+ } else {
+ enif_release_binary(&out_bin);
+ return atom_error;
+ }
+
+ badarg:
+ if (out_bin.data != NULL) {
+ enif_release_binary(&out_bin);
+ }
+ if (tmp_bin.data != NULL) {
+ enif_release_binary(&tmp_bin);
+ }
+#ifdef HAS_EVP_PKEY_CTX
+ EVP_PKEY_CTX_free(ctx);
+#else
+#endif
+ EVP_PKEY_free(pkey);
+ if (algo_init == -2)
+ return atom_notsup;
+ else
+ return enif_make_badarg(env);
+}
+
+
+
+/*--------------------------------*/
+static ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{ /* (Algorithm, PrivKey | KeyMap) */
+ EVP_PKEY *pkey;
+ ERL_NIF_TERM alg = argv[0];
+ ERL_NIF_TERM result[8];
+ if (get_pkey_private_key(env, alg, argv[1], &pkey) != PKEY_OK) {
+ return enif_make_badarg(env);
+ }
+
+ if (alg == atom_rsa) {
+ const BIGNUM *n = NULL, *e = NULL, *d = NULL;
+ RSA *rsa = EVP_PKEY_get1_RSA(pkey);
+ if (rsa) {
+ RSA_get0_key(rsa, &n, &e, &d);
+ result[0] = bin_from_bn(env, e); // Exponent E
+ result[1] = bin_from_bn(env, n); // Modulus N = p*q
+ EVP_PKEY_free(pkey);
+ return enif_make_list_from_array(env, result, 2);
+ }
+
+ } else if (argv[0] == atom_dss) {
+ const BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL;
+ DSA *dsa = EVP_PKEY_get1_DSA(pkey);
+ if (dsa) {
+ DSA_get0_pqg(dsa, &p, &q, &g);
+ DSA_get0_key(dsa, &pub_key, NULL);
+ result[0] = bin_from_bn(env, p);
+ result[1] = bin_from_bn(env, q);
+ result[2] = bin_from_bn(env, g);
+ result[3] = bin_from_bn(env, pub_key);
+ EVP_PKEY_free(pkey);
+ return enif_make_list_from_array(env, result, 4);
+ }
+
+ } else if (argv[0] == atom_ecdsa) {
+#if defined(HAVE_EC)
+ /* not yet implemented
+ EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pkey);
+ if (ec) {
+ / * Example of result:
+ {
+ Curve = {Field, Prime, Point, Order, CoFactor} =
+ {
+ Field = {prime_field,<<255,...,255>>},
+ Prime = {<<255,...,252>>,
+ <<90,...,75>>,
+ <<196,...,144>>
+ },
+ Point = <<4,...,245>>,
+ Order = <<255,...,81>>,
+ CoFactor = <<1>>
+ },
+ Key = <<151,...,62>>
+ }
+ or
+ {
+ Curve =
+ {characteristic_two_field,
+ M,
+ Basis = {tpbasis, _}
+ | {ppbasis, k1, k2, k3}
+ },
+ Key
+ }
+ * /
+ EVP_PKEY_free(pkey);
+ return enif_make_list_from_array(env, ..., ...);
+ */
+#endif
+ }
+
+ if (pkey) EVP_PKEY_free(pkey);
+ return enif_make_badarg(env);
+}
+
+/*================================================================*/
+
static ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary seed_bin;
@@ -3948,3 +5374,630 @@ static ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
RAND_seed(seed_bin.data,seed_bin.size);
return atom_ok;
}
+
+/*================================================================*/
+/* Engine */
+/*================================================================*/
+static ERL_NIF_TERM engine_by_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (EngineId) */
+#ifdef HAS_ENGINE_SUPPORT
+ ERL_NIF_TERM ret;
+ ErlNifBinary engine_id_bin;
+ char *engine_id;
+ ENGINE *engine;
+ struct engine_ctx *ctx;
+
+ // Get Engine Id
+ if(!enif_inspect_binary(env, argv[0], &engine_id_bin)) {
+ PRINTF_ERR0("engine_by_id_nif Leaved: badarg");
+ return enif_make_badarg(env);
+ } else {
+ engine_id = enif_alloc(engine_id_bin.size+1);
+ (void) memcpy(engine_id, engine_id_bin.data, engine_id_bin.size);
+ engine_id[engine_id_bin.size] = '\0';
+ }
+
+ engine = ENGINE_by_id(engine_id);
+ if(!engine) {
+ enif_free(engine_id);
+ PRINTF_ERR0("engine_by_id_nif Leaved: {error, bad_engine_id}");
+ return enif_make_tuple2(env, atom_error, atom_bad_engine_id);
+ }
+
+ ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx));
+ ctx->engine = engine;
+ ctx->id = engine_id;
+
+ ret = enif_make_resource(env, ctx);
+ enif_release_resource(ctx);
+
+ return enif_make_tuple2(env, atom_ok, ret);
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM engine_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ ERL_NIF_TERM ret = atom_ok;
+ struct engine_ctx *ctx;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_init_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+ if (!ENGINE_init(ctx->engine)) {
+ //ERR_print_errors_fp(stderr);
+ PRINTF_ERR0("engine_init_nif Leaved: {error, engine_init_failed}");
+ return enif_make_tuple2(env, atom_error, atom_engine_init_failed);
+ }
+
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM engine_free_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ struct engine_ctx *ctx;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_free_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+
+ ENGINE_free(ctx->engine);
+ return atom_ok;
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM engine_finish_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ struct engine_ctx *ctx;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_finish_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+
+ ENGINE_finish(ctx->engine);
+ return atom_ok;
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM engine_load_dynamic_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* () */
+#ifdef HAS_ENGINE_SUPPORT
+ ENGINE_load_dynamic();
+ return atom_ok;
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM engine_ctrl_cmd_strings_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine, Commands) */
+#ifdef HAS_ENGINE_SUPPORT
+ ERL_NIF_TERM ret = atom_ok;
+ unsigned int cmds_len = 0;
+ char **cmds = NULL;
+ struct engine_ctx *ctx;
+ int i, optional = 0;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_ctrl_cmd_strings_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+
+ PRINTF_ERR1("Engine Id: %s\r\n", ENGINE_get_id(ctx->engine));
+
+ // Get Command List
+ if(!enif_get_list_length(env, argv[1], &cmds_len)) {
+ PRINTF_ERR0("engine_ctrl_cmd_strings_nif Leaved: Bad Command List");
+ return enif_make_badarg(env);
+ } else {
+ cmds_len *= 2; // Key-Value list from erlang
+ cmds = enif_alloc((cmds_len+1)*sizeof(char*));
+ if(get_engine_load_cmd_list(env, argv[1], cmds, 0)) {
+ PRINTF_ERR0("engine_ctrl_cmd_strings_nif Leaved: Couldn't read Command List");
+ ret = enif_make_badarg(env);
+ goto error;
+ }
+ }
+
+ if(!enif_get_int(env, argv[2], &optional)) {
+ PRINTF_ERR0("engine_ctrl_cmd_strings_nif Leaved: Parameter optional not an integer");
+ return enif_make_badarg(env);
+ }
+
+ for(i = 0; i < cmds_len; i+=2) {
+ PRINTF_ERR2("Cmd: %s:%s\r\n",
+ cmds[i] ? cmds[i] : "(NULL)",
+ cmds[i+1] ? cmds[i+1] : "(NULL)");
+ if(!ENGINE_ctrl_cmd_string(ctx->engine, cmds[i], cmds[i+1], optional)) {
+ PRINTF_ERR2("Command failed: %s:%s\r\n",
+ cmds[i] ? cmds[i] : "(NULL)",
+ cmds[i+1] ? cmds[i+1] : "(NULL)");
+ //ENGINE_free(ctx->engine);
+ ret = enif_make_tuple2(env, atom_error, atom_ctrl_cmd_failed);
+ PRINTF_ERR0("engine_ctrl_cmd_strings_nif Leaved: {error, ctrl_cmd_failed}");
+ goto error;
+ }
+ }
+
+ error:
+ for(i = 0; cmds != NULL && cmds[i] != NULL; i++)
+ enif_free(cmds[i]);
+ enif_free(cmds);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM engine_add_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ struct engine_ctx *ctx;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_add_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+
+ if (!ENGINE_add(ctx->engine)) {
+ PRINTF_ERR0("engine_add_nif Leaved: {error, add_engine_failed}");
+ return enif_make_tuple2(env, atom_error, atom_add_engine_failed);
+ }
+ return atom_ok;
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM engine_remove_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ struct engine_ctx *ctx;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_remove_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+
+ if (!ENGINE_remove(ctx->engine)) {
+ PRINTF_ERR0("engine_remove_nif Leaved: {error, remove_engine_failed}");
+ return enif_make_tuple2(env, atom_error, atom_remove_engine_failed);
+ }
+ return atom_ok;
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM engine_register_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine, EngineMethod) */
+#ifdef HAS_ENGINE_SUPPORT
+ struct engine_ctx *ctx;
+ unsigned int method;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_register_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+ // Get Method
+ if (!enif_get_uint(env, argv[1], &method)) {
+ PRINTF_ERR0("engine_register_nif Leaved: Parameter Method not an uint");
+ return enif_make_badarg(env);
+ }
+
+ switch(method)
+ {
+#ifdef ENGINE_METHOD_RSA
+ case ENGINE_METHOD_RSA:
+ if (!ENGINE_register_RSA(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_DSA
+ case ENGINE_METHOD_DSA:
+ if (!ENGINE_register_DSA(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_DH
+ case ENGINE_METHOD_DH:
+ if (!ENGINE_register_DH(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_RAND
+ case ENGINE_METHOD_RAND:
+ if (!ENGINE_register_RAND(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_ECDH
+ case ENGINE_METHOD_ECDH:
+ if (!ENGINE_register_ECDH(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_ECDSA
+ case ENGINE_METHOD_ECDSA:
+ if (!ENGINE_register_ECDSA(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_STORE
+ case ENGINE_METHOD_STORE:
+ if (!ENGINE_register_STORE(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_CIPHERS
+ case ENGINE_METHOD_CIPHERS:
+ if (!ENGINE_register_ciphers(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_DIGESTS
+ case ENGINE_METHOD_DIGESTS:
+ if (!ENGINE_register_digests(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_PKEY_METHS
+ case ENGINE_METHOD_PKEY_METHS:
+ if (!ENGINE_register_pkey_meths(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_PKEY_ASN1_METHS
+ case ENGINE_METHOD_PKEY_ASN1_METHS:
+ if (!ENGINE_register_pkey_asn1_meths(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+#ifdef ENGINE_METHOD_EC
+ case ENGINE_METHOD_EC:
+ if (!ENGINE_register_EC(ctx->engine))
+ return enif_make_tuple2(env, atom_error, atom_register_engine_failed);
+ break;
+#endif
+ default:
+ return enif_make_tuple2(env, atom_error, atom_engine_method_not_supported);
+ break;
+ }
+ return atom_ok;
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM engine_unregister_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine, EngineMethod) */
+#ifdef HAS_ENGINE_SUPPORT
+ struct engine_ctx *ctx;
+ unsigned int method;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_unregister_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+ // Get Method
+ if (!enif_get_uint(env, argv[1], &method)) {
+ PRINTF_ERR0("engine_unregister_nif Leaved: Parameter Method not an uint");
+ return enif_make_badarg(env);
+ }
+
+ switch(method)
+ {
+#ifdef ENGINE_METHOD_RSA
+ case ENGINE_METHOD_RSA:
+ ENGINE_unregister_RSA(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_DSA
+ case ENGINE_METHOD_DSA:
+ ENGINE_unregister_DSA(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_DH
+ case ENGINE_METHOD_DH:
+ ENGINE_unregister_DH(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_RAND
+ case ENGINE_METHOD_RAND:
+ ENGINE_unregister_RAND(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_ECDH
+ case ENGINE_METHOD_ECDH:
+ ENGINE_unregister_ECDH(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_ECDSA
+ case ENGINE_METHOD_ECDSA:
+ ENGINE_unregister_ECDSA(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_STORE
+ case ENGINE_METHOD_STORE:
+ ENGINE_unregister_STORE(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_CIPHERS
+ case ENGINE_METHOD_CIPHERS:
+ ENGINE_unregister_ciphers(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_DIGESTS
+ case ENGINE_METHOD_DIGESTS:
+ ENGINE_unregister_digests(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_PKEY_METHS
+ case ENGINE_METHOD_PKEY_METHS:
+ ENGINE_unregister_pkey_meths(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_PKEY_ASN1_METHS
+ case ENGINE_METHOD_PKEY_ASN1_METHS:
+ ENGINE_unregister_pkey_asn1_meths(ctx->engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_EC
+ case ENGINE_METHOD_EC:
+ ENGINE_unregister_EC(ctx->engine);
+ break;
+#endif
+ default:
+ break;
+ }
+ return atom_ok;
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM engine_get_first_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ ERL_NIF_TERM ret;
+ ENGINE *engine;
+ ErlNifBinary engine_bin;
+ struct engine_ctx *ctx;
+
+ engine = ENGINE_get_first();
+ if(!engine) {
+ enif_alloc_binary(0, &engine_bin);
+ engine_bin.size = 0;
+ return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_bin));
+ }
+
+ ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx));
+ ctx->engine = engine;
+ ctx->id = NULL;
+
+ ret = enif_make_resource(env, ctx);
+ enif_release_resource(ctx);
+
+ return enif_make_tuple2(env, atom_ok, ret);
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM engine_get_next_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ ERL_NIF_TERM ret;
+ ENGINE *engine;
+ ErlNifBinary engine_bin;
+ struct engine_ctx *ctx, *next_ctx;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_get_next_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+ engine = ENGINE_get_next(ctx->engine);
+ if (!engine) {
+ enif_alloc_binary(0, &engine_bin);
+ engine_bin.size = 0;
+ return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_bin));
+ }
+
+ next_ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx));
+ next_ctx->engine = engine;
+ next_ctx->id = NULL;
+
+ ret = enif_make_resource(env, next_ctx);
+ enif_release_resource(next_ctx);
+
+ return enif_make_tuple2(env, atom_ok, ret);
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ ErlNifBinary engine_id_bin;
+ const char *engine_id;
+ int size;
+ struct engine_ctx *ctx;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_get_id_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+
+ engine_id = ENGINE_get_id(ctx->engine);
+ if (!engine_id) {
+ enif_alloc_binary(0, &engine_id_bin);
+ engine_id_bin.size = 0;
+ return enif_make_binary(env, &engine_id_bin);
+ }
+
+ size = strlen(engine_id);
+ enif_alloc_binary(size, &engine_id_bin);
+ engine_id_bin.size = size;
+ memcpy(engine_id_bin.data, engine_id, size);
+
+ return enif_make_binary(env, &engine_id_bin);
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM engine_get_name_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ ErlNifBinary engine_name_bin;
+ const char *engine_name;
+ int size;
+ struct engine_ctx *ctx;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_get_id_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+
+ engine_name = ENGINE_get_name(ctx->engine);
+ if (!engine_name) {
+ enif_alloc_binary(0, &engine_name_bin);
+ engine_name_bin.size = 0;
+ return enif_make_binary(env, &engine_name_bin);
+ }
+
+ size = strlen(engine_name);
+ enif_alloc_binary(size, &engine_name_bin);
+ engine_name_bin.size = size;
+ memcpy(engine_name_bin.data, engine_name, size);
+
+ return enif_make_binary(env, &engine_name_bin);
+#else
+ return atom_notsup;
+#endif
+}
+
+#ifdef HAS_ENGINE_SUPPORT
+static int get_engine_load_cmd_list(ErlNifEnv* env, const ERL_NIF_TERM term, char **cmds, int i)
+{
+ ERL_NIF_TERM head, tail;
+ const ERL_NIF_TERM *tmp_tuple;
+ ErlNifBinary tmpbin;
+ int arity;
+ char* tmpstr;
+
+ if(!enif_is_empty_list(env, term)) {
+ if(!enif_get_list_cell(env, term, &head, &tail)) {
+ cmds[i] = NULL;
+ return -1;
+ } else {
+ if(!enif_get_tuple(env, head, &arity, &tmp_tuple) || arity != 2) {
+ cmds[i] = NULL;
+ return -1;
+ } else {
+ if(!enif_inspect_binary(env, tmp_tuple[0], &tmpbin)) {
+ cmds[i] = NULL;
+ return -1;
+ } else {
+ tmpstr = enif_alloc(tmpbin.size+1);
+ (void) memcpy(tmpstr, tmpbin.data, tmpbin.size);
+ tmpstr[tmpbin.size] = '\0';
+ cmds[i++] = tmpstr;
+ }
+ if(!enif_inspect_binary(env, tmp_tuple[1], &tmpbin)) {
+ cmds[i] = NULL;
+ return -1;
+ } else {
+ if(tmpbin.size == 0)
+ cmds[i++] = NULL;
+ else {
+ tmpstr = enif_alloc(tmpbin.size+1);
+ (void) memcpy(tmpstr, tmpbin.data, tmpbin.size);
+ tmpstr[tmpbin.size] = '\0';
+ cmds[i++] = tmpstr;
+ }
+ }
+ return get_engine_load_cmd_list(env, tail, cmds, i);
+ }
+ }
+ } else {
+ cmds[i] = NULL;
+ return 0;
+ }
+}
+#endif
+
+static ERL_NIF_TERM engine_get_all_methods_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* () */
+#ifdef HAS_ENGINE_SUPPORT
+ ERL_NIF_TERM method_array[12];
+ int i = 0;
+
+#ifdef ENGINE_METHOD_RSA
+ method_array[i++] = atom_engine_method_rsa;
+#endif
+#ifdef ENGINE_METHOD_DSA
+ method_array[i++] = atom_engine_method_dsa;
+#endif
+#ifdef ENGINE_METHOD_DH
+ method_array[i++] = atom_engine_method_dh;
+#endif
+#ifdef ENGINE_METHOD_RAND
+ method_array[i++] = atom_engine_method_rand;
+#endif
+#ifdef ENGINE_METHOD_ECDH
+ method_array[i++] = atom_engine_method_ecdh;
+#endif
+#ifdef ENGINE_METHOD_ECDSA
+ method_array[i++] = atom_engine_method_ecdsa;
+#endif
+#ifdef ENGINE_METHOD_STORE
+ method_array[i++] = atom_engine_method_store;
+#endif
+#ifdef ENGINE_METHOD_CIPHERS
+ method_array[i++] = atom_engine_method_ciphers;
+#endif
+#ifdef ENGINE_METHOD_DIGESTS
+ method_array[i++] = atom_engine_method_digests;
+#endif
+#ifdef ENGINE_METHOD_PKEY_METHS
+ method_array[i++] = atom_engine_method_pkey_meths;
+#endif
+#ifdef ENGINE_METHOD_PKEY_ASN1_METHS
+ method_array[i++] = atom_engine_method_pkey_asn1_meths;
+#endif
+#ifdef ENGINE_METHOD_EC
+ method_array[i++] = atom_engine_method_ec;
+#endif
+
+ return enif_make_list_from_array(env, method_array, i);
+#else
+ return atom_notsup;
+#endif
+}
diff --git a/lib/crypto/c_src/otp_test_engine.c b/lib/crypto/c_src/otp_test_engine.c
new file mode 100644
index 0000000000..34c825059f
--- /dev/null
+++ b/lib/crypto/c_src/otp_test_engine.c
@@ -0,0 +1,280 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2017-2018. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#ifdef _WIN32
+#define OPENSSL_OPT_WINDLL
+#endif
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/md5.h>
+#include <openssl/rsa.h>
+
+#define PACKED_OPENSSL_VERSION(MAJ, MIN, FIX, P) \
+ ((((((((MAJ << 8) | MIN) << 8 ) | FIX) << 8) | (P-'a'+1)) << 4) | 0xf)
+
+#define PACKED_OPENSSL_VERSION_PLAIN(MAJ, MIN, FIX) \
+ PACKED_OPENSSL_VERSION(MAJ,MIN,FIX,('a'-1))
+
+#if OPENSSL_VERSION_NUMBER < PACKED_OPENSSL_VERSION_PLAIN(1,1,0) \
+ || defined(LIBRESSL_VERSION_NUMBER)
+#define OLD
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'o') \
+ && !defined(OPENSSL_NO_EC) \
+ && !defined(OPENSSL_NO_ECDH) \
+ && !defined(OPENSSL_NO_ECDSA)
+# define HAVE_EC
+#endif
+
+#if defined(HAVE_EC)
+/* If OPENSSL_NO_EC is set, there will be an error in ec.h included from engine.h
+ So if EC is disabled, you can't use Engine either....
+*/
+#include <openssl/engine.h>
+#include <openssl/pem.h>
+
+
+static const char *test_engine_id = "MD5";
+static const char *test_engine_name = "MD5 test engine";
+
+/* The callback that does the job of fetching keys on demand by the Engine */
+EVP_PKEY* test_key_load(ENGINE *er, const char *id, UI_METHOD *ui_method, void *callback_data);
+
+
+static int test_init(ENGINE *e) {
+ printf("OTP Test Engine Initializatzion!\r\n");
+
+ /* Load all digest and cipher algorithms. Needed for password protected private keys */
+ OpenSSL_add_all_ciphers();
+ OpenSSL_add_all_digests();
+
+ return 111;
+}
+
+static void add_test_data(unsigned char *md, unsigned int len)
+{
+ unsigned int i;
+
+ for (i=0; i<len; i++) {
+ md[i] = (unsigned char)(i & 0xff);
+ }
+}
+
+/* MD5 part */
+#undef data
+#ifdef OLD
+#define data(ctx) ((MD5_CTX *)ctx->md_data)
+#endif
+
+static int test_engine_md5_init(EVP_MD_CTX *ctx) {
+ fprintf(stderr, "MD5 initialized\r\n");
+#ifdef OLD
+ return MD5_Init(data(ctx));
+#else
+ return 1;
+#endif
+}
+
+static int test_engine_md5_update(EVP_MD_CTX *ctx,const void *data, size_t count)
+{
+ fprintf(stderr, "MD5 update\r\n");
+#ifdef OLD
+ return MD5_Update(data(ctx), data, (size_t)count);
+#else
+ return 1;
+#endif
+}
+
+static int test_engine_md5_final(EVP_MD_CTX *ctx,unsigned char *md) {
+#ifdef OLD
+ int ret;
+
+ fprintf(stderr, "MD5 final size of EVP_MD: %lu\r\n", sizeof(EVP_MD));
+ ret = MD5_Final(md, data(ctx));
+
+ if (ret > 0) {
+ add_test_data(md, MD5_DIGEST_LENGTH);
+ }
+ return ret;
+#else
+ fprintf(stderr, "MD5 final\r\n");
+ add_test_data(md, MD5_DIGEST_LENGTH);
+ return 1;
+#endif
+}
+
+#ifdef OLD
+static EVP_MD test_engine_md5_method= {
+ NID_md5, /* The name ID for MD5 */
+ NID_undef, /* IGNORED: MD5 with private key encryption NID */
+ MD5_DIGEST_LENGTH, /* Size of MD5 result, in bytes */
+ 0, /* Flags */
+ test_engine_md5_init, /* digest init */
+ test_engine_md5_update, /* digest update */
+ test_engine_md5_final, /* digest final */
+ NULL, /* digest copy */
+ NULL, /* digest cleanup */
+ EVP_PKEY_NULL_method, /* IGNORED: pkey methods */
+ MD5_CBLOCK, /* Internal blocksize, see rfc1321/md5.h */
+ sizeof(EVP_MD *) + sizeof(MD5_CTX),
+ NULL, /* IGNORED: control function */
+};
+#endif
+
+static int test_digest_ids[] = {NID_md5};
+
+static int test_engine_digest_selector(ENGINE *e, const EVP_MD **digest,
+ const int **nids, int nid) {
+ int ok = 1;
+ if (!digest) {
+ *nids = test_digest_ids;
+ fprintf(stderr, "Digest is empty! Nid:%d\r\n", nid);
+ return 2;
+ }
+ fprintf(stderr, "Digest no %d requested\r\n",nid);
+ if (nid == NID_md5) {
+#ifdef OLD
+ *digest = &test_engine_md5_method;
+#else
+ EVP_MD *md = EVP_MD_meth_new(NID_md5, NID_undef);
+ if (!md ||
+ !EVP_MD_meth_set_result_size(md, MD5_DIGEST_LENGTH) ||
+ !EVP_MD_meth_set_flags(md, 0) ||
+ !EVP_MD_meth_set_init(md, test_engine_md5_init) ||
+ !EVP_MD_meth_set_update(md, test_engine_md5_update) ||
+ !EVP_MD_meth_set_final(md, test_engine_md5_final) ||
+ !EVP_MD_meth_set_copy(md, NULL) ||
+ !EVP_MD_meth_set_cleanup(md, NULL) ||
+ !EVP_MD_meth_set_input_blocksize(md, MD5_CBLOCK) ||
+ !EVP_MD_meth_set_app_datasize(md, sizeof(EVP_MD *) + sizeof(MD5_CTX)) ||
+ !EVP_MD_meth_set_ctrl(md, NULL))
+ {
+ ok = 0;
+ *digest = NULL;
+ } else
+ {
+ *digest = md;
+ }
+#endif
+ }
+ else {
+ ok = 0;
+ *digest = NULL;
+ }
+
+ return ok;
+}
+
+
+static int bind_helper(ENGINE * e, const char *id)
+{
+ if (!ENGINE_set_id(e, test_engine_id) ||
+ !ENGINE_set_name(e, test_engine_name) ||
+ !ENGINE_set_init_function(e, test_init) ||
+ !ENGINE_set_digests(e, &test_engine_digest_selector) ||
+ /* For testing of key storage in an Engine: */
+ !ENGINE_set_load_privkey_function(e, &test_key_load) ||
+ !ENGINE_set_load_pubkey_function(e, &test_key_load)
+ )
+ return 0;
+
+ return 1;
+}
+
+IMPLEMENT_DYNAMIC_CHECK_FN();
+
+IMPLEMENT_DYNAMIC_BIND_FN(bind_helper);
+
+/********************************************************
+ *
+ * Engine storage simulation
+ *
+ */
+int pem_passwd_cb_fun(char *buf, int size, int rwflag, void *password);
+
+EVP_PKEY* test_key_load(ENGINE *er, const char *id, UI_METHOD *ui_method, void *callback_data)
+{
+ EVP_PKEY *pkey = NULL;
+ FILE *f = fopen(id, "r");
+
+ if (!f) {
+ fprintf(stderr, "%s:%d fopen(%s) failed\r\n", __FILE__,__LINE__,id);
+ return NULL;
+ }
+
+ /* First try to read as a private key. If that fails, try to read as a public key: */
+ pkey = PEM_read_PrivateKey(f, NULL, pem_passwd_cb_fun, callback_data);
+ if (!pkey) {
+ /* ERR_print_errors_fp (stderr); */
+ fclose(f);
+ f = fopen(id, "r");
+ pkey = PEM_read_PUBKEY(f, NULL, NULL, NULL);
+ }
+ fclose(f);
+
+ if (!pkey) {
+ fprintf(stderr, "%s:%d Key read from file %s failed.\r\n", __FILE__,__LINE__,id);
+ if (callback_data)
+ fprintf(stderr, "Pwd = \"%s\".\r\n", (char *)callback_data);
+ fprintf(stderr, "Contents of file \"%s\":\r\n",id);
+ f = fopen(id, "r");
+ { /* Print the contents of the key file */
+ char c;
+ while (!feof(f)) {
+ switch (c=fgetc(f)) {
+ case '\n':
+ case '\r': putc('\r',stderr); putc('\n',stderr); break;
+ default: putc(c, stderr);
+ }
+ }
+ }
+ fprintf(stderr, "File contents printed.\r\n");
+ fclose(f);
+ return NULL;
+ }
+
+ return pkey;
+}
+
+
+int pem_passwd_cb_fun(char *buf, int size, int rwflag, void *password)
+{
+ int i;
+
+ fprintf(stderr, "In pem_passwd_cb_fun\r\n");
+ if (!password)
+ return 0;
+
+ i = strlen(password);
+ if (i < size) {
+ /* whole pwd (incl terminating 0) fits */
+ fprintf(stderr, "Got FULL pwd %d(%d) chars\r\n", i, size);
+ memcpy(buf, (char*)password, i+1);
+ return i+1;
+ } else {
+ fprintf(stderr, "Got TO LONG pwd %d(%d) chars\r\n", i, size);
+ /* meaningless with a truncated password */
+ return 0;
+ }
+}
+
+#endif
diff --git a/lib/crypto/doc/specs/.gitignore b/lib/crypto/doc/specs/.gitignore
new file mode 100644
index 0000000000..322eebcb06
--- /dev/null
+++ b/lib/crypto/doc/specs/.gitignore
@@ -0,0 +1 @@
+specs_*.xml
diff --git a/lib/crypto/doc/src/Makefile b/lib/crypto/doc/src/Makefile
index 9c503b8fe0..cbcafb7375 100644
--- a/lib/crypto/doc/src/Makefile
+++ b/lib/crypto/doc/src/Makefile
@@ -9,11 +9,11 @@
# 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.
-#
+#
# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
# AB. All Rights Reserved.''
-#
+#
# $Id$
#
include $(ERL_TOP)/make/target.mk
@@ -38,13 +38,13 @@ XML_APPLICATION_FILES = ref_man.xml
XML_REF3_FILES = crypto.xml
XML_REF6_FILES = crypto_app.xml
-XML_PART_FILES = release_notes.xml usersguide.xml
-XML_CHAPTER_FILES = notes.xml licenses.xml fips.xml
+XML_PART_FILES = usersguide.xml
+XML_CHAPTER_FILES = notes.xml licenses.xml fips.xml engine_load.xml engine_keys.xml algorithm_details.xml
BOOK_FILES = book.xml
XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) $(XML_REF6_FILES) \
- $(XML_PART_FILES) $(XML_CHAPTER_FILES)
+ $(XML_PART_FILES) $(XML_CHAPTER_FILES)
GIF_FILES =
@@ -62,10 +62,16 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
+
+TOP_SPECS_FILE = specs.xml
+
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
+XML_FLAGS +=
+
+#in ssh it looks like this: SPECS_FLAGS = -I../../../public_key/include -I../../../public_key/src -I../../..
# ----------------------------------------------------
# Targets
@@ -73,7 +79,6 @@ XML_FLAGS +=
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-
docs: pdf html man
$(TOP_PDF_FILE): $(XML_FILES)
@@ -86,18 +91,20 @@ man: $(MAN3_FILES) $(MAN6_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-debug opt valgrind:
+debug opt valgrind:
clean clean_docs clean_tex:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+ rm -f $(SPECS_FILES)
rm -f errs core *~
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
@@ -114,4 +121,3 @@ release_docs_spec: docs
release_spec:
-
diff --git a/lib/crypto/doc/src/algorithm_details.xml b/lib/crypto/doc/src/algorithm_details.xml
new file mode 100644
index 0000000000..68ad264df7
--- /dev/null
+++ b/lib/crypto/doc/src/algorithm_details.xml
@@ -0,0 +1,297 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2014</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>Algorithm Details</title>
+ <prepared>Hans Nilsson</prepared>
+ <docno></docno>
+ <date>2018-08-22</date>
+ <rev>A</rev>
+ <file>algorithm_details.xml</file>
+ </header>
+ <p>
+ This chapter describes details of algorithms in the crypto application.
+ </p>
+ <p>The tables only documents the supported cryptos and key lengths. The user should not draw any conclusion
+ on security from the supplied tables.
+ </p>
+
+ <section>
+ <title>Ciphers</title>
+ <section>
+ <title>Block Ciphers</title>
+ <p>To be used in
+ <seealso marker="crypto#block_encrypt-3">block_encrypt/3</seealso>,
+ <seealso marker="crypto#block_encrypt-4">block_encrypt/4</seealso>,
+ <seealso marker="crypto#block_decrypt-3">block_decrypt/3</seealso> and
+ <seealso marker="crypto#block_decrypt-4">block_decrypt/4</seealso>.
+ </p>
+ <p>Available in all OpenSSL compatible with Erlang CRYPTO if not disabled by configuration.
+ </p>
+ <p>To dynamically check availability, check that the name in the <i>Cipher and Mode</i> column is present in the
+ list with the <c>cipher</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ <table>
+ <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>IV length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Block size</strong><br/><strong>[bytes]</strong></cell></row>
+ <row><cell><c>aes_cbc</c></cell> <cell>16, 24, 32</cell><cell>16</cell><cell>16</cell></row>
+ <row><cell><c>aes_cbc128</c></cell><cell>16</cell><cell>16</cell><cell>16</cell></row>
+ <row><cell><c>aes_cbc256</c></cell><cell>32</cell><cell>16</cell><cell>16</cell></row>
+
+ <row><cell><c>aes_cfb8</c></cell> <cell>16, 24, 32</cell><cell>16</cell><cell>any</cell></row>
+
+ <row><cell><c>aes_ecb</c></cell><cell>16, 24, 32</cell><cell> </cell><cell>16</cell></row>
+
+ <row><cell><c>aes_ige256</c></cell><cell>16</cell><cell>32</cell><cell>16</cell></row>
+ <row><cell><c>blowfish_cbc</c></cell> <cell>4-56</cell> <cell>8</cell> <cell>8</cell></row>
+ <row><cell><c>blowfish_cfb64</c></cell> <cell>1-</cell> <cell>8</cell> <cell>any</cell></row>
+ <row><cell><c>blowfish_ecb</c></cell><cell>1-</cell><cell> </cell><cell>8</cell></row>
+ <row><cell><c>blowfish_ofb64</c></cell><cell>1-</cell><cell>8</cell><cell>any</cell></row>
+
+ <row><cell><c>des3_cbc</c><br/><i>(=DES EDE3 CBC)</i></cell><cell>[8,8,8]</cell><cell>8</cell><cell>8</cell></row>
+ <row><cell><c>des3_cfb</c><br/><i>(=DES EDE3 CFB)</i></cell><cell>[8,8,8]</cell><cell>8</cell><cell>any</cell></row>
+
+ <row><cell><c>des_cbc</c></cell><cell>8</cell><cell>8</cell> <cell>8</cell></row>
+ <row><cell><c>des_cfb</c></cell><cell>8</cell><cell>8</cell><cell>any</cell></row>
+ <row><cell><c>des_ecb</c></cell><cell>8</cell><cell> </cell><cell>8</cell></row>
+ <row><cell><c>des_ede3</c><br/><i>(=DES EDE3 CBC)</i></cell><cell>[8,8,8]</cell><cell>8</cell><cell>8</cell></row>
+ <row><cell><c>rc2_cbc</c></cell><cell>1-</cell><cell>8</cell><cell>8</cell></row>
+ <tcaption>Block cipher key lengths</tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>AEAD Ciphers</title>
+ <p>To be used in <seealso marker="crypto#block_encrypt-4">block_encrypt/4</seealso> and
+ <seealso marker="crypto#block_decrypt-4">block_decrypt/4</seealso>.
+ </p>
+ <p>To dynamically check availability, check that the name in the <i>Cipher and Mode</i> column is present in the
+ list with the <c>cipher</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ <table>
+ <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>IV length</strong><br/><strong>[bytes]</strong></cell><cell><strong>AAD length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Tag length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Block size</strong><br/><strong>[bytes]</strong></cell><cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell></row>
+ <row><cell><c>aes_ccm</c></cell> <cell>16,24,32</cell> <cell>7-13</cell> <cell>any</cell> <cell>even 4-16<br/>default: 12</cell> <cell>any</cell><cell>1.1.0 -</cell></row>
+ <row><cell><c>aes_gcm</c></cell> <cell>16,24,32</cell> <cell>1-</cell> <cell>any</cell> <cell>1-16<br/>default: 16</cell> <cell>any</cell><cell>1.1.0 -</cell></row>
+ <row><cell><c>chacha20_poly1305</c></cell><cell>32</cell> <cell>1-16</cell> <cell>any</cell> <cell>16</cell> <cell>any</cell><cell>1.1.0 -</cell></row>
+ <tcaption>AEAD cipher key lengths</tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>Stream Ciphers</title>
+ <p>To be used in <seealso marker="crypto#stream_init-2">stream_init/2</seealso> and
+ <seealso marker="crypto#stream_init/3">stream_init/3</seealso>.
+ </p>
+ <p>To dynamically check availability, check that the name in the <i>Cipher and Mode</i> column is present in the
+ list with the <c>cipher</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ <table>
+ <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>IV length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell></row>
+ <row><cell><c>aes_ctr</c></cell><cell>16, 24, 32</cell><cell>16</cell><cell>1.0.1 -</cell></row>
+ <row><cell><c>rc4</c></cell><cell>1-</cell><cell> </cell> <cell>all</cell></row>
+ <tcaption>Stream cipher key lengths</tcaption>
+ </table>
+ </section>
+ </section>
+
+ <section>
+ <title>Message Authentication Codes (MACs)</title>
+
+ <section>
+ <title>CMAC</title>
+ <p>To be used in <seealso marker="crypto#cmac-3">cmac/3</seealso> and
+ <seealso marker="crypto#cmac-3">cmac/4</seealso>.
+ </p>
+ <p>CMAC with the following ciphers are available with OpenSSL 1.0.1 or later if not disabled by configuration.
+ </p>
+
+ <p>To dynamically check availability, check that the name <c>cmac</c> is present in the
+ list with the <c>macs</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ Also check that the name in the <i>Cipher and Mode</i> column is present in the
+ list with the <c>cipher</c> tag in the return value.
+ </p>
+ <table>
+ <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Max Mac Length</strong><br/><strong>[bytes]</strong></cell></row>
+ <row><cell><c>aes_cbc</c></cell> <cell>16, 24, 32</cell><cell>16</cell></row>
+ <row><cell><c>aes_cbc128</c></cell><cell>16</cell><cell>16</cell></row>
+ <row><cell><c>aes_cbc256</c></cell><cell>32</cell><cell>16</cell></row>
+
+ <row><cell><c>aes_cfb8</c></cell> <cell>16</cell><cell>1</cell></row>
+
+ <row><cell><c>blowfish_cbc</c></cell> <cell>4-56</cell> <cell>8</cell></row>
+ <row><cell><c>blowfish_cfb64</c></cell> <cell>1-</cell> <cell>1</cell></row>
+ <row><cell><c>blowfish_ecb</c></cell><cell>1-</cell> <cell>8</cell></row>
+ <row><cell><c>blowfish_ofb64</c></cell><cell>1-</cell> <cell>1</cell></row>
+
+ <row><cell><c>des3_cbc</c><br/><i>(=DES EDE3 CBC)</i></cell><cell>[8,8,8]</cell><cell>8</cell></row>
+ <row><cell><c>des3_cfb</c><br/><i>(=DES EDE3 CFB)</i></cell><cell>[8,8,8]</cell><cell>1</cell></row>
+
+ <row><cell><c>des_cbc</c></cell><cell>8</cell><cell>8</cell></row>
+
+ <row><cell><c>des_cfb</c></cell><cell>8</cell><cell>1</cell></row>
+ <row><cell><c>des_ecb</c></cell><cell>8</cell><cell>1</cell></row>
+ <row><cell><c>rc2_cbc</c></cell><cell>1-</cell><cell>8</cell></row>
+ <tcaption>CMAC cipher key lengths</tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>HMAC</title>
+ <p>Available in all OpenSSL compatible with Erlang CRYPTO if not disabled by configuration.
+ </p>
+ <p>To dynamically check availability, check that the name <c>hmac</c> is present in the
+ list with the <c>macs</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>POLY1305</title>
+ <p>POLY1305 is available with OpenSSL 1.1.1 or later if not disabled by configuration.
+ </p>
+ <p>To dynamically check availability, check that the name <c>poly1305</c> is present in the
+ list with the <c>macs</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ </section>
+
+ <section>
+ <title>Hash</title>
+
+ <p>To dynamically check availability, check that the wanted name in the <i>Names</i> column is present in the
+ list with the <c>hashs</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+
+
+ <table>
+ <row><cell><strong>Type</strong></cell>
+ <cell><strong>Names</strong></cell>
+ <cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell>
+ </row>
+ <row><cell>SHA1</cell><cell>sha</cell><cell>all</cell></row>
+ <row><cell>SHA2</cell><cell>sha224, sha256, sha384, sha512</cell><cell>all</cell></row>
+ <row><cell>SHA3</cell><cell>sha3_224, sha3_256, sha3_384, sha3_512</cell><cell>1.1.1 -</cell></row>
+ <row><cell>MD4</cell><cell>md4</cell><cell>all</cell></row>
+ <row><cell>MD5</cell><cell>md5</cell><cell>all</cell></row>
+ <row><cell>RIPEMD</cell><cell>ripemd160</cell><cell>all</cell></row>
+ <tcaption></tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>Public Key Cryptography</title>
+
+ <section>
+ <title>RSA</title>
+ <p>RSA is available with all OpenSSL versions compatible with Erlang CRYPTO if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>rsa</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ <warning>
+ <!-- In RefMan rsa_opt(), rsa_sign_verify_opt() and User's man RSA -->
+ <p>The RSA options are experimental.
+ </p>
+ <p>The exact set of options and there syntax <em>may</em> be changed
+ without prior notice.</p>
+ </warning>
+ <table>
+ <row><cell><strong>Option</strong></cell> <cell><strong>sign/verify</strong></cell> <cell><strong>encrypt/decrypt</strong></cell> <cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell> </row>
+ <row><cell>{rsa_mgf1_md,atom()}</cell> <cell>x</cell> <cell>x</cell> <cell>1.0.1</cell></row>
+ <row><cell>{rsa_oaep_label, binary()}</cell> <cell> </cell> <cell>x</cell> <cell></cell></row>
+ <row><cell>{rsa_oaep_md, atom()}</cell> <cell> </cell> <cell>x</cell> <cell></cell></row>
+ <row><cell>{rsa_padding,rsa_pkcs1_pss_padding}</cell> <cell>x</cell> <cell> </cell> <cell>1.0.0</cell></row>
+ <row><cell>{rsa_pss_saltlen, -2..}</cell> <cell>x</cell> <cell> </cell> <cell>1.0.0</cell></row>
+ <row><cell>{rsa_padding,rsa_no_padding}</cell> <cell>x</cell> <cell>x</cell> <cell></cell></row>
+ <row><cell>{rsa_padding,rsa_pkcs1_padding}</cell> <cell>x</cell> <cell>x</cell> <cell></cell></row>
+ <row><cell>{rsa_padding,rsa_sslv23_padding}</cell> <cell> </cell> <cell>x</cell> <cell></cell></row>
+ <row><cell>{rsa_padding,rsa_x931_padding}</cell> <cell>x</cell> <cell> </cell> <cell></cell></row>
+ <tcaption></tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>DSS</title>
+ <p>DSS is available with OpenSSL versions compatible with Erlang CRYPTO if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>dss</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>ECDSA</title>
+ <p>ECDSA is available with OpenSSL 0.9.8o or later if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>ecdsa</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ If the atom <c>ec_gf2m</c> characteristic two field curves are available.
+ </p>
+ <p>The actual supported named curves could be checked by examining the list with the
+ <c>curves</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>Diffie-Hellman</title>
+ <p>Diffie-Hellman computations are available with OpenSSL versions compatible with Erlang CRYPTO
+ if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>dh</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>Elliptic Curve Diffie-Hellman</title>
+ <p>Elliptic Curve Diffie-Hellman is available with OpenSSL 0.9.8o or later if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>ecdh</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+
+ <p>The Edward curves <c>x25519</c> and <c>x448</c> are supported with OpenSSL 1.1.1 or later
+ if not disabled by configuration.
+ </p>
+
+ <p>The actual supported named curves could be checked by examining the list with the
+ <c>curves</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ </section>
+
+
+</chapter>
+
+
+
+
+
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 89ef529c5d..651b647e1c 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -4,14 +4,14 @@
<erlref>
<header>
<copyright>
- <year>1999</year><year>2017</year>
+ <year>1999</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
@@ -19,7 +19,6 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-
</legalnotice>
<title>crypto</title>
@@ -29,190 +28,528 @@
<description>
<p>This module provides a set of cryptographic functions.
</p>
- <list type="bulleted">
- <item>
- <p>Hash functions -
- <url href="http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf"> Secure Hash Standard</url>,
- <url href="http://www.ietf.org/rfc/rfc1321.txt"> The MD5 Message Digest Algorithm (RFC 1321)</url> and
- <url href="http://www.ietf.org/rfc/rfc1320.txt">The MD4 Message Digest Algorithm (RFC 1320)</url>
- </p>
- </item>
- <item>
- <p>Hmac functions - <url href="http://www.ietf.org/rfc/rfc2104.txt"> Keyed-Hashing for Message Authentication (RFC 2104) </url></p>
- </item>
- <item>
- <p>Cmac functions - <url href="http://www.ietf.org/rfc/rfc4493.txt">The AES-CMAC Algorithm (RFC 4493)</url></p>
- </item>
- <item>
- <p>Block ciphers - <url href="http://csrc.nist.gov/groups/ST/toolkit/block_ciphers.html"> </url> DES and AES in
- Block Cipher Modes - <url href="http://csrc.nist.gov/groups/ST/toolkit/BCM/index.html"> ECB, CBC, CFB, OFB, CTR and GCM </url></p>
- </item>
- <item>
- <p><url href="http://www.ietf.org/rfc/rfc1321.txt"> RSA encryption RFC 1321 </url> </p>
- </item>
- <item>
- <p>Digital signatures <url href="http://csrc.nist.gov/publications/drafts/fips186-3/fips_186-3.pdf">Digital Signature Standard (DSS)</url> and<url href="http://csrc.nist.gov/groups/STM/cavp/documents/dss2/ecdsa2vs.pdf"> Elliptic Curve Digital
- Signature Algorithm (ECDSA) </url> </p>
- </item>
- <item>
- <p><url href="http://www.ietf.org/rfc/rfc2945.txt"> Secure Remote Password Protocol (SRP - RFC 2945) </url></p>
- </item>
- <item>
- <p>gcm: Dworkin, M., "Recommendation for Block Cipher Modes of
- Operation: Galois/Counter Mode (GCM) and GMAC",
- National Institute of Standards and Technology SP 800-
- 38D, November 2007.</p>
- </item>
- </list>
+ <taglist>
+ <tag>Hash functions</tag>
+ <item>
+ <p></p>
+ <taglist>
+ <tag>SHA1, SHA2</tag>
+ <item>
+ <url href="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf">
+ Secure Hash Standard [FIPS PUB 180-4]
+ </url>
+ </item>
+ <tag>SHA3</tag>
+ <item>
+ <url href="https://www.nist.gov/publications/sha-3-standard-permutation-based-hash-and-extendable-output-functions?pub_id=919061">
+ SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions [FIPS PUB 202]
+ </url>
+ </item>
+ <tag>MD5</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc1321.txt">The MD5 Message Digest Algorithm [RFC 1321]</url>
+ </item>
+ <tag>MD4</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc1320.txt">The MD4 Message Digest Algorithm [RFC 1320]</url>
+ </item>
+ </taglist>
+ <p></p>
+ </item>
+
+ <tag>MACs - Message Authentication Codes</tag>
+ <item>
+ <p></p>
+ <taglist>
+ <tag>Hmac functions</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc2104.txt">
+ Keyed-Hashing for Message Authentication [RFC 2104]
+ </url>
+ </item>
+ <tag>Cmac functions</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc4493.txt">
+ The AES-CMAC Algorithm [RFC 4493]
+ </url>
+ </item>
+ <tag>POLY1305</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc7539.txt">
+ ChaCha20 and Poly1305 for IETF Protocols [RFC 7539]
+ </url>
+ </item>
+ </taglist>
+ <p></p>
+ </item>
+
+ <tag>Symmetric Ciphers</tag>
+ <item>
+ <p></p>
+ <taglist>
+ <tag>DES, 3DES and AES</tag>
+ <item>
+ <url href="https://csrc.nist.gov/projects/block-cipher-techniques">Block Cipher Techniques [NIST]</url>
+ </item>
+ <tag>Blowfish</tag>
+ <item>
+ <url href="https://www.schneier.com/academic/archives/1994/09/description_of_a_new.html">
+ Fast Software Encryption, Cambridge Security Workshop Proceedings (December 1993), Springer-Verlag, 1994, pp. 191-204.
+ </url>
+ </item>
+ <tag>Chacha20</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc7539.txt">
+ ChaCha20 and Poly1305 for IETF Protocols [RFC 7539]
+ </url>
+ </item>
+ <tag>Chacha20_poly1305</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc7539.txt">
+ ChaCha20 and Poly1305 for IETF Protocols [RFC 7539]
+ </url>
+ </item>
+ </taglist>
+ <p></p>
+ </item>
+
+ <tag>Modes</tag>
+ <item>
+ <p></p>
+ <taglist>
+ <tag>ECB, CBC, CFB, OFB and CTR</tag>
+ <item>
+ <url href="https://csrc.nist.gov/publications/detail/sp/800-38a/final">
+ Recommendation for Block Cipher Modes of Operation: Methods and Techniques [NIST SP 800-38A]
+ </url>
+ </item>
+ <tag>GCM</tag>
+ <item>
+ <url href="https://csrc.nist.gov/publications/detail/sp/800-38d/final">
+ Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC [NIST SP 800-38D]
+ </url>
+ </item>
+ <tag>CCM</tag>
+ <item>
+ <url href="https://nvlpubs.nist.gov/nistpubs/legacy/sp/nistspecialpublication800-38c.pdf">
+ Recommendation for Block Cipher Modes of Operation:
+ The CCM Mode for Authentication and Confidentiality [NIST SP 800-38C]
+ </url>
+ </item>
+ </taglist>
+ <p></p>
+ </item>
+
+ <tag>Asymetric Ciphers - Public Key Techniques</tag>
+ <item>
+ <p></p>
+ <taglist>
+ <tag>RSA</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc3447.txt">
+ PKCS #1: RSA Cryptography Specifications [RFC 3447]
+ </url>
+ </item>
+ <tag>DSS</tag>
+ <item>
+ <url href="https://csrc.nist.gov/publications/detail/fips/186/4/final">
+ Digital Signature Standard (DSS) [FIPS 186-4]
+ </url>
+ </item>
+ <tag>ECDSA</tag>
+ <item>
+ <url href="http://csrc.nist.gov/groups/STM/cavp/documents/dss2/ecdsa2vs.pdf">
+ Elliptic Curve Digital Signature Algorithm [ECDSA]
+ </url>
+ </item>
+ <tag>SRP</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc2945.txt">
+ The SRP Authentication and Key Exchange System [RFC 2945]
+ </url>
+ </item>
+ </taglist>
+ <p></p>
+ </item>
+ </taglist>
+
+ <note>
+ <p>The actual supported algorithms and features depends on their availability in the actual libcrypto used.
+ See the <seealso marker="crypto:crypto_app">crypto (App)</seealso> about dependencies.
+ </p>
+ <p>Enabling FIPS mode will also disable algorithms and features.
+ </p>
+ </note>
+
+ <p>The <seealso marker="users_guide">CRYPTO User's Guide</seealso> has more information on
+ FIPS, Engines and Algorithm Details like key lengths.
+ </p>
</description>
- <section>
- <title>DATA TYPES </title>
-
- <code>key_value() = integer() | binary() </code>
- <p>Always <c>binary()</c> when used as return value</p>
+ <datatypes>
+ <datatype_title>Ciphers</datatype_title>
+ <datatype>
+ <name name="stream_cipher"/>
+ <desc>
+ <p>Stream ciphers for
+ <seealso marker="#stream_encrypt-2">stream_encrypt/2</seealso> and
+ <seealso marker="#stream_decrypt-2">stream_decrypt/2</seealso> .
+ </p>
+ </desc>
+ </datatype>
- <code>rsa_public() = [key_value()] = [E, N] </code>
- <p> Where E is the public exponent and N is public modulus. </p>
+ <datatype>
+ <name name="block_cipher_with_iv"/>
+ <name name="cbc_cipher"/>
+ <name name="cfb_cipher"/>
+ <desc>
+ <p>Block ciphers with initialization vector for
+ <seealso marker="#block_encrypt-4">block_encrypt/4</seealso> and
+ <seealso marker="#block_decrypt-4">block_decrypt/4</seealso> .
+ </p>
+ </desc>
+ </datatype>
- <code>rsa_private() = [key_value()] = [E, N, D] | [E, N, D, P1, P2, E1, E2, C] </code>
- <p>Where E is the public exponent, N is public modulus and D is
- the private exponent. The longer key format contains redundant
- information that will make the calculation faster. P1,P2 are first
- and second prime factors. E1,E2 are first and second exponents. C
- is the CRT coefficient. Terminology is taken from <url href="http://www.ietf.org/rfc/rfc3477.txt"> RFC 3447</url>.</p>
+ <datatype>
+ <name name="block_cipher_without_iv"/>
+ <name name="ecb_cipher"/>
+ <desc>
+ <p>Block ciphers without initialization vector for
+ <seealso marker="#block_encrypt-3">block_encrypt/3</seealso> and
+ <seealso marker="#block_decrypt-3">block_decrypt/3</seealso> .
+ </p>
+ </desc>
+ </datatype>
- <code>dss_public() = [key_value()] = [P, Q, G, Y] </code>
- <p>Where P, Q and G are the dss parameters and Y is the public key.</p>
+ <datatype>
+ <name name="aead_cipher"/>
+ <desc>
+ <p>Ciphers with simultaneous MAC-calculation or MAC-checking.
+ <seealso marker="#block_encrypt-4">block_encrypt/4</seealso> and
+ <seealso marker="#block_decrypt-4">block_decrypt/4</seealso> .
+ </p>
+ </desc>
+ </datatype>
- <code>dss_private() = [key_value()] = [P, Q, G, X] </code>
- <p>Where P, Q and G are the dss parameters and X is the private key.</p>
+ <datatype_title>Digests</datatype_title>
+ <datatype>
+ <name name="sha1"/>
+ <name name="sha2"/>
+ <name name="sha3"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>srp_public() = key_value() </code>
- <p>Where is <c>A</c> or <c>B</c> from <url href="http://srp.stanford.edu/design.html">SRP design</url></p>
+ <datatype>
+ <name name="compatibility_only_hash"/>
+ <desc>
+ <p>The <c>compatibility_only_hash()</c> algorithms are recommended only for compatibility with existing applications.</p>
+ </desc>
+ </datatype>
- <code>srp_private() = key_value() </code>
- <p>Where is <c>a</c> or <c>b</c> from <url href="http://srp.stanford.edu/design.html">SRP design</url></p>
+ <datatype>
+ <name name="rsa_digest_type"/>
+ <desc>
+ </desc>
+ </datatype>
- <p>Where Verifier is <c>v</c>, Generator is <c>g</c> and Prime is<c> N</c>, DerivedKey is <c>X</c>, and Scrambler is
- <c>u</c> (optional will be generated if not provided) from <url href="http://srp.stanford.edu/design.html">SRP design</url>
- Version = '3' | '6' | '6a'
- </p>
+ <datatype>
+ <name name="dss_digest_type"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>dh_public() = key_value() </code>
+ <datatype>
+ <name name="ecdsa_digest_type"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>dh_private() = key_value() </code>
+ <datatype_title>Elliptic Curves</datatype_title>
+ <datatype>
+ <name name="ec_named_curve"/>
+ <name name="edwards_curve"/>
+ <desc>
+ <p>Note that some curves are disabled if FIPS is enabled.</p>
+ </desc>
+ </datatype>
- <code>dh_params() = [key_value()] = [P, G] | [P, G, PrivateKeyBitLength]</code>
+ <datatype>
+ <name name="ec_explicit_curve"/>
+ <name name="ec_field"/>
+ <name name="ec_curve"/>
+ <desc>
+ <p>Parametric curve definition.</p>
+ </desc>
+ </datatype>
- <code>ecdh_public() = key_value() </code>
+ <datatype>
+ <name name="ec_prime_field"/>
+ <name name="ec_characteristic_two_field"/>
+ <name name="ec_basis"/>
+ <desc>
+ <p>Curve definition details.</p>
+ </desc>
+ </datatype>
- <code>ecdh_private() = key_value() </code>
+ <datatype_title>Keys</datatype_title>
+ <datatype>
+ <name name="key"/>
+ <name name="des3_key"/>
+ <desc>
+ <p>For keylengths, iv-sizes and blocksizes see the
+ <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>.
+ </p>
+ <p>A key for des3 is a list of three iolists</p>
+ </desc>
+ </datatype>
- <code>ecdh_params() = ec_named_curve() | ec_explicit_curve()</code>
+ <datatype>
+ <name name="key_integer"/>
+ <desc>
+ <p>Always <c>binary()</c> when used as return value</p>
+ </desc>
+ </datatype>
- <code>ec_explicit_curve() =
- {ec_field(), Prime :: key_value(), Point :: key_value(), Order :: integer(), CoFactor :: none | integer()} </code>
+ <datatype_title>Public/Private Keys</datatype_title>
+ <datatype>
+ <name name="rsa_public"/>
+ <name name="rsa_private"/>
+ <name name="rsa_params"/>
+ <desc>
+ <code>rsa_public() = [E, N]</code>
+ <code>rsa_private() = [E, N, D] | [E, N, D, P1, P2, E1, E2, C]</code>
+ <p>Where E is the public exponent, N is public modulus and D is
+ the private exponent. The longer key format contains redundant
+ information that will make the calculation faster. P1,P2 are first
+ and second prime factors. E1,E2 are first and second exponents. C
+ is the CRT coefficient. Terminology is taken from <url href="http://www.ietf.org/rfc/rfc3477.txt"> RFC 3447</url>.</p>
+ </desc>
+ </datatype>
- <code>ec_field() = {prime_field, Prime :: integer()} |
- {characteristic_two_field, M :: integer(), Basis :: ec_basis()}</code>
+ <datatype>
+ <name name="dss_public"/>
+ <name name="dss_private"/>
+ <desc>
+ <code>dss_public() = [P, Q, G, Y] </code>
+ <p>Where P, Q and G are the dss parameters and Y is the public key.</p>
- <code>ec_basis() = {tpbasis, K :: non_neg_integer()} |
- {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()} |
- onbasis</code>
+ <code>dss_private() = [P, Q, G, X] </code>
+ <p>Where P, Q and G are the dss parameters and X is the private key.</p>
+ </desc>
+ </datatype>
- <code>ec_named_curve() ->
- sect571r1| sect571k1| sect409r1| sect409k1| secp521r1| secp384r1| secp224r1| secp224k1|
- secp192k1| secp160r2| secp128r2| secp128r1| sect233r1| sect233k1| sect193r2| sect193r1|
- sect131r2| sect131r1| sect283r1| sect283k1| sect163r2| secp256k1| secp160k1| secp160r1|
- secp112r2| secp112r1| sect113r2| sect113r1| sect239k1| sect163r1| sect163k1| secp256r1|
- secp192r1|
- brainpoolP160r1| brainpoolP160t1| brainpoolP192r1| brainpoolP192t1| brainpoolP224r1|
- brainpoolP224t1| brainpoolP256r1| brainpoolP256t1| brainpoolP320r1| brainpoolP320t1|
- brainpoolP384r1| brainpoolP384t1| brainpoolP512r1| brainpoolP512t1
- </code>
- <p>Note that the <em>sect</em> curves are GF2m (characteristic two) curves and are only supported if the
- underlying OpenSSL has support for them.
- See also <seealso marker="#supports-0">crypto:supports/0</seealso>
- </p>
+ <datatype>
+ <name name="ecdsa_public"/>
+ <name name="ecdsa_private"/>
+ <name name="ecdsa_params"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="srp_public"/>
+ <name name="srp_private"/>
+ <desc>
+ <code>srp_public() = key_integer() </code>
+ <p>Where is <c>A</c> or <c>B</c> from <url href="http://srp.stanford.edu/design.html">SRP design</url></p>
+
+ <code>srp_private() = key_integer() </code>
+ <p>Where is <c>a</c> or <c>b</c> from <url href="http://srp.stanford.edu/design.html">SRP design</url></p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="srp_gen_params"/>
+ <name name="srp_comp_params"/>
+ <desc>
+ <marker id="type-srp_user_gen_params"/>
+ <code>srp_user_gen_params() = [DerivedKey::binary(), Prime::binary(), Generator::binary(), Version::atom()]</code>
+ <marker id="type-srp_host_gen_params"/>
+ <code>srp_host_gen_params() = [Verifier::binary(), Prime::binary(), Version::atom() ]</code>
+ <marker id="type-srp_user_comp_params"/>
+ <code>srp_user_comp_params() = [DerivedKey::binary(), Prime::binary(), Generator::binary(), Version::atom() | ScramblerArg::list()]</code>
+ <marker id="type-srp_host_comp_params"/>
+ <code>srp_host_comp_params() = [Verifier::binary(), Prime::binary(), Version::atom() | ScramblerArg::list()]</code>
+ <p>Where Verifier is <c>v</c>, Generator is <c>g</c> and Prime is<c> N</c>, DerivedKey is <c>X</c>, and Scrambler is
+ <c>u</c> (optional will be generated if not provided) from <url href="http://srp.stanford.edu/design.html">SRP design</url>
+ Version = '3' | '6' | '6a'
+ </p>
+ </desc>
+ </datatype>
- <code>stream_cipher() = rc4 | aes_ctr </code>
+ <datatype_title>Public Key Ciphers</datatype_title>
- <code>block_cipher() = aes_cbc | aes_cfb8 | aes_cfb128 | aes_ige256 | blowfish_cbc |
- blowfish_cfb64 | des_cbc | des_cfb | des3_cbc | des3_cfb | des_ede3 | rc2_cbc </code>
+ <datatype>
+ <name name="pk_encrypt_decrypt_algs"/>
+ <desc>
+ <p>Algorithms for public key encrypt/decrypt. Only RSA is supported.</p>
+ </desc>
+ </datatype>
- <code>aead_cipher() = aes_gcm | chacha20_poly1305 </code>
+ <datatype>
+ <name name="pk_encrypt_decrypt_opts"/>
+ <name name="rsa_opt"/>
+ <name name="rsa_padding"/>
+ <desc>
+ <p>Options for public key encrypt/decrypt. Only RSA is supported.</p>
+ <warning>
+ <!-- In RefMan rsa_opt(), rsa_sign_verify_opt() and User's man RSA -->
+ <p>The RSA options are experimental.
+ </p>
+ <p>The exact set of options and there syntax <em>may</em> be changed
+ without prior notice.</p>
+ </warning>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="rsa_compat_opts"/>
+ <desc>
+ <p>Those option forms are kept only for compatibility and should not be used in new code.</p>
+ </desc>
+ </datatype>
- <code>stream_key() = aes_key() | rc4_key() </code>
+ <datatype_title>Public Key Sign and Verify</datatype_title>
- <code>block_key() = aes_key() | blowfish_key() | des_key()| des3_key() </code>
+ <datatype>
+ <name name="pk_sign_verify_algs"/>
+ <desc>
+ <p>Algorithms for sign and verify.</p>
+ </desc>
+ </datatype>
- <code>aes_key() = iodata() </code> <p>Key length is 128, 192 or 256 bits</p>
+ <datatype>
+ <name name="pk_sign_verify_opts"/>
+ <name name="rsa_sign_verify_opt"/>
+ <name name="rsa_sign_verify_padding"/>
+ <desc>
+ <p>Options for sign and verify.</p>
+ <warning>
+ <!-- In RefMan rsa_opt(), rsa_sign_verify_opt() and User's man RSA -->
+ <p>The RSA options are experimental.
+ </p>
+ <p>The exact set of options and there syntax <em>may</em> be changed
+ without prior notice.</p>
+ </warning>
+ </desc>
+ </datatype>
- <code>rc4_key() = iodata() </code> <p>Variable key length from 8 bits up to 2048 bits (usually between 40 and 256)</p>
+ <datatype_title>Diffie-Hellman Keys and parameters</datatype_title>
+ <datatype>
+ <name name="dh_public"/>
+ <name name="dh_private"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="dh_params"/>
+ <desc>
+ <code>dh_params() = [P, G] | [P, G, PrivateKeyBitLength]</code>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="ecdh_public"/>
+ <name name="ecdh_private"/>
+ <name name="ecdh_params"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype_title>Types for Engines</datatype_title>
+
+ <datatype>
+ <name name="engine_key_ref"/>
+ <name name="engine_ref"/>
+ <desc>
+ <p>The result of a call to <seealso marker="#engine_load-3">engine_load/3</seealso>.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="key_id"/>
+ <desc>
+ <p>Identifies the key to be used. The format depends on the loaded engine. It is passed to
+ the <c>ENGINE_load_(private|public)_key</c> functions in libcrypto.
+ </p>
+ </desc>
+ </datatype>
- <code>blowfish_key() = iodata() </code> <p>Variable key length from 32 bits up to 448 bits</p>
+ <datatype>
+ <name name="password"/>
+ <desc>
+ <p>The password of the key stored in an engine.
+ </p>
+ </desc>
+ </datatype>
- <code>des_key() = iodata() </code> <p>Key length is 64 bits (in CBC mode only 8 bits are used)</p>
+ <datatype>
+ <name name="engine_method_type"/>
+ </datatype>
- <code>des3_key() = [binary(), binary(), binary()] </code> <p>Each key part is 64 bits (in CBC mode only 8 bits are used)</p>
+ <datatype>
+ <name name="engine_cmnd"/>
+ <desc>
+ <p>Pre and Post commands for <seealso marker="#engine_load-3">engine_load/3 and /4</seealso>.
+ </p>
+ </desc>
+ </datatype>
- <code>digest_type() = md5 | sha | sha224 | sha256 | sha384 | sha512</code>
+ <datatype_title>Internal data types</datatype_title>
- <code> hash_algorithms() = md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512 </code> <p>md4 is also supported for hash_init/1 and hash/2.
- Note that both md4 and md5 are recommended only for compatibility with existing applications.
- </p>
- <code> cipher_algorithms() = aes_cbc | aes_cfb8 | aes_cfb128 | aes_ctr | aes_gcm |
- aes_ige256 | blowfish_cbc | blowfish_cfb64 | chacha20_poly1305 | des_cbc | des_cfb |
- des3_cbc | des3_cfb | des_ede3 | rc2_cbc | rc4 </code>
- <code> public_key_algorithms() = rsa |dss | ecdsa | dh | ecdh | ec_gf2m</code>
- <p>Note that ec_gf2m is not strictly a public key algorithm, but a restriction on what curves are supported
- with ecdsa and ecdh.
- </p>
+ <datatype>
+ <name name="stream_state"/>
+ <name name="hmac_state"/>
+ <name name="hash_state"/>
+ <desc>
+ <p>Contexts with an internal state that should not be manipulated but passed between function calls.
+ </p>
+ </desc>
+ </datatype>
- </section>
+ </datatypes>
+ <!--================ FUNCTIONS ================-->
<funcs>
<func>
- <name>block_encrypt(Type, Key, PlainText) -> CipherText</name>
+ <name name="block_encrypt" arity="3"/>
<fsummary>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher</fsummary>
- <type>
- <v>Type = des_ecb | blowfish_ecb | aes_ecb </v>
- <v>Key = block_key() </v>
- <v>PlainText = iodata() </v>
- </type>
<desc>
- <p>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher.</p>
- <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying OpenSSL implementation.</p>
+ <p>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher.</p>
+ <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
+ is not supported by the underlying libcrypto implementation.</p>
+ <p>For keylengths and blocksizes see the
+ <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
<func>
- <name>block_decrypt(Type, Key, CipherText) -> PlainText</name>
+ <name name="block_decrypt" arity="3"/>
<fsummary>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher</fsummary>
- <type>
- <v>Type = des_ecb | blowfish_ecb | aes_ecb </v>
- <v>Key = block_key() </v>
- <v>PlainText = iodata() </v>
- </type>
<desc>
<p>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher.</p>
- <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying OpenSSL implementation.</p>
+ <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
+ is not supported by the underlying libcrypto implementation.</p>
+ <p>For keylengths and blocksizes see the
+ <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
<func>
<name>block_encrypt(Type, Key, Ivec, PlainText) -> CipherText</name>
<name>block_encrypt(AeadType, Key, Ivec, {AAD, PlainText}) -> {CipherText, CipherTag}</name>
- <name>block_encrypt(aes_gcm, Key, Ivec, {AAD, PlainText, TagLength}) -> {CipherText, CipherTag}</name>
+ <name>block_encrypt(aes_gcm | aes_ccm, Key, Ivec, {AAD, PlainText, TagLength}) -> {CipherText, CipherTag}</name>
<fsummary>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher</fsummary>
<type>
- <v>Type = block_cipher() </v>
- <v>AeadType = aead_cipher() </v>
- <v>Key = block_key() </v>
- <v>PlainText = iodata() </v>
+ <v>Type = <seealso marker="#type-block_cipher_with_iv">block_cipher_with_iv()</seealso></v>
+ <v>AeadType = <seealso marker="#type-aead_cipher">aead_cipher()</seealso></v>
+ <v>Key = <seealso marker="#type-key">key()</seealso> | <seealso marker="#type-des3_key">des3_key()</seealso></v>
+ <v>PlainText = iodata()</v>
<v>AAD = IVec = CipherText = CipherTag = binary()</v>
<v>TagLength = 1..16</v>
</type>
@@ -222,8 +559,11 @@
<p>In AEAD (Authenticated Encryption with Associated Data) mode, encrypt
<c>PlainText</c>according to <c>Type</c> block cipher and calculate
<c>CipherTag</c> that also authenticates the <c>AAD</c> (Associated Authenticated Data).</p>
- <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying OpenSSL implementation.</p>
+ <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
+ is not supported by the underlying libcrypto implementation.</p>
+ <p>For keylengths, iv-sizes and blocksizes see the
+ <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
@@ -232,10 +572,10 @@
<name>block_decrypt(AeadType, Key, Ivec, {AAD, CipherText, CipherTag}) -> PlainText | error</name>
<fsummary>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher</fsummary>
<type>
- <v>Type = block_cipher() </v>
- <v>AeadType = aead_cipher() </v>
- <v>Key = block_key() </v>
- <v>PlainText = iodata() </v>
+ <v>Type = <seealso marker="#type-block_cipher_with_iv">block_cipher_with_iv()</seealso></v>
+ <v>AeadType = <seealso marker="#type-aead_cipher">aead_cipher()</seealso></v>
+ <v>Key = <seealso marker="#type-key">key()</seealso> | <seealso marker="#type-des3_key">des3_key()</seealso></v>
+ <v>PlainText = iodata()</v>
<v>AAD = IVec = CipherText = CipherTag = binary()</v>
</type>
<desc>
@@ -245,19 +585,17 @@
<c>CipherText</c>according to <c>Type</c> block cipher and check the authenticity
the <c>PlainText</c> and <c>AAD</c> (Associated Authenticated Data) using the
<c>CipherTag</c>. May return <c>error</c> if the decryption or validation fail's</p>
- <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying OpenSSL implementation.</p>
+ <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
+ is not supported by the underlying libcrypto implementation.</p>
+ <p>For keylengths, iv-sizes and blocksizes see the
+ <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
-
+
<func>
- <name>bytes_to_integer(Bin) -> Integer </name>
+ <name name="bytes_to_integer" arity="1"/>
<fsummary>Convert binary representation, of an integer, to an Erlang integer.</fsummary>
- <type>
- <v>Bin = binary() - as returned by crypto functions</v>
-
- <v>Integer = integer() </v>
- </type>
<desc>
<p>Convert binary representation, of an integer, to an Erlang integer.
</p>
@@ -265,17 +603,8 @@
</func>
<func>
- <name>compute_key(Type, OthersPublicKey, MyKey, Params) -> SharedSecret</name>
+ <name name="compute_key" arity="4"/>
<fsummary>Computes the shared secret</fsummary>
- <type>
- <v> Type = dh | ecdh | srp </v>
- <v>OthersPublicKey = dh_public() | ecdh_public() | srp_public() </v>
- <v>MyKey = dh_private() | ecdh_private() | {srp_public(),srp_private()}</v>
- <v>Params = dh_params() | ecdh_params() | SrpUserParams | SrpHostParams</v>
- <v>SrpUserParams = {user, [DerivedKey::binary(), Prime::binary(), Generator::binary(), Version::atom() | [Scrambler:binary()]]} </v>
- <v>SrpHostParams = {host, [Verifier::binary(), Prime::binary(), Version::atom() | [Scrambler::binary]]} </v>
- <v>SharedSecret = binary()</v>
- </type>
<desc>
<p>Computes the shared secret from the private key and the other party's public key.
See also <seealso marker="public_key:public_key#compute_key-2">public_key:compute_key/2</seealso>
@@ -284,85 +613,61 @@
</func>
<func>
- <name>exor(Data1, Data2) -> Result</name>
+ <name name="exor" arity="2"/>
<fsummary>XOR data</fsummary>
- <type>
- <v>Data1, Data2 = iodata()</v>
- <v>Result = binary()</v>
- </type>
<desc>
<p>Performs bit-wise XOR (exclusive or) on the data supplied.</p>
</desc>
</func>
- <func>
- <name>generate_key(Type, Params) -> {PublicKey, PrivKeyOut} </name>
- <name>generate_key(Type, Params, PrivKeyIn) -> {PublicKey, PrivKeyOut} </name>
+
+ <func>
+ <name name="generate_key" arity="2"/>
+ <name name="generate_key" arity="3"/>
<fsummary>Generates a public key of type <c>Type</c></fsummary>
- <type>
- <v> Type = dh | ecdh | rsa | srp </v>
- <v>Params = dh_params() | ecdh_params() | RsaParams | SrpUserParams | SrpHostParams </v>
- <v>RsaParams = {ModulusSizeInBits::integer(), PublicExponent::key_value()}</v>
- <v>SrpUserParams = {user, [Generator::binary(), Prime::binary(), Version::atom()]}</v>
- <v>SrpHostParams = {host, [Verifier::binary(), Generator::binary(), Prime::binary(), Version::atom()]}</v>
- <v>PublicKey = dh_public() | ecdh_public() | rsa_public() | srp_public() </v>
- <v>PrivKeyIn = undefined | dh_private() | ecdh_private() | srp_private() </v>
- <v>PrivKeyOut = dh_private() | ecdh_private() | rsa_private() | srp_private() </v>
- </type>
<desc>
<p>Generates a public key of type <c>Type</c>.
See also <seealso marker="public_key:public_key#generate_key-1">public_key:generate_key/1</seealso>.
- May throw exception an exception of class <c>error</c>:
+ May raise exception:
</p>
<list type="bulleted">
- <item><c>badarg</c>: an argument is of wrong type or has an illegal value,</item>
- <item><c>low_entropy</c>: the random generator failed due to lack of secure "randomness",</item>
- <item><c>computation_failed</c>: the computation fails of another reason than <c>low_entropy</c>.</item>
+ <item><c>error:badarg</c>: an argument is of wrong type or has an illegal value,</item>
+ <item><c>error:low_entropy</c>: the random generator failed due to lack of secure "randomness",</item>
+ <item><c>error:computation_failed</c>: the computation fails of another reason than <c>low_entropy</c>.</item>
</list>
<note>
<p>RSA key generation is only available if the runtime was
built with dirty scheduler support. Otherwise, attempting to
- generate an RSA key will throw exception <c>error:notsup</c>.</p>
+ generate an RSA key will raise exception <c>error:notsup</c>.</p>
</note>
</desc>
</func>
<func>
- <name>hash(Type, Data) -> Digest</name>
+ <name name="hash" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Type = md4 | hash_algorithms()</v>
- <v>Data = iodata()</v>
- <v>Digest = binary()</v>
- </type>
<desc>
<p>Computes a message digest of type <c>Type</c> from <c>Data</c>.</p>
- <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying OpenSSL implementation.</p>
+ <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
+ is not supported by the underlying libcrypto implementation.</p>
</desc>
</func>
<func>
- <name>hash_init(Type) -> Context</name>
+ <name name="hash_init" arity="1"/>
<fsummary></fsummary>
- <type>
- <v>Type = md4 | hash_algorithms()</v>
- </type>
<desc>
<p>Initializes the context for streaming hash operations. <c>Type</c> determines
which digest to use. The returned context should be used as argument
to <seealso marker="#hash_update-2">hash_update</seealso>.</p>
- <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying OpenSSL implementation.</p>
+ <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
+ is not supported by the underlying libcrypto implementation.</p>
</desc>
</func>
<func>
- <name>hash_update(Context, Data) -> NewContext</name>
+ <name name="hash_update" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Data = iodata()</v>
- </type>
<desc>
<p>Updates the digest represented by <c>Context</c> using the given <c>Data</c>. <c>Context</c>
must have been generated using <seealso marker="#hash_init-1">hash_init</seealso>
@@ -371,12 +676,10 @@
or <seealso marker="#hash_final-1">hash_final</seealso>.</p>
</desc>
</func>
+
<func>
- <name>hash_final(Context) -> Digest</name>
+ <name name="hash_final" arity="1"/>
<fsummary></fsummary>
- <type>
- <v>Digest = binary()</v>
- </type>
<desc>
<p>Finalizes the hash operation referenced by <c>Context</c> returned
from a previous call to <seealso marker="#hash_update-2">hash_update</seealso>.
@@ -386,16 +689,9 @@
</func>
<func>
- <name>hmac(Type, Key, Data) -> Mac</name>
- <name>hmac(Type, Key, Data, MacLength) -> Mac</name>
+ <name name="hmac" arity="3"/>
+ <name name="hmac" arity="4"/>
<fsummary></fsummary>
- <type>
- <v>Type = hash_algorithms() - except ripemd160</v>
- <v>Key = iodata()</v>
- <v>Data = iodata()</v>
- <v>MacLength = integer()</v>
- <v>Mac = binary()</v>
- </type>
<desc>
<p>Computes a HMAC of type <c>Type</c> from <c>Data</c> using
<c>Key</c> as the authentication key.</p> <p><c>MacLength</c>
@@ -404,13 +700,8 @@
</func>
<func>
- <name>hmac_init(Type, Key) -> Context</name>
+ <name name="hmac_init" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Type = hash_algorithms() - except ripemd160</v>
- <v>Key = iodata()</v>
- <v>Context = binary()</v>
- </type>
<desc>
<p>Initializes the context for streaming HMAC operations. <c>Type</c> determines
which hash function to use in the HMAC operation. <c>Key</c> is the authentication
@@ -419,15 +710,11 @@
</func>
<func>
- <name>hmac_update(Context, Data) -> NewContext</name>
+ <name name="hmac_update" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Context = NewContext = binary()</v>
- <v>Data = iodata()</v>
- </type>
<desc>
<p>Updates the HMAC represented by <c>Context</c> using the given <c>Data</c>. <c>Context</c>
- must have been generated using an HMAC init function (such as
+ must have been generated using an HMAC init function (such as
<seealso marker="#hmac_init-2">hmac_init</seealso>). <c>Data</c> can be any length. <c>NewContext</c>
must be passed into the next call to <c>hmac_update</c>
or to one of the functions <seealso marker="#hmac_final-1">hmac_final</seealso> and
@@ -437,16 +724,13 @@
call to hmac_update or hmac_final. The semantics of reusing old contexts
in any way is undefined and could even crash the VM in earlier releases.
The reason for this limitation is a lack of support in the underlying
- OpenSSL API.</p></warning>
+ libcrypto API.</p></warning>
</desc>
</func>
<func>
- <name>hmac_final(Context) -> Mac</name>
+ <name name="hmac_final" arity="1"/>
<fsummary></fsummary>
- <type>
- <v>Context = Mac = binary()</v>
- </type>
<desc>
<p>Finalizes the HMAC operation referenced by <c>Context</c>. The size of the resultant MAC is
determined by the type of hash function used to generate it.</p>
@@ -454,12 +738,8 @@
</func>
<func>
- <name>hmac_final_n(Context, HashLen) -> Mac</name>
+ <name name="hmac_final_n" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Context = Mac = binary()</v>
- <v>HashLen = non_neg_integer()</v>
- </type>
<desc>
<p>Finalizes the HMAC operation referenced by <c>Context</c>. <c>HashLen</c> must be greater than
zero. <c>Mac</c> will be a binary with at most <c>HashLen</c> bytes. Note that if HashLen is greater than the actual number of bytes returned from the underlying hash, the returned hash will have fewer than <c>HashLen</c> bytes.</p>
@@ -467,16 +747,9 @@
</func>
<func>
- <name>cmac(Type, Key, Data) -> Mac</name>
- <name>cmac(Type, Key, Data, MacLength) -> Mac</name>
+ <name name="cmac" arity="3"/>
+ <name name="cmac" arity="4"/>
<fsummary>Calculates the Cipher-based Message Authentication Code.</fsummary>
- <type>
- <v>Type = block_cipher()</v>
- <v>Key = iodata()</v>
- <v>Data = iodata()</v>
- <v>MacLength = integer()</v>
- <v>Mac = binary()</v>
- </type>
<desc>
<p>Computes a CMAC of type <c>Type</c> from <c>Data</c> using
<c>Key</c> as the authentication key.</p> <p><c>MacLength</c>
@@ -485,20 +758,21 @@
</func>
<func>
- <name>info_fips() -> Status</name>
+ <name name="info_fips" arity="0"/>
<fsummary>Provides information about the FIPS operating status.</fsummary>
- <type>
- <v>Status = enabled | not_enabled | not_supported</v>
- </type>
<desc>
<p>Provides information about the FIPS operating status of
- crypto and the underlying OpenSSL library. If crypto was built
+ crypto and the underlying libcrypto library. If crypto was built
with FIPS support this can be either <c>enabled</c> (when
running in FIPS mode) or <c>not_enabled</c>. For other builds
- this value is always <c>not_supported</c>.</p>
+ this value is always <c>not_supported</c>.
+ </p>
+ <p>See <seealso marker="#enable_fips_mode-1">enable_fips_mode/1</seealso> about how to enable
+ FIPS mode.
+ </p>
<warning>
<p>In FIPS mode all non-FIPS compliant algorithms are
- disabled and throw exception <c>not_supported</c>. Check
+ disabled and raise exception <c>error:notsup</c>. Check
<seealso marker="#supports-0">supports</seealso> that in
FIPS mode returns the restricted list of available
algorithms.</p>
@@ -507,13 +781,23 @@
</func>
<func>
- <name>info_lib() -> [{Name,VerNum,VerStr}]</name>
+ <name name="enable_fips_mode" arity="1"/>
+ <fsummary>Change FIPS mode.</fsummary>
+ <desc>
+ <p>Enables (<c>Enable = true</c>) or disables (<c>Enable = false</c>) FIPS mode. Returns <c>true</c> if
+ the operation was successful or <c>false</c> otherwise.
+ </p>
+ <p>Note that to enable FIPS mode succesfully, OTP must be built with the configure option <c>--enable-fips</c>,
+ and the underlying libcrypto must also support FIPS.
+ </p>
+ <p>See also <seealso marker="#info_fips-0">info_fips/0</seealso>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="info_lib" arity="0"/>
<fsummary>Provides information about the libraries used by crypto.</fsummary>
- <type>
- <v>Name = binary()</v>
- <v>VerNum = integer()</v>
- <v>VerStr = binary()</v>
- </type>
<desc>
<p>Provides the name and version of the libraries used by crypto.</p>
<p><c>Name</c> is the name of the library. <c>VerNum</c> is
@@ -526,52 +810,45 @@
<note><p>
From OTP R16 the <em>numeric version</em> represents the version of the OpenSSL
<em>header files</em> (<c>openssl/opensslv.h</c>) used when crypto was compiled.
- The text variant represents the OpenSSL library used at runtime.
+ The text variant represents the libcrypto library used at runtime.
In earlier OTP versions both numeric and text was taken from the library.
</p></note>
</desc>
</func>
<func>
- <name>mod_pow(N, P, M) -> Result</name>
+ <name name="mod_pow" arity="3"/>
<fsummary>Computes the function: N^P mod M</fsummary>
- <type>
- <v>N, P, M = binary() | integer()</v>
- <v>Result = binary() | error</v>
- </type>
<desc>
<p>Computes the function <c>N^P mod M</c>.</p>
</desc>
</func>
<func>
- <name>next_iv(Type, Data) -> NextIVec</name>
- <name>next_iv(Type, Data, IVec) -> NextIVec</name>
- <fsummary></fsummary>
- <type>
- <v>Type = des_cbc | des3_cbc | aes_cbc | des_cfb</v>
- <v>Data = iodata()</v>
- <v>IVec = NextIVec = binary()</v>
- </type>
- <desc>
- <p>Returns the initialization vector to be used in the next
- iteration of encrypt/decrypt of type <c>Type</c>. <c>Data</c> is the
- encrypted data from the previous iteration step. The <c>IVec</c>
- argument is only needed for <c>des_cfb</c> as the vector used
- in the previous iteration step.</p>
- </desc>
+ <name name="next_iv" arity="2"/>
+ <name name="next_iv" arity="3"/>
+ <fsummary></fsummary>
+ <desc>
+ <p>Returns the initialization vector to be used in the next
+ iteration of encrypt/decrypt of type <c>Type</c>. <c>Data</c> is the
+ encrypted data from the previous iteration step. The <c>IVec</c>
+ argument is only needed for <c>des_cfb</c> as the vector used
+ in the previous iteration step.</p>
+ </desc>
</func>
<func>
- <name>private_decrypt(Type, CipherText, PrivateKey, Padding) -> PlainText</name>
+ <name name="poly1305" arity="2"/>
+ <fsummary></fsummary>
+ <desc>
+ <p>Computes a POLY1305 message authentication code (<c>Mac</c>) from <c>Data</c> using
+ <c>Key</c> as the authentication key.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="private_decrypt" arity="4"/>
<fsummary>Decrypts CipherText using the private Key.</fsummary>
- <type>
- <v>Type = rsa</v>
- <v>CipherText = binary()</v>
- <v>PrivateKey = rsa_private()</v>
- <v>Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding</v>
- <v>PlainText = binary()</v>
- </type>
<desc>
<p>Decrypts the <c>CipherText</c>, encrypted with
<seealso marker="#public_encrypt-4">public_encrypt/4</seealso> (or equivalent function)
@@ -582,21 +859,10 @@
</p>
</desc>
</func>
-
+
<func>
- <name>private_encrypt(Type, PlainText, PrivateKey, Padding) -> CipherText</name>
+ <name name="private_encrypt" arity="4"/>
<fsummary>Encrypts PlainText using the private Key.</fsummary>
- <type>
- <v>Type = rsa</v>
- <v>PlainText = binary()</v>
- <d> The size of the <c>PlainText</c> must be less
- than <c>byte_size(N)-11</c> if <c>rsa_pkcs1_padding</c> is
- used, and <c>byte_size(N)</c> if <c>rsa_no_padding</c> is
- used, where N is public modulus of the RSA key.</d>
- <v>PrivateKey = rsa_private()</v>
- <v>Padding = rsa_pkcs1_padding | rsa_no_padding</v>
- <v>CipherText = binary()</v>
- </type>
<desc>
<p>Encrypts the <c>PlainText</c> using the <c>PrivateKey</c>
and returns the ciphertext. This is a low level signature operation
@@ -606,16 +872,10 @@
</p>
</desc>
</func>
+
<func>
- <name>public_decrypt(Type, CipherText, PublicKey, Padding) -> PlainText</name>
+ <name name="public_decrypt" arity="4"/>
<fsummary>Decrypts CipherText using the public Key.</fsummary>
- <type>
- <v>Type = rsa</v>
- <v>CipherText = binary()</v>
- <v>PublicKey = rsa_public() </v>
- <v>Padding = rsa_pkcs1_padding | rsa_no_padding</v>
- <v>PlainText = binary()</v>
- </type>
<desc>
<p>Decrypts the <c>CipherText</c>, encrypted with
<seealso marker="#private_encrypt-4">private_encrypt/4</seealso>(or equivalent function)
@@ -628,19 +888,8 @@
</func>
<func>
- <name>public_encrypt(Type, PlainText, PublicKey, Padding) -> CipherText</name>
+ <name name="public_encrypt" arity="4"/>
<fsummary>Encrypts PlainText using the public Key.</fsummary>
- <type>
- <v>Type = rsa</v>
- <v>PlainText = binary()</v>
- <d> The size of the <c>PlainText</c> must be less
- than <c>byte_size(N)-11</c> if <c>rsa_pkcs1_padding</c> is
- used, and <c>byte_size(N)</c> if <c>rsa_no_padding</c> is
- used, where N is public modulus of the RSA key.</d>
- <v>PublicKey = rsa_public()</v>
- <v>Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding</v>
- <v>CipherText = binary()</v>
- </type>
<desc>
<p>Encrypts the <c>PlainText</c> (message digest) using the <c>PublicKey</c>
and returns the <c>CipherText</c>. This is a low level signature operation
@@ -651,18 +900,15 @@
</func>
<func>
- <name>rand_seed(Seed) -> ok</name>
+ <name name="rand_seed" arity="1"/>
<fsummary>Set the seed for random bytes generation</fsummary>
- <type>
- <v>Seed = binary()</v>
- </type>
<desc>
<p>Set the seed for PRNG to the given binary. This calls the
RAND_seed function from openssl. Only use this if the system
you are running on does not have enough "randomness" built in.
Normally this is when
<seealso marker="#strong_rand_bytes/1">strong_rand_bytes/1</seealso>
- throws <c>low_entropy</c></p>
+ raises <c>error:low_entropy</c></p>
</desc>
</func>
@@ -680,34 +926,15 @@
</func>
<func>
- <name>sign(Algorithm, DigestType, Msg, Key) -> binary()</name>
- <fsummary> Create digital signature.</fsummary>
- <type>
- <v>Algorithm = rsa | dss | ecdsa </v>
- <v>Msg = binary() | {digest,binary()}</v>
- <d>The msg is either the binary "cleartext" data to be
- signed or it is the hashed value of "cleartext" i.e. the
- digest (plaintext).</d>
- <v>DigestType = digest_type()</v>
- <v>Key = rsa_private() | dss_private() | [ecdh_private(),ecdh_params()]</v>
- </type>
- <desc>
- <p>Creates a digital signature.</p>
- <p>Algorithm <c>dss</c> can only be used together with digest type
- <c>sha</c>.</p>
- <p>See also <seealso marker="public_key:public_key#sign-3">public_key:sign/3</seealso>.</p>
- </desc>
- </func>
-
- <func>
- <name>start() -> ok</name>
+ <name name="start" arity="0"/>
<fsummary> Equivalent to application:start(crypto). </fsummary>
<desc>
<p> Equivalent to application:start(crypto).</p>
</desc>
</func>
+
<func>
- <name>stop() -> ok</name>
+ <name name="stop" arity="0"/>
<fsummary> Equivalent to application:stop(crypto).</fsummary>
<desc>
<p> Equivalent to application:stop(crypto).</p>
@@ -715,23 +942,20 @@
</func>
<func>
- <name>strong_rand_bytes(N) -> binary()</name>
+ <name name="strong_rand_bytes" arity="1"/>
<fsummary>Generate a binary of random bytes</fsummary>
- <type>
- <v>N = integer()</v>
- </type>
<desc>
<p>Generates N bytes randomly uniform 0..255, and returns the
result in a binary. Uses a cryptographically secure prng seeded and
periodically mixed with operating system provided entropy. By default
this is the <c>RAND_bytes</c> method from OpenSSL.</p>
- <p>May throw exception <c>low_entropy</c> in case the random generator
+ <p>May raise exception <c>error:low_entropy</c> in case the random generator
failed due to lack of secure "randomness".</p>
</desc>
</func>
<func>
- <name>rand_seed() -> rand:state()</name>
+ <name name="rand_seed" arity="0"/>
<fsummary>Strong random number generation plugin state</fsummary>
<desc>
<p>
@@ -739,9 +963,16 @@
<seealso marker="stdlib:rand">random number generation</seealso>,
in order to generate cryptographically strong random numbers
(based on OpenSSL's <c>BN_rand_range</c>),
- and saves it on process dictionary before returning it as well.
+ and saves it in the process dictionary before returning it as well.
See also
- <seealso marker="stdlib:rand#seed-1">rand:seed/1</seealso>.
+ <seealso marker="stdlib:rand#seed-1">rand:seed/1</seealso> and
+ <seealso marker="#rand_seed_s-0">rand_seed_s/0</seealso>.
+ </p>
+ <p>
+ When using the state object from this function the
+ <seealso marker="stdlib:rand">rand</seealso> functions using it
+ may raise exception <c>error:low_entropy</c> in case the random generator
+ failed due to lack of secure "randomness".
</p>
<p><em>Example</em></p>
<pre>
@@ -752,7 +983,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>rand_seed_s() -> rand:state()</name>
+ <name name="rand_seed_s" arity="0"/>
<fsummary>Strong random number generation plugin state</fsummary>
<desc>
<p>
@@ -763,49 +994,154 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
See also
<seealso marker="stdlib:rand#seed_s-1">rand:seed_s/1</seealso>.
</p>
+ <p>
+ When using the state object from this function the
+ <seealso marker="stdlib:rand">rand</seealso> functions using it
+ may raise exception <c>error:low_entropy</c> in case the random generator
+ failed due to lack of secure "randomness".
+ </p>
+ <note>
+ <p>
+ The state returned from this function can not be used
+ to get a reproducable random sequence as from
+ the other
+ <seealso marker="stdlib:rand">rand</seealso>
+ functions,
+ since reproducability does not match cryptographically safe.
+ </p>
+ <p>
+ The only supported usage is to generate one distinct
+ random sequence from this start state.
+ </p>
+ </note>
</desc>
</func>
<func>
- <name>stream_init(Type, Key) -> State</name>
- <fsummary></fsummary>
+ <name>rand_seed_alg(Alg) -> rand:state()</name>
+ <fsummary>Strong random number generation plugin state</fsummary>
+ <type>
+ <v>Alg = crypto | crypto_cache</v>
+ </type>
+ <desc>
+ <marker id="rand_seed_alg-1" />
+ <p>
+ Creates state object for
+ <seealso marker="stdlib:rand">random number generation</seealso>,
+ in order to generate cryptographically strong random numbers.
+ See also
+ <seealso marker="stdlib:rand#seed-1">rand:seed/1</seealso> and
+ <seealso marker="#rand_seed_alg_s-1">rand_seed_alg_s/1</seealso>.
+ </p>
+ <p>
+ When using the state object from this function the
+ <seealso marker="stdlib:rand">rand</seealso> functions using it
+ may raise exception <c>error:low_entropy</c> in case the random generator
+ failed due to lack of secure "randomness".
+ </p>
+ <p>
+ The cache size can be changed from its default value using the
+ <seealso marker="crypto_app">
+ crypto app's
+ </seealso> configuration parameter <c>rand_cache_size</c>.
+ </p>
+ <p><em>Example</em></p>
+ <pre>
+_ = crypto:rand_seed_alg(crypto_cache),
+_IntegerValue = rand:uniform(42), % [1; 42]
+_FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
+ </desc>
+ </func>
+
+ <func>
+ <name>rand_seed_alg_s(Alg) -> rand:state()</name>
+ <fsummary>Strong random number generation plugin state</fsummary>
<type>
- <v>Type = rc4 </v>
- <v>State = opaque() </v>
- <v>Key = iodata()</v>
+ <v>Alg = crypto | crypto_cache</v>
</type>
<desc>
+ <marker id="rand_seed_alg_s-1" />
+ <p>
+ Creates state object for
+ <seealso marker="stdlib:rand">random number generation</seealso>,
+ in order to generate cryptographically strongly random numbers.
+ See also
+ <seealso marker="stdlib:rand#seed_s-1">rand:seed_s/1</seealso>.
+ </p>
+ <p>
+ If <c>Alg</c> is <c>crypto</c> this function behaves exactly like
+ <seealso marker="#rand_seed_s-0">rand_seed_s/0</seealso>.
+ </p>
+ <p>
+ If <c>Alg</c> is <c>crypto_cache</c> this function
+ fetches random data with OpenSSL's <c>RAND_bytes</c>
+ and caches it for speed using an internal word size
+ of 56 bits that makes calculations fast on 64 bit machines.
+ </p>
+ <p>
+ When using the state object from this function the
+ <seealso marker="stdlib:rand">rand</seealso> functions using it
+ may raise exception <c>error:low_entropy</c> in case the random generator
+ failed due to lack of secure "randomness".
+ </p>
+ <p>
+ The cache size can be changed from its default value using the
+ <seealso marker="crypto_app">
+ crypto app's
+ </seealso> configuration parameter <c>rand_cache_size</c>.
+ </p>
+ <note>
+ <p>
+ The state returned from this function can not be used
+ to get a reproducable random sequence as from
+ the other
+ <seealso marker="stdlib:rand">rand</seealso>
+ functions,
+ since reproducability does not match cryptographically safe.
+ </p>
+ <p>
+ In fact since random data is cached some numbers may
+ get reproduced if you try, but this is unpredictable.
+ </p>
+ <p>
+ The only supported usage is to generate one distinct
+ random sequence from this start state.
+ </p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
+ <name name="stream_init" arity="2"/>
+ <fsummary></fsummary>
+ <desc>
<p>Initializes the state for use in RC4 stream encryption
<seealso marker="#stream_encrypt-2">stream_encrypt</seealso> and
<seealso marker="#stream_decrypt-2">stream_decrypt</seealso></p>
+ <p>For keylengths see the
+ <seealso marker="crypto:algorithm_details#stream-ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
<func>
- <name>stream_init(Type, Key, IVec) -> State</name>
+ <name name="stream_init" arity="3"/>
<fsummary></fsummary>
- <type>
- <v>Type = aes_ctr </v>
- <v>State = opaque() </v>
- <v>Key = iodata()</v>
- <v>IVec = binary()</v>
- </type>
<desc>
<p>Initializes the state for use in streaming AES encryption using Counter mode (CTR).
<c>Key</c> is the AES key and must be either 128, 192, or 256 bits long. <c>IVec</c> is
an arbitrary initializing vector of 128 bits (16 bytes). This state is for use with
<seealso marker="#stream_encrypt-2">stream_encrypt</seealso> and
<seealso marker="#stream_decrypt-2">stream_decrypt</seealso>.</p>
+ <p>For keylengths and iv-sizes see the
+ <seealso marker="crypto:algorithm_details#stream-ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
<func>
- <name>stream_encrypt(State, PlainText) -> { NewState, CipherText}</name>
+ <name name="stream_encrypt" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Text = iodata()</v>
- <v>CipherText = binary()</v>
- </type>
<desc>
<p>Encrypts <c>PlainText</c> according to the stream cipher <c>Type</c> specified in stream_init/3.
<c>Text</c> can be any number of bytes. The initial <c>State</c> is created using
@@ -815,12 +1151,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>stream_decrypt(State, CipherText) -> { NewState, PlainText }</name>
+ <name name="stream_decrypt" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>CipherText = iodata()</v>
- <v>PlainText = binary()</v>
- </type>
<desc>
<p>Decrypts <c>CipherText</c> according to the stream cipher <c>Type</c> specified in stream_init/3.
<c>PlainText</c> can be any number of bytes. The initial <c>State</c> is created using
@@ -830,57 +1162,57 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>supports() -> AlgorithmList </name>
+ <name name="supports" arity="0"/>
<fsummary>Provide a list of available crypto algorithms.</fsummary>
- <type>
- <v> AlgorithmList = [{hashs, [hash_algorithms()]},
- {ciphers, [cipher_algorithms()]},
- {public_keys, [public_key_algorithms()]}
- </v>
- </type>
<desc>
<p> Can be used to determine which crypto algorithms that are supported
- by the underlying OpenSSL library</p>
+ by the underlying libcrypto library</p>
+ <p>Note: the <c>rsa_opts</c> entry is in an experimental state and may change or be removed without notice.
+ No guarantee for the accuarcy of the rsa option's value list should be assumed.
+ </p>
</desc>
</func>
<func>
- <name>ec_curves() -> EllipticCurveList </name>
+ <name name="ec_curves" arity="0"/>
<fsummary>Provide a list of available named elliptic curves.</fsummary>
- <type>
- <v>EllipticCurveList = [ec_named_curve()]</v>
- </type>
<desc>
<p>Can be used to determine which named elliptic curves are supported.</p>
</desc>
</func>
<func>
- <name>ec_curve(NamedCurve) -> EllipticCurve </name>
+ <name name="ec_curve" arity="1"/>
<fsummary>Get the defining parameters of a elliptic curve.</fsummary>
- <type>
- <v>NamedCurve = ec_named_curve()</v>
- <v>EllipticCurve = ec_explicit_curve()</v>
- </type>
<desc>
<p>Return the defining parameters of a elliptic curve.</p>
</desc>
</func>
- <func>
- <name>verify(Algorithm, DigestType, Msg, Signature, Key) -> boolean()</name>
+ <func>
+ <name name="sign" arity="4"/>
+ <name name="sign" arity="5"/>
+ <fsummary> Create digital signature.</fsummary>
+ <desc>
+ <p>Creates a digital signature.</p>
+ <p>The msg is either the binary "cleartext" data to be
+ signed or it is the hashed value of "cleartext" i.e. the
+ digest (plaintext).</p>
+ <p>Algorithm <c>dss</c> can only be used together with digest type
+ <c>sha</c>.</p>
+ <p>See also <seealso marker="public_key:public_key#sign-3">public_key:sign/3</seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="verify" arity="5"/>
+ <name name="verify" arity="6"/>
<fsummary>Verifies a digital signature.</fsummary>
- <type>
- <v> Algorithm = rsa | dss | ecdsa </v>
- <v>Msg = binary() | {digest,binary()}</v>
- <d>The msg is either the binary "cleartext" data
- or it is the hashed value of "cleartext" i.e. the digest (plaintext).</d>
- <v>DigestType = digest_type()</v>
- <v>Signature = binary()</v>
- <v>Key = rsa_public() | dss_public() | [ecdh_public(),ecdh_params()]</v>
- </type>
<desc>
<p>Verifies a digital signature</p>
+ <p>The msg is either the binary "cleartext" data to be
+ signed or it is the hashed value of "cleartext" i.e. the
+ digest (plaintext).</p>
<p>Algorithm <c>dss</c> can only be used together with digest type
<c>sha</c>.</p>
@@ -888,78 +1220,317 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</desc>
</func>
+ <!-- Engine functions -->
+ <func>
+ <name name="privkey_to_pubkey" arity="2"/>
+ <fsummary>Fetches a public key from an Engine stored private key.</fsummary>
+ <desc>
+ <p>Fetches the corresponding public key from a private key stored in an Engine.
+ The key must be of the type indicated by the Type parameter.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_get_all_methods" arity="0"/>
+ <fsummary>Return list of all possible engine methods</fsummary>
+ <desc>
+ <p>
+ Returns a list of all possible engine methods.
+ </p>
+ <p>
+ May raise exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_load" arity="3"/>
+ <fsummary>Dynamical load an encryption engine</fsummary>
+ <desc>
+ <p>
+ Loads the OpenSSL engine given by <c>EngineId</c> if it is available and then returns ok and
+ an engine handle. This function is the same as calling <c>engine_load/4</c> with
+ <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
+ returned if the engine can't be loaded.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_load" arity="4"/>
+ <fsummary>Dynamical load an encryption engine</fsummary>
+ <desc>
+ <p>
+ Loads the OpenSSL engine given by <c>EngineId</c> if it is available and then returns ok and
+ an engine handle. An error tuple is returned if the engine can't be loaded.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_unload" arity="1"/>
+ <fsummary>Dynamical load an encryption engine</fsummary>
+ <desc>
+ <p>
+ Unloads the OpenSSL engine given by <c>Engine</c>.
+ An error tuple is returned if the engine can't be unloaded.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameter is in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_by_id" arity="1"/>
+ <fsummary>Get a reference to an already loaded engine</fsummary>
+ <desc>
+ <p>
+ Get a reference to an already loaded engine with <c>EngineId</c>.
+ An error tuple is returned if the engine can't be unloaded.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameter is in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_ctrl_cmd_string" arity="3"/>
+ <fsummary>Sends ctrl commands to an OpenSSL engine</fsummary>
+ <desc>
+ <p>
+ Sends ctrl commands to the OpenSSL engine given by <c>Engine</c>.
+ This function is the same as calling <c>engine_ctrl_cmd_string/4</c> with
+ <c>Optional</c> set to <c>false</c>.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_ctrl_cmd_string" arity="4"/>
+ <fsummary>Sends ctrl commands to an OpenSSL engine</fsummary>
+ <desc>
+ <p>
+ Sends ctrl commands to the OpenSSL engine given by <c>Engine</c>.
+ <c>Optional</c> is a boolean argument that can relax the semantics of the function.
+ If set to <c>true</c> it will only return failure if the ENGINE supported the given
+ command name but failed while executing it, if the ENGINE doesn't support the command
+ name it will simply return success without doing anything. In this case we assume
+ the user is only supplying commands specific to the given ENGINE so we set this to
+ <c>false</c>.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_add" arity="1"/>
+ <fsummary>Add engine to OpenSSL internal list</fsummary>
+ <desc>
+ <p>Add the engine to OpenSSL's internal list.</p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_remove" arity="1"/>
+ <fsummary>Remove engine to OpenSSL internal list</fsummary>
+ <desc>
+ <p>Remove the engine from OpenSSL's internal list.</p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_get_id" arity="1"/>
+ <fsummary>Fetch engine ID</fsummary>
+ <desc>
+ <p>Return the ID for the engine, or an empty binary if there is no id set.</p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_get_name" arity="1"/>
+ <fsummary>Fetch engine name</fsummary>
+ <desc>
+ <p>Return the name (eg a description) for the engine, or an empty binary if there is no name set.</p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_list" arity="0"/>
+ <fsummary>List the known engine ids</fsummary>
+ <desc>
+ <p>List the id's of all engines in OpenSSL's internal list.</p>
+ <p>
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ <p>
+ May raise exception <c>error:notsup</c> in case engine functionality is not supported by the underlying
+ OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="ensure_engine_loaded" arity="2"/>
+ <fsummary>Ensure encryption engine just loaded once</fsummary>
+ <desc>
+ <p>
+ Loads the OpenSSL engine given by <c>EngineId</c> and the path to the dynamic library
+ implementing the engine. This function is the same as calling <c>ensure_engine_loaded/3</c> with
+ <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
+ returned if the engine can't be loaded.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="ensure_engine_loaded" arity="3"/>
+ <fsummary>Ensure encryption engine just loaded once</fsummary>
+ <desc>
+ <p>
+ Loads the OpenSSL engine given by <c>EngineId</c> and the path to the dynamic library
+ implementing the engine. This function differs from the normal engine_load in that sense it
+ also add the engine id to the internal list in OpenSSL. Then in the following calls to the function
+ it just fetch the reference to the engine instead of loading it again.
+ An error tuple is returned if the engine can't be loaded.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="ensure_engine_unloaded" arity="1"/>
+ <fsummary>Unload an engine loaded with the ensure function</fsummary>
+ <desc>
+ <p>
+ Unloads an engine loaded with the <c>ensure_engine_loaded</c> function.
+ It both removes the label from the OpenSSL internal engine list and unloads the engine.
+ This function is the same as calling <c>ensure_engine_unloaded/2</c> with
+ <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
+ returned if the engine can't be unloaded.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="ensure_engine_unloaded" arity="2"/>
+ <fsummary>Unload an engine loaded with the ensure function</fsummary>
+ <desc>
+ <p>
+ Unloads an engine loaded with the <c>ensure_engine_loaded</c> function.
+ It both removes the label from the OpenSSL internal engine list and unloads the engine.
+ An error tuple is returned if the engine can't be unloaded.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
</funcs>
- <!-- Maybe put this in the users guide -->
- <!-- <section> -->
- <!-- <title>DES in CBC mode</title> -->
- <!-- <p>The Data Encryption Standard (DES) defines an algorithm for -->
- <!-- encrypting and decrypting an 8 byte quantity using an 8 byte key -->
- <!-- (actually only 56 bits of the key is used). -->
- <!-- </p> -->
- <!-- <p>When it comes to encrypting and decrypting blocks that are -->
- <!-- multiples of 8 bytes various modes are defined (NIST SP -->
- <!-- 800-38A). One of those modes is the Cipher Block Chaining (CBC) -->
- <!-- mode, where the encryption of an 8 byte segment depend not only -->
- <!-- of the contents of the segment itself, but also on the result of -->
- <!-- encrypting the previous segment: the encryption of the previous -->
- <!-- segment becomes the initializing vector of the encryption of the -->
- <!-- current segment. -->
- <!-- </p> -->
- <!-- <p>Thus the encryption of every segment depends on the encryption -->
- <!-- key (which is secret) and the encryption of the previous -->
- <!-- segment, except the first segment which has to be provided with -->
- <!-- an initial initializing vector. That vector could be chosen at -->
- <!-- random, or be a counter of some kind. It does not have to be -->
- <!-- secret. -->
- <!-- </p> -->
- <!-- <p>The following example is drawn from the old FIPS 81 standard -->
- <!-- (replaced by NIST SP 800-38A), where both the plain text and the -->
- <!-- resulting cipher text is settled. The following code fragment -->
- <!-- returns `true'. -->
- <!-- </p> -->
- <!-- <pre><![CDATA[ -->
-
- <!-- Key = <<16#01,16#23,16#45,16#67,16#89,16#ab,16#cd,16#ef>>, -->
- <!-- IVec = <<16#12,16#34,16#56,16#78,16#90,16#ab,16#cd,16#ef>>, -->
- <!-- P = "Now is the time for all ", -->
- <!-- C = crypto:des_cbc_encrypt(Key, IVec, P), -->
- <!-- % Which is the same as -->
- <!-- P1 = "Now is t", P2 = "he time ", P3 = "for all ", -->
- <!-- C1 = crypto:des_cbc_encrypt(Key, IVec, P1), -->
- <!-- C2 = crypto:des_cbc_encrypt(Key, C1, P2), -->
- <!-- C3 = crypto:des_cbc_encrypt(Key, C2, P3), -->
-
- <!-- C = <<C1/binary, C2/binary, C3/binary>>, -->
- <!-- C = <<16#e5,16#c7,16#cd,16#de,16#87,16#2b,16#f2,16#7c, -->
- <!-- 16#43,16#e9,16#34,16#00,16#8c,16#38,16#9c,16#0f, -->
- <!-- 16#68,16#37,16#88,16#49,16#9a,16#7c,16#05,16#f6>>, -->
- <!-- <<"Now is the time for all ">> == -->
- <!-- crypto:des_cbc_decrypt(Key, IVec, C). -->
- <!-- ]]></pre> -->
- <!-- <p>The following is true for the DES CBC mode. For all -->
- <!-- decompositions <c>P1 ++ P2 = P</c> of a plain text message -->
- <!-- <c>P</c> (where the length of all quantities are multiples of 8 -->
- <!-- bytes), the encryption <c>C</c> of <c>P</c> is equal to <c>C1 ++ -->
- <!-- C2</c>, where <c>C1</c> is obtained by encrypting <c>P1</c> with -->
- <!-- <c>Key</c> and the initializing vector <c>IVec</c>, and where -->
- <!-- <c>C2</c> is obtained by encrypting <c>P2</c> with <c>Key</c> -->
- <!-- and the initializing vector <c>last8(C1)</c>, -->
- <!-- where <c>last(Binary)</c> denotes the last 8 bytes of the -->
- <!-- binary <c>Binary</c>. -->
- <!-- </p> -->
- <!-- <p>Similarly, for all decompositions <c>C1 ++ C2 = C</c> of a -->
- <!-- cipher text message <c>C</c> (where the length of all quantities -->
- <!-- are multiples of 8 bytes), the decryption <c>P</c> of <c>C</c> -->
- <!-- is equal to <c>P1 ++ P2</c>, where <c>P1</c> is obtained by -->
- <!-- decrypting <c>C1</c> with <c>Key</c> and the initializing vector -->
- <!-- <c>IVec</c>, and where <c>P2</c> is obtained by decrypting -->
- <!-- <c>C2</c> with <c>Key</c> and the initializing vector -->
- <!-- <c>last8(C1)</c>, where <c>last8(Binary)</c> is as above. -->
- <!-- </p> -->
- <!-- <p>For DES3 (which uses three 64 bit keys) the situation is the -->
- <!-- same. -->
- <!-- </p> -->
- <!-- </section> -->
-</erlref>
+</erlref>
diff --git a/lib/crypto/doc/src/crypto_app.xml b/lib/crypto/doc/src/crypto_app.xml
index ba22557480..8296b1bc77 100644
--- a/lib/crypto/doc/src/crypto_app.xml
+++ b/lib/crypto/doc/src/crypto_app.xml
@@ -68,6 +68,24 @@
thus the crypto module will fail to load. This mechanism
prevents the accidental use of non-validated algorithms.</p>
</item>
+ <tag><c>rand_cache_size = integer()</c></tag>
+ <item>
+ <p>
+ Sets the cache size in bytes to use by
+ <seealso marker="crypto#rand_seed_alg-1">
+ <c>crypto:rand_seed_alg(crypto_cache)</c>
+ </seealso> and
+ <seealso marker="crypto#rand_seed_alg_s-1">
+ <c>crypto:rand_seed_alg_s(crypto_cache)</c>
+ </seealso>.
+ This parameter is read when a seed function is called,
+ and then kept in generators state object. It has a rather
+ small default value that causes reads of strong random bytes
+ about once per hundred calls for a random value.
+ The set value is rounded up to an integral number of words
+ of the size these seed functions use.
+ </p>
+ </item>
</taglist>
</section>
diff --git a/lib/crypto/doc/src/engine_keys.xml b/lib/crypto/doc/src/engine_keys.xml
new file mode 100644
index 0000000000..feeb353d1e
--- /dev/null
+++ b/lib/crypto/doc/src/engine_keys.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2017</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+ </legalnotice>
+ <title>Engine Stored Keys</title>
+ <prepared>Hans Nilsson</prepared>
+ <date>2017-11-10</date>
+ <file>engine_keys.xml</file>
+ </header>
+ <p>
+ <marker id="engine_key"></marker>
+ This chapter describes the support in the crypto application for using public and private keys stored in encryption engines.
+ </p>
+
+ <section>
+ <title>Background</title>
+ <p>
+ <url href="https://www.openssl.org/">OpenSSL</url> exposes an Engine API, which makes
+ it possible to plug in alternative implementations for some of the cryptographic
+ operations implemented by OpenSSL.
+ See the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ for details and how to load an Engine.
+ </p>
+ <p>
+ An engine could among other tasks provide a storage for
+ private or public keys. Such a storage could be made safer than the normal file system. Thoose techniques are not
+ described in this User's Guide. Here we concentrate on how to use private or public keys stored in
+ such an engine.
+ </p>
+ <p>
+ The storage engine must call <c>ENGINE_set_load_privkey_function</c> and <c>ENGINE_set_load_pubkey_function</c>.
+ See the OpenSSL cryptolib's <url href="https://www.openssl.org/docs/manpages.html">manpages</url>.
+ </p>
+ <p>
+ OTP/Crypto requires that the user provides two or three items of information about the key. The application used
+ by the user is usually on a higher level, for example in
+ <seealso marker="ssl:ssl#key_option_def">SSL</seealso>. If using
+ the crypto application directly, it is required that:
+ </p>
+ <list>
+ <item>an Engine is loaded, see the chapter on <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ or the <seealso marker="crypto:crypto#engine_load-3">Reference Manual</seealso>
+ </item>
+ <item>a reference to a key in the Engine is available. This should be an Erlang string or binary and depends
+ on the Engine loaded
+ </item>
+ <item>an Erlang map is constructed with the Engine reference, the key reference and possibly a key passphrase if
+ needed by the Engine. See the <seealso marker="crypto:crypto#type-engine_key_ref">Reference Manual</seealso> for
+ details of the map.
+ </item>
+ </list>
+ </section>
+
+ <section>
+ <title>Use Cases</title>
+ <section>
+ <title>Sign with an engine stored private key</title>
+ <p>
+ This example shows how to construct a key reference that is used in a sign operation.
+ The actual key is stored in the engine that is loaded at prompt 1.
+ </p>
+ <code>
+1> {ok, EngineRef} = crypto:engine_load(....).
+...
+{ok,#Ref&lt;0.2399045421.3028942852.173962>}
+2> PrivKey = #{engine => EngineRef,
+ key_id => "id of the private key in Engine"}.
+...
+3> Signature = crypto:sign(rsa, sha, &lt;&lt;"The message">>, PrivKey).
+&lt;&lt;65,6,125,254,54,233,84,77,83,63,168,28,169,214,121,76,
+ 207,177,124,183,156,185,160,243,36,79,125,230,231,...>>
+ </code>
+ </section>
+
+ <section>
+ <title>Verify with an engine stored public key</title>
+ <p>
+ Here the signature and message in the last example is verifyed using the public key.
+ The public key is stored in an engine, only to exemplify that it is possible. The public
+ key could of course be handled openly as usual.
+ </p>
+ <code>
+4> PublicKey = #{engine => EngineRef,
+ key_id => "id of the public key in Engine"}.
+...
+5> crypto:verify(rsa, sha, &lt;&lt;"The message">>, Signature, PublicKey).
+true
+6>
+ </code>
+ </section>
+
+ <section>
+ <title>Using a password protected private key</title>
+ <p>
+ The same example as the first sign example, except that a password protects the key down in the Engine.
+ </p>
+ <code>
+6> PrivKeyPwd = #{engine => EngineRef,
+ key_id => "id of the pwd protected private key in Engine",
+ password => "password"}.
+...
+7> crypto:sign(rsa, sha, &lt;&lt;"The message">>, PrivKeyPwd).
+&lt;&lt;140,80,168,101,234,211,146,183,231,190,160,82,85,163,
+ 175,106,77,241,141,120,72,149,181,181,194,154,175,76,
+ 223,...>>
+8>
+ </code>
+
+ </section>
+
+ </section>
+</chapter>
diff --git a/lib/crypto/doc/src/engine_load.xml b/lib/crypto/doc/src/engine_load.xml
new file mode 100644
index 0000000000..5f7ccc784b
--- /dev/null
+++ b/lib/crypto/doc/src/engine_load.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2017</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+ </legalnotice>
+ <title>Engine Load</title>
+ <prepared>Lars Thorsén</prepared>
+ <date>2017-08-22</date>
+ <file>engine_load.xml</file>
+ </header>
+ <p>
+ <marker id="engine_load"></marker>
+ This chapter describes the support for loading encryption engines in the crypto application.
+ </p>
+
+ <section>
+ <title>Background</title>
+ <p>
+ OpenSSL exposes an Engine API, which makes it possible to plug in alternative
+ implementations for some or all of the cryptographic operations implemented by OpenSSL.
+ When configured appropriately, OpenSSL calls the engine's implementation of these
+ operations instead of its own.
+ </p>
+ <p>
+ Typically, OpenSSL engines provide a hardware implementation of specific cryptographic
+ operations. The hardware implementation usually offers improved performance over its
+ software-based counterpart, which is known as cryptographic acceleration.
+ </p>
+ <note>
+ <p>The file name requirement on the engine dynamic library can differ between SSL versions.</p>
+ </note>
+ </section>
+
+ <section>
+ <title>Use Cases</title>
+ <section>
+ <title>Dynamically load an engine from default directory</title>
+ <p>
+ If the engine is located in the OpenSSL/LibreSSL installation <c>engines</c> directory.
+ </p>
+ <code>
+1> {ok, Engine} = crypto:engine_load(&lt;&lt;"otp_test_engine">>, [], []).
+ {ok, #Ref}</code>
+ </section>
+
+ <section>
+ <title>Load an engine with the dynamic engine</title>
+ <p>
+ Load an engine with the help of the dynamic engine by giving the path to the library.
+ </p>
+ <code>
+ 2> {ok, Engine} = crypto:engine_load(&lt;&lt;"dynamic">>,
+ [{&lt;&lt;"SO_PATH">>,
+ &lt;&lt;"/some/path/otp_test_engine.so">>},
+ {&lt;&lt;"ID">>, &lt;&lt;"MD5">>},
+ &lt;&lt;"LOAD">>],
+ []).
+ {ok, #Ref}</code>
+ </section>
+
+ <section>
+ <title>Load an engine and replace some methods</title>
+ <p>
+ Load an engine with the help of the dynamic engine and just
+ replace some engine methods.
+ </p>
+ <code>
+ 3> Methods = crypto:engine_get_all_methods() -- [engine_method_dh,engine_method_rand,
+engine_method_ciphers,engine_method_digests, engine_method_store,
+engine_method_pkey_meths, engine_method_pkey_asn1_meths].
+[engine_method_rsa,engine_method_dsa,
+ engine_method_ecdh,engine_method_ecdsa]
+ 4> {ok, Engine} = crypto:engine_load(&lt;&lt;"dynamic">>,
+ [{&lt;&lt;"SO_PATH">>,
+ &lt;&lt;"/some/path/otp_test_engine.so">>},
+ {&lt;&lt;"ID">>, &lt;&lt;"MD5">>},
+ &lt;&lt;"LOAD">>],
+ [],
+ Methods).
+ {ok, #Ref}</code>
+ </section>
+
+ <section>
+ <title>Load with the ensure loaded function</title>
+ <p>
+ This function makes sure the engine is loaded just once and the ID is added to the internal
+ engine list of OpenSSL. The following calls to the function will check if the ID is loaded
+ and then just get a new reference to the engine.
+ </p>
+ <code>
+ 5> {ok, Engine} = crypto:ensure_engine_loaded(&lt;&lt;"MD5">>,
+ &lt;&lt;"/some/path/otp_test_engine.so">>).
+ {ok, #Ref}</code>
+ <p>
+ To unload it use crypto:ensure_engine_unloaded/1 which removes the ID from the internal list
+ before unloading the engine.
+ </p>
+ <code>
+ 6> crypto:ensure_engine_unloaded(&lt;&lt;"MD5">>).
+ ok</code>
+ </section>
+
+
+
+ <section>
+ <title>List all engines currently loaded</title>
+ <code>
+ 5> crypto:engine_list().
+[&lt;&lt;"dynamic">>, &lt;&lt;"MD5">>]</code>
+ </section>
+
+ </section>
+</chapter>
diff --git a/lib/crypto/doc/src/fascicules.xml b/lib/crypto/doc/src/fascicules.xml
deleted file mode 100644
index cbc266cd30..0000000000
--- a/lib/crypto/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="usersguide" href="usersguide_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="release_notes" href="release_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/crypto/doc/src/note.gif b/lib/crypto/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/crypto/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml
index 574353ce7a..d81a8ddd87 100644
--- a/lib/crypto/doc/src/notes.xml
+++ b/lib/crypto/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1999</year><year>2017</year>
+ <year>1999</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,381 @@
</header>
<p>This document describes the changes made to the Crypto application.</p>
+<section><title>Crypto 4.3.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The RSA options <c>rsa_mgf1_md</c>, <c>rsa_oaep_md</c>,
+ and <c>rsa_oaep_label</c> were always disabled. They will
+ now be enabled when a suitable cryptolib is used.</p>
+ <p>
+ They are still experimental and may change without prior
+ notice.</p>
+ <p>
+ Own Id: OTP-15212 Aux Id: ERL-675, PR1899, PR838 </p>
+ </item>
+ <item>
+ <p>
+ The ciphers <c>aes_ige256</c> and <c>blowfish_cbc</c> had
+ naming issues in <c>crypto:next_iv/2</c>.</p>
+ <p>
+ Own Id: OTP-15283</p>
+ </item>
+ <item>
+ <p>
+ the <c>RSA_SSLV23_PADDING</c> is disabled if LibreSSL is
+ used as cryptlib. This is due to compilation problems.</p>
+ <p>
+ This will be investigated further in the future.</p>
+ <p>
+ Own Id: OTP-15303</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The supported named elliptic curves are now reported in
+ <c>crypto:supports/0</c> in a new entry tagged by
+ <c>'curves'</c>.</p>
+ <p>
+ The function <c>crypto:ec_curves/0</c> is kept for
+ compatibility.</p>
+ <p>
+ Own Id: OTP-14717 Aux Id: OTP-15244 </p>
+ </item>
+ <item>
+ <p>
+ The typing in the CRYPTO and PUBLIC_KEY applications are
+ reworked and a few mistakes are corrected.</p>
+ <p>
+ The documentation is now generated from the typing and
+ some clarifications are made.</p>
+ <p>
+ A new chapter on Algorithm Details such as key sizes and
+ availability is added to the CRYPTO User's Guide.</p>
+ <p>
+ Own Id: OTP-15134</p>
+ </item>
+ <item>
+ <p>
+ Support for SHA3 both as a separate hash and in HMAC is
+ now available if OpenSSL 1.1.1 or higher is used as
+ cryptolib.</p>
+ <p>
+ Available lengths are reported in the <c>'hashs'</c>
+ entry in <c>crypto:supports/0</c> as <c>sha3_*</c>.</p>
+ <p>
+ Own Id: OTP-15153</p>
+ </item>
+ <item>
+ <p>
+ The mac algorithm <c>poly1305</c> and the cipher
+ algorithm <c>chacha20</c> are now supported if OpenSSL
+ 1.1.1 or higher is used as cryptolib.</p>
+ <p>
+ Own Id: OTP-15164 Aux Id: OTP-15209 </p>
+ </item>
+ <item>
+ <p>
+ The key exchange Edward curves <c>x25519</c> and
+ <c>x448</c> are now supported if OpenSSL 1.1.1 or higher
+ is used as cryptolib.</p>
+ <p>
+ Own Id: OTP-15240 Aux Id: OTP-15133 </p>
+ </item>
+ <item>
+ <p>
+ The supported RSA options for sign/verify and
+ encrypt/decrypt are now reported in
+ <c>crypto:supports/0</c> in a new entry tagged by
+ '<c>rsa_opts</c>'.</p>
+ <p>
+ The exakt set is still experimental and may change
+ without prior notice.</p>
+ <p>
+ Own Id: OTP-15260</p>
+ </item>
+ <item>
+ <p>
+ The cipher <c>aes_ccm</c> is added.</p>
+ <p>
+ Own Id: OTP-15286</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 4.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Update the crypto engine functions to handle multiple
+ loads of an engine. </p> <p><c>engine_load/3/4</c> is
+ updated so it doesn't add the engine ID to OpenSSLs
+ internal list of engines which makes it possible to run
+ the engine_load more than once if it doesn't contain
+ global data.</p> <p>Added <c>ensure_engine_loaded/2/3</c>
+ which guarantees that the engine just is loaded once and
+ the following calls just returns a reference to it. This
+ is done by add the ID to the internal OpenSSL list and
+ check if it is already registered when the function is
+ called.</p> <p>Added <c>ensure_engine_unloaded/1/2</c> to
+ unload engines loaded with ensure_engine_loaded.</p>
+ <p>Then some more utility functions are added.</p>
+ <p><c>engine_add/1</c>, adds the engine to OpenSSL
+ internal list</p> <p><c>engine_remove/1</c>, remove the
+ engine from OpenSSL internal list</p>
+ <p><c>engine_get_id/1</c>, fetch the engines id</p>
+ <p><c>engine_get_name/1</c>, fetch the engine name</p>
+ <p>
+ Own Id: OTP-15233</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 4.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a node crash in <c>crypto:compute_key(ecdh,
+ ...)</c> when passing a wrongly typed Others
+ argument.</p>
+ <p>
+ Own Id: OTP-15194 Aux Id: ERL-673 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 4.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Removed two undocumented and erroneous functions
+ (<c>crypto:dh_generate_parameters/2</c> and
+ <c>crypto:dh_check/1</c>).</p>
+ <p>
+ Own Id: OTP-14956 Aux Id: ERL-579 </p>
+ </item>
+ <item>
+ <p>
+ Fixed bug causing VM crash if doing runtime upgrade of a
+ crypto module built against OpenSSL older than 0.9.8h.
+ Bug exists since OTP-20.2.</p>
+ <p>
+ Own Id: OTP-15088</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A new <c>rand</c> plugin algorithm has been implemented
+ in <c>crypto</c>, that is: <c>crypto_cache</c>. It uses
+ strong random bytes as randomness source and caches them
+ to get good speed. See <c>crypto:rand_seed_alg/1</c>.</p>
+ <p>
+ Own Id: OTP-13370 Aux Id: PR-1573 </p>
+ </item>
+ <item>
+ <p>
+ Diffie-Hellman key functions are re-written with the
+ EVP_PKEY api.</p>
+ <p>
+ Own Id: OTP-14864</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 4.2.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a node crash in <c>crypto:compute_key(ecdh,
+ ...)</c> when passing a wrongly typed Others
+ argument.</p>
+ <p>
+ Own Id: OTP-15194 Aux Id: ERL-673 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 4.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ If OPENSSL_NO_EC was set, the compilation of the crypto
+ nifs failed.</p>
+ <p>
+ Own Id: OTP-15073</p>
+ </item>
+ <item>
+ <p>
+ C-compile errors for LibreSSL 2.7.0 - 2.7.2 fixed</p>
+ <p>
+ Own Id: OTP-15074 Aux Id: ERL-618 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 4.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix build error caused by removed RSA padding functions
+ in LibreSSL >= 2.6.1</p>
+ <p>
+ Own Id: OTP-14873</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 4.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The compatibility function <c>void HMAC_CTX_free</c> in
+ <c>crypto.c</c> erroneously tried to return a value.</p>
+ <p>
+ Own Id: OTP-14720</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Rewrite public and private key encode/decode with EVP
+ api. New RSA padding options added. This is a modified
+ half of PR-838.</p>
+ <p>
+ Own Id: OTP-14446</p>
+ </item>
+ <item>
+ <p>
+ The crypto API is extended to use private/public keys
+ stored in an Engine for sign/verify or encrypt/decrypt
+ operations.</p>
+ <p>
+ The ssl application provides an API to use this new
+ engine concept in TLS.</p>
+ <p>
+ Own Id: OTP-14448</p>
+ </item>
+ <item>
+ <p> Add support to plug in alternative implementations
+ for some or all of the cryptographic operations supported
+ by the OpenSSL Engine API. When configured appropriately,
+ OpenSSL calls the engine's implementation of these
+ operations instead of its own. </p>
+ <p>
+ Own Id: OTP-14567</p>
+ </item>
+ <item>
+ <p>
+ Replaced a call of the OpenSSL deprecated function
+ <c>DH_generate_parameters</c> in <c>crypto.c</c>.</p>
+ <p>
+ Own Id: OTP-14639</p>
+ </item>
+ <item>
+ <p>
+ Documentation added about how to use keys stored in an
+ Engine.</p>
+ <p>
+ Own Id: OTP-14735 Aux Id: OTP-14448 </p>
+ </item>
+ <item>
+ <p> Add engine_ ctrl_cmd_string/3,4 the OpenSSL Engine
+ support in crypto. </p>
+ <p>
+ Own Id: OTP-14801</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 4.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>On macOS, <c>crypto</c> would crash if <c>observer</c>
+ had been started before <c>crypto</c>. On the beta for
+ macOS 10.13 (High Sierra), <c>crypto</c> would crash.
+ Both of those bugs have been fixed.</p>
+ <p>
+ Own Id: OTP-14499 Aux Id: ERL-251 ERL-439 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Extend crypto:sign, crypto:verify, public_key:sign and
+ public_key:verify with:</p>
+ <p>
+ * support for RSASSA-PS padding for signatures and for
+ saltlength setting<br/> * X9.31 RSA padding.<br/> * sha,
+ sha224, sha256, sha384, and sha512 for dss signatures as
+ mentioned in NIST SP 800-57 Part 1.<br/> * ripemd160 to
+ be used for rsa signatures.</p>
+ <p>
+ This is a manual merge of half of the pull request 838 by
+ potatosalad from Sept 2015.</p>
+ <p>
+ Own Id: OTP-13704 Aux Id: PR838 </p>
+ </item>
+ <item>
+ <p>
+ A new tuple in <c>crypto:supports/0</c> reports supported
+ MAC algorithms.</p>
+ <p>
+ Own Id: OTP-14504</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Crypto 4.0</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/crypto/doc/src/specs.xml b/lib/crypto/doc/src/specs.xml
new file mode 100644
index 0000000000..66c79a906b
--- /dev/null
+++ b/lib/crypto/doc/src/specs.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<specs xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="../specs/specs_crypto.xml"/>
+</specs>
diff --git a/lib/crypto/doc/src/usersguide.xml b/lib/crypto/doc/src/usersguide.xml
index 7971aefff4..2dfc966609 100644
--- a/lib/crypto/doc/src/usersguide.xml
+++ b/lib/crypto/doc/src/usersguide.xml
@@ -4,14 +4,14 @@
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2003</year><year>2016</year>
+ <year>2003</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
@@ -19,7 +19,7 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-
+
</legalnotice>
<title>Crypto User's Guide</title>
@@ -48,5 +48,7 @@
</description>
<xi:include href="licenses.xml"/>
<xi:include href="fips.xml"/>
+ <xi:include href="engine_load.xml"/>
+ <xi:include href="engine_keys.xml"/>
+ <xi:include href="algorithm_details.xml"/>
</part>
-
diff --git a/lib/crypto/doc/src/warning.gif b/lib/crypto/doc/src/warning.gif
deleted file mode 100644
index 96af52360e..0000000000
--- a/lib/crypto/doc/src/warning.gif
+++ /dev/null
Binary files differ
diff --git a/lib/crypto/src/Makefile b/lib/crypto/src/Makefile
index aea8a5a71c..1753ba4f36 100644
--- a/lib/crypto/src/Makefile
+++ b/lib/crypto/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
+# Copyright Ericsson AB 1999-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -39,8 +39,7 @@ MODULES= \
crypto \
crypto_ec_curves
-HRL_FILES=
-
+HRL_FILES=
ERL_FILES= $(MODULES:%=%.erl)
TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
@@ -56,16 +55,16 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
-ERL_COMPILE_FLAGS += -DCRYPTO_VSN=\"$(VSN)\" -Werror
+ERL_COMPILE_FLAGS += -DCRYPTO_VSN=\"$(VSN)\" -Werror -I../include
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt valgrind: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+debug opt valgrind: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
clean:
- rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
rm -f errs core *~
$(APP_TARGET): $(APP_SRC) ../vsn.mk
@@ -78,7 +77,7 @@ docs:
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
@@ -89,10 +88,3 @@ release_spec: opt
$(APPUP_TARGET) "$(RELSYSDIR)/ebin"
release_docs_spec:
-
-
-
-
-
-
-
diff --git a/lib/crypto/src/crypto.app.src b/lib/crypto/src/crypto.app.src
index 1d3f35e465..492aa10e51 100644
--- a/lib/crypto/src/crypto.app.src
+++ b/lib/crypto/src/crypto.app.src
@@ -24,7 +24,7 @@
crypto_ec_curves]},
{registered, []},
{applications, [kernel, stdlib]},
- {env, [{fips_mode, false}]},
+ {env, [{fips_mode, false}, {rand_cache_size, 896}]},
{runtime_dependencies, ["erts-9.0","stdlib-3.4","kernel-5.3"]}]}.
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index d111525214..2db73c4af0 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,25 +25,74 @@
-export([start/0, stop/0, info_lib/0, info_fips/0, supports/0, enable_fips_mode/1,
version/0, bytes_to_integer/1]).
-export([hash/2, hash_init/1, hash_update/2, hash_final/1]).
--export([sign/4, verify/5]).
+-export([sign/4, sign/5, verify/5, verify/6]).
-export([generate_key/2, generate_key/3, compute_key/4]).
-export([hmac/3, hmac/4, hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]).
-export([cmac/3, cmac/4]).
+-export([poly1305/2]).
-export([exor/2, strong_rand_bytes/1, mod_pow/3]).
--export([rand_seed/0]).
--export([rand_seed_s/0]).
+-export([rand_seed/0, rand_seed_alg/1]).
+-export([rand_seed_s/0, rand_seed_alg_s/1]).
-export([rand_plugin_next/1]).
-export([rand_plugin_uniform/1]).
-export([rand_plugin_uniform/2]).
+-export([rand_cache_plugin_next/1]).
-export([rand_uniform/2]).
-export([block_encrypt/3, block_decrypt/3, block_encrypt/4, block_decrypt/4]).
-export([next_iv/2, next_iv/3]).
-export([stream_init/2, stream_init/3, stream_encrypt/2, stream_decrypt/2]).
-export([public_encrypt/4, private_decrypt/4]).
-export([private_encrypt/4, public_decrypt/4]).
--export([dh_generate_parameters/2, dh_check/1]). %% Testing see
+-export([privkey_to_pubkey/2]).
-export([ec_curve/1, ec_curves/0]).
-export([rand_seed/1]).
+%% Engine
+-export([
+ engine_get_all_methods/0,
+ engine_load/3,
+ engine_load/4,
+ engine_unload/1,
+ engine_by_id/1,
+ engine_list/0,
+ engine_ctrl_cmd_string/3,
+ engine_ctrl_cmd_string/4,
+ engine_add/1,
+ engine_remove/1,
+ engine_get_id/1,
+ engine_get_name/1,
+ ensure_engine_loaded/2,
+ ensure_engine_loaded/3,
+ ensure_engine_unloaded/1,
+ ensure_engine_unloaded/2
+ ]).
+
+-export_type([ %% A minimum exported: only what public_key needs.
+ dh_private/0,
+ dh_public/0,
+ dss_digest_type/0,
+ ec_named_curve/0,
+ ecdsa_digest_type/0,
+ pk_encrypt_decrypt_opts/0,
+ pk_sign_verify_opts/0,
+ rsa_digest_type/0,
+ sha1/0,
+ sha2/0
+ ]).
+
+-export_type([engine_ref/0,
+ key_id/0,
+ password/0
+ ]).
+
+%%% Opaque types must be exported :(
+-export_type([
+ stream_state/0,
+ hmac_state/0,
+ hash_state/0
+ ]).
+
+%% Private. For tests.
+-export([packed_openssl_version/4, engine_methods_convert_to_bitmask/2, get_test_engine/0]).
-deprecated({rand_uniform, 2, next_major_release}).
@@ -53,16 +102,187 @@
%% Used by strong_rand_float/0
-define(HALF_DBL_EPSILON, 1.1102230246251565e-16). % math:pow(2, -53)
-%%-type ecdsa_digest_type() :: 'md5' | 'sha' | 'sha256' | 'sha384' | 'sha512'.
+
+%%% ===== BEGIN NEW TYPING ====
+
+%%% Basic
+-type key_integer() :: integer() | binary(). % Always binary() when used as return value
+
+%%% Keys
+-type rsa_public() :: [key_integer()] . % [E, N]
+-type rsa_private() :: [key_integer()] . % [E, N, D] | [E, N, D, P1, P2, E1, E2, C]
+-type rsa_params() :: {ModulusSizeInBits::integer(), PublicExponent::key_integer()} .
+
+-type dss_public() :: [key_integer()] . % [P, Q, G, Y]
+-type dss_private() :: [key_integer()] . % [P, Q, G, X]
+
+-type ecdsa_public() :: key_integer() .
+-type ecdsa_private() :: key_integer() .
+-type ecdsa_params() :: ec_named_curve() | edwards_curve() | ec_explicit_curve() .
+
+-type srp_public() :: key_integer() .
+-type srp_private() :: key_integer() .
+-type srp_gen_params() :: {user,srp_user_gen_params()} | {host,srp_host_gen_params()}.
+-type srp_comp_params() :: {user,srp_user_comp_params()} | {host,srp_host_comp_params()}.
+-type srp_user_gen_params() :: list(binary() | atom() | list()) .
+-type srp_host_gen_params() :: list(binary() | atom() | list()) .
+-type srp_user_comp_params() :: list(binary() | atom()) .
+-type srp_host_comp_params() :: list(binary() | atom()) .
+
+-type dh_public() :: key_integer() .
+-type dh_private() :: key_integer() .
+-type dh_params() :: [key_integer()] . % [P, G] | [P, G, PrivateKeyBitLength]
+
+-type ecdh_public() :: key_integer() .
+-type ecdh_private() :: key_integer() .
+-type ecdh_params() :: ec_named_curve() | edwards_curve() | ec_explicit_curve() .
+
+
+%%% Curves
+
+-type ec_explicit_curve() :: {Field :: ec_field(),
+ Curve :: ec_curve(),
+ BasePoint :: binary(),
+ Order :: binary(),
+ CoFactor :: none | % FIXME: Really?
+ binary()
+ } .
+
+-type ec_curve() :: {A :: binary(),
+ B :: binary(),
+ Seed :: none | binary()
+ } .
+
+-type ec_field() :: ec_prime_field() | ec_characteristic_two_field() .
+
+-type ec_prime_field() :: {prime_field, Prime :: integer()} .
+-type ec_characteristic_two_field() :: {characteristic_two_field, M :: integer(), Basis :: ec_basis()} .
+
+-type ec_basis() :: {tpbasis, K :: non_neg_integer()}
+ | {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()}
+ | onbasis .
+
+-type ec_named_curve() :: brainpoolP160r1
+ | brainpoolP160t1
+ | brainpoolP192r1
+ | brainpoolP192t1
+ | brainpoolP224r1
+ | brainpoolP224t1
+ | brainpoolP256r1
+ | brainpoolP256t1
+ | brainpoolP320r1
+ | brainpoolP320t1
+ | brainpoolP384r1
+ | brainpoolP384t1
+ | brainpoolP512r1
+ | brainpoolP512t1
+ | c2pnb163v1
+ | c2pnb163v2
+ | c2pnb163v3
+ | c2pnb176v1
+ | c2pnb208w1
+ | c2pnb272w1
+ | c2pnb304w1
+ | c2pnb368w1
+ | c2tnb191v1
+ | c2tnb191v2
+ | c2tnb191v3
+ | c2tnb239v1
+ | c2tnb239v2
+ | c2tnb239v3
+ | c2tnb359v1
+ | c2tnb431r1
+ | ipsec3
+ | ipsec4
+ | prime192v1
+ | prime192v2
+ | prime192v3
+ | prime239v1
+ | prime239v2
+ | prime239v3
+ | prime256v1
+ | secp112r1
+ | secp112r2
+ | secp128r1
+ | secp128r2
+ | secp160k1
+ | secp160r1
+ | secp160r2
+ | secp192k1
+ | secp192r1
+ | secp224k1
+ | secp224r1
+ | secp256k1
+ | secp256r1
+ | secp384r1
+ | secp521r1
+ | sect113r1
+ | sect113r2
+ | sect131r1
+ | sect131r2
+ | sect163k1
+ | sect163r1
+ | sect163r2
+ | sect193r1
+ | sect193r2
+ | sect233k1
+ | sect233r1
+ | sect239k1
+ | sect283k1
+ | sect283r1
+ | sect409k1
+ | sect409r1
+ | sect571k1
+ | sect571r1
+ | wtls1
+ | wtls10
+ | wtls11
+ | wtls12
+ | wtls3
+ | wtls4
+ | wtls5
+ | wtls6
+ | wtls7
+ | wtls8
+ | wtls9
+ .
+
+-type edwards_curve() :: x25519
+ | x448 .
+
+%%%
+-type block_cipher_with_iv() :: cbc_cipher()
+ | cfb_cipher()
+ | aes_cbc128
+ | aes_cbc256
+ | aes_ige256
+ | blowfish_ofb64
+ | des3_cbf % cfb misspelled
+ | des_ede3
+ | rc2_cbc .
+
+-type cbc_cipher() :: des_cbc | des3_cbc | aes_cbc | blowfish_cbc .
+-type aead_cipher() :: aes_gcm | aes_ccm | chacha20_poly1305 .
+-type cfb_cipher() :: aes_cfb128 | aes_cfb8 | blowfish_cfb64 | des3_cfb | des_cfb .
+
+-type block_cipher_without_iv() :: ecb_cipher() .
+-type ecb_cipher() :: des_ecb | blowfish_ecb | aes_ecb .
+
+-type key() :: iodata().
+-type des3_key() :: [key()].
+
+%%%
+-type rsa_digest_type() :: sha1() | sha2() | md5 | ripemd160 .
+-type dss_digest_type() :: sha1() | sha2() .
+-type ecdsa_digest_type() :: sha1() | sha2() .
+
+-type sha1() :: sha .
+-type sha2() :: sha224 | sha256 | sha384 | sha512 .
+-type sha3() :: sha3_224 | sha3_256 | sha3_384 | sha3_512 .
+
+-type compatibility_only_hash() :: md5 | md4 .
+
-type crypto_integer() :: binary() | integer().
-%%-type ec_named_curve() :: atom().
-%%-type ec_point() :: crypto_integer().
-%%-type ec_basis() :: {tpbasis, K :: non_neg_integer()} | {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()} | onbasis.
-%%-type ec_field() :: {prime_field, Prime :: integer()} | {characteristic_two_field, M :: integer(), Basis :: ec_basis()}.
-%%-type ec_prime() :: {A :: crypto_integer(), B :: crypto_integer(), Seed :: binary() | none}.
-%%-type ec_curve_spec() :: {Field :: ec_field(), Prime :: ec_prime(), Point :: crypto_integer(), Order :: integer(), CoFactor :: none | integer()}.
-%%-type ec_curve() :: ec_named_curve() | ec_curve_spec().
-%%-type ec_key() :: {Curve :: ec_curve(), PrivKey :: binary() | undefined, PubKey :: ec_point() | undefined}.
-compile(no_native).
-on_load(on_load/0).
@@ -78,143 +298,240 @@ nif_stub_error(Line) ->
%% Crypto app version history:
%% (no version): Driver implementation
%% 2.0 : NIF implementation, requires OTP R14
+
+%% When generating documentation from crypto.erl, the macro ?CRYPTO_VSN is not defined.
+%% That causes the doc generation to stop...
+-ifndef(CRYPTO_VSN).
+-define(CRYPTO_VSN, "??").
+-endif.
version() -> ?CRYPTO_VSN.
+-spec start() -> ok | {error, Reason::term()}.
start() ->
application:start(crypto).
+-spec stop() -> ok | {error, Reason::term()}.
stop() ->
application:stop(crypto).
+-spec supports() -> [Support]
+ when Support :: {hashs, Hashs}
+ | {ciphers, Ciphers}
+ | {public_keys, PKs}
+ | {macs, Macs}
+ | {curves, Curves}
+ | {rsa_opts, RSAopts},
+ Hashs :: [sha1() | sha2() | sha3() | ripemd160 | compatibility_only_hash()],
+ Ciphers :: [stream_cipher()
+ | block_cipher_with_iv() | block_cipher_without_iv()
+ | aead_cipher()
+ ],
+ PKs :: [rsa | dss | ecdsa | dh | ecdh | ec_gf2m],
+ Macs :: [hmac | cmac | poly1305],
+ Curves :: [ec_named_curve() | edwards_curve()],
+ RSAopts :: [rsa_sign_verify_opt() | rsa_opt()] .
supports()->
- {Hashs, PubKeys, Ciphers} = algorithms(),
-
+ {Hashs, PubKeys, Ciphers, Macs, Curves, RsaOpts} = algorithms(),
[{hashs, Hashs},
{ciphers, Ciphers},
- {public_keys, PubKeys}
+ {public_keys, PubKeys},
+ {macs, Macs},
+ {curves, Curves},
+ {rsa_opts, RsaOpts}
].
+-spec info_lib() -> [{Name,VerNum,VerStr}] when Name :: binary(),
+ VerNum :: integer(),
+ VerStr :: binary() .
info_lib() -> ?nif_stub.
-spec info_fips() -> not_supported | not_enabled | enabled.
info_fips() -> ?nif_stub.
--spec enable_fips_mode(boolean()) -> boolean().
-
+-spec enable_fips_mode(Enable) -> Result when Enable :: boolean(),
+ Result :: boolean().
enable_fips_mode(_) -> ?nif_stub.
--spec hash(_, iodata()) -> binary().
+%%%================================================================
+%%%
+%%% Hashing
+%%%
+%%%================================================================
-hash(Hash, Data0) ->
- Data = iolist_to_binary(Data0),
- MaxBytes = max_bytes(),
- hash(Hash, Data, erlang:byte_size(Data), MaxBytes).
+-define(HASH_HASH_ALGORITHM, sha1() | sha2() | sha3() | ripemd160 | compatibility_only_hash() ).
--spec hash_init('md5'|'md4'|'ripemd160'|
- 'sha'|'sha224'|'sha256'|'sha384'|'sha512') -> any().
+-spec hash(Type, Data) -> Digest when Type :: ?HASH_HASH_ALGORITHM,
+ Data :: iodata(),
+ Digest :: binary().
+hash(Type, Data) ->
+ Data1 = iolist_to_binary(Data),
+ MaxBytes = max_bytes(),
+ hash(Type, Data1, erlang:byte_size(Data1), MaxBytes).
-hash_init(Hash) ->
- notsup_to_error(hash_init_nif(Hash)).
+-opaque hash_state() :: reference().
--spec hash_update(_, iodata()) -> any().
+-spec hash_init(Type) -> State when Type :: ?HASH_HASH_ALGORITHM,
+ State :: hash_state().
+hash_init(Type) ->
+ notsup_to_error(hash_init_nif(Type)).
-hash_update(State, Data0) ->
- Data = iolist_to_binary(Data0),
+-spec hash_update(State, Data) -> NewState when State :: hash_state(),
+ NewState :: hash_state(),
+ Data :: iodata() .
+hash_update(Context, Data) ->
+ Data1 = iolist_to_binary(Data),
MaxBytes = max_bytes(),
- hash_update(State, Data, erlang:byte_size(Data), MaxBytes).
+ hash_update(Context, Data1, erlang:byte_size(Data1), MaxBytes).
--spec hash_final(_) -> binary().
+-spec hash_final(State) -> Digest when State :: hash_state(),
+ Digest :: binary().
+hash_final(Context) ->
+ notsup_to_error(hash_final_nif(Context)).
-hash_final(State) ->
- notsup_to_error(hash_final_nif(State)).
+%%%================================================================
+%%%
+%%% MACs (Message Authentication Codes)
+%%%
+%%%================================================================
+%%%---- HMAC
--spec hmac(_, iodata(), iodata()) -> binary().
--spec hmac(_, iodata(), iodata(), integer()) -> binary().
--spec hmac_init(atom(), iodata()) -> binary().
--spec hmac_update(binary(), iodata()) -> binary().
--spec hmac_final(binary()) -> binary().
--spec hmac_final_n(binary(), integer()) -> binary().
+-define(HMAC_HASH_ALGORITHM, sha1() | sha2() | sha3() | compatibility_only_hash()).
-hmac(Type, Key, Data0) ->
- Data = iolist_to_binary(Data0),
- hmac(Type, Key, Data, undefined, erlang:byte_size(Data), max_bytes()).
-hmac(Type, Key, Data0, MacSize) ->
- Data = iolist_to_binary(Data0),
- hmac(Type, Key, Data, MacSize, erlang:byte_size(Data), max_bytes()).
+%%%---- hmac/3,4
+-spec hmac(Type, Key, Data) ->
+ Mac when Type :: ?HMAC_HASH_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ Mac :: binary() .
+hmac(Type, Key, Data) ->
+ Data1 = iolist_to_binary(Data),
+ hmac(Type, Key, Data1, undefined, erlang:byte_size(Data1), max_bytes()).
+
+-spec hmac(Type, Key, Data, MacLength) ->
+ Mac when Type :: ?HMAC_HASH_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ MacLength :: integer(),
+ Mac :: binary() .
+
+hmac(Type, Key, Data, MacLength) ->
+ Data1 = iolist_to_binary(Data),
+ hmac(Type, Key, Data1, MacLength, erlang:byte_size(Data1), max_bytes()).
+
+%%%---- hmac_init, hamc_update, hmac_final
+
+-opaque hmac_state() :: binary().
+
+-spec hmac_init(Type, Key) ->
+ State when Type :: ?HMAC_HASH_ALGORITHM,
+ Key :: iodata(),
+ State :: hmac_state() .
hmac_init(Type, Key) ->
notsup_to_error(hmac_init_nif(Type, Key)).
+%%%---- hmac_update
+
+-spec hmac_update(State, Data) -> NewState when Data :: iodata(),
+ State :: hmac_state(),
+ NewState :: hmac_state().
hmac_update(State, Data0) ->
Data = iolist_to_binary(Data0),
hmac_update(State, Data, erlang:byte_size(Data), max_bytes()).
+%%%---- hmac_final
+
+-spec hmac_final(State) -> Mac when State :: hmac_state(),
+ Mac :: binary().
hmac_final(Context) ->
notsup_to_error(hmac_final_nif(Context)).
+
+-spec hmac_final_n(State, HashLen) -> Mac when State :: hmac_state(),
+ HashLen :: integer(),
+ Mac :: binary().
hmac_final_n(Context, HashLen) ->
notsup_to_error(hmac_final_nif(Context, HashLen)).
--spec cmac(_, iodata(), iodata()) -> binary().
--spec cmac(_, iodata(), iodata(), integer()) -> binary().
+%%%---- CMAC
+
+-define(CMAC_CIPHER_ALGORITHM, cbc_cipher() | cfb_cipher() | blowfish_cbc | des_ede3 | rc2_cbc ).
+-spec cmac(Type, Key, Data) ->
+ Mac when Type :: ?CMAC_CIPHER_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ Mac :: binary().
cmac(Type, Key, Data) ->
notsup_to_error(cmac_nif(Type, Key, Data)).
-cmac(Type, Key, Data, MacSize) ->
- erlang:binary_part(cmac(Type, Key, Data), 0, MacSize).
-
-%% Ecrypt/decrypt %%%
-
--spec block_encrypt(des_cbc | des_cfb |
- des3_cbc | des3_cbf | des3_cfb | des_ede3 |
- blowfish_cbc | blowfish_cfb64 | blowfish_ofb64 |
- aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | aes_ige256 |
- aes_cbc |
- rc2_cbc,
- Key::iodata(), Ivec::binary(), Data::iodata()) -> binary();
- (aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(), {AAD::binary(), Data::iodata()}) -> {binary(), binary()};
- (aes_gcm, Key::iodata(), Ivec::binary(), {AAD::binary(), Data::iodata(), TagLength::1..16}) -> {binary(), binary()}.
-
-block_encrypt(Type, Key, Ivec, Data) when Type =:= des_cbc;
- Type =:= des_cfb;
- Type =:= blowfish_cbc;
- Type =:= blowfish_cfb64;
- Type =:= blowfish_ofb64;
- Type =:= aes_cbc128;
- Type =:= aes_cfb8;
- Type =:= aes_cfb128;
- Type =:= aes_cbc256;
- Type =:= aes_cbc;
- Type =:= rc2_cbc ->
- block_crypt_nif(Type, Key, Ivec, Data, true);
-block_encrypt(Type, Key0, Ivec, Data) when Type =:= des3_cbc;
- Type =:= des_ede3 ->
+
+-spec cmac(Type, Key, Data, MacLength) ->
+ Mac when Type :: ?CMAC_CIPHER_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ MacLength :: integer(),
+ Mac :: binary().
+cmac(Type, Key, Data, MacLength) ->
+ erlang:binary_part(cmac(Type, Key, Data), 0, MacLength).
+
+%%%---- POLY1305
+
+-spec poly1305(iodata(), iodata()) -> Mac when Mac :: binary().
+
+poly1305(Key, Data) ->
+ poly1305_nif(Key, Data).
+
+%%%================================================================
+%%%
+%%% Encrypt/decrypt
+%%%
+%%%================================================================
+
+%%%---- Block ciphers
+
+-spec block_encrypt(Type::block_cipher_with_iv(), Key::key()|des3_key(), Ivec::binary(), PlainText::iodata()) -> binary();
+ (Type::aead_cipher(), Key::iodata(), Ivec::binary(), {AAD::binary(), PlainText::iodata()}) ->
+ {binary(), binary()};
+ (aes_gcm | aes_ccm, Key::iodata(), Ivec::binary(), {AAD::binary(), PlainText::iodata(), TagLength::1..16}) ->
+ {binary(), binary()}.
+
+block_encrypt(Type, Key, Ivec, PlainText) when Type =:= des_cbc;
+ Type =:= des_cfb;
+ Type =:= blowfish_cbc;
+ Type =:= blowfish_cfb64;
+ Type =:= blowfish_ofb64;
+ Type =:= aes_cbc128;
+ Type =:= aes_cfb8;
+ Type =:= aes_cfb128;
+ Type =:= aes_cbc256;
+ Type =:= aes_cbc;
+ Type =:= rc2_cbc ->
+ block_crypt_nif(Type, Key, Ivec, PlainText, true);
+block_encrypt(Type, Key0, Ivec, PlainText) when Type =:= des3_cbc;
+ Type =:= des_ede3 ->
Key = check_des3_key(Key0),
- block_crypt_nif(des_ede3_cbc, Key, Ivec, Data, true);
-block_encrypt(des3_cbf, Key0, Ivec, Data) ->
+ block_crypt_nif(des_ede3_cbc, Key, Ivec, PlainText, true);
+block_encrypt(des3_cbf, Key0, Ivec, PlainText) -> % cfb misspelled
Key = check_des3_key(Key0),
- block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, true);
-block_encrypt(des3_cfb, Key0, Ivec, Data) ->
+ block_crypt_nif(des_ede3_cbf, Key, Ivec, PlainText, true);
+block_encrypt(des3_cfb, Key0, Ivec, PlainText) ->
Key = check_des3_key(Key0),
- block_crypt_nif(des_ede3_cfb, Key, Ivec, Data, true);
-block_encrypt(aes_ige256, Key, Ivec, Data) ->
- notsup_to_error(aes_ige_crypt_nif(Key, Ivec, Data, true));
-block_encrypt(aes_gcm, Key, Ivec, {AAD, Data}) ->
- aes_gcm_encrypt(Key, Ivec, AAD, Data);
-block_encrypt(aes_gcm, Key, Ivec, {AAD, Data, TagLength}) ->
- aes_gcm_encrypt(Key, Ivec, AAD, Data, TagLength);
-block_encrypt(chacha20_poly1305, Key, Ivec, {AAD, Data}) ->
- chacha20_poly1305_encrypt(Key, Ivec, AAD, Data).
-
--spec block_decrypt(des_cbc | des_cfb |
- des3_cbc | des3_cbf | des3_cfb | des_ede3 |
- blowfish_cbc | blowfish_cfb64 | blowfish_ofb64 |
- aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | aes_ige256 |
- aes_cbc |
- rc2_cbc,
- Key::iodata(), Ivec::binary(), Data::iodata()) -> binary();
- (aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(),
+ block_crypt_nif(des_ede3_cfb, Key, Ivec, PlainText, true);
+block_encrypt(aes_ige256, Key, Ivec, PlainText) ->
+ notsup_to_error(aes_ige_crypt_nif(Key, Ivec, PlainText, true));
+block_encrypt(Type, Key, Ivec, {AAD, PlainText}) when Type =:= aes_gcm;
+ Type =:= aes_ccm ->
+ aead_encrypt(Type, Key, Ivec, AAD, PlainText);
+block_encrypt(Type, Key, Ivec, {AAD, PlainText, TagLength}) when Type =:= aes_gcm;
+ Type =:= aes_ccm ->
+ aead_encrypt(Type, Key, Ivec, AAD, PlainText, TagLength);
+block_encrypt(chacha20_poly1305=Type, Key, Ivec, {AAD, PlainText}) ->
+ aead_encrypt(Type, Key, Ivec, AAD, PlainText, 16).
+
+
+-spec block_decrypt(Type::block_cipher_with_iv(), Key::key()|des3_key(), Ivec::binary(), Data::iodata()) -> binary();
+ (Type::aead_cipher(), Key::iodata(), Ivec::binary(),
{AAD::binary(), Data::iodata(), Tag::binary()}) -> binary() | error.
block_decrypt(Type, Key, Ivec, Data) when Type =:= des_cbc;
Type =:= des_cfb;
@@ -232,7 +549,7 @@ block_decrypt(Type, Key0, Ivec, Data) when Type =:= des3_cbc;
Type =:= des_ede3 ->
Key = check_des3_key(Key0),
block_crypt_nif(des_ede3_cbc, Key, Ivec, Data, false);
-block_decrypt(des3_cbf, Key0, Ivec, Data) ->
+block_decrypt(des3_cbf, Key0, Ivec, Data) -> % cfb misspelled
Key = check_des3_key(Key0),
block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, false);
block_decrypt(des3_cfb, Key0, Ivec, Data) ->
@@ -240,23 +557,27 @@ block_decrypt(des3_cfb, Key0, Ivec, Data) ->
block_crypt_nif(des_ede3_cfb, Key, Ivec, Data, false);
block_decrypt(aes_ige256, Key, Ivec, Data) ->
notsup_to_error(aes_ige_crypt_nif(Key, Ivec, Data, false));
-block_decrypt(aes_gcm, Key, Ivec, {AAD, Data, Tag}) ->
- aes_gcm_decrypt(Key, Ivec, AAD, Data, Tag);
-block_decrypt(chacha20_poly1305, Key, Ivec, {AAD, Data, Tag}) ->
- chacha20_poly1305_decrypt(Key, Ivec, AAD, Data, Tag).
+block_decrypt(Type, Key, Ivec, {AAD, Data, Tag}) when Type =:= aes_gcm;
+ Type =:= aes_ccm;
+ Type =:= chacha20_poly1305 ->
+ aead_decrypt(Type, Key, Ivec, AAD, Data, Tag).
+
--spec block_encrypt(des_ecb | blowfish_ecb | aes_ecb, Key::iodata(), Data::iodata()) -> binary().
+-spec block_encrypt(Type::block_cipher_without_iv(), Key::key(), PlainText::iodata()) -> binary().
-block_encrypt(Type, Key, Data) ->
- block_crypt_nif(Type, Key, Data, true).
+block_encrypt(Type, Key, PlainText) ->
+ block_crypt_nif(Type, Key, PlainText, true).
--spec block_decrypt(des_ecb | blowfish_ecb | aes_ecb, Key::iodata(), Data::iodata()) -> binary().
+
+-spec block_decrypt(Type::block_cipher_without_iv(), Key::key(), Data::iodata()) -> binary().
block_decrypt(Type, Key, Data) ->
block_crypt_nif(Type, Key, Data, false).
--spec next_iv(des_cbc | des3_cbc | aes_cbc | aes_ige, Data::iodata()) -> binary().
+-spec next_iv(Type:: cbc_cipher(), Data) -> NextIVec when % Type :: cbc_cipher(), %des_cbc | des3_cbc | aes_cbc | aes_ige,
+ Data :: iodata(),
+ NextIVec :: binary().
next_iv(Type, Data) when is_binary(Data) ->
IVecSize = case Type of
des_cbc -> 8;
@@ -269,7 +590,9 @@ next_iv(Type, Data) when is_binary(Data) ->
next_iv(Type, Data) when is_list(Data) ->
next_iv(Type, list_to_binary(Data)).
--spec next_iv(des_cfb, Data::iodata(), Ivec::binary()) -> binary().
+-spec next_iv(des_cfb, Data, IVec) -> NextIVec when Data :: iodata(),
+ IVec :: binary(),
+ NextIVec :: binary().
next_iv(des_cfb, Data, IVec) ->
IVecAndData = list_to_binary([IVec, Data]),
@@ -278,30 +601,57 @@ next_iv(des_cfb, Data, IVec) ->
next_iv(Type, Data, _Ivec) ->
next_iv(Type, Data).
+%%%---- Stream ciphers
+
+-opaque stream_state() :: {stream_cipher(), reference()}.
+
+-type stream_cipher() :: rc4 | aes_ctr | chacha20 .
+
+-spec stream_init(Type, Key, IVec) -> State when Type :: aes_ctr | chacha20,
+ Key :: iodata(),
+ IVec :: binary(),
+ State :: stream_state() .
stream_init(aes_ctr, Key, Ivec) ->
- {aes_ctr, aes_ctr_stream_init(Key, Ivec)}.
+ {aes_ctr, aes_ctr_stream_init(Key, Ivec)};
+stream_init(chacha20, Key, Ivec) ->
+ {chacha20, chacha20_stream_init(Key,Ivec)}.
+
+-spec stream_init(Type, Key) -> State when Type :: rc4,
+ Key :: iodata(),
+ State :: stream_state() .
stream_init(rc4, Key) ->
{rc4, notsup_to_error(rc4_set_key(Key))}.
+-spec stream_encrypt(State, PlainText) -> {NewState, CipherText}
+ when State :: stream_state(),
+ PlainText :: iodata(),
+ NewState :: stream_state(),
+ CipherText :: iodata() .
stream_encrypt(State, Data0) ->
Data = iolist_to_binary(Data0),
MaxByts = max_bytes(),
stream_crypt(fun do_stream_encrypt/2, State, Data, erlang:byte_size(Data), MaxByts, []).
+-spec stream_decrypt(State, CipherText) -> {NewState, PlainText}
+ when State :: stream_state(),
+ CipherText :: iodata(),
+ NewState :: stream_state(),
+ PlainText :: iodata() .
stream_decrypt(State, Data0) ->
Data = iolist_to_binary(Data0),
MaxByts = max_bytes(),
stream_crypt(fun do_stream_decrypt/2, State, Data, erlang:byte_size(Data), MaxByts, []).
-%%
-%% RAND - pseudo random numbers using RN_ and BN_ functions in crypto lib
-%%
--spec strong_rand_bytes(non_neg_integer()) -> binary().
--spec rand_seed() -> rand:state().
--spec rand_seed_s() -> rand:state().
--spec rand_uniform(crypto_integer(), crypto_integer()) ->
- crypto_integer().
+%%%================================================================
+%%%
+%%% RAND - pseudo random numbers using RN_ and BN_ functions in crypto lib
+%%%
+%%%================================================================
+-type rand_cache_seed() ::
+ nonempty_improper_list(non_neg_integer(), binary()).
+
+-spec strong_rand_bytes(N::non_neg_integer()) -> binary().
strong_rand_bytes(Bytes) ->
case strong_rand_bytes_nif(Bytes) of
false -> erlang:error(low_entropy);
@@ -310,16 +660,48 @@ strong_rand_bytes(Bytes) ->
strong_rand_bytes_nif(_Bytes) -> ?nif_stub.
+-spec rand_seed() -> rand:state().
rand_seed() ->
rand:seed(rand_seed_s()).
+-spec rand_seed_s() -> rand:state().
rand_seed_s() ->
+ rand_seed_alg_s(?MODULE).
+
+-spec rand_seed_alg(Alg :: atom()) ->
+ {rand:alg_handler(),
+ atom() | rand_cache_seed()}.
+rand_seed_alg(Alg) ->
+ rand:seed(rand_seed_alg_s(Alg)).
+
+-define(CRYPTO_CACHE_BITS, 56).
+-spec rand_seed_alg_s(Alg :: atom()) ->
+ {rand:alg_handler(),
+ atom() | rand_cache_seed()}.
+rand_seed_alg_s(?MODULE) ->
{#{ type => ?MODULE,
bits => 64,
next => fun ?MODULE:rand_plugin_next/1,
uniform => fun ?MODULE:rand_plugin_uniform/1,
uniform_n => fun ?MODULE:rand_plugin_uniform/2},
- no_seed}.
+ no_seed};
+rand_seed_alg_s(crypto_cache) ->
+ CacheBits = ?CRYPTO_CACHE_BITS,
+ EnvCacheSize =
+ application:get_env(
+ crypto, rand_cache_size, CacheBits * 16), % Cache 16 * 8 words
+ Bytes = (CacheBits + 7) div 8,
+ CacheSize =
+ case ((EnvCacheSize + (Bytes - 1)) div Bytes) * Bytes of
+ Sz when is_integer(Sz), Bytes =< Sz ->
+ Sz;
+ _ ->
+ Bytes
+ end,
+ {#{ type => crypto_cache,
+ bits => CacheBits,
+ next => fun ?MODULE:rand_cache_plugin_next/1},
+ {CacheBits, CacheSize, <<>>}}.
rand_plugin_next(Seed) ->
{bytes_to_integer(strong_rand_range(1 bsl 64)), Seed}.
@@ -330,6 +712,12 @@ rand_plugin_uniform(State) ->
rand_plugin_uniform(Max, State) ->
{bytes_to_integer(strong_rand_range(Max)) + 1, State}.
+rand_cache_plugin_next({CacheBits, CacheSize, <<>>}) ->
+ rand_cache_plugin_next(
+ {CacheBits, CacheSize, strong_rand_bytes(CacheSize)});
+rand_cache_plugin_next({CacheBits, CacheSize, Cache}) ->
+ <<I:CacheBits, NewCache/binary>> = Cache,
+ {I, {CacheBits, CacheSize, NewCache}}.
strong_rand_range(Range) when is_integer(Range), Range > 0 ->
BinRange = int_to_bin(Range),
@@ -347,7 +735,9 @@ strong_rand_float() ->
WholeRange = strong_rand_range(1 bsl 53),
?HALF_DBL_EPSILON * bytes_to_integer(WholeRange).
-rand_uniform(From,To) when is_binary(From), is_binary(To) ->
+-spec rand_uniform(crypto_integer(), crypto_integer()) ->
+ crypto_integer().
+rand_uniform(From, To) when is_binary(From), is_binary(To) ->
case rand_uniform_nif(From,To) of
<<Len:32/integer, MSB, Rest/binary>> when MSB > 127 ->
<<(Len + 1):32/integer, 0, MSB, Rest/binary>>;
@@ -377,106 +767,233 @@ rand_uniform_nif(_From,_To) -> ?nif_stub.
-spec rand_seed(binary()) -> ok.
-rand_seed(Seed) ->
+rand_seed(Seed) when is_binary(Seed) ->
rand_seed_nif(Seed).
rand_seed_nif(_Seed) -> ?nif_stub.
--spec mod_pow(binary()|integer(), binary()|integer(), binary()|integer()) -> binary() | error.
-mod_pow(Base, Exponent, Prime) ->
- case mod_exp_nif(ensure_int_as_bin(Base), ensure_int_as_bin(Exponent), ensure_int_as_bin(Prime), 0) of
- <<0>> -> error;
- R -> R
- end.
-verify(dss, none, Data, Signature, Key) when is_binary(Data) ->
- verify(dss, sha, {digest, Data}, Signature, Key);
-verify(Alg, Type, Data, Signature, Key) when is_binary(Data) ->
- verify(Alg, Type, {digest, hash(Type, Data)}, Signature, Key);
-verify(dss, Type, {digest, Digest}, Signature, Key) ->
- dss_verify_nif(Type, Digest, Signature, map_ensure_int_as_bin(Key));
-verify(rsa, Type, {digest, Digest}, Signature, Key) ->
- notsup_to_error(
- rsa_verify_nif(Type, Digest, Signature, map_ensure_int_as_bin(Key)));
-verify(ecdsa, Type, {digest, Digest}, Signature, [Key, Curve]) ->
- notsup_to_error(
- ecdsa_verify_nif(Type, Digest, Signature, nif_curve_params(Curve), ensure_int_as_bin(Key))).
-sign(dss, none, Data, Key) when is_binary(Data) ->
- sign(dss, sha, {digest, Data}, Key);
-sign(Alg, Type, Data, Key) when is_binary(Data) ->
- sign(Alg, Type, {digest, hash(Type, Data)}, Key);
-sign(rsa, Type, {digest, Digest}, Key) ->
- case rsa_sign_nif(Type, Digest, map_ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [rsa, Type, {digest, Digest}, Key]);
- Sign -> Sign
- end;
-sign(dss, Type, {digest, Digest}, Key) ->
- case dss_sign_nif(Type, Digest, map_ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [dss, Type, {digest, Digest}, Key]);
- Sign -> Sign
- end;
-sign(ecdsa, Type, {digest, Digest}, [Key, Curve]) ->
- case ecdsa_sign_nif(Type, Digest, nif_curve_params(Curve), ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [ecdsa, Type, {digest, Digest}, [Key, Curve]]);
- Sign -> Sign
- end.
-
--spec public_encrypt(rsa, binary(), [binary()], rsa_padding()) ->
- binary().
--spec public_decrypt(rsa, binary(), [integer() | binary()], rsa_padding()) ->
- binary().
--spec private_encrypt(rsa, binary(), [integer() | binary()], rsa_padding()) ->
- binary().
--spec private_decrypt(rsa, binary(), [integer() | binary()], rsa_padding()) ->
- binary().
-
-public_encrypt(rsa, BinMesg, Key, Padding) ->
- case rsa_public_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, true) of
- error ->
- erlang:error(encrypt_failed, [rsa, BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
-%% Binary, Key = [E,N,D]
-private_decrypt(rsa, BinMesg, Key, Padding) ->
- case rsa_private_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, false) of
- error ->
- erlang:error(decrypt_failed, [rsa, BinMesg,Key, Padding]);
- Sign -> Sign
+%%%================================================================
+%%%
+%%% Sign/verify
+%%%
+%%%================================================================
+-type pk_sign_verify_algs() :: rsa | dss | ecdsa .
+
+-type pk_sign_verify_opts() :: [ rsa_sign_verify_opt() ] .
+
+-type rsa_sign_verify_opt() :: {rsa_padding, rsa_sign_verify_padding()}
+ | {rsa_pss_saltlen, integer()} .
+
+-type rsa_sign_verify_padding() :: rsa_pkcs1_padding | rsa_pkcs1_pss_padding
+ | rsa_x931_padding | rsa_no_padding
+ .
+
+
+%%%----------------------------------------------------------------
+%%% Sign
+
+-spec sign(Algorithm, DigestType, Msg, Key)
+ -> Signature
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type(),
+ Msg :: binary() | {digest,binary()},
+ Key :: rsa_private()
+ | dss_private()
+ | [ecdsa_private()|ecdsa_params()]
+ | engine_key_ref(),
+ Signature :: binary() .
+
+sign(Algorithm, Type, Data, Key) ->
+ sign(Algorithm, Type, Data, Key, []).
+
+
+-spec sign(Algorithm, DigestType, Msg, Key, Options)
+ -> Signature
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type()
+ | none,
+ Msg :: binary() | {digest,binary()},
+ Key :: rsa_private()
+ | dss_private()
+ | [ecdsa_private() | ecdsa_params()]
+ | engine_key_ref(),
+ Options :: pk_sign_verify_opts(),
+ Signature :: binary() .
+
+sign(Algorithm0, Type0, Data, Key, Options) ->
+ {Algorithm, Type} = sign_verify_compatibility(Algorithm0, Type0, Data),
+ case pkey_sign_nif(Algorithm, Type, Data, format_pkey(Algorithm, Key), Options) of
+ error -> erlang:error(badkey, [Algorithm, Type, Data, Key, Options]);
+ notsup -> erlang:error(notsup);
+ Signature -> Signature
end.
-
-%% Binary, Key = [E,N,D]
-private_encrypt(rsa, BinMesg, Key, Padding) ->
- case rsa_private_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, true) of
- error ->
- erlang:error(encrypt_failed, [rsa, BinMesg,Key, Padding]);
- Sign -> Sign
+pkey_sign_nif(_Algorithm, _Type, _Digest, _Key, _Options) -> ?nif_stub.
+
+%%%----------------------------------------------------------------
+%%% Verify
+
+-spec verify(Algorithm, DigestType, Msg, Signature, Key)
+ -> Result
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type(),
+ Msg :: binary() | {digest,binary()},
+ Signature :: binary(),
+ Key :: rsa_private()
+ | dss_private()
+ | [ecdsa_private() | ecdsa_params()]
+ | engine_key_ref(),
+ Result :: boolean().
+
+verify(Algorithm, Type, Data, Signature, Key) ->
+ verify(Algorithm, Type, Data, Signature, Key, []).
+
+-spec verify(Algorithm, DigestType, Msg, Signature, Key, Options)
+ -> Result
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type(),
+ Msg :: binary() | {digest,binary()},
+ Signature :: binary(),
+ Key :: rsa_public()
+ | dss_public()
+ | [ecdsa_public() | ecdsa_params()]
+ | engine_key_ref(),
+ Options :: pk_sign_verify_opts(),
+ Result :: boolean().
+
+verify(Algorithm0, Type0, Data, Signature, Key, Options) ->
+ {Algorithm, Type} = sign_verify_compatibility(Algorithm0, Type0, Data),
+ case pkey_verify_nif(Algorithm, Type, Data, Signature, format_pkey(Algorithm, Key), Options) of
+ notsup -> erlang:error(notsup);
+ Boolean -> Boolean
end.
-%% Binary, Key = [E,N]
-public_decrypt(rsa, BinMesg, Key, Padding) ->
- case rsa_public_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, false) of
- error ->
- erlang:error(decrypt_failed, [rsa, BinMesg,Key, Padding]);
- Sign -> Sign
+pkey_verify_nif(_Algorithm, _Type, _Data, _Signature, _Key, _Options) -> ?nif_stub.
+
+%% Backwards compatible:
+sign_verify_compatibility(dss, none, Digest) ->
+ {sha, {digest, Digest}};
+sign_verify_compatibility(Algorithm0, Type0, _Digest) ->
+ {Algorithm0, Type0}.
+
+%%%================================================================
+%%%
+%%% Public/private encrypt/decrypt
+%%%
+%%% Only rsa works so far (although ecdsa | dss should do it)
+%%%================================================================
+-type pk_encrypt_decrypt_algs() :: rsa .
+
+-type pk_encrypt_decrypt_opts() :: [rsa_opt()] | rsa_compat_opts().
+
+-type rsa_compat_opts() :: [{rsa_pad, rsa_padding()}]
+ | rsa_padding() .
+
+-type rsa_padding() :: rsa_pkcs1_padding
+ | rsa_pkcs1_oaep_padding
+ | rsa_sslv23_padding
+ | rsa_x931_padding
+ | rsa_no_padding.
+
+-type rsa_opt() :: {rsa_padding, rsa_padding()}
+ | {signature_md, atom()}
+ | {rsa_mgf1_md, sha}
+ | {rsa_oaep_label, binary()}
+ | {rsa_oaep_md, sha} .
+
+%%%---- Encrypt with public key
+
+-spec public_encrypt(Algorithm, PlainText, PublicKey, Options) ->
+ CipherText when Algorithm :: pk_encrypt_decrypt_algs(),
+ PlainText :: binary(),
+ PublicKey :: rsa_public() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ CipherText :: binary().
+public_encrypt(Algorithm, PlainText, PublicKey, Options) ->
+ pkey_crypt(Algorithm, PlainText, PublicKey, Options, false, true).
+
+%%%---- Decrypt with private key
+
+-spec private_decrypt(Algorithm, CipherText, PrivateKey, Options) ->
+ PlainText when Algorithm :: pk_encrypt_decrypt_algs(),
+ CipherText :: binary(),
+ PrivateKey :: rsa_private() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ PlainText :: binary() .
+private_decrypt(Algorithm, CipherText, PrivateKey, Options) ->
+ pkey_crypt(Algorithm, CipherText, PrivateKey, Options, true, false).
+
+%%%---- Encrypt with private key
+
+-spec private_encrypt(Algorithm, PlainText, PrivateKey, Options) ->
+ CipherText when Algorithm :: pk_encrypt_decrypt_algs(),
+ PlainText :: binary(),
+ PrivateKey :: rsa_private() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ CipherText :: binary().
+private_encrypt(Algorithm, PlainText, PrivateKey, Options) ->
+ pkey_crypt(Algorithm, PlainText, PrivateKey, Options, true, true).
+
+%%%---- Decrypt with public key
+
+-spec public_decrypt(Algorithm, CipherText, PublicKey, Options) ->
+ PlainText when Algorithm :: pk_encrypt_decrypt_algs(),
+ CipherText :: binary(),
+ PublicKey :: rsa_public() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ PlainText :: binary() .
+public_decrypt(Algorithm, CipherText, PublicKey, Options) ->
+ pkey_crypt(Algorithm, CipherText, PublicKey, Options, false, false).
+
+%%%---- Call the nif, but fix a compatibility issue first
+
+%% Backwards compatible (rsa_pad -> rsa_padding is handled by the pkey_crypt_nif):
+pkey_crypt(rsa, Text, Key, Padding, PubPriv, EncDec) when is_atom(Padding) ->
+ pkey_crypt(rsa, Text, Key, [{rsa_padding, Padding}], PubPriv, EncDec);
+
+pkey_crypt(Alg, Text, Key, Options, PubPriv, EncDec) ->
+ case pkey_crypt_nif(Alg, Text, format_pkey(Alg,Key), Options, PubPriv, EncDec) of
+ error when EncDec==true -> erlang:error(encrypt_failed, [Alg, Text, Key, Options]);
+ error when EncDec==false -> erlang:error(decrypt_failed, [Alg, Text, Key, Options]);
+ notsup -> erlang:error(notsup);
+ Out -> Out
end.
-%%
-%% XOR - xor to iolists and return a binary
-%% NB doesn't check that they are the same size, just concatenates
-%% them and sends them to the driver
-%%
--spec exor(iodata(), iodata()) -> binary().
-
-exor(Bin1, Bin2) ->
- Data1 = iolist_to_binary(Bin1),
- Data2 = iolist_to_binary(Bin2),
- MaxBytes = max_bytes(),
- exor(Data1, Data2, erlang:byte_size(Data1), MaxBytes, []).
-
+pkey_crypt_nif(_Algorithm, _In, _Key, _Options, _IsPrivate, _IsEncrypt) -> ?nif_stub.
+
+%%%================================================================
+%%%
+%%%
+%%%
+%%%================================================================
+
+-spec generate_key(Type, Params)
+ -> {PublicKey, PrivKeyOut}
+ when Type :: dh | ecdh | rsa | srp,
+ PublicKey :: dh_public() | ecdh_public() | rsa_public() | srp_public(),
+ PrivKeyOut :: dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()},
+ Params :: dh_params() | ecdh_params() | rsa_params() | srp_gen_params()
+ .
generate_key(Type, Params) ->
generate_key(Type, Params, undefined).
+-spec generate_key(Type, Params, PrivKeyIn)
+ -> {PublicKey, PrivKeyOut}
+ when Type :: dh | ecdh | rsa | srp,
+ PublicKey :: dh_public() | ecdh_public() | rsa_public() | srp_public(),
+ PrivKeyIn :: undefined | dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()},
+ PrivKeyOut :: dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()},
+ Params :: dh_params() | ecdh_params() | rsa_params() | srp_comp_params()
+ .
+
generate_key(dh, DHParameters0, PrivateKey) ->
{DHParameters, Len} =
case DHParameters0 of
@@ -512,9 +1029,26 @@ generate_key(rsa, {ModulusSize, PublicExponent}, undefined) ->
{lists:sublist(Private, 2), Private}
end;
+
+generate_key(ecdh, Curve, undefined) when Curve == x448 ;
+ Curve == x25519 ->
+ evp_generate_key_nif(Curve);
generate_key(ecdh, Curve, PrivKey) ->
ec_key_generate(nif_curve_params(Curve), ensure_int_as_bin(PrivKey)).
+
+evp_generate_key_nif(_Curve) -> ?nif_stub.
+
+
+-spec compute_key(Type, OthersPublicKey, MyPrivateKey, Params)
+ -> SharedSecret
+ when Type :: dh | ecdh | srp,
+ SharedSecret :: binary(),
+ OthersPublicKey :: dh_public() | ecdh_public() | srp_public(),
+ MyPrivateKey :: dh_private() | ecdh_private() | {srp_public(),srp_private()},
+ Params :: dh_params() | ecdh_params() | srp_comp_params()
+ .
+
compute_key(dh, OthersPublicKey, MyPrivateKey, DHParameters) ->
case dh_compute_key_nif(ensure_int_as_bin(OthersPublicKey),
ensure_int_as_bin(MyPrivateKey),
@@ -554,15 +1088,373 @@ compute_key(srp, UserPublic, {HostPublic, HostPrivate},
srp_host_secret_nif(Verifier, ensure_int_as_bin(HostPrivate), Scrambler,
UserPubBin, Prime));
+compute_key(ecdh, Others, My, Curve) when Curve == x448 ;
+ Curve == x25519 ->
+ evp_compute_key_nif(Curve, ensure_int_as_bin(Others), ensure_int_as_bin(My));
+
compute_key(ecdh, Others, My, Curve) ->
ecdh_compute_key_nif(ensure_int_as_bin(Others),
nif_curve_params(Curve),
ensure_int_as_bin(My)).
+
+evp_compute_key_nif(_Curve, _OthersBin, _MyBin) -> ?nif_stub.
+
+
+%%%================================================================
+%%%
+%%% XOR - xor to iolists and return a binary
+%%% NB doesn't check that they are the same size, just concatenates
+%%% them and sends them to the driver
+%%%
+%%%================================================================
+
+-spec exor(iodata(), iodata()) -> binary().
+
+exor(Bin1, Bin2) ->
+ Data1 = iolist_to_binary(Bin1),
+ Data2 = iolist_to_binary(Bin2),
+ MaxBytes = max_bytes(),
+ exor(Data1, Data2, erlang:byte_size(Data1), MaxBytes, []).
+
+
+%%%================================================================
+%%%
+%%% Exponentiation modulo
+%%%
+%%%================================================================
+
+-spec mod_pow(N, P, M) -> Result when N :: binary() | integer(),
+ P :: binary() | integer(),
+ M :: binary() | integer(),
+ Result :: binary() | error .
+mod_pow(Base, Exponent, Prime) ->
+ case mod_exp_nif(ensure_int_as_bin(Base), ensure_int_as_bin(Exponent), ensure_int_as_bin(Prime), 0) of
+ <<0>> -> error;
+ R -> R
+ end.
+
+%%%======================================================================
+%%%
+%%% Engine functions
+%%%
+%%%======================================================================
+
+%%%---- Refering to keys stored in an engine:
+-type key_id() :: string() | binary() .
+-type password() :: string() | binary() .
+
+-type engine_key_ref() :: #{engine := engine_ref(),
+ key_id := key_id(),
+ password => password(),
+ term() => term()
+ }.
+
+%%%---- Commands:
+-type engine_cmnd() :: {unicode:chardata(), unicode:chardata()}.
+
+%%----------------------------------------------------------------------
+%% Function: engine_get_all_methods/0
+%%----------------------------------------------------------------------
+-type engine_method_type() :: engine_method_rsa | engine_method_dsa | engine_method_dh |
+ engine_method_rand | engine_method_ecdh | engine_method_ecdsa |
+ engine_method_ciphers | engine_method_digests | engine_method_store |
+ engine_method_pkey_meths | engine_method_pkey_asn1_meths |
+ engine_method_ec.
+
+-type engine_ref() :: term().
+
+-spec engine_get_all_methods() -> Result when Result :: [engine_method_type()].
+engine_get_all_methods() ->
+ notsup_to_error(engine_get_all_methods_nif()).
+
+%%----------------------------------------------------------------------
+%% Function: engine_load/3
+%%----------------------------------------------------------------------
+-spec engine_load(EngineId, PreCmds, PostCmds) ->
+ Result when EngineId::unicode:chardata(),
+ PreCmds::[engine_cmnd()],
+ PostCmds::[engine_cmnd()],
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
+engine_load(EngineId, PreCmds, PostCmds) when is_list(PreCmds),
+ is_list(PostCmds) ->
+ engine_load(EngineId, PreCmds, PostCmds, engine_get_all_methods()).
+
+%%----------------------------------------------------------------------
+%% Function: engine_load/4
+%%----------------------------------------------------------------------
+-spec engine_load(EngineId, PreCmds, PostCmds, EngineMethods) ->
+ Result when EngineId::unicode:chardata(),
+ PreCmds::[engine_cmnd()],
+ PostCmds::[engine_cmnd()],
+ EngineMethods::[engine_method_type()],
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
+engine_load(EngineId, PreCmds, PostCmds, EngineMethods) when is_list(PreCmds),
+ is_list(PostCmds) ->
+ try
+ ok = notsup_to_error(engine_load_dynamic_nif()),
+ case notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId))) of
+ {ok, Engine} ->
+ engine_load_1(Engine, PreCmds, PostCmds, EngineMethods);
+ {error, Error1} ->
+ {error, Error1}
+ end
+ catch
+ throw:Error2 ->
+ Error2
+ end.
+
+engine_load_1(Engine, PreCmds, PostCmds, EngineMethods) ->
+ try
+ ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PreCmds), 0)),
+ ok = engine_nif_wrapper(engine_init_nif(Engine)),
+ engine_load_2(Engine, PostCmds, EngineMethods),
+ {ok, Engine}
+ catch
+ throw:Error ->
+ %% The engine couldn't initialise, release the structural reference
+ ok = engine_free_nif(Engine),
+ throw(Error)
+ end.
+
+engine_load_2(Engine, PostCmds, EngineMethods) ->
+ try
+ ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PostCmds), 0)),
+ [ok = engine_nif_wrapper(engine_register_nif(Engine, engine_method_atom_to_int(Method))) ||
+ Method <- EngineMethods],
+ ok
+ catch
+ throw:Error ->
+ %% The engine registration failed, release the functional reference
+ ok = engine_finish_nif(Engine),
+ throw(Error)
+ end.
+
+%%----------------------------------------------------------------------
+%% Function: engine_unload/1
+%%----------------------------------------------------------------------
+-spec engine_unload(Engine) -> Result when Engine :: engine_ref(),
+ Result :: ok | {error, Reason::term()}.
+engine_unload(Engine) ->
+ engine_unload(Engine, engine_get_all_methods()).
+
+-spec engine_unload(Engine, EngineMethods) -> Result when Engine :: engine_ref(),
+ EngineMethods :: [engine_method_type()],
+ Result :: ok | {error, Reason::term()}.
+engine_unload(Engine, EngineMethods) ->
+ try
+ [ok = engine_nif_wrapper(engine_unregister_nif(Engine, engine_method_atom_to_int(Method))) ||
+ Method <- EngineMethods],
+ %% Release the functional reference from engine_init_nif
+ ok = engine_nif_wrapper(engine_finish_nif(Engine)),
+ %% Release the structural reference from engine_by_id_nif
+ ok = engine_nif_wrapper(engine_free_nif(Engine))
+ catch
+ throw:Error ->
+ Error
+ end.
+
+%%----------------------------------------------------------------------
+%% Function: engine_by_id/1
+%%----------------------------------------------------------------------
+-spec engine_by_id(EngineId) -> Result when EngineId :: unicode:chardata(),
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()} .
+engine_by_id(EngineId) ->
+ try
+ notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId)))
+ catch
+ throw:Error ->
+ Error
+ end.
+
+%%----------------------------------------------------------------------
+%% Function: engine_add/1
+%%----------------------------------------------------------------------
+-spec engine_add(Engine) -> Result when Engine :: engine_ref(),
+ Result :: ok | {error, Reason::term()} .
+engine_add(Engine) ->
+ notsup_to_error(engine_add_nif(Engine)).
+
+%%----------------------------------------------------------------------
+%% Function: engine_remove/1
+%%----------------------------------------------------------------------
+-spec engine_remove(Engine) -> Result when Engine :: engine_ref(),
+ Result :: ok | {error, Reason::term()} .
+engine_remove(Engine) ->
+ notsup_to_error(engine_remove_nif(Engine)).
+
+%%----------------------------------------------------------------------
+%% Function: engine_get_id/1
+%%----------------------------------------------------------------------
+-spec engine_get_id(Engine) -> EngineId when Engine :: engine_ref(),
+ EngineId :: unicode:chardata().
+engine_get_id(Engine) ->
+ notsup_to_error(engine_get_id_nif(Engine)).
+
+%%----------------------------------------------------------------------
+%% Function: engine_get_name/1
+%%----------------------------------------------------------------------
+-spec engine_get_name(Engine) -> EngineName when Engine :: engine_ref(),
+ EngineName :: unicode:chardata().
+engine_get_name(Engine) ->
+ notsup_to_error(engine_get_name_nif(Engine)).
+
+%%----------------------------------------------------------------------
+%% Function: engine_list/0
+%%----------------------------------------------------------------------
+-spec engine_list() -> Result when Result :: [EngineId::unicode:chardata()].
+engine_list() ->
+ case notsup_to_error(engine_get_first_nif()) of
+ {ok, <<>>} ->
+ [];
+ {ok, Engine} ->
+ case notsup_to_error(engine_get_id_nif(Engine)) of
+ <<>> ->
+ engine_list(Engine, []);
+ EngineId ->
+ engine_list(Engine, [EngineId])
+ end
+ end.
+
+engine_list(Engine0, IdList) ->
+ case notsup_to_error(engine_get_next_nif(Engine0)) of
+ {ok, <<>>} ->
+ lists:reverse(IdList);
+ {ok, Engine1} ->
+ case notsup_to_error(engine_get_id_nif(Engine1)) of
+ <<>> ->
+ engine_list(Engine1, IdList);
+ EngineId ->
+ engine_list(Engine1, [EngineId |IdList])
+ end
+ end.
+
+%%----------------------------------------------------------------------
+%% Function: engine_ctrl_cmd_string/3
+%%----------------------------------------------------------------------
+-spec engine_ctrl_cmd_string(Engine, CmdName, CmdArg) ->
+ Result when Engine::term(),
+ CmdName::unicode:chardata(),
+ CmdArg::unicode:chardata(),
+ Result :: ok | {error, Reason::term()}.
+engine_ctrl_cmd_string(Engine, CmdName, CmdArg) ->
+ engine_ctrl_cmd_string(Engine, CmdName, CmdArg, false).
+
+%%----------------------------------------------------------------------
+%% Function: engine_ctrl_cmd_string/4
+%%----------------------------------------------------------------------
+-spec engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) ->
+ Result when Engine::term(),
+ CmdName::unicode:chardata(),
+ CmdArg::unicode:chardata(),
+ Optional::boolean(),
+ Result :: ok | {error, Reason::term()}.
+engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) ->
+ case engine_ctrl_cmd_strings_nif(Engine,
+ ensure_bin_cmds([{CmdName, CmdArg}]),
+ bool_to_int(Optional)) of
+ ok ->
+ ok;
+ notsup ->
+ erlang:error(notsup);
+ {error, Error} ->
+ {error, Error}
+ end.
+
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_loaded/2
+%% Special version of load that only uses dynamic engine to load
+%%----------------------------------------------------------------------
+-spec ensure_engine_loaded(EngineId, LibPath) ->
+ Result when EngineId :: unicode:chardata(),
+ LibPath :: unicode:chardata(),
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
+ensure_engine_loaded(EngineId, LibPath) ->
+ ensure_engine_loaded(EngineId, LibPath, engine_get_all_methods()).
+
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_loaded/3
+%% Special version of load that only uses dynamic engine to load
+%%----------------------------------------------------------------------
+-spec ensure_engine_loaded(EngineId, LibPath, EngineMethods) ->
+ Result when EngineId :: unicode:chardata(),
+ LibPath :: unicode:chardata(),
+ EngineMethods :: [engine_method_type()],
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
+ensure_engine_loaded(EngineId, LibPath, EngineMethods) ->
+ try
+ List = crypto:engine_list(),
+ case lists:member(EngineId, List) of
+ true ->
+ notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId)));
+ false ->
+ ok = notsup_to_error(engine_load_dynamic_nif()),
+ case notsup_to_error(engine_by_id_nif(ensure_bin_chardata(<<"dynamic">>))) of
+ {ok, Engine} ->
+ PreCommands = [{<<"SO_PATH">>, ensure_bin_chardata(LibPath)},
+ {<<"ID">>, ensure_bin_chardata(EngineId)},
+ <<"LOAD">>],
+ ensure_engine_loaded_1(Engine, PreCommands, EngineMethods);
+ {error, Error1} ->
+ {error, Error1}
+ end
+ end
+ catch
+ throw:Error2 ->
+ Error2
+ end.
+
+ensure_engine_loaded_1(Engine, PreCmds, Methods) ->
+ try
+ ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PreCmds), 0)),
+ ok = engine_nif_wrapper(engine_add_nif(Engine)),
+ ok = engine_nif_wrapper(engine_init_nif(Engine)),
+ ensure_engine_loaded_2(Engine, Methods),
+ {ok, Engine}
+ catch
+ throw:Error ->
+ %% The engine couldn't initialise, release the structural reference
+ ok = engine_free_nif(Engine),
+ throw(Error)
+ end.
+
+ensure_engine_loaded_2(Engine, Methods) ->
+ try
+ [ok = engine_nif_wrapper(engine_register_nif(Engine, engine_method_atom_to_int(Method))) ||
+ Method <- Methods],
+ ok
+ catch
+ throw:Error ->
+ %% The engine registration failed, release the functional reference
+ ok = engine_finish_nif(Engine),
+ throw(Error)
+ end.
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_unloaded/1
+%%----------------------------------------------------------------------
+-spec ensure_engine_unloaded(Engine) -> Result when Engine :: engine_ref(),
+ Result :: ok | {error, Reason::term()}.
+ensure_engine_unloaded(Engine) ->
+ ensure_engine_unloaded(Engine, engine_get_all_methods()).
+
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_unloaded/2
+%%----------------------------------------------------------------------
+-spec ensure_engine_unloaded(Engine, EngineMethods) ->
+ Result when Engine :: engine_ref(),
+ EngineMethods :: [engine_method_type()],
+ Result :: ok | {error, Reason::term()}.
+ensure_engine_unloaded(Engine, EngineMethods) ->
+ case engine_remove(Engine) of
+ ok ->
+ engine_unload(Engine, EngineMethods);
+ {error, E} ->
+ {error, E}
+ end.
+
%%--------------------------------------------------------------------
%%% On load
%%--------------------------------------------------------------------
-
on_load() ->
LibBaseName = "crypto",
PrivDir = code:priv_dir(crypto),
@@ -609,8 +1501,13 @@ on_load() ->
case Status of
ok -> ok;
{error, {E, Str}} ->
- error_logger:error_msg("Unable to load crypto library. Failed with error:~n\"~p, ~s\"~n"
- "OpenSSL might not be installed on this system.~n",[E,Str]),
+ Fmt = "Unable to load crypto library. Failed with error:~n\"~p, ~s\"~n~s",
+ Extra = case E of
+ load_failed ->
+ "OpenSSL might not be installed on this system.\n";
+ _ -> ""
+ end,
+ error_logger:error_msg(Fmt, [E,Str,Extra]),
Status
end.
@@ -621,9 +1518,13 @@ path2bin(Path) when is_list(Path) ->
Bin
end.
-%%--------------------------------------------------------------------
-%%% Internal functions
-%%--------------------------------------------------------------------
+%%%================================================================
+%%%================================================================
+%%%
+%%% Internal functions
+%%%
+%%%================================================================
+
max_bytes() ->
?MAX_BYTES_TO_NIF.
@@ -683,9 +1584,12 @@ hmac_final_nif(_Context) -> ?nif_stub.
hmac_final_nif(_Context, _MacSize) -> ?nif_stub.
%% CMAC
-
cmac_nif(_Type, _Key, _Data) -> ?nif_stub.
+%% POLY1305
+poly1305_nif(_Key, _Data) -> ?nif_stub.
+
+
%% CIPHERS --------------------------------------------------------------------
block_crypt_nif(_Type, _Key, _Ivec, _Text, _IsEncrypt) -> ?nif_stub.
@@ -705,16 +1609,11 @@ check_des3_key(Key) ->
%% AES - in Galois/Counter Mode (GCM)
%%
%% The default tag length is EVP_GCM_TLS_TAG_LEN(16),
-aes_gcm_encrypt(Key, Ivec, AAD, In) ->
- aes_gcm_encrypt(Key, Ivec, AAD, In, 16).
-aes_gcm_encrypt(_Key, _Ivec, _AAD, _In, _TagLength) -> ?nif_stub.
-aes_gcm_decrypt(_Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub.
+aead_encrypt(Type=aes_ccm, Key, Ivec, AAD, In) -> aead_encrypt(Type, Key, Ivec, AAD, In, 12);
+aead_encrypt(Type=aes_gcm, Key, Ivec, AAD, In) -> aead_encrypt(Type, Key, Ivec, AAD, In, 16).
-%%
-%% Chacha20/Ppoly1305
-%%
-chacha20_poly1305_encrypt(_Key, _Ivec, _AAD, _In) -> ?nif_stub.
-chacha20_poly1305_decrypt(_Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub.
+aead_encrypt(_Type, _Key, _Ivec, _AAD, _In, _TagLength) -> ?nif_stub.
+aead_decrypt(_Type, _Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub.
%%
%% AES - with 256 bit key in infinite garble extension mode (IGE)
@@ -740,37 +1639,42 @@ do_stream_encrypt({aes_ctr, State0}, Data) ->
{{aes_ctr, State}, Cipher};
do_stream_encrypt({rc4, State0}, Data) ->
{State, Cipher} = rc4_encrypt_with_state(State0, Data),
- {{rc4, State}, Cipher}.
+ {{rc4, State}, Cipher};
+do_stream_encrypt({chacha20, State0}, Data) ->
+ {State, Cipher} = chacha20_stream_encrypt(State0, Data),
+ {{chacha20, State}, Cipher}.
do_stream_decrypt({aes_ctr, State0}, Data) ->
{State, Text} = aes_ctr_stream_decrypt(State0, Data),
{{aes_ctr, State}, Text};
do_stream_decrypt({rc4, State0}, Data) ->
{State, Text} = rc4_encrypt_with_state(State0, Data),
- {{rc4, State}, Text}.
+ {{rc4, State}, Text};
+do_stream_decrypt({chacha20, State0}, Data) ->
+ {State, Cipher} = chacha20_stream_decrypt(State0, Data),
+ {{chacha20, State}, Cipher}.
%%
-%% AES - in counter mode (CTR) with state maintained for multi-call streaming
+%% AES - in counter mode (CTR) with state maintained for multi-call streaming
%%
--type ctr_state() :: { iodata(), binary(), binary(), integer() } | binary().
-
--spec aes_ctr_stream_init(iodata(), binary()) -> ctr_state().
--spec aes_ctr_stream_encrypt(ctr_state(), binary()) ->
- { ctr_state(), binary() }.
--spec aes_ctr_stream_decrypt(ctr_state(), binary()) ->
- { ctr_state(), binary() }.
-
aes_ctr_stream_init(_Key, _IVec) -> ?nif_stub.
aes_ctr_stream_encrypt(_State, _Data) -> ?nif_stub.
aes_ctr_stream_decrypt(_State, _Cipher) -> ?nif_stub.
-
+
%%
%% RC4 - symmetric stream cipher
%%
rc4_set_key(_Key) -> ?nif_stub.
rc4_encrypt_with_state(_State, _Data) -> ?nif_stub.
+%%
+%% CHACHA20 - stream cipher
+%%
+chacha20_stream_init(_Key, _IVec) -> ?nif_stub.
+chacha20_stream_encrypt(_State, _Data) -> ?nif_stub.
+chacha20_stream_decrypt(_State, _Data) -> ?nif_stub.
+
%% Secure remote password -------------------------------------------------------------------
user_srp_gen_key(Private, Generator, Prime) ->
@@ -837,15 +1741,6 @@ srp_user_secret_nif(_A, _U, _B, _Multiplier, _Generator, _Exponent, _Prime) -> ?
srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_stub.
-%% Digital signatures --------------------------------------------------------------------
-rsa_sign_nif(_Type,_Digest,_Key) -> ?nif_stub.
-dss_sign_nif(_Type,_Digest,_Key) -> ?nif_stub.
-ecdsa_sign_nif(_Type, _Digest, _Curve, _Key) -> ?nif_stub.
-
-dss_verify_nif(_Type, _Digest, _Signature, _Key) -> ?nif_stub.
-rsa_verify_nif(_Type, _Digest, _Signature, _Key) -> ?nif_stub.
-ecdsa_verify_nif(_Type, _Digest, _Signature, _Curve, _Key) -> ?nif_stub.
-
%% Public Keys --------------------------------------------------------------------
%% RSA Rivest-Shamir-Adleman functions
%%
@@ -853,28 +1748,7 @@ ecdsa_verify_nif(_Type, _Digest, _Signature, _Curve, _Key) -> ?nif_stub.
rsa_generate_key_nif(_Bits, _Exp) -> ?nif_stub.
%% DH Diffie-Hellman functions
-%%
-
-%% Generate (and check) Parameters is not documented because they are implemented
-%% for testing (and offline parameter generation) only.
-%% From the openssl doc:
-%% DH_generate_parameters() may run for several hours before finding a suitable prime.
-%% Thus dh_generate_parameters may in this implementation block
-%% the emulator for several hours.
%%
-%% usage: dh_generate_parameters(1024, 2 or 5) ->
-%% [Prime=mpint(), SharedGenerator=mpint()]
-dh_generate_parameters(PrimeLen, Generator) ->
- case dh_generate_parameters_nif(PrimeLen, Generator) of
- error -> erlang:error(generation_failed, [PrimeLen,Generator]);
- Ret -> Ret
- end.
-
-dh_generate_parameters_nif(_PrimeLen, _Generator) -> ?nif_stub.
-
-%% Checks that the DHParameters are ok.
-%% DHParameters = [P (Prime)= mpint(), G(Generator) = mpint()]
-dh_check([_Prime,_Gen]) -> ?nif_stub.
%% DHParameters = [P (Prime)= mpint(), G(Generator) = mpint()]
%% PrivKey = mpint()
@@ -888,12 +1762,37 @@ ec_key_generate(_Curve, _Key) -> ?nif_stub.
ecdh_compute_key_nif(_Others, _Curve, _My) -> ?nif_stub.
+-spec ec_curves() -> [EllipticCurve] when EllipticCurve :: ec_named_curve() | edwards_curve() .
+
ec_curves() ->
crypto_ec_curves:curves().
+-spec ec_curve(CurveName) -> ExplicitCurve when CurveName :: ec_named_curve(),
+ ExplicitCurve :: ec_explicit_curve() .
ec_curve(X) ->
crypto_ec_curves:curve(X).
+
+-spec privkey_to_pubkey(Type, EnginePrivateKeyRef) -> PublicKey when Type :: rsa | dss,
+ EnginePrivateKeyRef :: engine_key_ref(),
+ PublicKey :: rsa_public() | dss_public() .
+privkey_to_pubkey(Alg, EngineMap) when Alg == rsa; Alg == dss; Alg == ecdsa ->
+ try privkey_to_pubkey_nif(Alg, format_pkey(Alg,EngineMap))
+ of
+ [_|_]=L -> map_ensure_bin_as_int(L);
+ X -> X
+ catch
+ error:badarg when Alg==ecdsa ->
+ {error, notsup};
+ error:badarg ->
+ {error, not_found};
+ error:notsup ->
+ {error, notsup}
+ end.
+
+privkey_to_pubkey_nif(_Alg, _EngineMap) -> ?nif_stub.
+
+
%%
%% EC
%%
@@ -902,13 +1801,23 @@ term_to_nif_prime({prime_field, Prime}) ->
{prime_field, ensure_int_as_bin(Prime)};
term_to_nif_prime(PrimeField) ->
PrimeField.
+
term_to_nif_curve({A, B, Seed}) ->
{ensure_int_as_bin(A), ensure_int_as_bin(B), Seed}.
+
nif_curve_params({PrimeField, Curve, BasePoint, Order, CoFactor}) ->
- {term_to_nif_prime(PrimeField), term_to_nif_curve(Curve), ensure_int_as_bin(BasePoint), ensure_int_as_bin(Order), ensure_int_as_bin(CoFactor)};
+ {term_to_nif_prime(PrimeField),
+ term_to_nif_curve(Curve),
+ ensure_int_as_bin(BasePoint),
+ ensure_int_as_bin(Order),
+ ensure_int_as_bin(CoFactor)};
nif_curve_params(Curve) when is_atom(Curve) ->
%% named curve
- crypto_ec_curves:curve(Curve).
+ case Curve of
+ x448 -> {evp,Curve};
+ x25519 -> {evp,Curve};
+ _ -> crypto_ec_curves:curve(Curve)
+ end.
%% MISC --------------------------------------------------------------------
@@ -941,6 +1850,7 @@ int_to_bin_neg(-1, Ds=[MSB|_]) when MSB >= 16#80 ->
int_to_bin_neg(X,Ds) ->
int_to_bin_neg(X bsr 8, [(X band 255)|Ds]).
+-spec bytes_to_integer(binary()) -> integer() .
bytes_to_integer(Bin) ->
bin_to_int(Bin).
@@ -961,19 +1871,39 @@ ensure_int_as_bin(Int) when is_integer(Int) ->
ensure_int_as_bin(Bin) ->
Bin.
+map_ensure_bin_as_int(List) when is_list(List) ->
+ lists:map(fun ensure_bin_as_int/1, List).
+
+ensure_bin_as_int(Bin) when is_binary(Bin) ->
+ bin_to_int(Bin);
+ensure_bin_as_int(E) ->
+ E.
+
+format_pkey(_Alg, #{engine:=_, key_id:=T}=M) when is_binary(T) -> format_pwd(M);
+format_pkey(_Alg, #{engine:=_, key_id:=T}=M) when is_list(T) -> format_pwd(M#{key_id:=list_to_binary(T)});
+format_pkey(_Alg, #{engine:=_ }=M) -> error({bad_key_id, M});
+format_pkey(_Alg, #{}=M) -> error({bad_engine_map, M});
+%%%
+format_pkey(rsa, Key) ->
+ map_ensure_int_as_bin(Key);
+format_pkey(ecdsa, [Key, Curve]) ->
+ {nif_curve_params(Curve), ensure_int_as_bin(Key)};
+format_pkey(dss, Key) ->
+ map_ensure_int_as_bin(Key);
+format_pkey(_, Key) ->
+ Key.
+
+format_pwd(#{password := Pwd}=M) when is_list(Pwd) -> M#{password := list_to_binary(Pwd)};
+format_pwd(M) -> M.
+
%%--------------------------------------------------------------------
%%
--type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding' | 'rsa_no_padding'.
-
-rsa_public_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub.
-
-rsa_private_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub.
%% large integer in a binary with 32bit length
%% MP representaion (SSH2)
mpint(X) when X < 0 -> mpint_neg(X);
mpint(X) -> mpint_pos(X).
-
+
-define(UINT32(X), X:32/unsigned-big-integer).
@@ -981,7 +1911,7 @@ mpint_neg(X) ->
Bin = int_to_bin_neg(X, []),
Sz = byte_size(Bin),
<<?UINT32(Sz), Bin/binary>>.
-
+
mpint_pos(X) ->
Bin = int_to_bin_pos(X, []),
<<MSB,_/binary>> = Bin,
@@ -1003,3 +1933,105 @@ erlint(<<MPIntSize:32/integer,MPIntValue/binary>>) ->
%%
mod_exp_nif(_Base,_Exp,_Mod,_bin_hdr) -> ?nif_stub.
+%%%----------------------------------------------------------------
+%% 9470495 == V(0,9,8,zh).
+%% 268435615 == V(1,0,0,i).
+%% 268439663 == V(1,0,1,f).
+
+packed_openssl_version(MAJ, MIN, FIX, P0) ->
+ %% crypto.c
+ P1 = atom_to_list(P0),
+ P = lists:sum([C-$a||C<-P1]),
+ ((((((((MAJ bsl 8) bor MIN) bsl 8 ) bor FIX) bsl 8) bor (P+1)) bsl 4) bor 16#f).
+
+%%--------------------------------------------------------------------
+%% Engine nifs
+engine_by_id_nif(_EngineId) -> ?nif_stub.
+engine_init_nif(_Engine) -> ?nif_stub.
+engine_finish_nif(_Engine) -> ?nif_stub.
+engine_free_nif(_Engine) -> ?nif_stub.
+engine_load_dynamic_nif() -> ?nif_stub.
+engine_ctrl_cmd_strings_nif(_Engine, _Cmds, _Optional) -> ?nif_stub.
+engine_add_nif(_Engine) -> ?nif_stub.
+engine_remove_nif(_Engine) -> ?nif_stub.
+engine_register_nif(_Engine, _EngineMethod) -> ?nif_stub.
+engine_unregister_nif(_Engine, _EngineMethod) -> ?nif_stub.
+engine_get_first_nif() -> ?nif_stub.
+engine_get_next_nif(_Engine) -> ?nif_stub.
+engine_get_id_nif(_Engine) -> ?nif_stub.
+engine_get_name_nif(_Engine) -> ?nif_stub.
+engine_get_all_methods_nif() -> ?nif_stub.
+
+%%--------------------------------------------------------------------
+%% Engine internals
+engine_nif_wrapper(ok) ->
+ ok;
+engine_nif_wrapper(notsup) ->
+ erlang:error(notsup);
+engine_nif_wrapper({error, Error}) ->
+ throw({error, Error}).
+
+ensure_bin_chardata(CharData) when is_binary(CharData) ->
+ CharData;
+ensure_bin_chardata(CharData) ->
+ unicode:characters_to_binary(CharData).
+
+ensure_bin_cmds(CMDs) ->
+ ensure_bin_cmds(CMDs, []).
+
+ensure_bin_cmds([], Acc) ->
+ lists:reverse(Acc);
+ensure_bin_cmds([{Key, Value} |CMDs], Acc) ->
+ ensure_bin_cmds(CMDs, [{ensure_bin_chardata(Key), ensure_bin_chardata(Value)} | Acc]);
+ensure_bin_cmds([Key | CMDs], Acc) ->
+ ensure_bin_cmds(CMDs, [{ensure_bin_chardata(Key), <<"">>} | Acc]).
+
+engine_methods_convert_to_bitmask([], BitMask) ->
+ BitMask;
+engine_methods_convert_to_bitmask(engine_method_all, _BitMask) ->
+ 16#FFFF;
+engine_methods_convert_to_bitmask(engine_method_none, _BitMask) ->
+ 16#0000;
+engine_methods_convert_to_bitmask([M |Ms], BitMask) ->
+ engine_methods_convert_to_bitmask(Ms, BitMask bor engine_method_atom_to_int(M)).
+
+bool_to_int(true) -> 1;
+bool_to_int(false) -> 0.
+
+engine_method_atom_to_int(engine_method_rsa) -> 16#0001;
+engine_method_atom_to_int(engine_method_dsa) -> 16#0002;
+engine_method_atom_to_int(engine_method_dh) -> 16#0004;
+engine_method_atom_to_int(engine_method_rand) -> 16#0008;
+engine_method_atom_to_int(engine_method_ecdh) -> 16#0010;
+engine_method_atom_to_int(engine_method_ecdsa) -> 16#0020;
+engine_method_atom_to_int(engine_method_ciphers) -> 16#0040;
+engine_method_atom_to_int(engine_method_digests) -> 16#0080;
+engine_method_atom_to_int(engine_method_store) -> 16#0100;
+engine_method_atom_to_int(engine_method_pkey_meths) -> 16#0200;
+engine_method_atom_to_int(engine_method_pkey_asn1_meths) -> 16#0400;
+engine_method_atom_to_int(engine_method_ec) -> 16#0800;
+engine_method_atom_to_int(X) ->
+ erlang:error(badarg, [X]).
+
+get_test_engine() ->
+ Type = erlang:system_info(system_architecture),
+ LibDir = filename:join([code:priv_dir(crypto), "lib"]),
+ ArchDir = filename:join([LibDir, Type]),
+ case filelib:is_dir(ArchDir) of
+ true -> check_otp_test_engine(ArchDir);
+ false -> check_otp_test_engine(LibDir)
+ end.
+
+check_otp_test_engine(LibDir) ->
+ case filelib:wildcard("otp_test_engine*", LibDir) of
+ [] ->
+ {error, notexist};
+ [LibName] ->
+ LibPath = filename:join(LibDir,LibName),
+ case filelib:is_file(LibPath) of
+ true ->
+ {ok, unicode:characters_to_binary(LibPath)};
+ false ->
+ {error, notexist}
+ end
+ end.
diff --git a/lib/crypto/src/crypto_ec_curves.erl b/lib/crypto/src/crypto_ec_curves.erl
index 9602a7e24b..a0a2f99601 100644
--- a/lib/crypto/src/crypto_ec_curves.erl
+++ b/lib/crypto/src/crypto_ec_curves.erl
@@ -3,41 +3,7 @@
-export([curve/1, curves/0]).
curves() ->
- CryptoSupport = crypto:supports(),
- PubKeys = proplists:get_value(public_keys, CryptoSupport),
- HasEC = proplists:get_bool(ecdh, PubKeys),
- HasGF2m = proplists:get_bool(ec_gf2m, PubKeys),
- FIPSMode = crypto:info_fips() == enabled,
- prime_curves(HasEC, FIPSMode) ++ characteristic_two_curves(HasGF2m, FIPSMode).
-
-
-prime_curves(true, true) ->
- [secp160k1,secp160r1,secp160r2,
- secp192r1,secp192k1,secp224k1,secp224r1,secp256k1,secp256r1,secp384r1,
- secp521r1,prime192v1,prime192v2,prime192v3,prime239v1,prime239v2,prime239v3,
- prime256v1,wtls7,wtls9,wtls12,
- brainpoolP160r1,brainpoolP160t1,brainpoolP192r1,brainpoolP192t1,
- brainpoolP224r1,brainpoolP224t1,brainpoolP256r1,brainpoolP256t1,
- brainpoolP320r1,brainpoolP320t1,brainpoolP384r1,brainpoolP384t1,
- brainpoolP512r1,brainpoolP512t1];
-prime_curves(true, false) ->
- [secp112r1,secp112r2,secp128r1,secp128r2,wtls6,wtls8]
- ++ prime_curves(true, true);
-prime_curves(_, _) ->
- [].
-
-characteristic_two_curves(true, true) ->
- [sect163k1,sect163r1,
- sect163r2,sect193r1,sect193r2,sect233k1,sect233r1,sect239k1,sect283k1,
- sect283r1,sect409k1,sect409r1,sect571k1,sect571r1,c2pnb163v1,c2pnb163v2,
- c2pnb163v3,c2pnb176v1,c2tnb191v1,c2tnb191v2,c2tnb191v3,c2pnb208w1,c2tnb239v1,
- c2tnb239v2,c2tnb239v3,c2pnb272w1,c2pnb304w1,c2tnb359v1,c2pnb368w1,c2tnb431r1,
- wtls3,wtls5,wtls10,wtls11];
-characteristic_two_curves(true, _) ->
- [sect113r1,sect113r2,sect131r1,sect131r2,wtls1,wtls4,ipsec3,ipsec4]
- ++ characteristic_two_curves(true, true);
-characteristic_two_curves(_, _) ->
- [].
+ proplists:get_value(curves, crypto:supports()) -- [x25519,x448].
curve(secp112r1) ->
{
diff --git a/lib/crypto/test/Makefile b/lib/crypto/test/Makefile
index 138081d386..e046a25338 100644
--- a/lib/crypto/test/Makefile
+++ b/lib/crypto/test/Makefile
@@ -7,7 +7,8 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
MODULES = \
blowfish_SUITE \
- crypto_SUITE
+ crypto_SUITE \
+ engine_SUITE
ERL_FILES= $(MODULES:%=%.erl)
@@ -27,7 +28,7 @@ RELSYSDIR = $(RELEASE_PATH)/crypto_test
# FLAGS
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS +=
+ERL_COMPILE_FLAGS += +nowarn_export_all
EBIN = .
MAKE_EMAKE = $(wildcard $(ERL_TOP)/make/make_emakefile)
@@ -77,7 +78,7 @@ release_spec:
release_tests_spec: $(TEST_TARGET)
$(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) crypto.spec crypto.cover $(RELTEST_FILES) "$(RELSYSDIR)"
- @tar cfh - crypto_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
+ @tar cfh - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
chmod -R u+w "$(RELSYSDIR)"
release_docs_spec:
diff --git a/lib/crypto/test/blowfish_SUITE.erl b/lib/crypto/test/blowfish_SUITE.erl
index c2d0d2621b..a931ebb47e 100644
--- a/lib/crypto/test/blowfish_SUITE.erl
+++ b/lib/crypto/test/blowfish_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -47,6 +47,11 @@
init_per_suite(Config) ->
case catch crypto:start() of
ok ->
+ catch ct:comment("~s",[element(3,hd(crypto:info_lib()))]),
+ catch ct:log("crypto:info_lib() -> ~p~n"
+ "crypto:supports() -> ~p~n"
+ "crypto:version() -> ~p~n"
+ ,[crypto:info_lib(), crypto:supports(), crypto:version()]),
Config;
_Else ->
{skip,"Could not start crypto!"}
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 164f43dcb0..495c2adb55 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[app,
+ {group, api_errors},
appup,
{group, fips},
{group, non_fips},
@@ -50,6 +51,10 @@ groups() ->
{group, sha256},
{group, sha384},
{group, sha512},
+ {group, sha3_224},
+ {group, sha3_256},
+ {group, sha3_384},
+ {group, sha3_512},
{group, rsa},
{group, dss},
{group, ecdsa},
@@ -74,8 +79,11 @@ groups() ->
{group, rc2_cbc},
{group, rc4},
{group, aes_ctr},
+ {group, aes_ccm},
{group, aes_gcm},
{group, chacha20_poly1305},
+ {group, chacha20},
+ {group, poly1305},
{group, aes_cbc}]},
{fips, [], [{group, no_md4},
{group, no_md5},
@@ -109,8 +117,10 @@ groups() ->
{group, no_rc2_cbc},
{group, no_rc4},
{group, aes_ctr},
+ {group, aes_ccm},
{group, aes_gcm},
{group, no_chacha20_poly1305},
+ {group, no_chacha20},
{group, aes_cbc}]},
{md4, [], [hash]},
{md5, [], [hash, hmac]},
@@ -120,14 +130,24 @@ groups() ->
{sha256, [], [hash, hmac]},
{sha384, [], [hash, hmac]},
{sha512, [], [hash, hmac]},
+ {sha3_224, [], [hash, hmac]},
+ {sha3_256, [], [hash, hmac]},
+ {sha3_384, [], [hash, hmac]},
+ {sha3_512, [], [hash, hmac]},
{rsa, [], [sign_verify,
public_encrypt,
+ private_encrypt,
generate
]},
- {dss, [], [sign_verify]},
- {ecdsa, [], [sign_verify]},
- {dh, [], [generate_compute]},
- {ecdh, [], [compute, generate]},
+ {dss, [], [sign_verify
+ %% Does not work yet: ,public_encrypt, private_encrypt
+ ]},
+ {ecdsa, [], [sign_verify
+ %% Does not work yet: ,public_encrypt, private_encrypt
+ ]},
+ {dh, [], [generate_compute,
+ compute_bug]},
+ {ecdh, [], [generate_all_supported, compute, generate]},
{srp, [], [generate_compute]},
{des_cbc, [], [block]},
{des_cfb, [], [block]},
@@ -148,8 +168,11 @@ groups() ->
{blowfish_ofb64,[], [block]},
{rc4, [], [stream]},
{aes_ctr, [], [stream]},
+ {aes_ccm, [], [aead]},
{aes_gcm, [], [aead]},
{chacha20_poly1305, [], [aead]},
+ {chacha20, [], [stream]},
+ {poly1305, [], [poly1305]},
{aes_cbc, [], [block]},
{no_md4, [], [no_support, no_hash]},
{no_md5, [], [no_support, no_hash, no_hmac]},
@@ -163,8 +186,10 @@ groups() ->
{no_blowfish_ofb64, [], [no_support, no_block]},
{no_aes_ige256, [], [no_support, no_block]},
{no_chacha20_poly1305, [], [no_support, no_aead]},
+ {no_chacha20, [], [no_support, no_stream_ivec]},
{no_rc2_cbc, [], [no_support, no_block]},
- {no_rc4, [], [no_support, no_stream]}
+ {no_rc4, [], [no_support, no_stream]},
+ {api_errors, [], [api_errors_ecdh]}
].
%%-------------------------------------------------------------------
@@ -177,6 +202,12 @@ init_per_suite(Config) ->
try crypto:start() of
ok ->
+ catch ct:comment("~s",[element(3,hd(crypto:info_lib()))]),
+ catch ct:log("crypto:info_lib() -> ~p~n"
+ "crypto:supports() -> ~p~n"
+ "crypto:version() -> ~p~n"
+ ,[crypto:info_lib(), crypto:supports(), crypto:version()]),
+
try crypto:strong_rand_bytes(1) of
_ ->
Config
@@ -187,13 +218,13 @@ init_per_suite(Config) ->
%% This is NOT how you want to do seeding, it is just here
%% to make the tests pass. Check your OS manual for how you
%% really want to seed.
- {H,M,L} = erlang:now(),
+ {H,M,L} = erlang:timestamp(),
Bin = <<H:24,M:20,L:20>>,
crypto:rand_seed(<< <<Bin/binary>> || _ <- lists:seq(1,16) >>),
Config
end
catch _:_ ->
- {skip, "Crypto did not start"}
+ {fail, "Crypto did not start"}
end.
end_per_suite(_Config) ->
@@ -226,6 +257,8 @@ init_per_group(non_fips, Config) ->
_NotEnabled ->
NonFIPSConfig
end;
+init_per_group(api_errors, Config) ->
+ Config;
init_per_group(GroupName, Config) ->
case atom_to_list(GroupName) of
"no_" ++ TypeStr ->
@@ -340,6 +373,20 @@ cmac(Config) when is_list(Config) ->
lists:foreach(fun cmac_check/1, Pairs),
lists:foreach(fun cmac_check/1, cmac_iolistify(Pairs)).
%%--------------------------------------------------------------------
+poly1305() ->
+ [{doc, "Test poly1305 function"}].
+poly1305(Config) ->
+ lists:foreach(
+ fun({Key, Txt, Expect}) ->
+ case crypto:poly1305(Key,Txt) of
+ Expect ->
+ ok;
+ Other ->
+ ct:fail({{crypto, poly1305, [Key, Txt]}, {expected, Expect}, {got, Other}})
+ end
+ end, proplists:get_value(poly1305, Config)).
+
+%%--------------------------------------------------------------------
block() ->
[{doc, "Test block ciphers"}].
block(Config) when is_list(Config) ->
@@ -381,12 +428,18 @@ no_block(Config) when is_list(Config) ->
no_aead() ->
[{doc, "Test disabled aead ciphers"}].
no_aead(Config) when is_list(Config) ->
- [{Type, Key, PlainText, Nonce, AAD, CipherText, CipherTag} | _] =
- lazy_eval(proplists:get_value(aead, Config)),
- EncryptArgs = [Type, Key, Nonce, {AAD, PlainText}],
+ EncArg4 =
+ case lazy_eval(proplists:get_value(aead, Config)) of
+ [{Type, Key, PlainText, Nonce, AAD, CipherText, CipherTag, TagLen, _Info} | _] ->
+ {AAD, PlainText, TagLen};
+ [{Type, Key, PlainText, Nonce, AAD, CipherText, CipherTag, _Info} | _] ->
+ {AAD, PlainText}
+ end,
+ EncryptArgs = [Type, Key, Nonce, EncArg4],
DecryptArgs = [Type, Key, Nonce, {AAD, CipherText, CipherTag}],
notsup(fun crypto:block_encrypt/4, EncryptArgs),
notsup(fun crypto:block_decrypt/4, DecryptArgs).
+
%%--------------------------------------------------------------------
stream() ->
[{doc, "Test stream ciphers"}].
@@ -404,6 +457,13 @@ no_stream(Config) when is_list(Config) ->
notsup(fun crypto:stream_init/2, [Type, <<"Key">>]).
%%--------------------------------------------------------------------
+no_stream_ivec() ->
+ [{doc, "Test disabled stream ciphers that uses ivec"}].
+no_stream_ivec(Config) when is_list(Config) ->
+ Type = ?config(type, Config),
+ notsup(fun crypto:stream_init/3, [Type, <<"Key">>, <<"Ivec">>]).
+
+%%--------------------------------------------------------------------
aead() ->
[{doc, "Test AEAD ciphers"}].
aead(Config) when is_list(Config) ->
@@ -433,10 +493,16 @@ sign_verify(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
public_encrypt() ->
- [{doc, "Test public_encrypt/decrypt and private_encrypt/decrypt functions. "}].
+ [{doc, "Test public_encrypt/decrypt "}].
public_encrypt(Config) when is_list(Config) ->
Params = proplists:get_value(pub_priv_encrypt, Config),
- lists:foreach(fun do_public_encrypt/1, Params),
+ lists:foreach(fun do_public_encrypt/1, Params).
+
+%%--------------------------------------------------------------------
+private_encrypt() ->
+ [{doc, "Test private_encrypt/decrypt functions. "}].
+private_encrypt(Config) when is_list(Config) ->
+ Params = proplists:get_value(pub_priv_encrypt, Config),
lists:foreach(fun do_private_encrypt/1, Params).
%%--------------------------------------------------------------------
@@ -446,6 +512,24 @@ generate_compute(Config) when is_list(Config) ->
GenCom = proplists:get_value(generate_compute, Config),
lists:foreach(fun do_generate_compute/1, GenCom).
%%--------------------------------------------------------------------
+compute_bug() ->
+ [{doc, "Test that it works even if the Secret is smaller than expected"}].
+compute_bug(_Config) ->
+ ExpectedSecret = <<118,89,171,16,156,18,156,103,189,134,130,49,28,144,111,241,247,82,79,32,228,11,209,141,119,176,251,80,105,143,235,251,203,121,223,211,129,3,233,133,45,2,31,157,24,111,5,75,153,66,135,185,128,115,229,178,216,39,73,52,80,151,8,241,34,52,226,71,137,167,53,48,59,224,175,154,89,110,76,83,24,117,149,21,72,6,186,78,149,74,188,56,98,244,30,77,108,248,88,194,195,237,23,51,20,242,254,123,21,12,209,74,217,168,230,65,7,60,211,139,128,239,234,153,22,229,180,59,159,121,41,156,121,200,177,130,163,162,54,224,93,1,94,11,177,254,118,28,156,26,116,10,207,145,219,166,214,189,214,230,221,170,228,15,69,88,31,68,94,255,113,58,49,82,86,192,248,176,131,133,39,186,194,172,206,84,184,16,66,68,153,128,178,227,27,118,52,130,122,92,24,222,102,195,221,207,255,13,152,175,65,32,167,84,54,244,243,109,244,18,234,16,159,224,188,2,106,123,27,17,131,171,226,34,111,251,62,119,155,124,221,124,254,62,97,167,1,105,116,98,98,19,197,30,72,180,79,221,100,134,120,117,124,85,73,132,224,223,222,41,155,137,218,130,238,237,157,161,134,150,69,206,91,141,17,89,120,218,235,229,37,150,76,197,7,157,56,144,42,203,137,100,200,72,141,194,239,1,67,236,238,183,48,214,75,76,108,235,3,237,67,40,137,45,182,236,246,37,116,103,144,237,142,211,88,233,11,24,21,218,41,245,250,51,130,250,104,74,189,17,69,145,70,50,50,215,253,155,10,128,41,114,185,211,82,164,72,92,17,145,104,66,6,140,226,80,43,62,1,166,216,153,118,96,15,147,126,137,118,191,192,75,149,241,206,18,92,17,154,215,219,18,6,139,190,103,210,156,184,29,224,213,157,60,112,189,104,220,125,40,186,50,119,17,143,136,149,38,74,107,21,192,59,61,59,42,231,144,59,175,3,176,87,23,16,122,54,31,82,34,230,211,44,81,41,47,86,37,228,175,130,148,88,136,131,254,241,202,99,199,175,1,141,215,124,155,120,43,141,89,11,140,120,141,29,35,82,219,155,204,75,12,66,241,253,33,250,84,24,85,68,13,80,85,142,227,34,139,26,146,24>>,
+ OthersPublicKey = 635619632099733175381667940709387641100492974601603060984753028943194386334921787463327680809776598322996634648015962954045728174069768874873236397421720142610982770302060309928552098274817978606093380781524199673890631795310930242601197479471368910519338301177304682162189801040921618559902948819107531088646753320486728060005223263561551402855338732899079439899705951063999951507319258050864346087428042978411873495523439615429804957374639092580169417598963105885529553632847023899713490485619763926900318508906706745060947269748612049634207985438016935262521715769812475329234748426647554362991758104620357149045960316987533503707855364806010494793980069245562784050236811004893018183726397041999426883788660276453352521120006817370050691205529335316794439089316232980047277245051173281601960196573681285904611182521967067911862467395705665888521948321299521549941618586026714676885890192323289343756440666276226084448279082483536164085883288884231665240707495770544705648564889889198060417915693315346959170105413290799314390963124178046425737828369059171472978294050322371452255088799865552038756937873388385970088906560408959959429398326288750834357514847891423941047433478384621074116184703014798814515161475596555032391555842,
+ MyPrivateKey = 387759582879975726965038486537011291913744975764132199838375902680222019267527675651273586836110220500657652661706223760165097275862806031329642160439090779625708664007910974206651834216043397115514725827856461492311499129200688538220719685637154290305617686974719521885238198226075381217068175824097878445476010193039590876624464274744156624589136789060427283492343902761765833713520850870233407503430180028104167029073459918756981323130062648615262139444306321256382009848217866984408901761817655567071716275177768316006340055589170095799943481591033461616307776069027985761229636731465482676467627154100912586936231051371168178564599296638350391246393336702334311781595616786107810962134407697848002331639021101685320844880636050048769216986088652236979636019052557155807310341483407890060105599892252118584570558049301477535792498672552850760356632076013402382600669875697284264329434950712239302528367835155163504374877787288116104285944993818319105835423479332617802010952731990182088670508346704423006877514817882782443833997288652405892920173712497948376815825396272381214976859009518623799156300136570204539240675245115597412280078940442452936425561984312708387584800789375684525365060589104566195610526570099527133097201479,
+ P = 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024329058480379,
+ G = 2,
+ DHParameters = [P, G],
+ case crypto:compute_key(dh, OthersPublicKey, MyPrivateKey, DHParameters) of
+ ExpectedSecret ->
+ ok;
+ Others ->
+ ct:log("Got ~p",[Others]),
+ {fail, "crypto:compute_key(dh,...) failed for the bug test"}
+ end.
+
+%%--------------------------------------------------------------------
no_generate_compute() ->
[{doc, "Test crypto:genarate_key and crypto:compute_key "
"for disabled algorithms"}].
@@ -470,6 +554,33 @@ compute(Config) when is_list(Config) ->
Gen = proplists:get_value(compute, Config),
lists:foreach(fun do_compute/1, Gen).
%%--------------------------------------------------------------------
+generate_all_supported() ->
+ [{doc, " Test that all curves from crypto:ec_curves/0 returns two binaries"}].
+generate_all_supported(_Config) ->
+ Results =
+ [try
+ crypto:generate_key(ecdh, C)
+ of
+ {B1,B2} when is_binary(B1) and is_binary(B2) ->
+ %% That is, seems like it works as expected.
+ {ok,C};
+ Err ->
+ ct:log("ERROR: Curve ~p generated ~p", [C,Err]),
+ {error,{C,Err}}
+ catch
+ Cls:Err:Stack ->
+ ct:log("ERROR: Curve ~p exception ~p:~p~n~p", [C,Cls,Err,Stack]),
+ {error,{C,{Cls,Err}}}
+ end
+ || C <- crypto:ec_curves()
+ ],
+ OK = [C || {ok,C} <- Results],
+ ct:log("Ok (len=~p): ~p", [length(OK), OK]),
+ false = lists:any(fun({error,_}) -> true;
+ (_) -> false
+ end, Results).
+
+%%--------------------------------------------------------------------
generate() ->
[{doc, " Test crypto:generate_key"}].
generate(Config) when is_list(Config) ->
@@ -535,31 +646,29 @@ hash_increment(State0, [Increment | Rest]) ->
hmac(_, [],[],[]) ->
ok;
hmac(sha = Type, [Key | Keys], [ <<"Test With Truncation">> = Data| Rest], [Expected | Expects]) ->
- case crypto:hmac(Type, Key, Data, 20) of
- Expected ->
- ok;
- Other ->
- ct:fail({{crypto, hmac, [Type, Key, Data]}, {expected, Expected}, {got, Other}})
- end,
+ call_crypto_hmac([Type, Key, Data, 20], Type, Expected),
hmac(Type, Keys, Rest, Expects);
-
hmac(Type, [Key | Keys], [ <<"Test With Truncation">> = Data| Rest], [Expected | Expects]) ->
- case crypto:hmac(Type, Key, Data, 16) of
- Expected ->
- ok;
- Other ->
- ct:fail({{crypto, hmac, [Type, Key, Data]}, {expected, Expected}, {got, Other}})
- end,
+ call_crypto_hmac([Type, Key, Data, 16], Type, Expected),
hmac(Type, Keys, Rest, Expects);
-
hmac(Type, [Key | Keys], [Data| Rest], [Expected | Expects]) ->
- case crypto:hmac(Type, Key, Data) of
+ call_crypto_hmac([Type, Key, Data], Type, Expected),
+ hmac(Type, Keys, Rest, Expects).
+
+call_crypto_hmac(Args, Type, Expected) ->
+ try apply(crypto, hmac, Args)
+ of
Expected ->
ok;
Other ->
- ct:fail({{crypto, hmac, [Type, Key, Data]}, {expected, Expected}, {got, Other}})
- end,
- hmac(Type, Keys, Rest, Expects).
+ ct:fail({{crypto,hmac,Args}, {expected,Expected}, {got,Other}})
+ catch
+ error:notsup ->
+ ct:fail("HMAC ~p not supported", [Type]);
+ Class:Cause ->
+ ct:fail({{crypto,hmac,Args}, {expected,Expected}, {got,{Class,Cause}}})
+ end.
+
hmac_increment(Type) ->
Key = hmac_key(Type),
@@ -690,16 +799,33 @@ stream_cipher({Type, Key, IV, PlainText}) ->
ok;
Other ->
ct:fail({{crypto, stream_decrypt, [State, CipherText]}, {expected, PlainText}, {got, Other}})
+ end;
+stream_cipher({Type, Key, IV, PlainText, CipherText}) ->
+ Plain = iolist_to_binary(PlainText),
+ State = crypto:stream_init(Type, Key, IV),
+ case crypto:stream_encrypt(State, PlainText) of
+ {_, CipherText} ->
+ ok;
+ {_, Other0} ->
+ ct:fail({{crypto, stream_encrypt, [State, Type, Key, IV, Plain]}, {expected, CipherText}, {got, Other0}})
+ end,
+ case crypto:stream_decrypt(State, CipherText) of
+ {_, Plain} ->
+ ok;
+ Other1 ->
+ ct:fail({{crypto, stream_decrypt, [State, CipherText]}, {expected, PlainText}, {got, Other1}})
end.
stream_cipher_incment({Type, Key, PlainTexts}) ->
State = crypto:stream_init(Type, Key),
- stream_cipher_incment(State, State, PlainTexts, [], iolist_to_binary(PlainTexts));
+ stream_cipher_incment_loop(State, State, PlainTexts, [], iolist_to_binary(PlainTexts));
stream_cipher_incment({Type, Key, IV, PlainTexts}) ->
State = crypto:stream_init(Type, Key, IV),
- stream_cipher_incment(State, State, PlainTexts, [], iolist_to_binary(PlainTexts)).
+ stream_cipher_incment_loop(State, State, PlainTexts, [], iolist_to_binary(PlainTexts));
+stream_cipher_incment({Type, Key, IV, PlainTexts, _CipherText}) ->
+ stream_cipher_incment({Type, Key, IV, PlainTexts}).
-stream_cipher_incment(_State, OrigState, [], Acc, Plain) ->
+stream_cipher_incment_loop(_State, OrigState, [], Acc, Plain) ->
CipherText = iolist_to_binary(lists:reverse(Acc)),
case crypto:stream_decrypt(OrigState, CipherText) of
{_, Plain} ->
@@ -707,48 +833,99 @@ stream_cipher_incment(_State, OrigState, [], Acc, Plain) ->
Other ->
ct:fail({{crypto, stream_decrypt, [OrigState, CipherText]}, {expected, Plain}, {got, Other}})
end;
-stream_cipher_incment(State0, OrigState, [PlainText | PlainTexts], Acc, Plain) ->
+stream_cipher_incment_loop(State0, OrigState, [PlainText | PlainTexts], Acc, Plain) ->
{State, CipherText} = crypto:stream_encrypt(State0, PlainText),
- stream_cipher_incment(State, OrigState, PlainTexts, [CipherText | Acc], Plain).
+ stream_cipher_incment_loop(State, OrigState, PlainTexts, [CipherText | Acc], Plain).
-aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag}) ->
+aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag, Info}) ->
Plain = iolist_to_binary(PlainText),
case crypto:block_encrypt(Type, Key, IV, {AAD, Plain}) of
{CipherText, CipherTag} ->
ok;
Other0 ->
- ct:fail({{crypto, block_encrypt, [Plain, PlainText]}, {expected, {CipherText, CipherTag}}, {got, Other0}})
+ ct:fail({{crypto,
+ block_encrypt,
+ [{info,Info}, {key,Key}, {pt,PlainText}, {iv,IV}, {aad,AAD}, {ct,CipherText}, {tag,CipherTag}]},
+ {expected, {CipherText, CipherTag}},
+ {got, Other0}})
end,
case crypto:block_decrypt(Type, Key, IV, {AAD, CipherText, CipherTag}) of
Plain ->
ok;
Other1 ->
- ct:fail({{crypto, block_decrypt, [CipherText]}, {expected, Plain}, {got, Other1}})
+ ct:fail({{crypto,
+ block_decrypt,
+ [{info,Info}, {key,Key}, {pt,PlainText}, {iv,IV}, {aad,AAD}, {ct,CipherText}, {tag,CipherTag}]},
+ {expected, Plain},
+ {got, Other1}})
end;
-aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag, TagLen}) ->
+aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag, TagLen, Info}) ->
<<TruncatedCipherTag:TagLen/binary, _/binary>> = CipherTag,
Plain = iolist_to_binary(PlainText),
case crypto:block_encrypt(Type, Key, IV, {AAD, Plain, TagLen}) of
{CipherText, TruncatedCipherTag} ->
ok;
Other0 ->
- ct:fail({{crypto, block_encrypt, [Plain, PlainText]}, {expected, {CipherText, TruncatedCipherTag}}, {got, Other0}})
+ ct:fail({{crypto,
+ block_encrypt,
+ [{info,Info}, {key,Key}, {pt,PlainText}, {iv,IV}, {aad,AAD}, {ct,CipherText}, {tag,CipherTag}, {taglen,TagLen}]},
+ {expected, {CipherText, TruncatedCipherTag}},
+ {got, Other0}})
end,
case crypto:block_decrypt(Type, Key, IV, {AAD, CipherText, TruncatedCipherTag}) of
Plain ->
ok;
Other1 ->
- ct:fail({{crypto, block_decrypt, [CipherText]}, {expected, Plain}, {got, Other1}})
+ ct:fail({{crypto,
+ block_decrypt,
+ [{info,Info}, {key,Key}, {pt,PlainText}, {iv,IV}, {aad,AAD}, {ct,CipherText}, {tag,CipherTag},
+ {truncated,TruncatedCipherTag}]},
+ {expected, Plain},
+ {got, Other1}})
end.
do_sign_verify({Type, Hash, Public, Private, Msg}) ->
Signature = crypto:sign(Type, Hash, Msg, Private),
case crypto:verify(Type, Hash, Msg, Signature, Public) of
true ->
+ ct:log("OK crypto:sign(~p, ~p, ..., ..., ...)", [Type,Hash]),
negative_verify(Type, Hash, Msg, <<10,20>>, Public);
false ->
+ ct:log("ERROR crypto:sign(~p, ~p, ..., ..., ...)", [Type,Hash]),
ct:fail({{crypto, verify, [Type, Hash, Msg, Signature, Public]}})
- end.
+ end;
+do_sign_verify({Type, Hash, Public, Private, Msg, Options}) ->
+ LibVer =
+ case crypto:info_lib() of
+ [{<<"OpenSSL">>,Ver,<<"OpenSSL",_/binary>>}] -> Ver;
+ _ -> infinity
+ end,
+ Pad = proplists:get_value(rsa_padding, Options),
+ NotSupLow = lists:member(Pad, [rsa_pkcs1_pss_padding]),
+ try
+ crypto:sign(Type, Hash, Msg, Private, Options)
+ of
+ Signature ->
+ case crypto:verify(Type, Hash, Msg, Signature, Public, Options) of
+ true ->
+ ct:log("OK crypto:sign(~p, ~p, ..., ..., ..., ~p)", [Type,Hash,Options]),
+ negative_verify(Type, Hash, Msg, <<10,20>>, Public, Options);
+ false ->
+ ct:log("ERROR crypto:sign(~p, ~p, ..., ..., ..., ~p)", [Type,Hash,Options]),
+ ct:fail({{crypto, verify, [Type, Hash, Msg, Signature, Public, Options]}})
+ end
+ catch
+ error:notsup when NotSupLow == true,
+ is_integer(LibVer),
+ LibVer < 16#10001000 ->
+ %% Thoose opts where introduced in 1.0.1
+ ct:log("notsup but OK in old cryptolib crypto:sign(~p, ~p, ..., ..., ..., ~p)",
+ [Type,Hash,Options]),
+ true;
+ C:E ->
+ ct:log("~p:~p crypto:sign(~p, ~p, ..., ..., ..., ~p)", [C,E,Type,Hash,Options]),
+ ct:fail({{crypto, sign_verify, [LibVer, Type, Hash, Msg, Public, Options]}})
+ end.
negative_verify(Type, Hash, Msg, Signature, Public) ->
case crypto:verify(Type, Hash, Msg, Signature, Public) of
@@ -758,26 +935,77 @@ negative_verify(Type, Hash, Msg, Signature, Public) ->
ok
end.
+negative_verify(Type, Hash, Msg, Signature, Public, Options) ->
+ case crypto:verify(Type, Hash, Msg, Signature, Public, Options) of
+ true ->
+ ct:fail({{crypto, verify, [Type, Hash, Msg, Signature, Public, Options]}, should_fail});
+ false ->
+ ok
+ end.
+
+-define(PUB_PRIV_ENC_DEC_CATCH(Type,Padding),
+ CC:EE ->
+ ct:log("~p:~p in ~p:~p/~p, line ~p.~n"
+ "Type = ~p~nPadding = ~p",
+ [CC,EE,?MODULE,?FUNCTION_NAME,?FUNCTION_ARITY,?LINE,(Type),(Padding)]),
+ MaybeUnsupported =
+ case crypto:info_lib() of
+ [{<<"OpenSSL">>,_,_}] ->
+ is_list(Padding) andalso
+ lists:any(fun(P) -> lists:member(P,(Padding)) end,
+ [{rsa_padding, rsa_pkcs1_oaep_padding},
+ {rsa_padding, rsa_sslv23_padding},
+ {rsa_padding, rsa_x931_padding}]);
+ _ ->
+ false
+ end,
+ case CC of
+ error when MaybeUnsupported ->
+ ct:comment("Padding unsupported?",[]);
+ _ ->
+ ct:fail({?FUNCTION_NAME,CC,EE,(Type),(Padding)})
+ end
+ ).
+
do_public_encrypt({Type, Public, Private, Msg, Padding}) ->
- PublicEcn = (catch crypto:public_encrypt(Type, Msg, Public, Padding)),
- case crypto:private_decrypt(Type, PublicEcn, Private, Padding) of
- Msg ->
- ok;
- Other ->
- ct:fail({{crypto, private_decrypt, [Type, PublicEcn, Private, Padding]}, {expected, Msg}, {got, Other}})
+ try
+ crypto:public_encrypt(Type, Msg, Public, Padding)
+ of
+ PublicEcn ->
+ try
+ crypto:private_decrypt(Type, PublicEcn, Private, Padding)
+ of
+ Msg ->
+ ok;
+ Other ->
+ ct:fail({{crypto, private_decrypt, [Type, PublicEcn, Private, Padding]}, {expected, Msg}, {got, Other}})
+ catch
+ ?PUB_PRIV_ENC_DEC_CATCH(Type, Padding)
+ end
+ catch
+ ?PUB_PRIV_ENC_DEC_CATCH(Type, Padding)
end.
-do_private_encrypt({_Type, _Public, _Private, _Msg, rsa_pkcs1_oaep_padding}) ->
- ok; %% Not supported by openssl
+
do_private_encrypt({Type, Public, Private, Msg, Padding}) ->
- PrivEcn = (catch crypto:private_encrypt(Type, Msg, Private, Padding)),
- case crypto:public_decrypt(rsa, PrivEcn, Public, Padding) of
- Msg ->
- ok;
- Other ->
- ct:fail({{crypto, public_decrypt, [Type, PrivEcn, Public, Padding]}, {expected, Msg}, {got, Other}})
+ try
+ crypto:private_encrypt(Type, Msg, Private, Padding)
+ of
+ PrivEcn ->
+ try
+ crypto:public_decrypt(Type, PrivEcn, Public, Padding)
+ of
+ Msg ->
+ ok;
+ Other ->
+ ct:fail({{crypto, public_decrypt, [Type, PrivEcn, Public, Padding]}, {expected, Msg}, {got, Other}})
+ catch
+ ?PUB_PRIV_ENC_DEC_CATCH(Type, Padding)
+ end
+ catch
+ ?PUB_PRIV_ENC_DEC_CATCH(Type, Padding)
end.
-
+
do_generate_compute({srp = Type, UserPrivate, UserGenParams, UserComParams,
HostPublic, HostPrivate, HostGenParams, HostComParam, SessionKey}) ->
{UserPublic, UserPrivate} = crypto:generate_key(Type, UserGenParams, UserPrivate),
@@ -846,6 +1074,8 @@ hexstr2bin(S) when is_binary(S) ->
hexstr2bin(S) ->
list_to_binary(hexstr2list(S)).
+hexstr2list([$ |T]) ->
+ hexstr2list(T);
hexstr2list([X,Y|T]) ->
[mkint(X)*16 + mkint(Y) | hexstr2list(T)];
hexstr2list([]) ->
@@ -857,6 +1087,14 @@ mkint(C) when $A =< C, C =< $F ->
mkint(C) when $a =< C, C =< $f ->
C - $a + 10.
+bin2hexstr(B) when is_binary(B) ->
+ io_lib:format("~.16b",[crypto:bytes_to_integer(B)]).
+
+decstr2int(S) when is_binary(S) ->
+ list_to_integer(binary:bin_to_list(S));
+decstr2int(S) ->
+ list_to_integer(S).
+
is_supported(Group) ->
lists:member(Group, lists:append([Algo || {_, Algo} <- crypto:supports()])).
@@ -875,7 +1113,9 @@ do_cmac_iolistify({Type, Key, Text, Size, CMac}) ->
do_stream_iolistify({Type, Key, PlainText}) ->
{Type, iolistify(Key), iolistify(PlainText)};
do_stream_iolistify({Type, Key, IV, PlainText}) ->
- {Type, iolistify(Key), IV, iolistify(PlainText)}.
+ {Type, iolistify(Key), IV, iolistify(PlainText)};
+do_stream_iolistify({Type, Key, IV, PlainText, CipherText}) ->
+ {Type, iolistify(Key), IV, iolistify(PlainText), CipherText}.
do_block_iolistify({des_cbc = Type, Key, IV, PlainText}) ->
{Type, Key, IV, des_iolistify(PlainText)};
@@ -1121,7 +1361,7 @@ group_config(sha224 = Type, Config) ->
Keys = rfc_4231_keys(),
Data = rfc_4231_msgs(),
Hmac = rfc4231_hmac_sha224(),
- [{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
+ [{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
group_config(sha256 = Type, Config) ->
Msgs = [rfc_4634_test1(), rfc_4634_test2_1(), long_msg()],
Digests = rfc_4634_sha256_digests() ++ [long_sha256_digest()],
@@ -1143,6 +1383,18 @@ group_config(sha512 = Type, Config) ->
Data = rfc_4231_msgs() ++ [long_msg()],
Hmac = rfc4231_hmac_sha512() ++ [long_hmac(sha512)],
[{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
+group_config(sha3_224 = Type, Config) ->
+ {Msgs,Digests} = sha3_test_vectors(Type),
+ [{hash, {Type, Msgs, Digests}}, {hmac, hmac_sha3(Type)} | Config];
+group_config(sha3_256 = Type, Config) ->
+ {Msgs,Digests} = sha3_test_vectors(Type),
+ [{hash, {Type, Msgs, Digests}}, {hmac, hmac_sha3(Type)} | Config];
+group_config(sha3_384 = Type, Config) ->
+ {Msgs,Digests} = sha3_test_vectors(Type),
+ [{hash, {Type, Msgs, Digests}}, {hmac, hmac_sha3(Type)} | Config];
+group_config(sha3_512 = Type, Config) ->
+ {Msgs,Digests} = sha3_test_vectors(Type),
+ [{hash, {Type, Msgs, Digests}}, {hmac, hmac_sha3(Type)} | Config];
group_config(rsa = Type, Config) ->
Msg = rsa_plain(),
Public = rsa_public(),
@@ -1163,7 +1415,12 @@ group_config(rsa = Type, Config) ->
end,
MsgPubEnc = <<"7896345786348 Asldi">>,
PubPrivEnc = [{rsa, PublicS, PrivateS, MsgPubEnc, rsa_pkcs1_padding},
+ {rsa, PublicS, PrivateS, MsgPubEnc, [{rsa_padding, rsa_pkcs1_padding}]},
+ {rsa, PublicS, PrivateS, MsgPubEnc, [{rsa_padding, rsa_sslv23_padding}]},
+ {rsa, PublicS, PrivateS, MsgPubEnc, [{rsa_padding, rsa_x931_padding}]},
rsa_oaep(),
+ %% rsa_oaep_label(),
+ %% rsa_oaep256(),
no_padding()
],
Generate = [{rsa, 1024, 3}, {rsa, 2048, 17}, {rsa, 3072, 65537}],
@@ -1172,14 +1429,34 @@ group_config(dss = Type, Config) ->
Msg = dss_plain(),
Public = dss_params() ++ [dss_public()],
Private = dss_params() ++ [dss_private()],
- SignVerify = [{Type, sha, Public, Private, Msg}],
- [{sign_verify, SignVerify} | Config];
+ SupportedHashs = proplists:get_value(hashs, crypto:supports(), []),
+ DssHashs =
+ case crypto:info_lib() of
+ [{<<"OpenSSL">>,LibVer,_}] when is_integer(LibVer), LibVer > 16#10001000 ->
+ [sha, sha224, sha256, sha384, sha512];
+ [{<<"OpenSSL">>,LibVer,_}] when is_integer(LibVer), LibVer > 16#10000000 ->
+ [sha, sha224, sha256];
+ _Else ->
+ [sha]
+ end,
+ SignVerify = [{Type, Hash, Public, Private, Msg}
+ || Hash <- DssHashs,
+ lists:member(Hash, SupportedHashs)],
+ MsgPubEnc = <<"7896345786348 Asldi">>,
+ PubPrivEnc = [{dss, Public, Private, MsgPubEnc, []}],
+ [{sign_verify, SignVerify}, {pub_priv_encrypt, PubPrivEnc} | Config];
group_config(ecdsa = Type, Config) ->
{Private, Public} = ec_key_named(),
Msg = ec_msg(),
- SignVerify = [{Type, sha, Public, Private, Msg}],
- [{sign_verify, SignVerify} | Config];
+ SupportedHashs = proplists:get_value(hashs, crypto:supports(), []),
+ DssHashs = [sha, sha224, sha256, sha384, sha512],
+ SignVerify = [{Type, Hash, Public, Private, Msg}
+ || Hash <- DssHashs,
+ lists:member(Hash, SupportedHashs)],
+ MsgPubEnc = <<"7896345786348 Asldi">>,
+ PubPrivEnc = [{ecdsa, Public, Private, MsgPubEnc, []}],
+ [{sign_verify, SignVerify}, {pub_priv_encrypt, PubPrivEnc} | Config];
group_config(srp, Config) ->
GenerateCompute = [srp3(), srp6(), srp6a(), srp6a_smaller_prime()],
[{generate_compute, GenerateCompute} | Config];
@@ -1249,12 +1526,27 @@ group_config(rc4, Config) ->
group_config(aes_ctr, Config) ->
Stream = aes_ctr(),
[{stream, Stream} | Config];
+group_config(aes_ccm, Config) ->
+ AEAD = fun() -> aes_ccm(Config) end,
+ [{aead, AEAD} | Config];
group_config(aes_gcm, Config) ->
AEAD = fun() -> aes_gcm(Config) end,
[{aead, AEAD} | Config];
group_config(chacha20_poly1305, Config) ->
AEAD = chacha20_poly1305(),
[{aead, AEAD} | Config];
+group_config(chacha20, Config) ->
+ Stream = chacha20(),
+ [{stream, Stream} | Config];
+group_config(poly1305, Config) ->
+ V = [%% {Key, Txt, Expect}
+ {%% RFC7539 2.5.2
+ crypto_SUITE:hexstr2bin("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b"),
+ <<"Cryptographic Forum Research Group">>,
+ crypto_SUITE:hexstr2bin("a8061dc1305136c6c22b8baf0c0127a9")
+ }
+ ],
+ [{poly1305,V} | Config];
group_config(aes_cbc, Config) ->
Block = aes_cbc(Config),
[{block, Block} | Config];
@@ -1262,18 +1554,38 @@ group_config(_, Config) ->
Config.
sign_verify_tests(Type, Msg, Public, Private, PublicS, PrivateS) ->
- sign_verify_tests(Type, [md5, sha, sha224, sha256], Msg, Public, Private) ++
- sign_verify_tests(Type, [sha384, sha512], Msg, PublicS, PrivateS).
-
-sign_verify_tests(Type, Hashs, Msg, Public, Private) ->
- lists:foldl(fun(Hash, Acc) ->
- case is_supported(Hash) of
- true ->
- [{Type, Hash, Public, Private, Msg}|Acc];
- false ->
- Acc
- end
- end, [], Hashs).
+ gen_sign_verify_tests(Type, [md5, ripemd160, sha, sha224, sha256], Msg, Public, Private,
+ [undefined,
+ [{rsa_padding, rsa_pkcs1_pss_padding}],
+ [{rsa_padding, rsa_pkcs1_pss_padding}, {rsa_pss_saltlen, 0}],
+ [{rsa_padding, rsa_x931_padding}]
+ ]) ++
+ gen_sign_verify_tests(Type, [sha384, sha512], Msg, PublicS, PrivateS,
+ [undefined,
+ [{rsa_padding, rsa_pkcs1_pss_padding}],
+ [{rsa_padding, rsa_pkcs1_pss_padding}, {rsa_pss_saltlen, 0}],
+ [{rsa_padding, rsa_x931_padding}]
+ ]).
+
+gen_sign_verify_tests(Type, Hashs, Msg, Public, Private, Opts) ->
+ lists:foldr(fun(Hash, Acc0) ->
+ case is_supported(Hash) of
+ true ->
+ lists:foldr(fun
+ (undefined, Acc1) ->
+ [{Type, Hash, Public, Private, Msg} | Acc1];
+ ([{rsa_padding, rsa_x931_padding} | _], Acc1)
+ when Hash =:= md5
+ orelse Hash =:= ripemd160
+ orelse Hash =:= sha224 ->
+ Acc1;
+ (Opt, Acc1) ->
+ [{Type, Hash, Public, Private, Msg, Opt} | Acc1]
+ end, Acc0, Opts);
+ false ->
+ Acc0
+ end
+ end, [], Hashs).
rfc_1321_msgs() ->
[<<"">>,
@@ -1303,6 +1615,160 @@ rfc_1321_md5_digests() ->
hexstr2bin("d174ab98d277d9f5a5611c2c9f419d9f"),
hexstr2bin("57edf4a22be3c955ac49da2e2107b67a")].
+%%% https://www.di-mgt.com.au/sha_testvectors.html
+sha3_msgs() ->
+ ["abc",
+ "",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", % length 448 bits
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", % length 896 bits
+ lists:duplicate(1000000,$a)
+ ].
+
+sha3_test_vectors(sha3_224) ->
+ {sha3_msgs(),
+ [hexstr2bin("e642824c3f8cf24a d09234ee7d3c766f c9a3a5168d0c94ad 73b46fdf"),
+ hexstr2bin("6b4e03423667dbb7 3b6e15454f0eb1ab d4597f9a1b078e3f 5b5a6bc7"),
+ hexstr2bin("8a24108b154ada21 c9fd5574494479ba 5c7e7ab76ef264ea d0fcce33"),
+ hexstr2bin("543e6868e1666c1a 643630df77367ae5 a62a85070a51c14c bf665cbc"),
+ hexstr2bin("d69335b93325192e 516a912e6d19a15c b51c6ed5c15243e7 a7fd653c")
+ ]
+ };
+sha3_test_vectors(sha3_256) ->
+ {sha3_msgs(),
+ [hexstr2bin("3a985da74fe225b2 045c172d6bd390bd 855f086e3e9d525b 46bfe24511431532"),
+ hexstr2bin("a7ffc6f8bf1ed766 51c14756a061d662 f580ff4de43b49fa 82d80a4b80f8434a"),
+ hexstr2bin("41c0dba2a9d62408 49100376a8235e2c 82e1b9998a999e21 db32dd97496d3376"),
+ hexstr2bin("916f6061fe879741 ca6469b43971dfdb 28b1a32dc36cb325 4e812be27aad1d18"),
+ hexstr2bin("5c8875ae474a3634 ba4fd55ec85bffd6 61f32aca75c6d699 d0cdcb6c115891c1")
+ ]
+ };
+sha3_test_vectors(sha3_384) ->
+ {sha3_msgs(),
+ [hexstr2bin("ec01498288516fc9 26459f58e2c6ad8d f9b473cb0fc08c25 96da7cf0e49be4b2 98d88cea927ac7f5 39f1edf228376d25"),
+ hexstr2bin("0c63a75b845e4f7d 01107d852e4c2485 c51a50aaaa94fc61 995e71bbee983a2a c3713831264adb47 fb6bd1e058d5f004"),
+ hexstr2bin("991c665755eb3a4b 6bbdfb75c78a492e 8c56a22c5c4d7e42 9bfdbc32b9d4ad5a a04a1f076e62fea1 9eef51acd0657c22"),
+ hexstr2bin("79407d3b5916b59c 3e30b09822974791 c313fb9ecc849e40 6f23592d04f625dc 8c709b98b43b3852 b337216179aa7fc7"),
+ hexstr2bin("eee9e24d78c18553 37983451df97c8ad 9eedf256c6334f8e 948d252d5e0e7684 7aa0774ddb90a842 190d2c558b4b8340")
+ ]
+ };
+sha3_test_vectors(sha3_512) ->
+ {sha3_msgs(),
+ [hexstr2bin("b751850b1a57168a 5693cd924b6b096e 08f621827444f70d 884f5d0240d2712e 10e116e9192af3c9 1a7ec57647e39340 57340b4cf408d5a5 6592f8274eec53f0"),
+ hexstr2bin("a69f73cca23a9ac5 c8b567dc185a756e 97c982164fe25859 e0d1dcc1475c80a6 15b2123af1f5f94c 11e3e9402c3ac558 f500199d95b6d3e3 01758586281dcd26"),
+ hexstr2bin("04a371e84ecfb5b8 b77cb48610fca818 2dd457ce6f326a0f d3d7ec2f1e91636d ee691fbe0c985302 ba1b0d8dc78c0863 46b533b49c030d99 a27daf1139d6e75e"),
+ hexstr2bin("afebb2ef542e6579 c50cad06d2e578f9 f8dd6881d7dc824d 26360feebf18a4fa 73e3261122948efc fd492e74e82e2189 ed0fb440d187f382 270cb455f21dd185"),
+ hexstr2bin("3c3a876da14034ab 60627c077bb98f7e 120a2a5370212dff b3385a18d4f38859 ed311d0a9d5141ce 9cc5c66ee689b266 a8aa18ace8282a0e 0db596c90b0a7b87")
+ ]
+ }.
+
+
+
+%%% http://www.wolfgang-ehrhardt.de/hmac-sha3-testvectors.html
+
+hmac_sha3(Type) ->
+ N = case Type of
+ sha3_224 -> 1;
+ sha3_256 -> 2;
+ sha3_384 -> 3;
+ sha3_512 -> 4
+ end,
+ {Keys, Datas, Hmacs} =
+ lists:unzip3(
+ [{hexstr2bin(Key), hexstr2bin(Data), hexstr2bin(element(N,Hmacs))}
+ || {Key,Data,Hmacs} <- hmac_sha3_data()]),
+ {Type, Keys, Datas, Hmacs}.
+
+
+hmac_sha3_data() ->
+ [
+ {"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b 0b0b0b0b",
+ "4869205468657265",
+ {"3b16546bbc7be2706a031dcafd56373d 9884367641d8c59af3c860f7",
+ "ba85192310dffa96e2a3a40e69774351 140bb7185e1202cdcc917589f95e16bb",
+ "68d2dcf7fd4ddd0a2240c8a437305f61 fb7334cfb5d0226e1bc27dc10a2e723a 20d370b47743130e26ac7e3d532886bd",
+ "eb3fbd4b2eaab8f5c504bd3a41465aac ec15770a7cabac531e482f860b5ec7ba 47ccb2c6f2afce8f88d22b6dc61380f2 3a668fd3888bb80537c0a0b86407689e"
+ }},
+
+ {"4a656665",
+ "7768617420646f2079612077616e7420 666f72206e6f7468696e673f",
+ {"7fdb8dd88bd2f60d1b798634ad386811 c2cfc85bfaf5d52bbace5e66",
+ "c7d4072e788877ae3596bbb0da73b887 c9171f93095b294ae857fbe2645e1ba5",
+ "f1101f8cbf9766fd6764d2ed61903f21 ca9b18f57cf3e1a23ca13508a93243ce 48c045dc007f26a21b3f5e0e9df4c20a",
+ "5a4bfeab6166427c7a3647b747292b83 84537cdb89afb3bf5665e4c5e709350b 287baec921fd7ca0ee7a0c31d022a95e 1fc92ba9d77df883960275beb4e62024"
+ }},
+
+ {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaa",
+ "dddddddddddddddddddddddddddddddd dddddddddddddddddddddddddddddddd dddddddddddddddddddddddddddddddd dddd",
+ {"676cfc7d16153638780390692be142d2 df7ce924b909c0c08dbfdc1a",
+ "84ec79124a27107865cedd8bd82da996 5e5ed8c37b0ac98005a7f39ed58a4207",
+ "275cd0e661bb8b151c64d288f1f782fb 91a8abd56858d72babb2d476f0458373 b41b6ab5bf174bec422e53fc3135ac6e",
+ "309e99f9ec075ec6c6d475eda1180687 fcf1531195802a99b5677449a8625182 851cb332afb6a89c411325fbcbcd42af cb7b6e5aab7ea42c660f97fd8584bf03"
+ }},
+
+ {"0102030405060708090a0b0c0d0e0f10 111213141516171819",
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd cdcd",
+ {"a9d7685a19c4e0dbd9df2556cc8a7d2a 7733b67625ce594c78270eeb",
+ "57366a45e2305321a4bc5aa5fe2ef8a9 21f6af8273d7fe7be6cfedb3f0aea6d7",
+ "3a5d7a879702c086bc96d1dd8aa15d9c 46446b95521311c606fdc4e308f4b984 da2d0f9449b3ba8425ec7fb8c31bc136",
+ "b27eab1d6e8d87461c29f7f5739dd58e 98aa35f8e823ad38c5492a2088fa0281 993bbfff9a0e9c6bf121ae9ec9bb09d8 4a5ebac817182ea974673fb133ca0d1d"
+ }},
+
+ %% {"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c 0c0c0c0c",
+ %% "546573742057697468205472756e6361 74696f6e",
+ %% {"49fdd3abd005ebb8ae63fea946d1883c",
+ %% "6e02c64537fb118057abb7fb66a23b3c",
+ %% "47c51ace1ffacffd7494724682615783",
+ %% "0fa7475948f43f48ca0516671e18978c"
+ %% }},
+
+ {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaa",
+ "54657374205573696e67204c61726765 72205468616e20426c6f636b2d53697a 65204b6579202d2048617368204b6579 204669727374",
+ {"b4a1f04c00287a9b7f6075b313d279b8 33bc8f75124352d05fb9995f",
+ "ed73a374b96c005235f948032f09674a 58c0ce555cfc1f223b02356560312c3b",
+ "0fc19513bf6bd878037016706a0e57bc 528139836b9a42c3d419e498e0e1fb96 16fd669138d33a1105e07c72b6953bcc",
+ "00f751a9e50695b090ed6911a4b65524 951cdc15a73a5d58bb55215ea2cd839a c79d2b44a39bafab27e83fde9e11f634 0b11d991b1b91bf2eee7fc872426c3a4"
+ }},
+
+ {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaa",
+ "54657374205573696e67204c61726765 72205468616e20426c6f636b2d53697a 65204b6579202d2048617368204b6579 204669727374",
+ {
+ "b96d730c148c2daad8649d83defaa371 9738d34775397b7571c38515",
+ "a6072f86de52b38bb349fe84cd6d97fb 6a37c4c0f62aae93981193a7229d3467",
+ "713dff0302c85086ec5ad0768dd65a13 ddd79068d8d4c6212b712e4164944911 1480230044185a99103ed82004ddbfcc",
+ "b14835c819a290efb010ace6d8568dc6 b84de60bc49b004c3b13eda763589451 e5dd74292884d1bdce64e6b919dd61dc 9c56a282a81c0bd14f1f365b49b83a5b"
+ }},
+
+ {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaa",
+ "54686973206973206120746573742075 73696e672061206c6172676572207468 616e20626c6f636b2d73697a65206b65 7920616e642061206c61726765722074 68616e20626c6f636b2d73697a652064 6174612e20546865206b6579206e6565 647320746f2062652068617368656420 6265666f7265206265696e6720757365 642062792074686520484d414320616c 676f726974686d2e",
+ {
+ "05d8cd6d00faea8d1eb68ade28730bbd 3cbab6929f0a086b29cd62a0",
+ "65c5b06d4c3de32a7aef8763261e49ad b6e2293ec8e7c61e8de61701fc63e123",
+ "026fdf6b50741e373899c9f7d5406d4e b09fc6665636fc1a530029ddf5cf3ca5 a900edce01f5f61e2f408cdf2fd3e7e8",
+ "38a456a004bd10d32c9ab83366841128 62c3db61adcca31829355eaf46fd5c73 d06a1f0d13fec9a652fb3811b577b1b1 d1b9789f97ae5b83c6f44dfcf1d67eba"
+ }},
+
+ {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaa",
+ "54686973206973206120746573742075 73696e672061206c6172676572207468 616e20626c6f636b2d73697a65206b65 7920616e642061206c61726765722074 68616e20626c6f636b2d73697a652064 6174612e20546865206b6579206e6565 647320746f2062652068617368656420 6265666f7265206265696e6720757365 642062792074686520484d414320616c 676f726974686d2e",
+ {
+ "c79c9b093424e588a9878bbcb089e018 270096e9b4b1a9e8220c866a",
+ "e6a36d9b915f86a093cac7d110e9e04c f1d6100d30475509c2475f571b758b5a",
+ "cad18a8ff6c4cc3ad487b95f9769e9b6 1c062aefd6952569e6e6421897054cfc 70b5fdc6605c18457112fc6aaad45585",
+ "dc030ee7887034f32cf402df34622f31 1f3e6cf04860c6bbd7fa488674782b46 59fdbdf3fd877852885cfe6e22185fe7 b2ee952043629bc9d5f3298a41d02c66"
+ }}
+ %%,
+
+ %% {"4a656665",
+ %% "'11001' or LSB 13 or MSB c8",
+ %% {
+ %% "5f8c0ea7fafecd0c3463aad09742cece b142fe0ab6f4539438c59de8",
+ %% "ec8222773fac68b3d3dcb182aec8b050 7ace4448d20a1147e682118da4e3f44c",
+ %% "21fbd3bf3ebba3cfc9ef64c0591c92c5 acb265e92d8761d1f91a52a103a6c796 94cfd67a9a2ac1324f02fea63b81effc",
+ %% "27f9388c1567ef4ef200602a6cf871d6 8a6fb048d4737ac4418a2f021289d13d 1fd1120fecb9cf964c5b117ab5b11c61 4b2da39dadd51f2f5e22aaccec7d576e"
+ %% }}
+ ].
+
+
+
rfc_4634_test1() ->
<<"abc">>.
rfc_4634_test2_1() ->
@@ -1872,6 +2338,13 @@ aes_gcm(Config) ->
"gcmEncryptExtIV192.rsp",
"gcmEncryptExtIV256.rsp"]).
+aes_ccm(Config) ->
+ read_rsp(Config, aes_ccm,
+ ["VADT128.rsp", "VADT192.rsp", "VADT256.rsp",
+ "VNT128.rsp", "VNT192.rsp", "VNT256.rsp",
+ "VPT128.rsp", "VPT192.rsp", "VPT256.rsp"
+ ]).
+
%% https://tools.ietf.org/html/rfc7539#appendix-A.5
chacha20_poly1305() ->
[
@@ -1914,9 +2387,108 @@ chacha20_poly1305() ->
"49e617d91d361094fa68f0ff77987130"
"305beaba2eda04df997b714d6c6f2c29"
"a6ad5cb4022b02709b"),
- hexstr2bin("eead9d67890cbb22392336fea1851f38")} %% CipherTag
+ hexstr2bin("eead9d67890cbb22392336fea1851f38"), %% CipherTag
+ no_info
+ }
].
+
+chacha20() ->
+%%% chacha20 (no mode) test vectors from RFC 7539 A.2
+ [
+ %% Test Vector #1:
+ {chacha20,
+ hexstr2bin("00000000000000000000000000000000"
+ "00000000000000000000000000000000"), %% Key
+ hexstr2bin("00000000" % Initial counter = 0, little-endian
+ "000000000000000000000000"), %% IV
+ hexstr2bin("00000000000000000000000000000000" %% PlainText
+ "00000000000000000000000000000000"
+ "00000000000000000000000000000000"
+ "00000000000000000000000000000000"),
+ hexstr2bin("76b8e0ada0f13d90405d6ae55386bd28" %% CipherText
+ "bdd219b8a08ded1aa836efcc8b770dc7"
+ "da41597c5157488d7724e03fb8d84a37"
+ "6a43b8f41518a11cc387b669b2ee6586")},
+ %% Test Vector #2:
+ {chacha20,
+ hexstr2bin("00000000000000000000000000000000"
+ "00000000000000000000000000000001"), %% Key
+ hexstr2bin("01000000" % Initial counter = 1, little-endian
+ "000000000000000000000002"), %% IV
+ hexstr2bin("416e79207375626d697373696f6e2074" %% PlainText
+ "6f20746865204945544620696e74656e"
+ "6465642062792074686520436f6e7472"
+ "696275746f7220666f72207075626c69"
+ "636174696f6e20617320616c6c206f72"
+ "2070617274206f6620616e2049455446"
+ "20496e7465726e65742d447261667420"
+ "6f722052464320616e6420616e792073"
+ "746174656d656e74206d616465207769"
+ "7468696e2074686520636f6e74657874"
+ "206f6620616e20494554462061637469"
+ "7669747920697320636f6e7369646572"
+ "656420616e20224945544620436f6e74"
+ "7269627574696f6e222e205375636820"
+ "73746174656d656e747320696e636c75"
+ "6465206f72616c2073746174656d656e"
+ "747320696e2049455446207365737369"
+ "6f6e732c2061732077656c6c20617320"
+ "7772697474656e20616e6420656c6563"
+ "74726f6e696320636f6d6d756e696361"
+ "74696f6e73206d61646520617420616e"
+ "792074696d65206f7220706c6163652c"
+ "20776869636820617265206164647265"
+ "7373656420746f"),
+ hexstr2bin("a3fbf07df3fa2fde4f376ca23e827370" %% CipherText
+ "41605d9f4f4f57bd8cff2c1d4b7955ec"
+ "2a97948bd3722915c8f3d337f7d37005"
+ "0e9e96d647b7c39f56e031ca5eb6250d"
+ "4042e02785ececfa4b4bb5e8ead0440e"
+ "20b6e8db09d881a7c6132f420e527950"
+ "42bdfa7773d8a9051447b3291ce1411c"
+ "680465552aa6c405b7764d5e87bea85a"
+ "d00f8449ed8f72d0d662ab052691ca66"
+ "424bc86d2df80ea41f43abf937d3259d"
+ "c4b2d0dfb48a6c9139ddd7f76966e928"
+ "e635553ba76c5c879d7b35d49eb2e62b"
+ "0871cdac638939e25e8a1e0ef9d5280f"
+ "a8ca328b351c3c765989cbcf3daa8b6c"
+ "cc3aaf9f3979c92b3720fc88dc95ed84"
+ "a1be059c6499b9fda236e7e818b04b0b"
+ "c39c1e876b193bfe5569753f88128cc0"
+ "8aaa9b63d1a16f80ef2554d7189c411f"
+ "5869ca52c5b83fa36ff216b9c1d30062"
+ "bebcfd2dc5bce0911934fda79a86f6e6"
+ "98ced759c3ff9b6477338f3da4f9cd85"
+ "14ea9982ccafb341b2384dd902f3d1ab"
+ "7ac61dd29c6f21ba5b862f3730e37cfd"
+ "c4fd806c22f221")},
+ %%Test Vector #3:
+ {chacha20,
+ hexstr2bin("1c9240a5eb55d38af333888604f6b5f0"
+ "473917c1402b80099dca5cbc207075c0"), %% Key
+ hexstr2bin("2a000000" % Initial counter = 42 (decimal), little-endian
+ "000000000000000000000002"), %% IV
+ hexstr2bin("2754776173206272696c6c69672c2061" %% PlainText
+ "6e642074686520736c6974687920746f"
+ "7665730a446964206779726520616e64"
+ "2067696d626c6520696e207468652077"
+ "6162653a0a416c6c206d696d73792077"
+ "6572652074686520626f726f676f7665"
+ "732c0a416e6420746865206d6f6d6520"
+ "7261746873206f757467726162652e"),
+ hexstr2bin("62e6347f95ed87a45ffae7426f27a1df" %% CipherText
+ "5fb69110044c0d73118effa95b01e5cf"
+ "166d3df2d721caf9b21e5fb14c616871"
+ "fd84c54f9d65b283196c7fe4f60553eb"
+ "f39c6402c42234e32a356b3e764312a6"
+ "1a5532055716ead6962568f87d3f3f77"
+ "04c6a8d1bcd1bf4d50d6154b6da731b1"
+ "87b58dfd728afa36757a797ac188d1")}
+ ].
+
+
rsa_plain() ->
<<"7896345786348756234 Hejsan Svejsan, erlang crypto debugger"
"09812312908312378623487263487623412039812 huagasd">>.
@@ -2112,7 +2684,9 @@ srp(ClientPrivate, Generator, Prime, Version, Verifier, ServerPublic, ServerPriv
SessionKey}.
ecdh() ->
%% http://csrc.nist.gov/groups/STM/cavp/
- Curves = crypto:ec_curves(),
+ Curves = crypto:ec_curves() ++
+ [X || X <- proplists:get_value(curves, crypto:supports(), []),
+ lists:member(X, [x25519,x448])],
TestCases =
[{ecdh, hexstr2point("42ea6dd9969dd2a61fea1aac7f8e98edcc896c6e55857cc0", "dfbe5d7c61fac88b11811bde328e8a0d12bf01a9d204b523"),
hexstr2bin("f17d3fea367b74d340851ca4270dcb24c271f445bed9d527"),
@@ -2195,7 +2769,32 @@ ecdh() ->
"2FDC313095BCDD5FB3A91636F07A959C8E86B5636A1E930E8396049CB481961D365CC11453A06C719835475B12CB52FC3C383BCE35E27EF194512B71876285FA"),
hexstr2bin("16302FF0DBBB5A8D733DAB7141C1B45ACBC8715939677F6A56850A38BD87BD59B09E80279609FF333EB9D4C061231FB26F92EEB04982A5F1D1764CAD57665422"),
brainpoolP512r1,
- hexstr2bin("A7927098655F1F9976FA50A9D566865DC530331846381C87256BAF3226244B76D36403C024D7BBF0AA0803EAFF405D3D24F11A9B5C0BEF679FE1454B21C4CD1F")}],
+ hexstr2bin("A7927098655F1F9976FA50A9D566865DC530331846381C87256BAF3226244B76D36403C024D7BBF0AA0803EAFF405D3D24F11A9B5C0BEF679FE1454B21C4CD1F")},
+
+ %% RFC 7748, 6.1
+ {ecdh,
+ 16#8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a,
+ 16#5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb,
+ x25519,
+ hexstr2bin("4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742")},
+ {ecdh,
+ 16#de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f,
+ 16#77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a,
+ x25519,
+ hexstr2bin("4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742")},
+
+ %% RFC 7748, 6.2
+ {ecdh,
+ 16#9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0,
+ 16#1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d,
+ x448,
+ hexstr2bin("07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d")},
+ {ecdh,
+ 16#3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609,
+ 16#9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b,
+ x448,
+ hexstr2bin("07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d")}
+ ],
lists:filter(fun ({_Type, _Pub, _Priv, Curve, _SharedSecret}) ->
lists:member(Curve, Curves)
end,
@@ -2216,7 +2815,32 @@ rsa_oaep() ->
hexstr2bin("4f456c502493bdc0ed2ab756a3a6ed4d67352a697d4216e93212b127a63d5411ce6fa98d5dbefd73263e3728142743818166ed7dd63687dd2a8ca1d2f4fbd8e1")],
%%Msg = hexstr2bin("6628194e12073db03ba94cda9ef9532397d50dba79b987004afefe34"),
Msg = hexstr2bin("750c4047f547e8e41411856523298ac9bae245efaf1397fbe56f9dd5"),
- {rsa, Public, Private, Msg, rsa_pkcs1_oaep_padding}.
+ {rsa, Public, Private, Msg, [{rsa_padding, rsa_pkcs1_oaep_padding}]}.
+
+rsa_oaep_label() ->
+ Public = [hexstr2bin("010001"),
+ hexstr2bin("a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb")],
+ Private = Public ++ [hexstr2bin("53339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf119517ef4f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d4ac4d1812b8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c483116ee3d3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d0cf539e9cfcdd3de653729ead5d1"),
+ hexstr2bin("d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d"),
+ hexstr2bin("cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77"),
+ hexstr2bin("0e12bf1718e9cef5599ba1c3882fe8046a90874eefce8f2ccc20e4f2741fb0a33a3848aec9c9305fbecbd2d76819967d4671acc6431e4037968db37878e695c1"),
+ hexstr2bin("95297b0f95a2fa67d00707d609dfd4fc05c89dafc2ef6d6ea55bec771ea333734d9251e79082ecda866efef13c459e1a631386b7e354c899f5f112ca85d71583"),
+ hexstr2bin("4f456c502493bdc0ed2ab756a3a6ed4d67352a697d4216e93212b127a63d5411ce6fa98d5dbefd73263e3728142743818166ed7dd63687dd2a8ca1d2f4fbd8e1")],
+ Msg = hexstr2bin("750c4047f547e8e41411856523298ac9bae245efaf1397fbe56f9dd5"),
+ Lbl = hexstr2bin("1332a67ca7088f75c9b8fb5e3d072882"),
+ {rsa, Public, Private, Msg, [{rsa_padding, rsa_pkcs1_oaep_padding}, {rsa_oaep_label, Lbl}]}.
+
+rsa_oaep256() ->
+ Public = [hexstr2bin("010001"),
+ hexstr2bin("a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb")],
+ Private = Public ++ [hexstr2bin("53339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf119517ef4f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d4ac4d1812b8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c483116ee3d3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d0cf539e9cfcdd3de653729ead5d1"),
+ hexstr2bin("d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d"),
+ hexstr2bin("cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77"),
+ hexstr2bin("0e12bf1718e9cef5599ba1c3882fe8046a90874eefce8f2ccc20e4f2741fb0a33a3848aec9c9305fbecbd2d76819967d4671acc6431e4037968db37878e695c1"),
+ hexstr2bin("95297b0f95a2fa67d00707d609dfd4fc05c89dafc2ef6d6ea55bec771ea333734d9251e79082ecda866efef13c459e1a631386b7e354c899f5f112ca85d71583"),
+ hexstr2bin("4f456c502493bdc0ed2ab756a3a6ed4d67352a697d4216e93212b127a63d5411ce6fa98d5dbefd73263e3728142743818166ed7dd63687dd2a8ca1d2f4fbd8e1")],
+ Msg = hexstr2bin("750c4047f547e8e41411856523298ac9bae245efaf1397fbe56f9dd5"),
+ {rsa, Public, Private, Msg, [{rsa_padding, rsa_pkcs1_oaep_padding}, {rsa_oaep_md, sha256}]}.
ecc() ->
%% http://point-at-infinity.org/ecc/nisttv
@@ -2294,36 +2918,43 @@ fmt_words(Words) ->
log_rsp_size(Label, Term) ->
S = erts_debug:size(Term),
- ct:pal("~s: ~w test(s), Memory used: ~s",
+ ct:log("~s: ~w test(s), Memory used: ~s",
[Label, length(Term), fmt_words(S)]).
read_rsp(Config, Type, Files) ->
Tests =
lists:foldl(
fun(FileName, Acc) ->
- read_rsp_file(filename:join(datadir(Config), FileName),
- Type, Acc)
+ NewAcc = read_rsp_file(filename:join(datadir(Config), FileName),
+ Type, Acc),
+ ct:log("~p: ~p tests read.~n",[FileName,length(NewAcc)-length(Acc)]),
+ NewAcc
end, [], Files),
log_rsp_size(Type, Tests),
Tests.
read_rsp_file(FileName, Type, Acc) ->
- {ok, Raw} = file:read_file(FileName),
- Split = binary:split(Raw, [<<"\r">>, <<"\n">>], [global, trim_all]),
- parse_rsp(Type, Split, Acc).
+ case file:read_file(FileName) of
+ {ok, Raw} ->
+ Split = binary:split(Raw, [<<"\r">>, <<"\n">>], [global, trim_all]),
+ parse_rsp(Type, Split, #{file => FileName}, Acc);
+ Other ->
+ ct:fail("~p ~p",[FileName, Other])
+ end.
-parse_rsp(_Type, [], Acc) ->
+parse_rsp(_Type, [], _State, Acc) ->
Acc;
-parse_rsp(_Type, [<<"DECRYPT">>|_], Acc) ->
+parse_rsp(_Type, [<<"DECRYPT">>|_], _State, Acc) ->
Acc;
%% AES format
parse_rsp(Type, [<<"COUNT = ", _/binary>>,
<<"KEY = ", Key/binary>>,
<<"IV = ", IV/binary>>,
<<"PLAINTEXT = ", PlainText/binary>>,
- <<"CIPHERTEXT = ", CipherText/binary>>|Next], Acc) ->
- parse_rsp(Type, Next, [{Type, hexstr2bin(Key), hexstr2bin(IV),
- hexstr2bin(PlainText), hexstr2bin(CipherText)}|Acc]);
+ <<"CIPHERTEXT = ", CipherText/binary>>|Next], State, Acc) ->
+ parse_rsp(Type, Next, State,
+ [{Type, hexstr2bin(Key), hexstr2bin(IV),
+ hexstr2bin(PlainText), hexstr2bin(CipherText)}|Acc]);
%% CMAC format
parse_rsp(Type, [<<"Count = ", _/binary>>,
<<"Klen = ", _/binary>>,
@@ -2331,23 +2962,23 @@ parse_rsp(Type, [<<"Count = ", _/binary>>,
<<"Tlen = ", Tlen/binary>>,
<<"Key = ", Key/binary>>,
<<"Msg = ", Msg/binary>>,
- <<"Mac = ", MAC/binary>>|Rest], Acc) ->
+ <<"Mac = ", MAC/binary>>|Rest], State, Acc) ->
case Rest of
[<<"Result = P">>|Next] ->
- parse_rsp_cmac(Type, Key, Msg, Mlen, Tlen, MAC, Next, Acc);
+ parse_rsp_cmac(Type, Key, Msg, Mlen, Tlen, MAC, Next, State, Acc);
[<<"Result = ", _/binary>>|Next] ->
- parse_rsp(Type, Next, Acc);
+ parse_rsp(Type, Next, State, Acc);
_ ->
- parse_rsp_cmac(Type, Key, Msg, Mlen, Tlen, MAC, Rest, Acc)
+ parse_rsp_cmac(Type, Key, Msg, Mlen, Tlen, MAC, Rest, State, Acc)
end;
%% GCM format decode format
-parse_rsp(Type, [<<"Count = ", _/binary>>,
+parse_rsp(Type, [<<"Count = ", Count/binary>>,
<<"Key = ", Key/binary>>,
<<"IV = ", IV/binary>>,
<<"CT = ", CipherText/binary>>,
<<"AAD = ", AAD/binary>>,
<<"Tag = ", CipherTag0/binary>>,
- <<"PT = ", PlainText/binary>>|Next], Acc) ->
+ <<"PT = ", PlainText/binary>>|Next], #{file:=File}=State, Acc) ->
CipherTag = hexstr2bin(CipherTag0),
TestCase = {Type,
hexstr2bin(Key),
@@ -2356,16 +2987,17 @@ parse_rsp(Type, [<<"Count = ", _/binary>>,
hexstr2bin(AAD),
hexstr2bin(CipherText),
CipherTag,
- size(CipherTag)},
- parse_rsp(Type, Next, [TestCase|Acc]);
+ size(CipherTag),
+ {File,decstr2int(Count)}},
+ parse_rsp(Type, Next, State, [TestCase|Acc]);
%% GCM format encode format
-parse_rsp(Type, [<<"Count = ", _/binary>>,
+parse_rsp(Type, [<<"Count = ", Count/binary>>,
<<"Key = ", Key/binary>>,
<<"IV = ", IV/binary>>,
<<"PT = ", PlainText/binary>>,
<<"AAD = ", AAD/binary>>,
<<"CT = ", CipherText/binary>>,
- <<"Tag = ", CipherTag0/binary>>|Next], Acc) ->
+ <<"Tag = ", CipherTag0/binary>>|Next], #{file:=File}=State, Acc) ->
CipherTag = hexstr2bin(CipherTag0),
TestCase = {Type,
hexstr2bin(Key),
@@ -2374,13 +3006,88 @@ parse_rsp(Type, [<<"Count = ", _/binary>>,
hexstr2bin(AAD),
hexstr2bin(CipherText),
CipherTag,
- size(CipherTag)},
- parse_rsp(Type, Next, [TestCase|Acc]);
+ size(CipherTag),
+ {File,decstr2int(Count)}},
+ parse_rsp(Type, Next, State, [TestCase|Acc]);
+%% CCM-VADT format
+parse_rsp(Type, [<<"[Alen = ", AlenB0/binary>>|Next], State0, Acc) ->
+ AlenSize = size(AlenB0) - 1, % remove closing ']'
+ Alen = decstr2int(<<AlenB0:AlenSize/binary>>),
+ State = State0#{alen => Alen},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"[Nlen = ", NlenB0/binary>>|Next], State0, Acc) ->
+ NlenSize = size(NlenB0) - 1, % remove closing ']'
+ Nlen = decstr2int(<<NlenB0:NlenSize/binary>>),
+ State = State0#{nlen => Nlen},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"[Plen = ", PlenB0/binary>>|Next], State0, Acc) ->
+ PlenSize = size(PlenB0) - 1, % remove closing ']'
+ Plen = decstr2int(<<PlenB0:PlenSize/binary>>),
+ State = State0#{plen => Plen},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"[Tlen = ", TlenB0/binary>>|Next], State0, Acc) ->
+ TlenSize = size(TlenB0) - 1, % remove closing ']'
+ Tlen = decstr2int(<<TlenB0:TlenSize/binary>>),
+ State = State0#{tlen => Tlen},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Alen = ", B/binary>>|Next], State0, Acc) ->
+ State = State0#{alen => decstr2int(B)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Plen = ", B/binary>>|Next], State0, Acc) ->
+ State = State0#{plen => decstr2int(B)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Count = ", B/binary>>|Next], State0, Acc) ->
+ State = State0#{count => B},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Nlen = ", B/binary>>|Next], State0, Acc) ->
+ State = State0#{nlen => decstr2int(B)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Tlen = ", B/binary>>|Next], State0, Acc) ->
+ State = State0#{tlen => decstr2int(B)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Key = ",Key/binary>>|Next], State0, Acc) ->
+ State = State0#{key => hexstr2bin(Key)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Nonce = ",Nonce/binary>>|Next], State0, Acc) ->
+ State = State0#{nonce => hexstr2bin(Nonce)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Adata = ",Adata/binary>>|Next], State0, Acc) ->
+ State = State0#{adata => hexstr2bin(Adata)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Payload = ",Payload/binary>>|Next], State0, Acc) ->
+ State = State0#{payload => hexstr2bin(Payload)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type,
+ [<<"CT = ", CT/binary>>|Next],
+ #{count := Count,
+ file := File,
+ alen := Alen,
+ plen := Plen,
+ nlen := Nlen,
+ tlen := Tlen,
+ key := Key,
+ nonce := IV,
+ adata := Adata,
+ payload := Payload
+ } = State, Acc) ->
+ AAD = <<Adata:Alen/binary>>,
+ PlainText = <<Payload:Plen/binary>>,
+ <<CipherText:Plen/binary, CipherTag:Tlen/binary>> = hexstr2bin(CT),
+ TestCase = {Type,
+ Key,
+ PlainText,
+ IV,
+ AAD,
+ CipherText,
+ CipherTag,
+ Tlen,
+ {File,decstr2int(Count)}},
+ parse_rsp(Type, Next, State, [TestCase|Acc]);
+parse_rsp(Type, [_|Next], State, Acc) ->
+ parse_rsp(Type, Next, State, Acc).
-parse_rsp(Type, [_|Next], Acc) ->
- parse_rsp(Type, Next, Acc).
-parse_rsp_cmac(Type, Key0, Msg0, Mlen0, Tlen, MAC0, Next, Acc) ->
+parse_rsp_cmac(Type, Key0, Msg0, Mlen0, Tlen, MAC0, Next, State, Acc) ->
Key = hexstr2bin(Key0),
Mlen = binary_to_integer(Mlen0),
<<Msg:Mlen/bytes, _/binary>> = hexstr2bin(Msg0),
@@ -2388,7 +3095,18 @@ parse_rsp_cmac(Type, Key0, Msg0, Mlen0, Tlen, MAC0, Next, Acc) ->
case binary_to_integer(Tlen) of
0 ->
- parse_rsp(Type, Next, [{Type, Key, Msg, MAC}|Acc]);
+ parse_rsp(Type, Next, State, [{Type, Key, Msg, MAC}|Acc]);
I ->
- parse_rsp(Type, Next, [{Type, Key, Msg, I, MAC}|Acc])
+ parse_rsp(Type, Next, State, [{Type, Key, Msg, I, MAC}|Acc])
end.
+
+api_errors_ecdh(Config) when is_list(Config) ->
+ %% Check that we don't segfault when fed garbage.
+ Test = fun(Others, Curve) ->
+ {_Pub, Priv} = crypto:generate_key(ecdh, Curve),
+ crypto:compute_key(ecdh, Others, Priv, Curve)
+ end,
+ Others = [gurka, 0, <<0>>],
+ Curves = [gaffel, 0, sect571r1],
+ [_= (catch Test(O, C)) || O <- Others, C <- Curves],
+ ok.
diff --git a/lib/crypto/test/crypto_SUITE_data/VADT128.rsp b/lib/crypto/test/crypto_SUITE_data/VADT128.rsp
new file mode 100644
index 0000000000..a4fe9130a0
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VADT128.rsp
@@ -0,0 +1,1823 @@
+# CAVS 11.0
+# "CCM-VADT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:24 2011
+
+Plen = 24
+Nlen = 13
+Tlen = 16
+
+[Alen = 0]
+
+Key = d24a3d3dde8c84830280cb87abad0bb3
+Nonce = f1100035bb24a8d26004e0e24b
+
+Count = 0
+Adata = 00
+Payload = 7c86135ed9c2a515aaae0e9a208133897269220f30870006
+CT = 1faeb0ee2ca2cd52f0aa3966578344f24e69b742c4ab37ab1123301219c70599b7c373ad4b3ad67b
+
+Count = 1
+Adata = 00
+Payload = 48df73208cdc63d716752df7794807b1b2a80794a2433455
+CT = 2bf7d09079bc0b904c711a0b0e4a70ca8ea892d9566f03f8b77a140819f39ef045103e785e1df8c2
+
+Count = 2
+Adata = 00
+Payload = b99de8168e8c13ea4aef66bdb93133dff5d57e9837ff6ccb
+CT = dab54ba67bec7bad10eb5141ce3344a4c9d5ebd5c3d35b664b01098842a618390619b86e00850b2e
+
+Count = 3
+Adata = 00
+Payload = 09fc21ac4a1f43de29621cacf3ad84e055c6b220721af7ce
+CT = 6ad4821cbf7f2b9973662b5084aff39b69c6276d8636c0638bd518724ab84fb814fe7b5570769f7f
+
+Count = 4
+Adata = 00
+Payload = cb43320d7488dfd6eed9efd88f440ea3f6f77a0df09d0727
+CT = a86b91bd81e8b791b4ddd824f84679d8caf7ef4004b1308a7229cbcecef221570cee8345b38cd6ec
+
+Count = 5
+Adata = 00
+Payload = a350ed58c04473e113b9088b1fb9dad92807f6b63b0d690c
+CT = c0784ee835241ba649bd3f7768bbada2140763fbcf215ea1fee47fec27d7764e5e2819c850088bac
+
+Count = 6
+Adata = 00
+Payload = 0709e691faf41383fab5d1848a8eee77101d1c99e526a264
+CT = 642145210f947bc4a0b1e678fd8c990c2c1d89d4110a95c954d610bc1ab4bc9a8a28c7306f7c539e
+
+Count = 7
+Adata = 00
+Payload = e7b913c2f0630562eb1c16b3b1ed84090c011a15c09e5471
+CT = 8491b07205036d25b118214fc6eff37230018f5834b263dc2e31657ecc51f5ec8590482fc053230d
+
+Count = 8
+Adata = 00
+Payload = 6b909697074900d41ce8c7d559b229af11fb3cec334784d4
+CT = 08b83527f229689346ecf0292eb05ed42dfba9a1c76bb379d500827f2081b00397102f90fc9ccd88
+
+Count = 9
+Adata = 00
+Payload = 495ff03335bcb39a317b9ea3f8bb6306fa771f3c55adebce
+CT = 2a775383c0dcdbdd6b7fa95f8fb9147dc6778a71a181dc63e2e7997803029476598c0e8d4fc63857
+
+[Alen = 1]
+
+Key = 08b0da255d2083808a1b4d367090bacc
+Nonce = 777828b13679a9e2ca89568233
+
+Count = 10
+Adata = dd
+Payload = 1b156d7e2bf7c9a25ad91cff7b0b02161cb78ff9162286b0
+CT = e8b80af4960d5417c15726406e345c5c46831192b03432eed16b6282283e16602331bcca9d51ce76
+
+Count = 11
+Adata = c5
+Payload = 032fee9dbffccc751e6a1ee6d07bb218b3a7ec6bf5740ead
+CT = f0828917020651c085e42459c544ec52e99372005362baf308ebeed45f67ef8733737c9c6f82daad
+
+Count = 12
+Adata = 68
+Payload = 9c4cd65b92070bc382fd18146611defb4204acddfdf6b276
+CT = 6fe1b1d12ffd9676197322ab732e80b1183032b65be00628f9b477e3a23bfdfdb619c7bc531fbcce
+
+Count = 13
+Adata = be
+Payload = 2ff93ef2fc5fe2c297ace05f3f7585aed75ef90ade3acf89
+CT = dc54597841a57f770c22dae02a4adbe48d6a6761782c7bd7aa82130f5a86c0cd0433585e5c208cf7
+
+Count = 14
+Adata = 7a
+Payload = 62766e9acd41285eeed9b4007340dbb611699624274ad117
+CT = 91db091070bbb5eb75578ebf667f85fc4b5d084f815c65499d60012a2f25463e036ceecea57b3c97
+
+Count = 15
+Adata = 13
+Payload = ea689c268a04912d0527b16d9d9406df38302fb11cb64a99
+CT = 19c5fbac37fe0c989ea98bd288ab58956204b1dabaa0fec7e337897c90eb260729a729aed1c8a244
+
+Count = 16
+Adata = e5
+Payload = f31e35953beb211efcce487ba8c0cd1a8446343d5851b9fd
+CT = 00b3521f8611bcab674072c4bdff9350de72aa56fe470da373dc2911c75b37cd995481d42b04524a
+
+Count = 17
+Adata = e3
+Payload = c4ac3c645387584c2a95b1f16b8317730592924dd831a388
+CT = 37015beeee7dc5f9b11b8b4e7ebc49395fa60c267e2717d684f76ecf3dc5f3307ce982f185321248
+
+Count = 18
+Adata = d5
+Payload = 81af394c2ea3a85e1ea954596e3772f01635d007794c0b19
+CT = 72025ec6935935eb85276ee67b082cba4c014e6cdf5abf472c38d0fe4e4eba054c1420c39a3dcc61
+
+Count = 19
+Adata = ed
+Payload = e013a2edd5b86bab8df5c9940d0a0c864478c1ad42668304
+CT = 13bec5676842f61e167bf32b183552cc1e4c5fc6e470375a7cfa6c9945f5aee3c799eee37b0605db
+
+[Alen = 2]
+
+Key = 1538cc03b60880bf3e7d388e29f27739
+Nonce = 9e734de325026b5d7128193973
+
+Count = 20
+Adata = c93c
+Payload = e7b819a853ffe79baaa72097ff0d04f02640ae62bcfd3da5
+CT = 1d8f42f9730424fa27240bd6277f4882604f440324b11b003ca01d874439b4e1f79a26d8c6dc433a
+
+Count = 21
+Adata = 4cf9
+Payload = dc6cf325ed6d968efba9f57e48a58f4578cc3540fe121ba2
+CT = 265ba874cd9655ef762ade3f90d7c3373ec3df21665e3d07b40653cd23afc7cc7a31fa13ba8f4e49
+
+Count = 22
+Adata = b469
+Payload = 22ab6a0daf953165dda864cceeeb782e275c0b072aedd284
+CT = d89c315c8f6ef204502b4f8d3699345c6153e166b2a1f421c8c10aaf90b1116be216f912c82ca96a
+
+Count = 23
+Adata = cf6b
+Payload = a35f62a431fee63468dc02fdf7bef78d3a5937de56151939
+CT = 596839f511052555e55f29bc2fccbbff7c56ddbfce593f9c2f568ef41324189fb3644edcd76dc19c
+
+Count = 24
+Adata = af7c
+Payload = 548840cb0400824af809fb68447500b77e977128200d3b81
+CT = aebf1b9a24fb412b758ad0299c074cc538989b49b8411d242548c244a875d3681d715db3da19962f
+
+Count = 25
+Adata = 61dc
+Payload = 440b6095c77495e73fff54c785b7ceb5eb358731c213ffcd
+CT = be3c3bc4e78f5686b27c7f865dc582c7ad3a6d505a5fd968b599bc8927ad8d43067807f4b858f854
+
+Count = 26
+Adata = b97e
+Payload = 50c59ca54eb64575b82b13c6dac96488af369e9f5f86cdf2
+CT = aaf2c7f46e4d861435a8388702bb28fae93974fec7caeb577454774ee78f76e555cf743df340381e
+
+Count = 27
+Adata = 57ab
+Payload = 21b8eb1f0bda26ca36167ce7bc2e796818bf11fc8c192885
+CT = db8fb04e2b21e5abbb9557a6645c351a5eb0fb9d14550e20e0a22a5ee031978271c7dd2a0d4e7018
+
+Count = 28
+Adata = 5f9c
+Payload = b4d84fb1e81e18c89391a7a59fc05fedaf160e0d0d027a7c
+CT = 4eef14e0c8e5dba91e128ce447b2139fe919e46c954e5cd99a242ebae5c6da57ee38e5c227c46b32
+
+Count = 29
+Adata = e0c4
+Payload = 54dc5a0e1b67577cda4e7dbd48b769c120c1d13dd567cfad
+CT = aeeb015f3b9c941d57cd56fc90c525b366ce3b5c4d2be908a5f8a92f4201c4658289307167cee810
+
+[Alen = 3]
+
+Key = f149e41d848f59276cfddd743bafa9a9
+Nonce = 14b756d66fc51134e203d1c6f9
+
+Count = 30
+Adata = f5827e
+Payload = 9759e6f21f5a588010f57e6d6eae178d8b20ab59cda66f42
+CT = f634bf00f1f9f1f93f41049d7f3797b05e805f0b14850f4e78e2a23411147a6187da6818506232ee
+
+Count = 31
+Adata = e9699b
+Payload = 1555bc87d6c688fd221a2c75cd1e4dd1c1693207ac421d24
+CT = 7438e575386521840dae5685dc87cdec14c9c65575617d28f10835db9897b7528e3204fe3a81424f
+
+Count = 32
+Adata = 972896
+Payload = b72b2a080d92f3f3bb7d96222982de82a28c9eebaddba247
+CT = d64673fae3315a8a94c9ecd2381b5ebf772c6ab974f8c24b3efa05ba4a73ec2234461d459f54acd2
+
+Count = 33
+Adata = 3053f3
+Payload = b5417ed6933ffe2b57ea601d77e97eb12fa1fb8fdc06c86f
+CT = d42c27247d9c5752785e1aed6670fe8cfa010fdd0525a863b557537c6525e827750917a1ed49602f
+
+Count = 34
+Adata = 24db75
+Payload = 4e7f42666035a00e62783283c54b027603917685d27326bc
+CT = 2f121b948e9609774dcc4873d4d2824bd63182d70b5046b0dfd06b037e9094f120eb3d8649d48918
+
+Count = 35
+Adata = ff27a4
+Payload = 7bf180699c294421ad9565cacc27227a4b3a7cf9637290c6
+CT = 1a9cd99b728aed5882211f3addbea2479e9a88abba51f0cabfa8cfabbd79b3e3210482e6f3822fee
+
+Count = 36
+Adata = 77ec24
+Payload = 3d47071c13f994cb42fb2887e5c6e53a542be7ddad9779e0
+CT = 5c2a5eeefd5a3db26d4f5277f45f6507818b138f74b419ec3b9575e347051e98d0c8646ad46318e6
+
+Count = 37
+Adata = 6d7748
+Payload = 317d5da0a2ec12c3b96c83dd61cc955242a9c1c640e2b92f
+CT = 501004524c4fbbba96d8f92d7055156f9709359499c1d92378e7af65eb0388ae7a52f58f6ba32109
+
+Count = 38
+Adata = 029674
+Payload = c9bb21306ee1b4a6c4fa5443af2e181716993cbb374e177c
+CT = a8d678c280421ddfeb4e2eb3beb7982ac339c8e9ee6d77708019fa97ff70d4d21c0bd83caa434b3a
+
+Count = 39
+Adata = 60dfe8
+Payload = 44eb7edd6bee501ad97873aa7ecbf7ed8b613760d7c95e15
+CT = 2586272f854df963f6cc095a6f5277d05ec1c3320eea3e191814ed48a21d97ea02e86d7e6e8834cb
+
+[Alen = 4]
+
+Key = 9a57a22c7f26feff8ca6cceff214e4c2
+Nonce = 88f30fd2b04fb8ddbce8fc26e6
+
+Count = 40
+Adata = a95bdff6
+Payload = 035c516776c706a7dd5f181fa6aa891b04dd423042ea0667
+CT = b92f7ec2ebecebdbd2977b3874e61bf496a382153b2529fc9b6443a35f329b2068916fb6ab8227eb
+
+Count = 41
+Adata = d2672cbb
+Payload = 3ba306bcec94615c347f990b62841a16df7b321f113f1714
+CT = 81d0291971bf8c203bb7fa2cb0c888f94d05f23a68f0388f19e2aa492ce9ddfb6de0ab7a447f5351
+
+Count = 42
+Adata = 737f4d00
+Payload = 68313a29ace3efe521c3ca1e5bac8e98d6b4434c80a7dc74
+CT = d242158c31c802992e0ba93989e01c7744ca8369f968f3ef2bf683b1209f104e82ba39f7c62cd666
+
+Count = 43
+Adata = 3610b1ae
+Payload = 963bfe556138317bebe3936b18a2c1dd100dc73be6fde556
+CT = 2c48d1f0fc13dc07e42bf04ccaee53328273071e9f32cacd4fc7d5cac043f182edbe5c2658f73092
+
+Count = 44
+Adata = f1aa7f72
+Payload = 52d5c53ee4f23cb050a95db54112b44033c34ac31de96be8
+CT = e8a6ea9b79d9d1cc5f613e92935e26afa1bd8ae664264473b8234f3fbaca3dc2c497418219151b05
+
+Count = 45
+Adata = 6b1013aa
+Payload = a302aebc0f8fd61badc8371991beacf5933de46effacb8ce
+CT = 1971811992a43b67a200543e43f23e1a0143244b866397558fa5f9539e0500f139016e4a4337d86b
+
+Count = 46
+Adata = 33028129
+Payload = f7d653c23254875625b20e1ef60ae92847046d84bb4ce857
+CT = 4da57c67af7f6a2a2a7a6d3924467bc7d57aada1c283c7ccfa2379fde155e64b5b84e336056445c3
+
+Count = 47
+Adata = 2cab4a09
+Payload = 872a3f7230e626abff519e5aeecc93897249405daeaffc98
+CT = 3d5910d7adcdcbd7f099fd7d3c800166e0378078d760d30358208335cb81e4fb10923fca4ddb9ff9
+
+Count = 48
+Adata = 73142ba7
+Payload = 766f94e7d9b1ce74bbaf2c99d215350f060122767fc1953f
+CT = cc1cbb42449a2308b4674fbe0059a7e0947fe253060ebaa42d6ecfb49ac8983415503efef1e21950
+
+Count = 49
+Adata = bc9f967e
+Payload = 5f089ed9267363bc23c6c7b8f73208a36f61fa8ea8084ff7
+CT = e57bb17cbb588ec02c0ea49f257e9a4cfd1f3aabd1c7606c1978a62d15430fc20b87940292b49641
+
+[Alen = 5]
+
+Key = 54caf96ef6d448734700aadab50faf7a
+Nonce = a3803e752ae849c910d8da36af
+
+Count = 50
+Adata = 5f476348dd
+Payload = c69f7c5a50f3e72123371bbfd6bdf532b99ef78500508dfe
+CT = 20c43ad83610880249f1632dd418ec9a5ed333b50e996d1a4e5a32fbe7961b832b722bc07a18595b
+
+Count = 51
+Adata = 07db8aada5
+Payload = 9cf8b638f2b295b85cf782fabab11153dc091b4afcd761a9
+CT = 7aa3f0ba9451fa9b3631fa68b81408fb3b44df7af21e814d401a2222443696021b5faa520129b563
+
+Count = 52
+Adata = 31ef6561ff
+Payload = 62b8263dc015ef873cd16272e4da89799b910f2b04204420
+CT = 84e360bfa6f680a456171ae0e67f90d17cdccb1b0ae9a4c4f842681d2e90da5718234ed893197662
+
+Count = 53
+Adata = e97dfcbafb
+Payload = 810bed3a2bc0f9d75389155b7a39d9d014c08646814f9718
+CT = 6750abb84d2396f4394f6dc9789cc078f38d42768f8677fc33a08eb30ee154f71279682ab02eff27
+
+Count = 54
+Adata = 4981c51fcc
+Payload = 063d23fc3ec344c1ba3486802e01e55617455d5cfbfb5279
+CT = e066657e58202be2d0f2fe122ca4fcfef008996cf532b29d8d3071c79f0cf86fe4148cb5e8ace0ce
+
+Count = 55
+Adata = c8437dba76
+Payload = 41db5b245ea0fab985b93e7fc0a00cd3cca5bdbb642b7ebf
+CT = a7801da63843959aef7f46edc205157b2be8798b6ae29e5b842700619dc1599603f3f3f6cfdf5e0b
+
+Count = 56
+Adata = 6f65a24344
+Payload = b0e36734b2ba871d59df0b029c7f32af68e003a689ac4911
+CT = 56b821b6d459e83e331973909eda2b078fadc7968765a9f539a0cd8d8bbf211b907f34411f868c79
+
+Count = 57
+Adata = cd62d6d203
+Payload = 747e53e627eabde0cd77d78d1bd720bea518f8a2f76e57a2
+CT = 922515644109d2c3a7b1af1f1972391642553c92f9a7b746c4a90e5fc11266bab77eea1d24fbdbb9
+
+Count = 58
+Adata = 9663b3c8e6
+Payload = c70c92ec4c518802662fa4c41a6a33a22599f79f8f7264b3
+CT = 2157d46e2ab2e7210ce9dc5618cf2a0ac2d433af81bb8457b3c1246f7dd6462ce757db82db45f36e
+
+Count = 59
+Adata = 35c4720d3c
+Payload = a26835605b66fc08abdbb5dc77e39783d60b8e8f2314e95f
+CT = 443373e23d85932bc11dcd4e75468e2b31464abf2ddd09bbd472c06a5f4c04f97d06ec401d3e7fd9
+
+[Alen = 6]
+
+Key = cc0c084d7de011e2f031616a302e7a31
+Nonce = f0b4522847f6f8336fe534a4e7
+
+Count = 60
+Adata = da853a27aee2
+Payload = 15b369889699b6de1fa3ee73e5fe19814e46f129074c965b
+CT = f39755d160a64611368a8eccf6fcbc45ef7f1f56240eb19a2e3ca4ec3c776ab58843f617d605fd72
+
+Count = 61
+Adata = d4ed4584678e
+Payload = a18c0460b56a5bcd5bf6842cec6ed44d90b2bfa968a6a7e7
+CT = 47a838394355ab0272dfe493ff6c7189318b51d64be48026327804c44c8f17a4446a3d5ba85f9c7f
+
+Count = 62
+Adata = 590a27721a36
+Payload = 41cee0ecaf9c65cef740440af37954ef49a585779d2abbca
+CT = a7eadcb559a39501de6924b5e07bf12be89c6b08be689c0bbcd00e9cb726d75e4283820ee81d933a
+
+Count = 63
+Adata = 58830fb0b1f3
+Payload = dce983e4e3734a9bd8848dba0d744d07bbeba602f4006025
+CT = 3acdbfbd154cba54f1aded051e76e8c31ad2487dd74247e4d5d71a1f0f1b6518c35f0632a30931fd
+
+Count = 64
+Adata = eedd0d767a25
+Payload = 4653b3e879ab18b65c5c3706a5139698262cb830a22d943b
+CT = a0778fb18f94e879757557b9b611335c8715564f816fb3fa3ad112899e9ba442660eb5dfe33b2f96
+
+Count = 65
+Adata = 618bcf2e3e79
+Payload = 8586383281925363ac15fb19c26d64c639c75920c792dc2c
+CT = 63a2046b77ada3ac853c9ba6d16fc10298feb75fe4d0fbed54fba446028919342b2fe86ee67efcc7
+
+Count = 66
+Adata = 549c9b84c7f7
+Payload = 95c25ae4445cd8c4d267df82687484667e309992fcf1e737
+CT = 73e666bdb263280bfb4ebf3d7b7621a2df0977eddfb3c0f69fc23013142f62881ccfa3037067e1ef
+
+Count = 67
+Adata = 92d7fa6a8135
+Payload = e58034bbb0e6f5e724e32ee56896dadae25c2a3efb8c6f2f
+CT = 03a408e246d905280dca4e5a7b947f1e4365c441d8ce48ee8263568d56fae8bf35b2f2cdecbffe0a
+
+Count = 68
+Adata = f43e126c0f83
+Payload = d98f0dddfe9cb3cae1336970d5efb55316a65e2c51e316f4
+CT = 3fab318408a34305c81a09cfc6ed1097b79fb05372a13135de2c2fbfdddc7dd6672714af174c5121
+
+Count = 69
+Adata = f02074812dde
+Payload = 548747b1669c6383b793054d93957f9e99d605761c6c23b5
+CT = b2a37be890a3934c9eba65f28097da5a38efeb093f2e04743704560ff23ce0000fba8812c45940ad
+
+[Alen = 7]
+
+Key = d7572ed0e37261efa02f8c83e695efdc
+Nonce = f4f96d7b4384a3930b3d830f82
+
+Count = 70
+Adata = 922340ec94861f
+Payload = 1edef80c57d17f969f8bde10ab38a1a8811a124de72c526e
+CT = de14558cc686e1836f1f121ea1b941a9ebd4f0fb916dc870fd541b988a801cb5751c7faaf5b0c164
+
+Count = 71
+Adata = 4eb379f21b1531
+Payload = ddd5282a207c1dcb03c1c3bbc9eb12a7bd28534118db2735
+CT = 1d1f85aab12b83def3550fb5c36af2a6d7e6b1f76e9abd2bc068bd1b1c309dfbd52d9a24be07c630
+
+Count = 72
+Adata = 7fa89e9d6e3fec
+Payload = c5b7c462eb166f48bb59c8102ee7b3dc67a28e5de7570c51
+CT = 057d69e27a41f15d4bcd041e246653dd0d6c6ceb9116964f2d114d6ab082738d05d60acca8e8ccfb
+
+Count = 73
+Adata = fda8665f87c618
+Payload = af793815e147e3180f5146aa6a582e343dc479f26b4226b2
+CT = 6fb3959570107d0dffc58aa460d9ce35570a9b441d03bcac1cc84bd77fe00e1a13433f2c10e3b799
+
+Count = 74
+Adata = 46bde207491ebd
+Payload = 47c76a0bbd5b1616b278089d41a050c509c7a1c280574bf7
+CT = 870dc78b2c0c880342ecc4934b21b0c463094374f616d1e9990c81f1bae32c953bf02ddbde047632
+
+Count = 75
+Adata = a799f5f895fd7a
+Payload = d554806ffc3900a0952a3c094c745808950697a6e5d62c1d
+CT = 159e2def6d6e9eb565bef00746f5b809ffc875109397b6031af19f1f080dd1dd2da799059755e49f
+
+Count = 76
+Adata = 20225831a9ee06
+Payload = ba45e1859efae362a44a0116a14e488ba369da6c76c3913b
+CT = 7a8f4c050fad7d7754decd18abcfa88ac9a738da00820b2523d3b9a0060834ac4860dae0eac570ef
+
+Count = 77
+Adata = 785360916464eb
+Payload = 57bc338946ff78cf76adf5021e2e44e34e687fb68ad703f3
+CT = 97769e09d7a8e6da8639390c14afa4e224a69d00fc9699edff96e7cf841a66c50bbb6fb2bac7ef51
+
+Count = 78
+Adata = 57b946369226db
+Payload = 9ac5be9929c4fe5a9992749a38dc69874866db3d4747da97
+CT = 5a0f1319b893604f6906b894325d898622a8398b3106408986e1c33a45f9d52755c374650635bef6
+
+Count = 79
+Adata = 73e4da8973c1e3
+Payload = 5a05410aa3a71f5f1a253b8576eba269c06a4c30591144cc
+CT = 9acfec8a32f0814aeab1f78b7c6a4268aaa4ae862f50ded2d78592c2d89c15edc5bb7486aa93f896
+
+[Alen = 8]
+
+Key = 98a42d7a0c5917deaf3b4de3f0cbe0a1
+Nonce = 03d33ab0c2df7bfce88b5ee4c4
+
+Count = 80
+Adata = 2d5438b728b950d9
+Payload = 9aa9c8358117564371366beeec923051ef433252197aaad5
+CT = 9ff942baa60f440c17a78e9581216b9a947a67f04d54911feecfff971fdfaa856310b014aa59c978
+
+Count = 81
+Adata = 6e430b497a16e7f5
+Payload = 5758a500978c71a9b90f6e5beae9d96ef05a41486b10ea2e
+CT = 52082f8fb09463e6df9e8b20875a82a58b6314ea3f3ed1e46a4d7b4b4df6c831ee32116ee4dad98c
+
+Count = 82
+Adata = e12f98507d6514c3
+Payload = 49efe18c76a8355127d914a3a830c1c6ff2a163d728526e1
+CT = 4cbf6b0351b0271e4148f1d8c5839a0d8413439f26ab1d2b3243fc75cd1624e152f451678edcac87
+
+Count = 83
+Adata = eecf8d641ee0bee9
+Payload = 49ae2309fbe6ce4e9421516b8f79ae64b1316cb849eaf638
+CT = 4cfea986dcfedc01f2b0b410e2caf5afca08391a1dc4cdf2dd6d8ca57da1880e1baff43736b3da34
+
+Count = 84
+Adata = 9066367c784de0a4
+Payload = b1bda5fa4242aa6aad0f5a5b1d31d86b8d4a97588b3e315d
+CT = b4ed2f75655ab825cb9ebf20708283a0f673c2fadf100a97f05439a661001513a96b896de46b7081
+
+Count = 85
+Adata = edf848b2510f7803
+Payload = eaa8608f6763d968576a7e89056b9828a1686c8441b06377
+CT = eff8ea00407bcb2731fb9bf268d8c3e3da513926159e58bdcf20709b2dc2ff9946094190b5ea09d1
+
+Count = 86
+Adata = 0f49cae81c8628d2
+Payload = f32029cf51609f0df9832ad1b283ea94a5356f70112c1328
+CT = f670a34076788d429f12cfaadf30b15fde0c3ad2450228e2a5bb6b4f87b9b198665203e4fdf9e7f7
+
+Count = 87
+Adata = b0c47e9cce46a276
+Payload = 7a550ef9254a8da6e4fee290a76ea838ffb61d3533d4d31f
+CT = 7f05847602529fe9826f07ebcaddf3f3848f489767fae8d529f416f89f1a34bbbf2ce40d943c6d8b
+
+Count = 88
+Adata = a6fe7c9ce2d49f85
+Payload = e67c486dd7ba9a9061844b9354f55890321ae626efaa28cc
+CT = e32cc2e2f0a288df0715aee83946035b4923b384bb8413067eb95550b91b955d5c2d72d5c189b704
+
+Count = 89
+Adata = eb1d11cc4876f58f
+Payload = 35f2c810091e930a52e4a3f28c9c8184967f1554c2675eb5
+CT = 30a2429f2e06814534754689e12fda4fed4640f69649657f0e8e8a5a7e0ea6860bab4a4320f03ae5
+
+[Alen = 9]
+
+Key = 2a68e3fe746f593c1b97cb637079c3e5
+Nonce = cd62d0f27b7f4864dc7c343acd
+
+Count = 90
+Adata = abe4f1d3812bfe3ccf
+Payload = 13b4a874888db0e5d8fd814b5e7e04f7fdfbc1601ccc02bc
+CT = 032835a3dbf688d09cf2a32a92b101959d33ff47500f92f4fd49840440f866d1a22b0854996111d8
+
+Count = 91
+Adata = 2e21f466814d3d6340
+Payload = 08b5c773364cded74d7b308984313c17ff90eed496a27a2b
+CT = 18295aa46537e6e2097412e848fe39759f58d0f3da61ea63de2f5c335df537fbbc6ae59cd562732f
+
+Count = 92
+Adata = dba22aabcea0e694fc
+Payload = bbac1790abb7aafe272ec472c897e6363e335b3c4126c762
+CT = ab308a47f8cc92cb6321e6130458e3545efb651b0de5572acc5ed6e4a907ff4742ab6c835a427f92
+
+Count = 93
+Adata = 97e9d16bd757395ec1
+Payload = 7249612dc09809bbca9dd311e720f7da2cb54ce33e3eb9c3
+CT = 62d5fcfa93e3318e8e92f1702beff2b84c7d72c472fd298b1714b5a3df454f3bc35869da75adc882
+
+Count = 94
+Adata = 866cf710470cac74d3
+Payload = 060ae0ab9857324a3b2ac79f3b6e6f90f5de884ce9c7b930
+CT = 16967d7ccb2c0a7f7f25e5fef7a16af29516b66ba5042978aa33dffe2596832f98a9c8413bd898b9
+
+Count = 95
+Adata = 2dd7a7f832b29ccce2
+Payload = f77a9fd5363836deefd34e1bea0882484a7ab746b4495d59
+CT = e7e6020265430eebabdc6c7a26c7872a2ab28961f88acd11dd5049f7c53d6a7fe5d7f959689ee960
+
+Count = 96
+Adata = 502349a60e897356b5
+Payload = 96118dbfe53434d8aed88769a535eb0c8b5849dca1c81c34
+CT = 868d1068b64f0cedead7a50869faee6eeb9077fbed0b8c7ced9c3a0d0de8788471c5f6c2f9638b7c
+
+Count = 97
+Adata = debed45c9acf129268
+Payload = df5a47d3eb5c0b6cabb6711a45400602d205b82ecae9e849
+CT = cfc6da04b8273359efb9537b898f0360b2cd8609862a7801d49b4b9bead1b7de2021cff280d6f93b
+
+Count = 98
+Adata = 2726702dd62a6e5344
+Payload = 5a7649cb001fbb6f653cbca17756c5c1a078c2e240d92085
+CT = 4aead41c5364835a21339ec0bb99c0a3c0b0fcc50c1ab0cd69df31aba209d87ee22bd6a1dcadb168
+
+Count = 99
+Adata = e8006cfb0536696ac7
+Payload = 95186d41f927cdbef42157f21d966e88061b6558b5ec932f
+CT = 8584f096aa5cf58bb02e7593d1596bea66d35b7ff92f03677cc5b60c881fe834a789d28447d8fb54
+
+[Alen = 10]
+
+Key = 46b067cf9b1a28cf187002e90b14e130
+Nonce = bad8c03292bf01cfd8d34f860c
+
+Count = 100
+Adata = 8d65880eddb9fd96d276
+Payload = cc0915194218d4536e467433cd6d79ff1d9eb9ff160ab684
+CT = bd56edc015692c6ab9bec493a9893863598414a3d11a6a0f27ecdcb257d0d30491e5bf1aa8f90958
+
+Count = 101
+Adata = 8a65cde13149d9d54a5b
+Payload = 28257133b1d8b0b2be4faecd6e819ac783707a5c5f50c302
+CT = 597a89eae6a9488b69b71e6d0a65db5bc76ad70098401f89b10f9fc201e4128696dcd899dd2e24ea
+
+Count = 102
+Adata = e999ec3e1bfb25b5877c
+Payload = 96ab0cfc204bafc4f5851d6c682d631d0c5ad03ac925a943
+CT = e7f4f425773a57fd227dadcc0cc9228148407d660e3575c8c522e5ba5adbc6a639cbd06f103ebc9e
+
+Count = 103
+Adata = a8554441e073d6065dce
+Payload = 50925853a84a33ff392154e4e737efc18dcfc98f4d5235a9
+CT = 21cda08aff3bcbc6eed9e44483d3ae5dc9d564d38a42e922e1a4e0f7ebc3cff3915d27971cce7e91
+
+Count = 104
+Adata = 838f0be8d04d28d77549
+Payload = d0700658d5f4010ff21091f3d119c99645e339198029c3a9
+CT = a12ffe818285f93625e82153b5fd880a01f9944547391f22c215c88d80bffc881aff10ba40f11976
+
+Count = 105
+Adata = 20f014d928d5b25fbaf4
+Payload = 4bdf28748a0c281dd49c7294ae8e55fe7a52d45ff6384db3
+CT = 3a80d0addd7dd0240364c234ca6a14623e487903312891382cc9391bc06aa6ca9d486a4e2a218c54
+
+Count = 106
+Adata = 56c026b8a71974ff7ecd
+Payload = f75db057f0276fff85014f54ecdec8f90b96a2a982db14cb
+CT = 8602488ea75697c652f9fff4883a89654f8c0ff545cbc840778b05c6c582a0bb7d1d9dcf6a46b9f6
+
+Count = 107
+Adata = 75c3b9e52648a4f9aca9
+Payload = c15c554169dbb9b08494afaa44819a10dc9ddad54199ab54
+CT = b003ad983eaa4189536c1f0a2065db8c98877789868977dff47d9ebbd3cff14623b10cecc94b53d6
+
+Count = 108
+Adata = 1c76c3014a14b7fa1ca8
+Payload = 19eef6f798fc68086aad1cda6d7976cdcfe6b8af74598032
+CT = 68b10e2ecf8d9031bd55ac7a099d37518bfc15f3b3495cb9d2b74b84dc170c00dce85b56e346a976
+
+Count = 109
+Adata = a4eb60d4eb7ead1bd0e6
+Payload = e06e5dba5ac35cfd07949e5cc12ad70507d4a86a952ecca3
+CT = 9131a5630db2a4c4d06c2efca5ce969943ce0536523e1028d92e19fd8b5c1fcbff36adaa5e47ae84
+
+[Alen = 11]
+
+Key = e94dac9c90984790a7c0c867536615ff
+Nonce = c19f06f91e645d4199365f18c0
+
+Count = 110
+Adata = 537038b5357e358a930bd6
+Payload = 4d64461c55eb16bf7b9120f22be349598f2f394da8460dc6
+CT = e9fc5004c2359724e1e4411ae6f834ef6bea046d549753c88790c1648f461a31c84e62ea8592a074
+
+Count = 111
+Adata = 7e3d7b3eada988668f3784
+Payload = eab7d5dbd91d4cbbac8d79fadd70b5dcb3baadac5cb713a3
+CT = 4e2fc3c34ec3cd2036f81812106bc86a577f908ca0664dadacb1d1c9231d2c22ecfeed622792dfd0
+
+Count = 112
+Adata = 78b107b29c4878ff18f749
+Payload = 3c6ae2e2578875a1f5611582528e058aece2ddc33a4dde3d
+CT = 98f2f4fac056f43a6f14746a9f95783c0827e0e3c69c8033fffe60299768f048e7098033cde046b0
+
+Count = 113
+Adata = d293908bb516c5f3a411b9
+Payload = d7a46e726ed43f1580eb52141a93390982cc809dc833e3f0
+CT = 733c786af90abe8e1a9e33fcd78844bf6609bdbd34e2bdfe4ee6ebc0d90a0de05b428495c93e1801
+
+Count = 114
+Adata = 33ef208faad4d2948c9e67
+Payload = b1fe5d9d34157193fc0608cd8ecb872e17720f5f6814a466
+CT = 15664b85a3cbf0086673692543d0fa98f3b7327f94c5fa687e7e64cc0fcd6a92c79ceb6ce2abd8ee
+
+Count = 115
+Adata = b7f7ed9ccac3c2b4fbfee0
+Payload = de6bb539fb7a9c87414f62a7cf25a4cfca176509e991af41
+CT = 7af3a3216ca41d1cdb3a034f023ed9792ed258291540f14fb02b53bc779e0976b634b0d1b88fc0a9
+
+Count = 116
+Adata = a6e287383927f76e4927af
+Payload = 8719d20c20c8959068b8adcd65e6f6bc7b3693828f0735a0
+CT = 2381c414b716140bf2cdcc25a8fd8b0a9ff3aea273d66bae3c37fa936243b393f07fcccb0fc13e41
+
+Count = 117
+Adata = 70828be6dd93954f4e7b6b
+Payload = 30b39426831f61c8ba5f2ef5b71f0c4b2f916e3b5a578110
+CT = 942b823e14c1e053202a4f1d7a0471fdcb54531ba686df1e0d7534a489e6d242966ebea4455f8f79
+
+Count = 118
+Adata = 506015fc2831df293f4da0
+Payload = 818d5d810f678629f078723f5c6c3657271077533bfb7c29
+CT = 25154b9998b907b26a0d13d791774be1c3d54a73c72a2227ccbf64f04e95b180d09e843847d22104
+
+Count = 119
+Adata = e9394b0245b379e68e3dea
+Payload = f0613205a7a0822849df9e8a3cf6caf281f3adfa966c5507
+CT = 54f9241d307e03b3d3aaff62f1edb744653690da6abd0b0927b546ef8cd717073832584fb25a0645
+
+[Alen = 12]
+
+Key = f6bb5d59b0fa9de0828b115303bf94aa
+Nonce = 05358f33e1fc6a53ab5a5c98ce
+
+Count = 120
+Adata = 040b25771239cc2a39446e3c
+Payload = 011fc50329bfd63a85ebd4f7693363602f1a4147371270b7
+CT = 4432d7eb42980734d34f19c50cf8abf71ac1b19ed75a727854e5d050a405f755047d09cb0f49546a
+
+Count = 121
+Adata = 50a1d37fa2f3462bd304631b
+Payload = c90e40540d372ab1eb00ea5d5b8de5bf7c94ce4e376d6949
+CT = 8c2352bc6610fbbfbda4276f3e462d28494f3e97d7256b862abee8547ee3f24cfa677468ecc1d121
+
+Count = 122
+Adata = ac3bb872a41df35e415d2b0c
+Payload = 9e7be78c0ab9e6a4c6c257e77c63681bea35d951f168b0c5
+CT = db56f564619e37aa90669ad519a8a08cdfee29881120b20a61cef865ce4080e7c7abfc43f62c03a3
+
+Count = 123
+Adata = e3106ae6456153dd922640a1
+Payload = 00df0c5a5d3eceb2bd293066529799544f846672a9a1d31b
+CT = 45f21eb236191fbceb8dfd54375c51c37a5f96ab49e9d1d4e1d19c321a1e0852adba939b447220ab
+
+Count = 124
+Adata = 297b4498bf5427e6341aa927
+Payload = 14967a0476dbaea03b07fa8d40d344eabaf479be2443243a
+CT = 51bb68ec1dfc7fae6da337bf25188c7d8f2f8967c40b26f579ea5fb65018abdcde1a39f6859ecb56
+
+Count = 125
+Adata = 5de60dc0e3b5bda0b33a9520
+Payload = 2da3716d76d10b6766a1f9cbf9f420316fd5f396e7b9a2ba
+CT = 688e63851df6da69300534f99c3fe8a65a0e034f07f1a075c2629ff871ee15745fd8c1ddbdae4c29
+
+Count = 126
+Adata = 1c9b8541943ad50b4243c179
+Payload = 8c1b3ba18d1f5cff74a457aadd6b3e7d093d06ad2622e6a0
+CT = c9362949e6388df122009a98b8a0f6ea3ce6f674c66ae46f04e198ad16ad1106d3ba6172f4a13a8f
+
+Count = 127
+Adata = 51e926d2542ac8faef61465a
+Payload = 88936e97db070c0ec2aa58d1c6f5b34df3d32ddf7db34a8b
+CT = cdbe7c7fb020dd00940e95e3a33e7bdac608dd069dfb484475981131e3934ec6d41e00d502729799
+
+Count = 128
+Adata = ebefbac97b363e6f32526aac
+Payload = c20742e4b410c5b661da373a905fb0ed55b20e0e879eff5c
+CT = 872a500cdf3714b8377efa08f594787a6069fed767d6fd93e2c005b5bebe07ff578b1b4bc51971cd
+
+Count = 129
+Adata = 1ef059ac7d648e9e32d9b1f2
+Payload = 65c55ca21a89a8325365bf2be861d700559de2eabb41b37f
+CT = 20e84e4a71ae793c05c172198daa1f97604612335b09b1b021a25f15b5b4229a872a9199972c85b3
+
+[Alen = 13]
+
+Key = d1da2e961e78063af8de41865b226873
+Nonce = 03739f5474857006340cce554d
+
+Count = 130
+Adata = e3afd091d2b588465872a6300f
+Payload = 8e5fa1a6662a8378cda15697e926841594f2f394fa5a34ab
+CT = ca0d95e3ff186ad6b88d45fc4079e6b7b4a615e7e8dd5f4742d522cc9dc19c47a4fa0b1528069cf8
+
+Count = 131
+Adata = ce3186bb737753b59ee76b748c
+Payload = 311ebc5ff2f625944562ea699b2690df3e6e64a17c62bd3a
+CT = 754c881a6bc4cc3a304ef9023279f27d1e3a82d26ee5d6d659b26510b8f25610799e011d7c850ecd
+
+Count = 132
+Adata = bfd636989dfbcb0edc9f014cc8
+Payload = c96cee5ba7b799f16254a17b1870cdb85fe0ef3f42110c13
+CT = 8d3eda1e3e85705f1778b210b12faf1a7fb4094c509667ff52942aa0d39649f3d9ed535bebc2b603
+
+Count = 133
+Adata = 4812b092aa59d57451bfd812c3
+Payload = 13b1b4404dc5735655139414fcbd02c5327ae9fb148bd324
+CT = 57e38005d4f79af8203f877f55e26067122e0f88060cb8c8c1e61efb9c1d84ddac2d24f43531f569
+
+Count = 134
+Adata = f6ef9ac4f4c9ce1e4309c64fa8
+Payload = 6c5b59319e2710f5d63407f85b424d1860425ef8ce0cfe53
+CT = 28096d740715f95ba3181493f21d2fba4016b88bdc8b95bf13350de0ef34df12fb945b0ae0a0d9bd
+
+Count = 135
+Adata = 9bf12168bb3d79ebd25262f2b4
+Payload = 968e1d78008da78611e82985c4028e86770858cfe61c3723
+CT = d2dc293d99bf4e2864c43aee6d5dec24575cbebcf49b5ccfa0734563638598d8c4bf1fcd94009925
+
+Count = 136
+Adata = 7d870d7e52d3053c65eefad477
+Payload = 6a1306d911434cc7400d2f9a95e36aedceddca2b3d583f51
+CT = 2e41329c8871a56935213cf13cbc084fee892c582fdf54bda1f5fc53b08aca82bccfba6fbcb27e69
+
+Count = 137
+Adata = e95099f04371e445e5eaa1d80e
+Payload = b9197eb50c8168d16b8a12bd261d553ffcc521d979b26fee
+CT = fd4b4af095b3817f1ea601d68f42379ddc91c7aa6b3504027d1a922953facbd630d7fea6b63594ec
+
+Count = 138
+Adata = 3e80eb03db6545204ef4241ad6
+Payload = 95f59e36eac8eb3b51709d635b07fa2da0976ea20e25807f
+CT = d1a7aa7373fa0295245c8e08f258988f80c388d11ca2eb9383fa000d10078256b71249d9d1f1846c
+
+Count = 139
+Adata = 9748798c0f3cc766795c8ce0e4
+Payload = a48db9add9ecdeb49e51d3ab7bb2075202ed2aa50c0195b1
+CT = e0df8de840de371aeb7dc0c0d2ed65f022b9ccd61e86fe5d2773c2f55b752477c489facee812c614
+
+[Alen = 14]
+
+Key = 1eee667267ef10b03624cf9c341e3f75
+Nonce = 0630a3eae27e505c61c56e6560
+
+Count = 140
+Adata = d24651ef0561282d3e20e834960c
+Payload = 798e31cce0a83702a95171fb1162a17b9ce00ec3592ce262
+CT = f3c3e52f1a1ff528a8d3783ee4e75f114e3e6416334815d2d9236d5c5c9319092078411b72c51ba8
+
+Count = 141
+Adata = c527d309ab29ee91c5fc53117e71
+Payload = d79cd4c8891ec4ce2c51136712d23b32266b2b73768aeb1e
+CT = 5dd1002b73a906e42dd31aa2e757c558f4b541a61cee1caed8ad2a48cb734e3f93e602c15c7c775e
+
+Count = 142
+Adata = a93dfc3944514ddfc5acdd89fab7
+Payload = d7fa81c949f1f2af29dbd56529b307e3b348e996d0936455
+CT = 5db7552ab34630852859dca0dc36f98961968343baf793e5f34b297f3f106a9cdae255f7634fbd0f
+
+Count = 143
+Adata = e502abe21c7b22120693a08ef3e6
+Payload = 6330caaeddf0473d564d175b9408c6f12e6d3cd4ee2c423f
+CT = e97d1e4d2747851757cf1e9e618d389bfcb356018448b58f4f5d9c3dbfe3e2fe03a002e55039ebe6
+
+Count = 144
+Adata = a49b34dfad43333fb2ffd701a2d6
+Payload = 45671482c390e65f75de15ca91b93596e9bf3d6fc9178bcb
+CT = cf2ac06139272475745c1c0f643ccbfc3b6157baa3737c7b6f7bb0749c99d75740f2d193fef36c60
+
+Count = 145
+Adata = 9e4d8aa3dbdc4d4b4b8d72734f52
+Payload = c8f34bea8bdc403a48d8ed9268429141cd03c29558050ef4
+CT = 42be9f09716b8210495ae4579dc76f2b1fdda8403261f944ceec82fc674da9efa6926e8641729ed8
+
+Count = 146
+Adata = 052327ad59cc791259817fd0ed96
+Payload = d8d1c57b16c23894b66023c29f8648ce4a6074647e1f5f69
+CT = 529c1198ec75fabeb7e22a076a03b6a498be1eb1147ba8d92ff19e93f60c8f3a511300fddc38ee59
+
+Count = 147
+Adata = 14bc3c44c001ccb261a2a0526523
+Payload = 71c14a7031033db15bfe23b75fed9daf8886dd11392a0b78
+CT = fb8c9e93cbb4ff9b5a7c2a72aa6863c55a58b7c4534efcc87fa00fb244eda0d77cf6c05c8fd590af
+
+Count = 148
+Adata = 3477384c396a9e9efb3e169722cb
+Payload = afa795f836763a1210bb36fef167864f73ba3b6abc593537
+CT = 25ea411bccc1f83811393f3b04e27825a16451bfd63dc287bae19612657c87d3bb73cfb8cee7c8a8
+
+Count = 149
+Adata = 0c3b9a6924ad506038cb2d6590c9
+Payload = ca4a186f116a179579e3d327aec3f5be358bc7094f853bc3
+CT = 4007cc8cebddd5bf7861dae25b460bd4e755addc25e1cc733d9713d2e916c23ac3039de34c295fc4
+
+[Alen = 15]
+
+Key = dbbd26f5d9e970e4e384b2273961be5a
+Nonce = 0b1eabe504ef4822542e397fec
+
+Count = 150
+Adata = 477937301c83ba02d50760b603e0ea
+Payload = 553714e17a208a2eceb847a4a2d95088388b1ac8d8ca43e0
+CT = 1c80213268bad5402c4dc9b5d836ab7499810d0d8a974716df9a0e986ab2890736423bb3772cec3e
+
+Count = 151
+Adata = c91eb5a07ff19c044023e5cf339203
+Payload = c94d0b9e728413c58202cb3f6b82dba7aa9e3ca0a72c40c7
+CT = 80fa3e4d601e4cab60f7452e116d205b0b942b65f571443139f907a92cb01215e3cda84ae13af48b
+
+Count = 152
+Adata = 38c71a8e9b279c605c7f0418a0afc1
+Payload = b4e8c4fd5ad98a1be8b5a11677c57ca1c1694e3528092aa9
+CT = fd5ff12e4843d5750a402f070d2a875d606359f07a542e5f3dbd8dbf7485106cdf9ea0e7088a5650
+
+Count = 153
+Adata = f2c76ef617fa2bfc8a4d6bcbb15fe8
+Payload = 578ce26cdb5ba2e8798e23588e5cd04ef782820b80e49a42
+CT = 1e3bd7bfc9c1fd869b7bad49f4b32bb2568895ced2b99eb4853fde6f4dca88ff11bbce20ed9e5012
+
+Count = 154
+Adata = 36004342dd74e7966692a848b2c11e
+Payload = 78733c635d4d4e8b0729732f1e174dfcec4e020a7ac3870d
+CT = 31c409b04fd711e5e5dcfd3e64f8b6004d4415cf289e83fbd94e979108fcecbd32f6bdf72f0ccb4d
+
+Count = 155
+Adata = db92bc3fe5d4141aeb39baea6f114c
+Payload = c7aafe7760945e45703c1e19f1032dfd56ddc216c3b03826
+CT = 8e1dcba4720e012b92c990088becd601f7d7d5d391ed3cd0229c8f9d4e39fc16cbdb44236ef125c7
+
+Count = 156
+Adata = 34ec2d5b6f0d950509b47a0637d74c
+Payload = 2345e36a63be0b78df95e60907c78da0e48e61e70685a1f3
+CT = 6af2d6b9712454163d6068187d28765c4584762254d8a5051c9ab7cb0a779c3fa78c9ee12603802b
+
+Count = 157
+Adata = 6ab658d177c2dd87c9b8787cd70182
+Payload = b0725f735543eb0c0ec88ae69b140f5787d28ef4a2e36d57
+CT = f9c56aa047d9b462ec3d04f7e1fbf4ab26d89931f0be69a1648c6307ec5ea304045a7cdc93f36b9d
+
+Count = 158
+Adata = 483f135c61250fa610b4d14b99ecf0
+Payload = 315a947bf5291278d446d332ee5ca0def7655d5c957a8fb4
+CT = 78eda1a8e7b34d1636b35d2394b35b22566f4a99c7278b42364ff3b1ad915347b1c7f062b10d3da4
+
+Count = 159
+Adata = bb022aed60819ef84ae83ce27db9d0
+Payload = f78d00755bcb45e6822121fe7cb03c8e627c9f548ccd7e7c
+CT = be3a35a649511a8860d4afef065fc772c3768891de907a8a7569808dab58d42181543b2e2d05992c
+
+[Alen = 16]
+
+Key = 10a7720f2e18f739c26924925af6b670
+Nonce = 8c4e7813ab9bce9dafee01c628
+
+Count = 160
+Adata = a209941fab710fda38d11c68b13d930f
+Payload = e59782a9aea45f467b90e51a0fdf166baba05663def2d8b6
+CT = e357b1ccdaca6f3506dc45279c2e4c59f5307a5fd6a99cd72341ea8c0785569973f90ee9ee645acc
+
+Count = 161
+Adata = 2e2f6f9755a492ee54df77b2ecab9808
+Payload = 042a072f6ebf11f79fcb4f5a64f7946dc837d9d2355785ea
+CT = 02ea344a1ad12184e287ef67f706ce5f96a7f5ee3d0cc18b703eb81224cdb1fd2e1cfb2fbfe1e402
+
+Count = 162
+Adata = 99e98c9983c85d1f49ae43ebad67a652
+Payload = 5db6bda27910e7b8b61ac476c6532570b71b3932bd6a698c
+CT = 5b768ec70d7ed7cbcb56644b55a27f42e98b150eb5312ded64c4aea7f17f18f068897557c93ffaaa
+
+Count = 163
+Adata = 37a837d73fa15793f6f823fb99c2ea74
+Payload = 8cac261a461c3ddd2642b8e4e5c3389e491fcb2ff8356412
+CT = 8a6c157f32720dae5b0e18d9763262ac178fe713f06e20736f3b2e70e6e2dc7acc74a823a7f49722
+
+Count = 164
+Adata = 11119a4e779cfb64c736d425e4ff554d
+Payload = 3429f9b088b501d7944c462694d0799568282e7ce07d3e61
+CT = 32e9cad5fcdb31a4e900e61b072123a736b80240e8267a000dc3b57096f0df1d4eb5328c416921bc
+
+Count = 165
+Adata = 962d7d4305f23d1692747b504960c0a4
+Payload = a46ae4c71d4c9eb72fabfa76b8074aa02e07653eca10eef5
+CT = a2aad7a26922aec452e75a4b2bf6109270974902c24baa94f62ed804e9f2ac0f7001d0f35ea9f3c1
+
+Count = 166
+Adata = bbb1fdfefcf3657ba6cd93ff341a04e1
+Payload = 92f5e3083f57c77ac9553a2024a66489698bd2261f05d415
+CT = 9435d06d4b39f709b4199a1db7573ebb371bfe1a175e9074907dcd7ac1e0bb248d46c3036c39fb02
+
+Count = 167
+Adata = 74be126f7c596642dafa8fe3da904e69
+Payload = 41ecc3aae5cfebfad7921a47a0684601ffe73816380f8716
+CT = 472cf0cf91a1db89aadeba7a33991c33a177142a3054c37787cbb80fd21127feca7e76fd6947d5b7
+
+Count = 168
+Adata = d72cc521c90a468522af8966c24799f3
+Payload = 8850bdda4bd0271e333db344a47b837183eb48269c3dc0b6
+CT = 8e908ebf3fbe176d4e711379378ad943dd7b641a946684d7cdb5d1243b6e73b8e380d8ca041647db
+
+Count = 169
+Adata = 28f427fba8d0bb0380bbe5072ccfa519
+Payload = fdd3ca2f193f93f5a349b50357d26748b767cde6ab5cbfe7
+CT = fb13f94a6d51a386de05153ec4233d7ae9f7e1daa307fb864a0ae8604b103f882f17db893ed5c576
+
+[Alen = 17]
+
+Key = 6bffab1f4f4c1ff66b4a669b515b2f8d
+Nonce = ddb34d5e0140fb96d690e1a2b7
+
+Count = 170
+Adata = 5cbba9ea778e01af00afb2a934f28c7211
+Payload = d91b12e8655dd92b1332fc1d71c391c96a17111562d90ba3
+CT = d302e5b2d5d90433186b804cd7717e2db2f22cdc34fb2942ab30780a2c4f12af8f35350d65284c59
+
+Count = 171
+Adata = 1583138aa307401dddc40804ac0f414d33
+Payload = eeafb08d4a4819f5682a01d44371e34cc5729079e74e73a6
+CT = e4b647d7faccc4ed63737d85e5c30ca81d97adb0b16c514746577901b7f6feb88b8e2b8562f9cb5f
+
+Count = 172
+Adata = 23931c258c84086500c6a3b6eda457e6b5
+Payload = b8737d5bbfc976c2d8d9786148dea664dd83cee98df537b5
+CT = b26a8a010f4dabdad3800430ee6c49800566f320dbd715548735a59390ba7a892741694f3a89b0bf
+
+Count = 173
+Adata = e12f98507d6514c3b551d240595346bc9e
+Payload = eb021b63c61c0b194bd44870608d7ef0b932b6104412d7a9
+CT = e11bec397698d601408d3421c63f911461d78bd91230f548f4f81ed18cc1820375a7bec2318cde1e
+
+Count = 174
+Adata = e14b87d49d231c0199eec627fd7f1b5332
+Payload = 93b42584c4956078359d77e80aef52281b9228a1f66aa36b
+CT = 99add2de7411bd603ec40bb9ac5dbdccc3771568a048818a187b430caa60d98dc3e2aeefe6249b44
+
+Count = 175
+Adata = ca095aec96a8b093e62b10f0950ce35ce7
+Payload = 6a788d8238c7b313b8eba27b210a71c36819d719115b9b76
+CT = 60617ad888436e0bb3b2de2a87b89e27b0fcead04779b9970a77372b727408e1bf5a70790b9eba3a
+
+Count = 176
+Adata = d1cac02b34ad33c0e77a5bda2c3baf5e5d
+Payload = 3bc1ee54d0094603dfc68eee118e547d031fb36e464e776d
+CT = 31d8190e608d9b1bd49ff2bfb73cbb99dbfa8ea7106c558cdc1f5cb4d4fa2204e82eedcb3784443d
+
+Count = 177
+Adata = 065c06b49a49898e20bb679e35edbb1f76
+Payload = 8a12adb8b746216baa8a418725e608e4377f13816a036a10
+CT = 800b5ae207c2fc73a1d33dd68354e700ef9a2e483c2148f12413f9496592a75a1d6e42ee3a258607
+
+Count = 178
+Adata = 98a42d7a0c5917deaf3b4de3f0cbe0a191
+Payload = 30a226c07401d0ae24c73d682e3a6e7e377ec1613bafba17
+CT = 3abbd19ac4850db62f9e41398888819aef9bfca86d8d98f6b571a3150887df1ac5f813676b2eb24f
+
+Count = 179
+Adata = e245a7528931841b52a5f59d861d98d7b7
+Payload = 3d17bcdf30445ebd8a9b6aa2fe11d443c1161bb1ee69ced0
+CT = 370e4b8580c083a581c216f358a33ba719f32678b84bec3131aa5e4657c92e31c69ab18d447d3578
+
+[Alen = 18]
+
+Key = ae6136df9ab43631ef143515dacedbe7
+Nonce = c5c445792208a50c8e93d64aa3
+
+Count = 180
+Adata = e04006b68c83a5dd4ceac3cde238e48895ae
+Payload = 6a493c5ef3769ccc4101dbb2eb36e1e5bbc577a057ce0731
+CT = c7584c0203c2535c5702c6ae93b7cbfb066f4a055c627a180d6d676d11fce907b5c93fa1ed7bff2b
+
+Count = 181
+Adata = 5da64e368f45153ea5b7ddca966b6c5b699a
+Payload = 15e0c672c6764f3699d9d3e7120f8ce5daab166f08fdd074
+CT = b8f1b62e36c280a68fdacefb6a8ea6fb67012bca0351ad5d2cd45f211b1a1364c91ad07959bf0ee5
+
+Count = 182
+Adata = 1b315d024bb5d1e03d7510e61f37d8adb10a
+Payload = de907d58cd8f5a72acaa1d329b937dfbbfed65a4e45eb029
+CT = 73810d043d3b95e2baa9002ee31257e502475801eff2cd0018f021a98b2edfb0b7500363099c2a1a
+
+Count = 183
+Adata = 8691ba4f9232ca86f919fe72ddb39c91d707
+Payload = c7fa314d27be79f9d3e2d1e188c1785b0c970f91b8ed4290
+CT = 6aeb4111d70ab669c5e1ccfdf0405245b13d3234b3413fb92ac9aeb018c48f3902276ac759710b6d
+
+Count = 184
+Adata = ff0baf1cbb5884a9290ea7b5ee49915efb4b
+Payload = 33b05b20f3c849fac091a5028cbfa0bc9a1c32514136fee3
+CT = 9ea12b7c037c866ad692b81ef43e8aa227b60ff44a9a83ca7dac49f606dadb9f7034e0a1860d519b
+
+Count = 185
+Adata = 2d118cda20700bc2748ea1753fbca6f74933
+Payload = f43832e420e2eccd5d80502bea2ba1804e17d4433318fc86
+CT = 592942b8d056235d4b834d3792aa8b9ef3bde9e638b481af623ccbab19c1442806e21c5a820945da
+
+Count = 186
+Adata = 0c7a5fd2010c999a8a0efa81f89ff5bfefe0
+Payload = ceb203c842a962183f22e602644fc66e4290b3d5be445fb4
+CT = 63a37394b21dad882921fb1e1cceec70ff3a8e70b5e8229ddbcd18947ac1800856c9c92eb0388c70
+
+Count = 187
+Adata = 73fdddb9e0a64f5671fd70c4ea8443507789
+Payload = d6015b6bd5f5eabb2a649129f8f727c06a3ad59499f21caf
+CT = 7b102b372541252b3c678c3580760dded790e831925e618639c29ea73b0c5aa130d8b14f7b9926a9
+
+Count = 188
+Adata = 82c4484e3a6e18b6bbfd78b69b00c40b30c5
+Payload = c288b810fb533441bd549d02c0b28d5b834293683eaacda2
+CT = 6f99c84c0be7fbd1ab57801eb833a7453ee8aecd3506b08bf0a0f148ae138c2ea02538c8fd7ac76c
+
+Count = 189
+Adata = 267d8385b14721eded743cffd69e4d595f7e
+Payload = 667cc47d13c34923be2441300066a6c150b24d66c947ca7b
+CT = cb6db421e37786b3a8275c2c78e78cdfed1870c3c2ebb75285eb537e7583f04e040a0ddc41106213
+
+[Alen = 19]
+
+Key = f1908328edf2996ebfc9655472ca5ad0
+Nonce = 4c693364546930b6c5250e2699
+
+Count = 190
+Adata = 4a3634e5028df97fbe00eb016e8ea4f1918faa
+Payload = eede01b08f9a303cdf14c99d7a45732972c6eff2a1db06eb
+CT = 90c850790b0b380f5aeb2488fdf43c9d5ef1759861e86f6e52570e769629dcc2e568737ba53a1195
+
+Count = 191
+Adata = 041b93e3fc059fa44aa755e88df277b9b6e499
+Payload = e61ca7310172eec16745a73e34516f65844eecd0dbc5566a
+CT = 980af6f885e3e6f2e2ba4a2bb3e020d1a87976ba1bf63feff1d82ec19a2e3ec43bbdb34e10999d90
+
+Count = 192
+Adata = d1be393376cb5d23cf8139da0fd92f3d520ae9
+Payload = ea887edee68ad5fa6bae928aa480dda898037f820700ec52
+CT = 949e2f17621bddc9ee517f9f2331921cb434e5e8c73385d7f2abb0ce4de9eeb5e8af9cdf3391d3cc
+
+Count = 193
+Adata = f3e551b34d2db1286a9f41085e4dda95ec3f75
+Payload = 71fe1ba5d299495d2a56039c64032ec6263d437f55e3f5be
+CT = 0fe84a6c5608416eafa9ee89e3b261720a0ad91595d09c3b239c73b01ba49a8498b5ff4833851069
+
+Count = 194
+Adata = a69ddc66e63a3415f21009d53adcf26bc1a9a5
+Payload = bd04d854216740a6ceb9827cbddd83761d19feb2a21d78ef
+CT = c312899da5f648954b466f693a6cccc2312e64d8622e116a2248dacd3903c26a2dc5ae649566ad67
+
+Count = 195
+Adata = 5735d6f5882d8f27155eb4cc285a65138ad64a
+Payload = 33b44873a7a1e5b0fdbb7e7347623e4fa1ccd937feb26fda
+CT = 4da219ba2330ed8378449366c0d371fb8dfb435d3e81065fd4156cf7d97b2e744351b6960a807cf8
+
+Count = 196
+Adata = 5d94ed976ab2063512690ae704c3b115519742
+Payload = d3909d577a4e89642227cc6fc146b61bc18392175e342898
+CT = ad86cc9efedf8157a7d8217a46f7f9afedb4087d9e07411d5a50086b6711ac72533c3c5717f6892c
+
+Count = 197
+Adata = db20b384620ab8691aed2fed14a745188d94c0
+Payload = ba0716355fffb8ef947d2a15eb58375a1ff1084c56699029
+CT = c41147fcdb6eb0dc1182c7006ce978ee33c69226965af9ac54fb74ecb9a5163b01b9dbf97ff2f999
+
+Count = 198
+Adata = 94897cdd04e0c8480b2ef7b5201dda37558ba9
+Payload = 5f4b4f97b6aa48adb3336c451aac377fde4adf47897fd9cc
+CT = 215d1e5e323b409e36cc81509d1d78cbf27d452d494cb049d2a81702f665ff5c54f586defd268c94
+
+Count = 199
+Adata = 95c44e1e5ad256b3ce1cc1d87137a1e09f1fd4
+Payload = 598e91d39c414496fd5e69f2cf80826b4e7d59ba28e0a0d8
+CT = 2798c01a18d04ca578a184e74831cddf624ac3d0e8d3c95dfa641889723e163825ab65727e8a5343
+
+[Alen = 20]
+
+Key = 61cb8eb792e95d099a1455fb789d8d16
+Nonce = 1f37b3e59137f2a60dc09d16ac
+
+Count = 200
+Adata = 09db3efac9473f713da630ae92c2c8604c61c51e
+Payload = 6ad541695a37c32d73ff6d5f870abd5b0f362a8968c4fce0
+CT = e65fcc975865c1499b088b58ba163283085d8ca68dc3b235d89756e5d78753ef22c012ae34b39a20
+
+Count = 201
+Adata = b6d07035aed9c141c713cc3bce60f7ba8ac2545f
+Payload = 9cce4c82fe9d38ef64ac8abdf0619f201a25ce6903675627
+CT = 1044c17cfccf3a8b8c5b6cbacd7d10f81d4e6846e66018f2fc78ebae9c143a7283b0641e1f83f5a0
+
+Count = 202
+Adata = 80a5ab693378af29cd5a33555cb3579f9ae540aa
+Payload = 7295a7aed3e987baef19ad68c33ba5a5dcbff27875ff5236
+CT = fe1f2a50d1bb85de07ee4b6ffe272a7ddbd4545790f81ce35a7e44348d2b3085348f787128a4e96a
+
+Count = 203
+Adata = 220817144a15a0a654fc1beaabce60270aa72df8
+Payload = eb21fe20fc4f92452b261eac0d7b70016f7469afdff7a3f5
+CT = 67ab73defe1d9021c3d1f8ab3067ffd9681fcf803af0ed2024dfc096cd8a09d2d81f6146fb54082a
+
+Count = 204
+Adata = 5a2423c2ff2d642c80ac1ca27dd779321f3e9c01
+Payload = 23bf80f51dfd83f63986910e69d54a315c2bfb43f432b7de
+CT = af350d0b1faf8192d171770954c9c5e95b405d6c1135f90b5da82204f4dd8f535cb2fec2f133d882
+
+Count = 205
+Adata = f2c76ef617fa2bfc8a4d6bcbb15fe88436fdc216
+Payload = fc3a50cc8a68778327923ea697f5388da4c814381e29c5e4
+CT = 70b0dd32883a75e7cf65d8a1aae9b755a3a3b217fb2e8b31108630135498ba409f4b6c8caee8a85b
+
+Count = 206
+Adata = b40c8c1d2cee490653105ca2443356cdb63e4fd0
+Payload = 465e41c69928d08c33e063ea119595a04d0de6bffd17bba5
+CT = cad4cc389b7ad2e8db1785ed2c891a784a6640901810f570f89c515837d129ba41f9c24b0229ddcf
+
+Count = 207
+Adata = 6ebfa1e8f80b3cdb1bedf2e3c7e74f30f55c38e1
+Payload = 3f98ee3922f8f1086e3135ae66c5465426b13c8794954880
+CT = b31263c720aaf36c86c6d3a95bd9c98c21da9aa871920655a352fa6b9c4e40733ddcd3fcdaf9ae63
+
+Count = 208
+Adata = 6d0159861031c1a5f01aab35927fe2ab28154d19
+Payload = 5b43067a5ab3a9f9e633fdc084c44ffa7f11edd12ea5873d
+CT = d7c98b8458e1ab9d0ec41bc7b9d8c022787a4bfecba2c9e82c1aa13f062c0f1f5008e27ff2191942
+
+Count = 209
+Adata = 15e5ade017b30ab41878a2747e93aa91c61c2908
+Payload = e40b7e9e46e339e64891526e730b3bf6562fa37acefce307
+CT = 6881f36044b13b82a066b4694e17b42e514405552bfbadd2e149dd02bc7face0c4dfe4e501c2ac2a
+
+[Alen = 21]
+
+Key = be1ed49e2cb0caf6b6a0940c58453b93
+Nonce = b78ad129457681fa7346435b97
+
+Count = 210
+Adata = 161d92c7df1ebb0924719e066e08b95eb4914a5eda
+Payload = a9eec383f63892521e4616fcbadc5485942ffaf4669c43a7
+CT = 949be340720c4fdc4adc05cb777dd81a2549628d33fba07e62d2b338a7b34ebd9d85c244c952d681
+
+Count = 211
+Adata = 6b1d94bc0c6e45fc905c509ea667853e4b2c5a8848
+Payload = 7b44a093162bfc8b4d65f1031d890a6b08a3705b142c0c26
+CT = 46318050921f210519ffe234d02886f4b9c5e822414befff8a4defafeb3d61dad8c007b68d8fb9b3
+
+Count = 212
+Adata = 868dd3e241f60f097a7a2fe571307ee5eb961218ca
+Payload = 28c4d6de3e2ce51b849b135d9cfd3084f0e3155447cad9d5
+CT = 15b1f61dba183895d001006a515cbc1b41858d2d12ad3a0c57cbab553b511d68a4f41db211d0a2fc
+
+Count = 213
+Adata = 3776f37fbf8803bdfd246ffaff2e59658a6c3f0ebb
+Payload = 16d345606a315ad2406abbcb43cd8cabe948107ba6d17a72
+CT = 2ba665a3ee05875c14f0a8fc8e6c0034582e8802f3b699ab0290fd7dbf0afa3e597274e3c9fe170b
+
+Count = 214
+Adata = d0f2769eba9b8e618f00eed6b34c261c59322a253b
+Payload = fcbbcdd9599a86e7c8ccb9347065789a9728ca1220fa51ca
+CT = c1ceed1addae5b699c56aa03bdc4f405264e526b759db2139c7dec3960e6aba3174d793b4e08f449
+
+Count = 215
+Adata = 2be180892faed0bb75887668d187807666d3c66c68
+Payload = 8d145b1f792cc31a2e5b86216609bb018e7aea3012ff70a5
+CT = b0617bdcfd181e947ac19516aba8379e3f1c72494798937c7057b9e2d844e86ee5c3ecfb3270804e
+
+Count = 216
+Adata = 52859849a5b7c1d432c3bfb35271cd8141db2ec774
+Payload = 741db990b43ef34993c33d1c4953b67b128b9299dfe86d74
+CT = 49689953300a2ec7c7592e2b84f23ae4a3ed0ae08a8f8ead1150fa899152eef7a30ae0f20986818e
+
+Count = 217
+Adata = aa192759625f4e42d1d1fa73dc0f62199142155615
+Payload = 51dca5c0f8e5d49596f32d3eb87437bcae866640310ce1e3
+CT = 6ca985037cd1091bc2693e0975d5bb231fe0fe39646b023aba7ff9203608089558698ec29472dda7
+
+Count = 218
+Adata = 6de564226884188ec7bea3894535a875cff2a42fdb
+Payload = dfaa7aa8b28626210d5c24e2ddfe516189be05aabe26f3b2
+CT = e2df5a6b36b2fbaf59c637d5105fddfe38d89dd3eb41106b85bd0a5074ef852575baf5f12c22663e
+
+Count = 219
+Adata = f245f2ee23755df863dee55d7ef0c3c09a0b6f0b0c
+Payload = eedf00aab5edefdd6549d37ed44358e11c588c24f141dc57
+CT = d3aa206931d9325331d3c04919e2d47ead3e145da4263f8e9eb617436bae012331daf020fce24e47
+
+[Alen = 22]
+
+Key = 34ab6fd7f54a2e0276fcb7cf1e203aba
+Nonce = 6091afb62c1a8eed4da5624dd7
+
+Count = 220
+Adata = 1ab5cc3d7b01dc74e6cf838bb565fea3187d33d552a2
+Payload = 8d164f598ea141082b1069776fccd87baf6a2563cbdbc9d1
+CT = 0d30ab07153b5153637969e6bd3539448c541e42b3d432fd7ef14622a9b621d1721b944c60f7fd67
+
+Count = 221
+Adata = 1f1ac4674b272bc7a4ee9f4eae33e969b16fa90a69ba
+Payload = 14e99a2ef0de650adbd785c692342cdb765e6d20d5fca09a
+CT = 94cf7e706b44755193be855740cdcde455605601adf35bb6dfa4ec2c92671c64ee07946527be67f0
+
+Count = 222
+Adata = 43ee77f12ea42e82a02275a68aa95cbd1bb440442bcf
+Payload = 383242c709fe5f2ce782bf8c83b645d171f2bd238abc655d
+CT = b814a69992644f77afebbf1d514fa4ee52cc8602f2b39e71173572fbf3d9495760aae4347397b110
+
+Count = 223
+Adata = ae2ff288199be25bf640811541394ad7e1dd0dc0d24d
+Payload = 9c16a5b638c35c97c5c981c1b8dbcba11aec30e72e45a936
+CT = 1c3041e8a3594ccc8da081506a222a9e39d20bc6564a521a4d2327956e030b9df753e063b5b71201
+
+Count = 224
+Adata = 4ccfb4281852b5ca7e787723d689384a68ff9437db31
+Payload = ec9d8edff25645520801b6e8d14a2fc3b193db70d5e5e878
+CT = 6cbb6a8169cc55094068b67903b3cefc92ade051adea1354e4dac0c9130f5641afd035dd884b6271
+
+Count = 225
+Adata = d3a2fffc798fd9cc2f409471faf18caa2ff3dcf4e652
+Payload = 0db33eda4188a9165147e24e40f79fee1985eb68d5162728
+CT = 8d95da84da12b94d192ee2df920e7ed13abbd049ad19dc0448807dd50a9cf41651083c49c7493ceb
+
+Count = 226
+Adata = 7b5121aa4d1e314f209ffe3e92cd26ee4f74d91e27f2
+Payload = e0d3ea4308376423c4322503f56e427a64e2e6d8b4f5e668
+CT = 60f50e1d93ad74788c5b25922797a34547dcddf9ccfa1d448ea0da53046733f522ded40a09c6d7a6
+
+Count = 227
+Adata = 6e12c112720ef346bbbe7d1c19483721b1c52c438dad
+Payload = 491f2bca585d6b5fdf38d18890e4d1bc923fe26930b3d2f1
+CT = c939cf94c3c77b049751d119421d3083b101d94848bc29dd345cb5a968f39654b994686699d532c2
+
+Count = 228
+Adata = 20433402a2d869c95ac4a070c7a3da838c928a385f89
+Payload = f45908d691ddaf89c0bc129ffada94c3ceda5f47d63ef76a
+CT = 747fec880a47bfd288d5120e282375fcede46466ae310c46cce85eb55339b886b7121b306fccc0b2
+
+Count = 229
+Adata = 42f944c21cc221beaacb288115ac628346b8a1d94bd5
+Payload = e300fc7a5b96806382c35af5b2c2e8e26382751b59010d4b
+CT = 63261824c00c9038caaa5a64603b09dd40bc4e3a210ef667a37ca5ce12aa6f0659467642deb8bfcd
+
+[Alen = 23]
+
+Key = ea96f90fbae12a857f5c97e0cba57943
+Nonce = 21cc46d9ced1539b0ad946e600
+
+Count = 230
+Adata = 105258d2f25f62675aee975cfdb668aff833f05b61eb2a
+Payload = 49db80f22bc267a70e5636dfbc8a21c83d9691fe4b9c3051
+CT = d2fcc8b7809b5fc07e44083e437d8180157f1782a9ce9f65c7fa9ee2e7cdc1b755258f2212a8a8f4
+
+Count = 231
+Adata = 0f5938540651fa4ca03867e67518eb2b73f60dd8750fa0
+Payload = 26618e21099a79d6c517335389551323065ad89c8848ea12
+CT = bd46c664a2c341b1b5050db276a2b36b2eb35ee06a1a4526bfdb9bfcd3b969fb2e41221eb92b0147
+
+Count = 232
+Adata = d6b228960fcbcf07c7bede616139db62b3808718a5b511
+Payload = 4de1d6d57144896ddea1c30f49afecd27bdf4840ed9928b5
+CT = d6c69e90da1db10aaeb3fdeeb6584c9a5336ce3c0fcb8781f8beea22cba93203c912209c78c03aa1
+
+Count = 233
+Adata = 75f8f071e229355e286882917ce5dd4f1db591fee51b6c
+Payload = 785359b1dc754a1e1b6d8731bd2d917ce3e91507401310e8
+CT = e37411f4772c72796b7fb9d042da3134cb00937ba241bfdc69a2e3ea4a40f7c491912c1a0778ebde
+
+Count = 234
+Adata = 4afb62aa8648ac7474dd16fcc376f8909c69e1ce36e6d1
+Payload = ab627aac1496d011ed2edcb2fc6b2afbcc394654f56124f6
+CT = 304532e9bfcfe8769d3ce253039c8ab3e4d0c02817338bc2a75c7ba2a769c27903e99b72639b0841
+
+Count = 235
+Adata = 736fdf94db820a2efe89e7fc9dcfe7c23d5754ac2bcc7c
+Payload = 40722cffb37f1455c2618408e777ed0f4b1bd039952730cc
+CT = db5564ba18262c32b273bae918804d4763f2564577759ff8f84f4ca4a69fde75d7207e50494819b6
+
+Count = 236
+Adata = 8a9a0367137c28db4c4e78d9cd9a68cde0d1b4583532ae
+Payload = dcaabf7a061502618541c09ea59dbbbd52b2692fd0064747
+CT = 478df73fad4c3a06f553fe7f5a6a1bf57a5bef533254e873a0c34a24d3ee0946034c71fba4dbb333
+
+Count = 237
+Adata = 34dbbff560ef04ea731b8979aef2ae50972f4db3efe14a
+Payload = dd641a893b16e0e173ea2eda20638bb01849ac11e64e8ddb
+CT = 464352cc904fd88603f8103bdf942bf830a02a6d041c22ef0f5e24a435a39a716c39f43dabdc4281
+
+Count = 238
+Adata = f3d1fcd912252431db9d8ccfc3e203d5b34d537468b4c6
+Payload = 9aa3e8ad92777dfeb121a646ce2e918d1e12b30754bc0947
+CT = 0184a0e8392e4599c13398a731d931c536fb357bb6eea673f623d59f66764d859a772bb50ec91fc3
+
+Count = 239
+Adata = 513b4cdc551c203ed5f1e659813584862023911590b672
+Payload = c8f44ae4b02fffdbce0df773c24075f877945fc7a86be460
+CT = 53d302a11b76c7bcbe1fc9923db7d5b05f7dd9bb4a394b543b6549eb16fba96318afb3df51f4675f
+
+[Alen = 24]
+
+Key = 35b403a15212097085d6e2b77ec3d4f2
+Nonce = daa423bf9256c3fcc347a293aa
+
+Count = 240
+Adata = d3c0ed74e5f25e4c1e479e1a51182bb018698ec267269149
+Payload = 7dd7396db6613eb80909a3b8c0029b624912aabedda0659b
+CT = 5b00cf8a66baa7fe22502ed6f4861af71fa64b550d643f95eee82c19ecba34280604b58d92dacd3f
+
+Count = 241
+Adata = 62f4fe53e99a9b0c51e9561d910d7e2ffe19a5176c9dec06
+Payload = 897f0dfd90213f64a9277a0eda4f134f303fa89f56ca54fb
+CT = afa8fb1a40faa622827ef760eecb92da668b4974860e0ef5ab4999e9689d52b8afeb87923efa3b48
+
+Count = 242
+Adata = 191c4dfa653c20292657f7694c6b6a4a410c49a879abd217
+Payload = 2b7cf9e6e2d6abcd7775f8a6eb6294e822041c4c45f09c3c
+CT = 0dab0f01320d328b5c2c75c8dfe6157d74b0fda79534c632cdc71e556c34fd4e1b5ebc50d38da8b3
+
+Count = 243
+Adata = ba34741f8edb51470eb20f891869aabeab562d92571ac943
+Payload = dccb9a4625512496b372a2b8b768f75741d8c2e30e57d638
+CT = fa1c6ca1f58abdd0982b2fd683ec76c2176c2308de938c3646223d381090661c2ee2370d29a572a9
+
+Count = 244
+Adata = 8b922aca6125722ec490b134a45864397f4e2c281d6e2089
+Payload = e0e452c990665465160b02cad6367ca89723613488d8efbf
+CT = c633a42e40bdcd233d528fa4e2b2fd3dc19780df581cb5b1f78af50466646b7c7e652f787afe5357
+
+Count = 245
+Adata = afb9fd78e3f8eaf4e8c91da62b2da534508e54f7dfa214fc
+Payload = b536fdb8839f87080ae65ec35da347e792622ffe18a61d46
+CT = 93e10b5f53441e4e21bfd3ad6927c672c4d6ce15c8624748cc9d9a1270f78648a6b66cb8c0f2471b
+
+Count = 246
+Adata = ecf942ccee7396cb3ee177eadd4d96a4af1d90afdce97376
+Payload = c81233826e5125e1f31fe275184ccba8f1a743e58e146e4d
+CT = eec5c565be8abca7d8466f1b2cc84a3da713a20e5ed03443b17d3d6f1fc4f530841b749d9f3a0a7a
+
+Count = 247
+Adata = 16fea92ffcaad563792aa924bffe7ef690edc90ea4e29cc0
+Payload = 24ab253b5b06552665c3c810254c0ed15e68a783180d7eee
+CT = 027cd3dc8bddcc604e9a457e11c88f4408dc4668c8c924e05852ed48cf88d9ab2326aa46b6541b60
+
+Count = 248
+Adata = 76f110eecd369d79e21fb208058359d3a2f37581d1f7f691
+Payload = 7f596bc7a815d103ed9f6dc428b60e72aeadcb9382ccde4a
+CT = 598e9d2078ce4845c6c6e0aa1c328fe7f8192a7852088444c62dff6bcade5ac2edb8ec9797ce433e
+
+Count = 249
+Adata = 8834c776a3237f060ae0ab9857324a3b2ac79f3b6e6f90f5
+Payload = 11cbfb3d348c7abef99f562607e289de34a2bb379a5dfe50
+CT = 371c0ddae457e3f8d2c6db483366084b62165adc4a99a45eb936ac4764575f85352c24ab23209d42
+
+[Alen = 25]
+
+Key = 7a459aadb48f1a528edae71fcf698b84
+Nonce = fa4616b715ea898772b0e89dd4
+
+Count = 250
+Adata = 0c0b4a45df5c3919c1e1669c5af5d398d9545e44307d95c481
+Payload = 0b3d947de8632dc8ff752f619ba7c84716fac7a23e101641
+CT = 7db9f3f7dc26fc2adf58d4525d26d5601e977de5a7c33911a1138cff7b624f9908b5b4d7e90a824a
+
+Count = 251
+Adata = aa27a28a36b5a2cee57ffeca0233feb4bdd4eacb2cae28e98f
+Payload = e6dedce2c278c44e5678d13e7d5b5d3501d61bb0bb6b5558
+CT = 905abb68f63d15ac76552a0dbbda401209bba1f722b87a08e23f92b598f7a248a894e6b8f5691bee
+
+Count = 252
+Adata = 66220aa9b40a1772caba7749a544bff938e804dbc6e556498f
+Payload = a276b0922fbd5094bf89b9329d07341e039d6204397b81c0
+CT = d4f2d7181bf881769fa442015b8629390bf0d843a0a8ae90e94043c0d80fd651469232fe9d47a81f
+
+Count = 253
+Adata = 3d765d20e03a4cebfda50316c4b7d8b6c55078d5b3e9cbc567
+Payload = b99afbc2dbb377350cc58d4bfe8e954cef25d7b27b82fad4
+CT = cf1e9c48eff6a6d72ce87678380f886be7486df5e251d58425088b522fc0731097e729448236b317
+
+Count = 254
+Adata = e91b6265879153e1692b00a112b4205111c8eb1a7b7f2c6898
+Payload = 56114cc783b80ca2dd2881387b6d92a59a237dfc8e976d8b
+CT = 20952b4db7fddd40fd057a0bbdec8f82924ec7bb174442db2208cf07574cc4f3f83ed6301b904404
+
+Count = 255
+Adata = 340b16f352817babb4fb70e9e6e18784b3e67bdd449872158c
+Payload = eb21fe20fc4f92452b261eac0d7b70016f7469afdff7a3f5
+CT = 9da599aac80a43a70b0be59fcbfa6d266719d3e846248ca514b0a900068e55cd24c92bbb78c521ad
+
+Count = 256
+Adata = 5a2423c2ff2d642c80ac1ca27dd779321f3e9c01445be684dc
+Payload = b15083a73607c9d7e197a8cc884ad3be98ac343f6493df67
+CT = c7d4e42d02421835c1ba53ff4ecbce9990c18e78fd40f0373f8ba66d74321c80c057f010078d2f28
+
+Count = 257
+Adata = 5fe8bb27a59a5f4e370adbba96484c2365fc0d8c6e58d7d3e6
+Payload = 07542d18e8f2d3e199fca0f90cabb78b169525fdce81666a
+CT = 71d04a92dcb70203b9d15bcaca2aaaac1ef89fba5752493a0a189319e4f06d53c1405d37b06cc8eb
+
+Count = 258
+Adata = 23e5422e8d7560a9e65642b5e723a47536c16791f3a0cf918d
+Payload = cd574ed56bdfd1408f7831e0b24b4345ee979ac906a7aa22
+CT = bbd3295f5f9a00a2af55cad374ca5e62e6fa208e9f748572dd72f48ae03670249d74f8460b63b1ae
+
+Count = 259
+Adata = fcc9422ba5023a9997baa9c4ee6cb196ffe96e08eb9c2b8a75
+Payload = 8c9abe94beed4c9bd46adb1d04fbfe7016dd50d324525abb
+CT = fa1ed91e8aa89d79f447202ec27ae3571eb0ea94bd8175eb1717c00c93d36a77141b723d573c8c65
+
+[Alen = 26]
+
+Key = ca748225057f735f712ecc64791367f0
+Nonce = 1341a6998eb1f50d4b710a13ac
+
+Count = 260
+Adata = 5fb96b045f494808c02014f06074bd45b8a8ad12b4cb448ec162
+Payload = e92cd0cb97afe4fb00c4f12e9b9abe1d08db98f49a27f461
+CT = 82b666694232e86e82295beae66ae67d56aceb5d6b1484ceb4a6843ec16078038c10afedc41f5362
+
+Count = 261
+Adata = 87db0d9d69bc0cf69cabeb92570e482bbc8ff3e1ba72f12f3225
+Payload = a6dbad96ad23ff61479df39b99f0673a09f2a7eaebbd34b9
+CT = cd411b3478bef3f4c570595fe4003f5a5785d4431a8e4416a7c6566d0b8ff97f946d7c7773a845f2
+
+Count = 262
+Adata = a061a09024f1e03b223695d4703ee202e90e07156b95859a22e3
+Payload = b1dd81cc3b2b0efe540a3194d6fe304cd2de53db7929ebe1
+CT = da47376eeeb6026bd6e79b50ab0e682c8ca92072881a9b4ee1d66a4728b67b42602e23c8500b0115
+
+Count = 263
+Adata = 0dd513c5d8d62b723ab8b0a3aaa477e843d9149dc8a2f878e585
+Payload = fb30c2e98f3d7e4ed7431da285711d3d287884db13a474e7
+CT = 90aa744b5aa072db55aeb766f881455d760ff772e297044803c51e8c59ed13b3e5d9b489d4ea2ccf
+
+Count = 264
+Adata = 3ff59c40bd796048e586eccc23a82e4d09fc5e779f38eb4afbed
+Payload = 886f9f91a6566ceb99c39462ab675a3ae3be98f68787626f
+CT = e3f5293373cb607e1b2e3ea6d697025abdc9eb5f76b412c0f1ec270b43fc5a9811b56ccf033789c6
+
+Count = 265
+Adata = 0df7ef91f7124da867e992bcbc6fb38232ff6d5205f38768da72
+Payload = ed370d1c2d6dc03e4fae4deb9343a7d4339562cffd427587
+CT = 86adbbbef8f0ccabcd43e72feeb3ffb46de211660c710528bb4ed25940d58cba64271fe1d2e8013d
+
+Count = 266
+Adata = 6777de159c34d005b94f67c33ae4a35ebab09d9cb9c56b4c9c81
+Payload = 2f77c2eb07db14bd713c5af10c0760ea3a6ca5ff8d046d36
+CT = 44ed7449d2461828f3d1f03571f7388a641bd6567c371d99392636a5e373c1354ea9b969abb4932a
+
+Count = 267
+Adata = 75559898f4ba03c55afc25ea91aa61a93c2f8270a5fa51b6f6dc
+Payload = 360fb89429dc9b48358097d930c8561b2bd18dc0a470d1d6
+CT = 5d950e36fc4197ddb76d3d1d4d380e7b75a6fe695543a17959a7e8bc0570f19159f91fc14ac6532a
+
+Count = 268
+Adata = 5e03fc430473c5de96d68907fa506f9da353ae48a965445e1f24
+Payload = f2d8d67b9f291c3edc264893922622b2693f3e7231137eba
+CT = 994260d94ab410ab5ecbe257efd67ad237484ddbc0200e1507e559568c27a30b5676f98cc66f57d6
+
+Count = 269
+Adata = 7eee4869e77f6db12c91d1f647cad2340d33a3defaeb362d311d
+Payload = 7fd6fb81c36e44b150af10e04683b1ec9b5dda87c71ff939
+CT = 144c4d2316f34824d242ba243b73e98cc52aa92e362c89964910615920f6f3c3421a9c2bec1bec7e
+
+[Alen = 27]
+
+Key = fdf2b2c7fcb3789b4e90abe607dca2af
+Nonce = a69ddc66e63a3415f21009d53a
+
+Count = 270
+Adata = c76846da496ed87b9c0f65c6266c9a822224acde9775efb186a4a5
+Payload = d7aa4efa5d75195a400018bd38f7d8cd53fdffe88df1837f
+CT = 150d9a8b78d9c04239d66207a1f95021bbb1b7c70d7c354825d05e5a2e76a90f6fe489fd74cab2a3
+
+Count = 271
+Adata = 4efbd225553b541c3f53cabe8a1ac03845b0e846c8616b3ea2cc7d
+Payload = 5f94a2e48d348a1d56c55a659306e319c3d2ad78b9fe43a7
+CT = 9d337695a89853052f1320df0a086bf52b9ee5573973f590be6af49ce97d5e0e77c7fd5d9cc6d932
+
+Count = 272
+Adata = 7631cf7822a545daefa16a5ec43c877d475a82d5aa2d51cec7fbb4
+Payload = a44b010fc1c659eac9241a58b11a73d7ce33156ddfc54c3c
+CT = 66ecd57ee46a80f2b0f260e22814fb3b267f5d425f48fa0b924b268cab915f999aea3e1cc3a88ccd
+
+Count = 273
+Adata = e4da34663edc44370bfd8aa8315945471a893a1cc069628a071ee0
+Payload = 28d157f5741f1be057d5219711414c0638b47d165a905a6a
+CT = ea76838451b3c2f82e035b2d884fc4ead0f83539da1dec5dc368f5af8e311e67209e02dfa2613377
+
+Count = 274
+Adata = 077509eae1dc367540f87832c5780f6c5b29e180bc6c1fee38e826
+Payload = ba7432a8e34bfaa91b35c8dfd822d86850be39e63150257f
+CT = 78d3e6d9c6e723b162e3b265412c5084b8f271c9b1dd9348ad175fcad35d29396380b79a28784cff
+
+Count = 275
+Adata = a513d750ca1e8bf6cb7b8cea5204e064c15c2dc40d742b31cf5459
+Payload = 3f5830b0ce8849a660af7d58a60c19a9824a3033bb5fed43
+CT = fdffe4c1eb2490be197907e23f0291456a06781c3bd25b7493b4b3e33d325359c9c651290ce73bed
+
+Count = 276
+Adata = e439db829c1291df49fc42c2fa1a92118c2665f11e13f28dc6f11a
+Payload = e69b2a243340df5dc70b2cb05be12e5992ee36f7d9f4ca84
+CT = 243cfe5516ec0645bedd560ac2efa6b57aa27ed859797cb371f88ca5857c6d801e726a01c621a0c3
+
+Count = 277
+Adata = a12c690568114fd7a677f49d74e84fc1a6b7f7d2a08693266c0a91
+Payload = 9de35b840a69a84701ffae1b1d2bf13c34b42a57d14c524d
+CT = 5f448ff52fc5715f7829d4a1842579d0dcf8627851c1e47a0592d360fc6a46aa18c4ce5d74fa4532
+
+Count = 278
+Adata = 1813bf176a1127f4d508d7663ae750f9c4bcb84a6e26811ac60d46
+Payload = 9e2fa20bf76768a5a1467d90a048bb503a2c33bbbaa71653
+CT = 5c88767ad2cbb1bdd890072a394633bcd2607b943a2aa0648b772cef893495cf0a94e8ebf06e920b
+
+Count = 279
+Adata = cc6e9cc2699d3ba0e624e715599480d6b7dbc6eeea0d12a9236444
+Payload = 6681b1cbeceea57a828324831407280b00f4917ed52a10df
+CT = a42665bac9427c62fb555e398d09a0e7e8b8d95155a7a6e8b1851d571a1ef8aed565b784dcaaac4e
+
+[Alen = 28]
+
+Key = 7d870d7e52d3053c65eefad47764cfeb
+Nonce = 37d888f4aa452d7bf217f5a529
+
+Count = 280
+Adata = 9610949f6d23d5b1f3989b2f4e524fab4f297a5bec8ddad4f16cb616
+Payload = 109317556c21c969eda65a94176d7a11462c9ae18a865b6d
+CT = 4e6b967b1571c6d7b9e118b112b7ac949a4a175650316a242dd579cb0d201d22c86bbc7fbe47bd0d
+
+Count = 281
+Adata = 96118dbfe53434d8aed88769a535eb0c8b5849dca1c81c34626ac9b9
+Payload = 3e6c914a196e175079315b1c92b2b8a844deb472e249e3d3
+CT = 60941064603e18ee2d76193997686e2d98b839c538fed29af0dd7aef4a609f3587652173446ebd82
+
+Count = 282
+Adata = 21fc96f73975298207f818909088295d6d6861677130ca258c2174f6
+Payload = e0014147d5771b4380dc0192d45f36f7d60776d1ba47374d
+CT = bef9c069ac2714fdd49b43b7d185e0720a61fb6660f0060463e4405d45caf4836467edbf35089d87
+
+Count = 283
+Adata = 72a5151abcb55933ff7c9314f3235eba2a400121454144c2670e8359
+Payload = 0f1c6dffeda98f7a159f9cc61820bfb29910d8eaa41b751a
+CT = 51e4ecd194f980c441d8dee31dfa69374576555d7eac44537441c813e90fac775eddb7290df059d9
+
+Count = 284
+Adata = dbbf192914b1ad73666e9f5e9c22c08ca398f7524af62b1046a863bd
+Payload = c1ddd14e380cc91324cf2a381df1da1ccffd90ae436a373a
+CT = 9f255060415cc6ad7088681d182b0c99139b1d1999dd067334d9316f1f1c3142c1c9b26e5c220a32
+
+Count = 285
+Adata = 28e4b88fbf04e9897057ff5bfde7eb04fa480256817a50fa281030b4
+Payload = d4dae9c4cae92afb80f9a5c99383ff16e23a2ec942eed4d2
+CT = 8a2268eab3b92545d4bee7ec965929933e5ca37e9859e59bc0b188e33bfab29b237d6c6920ce3418
+
+Count = 286
+Adata = d9ebc1cbfab9034317132a72e0f11c341331146a59e7a2f26bf4f3d7
+Payload = 8a188d40a6e6fbb06a9f06304349a7a808b092cc2fc10b9e
+CT = d4e00c6edfb6f40e3ed844154693712dd4d61f7bf5763ad7fdde04d21b876468bd9184101b5f32d0
+
+Count = 287
+Adata = 34ad69f192ae4dcab771aeeacf01bbd32609bcbbea8ff9df31ded719
+Payload = 590c1aac30ab166b1caff748452fc146765c372e226ffc26
+CT = 07f49b8249fb19d548e8b56d40f517c3aa3aba99f8d8cd6f068c65e9d0e5f1b81c86393900e64c19
+
+Count = 288
+Adata = f5e50ce1f99ed5e9f2baa54b96ae7039234b1131e734ec190695d28d
+Payload = 16d0522b2e691e42bd80ce95e00c8a7a1fc738169e904bdb
+CT = 4828d305573911fce9c78cb0e5d65cffc3a1b5a144277a9206ab3b72c56c8df4a12dba89a2f21276
+
+Count = 289
+Adata = 9b1e7e52ea1a12444d884866e11dcf367b70b816460936fdaebba36d
+Payload = 0bddf342121b82f906368b0d7b04df1c682ecd4c2b2b43df
+CT = 5525726c6b4b8d475271c9287ede0999b44840fbf19c72960170ca7b16d23537eeb3034105334699
+
+[Alen = 29]
+
+Key = 8fcac40527c0e7ca8eaff265ca12c053
+Nonce = ae9f012fd9af60a400e20b1690
+
+Count = 290
+Adata = 9ce65598cd1f86afc9aaaf172809570cc306333c25523f863c6d0e0154
+Payload = 78d1e96af8cebdcc7e7e2a4ddcfa34f6cf9a24fb85672ad7
+CT = 9adb9a95a9379ad795d8d3ffd4e37a045160d6d727f974a6cb3b5151f327e65447e52c7525562c91
+
+Count = 291
+Adata = e7c78ef4c4b959ee00cb1a09d71221a43892ef8ad705edd27ed85d03a3
+Payload = bc59f18c8473941abc681a92741ab5ee13679829f542b8f4
+CT = 5e538273d58ab30157cee3207c03fb1c8d9d6a0557dce68534e5b08e27d8f5eeef0f064ff620652a
+
+Count = 292
+Adata = f1bce6f2a4bdd3a07ebf5f8d47f931d27e7e63389d70e1059f701216be
+Payload = 5575d950312c14c89ac609dfb0b2fd1af732bb6aae5e8651
+CT = b77faaaf60d533d37160f06db8abb3e869c849460cc0d82044c0a96baae318f4714f0206812516b5
+
+Count = 293
+Adata = 3da3bb091016e54477dae88af1c84c1a51b59c1bb49a05deb6f32064e6
+Payload = df5947d8c6094ccc25816639ec42214b28731bfd7b8312dc
+CT = 3d53342797f06bd7ce279f8be45b6fb9b689e9d1d91d4cad4e7bdce2dc6aae24178aab6984f31028
+
+Count = 294
+Adata = c4cd183071c37a8157c6930a7d4d530cf4b7eb021682327810bd48209e
+Payload = 2fbb6dc235761875411ef59ae06110df8f15f66b721b0fd6
+CT = cdb11e3d648f3f6eaab80c28e8785e2d11ef0447d08551a7f18ece8260bd56ecdee768022d0dd8d1
+
+Count = 295
+Adata = 0e0fece7b6b659b642668e8ba3dca330523e70279155f485f3f6f8041e
+Payload = cd149d17dba7ec50000b8c5390d114697fafb61025301f4e
+CT = 2f1eeee88a5ecb4bebad75e198c85a9be155443c87ae413f6f0fb3b7440b84ddc3cc53819c2e93be
+
+Count = 296
+Adata = a35c6f70f637a9a5e6f215c694fdf65b6fd85f794ed3eaa1bc19abe592
+Payload = 030390adb572f2bd2a6a4454fd68236cd1d465574328aa00
+CT = e109e352e48bd5a6c1ccbde6f5716d9e4f2e977be1b6f47129ca778c51f9320f121dd803ece8d5da
+
+Count = 297
+Adata = c2992096828325820e2d7acaa17ac789b6830ec3128dd7f904398afbec
+Payload = f2d9cf953c8d3a051d9b3eae4307a3cb4fffaa2435b49586
+CT = 10d3bc6a6d741d1ef63dc71c4b1eed39d1055808972acbf79c223a5ad65120bfca4a5992e5ebc6fc
+
+Count = 298
+Adata = c023763a285ea934bc5bc7ddfc2aefe2b3f9eafe7b87c61383dcc07990
+Payload = 4b92e8d2ffaa4af8f3e0ac037a900bd18e195f490a3d71e1
+CT = a9989b2dae536de3184655b17289452310e3ad65a8a32f905c3bc4f618ffb3a159f4e2d0622cea6e
+
+Count = 299
+Adata = 0a39ec0163c7aeb1b4fbe7cb4fa5b0592fade70f430e23730a23ed4160
+Payload = 7c0e6a0d35f8ac854c7245ebc73693731bbbc3e6fab64446
+CT = 9e0419f264018b9ea7d4bc59cf2fdd81854131ca58281a376f099dce6e18435fba4d26c1e93bda0c
+
+[Alen = 30]
+
+Key = ddf9f150cc3f1c15e8e773663c5b061c
+Nonce = 98c5036b7d54da9a1177105600
+
+Count = 300
+Adata = 20c5ab290e6d97f53c74121951f39ba865b3acc465fa3f0fb8a591622277
+Payload = 79d8841ab83279724ce35e1a8abd4e158168dcf388ab4c3d
+CT = d00d29396ffa9e691290d746527777bf96a851f306d4da0b1816df1e0e82bb7bc8105930ad6a2232
+
+Count = 301
+Adata = 0e205a4dc5d5ead0d9ff7f182dc140fc49511c01b0fdbc7e6d6cb5fdf027
+Payload = 88b2572fbe7cf2b46df04db476ffedb41778ae2eb3c3aae4
+CT = 2167fa0c69b415af3383c4e8ae35d41e00b8232e3dbc3cd2df823c8ccd466807f2bd1c4032f0cfeb
+
+Count = 302
+Adata = 48043560d60381e83c11d4bc9d997d3ee2add6b0524b779c62dfaa73ce0a
+Payload = d44bf28b010e076b45db1b053af03db718b60748da51db1f
+CT = 7d9e5fa8d6c6e0701ba89259e23a041d0f768a48542e4d2931f5be8c9965345c760c72cc1b7908d1
+
+Count = 303
+Adata = f0729a8a2fd073699ab87b521cbe0420b43529556a505f5f87874d1a053c
+Payload = eab8cffb512eabe267cd64353552513defe97c2d10f35503
+CT = 436d62d886e64cf939beed69ed986897f829f12d9e8cc335381d94a828a95872ebdfda8a4c6a196b
+
+Count = 304
+Adata = fc2cd69bb61223f713e33a5071d09bf2783640c307c22d836dd94952dd37
+Payload = 001056926546c261fbbdf92b94498e038c2bcfd0b6345497
+CT = a9c5fbb1b28e257aa5ce70774c83b7a99beb42d0384bc2a163931808533f4f70d7a78242ced110eb
+
+Count = 305
+Adata = 8f653c5c003c807d16d17f833eebb97c9c2f0e5aae3780a52ce53a6c33f7
+Payload = 29ffaef9415fd300127ffd26ef324083a9d90e0f60e2ab4f
+CT = 802a03da9697341b4c0c747a37f87929be19830fee9d3d79f34553198f8e40fde6473f9cf04f1de6
+
+Count = 306
+Adata = 8d05e7d3077151c6d9378cb08e049e4d7c28a908f7f7c079c46ff92cd01b
+Payload = 9874dc5ca1b541f7b21c7b3860fa6b0c3ab1b712ab0fca98
+CT = 31a1717f767da6ecec6ff264b83052a62d713a1225705cae0fac20e8d45d2b0771d140b5e4a47c87
+
+Count = 307
+Adata = d4feb3ea76ac2945651f557406f3f38a2d7e9232ed55ff4eaf1201dd8255
+Payload = 1e01c7128c821fb9c971a27fc7c6f9bb902fa735de583b8a
+CT = b7d46a315b4af8a297022b231f0cc01187ef2a355027adbcd3cacfe4281e52d79e60eeb38319bc3a
+
+Count = 308
+Adata = 7cbb4ae995a3367a256cafd11cd6c6cab5bf3252fa97f27a8a1434ca9a27
+Payload = 51cd306fac7d20e3c7043eae3a6dfec046c5c24a666a0723
+CT = f8189d4c7bb5c7f89977b7f2e2a7c76a51054f4ae81591158f0d7646a799b14288bb2f354b5d8847
+
+Count = 309
+Adata = bd40b06a4beded2be3d176266b10772c7fa2949f0a9b20d613af90c2daf5
+Payload = fc5b26befc633a3e8ace011aa7a42bd0258a9f3dc14fc1c8
+CT = 558e8b9d2babdd25d4bd88467f6e127a324a123d4f3057fefd7f95e1d331e700aa9ef83f09b689fd
+
+[Alen = 31]
+
+Key = b1dc81d116d94f5eced526b37c004b95
+Nonce = 97c8f69fb91b17299461fd8d63
+
+Count = 310
+Adata = f8b08aa83bed09ca342249b2cf9e2b45a89dcfb8711a120395e455921af481
+Payload = 54390715b6e7c7bd51a234db059a51ba030cf22ee00b7277
+CT = cb629994c3418a662a8cde1b5f4d99aa7df66e24c53dc6df11297930fd44c63675b7cca70671ef4d
+
+Count = 311
+Adata = 0351c969dd38eeaa4b9b0000e346eeb1a2cd462033c59d9e6e3331822045cd
+Payload = 65b5e856a8cf35dffd42c5ba105cba4c434aa1c2a0390352
+CT = faee76d7dd697804866c2f7a4a8b725c3db03dc8850fb7fa7e77f5566ca2fd9293835bceb461dbaa
+
+Count = 312
+Adata = 5db8b6bc16740680f78fba917733a6899cdba5e4c10a8058963d1265681eaa
+Payload = 9a7685e3daac43ccf22cad0df900ba8acddc5d420846118d
+CT = 052d1b62af0a0e17890247cda3d7729ab326c1482d70a525ec2cf9f5d35521c1c000685e49d2ed42
+
+Count = 313
+Adata = e7d6024611210da0cfb90a9955195aa0a0539280a3a7c792a1540930daae2d
+Payload = c18d9e7971e2ae5fc128777086338fbe194443324e2d2cd1
+CT = 5ed600f80444e384ba069db0dce447ae67bedf386b1b987966f33dfb44ae413283b238616c6b99fb
+
+Count = 314
+Adata = 77a878c9c76f3e6a4ddd330d1d8828949d08e0fedffe0d8e2e557b29e7c78c
+Payload = fcf8982f7342f1b953658453cd5ea413700eff00f1ee7d6f
+CT = 63a306ae06e4bc62284b6e9397896c030ef4630ad4d8c9c731df6fc6b4cf0b6332936ed7cfe9455e
+
+Count = 315
+Adata = aa540554ee80dbffa475f702d862d6b60e0a4090792420a26d02926517723e
+Payload = 0d5690d2a7083ad6daf22b308314b8f5363aca77ca72835e
+CT = 920d0e53d2ae770da1dcc1f0d9c370e548c0567def4437f67c8162a815f2809601ad02595e2e0ff4
+
+Count = 316
+Adata = fae86f95dd06fb7fbae63a646615555aec8153dc328bdf79da5d4cc9677ed6
+Payload = f6e313cc35e8f8812b10a44f8ad00b6893f8084d942effe0
+CT = 69b88d4d404eb55a503e4e8fd007c378ed029447b1184b487fcaa11bdeab86f60f9cd0a2b45cee1a
+
+Count = 317
+Adata = fd525302d2fb246a47cf4e3a27808bda89d8488cf450f1a1c7df6eedd810ee
+Payload = 91e961ea2eb750577c5137c609602dbfcc4c07955ba429ec
+CT = 0eb2ff6b5b111d8c077fdd0653b7e5afb2b69b9f7e929d440a86a810881bd969744ad80f579400f1
+
+Count = 318
+Adata = 767b1bdf9793a512d3a84e99ef77b43011a3bcb8de4cd375dfe47a79293e01
+Payload = 98438c4411bead6f30c89ead762a12bf39391d3652b78b7a
+CT = 071812c56418e0b44be6746d2cfddaaf47c3813c77813fd2250ca00d3231819ecdf501ad39c864f3
+
+Count = 319
+Adata = aac7014f606df6feec415a75e29015891007f07518c955875fbf5619262ff2
+Payload = 540cb00c0eface3d1b2d632d80a642f53c78ff672a1ff6ff
+CT = cb572e8d7b5c83e6600389edda718ae54282636d0f2942571224d1d0294d46981d7dc39114a693d2
+
+[Alen = 32]
+
+Key = 5a33980e71e7d67fd6cf171454dc96e5
+Nonce = 33ae68ebb8010c6b3da6b9cb29
+
+Count = 320
+Adata = eca622a37570df619e10ebb18bebadb2f2b49c4d2b2ff715873bb672e30fc0ff
+Payload = a34dfa24847c365291ce1b54bcf8d9a75d861e5133cc3a74
+CT = 7a60fa7ee8859e283cce378fb6b95522ab8b70efcdb0265f7c4b4fa597666b86dd1353e400f28864
+
+Count = 321
+Adata = 55a62968c222a8501d1ae56a9a815667f8a9554607b7c56e6753f8fa92a4d054
+Payload = 764dbefb42644d18d23e5e4568685d14dbacfa418d36c4ef
+CT = af60bea12e9de5627f3e729e6229d1912da194ff734ad8c4423862a715dda2f63a4197f894515803
+
+Count = 322
+Adata = f8436e35b7a1c810ac6aabe8e2d48a3678d19e1e96337dada514ee5fc075fce4
+Payload = cecef24b62676a5623bedae8087b9b05d7e22b41a14dd2d5
+CT = 17e3f2110e9ec22c8ebef633023a178021ef45ff5f31cefec200f190bd700f6108f9959f6d12f0f0
+
+Count = 323
+Adata = 548e2152f3a15b8fb81dc01062d99f7b4fc8f074e5cbdc1030c97f8ccc02ec3f
+Payload = 53c164a4990c6e0637267ff2556c1542712fc584f6ff7458
+CT = 8aec64fef5f5c67c9a2653295f2d99c78722ab3a088368733a66ebc4e0777a6fc140a51e04a10f86
+
+Count = 324
+Adata = d100f1d08ef1e3eda4aef22cd970c2b785c4ff9b523c401b4064324aecf7f2d9
+Payload = 15681d2121ac56a63b9d0a38b9c4eccf84fdb746d32c14b4
+CT = cc451d7b4d55fedc969d26e3b385604a72f0d9f82d50089fb810cdc08db0a9966dffeb43ba26446e
+
+Count = 325
+Adata = eece934a807c9f21487cd810f15fd55d7bb4421882333ff2c43b0353de7fc5a6
+Payload = 412a8ef924ca156de860f147575e5731825f0a3759688928
+CT = 98078ea34833bd174560dd9c5d1fdbb474526489a7149503cfc5b397578f8d02a0b936ffac29b99a
+
+Count = 326
+Adata = 86311ff444d9be90459b6ee3652e1705ed0b5cdac3d27293ddea3378fb686ee5
+Payload = 54ba8a020d0876fa369dc32e8627f565ba3dda862ea0bcfe
+CT = 8d978a5861f1de809b9deff58c6679e04c30b438d0dca0d52c3fcd6d618c260d51724126f257534a
+
+Count = 327
+Adata = ab6efbc44a8906d5c067eaed71af467e130aaf170827a58beb03c55069674125
+Payload = 7a15506fd1dae444d77b2a3ae7b57a8d5b4f10e25a9f78e2
+CT = a3385035bd234c3e7a7b06e1edf4f608ad427e5ca4e364c9bf8b2821920640b992b00cd1c9618025
+
+Count = 328
+Adata = ddb640923d083725587aced81ae1d7409983d1f1e3ccc8dcf94376dc1bbcae8b
+Payload = b18a61a89cd698f32e059b7a2a9f62a46be2c248790a9915
+CT = 68a761f2f02f30898305b7a120deee219defacf68776853e4cd52d41a968284af8907ccbb4588cc0
+
+Count = 329
+Adata = d95ec4a6f594be1ba39fa1aa933dc0a5dafff5ce44509577ebb3a3e8084c4401
+Payload = 16ee3bc9ec8b4448e292b8973618e02a99da1c348539d5c7
+CT = cfc33b938072ec324f92944c3c596caf6fd7728a7b45c9ec47449a5cb4943ff2846c589b7c98ef49
diff --git a/lib/crypto/test/crypto_SUITE_data/VADT192.rsp b/lib/crypto/test/crypto_SUITE_data/VADT192.rsp
new file mode 100644
index 0000000000..1a7a5875fe
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VADT192.rsp
@@ -0,0 +1,1823 @@
+# CAVS 11.0
+# "CCM-VADT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Plen = 24
+Nlen = 13
+Tlen = 16
+
+[Alen = 0]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886
+Nonce = 15b369889699b6de1fa3ee73e5
+
+Count = 0
+Adata = 00
+Payload = 39f08a2af1d8da6212550639b91fb2573e39a8eb5d801de8
+CT = 6342b8700edec97a960eb16e7cb1eb4412fb4e263ddd2206b090155d34a76c8324e5550c3ef426ed
+
+Count = 1
+Adata = 00
+Payload = 296fbda0017351491c2187273fbde2c3a427170e430a703c
+CT = 73dd8ffafe754251987a3070fa13bbd088e5f1c323574fd2167ee33e75d05023a7d63c770cfef2ea
+
+Count = 2
+Adata = 00
+Payload = eb61c284fe009921039ef6a9ce50e702823e44b35357923f
+CT = b1d3f0de01068a3987c541fe0bfebe11aefca27e330aadd170647420f79c0d91cbbd69b806fe96a5
+
+Count = 3
+Adata = 00
+Payload = ffeccc6460d23fdcc387c697e75dbb959b78013a8282eaa4
+CT = a55efe3e9fd42cc447dc71c022f3e286b7bae7f7e2dfd54a8a3ef2324754539ac774872282534386
+
+Count = 4
+Adata = 00
+Payload = 90958d7f458d98c48cbb464c74bf495a49846dd468c514e9
+CT = ca27bf25ba8b8bdc08e0f11bb111104965468b1908982b07e292cd0e32535a848e327bc53cdae94c
+
+Count = 5
+Adata = 00
+Payload = a4fad5205d38206e25097075687ca86032b95b3fe7e82a07
+CT = fe48e77aa23e3376a152c722add2f1731e7bbdf287b515e9bb21701af36936be5f62d02b84df87c3
+
+Count = 6
+Adata = 00
+Payload = b37114c65372b052cbeecf83d05a5da44f7b5bbff7d986b5
+CT = e9c3269cac74a34a4fb578d415f404b763b9bd729784b95b7da7f975367be24341e4af51b8bb156a
+
+Count = 7
+Adata = 00
+Payload = 9c0f0426f171ff18b2a4392f61fb4ee4a44c476fe03dc930
+CT = c6bd367c0e77ec0036ff8e78a45517f7888ea1a28060f6de360c6d50a96f316eda0b216cbb6380ef
+
+Count = 8
+Adata = 00
+Payload = 7b6e0a480a40585545b0e940e8d97c9ec987bd3c0e9c16a8
+CT = 21dc3812f5464b4dc1eb5e172d77258de5455bf16ec1294634cd1bd98e8137b578a174e39efe09b8
+
+Count = 9
+Adata = 00
+Payload = 34dac6dbc28be62332a6935efc122e37b26ee100eb4033f8
+CT = 6e68f4813d8df53bb6fd240939bc77249eac07cd8b1d0c16909a895a3b08b63d7a2a1e75d25e7861
+
+[Alen = 1]
+
+Key = 9748798c0f3cc766795c8ce0e4c979c1930dfe7faefea84a
+Nonce = cdf4ba655acfe8e2134fa0542f
+
+Count = 10
+Adata = 67
+Payload = 100fa71462277d76ca81f2cfdb3d39d3894b0ca28074a0f0
+CT = 36e2415b4f888a6072f260d7e786d803be16f8b9cbee112d7ff74e3b05b7d7c13284573bd3e7e481
+
+Count = 11
+Adata = 17
+Payload = 0217eb6778691f8dfe2d0e5241f05fcbcf97b9171f4de3f0
+CT = 24fa0d2855c6e89b465e9c4a7d4bbe1bf8ca4d0c54d7522d3ee7ce845f85dfc770d96dee9ca54ccd
+
+Count = 12
+Adata = dc
+Payload = a78b7bc6c1a7250c5fc236f2a8343725a9a7bd3ca81b53e4
+CT = 81669d89ec08d21ae7b1a4ea948fd6f59efa4927e381e239dc14ddd8ae0aa5d810040a8d1d4da1e9
+
+Count = 13
+Adata = 0c
+Payload = 390c808d998582793bb10ee60568eb8d975c51d68b4e4da9
+CT = 1fe166c2b42a756f83c29cfe39d30a5da001a5cdc0d4fc746b40dec7e647720f1f5e8474bf570c2f
+
+Count = 14
+Adata = 3e
+Payload = bcd9747fb54184b61b2e9e049caa75e22006e250f3722c0e
+CT = 9a34923098ee73a0a35d0c1ca0119432175b164bb8e89dd3c10c4aac45d90119cce490cc8681a49f
+
+Count = 15
+Adata = 7e
+Payload = d0342e3cd2c1142b642da7297ee3b9978cec405e6810f12f
+CT = f6d9c873ff6ee33ddc5e353142585847bbb1b445238a40f2f9a95091d2cab7d3d9fa3e10d3e67ac9
+
+Count = 16
+Adata = e3
+Payload = 7fab91d1aa072947d22f0dc322355a022fe7f0747f4a184b
+CT = 5946779e87a8de516a5c9fdb1e8ebbd218ba046f34d0a996180f7818c373e89f7ff3003f53260060
+
+Count = 17
+Adata = 3e
+Payload = e487143dc4d98dcc6a2dfe6ee0f85d565d1f46bb0fafe62a
+CT = c26af272e9767adad25e6c76dc43bc866a42b2a0443557f71905f581585e59e3c8c038b5bf966559
+
+Count = 18
+Adata = 3b
+Payload = 976b489244ed6789a34251500057d1d4a3229367a42b9066
+CT = b186aedd6942909f1b31c3483cec3004947f677cefb121bbea56569c34f8d9eea23e85fec18cfc51
+
+Count = 19
+Adata = a5
+Payload = 71efa75961dfd60ad533082a8cfe111214eb02573adc4591
+CT = 570241164c70211c6d409a32b045f0c223b6f64c7146f44c212da23548f2ca4e9a8a07962be6422c
+
+[Alen = 2]
+
+Key = 393dcac5a28d77297946d7ab471ae03bd303ba3499e2ce26
+Nonce = fe7329f343f6e726a90b11ae37
+
+Count = 20
+Adata = 1c8b
+Payload = 262f4ac988812500cb437f52f0c182148e85a0bec67a2736
+CT = e6d43f822ad168aa9c2e29c07f4592d7bbeb0203f418f3020ecdbc200be353112faf20e2be711908
+
+Count = 21
+Adata = 9db5
+Payload = d5982c462ad40458660cd7b120ce07fce9afe812caedcebd
+CT = 1563590d888449f231618123af4a173fdcc14aaff88f1a89015e5cd97b7dd3d981321ae0b2d99e1a
+
+Count = 22
+Adata = 69cf
+Payload = 1a95f06b821879df3fd3ac52fc99a7c1d3e9775263b7d036
+CT = da6e85202048347568befac0731db702e687d5ef51d50402bf3e75863c7acd2699caba3cc301f4b2
+
+Count = 23
+Adata = 6c6e
+Payload = 373c157e59b934a1afb57d4c5dd9ca7fb736b206a6210bef
+CT = f7c76035fbe9790bf8d82bded25ddabc825810bb9443dfdb5d6a8f7a9f52a8038aa9dc1bdc9ed876
+
+Count = 24
+Adata = dafa
+Payload = 26e10a2ed8cc883a6552aee162c5542ff8bb8e758a1975f8
+CT = e61a7f657a9cc590323ff873ed4144eccdd52cc8b87ba1cc8a15603f10cbfdb041f8b2b12cc8f037
+
+Count = 25
+Adata = c8b1
+Payload = dd235b05c15479dfe0326ba206ac784eca50038bbeb35d32
+CT = 1dd82e4e63043475b75f3d308928688dff3ea1368cd189061278bf62ba6a4819513d49fdcdb45480
+
+Count = 26
+Adata = af48
+Payload = a0818342a5cae4a90ef281d3d1289d83f273f418a545fcbf
+CT = 607af609079aa903599fd7415eac8d40c71d56a59727288b8b4d00309b50f9ea72f8105c94475b52
+
+Count = 27
+Adata = b1cd
+Payload = 33c0d06b6583bb4d15b4a07364c4be70ac6e72795c3dae0f
+CT = f33ba520c7d3f6e742d9f6e1eb40aeb39900d0c46e5f7a3b220ba58e97936612c4183ba86705b2f9
+
+Count = 28
+Adata = 649a
+Payload = 3ba11282d61fe36e38cab7b559c2fd9cbe8bf7eb5863bde9
+CT = fb5a67c9744faec46fa7e127d646ed5f8be555566a0169dd87d602dc85bb260fb3df1221e2fbd10c
+
+Count = 29
+Adata = 593c
+Payload = a97faefcae36732fcfe47736c2334ea7d411bf7638b0c019
+CT = 6984dbb70c663e85988921a44db75e64e17f1dcb0ad2142deb3835b7eecad6dac9785ad1d370ede4
+
+[Alen = 3]
+
+Key = a74abc4347e4be0acb0a73bb8f7d25c35bae13b77f80233a
+Nonce = 6a850e94940da8781159ba97ef
+
+Count = 30
+Adata = a4490e
+Payload = 6372824bf416cd072a7ad0ae5f9f596c6127520c1b688ab4
+CT = b14a07bdc119d87611342c4c6935c5786ff1f9ae2eb49e6191c88a3cb4fbafcb8a4a157d587d7e39
+
+Count = 31
+Adata = 5cad2e
+Payload = 295f4f3417a77fcf0bbda17b0fd629ad57a6086573c87eb1
+CT = fb67cac222a86abe30f35d99397cb5b95970a3c746146a64235c34d1390bba5b008c3fb29c2df958
+
+Count = 32
+Adata = ebdf4c
+Payload = 86f354a505de941d34cd98e3af3706d56a938ab9a2797182
+CT = 54cbd15330d1816c0f836401999d9ac16445211b97a565575a733bba0a6992d0664dc77d2b5d194c
+
+Count = 33
+Adata = 7c0d70
+Payload = 88c3bfb546abe2f6bfc92a7c56c627e24ab92a8a87a6b43c
+CT = 5afb3a4373a4f7878487d69e606cbbf6446f8128b27aa0e90902a31b15eed99c2dc4ed1bf11cad96
+
+Count = 34
+Adata = 8fa501
+Payload = 75d4216bad77943bfe82be216157843b0da0fd16eeee8471
+CT = a7eca49d9878814ac5cc42c357fd182f037656b4db3290a42f25595ae00103d4eb20288158132e7d
+
+Count = 35
+Adata = b7aca7
+Payload = bf1401e8dcf6f681ed6dd74c7e23b7e54b384608b0e5ec52
+CT = 6d2c841ee9f9e3f0d6232bae48892bf145eeedaa8539f88760e67693b509ea4795b7da32c5c5d17f
+
+Count = 36
+Adata = 1f283f
+Payload = 7e623e7ef7d0a678b5d22a8402d89220f4f1bf759e3084dd
+CT = ac5abb88c2dfb3098e9cd66634720e34fa2714d7abec900880ef8ea380a1a0a38b2c20288e637a9f
+
+Count = 37
+Adata = e93f31
+Payload = 14f80e7a6298d85d31fb80376a394a8f88b0ae47f00450c7
+CT = c6c08b8c5797cd2c0ab57cd55c93d69b866605e5c5d84412d553aafe8536385d34c412c14d3a1563
+
+Count = 38
+Adata = 27e9a5
+Payload = 3330df12249639961f562a74b34f60b0a8bc7c783f6572fd
+CT = e1085ae411992ce72418d69685e5fca4a66ad7da0ab96628f594d366c8fc826ce58309e9053c27f7
+
+Count = 39
+Adata = 72d566
+Payload = 1a1860ac8c11c5d262f8141738cae8ff91ca05906dc98bb4
+CT = c820e55ab91ed0a359b6e8f50e6074eb9f1cae3258159f61cdd6ac6c42cd3d11e0344a9c1001e253
+
+[Alen = 4]
+
+Key = df052e95aea3769a433ce4e4e800b8418649bbe8c6297eb0
+Nonce = ba356d392c3f700f4f2706a4ca
+
+Count = 40
+Adata = 8ffc0e3d
+Payload = e8c1a89228d8212f75c136bab7923a89f9fea18e781cb836
+CT = 66b5d782323925e1bd0a8413a9a5a881356453d5df2cbeb199b2e1e803550dcdde55fd66ecb45edd
+
+Count = 41
+Adata = 2b4f9cfc
+Payload = a12c6324e022affd61b7e0d8cccbeb23e2e6c65355c1d586
+CT = 2f581c34fac3ab33a97c5271d2fc792b2e7c3408f2f1d3019e8fbc507244ba234a0581dc69962a66
+
+Count = 42
+Adata = b4de3039
+Payload = 7cccb26f1dd227bc77458b99fd9e00f8e801adaece7bfcd1
+CT = f2b8cd7f07332372bf8e3930e3a992f0249b5ff5694bfa5628a2857099af20a4ae08e687bdb02c75
+
+Count = 43
+Adata = bc59f18c
+Payload = 692b53c1355475c71ceff0b0952a8b3541b2938270247d44
+CT = e75f2cd12fb57109d42442198b1d193d8d2861d9d7147bc3e33a6416e387d9e571a1954471ec9cc7
+
+Count = 44
+Adata = 4fd9fd39
+Payload = 7e3e755e25bbe78d4a7770f9356ab9f4ff1bbfdba46383f5
+CT = f04a0a4e3f5ae34382bcc2502b5d2bfc33814d8003538572180f9735f994c8335e593f30b331a920
+
+Count = 45
+Adata = 296cd04c
+Payload = 997b712cd9295dc43cc19b40679f218c27af3e8c638d2e5d
+CT = 170f0e3cc3c8590af40a29e979a8b384eb35ccd7c4bd28da91990fa537d2657d01f66872ba9af22f
+
+Count = 46
+Adata = 88037d3e
+Payload = 577981ccb6c893dfe6405075fcb41507de7f9bfda860791f
+CT = d90dfedcac2997112e8be2dce283870f12e569a60f507f984915cb93e84028c7aedce1a2dadbb6bb
+
+Count = 47
+Adata = fc4bb852
+Payload = 37ba9f57ec230675ce060ba3d388095adf15907aa0b0673d
+CT = b9cee047f6c202bb06cdb90acdbf9b52138f6221078061ba25baa6385af8d7b807a2d2ab19aa4999
+
+Count = 48
+Adata = f40ec14f
+Payload = 401e0cdc132a9e4a9b5ceeed3c181f67e5203ea69508deff
+CT = ce6a73cc09cb9a8453975c44222f8d6f29baccfd3238d8786adcdb44870e1105b7318d8bad0af957
+
+Count = 49
+Adata = 90e2c63b
+Payload = 0234dae5bd7ae66c67ff0c1a3f1a191a0d7bceb451bc2b7d
+CT = 8c40a5f5a79be2a2af34beb3212d8b12c1e13ceff68c2dfa8b079fb71d45bd985bffd343c3362653
+
+[Alen = 5]
+
+Key = 16d345606a315ad2406abbcb43cd8cabe948107ba6d17a72
+Nonce = d4ef3e9e04f1b7f20ffc5a022e
+
+Count = 50
+Adata = a468f08d07
+Payload = d3bef460223c81e4579c9d1d463ac5e0881685de1420a411
+CT = abb85db49a9b1c8724ecbc734cc8373bd20083cfa4007b1cfe4d3a3bb25f89f692884be230c6035c
+
+Count = 51
+Adata = 4497649a54
+Payload = 81ad3f386bedcbf656ff535c63580d1f87e3c72326461ee1
+CT = f9ab96ecd34a5695258f723269aaffc4ddf5c1329666c1ecd05ae56511a230627e02d066c52a919e
+
+Count = 52
+Adata = c30ddd994e
+Payload = 84b88264afec06b370dfcebf5e1d3e2c1f005faf248b3215
+CT = fcbe2bb0174b9bd003afefd154efccf7451659be94abed188ef92fc17dca026f1ac1eaf78a05017c
+
+Count = 53
+Adata = 9573270f7e
+Payload = 9e4c8aa9b58a8eabc5586892f5541000b43f17d9a051a040
+CT = e64a237d0d2d13c8b62849fcffa6e2dbee2911c810717f4d38eddff1e60e2d9ae74a936364b8df21
+
+Count = 54
+Adata = 40336790fc
+Payload = 260f67122dfbe03365bc9e35e9d4ac4b2eb150eddb30857d
+CT = 5e09cec6955c7d5016ccbf5be3265e9074a756fc6b105a70aa3d464ad89cae59b474d019a5a7605c
+
+Count = 55
+Adata = 0b310c8529
+Payload = 1d55e7352bd895c4ef77389a7225c664f72b38c8de778d57
+CT = 65534ee1937f08a79c0719f478d734bfad3d3ed96e57525abeab0c520e64939c6950c0fa406eafb1
+
+Count = 56
+Adata = 5756b2c681
+Payload = fbd315e1f5bd0f0e60ee6684c88f3543452c62ea0701d11d
+CT = 83d5bc354d1a926d139e47eac27dc7981f3a64fbb7210e10d22d339c382343bf39c239fd64c2a64f
+
+Count = 57
+Adata = 3b919e3665
+Payload = d68d6556c5a5b1f5a123389b3ce966d5837cb8fcf5accfff
+CT = ae8bcc827d022c96d25319f5361b940ed96abeed458c10f2fcd6b562a1b6aa10be92a81f99ed540c
+
+Count = 58
+Adata = 58749b643f
+Payload = 062cb6962fa5b3a6239b95f3a51b478a1f32b081dc538a80
+CT = 7e2a1f4297022ec550ebb49dafe9b5514524b6906c73558d4b853022237d94d253b375bf2150e699
+
+Count = 59
+Adata = a5d50c008b
+Payload = 08c62ff9bd7bcf189f530d5065f8764532d2692f69858483
+CT = 70c0862d05dc527bec232c3e6f0a849e68c46f3ed9a55b8ee7aee0d403b2cf6f8b993eebd6b93615
+
+[Alen = 6]
+
+Key = 1c476cfd7dd300d961fd3f24a6fe0e80742b00851676ca63
+Nonce = e300fc7a5b96806382c35af5b2
+
+Count = 60
+Adata = 28130f938c45
+Payload = 6f3938932b5c1280311e892280d8a822a828a0be7fdb1bcd
+CT = df48662fe134e75a85abc2cece2c3b6236c88a70fa792e9beadc9601adf9fbdf4e3e94b395b0a332
+
+Count = 61
+Adata = f600024a7bf9
+Payload = 0af7345e71f4e8886503395ade0b0296a5856e086638b06a
+CT = ba866ae2bb9c1d52d1b672b690ff91d63b6544c6e39a853c0692a40a6aba8d7c5addae21de90fea9
+
+Count = 62
+Adata = 4eef510d1f48
+Payload = 37f57772f056f45a5ce9f46d27be1858980c8935b9c839b7
+CT = 878429ce3a3e0180e85cbf81694a8b1806eca3fb3c6a0ce122f64becb581070411957e632e19bb8f
+
+Count = 63
+Adata = 4c9c76b6fad5
+Payload = 8bb10c82bcabb7fb2b169252ab443b01df217cf908b8c241
+CT = 3bc0523e76c342219fa3d9bee5b0a84141c156378d1af71708c59f83aa97d069b6d83d9387051f43
+
+Count = 64
+Adata = 5572ecfc7e53
+Payload = d1ccb4654a22b1afe32f3d3035fdccd87e9cbed83c679007
+CT = 61bdead9804a4475579a76dc7b095f98e07c9416b9c5a551f04686ee1d7b985d903f1de6cf78f8f4
+
+Count = 65
+Adata = bffdf9d20d74
+Payload = f990a8f6ba14065d48665db36eb470c49f38e2b6376a9bde
+CT = 49e1f64a707cf387fcd3165f2040e38401d8c878b2c8ae88f8118f1b9f39b51965ae9ef1bdb40111
+
+Count = 66
+Adata = 3f27e678c580
+Payload = f8c7d89639ab742a8bcfffe776e868d671e1fbdd55807a8a
+CT = 48b6862af3c381f03f7ab40b381cfb96ef01d113d0224fdca3236d02f33f49759f281315e449bfef
+
+Count = 67
+Adata = 1294cb9db5f5
+Payload = 8601cfd7d935e8a8487b9c39d55ca27096255f2eb9e009e3
+CT = 3670916b135d1d72fcced7d59ba8313008c575e03c423cb5e74770a07c242c3854ceb242dadc1976
+
+Count = 68
+Adata = cec271332b75
+Payload = 77c85b8022f58337b364142a2474fe5cfddb31cfca48af46
+CT = c7b9053ce89d76ed07d15fc66a806d1c633b1b014fea9a10d6c65f19175cfa49898655ccdddb864a
+
+Count = 69
+Adata = da06bd140502
+Payload = b0f2db802475fa70af02057373844f637a3244cda4b4f93d
+CT = 0083853cee1d0faa1bb74e9f3d70dc23e4d26e032116cc6b458822e49e69031431b3eea872a72eb7
+
+[Alen = 7]
+
+Key = 79d1e38a70df1cf239be168833dcd0570bc8f37b3aa26c37
+Nonce = 8229d6d7e9e21fdc789bff5dcf
+
+Count = 70
+Adata = 076887d2abe900
+Payload = 83c24f3a77b83b4ef45277ba90225f3ba1722312f52b1a07
+CT = 19d880f1d959a68f162de243d4a45747ace704613359b27218d1531a066de60a95d2924a6910e990
+
+Count = 71
+Adata = 7535bcc6fbd1a0
+Payload = 24f85ef683cc521387f484bc0b2ad9172f61884c09a9718c
+CT = bee2913d2d2dcfd2658b11454facd16b22f4af3fcfdbd9f96dbf58406020e6df7b312b6825127f9a
+
+Count = 72
+Adata = f4f96d7b4384a3
+Payload = 212bedfa06b5e1a2c3a2f31f6f791dd9df8ef26077821c0a
+CT = bb312231a8547c6321dd66e62bff15a5d21bd513b1f0b47f64dd755177efc87f8b1daf1fd88e51a6
+
+Count = 73
+Adata = 3b7e3d9c1a7fa2
+Payload = 8b9036914bb0f440c8dbcfde9b9547be5e5ef1f56492c75e
+CT = 118af95ae55169812aa45a27df134fc253cbd686a2e06f2b0be31cab31f1a20805d5c07dc516d707
+
+Count = 74
+Adata = a8c35fae8912d6
+Payload = 50f3f3a91bf6fd9573d5ef54b9bb5805205b2f9865d81fd7
+CT = cae93c62b517605491aa7aadfd3d50792dce08eba3aab7a2399df9a45ad153c0dfb3fec3b9d6f7c5
+
+Count = 75
+Adata = db636541f2429d
+Payload = 6fbda8d435555e735443f1e6bc09e96065092efd89edd64a
+CT = f5a7671f9bb4c3b2b63c641ff88fe11c689c098e4f9f7e3fe20b7da94eac8c7ef8478671165e0d82
+
+Count = 76
+Adata = a8de55170c6dc0
+Payload = 640ef4c246a2c6e16ddc49072a5aeef70319149ffba071ef
+CT = fe143b09e8435b208fa3dcfe6edce68b0e8c33ec3dd2d99a4979c35bdbf9538666b6fa57f0f915d8
+
+Count = 77
+Adata = f8d64ce2aa66e6
+Payload = a14e3910766f31594a28ad2c3678c31d0c3aee88484ca6d6
+CT = 3b54f6dbd88eac98a85738d572fecb6101afc9fb8e3e0ea3752824a691da2e99374ae6c031d74ffb
+
+Count = 78
+Adata = b3c340afdc53a8
+Payload = 1b8e0a09e6364020b4cac704dc19bfa79455295604cf9c9a
+CT = 8194c5c248d7dde156b552fd989fb7db99c00e25c2bd34ef04159a68706faa2e8c3376b4dbeb423a
+
+Count = 79
+Adata = 73824034001519
+Payload = 52c84a0735eea6c5c230644075ebfc5db0c3128056e7a8f4
+CT = c8d285cc9b0f3b04204ff1b9316df421bd5635f390950081e5adc7564721ead2af75cb98e61148b4
+
+[Alen = 8]
+
+Key = 72e6cebdaf88205c4e74428664bc0d7eb4687a272217b7ca
+Nonce = 3820db475c7cb04a0f74d8e449
+
+Count = 80
+Adata = f427c47e10c45bb3
+Payload = 54bc7e3c227df4e83252a5848fea12dfdb2d14b9e67c1629
+CT = 91e7baff2b42af63e26c87ce6991af22422c1f82906858b1721961de5c768f4d19bd3034f44f08d2
+
+Count = 81
+Adata = ca25504f3f5559aa
+Payload = ff4493fea916f49fbb3cae2838bc84e293531092cc0904ab
+CT = 3a1f573da029af146b028c62dec7391f0a521ba9ba1d4a3342968c638ecb8a2b358e8eaefd931efb
+
+Count = 82
+Adata = 8215753d9efc5132
+Payload = af16ab8558269a93d8e8c9e38f12a8768947d8b69be0e259
+CT = 6a4d6f465119c11808d6eba96969158b1046d38dedf4acc1f8ac11752fe51e354f3f8a68815539aa
+
+Count = 83
+Adata = 9e7cdbc6202e6492
+Payload = 744a167ae31a8ca20df82290766429de9ef0b7dfe199a78d
+CT = b111d2b9ea25d729ddc600da901f942307f1bce4978de915489de8e241dcab16bdcbf1a1ff4d8d10
+
+Count = 84
+Adata = b8d511d0ab86a07f
+Payload = eeb39de1fe21b5aba654da45fe1481decb22365fa4cbe49d
+CT = 2be85922f71eee20766af80f186f3c2352233d64d2dfaa053fab212a1b6dc7b953e2bc211be194ae
+
+Count = 85
+Adata = c74a5d4265f9f3d5
+Payload = e95c20e80153bae3fde3c3d82b6b33b35fc1959fa31a5d11
+CT = 2c07e42b086ce1682ddde192cd108e4ec6c09ea4d50e138973918ab70fe048d6c5b63a01725eddfb
+
+Count = 86
+Adata = fd849d3ada03181a
+Payload = 6d00606c72cea3deaea5b51ae09e61924355e167058ef42c
+CT = a85ba4af7bf1f8557e9b975006e5dc6fda54ea5c739abab487089bc20867f474c1127aa1320f0000
+
+Count = 87
+Adata = 56825a68681f498c
+Payload = c47705d897a6c7e7aed710b96e2d8532c23b82090e21b114
+CT = 012cc11b9e999c6c7ee932f3885638cf5b3a89327835ff8c34a23b0b6ac4d297dd7832a5e2102272
+
+Count = 88
+Adata = 72e4da839913a26e
+Payload = c822a1ee581cf85b0482c821473385bd3f28528e5e5760d9
+CT = 0d79652d5123a3d0d4bcea6ba1483840a62959b528432e41dd665766c7af21ff890bd40178f1c660
+
+Count = 89
+Adata = 138457571ee8dafd
+Payload = 3ffb82a83308da66e95ac63ae92931b09ffe0e42afbb4979
+CT = faa0466b3a3781ed3964e4700f528c4d06ff0579d9af07e16a6a58bb772c79481dc26861ffbd68c6
+
+[Alen = 9]
+
+Key = 39c03a0c8634047b1635348f284d3dc1e752ab40548eb337
+Nonce = 9e2ea8eb7f56087ee506925648
+
+Count = 90
+Adata = 28d157f09a71da80dd
+Payload = 0662e63c88e963d3e0cf2c4653515ae4474a2c78ab0394c0
+CT = 01dcd4dd3b8c1369518136ce45e8bb9df565b0ad231a887b02ada34addf0aa2f4744ed2e07995491
+
+Count = 91
+Adata = c17d311362c41d442b
+Payload = d6df8b60c697093987b3d89a3667b36504b6ddddf12b0900
+CT = d161b98175f2798336fdc21220de521cb6994108793215bb38a27466b8741bffce44ef04b23af321
+
+Count = 92
+Adata = 006669ef1a11b65b1d
+Payload = 49ad29ef5e82b08752ac5a50dd982e4bcb700005454ade6c
+CT = 4e131b0eede7c03de3e240d8cb21cf32795f9cd0cd53c2d77d11372fb0dab1c99b159e5fe9f91118
+
+Count = 93
+Adata = 8eafce9ba466fd53eb
+Payload = 385f9fb139dbf88561b7a500b0c7b835fe57e2698c6d9f76
+CT = 3fe1ad508abe883fd0f9bf88a67e594c4c787ebc047483cd09e4898a4046f6ec9f40e412915007e4
+
+Count = 94
+Adata = 796e55fbe7bed46d02
+Payload = 4ebb149b01cbacba32d11168ca61928ea149dcf2ee2c1001
+CT = 4905267ab2aedc00839f0be0dcd873f71366402766350cba5d40a9902481bfac7ff33d08fb4b3d31
+
+Count = 95
+Adata = 8f958d796be0566512
+Payload = 0d974e5621caa1d86eaaee689ccbca57843373fcf20db407
+CT = 0a297cb792afd162dfe4f4e08a722b2e361cef297a14a8bcd972d09a17172161eb68a30b593b1bd6
+
+Count = 96
+Adata = cc879ff2d583a7288c
+Payload = f8e0dac6a691dfb231411b5c5f70a0daff83cc637b0c7bb3
+CT = ff5ee82715f4af08800f01d449c941a34dac50b6f3156708119cc26a80c152c253fbc36cb886e0fc
+
+Count = 97
+Adata = 4765d696d19dec58bc
+Payload = 096a36396ccfa260f28fb0919157a5076b53506c51a2a4ef
+CT = 0ed404d8dfaad2da43c1aa1987ee447ed97cccb9d9bbb8549de06cc5c3bc4ad75076c774576843fb
+
+Count = 98
+Adata = a004f283afc3309c31
+Payload = 5b943269be41e2758a4ea6a3cc621b711a8ba6002783aa72
+CT = 5c2a00880d2492cf3b00bc2bdadbfa08a8a43ad5af9ab6c9135493b44f79a5774df6b2943b0bec67
+
+Count = 99
+Adata = cdd5d8aefe49a315ad
+Payload = 5f27867109e74862ce0dbc9ba73c420b93067bdede17ae51
+CT = 5899b490ba8238d87f43a613b185a3722129e70b560eb2ea7a5da4a29a9012d78b6de6f1b3e8c9ed
+
+[Alen = 10]
+
+Key = e2a92ffbb0b5eb68cb82687f12449fae5167d375131b0b10
+Nonce = 441ad5e1382e083a95224f395d
+
+Count = 100
+Adata = 2352648299b0413cb2ce
+Payload = 048c9ba4597c3bb595bfd5048e5e9a1296f30e5c0118b177
+CT = 25247a258e4ac0a988d8def60cc174a9d4578cd5346fb5150c96e8ab8774baa421f39c64a386c418
+
+Count = 101
+Adata = ce003c836a6f5f066053
+Payload = 02ea8e7e488c863584f828df13dfeb68433294d11d9ca9d7
+CT = 23426fff9fba7d29999f232d914005d30196165828ebadb5d453036cdc6bad0c5e770a6249a52e74
+
+Count = 102
+Adata = d11be73a104ccc6346d5
+Payload = 6d5573c9279897d7d1602d8a95c04bb5ca3fad2dbe89a024
+CT = 4cfd9248f0ae6ccbcc072678175fa50e889b2fa48bfea4464627ad75bbfe17f3f5ddfd3dbc1045f3
+
+Count = 103
+Adata = 6a7b80b6738ff0a23ad5
+Payload = 97a813e75d95d25c2edb1c705c4ffe4d7c08c756761fbc0b
+CT = b600f2668aa3294033bc1782ded010f63eac45df4368b869af8943f74706cc3394a170fd49f7011a
+
+Count = 104
+Adata = a391acdb3a06dae4a671
+Payload = a78981ac244307451e4d3fd7f654b70cc4e6518aa47a3c18
+CT = 8621602df375fc59032a342574cb59b78642d303910d387af22597f63074ca3533bb5e107860481f
+
+Count = 105
+Adata = 0b9f28f2d3215785f569
+Payload = 5d649d79ff0e304e164a383c74f13d7ffab145d00cb0ec2c
+CT = 7ccc7cf82838cb520b2d33cef66ed3c4b815c75939c7e84e905b5609f593c6ea9281f66cd2e646dd
+
+Count = 106
+Adata = 7928b1091cbfb2eef0fe
+Payload = 83a273687dced7b94d569f81d75508595cde668f06406183
+CT = a20a92e9aaf82ca55031947355cae6e21e7ae406333765e1428195355618ea0cf87260ad20b6d7b9
+
+Count = 107
+Adata = 3b74afb81f54a93c79d5
+Payload = b4dc3c059cf7b47dd0bb7f165a63fc80b5c6b5f3ca7eeb73
+CT = 9574dd844bc14f61cddc74e4d8fc123bf762377aff09ef1155019659f41a5f0430695b4ada9d8b8d
+
+Count = 108
+Adata = a46ae4c71d4c9eb72fab
+Payload = 7e919581c5105d98717d0613e1ca869c6516506ea482d5c2
+CT = 5f3974001226a6846c1a0de16355682727b2d2e791f5d1a01514b252f33dc870c42260e48c4fa9fd
+
+Count = 109
+Adata = a1ace61711f0a09ac17d
+Payload = 3a4558b55214f21cbd2ae2eda5a2321cfc2f102e059b744a
+CT = 1bedb93485220900a04de91f273ddca7be8b92a730ec7028c263c667d7ed58907452c092905d0b31
+
+[Alen = 11]
+
+Key = ef1ad3eb0bde7d4728389da2255d1f8a66ecb72e6f2f1ac4
+Nonce = 8e7d8a44244daa7df2b340993e
+
+Count = 110
+Adata = 521583c25eb4a3b2e46120
+Payload = 9f580cc6c62a05ce125c6bec109a48ca527ee26a64b14b68
+CT = ff0ff95bcb0bccd5e4aadd77ac6770f5013654eb3c6386fded2c87135861b43a99f258b6938f66e3
+
+Count = 111
+Adata = 31adb39e947f8883fa4b69
+Payload = f16bba081bddda83546eabc9a55c81a439720dd8562ce964
+CT = 913c4f9516fc1398a2981d5219a1b99b6a3abb590efe24f132b87476d66a1bd405f484ef9ac8ab7e
+
+Count = 112
+Adata = f05f39eb0a3d6460076aa8
+Payload = 6baf784f63cf45a1836fa8f3609fff7870ce8cbd1e91268c
+CT = 0bf88dd26eee8cba75991e68dc62c74723863a3c4643eb19a120b455b366cb104fd8b6dc2c80471e
+
+Count = 113
+Adata = 74c7a633ff73ff507009c5
+Payload = d8176a6de1c15a14c8b8b58725c179dc84c9308268d718d5
+CT = b8409ff0ece0930f3e4e031c993c41e3d78186033005d5400c8ca09f4bf06b1c27e75abf15112e49
+
+Count = 114
+Adata = ab322a88cf44b9ca774415
+Payload = 3706e4d8ff748574f382e5f9b0a3b6258f1f360fd87001b0
+CT = 57511145f2554c6f057453620c5e8e1adc57808e80a2cc25b3159274a7de3550baf759f7fae53dbc
+
+Count = 115
+Adata = d6fe6e17221d4e06ed3ab9
+Payload = e02217394772deffe218c405e40f2a3a56ca01d55d6d3330
+CT = 8075e2a44a5317e414ee729e58f212050582b75405bffea516fba8d193e133e6f78daa39681cb262
+
+Count = 116
+Adata = 2739d2cdfcbe7d5cd7d28c
+Payload = bb713f74a884bd1a994adba87561d637853c6181290ef5e8
+CT = db26cae9a5a574016fbc6d33c99cee08d674d70071dc387d65f92db3b3d1c2de04c69c5d06b0e001
+
+Count = 117
+Adata = 5841571299cd064a6262b7
+Payload = 9641dedd50d80ac0abf7591436065fa2e23e4687abbb86e4
+CT = f6162b405df9c3db5d01ef8f8afb679db176f006f3694b716e4d20ab5ffad6f71155f6839dfdbb25
+
+Count = 118
+Adata = dc5d7fd97bb3243ba585fa
+Payload = aefda8501193edacb8abb94fff875529a537a462c4b9b69c
+CT = ceaa5dcd1cb224b74e5d0fd4437a6d16f67f12e39c6b7b090ebc3af2de52b8bee3d130fa973f716b
+
+Count = 119
+Adata = 8789e0b3e0dc13d9725b37
+Payload = 65e53f549b62aca03f21ab2a494b93805e02cfecf4f12aa4
+CT = 05b2cac9964365bbc9d71db1f5b6abbf0d4a796dac23e731b5cd5a004a0ef28e30383bdaed8f93c7
+
+[Alen = 12]
+
+Key = 44cba20b7204ed85327c9c71c6fea00b47ce7bdde9dea490
+Nonce = f3329154d8908f4e4a5b079992
+
+Count = 120
+Adata = f1e0af185180d2eb63e50e37
+Payload = 6333bde218b784ccd8370492f7c8c722f8ef143af66d71d7
+CT = b9401a4927b34dc15e9193db00212f85f0c319781ec90e3b4484d93cb422cb564acc63d3d18e169c
+
+Count = 121
+Adata = ea74231e49e667ca1c21d46d
+Payload = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e
+CT = e67d8fbeec794d42fc64d7f36a87d2ac22aafa440021ea72c4c151d9927e6a9f19d47ff7d79ca6f6
+
+Count = 122
+Adata = 7f5871a8300471dc325f8289
+Payload = c642c9722d84d708682350dc70bdaa9a1181a415a9e72b93
+CT = 1c316ed912801e05ee85c7958754423d19ada9574143547f959eee29be1415ab03444de0fa42707d
+
+Count = 123
+Adata = ee7e6075ba52846de5d62549
+Payload = 2286a1eddd80737a724ca941217e9f0232870b6c2f20d29c
+CT = f8f50646e284ba77f4ea3e08d69777a53aab062ec784ad70ce97c1c8aea70de04580d7b37f8c014d
+
+Count = 124
+Adata = a30f2fd445820cdf80014554
+Payload = 92577d5db20391110309d490f52acecdfc18382f368bbe42
+CT = 4824daf68d07581c85af43d902c3266af434356dde2fc1ae23b536f993381e525a14599dd5c02e80
+
+Count = 125
+Adata = 0cfec933831644b468724e80
+Payload = 6803dc3f7c06568ca78ee5aa2e9b1b354a4f1e067ff6a25b
+CT = b2707b9443029f81212872e3d972f392426313449752ddb7d6ea722fdd82ede2c7b8832dde3cbe80
+
+Count = 126
+Adata = 6bd14e3bf91dc7fd6be07647
+Payload = 5580672e52aacb9d714a34c31c33fc221e13e8f90849adba
+CT = 8ff3c0856dae0290f7eca38aebda1485163fe5bbe0edd2565c2994b2b469ad977564d83db1ebfe38
+
+Count = 127
+Adata = 6c6ad35e97d023217018162f
+Payload = 1bd1bcc6766d251144376d91ff93ef83033d0e0ee546266f
+CT = c1a21b6d4969ec1cc291fad8087a07240b11034c0de25983ac31ebf9e255eecf3c69ddf198760556
+
+Count = 128
+Adata = 52c35db85cc34b6efed180ee
+Payload = 28f71a2fe498f89203a5d23e8f8fa64b124aea6459fe721d
+CT = f284bd84db9c319f8503457778664eec1a66e726b15a0df13424079e3de87fa59c3d10fd62380a90
+
+Count = 129
+Adata = a96e4776270683ee7d0c9b6e
+Payload = 5be078ead1926074afca81f9a97dc93dcb954c955e4343e4
+CT = 8193df41ee96a979296c16b05e94219ac3b941d7b6e73c082258e1f3fc3eb7e976c86c8a21bd6569
+
+[Alen = 13]
+
+Key = b5f43f3ae38a6165f0f990abe9ee50cd9ad7e847a0a51731
+Nonce = 13501aebda19a9bf1b5ffaa42a
+
+Count = 130
+Adata = ead4c45ff9db54f9902a6de181
+Payload = 3726c1aaf85ee8099a7ebd3268700e07d4b3f292c65bba34
+CT = fd80e88f07dad09eed5569a4f9bb65c42ef426dda40450119503d811701642143013f28ce384d912
+
+Count = 131
+Adata = e63b89e95df8338ecdcc885c3b
+Payload = 37f86aa62b1e31e9ded3e1a38a7e1a8a638d619ac109694f
+CT = fd5e4383d49a097ea9f835351bb5714999cab5d5a356836ac6d3f9c7b9f25e09ce164a11370b8b05
+
+Count = 132
+Adata = a2161536e263459e0b0a29a225
+Payload = 1749f5977197359a5d318d5fea38aba95b3603f1d7011e66
+CT = ddefdcb28e130d0d2a1a59c97bf3c06aa171d7beb55ef443e02b848b006c28803303fd97bdc35476
+
+Count = 133
+Adata = 8ac95a6ae0bce0fb07f85368ab
+Payload = 0842bfb8b38283257c2ea58b29c8350775f1dbf15f73c905
+CT = c2e4969d4c06bbb20b05711db8035ec48fb60fbe3d2c2320431de2bc45b2b726bfda92939a11f68b
+
+Count = 134
+Adata = 44cc9b2510680c4d73f1938c77
+Payload = 68d09fce5e89e4ef6d453b8ee326090cedb97b75b886c7b3
+CT = a276b6eba10ddc781a6eef1872ed62cf17feaf3adad92d96786add8c2619f0782ca12312a1d64266
+
+Count = 135
+Adata = d8a662ab8449bd037da0346a24
+Payload = 45245de4ac6a6196a0b15b77c622a21bb50627379ddb4256
+CT = 8f8274c153ee5901d79a8fe157e9c9d84f41f378ff84a873b6bd4a09f9b4aa2864d39ff1a03e0ff7
+
+Count = 136
+Adata = 8ed39da1d9179e77156eb909f3
+Payload = e928e37dbe8389a53c650edc86f83cd3589a53dc8e45adfd
+CT = 238eca584107b1324b4eda4a17335710a2dd8793ec1a47d819b6935778ffbc0953974de0a9d87a31
+
+Count = 137
+Adata = 423515f7bd592d6a7a2408661a
+Payload = 4c3bdc6186297896097b3297ba90bcde78dc8a9efe3bd8b1
+CT = 869df54479ad40017e50e6012b5bd71d829b5ed19c64329400a3da0d3ce34a272b51582a998f461e
+
+Count = 138
+Adata = 5a6bc2cd6890a473d478a582b4
+Payload = 1c5ebaeb7b926a39b8aaf65a4c484b113d6f2caafadc33ea
+CT = d6f893ce841652aecf8122ccdd8320d2c728f8e59883d9cf4ef28c338f497a40f550f2945734ad1a
+
+Count = 139
+Adata = 7bdc26b5b4df58af539d91eb2e
+Payload = be5c9fee6babf569c66e6a0d0f3c4dc314f40c0aeca493f7
+CT = 74fab6cb942fcdfeb145be9b9ef72600eeb3d8458efb79d2e07f1998e57ba9b611568632dc5cb9fe
+
+[Alen = 14]
+
+Key = 13f179aa2a23bc90a85660306394940e9bb226ce3885ec01
+Nonce = aaa52c63ca1f74a203d08c2078
+
+Count = 140
+Adata = 5cc924222692979a8e28ab1e0018
+Payload = d3b36c6289ad6ae7c5d885fe83d62a76270689ce05fa3b48
+CT = bc4fcef401c2e1d1c335734ff23ea52c3474d2e6f31648a7f58649400ac9e825b038d67f0c2a6f1c
+
+Count = 141
+Adata = 21fb9cdd9b110bbbc6832275dfa7
+Payload = a7742dd9c3e8bbad08157fbd01ebfb94e1639117c4b4eb5d
+CT = c8888f4f4b87309b0ef8890c700374cef211ca3f325898b23fa5ad4142e0b4650fa5cc8f7ef70d62
+
+Count = 142
+Adata = 9919ddb6ee6c330646cd15953d39
+Payload = 297b4498bf5427e6341aa9275c1f62e3b0c9b150a195ae72
+CT = 4687e60e373bacd032f75f962df7edb9a3bbea785779dd9dfec551d11b8647432cc4320173939600
+
+Count = 143
+Adata = f94cfd1f8c7902a57784c10b9a5a
+Payload = 2218868033e17220655f0196dab6193c58293ca105d467d9
+CT = 4de42416bb8ef91663b2f727ab5e96664b5b6789f3381436a79a075ec2cacee1482b8328b697a3b2
+
+Count = 144
+Adata = 63f3fe58c348dc6bcbb44c3c370f
+Payload = 4a9bc26fb10000a57b9e73a8a3d30f66ef9de8782201ffa8
+CT = 256760f9396f8b937d738519d23b803cfcefb350d4ed8c4739cbe17b4edd64a3dcd2b8ae3352c04a
+
+Count = 145
+Adata = dec0ce763833305aa9c9efdc2c65
+Payload = 1b61b3ff3e4847a17f55f7565826b0e2ccc1368f4de32022
+CT = 749d1169b627cc9779b801e729ce3fb8dfb36da7bb0f53cdf54665c476d0741164685b0d81caca31
+
+Count = 146
+Adata = 592ef6784ee839a049e0d96257fa
+Payload = 32e5998b37987a38800f5bfe3132979ca1447314570aaef7
+CT = 5d193b1dbff7f10e86e2ad4f40da18c6b236283ca1e6dd18500d93b11fecc8b4560320878ba53550
+
+Count = 147
+Adata = 4a47a82b999a2a739959f153a091
+Payload = 84acfb6cf10b301558e5acbf41bbbe0b145dc66dc600f4df
+CT = eb5059fa7964bb235e085a0e30533151072f9d4530ec87303c2a41443578adaf31483bbb6b9f10b0
+
+Count = 148
+Adata = 4ceba98cc0ff5de1a7d580cf23d2
+Payload = d7c73d77a286df38aad116843620911c92e11486be5fcb0c
+CT = b83b9fe12ae9540eac3ce03547c81e4681934fae48b3b8e32232a856c07999e99a4701988b486ef2
+
+Count = 149
+Adata = 15e3b3c5794fececd703ac58ccb2
+Payload = 140882c5d3534bb0861e7ba9423e67439a02ee6f0b0b00f3
+CT = 7bf420535b3cc08680f38d1833d6e8198970b547fde7731cb3a6d50a92f3183c0c5090edc3c7f822
+
+[Alen = 15]
+
+Key = c1dfc48273d406a3a7b9176f80b2dc4e9a7f68134bab66d2
+Nonce = 1ac53ba965cdaeeef7326a37e4
+
+Count = 150
+Adata = 39ba54a410a58a5d11615a2163cc3b
+Payload = 67d9728a88f1fac3af43ed6d634ba902896bd226858697d9
+CT = 360f0fc714994e3b59448b50cdd61d511b4f09e0e5fb5ac826a51fe5b9b598a17eb3da10f936813b
+
+Count = 151
+Adata = 38b0cca09d69320105d24ee3f96684
+Payload = a8365ba9fcfff060b28895f7a2d786c5991a8f7758962caa
+CT = f9e026e460974498448ff3ca0c4a32960b3e54b138ebe1bbba673a94f4280e84724f4a2510165e9a
+
+Count = 152
+Adata = 76718dfb9c68acdd82592d96def39a
+Payload = 497be597dd695cb159d8a64f44049c3b549ac927837b1b90
+CT = 18ad98da4101e849afdfc072ea992868c6be12e1e306d68118865ab37be6f015316e0d177b6c2e91
+
+Count = 153
+Adata = dd719ba1710916a546233c1494a7a7
+Payload = ca452c21383ebc3fb584f0d59a227374854983f243a3f460
+CT = 9b93516ca45608c7438396e834bfc727176d583423de39713d903f67ad0d72fb8ffea2035216b769
+
+Count = 154
+Adata = d893fa2bd7c70e21a5934dc2e99037
+Payload = 3dd118ed65453d3d7844d8de78d7a43587ac5e9305b11464
+CT = 6c0765a0f92d89c58e43bee3d64a10661588855565ccd9750b885e3e054f519d0355db1bd589bb35
+
+Count = 155
+Adata = 97c60265a3a6993b97ac1b375a79b8
+Payload = a7375ba32251af0138bd9fd8fcd56a7c43ab2ca9a7fc0117
+CT = f6e126eebe391bf9cebaf9e55248de2fd18ff76fc781cc064a950e4bed4137e38787839e39924821
+
+Count = 156
+Adata = acfdf302ed116ac4755069d1704423
+Payload = d39d188f28521e4fb0a0c5e48e6d6efe4383c95b2535ea8d
+CT = 824b65c2b43aaab746a7a3d920f0daadd1a7129d4548279cca94dd97fd2a5d50eb7dd6234b40c525
+
+Count = 157
+Adata = d449f97164aae9a3046624e98810bc
+Payload = 758102470e221e30d87d2807b5f8b793a7a56c83eecf32a4
+CT = 24577f0a924aaac82e7a4e3a1b6503c03581b7458eb2ffb596f11450d5d2ba55ffb4a6cf7eab847a
+
+Count = 158
+Adata = 3e6c914a196e175079315b1c92b2b8
+Payload = 1db875c4b4f9dd4926dfb5604d6c4d21aba7d905aed9d1b0
+CT = 4c6e0889289169b1d0d8d35de3f1f972398302c3cea41ca164894e9218ecacd143fb62df69a13d33
+
+Count = 159
+Adata = e2b7b00d0cfbdfcc24f1819ae1869f
+Payload = d7a75bc621addccbbe162b86d536d69c887c278384af54e7
+CT = 8671268bbdc5683348114dbb7bab62cf1a58fc45e4d299f685a7c19bc9c2f8e36ed95015ebb679ae
+
+[Alen = 16]
+
+Key = d8a662ab8449bd037da0346a24565683a3bbbbd1800e3c1c
+Nonce = 166fb8d0e110124c09013e0568
+
+Count = 160
+Adata = 1c1c082eeb5b8548283d50cc2ace1c35
+Payload = 61fdd10938557080191d13dd6c3002dd445d9af988029199
+CT = 23c05927502a4ee6e61e4e10552d49b020643eab476eeacc867601fe79a122a7817819655183283e
+
+Count = 161
+Adata = cae884fa25adedd883ef4e7c855def19
+Payload = 8c7ae2c3c503e9072d6e04e44c2ea78fd24994503567a136
+CT = ce476aedad7cd761d26d59297533ece2b6703002fa0bda63160bb976ab072aec8fcea8eab3dc5aff
+
+Count = 162
+Adata = a350ed58c04473e113b9088b1fb9dad9
+Payload = 863f9a26182f131c594972398b52b3a01a9d314fd9390bf4
+CT = c402120870502d7aa64a2ff4b24ff8cd7ea4951d165570a1291b2c13a3f5e49ce35b9047ee1e8627
+
+Count = 163
+Adata = cb7090f7a465782f680fd44cbc558107
+Payload = bd94c9ad6253c25dc417f87b6e52e03621ccf4b3bff5b402
+CT = ffa941830a2cfc3b3b14a5b6574fab5b45f550e17099cf57fdd9fd1d469a9042b80e6458d25292b4
+
+Count = 164
+Adata = 914cf55a3fc739b5f87ac7518cc4171b
+Payload = c313bd213dc29c00691e25ce028884192e21a820003aece4
+CT = 812e350f55bda266961d78033b95cf744a180c72cf5697b1a8b8e82175ff30c69ea71d2cfb814ada
+
+Count = 165
+Adata = adc8b69d84ef7ae62f9ca9f371d3488e
+Payload = 85e4e053b976e06a64dfa8523130cdd802d3e7c3d6d797c2
+CT = c7d9687dd109de0c9bdcf59f082d86b566ea439119bbec9776fa36db27b2f84d1b8ab55e2fc89ab8
+
+Count = 166
+Adata = 29ed477994dd231d3a71157eb56d219d
+Payload = c77aae5fd09dc9bceee7428e0734d4b0556528396a58f909
+CT = 85472671b8e2f7da11e41f433e299fdd315c8c6ba534825c0e32058ea939036805a735198934a072
+
+Count = 167
+Adata = 494c8f931029a4919e2dcbc16512a8bf
+Payload = 1f47273103f265f963e498878361c06c01a5ffcfb630a161
+CT = 5d7aaf1f6b8d5b9f9ce7c54aba7c8b01659c5b9d795cda3437098c81475f8a1d8f3b0e63d499d387
+
+Count = 168
+Adata = 53200bc5d1f1fb0eeff02d2bc42f7d54
+Payload = a38231af405dc7b70c8dbc8cb84e6be8a0dc2e95fddc2ce8
+CT = e1bfb9812822f9d1f38ee14181532085c4e58ac732b057bd9d7317973878957e8fc1fa57a025a3e9
+
+Count = 169
+Adata = 61e0e28bf344a9a1b04b15156e06498e
+Payload = a0d3a94ba6bb3bedf38220d1cba7e91273ad19f9a1c436c0
+CT = e2ee2165cec4058b0c817d1cf2baa27f1794bdab6ea84d95b0aa1befae96e71b9d221673844b1cb7
+
+[Alen = 17]
+
+Key = 116f4855121d6aa53e8b8b43a2e23d468c8568c744f49de5
+Nonce = 924322a3ef0c64412f460a91b2
+
+Count = 170
+Adata = 03c2d22a3bb08bbb96b2811ce4b1110a83
+Payload = 1bd3b5db392402790be16e8d0a715453928f17f3384c13a7
+CT = ad736402626df0f9393fe4491eb812725ad39d6facf20b5b2f9340b0d48a17ae1cc71d7515e61ee9
+
+Count = 171
+Adata = f390387610741d560325b5d2010d8cd4a0
+Payload = c93aaa04279e451b6880ed7b7fdb3ca9e80ab76180434937
+CT = 7f9a7bdd7cd7b79b5a5e67bf6b127a8820563dfd14fd51cb717bae4c040561bcfcf80fd842ae8dd8
+
+Count = 172
+Adata = 891d7988a56415a7b433f463b1e80eaa62
+Payload = 2611612ccb5ffefaa73195509bb52c641472bca0dfd09d49
+CT = 90b1b0f590160c7a95ef1f948f7c6a45dc2e363c4b6e85b5bc9fb15d874feccb6b5f581fa470734f
+
+Count = 173
+Adata = 831c0fed5e600dd82d7d55669262a9a17d
+Payload = 08136e946e306cde0544ddc2f3f4a529c89c7b77a5e635c1
+CT = beb3bf4d35799e5e379a5706e73de30800c0f1eb31582d3da72589ee50d23f925f7998ab3ccac37f
+
+Count = 174
+Adata = 32ca9d412d4ef0e89928496e96c9de7f2e
+Payload = 695aaac402942de7d899cc3f741c7fb2b2d8247a7676cf29
+CT = dffa7b1d59dddf67ea4746fb60d539937a84aee6e2c8d7d555c0b608f331dca47c65f5c879f2d532
+
+Count = 175
+Adata = 0746b2e6149c7f55854e9ca3e6861bf0e9
+Payload = 8f958d796be0566512f0512dcebd2e12f3160b05b72ae955
+CT = 39355ca030a9a4e5202edbe9da7468333b4a81992394f1a9b039bd916e923e2fc1f7c60eb59916fd
+
+Count = 176
+Adata = 0e4cbd1c574d656112bf6e70a8f23347f0
+Payload = 367ecd1b71dfb96a84e2369f28705dfaebf0c73ed35d5364
+CT = 80de1cc22a964beab63cbc5b3cb91bdb23ac4da247e34b98ac07f2c0847069fe5be26e623033f532
+
+Count = 177
+Adata = 1a05ff12412bf728497536534c234901ce
+Payload = a9ccee975feb10f635d548a8502f7c8b6adbd2be74117257
+CT = 1f6c3f4e04a2e276070bc26c44e63aaaa2875822e0af6aabf4e66a2b210e5a03bb10ff2926ed8a48
+
+Count = 178
+Adata = 3bd063a51c71fab5aeb47e7f8f958d796b
+Payload = 7df6220599d6235eb450989b6f0cd6c96db62b0d13afc4f4
+CT = cb56f3dcc29fd1de868e125f7bc590e8a5eaa1918711dc08ec90169d0c5c11fff8f255fedb13a99a
+
+Count = 179
+Adata = f0d334e0a27c3d00d56b15c2ee426e6347
+Payload = 6f65a24344c32debaf9f8c3fa426fe0b139e8ad1c8b1fbbb
+CT = d9c5739a1f8adf6b9d4106fbb0efb82adbc2004d5c0fe347170141cf3f207c4f0fc1b0238477cfad
+
+[Alen = 18]
+
+Key = e67f3ba11282d61fe36e38cab7b559c2fd9cbe8bf7eb5863
+Nonce = a727ed373886dd872859b92ccd
+
+Count = 180
+Adata = 68d199e8fced02b7aeba31aa94068a25d27a
+Payload = d7a954dae563b93385c02c82e0143b6c17ce3067d8b54120
+CT = c6cfaa1f54d041089bd81f89197e57a53b2880cefc3f9d877e30b2bcc3f1ea9ec2b8f28bf0af4ecf
+
+Count = 181
+Adata = fc4bbe329a86089ebe2a2f3320dad55a9bda
+Payload = a206a1eb70a9d24bb5e72f314e7d91de074f59055653bdd2
+CT = b3605f2ec11a2a70abff1c3ab717fd172ba9e9ac72d961753a6e6844102d6bb86986c030765d3393
+
+Count = 182
+Adata = d8741e540330692d83cc806a8ac1c4742be6
+Payload = 56ef76dbec6b8b46f5b7b4e311c0baaa6fcf54c69c0b9c3b
+CT = 4789881e5dd8737debaf87e8e8aad6634329e46fb881409c3f92a80b1d82f8c1dc32bfe64adca12a
+
+Count = 183
+Adata = c8b1992dfba55b4ab86b480546c861655e1a
+Payload = 2729636112f2abe2c76ea5e52a3f80b0f882f0f3b6f7c806
+CT = 364f9da4a34153d9d97696eed355ec79d464405a927d14a12fb48ad162b0c0678674d79d26a6b5ef
+
+Count = 184
+Adata = 347e12eec56e95aafcc7d25bf10fc756b4e4
+Payload = dd433eb7422c7c4dccee57a1679633ced3b5f08df763d457
+CT = cc25c072f39f8476d2f664aa9efc5f07ff534024d3e908f081c7cd81c974d985bf24b7fe9542141a
+
+Count = 185
+Adata = 45b35a04d6e2645e9a5aef206ed4e36199c9
+Payload = 70523bc397417e09d791a4976960e02636ca7144a5681cf7
+CT = 6134c50626f28632c989979c900a8cef1a2cc1ed81e2c050a7f6a5c04e59896074e1594706ab27e9
+
+Count = 186
+Adata = 378b48531fe34f55125b2f14f59715dd6ef0
+Payload = 514cb462dd4b117f26cac22062fcbeb353650c71649a7b3d
+CT = 402a4aa76cf8e94438d2f12b9b96d27a7f83bcd84010a79aa9d16c3ab79276cff345444511940a9d
+
+Count = 187
+Adata = 73ed686d6fecdc031cd97653137f269d6537
+Payload = 7f0c2b261db3f3de0ce3a733f4b8c446c374567d96d00379
+CT = 6e6ad5e3ac000be512fb94380dd2a88fef92e6d4b25adfdef92bf8aa6facbe6f9607ea02b54a1bf0
+
+Count = 188
+Adata = 5b0441107e5560be94f030a41cedbdb116d9
+Payload = ebb3e2ad7803508ba46e81e220b1cff33ea8381504110e9f
+CT = fad51c68c9b0a8b0ba76b2e9d9dba33a124e88bc209bd238e4936ee93b5c7a302913292df33c1700
+
+Count = 189
+Adata = feedcc5f8524fe7d49bcd178415b9f4c450a
+Payload = 3216dce3b8b1ce0e79e40fffcac728ab191aaaf319d971d3
+CT = 237022260902363567fc3cf433ad446235fc1a5a3d53ad7493426b6193afe765a76b3dec00266e69
+
+[Alen = 19]
+
+Key = e0a29a2c7840cf9b41de49780b9ee92d646a4bfc5b9da74a
+Nonce = fc9fd876b1edded09f70b18824
+
+Count = 190
+Adata = 36e15baafa0002efbb4bb26503b7e3b79f6c68
+Payload = 344dc8b6bd66a1fbbe330a95af5dd2a8783dc264d6a9267d
+CT = 43b3b96aa5a54378f3bb573ffda3e154aa7f425fc3008175b60a77b9d38740356b544b1c0f259086
+
+Count = 191
+Adata = 712b788f0276e2b5a58be80f9114a12ab2a268
+Payload = 6d0546d4e95d1cfcb37a8f88a62064f5d95791311511535b
+CT = 1afb3708f19efe7ffef2d222f4de57090b15110a00b8f4535f750bb4cd42db3038e2c1622b72cea8
+
+Count = 192
+Adata = 07f77f114d7264a122a7e9db4fc8d091334a03
+Payload = 05024ce13b9057dd2c509db7dbcbd5585e4e64a1e2e380ff
+CT = 72fc3d3d2353b55e61d8c01d8935e6a48c0ce49af74a27f761e77b59ef7eeeae35bb53bb9543b64a
+
+Count = 193
+Adata = 899b036138cee77cd28382ba27984d858a6351
+Payload = 77b8e735b13b10e45e411ab94c6fe1a9eb89f0a7af40ff1a
+CT = 004696e9a9f8f26713c947131e91d25539cb709cbae9581244a60fdb473098a11b2176d37b2c4643
+
+Count = 194
+Adata = 4b000440a8484a5201cd54aec058919769772e
+Payload = 6b21800ae599a15254bb33f0bb080788fb6e9fa054bfd8b2
+CT = 1cdff1d6fd5a43d119336e5ae9f63474292c1f9b41167fba58d4afc30a7f672ea34e05ec1843d848
+
+Count = 195
+Adata = 73a222e681ed1ca47d92a6dd90625d895fbf29
+Payload = bfa9d9af6e1f32b6626a1cd89b1c32513b5b50a18ddab028
+CT = c857a87376dcd0352fe24172c9e201ade919d09a987317204ef270e0f3b5e3ca0b8440af65c76e85
+
+Count = 196
+Adata = 7109a3a36b286059bc1a1abb2767c92f884e3f
+Payload = c68b1bc0050e19780ab53efbea175634f70a7245d966966e
+CT = b1756a1c1dcdfbfb473d6351b8e965c82548f27ecccf3166ffb66991b38a0345fbbff5f2362f87de
+
+Count = 197
+Adata = cd15973753b94b77bb4b778de8b3b0cabbde85
+Payload = 4256f1c9b64390fe2120df9fd38e497c2903c2ca5679ab75
+CT = 35a88015ae80727d6ca8823581707a80fb4142f143d00c7dd033a087c44c2e44adbeb333aa9ded10
+
+Count = 198
+Adata = 6e5e0793855f7145e13a5872f563e5ec61cfd2
+Payload = bb0036b34b0c20094d335a8c74f6b3dea42eeccf4145192e
+CT = ccfe476f53cfc28a00bb072626088022766c6cf454ecbe26ff9c8713422fe38d5bbf2dedccbffe10
+
+Count = 199
+Adata = f844684f5404e7d8eedfa20394b40b4f5d910a
+Payload = 86afa9cdd743916563ebfd3adbdd56e015ea3a4ebc61cfe2
+CT = f151d811cf8073e62e63a0908923651cc7a8ba75a9c868eae75de56eabcf8e02c1a27705adef2732
+
+[Alen = 20]
+
+Key = 26d0a3a8509d97f81379d21981fe1a02c579121ab7356ca0
+Nonce = 8015c0f07a7acd4b1cbdd21b54
+
+Count = 200
+Adata = 093ed26ada5628cfb8cfc1391526b3bcc4af97d9
+Payload = 37ab2a0b7b69942278e21032fc83eba6cdc34f5285a8b711
+CT = a3a60b422eb070b499cf6da0a404b13a05cedda549c6b93e6ca0e07e04674f21a46df2659a5905fb
+
+Count = 201
+Adata = 7df13c9d2247aa40af7bbe2da98bd366d8b47b43
+Payload = 93925579b6367ff592ecbd59495fdeccb50f31ea4fa390bc
+CT = 079f7430e3ef9b6373c1c0cb11d884507d02a31d83cd9e93836597806f5da1d176c745d95c4fa46a
+
+Count = 202
+Adata = 7f369bbc99b6f08049eeb43566269a174829d4dd
+Payload = 8363aef9c7c34e1f8149de46c97d5ac79d38c6ed31ab1d12
+CT = 176e8fb0921aaa896064a3d491fa005b5535541afdc5133df826dda99111691993027628c70ff6ae
+
+Count = 203
+Adata = 04aa8442179f62babad0c006e36af0c21105f27a
+Payload = 17281acb525b13653000ab45d86e70106c10a93c99b18f76
+CT = 83253b820782f7f3d12dd6d780e92a8ca41d3bcb55df8159d074b018143a7ea1b5369b7f80eae20d
+
+Count = 204
+Adata = 997e646014f19a53beab8877ca6022bef23016f1
+Payload = 5d48a71557608736eded309027a80349a18e9ce5dee2bc6a
+CT = c945865c02b963a00cc04d027f2f59d569830e12128cb2455db17d3f75214c3cf39858617cfee57a
+
+Count = 205
+Adata = 60ffcb23d6b88e485b920af81d1083f6291d06ac
+Payload = 6c9d11cfb64d96bfab61c04a25d9e19294fb7330fb4847c8
+CT = f8903086e39472294a4cbdd87d5ebb0e5cf6e1c7372649e79550998376e61e11a5a69e9f8fe1c329
+
+Count = 206
+Adata = d574632658bf456dfbb11c2653602ed0f4dae777
+Payload = 7d41688c86d5e3bc53966810f2299fdd732e3471fb0a88f9
+CT = e94c49c5d30c072ab2bb1582aaaec541bb23a686376486d6a1b0d05a7ebc657c3235479893bf7e5d
+
+Count = 207
+Adata = d896ed60128f4bb0277d3af94c5138cf91697aa9
+Payload = 8c7ae2c3c503e9072d6e04e44c2ea78fd24994503567a136
+CT = 1877c38a90da0d91cc43797614a9fd131a4406a7f909af1980c98c8959c158ce209aebcbd554f250
+
+Count = 208
+Adata = a350ed58c04473e113b9088b1fb9dad92807f6b6
+Payload = 49bc9d3bcf3c22daa8cf55c1b59d4bffddc2412d60518e98
+CT = ddb1bc729ae5c64c49e22853ed1a116315cfd3daac3f80b7573175f9105cd16ee384465ebb232200
+
+Count = 209
+Adata = 1db5887001204194e8b5dcee92c8af8fa5f7321f
+Payload = 25f3788e0d3dd8f5821faa4e45a9d6b3995fd881f927135c
+CT = b1fe59c758e43c636332d7dc1d2e8c2f51524a7635491d732b67e993384f2e7229d1838efd040d99
+
+[Alen = 21]
+
+Key = aac60835c309d837aacc635931af95702a4784c214283ebb
+Nonce = 0e20602d4dc38baa1ebf94ded5
+
+Count = 210
+Adata = 796e55fbe7bed46d025599c258964a99574c523f6a
+Payload = e8610756528f75607b83926597ef515f4b32a8386437e6d4
+CT = e0a3d5f43e688ce104f4ae1a4fcd85500aa6b8fdbcd1b8d3003c0c3b7369e79339433e1754c0937f
+
+Count = 211
+Adata = 5170836711fcb1a350b087907d8a17c7637aa1595b
+Payload = c61b0c1845fa9b2e0013b3fa9a8cb4f4fbbc6846f63ed180
+CT = ced9deba291d62af7f648f8542ae60fbba2878832ed88f87120a7f18d021833b167bf330c4858239
+
+Count = 212
+Adata = 2a68e3fe746f593c1b97cb637079c3e5ee352c107a
+Payload = 10c654c78a9e3c0628f004b061e28c39a3c23e7250f53615
+CT = 18048665e679c587578738cfb9c05836e2562eb788136812ca9698d9a88e892c364e57dd35c2f17a
+
+Count = 213
+Adata = bf38ca0e89b8f5ccd29387f7f193ab5a967caa715b
+Payload = fa3a959fdff853c39f76da626094a1ea6dbc78bd2f091a79
+CT = f2f8473db31faa42e001e61db8b675e52c286878f7ef447ef3839d6f7e20a2e343f4c4da9eb9be13
+
+Count = 214
+Adata = bee00f2f75a4415ce993d2d14a6d8e01d1d59a48f6
+Payload = 76d12e3c4c5d990bf563c60aa4999e52998d887f97477f6d
+CT = 7e13fc9e20ba608a8a14fa757cbb4a5dd81998ba4fa1216a6630bfb7a2a2441e020efdf36274b72f
+
+Count = 215
+Adata = d5b614e4e8f72a5d8b1ec2b375da5dac64c2cc30b1
+Payload = 693fae7af84aa397f0b2baaed9b3c7953f75e7424c49b634
+CT = 61fd7cd894ad5a168fc586d10191139a7ee1f78794afe833866bcee343ec5aae61f9effa19b99d3b
+
+Count = 216
+Adata = 33f11aa36d8ab0fc53486839a576b31ee915dbd769
+Payload = 56ce9a09f38127b14dbbdcaa59f363c92a3b9843ad20e2b7
+CT = 5e0c48ab9f66de3032cce0d581d1b7c66baf888675c6bcb00331b60eb252f744a06b4a95aa9f4e7c
+
+Count = 217
+Adata = f40bce1a6817b29b9e8b56f214fcca7dfde17e7ee6
+Payload = 5cd8986e974d09ede34ba68fd81d6109a64092e7fbbaf87d
+CT = 541a4accfbaaf06c9c3c9af0003fb506e7d48222235ca67a4153778a644cb2469cef3ad125e257bc
+
+Count = 218
+Adata = 53c457d8d4d4ab95ba116c28b82c16743cb09de9fe
+Payload = 9c3c610f204d98702dd91ea28e0cc14830b26bb5e2ee0349
+CT = 94feb3ad4caa61f152ae22dd562e154771267b703a085d4e7013e1c34dbc5efc7bcd4f8e52797644
+
+Count = 219
+Adata = c7acf1b17609dc336df1006ffac6497777cdfd497c
+Payload = 90c5dd9db0316dac89db18f70491bdf0a06a6a7f72b77d9a
+CT = 98070f3fdcd6942df6ac2488dcb369ffe1fe7abaaa51239d66aed667c761b7dea44822e30cff671f
+
+[Alen = 22]
+
+Key = 671544bf2988056f7f9ccd526861391a27233793a23f811f
+Nonce = 0a259148a1d081e0df381ecd0c
+
+Count = 220
+Adata = 61dafc237cb52f83ab773ba8a885462b6f77d4924611
+Payload = 576b069ae2713f53d2924c1fd68f786cb2eec68892f9e1be
+CT = ce06b3d09b02921f290544032a081a7766612940048867281bb089af0245792c16e6320cf5ffa19e
+
+Count = 221
+Adata = 87e49b8164e7052becfa0c966991637b38df833fc5f7
+Payload = d7eb0d7dd737805cd3b8dbf451aeea2fa1f6a96eb58cb428
+CT = 4e86b837ae442d10282fd3e8ad298834757946a623fd32be3cec29bd5df92363d6bb75456f5cd32b
+
+Count = 222
+Adata = d302a518d7c625756d3e4c8cc2b1d973a19107c945fc
+Payload = 77d8c9e6321314524afd05b7ad599c29f4eedda9e9f0763f
+CT = eeb57cac4b60b91eb16a0dab51defe32206132617f81f0a901ca82cddb78a2fe3904d1d8bf6fe5b2
+
+Count = 223
+Adata = 6566bb616a94bb03df5c26b722bcd38d516285c5f6c1
+Payload = abbf28b3ae164051648293d0b94e11f5af8468450005c7c0
+CT = 32d29df9d765ed1d9f159bcc45c973ee7b0b878d96744156d095ad121f0f76f07b715cad996def52
+
+Count = 224
+Adata = 141be3601e38185a9fa1596d2ee406415c9673af32f5
+Payload = b67d50110f844b36a00d352123012a1123c7c3cba959dc48
+CT = 2f10e55b76f7e67a5b9a3d3ddf86480af7482c033f285ade8529ec8f477462dc2409482c3479756d
+
+Count = 225
+Adata = a2969243b0955402ab45a430fef2ef9e0c025006732b
+Payload = 2a63f7b09b43fee65738e8115bd8419b3ef3e8f86eca707f
+CT = b30e42fae23053aaacafe00da75f2380ea7c0730f8bbf6e9b14fe8dbb3c361ea61d7b44e689a1c48
+
+Count = 226
+Adata = 87faef55c54250c30232ccaf5efa1ff41b6243b2a5bc
+Payload = 59dad755af92c29522da4348ab9b3037fe87004f5fa1394a
+CT = c0b7621fd6e16fd9d94d4b54571c522c2a08ef87c9d0bfdc54f0659fae291f943f2f3b33688602cb
+
+Count = 227
+Adata = 5d895fb949344e603ce5de029842b20d2bb614ecbbb8
+Payload = 64d8bd3c646f76dc6ce89defd40777fe17316729e22ba90f
+CT = fdb508761d1cdb90977f95f3288015e5c3be88e1745a2f993af4e3a7a20390a8da264299712a34e3
+
+Count = 228
+Adata = 74cc8da150b0bacdefa8943900b4ea047611d96be70a
+Payload = 0c3c9a634a000f00be003846eac7482e303a5bef3a70fe75
+CT = 95512f293373a24c4597305a16402a35e4b5b427ac0178e3a7f79d2b5a9bde5bd453bc8a03e971d8
+
+Count = 229
+Adata = 65f6adbaaa803dbad5ba9cb6d231314d55147cc61399
+Payload = 712c788928c8a1562bc1f3f0eb1286e15c3405f6a6fa0443
+CT = e841cdc351bb0c1ad056fbec1795e4fa88bbea3e308b82d5ffccebfb8c833833db40e98a1950fb70
+
+[Alen = 23]
+
+Key = 90e2c63b6e5394b1aeec03f95a9d13a01a7d4e9d58610786
+Nonce = dada5465eb9b7229807a39e557
+
+Count = 230
+Adata = f5629ca0eea589f6cf963d875a7d2efb656983f2dd2231
+Payload = 44dd098b1f869d670a8a841900c4bef023a1946a0c278354
+CT = 6b38ca85450e05e7b9362ed7e6e291a130ff233b5a561cdef7ec84dd992fdf98514f845dac8f656e
+
+Count = 231
+Adata = d43d7753530a7280b76221906dca85d396b6cf05125018
+Payload = cea19562328bd1fea889f575db6a28a14b7d06fb9f9c98bb
+CT = e144566c6803497e1b355fbb3d4c07f05823b1aac9ed07313613ed15d527d9dc58ab6893e723db58
+
+Count = 232
+Adata = 75650ce366757618af20205b69af7e5d4e82c398c00101
+Payload = f0641f595b791edd860977fcf699688587a354e053e9c7fe
+CT = df81dc5701f1865d35b5dd3210bf47d494fde3b105985874ef8728d1bf3a2d93db3266bafadb7c26
+
+Count = 233
+Adata = c00f1b8066677c63e898fddfb8a1b482b536963da0628d
+Payload = c7486a084f8475e6f5138e8d6e9f42a1de90f05aa88a362d
+CT = e8ada906150ced6646af244388b96df0cdce470bfefba9a7a5bce94d7564d297fe87730f1a36acf4
+
+Count = 234
+Adata = 5a89ab6b26b2ca78f98a8f8409fe8008b97ba9ef185d41
+Payload = 091ef698e16dc43a11d3ea005d5a5cdb7f1bdb5665a6c81e
+CT = 26fb3596bbe55cbaa26f40cebb7c738a6c456c0733d75794cd971b07fc14c512b8df6dd964b129d0
+
+Count = 235
+Adata = 5d24d80f22afe713c4076c200c1bab36917907fde7b6d3
+Payload = 62f204394b367c4410746001e02dfd171858396568fdd43b
+CT = 4d17c73711bee4c4a3c8cacf060bd2460b068e343e8c4bb1a192b781dc94448d4a0f6a439a716339
+
+Count = 236
+Adata = 4a47a82b999a2a739959f153a091a65c4d7387646da66b
+Payload = ac1cd5ba4997af91dbd74aee7730f9ee92cf8a360ca96a8a
+CT = 83f916b4131f3711686be0209116d6bf81913d675ad8f500cade9533b272e0a3edeba68362b057b4
+
+Count = 237
+Adata = d9fc295082e8f48569eb073ac1b9566246728fc62ccaab
+Payload = d0a249a97b5f1486721a50d4c4ab3f5d674a0e29925d5bf2
+CT = ff478aa721d78c06c1a6fa1a228d100c7414b978c42cc4785d68df8ff28345be4d83541a72071059
+
+Count = 238
+Adata = 720a9dc3e33ac080775a06f67f4a6591c37d0e101944a0
+Payload = 77fb98f24172f5d5edadbf466ee910855a71d46090b789ee
+CT = 581e5bfc1bfa6d555e11158888cf3fd4492f6331c6c61664caa7ec8892be6a18458c663665495035
+
+Count = 239
+Adata = 13cdaaa4f5721c6d7e709cc048063cfb8b9d92e6425903
+Payload = 77fb98f24172f5d5edadbf466ee910855a71d46090b789ee
+CT = 581e5bfc1bfa6d555e11158888cf3fd4492f6331c6c61664862fda880e45e891a3a50da7e14344c8
+
+[Alen = 24]
+
+Key = 13cdaaa4f5721c6d7e709cc048063cfb8b9d92e6425903e6
+Nonce = f97b532259babac5322e9d9a79
+
+Count = 240
+Adata = ad6622279832502839a82348486d42e9b38626e8f06317c4
+Payload = d7c837971b973f5f651102bf8d032e7dcd10e306739a0d6c
+CT = 4709600418f2839841e6d126359f6982bdb53acc7ff209635623d15b24184481eadc63bb8c878fc4
+
+Count = 241
+Adata = ad4833aa53218949cfd724814a43889a74a2114bbef4cf37
+Payload = 7d672bccd0fb01ce79320ed61779146aa432038daa13cb41
+CT = eda67c5fd39ebd095dc5dd4fafe55395d497da47a67bcf4e614c3e546273f0aeef207bd3f4d32fca
+
+Count = 242
+Adata = 54a723826086c7175e8fdc854b62d780de6ac1f90b57dd3a
+Payload = 0e1b73df74982f535a5fb08bc13d22515ee10969efe033bb
+CT = 9eda244c77fd93947ea8631279a165ae2e44d0a3e38837b413c6395ce9aee2e22ac0606beb140185
+
+Count = 243
+Adata = bec02d7df4cc3deefdd7e7d3ea82d381c870ad46bc06d64f
+Payload = 9a55aff269b180118ff0ea99e851c7474d19d23e641f16a9
+CT = 0a94f8616ad43cd6ab07390050cd80b83dbc0bf4687712a661e4f02150bedd86dfa49f52b214239d
+
+Count = 244
+Adata = 1b8090d712e0ec95a01bc3aeb6f5230c67c355e0ed68043a
+Payload = ff19294e8faed8353dbcab0b146e2ef928dd2680833424bd
+CT = 6fd87edd8ccb64f2194b7892acf269065878ff4a8f5c20b2f0e82b9f04bfc0cc0ba432b5135450c2
+
+Count = 245
+Adata = 5ed0b9f25d07b26717cdcb2507bef9d681ecd9389831ac15
+Payload = db1eba6ac4a79aa1d97838d263c7c4ffa7d354770e762805
+CT = 4bdfedf9c7c22666fd8feb4bdb5b8300d7768dbd021e2c0a2e64c82b60880c5c7506321a1060a481
+
+Count = 246
+Adata = 55f16fefaf2168aebc61b5e01d9e1f7bfe215eaaef118974
+Payload = 012d45168505ca9fde5aed123875639a207d473b993dc7b8
+CT = 91ec128586607658faad3e8b80e9246550d89ef19555c3b77152f64dc993b36ad9d5d12bb52b1ad5
+
+Count = 247
+Adata = 9893bf14fd3a86c418a35c5667e642d5998507e396596c50
+Payload = b205f26d6c8a8d6085ab28d595703cae046f96d82093082b
+CT = 22c4a5fe6fef31a7a15cfb4c2dec7b5174ca4f122cfb0c243e5c69256b6326ebb7ee6e677d396765
+
+Count = 248
+Adata = 244b840085bda9576c8424bb05a925a6b09cad2d0528ab8d
+Payload = 549ba26a299391538b56ce4bd71dbbfd96995836f8915ca5
+CT = c45af5f92af62d94afa11dd26f81fc02e63c81fcf4f958aa2083dac565c7a63908f0022e2867bb68
+
+Count = 249
+Adata = 9e8d492c304cf6ad59102bca0e0b23620338c15fc9ecd1e9
+Payload = 9e9dbd78a1066800ae33253be6104015158a0187e4f38116
+CT = 0e5ceaeba263d4c78ac4f6a25e8c07ea652fd84de89b851968242fe32958ea32e670ae1b3543974f
+
+[Alen = 25]
+
+Key = 90851933d4d3257137984cdb9cba2ca737322dac4dbd64bc
+Nonce = be02df3a840322df8d448c600c
+
+Count = 250
+Adata = 69a9dd9ac8be489c3a3f7f070bdaca10699171f66ab3da9351
+Payload = ba1785a149cb8b69a4e011c11a3ff06f6d7218f525ac81b5
+CT = 89ab2efefa8406336d9e2245199fbc9454f0ef650b9ed0f446c7246bd3130803bf8d703ef5bdf15c
+
+Count = 251
+Adata = 0c39a72f0f38d2713c164b0f870646fc65b9838a322ecfddd0
+Payload = 263dc4fb5cd8798ce0f183a816e51fafba167533dde1bf96
+CT = 15816fa4ef97f4d6298fb02c15455354839482a3f3d3eed7096a6a4422e582c5d02973952ac80e5f
+
+Count = 252
+Adata = 911d9f5c4c34c2f4b69be1e253d43fe729e2ab2622130394b1
+Payload = 7b5da2c283116713f3d80c7907114270964541e03ab80d50
+CT = 48e1099d305eea493aa63ffd04b10e8bafc7b670148a5c115965f6df4332fe7a2cdc4d1b80e28a34
+
+Count = 253
+Adata = 8a961df9c23f6d5ecdafa94c61164a22f460a1bf7415258d39
+Payload = 541a2b3ee25022c92fdc6783a6cbde90680ad3dc41868e5f
+CT = 67a68061511faf93e6a25407a56b926b5188244c6fb4df1e18bed174081b2170ffc6ab53b54c9ddb
+
+Count = 254
+Adata = cac7a248a4d4e96a9733627e247234995d6aa57e491498118a
+Payload = ebb2e893da9f32c363f98bc76fd14eda59e7cc620070f6d3
+CT = d80e43cc69d0bf99aa87b8436c71022160653bf22e42a792bac3d3a2b9ef6d4c8715f9a5c6fe8245
+
+Count = 255
+Adata = 41eacf70d05a6d0cdbdd38f197a52987def8fde37f332eebd9
+Payload = 199cca0d0e1c70ec405d6816cbddc69f8ada624f2c168891
+CT = 2a206152bd53fdb689235b92c87d8a64b35895df0224d9d07f9610c82fe9a7c78e8f1980e886b446
+
+Count = 256
+Adata = 78b6ed20ed85337c969618bd41917cd85c37e7c35c3a12e25f
+Payload = ca481f557306f9ce386edd0cfde375a550cb5b574be524f7
+CT = f9f4b40ac0497494f110ee88fe43395e6949acc765d775b6aab366637ec41d0bf557f578be424a8b
+
+Count = 257
+Adata = 87faef55c54250c30232ccaf5efa1ff41b6243b2a5bc93e7cf
+Payload = 6f1b4ff66d3aec7b0c0d9e202acc52722e15bca0983291e0
+CT = 5ca7e4a9de756121c573ada4296c1e8917974b30b600c0a1e57a5b3ae26469d229425f887ad5a2a1
+
+Count = 258
+Adata = 7f19ac3e53a629a2df1cb56d68fde0c80a46be40a996830e2a
+Payload = 7533c88ce55c2243b64b6c5bd01aed4dd6ac8bb9fd333e06
+CT = 468f63d35613af197f355fdfd3baa1b6ef2e7c29d3016f476ce4fe492062f74bff4c3c0e9ea849a4
+
+Count = 259
+Adata = 0516a69bfd8785ad001367b51e5410b75c11b761be08b9eea5
+Payload = 19ea09a9bfd10db2a74e398859d8f4831fa5749767773acf
+CT = 2a56a2f60c9e80e86e300a0c5a78b8782627830749456b8ead47ffc17b871f530f62b9f9aec98509
+
+[Alen = 26]
+
+Key = 5c5d02c93faa74a848e5046fc52f236049e28cd8096dcac6
+Nonce = 54cbf2889437673b8875a0f567
+
+Count = 260
+Adata = 09fc21ac4a1f43de29621cacf3ad84e055c6b220721af7ce33bb
+Payload = b4da43ebfe9396b68f4689fba8837c68d0064841c6ddd4a7
+CT = d40725397229021a18f3481e3a85f70445557bb2a85e4ae8101a34c777e918e16186fda05a386572
+
+Count = 261
+Adata = 10f0c45d06a138a964fb11b2d450620a2977bcd2952afe371cad
+Payload = 7b628930d44e22907277db057395601b82b65479fbd59613
+CT = 1bbfefe258f4b63ce5c21ae0e193eb7717e5678a9556085cc1e79234882846d916dabae40b1bd055
+
+Count = 262
+Adata = 64dbb170a037b36beed28a2637c87830e2b23f8eea6cd9a7331c
+Payload = 9db30b669fc5d25f05e0dc708d597da6ddce2dacc85ae99c
+CT = fd6e6db4137f46f392551d951f5ff6ca489d1e5fa6d977d3e35499e3c09dc384eb41344ee8be3769
+
+Count = 263
+Adata = c47de6608546a02c6eebd6628c9123f6936c0154d3df52a367e5
+Payload = 62036cbed3666d85624d3dc9c1f437454b9ab5c03ce0de92
+CT = 02de0a6c5fdcf929f5f8fc2c53f2bc29dec98633526340ddd605189608ce40b237dde7bed6fde487
+
+Count = 264
+Adata = bab7e36098d59d3a31d7784d549aebfc6938bbd0612c85c0edb7
+Payload = 5c9bc739f6b6fe4214f3c6aad307d1f208892d79de010e37
+CT = 3c46a1eb7a0c6aee8346074f41015a9e9dda1e8ab0829078c31f69c847440be20bd08cfef330002f
+
+Count = 265
+Adata = 8a9716135fa38c250e249f6712f7cb3ad9210d7278b53d599df9
+Payload = 0df109298083d3896214b84ff6edb11e9cfdbd88f5702839
+CT = 6d2c6ffb0c394725f5a179aa64eb3a7209ae8e7b9bf3b676ca83622b127fa50fc9637998c0ddd44d
+
+Count = 266
+Adata = 2d52447d1244d2ebc28650e7b05654bad35b3a68eedc7f851530
+Payload = 518f651f6d82f670b63767ad8476ed8fc24df12a45110611
+CT = 315203cde13862dc2182a648167066e3571ec2d92b92985e81e738b9e4b0dc7b7a39eb7d03adc64a
+
+Count = 267
+Adata = 3cba0fd2bb16ae1d997cbe659a2dd101885c97f2322b0172b5d6
+Payload = e91a694bea2d351928b6098660d49f382c087f6777de159c
+CT = 89c70f996697a1b5bf03c863f2d21454b95b4c94195d8bd3d298c05b1d2e597f44f8621ecd11ed16
+
+Count = 268
+Adata = c7f93152016bba584dadc6002ec493a46305726068886d2340da
+Payload = 2d14792ed349a878b2b879e7fa5f438a50e36947ce827e73
+CT = 4dc91ffc5ff33cd4250db8026859c8e6c5b05ab4a001e03c5fd5221fceecbf0dc7211a1aec06793a
+
+Count = 269
+Adata = 799cac048eaccded37ca6a70dd89595e1ee04606212da5572679
+Payload = 315b8d95938d304015bbc94ea03c21f6dc25c90f991ba680
+CT = 5186eb471f37a4ec820e08ab323aaa9a4976fafcf79838cf5c25f00b862b49fcfe8447949f39787c
+
+[Alen = 27]
+
+Key = 0234dae5bd7ae66c67ff0c1a3f1a191a0d7bceb451bc2b7d
+Nonce = 16d345606a315ad2406abbcb43
+
+Count = 270
+Adata = c37fdf7449fd7e943595d75e977089c623be0a3926e63fdbbfdf4a
+Payload = 0f960a89a7e806f8709047cb7a2e7c4211ad724692c88a05
+CT = 3907880d25f910eab12dd14e704d1b33ea7c453634d54da2a461f44dac1112ae3f9c65671a931d3e
+
+Count = 271
+Adata = 85f647d940a6d1acb6b7851912f807063515631eaabaa019dcfb99
+Payload = ab40a4baa39b0e568bf2193fecbc36b84c76bb50523b2912
+CT = 9dd1263e218a18444a4f8fbae6df51c9b7a78c20f426eeb5ed15db6e142ee07b59eb5b0ad3a59194
+
+Count = 272
+Adata = 79ae14843b2e7ccf0fd85218184f7844fbb35e934476841b056b3a
+Payload = b74c06d9077c568762796d5be14f3563e7205a6e9bc65bcb
+CT = 81dd845d856d4095a3c4fbdeeb2c52121cf16d1e3ddb9c6c203f11f66b74366caeca8dbded2bf17a
+
+Count = 273
+Adata = 542d86fd7ff591f97e6926a090553538bc3b8a6bcd45f2e29c7d9f
+Payload = f2179beb5635a6d8a8340acea0ffcf4428e5de1306a8c12b
+CT = c486196fd424b0ca69899c4baa9ca835d334e963a0b5068ced925fb9a4cf6b6bf17f72ab044653d1
+
+Count = 274
+Adata = 4392c3043287dd096b43b4a37ea7f5dc1d298b0623ccbf4fd650a4
+Payload = d1a9e4593bc3d02c407e84a1736e587c1819c72195a07d57
+CT = e73866ddb9d2c63e81c31224790d3f0de3c8f05133bdbaf0d1f677deca1bfda83c1b9223aaaedbfc
+
+Count = 275
+Adata = 966954582e78e99ba68d6ffaf794b55a82325834ec4f373b2bd227
+Payload = 15b94910853a8f23dfb8b31c0262b8461f777075cc0937e9
+CT = 2328cb94072b99311e0525990801df37e4a647056a14f04e12937871932a7ca3e1e27a90a7f73694
+
+Count = 276
+Adata = b7aca715dcc402565cb711b001f21e8e95ec54c4afab2e2dcc8a2f
+Payload = fd1681cc306518bf77766f55226afac3eb21e31ed897075c
+CT = cb870348b2740eadb6cbf9d028099db210f0d46e7e8ac0fba0464ff4ddeccbd523a5ed3b32337f7c
+
+Count = 277
+Adata = 290a36f7daeeeafca4431446b396dbec0bea0a1f6f081418811656
+Payload = 0804fa48fc76f98bb021e3501bef8875b64a3b508adf8594
+CT = 3e9578cc7e67ef99719c75d5118cef044d9b0c202cc242332f68ed5e44a71c5ba8bade07b7bf5495
+
+Count = 278
+Adata = f0739a855422310a21ed863376bce9d75dc7c687b9b535cb7a05cc
+Payload = 4f5c6d80a3955f12f4d2594e02a045c42fabb11d90817fff
+CT = 79cdef0421844900356fcfcb08c322b5d47a866d369cb8583b5dc1fbe32743e257b7c1c9d624adc8
+
+Count = 279
+Adata = ffac0edb0b62977bb5040e4128a48deaf711f5e6a84d8f677341f3
+Payload = 5c29c458212d010a0d9c5a547aba1138eb4ce94742fef01e
+CT = 6ab846dca33c1718cc21ccd170d97649109dde37e4e337b9e53b654de1976294897cae0476ac6248
+
+[Alen = 28]
+
+Key = 6351a67fd6daabd2fd49ee944dd41dd37301f958dd17fcc3
+Nonce = b8d517b033754058128d13d11a
+
+Count = 280
+Adata = 511c6924fa96db716f6b053b7a48aebdc1504145a56cd02d6be2590d
+Payload = 0c0663dd69ccbffbbd0c8c2e9473d0354451ae7a20fa3695
+CT = 19f2745df5007619c79c84d174e4521b942776478a0601d982c560fede4741e2fd3b54b3a48f3e38
+
+Count = 281
+Adata = d9ccd93317441e9d6ccc358f31e7e2ccef8c921b23d742993eff9d53
+Payload = 34a882834172924d39d2df5d637d9d273a99a9222971701c
+CT = 215c9503ddbe5baf4342d7a283ea1f09eaef711f838d4750ee82d927a2aa678e792acdeb615409f8
+
+Count = 282
+Adata = c268d65f7a7b30d3d198b2045fc8d1db7adda56604fa567d8855d1a5
+Payload = 5b7450b73d68de079e92bba56c7860f11126b8fdedd3334d
+CT = 4e804737a1a417e5e402b35a8cefe2dfc15060c0472f04017a48226389d24ed3ec3da2da1a9bdf7c
+
+Count = 283
+Adata = 4c2b6815156f0643b4573825e28b9f2a668a4976e3342884f48bc310
+Payload = 140c6933248f052e05bd4a36aec185ee86730108cc2989b6
+CT = 01f87eb3b843cccc7f2d42c94e5607c05605d93566d5befa16fe6bd83993ccbdd50e1ca061f4845f
+
+Count = 284
+Adata = f11c873354b3c0cff2c8f8010e9e364582b9c05c62efdefbdcc2e1c0
+Payload = 2a083de317380d94dd991349a7b8761c7c98013b1b0227e0
+CT = 3ffc2a638bf4c476a7091bb6472ff432aceed906b1fe10ac577c5893cb3896400012e48f5b190b73
+
+Count = 285
+Adata = d0a056754098d7f7ef2f639d61ea3d2b9cc936c48a1b2c5a9e96d169
+Payload = 02769283d5a06c363c2cc66c09b1ac954134e3ec7df773f2
+CT = 17828503496ca5d446bcce93e9262ebb91423bd1d70b44be80c80101fdfe6dc4cfce080bf921582e
+
+Count = 286
+Adata = 56de0e55653b9a04a3ded71c31f8807c3c8dd96bc82892e4acccef30
+Payload = 4890404bc5b24822b4cf7a2fe28abc52fbefb919ae0629ec
+CT = 5d6457cb597e81c0ce5f72d0021d3e7c2b99612404fa1ea0122dfc20e3088dcd33b6706a0c1fdfa8
+
+Count = 287
+Adata = 794a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b425
+Payload = 161f8501f59338f72026815c77cad6d8d581859192cd5644
+CT = 03eb9281695ff1155ab689a3975d54f605f75dac3831610828f0a78ce798448529afe26eec875aa6
+
+Count = 288
+Adata = b1eafc03ea2fa3e9e3842a09a225e83055de8a1f412badd6fc9ead12
+Payload = b3f38aedbf08dd7ead9d402c5aaa1ec9279c7e4bfd4a2967
+CT = a6079d6d23c4149cd70d48d3ba3d9ce7f7eaa67657b61e2ba48856a266c0d404474316f418f8f4e4
+
+Count = 289
+Adata = 8fec99f1be0e69267620c0b934bf984d60c1437f74c6ac19610fe188
+Payload = 5c09e2a6a055fe9c21e06e5519cf56b8e2e7fb44094e79f9
+CT = 49fdf5263c99377e5b7066aaf958d49632912379a3b24eb56412292d8015285efaa6f1154580eb57
+
+[Alen = 29]
+
+Key = 9a5a9560baed3b8e0e90b92655d4e5f33889e5d7253d9f6c
+Nonce = c0049382cdd8646756d4e6bff5
+
+Count = 290
+Adata = c95a86d52088a8b0107cc5b437a8938b2c9e74e46e2e03bb9bceecdbe3
+Payload = 5bbe9c1fb2563e3e82999fe097b28da4dc6ff2e020f3b4f3
+CT = 6d5401db42b5c48b79203b6ad82806d7460ac4c82ad0809b811020480e834f6fe55900a162a4e61a
+
+Count = 291
+Adata = 1dd56442fa09a42890b1b4274b950770ea8beea2e048193dfa755a5943
+Payload = 8a85a9b32a323c6af156a3fa2f1448b6387cc3660aa8a0f4
+CT = bc6f3477dad1c6df0aef0770608ec3c5a219f54e008b949cba9827513c7f1de970d316b6f81c109d
+
+Count = 292
+Adata = c834096e059ea73ddc90b0c982f9a3a31bfc6b1b81a03f9d41c9c741e7
+Payload = 1e02c13104937fe084b18eba1ea8951dcc5e75b692937dea
+CT = 28e85cf5f47085557f082a3051321e6e563b439e98b04982c9d79dd3255a8323f8229ac1c6d76ae4
+
+Count = 293
+Adata = 9249022bdead3d86ef5bd03acf053132d08663ba1f2426e19c126b22e9
+Payload = 3225570fb15ae13a13c71e364ae9a9fef03d1c9a7fa5dfa0
+CT = 04cfcacb41b91b8fe87ebabc0573228d6a582ab27586ebc8425dc81f93257ae8399fc2d48b4a7685
+
+Count = 294
+Adata = 3c3a92c4ece49fb9f84243d7c1bc91f595fce118305a758c83985c34b4
+Payload = fa0a458174537ddba25708b8d0c22d5517d57b122517b0c9
+CT = cce0d84584b0876e59eeac329f58a6268db04d3a2f3484a1b595003c58e69600c2a3b9ec45c0e15a
+
+Count = 295
+Adata = b49b845ccf76acf508f9db8543c73375d530d91f3b0e4ed70decfd2c2d
+Payload = b7fbdaeaa3ee1d0bbf5ec47898b069ec4ba6a140a3e83996
+CT = 8111472e530de7be44e760f2d72ae29fd1c39768a9cb0dfe0da009261c43c6640303696655e2981f
+
+Count = 296
+Adata = 3aabdf589eeb1709bb3d60b08bc71eaa3ffeba4e2903a5dbd8339aae85
+Payload = 9aea86b9fbd9bd4504ee2e25054942b33d3cdbd84215db7e
+CT = ac001b7d0b3a47f0ff578aaf4ad3c9c0a759edf04836ef16dfdcdbd4ad711c493d3176f032a02af0
+
+Count = 297
+Adata = 6a79879cd62bd1dbf9609897d2ebf2dc4dda43cc15fcb241aaa0deb4b3
+Payload = 3a861638ccd6591e51e2a525be59447e4a28bab32e36a5f3
+CT = 0c6c8bfc3c35a3abaa5b01aff1c3cf0dd04d8c9b2415919bfd59b45c05873c670f5f8bb47732d59f
+
+Count = 298
+Adata = c5b6ca474eb251817ae4d2f47c0632c381e222aae3b6f585a0dcae120a
+Payload = c7da4e9ba6e5758be726e6e227d7bddb0332228f7e3ecb6b
+CT = f130d35f56068f3e1c9f4268684d36a8995714a7741dff031572a24bc00b40a6b4b172b3648142e7
+
+Count = 299
+Adata = 64a96d191f1d5f95f5fed6259e33e7206adc07b0279e16cb453a9c6438
+Payload = 2b9347d3e195152dce22afdb92acd179eb484872285704c3
+CT = 1d79da171176ef98359b0b51dd365a0a712d7e5a227430ab828bc33396179ac39ce0027a1d62e0fe
+
+[Alen = 30]
+
+Key = 3e61094c80df0053e86d43fccf4e1d3ee2cdb862d3237b0a
+Nonce = 63f00b2488809fdc49ca5f05d5
+
+Count = 300
+Adata = a08763ca936abdeece06467bef8c3c47c3a473636a039d4db540c867d3e3
+Payload = 1fada8f4c7daea0d1c370184c169485b80a278708ed41451
+CT = 680dd22f16a1290bde42c9792dfa997aed24d5bd2265b6e095aa6b99d3f894d3790c2aa2dae1ba2c
+
+Count = 301
+Adata = 19508a6c83b992c660a1a28597e07c729ea2ed39401aadbf9d7586b5720d
+Payload = e9f1f2cf0b8d563e2d20f39f9f464a808b136dba364a6446
+CT = 9e518814daf69538ef553b6273d59ba1e695c0779afbc6f72d9d77109f4597e9c4c8cf7023dc5f3b
+
+Count = 302
+Adata = e5929c3b5d68a4c9fcf1168ea35bf8c0bf3043cb1ed54ff301578b3b7266
+Payload = 07a74c3b874849ecbf013713b80a84337c90b690cea0b837
+CT = 700736e056338aea7d74ffee5499551211161b5d62111a86b2544ecc3c7d5accd22ac075e7b44d5a
+
+Count = 303
+Adata = caa5cc5d0d87680eafc29429bac55c9e33167d485789c7c124b5c57a1ba8
+Payload = 4255f2cf90f0d15e9bead4be799165c57f7225980713d609
+CT = 35f58814418b1258599f1c439502b4e412f48855aba274b8f1a8a1db25de0fab7cabb11a18497584
+
+Count = 304
+Adata = f61cf7ae23a66777bd3fabc3d542feed2b00c6d4f46a772fda11b5214551
+Payload = 70b1e2e4cf260b108f5a52d0d8234838ffd6ffe7b4acd78d
+CT = 0711983f1e5dc8164d2f9a2d34b099199250522a181d753c5a9718ed0257a50e38de86154054fc3a
+
+Count = 305
+Adata = 85f647d940a6d1acb6b7851912f807063515631eaabaa019dcfb993e86f4
+Payload = af4be10b3a59ea99dadc75fbe5651f6f7630852bb556aa39
+CT = d8eb9bd0eb22299f18a9bd0609f6ce4e1bb628e619e70888550d1acca34c28ba8a3b890bb0542b23
+
+Count = 306
+Adata = 296cd04c4d9ab493def7aeb6841a45309e777028868efe45166235c56b2d
+Payload = 72d5663727592f1bfc9c65be83f4d3508126fecc4e34ae72
+CT = 05751cecf622ec1d3ee9ad436f670271eca05301e2850cc3a268dc1596a7855639c63fa76ad8479b
+
+Count = 307
+Adata = f380ca0a26a94adcf2c1ce26d226d3bf520268c72412e58a71acd9a66d00
+Payload = 3e2ccce03c10ce1527ef8e002adb265edba5779fbd4fcaf6
+CT = 498cb63bed6b0d13e59a46fdc648f77fb623da5211fe6847e3416c75fc28924a21cc123e62a7894c
+
+Count = 308
+Adata = 8825532a31680cb3b5bdb027802d2d8718755e135367e0c8c88e21288311
+Payload = a18dfe7f2d7bbaf316366f67445170afcbe18e2a1de1e947
+CT = d62d84a4fc0079f5d443a79aa8c2a18ea66723e7b1504bf6ff1a47f23d08485951aab18b393584ef
+
+Count = 309
+Adata = f768375589b687fb17c56673af4263626da69eb991007d94d4f5a163fd05
+Payload = 17ca72a440c944fefd6c08ecc3a8ecb54d96b9cad9d2aa4c
+CT = 606a087f91b287f83f19c0112f3b3d9420101407756308fd7d024456bcb69a4f77008773a3f48805
+
+[Alen = 31]
+
+Key = b5664dd6ed435df006052f6ded74bb7ce9482ca9229886f7
+Nonce = 7a1649896f3e030c18f0205599
+
+Count = 310
+Adata = c5f1a26351e53e6509c8bbbed03c42c23ad81c65fccec7ffa1cb494c7f1fc4
+Payload = 0b6de49b530703affc94010c2b793ddc6de0c44d48037ff2
+CT = 56b02fea595cc24e798691ae905be3d466ca68ca744005dba260b5ea3b047020b73b5bafa17e5084
+
+Count = 311
+Adata = 89899be18b4c389afa769b11ecd22e9fad8f38fd614ea5f8eb7a066c0ed8d8
+Payload = 2f1821aa57e5278ffd33c17d46615b77363149dbc9847041
+CT = 72c5eadb5dbee66e782151dffd43857f3d1be55cf5c70a685e4bd97b9dc83134867c00c2acea0aaf
+
+Count = 312
+Adata = d43b841f174335f1347834590b0984a2cb35f7a00a0ee993157d2d4f848748
+Payload = c7da4e95cb38342c6d5bf0c381d5a192adc3bfc1cda3a1d7
+CT = 9a0785e4c163f5cde84960613af77f9aa6e91346f1e0dbfe55202ba34bb9918fe915776de65947c0
+
+Count = 313
+Adata = c1093518efd80245e3c42371f220b21f2034e6738fe02ef43e828190f01aef
+Payload = 414a70aba5a219dbd41cdc46b84812b28cc4f7399218004d
+CT = 1c97bbdaaff9d83a510e4ce4036accba87ee5bbeae5b7a642fdf807b5a6880f2d4c36d558b40eb90
+
+Count = 314
+Adata = 90f627d5b939625bc76fe1bd4643b39edc11d3dc7f4bfe16e61bc26c3d49d8
+Payload = 58b260d3f645a35bad7a3842440bc03608248bd46e725e60
+CT = 056faba2fc1e62ba2868a8e0ff291e3e030e2753523124495a9307ca4239380a45bb7f87e41c4cf7
+
+Count = 315
+Adata = 2f360a4715074e942244ab7f9b6db127b0442df9af2efa2e78db1a94312905
+Payload = 5505caa97218957e90247fde60275bdafce4b16bcb36c263
+CT = 08d801d87843549f1536ef7cdb0585d2f7ce1decf775b84af3aeadff9dd60468aef2a8e2c56dda7d
+
+Count = 316
+Adata = 7db564811f14bc5c2098d5635655c3671fbd8288ea14944af925eaec653408
+Payload = b93e40f556a786e39126b8834a6ecacd2dc9f0f528bab135
+CT = e4e38b845cfc470214342821f14c14c526e35c7214f9cb1c8335f2e31a0468b830c5009cd02dbd5f
+
+Count = 317
+Adata = 36be91854d3d02a5d62503bb9047ef4354280510f7576c4272fd757240b621
+Payload = 543a070fdb3a855dd7d83fbc5f983671ad9e905f307148e4
+CT = 09e7cc7ed16144bc52caaf1ee4bae879a6b43cd80c3232cd5d772a599e91504e022b9dbfb124b71a
+
+Count = 318
+Adata = 6aa6ea668df60b0db85592d0a819c9df9e1099916272aafb8813ccc2f2dd96
+Payload = 86ef67572cb339c6706eb5909b96848aba5246a196972a1e
+CT = db32ac2626e8f827f57c253220b45a82b178ea26aad450379846cd12430f7adc910d1f0c51d80636
+
+Count = 319
+Adata = 3a64414c3588d7c26871d7d054ac6c8420d4917e3baad4a343685916265321
+Payload = cecef24b62676a5623bedae8087b9b05d7e22b41a14dd2d5
+CT = 9313393a683cabb7a6ac4a4ab359450ddcc887c69d0ea8fcd9ee65ac3a8fae1b00a4f1dfe2577293
+
+[Alen = 32]
+
+Key = 50925853a84a33ff392154e4e737efc18dcfc98f4d5235a9
+Nonce = 809343e986f6ff47f54d4cac22
+
+Count = 320
+Adata = d70aef3532bdc5293a3ebb11589ac1f801c9f93ea0d656e1d04068facf9f768b
+Payload = 718f061e8b972a3adcf465d66c5b28e8661f080127f6722f
+CT = bad3b0e6772e9c4c9c631c095e259d99692292932efb72b8966e91a19617bb748f3495aa433585bb
+
+Count = 321
+Adata = 1ee0eb409398bc252175cb460ef9a2da4c9beab2ef6d8206e4fcce74df785246
+Payload = 72e6cebdaf88205c4e74428664bc0d7eb4687a272217b7ca
+CT = b9ba78455331962a0ee33b5956c2b80fbb55e0b52b1ab75dc8f70aa565a12ca3545e68110968040f
+
+Count = 322
+Adata = 3820db475c7cb04a0f74d8e449f026ec951fa59667738698b0ed5c8cb09a8c96
+Payload = d959dd38a458039e2400d21d27b9a2faee8fe23683330cb5
+CT = 12056bc058e1b5e86497abc215c7178be1b278a48a3e0c22daf38076c810e14a7843444a02f010e0
+
+Count = 323
+Adata = f555216840a1f40b411d44128e567617e2694caf16216ea74c604a8d6ec01e72
+Payload = 337f12e8ebc0544b82fcdd3c4a0dab0e5e75c9f433a27d66
+CT = f823a4101779e23dc26ba4e378731e7f514853663aaf7df1594aebf9b8318877bdec2900a22df858
+
+Count = 324
+Adata = 2311a6fe1feeda3a1f16310d635496c0dd662024f0b0f1de79325e030cb850e5
+Payload = 463c65fa7becae5605af80d1feca59075ee88c0abfc72cb4
+CT = 8d60d302875518204538f90eccb4ec7651d51698b6ca2c231d9872d1c10a6594b5c349b84f710d64
+
+Count = 325
+Adata = b2c633e3181ae5fe7828707ed5b70e0460088a84465eadeecdbcfa0e9ff19bb1
+Payload = 23c1732959c4bf85bc707e45cc964b6227acd3a8fc73e675
+CT = e89dc5d1a57d09f3fce7079afee8fe132891493af57ee6e2a9db7c4bcaf6087e158c1a5d4eb1c2cc
+
+Count = 326
+Adata = 791f23252094b9b99fafe7fac1d8ff3ba09305c476041e75afb245ac438b4069
+Payload = 02f60f967e7fbcf957313619882407ea8a03fc943062296c
+CT = c9aab96e82c60a8f17a64fc6ba5ab29b853e6606396f29fb5e1c87d9e1c1f3b7d30fdc2f0ccac783
+
+Count = 327
+Adata = 22197f9ad14591e7a6d5f8b18c969a553de9a85309757fa5d319cc505c24f438
+Payload = 6c1aa088d1a6086d0e72636744a6840c80ab8223409c61b7
+CT = a74616702d1fbe1b4ee51ab876d8317d8f9618b1499161201514b449a741e07f9287f7e9090fa54b
+
+Count = 328
+Adata = 0bb18f7280a30767cd769cb5ffd3edd1c18914b92d1b2192e27ac88f57135616
+Payload = 57275bc3b4d63b9b01b0b0760235c9785d45761cace23f1e
+CT = 9c7bed3b486f8ded4127c9a9304b7c095278ec8ea5ef3f892c889b610157e16e9f31558c669298a7
+
+Count = 329
+Adata = 3e5f0f32e27be18ca6f84de11e6e9c25fc0c4cb0cf83633eea1f033aa1373f3c
+Payload = eba27a27f0d4604a5296a41b3fe995c50c66bcba302d0447
+CT = 20feccdf0c6dd63c1201ddc40d9720b4035b2628392004d0fbe19321dc22c748a17aa5eda29d8cf3
diff --git a/lib/crypto/test/crypto_SUITE_data/VADT256.rsp b/lib/crypto/test/crypto_SUITE_data/VADT256.rsp
new file mode 100644
index 0000000000..af4f5c1df7
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VADT256.rsp
@@ -0,0 +1,1823 @@
+# CAVS 11.0
+# "CCM-VADT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Plen = 24
+Nlen = 13
+Tlen = 16
+
+[Alen = 0]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886df3ba3e6da3a1389
+Nonce = 72a60f345a1978fb40f28a2fa4
+
+Count = 0
+Adata = 00
+Payload = 30d56ff2a25b83fee791110fcaea48e41db7c7f098a81000
+CT = 55f068c0bbba8b598013dd1841fd740fda2902322148ab5e935753e601b79db4ae730b6ae3500731
+
+Count = 1
+Adata = 00
+Payload = e44b4307234281209bd41f89dbe2cc3fbf68e14df2f7fce4
+CT = 816e44353aa38987fc56d39e50f5f0d478f6248f4b1747ba003abc6a4b020625adc8b6cd7bafbd42
+
+Count = 2
+Adata = 00
+Payload = 8db7a73856bcb4007346bb3e00096f69e75e97c0bb960f3b
+CT = e892a00a4f5dbca714c477298b1e538220c052020276b465e7cfa7a208a8b3e6b6377236045df17d
+
+Count = 3
+Adata = 00
+Payload = 48f3ceda4fd390a7eb38f7f5bcd14310af6b5a557e676d44
+CT = 2dd6c9e8563298008cba3be237c67ffb68f59f97c787d61a81b39a0c55822e32042b4f8981021090
+
+Count = 4
+Adata = 00
+Payload = 7cdb2c9b167b3ae811289acf7dc1814bbe241f553447699f
+CT = 19fe2ba90f9a324f76aa56d8f6d6bda079bada978da7d2c1091117e2ad77db510d902038743b5a98
+
+Count = 5
+Adata = 00
+Payload = 41eacf70d05a6d0cdbdd38f197a52987def8fde37f332eeb
+CT = 24cfc842c9bb65abbc5ff4e61cb2156c19663821c6d395b5ac7379b8e51592b98e4874f4592278a8
+
+Count = 6
+Adata = 00
+Payload = bde9e3eb9f0c57302c9185b1cb912ef76d88f2f9c3b51e9a
+CT = d8cce4d986ed5f974b1349a64086121caa16373b7a55a5c4d08c1c902c4c2f078452dd6943b85028
+
+Count = 7
+Adata = 00
+Payload = 6f9ccc033c6bfbdfad4719ad033c927e2175727a9a021dc6
+CT = 0ab9cb31258af378cac5d5ba882bae95e6ebb7b823e2a69832fefb87445f1ca42811899acc0cdf68
+
+Count = 8
+Adata = 00
+Payload = cc67bc3b7afd625b2610226d3b30e111e6aa47a3254f711a
+CT = a942bb09631c6afc4192ee7ab027ddfa213482619cafca4481d605a1019c8e9778b8928b4636053e
+
+Count = 9
+Adata = 00
+Payload = a10c81725f49ab9075fbf4d96be030a2d881d8501b115d61
+CT = c429864046a8a337127938cee0f70c491f1f1d92a2f1e63f96a82e8411e5b04426dc608298c6408d
+
+[Alen = 1]
+
+Key = a4490ed6ab51dbfccd6f3702a857575dad44da3a27eaf31178abc97da60d1e4b
+Nonce = 26ceaf6e3b28190a17c4f0c378
+
+Count = 10
+Adata = 9e
+Payload = 1b5cc6b1651dec4bbbf5130343852e971c7ff1774100d9be
+CT = 789bce069a725a96c484e64a9e54dcb7a7c268c85df47815a462ff2dd8ba44a381e1f6edab12b5a9
+
+Count = 11
+Adata = 4e
+Payload = e7ab98901c0cb1d7d76e125d8ac8e86edf6f469fa937bc10
+CT = 846c9027e363070aa81fe71457191a4e64d2df20b5c31dbb6b0789c5866b7e3312ad992e228d6d20
+
+Count = 12
+Adata = cc
+Payload = 53bc7e3648d0b389b887b065e9e8f79685beb2eb36e2eb95
+CT = 307b7681b7bf0554c7f6452c343905b63e032b542a164a3e39b1b1a480fdd268c1c75b131cde798b
+
+Count = 13
+Adata = 45
+Payload = 6d7262476da95db63b322c5193ea05030923c3cbf0f8e8b1
+CT = 0eb56af092c6eb6b4443d9184e3bf723b29e5a74ec0c491a32060fea35c3e9528fd18994fae9fce8
+
+Count = 14
+Adata = 2c
+Payload = 8246bf7b81b287411777df7ecb53a1795e54b150ff3dd584
+CT = e181b7cc7edd319c68062a3716825359e5e928efe3c9742fb4e0a604ab30a764e8c98a9cafbca8d4
+
+Count = 15
+Adata = a9
+Payload = 2596ca8772bc69b50bcbf33088c6efbab614b691ed836f92
+CT = 4651c2308dd3df6874ba067955171d9a0da92f2ef177ce397ca72f1acf6dfd078b6f4eb82fa01e9b
+
+Count = 16
+Adata = 85
+Payload = 703065d701f4fcadee20d64300b3082c0c76490eb2dc4ba7
+CT = 13f76d60fe9b4a709151230add62fa0cb7cbd0b1ae28ea0c2a85c9252ee62612dc29cffa7289b2ca
+
+Count = 17
+Adata = dc
+Payload = a1aeda4b4cb8dd2943675181561bac48ba07e8de5b327837
+CT = c269d2fcb3d76bf43c16a4c88bca5e6801ba716147c6d99c9fbdac729413152c089d3939e30b8602
+
+Count = 18
+Adata = ce
+Payload = aa17341f4cead054d41c171dd34c459f7052da225c6c365d
+CT = c9d03ca8b3856689ab6de2540e9db7bfcbef439d409897f6f86266c273f8184e901b50c04845b8ab
+
+Count = 19
+Adata = a6
+Payload = 448cdd9cbbf863eb666fda36b825f3798827da3c1349611f
+CT = 274bd52b4497d536191e2f7f65f40159339a43830fbdc0b4ddd02d5c9ae2bbac47a7a076edb1d207
+
+[Alen = 2]
+
+Key = df594db94ef8eca56a417afe946085eaed444c7cc648d07d58132e6cb5bc2bc3
+Nonce = c1ad812bf2bbb2cdaee4636ee7
+
+Count = 20
+Adata = c0c3
+Payload = f4d7978fad36223623ccb5bb18a7373cba8a6e3b1c921259
+CT = bea778540a90033b2c0d087e3cc447711ea25f7eea96855506ec97f23bd6ea97834f92f7263c3195
+
+Count = 21
+Adata = 34b9
+Payload = f6c043c70136585d012ae0df6f42b25584e374649d0116c5
+CT = bcb0ac1ca69079500eeb5d1a4b21c21820cb45216b0581c9f3230df0b52b5cb7ac907dcadcb662ca
+
+Count = 22
+Adata = d4ab
+Payload = dec0c896b04490816409da1783478ef2510231d0a28c5b39
+CT = 94b0274d17e2b18c6bc867d2a724febff52a00955488cc35a99c3165ce83102891ef3885088ed6eb
+
+Count = 23
+Adata = 2a3a
+Payload = cbfd94fc31785d30214271dab2264134805fee6e52aa0b5c
+CT = 818d7b2796de7c3d2e83cc1f964531792477df2ba4ae9c50c9d8078607994ae5dff0de6526fb53d1
+
+Count = 24
+Adata = 4eb1
+Payload = 134d2d9726400d09dd3521326f96fbef993ddc0c40887700
+CT = 593dc24c81e62c04d2f49cf74bf58ba23d15ed49b68ce00c7e84da7d2564533e7ad55390ec3a6ff9
+
+Count = 25
+Adata = 0a79
+Payload = 1ccdcf789d42caba80d7893feaf26d3853fbcaf7d964df0b
+CT = 56bd20a33ae4ebb78f1634face911d75f7d3fbb22f604807520849295a56191367a696999ffef8e9
+
+Count = 26
+Adata = 865f
+Payload = 4042dbe148db3e6dc542b25d57a5787af535d38e8c34c71b
+CT = 0a32343aef7d1f60ca830f9873c60837511de2cb7a305017bc4aceed1a10309b6402b9e9420b33a3
+
+Count = 27
+Adata = f4ae
+Payload = 85b6894fec36294aa934cdc3523fd95c90ad56cbd18545dd
+CT = cfc666944b900847a6f57006765ca9113485678e2781d2d176c180d2e299ccf0b8781ba6de8a72ce
+
+Count = 28
+Adata = 10bf
+Payload = 0f27f4fc8538a676a763b3e5db845a1bfb20d5fab340dee3
+CT = 45571b27229e877ba8a20e20ffe72a565f08e4bf454449ef98d91c68d94873a5d6557611a5402a0a
+
+Count = 29
+Adata = b92e
+Payload = 1b5ec0cb03810a12fc6a0a1ff565afb001405d2a45a1f18a
+CT = 512e2f10a4272b1ff3abb7dad106dffda5686c6fb3a566865321cedf1122354636e130acbd69718b
+
+[Alen = 3]
+
+Key = d98193ab2a465e3fcd85651aaeca18b8e91489b73b7c7e93b518c4b5b81fc6ac
+Nonce = 2247dc7e2674e9e0a63fe70613
+
+Count = 30
+Adata = 4dc2f4
+Payload = edba7d6312144e90ec9eaace7576045a46e553dcb8ee5a98
+CT = 44b9ea727c847336fd739ad11f4b906b292edb810462f06ef59626ad5cdac2e4d4cb07b538a1fd8f
+
+Count = 31
+Adata = 2f3bf0
+Payload = 52a9626f5279c11e17e96f5dc5e1c1f58c1e913020d8499b
+CT = fbaaf57e3ce9fcb806045f42afdc55c4e3d5196d9c54e36ded0d53402253453e494ad350994ca77a
+
+Count = 32
+Adata = 95d2cf
+Payload = 87b6447d97a74d0b315031078aa06fffc7b9f246bfa5f147
+CT = 2eb5d36cf93770ad20bd0118e09dfbcea8727a1b03295bb196dbc3bff865a1d94b164df23d708e8e
+
+Count = 33
+Adata = 0caba9
+Payload = 1852848046706f2e274ba381a2bee1422df4f61d93219af7
+CT = b151139128e0528836a6939ec8837573423f7e402fad3001791b4469fe50d45f8efb81217cd68580
+
+Count = 34
+Adata = f8d459
+Payload = 99aac82fa66a15e4f76b76cf4590150999d5cf8468df7f42
+CT = 30a95f3ec8fa2842e68646d02fad8138f61e47d9d453d5b4587106da25012f92f01cc2db8d11ac29
+
+Count = 35
+Adata = e883dd
+Payload = 4e2f0f91990b855a00d27fbb2e8db7184cd82909de361b52
+CT = e72c9880f79bb8fc113f4fa444b023292313a15462bab1a464148536847290e4fdda7966fe6d5e3b
+
+Count = 36
+Adata = e45da4
+Payload = e558be3fd246170b294d18ffa708842242681890baf8bed9
+CT = 4c5b292ebcd62aad38a028e0cd3510132da390cd0674142fcc4cb33472825363940e2b26424b7802
+
+Count = 37
+Adata = 3b6fc8
+Payload = f8b284c2d851289275973fcd807fac5d8e5e3b6a75ba2ace
+CT = 51b113d3b6c11534647a0fd2ea42386ce195b337c9368038a99dd8dbe89b3ecf663eda1b0f92be7f
+
+Count = 38
+Adata = 043d68
+Payload = 8edf1eb90f0ad33be8a7c6446899e06addc10b3badc4ea25
+CT = 27dc89a8619aee9df94af65b02a4745bb20a8366114840d3dc4894c8fa0a1e1aa760acf9360042f5
+
+Count = 39
+Adata = e89257
+Payload = 8fe9a6bd82462c97f436d382d1ff971c95406b1a6c847d81
+CT = 26ea31acecd61131e5dbe39dbbc2032dfa8be347d008d777cdad1590fd8bf2d7ea919e60d0316566
+
+[Alen = 4]
+
+Key = 45c8afd7373cb0f6b092af3a633d9fd97c4ca378e19d75f9b74d089429726c29
+Nonce = fdb1fa230ae0b172ff98fc7496
+
+Count = 40
+Adata = 270981af
+Payload = 0b92adbb251dc29a67f0bb97f8e7160862b6c4e843d07fd9
+CT = 274e2faea3271ea6fa0494c1951f115b5491a893056c3ee4c76fc350e585277e373e9119bf9595cb
+
+Count = 41
+Adata = 633f3efa
+Payload = 1f88dfd4f5c52c22b1db47f9f4fb6e2f8bcd78d593061369
+CT = 33545dc173fff01e2c2f68af9903697cbdea14aed5ba52540fa7e55dc54e80488a05ee7f1fc96e9d
+
+Count = 42
+Adata = aad86fb5
+Payload = b2b4cb5e90ebf4bd265093b7f5efd4d62dc60e29737aa496
+CT = 9e68494b16d12881bba4bce19817d3851be1625235c6e5ab18151c17d9e3f97244000a3b2d3c2f95
+
+Count = 43
+Adata = ed42941a
+Payload = f312b47d05f8eb5a29943b41347cb1983c75cb7a458a3868
+CT = dfce366883c23766b46014175984b6cb0a52a7010336795562d521c4b5c7a6f2c5ac65f2fd15b066
+
+Count = 44
+Adata = e5b085d8
+Payload = e9fb86938ea7f04cc230296859e7c96fcc352f968c9473e4
+CT = c5270486089d2c705fc4063e341fce3cfa1243edca2832d9e491a31218f688744098851672a09a64
+
+Count = 45
+Adata = 3776f37f
+Payload = 8af6b7540f997954812e38dbd99ccfaedd5c69963c353a4e
+CT = a62a354189a3a5681cda178db464c8fdeb7b05ed7a897b730ece28347d7ebf8291d7eb66b7651b4e
+
+Count = 46
+Adata = 4eb08c9e
+Payload = b90cfd9dd58e320d98510483b1d939bdb5f3b81666ecee59
+CT = 95d07f8853b4ee3105a52bd5dc213eee83d4d46d2050af64cbd25fb40480d15c039878b5d2f25afb
+
+Count = 47
+Adata = c7f93152
+Payload = 02caabc6ed0641681e7148c10cf3159fe35e44013252071e
+CT = 2e1629d36b3c9d5483856797610b12ccd579287a74ee4623fbfd98c8567b78d4b9c3a49a4641908e
+
+Count = 48
+Adata = 57957630
+Payload = 2f29882fdf1418d04f0b9d44272995a56973c4369c687a99
+CT = 03f50a3a592ec4ecd2ffb2124ad192f65f54a84ddad43ba4655c1abcb3ed1a175f12721a407c5d00
+
+Count = 49
+Adata = 19da955d
+Payload = 4e427130be9e94639320529ec135715e65da1117b5ba3c76
+CT = 629ef32538a4485f0ed47dc8accd760d53fd7d6cf3067d4b90621a5e5683df421a0dc52341485d1b
+
+[Alen = 5]
+
+Key = a2e6bf39efd1ceddc92b4333ed92d65efeea6c031ca345adb93a7770a8039bcd
+Nonce = 693cbb46bc8366086ec7cd7776
+
+Count = 50
+Adata = 3ba11282d6
+Payload = d822f84b023f12ea9e3ce16b904278e4aaab5e11c2c23f3f
+CT = 9f91fd2f6472e33b02b1eabb9d6655729d44c44dad6b3883fe0667bcc5806b225224b04ade8b21c1
+
+Count = 51
+Adata = 3f3a4718ea
+Payload = af87b347b59e37a424004a00907dcbcf6a554e6782a9be12
+CT = e834b623d3d3c675b88d41d09d59e6595dbad43bed00b9aea6750fffa5a487540ce65770cd836e99
+
+Count = 52
+Adata = ff79ca8965
+Payload = 82b7cd168b6a82cb2d837f41ceda0c27adc5f5b28030454b
+CT = c504c872ed27731ab10e7491c3fe21b19a2a6feeef9942f7e7cfafe32bd71ea9813607c5df446c9d
+
+Count = 53
+Adata = 0021be18ed
+Payload = 1c1a0f144df76781e7c85ab178ed9b1ce8c6dc3f15c59149
+CT = 5ba90a702bba96507b45516175c9b68adf2946637a6c96f576716fe674c33ad3b9d3e54cc86bfccf
+
+Count = 54
+Adata = 9ae7996547
+Payload = d9bb71ad90152d5c1af358c8501fa89ebd4b17bf4ff43841
+CT = 9e0874c9f658dc8d867e53185d3b85088aa48de3205d3ffdab55dbee34f1bab555bbb196095fb5fd
+
+Count = 55
+Adata = fa292d1958
+Payload = fc7d028a1aa05c74b7ffe333ba6f676913b0f9f1ffa050b8
+CT = bbce07ee7cedada52b72e8e3b74b4aff245f63ad9009570476a4e9e759d5bb79c187a157099e3d12
+
+Count = 56
+Adata = 88800df7b6
+Payload = c9ea772e61742a6706da3ab3e81df14b31506ae58b063ece
+CT = 8e59724a0739dbb69a573163e539dcdd06bff0b9e4af39729f0f3699c9743ad6c9f09dc00ea10487
+
+Count = 57
+Adata = 715041afd4
+Payload = 70d2b8d64121ceccf1961444e8d33b7b7f998aeb58d3d270
+CT = 3761bdb2276c3f1d6d1b1f94e5f716ed487610b7377ad5cc560d78cba6d9f50e9c2677a710f92155
+
+Count = 58
+Adata = 14682301a9
+Payload = 1013946815001a2c08acca4196e0d6668ffbb3883cf111e7
+CT = 57a0910c734debfd9421c1919bc4fbf0b81429d45358165b95ffb6e29172a283d47e4478e2e1f7c4
+
+Count = 59
+Adata = e44c3c21c1
+Payload = f40dc834067bd163e0004d0ec5dd4b96e2a1ea31ea431c98
+CT = b3becd50603620b27c8d46dec8f96600d54e706d85ea1b24ccf233caf0bad9f68f71d78ee58512ec
+
+[Alen = 6]
+
+Key = c5a850167a5bfdf56636ce9e56e2952855504e35cc4f5d24ee5e168853be82d8
+Nonce = c45b165477e8bfa9ca3a1cd3ca
+
+Count = 60
+Adata = 4759557e9bab
+Payload = e758796d7db73bccb1697c42df691ac57974b40ca9186a43
+CT = 93ad58bd5f4f77ac4f92b0ae16c62489e4074c7f152e2ed8a88179e0d32f4928eff13b4ce2873338
+
+Count = 61
+Adata = 2ea07d393a0a
+Payload = ce60ddbe40b70bd55a9147036ad079dec1558ef4c2c625b3
+CT = ba95fc6e624f47b5a46a8befa37f47925c2676877ef06128b7d812c4d69f1f53ee9158382e56625b
+
+Count = 62
+Adata = aa6667faedc1
+Payload = 89eb3056770a6157f06921bc153834447c4b6d862d10d185
+CT = fd1e118655f22d370e92ed50dc970a08e13895f59126951e26fdbed62b228db008a1b14bd7942e12
+
+Count = 63
+Adata = 9e2127d92311
+Payload = 132f3e19e12f462a7463226b716c41a05a59c76f0e1a2f72
+CT = 67da1fc9c3d70a4a8a98ee87b8c37fecc72a3f1cb22c6be9124e1eb78de01b8af83b684baf3e43ad
+
+Count = 64
+Adata = 2f191bc9cff6
+Payload = b8611cbb9a3667b9458ca57eb636eb1dc580e7dbb5701692
+CT = cc943d6bb8ce2bd9bb7769927f99d55158f31fa809465209cb0f79736d1a810d06a776094f9fb67f
+
+Count = 65
+Adata = ad739d5f4736
+Payload = 112f89ccbdadc2433008d3ede2290f9ce81e5c736abf42a8
+CT = 65daa81c9f558e23cef31f012b8631d0756da400d6890633bfba2348f629471c232c9ff7e5f6f85a
+
+Count = 66
+Adata = 01acc909b7d3
+Payload = d47f2ff745de39a9055ad002de6334971fde480bef268b33
+CT = a08a0e27672675c9fba11cee17cc0adb82adb0785310cfa8c0f694d03ffed043787343827ea2603f
+
+Count = 67
+Adata = ce003c836a6f
+Payload = 13be365884b8a91a284ca24f70011e48794b51be275153b9
+CT = 674b1788a640e57ad6b76ea3b9ae2004e438a9cd9b671722279b553998a6fee0a86e177a448573a4
+
+Count = 68
+Adata = 6a759a4efd00
+Payload = d5c87c649579da3f632ba95cb0a07c924095e4bdd4e0376e
+CT = a13d5db4b781965f9dd065b0790f42dedde61cce68d673f54eeb434cca3ea719827417e94d6ed564
+
+Count = 69
+Adata = 02b84a26c773
+Payload = b7bc1580c68fd5d06c1bf75c31dad7a3e26d636d7eee20b9
+CT = c3493450e47799b092e03bb0f875e9ef7f1e9b1ec2d86422a74b5e4e2edb91fbbe722bfaf1500db4
+
+[Alen = 7]
+
+Key = ae8f93c3efe38e2af07e256961dd33028faa0716e5320a7ab319a10d2f4c5548
+Nonce = 6333bde218b784ccd8370492f7
+
+Count = 70
+Adata = 0b1fabdf2a4107
+Payload = bc9ca92a9c9919e39095d3e53fb148694620ae61227e0069
+CT = 45811b0c8f754bf03950e520cd4afc81c2e3eb8a11f4fd386d5a6e4b1fbee15d35939c721004502e
+
+Count = 71
+Adata = 2fc7f5c0ce052f
+Payload = f25a4ca20bbf4969bed6b93c1c77e3d7415f60fe3784216b
+CT = 0b47fe8418531b7a17138ff9ee8c573fc59c2515040edc3a24a68f98716190fb55f743a8bf62a085
+
+Count = 72
+Adata = 8a74412da3034b
+Payload = 3237bf953989d17c65a0fafd2bb1e32c237f98f55389e8f8
+CT = cb2a0db32a65836fcc65cc38d94a57c4a7bcdd1e600315a923afef7b4955d7d1e8f1abef9933bf9f
+
+Count = 73
+Adata = 7139f3c1d6cc36
+Payload = 55d86dc0423cfc2616ef996a3316e776707f8d25c985884a
+CT = acc5dfe651d0ae35bf2aafafc1ed539ef4bcc8cefa0f751b8e824c62632dff5cbc103d3060fbd174
+
+Count = 74
+Adata = af7a380f079aa1
+Payload = ac48398adb10292314973946f261ec39397442ca09b98dd8
+CT = 55558bacc8fc7b30bd520f83009a58d1bdb707213a33708980202d518ca871c9544f4a8c55fd8d20
+
+Count = 75
+Adata = e602abe8f72964
+Payload = 2fb78654e4395df8c37f260d74def234a3a4e3d2b1fe8614
+CT = d6aa3472f7d50feb6aba10c8862546dc2767a63982747b454b33ea6e4344033f74f513d1e41b82ae
+
+Count = 76
+Adata = 82741c5fd6e1df
+Payload = d488bdda400932de56a9f105f0e74ee79c2ed869faaadc31
+CT = 2d950ffc53e560cdff6cc7c0021cfa0f18ed9d82c920216073ccf18c7ea7dce79d0be1204c593234
+
+Count = 77
+Adata = 78f0cc22535402
+Payload = b22aba8d3e9f4b4bf006e26062de15daf94597731a600912
+CT = 4b3708ab2d73195859c3d4a59025a1327d86d29829eaf443b81b8af57b85093778690266e20e2fbb
+
+Count = 78
+Adata = 18e468139dd16f
+Payload = bd864f7b8efd6ed2b068f425482d449bf53a203ea88e1ca1
+CT = 449bfd5d9d113cc119adc2e0bad6f07371f965d59b04e1f09b94a857e7a0423ef6c9cbebde1f9c40
+
+Count = 79
+Adata = a6dab47c0fbfe1
+Payload = 47d9d18b6addc5f88986f0457b666faae59aba4fa3a02abb
+CT = bec463ad793197eb2043c680899ddb426159ffa4902ad7ea64718820065a739fbd3ba560a416895c
+
+[Alen = 8]
+
+Key = 548c2d1eb7d91e003633d4d9ff199e4a8447180edd89ac7867d25a1db288b5ce
+Nonce = 23b205bd6ff8ed0bab0c98999c
+
+Count = 80
+Adata = a6601111cd92c943
+Payload = 49fd5cbe4aff89dc3b8718f9ce545d612cbbebb289ecbf42
+CT = 3cfc6211e359ae322802fc9566f377b0dfe17d1dfe0878ebf2a9047e37cc0be1fab0006af8db8dc4
+
+Count = 81
+Adata = 96f0b7cd7439721d
+Payload = 94a95e945f660d1571b4d7d22709b000b45ff98b2129a4ae
+CT = e1a8603bf6c02afb623133be8fae9ad147056f2456cd6307106a430b04938e97f2e4cda81108ad3e
+
+Count = 82
+Adata = 2ee135dc2ddd9501
+Payload = aeed3aea01755c912213c8c276a2b75dad24f888a611efa3
+CT = dbec0445a8d37b7f31962caede059d8c5e7e6e27d1f5280ab2ab219c6c4952d52505cd9f904b0e04
+
+Count = 83
+Adata = 10c361934fd6ff77
+Payload = be1fcebea4c22a1d71e08047b028d7f4ccab0a6b8085d344
+CT = cb1ef0110d640df36265642b188ffd253ff19cc4f76114edfc1f7b2fe314faea28ab0dae349feb9c
+
+Count = 84
+Adata = 3f6c8a69917f7776
+Payload = 87680ac26fe1511e0f1f745aa4c2a5b9f6c0117dcf08feaa
+CT = f269346dc64776f01c9a90360c658f68059a87d2b8ec390308e529d64e786a29661cccddc0366f3b
+
+Count = 85
+Adata = 0f7a1426ff3b5ee1
+Payload = 9e004b072a27b085e59ca201c157c7d3c906a2c3b455c56e
+CT = eb0175a88381976bf619466d69f0ed023a5c346cc3b102c797c6510b85dfd097f3eac276aff00ba2
+
+Count = 86
+Adata = faa5bed84dcf168e
+Payload = a1bf47b15cd66e43daff420edf014a14b11994b97ada4030
+CT = d4be791ef57049adc97aa66277a660c5424302160d3e87998e522b6f13f99ecb553b6de845940907
+
+Count = 87
+Adata = 2851dae3cb3fcb1c
+Payload = 2d15734871adc63ff32d7002ab40c4a235a4d5fad223953f
+CT = 58144de7d80be1d1e0a8946e03e7ee73c6fe4355a5c752967a9ca39566189ee96c86462bfea78af5
+
+Count = 88
+Adata = 35a29c1bcbe2182f
+Payload = 5a84c4fdd47510fb7aebc0f79d7b625ccd0a96575740b8e6
+CT = 2f85fa527dd33715696e249b35dc488d3e5000f820a47f4fa613b5fbbe73a2df6c630a00ff4b1b92
+
+Count = 89
+Adata = 45820ae66c3e8e77
+Payload = 2052a94e1392dc1db0e89be19ea8f7379ee4cb607a914c89
+CT = 555397e1ba34fbf3a36d7f8d360fdde66dbe5dcf0d758b20d19feb067e9f6225376da21b4899d296
+
+[Alen = 9]
+
+Key = aab793e377a12484dbdd74c9b3a85c74c286e1cc498663fbd7c718b5633bb91a
+Nonce = 10022cddb323e88b3c08f95a0f
+
+Count = 90
+Adata = 82b8c736037ce2f2e8
+Payload = 7c0889854658d3408c5d8043aad2f4ae4a89449a36f8a3b8
+CT = 1044250f58857c69f72b5d3454d43949e5c02b3822970b280de1a3f7fc5d06cc30f06075f5504ed7
+
+Count = 91
+Adata = 8f2777ec4930f7e349
+Payload = bd845561f099500a6ff3fd09964dc3820f7ab48ba4ed04d5
+CT = d1c8f9ebee44ff231485207e684b0e65a033db29b082ac45835840df6fa96f5c972ac09d94148cbc
+
+Count = 92
+Adata = 5cab3b846870709569
+Payload = a6e09404fe60badfc63dc228057485e6f563ba82acdabd7c
+CT = caac388ee0bd15f6bd4b1f5ffb7248015a2ad520b8b515ec2f83ef84b299cfdb61d2b5039d536c3f
+
+Count = 93
+Adata = 0938f2e2ebb64f8af8
+Payload = 33404d7e0e620c1030b91020e33619c5f53d8b210fa86489
+CT = 5f0ce1f410bfa3394bcfcd571d30d4225a74e4831bc7cc19db04e655cbe22b9ea508d2a03757b97c
+
+Count = 94
+Adata = 82f78ca0e0da2b2d3a
+Payload = 617868ae91f705c6b583b5fd7e1e4086a1bb9f087a50bf50
+CT = 0d34c4248f2aaaefcef5688a80188d610ef2f0aa6e3f17c04bd88dc6985f819004c2b634c5303ed8
+
+Count = 95
+Adata = 401191aa3fd34abe87
+Payload = 949cdd7c2973d7519e7bca98b2c5947e6d8e91c90e632319
+CT = f8d071f637ae7878e50d17ef4cc35999c2c7fe6b1a0c8b894ff3572e4ebf78473760d8cb4b0366b4
+
+Count = 96
+Adata = 4df4377596d8987671
+Payload = f6720a0bd8705c70e0f923338965e810b3ea939bad652327
+CT = 9a3ea681c6adf3599b8ffe44776325f71ca3fc39b90a8bb7de95ec3eee17753e60fb3c0661bdd098
+
+Count = 97
+Adata = 6593194b9970545c5a
+Payload = de9b0556661e726f3e6e34515ff7196420fe61b4f38419f2
+CT = b2d7a9dc78c3dd464518e926a1f1d4838fb70e16e7ebb162b8590ff04f967e51fbd1be84f01b4dcb
+
+Count = 98
+Adata = ab2d432058b540ac72
+Payload = 6cad7f3b9f196839bbc5a7f755c09aa8e17c83d9cb8b3954
+CT = 00e1d3b181c4c710c0b37a80abc6574f4e35ec7bdfe491c471d67b75b2da855a12ffb24ddd64a048
+
+Count = 99
+Adata = 5dc631eeeacb5a0b0b
+Payload = 70a55aec1144357377612fd0bbc2c817f33465a656219957
+CT = 1ce9f6660f999a5a0c17f2a745c405f05c7d0a04424e31c71fc798dd16c1fadef607a9297cbfbfef
+
+[Alen = 10]
+
+Key = 06ac39896073a44283611a66ccab067e2dd2faa8da82ff9a45bb29e54d2e6e77
+Nonce = 6c7942c9819cf69b817bfcdb0a
+
+Count = 100
+Adata = 215e2a6c24325340fdec
+Payload = 3216dce3b8b1ce0e79e40fffcac728ab191aaaf319d971d3
+CT = c5b3b50ed8a7b7b96b02ba9464b6a2ff80e90548605699a63d70e6dffb31a376a1eb7f94526dca48
+
+Count = 101
+Adata = e0a29a2c7840cf9b41de
+Payload = 7e5e5710a693ebfa36335cf7965574740880acdddd13fb1a
+CT = 89fb3efdc685924d24d5e99c3824fe2091730366a49c136fcbf516608fe20e06bbff931e84683545
+
+Count = 102
+Adata = b8026fbada6339d84802
+Payload = 08c342a50aa23362622934dfab55d9b22c22c249ad08138c
+CT = ff662b486ab44ad570cf81b4052453e6b5d16df2d487fbf9d70eb14f3fa0229906b9e0360be3d3f9
+
+Count = 103
+Adata = 65f4b3a00c1c1ef39445
+Payload = e085aba85882c75d5e41559167731496cf17d3907894352a
+CT = 1720c2453894beea4ca7e0fac9029ec256e47c2b011bdd5f4184771199a427861bf17cd8401e794e
+
+Count = 104
+Adata = 96118dbfe53434d8aed8
+Payload = 710f890be2b8da77c1eff429ede9cc931d50f059748cbcb6
+CT = 86aae0e682aea3c0d3094142439846c784a35fe20d0354c34e20b2db52fde68f88bfb886fdcb2c47
+
+Count = 105
+Adata = cdf4b485d2e04709cf8f
+Payload = cda96efee4e188ab3048bc1904ac2c36ab018f2ab7602682
+CT = 3a0c071384f7f11c22ae0972aadda66232f22091ceefcef782ee3df38ddea8e269eb47e39900345e
+
+Count = 106
+Adata = 50e57e57cf8e49e3a4e6
+Payload = 3dc596d52e520779a50bcba3049388b340dbf6d0f2eb94cf
+CT = ca60ff384e447eceb7ed7ec8aae202e7d928596b8b647cba44aaac4ed86f687cfc031f22827725f1
+
+Count = 107
+Adata = 48c670f11ff7f74e7003
+Payload = a33105c0dccf8e3b687212a870af9f710462756705fe09b3
+CT = 54946c2dbcd9f78c7a94a7c3dede15259d91dadc7c71e1c6d75255006ac037d6a4d048f1fc338012
+
+Count = 108
+Adata = 465e3be6113a2fb2ee20
+Payload = 573ac2436158eb7dd9be981e3cfbe75d3a188ea9cf2b1ee2
+CT = a09fabae014e92cacb582d75928a6d09a3eb2112b6a4f6976c1da33a80bc8157cece1acf9400b2bb
+
+Count = 109
+Adata = ee4e10574faeae85e9b6
+Payload = ca35bdb54e73eac5a5200a296b3aba5f37c87349746102d4
+CT = 3d90d4582e659372b7c6bf42c54b300bae3bdcf20deeeaa165c1cb98da4a1a920ca1ed9a7b6ec514
+
+[Alen = 11]
+
+Key = 50412c6444bcf9829506ab019e98234af1541061557412740bc120b456052763
+Nonce = 85684f94c3702c5d870310166d
+
+Count = 110
+Adata = f706a3e09df95d3e21d2e0
+Payload = 6cdbd63f6d591f59776f828533b28e2453a214d1d0dd8a39
+CT = 8c8b4ae854a5d5c265b25e3b54bded9444cc454b3e0e6a24d6c05eaf406a5ebd578e19edd5227380
+
+Count = 111
+Adata = e46b25b9a41a858e87900a
+Payload = 100132c315bfc9c4fb93023f5d3500d7208a68acb4d2c630
+CT = f051ae142c43035fe94ede813a3a636737e439365a01262d5088446e42591c0ede68e82334d97cfa
+
+Count = 112
+Adata = 28d34b29afe6586fd9bf0e
+Payload = d5460c1db0d24dedc63c4c78ce6d1f0b2d46f3b01934525c
+CT = 351690ca892e8776d4e190c6a9627cbb3a28a22af7e7b2413eaaef2823f5ac3f313f560bd774d10e
+
+Count = 113
+Adata = 2852d4fd68a3e9e47d44a7
+Payload = d2d73b62e3b1c9ab75f3544ff8616741e0adbae84b8cf9d0
+CT = 3287a7b5da4d0330672e88f19f6e04f1f7c3eb72a55f19cd62d30d99bb7dadec34e2891c156a1f5d
+
+Count = 114
+Adata = ec1c17b2ab13d7c8ac874f
+Payload = 74796d78d6ad03634ed80800af530212baa7e5093651cedf
+CT = 9429f1afef51c9f85c05d4bec85c61a2adc9b493d8822ec241c9a05ebf9ed27792bbced83b5dc582
+
+Count = 115
+Adata = 4f1ab5ddb1c199e9a5daab
+Payload = fb432488b5d08d576a90f085181ad883407a6ce9ea29950a
+CT = 1b13b85f8c2c47cc784d2c3b7f15bb3357143d7304fa75171ffc24020e86b1314724104e6b57b3ce
+
+Count = 116
+Adata = 864e0e728aea856fae6c6d
+Payload = 2b82d96ed1778412378abe4e09c633acf3359b9709ae3dcb
+CT = cbd245b9e88b4e89255762f06ec9501ce45bca0de77dddd6539bbb0af8ecf77b4508533247b3501a
+
+Count = 117
+Adata = 21ee21a5ed0d75d0380a28
+Payload = 85143071241bb65261fe7afcc102416e59b9e46ee0c90073
+CT = 6544aca61de77cc97323a642a60d22de4ed7b5f40e1ae06ef8981ec6ce7c4687b178f2103fa8c8be
+
+Count = 118
+Adata = 2b63f7b676f13f45d103dd
+Payload = 185577b48237acbdaa3590b8057fe374f875ce829b62c98f
+CT = f805eb63bbcb6626b8e84c06627080c4ef1b9f1875b1299265d9d899c6b71c0ab3049ea1dbfaf6a9
+
+Count = 119
+Adata = a33e86d813c2c4ff3bab20
+Payload = f051beb936e60fd4f3bca31964f1ad3e6fa16dd27b65a6db
+CT = 1001226e0f1ac54fe1617fa703fece8e78cf3c4895b646c6b246474c4e79822f5fd55f2fb0067a40
+
+[Alen = 12]
+
+Key = 8a56588fe5e125237b6cdc30f940b8d88b2863ec501a0cb00b1abade1b5ce0ed
+Nonce = d80210b9f9776ea36dc0e0a787
+
+Count = 120
+Adata = e4296d1c8cf4ffc4b2635135
+Payload = c825952293e434ea866db558aaf486ef09a92bf366988f71
+CT = b8b3b15fdf6a4a0b5abc313afc769e4e8413bd887552583ede3ed995d1b70561c8e28a7b1a7e3dc8
+
+Count = 121
+Adata = d18bfcc1584eeb8695388ebe
+Payload = a1e0248355bfd1d881fb1a4798cda2f6f6ad513c69c5f9b4
+CT = d17600fe1931af395d2a9e25ce4fba577b17c7477a0f2efb561575f6743c5759494be59afa0c3e11
+
+Count = 122
+Adata = 14682301a99bf680805d1ffe
+Payload = ded135fcbf62219bfba2cba40c2d2cbe4815ddaac1342231
+CT = ae471181f3ec5f7a27734fc65aaf341fc5af4bd1d2fef57e34f689367228cbaf3cd76fb407109cf6
+
+Count = 123
+Adata = 8853aa2dfea9c4d370678bb6
+Payload = 12d3900c6c01968b8344762e0e883e5e219f42b052dc6215
+CT = 6245b471208fe86a5f95f24c580a26ffac25d4cb4116b55a2cacb7fc3856abcf759feb8dc0998ab1
+
+Count = 124
+Adata = c5d3b9c593c3185fe4b6d1bc
+Payload = 8c3c1193fe1a1ebad7e01a1eed1a32c08a0091b1c948e184
+CT = fcaa35eeb294605b0b319e7cbb982a6107ba07cada8236cb42a740cd3262424a2c3d77849ead6149
+
+Count = 125
+Adata = dfb9e8149b51f89b1ec00a8e
+Payload = 8219618b7728ac89237705ecf84012cc7c80293c4cf171d8
+CT = f28f45f63ba6d268ffa6818eaec20a6df13abf475f3ba69747d4dbe0f9415d40843070e1e93059eb
+
+Count = 126
+Adata = 08a4590d262e4dbcb7e23ffc
+Payload = b344b7dc239617fa51b9ea10a349e940c3163779f5284c9c
+CT = c3d293a16f18691b8d686e72f5cbf1e14eaca102e6e29bd31215b3dccba4ca5de64be7fab8a7a22c
+
+Count = 127
+Adata = 74aab7b5b96238710637c6e5
+Payload = 740d4b25ca7221d0826057701a6bfd66c50a82f010a57be8
+CT = 049b6f5886fc5f315eb1d3124ce9e5c748b0148b036faca734e09945ee44c95c7923d8b9249ade7b
+
+Count = 128
+Adata = 420aac47a3f212fffca40549
+Payload = 5d9000489186abdf4f0a2794f0222fcaa156fe6309c10f79
+CT = 2d062435dd08d53e93dba3f6a6a0376b2cec68181a0bd8360a568dd779526a0058d522af1dafde30
+
+Count = 129
+Adata = 6e80dd7f1badf3a1c9ab25c7
+Payload = ac2c44263363810bec3a309aa618b303e05099dfdbeb5c16
+CT = dcba605b7fedffea30ebb4f8f09aaba26dea0fa4c8218b59279442c88d612ed1a39ae0005f88155d
+
+[Alen = 13]
+
+Key = a4cc7e1c90f8684e6a5f95e6898ab4e3c194cb46e196d8228062b9f3fa744930
+Nonce = cdc2712e51c7f333d6bad78eee
+
+Count = 130
+Adata = 569c56b27268d3db54e728aac0
+Payload = 10d4cff95ef490923c9e0906880729d4d05412e7675cce76
+CT = be3ce3e9dc72499839a98ae52abb17415e8547687e8a3c7b8aaaac20d4c9276f2851cbba2b04d185
+
+Count = 131
+Adata = d75635b6450e43285fba966835
+Payload = c9db03e2efbab713b0b640421018d3971ffe2abd70fe8fa1
+CT = 67332ff26d3c6e19b581c3a1b2a4ed02912f7f3269287dacc121ff83891335dd1214ea6fc25f6a68
+
+Count = 132
+Adata = 70750acea6a05f8b7b425d262b
+Payload = add631ce5846ce71434aad4998f8e429aed430e7d38bdbb2
+CT = 033e1ddedac0177b467d2eaa3a44dabc20056568ca5d29bf549e71ec517cd65150f42b3cb53f936e
+
+Count = 133
+Adata = 2a567c7ec7edaa5a438ae3bb35
+Payload = a514d170422feb1d87bb7725a9e77cc6fc8afb45c2af6d90
+CT = 0bfcfd60c0a93217828cf4c60b5b4253725baecadb799f9d0e432ec394ddbb65205dc40a5a8e90a4
+
+Count = 134
+Adata = 0f8795385b805246a0a2573afc
+Payload = 79d8841ab83279724ce35e1a8abd4e158168dcf388ab4c3d
+CT = d730a80a3ab4a07849d4ddf9280170800fb9897c917dbe30926b0d977107a3918717f79b63f36b0a
+
+Count = 135
+Adata = 111d224c102b136159fbeb44a7
+Payload = 2edd498e54b23aab6f4fd7b3f22c4c787e3a4f1fb06c9ec7
+CT = 8035659ed634e3a16a785450509072edf0eb1a90a9ba6ccac2cd61599bb93db3dd3dabc12aa90932
+
+Count = 136
+Adata = df0821c9ea6ab329c626d11b4b
+Payload = 6e3e25db29da2c787bb37755ee770e2402fb8208da23389d
+CT = c0d609cbab5cf5727e84f4b64ccb30b18c2ad787c3f5ca90bd027ecd00cc6dc5ffd5d746d92281e9
+
+Count = 137
+Adata = aacaf4839c35338d6e2b47ac45
+Payload = d4ed4584678e982ace8664e77d0e55be356be558cead3755
+CT = 7a056994e5084120cbb1e704dfb26b2bbbbab0d7d77bc5583c01354a450eda2588be7578530e38c0
+
+Count = 138
+Adata = dc6eed3f8bd1b5563c1eeb9afa
+Payload = 4ebf00eadaf70711f630f5badf0214d8518a200afb0e5765
+CT = e0572cfa5871de1bf30776597dbe2a4ddf5b7585e2d8a5688d7a1d546e25ba026cd46556eb2c4b7e
+
+Count = 139
+Adata = fbfe7e910f242a78dd6e69a2ec
+Payload = 2729636112f2abe2c76ea5e52a3f80b0f882f0f3b6f7c806
+CT = 89c14f71907472e8c25926068883be257653a57caf213a0b0e951aee790239e7067ef37f497b4bf4
+
+[Alen = 14]
+
+Key = 347e12eec56e95aafcc7d25bf10fc756b4e42bc2e43da7f97df24331f27f1f5c
+Nonce = b8d517b033754058128d13d11a
+
+Count = 140
+Adata = 511c6924fa96db716f6b053b7a48
+Payload = ca88dddfc876a12f45f19562bc9ca250f43267ab251a7f34
+CT = eeedcfa8f5b5b48c1d7e277526eecb7294213b9f5785167ae949b93003dfe63c95c1d49edfb4de3f
+
+Count = 141
+Adata = 10c26d5939618189a9503623f55f
+Payload = de0c0d17c3950e7f8985b56d60623cbd010cd765da4df5ab
+CT = fa691f60fe561bdcd10a077afa10559f611f8b51a8d29ce585c32a90d77fed97eb0ac164ed616e1c
+
+Count = 142
+Adata = bc09c59d20e55a9e184d70af2c7c
+Payload = 2f35102d78a32fcde1cfb563ea8d310ecb83c146ab8de362
+CT = 0b50025a45603a6eb940077470ff582cab909d72d9128a2c180fdf5f63045f326057cf74fd4cee6b
+
+Count = 143
+Adata = b75887f13d6e8c4b35b27b965693
+Payload = a3fcce3420effdd6edb37271735a0d30c10c65233aee173f
+CT = 8799dc431d2ce875b53cc066e9286412a11f391748717e7134959a180fc2cf2ba99af21cc1bc8e5c
+
+Count = 144
+Adata = 603401a9b8ecde4d5c86b6107363
+Payload = 4ac918727e41b8c536484e3781c403e260c278712853508d
+CT = 6eac0a054382ad666ec7fc201bb66ac000d124455acc39c32ca2e5195dbd44f0a119538c95788510
+
+Count = 145
+Adata = 7206b06f306124ca3a302e84c5a6
+Payload = 97d770cbb2c42a552e450cc4e35e5668b2ff89cec735cc91
+CT = b3b262bc8f073ff676cabed3792c3f4ad2ecd5fab5aaa5df74a4e1198878a76291594b9826d4b563
+
+Count = 146
+Adata = b15efed90a5d1d62f545ac22af6e
+Payload = 86bb2ae50e36c72936240a74502172625cbca210cf285077
+CT = a2de389233f5d28a6eabb863ca531b403caffe24bdb73939ff5f993dcfbd048274da7439c0f9ef5a
+
+Count = 147
+Adata = c9eb714ed9858a8dc11a26ee3f00
+Payload = 0dc79993047fd6e7260aac4d847fdb4d16483f28b13b5f17
+CT = 29a28be439bcc3447e851e5a1e0db26f765b631cc3a436590e87710559a375ece6ef2953b6aa2542
+
+Count = 148
+Adata = 07ca22271e95cb48a872046822b7
+Payload = f950e96d65a55efb3be3a55daffb421afad1d5625e3440a1
+CT = dd35fb1a58664b58636c174a35892b389ac289562cab29ef998035c81716e2d1ed4b4d56ff18af5d
+
+Count = 149
+Adata = b65f6773516124317cfb4b1fcdf5
+Payload = e160e28e601a49d16db18f25410756b330b036c42e615fd6
+CT = c505f0f95dd95c72353e3d32db753f9150a36af05cfe36981ae73a9b6896d8fc1b8c0d772d632983
+
+[Alen = 15]
+
+Key = 520902aa27c16dee112812b2e685aa203aeb8b8633bd1bfc99728a482d96c1fe
+Nonce = ddf50502f414c1bf24888f1328
+
+Count = 150
+Adata = 22b4f8f1aac02a9b2ef785d0ff6f93
+Payload = 533fee7d2c7740db55770e48cb1b541d990ea3f8f08ed1a6
+CT = fc867b319e0e4ab45ec518a1b5dcec4f29982173f3abfd4d8a8f8d14d2bdac84c3737cfbd75b7c0b
+
+Count = 151
+Adata = d0a43de391d492746ecf322acd6e5b
+Payload = cced20b59a6b2c3c45ea6c87802440c9c47b1015e83d86c3
+CT = 6354b5f9281226534e587a6efee3f89b74ed929eeb18aa28fce59f5e6e3cee284b4cc747ff5ee13f
+
+Count = 152
+Adata = 3a789c06f87f05933c34a1cf9834a8
+Payload = 90939a4530181ad6900664f66bfc2ce0289432a0afe9babe
+CT = 3f2a0f09826110b99bb4721f153b94b29802b02baccc9655ddaef56d8255125f7c316c6c59ce779f
+
+Count = 153
+Adata = 785260973f112c56d9f891160c4c11
+Payload = 86cd926b9565b76a88fde73c31e9ac908ffd1e6ca30b59ce
+CT = 29740727271cbd05834ff1d54f2e14c23f6b9ce7a02e752555810cbcdf48f05d0a7808673c82d08d
+
+Count = 154
+Adata = bf6a144591c0ea7b10274fbd3345a1
+Payload = 6ecd1c1acc6290672f9cf639ed0cebcb21ed0c56f35a5ce3
+CT = c17489567e1b9a08242ee0d093cb5399917b8eddf07f700849e41e5d34a698ae1d96f16bc68da944
+
+Count = 155
+Adata = 7d9488b500d89a27f367f34a448a87
+Payload = b01e3f4fb5ee7501e8c2f4ccefb542ae20d7fd61a2c41c8b
+CT = 1fa7aa0307977f6ee370e2259172fafc90417feaa1e130601bc54e546d1a6fcf6187169feb1ea533
+
+Count = 156
+Adata = 060fc718e994edc7bac9962ca7f28d
+Payload = 22ab6a0daf953165dda864cceeeb782e275c0b072aedd284
+CT = 8d12ff411dec3b0ad61a7225902cc07c97ca898c29c8fe6ff2eb6c0ab42acf42985c721bfd576e71
+
+Count = 157
+Adata = cb6f96dd06015967279ade310a7401
+Payload = f96ed20b23c784015ff58f5f040798ca75e3b98045deca8e
+CT = 56d7474791be8e6e544799b67ac02098c5753b0b46fbe665ac502b8e65cc1329b6895afdd354f5db
+
+Count = 158
+Adata = 9aa6d501455019b4ef4c7fb789d22f
+Payload = 648a84813ca97aef4ab7e143ee29acb946388660f18eb671
+CT = cb3311cd8ed070804105f7aa90ee14ebf6ae04ebf2ab9a9a87e5f8a8148f21adf721477c36bd99ca
+
+Count = 159
+Adata = ebd1d12bbd14176a0d4080aa1edb89
+Payload = 32d71e59634126ac6c6156a80a0dfa0175b29e9f40a31696
+CT = 9d6e8b15d1382cc367d3404174ca4253c5241c1443863a7dda9ea0427522dbeaa509a11755434760
+
+[Alen = 16]
+
+Key = 57da1c2704219ed59abfdf04743a9a93c87a63d471818de0f1564b2db6421562
+Nonce = 4b60a47b7e90f622fa0bf803e1
+
+Count = 160
+Adata = 0ae8c012ff39753510df3ee80707e4e2
+Payload = ddc3c1aa73fb6de92bb4db138e26f3c2e0543ab4f5924871
+CT = daa8256d4753fdf9cfef876295badaba89b45cc497f54d220ec2c6fb687753bca4580adc6aa2f296
+
+Count = 161
+Adata = d5b22e7697ba70e00c7ef32709563f01
+Payload = 34270576724083e9989764d08a0d5c1b4738f34927a1e436
+CT = 334ce1b146e813f97ccc38a1919175632ed8953945c6e1658f30b9c8e380c98bb939a4e8a85af758
+
+Count = 162
+Adata = 6b4edef415763aabcef01863e8197aec
+Payload = 904fe88e7a8e76447a64b488ef84184d0f1ab1b67f0c5a7d
+CT = 97240c494e26e6549e3fe8f9f418313566fad7c61d6b5f2e53e80d8ccc687fd303f4cdef44b6e8b9
+
+Count = 163
+Adata = 4c099809061024c010a77e9621fc2bcf
+Payload = 51fe7bac8f3255f17f64fb9322210fb7d8da8e762498b233
+CT = 56959f6bbb9ac5e19b3fa7e239bd26cfb13ae80646ffb7600c635dac5b70338dac3f33ce16a99145
+
+Count = 164
+Adata = 9d329439588164d5a96675a85c07a039
+Payload = eab6dbc13bb92df36b1882df2b8f34c3cefa41f95717fbd7
+CT = eddd3f060f11bde38f43deae30131dbba71a27893570fe84f996e8163affb1494bb3c12eeadf16b6
+
+Count = 165
+Adata = b768fc3daf29ff9e8bd575072d986e99
+Payload = c44c9c287d3eac7c30570d9c4adf2e4857c598f7c54cd126
+CT = c32778ef49963c6cd40c51ed514307303e25fe87a72bd47598b4206a9622d5631751a497dfb1f662
+
+Count = 166
+Adata = 3efc7cc2d16bf82d2bcfbc559a09b2c9
+Payload = c11b9c9d7607f387359c0038d3e8ec4d527562ce63c3384c
+CT = c670785a42af6397d1c75c49c874c5353b9504be01a43d1f7dd300167d267ad700dea37fb475ecdd
+
+Count = 167
+Adata = 0ff89eff92a530b66684cd75a39481e7
+Payload = cc17904b166f28df82f57889f391159a4a308e752d714ee5
+CT = cb7c748c22c7b8cf66ae24f8e80d3ce223d0e8054f164bb6303e9c9bd0d8e4aac42894ca03d6ab06
+
+Count = 168
+Adata = fbd11bc75759f0461e796f6917aeb42b
+Payload = 6f97e595ea2f40612ea84a2097b974d235055fe1dae59403
+CT = 68fc0152de87d071caf316518c255daa5ce53991b88291500953f46e0e9cf1369e9eb018a4df3c09
+
+Count = 169
+Adata = b79940952f42537484aa2907c72dffa9
+Payload = a48cbf933b88c0ec5ddcdd8fcad186391c2cbef308607de5
+CT = a3e75b540f2050fcb98781fed14daf4175ccd8836a0778b68a1702dfa0cd9c290c5ff9c35cc83705
+
+[Alen = 17]
+
+Key = 9267ebc99ccf648b146cba3c251187e24a9947d806ceb0ced6894211641a1e0d
+Nonce = 9b7298950280e8762ecdc9bbe4
+
+Count = 170
+Adata = 5824689453bc406bf891b85e4576e38fe8
+Payload = 967daf12f16f166b7b5038f83a1cf0b980f5abf4c7746f2a
+CT = 7cfe2a7a54306eb8d8a63d3d1ae86794f9a2c22198b2cb4f10ca926f1a430c08c12e23db3d913e93
+
+Count = 171
+Adata = cd15973753b94b77bb4b778de8b3b0cabb
+Payload = c4a756f6024a9dceabf6e264fffff9c719217fb418141ac5
+CT = 2e24d39ea715e51d0800e7a1df0b6eea6076166147d2bea05d5b674fd15410cc235dba6d8c8d82a8
+
+Count = 172
+Adata = ed8540f7ce451c522c1ff5d2d1030d7b3f
+Payload = e0d5de7d1eace211c0e70859ff315ff485d1200c6dd13f93
+CT = 0a565b15bbf39ac263110d9cdfc5c8d9fc8649d932179bf688750b5f36c86e7eda9015e960a7471a
+
+Count = 173
+Adata = cbbecf92551a15f5cf00a5be4a50b0eb17
+Payload = 05a4a4ba28fe8876f9bcfa5ec60651fd3fd4732f22049bd5
+CT = ef2721d28da1f0a55a4aff9be6f2c6d046831afa7dc23fb0d5fa842209dbbc04c87965f78500fec1
+
+Count = 174
+Adata = 873ba7f8b71517ec50297b21cf94cdb7a5
+Payload = 9cdebaeee8690b68751070691f49593668a6de12d3a948b3
+CT = 765d3f864d3673bbd6e675ac3fbdce1b11f1b7c78c6fecd67d147edbe114bfdb3f3b9b37d5719ef5
+
+Count = 175
+Adata = ac087420feb1e1e8c2546c2a8b8a5af0d0
+Payload = 5672e61cf664d73918dc1ca84df1fce82db0e305a61d57b9
+CT = bcf16374533bafeabb2a196d6d056bc554e78ad0f9dbf3dc57b4c2bbc377937d15b3b89543e29d0e
+
+Count = 176
+Adata = a12c690568114fd7a677f49d74e84fc1a6
+Payload = 0f5452e6b51540cf219998590995cd7f8785fa40b4f217fc
+CT = e5d7d78e104a381c826f9d9c29615a52fed29395eb34b3992e6ca774074b47b59adabeaf8835582d
+
+Count = 177
+Adata = 7a78ddfe5afb2dc90ee4a600c2fc014b0f
+Payload = 9ad338cbfd1b52e6ae4178f05e00062274f8b0b25eae72f7
+CT = 7050bda358442a350db77d357ef4910f0dafd9670168d692bd320f48a7221537e3cbed5ac4154a56
+
+Count = 178
+Adata = 6053e466ed1f647a3cd88c4d2052ec00cb
+Payload = d17b8d556e83190c84d4a812957c64ffa7f336298f4e2c72
+CT = 3bf8083dcbdc61df2722add7b588f3d2dea45ffcd088881740574e201f9a26932a87c8d822505814
+
+Count = 179
+Adata = f7673e3beb526834d6507058fe62e34987
+Payload = 2eaef86b0f602364f86510eabc58bc9ad1e6f0a6f6df0b83
+CT = c42d7d03aa3f5bb75b93152f9cac2bb7a8b19973a919afe6837dfa3fdef2f012b6609de2ac5dd9d6
+
+[Alen = 18]
+
+Key = 7a855e1690ee638de01db43b37401dcd569c1ae03dc73dd0a917d0cadb5abc29
+Nonce = 8f160a873a1166c8b32bccbba7
+
+Count = 180
+Adata = 72674aca7eba2fc0eeafbd143c2c4d8aa6c8
+Payload = 33ae68ebb8010c6b3da6b9cb29fe9f8bd09b59ec39f4ce4b
+CT = b22afdf4f12c43ec23e01ac1215a3f5286059211207e957057e9a9203da74387a9468f8af5e27547
+
+Count = 181
+Adata = f7da3f100b80e2ade812f1700aab6b72f746
+Payload = dbb29817b86cb80e0d008742cedfbf52b236f15ee8cad50e
+CT = 5a360d08f141f78913462448c67b1f8be4a83aa3f1408e35a3985f12a49eac424a35c94645917e91
+
+Count = 182
+Adata = 4b05eaadf98505d0806c233b2cdcaf4254e8
+Payload = 145aa8cfd544a2f46bae1aa83cbdb3d21c3d1350078a3af4
+CT = 95de3dd09c69ed7375e8b9a23419130b4aa3d8ad1e0061cf4ab089a8724b87a1167180963d44ec65
+
+Count = 183
+Adata = 05a3aaa08b9a6aaeb84704431425d0e45a14
+Payload = 6b32e8906dc89194a69410b79cd041b62eb01afb28a3e10a
+CT = eab67d8f24e5de13b8d2b3bd9474e16f782ed1063129ba310a7d1520141892e140448292185c41c7
+
+Count = 184
+Adata = 74db01edc26a2d2044cb8eaad8b907b78863
+Payload = 545ed03588fd85a8bbfeee66d2082ae6f8e2f3c9dbd8725f
+CT = d5da452ac1d0ca2fa5b84d6cdaac8a3fae7c3834c252296472d3eee219d94bd788f62df4add5ec40
+
+Count = 185
+Adata = 5f2c6ddf5a2403e04dac8b2813c060b67e76
+Payload = 66dd5fd8611c551973a3d0c078ec2b4d39ad163d9168de3c
+CT = e759cac728311a9e6de573ca70488b946f33ddc088e28507c600496f4f8b1b7da118ee36d8cd57f8
+
+Count = 186
+Adata = a650a2a5e3c6f7c95614570aaefd0cdd9a42
+Payload = 6f364b3f778376cbf3f4b0b0c5350a8fa278f9d8c25faad6
+CT = eeb2de203eae394cedb213bacd91aa56f4e63225dbd5f1ed4710004d06ce7a7efbd19da4e3ce3cf7
+
+Count = 187
+Adata = 477c2484cf5c56b813313927be8387b1024f
+Payload = 3de4798d8ad84c460b92abc10b7f5e7c9fae46a1dd353687
+CT = bc60ec92c3f503c115d408cb03dbfea5c9308d5cc4bf6dbc304099641c4ec3dc2c54fdf4f48dbef2
+
+Count = 188
+Adata = 564e1df74aa2d7ee33b66cfeda810774e16c
+Payload = 7769b45fea11f530fb9a67f1b5b1964a34cfa32bbb03f4b1
+CT = f6ed2140a33cbab7e5dcc4fbbd153693625168d6a289af8a905c1b05e8945685f8688faea777eb43
+
+Count = 189
+Adata = d5e66502529b0045883d935e05acd242baa8
+Payload = 0c0a502b42f81b51806c7080a8155280f493f2922cdc7df8
+CT = 8d8ec5340bd554d69e2ad38aa0b1f259a20d396f355626c3ea5a3b6a8bafde4006b993cfb3b13557
+
+[Alen = 19]
+
+Key = 0ebdc6ddb4c502725dd6ee8da95d56a0d1044b4694d6ba8475a4434f23a8474f
+Nonce = fb717a8c82114477253acc14f6
+
+Count = 190
+Adata = 41e9d65632f74f449a6842d5e6c4a86ef83791
+Payload = c7360282c85484a5a33ab1c68dd70873ab4e74ffd4a62cd5
+CT = 2e961b3a2fa1609a4e6fd04bff6ac5e306ae2638706f997b42be2e2ba05c54b619850db5c9d684fe
+
+Count = 191
+Adata = 555304659bde926cb2553b8a4605251fcddd92
+Payload = 1332314d1cf783b9f64e0fa2d42d43d225da9fd5165b5f0a
+CT = fa9228f5fb0267861b1b6e2fa6908e42883acd12b292eaa4bbdee2605bc69601b1e83d1e7a0b400d
+
+Count = 192
+Adata = 69ea953dbb910ec589372d797c7379d3f3b9e9
+Payload = f264da8606ea429e0e25da3f2efafe28beaff05b42097369
+CT = 1bc4c33ee11fa6a1e370bbb25c4733b8134fa29ce6c0c6c7304611baf530932da7954f714514d228
+
+Count = 193
+Adata = d7186a67061319b44eedc0677ebf5d932d5bce
+Payload = c9ee6482144dc61c43041324a2c18ede370011cb4882b0c5
+CT = 204e7d3af3b82223ae5172a9d07c434e9ae0430cec4b056b6d1d44e26404b7324767f0b3f7486f8b
+
+Count = 194
+Adata = 38f37d5e2da017f1953ff3701be0b38809ba80
+Payload = 40524a4d32a711e7d5a59809878c318f42b6e2375b77b8a7
+CT = a9f253f5d552f5d838f0f984f531fc1fef56b0f0ffbe0d095453724d2db19f606c85d00e49b0bb38
+
+Count = 195
+Adata = b3b2d249cd3517555fa692bbe9116f069e7405
+Payload = 961c15bd7dc34cd5409c9e8869988676ec6845ecb0ee85fd
+CT = 7fbc0c059a36a8eaadc9ff051b254be64188172b142730536db1e4112fcd650e8c0f0f6fbf2d07e1
+
+Count = 196
+Adata = f5b5bcc38efaff01f69bd3a106dcfca3cc6414
+Payload = 879568ab9ebdea768a5459ced1d3181d822536c3d1ba38c3
+CT = 6e35711379480e4967013843a36ed58d2fc5640475738d6d1cedb29e68322e47ff9997f859257d98
+
+Count = 197
+Adata = a2098e3e23826e01f31107a208202f710eff00
+Payload = 47cb57599686716c75d7ecef5541d20fb908e6d98c39925a
+CT = ae6b4ee17173955398828d6227fc1f9f14e8b41e28f027f41c12bf2a3571ed672592b27e986e9058
+
+Count = 198
+Adata = 20a3d53e77201599540344c4e746c3ae3a5f84
+Payload = 4a8667b5ee09d3d4a6dca9a95f4ad406f1da94b846dcc6b8
+CT = a3267e0d09fc37eb4b89c8242df719965c3ac67fe2157316f12b2be8f5966d96602111c28f87b104
+
+Count = 199
+Adata = 92c592ead4b3f193cc36687593d4f0f412a5d5
+Payload = 1dc9e32ac4176f64bd78a6edd651ebeea3ba85dfcd8298a8
+CT = f469fa9223e28b5b502dc760a4ec267e0e5ad718694b2d06776df0a0cf048892e65bd8ad77cb2255
+
+[Alen = 20]
+
+Key = 2ff64bbec197a63315c2f328dcb4837d0cdc21a5d6f89ff1d97cb51195330cd8
+Nonce = a235f8ee3de9896b71910ac02c
+
+Count = 200
+Adata = 2b411bea57b51d10a4d2fb17ef0f204aa53cf112
+Payload = 4a17522da707b4b2587a0ae367a2cd2831bb593a18ef442a
+CT = 1bf122798bd8ee8e73391d589bd046a294d1615794e69cb9e6f3ba30143acbc3a1c1c6ec74333107
+
+Count = 201
+Adata = 0248359f8071143c3cc1d61882a3547a0b3d2175
+Payload = 4a6a7151465c2abd7e7fa1fd13019ad098b6ebcd190e96f7
+CT = 1b8c01056a837081553cb646ef73115a3ddcd3a095074e6436cb510c13a039f4df8cc26a942f9911
+
+Count = 202
+Adata = cca77bc4cf6c0abd3393dac3fbe90fbc8a1154f7
+Payload = a94f5ede43929d48d2c5a58c3262d9127d2ac3cb2fbd5768
+CT = f8a92e8a6f4dc774f986b237ce105298d840fba6a3b48ffb7fe0dedc2899dff81a251cff16bf5897
+
+Count = 203
+Adata = 9c082a84646c070bb11b7d6b92b62f06ee5b5b71
+Payload = 7303bd41cf47289a3111366d08e8e21548baf293052029eb
+CT = 22e5cd15e39872a61a5221d6f49a699fedd0cafe8929f17886c43ac23800de60a1fd2caef0f03261
+
+Count = 204
+Adata = 1c3ede1982a807a410ae1e21947bf430f8db7027
+Payload = fa9743a67978c20316cb91801d7789e350079aae3aadbd43
+CT = ab7133f255a7983f3d88863be1050269f56da2c3b6a465d026f7907e235c09d3322c4092d2e88f88
+
+Count = 205
+Adata = deb05a30a026ff66ce71e98afa62f0255aef84f5
+Payload = 99599b4042dcdb685350cdecfdf24992fd5b165670025d0c
+CT = c8bfeb146e0381547813da570180c21858312e3bfc0b859f6bb44a28c145d49f49f2821d4044e4b6
+
+Count = 206
+Adata = 93dd9b00a3353e5331338dcfcb7ca7e0bb873a4e
+Payload = 451101250ec6f26652249d59dc974b7361d571a8101cdfd3
+CT = 14f771712219a85a79678ae220e5c0f9c4bf49c59c1507400f7d20aa3d792d6a3ebc5ee0df2fd89c
+
+Count = 207
+Adata = 0855263860043207543c8c34648d53ec51c4f47e
+Payload = b2db87b7787531968d603098cb20ca7c438b4af72623fea9
+CT = e33df7e354aa6baaa6232723375241f6e6e1729aaa2a263a7ca4733f0208668b0a7879305e861d71
+
+Count = 208
+Adata = ee2d3a66deb3ebca867a902bb9202226ed516ded
+Payload = ca18ce38086223e63b4f0b616d110010f9e45eac42f2ba46
+CT = 9bfebe6c24bd79da100c1cda91638b9a5c8e66c1cefb62d5d76b482ff20429da8f60f0f863e1af50
+
+Count = 209
+Adata = 8e531aaea849addab6a83497cbc504f489505952
+Payload = 5717ed5da5b8aa806a18bfe979502bab6632c9428d3a7725
+CT = 06f19d098967f0bc415ba8528522a021c358f12f0133afb6aab66e1ac2346ef97850a4985c64b737
+
+[Alen = 21]
+
+Key = 24e9f08a9a007f9976919e10dc432002e2e078a339677f00105c72ed35633a3f
+Nonce = 15977424eeec0ec7f647e6c798
+
+Count = 210
+Adata = 2d838eb51a4bc69a001a18adf2084a680f02a3c5fc
+Payload = d3416a81b4246eb0bf8119a72a886bbc0ac9449c69f71d2f
+CT = e001a8fae390dc5d672cdd18f86a1f728158ec83a002050def9af5679edbcbb7db20ab6af30698db
+
+Count = 211
+Adata = d83ee7ce22fd1a2882d8d552346e4d7b3efdd67da4
+Payload = 22b6f10b482448626f6c7bebb14f1497896d071738133b4d
+CT = 11f633701f90fa8fb7c1bf5463ad605902fcaf08f1e6236fd435a5a38f84387f63b13407f65ec86c
+
+Count = 212
+Adata = 2d5537b24d0b0f7a45703c1e131656ec9edc12cdf7
+Payload = d60edc830be8207ffd9e9f646d3b4343b10b3d56acb89d44
+CT = e54e1ef85c5c929225335bdbbfd9378d3a9a9549654d85662ede8a705f8c988f55459542bd631b1c
+
+Count = 213
+Adata = 1a750eb326923412d94ccb35f5acd0f87415268178
+Payload = 716d3132f449a9def383978102ae50ed3ccae0cb346ba1df
+CT = 422df349a3fd1b332b2e533ed04c2423b75b48d4fd9eb9fd986de774a612230ce6c71449d26732ce
+
+Count = 214
+Adata = b10fc523bc4562d44edfe5956f93c15c4ab38bba3c
+Payload = 063c2ae2a15f26f979bf90657d20643e3184f1a9f75a3aad
+CT = 357ce899f6eb9414a11254daafc210f0ba1559b63eaf228fe710431005264fa7d3fc04bac50fc1ec
+
+Count = 215
+Adata = fe4f60ce9634e7dbc5e56204c4bf8aa9be577027ec
+Payload = bdc513e56a5bb70c02abc041af04d6e45e735d10cc88357f
+CT = 8e85d19e3def05e1da0604fe7de6a22ad5e2f50f057d2d5d5c13bea6ad0cad724e6cd02c89517ffc
+
+Count = 216
+Adata = 48f3ceda4fd390a7eb38f7f5bcd14310af6b5a557e
+Payload = 7dc5d8cd90ce2faf76bbd0d52e5ae11b310fc2b0051c4377
+CT = 4e851ab6c77a9d42ae16146afcb895d5ba9e6aafcce95b55d2a5531655aae01e249f213e0e04af0d
+
+Count = 217
+Adata = 199ec321d1d24d5408076912d6bb2b6f192d6b347f
+Payload = 66c2696edec26ba3d07bd3f485a0d6ce8a1b0a85b20083e7
+CT = 5582ab158976d94e08d6174b5742a200018aa29a7bf59bc52a127ef341345f9641b26e91265e1482
+
+Count = 218
+Adata = 8b013f5782d5d1af8dbd451a4202866095dac975fc
+Payload = f4da8ac3e8fe5ec6a5b6a2f27b68396e850b46a024d441f0
+CT = c79a48b8bf4aec2b7d1b664da98a4da00e9aeebfed2159d2a005ca13c4bf715c3b7b2782f799b23a
+
+Count = 219
+Adata = e320df32b71cc530e8493b12b9afbeabc255c5eb44
+Payload = 244891cb4af66cc8e99a3784a2e82475e51bd5c7fde67cf5
+CT = 170853b01d42de253137f33b700a50bb6e8a7dd8341364d704642aff9cb9288d49f0e567dd837e05
+
+[Alen = 22]
+
+Key = 0ec1b22b8df05dc92135d2dfbefed8ea81458f5ea1b801e8a218faf6cbdf1a79
+Nonce = 97ebcb8575bb58260208d5c227
+
+Count = 220
+Adata = a2f6337f86dd00d1a58448851e95d8c9bace4a5c8710
+Payload = 2f59d94d4ab8eeb84c2a6fefb7fb0a3ac059c1e1a65ae34a
+CT = 7ca0b1dbe34b0391e524b868b0af08b3e096917664d6aa2cabc1f9d0132394149c9062b74b82f04b
+
+Count = 221
+Adata = abf26b05558252c8e38c52b1ace087bbd1eb3d561239
+Payload = c25381853f73a3dc4195fdcbc45dfa1a40eb8324749adb2e
+CT = 91aae91396804ef5e89b2a4cc309f8936024d3b3b61692486d7df57c6a792f6f6b24cb5f87e92123
+
+Count = 222
+Adata = a13ade56b47803897666e42ef2ef88be0e779ac86c28
+Payload = 8dc5226a2a13088c87f4bf94262e0c0413f06b35d2fda79b
+CT = de3c4afc83e0e5a52efa6813217a0e8d333f3ba21071eefd4ac19b0b74cd9d5e100598b96c9f1f2e
+
+Count = 223
+Adata = 3c5b68b65edf62755b7e064bd26c843816bf6c1cd481
+Payload = ee4b23039cd512cfab8c7a2d0f2c78d66764520bc88759e1
+CT = bdb24b953526ffe60282adaa08787a5f47ab029c0a0b1087a77a27eabfc79f192c0ac491280af8d0
+
+Count = 224
+Adata = 0213fe13c49083d7c00335e1864dc139c9e7123162d1
+Payload = 30b48d4021838090fbd5251069ff8c631452daee5ef899db
+CT = 634de5d688706db952dbf2976eab8eea349d8a799c74d0bd39935f91c1e29fc1e4c5c5427ca9da79
+
+Count = 225
+Adata = a32291746b151be8134e183798aa82bef210343feaf6
+Payload = 2286a1eddd80737a724ca941217e9f0232870b6c2f20d29c
+CT = 717fc97b74739e53db427ec6262a9d8b12485bfbedac9bfaaeaec90ada2a1ffef64c3873af645a40
+
+Count = 226
+Adata = a30f2fd445820cdf800145540602c877da0e4c311272
+Payload = fe703ca0901e4a706ce1393c7d8ce18a03eb2caadbfa7b8e
+CT = ad89543639eda759c5efeebb7ad8e30323247c3d197632e87932952831d0ba25c77c18fe154d8ed8
+
+Count = 227
+Adata = ed438e393e0e37629cb25044ae89de9fd0d42d60c1a3
+Payload = 7043c67726870bb5816da925925bc2722478311c8a606cca
+CT = 23baaee18f74e69c28637ea2950fc0fb04b7618b48ec25ac234fd0241d00f3890a23ccd0bf16dcbf
+
+Count = 228
+Adata = 1013946815001a2c08acca4196e0d6668ffbb3883cf1
+Payload = 695e9712dbbf883e9bf8af9188bd01fc631968928258168d
+CT = 3aa7ff84724c651732f678168fe9037543d6380540d45febaf43498b0c3f70c119f82d5812db940f
+
+Count = 229
+Adata = 44cc9b2510680c4d73f1938c77de21242c8ee790ed7f
+Payload = 67ba90d22c6bb5f649bc0c505c5ed23a299882559a3bf520
+CT = 3443f844859858dfe0b2dbd75b0ad0b30957d2c258b7bc46db66dbb03a4c943ac089ed11eb214bbb
+
+[Alen = 23]
+
+Key = 0875020959ed969cfb38636d1d5aabce9658b00171a7614ea9e5395331c7659c
+Nonce = 451101250ec6f26652249d59dc
+
+Count = 230
+Adata = 7cc9c51b69f98a06391ab32742fb6365e15106c811fe8a
+Payload = 065ef9eeafbe077c1c7049f43eb0d8999708e8609f214d5c
+CT = 990065322a438e136860f7b019807e9feff52a642bf3d44a9163fa7a867f04cab6f52dc250070f31
+
+Count = 231
+Adata = 7bb1bc069a783d45d51d8ecd0a53ab7a386fa1f5ef12a1
+Payload = 69b2b056f2265e707d3e31e68bff6a060544c8a737b2a9b9
+CT = f6ec2c8a77dbd71f092e8fa2accfcc007db90aa3836030affd33dd9155619fb040dcd6038c7b7367
+
+Count = 232
+Adata = 0dd220919d0eeee3b7cec36c47e376b778583b38bf61c8
+Payload = b98d79aaa4c04171398c7f1189497acaa7546ef068bc7a3f
+CT = 26d3e576213dc81e4d9cc155ae79dcccdfa9acf4dc6ee3294fcba5a886b1f33cf1cf44618d28f01f
+
+Count = 233
+Adata = 1c1915fab09348b9a5536495c70d1a040305708c112479
+Payload = eeaeb773ade5fb2d27b50bb892916333e0b123c6e3ae5bdb
+CT = 71f02baf2818724253a5b5fcb5a1c535984ce1c2577cc2cdeafe2c670eac203d5e90b9d520e7a618
+
+Count = 234
+Adata = 614b0ac4611b6c6d3b4ed089510dcd2215567bc3789f85
+Payload = f2198e1f91fde2672a1ef60403c0d175f366b6780ee9f1c2
+CT = 6d4712c314006b085e0e484024f077738b9b747cba3b68d4f0388746438e83b731b5588fef53f1f3
+
+Count = 235
+Adata = 866fea4483d4e903566844e31c24283571832dfae32c74
+Payload = ba37617342b4eefd4bdce8fad30c4751b206d47814973b3a
+CT = 2569fdafc74967923fcc56bef43ce157cafb167ca045a22cfca81f8b36d16698a600fd701f2c6424
+
+Count = 236
+Adata = 9d7546f7e8b949c539d21a357f81d0151e278d0bf2c5a5
+Payload = 69adcae8a1e9a3f2fe9e62591f7b4c5b19d3b50e769521f6
+CT = f6f3563424142a9d8a8edc1d384bea5d612e770ac247b8e04c15a6d292c7ed2f31cf9512435ec7d2
+
+Count = 237
+Adata = 42b692048c8b3cce1b5e83f4f33232a7d7d0bc20695e7e
+Payload = e0753d4248643642c7a96404de8d76c9d80527b659ec6d31
+CT = 7f2ba19ecd99bf2db3b9da40f9bdd0cfa0f8e5b2ed3ef427a2ad73179d0314b5fe52dd7217518cb8
+
+Count = 238
+Adata = f1dfb6fdb31cb423226f181c0988a52ee4015aef4536f4
+Payload = 79ba959c7221b293e2115f538d9394c64284c756563c04b0
+CT = e6e40940f7dc3bfc9601e117aaa332c03a790552e2ee9da69ccc5ba1caf933b80bfc6f281109688f
+
+Count = 239
+Adata = 8eafce9ba466fd53eb87f499d7c76bd486db0e90a3d281
+Payload = e1590206717a708cad9cca7d23a3b8ee5f7fb7786aa3be47
+CT = 7e079edaf487f9e3d98c743904931ee82782757cde71275173271ec36d92fff34609169f579c8f1d
+
+[Alen = 24]
+
+Key = ef4c1d2314e671f666cc6667660f1438a293208c7cc29b412d81277f0a635c91
+Nonce = 50b23b052922366c25dd40e348
+
+Count = 240
+Adata = cd0522ebe1fed82465277d1c10ae9316a98b4469be63b180
+Payload = c99c3e79125b6fd95e737326a842424eb6c6ecea4c0475c4
+CT = 76df4be4ec8373864399acda11294b220b9f7c3a7d2b3660b25764e40ac6a171e7e6bab4fdee4288
+
+Count = 241
+Adata = ce5bf070678cb07e963263b1562ff79311144addb6e4de4f
+Payload = eede01b08f9a303cdf14c99d7a45732972c6eff2a1db06eb
+CT = 519d742d71422c63c2fe1661c32e7a45cf9f7f2290f4454ffca49758d17f2073066b82667eae6ce3
+
+Count = 242
+Adata = 07175be2475cc735c9a3c1140895277378debf8fb1c87c24
+Payload = 6d5579aaaf8737b01620424f3ddeaf538f10dfad094e5ec4
+CT = d2160c37515f2bef0bca9db384b5a63f32494f7d38611d607c1d64d7e9de47a6ad7878283da9d870
+
+Count = 243
+Adata = c821a8d4bab9d993c20dd206955304a55968e6db5ab6480d
+Payload = d0628b2027f06c246497977d05f211b2c2e302d5b82700b5
+CT = 6f21febdd928707b797d4881bc9918de7fba920589084311adc2bb471862d25cfe25e66fedb8e28c
+
+Count = 244
+Adata = 68439bc9d176feeeb4119d00ed5449dfefb72b5a582bfd97
+Payload = 6cc9749f48c61050e421afa3a10ad3dd3aa02cc3f8586915
+CT = d38a0102b61e0c0ff9cb705f1861dab187f9bc13c9772ab1319a493abc947945f1312395ea98d937
+
+Count = 245
+Adata = adb262c924942e4e1964e9d97c6a8c159fbf9bfedc5ff296
+Payload = 92d50736466e64e6225962e76bd90da824f716a3301a1a90
+CT = 2d9672abb8b678b93fb3bd1bd2b204c499ae86730135593421d0602d29447ba6b24a67509eaee1e8
+
+Count = 246
+Adata = fc7b08707d3c3dac7689ec18088ee6502ef08d3ffbff38ed
+Payload = 87c7ac031fd63e4c83280dce6b68a92dfafb6ea19388fa9f
+CT = 3884d99ee10e22139ec2d232d203a04147a2fe71a2a7b93be52a2eeacb1f023e849161b6306b6cfa
+
+Count = 247
+Adata = fd43dfb66041b117f2ac54c94f7b6e2677860864d9494175
+Payload = 6b53c46266b2f4284d8fe7f0549c98977344d67e178e9a8e
+CT = d410b1ff986ae8775065380cedf791fbce1d46ae26a1d92a0d8c5b1e96b21460e0b5414639abeb0b
+
+Count = 248
+Adata = ef1ad3eb0bde7d4728389da2255d1f8a66ecb72e6f2f1ac4
+Payload = 8e7d8a44244daa7df2b340993e32dac50e05d7b2e103be98
+CT = 313effd9da95b622ef599f658759d3a9b35c4762d02cfd3c1c97260d20797d374c595cbc2ff080bc
+
+Count = 249
+Adata = 9895b24d12b004b215583eac70a95f4fba7442164f35c57b
+Payload = cec07df916ffb7a453d0eb588b7462096f22874bd5abf814
+CT = 71830864e827abfb4e3a34a4321f6b65d27b179be484bbb06cd287afcbdbc5531f11246080b22677
+
+[Alen = 25]
+
+Key = 8544808e8fbf8c3a5e1d4ca751d4b603af9fe119eabc6923205815e0e748b7e7
+Nonce = b44a58724596b4d8dea827c1a0
+
+Count = 250
+Adata = f5b2c88f5232c37273b1e66aa31cfa7201e33c21d60054d025
+Payload = 617d54fc6a23601c79e3984f93bfc2d151fde420863206b3
+CT = 57b3414db48982c6567265e1e0173bf38fdfaffe4461fbebc1411af83237c0f9eb0bfe8ed914da66
+
+Count = 251
+Adata = 8fabe14dcb3aa2fd28281147c326e98ad699ca7997f03a105d
+Payload = 337290d0b4ce1e87afc3cf01d6c98f8c17a4603120dcfcd1
+CT = 05bc85616a64fc5d805232afa56176aec9862befe28f01897ed6e23720b60ffe54bbb9f7ff371008
+
+Count = 252
+Adata = cf193eb3d755cb8e06c5be2334b5c8b7a22b6524d46d547ba3
+Payload = 01ef7ac6470aa02ccd8c1712827e52699d05751b78e4c5a6
+CT = 37216f7799a042f6e21deabcf1d6ab4b43273ec5bab738feb6aa6b284e7720acbd027a50317f816a
+
+Count = 253
+Adata = b4cadb5f9cb66415c3a3b71421b926f147566a174160a0bcc0
+Payload = 64fb9322210fb7d8da8e762498b233b0eb172c91231c50cb
+CT = 52358693ffa55502f51f8b8aeb1aca923535674fe14fad937058e9c0164ca079668097fde19e5302
+
+Count = 254
+Adata = 48400d76ff882d6d5129c8674acc71f445356c9db9c91f8256
+Payload = 291aa463c4babc76b4a6faf2e27e9401586b1ac83e4b06a4
+CT = 1fd4b1d21a105eac9b37075c91d66d2386495116fc18fbfcf988611d5ce0f65b217bb4787bf59bbc
+
+Count = 255
+Adata = 749d369d837002ad33feb8aa22c3f68705eb4872e1b8f85a7f
+Payload = 141cdd7f964a78815be144a785c6a2a298c54230e73039e2
+CT = 22d2c8ce48e09a5b7470b909f66e5b8046e709ee2563c4bad6251a5fd375a48583a6d0f8eb75cbb4
+
+Count = 256
+Adata = 80214108b16d030feff6e056c9a07a00a1d5e3ebb07abd3f4a
+Payload = fa2441cb7f9d072b8a3f1a496b2be6728a38b94a4f44c9be
+CT = ccea547aa137e5f1a5aee7e718831f50541af2948d1734e6af1dab0f105414293cb130bea285fd6a
+
+Count = 257
+Adata = 8b9fabe29718a8f297c9bf6f199c80bbc71f94eb3034a11ecb
+Payload = c8ce88ab40b62229223d46cc44f21bb39cfef27aa9fdccad
+CT = fe009d1a9e1cc0f30dacbb62375ae29142dcb9a46bae31f51cc3f7640a42460be877fb7059a3ed61
+
+Count = 258
+Adata = 8812f28a0cd5fdaa226fdd44ed857241007377057be3bea577
+Payload = cf59f75ca4d6d216cf8862b44b5192c382c140f862def117
+CT = f997e2ed7a7c30cce0199f1a38f96be15ce30b26a08d0c4fbbe0ddd2e7f4aa2024b3fec9281b6cac
+
+Count = 259
+Adata = c8f05e96d703a4850bae1421ae9ff3aec7531baf9b899dfd75
+Payload = 4eed58f381e500902ba5c56864f6249d191e14d1b1fad3dd
+CT = 78234d425f4fe24a043438c6175eddbfc73c5f0f73a92e85e5df1e5e96bb84f730fcb253d468278f
+
+[Alen = 26]
+
+Key = e19eaddd9f1574447e7e6525f7fd67e3b42807e44fbb60e75d8c3e98abc18361
+Nonce = a8c459ce0223358826fb1ec0f0
+
+Count = 260
+Adata = ef88f4393d6c1e7b7be55a12144209ee051bb779e440432721ef
+Payload = b3b0de10b7c0996662f1b064e04e528b7d85ca1166985d33
+CT = d63e6082c95c6c5ff2bc0771321a4f883ef61cff7b99e0ea8a20a1abe7c842ebc08c8c81a2743c81
+
+Count = 261
+Adata = a4c891c9dd1fcc982c35bc74cfe71651bae424602519672b466d
+Payload = 4f0b40913f07269550b7b06ab9027a4d9331f8ef98a45dca
+CT = 2a85fe03419bd3acc0fa077f6b56674ed0422e0185a5e013845e2d6de83ab729dd200a21088a1ec3
+
+Count = 262
+Adata = 4db5730cb9794f3b1facc9d6738115d02ba9f27ba02330fbb856
+Payload = 841e032773d58bc72a3237bc9b24c61b9efdd850fc2ea605
+CT = e190bdb50d497efeba7f80a94970db18dd8e0ebee12f1bdc10ed272c732247a696a608ef67510f9c
+
+Count = 263
+Adata = 471a900ee49f2cfa1d3eb37c951d810c349364d4cc3b5b64fc47
+Payload = b4db42e523e65557157b93dc0281601f7997e6731543a914
+CT = d155fc775d7aa06e853624c9d0d57d1c3ae4309d084214cd15f0df52e392c37ec15f7458469dae84
+
+Count = 264
+Adata = 7b40b3443d00a0348a060db109e8882157612c43084ac5c3e9c5
+Payload = 73e0ed35c0e847188e607cde46586eb9e237fbdc5d59163c
+CT = 166e53a7be74b2211e2dcbcb940c73baa1442d324058abe5421433dafea2b5484ba87b5050e1fb49
+
+Count = 265
+Adata = d563f5c048a1b45265182b99ca7b9004fdc73a9cb07806dd44fc
+Payload = 4f7669caaedee961dbba6bde9d09fee1a20eee55baaf98f5
+CT = 2af8d758d0421c584bf7dccb4f5de3e2e17d38bba7ae252cdf91749fe3cd52a9431d9a847a8c2a9a
+
+Count = 266
+Adata = d301a61eb17366d4e70942ab69b4f4bcf8ff6a97f5972ee5780a
+Payload = 154454fb74e9565c56775a8e4654f75a38b954dd28c4e939
+CT = 70caea690a75a365c63aed9b9400ea597bca823335c554e07563d37846f5185bb44d71be1ea6a73c
+
+Count = 267
+Adata = f74b48d168f77fbd3429728c0b168ecbd854264eaef70b74fffb
+Payload = 716b371857e68a17b20ea06651cdcfd4560a741830ca8a13
+CT = 14e5898a297a7f2e224317738399d2d71579a2f62dcb37ca55e93bc2d3f05d7016747690fb920e12
+
+Count = 268
+Adata = 3a257ce3592a8f88162f0bb4ecd5db3bb79b54ab17b0bbc61506
+Payload = cfdb7363985aa01af6f8e8237dbfb7871eb39303b4135269
+CT = aa55cdf1e6c6552366b55f36afebaa845dc045eda912efb01c46822f839f09c41b7aa6dc06035c93
+
+Count = 269
+Adata = 21916ebeca9e66b77cf55d1cac80a4c85d8b6b014f268ffa73ca
+Payload = b4b67ac551d1966caa20d951351387f384c2e5d81a76a92c
+CT = d138c4572f4d63553a6d6e44e7479af0c7b13336077714f54f8e77600c5bbc6d028fa25ba61a1719
+
+[Alen = 27]
+
+Key = 9498f02e50487cfbda1ce6459e241233bd4c4cb10281dcb51915dbc7fb6545c0
+Nonce = e3bd4bc3a60cddd26c20aa8636
+
+Count = 270
+Adata = 70cfcb828d483216b46c3cd22e2f9ee879e9e3059b566179b6e16c
+Payload = 0d16cc69caa9f19b88b05e151b3d26accd018ca4a5786a80
+CT = f1c4bedb8d6f91676881daa37656a7e6402f472735b04a0f1f8332f4236437737438e7aa1b5100c7
+
+Count = 271
+Adata = e7e5779282db80f424dc050b2c1e7754b2a5d3a8beae77beb74e34
+Payload = 148de640f3c11591a6f8c5c48632c5fb79d3b7e1cef9159c
+CT = e85f94f2b407756d46c94172eb5944b1f4fd7c625e3135138be2f6f356c2eb401468be15104e7763
+
+Count = 272
+Adata = d17e8189a94a559b07be9549f73d653172740e8e978f5b0a38ad43
+Payload = 00a23b25bca7c206edd051814d81083db1cd00048ce8ead5
+CT = fc704997fb61a2fa0de1d53720ea89773ce3cb871c20ca5a9646f2b6c2455603f1a6f20ea5a4611a
+
+Count = 273
+Adata = fda37ff136895de7ebeaf81e701e5751245201baed2e13d7e1b591
+Payload = a89409b0977f60a029dc4c1560ba6dbe7c65b068633acf74
+CT = 54467b02d0b9005cc9edc8a30dd1ecf4f14b7bebf3f2effb303fa5d8321241b1c9e18a5909d6e428
+
+Count = 274
+Adata = 9c179fd0d6277a5e073e77dd6abb4cba00ad9c9932e6c002b951c7
+Payload = e16c69861efc206e85aab1255e69d6d33c52cf058dec9d0b
+CT = 1dbe1b34593a4092659b359333025799b17c04861d24bd849e8cb01db1da077502814db1610662ce
+
+Count = 275
+Adata = cf5703228e615428d3d3805e428e754961d205c5aa0297ecdea71d
+Payload = 62036cbed3666d85624d3dc9c1f437454b9ab5c03ce0de92
+CT = 9ed11e0c94a00d79827cb97fac9fb60fc6b47e43ac28fe1d40a02a49857d7b280330b8105efac854
+
+Count = 276
+Adata = bab7e36098d59d3a31d7784d549aebfc6938bbd0612c85c0edb796
+Payload = 790ac86c5e9d8ce8cbec1dfb7e4fc4dca3d0b1039adfe585
+CT = 85d8bade195bec142bdd994d132445962efe7a800a17c50a5ecfa9dd03e2db70aa212ee7dcb573fd
+
+Count = 277
+Adata = 96f0b7cd7439721d4c9cc4f69585f8c90a95bed8fea22150efffba
+Payload = 3cfacd61ea3398de20ca6bdb00e81af482320614bdfb8642
+CT = c028bfd3adf5f822c0fbef6d6d839bbe0f1ccd972d33a6cde17a7a0cd162945a3616892e101e3e93
+
+Count = 278
+Adata = ee71e53d0b4eef82575c2bd38d7bd21b41fabe58c6f571954fe159
+Payload = d75c153e34ae1c6d1fcf5b1052190d8882041e1f9c5490e2
+CT = 2b8e678c73687c91fffedfa63f728cc20f2ad59c0c9cb06d15fadc2d79841d230cd55c04379f22b4
+
+Count = 279
+Adata = 18a4aa894861c7720ddb43809c3d2ed2af2f1bfe8f9fd4f872c14c
+Payload = 0e728056c7c64214be8f1f1727408d8cca8c42e2ac7bf67e
+CT = f2a0f2e4800022e85ebe9ba14a2b0cc647a289613cb3d6f1b229b9bae4634eea6b723f432e19ae55
+
+[Alen = 28]
+
+Key = 3ac7d5bc4698c021e49a685cd71057e09821633957d1d59c3c30cbc3f2d1dbf8
+Nonce = 54c8ff5459702aac058bb3be04
+
+Count = 280
+Adata = ecbd7091732e49c0f4bda2e63235ea43bbf8c8730f955f9c049dd1ec
+Payload = 89198d3acc39b950f0d411119c478c60b2422ffe7e26e00b
+CT = 7717b8e4447afcea1eeebf3e39ffdab2f52828e7931ef27e475acd27900478f09fec1f479ab3a7c8
+
+Count = 281
+Adata = 9a04820205234795ecd540b6a0b2fbd0b19f18106c42f374a2b98425
+Payload = c0f61950f98110db4226e269cf197c7e2794c5b87ad68cf9
+CT = 3ef82c8e71c25561ac1c4c466aa12aac60fec2a197ee9e8cf7b7ed6e8ede6ef5a73b484bf13b3424
+
+Count = 282
+Adata = 0e4dbd167da0240298f4795102ef18ff9a8772c6fd73b3374cdfa30a
+Payload = 7960dbc9136880e2eea7956c3271adfe2aba7dca53da917d
+CT = 876eee179b2bc558009d3b4397c9fb2c6dd07ad3bee28308e47d08ea0788f7ca0ecd846689c8027a
+
+Count = 283
+Adata = 2de4291068a5d290b599a73c6a8ecff4f9fd6c9cc48f14c233e18581
+Payload = 0c5d7055bbfbd2bc213cfbbafa763b71b1fde6f4de96fa59
+CT = f253458b33b89706cf0655955fce6da3f697e1ed33aee82cd081f66b1c7b70718dc50367c3da6792
+
+Count = 284
+Adata = dedeb714f555575fcedbd9de8171484090e6466dd4fba3c6b7c42eae
+Payload = b5654edcc8f09e4f80d0258c9376d7c53fb68f78d333b18b
+CT = 4b6b7b0240b3dbf56eea8ba336ce811778dc88613e0ba3fece672883438da186741e6c542b3f805d
+
+Count = 285
+Adata = 03d340904ace1cd52d4b72a96d96afd77aee68ac3936415005ed0d56
+Payload = d796f3409a7eeb896c3d4ebef46e9c6e553aab28b1cc4a90
+CT = 2998c69e123dae338207e09151d6cabc1250ac315cf458e5cf58d4a5552bc8ed1b1dda46703a256e
+
+Count = 286
+Adata = c67f9aa8cf1be3b4377c30c175d33ab2af390982c6a015d99209acdd
+Payload = e4dd279a79a381c68de777df941a4779e50a1381c8aa9122
+CT = 1ad31244f1e0c47c63ddd9f031a211aba260149825928357f95cf2b57e06de4d01bbb6c0e39f37e1
+
+Count = 287
+Adata = fef1b2ccd661b9fac85ba005addebdf8317ab104920549d3a490a21a
+Payload = bbf0c267d952aeb6f810601b9cf1962a92dcaba7273e6902
+CT = 45fef7b95111eb0c162ace343949c0f8d5b6acbeca067b777589cd12984286af98908db88920323c
+
+Count = 288
+Adata = 693fae7af84aa397f0b2baaed9b3c7953f75e7424c49b6349c2fc20f
+Payload = e8b13a263e0c4fb5645e500e88ab8074ab7d92e5a8dac6aa
+CT = 16bf0ff8b64f0a0f8a64fe212d13d6a6ec1795fc45e2d4dfee8fc441da990dd92c0caeac9d956699
+
+Count = 289
+Adata = 85e5df4ddec99f0bea14b3338b2eb190ab6584f5253c6c2ee3064637
+Payload = 067de2869333ed22c7b63ed7eeba1301bbac69b0d430adb5
+CT = f873d7581b70a898298c90f84b0245d3fcc66ea93908bfc0d502f5434bea8c3c13ad5422ff90e218
+
+[Alen = 29]
+
+Key = 948882c3667caa81c9b900996e3d591e6fcb3d08333eeb29911e9c6338710c17
+Nonce = 43b0aca2f0a9030f90559fa6d3
+
+Count = 290
+Adata = a516ca8405e5c8854e667921b5c5e1968bdd052915b55ac9984b7eefb3
+Payload = 8b9130b0c3c15366831bbb19f377e3209a8dbf7619cd09bd
+CT = 4646b2acdeb11174171da23999cd54e297daa32bbc13d30512e57c576b315f48c11877178389aaa0
+
+Count = 291
+Adata = db3121ea71294983b185207a9d8de3e484a66c0431bf07c962eb82977c
+Payload = 7f369bbc99b6f08049eeb43566269a174829d4dddb05cb9b
+CT = b2e119a084c6b292dde8ad150c9c2dd5457ec8807edb112366775e693f93af6575dccc7903538065
+
+Count = 292
+Adata = 1651cf38fd9b2da65ebb4922b97dcb861128eeefa060d6c1c94b25eb4e
+Payload = fd0900b5fa72e2fba43d611bad25de40a3507a5cc5d186c7
+CT = 30de82a9e702a0e9303b783bc79f6982ae076601600f5c7fb70d8de40c2068de96a274d3b5086b5a
+
+Count = 293
+Adata = af87b347b59e37a424004a00907dcbcf6a554e6782a9be12cb3047625e
+Payload = 36318d80c02a1da41ef1652d9a752e155526b5f597fba226
+CT = fbe60f9cdd5a5fb68af77c0df0cf99d75871a9a83225789ee7da096d2fb28f20f64a000fe93e96e2
+
+Count = 294
+Adata = 0680d5bacefa2ab14aa12b0e517a1432862d4215dc72dc4d5ac6b96c1c
+Payload = 7a29aa2994d11215ab3ef3382b3db6ed581164a235c4b1d1
+CT = b7fe283589a150073f38ea184187012f554678ff901a6b69b88748a2de31261534cdb2237565bf8a
+
+Count = 295
+Adata = 9af701f0a9de52309267289bd170fb97c03c131c0a169d736137ff3d74
+Payload = 3542fbe0f59a6d5f3abf619b7d58b199f7caff0205093f8b
+CT = f89579fce8ea2f4daeb978bb17e2065bfa9de35fa0d7e5330c003eb65ceedc98ae4e38ef341ee47d
+
+Count = 296
+Adata = dab7845fb7ead205569475753c7e26540c09d3a74312f2de25181511f8
+Payload = 83c15520d9541c86b3dd809ede42de22bbb2b75ff18a023b
+CT = 4e16d73cc4245e9427db99beb4f869e0b6e5ab025454d8835c2fb596d8ff6a863604cd224fa3be42
+
+Count = 297
+Adata = a844d6dbd05545ecc736994dc9fc2260c5ab63ed6ffdc40b915f8744a1
+Payload = 793a188fa3efa32f41d6e4c5b42353b95024117d546c79ca
+CT = b4ed9a93be9fe13dd5d0fde5de99e47b5d730d20f1b2a3722ac782e2cd8ecb06172eef2cb9b0e331
+
+Count = 298
+Adata = f9112503884615c0e8a1d8414724b0d19298988f393a27c436b2b6734c
+Payload = 6b237444fb0e1f4150701546c4cb24021c5edad30d9b31dd
+CT = a6f4f658e67e5d53c4760c66ae7193c01109c68ea845eb65f814492b42571033f4dffc0282ea2f51
+
+Count = 299
+Adata = d633a5a3defdde6a68f959ef39a91c6ea6e13ef1a7859d2c2c94d3a5b4
+Payload = 6342312e8a72f71f2e5afe04cfcde4d60a41556111752103
+CT = ae95b3329702b50dba5ce724a57753140716493cb4abfbbb75999099df2de6e436bd99f0341423f4
+
+[Alen = 30]
+
+Key = 3bf52cc5ee86b9a0190f390a5c0366a560b557000dbe5115fd9ee11630a62769
+Nonce = f9fbd02f28ecc929d369182752
+
+Count = 300
+Adata = ebf0b3e3199a5c3773c761c725c7600add5f9d8321c9f8e5e5fd1c7a5d2f
+Payload = 094b538110495e938b08cf748a6bcf3e0c80ff9c66570237
+CT = 4d8b53016fc8bc9677184c0fa15bbd3d671b9366d82ecb67f8562eadcdcbcdbad1299bea1523f5d2
+
+Count = 301
+Adata = a865b88d512e485ab3f2844c29e6dde0cf1151efa9ad3b3021d06fffb74b
+Payload = 23edddd8732cdbf03af08162f0e4a24c9222bdbb4549c663
+CT = 672ddd580cad39f5c6e00219dbd4d04ff9b9d141fb300f3359ff77cf0962455b3539dbf91f3077cc
+
+Count = 302
+Adata = 16918dbc785d94a8f1720c5ad234dde860219874c9fb076a5c290903f85b
+Payload = 1798286c37c1504fc0d7402681f6f70711ef506dcc3e29d0
+CT = 535828ec4840b24a3cc7c35daac685047a743c977247e0806dbed76d94c90595b49d50c84c3efc76
+
+Count = 303
+Adata = a2969243b0955402ab45a430fef2ef9e0c025006732bf8e592e3d3884918
+Payload = 0d02778f90a164a4f9ada9dc7fd24eeb941069621418ef32
+CT = 49c2770fef2086a105bd2aa754e23ce8ff8b0598aa61266248fbe60c146056e5cb01268403e4b9f5
+
+Count = 304
+Adata = 2de5222a0609f058f60e9e581b6e4f0ddebed84fc8302c8e985d17b89241
+Payload = b0c3858231e284af6d231f043b95772f5e7b16a34ffcd2ec
+CT = f40385024e6366aa91339c7f10a5052c35e07a59f1851bbcacff35df1ec942b43eef5aef980cb038
+
+Count = 305
+Adata = 3fc7453df038a92829dc103d44b63ad097d7cd7f9ae7996547012090c7c4
+Payload = 319f396cc02834f8e69d65f77496d0eb31ce1a7b7e324820
+CT = 755f39ecbfa9d6fd1a8de68c5fa6a2e85a557681c04b817091a93f5fc28e5f4f351cfb888da763dc
+
+Count = 306
+Adata = 18f1e92bd3c4a597ed970911d03a78ff9a6790147c9bb0ca5f23b70cce7a
+Payload = 25550c03f8fa02b3781330f96e0fdc58681b0c0bc5e83fe9
+CT = 61950c83877be0b68403b382453fae5b038060f17b91f6b92c6a90ef2e9a969ec0576fae1d126a85
+
+Count = 307
+Adata = 09ecb2406054716418ff3600c3c5cacb0845a377a2d80542abc36ec81bb1
+Payload = 210ff7975e08388b9a46eb732230e3a3856a497549b5eb49
+CT = 65cff7172189da8e66566808090091a0eef1258ff7cc221959fd6aeb047200907911621e8756b45f
+
+Count = 308
+Adata = 62d515bb0525b565a6a3613ae20343c8da7424c8368e8cad6a862b7d37a5
+Payload = 5d867265965bb2aafebb0691de9e157a24066d06fe3cbd7c
+CT = 194672e5e9da50af02ab85eaf5ae67794f9d01fc4045742cc4db6d5fd910c83fd77aefba3f7665d8
+
+Count = 309
+Adata = 00617ca141e55b045a188e4934caf6db63d4577f634db92c22010e1cbf1e
+Payload = 396b27afd16a1081f37bbc1f742b549f5f68df799b93083f
+CT = 7dab272faeebf2840f6b3f645f1b269c34f3b38325eac16fdf5f21f32cbe5d272004f1c104cbcae9
+
+[Alen = 31]
+
+Key = e45bb1730d0d539aab3805350ac986540de9f0f6c239ee70395c291397b70309
+Nonce = d5c7824af715bb7822b6b340fe
+
+Count = 310
+Adata = 860f4a09ad8b3d345c2aa18ffb803f0bc3b734a4d047a1437701a5e3d95288
+Payload = bc8b3bc48c7a88c9fafde258b6ccaa9d4f0d018703d63871
+CT = 95f083ad6bbaee6ab540fe023858f8baf25e333fd3e89c00e678a392d228b210dc5c991905dacf3f
+
+Count = 311
+Adata = 8a84b57915bdbe7bf5a1c1a426512b3c178d883251cc46c95a8bbc8ed9e56b
+Payload = 9499ea48edab9bc21b91dd614f04934ca20db8630622f481
+CT = bde252210a6bfd61542cc13bc190c16b1f5e8adbd61c50f010fbdd3b305522dae6b652322d89d9ac
+
+Count = 312
+Adata = ed8540f7ce451c522c1ff5d2d1030d7b3fbd1219a21aaa84044c4f23c08f5d
+Payload = 73843a4e9e7937fed24bb1fae15822213b1aa86c07f1b5d1
+CT = 5aff822779b9515d9df6ada06fcc700686499ad4d7cf11a08b6b08548e794eaf85ad9f5de80b1c00
+
+Count = 313
+Adata = 61bb196b212feab645f05a8aa1986f6210a384c15bc749245d840b3565fb36
+Payload = a8e24266e5981b2ed14213a29f961cbbf7f02f63a33c987e
+CT = 8199fa0f02587d8d9eff0ff811024e9c4aa31ddb73023c0fcc73643a7ee9291e15137d7046a92f3f
+
+Count = 314
+Adata = a49c2df94ba65107f375ce1c53b72406143f6bcd270945de5b7811682fe361
+Payload = 3e3c402caeca41687d12897102e04312edf7b8c7d8567a22
+CT = 1747f845490a27cb32af952b8c74113550a48a7f0868de53204438662ea82f423a69c6e4e3c0623a
+
+Count = 315
+Adata = 7c48480e9bc87ba299e03899698b2259eef150ee0f2efff40a5583b80ab484
+Payload = cfa9292b9052ac6bb863205d3c0dc2d9e20d2ba6a680d2ed
+CT = e6d291427792cac8f7de3c07b29990fe5f5e191e76be769c6ea00b9cd881e3f4b1e838dfa31f6560
+
+Count = 316
+Adata = 5cf9744090366d828b477dc890eab8ebebd44f6aeaa5b101291bf67d12867e
+Payload = e0fe4e139ab0deb4fdf2145b719f35c50b869e6cb20608b5
+CT = c985f67a7d70b817b24f0801ff0b67e2b6d5acd46238acc4c59b3b87d722a58cd1de58f3963d12b3
+
+Count = 317
+Adata = 761d74be5fae170a1bdfa16081b44c1e49972e15ce0818df1390bf7204f619
+Payload = 665fdcdf55a1231e9912562eaa5a5011d69f6948e29e3f8f
+CT = 4f2464b6b26145bdd6af4a7424ce02366bcc5bf032a09bfe158759886124f1f0ce8147c94f4e7114
+
+Count = 318
+Adata = 9815353b69d0b4effa52cefff13703fa71a6296f9cca0f02568661be4b64cb
+Payload = 7b2d52a5186d912cf6b83ace7740ceda3f5f443530c5a49f
+CT = 5256eaccffadf78fb9052694f9d49cfd820c768de0fb00ee6310a79c9932456dbc00515b264f3168
+
+Count = 319
+Adata = 69dd1a050c8d79dafbbe3403af4dc1f070b9b2b980888aa796e6cff68d9060
+Payload = 3cea5ff50167c5641066852fd00061df35b1f66bedb894b7
+CT = 1591e79ce6a7a3c75fdb99755e9433f888e2c4d33d8630c6da7e97f9984a7db3b93aefb4316d9acb
+
+[Alen = 32]
+
+Key = 2e6e34070caf1b8820ed39edfa83459abe1c15a1827f1c39f7ac316c4c27910f
+Nonce = c49ccef869bb86d21932cb443b
+
+Count = 320
+Adata = d37e35d7cdccd9824a1ae4c787819735e4af798a3beb49d4705336d6496853ad
+Payload = 771a7baa9cf83aa253349f6475d5e74dba4525307b022ba7
+CT = eebac2475004970071dfa2cfb855c4e78b1add8dcbccfc0bd6b14027324b657a56263df148665393
+
+Count = 321
+Adata = ab22bc22bf2628b0e0ab245c3db2fc5128d13a011c2cc9b9fea05a79a3410704
+Payload = dad95a4b4d3754613f0542caa62cfe4e375dfbdd369ec32e
+CT = 4379e3a681cbf9c31dee7f616bacdde40602036086501482a8c810b6944815fd2e434193520b1d5b
+
+Count = 322
+Adata = c48c5aacf701137fc40fd0d3649641aaa5be427ceee702cf7ddf6408f458a581
+Payload = 3f28df9263e473be648fabad163aa4142b633388b16d8392
+CT = a688667faf18de1c46649606dbba87be1a3ccb3501a3543e8aa447b79284c588bef50b423de97908
+
+Count = 323
+Adata = 477c2484cf5c56b813313927be8387b1024f995e98fc87f1029091c01424bdc2
+Payload = f83107b50a1f192ed45cc43fa80e6b519bfd859173ea9ee9
+CT = 6191be58c6e3b48cf6b7f994658e48fbaaa27d2cc3244945d4f4a413eb3ac2c474134995d4db9a16
+
+Count = 324
+Adata = 143bc037f1d0bd4ec16825c58cb3796bf8989200d27bda9beabbbc49247f59f7
+Payload = dfeb324ba459ec4a5c54d2534e98002412e67db19cfc66bb
+CT = 464b8ba668a541e87ebfeff88318238e23b9850c2c32b11756a3fb2e06734b28fbd57942a609d914
+
+Count = 325
+Adata = ffc416f1dae4e43c1a01339a604c44d6a0f25ab9ca3978c6aacb6d270d510ee6
+Payload = 0765949e6f22c422ebd47dc1ed73f1b849d7a058a1656fc2
+CT = 9ec52d73a3de6980c93f406a20f3d212788858e511abb86edb94280d3c4a1cd8cb00705f60ae36f2
+
+Count = 326
+Adata = 6090b596b4082ec6926576137f6561cf13916860ad1cfc43650d1b5142a12041
+Payload = 6db320cbe76bc5b8cee9ef89aca11765571c6c501993195a
+CT = f41399262b97681aec02d222612134cf664394eda95dcef612caca26cc3bbb289da3be0616b3445f
+
+Count = 327
+Adata = 178ba75adb7c5bea6769270bb3b4f6ce208d4a786913d3ced7bb4090b5f65544
+Payload = 0875020959ed969cfb38636d1d5aabce9658b00171a7614e
+CT = 91d5bbe495113b3ed9d35ec6d0da8864a70748bcc169b6e26cc8c665289d907628eb0e299c2d411e
+
+Count = 328
+Adata = 90f0474dca998916075b1b1428df14d90be05491bb8d5d88e32e65ec890ba9d3
+Payload = 4f89ca6ad371f86a6e073ec12fb1b928bb10d6639233b918
+CT = d62973871f8d55c84cec036ae2319a828a4f2ede22fd6eb4f7e481607a2a0529f9cda1d5903325b7
+
+Count = 329
+Adata = 5ad8dd40ecdce52d5b30424ca0bccb666f34f66b0c9a4c1260051ac04ca06aab
+Payload = fe2009d0a4a1711b83057b948cd0b174a3a042fd97579ab8
+CT = 6780b03d685ddcb9a1ee463f415092de92ffba4027994d140a1b9ba2bfe5bf778b859f0ff0c29a67
diff --git a/lib/crypto/test/crypto_SUITE_data/VNT128.rsp b/lib/crypto/test/crypto_SUITE_data/VNT128.rsp
new file mode 100644
index 0000000000..b796541cf5
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VNT128.rsp
@@ -0,0 +1,456 @@
+# CAVS 11.0
+# "CCM-VNT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Tlen = 16
+
+[Nlen = 7]
+
+Key = c0425ed20cd28fda67a2bcc0ab342a49
+
+Count = 0
+Nonce = 37667f334dce90
+Adata = 0b3e8d9785c74c8f41ea257d4d87495ffbbb335542b12e0d62bb177ec7a164d9
+Payload = 4f065a23eeca6b18d118e1de4d7e5ca1a7c0e556d786d407
+CT = 768fccdf4898bca099e33c3d40565497dec22dd6e33dcf4384d71be8565c21a455db45816da8158c
+
+Count = 1
+Nonce = f7a5098b2a4d92
+Adata = bc498326755503ff25d02805eb3517221b54eb4fd79af0fcdf9312b2a9ad95f7
+Payload = 3e2144e2a381b718962a77e167778bf579957a8fae29612c
+CT = 98ce91033fabaa8fe853d347be6cbe5de102fdccf042e7be697b41c9a69acaf8386140ee6e36f406
+
+Count = 2
+Nonce = 732d2dd64b4a25
+Adata = 495b03df82e317e4f351c5323d17c673f4c77856983179d7c7cb75c2b0573c72
+Payload = 4bb0d170bdcc70fd18f19605cf9c6181082c4367f1e6fbce
+CT = 9bd9304259962448fa8487bc15d950303621213afd88f1e32d442ff663242fa269c4a742a220edc5
+
+Count = 3
+Nonce = fefd3ac595428f
+Adata = 91ffb6be8e129cef9189f7e0fec8e937afcfc6083b6a79a778a724bb3e8d0794
+Payload = 9e8c4f1292e8d7e5179b34ae5d2ba2491d7754acc54bb91d
+CT = a5d012b3062cc93b831860d76539169c88854b85550c67fc564a2f1cb7d77e0223287740d5ff9003
+
+Count = 4
+Nonce = e14d81ee3b873a
+Adata = ecdc5249ceb48e8d5a4483043921c00c1acb1843fae00155a28f3a127150b1c4
+Payload = f99e23288e6b5ae85c14610994d90d5fcbcab62b4ed1333e
+CT = cc4ee711d0202deb58664e00cf0cf70b737f48ddadcefd6cd217fb611daeb66fa2d8e1bd43cb2131
+
+Count = 5
+Nonce = 2cbeaba94dbbd1
+Adata = d129674c6c91c1c89f4408139afe187026b8114893d0f172f16469b183fee97e
+Payload = 1b42cb685bd462fbd40e0273a81c767aa81cb43f17d3c0c9
+CT = 1a1b1c7130aa63098dea17ffbb2216d1d276cb10145b0762a45116736e95d823e579d73dc31dc487
+
+Count = 6
+Nonce = 8a961df9c23f6d
+Adata = 07185502bf6d275c84e3ac4f5f77c3d4b30d8e106603be84410c11849a3c18ea
+Payload = 434e182d04ecda519a6119fbaa4c45e8c9803a9a3eb51dae
+CT = 3f603939c6226d8208b2b0e675b82557609ceaeeee4032c7837ed517dbd7e6fe34ea42b01c69d370
+
+Count = 7
+Nonce = d3604d390faab3
+Adata = c95e7329d36145664da69d25f24b301d334e1bca2baa74b2d5c325ed7d04fae4
+Payload = ee104be898a225eb1da99163bbf768d8ae6d5850af6f8767
+CT = 3e6a7683d9d804f791f77d2b69996102ba82477ec4557747ef2e0b322f51abb366a1e8e37f4fe4ee
+
+Count = 8
+Nonce = db5004a1cdae8e
+Adata = 1370fc9d5bf1ad2d071be5a28b235402a85270f536b5601c221519a3b329c71a
+Payload = 59bee7d18fd4ba573f3e4f61076f5b9f6a3487e47d98c729
+CT = 6db54d6f5c3f3efa6da67aea1234d46e8b679a5c257c66d82e4ef944778281ed186b4a8099b47fff
+
+Count = 9
+Nonce = 783477f981ef05
+Adata = 04bbf2a826bdf3d55069b1936c4f8e8e08189f54066a035c950c7347604b1b65
+Payload = 6150f132b25727ebbaed9f16bd91ebce00c68e5b39bc0ef9
+CT = 36f78cef22cacaf9f3d4464821737f7fbacd79be517b4727bc5c098625c51ac7fdd15da2cc9ef4b6
+
+[Nlen = 8]
+
+Key = 0b6256bd328a4cda2510d527c0f73ed4
+
+Count = 10
+Nonce = 21fd9011d6d9484a
+Adata = 66ff35c4f86ad7755b149e14e299034763023e7384f4af8c35277d2c7e1a7de2
+Payload = 78a292662b8e05abc2d44fbefd0840795e7493028015d9f2
+CT = 5a0be834c57b59d47a4590d8d19a1206d3c06e937a9b57f74034d9fdb43c3f48932aa72177b23bf6
+
+Count = 11
+Nonce = 97f940d7c1230bd8
+Adata = 78337ddfe38be7897372b0f805603a9a9e55598452285764641c3bb7aeb54a3c
+Payload = 772aeff60eb3adf5a9589ad54dda0401cc9765589609dbd3
+CT = ef5c408dc6d0b501925a47def54d8deb9880a07a3e6380bca20a3995cf25c5a7b9477d8916adff73
+
+Count = 12
+Nonce = acfdf302ed116ac4
+Adata = fe9d9989bffae3c9e6161eb0aa9d54ee8f5051f0dcabb5a750c5478c11798ce1
+Payload = 99ffe16de323a9b65fe60305a2d062cae490ccca6d9fe9da
+CT = 1bbc2c7877d845591660636cb6ccf4edcd4c156996a26a707d0e2fe322f203c08f44d7f9bd7258c3
+
+Count = 13
+Nonce = c8d36e13b7459c47
+Adata = 3f3c3a4c26dba18f385274ac5ac3df73282686488d91bc8190b7f61071b07f62
+Payload = 316ee95430329f706348886b8ac7779e3056809e25da0a03
+CT = fd2db9611a26a3e90f4861467df60edcc595f442332b089905fdd72307c3355b19ea66d4a16ef17d
+
+Count = 14
+Nonce = 5822755a3e47c27d
+Adata = 1d72d6b371e85ca359483761704f80b3360f4d6610e6d5e490b0d509f73c3233
+Payload = af4ae8f19cf6cbd199677fe033859f56906f1979b1b5926d
+CT = d5ed6f8d5c42f4f3ea527094173b278724a2ba787e416ad759124db19ab1373a5376f46ec7095ef4
+
+Count = 15
+Nonce = 6c1c94c2e71b865b
+Adata = 298cac1e4684182786f386ef3de79c11e30b2dab7579b8ca18d0312200860403
+Payload = 6e4d992d7541e02a4aa167e56c7e47206abc25fea6c5125d
+CT = 560cd43a502a6e8b1af478a3b640a68937d1a83057110d38eaa52d69ab9790edc384b9a5d8c91dbf
+
+Count = 16
+Nonce = ce7ec65cfeda31da
+Adata = 13c1298cbf7fe6a9ab378f86d3c2207944cc2a232f9383513ceb3b202086d365
+Payload = 196c80d02b663bdd89fdaa31e329b5a8f7c596236ee8dd80
+CT = 00174dd83a7f8edc71afbe5da095160336be9184f693db3db1f45de395e021c6fb1b2991c91bd643
+
+Count = 17
+Nonce = ddb739acda6c56ec
+Adata = 7f89bbe513b9a7ebe9be3f6eb88782080593c83e8cbe47fbe15bdc3e5782090f
+Payload = e95e142217c838d1f998a52e342e4f2d80b1cfd35cf6b73d
+CT = 819d73dadaf095652cf39729b2e2cad7fc7783887a5acc15713d941b845d96a5bf65e9f80ae7f923
+
+Count = 18
+Nonce = d9bb71ad90152d5c
+Adata = 20bfcba120cdbeb07c5f4d70338ffce493822d78a03c9e80b5b934e16e39f70e
+Payload = f1fe98b50ea2f9f088f6f93910757cf744d5aabf3081966d
+CT = 36decda8ade6ab104a201c6d370412b907a559738eef59665e99761cb1ac77d772b9cce9345d9a75
+
+Count = 19
+Nonce = 2c9ec9f1f1358c50
+Adata = 96f0b1edec4ad14407dcaf30ed68942b46c48d58b2dd63af60fccd5bdd48e560
+Payload = d74badb8ad7f2c2bcdf67e497151d35a4fc2a3c4c871868a
+CT = 0e9066270da6e03cb4307c43adc71b4b596213a63fc8032085ce60506ac3bd97327904ad2e072a6a
+
+[Nlen = 9]
+
+Key = afdccc84f257cb768b7ad735edbd1990
+
+Count = 20
+Nonce = b7776aa998f4d1189b
+Adata = 9f9ac464de508b98e789243fdb32db458538f8a291ed93ddf8aeaacfbfc371aa
+Payload = 56d0942490e546798f30d3c60ad4e3e110fc04f5b1c1fa83
+CT = 96f124c74fd737819008ddef440320f4a3733d0062c83c893e259aecf12ba08f2a2e966a3341d6d4
+
+Count = 21
+Nonce = 278cf1f09b13f467fe
+Adata = af9627922758a9f7792345716782e8837ca78e8f9db16e3fe12a7124a3d4e99d
+Payload = aa9b9e80cef47b6db3816b1d665f233e696337e21bb8333a
+CT = 5eba7e3b3ecab78121b0d56acb9dbfc6756c1255b42f145d11751638ed36c1fd3c7268b71633c1cf
+
+Count = 22
+Nonce = 4ae701103c63deca5b
+Adata = 5872a1507c833c581ac2750b2b54add4b92be14e45d72db7679f8fa2b4d1eeeb
+Payload = e832b053854fbd40c0d8b6d6b8fd5de2da0c173f5fe594ef
+CT = 3b2b964c3a90d51c0ace186db79818b4d0f7b81236d36017d3635aa1d8167087600b01643b0a5ce5
+
+Count = 23
+Nonce = cfb5b12928e1c36849
+Adata = febe755bb8e4475d8d12f5e96269abd0d4e40d73cb966e2c523343e9a6d2d71a
+Payload = f46d6970dcc37d32d93ff062e68034c1906ee487fd28eefa
+CT = 0d5332a42fc583f4f81744b899cdf2a64cad1e78d577112fee6f8c4b252e10b42fbaf8c7af1e9f3e
+
+Count = 24
+Nonce = 68d5863cafc69e6ceb
+Adata = 048ba28abb191ded5449dfe9dc7d19f9b132a2a9fd779aab7da44d2887485954
+Payload = dd4438d7ba3edc73872e42dbbf78cf300fe4bf0eac9e16b6
+CT = 874d3ef7f916db2c2799b6892ef4bfbeb4729ecbf26ac4983a8639f21f8548fae45dc76de57bcee0
+
+Count = 25
+Nonce = ea09fbe5da0fa4fe91
+Adata = 63ee18eb720b21ee4c157dafcb8c7bcc6817f54d5c1b8dd7058c37228a03f8ad
+Payload = c1811d613bf0789beeef693611ef733cd173da703b66ab3c
+CT = cbe5c799952b28fadf414607a6cf8194e9f41194abace4541d3853a52971b0ab46cc0a3eded435c1
+
+Count = 26
+Nonce = 0021be18ed76b3a34c
+Adata = bb5eded483f0ae1106fd08c5e2b91cf06d3a7a73518ad4c479fb05e631ba5399
+Payload = 2d5531d1c51c6ea100b028596bf9f24dd90be14eab58f07b
+CT = 7af0449f7359b7f3e5f6c1e7bc264c7724037f4f16077fd0a2a8e3cfb827c7e6edabb34f7bbafd01
+
+Count = 27
+Nonce = 449b51ee0760179e35
+Adata = e99bdf783070a3a48431704e90277ca65a9704c12eeae2e2d70b62f816115267
+Payload = c4896d58442877c986e4f862a9f3a3179f0e9b96316a90d8
+CT = af7531c073df01077fd5c8ea9a5530c2fe1688d529e5c2f24aa8feae6a500919a336dbba1d9fb7e9
+
+Count = 28
+Nonce = 232114642e0c6b55b5
+Adata = da288d2014616f16a2abf5923dea49aded1748592adbcd97415c33ebfa57150d
+Payload = 11fd3f94b5a5ce94f2740a27a0771aeeac77f3155d2bc12c
+CT = f0c174a7927da0bb88e92917af8ae1df4ffc3527004e9e2d0b25cea7ed6e4fe9069a2ce49875230d
+
+Count = 29
+Nonce = 660cb6d654afcbdab4
+Adata = bd96c3c225099fc58cc1f97779304606b11efe9712fba13abf74fc1d7d44a900
+Payload = 793c0bc3deb6e0bec4c1d1fc17e455eb1aa5e9e25cada861
+CT = fa4b14a381ee41fec7b7279e58f0d06a3beec26d645f81336218635754d5563f2cd48bdbb267e5ca
+
+[Nlen = 10]
+
+Key = 6ccb68d3838d4ddf660b9cd904cad40f
+
+Count = 30
+Nonce = c4fb7519a19f13d9d1fc
+Adata = 092e64fef08b5655a86cdb8de63ffaa7772e8730844e9016141af8bad2216246
+Payload = 5ea35c082e2b190e9d98e6b2daad8672f587b4f2968072fc
+CT = cda5fe3d15d00150b99120c7f206b88a4c2c4a39ca9143425603ab284a73a38cc916f8b653c92ab4
+
+Count = 31
+Nonce = 45927852550961f1ae9e
+Adata = 53ae030474795ffda4d9ac0fc3c45afb592ddd761f7b5335c13a6747e21075a7
+Payload = 6c5f468077536b4c9a94ea4a6fe3cf621083a210daee45b6
+CT = 694847b6429cbc3902d9cb7049625aef1e97b569e1e3169035bb811491d142cf1b26350f8451bd14
+
+Count = 32
+Nonce = d8c54463dfcf02d0e327
+Adata = ff95c0ed0da32d1b5f57570b815a50592ecdc9c1c4e727e0f6dfd93fc10ce88d
+Payload = 7321a6de8d694ea05623206f5df438c5c2cdd6b1eccab4d8
+CT = 9cf8ef119aa5cf3d6305d50b2b520a0b10bcd240e27276749c68e8e641b0120f7dd66e8f0cfa4205
+
+Count = 33
+Nonce = f690f3a996928275050b
+Adata = 41c05fda535770699ed22cef253753b658437f833afe65c9c393581d835f0fea
+Payload = 56520a4bfd7b73a471e0446f9524a407e81c2681b7329e35
+CT = 14aa15f9f64c4c64f6e88094e012ecb24193249f044c033dda44a62f97c0fead3f65b28928bfbcc3
+
+Count = 34
+Nonce = 26eb9ef25be62148fa61
+Adata = 8f45608a07521de86ed5a84a851e629b579b51d7bf4cc7202a773e0f9e9d8748
+Payload = c68094c26c7f017b79f126dc26b3bbcb95f97535ca412da5
+CT = 7ba8a0c2fe2b230768d1c1874085ddff8926931961bc4558f0d5444466bcc631bef8e58fe5818af7
+
+Count = 35
+Nonce = fad21bc27dabafe7a4ae
+Adata = dc5d7fd97bb3243ba585fa0d71a07191667af418e30a6b76bedd05b32c673403
+Payload = c247fa8d8091cd3f299cdacba7fb7af93549e9e3160f9cf8
+CT = 3097d2ec0f8bf00b22504ab03a75e740d3e59c269c3ee3f00b5419293a67eb008aef0f9f675201df
+
+Count = 36
+Nonce = c911348848fe67406dea
+Adata = 50d50a0b5ed4d6904ec3045263af0255a6494b7a7e2e95ea806c4bb788423dc1
+Payload = d846c170ae0111348362901503b26d58f5efc17b6d296aba
+CT = 5d72562f7dfb47bf34b90ee4ea11ff9f726c915b07f4d843dec5a554f4bbecbf6943ffdab8d8a26a
+
+Count = 37
+Nonce = bb921b46a16d20ae4046
+Adata = 7d17f8f60ad1e61a168b5b0e7fbbc90cee79b612b6d6c0d7ff6ede042341e8a1
+Payload = 71bb6ae84262646c9be95e0f4289ffeab7555ec6746c6ae9
+CT = bac123320888b553666249756e6d63b3498760791cbe9e34e5b1162b7489a59a50c0f0f3618e6c2e
+
+Count = 38
+Nonce = 61a8b8cbfc9bdbadb2a3
+Adata = 51cf2a8949e13eaa087a34c9ec4d7fd92b862efd6a0b1fef8b016fa2c6933426
+Payload = 362f9a46aab59fb6213c83d791b2129b34367ac2de2048fb
+CT = b8a57e8714d8789f4ef2af29e0efec21b1ef67fdabc7cdf0ed5505f1f0ff77723771338585c456b7
+
+Count = 39
+Nonce = 6bc4cd23c32a913998a7
+Adata = 92fbc970b5e64198ce2a138de92767edff8d82f12f8832444b346d159657356b
+Payload = fa442383da234cf8f0c5fb667218bc3bea0c091b3a8e6b77
+CT = cdfe3e83aba43a9804c5a1832e0e47a9a153359cc32db907714025f485c7f40256049f16f859b859
+
+[Nlen = 11]
+
+Key = e6ab9e70a4fb51b01c2e262233e64c0d
+
+Count = 40
+Nonce = 74e689eb5af9441dd690a6
+Adata = 42f6518ee0fbe42f28e13b4bb2eb60517b37c9744394d9143393a879c3e107c7
+Payload = ba15916733550d7aa82b2f6b117cd3f54c83ddc16cd0288a
+CT = dcc151443288f35d39ed8fae6f0ce1d1eb656f4f7fd65c0b16f322ce85d7c54e71ac560fd4da9651
+
+Count = 41
+Nonce = eb118fb41284bfcb1bc338
+Adata = b5a6067fbac46578cfc8d3fe04108588c9de077eb009249374f205553bba9d02
+Payload = 863da00c7accf45418d47c1eda72338734dcc49cd599f328
+CT = d64de7a56146b971e21bf5784d67bab32dd837cfb81591da4a0177883346dc896eb39e8a32bc1393
+
+Count = 42
+Nonce = caba2716d07e95de83855e
+Adata = 0e0ff2c73ea5fa8f8726a3514cf906ce1610a1a6dc19b22682f9e4619f762d82
+Payload = 2af6d5636ab65db2058b2ba16df257369fc4e8aef8b9481c
+CT = 3c9e006c7d8eff5f448b0cc9c27c964713241aa7fed3665d775ea25fb272981de8b8aa0a637498fb
+
+Count = 43
+Nonce = 314c136999e41d137bd7ba
+Adata = 366c659bc45d0a88acd54ef7eeaa3e140e1cafb1b01474a065a9d460c5e83bfd
+Payload = 217b19ea6a431a1f66bd9d02b718e8507a08ab8e6f603e3f
+CT = 33d7b672b23e8b03a39ff3fd1e7b0f2be67163e3e3bae072f2aaa211dec623947a50b1252bc5aad3
+
+Count = 44
+Nonce = 6fe51f5013f53d4e4fd907
+Adata = ff182f2e179d790e827cbfd0bd8b9297ecae57ffcef9e25ef114474a22e4ec5b
+Payload = c6bf582b49dd4ab6cb33f3f88e8a4d14fe32b308ee3b4682
+CT = 26cd5dc5eac2acda283ca03354260ad57af79e20c5e92f5775ed171bb0fbaa6f431c5411cf9b536d
+
+Count = 45
+Nonce = 24bc8dc1e2354667b79ba4
+Adata = d0d48d01fc79685c6bee04d45e40d06cdf1f4607542b1ece556fc2d1bb2b03f1
+Payload = 90f52ebb1bd5439386faeaa194623285f750672a7baae64b
+CT = a7f43f56c50705a1a101044b954414fdfbe32b518e934d38f391749ea3acd624c01e4583ab1506b7
+
+Count = 46
+Nonce = 89ce46b3de3afaf2518d41
+Adata = 5767202c913584d653f37d926a0c5ac1c67db3efd1dc58fbff998778a6856254
+Payload = b2ab379a0dd15baf91415eee3a4e56e7eca54d4c1c3094f8
+CT = 9f530e455a54b86835eacd8801b34c884a3b2ac819ba38f894e43a6b1cf73cb2d6a1dd8331549520
+
+Count = 47
+Nonce = d3208eb695e84c7a925037
+Adata = 91d8fa65a6885f162a795afe2898f391990a8b3a87c11f94734dcbddf5f58da8
+Payload = f15e39f0e4eaa5bf81359d8e30186522f1a1a415436668cf
+CT = 7f1d9fcd9e5cce3a81e3495bfecec817fd7180d8bbfe0abab27fb6425fcc3537ce471425a5b17dcf
+
+Count = 48
+Nonce = 067de2869333ed22c7b63e
+Adata = c31e441fd551b3fdfbe23ceec5ec1f838f31a5300f6055ad2a936a9d0c1c856e
+Payload = 1536d9c9a09302d142c85638202f5bbf0c287f68115d51d8
+CT = b1a5c7a7fd23228dc7ea26885802daa0719f6a23681e1d65dfb879c21b46f3307ef22f1da579303f
+
+Count = 49
+Nonce = 15f61b4526d19bceae1093
+Adata = b97b122af73e928e617e98684f845be4cb80566345739b7a884c6a3eec5102bf
+Payload = 37c81988c07a5b01e2b40ff9f9ada5f50ca764efb717ff9e
+CT = 0d93a5c77482d573b7f1b8c5e283f2571efc9f54216a4c01900504a73c8817ff2b55618b2602bf38
+
+[Nlen = 12]
+
+Key = 005e8f4d8e0cbf4e1ceeb5d87a275848
+
+Count = 50
+Nonce = 0ec3ac452b547b9062aac8fa
+Adata = 2f1821aa57e5278ffd33c17d46615b77363149dbc98470413f6543a6b749f2ca
+Payload = b6f345204526439daf84998f380dcfb4b4167c959c04ff65
+CT = 9575e16f35da3c88a19c26a7b762044f4d7bbbafeff05d754829e2a7752fa3a14890972884b511d8
+
+Count = 51
+Nonce = 472711261a9262bef077c0b7
+Adata = 17c87889a2652636bcf712d111c86b9d68d64d18d531928030a5ec97c59931a4
+Payload = 9d63df773b3799e361c5328d44bbb12f4154747ecf7cc667
+CT = 53323b82d7a754d82cebf0d4bc930ef06d11e162c5c027c4715a641834bbb75bb6572ca5a45c3183
+
+Count = 52
+Nonce = 6a7b80b6738ff0a23ad58fb2
+Adata = 26c12e5cdfe225a5be56d7a8aaf9fd4eb327d2f29c2ebc7396022f884f33ce54
+Payload = ba1978d58492c7f827cafef87d00f1a137f3f05a2dedb14d
+CT = aa1d9eacabdcdd0f54681653ac44042a3dd47e338d15604e86a0e926daf21d17b359253d0d5d5d00
+
+Count = 53
+Nonce = d8e133e7ff8e0a0ec6c4096e
+Adata = ef9e432c15d8c93a4b5c0666608e61c824cd466d7940d642acd3dc33057c0395
+Payload = 2836de99c0f641cd55e89f5af76638947b8227377ef88bfb
+CT = 5edb056d85dafeaaf74bdf4caa47339d6a75bf1ee998565e9f9cdf6ab825f6e026f5be2ad895033e
+
+Count = 54
+Nonce = 2fa8120398d1a946f391367c
+Adata = 377cd407ad28dc02bd3835a31d92f8295c9dbe597f56662ceda112c588dc73a5
+Payload = 7a37255b682766a0bfecf78e5162528885a339174c2a4932
+CT = 701f5f506fc7e9ea4a27a4db5cb890f7be3b4f6bcb20f97ed3021f6ad620648b8196ab1693710398
+
+Count = 55
+Nonce = 8d638ef43f56dece910139e9
+Adata = 87ea7b095388de70ac0ed23e86f502400910028a8ab5e3bbb91d05821c0d2d61
+Payload = 7370d9b453936955b9c9d336f4b283237986232de007bf41
+CT = be2f03f6ce1731418a5f53b6f6e467b73992a0c8102d8ffc2d236162688096d80b8733d2afbcd244
+
+Count = 56
+Nonce = f479ea8812b6b2f6ac78fe9d
+Adata = 20c2b8f5d3a65a66ba8a25e2ee339a779a32d45f5db91077efae6cf308feef50
+Payload = 59ff9f7581a781808d36fed378080963f35c00ea5a6e3932
+CT = d127c956349c16e2186f55b72254c677f03c61f1c4ada9e661bb9415b32d6a58f5f7647ed41de685
+
+Count = 57
+Nonce = 423515f7bd592d6a7a240866
+Adata = 19eef6f798fc68086aad1cda6d7976cdcfe6b8af74598032972c939db300d8c1
+Payload = 3c379f90b11c622a765756a15efc8fc3ca7b08b3281945f5
+CT = 15792e01fc17f5294c3405484291082c00a8f46dd9af8ca230ba95c4058501234a1b97543c998e9d
+
+Count = 58
+Nonce = c3f3da69e13c5733039744b1
+Adata = eedf00aab5edefdd6549d37ed44358e11c588c24f141dc5731303fe0bd56b11e
+Payload = 9db6fe9adb8c0fee87cac9a7f01a7ed8a84f0512d09b1834
+CT = 9b6b829ca1dc4e90d4402188632ea3377cbec2ba60f0f072afca1b08b6dd589a17a32d49b6f7135b
+
+Count = 59
+Nonce = 0a57d59f21ead5b6d80cd2ce
+Adata = de5f2d413c98c6ea2a5640a7b1c424aebe75cbc78b06710b5bff8bec6afb5a76
+Payload = 0b5f6389f7c20f4ba326e8f05d373ca27b7ebe59e6d729f0
+CT = 0b704e14bc7d2977d89e0b2e7ed7fe3c9e0f2ea80d2d6165f344f2f1b2218d9b4283fe640a6d315b
+
+[Nlen = 13]
+
+Key = ac87fef3b76e725d66d905625a387e82
+
+Count = 60
+Nonce = 61bf06b9fa5a450d094f3ddcb5
+Adata = 0245484bcd987787fe97fda6c8ffb6e7058d7b8f7064f27514afaac4048767fd
+Payload = 959403e0771c21a416bd03f3898390e90d0a0899f69f9552
+CT = cabf8aa613d5357aa3e70173d43f1f202b628a61d18e8b572eb66bb8213a515aa61e5f0945cd57f4
+
+Count = 61
+Nonce = 2a27257bfaadf23a87df082c57
+Adata = 0001dc666c9daf3560daeaf514270db0b5075d295068e6caf231c1de0e1a9300
+Payload = 6cbbfa6d736fbcc4cf73ab4d7be537420e0e574ee1f2d1b5
+CT = 72d525e6bb312bf2c20b91f41108779789c25720797ebffa4cd9d735f51430275387c565cf1a69bc
+
+Count = 62
+Nonce = b94ac8ed14895c80a91fda8367
+Adata = e1eaf35fb266f243a3fa407cd41815ae6432ad79877bfa59d8f196cbf19bfbb2
+Payload = e6ec561496ce18d96b26d594a47ffad02d68ef25d2d2edb9
+CT = c63500445239bbdf71a8dfe3f8c01061d659cfeb038b825dc89fb5f507f5aeefaa9365f0b18dcb3c
+
+Count = 63
+Nonce = bbae10aa491ac9c668a3ba8d7a
+Adata = 981fc31e64fbad244ba1ef0303ba1e4beef5bacca74f60ffdb9142a25a1ad5a3
+Payload = b9bec3e2adc83620772048d6cbfb6f78e4fad74d754ffbbb
+CT = 9c629c375f014e162895cfc25a972c29839f97407e7c7cca83d0a61d453d596fbc5c2e315d9780bf
+
+Count = 64
+Nonce = e0b10e78e9fb41ee970143e9e3
+Adata = 399b71ecb41f4590abda79045cdf6495f27daaa559c1b34f513b5c4ac105ec10
+Payload = 4b81804d777a59b6a107cf3c99c9d1a35bd8e4ed36596789
+CT = 867799b30558697d6efb4afcfe458cfad8da21139a0b43128e8f8e13b7896b244d0c9aa52ed31a95
+
+Count = 65
+Nonce = 17b61109f5e37754e4e92a28d7
+Adata = 0bc2fdd890c19882640f8d4188b88b9db99cc1934cc3e98a5df08589287968a6
+Payload = 347c1eb4aff917bc0012f005e74caadc93f4f18f2b614ece
+CT = ee19f3120991b67b2389e6f36543d99590f2e6d785c9c8ecc40eb85585cc3b7520a940a4e993327d
+
+Count = 66
+Nonce = db3ca9e80ab761804349379961
+Adata = ce01369d08d37dcda2c899c9fc0d11ccf94a0051b2816a1d6c3ad07fc8dd02d7
+Payload = f0e1af1276d2918be91a191814660bfe735463d3983de1ed
+CT = 0f1b1228729b181772d7cf55ad257fbcb19cd46f7b31a885401358c7b44aea27617b429583103a1a
+
+Count = 67
+Nonce = 1f57959cecbd377374477e33b3
+Adata = de1c7c83ac61e1f99ae99b198f4af5d24f8de60ea98fe637f3a801fab38b2a4b
+Payload = 42a42b84df098ceb43519c4cb86c14c2fafca39346159e13
+CT = 12425453de653d0fe8103013fde1ebf4a8fe18f76f0c9d60e93525fe8048c3b2147a149f12eaecd3
+
+Count = 68
+Nonce = c9db03e2efbab713b0b6404210
+Adata = a2969243b0955402ab45a430fef2ef9e0c025006732bf8e592e3d3884918696a
+Payload = d633a5a3defdde6a68f959ef39a91c6ea6e13ef1a7859d2c
+CT = 5cdc183c32b4c1878eb83e8473a17c55c88e2ad6b944ab1f64ddee42614aa737231207636c114575
+
+Count = 69
+Nonce = 89ed296a3ac03fbfb71422b921
+Adata = 1ffbe1aff0a1e7fa3e68be31a74612a1519b59397e7007ef61fc015f316d55b5
+Payload = bff42516e30c92ed46710013c656600406a48a84c1fa32ce
+CT = e08c1ab4ae7edb5184c30ffb3e74689ea855f50b0e890392f26b130720f75c422fdf66fb174383b5
diff --git a/lib/crypto/test/crypto_SUITE_data/VNT192.rsp b/lib/crypto/test/crypto_SUITE_data/VNT192.rsp
new file mode 100644
index 0000000000..06e9ff5655
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VNT192.rsp
@@ -0,0 +1,456 @@
+# CAVS 11.0
+# "CCM-VNT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Tlen = 16
+
+[Nlen = 7]
+
+Key = ceb009aea4454451feadf0e6b36f45555dd04723baa448e8
+
+Count = 0
+Nonce = 764043c49460b7
+Adata = 6e80dd7f1badf3a1c9ab25c75f10bde78c23fa0eb8f9aaa53adefbf4cbf78fe4
+Payload = c8d275f919e17d7fe69c2a1f58939dfe4d403791b5df1310
+CT = 8a0f3d8229e48e7487fd95a28ad392c80b3681d4fbc7bbfd2dd6ef1c45d4ccb723dc074414db506d
+
+Count = 1
+Nonce = 026a0b8b17be95
+Adata = 44caa8ecfaf38e5e773cb0366e1b04aa0b9fac5c34a362310f471960c4a1e1c9
+Payload = 0e52a384cedcdf7f179348de6e7336aa86f8855fbd903cfa
+CT = 3417044bad5fddd9455579123dda4fd342c273a57ff6333dfedf191496d88cbe17c6271b65096e66
+
+Count = 2
+Nonce = ea09fbe5da0fa4
+Adata = 1d9799f2bb0f7ab57fe3de27949ff64066131c81bfee172b308f9bb0b3171067
+Payload = 469ff9698cfc96b581d7115c822e4363d7355ec5daed2eae
+CT = 1dae7cc16f1b469290902cfad47b959784b4d6f48a79e690d47e30b635d10d1663477d61d7ffb55d
+
+Count = 3
+Nonce = 8d27bcbf9ebfd3
+Adata = a7070b85b7add9193c9dcd2e6c03f6e7ecc52ffe9e099866baf7472f20c03aab
+Payload = 225651d072dc9d93762dd79691ac2b6ddba00ec1252d69eb
+CT = 5da819adefbf794612eb458519debcd524c283763eb3d7252eca8766bdf0db6bb2dcc793e1749c21
+
+Count = 4
+Nonce = 13f560187b6077
+Adata = c4ab4244db75f8256e55c5b613a07b11c963c3cc24f66128aad4ba8b7ca99331
+Payload = a38231af405dc7b70c8dbc8cb84e6be8a0dc2e95fddc2ce8
+CT = 3aedcf8347aa23fd3325ce08b6b00462536baed69968a753feab6761c55431bb5668e1f5b7505e89
+
+Count = 5
+Nonce = 61e0e28bf344a9
+Adata = 5f998952de70449ad46428f2ff8a01c5af43c0107a1bcc6930f19d4112598666
+Payload = db21b37e875d7709a02239ce6ea529cf37255d5b617c153d
+CT = b8f5fed39c723d7643d6dcf2efd3bbd1ba0da1ec901305fd64b2302ace4f66216ca8b4d776197692
+
+Count = 6
+Nonce = f6be4aad63d33a
+Adata = 18339be863fb8a887d04ae9ff3b4a7db095075cd5d113a9ec87b41fe85ea405e
+Payload = e53101e6eabcda32c13d7b1dd1d88e7c2ca3ddc2064f64c6
+CT = b758858ab60e1630a0883d4d330119a593729a3015c42525effb985b9c2dd9ec954bd25d9c464c67
+
+Count = 7
+Nonce = 2c1c59aa0d8eff
+Adata = d44af86b89fda8448a9b2fcae20ea156dd8738c8251699c02b785811c830bf72
+Payload = 1fd7188a43dee7b059420e8634d71d2c0658f6d0d308dc73
+CT = d046f845a67800a5a58f461e5a8641e8fc9b4c53b32e61d172adafffbacb297d67f6b5c02b982e04
+
+Count = 8
+Nonce = 48e4598edd191e
+Adata = 61588bdc980ea2310e87dec4c651e9a55c27e3858b6505cbf3bf85e51931badc
+Payload = c25868f390af5e59c035cb5830e018c62c5b96bd35b764f1
+CT = 0ece161bd77b7f969b3b20c818769a98c178d84524544664500ff4cfe66ade1832babc019778acc3
+
+Count = 9
+Nonce = 6d576ce3c5fcb5
+Adata = 92c598cb5ca2926c11f67c3b3cf25493d77606fa60d7290430e0e975091644a6
+Payload = bcd97479db934357a163a9e5f5a85999ca987f8243d8017b
+CT = bee185e11b3d42bac846b9d92c70a078aebfa630ab763840391031b3a22b2adeb9791ee35765c8cc
+
+[Nlen = 8]
+
+Key = 1dd56442fa09a42890b1b4274b950770ea8beea2e048193d
+
+Count = 10
+Nonce = ad749d596d88a4b4
+Adata = c67219909828adef64422286008e1e306867a1c0b3da95444507a68b45c953e4
+Payload = bd92d6744cde446fc8621625658fc4bc00dcb97f06195ad7
+CT = 076cffd0ca978fe2bad411ced45a090abafb22a99896f6a75a1969276aa2b0cdb37ccaf2845dbf6e
+
+Count = 11
+Nonce = b1dc81d116d94f5e
+Adata = aa4b71906b6642f10f66c2391ec157c7cde97eb322db10045af4c5248807f691
+Payload = 9aa6dbe1cd3eb98d330c937d31ef93bee8938b6c5cfd38de
+CT = 720f6876ac91665f20147483f0655fdbe21963a01e36f1daa67e36d7cc8d54cfec0762514475127b
+
+Count = 12
+Nonce = e758738df5c89af3
+Adata = 5715fa238f432c926e62dd93708d0e3145428e0ed45e1efa8148d2c4ab6cba50
+Payload = ce80b99039a16e69018d1e3c239dd1bf06e94a78b0b1df37
+CT = acdf7ba3edca1563727ed85cabf085c2f0c8f27556c3c064ef50d85bc3ade6a773d956b2660ac367
+
+Count = 13
+Nonce = d586c4c67d535476
+Adata = 1e8dc63c6c54a540b6b02067ba7c719221cf289fa3897299722c9a2bd6eed05b
+Payload = 2f88305117f9a5d807d54b7e95ecfeb7327e52d9acac352f
+CT = e42b86e619be1a38973c934babeb4688243a9012c85d643d81e024aaf0a62b353f9bed36681288d2
+
+Count = 14
+Nonce = 77e83758f68d272b
+Adata = 25c80edef3d5bd8b049fa731215b80ca2ee9ee6fb051326e8c6d0b9e11e3d7ef
+Payload = 92e47b82b728d639777d5d5843de2a5c364956cb4b21cabd
+CT = 1b9177f5b76403cb8c690b39c3dd22b55da35cebccb9b64e05fe32f796f0b4a75a459fce6c7d740c
+
+Count = 15
+Nonce = 311dc245549206cd
+Adata = 87767f13bb4904d0df0d64eb22c9ddb65e81b5739baad86ad5e2c239ffde9f6c
+Payload = 8691c0301a216a5f3ed9123886d100309bd85630d6b845f5
+CT = f39fe3620a03b37a4bf457909e0770447b498ad2a2f0f9d7b75f9e4239e43bbf93066897e60f6fbe
+
+Count = 16
+Nonce = 2a17b70f10e120c0
+Adata = 981fc31e64fbad244ba1ef0303ba1e4beef5bacca74f60ffdb9142a25a1ad5a3
+Payload = b9bec3e2adc83620772048d6cbfb6f78e4fad74d754ffbbb
+CT = 92187955ee1ae702ef01a385537119b2bd4545402e8b2384a0c069a2439a2d8843302c6a9999e658
+
+Count = 17
+Nonce = e0b10e78e9fb41ee
+Adata = 9d072b8a3f1a496b2be6728a38b94a4f44c9be40c8793b69afd81d01696a6b4a
+Payload = cea28e7cd0eff0c5eafeec908d4aa8ba303e72ada33db087
+CT = c605e48f2e66e8e0a92471e466981ae5e31db3e4ad80b09f5005b06d15f63f2f015cfe447828da09
+
+Count = 18
+Nonce = 02d72dde23f9772c
+Adata = 2dc44c39940e2d9c94d2dbe40bbf5cca5efb4d4b250a31aa24f208b87e9c2453
+Payload = 809343e986f6ff47f54d4cac22ed39babd12271d4c7edb58
+CT = 0bb59581f22f6b15de76c0066645495a5c19e44381c349263ed92ebb789c314a89c83542b15ed694
+
+Count = 19
+Nonce = 28c4d6de3e2ce51b
+Adata = 913a8eda924589d3206ce0a951fef93668c6c0c454824b217997bff6b3026d54
+Payload = a19f65ffdafd6ad5ee43570f7e168f94a8b4a7b7402ac80b
+CT = f0c91a29f1222b906550ef5c7c0944c5c4236cb6c31122cfada8e796f2ce7f9449f42de504873868
+
+[Nlen = 9]
+
+Key = 8cc622645065c72d0d2aca75802cf1bbbd81096721627c08
+
+Count = 20
+Nonce = cd84acbe9abb6a990a
+Adata = 447b6f36acdad2d1cfd6e9a92f4055ad90142e61f4a19927caea9dbe634d3208
+Payload = 597b3614ff9cd567afd1aad4e5f52cc3fa4ca32b9b213c55
+CT = 2d7fb83e6621eed9073e0386d032c6941bef37b2cf36a4c6c5e36222d17c6fb0631c3f560a3ce4a4
+
+Count = 21
+Nonce = 1fc7a43ed124745d04
+Adata = c892b095173076a40e24522297be27fd3a765c8d417f24c71a9f03b3fe3d8e20
+Payload = 415cd8312dd20a1c26f4b90d98104cdfbe06739466fc0aa5
+CT = 7bebd6f55f15ae57ab73f92f7be6ff37ddd99740e988f01a7a2a13c22df4a156e6d6063235452c85
+
+Count = 22
+Nonce = 19ff5e7c1f2c594abc
+Adata = effcea4e4dbc57410426b39fcf51c9daecd9d310888590d77827973a29c4ebff
+Payload = 97fd2c259a4e672e9555a9a5b98f4c0ec8c4c49c7ade26a4
+CT = a460674c2f358762e97dfc958d90973e1e419dbc6a832e987579b2c4a6bcf0356f48cf8959cfa54a
+
+Count = 23
+Nonce = 64d9bd368ac2357cf2
+Adata = 62c5a16f946b4312517f67c80afe2614c822e3a01b87dc81538c00bbf3fc0108
+Payload = b6ada12f7a28211e9d2c07cbb3d39fa77aadc077b34c46f9
+CT = 8fb5e0954388b9b58519482962487e9b0768f0cee08afe9a92be2b06a0ecd2d00877abded7d9634c
+
+Count = 24
+Nonce = b4aaf2cd93efc0ce93
+Adata = 79d8841ab83279724ce35e1a8abd4e158168dcf388ab4c3d1ae70413e4e43d14
+Payload = dd42449da4c95e858b796085b6b5b3b5eef484dbf3c2bc8b
+CT = 893f86e29972928c1f3c3e25c73947c8d677814bca7fff2cf8d301ceace678f9bf91fc361dff5812
+
+Count = 25
+Nonce = 132f3e19e12f462a74
+Adata = 176cc5a280f6171d00e247edacc81f05c1b9faa87fc831163ac9d76aae59a6c3
+Payload = 8ea05a5033ab8b009664fa2800c24e217488ce6888cad147
+CT = 4771d210ea678dbfab96e320e9c44b68f47cb05b01826ccf42ca4f4ccf986eb6a6b85b99db2fcd93
+
+Count = 26
+Nonce = de709ba64cb75704c0
+Adata = 0cf8e9ab95766b6fa85e88d86e4f349a17c0d90509939e343eede988e7462255
+Payload = 51dd9fda9549f25dd868245a6a54b8d59346d2f336adf9af
+CT = fccc3e44afa6bd2fbcfc5c834db63dc9d152c04c0dc0b43d393162252ae91ca46fb8e8338cbeb75d
+
+Count = 27
+Nonce = b11b4c1b7a26387265
+Adata = 14ed867cc909c0619f366918a7d5ae25279fb137e1dee7fd98ddbe3bd19d841d
+Payload = e35ea4a16e274fcab457fd4dc7886c3d81fc668c19e0f374
+CT = dcca8aa2eab8ac3f5db9cd9560ae0758d7df40d7d868d1f71f498ea6ec8251a6d149c7ca38b25fe4
+
+Count = 28
+Nonce = 20d03227a7fcaef1ce
+Adata = c5c15245e641687d0ca9e913406acd2de3f21fbaf2dc5e4e8963222da61d02a6
+Payload = 6775e5faffd0b13e78da70a789042245d5ef31eab5245380
+CT = 4bb8ed2207f36f40f62d3a2c90f8e3bd8f589059b69037118ce3ab864545ea81943ef0ea9489d223
+
+Count = 29
+Nonce = 267f76b9ec0f5e7c6f
+Adata = 2b421be47d07dcb12a0706f7490d05024fce8f433079e18ec78f4c8678f5f155
+Payload = 9330bb23428ab45f573923e977db74882282cbe1371da68e
+CT = c6ae24f82ac5cf9c18a2d98e610027eb2566a1ccfcf99945655e14c7bc8be97ea47388cb7b18bcf0
+
+[Nlen = 10]
+
+Key = ab72eef2aba30205c986e2052d6e2c67881d24ae5fceaa8f
+
+Count = 30
+Nonce = d7a46e726ed43f1580eb
+Adata = baa86f14271b2be7dbb37ddc7c95ce4857e57aa94624d594d7bd6ceeaada8d5f
+Payload = 2a794b84fc9e4a7e6d70a82b5141fd132177a86b4e8fc13a
+CT = 2d7f76464417613bb61d3657481346b74fc9d6abc6a3babd39365dce86859cd82395d11bfc8cf188
+
+Count = 31
+Nonce = d0afcbc1b2524a4a4553
+Adata = 7c267223047af946b06f6a45ffde4a5ec49c28b81ca22da4a36bf523e89e9da8
+Payload = bfc5ce1316ccdbcd8ac62484e7656c87947ff98cbba8e1e9
+CT = 4772c121367d0e8d3edade883342395f3ea065fe7dd7be8c8355b915ca2633fd557ca7ed41e00926
+
+Count = 32
+Nonce = 6eecffd227e8d5349523
+Adata = df7736560b1a13aa8e536500ea6cdb9a6757309aadf25a6a9189055a309c3f8b
+Payload = 19eef017100dc82f26ed0815c55c122e0b1587302894c391
+CT = e2864c6e12ac089daaa1e94af4b2ed04060d7ef65d2f72f0e7d017514d498f1f3c07d650afde8293
+
+Count = 33
+Nonce = a67c0675753f725a8fd4
+Adata = 7dd546397a9a0129861fb6815d419a307f90d259d55f3503961754126cd1b776
+Payload = 80f1f1ea46c92d28f2d60eab39ce056a4aefe63fa688538e
+CT = 882c687c03eaaad9d7f591649e736f0c1c78f95e40d40cd77499a8544bc2a8fe95f55fefc7316f8d
+
+Count = 34
+Nonce = eb83928f0d5f7aa3a74f
+Adata = 060cd3e4aecdb03837dfa9f544318c0a16cdc37fa2a3135be7888ac67e7eb26b
+Payload = 81e9174e9472777b6b184707108c01d6ea6b5d108ec3c6c8
+CT = 243cfa0a0a36a4c20333968910e6f52acc04c6f74e704180623f3a13fc13db958cbac49f7421d6af
+
+Count = 35
+Nonce = 5757abe01f7a1183fdcf
+Adata = 744629263041f0eccfce4a1ebcc18c4c984010f9241d35966263a8b2f72ee26b
+Payload = 991049f26b529af8b0bee0cc83989cf817d248254182f332
+CT = b20469b5f33f0996e8de869ad10ce09924a0bdd7b67a89a09c447a3132fbe5213133650000d50b06
+
+Count = 36
+Nonce = d9adfc5b44ad7aa94b05
+Adata = aa6a5448c6ec87be75eca35725ad2e902dbccf840d25b2bdf7e62e4a8fa4a511
+Payload = 14682301a99bf680805d1ffe62e1506d48cee8c51ef1d255
+CT = 9b44efa185b0c10325bb4c3c0815e6a6e46eea366b9a416b5ae554cb440eadd875657fd5cecc214a
+
+Count = 37
+Nonce = dc3ca30782c9c0a7fe89
+Adata = e788c98ae85b11b3ae884eed6f3b8f5bcf5ab1b7b20ad3f44f760b2287cc5793
+Payload = f9cb86f24536931a1b095b426a07e4621c000cf09b472bf8
+CT = 463f9124d1cc387a0f8b971d1e2da448f0efffc3956ebb2af8312986315522081f0989838ef0429b
+
+Count = 38
+Nonce = 9523f53f92b6e4ba86e5
+Adata = c3b123ccc916d26a2e6a8b5e30041ad69a944217e9b402b7acc0170c31e8c2e4
+Payload = b9bdcac80f64175836ab51bb1a1bee5ffe3a6b9b71afe3ef
+CT = c356b5a78cebd123808fb740754dc47a8ec7c9448bfacf39768e94f062e86129cc9210dfcd3e6128
+
+Count = 39
+Nonce = 16bdf18c09d60f3a2a32
+Adata = eedd0796f23612749e9fd282c864f3118d0683409d3bef1fda352e1422273c7e
+Payload = cc96133e473d197be1bafdfc1a21d58e57d0d89b2ba1c3ff
+CT = f9d78e9e3a41b3bcbfe756385a3715776eb84bb7d8d15432978757883f07802b25e9a5b15c43b451
+
+[Nlen = 11]
+
+Key = af84c6f302c59aeee6d5728ed5da2e3c64a5a781c52c4d1b
+
+Count = 40
+Nonce = df990c42a268950677c433
+Adata = a6ab5d78427f297a4b7e21f1091ff3a5b20caa3fe1cbcb09459d9df596a6c8e1
+Payload = 6db41aeb5f7c24df8929dbc30483b3c7934b3bd1cdce5bb9
+CT = 8c9328258bf71970d33e23a3ff81cc1c9cbe196a1294264bfd6a7255e4801963bb30a63de3fc5b82
+
+Count = 41
+Nonce = b7ea72641bbe2dca6d85e7
+Adata = 4e0f2ddf183281ec131693bdcea3fc9743733c07a486a42d5737735b3f6e3fdf
+Payload = 726844e41b1e4d883024b32fee0dcea38c889cb328885b7c
+CT = 9a133e4582c2ebc445862a9c6f2f4e39223c84081e322c8f262de30da6ef505fe640c53d765f672c
+
+Count = 42
+Nonce = 446fee1e75e79c0dfc9ddc
+Adata = 42b598eaee271e06d9e98dd94152b28ef10f506d65bd660b2fb8b1be9a2d7254
+Payload = 0cdcf348ecc9c3588001802c2106fb64be9c301adcc66e73
+CT = 0c2657b0482b6ca92e1b1c8fdf75eae3b0cd3af205e9bca396ecb1e46beb16000d585e1d9559ee22
+
+Count = 43
+Nonce = 2e6e34070caf1b8820ed39
+Adata = 8bd1ef3a1831fcc8919d736fb23111ca3ef4cccaf20264fab8eb3b071e56667f
+Payload = ca0860cc1e96506c2beb25b53d2947fbab634f0372afc8ba
+CT = 19e4774030e43e6853ab5bf176ba9c4b59f29f285977e3c15198cbe3e34c884c3f56a732974aa1d6
+
+Count = 44
+Nonce = 428542ecfb94a745980aa6
+Adata = 8efe01716b9018084e2ea7616f85b7333d945c0c970f8cdd400130b98db67cda
+Payload = bc6b59120ba2845b0e41f65a55e2ef1c45a81485c926c14c
+CT = cb48b0af6fad251d409d14ce0fbfae9cd9c40bf4a0c1e2b7e7cec415030997e1ac5db974b617b5a7
+
+Count = 45
+Nonce = eff703e6d72ddd23ff52d9
+Adata = d7fc74035e66709d2590b7bb3276245dd43824c9896fbd801ec1d07018b39b6b
+Payload = 1a5432e8085511ddac1be91be3e2945f85f0cdcc3a1c9f8d
+CT = c0a00cbaec65b7ca525fb26e80ee0cd18c7ef47c39c704833e59bfecf263bfdb24686627fd95e120
+
+Count = 46
+Nonce = 6a652ce21334a40a259dcf
+Adata = 5d24d80f22afe713c4076c200c1bab36917907fde7b6d34e141066f543526db6
+Payload = eb8f1988cb405041bf48d138ad41da7ef364d4ac59a9e324
+CT = d4f23166c09a15466c7e0e2b30627ee5a84f22d7e6135b4a0652b67d559a84b4a915ca6a420fd300
+
+Count = 47
+Nonce = 9382e12d447c0ca23cc9c3
+Adata = 239129eb760f8a770410c160e4e13a6b9497077c3e463b65397393fcd3cb5c70
+Payload = b40e80564263c7f450c53ef84df67247d72e8a04dbb284bc
+CT = 6de2ba26caa80874814816154784912c55e3d6da83488e7250f5a52f82211542b4e2661cf870c80c
+
+Count = 48
+Nonce = 2c3a4148cbb02504a2483f
+Adata = 33c3bdbf185b580353de79e51e675b03b31e195f19ba1f063d44def0441dc528
+Payload = 60a31736d99c3dcf25b349f6110e1c152b93506e85a01e67
+CT = 4d5e705d08f3ed1ca6f1caa74b46e4b1eee18a0783686f207de16aaa41d06bc071657dacf14da754
+
+Count = 49
+Nonce = 691cdf6fe9ecc2154d0101
+Adata = dc096596644c4e09c44078b86e5e0887c45094042eb0d74a6a13aa2524463076
+Payload = 77e6441ee017a93dd876ff2c7980540c77ee15edb0f23933
+CT = 24cecc81c8ac7ca9906372dc5263f2220b4dd162f1e08283f07f23e65475a20fd96e45c6c695cd83
+
+[Nlen = 12]
+
+Key = d49b255aed8be1c02eb6d8ae2bac6dcd7901f1f61df3bbf5
+
+Count = 50
+Nonce = 1af29e721c98e81fb6286370
+Adata = 64f8a0eee5487a4958a489ed35f1327e2096542c1bdb2134fb942ca91804c274
+Payload = 062eafb0cd09d26e65108c0f56fcc7a305f31c34e0f3a24c
+CT = 721344e2fd05d2ee50713531052d75e4071103ab0436f65f0af2a663da51bac626c9f4128ba5ec0b
+
+Count = 51
+Nonce = ca650ed993c4010c1b0bd1f2
+Adata = 4efbd225553b541c3f53cabe8a1ac03845b0e846c8616b3ea2cc7d50d344340c
+Payload = fc375d984fa13af4a5a7516f3434365cd9473cd316e8964c
+CT = 5b300c718d5a64f537f6cbb4d212d0f903b547ab4b21af56ef7662525021c5777c2d74ea239a4c44
+
+Count = 52
+Nonce = 318adeb8d8df47878ca59117
+Adata = feccf08d8c3a9be9a2c0f93f888e486b0076e2e9e2fd068c04b2db735cbeb23a
+Payload = 610a52216f47a544ec562117e0741e5f8b2e02bc9bc9122e
+CT = 83f14f6ba09a6e6b50f0d94d7d79376561f891f9a6162d0f8925c37cc35c1c8530b0be4817814a8e
+
+Count = 53
+Nonce = b4cadb5f9cb66415c3a3b714
+Adata = c4384069e09a3d4de2c94e7e6055d8a00394e268398d6ea32914097aec37a1f4
+Payload = 22bade59214fa4b933cb5e3dc5f096e239af4c2f44f582b0
+CT = 2296e3f8a2245224d274f1b90ed1287cbeeb464c70a89ee475ecb546efb8872a3f8b0281b3901752
+
+Count = 54
+Nonce = 72e6cebdaf88205c4e744286
+Adata = feaf010f462ad40a38eefb788b648e1cc292cd4bb08ebeff3c39182862296042
+Payload = 30655a6b5a5965db992e7248d24141055e988d726abb8e72
+CT = 69b27f2bbaa61c4f24e1c25e0779147fef79ec1582486b4651cffa571570618e2ada3376bd9f3e5f
+
+Count = 55
+Nonce = d8030fb31eca2c43f3f5eb88
+Adata = 66704365ddd0145febeb33f68b228a3f09e1e5a4b68149e6e06d886301841295
+Payload = 9d014a02507a6f266bd1ace21b55ab8b73983ff503bb9adb
+CT = 233a883650538ab8c0da30b90527f880fcad5b16bd435e762beeeea7a638c717e63764b3a5118a0c
+
+Count = 56
+Nonce = 58038cc35ad3dcd75195e125
+Adata = 3da7a757e942409a3b39ccdc0669ce6401f7e133c07c4c42e366d70a8e9bdd49
+Payload = eccfd817fa5e3a0146967fae13fc2471ee3944cee37969f4
+CT = 415a36872a04f5b4b5372f63394ab9fb353e0eb9b430450133a87fa29e5fbfa9bc0430b0cac00b7e
+
+Count = 57
+Nonce = acd82ae31bfcabd90af5af45
+Adata = ce22126f01bde16249c47102b4da68ad3edebcd4a16c24a16ea7ccdd5d364d10
+Payload = 9d2126d34963d3ba12cd841bd321036cb82cfb78f2a6535f
+CT = 88a5b889e6fd74fc15336e23374b430988416c7e6b6e7248b336cbbeb64fbebf2e7076a98ecf5bbe
+
+Count = 58
+Nonce = d24457d567fd0a65fdabf219
+Adata = 0091d39f3478d2c59bf874b96db9ce0f7e8b85a9b805e07dc96b219819d51663
+Payload = 6da3ac85505e93c4f391ea367a9e15fa9b388ef7ae2693c1
+CT = 7039a8a49cfa6402b4ba3b840e69200c13ac4a3eb1c709a30ea909047af4998c660afbaf346ed65b
+
+Count = 59
+Nonce = 50c59ca54eb64575b82b13c6
+Adata = 5e4e42cbf172853c351d597c7d6d38b1a9cbb7ac92c00863a80ac4a2d9f0e7fd
+Payload = 25b2ba0a937b71f3ee68e7172cf2c4524b662efcd08ce2b3
+CT = e95fc44287ce39c5ad6b91c88582563fa68a9e304094deb8b193dd767f17783f0b51ac0fb7323301
+
+[Nlen = 13]
+
+Key = 36ad1e3fb630d1b1fbccfd685f44edd8984427b78deae7a9
+
+Count = 60
+Nonce = 3af625df8be9d7685a842f260e
+Adata = 308443033ecd4a814475672b814b7c6d813d0ec2a0caeecbcaba18a2840cdb6c
+Payload = 8b9db1c8f9b4892a5654c85467bcffa2e15e28392c938952
+CT = 6bc6890fee299c712fb8d9df9c141f24ee1572b8f15112c2f8c99ccf2d82788cf613a61d60dae458
+
+Count = 61
+Nonce = 24eaeaa437649e61b706942b8d
+Adata = fff75462f96157d9554bddb6aac156fefd88fd4a90a8536dfc28cc577f19c83a
+Payload = 49ff4ff85f7407ca383cfa4fd7177adb4dab26e642c8186d
+CT = 3647fae50c588d792442f43a20125e77ab5db3c469391d24d0a421bbbc002eb9ac9ad01f625f824b
+
+Count = 62
+Nonce = 7325932d6694aaf61a8204c172
+Adata = be20ceb8ca14e9bef7158b280a26bcac763da79cd0eba9b1833ea808c5e7a66a
+Payload = 2861494eb40b9d964d339797c1b6aac63c6674187768957c
+CT = 286dc74001e2a6000a23db164f4b2912de4afcf1df8c3aa5ee32a7ffd4e7bc303d3482fbac431828
+
+Count = 63
+Nonce = 61c9949df5853e42599e5ee0c7
+Adata = 243d09ceb16755cb58d62065df84890b840ad9b7eec1132c6427cd7c3d843fcc
+Payload = 943a49073db6ae94a88844ed895f8fd99ed25c3f42a2f78c
+CT = d3c56bd265a2cb0811dd218f248800ceade4f02b5403b9635eb30cbec49cbb51c41cd5032b7fd759
+
+Count = 64
+Nonce = 07b6c18dd3b0fd9e8ff026a436
+Adata = e85f141c3d1af7727fcdb00f8e2c34e42a436d04ac5b8ca9f321a178a2056806
+Payload = a18b0a4618063c0519818d113b8e5435aaf153f664058f1b
+CT = 69f933a2a5e774e8d013cbf78c6ab0b73e6ca323d0c52691acb5cf2631987d3d963349b035324aac
+
+Count = 65
+Nonce = 0c075df70630dec2fe81834945
+Adata = f3f5c5ffbfe8247bc0c33c793652f749fe91b6dd141cf0db56e71cef8a2fd266
+Payload = ddc4bac4115e8cb06d29d22e400674dbc615a667f933603d
+CT = 26bdd25c9f204fc7520d26c161464c28fb35e395b295b3db4e239d33283d18415b54c2aad4bde354
+
+Count = 66
+Nonce = 0c2d20375057fcd4241d290f6a
+Adata = 70ff1b9ff8ec08fdb18b0e7dbe01127ed0cfe0b0a449ca2ace4992b7b6248b71
+Payload = dacbdf1979e000d52b573e74800761b30acc26681f372acd
+CT = 6a642c389433a3464fc64783ae6a14a9a45f0998b56a5b9162d7e0320dc930df3640a786d7ea9ae4
+
+Count = 67
+Nonce = ea0801cb3dab853750a922dd25
+Adata = d83360d0896e022bf014bd33710ab212ddedda6d95a54996f33db304e5f12f01
+Payload = 46cc5653bbd8300dfb0df6d0af3fb7c7639a830bdc9f68c7
+CT = f1b0728920351d9edfdbe7df360b21f6cc5b628dcf43a3f10d06b4a545609a2128a95d4d73471559
+
+Count = 68
+Nonce = 97e6de379c90fccf3fa8f27013
+Adata = 539f8eb802bfecaa4fb5b19debbf3d4847db9c4e0473a308ab3f3c859e68fecf
+Payload = 8b013f52a828905013f250fb9c006a173f6c66a64b5ba317
+CT = 556a439bc979dac1cfea8c5b64aa78547f52a62896c19893f3512baf72cd79ba9301194be204bcc0
+
+Count = 69
+Nonce = e832b6330d3e5e190598cb9c61
+Adata = 093be516277e8b197ba5e9c85a831529befff0f3971510ab611dfe0dfb50a2ad
+Payload = 635d2d7894bb816f154210946a369df37ea492993ba23af9
+CT = d8e19c67e5aa7f14a16ecaaac414a2b15a15bb5f966932e6b0bfe9a5857fd36df94aeadda7f83a79
diff --git a/lib/crypto/test/crypto_SUITE_data/VNT256.rsp b/lib/crypto/test/crypto_SUITE_data/VNT256.rsp
new file mode 100644
index 0000000000..2817684910
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VNT256.rsp
@@ -0,0 +1,456 @@
+# CAVS 11.0
+# "CCM-VNT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Tlen = 16
+
+[Nlen = 7]
+
+Key = 553521a765ab0c3fd203654e9916330e189bdf951feee9b44b10da208fee7acf
+
+Count = 0
+Nonce = aaa23f101647d8
+Adata = a355d4c611812e5f9258d7188b3df8851477094ffc2af2cf0c8670db903fbbe0
+Payload = 644eb34b9a126e437b5e015eea141ca1a88020f2d5d6cc2c
+CT = 27ed90668174ebf8241a3c74b35e1246b6617e4123578f153bdb67062a13ef4e986f5bb3d0bb4307
+
+Count = 1
+Nonce = 195c0b84baacc8
+Adata = c7d9557b2ed415652ce6faa8cff5217ac803530ec902890b31eaaf3eeb0aa98b
+Payload = fe012718481b2c4e1d7f9a7685e3daac43ccf22cad0df900
+CT = 893af0f130f1317de9f217234274b0c04fcc202cea9a0df882c00b5b463654adbf82888099a7d258
+
+Count = 2
+Nonce = 363e0e921c6f11
+Adata = 805678936d4e94746ab4818dc5f50c41e32cf32e7a8aafb300fb91af6406108c
+Payload = 7e7e33e1a07d4e8fde2f33304f21cb564d146860ccfeb49f
+CT = 645cdd11a1c232815ce1e07ca3ea83f372eba46cedafddd980adf2762a1617adfd4d8356bb48aa8a
+
+Count = 3
+Nonce = e323cc866af462
+Adata = 163c747f3ba4ffd68af87f2475f48f2714659a2ec43b9ed115e02fe0e3c8be99
+Payload = 2bfc76f3b108ba3118b07433c4d3d5f41564d22547c12822
+CT = 0db04c6b068e73e3c4d71059bdeee3d27622f99dfd07d868fb9c02753c57fec7e1a5fa8f3860501b
+
+Count = 4
+Nonce = 03ae777078b95d
+Adata = f1dacf9062dff9a6a3d0498f9d058782f891475684196bf2d8e7e905393acff7
+Payload = 38c4275a5f605fd1d99517e13deebf0c9794ef586070fa9a
+CT = df8f524872b5f06f3f219ba76524990b466409894930d7e0d104990e598eabd88cc8342ac16424b5
+
+Count = 5
+Nonce = 1c6c351d4fe9be
+Adata = 14285e97cc3cae452e1a52e2fa0bbe24df96abf2faf6b9779acc59764612eadd
+Payload = 9e2220f3c17532e1ce0d6f562b049fcef35bcaf9a7e196be
+CT = c274b28228a6b13b670c325080f88d188d40d78d385481eae004894b1861db5d2d8ae98ed8926c1e
+
+Count = 6
+Nonce = a121dc27479397
+Adata = 359421e9f78cc4a31f4f019977d7fd29780524e20288798c50002a682a6368b9
+Payload = d42b16b32e77637724144eaddb21ca8d7db4e7f73acbf707
+CT = 56e3e3e59e978161355e7d8573dc0657db400ca0b083dae8ed2ac2cb63e1b9d7dc598634198fe4fc
+
+Count = 7
+Nonce = b1f0e26b60bf1d
+Adata = 2ab4239fffd13762fb5391f5a4760d12d96ea12666a793b4d651e9f4891c22c1
+Payload = 9a2851083ad4e7b915bb0526bb4054e4c0b4adf8626edc90
+CT = 5b2e0215523ff37f0df46e84f996fc9fc779986c766fa51595b8a23ee377d5c2850f4ed95a385253
+
+Count = 8
+Nonce = 50412c6444bcf9
+Adata = 09cdcaa87ddf8bbe6db8411d14bb9064e4a121286cc8a6e97fce1844935f436b
+Payload = b28a5bc814e7f71ae94586b58281ff05a71191c92e45db74
+CT = 05cbc32a6ca797684636dedd16ce65a1eed69bcab1b1bdbd514ef5cbf9991a919fb4974d55506ce1
+
+Count = 9
+Nonce = 225557b0faca3d
+Adata = 21611da060fa90cf7fd68b721caf303307a56e56453326495b628c7dc93cd175
+Payload = e831b739e8eb9f787f63c0bb071ddcc9f44cab8d5b447d23
+CT = a97e0879407eb3b7f93118ca73f17eb34e9f4baf43b07be2e8a3f7b848054cb235e1b58d6a12c5cb
+
+[Nlen = 8]
+
+Key = 472bf7946bce1d3c6f168f4475e5bb3a67d5df2fa01e64bce8bb6e43a6c8b177
+
+Count = 10
+Nonce = 790134a8db83f2da
+Adata = a7a86a4407b7ecebc89434baa65ef173e88bd2dad9899b717ca578867c2d916f
+Payload = 59eb45bbbeb054b0b97334d53580ce03f699ac2a7e490143
+CT = db4961070f528ccd1a5a0681ee4d0ce3515fb890bccedc2dbc00b1d8b2bc393a8d09e87af7811f55
+
+Count = 11
+Nonce = fb2441d1594a488a
+Adata = 0875020959ed969cfb38636d1d5aabce9658b00171a7614ea9e5395331c7659c
+Payload = 451101250ec6f26652249d59dc974b7361d571a8101cdfd3
+CT = 1bca7b0d35a68c0ffc568ffc8221cca738b67b95e3ab26efee21c5738d1f7fddf3030d004a702704
+
+Count = 12
+Nonce = 0855263860043207
+Adata = c7fc24863c33f7e8cf97b337918495d52d864ac570c99cbb09d151758d6b504e
+Payload = 61fcd7ef9bf151b9d8a81dc1ba4f82c45e9c2e4784627acd
+CT = 9b939b6b188e1d0fe016f366fb01eb79a99ef7b1b57c6f7ab223454c57c714d96681cd4d55615afd
+
+Count = 13
+Nonce = 415cd251a5e36943
+Adata = 1a393c7e85fb286709f4eb50f09640e1d65ec1135cb4443820136b3cec69772a
+Payload = 66ae08d494dc9df9b7f8f53199fa37d0c88885458b168c57
+CT = 1731e260ae31b8068ad1099313b167d9e6cbe49f471da61a9af96d3ce4ea94213b60cb69d92050e6
+
+Count = 14
+Nonce = d95bd65242bb2265
+Adata = d0e20e1358be5cc1c45c1cf02c82d0a6d0824cfcb65774cf95f047b9f2cc1d3f
+Payload = 312c3791c64d79205a11eebfc14b2d7a6b00391793c9559b
+CT = c3fbe558ff9ea83ed86b7d66503ee38eee94e4a41fd53f0f627a352d056712e0d44404c61712e2ab
+
+Count = 15
+Nonce = 3f0bf0141dd3ace0
+Adata = 9dd4ed18209dd6cdf19cc76fee443827e7331aaf020960c15d7bbed0f6a3b1f7
+Payload = 08354480047eee3beeb5ab165da17d23f2f1a4ad98720611
+CT = 2db9d2c54134d37ebefcecb9e2076034b975677fde58ef6032645a322fa9bc8aace600f942a84db4
+
+Count = 16
+Nonce = 3fd8b3a3ff563a42
+Adata = e58327efebad3276a7cd1b1ccb56db0caddd02a303cd9fc7ea5c607a2ebefaae
+Payload = d1abd89351384e1a3c3366f77c3175f6390801554d7cd783
+CT = be284dcb357ae99ada7cc891730320ebb32ca627eb8c80623957a2a5b6164218fc83e12c42d5c532
+
+Count = 17
+Nonce = 14db1ffc1c87117f
+Adata = 6c2b091433833a0ed915354dcb70d982095b614dc51a95a22cec417184d8e786
+Payload = 0594307491f157821e63f50c94034f9284f095d5b897153c
+CT = a114c84a10071e359bba2b2ba4ea67f893e27e6ea880aa4b2cf16ce68a93f8839245baebb2278300
+
+Count = 18
+Nonce = 40b0f74ff27a3fc8
+Adata = 3b9e1f4e9b57a6dfb5e0ca7ef601fc6af30a1f8650228e51e0dc61180d0bec6b
+Payload = fc8b7dbceef6b0ffcbade789e09303044042cd671607e819
+CT = d00ef56074a8213740af8b8f974f778db560ac365d6ce916b8d191130e864bcfcd1dec94a1aaeaef
+
+Count = 19
+Nonce = 96cbe9cd19351359
+Adata = cf498fd042f9a07503e490cec4873d4df91162cfde60bd2cbb2b710c6681a9fd
+Payload = 315e81c9ce556dcf97a5b68503fd2228a7a6a174a15cd618
+CT = 7383c2de08bce3f0b7e504dc03d062f44396bcedd2180fd954e6ec9f6ae1e0976ecf04dbee6463c2
+
+[Nlen = 9]
+
+Key = 58ae7965a508e8dd2eda69b5d888a28a1cb3783bad55d59d5b0da87137b72e93
+
+Count = 20
+Nonce = caa3d928d2bf2b7f2c
+Adata = 304678b3ffd3200e33a8912bcb556b3cfec53ca17f70ecba00d359f9f51d3e3b
+Payload = e61bad17640ecff926d0b0238271ee4c9f8e801dd7243e9e
+CT = 7bb1137c14cb4d324a4a8f1115c619ebf74927f0bed60a8d5a9140ff50dc4da375c7d2de80de097f
+
+Count = 21
+Nonce = cf09ca67659a583bb1
+Adata = 5507c4c3107cb446d19975f91207dbf3e2a51d1dcfd7da2f082159dbc3f41547
+Payload = 1887bb0c02500093a30a44b99e137483704b06615d308c6b
+CT = 834d3b2e5f0915c2348c706b4d2ff2717983ab4490edcc63971f02b7122d1e4f78de9c3376520f5a
+
+Count = 22
+Nonce = 97f940d7c1230bd8d2
+Adata = 56be2c9e09b555373d58f6fe2a0ca9b4ddba899addddf12b0fda860ad791773a
+Payload = 5ac67c9bec9b95c54e187a4a6812f5d701c4ac8f847c005b
+CT = 9f372ba1c87a115847cd708aaf5b8a143b6981ffc2c61cefd30ece13481609809b218de04c4e5ed0
+
+Count = 23
+Nonce = 147c7ebb6c92245054
+Adata = f95d64a513a9f3e6c95c9ed27b22fafd7dd10da52636029523142149116aff53
+Payload = 08f199a8d7e3ea821dd3106e8947cd2e9d485342b25a6471
+CT = c438aa6d187643d030dfe4d6b5b578f84838f4dc5c396d700c0986ecd7dab44e5e97db37392a485a
+
+Count = 24
+Nonce = b9bad794d49cdac9b3
+Adata = de9ff2a43f49cdc502cd17a373989bafd13fa6ccff6660557ce05b6295186d47
+Payload = 40d1cd4063750184356a1d7cae1cf1824f552c5d59a62dc1
+CT = 9952b25f4f4f375440cd958456184fe61610381ba92ca48f38dd977042c4d97da84e4effa650799a
+
+Count = 25
+Nonce = bbe054fbef86db3ce7
+Adata = dcec76181e3b872a5a6e79f070354e38866c7f67fc428fbca29ae6d929b1dd7f
+Payload = 5f29808ba74b672a0f82b3b7581dc32478c6e790e2b8c61c
+CT = 4d176f48b09b772dde8adbdaef720aba128a8d38a902847ebf22c81a5d824b4916660be6f9b513e6
+
+Count = 26
+Nonce = 6a35e1a4307f6efc6d
+Adata = af28120505a84a75b0f6b18cc9d8c75c661bf143be29c11d8ede78b9bb98c98a
+Payload = 5e2f601395ec406fcf96785f768162e849f867dca77667ab
+CT = 4e305e26d34711c6aa775f490939cc6560d3cb6905f5b0f5588ace6fc303600abc8e5825cbaedc7c
+
+Count = 27
+Nonce = f6c237fb3cfe95ec84
+Adata = 038f8ed89444784417a9c23bf11e9b436174e6c10959e00faa1704ce2f7f2c7e
+Payload = dfd9cacbf7d73d688447ebab13d2e13f3613652379b386f6
+CT = fb16c17a6b22a8658f446203ad46a48b34808083b271cabb015a1f78abc287bd2a63381ead07c558
+
+Count = 28
+Nonce = 50d024a3e7455d7249
+Adata = 8513365786b7988b208984e11022c15573f978bbdc29e8a7a4745c8a81885a1d
+Payload = 400317786b7df63373ffe541efcee6318cfc95bb673aad3e
+CT = d33b3141fea3a9ebdeb80d1da32dae42680be78471fb3023721f714120162514555b60560afa4256
+
+Count = 29
+Nonce = 02769283d5a06c363c
+Adata = 292c0be3713c6c588cb4e29a1c43b3e6353e33556194e568e800e4e44e8281e0
+Payload = 12ba8eddff1c2a03ddd25bb924ff065a93fd712b2c4f61eb
+CT = b15b1789c323a68568f86f35483bd7e204beff8f318ae14351f5e62b3b923a937e6c307af202fab3
+
+[Nlen = 10]
+
+Key = aecc5e18088bf9fd7b17f089bdd5607b69903b04b726361f8a81e221b1c91891
+
+Count = 30
+Nonce = c527d309ab29ee91c5fc
+Adata = 8f9a73e7bc1c11e2919020ba3a404cbddf861e9e78477218e3be2cd4337b278d
+Payload = d4291c99901345afe29f58912a414a7498f37b44362bdf3c
+CT = 392784a9e0b14bcd37639ec5409d6ead3e75f855e5a92c33ffc040ef3977e0035ce6ea6d157c18d3
+
+Count = 31
+Nonce = eebc31a5813b4fb93b63
+Adata = 9c87ad77953bf8a811e001ddb946eefafbfaa598150e85f0701853fa307d77d6
+Payload = ebcfd71120b0f9a2cccb898e6dfa082998cbe10032de3e61
+CT = e38eaad1e2df77e85e7129a8ce0f82cfc32b0aef79ab651bade65aa17e4dfb0aafe18cf71a72b180
+
+Count = 32
+Nonce = 231b33dc406c9210f59a
+Adata = 38be46d271bf868c198052391f8a2147c663700d9bb25a0caaa36974f18dacea
+Payload = 9032f910347daf661092b5c1f15b5ffed1369b194d9e12f0
+CT = 868b85288828501cf1d06610fec25e8b8a4b437e2e4f5563b7f3b898a2356909784598f8a8916f5a
+
+Count = 33
+Nonce = f2a88c3ebc74e62f24c7
+Adata = 5f495c5da035cabeb77e8aef10e91a05bd5aa414d1a37fa1099af959b26e5403
+Payload = cfe8ee9b475e36058471e2984ae66f6ba1b3cb477b15155e
+CT = 22c16333ac651cd9c183e78aba3e9312fb3b77dd6f9199502788860aae5534cf84979e30c3327d37
+
+Count = 34
+Nonce = 9cbaf1c83ba60b1e90ea
+Adata = 7ef136bd9a5809676abbaa68016d6fc713e34ac4b768a8246b1198c959f43085
+Payload = c3bcb0aaea93893f05eeb6439c8619dec17670a6439e2921
+CT = ebd9fb86563aa8f10062624441336f982c161ce5717d990a599ca6ec1c61a14c37b5902389e47aee
+
+Count = 35
+Nonce = e25322845d87d8a76753
+Adata = 2a89b9f0e56a1cf87dd38ed78028b6286ef8b7141dd2b3c65c5a8e1ed79bf4aa
+Payload = ae622ff9381854f831892c318bae5c003e74b15199bc12c0
+CT = 144c920f0fe278f353d0b053563d907c7589e4f1479d7a93a0604deb3fd9cea2d89987833ff5c2f1
+
+Count = 36
+Nonce = f4d7978fad36223623cc
+Adata = 8671de7e994967f2521d263925e745af9273682d9c08ced07d4a98fc985f68a0
+Payload = ef9b4ff8da108cabc972192ffecd5f96594c6d0871ffa6aa
+CT = ae4948b3bc1e50beb9f5d005871fc0d3dbde295de1c9ec3cbc866ab47bea7a4d0070e52b492fb8f6
+
+Count = 37
+Nonce = 6597ffb9eaad0fd9d830
+Adata = d2967ddf69ef62a9e23c9118dfaa55df92b4116322f1c9275131e3875dc92faa
+Payload = 5015c894b2437ff15c46bca9236830ff4bb057cd5764f027
+CT = 0b1dcb3cb0b4c32f398f3c43eccfe8f4242f33c99a2a2283efcb3dacac25bed0304f227fd5b77b8f
+
+Count = 38
+Nonce = 80e376b87272d99cde28
+Adata = c9cc8f967dff45c05b9345d03813b6e30dace99556f7df75b7120bb6e5f55827
+Payload = 615f657e24129a3e0f119988959608821219ce8354c4be26
+CT = d3e8b8f7ff8faa666ffe2509187fa7befc7412fd4e3bdb06cd2f7494b1fb0a0c6a2184e5c4787fea
+
+Count = 39
+Nonce = 344cce96455541d403f3
+Adata = 748cce18fb40126ce125dbe341fbbc59d2aacc170ed5ef0293b15713c9184a07
+Payload = 828b6a4cd49f499a6e8e8508f9ab35255d8e9fed33ba4d91
+CT = b67e582a74d7f022a16ada2de7ec18caafdefa6b104baf4ed93b6f8c8a1bf72be75976e4ebe6dd1f
+
+[Nlen = 11]
+
+Key = 97bc7482a87ba005475dfa3448f59d4b3f9c4c969d08b39b1b21ef965c0f5125
+
+Count = 40
+Nonce = 0bcf78103ec52d6df28887
+Adata = 049c10f0cb37ae08eae2d0766563b7c5a8454f841c2061a4f71a0a2158ae6ce5
+Payload = b99bf4dc781795fc4d3a8467b06e1665d4e543657f23129f
+CT = 0d3891fa0caac1f7ebe41b480920ffd34d4155064c24f3b17a483163dd8f228d1f20cd4f86cf38fd
+
+Count = 41
+Nonce = ab6374c6b2faefd92fa3d3
+Adata = f19c044023e5cf339203738ee70e76527519763664c06ae00e002a5ba94c32c6
+Payload = a2e5c51f516db01688b64c173bb25645182a005018022ee1
+CT = f70c598df3c64d3527ebb7fc8408b7de2cfaa1da7984ec361f1ad61758d828b70d4881b7d6ae8cd0
+
+Count = 42
+Nonce = cfb89e7ddcba601e875110
+Adata = 052714010da516c896ac5842a839ae845324643cddb080e6206148432d0d0407
+Payload = 037f206cab78a6ca0745dc8fc137e22e14f3d7183917ef83
+CT = ccd675862502a2e2520a33250150b8b7b220e84db854888c316dd62075fc761e2bc80edc5c564bdf
+
+Count = 43
+Nonce = 967cb6f8530bf8a43adb42
+Adata = cf391a84d03e2e22aec1965cec821f99e7bf21a7c3580dffa531464b22d83225
+Payload = caa3d928d2bf2b7f2cd8a7f357055b6d6895a5e34f47972a
+CT = 4f4f509debe6e52eae4af8b1740dde0a5338f78711a3b4ebfc8b5aca6d606222d6af7cfea0d1f4e1
+
+Count = 44
+Nonce = f5b7b5dd2b5e1ec93710c9
+Adata = e7a6b228a67d37b9d29a38efc547e50b4a6d95d599b45ee189ece21101ac6b5b
+Payload = 4a74ff35418723f2cecec1012484b52114067b2b2393e7f4
+CT = 25b140922a9d4f2ce153a4ff86596a49d7de6a6184e931e8b2ff27a98029b23484e00c2a5d291887
+
+Count = 45
+Nonce = 713de00faff892977d99d0
+Adata = 14ea93488d4284d21d4c7ce14414adf45c1ed9d2d99db866d0e59accb6234dac
+Payload = 3820db475c7cb04a0f74d8e449f026ec951fa59667738698
+CT = e4d92ab8d1ffb0976670d891cc8338da12f86d5d79b334103d2ae816edf857c810b6fdc7f2c71f1d
+
+Count = 46
+Nonce = ba87934808de09b2ae829b
+Adata = 30e2ea2a505f19e8760a0a84961000c7a0b7fe3460a9d3f5a38f54149be2e9ee
+Payload = 0e52a384cedcdf7f179348de6e7336aa86f8855fbd903cfa
+CT = 6df893eed2be958e5f542f8cb4adb392b34786cb4ce821ec93fc57997b977948d55bdb026db5bc48
+
+Count = 47
+Nonce = ea09fbe5da0fa4fe911e18
+Adata = 237dc8512b29bccdeb8ee39cf83b9b6dd203823d175c44d5f605b194e7ec136e
+Payload = 41cee0ecaf9c65cef740440af37954ef49a585779d2abbca
+CT = 2f204ebcf549ee2a800d870e6341b9a89a41ab4ae91b6902ff704a2bcfb8becd0226f76d68fbb08b
+
+Count = 48
+Nonce = 5b80d7affc4ab4a4b68bdd
+Adata = 3a38dd7da30f5c312fb1e978d87b7a39792fd9ea3e9ab1565874e99df587327c
+Payload = 5ff92f6d3ca791421363e10cc84b4e8e21e0ebe5d8c55d6c
+CT = 05472db7875d59f8bed45606f355a516de93740aa2baeba18df9400df42baee6b9a0d75b45840104
+
+Count = 49
+Nonce = 514bba483fe7f2b7e555cc
+Adata = ac8beb419099cdb42a39e9b46fd900cc52eec4b43a96ed18b37b899b63fb931c
+Payload = b0b11dfca9b3936d1b4a423c5acd3d012b399a487c19c994
+CT = fa20629d514c4ce7bf727629bca5aa1c0c7e7851fc1bfc5c847729a70d7b4cff5281aece37006015
+
+[Nlen = 12]
+
+Key = d6ff67379a2ead2ca87aa4f29536258f9fb9fc2e91b0ed18e7b9f5df332dd1dc
+
+Count = 50
+Nonce = 2f1d0717a822e20c7cd28f0a
+Adata = d50741d34c8564d92f396b97be782923ff3c855ea9757bde419f632c83997630
+Payload = 98626ffc6c44f13c964e7fcb7d16e988990d6d063d012d33
+CT = 50e22db70ac2bab6d6af7059c90d00fbf0fb52eee5eb650e08aca7dec636170f481dcb9fefb85c05
+
+Count = 51
+Nonce = 819ecbe71f851743871163cc
+Adata = 48e06c3b2940819e58eb24122a2988c997697347a6e34c21267d76049febdcf8
+Payload = 8d164f598ea141082b1069776fccd87baf6a2563cbdbc9d1
+CT = 70fd9d3c7d9e8af610edb3d329f371cf3052d820e79775a932d42f9954f9d35d989a09e4292949fc
+
+Count = 52
+Nonce = 22168c66967d545823ea0b7a
+Adata = 7f596bc7a815d103ed9f6dc428b60e72aeadcb9382ccde4ac9f3b61e7e8047fd
+Payload = b28a5bc814e7f71ae94586b58281ff05a71191c92e45db74
+CT = 30254fe7c249c0125c56c90bad3983c7f852df91fa4e828b7522efcd96cd4de4cf41e9b67c708f9f
+
+Count = 53
+Nonce = 225557b0faca3d6cbaedec5c
+Adata = c7aafe7d3b419fa4ea06143897054846ac4b25e4744b62ba8a809cc19253a94b
+Payload = 0e71863c2962244c7d1a28fc755f0c73e5cbd630a8dbdeb3
+CT = 2369b56f21336aba9ac3e9ba428e0d648842a7971182d5ffac57f6ae1080efab4ed93f8b4ce1d355
+
+Count = 54
+Nonce = 78912be1a35e156a70fb72f7
+Adata = 12ba8eddff1c2a03ddd25bb924ff065a93fd712b2c4f61eb80d77fab2c4900e0
+Payload = 113efd182f683596862ccd5eba2e2d4ffa709d9b85c6f1d5
+CT = 835a22eb8d718c0ee1531a2d1bb95f58215c997c612908eeed3ccaeb7a814f69d3ec1fbf2ee9792d
+
+Count = 55
+Nonce = 91ad90b58d2044abacf957e1
+Adata = 4fc795b9126c23dd7fd514c2e5a8ca583e88a783b28cbb2a5df09f8b520ba0d1
+Payload = ed55f6b9eb8fe74474c037ede94ffd84ada846ede4ecff74
+CT = ecb595276fd5d412a7cc3f5cfe960f47a0d0e2df0b08a11ac257d67143722a976c9d7f44b09a767d
+
+Count = 56
+Nonce = 4bbe4ca29122c4892ca09b5b
+Adata = 367ecd1b71dfb96a84e2369f28705dfaebf0c73ed35d5364449b2391230be846
+Payload = 8dd497bb777bbc3e56e3af25a43545007bb00f2b9e9f815c
+CT = 563d61fc0a5b82804a580a7d752a8e61d3342fb39372b39b6843a685bde3175695796f6e64f35901
+
+Count = 57
+Nonce = 218e7b8a8fd62927f90b70e5
+Adata = 01815f599d6ba0d1c09f6f673bb6cca4c2a7a74f4e985be4c0f37842c7bbc5a4
+Payload = 80f3e4245c3eab16ef8bf001429122e46bde21735f63adba
+CT = aaceb16589b9de253c99d0d32409a631db71e8df8a7644bfd027e3466e8220144cb0552f9b2800e6
+
+Count = 58
+Nonce = eecc9f106a0721334cc7f5ba
+Adata = bf38d0ee11a796a517539bbc9ab00ff85a4ddbf0a612d46e2bc635180ad34c50
+Payload = 36cefa10af1a3446a2c8d4a1171144b9ddd8e33a7cd5a02d
+CT = 9bf3b2df93cf5b587ecc96f45fc75e6eb066cb286cb06f284c9027fc41bb8c848025fcf9d092a873
+
+Count = 59
+Nonce = e41af8ca408c4c12e37561a4
+Adata = e0b20892875f60b5d8763a04958487fa5b7cf8d67a456e430475b337245d671c
+Payload = 32a4da08bdd51336ed5798c7177b853a534bc98f2e6f7d4e
+CT = 95ffdc68f721cf2294d0d88002e3814167306fd906dbebdb7e6e0e5dc0a03826e51bd94269d7a41d
+
+[Nlen = 13]
+
+Key = 4a75ff2f66dae2935403cce27e829ad8be98185c73f8bc61d3ce950a83007e11
+
+Count = 60
+Nonce = 46eb390b175e75da6193d7edb6
+Adata = 282f05f734f249c0535ee396282218b7c4913c39b59ad2a03ffaf5b0e9b0f780
+Payload = 205f2a664a8512e18321a91c13ec13b9e6b633228c57cc1e
+CT = 58f1584f761983bef4d0060746b5d5ee610ecfda31101a7f5460e9b7856d60a5ad9803c0762f8176
+
+Count = 61
+Nonce = 8a56588fe5e125237b6cdc30f9
+Adata = b3aee5fbf409bcfe9b46ae68d570edbbed32c12d13926ffb5ddc60ff0bdb7f85
+Payload = eca81bbd12d3fd28df85e2cc3dcc2ecbd87408002fd00fe1
+CT = 9aad62a5443550d11f9efdab2de0eba74d47ae4f7d16adf4276664f6567f2f978bd4be4d80cd07be
+
+Count = 62
+Nonce = d908b04840caca2280e5293ade
+Adata = 314a202f836f9f257e22d8c11757832ae5131d357a72df88f3eff0ffcee0da4e
+Payload = ad1109ea5c79bb55d22e9713eb2df42767cb29a2eba3ad2c
+CT = 61fdcebb158cd03151697ae7871c0a998802997e0672e5886e5a9df1b1d6284ef657cde6f74734bb
+
+Count = 63
+Nonce = 6df8c5c28d1728975a0b766cd7
+Adata = 080f82469505118842e5fa70df5323de175a37609904ee5e76288f94ca84b3c5
+Payload = 1a95f06b821879df3fd3ac52fc99a7c1d3e9775263b7d036
+CT = 704f60f9cc3ef7bc00b4f7a271ca70a89f4d5605387b3e2f8cc80aa08572b90e9598d0a73712b720
+
+Count = 64
+Nonce = 6c6ebacce80dde9fefb7e5bb47
+Adata = 93f0fca0c8c84d5cc48160b25e246226d489225c0f8275e52856da592c715aa6
+Payload = 46820aec46ebd0d61706129584058a1498514928a87fe620
+CT = 00f6cccf45f046da1e6266afe61eed61c60c28515b2e1ab386b2c952055899184f0d95ffe3959f89
+
+Count = 65
+Nonce = b94bc20d8c9abca7645fc6bebf
+Adata = e1c083c93663f5a066ef337a61aa3fddde7c301a42463137c375cc2dcdd76954
+Payload = f1fca581d3dbbc61060c0c02adb47bc57954d25a283f66d6
+CT = 90c65d23e0e1786cebb95f9b1306d001b2e503842cdedb75e37a53d77b9e38605febdd7b2b666f98
+
+Count = 66
+Nonce = a4974791d417d7e9eea0f4ae8d
+Adata = 33602f308f3a0f7e1c75fc1e4321d545ffa278234958dbadd37f59a0f85349c3
+Payload = 41712c058d2d56b43b2c79278e790858a289320746c15a60
+CT = aab5656a1ef060c9b1ef7e2f3cc0bda40ff067900401182563ceb824708a20724c99c83f1caacd70
+
+Count = 67
+Nonce = 6003b771afe4e99e1ef1ed4a31
+Adata = f60d8362b2ebf523681bb051fd3ee13919ad86acd963c703c4178a5f01a84236
+Payload = b766022311c5e1d74a607fec7cb8ee805b8397a6c5f374c1
+CT = f73b2a6dbf8f798d4bfb489a6578c9c79152e42aa3b81b64a84e7af3116a18f7ce44ae93f420270b
+
+Count = 68
+Nonce = 27861168ac731a223dc35c03e8
+Adata = b7ba1c66282cb6092ba601407ff9578afdadf7ba7a4d08edef06dbbfd87171bf
+Payload = 0822e3e6ba982091d532cd5271fbde25305d1f6e71880f81
+CT = 5ab3e5296cd1f08704c82f6b42939702515b7733853d723d4009312bdae46958d844eca502bcb005
+
+Count = 69
+Nonce = ef284d1ddf35d1d23de6a2f84b
+Adata = 0b90b3a087b9a4d3267bc57c470695ef7cf658353f2f680ee00ccc32c2ba0bdc
+Payload = bf35ddbad5e059169468ae8537f00ec790cc038b9ed0a5d7
+CT = b702ad593b4169fd7011f0288e4e62620543095186b32c122389523b5ccc33c6b41b139108a99442
diff --git a/lib/crypto/test/crypto_SUITE_data/VPT128.rsp b/lib/crypto/test/crypto_SUITE_data/VPT128.rsp
new file mode 100644
index 0000000000..f79db90b4d
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VPT128.rsp
@@ -0,0 +1,1383 @@
+# CAVS 11.0
+# "CCM-VPT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:24 2011
+
+Alen = 32
+Nlen = 13
+Tlen = 16
+
+[Plen = 0]
+
+Key = 2ebf60f0969013a54a3dedb19d20f6c8
+Nonce = 1de8c5e21f9db33123ff870add
+
+Count = 0
+Adata = e1de6c6119d7db471136285d10b47a450221b16978569190ef6a22b055295603
+Payload = 00
+CT = 0ead29ef205fbb86d11abe5ed704b880
+
+Count = 1
+Adata = 98d477b7ef0e4ded679b0bc8d880f09823ad80e9732fde59c3a87da6a1fcf70b
+Payload = 00
+CT = 5b85d144bb51d4927074d3536a2db83a
+
+Count = 2
+Adata = 28f32de10b6c9d3c3f46efec7aee24006208a54c4d1c2bba4b8cdce166cab7d9
+Payload = 00
+CT = 01045de4a09486eea5efa33ecc6cd299
+
+Count = 3
+Adata = af397a8b8dd73ab702ce8e53aa9f0189995c6c9e920dcb75795149550b499deb
+Payload = 00
+CT = dfd75400b59c3ad387bc86dfbbfb52ac
+
+Count = 4
+Adata = 3fa956bfaa27e249bf0a1276468d808259f3b8e2687851d780885d44cc2f04bd
+Payload = 00
+CT = 2b11d2549b4e2f0a81c07ee90af4d081
+
+Count = 5
+Adata = babbd1b44cae3af06e0150bf0e3d898f6fe862b71ea9f6b727accfc18848fc79
+Payload = 00
+CT = 10f76ab445f4ec158ccc1f7c6fee3ede
+
+Count = 6
+Adata = 7fba0bfda3b03c736c121cf9a257db55060b621be5168619ec4182f13ef6a408
+Payload = 00
+CT = 59e02d6a6aa3fb2692b04e65a0e735da
+
+Count = 7
+Adata = 057354a29808f4ed77671ed3dc36f8b03f5cd952caac5cb80dc3b319f3333e29
+Payload = 00
+CT = 367a2ade4087964dcb0ca2984d44657e
+
+Count = 8
+Adata = ec08b618602d091e9304715cb552b357c16fd1d7f7f023a28d84a98ba21ca0ab
+Payload = 00
+CT = 47cb92cd40bc89328d4dd44fbd727032
+
+Count = 9
+Adata = 45622834ea658b09b17f32777d18b34b387ef957bd344468f68e7178417a7c24
+Payload = 00
+CT = f5185afb8359b5ef995483c0bc4192c3
+
+[Plen = 1]
+
+Key = 6ae7a8e907b8720f4b0d5507c1d0dc41
+Nonce = 7f18ad442e536a0159e7aa8c0f
+
+Count = 10
+Adata = 9c9b0f11e020c6512a63dfa1a5ec8df8bd8e2ad83cf87b80b38635621c5dc0d7
+Payload = 0e
+CT = 4c201784bdab19e255787fecd02000c49d
+
+Count = 11
+Adata = 73616a428f1a567b2e9af86b1fc8aec6d597b1b55f2aa2219b3b662fa6bd3407
+Payload = 30
+CT = 72f14519f06b63fac3d5b2d9bbfa0cb758
+
+Count = 12
+Adata = 6d62f4e15e8bcc9ba4993bc50a046737121016f0d15020b90068250551167b1c
+Payload = 34
+CT = 7676b581a28ca0a0ba5178eba7fe028da6
+
+Count = 13
+Adata = 8f0b8289a1834ecc2167b59ce3c9d3b58465c4cfaad50c728d04360cb7e5bc41
+Payload = ec
+CT = aed99b805c0a4785ff2913cab3e50f6205
+
+Count = 14
+Adata = 477b2a6932f838f0d1bc420c0ca306981d8e2dab945b6f259e15fe888667220a
+Payload = ec
+CT = aeb50e41cd7af84a8fdb6aee144e904616
+
+Count = 15
+Adata = d6518d409b1f05708d0b44f18fb5721f20f3220f8d2f2718650aa9932e4579e0
+Payload = d1
+CT = 9312639c863974f077fe8236c943b464c4
+
+Count = 16
+Adata = 865e7cde73b558e9bfd05356923f8a697970811fc484acad2d5b3528baf1f986
+Payload = 24
+CT = 66d7265cde50bc7a3989458437baf06db5
+
+Count = 17
+Adata = f0c3c67a935eace53ed32435655dd0974fafe283622e8294a15d70977398eae2
+Payload = c5
+CT = 87063144b25d2268063815d1b42ebbac34
+
+Count = 18
+Adata = 341e71b2ef26e9db03882e06d06cde2c0617326cd157d5984d22f6f3407a9c39
+Payload = 34
+CT = 767da45c10d0d6498716bcf3f13ca7e26c
+
+Count = 19
+Adata = 31fce6735ba9a3385df11c153179b8e4141a3c6b8ad6eceaa211f3f17bfd0474
+Payload = 7d
+CT = 3fcb0a6f562974cfb3fb7c8d5cafd50f2b
+
+[Plen = 2]
+
+Key = 3d746ae6cac5cefd01f021c0bbf4bc3c
+Nonce = 597b3614ff9cd567afd1aad4e5
+
+Count = 20
+Adata = 90446190e1ff5e48e8a09d692b217de3ad0ab4a670e7f1b437f9c07a902cad60
+Payload = 4360
+CT = e38fdb77c1f8bbac2903a2ec7bc0f9c5654d
+
+Count = 21
+Adata = 6bc3d30925c67371573271f1a4273ad76e91e07dfab65f7bce0b241b5e4cd00e
+Payload = 17c6
+CT = b72955210d62e1393e4fda647c2b2e59a47d
+
+Count = 22
+Adata = d1bb4cdfc3f2c16d92576068543692aa4b5a427d688387af0f1583e91a0e8b3c
+Payload = 6575
+CT = c59ad54fd88a47b9f6e39cb4606af86d13e8
+
+Count = 23
+Adata = ae6136df9ab43631ef143515dacedbe759b3459e951bfaf4712a21c86352f1c0
+Payload = b1dd
+CT = 11326de841af64b55bb7ebe3fd30ba493c7d
+
+Count = 24
+Adata = ffead34ac26e21158212d07c367c3a7cb6b795887ee2d3d8ae25c60556ea88d3
+Payload = cd16
+CT = 6df93a206339de534271f6469edfa5ed07d3
+
+Count = 25
+Adata = e768e7d867820d46c1cc62ee0e51d4dac6f5c4b5785b5ccfbf05236871bdce2a
+Payload = 12f5
+CT = b21aa8f65144f2ec5809e2ccb38c8760f7bc
+
+Count = 26
+Adata = 402e802885e4119df17fe85f141c3d1af7727fcdb00f8e2c34e42a436d04ac5b
+Payload = 39c0
+CT = 992f9af825957abe7d89e175b6e8c0b84b5f
+
+Count = 27
+Adata = 8a3a622b3d347c0c5210d484adf77fa33205ba02224ddceea71d89c9ad8429ae
+Payload = 912f
+CT = 31c025d6a12e91e84e355934547f6b5dceb8
+
+Count = 28
+Adata = 636114e5e5f83cec94e1df21d6babb9f6a14a532fcbfc3bcf649fbd79ac1abbb
+Payload = cb6d
+CT = 6b826db959a21e9e4ebf25ca4f98501b560d
+
+Count = 29
+Adata = 04e84f9156998c2eca9e96079a6001f2947dc49a081b3d75e47d75f71ed4a606
+Payload = 5bd2
+CT = fb3d2006ff22ff231a6646ae561923818a21
+
+[Plen = 3]
+
+Key = 3e4fa1c6f8b00f1296956735ee86e310
+Nonce = c6a170936568651020edfe15df
+
+Count = 30
+Adata = 00d57896da2435a4271afb9c98f61a650e63a4955357c47d073c5165dd4ea318
+Payload = 3a6734
+CT = 384be657bfc5f385b179be7333eb3f57df546b
+
+Count = 31
+Adata = 50f6e6dd57bd3a24f6bfdc8b1c7b5a36ebdd07fd6d194e6e82da47151d9c88fb
+Payload = 4ffad3
+CT = 4dd601b8ca97bda492546d82dccdebef441f8b
+
+Count = 32
+Adata = 70e132023acae1f88c7a237b68f5bdce56bcfc92be9f403d95d3bcc93b4477a9
+Payload = 8a594b
+CT = 887599fa0f3e397d9a580aa39c7028e1a508c9
+
+Count = 33
+Adata = 08d2b011f36e05dc728c1a8bda3d92c779a3d2f27c4b041810bd6222c852b14d
+Payload = 1f89df
+CT = 1da50d593460d335e2f7a6d40b8fe305b0f690
+
+Count = 34
+Adata = b207eb870aeeab27c6201ef04650bdc7ea30028a243420f7d198f1c9c9a43023
+Payload = 72e9c1
+CT = 70c513a2d49e1a113767ea4219107819d88b65
+
+Count = 35
+Adata = 74294088721fc9e7aabd5f1c66b5369b1e2d2cdb3e73abaa28ecd1c37d4ecea2
+Payload = 016083
+CT = 034c51dab1c819778be8453db163c882063af8
+
+Count = 36
+Adata = abbd347999a1c26368cdb17ab08bf57a8e942d1248296e952f5f42f2cabbf0e6
+Payload = 25f665
+CT = 27dab7537eb435df8d0e48c3f7e0bd1877c866
+
+Count = 37
+Adata = 231b33dc406c9210f59a5df1cfd595c803474db34b9b1848f0bcbe7b28df33c2
+Payload = 158606
+CT = 17aad4da549fc63d55b5910bbbf64435b95220
+
+Count = 38
+Adata = 69b851e63a78baef90637978e3dfe8c47be4b21e85bb89bf67051cf251004376
+Payload = b07452
+CT = b25880d5ee29fb2af47f8040fad585921057f5
+
+Count = 39
+Adata = 9b1f786c887d310b8efd3e8192fe504f603024c94aaa4ec9123736a40bf1605d
+Payload = 65187c
+CT = 6734aebc3ee43e10205f83143e0d3794a6734c
+
+[Plen = 4]
+
+Key = 7ccbb8557f6e08f436d0957d4bbe7fdf
+Nonce = bb8e2ef2ed9484f9021cda7073
+
+Count = 40
+Adata = fba1d18a74a3bb38671ab2842ffaa434cd572a0b45320e4145930b3008d8d350
+Payload = 4cabeb02
+CT = 32501f4235c4dd96e83d5ab4c3c31c523453c317
+
+Count = 41
+Adata = 78b3faecb2bdf6ed14ac2b86ded07aa791b60f5d54f9e24a965a8453f5131898
+Payload = 5ff73653
+CT = 210cc2137907d6a03e66403a7d9330d30d934a8d
+
+Count = 42
+Adata = db1239528eb464dd063e2a97ee83a87d6002ebb4fbafa77036f72c14f3fe959b
+Payload = 062fa9ca
+CT = 78d45d8a44f4bc78fbb969935076134437df82b4
+
+Count = 43
+Adata = 0071f1edb3a0ce57af3c88bb0ccf138f752697a77e55695838fb39de04c78dfb
+Payload = cad710b4
+CT = b42ce4f459692911fea2e0034d06c3b2e89af3d1
+
+Count = 44
+Adata = 7381471a62b1fa6f5061c4c37e9721f07099d007ffaf8639aa2ae3f82da5a559
+Payload = 7ac716b4
+CT = 043ce2f468484e22381923bfcaed16e0cb85b0f8
+
+Count = 45
+Adata = 19bea6d92d5892216e8e4a30dda802387800bb046a6717817fc46c7edafe17b0
+Payload = 362da02c
+CT = 48d6546cd081de39c247df309c4b56c31c03690d
+
+Count = 46
+Adata = 8503c8eb9cebc6110f259e35e03a0740267768130ce6f61b1c7d1d25be942274
+Payload = de52b209
+CT = a0a94649c6c6bd7b3a9d7c4dfa2738847ea3cb33
+
+Count = 47
+Adata = d2445db6efecaa3f426b06de8d496ceed54a1d0171384cc762e21b31e265c6d5
+Payload = 8fe8b383
+CT = f11347c32ca874d18d0b790856837555f4d4699a
+
+Count = 48
+Adata = 8cda7d1e135cf5fde1ec9473c4b42c1bbb445c27fd87b5f73df61ceb2d0b6f75
+Payload = d8d6b2c9
+CT = a62d4689932c2f8d78e322aaffc90846025190f1
+
+Count = 49
+Adata = b506a6ba900c1147c806775324b36eb376aa01d4c3eef6f5a4c25393ecbf2025
+Payload = 6a029e53
+CT = 14f96a13c346a4084918081b4bbe53b50d896788
+
+[Plen = 5]
+
+Key = 3725c7905bfaca415908c617b78f8dee
+Nonce = c98ec4473e051a4d4ac56fd082
+
+Count = 50
+Adata = 11bc87f1c2d2076ba47c5cb530dd6c2a224f7a0f7f554e23d7d29077c7787680
+Payload = f5499a7082
+CT = e378b776242066751af249d521c6eaebdff40b2642
+
+Count = 51
+Adata = d54219ef4fb851bebd1c546011ae3922b8337e19c28d4d58428efd66f80edcf0
+Payload = 513c46fcce
+CT = 470d6bfa68e7258df363e0e9af67a543c86db3c994
+
+Count = 52
+Adata = a92e88edd297da8c7089e21822b3e6cffd6837c78b975c8413fd6cca1b99bcb0
+Payload = 9d62e557c3
+CT = 8b53c8516572b7573e5b27a1d0e15cdb7b06c8857f
+
+Count = 53
+Adata = 77d9c306aa257379053cf1f2043c388a301dac2a9e2bb89eb8bab6eb3f150fe3
+Payload = 7a05db235f
+CT = 6c34f625f9de691a412ad54bbdb6ceac45ed45902b
+
+Count = 54
+Adata = 081568ae0b948aa647b9d4dda5d42641ad5de72aa9874d8d0717d872007720a8
+Payload = 30a22ca0fc
+CT = 269301a65a8a1bb8ba3d6763dcb1bdd3400e3459f7
+
+Count = 55
+Adata = 695ba4dea0f84baf190ec25a25fc00cb9898902d7a17e6f5ff2df323b974f7c4
+Payload = 35e25aa51f
+CT = 23d377a3b9403897d496cabcd5bd9de3282199a8ed
+
+Count = 56
+Adata = 1f3ba0336a634efdd11f8168c0fe25039f9403bfa70b3898f4dbe577dbd52957
+Payload = 8bde704c74
+CT = 9def5d4ad270a81f7cb0ab7ab2b495f51d66abeee5
+
+Count = 57
+Adata = 097b9ebff3ff93a143678d59721fdf359e95cbc82585ae47727a773317925d38
+Payload = 428542ecfb
+CT = 54b46fea5dce68e9b01a4462a2221bd2f3cadf64c0
+
+Count = 58
+Adata = 76d0341dd44c39e43a23dbcf4cb602f15d5fb9fee20c3d0d262d539c3fd1dfd5
+Payload = bd6866ded0
+CT = ab594bd876f2545964ef3978cad3387d61104bab84
+
+Count = 59
+Adata = 7e7c40ad64b511005b4546f9ec61ca24829390fbc4bd8507225bc348ae0807d7
+Payload = 5822755a3e
+CT = 4e13585c98002c41938a935d51905b2a708a2c5194
+
+[Plen = 6]
+
+Key = 80bead98a05d1bb173cd4fca463b8fa3
+Nonce = 8a14a6d255aa4032ebff37a3d7
+
+Count = 60
+Adata = bb4e706e73d21df66f64173859d47e247527cd9832e20dccff8548ed5f554108
+Payload = e479990bf082
+CT = 89c9246238878427f36b1f6c633e4542f32b50ca8edb
+
+Count = 61
+Adata = 9db2182c8a4f5471082bfa1a8496602cbcdef2790f7e8f71f791303bd48dcb05
+Payload = 017a7fd1aecb
+CT = 6ccac2b866ced76fe54da69af5edf8309c7f013bb07e
+
+Count = 62
+Adata = bf483f59fb73681f27b68168c998c90ea8ceea997654c6fab2bd737dcdc884f9
+Payload = 512fc5e4973a
+CT = 3c9f788d5f3f662f53d17f7cb6673415bb2324ca0666
+
+Count = 63
+Adata = b91e641d8210e1ef705fec2beb9f58a391c7d1a38935cd1d13f2c00363388ff5
+Payload = 06212e989616
+CT = 6b9193f15e1340c86156b1065b64af1e4d6c89b32603
+
+Count = 64
+Adata = 5cebf908e232d797fcce8453c4c3000868d4172622a4ee0d6a1bdd876a0b7c96
+Payload = c45629069ebc
+CT = a9e6946f56b9c07ef5349903b928e39e99e2e32625de
+
+Count = 65
+Adata = ab92cbc97f3aa6f9ea4dae5d8c3d9e91231f43ffff548da7b668e61c183ac2cf
+Payload = b949ced37725
+CT = d4f973babf205e40654ea16e83cc6faeaad668c416f3
+
+Count = 66
+Adata = 2c3d2f9c7e89c2b9e07317c4db6e9f00f5faadfad531c5bea79d164ac24d4543
+Payload = 517ff7b383b7
+CT = 3ccf4ada4bb23102a502dbba0c280e1d5fc627fe3a9e
+
+Count = 67
+Adata = d798e77ab0f3697768f23014fd31b9e8762ae65b6aa8a4bbc17ecb8cbe78461f
+Payload = b40d863ca4ff
+CT = d9bd3b556cfa6745fd4c954396e696697731e1f9a262
+
+Count = 68
+Adata = 45b44e3dec57e24d960fd1767797ffdbbab81e38bab37e6974df262c3d932327
+Payload = 56e00289a003
+CT = 3b50bfe06806bdf2b2dd47077c98234eae5d47c3b594
+
+Count = 69
+Adata = 645d27970ccce096d082fccfc1183955bad2611af0dd7c58c9d54430f28bd992
+Payload = aa22bb1de579
+CT = c79206742d7cea66649ad7e204a344d3234125aa324b
+
+[Plen = 7]
+
+Key = dc8ec91184ba18eae31ac2d3b252673f
+Nonce = 0da4c988f521f5648259f2bec2
+
+Count = 70
+Adata = 6d5573c9279897d7d1602d8a95c04bb5ca3fad2dbe89a024b3651eb227e73bb5
+Payload = 2a5775986551c8
+CT = 4f259f2a718faea852a7c4358dfa9f5467357638acac90
+
+Count = 71
+Adata = ff0ab5021ef466e2e898b0993d691145168be558682c74914c172f2b5e863754
+Payload = 8db3c1ca0580f9
+CT = e8c12b78115e9f8767c76e707d48a2144e090812e0192d
+
+Count = 72
+Adata = 2ee03cc28f79773af139c4ea55ec4daa48bb2885b8adcd5f066eceda5c4ec27b
+Payload = 3c69e2e83236b6
+CT = 591b085a26e8d05486df740083c959fb62ef7e2e221602
+
+Count = 73
+Adata = f041504d4c1b3d5be358bd6d350af42921205d29ab22b44ffe221358adef5bb4
+Payload = 777828ab5ccb68
+CT = 120ac21948150ebdc4d2b86b2528f75db4a7f5423f4395
+
+Count = 74
+Adata = 81ea116832d69542ac8d3d22c16c82eecf2ccac39264dd933c4f9c13c8d0f1d4
+Payload = af556fef3584e3
+CT = ca27855d215a85a7b06d1b710baa15daef19069ecf46f0
+
+Count = 75
+Adata = 8a0a120ed290a62456f002da1c250a0ddb1ebd57185a733d8fb562aad482679d
+Payload = 98f26635351f14
+CT = fd808c8721c1723811129add52e1406d50cbff4aa82802
+
+Count = 76
+Adata = 12b5a76faedf6f855e328c2cb87be8aea78c5e926b32d828e167b46205c86de5
+Payload = bd22c1ec05dc26
+CT = d8502b5e1102401563d3da8a6cabb7515f642e42fb4b2e
+
+Count = 77
+Adata = 8dc32f35ef4bcbfd040ad25dc36d0bd2486f93d0cabb7704cd1582dc99f65449
+Payload = 2a87c0d64806fe
+CT = 4ff52a645cd89817609a21f703253e5e56beef4ac71759
+
+Count = 78
+Adata = 83ced632359a11eb0c4c99baad84df5cac15bc5453b6593d9ffb4c5e8c84037f
+Payload = f05f39eb0a3d64
+CT = 952dd3591ee302236c72f98da859b54be7c598d85c37eb
+
+Count = 79
+Adata = 771a818a24e7da7b98f4b4291ef34bec7e1656b0c6c6e9474a989a04ea7de385
+Payload = 59dad755af92c2
+CT = 3ca83de7bb4ca464c8cd38cbcc46e7f09bf3e1c6590c71
+
+[Plen = 8]
+
+Key = 19f97ef5318b8005fc7133fa31dd1236
+Nonce = 01ce9814c6329dbee1d02b1321
+
+Count = 80
+Adata = 85853f120981f33cf1d50fde6b8bc865fe988a9f12579acdb336f9f992b08b89
+Payload = 6d972a673fbe1ca1
+CT = 2f12a7e7acecae5d2563309efc19368cdee8266538ca89d3
+
+Count = 81
+Adata = a4ec5aee89e2cce2115b6c1f42570bc5062887cad08192a682d0b4508fcd936a
+Payload = 68b1b6367a15fe49
+CT = 2a343bb6e9474cb528096a5fec5e5359c369833eac3b7efb
+
+Count = 82
+Adata = f5499a7082bf1e6e2923211271f5f7f6d7c7b26db7963071705a58ddc4dca0dd
+Payload = 707023615563a40e
+CT = 32f5aee1c63116f2754a65863efb60c98dbb536e2b5a69d8
+
+Count = 83
+Adata = 765f267befe6fcfaaa4b46eda32e7bfab87f12ceb07fa3b37be74965bb664a21
+Payload = b56454bc50df3e28
+CT = f7e1d93cc38d8cd40b6e9b7f3b3541ffee66a1f668f67d28
+
+Count = 84
+Adata = 9ce65598cd1f86afc9aaaf172809570cc306333c25523f863c6d0e0154c55e40
+Payload = 962f765da3565bde
+CT = d4aafbdd3004e9227018c9db8baf6be349d93d4eef7d7c9d
+
+Count = 85
+Adata = d0125e30c36232a8c07cee9abc53453b276849a7c04ade80ad586ed8cbcede51
+Payload = 4f18bcc8ee0bbb80
+CT = 0d9d31487d59097c501b28887f05fd66f050525943d101f8
+
+Count = 86
+Adata = 90dfd9e7bb7bf8fb70c22a879ffa760d14cda7b79ce4968f69b8a7f2b7a59642
+Payload = ca293c9e1780b401
+CT = 88acb11e84d206fdda53dde2e1aef96b3658a7635ee54188
+
+Count = 87
+Adata = 58f518710e6b282482a7f1950fa353b13bdda10c9aaea6d5f0d7ea0a965d31e8
+Payload = b9df9fb4a6b299b4
+CT = fb5a123435e02b48b62a5ec234f1efd1b52c8fad1cf09890
+
+Count = 88
+Adata = df052e95aea3769a433ce4e4e800b8418649bbe8c6297eb07545e6802de7e807
+Payload = fb2441d1594a488a
+CT = b9a1cc51ca18fa76bc051ede6f37cf67543a7252d7d9b203
+
+Count = 89
+Adata = 0875020959ed969cfb38636d1d5aabce9658b00171a7614ea9e5395331c7659c
+Payload = 451101250ec6f266
+CT = 07948ca59d94409a5be4be6bc6b18104fac167b6e3fc15f7
+
+[Plen = 9]
+
+Key = c17944bfaeeb808eed66ae7242ab545f
+Nonce = 910b3db64df3728ca98219e01b
+
+Count = 90
+Adata = edf64f98b3ab593cbcf68ab37a8c9472e49cb849d4a744deae925a5a43faf262
+Payload = 7caae2640e734539d3
+CT = 0dae8b3ccf0b439f6ff8ee4a233dfb7753f6bfe321b3e26959
+
+Count = 91
+Adata = 29ac8fd6a20a5df4ec79660c44d373da42de7d7c5fc35982b6c29b480723b484
+Payload = e574b3a37af3bf2251
+CT = 9470dafbbb8bb984ed63b1477d9506a51ae23abbac179d8b02
+
+Count = 92
+Adata = 9ae5a04baa9d02c8854e609899c6240851cbc83f81f752bc04c71affa4eed385
+Payload = 2e3cf0af8c96c7b227
+CT = 5f3899f74deec1149bdb0986198bce2e486581c041029a81d9
+
+Count = 93
+Adata = cc8e789462879e348d20be4e1161d7b7fc6f8371d8f8cb2d25d13f0e07de47b0
+Payload = 16f22817c5b79f9fa6
+CT = 67f6414f04cf99391a0cbb2df2079a6eb964c3469f4f326122
+
+Count = 94
+Adata = c63061f2800228269015693336f78bb535ae8b88869e4ccf4ead2f3b0ea4e48a
+Payload = 64fe8076d4e8538e18
+CT = 15fae92e15905528a4a40ca7622acf7266b7c24cf0c3202e4c
+
+Count = 95
+Adata = 71c14a7031033db15bfe23b75fed9daf8886dd11392a0b787660e7b1a581af11
+Payload = 4814aaac48bdf43c92
+CT = 3910c3f489c5f29a2e7de20e98586cd5d684bf015a7abbe82c
+
+Count = 96
+Adata = 8f4947f8588ed866ed7477d7f1a28046430c6470806a50e3c9e80958c61f1b42
+Payload = 392a692b57a8a97f60
+CT = 482e007396d0afd9dc8d503f5d87818f7c0e173b857cef4288
+
+Count = 97
+Adata = 9d44f6df58c2b43db67e3daa95b176c81daff32e996d670e86405e15eae72e93
+Payload = cba1e00e345b0cb7eb
+CT = baa58956f5230a1157c85e2283d9e80700268a6459d1451d00
+
+Count = 98
+Adata = b6ada12f7a28211e9d2c07cbb3d39fa77aadc077b34c46f93006c1ca2ff66f87
+Payload = 22f5b6752582919dc1
+CT = 53f1df2de4fa973b7d1056aea3d3e4f7a5219170aaa52465e1
+
+Count = 99
+Adata = d6411fd5b25433f67ca75e4560ceb809d3721266beec358dde126b2f6a514137
+Payload = 6e1b55d6f5288c5451
+CT = 1f1f3c8e34508af2edfbfcf8200a8a3f8d995f50284a7280c8
+
+[Plen = 10]
+
+Key = 0fb9df6f638847f5de371f003dd938f4
+Nonce = c9ddf61c052f3502ad6b229819
+
+Count = 100
+Adata = 4f9938d5bc3dcbe47f6b256d5e99723d0891e50c6175aba41b011e4686113c49
+Payload = e10cc36bc1c5d3c646ab
+CT = 7f797367de50be6dc04e4cf0d8c24189affd35060cb7ca3dd136
+
+Count = 101
+Adata = e013a2edd5b86bab8df5c9940d0a0c864478c1ad42668304a643141855adac10
+Payload = 15841284c959febe63f9
+CT = 8bf1a288d6cc9315e51c4148ef85caab151488c1a6b3df540d21
+
+Count = 102
+Adata = 147d77d509f642189594df17574a0ce62b52a838feb62310e11533995ba4c851
+Payload = a8b4e5829069c335d1d8
+CT = 36c1558e8ffcae9e573ddaaa1e7c22b3efa8362abb3d31ee8884
+
+Count = 103
+Adata = 0bb09658e23fe8a08c01a6994ef36cb8dcc9a806297a09c67efe3558ca56bb5d
+Payload = 1bb2da0f1ae7e044deb0
+CT = 85c76a0305728def5855317b141383ad38dd78569d5f846f2520
+
+Count = 104
+Adata = 34eb2e6149bad764837f6f25ddd96865e5b05d5cbf233c4f6cc2aa654dfea3b7
+Payload = 63af538196add9b3fad2
+CT = fddae38d8938b4187c374e6432971aecf6bf7cf5244d21f7f173
+
+Count = 105
+Adata = b69f26fda6d1cd92897e03758cae020c4e1beb019ce5ad987f872940780a9468
+Payload = 6ef2df5a1688ae795537
+CT = f0876f56091dc3d2d3d2e4d0ffc0f0add38a80c7ffe6b4701e54
+
+Count = 106
+Adata = a7375ba32251af0138bd9fd8fcd56a7c43ab2ca9a7fc0117d25f6d4ef9c2fcbc
+Payload = 3f46c83021069ac488a1
+CT = a133783c3e93f76f0e4447fdd0b2f29f39094ba5a7375e278349
+
+Count = 107
+Adata = f9b91f7298b4e43843fc739a2f41c57c3f2cf36378fe4c34b574a43f9cedee7b
+Payload = 86c10a6dfdd6a06ef638
+CT = 18b4ba61e243cdc570dd57500f913ee3f46801e1bba9d4db7ecf
+
+Count = 108
+Adata = 9d35876d9449a1642b5062dfbfc7a26a7ac080b7198f4aeff2c79e463565cfd2
+Payload = 196c80d02b663bdd89fd
+CT = 871930dc34f356760f1856a6b87519b4807a2114ced587f72189
+
+Count = 109
+Adata = f2d5e927eb507f889efc6f21d783851f638f978c74960cc347f89f2703476114
+Payload = bd27ae3ade0781a33d5f
+CT = 23521e36c192ec08bbba2101012808adefe9b8166e04685bd537
+
+[Plen = 11]
+
+Key = 006ff7d3153caf906ec7929f5aef9276
+Nonce = 57db1541a185bd9cdc34d62025
+
+Count = 110
+Adata = 7d9681cac38e778fba11f4464f69ed9ebfea31b7ffcaf2925b3381c65d975974
+Payload = 31be1b241cae79c54c2446
+CT = 9dd8a4244fbdb30b624578a625c43233476bbb959acd9edebe2883
+
+Count = 111
+Adata = 1b0012c468009bd2851653013782c7b71ef43c393afd4dc0aec4d6d0c3fa11c5
+Payload = 8802831e22092b30110cf7
+CT = 24643c1e711ae1fe3f6dc9d477ca066ec2befa854a1faef018ea8b
+
+Count = 112
+Adata = 48b216375c00ca7e9c4048834b37944d2543e24fa091fb3c7290e11c53a6b6a0
+Payload = 3b3f782d637319d7fd161d
+CT = 9759c72d3060d319d37723eb6be9a78dfbd9e16181679b782969ad
+
+Count = 113
+Adata = f3e06a45fcf1f6abeb00727bf2c9bcea00ce621d38f7b7eba17c27e51f04c793
+Payload = e98f5e5a20d02c80372d6d
+CT = 45e9e15a73c3e64e194c533d9574d95b821a5170e9b61d8e6b2ff3
+
+Count = 114
+Adata = b36e27729f9a139d8ec4f61215b7bf1149cbb4d93a5c14bebd7cfb7c6fe585cb
+Payload = ceeed4fde3406ec40f7ac6
+CT = 62886bfdb053a40a211bf8aa193d257907be1330abaa56bc4f431a
+
+Count = 115
+Adata = 8886ed7fa414d74aef704a9751b197cbab02c41c6aedcaf65cda019dc2d2d815
+Payload = b38f03449883773135c0cd
+CT = 1fe9bc44cb90bdff1ba1f31d92029a6428748664b5c815f15ca1b7
+
+Count = 116
+Adata = 816d81af167d2294497d9b06a39fdf75e37cbacf4d10c3a444068c891b361bba
+Payload = 8efb141db7b77c521003cf
+CT = 229dab1de4a4b69c3e62f1386e4ad7c72ce0081a85d4cfd34254c7
+
+Count = 117
+Adata = f427c47e10c45bb3c7e75e9e604503b3560427691470358efdef48ddaf3794d2
+Payload = 6dc38e37d1379732df4dd5
+CT = c1a5313782245dfcf12ceb98eeb05bc376a1042735569d5b63f8fa
+
+Count = 118
+Adata = f3df712b5e8dd8e4aa8b7c5f41e93bd11b0df66a3456a01f3d0094ad91482cdb
+Payload = e0e358aff203369dd5960c
+CT = 4c85e7afa110fc53fbf732065b03ebeb68a9153cb4ed152ce0d64c
+
+Count = 119
+Adata = 264f2c7b095a296eb8ff6b5151ab3d9497ea8dc0002a9e5b09c2fd0ccd32b6ff
+Payload = 57b940550a383b40f3c308
+CT = fbdfff55592bf18edda236fcd16c8360a408e2787f930ed275bf3f
+
+[Plen = 12]
+
+Key = 026331e98aba9e8c23a9e8a91d0b0c97
+Nonce = bccfe69bba168b81cbdf7d018a
+
+Count = 120
+Adata = 26e011143a686a7224ddb8c5b1e5d31713fa22c386785e2c34f498ae56d07ed5
+Payload = a82200ef3a08c390dec5cbf9
+CT = adf4fc6f9be113066c09248fcb56a9c1a1c3bb16fbb9fbaedacdb12b
+
+Count = 121
+Adata = 97a720ae4720546e31263a1a538ce1d35c198c23bd4362e0023a67536328ab9a
+Payload = 7fc58d1bb450b396b9161f53
+CT = 7a13719b15b963000bdaf025002120b619a391fbd23402e5edd4949e
+
+Count = 122
+Adata = aff6c8cefda055c67262e9c68825d1ad2a7488e5b09640a111fabf6254d96cc0
+Payload = e9ea182d7f895f312b9738db
+CT = ec3ce4adde608fa7995bd7ad48b6e9a8de0099a28cebbf5c2bad42ff
+
+Count = 123
+Adata = 35a3963b43f47855ef3df12af5de3626e0c5c8d9cd2a534c737cd695609b05a9
+Payload = cfbc8bcbb5e5bb744bb1f340
+CT = ca6a774b140c6be2f97d1c36df80fd62e751757bb0a32a987980afe6
+
+Count = 124
+Adata = 46a2e6bd3fd5336abf02eace3cd1e1f6dde505ab976a9fa596edd6fbde7175de
+Payload = a334f8f41897cbcaeb5cffdf
+CT = a6e20474b97e1b5c599010a93b211350c70adf9bab5c01081bdc6a99
+
+Count = 125
+Adata = d110651c00ac5540f9d1ed9eb175e06b97163fc36d43f048565e5d0c30a069b1
+Payload = 3f781267290e8e73c6355e75
+CT = 3aaeeee788e75ee574f9b103d7f65690d9a2fb6759d658c9bdfdfc37
+
+Count = 126
+Adata = 978644dc4e36f1d98a2a63e19bbf8af11785d09fce58a95c00cc6bf6cecf6161
+Payload = 3dc39dbb91efe8b16396d488
+CT = 3815613b30063827d15a3bfe0d5df472f49e7f713cd1373293810906
+
+Count = 127
+Adata = 5ae7528c5e965880b1533cbd78c1e81a8187379327a2fc3f76ff45829049e183
+Payload = 6caa8c0764512baa39dabac0
+CT = 697c7087c5b8fb3c8b1655b64bfca9ef00b0f2bbb03c1a3f7a0862e7
+
+Count = 128
+Adata = afe754828be6e3731d3eee54b021b4fa182247bd958e9074fb0094a11030f5e8
+Payload = b19bc92e2305883580dd7742
+CT = b44d35ae82ec58a332119834a03be1d1d262b03c0ab425d533fe4ec1
+
+Count = 129
+Adata = 0650859c635654ca4d815963c0a99f9d2f47456ad37f739c425e924d4360bd7e
+Payload = dab87e79544df1cc98096b91
+CT = df6e82f9f5a4215a2ac584e7da61ca8461925996880e2874393232d6
+
+[Plen = 13]
+
+Key = d32088d50df9aba14d9022c870a0cb85
+Nonce = e16c69861efc206e85aab1255e
+
+Count = 130
+Adata = 0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa
+Payload = 4b10788c1a03bca656f04f1f98
+CT = 89f15b1cb665a8851da03b874ca6f73242f2f227350c0277e4e72cdaa6
+
+Count = 131
+Adata = a533b3279db530eaed425842b0d3528f5c5e4c16acfa0f49de43d6491f0060a9
+Payload = de6ea86d3641d916c4394fdd31
+CT = 1c8f8bfd9a27cd358f693b45e594271cc06f81d510075728cfeb89222c
+
+Count = 132
+Adata = 8e6c1cde142e18635c1b4f0cb54d3cf817f22ad7c25bf6a022501682f6a7da1c
+Payload = 6f3b32adc8c0314872947f3d31
+CT = adda113d64a6256b39c40ba5e5ab1aefed75400a41447b2bd8f0605542
+
+Count = 133
+Adata = 248a4389da2d51b87907dc11c46253515503ba80de5d06c9b505cb89906614a6
+Payload = 0cc992a8c736b44fedb4ad498f
+CT = ce28b1386b50a06ca6e4d9d15b46b3a6463876f1a43a287748f339e913
+
+Count = 134
+Adata = 2e2c8244a2cbf53816b59e413207fb75f9c5ce1af06e67d182d3250ea3283bcb
+Payload = 98104fd3f3413ad1f57ef4912c
+CT = 5af16c435f272ef2be2e8009f8f625786bdc58af24b17c1ba34fa87baa
+
+Count = 135
+Adata = 4ada86d88d5f49dfcde13fc30ba9a1af58d5254b47fb1885a20fad915c87952e
+Payload = 3b4fec79d52d8b2a533917b75f
+CT = f9aecfe9794b9f091869632f8bd4a918290cf97208232c76908514b07a
+
+Count = 136
+Adata = 9e3b23232e5a9e69747f8bcb148cd6d282fd9b7ecd6d97e8bb5cdc261b2fc86f
+Payload = f10c19c76ae7ed55e1651155df
+CT = 33ed3a57c681f976aa3565cd0b01d6306bb91c315bb4a23fe23d496d09
+
+Count = 137
+Adata = ccea2c815ea4efadc3007f511d633e98f9fa38b0e0fb572b282ed6a610adf7a9
+Payload = fa34af376868d9a49aa200f59a
+CT = 38d58ca7c40ecd87d1f2746d4e620d9d3004587c5d510e2a857fc857ea
+
+Count = 138
+Adata = f7277fb296e2c0d2c9ceb7013ea8b59fe37e26b3b42a0b8cd01aaaa8d35283d4
+Payload = abe2fd996bb6804ed3286c057d
+CT = 6903de09c7d0946d9878189da982d2438a5138977bde5f514e2335c28c
+
+Count = 139
+Adata = 14dd1810df3eeee78ed3836c77edf510d91ea28f119bf57111e580d70da94b74
+Payload = 395ea6979b77dabd2042aee4ff
+CT = fbbf85073711ce9e6b12da7c2b78100a05448fa6e74bd3ed16c3bd364e
+
+[Plen = 14]
+
+Key = 7301c907b9d2aaac355c5416ff25c59b
+Nonce = 7304b65b6dab466273862c88b9
+
+Count = 140
+Adata = 2c5d114eff62c527cc2e03c33c595a80fe609bfc0fe13ce3380efe05d85cceac
+Payload = 484300aa3a506afcd313b49ead8d
+CT = 928ca58b0d373dc50c52afac787ce8eeb5d5b493661259a9d91ea31a5f7e
+
+Count = 141
+Adata = d9ebc1cbfab9034317132a72e0f11c341331146a59e7a2f26bf4f3d778da52c4
+Payload = 8b318f75ed79a7978adc17c4d2d4
+CT = 51fe2a54da1ef0ae559d0cf60725552193439abfedda67d765d030cef30b
+
+Count = 142
+Adata = 9aea86b9fbd9bd4504ee2e25054942b33d3cdbd84215db7ea337e548cb706780
+Payload = 0256b0d154c768c85070da6ea8c7
+CT = d89915f063a03ff18f31c15c7d3615013c2bc9338868fad0d2fac11df019
+
+Count = 143
+Adata = 08afe10bbfbd65b948a6561bbeaf3ab46a8e3d0a861f1cfc46584156197f30a3
+Payload = 89ed296a3ac03fbfb71422b92117
+CT = 53228c4b0da768866855398bf4e66c3c4cb8c50891d6523245e4c619aa99
+
+Count = 144
+Adata = 7d653792bb8683e07c7d2c800db6f7f08343c85af2377115df4fc86ff7d8fcaa
+Payload = 414b6acb1db479028f5cc8800f2b
+CT = 9b84cfea2ad32e3b501dd3b2dada792d2cb93e45811a4c897ae9d907c9cf
+
+Count = 145
+Adata = 4d73c1484f9429eb15742f29ab05cbab6552abf40e127b93427d649d195ed25a
+Payload = 163f67b3766c3c650ce26c5bd8b5
+CT = ccf0c292410b6b5cd3a377690d441983a87812eaa7b66c5a0e54a01cb882
+
+Count = 146
+Adata = 2fba7a881f019a8745691343d79ef3656e25bb37b93fb5ab7311889f92010a5f
+Payload = 9c5b4aa703c27d16d82013853e16
+CT = 4694ef8634a52a2f076108b7ebe7b0afabd23b33765a63753cad66b0e6db
+
+Count = 147
+Adata = a640343fd4a866aec07b667d25176e11a32fb4d8bfc08fde2c46dc9b492fa010
+Payload = 99eb86b3202c7ce68a2339065f47
+CT = 43242392174b2bdf556222348ab639b8d0f97540373a7b9061aa3b2f7044
+
+Count = 148
+Adata = 9efd58d3ef5f74f663b2b5ca5e96c5a2fe85ca5eac1495d7f1751c7d8b412b3e
+Payload = 3f5c1d038161e65c9ed955c961af
+CT = e593b822b606b16541984efbb45e312c803e29f7be7c5eb236401037a320
+
+Count = 149
+Adata = a7d7ba684c0903323f7efc83dc32815195df325394162fb5a18f201047be7999
+Payload = be8dea2b4e602a787ecd28f2f7f0
+CT = 64424f0a79077d41a18c33c02201fd929c717d75388387dc25bfcf90b707
+
+[Plen = 15]
+
+Key = 38be46d271bf868c198052391f8a2147
+Nonce = 6758f67db9bfea5f0e0972e08b
+
+Count = 150
+Adata = c6de3be97f11d0e2ab85c9353b783f25b37366a78a2012cecf5b7a87138b3c86
+Payload = 61bd1385be92097e866550a55278f0
+CT = 7c9fa8d99b38f825315ece6a2613f55e902f296dcce870263ae50cda4fadae
+
+Count = 151
+Adata = 7c8cf9c650511f33af82e807e60336ec086bd2d9400a5f35652b8c3fcf968ead
+Payload = 7e5e51301fa44a21f2734731ee3710
+CT = 637cea6c3a0ebb7a4548d9fe9a5c15cae8a9e4b606f5fbeac2b829b42a150a
+
+Count = 152
+Adata = 5f8b1400920891e8057639618183c9c847821c1aae79f2a90d75f114db21e975
+Payload = 9cea3b061e5c402d48497ea4948d75
+CT = 81c8805a3bf6b176ff72e06be0e670f5419c6085e5434f056162cf80f6729d
+
+Count = 153
+Adata = 238d3c9d9de32f2040b1dd0dd040b921e456c3653263f4020cffdc552b948a46
+Payload = 20660408d6890aed84aa65dfe23032
+CT = 3d44bf54f323fbb63391fb10965b377fedcc743389a9d48e6b871dc0dd63b2
+
+Count = 154
+Adata = 3b5d61ca21953fdd22280747dd4ae908a511750127875da84dfe7d0063a318c9
+Payload = 9ab83c81f2d2c896c6596660c3974d
+CT = 879a87ddd77839cd7162f8afb7fc488137e0a856d3d911af9f420b68d8110d
+
+Count = 155
+Adata = 78c1751e86144a78285a30dc04f51742bd47e3d36b607bab48d91cddabfff4b7
+Payload = c1ec469aa9c73b677af225a9f5f6f8
+CT = dccefdc68c6dca3ccdc9bb66819dfd5644448fa8445b6cd185bdf9b3718033
+
+Count = 156
+Adata = add33e9a1d7e91e2c160c1123537e3f7e3535881cb4aac1a80ecbe367379212c
+Payload = 9df1d6b6debffdd316aeb27143508e
+CT = 80d36deafb150c88a1952cbe373b8bbd38e4dc44f768cef0c51344e3a7f7b8
+
+Count = 157
+Adata = df7736560b1a13aa8e536500ea6cdb9a6757309aadf25a6a9189055a309c3f8b
+Payload = 19eef017100dc82f26ed0815c55c12
+CT = 04cc4b4b35a7397491d696dab137172e7f2ec918099898b843a34c385f2a57
+
+Count = 158
+Adata = b40c8d22069b8a65cddb51c1ea3571160cacb19fd371552436b19c7122b28d08
+Payload = 2af5db43f2a5fe8b494b40661510bb
+CT = 37d7601fd70f0fd0fe70dea9617bbe94c2709685b0827cc42f3a25b579db28
+
+Count = 159
+Adata = 9de5559ea8ccc70f4375a436ce0b72551a75960ad5ed6a1949ee8f6c47548558
+Payload = 5de41a8ca8ed8011304fa9e9f36498
+CT = 40c6a1d08d47714a87743726870f9d63bf4b40ce7e672587816fdcda16efbe
+
+[Plen = 16]
+
+Key = 70010ed90e6186ecad41f0d3c7c42ff8
+Nonce = a5f4f4986e98472965f5abcc4b
+
+Count = 160
+Adata = 3fec0e5cc24d67139437cbc8112414fc8daccd1a94b49a4c76e2d39303547317
+Payload = be322f58efa7f8c68a635e0b9cce77f2
+CT = 8e4425ae573974f0f0693a188b525812eef08e3fb15f4227e0d989a4d587a8cf
+
+Count = 161
+Adata = b6fecd1edeb55a9a4148b1aefb716a1e162779a5ab2a682e4adce4479c527bd2
+Payload = 0e6118d0409751d36cb642504678535e
+CT = 3e171226f809dde516bc264351e47cbedf7f186e8d3d7c21c549c41ebcc7f505
+
+Count = 162
+Adata = 5c3933c30bf9d4841eff4000aaa1cb4d39cdf8ef1240e2aabbf9da95bdee5270
+Payload = 5c8a5fb36f860d00c21ae9e3f24097c4
+CT = 6cfc5545d7188136b8108df0e5dcb824810a68be1814f53c09aca4066527fef8
+
+Count = 163
+Adata = 7ca7ef30d3ac08aa51a9e5d3d84e8b6bb7fdde921e72b98ad6a93ebf2efc6b04
+Payload = ebd1cb4b35257790c9806be476bd25a3
+CT = dba7c1bd8dbbfba6b38a0ff761210a43cc30245a6e64625c4f6531d7497fb144
+
+Count = 164
+Adata = 90f1416768fca7dd48d01230dabf95f2f1a0c044bf2d755448aaf72316c8448c
+Payload = 842b7e5f22d921b2b8ab3131684b7eff
+CT = b45d74a99a47ad84c2a155227fd7511f10d85725dacc274034669acf7f34fed7
+
+Count = 165
+Adata = adc5c36849283d57acb2bcbc0e12465cb7c1830cb4e314b9ce6e25acbd8d460c
+Payload = f0c2cc5a1b4c4cbe839338fa0d7a3435
+CT = c0b4c6aca3d2c088f9995ce91ae61bd5f731b465eb59c4989e42020d86102a59
+
+Count = 166
+Adata = 80a7a483d1dbcdf00ed02a700e93d8b87fa6ac5c7368d1e81bd1b32cd1621cd7
+Payload = 2c1a5f906f2ae0373cc25e3519df2ba4
+CT = 1c6c5566d7b46c0146c83a260e43044484bcd2775448447ed801b3b0ff071c19
+
+Count = 167
+Adata = 13c02992992d2708250184a579c43bc29a3a8cf1e02dade4496cbd8b1214f97d
+Payload = 1da5190517546f1ad852f64263e1f679
+CT = 2dd313f3afcae32ca2589251747dd99901d1919f1451ad16f115cde863f15303
+
+Count = 168
+Adata = f6f18dfe093e4c0c3fbfa8a5b1f4a703c08addc2ab959741611a594b93d08bf7
+Payload = 13ccb08a580efea53dfba6a59626bbe2
+CT = 23baba7ce090729347f1c2b681ba9402ccae4f6ec07bf73d6f086cf09e2e14ed
+
+Count = 169
+Adata = 63708e12dfa14f192ec5ee5856dc3cf2403817d9628c31899b4613f65e1e61c2
+Payload = e0b5fbc6c2269d445a60273bf844892b
+CT = d0c3f1307ab81172206a4328efd8a6cb2bad8bf67d32a855c3940ac908397a5f
+
+[Plen = 17]
+
+Key = 79eae5baddc5887bdf3031fd1d65085b
+Nonce = 9da59614535d1fad35f2ece00f
+
+Count = 170
+Adata = 46603500af9e4e7a2f9545411a58b21a6efd21f2b5f315d02d964c09270145b3
+Payload = 001343e6191f5f1738e7d19d4eec2b9592
+CT = 2162e27bfbf1d00f2404754a254665fd9270f0edb415993588b2535e2e0e4fd086
+
+Count = 171
+Adata = 278afebc604bb7d87bed3574a2c5053de17eb8ca7e18ddc7892f2c54b38104a8
+Payload = ba47d5bfb36f6150a100e36caa116405c4
+CT = 9b3674225181ee48bde347bbc1bb2a6dc4778e3c4a11f3f9dc42554d45796379ef
+
+Count = 172
+Adata = 3239b2ce4efe4f6a6255dc53347400a6446ed3280c65422386fab471ef09eed6
+Payload = 96eccb7f9b0e16c6883de0a381e4767f5a
+CT = b79d6ae279e099de94de4474ea4e38175aab5540cc01d867f641c9b196fa159291
+
+Count = 173
+Adata = e2a5488d5f7930ea4ce399f2a6c0810265f7c0dc52fe824d19a0fa0d9ffd55e6
+Payload = d68f5990da1a2fe39ed81af145ab834fa4
+CT = f7fef80d38f4a0fb823bbe262e01cd27a46366fbe302e142dcf6aa16337d98550f
+
+Count = 174
+Adata = 0071f1edb3a0ce57af3c88bb0ccf138f752697a77e55695838fb39de04c78dfb
+Payload = cdd4d8b3d8f6e4742793b456cefc9e686d
+CT = eca5792e3a186b6c3b701081a556d0006df88c07797267bf5a49b3d0f601a225ce
+
+Count = 175
+Adata = f5d6989587e463969d97aadabea9538511f8d109cc2d3cecf09ba7cc346aaea0
+Payload = e7d7fc60ae852b68102e01b506f9dab986
+CT = c6a65dfd4c6ba4700ccda5626d5394d1865c9fbf69d81cef238ac513562d4a0dd5
+
+Count = 176
+Adata = e0b5fbc6c2269d445a60273bf844892b26fed03b82869edacd6dd7a63fd69e8d
+Payload = be9f51abfbe2da5a56db0f9a31b67c9f83
+CT = 9feef036190c55424a38ab4d5a1c32f783e2c748c8c9e3190de095de8eb0650203
+
+Count = 177
+Adata = e6bd0010c98e60b9af7cf905c58e0653bc425e2ccc809bd4f9cd7b1f95c18786
+Payload = 81b9c73029cea1936ef8755c80ba8d4093
+CT = a0c866adcb202e8b721bd18beb10c3289305cf563c5b4ba4ebd5bf107f2ad3555b
+
+Count = 178
+Adata = b1688cbc058816974694cd26c0f28ba9418e9912867fc8c5f4e7bd9c891a8d2e
+Payload = 618dc26853ee339689467ffbc2a77be69e
+CT = 40fc63f5b100bc8e95a5db2ca90d358e9e60dbbd8f46343c8442b03a472da4e23f
+
+Count = 179
+Adata = 469e004fee9878ed40621b41d04ec34af175f213d64d16e2f77d0bb2b6efe2e3
+Payload = 4f18bcc8ee0bbb80de30a9e08629323116
+CT = 6e691d550ce53498c2d30d37ed837c591643352e46995e8c1aee43dbdb26b46c30
+
+[Plen = 18]
+
+Key = c14eda0f958465246fe6ab541e5dfd75
+Nonce = 32b63ca7e269223f80a56baaaa
+
+Count = 180
+Adata = 733f8e7670de3446016916510dfe722ce671570121d91331a64feb3d03f210e6
+Payload = 617868ae91f705c6b583b5fd7e1e4086a1bb
+CT = b2dc1e548b3d3f225a34082f4391980a0788b4cc36852fd64a423fb8e872252b248e
+
+Count = 181
+Adata = b6ec659856866959ef6fd4e71ba930f0e3e5fd49d7465fd65f6813ab4ca1a770
+Payload = b8b342c49c28bffc2a1c457db0b537ad46bb
+CT = 6b17343e86e28518c5abf8af8d3aef21e08895a66eb5b902bb23a1a8584249409fda
+
+Count = 182
+Adata = 89eb3636fff80230352a3582be5698e3401c9e0579d48f2680c6e5e24d99f74b
+Payload = 37d694ba94d0af8df662134f20d142903839
+CT = e472e2408e1a956919d5ae9d1d5e9a1c9e0a7fa792fb7246218f7d56d5fa4a5476bd
+
+Count = 183
+Adata = 03434f3709e19a1e37edfcaabc215116763b71ab1c5e053dbdb599f86959f25d
+Payload = 90e4c0550cb7b279ef61f9140b7d94b8003d
+CT = 4340b6af167d889d00d644c636f24c34a60ea83dc3f0012ae6da32a15fd1684835ef
+
+Count = 184
+Adata = 0e2ddb65fcc72094ac388d53a1055c7e902285c4c3c33c13bb6fbb4f1956414a
+Payload = 69b851e63a78baef90637978e3dfe8c47be4
+CT = ba1c271c20b2800b7fd4c4aade503048ddd7f09d38d3dba01995e36bd685c8ea3371
+
+Count = 185
+Adata = a42b2538ee2fb5f6a85d4d00524b01ad3331f61c404069243f35f28e2c2d0a82
+Payload = b7dbf8382115199dd2a2d87938c6ae6c4241
+CT = 647f8ec23bdf23793d1565ab054976e0e472c89becf8d2bb935cb17f44b950df3ef5
+
+Count = 186
+Adata = 09bc5c426dc1faa4d71f50908bd6f297ec8e754d4d20def005585b4bc1fa31da
+Payload = d53698d719c51bf9eae346269c6a1da07162
+CT = 0692ee2d030f211d0554fbf4a1e5c52cd75196e28badf0202097e80561451796194d
+
+Count = 187
+Adata = 2ac87e59c2c86532cf165af3e8ff4871d730f5e742cccca38bbcdffff4472c93
+Payload = cfdb7363985aa01af6f8e8237dbfb7871eb3
+CT = 1c7f059982909afe194f55f140306f0bb880710d4d7f66660891ac655d6eca4a3f3e
+
+Count = 188
+Adata = 05d2fbc3d0ec81f52f31cb0c4bf960c2076867f6d9f0174ed9176e20177b2693
+Payload = 56fdf10dc0c1dfd10965b83938e557459c61
+CT = 855987f7da0be535e6d205eb056a8fc93a52f90ab18925fea6964490f364a975a473
+
+Count = 189
+Adata = c2c3902cfe8622254b3787cc13e79c5a3c388c2357c29f1c1ab5539a10bfae5c
+Payload = e7c9812eda2ed7dcfc80fc5fe0d43e1e5982
+CT = 346df7d4c0e4ed381337418ddd5be692ffb168a00e5e7a39b371024927d3ac98fe43
+
+[Plen = 19]
+
+Key = c5e7147f56ba4530b8799ababeb82772
+Nonce = bdd38e173fb20b981659c597d6
+
+Count = 190
+Adata = 3a069a2bfda44abbb0a82a97e5e9047258c803da2c66190d77149e0f010b3af9
+Payload = 2f3bf0b566440912a1e47a0c07f1cfd39cb440
+CT = bd6265dcba9e14c59e515e395dc60bd053345fa6d7568c738e3a7fdf142d8f2d1562c0
+
+Count = 191
+Adata = 7709132415c94960025cc39c950ead208703a9d5a71e224fd022dc0a1817d0f4
+Payload = 7c880d787726c4ddeb2304b5d161b4a257298e
+CT = eed19811abfcd90ad49620808b5670a198a991f22337efa5cb7db7240e7518b67ffbb1
+
+Count = 192
+Adata = aad77595f87a27f2c7995fc7149317f4cbebcece8336db2068380070784a4283
+Payload = 08c43bbfa706512aa39e2bfa5c365aca11e22e
+CT = 9a9daed67bdc4cfd9c2b0fcf06019ec9de623140bac6094528f02eeda093312fcf716f
+
+Count = 193
+Adata = bdb1b82ba864893c2ee8f7426c7b9a8460b00a50f164fc8f2ff2ae9cddab8657
+Payload = a531c0ed8840b2fcf08d76eca71036153b6e11
+CT = 37685584549aaf2bcf3852d9fd27f216f4ee0e0c041d86dd483c1d6da366e91bd826dd
+
+Count = 194
+Adata = 38b3b9f45041ceb743fc2655b409213fa081427e41c833a2321a09fbd566c80c
+Payload = 177946b4dc3b0b825a505f097a0a203eb21c00
+CT = 8520d3dd00e1165565e57b3c203de43d7d9c1ffde45ca2a83dec2f930bb652a6fcdc5f
+
+Count = 195
+Adata = ec9d8edff25645520801b6e8d14a2fc3b193db70d5e5e878742de83154a578da
+Payload = a2634ef20a2a418b2c3be64f0b5f79d7ea9b7b
+CT = 303adb9bd6f05c5c138ec27a5168bdd4251b648b89aa22cd7d0170a975565cd3a33dc1
+
+Count = 196
+Adata = 8f6c1de4efdc5ac2d6e5452b5b4f58416d618da672f521332fd297ede8350134
+Payload = 40e52edaad5acf2d4eedfb3f9ac2908112e9b1
+CT = d2bcbbb37180d2fa7158df0ac0f55482dd69aed960b33c3df5cd38a82980dc0950ada4
+
+Count = 197
+Adata = b0f1dc85fe223bcf29cdfa9319866bacd0a0a79c554e24d1f10889279e31c0af
+Payload = bf97780f498c23adcf1c49f60873780a235969
+CT = 2dceed6695563e7af0a96dc35244bc09ecd97638fa273c4102b5ca050b23044ac2064f
+
+Count = 198
+Adata = 7d02a323aa769a8201549bf48a520d940bf6f69ed6106f1ce68856c22a594216
+Payload = 58bfe1eb2d38d91f80b3467db94fdcb84ff5f3
+CT = cae67482f1e2c4c8bf066248e37818bb8075ecc15438af1bafac3eac61e1c24ed00ab7
+
+Count = 199
+Adata = d4b90ef8abad08c552c8c3b080b8c37df314d514049d45e27ec4527cb06cdf85
+Payload = a206a1eb70a9d24bb5e72f314e7d91de074f59
+CT = 305f3482ac73cf9c8a520b04144a55ddc8cf464422d9e2f4f84fde49e9701296294d5a
+
+[Plen = 20]
+
+Key = 78c46e3249ca28e1ef0531d80fd37c12
+Nonce = 5de41a86ce3f3fb1b685b3ca4d
+
+Count = 200
+Adata = e98a77f2a941b36232589486b05f4278275588665a06d98aec98915cc5607e06
+Payload = 4802422c9b3b4459ba26e7863ad87b0c172cfe4b
+CT = daea2234ea433533bf0716abe1aa3844b6d3c51e9d5ca3d8ec5065630d2de0717cdeb7d5
+
+Count = 201
+Adata = 5970a836de1f1e91d94d7eef79742cbbd46a759c413715eb0224fd6a27145333
+Payload = 796a69ad0e9379173ef6b66f44f5c84fa70a0e28
+CT = eb8209b57feb087d3bd747429f878b0706f5357d0ff0648ddb07f42f815b38bfc95688b1
+
+Count = 202
+Adata = e3f08834c4894f6fa66a55a280c0e677a79e97c1ef9488b21384e74e57b1b51f
+Payload = 98e1f8cf250183b13ad418024dc40c1a6a7ee8ac
+CT = 0a0998d75479f2db3ff5e92f96b64f52cb81d3f93ddd9a6977ea8e7adf5c5234346e560f
+
+Count = 203
+Adata = 18349be2894d49290339b97f4db28c92b3e112ffac77100abbf9c093935b1a46
+Payload = 4a856d9b50a5b40d6566b38eae6a53ed0c192805
+CT = d86d0d8321ddc567604742a3751810a5ade61350bdee05328a7ea8cc6c2e42bf3faeeda0
+
+Count = 204
+Adata = 7355e34ad13880de17a1d66b02672ea5c9f51774019f64ecbe36747ffcd9b671
+Payload = ad048eb2ad75266b43b59d9d1f073c44e4cbf25e
+CT = 3feceeaadc0d570146946cb0c4757f0c4534c90bafb1435cf929db35ec5986aabaf4a7d1
+
+Count = 205
+Adata = 4be21ba2eb26234ddcbb6aac6b4c3be7ef644af64edf51b7c29ffc3ddd80036b
+Payload = 5b527ac6cc6d1b4c3c56f8315bc96dae91632df9
+CT = c9ba1adebd156a263977091c80bb2ee6309c16ac736be6563cf9f5bce97486b7cc6f1c18
+
+Count = 206
+Adata = 266e0e3365e06d3b1e864c6e5897145df7bdde90eb744013a7b36632d4cf6580
+Payload = cee059cb0fe91a39faccc2914340baeab4b644ce
+CT = 5c0839d37e916b53ffed33bc9832f9a215497f9b2e90335fcea56b969b4fce65442768dd
+
+Count = 207
+Adata = 55a723883a340877d85ad1a5f264f2c834d824c7bbf207cdd8500c9d11ef9225
+Payload = 85321fef6a2b7d31cbd079c4bf2bfbbc979df90b
+CT = 17da7ff71b530c5bcef188e96459b8f43662c25eacd6afdb3578ebc75e8a408d32758931
+
+Count = 208
+Adata = 773864475a1a60a778468a66cbe13dfe3458094e62abb593f50c8495e3a8b81e
+Payload = e227b8d44320bd3ce9d3f7d688f3de887947b1e9
+CT = 70cfd8cc3258cc56ecf206fb53819dc0d8b88abca19fb73fc0488d9f29a09c1b47e3e066
+
+Count = 209
+Adata = f64f3b00c9117aed3c486aa4c8d574b44d679be4069e1078bb7100af38cdb190
+Payload = 206e9eb2bc3f8534d844a38debf1306df808744a
+CT = b286feaacd47f45edd6552a03083732559f74f1fce2c5ef8cdce76b358739e2a1b173fb3
+
+[Plen = 21]
+
+Key = 8883002bf13b3a94b2467225970df938
+Nonce = 818a702d5c8ee973b34e9acda1
+
+Count = 210
+Adata = 545aeac737c0ca2a3d5e1fd966840c3a0d71e0301abbe99c7af18d24cc7e9633
+Payload = d516bbff452e7706c91c7ace3e9baa76d65ff7050f
+CT = b85242fdc06344f2bd9a97b408902ebcd22aece3d42f2da4dd4d817c9fa2d44bc02163a0a9
+
+Count = 211
+Adata = f032db01da60ca078d35c3fb5d05d6750fce1c01911a0422e827e8976946e4dc
+Payload = 590d1aa655fed50ca2e402299f2da6fe20eed56071
+CT = 3449e3a4d0b3e6f8d662ef53a9262234249bce86aa180f41bccbcd47c8b7890754c032269b
+
+Count = 212
+Adata = 71ecb4252518997b53491cf42a3e0fe1496a2af2329a16f9fcd9c4f249900341
+Payload = ecd86cdb7d78d310dca5b477cd9da2612f5a05ab39
+CT = 819c95d9f835e0e4a823590dfb9626ab2b2f1e4de21d6ba58cc2eb474401851bf9502c3413
+
+Count = 213
+Adata = ec7abed9bda4a52fdf1bf278b6bdd6b0a27d4688deb9ff5ca9c8c865a4d2f730
+Payload = 0024b14c283df032cf80c22ad8d2c96289ee229092
+CT = 6d60484ead70c3c6bb062f50eed94da88d9b3976499b94d4b7a2044696c72322e850537b6d
+
+Count = 214
+Adata = c2c77d7ad7b27d7c0f976a1e28881ea4ec7ad03b63a4e67f47280a40b8f58086
+Payload = bc6965d8f62d066d118c14044c1fd2a224b9d95110
+CT = d12d9cda73603599650af97e7a14566820ccc2b7cb9d8da8e718570caf8bed7909fbff3ec6
+
+Count = 215
+Adata = 28929286bd1391468ac75f5c03689f74780ddd7585fc16f9a9bf7b00357a72e5
+Payload = da4a630cabaff0728a1cc3e6a79721a7176b708f1d
+CT = b70e9a0e2ee2c386fe9a2e9c919ca56d131e6b69c6e671012690c61fe3c9abd50a78eb4736
+
+Count = 216
+Adata = ed360d22081b019dc979420a3a45c21c8903c59daedd9f1b4ef2bfdedff0ec1d
+Payload = a95058f8e1f6bc0f143a9ca7e4425a2a63eb2f7e33
+CT = c414a1fa64bb8ffb60bc71ddd249dee0679e3498e8e657e2250427130acef7032454cde7b6
+
+Count = 217
+Adata = 2b4022d0b951fe48635d04fb3e2fa032c07c855fdd73f45670953bb9ddc77cb4
+Payload = fcbbc7f9d1ace60e830ca56ec84814fbd2579993d4
+CT = 91ff3efb54e1d5faf78a4814fe439031d62282750faac6ff0a264b8199550d93c1f06063da
+
+Count = 218
+Adata = 48e553a87a7d3c1bd68af39f96aca67583da86e06701d5e4c4ed404dc66d70f3
+Payload = b95d298d391c6b893c6cad66f9780534516e71455e
+CT = d419d08fbc51587d48ea401ccf7381fe551b6aa3857e68bf636e81c332f72063dc0d6fc2b6
+
+Count = 219
+Adata = e8e2835e47144365a2f218d4c95d7522e824fb43b66d4727ee570f8303dd6dd3
+Payload = bc79d444dff9d9e722effab07b068cb7723ae8fae0
+CT = d13d2d465ab4ea13566917ca4d0d087d764ff31c3bdf3af9e9c4e04bad261dc17cf00a00dd
+
+[Plen = 22]
+
+Key = 5cea00ee44cfb9cfbb598d3812e380ef
+Nonce = 948788a9c8188cb988430a7ebd
+
+Count = 220
+Adata = 50422c5e6a0fb8231b3bb6e2f89607019be6ad92a4dae8e0fe3f9e486476004b
+Payload = 33bfd0713f30fcac8f7f95920ac6d9b803ddd5480dd8
+CT = b168747dea3ae0fbede4402af9a3dc3185d6d162f859d828101682de32923788c70262b84814
+
+Count = 221
+Adata = bb0036b34b0c20094d335a8c74f6b3dea42eeccf4145192eada64ae00c726b2e
+Payload = 5576d94b577ed26820fb13c00ab0e2d1a1c3589bfdc4
+CT = d7a17d478274ce3f4260c678f9d5e75827c85cb10845bafc4ae4d31907def6f648b081174e2a
+
+Count = 222
+Adata = 5140324aa758dbbb5391b5e6edb8a2310c94a4ae51d4fba8a7458d7cc8488baa
+Payload = 13303e14068205cbfa992d4ccb6a265804ea64a15d7f
+CT = 91e79a18d388199c9802f8f4380f23d182e1608ba8fe314e378e9ed6e725a14c07632b02bdbd
+
+Count = 223
+Adata = 74da07d324060e590356988f27d9879fa3a3ade0fe71e2a0e49054211cfa1fe1
+Payload = 567e6d14b446add630d53ea86a537c0938537c4604a8
+CT = d4a9c918614cb181524eeb1099367980be58786cf1295bc2f2f9331536f7f70be09c41bda0ad
+
+Count = 224
+Adata = 0e403cff47adee3ec5bb6b178dabfc7d53b60a04eaad33a2fedd9db705358a4c
+Payload = 9f3d165d44cf1c5770346d211d4ff34ca2ecd6b28549
+CT = 1deab25191c5000012afb899ee2af6c524e7d29870c86b59cc9c3c008bc5876ef86327859cbe
+
+Count = 225
+Adata = 211e6ce3d0c3abdef069e6e4fa35015797bd8a9d64bc9b75f20b028b12cca04a
+Payload = d726e599db6a6d40629bc4bda5e3fa2e5aeda229cea4
+CT = 55f141950e607117000011055686ffa7dce6a6033b25135e6d59a5385a78658d60d254f99962
+
+Count = 226
+Adata = 3c5c67b083322115e1b3112c2b6968efc050094e23e646dce982eac9d6e67d10
+Payload = 42646cfb8a99e48a35cee3f5f9b3e6175695973f6de0
+CT = c0b3c8f75f93f8dd5755364d0ad6e39ed09e93159861e234e83d9a0570dbf2b2fa59ce3cdbd9
+
+Count = 227
+Adata = 37a931f1dd05755b376d1a164aa36b8de802e39f8108a0453c1114754665fe46
+Payload = e814c7b5c72d973a9bc7ccd463f107325ffa3321783b
+CT = 6ac363b912278b6df95c196c909402bbd9f1370b8dba2084e352b1b157267228576dd056c1a3
+
+Count = 228
+Adata = f1ddc2c49da7363526ba36c600c589b4c3121fbb8c5b9a8aa0de0e7453b30568
+Payload = 4f7a5618870945b89f194e31b1aa802c5350326dc691
+CT = cdadf214520359effd829b8942cf85a5d55b36473310bf88ad35ee338e489e55bb49732447cf
+
+Count = 229
+Adata = d14b3d3803df432488b5d66704abef6a500d397e855bc2c2574df746a515cf70
+Payload = f555216840a1f40b411d44128e567617e2694caf1621
+CT = 7782856495abe85c238691aa7d33739e64624885e3a07ab67f9397a81371ef6ebc775cb7007b
+
+[Plen = 23]
+
+Key = cb83f77751e72711401cbbf4f61aa0ed
+Nonce = c0b461b2e15b8b116ef9281704
+
+Count = 230
+Adata = 2bd112231f903fa0dff085db48a2e2a96ec0199249b005d5ab4c2eab753f9ad0
+Payload = eede01b08f9a303cdf14c99d7a45732972c6eff2a1db06
+CT = feb114b7bd3b43497b62454a675a632c3546d2802462c6af57647efda119c59862cd5dd3904efc
+
+Count = 231
+Adata = 864e0e728aea856fae6c6daa6357d1542cef7177f441ba21a563f6c4f6fdc1dd
+Payload = 8a56588fe5e125237b6cdc30f940b8d88b2863ec501a0c
+CT = 9a394d88d7405656df1a50e7e45fa8ddcca85e9ed5a3cc2af4027ca5824b41c7bb238d3e8eeebf
+
+Count = 232
+Adata = dac7f3cba0b5a47f67f85b226b66df695a8ae2501355e36aad105375bb95f732
+Payload = 66e34540d7accf377877aa2d3e6d2db0cfafc608a1eb3d
+CT = 768c5047e50dbc42dc0126fa23723db5882ffb7a2452fdf7fbd7044ce1d7b266bdf545247a3c2b
+
+Count = 233
+Adata = 07f48cdc12aa27119fbdfda4ec07ce6068c92ba7ba9c930905aadd156b1dd56e
+Payload = a9ebd04fba7155c39b5c29c5571b5354c9ae228f5e5b13
+CT = b984c54888d026b63f2aa5124a0443518e2e1ffddbe2d3afabc559b552cf7c7730c7dca25bc3ed
+
+Count = 234
+Adata = 2d24e79abd157af2c21b60932947fd9f9d6478f09ec56fffd341ea04a17b8e5f
+Payload = f179353aef342f0f691caf1fcb811e3f6504e14d6d9381
+CT = e116203ddd955c7acd6a23c8d69e0e3a2284dc3fe82a41488ca99e0f85ac388f981ce25560b8f9
+
+Count = 235
+Adata = fea280f710379e4665b5ed3d1620729a7bc164899dc83e6aee3612d538fa20db
+Payload = 6c19a18eab544acc883c5886eaa89f54d61ae5f1f1368c
+CT = 7c76b48999f539b92c4ad451f7b78f51919ad883748f4c9156faae3d8860bed216e8d497a75962
+
+Count = 236
+Adata = 18f2e3457127c35f2e0cff2d821af8178028fcc7803bc795c49f4a435b37abeb
+Payload = d0df1bdf1df6203241722fb9c9c1cf7405017497ae1545
+CT = c0b00ed82f575347e504a36ed4dedf71428149e52bac8588cd7791c544d1098b2de49d04b1e0c1
+
+Count = 237
+Adata = 35221f0efcb109cb93c38a62c58b5ab8b236437e171e8507cf417a569af1767c
+Payload = 479526b33c42c240b9a4549ca70cbfb691f16ae3be8888
+CT = 57fa33b40ee3b1351dd2d84bba13afb3d67157913b3148c523fd8a2524717f63dac75c22268fa6
+
+Count = 238
+Adata = 95f2ab02af01aeacce86b02cf846f9fbd516963d06e350e8b7f6df2778765a01
+Payload = aa6761148b254a2ff202b620c2ec2c5e623bf61f05e483
+CT = ba087413b984395a56743af7dff33c5b25bbcb6d805d4392904f05dc2397596543df73de5aa708
+
+Count = 239
+Adata = 3746a36154e42dd600049d506f5ce4d034864263b1a65cecd24c8e25fb9c82e1
+Payload = 2f298f106703b8a994cbb20acf47f9442e44f6b5e82c38
+CT = 3f469a1755a2cbdc30bd3eddd258e94169c4cbc76d95f8c3cbfecfa3f75fb111ef0011222b7948
+
+[Plen = 24]
+
+Key = 43c1142877d9f450e12d7b6db47a85ba
+Nonce = 76becd9d27ca8a026215f32712
+
+Count = 240
+Adata = 6a59aacadd416e465264c15e1a1e9bfa084687492710f9bda832e2571e468224
+Payload = b506a6ba900c1147c806775324b36eb376aa01d4c3eef6f5
+CT = 14b14fe5b317411392861638ec383ae40ba95fefe34255dc2ec067887114bc370281de6f00836ce4
+
+Count = 241
+Adata = e82fc3ffd276218a82aede65fe5abf4fd35c7059a26923f8dbb97a59c903a7f4
+Payload = eab8cef576816a82ed036f158e5036f5987b195e60582a6f
+CT = 4b0f27aa559a3ad6b7830e7e46db62a2e578476540f489460d2d30268e9f1ce0e7c762993297d828
+
+Count = 242
+Adata = 776aae7f62225556b6da522c0c9432ac70fe72ac6f3f361071ef3deb4a6715e8
+Payload = 566ef9ce1d397be2547c385639507a9e7d6f9eed9a3b1055
+CT = f7d910913e222bb60efc593df1db2ec9006cc0d6ba97b37c0939e56f0b7200d1b1409f3f8e8179cc
+
+Count = 243
+Adata = d9aef0955922f89747ba4a8ddcdb8c1c7579aefd3c2eb8ad0589c66576a8504c
+Payload = 8c28b6d93b23f1ea031d5020aa92f6608c3d3df0ee24a895
+CT = 2d9f5f861838a1be599d314b6219a237f13e63cbce880bbc138e3b817023993608be06fe92efca8b
+
+Count = 244
+Adata = 13c222a65ce30570ecac85a185a2a0922a8c96d633339a1ca067ce57ae426e1d
+Payload = f0c1cd60f5fa8d1efd5e2e1ab37c4f7e6aef76d15e8d6ac8
+CT = 5176243fd6e1dd4aa7de4f717bf71b2917ec28ea7e21c9e1f3ca13b4ab7fd0d4badf158972570c06
+
+Count = 245
+Adata = ce40fb0cbfdf07676ed55b040ae6be5db8f0a0f28816ae8ea71da3cbd71661d8
+Payload = 570d5f79aa8db14b1ac99ee567cc105ae9e238e482b52628
+CT = f6bab6268996e11f4049ff8eaf47440d94e166dfa21985010a79fa4e8b27a31ff360a1b6c05ff844
+
+Count = 246
+Adata = 446b01d09cbc41b6393ef81ca65ab7e099018187d5f9d22f5074dfc491e72077
+Payload = 7c267223047af946b06f6a45ffde4a5ec49c28b81ca22da4
+CT = dd919b7c2761a912eaef0b2e37551e09b99f76833c0e8e8d5d34ef0ca0b47d6a2ec7442cbb739504
+
+Count = 247
+Adata = 01ec87920b42639d4ba22adb1fbe5138d2849db670a2960fd94a399c1532ed75
+Payload = cbf112e4fb85276c4e09649f3de225b2398e86ac3fe48bc7
+CT = 6a46fbbbd89e7738148905f4f56971e5448dd8971f4828ee8f607d154393e35fd1efc1ae8cb244e4
+
+Count = 248
+Adata = 5032b818d202872f3fe2b08fc7940696df02cf393a6d6247f5c6f5f2125cb08b
+Payload = 4324a89788e8ddae5d560cf937df701743cbbc3bf980558c
+CT = e29341c8abf38dfa07d66d92ff5424403ec8e200d92cf6a5617d9cebea38591a00c9fba4ef9c8e71
+
+Count = 249
+Adata = 27b661861717f00a3ae22ead78f4dc3f32b40e8fcb8ed58167a31a61f2becd77
+Payload = db72d98d63fc10acff7dceec0e2691a80ecee50a0e957ad1
+CT = 7ac530d240e740f8a5fdaf87c6adc5ff73cdbb312e39d9f897062a1ec759a515b938780f902fa7c2
diff --git a/lib/crypto/test/crypto_SUITE_data/VPT192.rsp b/lib/crypto/test/crypto_SUITE_data/VPT192.rsp
new file mode 100644
index 0000000000..abf1775dd1
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VPT192.rsp
@@ -0,0 +1,1383 @@
+# CAVS 11.0
+# "CCM-VPT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Nlen = 13
+Tlen = 16
+
+[Plen = 0]
+
+Key = 086e2967cde99e90faaea8a94e168bf0e066c503a849a9f3
+Nonce = 929542cd690f1babcf1696cb03
+
+Count = 0
+Adata = 58f70bab24e0a6137e5cd3eb18656f2b5ccddc3f538a0000c65190e4a3668e71
+Payload = 00
+CT = 3bf9d93af6ffac9ac84cd3202d4e0cc8
+
+Count = 1
+Adata = 760d065275e345900a7bbab451cc9309fb161e6cfec526538b98800e4102e14d
+Payload = 00
+CT = b0078a769ab68db44e723993da382abc
+
+Count = 2
+Adata = ffedc67efd355ea404fcbcb3993d3bae81386ded86230270771deb747163bf44
+Payload = 00
+CT = 31fbff2d715a2eb9af54e8320a8e42e1
+
+Count = 3
+Adata = 55153ff5e4d208d2e647794f382c788e0e36f293e63e7290ba9ff2657ae0f167
+Payload = 00
+CT = 945839d62c9d1b899f6dcd0ca9517e68
+
+Count = 4
+Adata = f8813985f59bf284bd3882e899ca9b67fb496f3eb78d7ebe6ffbad084f639915
+Payload = 00
+CT = 903f90d23321a6882d6c4c1955b14847
+
+Count = 5
+Adata = 7b95cd827ab93507f1819ae76627d6e2a31d29890c092e5c300f0e2f9e4ef4d2
+Payload = 00
+CT = 652ec5ab43088eb568186d0d9887b30f
+
+Count = 6
+Adata = bd144c9bb974729aaa1188ceefdf85e1d9fddc0b0c8afe8828ba204aa9293feb
+Payload = 00
+CT = e6c1455d1117eec49338c96f51007309
+
+Count = 7
+Adata = 92b911cdc3137a6f7f32651b788eb82975660aea52b2c03b4759755a6da4a0f8
+Payload = 00
+CT = 1cf3c32fb229dac209523eaa517bb59a
+
+Count = 8
+Adata = a8200dbbfe4086015cdbdec2fc8e4934d0d663527430c424627ed44065ade091
+Payload = 00
+CT = ee10bfeb1cf9b3cd5a0faebd4d8f3fe1
+
+Count = 9
+Adata = 3b7f37b6b8e3c1390a99d59c47f7c102cf659d361a132ef8b4e70b9585bafebb
+Payload = 00
+CT = c51ed994253adb9bb5b9a8c34a27f225
+
+[Plen = 1]
+
+Key = 992d38768b11a236945bd4b327c3728fac24c091238b6553
+Nonce = b248a90b84b0122a5ad8e12760
+
+Count = 10
+Adata = 27cabc40da0e1eda0ea5f8abbb7c179e30776250a7b30d711b0e106c5ee9d84a
+Payload = 1c
+CT = 1a96f58c3f38c44d1a345f3e2da6679f20
+
+Count = 11
+Adata = dc2e28d5ae726c1beadb1e7e92ae7d14f5546320deb81a910bf170cbe0210eaa
+Payload = e9
+CT = ef0579aee7c17482691f3f832d867ffea7
+
+Count = 12
+Adata = c579f912ac1b45d5aa8cf20f78f0a1ace32abd3dc7fd0b3f3a7182a008795c7f
+Payload = 97
+CT = 913452d8ece38ffa1d4107d6a053acd8c8
+
+Count = 13
+Adata = 69ea953dbb910ec589372d797c7379d3f3b9e9fd48894c9b55e6e8eb360a6211
+Payload = f4
+CT = f20d760b9fe29530738157db0ba2d253f0
+
+Count = 14
+Adata = 622835dea57b2c70cca8f7548d6210714070b55b36adde7a4c547269c07aba9c
+Payload = 9f
+CT = 996fc21f24dee7b52f51d69eea30819f4a
+
+Count = 15
+Adata = 67ebda0a3573a9a58751d4169e10c7e8663febb3a8cf769d81bc872113f0720f
+Payload = 43
+CT = 4594c5b8db0064426a77dc536814c56147
+
+Count = 16
+Adata = 255412e380e9a28cbcd345be172c40f72dec3e8a10adfd8a9ab147e9022524e1
+Payload = c1
+CT = c76d36c0b0d699a22da3116dfb8f453181
+
+Count = 17
+Adata = c7c8e7151eb6844a954d091b460f83add0f0a634aa5ac213b774f2451aa497fb
+Payload = 31
+CT = 370c3a1690acc3f0eb09c9cfd3396c7fa9
+
+Count = 18
+Adata = 63f00b2488809fdc49ca5f05d54e98468906308115f7e702da05ddfd970b5537
+Payload = a7
+CT = a1ad45070fe4c61270c13cc52247fee411
+
+Count = 19
+Adata = 8e2c5e55c0bf70014e9897b6f6940e4e738b1e84e8269b6382f0b1fe59b0e162
+Payload = 40
+CT = 46b2a2a8b283ff7eeff5c2670f77b8809d
+
+[Plen = 2]
+
+Key = 5012db40ff6ae23c1e1ce43768c5936c4400b0e79ae77f30
+Nonce = b67e500b35d60ad7264240027c
+
+Count = 20
+Adata = 40affd355416200191ba64edec8d7d27ead235a7b2e01a12662273deb36379b8
+Payload = 0c6c
+CT = c996ef3d6ef9f981557506ecc8797bbaaaa7
+
+Count = 21
+Adata = c5e12e17e02bcc12b3a4c14cf837250e2886db3ee1c717d28bd11e8a3b764ddf
+Payload = 23df
+CT = e6254405257a837c5343b59d5689d6de5269
+
+Count = 22
+Adata = 213b5b6015d472bd593be5acf85ebba6d6a09f3a962be302ba83c6d70c61f241
+Payload = 0dc2
+CT = c838e93e67d37d2367bb1f27f71b54b29317
+
+Count = 23
+Adata = fc1b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+Payload = dc88
+CT = 1972ca3744a4ab375af9060621a9dc4f4c32
+
+Count = 24
+Adata = 5b2eb1a6fa585d61d1fb3da68f5b93829c8e2d5e4fe03782617553d7a130ecf1
+Payload = 8179
+CT = 4483172626e930d24052bc056d8609c4175f
+
+Count = 25
+Adata = e2b3c3bf33cf847660929e48cce51d9d9289945169651aaecb1e939756e93105
+Payload = 01fd
+CT = c407852310207be8d3417de800b372700da2
+
+Count = 26
+Adata = 6051f12cd8aae68b4023aaf7178fd086aa582b8d8821e36637abc97025f5e858
+Payload = ca18
+CT = 0fe228553bc037954dbf4ce5db99792c2c7a
+
+Count = 27
+Adata = 2d3555faf285caaddfe95c010c2a7f233e09c2fc0cd30d644035269280527ad7
+Payload = a855
+CT = 6daf904725668634d6345bd8f90a3831b452
+
+Count = 28
+Adata = 4fca820dc545bf93bdffed33a04b67eb45384e696f092c2197e5d79cecd09913
+Payload = 5555
+CT = 90afdf6098cb3135c3045a54ffce88efaceb
+
+Count = 29
+Adata = 1789ae403e183d2225f431f001d475b53bccdec66572bb027340ae592839ba8b
+Payload = 11dd
+CT = d4278568e8c08ff5ee5ea0a608589c2fc029
+
+[Plen = 3]
+
+Key = fa15cc7f0de294d7341b1fd79326c8be78e67822343c1992
+Nonce = e5257aed2bda0495aa44591db4
+
+Count = 30
+Adata = 31a0338c3839931fa1dd5131cb796c4c6cfde9fb336d8a80ac35dec463be7a94
+Payload = bcb898
+CT = 68f08298d9a2147776dca9c1a42382bce323b2
+
+Count = 31
+Adata = 4863dd810ee70ef0f5da81f60c5ce550abb96454619032322e34657af25207de
+Payload = d1da2e
+CT = 059234a9a77755b324f3a557217752ade14ed7
+
+Count = 32
+Adata = 173594fc26b167f044aeaf9bfe920cab99a27eb2b01827d61f7553cb2018b5fe
+Payload = 394f31
+CT = ed072ba4441a79a90e228a28069fe109d5d876
+
+Count = 33
+Adata = 71cdd16eca9255aeedc23bd623513918ea97da21485074415fe75bcc42f454c0
+Payload = 868bda
+CT = 52c3c065f272f44c5210b5bcc571e819580910
+
+Count = 34
+Adata = e84418d332d16d2298e69e7ff3c37bc7b6e030cc822e73b3f4a0029bc2ea4d80
+Payload = 52d6bf
+CT = 869ea559c5f7f73a1b5f419c9f63ca401894a8
+
+Count = 35
+Adata = 42d962109bea1d50be0f3d83b4c2a6033d53b3d7112591866b1ae52dc84cb5d0
+Payload = 6f8d58
+CT = bbc542220b828cf5365137fb3f1df67cc8d2a1
+
+Count = 36
+Adata = 943b4327b5c70dba63c82f27e0412b3ada012bc0f7dd39ebb13db2f864daf80e
+Payload = fda286
+CT = 29ea9c422b0f41075ac79a0afa2d1047cbbfb5
+
+Count = 37
+Adata = 6076b94caabfa476ab7e6482e4fda9b29f2e2b2883efe44d668c7c74628505bb
+Payload = 8651fb
+CT = 5219e1ae68cd6d6815ecbfd01293d160d4d38a
+
+Count = 38
+Adata = 3e4bb5781f84b4bbd23583e3dae561c6ff4af8eff35e2a4f35b50d2f360d3469
+Payload = c3e179
+CT = 17a963fbaa81cfdbcaee476860cd5102f556e4
+
+Count = 39
+Adata = 364008acbad330d0b8d574641a97b0682c49279cfdc80ff309b7514514d18a44
+Payload = 4a97d5
+CT = 9edfcf7ad1520564b68824a3a939371c21a336
+
+[Plen = 4]
+
+Key = b5330a8447d74a7987fb718cfae246b5c7e057991064eeaf
+Nonce = 2ef29d62b40d8643848797cde8
+
+Count = 40
+Adata = 1225b036e6044df52314016760e92750de0936120395de750a2c54a7fa0cea82
+Payload = b46b343e
+CT = c2c39d6f9344e2de064f269d065a2a6108605916
+
+Count = 41
+Adata = aaa6257d6783936a4445833c2ac3bea8cb7334f22ade9c035d515bbc91d6a78a
+Payload = cb216301
+CT = bd89ca50693d90b8297b90bc41c231d08b0204fb
+
+Count = 42
+Adata = 1c1915fab09348b9a5536495c70d1a040305708c1124797e564b63e008e7b8ab
+Payload = 697a8696
+CT = 1fd22fc79d0146fe373437c529fb2eeb169e4bd7
+
+Count = 43
+Adata = 864d0f786497c7ce283762ca0959ec9c825ed445a5dbe5b4b2e5772fe88ce7f5
+Payload = 6bee3db9
+CT = 1d4694e8e389c549bfc4ede936d7896e544b23ad
+
+Count = 44
+Adata = d5388b0b548c58886dcd335dff2b1ed23ce3eebbb708fb5bbd831c83e959d3fa
+Payload = 85d95855
+CT = f371f10495177a9fe6d9329a585c8737c92a4d29
+
+Count = 45
+Adata = 83cddd189736f224cad6a29efba45e43c75450a14f1541713b7fb926ffc768c6
+Payload = e8b23340
+CT = 9e1a9a113914431a10b1f94a2b99b9e442f3dca4
+
+Count = 46
+Adata = 8fccbd1fc5240691cf24e8807bf3416c1b2d87fc86dbf3955fa2e52b9a3a8457
+Payload = 595c4d7c
+CT = 2ff4e42d383d8dc98b22010dd93cd0cbb396d9e3
+
+Count = 47
+Adata = 513d45f6f37f3f051667dc743215059e06e4fdc8945789b16d50556a2e839368
+Payload = 314e0c7d
+CT = 47e6a52c40c513bfc92d1a7db5ed7cab2d8212b0
+
+Count = 48
+Adata = 70828be102e554f0d4b07641fa3254bc8db06eefaf5b85a7c97e01c217fc8f3f
+Payload = 35753e32
+CT = 43dd9763ea98f4ac6b3eabd483f1e6ab92f3b83c
+
+Count = 49
+Adata = 343d5a4ad39acf81adcf24e9807618932abcb3bc076734f179174c77c8cb89e9
+Payload = a531c0ed
+CT = d39969bcf99fb67b1e2aba2d232db2445e6aec2a
+
+[Plen = 5]
+
+Key = 30419145ae966591b408c29e5fd14d9112542909be5363f7
+Nonce = 27e6b2a482bbc6f13702005708
+
+Count = 50
+Adata = e04e81e860daf9696098c723085d8023c240ebe7a643131e35359ab04bd650fe
+Payload = 8ceaeb89fd
+CT = ec9d5ed36243ddf77b33d8cf2963ba76fd4e19f3c5
+
+Count = 51
+Adata = 6217cd581d4b3b2f7bcf1b8dad9ad6430e2e3a0063cad52260e0a1cd6fc9e73a
+Payload = 7e51d6f870
+CT = 1e2663a2ef6b73fe9e638e205b27f78ed1bb9b0ed0
+
+Count = 52
+Adata = 8aa7847e496f5e9f1f87851442de844f27a21c1b48f82fe525f0dd5a88b8ec38
+Payload = e0023b674d
+CT = 80758e3dd25936115e23158aff1916edec241fad56
+
+Count = 53
+Adata = 3612abc865a4d8d7b86a84109388584df6526525adb1006ec6c8d00048d725bc
+Payload = e2b5b6f36e
+CT = 82c203a9f1f15aae4b70dbee244be1daa74475d7e2
+
+Count = 54
+Adata = 849a99c6f1cae0ad4bcde4bd0811e87ca5ed7b913de1a8285a206e980b4b7043
+Payload = 9a17e4a22a
+CT = fa6051f8b5bbff424487848385f8501ab5a77f327c
+
+Count = 55
+Adata = 9066367c784de0a4d1116bbe95ce55ded85edddb6273c2049ee24e0fb3429352
+Payload = d4e765fc78
+CT = b490d0a6e772d8d5da6f593a8d9956731b42645aa9
+
+Count = 56
+Adata = e7aa9f767fa8920f96f91c41d9e86755faaedaeda596a444b65f99b7a9e23e85
+Payload = 1074349e10
+CT = 700381c48fe3eca12b835dcfd08166ac8831585626
+
+Count = 57
+Adata = bc0db1ebf910b6f4dcad5401401d6bc2272e23130947dc236ca664d5b5ed6d66
+Payload = a46dd7fb58
+CT = c41a62a1c72bcce66018e9e552d2c8a229301361df
+
+Count = 58
+Adata = fcbeba2d0d73239d05f691a52b08152c9dd871f8dc76c2c18b8a638a74460d31
+Payload = 2e0ca09221
+CT = 4e7b15c8be3e41a50a28ea3be14baadf12964a37c4
+
+Count = 59
+Adata = dcdefce64ae4339f46c0759a4a10b29d59daaaf1e5dbf75cf11b4e4f73c5025f
+Payload = 2e108ce0fa
+CT = 4e6739ba65bee2ab25bfafa76dc3e54832b2f76864
+
+[Plen = 6]
+
+Key = 748ad503388a34041a7bdae6361d57894357c333bacf02ca
+Nonce = 518b79d194579b19f2d8845b70
+
+Count = 60
+Adata = 691dd98f61fd213b0840ec5a6f06ef9a1420be0d59bde5e43546347a2a865a94
+Payload = 24d6880aed7e
+CT = 270120f9634ec15536e21d961c675070ec4cff9037bc
+
+Count = 61
+Adata = d1fd047cdb18463766841abb1fcd25257f1458b595bfcf24066ff9385232fa97
+Payload = 2298028d0213
+CT = 214faa7e8c239b303af0b098f902dc24e66fe56adc6e
+
+Count = 62
+Adata = 65a480d120a0459dab69e8f23094801e10092666cc56f9fb2549662982bda6d0
+Payload = f248e5225e3d
+CT = f19f4dd1d00d1b657925a9740d6828bd85cd12205764
+
+Count = 63
+Adata = b738a53fbc9689dd49f68f97f5a99665258cd52e74dc653b594cffec045508aa
+Payload = 611dade00cec
+CT = 62ca051382dc395a1c49129ef6cce0ad5f6ef378aa1c
+
+Count = 64
+Adata = 7006f54184f0ff0ab215ca408d46325b86c1cbae6da7838435b1826ff81f55dd
+Payload = 5871a8300471
+CT = 5ba600c38a415e68468d1b2b516be3d688567d84ab80
+
+Count = 65
+Adata = 9e6e6675d4c6b1e0f3894aac071f4c99a364708edea12f319cbc27b40fabc0f1
+Payload = 3ca8a7520e94
+CT = 3f7f0fa180a40ba1af163049d16817021665d183bc9e
+
+Count = 66
+Adata = 10ceef716f54b74d7c8a435d6aa38a10ff23939ca29e2de7b6c3e0a8269a23c9
+Payload = 9c2a0070fbba
+CT = 9ffda883758a670f35869da9821b6ff1fab3e6062ad4
+
+Count = 67
+Adata = 3ee0865f29be50160273b4a94ec078932b9cd10a858e31838d5b607867e1ce69
+Payload = 436179c74fd2
+CT = 40b6d134c1e208f395250fd79087c858b83755411114
+
+Count = 68
+Adata = ec2b8bfe1ccd491b02aa4a9178fd6f099556963e39e2ca5fe6ecb6b5d2a46085
+Payload = ecfa41c614c5
+CT = ef2de9359af5afcbd9af2d584a0f638d066f2496d9be
+
+Count = 69
+Adata = 5b6f6369643d83b1db33d75257d7dea761e574e6e1f1ecead64e5e354a2f4235
+Payload = b48c10105dbc
+CT = b75bb8e3d38c17861882b8930296fd51d969a1e9489e
+
+[Plen = 7]
+
+Key = b930cca30a3fd230c237c8f3cc6792d0c4084dff5c18d775
+Nonce = 7574802fd82fe96c05431acd40
+
+Count = 70
+Adata = 1cf83928b6a9e525fe578c5c0f40c322be71b3092239bff954dd6883738d6d71
+Payload = 2a755e362373ef
+CT = f06238b0450fd1f4b6cab1383adb420c4724aa7bdfefb7
+
+Count = 71
+Adata = bb5450f66273f63b2f79dce177381ce846584ce4f7a0ad5a0171a56e149370bb
+Payload = fab43224bf8989
+CT = 20a354a2d9f5b7a1f99175d3dff5a73f0053a95c36fd8d
+
+Count = 72
+Adata = 3e5e1037bd2922eb20c34200c470b76e537baf7e7f1d8dd2f7a184a593c66554
+Payload = e3aed6715aa429
+CT = 39b9b0f73cd81734b4ad0e41117940abf530093dac648e
+
+Count = 73
+Adata = 3cc88a096a1a440827f5b7da675389e50b5cce35fa2cc36674d6bfc5a3a966b2
+Payload = e78db0f83997cb
+CT = 3d9ad67e5febf5663a8324014550430c7eaeffbd8568f7
+
+Count = 74
+Adata = 2cca33a10b9da7ba99a6b552d1405f2df3fdfd15358d8fdab5e15296b38f9135
+Payload = 726557906845b1
+CT = a87231160e398f34ab635c4eb5b38b86e71da8af3840ae
+
+Count = 75
+Adata = 2fe5dd58b17914187e29029c53cfe5b015ca74cab750d8f95e05f818c3cdf947
+Payload = 043a759b578be4
+CT = de2d131d31f7dabd9961766e03eaa7e8888227c98d1f42
+
+Count = 76
+Adata = 8b8e3d7c88fa16d70130cee290b7e2eecf0ce711118cd9265093b11467e63554
+Payload = f31f2fb4b3fd80
+CT = 29084932d581be637842d96d13c4aab97e296458745a9d
+
+Count = 77
+Adata = 6341370e126097f9721a13c977eb4875cf1286e15c3adfa4e7597e0e13d93b6a
+Payload = 7e3c8224104669
+CT = a42be4a2763a57a51ac46611366c666cab6bfd3d1baaa5
+
+Count = 78
+Adata = 227926b62f7cdd90e4d3b0cb5457e71fb087d329671f0fa891ec06eb8edeb58a
+Payload = 26a0528ae6f9c1
+CT = fcb7340c8085ff8c7d7e5aec14845f844ad38544a2f11d
+
+Count = 79
+Adata = 05b50c40b02e79b74b94d726a7ce8b2b7216ef8af6e7a42d041d2a692a58ad83
+Payload = 61dcf53d1a184e
+CT = bbcb93bb7c6470f1605ab8a2332012b759ccd2eedbed24
+
+[Plen = 8]
+
+Key = 314c136999e41d137bd7ba17201a9fa406025868334e39b3
+Nonce = 65f7a0f4c0f5bba9d26f7e0ddb
+
+Count = 80
+Adata = 5c7ce4819b30b975ae6ce58dcc1bfa29a8b6dda8f4b76c7e23516487745e829c
+Payload = 4d54d8b06b204445
+CT = 2baf90c490b11f9607482362ab3f157c42d0e9c6c5cffcf0
+
+Count = 81
+Adata = 90257ed88679197b8219bc4c2434a71a4e3664d5859c4ffb9a075654898ffedf
+Payload = b2a35df881cd63a2
+CT = d458158c7a5c38715389509b5b6f2df1faf7e8c39203970f
+
+Count = 82
+Adata = dff8ad83525d8235eacdccc91abeb80795e6b5f463fd28af35c46199f646ceb8
+Payload = e98f5e5a20d02c80
+CT = 8f74162edb41775395328747ca544e987df28883d0377b35
+
+Count = 83
+Adata = cde159c5343cd9d98001cd719d3e9ea25e47e1ff13fc87055d4a53b741f59285
+Payload = 90c3e48313cd4fe4
+CT = f638acf7e85c1437a4ba841883a0d7aeda398c043161966f
+
+Count = 84
+Adata = fa88cf5a08be4fb0c1a7960f45726c303eb559861fa60d17aa8dfe8bb5795382
+Payload = 8ad6d5a28ec075e6
+CT = ec2d9dd675512e3509195efe66c5faf413e0f68df8cb647d
+
+Count = 85
+Adata = fe9e93a9370b43efa1560aeb017ff04fca7f207191e6f707c1c35b2e90c44eb2
+Payload = eb83928f0d5f7aa3
+CT = 8d78dafbf6ce2170b51af067ad69ad96009e50ead3d03f02
+
+Count = 86
+Adata = 35792c854fdf1c8cf7f3f8ed2b8ec4f31fe17bf8d4ba49caec03f954bd8bb17a
+Payload = 4cd74ed2fd083011
+CT = 2a2c06a606996bc26b1cb03ee76587f84364825f7c1fcbe9
+
+Count = 87
+Adata = c084108f9c0a74cbf70f614dceae592546865006930db0401828a0eecff98671
+Payload = 52365f94579e0646
+CT = 34cd17e0ac0f5d958fa70c5e195f1f955d64892f532b7683
+
+Count = 88
+Adata = e8045949de61c5c18a63e628330a4d1d12782379a8f9187755409d1825f453c5
+Payload = 8fb85c857a3e38e7
+CT = e94314f181af63342ddf297bdad58083645a052815d29a83
+
+Count = 89
+Adata = 53cfdfd66d63c2924bd583487b90b1dd9ec199f90d660cb9c3a763a4776abfe1
+Payload = 43d2828e86f7856b
+CT = 2529cafa7d66deb81ad3b2be41dbc39df4c0145dcbae3e76
+
+[Plen = 9]
+
+Key = a19f6be062ec0aaf33046bd52734f3336c85d8368bef86ab
+Nonce = 7f2d07f8169c5672b4df7f6cac
+
+Count = 90
+Adata = d68d5f763db6111c5d6324d694cb0236beab877daae8115ecb75d60530777b58
+Payload = 13511ae5ff6c6860a1
+CT = b3859b757802ebd048467fd8e139eb9ee8fcdca45ed87dc1c8
+
+Count = 91
+Adata = f6e219b29884dab9ea9bad34d9ef8a50ae389c9a908de7154a1f2e894f27141f
+Payload = 7e7e33e1a07d4e8fde
+CT = deaab2712713cd3f3789d0ee8323ea2ee7a68aaaa9c49b98df
+
+Count = 92
+Adata = bcca002d69d9d1044c40ae741ea33ce6b8463f5a28d0514e044fdae2fe7d3c3b
+Payload = cc88980c73e6c5f0cd
+CT = 6c5c199cf48846402437c9fe3d9feb0485e6d7c04423b77a53
+
+Count = 93
+Adata = 39cac8f0825ffdb0668455933ad1581263a23b9e5f1305340528f0320d4b1269
+Payload = 34cb528f50d073cfdc
+CT = 941fd31fd7bef07f35b87e90a71ffe6c30bee1771078a701ab
+
+Count = 94
+Adata = 510a02a44d142c8e975d1d933f828fd7e47d28b88223f1698cf009dc3b079be6
+Payload = cbce3df86438a61065
+CT = 6b1abc68e35625a08c9e9c5be0657649448c38692e8d703d30
+
+Count = 95
+Adata = 40e0418cd52f74d78a8e18ed86210e3661a86d8574aedcee540340d8996d9852
+Payload = 80a2b835f8b0729a4b
+CT = 207639a57fdef12aa213e5f2bfd33101597cfae7cf334a8528
+
+Count = 96
+Adata = 1f2938b3bde19e1af91299c08638061dc3c1ea3284c259d415e996477cb37b0e
+Payload = dd04794e65ce34127a
+CT = 7dd0f8dee2a0b7a293516a7310fbd4ceb90d8db9a86cb6311b
+
+Count = 97
+Adata = cbae5b46e35fa2a279dcaa4c724b923805d4707412a84252b64228c91cedd019
+Payload = 00c4101052f54462d5
+CT = a0109180d59bc7d23cef6165af65f3522dfbfed0293db39ecd
+
+Count = 98
+Adata = d0f27c7f42892f3ad4c0029c5b698abb1d035ba5869a665b1de8861db6c055e8
+Payload = d0865445d3b26b6f49
+CT = 7052d5d554dce8dfa00726434c1349e3e874a2d6bf598d05fc
+
+Count = 99
+Adata = ab0f5a829a9319a74d5d5179aa0a410a0fcf52f344a7a896aeb1f7a6c5d398ea
+Payload = 7c7c8580b944ed3fd3
+CT = dca804103e2a6e8f3aab491e60fc97b3cb5248291e4866dcab
+
+[Plen = 10]
+
+Key = de1c8263345081d2dfa9afdf37675971135e178df554a4d8
+Nonce = a301bb82f91a582db01355c388
+
+Count = 100
+Adata = 9ad52c041390d0d4aaf65a4667c3239c95e7eae6178acc23fb4e70a852d483c6
+Payload = f777aba1fa70f94e6de9
+CT = 9d8bff6d2dcde77104ac6aba025abc01416a7ca9f096ab2529cb
+
+Count = 101
+Adata = b49c7e7b47870c1cc339c7c09aaacfd6115fa8a0f04990367eea10cfacb9d23c
+Payload = 349feebfbe58f93ea3c3
+CT = 5e63ba7369e5e701ca864acb200e85a0d4753a8ba226aca72f98
+
+Count = 102
+Adata = e61ca7310172eec16745a73e34516f65844eecd0dbc5566ac5213626b9096ef1
+Payload = 678a40b4c2c7df0e4c9d
+CT = 0d761478157ac13125d87869784e3321183d8c044657a020e9b9
+
+Count = 103
+Adata = 690f5e5d8da6cdb0f492e80449e152ffe88fea9742564d8383c79cef739a7f74
+Payload = 2b81e0533313664bf615
+CT = 417db49fe4ae78749f5070634d00b1facf0e9e9979ca257a71e2
+
+Count = 104
+Adata = 78e34b0a1d61ccd411cbfd306ea2ef3ce89c0b085deb4cfbaec2ab72ce16daa9
+Payload = 1ac63aa38a206d8e7d68
+CT = 703a6e6f5d9d73b1142d994630ed92e2973b22773f229b45bdad
+
+Count = 105
+Adata = 51bacfcf87ea11da34b76acba8c444792ec3db3c8ee6e600d69679975a682a54
+Payload = 027a7fd7897808ec7a56
+CT = 68862b1b5ec516d3131304571b015bb6b4651f1eb9f6fb3a7b74
+
+Count = 106
+Adata = 5159357a133e4743f903d05bd641da369a3675337760fcd2424a99221ba70b78
+Payload = 1086953d352e94a51a6d
+CT = 7a7ac1f1e2938a9a7328bb0e11ac4608081fd0702a137da0aea3
+
+Count = 107
+Adata = f567820865340314d46a17f520ff315efb6b33bdeda590ca9c4fad604c2d8e8d
+Payload = b8b148aafec4a035e9a7
+CT = d24d1c662979be0a80e252c9ec1317ce30dffeb4c9bf3fd0bbdd
+
+Count = 108
+Adata = 0cfec933831644b468724e808bb3d25fe8f15850ce513fc341da46089c845208
+Payload = 884242a87779d3921f8e
+CT = e2be1664a0c4cdad76cb691e32be3cdd9721a13aabad26dba58c
+
+Count = 109
+Adata = 8edc2b85d44297ac66bdd90d05d8df38124033d6a583bb8dda18a2246ba096e8
+Payload = 25c32770a299020d8500
+CT = 4f3f73bc75241c32ec45333a381be77800654aac335bf9220ac9
+
+[Plen = 11]
+
+Key = 248d36bd15f58e47fcf1c948272355821f8492e6e69f3661
+Nonce = 9e8d492c304cf6ad59102bca0e
+
+Count = 110
+Adata = 9ec08c7ed6b70823d819e9ab019e9929249f966fdb2069311a0ddc680ac468f5
+Payload = 33709d9c7906e2f82dd9e2
+CT = 9114d36b79b1918b2720f40cddce66df9b4802f737bea4bd8f5378
+
+Count = 111
+Adata = ba13974d95f2eeb367b63850609c53dc66c2710f682f10bef0142d48f851b430
+Payload = 84172985e7d194ba28a87c
+CT = 26736772e766e7c922516a12c94615be2bd81bd598f3022f5775a4
+
+Count = 112
+Adata = 5f16180bfac9b7483774cb0e1d57a43e9bf3cf03bf6fe758293aadcbbef25b80
+Payload = 9a34d32070c71d7de8f512
+CT = 38509dd770706e0ee20c042758e936750e335702542bc598e211c4
+
+Count = 113
+Adata = 4352057bdd1735a85dc0fc4dbeedc73279c27eb24a97641236f03f11cdafb8c0
+Payload = 2054a268b1f6fae4f15d91
+CT = 8230ec9fb1418997fba4870762bb2a7d04ba2ad251d595d0619dc4
+
+Count = 114
+Adata = ddf118ae403b2509e75eb7a26d17e73e527acbacfbe49a56fa3210169030144b
+Payload = f71afe9a60f08a0ef694aa
+CT = 557eb06d6047f97dfc6dbc27d85594da3fd35bd8498d7e389ee7cd
+
+Count = 115
+Adata = 973904409e8154132439926f0dc45c0d81bbbd5793f7f81e20eb818bfa374d58
+Payload = cdf5b47ff73306aa55c496
+CT = 6f91fa88f78475d95f3d80055936db383a8ad10b152046d721d3f7
+
+Count = 116
+Adata = 06bca7ef6f91355d19f90bf25590a44a24e5a782f92bc693c031e6de1e948008
+Payload = 9ebf93643854ea5c97a4f3
+CT = 3cdbdd9338e3992f9d5de5d57e228369e24fe955fd8924526af6e5
+
+Count = 117
+Adata = 8321f65baf9dc856ac1c24f3fee5c74d697eb0b50470d59d8f4a14b506e86c53
+Payload = 685116faa5cc527ac8bfa1
+CT = ca35580da57b2109c246b76c23abfb3b4eb39deb8da2064390dfa8
+
+Count = 118
+Adata = a4e7738038a5116592bb9d92d6d4ed191ab774310f6409e4e45fe907674c006f
+Payload = 9e8c4f1292e8d7e5179b34
+CT = 3ce801e5925fa4961d6222b4272c0639e8e6a1d356fb4fea86762c
+
+Count = 119
+Adata = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005adfe9faab253b572
+Payload = 3ecc2ba566c723462eb0ea
+CT = 9ca86552667050352449fc0633a0f9cdc9490231ec2dd69f6e35db
+
+[Plen = 12]
+
+Key = 77a67fb504b961028633321111aac2c30eb6d71a8cf72056
+Nonce = acadc0330194906f8c75ac287f
+
+Count = 120
+Adata = 8c18486d52571f70f2ba6a747aaa3d4b3ebc2e481ee1b70907dddb94bdfa0ca6
+Payload = 10554c062d269ff6dcd98493
+CT = 7f8b0cad79b545e5addf0b04ff4b0f2b2a5067283210aba8630d0306
+
+Count = 121
+Adata = 4e0b4771c7f6c66f9577c430611fdeec5702296ee3691b6bb8c6a81217edabe4
+Payload = 1c9e7875cf02129ac52daeb0
+CT = 734038de9b91c889b42b21275b16dbdf0b9be3c8c82ac652992d630d
+
+Count = 122
+Adata = 4a687e1d0a95ed2efb95b4c6b040999fcd35136811cd665f934d10224b6064c2
+Payload = 34575694dde459d195b7357a
+CT = 5b89163f897783c2e4b1baede629274d654ef5a4480e24f6bef3bc8c
+
+Count = 123
+Adata = b5330a8447d74a7987fb718cfae246b5c7e057991064eeaf823641a12bfce9f5
+Payload = ab20c8e8aab1aac1e4f64206
+CT = c4fe8843fe2270d295f0cd9142ab5407a08b648ce24e9955e28fe47e
+
+Count = 124
+Adata = 4f19bbc3135d7a216465b4c1df2616e8bfc3cc64af0bf52bdc42543f4d2448d4
+Payload = e556ca05bcd1991d2c9836a9
+CT = 8a888aaee842430e5d9eb93e151e94d311c7cd2c1b9048575076ceac
+
+Count = 125
+Adata = b6ffc7387b19786282bda7caad52eb37fbe7e557afcb80faaf57767e2a0f178a
+Payload = e5b665600a2aa413e117c538
+CT = 8a6825cb5eb97e0090114aaf61b71330d72506050368186a5619f180
+
+Count = 126
+Adata = 6a493c5ef3769ccc4101dbb2eb36e1e5bbc577a057ce0731203ba3f25b52497b
+Payload = 870864a611aa0475d120bc40
+CT = e8d6240d4539de66a02633d7ea21e36f99e5aab6ffa85994d13d5bb0
+
+Count = 127
+Adata = 8215753d9efc51325f182199e39f9082cc3fe524400f2a7434c68df7eb2b06d4
+Payload = 71afe8d00c6f2ea8c8b050d4
+CT = 1e71a87b58fcf4bbb9b6df437cc93a50dea11c5e0b19f14b9c8f16bd
+
+Count = 128
+Adata = eb8f198da6ee92a03913c6575343f6c749d2377a09430eb751b13c041e6edbea
+Payload = 7021f18b8f398a5999fcdcd1
+CT = 1fffb120dbaa504ae8fa534699cbfd1beafa2d2942f6812b8dfc88e6
+
+Count = 129
+Adata = de2ee30359e390db72f682c2ca0f14b72b60ff9bccd8c6fbd19a512b12add794
+Payload = affca856eb412f0b3276ae6e
+CT = c022e8fdbfd2f518437021f9337405235dce6161441caa25cc6007c6
+
+[Plen = 13]
+
+Key = 0d423519e4110c06063061323f8c7c95387776b6ee4e4b6e
+Nonce = 39abe53826d9b8e300fe747533
+
+Count = 130
+Adata = cdd9bf1b4f865e922c678ec4947ea0cb02e78bd5c1538f33aeb818ad3f47e519
+Payload = 4021ff104ff1dbd91e46db249f
+CT = 7953d3cd66d093785d123f65ba37f16761dd6aedbfc789ad96edf1490d
+
+Count = 131
+Adata = 342de5fe61e05c2e58ac2978a871fbdf186a7294ec5f85c4631c21b584231211
+Payload = 95050ca1d494bdb561d4840f8a
+CT = ac77207cfdb5f5142280604eaf8f8e855ae975a1fc64bcce3e7492e9d6
+
+Count = 132
+Adata = 7871482948d8d09d0a7491d915543082cb5fc7d6c1e82ee2218279f54c15c154
+Payload = c45823203b20821a48502f9c67
+CT = fd2a0ffd1201cabb0b04cbdd42017a6515156691b3161b747576078da4
+
+Count = 133
+Adata = 65781d018f27ca0c72a9fa9ab4648ed369646dd3ce45d7ad3a54f6b051f1b6e9
+Payload = e901661b7d47c9918244ee1077
+CT = d0734ac654668130c1100a515225cec7d2566a07cd78181ae94577befe
+
+Count = 134
+Adata = 05556b04dae5cde8525633d1862aa200c54af534e302d2cbd34ddc2b78532a60
+Payload = 5556f799d6a6cffb343f28c1a9
+CT = 6c24db44ff87875a776bcc808c133f51dac00f973fd42e0948fab70ea9
+
+Count = 135
+Adata = 151304e3e4f3c2d4d3227e035d849e0d3841ba00cf6cab1cf2e3e4d6cc760623
+Payload = 56bf26be81c7b55ef898e23981
+CT = 6fcd0a63a8e6fdffbbcc0678a4fe78bdeaa8d408ffe8fe64811aa87742
+
+Count = 136
+Adata = f870cc1fe67d6169279f905b0fe5fd9a0436c36498e4b7c6f584f00f7efe8784
+Payload = 36b304a72dbf4acfffa1d7d624
+CT = 0fc1287a049e026ebcf533970197228d155dda2bc814ff33ebeb9a7ffd
+
+Count = 137
+Adata = 5692c9d452ea1c067e62fdc554ddd2b18c8433d59067f971316797fd9853ae6a
+Payload = fb529eb5ae79a0830474ffbc98
+CT = c220b2688758e82247201bfdbde7ba03e144e34a4ab34791a372a2b8ab
+
+Count = 138
+Adata = dcf7fe16b7ca9e27ec3291103398eaa2e77c7b770b67f8858c215af4c523822d
+Payload = 6218c778955d9a56360f06c704
+CT = 5b6aeba5bc7cd2f7755be2862103c2eb5ef0657306d12b753a0694efcc
+
+Count = 139
+Adata = b0f1e2668611dca86e8d0f58c2a4cf4a9472d81ba013e271800b75841fe5ffde
+Payload = bf6b143fb713a81c965c5a9d8d
+CT = 861938e29e32e0bdd508bedca87cc6119151393461ecf65bfe06e0163b
+
+[Plen = 14]
+
+Key = a60cf7ceb62bf3118532bc61daa25ce946991047f951b536
+Nonce = 7499494faa44a7576f9ed5580d
+
+Count = 140
+Adata = baa482c64eefd09118549a8968f44cfea7a436913a428e30aa4ab44802a4ba35
+Payload = d64f9426febce6a84c954dd5ded5
+CT = f7580f17266d68237747bf57c7ed8242ac1a1979c5a9e7bc67d7698c7efa
+
+Count = 141
+Adata = 2ad8ecc5ac9437ace079419f17e6018625b10490120fbe2f12b41e64b73b653c
+Payload = fcd9b67717bcadeceddea336c671
+CT = ddce2d46cf6d2367d60c51b4df4918abced491c063d8bfd0e7341febddc3
+
+Count = 142
+Adata = 7585ee95e74d7a869bdc0b59ca9939dd57e7b09afab179079d467bfe0668416c
+Payload = 18232d7c792fb80e6ca1c8f2c3cc
+CT = 3934b64da1fe368557733a70daf4659ecbb3dbfbcdb0f913abedf8afab05
+
+Count = 143
+Adata = 41be6ca6188f34da1ce83fb8c27652848dc2a71e32bd3631fb9b33ae69e5d879
+Payload = 764dbefb42644d18d23e5e456868
+CT = 575a25ca9ab5c393e9ecacc77150a220d5ec0b5397d6b4e323b5dc7d1b63
+
+Count = 144
+Adata = 197cee3b15320d57996191dd13106fbd4546a5cc3d2bcf0c886af52ea3d9a855
+Payload = 8003586af34bdd0acae4f5547394
+CT = a114c35b2b9a5381f13607d66aac3a5f713f5d0793b732c6e114805cc9b3
+
+Count = 145
+Adata = ee0b647a47656a6e9e09c2d64f734a2cc3fd45b7ee52fea51c24af59ee22a006
+Payload = da143266516a4145cde92c93f961
+CT = fb03a95789bbcfcef63bde11e059ed90e8650bc16f590789dcc625b9e63d
+
+Count = 146
+Adata = 9f5bfffa01f1425d95465723735b49fc1dffbad06cf37a00ca4b59efa21739c1
+Payload = 3842b033f3ca31a6f8e5a638b39e
+CT = 19552b022b1bbf2dc33754baaaa6bda183dda1aef021d92210e27cdd7c5e
+
+Count = 147
+Adata = 64e92ba2748d07f602808f7c5ded15cb0e43140400d37107e59a01e7d45b4c9c
+Payload = cedf60b17185fc71b957cb759260
+CT = efc8fb80a95472fa828539f78b585e4087fb314f893937e95383e66745c0
+
+Count = 148
+Adata = 6ebcaeb4bd44ff4c990305ac64264dfe2ada5f7cd4b294eb9f492865cd28905c
+Payload = 035f449bb28f43365f4a0556096a
+CT = 2248dfaa6a5ecdbd6498f7d410520a71ce5813c578532b742d704fa92276
+
+Count = 149
+Adata = db617207dccd1f6baea5f2242d5e577adb8d69af3bb1707a7a53a8b75452455c
+Payload = 9a2a45424f4965a71270e77cc403
+CT = bb3dde739798eb2c29a215fedd3bb7fc45d15d6939668065d2282fc589c7
+
+[Plen = 15]
+
+Key = 82d4bc9aac298b09112073277205e1bf42176d1e6339b76c
+Nonce = 70325ef19e581b743095cd5eb1
+
+Count = 150
+Adata = 6d14bb2635c5d0ae83687f1824279cf141173527e1b32d1baf8a27f7fe34a542
+Payload = 25a53fd3e476dc0860eeeea25fcb0c
+CT = 4a1cfd0023557a184b929965b0a445cb3993ca35acf354cb2b4254ff672e7f
+
+Count = 151
+Adata = 9f8a56fecf32fa7d50f033b2524c3d798e254bc87245cce57e38edd6ee5d5f1a
+Payload = 797dca47597947c057789433309b67
+CT = 16c408949e5ae1d07c04e3f4dff42ea25b5eb103bac224cad66ec0f100875c
+
+Count = 152
+Adata = 86f15b8b677b7655f358a2c7fd5785bc84d31e079ed859b6af88e198debd36fc
+Payload = e61f9a663d3a2b50ea2f9475971270
+CT = 89a658b5fa198d40c153e3b2787d39b598cc6ec2295c586e7ae270a01846d1
+
+Count = 153
+Adata = 4de6bd43c28143ea5d40919cb5330a7e674f5bd8aeb7b178343a2851281c8668
+Payload = df990c42a268950677c433555319b3
+CT = b020ce91654b33165cb84492bc76fa97ff732093f7d0a96b30d8cdfd1bd583
+
+Count = 154
+Adata = a5c3a480dea1b2a1e3a0ce416148b04f60104217c9d24a5b267b4aa6aa07a4dd
+Payload = a7e72fb4bec3768594a2f6f5b4379e
+CT = c85eed6779e0d095bfde81325b58d7ad98e32a9156e125ff021ef6951b0c40
+
+Count = 155
+Adata = 51b041f1666c59045d333fe63d43457107e1adad34fcbf965e0d191f3e414776
+Payload = d3d1550047cf90eceaea7000d8e280
+CT = bc6897d380ec36fcc19607c7378dc9390f10df08a84c21031626861b201fbd
+
+Count = 156
+Adata = 22f8a3c9d85b2d53ffd92078d3c94373f855ecd01a8ac521d1abd0f2c7cba9ff
+Payload = 756412c4ee6416f2f4e0342011cde2
+CT = 1addd0172947b0e2df9c43e7fea2abdd5d840bb8c4348a9a548482e6b93043
+
+Count = 157
+Adata = da08b14e1b770b81faaf1e59851df1cba8838cd63bef141340ee378e65fdcbd4
+Payload = 666e4a4b3f6cf598aa763cdada4109
+CT = 09d78898f84f5388810a4b1d352e403f0d49927cd6103e3705ba201e8f73c6
+
+Count = 158
+Adata = 2db3ded385ef9c82fd39ea5782d9befe66e8a070066269b2aa7c4bbfac3711c3
+Payload = eb9013a74352b0677a88bd73052477
+CT = 8429d1748471167751f4cab4ea4b3e2d97f7c2b3b42bf570cce79bf30ccc50
+
+Count = 159
+Adata = 194c9e1eaa8e376f9c41bf33823efa28ee60a9213438665b7002cf0fcad7e644
+Payload = e3126400e3c571a4d39b37bc938a22
+CT = 8caba6d324e6d7b4f8e7407b7ce56bd3c2a4fc45d014a0c54edab2930a5bdc
+
+[Plen = 16]
+
+Key = 6873f1c6c30975aff6f08470264321130a6e5984ade324e9
+Nonce = 7c4d2f7cec04361f187f0726d5
+
+Count = 160
+Adata = 77743b5d83a00d2c8d5f7e10781531b496e09f3bc9295d7ae9799e64668ef8c5
+Payload = 5051a0b0b6766cd6ea29a672769d40fe
+CT = 0ce5ac8d6b256fb7580bf6acc76426af40bce58fd4cd6548df90a0337c842004
+
+Count = 161
+Adata = e883dd42e9ddf7bc64f460ba019c28597587d06e57c3b7242f84d5e7d124ab81
+Payload = b31dfa833b0cda20eaa84d2ecd18f49a
+CT = efa9f6bee65fd941588a1df07ce192cb8707b1a4d9ce3def33703e19eaab6dda
+
+Count = 162
+Adata = 409401eb49cd96b1aad2525c5124c509766ff86f88b2011c67a1d501d3485e31
+Payload = 24bc8dc1e2354667b79ba4d7061448ff
+CT = 780881fc3f66450605b9f409b7ed2eaefd9041ddce37d88e79fba28e385b2327
+
+Count = 163
+Adata = 83bf5c063bf1febf71688a832d615e09d6f14badedeaeb6ffbfe343fc7274e78
+Payload = d41d95a1d2326e12cba636910ddfca53
+CT = 88a9999c0f616d737984664fbc26ac0291d971893543868bd8c69078fc2bdb24
+
+Count = 164
+Adata = 8cdd70524e24318c64d681aa27752d4c86c5348c05c9e48f06ed41594785a6e6
+Payload = e8a4b80e081919f1912542d3136764f2
+CT = b410b433d54a1a902307120da29e02a3866b23e4c991f4007e56a1ee9265c6cf
+
+Count = 165
+Adata = 615985f63571c0f94ffcd4df77326abd41e84f388f061d97573a181da7ee5695
+Payload = 7fca7388058d6d1438b6eee0292131cb
+CT = 237e7fb5d8de6e758a94be3e98d8579a2abbea637996b954027efa9464ced6b9
+
+Count = 166
+Adata = 17aa90f2bff0419011b01dee62be31354431cbc89f22332704b096143d4743f4
+Payload = aa540554ee80dbffa475f702d862d6b6
+CT = f6e0096933d3d89e1657a7dc699bb0e757bc8d48d82ebefc76f17323c518ecc2
+
+Count = 167
+Adata = 85288b2be612e42335c144fb058a7dcd567c382fbcee3962bd5be4cc7a7000a8
+Payload = 6d745581831edba437e70ea89cad217d
+CT = 31c059bc5e4dd8c585c55e762d54472c65470c81e487a26cdc26830f2b51bd1c
+
+Count = 168
+Adata = 288f9f52824b54b608dd7226a0a89d43ae8c05107dbae761e1c756911a003b74
+Payload = 811a61869c7a6b2aa9ac0fcc523ef784
+CT = ddae6dbb4129684b1b8e5f12e3c791d5a3043722be9448c3ef144f2288066f75
+
+Count = 169
+Adata = 51dbaba180d4746edbb3420461919b5b735797bf7dd19f84d80475f5efc2748d
+Payload = 378a4e39817f308ed1e639f943b694c4
+CT = 6b3e42045c2c33ef63c46927f24ff29549aba95e04e11cf18ddf73773d395c1a
+
+[Plen = 17]
+
+Key = 3cf8da27d5be1af024158985f725fd7a6242cbe0041f2c17
+Nonce = 07f77f114d7264a122a7e9db4f
+
+Count = 170
+Adata = 30457e99616f0247f1339b101974ea231904d0ef7bd0d5ee9b57c6c16761a282
+Payload = f6dd2c64bf597e63263ccae1c54e0805fe
+CT = ce3031c3a70600e9340b2ddfe56aa72cffdc5e53e68c51ee55b276eb3f85d2cf63
+
+Count = 171
+Adata = 42370f115bbd4b31bb99fe82cca273b3c93072f96b2e09bdc6718d926d48db69
+Payload = f45fee3e086c28a7c590ec0cc05b972664
+CT = ccb2f3991033562dd7a70b32e07f380f65c6328a7476db2c10ec7bca3f6bd3df42
+
+Count = 172
+Adata = e2d692c5678124998a7862b8e87276b0a19e293a609103c99583b36305bcb2b0
+Payload = 4ad69a8ab433ed8909825c71f6081f64a7
+CT = 723b872dac6c93031bb5bb4fd62cb04da68080f0d51d3b8841683eff361984f7e4
+
+Count = 173
+Adata = b5b38791160959dd2836ec1ad25286c1ba410d7212347a95b5738a3d725bb651
+Payload = 3d47071c13f994cb42fb2887e5c6e53a54
+CT = 05aa1abb0ba6ea4150cccfb9c5e24a1355c1428ef5d40bc9e363817f219af2ed56
+
+Count = 174
+Adata = 02691171795a77d1e3bdad513b6fab5b50d1def81bcc1df15012de3433a6aa78
+Payload = e8a4b80e081919f1912542d3136764f264
+CT = d049a5a91046677b8312a5ed3343cbdb65fdfb37dfd1236198035c8461b304152b
+
+Count = 175
+Adata = 7371d8ae79e628f53ffede174eb068db2318c05e2f6d94ad2233a59369b16db0
+Payload = 549aa84bb182312dd016e3107f3b1f9c5b
+CT = 6c77b5eca9dd4fa7c221042e5f1fb0b55acefde0e84a3ce0cb702ceb73ca1dd9a5
+
+Count = 176
+Adata = bb1e1f51082e470f7245458ec902098e1e41d0ed28efa31be71d21ce86527ff7
+Payload = 31a12ca6d69db2e6e252474d7d59ed6552
+CT = 094c3101cec2cc6cf065a0735d7d424c53f8441d46dc5456a587b765e1a820c11c
+
+Count = 177
+Adata = 7584f57b49e95bbf5a67153e18b9b8c4722644e8f611613c39cbe8c679aba5b4
+Payload = 5bb121e70452a954f420a56aca8cd5c059
+CT = 635c3c401c0dd7dee6174254eaa87ae958d0daddcfcc92349ef059149c54a25cd0
+
+Count = 178
+Adata = 505687182c06e6f4effe7fe03c1f436199a9015380ff21d0b2aa9453cfa10b1d
+Payload = 5b80d1cf745b14cb71cbc8dfe0bc7c7358
+CT = 636dcc686c046a4163fc2fe1c098d35a5948c1242b89490c6ee69dedc1e91286ee
+
+Count = 179
+Adata = 7ebb051741145a3bad87131553375c6debcbcecee9b79ee451bd1429cbb33fc1
+Payload = 79ac204a26b9fee1132370c20f8c5bcada
+CT = 41413ded3ee6806b011497fc2fa8f4e3dba2ddd54e509bca0a45dcf2fd514e1496
+
+[Plen = 18]
+
+Key = b46a3a24c66eb846ca6413c001153dc6998970c12e7acd5a
+Nonce = b79c33c96a0a90030694163e2a
+
+Count = 180
+Adata = ea9405d6a46cac9783a7b48ac2e25cc9a3a519c4658b2a8770a37240d41587fb
+Payload = 56d18d3e2e496440d0a5c9e1bcb464faf5bc
+CT = 01baba2e0d5b49d600d03a7ed84ee878926c0ca478f40a6fbde01f584d938a1c91bf
+
+Count = 181
+Adata = 72340d595f3dbd23b46513f8f2b73b6249328c705e7968084bcb647fe734a967
+Payload = 7a76eac44486afdb112fc4aab939e4d1eedb
+CT = 2d1dddd46794824dc15a3735ddc36853890be4646492b6f4cb169383c075756073b6
+
+Count = 182
+Adata = d5c87c649579da3f632ba95cb0a07c924095e4bdd4e0376e06bb90e07460172e
+Payload = 48348c5ec996f7a97ef0ba2cd6885572fe64
+CT = 1f5fbb4eea84da3fae8549b3b272d9f099b4f584289f560cbf76606942fe1a92dd63
+
+Count = 183
+Adata = ffa6277395d31d5db13034d362228a87610e441c98ca3038e252a9db12bdbcef
+Payload = d5c58f10e1a03d8a2501d1eaf5fcdfff3ae5
+CT = 82aeb800c2b2101cf57422759106537d5d355964f5f5532d7cddd7207f0e9a6aace9
+
+Count = 184
+Adata = daf83d02a9bd992ea58c23e7ad18d41796314bae20e864e729f40ccc215454fc
+Payload = da2a863ab1c58ddde320ecadeecac9c5d2d8
+CT = 8d41b12a92d7a04b33551f328a304547b50890ae047e35aecfc38ffdc07e7d8f5705
+
+Count = 185
+Adata = 21ddad5f550044dc5cb123ade17eeef549c4e0173b216bcc602c1e736764cca8
+Payload = 4573969afa831c244817230406fe51183091
+CT = 1218a18ad99131b29862d09b6204dd9a5741b2bdf539ceaa35015712dd15265ca476
+
+Count = 186
+Adata = 9228265ae5c3daf1485ff8011738da508bf2a73731396c5d9aa56fc554e0c00b
+Payload = edf5557e15473b747a819398c9ac1459ffdb
+CT = ba9e626e365516e2aaf46007ad5698db980b241412124ae20b84c13b0c3671d305c9
+
+Count = 187
+Adata = c0a2ff0de21b3ba961e06015ccd71374856a65a4c57cf8cde0a1643aca8ed868
+Payload = e139263478900df806a0f3446bd6600c1aeb
+CT = b65211245b82206ed6d500db0f2cec8e7d3bee9803747bf9fa63412bfc4e10aea89e
+
+Count = 188
+Adata = b54378f031a31cf3985f573829c9ffca14616742e0a7e03b0a2d7f05eff0219e
+Payload = 660eaff0f113eaa2f5f7ad4b62bb849a3a25
+CT = 316598e0d201c73425825ed4064108185df55afdf430b57845dcf622d4f25cdeb2a3
+
+Count = 189
+Adata = e67f35c18a9336469eae23040f98f52338ca8d0cab269ac32fe6bc7605d3ea56
+Payload = 0f89897271f5d0349d57399005ea60c0cadc
+CT = 58e2be6252e7fda24d22ca0f6110ec42ad0c7ed4c04c4b4dd585891ecfddeab8cc87
+
+[Plen = 19]
+
+Key = 7b71045ccef735bd0c5bea3cf3b7e16e58d9c62061a204e0
+Nonce = 2b9ecfd179242c295fe6c6fa55
+
+Count = 190
+Adata = b89166f97deb9cc7fdeb63639eeafb145895b307749ec1a293b27115f3aa8232
+Payload = 890d05420d57e3b3d8dbef117fe60c3fa6a095
+CT = f842ff6662684de8785af275fa2d82d587de0687ebe35e883cbd53b82f2a4624c03894
+
+Count = 191
+Adata = 4392c3043287dd096b43b4a37ea7f5dc1d298b0623ccbf4fd650a49569a5b27b
+Payload = 6b425cdcdf8304e7fbb70b2973d55e6940025b
+CT = 1a0da6f8b0bcaabc5b36164df61ed083617cc807d4824f0a98db2d87365a42ca3b80e1
+
+Count = 192
+Adata = 9b4fc98fcdcf485205e7054bc9d1e02d0d8584420537e20d3821de2fd6824787
+Payload = c8bf145fcffbafd6cd1a4c5b6cedfe008aacb2
+CT = b9f0ee7ba0c4018d6d9b513fe92670eaabd221404e631735c544edeeb4c0105c55bf0b
+
+Count = 193
+Adata = 45622e1472542be2f63f463d253617eafd4f2ad609f9020884905dd5c22fba53
+Payload = 12b5a76faedf6f855e328c2cb87be8aea78c5e
+CT = 63fa5d4bc1e0c1defeb391483db0664486f2cdc16a4cf37e8e96eed1217d21133e83d1
+
+Count = 194
+Adata = 958689aea3c6cd19020eff9d635ef44ee0793424df38fdf13a238b969d429777
+Payload = f0927c3cb0a876d7877466507da8bfa0bd9a16
+CT = 81dd8618df97d88c27f57b34f863314a9ce4859facf81a636351f6e67d6ec12636ae0b
+
+Count = 195
+Adata = c22911efc36fa739048af0c951ef2449bb3605c52f65120c4d71fe5976026032
+Payload = d2c5d4e2362f19c99de66da7bd9c495c03d9a1
+CT = a38a2ec65910b7923d6770c33857c7b622a7327ce73a7e2db69d30441f89a03fd0e84e
+
+Count = 196
+Adata = 799da61e2c10ebb4783f618b8f69da7704a1b2b925cebc228af57d7ceebb9825
+Payload = 1c9d7f5b329ef4d384b8b7955a20f8a3fc15cd
+CT = 6dd2857f5da15a882439aaf1dfeb7649dd6b5e8d787a9d06b8533ca96fb1db8aecc8e5
+
+Count = 197
+Adata = 14a8e18afe0b9fe18ddfd754219a7e18ed36f419f8262d91678e10daffb31c81
+Payload = 3a64414c3588d7c26871d7d054ac6c8420d491
+CT = 4b2bbb685ab77999c8f0cab4d167e26e01aa028ff5f819d552c08054b5ac02063e102a
+
+Count = 198
+Adata = 7294a8b4ad97c81969e4a2876a3dc0ee322d554726997dc9ed98c5601985ee5b
+Payload = 545dd71bea9967e07a89f84a2027aacd132187
+CT = 25122d3f85a6c9bbda08e52ea5ec2427325f141cde5af8fada67c47cbb5787a6b2d9c9
+
+Count = 199
+Adata = 99294b22d73805805630fb416d20d4fca67419ab660ff45cd19a3729e81b9f69
+Payload = ec1b17b885c018272652453f47fa6e9ed972b9
+CT = 9d54ed9ceaffb67c86d3585bc231e074f80c2a7412640b179bd3e8a417dc38462c16e8
+
+[Plen = 20]
+
+Key = dc7c67715f2709e150cceff020aaacf88a1e7568191acbcf
+Nonce = da56ea046990c70fa216e5e6c4
+
+Count = 200
+Adata = f799818d91be7bab555a2e39f1f45810a94d07179f94fe1151d95ab963c47611
+Payload = f383bd3e6270876b74abbb5d35e7d4f11d83412c
+CT = 377b5df263c5c74f63603692cbb61ea37b6d686c743f71e15490ca41d245768988719ede
+
+Count = 201
+Adata = 69adcae8a1e9a3f2fe9e62591f7b4c5b19d3b50e769521f67e7ea8d7b58d9fc8
+Payload = 615d724ae94a5daf8d27ad5132d507504898f61e
+CT = a5a59286e8ff1d8b9aec209ecc84cd022e76df5ea9bc8cfaf2a1734a792076618c4b9690
+
+Count = 202
+Adata = 4586f73a1f162b2cdb65f6e798a60b5f48938d40b4612d84c1f39244f14efdce
+Payload = 6e923e1f404002aa5cf8f8aaf1b9772da425e21c
+CT = aa6aded341f5428e4b3375650fe8bd7fc2cbcb5cc5122df904b052e4d5580fdeddf5297c
+
+Count = 203
+Adata = 9f7ae892e5662803408d4d062265846441a43c1fa202da59f640ae722a692671
+Payload = 68115771505daa18bb3ce90054bfb7d077e1f37c
+CT = ace9b7bd51e8ea3cacf764cfaaee7d82110fda3ce0ba1bb1af18e15ade3316c21d6b41fb
+
+Count = 204
+Adata = 1f0769a7ae82bd985661e031c4a892c15d3ef37bdcfb45243d02f40fdb51d34b
+Payload = 681fd2a324b3fea4cfebed567ae4546ba373c8f1
+CT = ace7326f2506be80d820609984b59e39c59de1b1dc71e342fbc44289ef7e53e28edf3839
+
+Count = 205
+Adata = bf957ef5ab2805e58ea752da5793f7f23d98fce1b2b67738929e5de8a15f9801
+Payload = a7b9d2d069941e8b943706a02d2847ea713bb103
+CT = 6341321c68215eaf83fc8b6fd3798db817d59843ced1fb4a2a3e349aa590aabbfc3d13bc
+
+Count = 206
+Adata = 833264c1bebb597043b4158087cb651960915d9023189c9509c0d2aed84e7fe4
+Payload = 9b946e8198ce69d2173e970f4e0c103a47ee4160
+CT = 5f6c8e4d997b29f600f51ac0b05dda68210068205079f6c2739e2b789b6e3d3c60389374
+
+Count = 207
+Adata = 94c8414cbbec52e2d73bb8f02ef687c91432495c0c744666317d02e6d46706d2
+Payload = 81ac4618f3db6bcf9bbf67220b7671be4bb4f8a2
+CT = 4554a6d4f26e2beb8c74eaedf527bbec2d5ad1e22a02f287db7217148317d897f65f6a0c
+
+Count = 208
+Adata = fced1131dab3dabdc1a16d3409fa09a90ffe02f0e2c814a63f77f771c08c3389
+Payload = 90851933d4d3257137984cdb9cba2ca737322dac
+CT = 547df9ffd56665552053c11462ebe6f551dc04ec362df9f8b41b1dd4821f8f14e9e633d7
+
+Count = 209
+Adata = 495dfcf91f4735ab35c6bc4deef8468bd988e4099cd291a32b4707f93e13d82b
+Payload = c14ce6d57f0fe7367331c9fe159ae1fb8f1ccb2c
+CT = 05b406197ebaa71264fa4431ebcb2ba9e9f2e26cf61ffb51e56497ca9f39c6665fcbdfa8
+
+[Plen = 21]
+
+Key = f41e369a1599627e76983e9a4fc2e963dab4960b09ebe390
+Nonce = 68ef8285b90f28bcd3cb1bacea
+
+Count = 210
+Adata = dbe3e82e49624d968f5463ceb8af189fb3ad8b3b4122142b110d848a286dae71
+Payload = 81ad3f386bedcbf656ff535c63580d1f87e3c72326
+CT = 9f6028153e06d14d30b862a99a35413413c04a49dc6f68a03a11cf00d58f062a7b36465d13
+
+Count = 211
+Adata = d9acfd611e5bbb08c5d05d56791b8aebabf8d69734ec89153c91a1f65b2e1adb
+Payload = 35f6bb3f6a388f3a5a039b0a495b676d0b928aeb19
+CT = 2b3bac123fd395813c44aaffb0362b469fb10781e3ca1fb470b666523a19f83481f16481ed
+
+Count = 212
+Adata = 6003b771afe4e99e1ef1ed4a31b10540d95f4ac49885f0c8e5cdcb63d213127e
+Payload = 6aa7e3802b5a29d4f9ca88eb59f94af783d1054466
+CT = 746af4ad7eb1336f9f8db91ea09406dc17f2882e9c53cb05bfcd64da2b45c2e9a89a380b49
+
+Count = 213
+Adata = c371644275a6290821e7d308714bec2bf62d36c30f7fa77a0d60b28894f1c82a
+Payload = 13332b67ba5ba18137c306bd860dc3eb0a9a0b871a
+CT = 0dfe3c4aefb0bb3a518437487f608fc09eb986ede048f70fbc680cf7092b3dd90b943fc6e5
+
+Count = 214
+Adata = 8eceb15300ec4220510ed5b7deb3429de6ae5f618e1c222c28990a9ab4b4bac8
+Payload = 05981dc26a1db2d8e2c3d85ea9a4d1dc3432d9edc4
+CT = 1b550aef3ff6a8638484e9ab50c99df7a01154873ee386f33c0b8da8d0c5934e617dd618e5
+
+Count = 215
+Adata = 96d1cf3690c48c77a155ce13e67bbd62e6f03d88c893c1f7c30a6435d5ab36e0
+Payload = 60249343a8cd4d33c6edc583ea7e5c221ef3064787
+CT = 7ee9846efd265788a0aaf476131310098ad08b2d7d3d2db1360fb1121893f4d197731bce4f
+
+Count = 216
+Adata = 379bbc9f919dc2a8687f2a86cc9c3291804240a9b566c58519956848102e6155
+Payload = 79003a8d3d20d412f468f11712cec4d37cee847440
+CT = 67cd2da068cbcea9922fc0e2eba388f8e8cd091eba335ce1bfafc0948f2523e75f2aad86f9
+
+Count = 217
+Adata = 9bff9c9a8f94cd77e7016748da31f86d1b9c68465cbf954511c93a4776981524
+Payload = 7d078a8b200514a00628756250d410f7a0f8a769e6
+CT = 63ca9da675ee0e1b606f4497a9b95cdc34db2a031c7dc265e281307f0f4c38cddc556ac725
+
+Count = 218
+Adata = 25125a4668c31dc2e8a68b6c4c95ad7cf9322852e371b415a357d09acb01b587
+Payload = d9b0eaaff786165f882f41a98dbc0c355b3a1aaf40
+CT = c77dfd82a26d0ce4ee68705c74d1401ecf1997c5ba61c78a2f85a447c3e62b6197d65b9065
+
+Count = 219
+Adata = ad34d8f0902a5b79fb145b8206bb4d3b77e0bd8ae2d0964815389eacb33b4007
+Payload = 17b517ef577f588da374340d2522cc9ea642c8d8ae
+CT = 097800c202944236c53305f8dc4f80b5326145b2540312d067c08a9b4400e1df8bb7ed671a
+
+[Plen = 22]
+
+Key = 3289e59e3a7b29bf4a309afc253030bba4b9bdd64f0722f9
+Nonce = 30259ce106e9bd7a8bacbaf212
+
+Count = 220
+Adata = 2870bd9a26c510e9a256920899bbc77a4eb9b53f927045a943d5ed6b13638cf3
+Payload = 53911a67b65738f87fc7c20d6db8044bde1af95838d1
+CT = 70cf37d4b6f7e707376b1574ce17c040b5143da47abb2fe9afafc2fccd98ccf63b0fdec30eac
+
+Count = 221
+Adata = 611032a95ee87f89ad6be7c0fed8bd245c5f81076087b3bda4cde5587b8d14b6
+Payload = 46917e38b8a542296d290d065b0aa7c8aaa38950c386
+CT = 65cf538bb8059dd62585da7ff8a563c3c1ad4dac81ec102dfd8c231d6a355f079c213ce6858e
+
+Count = 222
+Adata = 2e7ea26d1cceaca3b7862a7a8469e366b52ec27ca127e3317222ee651d8da4a0
+Payload = b527828c89f674dc6f024f8cdd80c694bb3ebd57b2d9
+CT = 9679af3f8956ab2327ae98f57e2f029fd03079abf0b36df11febe34dd568da12c374674b9ac4
+
+Count = 223
+Adata = 0bf4413010daec585de34142224d1cad3072f9720f91ac664ad152820e838741
+Payload = 78230f73f9c0150f630eca4cd679818551d449db82e6
+CT = 5b7d22c0f960caf02ba21d3575d6458e3ada8d27c08cb2916540d9439b832aa44236a7e187ac
+
+Count = 224
+Adata = 2e7cae3306582eb5bad148247aa6c6ec943f8748e84b8a069ca9488b11844716
+Payload = 847bb12e0e56fa07a086eeda5907ae148148fa4107d2
+CT = a7259c9d0ef625f8e82a39a3faa86a1fea463ebd45b80d0768a18dead55700901408aa3f901a
+
+Count = 225
+Adata = 63036dc4ad13aee5dc1832e867f7538da108188fec7b08262af440d07579c451
+Payload = ec59e208c4bb429a371f1b3ffdf07fce5dea8a05f0ce
+CT = cf07cfbbc41b9d657fb3cc465e5fbbc536e44ef9b2a45f2073605d2a441805b6ff89d8beb68c
+
+Count = 226
+Adata = f9ec5ce4b63156d57e451eb67ab6d7a59cc397f43f6d26dc07d1036f0fb4a8cf
+Payload = fb12d94bd21b5748b23132a03065c78dae65a0bd2cfb
+CT = d84cf4f8d2bb88b7fa9de5d993ca0386c56b64416e91dcabef6907811c6b7df4e74c7a63d83b
+
+Count = 227
+Adata = e13a204e16f42bbf4716e95f1cb7e125ffac66a87f591c8ef2c7b8485ff707fd
+Payload = 239fa31d4a65de0318bfc5b60a06d706c129dcf255ac
+CT = 00c18eae4ac501fc501312cfa9a9130daa27180e17c626aa8aa37e858cd990f5593d9ef35f2a
+
+Count = 228
+Adata = c4591c3ad984a1e189c526b719212f8248289eeb277827272b8205d78191eb2d
+Payload = 57caadbb1a56cc5b8a5cf9584552e17e7af9542ba13e
+CT = 749480081af613a4c2f02e21e6fd257511f790d7e354d81e424d6b4528901ae46fb35f8b3106
+
+Count = 229
+Adata = cf4795bc7f43c30d3c3a8fd1b8a9d77d69bf59eb8b59d0f464315f40cb52335d
+Payload = a68c74e05f0a44d4a0372c0e5915b83d8e6729efacbb
+CT = 85d259535faa9b2be89bfb77faba7c36e569ed13eed1f25a4bfda35e1390f3f16f638dcd4047
+
+[Plen = 23]
+
+Key = 40f1aff2e44d05f12126097a0f07ac0359ba1a609356a4e6
+Nonce = 0df3fc6396f851785fca9aa5ff
+
+Count = 230
+Adata = e9699b20b0574fce8b5cbc4ef792eb96e2c1cce36b1b1f06ea2a95fe300633cc
+Payload = 8d98c580fb366f330dbfda20f91d99a0878b47efd14c6d
+CT = 579cdf9da62a2df471e03450516adb4ce99ae0f70b1776a39c3b429a1f922fac0b59e29a122e43
+
+Count = 231
+Adata = bd94c9ad6253c25dc417f87b6e52e03621ccf4b3bff5b402677aeb51e216335f
+Payload = 7391ba60fabe2c632bbaca16af9a235b2c7dae61691c0b
+CT = a995a07da7a26ea457e5246607ed61b7426c0979b3471067bf538e40f9366adf8758968f06ce8a
+
+Count = 232
+Adata = 4f263cda4a50b0e5379ec2fb546b326a07943527c1d175c029455a917753883b
+Payload = 7e1e93a6ca35a2c0e4f08fdb2e7ee22b9f486f0ab919e2
+CT = a41a89bb9729e00798af61ab8609a0c7f159c8126342f964a1199251b54f419720a30de83161de
+
+Count = 233
+Adata = 4d43702be4f0530319555d7f1a3356160f6cae48051f12e22a153d7e405c1149
+Payload = f94ff053c7413f34f96eae41fd1ac101151069af5a9428
+CT = 234bea4e9a5d7df385314031556d83ed7b01ceb780cf33b417e4cceb8dcf45ef33cc0007755bbc
+
+Count = 234
+Adata = f4d7978fad36223623ccb5bb18a7373cba8a6e3b1c921259e319266042db8887
+Payload = ba0716355fffb8ef947d2a15eb58375a1ff1084c566990
+CT = 60030c2802e3fa28e822c465432f75b671e0af548c328bd35aed57f49dcfecf248cf9d246ac024
+
+Count = 235
+Adata = 12e4fe727b1f27a619dd67bb976ddc2b18b2ef8b7184290d9553494a500d933e
+Payload = 872940780a94680a791c937994ceafd2c8b7a22b5f4927
+CT = 5d2d5a6557882acd05437d093cb9ed3ea6a6053385123c97cda0e04d2ff65c2e06a8276bdf6f97
+
+Count = 236
+Adata = 2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57
+Payload = d71864877f2578db092daba2d6a1f9f4698a9c356c7830
+CT = 0d1c7e9a22393a1c757245d27ed6bb18079b3b2db6232b3494dd2ee0a0fe5bfc9f69234c8142ed
+
+Count = 237
+Adata = cefc4f2fb796c2502329ca3d8f8af3200dd9edb8f164e15acec90536a15b6fdc
+Payload = cda681aa3109ebf5f21ee3a849098ea3a551e844fae4b4
+CT = 17a29bb76c15a9328e410dd8e17ecc4fcb404f5c20bfaf9008ead8e923997508eebf5e776198dc
+
+Count = 238
+Adata = 94fc7eb8febb832097ba6eecd2697da91b5a8a1f2248f67a7659e0ac55a09a0d
+Payload = d4f8d262870b5000a40b8fcce88f55c65c4d12e729975e
+CT = 0efcc87fda1712c7d85461bc40f8172a325cb5fff3cc45f136cc6ea1b0fdb554e0803053875b89
+
+Count = 239
+Adata = 459085184094e302b2e921cc04270b676e75bbcf0e4b53ed387df2bd0e75e0ac
+Payload = 732f211061c0a32c6ad124c58418d560ef5eab2602314c
+CT = a92b3b0d3cdce1eb168ecab52c6f978c814f0c3ed86a575da8ceccae093888daaf92c95817fc3d
+
+[Plen = 24]
+
+Key = 91f9d636a071c3aad1743137e0644a73de9e47bd76acd919
+Nonce = 1bf491ac320d660eb2dd45c6c3
+
+Count = 240
+Adata = 3bdfd7f18d2b6d0804d779f0679aaa2d7d32978c2df8015ae4b758d337be81dd
+Payload = 4eaf9384cad976f65f98042d561d760b5a787330dc658f6c
+CT = 635530cab14e3d0a135bb6eebb5829412676e6dd4995f99cb7e17f235bd660e7e17b2c65320e9fd4
+
+Count = 241
+Adata = 9de45b7e30bb67e88735b8fb7729d6f3de46c78921b228bad8f17cc9c709c387
+Payload = 59bee7d18fd4ba573f3e4f61076f5b9f6a3487e47d98c729
+CT = 7444449ff443f1ab73fdfda2ea2a04d5163a1209e868b1d99f40890c7d650afccda40fb2a4cd603b
+
+Count = 242
+Adata = 783477f981ef0551b5e7a714b640bbb38316c53756c96e30c898cdee3b72e6f4
+Payload = 4e7f3c86d846ff351db81dbe1d2e9ed73ec0450587ae681b
+CT = 63859fc8a3d1b4c9517baf7df06bc19d42ced0e8125e1eeb50236cf1a12a9e3542a4051788f9775a
+
+Count = 243
+Adata = 2851d40243512a43f70f9c25e9b18c122a1433f05c61e65017e197e88b129e43
+Payload = 2db7cb2739c839383b64c2c93c7d5c906d984756c3dedaa9
+CT = 004d6869425f72c477a7700ad13803da1196d2bb562eac59b1bbad9861192df356c6678b2f561ea3
+
+Count = 244
+Adata = 1cfa2d62cc1f6313fb0c6eb21803e09cdf61ee3ddb15192529560e5d8096cafb
+Payload = 2f2b82497c78369890809460d80a16be4f3330e8a0089165
+CT = 02d1210707ef7d64dc4326a3354f49f4333da50535f8e7951da4211d4c28d2d91568117fc99fd911
+
+Count = 245
+Adata = 5a14b556156191b2704936f64df0bf1dd2bd8d587418f4f85472338fcf86aa52
+Payload = 7cfefca725da1b6bb5d9545e3e50f5a624a8160bdb0e7d4e
+CT = 51045fe95e4d5097f91ae69dd315aaec58a683e64efe0bbeda99be0e054bb881a25a74b547d3ed5e
+
+Count = 246
+Adata = 148de640f3c11591a6f8c5c48632c5fb79d3b7e1cef9159c680d71fd1f9801fa
+Payload = 5205165c4e9612974dc92f60d1e328d68aa9466e27dbd499
+CT = 7fffb5123501596b010a9da33ca6779cf6a7d383b22ba2694c1fedb47fa30ff2ead6bf382431b2de
+
+Count = 247
+Adata = f852e38703097cc37c589b7860dbc333e091411462d5576dc9909a8cf6ac99d4
+Payload = f968f2833427abbc9fe1cab7e7a3f905a3b23a35802029ff
+CT = d49251cd4fb0e040d32278740ae6a64fdfbcafd815d05f0f338762a4e4299615c67130a28b56a383
+
+Count = 248
+Adata = 43df03a0e23c7ad0d13485150ca224c0b3f39d4e5f2d718db6308e003d3dc683
+Payload = 67da6ca42655188af0b8e389152b2a1b6e2c3ed88926afa5
+CT = 4a20cfea5dc25376bc7b514af86e75511222ab351cd6d9559dbdf61387294812f483aad76d48d899
+
+Count = 249
+Adata = b297dce04ada2ddebc7e94eff7c51b87eee2f98c410c5c0919d0652653ab7458
+Payload = 9777cf90dd7c7e863506686fc3ba6d3d05328f78b350f92f
+CT = ba8d6cdea6eb357a79c5daac2eff3277793c1a9526a08fdf078177541e19b11dfec995f40c99af70
diff --git a/lib/crypto/test/crypto_SUITE_data/VPT256.rsp b/lib/crypto/test/crypto_SUITE_data/VPT256.rsp
new file mode 100644
index 0000000000..e9cd7eefe9
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VPT256.rsp
@@ -0,0 +1,1383 @@
+# CAVS 11.0
+# "CCM-VPT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Nlen = 13
+Tlen = 16
+
+[Plen = 0]
+
+Key = c6c14c655e52c8a4c7e8d54e974d698e1f21ee3ba717a0adfa6136d02668c476
+Nonce = 291e91b19de518cd7806de44f6
+
+Count = 0
+Adata = b4f8326944a45d95f91887c2a6ac36b60eea5edef84c1c358146a666b6878335
+Payload = 00
+CT = ca482c674b599046cc7d7ee0d00eec1e
+
+Count = 1
+Adata = 36c17fd901169e5b144fdb2c4bea8cd65ad8acf7b4d3dd39acf2ad83da7b1971
+Payload = 00
+CT = 67747defe5da5fecc00b9bf3b249f434
+
+Count = 2
+Adata = 9a37c654ab8e5a0c6bdfff9793457197d206ed207d768cbc8318cfb39f077b89
+Payload = 00
+CT = c57ef5d0faf49149c311707493a4cfd4
+
+Count = 3
+Adata = 5ab80169184541393a6975f442ee583cd432d71a6d1568fa51159df7c5b8f959
+Payload = 00
+CT = bc2fb5571a7563bb90689a229d2f63a7
+
+Count = 4
+Adata = c78a22a667aafab0c94047e03837d51b11490693d5c57ea27b901ff80b6a38f9
+Payload = 00
+CT = 428888c6420c56806f465b415a66e65a
+
+Count = 5
+Adata = e11e30cbf63623816379f578788b0c8e6b59ee3c9c50aa6e1dcd749172d48fed
+Payload = 00
+CT = 9f1b7520025e1075731adc946b80121d
+
+Count = 6
+Adata = 05716168829276ff7ab23b7dd373db361e6d9e1f11d0028d374a0d3fe62be19f
+Payload = 00
+CT = bd36b053b6a90f19e3b6622cba93105d
+
+Count = 7
+Adata = 3e915389639435629fcc01e1b7022d3574e2848e9151261ad801d03387425dd7
+Payload = 00
+CT = 458595a3413b965b189de46703760aa0
+
+Count = 8
+Adata = 2f496be73a9a5d9db5927e622e166c6ec946150687b21c51c8ca7e680f9775ac
+Payload = 00
+CT = 8b259b84a6ee5669e175affca8ba3b1a
+
+Count = 9
+Adata = 0a8725bd8c8eab9ed52ca47835837b9f00a6c8d834ab17105b01eb4eb30402e7
+Payload = 00
+CT = c5f35fdf2b63e77a18d154f0ddcfedbf
+
+[Plen = 1]
+
+Key = cc49d4a397887cb57bc92c8a8c26a7aac205c653ef4011c1f48390ad35f5df14
+Nonce = 6df8c5c28d1728975a0b766cd7
+
+Count = 10
+Adata = 080f82469505118842e5fa70df5323de175a37609904ee5e76288f94ca84b3c5
+Payload = 1a
+CT = a5f24e87a11a95374d4c190945bf08ef2f
+
+Count = 11
+Adata = f6cfb81373f1cbb0574dda514747d0099635b48cb809c6f1fa30cbb671baa505
+Payload = 40
+CT = ffd43c5f39be92778fdce3c832d2d3a019
+
+Count = 12
+Adata = 5a88b14bada16b513d4aa349b11ce4a77d4cda6f6322ff4939ad77d8ecb63748
+Payload = 41
+CT = fe753b7b661f1aad57c24c889b1c4fe513
+
+Count = 13
+Adata = a92b95b997cf9efded9ff5e1bff2e49d32e65f6283552ded4b05485b011f853f
+Payload = 06
+CT = b91c5ac66e89bf2769ef5f38a3f1738b24
+
+Count = 14
+Adata = a206a1eb70a9d24bb5e72f314e7d91de074f59055653bdd24aab5f2bbe112436
+Payload = c8
+CT = 773fe64379cea1a8ae3627418dd3e489a2
+
+Count = 15
+Adata = d3029f384fd7859c287e38c61a9475d5ddbfd64af93746b1dc86b8842a8c194c
+Payload = e2
+CT = 5dabc529442ff93005551b7689bcb748f7
+
+Count = 16
+Adata = 51ca3d3b70b5e354451a5177d7acfd8e7b44eae55e29d88b5e8eb8fc1e5c62fc
+Payload = 1a
+CT = a5ee68e416617ac974b3d1af7320cd51f6
+
+Count = 17
+Adata = 8c6c6791f1ac957b18bf008e260a0af4a5b7bfdb1e0008d6eaaa227f45cf4f62
+Payload = dd
+CT = 6243883d93d7066991e0fac453400b4fbf
+
+Count = 18
+Adata = b0a1af969a95025385b251afd1e89f353426ed6e5d71019cd73366aa31d5b464
+Payload = 4c
+CT = f3b940d416f3435812f9d1b18f441b7721
+
+Count = 19
+Adata = 7e72b2ca698a18cb0bf625f5daddb0d40643009db938340a9e4fe164a052fee1
+Payload = 88
+CT = 371d27e9a32feea28a6a7e7da2d27e1cc4
+
+[Plen = 2]
+
+Key = 36b0175379e7ae19c277fe656a2252a82796309be0f0d4e1c07fdde88aca4510
+Nonce = 021bd8b551947be4c18cf1a455
+
+Count = 20
+Adata = b5c6e8313b9c68e6bb84bffd65fa4108d243f580eab99bb80563ed1050c8266b
+Payload = be80
+CT = ecacc3152e43d9efea26e16c1d1793e2a8c4
+
+Count = 21
+Adata = 38e5032c5949c2668191ef1af5bb17eddc28abdb4e5bb41eaffec2523b2525d6
+Payload = 82c9
+CT = d0e5d06bf4b50ccce0b2acfd16ce90a8854d
+
+Count = 22
+Adata = 0b50f5173249fb7118f80d25874d6745d88e4ce265fa0dd141ad67ae26c31122
+Payload = 8239
+CT = d0158d784f486c1dc4a2bafd5b02ca1e1c05
+
+Count = 23
+Adata = 0296743a3125b103a2b2a78a109e825ea10834bd684215ab2e85cc4172e37348
+Payload = 16c1
+CT = 44eda3377002a48f9fe306d157358e6df37d
+
+Count = 24
+Adata = a94e64becb803e211785ba51db7f3db042fbf44a7a821509156a6828b0f207e9
+Payload = 2801
+CT = 7a2df6c09bf1dcb1c82bd98c6e2c13a8d7a5
+
+Count = 25
+Adata = 105358cc17b12107e023a23d57b44c66a2c58d8db05100311575e1ea152fc350
+Payload = 65e7
+CT = 37cb2ea363c0d8864363056467570959ba03
+
+Count = 26
+Adata = 669f9a63cf638a202dca1965c4116273249813ce0b39703887d89bdf5b3b12d6
+Payload = 819d
+CT = d3b16519377e6d0252b5f80cdf3d0253eccf
+
+Count = 27
+Adata = e288590a3eba28ac6847a50b0294ab6bd0a548716ff5102c44a5b656b2d9ddd6
+Payload = 761e
+CT = 24329a4dee6ca2cde473f08f76f779856c3c
+
+Count = 28
+Adata = 5b222aae3c7786c3b9021ba672f9136190ec931cf055f84c85706127f74c6d5b
+Payload = 56de
+CT = 04f29e65c0f01e644e74092253b470cd5511
+
+Count = 29
+Adata = 2082f96c7e36b204ad076d8b2f796cccf5cbc80b8384b53a504e07706b07f596
+Payload = b275
+CT = e059809fa107f379957b52ac29fe0bc8a1e2
+
+[Plen = 3]
+
+Key = ddb739acda6c56ec9aefc4f4cbc258587f443da4e76ddfa85dbe0813a8784944
+Nonce = 0bddf342121b82f906368b0d7b
+
+Count = 30
+Adata = 887486fff7922768186363ef17eb78e5cf2fab8f47a4eb327de8b16d63b02acb
+Payload = db457c
+CT = 54473c3f65d6be431e79700378049ac06f2599
+
+Count = 31
+Adata = 0683c20e82d3c66787cb047f0b1eb1c58cdde9fb99ee4e4494bbf27eb62777d1
+Payload = 62a6c5
+CT = eda4853b186edc15c22ba24e470eb5a072da9f
+
+Count = 32
+Adata = 413074619b598f8bed34cab51ddf59941861ba0169ebe7570a5ed01d790c08e5
+Payload = cc67bc
+CT = 4365fc52a1fb5a58bd51931230c1a7dfb1a8c1
+
+Count = 33
+Adata = 2d65a5175c29a095dc082dab9cfcf4b895efbfa715c57614589d4db159543ce9
+Payload = 33800b
+CT = bc824b7d3810f59176cb108c7e969da51d4d79
+
+Count = 34
+Adata = 6a831b6059456be98e6fce608d8c71cb8efb04a96b45c2dfbdaeabf5420a1482
+Payload = b2c826
+CT = 3dca6646ffea832595c9c86e6517215541ddbd
+
+Count = 35
+Adata = 3a04a01160402bf36f33337c340883597207972728c5014213980cd7744e9e41
+Payload = d7e620
+CT = 58e460e89a6725f0fc35622d89d2f3e34be90a
+
+Count = 36
+Adata = 64d8bd3c646f76dc6ce89defd40777fe17316729e22ba90f6a2443ee03f6390b
+Payload = 795af4
+CT = f658b4b1bd7ad5d81686aeb44caa6025d488bd
+
+Count = 37
+Adata = 7bef8d35616108922aab78936967204980b8a4945b31602f5ef2feec9b144841
+Payload = 66efcd
+CT = e9ed8d0553c801f37c2b6f82861a3cd68a75e3
+
+Count = 38
+Adata = 92f7dc22dcbbe6420aca303bd586e5a24f4c3ed923a6ebe01ec1b66eee216341
+Payload = 78b00d
+CT = f7b24de3eeb8ea6c08b466baf246b3667feb3f
+
+Count = 39
+Adata = 71bf573cf63b0022d8143780fc2d9c7dbd0505ac31e9dce0ad68c2428b0878a0
+Payload = 9dd5e1
+CT = 12d7a11db811640c533794bfec6eeb977233ec
+
+[Plen = 4]
+
+Key = 62b82637e567ad27c3066d533ed76e314522ac5c53851a8c958ce6c64b82ffd0
+Nonce = 5bc2896d8b81999546f88232ab
+
+Count = 40
+Adata = fffb40b0d18cb23018aac109bf62d849adca42629d8a9ad1299b83fe274f9a63
+Payload = 87294078
+CT = 2bc22735ab21dfdcfe95bd83592fb6b4168d9a23
+
+Count = 41
+Adata = 75c3b3059e59032067e9cd94d872e66f168e503bcf46bc78d82a4d4a15a29f6e
+Payload = 0f28ee1c
+CT = a3c38951b5de3331078aa13bd3742b59df4f661a
+
+Count = 42
+Adata = 8fb9569f18a256aff71601d8412d22863e5a6e6f639214d180b095fa3b18d60e
+Payload = d41c9c87
+CT = 78f7fbcae52afe7326a12a9aaf22255a38d4bd0d
+
+Count = 43
+Adata = 8b62d9adf6819c46c870df8a1486f0a329672f7d137bb7d8659f419c361a466c
+Payload = 046bc0d8
+CT = a880a7957543692a72f0d599de48b5e5f5a9413f
+
+Count = 44
+Adata = fd98f8f39dfa46ea5926e0ffacbabbe8c34205aade08aa0df82e1d4eaaf95515
+Payload = 39bd4db8
+CT = 95562af530fc357f5482b9004d466bf858586acb
+
+Count = 45
+Adata = 09bf4f77a9883733590a3cc7ee97f3c9b70f4db255620e88cd5080badc73684c
+Payload = b43cdd3a
+CT = 18d7ba77a9e8db046fdd548b52d40375c1e9a448
+
+Count = 46
+Adata = 40326d765e0f6cf4b4deccb128bebf65a7b3c3e5bcf1d58f6158e1e9153b7e85
+Payload = e0052e9b
+CT = 4cee49d64efbdd4ad8d3e863172d9372fca07c20
+
+Count = 47
+Adata = aa5ae6dcdc21b5446489bdabf5c6747bdf3bbfdb3de2c03170efefe5ccb06d69
+Payload = 696825f6
+CT = c58342bb95bd661b32bc18025808f8b4035acad6
+
+Count = 48
+Adata = d3d34f140a856e55b29471fde4c0e5f7306b76d03faab26db79c10f95ffb3122
+Payload = 7eb07739
+CT = d25b1074ac05b072264e31a4b2801a6d790512d7
+
+Count = 49
+Adata = 648a84813ca97aef4ab7e143ee29acb946388660f18eb671194646e0b0136432
+Payload = 9cad70b1
+CT = 304617fcc00514d260e1d211de361c254369e93a
+
+[Plen = 5]
+
+Key = bc29a16e19cfbe32bf4948e8e4484159bc819b7eec504e4441a1a98ca210e576
+Nonce = 4f18bcc8ee0bbb80de30a9e086
+
+Count = 50
+Adata = 574931ae4b24bdf7e9217eca6ce2a07287999e529f6e106e3721c42dacf00f5d
+Payload = 3e8c6d1b12
+CT = 45f3795fcf9c66e1a43103d9a18f5fba5fab83f994
+
+Count = 51
+Adata = 99cd9d15630a55e166114f04093bd1bb6dbb94ecaad126fe5c408dee5f012d9f
+Payload = 76fc98ec66
+CT = 0d838ca8bb6f3cd579294f706213ed0f0bf32f00c5
+
+Count = 52
+Adata = 1516fdf7a7a99f3c9acc7fff686203dec794c3e52272985449ddf5a268a47bc3
+Payload = 6564c247cc
+CT = 1e1bd603117d38e026f706c9273dbcb6dc982751d0
+
+Count = 53
+Adata = 0c9c35be98591bf6737fc8d5624dcdba1a3523c6029013363b9153f0de77725b
+Payload = c11b9c9d76
+CT = ba6488d9abc3e46166767c6ad2aeffb347168b1b55
+
+Count = 54
+Adata = e74afe3ba960e6409dba78ecb9457e2a4ce2e09792b1d2e3858f4c79f7ddba62
+Payload = 45a4e0d7dd
+CT = 3edbf4930033a7dca78bcbf4d75d651ee5fadff31b
+
+Count = 55
+Adata = 96cbe9cd193513599c81f5a520fabaff51ee8cbdb81063c8311b1a57a0b8c8fd
+Payload = e5861b2327
+CT = 9ef90f67fa11585167c83105ee16828a574c84ac86
+
+Count = 56
+Adata = 2e7ea84da4bc4d7cfb463e3f2c8647057afff3fbececa1d20024dac29e41e2cf
+Payload = f5b5bcc38e
+CT = 8ecaa88753ffaba456f78e431f4baa5665f14e1845
+
+Count = 57
+Adata = be125386f5be9532e36786d2e4011f1149abd227b9841150d1c00f7d0efbca4a
+Payload = b6cc89c75d
+CT = cdb39d838034714731f9503993df357954ecb19cd3
+
+Count = 58
+Adata = 3fa8628594b2645bc35530203dca640838037daeaf9cf8acaa0fb76abf27a733
+Payload = 3802f2aa9e
+CT = 437de6ee436c1b008b7572752f04362b2bfdc296bb
+
+Count = 59
+Adata = 642ae3466661ce1f51783deece86c38e986b8c0adea9e410e976f8a2fe0fe10f
+Payload = e082b8741c
+CT = 9bfdac30c1a3f7c3c29dc312c1f51a675400500e32
+
+[Plen = 6]
+
+Key = 5f4b4f97b6aa48adb3336c451aac377fde4adf47897fd9ccdf139f33be76b18c
+Nonce = 7a76eac44486afdb112fc4aab9
+
+Count = 60
+Adata = a66c980f6621e03ff93b55d5a148615c4ad36d6cbdd0b22b173b4b1479fb8ff7
+Payload = 1b62ad19dcac
+CT = 4ad1fcf57c12b14e0e659a6305b4aeffae82f8a66c94
+
+Count = 61
+Adata = c13f65bd491cb172a0f7bbc4a056c579484b62695e90383358d605307d5be0a5
+Payload = 3ef0faaa9b79
+CT = 6f43ab463bc779fa7932d365e2da9b05c00a7318384a
+
+Count = 62
+Adata = 59dcca8fc50740831f8f259eb55d4db11f763a83187d93758d78d166f4d73cd5
+Payload = 1a98ddbf35f1
+CT = 4b2b8c53954f813229912137b7a4945dc07cea24a974
+
+Count = 63
+Adata = 578509ca4f57aadb78056794bf18b0714090970db786e2e838105e672165761c
+Payload = f46a7b1c28ea
+CT = a5d92af088546e045f19f737a24c8addf832ed3f7a42
+
+Count = 64
+Adata = 696c0c6427273cf06be79f2206c43af9cbda0b884efaf04deba0c4bf0a25cb26
+Payload = e98f5e5a20d0
+CT = b83c0fb6806edaae8a7dcd3b0fbb59438f88743ec6e8
+
+Count = 65
+Adata = 95a66b60249ed086eecaeb9bc449afcee9de212619e87516ca947351b25120df
+Payload = 06319c0480e2
+CT = 5782cde8205cd9cb636ca6543c4e35964f47341f2814
+
+Count = 66
+Adata = 2b411bea57b51d10a4d2fb17ef0f204aa53cf112e1130c21d411cdf16a84176d
+Payload = f4c723433b7c
+CT = a57472af9bc2ec82eadf4eb1f055da1a92a82052ab8b
+
+Count = 67
+Adata = ff3bff3a26fc5a91252d795f7e1b06f352314eb676bff50dc9fbe881c446941e
+Payload = 02f809b01ce3
+CT = 534b585cbc5d01b10a7ae24a4ca2bfb07ea2a3b31a97
+
+Count = 68
+Adata = f6be4aad63d33a96c0b5e9c4be62323c9e2308b29961fff980ba0dbda0549274
+Payload = 2b6004823a29
+CT = 7ad3556e9a97231323a4b88af5d7d0b07c0e73ddce1d
+
+Count = 69
+Adata = c3706a28d7420b41e072dcecc06b6b13116cca110bde8faea8e51f5107352d71
+Payload = 236c60cba4fa
+CT = 72df31270444db30eb33d2ede33abbe22f37704fe68b
+
+[Plen = 7]
+
+Key = f7aaeff3a1dc0cc5ecf220c67ad9f6dda060b4f1be3cc609cb4f18b2342a88a2
+Nonce = d0d6871b9adc8623ac63faf00f
+
+Count = 70
+Adata = e97175c23c5b47da8ce67811c6d60a7499b3b7e1347ad860519285b67201fe38
+Payload = d48daa2919348d
+CT = eb32ab153a8e092fa325bafc176a07c31e6cc0a852d288
+
+Count = 71
+Adata = ba45e1859efae362a44a0116a14e488ba369da6c76c3913b6df8e69e5e1111fa
+Payload = f95b716bfe3475
+CT = c6e47057dd8ef1a24840f4f40a7963becde3a85968b29c
+
+Count = 72
+Adata = efcaa6f6cda3036b0b52ff9f36bc38ca74049c32c6b7cdfb8a46ca4144bacd64
+Payload = 4862e3677083f0
+CT = 77dde25b5339748f2a4a5c276727e0a210fc2efb5aeabe
+
+Count = 73
+Adata = 360bcb407603fe92f856bf677625b9882521e6dae8f35fdfc3dc737f9398f609
+Payload = 7f1ca0728f6d65
+CT = 40a3a14eacd7e1051734fc31232ab2ab63474020ab4dc9
+
+Count = 74
+Adata = f12ee9d37946cfd88516cbe4a046f08c9bbba76a3973ff1e2cb14493405bd384
+Payload = 67478ef73290fa
+CT = 58f88fcb112a7ec715244f307609ffa253e4e3659b0ece
+
+Count = 75
+Adata = 5833dde0c577b2be4eb4b3d01d7b0042fa8441ad7043ea462bbbbd56a59790ea
+Payload = 36bb9e511276c5
+CT = 09049f6d31cc41f11047da612d2987fa2e50ada5ae7f9d
+
+Count = 76
+Adata = 1e103c63d8ead36b985f921044cd32b8f9f04a2ba9fa154a09e676ffaa093970
+Payload = d68d6556c5a5b1
+CT = e932646ae61f35382f7648718127ebae7eb7443ebd2c2c
+
+Count = 77
+Adata = a1cfb61d45a140bdea6329ba0fe80429ff9aa4624a1d31bc752f7c97f1d390a0
+Payload = 0568cca4ff79dc
+CT = 3ad7cd98dcc358cc40a5e7fffb1fb9a5dd9d6ba91bede1
+
+Count = 78
+Adata = 116b5b015e44ceef0061b2d2e73fa0b386d5c1e187782beebdfc6efb5a1c6935
+Payload = bd93d08eea4263
+CT = 822cd1b2c9f8e7468d2b70c311732f11ed72b57d83e500
+
+Count = 79
+Adata = 3d55882e6f3f89309b6940a3b408e573458eedd10fc3d0e1f3170eb313367475
+Payload = 4fb62753024e92
+CT = 7009266f21f416b41a70f548e359add30c0e5746fbeb2b
+
+[Plen = 8]
+
+Key = 493e14623cd250058a7fc66a3fee0c24b6e363b966c2314aff53b276b6c2ea7b
+Nonce = fe2d8ae8da94a6df563f89ce00
+
+Count = 80
+Adata = 579a637e37a0974cd2fc3b735d9ed088e8e488ffe210f043e0f9d2079a015ad6
+Payload = e5653e512d8b0b70
+CT = 75d31f8d47bee5c4e2ba537355ae8ab25cc9ed3511ff5053
+
+Count = 81
+Adata = 1583138aa307401dddc40804ac0f414d338fc3ffb2946f09aaaa7079426fc1ee
+Payload = 2c4ba9ce52e01645
+CT = bcfd881238d5f8f1781a9e359804831f31a1efb1ae1cb71d
+
+Count = 82
+Adata = 78d3dda40e433bba7a330ca3e5bd5170f0895f2e3e438402344ced79fcb0c719
+Payload = 5eb2d054a0e58c62
+CT = ce04f188cad062d62dcc77c4e1fe2bafd477598977835f0c
+
+Count = 83
+Adata = dfc762466fa84c27326e0ee4320aa71103d1e9c8a5cf7d9fab5f27d79df94bd6
+Payload = bbbf7830d04ab907
+CT = 2b0959ecba7f57b308946723baf0dbf613359b6e040f9bd5
+
+Count = 84
+Adata = 7e8ea82d1137c1e233522da12626e90a5f66a988e70664cb014c12790d2ab520
+Payload = 10c654c78a9e3c06
+CT = 8070751be0abd2b2003bd62ca51f74088bbbd33e54ac9dd4
+
+Count = 85
+Adata = 873da112557935b3929f713d80744ed08b4b276b86331dbc386fba361726d565
+Payload = 668d32e322e1da3e
+CT = f63b133f48d4348a67e65e7f2cdedf6ef8cc0ee7a6dcfb02
+
+Count = 86
+Adata = cfba97919f703d864efc11eac5f260a5d920d780c52899e5d76f8fe66936ff82
+Payload = e39f6225e8eab6cc
+CT = 732943f982df58780532f8c6639e5d6c7b755fcf516724e3
+
+Count = 87
+Adata = 01abcfee196f9d74fcaa7b69ae24a275485c25af93cc2306d56e41e1eb7f5702
+Payload = 6021a00f6d0610a4
+CT = f09781d30733fe107fd7a33828413ebc252dd9d015773524
+
+Count = 88
+Adata = ce1c31e7121c071d89afab5a9676c9e96cac3d89dcae83136bbb6f5ca8f81e5d
+Payload = bbaf0ac4e77ee78d
+CT = 2b192b188d4b0939d3d51368799325ad1c8233fa071bade0
+
+Count = 89
+Adata = bb210ca5bc07e3c5b06f1d0084a5a72125f177d3e56c151221115ae020177739
+Payload = 98a2336549a23a76
+CT = 081412b92397d4c25d1ea568637f773174a7f920a51b1fe1
+
+[Plen = 9]
+
+Key = b23255372455c69244a0210e6a9e13b155a5ec9d6d0900e54a8f4d9f7a255e3a
+Nonce = 274846196d78f0af2df5860231
+
+Count = 90
+Adata = 69adcae8a1e9a3f2fe9e62591f7b4c5b19d3b50e769521f67e7ea8d7b58d9fc8
+Payload = 615d724ae94a5daf8d
+CT = f019ae51063239287d896e7127f17d13f98013b420219eb877
+
+Count = 91
+Adata = 162d0033c9ea8d8334d485b29eef727302135a07a934eea5fee6041e9f1f47c1
+Payload = 0d9168eeab3b27ba69
+CT = 9cd5b4f54443433d997cc2cd61da9358b4045fef32f8192cbf
+
+Count = 92
+Adata = 3f4ab57efa32f51a4c00790280e77c0e55b85bbda4f854e242368e9a289b5a81
+Payload = 6287dcffdd5fb97885
+CT = f3c300e43227ddff75d280f0ffdd560fb8915978e3bd6205bb
+
+Count = 93
+Adata = 945d18134c148f164b39fd7c4aef0335045553f6ea690a3b1726418d86f0de00
+Payload = 6e5e01b3fd71d16b9c
+CT = ff1adda81209b5ec6c7dbf90420a1ff2e24bd6303b80cfc199
+
+Count = 94
+Adata = 23af12893431b07c2922ab623aed901c0eaaeb9a24efc55273e96aea4dab7038
+Payload = b51521e689b5247362
+CT = 2451fdfd66cd40f492d741f4329ae7cc77d42bf7e5f2ec5ab6
+
+Count = 95
+Adata = b15a118b3132c20c31e6c9d09acdee0e15fcc59d6f18306442682512d22eb10f
+Payload = 7f973617e710fb76fe
+CT = eed3ea0c08689ff10ec9ffdcc2f36edac14613b1d85baf25a9
+
+Count = 96
+Adata = dcfbeb6490f5fa7eaf917462473a6cec98bebf8f17493fe9b994119a6d5a5457
+Payload = 7e909b6727ac3fd02f
+CT = efd4477cc8d45b57df5a61a28bb10265b26043d7a8dd357713
+
+Count = 97
+Adata = 77e9317294f046f315a0d79e3423f29f7d9ebcd36d6eaa2a3fb2f4500309478c
+Payload = a5075638932b5632f8
+CT = 34438a237c5332b508d321c371ae1fd01bdf3b6c75a597da6e
+
+Count = 98
+Adata = 3aa8f204eb127b547e13873ed0238018394e13686c8734e49e3e629deb352c77
+Payload = c10f15a0de78db8aa3
+CT = 504bc9bb3100bf0d539393d1635bc40ac62405a39155406c47
+
+Count = 99
+Adata = 7f67e6f97c6c258f014d721a4edaaa0ddb3f9f09993276ab7b714ea9356c231d
+Payload = 8294f830cfca42cfbe
+CT = 13d0242b20b226484eff89641e1bd5ad6cc827441b17c45ecf
+
+[Plen = 10]
+
+Key = dbf06366f766e2811ecd5d4384d6d08336adc37e0824d620cf0d9e7fd1e7afa9
+Nonce = b3503ed4e277ed9769b20c10c0
+
+Count = 100
+Adata = 9ae5a04baa9d02c8854e609899c6240851cbc83f81f752bc04c71affa4eed385
+Payload = 2e3cf0af8c96c7b22719
+CT = e317df43ab46eb31be7e76f2730d771d56099a0c8d2703d7a24e
+
+Count = 101
+Adata = da77c6d5627a2aa34911bd1f7cc5f8aa68a2c6546adc96a186b9af8e5baac4cf
+Payload = e081c43a07450ce0dfa2
+CT = 2daaebd62095206346c5bcc7a8260ef361dc39fdb776d041f0d4
+
+Count = 102
+Adata = 134d2d9726400d09dd3521326f96fbef993ddc0c4088770057b0f8d70356456f
+Payload = c381d2ae5e72fc82324a
+CT = 0eaafd4279a2d001ab2d19f0cbb0899f221aac9762f2650f8058
+
+Count = 103
+Adata = 0d065dfde1de1f21784c7869eb566c977f807cfbd53578f4616995b51d7dc045
+Payload = 737f4d00c54ddca80eec
+CT = be5462ece29df02b978b3dc92a9bd26b9653e5917359c331fcff
+
+Count = 104
+Adata = 95c54d187f2415535451cbb9cb35869749b171f7043216ce6886dd77baeecf60
+Payload = 4e9e251ebbbbe5dbc8ff
+CT = 83b50af29c6bc958519891dda72c27d272561e00f7041845d998
+
+Count = 105
+Adata = 0f98039e6a9fe360373b48c7850ce113a0ff7b2ae5ce773dd4c67ca967cd691b
+Payload = 0db72b281ab4046d15a6
+CT = c09c04c43d6428ee8cc1928ac628758ad58fc1b5a768d4722848
+
+Count = 106
+Adata = ad840bc55654762e5eba0e4a9e7998992d990a06d70da1b1ca922ef193dab19a
+Payload = 4f7b4f38ff1ba4df5a59
+CT = 825060d4d8cb885cc33ed11dad4dc8b265a53cf0bdd85c5f15f4
+
+Count = 107
+Adata = 911e9876ea98e1bcf710d8fd05b5bf000ea317d926b41b6015998ee1462ab615
+Payload = 58ce55379ef24b72d6d6
+CT = 95e57adbb92267f14fb18eb659a5a7084be48d099467da4395df
+
+Count = 108
+Adata = 3f68a4fb4043bcf9b6d277c97e11365d949c705bd6679c6f0aaf52e62330ad79
+Payload = a219028a953ce1544835
+CT = 6f322d66b2eccdd7d1523b2b2583fd117cec47b1c84d3863159e
+
+Count = 109
+Adata = 02f32242cba6204319075ea8ce806a57845355ae73e6b875955df510096ebff9
+Payload = 83b0ee9a52252c456105
+CT = 4e9bc17675f500c6f8625456eb2b6a2d35c649a84051f843153c
+
+[Plen = 11]
+
+Key = 4dd555bd3a5253a90b68b5d4d46bd050340ee07ddad3a72048c657b5d76bb207
+Nonce = bdb1b82ba864893c2ee8f7426c
+
+Count = 110
+Adata = 9bcc5848e928ba0068f7a867e79e83a6f93593354a8bfcfc306aeeb9821c1da1
+Payload = 8015c0f07a7acd4b1cbdd2
+CT = 8e9f80c726980b3d42e43a6512a0481255b729a10f9edb5f07c60c
+
+Count = 111
+Adata = c2e75952ab49216f305e3776865791ce877cef8c0229ca97561787093fddf1d8
+Payload = c97b62a719720b44b7779c
+CT = c7f122904590cd32e92e748c514444f00ffdb80a4bb7e9eb651946
+
+Count = 112
+Adata = c76a3ff4e6d1f742dd845be2d74c1a9b08e418909b15077deb20373ef55caf91
+Payload = cb7c17ef62464ecc8008f6
+CT = c5f657d83ea488bade511edb609dfc1929ac1ba5753fc83bf945b7
+
+Count = 113
+Adata = bdb69f99f9a144b9ad88c6cfd8ffb8304c201de9b2818552ce6379e6042c1951
+Payload = 893a690cc5221de597d0e8
+CT = 87b0293b99c0db93c9890053b74283296d0fca83b262915289163c
+
+Count = 114
+Adata = 01815f599d6ba0d1c09f6f673bb6cca4c2a7a74f4e985be4c0f37842c7bbc5a4
+Payload = 80f3e4245c3eab16ef8bf0
+CT = 8e79a41300dc6d60b1d21888a34955893059d66549795b3ac2105c
+
+Count = 115
+Adata = a9db62e9ab53c4a805c43838ce36b587d29b75b43fb34c17a22d3981120f3bc5
+Payload = 641c6914920a79943dca39
+CT = 6a962923cee8bfe26393d1377c4e2f20aaa872a9a0b1d1d7f56df0
+
+Count = 116
+Adata = f0c2cc5a1b4c4cbe839338fa0d7a343514801302aef2403530605cf4f44d2811
+Payload = 2286a1eddd80737a724ca9
+CT = 2c0ce1da8162b50c2c15415545aa0c1dd11551891ae553d3a91908
+
+Count = 117
+Adata = 9842922499ad4d487488b3731f48765efe0b4eb59e7b491ba5f6636f09ed564d
+Payload = d8c63e7d7d332198249c0c
+CT = d64c7e4a21d1e7ee7ac5e4d9e07ec5806360843676ef27d811b246
+
+Count = 118
+Adata = 399b71ecb41f4590abda79045cdf6495f27daaa559c1b34f513b5c4ac105ec10
+Payload = 4b81804d777a59b6a107cf
+CT = 450bc07a2b989fc0ff5e27483b8727c5753ede25e1fab0d86963be
+
+Count = 119
+Adata = 2c186c5c3463a4a8bad771feb71e2973c4f6dede2529827707bf4fa40672660f
+Payload = dfc762466fa84c27326e0e
+CT = d14d2271334a8a516c37e64b5c3c1dc577ee8fcf6ef3ebc0783430
+
+[Plen = 12]
+
+Key = d3ad8cda9a0d91a205c4c05665728bb255d50a83403c9ab9243fcbbe95ae7906
+Nonce = 0b5f69697eb1af24e8e6fcb605
+
+Count = 120
+Adata = ea26ea68facdac3c75ba0cdf7b1ad703c9474af83b3fbfc58e548d776b2529b9
+Payload = a203aeb635e195bc33fd42fa
+CT = 62666297a809c982b50722bd56bc555899345e0404b2938edf33168e
+
+Count = 121
+Adata = 0b32069fc7e676f229f1037d3026c93eef199913e426efd786b524ce1dbde543
+Payload = aac414fbad945a49ae178103
+CT = 6aa1d8da307c067728ede1449b15447c904b671824c2ca24c4fc7ad4
+
+Count = 122
+Adata = 7a8658302e5181552292aa56e8209de63b5d86934167549b0d936202681757e1
+Payload = 7ee0ce371329192618e3cda0
+CT = be8502168ec145189e19ade7ea13850e99ef9300c65f5abc9419d13a
+
+Count = 123
+Adata = 4f05600950664d5190a2ebc29c9edb89c20079a4d3e6bc3b27d75e34e2fa3d02
+Payload = b0a1af969a95025385b251af
+CT = 70c463b7077d5e6d034831e8486c93c31bbedc9e5ffa2f4154bceea9
+
+Count = 124
+Adata = 4530e4dc6a4c3733b8ab7e77e384223cc1a8c179fb66818c08aca47e5c705d89
+Payload = 9f6c6d60110fd3782bdf49b0
+CT = 5f09a1418ce78f46ad2529f7f18b556e7da59fd2549dc57a17bf64f8
+
+Count = 125
+Adata = f179353aef342f0f691caf1fcb811e3f6504e14d6d9381c5439b098ff978b01b
+Payload = 90958d7f458d98c48cbb464c
+CT = 50f0415ed865c4fa0a41260b30aad3a838680cbd313004685a5510c5
+
+Count = 126
+Adata = f6df267e5cbc9d2a67b1c0fd762f891ee3b7c435884cb87d8228091b34aeddae
+Payload = 9f7ae892e5662803408d4d06
+CT = 5f1f24b3788e743dc6772d411d57b89ed0c91251aed37a6ca68a50c7
+
+Count = 127
+Adata = 4372e152b1afd99c7f87c8a51dbc3a5c14c49d04ea1c482a45dfbcda54972912
+Payload = 817074e351455f23cb67883d
+CT = 4115b8c2ccad031d4d9de87ad79a3b0feea16ff5fbca16211ea6fdd9
+
+Count = 128
+Adata = 82b6cd1c6618c42ba74e746075dc28700333578131ca6fde6971d2f0c6e31e6a
+Payload = 1b7da3835e074fdf62f1eb3c
+CT = db186fa2c3ef13e1e40b8b7b49f22737c4b2f9fa0a7e3dd4b067fbaa
+
+Count = 129
+Adata = a5422e53975e43168726677930f6d3e13281bdbd13c67c168340ed67e45d15b0
+Payload = 57473e7a105c806867379194
+CT = 9722f25b8db4dc56e1cdf1d3ef43a48dbea8c1547455ad0197af88a2
+
+[Plen = 13]
+
+Key = e300fc7a5b96806382c35af5b2c2e8e26382751b59010d4b1cfc90a4a9cb06df
+Nonce = 55b59eb434dd1ba3723ee0dc72
+
+Count = 130
+Adata = 9b1d85384cb6f47c0b13514a303d4e1d95af4c6442691f314a401135f07829ec
+Payload = 8714eb9ecf8bdb13e919de40f9
+CT = ba6063824d314aa3cbab14b8c54c6520dac0f073856d9b9010b7857736
+
+Count = 131
+Adata = fa17c693d0997140fbc521d39e042d8e08388106874207ca81c85f45c035d6e6
+Payload = a0837676e091213890dc6e0a34
+CT = 9df7fe6a622bb088b26ea4f20820a423dd30796b6016baff106aaef206
+
+Count = 132
+Adata = 27663597b389b78e96c785ca2f5510c8963a5561d2b0b24c4dcdf8e58562c12c
+Payload = b8a2ce7e051b8d094ec43f2a7f
+CT = 85d6466287a11cb96c76f5d2436032bc79c4aef1f74da25e92b0aa7f8a
+
+Count = 133
+Adata = d8f1a83371487d611ce704e0a6731f97a933c43569690022fce33cb5aecdc0a7
+Payload = 9e4103ab1dfb77ae3494507332
+CT = a3358bb79f41e61e16269a8b0e658123d2e5bb324c7ead8897f8e32b0a
+
+Count = 134
+Adata = 05c57aab99f94b315cf8bdd2d6b54440c097fe33c62a96b98b1568cdee4ce62c
+Payload = fb3e3d1b6394d2daebf121f8ac
+CT = c64ab507e12e436ac943eb0090270758ab09f93fa3ba7d7a2aa8eac789
+
+Count = 135
+Adata = 1c1b0933c508c6a8a20846ebd0d0377e24f4abc0c900d3a92bc409ba14ef1434
+Payload = 549ba26a299391538b56ce4bd7
+CT = 69ef2a76ab2900e3a9e404b3eb2293813f1bcb96564f772e9308e42b2d
+
+Count = 136
+Adata = 9f5cf9149f556124d6bb4e3e243cca1502c02682709392cc2ec7eb262fd4d479
+Payload = 287f31e69880823df7798c7970
+CT = 150bb9fa1a3a138dd5cb46814c81877380d5cf097c2fb5177750f8b53a
+
+Count = 137
+Adata = 1a49aaea6fc6fae01a57d2fc207ef9f623dfd0bc2cf736c4a70aaaa0af5dafd3
+Payload = 040d18b128ae4a1935f9509266
+CT = 397990adaa14dba9174b9a6a5acf42c75787edc62a180568c6ef56545d
+
+Count = 138
+Adata = f29a0b2c602ff2cacb587292db301182e6c76c5110b97ca8b706198f0e1dbc26
+Payload = 92441cbe8d70820870bb01ad63
+CT = af3094a20fca13b85209cb555f56d47a0631f2038103e3904b556ba7a5
+
+Count = 139
+Adata = 01fcf5fef50e36175b0510874ea50a4d2005ad5e40e5889b61417700d827251e
+Payload = f11d814df217de96333dee1cbf
+CT = cc69095170ad4f26118f24e4835be15b7ae24edccd0b0934e3af513ed3
+
+[Plen = 14]
+
+Key = 3ae5be5904bae62609ac525e2d1cad90133447573d7b608975a6a2b16cb2efc0
+Nonce = 61bf06b9fa5a450d094f3ddcb5
+
+Count = 140
+Adata = 0245484bcd987787fe97fda6c8ffb6e7058d7b8f7064f27514afaac4048767fd
+Payload = 959403e0771c21a416bd03f38983
+CT = 37a346bc4909965c5497838251826385a52c68914e9d1f63fd297ee6e7ed
+
+Count = 141
+Adata = 52f6a10a022e5ee57eda3fcf53dcf0d922e9a3785b39fad9498327744f2852e4
+Payload = 23fe445efa5bcb318cc85e2ad1ac
+CT = 81c90102c44e7cc9cee2de5b09ad364b603de6afbc2d96d00510894ccbe7
+
+Count = 142
+Adata = d236e3841b9556b32dbd02886724d053a9b8488c5ad1b466b06482a62b79ebb6
+Payload = 762fdc3e0c30c7ecf2ec8808bb79
+CT = d418996232257014b0c6087963781a4321c2ddbc35ce4864457d611219e9
+
+Count = 143
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+Payload = b6813d5fe8afa68d646c197337a2
+CT = 14b67803d6ba117526469902efa3296e55efebb17fe145cdca9b31ea7bcc
+
+Count = 144
+Adata = 7f291aa463c4babc76b4a6faf2e27e9401586b1ac83e4b06a4090e94b3ef5fd4
+Payload = 4ce8b6578537215224eb9398c011
+CT = eedff30bbb2296aa66c113e9181059270a0510e7cc1b599705853af2144d
+
+Count = 145
+Adata = 06bca7ef6f91355d19f90bf25590a44a24e5a782f92bc693c031e6de1e948008
+Payload = 9ebf93643854ea5c97a4f38f50bd
+CT = 3c88d63806415da4d58e73fe88bcb55847573bf21e946ce9bdc5f569e3ff
+
+Count = 146
+Adata = 5a44ff94f817c7c028a8f3db35a4d01364d2598432469f09ded86e5127d42d35
+Payload = da989cc7d375ed5fac4d7f938d74
+CT = 78afd99bed605aa7ee67ffe25575b8a61c5687ea02f0276824b8316b76f1
+
+Count = 147
+Adata = 2a755e362373ef27a911c4d93ca07bc97135645442ad7ad6a8ef98146c71e9d7
+Payload = 6fbab5a0f98e21e4d15904af5948
+CT = cd8df0fcc79b961c937384de8149a07ee02791011129fcacffcfb1bf4145
+
+Count = 148
+Adata = f7988873f45a5de314e5381d3f14d8f8c48c9b649bf3e745ed5dc882d507da58
+Payload = b610349e8b370a7c195598573637
+CT = 142771c2b522bd845b7f1826ee36d34204b1ce23f5f58a8eb7cf1fa8cfa7
+
+Count = 149
+Adata = 95d2c8502e28ab3ee2cac52e975c3e7bccb1a93acc33d9c32786f66d6268d198
+Payload = 1d969fd81dab5ced3e6ee70be3bf
+CT = bfa1da8423beeb157c44677a3bbe9c618bb88bbcefb008a5ea6bed4ff949
+
+[Plen = 15]
+
+Key = fab62b3e5deda7a9c1128663cc81c44b74ab1bfe70bc1c9dec7c7fd08173b80a
+Nonce = a5c1b146c82c34b2e6ebeceb58
+
+Count = 150
+Adata = 5e60b02b26e2d5f752eb55ea5f50bb354a6f01b800cea5c815ff0030b8c7d475
+Payload = 54be71705e453177b53c92bbf2ab13
+CT = 788db949697b8cd9abbc74ed9aa40cd6852dc829469368491149d6bb140071
+
+Count = 151
+Adata = 210c04632341fbfc185bfe3cbf6fe272bbe971104173bcb11419b35ab3aaf200
+Payload = 22197f9ad14591e7a6d5f8b18c969a
+CT = 0e2ab7a3e67b2c49b8551ee7e4998556940dc5a7e44bf10234806d00a012b5
+
+Count = 152
+Adata = d3a205dd017e79a67400a937a20ef049f4c40d73311731f03ab857a3f93bd458
+Payload = 096b2f530933c1273304a6ad423726
+CT = 2558e76a3e0d7c892d8440fb2a38390898f7dbde25b0b70d335df71a06987b
+
+Count = 153
+Adata = 0c9b3ba4faf5fc2f310ad1bab06c4ca13474b714feeffb6ad615c1b850bbd6a3
+Payload = d44fdfd9da3a63c1083afe574e91bf
+CT = f87c17e0ed04de6f16ba1801269ea02fd10d1f21b6b963c05aeda8eb09e272
+
+Count = 154
+Adata = d9bb71ad90152d5c1af358c8501fa89ebd4b17bf4ff43841528cccb79fd791b3
+Payload = 8d836acc13ed83c2b2c706415c9679
+CT = a1b0a2f524d33e6cac47e0173499664491d23d90ff55abca17e9d943b98c7f
+
+Count = 155
+Adata = 69dc21eb6f295b12ba493ee8fe6c40d78af946067ce772db316a3cbf00d3c521
+Payload = 2a68e3fe746f593c1b97cb637079c3
+CT = 065b2bc74351e49205172d351876dc9616886c6b2adc97db5a673846b6662c
+
+Count = 156
+Adata = 095eb52135dc6d9c1f56a2571c1389852482e7aa3edc245a3904a0449db24a70
+Payload = 39799b001ed2c334c269acb0f2328c
+CT = 154a533929ec7e9adce94ae69a3d932441dcae1760db90379bd354fa99164e
+
+Count = 157
+Adata = efd7270e0396392fde8b0ddaab00544cbbd504f4d97d4e90d749d1946de90dcb
+Payload = 42143a2b9e1d0b354df3264d08f7b6
+CT = 6e27f212a923b69b5373c01b60f8a9c7c7deb28bdcf84886ef843216b94449
+
+Count = 158
+Adata = 8bc181ce2e66294e803a8dc3834958b5f173bc2123c0726e31f3fca25b622ed6
+Payload = a3dcf26327059a4245b79a38bb8db6
+CT = 8fef3a5a103b27ec5b377c6ed382a935061ae3cd892ba63c44b809d6d29421
+
+Count = 159
+Adata = c39ec70c2c71633ae0dccc41477ac32e47638c885cf59f34ebd4a096d32f91f9
+Payload = 3d54883449ecca8f153436c25a0a01
+CT = 1167400d7ed277210bb4d09432051e3c9ae69a4c59ff8e251c2fe022d065a9
+
+[Plen = 16]
+
+Key = ee8ce187169779d13e443d6428e38b38b55dfb90f0228a8a4e62f8f535806e62
+Nonce = 121642c4218b391c98e6269c8a
+
+Count = 160
+Adata = 718d13e47522ac4cdf3f828063980b6d452fcdcd6e1a1904bf87f548a5fd5a05
+Payload = d15f98f2c6d670f55c78a06648332bc9
+CT = cc17bf8794c843457d899391898ed22a6f9d28fcb64234e1cd793c4144f1da50
+
+Count = 161
+Adata = a371ca29b92ed676bab5dfc4d78631bb6d9bb23a29f822907084a1f0fe17721f
+Payload = 60d55a8d5ab591a51e87fdf6aaa2ad25
+CT = 7d9d7df808aba2153f76ce016b1f54c68b55bbe42d8c97504b97c34a5f16e6a6
+
+Count = 162
+Adata = 01ec87920b42639d4ba22adb1fbe5138d2849db670a2960fd94a399c1532ed75
+Payload = cbf112e4fb85276c4e09649f3de225b2
+CT = d6b93591a99b14dc6ff85768fc5fdc51017d8706acd676ae99e93d5312a4113c
+
+Count = 163
+Adata = eebd2bbf1e9f6d817cd8062a6a9680e7f10464eefeb50b07cb46b14b9b3fcb2c
+Payload = 865b89aa38ee1b5a3ce56620307e8937
+CT = 9b13aedf6af028ea1d1455d7f1c370d45982f0fe5d951a8c62c87894657301e4
+
+Count = 164
+Adata = 72863362612f146699f6b2f6ec3688f2ca6cb1505af7a309c91c1933e34d516a
+Payload = a8efc37d1b8b51f2a47b21dd14da383d
+CT = b5a7e40849956242858a122ad567c1de5addfddbb59f4985947fb3a9ab56333e
+
+Count = 165
+Adata = 9c9efc6593f96207678db813608f2b8bc33ed1bef974ed77ed7b6e74b621b819
+Payload = d9b0eaaff786165f882f41a98dbc0c35
+CT = c4f8cddaa59825efa9de725e4c01f5d6b651053516673402a57538db1a9ce7e9
+
+Count = 166
+Adata = dc482a051b58d8a3904d3af37c37b51983f634a504451bbba6f77d71337f8e78
+Payload = df49d972b6ebbbb18ee975ac635d847e
+CT = c201fe07e4f58801af18465ba2e07d9d86d772b1a1991b7be6589bbccad36171
+
+Count = 167
+Adata = 51ef065a43caa23faf750b02a41ad6ba701aeb8058f6d8738d6f6b005bec7f60
+Payload = 78318aa5cd16699b77bdcea2fc9d1d20
+CT = 6579add09f085a2b564cfd553d20e4c3569387a1a6bcc826e94012670820576e
+
+Count = 168
+Adata = 88e2a74d2920c89c6a101f5f06d0624a6d5eabd9bdb51395ee3983934c55c73d
+Payload = 8e20d65d02dd9a64379f75b6d8328f2d
+CT = 9368f12850c3a9d4166e4641198f76cee9c788b4aae9b2c6caf0c44aa9bd2ed0
+
+Count = 169
+Adata = ada3ed7db2dabbfbc441ef68a5656e628d6d5bd6c1574369688497179a77601a
+Payload = 97e8d8513af41b97801de98cc4269096
+CT = 8aa0ff2468ea2827a1ecda7b059b6975f1df0f01944641a1b04d753e6ab8d3cc
+
+[Plen = 17]
+
+Key = 7da6ef35ad594a09cb74daf27e50a6b30d6b4160cf0de41ee32bbf2a208b911d
+Nonce = 98a32d7fe606583e2906420297
+
+Count = 170
+Adata = 217d130408a738e6a833931e69f8696960c817407301560bbe5fbd92361488b4
+Payload = b0053d1f490809794250d856062d0aaa92
+CT = a6341ee3d60eb34a8a8bc2806d50dd57a3f628ee49a8c2005c7d07d354bf80994d
+
+Count = 171
+Adata = 4ae414bc888a42141d3060c71c2dbbffd425b6a952806982271a8e756b3c9e24
+Payload = 51eb190c6a9f46e8ec1628b090795470c0
+CT = 47da3af0f599fcdb24cd3266fb04838df13c1c5755a5a240c33b2b890a486aac8b
+
+Count = 172
+Adata = 7b7f78ae1a5ee96fdc49dacd71be1a6ac09a6a162d44dea0172886eca5674e46
+Payload = 25144e807e389bb0e45b6dc25558caf61a
+CT = 33256d7ce13e21832c8077143e251d0b2b4cfca1c19abf447d7bc0898d61885144
+
+Count = 173
+Adata = 03f31c6143b77f6ad44749e2256306b8bf82242f2821fad4075b09b388ba81ca
+Payload = dbe1ee14abfe2ecf4edf6db206cf9886ce
+CT = cdd0cde834f894fc860477646db24f7bff229cc7a390867a245dcb7c434f1db347
+
+Count = 174
+Adata = 030390adb572f2bd2a6a4454fd68236cd1d465574328aa001d553375cc63f8a2
+Payload = db6df31f12bf552f81deff5fa2a373fc22
+CT = cd5cd0e38db9ef1c4905e589c9dea401135361b539f9fe0fb7842907c2326aef63
+
+Count = 175
+Adata = 7294ae94358669f2ada4b64c125b248df7fe86c6715e3b6a7b9bb2bd99392c8a
+Payload = ff2a97b49fcc6a50d4549c979d53ccc51f
+CT = e91bb44800cad0631c8f8641f62e1b382e8ed10943929e7d7bf798b2ae8371aae5
+
+Count = 176
+Adata = 4d1513478fc1fb0a18eb6d2a9324fefbd975ecd1b409025de826bc397462acc1
+Payload = 73ddfa0185200a890b7690a7e3986d8818
+CT = 65ecd9fd1a26b0bac3ad8a7188e5ba7529f92b9e49ab83f113f8949dc9e4a36e0d
+
+Count = 177
+Adata = b26a7ff61bfe94864249af7cc9b4a723627dd4463f5a22f0ca6063769522eab7
+Payload = 5c7604f9ac8fdf30ee5820e5aeb75b65d7
+CT = 4a4727053389650326833a33c5ca8c98e6d0e53223adff22a08e3dddf66fff23e3
+
+Count = 178
+Adata = 960f9a85cfbfb6eab223a4139c72ce926a680ea8e8ecc3088cf123de659ad310
+Payload = d44fdfd9da3a63c1083afe574e91bf01c9
+CT = c27efc25453cd9f2c0e1e48125ec68fcf833f49a42521a7a2367f91bfcc2180b7c
+
+Count = 179
+Adata = 3718467effb5d5dc009aaefce84d8cb4fe8f80eb608f4c678f5d0de02ea11e59
+Payload = bb515dc227abb9acad8fefaa14771bb77b
+CT = ad607e3eb8ad039f6554f57c7f0acc4a4ac08bd395c6807223311070659f550934
+
+[Plen = 18]
+
+Key = 0786706f680c27b792d054faa63f499a8e6b5ddb90502946235bf74c022d772c
+Nonce = f61ef1c8c10a863efeb4a1de86
+
+Count = 180
+Adata = 67874c808600a27fcab34d6f69cc5c730831ad4589075dd82479823cb9b41dc3
+Payload = 6a26677836d65bd0d35a027d278b2534e7df
+CT = d1c1f3c60603359c7d6a707f05ecb2296f8e52f2210b7a798ad5c778ee7cfd7fe6e0
+
+Count = 181
+Adata = e0c27cddf919d3092d9a34766c89a5ae6dcf39fe954d1e6f1a70ddf96805def4
+Payload = 4021ff104ff1dbd91e46db249fd82198b0a1
+CT = fbc66bae7f24b595b076a926bdbfb68538f00923bb5a347af13df12f234fca5f03ef
+
+Count = 182
+Adata = 7ae9eca03f616ab39ebb3be26b848842b4aa584e5c8e5695065ad5af34951175
+Payload = 6a681f164efce199a787bccff223b8ae1a98
+CT = d18f8ba87e298fd509b7cecdd0442fb392c9d03ed7bffac83e890caceb6903d9cab5
+
+Count = 183
+Adata = b47c9bc4eb01c74f5db2e6a293bef80db18c58cf06feef7ee0f8a7a9a51c22bb
+Payload = 7861dac338ba3f8274dca04c8c6f92b6d44c
+CT = c3864e7d086f51cedaecd24eae0805ab5c1d4dd8f30870025b2bd1e2a2511574d3e7
+
+Count = 184
+Adata = f6afd661f218c7426b92ee53e65d14898cd0c78a7e594fcc6ac0e3fb5cab1c9c
+Payload = a3f0473c620d2739d5ba4f7156f88d0fb669
+CT = 1817d38252d849757b8a3d73749f1a123e386046d17f337f3cb49884d94995edbdc9
+
+Count = 185
+Adata = d3802911e341577046cfc61d9043b4af059fb4bef3c6a2ff46ccdcb05670af37
+Payload = 07c535d9456a6ff1e41321150d16dae3f7a3
+CT = bc22a16775bf01bd4a2353172f714dfe7ff25fdc77b43bca254d6459263cdfed8fbb
+
+Count = 186
+Adata = db60720db67a60ca286fe744d46173c231fbcc7deb4c9b0d87d52a2247e06b74
+Payload = 5ee220720a896249efdab2ce418318bb5ebf
+CT = e505b4cc3a5c0c0541eac0cc63e48fa6d6eedd1a1d36c8164c55d55dbf0ff1e9517a
+
+Count = 187
+Adata = 57f70ba5493265b30491decc726354e2065e7971a2efd56db9cf0f79b1d76859
+Payload = 98e4eb0361c8bf40bcbe0539b0850e4c35ff
+CT = 23037fbd511dd10c128e773b92e29951bdaeb476e2ca48fd52bec0539b00744a8a07
+
+Count = 188
+Adata = 4a29b9ad548964942f87f28ba267ec0d0e8f72c73b3823ee57693dd63c2605c1
+Payload = 7f0745bea62479c0080ecec52e37c1e32d72
+CT = c4e0d10096f1178ca63ebcc70c5056fea523fad68c62b81d62f2d490ae74f5bb1465
+
+Count = 189
+Adata = acbd2e9911b3218a230d9db5086d91dccac3fc93fc64b0f4a15d56954906b2b7
+Payload = e99ed2ac6c38e033061b5d85f3e77dd72518
+CT = 527946125ced8e7fa82b2f87d180eacaad4913b15d8000266c61ba5aec898eb35b52
+
+[Plen = 19]
+
+Key = bac55f9847d93325bf5071c220c0a3dfeb38f214292d47b4acb7b0a597fe056f
+Nonce = 05b50c458adbba16c55fcc454d
+
+Count = 190
+Adata = 89ad6ae1e550975eaa916a62615e6b6a66366a17a7e06380a95ea5cdcc1d3302
+Payload = c1a994dc198f5676ea85801cd27cc8f47267ec
+CT = 7c9b138177590edaafec4728c4663e77458ffbe3243faec177de4a2e4a293952073e43
+
+Count = 191
+Adata = dfddb719d00398bf48a6cefd27736389e654a93b8595cd5ac446af1996e0f161
+Payload = 791e232bfb42fb18197adc1967da1a83f70168
+CT = c42ca4769594a3b45c131b2d71c0ec00c0e97f8422f736fc435687634d42254b22fd99
+
+Count = 192
+Adata = 58ef310997dcaf067dd217274921504da6dbf0428a2b48a65fe8a02c616ac306
+Payload = 3d4127942459bb8682e662dfc862467582fa68
+CT = 8073a0c94a8fe32ac78fa5ebde78b0f6b5127f38a96e68ef7dbaef1b460cc0980eacd4
+
+Count = 193
+Adata = 511e5d5e100b595f6b20e791830bca37e23f7b785e482a58405bffe7a632a5b8
+Payload = 0e71863c2962244c7d1a28fc755f0c73e5cbd6
+CT = b343016147b47ce03873efc86345faf0d223c15c5c702a82d468929227502e4e35796f
+
+Count = 194
+Adata = e48dfaa53b6807ea6f01d8dca67960b9f321f7851f324459a9bf61fe0be73abb
+Payload = e0f1cd013e6aea4fa484fc3fa35d348b1a2399
+CT = 5dc34a5c50bcb2e3e1ed3b0bb547c2082dcb8e89188c0940182dd99a902d158c5b0810
+
+Count = 195
+Adata = c12c0423fe36e4c88775dd00b4af267b85b7dd2a37a742a3156923c8917c97a3
+Payload = b1cc1946b4fc1dbd033254cdf536f61e9f9cd7
+CT = 0cfe9e1bda2a4511465b93f9e32c009da874c015849acbb7af1892790300bb84fb0558
+
+Count = 196
+Adata = 4255f8af18df7237e0abe98421aec9634443561752d893aaffe76380e829ef32
+Payload = 87284658928208e3bddca83e3ceb13708d88d4
+CT = 3a1ac105fc54504ff8b56f0a2af1e5f3ba60c3e75aaf3077ac6dfb5454851ec3910de6
+
+Count = 197
+Adata = ab83567833d2f3461b5fbecc0e366694bb5ea00933b2b3e792ec3aefe20325df
+Payload = bdb79f931ef3035a33bdd1b032fd9de8f6b2ba
+CT = 008518ce70255bf676d4168424e76b6bc15aade70f42e3e1f2b5bb58433bd11f5dea1f
+
+Count = 198
+Adata = bd1446ba3185d1c16551730947c22142142caa8cc1c540e89ab734ec297401bc
+Payload = 1f9c3a8eb8bc59f3869e10f73883aa8f8990cb
+CT = a2aebdd3d66a015fc3f7d7c32e995c0cbe78dc564f6248cefe5fc7cfb547c90a558925
+
+Count = 199
+Adata = b87577755d2d9489194f6f7cfabf267dc3433a9c91954e81beb72c5e06870922
+Payload = 5f28809181f9a889894da8d6fe1fde6cce354a
+CT = e21a07ccef2ff025cc246fe2e80528eff9dd5db52249d812f7f235afa0732e984e91b2
+
+[Plen = 20]
+
+Key = 8beedeb85d42c2a7fa6f7237b05acb197dd8e1672471ac878064fe5319eab876
+Nonce = 8479bdfad28ebe781e9c01a3f6
+
+Count = 200
+Adata = 7aebdfd955d6e8a19a701d387447a4bdd59a9382156ab0c0dcd37b89419d6eff
+Payload = 7b125c3b9612a8b554913d0384f4795c90cd387c
+CT = 6cc611d816b18c6847b348e46a4119465104254a04e2dfeeeac9c3255f6227704848d5b2
+
+Count = 201
+Adata = d119f300fbd74e754a200ea2c3f9fabc1466d02078c84245db693eef3f5672a6
+Payload = 8b013f5782d5d1af8dbd451a4202866095dac975
+CT = 9cd572b40276f5729e9f30fdacb7e67a5413d44338d48329997c5981d678b5e24a6f01b0
+
+Count = 202
+Adata = d6204303b86acf62d5ab860ca70161288ede56e3cf017c08dca56fd2d6f8f6fe
+Payload = b2b1d82a5523b72ea366a680922ed3a4624536c4
+CT = a56595c9d58093f3b044d3677c9bb3bea38c2bf2a77e3ab68e0a73519591a33ed098b758
+
+Count = 203
+Adata = 8557e22eb4529b43f16b1f8ae47c714ac8a2c827c1408a47704778b4c5b52601
+Payload = f8c4eb4285d3d7744da52775bb44ca436a3154f7
+CT = ef10a6a10570f3a95e87529255f1aa59abf849c1cff6c24251c2fb7b8604dfa10c60ef4a
+
+Count = 204
+Adata = 8c1a4187efbb3d38332f608f2c8bbe64247d9afa2281ced56c586ecb4ab7a85e
+Payload = 6e7fe35fa39c937a0e6b3a8c072e218650f42b8d
+CT = 79abaebc233fb7a71d494f6be99b419c913d36bb6c3c39f915d081d34559179869b32d81
+
+Count = 205
+Adata = a41bb1f256228302cd0548ae2148ff42774d18c2d6d3e38b36bc4938da13bac3
+Payload = 917b467d841850fc6e648f1bc298a7f9f1ee38ca
+CT = 86af0b9e04bb74217d46fafc2c2dc7e3302725fc9389a6a6a74c6eb0e1f87562469f2082
+
+Count = 206
+Adata = b0b024e20c4f75a6dad54c21a9edbce846792e957878b1c8ed2d916c757e2b3c
+Payload = 2b4314fe1a6bfa786b7cfc13fbee861b348efbf6
+CT = 3c97591d9ac8dea5785e89f4155be601f547e6c03bed3a2f5dfdbfcc0d7ac26c88d1962c
+
+Count = 207
+Adata = 42153925c46fc9d5d328312d62f59bb99fdc4ac479a3386d5f88fefd4b32f577
+Payload = e19fa7f83c79920cbff45c41a9dee8fc99e97396
+CT = f64bea1bbcdab6d1acd629a6476b88e658206ea035ea1d99be344fa1467ee91c73bbca67
+
+Count = 208
+Adata = 37ab2a0b7b69942278e21032fc83eba6cdc34f5285a8b711a08da6acd42299fe
+Payload = 53e0475cf492b3d39dad600f5c58eb0bd0021554
+CT = 44340abf7431970e8e8f15e8b2ed8b1111cb08627936ec10a81b36768b606e9a38b2f4c5
+
+Count = 209
+Adata = 4a17522da707b4b2587a0ae367a2cd2831bb593a18ef442a7977eda6de045878
+Payload = c119a383d9a3d4bff4270a1d22076b346db5f61c
+CT = d6cdee605900f062e7057ffaccb20b2eac7ceb2a11575ae03ea8a57bbe4a67c060367b74
+
+[Plen = 21]
+
+Key = c3a0c126cad581012151c25cf85a44472c23f83b6095b6004f4f32cd60ec2db2
+Nonce = 94ab51ce75db8b046d6ab92830
+
+Count = 210
+Adata = 2a243246bfe5b5ab05f51bf5f401af52d5bbaa2549cf57a18e197597fe15dd8c
+Payload = 73b09d18554471309141aa33b687f9248b50fe3154
+CT = b7e8264ca70fd2a4fb76f20a8ad5da3c37f5893fb12abeeaef1187f815ca481ed8ddd3dd37
+
+Count = 211
+Adata = 0595306eb7441622a49800edee0134492d82320707fceba902af2e0c95fe634a
+Payload = b64d00f3a4df754fa4ee6376922fb67ccce0c6209f
+CT = 7215bba75694d6dbced93b4fae7d95647045b12e7accc2b55011dbe92ce7619e0ad48b4ccf
+
+Count = 212
+Adata = bd439dbefec589e120fb4f9825b315bf86523b85c61791cd4da4c8d474ba2714
+Payload = 2b11d1ac74ffe701ec733d32085b1054132726e622
+CT = ef496af886b444958644650b3409334caf8251e8c71e8b1f4d70d8f4c7df4f22847d36b394
+
+Count = 213
+Adata = cfebe1cf82267394065bcecfada6709c6c35a3ac835644f560d4c9a8c1848364
+Payload = a88f22424643a523aa3d7d88f4364f1290f49dd0a2
+CT = 6cd79916b40806b7c00a25b1c8646c0a2c51eade47a85e76a9d07b7b361ca56d53c34cda50
+
+Count = 214
+Adata = 7a37255b682766a0bfecf78e5162528885a339174c2a49325739d2bd8877e64f
+Payload = c81427bc84c6a3cfefd4c4cb210fe82212977e1947
+CT = 0c4c9ce8768d005b85e39cf21d5dcb3aae320917a2fddb010e7508ad03ad287068ecee6020
+
+Count = 215
+Adata = 619f2ae80070e278615466a3fd6c9acb7b510c5679bed7038889c77e78d8bd32
+Payload = 28c4d6de3e2ce51b849b135d9cfd3084f0e3155447
+CT = ec9c6d8acc67468feeac4b64a0af139c4c46625aa2ddea785e6c470c52c4fdf432fd78b66e
+
+Count = 216
+Adata = b2571e56f66a857daffbdc99370ceddd4a7bed3867d600cc797000a3b7b57a9d
+Payload = 4c88151cafef75832bacef43a06e862349d56b67ee
+CT = 88d0ae485da4d617419bb77a9c3ca53bf5701c690b91232cfbd7ffff252498b35274fb2995
+
+Count = 217
+Adata = db409636e3e3bcd606a91aeb7592009896f9ad2c4cc6b7f578e6ad59c0f8fa22
+Payload = 572855e22ce89bc2bcf09cb15a1765d99973449d61
+CT = 9370eeb6dea33856d6c7c488664546c125d633938472b2c50e5e391ad104f9ee33b94f2872
+
+Count = 218
+Adata = 62c89a835721207a182968c516dc8be45774ec846e8dcab9ab8611888f2a76a8
+Payload = 89ce46b3de3afaf2518d419b1a2ac24cabca269a96
+CT = 4d96fde72c7159663bba19a22678e154176f5194732d69c5d6db1b130102af3dae0690673b
+
+Count = 219
+Adata = 33f30ddd83002eea50fd4a8fae39d0980a04160a22ac88b755ac050f1d1f8639
+Payload = edf1682a626e9fbf3d57bb260e0876c6f92ba5b114
+CT = 29a9d37e90253c2b5760e31f325a55de458ed2bff1489903365970c2673c9fd457e1077aad
+
+[Plen = 22]
+
+Key = 9cdebaeee8690b68751070691f49593668a6de12d3a948b38ddbd3f75218b2d4
+Nonce = af1a97d43151f5ea9c48ad36a3
+
+Count = 220
+Adata = f5353fb6bfc8f09d556158132d6cbb97d9045eacdc71f782bcef62d258b1950a
+Payload = 3cbb08f133270e4454bcaaa0f20f6d63c38b6572e766
+CT = 3966930a2ae8fdd8f40e7007f3fde0bd6eb48a46e6d26eef83da9f6384b1a2bda10790dadb3f
+
+Count = 221
+Adata = e3a1555ffe5f34bb43c4a2dae9019b19f1e44a45fb577d495d2a57097612448d
+Payload = 946e86795c332031e2d1ee09d3d4a101fb6800d00911
+CT = 91b31d8245fcd3ad426334aed2262cdf5657efe408a5587bdd120a7d08cd3841cb117af444fb
+
+Count = 222
+Adata = 9c5d43c1a1269cde199509a1eff67cc83a1759b71c9e7a6ee99f76b98c6e23a6
+Payload = b76ce2ab0065ba1c0a754494991c8c452cb416f18ab1
+CT = b2b1795019aa4980aac79e3398ee019b818bf9c58b0545b32f81dcf03e2bcc2aaf62ad366e97
+
+Count = 223
+Adata = b07452a7900a289b91b2771dfdd5108852536659aa259def7b41e38f80bd03ab
+Payload = a3e0d8d0784155bfc45769c52711d4fa68e8bc390c20
+CT = a63d432b618ea62364e5b36226e35924c5d7530d0d94fea17d78533bc9e022dbfb460afdf499
+
+Count = 224
+Adata = 6b30f55c3101540523a92380390f3f84632f42962061b2724cde78ac39809397
+Payload = 6e6a88abbb52a709b47365ad6aa8016fa9a03a9bd834
+CT = 6bb71350a29d549514c1bf0a6b5a8cb1049fd5afd98056defc6dcaeec80b1c639350ab6f1fde
+
+Count = 225
+Adata = 9fc62d14f8b7a6026509275cff80312ff1ade2b5d9c274cb72a506a571439fc1
+Payload = eba1810d537041821121aeff8e0914ac26a550072c8c
+CT = ee7c1af64abfb21eb19374588ffb99728b9abf332d389d37b7251fb8c0ef2b37c36d51219d0f
+
+Count = 226
+Adata = 6b9389cc42113d639fd2b40cbc732ae0dc7c14513b88b36b45a6ea5a06fe4d2b
+Payload = dfc6692cd2442e5ff1f918c8812a27f81d107d16a12f
+CT = da1bf2d7cb8bddc3514bc26f80d8aa26b02f9222a09bd279d9da4437c8a2a252436508134c56
+
+Count = 227
+Adata = db72d98d63fc10acff7dceec0e2691a80ecee50a0e957ad166c77952a50318bd
+Payload = 9ad338cbfd1b52e6ae4178f05e00062274f8b0b25eae
+CT = 9f0ea330e4d4a17a0ef3a2575ff28bfcd9c75f865f1a63943543bc1c5f5991ecc5964a288f79
+
+Count = 228
+Adata = e98b710c47a4d12a73cd8aa2613fc2910c16f4195ea7f15650132493521d19be
+Payload = 9f5a05db89e0e336da066ce81b79ad9be1d0ec4fb7b8
+CT = 9a879e20902f10aa7ab4b64f1a8b20454cef037bb60c0a49ee2b7ceddcbd28abb24b77d5edee
+
+Count = 229
+Adata = 527817316fc48b105f8ab178dd2db1fefa09c50461aa9d8bdf3c03482343bbf9
+Payload = 58f31e5770070a5d4031fb795dc2d298561d3559960d
+CT = 5d2e85ac69c8f9c1e08321de5c305f46fb22da6d97b9b099a68cfa3572d974e03232e09f37fb
+
+[Plen = 23]
+
+Key = d34264a12c35cdd67ac105e2826b071e46f8131d1e325f8e0ae80a6447375135
+Nonce = 3891e308b9f44c5b5a8b59004a
+
+Count = 230
+Adata = 0cda000ed754456a844c9ed61843deea9dadf5e723ea1448057712996d660f8c
+Payload = 79ac1a6a9eca5e07ce635bfd666ef72b16f3f2e140d56c
+CT = 1abcc9b1649deaa0bfa7dcd23508282d9c50ca7fee72486950608d7bcb39dcf03a2cab01587f61
+
+Count = 231
+Adata = 3fb6ddb76809b8e6d703347664ef00a365955124c603900d5c8d4ff476138252
+Payload = 76d12e3c4c5d990bf563c60aa4999e52998d887f97477f
+CT = 15c1fde7b60a2dac84a74125f7ff4154132eb0e139e05b1c4fb40e5c8bc37152a173d4bbb18c3e
+
+Count = 232
+Adata = d9fc295082e8f48569eb073ac1b9566246728fc62ccaab4a5667c472c98b2626
+Payload = a027c28fbe22111fd4c8a226cfe8531c16d7790d561eca
+CT = c33711544475a5b8a50c25099c8e8c1a9c744193f8b9ee019c359008adae3070b5a543ead0effb
+
+Count = 233
+Adata = 7a459aadb48f1a528edae71fcf698b84ed64dc0e18cc23f27ab47eeabeaf833f
+Payload = fa597e37c26c38694abdcf450f9edc529160fa0d651979
+CT = 9949adec383b8cce3b79486a5cf803541bc3c293cbbe5dbd099ab134756b90746762a92a4a9f7f
+
+Count = 234
+Adata = 484207909dec4c35929ebe82fcacf20d2af6d850bd69364ebac9557adeadfbd4
+Payload = 9e4c8aa9b58a8eabc5586892f5541000b43f17d9a051a0
+CT = fd5c59724fdd3a0cb49cefbda632cf063e9c2f470ef684fa4f6adfec85d055310107ba89198afa
+
+Count = 235
+Adata = 88b5448372548e6aab1b262630a28a471d285514703f1bdb10c695850e18fe6d
+Payload = 7d9582cf9e3bb9ee34dce965f56b08e716589486b0641c
+CT = 1e855114646c0d4945186e4aa60dd7e19cfbac181ec338915d23eb2e952afcc89fbddb567d9d75
+
+Count = 236
+Adata = 0e71863c2962244c7d1a28fc755f0c73e5cbd630a8dbdeb38842d7795d830d2e
+Payload = 5a387e7cc22491fc556fe6a0c060b4911d01f0c11f801e
+CT = 3928ada73873255b24ab618f93066b9797a2c85fb1273aaad6c31828314e24198f005955ca8f5e
+
+Count = 237
+Adata = 2aa7a28da38c42fda2e578d9d6340cd8e80b9b32047c3db296d0640d517b0872
+Payload = 87946e910059cbaf48df63b220f397049c65ca10cd1920
+CT = e484bd4afa0e7f08391be49d7395480216c6f28e63be04e531ebbadccfe47182b41904bbfebcfe
+
+Count = 238
+Adata = 3382051c268891da04e6ca73adcead4029f6a1593be4acfe3968e7351a6a2fb5
+Payload = c62f67d208f1c8ffd5d57df9de15ef54f97fbc07d1630a
+CT = a53fb409f2a67c58a411fad68d73305273dc84997fc42e7c582414154236c09ee704cf4a5de411
+
+Count = 239
+Adata = c352828b1920e53bbb60f2ea6a5f15639659e6f3243405c26f6e48628d5519a9
+Payload = 697e73eaaf562d31bdbf7ce9e78c7426fe1c87e421def9
+CT = 0a6ea03155019996cc7bfbc6b4eaab2074bfbf7a8f79dd57c9990029c89d1b37988745fa5737a3
+
+[Plen = 24]
+
+Key = 4ad98dbef0fb2a188b6c49a859c920967214b998435a00b93d931b5acecaf976
+Nonce = 00d772b07788536b688ff2b84a
+
+Count = 240
+Adata = 5f8b1400920891e8057639618183c9c847821c1aae79f2a90d75f114db21e975
+Payload = 9cea3b061e5c402d48497ea4948d75b8af7746d4e570c848
+CT = f28ec535c2d834963c85814ec4173c0b8983dff8dc4a2d4e0f73bfb28ad42aa8f75f549a93594dd4
+
+Count = 241
+Adata = 1ae8108f216defea65d9426da8f8746a3ae408e563d62203063d49bf7e0d6bdf
+Payload = 2b223932fb2fd8433e4b1af9e8234a824569a141f6c96a69
+CT = 4546c70127abacf84a87e513b8b90331639d386dcff38f6f4de907a59c5e4d3f21e1348d7cdf92b6
+
+Count = 242
+Adata = 460f08114b1015fe8b7a9b5dd1b9e6a3d28367c4bd15f29b13c02a8cb9a53968
+Payload = 4d57cbe4a7e780d4ed17267d5ebc91750c2f0209e0444bd2
+CT = 233335d77b63f46f99dbd9970e26d8c62adb9b25d97eaed4ff4239544e2f354d6c6837cd9c23b884
+
+Count = 243
+Adata = 860f4428259d9c5b17698cc95363db6cfee603258582e3a3e8feb886599d4ac4
+Payload = fda8665f87c618646a89c7abdca275fd10c31453ad4b9c99
+CT = 93cc986c5b426cdf1e4538418c383c4e36378d7f9471799f3f6c6f7cc494201069344e2d6d41bd9b
+
+Count = 244
+Adata = 1b43c482f83780c21583f88e5afcf6938edd20f21b74d895161b60c27a6a42f0
+Payload = 98104fd3f3413ad1f57ef4912cb50097dca379a58c47b0d2
+CT = f674b1e02fc54e6a81b20b7b7c2f4924fa57e089b57d55d43787a15352cfceb028202c8730beaa7a
+
+Count = 245
+Adata = b082ccd964617c27a5607b7324faad237ee53acfc18c35502dbf7c1937a9dfcb
+Payload = b46b343e64d2d70e0bd909dbb3f6bedf7e4adc74321be526
+CT = da0fca0db856a3b57f15f631e36cf76c58be45580b210020f3a0ca3da647eb31893e867956097983
+
+Count = 246
+Adata = b8539ba93ef17254ec1d8d62e8f4eae4d41ee1e75345bf90c9cbb26c63bce501
+Payload = 8e12620bb575e6b167b085255b2b5631ff28e04cbef8826d
+CT = e0769c3869f1920a137c7acf0bb11f82d9dc796087c2676be663fbbebbc251b9f1760afa49e89e71
+
+Count = 247
+Adata = b6b09463b5ef5ead1f17f4021693a0d8452e98dcbb8e7590f9fde6394970a6f8
+Payload = 792aaa23b923d1b53173fe19853b9aa402a301d48529873e
+CT = 174e541065a7a50e45bf01f3d5a1d317245798f8bc136238da90cd87e9d9ca5d85430a150e682752
+
+Count = 248
+Adata = 390f6de14d5e1f2f78dbe757c00b89209d0cf8bc48cbbea035779f93de357905
+Payload = ddc5b4e48970ebd72869be6998e9103c014475e8ae6ea29c
+CT = b3a14ad755f49f6c5ca54183c873598f27b0ecc49754479afc0cc4601afb61efa7059cfe49ec9dde
+
+Count = 249
+Adata = 1d75c9e7acb09932db332498d30f82e4009025cb1827047c59a8f97812b568a4
+Payload = d2b66096c475a77648c27235e6972ba8f18761330d3c6adf
+CT = bcd29ea518f1d3cd3c0e8ddfb60d621bd773f81f34068fd9cf7474962c3602dcfcb50039f43e3d6f
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.rsp
new file mode 100644
index 0000000000..0e56a03d42
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.rsp
@@ -0,0 +1,1589 @@
+# CAVS 11.0
+# "CCM-DVPT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:25 2011
+
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 4ae701103c63deca5b5a3939d7d05992
+
+Count = 0
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 02209f55
+Result = Pass
+Payload = 00
+
+Count = 1
+Nonce = 3796cf51b87266
+Adata = 00
+CT = 9a04c241
+Result = Fail
+
+Count = 2
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = f5f915df
+Result = Fail
+
+Count = 3
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 7a3c3499
+Result = Fail
+
+Count = 4
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = f09c2986
+Result = Pass
+Payload = 00
+
+Count = 5
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 4ae97e71
+Result = Fail
+
+Count = 6
+Nonce = 06d102a9328863
+Adata = 00
+CT = ecb38c8b
+Result = Fail
+
+Count = 7
+Nonce = c288b810fb5334
+Adata = 00
+CT = 9c4dc530
+Result = Fail
+
+Count = 8
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = 67299ef6
+Result = Fail
+
+Count = 9
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = b0538d02
+Result = Fail
+
+Count = 10
+Nonce = 44077341139bf9
+Adata = 00
+CT = 88200ea8
+Result = Fail
+
+Count = 11
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 19867aa5
+Result = Pass
+Payload = 00
+
+Count = 12
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = 3b392a52
+Result = Pass
+Payload = 00
+
+Count = 13
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = 1c5e47e0
+Result = Pass
+Payload = 00
+
+Count = 14
+Nonce = 9dc18698731b27
+Adata = 00
+CT = 97a56b8b
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3
+
+Count = 15
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 75d582db43ce9b13ab4b6f7f14341330
+Result = Pass
+Payload = 00
+
+Count = 16
+Nonce = 3796cf51b87266
+Adata = 00
+CT = 3a65e03af37b81d05acc7ec1bc39deb0
+Result = Fail
+
+Count = 17
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = efc5721e0b9e4c3c90deab0e1d5c11bd
+Result = Fail
+
+Count = 18
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 91b4b779823f4f0e3979ced93b99736c
+Result = Fail
+
+Count = 19
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = e2e87ca82523ccfeb416b42af9d9aadc
+Result = Pass
+Payload = 00
+
+Count = 20
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 7b85fd105cc960df86ad86846d178274
+Result = Fail
+
+Count = 21
+Nonce = 06d102a9328863
+Adata = 00
+CT = ffa140be27b25f307a6efd9697d66c9b
+Result = Fail
+
+Count = 22
+Nonce = c288b810fb5334
+Adata = 00
+CT = ed356542e0a804a724bfaa422e98a970
+Result = Fail
+
+Count = 23
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = e31dd8dc920fe7900e1b1817fe845c7d
+Result = Fail
+
+Count = 24
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = ae5a0777f03bbf541f305d00acff0396
+Result = Fail
+
+Count = 25
+Nonce = 44077341139bf9
+Adata = 00
+CT = 957dca58616c1cbe99f94fd8f7c257d9
+Result = Fail
+
+Count = 26
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 0e150af422f6da238bb476810b2d5bc2
+Result = Pass
+Payload = 00
+
+Count = 27
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = 8e1150756ff3a733a1274470f072b74c
+Result = Pass
+Payload = 00
+
+Count = 28
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = a1f70df3fa9cfeb95f869b3fe08466e0
+Result = Pass
+Payload = 00
+
+Count = 29
+Nonce = 9dc18698731b27
+Adata = 00
+CT = fdf3f6c177aa1d71fe3474a5a2eb6bb1
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3
+
+Count = 30
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 90156f3f
+Result = Pass
+Payload = 00
+
+Count = 31
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = 88909016
+Result = Fail
+
+Count = 32
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = de547d03
+Result = Fail
+
+Count = 33
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = ea4bad52
+Result = Fail
+
+Count = 34
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 1bc82b3d
+Result = Pass
+Payload = 00
+
+Count = 35
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = 92e72250
+Result = Fail
+
+Count = 36
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = e81f0647
+Result = Fail
+
+Count = 37
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = 7cb906ec
+Result = Fail
+
+Count = 38
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = d60f815b
+Result = Fail
+
+Count = 39
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = d3d4f3b0
+Result = Fail
+
+Count = 40
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = a9df97ad
+Result = Fail
+
+Count = 41
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = 36a37a59
+Result = Pass
+Payload = 00
+
+Count = 42
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = dba02a36
+Result = Pass
+Payload = 00
+
+Count = 43
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = 25dcb3c5
+Result = Pass
+Payload = 00
+
+Count = 44
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = 1d2832d0
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd
+
+Count = 45
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = fb04dc5a44c6bb000f2440f5154364b4
+Result = Pass
+Payload = 00
+
+Count = 46
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = 5447075bf42a59b91f08064738b015ab
+Result = Fail
+
+Count = 47
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = fdc992847f0815fac67aa935b35208ed
+Result = Fail
+
+Count = 48
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = 2cabd690a45e59854b7587b26dd77f8e
+Result = Fail
+
+Count = 49
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 3dacc71169f6da77ec91ff1d2f649ed1
+Result = Pass
+Payload = 00
+
+Count = 50
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = 97a2eb170ef03fa12124f1315e3b694f
+Result = Fail
+
+Count = 51
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = 94d85a83169d8dc76f58baf4d63ecfee
+Result = Fail
+
+Count = 52
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = d3903c6289ca3684b8ce1174c23153a4
+Result = Fail
+
+Count = 53
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = 5cbac5c418374a68bd7085454c4b0c13
+Result = Fail
+
+Count = 54
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = 26317f6b8b0130097441ed04b8009aef
+Result = Fail
+
+Count = 55
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = b82ab6f3bbf59b6caafc54f05570f74e
+Result = Fail
+
+Count = 56
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = 1ae34207e74c8c78890ae17e320e84bd
+Result = Pass
+Payload = 00
+
+Count = 57
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = 5c5fa254c0be503b02caffade6b85259
+Result = Pass
+Payload = 00
+
+Count = 58
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = 9340266730ea36207bb734819d3553e9
+Result = Pass
+Payload = 00
+
+Count = 59
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = ec17cccf33bd9a0d4ce7aa20690c1333
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd
+
+Count = 60
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = a90e8ea44085ced791b2fdb7fd44b5cf0bd7d27718029bb703e1fa6b
+Result = Pass
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 61
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = 50aafe0578c115c4a8e126ff7b3ccb64dce8ccaa8ceda69f23e5d81c
+Result = Fail
+
+Count = 62
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = 512ed208bf10d57406537e94d20a5b6e2e9ab0683dfdc685869a97f0
+Result = Fail
+
+Count = 63
+Nonce = 9cbce402511b89
+Adata = 00
+CT = af72db9cd9d6f46607d6f9542ca69988dd15255c5c91171c838e7f95
+Result = Fail
+
+Count = 64
+Nonce = 123a0beace4e39
+Adata = 00
+CT = 47d71409a03c330be9451b3f92c9d21c584391ad1010e9d609b89801
+Result = Pass
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 65
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = e562c7af0384ea16431ca20934a293a058d722cbfc3186c8eaf5f825
+Result = Fail
+
+Count = 66
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = 004d9d89c401aa79919c2805fcd5de69316e191df56426c05ec1aa6a
+Result = Fail
+
+Count = 67
+Nonce = f477f754d7ee76
+Adata = 00
+CT = d623673d7f6d57c208bde112ca858561f3af5cc2bf5de926f3586c6f
+Result = Fail
+
+Count = 68
+Nonce = 040a257dede70e
+Adata = 00
+CT = fd4733d158b5630f4f6c03ab26b11bff0cbe0d5d3df99a735fa40618
+Result = Fail
+
+Count = 69
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = d352cb996c3075ff367a8dcacbbae46a12fbef08aa96ec835bf4f930
+Result = Fail
+
+Count = 70
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 31730fac20e21eca0aef591faa9fa90b3c058e32af1ce48a66f0496e
+Result = Fail
+
+Count = 71
+Nonce = f67b98efd39b55
+Adata = 00
+CT = dd175905a7ea3aef9fce068e6cb78e9cc60519755a178c77b753181c
+Result = Pass
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 72
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = 8ad6b76f54392ee0f2834f09142545bcde9bf03d04d64aa10876f2da
+Result = Pass
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 73
+Nonce = 098e053fa08043
+Adata = 00
+CT = 808eb3e04c39abde64674f0f7716dde11699cff8dd367c4cd4f7fc07
+Result = Pass
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 74
+Nonce = 4bf48328725514
+Adata = 00
+CT = e074d13aad43f7b2364d47db0a02326641ca3b2ad61a1c49973a2712
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = 197afb02ffbd8f699dacae87094d5243
+
+Count = 75
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 24ab9eeb0e5508cae80074f1070ee188a637171860881f1f2d9a3fbc210595b7b8b1b41523111a8e
+Result = Pass
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 76
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = 7ebfda6fa5da1dbffd82dc29b875798fbcef8ba0084fbd2463af747cc88a001fa94e060290f209c4
+Result = Fail
+
+Count = 77
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = cbf133643851f91ddc7a1e19a0c21990459f2b7728da58f5cf3b8e6c8aeb5eeb0a5efb3700be45a2
+Result = Fail
+
+Count = 78
+Nonce = 9cbce402511b89
+Adata = 00
+CT = 0de7567a945c0af4a2291a651de411e8d0438508f2d4da80f7bd61a0158accbca28913e39fe80906
+Result = Fail
+
+Count = 79
+Nonce = 123a0beace4e39
+Adata = 00
+CT = d43035cdb5a1868aa430e8b41a1dc57a639087238e38bd628feeda2e8f249dd93a8358def7639875
+Result = Pass
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 80
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = 389547260b354a6cbc909de057d367677049e80613877f6fbf19f89da977e56f308373c616299ad4
+Result = Fail
+
+Count = 81
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = a95aa33483ed3711470025394616bf98fe624fbca8aa6fbc21366b9da457ede2a673351475b53d41
+Result = Fail
+
+Count = 82
+Nonce = f477f754d7ee76
+Adata = 00
+CT = 3d53b6ab8925f429ae14a0065cd203d4f9deddd402a79ac6d889a7cae55efd71b369cd6d43ef363b
+Result = Fail
+
+Count = 83
+Nonce = 040a257dede70e
+Adata = 00
+CT = d5e6e82cb5f8034a89e58adf8298476253f18981bcb3b0364be7f19463dd330a4b9f3cbb30b88fa5
+Result = Fail
+
+Count = 84
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = 02f69107d62ff77145c7d57684c70ba671d55f1c63bb2ad8c2df063f7fdbae27f0736a37fd065fb4
+Result = Fail
+
+Count = 85
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 64ec2f321111da9c5389e8255bfe69876d4f548f94cacd529b45d54cc24cff1b1d8aa1df32fbd81a
+Result = Fail
+
+Count = 86
+Nonce = f67b98efd39b55
+Adata = 00
+CT = 37d63c2bbf44d2eb155ecc1a844841d5c33f1a6d443419330217a4f1f4fb302257b0de7c9da2e750
+Result = Pass
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 87
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = 33e0dce4410e51bed5323ea49490207084ac91732bae429236a305d520a1a24930a70a311aa3695d
+Result = Pass
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 88
+Nonce = 098e053fa08043
+Adata = 00
+CT = 1d732c334319bd775e7cf93dbdc4204bbdb58192be08280481e3d64ed546b6b70ee088a693f55fbb
+Result = Pass
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 89
+Nonce = 4bf48328725514
+Adata = 00
+CT = c92fc2f0d24593f67d9c09d326158a8138237c4096093f0d737719dd84ccfb397a4f61b70c85262a
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = 197afb02ffbd8f699dacae87094d5243
+
+Count = 90
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 4a550134f94455979ec4bf89ad2bd80d25a77ae94e456134a3e138b9
+Result = Pass
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 91
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 118ec53dd1bfbe52d5b9fe5dfebecf2ee674ec983eada654091a5ae9
+Result = Fail
+
+Count = 92
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = 6b0fea26e4dfe902b5e876c7ba92afbad8aa52d3c1d00ae578b6bcc4
+Result = Fail
+
+Count = 93
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = 640c740e2b8af851712a05948ecee055b25b145ccb82ca58ac542b09
+Result = Fail
+
+Count = 94
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 05f20b2ae70fcb0ea79aa1845c15b899a799ca60f51e6c296413020a
+Result = Pass
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 95
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = 9fa576a8a5c72468afa372338cbbc33fef81ad5a873eb38a142d5636
+Result = Fail
+
+Count = 96
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = 8d26582c74b2b4d960ee9e417c6395daafaebb3aff45d477f3757b6a
+Result = Fail
+
+Count = 97
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = cb62a13e38e17cc6635e409c922956ece38f593189a51b99a7001a16
+Result = Fail
+
+Count = 98
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = f3e29b792423c7fbe743a3b2f890a2bff29519f3636a6232050e9225
+Result = Fail
+
+Count = 99
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = 136e60d6714d906d1f4c02b7bdbb5f3ccdd2165306912dec850ec9f0
+Result = Fail
+
+Count = 100
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = 49b6d0b6eeff74af0de70072d9ccdc68a0ee36a5ddbf098b4eb95533
+Result = Fail
+
+Count = 101
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = a2a59041c3f78f6e10c3045118e8a475945e24c85b02abc40f8fb949
+Result = Pass
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 102
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = 19b4ad222795326cb031cfdb07b652dbf64ca5db5ff5d6d569d8ab41
+Result = Pass
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 103
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = 76b66b908657f4df8a329c34ccdde50ae7fc71c4a718b712f00fe764
+Result = Pass
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 104
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = 20df4662ce6c8c4ce49b14fa791e41ff8598ec93d8a825e879f9eb72
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 90929a4b0ac65b350ad1591611fe4829
+
+Count = 105
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 4bfe4e35784f0a65b545477e5e2f4bae0e1e6fa717eaf2cb6a9a970b9beb2ac1bd4fd62168f8378a
+Result = Pass
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 106
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 0c56a503aa2c12e87450d45a7b714db980fd348f327c0065a65666144994bad0c8195bcb4ade1337
+Result = Fail
+
+Count = 107
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = 5f69d6c21f771eb98dc724f891f530b1c045f49a054de103a85f868739404b64a7cbdd61b577c388
+Result = Fail
+
+Count = 108
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = d335ba572520c336f711edf27ea738ba5e6b0d772ea443b8b2b164f3c255b699cbf75330d96c3c13
+Result = Fail
+
+Count = 109
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 9fa846ef8d198c538f84f856bab8f7f9c3bed90b53acb6a32658e077687315eaf11458bdf6e3c36a
+Result = Pass
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 110
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = b7095030acdc5fbb8fea2c24717c1c236231f9737bcc78f463db3756abba1feef626a956794d7e56
+Result = Fail
+
+Count = 111
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = d6911d5831163c8ebad0916af1833051b885aae822f9f6657d6fee1de626bc7c93f2caa27a3ecaa0
+Result = Fail
+
+Count = 112
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = 6b10a098c96c2bbf9aeb5c9adcf91e4812838dff319f8be989e2d235192f33ba0f357492112d98f4
+Result = Fail
+
+Count = 113
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = aecd11cbac04e1f79b0fd24052c8cedf393dce9df350d24f800b81e834ea5dd2bdc2c688d9505359
+Result = Fail
+
+Count = 114
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = d3a7a25f71b1988482dc852ed713d55abdcc4bb1129ddcae430889cd5c97343cc0dedfbd62e6b6eb
+Result = Fail
+
+Count = 115
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = 368e1574a433d78d0276ce4a1cacfba834a216693536c00b15acded53c41010554e1c1fe937a7605
+Result = Fail
+
+Count = 116
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = 99e40b3c67aca95dd4462c20cbd6b2741e7033fc4f41a975c9390fbdb9ec416267096ccbf2c148e5
+Result = Pass
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 117
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = de079418c25ba67e5fda009998e3fce61bfdc3b7787cf06655c18ae38b7ee7f00f96cfca4fe9a2ef
+Result = Pass
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 118
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = fbab64d8dd8b6e33c7cc6124cd65f004d7247277fe98d5d3b35357a35ff9e58e18d6d80df9fc335d
+Result = Pass
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 119
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = 372b9af0655df2d0c830b4949a2d2faa8db251ee922a3bff9aba89639f4033be9ba9f3c101acc1bd
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 90929a4b0ac65b350ad1591611fe4829
+
+Count = 120
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 782e4318
+Result = Pass
+Payload = 00
+
+Count = 121
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = a04f270a
+Result = Fail
+
+Count = 122
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 97dfd257
+Result = Fail
+
+Count = 123
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 6c202a1c
+Result = Fail
+
+Count = 124
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = 1be535a0
+Result = Pass
+Payload = 00
+
+Count = 125
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 4fb6617d
+Result = Fail
+
+Count = 126
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = c056bd3e
+Result = Fail
+
+Count = 127
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = 87048576
+Result = Fail
+
+Count = 128
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = ea8c0407
+Result = Fail
+
+Count = 129
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = 41c12dc5
+Result = Fail
+
+Count = 130
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = de84cf5c
+Result = Fail
+
+Count = 131
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = e617e006
+Result = Pass
+Payload = 00
+
+Count = 132
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = b7909395
+Result = Pass
+Payload = 00
+
+Count = 133
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = 8a05d2ea
+Result = Pass
+Payload = 00
+
+Count = 134
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 8643ba47
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b
+
+Count = 135
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 41b476013f45e4a781f253a6f3b1e530
+Result = Pass
+Payload = 00
+
+Count = 136
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = f9f018fcd125822616083fffebc4c8e6
+Result = Fail
+
+Count = 137
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 534cc67c44c877c9c908071ee1082f4c
+Result = Fail
+
+Count = 138
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 201c0ef2ddaa51b645911b5c37d76e95
+Result = Fail
+
+Count = 139
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = ec774d9000763bba3a5ac307418827b2
+Result = Pass
+Payload = 00
+
+Count = 140
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 75798c3fe5202f0e33c9183c837aeaf5
+Result = Fail
+
+Count = 141
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = 32601de5960c11c925444b5c47d42289
+Result = Fail
+
+Count = 142
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = 4c1cd6a774c8e6f4e261db1f73b0aa20
+Result = Fail
+
+Count = 143
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = 8bd9c00ff23310216bbd24981c1e2cf7
+Result = Fail
+
+Count = 144
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = 174efd089409f9932b8e631965e762a6
+Result = Fail
+
+Count = 145
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = 8de80f620bd41eee6a58925dc8404bfa
+Result = Fail
+
+Count = 146
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = 0b9d79e8e33ec45532af5515a99f05df
+Result = Pass
+Payload = 00
+
+Count = 147
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = 1583e1e5a86001bbcec62292ccfd4d48
+Result = Pass
+Payload = 00
+
+Count = 148
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = b72caac6362e68e445f69f605f21e0a2
+Result = Pass
+Payload = 00
+
+Count = 149
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 352769a19ac75b8a116be031b33d6449
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b
+
+Count = 150
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 9f69f24f
+Result = Pass
+Payload = 00
+
+Count = 151
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = e17afaa4
+Result = Fail
+
+Count = 152
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = 07155b7e
+Result = Fail
+
+Count = 153
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = d538cf2f
+Result = Fail
+
+Count = 154
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = c283466f
+Result = Pass
+Payload = 00
+
+Count = 155
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = aa8d8098
+Result = Fail
+
+Count = 156
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = a44b69b0
+Result = Fail
+
+Count = 157
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = f395733f
+Result = Fail
+
+Count = 158
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 1e9e9237
+Result = Fail
+
+Count = 159
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = e9d2a722
+Result = Fail
+
+Count = 160
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = a90fc438
+Result = Fail
+
+Count = 161
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = 48f3a1ec
+Result = Pass
+Payload = 00
+
+Count = 162
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = 24763def
+Result = Pass
+Payload = 00
+
+Count = 163
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = 63394bee
+Result = Pass
+Payload = 00
+
+Count = 164
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = d79b1686
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = f9fdca4ac64fe7f014de0f43039c7571
+
+Count = 165
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 1859ac36a40a6b28b34266253627797a
+Result = Pass
+Payload = 00
+
+Count = 166
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = edf8b46eb69ac0044116019dec183072
+Result = Fail
+
+Count = 167
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = 66622ac26c7227a0329739612012737c
+Result = Fail
+
+Count = 168
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = e4c9e86493ee78b1cbf6e55e94731b63
+Result = Fail
+
+Count = 169
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = 8b5bfe6b5b5552007300bae71172612f
+Result = Pass
+Payload = 00
+
+Count = 170
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = 1848be3cb7665ac68874c617a75d8bd2
+Result = Fail
+
+Count = 171
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = 65a23b7b5ee78af9c7d0113447f78ab9
+Result = Fail
+
+Count = 172
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = 90a420b6d2252392e161dcf4fb953d7e
+Result = Fail
+
+Count = 173
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 004cbe11292887e246de7704a4a1a05f
+Result = Fail
+
+Count = 174
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = ad7af41e39ea0c0cd072263e826f3cf0
+Result = Fail
+
+Count = 175
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = 16b1a4fadbadc906a949592d6ef319a3
+Result = Fail
+
+Count = 176
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = e9cfb1069380434f221db4229a083a76
+Result = Pass
+Payload = 00
+
+Count = 177
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = 380cb57fd531bb1dcf22350518bbf8af
+Result = Pass
+Payload = 00
+
+Count = 178
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = fbf2becc35b5024078bfcfc1f831b669
+Result = Pass
+Payload = 00
+
+Count = 179
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = 080203eb842b3f98a730abbbf98f493e
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = f9fdca4ac64fe7f014de0f43039c7571
+
+Count = 180
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 6be31860ca271ef448de8f8d8b39346daf4b81d7e92d65b338f125fa
+Result = Pass
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 181
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = 4cc57a9927a6bc401441870d3193bf89ebd163f5c01501c728a66b69
+Result = Fail
+
+Count = 182
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 1f16c6d370fff40c011a243356076b67e905d4672ae2f38fee2de18c
+Result = Fail
+
+Count = 183
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 46edb001d58a01dce1bcf064cfc9a04accc82c42b33ba16524537a81
+Result = Fail
+
+Count = 184
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = 9b61335f96fc5b31274cc1fb275f29c1105d68c67b70654f9405edb1
+Result = Pass
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 185
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 97b5eb2d55847f5d5d9f8c762dace481d8efb19ccfd72265548effe3
+Result = Fail
+
+Count = 186
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = f5cc8198dce8e890587b62572b07413a915bfb55628c901c03459b29
+Result = Fail
+
+Count = 187
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = 50c0b1f6c5e4c86a0c938ecbc762eeaf99b9fe04c2820a43963b04f3
+Result = Fail
+
+Count = 188
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = 1fdbe91189da01c5098cf1538addd85b1cfef0abd0797c141330f633
+Result = Fail
+
+Count = 189
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = 462e7cdf9a6a553bca37d4d93bed4986b715d0349238613e10c1f6d7
+Result = Fail
+
+Count = 190
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = 7d142f26aa6c9d55850c5c9f58ab36a66670d47c515bf93cd37e5543
+Result = Fail
+
+Count = 191
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = f7122cbcec93d53fc7e3fc629ea15d28363cad1c83a23bb3cc5e0c4a
+Result = Pass
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 192
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = e1cad7f946b20c373323218c8a89e56edf3030662e50d459fc12a512
+Result = Pass
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 193
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = d4741814466a23e26107d773f103a4c83db9d772dbd5fdc1c2eaf895
+Result = Pass
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 194
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = ed35ff66bc7f6d8ec7acf896f994d79f5792cf6d22d6691ff92fa2f7
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = a7aa635ea51b0bb20a092bd5573e728c
+
+Count = 195
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = b351ab96b2e45515254558d5212673ee6c776d42dbca3b512cf3a20b7fd7c49e6e79bef475c2906f
+Result = Pass
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 196
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = df1a5285caa41b4bb47f6e5ceceba4e82721828d68427a3081d18ca149d6766bfaccec88f194eb5b
+Result = Fail
+
+Count = 197
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 04a29fc109dfc626e8297e0f586d0bfaf31260017d95f62d5eb4f0875dda5ccd9b94026ba49fb34e
+Result = Fail
+
+Count = 198
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 77e4cd5d319353ecb6b89e2de14bcfee4fbf738b61df14f3920843994def41aed3103995d3392eed
+Result = Fail
+
+Count = 199
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = e676f5dfde8ad810d9e729d142670eef77f2878369a28797d57603d5c45606c68be5535c671d5432
+Result = Pass
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 200
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 60c51e5c3fe4197454d64fa14017639bcfd1423b9d74e506a0bfd54fb786208e1e49c6d0e645d9fb
+Result = Fail
+
+Count = 201
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = 64d1160365062eca1027cc7036862b027bdda3a9abdf794daf8a9b7a5c50b0be4596290a4d405e79
+Result = Fail
+
+Count = 202
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = 968ca115583c645710d2b47fb196cf55f6ef33f2b01400e22ce9c776932ecf7fddd849be58096b88
+Result = Fail
+
+Count = 203
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = 4985821b16ff6d4d3416573e2fba4d53186d912f0b023a99915d0020da92f483a5a7914cba14b1e7
+Result = Fail
+
+Count = 204
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = c7345b031ef85bde766226a7603adaa7dcb07a7b2a8be1b571420e036ea48dddd671be622d372c5b
+Result = Fail
+
+Count = 205
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = 11460b9acccc13001be236814da6b73f2c8e0467574f151bb619a331f8d67d70c3f3a59b3fab53a5
+Result = Fail
+
+Count = 206
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = 1bcff940a2d9d48e93bbfd13aed5947237485983e6ae04b8b944bb46306a9b1e783f3e54c92d5f5e
+Result = Pass
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 207
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = 3b6c1570c85f297079be14cd66d335251c7b52e131a636f148608963f3037763843b70c35d7011f8
+Result = Pass
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 208
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = b540cd8cbe733e0ca2ba2112ea785596d2c1d707f41608514ba2d0944c68cc36d4125b3ef9071d69
+Result = Pass
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 209
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = 3c9c1481f1428acf202b510dca67e5e6b2abc5dd71a954da51387922af7182b7d46a33c703e6e7a8
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = a7aa635ea51b0bb20a092bd5573e728c
+
+Count = 210
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 934f893824e880f743d196b22d1f340a52608155087bd28ac25e5329
+Result = Pass
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 211
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = f43ba9d834ad85dfab3f1c0c27c3441fe4e411a38a261a6559b3b3ee
+Result = Fail
+
+Count = 212
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = c686eac859a7bae3cce97d0b6527a0a7c8c2b24ece35f4370bf6688e
+Result = Fail
+
+Count = 213
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = 2b28355ecf7246ddb08d65c464dcaa90af85f434ff95267280ed869c
+Result = Fail
+
+Count = 214
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = ecde42091baa1f5c17b79746e21c3de5c78984570748021ccd399507
+Result = Pass
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 215
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = 5c338435ed4f148342604c9aed63e907c100453d719fda2a3da37b66
+Result = Fail
+
+Count = 216
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = 30eac1042015eb82729673edd9939bf9995b2575da4d6c4c7e75dded
+Result = Fail
+
+Count = 217
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = ebd3ce55b40e4bbd8172033948c6c78049161ee8f949eb50722b9c87
+Result = Fail
+
+Count = 218
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = 20f79b36ca83baac97600fd8a6dad22c2cd0f9b7e770576048c042e5
+Result = Fail
+
+Count = 219
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = 77b76f249f936fb19bd47fe28ad4dbb7725dec365a1cb23a885ba975
+Result = Fail
+
+Count = 220
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = cf6763a23c2eab730845d1eb79bbba9f54ee899fe3d70570aa799e79
+Result = Fail
+
+Count = 221
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = 1f8086a43c1b2dea557952db88e0dbbdb96aafdb345eddae6c0b0104
+Result = Pass
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 222
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = c0c5f92285b114e0a0777e1bc22b810e7cc4f68c28cd5ce047a28dd8
+Result = Pass
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 223
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 56327f4db9c18f72bbefc3f316d31f9795dd77f493385ab7b7543552
+Result = Pass
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 224
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 37d5b17995fac8c94302ec9ba20a36d97678e85199b677f8ee39867e
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0e
+
+Count = 225
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 50038b5fdd364ee747b70d00bd36840ece4ea19998123375c0a458bfcafa3b2609afe0f825cbf503
+Result = Pass
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 226
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = 78ed8ff6b5a1255d0fbd0a719a9c27b059ff5f83d0c4962c390042ba8bb5f6798dab01c5afad7306
+Result = Fail
+
+Count = 227
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = 4b91d8e616d3f60452fd3a576bd7c265b7f549523ed4a5d7a3463394cf3c25bef8af8f244d0c0b00
+Result = Fail
+
+Count = 228
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = ab8cf8891ab62924c0c6f49dd253cfa0c3d6260d0ee4d9ba88caf8ae59d9d1131626da0dddf8722d
+Result = Fail
+
+Count = 229
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = c6b7680f321132a8bd00e8e92f785d0b828b100af6392a04d1292373a76970eda77a8194f6276262
+Result = Pass
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 230
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = aea98867d3d707c43a963c1d7fdcfc953cbd707803b2b5f0a97af19d0b7bf7c7ce398cb0b44d73af
+Result = Fail
+
+Count = 231
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = c55e17ba7886eb58126d50bde8c5c211cc1aafd71a3d9e5b343065b4bdd973ee072dbf5160d310f3
+Result = Fail
+
+Count = 232
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = 791a62d5fb39ff9735ad94507e1afe2647714d5cc56b6ff4233ec600bca1d31f704807494fb0f18d
+Result = Fail
+
+Count = 233
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = f98a081998e29500f15ebd8978a95423aed4e8e78e0279d17ec183db0e2a33ebb147d0e2363fbb01
+Result = Fail
+
+Count = 234
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = 7779814dc295a23b4100ca94bec0ad4ce2f6be6fb75a0c217e67ea2577ade5836c26a89760e0959b
+Result = Fail
+
+Count = 235
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = 55640eed12c7595a36ab423da8d8241905b6ff1e906db9624978a7865df8369635269411b3aaeb32
+Result = Fail
+
+Count = 236
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = 7fcdce0ba567b9a708d54fdb16125de71dce952f4741684f4f9d302e4f1d2a2aedf2768d7b29163f
+Result = Pass
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 237
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = d42111ba22987eac1ead5cc6cb8548bcda190d118dcd5461a50036af67fadab163e9daa8bd8e9030
+Result = Pass
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 238
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 1bf0ba0ebb20d8edba59f29a9371750c9c714078f73c335d2f1322ac69b848b001476323aed84c47
+Result = Pass
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 239
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 9d993b945476ace0b9ca932963ac8835e1bd02e8065da2d816786c4d8cf14c03b031ff723311b3c4
+Result = Fail
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.txt b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.txt
new file mode 100644
index 0000000000..1606dcb21e
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.txt
@@ -0,0 +1,1589 @@
+# CAVS 11.0
+# "CCM-DVPT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:25 2011
+
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 4ae701103c63deca5b5a3939d7d05992
+
+Count = 0
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 02209f55
+Result = Pass (0)
+Payload = 00
+
+Count = 1
+Nonce = 3796cf51b87266
+Adata = 00
+CT = 9a04c241
+Result = Fail (2 - CT changed)
+
+Count = 2
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = f5f915df
+Result = Fail (1 - Adata changed)
+
+Count = 3
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 7a3c3499
+Result = Fail (1 - Adata changed)
+
+Count = 4
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = f09c2986
+Result = Pass (0)
+Payload = 00
+
+Count = 5
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 4ae97e71
+Result = Fail (2 - CT changed)
+
+Count = 6
+Nonce = 06d102a9328863
+Adata = 00
+CT = ecb38c8b
+Result = Fail (1 - Adata changed)
+
+Count = 7
+Nonce = c288b810fb5334
+Adata = 00
+CT = 9c4dc530
+Result = Fail (2 - CT changed)
+
+Count = 8
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = 67299ef6
+Result = Fail (2 - CT changed)
+
+Count = 9
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = b0538d02
+Result = Fail (1 - Adata changed)
+
+Count = 10
+Nonce = 44077341139bf9
+Adata = 00
+CT = 88200ea8
+Result = Fail (1 - Adata changed)
+
+Count = 11
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 19867aa5
+Result = Pass (0)
+Payload = 00
+
+Count = 12
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = 3b392a52
+Result = Pass (0)
+Payload = 00
+
+Count = 13
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = 1c5e47e0
+Result = Pass (0)
+Payload = 00
+
+Count = 14
+Nonce = 9dc18698731b27
+Adata = 00
+CT = 97a56b8b
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3
+
+Count = 15
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 75d582db43ce9b13ab4b6f7f14341330
+Result = Pass (0)
+Payload = 00
+
+Count = 16
+Nonce = 3796cf51b87266
+Adata = 00
+CT = 3a65e03af37b81d05acc7ec1bc39deb0
+Result = Fail (2 - CT changed)
+
+Count = 17
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = efc5721e0b9e4c3c90deab0e1d5c11bd
+Result = Fail (1 - Adata changed)
+
+Count = 18
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 91b4b779823f4f0e3979ced93b99736c
+Result = Fail (1 - Adata changed)
+
+Count = 19
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = e2e87ca82523ccfeb416b42af9d9aadc
+Result = Pass (0)
+Payload = 00
+
+Count = 20
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 7b85fd105cc960df86ad86846d178274
+Result = Fail (2 - CT changed)
+
+Count = 21
+Nonce = 06d102a9328863
+Adata = 00
+CT = ffa140be27b25f307a6efd9697d66c9b
+Result = Fail (1 - Adata changed)
+
+Count = 22
+Nonce = c288b810fb5334
+Adata = 00
+CT = ed356542e0a804a724bfaa422e98a970
+Result = Fail (2 - CT changed)
+
+Count = 23
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = e31dd8dc920fe7900e1b1817fe845c7d
+Result = Fail (2 - CT changed)
+
+Count = 24
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = ae5a0777f03bbf541f305d00acff0396
+Result = Fail (1 - Adata changed)
+
+Count = 25
+Nonce = 44077341139bf9
+Adata = 00
+CT = 957dca58616c1cbe99f94fd8f7c257d9
+Result = Fail (1 - Adata changed)
+
+Count = 26
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 0e150af422f6da238bb476810b2d5bc2
+Result = Pass (0)
+Payload = 00
+
+Count = 27
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = 8e1150756ff3a733a1274470f072b74c
+Result = Pass (0)
+Payload = 00
+
+Count = 28
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = a1f70df3fa9cfeb95f869b3fe08466e0
+Result = Pass (0)
+Payload = 00
+
+Count = 29
+Nonce = 9dc18698731b27
+Adata = 00
+CT = fdf3f6c177aa1d71fe3474a5a2eb6bb1
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3
+
+Count = 30
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 90156f3f
+Result = Pass (0)
+Payload = 00
+
+Count = 31
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = 88909016
+Result = Fail (2 - CT changed)
+
+Count = 32
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = de547d03
+Result = Fail (1 - Adata changed)
+
+Count = 33
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = ea4bad52
+Result = Fail (1 - Adata changed)
+
+Count = 34
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 1bc82b3d
+Result = Pass (0)
+Payload = 00
+
+Count = 35
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = 92e72250
+Result = Fail (2 - CT changed)
+
+Count = 36
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = e81f0647
+Result = Fail (1 - Adata changed)
+
+Count = 37
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = 7cb906ec
+Result = Fail (2 - CT changed)
+
+Count = 38
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = d60f815b
+Result = Fail (2 - CT changed)
+
+Count = 39
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = d3d4f3b0
+Result = Fail (1 - Adata changed)
+
+Count = 40
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = a9df97ad
+Result = Fail (1 - Adata changed)
+
+Count = 41
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = 36a37a59
+Result = Pass (0)
+Payload = 00
+
+Count = 42
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = dba02a36
+Result = Pass (0)
+Payload = 00
+
+Count = 43
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = 25dcb3c5
+Result = Pass (0)
+Payload = 00
+
+Count = 44
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = 1d2832d0
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd
+
+Count = 45
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = fb04dc5a44c6bb000f2440f5154364b4
+Result = Pass (0)
+Payload = 00
+
+Count = 46
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = 5447075bf42a59b91f08064738b015ab
+Result = Fail (2 - CT changed)
+
+Count = 47
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = fdc992847f0815fac67aa935b35208ed
+Result = Fail (1 - Adata changed)
+
+Count = 48
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = 2cabd690a45e59854b7587b26dd77f8e
+Result = Fail (1 - Adata changed)
+
+Count = 49
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 3dacc71169f6da77ec91ff1d2f649ed1
+Result = Pass (0)
+Payload = 00
+
+Count = 50
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = 97a2eb170ef03fa12124f1315e3b694f
+Result = Fail (2 - CT changed)
+
+Count = 51
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = 94d85a83169d8dc76f58baf4d63ecfee
+Result = Fail (1 - Adata changed)
+
+Count = 52
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = d3903c6289ca3684b8ce1174c23153a4
+Result = Fail (2 - CT changed)
+
+Count = 53
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = 5cbac5c418374a68bd7085454c4b0c13
+Result = Fail (2 - CT changed)
+
+Count = 54
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = 26317f6b8b0130097441ed04b8009aef
+Result = Fail (1 - Adata changed)
+
+Count = 55
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = b82ab6f3bbf59b6caafc54f05570f74e
+Result = Fail (1 - Adata changed)
+
+Count = 56
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = 1ae34207e74c8c78890ae17e320e84bd
+Result = Pass (0)
+Payload = 00
+
+Count = 57
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = 5c5fa254c0be503b02caffade6b85259
+Result = Pass (0)
+Payload = 00
+
+Count = 58
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = 9340266730ea36207bb734819d3553e9
+Result = Pass (0)
+Payload = 00
+
+Count = 59
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = ec17cccf33bd9a0d4ce7aa20690c1333
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd
+
+Count = 60
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = a90e8ea44085ced791b2fdb7fd44b5cf0bd7d27718029bb703e1fa6b
+Result = Pass (0)
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 61
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = 50aafe0578c115c4a8e126ff7b3ccb64dce8ccaa8ceda69f23e5d81c
+Result = Fail (2 - CT changed)
+
+Count = 62
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = 512ed208bf10d57406537e94d20a5b6e2e9ab0683dfdc685869a97f0
+Result = Fail (1 - Adata changed)
+
+Count = 63
+Nonce = 9cbce402511b89
+Adata = 00
+CT = af72db9cd9d6f46607d6f9542ca69988dd15255c5c91171c838e7f95
+Result = Fail (1 - Adata changed)
+
+Count = 64
+Nonce = 123a0beace4e39
+Adata = 00
+CT = 47d71409a03c330be9451b3f92c9d21c584391ad1010e9d609b89801
+Result = Pass (0)
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 65
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = e562c7af0384ea16431ca20934a293a058d722cbfc3186c8eaf5f825
+Result = Fail (2 - CT changed)
+
+Count = 66
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = 004d9d89c401aa79919c2805fcd5de69316e191df56426c05ec1aa6a
+Result = Fail (1 - Adata changed)
+
+Count = 67
+Nonce = f477f754d7ee76
+Adata = 00
+CT = d623673d7f6d57c208bde112ca858561f3af5cc2bf5de926f3586c6f
+Result = Fail (2 - CT changed)
+
+Count = 68
+Nonce = 040a257dede70e
+Adata = 00
+CT = fd4733d158b5630f4f6c03ab26b11bff0cbe0d5d3df99a735fa40618
+Result = Fail (2 - CT changed)
+
+Count = 69
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = d352cb996c3075ff367a8dcacbbae46a12fbef08aa96ec835bf4f930
+Result = Fail (1 - Adata changed)
+
+Count = 70
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 31730fac20e21eca0aef591faa9fa90b3c058e32af1ce48a66f0496e
+Result = Fail (1 - Adata changed)
+
+Count = 71
+Nonce = f67b98efd39b55
+Adata = 00
+CT = dd175905a7ea3aef9fce068e6cb78e9cc60519755a178c77b753181c
+Result = Pass (0)
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 72
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = 8ad6b76f54392ee0f2834f09142545bcde9bf03d04d64aa10876f2da
+Result = Pass (0)
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 73
+Nonce = 098e053fa08043
+Adata = 00
+CT = 808eb3e04c39abde64674f0f7716dde11699cff8dd367c4cd4f7fc07
+Result = Pass (0)
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 74
+Nonce = 4bf48328725514
+Adata = 00
+CT = e074d13aad43f7b2364d47db0a02326641ca3b2ad61a1c49973a2712
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = 197afb02ffbd8f699dacae87094d5243
+
+Count = 75
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 24ab9eeb0e5508cae80074f1070ee188a637171860881f1f2d9a3fbc210595b7b8b1b41523111a8e
+Result = Pass (0)
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 76
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = 7ebfda6fa5da1dbffd82dc29b875798fbcef8ba0084fbd2463af747cc88a001fa94e060290f209c4
+Result = Fail (2 - CT changed)
+
+Count = 77
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = cbf133643851f91ddc7a1e19a0c21990459f2b7728da58f5cf3b8e6c8aeb5eeb0a5efb3700be45a2
+Result = Fail (1 - Adata changed)
+
+Count = 78
+Nonce = 9cbce402511b89
+Adata = 00
+CT = 0de7567a945c0af4a2291a651de411e8d0438508f2d4da80f7bd61a0158accbca28913e39fe80906
+Result = Fail (1 - Adata changed)
+
+Count = 79
+Nonce = 123a0beace4e39
+Adata = 00
+CT = d43035cdb5a1868aa430e8b41a1dc57a639087238e38bd628feeda2e8f249dd93a8358def7639875
+Result = Pass (0)
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 80
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = 389547260b354a6cbc909de057d367677049e80613877f6fbf19f89da977e56f308373c616299ad4
+Result = Fail (2 - CT changed)
+
+Count = 81
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = a95aa33483ed3711470025394616bf98fe624fbca8aa6fbc21366b9da457ede2a673351475b53d41
+Result = Fail (1 - Adata changed)
+
+Count = 82
+Nonce = f477f754d7ee76
+Adata = 00
+CT = 3d53b6ab8925f429ae14a0065cd203d4f9deddd402a79ac6d889a7cae55efd71b369cd6d43ef363b
+Result = Fail (2 - CT changed)
+
+Count = 83
+Nonce = 040a257dede70e
+Adata = 00
+CT = d5e6e82cb5f8034a89e58adf8298476253f18981bcb3b0364be7f19463dd330a4b9f3cbb30b88fa5
+Result = Fail (2 - CT changed)
+
+Count = 84
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = 02f69107d62ff77145c7d57684c70ba671d55f1c63bb2ad8c2df063f7fdbae27f0736a37fd065fb4
+Result = Fail (1 - Adata changed)
+
+Count = 85
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 64ec2f321111da9c5389e8255bfe69876d4f548f94cacd529b45d54cc24cff1b1d8aa1df32fbd81a
+Result = Fail (1 - Adata changed)
+
+Count = 86
+Nonce = f67b98efd39b55
+Adata = 00
+CT = 37d63c2bbf44d2eb155ecc1a844841d5c33f1a6d443419330217a4f1f4fb302257b0de7c9da2e750
+Result = Pass (0)
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 87
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = 33e0dce4410e51bed5323ea49490207084ac91732bae429236a305d520a1a24930a70a311aa3695d
+Result = Pass (0)
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 88
+Nonce = 098e053fa08043
+Adata = 00
+CT = 1d732c334319bd775e7cf93dbdc4204bbdb58192be08280481e3d64ed546b6b70ee088a693f55fbb
+Result = Pass (0)
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 89
+Nonce = 4bf48328725514
+Adata = 00
+CT = c92fc2f0d24593f67d9c09d326158a8138237c4096093f0d737719dd84ccfb397a4f61b70c85262a
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = 197afb02ffbd8f699dacae87094d5243
+
+Count = 90
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 4a550134f94455979ec4bf89ad2bd80d25a77ae94e456134a3e138b9
+Result = Pass (0)
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 91
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 118ec53dd1bfbe52d5b9fe5dfebecf2ee674ec983eada654091a5ae9
+Result = Fail (2 - CT changed)
+
+Count = 92
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = 6b0fea26e4dfe902b5e876c7ba92afbad8aa52d3c1d00ae578b6bcc4
+Result = Fail (1 - Adata changed)
+
+Count = 93
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = 640c740e2b8af851712a05948ecee055b25b145ccb82ca58ac542b09
+Result = Fail (1 - Adata changed)
+
+Count = 94
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 05f20b2ae70fcb0ea79aa1845c15b899a799ca60f51e6c296413020a
+Result = Pass (0)
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 95
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = 9fa576a8a5c72468afa372338cbbc33fef81ad5a873eb38a142d5636
+Result = Fail (2 - CT changed)
+
+Count = 96
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = 8d26582c74b2b4d960ee9e417c6395daafaebb3aff45d477f3757b6a
+Result = Fail (1 - Adata changed)
+
+Count = 97
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = cb62a13e38e17cc6635e409c922956ece38f593189a51b99a7001a16
+Result = Fail (2 - CT changed)
+
+Count = 98
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = f3e29b792423c7fbe743a3b2f890a2bff29519f3636a6232050e9225
+Result = Fail (2 - CT changed)
+
+Count = 99
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = 136e60d6714d906d1f4c02b7bdbb5f3ccdd2165306912dec850ec9f0
+Result = Fail (1 - Adata changed)
+
+Count = 100
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = 49b6d0b6eeff74af0de70072d9ccdc68a0ee36a5ddbf098b4eb95533
+Result = Fail (1 - Adata changed)
+
+Count = 101
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = a2a59041c3f78f6e10c3045118e8a475945e24c85b02abc40f8fb949
+Result = Pass (0)
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 102
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = 19b4ad222795326cb031cfdb07b652dbf64ca5db5ff5d6d569d8ab41
+Result = Pass (0)
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 103
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = 76b66b908657f4df8a329c34ccdde50ae7fc71c4a718b712f00fe764
+Result = Pass (0)
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 104
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = 20df4662ce6c8c4ce49b14fa791e41ff8598ec93d8a825e879f9eb72
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 90929a4b0ac65b350ad1591611fe4829
+
+Count = 105
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 4bfe4e35784f0a65b545477e5e2f4bae0e1e6fa717eaf2cb6a9a970b9beb2ac1bd4fd62168f8378a
+Result = Pass (0)
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 106
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 0c56a503aa2c12e87450d45a7b714db980fd348f327c0065a65666144994bad0c8195bcb4ade1337
+Result = Fail (2 - CT changed)
+
+Count = 107
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = 5f69d6c21f771eb98dc724f891f530b1c045f49a054de103a85f868739404b64a7cbdd61b577c388
+Result = Fail (1 - Adata changed)
+
+Count = 108
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = d335ba572520c336f711edf27ea738ba5e6b0d772ea443b8b2b164f3c255b699cbf75330d96c3c13
+Result = Fail (1 - Adata changed)
+
+Count = 109
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 9fa846ef8d198c538f84f856bab8f7f9c3bed90b53acb6a32658e077687315eaf11458bdf6e3c36a
+Result = Pass (0)
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 110
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = b7095030acdc5fbb8fea2c24717c1c236231f9737bcc78f463db3756abba1feef626a956794d7e56
+Result = Fail (2 - CT changed)
+
+Count = 111
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = d6911d5831163c8ebad0916af1833051b885aae822f9f6657d6fee1de626bc7c93f2caa27a3ecaa0
+Result = Fail (1 - Adata changed)
+
+Count = 112
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = 6b10a098c96c2bbf9aeb5c9adcf91e4812838dff319f8be989e2d235192f33ba0f357492112d98f4
+Result = Fail (2 - CT changed)
+
+Count = 113
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = aecd11cbac04e1f79b0fd24052c8cedf393dce9df350d24f800b81e834ea5dd2bdc2c688d9505359
+Result = Fail (2 - CT changed)
+
+Count = 114
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = d3a7a25f71b1988482dc852ed713d55abdcc4bb1129ddcae430889cd5c97343cc0dedfbd62e6b6eb
+Result = Fail (1 - Adata changed)
+
+Count = 115
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = 368e1574a433d78d0276ce4a1cacfba834a216693536c00b15acded53c41010554e1c1fe937a7605
+Result = Fail (1 - Adata changed)
+
+Count = 116
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = 99e40b3c67aca95dd4462c20cbd6b2741e7033fc4f41a975c9390fbdb9ec416267096ccbf2c148e5
+Result = Pass (0)
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 117
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = de079418c25ba67e5fda009998e3fce61bfdc3b7787cf06655c18ae38b7ee7f00f96cfca4fe9a2ef
+Result = Pass (0)
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 118
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = fbab64d8dd8b6e33c7cc6124cd65f004d7247277fe98d5d3b35357a35ff9e58e18d6d80df9fc335d
+Result = Pass (0)
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 119
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = 372b9af0655df2d0c830b4949a2d2faa8db251ee922a3bff9aba89639f4033be9ba9f3c101acc1bd
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 90929a4b0ac65b350ad1591611fe4829
+
+Count = 120
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 782e4318
+Result = Pass (0)
+Payload = 00
+
+Count = 121
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = a04f270a
+Result = Fail (2 - CT changed)
+
+Count = 122
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 97dfd257
+Result = Fail (1 - Adata changed)
+
+Count = 123
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 6c202a1c
+Result = Fail (1 - Adata changed)
+
+Count = 124
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = 1be535a0
+Result = Pass (0)
+Payload = 00
+
+Count = 125
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 4fb6617d
+Result = Fail (2 - CT changed)
+
+Count = 126
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = c056bd3e
+Result = Fail (1 - Adata changed)
+
+Count = 127
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = 87048576
+Result = Fail (2 - CT changed)
+
+Count = 128
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = ea8c0407
+Result = Fail (2 - CT changed)
+
+Count = 129
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = 41c12dc5
+Result = Fail (1 - Adata changed)
+
+Count = 130
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = de84cf5c
+Result = Fail (1 - Adata changed)
+
+Count = 131
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = e617e006
+Result = Pass (0)
+Payload = 00
+
+Count = 132
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = b7909395
+Result = Pass (0)
+Payload = 00
+
+Count = 133
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = 8a05d2ea
+Result = Pass (0)
+Payload = 00
+
+Count = 134
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 8643ba47
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b
+
+Count = 135
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 41b476013f45e4a781f253a6f3b1e530
+Result = Pass (0)
+Payload = 00
+
+Count = 136
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = f9f018fcd125822616083fffebc4c8e6
+Result = Fail (2 - CT changed)
+
+Count = 137
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 534cc67c44c877c9c908071ee1082f4c
+Result = Fail (1 - Adata changed)
+
+Count = 138
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 201c0ef2ddaa51b645911b5c37d76e95
+Result = Fail (1 - Adata changed)
+
+Count = 139
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = ec774d9000763bba3a5ac307418827b2
+Result = Pass (0)
+Payload = 00
+
+Count = 140
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 75798c3fe5202f0e33c9183c837aeaf5
+Result = Fail (2 - CT changed)
+
+Count = 141
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = 32601de5960c11c925444b5c47d42289
+Result = Fail (1 - Adata changed)
+
+Count = 142
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = 4c1cd6a774c8e6f4e261db1f73b0aa20
+Result = Fail (2 - CT changed)
+
+Count = 143
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = 8bd9c00ff23310216bbd24981c1e2cf7
+Result = Fail (2 - CT changed)
+
+Count = 144
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = 174efd089409f9932b8e631965e762a6
+Result = Fail (1 - Adata changed)
+
+Count = 145
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = 8de80f620bd41eee6a58925dc8404bfa
+Result = Fail (1 - Adata changed)
+
+Count = 146
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = 0b9d79e8e33ec45532af5515a99f05df
+Result = Pass (0)
+Payload = 00
+
+Count = 147
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = 1583e1e5a86001bbcec62292ccfd4d48
+Result = Pass (0)
+Payload = 00
+
+Count = 148
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = b72caac6362e68e445f69f605f21e0a2
+Result = Pass (0)
+Payload = 00
+
+Count = 149
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 352769a19ac75b8a116be031b33d6449
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b
+
+Count = 150
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 9f69f24f
+Result = Pass (0)
+Payload = 00
+
+Count = 151
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = e17afaa4
+Result = Fail (2 - CT changed)
+
+Count = 152
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = 07155b7e
+Result = Fail (1 - Adata changed)
+
+Count = 153
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = d538cf2f
+Result = Fail (1 - Adata changed)
+
+Count = 154
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = c283466f
+Result = Pass (0)
+Payload = 00
+
+Count = 155
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = aa8d8098
+Result = Fail (2 - CT changed)
+
+Count = 156
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = a44b69b0
+Result = Fail (1 - Adata changed)
+
+Count = 157
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = f395733f
+Result = Fail (2 - CT changed)
+
+Count = 158
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 1e9e9237
+Result = Fail (2 - CT changed)
+
+Count = 159
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = e9d2a722
+Result = Fail (1 - Adata changed)
+
+Count = 160
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = a90fc438
+Result = Fail (1 - Adata changed)
+
+Count = 161
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = 48f3a1ec
+Result = Pass (0)
+Payload = 00
+
+Count = 162
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = 24763def
+Result = Pass (0)
+Payload = 00
+
+Count = 163
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = 63394bee
+Result = Pass (0)
+Payload = 00
+
+Count = 164
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = d79b1686
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = f9fdca4ac64fe7f014de0f43039c7571
+
+Count = 165
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 1859ac36a40a6b28b34266253627797a
+Result = Pass (0)
+Payload = 00
+
+Count = 166
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = edf8b46eb69ac0044116019dec183072
+Result = Fail (2 - CT changed)
+
+Count = 167
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = 66622ac26c7227a0329739612012737c
+Result = Fail (1 - Adata changed)
+
+Count = 168
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = e4c9e86493ee78b1cbf6e55e94731b63
+Result = Fail (1 - Adata changed)
+
+Count = 169
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = 8b5bfe6b5b5552007300bae71172612f
+Result = Pass (0)
+Payload = 00
+
+Count = 170
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = 1848be3cb7665ac68874c617a75d8bd2
+Result = Fail (2 - CT changed)
+
+Count = 171
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = 65a23b7b5ee78af9c7d0113447f78ab9
+Result = Fail (1 - Adata changed)
+
+Count = 172
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = 90a420b6d2252392e161dcf4fb953d7e
+Result = Fail (2 - CT changed)
+
+Count = 173
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 004cbe11292887e246de7704a4a1a05f
+Result = Fail (2 - CT changed)
+
+Count = 174
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = ad7af41e39ea0c0cd072263e826f3cf0
+Result = Fail (1 - Adata changed)
+
+Count = 175
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = 16b1a4fadbadc906a949592d6ef319a3
+Result = Fail (1 - Adata changed)
+
+Count = 176
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = e9cfb1069380434f221db4229a083a76
+Result = Pass (0)
+Payload = 00
+
+Count = 177
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = 380cb57fd531bb1dcf22350518bbf8af
+Result = Pass (0)
+Payload = 00
+
+Count = 178
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = fbf2becc35b5024078bfcfc1f831b669
+Result = Pass (0)
+Payload = 00
+
+Count = 179
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = 080203eb842b3f98a730abbbf98f493e
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = f9fdca4ac64fe7f014de0f43039c7571
+
+Count = 180
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 6be31860ca271ef448de8f8d8b39346daf4b81d7e92d65b338f125fa
+Result = Pass (0)
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 181
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = 4cc57a9927a6bc401441870d3193bf89ebd163f5c01501c728a66b69
+Result = Fail (2 - CT changed)
+
+Count = 182
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 1f16c6d370fff40c011a243356076b67e905d4672ae2f38fee2de18c
+Result = Fail (1 - Adata changed)
+
+Count = 183
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 46edb001d58a01dce1bcf064cfc9a04accc82c42b33ba16524537a81
+Result = Fail (1 - Adata changed)
+
+Count = 184
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = 9b61335f96fc5b31274cc1fb275f29c1105d68c67b70654f9405edb1
+Result = Pass (0)
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 185
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 97b5eb2d55847f5d5d9f8c762dace481d8efb19ccfd72265548effe3
+Result = Fail (2 - CT changed)
+
+Count = 186
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = f5cc8198dce8e890587b62572b07413a915bfb55628c901c03459b29
+Result = Fail (1 - Adata changed)
+
+Count = 187
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = 50c0b1f6c5e4c86a0c938ecbc762eeaf99b9fe04c2820a43963b04f3
+Result = Fail (2 - CT changed)
+
+Count = 188
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = 1fdbe91189da01c5098cf1538addd85b1cfef0abd0797c141330f633
+Result = Fail (2 - CT changed)
+
+Count = 189
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = 462e7cdf9a6a553bca37d4d93bed4986b715d0349238613e10c1f6d7
+Result = Fail (1 - Adata changed)
+
+Count = 190
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = 7d142f26aa6c9d55850c5c9f58ab36a66670d47c515bf93cd37e5543
+Result = Fail (1 - Adata changed)
+
+Count = 191
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = f7122cbcec93d53fc7e3fc629ea15d28363cad1c83a23bb3cc5e0c4a
+Result = Pass (0)
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 192
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = e1cad7f946b20c373323218c8a89e56edf3030662e50d459fc12a512
+Result = Pass (0)
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 193
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = d4741814466a23e26107d773f103a4c83db9d772dbd5fdc1c2eaf895
+Result = Pass (0)
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 194
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = ed35ff66bc7f6d8ec7acf896f994d79f5792cf6d22d6691ff92fa2f7
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = a7aa635ea51b0bb20a092bd5573e728c
+
+Count = 195
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = b351ab96b2e45515254558d5212673ee6c776d42dbca3b512cf3a20b7fd7c49e6e79bef475c2906f
+Result = Pass (0)
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 196
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = df1a5285caa41b4bb47f6e5ceceba4e82721828d68427a3081d18ca149d6766bfaccec88f194eb5b
+Result = Fail (2 - CT changed)
+
+Count = 197
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 04a29fc109dfc626e8297e0f586d0bfaf31260017d95f62d5eb4f0875dda5ccd9b94026ba49fb34e
+Result = Fail (1 - Adata changed)
+
+Count = 198
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 77e4cd5d319353ecb6b89e2de14bcfee4fbf738b61df14f3920843994def41aed3103995d3392eed
+Result = Fail (1 - Adata changed)
+
+Count = 199
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = e676f5dfde8ad810d9e729d142670eef77f2878369a28797d57603d5c45606c68be5535c671d5432
+Result = Pass (0)
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 200
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 60c51e5c3fe4197454d64fa14017639bcfd1423b9d74e506a0bfd54fb786208e1e49c6d0e645d9fb
+Result = Fail (2 - CT changed)
+
+Count = 201
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = 64d1160365062eca1027cc7036862b027bdda3a9abdf794daf8a9b7a5c50b0be4596290a4d405e79
+Result = Fail (1 - Adata changed)
+
+Count = 202
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = 968ca115583c645710d2b47fb196cf55f6ef33f2b01400e22ce9c776932ecf7fddd849be58096b88
+Result = Fail (2 - CT changed)
+
+Count = 203
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = 4985821b16ff6d4d3416573e2fba4d53186d912f0b023a99915d0020da92f483a5a7914cba14b1e7
+Result = Fail (2 - CT changed)
+
+Count = 204
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = c7345b031ef85bde766226a7603adaa7dcb07a7b2a8be1b571420e036ea48dddd671be622d372c5b
+Result = Fail (1 - Adata changed)
+
+Count = 205
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = 11460b9acccc13001be236814da6b73f2c8e0467574f151bb619a331f8d67d70c3f3a59b3fab53a5
+Result = Fail (1 - Adata changed)
+
+Count = 206
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = 1bcff940a2d9d48e93bbfd13aed5947237485983e6ae04b8b944bb46306a9b1e783f3e54c92d5f5e
+Result = Pass (0)
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 207
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = 3b6c1570c85f297079be14cd66d335251c7b52e131a636f148608963f3037763843b70c35d7011f8
+Result = Pass (0)
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 208
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = b540cd8cbe733e0ca2ba2112ea785596d2c1d707f41608514ba2d0944c68cc36d4125b3ef9071d69
+Result = Pass (0)
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 209
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = 3c9c1481f1428acf202b510dca67e5e6b2abc5dd71a954da51387922af7182b7d46a33c703e6e7a8
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = a7aa635ea51b0bb20a092bd5573e728c
+
+Count = 210
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 934f893824e880f743d196b22d1f340a52608155087bd28ac25e5329
+Result = Pass (0)
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 211
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = f43ba9d834ad85dfab3f1c0c27c3441fe4e411a38a261a6559b3b3ee
+Result = Fail (2 - CT changed)
+
+Count = 212
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = c686eac859a7bae3cce97d0b6527a0a7c8c2b24ece35f4370bf6688e
+Result = Fail (1 - Adata changed)
+
+Count = 213
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = 2b28355ecf7246ddb08d65c464dcaa90af85f434ff95267280ed869c
+Result = Fail (1 - Adata changed)
+
+Count = 214
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = ecde42091baa1f5c17b79746e21c3de5c78984570748021ccd399507
+Result = Pass (0)
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 215
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = 5c338435ed4f148342604c9aed63e907c100453d719fda2a3da37b66
+Result = Fail (2 - CT changed)
+
+Count = 216
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = 30eac1042015eb82729673edd9939bf9995b2575da4d6c4c7e75dded
+Result = Fail (1 - Adata changed)
+
+Count = 217
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = ebd3ce55b40e4bbd8172033948c6c78049161ee8f949eb50722b9c87
+Result = Fail (2 - CT changed)
+
+Count = 218
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = 20f79b36ca83baac97600fd8a6dad22c2cd0f9b7e770576048c042e5
+Result = Fail (2 - CT changed)
+
+Count = 219
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = 77b76f249f936fb19bd47fe28ad4dbb7725dec365a1cb23a885ba975
+Result = Fail (1 - Adata changed)
+
+Count = 220
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = cf6763a23c2eab730845d1eb79bbba9f54ee899fe3d70570aa799e79
+Result = Fail (1 - Adata changed)
+
+Count = 221
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = 1f8086a43c1b2dea557952db88e0dbbdb96aafdb345eddae6c0b0104
+Result = Pass (0)
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 222
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = c0c5f92285b114e0a0777e1bc22b810e7cc4f68c28cd5ce047a28dd8
+Result = Pass (0)
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 223
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 56327f4db9c18f72bbefc3f316d31f9795dd77f493385ab7b7543552
+Result = Pass (0)
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 224
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 37d5b17995fac8c94302ec9ba20a36d97678e85199b677f8ee39867e
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0e
+
+Count = 225
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 50038b5fdd364ee747b70d00bd36840ece4ea19998123375c0a458bfcafa3b2609afe0f825cbf503
+Result = Pass (0)
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 226
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = 78ed8ff6b5a1255d0fbd0a719a9c27b059ff5f83d0c4962c390042ba8bb5f6798dab01c5afad7306
+Result = Fail (2 - CT changed)
+
+Count = 227
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = 4b91d8e616d3f60452fd3a576bd7c265b7f549523ed4a5d7a3463394cf3c25bef8af8f244d0c0b00
+Result = Fail (1 - Adata changed)
+
+Count = 228
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = ab8cf8891ab62924c0c6f49dd253cfa0c3d6260d0ee4d9ba88caf8ae59d9d1131626da0dddf8722d
+Result = Fail (1 - Adata changed)
+
+Count = 229
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = c6b7680f321132a8bd00e8e92f785d0b828b100af6392a04d1292373a76970eda77a8194f6276262
+Result = Pass (0)
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 230
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = aea98867d3d707c43a963c1d7fdcfc953cbd707803b2b5f0a97af19d0b7bf7c7ce398cb0b44d73af
+Result = Fail (2 - CT changed)
+
+Count = 231
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = c55e17ba7886eb58126d50bde8c5c211cc1aafd71a3d9e5b343065b4bdd973ee072dbf5160d310f3
+Result = Fail (1 - Adata changed)
+
+Count = 232
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = 791a62d5fb39ff9735ad94507e1afe2647714d5cc56b6ff4233ec600bca1d31f704807494fb0f18d
+Result = Fail (2 - CT changed)
+
+Count = 233
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = f98a081998e29500f15ebd8978a95423aed4e8e78e0279d17ec183db0e2a33ebb147d0e2363fbb01
+Result = Fail (2 - CT changed)
+
+Count = 234
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = 7779814dc295a23b4100ca94bec0ad4ce2f6be6fb75a0c217e67ea2577ade5836c26a89760e0959b
+Result = Fail (1 - Adata changed)
+
+Count = 235
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = 55640eed12c7595a36ab423da8d8241905b6ff1e906db9624978a7865df8369635269411b3aaeb32
+Result = Fail (1 - Adata changed)
+
+Count = 236
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = 7fcdce0ba567b9a708d54fdb16125de71dce952f4741684f4f9d302e4f1d2a2aedf2768d7b29163f
+Result = Pass (0)
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 237
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = d42111ba22987eac1ead5cc6cb8548bcda190d118dcd5461a50036af67fadab163e9daa8bd8e9030
+Result = Pass (0)
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 238
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 1bf0ba0ebb20d8edba59f29a9371750c9c714078f73c335d2f1322ac69b848b001476323aed84c47
+Result = Pass (0)
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 239
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 9d993b945476ace0b9ca932963ac8835e1bd02e8065da2d816786c4d8cf14c03b031ff723311b3c4
+Result = Fail (2 - CT changed)
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.rsp
new file mode 100644
index 0000000000..e0978a99ac
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.rsp
@@ -0,0 +1,1589 @@
+# CAVS 11.0
+# "CCM-DVPT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = c98ad7f38b2c7e970c9b965ec87a08208384718f78206c6c
+
+Count = 0
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 9d4b7f3b
+Result = Pass
+Payload = 00
+
+Count = 1
+Nonce = 3796cf51b87266
+Adata = 00
+CT = 80745de9
+Result = Fail
+
+Count = 2
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = 2f6fa823
+Result = Fail
+
+Count = 3
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 3cc132c6
+Result = Fail
+
+Count = 4
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = c79d5557
+Result = Pass
+Payload = 00
+
+Count = 5
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 41e0eea0
+Result = Fail
+
+Count = 6
+Nonce = 06d102a9328863
+Adata = 00
+CT = 1f129266
+Result = Fail
+
+Count = 7
+Nonce = c288b810fb5334
+Adata = 00
+CT = 41b0e4e2
+Result = Fail
+
+Count = 8
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = 5082e06a
+Result = Fail
+
+Count = 9
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = 70587cce
+Result = Fail
+
+Count = 10
+Nonce = 44077341139bf9
+Adata = 00
+CT = 6aaa0acd
+Result = Fail
+
+Count = 11
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 22976e42
+Result = Pass
+Payload = 00
+
+Count = 12
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = f440ea1d
+Result = Pass
+Payload = 00
+
+Count = 13
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = 88903fb9
+Result = Pass
+Payload = 00
+
+Count = 14
+Nonce = 9dc18698731b27
+Adata = 00
+CT = 3ff345c3
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3d3ad1bccf9282a65
+
+Count = 15
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 17223038fa99d53681ca1beabe78d1b4
+Result = Pass
+Payload = 00
+
+Count = 16
+Nonce = 3796cf51b87266
+Adata = 00
+CT = d0e1eeef4d2a264536bb1c2c1bde7c35
+Result = Fail
+
+Count = 17
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = 81d587f8673fd514c23172af7fb7523d
+Result = Fail
+
+Count = 18
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 500142447e535207899ab1499994daea
+Result = Fail
+
+Count = 19
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = fdfdbb38bf161785114f9ee2018e892f
+Result = Pass
+Payload = 00
+
+Count = 20
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 38fe9622eaa2a50152cf57e393dd3063
+Result = Fail
+
+Count = 21
+Nonce = 06d102a9328863
+Adata = 00
+CT = 73af4b87c167572e1400a0ee28209aff
+Result = Fail
+
+Count = 22
+Nonce = c288b810fb5334
+Adata = 00
+CT = ace2248b9f23efa813449c82217e4a4a
+Result = Fail
+
+Count = 23
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = a9bb0e469829d9cf09ad765c5b0b58bf
+Result = Fail
+
+Count = 24
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = a5977f0826926ec0d32541b2bd4e2b1e
+Result = Fail
+
+Count = 25
+Nonce = 44077341139bf9
+Adata = 00
+CT = 6938fb5afec1a84e4abb062e1a943c20
+Result = Fail
+
+Count = 26
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 7e3bbe0eb13988a93972f2fbcd35659e
+Result = Pass
+Payload = 00
+
+Count = 27
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = 48d7a15cf4f5808eb45d1ad817470554
+Result = Pass
+Payload = 00
+
+Count = 28
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = 97185ce68af1e6ab718c8c4b83ec04cd
+Result = Pass
+Payload = 00
+
+Count = 29
+Nonce = 9dc18698731b27
+Adata = 00
+CT = a81bc8f5a18293ffe19505a3687ce3f3
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3d3ad1bccf9282a65
+
+Count = 30
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = fe69ed84
+Result = Pass
+Payload = 00
+
+Count = 31
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = db7ffc82
+Result = Fail
+
+Count = 32
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = 7a677329
+Result = Fail
+
+Count = 33
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = d903d8f7
+Result = Fail
+
+Count = 34
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 215e0bf2
+Result = Pass
+Payload = 00
+
+Count = 35
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = 0d38100f
+Result = Fail
+
+Count = 36
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = 9f8ab5f7
+Result = Fail
+
+Count = 37
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = 7d811d50
+Result = Fail
+
+Count = 38
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = c2e18439
+Result = Fail
+
+Count = 39
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = d8b5817b
+Result = Fail
+
+Count = 40
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = 28cd70ff
+Result = Fail
+
+Count = 41
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = 790b2624
+Result = Pass
+Payload = 00
+
+Count = 42
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = 9e46632d
+Result = Pass
+Payload = 00
+
+Count = 43
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = 39b82901
+Result = Pass
+Payload = 00
+
+Count = 44
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = 4c0cf71f
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd4094afcb205393fa
+
+Count = 45
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 0c66a8e547ed4f8c2c9a9a1eb5d455b9
+Result = Pass
+Payload = 00
+
+Count = 46
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = 38757b3a61a4dc97ca3ab88bf1240695
+Result = Fail
+
+Count = 47
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = 11875da4445d92391d0fab5f3625497b
+Result = Fail
+
+Count = 48
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = 64477bcd4316e5c5789e1a678fdef943
+Result = Fail
+
+Count = 49
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 87da5dbc04e39fc468f43675d4e7df33
+Result = Pass
+Payload = 00
+
+Count = 50
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = bf0d53ee529d8cafc5ad7a8f2d85e7a2
+Result = Fail
+
+Count = 51
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = 676370637ad78c705d43fce066dc909f
+Result = Fail
+
+Count = 52
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = 289936db0f9f148a3c9e2d28f7d7de51
+Result = Fail
+
+Count = 53
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = 58a283641627669d5514f2af559b6c14
+Result = Fail
+
+Count = 54
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = a6b058540ed905d6e3499a13ea1f3d83
+Result = Fail
+
+Count = 55
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = 7a19b3377384f09915d0e1ae93a9f16c
+Result = Fail
+
+Count = 56
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = a0d047a1f9940d325e474da54aa13897
+Result = Pass
+Payload = 00
+
+Count = 57
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = 8a4768a2093694b6bcb7083c0bb6331c
+Result = Pass
+Payload = 00
+
+Count = 58
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = a7cafd6f68dc1f15a3603da654ce27bc
+Result = Pass
+Payload = 00
+
+Count = 59
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = c49845f2ea3c9981ad7e9b942f615b8d
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd4094afcb205393fa
+
+Count = 60
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 411986d04d6463100bff03f7d0bde7ea2c3488784378138cddc93a54
+Result = Pass
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 61
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = 32b649ab56162e55d4148a1292d6a225a988eb1308298273b6889036
+Result = Fail
+
+Count = 62
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = a963c3568ab413b174cd95cc1e3ca61ee181292bebdb28179b4de35f
+Result = Fail
+
+Count = 63
+Nonce = 9cbce402511b89
+Adata = 00
+CT = 0396e6c8db43e5fac205f4c576fd577368adcb688cf3d7e76df9ffc5
+Result = Fail
+
+Count = 64
+Nonce = 123a0beace4e39
+Adata = 00
+CT = b41bfba94edcafc41b4c144269b9126a6d47b19e83b15772b28c8e38
+Result = Pass
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 65
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = 01e3bb938e16d0284d1d0fee049d80fb97356ae4d84127cf7336a30a
+Result = Fail
+
+Count = 66
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = abd7551c5e84e9bef5fbfad3e24d13f02864410eae9177ad0c40cc72
+Result = Fail
+
+Count = 67
+Nonce = f477f754d7ee76
+Adata = 00
+CT = 3b5ae49e0974f41826152432b46f1a85ab4995afefbbccddfc9fd290
+Result = Fail
+
+Count = 68
+Nonce = 040a257dede70e
+Adata = 00
+CT = 21fb4324de4ba1e2762b3041ce26e43a3d191458a046d489e485910b
+Result = Fail
+
+Count = 69
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = 99ca8f542fd06481e23719214c9892442f393d72899deea08695053f
+Result = Fail
+
+Count = 70
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 5fcc05342cdc27f66b324ae7387205bfb4ab6302bfe0af09050d2054
+Result = Fail
+
+Count = 71
+Nonce = f67b98efd39b55
+Adata = 00
+CT = 0a7fe63046daf8a979935b897088c64acc1b47a5a9b86fdd6def28ab
+Result = Pass
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 72
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = daf7d7dfa512ceb1d7d3435634d9a70b3ef6c6dc38f409e068941fce
+Result = Pass
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 73
+Nonce = 098e053fa08043
+Adata = 00
+CT = cdb417dff6502208775f21e35cdb8e3e1199308d1a94229051a1ec4a
+Result = Pass
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 74
+Nonce = 4bf48328725514
+Adata = 00
+CT = e75441093c8ccba6eac5913dc246ce96de4784a01051498298eaddaf
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = 197afb02ffbd8f699dacae87094d524324576b99844f75e1
+
+Count = 75
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = cba4b4aeb85f0492fd8d905c4a6d8233139833373ef188a8c5a5ebecf7ac8607fe412189e83d9d20
+Result = Pass
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 76
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = ca62713728b5c9d652504b0ae8fd4fee5d297ee6a8d19cb6e699f15f14d34dcaf9ba8ed4b877c97d
+Result = Fail
+
+Count = 77
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = 93012c0a5f6f1025b8c4a5d897d3eea0b1c77be8000c9e59f3b8899459788c58794f177cfd838f35
+Result = Fail
+
+Count = 78
+Nonce = 9cbce402511b89
+Adata = 00
+CT = b8eb95f72f643c2c51ad74775cc203d215c86626e903eb013ad22e8fa4d2f9725ce4f212a8844855
+Result = Fail
+
+Count = 79
+Nonce = 123a0beace4e39
+Adata = 00
+CT = 71f17cf21c44267c676657db9e55bee33273787474e77b17b5eab45d7d096577643815e6d467312d
+Result = Pass
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 80
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = d6737f642260c4ee3b19cb78cc2ef1767213416b82c71e918b1a5ecca7354af824fea617b9b69031
+Result = Fail
+
+Count = 81
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = cbe60d633399daa6ee66418be6d16e292ea47a93c291fce2c54c98f8007ed55a21759f5452559538
+Result = Fail
+
+Count = 82
+Nonce = f477f754d7ee76
+Adata = 00
+CT = 2a78a7beb8df4bf5d35ff0b2853bc51ce127163d2f56e00ea555aa972e1c2e3f439f85663ae25889
+Result = Fail
+
+Count = 83
+Nonce = 040a257dede70e
+Adata = 00
+CT = ee78ddbea9c3aede9f88af0e82464d9d1afe81de16aa18c49aeb326578fa615e86969348d9bbfb7f
+Result = Fail
+
+Count = 84
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = cdf7cb74d978e7ea738e288ed79edfccf10b553c09d1856e2efbff1da769af3b72099cbda3cbf091
+Result = Fail
+
+Count = 85
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 90b990a1ea254592f2c226c969b332fc7bfe5f808729c2d83291a566e6641a965ffdabe097050dc5
+Result = Fail
+
+Count = 86
+Nonce = f67b98efd39b55
+Adata = 00
+CT = 44a6aa954c3508b3c9264c20c272e80c0e95d50ddec2849084b47504dced5b70c302cc93502cc37e
+Result = Pass
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 87
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = 9d4ff7a44cdb9b14f586efc3d6be02d069b425c06bec4eed37109739a3676f03adfd740dbaa4940d
+Result = Pass
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 88
+Nonce = 098e053fa08043
+Adata = 00
+CT = 23da95e102c7921a51b19b5733ea5776ab6c287f6057c00ec4bfacbb2f246b570efd93d98e99be49
+Result = Pass
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 89
+Nonce = 4bf48328725514
+Adata = 00
+CT = 53d00d5839d0a1e695916151f9450b7311982917edcbd7c66496912db41761a1d2aecfda04fb2cfa
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = 197afb02ffbd8f699dacae87094d524324576b99844f75e1
+
+Count = 90
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 042653c674ef2a90f7fb11d30848e530ae59478f1051633a34fad277
+Result = Pass
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 91
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 1902d9769a7ba3d3268e1257395c8c2e5f98eef295dcbfa5a35df775
+Result = Fail
+
+Count = 92
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = ebacb8e78c0ad9d3ed99f1821b0b0085beac351f88a79ef71faaf310
+Result = Fail
+
+Count = 93
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = efc1d5b6f0a48e4ce3e821d743d34206b28c69485c410fa94d5e6103
+Result = Fail
+
+Count = 94
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 3c1836e5d0f0473dab7bfd7a95ba69575f7f841970ac6c6769ac966a
+Result = Pass
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 95
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = 2c583e54d75a02948c7f6dcd12cba32a65e8d605fba7ec10c47e9a8e
+Result = Fail
+
+Count = 96
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = a8632dee22f34315b05c40135c6dd471c63b09438da834dc1f3f537f
+Result = Fail
+
+Count = 97
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = 0f03ea1b2561951d79062e19a85d98293c8c2846936c724c26421940
+Result = Fail
+
+Count = 98
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = f9764405e54d827ac433fd624506b92e123463a5b01f21ffa3a22ac7
+Result = Fail
+
+Count = 99
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = a326e0cf3f97adff3249944880ddfb8d616cd18a086e046289429246
+Result = Fail
+
+Count = 100
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = f188bc1a72e81b34d75b402e4f8ef3d638d2f56a409eab064c9649b7
+Result = Fail
+
+Count = 101
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = 341df3a273e85cf387ab823bdf9c34a1ae2c86940cb4bfcde2e93f29
+Result = Pass
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 102
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = a0e7997fd67ea66b6274d719b84da92433fdf7d512b160da35c7081d
+Result = Pass
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 103
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = dd8fd11e1c0746e7273fdd2e7dfa1ee4fc8ad835ca3141c0f83a9ad7
+Result = Pass
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 104
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = 39b0d3603f1289b5885ac244953275d28491952e7e57d93c7ff1eb5d
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 90929a4b0ac65b350ad1591611fe48297e03956f6083e451
+
+Count = 105
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = a5b7d8cca2069908d1ed88e6a9fe2c9bede3131dad54671ea7ade30a07d185692ab0ebdf4c78cf7a
+Result = Pass
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 106
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 9a98617fb97a0dfe466be692272dcdaec1c5443a3b51312ef042c86363cc05afb98c66e16be8a445
+Result = Fail
+
+Count = 107
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = d3068ae815c3605d7670058abb9384f4c15b75150eb7910041a8f6ac697430627826bd76b19da027
+Result = Fail
+
+Count = 108
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = 388a289bb85533b667b141a78d0c79acdeb9fbf72886d5ab980581017fefef92c2b50ae20b93c81c
+Result = Fail
+
+Count = 109
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 71f68480a8801d4966c84807c5ff6139d83ba0a5b902bee3327f5f91763c0a0bec43264c27cd237f
+Result = Pass
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 110
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = 8627bf1e3edafc69f1328c393dd8e7bd1c182d021e6d3a3652c4b7fd911ca77950ff2d035e47b7ec
+Result = Fail
+
+Count = 111
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = b10ea86a384432a45f50b3c2e482595b46c81c61ca39bc0f4ffcb29bde8b9a81945d671b0f619045
+Result = Fail
+
+Count = 112
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = 3ace8b7e03a0c1fa9e97f46975ab0a4924446e791540e225578cc14aa558e18d5f777ab6e16dcfee
+Result = Fail
+
+Count = 113
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = 8190abe4c21e320e10825e269190bb10a354691958e2436275433c4ae28757c8544c86f1f74ea6a5
+Result = Fail
+
+Count = 114
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = 1d7e308c34cdca7b7b222f4ebc92afd8055bff542c0b76d3d7752ebe9c5dbf00ee8ad60ac34dd7d0
+Result = Fail
+
+Count = 115
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = 9c2609f7af5b634a16e58f2e9cc7a9ef7812a12d209847000a4432b35d3b884e4169c28d287499ff
+Result = Fail
+
+Count = 116
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = 5b0b5e6690d648e1b92c12cfddb431d6d3dfe689d01db8199256ace490c2f0afb93ba32be58fd1de
+Result = Pass
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 117
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = 8722fca71fdf750ec5d62fc6d7ba079aef19210da764067aefd8535dd6b7fa701c9ca8c8b635c30b
+Result = Pass
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 118
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = 91ac457f5e53492301e72d9d495277ed17edb30e8c7a48d21b5d2cd4d5b6d2ef48413245a6b27b67
+Result = Pass
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 119
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = d2fe5293b7d53ed46ddf02a5618039adbae22845ce72e434fdc83ea4863c3e84a5456f7f853a1ea6
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 90929a4b0ac65b350ad1591611fe48297e03956f6083e451
+
+Count = 120
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 1d089a5f
+Result = Pass
+Payload = 00
+
+Count = 121
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = 2f46022a
+Result = Fail
+
+Count = 122
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 67dc4693
+Result = Fail
+
+Count = 123
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 7027a849
+Result = Fail
+
+Count = 124
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = 5c6a4de2
+Result = Pass
+Payload = 00
+
+Count = 125
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 1d855f5d
+Result = Fail
+
+Count = 126
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = 1b318980
+Result = Fail
+
+Count = 127
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = cf871f91
+Result = Fail
+
+Count = 128
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = 4f0e04bc
+Result = Fail
+
+Count = 129
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = fc9013df
+Result = Fail
+
+Count = 130
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = 5134def3
+Result = Fail
+
+Count = 131
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = 5814103a
+Result = Pass
+Payload = 00
+
+Count = 132
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = 74c75c4a
+Result = Pass
+Payload = 00
+
+Count = 133
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = 9884898b
+Result = Pass
+Payload = 00
+
+Count = 134
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 0b1cbfb1
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b12ab744b61c070e2
+
+Count = 135
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 5280a2137fee3deefcfe9b63a1199fb3
+Result = Pass
+Payload = 00
+
+Count = 136
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = d40a7318c5f2d82f838c0beeefe0d598
+Result = Fail
+
+Count = 137
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 7551978bc9592bf9e294b4984c5862bb
+Result = Fail
+
+Count = 138
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 859cf444f89225b32a55a1645bd24979
+Result = Fail
+
+Count = 139
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = 29e967a0245607c36cf3eaf00fdae566
+Result = Pass
+Payload = 00
+
+Count = 140
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 9daa0e1c4df5f2bf507b1a57a1135b86
+Result = Fail
+
+Count = 141
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = 18caec79720a5d67d7457e9b7c7a153c
+Result = Fail
+
+Count = 142
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = 5f2c455546c56f514a0f69f05345c2c4
+Result = Fail
+
+Count = 143
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = b7e4846ff30b7c3673a962a2701c0387
+Result = Fail
+
+Count = 144
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = 7b5fa0d42a616ab05ac2c58c904ce92f
+Result = Fail
+
+Count = 145
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = c8c67f558b5844b149dd47824c8cb9d8
+Result = Fail
+
+Count = 146
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = 70a09aaf22ac316124a169f6b0a83ffe
+Result = Pass
+Payload = 00
+
+Count = 147
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = 5bc85ed5521a91b9eb42b437950f0e06
+Result = Pass
+Payload = 00
+
+Count = 148
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = 989ec0e7b192ea010dd61d3fb64e8de0
+Result = Pass
+Payload = 00
+
+Count = 149
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 15c2dbe7fa307654d8ca7c0f8d6d2f14
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b12ab744b61c070e2
+
+Count = 150
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 5e0eaebd
+Result = Pass
+Payload = 00
+
+Count = 151
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = 71b7fc33
+Result = Fail
+
+Count = 152
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = 93227bd4
+Result = Fail
+
+Count = 153
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = ced654e2
+Result = Fail
+
+Count = 154
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = bf7a8e0c
+Result = Pass
+Payload = 00
+
+Count = 155
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = 840caa3e
+Result = Fail
+
+Count = 156
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = 1e22fc41
+Result = Fail
+
+Count = 157
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = 968ccbbf
+Result = Fail
+
+Count = 158
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 0a31cc96
+Result = Fail
+
+Count = 159
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = a456c3da
+Result = Fail
+
+Count = 160
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = 29746eea
+Result = Fail
+
+Count = 161
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = df7f63ca
+Result = Pass
+Payload = 00
+
+Count = 162
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = bf0b1445
+Result = Pass
+Payload = 00
+
+Count = 163
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = ae8533f5
+Result = Pass
+Payload = 00
+
+Count = 164
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = 9426cf89
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = f9fdca4ac64fe7f014de0f43039c757194d544ce5d15eed4
+
+Count = 165
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = d07ccf9fdc3d33aa94cda3d230da707c
+Result = Pass
+Payload = 00
+
+Count = 166
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = 65fe32b649dc328c9f531584897e85b3
+Result = Fail
+
+Count = 167
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = ec31fb6b41c2dae87cf395fc1fe3a080
+Result = Fail
+
+Count = 168
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = 33c2f2312dd5bfcadbb05f8d0a33fd4a
+Result = Fail
+
+Count = 169
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = a9e81afd1030d195c679e2c837aeb736
+Result = Pass
+Payload = 00
+
+Count = 170
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = 1db000f0e7d3a03718293fc118678427
+Result = Fail
+
+Count = 171
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = ea37900f049db8fc5cbf46edb5fcac2c
+Result = Fail
+
+Count = 172
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = d1097ebd7ad0a41f61ba32a44dc15305
+Result = Fail
+
+Count = 173
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 0979729272d8b42f2e3dc0eb181a1217
+Result = Fail
+
+Count = 174
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = 4457200916a20116b096225606f1a9e2
+Result = Fail
+
+Count = 175
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = cc6b51f39a3dcfb54abbb89f4df21114
+Result = Fail
+
+Count = 176
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = aac09cef9697927331251f028d24c31f
+Result = Pass
+Payload = 00
+
+Count = 177
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = 56c00070eae0db329894a045d866bbaf
+Result = Pass
+Payload = 00
+
+Count = 178
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = 090016bb96aeaabbf66fd34fc97591a4
+Result = Pass
+Payload = 00
+
+Count = 179
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = 264407dfe796bf7f6eb1f26c1f8504ef
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = f9fdca4ac64fe7f014de0f43039c757194d544ce5d15eed4
+
+Count = 180
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 9f6ca4af9b159148c889a6584d1183ea26e2614874b0504575dea8d1
+Result = Pass
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 181
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = 84d8212e9cfc2121252baa3b065b1edcf50497b9594db1ebd7965825
+Result = Fail
+
+Count = 182
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 5f60a8f867a33b2077ecc69863b295c3c6aeae7d7cade7f8f7f796fe
+Result = Fail
+
+Count = 183
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 1353b3fa1bb1d57ffb139017885c02e26c90231a24b5a615b8f1f2ae
+Result = Fail
+
+Count = 184
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = c3116d9040e1ed4f7c9464d270fb302bd3f1561c25c5b95b8b4b53f6
+Result = Pass
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 185
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 0ca17e8f89bea67db48a8f132ef6c6df7a292914d401299af6bf3800
+Result = Fail
+
+Count = 186
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = 0ce543569e8187f3cec70399ff922e4903cb1d12f990f05613244cf6
+Result = Fail
+
+Count = 187
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = 3acdbc163a350f312791b152a41e57627b1cc8bf3e41c8aea5876de8
+Result = Fail
+
+Count = 188
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = 604518e436edf7a0561d5e284f3915839a6d28cb06ef792a1970ed17
+Result = Fail
+
+Count = 189
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = fc79b520d67da891e63654d7927db6c8012c96985a0059d5f68d8da4
+Result = Fail
+
+Count = 190
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = d86bb51a98770098d0feb39170bd979199a8f741041df13790ee4c14
+Result = Fail
+
+Count = 191
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = 51b6b928bdd1cc0bd0a0aed2cda302472d618ffaa60e179029c87855
+Result = Pass
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 192
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = d0abab9b8e9d6c11bb9c15bea8a486704bed32c57297055b4de8ed8d
+Result = Pass
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 193
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = 92fd519a966c0fbdd7087ff5a1bd946cd663502db378383531d69947
+Result = Pass
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 194
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = 7f239b1916830161f3b52b7ab13542a5a0a97a17f30ca5fa30768d4d
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = a7aa635ea51b0bb20a092bd5573e728ccd4b3e8cdd2ab33d
+
+Count = 195
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 6aab64c4787599d8f213446beadb16e08dba60e97f56dbd14d1d980d6fe0fb44b421992662b97975
+Result = Pass
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 196
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = 4980b2ee49b1aaf393175f5ab9bae95ec7904557dfa206603c51d36c826f01384100886198a7f6a3
+Result = Fail
+
+Count = 197
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 86a02bdd6ae733eee26f8eab898b336105978b5bbd6df781758a111aae4f735b7dd4d9802f2a8406
+Result = Fail
+
+Count = 198
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 59cfab8956813c48e09332a2bb8a30dbcdf5afb2529532ab8cef14ebc2951069739d5d657d82addb
+Result = Fail
+
+Count = 199
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = 67d989ea935b9ce190e3a7f3b645305e1e308a7fe617f80f170a2b9c309de6c2326115a76efbdf98
+Result = Pass
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 200
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 2522a5e4d157193ef2c264cfe877db8ac75b3cc5aab08a814bcd14af0205af716f2b864f0c397f65
+Result = Fail
+
+Count = 201
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = 4536422bbad220079ee09e700e103efdaac832d016a20813762d5d8adafe75a191310a2618930c48
+Result = Fail
+
+Count = 202
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = d6711a78adf54f4effe647d531c4618cf32e3037eb700580206f80080dfa3e66e6371c0cde6cd205
+Result = Fail
+
+Count = 203
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = e44034a397778e1c6babab27f5a50fa4aac0e83d6b3eb25db1b5b2b35c8a8125efccd1f4102f3e82
+Result = Fail
+
+Count = 204
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = b8e31c5910623e405f2ebf65821963e5b8814043612395feca36f53b01943f03cb8b69b5af53e505
+Result = Fail
+
+Count = 205
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = 4000faf8558f2f4e01e45e90796cd236e5211d1704270f31c3bfc6851049d32105fd16bd45b29f29
+Result = Fail
+
+Count = 206
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = 53bb608f6236798839af35888cb0fa4797b599271084cc13847b022733ca5a5e3c4d472332484b7f
+Result = Pass
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 207
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = be54551d1d2f1b3eb60ffe3b165524ff90ca09fb252bf21c1c79edbf38c50e0f240a2d70f65aa79f
+Result = Pass
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 208
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = f07c1072d8f8e077dfbb3ad86dd92d32b41f29e647dcd7e3a82cd3ebaf6c2d3e21749bdf570ad28d
+Result = Pass
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 209
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = 7f7cf7f4d0645934cb0a5e67b4227a909aa55dba09b2c39cef93a8759845326683a0d9c22151f486
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = a7aa635ea51b0bb20a092bd5573e728ccd4b3e8cdd2ab33d
+
+Count = 210
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 16e543d0e20615ff0df15acd9927ddfe40668a54bb854cccc25e9fce
+Result = Pass
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 211
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = df35b109caf690656ae278bbd8f8bba687a2ce11b105dae98ecedb3e
+Result = Fail
+
+Count = 212
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = 7075da2291e2cb527eb926ed08d8020c5f8f0f2d4a6a4745728da544
+Result = Fail
+
+Count = 213
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = 18a77a66457b53286b1aea0845304cac8e66a02d5c642e4c02a9b9bc
+Result = Fail
+
+Count = 214
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = 24e1d3820101412d8f4d57118cab8f7e489d5cac78802dd5ccf8ecf0
+Result = Pass
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 215
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = b5929bc9648e24a553c5cd953ecb9d67ee508d2d4ac7b46e661181d5
+Result = Fail
+
+Count = 216
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = 54aa018dc7fdf8a54809e1393d18031bab4aa5ca35c201907d74517d
+Result = Fail
+
+Count = 217
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = 69bcc300a459862b3cd284c15dd4af53dc7e95f3067bb8254a8edd83
+Result = Fail
+
+Count = 218
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = 5c2d2df0d8aade3e5ae0f8d8b4b4d7c565817a31b2865dc270ad39a6
+Result = Fail
+
+Count = 219
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = df1b3f98b6b0060191e7eb817f5908ddc0bc6f83860349e8ae423997
+Result = Fail
+
+Count = 220
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = 16e59dd38395c7be7f580371edabb1e9bf21270de270aa283309108e
+Result = Fail
+
+Count = 221
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = 0ef8981dd37c055a3c3e14786fc662b2a11065964911d35ebcc87096
+Result = Pass
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 222
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = fc1870cfc440f74f73f40e682cf4713d027c297b9426c3efe981e935
+Result = Pass
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 223
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 9fc2c462dff1ba9756772d73de5c4e822b5ea0bc88845a323b98de4f
+Result = Pass
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 224
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 05fc586d5c780b8e06f618b5bb85f591665a54390eba4e14af3b74e1
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886
+
+Count = 225
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = c5b0b2ef17498c5570eb335df4588032958ba3d69bf6f3178464a6f7fa2b76744e8e8d95691cecb8
+Result = Pass
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 226
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = d1f0518929f4ae2f0543de2a7dfe4bb0110bb3057e524a1c06bd6dc2e6bcc3436cffb969ae900388
+Result = Fail
+
+Count = 227
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = 1aa7dfa3a9818142c4971cbf4f64d4cbdbd354c6958ef474bb56d90669c726d866fe2206b8828727
+Result = Fail
+
+Count = 228
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = 90352a5ec92d4fa52a96ae28251a57933728b2a3670e2ecd9953fec4e091b3573214e1ecac1ac00c
+Result = Fail
+
+Count = 229
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = eaa995946ed91d6a08ade14b260ac752cbd1081d5a7cad90783618374f6d03df28ee57a1a5aa38d8
+Result = Pass
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 230
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = 0e320c4ece6ef0305a431a07a5a34d463ec4a37fc513c4b947bb3f30d6e674d10a496806c1c8933e
+Result = Fail
+
+Count = 231
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = 10685888091597c50acc54b2fb65150b83a7115351d6f8bd7dd7ee3f75cfb47fa72433644f9cf62e
+Result = Fail
+
+Count = 232
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = e456abf9ee83e0a68fbdb09c4a7afaba0efb0aa6d74a17c443314076072a0ebd253fe1ab4883ebea
+Result = Fail
+
+Count = 233
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = 5adadfd296edaf4bea92c8245983dc31b11335f682fb222c16a72444f0949868f0e71907acbb29f4
+Result = Fail
+
+Count = 234
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = c2bb4d5a830646b3f8bf84044851c3b676c4ec02e43dcbf1ab2025208191d73041c038cf2562bb8c
+Result = Fail
+
+Count = 235
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = 9589b8abcb47e54e6e8fad3e64fec7ed4f70ac435bb3e548b7e6d183efa1f51b7ff31eaa52ed59ba
+Result = Fail
+
+Count = 236
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = af63f27e2a9e70f106477493dc141d16a1d059dd7a8a7810d990b642039f24755790332b3cc47c49
+Result = Pass
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 237
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = 1d2ae88c878684a0b404986252b3a7583e1a5a51163ddc606d3968fdceaae5138c411a29d0d333ee
+Result = Pass
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 238
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 30c154c616946eccc2e241d336ad33720953e449a0e6b0f0dbf8e9464909bdf337e48093c082a10b
+Result = Pass
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 239
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 0c95b692b07b39039b40c80cf52ff71608ae87c973ac9ccb88bba8f204bb98b17cb3c8644e472b1e
+Result = Fail
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.txt b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.txt
new file mode 100644
index 0000000000..27671e1a0a
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.txt
@@ -0,0 +1,1589 @@
+# CAVS 11.0
+# "CCM-DVPT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = c98ad7f38b2c7e970c9b965ec87a08208384718f78206c6c
+
+Count = 0
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 9d4b7f3b
+Result = Pass (0)
+Payload = 00
+
+Count = 1
+Nonce = 3796cf51b87266
+Adata = 00
+CT = 80745de9
+Result = Fail (2 - CT changed)
+
+Count = 2
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = 2f6fa823
+Result = Fail (1 - Adata changed)
+
+Count = 3
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 3cc132c6
+Result = Fail (1 - Adata changed)
+
+Count = 4
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = c79d5557
+Result = Pass (0)
+Payload = 00
+
+Count = 5
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 41e0eea0
+Result = Fail (2 - CT changed)
+
+Count = 6
+Nonce = 06d102a9328863
+Adata = 00
+CT = 1f129266
+Result = Fail (1 - Adata changed)
+
+Count = 7
+Nonce = c288b810fb5334
+Adata = 00
+CT = 41b0e4e2
+Result = Fail (2 - CT changed)
+
+Count = 8
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = 5082e06a
+Result = Fail (2 - CT changed)
+
+Count = 9
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = 70587cce
+Result = Fail (1 - Adata changed)
+
+Count = 10
+Nonce = 44077341139bf9
+Adata = 00
+CT = 6aaa0acd
+Result = Fail (1 - Adata changed)
+
+Count = 11
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 22976e42
+Result = Pass (0)
+Payload = 00
+
+Count = 12
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = f440ea1d
+Result = Pass (0)
+Payload = 00
+
+Count = 13
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = 88903fb9
+Result = Pass (0)
+Payload = 00
+
+Count = 14
+Nonce = 9dc18698731b27
+Adata = 00
+CT = 3ff345c3
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3d3ad1bccf9282a65
+
+Count = 15
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 17223038fa99d53681ca1beabe78d1b4
+Result = Pass (0)
+Payload = 00
+
+Count = 16
+Nonce = 3796cf51b87266
+Adata = 00
+CT = d0e1eeef4d2a264536bb1c2c1bde7c35
+Result = Fail (2 - CT changed)
+
+Count = 17
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = 81d587f8673fd514c23172af7fb7523d
+Result = Fail (1 - Adata changed)
+
+Count = 18
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 500142447e535207899ab1499994daea
+Result = Fail (1 - Adata changed)
+
+Count = 19
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = fdfdbb38bf161785114f9ee2018e892f
+Result = Pass (0)
+Payload = 00
+
+Count = 20
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 38fe9622eaa2a50152cf57e393dd3063
+Result = Fail (2 - CT changed)
+
+Count = 21
+Nonce = 06d102a9328863
+Adata = 00
+CT = 73af4b87c167572e1400a0ee28209aff
+Result = Fail (1 - Adata changed)
+
+Count = 22
+Nonce = c288b810fb5334
+Adata = 00
+CT = ace2248b9f23efa813449c82217e4a4a
+Result = Fail (2 - CT changed)
+
+Count = 23
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = a9bb0e469829d9cf09ad765c5b0b58bf
+Result = Fail (2 - CT changed)
+
+Count = 24
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = a5977f0826926ec0d32541b2bd4e2b1e
+Result = Fail (1 - Adata changed)
+
+Count = 25
+Nonce = 44077341139bf9
+Adata = 00
+CT = 6938fb5afec1a84e4abb062e1a943c20
+Result = Fail (1 - Adata changed)
+
+Count = 26
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 7e3bbe0eb13988a93972f2fbcd35659e
+Result = Pass (0)
+Payload = 00
+
+Count = 27
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = 48d7a15cf4f5808eb45d1ad817470554
+Result = Pass (0)
+Payload = 00
+
+Count = 28
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = 97185ce68af1e6ab718c8c4b83ec04cd
+Result = Pass (0)
+Payload = 00
+
+Count = 29
+Nonce = 9dc18698731b27
+Adata = 00
+CT = a81bc8f5a18293ffe19505a3687ce3f3
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3d3ad1bccf9282a65
+
+Count = 30
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = fe69ed84
+Result = Pass (0)
+Payload = 00
+
+Count = 31
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = db7ffc82
+Result = Fail (2 - CT changed)
+
+Count = 32
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = 7a677329
+Result = Fail (1 - Adata changed)
+
+Count = 33
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = d903d8f7
+Result = Fail (1 - Adata changed)
+
+Count = 34
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 215e0bf2
+Result = Pass (0)
+Payload = 00
+
+Count = 35
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = 0d38100f
+Result = Fail (2 - CT changed)
+
+Count = 36
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = 9f8ab5f7
+Result = Fail (1 - Adata changed)
+
+Count = 37
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = 7d811d50
+Result = Fail (2 - CT changed)
+
+Count = 38
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = c2e18439
+Result = Fail (2 - CT changed)
+
+Count = 39
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = d8b5817b
+Result = Fail (1 - Adata changed)
+
+Count = 40
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = 28cd70ff
+Result = Fail (1 - Adata changed)
+
+Count = 41
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = 790b2624
+Result = Pass (0)
+Payload = 00
+
+Count = 42
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = 9e46632d
+Result = Pass (0)
+Payload = 00
+
+Count = 43
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = 39b82901
+Result = Pass (0)
+Payload = 00
+
+Count = 44
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = 4c0cf71f
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd4094afcb205393fa
+
+Count = 45
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 0c66a8e547ed4f8c2c9a9a1eb5d455b9
+Result = Pass (0)
+Payload = 00
+
+Count = 46
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = 38757b3a61a4dc97ca3ab88bf1240695
+Result = Fail (2 - CT changed)
+
+Count = 47
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = 11875da4445d92391d0fab5f3625497b
+Result = Fail (1 - Adata changed)
+
+Count = 48
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = 64477bcd4316e5c5789e1a678fdef943
+Result = Fail (1 - Adata changed)
+
+Count = 49
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 87da5dbc04e39fc468f43675d4e7df33
+Result = Pass (0)
+Payload = 00
+
+Count = 50
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = bf0d53ee529d8cafc5ad7a8f2d85e7a2
+Result = Fail (2 - CT changed)
+
+Count = 51
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = 676370637ad78c705d43fce066dc909f
+Result = Fail (1 - Adata changed)
+
+Count = 52
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = 289936db0f9f148a3c9e2d28f7d7de51
+Result = Fail (2 - CT changed)
+
+Count = 53
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = 58a283641627669d5514f2af559b6c14
+Result = Fail (2 - CT changed)
+
+Count = 54
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = a6b058540ed905d6e3499a13ea1f3d83
+Result = Fail (1 - Adata changed)
+
+Count = 55
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = 7a19b3377384f09915d0e1ae93a9f16c
+Result = Fail (1 - Adata changed)
+
+Count = 56
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = a0d047a1f9940d325e474da54aa13897
+Result = Pass (0)
+Payload = 00
+
+Count = 57
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = 8a4768a2093694b6bcb7083c0bb6331c
+Result = Pass (0)
+Payload = 00
+
+Count = 58
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = a7cafd6f68dc1f15a3603da654ce27bc
+Result = Pass (0)
+Payload = 00
+
+Count = 59
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = c49845f2ea3c9981ad7e9b942f615b8d
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd4094afcb205393fa
+
+Count = 60
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 411986d04d6463100bff03f7d0bde7ea2c3488784378138cddc93a54
+Result = Pass (0)
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 61
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = 32b649ab56162e55d4148a1292d6a225a988eb1308298273b6889036
+Result = Fail (2 - CT changed)
+
+Count = 62
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = a963c3568ab413b174cd95cc1e3ca61ee181292bebdb28179b4de35f
+Result = Fail (1 - Adata changed)
+
+Count = 63
+Nonce = 9cbce402511b89
+Adata = 00
+CT = 0396e6c8db43e5fac205f4c576fd577368adcb688cf3d7e76df9ffc5
+Result = Fail (1 - Adata changed)
+
+Count = 64
+Nonce = 123a0beace4e39
+Adata = 00
+CT = b41bfba94edcafc41b4c144269b9126a6d47b19e83b15772b28c8e38
+Result = Pass (0)
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 65
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = 01e3bb938e16d0284d1d0fee049d80fb97356ae4d84127cf7336a30a
+Result = Fail (2 - CT changed)
+
+Count = 66
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = abd7551c5e84e9bef5fbfad3e24d13f02864410eae9177ad0c40cc72
+Result = Fail (1 - Adata changed)
+
+Count = 67
+Nonce = f477f754d7ee76
+Adata = 00
+CT = 3b5ae49e0974f41826152432b46f1a85ab4995afefbbccddfc9fd290
+Result = Fail (2 - CT changed)
+
+Count = 68
+Nonce = 040a257dede70e
+Adata = 00
+CT = 21fb4324de4ba1e2762b3041ce26e43a3d191458a046d489e485910b
+Result = Fail (2 - CT changed)
+
+Count = 69
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = 99ca8f542fd06481e23719214c9892442f393d72899deea08695053f
+Result = Fail (1 - Adata changed)
+
+Count = 70
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 5fcc05342cdc27f66b324ae7387205bfb4ab6302bfe0af09050d2054
+Result = Fail (1 - Adata changed)
+
+Count = 71
+Nonce = f67b98efd39b55
+Adata = 00
+CT = 0a7fe63046daf8a979935b897088c64acc1b47a5a9b86fdd6def28ab
+Result = Pass (0)
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 72
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = daf7d7dfa512ceb1d7d3435634d9a70b3ef6c6dc38f409e068941fce
+Result = Pass (0)
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 73
+Nonce = 098e053fa08043
+Adata = 00
+CT = cdb417dff6502208775f21e35cdb8e3e1199308d1a94229051a1ec4a
+Result = Pass (0)
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 74
+Nonce = 4bf48328725514
+Adata = 00
+CT = e75441093c8ccba6eac5913dc246ce96de4784a01051498298eaddaf
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = 197afb02ffbd8f699dacae87094d524324576b99844f75e1
+
+Count = 75
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = cba4b4aeb85f0492fd8d905c4a6d8233139833373ef188a8c5a5ebecf7ac8607fe412189e83d9d20
+Result = Pass (0)
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 76
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = ca62713728b5c9d652504b0ae8fd4fee5d297ee6a8d19cb6e699f15f14d34dcaf9ba8ed4b877c97d
+Result = Fail (2 - CT changed)
+
+Count = 77
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = 93012c0a5f6f1025b8c4a5d897d3eea0b1c77be8000c9e59f3b8899459788c58794f177cfd838f35
+Result = Fail (1 - Adata changed)
+
+Count = 78
+Nonce = 9cbce402511b89
+Adata = 00
+CT = b8eb95f72f643c2c51ad74775cc203d215c86626e903eb013ad22e8fa4d2f9725ce4f212a8844855
+Result = Fail (1 - Adata changed)
+
+Count = 79
+Nonce = 123a0beace4e39
+Adata = 00
+CT = 71f17cf21c44267c676657db9e55bee33273787474e77b17b5eab45d7d096577643815e6d467312d
+Result = Pass (0)
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 80
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = d6737f642260c4ee3b19cb78cc2ef1767213416b82c71e918b1a5ecca7354af824fea617b9b69031
+Result = Fail (2 - CT changed)
+
+Count = 81
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = cbe60d633399daa6ee66418be6d16e292ea47a93c291fce2c54c98f8007ed55a21759f5452559538
+Result = Fail (1 - Adata changed)
+
+Count = 82
+Nonce = f477f754d7ee76
+Adata = 00
+CT = 2a78a7beb8df4bf5d35ff0b2853bc51ce127163d2f56e00ea555aa972e1c2e3f439f85663ae25889
+Result = Fail (2 - CT changed)
+
+Count = 83
+Nonce = 040a257dede70e
+Adata = 00
+CT = ee78ddbea9c3aede9f88af0e82464d9d1afe81de16aa18c49aeb326578fa615e86969348d9bbfb7f
+Result = Fail (2 - CT changed)
+
+Count = 84
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = cdf7cb74d978e7ea738e288ed79edfccf10b553c09d1856e2efbff1da769af3b72099cbda3cbf091
+Result = Fail (1 - Adata changed)
+
+Count = 85
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 90b990a1ea254592f2c226c969b332fc7bfe5f808729c2d83291a566e6641a965ffdabe097050dc5
+Result = Fail (1 - Adata changed)
+
+Count = 86
+Nonce = f67b98efd39b55
+Adata = 00
+CT = 44a6aa954c3508b3c9264c20c272e80c0e95d50ddec2849084b47504dced5b70c302cc93502cc37e
+Result = Pass (0)
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 87
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = 9d4ff7a44cdb9b14f586efc3d6be02d069b425c06bec4eed37109739a3676f03adfd740dbaa4940d
+Result = Pass (0)
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 88
+Nonce = 098e053fa08043
+Adata = 00
+CT = 23da95e102c7921a51b19b5733ea5776ab6c287f6057c00ec4bfacbb2f246b570efd93d98e99be49
+Result = Pass (0)
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 89
+Nonce = 4bf48328725514
+Adata = 00
+CT = 53d00d5839d0a1e695916151f9450b7311982917edcbd7c66496912db41761a1d2aecfda04fb2cfa
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = 197afb02ffbd8f699dacae87094d524324576b99844f75e1
+
+Count = 90
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 042653c674ef2a90f7fb11d30848e530ae59478f1051633a34fad277
+Result = Pass (0)
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 91
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 1902d9769a7ba3d3268e1257395c8c2e5f98eef295dcbfa5a35df775
+Result = Fail (2 - CT changed)
+
+Count = 92
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = ebacb8e78c0ad9d3ed99f1821b0b0085beac351f88a79ef71faaf310
+Result = Fail (1 - Adata changed)
+
+Count = 93
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = efc1d5b6f0a48e4ce3e821d743d34206b28c69485c410fa94d5e6103
+Result = Fail (1 - Adata changed)
+
+Count = 94
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 3c1836e5d0f0473dab7bfd7a95ba69575f7f841970ac6c6769ac966a
+Result = Pass (0)
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 95
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = 2c583e54d75a02948c7f6dcd12cba32a65e8d605fba7ec10c47e9a8e
+Result = Fail (2 - CT changed)
+
+Count = 96
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = a8632dee22f34315b05c40135c6dd471c63b09438da834dc1f3f537f
+Result = Fail (1 - Adata changed)
+
+Count = 97
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = 0f03ea1b2561951d79062e19a85d98293c8c2846936c724c26421940
+Result = Fail (2 - CT changed)
+
+Count = 98
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = f9764405e54d827ac433fd624506b92e123463a5b01f21ffa3a22ac7
+Result = Fail (2 - CT changed)
+
+Count = 99
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = a326e0cf3f97adff3249944880ddfb8d616cd18a086e046289429246
+Result = Fail (1 - Adata changed)
+
+Count = 100
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = f188bc1a72e81b34d75b402e4f8ef3d638d2f56a409eab064c9649b7
+Result = Fail (1 - Adata changed)
+
+Count = 101
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = 341df3a273e85cf387ab823bdf9c34a1ae2c86940cb4bfcde2e93f29
+Result = Pass (0)
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 102
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = a0e7997fd67ea66b6274d719b84da92433fdf7d512b160da35c7081d
+Result = Pass (0)
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 103
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = dd8fd11e1c0746e7273fdd2e7dfa1ee4fc8ad835ca3141c0f83a9ad7
+Result = Pass (0)
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 104
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = 39b0d3603f1289b5885ac244953275d28491952e7e57d93c7ff1eb5d
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 90929a4b0ac65b350ad1591611fe48297e03956f6083e451
+
+Count = 105
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = a5b7d8cca2069908d1ed88e6a9fe2c9bede3131dad54671ea7ade30a07d185692ab0ebdf4c78cf7a
+Result = Pass (0)
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 106
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 9a98617fb97a0dfe466be692272dcdaec1c5443a3b51312ef042c86363cc05afb98c66e16be8a445
+Result = Fail (2 - CT changed)
+
+Count = 107
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = d3068ae815c3605d7670058abb9384f4c15b75150eb7910041a8f6ac697430627826bd76b19da027
+Result = Fail (1 - Adata changed)
+
+Count = 108
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = 388a289bb85533b667b141a78d0c79acdeb9fbf72886d5ab980581017fefef92c2b50ae20b93c81c
+Result = Fail (1 - Adata changed)
+
+Count = 109
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 71f68480a8801d4966c84807c5ff6139d83ba0a5b902bee3327f5f91763c0a0bec43264c27cd237f
+Result = Pass (0)
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 110
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = 8627bf1e3edafc69f1328c393dd8e7bd1c182d021e6d3a3652c4b7fd911ca77950ff2d035e47b7ec
+Result = Fail (2 - CT changed)
+
+Count = 111
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = b10ea86a384432a45f50b3c2e482595b46c81c61ca39bc0f4ffcb29bde8b9a81945d671b0f619045
+Result = Fail (1 - Adata changed)
+
+Count = 112
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = 3ace8b7e03a0c1fa9e97f46975ab0a4924446e791540e225578cc14aa558e18d5f777ab6e16dcfee
+Result = Fail (2 - CT changed)
+
+Count = 113
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = 8190abe4c21e320e10825e269190bb10a354691958e2436275433c4ae28757c8544c86f1f74ea6a5
+Result = Fail (2 - CT changed)
+
+Count = 114
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = 1d7e308c34cdca7b7b222f4ebc92afd8055bff542c0b76d3d7752ebe9c5dbf00ee8ad60ac34dd7d0
+Result = Fail (1 - Adata changed)
+
+Count = 115
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = 9c2609f7af5b634a16e58f2e9cc7a9ef7812a12d209847000a4432b35d3b884e4169c28d287499ff
+Result = Fail (1 - Adata changed)
+
+Count = 116
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = 5b0b5e6690d648e1b92c12cfddb431d6d3dfe689d01db8199256ace490c2f0afb93ba32be58fd1de
+Result = Pass (0)
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 117
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = 8722fca71fdf750ec5d62fc6d7ba079aef19210da764067aefd8535dd6b7fa701c9ca8c8b635c30b
+Result = Pass (0)
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 118
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = 91ac457f5e53492301e72d9d495277ed17edb30e8c7a48d21b5d2cd4d5b6d2ef48413245a6b27b67
+Result = Pass (0)
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 119
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = d2fe5293b7d53ed46ddf02a5618039adbae22845ce72e434fdc83ea4863c3e84a5456f7f853a1ea6
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 90929a4b0ac65b350ad1591611fe48297e03956f6083e451
+
+Count = 120
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 1d089a5f
+Result = Pass (0)
+Payload = 00
+
+Count = 121
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = 2f46022a
+Result = Fail (2 - CT changed)
+
+Count = 122
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 67dc4693
+Result = Fail (1 - Adata changed)
+
+Count = 123
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 7027a849
+Result = Fail (1 - Adata changed)
+
+Count = 124
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = 5c6a4de2
+Result = Pass (0)
+Payload = 00
+
+Count = 125
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 1d855f5d
+Result = Fail (2 - CT changed)
+
+Count = 126
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = 1b318980
+Result = Fail (1 - Adata changed)
+
+Count = 127
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = cf871f91
+Result = Fail (2 - CT changed)
+
+Count = 128
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = 4f0e04bc
+Result = Fail (2 - CT changed)
+
+Count = 129
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = fc9013df
+Result = Fail (1 - Adata changed)
+
+Count = 130
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = 5134def3
+Result = Fail (1 - Adata changed)
+
+Count = 131
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = 5814103a
+Result = Pass (0)
+Payload = 00
+
+Count = 132
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = 74c75c4a
+Result = Pass (0)
+Payload = 00
+
+Count = 133
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = 9884898b
+Result = Pass (0)
+Payload = 00
+
+Count = 134
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 0b1cbfb1
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b12ab744b61c070e2
+
+Count = 135
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 5280a2137fee3deefcfe9b63a1199fb3
+Result = Pass (0)
+Payload = 00
+
+Count = 136
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = d40a7318c5f2d82f838c0beeefe0d598
+Result = Fail (2 - CT changed)
+
+Count = 137
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 7551978bc9592bf9e294b4984c5862bb
+Result = Fail (1 - Adata changed)
+
+Count = 138
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 859cf444f89225b32a55a1645bd24979
+Result = Fail (1 - Adata changed)
+
+Count = 139
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = 29e967a0245607c36cf3eaf00fdae566
+Result = Pass (0)
+Payload = 00
+
+Count = 140
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 9daa0e1c4df5f2bf507b1a57a1135b86
+Result = Fail (2 - CT changed)
+
+Count = 141
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = 18caec79720a5d67d7457e9b7c7a153c
+Result = Fail (1 - Adata changed)
+
+Count = 142
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = 5f2c455546c56f514a0f69f05345c2c4
+Result = Fail (2 - CT changed)
+
+Count = 143
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = b7e4846ff30b7c3673a962a2701c0387
+Result = Fail (2 - CT changed)
+
+Count = 144
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = 7b5fa0d42a616ab05ac2c58c904ce92f
+Result = Fail (1 - Adata changed)
+
+Count = 145
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = c8c67f558b5844b149dd47824c8cb9d8
+Result = Fail (1 - Adata changed)
+
+Count = 146
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = 70a09aaf22ac316124a169f6b0a83ffe
+Result = Pass (0)
+Payload = 00
+
+Count = 147
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = 5bc85ed5521a91b9eb42b437950f0e06
+Result = Pass (0)
+Payload = 00
+
+Count = 148
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = 989ec0e7b192ea010dd61d3fb64e8de0
+Result = Pass (0)
+Payload = 00
+
+Count = 149
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 15c2dbe7fa307654d8ca7c0f8d6d2f14
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b12ab744b61c070e2
+
+Count = 150
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 5e0eaebd
+Result = Pass (0)
+Payload = 00
+
+Count = 151
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = 71b7fc33
+Result = Fail (2 - CT changed)
+
+Count = 152
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = 93227bd4
+Result = Fail (1 - Adata changed)
+
+Count = 153
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = ced654e2
+Result = Fail (1 - Adata changed)
+
+Count = 154
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = bf7a8e0c
+Result = Pass (0)
+Payload = 00
+
+Count = 155
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = 840caa3e
+Result = Fail (2 - CT changed)
+
+Count = 156
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = 1e22fc41
+Result = Fail (1 - Adata changed)
+
+Count = 157
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = 968ccbbf
+Result = Fail (2 - CT changed)
+
+Count = 158
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 0a31cc96
+Result = Fail (2 - CT changed)
+
+Count = 159
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = a456c3da
+Result = Fail (1 - Adata changed)
+
+Count = 160
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = 29746eea
+Result = Fail (1 - Adata changed)
+
+Count = 161
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = df7f63ca
+Result = Pass (0)
+Payload = 00
+
+Count = 162
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = bf0b1445
+Result = Pass (0)
+Payload = 00
+
+Count = 163
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = ae8533f5
+Result = Pass (0)
+Payload = 00
+
+Count = 164
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = 9426cf89
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = f9fdca4ac64fe7f014de0f43039c757194d544ce5d15eed4
+
+Count = 165
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = d07ccf9fdc3d33aa94cda3d230da707c
+Result = Pass (0)
+Payload = 00
+
+Count = 166
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = 65fe32b649dc328c9f531584897e85b3
+Result = Fail (2 - CT changed)
+
+Count = 167
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = ec31fb6b41c2dae87cf395fc1fe3a080
+Result = Fail (1 - Adata changed)
+
+Count = 168
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = 33c2f2312dd5bfcadbb05f8d0a33fd4a
+Result = Fail (1 - Adata changed)
+
+Count = 169
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = a9e81afd1030d195c679e2c837aeb736
+Result = Pass (0)
+Payload = 00
+
+Count = 170
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = 1db000f0e7d3a03718293fc118678427
+Result = Fail (2 - CT changed)
+
+Count = 171
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = ea37900f049db8fc5cbf46edb5fcac2c
+Result = Fail (1 - Adata changed)
+
+Count = 172
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = d1097ebd7ad0a41f61ba32a44dc15305
+Result = Fail (2 - CT changed)
+
+Count = 173
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 0979729272d8b42f2e3dc0eb181a1217
+Result = Fail (2 - CT changed)
+
+Count = 174
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = 4457200916a20116b096225606f1a9e2
+Result = Fail (1 - Adata changed)
+
+Count = 175
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = cc6b51f39a3dcfb54abbb89f4df21114
+Result = Fail (1 - Adata changed)
+
+Count = 176
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = aac09cef9697927331251f028d24c31f
+Result = Pass (0)
+Payload = 00
+
+Count = 177
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = 56c00070eae0db329894a045d866bbaf
+Result = Pass (0)
+Payload = 00
+
+Count = 178
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = 090016bb96aeaabbf66fd34fc97591a4
+Result = Pass (0)
+Payload = 00
+
+Count = 179
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = 264407dfe796bf7f6eb1f26c1f8504ef
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = f9fdca4ac64fe7f014de0f43039c757194d544ce5d15eed4
+
+Count = 180
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 9f6ca4af9b159148c889a6584d1183ea26e2614874b0504575dea8d1
+Result = Pass (0)
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 181
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = 84d8212e9cfc2121252baa3b065b1edcf50497b9594db1ebd7965825
+Result = Fail (2 - CT changed)
+
+Count = 182
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 5f60a8f867a33b2077ecc69863b295c3c6aeae7d7cade7f8f7f796fe
+Result = Fail (1 - Adata changed)
+
+Count = 183
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 1353b3fa1bb1d57ffb139017885c02e26c90231a24b5a615b8f1f2ae
+Result = Fail (1 - Adata changed)
+
+Count = 184
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = c3116d9040e1ed4f7c9464d270fb302bd3f1561c25c5b95b8b4b53f6
+Result = Pass (0)
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 185
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 0ca17e8f89bea67db48a8f132ef6c6df7a292914d401299af6bf3800
+Result = Fail (2 - CT changed)
+
+Count = 186
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = 0ce543569e8187f3cec70399ff922e4903cb1d12f990f05613244cf6
+Result = Fail (1 - Adata changed)
+
+Count = 187
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = 3acdbc163a350f312791b152a41e57627b1cc8bf3e41c8aea5876de8
+Result = Fail (2 - CT changed)
+
+Count = 188
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = 604518e436edf7a0561d5e284f3915839a6d28cb06ef792a1970ed17
+Result = Fail (2 - CT changed)
+
+Count = 189
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = fc79b520d67da891e63654d7927db6c8012c96985a0059d5f68d8da4
+Result = Fail (1 - Adata changed)
+
+Count = 190
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = d86bb51a98770098d0feb39170bd979199a8f741041df13790ee4c14
+Result = Fail (1 - Adata changed)
+
+Count = 191
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = 51b6b928bdd1cc0bd0a0aed2cda302472d618ffaa60e179029c87855
+Result = Pass (0)
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 192
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = d0abab9b8e9d6c11bb9c15bea8a486704bed32c57297055b4de8ed8d
+Result = Pass (0)
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 193
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = 92fd519a966c0fbdd7087ff5a1bd946cd663502db378383531d69947
+Result = Pass (0)
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 194
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = 7f239b1916830161f3b52b7ab13542a5a0a97a17f30ca5fa30768d4d
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = a7aa635ea51b0bb20a092bd5573e728ccd4b3e8cdd2ab33d
+
+Count = 195
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 6aab64c4787599d8f213446beadb16e08dba60e97f56dbd14d1d980d6fe0fb44b421992662b97975
+Result = Pass (0)
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 196
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = 4980b2ee49b1aaf393175f5ab9bae95ec7904557dfa206603c51d36c826f01384100886198a7f6a3
+Result = Fail (2 - CT changed)
+
+Count = 197
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 86a02bdd6ae733eee26f8eab898b336105978b5bbd6df781758a111aae4f735b7dd4d9802f2a8406
+Result = Fail (1 - Adata changed)
+
+Count = 198
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 59cfab8956813c48e09332a2bb8a30dbcdf5afb2529532ab8cef14ebc2951069739d5d657d82addb
+Result = Fail (1 - Adata changed)
+
+Count = 199
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = 67d989ea935b9ce190e3a7f3b645305e1e308a7fe617f80f170a2b9c309de6c2326115a76efbdf98
+Result = Pass (0)
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 200
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 2522a5e4d157193ef2c264cfe877db8ac75b3cc5aab08a814bcd14af0205af716f2b864f0c397f65
+Result = Fail (2 - CT changed)
+
+Count = 201
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = 4536422bbad220079ee09e700e103efdaac832d016a20813762d5d8adafe75a191310a2618930c48
+Result = Fail (1 - Adata changed)
+
+Count = 202
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = d6711a78adf54f4effe647d531c4618cf32e3037eb700580206f80080dfa3e66e6371c0cde6cd205
+Result = Fail (2 - CT changed)
+
+Count = 203
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = e44034a397778e1c6babab27f5a50fa4aac0e83d6b3eb25db1b5b2b35c8a8125efccd1f4102f3e82
+Result = Fail (2 - CT changed)
+
+Count = 204
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = b8e31c5910623e405f2ebf65821963e5b8814043612395feca36f53b01943f03cb8b69b5af53e505
+Result = Fail (1 - Adata changed)
+
+Count = 205
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = 4000faf8558f2f4e01e45e90796cd236e5211d1704270f31c3bfc6851049d32105fd16bd45b29f29
+Result = Fail (1 - Adata changed)
+
+Count = 206
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = 53bb608f6236798839af35888cb0fa4797b599271084cc13847b022733ca5a5e3c4d472332484b7f
+Result = Pass (0)
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 207
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = be54551d1d2f1b3eb60ffe3b165524ff90ca09fb252bf21c1c79edbf38c50e0f240a2d70f65aa79f
+Result = Pass (0)
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 208
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = f07c1072d8f8e077dfbb3ad86dd92d32b41f29e647dcd7e3a82cd3ebaf6c2d3e21749bdf570ad28d
+Result = Pass (0)
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 209
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = 7f7cf7f4d0645934cb0a5e67b4227a909aa55dba09b2c39cef93a8759845326683a0d9c22151f486
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = a7aa635ea51b0bb20a092bd5573e728ccd4b3e8cdd2ab33d
+
+Count = 210
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 16e543d0e20615ff0df15acd9927ddfe40668a54bb854cccc25e9fce
+Result = Pass (0)
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 211
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = df35b109caf690656ae278bbd8f8bba687a2ce11b105dae98ecedb3e
+Result = Fail (2 - CT changed)
+
+Count = 212
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = 7075da2291e2cb527eb926ed08d8020c5f8f0f2d4a6a4745728da544
+Result = Fail (1 - Adata changed)
+
+Count = 213
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = 18a77a66457b53286b1aea0845304cac8e66a02d5c642e4c02a9b9bc
+Result = Fail (1 - Adata changed)
+
+Count = 214
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = 24e1d3820101412d8f4d57118cab8f7e489d5cac78802dd5ccf8ecf0
+Result = Pass (0)
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 215
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = b5929bc9648e24a553c5cd953ecb9d67ee508d2d4ac7b46e661181d5
+Result = Fail (2 - CT changed)
+
+Count = 216
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = 54aa018dc7fdf8a54809e1393d18031bab4aa5ca35c201907d74517d
+Result = Fail (1 - Adata changed)
+
+Count = 217
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = 69bcc300a459862b3cd284c15dd4af53dc7e95f3067bb8254a8edd83
+Result = Fail (2 - CT changed)
+
+Count = 218
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = 5c2d2df0d8aade3e5ae0f8d8b4b4d7c565817a31b2865dc270ad39a6
+Result = Fail (2 - CT changed)
+
+Count = 219
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = df1b3f98b6b0060191e7eb817f5908ddc0bc6f83860349e8ae423997
+Result = Fail (1 - Adata changed)
+
+Count = 220
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = 16e59dd38395c7be7f580371edabb1e9bf21270de270aa283309108e
+Result = Fail (1 - Adata changed)
+
+Count = 221
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = 0ef8981dd37c055a3c3e14786fc662b2a11065964911d35ebcc87096
+Result = Pass (0)
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 222
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = fc1870cfc440f74f73f40e682cf4713d027c297b9426c3efe981e935
+Result = Pass (0)
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 223
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 9fc2c462dff1ba9756772d73de5c4e822b5ea0bc88845a323b98de4f
+Result = Pass (0)
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 224
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 05fc586d5c780b8e06f618b5bb85f591665a54390eba4e14af3b74e1
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886
+
+Count = 225
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = c5b0b2ef17498c5570eb335df4588032958ba3d69bf6f3178464a6f7fa2b76744e8e8d95691cecb8
+Result = Pass (0)
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 226
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = d1f0518929f4ae2f0543de2a7dfe4bb0110bb3057e524a1c06bd6dc2e6bcc3436cffb969ae900388
+Result = Fail (2 - CT changed)
+
+Count = 227
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = 1aa7dfa3a9818142c4971cbf4f64d4cbdbd354c6958ef474bb56d90669c726d866fe2206b8828727
+Result = Fail (1 - Adata changed)
+
+Count = 228
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = 90352a5ec92d4fa52a96ae28251a57933728b2a3670e2ecd9953fec4e091b3573214e1ecac1ac00c
+Result = Fail (1 - Adata changed)
+
+Count = 229
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = eaa995946ed91d6a08ade14b260ac752cbd1081d5a7cad90783618374f6d03df28ee57a1a5aa38d8
+Result = Pass (0)
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 230
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = 0e320c4ece6ef0305a431a07a5a34d463ec4a37fc513c4b947bb3f30d6e674d10a496806c1c8933e
+Result = Fail (2 - CT changed)
+
+Count = 231
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = 10685888091597c50acc54b2fb65150b83a7115351d6f8bd7dd7ee3f75cfb47fa72433644f9cf62e
+Result = Fail (1 - Adata changed)
+
+Count = 232
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = e456abf9ee83e0a68fbdb09c4a7afaba0efb0aa6d74a17c443314076072a0ebd253fe1ab4883ebea
+Result = Fail (2 - CT changed)
+
+Count = 233
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = 5adadfd296edaf4bea92c8245983dc31b11335f682fb222c16a72444f0949868f0e71907acbb29f4
+Result = Fail (2 - CT changed)
+
+Count = 234
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = c2bb4d5a830646b3f8bf84044851c3b676c4ec02e43dcbf1ab2025208191d73041c038cf2562bb8c
+Result = Fail (1 - Adata changed)
+
+Count = 235
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = 9589b8abcb47e54e6e8fad3e64fec7ed4f70ac435bb3e548b7e6d183efa1f51b7ff31eaa52ed59ba
+Result = Fail (1 - Adata changed)
+
+Count = 236
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = af63f27e2a9e70f106477493dc141d16a1d059dd7a8a7810d990b642039f24755790332b3cc47c49
+Result = Pass (0)
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 237
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = 1d2ae88c878684a0b404986252b3a7583e1a5a51163ddc606d3968fdceaae5138c411a29d0d333ee
+Result = Pass (0)
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 238
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 30c154c616946eccc2e241d336ad33720953e449a0e6b0f0dbf8e9464909bdf337e48093c082a10b
+Result = Pass (0)
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 239
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 0c95b692b07b39039b40c80cf52ff71608ae87c973ac9ccb88bba8f204bb98b17cb3c8644e472b1e
+Result = Fail (2 - CT changed)
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.rsp
new file mode 100644
index 0000000000..b8045d8291
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.rsp
@@ -0,0 +1,1589 @@
+# CAVS 11.0
+# "CCM-DVPT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:26 2011
+
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = eda32f751456e33195f1f499cf2dc7c97ea127b6d488f211ccc5126fbb24afa6
+
+Count = 0
+Nonce = a544218dadd3c1
+Adata = 00
+CT = 469c90bb
+Result = Pass
+Payload = 00
+
+Count = 1
+Nonce = d3d5424e20fbec
+Adata = 00
+CT = 46a908ed
+Result = Fail
+
+Count = 2
+Nonce = e776620a3bd961
+Adata = 00
+CT = fdd35c4d
+Result = Fail
+
+Count = 3
+Nonce = 6c7a3be9f9ad55
+Adata = 00
+CT = 869ce60e
+Result = Fail
+
+Count = 4
+Nonce = dbb3923156cfd6
+Adata = 00
+CT = 1302d515
+Result = Pass
+Payload = 00
+
+Count = 5
+Nonce = b390f67eaef8f5
+Adata = 00
+CT = 156416ee
+Result = Fail
+
+Count = 6
+Nonce = a259c114eaac89
+Adata = 00
+CT = 4fe06e92
+Result = Pass
+Payload = 00
+
+Count = 7
+Nonce = 7fc8804fef18ef
+Adata = 00
+CT = 611091aa
+Result = Fail
+
+Count = 8
+Nonce = fbaf4cbc49fa0f
+Adata = 00
+CT = 696e9371
+Result = Fail
+
+Count = 9
+Nonce = 2ed0c8761dbf04
+Adata = 00
+CT = a0e0a2cb
+Result = Fail
+
+Count = 10
+Nonce = 346bb04ea0db86
+Adata = 00
+CT = 43cc0375
+Result = Fail
+
+Count = 11
+Nonce = e1be89af98ffd7
+Adata = 00
+CT = e5417f6b
+Result = Pass
+Payload = 00
+
+Count = 12
+Nonce = a6a0d57aaaf012
+Adata = 00
+CT = fff8a068
+Result = Fail
+
+Count = 13
+Nonce = 1aa758eb2f9a28
+Adata = 00
+CT = f8fa8e71
+Result = Pass
+Payload = 00
+
+Count = 14
+Nonce = 2911167fc98fc3
+Adata = 00
+CT = 0bfa2d9d
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = e1b8a927a95efe94656677b692662000278b441c79e879dd5c0ddc758bdc9ee8
+
+Count = 15
+Nonce = a544218dadd3c1
+Adata = 00
+CT = 8207eb14d33855a52acceed17dbcbf6e
+Result = Pass
+Payload = 00
+
+Count = 16
+Nonce = d3d5424e20fbec
+Adata = 00
+CT = 60f8e127cb4d30db6df0622158cd931d
+Result = Fail
+
+Count = 17
+Nonce = e776620a3bd961
+Adata = 00
+CT = 4239f29871651e9a26b8b06ffc5b3748
+Result = Fail
+
+Count = 18
+Nonce = 6c7a3be9f9ad55
+Adata = 00
+CT = 5d35364c621fe8959dfe70ab44700fbe
+Result = Fail
+
+Count = 19
+Nonce = dbb3923156cfd6
+Adata = 00
+CT = e4dc5e03aacea691262ee69cee8ffbbe
+Result = Pass
+Payload = 00
+
+Count = 20
+Nonce = b390f67eaef8f5
+Adata = 00
+CT = c8eb7643b4ed3c796c3873e8c6624e0d
+Result = Fail
+
+Count = 21
+Nonce = a259c114eaac89
+Adata = 00
+CT = f79c53fd5e69835b7e70496ea999718b
+Result = Pass
+Payload = 00
+
+Count = 22
+Nonce = 7fc8804fef18ef
+Adata = 00
+CT = 687e00723a419fa81c0923b8b8e245ae
+Result = Fail
+
+Count = 23
+Nonce = fbaf4cbc49fa0f
+Adata = 00
+CT = 499ab350309ad6091ec4aaf6bf0cbd00
+Result = Fail
+
+Count = 24
+Nonce = 2ed0c8761dbf04
+Adata = 00
+CT = c27b9f14787dc5375f59d0c561a23446
+Result = Fail
+
+Count = 25
+Nonce = 346bb04ea0db86
+Adata = 00
+CT = 655c737722c78ac96582a883d407b2bb
+Result = Fail
+
+Count = 26
+Nonce = e1be89af98ffd7
+Adata = 00
+CT = 10d3f6fe08280d45e67e58fe41a7f036
+Result = Pass
+Payload = 00
+
+Count = 27
+Nonce = a6a0d57aaaf012
+Adata = 00
+CT = b4e425e43edb92c606f7cb2de8a06932
+Result = Fail
+
+Count = 28
+Nonce = 1aa758eb2f9a28
+Adata = 00
+CT = 2590df2453cb94c304ba0a2bff3f3c71
+Result = Pass
+Payload = 00
+
+Count = 29
+Nonce = 2911167fc98fc3
+Adata = 00
+CT = 1f344e30dfa95b2319e274caa5780e60
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = e1b8a927a95efe94656677b692662000278b441c79e879dd5c0ddc758bdc9ee8
+
+Count = 30
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = 8a19a133
+Result = Pass
+Payload = 00
+
+Count = 31
+Nonce = 3c0e2815d37d844f7ac240ba9d
+Adata = 00
+CT = 2e317f1b
+Result = Fail
+
+Count = 32
+Nonce = 75549e7e5657e5fe19872fcee0
+Adata = 00
+CT = 979bdcfe
+Result = Fail
+
+Count = 33
+Nonce = d071ff72735820d73485870e83
+Adata = 00
+CT = 8ef89acf
+Result = Fail
+
+Count = 34
+Nonce = 79ac204a26b9fee1132370c20f
+Adata = 00
+CT = 154024b2
+Result = Pass
+Payload = 00
+
+Count = 35
+Nonce = a64bbc3d6d377dab513f7d9ce8
+Adata = 00
+CT = 8dbcc439
+Result = Fail
+
+Count = 36
+Nonce = 0545fd9ecbc73ccdbbbd4244fd
+Adata = 00
+CT = 5c349fb2
+Result = Pass
+Payload = 00
+
+Count = 37
+Nonce = 182fb47a12becf0bfe65df1287
+Adata = 00
+CT = 79df3e02
+Result = Fail
+
+Count = 38
+Nonce = f342059a6f9dc14226b40debc4
+Adata = 00
+CT = fbc2c500
+Result = Fail
+
+Count = 39
+Nonce = 6cbfe6bb4c9b171b93d28e9f8f
+Adata = 00
+CT = 2fac1bca
+Result = Fail
+
+Count = 40
+Nonce = 82877df921c6ade43064ad963e
+Adata = 00
+CT = 99948f6e
+Result = Fail
+
+Count = 41
+Nonce = 0a37f2e7c66490e97285f1b09e
+Adata = 00
+CT = c59bf14c
+Result = Pass
+Payload = 00
+
+Count = 42
+Nonce = d7b9c346ce2f8bad9623122e10
+Adata = 00
+CT = b764c393
+Result = Fail
+
+Count = 43
+Nonce = c1ad812bf2bbb2cdaee4636ee7
+Adata = 00
+CT = 5b96f41d
+Result = Pass
+Payload = 00
+
+Count = 44
+Nonce = b6ce7d00731184b24428df046b
+Adata = 00
+CT = f7e12df1
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = af063639e66c284083c5cf72b70d8bc277f5978e80d9322d99f2fdc718cda569
+
+Count = 45
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = 97e1a8dd4259ccd2e431e057b0397fcf
+Result = Pass
+Payload = 00
+
+Count = 46
+Nonce = 3c0e2815d37d844f7ac240ba9d
+Adata = 00
+CT = 5a9596c511ea6a8671adefc4f2157d8b
+Result = Fail
+
+Count = 47
+Nonce = 75549e7e5657e5fe19872fcee0
+Adata = 00
+CT = 66f5c53efbc74fa02dedc303fd95133a
+Result = Fail
+
+Count = 48
+Nonce = d071ff72735820d73485870e83
+Adata = 00
+CT = 2dfd3c852f68eace45acf433a6aa9c05
+Result = Fail
+
+Count = 49
+Nonce = 79ac204a26b9fee1132370c20f
+Adata = 00
+CT = 5c8c9a5b97be8c7bc01ca8d693b809f9
+Result = Pass
+Payload = 00
+
+Count = 50
+Nonce = a64bbc3d6d377dab513f7d9ce8
+Adata = 00
+CT = ec093121bdcd589285f2262be8db5c4e
+Result = Fail
+
+Count = 51
+Nonce = 0545fd9ecbc73ccdbbbd4244fd
+Adata = 00
+CT = 84201662b213c7a1ff0c1b3c25e4ec45
+Result = Pass
+Payload = 00
+
+Count = 52
+Nonce = 182fb47a12becf0bfe65df1287
+Adata = 00
+CT = bbe746d6d31e8e9745faed4095ab8d5d
+Result = Fail
+
+Count = 53
+Nonce = f342059a6f9dc14226b40debc4
+Adata = 00
+CT = 646c1258dc4aa6fc380818e70e5f4328
+Result = Fail
+
+Count = 54
+Nonce = 6cbfe6bb4c9b171b93d28e9f8f
+Adata = 00
+CT = 15fa37ca7f2883a4642c1ed41b8f6293
+Result = Fail
+
+Count = 55
+Nonce = 82877df921c6ade43064ad963e
+Adata = 00
+CT = c6acf5e5ded4efb2c314370ebb9e9cde
+Result = Fail
+
+Count = 56
+Nonce = 0a37f2e7c66490e97285f1b09e
+Adata = 00
+CT = 586e728193ce6db9a926b03b2d77dd6e
+Result = Pass
+Payload = 00
+
+Count = 57
+Nonce = d7b9c346ce2f8bad9623122e10
+Adata = 00
+CT = 642a187e71feff5989e28184aded0199
+Result = Fail
+
+Count = 58
+Nonce = c1ad812bf2bbb2cdaee4636ee7
+Adata = 00
+CT = 64864d21b6ee3fca13f07fc0486e232d
+Result = Pass
+Payload = 00
+
+Count = 59
+Nonce = b6ce7d00731184b24428df046b
+Adata = 00
+CT = 58c63ce68f132d30d177c5834344cc5d
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = af063639e66c284083c5cf72b70d8bc277f5978e80d9322d99f2fdc718cda569
+
+Count = 60
+Nonce = a544218dadd3c1
+Adata = 00
+CT = 64a1341679972dc5869fcf69b19d5c5ea50aa0b5e985f5b722aa8d59
+Result = Pass
+Payload = d3d5424e20fbec43ae495353ed830271515ab104f8860c98
+
+Count = 61
+Nonce = bfcda8b5a2d0d2
+Adata = 00
+CT = c5b7f802bffc498c1626e3774f1d9f94045dfd8e1a10a20277d00a75
+Result = Fail
+
+Count = 62
+Nonce = 6bae7f35c56b27
+Adata = 00
+CT = bf432e246b7fa4aff8b3ada738432b51f6872ed92284db9d28588021
+Result = Fail
+
+Count = 63
+Nonce = c5e4214b1bf209
+Adata = 00
+CT = 0d5760ad0e156e401120a1ebd1b139248784c88e10e3425437921120
+Result = Fail
+
+Count = 64
+Nonce = 9d773a31fe2ec7
+Adata = 00
+CT = 5acfbe5e488976d8b9b77e69a736e8c919053f9415551209dce2d25e
+Result = Pass
+Payload = 839d8cfa2c921c3cceb7d1f46bd2eaad706e53f64523d8c0
+
+Count = 65
+Nonce = f42cb0cce9efb6
+Adata = 00
+CT = be8be6046ac58411a00c131dd4a72d565f98d87a2c89124b1ef530d0
+Result = Fail
+
+Count = 66
+Nonce = 24b7a65391f88b
+Adata = 00
+CT = f00628e10e8e0115b4a4532a1212a23aade4090832c1972d750125f3
+Result = Pass
+Payload = 3bed52236182c19418867d468dbf47c8aac46c02445f99bb
+
+Count = 67
+Nonce = d2a7eb45780df3
+Adata = 00
+CT = 9078151f674d5f7b56e2451b0316156f776459f17d277e0108aaaf93
+Result = Fail
+
+Count = 68
+Nonce = 046cbfd26093d8
+Adata = 00
+CT = 921cbecce3b06f3d655a5a0a4d212320d4f147575079fd23bd95e677
+Result = Fail
+
+Count = 69
+Nonce = 51b13b0b04d077
+Adata = 00
+CT = 8cab1ff22d474e9863c153e84680e2a66981f036051360477e2ebb1d
+Result = Fail
+
+Count = 70
+Nonce = ce2e9967bf9eb7
+Adata = 00
+CT = 15f476b5aefe072548a54f59506d9c3b9ce29025340214be662f8684
+Result = Fail
+
+Count = 71
+Nonce = b672c91376f533
+Adata = 00
+CT = 758aa03dc72c362c43b5f85bfaa3db4a74860887a8c29e47d5642830
+Result = Pass
+Payload = 4f7a561e61b7861719e4445057ac9b74a9be953b772b09ec
+
+Count = 72
+Nonce = 62f6f1872462d8
+Adata = 00
+CT = ec645769b22161567e6a7e23aa06575bc767a34aa54d3cba01472fe1
+Result = Fail
+
+Count = 73
+Nonce = a6d01fb88ca547
+Adata = 00
+CT = 615cbeabbe163ba8bc9c073df9ad40833fcf3f424644ccc37aa999d7
+Result = Pass
+Payload = a36155de477364236591e453008114075b4872120ef17264
+
+Count = 74
+Nonce = 46ad6ebbd8644a
+Adata = 00
+CT = 0ed6cc6451de57ca672d56dee45d4548a810d5c49dfe442dd27b7cf2
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = f7079dfa3b5c7b056347d7e437bcded683abd6e2c9e069d333284082cbb5d453
+
+Count = 75
+Nonce = a544218dadd3c1
+Adata = 00
+CT = bc51c3925a960e7732533e4ef3a4f69ee6826de952bcb0fd374f3bb6db8377ebfc79674858c4f305
+Result = Pass
+Payload = d3d5424e20fbec43ae495353ed830271515ab104f8860c98
+
+Count = 76
+Nonce = bfcda8b5a2d0d2
+Adata = 00
+CT = afa1fa8e8a70e26b02161150556d604101fdf423f332c3363275f2a4907d51b734fe7238cebbd48f
+Result = Fail
+
+Count = 77
+Nonce = 6bae7f35c56b27
+Adata = 00
+CT = 72bc8ef21a847047091b673ccf231d35ecf6f4049741703be672f1f22cbe4a5305f19aaa6967237b
+Result = Fail
+
+Count = 78
+Nonce = c5e4214b1bf209
+Adata = 00
+CT = b719f6555fc4e5424273f5903d5672af460413110278707f400b152113c3976be63dcd9e7a84ddac
+Result = Fail
+
+Count = 79
+Nonce = 9d773a31fe2ec7
+Adata = 00
+CT = 4539bb13382b034ddb16a3329148f9243a4eee998fe444aff2870ce198af11f4fb698a67af6c89ad
+Result = Pass
+Payload = 839d8cfa2c921c3cceb7d1f46bd2eaad706e53f64523d8c0
+
+Count = 80
+Nonce = f42cb0cce9efb6
+Adata = 00
+CT = 47cbb909cb12fa0a4b0f1aefd54c52d1edd1533290f76b8ccc98b3f5758972bf08ea9e88dc6e54ed
+Result = Fail
+
+Count = 81
+Nonce = 24b7a65391f88b
+Adata = 00
+CT = 6d0f928352a17d63aca1899cbd305e1f831f1638d27c1e24432704eff9b6830476db3d30d4c103e4
+Result = Pass
+Payload = 3bed52236182c19418867d468dbf47c8aac46c02445f99bb
+
+Count = 82
+Nonce = d2a7eb45780df3
+Adata = 00
+CT = e0e686d917f78b3b0058fed7b084976244789073a6305ff571256981db86f1e768170a104ebfb81d
+Result = Fail
+
+Count = 83
+Nonce = 046cbfd26093d8
+Adata = 00
+CT = 960c573f5d6934a4cac49d06998f827b3d665cf02c998fe55efbbae6a346863a93d52e0321cef8b2
+Result = Fail
+
+Count = 84
+Nonce = 51b13b0b04d077
+Adata = 00
+CT = 7cf8f4806848e34aa7d3bd7e2cb9f5d9ff21395ff6d34826ac2fdc3cc683f6120e405f446a10e0f3
+Result = Fail
+
+Count = 85
+Nonce = ce2e9967bf9eb7
+Adata = 00
+CT = e4f6445ca36e7ee3323f11f6a5ca8ded0c85871e092aa687d254f7765b6155054a5efde28dd38750
+Result = Fail
+
+Count = 86
+Nonce = b672c91376f533
+Adata = 00
+CT = f23ac1426cb1130c9a0913b347d8efafb6ed125913aa678a9dc42d22a5436bc12eff5505edb25e19
+Result = Pass
+Payload = 4f7a561e61b7861719e4445057ac9b74a9be953b772b09ec
+
+Count = 87
+Nonce = 62f6f1872462d8
+Adata = 00
+CT = ac9f131389181b1023f1ee47633aa433fc5d93a87d9ece962db05feb368ab772d977fd97b35262fa
+Result = Fail
+
+Count = 88
+Nonce = a6d01fb88ca547
+Adata = 00
+CT = 773b8eea2e9830297ac11d3c1f6ea4008c96040e83d76d55789d2043179fdd8fdcbd52313b7b15cb
+Result = Pass
+Payload = a36155de477364236591e453008114075b4872120ef17264
+
+Count = 89
+Nonce = 46ad6ebbd8644a
+Adata = 00
+CT = d3fae92043c419fe8ac0d7491ca8041ad089559d895103cf079a2bac0ab4bc249bbdb330181cdd16
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = f7079dfa3b5c7b056347d7e437bcded683abd6e2c9e069d333284082cbb5d453
+
+Count = 90
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = 63e00d30e4b08fd2a1cc8d70fab327b2368e77a93be4f4123d14fb3f
+Result = Pass
+Payload = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e
+
+Count = 91
+Nonce = 894dcaa61008eb8fb052c60d41
+Adata = 00
+CT = bb5425b3869b76856ec58e39886fb6f6f2ac13fe44cb132d8d0c0099
+Result = Fail
+
+Count = 92
+Nonce = 8feba0d720aa4a5e35abc99e82
+Adata = 00
+CT = 2ca3be419d5be5ed682f8954d2c20efd9e6d360814735daeefd4365c
+Result = Fail
+
+Count = 93
+Nonce = ed04c9ca8702aec8d0a58e09a0
+Adata = 00
+CT = 3d34bda62db39d6118d6fd5cd38f1a3820ca69ce584b94a2a4ccbef1
+Result = Fail
+
+Count = 94
+Nonce = 1501a243bf60b2cb40d5aa20ca
+Adata = 00
+CT = 377b2f1e7bd9e3d1077038e084f61950761361095f7eeebbf1a72afc
+Result = Pass
+Payload = f5730a05fec31a11662e2e14e362ccc75c7c30cdfccbf994
+
+Count = 95
+Nonce = c6edaf35f0cb433500a8c3a613
+Adata = 00
+CT = 9cef6c889ff51666df9dd1dd2215c15f4b2078a29373c106be4f5f9a
+Result = Fail
+
+Count = 96
+Nonce = d65e0e53f765f9d5e6795c0c5e
+Adata = 00
+CT = 6cab3060bf3b33b163b933c2ed0ba51406810b54d0edcf5c9d0ef4f7
+Result = Pass
+Payload = 20e394c7cc90bdfa6186fc1ba6fff158dfc690e24ba4c9fb
+
+Count = 97
+Nonce = 2b0163418a341588db0f5786d8
+Adata = 00
+CT = f9543a659e9a8b7d75dd859df923817452735f5051726422c08a9e85
+Result = Fail
+
+Count = 98
+Nonce = f16bba081bddda83546eabc9a5
+Adata = 00
+CT = 0d20bf6a9d02da72091d94cdb38743bfea2473d3ab62dcad75dd819a
+Result = Fail
+
+Count = 99
+Nonce = ace99268a32b9c1b5ccd8b0d84
+Adata = 00
+CT = 8bca01e6ebd7ebcdfe52b88e314670ffeb35882fc05394b386e205f9
+Result = Fail
+
+Count = 100
+Nonce = 24570517bbb0df1b3fbd32f57a
+Adata = 00
+CT = 7061c84e2e1d9d58013543ff82666055a1f055c1296c42c8f73a8bf0
+Result = Fail
+
+Count = 101
+Nonce = a6b2371acf8321864c08ddb4d8
+Adata = 00
+CT = c5aa500d1f7c09a590e9d15d6860c4433684e04dd6bc5c8f94f223f0
+Result = Pass
+Payload = 1a43ca628026219c5a430c54021a5a3152ae517167399635
+
+Count = 102
+Nonce = f8e2d4e043f5fe7a72b6117811
+Adata = 00
+CT = e3efa7971e27ba1245ee9491ebdbb28ad9b24b325da5760417af8b14
+Result = Fail
+
+Count = 103
+Nonce = c2b60f14c894ec6178fe79919f
+Adata = 00
+CT = 852cca903d7fdf899807bd14642057534c8a0ccacb8c7b8fb4d35d44
+Result = Pass
+Payload = 3e707d98f19972a63d913e6ea7533af2f41ff98aee2b2a36
+
+Count = 104
+Nonce = 4de4c909ac0cc5fc608baf45ac
+Adata = 00
+CT = e04fd4f5b60833021ed57c98de300bb68d0d892b2bf68e080bc044b1
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 1b0e8df63c57f05d9ac457575ea764524b8610ae5164e6215f426f5a7ae6ede4
+
+Count = 105
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = f0050ad16392021a3f40207bed3521fb1e9f808f49830c423a578d179902f912f9ea1afbce1120b3
+Result = Pass
+Payload = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e
+
+Count = 106
+Nonce = 894dcaa61008eb8fb052c60d41
+Adata = 00
+CT = c408190d0fbf5034f83b24a8ed9657331a7ce141de4fae769084607b83bd06e6442eac8dacf583cc
+Result = Fail
+
+Count = 107
+Nonce = 8feba0d720aa4a5e35abc99e82
+Adata = 00
+CT = 52b3d31d02d1b92b38cbae8c510204dde6bf9588e994296c9002a46cfb734290924a15e9c3d99924
+Result = Fail
+
+Count = 108
+Nonce = ed04c9ca8702aec8d0a58e09a0
+Adata = 00
+CT = f80190470212ce1e64bf4c64ca0133d90469abf87a8233c2b238e316c3f9adccce95e8c8b9c7e8d2
+Result = Fail
+
+Count = 109
+Nonce = 1501a243bf60b2cb40d5aa20ca
+Adata = 00
+CT = 254b847d4175bbb44a82b4e805514fa444c224710933f3ec8aaa3f0133234c0cd91609982adc034b
+Result = Pass
+Payload = f5730a05fec31a11662e2e14e362ccc75c7c30cdfccbf994
+
+Count = 110
+Nonce = c6edaf35f0cb433500a8c3a613
+Adata = 00
+CT = 7a5c7bc02aa69efc5a159d653f3993399f69e20752c3b00633255731cd88345860da913bc696fdc1
+Result = Fail
+
+Count = 111
+Nonce = d65e0e53f765f9d5e6795c0c5e
+Adata = 00
+CT = c3618c991b15de641d291419ff6957e8b9ae5046dd8c6f08fafb76adf12f36740347e3edae62bca4
+Result = Pass
+Payload = 20e394c7cc90bdfa6186fc1ba6fff158dfc690e24ba4c9fb
+
+Count = 112
+Nonce = 2b0163418a341588db0f5786d8
+Adata = 00
+CT = 240927bfd671a92aef0311395ad55ae42233ecee53873da4066f55f23d4e55bcbbbf2312ea2d8071
+Result = Fail
+
+Count = 113
+Nonce = f16bba081bddda83546eabc9a5
+Adata = 00
+CT = 4731a7e690c77cd47582ce54a1cec23d94c856b93a9fc767004753689cc84810b8414f1464c0c5b9
+Result = Fail
+
+Count = 114
+Nonce = ace99268a32b9c1b5ccd8b0d84
+Adata = 00
+CT = f0ea12eaff20c3a50674aa1546aaae3bd5c9249108535b21504da83478ede24026ec91fb12769e4b
+Result = Fail
+
+Count = 115
+Nonce = 24570517bbb0df1b3fbd32f57a
+Adata = 00
+CT = 5b164d9752ad6c497a7ab2d0bf8be68fea084ea5839b07b7c9fcf9b9fd5e99767a7b1679b57ea961
+Result = Fail
+
+Count = 116
+Nonce = a6b2371acf8321864c08ddb4d8
+Adata = 00
+CT = bd37326da18e5ac79a1a9512f724bb539530868576b79c67acb5a51d10a58d6584fbe73f1063c31b
+Result = Pass
+Payload = 1a43ca628026219c5a430c54021a5a3152ae517167399635
+
+Count = 117
+Nonce = f8e2d4e043f5fe7a72b6117811
+Adata = 00
+CT = 0455b4dd1069281e10531c0dc180ced9a5ef5d3fe0007470ce54cd7623a80a176f29a01b3abb642e
+Result = Fail
+
+Count = 118
+Nonce = c2b60f14c894ec6178fe79919f
+Adata = 00
+CT = ecd337640022635ce1ed273756d02b7feeb2515614c1fadc95c66d3f411b478853886afd177d88c3
+Result = Pass
+Payload = 3e707d98f19972a63d913e6ea7533af2f41ff98aee2b2a36
+
+Count = 119
+Nonce = 4de4c909ac0cc5fc608baf45ac
+Adata = 00
+CT = e25d7c9fb388596b13a13b885d5b24e31579a3494ad256da830b2b6317716b3975e2b101aebdd920
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 1b0e8df63c57f05d9ac457575ea764524b8610ae5164e6215f426f5a7ae6ede4
+
+Count = 120
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = 92d00fbe
+Result = Pass
+Payload = 00
+
+Count = 121
+Nonce = 78c46e3249ca28
+Adata = 232e957c65ffa11988e830d4617d500f1c4a35c1221f396c41ab214f074ca2dc
+CT = 9143e5c4
+Result = Fail
+
+Count = 122
+Nonce = c18d9e7971e2ae
+Adata = 0d40324aa758dbbb5391b5e6edb8a2310c94a4ae51d4fba8a7458d7cc8488baa
+CT = 54337466
+Result = Fail
+
+Count = 123
+Nonce = 162d061351d82d
+Adata = 106d1fb32d948b0d8884f178ad2332a599445fae0f6f71f9ebe53a60b2df9b8e
+CT = bf0bf84c
+Result = Fail
+
+Count = 124
+Nonce = 3fcb328bc96404
+Adata = 10b2ffed4f95af0f98ed4f77c677b5786ad01b31c095bbc6e1c99cf13977abba
+CT = 11250056
+Result = Pass
+Payload = 00
+
+Count = 125
+Nonce = b3fd1eb1422277
+Adata = fa5398cf4cddbe4b45e9f5d7491cd9eefc5e494255961ba3f4b40d22b5f5fe76
+CT = 13de5339
+Result = Fail
+
+Count = 126
+Nonce = c42ac63de6f12a
+Adata = 7ff8d06c5abcc50d3820de34b03089e6c5b202bcbaabca892825553d4d30020a
+CT = 4eed80fd
+Result = Pass
+Payload = 00
+
+Count = 127
+Nonce = d4a7a672237e17
+Adata = d1cdad7fe886d07625a4334be6de4df0645d2a8b4008a8d35f04e6bcf87bfa56
+CT = 4bc2e450
+Result = Fail
+
+Count = 128
+Nonce = b23255372455c6
+Adata = d2e2c3607c40e0a807b86c6ebbc502ab42bdb7f85ab26299cd963bbba3a3a8fa
+CT = b30e6bbd
+Result = Fail
+
+Count = 129
+Nonce = 92272d40475fbb
+Adata = 2f3af695ee33a9ebe6a48ed1b00e337261857110bb104191a54fd13bd960d8bc
+CT = f7c11fe2
+Result = Fail
+
+Count = 130
+Nonce = c4a756f6024a9d
+Adata = 2317b324b6420ada9ea7bf52b71c5faf2485528da5f56b42c517be6355cdb28b
+CT = 76673751
+Result = Fail
+
+Count = 131
+Nonce = 3a1701b185d33a
+Adata = e5d54df8ed9f89b98c5ebb1bc5d5279c2e182784ff4cd9c869ae152e29d7a2b2
+CT = 9a5382c3
+Result = Pass
+Payload = 00
+
+Count = 132
+Nonce = e4db2e80dc3f63
+Adata = 7616bdf5737d01f936072b6576fa76556dfa072f7e2d7de16b9dc96ac8de409c
+CT = 9e632f56
+Result = Fail
+
+Count = 133
+Nonce = 4f490ce07e0150
+Adata = 3e12d09632c644c540077c6f90726d4167423a679322b2000a3f19cfcea02b33
+CT = e1842c46
+Result = Pass
+Payload = 00
+
+Count = 134
+Nonce = b4aaf9ad1bde60
+Adata = 8c96c891456ddec29fe04299506723db2079a6667f96db5d198bf085acf2a4ef
+CT = 9f644671
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = a4bc10b1a62c96d459fbaf3a5aa3face7313bb9e1253e696f96a7a8e36801088
+
+Count = 135
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = 93af11a08379eb37a16aa2837f09d69d
+Result = Pass
+Payload = 00
+
+Count = 136
+Nonce = 78c46e3249ca28
+Adata = 232e957c65ffa11988e830d4617d500f1c4a35c1221f396c41ab214f074ca2dc
+CT = d19b0c14ec686a7961ca7c386d125a65
+Result = Fail
+
+Count = 137
+Nonce = c18d9e7971e2ae
+Adata = 0d40324aa758dbbb5391b5e6edb8a2310c94a4ae51d4fba8a7458d7cc8488baa
+CT = 02ea916d60e2ceec6d9dc9b1185569b3
+Result = Fail
+
+Count = 138
+Nonce = 162d061351d82d
+Adata = 106d1fb32d948b0d8884f178ad2332a599445fae0f6f71f9ebe53a60b2df9b8e
+CT = fabd2d0c422b47d363ea9936ff4a311b
+Result = Fail
+
+Count = 139
+Nonce = 3fcb328bc96404
+Adata = 10b2ffed4f95af0f98ed4f77c677b5786ad01b31c095bbc6e1c99cf13977abba
+CT = b3884b69d117146cfa5529901753ddc0
+Result = Pass
+Payload = 00
+
+Count = 140
+Nonce = b3fd1eb1422277
+Adata = fa5398cf4cddbe4b45e9f5d7491cd9eefc5e494255961ba3f4b40d22b5f5fe76
+CT = 7162026b6306e74fe32ece8433801bc2
+Result = Fail
+
+Count = 141
+Nonce = c42ac63de6f12a
+Adata = 7ff8d06c5abcc50d3820de34b03089e6c5b202bcbaabca892825553d4d30020a
+CT = b53d93cbfd3d5cf3720cef5080bc7224
+Result = Pass
+Payload = 00
+
+Count = 142
+Nonce = d4a7a672237e17
+Adata = d1cdad7fe886d07625a4334be6de4df0645d2a8b4008a8d35f04e6bcf87bfa56
+CT = c8bbecf69ecf8d10f0863bb4b7cbed51
+Result = Fail
+
+Count = 143
+Nonce = b23255372455c6
+Adata = d2e2c3607c40e0a807b86c6ebbc502ab42bdb7f85ab26299cd963bbba3a3a8fa
+CT = 6037145cc23a175760ae4b573907c80c
+Result = Fail
+
+Count = 144
+Nonce = 92272d40475fbb
+Adata = 2f3af695ee33a9ebe6a48ed1b00e337261857110bb104191a54fd13bd960d8bc
+CT = df7ea77425d631f652ffe096a8157f71
+Result = Fail
+
+Count = 145
+Nonce = c4a756f6024a9d
+Adata = 2317b324b6420ada9ea7bf52b71c5faf2485528da5f56b42c517be6355cdb28b
+CT = 7182b25ef5b113c13fa8f6769e74f1e2
+Result = Fail
+
+Count = 146
+Nonce = 3a1701b185d33a
+Adata = e5d54df8ed9f89b98c5ebb1bc5d5279c2e182784ff4cd9c869ae152e29d7a2b2
+CT = 0a5d1bc02c5fe096a8b9d94d1267c49a
+Result = Pass
+Payload = 00
+
+Count = 147
+Nonce = e4db2e80dc3f63
+Adata = 7616bdf5737d01f936072b6576fa76556dfa072f7e2d7de16b9dc96ac8de409c
+CT = 9eb6d9757ec7c56cc8c79461e0017486
+Result = Fail
+
+Count = 148
+Nonce = 4f490ce07e0150
+Adata = 3e12d09632c644c540077c6f90726d4167423a679322b2000a3f19cfcea02b33
+CT = 1eda43bf07f2bf003107f3a0ba3a4c18
+Result = Pass
+Payload = 00
+
+Count = 149
+Nonce = b4aaf9ad1bde60
+Adata = 8c96c891456ddec29fe04299506723db2079a6667f96db5d198bf085acf2a4ef
+CT = 5287cc160c5dd3a0f9c1986aac2a621c
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = a4bc10b1a62c96d459fbaf3a5aa3face7313bb9e1253e696f96a7a8e36801088
+
+Count = 150
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = 866d4227
+Result = Pass
+Payload = 00
+
+Count = 151
+Nonce = e8de970f6ee8e80ede933581b5
+Adata = 89f8b068d34f56bc49d839d8e47b347e6dae737b903b278632447e6c0485d26a
+CT = 94cb1127
+Result = Fail
+
+Count = 152
+Nonce = 6de75d3c05e83755083399a5f7
+Adata = 504b08cf34cbe17acf631ef219ae01437ebb6a980ab2f00121bb3073701b6511
+CT = 82c2b67a
+Result = Fail
+
+Count = 153
+Nonce = 58d43b9f1581c590daab1a5c56
+Adata = 749f149ef306c70a5d006d9777adbbf7c0de453898c2978ef7c281535ea9b24c
+CT = 8c8283f9
+Result = Fail
+
+Count = 154
+Nonce = dfdcbdff329f7af70731d8e276
+Adata = 2ae56ddde2876d70b3b34eda8c2b1d096c836d5225d53ec460b724b6e16aa5a3
+CT = c4ac0952
+Result = Pass
+Payload = 00
+
+Count = 155
+Nonce = 199ec321d1d24d5408076912d6
+Adata = a77526f3614cd974498a76d8b3cb7bacc623fdc9c85503289c462df888b199ed
+CT = c59aa931
+Result = Fail
+
+Count = 156
+Nonce = 60f2490ba0c658848859fcbea8
+Adata = 3ad743283064929bf4fe4e0807f710f5e6a273e22614c728c3280a27b6c614a0
+CT = 27c3953d
+Result = Pass
+Payload = 00
+
+Count = 157
+Nonce = 6f29ca274190400720bba27651
+Adata = c0850aaf141bd3f1b24f4d882590f58682b41f874748f29f8925b4914f444842
+CT = cb1ac8eb
+Result = Fail
+
+Count = 158
+Nonce = f1dfb6fdb31cb423226f181c09
+Adata = ac6b08900fc1c9463e7dfdb60eee444c4989d7b200e675f3220ba1e14eed0ab4
+CT = 4dcc55cc
+Result = Fail
+
+Count = 159
+Nonce = 0d45226c98eaa9bb445a3aa4f9
+Adata = b9cb3e1a5bcccb0b0599414c9822275b66fa0f913d51bdb0a2228cbb5aad0e0a
+CT = 727d8f5e
+Result = Fail
+
+Count = 160
+Nonce = 39cdbb24bd273a3fe96f42ca9d
+Adata = ddfe6c22f4cdc3128050072005f5bd4ecdef1d836e891683f1ba921d33fafba7
+CT = 5aa56a54
+Result = Fail
+
+Count = 161
+Nonce = db113f38f0504615c5c9347c3d
+Adata = 3b71bc84e48c6dadf6ead14621d22468a3d4c9c103ac96970269730bcfce239b
+CT = c38fbdff
+Result = Pass
+Payload = 00
+
+Count = 162
+Nonce = d16a20ef5f6587f1ee3cb7850b
+Adata = b1133e1cd369617a9f937e9a1eb86a0979ee30b5b7b0b6ff838d9e11301d6b72
+CT = 6be30c42
+Result = Fail
+
+Count = 163
+Nonce = d35f531f714694b5e49303a980
+Adata = 55b791ee495299916ff3c2327b4990952bebd0a2da9acfc553c6c996e354a4b5
+CT = d34e90bb
+Result = Pass
+Payload = 00
+
+Count = 164
+Nonce = 220624db34a022b758473994a2
+Adata = 5b3b2ae87b0d6759f38a858423227f8687f35478a8f565409b741eadcac4d8c4
+CT = 4a5d14bc
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = 8c5cf3457ff22228c39c051c4e05ed4093657eb303f859a9d4b0f8be0127d88a
+
+Count = 165
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = 867b0d87cf6e0f718200a97b4f6d5ad5
+Result = Pass
+Payload = 00
+
+Count = 166
+Nonce = e8de970f6ee8e80ede933581b5
+Adata = 89f8b068d34f56bc49d839d8e47b347e6dae737b903b278632447e6c0485d26a
+CT = 677a040d46ee3f2b7838273bdad14f16
+Result = Fail
+
+Count = 167
+Nonce = 6de75d3c05e83755083399a5f7
+Adata = 504b08cf34cbe17acf631ef219ae01437ebb6a980ab2f00121bb3073701b6511
+CT = f650d46ade2cbabbc68ead6df1ea0c37
+Result = Fail
+
+Count = 168
+Nonce = 58d43b9f1581c590daab1a5c56
+Adata = 749f149ef306c70a5d006d9777adbbf7c0de453898c2978ef7c281535ea9b24c
+CT = 11b8fe8c139ee38f77fd8fa552cbff67
+Result = Fail
+
+Count = 169
+Nonce = dfdcbdff329f7af70731d8e276
+Adata = 2ae56ddde2876d70b3b34eda8c2b1d096c836d5225d53ec460b724b6e16aa5a3
+CT = ad879c64425e6c1ec4841bbb0f99aa8b
+Result = Pass
+Payload = 00
+
+Count = 170
+Nonce = 199ec321d1d24d5408076912d6
+Adata = a77526f3614cd974498a76d8b3cb7bacc623fdc9c85503289c462df888b199ed
+CT = 3c64f8731930ae000162c10654531066
+Result = Fail
+
+Count = 171
+Nonce = 60f2490ba0c658848859fcbea8
+Adata = 3ad743283064929bf4fe4e0807f710f5e6a273e22614c728c3280a27b6c614a0
+CT = e2751f153fc76c0dec5e0cf2d30c1a28
+Result = Pass
+Payload = 00
+
+Count = 172
+Nonce = 6f29ca274190400720bba27651
+Adata = c0850aaf141bd3f1b24f4d882590f58682b41f874748f29f8925b4914f444842
+CT = 76127bf891141e73854752ed10c02bd0
+Result = Fail
+
+Count = 173
+Nonce = f1dfb6fdb31cb423226f181c09
+Adata = ac6b08900fc1c9463e7dfdb60eee444c4989d7b200e675f3220ba1e14eed0ab4
+CT = 4bd833f9da0496e5f6a08a05d02df385
+Result = Fail
+
+Count = 174
+Nonce = 0d45226c98eaa9bb445a3aa4f9
+Adata = b9cb3e1a5bcccb0b0599414c9822275b66fa0f913d51bdb0a2228cbb5aad0e0a
+CT = 05f166328a67a8c58b10a7348f3df612
+Result = Fail
+
+Count = 175
+Nonce = 39cdbb24bd273a3fe96f42ca9d
+Adata = ddfe6c22f4cdc3128050072005f5bd4ecdef1d836e891683f1ba921d33fafba7
+CT = 42499bcd949a5163855a9794f11f917e
+Result = Fail
+
+Count = 176
+Nonce = db113f38f0504615c5c9347c3d
+Adata = 3b71bc84e48c6dadf6ead14621d22468a3d4c9c103ac96970269730bcfce239b
+CT = fc85464a81fe372c12c9e4f0f3bf9c37
+Result = Pass
+Payload = 00
+
+Count = 177
+Nonce = d16a20ef5f6587f1ee3cb7850b
+Adata = b1133e1cd369617a9f937e9a1eb86a0979ee30b5b7b0b6ff838d9e11301d6b72
+CT = 8c7501f423647dee77668858c5e350bb
+Result = Fail
+
+Count = 178
+Nonce = d35f531f714694b5e49303a980
+Adata = 55b791ee495299916ff3c2327b4990952bebd0a2da9acfc553c6c996e354a4b5
+CT = b1c09b093788da19e33c5a6e82ed9627
+Result = Pass
+Payload = 00
+
+Count = 179
+Nonce = 220624db34a022b758473994a2
+Adata = 5b3b2ae87b0d6759f38a858423227f8687f35478a8f565409b741eadcac4d8c4
+CT = d2231ee1455b0bc337c4f8173fb8647c
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = 8c5cf3457ff22228c39c051c4e05ed4093657eb303f859a9d4b0f8be0127d88a
+
+Count = 180
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = c2fe12658139f5d0dd22cadf2e901695b579302a72fc56083ebc7720
+Result = Pass
+Payload = 78c46e3249ca28e1ef0531d80fd37c124d9aecb7be6668e3
+
+Count = 181
+Nonce = 6ba004fd176791
+Adata = 5a053b2a1bb87e85d56527bfcdcd3ecafb991bb10e4c862bb0751c700a29f54b
+CT = 94748ba81229e53c38583a8564b23ebbafc6f6efdf4c2a81c44db2c9
+Result = Fail
+
+Count = 182
+Nonce = 45c5c284836414
+Adata = 8f01a61eb17366d4e70942ab69b4f4bcf8ff6a97f5972ee5780a264c9dcf7d93
+CT = 1d670ccf3e9ba59186c48da2e5bd0ab21973eee2ea2985bf83a09067
+Result = Fail
+
+Count = 183
+Nonce = c69f7679c80546
+Adata = 5d6c04a5b422b46065a79a889e30ac8d1b53b65d230d4c88190903a24e1fe1ea
+CT = 2c8c80ff10fac1bf6c9c83533c1514ee032c0983730b0657392ae25d
+Result = Fail
+
+Count = 184
+Nonce = 57b940550a383b
+Adata = 33c2c3a57bf8393b126982c96d87daeacd5eadad1519073ad8c84cb9b760296f
+CT = e1b4ec4279bb62902c12521e6b874171695c5da46c647cc03b91ff03
+Result = Pass
+Payload = 6fb5ce32a851676753ba3523edc5ca82af1843ffc08f1ef0
+
+Count = 185
+Nonce = 11edd12ea5873d
+Adata = e32e5384038379e2b7382ba337b6f7a72a1569e110ee89c4dd6aa6f7e69f5250
+CT = b5dda89fe879d6a665b99285b6d937fd5877ebef4de049fb64b837fb
+Result = Fail
+
+Count = 186
+Nonce = f32222e9eec4bd
+Adata = 684595e36eda1db5f586941c9f34c9f8d477970d5ccc14632d1f0cec8190ae68
+CT = 224db21beb8cd0069007660e783c3f85706b014128368aab2a4e56a7
+Result = Pass
+Payload = 2c29d4e2bb9294e90cb04ec697e663a1f7385a39f90c8ccf
+
+Count = 187
+Nonce = e0a0a7f262cb51
+Adata = 1d93b2856ad2bf3700440f9a281bd8947ba209e9ffd18e69921ed0678c957c6c
+CT = ba1ce3a799e1173178b6788723005566f9269d5828c85d28e960a769
+Result = Fail
+
+Count = 188
+Nonce = 40316e7b38bdad
+Adata = 6e49acd9c26944740c778e74b1dbaa8d640c7e18e949a1661f8a77543db69e1f
+CT = 79d59e4bb251988c019c4eaaee2a2513f9cb0521334018fded14a5a5
+Result = Fail
+
+Count = 189
+Nonce = 33008ef5baf263
+Adata = a726f31d9a22bfc0e7e4c3111b0d304e106ab04ed318f8bfe6ec9cb3a811285b
+CT = af4350795f24087aa05070d6d5f55ebb12d7ad3141066866d7d6c61d
+Result = Fail
+
+Count = 190
+Nonce = b48a16fb9a065d
+Adata = be05e9c934c1dcba45223d47c6646a2d13c3b93265e354ae4970484b5101d809
+CT = 22d2da531be1f0d1da4bc21f984d29bf56bed2e92da6bf42d0605b84
+Result = Fail
+
+Count = 191
+Nonce = 14c9bd561c47c1
+Adata = 141ae365f8e65ab9196c4e8cd4e62189b304d67de38f2117e84ec0ec8f260ebd
+CT = 61b46c9024eed3989064a52df90349c18e14e4b552779d3f8f9d6814
+Result = Pass
+Payload = c22524a1ea444be3412b0d773d4ea2ff0af4c1ad2383cba8
+
+Count = 192
+Nonce = 5fb871eac2e52a
+Adata = ff23906e9067da8999842318f2a867759ca2d171395c2ff31fa5a4e2ab349c45
+CT = 539799c2b22a33dd648fc4497d12f9455beaf932f1eaaff4d930f5ce
+Result = Fail
+
+Count = 193
+Nonce = 1ccec9923aa6e8
+Adata = 88a6d037009a1c1756f72bb4589d6d940bd514ed55386baefacc6ac3ca6f8795
+CT = 52f8205534447d722be2b9377f7395938cc88af081a11ccb0d83fa19
+Result = Pass
+Payload = 518a7fb11c463bf23798982118f3cfe4d7ddde9184f37d4f
+
+Count = 194
+Nonce = 68a5351e4422c8
+Adata = 303c767468f48ac9f6e331bbad535b06aa00ab593327320799e17eff63afd3fe
+CT = d11c892ae155098f5e4b5fe60c7afd74fb2dbcc4db956556f243e273
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = 705334e30f53dd2f92d190d2c1437c8772f940c55aa35e562214ed45bd458ffe
+
+Count = 195
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = 3341168eb8c48468c414347fb08f71d2086f7c2d1bd581ce1ac68bd42f5ec7fa7e068cc0ecd79c2a
+Result = Pass
+Payload = 78c46e3249ca28e1ef0531d80fd37c124d9aecb7be6668e3
+
+Count = 196
+Nonce = 6ba004fd176791
+Adata = 5a053b2a1bb87e85d56527bfcdcd3ecafb991bb10e4c862bb0751c700a29f54b
+CT = d543acda712b898cbb27b8f598b2e4438ce587a836e2785147c3338a2400809e739b63ba8227d2f9
+Result = Fail
+
+Count = 197
+Nonce = 45c5c284836414
+Adata = 8f01a61eb17366d4e70942ab69b4f4bcf8ff6a97f5972ee5780a264c9dcf7d93
+CT = 39a8af5c976b995ea8049e55b68bc65503592ab00915638646288ce9dd1c7088c752e35947fdca98
+Result = Fail
+
+Count = 198
+Nonce = c69f7679c80546
+Adata = 5d6c04a5b422b46065a79a889e30ac8d1b53b65d230d4c88190903a24e1fe1ea
+CT = 950fbf6445f6ffb68178f52f5079d0c6081a48ae1f267a0b7fd89caef9388fbb82361b8d53d9edc6
+Result = Fail
+
+Count = 199
+Nonce = 57b940550a383b
+Adata = 33c2c3a57bf8393b126982c96d87daeacd5eadad1519073ad8c84cb9b760296f
+CT = fbfed2c94f50ca10466da9903ef85833ad48ca00556e66d14d8b30df941f3536ffb42083ef0e1c30
+Result = Pass
+Payload = 6fb5ce32a851676753ba3523edc5ca82af1843ffc08f1ef0
+
+Count = 200
+Nonce = 11edd12ea5873d
+Adata = e32e5384038379e2b7382ba337b6f7a72a1569e110ee89c4dd6aa6f7e69f5250
+CT = 2ebfeb7a843618b37025352df3538526517ed320adfb486c04cf3426e8f975125a7eed00e5f33b6c
+Result = Fail
+
+Count = 201
+Nonce = f32222e9eec4bd
+Adata = 684595e36eda1db5f586941c9f34c9f8d477970d5ccc14632d1f0cec8190ae68
+CT = dae13e6967c8b1ee0dd2d5ba1dd1de69f22c95da39528f9ef78e9e5e9faa058112af57f4ac78db2c
+Result = Pass
+Payload = 2c29d4e2bb9294e90cb04ec697e663a1f7385a39f90c8ccf
+
+Count = 202
+Nonce = e0a0a7f262cb51
+Adata = 1d93b2856ad2bf3700440f9a281bd8947ba209e9ffd18e69921ed0678c957c6c
+CT = e683040a0bcf04c1748e7746400d6ef0f7cd8e77a29517790c63959ce534a0f87fb42a9b000dec84
+Result = Fail
+
+Count = 203
+Nonce = 40316e7b38bdad
+Adata = 6e49acd9c26944740c778e74b1dbaa8d640c7e18e949a1661f8a77543db69e1f
+CT = 829e50e8c09e727a58287e6eb7d38edeb8ab39db279c06397d1a2111dc21aec79ef73193b306d31f
+Result = Fail
+
+Count = 204
+Nonce = 33008ef5baf263
+Adata = a726f31d9a22bfc0e7e4c3111b0d304e106ab04ed318f8bfe6ec9cb3a811285b
+CT = 873c91e76dca0062ae66325aefb84ece3e98928f8dbc5fee7c516d2d1a8318893923f398ca249401
+Result = Fail
+
+Count = 205
+Nonce = b48a16fb9a065d
+Adata = be05e9c934c1dcba45223d47c6646a2d13c3b93265e354ae4970484b5101d809
+CT = 343f6c86f2b852ac388a096faec4472107a924aba56d0cb88055e777bb57eb49497cd2e233ee06fd
+Result = Fail
+
+Count = 206
+Nonce = 14c9bd561c47c1
+Adata = 141ae365f8e65ab9196c4e8cd4e62189b304d67de38f2117e84ec0ec8f260ebd
+CT = a654238fb8b05e293dba07f9d68d75a7f0fbf40fe20edaeba1586bf922412e73ce338e372615c3bc
+Result = Pass
+Payload = c22524a1ea444be3412b0d773d4ea2ff0af4c1ad2383cba8
+
+Count = 207
+Nonce = 5fb871eac2e52a
+Adata = ff23906e9067da8999842318f2a867759ca2d171395c2ff31fa5a4e2ab349c45
+CT = 4846816923ed9f0254bdd0be01028f75061d3594ad3a45bd03538d108df6ecd6f39acfe076ba5fb8
+Result = Fail
+
+Count = 208
+Nonce = 1ccec9923aa6e8
+Adata = 88a6d037009a1c1756f72bb4589d6d940bd514ed55386baefacc6ac3ca6f8795
+CT = 765067ef768908d91ee4c3923943e0c7be70e2e06db99a4b3e3f51ee37fdcc5d81dd85d9e9d4f44e
+Result = Pass
+Payload = 518a7fb11c463bf23798982118f3cfe4d7ddde9184f37d4f
+
+Count = 209
+Nonce = 68a5351e4422c8
+Adata = 303c767468f48ac9f6e331bbad535b06aa00ab593327320799e17eff63afd3fe
+CT = e58ea6c1522e5a3e93a85edd05ae80d6cf5c4dd6d604a8f8d8a906488f79ad5d2234d72458dcfcd4
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = 705334e30f53dd2f92d190d2c1437c8772f940c55aa35e562214ed45bd458ffe
+
+Count = 210
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = c0ea400b599561e7905b99262b4565d5c3dc49fad84d7c69ef891339
+Result = Pass
+Payload = e8de970f6ee8e80ede933581b5bcf4d837e2b72baa8b00c3
+
+Count = 211
+Nonce = 8fa501c5dd9ac9b868144c9fa5
+Adata = 5bb40e3bb72b4509324a7edc852f72535f1f6283156e63f6959ffaf39dcde800
+CT = 60871e03ea0eb968536c99f926ea24ef43d41272ad9fb7f63d488623
+Result = Fail
+
+Count = 212
+Nonce = 9bc0d1502a47e46350fe8667ca
+Adata = 07203674260208d5bd4d39506836f7e76ffc58e938799f21aff7bb4dea4410d2
+CT = 81d7859dcbe51dcc94fe2591cd3b0540003d49a8c4dccbf4527e5ed0
+Result = Fail
+
+Count = 213
+Nonce = 611cb4c66e88f6acf96fea1919
+Adata = 327ee3657e49d4d988362fabae303ccea6638e5cb45993d9d56269bc3d3af32b
+CT = bef380ad725b65fb5fceeabf09c665bc35089f434ec831494d20d5fa
+Result = Fail
+
+Count = 214
+Nonce = 0dd613c0fe28e913c0edbb8404
+Adata = 2ad306575b577c2f61da7212ab63e3db3941f1f751f2356c7443531a90b9d141
+CT = fabe11c9629e598228f5209f3dbcc641fe4b1a22cadb0821d2898c3b
+Result = Pass
+Payload = 9522fb1f1aa58493cba682d788186d902cfc93e80fd6b998
+
+Count = 215
+Nonce = 68806dfe720d0a9a84697de5f2
+Adata = c6b0e4dfd723d7637510f887b7852f60ecdf72e0d33396560fed6534d5b7f015
+CT = b7eb87f84951640de731d4093f1a4ed5f831138a27465d3941e92090
+Result = Fail
+
+Count = 216
+Nonce = 3e0fe3427eeda80f02dda4fed5
+Adata = ae0d1c9c834d60ff0ecfb3c0d78c72ddb789e58adfc166c81d5fc6395b31ec33
+CT = d88f8fcd772125212ce09c2a6e5b5693dd35073f992004f0d18fc889
+Result = Pass
+Payload = 38333ce78110bf53a2c2abc7db99e133ad218ca43ff7a7bc
+
+Count = 217
+Nonce = 7c0c76d9f9316ff6c98758b464
+Adata = 31a0338c3839931fa1dd5131cb796c4c6cfde9fb336d8a80ac35dec463be7a94
+CT = d2d7d52b11304fc1d15b8c20e296ba7c63d99f4ce86cc8ae0f39ecea
+Result = Fail
+
+Count = 218
+Nonce = 07c728135bdfede0e0c8036b17
+Adata = 25a152850b4b80b19d8f0b504b2a8a241824b3a1fca8d85c8713b2c0c84b5e02
+CT = ae1d9f82efb464d5dc2018cffa309634c09b34d1122c4bd994b1d516
+Result = Fail
+
+Count = 219
+Nonce = 710c96d7a6f09de83f0507f28a
+Adata = 2d64acfdbfc582cd9a933790eb1b739fb02e53f511255e49f421bb7acc98a130
+CT = 477c985d92ad1b69d22315235a29e3d3a5991487cbdc8d11d394d047
+Result = Fail
+
+Count = 220
+Nonce = 977bbcdeb6a7d9dcf8664bc2d8
+Adata = 135786125258a49475338ac1961d2718433b9e84cf64f63ca52913e8dd12e505
+CT = d1c085c75d808dc6db493b8a0b4d884e0700d2844a1b4b46bd3d22eb
+Result = Fail
+
+Count = 221
+Nonce = 60122cbd219e5cf17415e8bc09
+Adata = 895a45ddbe0c80793eccbf820de13a233b6aa7045cfd5313388e7184c392b216
+CT = 76bdd9a7b34bf14ae121a87fdfa144f71b848744af6a2f0b1c0d067c
+Result = Pass
+Payload = 794e734966e6d0001699aec3f8ab8f194de7653d3091b1b9
+
+Count = 222
+Nonce = 83a07f2e685959cb50a1bd2bce
+Adata = 02afe300ec0cf0acb59108b2f70e069300294e34f40bb032cb59907599664408
+CT = 413e2e8df9d65b4e5d3b63a738258aaee643f364be9a01b974192744
+Result = Fail
+
+Count = 223
+Nonce = 3542fbe0f59a6d5f3abf619b7d
+Adata = dd4531f158a2fa3bc8a339f770595048f4a42bc1b03f2e824efc6ba4985119d8
+CT = 617d8036e2039d516709062379e0550cbd71ebb90fea967c79018ad5
+Result = Pass
+Payload = c5b3d71312ea14f2f8fae5bd1a453192b6604a45db75c5ed
+
+Count = 224
+Nonce = 48f2d4c0b17072e0a9c300d90b
+Adata = c56175e2cfe0d37454d989afcc36686fb34c015439601567506a4d0003182be7
+CT = 40e609c739e409750a6c41d9c6ea64ce36f70711b4ca3e365c916f91
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 314a202f836f9f257e22d8c11757832ae5131d357a72df88f3eff0ffcee0da4e
+
+Count = 225
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = 8d34cdca37ce77be68f65baf3382e31efa693e63f914a781367f30f2eaad8c063ca50795acd90203
+Result = Pass
+Payload = e8de970f6ee8e80ede933581b5bcf4d837e2b72baa8b00c3
+
+Count = 226
+Nonce = 8fa501c5dd9ac9b868144c9fa5
+Adata = 5bb40e3bb72b4509324a7edc852f72535f1f6283156e63f6959ffaf39dcde800
+CT = 516c0095cc3d85fd55e48da17c592e0c7014b9daafb82bdc4b41096dfdbe9cc1ab610f8f3e038d16
+Result = Fail
+
+Count = 227
+Nonce = 9bc0d1502a47e46350fe8667ca
+Adata = 07203674260208d5bd4d39506836f7e76ffc58e938799f21aff7bb4dea4410d2
+CT = 0293eae9f8d8bd7ad45357f733fc7b5d990d894783e18501d81ec96df41b8fa8262ed2db880b5e85
+Result = Fail
+
+Count = 228
+Nonce = 611cb4c66e88f6acf96fea1919
+Adata = 327ee3657e49d4d988362fabae303ccea6638e5cb45993d9d56269bc3d3af32b
+CT = 256bad8295e67d8d450f5ecc8276920ec23b1156c57be7c96ee80f60f72db2cbf25b2f8c6af8749c
+Result = Fail
+
+Count = 229
+Nonce = 0dd613c0fe28e913c0edbb8404
+Adata = 2ad306575b577c2f61da7212ab63e3db3941f1f751f2356c7443531a90b9d141
+CT = 6df09613ea986c2d91a57a45a0942cbf20e0dfca12fbda8c945ee6db24aea5f5098952f1203339ce
+Result = Pass
+Payload = 9522fb1f1aa58493cba682d788186d902cfc93e80fd6b998
+
+Count = 230
+Nonce = 68806dfe720d0a9a84697de5f2
+Adata = c6b0e4dfd723d7637510f887b7852f60ecdf72e0d33396560fed6534d5b7f015
+CT = c5b64577d3c34e50f7da5072db5bda1d1d2c6db1a4f1183e2cc4c90ac3f798957cb09a05868a8ad5
+Result = Fail
+
+Count = 231
+Nonce = 3e0fe3427eeda80f02dda4fed5
+Adata = ae0d1c9c834d60ff0ecfb3c0d78c72ddb789e58adfc166c81d5fc6395b31ec33
+CT = 2bfe51f1f43b982d47f76ea8206ddbf585d6f30cec0d4ef16b1556631d3b52bf24154afec1448ef6
+Result = Pass
+Payload = 38333ce78110bf53a2c2abc7db99e133ad218ca43ff7a7bc
+
+Count = 232
+Nonce = 7c0c76d9f9316ff6c98758b464
+Adata = 31a0338c3839931fa1dd5131cb796c4c6cfde9fb336d8a80ac35dec463be7a94
+CT = 1622ae109073f44a4596722d9943fea774dfc2a1f939fc0914f42ec81e3af71c9a5de7e0ac16ca69
+Result = Fail
+
+Count = 233
+Nonce = 07c728135bdfede0e0c8036b17
+Adata = 25a152850b4b80b19d8f0b504b2a8a241824b3a1fca8d85c8713b2c0c84b5e02
+CT = 4c0b361a766d366d983c41e793d75635e17f6eab2eadcf9743d67d90850c4c76a43df1f95170b29b
+Result = Fail
+
+Count = 234
+Nonce = 710c96d7a6f09de83f0507f28a
+Adata = 2d64acfdbfc582cd9a933790eb1b739fb02e53f511255e49f421bb7acc98a130
+CT = 5b02347f30213df7f1506d7dca41b838c92aea0f190c5dba7bd5d5c8c098299394333b34fae9a110
+Result = Fail
+
+Count = 235
+Nonce = 977bbcdeb6a7d9dcf8664bc2d8
+Adata = 135786125258a49475338ac1961d2718433b9e84cf64f63ca52913e8dd12e505
+CT = c77283ca15484d82469ce7249d1fb8e5f4c3bc8245fb4d97e26149d4a9711be81b4f69aa9fabd7f6
+Result = Fail
+
+Count = 236
+Nonce = 60122cbd219e5cf17415e8bc09
+Adata = 895a45ddbe0c80793eccbf820de13a233b6aa7045cfd5313388e7184c392b216
+CT = bf0d219bb50fcc1d51f654bb0fd8b44efa25aef39e2f11afe47d00f2eebb544e6ba7559ac2f34edb
+Result = Pass
+Payload = 794e734966e6d0001699aec3f8ab8f194de7653d3091b1b9
+
+Count = 237
+Nonce = 83a07f2e685959cb50a1bd2bce
+Adata = 02afe300ec0cf0acb59108b2f70e069300294e34f40bb032cb59907599664408
+CT = 1609f8de59da4f50ce034977d132d4f9881a9b85ffa5bb886fa3fddc87690a359fe55f8fa12ba749
+Result = Fail
+
+Count = 238
+Nonce = 3542fbe0f59a6d5f3abf619b7d
+Adata = dd4531f158a2fa3bc8a339f770595048f4a42bc1b03f2e824efc6ba4985119d8
+CT = 39c2e8f6edfe663b90963b98eb79e2d4f7f28a5053ae8881567a6b4426f1667136bed4a5e32a2bc1
+Result = Pass
+Payload = c5b3d71312ea14f2f8fae5bd1a453192b6604a45db75c5ed
+
+Count = 239
+Nonce = 48f2d4c0b17072e0a9c300d90b
+Adata = c56175e2cfe0d37454d989afcc36686fb34c015439601567506a4d0003182be7
+CT = 27c575be0b99af9b106f53f471c31cac4d54ea0bcb602a33fb67bb6092cd579f722ae9b680da083d
+Result = Fail
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.txt b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.txt
new file mode 100644
index 0000000000..6d9a3eadcb
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.txt
@@ -0,0 +1,1589 @@
+# CAVS 11.0
+# "CCM-DVPT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:26 2011
+
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = eda32f751456e33195f1f499cf2dc7c97ea127b6d488f211ccc5126fbb24afa6
+
+Count = 0
+Nonce = a544218dadd3c1
+Adata = 00
+CT = 469c90bb
+Result = Pass (0)
+Payload = 00
+
+Count = 1
+Nonce = d3d5424e20fbec
+Adata = 00
+CT = 46a908ed
+Result = Fail (2 - CT changed)
+
+Count = 2
+Nonce = e776620a3bd961
+Adata = 00
+CT = fdd35c4d
+Result = Fail (1 - Adata changed)
+
+Count = 3
+Nonce = 6c7a3be9f9ad55
+Adata = 00
+CT = 869ce60e
+Result = Fail (1 - Adata changed)
+
+Count = 4
+Nonce = dbb3923156cfd6
+Adata = 00
+CT = 1302d515
+Result = Pass (0)
+Payload = 00
+
+Count = 5
+Nonce = b390f67eaef8f5
+Adata = 00
+CT = 156416ee
+Result = Fail (2 - CT changed)
+
+Count = 6
+Nonce = a259c114eaac89
+Adata = 00
+CT = 4fe06e92
+Result = Pass (0)
+Payload = 00
+
+Count = 7
+Nonce = 7fc8804fef18ef
+Adata = 00
+CT = 611091aa
+Result = Fail (2 - CT changed)
+
+Count = 8
+Nonce = fbaf4cbc49fa0f
+Adata = 00
+CT = 696e9371
+Result = Fail (2 - CT changed)
+
+Count = 9
+Nonce = 2ed0c8761dbf04
+Adata = 00
+CT = a0e0a2cb
+Result = Fail (2 - CT changed)
+
+Count = 10
+Nonce = 346bb04ea0db86
+Adata = 00
+CT = 43cc0375
+Result = Fail (1 - Adata changed)
+
+Count = 11
+Nonce = e1be89af98ffd7
+Adata = 00
+CT = e5417f6b
+Result = Pass (0)
+Payload = 00
+
+Count = 12
+Nonce = a6a0d57aaaf012
+Adata = 00
+CT = fff8a068
+Result = Fail (1 - Adata changed)
+
+Count = 13
+Nonce = 1aa758eb2f9a28
+Adata = 00
+CT = f8fa8e71
+Result = Pass (0)
+Payload = 00
+
+Count = 14
+Nonce = 2911167fc98fc3
+Adata = 00
+CT = 0bfa2d9d
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = e1b8a927a95efe94656677b692662000278b441c79e879dd5c0ddc758bdc9ee8
+
+Count = 15
+Nonce = a544218dadd3c1
+Adata = 00
+CT = 8207eb14d33855a52acceed17dbcbf6e
+Result = Pass (0)
+Payload = 00
+
+Count = 16
+Nonce = d3d5424e20fbec
+Adata = 00
+CT = 60f8e127cb4d30db6df0622158cd931d
+Result = Fail (2 - CT changed)
+
+Count = 17
+Nonce = e776620a3bd961
+Adata = 00
+CT = 4239f29871651e9a26b8b06ffc5b3748
+Result = Fail (1 - Adata changed)
+
+Count = 18
+Nonce = 6c7a3be9f9ad55
+Adata = 00
+CT = 5d35364c621fe8959dfe70ab44700fbe
+Result = Fail (1 - Adata changed)
+
+Count = 19
+Nonce = dbb3923156cfd6
+Adata = 00
+CT = e4dc5e03aacea691262ee69cee8ffbbe
+Result = Pass (0)
+Payload = 00
+
+Count = 20
+Nonce = b390f67eaef8f5
+Adata = 00
+CT = c8eb7643b4ed3c796c3873e8c6624e0d
+Result = Fail (2 - CT changed)
+
+Count = 21
+Nonce = a259c114eaac89
+Adata = 00
+CT = f79c53fd5e69835b7e70496ea999718b
+Result = Pass (0)
+Payload = 00
+
+Count = 22
+Nonce = 7fc8804fef18ef
+Adata = 00
+CT = 687e00723a419fa81c0923b8b8e245ae
+Result = Fail (2 - CT changed)
+
+Count = 23
+Nonce = fbaf4cbc49fa0f
+Adata = 00
+CT = 499ab350309ad6091ec4aaf6bf0cbd00
+Result = Fail (2 - CT changed)
+
+Count = 24
+Nonce = 2ed0c8761dbf04
+Adata = 00
+CT = c27b9f14787dc5375f59d0c561a23446
+Result = Fail (2 - CT changed)
+
+Count = 25
+Nonce = 346bb04ea0db86
+Adata = 00
+CT = 655c737722c78ac96582a883d407b2bb
+Result = Fail (1 - Adata changed)
+
+Count = 26
+Nonce = e1be89af98ffd7
+Adata = 00
+CT = 10d3f6fe08280d45e67e58fe41a7f036
+Result = Pass (0)
+Payload = 00
+
+Count = 27
+Nonce = a6a0d57aaaf012
+Adata = 00
+CT = b4e425e43edb92c606f7cb2de8a06932
+Result = Fail (1 - Adata changed)
+
+Count = 28
+Nonce = 1aa758eb2f9a28
+Adata = 00
+CT = 2590df2453cb94c304ba0a2bff3f3c71
+Result = Pass (0)
+Payload = 00
+
+Count = 29
+Nonce = 2911167fc98fc3
+Adata = 00
+CT = 1f344e30dfa95b2319e274caa5780e60
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = e1b8a927a95efe94656677b692662000278b441c79e879dd5c0ddc758bdc9ee8
+
+Count = 30
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = 8a19a133
+Result = Pass (0)
+Payload = 00
+
+Count = 31
+Nonce = 3c0e2815d37d844f7ac240ba9d
+Adata = 00
+CT = 2e317f1b
+Result = Fail (2 - CT changed)
+
+Count = 32
+Nonce = 75549e7e5657e5fe19872fcee0
+Adata = 00
+CT = 979bdcfe
+Result = Fail (1 - Adata changed)
+
+Count = 33
+Nonce = d071ff72735820d73485870e83
+Adata = 00
+CT = 8ef89acf
+Result = Fail (1 - Adata changed)
+
+Count = 34
+Nonce = 79ac204a26b9fee1132370c20f
+Adata = 00
+CT = 154024b2
+Result = Pass (0)
+Payload = 00
+
+Count = 35
+Nonce = a64bbc3d6d377dab513f7d9ce8
+Adata = 00
+CT = 8dbcc439
+Result = Fail (2 - CT changed)
+
+Count = 36
+Nonce = 0545fd9ecbc73ccdbbbd4244fd
+Adata = 00
+CT = 5c349fb2
+Result = Pass (0)
+Payload = 00
+
+Count = 37
+Nonce = 182fb47a12becf0bfe65df1287
+Adata = 00
+CT = 79df3e02
+Result = Fail (2 - CT changed)
+
+Count = 38
+Nonce = f342059a6f9dc14226b40debc4
+Adata = 00
+CT = fbc2c500
+Result = Fail (2 - CT changed)
+
+Count = 39
+Nonce = 6cbfe6bb4c9b171b93d28e9f8f
+Adata = 00
+CT = 2fac1bca
+Result = Fail (2 - CT changed)
+
+Count = 40
+Nonce = 82877df921c6ade43064ad963e
+Adata = 00
+CT = 99948f6e
+Result = Fail (1 - Adata changed)
+
+Count = 41
+Nonce = 0a37f2e7c66490e97285f1b09e
+Adata = 00
+CT = c59bf14c
+Result = Pass (0)
+Payload = 00
+
+Count = 42
+Nonce = d7b9c346ce2f8bad9623122e10
+Adata = 00
+CT = b764c393
+Result = Fail (1 - Adata changed)
+
+Count = 43
+Nonce = c1ad812bf2bbb2cdaee4636ee7
+Adata = 00
+CT = 5b96f41d
+Result = Pass (0)
+Payload = 00
+
+Count = 44
+Nonce = b6ce7d00731184b24428df046b
+Adata = 00
+CT = f7e12df1
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = af063639e66c284083c5cf72b70d8bc277f5978e80d9322d99f2fdc718cda569
+
+Count = 45
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = 97e1a8dd4259ccd2e431e057b0397fcf
+Result = Pass (0)
+Payload = 00
+
+Count = 46
+Nonce = 3c0e2815d37d844f7ac240ba9d
+Adata = 00
+CT = 5a9596c511ea6a8671adefc4f2157d8b
+Result = Fail (2 - CT changed)
+
+Count = 47
+Nonce = 75549e7e5657e5fe19872fcee0
+Adata = 00
+CT = 66f5c53efbc74fa02dedc303fd95133a
+Result = Fail (1 - Adata changed)
+
+Count = 48
+Nonce = d071ff72735820d73485870e83
+Adata = 00
+CT = 2dfd3c852f68eace45acf433a6aa9c05
+Result = Fail (1 - Adata changed)
+
+Count = 49
+Nonce = 79ac204a26b9fee1132370c20f
+Adata = 00
+CT = 5c8c9a5b97be8c7bc01ca8d693b809f9
+Result = Pass (0)
+Payload = 00
+
+Count = 50
+Nonce = a64bbc3d6d377dab513f7d9ce8
+Adata = 00
+CT = ec093121bdcd589285f2262be8db5c4e
+Result = Fail (2 - CT changed)
+
+Count = 51
+Nonce = 0545fd9ecbc73ccdbbbd4244fd
+Adata = 00
+CT = 84201662b213c7a1ff0c1b3c25e4ec45
+Result = Pass (0)
+Payload = 00
+
+Count = 52
+Nonce = 182fb47a12becf0bfe65df1287
+Adata = 00
+CT = bbe746d6d31e8e9745faed4095ab8d5d
+Result = Fail (2 - CT changed)
+
+Count = 53
+Nonce = f342059a6f9dc14226b40debc4
+Adata = 00
+CT = 646c1258dc4aa6fc380818e70e5f4328
+Result = Fail (2 - CT changed)
+
+Count = 54
+Nonce = 6cbfe6bb4c9b171b93d28e9f8f
+Adata = 00
+CT = 15fa37ca7f2883a4642c1ed41b8f6293
+Result = Fail (2 - CT changed)
+
+Count = 55
+Nonce = 82877df921c6ade43064ad963e
+Adata = 00
+CT = c6acf5e5ded4efb2c314370ebb9e9cde
+Result = Fail (1 - Adata changed)
+
+Count = 56
+Nonce = 0a37f2e7c66490e97285f1b09e
+Adata = 00
+CT = 586e728193ce6db9a926b03b2d77dd6e
+Result = Pass (0)
+Payload = 00
+
+Count = 57
+Nonce = d7b9c346ce2f8bad9623122e10
+Adata = 00
+CT = 642a187e71feff5989e28184aded0199
+Result = Fail (1 - Adata changed)
+
+Count = 58
+Nonce = c1ad812bf2bbb2cdaee4636ee7
+Adata = 00
+CT = 64864d21b6ee3fca13f07fc0486e232d
+Result = Pass (0)
+Payload = 00
+
+Count = 59
+Nonce = b6ce7d00731184b24428df046b
+Adata = 00
+CT = 58c63ce68f132d30d177c5834344cc5d
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = af063639e66c284083c5cf72b70d8bc277f5978e80d9322d99f2fdc718cda569
+
+Count = 60
+Nonce = a544218dadd3c1
+Adata = 00
+CT = 64a1341679972dc5869fcf69b19d5c5ea50aa0b5e985f5b722aa8d59
+Result = Pass (0)
+Payload = d3d5424e20fbec43ae495353ed830271515ab104f8860c98
+
+Count = 61
+Nonce = bfcda8b5a2d0d2
+Adata = 00
+CT = c5b7f802bffc498c1626e3774f1d9f94045dfd8e1a10a20277d00a75
+Result = Fail (2 - CT changed)
+
+Count = 62
+Nonce = 6bae7f35c56b27
+Adata = 00
+CT = bf432e246b7fa4aff8b3ada738432b51f6872ed92284db9d28588021
+Result = Fail (1 - Adata changed)
+
+Count = 63
+Nonce = c5e4214b1bf209
+Adata = 00
+CT = 0d5760ad0e156e401120a1ebd1b139248784c88e10e3425437921120
+Result = Fail (1 - Adata changed)
+
+Count = 64
+Nonce = 9d773a31fe2ec7
+Adata = 00
+CT = 5acfbe5e488976d8b9b77e69a736e8c919053f9415551209dce2d25e
+Result = Pass (0)
+Payload = 839d8cfa2c921c3cceb7d1f46bd2eaad706e53f64523d8c0
+
+Count = 65
+Nonce = f42cb0cce9efb6
+Adata = 00
+CT = be8be6046ac58411a00c131dd4a72d565f98d87a2c89124b1ef530d0
+Result = Fail (2 - CT changed)
+
+Count = 66
+Nonce = 24b7a65391f88b
+Adata = 00
+CT = f00628e10e8e0115b4a4532a1212a23aade4090832c1972d750125f3
+Result = Pass (0)
+Payload = 3bed52236182c19418867d468dbf47c8aac46c02445f99bb
+
+Count = 67
+Nonce = d2a7eb45780df3
+Adata = 00
+CT = 9078151f674d5f7b56e2451b0316156f776459f17d277e0108aaaf93
+Result = Fail (2 - CT changed)
+
+Count = 68
+Nonce = 046cbfd26093d8
+Adata = 00
+CT = 921cbecce3b06f3d655a5a0a4d212320d4f147575079fd23bd95e677
+Result = Fail (2 - CT changed)
+
+Count = 69
+Nonce = 51b13b0b04d077
+Adata = 00
+CT = 8cab1ff22d474e9863c153e84680e2a66981f036051360477e2ebb1d
+Result = Fail (2 - CT changed)
+
+Count = 70
+Nonce = ce2e9967bf9eb7
+Adata = 00
+CT = 15f476b5aefe072548a54f59506d9c3b9ce29025340214be662f8684
+Result = Fail (1 - Adata changed)
+
+Count = 71
+Nonce = b672c91376f533
+Adata = 00
+CT = 758aa03dc72c362c43b5f85bfaa3db4a74860887a8c29e47d5642830
+Result = Pass (0)
+Payload = 4f7a561e61b7861719e4445057ac9b74a9be953b772b09ec
+
+Count = 72
+Nonce = 62f6f1872462d8
+Adata = 00
+CT = ec645769b22161567e6a7e23aa06575bc767a34aa54d3cba01472fe1
+Result = Fail (1 - Adata changed)
+
+Count = 73
+Nonce = a6d01fb88ca547
+Adata = 00
+CT = 615cbeabbe163ba8bc9c073df9ad40833fcf3f424644ccc37aa999d7
+Result = Pass (0)
+Payload = a36155de477364236591e453008114075b4872120ef17264
+
+Count = 74
+Nonce = 46ad6ebbd8644a
+Adata = 00
+CT = 0ed6cc6451de57ca672d56dee45d4548a810d5c49dfe442dd27b7cf2
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = f7079dfa3b5c7b056347d7e437bcded683abd6e2c9e069d333284082cbb5d453
+
+Count = 75
+Nonce = a544218dadd3c1
+Adata = 00
+CT = bc51c3925a960e7732533e4ef3a4f69ee6826de952bcb0fd374f3bb6db8377ebfc79674858c4f305
+Result = Pass (0)
+Payload = d3d5424e20fbec43ae495353ed830271515ab104f8860c98
+
+Count = 76
+Nonce = bfcda8b5a2d0d2
+Adata = 00
+CT = afa1fa8e8a70e26b02161150556d604101fdf423f332c3363275f2a4907d51b734fe7238cebbd48f
+Result = Fail (2 - CT changed)
+
+Count = 77
+Nonce = 6bae7f35c56b27
+Adata = 00
+CT = 72bc8ef21a847047091b673ccf231d35ecf6f4049741703be672f1f22cbe4a5305f19aaa6967237b
+Result = Fail (1 - Adata changed)
+
+Count = 78
+Nonce = c5e4214b1bf209
+Adata = 00
+CT = b719f6555fc4e5424273f5903d5672af460413110278707f400b152113c3976be63dcd9e7a84ddac
+Result = Fail (1 - Adata changed)
+
+Count = 79
+Nonce = 9d773a31fe2ec7
+Adata = 00
+CT = 4539bb13382b034ddb16a3329148f9243a4eee998fe444aff2870ce198af11f4fb698a67af6c89ad
+Result = Pass (0)
+Payload = 839d8cfa2c921c3cceb7d1f46bd2eaad706e53f64523d8c0
+
+Count = 80
+Nonce = f42cb0cce9efb6
+Adata = 00
+CT = 47cbb909cb12fa0a4b0f1aefd54c52d1edd1533290f76b8ccc98b3f5758972bf08ea9e88dc6e54ed
+Result = Fail (2 - CT changed)
+
+Count = 81
+Nonce = 24b7a65391f88b
+Adata = 00
+CT = 6d0f928352a17d63aca1899cbd305e1f831f1638d27c1e24432704eff9b6830476db3d30d4c103e4
+Result = Pass (0)
+Payload = 3bed52236182c19418867d468dbf47c8aac46c02445f99bb
+
+Count = 82
+Nonce = d2a7eb45780df3
+Adata = 00
+CT = e0e686d917f78b3b0058fed7b084976244789073a6305ff571256981db86f1e768170a104ebfb81d
+Result = Fail (2 - CT changed)
+
+Count = 83
+Nonce = 046cbfd26093d8
+Adata = 00
+CT = 960c573f5d6934a4cac49d06998f827b3d665cf02c998fe55efbbae6a346863a93d52e0321cef8b2
+Result = Fail (2 - CT changed)
+
+Count = 84
+Nonce = 51b13b0b04d077
+Adata = 00
+CT = 7cf8f4806848e34aa7d3bd7e2cb9f5d9ff21395ff6d34826ac2fdc3cc683f6120e405f446a10e0f3
+Result = Fail (2 - CT changed)
+
+Count = 85
+Nonce = ce2e9967bf9eb7
+Adata = 00
+CT = e4f6445ca36e7ee3323f11f6a5ca8ded0c85871e092aa687d254f7765b6155054a5efde28dd38750
+Result = Fail (1 - Adata changed)
+
+Count = 86
+Nonce = b672c91376f533
+Adata = 00
+CT = f23ac1426cb1130c9a0913b347d8efafb6ed125913aa678a9dc42d22a5436bc12eff5505edb25e19
+Result = Pass (0)
+Payload = 4f7a561e61b7861719e4445057ac9b74a9be953b772b09ec
+
+Count = 87
+Nonce = 62f6f1872462d8
+Adata = 00
+CT = ac9f131389181b1023f1ee47633aa433fc5d93a87d9ece962db05feb368ab772d977fd97b35262fa
+Result = Fail (1 - Adata changed)
+
+Count = 88
+Nonce = a6d01fb88ca547
+Adata = 00
+CT = 773b8eea2e9830297ac11d3c1f6ea4008c96040e83d76d55789d2043179fdd8fdcbd52313b7b15cb
+Result = Pass (0)
+Payload = a36155de477364236591e453008114075b4872120ef17264
+
+Count = 89
+Nonce = 46ad6ebbd8644a
+Adata = 00
+CT = d3fae92043c419fe8ac0d7491ca8041ad089559d895103cf079a2bac0ab4bc249bbdb330181cdd16
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = f7079dfa3b5c7b056347d7e437bcded683abd6e2c9e069d333284082cbb5d453
+
+Count = 90
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = 63e00d30e4b08fd2a1cc8d70fab327b2368e77a93be4f4123d14fb3f
+Result = Pass (0)
+Payload = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e
+
+Count = 91
+Nonce = 894dcaa61008eb8fb052c60d41
+Adata = 00
+CT = bb5425b3869b76856ec58e39886fb6f6f2ac13fe44cb132d8d0c0099
+Result = Fail (2 - CT changed)
+
+Count = 92
+Nonce = 8feba0d720aa4a5e35abc99e82
+Adata = 00
+CT = 2ca3be419d5be5ed682f8954d2c20efd9e6d360814735daeefd4365c
+Result = Fail (1 - Adata changed)
+
+Count = 93
+Nonce = ed04c9ca8702aec8d0a58e09a0
+Adata = 00
+CT = 3d34bda62db39d6118d6fd5cd38f1a3820ca69ce584b94a2a4ccbef1
+Result = Fail (1 - Adata changed)
+
+Count = 94
+Nonce = 1501a243bf60b2cb40d5aa20ca
+Adata = 00
+CT = 377b2f1e7bd9e3d1077038e084f61950761361095f7eeebbf1a72afc
+Result = Pass (0)
+Payload = f5730a05fec31a11662e2e14e362ccc75c7c30cdfccbf994
+
+Count = 95
+Nonce = c6edaf35f0cb433500a8c3a613
+Adata = 00
+CT = 9cef6c889ff51666df9dd1dd2215c15f4b2078a29373c106be4f5f9a
+Result = Fail (2 - CT changed)
+
+Count = 96
+Nonce = d65e0e53f765f9d5e6795c0c5e
+Adata = 00
+CT = 6cab3060bf3b33b163b933c2ed0ba51406810b54d0edcf5c9d0ef4f7
+Result = Pass (0)
+Payload = 20e394c7cc90bdfa6186fc1ba6fff158dfc690e24ba4c9fb
+
+Count = 97
+Nonce = 2b0163418a341588db0f5786d8
+Adata = 00
+CT = f9543a659e9a8b7d75dd859df923817452735f5051726422c08a9e85
+Result = Fail (2 - CT changed)
+
+Count = 98
+Nonce = f16bba081bddda83546eabc9a5
+Adata = 00
+CT = 0d20bf6a9d02da72091d94cdb38743bfea2473d3ab62dcad75dd819a
+Result = Fail (2 - CT changed)
+
+Count = 99
+Nonce = ace99268a32b9c1b5ccd8b0d84
+Adata = 00
+CT = 8bca01e6ebd7ebcdfe52b88e314670ffeb35882fc05394b386e205f9
+Result = Fail (2 - CT changed)
+
+Count = 100
+Nonce = 24570517bbb0df1b3fbd32f57a
+Adata = 00
+CT = 7061c84e2e1d9d58013543ff82666055a1f055c1296c42c8f73a8bf0
+Result = Fail (1 - Adata changed)
+
+Count = 101
+Nonce = a6b2371acf8321864c08ddb4d8
+Adata = 00
+CT = c5aa500d1f7c09a590e9d15d6860c4433684e04dd6bc5c8f94f223f0
+Result = Pass (0)
+Payload = 1a43ca628026219c5a430c54021a5a3152ae517167399635
+
+Count = 102
+Nonce = f8e2d4e043f5fe7a72b6117811
+Adata = 00
+CT = e3efa7971e27ba1245ee9491ebdbb28ad9b24b325da5760417af8b14
+Result = Fail (1 - Adata changed)
+
+Count = 103
+Nonce = c2b60f14c894ec6178fe79919f
+Adata = 00
+CT = 852cca903d7fdf899807bd14642057534c8a0ccacb8c7b8fb4d35d44
+Result = Pass (0)
+Payload = 3e707d98f19972a63d913e6ea7533af2f41ff98aee2b2a36
+
+Count = 104
+Nonce = 4de4c909ac0cc5fc608baf45ac
+Adata = 00
+CT = e04fd4f5b60833021ed57c98de300bb68d0d892b2bf68e080bc044b1
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 1b0e8df63c57f05d9ac457575ea764524b8610ae5164e6215f426f5a7ae6ede4
+
+Count = 105
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = f0050ad16392021a3f40207bed3521fb1e9f808f49830c423a578d179902f912f9ea1afbce1120b3
+Result = Pass (0)
+Payload = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e
+
+Count = 106
+Nonce = 894dcaa61008eb8fb052c60d41
+Adata = 00
+CT = c408190d0fbf5034f83b24a8ed9657331a7ce141de4fae769084607b83bd06e6442eac8dacf583cc
+Result = Fail (2 - CT changed)
+
+Count = 107
+Nonce = 8feba0d720aa4a5e35abc99e82
+Adata = 00
+CT = 52b3d31d02d1b92b38cbae8c510204dde6bf9588e994296c9002a46cfb734290924a15e9c3d99924
+Result = Fail (1 - Adata changed)
+
+Count = 108
+Nonce = ed04c9ca8702aec8d0a58e09a0
+Adata = 00
+CT = f80190470212ce1e64bf4c64ca0133d90469abf87a8233c2b238e316c3f9adccce95e8c8b9c7e8d2
+Result = Fail (1 - Adata changed)
+
+Count = 109
+Nonce = 1501a243bf60b2cb40d5aa20ca
+Adata = 00
+CT = 254b847d4175bbb44a82b4e805514fa444c224710933f3ec8aaa3f0133234c0cd91609982adc034b
+Result = Pass (0)
+Payload = f5730a05fec31a11662e2e14e362ccc75c7c30cdfccbf994
+
+Count = 110
+Nonce = c6edaf35f0cb433500a8c3a613
+Adata = 00
+CT = 7a5c7bc02aa69efc5a159d653f3993399f69e20752c3b00633255731cd88345860da913bc696fdc1
+Result = Fail (2 - CT changed)
+
+Count = 111
+Nonce = d65e0e53f765f9d5e6795c0c5e
+Adata = 00
+CT = c3618c991b15de641d291419ff6957e8b9ae5046dd8c6f08fafb76adf12f36740347e3edae62bca4
+Result = Pass (0)
+Payload = 20e394c7cc90bdfa6186fc1ba6fff158dfc690e24ba4c9fb
+
+Count = 112
+Nonce = 2b0163418a341588db0f5786d8
+Adata = 00
+CT = 240927bfd671a92aef0311395ad55ae42233ecee53873da4066f55f23d4e55bcbbbf2312ea2d8071
+Result = Fail (2 - CT changed)
+
+Count = 113
+Nonce = f16bba081bddda83546eabc9a5
+Adata = 00
+CT = 4731a7e690c77cd47582ce54a1cec23d94c856b93a9fc767004753689cc84810b8414f1464c0c5b9
+Result = Fail (2 - CT changed)
+
+Count = 114
+Nonce = ace99268a32b9c1b5ccd8b0d84
+Adata = 00
+CT = f0ea12eaff20c3a50674aa1546aaae3bd5c9249108535b21504da83478ede24026ec91fb12769e4b
+Result = Fail (2 - CT changed)
+
+Count = 115
+Nonce = 24570517bbb0df1b3fbd32f57a
+Adata = 00
+CT = 5b164d9752ad6c497a7ab2d0bf8be68fea084ea5839b07b7c9fcf9b9fd5e99767a7b1679b57ea961
+Result = Fail (1 - Adata changed)
+
+Count = 116
+Nonce = a6b2371acf8321864c08ddb4d8
+Adata = 00
+CT = bd37326da18e5ac79a1a9512f724bb539530868576b79c67acb5a51d10a58d6584fbe73f1063c31b
+Result = Pass (0)
+Payload = 1a43ca628026219c5a430c54021a5a3152ae517167399635
+
+Count = 117
+Nonce = f8e2d4e043f5fe7a72b6117811
+Adata = 00
+CT = 0455b4dd1069281e10531c0dc180ced9a5ef5d3fe0007470ce54cd7623a80a176f29a01b3abb642e
+Result = Fail (1 - Adata changed)
+
+Count = 118
+Nonce = c2b60f14c894ec6178fe79919f
+Adata = 00
+CT = ecd337640022635ce1ed273756d02b7feeb2515614c1fadc95c66d3f411b478853886afd177d88c3
+Result = Pass (0)
+Payload = 3e707d98f19972a63d913e6ea7533af2f41ff98aee2b2a36
+
+Count = 119
+Nonce = 4de4c909ac0cc5fc608baf45ac
+Adata = 00
+CT = e25d7c9fb388596b13a13b885d5b24e31579a3494ad256da830b2b6317716b3975e2b101aebdd920
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 1b0e8df63c57f05d9ac457575ea764524b8610ae5164e6215f426f5a7ae6ede4
+
+Count = 120
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = 92d00fbe
+Result = Pass (0)
+Payload = 00
+
+Count = 121
+Nonce = 78c46e3249ca28
+Adata = 232e957c65ffa11988e830d4617d500f1c4a35c1221f396c41ab214f074ca2dc
+CT = 9143e5c4
+Result = Fail (2 - CT changed)
+
+Count = 122
+Nonce = c18d9e7971e2ae
+Adata = 0d40324aa758dbbb5391b5e6edb8a2310c94a4ae51d4fba8a7458d7cc8488baa
+CT = 54337466
+Result = Fail (1 - Adata changed)
+
+Count = 123
+Nonce = 162d061351d82d
+Adata = 106d1fb32d948b0d8884f178ad2332a599445fae0f6f71f9ebe53a60b2df9b8e
+CT = bf0bf84c
+Result = Fail (1 - Adata changed)
+
+Count = 124
+Nonce = 3fcb328bc96404
+Adata = 10b2ffed4f95af0f98ed4f77c677b5786ad01b31c095bbc6e1c99cf13977abba
+CT = 11250056
+Result = Pass (0)
+Payload = 00
+
+Count = 125
+Nonce = b3fd1eb1422277
+Adata = fa5398cf4cddbe4b45e9f5d7491cd9eefc5e494255961ba3f4b40d22b5f5fe76
+CT = 13de5339
+Result = Fail (2 - CT changed)
+
+Count = 126
+Nonce = c42ac63de6f12a
+Adata = 7ff8d06c5abcc50d3820de34b03089e6c5b202bcbaabca892825553d4d30020a
+CT = 4eed80fd
+Result = Pass (0)
+Payload = 00
+
+Count = 127
+Nonce = d4a7a672237e17
+Adata = d1cdad7fe886d07625a4334be6de4df0645d2a8b4008a8d35f04e6bcf87bfa56
+CT = 4bc2e450
+Result = Fail (2 - CT changed)
+
+Count = 128
+Nonce = b23255372455c6
+Adata = d2e2c3607c40e0a807b86c6ebbc502ab42bdb7f85ab26299cd963bbba3a3a8fa
+CT = b30e6bbd
+Result = Fail (2 - CT changed)
+
+Count = 129
+Nonce = 92272d40475fbb
+Adata = 2f3af695ee33a9ebe6a48ed1b00e337261857110bb104191a54fd13bd960d8bc
+CT = f7c11fe2
+Result = Fail (2 - CT changed)
+
+Count = 130
+Nonce = c4a756f6024a9d
+Adata = 2317b324b6420ada9ea7bf52b71c5faf2485528da5f56b42c517be6355cdb28b
+CT = 76673751
+Result = Fail (1 - Adata changed)
+
+Count = 131
+Nonce = 3a1701b185d33a
+Adata = e5d54df8ed9f89b98c5ebb1bc5d5279c2e182784ff4cd9c869ae152e29d7a2b2
+CT = 9a5382c3
+Result = Pass (0)
+Payload = 00
+
+Count = 132
+Nonce = e4db2e80dc3f63
+Adata = 7616bdf5737d01f936072b6576fa76556dfa072f7e2d7de16b9dc96ac8de409c
+CT = 9e632f56
+Result = Fail (1 - Adata changed)
+
+Count = 133
+Nonce = 4f490ce07e0150
+Adata = 3e12d09632c644c540077c6f90726d4167423a679322b2000a3f19cfcea02b33
+CT = e1842c46
+Result = Pass (0)
+Payload = 00
+
+Count = 134
+Nonce = b4aaf9ad1bde60
+Adata = 8c96c891456ddec29fe04299506723db2079a6667f96db5d198bf085acf2a4ef
+CT = 9f644671
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = a4bc10b1a62c96d459fbaf3a5aa3face7313bb9e1253e696f96a7a8e36801088
+
+Count = 135
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = 93af11a08379eb37a16aa2837f09d69d
+Result = Pass (0)
+Payload = 00
+
+Count = 136
+Nonce = 78c46e3249ca28
+Adata = 232e957c65ffa11988e830d4617d500f1c4a35c1221f396c41ab214f074ca2dc
+CT = d19b0c14ec686a7961ca7c386d125a65
+Result = Fail (2 - CT changed)
+
+Count = 137
+Nonce = c18d9e7971e2ae
+Adata = 0d40324aa758dbbb5391b5e6edb8a2310c94a4ae51d4fba8a7458d7cc8488baa
+CT = 02ea916d60e2ceec6d9dc9b1185569b3
+Result = Fail (1 - Adata changed)
+
+Count = 138
+Nonce = 162d061351d82d
+Adata = 106d1fb32d948b0d8884f178ad2332a599445fae0f6f71f9ebe53a60b2df9b8e
+CT = fabd2d0c422b47d363ea9936ff4a311b
+Result = Fail (1 - Adata changed)
+
+Count = 139
+Nonce = 3fcb328bc96404
+Adata = 10b2ffed4f95af0f98ed4f77c677b5786ad01b31c095bbc6e1c99cf13977abba
+CT = b3884b69d117146cfa5529901753ddc0
+Result = Pass (0)
+Payload = 00
+
+Count = 140
+Nonce = b3fd1eb1422277
+Adata = fa5398cf4cddbe4b45e9f5d7491cd9eefc5e494255961ba3f4b40d22b5f5fe76
+CT = 7162026b6306e74fe32ece8433801bc2
+Result = Fail (2 - CT changed)
+
+Count = 141
+Nonce = c42ac63de6f12a
+Adata = 7ff8d06c5abcc50d3820de34b03089e6c5b202bcbaabca892825553d4d30020a
+CT = b53d93cbfd3d5cf3720cef5080bc7224
+Result = Pass (0)
+Payload = 00
+
+Count = 142
+Nonce = d4a7a672237e17
+Adata = d1cdad7fe886d07625a4334be6de4df0645d2a8b4008a8d35f04e6bcf87bfa56
+CT = c8bbecf69ecf8d10f0863bb4b7cbed51
+Result = Fail (2 - CT changed)
+
+Count = 143
+Nonce = b23255372455c6
+Adata = d2e2c3607c40e0a807b86c6ebbc502ab42bdb7f85ab26299cd963bbba3a3a8fa
+CT = 6037145cc23a175760ae4b573907c80c
+Result = Fail (2 - CT changed)
+
+Count = 144
+Nonce = 92272d40475fbb
+Adata = 2f3af695ee33a9ebe6a48ed1b00e337261857110bb104191a54fd13bd960d8bc
+CT = df7ea77425d631f652ffe096a8157f71
+Result = Fail (2 - CT changed)
+
+Count = 145
+Nonce = c4a756f6024a9d
+Adata = 2317b324b6420ada9ea7bf52b71c5faf2485528da5f56b42c517be6355cdb28b
+CT = 7182b25ef5b113c13fa8f6769e74f1e2
+Result = Fail (1 - Adata changed)
+
+Count = 146
+Nonce = 3a1701b185d33a
+Adata = e5d54df8ed9f89b98c5ebb1bc5d5279c2e182784ff4cd9c869ae152e29d7a2b2
+CT = 0a5d1bc02c5fe096a8b9d94d1267c49a
+Result = Pass (0)
+Payload = 00
+
+Count = 147
+Nonce = e4db2e80dc3f63
+Adata = 7616bdf5737d01f936072b6576fa76556dfa072f7e2d7de16b9dc96ac8de409c
+CT = 9eb6d9757ec7c56cc8c79461e0017486
+Result = Fail (1 - Adata changed)
+
+Count = 148
+Nonce = 4f490ce07e0150
+Adata = 3e12d09632c644c540077c6f90726d4167423a679322b2000a3f19cfcea02b33
+CT = 1eda43bf07f2bf003107f3a0ba3a4c18
+Result = Pass (0)
+Payload = 00
+
+Count = 149
+Nonce = b4aaf9ad1bde60
+Adata = 8c96c891456ddec29fe04299506723db2079a6667f96db5d198bf085acf2a4ef
+CT = 5287cc160c5dd3a0f9c1986aac2a621c
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = a4bc10b1a62c96d459fbaf3a5aa3face7313bb9e1253e696f96a7a8e36801088
+
+Count = 150
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = 866d4227
+Result = Pass (0)
+Payload = 00
+
+Count = 151
+Nonce = e8de970f6ee8e80ede933581b5
+Adata = 89f8b068d34f56bc49d839d8e47b347e6dae737b903b278632447e6c0485d26a
+CT = 94cb1127
+Result = Fail (2 - CT changed)
+
+Count = 152
+Nonce = 6de75d3c05e83755083399a5f7
+Adata = 504b08cf34cbe17acf631ef219ae01437ebb6a980ab2f00121bb3073701b6511
+CT = 82c2b67a
+Result = Fail (1 - Adata changed)
+
+Count = 153
+Nonce = 58d43b9f1581c590daab1a5c56
+Adata = 749f149ef306c70a5d006d9777adbbf7c0de453898c2978ef7c281535ea9b24c
+CT = 8c8283f9
+Result = Fail (1 - Adata changed)
+
+Count = 154
+Nonce = dfdcbdff329f7af70731d8e276
+Adata = 2ae56ddde2876d70b3b34eda8c2b1d096c836d5225d53ec460b724b6e16aa5a3
+CT = c4ac0952
+Result = Pass (0)
+Payload = 00
+
+Count = 155
+Nonce = 199ec321d1d24d5408076912d6
+Adata = a77526f3614cd974498a76d8b3cb7bacc623fdc9c85503289c462df888b199ed
+CT = c59aa931
+Result = Fail (2 - CT changed)
+
+Count = 156
+Nonce = 60f2490ba0c658848859fcbea8
+Adata = 3ad743283064929bf4fe4e0807f710f5e6a273e22614c728c3280a27b6c614a0
+CT = 27c3953d
+Result = Pass (0)
+Payload = 00
+
+Count = 157
+Nonce = 6f29ca274190400720bba27651
+Adata = c0850aaf141bd3f1b24f4d882590f58682b41f874748f29f8925b4914f444842
+CT = cb1ac8eb
+Result = Fail (2 - CT changed)
+
+Count = 158
+Nonce = f1dfb6fdb31cb423226f181c09
+Adata = ac6b08900fc1c9463e7dfdb60eee444c4989d7b200e675f3220ba1e14eed0ab4
+CT = 4dcc55cc
+Result = Fail (2 - CT changed)
+
+Count = 159
+Nonce = 0d45226c98eaa9bb445a3aa4f9
+Adata = b9cb3e1a5bcccb0b0599414c9822275b66fa0f913d51bdb0a2228cbb5aad0e0a
+CT = 727d8f5e
+Result = Fail (2 - CT changed)
+
+Count = 160
+Nonce = 39cdbb24bd273a3fe96f42ca9d
+Adata = ddfe6c22f4cdc3128050072005f5bd4ecdef1d836e891683f1ba921d33fafba7
+CT = 5aa56a54
+Result = Fail (1 - Adata changed)
+
+Count = 161
+Nonce = db113f38f0504615c5c9347c3d
+Adata = 3b71bc84e48c6dadf6ead14621d22468a3d4c9c103ac96970269730bcfce239b
+CT = c38fbdff
+Result = Pass (0)
+Payload = 00
+
+Count = 162
+Nonce = d16a20ef5f6587f1ee3cb7850b
+Adata = b1133e1cd369617a9f937e9a1eb86a0979ee30b5b7b0b6ff838d9e11301d6b72
+CT = 6be30c42
+Result = Fail (1 - Adata changed)
+
+Count = 163
+Nonce = d35f531f714694b5e49303a980
+Adata = 55b791ee495299916ff3c2327b4990952bebd0a2da9acfc553c6c996e354a4b5
+CT = d34e90bb
+Result = Pass (0)
+Payload = 00
+
+Count = 164
+Nonce = 220624db34a022b758473994a2
+Adata = 5b3b2ae87b0d6759f38a858423227f8687f35478a8f565409b741eadcac4d8c4
+CT = 4a5d14bc
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = 8c5cf3457ff22228c39c051c4e05ed4093657eb303f859a9d4b0f8be0127d88a
+
+Count = 165
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = 867b0d87cf6e0f718200a97b4f6d5ad5
+Result = Pass (0)
+Payload = 00
+
+Count = 166
+Nonce = e8de970f6ee8e80ede933581b5
+Adata = 89f8b068d34f56bc49d839d8e47b347e6dae737b903b278632447e6c0485d26a
+CT = 677a040d46ee3f2b7838273bdad14f16
+Result = Fail (2 - CT changed)
+
+Count = 167
+Nonce = 6de75d3c05e83755083399a5f7
+Adata = 504b08cf34cbe17acf631ef219ae01437ebb6a980ab2f00121bb3073701b6511
+CT = f650d46ade2cbabbc68ead6df1ea0c37
+Result = Fail (1 - Adata changed)
+
+Count = 168
+Nonce = 58d43b9f1581c590daab1a5c56
+Adata = 749f149ef306c70a5d006d9777adbbf7c0de453898c2978ef7c281535ea9b24c
+CT = 11b8fe8c139ee38f77fd8fa552cbff67
+Result = Fail (1 - Adata changed)
+
+Count = 169
+Nonce = dfdcbdff329f7af70731d8e276
+Adata = 2ae56ddde2876d70b3b34eda8c2b1d096c836d5225d53ec460b724b6e16aa5a3
+CT = ad879c64425e6c1ec4841bbb0f99aa8b
+Result = Pass (0)
+Payload = 00
+
+Count = 170
+Nonce = 199ec321d1d24d5408076912d6
+Adata = a77526f3614cd974498a76d8b3cb7bacc623fdc9c85503289c462df888b199ed
+CT = 3c64f8731930ae000162c10654531066
+Result = Fail (2 - CT changed)
+
+Count = 171
+Nonce = 60f2490ba0c658848859fcbea8
+Adata = 3ad743283064929bf4fe4e0807f710f5e6a273e22614c728c3280a27b6c614a0
+CT = e2751f153fc76c0dec5e0cf2d30c1a28
+Result = Pass (0)
+Payload = 00
+
+Count = 172
+Nonce = 6f29ca274190400720bba27651
+Adata = c0850aaf141bd3f1b24f4d882590f58682b41f874748f29f8925b4914f444842
+CT = 76127bf891141e73854752ed10c02bd0
+Result = Fail (2 - CT changed)
+
+Count = 173
+Nonce = f1dfb6fdb31cb423226f181c09
+Adata = ac6b08900fc1c9463e7dfdb60eee444c4989d7b200e675f3220ba1e14eed0ab4
+CT = 4bd833f9da0496e5f6a08a05d02df385
+Result = Fail (2 - CT changed)
+
+Count = 174
+Nonce = 0d45226c98eaa9bb445a3aa4f9
+Adata = b9cb3e1a5bcccb0b0599414c9822275b66fa0f913d51bdb0a2228cbb5aad0e0a
+CT = 05f166328a67a8c58b10a7348f3df612
+Result = Fail (2 - CT changed)
+
+Count = 175
+Nonce = 39cdbb24bd273a3fe96f42ca9d
+Adata = ddfe6c22f4cdc3128050072005f5bd4ecdef1d836e891683f1ba921d33fafba7
+CT = 42499bcd949a5163855a9794f11f917e
+Result = Fail (1 - Adata changed)
+
+Count = 176
+Nonce = db113f38f0504615c5c9347c3d
+Adata = 3b71bc84e48c6dadf6ead14621d22468a3d4c9c103ac96970269730bcfce239b
+CT = fc85464a81fe372c12c9e4f0f3bf9c37
+Result = Pass (0)
+Payload = 00
+
+Count = 177
+Nonce = d16a20ef5f6587f1ee3cb7850b
+Adata = b1133e1cd369617a9f937e9a1eb86a0979ee30b5b7b0b6ff838d9e11301d6b72
+CT = 8c7501f423647dee77668858c5e350bb
+Result = Fail (1 - Adata changed)
+
+Count = 178
+Nonce = d35f531f714694b5e49303a980
+Adata = 55b791ee495299916ff3c2327b4990952bebd0a2da9acfc553c6c996e354a4b5
+CT = b1c09b093788da19e33c5a6e82ed9627
+Result = Pass (0)
+Payload = 00
+
+Count = 179
+Nonce = 220624db34a022b758473994a2
+Adata = 5b3b2ae87b0d6759f38a858423227f8687f35478a8f565409b741eadcac4d8c4
+CT = d2231ee1455b0bc337c4f8173fb8647c
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = 8c5cf3457ff22228c39c051c4e05ed4093657eb303f859a9d4b0f8be0127d88a
+
+Count = 180
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = c2fe12658139f5d0dd22cadf2e901695b579302a72fc56083ebc7720
+Result = Pass (0)
+Payload = 78c46e3249ca28e1ef0531d80fd37c124d9aecb7be6668e3
+
+Count = 181
+Nonce = 6ba004fd176791
+Adata = 5a053b2a1bb87e85d56527bfcdcd3ecafb991bb10e4c862bb0751c700a29f54b
+CT = 94748ba81229e53c38583a8564b23ebbafc6f6efdf4c2a81c44db2c9
+Result = Fail (2 - CT changed)
+
+Count = 182
+Nonce = 45c5c284836414
+Adata = 8f01a61eb17366d4e70942ab69b4f4bcf8ff6a97f5972ee5780a264c9dcf7d93
+CT = 1d670ccf3e9ba59186c48da2e5bd0ab21973eee2ea2985bf83a09067
+Result = Fail (1 - Adata changed)
+
+Count = 183
+Nonce = c69f7679c80546
+Adata = 5d6c04a5b422b46065a79a889e30ac8d1b53b65d230d4c88190903a24e1fe1ea
+CT = 2c8c80ff10fac1bf6c9c83533c1514ee032c0983730b0657392ae25d
+Result = Fail (1 - Adata changed)
+
+Count = 184
+Nonce = 57b940550a383b
+Adata = 33c2c3a57bf8393b126982c96d87daeacd5eadad1519073ad8c84cb9b760296f
+CT = e1b4ec4279bb62902c12521e6b874171695c5da46c647cc03b91ff03
+Result = Pass (0)
+Payload = 6fb5ce32a851676753ba3523edc5ca82af1843ffc08f1ef0
+
+Count = 185
+Nonce = 11edd12ea5873d
+Adata = e32e5384038379e2b7382ba337b6f7a72a1569e110ee89c4dd6aa6f7e69f5250
+CT = b5dda89fe879d6a665b99285b6d937fd5877ebef4de049fb64b837fb
+Result = Fail (2 - CT changed)
+
+Count = 186
+Nonce = f32222e9eec4bd
+Adata = 684595e36eda1db5f586941c9f34c9f8d477970d5ccc14632d1f0cec8190ae68
+CT = 224db21beb8cd0069007660e783c3f85706b014128368aab2a4e56a7
+Result = Pass (0)
+Payload = 2c29d4e2bb9294e90cb04ec697e663a1f7385a39f90c8ccf
+
+Count = 187
+Nonce = e0a0a7f262cb51
+Adata = 1d93b2856ad2bf3700440f9a281bd8947ba209e9ffd18e69921ed0678c957c6c
+CT = ba1ce3a799e1173178b6788723005566f9269d5828c85d28e960a769
+Result = Fail (2 - CT changed)
+
+Count = 188
+Nonce = 40316e7b38bdad
+Adata = 6e49acd9c26944740c778e74b1dbaa8d640c7e18e949a1661f8a77543db69e1f
+CT = 79d59e4bb251988c019c4eaaee2a2513f9cb0521334018fded14a5a5
+Result = Fail (2 - CT changed)
+
+Count = 189
+Nonce = 33008ef5baf263
+Adata = a726f31d9a22bfc0e7e4c3111b0d304e106ab04ed318f8bfe6ec9cb3a811285b
+CT = af4350795f24087aa05070d6d5f55ebb12d7ad3141066866d7d6c61d
+Result = Fail (2 - CT changed)
+
+Count = 190
+Nonce = b48a16fb9a065d
+Adata = be05e9c934c1dcba45223d47c6646a2d13c3b93265e354ae4970484b5101d809
+CT = 22d2da531be1f0d1da4bc21f984d29bf56bed2e92da6bf42d0605b84
+Result = Fail (1 - Adata changed)
+
+Count = 191
+Nonce = 14c9bd561c47c1
+Adata = 141ae365f8e65ab9196c4e8cd4e62189b304d67de38f2117e84ec0ec8f260ebd
+CT = 61b46c9024eed3989064a52df90349c18e14e4b552779d3f8f9d6814
+Result = Pass (0)
+Payload = c22524a1ea444be3412b0d773d4ea2ff0af4c1ad2383cba8
+
+Count = 192
+Nonce = 5fb871eac2e52a
+Adata = ff23906e9067da8999842318f2a867759ca2d171395c2ff31fa5a4e2ab349c45
+CT = 539799c2b22a33dd648fc4497d12f9455beaf932f1eaaff4d930f5ce
+Result = Fail (1 - Adata changed)
+
+Count = 193
+Nonce = 1ccec9923aa6e8
+Adata = 88a6d037009a1c1756f72bb4589d6d940bd514ed55386baefacc6ac3ca6f8795
+CT = 52f8205534447d722be2b9377f7395938cc88af081a11ccb0d83fa19
+Result = Pass (0)
+Payload = 518a7fb11c463bf23798982118f3cfe4d7ddde9184f37d4f
+
+Count = 194
+Nonce = 68a5351e4422c8
+Adata = 303c767468f48ac9f6e331bbad535b06aa00ab593327320799e17eff63afd3fe
+CT = d11c892ae155098f5e4b5fe60c7afd74fb2dbcc4db956556f243e273
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = 705334e30f53dd2f92d190d2c1437c8772f940c55aa35e562214ed45bd458ffe
+
+Count = 195
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = 3341168eb8c48468c414347fb08f71d2086f7c2d1bd581ce1ac68bd42f5ec7fa7e068cc0ecd79c2a
+Result = Pass (0)
+Payload = 78c46e3249ca28e1ef0531d80fd37c124d9aecb7be6668e3
+
+Count = 196
+Nonce = 6ba004fd176791
+Adata = 5a053b2a1bb87e85d56527bfcdcd3ecafb991bb10e4c862bb0751c700a29f54b
+CT = d543acda712b898cbb27b8f598b2e4438ce587a836e2785147c3338a2400809e739b63ba8227d2f9
+Result = Fail (2 - CT changed)
+
+Count = 197
+Nonce = 45c5c284836414
+Adata = 8f01a61eb17366d4e70942ab69b4f4bcf8ff6a97f5972ee5780a264c9dcf7d93
+CT = 39a8af5c976b995ea8049e55b68bc65503592ab00915638646288ce9dd1c7088c752e35947fdca98
+Result = Fail (1 - Adata changed)
+
+Count = 198
+Nonce = c69f7679c80546
+Adata = 5d6c04a5b422b46065a79a889e30ac8d1b53b65d230d4c88190903a24e1fe1ea
+CT = 950fbf6445f6ffb68178f52f5079d0c6081a48ae1f267a0b7fd89caef9388fbb82361b8d53d9edc6
+Result = Fail (1 - Adata changed)
+
+Count = 199
+Nonce = 57b940550a383b
+Adata = 33c2c3a57bf8393b126982c96d87daeacd5eadad1519073ad8c84cb9b760296f
+CT = fbfed2c94f50ca10466da9903ef85833ad48ca00556e66d14d8b30df941f3536ffb42083ef0e1c30
+Result = Pass (0)
+Payload = 6fb5ce32a851676753ba3523edc5ca82af1843ffc08f1ef0
+
+Count = 200
+Nonce = 11edd12ea5873d
+Adata = e32e5384038379e2b7382ba337b6f7a72a1569e110ee89c4dd6aa6f7e69f5250
+CT = 2ebfeb7a843618b37025352df3538526517ed320adfb486c04cf3426e8f975125a7eed00e5f33b6c
+Result = Fail (2 - CT changed)
+
+Count = 201
+Nonce = f32222e9eec4bd
+Adata = 684595e36eda1db5f586941c9f34c9f8d477970d5ccc14632d1f0cec8190ae68
+CT = dae13e6967c8b1ee0dd2d5ba1dd1de69f22c95da39528f9ef78e9e5e9faa058112af57f4ac78db2c
+Result = Pass (0)
+Payload = 2c29d4e2bb9294e90cb04ec697e663a1f7385a39f90c8ccf
+
+Count = 202
+Nonce = e0a0a7f262cb51
+Adata = 1d93b2856ad2bf3700440f9a281bd8947ba209e9ffd18e69921ed0678c957c6c
+CT = e683040a0bcf04c1748e7746400d6ef0f7cd8e77a29517790c63959ce534a0f87fb42a9b000dec84
+Result = Fail (2 - CT changed)
+
+Count = 203
+Nonce = 40316e7b38bdad
+Adata = 6e49acd9c26944740c778e74b1dbaa8d640c7e18e949a1661f8a77543db69e1f
+CT = 829e50e8c09e727a58287e6eb7d38edeb8ab39db279c06397d1a2111dc21aec79ef73193b306d31f
+Result = Fail (2 - CT changed)
+
+Count = 204
+Nonce = 33008ef5baf263
+Adata = a726f31d9a22bfc0e7e4c3111b0d304e106ab04ed318f8bfe6ec9cb3a811285b
+CT = 873c91e76dca0062ae66325aefb84ece3e98928f8dbc5fee7c516d2d1a8318893923f398ca249401
+Result = Fail (2 - CT changed)
+
+Count = 205
+Nonce = b48a16fb9a065d
+Adata = be05e9c934c1dcba45223d47c6646a2d13c3b93265e354ae4970484b5101d809
+CT = 343f6c86f2b852ac388a096faec4472107a924aba56d0cb88055e777bb57eb49497cd2e233ee06fd
+Result = Fail (1 - Adata changed)
+
+Count = 206
+Nonce = 14c9bd561c47c1
+Adata = 141ae365f8e65ab9196c4e8cd4e62189b304d67de38f2117e84ec0ec8f260ebd
+CT = a654238fb8b05e293dba07f9d68d75a7f0fbf40fe20edaeba1586bf922412e73ce338e372615c3bc
+Result = Pass (0)
+Payload = c22524a1ea444be3412b0d773d4ea2ff0af4c1ad2383cba8
+
+Count = 207
+Nonce = 5fb871eac2e52a
+Adata = ff23906e9067da8999842318f2a867759ca2d171395c2ff31fa5a4e2ab349c45
+CT = 4846816923ed9f0254bdd0be01028f75061d3594ad3a45bd03538d108df6ecd6f39acfe076ba5fb8
+Result = Fail (1 - Adata changed)
+
+Count = 208
+Nonce = 1ccec9923aa6e8
+Adata = 88a6d037009a1c1756f72bb4589d6d940bd514ed55386baefacc6ac3ca6f8795
+CT = 765067ef768908d91ee4c3923943e0c7be70e2e06db99a4b3e3f51ee37fdcc5d81dd85d9e9d4f44e
+Result = Pass (0)
+Payload = 518a7fb11c463bf23798982118f3cfe4d7ddde9184f37d4f
+
+Count = 209
+Nonce = 68a5351e4422c8
+Adata = 303c767468f48ac9f6e331bbad535b06aa00ab593327320799e17eff63afd3fe
+CT = e58ea6c1522e5a3e93a85edd05ae80d6cf5c4dd6d604a8f8d8a906488f79ad5d2234d72458dcfcd4
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = 705334e30f53dd2f92d190d2c1437c8772f940c55aa35e562214ed45bd458ffe
+
+Count = 210
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = c0ea400b599561e7905b99262b4565d5c3dc49fad84d7c69ef891339
+Result = Pass (0)
+Payload = e8de970f6ee8e80ede933581b5bcf4d837e2b72baa8b00c3
+
+Count = 211
+Nonce = 8fa501c5dd9ac9b868144c9fa5
+Adata = 5bb40e3bb72b4509324a7edc852f72535f1f6283156e63f6959ffaf39dcde800
+CT = 60871e03ea0eb968536c99f926ea24ef43d41272ad9fb7f63d488623
+Result = Fail (2 - CT changed)
+
+Count = 212
+Nonce = 9bc0d1502a47e46350fe8667ca
+Adata = 07203674260208d5bd4d39506836f7e76ffc58e938799f21aff7bb4dea4410d2
+CT = 81d7859dcbe51dcc94fe2591cd3b0540003d49a8c4dccbf4527e5ed0
+Result = Fail (1 - Adata changed)
+
+Count = 213
+Nonce = 611cb4c66e88f6acf96fea1919
+Adata = 327ee3657e49d4d988362fabae303ccea6638e5cb45993d9d56269bc3d3af32b
+CT = bef380ad725b65fb5fceeabf09c665bc35089f434ec831494d20d5fa
+Result = Fail (1 - Adata changed)
+
+Count = 214
+Nonce = 0dd613c0fe28e913c0edbb8404
+Adata = 2ad306575b577c2f61da7212ab63e3db3941f1f751f2356c7443531a90b9d141
+CT = fabe11c9629e598228f5209f3dbcc641fe4b1a22cadb0821d2898c3b
+Result = Pass (0)
+Payload = 9522fb1f1aa58493cba682d788186d902cfc93e80fd6b998
+
+Count = 215
+Nonce = 68806dfe720d0a9a84697de5f2
+Adata = c6b0e4dfd723d7637510f887b7852f60ecdf72e0d33396560fed6534d5b7f015
+CT = b7eb87f84951640de731d4093f1a4ed5f831138a27465d3941e92090
+Result = Fail (2 - CT changed)
+
+Count = 216
+Nonce = 3e0fe3427eeda80f02dda4fed5
+Adata = ae0d1c9c834d60ff0ecfb3c0d78c72ddb789e58adfc166c81d5fc6395b31ec33
+CT = d88f8fcd772125212ce09c2a6e5b5693dd35073f992004f0d18fc889
+Result = Pass (0)
+Payload = 38333ce78110bf53a2c2abc7db99e133ad218ca43ff7a7bc
+
+Count = 217
+Nonce = 7c0c76d9f9316ff6c98758b464
+Adata = 31a0338c3839931fa1dd5131cb796c4c6cfde9fb336d8a80ac35dec463be7a94
+CT = d2d7d52b11304fc1d15b8c20e296ba7c63d99f4ce86cc8ae0f39ecea
+Result = Fail (2 - CT changed)
+
+Count = 218
+Nonce = 07c728135bdfede0e0c8036b17
+Adata = 25a152850b4b80b19d8f0b504b2a8a241824b3a1fca8d85c8713b2c0c84b5e02
+CT = ae1d9f82efb464d5dc2018cffa309634c09b34d1122c4bd994b1d516
+Result = Fail (2 - CT changed)
+
+Count = 219
+Nonce = 710c96d7a6f09de83f0507f28a
+Adata = 2d64acfdbfc582cd9a933790eb1b739fb02e53f511255e49f421bb7acc98a130
+CT = 477c985d92ad1b69d22315235a29e3d3a5991487cbdc8d11d394d047
+Result = Fail (2 - CT changed)
+
+Count = 220
+Nonce = 977bbcdeb6a7d9dcf8664bc2d8
+Adata = 135786125258a49475338ac1961d2718433b9e84cf64f63ca52913e8dd12e505
+CT = d1c085c75d808dc6db493b8a0b4d884e0700d2844a1b4b46bd3d22eb
+Result = Fail (1 - Adata changed)
+
+Count = 221
+Nonce = 60122cbd219e5cf17415e8bc09
+Adata = 895a45ddbe0c80793eccbf820de13a233b6aa7045cfd5313388e7184c392b216
+CT = 76bdd9a7b34bf14ae121a87fdfa144f71b848744af6a2f0b1c0d067c
+Result = Pass (0)
+Payload = 794e734966e6d0001699aec3f8ab8f194de7653d3091b1b9
+
+Count = 222
+Nonce = 83a07f2e685959cb50a1bd2bce
+Adata = 02afe300ec0cf0acb59108b2f70e069300294e34f40bb032cb59907599664408
+CT = 413e2e8df9d65b4e5d3b63a738258aaee643f364be9a01b974192744
+Result = Fail (1 - Adata changed)
+
+Count = 223
+Nonce = 3542fbe0f59a6d5f3abf619b7d
+Adata = dd4531f158a2fa3bc8a339f770595048f4a42bc1b03f2e824efc6ba4985119d8
+CT = 617d8036e2039d516709062379e0550cbd71ebb90fea967c79018ad5
+Result = Pass (0)
+Payload = c5b3d71312ea14f2f8fae5bd1a453192b6604a45db75c5ed
+
+Count = 224
+Nonce = 48f2d4c0b17072e0a9c300d90b
+Adata = c56175e2cfe0d37454d989afcc36686fb34c015439601567506a4d0003182be7
+CT = 40e609c739e409750a6c41d9c6ea64ce36f70711b4ca3e365c916f91
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 314a202f836f9f257e22d8c11757832ae5131d357a72df88f3eff0ffcee0da4e
+
+Count = 225
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = 8d34cdca37ce77be68f65baf3382e31efa693e63f914a781367f30f2eaad8c063ca50795acd90203
+Result = Pass (0)
+Payload = e8de970f6ee8e80ede933581b5bcf4d837e2b72baa8b00c3
+
+Count = 226
+Nonce = 8fa501c5dd9ac9b868144c9fa5
+Adata = 5bb40e3bb72b4509324a7edc852f72535f1f6283156e63f6959ffaf39dcde800
+CT = 516c0095cc3d85fd55e48da17c592e0c7014b9daafb82bdc4b41096dfdbe9cc1ab610f8f3e038d16
+Result = Fail (2 - CT changed)
+
+Count = 227
+Nonce = 9bc0d1502a47e46350fe8667ca
+Adata = 07203674260208d5bd4d39506836f7e76ffc58e938799f21aff7bb4dea4410d2
+CT = 0293eae9f8d8bd7ad45357f733fc7b5d990d894783e18501d81ec96df41b8fa8262ed2db880b5e85
+Result = Fail (1 - Adata changed)
+
+Count = 228
+Nonce = 611cb4c66e88f6acf96fea1919
+Adata = 327ee3657e49d4d988362fabae303ccea6638e5cb45993d9d56269bc3d3af32b
+CT = 256bad8295e67d8d450f5ecc8276920ec23b1156c57be7c96ee80f60f72db2cbf25b2f8c6af8749c
+Result = Fail (1 - Adata changed)
+
+Count = 229
+Nonce = 0dd613c0fe28e913c0edbb8404
+Adata = 2ad306575b577c2f61da7212ab63e3db3941f1f751f2356c7443531a90b9d141
+CT = 6df09613ea986c2d91a57a45a0942cbf20e0dfca12fbda8c945ee6db24aea5f5098952f1203339ce
+Result = Pass (0)
+Payload = 9522fb1f1aa58493cba682d788186d902cfc93e80fd6b998
+
+Count = 230
+Nonce = 68806dfe720d0a9a84697de5f2
+Adata = c6b0e4dfd723d7637510f887b7852f60ecdf72e0d33396560fed6534d5b7f015
+CT = c5b64577d3c34e50f7da5072db5bda1d1d2c6db1a4f1183e2cc4c90ac3f798957cb09a05868a8ad5
+Result = Fail (2 - CT changed)
+
+Count = 231
+Nonce = 3e0fe3427eeda80f02dda4fed5
+Adata = ae0d1c9c834d60ff0ecfb3c0d78c72ddb789e58adfc166c81d5fc6395b31ec33
+CT = 2bfe51f1f43b982d47f76ea8206ddbf585d6f30cec0d4ef16b1556631d3b52bf24154afec1448ef6
+Result = Pass (0)
+Payload = 38333ce78110bf53a2c2abc7db99e133ad218ca43ff7a7bc
+
+Count = 232
+Nonce = 7c0c76d9f9316ff6c98758b464
+Adata = 31a0338c3839931fa1dd5131cb796c4c6cfde9fb336d8a80ac35dec463be7a94
+CT = 1622ae109073f44a4596722d9943fea774dfc2a1f939fc0914f42ec81e3af71c9a5de7e0ac16ca69
+Result = Fail (2 - CT changed)
+
+Count = 233
+Nonce = 07c728135bdfede0e0c8036b17
+Adata = 25a152850b4b80b19d8f0b504b2a8a241824b3a1fca8d85c8713b2c0c84b5e02
+CT = 4c0b361a766d366d983c41e793d75635e17f6eab2eadcf9743d67d90850c4c76a43df1f95170b29b
+Result = Fail (2 - CT changed)
+
+Count = 234
+Nonce = 710c96d7a6f09de83f0507f28a
+Adata = 2d64acfdbfc582cd9a933790eb1b739fb02e53f511255e49f421bb7acc98a130
+CT = 5b02347f30213df7f1506d7dca41b838c92aea0f190c5dba7bd5d5c8c098299394333b34fae9a110
+Result = Fail (2 - CT changed)
+
+Count = 235
+Nonce = 977bbcdeb6a7d9dcf8664bc2d8
+Adata = 135786125258a49475338ac1961d2718433b9e84cf64f63ca52913e8dd12e505
+CT = c77283ca15484d82469ce7249d1fb8e5f4c3bc8245fb4d97e26149d4a9711be81b4f69aa9fabd7f6
+Result = Fail (1 - Adata changed)
+
+Count = 236
+Nonce = 60122cbd219e5cf17415e8bc09
+Adata = 895a45ddbe0c80793eccbf820de13a233b6aa7045cfd5313388e7184c392b216
+CT = bf0d219bb50fcc1d51f654bb0fd8b44efa25aef39e2f11afe47d00f2eebb544e6ba7559ac2f34edb
+Result = Pass (0)
+Payload = 794e734966e6d0001699aec3f8ab8f194de7653d3091b1b9
+
+Count = 237
+Nonce = 83a07f2e685959cb50a1bd2bce
+Adata = 02afe300ec0cf0acb59108b2f70e069300294e34f40bb032cb59907599664408
+CT = 1609f8de59da4f50ce034977d132d4f9881a9b85ffa5bb886fa3fddc87690a359fe55f8fa12ba749
+Result = Fail (1 - Adata changed)
+
+Count = 238
+Nonce = 3542fbe0f59a6d5f3abf619b7d
+Adata = dd4531f158a2fa3bc8a339f770595048f4a42bc1b03f2e824efc6ba4985119d8
+CT = 39c2e8f6edfe663b90963b98eb79e2d4f7f28a5053ae8881567a6b4426f1667136bed4a5e32a2bc1
+Result = Pass (0)
+Payload = c5b3d71312ea14f2f8fae5bd1a453192b6604a45db75c5ed
+
+Count = 239
+Nonce = 48f2d4c0b17072e0a9c300d90b
+Adata = c56175e2cfe0d37454d989afcc36686fb34c015439601567506a4d0003182be7
+CT = 27c575be0b99af9b106f53f471c31cac4d54ea0bcb602a33fb67bb6092cd579f722ae9b680da083d
+Result = Fail (1 - Adata changed)
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/Readme.txt b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/Readme.txt
new file mode 100644
index 0000000000..88bdc95fd0
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/Readme.txt
@@ -0,0 +1,9 @@
+There are two sets of CCM example files:
+
+1. The response (.rsp) files contain properly formatted CAVS response files.
+
+2. The three DVPT{128/192/256}.txt files contain the same values as the
+ DVPT{128/192/256}.rsp files but have additional information. For the cases
+ that fail, the reason for failure is in parentheses following the result:
+ e.g., Result = Fail (2 - CT changed)
+ This additional information is not in properly formatted response files.
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT128.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT128.rsp
new file mode 100644
index 0000000000..a4fe9130a0
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT128.rsp
@@ -0,0 +1,1823 @@
+# CAVS 11.0
+# "CCM-VADT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:24 2011
+
+Plen = 24
+Nlen = 13
+Tlen = 16
+
+[Alen = 0]
+
+Key = d24a3d3dde8c84830280cb87abad0bb3
+Nonce = f1100035bb24a8d26004e0e24b
+
+Count = 0
+Adata = 00
+Payload = 7c86135ed9c2a515aaae0e9a208133897269220f30870006
+CT = 1faeb0ee2ca2cd52f0aa3966578344f24e69b742c4ab37ab1123301219c70599b7c373ad4b3ad67b
+
+Count = 1
+Adata = 00
+Payload = 48df73208cdc63d716752df7794807b1b2a80794a2433455
+CT = 2bf7d09079bc0b904c711a0b0e4a70ca8ea892d9566f03f8b77a140819f39ef045103e785e1df8c2
+
+Count = 2
+Adata = 00
+Payload = b99de8168e8c13ea4aef66bdb93133dff5d57e9837ff6ccb
+CT = dab54ba67bec7bad10eb5141ce3344a4c9d5ebd5c3d35b664b01098842a618390619b86e00850b2e
+
+Count = 3
+Adata = 00
+Payload = 09fc21ac4a1f43de29621cacf3ad84e055c6b220721af7ce
+CT = 6ad4821cbf7f2b9973662b5084aff39b69c6276d8636c0638bd518724ab84fb814fe7b5570769f7f
+
+Count = 4
+Adata = 00
+Payload = cb43320d7488dfd6eed9efd88f440ea3f6f77a0df09d0727
+CT = a86b91bd81e8b791b4ddd824f84679d8caf7ef4004b1308a7229cbcecef221570cee8345b38cd6ec
+
+Count = 5
+Adata = 00
+Payload = a350ed58c04473e113b9088b1fb9dad92807f6b63b0d690c
+CT = c0784ee835241ba649bd3f7768bbada2140763fbcf215ea1fee47fec27d7764e5e2819c850088bac
+
+Count = 6
+Adata = 00
+Payload = 0709e691faf41383fab5d1848a8eee77101d1c99e526a264
+CT = 642145210f947bc4a0b1e678fd8c990c2c1d89d4110a95c954d610bc1ab4bc9a8a28c7306f7c539e
+
+Count = 7
+Adata = 00
+Payload = e7b913c2f0630562eb1c16b3b1ed84090c011a15c09e5471
+CT = 8491b07205036d25b118214fc6eff37230018f5834b263dc2e31657ecc51f5ec8590482fc053230d
+
+Count = 8
+Adata = 00
+Payload = 6b909697074900d41ce8c7d559b229af11fb3cec334784d4
+CT = 08b83527f229689346ecf0292eb05ed42dfba9a1c76bb379d500827f2081b00397102f90fc9ccd88
+
+Count = 9
+Adata = 00
+Payload = 495ff03335bcb39a317b9ea3f8bb6306fa771f3c55adebce
+CT = 2a775383c0dcdbdd6b7fa95f8fb9147dc6778a71a181dc63e2e7997803029476598c0e8d4fc63857
+
+[Alen = 1]
+
+Key = 08b0da255d2083808a1b4d367090bacc
+Nonce = 777828b13679a9e2ca89568233
+
+Count = 10
+Adata = dd
+Payload = 1b156d7e2bf7c9a25ad91cff7b0b02161cb78ff9162286b0
+CT = e8b80af4960d5417c15726406e345c5c46831192b03432eed16b6282283e16602331bcca9d51ce76
+
+Count = 11
+Adata = c5
+Payload = 032fee9dbffccc751e6a1ee6d07bb218b3a7ec6bf5740ead
+CT = f0828917020651c085e42459c544ec52e99372005362baf308ebeed45f67ef8733737c9c6f82daad
+
+Count = 12
+Adata = 68
+Payload = 9c4cd65b92070bc382fd18146611defb4204acddfdf6b276
+CT = 6fe1b1d12ffd9676197322ab732e80b1183032b65be00628f9b477e3a23bfdfdb619c7bc531fbcce
+
+Count = 13
+Adata = be
+Payload = 2ff93ef2fc5fe2c297ace05f3f7585aed75ef90ade3acf89
+CT = dc54597841a57f770c22dae02a4adbe48d6a6761782c7bd7aa82130f5a86c0cd0433585e5c208cf7
+
+Count = 14
+Adata = 7a
+Payload = 62766e9acd41285eeed9b4007340dbb611699624274ad117
+CT = 91db091070bbb5eb75578ebf667f85fc4b5d084f815c65499d60012a2f25463e036ceecea57b3c97
+
+Count = 15
+Adata = 13
+Payload = ea689c268a04912d0527b16d9d9406df38302fb11cb64a99
+CT = 19c5fbac37fe0c989ea98bd288ab58956204b1dabaa0fec7e337897c90eb260729a729aed1c8a244
+
+Count = 16
+Adata = e5
+Payload = f31e35953beb211efcce487ba8c0cd1a8446343d5851b9fd
+CT = 00b3521f8611bcab674072c4bdff9350de72aa56fe470da373dc2911c75b37cd995481d42b04524a
+
+Count = 17
+Adata = e3
+Payload = c4ac3c645387584c2a95b1f16b8317730592924dd831a388
+CT = 37015beeee7dc5f9b11b8b4e7ebc49395fa60c267e2717d684f76ecf3dc5f3307ce982f185321248
+
+Count = 18
+Adata = d5
+Payload = 81af394c2ea3a85e1ea954596e3772f01635d007794c0b19
+CT = 72025ec6935935eb85276ee67b082cba4c014e6cdf5abf472c38d0fe4e4eba054c1420c39a3dcc61
+
+Count = 19
+Adata = ed
+Payload = e013a2edd5b86bab8df5c9940d0a0c864478c1ad42668304
+CT = 13bec5676842f61e167bf32b183552cc1e4c5fc6e470375a7cfa6c9945f5aee3c799eee37b0605db
+
+[Alen = 2]
+
+Key = 1538cc03b60880bf3e7d388e29f27739
+Nonce = 9e734de325026b5d7128193973
+
+Count = 20
+Adata = c93c
+Payload = e7b819a853ffe79baaa72097ff0d04f02640ae62bcfd3da5
+CT = 1d8f42f9730424fa27240bd6277f4882604f440324b11b003ca01d874439b4e1f79a26d8c6dc433a
+
+Count = 21
+Adata = 4cf9
+Payload = dc6cf325ed6d968efba9f57e48a58f4578cc3540fe121ba2
+CT = 265ba874cd9655ef762ade3f90d7c3373ec3df21665e3d07b40653cd23afc7cc7a31fa13ba8f4e49
+
+Count = 22
+Adata = b469
+Payload = 22ab6a0daf953165dda864cceeeb782e275c0b072aedd284
+CT = d89c315c8f6ef204502b4f8d3699345c6153e166b2a1f421c8c10aaf90b1116be216f912c82ca96a
+
+Count = 23
+Adata = cf6b
+Payload = a35f62a431fee63468dc02fdf7bef78d3a5937de56151939
+CT = 596839f511052555e55f29bc2fccbbff7c56ddbfce593f9c2f568ef41324189fb3644edcd76dc19c
+
+Count = 24
+Adata = af7c
+Payload = 548840cb0400824af809fb68447500b77e977128200d3b81
+CT = aebf1b9a24fb412b758ad0299c074cc538989b49b8411d242548c244a875d3681d715db3da19962f
+
+Count = 25
+Adata = 61dc
+Payload = 440b6095c77495e73fff54c785b7ceb5eb358731c213ffcd
+CT = be3c3bc4e78f5686b27c7f865dc582c7ad3a6d505a5fd968b599bc8927ad8d43067807f4b858f854
+
+Count = 26
+Adata = b97e
+Payload = 50c59ca54eb64575b82b13c6dac96488af369e9f5f86cdf2
+CT = aaf2c7f46e4d861435a8388702bb28fae93974fec7caeb577454774ee78f76e555cf743df340381e
+
+Count = 27
+Adata = 57ab
+Payload = 21b8eb1f0bda26ca36167ce7bc2e796818bf11fc8c192885
+CT = db8fb04e2b21e5abbb9557a6645c351a5eb0fb9d14550e20e0a22a5ee031978271c7dd2a0d4e7018
+
+Count = 28
+Adata = 5f9c
+Payload = b4d84fb1e81e18c89391a7a59fc05fedaf160e0d0d027a7c
+CT = 4eef14e0c8e5dba91e128ce447b2139fe919e46c954e5cd99a242ebae5c6da57ee38e5c227c46b32
+
+Count = 29
+Adata = e0c4
+Payload = 54dc5a0e1b67577cda4e7dbd48b769c120c1d13dd567cfad
+CT = aeeb015f3b9c941d57cd56fc90c525b366ce3b5c4d2be908a5f8a92f4201c4658289307167cee810
+
+[Alen = 3]
+
+Key = f149e41d848f59276cfddd743bafa9a9
+Nonce = 14b756d66fc51134e203d1c6f9
+
+Count = 30
+Adata = f5827e
+Payload = 9759e6f21f5a588010f57e6d6eae178d8b20ab59cda66f42
+CT = f634bf00f1f9f1f93f41049d7f3797b05e805f0b14850f4e78e2a23411147a6187da6818506232ee
+
+Count = 31
+Adata = e9699b
+Payload = 1555bc87d6c688fd221a2c75cd1e4dd1c1693207ac421d24
+CT = 7438e575386521840dae5685dc87cdec14c9c65575617d28f10835db9897b7528e3204fe3a81424f
+
+Count = 32
+Adata = 972896
+Payload = b72b2a080d92f3f3bb7d96222982de82a28c9eebaddba247
+CT = d64673fae3315a8a94c9ecd2381b5ebf772c6ab974f8c24b3efa05ba4a73ec2234461d459f54acd2
+
+Count = 33
+Adata = 3053f3
+Payload = b5417ed6933ffe2b57ea601d77e97eb12fa1fb8fdc06c86f
+CT = d42c27247d9c5752785e1aed6670fe8cfa010fdd0525a863b557537c6525e827750917a1ed49602f
+
+Count = 34
+Adata = 24db75
+Payload = 4e7f42666035a00e62783283c54b027603917685d27326bc
+CT = 2f121b948e9609774dcc4873d4d2824bd63182d70b5046b0dfd06b037e9094f120eb3d8649d48918
+
+Count = 35
+Adata = ff27a4
+Payload = 7bf180699c294421ad9565cacc27227a4b3a7cf9637290c6
+CT = 1a9cd99b728aed5882211f3addbea2479e9a88abba51f0cabfa8cfabbd79b3e3210482e6f3822fee
+
+Count = 36
+Adata = 77ec24
+Payload = 3d47071c13f994cb42fb2887e5c6e53a542be7ddad9779e0
+CT = 5c2a5eeefd5a3db26d4f5277f45f6507818b138f74b419ec3b9575e347051e98d0c8646ad46318e6
+
+Count = 37
+Adata = 6d7748
+Payload = 317d5da0a2ec12c3b96c83dd61cc955242a9c1c640e2b92f
+CT = 501004524c4fbbba96d8f92d7055156f9709359499c1d92378e7af65eb0388ae7a52f58f6ba32109
+
+Count = 38
+Adata = 029674
+Payload = c9bb21306ee1b4a6c4fa5443af2e181716993cbb374e177c
+CT = a8d678c280421ddfeb4e2eb3beb7982ac339c8e9ee6d77708019fa97ff70d4d21c0bd83caa434b3a
+
+Count = 39
+Adata = 60dfe8
+Payload = 44eb7edd6bee501ad97873aa7ecbf7ed8b613760d7c95e15
+CT = 2586272f854df963f6cc095a6f5277d05ec1c3320eea3e191814ed48a21d97ea02e86d7e6e8834cb
+
+[Alen = 4]
+
+Key = 9a57a22c7f26feff8ca6cceff214e4c2
+Nonce = 88f30fd2b04fb8ddbce8fc26e6
+
+Count = 40
+Adata = a95bdff6
+Payload = 035c516776c706a7dd5f181fa6aa891b04dd423042ea0667
+CT = b92f7ec2ebecebdbd2977b3874e61bf496a382153b2529fc9b6443a35f329b2068916fb6ab8227eb
+
+Count = 41
+Adata = d2672cbb
+Payload = 3ba306bcec94615c347f990b62841a16df7b321f113f1714
+CT = 81d0291971bf8c203bb7fa2cb0c888f94d05f23a68f0388f19e2aa492ce9ddfb6de0ab7a447f5351
+
+Count = 42
+Adata = 737f4d00
+Payload = 68313a29ace3efe521c3ca1e5bac8e98d6b4434c80a7dc74
+CT = d242158c31c802992e0ba93989e01c7744ca8369f968f3ef2bf683b1209f104e82ba39f7c62cd666
+
+Count = 43
+Adata = 3610b1ae
+Payload = 963bfe556138317bebe3936b18a2c1dd100dc73be6fde556
+CT = 2c48d1f0fc13dc07e42bf04ccaee53328273071e9f32cacd4fc7d5cac043f182edbe5c2658f73092
+
+Count = 44
+Adata = f1aa7f72
+Payload = 52d5c53ee4f23cb050a95db54112b44033c34ac31de96be8
+CT = e8a6ea9b79d9d1cc5f613e92935e26afa1bd8ae664264473b8234f3fbaca3dc2c497418219151b05
+
+Count = 45
+Adata = 6b1013aa
+Payload = a302aebc0f8fd61badc8371991beacf5933de46effacb8ce
+CT = 1971811992a43b67a200543e43f23e1a0143244b866397558fa5f9539e0500f139016e4a4337d86b
+
+Count = 46
+Adata = 33028129
+Payload = f7d653c23254875625b20e1ef60ae92847046d84bb4ce857
+CT = 4da57c67af7f6a2a2a7a6d3924467bc7d57aada1c283c7ccfa2379fde155e64b5b84e336056445c3
+
+Count = 47
+Adata = 2cab4a09
+Payload = 872a3f7230e626abff519e5aeecc93897249405daeaffc98
+CT = 3d5910d7adcdcbd7f099fd7d3c800166e0378078d760d30358208335cb81e4fb10923fca4ddb9ff9
+
+Count = 48
+Adata = 73142ba7
+Payload = 766f94e7d9b1ce74bbaf2c99d215350f060122767fc1953f
+CT = cc1cbb42449a2308b4674fbe0059a7e0947fe253060ebaa42d6ecfb49ac8983415503efef1e21950
+
+Count = 49
+Adata = bc9f967e
+Payload = 5f089ed9267363bc23c6c7b8f73208a36f61fa8ea8084ff7
+CT = e57bb17cbb588ec02c0ea49f257e9a4cfd1f3aabd1c7606c1978a62d15430fc20b87940292b49641
+
+[Alen = 5]
+
+Key = 54caf96ef6d448734700aadab50faf7a
+Nonce = a3803e752ae849c910d8da36af
+
+Count = 50
+Adata = 5f476348dd
+Payload = c69f7c5a50f3e72123371bbfd6bdf532b99ef78500508dfe
+CT = 20c43ad83610880249f1632dd418ec9a5ed333b50e996d1a4e5a32fbe7961b832b722bc07a18595b
+
+Count = 51
+Adata = 07db8aada5
+Payload = 9cf8b638f2b295b85cf782fabab11153dc091b4afcd761a9
+CT = 7aa3f0ba9451fa9b3631fa68b81408fb3b44df7af21e814d401a2222443696021b5faa520129b563
+
+Count = 52
+Adata = 31ef6561ff
+Payload = 62b8263dc015ef873cd16272e4da89799b910f2b04204420
+CT = 84e360bfa6f680a456171ae0e67f90d17cdccb1b0ae9a4c4f842681d2e90da5718234ed893197662
+
+Count = 53
+Adata = e97dfcbafb
+Payload = 810bed3a2bc0f9d75389155b7a39d9d014c08646814f9718
+CT = 6750abb84d2396f4394f6dc9789cc078f38d42768f8677fc33a08eb30ee154f71279682ab02eff27
+
+Count = 54
+Adata = 4981c51fcc
+Payload = 063d23fc3ec344c1ba3486802e01e55617455d5cfbfb5279
+CT = e066657e58202be2d0f2fe122ca4fcfef008996cf532b29d8d3071c79f0cf86fe4148cb5e8ace0ce
+
+Count = 55
+Adata = c8437dba76
+Payload = 41db5b245ea0fab985b93e7fc0a00cd3cca5bdbb642b7ebf
+CT = a7801da63843959aef7f46edc205157b2be8798b6ae29e5b842700619dc1599603f3f3f6cfdf5e0b
+
+Count = 56
+Adata = 6f65a24344
+Payload = b0e36734b2ba871d59df0b029c7f32af68e003a689ac4911
+CT = 56b821b6d459e83e331973909eda2b078fadc7968765a9f539a0cd8d8bbf211b907f34411f868c79
+
+Count = 57
+Adata = cd62d6d203
+Payload = 747e53e627eabde0cd77d78d1bd720bea518f8a2f76e57a2
+CT = 922515644109d2c3a7b1af1f1972391642553c92f9a7b746c4a90e5fc11266bab77eea1d24fbdbb9
+
+Count = 58
+Adata = 9663b3c8e6
+Payload = c70c92ec4c518802662fa4c41a6a33a22599f79f8f7264b3
+CT = 2157d46e2ab2e7210ce9dc5618cf2a0ac2d433af81bb8457b3c1246f7dd6462ce757db82db45f36e
+
+Count = 59
+Adata = 35c4720d3c
+Payload = a26835605b66fc08abdbb5dc77e39783d60b8e8f2314e95f
+CT = 443373e23d85932bc11dcd4e75468e2b31464abf2ddd09bbd472c06a5f4c04f97d06ec401d3e7fd9
+
+[Alen = 6]
+
+Key = cc0c084d7de011e2f031616a302e7a31
+Nonce = f0b4522847f6f8336fe534a4e7
+
+Count = 60
+Adata = da853a27aee2
+Payload = 15b369889699b6de1fa3ee73e5fe19814e46f129074c965b
+CT = f39755d160a64611368a8eccf6fcbc45ef7f1f56240eb19a2e3ca4ec3c776ab58843f617d605fd72
+
+Count = 61
+Adata = d4ed4584678e
+Payload = a18c0460b56a5bcd5bf6842cec6ed44d90b2bfa968a6a7e7
+CT = 47a838394355ab0272dfe493ff6c7189318b51d64be48026327804c44c8f17a4446a3d5ba85f9c7f
+
+Count = 62
+Adata = 590a27721a36
+Payload = 41cee0ecaf9c65cef740440af37954ef49a585779d2abbca
+CT = a7eadcb559a39501de6924b5e07bf12be89c6b08be689c0bbcd00e9cb726d75e4283820ee81d933a
+
+Count = 63
+Adata = 58830fb0b1f3
+Payload = dce983e4e3734a9bd8848dba0d744d07bbeba602f4006025
+CT = 3acdbfbd154cba54f1aded051e76e8c31ad2487dd74247e4d5d71a1f0f1b6518c35f0632a30931fd
+
+Count = 64
+Adata = eedd0d767a25
+Payload = 4653b3e879ab18b65c5c3706a5139698262cb830a22d943b
+CT = a0778fb18f94e879757557b9b611335c8715564f816fb3fa3ad112899e9ba442660eb5dfe33b2f96
+
+Count = 65
+Adata = 618bcf2e3e79
+Payload = 8586383281925363ac15fb19c26d64c639c75920c792dc2c
+CT = 63a2046b77ada3ac853c9ba6d16fc10298feb75fe4d0fbed54fba446028919342b2fe86ee67efcc7
+
+Count = 66
+Adata = 549c9b84c7f7
+Payload = 95c25ae4445cd8c4d267df82687484667e309992fcf1e737
+CT = 73e666bdb263280bfb4ebf3d7b7621a2df0977eddfb3c0f69fc23013142f62881ccfa3037067e1ef
+
+Count = 67
+Adata = 92d7fa6a8135
+Payload = e58034bbb0e6f5e724e32ee56896dadae25c2a3efb8c6f2f
+CT = 03a408e246d905280dca4e5a7b947f1e4365c441d8ce48ee8263568d56fae8bf35b2f2cdecbffe0a
+
+Count = 68
+Adata = f43e126c0f83
+Payload = d98f0dddfe9cb3cae1336970d5efb55316a65e2c51e316f4
+CT = 3fab318408a34305c81a09cfc6ed1097b79fb05372a13135de2c2fbfdddc7dd6672714af174c5121
+
+Count = 69
+Adata = f02074812dde
+Payload = 548747b1669c6383b793054d93957f9e99d605761c6c23b5
+CT = b2a37be890a3934c9eba65f28097da5a38efeb093f2e04743704560ff23ce0000fba8812c45940ad
+
+[Alen = 7]
+
+Key = d7572ed0e37261efa02f8c83e695efdc
+Nonce = f4f96d7b4384a3930b3d830f82
+
+Count = 70
+Adata = 922340ec94861f
+Payload = 1edef80c57d17f969f8bde10ab38a1a8811a124de72c526e
+CT = de14558cc686e1836f1f121ea1b941a9ebd4f0fb916dc870fd541b988a801cb5751c7faaf5b0c164
+
+Count = 71
+Adata = 4eb379f21b1531
+Payload = ddd5282a207c1dcb03c1c3bbc9eb12a7bd28534118db2735
+CT = 1d1f85aab12b83def3550fb5c36af2a6d7e6b1f76e9abd2bc068bd1b1c309dfbd52d9a24be07c630
+
+Count = 72
+Adata = 7fa89e9d6e3fec
+Payload = c5b7c462eb166f48bb59c8102ee7b3dc67a28e5de7570c51
+CT = 057d69e27a41f15d4bcd041e246653dd0d6c6ceb9116964f2d114d6ab082738d05d60acca8e8ccfb
+
+Count = 73
+Adata = fda8665f87c618
+Payload = af793815e147e3180f5146aa6a582e343dc479f26b4226b2
+CT = 6fb3959570107d0dffc58aa460d9ce35570a9b441d03bcac1cc84bd77fe00e1a13433f2c10e3b799
+
+Count = 74
+Adata = 46bde207491ebd
+Payload = 47c76a0bbd5b1616b278089d41a050c509c7a1c280574bf7
+CT = 870dc78b2c0c880342ecc4934b21b0c463094374f616d1e9990c81f1bae32c953bf02ddbde047632
+
+Count = 75
+Adata = a799f5f895fd7a
+Payload = d554806ffc3900a0952a3c094c745808950697a6e5d62c1d
+CT = 159e2def6d6e9eb565bef00746f5b809ffc875109397b6031af19f1f080dd1dd2da799059755e49f
+
+Count = 76
+Adata = 20225831a9ee06
+Payload = ba45e1859efae362a44a0116a14e488ba369da6c76c3913b
+CT = 7a8f4c050fad7d7754decd18abcfa88ac9a738da00820b2523d3b9a0060834ac4860dae0eac570ef
+
+Count = 77
+Adata = 785360916464eb
+Payload = 57bc338946ff78cf76adf5021e2e44e34e687fb68ad703f3
+CT = 97769e09d7a8e6da8639390c14afa4e224a69d00fc9699edff96e7cf841a66c50bbb6fb2bac7ef51
+
+Count = 78
+Adata = 57b946369226db
+Payload = 9ac5be9929c4fe5a9992749a38dc69874866db3d4747da97
+CT = 5a0f1319b893604f6906b894325d898622a8398b3106408986e1c33a45f9d52755c374650635bef6
+
+Count = 79
+Adata = 73e4da8973c1e3
+Payload = 5a05410aa3a71f5f1a253b8576eba269c06a4c30591144cc
+CT = 9acfec8a32f0814aeab1f78b7c6a4268aaa4ae862f50ded2d78592c2d89c15edc5bb7486aa93f896
+
+[Alen = 8]
+
+Key = 98a42d7a0c5917deaf3b4de3f0cbe0a1
+Nonce = 03d33ab0c2df7bfce88b5ee4c4
+
+Count = 80
+Adata = 2d5438b728b950d9
+Payload = 9aa9c8358117564371366beeec923051ef433252197aaad5
+CT = 9ff942baa60f440c17a78e9581216b9a947a67f04d54911feecfff971fdfaa856310b014aa59c978
+
+Count = 81
+Adata = 6e430b497a16e7f5
+Payload = 5758a500978c71a9b90f6e5beae9d96ef05a41486b10ea2e
+CT = 52082f8fb09463e6df9e8b20875a82a58b6314ea3f3ed1e46a4d7b4b4df6c831ee32116ee4dad98c
+
+Count = 82
+Adata = e12f98507d6514c3
+Payload = 49efe18c76a8355127d914a3a830c1c6ff2a163d728526e1
+CT = 4cbf6b0351b0271e4148f1d8c5839a0d8413439f26ab1d2b3243fc75cd1624e152f451678edcac87
+
+Count = 83
+Adata = eecf8d641ee0bee9
+Payload = 49ae2309fbe6ce4e9421516b8f79ae64b1316cb849eaf638
+CT = 4cfea986dcfedc01f2b0b410e2caf5afca08391a1dc4cdf2dd6d8ca57da1880e1baff43736b3da34
+
+Count = 84
+Adata = 9066367c784de0a4
+Payload = b1bda5fa4242aa6aad0f5a5b1d31d86b8d4a97588b3e315d
+CT = b4ed2f75655ab825cb9ebf20708283a0f673c2fadf100a97f05439a661001513a96b896de46b7081
+
+Count = 85
+Adata = edf848b2510f7803
+Payload = eaa8608f6763d968576a7e89056b9828a1686c8441b06377
+CT = eff8ea00407bcb2731fb9bf268d8c3e3da513926159e58bdcf20709b2dc2ff9946094190b5ea09d1
+
+Count = 86
+Adata = 0f49cae81c8628d2
+Payload = f32029cf51609f0df9832ad1b283ea94a5356f70112c1328
+CT = f670a34076788d429f12cfaadf30b15fde0c3ad2450228e2a5bb6b4f87b9b198665203e4fdf9e7f7
+
+Count = 87
+Adata = b0c47e9cce46a276
+Payload = 7a550ef9254a8da6e4fee290a76ea838ffb61d3533d4d31f
+CT = 7f05847602529fe9826f07ebcaddf3f3848f489767fae8d529f416f89f1a34bbbf2ce40d943c6d8b
+
+Count = 88
+Adata = a6fe7c9ce2d49f85
+Payload = e67c486dd7ba9a9061844b9354f55890321ae626efaa28cc
+CT = e32cc2e2f0a288df0715aee83946035b4923b384bb8413067eb95550b91b955d5c2d72d5c189b704
+
+Count = 89
+Adata = eb1d11cc4876f58f
+Payload = 35f2c810091e930a52e4a3f28c9c8184967f1554c2675eb5
+CT = 30a2429f2e06814534754689e12fda4fed4640f69649657f0e8e8a5a7e0ea6860bab4a4320f03ae5
+
+[Alen = 9]
+
+Key = 2a68e3fe746f593c1b97cb637079c3e5
+Nonce = cd62d0f27b7f4864dc7c343acd
+
+Count = 90
+Adata = abe4f1d3812bfe3ccf
+Payload = 13b4a874888db0e5d8fd814b5e7e04f7fdfbc1601ccc02bc
+CT = 032835a3dbf688d09cf2a32a92b101959d33ff47500f92f4fd49840440f866d1a22b0854996111d8
+
+Count = 91
+Adata = 2e21f466814d3d6340
+Payload = 08b5c773364cded74d7b308984313c17ff90eed496a27a2b
+CT = 18295aa46537e6e2097412e848fe39759f58d0f3da61ea63de2f5c335df537fbbc6ae59cd562732f
+
+Count = 92
+Adata = dba22aabcea0e694fc
+Payload = bbac1790abb7aafe272ec472c897e6363e335b3c4126c762
+CT = ab308a47f8cc92cb6321e6130458e3545efb651b0de5572acc5ed6e4a907ff4742ab6c835a427f92
+
+Count = 93
+Adata = 97e9d16bd757395ec1
+Payload = 7249612dc09809bbca9dd311e720f7da2cb54ce33e3eb9c3
+CT = 62d5fcfa93e3318e8e92f1702beff2b84c7d72c472fd298b1714b5a3df454f3bc35869da75adc882
+
+Count = 94
+Adata = 866cf710470cac74d3
+Payload = 060ae0ab9857324a3b2ac79f3b6e6f90f5de884ce9c7b930
+CT = 16967d7ccb2c0a7f7f25e5fef7a16af29516b66ba5042978aa33dffe2596832f98a9c8413bd898b9
+
+Count = 95
+Adata = 2dd7a7f832b29ccce2
+Payload = f77a9fd5363836deefd34e1bea0882484a7ab746b4495d59
+CT = e7e6020265430eebabdc6c7a26c7872a2ab28961f88acd11dd5049f7c53d6a7fe5d7f959689ee960
+
+Count = 96
+Adata = 502349a60e897356b5
+Payload = 96118dbfe53434d8aed88769a535eb0c8b5849dca1c81c34
+CT = 868d1068b64f0cedead7a50869faee6eeb9077fbed0b8c7ced9c3a0d0de8788471c5f6c2f9638b7c
+
+Count = 97
+Adata = debed45c9acf129268
+Payload = df5a47d3eb5c0b6cabb6711a45400602d205b82ecae9e849
+CT = cfc6da04b8273359efb9537b898f0360b2cd8609862a7801d49b4b9bead1b7de2021cff280d6f93b
+
+Count = 98
+Adata = 2726702dd62a6e5344
+Payload = 5a7649cb001fbb6f653cbca17756c5c1a078c2e240d92085
+CT = 4aead41c5364835a21339ec0bb99c0a3c0b0fcc50c1ab0cd69df31aba209d87ee22bd6a1dcadb168
+
+Count = 99
+Adata = e8006cfb0536696ac7
+Payload = 95186d41f927cdbef42157f21d966e88061b6558b5ec932f
+CT = 8584f096aa5cf58bb02e7593d1596bea66d35b7ff92f03677cc5b60c881fe834a789d28447d8fb54
+
+[Alen = 10]
+
+Key = 46b067cf9b1a28cf187002e90b14e130
+Nonce = bad8c03292bf01cfd8d34f860c
+
+Count = 100
+Adata = 8d65880eddb9fd96d276
+Payload = cc0915194218d4536e467433cd6d79ff1d9eb9ff160ab684
+CT = bd56edc015692c6ab9bec493a9893863598414a3d11a6a0f27ecdcb257d0d30491e5bf1aa8f90958
+
+Count = 101
+Adata = 8a65cde13149d9d54a5b
+Payload = 28257133b1d8b0b2be4faecd6e819ac783707a5c5f50c302
+CT = 597a89eae6a9488b69b71e6d0a65db5bc76ad70098401f89b10f9fc201e4128696dcd899dd2e24ea
+
+Count = 102
+Adata = e999ec3e1bfb25b5877c
+Payload = 96ab0cfc204bafc4f5851d6c682d631d0c5ad03ac925a943
+CT = e7f4f425773a57fd227dadcc0cc9228148407d660e3575c8c522e5ba5adbc6a639cbd06f103ebc9e
+
+Count = 103
+Adata = a8554441e073d6065dce
+Payload = 50925853a84a33ff392154e4e737efc18dcfc98f4d5235a9
+CT = 21cda08aff3bcbc6eed9e44483d3ae5dc9d564d38a42e922e1a4e0f7ebc3cff3915d27971cce7e91
+
+Count = 104
+Adata = 838f0be8d04d28d77549
+Payload = d0700658d5f4010ff21091f3d119c99645e339198029c3a9
+CT = a12ffe818285f93625e82153b5fd880a01f9944547391f22c215c88d80bffc881aff10ba40f11976
+
+Count = 105
+Adata = 20f014d928d5b25fbaf4
+Payload = 4bdf28748a0c281dd49c7294ae8e55fe7a52d45ff6384db3
+CT = 3a80d0addd7dd0240364c234ca6a14623e487903312891382cc9391bc06aa6ca9d486a4e2a218c54
+
+Count = 106
+Adata = 56c026b8a71974ff7ecd
+Payload = f75db057f0276fff85014f54ecdec8f90b96a2a982db14cb
+CT = 8602488ea75697c652f9fff4883a89654f8c0ff545cbc840778b05c6c582a0bb7d1d9dcf6a46b9f6
+
+Count = 107
+Adata = 75c3b9e52648a4f9aca9
+Payload = c15c554169dbb9b08494afaa44819a10dc9ddad54199ab54
+CT = b003ad983eaa4189536c1f0a2065db8c98877789868977dff47d9ebbd3cff14623b10cecc94b53d6
+
+Count = 108
+Adata = 1c76c3014a14b7fa1ca8
+Payload = 19eef6f798fc68086aad1cda6d7976cdcfe6b8af74598032
+CT = 68b10e2ecf8d9031bd55ac7a099d37518bfc15f3b3495cb9d2b74b84dc170c00dce85b56e346a976
+
+Count = 109
+Adata = a4eb60d4eb7ead1bd0e6
+Payload = e06e5dba5ac35cfd07949e5cc12ad70507d4a86a952ecca3
+CT = 9131a5630db2a4c4d06c2efca5ce969943ce0536523e1028d92e19fd8b5c1fcbff36adaa5e47ae84
+
+[Alen = 11]
+
+Key = e94dac9c90984790a7c0c867536615ff
+Nonce = c19f06f91e645d4199365f18c0
+
+Count = 110
+Adata = 537038b5357e358a930bd6
+Payload = 4d64461c55eb16bf7b9120f22be349598f2f394da8460dc6
+CT = e9fc5004c2359724e1e4411ae6f834ef6bea046d549753c88790c1648f461a31c84e62ea8592a074
+
+Count = 111
+Adata = 7e3d7b3eada988668f3784
+Payload = eab7d5dbd91d4cbbac8d79fadd70b5dcb3baadac5cb713a3
+CT = 4e2fc3c34ec3cd2036f81812106bc86a577f908ca0664dadacb1d1c9231d2c22ecfeed622792dfd0
+
+Count = 112
+Adata = 78b107b29c4878ff18f749
+Payload = 3c6ae2e2578875a1f5611582528e058aece2ddc33a4dde3d
+CT = 98f2f4fac056f43a6f14746a9f95783c0827e0e3c69c8033fffe60299768f048e7098033cde046b0
+
+Count = 113
+Adata = d293908bb516c5f3a411b9
+Payload = d7a46e726ed43f1580eb52141a93390982cc809dc833e3f0
+CT = 733c786af90abe8e1a9e33fcd78844bf6609bdbd34e2bdfe4ee6ebc0d90a0de05b428495c93e1801
+
+Count = 114
+Adata = 33ef208faad4d2948c9e67
+Payload = b1fe5d9d34157193fc0608cd8ecb872e17720f5f6814a466
+CT = 15664b85a3cbf0086673692543d0fa98f3b7327f94c5fa687e7e64cc0fcd6a92c79ceb6ce2abd8ee
+
+Count = 115
+Adata = b7f7ed9ccac3c2b4fbfee0
+Payload = de6bb539fb7a9c87414f62a7cf25a4cfca176509e991af41
+CT = 7af3a3216ca41d1cdb3a034f023ed9792ed258291540f14fb02b53bc779e0976b634b0d1b88fc0a9
+
+Count = 116
+Adata = a6e287383927f76e4927af
+Payload = 8719d20c20c8959068b8adcd65e6f6bc7b3693828f0735a0
+CT = 2381c414b716140bf2cdcc25a8fd8b0a9ff3aea273d66bae3c37fa936243b393f07fcccb0fc13e41
+
+Count = 117
+Adata = 70828be6dd93954f4e7b6b
+Payload = 30b39426831f61c8ba5f2ef5b71f0c4b2f916e3b5a578110
+CT = 942b823e14c1e053202a4f1d7a0471fdcb54531ba686df1e0d7534a489e6d242966ebea4455f8f79
+
+Count = 118
+Adata = 506015fc2831df293f4da0
+Payload = 818d5d810f678629f078723f5c6c3657271077533bfb7c29
+CT = 25154b9998b907b26a0d13d791774be1c3d54a73c72a2227ccbf64f04e95b180d09e843847d22104
+
+Count = 119
+Adata = e9394b0245b379e68e3dea
+Payload = f0613205a7a0822849df9e8a3cf6caf281f3adfa966c5507
+CT = 54f9241d307e03b3d3aaff62f1edb744653690da6abd0b0927b546ef8cd717073832584fb25a0645
+
+[Alen = 12]
+
+Key = f6bb5d59b0fa9de0828b115303bf94aa
+Nonce = 05358f33e1fc6a53ab5a5c98ce
+
+Count = 120
+Adata = 040b25771239cc2a39446e3c
+Payload = 011fc50329bfd63a85ebd4f7693363602f1a4147371270b7
+CT = 4432d7eb42980734d34f19c50cf8abf71ac1b19ed75a727854e5d050a405f755047d09cb0f49546a
+
+Count = 121
+Adata = 50a1d37fa2f3462bd304631b
+Payload = c90e40540d372ab1eb00ea5d5b8de5bf7c94ce4e376d6949
+CT = 8c2352bc6610fbbfbda4276f3e462d28494f3e97d7256b862abee8547ee3f24cfa677468ecc1d121
+
+Count = 122
+Adata = ac3bb872a41df35e415d2b0c
+Payload = 9e7be78c0ab9e6a4c6c257e77c63681bea35d951f168b0c5
+CT = db56f564619e37aa90669ad519a8a08cdfee29881120b20a61cef865ce4080e7c7abfc43f62c03a3
+
+Count = 123
+Adata = e3106ae6456153dd922640a1
+Payload = 00df0c5a5d3eceb2bd293066529799544f846672a9a1d31b
+CT = 45f21eb236191fbceb8dfd54375c51c37a5f96ab49e9d1d4e1d19c321a1e0852adba939b447220ab
+
+Count = 124
+Adata = 297b4498bf5427e6341aa927
+Payload = 14967a0476dbaea03b07fa8d40d344eabaf479be2443243a
+CT = 51bb68ec1dfc7fae6da337bf25188c7d8f2f8967c40b26f579ea5fb65018abdcde1a39f6859ecb56
+
+Count = 125
+Adata = 5de60dc0e3b5bda0b33a9520
+Payload = 2da3716d76d10b6766a1f9cbf9f420316fd5f396e7b9a2ba
+CT = 688e63851df6da69300534f99c3fe8a65a0e034f07f1a075c2629ff871ee15745fd8c1ddbdae4c29
+
+Count = 126
+Adata = 1c9b8541943ad50b4243c179
+Payload = 8c1b3ba18d1f5cff74a457aadd6b3e7d093d06ad2622e6a0
+CT = c9362949e6388df122009a98b8a0f6ea3ce6f674c66ae46f04e198ad16ad1106d3ba6172f4a13a8f
+
+Count = 127
+Adata = 51e926d2542ac8faef61465a
+Payload = 88936e97db070c0ec2aa58d1c6f5b34df3d32ddf7db34a8b
+CT = cdbe7c7fb020dd00940e95e3a33e7bdac608dd069dfb484475981131e3934ec6d41e00d502729799
+
+Count = 128
+Adata = ebefbac97b363e6f32526aac
+Payload = c20742e4b410c5b661da373a905fb0ed55b20e0e879eff5c
+CT = 872a500cdf3714b8377efa08f594787a6069fed767d6fd93e2c005b5bebe07ff578b1b4bc51971cd
+
+Count = 129
+Adata = 1ef059ac7d648e9e32d9b1f2
+Payload = 65c55ca21a89a8325365bf2be861d700559de2eabb41b37f
+CT = 20e84e4a71ae793c05c172198daa1f97604612335b09b1b021a25f15b5b4229a872a9199972c85b3
+
+[Alen = 13]
+
+Key = d1da2e961e78063af8de41865b226873
+Nonce = 03739f5474857006340cce554d
+
+Count = 130
+Adata = e3afd091d2b588465872a6300f
+Payload = 8e5fa1a6662a8378cda15697e926841594f2f394fa5a34ab
+CT = ca0d95e3ff186ad6b88d45fc4079e6b7b4a615e7e8dd5f4742d522cc9dc19c47a4fa0b1528069cf8
+
+Count = 131
+Adata = ce3186bb737753b59ee76b748c
+Payload = 311ebc5ff2f625944562ea699b2690df3e6e64a17c62bd3a
+CT = 754c881a6bc4cc3a304ef9023279f27d1e3a82d26ee5d6d659b26510b8f25610799e011d7c850ecd
+
+Count = 132
+Adata = bfd636989dfbcb0edc9f014cc8
+Payload = c96cee5ba7b799f16254a17b1870cdb85fe0ef3f42110c13
+CT = 8d3eda1e3e85705f1778b210b12faf1a7fb4094c509667ff52942aa0d39649f3d9ed535bebc2b603
+
+Count = 133
+Adata = 4812b092aa59d57451bfd812c3
+Payload = 13b1b4404dc5735655139414fcbd02c5327ae9fb148bd324
+CT = 57e38005d4f79af8203f877f55e26067122e0f88060cb8c8c1e61efb9c1d84ddac2d24f43531f569
+
+Count = 134
+Adata = f6ef9ac4f4c9ce1e4309c64fa8
+Payload = 6c5b59319e2710f5d63407f85b424d1860425ef8ce0cfe53
+CT = 28096d740715f95ba3181493f21d2fba4016b88bdc8b95bf13350de0ef34df12fb945b0ae0a0d9bd
+
+Count = 135
+Adata = 9bf12168bb3d79ebd25262f2b4
+Payload = 968e1d78008da78611e82985c4028e86770858cfe61c3723
+CT = d2dc293d99bf4e2864c43aee6d5dec24575cbebcf49b5ccfa0734563638598d8c4bf1fcd94009925
+
+Count = 136
+Adata = 7d870d7e52d3053c65eefad477
+Payload = 6a1306d911434cc7400d2f9a95e36aedceddca2b3d583f51
+CT = 2e41329c8871a56935213cf13cbc084fee892c582fdf54bda1f5fc53b08aca82bccfba6fbcb27e69
+
+Count = 137
+Adata = e95099f04371e445e5eaa1d80e
+Payload = b9197eb50c8168d16b8a12bd261d553ffcc521d979b26fee
+CT = fd4b4af095b3817f1ea601d68f42379ddc91c7aa6b3504027d1a922953facbd630d7fea6b63594ec
+
+Count = 138
+Adata = 3e80eb03db6545204ef4241ad6
+Payload = 95f59e36eac8eb3b51709d635b07fa2da0976ea20e25807f
+CT = d1a7aa7373fa0295245c8e08f258988f80c388d11ca2eb9383fa000d10078256b71249d9d1f1846c
+
+Count = 139
+Adata = 9748798c0f3cc766795c8ce0e4
+Payload = a48db9add9ecdeb49e51d3ab7bb2075202ed2aa50c0195b1
+CT = e0df8de840de371aeb7dc0c0d2ed65f022b9ccd61e86fe5d2773c2f55b752477c489facee812c614
+
+[Alen = 14]
+
+Key = 1eee667267ef10b03624cf9c341e3f75
+Nonce = 0630a3eae27e505c61c56e6560
+
+Count = 140
+Adata = d24651ef0561282d3e20e834960c
+Payload = 798e31cce0a83702a95171fb1162a17b9ce00ec3592ce262
+CT = f3c3e52f1a1ff528a8d3783ee4e75f114e3e6416334815d2d9236d5c5c9319092078411b72c51ba8
+
+Count = 141
+Adata = c527d309ab29ee91c5fc53117e71
+Payload = d79cd4c8891ec4ce2c51136712d23b32266b2b73768aeb1e
+CT = 5dd1002b73a906e42dd31aa2e757c558f4b541a61cee1caed8ad2a48cb734e3f93e602c15c7c775e
+
+Count = 142
+Adata = a93dfc3944514ddfc5acdd89fab7
+Payload = d7fa81c949f1f2af29dbd56529b307e3b348e996d0936455
+CT = 5db7552ab34630852859dca0dc36f98961968343baf793e5f34b297f3f106a9cdae255f7634fbd0f
+
+Count = 143
+Adata = e502abe21c7b22120693a08ef3e6
+Payload = 6330caaeddf0473d564d175b9408c6f12e6d3cd4ee2c423f
+CT = e97d1e4d2747851757cf1e9e618d389bfcb356018448b58f4f5d9c3dbfe3e2fe03a002e55039ebe6
+
+Count = 144
+Adata = a49b34dfad43333fb2ffd701a2d6
+Payload = 45671482c390e65f75de15ca91b93596e9bf3d6fc9178bcb
+CT = cf2ac06139272475745c1c0f643ccbfc3b6157baa3737c7b6f7bb0749c99d75740f2d193fef36c60
+
+Count = 145
+Adata = 9e4d8aa3dbdc4d4b4b8d72734f52
+Payload = c8f34bea8bdc403a48d8ed9268429141cd03c29558050ef4
+CT = 42be9f09716b8210495ae4579dc76f2b1fdda8403261f944ceec82fc674da9efa6926e8641729ed8
+
+Count = 146
+Adata = 052327ad59cc791259817fd0ed96
+Payload = d8d1c57b16c23894b66023c29f8648ce4a6074647e1f5f69
+CT = 529c1198ec75fabeb7e22a076a03b6a498be1eb1147ba8d92ff19e93f60c8f3a511300fddc38ee59
+
+Count = 147
+Adata = 14bc3c44c001ccb261a2a0526523
+Payload = 71c14a7031033db15bfe23b75fed9daf8886dd11392a0b78
+CT = fb8c9e93cbb4ff9b5a7c2a72aa6863c55a58b7c4534efcc87fa00fb244eda0d77cf6c05c8fd590af
+
+Count = 148
+Adata = 3477384c396a9e9efb3e169722cb
+Payload = afa795f836763a1210bb36fef167864f73ba3b6abc593537
+CT = 25ea411bccc1f83811393f3b04e27825a16451bfd63dc287bae19612657c87d3bb73cfb8cee7c8a8
+
+Count = 149
+Adata = 0c3b9a6924ad506038cb2d6590c9
+Payload = ca4a186f116a179579e3d327aec3f5be358bc7094f853bc3
+CT = 4007cc8cebddd5bf7861dae25b460bd4e755addc25e1cc733d9713d2e916c23ac3039de34c295fc4
+
+[Alen = 15]
+
+Key = dbbd26f5d9e970e4e384b2273961be5a
+Nonce = 0b1eabe504ef4822542e397fec
+
+Count = 150
+Adata = 477937301c83ba02d50760b603e0ea
+Payload = 553714e17a208a2eceb847a4a2d95088388b1ac8d8ca43e0
+CT = 1c80213268bad5402c4dc9b5d836ab7499810d0d8a974716df9a0e986ab2890736423bb3772cec3e
+
+Count = 151
+Adata = c91eb5a07ff19c044023e5cf339203
+Payload = c94d0b9e728413c58202cb3f6b82dba7aa9e3ca0a72c40c7
+CT = 80fa3e4d601e4cab60f7452e116d205b0b942b65f571443139f907a92cb01215e3cda84ae13af48b
+
+Count = 152
+Adata = 38c71a8e9b279c605c7f0418a0afc1
+Payload = b4e8c4fd5ad98a1be8b5a11677c57ca1c1694e3528092aa9
+CT = fd5ff12e4843d5750a402f070d2a875d606359f07a542e5f3dbd8dbf7485106cdf9ea0e7088a5650
+
+Count = 153
+Adata = f2c76ef617fa2bfc8a4d6bcbb15fe8
+Payload = 578ce26cdb5ba2e8798e23588e5cd04ef782820b80e49a42
+CT = 1e3bd7bfc9c1fd869b7bad49f4b32bb2568895ced2b99eb4853fde6f4dca88ff11bbce20ed9e5012
+
+Count = 154
+Adata = 36004342dd74e7966692a848b2c11e
+Payload = 78733c635d4d4e8b0729732f1e174dfcec4e020a7ac3870d
+CT = 31c409b04fd711e5e5dcfd3e64f8b6004d4415cf289e83fbd94e979108fcecbd32f6bdf72f0ccb4d
+
+Count = 155
+Adata = db92bc3fe5d4141aeb39baea6f114c
+Payload = c7aafe7760945e45703c1e19f1032dfd56ddc216c3b03826
+CT = 8e1dcba4720e012b92c990088becd601f7d7d5d391ed3cd0229c8f9d4e39fc16cbdb44236ef125c7
+
+Count = 156
+Adata = 34ec2d5b6f0d950509b47a0637d74c
+Payload = 2345e36a63be0b78df95e60907c78da0e48e61e70685a1f3
+CT = 6af2d6b9712454163d6068187d28765c4584762254d8a5051c9ab7cb0a779c3fa78c9ee12603802b
+
+Count = 157
+Adata = 6ab658d177c2dd87c9b8787cd70182
+Payload = b0725f735543eb0c0ec88ae69b140f5787d28ef4a2e36d57
+CT = f9c56aa047d9b462ec3d04f7e1fbf4ab26d89931f0be69a1648c6307ec5ea304045a7cdc93f36b9d
+
+Count = 158
+Adata = 483f135c61250fa610b4d14b99ecf0
+Payload = 315a947bf5291278d446d332ee5ca0def7655d5c957a8fb4
+CT = 78eda1a8e7b34d1636b35d2394b35b22566f4a99c7278b42364ff3b1ad915347b1c7f062b10d3da4
+
+Count = 159
+Adata = bb022aed60819ef84ae83ce27db9d0
+Payload = f78d00755bcb45e6822121fe7cb03c8e627c9f548ccd7e7c
+CT = be3a35a649511a8860d4afef065fc772c3768891de907a8a7569808dab58d42181543b2e2d05992c
+
+[Alen = 16]
+
+Key = 10a7720f2e18f739c26924925af6b670
+Nonce = 8c4e7813ab9bce9dafee01c628
+
+Count = 160
+Adata = a209941fab710fda38d11c68b13d930f
+Payload = e59782a9aea45f467b90e51a0fdf166baba05663def2d8b6
+CT = e357b1ccdaca6f3506dc45279c2e4c59f5307a5fd6a99cd72341ea8c0785569973f90ee9ee645acc
+
+Count = 161
+Adata = 2e2f6f9755a492ee54df77b2ecab9808
+Payload = 042a072f6ebf11f79fcb4f5a64f7946dc837d9d2355785ea
+CT = 02ea344a1ad12184e287ef67f706ce5f96a7f5ee3d0cc18b703eb81224cdb1fd2e1cfb2fbfe1e402
+
+Count = 162
+Adata = 99e98c9983c85d1f49ae43ebad67a652
+Payload = 5db6bda27910e7b8b61ac476c6532570b71b3932bd6a698c
+CT = 5b768ec70d7ed7cbcb56644b55a27f42e98b150eb5312ded64c4aea7f17f18f068897557c93ffaaa
+
+Count = 163
+Adata = 37a837d73fa15793f6f823fb99c2ea74
+Payload = 8cac261a461c3ddd2642b8e4e5c3389e491fcb2ff8356412
+CT = 8a6c157f32720dae5b0e18d9763262ac178fe713f06e20736f3b2e70e6e2dc7acc74a823a7f49722
+
+Count = 164
+Adata = 11119a4e779cfb64c736d425e4ff554d
+Payload = 3429f9b088b501d7944c462694d0799568282e7ce07d3e61
+CT = 32e9cad5fcdb31a4e900e61b072123a736b80240e8267a000dc3b57096f0df1d4eb5328c416921bc
+
+Count = 165
+Adata = 962d7d4305f23d1692747b504960c0a4
+Payload = a46ae4c71d4c9eb72fabfa76b8074aa02e07653eca10eef5
+CT = a2aad7a26922aec452e75a4b2bf6109270974902c24baa94f62ed804e9f2ac0f7001d0f35ea9f3c1
+
+Count = 166
+Adata = bbb1fdfefcf3657ba6cd93ff341a04e1
+Payload = 92f5e3083f57c77ac9553a2024a66489698bd2261f05d415
+CT = 9435d06d4b39f709b4199a1db7573ebb371bfe1a175e9074907dcd7ac1e0bb248d46c3036c39fb02
+
+Count = 167
+Adata = 74be126f7c596642dafa8fe3da904e69
+Payload = 41ecc3aae5cfebfad7921a47a0684601ffe73816380f8716
+CT = 472cf0cf91a1db89aadeba7a33991c33a177142a3054c37787cbb80fd21127feca7e76fd6947d5b7
+
+Count = 168
+Adata = d72cc521c90a468522af8966c24799f3
+Payload = 8850bdda4bd0271e333db344a47b837183eb48269c3dc0b6
+CT = 8e908ebf3fbe176d4e711379378ad943dd7b641a946684d7cdb5d1243b6e73b8e380d8ca041647db
+
+Count = 169
+Adata = 28f427fba8d0bb0380bbe5072ccfa519
+Payload = fdd3ca2f193f93f5a349b50357d26748b767cde6ab5cbfe7
+CT = fb13f94a6d51a386de05153ec4233d7ae9f7e1daa307fb864a0ae8604b103f882f17db893ed5c576
+
+[Alen = 17]
+
+Key = 6bffab1f4f4c1ff66b4a669b515b2f8d
+Nonce = ddb34d5e0140fb96d690e1a2b7
+
+Count = 170
+Adata = 5cbba9ea778e01af00afb2a934f28c7211
+Payload = d91b12e8655dd92b1332fc1d71c391c96a17111562d90ba3
+CT = d302e5b2d5d90433186b804cd7717e2db2f22cdc34fb2942ab30780a2c4f12af8f35350d65284c59
+
+Count = 171
+Adata = 1583138aa307401dddc40804ac0f414d33
+Payload = eeafb08d4a4819f5682a01d44371e34cc5729079e74e73a6
+CT = e4b647d7faccc4ed63737d85e5c30ca81d97adb0b16c514746577901b7f6feb88b8e2b8562f9cb5f
+
+Count = 172
+Adata = 23931c258c84086500c6a3b6eda457e6b5
+Payload = b8737d5bbfc976c2d8d9786148dea664dd83cee98df537b5
+CT = b26a8a010f4dabdad3800430ee6c49800566f320dbd715548735a59390ba7a892741694f3a89b0bf
+
+Count = 173
+Adata = e12f98507d6514c3b551d240595346bc9e
+Payload = eb021b63c61c0b194bd44870608d7ef0b932b6104412d7a9
+CT = e11bec397698d601408d3421c63f911461d78bd91230f548f4f81ed18cc1820375a7bec2318cde1e
+
+Count = 174
+Adata = e14b87d49d231c0199eec627fd7f1b5332
+Payload = 93b42584c4956078359d77e80aef52281b9228a1f66aa36b
+CT = 99add2de7411bd603ec40bb9ac5dbdccc3771568a048818a187b430caa60d98dc3e2aeefe6249b44
+
+Count = 175
+Adata = ca095aec96a8b093e62b10f0950ce35ce7
+Payload = 6a788d8238c7b313b8eba27b210a71c36819d719115b9b76
+CT = 60617ad888436e0bb3b2de2a87b89e27b0fcead04779b9970a77372b727408e1bf5a70790b9eba3a
+
+Count = 176
+Adata = d1cac02b34ad33c0e77a5bda2c3baf5e5d
+Payload = 3bc1ee54d0094603dfc68eee118e547d031fb36e464e776d
+CT = 31d8190e608d9b1bd49ff2bfb73cbb99dbfa8ea7106c558cdc1f5cb4d4fa2204e82eedcb3784443d
+
+Count = 177
+Adata = 065c06b49a49898e20bb679e35edbb1f76
+Payload = 8a12adb8b746216baa8a418725e608e4377f13816a036a10
+CT = 800b5ae207c2fc73a1d33dd68354e700ef9a2e483c2148f12413f9496592a75a1d6e42ee3a258607
+
+Count = 178
+Adata = 98a42d7a0c5917deaf3b4de3f0cbe0a191
+Payload = 30a226c07401d0ae24c73d682e3a6e7e377ec1613bafba17
+CT = 3abbd19ac4850db62f9e41398888819aef9bfca86d8d98f6b571a3150887df1ac5f813676b2eb24f
+
+Count = 179
+Adata = e245a7528931841b52a5f59d861d98d7b7
+Payload = 3d17bcdf30445ebd8a9b6aa2fe11d443c1161bb1ee69ced0
+CT = 370e4b8580c083a581c216f358a33ba719f32678b84bec3131aa5e4657c92e31c69ab18d447d3578
+
+[Alen = 18]
+
+Key = ae6136df9ab43631ef143515dacedbe7
+Nonce = c5c445792208a50c8e93d64aa3
+
+Count = 180
+Adata = e04006b68c83a5dd4ceac3cde238e48895ae
+Payload = 6a493c5ef3769ccc4101dbb2eb36e1e5bbc577a057ce0731
+CT = c7584c0203c2535c5702c6ae93b7cbfb066f4a055c627a180d6d676d11fce907b5c93fa1ed7bff2b
+
+Count = 181
+Adata = 5da64e368f45153ea5b7ddca966b6c5b699a
+Payload = 15e0c672c6764f3699d9d3e7120f8ce5daab166f08fdd074
+CT = b8f1b62e36c280a68fdacefb6a8ea6fb67012bca0351ad5d2cd45f211b1a1364c91ad07959bf0ee5
+
+Count = 182
+Adata = 1b315d024bb5d1e03d7510e61f37d8adb10a
+Payload = de907d58cd8f5a72acaa1d329b937dfbbfed65a4e45eb029
+CT = 73810d043d3b95e2baa9002ee31257e502475801eff2cd0018f021a98b2edfb0b7500363099c2a1a
+
+Count = 183
+Adata = 8691ba4f9232ca86f919fe72ddb39c91d707
+Payload = c7fa314d27be79f9d3e2d1e188c1785b0c970f91b8ed4290
+CT = 6aeb4111d70ab669c5e1ccfdf0405245b13d3234b3413fb92ac9aeb018c48f3902276ac759710b6d
+
+Count = 184
+Adata = ff0baf1cbb5884a9290ea7b5ee49915efb4b
+Payload = 33b05b20f3c849fac091a5028cbfa0bc9a1c32514136fee3
+CT = 9ea12b7c037c866ad692b81ef43e8aa227b60ff44a9a83ca7dac49f606dadb9f7034e0a1860d519b
+
+Count = 185
+Adata = 2d118cda20700bc2748ea1753fbca6f74933
+Payload = f43832e420e2eccd5d80502bea2ba1804e17d4433318fc86
+CT = 592942b8d056235d4b834d3792aa8b9ef3bde9e638b481af623ccbab19c1442806e21c5a820945da
+
+Count = 186
+Adata = 0c7a5fd2010c999a8a0efa81f89ff5bfefe0
+Payload = ceb203c842a962183f22e602644fc66e4290b3d5be445fb4
+CT = 63a37394b21dad882921fb1e1cceec70ff3a8e70b5e8229ddbcd18947ac1800856c9c92eb0388c70
+
+Count = 187
+Adata = 73fdddb9e0a64f5671fd70c4ea8443507789
+Payload = d6015b6bd5f5eabb2a649129f8f727c06a3ad59499f21caf
+CT = 7b102b372541252b3c678c3580760dded790e831925e618639c29ea73b0c5aa130d8b14f7b9926a9
+
+Count = 188
+Adata = 82c4484e3a6e18b6bbfd78b69b00c40b30c5
+Payload = c288b810fb533441bd549d02c0b28d5b834293683eaacda2
+CT = 6f99c84c0be7fbd1ab57801eb833a7453ee8aecd3506b08bf0a0f148ae138c2ea02538c8fd7ac76c
+
+Count = 189
+Adata = 267d8385b14721eded743cffd69e4d595f7e
+Payload = 667cc47d13c34923be2441300066a6c150b24d66c947ca7b
+CT = cb6db421e37786b3a8275c2c78e78cdfed1870c3c2ebb75285eb537e7583f04e040a0ddc41106213
+
+[Alen = 19]
+
+Key = f1908328edf2996ebfc9655472ca5ad0
+Nonce = 4c693364546930b6c5250e2699
+
+Count = 190
+Adata = 4a3634e5028df97fbe00eb016e8ea4f1918faa
+Payload = eede01b08f9a303cdf14c99d7a45732972c6eff2a1db06eb
+CT = 90c850790b0b380f5aeb2488fdf43c9d5ef1759861e86f6e52570e769629dcc2e568737ba53a1195
+
+Count = 191
+Adata = 041b93e3fc059fa44aa755e88df277b9b6e499
+Payload = e61ca7310172eec16745a73e34516f65844eecd0dbc5566a
+CT = 980af6f885e3e6f2e2ba4a2bb3e020d1a87976ba1bf63feff1d82ec19a2e3ec43bbdb34e10999d90
+
+Count = 192
+Adata = d1be393376cb5d23cf8139da0fd92f3d520ae9
+Payload = ea887edee68ad5fa6bae928aa480dda898037f820700ec52
+CT = 949e2f17621bddc9ee517f9f2331921cb434e5e8c73385d7f2abb0ce4de9eeb5e8af9cdf3391d3cc
+
+Count = 193
+Adata = f3e551b34d2db1286a9f41085e4dda95ec3f75
+Payload = 71fe1ba5d299495d2a56039c64032ec6263d437f55e3f5be
+CT = 0fe84a6c5608416eafa9ee89e3b261720a0ad91595d09c3b239c73b01ba49a8498b5ff4833851069
+
+Count = 194
+Adata = a69ddc66e63a3415f21009d53adcf26bc1a9a5
+Payload = bd04d854216740a6ceb9827cbddd83761d19feb2a21d78ef
+CT = c312899da5f648954b466f693a6cccc2312e64d8622e116a2248dacd3903c26a2dc5ae649566ad67
+
+Count = 195
+Adata = 5735d6f5882d8f27155eb4cc285a65138ad64a
+Payload = 33b44873a7a1e5b0fdbb7e7347623e4fa1ccd937feb26fda
+CT = 4da219ba2330ed8378449366c0d371fb8dfb435d3e81065fd4156cf7d97b2e744351b6960a807cf8
+
+Count = 196
+Adata = 5d94ed976ab2063512690ae704c3b115519742
+Payload = d3909d577a4e89642227cc6fc146b61bc18392175e342898
+CT = ad86cc9efedf8157a7d8217a46f7f9afedb4087d9e07411d5a50086b6711ac72533c3c5717f6892c
+
+Count = 197
+Adata = db20b384620ab8691aed2fed14a745188d94c0
+Payload = ba0716355fffb8ef947d2a15eb58375a1ff1084c56699029
+CT = c41147fcdb6eb0dc1182c7006ce978ee33c69226965af9ac54fb74ecb9a5163b01b9dbf97ff2f999
+
+Count = 198
+Adata = 94897cdd04e0c8480b2ef7b5201dda37558ba9
+Payload = 5f4b4f97b6aa48adb3336c451aac377fde4adf47897fd9cc
+CT = 215d1e5e323b409e36cc81509d1d78cbf27d452d494cb049d2a81702f665ff5c54f586defd268c94
+
+Count = 199
+Adata = 95c44e1e5ad256b3ce1cc1d87137a1e09f1fd4
+Payload = 598e91d39c414496fd5e69f2cf80826b4e7d59ba28e0a0d8
+CT = 2798c01a18d04ca578a184e74831cddf624ac3d0e8d3c95dfa641889723e163825ab65727e8a5343
+
+[Alen = 20]
+
+Key = 61cb8eb792e95d099a1455fb789d8d16
+Nonce = 1f37b3e59137f2a60dc09d16ac
+
+Count = 200
+Adata = 09db3efac9473f713da630ae92c2c8604c61c51e
+Payload = 6ad541695a37c32d73ff6d5f870abd5b0f362a8968c4fce0
+CT = e65fcc975865c1499b088b58ba163283085d8ca68dc3b235d89756e5d78753ef22c012ae34b39a20
+
+Count = 201
+Adata = b6d07035aed9c141c713cc3bce60f7ba8ac2545f
+Payload = 9cce4c82fe9d38ef64ac8abdf0619f201a25ce6903675627
+CT = 1044c17cfccf3a8b8c5b6cbacd7d10f81d4e6846e66018f2fc78ebae9c143a7283b0641e1f83f5a0
+
+Count = 202
+Adata = 80a5ab693378af29cd5a33555cb3579f9ae540aa
+Payload = 7295a7aed3e987baef19ad68c33ba5a5dcbff27875ff5236
+CT = fe1f2a50d1bb85de07ee4b6ffe272a7ddbd4545790f81ce35a7e44348d2b3085348f787128a4e96a
+
+Count = 203
+Adata = 220817144a15a0a654fc1beaabce60270aa72df8
+Payload = eb21fe20fc4f92452b261eac0d7b70016f7469afdff7a3f5
+CT = 67ab73defe1d9021c3d1f8ab3067ffd9681fcf803af0ed2024dfc096cd8a09d2d81f6146fb54082a
+
+Count = 204
+Adata = 5a2423c2ff2d642c80ac1ca27dd779321f3e9c01
+Payload = 23bf80f51dfd83f63986910e69d54a315c2bfb43f432b7de
+CT = af350d0b1faf8192d171770954c9c5e95b405d6c1135f90b5da82204f4dd8f535cb2fec2f133d882
+
+Count = 205
+Adata = f2c76ef617fa2bfc8a4d6bcbb15fe88436fdc216
+Payload = fc3a50cc8a68778327923ea697f5388da4c814381e29c5e4
+CT = 70b0dd32883a75e7cf65d8a1aae9b755a3a3b217fb2e8b31108630135498ba409f4b6c8caee8a85b
+
+Count = 206
+Adata = b40c8c1d2cee490653105ca2443356cdb63e4fd0
+Payload = 465e41c69928d08c33e063ea119595a04d0de6bffd17bba5
+CT = cad4cc389b7ad2e8db1785ed2c891a784a6640901810f570f89c515837d129ba41f9c24b0229ddcf
+
+Count = 207
+Adata = 6ebfa1e8f80b3cdb1bedf2e3c7e74f30f55c38e1
+Payload = 3f98ee3922f8f1086e3135ae66c5465426b13c8794954880
+CT = b31263c720aaf36c86c6d3a95bd9c98c21da9aa871920655a352fa6b9c4e40733ddcd3fcdaf9ae63
+
+Count = 208
+Adata = 6d0159861031c1a5f01aab35927fe2ab28154d19
+Payload = 5b43067a5ab3a9f9e633fdc084c44ffa7f11edd12ea5873d
+CT = d7c98b8458e1ab9d0ec41bc7b9d8c022787a4bfecba2c9e82c1aa13f062c0f1f5008e27ff2191942
+
+Count = 209
+Adata = 15e5ade017b30ab41878a2747e93aa91c61c2908
+Payload = e40b7e9e46e339e64891526e730b3bf6562fa37acefce307
+CT = 6881f36044b13b82a066b4694e17b42e514405552bfbadd2e149dd02bc7face0c4dfe4e501c2ac2a
+
+[Alen = 21]
+
+Key = be1ed49e2cb0caf6b6a0940c58453b93
+Nonce = b78ad129457681fa7346435b97
+
+Count = 210
+Adata = 161d92c7df1ebb0924719e066e08b95eb4914a5eda
+Payload = a9eec383f63892521e4616fcbadc5485942ffaf4669c43a7
+CT = 949be340720c4fdc4adc05cb777dd81a2549628d33fba07e62d2b338a7b34ebd9d85c244c952d681
+
+Count = 211
+Adata = 6b1d94bc0c6e45fc905c509ea667853e4b2c5a8848
+Payload = 7b44a093162bfc8b4d65f1031d890a6b08a3705b142c0c26
+CT = 46318050921f210519ffe234d02886f4b9c5e822414befff8a4defafeb3d61dad8c007b68d8fb9b3
+
+Count = 212
+Adata = 868dd3e241f60f097a7a2fe571307ee5eb961218ca
+Payload = 28c4d6de3e2ce51b849b135d9cfd3084f0e3155447cad9d5
+CT = 15b1f61dba183895d001006a515cbc1b41858d2d12ad3a0c57cbab553b511d68a4f41db211d0a2fc
+
+Count = 213
+Adata = 3776f37fbf8803bdfd246ffaff2e59658a6c3f0ebb
+Payload = 16d345606a315ad2406abbcb43cd8cabe948107ba6d17a72
+CT = 2ba665a3ee05875c14f0a8fc8e6c0034582e8802f3b699ab0290fd7dbf0afa3e597274e3c9fe170b
+
+Count = 214
+Adata = d0f2769eba9b8e618f00eed6b34c261c59322a253b
+Payload = fcbbcdd9599a86e7c8ccb9347065789a9728ca1220fa51ca
+CT = c1ceed1addae5b699c56aa03bdc4f405264e526b759db2139c7dec3960e6aba3174d793b4e08f449
+
+Count = 215
+Adata = 2be180892faed0bb75887668d187807666d3c66c68
+Payload = 8d145b1f792cc31a2e5b86216609bb018e7aea3012ff70a5
+CT = b0617bdcfd181e947ac19516aba8379e3f1c72494798937c7057b9e2d844e86ee5c3ecfb3270804e
+
+Count = 216
+Adata = 52859849a5b7c1d432c3bfb35271cd8141db2ec774
+Payload = 741db990b43ef34993c33d1c4953b67b128b9299dfe86d74
+CT = 49689953300a2ec7c7592e2b84f23ae4a3ed0ae08a8f8ead1150fa899152eef7a30ae0f20986818e
+
+Count = 217
+Adata = aa192759625f4e42d1d1fa73dc0f62199142155615
+Payload = 51dca5c0f8e5d49596f32d3eb87437bcae866640310ce1e3
+CT = 6ca985037cd1091bc2693e0975d5bb231fe0fe39646b023aba7ff9203608089558698ec29472dda7
+
+Count = 218
+Adata = 6de564226884188ec7bea3894535a875cff2a42fdb
+Payload = dfaa7aa8b28626210d5c24e2ddfe516189be05aabe26f3b2
+CT = e2df5a6b36b2fbaf59c637d5105fddfe38d89dd3eb41106b85bd0a5074ef852575baf5f12c22663e
+
+Count = 219
+Adata = f245f2ee23755df863dee55d7ef0c3c09a0b6f0b0c
+Payload = eedf00aab5edefdd6549d37ed44358e11c588c24f141dc57
+CT = d3aa206931d9325331d3c04919e2d47ead3e145da4263f8e9eb617436bae012331daf020fce24e47
+
+[Alen = 22]
+
+Key = 34ab6fd7f54a2e0276fcb7cf1e203aba
+Nonce = 6091afb62c1a8eed4da5624dd7
+
+Count = 220
+Adata = 1ab5cc3d7b01dc74e6cf838bb565fea3187d33d552a2
+Payload = 8d164f598ea141082b1069776fccd87baf6a2563cbdbc9d1
+CT = 0d30ab07153b5153637969e6bd3539448c541e42b3d432fd7ef14622a9b621d1721b944c60f7fd67
+
+Count = 221
+Adata = 1f1ac4674b272bc7a4ee9f4eae33e969b16fa90a69ba
+Payload = 14e99a2ef0de650adbd785c692342cdb765e6d20d5fca09a
+CT = 94cf7e706b44755193be855740cdcde455605601adf35bb6dfa4ec2c92671c64ee07946527be67f0
+
+Count = 222
+Adata = 43ee77f12ea42e82a02275a68aa95cbd1bb440442bcf
+Payload = 383242c709fe5f2ce782bf8c83b645d171f2bd238abc655d
+CT = b814a69992644f77afebbf1d514fa4ee52cc8602f2b39e71173572fbf3d9495760aae4347397b110
+
+Count = 223
+Adata = ae2ff288199be25bf640811541394ad7e1dd0dc0d24d
+Payload = 9c16a5b638c35c97c5c981c1b8dbcba11aec30e72e45a936
+CT = 1c3041e8a3594ccc8da081506a222a9e39d20bc6564a521a4d2327956e030b9df753e063b5b71201
+
+Count = 224
+Adata = 4ccfb4281852b5ca7e787723d689384a68ff9437db31
+Payload = ec9d8edff25645520801b6e8d14a2fc3b193db70d5e5e878
+CT = 6cbb6a8169cc55094068b67903b3cefc92ade051adea1354e4dac0c9130f5641afd035dd884b6271
+
+Count = 225
+Adata = d3a2fffc798fd9cc2f409471faf18caa2ff3dcf4e652
+Payload = 0db33eda4188a9165147e24e40f79fee1985eb68d5162728
+CT = 8d95da84da12b94d192ee2df920e7ed13abbd049ad19dc0448807dd50a9cf41651083c49c7493ceb
+
+Count = 226
+Adata = 7b5121aa4d1e314f209ffe3e92cd26ee4f74d91e27f2
+Payload = e0d3ea4308376423c4322503f56e427a64e2e6d8b4f5e668
+CT = 60f50e1d93ad74788c5b25922797a34547dcddf9ccfa1d448ea0da53046733f522ded40a09c6d7a6
+
+Count = 227
+Adata = 6e12c112720ef346bbbe7d1c19483721b1c52c438dad
+Payload = 491f2bca585d6b5fdf38d18890e4d1bc923fe26930b3d2f1
+CT = c939cf94c3c77b049751d119421d3083b101d94848bc29dd345cb5a968f39654b994686699d532c2
+
+Count = 228
+Adata = 20433402a2d869c95ac4a070c7a3da838c928a385f89
+Payload = f45908d691ddaf89c0bc129ffada94c3ceda5f47d63ef76a
+CT = 747fec880a47bfd288d5120e282375fcede46466ae310c46cce85eb55339b886b7121b306fccc0b2
+
+Count = 229
+Adata = 42f944c21cc221beaacb288115ac628346b8a1d94bd5
+Payload = e300fc7a5b96806382c35af5b2c2e8e26382751b59010d4b
+CT = 63261824c00c9038caaa5a64603b09dd40bc4e3a210ef667a37ca5ce12aa6f0659467642deb8bfcd
+
+[Alen = 23]
+
+Key = ea96f90fbae12a857f5c97e0cba57943
+Nonce = 21cc46d9ced1539b0ad946e600
+
+Count = 230
+Adata = 105258d2f25f62675aee975cfdb668aff833f05b61eb2a
+Payload = 49db80f22bc267a70e5636dfbc8a21c83d9691fe4b9c3051
+CT = d2fcc8b7809b5fc07e44083e437d8180157f1782a9ce9f65c7fa9ee2e7cdc1b755258f2212a8a8f4
+
+Count = 231
+Adata = 0f5938540651fa4ca03867e67518eb2b73f60dd8750fa0
+Payload = 26618e21099a79d6c517335389551323065ad89c8848ea12
+CT = bd46c664a2c341b1b5050db276a2b36b2eb35ee06a1a4526bfdb9bfcd3b969fb2e41221eb92b0147
+
+Count = 232
+Adata = d6b228960fcbcf07c7bede616139db62b3808718a5b511
+Payload = 4de1d6d57144896ddea1c30f49afecd27bdf4840ed9928b5
+CT = d6c69e90da1db10aaeb3fdeeb6584c9a5336ce3c0fcb8781f8beea22cba93203c912209c78c03aa1
+
+Count = 233
+Adata = 75f8f071e229355e286882917ce5dd4f1db591fee51b6c
+Payload = 785359b1dc754a1e1b6d8731bd2d917ce3e91507401310e8
+CT = e37411f4772c72796b7fb9d042da3134cb00937ba241bfdc69a2e3ea4a40f7c491912c1a0778ebde
+
+Count = 234
+Adata = 4afb62aa8648ac7474dd16fcc376f8909c69e1ce36e6d1
+Payload = ab627aac1496d011ed2edcb2fc6b2afbcc394654f56124f6
+CT = 304532e9bfcfe8769d3ce253039c8ab3e4d0c02817338bc2a75c7ba2a769c27903e99b72639b0841
+
+Count = 235
+Adata = 736fdf94db820a2efe89e7fc9dcfe7c23d5754ac2bcc7c
+Payload = 40722cffb37f1455c2618408e777ed0f4b1bd039952730cc
+CT = db5564ba18262c32b273bae918804d4763f2564577759ff8f84f4ca4a69fde75d7207e50494819b6
+
+Count = 236
+Adata = 8a9a0367137c28db4c4e78d9cd9a68cde0d1b4583532ae
+Payload = dcaabf7a061502618541c09ea59dbbbd52b2692fd0064747
+CT = 478df73fad4c3a06f553fe7f5a6a1bf57a5bef533254e873a0c34a24d3ee0946034c71fba4dbb333
+
+Count = 237
+Adata = 34dbbff560ef04ea731b8979aef2ae50972f4db3efe14a
+Payload = dd641a893b16e0e173ea2eda20638bb01849ac11e64e8ddb
+CT = 464352cc904fd88603f8103bdf942bf830a02a6d041c22ef0f5e24a435a39a716c39f43dabdc4281
+
+Count = 238
+Adata = f3d1fcd912252431db9d8ccfc3e203d5b34d537468b4c6
+Payload = 9aa3e8ad92777dfeb121a646ce2e918d1e12b30754bc0947
+CT = 0184a0e8392e4599c13398a731d931c536fb357bb6eea673f623d59f66764d859a772bb50ec91fc3
+
+Count = 239
+Adata = 513b4cdc551c203ed5f1e659813584862023911590b672
+Payload = c8f44ae4b02fffdbce0df773c24075f877945fc7a86be460
+CT = 53d302a11b76c7bcbe1fc9923db7d5b05f7dd9bb4a394b543b6549eb16fba96318afb3df51f4675f
+
+[Alen = 24]
+
+Key = 35b403a15212097085d6e2b77ec3d4f2
+Nonce = daa423bf9256c3fcc347a293aa
+
+Count = 240
+Adata = d3c0ed74e5f25e4c1e479e1a51182bb018698ec267269149
+Payload = 7dd7396db6613eb80909a3b8c0029b624912aabedda0659b
+CT = 5b00cf8a66baa7fe22502ed6f4861af71fa64b550d643f95eee82c19ecba34280604b58d92dacd3f
+
+Count = 241
+Adata = 62f4fe53e99a9b0c51e9561d910d7e2ffe19a5176c9dec06
+Payload = 897f0dfd90213f64a9277a0eda4f134f303fa89f56ca54fb
+CT = afa8fb1a40faa622827ef760eecb92da668b4974860e0ef5ab4999e9689d52b8afeb87923efa3b48
+
+Count = 242
+Adata = 191c4dfa653c20292657f7694c6b6a4a410c49a879abd217
+Payload = 2b7cf9e6e2d6abcd7775f8a6eb6294e822041c4c45f09c3c
+CT = 0dab0f01320d328b5c2c75c8dfe6157d74b0fda79534c632cdc71e556c34fd4e1b5ebc50d38da8b3
+
+Count = 243
+Adata = ba34741f8edb51470eb20f891869aabeab562d92571ac943
+Payload = dccb9a4625512496b372a2b8b768f75741d8c2e30e57d638
+CT = fa1c6ca1f58abdd0982b2fd683ec76c2176c2308de938c3646223d381090661c2ee2370d29a572a9
+
+Count = 244
+Adata = 8b922aca6125722ec490b134a45864397f4e2c281d6e2089
+Payload = e0e452c990665465160b02cad6367ca89723613488d8efbf
+CT = c633a42e40bdcd233d528fa4e2b2fd3dc19780df581cb5b1f78af50466646b7c7e652f787afe5357
+
+Count = 245
+Adata = afb9fd78e3f8eaf4e8c91da62b2da534508e54f7dfa214fc
+Payload = b536fdb8839f87080ae65ec35da347e792622ffe18a61d46
+CT = 93e10b5f53441e4e21bfd3ad6927c672c4d6ce15c8624748cc9d9a1270f78648a6b66cb8c0f2471b
+
+Count = 246
+Adata = ecf942ccee7396cb3ee177eadd4d96a4af1d90afdce97376
+Payload = c81233826e5125e1f31fe275184ccba8f1a743e58e146e4d
+CT = eec5c565be8abca7d8466f1b2cc84a3da713a20e5ed03443b17d3d6f1fc4f530841b749d9f3a0a7a
+
+Count = 247
+Adata = 16fea92ffcaad563792aa924bffe7ef690edc90ea4e29cc0
+Payload = 24ab253b5b06552665c3c810254c0ed15e68a783180d7eee
+CT = 027cd3dc8bddcc604e9a457e11c88f4408dc4668c8c924e05852ed48cf88d9ab2326aa46b6541b60
+
+Count = 248
+Adata = 76f110eecd369d79e21fb208058359d3a2f37581d1f7f691
+Payload = 7f596bc7a815d103ed9f6dc428b60e72aeadcb9382ccde4a
+CT = 598e9d2078ce4845c6c6e0aa1c328fe7f8192a7852088444c62dff6bcade5ac2edb8ec9797ce433e
+
+Count = 249
+Adata = 8834c776a3237f060ae0ab9857324a3b2ac79f3b6e6f90f5
+Payload = 11cbfb3d348c7abef99f562607e289de34a2bb379a5dfe50
+CT = 371c0ddae457e3f8d2c6db483366084b62165adc4a99a45eb936ac4764575f85352c24ab23209d42
+
+[Alen = 25]
+
+Key = 7a459aadb48f1a528edae71fcf698b84
+Nonce = fa4616b715ea898772b0e89dd4
+
+Count = 250
+Adata = 0c0b4a45df5c3919c1e1669c5af5d398d9545e44307d95c481
+Payload = 0b3d947de8632dc8ff752f619ba7c84716fac7a23e101641
+CT = 7db9f3f7dc26fc2adf58d4525d26d5601e977de5a7c33911a1138cff7b624f9908b5b4d7e90a824a
+
+Count = 251
+Adata = aa27a28a36b5a2cee57ffeca0233feb4bdd4eacb2cae28e98f
+Payload = e6dedce2c278c44e5678d13e7d5b5d3501d61bb0bb6b5558
+CT = 905abb68f63d15ac76552a0dbbda401209bba1f722b87a08e23f92b598f7a248a894e6b8f5691bee
+
+Count = 252
+Adata = 66220aa9b40a1772caba7749a544bff938e804dbc6e556498f
+Payload = a276b0922fbd5094bf89b9329d07341e039d6204397b81c0
+CT = d4f2d7181bf881769fa442015b8629390bf0d843a0a8ae90e94043c0d80fd651469232fe9d47a81f
+
+Count = 253
+Adata = 3d765d20e03a4cebfda50316c4b7d8b6c55078d5b3e9cbc567
+Payload = b99afbc2dbb377350cc58d4bfe8e954cef25d7b27b82fad4
+CT = cf1e9c48eff6a6d72ce87678380f886be7486df5e251d58425088b522fc0731097e729448236b317
+
+Count = 254
+Adata = e91b6265879153e1692b00a112b4205111c8eb1a7b7f2c6898
+Payload = 56114cc783b80ca2dd2881387b6d92a59a237dfc8e976d8b
+CT = 20952b4db7fddd40fd057a0bbdec8f82924ec7bb174442db2208cf07574cc4f3f83ed6301b904404
+
+Count = 255
+Adata = 340b16f352817babb4fb70e9e6e18784b3e67bdd449872158c
+Payload = eb21fe20fc4f92452b261eac0d7b70016f7469afdff7a3f5
+CT = 9da599aac80a43a70b0be59fcbfa6d266719d3e846248ca514b0a900068e55cd24c92bbb78c521ad
+
+Count = 256
+Adata = 5a2423c2ff2d642c80ac1ca27dd779321f3e9c01445be684dc
+Payload = b15083a73607c9d7e197a8cc884ad3be98ac343f6493df67
+CT = c7d4e42d02421835c1ba53ff4ecbce9990c18e78fd40f0373f8ba66d74321c80c057f010078d2f28
+
+Count = 257
+Adata = 5fe8bb27a59a5f4e370adbba96484c2365fc0d8c6e58d7d3e6
+Payload = 07542d18e8f2d3e199fca0f90cabb78b169525fdce81666a
+CT = 71d04a92dcb70203b9d15bcaca2aaaac1ef89fba5752493a0a189319e4f06d53c1405d37b06cc8eb
+
+Count = 258
+Adata = 23e5422e8d7560a9e65642b5e723a47536c16791f3a0cf918d
+Payload = cd574ed56bdfd1408f7831e0b24b4345ee979ac906a7aa22
+CT = bbd3295f5f9a00a2af55cad374ca5e62e6fa208e9f748572dd72f48ae03670249d74f8460b63b1ae
+
+Count = 259
+Adata = fcc9422ba5023a9997baa9c4ee6cb196ffe96e08eb9c2b8a75
+Payload = 8c9abe94beed4c9bd46adb1d04fbfe7016dd50d324525abb
+CT = fa1ed91e8aa89d79f447202ec27ae3571eb0ea94bd8175eb1717c00c93d36a77141b723d573c8c65
+
+[Alen = 26]
+
+Key = ca748225057f735f712ecc64791367f0
+Nonce = 1341a6998eb1f50d4b710a13ac
+
+Count = 260
+Adata = 5fb96b045f494808c02014f06074bd45b8a8ad12b4cb448ec162
+Payload = e92cd0cb97afe4fb00c4f12e9b9abe1d08db98f49a27f461
+CT = 82b666694232e86e82295beae66ae67d56aceb5d6b1484ceb4a6843ec16078038c10afedc41f5362
+
+Count = 261
+Adata = 87db0d9d69bc0cf69cabeb92570e482bbc8ff3e1ba72f12f3225
+Payload = a6dbad96ad23ff61479df39b99f0673a09f2a7eaebbd34b9
+CT = cd411b3478bef3f4c570595fe4003f5a5785d4431a8e4416a7c6566d0b8ff97f946d7c7773a845f2
+
+Count = 262
+Adata = a061a09024f1e03b223695d4703ee202e90e07156b95859a22e3
+Payload = b1dd81cc3b2b0efe540a3194d6fe304cd2de53db7929ebe1
+CT = da47376eeeb6026bd6e79b50ab0e682c8ca92072881a9b4ee1d66a4728b67b42602e23c8500b0115
+
+Count = 263
+Adata = 0dd513c5d8d62b723ab8b0a3aaa477e843d9149dc8a2f878e585
+Payload = fb30c2e98f3d7e4ed7431da285711d3d287884db13a474e7
+CT = 90aa744b5aa072db55aeb766f881455d760ff772e297044803c51e8c59ed13b3e5d9b489d4ea2ccf
+
+Count = 264
+Adata = 3ff59c40bd796048e586eccc23a82e4d09fc5e779f38eb4afbed
+Payload = 886f9f91a6566ceb99c39462ab675a3ae3be98f68787626f
+CT = e3f5293373cb607e1b2e3ea6d697025abdc9eb5f76b412c0f1ec270b43fc5a9811b56ccf033789c6
+
+Count = 265
+Adata = 0df7ef91f7124da867e992bcbc6fb38232ff6d5205f38768da72
+Payload = ed370d1c2d6dc03e4fae4deb9343a7d4339562cffd427587
+CT = 86adbbbef8f0ccabcd43e72feeb3ffb46de211660c710528bb4ed25940d58cba64271fe1d2e8013d
+
+Count = 266
+Adata = 6777de159c34d005b94f67c33ae4a35ebab09d9cb9c56b4c9c81
+Payload = 2f77c2eb07db14bd713c5af10c0760ea3a6ca5ff8d046d36
+CT = 44ed7449d2461828f3d1f03571f7388a641bd6567c371d99392636a5e373c1354ea9b969abb4932a
+
+Count = 267
+Adata = 75559898f4ba03c55afc25ea91aa61a93c2f8270a5fa51b6f6dc
+Payload = 360fb89429dc9b48358097d930c8561b2bd18dc0a470d1d6
+CT = 5d950e36fc4197ddb76d3d1d4d380e7b75a6fe695543a17959a7e8bc0570f19159f91fc14ac6532a
+
+Count = 268
+Adata = 5e03fc430473c5de96d68907fa506f9da353ae48a965445e1f24
+Payload = f2d8d67b9f291c3edc264893922622b2693f3e7231137eba
+CT = 994260d94ab410ab5ecbe257efd67ad237484ddbc0200e1507e559568c27a30b5676f98cc66f57d6
+
+Count = 269
+Adata = 7eee4869e77f6db12c91d1f647cad2340d33a3defaeb362d311d
+Payload = 7fd6fb81c36e44b150af10e04683b1ec9b5dda87c71ff939
+CT = 144c4d2316f34824d242ba243b73e98cc52aa92e362c89964910615920f6f3c3421a9c2bec1bec7e
+
+[Alen = 27]
+
+Key = fdf2b2c7fcb3789b4e90abe607dca2af
+Nonce = a69ddc66e63a3415f21009d53a
+
+Count = 270
+Adata = c76846da496ed87b9c0f65c6266c9a822224acde9775efb186a4a5
+Payload = d7aa4efa5d75195a400018bd38f7d8cd53fdffe88df1837f
+CT = 150d9a8b78d9c04239d66207a1f95021bbb1b7c70d7c354825d05e5a2e76a90f6fe489fd74cab2a3
+
+Count = 271
+Adata = 4efbd225553b541c3f53cabe8a1ac03845b0e846c8616b3ea2cc7d
+Payload = 5f94a2e48d348a1d56c55a659306e319c3d2ad78b9fe43a7
+CT = 9d337695a89853052f1320df0a086bf52b9ee5573973f590be6af49ce97d5e0e77c7fd5d9cc6d932
+
+Count = 272
+Adata = 7631cf7822a545daefa16a5ec43c877d475a82d5aa2d51cec7fbb4
+Payload = a44b010fc1c659eac9241a58b11a73d7ce33156ddfc54c3c
+CT = 66ecd57ee46a80f2b0f260e22814fb3b267f5d425f48fa0b924b268cab915f999aea3e1cc3a88ccd
+
+Count = 273
+Adata = e4da34663edc44370bfd8aa8315945471a893a1cc069628a071ee0
+Payload = 28d157f5741f1be057d5219711414c0638b47d165a905a6a
+CT = ea76838451b3c2f82e035b2d884fc4ead0f83539da1dec5dc368f5af8e311e67209e02dfa2613377
+
+Count = 274
+Adata = 077509eae1dc367540f87832c5780f6c5b29e180bc6c1fee38e826
+Payload = ba7432a8e34bfaa91b35c8dfd822d86850be39e63150257f
+CT = 78d3e6d9c6e723b162e3b265412c5084b8f271c9b1dd9348ad175fcad35d29396380b79a28784cff
+
+Count = 275
+Adata = a513d750ca1e8bf6cb7b8cea5204e064c15c2dc40d742b31cf5459
+Payload = 3f5830b0ce8849a660af7d58a60c19a9824a3033bb5fed43
+CT = fdffe4c1eb2490be197907e23f0291456a06781c3bd25b7493b4b3e33d325359c9c651290ce73bed
+
+Count = 276
+Adata = e439db829c1291df49fc42c2fa1a92118c2665f11e13f28dc6f11a
+Payload = e69b2a243340df5dc70b2cb05be12e5992ee36f7d9f4ca84
+CT = 243cfe5516ec0645bedd560ac2efa6b57aa27ed859797cb371f88ca5857c6d801e726a01c621a0c3
+
+Count = 277
+Adata = a12c690568114fd7a677f49d74e84fc1a6b7f7d2a08693266c0a91
+Payload = 9de35b840a69a84701ffae1b1d2bf13c34b42a57d14c524d
+CT = 5f448ff52fc5715f7829d4a1842579d0dcf8627851c1e47a0592d360fc6a46aa18c4ce5d74fa4532
+
+Count = 278
+Adata = 1813bf176a1127f4d508d7663ae750f9c4bcb84a6e26811ac60d46
+Payload = 9e2fa20bf76768a5a1467d90a048bb503a2c33bbbaa71653
+CT = 5c88767ad2cbb1bdd890072a394633bcd2607b943a2aa0648b772cef893495cf0a94e8ebf06e920b
+
+Count = 279
+Adata = cc6e9cc2699d3ba0e624e715599480d6b7dbc6eeea0d12a9236444
+Payload = 6681b1cbeceea57a828324831407280b00f4917ed52a10df
+CT = a42665bac9427c62fb555e398d09a0e7e8b8d95155a7a6e8b1851d571a1ef8aed565b784dcaaac4e
+
+[Alen = 28]
+
+Key = 7d870d7e52d3053c65eefad47764cfeb
+Nonce = 37d888f4aa452d7bf217f5a529
+
+Count = 280
+Adata = 9610949f6d23d5b1f3989b2f4e524fab4f297a5bec8ddad4f16cb616
+Payload = 109317556c21c969eda65a94176d7a11462c9ae18a865b6d
+CT = 4e6b967b1571c6d7b9e118b112b7ac949a4a175650316a242dd579cb0d201d22c86bbc7fbe47bd0d
+
+Count = 281
+Adata = 96118dbfe53434d8aed88769a535eb0c8b5849dca1c81c34626ac9b9
+Payload = 3e6c914a196e175079315b1c92b2b8a844deb472e249e3d3
+CT = 60941064603e18ee2d76193997686e2d98b839c538fed29af0dd7aef4a609f3587652173446ebd82
+
+Count = 282
+Adata = 21fc96f73975298207f818909088295d6d6861677130ca258c2174f6
+Payload = e0014147d5771b4380dc0192d45f36f7d60776d1ba47374d
+CT = bef9c069ac2714fdd49b43b7d185e0720a61fb6660f0060463e4405d45caf4836467edbf35089d87
+
+Count = 283
+Adata = 72a5151abcb55933ff7c9314f3235eba2a400121454144c2670e8359
+Payload = 0f1c6dffeda98f7a159f9cc61820bfb29910d8eaa41b751a
+CT = 51e4ecd194f980c441d8dee31dfa69374576555d7eac44537441c813e90fac775eddb7290df059d9
+
+Count = 284
+Adata = dbbf192914b1ad73666e9f5e9c22c08ca398f7524af62b1046a863bd
+Payload = c1ddd14e380cc91324cf2a381df1da1ccffd90ae436a373a
+CT = 9f255060415cc6ad7088681d182b0c99139b1d1999dd067334d9316f1f1c3142c1c9b26e5c220a32
+
+Count = 285
+Adata = 28e4b88fbf04e9897057ff5bfde7eb04fa480256817a50fa281030b4
+Payload = d4dae9c4cae92afb80f9a5c99383ff16e23a2ec942eed4d2
+CT = 8a2268eab3b92545d4bee7ec965929933e5ca37e9859e59bc0b188e33bfab29b237d6c6920ce3418
+
+Count = 286
+Adata = d9ebc1cbfab9034317132a72e0f11c341331146a59e7a2f26bf4f3d7
+Payload = 8a188d40a6e6fbb06a9f06304349a7a808b092cc2fc10b9e
+CT = d4e00c6edfb6f40e3ed844154693712dd4d61f7bf5763ad7fdde04d21b876468bd9184101b5f32d0
+
+Count = 287
+Adata = 34ad69f192ae4dcab771aeeacf01bbd32609bcbbea8ff9df31ded719
+Payload = 590c1aac30ab166b1caff748452fc146765c372e226ffc26
+CT = 07f49b8249fb19d548e8b56d40f517c3aa3aba99f8d8cd6f068c65e9d0e5f1b81c86393900e64c19
+
+Count = 288
+Adata = f5e50ce1f99ed5e9f2baa54b96ae7039234b1131e734ec190695d28d
+Payload = 16d0522b2e691e42bd80ce95e00c8a7a1fc738169e904bdb
+CT = 4828d305573911fce9c78cb0e5d65cffc3a1b5a144277a9206ab3b72c56c8df4a12dba89a2f21276
+
+Count = 289
+Adata = 9b1e7e52ea1a12444d884866e11dcf367b70b816460936fdaebba36d
+Payload = 0bddf342121b82f906368b0d7b04df1c682ecd4c2b2b43df
+CT = 5525726c6b4b8d475271c9287ede0999b44840fbf19c72960170ca7b16d23537eeb3034105334699
+
+[Alen = 29]
+
+Key = 8fcac40527c0e7ca8eaff265ca12c053
+Nonce = ae9f012fd9af60a400e20b1690
+
+Count = 290
+Adata = 9ce65598cd1f86afc9aaaf172809570cc306333c25523f863c6d0e0154
+Payload = 78d1e96af8cebdcc7e7e2a4ddcfa34f6cf9a24fb85672ad7
+CT = 9adb9a95a9379ad795d8d3ffd4e37a045160d6d727f974a6cb3b5151f327e65447e52c7525562c91
+
+Count = 291
+Adata = e7c78ef4c4b959ee00cb1a09d71221a43892ef8ad705edd27ed85d03a3
+Payload = bc59f18c8473941abc681a92741ab5ee13679829f542b8f4
+CT = 5e538273d58ab30157cee3207c03fb1c8d9d6a0557dce68534e5b08e27d8f5eeef0f064ff620652a
+
+Count = 292
+Adata = f1bce6f2a4bdd3a07ebf5f8d47f931d27e7e63389d70e1059f701216be
+Payload = 5575d950312c14c89ac609dfb0b2fd1af732bb6aae5e8651
+CT = b77faaaf60d533d37160f06db8abb3e869c849460cc0d82044c0a96baae318f4714f0206812516b5
+
+Count = 293
+Adata = 3da3bb091016e54477dae88af1c84c1a51b59c1bb49a05deb6f32064e6
+Payload = df5947d8c6094ccc25816639ec42214b28731bfd7b8312dc
+CT = 3d53342797f06bd7ce279f8be45b6fb9b689e9d1d91d4cad4e7bdce2dc6aae24178aab6984f31028
+
+Count = 294
+Adata = c4cd183071c37a8157c6930a7d4d530cf4b7eb021682327810bd48209e
+Payload = 2fbb6dc235761875411ef59ae06110df8f15f66b721b0fd6
+CT = cdb11e3d648f3f6eaab80c28e8785e2d11ef0447d08551a7f18ece8260bd56ecdee768022d0dd8d1
+
+Count = 295
+Adata = 0e0fece7b6b659b642668e8ba3dca330523e70279155f485f3f6f8041e
+Payload = cd149d17dba7ec50000b8c5390d114697fafb61025301f4e
+CT = 2f1eeee88a5ecb4bebad75e198c85a9be155443c87ae413f6f0fb3b7440b84ddc3cc53819c2e93be
+
+Count = 296
+Adata = a35c6f70f637a9a5e6f215c694fdf65b6fd85f794ed3eaa1bc19abe592
+Payload = 030390adb572f2bd2a6a4454fd68236cd1d465574328aa00
+CT = e109e352e48bd5a6c1ccbde6f5716d9e4f2e977be1b6f47129ca778c51f9320f121dd803ece8d5da
+
+Count = 297
+Adata = c2992096828325820e2d7acaa17ac789b6830ec3128dd7f904398afbec
+Payload = f2d9cf953c8d3a051d9b3eae4307a3cb4fffaa2435b49586
+CT = 10d3bc6a6d741d1ef63dc71c4b1eed39d1055808972acbf79c223a5ad65120bfca4a5992e5ebc6fc
+
+Count = 298
+Adata = c023763a285ea934bc5bc7ddfc2aefe2b3f9eafe7b87c61383dcc07990
+Payload = 4b92e8d2ffaa4af8f3e0ac037a900bd18e195f490a3d71e1
+CT = a9989b2dae536de3184655b17289452310e3ad65a8a32f905c3bc4f618ffb3a159f4e2d0622cea6e
+
+Count = 299
+Adata = 0a39ec0163c7aeb1b4fbe7cb4fa5b0592fade70f430e23730a23ed4160
+Payload = 7c0e6a0d35f8ac854c7245ebc73693731bbbc3e6fab64446
+CT = 9e0419f264018b9ea7d4bc59cf2fdd81854131ca58281a376f099dce6e18435fba4d26c1e93bda0c
+
+[Alen = 30]
+
+Key = ddf9f150cc3f1c15e8e773663c5b061c
+Nonce = 98c5036b7d54da9a1177105600
+
+Count = 300
+Adata = 20c5ab290e6d97f53c74121951f39ba865b3acc465fa3f0fb8a591622277
+Payload = 79d8841ab83279724ce35e1a8abd4e158168dcf388ab4c3d
+CT = d00d29396ffa9e691290d746527777bf96a851f306d4da0b1816df1e0e82bb7bc8105930ad6a2232
+
+Count = 301
+Adata = 0e205a4dc5d5ead0d9ff7f182dc140fc49511c01b0fdbc7e6d6cb5fdf027
+Payload = 88b2572fbe7cf2b46df04db476ffedb41778ae2eb3c3aae4
+CT = 2167fa0c69b415af3383c4e8ae35d41e00b8232e3dbc3cd2df823c8ccd466807f2bd1c4032f0cfeb
+
+Count = 302
+Adata = 48043560d60381e83c11d4bc9d997d3ee2add6b0524b779c62dfaa73ce0a
+Payload = d44bf28b010e076b45db1b053af03db718b60748da51db1f
+CT = 7d9e5fa8d6c6e0701ba89259e23a041d0f768a48542e4d2931f5be8c9965345c760c72cc1b7908d1
+
+Count = 303
+Adata = f0729a8a2fd073699ab87b521cbe0420b43529556a505f5f87874d1a053c
+Payload = eab8cffb512eabe267cd64353552513defe97c2d10f35503
+CT = 436d62d886e64cf939beed69ed986897f829f12d9e8cc335381d94a828a95872ebdfda8a4c6a196b
+
+Count = 304
+Adata = fc2cd69bb61223f713e33a5071d09bf2783640c307c22d836dd94952dd37
+Payload = 001056926546c261fbbdf92b94498e038c2bcfd0b6345497
+CT = a9c5fbb1b28e257aa5ce70774c83b7a99beb42d0384bc2a163931808533f4f70d7a78242ced110eb
+
+Count = 305
+Adata = 8f653c5c003c807d16d17f833eebb97c9c2f0e5aae3780a52ce53a6c33f7
+Payload = 29ffaef9415fd300127ffd26ef324083a9d90e0f60e2ab4f
+CT = 802a03da9697341b4c0c747a37f87929be19830fee9d3d79f34553198f8e40fde6473f9cf04f1de6
+
+Count = 306
+Adata = 8d05e7d3077151c6d9378cb08e049e4d7c28a908f7f7c079c46ff92cd01b
+Payload = 9874dc5ca1b541f7b21c7b3860fa6b0c3ab1b712ab0fca98
+CT = 31a1717f767da6ecec6ff264b83052a62d713a1225705cae0fac20e8d45d2b0771d140b5e4a47c87
+
+Count = 307
+Adata = d4feb3ea76ac2945651f557406f3f38a2d7e9232ed55ff4eaf1201dd8255
+Payload = 1e01c7128c821fb9c971a27fc7c6f9bb902fa735de583b8a
+CT = b7d46a315b4af8a297022b231f0cc01187ef2a355027adbcd3cacfe4281e52d79e60eeb38319bc3a
+
+Count = 308
+Adata = 7cbb4ae995a3367a256cafd11cd6c6cab5bf3252fa97f27a8a1434ca9a27
+Payload = 51cd306fac7d20e3c7043eae3a6dfec046c5c24a666a0723
+CT = f8189d4c7bb5c7f89977b7f2e2a7c76a51054f4ae81591158f0d7646a799b14288bb2f354b5d8847
+
+Count = 309
+Adata = bd40b06a4beded2be3d176266b10772c7fa2949f0a9b20d613af90c2daf5
+Payload = fc5b26befc633a3e8ace011aa7a42bd0258a9f3dc14fc1c8
+CT = 558e8b9d2babdd25d4bd88467f6e127a324a123d4f3057fefd7f95e1d331e700aa9ef83f09b689fd
+
+[Alen = 31]
+
+Key = b1dc81d116d94f5eced526b37c004b95
+Nonce = 97c8f69fb91b17299461fd8d63
+
+Count = 310
+Adata = f8b08aa83bed09ca342249b2cf9e2b45a89dcfb8711a120395e455921af481
+Payload = 54390715b6e7c7bd51a234db059a51ba030cf22ee00b7277
+CT = cb629994c3418a662a8cde1b5f4d99aa7df66e24c53dc6df11297930fd44c63675b7cca70671ef4d
+
+Count = 311
+Adata = 0351c969dd38eeaa4b9b0000e346eeb1a2cd462033c59d9e6e3331822045cd
+Payload = 65b5e856a8cf35dffd42c5ba105cba4c434aa1c2a0390352
+CT = faee76d7dd697804866c2f7a4a8b725c3db03dc8850fb7fa7e77f5566ca2fd9293835bceb461dbaa
+
+Count = 312
+Adata = 5db8b6bc16740680f78fba917733a6899cdba5e4c10a8058963d1265681eaa
+Payload = 9a7685e3daac43ccf22cad0df900ba8acddc5d420846118d
+CT = 052d1b62af0a0e17890247cda3d7729ab326c1482d70a525ec2cf9f5d35521c1c000685e49d2ed42
+
+Count = 313
+Adata = e7d6024611210da0cfb90a9955195aa0a0539280a3a7c792a1540930daae2d
+Payload = c18d9e7971e2ae5fc128777086338fbe194443324e2d2cd1
+CT = 5ed600f80444e384ba069db0dce447ae67bedf386b1b987966f33dfb44ae413283b238616c6b99fb
+
+Count = 314
+Adata = 77a878c9c76f3e6a4ddd330d1d8828949d08e0fedffe0d8e2e557b29e7c78c
+Payload = fcf8982f7342f1b953658453cd5ea413700eff00f1ee7d6f
+CT = 63a306ae06e4bc62284b6e9397896c030ef4630ad4d8c9c731df6fc6b4cf0b6332936ed7cfe9455e
+
+Count = 315
+Adata = aa540554ee80dbffa475f702d862d6b60e0a4090792420a26d02926517723e
+Payload = 0d5690d2a7083ad6daf22b308314b8f5363aca77ca72835e
+CT = 920d0e53d2ae770da1dcc1f0d9c370e548c0567def4437f67c8162a815f2809601ad02595e2e0ff4
+
+Count = 316
+Adata = fae86f95dd06fb7fbae63a646615555aec8153dc328bdf79da5d4cc9677ed6
+Payload = f6e313cc35e8f8812b10a44f8ad00b6893f8084d942effe0
+CT = 69b88d4d404eb55a503e4e8fd007c378ed029447b1184b487fcaa11bdeab86f60f9cd0a2b45cee1a
+
+Count = 317
+Adata = fd525302d2fb246a47cf4e3a27808bda89d8488cf450f1a1c7df6eedd810ee
+Payload = 91e961ea2eb750577c5137c609602dbfcc4c07955ba429ec
+CT = 0eb2ff6b5b111d8c077fdd0653b7e5afb2b69b9f7e929d440a86a810881bd969744ad80f579400f1
+
+Count = 318
+Adata = 767b1bdf9793a512d3a84e99ef77b43011a3bcb8de4cd375dfe47a79293e01
+Payload = 98438c4411bead6f30c89ead762a12bf39391d3652b78b7a
+CT = 071812c56418e0b44be6746d2cfddaaf47c3813c77813fd2250ca00d3231819ecdf501ad39c864f3
+
+Count = 319
+Adata = aac7014f606df6feec415a75e29015891007f07518c955875fbf5619262ff2
+Payload = 540cb00c0eface3d1b2d632d80a642f53c78ff672a1ff6ff
+CT = cb572e8d7b5c83e6600389edda718ae54282636d0f2942571224d1d0294d46981d7dc39114a693d2
+
+[Alen = 32]
+
+Key = 5a33980e71e7d67fd6cf171454dc96e5
+Nonce = 33ae68ebb8010c6b3da6b9cb29
+
+Count = 320
+Adata = eca622a37570df619e10ebb18bebadb2f2b49c4d2b2ff715873bb672e30fc0ff
+Payload = a34dfa24847c365291ce1b54bcf8d9a75d861e5133cc3a74
+CT = 7a60fa7ee8859e283cce378fb6b95522ab8b70efcdb0265f7c4b4fa597666b86dd1353e400f28864
+
+Count = 321
+Adata = 55a62968c222a8501d1ae56a9a815667f8a9554607b7c56e6753f8fa92a4d054
+Payload = 764dbefb42644d18d23e5e4568685d14dbacfa418d36c4ef
+CT = af60bea12e9de5627f3e729e6229d1912da194ff734ad8c4423862a715dda2f63a4197f894515803
+
+Count = 322
+Adata = f8436e35b7a1c810ac6aabe8e2d48a3678d19e1e96337dada514ee5fc075fce4
+Payload = cecef24b62676a5623bedae8087b9b05d7e22b41a14dd2d5
+CT = 17e3f2110e9ec22c8ebef633023a178021ef45ff5f31cefec200f190bd700f6108f9959f6d12f0f0
+
+Count = 323
+Adata = 548e2152f3a15b8fb81dc01062d99f7b4fc8f074e5cbdc1030c97f8ccc02ec3f
+Payload = 53c164a4990c6e0637267ff2556c1542712fc584f6ff7458
+CT = 8aec64fef5f5c67c9a2653295f2d99c78722ab3a088368733a66ebc4e0777a6fc140a51e04a10f86
+
+Count = 324
+Adata = d100f1d08ef1e3eda4aef22cd970c2b785c4ff9b523c401b4064324aecf7f2d9
+Payload = 15681d2121ac56a63b9d0a38b9c4eccf84fdb746d32c14b4
+CT = cc451d7b4d55fedc969d26e3b385604a72f0d9f82d50089fb810cdc08db0a9966dffeb43ba26446e
+
+Count = 325
+Adata = eece934a807c9f21487cd810f15fd55d7bb4421882333ff2c43b0353de7fc5a6
+Payload = 412a8ef924ca156de860f147575e5731825f0a3759688928
+CT = 98078ea34833bd174560dd9c5d1fdbb474526489a7149503cfc5b397578f8d02a0b936ffac29b99a
+
+Count = 326
+Adata = 86311ff444d9be90459b6ee3652e1705ed0b5cdac3d27293ddea3378fb686ee5
+Payload = 54ba8a020d0876fa369dc32e8627f565ba3dda862ea0bcfe
+CT = 8d978a5861f1de809b9deff58c6679e04c30b438d0dca0d52c3fcd6d618c260d51724126f257534a
+
+Count = 327
+Adata = ab6efbc44a8906d5c067eaed71af467e130aaf170827a58beb03c55069674125
+Payload = 7a15506fd1dae444d77b2a3ae7b57a8d5b4f10e25a9f78e2
+CT = a3385035bd234c3e7a7b06e1edf4f608ad427e5ca4e364c9bf8b2821920640b992b00cd1c9618025
+
+Count = 328
+Adata = ddb640923d083725587aced81ae1d7409983d1f1e3ccc8dcf94376dc1bbcae8b
+Payload = b18a61a89cd698f32e059b7a2a9f62a46be2c248790a9915
+CT = 68a761f2f02f30898305b7a120deee219defacf68776853e4cd52d41a968284af8907ccbb4588cc0
+
+Count = 329
+Adata = d95ec4a6f594be1ba39fa1aa933dc0a5dafff5ce44509577ebb3a3e8084c4401
+Payload = 16ee3bc9ec8b4448e292b8973618e02a99da1c348539d5c7
+CT = cfc33b938072ec324f92944c3c596caf6fd7728a7b45c9ec47449a5cb4943ff2846c589b7c98ef49
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT192.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT192.rsp
new file mode 100644
index 0000000000..1a7a5875fe
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT192.rsp
@@ -0,0 +1,1823 @@
+# CAVS 11.0
+# "CCM-VADT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Plen = 24
+Nlen = 13
+Tlen = 16
+
+[Alen = 0]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886
+Nonce = 15b369889699b6de1fa3ee73e5
+
+Count = 0
+Adata = 00
+Payload = 39f08a2af1d8da6212550639b91fb2573e39a8eb5d801de8
+CT = 6342b8700edec97a960eb16e7cb1eb4412fb4e263ddd2206b090155d34a76c8324e5550c3ef426ed
+
+Count = 1
+Adata = 00
+Payload = 296fbda0017351491c2187273fbde2c3a427170e430a703c
+CT = 73dd8ffafe754251987a3070fa13bbd088e5f1c323574fd2167ee33e75d05023a7d63c770cfef2ea
+
+Count = 2
+Adata = 00
+Payload = eb61c284fe009921039ef6a9ce50e702823e44b35357923f
+CT = b1d3f0de01068a3987c541fe0bfebe11aefca27e330aadd170647420f79c0d91cbbd69b806fe96a5
+
+Count = 3
+Adata = 00
+Payload = ffeccc6460d23fdcc387c697e75dbb959b78013a8282eaa4
+CT = a55efe3e9fd42cc447dc71c022f3e286b7bae7f7e2dfd54a8a3ef2324754539ac774872282534386
+
+Count = 4
+Adata = 00
+Payload = 90958d7f458d98c48cbb464c74bf495a49846dd468c514e9
+CT = ca27bf25ba8b8bdc08e0f11bb111104965468b1908982b07e292cd0e32535a848e327bc53cdae94c
+
+Count = 5
+Adata = 00
+Payload = a4fad5205d38206e25097075687ca86032b95b3fe7e82a07
+CT = fe48e77aa23e3376a152c722add2f1731e7bbdf287b515e9bb21701af36936be5f62d02b84df87c3
+
+Count = 6
+Adata = 00
+Payload = b37114c65372b052cbeecf83d05a5da44f7b5bbff7d986b5
+CT = e9c3269cac74a34a4fb578d415f404b763b9bd729784b95b7da7f975367be24341e4af51b8bb156a
+
+Count = 7
+Adata = 00
+Payload = 9c0f0426f171ff18b2a4392f61fb4ee4a44c476fe03dc930
+CT = c6bd367c0e77ec0036ff8e78a45517f7888ea1a28060f6de360c6d50a96f316eda0b216cbb6380ef
+
+Count = 8
+Adata = 00
+Payload = 7b6e0a480a40585545b0e940e8d97c9ec987bd3c0e9c16a8
+CT = 21dc3812f5464b4dc1eb5e172d77258de5455bf16ec1294634cd1bd98e8137b578a174e39efe09b8
+
+Count = 9
+Adata = 00
+Payload = 34dac6dbc28be62332a6935efc122e37b26ee100eb4033f8
+CT = 6e68f4813d8df53bb6fd240939bc77249eac07cd8b1d0c16909a895a3b08b63d7a2a1e75d25e7861
+
+[Alen = 1]
+
+Key = 9748798c0f3cc766795c8ce0e4c979c1930dfe7faefea84a
+Nonce = cdf4ba655acfe8e2134fa0542f
+
+Count = 10
+Adata = 67
+Payload = 100fa71462277d76ca81f2cfdb3d39d3894b0ca28074a0f0
+CT = 36e2415b4f888a6072f260d7e786d803be16f8b9cbee112d7ff74e3b05b7d7c13284573bd3e7e481
+
+Count = 11
+Adata = 17
+Payload = 0217eb6778691f8dfe2d0e5241f05fcbcf97b9171f4de3f0
+CT = 24fa0d2855c6e89b465e9c4a7d4bbe1bf8ca4d0c54d7522d3ee7ce845f85dfc770d96dee9ca54ccd
+
+Count = 12
+Adata = dc
+Payload = a78b7bc6c1a7250c5fc236f2a8343725a9a7bd3ca81b53e4
+CT = 81669d89ec08d21ae7b1a4ea948fd6f59efa4927e381e239dc14ddd8ae0aa5d810040a8d1d4da1e9
+
+Count = 13
+Adata = 0c
+Payload = 390c808d998582793bb10ee60568eb8d975c51d68b4e4da9
+CT = 1fe166c2b42a756f83c29cfe39d30a5da001a5cdc0d4fc746b40dec7e647720f1f5e8474bf570c2f
+
+Count = 14
+Adata = 3e
+Payload = bcd9747fb54184b61b2e9e049caa75e22006e250f3722c0e
+CT = 9a34923098ee73a0a35d0c1ca0119432175b164bb8e89dd3c10c4aac45d90119cce490cc8681a49f
+
+Count = 15
+Adata = 7e
+Payload = d0342e3cd2c1142b642da7297ee3b9978cec405e6810f12f
+CT = f6d9c873ff6ee33ddc5e353142585847bbb1b445238a40f2f9a95091d2cab7d3d9fa3e10d3e67ac9
+
+Count = 16
+Adata = e3
+Payload = 7fab91d1aa072947d22f0dc322355a022fe7f0747f4a184b
+CT = 5946779e87a8de516a5c9fdb1e8ebbd218ba046f34d0a996180f7818c373e89f7ff3003f53260060
+
+Count = 17
+Adata = 3e
+Payload = e487143dc4d98dcc6a2dfe6ee0f85d565d1f46bb0fafe62a
+CT = c26af272e9767adad25e6c76dc43bc866a42b2a0443557f71905f581585e59e3c8c038b5bf966559
+
+Count = 18
+Adata = 3b
+Payload = 976b489244ed6789a34251500057d1d4a3229367a42b9066
+CT = b186aedd6942909f1b31c3483cec3004947f677cefb121bbea56569c34f8d9eea23e85fec18cfc51
+
+Count = 19
+Adata = a5
+Payload = 71efa75961dfd60ad533082a8cfe111214eb02573adc4591
+CT = 570241164c70211c6d409a32b045f0c223b6f64c7146f44c212da23548f2ca4e9a8a07962be6422c
+
+[Alen = 2]
+
+Key = 393dcac5a28d77297946d7ab471ae03bd303ba3499e2ce26
+Nonce = fe7329f343f6e726a90b11ae37
+
+Count = 20
+Adata = 1c8b
+Payload = 262f4ac988812500cb437f52f0c182148e85a0bec67a2736
+CT = e6d43f822ad168aa9c2e29c07f4592d7bbeb0203f418f3020ecdbc200be353112faf20e2be711908
+
+Count = 21
+Adata = 9db5
+Payload = d5982c462ad40458660cd7b120ce07fce9afe812caedcebd
+CT = 1563590d888449f231618123af4a173fdcc14aaff88f1a89015e5cd97b7dd3d981321ae0b2d99e1a
+
+Count = 22
+Adata = 69cf
+Payload = 1a95f06b821879df3fd3ac52fc99a7c1d3e9775263b7d036
+CT = da6e85202048347568befac0731db702e687d5ef51d50402bf3e75863c7acd2699caba3cc301f4b2
+
+Count = 23
+Adata = 6c6e
+Payload = 373c157e59b934a1afb57d4c5dd9ca7fb736b206a6210bef
+CT = f7c76035fbe9790bf8d82bded25ddabc825810bb9443dfdb5d6a8f7a9f52a8038aa9dc1bdc9ed876
+
+Count = 24
+Adata = dafa
+Payload = 26e10a2ed8cc883a6552aee162c5542ff8bb8e758a1975f8
+CT = e61a7f657a9cc590323ff873ed4144eccdd52cc8b87ba1cc8a15603f10cbfdb041f8b2b12cc8f037
+
+Count = 25
+Adata = c8b1
+Payload = dd235b05c15479dfe0326ba206ac784eca50038bbeb35d32
+CT = 1dd82e4e63043475b75f3d308928688dff3ea1368cd189061278bf62ba6a4819513d49fdcdb45480
+
+Count = 26
+Adata = af48
+Payload = a0818342a5cae4a90ef281d3d1289d83f273f418a545fcbf
+CT = 607af609079aa903599fd7415eac8d40c71d56a59727288b8b4d00309b50f9ea72f8105c94475b52
+
+Count = 27
+Adata = b1cd
+Payload = 33c0d06b6583bb4d15b4a07364c4be70ac6e72795c3dae0f
+CT = f33ba520c7d3f6e742d9f6e1eb40aeb39900d0c46e5f7a3b220ba58e97936612c4183ba86705b2f9
+
+Count = 28
+Adata = 649a
+Payload = 3ba11282d61fe36e38cab7b559c2fd9cbe8bf7eb5863bde9
+CT = fb5a67c9744faec46fa7e127d646ed5f8be555566a0169dd87d602dc85bb260fb3df1221e2fbd10c
+
+Count = 29
+Adata = 593c
+Payload = a97faefcae36732fcfe47736c2334ea7d411bf7638b0c019
+CT = 6984dbb70c663e85988921a44db75e64e17f1dcb0ad2142deb3835b7eecad6dac9785ad1d370ede4
+
+[Alen = 3]
+
+Key = a74abc4347e4be0acb0a73bb8f7d25c35bae13b77f80233a
+Nonce = 6a850e94940da8781159ba97ef
+
+Count = 30
+Adata = a4490e
+Payload = 6372824bf416cd072a7ad0ae5f9f596c6127520c1b688ab4
+CT = b14a07bdc119d87611342c4c6935c5786ff1f9ae2eb49e6191c88a3cb4fbafcb8a4a157d587d7e39
+
+Count = 31
+Adata = 5cad2e
+Payload = 295f4f3417a77fcf0bbda17b0fd629ad57a6086573c87eb1
+CT = fb67cac222a86abe30f35d99397cb5b95970a3c746146a64235c34d1390bba5b008c3fb29c2df958
+
+Count = 32
+Adata = ebdf4c
+Payload = 86f354a505de941d34cd98e3af3706d56a938ab9a2797182
+CT = 54cbd15330d1816c0f836401999d9ac16445211b97a565575a733bba0a6992d0664dc77d2b5d194c
+
+Count = 33
+Adata = 7c0d70
+Payload = 88c3bfb546abe2f6bfc92a7c56c627e24ab92a8a87a6b43c
+CT = 5afb3a4373a4f7878487d69e606cbbf6446f8128b27aa0e90902a31b15eed99c2dc4ed1bf11cad96
+
+Count = 34
+Adata = 8fa501
+Payload = 75d4216bad77943bfe82be216157843b0da0fd16eeee8471
+CT = a7eca49d9878814ac5cc42c357fd182f037656b4db3290a42f25595ae00103d4eb20288158132e7d
+
+Count = 35
+Adata = b7aca7
+Payload = bf1401e8dcf6f681ed6dd74c7e23b7e54b384608b0e5ec52
+CT = 6d2c841ee9f9e3f0d6232bae48892bf145eeedaa8539f88760e67693b509ea4795b7da32c5c5d17f
+
+Count = 36
+Adata = 1f283f
+Payload = 7e623e7ef7d0a678b5d22a8402d89220f4f1bf759e3084dd
+CT = ac5abb88c2dfb3098e9cd66634720e34fa2714d7abec900880ef8ea380a1a0a38b2c20288e637a9f
+
+Count = 37
+Adata = e93f31
+Payload = 14f80e7a6298d85d31fb80376a394a8f88b0ae47f00450c7
+CT = c6c08b8c5797cd2c0ab57cd55c93d69b866605e5c5d84412d553aafe8536385d34c412c14d3a1563
+
+Count = 38
+Adata = 27e9a5
+Payload = 3330df12249639961f562a74b34f60b0a8bc7c783f6572fd
+CT = e1085ae411992ce72418d69685e5fca4a66ad7da0ab96628f594d366c8fc826ce58309e9053c27f7
+
+Count = 39
+Adata = 72d566
+Payload = 1a1860ac8c11c5d262f8141738cae8ff91ca05906dc98bb4
+CT = c820e55ab91ed0a359b6e8f50e6074eb9f1cae3258159f61cdd6ac6c42cd3d11e0344a9c1001e253
+
+[Alen = 4]
+
+Key = df052e95aea3769a433ce4e4e800b8418649bbe8c6297eb0
+Nonce = ba356d392c3f700f4f2706a4ca
+
+Count = 40
+Adata = 8ffc0e3d
+Payload = e8c1a89228d8212f75c136bab7923a89f9fea18e781cb836
+CT = 66b5d782323925e1bd0a8413a9a5a881356453d5df2cbeb199b2e1e803550dcdde55fd66ecb45edd
+
+Count = 41
+Adata = 2b4f9cfc
+Payload = a12c6324e022affd61b7e0d8cccbeb23e2e6c65355c1d586
+CT = 2f581c34fac3ab33a97c5271d2fc792b2e7c3408f2f1d3019e8fbc507244ba234a0581dc69962a66
+
+Count = 42
+Adata = b4de3039
+Payload = 7cccb26f1dd227bc77458b99fd9e00f8e801adaece7bfcd1
+CT = f2b8cd7f07332372bf8e3930e3a992f0249b5ff5694bfa5628a2857099af20a4ae08e687bdb02c75
+
+Count = 43
+Adata = bc59f18c
+Payload = 692b53c1355475c71ceff0b0952a8b3541b2938270247d44
+CT = e75f2cd12fb57109d42442198b1d193d8d2861d9d7147bc3e33a6416e387d9e571a1954471ec9cc7
+
+Count = 44
+Adata = 4fd9fd39
+Payload = 7e3e755e25bbe78d4a7770f9356ab9f4ff1bbfdba46383f5
+CT = f04a0a4e3f5ae34382bcc2502b5d2bfc33814d8003538572180f9735f994c8335e593f30b331a920
+
+Count = 45
+Adata = 296cd04c
+Payload = 997b712cd9295dc43cc19b40679f218c27af3e8c638d2e5d
+CT = 170f0e3cc3c8590af40a29e979a8b384eb35ccd7c4bd28da91990fa537d2657d01f66872ba9af22f
+
+Count = 46
+Adata = 88037d3e
+Payload = 577981ccb6c893dfe6405075fcb41507de7f9bfda860791f
+CT = d90dfedcac2997112e8be2dce283870f12e569a60f507f984915cb93e84028c7aedce1a2dadbb6bb
+
+Count = 47
+Adata = fc4bb852
+Payload = 37ba9f57ec230675ce060ba3d388095adf15907aa0b0673d
+CT = b9cee047f6c202bb06cdb90acdbf9b52138f6221078061ba25baa6385af8d7b807a2d2ab19aa4999
+
+Count = 48
+Adata = f40ec14f
+Payload = 401e0cdc132a9e4a9b5ceeed3c181f67e5203ea69508deff
+CT = ce6a73cc09cb9a8453975c44222f8d6f29baccfd3238d8786adcdb44870e1105b7318d8bad0af957
+
+Count = 49
+Adata = 90e2c63b
+Payload = 0234dae5bd7ae66c67ff0c1a3f1a191a0d7bceb451bc2b7d
+CT = 8c40a5f5a79be2a2af34beb3212d8b12c1e13ceff68c2dfa8b079fb71d45bd985bffd343c3362653
+
+[Alen = 5]
+
+Key = 16d345606a315ad2406abbcb43cd8cabe948107ba6d17a72
+Nonce = d4ef3e9e04f1b7f20ffc5a022e
+
+Count = 50
+Adata = a468f08d07
+Payload = d3bef460223c81e4579c9d1d463ac5e0881685de1420a411
+CT = abb85db49a9b1c8724ecbc734cc8373bd20083cfa4007b1cfe4d3a3bb25f89f692884be230c6035c
+
+Count = 51
+Adata = 4497649a54
+Payload = 81ad3f386bedcbf656ff535c63580d1f87e3c72326461ee1
+CT = f9ab96ecd34a5695258f723269aaffc4ddf5c1329666c1ecd05ae56511a230627e02d066c52a919e
+
+Count = 52
+Adata = c30ddd994e
+Payload = 84b88264afec06b370dfcebf5e1d3e2c1f005faf248b3215
+CT = fcbe2bb0174b9bd003afefd154efccf7451659be94abed188ef92fc17dca026f1ac1eaf78a05017c
+
+Count = 53
+Adata = 9573270f7e
+Payload = 9e4c8aa9b58a8eabc5586892f5541000b43f17d9a051a040
+CT = e64a237d0d2d13c8b62849fcffa6e2dbee2911c810717f4d38eddff1e60e2d9ae74a936364b8df21
+
+Count = 54
+Adata = 40336790fc
+Payload = 260f67122dfbe03365bc9e35e9d4ac4b2eb150eddb30857d
+CT = 5e09cec6955c7d5016ccbf5be3265e9074a756fc6b105a70aa3d464ad89cae59b474d019a5a7605c
+
+Count = 55
+Adata = 0b310c8529
+Payload = 1d55e7352bd895c4ef77389a7225c664f72b38c8de778d57
+CT = 65534ee1937f08a79c0719f478d734bfad3d3ed96e57525abeab0c520e64939c6950c0fa406eafb1
+
+Count = 56
+Adata = 5756b2c681
+Payload = fbd315e1f5bd0f0e60ee6684c88f3543452c62ea0701d11d
+CT = 83d5bc354d1a926d139e47eac27dc7981f3a64fbb7210e10d22d339c382343bf39c239fd64c2a64f
+
+Count = 57
+Adata = 3b919e3665
+Payload = d68d6556c5a5b1f5a123389b3ce966d5837cb8fcf5accfff
+CT = ae8bcc827d022c96d25319f5361b940ed96abeed458c10f2fcd6b562a1b6aa10be92a81f99ed540c
+
+Count = 58
+Adata = 58749b643f
+Payload = 062cb6962fa5b3a6239b95f3a51b478a1f32b081dc538a80
+CT = 7e2a1f4297022ec550ebb49dafe9b5514524b6906c73558d4b853022237d94d253b375bf2150e699
+
+Count = 59
+Adata = a5d50c008b
+Payload = 08c62ff9bd7bcf189f530d5065f8764532d2692f69858483
+CT = 70c0862d05dc527bec232c3e6f0a849e68c46f3ed9a55b8ee7aee0d403b2cf6f8b993eebd6b93615
+
+[Alen = 6]
+
+Key = 1c476cfd7dd300d961fd3f24a6fe0e80742b00851676ca63
+Nonce = e300fc7a5b96806382c35af5b2
+
+Count = 60
+Adata = 28130f938c45
+Payload = 6f3938932b5c1280311e892280d8a822a828a0be7fdb1bcd
+CT = df48662fe134e75a85abc2cece2c3b6236c88a70fa792e9beadc9601adf9fbdf4e3e94b395b0a332
+
+Count = 61
+Adata = f600024a7bf9
+Payload = 0af7345e71f4e8886503395ade0b0296a5856e086638b06a
+CT = ba866ae2bb9c1d52d1b672b690ff91d63b6544c6e39a853c0692a40a6aba8d7c5addae21de90fea9
+
+Count = 62
+Adata = 4eef510d1f48
+Payload = 37f57772f056f45a5ce9f46d27be1858980c8935b9c839b7
+CT = 878429ce3a3e0180e85cbf81694a8b1806eca3fb3c6a0ce122f64becb581070411957e632e19bb8f
+
+Count = 63
+Adata = 4c9c76b6fad5
+Payload = 8bb10c82bcabb7fb2b169252ab443b01df217cf908b8c241
+CT = 3bc0523e76c342219fa3d9bee5b0a84141c156378d1af71708c59f83aa97d069b6d83d9387051f43
+
+Count = 64
+Adata = 5572ecfc7e53
+Payload = d1ccb4654a22b1afe32f3d3035fdccd87e9cbed83c679007
+CT = 61bdead9804a4475579a76dc7b095f98e07c9416b9c5a551f04686ee1d7b985d903f1de6cf78f8f4
+
+Count = 65
+Adata = bffdf9d20d74
+Payload = f990a8f6ba14065d48665db36eb470c49f38e2b6376a9bde
+CT = 49e1f64a707cf387fcd3165f2040e38401d8c878b2c8ae88f8118f1b9f39b51965ae9ef1bdb40111
+
+Count = 66
+Adata = 3f27e678c580
+Payload = f8c7d89639ab742a8bcfffe776e868d671e1fbdd55807a8a
+CT = 48b6862af3c381f03f7ab40b381cfb96ef01d113d0224fdca3236d02f33f49759f281315e449bfef
+
+Count = 67
+Adata = 1294cb9db5f5
+Payload = 8601cfd7d935e8a8487b9c39d55ca27096255f2eb9e009e3
+CT = 3670916b135d1d72fcced7d59ba8313008c575e03c423cb5e74770a07c242c3854ceb242dadc1976
+
+Count = 68
+Adata = cec271332b75
+Payload = 77c85b8022f58337b364142a2474fe5cfddb31cfca48af46
+CT = c7b9053ce89d76ed07d15fc66a806d1c633b1b014fea9a10d6c65f19175cfa49898655ccdddb864a
+
+Count = 69
+Adata = da06bd140502
+Payload = b0f2db802475fa70af02057373844f637a3244cda4b4f93d
+CT = 0083853cee1d0faa1bb74e9f3d70dc23e4d26e032116cc6b458822e49e69031431b3eea872a72eb7
+
+[Alen = 7]
+
+Key = 79d1e38a70df1cf239be168833dcd0570bc8f37b3aa26c37
+Nonce = 8229d6d7e9e21fdc789bff5dcf
+
+Count = 70
+Adata = 076887d2abe900
+Payload = 83c24f3a77b83b4ef45277ba90225f3ba1722312f52b1a07
+CT = 19d880f1d959a68f162de243d4a45747ace704613359b27218d1531a066de60a95d2924a6910e990
+
+Count = 71
+Adata = 7535bcc6fbd1a0
+Payload = 24f85ef683cc521387f484bc0b2ad9172f61884c09a9718c
+CT = bee2913d2d2dcfd2658b11454facd16b22f4af3fcfdbd9f96dbf58406020e6df7b312b6825127f9a
+
+Count = 72
+Adata = f4f96d7b4384a3
+Payload = 212bedfa06b5e1a2c3a2f31f6f791dd9df8ef26077821c0a
+CT = bb312231a8547c6321dd66e62bff15a5d21bd513b1f0b47f64dd755177efc87f8b1daf1fd88e51a6
+
+Count = 73
+Adata = 3b7e3d9c1a7fa2
+Payload = 8b9036914bb0f440c8dbcfde9b9547be5e5ef1f56492c75e
+CT = 118af95ae55169812aa45a27df134fc253cbd686a2e06f2b0be31cab31f1a20805d5c07dc516d707
+
+Count = 74
+Adata = a8c35fae8912d6
+Payload = 50f3f3a91bf6fd9573d5ef54b9bb5805205b2f9865d81fd7
+CT = cae93c62b517605491aa7aadfd3d50792dce08eba3aab7a2399df9a45ad153c0dfb3fec3b9d6f7c5
+
+Count = 75
+Adata = db636541f2429d
+Payload = 6fbda8d435555e735443f1e6bc09e96065092efd89edd64a
+CT = f5a7671f9bb4c3b2b63c641ff88fe11c689c098e4f9f7e3fe20b7da94eac8c7ef8478671165e0d82
+
+Count = 76
+Adata = a8de55170c6dc0
+Payload = 640ef4c246a2c6e16ddc49072a5aeef70319149ffba071ef
+CT = fe143b09e8435b208fa3dcfe6edce68b0e8c33ec3dd2d99a4979c35bdbf9538666b6fa57f0f915d8
+
+Count = 77
+Adata = f8d64ce2aa66e6
+Payload = a14e3910766f31594a28ad2c3678c31d0c3aee88484ca6d6
+CT = 3b54f6dbd88eac98a85738d572fecb6101afc9fb8e3e0ea3752824a691da2e99374ae6c031d74ffb
+
+Count = 78
+Adata = b3c340afdc53a8
+Payload = 1b8e0a09e6364020b4cac704dc19bfa79455295604cf9c9a
+CT = 8194c5c248d7dde156b552fd989fb7db99c00e25c2bd34ef04159a68706faa2e8c3376b4dbeb423a
+
+Count = 79
+Adata = 73824034001519
+Payload = 52c84a0735eea6c5c230644075ebfc5db0c3128056e7a8f4
+CT = c8d285cc9b0f3b04204ff1b9316df421bd5635f390950081e5adc7564721ead2af75cb98e61148b4
+
+[Alen = 8]
+
+Key = 72e6cebdaf88205c4e74428664bc0d7eb4687a272217b7ca
+Nonce = 3820db475c7cb04a0f74d8e449
+
+Count = 80
+Adata = f427c47e10c45bb3
+Payload = 54bc7e3c227df4e83252a5848fea12dfdb2d14b9e67c1629
+CT = 91e7baff2b42af63e26c87ce6991af22422c1f82906858b1721961de5c768f4d19bd3034f44f08d2
+
+Count = 81
+Adata = ca25504f3f5559aa
+Payload = ff4493fea916f49fbb3cae2838bc84e293531092cc0904ab
+CT = 3a1f573da029af146b028c62dec7391f0a521ba9ba1d4a3342968c638ecb8a2b358e8eaefd931efb
+
+Count = 82
+Adata = 8215753d9efc5132
+Payload = af16ab8558269a93d8e8c9e38f12a8768947d8b69be0e259
+CT = 6a4d6f465119c11808d6eba96969158b1046d38dedf4acc1f8ac11752fe51e354f3f8a68815539aa
+
+Count = 83
+Adata = 9e7cdbc6202e6492
+Payload = 744a167ae31a8ca20df82290766429de9ef0b7dfe199a78d
+CT = b111d2b9ea25d729ddc600da901f942307f1bce4978de915489de8e241dcab16bdcbf1a1ff4d8d10
+
+Count = 84
+Adata = b8d511d0ab86a07f
+Payload = eeb39de1fe21b5aba654da45fe1481decb22365fa4cbe49d
+CT = 2be85922f71eee20766af80f186f3c2352233d64d2dfaa053fab212a1b6dc7b953e2bc211be194ae
+
+Count = 85
+Adata = c74a5d4265f9f3d5
+Payload = e95c20e80153bae3fde3c3d82b6b33b35fc1959fa31a5d11
+CT = 2c07e42b086ce1682ddde192cd108e4ec6c09ea4d50e138973918ab70fe048d6c5b63a01725eddfb
+
+Count = 86
+Adata = fd849d3ada03181a
+Payload = 6d00606c72cea3deaea5b51ae09e61924355e167058ef42c
+CT = a85ba4af7bf1f8557e9b975006e5dc6fda54ea5c739abab487089bc20867f474c1127aa1320f0000
+
+Count = 87
+Adata = 56825a68681f498c
+Payload = c47705d897a6c7e7aed710b96e2d8532c23b82090e21b114
+CT = 012cc11b9e999c6c7ee932f3885638cf5b3a89327835ff8c34a23b0b6ac4d297dd7832a5e2102272
+
+Count = 88
+Adata = 72e4da839913a26e
+Payload = c822a1ee581cf85b0482c821473385bd3f28528e5e5760d9
+CT = 0d79652d5123a3d0d4bcea6ba1483840a62959b528432e41dd665766c7af21ff890bd40178f1c660
+
+Count = 89
+Adata = 138457571ee8dafd
+Payload = 3ffb82a83308da66e95ac63ae92931b09ffe0e42afbb4979
+CT = faa0466b3a3781ed3964e4700f528c4d06ff0579d9af07e16a6a58bb772c79481dc26861ffbd68c6
+
+[Alen = 9]
+
+Key = 39c03a0c8634047b1635348f284d3dc1e752ab40548eb337
+Nonce = 9e2ea8eb7f56087ee506925648
+
+Count = 90
+Adata = 28d157f09a71da80dd
+Payload = 0662e63c88e963d3e0cf2c4653515ae4474a2c78ab0394c0
+CT = 01dcd4dd3b8c1369518136ce45e8bb9df565b0ad231a887b02ada34addf0aa2f4744ed2e07995491
+
+Count = 91
+Adata = c17d311362c41d442b
+Payload = d6df8b60c697093987b3d89a3667b36504b6ddddf12b0900
+CT = d161b98175f2798336fdc21220de521cb6994108793215bb38a27466b8741bffce44ef04b23af321
+
+Count = 92
+Adata = 006669ef1a11b65b1d
+Payload = 49ad29ef5e82b08752ac5a50dd982e4bcb700005454ade6c
+CT = 4e131b0eede7c03de3e240d8cb21cf32795f9cd0cd53c2d77d11372fb0dab1c99b159e5fe9f91118
+
+Count = 93
+Adata = 8eafce9ba466fd53eb
+Payload = 385f9fb139dbf88561b7a500b0c7b835fe57e2698c6d9f76
+CT = 3fe1ad508abe883fd0f9bf88a67e594c4c787ebc047483cd09e4898a4046f6ec9f40e412915007e4
+
+Count = 94
+Adata = 796e55fbe7bed46d02
+Payload = 4ebb149b01cbacba32d11168ca61928ea149dcf2ee2c1001
+CT = 4905267ab2aedc00839f0be0dcd873f71366402766350cba5d40a9902481bfac7ff33d08fb4b3d31
+
+Count = 95
+Adata = 8f958d796be0566512
+Payload = 0d974e5621caa1d86eaaee689ccbca57843373fcf20db407
+CT = 0a297cb792afd162dfe4f4e08a722b2e361cef297a14a8bcd972d09a17172161eb68a30b593b1bd6
+
+Count = 96
+Adata = cc879ff2d583a7288c
+Payload = f8e0dac6a691dfb231411b5c5f70a0daff83cc637b0c7bb3
+CT = ff5ee82715f4af08800f01d449c941a34dac50b6f3156708119cc26a80c152c253fbc36cb886e0fc
+
+Count = 97
+Adata = 4765d696d19dec58bc
+Payload = 096a36396ccfa260f28fb0919157a5076b53506c51a2a4ef
+CT = 0ed404d8dfaad2da43c1aa1987ee447ed97cccb9d9bbb8549de06cc5c3bc4ad75076c774576843fb
+
+Count = 98
+Adata = a004f283afc3309c31
+Payload = 5b943269be41e2758a4ea6a3cc621b711a8ba6002783aa72
+CT = 5c2a00880d2492cf3b00bc2bdadbfa08a8a43ad5af9ab6c9135493b44f79a5774df6b2943b0bec67
+
+Count = 99
+Adata = cdd5d8aefe49a315ad
+Payload = 5f27867109e74862ce0dbc9ba73c420b93067bdede17ae51
+CT = 5899b490ba8238d87f43a613b185a3722129e70b560eb2ea7a5da4a29a9012d78b6de6f1b3e8c9ed
+
+[Alen = 10]
+
+Key = e2a92ffbb0b5eb68cb82687f12449fae5167d375131b0b10
+Nonce = 441ad5e1382e083a95224f395d
+
+Count = 100
+Adata = 2352648299b0413cb2ce
+Payload = 048c9ba4597c3bb595bfd5048e5e9a1296f30e5c0118b177
+CT = 25247a258e4ac0a988d8def60cc174a9d4578cd5346fb5150c96e8ab8774baa421f39c64a386c418
+
+Count = 101
+Adata = ce003c836a6f5f066053
+Payload = 02ea8e7e488c863584f828df13dfeb68433294d11d9ca9d7
+CT = 23426fff9fba7d29999f232d914005d30196165828ebadb5d453036cdc6bad0c5e770a6249a52e74
+
+Count = 102
+Adata = d11be73a104ccc6346d5
+Payload = 6d5573c9279897d7d1602d8a95c04bb5ca3fad2dbe89a024
+CT = 4cfd9248f0ae6ccbcc072678175fa50e889b2fa48bfea4464627ad75bbfe17f3f5ddfd3dbc1045f3
+
+Count = 103
+Adata = 6a7b80b6738ff0a23ad5
+Payload = 97a813e75d95d25c2edb1c705c4ffe4d7c08c756761fbc0b
+CT = b600f2668aa3294033bc1782ded010f63eac45df4368b869af8943f74706cc3394a170fd49f7011a
+
+Count = 104
+Adata = a391acdb3a06dae4a671
+Payload = a78981ac244307451e4d3fd7f654b70cc4e6518aa47a3c18
+CT = 8621602df375fc59032a342574cb59b78642d303910d387af22597f63074ca3533bb5e107860481f
+
+Count = 105
+Adata = 0b9f28f2d3215785f569
+Payload = 5d649d79ff0e304e164a383c74f13d7ffab145d00cb0ec2c
+CT = 7ccc7cf82838cb520b2d33cef66ed3c4b815c75939c7e84e905b5609f593c6ea9281f66cd2e646dd
+
+Count = 106
+Adata = 7928b1091cbfb2eef0fe
+Payload = 83a273687dced7b94d569f81d75508595cde668f06406183
+CT = a20a92e9aaf82ca55031947355cae6e21e7ae406333765e1428195355618ea0cf87260ad20b6d7b9
+
+Count = 107
+Adata = 3b74afb81f54a93c79d5
+Payload = b4dc3c059cf7b47dd0bb7f165a63fc80b5c6b5f3ca7eeb73
+CT = 9574dd844bc14f61cddc74e4d8fc123bf762377aff09ef1155019659f41a5f0430695b4ada9d8b8d
+
+Count = 108
+Adata = a46ae4c71d4c9eb72fab
+Payload = 7e919581c5105d98717d0613e1ca869c6516506ea482d5c2
+CT = 5f3974001226a6846c1a0de16355682727b2d2e791f5d1a01514b252f33dc870c42260e48c4fa9fd
+
+Count = 109
+Adata = a1ace61711f0a09ac17d
+Payload = 3a4558b55214f21cbd2ae2eda5a2321cfc2f102e059b744a
+CT = 1bedb93485220900a04de91f273ddca7be8b92a730ec7028c263c667d7ed58907452c092905d0b31
+
+[Alen = 11]
+
+Key = ef1ad3eb0bde7d4728389da2255d1f8a66ecb72e6f2f1ac4
+Nonce = 8e7d8a44244daa7df2b340993e
+
+Count = 110
+Adata = 521583c25eb4a3b2e46120
+Payload = 9f580cc6c62a05ce125c6bec109a48ca527ee26a64b14b68
+CT = ff0ff95bcb0bccd5e4aadd77ac6770f5013654eb3c6386fded2c87135861b43a99f258b6938f66e3
+
+Count = 111
+Adata = 31adb39e947f8883fa4b69
+Payload = f16bba081bddda83546eabc9a55c81a439720dd8562ce964
+CT = 913c4f9516fc1398a2981d5219a1b99b6a3abb590efe24f132b87476d66a1bd405f484ef9ac8ab7e
+
+Count = 112
+Adata = f05f39eb0a3d6460076aa8
+Payload = 6baf784f63cf45a1836fa8f3609fff7870ce8cbd1e91268c
+CT = 0bf88dd26eee8cba75991e68dc62c74723863a3c4643eb19a120b455b366cb104fd8b6dc2c80471e
+
+Count = 113
+Adata = 74c7a633ff73ff507009c5
+Payload = d8176a6de1c15a14c8b8b58725c179dc84c9308268d718d5
+CT = b8409ff0ece0930f3e4e031c993c41e3d78186033005d5400c8ca09f4bf06b1c27e75abf15112e49
+
+Count = 114
+Adata = ab322a88cf44b9ca774415
+Payload = 3706e4d8ff748574f382e5f9b0a3b6258f1f360fd87001b0
+CT = 57511145f2554c6f057453620c5e8e1adc57808e80a2cc25b3159274a7de3550baf759f7fae53dbc
+
+Count = 115
+Adata = d6fe6e17221d4e06ed3ab9
+Payload = e02217394772deffe218c405e40f2a3a56ca01d55d6d3330
+CT = 8075e2a44a5317e414ee729e58f212050582b75405bffea516fba8d193e133e6f78daa39681cb262
+
+Count = 116
+Adata = 2739d2cdfcbe7d5cd7d28c
+Payload = bb713f74a884bd1a994adba87561d637853c6181290ef5e8
+CT = db26cae9a5a574016fbc6d33c99cee08d674d70071dc387d65f92db3b3d1c2de04c69c5d06b0e001
+
+Count = 117
+Adata = 5841571299cd064a6262b7
+Payload = 9641dedd50d80ac0abf7591436065fa2e23e4687abbb86e4
+CT = f6162b405df9c3db5d01ef8f8afb679db176f006f3694b716e4d20ab5ffad6f71155f6839dfdbb25
+
+Count = 118
+Adata = dc5d7fd97bb3243ba585fa
+Payload = aefda8501193edacb8abb94fff875529a537a462c4b9b69c
+CT = ceaa5dcd1cb224b74e5d0fd4437a6d16f67f12e39c6b7b090ebc3af2de52b8bee3d130fa973f716b
+
+Count = 119
+Adata = 8789e0b3e0dc13d9725b37
+Payload = 65e53f549b62aca03f21ab2a494b93805e02cfecf4f12aa4
+CT = 05b2cac9964365bbc9d71db1f5b6abbf0d4a796dac23e731b5cd5a004a0ef28e30383bdaed8f93c7
+
+[Alen = 12]
+
+Key = 44cba20b7204ed85327c9c71c6fea00b47ce7bdde9dea490
+Nonce = f3329154d8908f4e4a5b079992
+
+Count = 120
+Adata = f1e0af185180d2eb63e50e37
+Payload = 6333bde218b784ccd8370492f7c8c722f8ef143af66d71d7
+CT = b9401a4927b34dc15e9193db00212f85f0c319781ec90e3b4484d93cb422cb564acc63d3d18e169c
+
+Count = 121
+Adata = ea74231e49e667ca1c21d46d
+Payload = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e
+CT = e67d8fbeec794d42fc64d7f36a87d2ac22aafa440021ea72c4c151d9927e6a9f19d47ff7d79ca6f6
+
+Count = 122
+Adata = 7f5871a8300471dc325f8289
+Payload = c642c9722d84d708682350dc70bdaa9a1181a415a9e72b93
+CT = 1c316ed912801e05ee85c7958754423d19ada9574143547f959eee29be1415ab03444de0fa42707d
+
+Count = 123
+Adata = ee7e6075ba52846de5d62549
+Payload = 2286a1eddd80737a724ca941217e9f0232870b6c2f20d29c
+CT = f8f50646e284ba77f4ea3e08d69777a53aab062ec784ad70ce97c1c8aea70de04580d7b37f8c014d
+
+Count = 124
+Adata = a30f2fd445820cdf80014554
+Payload = 92577d5db20391110309d490f52acecdfc18382f368bbe42
+CT = 4824daf68d07581c85af43d902c3266af434356dde2fc1ae23b536f993381e525a14599dd5c02e80
+
+Count = 125
+Adata = 0cfec933831644b468724e80
+Payload = 6803dc3f7c06568ca78ee5aa2e9b1b354a4f1e067ff6a25b
+CT = b2707b9443029f81212872e3d972f392426313449752ddb7d6ea722fdd82ede2c7b8832dde3cbe80
+
+Count = 126
+Adata = 6bd14e3bf91dc7fd6be07647
+Payload = 5580672e52aacb9d714a34c31c33fc221e13e8f90849adba
+CT = 8ff3c0856dae0290f7eca38aebda1485163fe5bbe0edd2565c2994b2b469ad977564d83db1ebfe38
+
+Count = 127
+Adata = 6c6ad35e97d023217018162f
+Payload = 1bd1bcc6766d251144376d91ff93ef83033d0e0ee546266f
+CT = c1a21b6d4969ec1cc291fad8087a07240b11034c0de25983ac31ebf9e255eecf3c69ddf198760556
+
+Count = 128
+Adata = 52c35db85cc34b6efed180ee
+Payload = 28f71a2fe498f89203a5d23e8f8fa64b124aea6459fe721d
+CT = f284bd84db9c319f8503457778664eec1a66e726b15a0df13424079e3de87fa59c3d10fd62380a90
+
+Count = 129
+Adata = a96e4776270683ee7d0c9b6e
+Payload = 5be078ead1926074afca81f9a97dc93dcb954c955e4343e4
+CT = 8193df41ee96a979296c16b05e94219ac3b941d7b6e73c082258e1f3fc3eb7e976c86c8a21bd6569
+
+[Alen = 13]
+
+Key = b5f43f3ae38a6165f0f990abe9ee50cd9ad7e847a0a51731
+Nonce = 13501aebda19a9bf1b5ffaa42a
+
+Count = 130
+Adata = ead4c45ff9db54f9902a6de181
+Payload = 3726c1aaf85ee8099a7ebd3268700e07d4b3f292c65bba34
+CT = fd80e88f07dad09eed5569a4f9bb65c42ef426dda40450119503d811701642143013f28ce384d912
+
+Count = 131
+Adata = e63b89e95df8338ecdcc885c3b
+Payload = 37f86aa62b1e31e9ded3e1a38a7e1a8a638d619ac109694f
+CT = fd5e4383d49a097ea9f835351bb5714999cab5d5a356836ac6d3f9c7b9f25e09ce164a11370b8b05
+
+Count = 132
+Adata = a2161536e263459e0b0a29a225
+Payload = 1749f5977197359a5d318d5fea38aba95b3603f1d7011e66
+CT = ddefdcb28e130d0d2a1a59c97bf3c06aa171d7beb55ef443e02b848b006c28803303fd97bdc35476
+
+Count = 133
+Adata = 8ac95a6ae0bce0fb07f85368ab
+Payload = 0842bfb8b38283257c2ea58b29c8350775f1dbf15f73c905
+CT = c2e4969d4c06bbb20b05711db8035ec48fb60fbe3d2c2320431de2bc45b2b726bfda92939a11f68b
+
+Count = 134
+Adata = 44cc9b2510680c4d73f1938c77
+Payload = 68d09fce5e89e4ef6d453b8ee326090cedb97b75b886c7b3
+CT = a276b6eba10ddc781a6eef1872ed62cf17feaf3adad92d96786add8c2619f0782ca12312a1d64266
+
+Count = 135
+Adata = d8a662ab8449bd037da0346a24
+Payload = 45245de4ac6a6196a0b15b77c622a21bb50627379ddb4256
+CT = 8f8274c153ee5901d79a8fe157e9c9d84f41f378ff84a873b6bd4a09f9b4aa2864d39ff1a03e0ff7
+
+Count = 136
+Adata = 8ed39da1d9179e77156eb909f3
+Payload = e928e37dbe8389a53c650edc86f83cd3589a53dc8e45adfd
+CT = 238eca584107b1324b4eda4a17335710a2dd8793ec1a47d819b6935778ffbc0953974de0a9d87a31
+
+Count = 137
+Adata = 423515f7bd592d6a7a2408661a
+Payload = 4c3bdc6186297896097b3297ba90bcde78dc8a9efe3bd8b1
+CT = 869df54479ad40017e50e6012b5bd71d829b5ed19c64329400a3da0d3ce34a272b51582a998f461e
+
+Count = 138
+Adata = 5a6bc2cd6890a473d478a582b4
+Payload = 1c5ebaeb7b926a39b8aaf65a4c484b113d6f2caafadc33ea
+CT = d6f893ce841652aecf8122ccdd8320d2c728f8e59883d9cf4ef28c338f497a40f550f2945734ad1a
+
+Count = 139
+Adata = 7bdc26b5b4df58af539d91eb2e
+Payload = be5c9fee6babf569c66e6a0d0f3c4dc314f40c0aeca493f7
+CT = 74fab6cb942fcdfeb145be9b9ef72600eeb3d8458efb79d2e07f1998e57ba9b611568632dc5cb9fe
+
+[Alen = 14]
+
+Key = 13f179aa2a23bc90a85660306394940e9bb226ce3885ec01
+Nonce = aaa52c63ca1f74a203d08c2078
+
+Count = 140
+Adata = 5cc924222692979a8e28ab1e0018
+Payload = d3b36c6289ad6ae7c5d885fe83d62a76270689ce05fa3b48
+CT = bc4fcef401c2e1d1c335734ff23ea52c3474d2e6f31648a7f58649400ac9e825b038d67f0c2a6f1c
+
+Count = 141
+Adata = 21fb9cdd9b110bbbc6832275dfa7
+Payload = a7742dd9c3e8bbad08157fbd01ebfb94e1639117c4b4eb5d
+CT = c8888f4f4b87309b0ef8890c700374cef211ca3f325898b23fa5ad4142e0b4650fa5cc8f7ef70d62
+
+Count = 142
+Adata = 9919ddb6ee6c330646cd15953d39
+Payload = 297b4498bf5427e6341aa9275c1f62e3b0c9b150a195ae72
+CT = 4687e60e373bacd032f75f962df7edb9a3bbea785779dd9dfec551d11b8647432cc4320173939600
+
+Count = 143
+Adata = f94cfd1f8c7902a57784c10b9a5a
+Payload = 2218868033e17220655f0196dab6193c58293ca105d467d9
+CT = 4de42416bb8ef91663b2f727ab5e96664b5b6789f3381436a79a075ec2cacee1482b8328b697a3b2
+
+Count = 144
+Adata = 63f3fe58c348dc6bcbb44c3c370f
+Payload = 4a9bc26fb10000a57b9e73a8a3d30f66ef9de8782201ffa8
+CT = 256760f9396f8b937d738519d23b803cfcefb350d4ed8c4739cbe17b4edd64a3dcd2b8ae3352c04a
+
+Count = 145
+Adata = dec0ce763833305aa9c9efdc2c65
+Payload = 1b61b3ff3e4847a17f55f7565826b0e2ccc1368f4de32022
+CT = 749d1169b627cc9779b801e729ce3fb8dfb36da7bb0f53cdf54665c476d0741164685b0d81caca31
+
+Count = 146
+Adata = 592ef6784ee839a049e0d96257fa
+Payload = 32e5998b37987a38800f5bfe3132979ca1447314570aaef7
+CT = 5d193b1dbff7f10e86e2ad4f40da18c6b236283ca1e6dd18500d93b11fecc8b4560320878ba53550
+
+Count = 147
+Adata = 4a47a82b999a2a739959f153a091
+Payload = 84acfb6cf10b301558e5acbf41bbbe0b145dc66dc600f4df
+CT = eb5059fa7964bb235e085a0e30533151072f9d4530ec87303c2a41443578adaf31483bbb6b9f10b0
+
+Count = 148
+Adata = 4ceba98cc0ff5de1a7d580cf23d2
+Payload = d7c73d77a286df38aad116843620911c92e11486be5fcb0c
+CT = b83b9fe12ae9540eac3ce03547c81e4681934fae48b3b8e32232a856c07999e99a4701988b486ef2
+
+Count = 149
+Adata = 15e3b3c5794fececd703ac58ccb2
+Payload = 140882c5d3534bb0861e7ba9423e67439a02ee6f0b0b00f3
+CT = 7bf420535b3cc08680f38d1833d6e8198970b547fde7731cb3a6d50a92f3183c0c5090edc3c7f822
+
+[Alen = 15]
+
+Key = c1dfc48273d406a3a7b9176f80b2dc4e9a7f68134bab66d2
+Nonce = 1ac53ba965cdaeeef7326a37e4
+
+Count = 150
+Adata = 39ba54a410a58a5d11615a2163cc3b
+Payload = 67d9728a88f1fac3af43ed6d634ba902896bd226858697d9
+CT = 360f0fc714994e3b59448b50cdd61d511b4f09e0e5fb5ac826a51fe5b9b598a17eb3da10f936813b
+
+Count = 151
+Adata = 38b0cca09d69320105d24ee3f96684
+Payload = a8365ba9fcfff060b28895f7a2d786c5991a8f7758962caa
+CT = f9e026e460974498448ff3ca0c4a32960b3e54b138ebe1bbba673a94f4280e84724f4a2510165e9a
+
+Count = 152
+Adata = 76718dfb9c68acdd82592d96def39a
+Payload = 497be597dd695cb159d8a64f44049c3b549ac927837b1b90
+CT = 18ad98da4101e849afdfc072ea992868c6be12e1e306d68118865ab37be6f015316e0d177b6c2e91
+
+Count = 153
+Adata = dd719ba1710916a546233c1494a7a7
+Payload = ca452c21383ebc3fb584f0d59a227374854983f243a3f460
+CT = 9b93516ca45608c7438396e834bfc727176d583423de39713d903f67ad0d72fb8ffea2035216b769
+
+Count = 154
+Adata = d893fa2bd7c70e21a5934dc2e99037
+Payload = 3dd118ed65453d3d7844d8de78d7a43587ac5e9305b11464
+CT = 6c0765a0f92d89c58e43bee3d64a10661588855565ccd9750b885e3e054f519d0355db1bd589bb35
+
+Count = 155
+Adata = 97c60265a3a6993b97ac1b375a79b8
+Payload = a7375ba32251af0138bd9fd8fcd56a7c43ab2ca9a7fc0117
+CT = f6e126eebe391bf9cebaf9e55248de2fd18ff76fc781cc064a950e4bed4137e38787839e39924821
+
+Count = 156
+Adata = acfdf302ed116ac4755069d1704423
+Payload = d39d188f28521e4fb0a0c5e48e6d6efe4383c95b2535ea8d
+CT = 824b65c2b43aaab746a7a3d920f0daadd1a7129d4548279cca94dd97fd2a5d50eb7dd6234b40c525
+
+Count = 157
+Adata = d449f97164aae9a3046624e98810bc
+Payload = 758102470e221e30d87d2807b5f8b793a7a56c83eecf32a4
+CT = 24577f0a924aaac82e7a4e3a1b6503c03581b7458eb2ffb596f11450d5d2ba55ffb4a6cf7eab847a
+
+Count = 158
+Adata = 3e6c914a196e175079315b1c92b2b8
+Payload = 1db875c4b4f9dd4926dfb5604d6c4d21aba7d905aed9d1b0
+CT = 4c6e0889289169b1d0d8d35de3f1f972398302c3cea41ca164894e9218ecacd143fb62df69a13d33
+
+Count = 159
+Adata = e2b7b00d0cfbdfcc24f1819ae1869f
+Payload = d7a75bc621addccbbe162b86d536d69c887c278384af54e7
+CT = 8671268bbdc5683348114dbb7bab62cf1a58fc45e4d299f685a7c19bc9c2f8e36ed95015ebb679ae
+
+[Alen = 16]
+
+Key = d8a662ab8449bd037da0346a24565683a3bbbbd1800e3c1c
+Nonce = 166fb8d0e110124c09013e0568
+
+Count = 160
+Adata = 1c1c082eeb5b8548283d50cc2ace1c35
+Payload = 61fdd10938557080191d13dd6c3002dd445d9af988029199
+CT = 23c05927502a4ee6e61e4e10552d49b020643eab476eeacc867601fe79a122a7817819655183283e
+
+Count = 161
+Adata = cae884fa25adedd883ef4e7c855def19
+Payload = 8c7ae2c3c503e9072d6e04e44c2ea78fd24994503567a136
+CT = ce476aedad7cd761d26d59297533ece2b6703002fa0bda63160bb976ab072aec8fcea8eab3dc5aff
+
+Count = 162
+Adata = a350ed58c04473e113b9088b1fb9dad9
+Payload = 863f9a26182f131c594972398b52b3a01a9d314fd9390bf4
+CT = c402120870502d7aa64a2ff4b24ff8cd7ea4951d165570a1291b2c13a3f5e49ce35b9047ee1e8627
+
+Count = 163
+Adata = cb7090f7a465782f680fd44cbc558107
+Payload = bd94c9ad6253c25dc417f87b6e52e03621ccf4b3bff5b402
+CT = ffa941830a2cfc3b3b14a5b6574fab5b45f550e17099cf57fdd9fd1d469a9042b80e6458d25292b4
+
+Count = 164
+Adata = 914cf55a3fc739b5f87ac7518cc4171b
+Payload = c313bd213dc29c00691e25ce028884192e21a820003aece4
+CT = 812e350f55bda266961d78033b95cf744a180c72cf5697b1a8b8e82175ff30c69ea71d2cfb814ada
+
+Count = 165
+Adata = adc8b69d84ef7ae62f9ca9f371d3488e
+Payload = 85e4e053b976e06a64dfa8523130cdd802d3e7c3d6d797c2
+CT = c7d9687dd109de0c9bdcf59f082d86b566ea439119bbec9776fa36db27b2f84d1b8ab55e2fc89ab8
+
+Count = 166
+Adata = 29ed477994dd231d3a71157eb56d219d
+Payload = c77aae5fd09dc9bceee7428e0734d4b0556528396a58f909
+CT = 85472671b8e2f7da11e41f433e299fdd315c8c6ba534825c0e32058ea939036805a735198934a072
+
+Count = 167
+Adata = 494c8f931029a4919e2dcbc16512a8bf
+Payload = 1f47273103f265f963e498878361c06c01a5ffcfb630a161
+CT = 5d7aaf1f6b8d5b9f9ce7c54aba7c8b01659c5b9d795cda3437098c81475f8a1d8f3b0e63d499d387
+
+Count = 168
+Adata = 53200bc5d1f1fb0eeff02d2bc42f7d54
+Payload = a38231af405dc7b70c8dbc8cb84e6be8a0dc2e95fddc2ce8
+CT = e1bfb9812822f9d1f38ee14181532085c4e58ac732b057bd9d7317973878957e8fc1fa57a025a3e9
+
+Count = 169
+Adata = 61e0e28bf344a9a1b04b15156e06498e
+Payload = a0d3a94ba6bb3bedf38220d1cba7e91273ad19f9a1c436c0
+CT = e2ee2165cec4058b0c817d1cf2baa27f1794bdab6ea84d95b0aa1befae96e71b9d221673844b1cb7
+
+[Alen = 17]
+
+Key = 116f4855121d6aa53e8b8b43a2e23d468c8568c744f49de5
+Nonce = 924322a3ef0c64412f460a91b2
+
+Count = 170
+Adata = 03c2d22a3bb08bbb96b2811ce4b1110a83
+Payload = 1bd3b5db392402790be16e8d0a715453928f17f3384c13a7
+CT = ad736402626df0f9393fe4491eb812725ad39d6facf20b5b2f9340b0d48a17ae1cc71d7515e61ee9
+
+Count = 171
+Adata = f390387610741d560325b5d2010d8cd4a0
+Payload = c93aaa04279e451b6880ed7b7fdb3ca9e80ab76180434937
+CT = 7f9a7bdd7cd7b79b5a5e67bf6b127a8820563dfd14fd51cb717bae4c040561bcfcf80fd842ae8dd8
+
+Count = 172
+Adata = 891d7988a56415a7b433f463b1e80eaa62
+Payload = 2611612ccb5ffefaa73195509bb52c641472bca0dfd09d49
+CT = 90b1b0f590160c7a95ef1f948f7c6a45dc2e363c4b6e85b5bc9fb15d874feccb6b5f581fa470734f
+
+Count = 173
+Adata = 831c0fed5e600dd82d7d55669262a9a17d
+Payload = 08136e946e306cde0544ddc2f3f4a529c89c7b77a5e635c1
+CT = beb3bf4d35799e5e379a5706e73de30800c0f1eb31582d3da72589ee50d23f925f7998ab3ccac37f
+
+Count = 174
+Adata = 32ca9d412d4ef0e89928496e96c9de7f2e
+Payload = 695aaac402942de7d899cc3f741c7fb2b2d8247a7676cf29
+CT = dffa7b1d59dddf67ea4746fb60d539937a84aee6e2c8d7d555c0b608f331dca47c65f5c879f2d532
+
+Count = 175
+Adata = 0746b2e6149c7f55854e9ca3e6861bf0e9
+Payload = 8f958d796be0566512f0512dcebd2e12f3160b05b72ae955
+CT = 39355ca030a9a4e5202edbe9da7468333b4a81992394f1a9b039bd916e923e2fc1f7c60eb59916fd
+
+Count = 176
+Adata = 0e4cbd1c574d656112bf6e70a8f23347f0
+Payload = 367ecd1b71dfb96a84e2369f28705dfaebf0c73ed35d5364
+CT = 80de1cc22a964beab63cbc5b3cb91bdb23ac4da247e34b98ac07f2c0847069fe5be26e623033f532
+
+Count = 177
+Adata = 1a05ff12412bf728497536534c234901ce
+Payload = a9ccee975feb10f635d548a8502f7c8b6adbd2be74117257
+CT = 1f6c3f4e04a2e276070bc26c44e63aaaa2875822e0af6aabf4e66a2b210e5a03bb10ff2926ed8a48
+
+Count = 178
+Adata = 3bd063a51c71fab5aeb47e7f8f958d796b
+Payload = 7df6220599d6235eb450989b6f0cd6c96db62b0d13afc4f4
+CT = cb56f3dcc29fd1de868e125f7bc590e8a5eaa1918711dc08ec90169d0c5c11fff8f255fedb13a99a
+
+Count = 179
+Adata = f0d334e0a27c3d00d56b15c2ee426e6347
+Payload = 6f65a24344c32debaf9f8c3fa426fe0b139e8ad1c8b1fbbb
+CT = d9c5739a1f8adf6b9d4106fbb0efb82adbc2004d5c0fe347170141cf3f207c4f0fc1b0238477cfad
+
+[Alen = 18]
+
+Key = e67f3ba11282d61fe36e38cab7b559c2fd9cbe8bf7eb5863
+Nonce = a727ed373886dd872859b92ccd
+
+Count = 180
+Adata = 68d199e8fced02b7aeba31aa94068a25d27a
+Payload = d7a954dae563b93385c02c82e0143b6c17ce3067d8b54120
+CT = c6cfaa1f54d041089bd81f89197e57a53b2880cefc3f9d877e30b2bcc3f1ea9ec2b8f28bf0af4ecf
+
+Count = 181
+Adata = fc4bbe329a86089ebe2a2f3320dad55a9bda
+Payload = a206a1eb70a9d24bb5e72f314e7d91de074f59055653bdd2
+CT = b3605f2ec11a2a70abff1c3ab717fd172ba9e9ac72d961753a6e6844102d6bb86986c030765d3393
+
+Count = 182
+Adata = d8741e540330692d83cc806a8ac1c4742be6
+Payload = 56ef76dbec6b8b46f5b7b4e311c0baaa6fcf54c69c0b9c3b
+CT = 4789881e5dd8737debaf87e8e8aad6634329e46fb881409c3f92a80b1d82f8c1dc32bfe64adca12a
+
+Count = 183
+Adata = c8b1992dfba55b4ab86b480546c861655e1a
+Payload = 2729636112f2abe2c76ea5e52a3f80b0f882f0f3b6f7c806
+CT = 364f9da4a34153d9d97696eed355ec79d464405a927d14a12fb48ad162b0c0678674d79d26a6b5ef
+
+Count = 184
+Adata = 347e12eec56e95aafcc7d25bf10fc756b4e4
+Payload = dd433eb7422c7c4dccee57a1679633ced3b5f08df763d457
+CT = cc25c072f39f8476d2f664aa9efc5f07ff534024d3e908f081c7cd81c974d985bf24b7fe9542141a
+
+Count = 185
+Adata = 45b35a04d6e2645e9a5aef206ed4e36199c9
+Payload = 70523bc397417e09d791a4976960e02636ca7144a5681cf7
+CT = 6134c50626f28632c989979c900a8cef1a2cc1ed81e2c050a7f6a5c04e59896074e1594706ab27e9
+
+Count = 186
+Adata = 378b48531fe34f55125b2f14f59715dd6ef0
+Payload = 514cb462dd4b117f26cac22062fcbeb353650c71649a7b3d
+CT = 402a4aa76cf8e94438d2f12b9b96d27a7f83bcd84010a79aa9d16c3ab79276cff345444511940a9d
+
+Count = 187
+Adata = 73ed686d6fecdc031cd97653137f269d6537
+Payload = 7f0c2b261db3f3de0ce3a733f4b8c446c374567d96d00379
+CT = 6e6ad5e3ac000be512fb94380dd2a88fef92e6d4b25adfdef92bf8aa6facbe6f9607ea02b54a1bf0
+
+Count = 188
+Adata = 5b0441107e5560be94f030a41cedbdb116d9
+Payload = ebb3e2ad7803508ba46e81e220b1cff33ea8381504110e9f
+CT = fad51c68c9b0a8b0ba76b2e9d9dba33a124e88bc209bd238e4936ee93b5c7a302913292df33c1700
+
+Count = 189
+Adata = feedcc5f8524fe7d49bcd178415b9f4c450a
+Payload = 3216dce3b8b1ce0e79e40fffcac728ab191aaaf319d971d3
+CT = 237022260902363567fc3cf433ad446235fc1a5a3d53ad7493426b6193afe765a76b3dec00266e69
+
+[Alen = 19]
+
+Key = e0a29a2c7840cf9b41de49780b9ee92d646a4bfc5b9da74a
+Nonce = fc9fd876b1edded09f70b18824
+
+Count = 190
+Adata = 36e15baafa0002efbb4bb26503b7e3b79f6c68
+Payload = 344dc8b6bd66a1fbbe330a95af5dd2a8783dc264d6a9267d
+CT = 43b3b96aa5a54378f3bb573ffda3e154aa7f425fc3008175b60a77b9d38740356b544b1c0f259086
+
+Count = 191
+Adata = 712b788f0276e2b5a58be80f9114a12ab2a268
+Payload = 6d0546d4e95d1cfcb37a8f88a62064f5d95791311511535b
+CT = 1afb3708f19efe7ffef2d222f4de57090b15110a00b8f4535f750bb4cd42db3038e2c1622b72cea8
+
+Count = 192
+Adata = 07f77f114d7264a122a7e9db4fc8d091334a03
+Payload = 05024ce13b9057dd2c509db7dbcbd5585e4e64a1e2e380ff
+CT = 72fc3d3d2353b55e61d8c01d8935e6a48c0ce49af74a27f761e77b59ef7eeeae35bb53bb9543b64a
+
+Count = 193
+Adata = 899b036138cee77cd28382ba27984d858a6351
+Payload = 77b8e735b13b10e45e411ab94c6fe1a9eb89f0a7af40ff1a
+CT = 004696e9a9f8f26713c947131e91d25539cb709cbae9581244a60fdb473098a11b2176d37b2c4643
+
+Count = 194
+Adata = 4b000440a8484a5201cd54aec058919769772e
+Payload = 6b21800ae599a15254bb33f0bb080788fb6e9fa054bfd8b2
+CT = 1cdff1d6fd5a43d119336e5ae9f63474292c1f9b41167fba58d4afc30a7f672ea34e05ec1843d848
+
+Count = 195
+Adata = 73a222e681ed1ca47d92a6dd90625d895fbf29
+Payload = bfa9d9af6e1f32b6626a1cd89b1c32513b5b50a18ddab028
+CT = c857a87376dcd0352fe24172c9e201ade919d09a987317204ef270e0f3b5e3ca0b8440af65c76e85
+
+Count = 196
+Adata = 7109a3a36b286059bc1a1abb2767c92f884e3f
+Payload = c68b1bc0050e19780ab53efbea175634f70a7245d966966e
+CT = b1756a1c1dcdfbfb473d6351b8e965c82548f27ecccf3166ffb66991b38a0345fbbff5f2362f87de
+
+Count = 197
+Adata = cd15973753b94b77bb4b778de8b3b0cabbde85
+Payload = 4256f1c9b64390fe2120df9fd38e497c2903c2ca5679ab75
+CT = 35a88015ae80727d6ca8823581707a80fb4142f143d00c7dd033a087c44c2e44adbeb333aa9ded10
+
+Count = 198
+Adata = 6e5e0793855f7145e13a5872f563e5ec61cfd2
+Payload = bb0036b34b0c20094d335a8c74f6b3dea42eeccf4145192e
+CT = ccfe476f53cfc28a00bb072626088022766c6cf454ecbe26ff9c8713422fe38d5bbf2dedccbffe10
+
+Count = 199
+Adata = f844684f5404e7d8eedfa20394b40b4f5d910a
+Payload = 86afa9cdd743916563ebfd3adbdd56e015ea3a4ebc61cfe2
+CT = f151d811cf8073e62e63a0908923651cc7a8ba75a9c868eae75de56eabcf8e02c1a27705adef2732
+
+[Alen = 20]
+
+Key = 26d0a3a8509d97f81379d21981fe1a02c579121ab7356ca0
+Nonce = 8015c0f07a7acd4b1cbdd21b54
+
+Count = 200
+Adata = 093ed26ada5628cfb8cfc1391526b3bcc4af97d9
+Payload = 37ab2a0b7b69942278e21032fc83eba6cdc34f5285a8b711
+CT = a3a60b422eb070b499cf6da0a404b13a05cedda549c6b93e6ca0e07e04674f21a46df2659a5905fb
+
+Count = 201
+Adata = 7df13c9d2247aa40af7bbe2da98bd366d8b47b43
+Payload = 93925579b6367ff592ecbd59495fdeccb50f31ea4fa390bc
+CT = 079f7430e3ef9b6373c1c0cb11d884507d02a31d83cd9e93836597806f5da1d176c745d95c4fa46a
+
+Count = 202
+Adata = 7f369bbc99b6f08049eeb43566269a174829d4dd
+Payload = 8363aef9c7c34e1f8149de46c97d5ac79d38c6ed31ab1d12
+CT = 176e8fb0921aaa896064a3d491fa005b5535541afdc5133df826dda99111691993027628c70ff6ae
+
+Count = 203
+Adata = 04aa8442179f62babad0c006e36af0c21105f27a
+Payload = 17281acb525b13653000ab45d86e70106c10a93c99b18f76
+CT = 83253b820782f7f3d12dd6d780e92a8ca41d3bcb55df8159d074b018143a7ea1b5369b7f80eae20d
+
+Count = 204
+Adata = 997e646014f19a53beab8877ca6022bef23016f1
+Payload = 5d48a71557608736eded309027a80349a18e9ce5dee2bc6a
+CT = c945865c02b963a00cc04d027f2f59d569830e12128cb2455db17d3f75214c3cf39858617cfee57a
+
+Count = 205
+Adata = 60ffcb23d6b88e485b920af81d1083f6291d06ac
+Payload = 6c9d11cfb64d96bfab61c04a25d9e19294fb7330fb4847c8
+CT = f8903086e39472294a4cbdd87d5ebb0e5cf6e1c7372649e79550998376e61e11a5a69e9f8fe1c329
+
+Count = 206
+Adata = d574632658bf456dfbb11c2653602ed0f4dae777
+Payload = 7d41688c86d5e3bc53966810f2299fdd732e3471fb0a88f9
+CT = e94c49c5d30c072ab2bb1582aaaec541bb23a686376486d6a1b0d05a7ebc657c3235479893bf7e5d
+
+Count = 207
+Adata = d896ed60128f4bb0277d3af94c5138cf91697aa9
+Payload = 8c7ae2c3c503e9072d6e04e44c2ea78fd24994503567a136
+CT = 1877c38a90da0d91cc43797614a9fd131a4406a7f909af1980c98c8959c158ce209aebcbd554f250
+
+Count = 208
+Adata = a350ed58c04473e113b9088b1fb9dad92807f6b6
+Payload = 49bc9d3bcf3c22daa8cf55c1b59d4bffddc2412d60518e98
+CT = ddb1bc729ae5c64c49e22853ed1a116315cfd3daac3f80b7573175f9105cd16ee384465ebb232200
+
+Count = 209
+Adata = 1db5887001204194e8b5dcee92c8af8fa5f7321f
+Payload = 25f3788e0d3dd8f5821faa4e45a9d6b3995fd881f927135c
+CT = b1fe59c758e43c636332d7dc1d2e8c2f51524a7635491d732b67e993384f2e7229d1838efd040d99
+
+[Alen = 21]
+
+Key = aac60835c309d837aacc635931af95702a4784c214283ebb
+Nonce = 0e20602d4dc38baa1ebf94ded5
+
+Count = 210
+Adata = 796e55fbe7bed46d025599c258964a99574c523f6a
+Payload = e8610756528f75607b83926597ef515f4b32a8386437e6d4
+CT = e0a3d5f43e688ce104f4ae1a4fcd85500aa6b8fdbcd1b8d3003c0c3b7369e79339433e1754c0937f
+
+Count = 211
+Adata = 5170836711fcb1a350b087907d8a17c7637aa1595b
+Payload = c61b0c1845fa9b2e0013b3fa9a8cb4f4fbbc6846f63ed180
+CT = ced9deba291d62af7f648f8542ae60fbba2878832ed88f87120a7f18d021833b167bf330c4858239
+
+Count = 212
+Adata = 2a68e3fe746f593c1b97cb637079c3e5ee352c107a
+Payload = 10c654c78a9e3c0628f004b061e28c39a3c23e7250f53615
+CT = 18048665e679c587578738cfb9c05836e2562eb788136812ca9698d9a88e892c364e57dd35c2f17a
+
+Count = 213
+Adata = bf38ca0e89b8f5ccd29387f7f193ab5a967caa715b
+Payload = fa3a959fdff853c39f76da626094a1ea6dbc78bd2f091a79
+CT = f2f8473db31faa42e001e61db8b675e52c286878f7ef447ef3839d6f7e20a2e343f4c4da9eb9be13
+
+Count = 214
+Adata = bee00f2f75a4415ce993d2d14a6d8e01d1d59a48f6
+Payload = 76d12e3c4c5d990bf563c60aa4999e52998d887f97477f6d
+CT = 7e13fc9e20ba608a8a14fa757cbb4a5dd81998ba4fa1216a6630bfb7a2a2441e020efdf36274b72f
+
+Count = 215
+Adata = d5b614e4e8f72a5d8b1ec2b375da5dac64c2cc30b1
+Payload = 693fae7af84aa397f0b2baaed9b3c7953f75e7424c49b634
+CT = 61fd7cd894ad5a168fc586d10191139a7ee1f78794afe833866bcee343ec5aae61f9effa19b99d3b
+
+Count = 216
+Adata = 33f11aa36d8ab0fc53486839a576b31ee915dbd769
+Payload = 56ce9a09f38127b14dbbdcaa59f363c92a3b9843ad20e2b7
+CT = 5e0c48ab9f66de3032cce0d581d1b7c66baf888675c6bcb00331b60eb252f744a06b4a95aa9f4e7c
+
+Count = 217
+Adata = f40bce1a6817b29b9e8b56f214fcca7dfde17e7ee6
+Payload = 5cd8986e974d09ede34ba68fd81d6109a64092e7fbbaf87d
+CT = 541a4accfbaaf06c9c3c9af0003fb506e7d48222235ca67a4153778a644cb2469cef3ad125e257bc
+
+Count = 218
+Adata = 53c457d8d4d4ab95ba116c28b82c16743cb09de9fe
+Payload = 9c3c610f204d98702dd91ea28e0cc14830b26bb5e2ee0349
+CT = 94feb3ad4caa61f152ae22dd562e154771267b703a085d4e7013e1c34dbc5efc7bcd4f8e52797644
+
+Count = 219
+Adata = c7acf1b17609dc336df1006ffac6497777cdfd497c
+Payload = 90c5dd9db0316dac89db18f70491bdf0a06a6a7f72b77d9a
+CT = 98070f3fdcd6942df6ac2488dcb369ffe1fe7abaaa51239d66aed667c761b7dea44822e30cff671f
+
+[Alen = 22]
+
+Key = 671544bf2988056f7f9ccd526861391a27233793a23f811f
+Nonce = 0a259148a1d081e0df381ecd0c
+
+Count = 220
+Adata = 61dafc237cb52f83ab773ba8a885462b6f77d4924611
+Payload = 576b069ae2713f53d2924c1fd68f786cb2eec68892f9e1be
+CT = ce06b3d09b02921f290544032a081a7766612940048867281bb089af0245792c16e6320cf5ffa19e
+
+Count = 221
+Adata = 87e49b8164e7052becfa0c966991637b38df833fc5f7
+Payload = d7eb0d7dd737805cd3b8dbf451aeea2fa1f6a96eb58cb428
+CT = 4e86b837ae442d10282fd3e8ad298834757946a623fd32be3cec29bd5df92363d6bb75456f5cd32b
+
+Count = 222
+Adata = d302a518d7c625756d3e4c8cc2b1d973a19107c945fc
+Payload = 77d8c9e6321314524afd05b7ad599c29f4eedda9e9f0763f
+CT = eeb57cac4b60b91eb16a0dab51defe32206132617f81f0a901ca82cddb78a2fe3904d1d8bf6fe5b2
+
+Count = 223
+Adata = 6566bb616a94bb03df5c26b722bcd38d516285c5f6c1
+Payload = abbf28b3ae164051648293d0b94e11f5af8468450005c7c0
+CT = 32d29df9d765ed1d9f159bcc45c973ee7b0b878d96744156d095ad121f0f76f07b715cad996def52
+
+Count = 224
+Adata = 141be3601e38185a9fa1596d2ee406415c9673af32f5
+Payload = b67d50110f844b36a00d352123012a1123c7c3cba959dc48
+CT = 2f10e55b76f7e67a5b9a3d3ddf86480af7482c033f285ade8529ec8f477462dc2409482c3479756d
+
+Count = 225
+Adata = a2969243b0955402ab45a430fef2ef9e0c025006732b
+Payload = 2a63f7b09b43fee65738e8115bd8419b3ef3e8f86eca707f
+CT = b30e42fae23053aaacafe00da75f2380ea7c0730f8bbf6e9b14fe8dbb3c361ea61d7b44e689a1c48
+
+Count = 226
+Adata = 87faef55c54250c30232ccaf5efa1ff41b6243b2a5bc
+Payload = 59dad755af92c29522da4348ab9b3037fe87004f5fa1394a
+CT = c0b7621fd6e16fd9d94d4b54571c522c2a08ef87c9d0bfdc54f0659fae291f943f2f3b33688602cb
+
+Count = 227
+Adata = 5d895fb949344e603ce5de029842b20d2bb614ecbbb8
+Payload = 64d8bd3c646f76dc6ce89defd40777fe17316729e22ba90f
+CT = fdb508761d1cdb90977f95f3288015e5c3be88e1745a2f993af4e3a7a20390a8da264299712a34e3
+
+Count = 228
+Adata = 74cc8da150b0bacdefa8943900b4ea047611d96be70a
+Payload = 0c3c9a634a000f00be003846eac7482e303a5bef3a70fe75
+CT = 95512f293373a24c4597305a16402a35e4b5b427ac0178e3a7f79d2b5a9bde5bd453bc8a03e971d8
+
+Count = 229
+Adata = 65f6adbaaa803dbad5ba9cb6d231314d55147cc61399
+Payload = 712c788928c8a1562bc1f3f0eb1286e15c3405f6a6fa0443
+CT = e841cdc351bb0c1ad056fbec1795e4fa88bbea3e308b82d5ffccebfb8c833833db40e98a1950fb70
+
+[Alen = 23]
+
+Key = 90e2c63b6e5394b1aeec03f95a9d13a01a7d4e9d58610786
+Nonce = dada5465eb9b7229807a39e557
+
+Count = 230
+Adata = f5629ca0eea589f6cf963d875a7d2efb656983f2dd2231
+Payload = 44dd098b1f869d670a8a841900c4bef023a1946a0c278354
+CT = 6b38ca85450e05e7b9362ed7e6e291a130ff233b5a561cdef7ec84dd992fdf98514f845dac8f656e
+
+Count = 231
+Adata = d43d7753530a7280b76221906dca85d396b6cf05125018
+Payload = cea19562328bd1fea889f575db6a28a14b7d06fb9f9c98bb
+CT = e144566c6803497e1b355fbb3d4c07f05823b1aac9ed07313613ed15d527d9dc58ab6893e723db58
+
+Count = 232
+Adata = 75650ce366757618af20205b69af7e5d4e82c398c00101
+Payload = f0641f595b791edd860977fcf699688587a354e053e9c7fe
+CT = df81dc5701f1865d35b5dd3210bf47d494fde3b105985874ef8728d1bf3a2d93db3266bafadb7c26
+
+Count = 233
+Adata = c00f1b8066677c63e898fddfb8a1b482b536963da0628d
+Payload = c7486a084f8475e6f5138e8d6e9f42a1de90f05aa88a362d
+CT = e8ada906150ced6646af244388b96df0cdce470bfefba9a7a5bce94d7564d297fe87730f1a36acf4
+
+Count = 234
+Adata = 5a89ab6b26b2ca78f98a8f8409fe8008b97ba9ef185d41
+Payload = 091ef698e16dc43a11d3ea005d5a5cdb7f1bdb5665a6c81e
+CT = 26fb3596bbe55cbaa26f40cebb7c738a6c456c0733d75794cd971b07fc14c512b8df6dd964b129d0
+
+Count = 235
+Adata = 5d24d80f22afe713c4076c200c1bab36917907fde7b6d3
+Payload = 62f204394b367c4410746001e02dfd171858396568fdd43b
+CT = 4d17c73711bee4c4a3c8cacf060bd2460b068e343e8c4bb1a192b781dc94448d4a0f6a439a716339
+
+Count = 236
+Adata = 4a47a82b999a2a739959f153a091a65c4d7387646da66b
+Payload = ac1cd5ba4997af91dbd74aee7730f9ee92cf8a360ca96a8a
+CT = 83f916b4131f3711686be0209116d6bf81913d675ad8f500cade9533b272e0a3edeba68362b057b4
+
+Count = 237
+Adata = d9fc295082e8f48569eb073ac1b9566246728fc62ccaab
+Payload = d0a249a97b5f1486721a50d4c4ab3f5d674a0e29925d5bf2
+CT = ff478aa721d78c06c1a6fa1a228d100c7414b978c42cc4785d68df8ff28345be4d83541a72071059
+
+Count = 238
+Adata = 720a9dc3e33ac080775a06f67f4a6591c37d0e101944a0
+Payload = 77fb98f24172f5d5edadbf466ee910855a71d46090b789ee
+CT = 581e5bfc1bfa6d555e11158888cf3fd4492f6331c6c61664caa7ec8892be6a18458c663665495035
+
+Count = 239
+Adata = 13cdaaa4f5721c6d7e709cc048063cfb8b9d92e6425903
+Payload = 77fb98f24172f5d5edadbf466ee910855a71d46090b789ee
+CT = 581e5bfc1bfa6d555e11158888cf3fd4492f6331c6c61664862fda880e45e891a3a50da7e14344c8
+
+[Alen = 24]
+
+Key = 13cdaaa4f5721c6d7e709cc048063cfb8b9d92e6425903e6
+Nonce = f97b532259babac5322e9d9a79
+
+Count = 240
+Adata = ad6622279832502839a82348486d42e9b38626e8f06317c4
+Payload = d7c837971b973f5f651102bf8d032e7dcd10e306739a0d6c
+CT = 4709600418f2839841e6d126359f6982bdb53acc7ff209635623d15b24184481eadc63bb8c878fc4
+
+Count = 241
+Adata = ad4833aa53218949cfd724814a43889a74a2114bbef4cf37
+Payload = 7d672bccd0fb01ce79320ed61779146aa432038daa13cb41
+CT = eda67c5fd39ebd095dc5dd4fafe55395d497da47a67bcf4e614c3e546273f0aeef207bd3f4d32fca
+
+Count = 242
+Adata = 54a723826086c7175e8fdc854b62d780de6ac1f90b57dd3a
+Payload = 0e1b73df74982f535a5fb08bc13d22515ee10969efe033bb
+CT = 9eda244c77fd93947ea8631279a165ae2e44d0a3e38837b413c6395ce9aee2e22ac0606beb140185
+
+Count = 243
+Adata = bec02d7df4cc3deefdd7e7d3ea82d381c870ad46bc06d64f
+Payload = 9a55aff269b180118ff0ea99e851c7474d19d23e641f16a9
+CT = 0a94f8616ad43cd6ab07390050cd80b83dbc0bf4687712a661e4f02150bedd86dfa49f52b214239d
+
+Count = 244
+Adata = 1b8090d712e0ec95a01bc3aeb6f5230c67c355e0ed68043a
+Payload = ff19294e8faed8353dbcab0b146e2ef928dd2680833424bd
+CT = 6fd87edd8ccb64f2194b7892acf269065878ff4a8f5c20b2f0e82b9f04bfc0cc0ba432b5135450c2
+
+Count = 245
+Adata = 5ed0b9f25d07b26717cdcb2507bef9d681ecd9389831ac15
+Payload = db1eba6ac4a79aa1d97838d263c7c4ffa7d354770e762805
+CT = 4bdfedf9c7c22666fd8feb4bdb5b8300d7768dbd021e2c0a2e64c82b60880c5c7506321a1060a481
+
+Count = 246
+Adata = 55f16fefaf2168aebc61b5e01d9e1f7bfe215eaaef118974
+Payload = 012d45168505ca9fde5aed123875639a207d473b993dc7b8
+CT = 91ec128586607658faad3e8b80e9246550d89ef19555c3b77152f64dc993b36ad9d5d12bb52b1ad5
+
+Count = 247
+Adata = 9893bf14fd3a86c418a35c5667e642d5998507e396596c50
+Payload = b205f26d6c8a8d6085ab28d595703cae046f96d82093082b
+CT = 22c4a5fe6fef31a7a15cfb4c2dec7b5174ca4f122cfb0c243e5c69256b6326ebb7ee6e677d396765
+
+Count = 248
+Adata = 244b840085bda9576c8424bb05a925a6b09cad2d0528ab8d
+Payload = 549ba26a299391538b56ce4bd71dbbfd96995836f8915ca5
+CT = c45af5f92af62d94afa11dd26f81fc02e63c81fcf4f958aa2083dac565c7a63908f0022e2867bb68
+
+Count = 249
+Adata = 9e8d492c304cf6ad59102bca0e0b23620338c15fc9ecd1e9
+Payload = 9e9dbd78a1066800ae33253be6104015158a0187e4f38116
+CT = 0e5ceaeba263d4c78ac4f6a25e8c07ea652fd84de89b851968242fe32958ea32e670ae1b3543974f
+
+[Alen = 25]
+
+Key = 90851933d4d3257137984cdb9cba2ca737322dac4dbd64bc
+Nonce = be02df3a840322df8d448c600c
+
+Count = 250
+Adata = 69a9dd9ac8be489c3a3f7f070bdaca10699171f66ab3da9351
+Payload = ba1785a149cb8b69a4e011c11a3ff06f6d7218f525ac81b5
+CT = 89ab2efefa8406336d9e2245199fbc9454f0ef650b9ed0f446c7246bd3130803bf8d703ef5bdf15c
+
+Count = 251
+Adata = 0c39a72f0f38d2713c164b0f870646fc65b9838a322ecfddd0
+Payload = 263dc4fb5cd8798ce0f183a816e51fafba167533dde1bf96
+CT = 15816fa4ef97f4d6298fb02c15455354839482a3f3d3eed7096a6a4422e582c5d02973952ac80e5f
+
+Count = 252
+Adata = 911d9f5c4c34c2f4b69be1e253d43fe729e2ab2622130394b1
+Payload = 7b5da2c283116713f3d80c7907114270964541e03ab80d50
+CT = 48e1099d305eea493aa63ffd04b10e8bafc7b670148a5c115965f6df4332fe7a2cdc4d1b80e28a34
+
+Count = 253
+Adata = 8a961df9c23f6d5ecdafa94c61164a22f460a1bf7415258d39
+Payload = 541a2b3ee25022c92fdc6783a6cbde90680ad3dc41868e5f
+CT = 67a68061511faf93e6a25407a56b926b5188244c6fb4df1e18bed174081b2170ffc6ab53b54c9ddb
+
+Count = 254
+Adata = cac7a248a4d4e96a9733627e247234995d6aa57e491498118a
+Payload = ebb2e893da9f32c363f98bc76fd14eda59e7cc620070f6d3
+CT = d80e43cc69d0bf99aa87b8436c71022160653bf22e42a792bac3d3a2b9ef6d4c8715f9a5c6fe8245
+
+Count = 255
+Adata = 41eacf70d05a6d0cdbdd38f197a52987def8fde37f332eebd9
+Payload = 199cca0d0e1c70ec405d6816cbddc69f8ada624f2c168891
+CT = 2a206152bd53fdb689235b92c87d8a64b35895df0224d9d07f9610c82fe9a7c78e8f1980e886b446
+
+Count = 256
+Adata = 78b6ed20ed85337c969618bd41917cd85c37e7c35c3a12e25f
+Payload = ca481f557306f9ce386edd0cfde375a550cb5b574be524f7
+CT = f9f4b40ac0497494f110ee88fe43395e6949acc765d775b6aab366637ec41d0bf557f578be424a8b
+
+Count = 257
+Adata = 87faef55c54250c30232ccaf5efa1ff41b6243b2a5bc93e7cf
+Payload = 6f1b4ff66d3aec7b0c0d9e202acc52722e15bca0983291e0
+CT = 5ca7e4a9de756121c573ada4296c1e8917974b30b600c0a1e57a5b3ae26469d229425f887ad5a2a1
+
+Count = 258
+Adata = 7f19ac3e53a629a2df1cb56d68fde0c80a46be40a996830e2a
+Payload = 7533c88ce55c2243b64b6c5bd01aed4dd6ac8bb9fd333e06
+CT = 468f63d35613af197f355fdfd3baa1b6ef2e7c29d3016f476ce4fe492062f74bff4c3c0e9ea849a4
+
+Count = 259
+Adata = 0516a69bfd8785ad001367b51e5410b75c11b761be08b9eea5
+Payload = 19ea09a9bfd10db2a74e398859d8f4831fa5749767773acf
+CT = 2a56a2f60c9e80e86e300a0c5a78b8782627830749456b8ead47ffc17b871f530f62b9f9aec98509
+
+[Alen = 26]
+
+Key = 5c5d02c93faa74a848e5046fc52f236049e28cd8096dcac6
+Nonce = 54cbf2889437673b8875a0f567
+
+Count = 260
+Adata = 09fc21ac4a1f43de29621cacf3ad84e055c6b220721af7ce33bb
+Payload = b4da43ebfe9396b68f4689fba8837c68d0064841c6ddd4a7
+CT = d40725397229021a18f3481e3a85f70445557bb2a85e4ae8101a34c777e918e16186fda05a386572
+
+Count = 261
+Adata = 10f0c45d06a138a964fb11b2d450620a2977bcd2952afe371cad
+Payload = 7b628930d44e22907277db057395601b82b65479fbd59613
+CT = 1bbfefe258f4b63ce5c21ae0e193eb7717e5678a9556085cc1e79234882846d916dabae40b1bd055
+
+Count = 262
+Adata = 64dbb170a037b36beed28a2637c87830e2b23f8eea6cd9a7331c
+Payload = 9db30b669fc5d25f05e0dc708d597da6ddce2dacc85ae99c
+CT = fd6e6db4137f46f392551d951f5ff6ca489d1e5fa6d977d3e35499e3c09dc384eb41344ee8be3769
+
+Count = 263
+Adata = c47de6608546a02c6eebd6628c9123f6936c0154d3df52a367e5
+Payload = 62036cbed3666d85624d3dc9c1f437454b9ab5c03ce0de92
+CT = 02de0a6c5fdcf929f5f8fc2c53f2bc29dec98633526340ddd605189608ce40b237dde7bed6fde487
+
+Count = 264
+Adata = bab7e36098d59d3a31d7784d549aebfc6938bbd0612c85c0edb7
+Payload = 5c9bc739f6b6fe4214f3c6aad307d1f208892d79de010e37
+CT = 3c46a1eb7a0c6aee8346074f41015a9e9dda1e8ab0829078c31f69c847440be20bd08cfef330002f
+
+Count = 265
+Adata = 8a9716135fa38c250e249f6712f7cb3ad9210d7278b53d599df9
+Payload = 0df109298083d3896214b84ff6edb11e9cfdbd88f5702839
+CT = 6d2c6ffb0c394725f5a179aa64eb3a7209ae8e7b9bf3b676ca83622b127fa50fc9637998c0ddd44d
+
+Count = 266
+Adata = 2d52447d1244d2ebc28650e7b05654bad35b3a68eedc7f851530
+Payload = 518f651f6d82f670b63767ad8476ed8fc24df12a45110611
+CT = 315203cde13862dc2182a648167066e3571ec2d92b92985e81e738b9e4b0dc7b7a39eb7d03adc64a
+
+Count = 267
+Adata = 3cba0fd2bb16ae1d997cbe659a2dd101885c97f2322b0172b5d6
+Payload = e91a694bea2d351928b6098660d49f382c087f6777de159c
+CT = 89c70f996697a1b5bf03c863f2d21454b95b4c94195d8bd3d298c05b1d2e597f44f8621ecd11ed16
+
+Count = 268
+Adata = c7f93152016bba584dadc6002ec493a46305726068886d2340da
+Payload = 2d14792ed349a878b2b879e7fa5f438a50e36947ce827e73
+CT = 4dc91ffc5ff33cd4250db8026859c8e6c5b05ab4a001e03c5fd5221fceecbf0dc7211a1aec06793a
+
+Count = 269
+Adata = 799cac048eaccded37ca6a70dd89595e1ee04606212da5572679
+Payload = 315b8d95938d304015bbc94ea03c21f6dc25c90f991ba680
+CT = 5186eb471f37a4ec820e08ab323aaa9a4976fafcf79838cf5c25f00b862b49fcfe8447949f39787c
+
+[Alen = 27]
+
+Key = 0234dae5bd7ae66c67ff0c1a3f1a191a0d7bceb451bc2b7d
+Nonce = 16d345606a315ad2406abbcb43
+
+Count = 270
+Adata = c37fdf7449fd7e943595d75e977089c623be0a3926e63fdbbfdf4a
+Payload = 0f960a89a7e806f8709047cb7a2e7c4211ad724692c88a05
+CT = 3907880d25f910eab12dd14e704d1b33ea7c453634d54da2a461f44dac1112ae3f9c65671a931d3e
+
+Count = 271
+Adata = 85f647d940a6d1acb6b7851912f807063515631eaabaa019dcfb99
+Payload = ab40a4baa39b0e568bf2193fecbc36b84c76bb50523b2912
+CT = 9dd1263e218a18444a4f8fbae6df51c9b7a78c20f426eeb5ed15db6e142ee07b59eb5b0ad3a59194
+
+Count = 272
+Adata = 79ae14843b2e7ccf0fd85218184f7844fbb35e934476841b056b3a
+Payload = b74c06d9077c568762796d5be14f3563e7205a6e9bc65bcb
+CT = 81dd845d856d4095a3c4fbdeeb2c52121cf16d1e3ddb9c6c203f11f66b74366caeca8dbded2bf17a
+
+Count = 273
+Adata = 542d86fd7ff591f97e6926a090553538bc3b8a6bcd45f2e29c7d9f
+Payload = f2179beb5635a6d8a8340acea0ffcf4428e5de1306a8c12b
+CT = c486196fd424b0ca69899c4baa9ca835d334e963a0b5068ced925fb9a4cf6b6bf17f72ab044653d1
+
+Count = 274
+Adata = 4392c3043287dd096b43b4a37ea7f5dc1d298b0623ccbf4fd650a4
+Payload = d1a9e4593bc3d02c407e84a1736e587c1819c72195a07d57
+CT = e73866ddb9d2c63e81c31224790d3f0de3c8f05133bdbaf0d1f677deca1bfda83c1b9223aaaedbfc
+
+Count = 275
+Adata = 966954582e78e99ba68d6ffaf794b55a82325834ec4f373b2bd227
+Payload = 15b94910853a8f23dfb8b31c0262b8461f777075cc0937e9
+CT = 2328cb94072b99311e0525990801df37e4a647056a14f04e12937871932a7ca3e1e27a90a7f73694
+
+Count = 276
+Adata = b7aca715dcc402565cb711b001f21e8e95ec54c4afab2e2dcc8a2f
+Payload = fd1681cc306518bf77766f55226afac3eb21e31ed897075c
+CT = cb870348b2740eadb6cbf9d028099db210f0d46e7e8ac0fba0464ff4ddeccbd523a5ed3b32337f7c
+
+Count = 277
+Adata = 290a36f7daeeeafca4431446b396dbec0bea0a1f6f081418811656
+Payload = 0804fa48fc76f98bb021e3501bef8875b64a3b508adf8594
+CT = 3e9578cc7e67ef99719c75d5118cef044d9b0c202cc242332f68ed5e44a71c5ba8bade07b7bf5495
+
+Count = 278
+Adata = f0739a855422310a21ed863376bce9d75dc7c687b9b535cb7a05cc
+Payload = 4f5c6d80a3955f12f4d2594e02a045c42fabb11d90817fff
+CT = 79cdef0421844900356fcfcb08c322b5d47a866d369cb8583b5dc1fbe32743e257b7c1c9d624adc8
+
+Count = 279
+Adata = ffac0edb0b62977bb5040e4128a48deaf711f5e6a84d8f677341f3
+Payload = 5c29c458212d010a0d9c5a547aba1138eb4ce94742fef01e
+CT = 6ab846dca33c1718cc21ccd170d97649109dde37e4e337b9e53b654de1976294897cae0476ac6248
+
+[Alen = 28]
+
+Key = 6351a67fd6daabd2fd49ee944dd41dd37301f958dd17fcc3
+Nonce = b8d517b033754058128d13d11a
+
+Count = 280
+Adata = 511c6924fa96db716f6b053b7a48aebdc1504145a56cd02d6be2590d
+Payload = 0c0663dd69ccbffbbd0c8c2e9473d0354451ae7a20fa3695
+CT = 19f2745df5007619c79c84d174e4521b942776478a0601d982c560fede4741e2fd3b54b3a48f3e38
+
+Count = 281
+Adata = d9ccd93317441e9d6ccc358f31e7e2ccef8c921b23d742993eff9d53
+Payload = 34a882834172924d39d2df5d637d9d273a99a9222971701c
+CT = 215c9503ddbe5baf4342d7a283ea1f09eaef711f838d4750ee82d927a2aa678e792acdeb615409f8
+
+Count = 282
+Adata = c268d65f7a7b30d3d198b2045fc8d1db7adda56604fa567d8855d1a5
+Payload = 5b7450b73d68de079e92bba56c7860f11126b8fdedd3334d
+CT = 4e804737a1a417e5e402b35a8cefe2dfc15060c0472f04017a48226389d24ed3ec3da2da1a9bdf7c
+
+Count = 283
+Adata = 4c2b6815156f0643b4573825e28b9f2a668a4976e3342884f48bc310
+Payload = 140c6933248f052e05bd4a36aec185ee86730108cc2989b6
+CT = 01f87eb3b843cccc7f2d42c94e5607c05605d93566d5befa16fe6bd83993ccbdd50e1ca061f4845f
+
+Count = 284
+Adata = f11c873354b3c0cff2c8f8010e9e364582b9c05c62efdefbdcc2e1c0
+Payload = 2a083de317380d94dd991349a7b8761c7c98013b1b0227e0
+CT = 3ffc2a638bf4c476a7091bb6472ff432aceed906b1fe10ac577c5893cb3896400012e48f5b190b73
+
+Count = 285
+Adata = d0a056754098d7f7ef2f639d61ea3d2b9cc936c48a1b2c5a9e96d169
+Payload = 02769283d5a06c363c2cc66c09b1ac954134e3ec7df773f2
+CT = 17828503496ca5d446bcce93e9262ebb91423bd1d70b44be80c80101fdfe6dc4cfce080bf921582e
+
+Count = 286
+Adata = 56de0e55653b9a04a3ded71c31f8807c3c8dd96bc82892e4acccef30
+Payload = 4890404bc5b24822b4cf7a2fe28abc52fbefb919ae0629ec
+CT = 5d6457cb597e81c0ce5f72d0021d3e7c2b99612404fa1ea0122dfc20e3088dcd33b6706a0c1fdfa8
+
+Count = 287
+Adata = 794a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b425
+Payload = 161f8501f59338f72026815c77cad6d8d581859192cd5644
+CT = 03eb9281695ff1155ab689a3975d54f605f75dac3831610828f0a78ce798448529afe26eec875aa6
+
+Count = 288
+Adata = b1eafc03ea2fa3e9e3842a09a225e83055de8a1f412badd6fc9ead12
+Payload = b3f38aedbf08dd7ead9d402c5aaa1ec9279c7e4bfd4a2967
+CT = a6079d6d23c4149cd70d48d3ba3d9ce7f7eaa67657b61e2ba48856a266c0d404474316f418f8f4e4
+
+Count = 289
+Adata = 8fec99f1be0e69267620c0b934bf984d60c1437f74c6ac19610fe188
+Payload = 5c09e2a6a055fe9c21e06e5519cf56b8e2e7fb44094e79f9
+CT = 49fdf5263c99377e5b7066aaf958d49632912379a3b24eb56412292d8015285efaa6f1154580eb57
+
+[Alen = 29]
+
+Key = 9a5a9560baed3b8e0e90b92655d4e5f33889e5d7253d9f6c
+Nonce = c0049382cdd8646756d4e6bff5
+
+Count = 290
+Adata = c95a86d52088a8b0107cc5b437a8938b2c9e74e46e2e03bb9bceecdbe3
+Payload = 5bbe9c1fb2563e3e82999fe097b28da4dc6ff2e020f3b4f3
+CT = 6d5401db42b5c48b79203b6ad82806d7460ac4c82ad0809b811020480e834f6fe55900a162a4e61a
+
+Count = 291
+Adata = 1dd56442fa09a42890b1b4274b950770ea8beea2e048193dfa755a5943
+Payload = 8a85a9b32a323c6af156a3fa2f1448b6387cc3660aa8a0f4
+CT = bc6f3477dad1c6df0aef0770608ec3c5a219f54e008b949cba9827513c7f1de970d316b6f81c109d
+
+Count = 292
+Adata = c834096e059ea73ddc90b0c982f9a3a31bfc6b1b81a03f9d41c9c741e7
+Payload = 1e02c13104937fe084b18eba1ea8951dcc5e75b692937dea
+CT = 28e85cf5f47085557f082a3051321e6e563b439e98b04982c9d79dd3255a8323f8229ac1c6d76ae4
+
+Count = 293
+Adata = 9249022bdead3d86ef5bd03acf053132d08663ba1f2426e19c126b22e9
+Payload = 3225570fb15ae13a13c71e364ae9a9fef03d1c9a7fa5dfa0
+CT = 04cfcacb41b91b8fe87ebabc0573228d6a582ab27586ebc8425dc81f93257ae8399fc2d48b4a7685
+
+Count = 294
+Adata = 3c3a92c4ece49fb9f84243d7c1bc91f595fce118305a758c83985c34b4
+Payload = fa0a458174537ddba25708b8d0c22d5517d57b122517b0c9
+CT = cce0d84584b0876e59eeac329f58a6268db04d3a2f3484a1b595003c58e69600c2a3b9ec45c0e15a
+
+Count = 295
+Adata = b49b845ccf76acf508f9db8543c73375d530d91f3b0e4ed70decfd2c2d
+Payload = b7fbdaeaa3ee1d0bbf5ec47898b069ec4ba6a140a3e83996
+CT = 8111472e530de7be44e760f2d72ae29fd1c39768a9cb0dfe0da009261c43c6640303696655e2981f
+
+Count = 296
+Adata = 3aabdf589eeb1709bb3d60b08bc71eaa3ffeba4e2903a5dbd8339aae85
+Payload = 9aea86b9fbd9bd4504ee2e25054942b33d3cdbd84215db7e
+CT = ac001b7d0b3a47f0ff578aaf4ad3c9c0a759edf04836ef16dfdcdbd4ad711c493d3176f032a02af0
+
+Count = 297
+Adata = 6a79879cd62bd1dbf9609897d2ebf2dc4dda43cc15fcb241aaa0deb4b3
+Payload = 3a861638ccd6591e51e2a525be59447e4a28bab32e36a5f3
+CT = 0c6c8bfc3c35a3abaa5b01aff1c3cf0dd04d8c9b2415919bfd59b45c05873c670f5f8bb47732d59f
+
+Count = 298
+Adata = c5b6ca474eb251817ae4d2f47c0632c381e222aae3b6f585a0dcae120a
+Payload = c7da4e9ba6e5758be726e6e227d7bddb0332228f7e3ecb6b
+CT = f130d35f56068f3e1c9f4268684d36a8995714a7741dff031572a24bc00b40a6b4b172b3648142e7
+
+Count = 299
+Adata = 64a96d191f1d5f95f5fed6259e33e7206adc07b0279e16cb453a9c6438
+Payload = 2b9347d3e195152dce22afdb92acd179eb484872285704c3
+CT = 1d79da171176ef98359b0b51dd365a0a712d7e5a227430ab828bc33396179ac39ce0027a1d62e0fe
+
+[Alen = 30]
+
+Key = 3e61094c80df0053e86d43fccf4e1d3ee2cdb862d3237b0a
+Nonce = 63f00b2488809fdc49ca5f05d5
+
+Count = 300
+Adata = a08763ca936abdeece06467bef8c3c47c3a473636a039d4db540c867d3e3
+Payload = 1fada8f4c7daea0d1c370184c169485b80a278708ed41451
+CT = 680dd22f16a1290bde42c9792dfa997aed24d5bd2265b6e095aa6b99d3f894d3790c2aa2dae1ba2c
+
+Count = 301
+Adata = 19508a6c83b992c660a1a28597e07c729ea2ed39401aadbf9d7586b5720d
+Payload = e9f1f2cf0b8d563e2d20f39f9f464a808b136dba364a6446
+CT = 9e518814daf69538ef553b6273d59ba1e695c0779afbc6f72d9d77109f4597e9c4c8cf7023dc5f3b
+
+Count = 302
+Adata = e5929c3b5d68a4c9fcf1168ea35bf8c0bf3043cb1ed54ff301578b3b7266
+Payload = 07a74c3b874849ecbf013713b80a84337c90b690cea0b837
+CT = 700736e056338aea7d74ffee5499551211161b5d62111a86b2544ecc3c7d5accd22ac075e7b44d5a
+
+Count = 303
+Adata = caa5cc5d0d87680eafc29429bac55c9e33167d485789c7c124b5c57a1ba8
+Payload = 4255f2cf90f0d15e9bead4be799165c57f7225980713d609
+CT = 35f58814418b1258599f1c439502b4e412f48855aba274b8f1a8a1db25de0fab7cabb11a18497584
+
+Count = 304
+Adata = f61cf7ae23a66777bd3fabc3d542feed2b00c6d4f46a772fda11b5214551
+Payload = 70b1e2e4cf260b108f5a52d0d8234838ffd6ffe7b4acd78d
+CT = 0711983f1e5dc8164d2f9a2d34b099199250522a181d753c5a9718ed0257a50e38de86154054fc3a
+
+Count = 305
+Adata = 85f647d940a6d1acb6b7851912f807063515631eaabaa019dcfb993e86f4
+Payload = af4be10b3a59ea99dadc75fbe5651f6f7630852bb556aa39
+CT = d8eb9bd0eb22299f18a9bd0609f6ce4e1bb628e619e70888550d1acca34c28ba8a3b890bb0542b23
+
+Count = 306
+Adata = 296cd04c4d9ab493def7aeb6841a45309e777028868efe45166235c56b2d
+Payload = 72d5663727592f1bfc9c65be83f4d3508126fecc4e34ae72
+CT = 05751cecf622ec1d3ee9ad436f670271eca05301e2850cc3a268dc1596a7855639c63fa76ad8479b
+
+Count = 307
+Adata = f380ca0a26a94adcf2c1ce26d226d3bf520268c72412e58a71acd9a66d00
+Payload = 3e2ccce03c10ce1527ef8e002adb265edba5779fbd4fcaf6
+CT = 498cb63bed6b0d13e59a46fdc648f77fb623da5211fe6847e3416c75fc28924a21cc123e62a7894c
+
+Count = 308
+Adata = 8825532a31680cb3b5bdb027802d2d8718755e135367e0c8c88e21288311
+Payload = a18dfe7f2d7bbaf316366f67445170afcbe18e2a1de1e947
+CT = d62d84a4fc0079f5d443a79aa8c2a18ea66723e7b1504bf6ff1a47f23d08485951aab18b393584ef
+
+Count = 309
+Adata = f768375589b687fb17c56673af4263626da69eb991007d94d4f5a163fd05
+Payload = 17ca72a440c944fefd6c08ecc3a8ecb54d96b9cad9d2aa4c
+CT = 606a087f91b287f83f19c0112f3b3d9420101407756308fd7d024456bcb69a4f77008773a3f48805
+
+[Alen = 31]
+
+Key = b5664dd6ed435df006052f6ded74bb7ce9482ca9229886f7
+Nonce = 7a1649896f3e030c18f0205599
+
+Count = 310
+Adata = c5f1a26351e53e6509c8bbbed03c42c23ad81c65fccec7ffa1cb494c7f1fc4
+Payload = 0b6de49b530703affc94010c2b793ddc6de0c44d48037ff2
+CT = 56b02fea595cc24e798691ae905be3d466ca68ca744005dba260b5ea3b047020b73b5bafa17e5084
+
+Count = 311
+Adata = 89899be18b4c389afa769b11ecd22e9fad8f38fd614ea5f8eb7a066c0ed8d8
+Payload = 2f1821aa57e5278ffd33c17d46615b77363149dbc9847041
+CT = 72c5eadb5dbee66e782151dffd43857f3d1be55cf5c70a685e4bd97b9dc83134867c00c2acea0aaf
+
+Count = 312
+Adata = d43b841f174335f1347834590b0984a2cb35f7a00a0ee993157d2d4f848748
+Payload = c7da4e95cb38342c6d5bf0c381d5a192adc3bfc1cda3a1d7
+CT = 9a0785e4c163f5cde84960613af77f9aa6e91346f1e0dbfe55202ba34bb9918fe915776de65947c0
+
+Count = 313
+Adata = c1093518efd80245e3c42371f220b21f2034e6738fe02ef43e828190f01aef
+Payload = 414a70aba5a219dbd41cdc46b84812b28cc4f7399218004d
+CT = 1c97bbdaaff9d83a510e4ce4036accba87ee5bbeae5b7a642fdf807b5a6880f2d4c36d558b40eb90
+
+Count = 314
+Adata = 90f627d5b939625bc76fe1bd4643b39edc11d3dc7f4bfe16e61bc26c3d49d8
+Payload = 58b260d3f645a35bad7a3842440bc03608248bd46e725e60
+CT = 056faba2fc1e62ba2868a8e0ff291e3e030e2753523124495a9307ca4239380a45bb7f87e41c4cf7
+
+Count = 315
+Adata = 2f360a4715074e942244ab7f9b6db127b0442df9af2efa2e78db1a94312905
+Payload = 5505caa97218957e90247fde60275bdafce4b16bcb36c263
+CT = 08d801d87843549f1536ef7cdb0585d2f7ce1decf775b84af3aeadff9dd60468aef2a8e2c56dda7d
+
+Count = 316
+Adata = 7db564811f14bc5c2098d5635655c3671fbd8288ea14944af925eaec653408
+Payload = b93e40f556a786e39126b8834a6ecacd2dc9f0f528bab135
+CT = e4e38b845cfc470214342821f14c14c526e35c7214f9cb1c8335f2e31a0468b830c5009cd02dbd5f
+
+Count = 317
+Adata = 36be91854d3d02a5d62503bb9047ef4354280510f7576c4272fd757240b621
+Payload = 543a070fdb3a855dd7d83fbc5f983671ad9e905f307148e4
+CT = 09e7cc7ed16144bc52caaf1ee4bae879a6b43cd80c3232cd5d772a599e91504e022b9dbfb124b71a
+
+Count = 318
+Adata = 6aa6ea668df60b0db85592d0a819c9df9e1099916272aafb8813ccc2f2dd96
+Payload = 86ef67572cb339c6706eb5909b96848aba5246a196972a1e
+CT = db32ac2626e8f827f57c253220b45a82b178ea26aad450379846cd12430f7adc910d1f0c51d80636
+
+Count = 319
+Adata = 3a64414c3588d7c26871d7d054ac6c8420d4917e3baad4a343685916265321
+Payload = cecef24b62676a5623bedae8087b9b05d7e22b41a14dd2d5
+CT = 9313393a683cabb7a6ac4a4ab359450ddcc887c69d0ea8fcd9ee65ac3a8fae1b00a4f1dfe2577293
+
+[Alen = 32]
+
+Key = 50925853a84a33ff392154e4e737efc18dcfc98f4d5235a9
+Nonce = 809343e986f6ff47f54d4cac22
+
+Count = 320
+Adata = d70aef3532bdc5293a3ebb11589ac1f801c9f93ea0d656e1d04068facf9f768b
+Payload = 718f061e8b972a3adcf465d66c5b28e8661f080127f6722f
+CT = bad3b0e6772e9c4c9c631c095e259d99692292932efb72b8966e91a19617bb748f3495aa433585bb
+
+Count = 321
+Adata = 1ee0eb409398bc252175cb460ef9a2da4c9beab2ef6d8206e4fcce74df785246
+Payload = 72e6cebdaf88205c4e74428664bc0d7eb4687a272217b7ca
+CT = b9ba78455331962a0ee33b5956c2b80fbb55e0b52b1ab75dc8f70aa565a12ca3545e68110968040f
+
+Count = 322
+Adata = 3820db475c7cb04a0f74d8e449f026ec951fa59667738698b0ed5c8cb09a8c96
+Payload = d959dd38a458039e2400d21d27b9a2faee8fe23683330cb5
+CT = 12056bc058e1b5e86497abc215c7178be1b278a48a3e0c22daf38076c810e14a7843444a02f010e0
+
+Count = 323
+Adata = f555216840a1f40b411d44128e567617e2694caf16216ea74c604a8d6ec01e72
+Payload = 337f12e8ebc0544b82fcdd3c4a0dab0e5e75c9f433a27d66
+CT = f823a4101779e23dc26ba4e378731e7f514853663aaf7df1594aebf9b8318877bdec2900a22df858
+
+Count = 324
+Adata = 2311a6fe1feeda3a1f16310d635496c0dd662024f0b0f1de79325e030cb850e5
+Payload = 463c65fa7becae5605af80d1feca59075ee88c0abfc72cb4
+CT = 8d60d302875518204538f90eccb4ec7651d51698b6ca2c231d9872d1c10a6594b5c349b84f710d64
+
+Count = 325
+Adata = b2c633e3181ae5fe7828707ed5b70e0460088a84465eadeecdbcfa0e9ff19bb1
+Payload = 23c1732959c4bf85bc707e45cc964b6227acd3a8fc73e675
+CT = e89dc5d1a57d09f3fce7079afee8fe132891493af57ee6e2a9db7c4bcaf6087e158c1a5d4eb1c2cc
+
+Count = 326
+Adata = 791f23252094b9b99fafe7fac1d8ff3ba09305c476041e75afb245ac438b4069
+Payload = 02f60f967e7fbcf957313619882407ea8a03fc943062296c
+CT = c9aab96e82c60a8f17a64fc6ba5ab29b853e6606396f29fb5e1c87d9e1c1f3b7d30fdc2f0ccac783
+
+Count = 327
+Adata = 22197f9ad14591e7a6d5f8b18c969a553de9a85309757fa5d319cc505c24f438
+Payload = 6c1aa088d1a6086d0e72636744a6840c80ab8223409c61b7
+CT = a74616702d1fbe1b4ee51ab876d8317d8f9618b1499161201514b449a741e07f9287f7e9090fa54b
+
+Count = 328
+Adata = 0bb18f7280a30767cd769cb5ffd3edd1c18914b92d1b2192e27ac88f57135616
+Payload = 57275bc3b4d63b9b01b0b0760235c9785d45761cace23f1e
+CT = 9c7bed3b486f8ded4127c9a9304b7c095278ec8ea5ef3f892c889b610157e16e9f31558c669298a7
+
+Count = 329
+Adata = 3e5f0f32e27be18ca6f84de11e6e9c25fc0c4cb0cf83633eea1f033aa1373f3c
+Payload = eba27a27f0d4604a5296a41b3fe995c50c66bcba302d0447
+CT = 20feccdf0c6dd63c1201ddc40d9720b4035b2628392004d0fbe19321dc22c748a17aa5eda29d8cf3
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT256.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT256.rsp
new file mode 100644
index 0000000000..af4f5c1df7
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT256.rsp
@@ -0,0 +1,1823 @@
+# CAVS 11.0
+# "CCM-VADT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Plen = 24
+Nlen = 13
+Tlen = 16
+
+[Alen = 0]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886df3ba3e6da3a1389
+Nonce = 72a60f345a1978fb40f28a2fa4
+
+Count = 0
+Adata = 00
+Payload = 30d56ff2a25b83fee791110fcaea48e41db7c7f098a81000
+CT = 55f068c0bbba8b598013dd1841fd740fda2902322148ab5e935753e601b79db4ae730b6ae3500731
+
+Count = 1
+Adata = 00
+Payload = e44b4307234281209bd41f89dbe2cc3fbf68e14df2f7fce4
+CT = 816e44353aa38987fc56d39e50f5f0d478f6248f4b1747ba003abc6a4b020625adc8b6cd7bafbd42
+
+Count = 2
+Adata = 00
+Payload = 8db7a73856bcb4007346bb3e00096f69e75e97c0bb960f3b
+CT = e892a00a4f5dbca714c477298b1e538220c052020276b465e7cfa7a208a8b3e6b6377236045df17d
+
+Count = 3
+Adata = 00
+Payload = 48f3ceda4fd390a7eb38f7f5bcd14310af6b5a557e676d44
+CT = 2dd6c9e8563298008cba3be237c67ffb68f59f97c787d61a81b39a0c55822e32042b4f8981021090
+
+Count = 4
+Adata = 00
+Payload = 7cdb2c9b167b3ae811289acf7dc1814bbe241f553447699f
+CT = 19fe2ba90f9a324f76aa56d8f6d6bda079bada978da7d2c1091117e2ad77db510d902038743b5a98
+
+Count = 5
+Adata = 00
+Payload = 41eacf70d05a6d0cdbdd38f197a52987def8fde37f332eeb
+CT = 24cfc842c9bb65abbc5ff4e61cb2156c19663821c6d395b5ac7379b8e51592b98e4874f4592278a8
+
+Count = 6
+Adata = 00
+Payload = bde9e3eb9f0c57302c9185b1cb912ef76d88f2f9c3b51e9a
+CT = d8cce4d986ed5f974b1349a64086121caa16373b7a55a5c4d08c1c902c4c2f078452dd6943b85028
+
+Count = 7
+Adata = 00
+Payload = 6f9ccc033c6bfbdfad4719ad033c927e2175727a9a021dc6
+CT = 0ab9cb31258af378cac5d5ba882bae95e6ebb7b823e2a69832fefb87445f1ca42811899acc0cdf68
+
+Count = 8
+Adata = 00
+Payload = cc67bc3b7afd625b2610226d3b30e111e6aa47a3254f711a
+CT = a942bb09631c6afc4192ee7ab027ddfa213482619cafca4481d605a1019c8e9778b8928b4636053e
+
+Count = 9
+Adata = 00
+Payload = a10c81725f49ab9075fbf4d96be030a2d881d8501b115d61
+CT = c429864046a8a337127938cee0f70c491f1f1d92a2f1e63f96a82e8411e5b04426dc608298c6408d
+
+[Alen = 1]
+
+Key = a4490ed6ab51dbfccd6f3702a857575dad44da3a27eaf31178abc97da60d1e4b
+Nonce = 26ceaf6e3b28190a17c4f0c378
+
+Count = 10
+Adata = 9e
+Payload = 1b5cc6b1651dec4bbbf5130343852e971c7ff1774100d9be
+CT = 789bce069a725a96c484e64a9e54dcb7a7c268c85df47815a462ff2dd8ba44a381e1f6edab12b5a9
+
+Count = 11
+Adata = 4e
+Payload = e7ab98901c0cb1d7d76e125d8ac8e86edf6f469fa937bc10
+CT = 846c9027e363070aa81fe71457191a4e64d2df20b5c31dbb6b0789c5866b7e3312ad992e228d6d20
+
+Count = 12
+Adata = cc
+Payload = 53bc7e3648d0b389b887b065e9e8f79685beb2eb36e2eb95
+CT = 307b7681b7bf0554c7f6452c343905b63e032b542a164a3e39b1b1a480fdd268c1c75b131cde798b
+
+Count = 13
+Adata = 45
+Payload = 6d7262476da95db63b322c5193ea05030923c3cbf0f8e8b1
+CT = 0eb56af092c6eb6b4443d9184e3bf723b29e5a74ec0c491a32060fea35c3e9528fd18994fae9fce8
+
+Count = 14
+Adata = 2c
+Payload = 8246bf7b81b287411777df7ecb53a1795e54b150ff3dd584
+CT = e181b7cc7edd319c68062a3716825359e5e928efe3c9742fb4e0a604ab30a764e8c98a9cafbca8d4
+
+Count = 15
+Adata = a9
+Payload = 2596ca8772bc69b50bcbf33088c6efbab614b691ed836f92
+CT = 4651c2308dd3df6874ba067955171d9a0da92f2ef177ce397ca72f1acf6dfd078b6f4eb82fa01e9b
+
+Count = 16
+Adata = 85
+Payload = 703065d701f4fcadee20d64300b3082c0c76490eb2dc4ba7
+CT = 13f76d60fe9b4a709151230add62fa0cb7cbd0b1ae28ea0c2a85c9252ee62612dc29cffa7289b2ca
+
+Count = 17
+Adata = dc
+Payload = a1aeda4b4cb8dd2943675181561bac48ba07e8de5b327837
+CT = c269d2fcb3d76bf43c16a4c88bca5e6801ba716147c6d99c9fbdac729413152c089d3939e30b8602
+
+Count = 18
+Adata = ce
+Payload = aa17341f4cead054d41c171dd34c459f7052da225c6c365d
+CT = c9d03ca8b3856689ab6de2540e9db7bfcbef439d409897f6f86266c273f8184e901b50c04845b8ab
+
+Count = 19
+Adata = a6
+Payload = 448cdd9cbbf863eb666fda36b825f3798827da3c1349611f
+CT = 274bd52b4497d536191e2f7f65f40159339a43830fbdc0b4ddd02d5c9ae2bbac47a7a076edb1d207
+
+[Alen = 2]
+
+Key = df594db94ef8eca56a417afe946085eaed444c7cc648d07d58132e6cb5bc2bc3
+Nonce = c1ad812bf2bbb2cdaee4636ee7
+
+Count = 20
+Adata = c0c3
+Payload = f4d7978fad36223623ccb5bb18a7373cba8a6e3b1c921259
+CT = bea778540a90033b2c0d087e3cc447711ea25f7eea96855506ec97f23bd6ea97834f92f7263c3195
+
+Count = 21
+Adata = 34b9
+Payload = f6c043c70136585d012ae0df6f42b25584e374649d0116c5
+CT = bcb0ac1ca69079500eeb5d1a4b21c21820cb45216b0581c9f3230df0b52b5cb7ac907dcadcb662ca
+
+Count = 22
+Adata = d4ab
+Payload = dec0c896b04490816409da1783478ef2510231d0a28c5b39
+CT = 94b0274d17e2b18c6bc867d2a724febff52a00955488cc35a99c3165ce83102891ef3885088ed6eb
+
+Count = 23
+Adata = 2a3a
+Payload = cbfd94fc31785d30214271dab2264134805fee6e52aa0b5c
+CT = 818d7b2796de7c3d2e83cc1f964531792477df2ba4ae9c50c9d8078607994ae5dff0de6526fb53d1
+
+Count = 24
+Adata = 4eb1
+Payload = 134d2d9726400d09dd3521326f96fbef993ddc0c40887700
+CT = 593dc24c81e62c04d2f49cf74bf58ba23d15ed49b68ce00c7e84da7d2564533e7ad55390ec3a6ff9
+
+Count = 25
+Adata = 0a79
+Payload = 1ccdcf789d42caba80d7893feaf26d3853fbcaf7d964df0b
+CT = 56bd20a33ae4ebb78f1634face911d75f7d3fbb22f604807520849295a56191367a696999ffef8e9
+
+Count = 26
+Adata = 865f
+Payload = 4042dbe148db3e6dc542b25d57a5787af535d38e8c34c71b
+CT = 0a32343aef7d1f60ca830f9873c60837511de2cb7a305017bc4aceed1a10309b6402b9e9420b33a3
+
+Count = 27
+Adata = f4ae
+Payload = 85b6894fec36294aa934cdc3523fd95c90ad56cbd18545dd
+CT = cfc666944b900847a6f57006765ca9113485678e2781d2d176c180d2e299ccf0b8781ba6de8a72ce
+
+Count = 28
+Adata = 10bf
+Payload = 0f27f4fc8538a676a763b3e5db845a1bfb20d5fab340dee3
+CT = 45571b27229e877ba8a20e20ffe72a565f08e4bf454449ef98d91c68d94873a5d6557611a5402a0a
+
+Count = 29
+Adata = b92e
+Payload = 1b5ec0cb03810a12fc6a0a1ff565afb001405d2a45a1f18a
+CT = 512e2f10a4272b1ff3abb7dad106dffda5686c6fb3a566865321cedf1122354636e130acbd69718b
+
+[Alen = 3]
+
+Key = d98193ab2a465e3fcd85651aaeca18b8e91489b73b7c7e93b518c4b5b81fc6ac
+Nonce = 2247dc7e2674e9e0a63fe70613
+
+Count = 30
+Adata = 4dc2f4
+Payload = edba7d6312144e90ec9eaace7576045a46e553dcb8ee5a98
+CT = 44b9ea727c847336fd739ad11f4b906b292edb810462f06ef59626ad5cdac2e4d4cb07b538a1fd8f
+
+Count = 31
+Adata = 2f3bf0
+Payload = 52a9626f5279c11e17e96f5dc5e1c1f58c1e913020d8499b
+CT = fbaaf57e3ce9fcb806045f42afdc55c4e3d5196d9c54e36ded0d53402253453e494ad350994ca77a
+
+Count = 32
+Adata = 95d2cf
+Payload = 87b6447d97a74d0b315031078aa06fffc7b9f246bfa5f147
+CT = 2eb5d36cf93770ad20bd0118e09dfbcea8727a1b03295bb196dbc3bff865a1d94b164df23d708e8e
+
+Count = 33
+Adata = 0caba9
+Payload = 1852848046706f2e274ba381a2bee1422df4f61d93219af7
+CT = b151139128e0528836a6939ec8837573423f7e402fad3001791b4469fe50d45f8efb81217cd68580
+
+Count = 34
+Adata = f8d459
+Payload = 99aac82fa66a15e4f76b76cf4590150999d5cf8468df7f42
+CT = 30a95f3ec8fa2842e68646d02fad8138f61e47d9d453d5b4587106da25012f92f01cc2db8d11ac29
+
+Count = 35
+Adata = e883dd
+Payload = 4e2f0f91990b855a00d27fbb2e8db7184cd82909de361b52
+CT = e72c9880f79bb8fc113f4fa444b023292313a15462bab1a464148536847290e4fdda7966fe6d5e3b
+
+Count = 36
+Adata = e45da4
+Payload = e558be3fd246170b294d18ffa708842242681890baf8bed9
+CT = 4c5b292ebcd62aad38a028e0cd3510132da390cd0674142fcc4cb33472825363940e2b26424b7802
+
+Count = 37
+Adata = 3b6fc8
+Payload = f8b284c2d851289275973fcd807fac5d8e5e3b6a75ba2ace
+CT = 51b113d3b6c11534647a0fd2ea42386ce195b337c9368038a99dd8dbe89b3ecf663eda1b0f92be7f
+
+Count = 38
+Adata = 043d68
+Payload = 8edf1eb90f0ad33be8a7c6446899e06addc10b3badc4ea25
+CT = 27dc89a8619aee9df94af65b02a4745bb20a8366114840d3dc4894c8fa0a1e1aa760acf9360042f5
+
+Count = 39
+Adata = e89257
+Payload = 8fe9a6bd82462c97f436d382d1ff971c95406b1a6c847d81
+CT = 26ea31acecd61131e5dbe39dbbc2032dfa8be347d008d777cdad1590fd8bf2d7ea919e60d0316566
+
+[Alen = 4]
+
+Key = 45c8afd7373cb0f6b092af3a633d9fd97c4ca378e19d75f9b74d089429726c29
+Nonce = fdb1fa230ae0b172ff98fc7496
+
+Count = 40
+Adata = 270981af
+Payload = 0b92adbb251dc29a67f0bb97f8e7160862b6c4e843d07fd9
+CT = 274e2faea3271ea6fa0494c1951f115b5491a893056c3ee4c76fc350e585277e373e9119bf9595cb
+
+Count = 41
+Adata = 633f3efa
+Payload = 1f88dfd4f5c52c22b1db47f9f4fb6e2f8bcd78d593061369
+CT = 33545dc173fff01e2c2f68af9903697cbdea14aed5ba52540fa7e55dc54e80488a05ee7f1fc96e9d
+
+Count = 42
+Adata = aad86fb5
+Payload = b2b4cb5e90ebf4bd265093b7f5efd4d62dc60e29737aa496
+CT = 9e68494b16d12881bba4bce19817d3851be1625235c6e5ab18151c17d9e3f97244000a3b2d3c2f95
+
+Count = 43
+Adata = ed42941a
+Payload = f312b47d05f8eb5a29943b41347cb1983c75cb7a458a3868
+CT = dfce366883c23766b46014175984b6cb0a52a7010336795562d521c4b5c7a6f2c5ac65f2fd15b066
+
+Count = 44
+Adata = e5b085d8
+Payload = e9fb86938ea7f04cc230296859e7c96fcc352f968c9473e4
+CT = c5270486089d2c705fc4063e341fce3cfa1243edca2832d9e491a31218f688744098851672a09a64
+
+Count = 45
+Adata = 3776f37f
+Payload = 8af6b7540f997954812e38dbd99ccfaedd5c69963c353a4e
+CT = a62a354189a3a5681cda178db464c8fdeb7b05ed7a897b730ece28347d7ebf8291d7eb66b7651b4e
+
+Count = 46
+Adata = 4eb08c9e
+Payload = b90cfd9dd58e320d98510483b1d939bdb5f3b81666ecee59
+CT = 95d07f8853b4ee3105a52bd5dc213eee83d4d46d2050af64cbd25fb40480d15c039878b5d2f25afb
+
+Count = 47
+Adata = c7f93152
+Payload = 02caabc6ed0641681e7148c10cf3159fe35e44013252071e
+CT = 2e1629d36b3c9d5483856797610b12ccd579287a74ee4623fbfd98c8567b78d4b9c3a49a4641908e
+
+Count = 48
+Adata = 57957630
+Payload = 2f29882fdf1418d04f0b9d44272995a56973c4369c687a99
+CT = 03f50a3a592ec4ecd2ffb2124ad192f65f54a84ddad43ba4655c1abcb3ed1a175f12721a407c5d00
+
+Count = 49
+Adata = 19da955d
+Payload = 4e427130be9e94639320529ec135715e65da1117b5ba3c76
+CT = 629ef32538a4485f0ed47dc8accd760d53fd7d6cf3067d4b90621a5e5683df421a0dc52341485d1b
+
+[Alen = 5]
+
+Key = a2e6bf39efd1ceddc92b4333ed92d65efeea6c031ca345adb93a7770a8039bcd
+Nonce = 693cbb46bc8366086ec7cd7776
+
+Count = 50
+Adata = 3ba11282d6
+Payload = d822f84b023f12ea9e3ce16b904278e4aaab5e11c2c23f3f
+CT = 9f91fd2f6472e33b02b1eabb9d6655729d44c44dad6b3883fe0667bcc5806b225224b04ade8b21c1
+
+Count = 51
+Adata = 3f3a4718ea
+Payload = af87b347b59e37a424004a00907dcbcf6a554e6782a9be12
+CT = e834b623d3d3c675b88d41d09d59e6595dbad43bed00b9aea6750fffa5a487540ce65770cd836e99
+
+Count = 52
+Adata = ff79ca8965
+Payload = 82b7cd168b6a82cb2d837f41ceda0c27adc5f5b28030454b
+CT = c504c872ed27731ab10e7491c3fe21b19a2a6feeef9942f7e7cfafe32bd71ea9813607c5df446c9d
+
+Count = 53
+Adata = 0021be18ed
+Payload = 1c1a0f144df76781e7c85ab178ed9b1ce8c6dc3f15c59149
+CT = 5ba90a702bba96507b45516175c9b68adf2946637a6c96f576716fe674c33ad3b9d3e54cc86bfccf
+
+Count = 54
+Adata = 9ae7996547
+Payload = d9bb71ad90152d5c1af358c8501fa89ebd4b17bf4ff43841
+CT = 9e0874c9f658dc8d867e53185d3b85088aa48de3205d3ffdab55dbee34f1bab555bbb196095fb5fd
+
+Count = 55
+Adata = fa292d1958
+Payload = fc7d028a1aa05c74b7ffe333ba6f676913b0f9f1ffa050b8
+CT = bbce07ee7cedada52b72e8e3b74b4aff245f63ad9009570476a4e9e759d5bb79c187a157099e3d12
+
+Count = 56
+Adata = 88800df7b6
+Payload = c9ea772e61742a6706da3ab3e81df14b31506ae58b063ece
+CT = 8e59724a0739dbb69a573163e539dcdd06bff0b9e4af39729f0f3699c9743ad6c9f09dc00ea10487
+
+Count = 57
+Adata = 715041afd4
+Payload = 70d2b8d64121ceccf1961444e8d33b7b7f998aeb58d3d270
+CT = 3761bdb2276c3f1d6d1b1f94e5f716ed487610b7377ad5cc560d78cba6d9f50e9c2677a710f92155
+
+Count = 58
+Adata = 14682301a9
+Payload = 1013946815001a2c08acca4196e0d6668ffbb3883cf111e7
+CT = 57a0910c734debfd9421c1919bc4fbf0b81429d45358165b95ffb6e29172a283d47e4478e2e1f7c4
+
+Count = 59
+Adata = e44c3c21c1
+Payload = f40dc834067bd163e0004d0ec5dd4b96e2a1ea31ea431c98
+CT = b3becd50603620b27c8d46dec8f96600d54e706d85ea1b24ccf233caf0bad9f68f71d78ee58512ec
+
+[Alen = 6]
+
+Key = c5a850167a5bfdf56636ce9e56e2952855504e35cc4f5d24ee5e168853be82d8
+Nonce = c45b165477e8bfa9ca3a1cd3ca
+
+Count = 60
+Adata = 4759557e9bab
+Payload = e758796d7db73bccb1697c42df691ac57974b40ca9186a43
+CT = 93ad58bd5f4f77ac4f92b0ae16c62489e4074c7f152e2ed8a88179e0d32f4928eff13b4ce2873338
+
+Count = 61
+Adata = 2ea07d393a0a
+Payload = ce60ddbe40b70bd55a9147036ad079dec1558ef4c2c625b3
+CT = ba95fc6e624f47b5a46a8befa37f47925c2676877ef06128b7d812c4d69f1f53ee9158382e56625b
+
+Count = 62
+Adata = aa6667faedc1
+Payload = 89eb3056770a6157f06921bc153834447c4b6d862d10d185
+CT = fd1e118655f22d370e92ed50dc970a08e13895f59126951e26fdbed62b228db008a1b14bd7942e12
+
+Count = 63
+Adata = 9e2127d92311
+Payload = 132f3e19e12f462a7463226b716c41a05a59c76f0e1a2f72
+CT = 67da1fc9c3d70a4a8a98ee87b8c37fecc72a3f1cb22c6be9124e1eb78de01b8af83b684baf3e43ad
+
+Count = 64
+Adata = 2f191bc9cff6
+Payload = b8611cbb9a3667b9458ca57eb636eb1dc580e7dbb5701692
+CT = cc943d6bb8ce2bd9bb7769927f99d55158f31fa809465209cb0f79736d1a810d06a776094f9fb67f
+
+Count = 65
+Adata = ad739d5f4736
+Payload = 112f89ccbdadc2433008d3ede2290f9ce81e5c736abf42a8
+CT = 65daa81c9f558e23cef31f012b8631d0756da400d6890633bfba2348f629471c232c9ff7e5f6f85a
+
+Count = 66
+Adata = 01acc909b7d3
+Payload = d47f2ff745de39a9055ad002de6334971fde480bef268b33
+CT = a08a0e27672675c9fba11cee17cc0adb82adb0785310cfa8c0f694d03ffed043787343827ea2603f
+
+Count = 67
+Adata = ce003c836a6f
+Payload = 13be365884b8a91a284ca24f70011e48794b51be275153b9
+CT = 674b1788a640e57ad6b76ea3b9ae2004e438a9cd9b671722279b553998a6fee0a86e177a448573a4
+
+Count = 68
+Adata = 6a759a4efd00
+Payload = d5c87c649579da3f632ba95cb0a07c924095e4bdd4e0376e
+CT = a13d5db4b781965f9dd065b0790f42dedde61cce68d673f54eeb434cca3ea719827417e94d6ed564
+
+Count = 69
+Adata = 02b84a26c773
+Payload = b7bc1580c68fd5d06c1bf75c31dad7a3e26d636d7eee20b9
+CT = c3493450e47799b092e03bb0f875e9ef7f1e9b1ec2d86422a74b5e4e2edb91fbbe722bfaf1500db4
+
+[Alen = 7]
+
+Key = ae8f93c3efe38e2af07e256961dd33028faa0716e5320a7ab319a10d2f4c5548
+Nonce = 6333bde218b784ccd8370492f7
+
+Count = 70
+Adata = 0b1fabdf2a4107
+Payload = bc9ca92a9c9919e39095d3e53fb148694620ae61227e0069
+CT = 45811b0c8f754bf03950e520cd4afc81c2e3eb8a11f4fd386d5a6e4b1fbee15d35939c721004502e
+
+Count = 71
+Adata = 2fc7f5c0ce052f
+Payload = f25a4ca20bbf4969bed6b93c1c77e3d7415f60fe3784216b
+CT = 0b47fe8418531b7a17138ff9ee8c573fc59c2515040edc3a24a68f98716190fb55f743a8bf62a085
+
+Count = 72
+Adata = 8a74412da3034b
+Payload = 3237bf953989d17c65a0fafd2bb1e32c237f98f55389e8f8
+CT = cb2a0db32a65836fcc65cc38d94a57c4a7bcdd1e600315a923afef7b4955d7d1e8f1abef9933bf9f
+
+Count = 73
+Adata = 7139f3c1d6cc36
+Payload = 55d86dc0423cfc2616ef996a3316e776707f8d25c985884a
+CT = acc5dfe651d0ae35bf2aafafc1ed539ef4bcc8cefa0f751b8e824c62632dff5cbc103d3060fbd174
+
+Count = 74
+Adata = af7a380f079aa1
+Payload = ac48398adb10292314973946f261ec39397442ca09b98dd8
+CT = 55558bacc8fc7b30bd520f83009a58d1bdb707213a33708980202d518ca871c9544f4a8c55fd8d20
+
+Count = 75
+Adata = e602abe8f72964
+Payload = 2fb78654e4395df8c37f260d74def234a3a4e3d2b1fe8614
+CT = d6aa3472f7d50feb6aba10c8862546dc2767a63982747b454b33ea6e4344033f74f513d1e41b82ae
+
+Count = 76
+Adata = 82741c5fd6e1df
+Payload = d488bdda400932de56a9f105f0e74ee79c2ed869faaadc31
+CT = 2d950ffc53e560cdff6cc7c0021cfa0f18ed9d82c920216073ccf18c7ea7dce79d0be1204c593234
+
+Count = 77
+Adata = 78f0cc22535402
+Payload = b22aba8d3e9f4b4bf006e26062de15daf94597731a600912
+CT = 4b3708ab2d73195859c3d4a59025a1327d86d29829eaf443b81b8af57b85093778690266e20e2fbb
+
+Count = 78
+Adata = 18e468139dd16f
+Payload = bd864f7b8efd6ed2b068f425482d449bf53a203ea88e1ca1
+CT = 449bfd5d9d113cc119adc2e0bad6f07371f965d59b04e1f09b94a857e7a0423ef6c9cbebde1f9c40
+
+Count = 79
+Adata = a6dab47c0fbfe1
+Payload = 47d9d18b6addc5f88986f0457b666faae59aba4fa3a02abb
+CT = bec463ad793197eb2043c680899ddb426159ffa4902ad7ea64718820065a739fbd3ba560a416895c
+
+[Alen = 8]
+
+Key = 548c2d1eb7d91e003633d4d9ff199e4a8447180edd89ac7867d25a1db288b5ce
+Nonce = 23b205bd6ff8ed0bab0c98999c
+
+Count = 80
+Adata = a6601111cd92c943
+Payload = 49fd5cbe4aff89dc3b8718f9ce545d612cbbebb289ecbf42
+CT = 3cfc6211e359ae322802fc9566f377b0dfe17d1dfe0878ebf2a9047e37cc0be1fab0006af8db8dc4
+
+Count = 81
+Adata = 96f0b7cd7439721d
+Payload = 94a95e945f660d1571b4d7d22709b000b45ff98b2129a4ae
+CT = e1a8603bf6c02afb623133be8fae9ad147056f2456cd6307106a430b04938e97f2e4cda81108ad3e
+
+Count = 82
+Adata = 2ee135dc2ddd9501
+Payload = aeed3aea01755c912213c8c276a2b75dad24f888a611efa3
+CT = dbec0445a8d37b7f31962caede059d8c5e7e6e27d1f5280ab2ab219c6c4952d52505cd9f904b0e04
+
+Count = 83
+Adata = 10c361934fd6ff77
+Payload = be1fcebea4c22a1d71e08047b028d7f4ccab0a6b8085d344
+CT = cb1ef0110d640df36265642b188ffd253ff19cc4f76114edfc1f7b2fe314faea28ab0dae349feb9c
+
+Count = 84
+Adata = 3f6c8a69917f7776
+Payload = 87680ac26fe1511e0f1f745aa4c2a5b9f6c0117dcf08feaa
+CT = f269346dc64776f01c9a90360c658f68059a87d2b8ec390308e529d64e786a29661cccddc0366f3b
+
+Count = 85
+Adata = 0f7a1426ff3b5ee1
+Payload = 9e004b072a27b085e59ca201c157c7d3c906a2c3b455c56e
+CT = eb0175a88381976bf619466d69f0ed023a5c346cc3b102c797c6510b85dfd097f3eac276aff00ba2
+
+Count = 86
+Adata = faa5bed84dcf168e
+Payload = a1bf47b15cd66e43daff420edf014a14b11994b97ada4030
+CT = d4be791ef57049adc97aa66277a660c5424302160d3e87998e522b6f13f99ecb553b6de845940907
+
+Count = 87
+Adata = 2851dae3cb3fcb1c
+Payload = 2d15734871adc63ff32d7002ab40c4a235a4d5fad223953f
+CT = 58144de7d80be1d1e0a8946e03e7ee73c6fe4355a5c752967a9ca39566189ee96c86462bfea78af5
+
+Count = 88
+Adata = 35a29c1bcbe2182f
+Payload = 5a84c4fdd47510fb7aebc0f79d7b625ccd0a96575740b8e6
+CT = 2f85fa527dd33715696e249b35dc488d3e5000f820a47f4fa613b5fbbe73a2df6c630a00ff4b1b92
+
+Count = 89
+Adata = 45820ae66c3e8e77
+Payload = 2052a94e1392dc1db0e89be19ea8f7379ee4cb607a914c89
+CT = 555397e1ba34fbf3a36d7f8d360fdde66dbe5dcf0d758b20d19feb067e9f6225376da21b4899d296
+
+[Alen = 9]
+
+Key = aab793e377a12484dbdd74c9b3a85c74c286e1cc498663fbd7c718b5633bb91a
+Nonce = 10022cddb323e88b3c08f95a0f
+
+Count = 90
+Adata = 82b8c736037ce2f2e8
+Payload = 7c0889854658d3408c5d8043aad2f4ae4a89449a36f8a3b8
+CT = 1044250f58857c69f72b5d3454d43949e5c02b3822970b280de1a3f7fc5d06cc30f06075f5504ed7
+
+Count = 91
+Adata = 8f2777ec4930f7e349
+Payload = bd845561f099500a6ff3fd09964dc3820f7ab48ba4ed04d5
+CT = d1c8f9ebee44ff231485207e684b0e65a033db29b082ac45835840df6fa96f5c972ac09d94148cbc
+
+Count = 92
+Adata = 5cab3b846870709569
+Payload = a6e09404fe60badfc63dc228057485e6f563ba82acdabd7c
+CT = caac388ee0bd15f6bd4b1f5ffb7248015a2ad520b8b515ec2f83ef84b299cfdb61d2b5039d536c3f
+
+Count = 93
+Adata = 0938f2e2ebb64f8af8
+Payload = 33404d7e0e620c1030b91020e33619c5f53d8b210fa86489
+CT = 5f0ce1f410bfa3394bcfcd571d30d4225a74e4831bc7cc19db04e655cbe22b9ea508d2a03757b97c
+
+Count = 94
+Adata = 82f78ca0e0da2b2d3a
+Payload = 617868ae91f705c6b583b5fd7e1e4086a1bb9f087a50bf50
+CT = 0d34c4248f2aaaefcef5688a80188d610ef2f0aa6e3f17c04bd88dc6985f819004c2b634c5303ed8
+
+Count = 95
+Adata = 401191aa3fd34abe87
+Payload = 949cdd7c2973d7519e7bca98b2c5947e6d8e91c90e632319
+CT = f8d071f637ae7878e50d17ef4cc35999c2c7fe6b1a0c8b894ff3572e4ebf78473760d8cb4b0366b4
+
+Count = 96
+Adata = 4df4377596d8987671
+Payload = f6720a0bd8705c70e0f923338965e810b3ea939bad652327
+CT = 9a3ea681c6adf3599b8ffe44776325f71ca3fc39b90a8bb7de95ec3eee17753e60fb3c0661bdd098
+
+Count = 97
+Adata = 6593194b9970545c5a
+Payload = de9b0556661e726f3e6e34515ff7196420fe61b4f38419f2
+CT = b2d7a9dc78c3dd464518e926a1f1d4838fb70e16e7ebb162b8590ff04f967e51fbd1be84f01b4dcb
+
+Count = 98
+Adata = ab2d432058b540ac72
+Payload = 6cad7f3b9f196839bbc5a7f755c09aa8e17c83d9cb8b3954
+CT = 00e1d3b181c4c710c0b37a80abc6574f4e35ec7bdfe491c471d67b75b2da855a12ffb24ddd64a048
+
+Count = 99
+Adata = 5dc631eeeacb5a0b0b
+Payload = 70a55aec1144357377612fd0bbc2c817f33465a656219957
+CT = 1ce9f6660f999a5a0c17f2a745c405f05c7d0a04424e31c71fc798dd16c1fadef607a9297cbfbfef
+
+[Alen = 10]
+
+Key = 06ac39896073a44283611a66ccab067e2dd2faa8da82ff9a45bb29e54d2e6e77
+Nonce = 6c7942c9819cf69b817bfcdb0a
+
+Count = 100
+Adata = 215e2a6c24325340fdec
+Payload = 3216dce3b8b1ce0e79e40fffcac728ab191aaaf319d971d3
+CT = c5b3b50ed8a7b7b96b02ba9464b6a2ff80e90548605699a63d70e6dffb31a376a1eb7f94526dca48
+
+Count = 101
+Adata = e0a29a2c7840cf9b41de
+Payload = 7e5e5710a693ebfa36335cf7965574740880acdddd13fb1a
+CT = 89fb3efdc685924d24d5e99c3824fe2091730366a49c136fcbf516608fe20e06bbff931e84683545
+
+Count = 102
+Adata = b8026fbada6339d84802
+Payload = 08c342a50aa23362622934dfab55d9b22c22c249ad08138c
+CT = ff662b486ab44ad570cf81b4052453e6b5d16df2d487fbf9d70eb14f3fa0229906b9e0360be3d3f9
+
+Count = 103
+Adata = 65f4b3a00c1c1ef39445
+Payload = e085aba85882c75d5e41559167731496cf17d3907894352a
+CT = 1720c2453894beea4ca7e0fac9029ec256e47c2b011bdd5f4184771199a427861bf17cd8401e794e
+
+Count = 104
+Adata = 96118dbfe53434d8aed8
+Payload = 710f890be2b8da77c1eff429ede9cc931d50f059748cbcb6
+CT = 86aae0e682aea3c0d3094142439846c784a35fe20d0354c34e20b2db52fde68f88bfb886fdcb2c47
+
+Count = 105
+Adata = cdf4b485d2e04709cf8f
+Payload = cda96efee4e188ab3048bc1904ac2c36ab018f2ab7602682
+CT = 3a0c071384f7f11c22ae0972aadda66232f22091ceefcef782ee3df38ddea8e269eb47e39900345e
+
+Count = 106
+Adata = 50e57e57cf8e49e3a4e6
+Payload = 3dc596d52e520779a50bcba3049388b340dbf6d0f2eb94cf
+CT = ca60ff384e447eceb7ed7ec8aae202e7d928596b8b647cba44aaac4ed86f687cfc031f22827725f1
+
+Count = 107
+Adata = 48c670f11ff7f74e7003
+Payload = a33105c0dccf8e3b687212a870af9f710462756705fe09b3
+CT = 54946c2dbcd9f78c7a94a7c3dede15259d91dadc7c71e1c6d75255006ac037d6a4d048f1fc338012
+
+Count = 108
+Adata = 465e3be6113a2fb2ee20
+Payload = 573ac2436158eb7dd9be981e3cfbe75d3a188ea9cf2b1ee2
+CT = a09fabae014e92cacb582d75928a6d09a3eb2112b6a4f6976c1da33a80bc8157cece1acf9400b2bb
+
+Count = 109
+Adata = ee4e10574faeae85e9b6
+Payload = ca35bdb54e73eac5a5200a296b3aba5f37c87349746102d4
+CT = 3d90d4582e659372b7c6bf42c54b300bae3bdcf20deeeaa165c1cb98da4a1a920ca1ed9a7b6ec514
+
+[Alen = 11]
+
+Key = 50412c6444bcf9829506ab019e98234af1541061557412740bc120b456052763
+Nonce = 85684f94c3702c5d870310166d
+
+Count = 110
+Adata = f706a3e09df95d3e21d2e0
+Payload = 6cdbd63f6d591f59776f828533b28e2453a214d1d0dd8a39
+CT = 8c8b4ae854a5d5c265b25e3b54bded9444cc454b3e0e6a24d6c05eaf406a5ebd578e19edd5227380
+
+Count = 111
+Adata = e46b25b9a41a858e87900a
+Payload = 100132c315bfc9c4fb93023f5d3500d7208a68acb4d2c630
+CT = f051ae142c43035fe94ede813a3a636737e439365a01262d5088446e42591c0ede68e82334d97cfa
+
+Count = 112
+Adata = 28d34b29afe6586fd9bf0e
+Payload = d5460c1db0d24dedc63c4c78ce6d1f0b2d46f3b01934525c
+CT = 351690ca892e8776d4e190c6a9627cbb3a28a22af7e7b2413eaaef2823f5ac3f313f560bd774d10e
+
+Count = 113
+Adata = 2852d4fd68a3e9e47d44a7
+Payload = d2d73b62e3b1c9ab75f3544ff8616741e0adbae84b8cf9d0
+CT = 3287a7b5da4d0330672e88f19f6e04f1f7c3eb72a55f19cd62d30d99bb7dadec34e2891c156a1f5d
+
+Count = 114
+Adata = ec1c17b2ab13d7c8ac874f
+Payload = 74796d78d6ad03634ed80800af530212baa7e5093651cedf
+CT = 9429f1afef51c9f85c05d4bec85c61a2adc9b493d8822ec241c9a05ebf9ed27792bbced83b5dc582
+
+Count = 115
+Adata = 4f1ab5ddb1c199e9a5daab
+Payload = fb432488b5d08d576a90f085181ad883407a6ce9ea29950a
+CT = 1b13b85f8c2c47cc784d2c3b7f15bb3357143d7304fa75171ffc24020e86b1314724104e6b57b3ce
+
+Count = 116
+Adata = 864e0e728aea856fae6c6d
+Payload = 2b82d96ed1778412378abe4e09c633acf3359b9709ae3dcb
+CT = cbd245b9e88b4e89255762f06ec9501ce45bca0de77dddd6539bbb0af8ecf77b4508533247b3501a
+
+Count = 117
+Adata = 21ee21a5ed0d75d0380a28
+Payload = 85143071241bb65261fe7afcc102416e59b9e46ee0c90073
+CT = 6544aca61de77cc97323a642a60d22de4ed7b5f40e1ae06ef8981ec6ce7c4687b178f2103fa8c8be
+
+Count = 118
+Adata = 2b63f7b676f13f45d103dd
+Payload = 185577b48237acbdaa3590b8057fe374f875ce829b62c98f
+CT = f805eb63bbcb6626b8e84c06627080c4ef1b9f1875b1299265d9d899c6b71c0ab3049ea1dbfaf6a9
+
+Count = 119
+Adata = a33e86d813c2c4ff3bab20
+Payload = f051beb936e60fd4f3bca31964f1ad3e6fa16dd27b65a6db
+CT = 1001226e0f1ac54fe1617fa703fece8e78cf3c4895b646c6b246474c4e79822f5fd55f2fb0067a40
+
+[Alen = 12]
+
+Key = 8a56588fe5e125237b6cdc30f940b8d88b2863ec501a0cb00b1abade1b5ce0ed
+Nonce = d80210b9f9776ea36dc0e0a787
+
+Count = 120
+Adata = e4296d1c8cf4ffc4b2635135
+Payload = c825952293e434ea866db558aaf486ef09a92bf366988f71
+CT = b8b3b15fdf6a4a0b5abc313afc769e4e8413bd887552583ede3ed995d1b70561c8e28a7b1a7e3dc8
+
+Count = 121
+Adata = d18bfcc1584eeb8695388ebe
+Payload = a1e0248355bfd1d881fb1a4798cda2f6f6ad513c69c5f9b4
+CT = d17600fe1931af395d2a9e25ce4fba577b17c7477a0f2efb561575f6743c5759494be59afa0c3e11
+
+Count = 122
+Adata = 14682301a99bf680805d1ffe
+Payload = ded135fcbf62219bfba2cba40c2d2cbe4815ddaac1342231
+CT = ae471181f3ec5f7a27734fc65aaf341fc5af4bd1d2fef57e34f689367228cbaf3cd76fb407109cf6
+
+Count = 123
+Adata = 8853aa2dfea9c4d370678bb6
+Payload = 12d3900c6c01968b8344762e0e883e5e219f42b052dc6215
+CT = 6245b471208fe86a5f95f24c580a26ffac25d4cb4116b55a2cacb7fc3856abcf759feb8dc0998ab1
+
+Count = 124
+Adata = c5d3b9c593c3185fe4b6d1bc
+Payload = 8c3c1193fe1a1ebad7e01a1eed1a32c08a0091b1c948e184
+CT = fcaa35eeb294605b0b319e7cbb982a6107ba07cada8236cb42a740cd3262424a2c3d77849ead6149
+
+Count = 125
+Adata = dfb9e8149b51f89b1ec00a8e
+Payload = 8219618b7728ac89237705ecf84012cc7c80293c4cf171d8
+CT = f28f45f63ba6d268ffa6818eaec20a6df13abf475f3ba69747d4dbe0f9415d40843070e1e93059eb
+
+Count = 126
+Adata = 08a4590d262e4dbcb7e23ffc
+Payload = b344b7dc239617fa51b9ea10a349e940c3163779f5284c9c
+CT = c3d293a16f18691b8d686e72f5cbf1e14eaca102e6e29bd31215b3dccba4ca5de64be7fab8a7a22c
+
+Count = 127
+Adata = 74aab7b5b96238710637c6e5
+Payload = 740d4b25ca7221d0826057701a6bfd66c50a82f010a57be8
+CT = 049b6f5886fc5f315eb1d3124ce9e5c748b0148b036faca734e09945ee44c95c7923d8b9249ade7b
+
+Count = 128
+Adata = 420aac47a3f212fffca40549
+Payload = 5d9000489186abdf4f0a2794f0222fcaa156fe6309c10f79
+CT = 2d062435dd08d53e93dba3f6a6a0376b2cec68181a0bd8360a568dd779526a0058d522af1dafde30
+
+Count = 129
+Adata = 6e80dd7f1badf3a1c9ab25c7
+Payload = ac2c44263363810bec3a309aa618b303e05099dfdbeb5c16
+CT = dcba605b7fedffea30ebb4f8f09aaba26dea0fa4c8218b59279442c88d612ed1a39ae0005f88155d
+
+[Alen = 13]
+
+Key = a4cc7e1c90f8684e6a5f95e6898ab4e3c194cb46e196d8228062b9f3fa744930
+Nonce = cdc2712e51c7f333d6bad78eee
+
+Count = 130
+Adata = 569c56b27268d3db54e728aac0
+Payload = 10d4cff95ef490923c9e0906880729d4d05412e7675cce76
+CT = be3ce3e9dc72499839a98ae52abb17415e8547687e8a3c7b8aaaac20d4c9276f2851cbba2b04d185
+
+Count = 131
+Adata = d75635b6450e43285fba966835
+Payload = c9db03e2efbab713b0b640421018d3971ffe2abd70fe8fa1
+CT = 67332ff26d3c6e19b581c3a1b2a4ed02912f7f3269287dacc121ff83891335dd1214ea6fc25f6a68
+
+Count = 132
+Adata = 70750acea6a05f8b7b425d262b
+Payload = add631ce5846ce71434aad4998f8e429aed430e7d38bdbb2
+CT = 033e1ddedac0177b467d2eaa3a44dabc20056568ca5d29bf549e71ec517cd65150f42b3cb53f936e
+
+Count = 133
+Adata = 2a567c7ec7edaa5a438ae3bb35
+Payload = a514d170422feb1d87bb7725a9e77cc6fc8afb45c2af6d90
+CT = 0bfcfd60c0a93217828cf4c60b5b4253725baecadb799f9d0e432ec394ddbb65205dc40a5a8e90a4
+
+Count = 134
+Adata = 0f8795385b805246a0a2573afc
+Payload = 79d8841ab83279724ce35e1a8abd4e158168dcf388ab4c3d
+CT = d730a80a3ab4a07849d4ddf9280170800fb9897c917dbe30926b0d977107a3918717f79b63f36b0a
+
+Count = 135
+Adata = 111d224c102b136159fbeb44a7
+Payload = 2edd498e54b23aab6f4fd7b3f22c4c787e3a4f1fb06c9ec7
+CT = 8035659ed634e3a16a785450509072edf0eb1a90a9ba6ccac2cd61599bb93db3dd3dabc12aa90932
+
+Count = 136
+Adata = df0821c9ea6ab329c626d11b4b
+Payload = 6e3e25db29da2c787bb37755ee770e2402fb8208da23389d
+CT = c0d609cbab5cf5727e84f4b64ccb30b18c2ad787c3f5ca90bd027ecd00cc6dc5ffd5d746d92281e9
+
+Count = 137
+Adata = aacaf4839c35338d6e2b47ac45
+Payload = d4ed4584678e982ace8664e77d0e55be356be558cead3755
+CT = 7a056994e5084120cbb1e704dfb26b2bbbbab0d7d77bc5583c01354a450eda2588be7578530e38c0
+
+Count = 138
+Adata = dc6eed3f8bd1b5563c1eeb9afa
+Payload = 4ebf00eadaf70711f630f5badf0214d8518a200afb0e5765
+CT = e0572cfa5871de1bf30776597dbe2a4ddf5b7585e2d8a5688d7a1d546e25ba026cd46556eb2c4b7e
+
+Count = 139
+Adata = fbfe7e910f242a78dd6e69a2ec
+Payload = 2729636112f2abe2c76ea5e52a3f80b0f882f0f3b6f7c806
+CT = 89c14f71907472e8c25926068883be257653a57caf213a0b0e951aee790239e7067ef37f497b4bf4
+
+[Alen = 14]
+
+Key = 347e12eec56e95aafcc7d25bf10fc756b4e42bc2e43da7f97df24331f27f1f5c
+Nonce = b8d517b033754058128d13d11a
+
+Count = 140
+Adata = 511c6924fa96db716f6b053b7a48
+Payload = ca88dddfc876a12f45f19562bc9ca250f43267ab251a7f34
+CT = eeedcfa8f5b5b48c1d7e277526eecb7294213b9f5785167ae949b93003dfe63c95c1d49edfb4de3f
+
+Count = 141
+Adata = 10c26d5939618189a9503623f55f
+Payload = de0c0d17c3950e7f8985b56d60623cbd010cd765da4df5ab
+CT = fa691f60fe561bdcd10a077afa10559f611f8b51a8d29ce585c32a90d77fed97eb0ac164ed616e1c
+
+Count = 142
+Adata = bc09c59d20e55a9e184d70af2c7c
+Payload = 2f35102d78a32fcde1cfb563ea8d310ecb83c146ab8de362
+CT = 0b50025a45603a6eb940077470ff582cab909d72d9128a2c180fdf5f63045f326057cf74fd4cee6b
+
+Count = 143
+Adata = b75887f13d6e8c4b35b27b965693
+Payload = a3fcce3420effdd6edb37271735a0d30c10c65233aee173f
+CT = 8799dc431d2ce875b53cc066e9286412a11f391748717e7134959a180fc2cf2ba99af21cc1bc8e5c
+
+Count = 144
+Adata = 603401a9b8ecde4d5c86b6107363
+Payload = 4ac918727e41b8c536484e3781c403e260c278712853508d
+CT = 6eac0a054382ad666ec7fc201bb66ac000d124455acc39c32ca2e5195dbd44f0a119538c95788510
+
+Count = 145
+Adata = 7206b06f306124ca3a302e84c5a6
+Payload = 97d770cbb2c42a552e450cc4e35e5668b2ff89cec735cc91
+CT = b3b262bc8f073ff676cabed3792c3f4ad2ecd5fab5aaa5df74a4e1198878a76291594b9826d4b563
+
+Count = 146
+Adata = b15efed90a5d1d62f545ac22af6e
+Payload = 86bb2ae50e36c72936240a74502172625cbca210cf285077
+CT = a2de389233f5d28a6eabb863ca531b403caffe24bdb73939ff5f993dcfbd048274da7439c0f9ef5a
+
+Count = 147
+Adata = c9eb714ed9858a8dc11a26ee3f00
+Payload = 0dc79993047fd6e7260aac4d847fdb4d16483f28b13b5f17
+CT = 29a28be439bcc3447e851e5a1e0db26f765b631cc3a436590e87710559a375ece6ef2953b6aa2542
+
+Count = 148
+Adata = 07ca22271e95cb48a872046822b7
+Payload = f950e96d65a55efb3be3a55daffb421afad1d5625e3440a1
+CT = dd35fb1a58664b58636c174a35892b389ac289562cab29ef998035c81716e2d1ed4b4d56ff18af5d
+
+Count = 149
+Adata = b65f6773516124317cfb4b1fcdf5
+Payload = e160e28e601a49d16db18f25410756b330b036c42e615fd6
+CT = c505f0f95dd95c72353e3d32db753f9150a36af05cfe36981ae73a9b6896d8fc1b8c0d772d632983
+
+[Alen = 15]
+
+Key = 520902aa27c16dee112812b2e685aa203aeb8b8633bd1bfc99728a482d96c1fe
+Nonce = ddf50502f414c1bf24888f1328
+
+Count = 150
+Adata = 22b4f8f1aac02a9b2ef785d0ff6f93
+Payload = 533fee7d2c7740db55770e48cb1b541d990ea3f8f08ed1a6
+CT = fc867b319e0e4ab45ec518a1b5dcec4f29982173f3abfd4d8a8f8d14d2bdac84c3737cfbd75b7c0b
+
+Count = 151
+Adata = d0a43de391d492746ecf322acd6e5b
+Payload = cced20b59a6b2c3c45ea6c87802440c9c47b1015e83d86c3
+CT = 6354b5f9281226534e587a6efee3f89b74ed929eeb18aa28fce59f5e6e3cee284b4cc747ff5ee13f
+
+Count = 152
+Adata = 3a789c06f87f05933c34a1cf9834a8
+Payload = 90939a4530181ad6900664f66bfc2ce0289432a0afe9babe
+CT = 3f2a0f09826110b99bb4721f153b94b29802b02baccc9655ddaef56d8255125f7c316c6c59ce779f
+
+Count = 153
+Adata = 785260973f112c56d9f891160c4c11
+Payload = 86cd926b9565b76a88fde73c31e9ac908ffd1e6ca30b59ce
+CT = 29740727271cbd05834ff1d54f2e14c23f6b9ce7a02e752555810cbcdf48f05d0a7808673c82d08d
+
+Count = 154
+Adata = bf6a144591c0ea7b10274fbd3345a1
+Payload = 6ecd1c1acc6290672f9cf639ed0cebcb21ed0c56f35a5ce3
+CT = c17489567e1b9a08242ee0d093cb5399917b8eddf07f700849e41e5d34a698ae1d96f16bc68da944
+
+Count = 155
+Adata = 7d9488b500d89a27f367f34a448a87
+Payload = b01e3f4fb5ee7501e8c2f4ccefb542ae20d7fd61a2c41c8b
+CT = 1fa7aa0307977f6ee370e2259172fafc90417feaa1e130601bc54e546d1a6fcf6187169feb1ea533
+
+Count = 156
+Adata = 060fc718e994edc7bac9962ca7f28d
+Payload = 22ab6a0daf953165dda864cceeeb782e275c0b072aedd284
+CT = 8d12ff411dec3b0ad61a7225902cc07c97ca898c29c8fe6ff2eb6c0ab42acf42985c721bfd576e71
+
+Count = 157
+Adata = cb6f96dd06015967279ade310a7401
+Payload = f96ed20b23c784015ff58f5f040798ca75e3b98045deca8e
+CT = 56d7474791be8e6e544799b67ac02098c5753b0b46fbe665ac502b8e65cc1329b6895afdd354f5db
+
+Count = 158
+Adata = 9aa6d501455019b4ef4c7fb789d22f
+Payload = 648a84813ca97aef4ab7e143ee29acb946388660f18eb671
+CT = cb3311cd8ed070804105f7aa90ee14ebf6ae04ebf2ab9a9a87e5f8a8148f21adf721477c36bd99ca
+
+Count = 159
+Adata = ebd1d12bbd14176a0d4080aa1edb89
+Payload = 32d71e59634126ac6c6156a80a0dfa0175b29e9f40a31696
+CT = 9d6e8b15d1382cc367d3404174ca4253c5241c1443863a7dda9ea0427522dbeaa509a11755434760
+
+[Alen = 16]
+
+Key = 57da1c2704219ed59abfdf04743a9a93c87a63d471818de0f1564b2db6421562
+Nonce = 4b60a47b7e90f622fa0bf803e1
+
+Count = 160
+Adata = 0ae8c012ff39753510df3ee80707e4e2
+Payload = ddc3c1aa73fb6de92bb4db138e26f3c2e0543ab4f5924871
+CT = daa8256d4753fdf9cfef876295badaba89b45cc497f54d220ec2c6fb687753bca4580adc6aa2f296
+
+Count = 161
+Adata = d5b22e7697ba70e00c7ef32709563f01
+Payload = 34270576724083e9989764d08a0d5c1b4738f34927a1e436
+CT = 334ce1b146e813f97ccc38a1919175632ed8953945c6e1658f30b9c8e380c98bb939a4e8a85af758
+
+Count = 162
+Adata = 6b4edef415763aabcef01863e8197aec
+Payload = 904fe88e7a8e76447a64b488ef84184d0f1ab1b67f0c5a7d
+CT = 97240c494e26e6549e3fe8f9f418313566fad7c61d6b5f2e53e80d8ccc687fd303f4cdef44b6e8b9
+
+Count = 163
+Adata = 4c099809061024c010a77e9621fc2bcf
+Payload = 51fe7bac8f3255f17f64fb9322210fb7d8da8e762498b233
+CT = 56959f6bbb9ac5e19b3fa7e239bd26cfb13ae80646ffb7600c635dac5b70338dac3f33ce16a99145
+
+Count = 164
+Adata = 9d329439588164d5a96675a85c07a039
+Payload = eab6dbc13bb92df36b1882df2b8f34c3cefa41f95717fbd7
+CT = eddd3f060f11bde38f43deae30131dbba71a27893570fe84f996e8163affb1494bb3c12eeadf16b6
+
+Count = 165
+Adata = b768fc3daf29ff9e8bd575072d986e99
+Payload = c44c9c287d3eac7c30570d9c4adf2e4857c598f7c54cd126
+CT = c32778ef49963c6cd40c51ed514307303e25fe87a72bd47598b4206a9622d5631751a497dfb1f662
+
+Count = 166
+Adata = 3efc7cc2d16bf82d2bcfbc559a09b2c9
+Payload = c11b9c9d7607f387359c0038d3e8ec4d527562ce63c3384c
+CT = c670785a42af6397d1c75c49c874c5353b9504be01a43d1f7dd300167d267ad700dea37fb475ecdd
+
+Count = 167
+Adata = 0ff89eff92a530b66684cd75a39481e7
+Payload = cc17904b166f28df82f57889f391159a4a308e752d714ee5
+CT = cb7c748c22c7b8cf66ae24f8e80d3ce223d0e8054f164bb6303e9c9bd0d8e4aac42894ca03d6ab06
+
+Count = 168
+Adata = fbd11bc75759f0461e796f6917aeb42b
+Payload = 6f97e595ea2f40612ea84a2097b974d235055fe1dae59403
+CT = 68fc0152de87d071caf316518c255daa5ce53991b88291500953f46e0e9cf1369e9eb018a4df3c09
+
+Count = 169
+Adata = b79940952f42537484aa2907c72dffa9
+Payload = a48cbf933b88c0ec5ddcdd8fcad186391c2cbef308607de5
+CT = a3e75b540f2050fcb98781fed14daf4175ccd8836a0778b68a1702dfa0cd9c290c5ff9c35cc83705
+
+[Alen = 17]
+
+Key = 9267ebc99ccf648b146cba3c251187e24a9947d806ceb0ced6894211641a1e0d
+Nonce = 9b7298950280e8762ecdc9bbe4
+
+Count = 170
+Adata = 5824689453bc406bf891b85e4576e38fe8
+Payload = 967daf12f16f166b7b5038f83a1cf0b980f5abf4c7746f2a
+CT = 7cfe2a7a54306eb8d8a63d3d1ae86794f9a2c22198b2cb4f10ca926f1a430c08c12e23db3d913e93
+
+Count = 171
+Adata = cd15973753b94b77bb4b778de8b3b0cabb
+Payload = c4a756f6024a9dceabf6e264fffff9c719217fb418141ac5
+CT = 2e24d39ea715e51d0800e7a1df0b6eea6076166147d2bea05d5b674fd15410cc235dba6d8c8d82a8
+
+Count = 172
+Adata = ed8540f7ce451c522c1ff5d2d1030d7b3f
+Payload = e0d5de7d1eace211c0e70859ff315ff485d1200c6dd13f93
+CT = 0a565b15bbf39ac263110d9cdfc5c8d9fc8649d932179bf688750b5f36c86e7eda9015e960a7471a
+
+Count = 173
+Adata = cbbecf92551a15f5cf00a5be4a50b0eb17
+Payload = 05a4a4ba28fe8876f9bcfa5ec60651fd3fd4732f22049bd5
+CT = ef2721d28da1f0a55a4aff9be6f2c6d046831afa7dc23fb0d5fa842209dbbc04c87965f78500fec1
+
+Count = 174
+Adata = 873ba7f8b71517ec50297b21cf94cdb7a5
+Payload = 9cdebaeee8690b68751070691f49593668a6de12d3a948b3
+CT = 765d3f864d3673bbd6e675ac3fbdce1b11f1b7c78c6fecd67d147edbe114bfdb3f3b9b37d5719ef5
+
+Count = 175
+Adata = ac087420feb1e1e8c2546c2a8b8a5af0d0
+Payload = 5672e61cf664d73918dc1ca84df1fce82db0e305a61d57b9
+CT = bcf16374533bafeabb2a196d6d056bc554e78ad0f9dbf3dc57b4c2bbc377937d15b3b89543e29d0e
+
+Count = 176
+Adata = a12c690568114fd7a677f49d74e84fc1a6
+Payload = 0f5452e6b51540cf219998590995cd7f8785fa40b4f217fc
+CT = e5d7d78e104a381c826f9d9c29615a52fed29395eb34b3992e6ca774074b47b59adabeaf8835582d
+
+Count = 177
+Adata = 7a78ddfe5afb2dc90ee4a600c2fc014b0f
+Payload = 9ad338cbfd1b52e6ae4178f05e00062274f8b0b25eae72f7
+CT = 7050bda358442a350db77d357ef4910f0dafd9670168d692bd320f48a7221537e3cbed5ac4154a56
+
+Count = 178
+Adata = 6053e466ed1f647a3cd88c4d2052ec00cb
+Payload = d17b8d556e83190c84d4a812957c64ffa7f336298f4e2c72
+CT = 3bf8083dcbdc61df2722add7b588f3d2dea45ffcd088881740574e201f9a26932a87c8d822505814
+
+Count = 179
+Adata = f7673e3beb526834d6507058fe62e34987
+Payload = 2eaef86b0f602364f86510eabc58bc9ad1e6f0a6f6df0b83
+CT = c42d7d03aa3f5bb75b93152f9cac2bb7a8b19973a919afe6837dfa3fdef2f012b6609de2ac5dd9d6
+
+[Alen = 18]
+
+Key = 7a855e1690ee638de01db43b37401dcd569c1ae03dc73dd0a917d0cadb5abc29
+Nonce = 8f160a873a1166c8b32bccbba7
+
+Count = 180
+Adata = 72674aca7eba2fc0eeafbd143c2c4d8aa6c8
+Payload = 33ae68ebb8010c6b3da6b9cb29fe9f8bd09b59ec39f4ce4b
+CT = b22afdf4f12c43ec23e01ac1215a3f5286059211207e957057e9a9203da74387a9468f8af5e27547
+
+Count = 181
+Adata = f7da3f100b80e2ade812f1700aab6b72f746
+Payload = dbb29817b86cb80e0d008742cedfbf52b236f15ee8cad50e
+CT = 5a360d08f141f78913462448c67b1f8be4a83aa3f1408e35a3985f12a49eac424a35c94645917e91
+
+Count = 182
+Adata = 4b05eaadf98505d0806c233b2cdcaf4254e8
+Payload = 145aa8cfd544a2f46bae1aa83cbdb3d21c3d1350078a3af4
+CT = 95de3dd09c69ed7375e8b9a23419130b4aa3d8ad1e0061cf4ab089a8724b87a1167180963d44ec65
+
+Count = 183
+Adata = 05a3aaa08b9a6aaeb84704431425d0e45a14
+Payload = 6b32e8906dc89194a69410b79cd041b62eb01afb28a3e10a
+CT = eab67d8f24e5de13b8d2b3bd9474e16f782ed1063129ba310a7d1520141892e140448292185c41c7
+
+Count = 184
+Adata = 74db01edc26a2d2044cb8eaad8b907b78863
+Payload = 545ed03588fd85a8bbfeee66d2082ae6f8e2f3c9dbd8725f
+CT = d5da452ac1d0ca2fa5b84d6cdaac8a3fae7c3834c252296472d3eee219d94bd788f62df4add5ec40
+
+Count = 185
+Adata = 5f2c6ddf5a2403e04dac8b2813c060b67e76
+Payload = 66dd5fd8611c551973a3d0c078ec2b4d39ad163d9168de3c
+CT = e759cac728311a9e6de573ca70488b946f33ddc088e28507c600496f4f8b1b7da118ee36d8cd57f8
+
+Count = 186
+Adata = a650a2a5e3c6f7c95614570aaefd0cdd9a42
+Payload = 6f364b3f778376cbf3f4b0b0c5350a8fa278f9d8c25faad6
+CT = eeb2de203eae394cedb213bacd91aa56f4e63225dbd5f1ed4710004d06ce7a7efbd19da4e3ce3cf7
+
+Count = 187
+Adata = 477c2484cf5c56b813313927be8387b1024f
+Payload = 3de4798d8ad84c460b92abc10b7f5e7c9fae46a1dd353687
+CT = bc60ec92c3f503c115d408cb03dbfea5c9308d5cc4bf6dbc304099641c4ec3dc2c54fdf4f48dbef2
+
+Count = 188
+Adata = 564e1df74aa2d7ee33b66cfeda810774e16c
+Payload = 7769b45fea11f530fb9a67f1b5b1964a34cfa32bbb03f4b1
+CT = f6ed2140a33cbab7e5dcc4fbbd153693625168d6a289af8a905c1b05e8945685f8688faea777eb43
+
+Count = 189
+Adata = d5e66502529b0045883d935e05acd242baa8
+Payload = 0c0a502b42f81b51806c7080a8155280f493f2922cdc7df8
+CT = 8d8ec5340bd554d69e2ad38aa0b1f259a20d396f355626c3ea5a3b6a8bafde4006b993cfb3b13557
+
+[Alen = 19]
+
+Key = 0ebdc6ddb4c502725dd6ee8da95d56a0d1044b4694d6ba8475a4434f23a8474f
+Nonce = fb717a8c82114477253acc14f6
+
+Count = 190
+Adata = 41e9d65632f74f449a6842d5e6c4a86ef83791
+Payload = c7360282c85484a5a33ab1c68dd70873ab4e74ffd4a62cd5
+CT = 2e961b3a2fa1609a4e6fd04bff6ac5e306ae2638706f997b42be2e2ba05c54b619850db5c9d684fe
+
+Count = 191
+Adata = 555304659bde926cb2553b8a4605251fcddd92
+Payload = 1332314d1cf783b9f64e0fa2d42d43d225da9fd5165b5f0a
+CT = fa9228f5fb0267861b1b6e2fa6908e42883acd12b292eaa4bbdee2605bc69601b1e83d1e7a0b400d
+
+Count = 192
+Adata = 69ea953dbb910ec589372d797c7379d3f3b9e9
+Payload = f264da8606ea429e0e25da3f2efafe28beaff05b42097369
+CT = 1bc4c33ee11fa6a1e370bbb25c4733b8134fa29ce6c0c6c7304611baf530932da7954f714514d228
+
+Count = 193
+Adata = d7186a67061319b44eedc0677ebf5d932d5bce
+Payload = c9ee6482144dc61c43041324a2c18ede370011cb4882b0c5
+CT = 204e7d3af3b82223ae5172a9d07c434e9ae0430cec4b056b6d1d44e26404b7324767f0b3f7486f8b
+
+Count = 194
+Adata = 38f37d5e2da017f1953ff3701be0b38809ba80
+Payload = 40524a4d32a711e7d5a59809878c318f42b6e2375b77b8a7
+CT = a9f253f5d552f5d838f0f984f531fc1fef56b0f0ffbe0d095453724d2db19f606c85d00e49b0bb38
+
+Count = 195
+Adata = b3b2d249cd3517555fa692bbe9116f069e7405
+Payload = 961c15bd7dc34cd5409c9e8869988676ec6845ecb0ee85fd
+CT = 7fbc0c059a36a8eaadc9ff051b254be64188172b142730536db1e4112fcd650e8c0f0f6fbf2d07e1
+
+Count = 196
+Adata = f5b5bcc38efaff01f69bd3a106dcfca3cc6414
+Payload = 879568ab9ebdea768a5459ced1d3181d822536c3d1ba38c3
+CT = 6e35711379480e4967013843a36ed58d2fc5640475738d6d1cedb29e68322e47ff9997f859257d98
+
+Count = 197
+Adata = a2098e3e23826e01f31107a208202f710eff00
+Payload = 47cb57599686716c75d7ecef5541d20fb908e6d98c39925a
+CT = ae6b4ee17173955398828d6227fc1f9f14e8b41e28f027f41c12bf2a3571ed672592b27e986e9058
+
+Count = 198
+Adata = 20a3d53e77201599540344c4e746c3ae3a5f84
+Payload = 4a8667b5ee09d3d4a6dca9a95f4ad406f1da94b846dcc6b8
+CT = a3267e0d09fc37eb4b89c8242df719965c3ac67fe2157316f12b2be8f5966d96602111c28f87b104
+
+Count = 199
+Adata = 92c592ead4b3f193cc36687593d4f0f412a5d5
+Payload = 1dc9e32ac4176f64bd78a6edd651ebeea3ba85dfcd8298a8
+CT = f469fa9223e28b5b502dc760a4ec267e0e5ad718694b2d06776df0a0cf048892e65bd8ad77cb2255
+
+[Alen = 20]
+
+Key = 2ff64bbec197a63315c2f328dcb4837d0cdc21a5d6f89ff1d97cb51195330cd8
+Nonce = a235f8ee3de9896b71910ac02c
+
+Count = 200
+Adata = 2b411bea57b51d10a4d2fb17ef0f204aa53cf112
+Payload = 4a17522da707b4b2587a0ae367a2cd2831bb593a18ef442a
+CT = 1bf122798bd8ee8e73391d589bd046a294d1615794e69cb9e6f3ba30143acbc3a1c1c6ec74333107
+
+Count = 201
+Adata = 0248359f8071143c3cc1d61882a3547a0b3d2175
+Payload = 4a6a7151465c2abd7e7fa1fd13019ad098b6ebcd190e96f7
+CT = 1b8c01056a837081553cb646ef73115a3ddcd3a095074e6436cb510c13a039f4df8cc26a942f9911
+
+Count = 202
+Adata = cca77bc4cf6c0abd3393dac3fbe90fbc8a1154f7
+Payload = a94f5ede43929d48d2c5a58c3262d9127d2ac3cb2fbd5768
+CT = f8a92e8a6f4dc774f986b237ce105298d840fba6a3b48ffb7fe0dedc2899dff81a251cff16bf5897
+
+Count = 203
+Adata = 9c082a84646c070bb11b7d6b92b62f06ee5b5b71
+Payload = 7303bd41cf47289a3111366d08e8e21548baf293052029eb
+CT = 22e5cd15e39872a61a5221d6f49a699fedd0cafe8929f17886c43ac23800de60a1fd2caef0f03261
+
+Count = 204
+Adata = 1c3ede1982a807a410ae1e21947bf430f8db7027
+Payload = fa9743a67978c20316cb91801d7789e350079aae3aadbd43
+CT = ab7133f255a7983f3d88863be1050269f56da2c3b6a465d026f7907e235c09d3322c4092d2e88f88
+
+Count = 205
+Adata = deb05a30a026ff66ce71e98afa62f0255aef84f5
+Payload = 99599b4042dcdb685350cdecfdf24992fd5b165670025d0c
+CT = c8bfeb146e0381547813da570180c21858312e3bfc0b859f6bb44a28c145d49f49f2821d4044e4b6
+
+Count = 206
+Adata = 93dd9b00a3353e5331338dcfcb7ca7e0bb873a4e
+Payload = 451101250ec6f26652249d59dc974b7361d571a8101cdfd3
+CT = 14f771712219a85a79678ae220e5c0f9c4bf49c59c1507400f7d20aa3d792d6a3ebc5ee0df2fd89c
+
+Count = 207
+Adata = 0855263860043207543c8c34648d53ec51c4f47e
+Payload = b2db87b7787531968d603098cb20ca7c438b4af72623fea9
+CT = e33df7e354aa6baaa6232723375241f6e6e1729aaa2a263a7ca4733f0208668b0a7879305e861d71
+
+Count = 208
+Adata = ee2d3a66deb3ebca867a902bb9202226ed516ded
+Payload = ca18ce38086223e63b4f0b616d110010f9e45eac42f2ba46
+CT = 9bfebe6c24bd79da100c1cda91638b9a5c8e66c1cefb62d5d76b482ff20429da8f60f0f863e1af50
+
+Count = 209
+Adata = 8e531aaea849addab6a83497cbc504f489505952
+Payload = 5717ed5da5b8aa806a18bfe979502bab6632c9428d3a7725
+CT = 06f19d098967f0bc415ba8528522a021c358f12f0133afb6aab66e1ac2346ef97850a4985c64b737
+
+[Alen = 21]
+
+Key = 24e9f08a9a007f9976919e10dc432002e2e078a339677f00105c72ed35633a3f
+Nonce = 15977424eeec0ec7f647e6c798
+
+Count = 210
+Adata = 2d838eb51a4bc69a001a18adf2084a680f02a3c5fc
+Payload = d3416a81b4246eb0bf8119a72a886bbc0ac9449c69f71d2f
+CT = e001a8fae390dc5d672cdd18f86a1f728158ec83a002050def9af5679edbcbb7db20ab6af30698db
+
+Count = 211
+Adata = d83ee7ce22fd1a2882d8d552346e4d7b3efdd67da4
+Payload = 22b6f10b482448626f6c7bebb14f1497896d071738133b4d
+CT = 11f633701f90fa8fb7c1bf5463ad605902fcaf08f1e6236fd435a5a38f84387f63b13407f65ec86c
+
+Count = 212
+Adata = 2d5537b24d0b0f7a45703c1e131656ec9edc12cdf7
+Payload = d60edc830be8207ffd9e9f646d3b4343b10b3d56acb89d44
+CT = e54e1ef85c5c929225335bdbbfd9378d3a9a9549654d85662ede8a705f8c988f55459542bd631b1c
+
+Count = 213
+Adata = 1a750eb326923412d94ccb35f5acd0f87415268178
+Payload = 716d3132f449a9def383978102ae50ed3ccae0cb346ba1df
+CT = 422df349a3fd1b332b2e533ed04c2423b75b48d4fd9eb9fd986de774a612230ce6c71449d26732ce
+
+Count = 214
+Adata = b10fc523bc4562d44edfe5956f93c15c4ab38bba3c
+Payload = 063c2ae2a15f26f979bf90657d20643e3184f1a9f75a3aad
+CT = 357ce899f6eb9414a11254daafc210f0ba1559b63eaf228fe710431005264fa7d3fc04bac50fc1ec
+
+Count = 215
+Adata = fe4f60ce9634e7dbc5e56204c4bf8aa9be577027ec
+Payload = bdc513e56a5bb70c02abc041af04d6e45e735d10cc88357f
+CT = 8e85d19e3def05e1da0604fe7de6a22ad5e2f50f057d2d5d5c13bea6ad0cad724e6cd02c89517ffc
+
+Count = 216
+Adata = 48f3ceda4fd390a7eb38f7f5bcd14310af6b5a557e
+Payload = 7dc5d8cd90ce2faf76bbd0d52e5ae11b310fc2b0051c4377
+CT = 4e851ab6c77a9d42ae16146afcb895d5ba9e6aafcce95b55d2a5531655aae01e249f213e0e04af0d
+
+Count = 217
+Adata = 199ec321d1d24d5408076912d6bb2b6f192d6b347f
+Payload = 66c2696edec26ba3d07bd3f485a0d6ce8a1b0a85b20083e7
+CT = 5582ab158976d94e08d6174b5742a200018aa29a7bf59bc52a127ef341345f9641b26e91265e1482
+
+Count = 218
+Adata = 8b013f5782d5d1af8dbd451a4202866095dac975fc
+Payload = f4da8ac3e8fe5ec6a5b6a2f27b68396e850b46a024d441f0
+CT = c79a48b8bf4aec2b7d1b664da98a4da00e9aeebfed2159d2a005ca13c4bf715c3b7b2782f799b23a
+
+Count = 219
+Adata = e320df32b71cc530e8493b12b9afbeabc255c5eb44
+Payload = 244891cb4af66cc8e99a3784a2e82475e51bd5c7fde67cf5
+CT = 170853b01d42de253137f33b700a50bb6e8a7dd8341364d704642aff9cb9288d49f0e567dd837e05
+
+[Alen = 22]
+
+Key = 0ec1b22b8df05dc92135d2dfbefed8ea81458f5ea1b801e8a218faf6cbdf1a79
+Nonce = 97ebcb8575bb58260208d5c227
+
+Count = 220
+Adata = a2f6337f86dd00d1a58448851e95d8c9bace4a5c8710
+Payload = 2f59d94d4ab8eeb84c2a6fefb7fb0a3ac059c1e1a65ae34a
+CT = 7ca0b1dbe34b0391e524b868b0af08b3e096917664d6aa2cabc1f9d0132394149c9062b74b82f04b
+
+Count = 221
+Adata = abf26b05558252c8e38c52b1ace087bbd1eb3d561239
+Payload = c25381853f73a3dc4195fdcbc45dfa1a40eb8324749adb2e
+CT = 91aae91396804ef5e89b2a4cc309f8936024d3b3b61692486d7df57c6a792f6f6b24cb5f87e92123
+
+Count = 222
+Adata = a13ade56b47803897666e42ef2ef88be0e779ac86c28
+Payload = 8dc5226a2a13088c87f4bf94262e0c0413f06b35d2fda79b
+CT = de3c4afc83e0e5a52efa6813217a0e8d333f3ba21071eefd4ac19b0b74cd9d5e100598b96c9f1f2e
+
+Count = 223
+Adata = 3c5b68b65edf62755b7e064bd26c843816bf6c1cd481
+Payload = ee4b23039cd512cfab8c7a2d0f2c78d66764520bc88759e1
+CT = bdb24b953526ffe60282adaa08787a5f47ab029c0a0b1087a77a27eabfc79f192c0ac491280af8d0
+
+Count = 224
+Adata = 0213fe13c49083d7c00335e1864dc139c9e7123162d1
+Payload = 30b48d4021838090fbd5251069ff8c631452daee5ef899db
+CT = 634de5d688706db952dbf2976eab8eea349d8a799c74d0bd39935f91c1e29fc1e4c5c5427ca9da79
+
+Count = 225
+Adata = a32291746b151be8134e183798aa82bef210343feaf6
+Payload = 2286a1eddd80737a724ca941217e9f0232870b6c2f20d29c
+CT = 717fc97b74739e53db427ec6262a9d8b12485bfbedac9bfaaeaec90ada2a1ffef64c3873af645a40
+
+Count = 226
+Adata = a30f2fd445820cdf800145540602c877da0e4c311272
+Payload = fe703ca0901e4a706ce1393c7d8ce18a03eb2caadbfa7b8e
+CT = ad89543639eda759c5efeebb7ad8e30323247c3d197632e87932952831d0ba25c77c18fe154d8ed8
+
+Count = 227
+Adata = ed438e393e0e37629cb25044ae89de9fd0d42d60c1a3
+Payload = 7043c67726870bb5816da925925bc2722478311c8a606cca
+CT = 23baaee18f74e69c28637ea2950fc0fb04b7618b48ec25ac234fd0241d00f3890a23ccd0bf16dcbf
+
+Count = 228
+Adata = 1013946815001a2c08acca4196e0d6668ffbb3883cf1
+Payload = 695e9712dbbf883e9bf8af9188bd01fc631968928258168d
+CT = 3aa7ff84724c651732f678168fe9037543d6380540d45febaf43498b0c3f70c119f82d5812db940f
+
+Count = 229
+Adata = 44cc9b2510680c4d73f1938c77de21242c8ee790ed7f
+Payload = 67ba90d22c6bb5f649bc0c505c5ed23a299882559a3bf520
+CT = 3443f844859858dfe0b2dbd75b0ad0b30957d2c258b7bc46db66dbb03a4c943ac089ed11eb214bbb
+
+[Alen = 23]
+
+Key = 0875020959ed969cfb38636d1d5aabce9658b00171a7614ea9e5395331c7659c
+Nonce = 451101250ec6f26652249d59dc
+
+Count = 230
+Adata = 7cc9c51b69f98a06391ab32742fb6365e15106c811fe8a
+Payload = 065ef9eeafbe077c1c7049f43eb0d8999708e8609f214d5c
+CT = 990065322a438e136860f7b019807e9feff52a642bf3d44a9163fa7a867f04cab6f52dc250070f31
+
+Count = 231
+Adata = 7bb1bc069a783d45d51d8ecd0a53ab7a386fa1f5ef12a1
+Payload = 69b2b056f2265e707d3e31e68bff6a060544c8a737b2a9b9
+CT = f6ec2c8a77dbd71f092e8fa2accfcc007db90aa3836030affd33dd9155619fb040dcd6038c7b7367
+
+Count = 232
+Adata = 0dd220919d0eeee3b7cec36c47e376b778583b38bf61c8
+Payload = b98d79aaa4c04171398c7f1189497acaa7546ef068bc7a3f
+CT = 26d3e576213dc81e4d9cc155ae79dcccdfa9acf4dc6ee3294fcba5a886b1f33cf1cf44618d28f01f
+
+Count = 233
+Adata = 1c1915fab09348b9a5536495c70d1a040305708c112479
+Payload = eeaeb773ade5fb2d27b50bb892916333e0b123c6e3ae5bdb
+CT = 71f02baf2818724253a5b5fcb5a1c535984ce1c2577cc2cdeafe2c670eac203d5e90b9d520e7a618
+
+Count = 234
+Adata = 614b0ac4611b6c6d3b4ed089510dcd2215567bc3789f85
+Payload = f2198e1f91fde2672a1ef60403c0d175f366b6780ee9f1c2
+CT = 6d4712c314006b085e0e484024f077738b9b747cba3b68d4f0388746438e83b731b5588fef53f1f3
+
+Count = 235
+Adata = 866fea4483d4e903566844e31c24283571832dfae32c74
+Payload = ba37617342b4eefd4bdce8fad30c4751b206d47814973b3a
+CT = 2569fdafc74967923fcc56bef43ce157cafb167ca045a22cfca81f8b36d16698a600fd701f2c6424
+
+Count = 236
+Adata = 9d7546f7e8b949c539d21a357f81d0151e278d0bf2c5a5
+Payload = 69adcae8a1e9a3f2fe9e62591f7b4c5b19d3b50e769521f6
+CT = f6f3563424142a9d8a8edc1d384bea5d612e770ac247b8e04c15a6d292c7ed2f31cf9512435ec7d2
+
+Count = 237
+Adata = 42b692048c8b3cce1b5e83f4f33232a7d7d0bc20695e7e
+Payload = e0753d4248643642c7a96404de8d76c9d80527b659ec6d31
+CT = 7f2ba19ecd99bf2db3b9da40f9bdd0cfa0f8e5b2ed3ef427a2ad73179d0314b5fe52dd7217518cb8
+
+Count = 238
+Adata = f1dfb6fdb31cb423226f181c0988a52ee4015aef4536f4
+Payload = 79ba959c7221b293e2115f538d9394c64284c756563c04b0
+CT = e6e40940f7dc3bfc9601e117aaa332c03a790552e2ee9da69ccc5ba1caf933b80bfc6f281109688f
+
+Count = 239
+Adata = 8eafce9ba466fd53eb87f499d7c76bd486db0e90a3d281
+Payload = e1590206717a708cad9cca7d23a3b8ee5f7fb7786aa3be47
+CT = 7e079edaf487f9e3d98c743904931ee82782757cde71275173271ec36d92fff34609169f579c8f1d
+
+[Alen = 24]
+
+Key = ef4c1d2314e671f666cc6667660f1438a293208c7cc29b412d81277f0a635c91
+Nonce = 50b23b052922366c25dd40e348
+
+Count = 240
+Adata = cd0522ebe1fed82465277d1c10ae9316a98b4469be63b180
+Payload = c99c3e79125b6fd95e737326a842424eb6c6ecea4c0475c4
+CT = 76df4be4ec8373864399acda11294b220b9f7c3a7d2b3660b25764e40ac6a171e7e6bab4fdee4288
+
+Count = 241
+Adata = ce5bf070678cb07e963263b1562ff79311144addb6e4de4f
+Payload = eede01b08f9a303cdf14c99d7a45732972c6eff2a1db06eb
+CT = 519d742d71422c63c2fe1661c32e7a45cf9f7f2290f4454ffca49758d17f2073066b82667eae6ce3
+
+Count = 242
+Adata = 07175be2475cc735c9a3c1140895277378debf8fb1c87c24
+Payload = 6d5579aaaf8737b01620424f3ddeaf538f10dfad094e5ec4
+CT = d2160c37515f2bef0bca9db384b5a63f32494f7d38611d607c1d64d7e9de47a6ad7878283da9d870
+
+Count = 243
+Adata = c821a8d4bab9d993c20dd206955304a55968e6db5ab6480d
+Payload = d0628b2027f06c246497977d05f211b2c2e302d5b82700b5
+CT = 6f21febdd928707b797d4881bc9918de7fba920589084311adc2bb471862d25cfe25e66fedb8e28c
+
+Count = 244
+Adata = 68439bc9d176feeeb4119d00ed5449dfefb72b5a582bfd97
+Payload = 6cc9749f48c61050e421afa3a10ad3dd3aa02cc3f8586915
+CT = d38a0102b61e0c0ff9cb705f1861dab187f9bc13c9772ab1319a493abc947945f1312395ea98d937
+
+Count = 245
+Adata = adb262c924942e4e1964e9d97c6a8c159fbf9bfedc5ff296
+Payload = 92d50736466e64e6225962e76bd90da824f716a3301a1a90
+CT = 2d9672abb8b678b93fb3bd1bd2b204c499ae86730135593421d0602d29447ba6b24a67509eaee1e8
+
+Count = 246
+Adata = fc7b08707d3c3dac7689ec18088ee6502ef08d3ffbff38ed
+Payload = 87c7ac031fd63e4c83280dce6b68a92dfafb6ea19388fa9f
+CT = 3884d99ee10e22139ec2d232d203a04147a2fe71a2a7b93be52a2eeacb1f023e849161b6306b6cfa
+
+Count = 247
+Adata = fd43dfb66041b117f2ac54c94f7b6e2677860864d9494175
+Payload = 6b53c46266b2f4284d8fe7f0549c98977344d67e178e9a8e
+CT = d410b1ff986ae8775065380cedf791fbce1d46ae26a1d92a0d8c5b1e96b21460e0b5414639abeb0b
+
+Count = 248
+Adata = ef1ad3eb0bde7d4728389da2255d1f8a66ecb72e6f2f1ac4
+Payload = 8e7d8a44244daa7df2b340993e32dac50e05d7b2e103be98
+CT = 313effd9da95b622ef599f658759d3a9b35c4762d02cfd3c1c97260d20797d374c595cbc2ff080bc
+
+Count = 249
+Adata = 9895b24d12b004b215583eac70a95f4fba7442164f35c57b
+Payload = cec07df916ffb7a453d0eb588b7462096f22874bd5abf814
+CT = 71830864e827abfb4e3a34a4321f6b65d27b179be484bbb06cd287afcbdbc5531f11246080b22677
+
+[Alen = 25]
+
+Key = 8544808e8fbf8c3a5e1d4ca751d4b603af9fe119eabc6923205815e0e748b7e7
+Nonce = b44a58724596b4d8dea827c1a0
+
+Count = 250
+Adata = f5b2c88f5232c37273b1e66aa31cfa7201e33c21d60054d025
+Payload = 617d54fc6a23601c79e3984f93bfc2d151fde420863206b3
+CT = 57b3414db48982c6567265e1e0173bf38fdfaffe4461fbebc1411af83237c0f9eb0bfe8ed914da66
+
+Count = 251
+Adata = 8fabe14dcb3aa2fd28281147c326e98ad699ca7997f03a105d
+Payload = 337290d0b4ce1e87afc3cf01d6c98f8c17a4603120dcfcd1
+CT = 05bc85616a64fc5d805232afa56176aec9862befe28f01897ed6e23720b60ffe54bbb9f7ff371008
+
+Count = 252
+Adata = cf193eb3d755cb8e06c5be2334b5c8b7a22b6524d46d547ba3
+Payload = 01ef7ac6470aa02ccd8c1712827e52699d05751b78e4c5a6
+CT = 37216f7799a042f6e21deabcf1d6ab4b43273ec5bab738feb6aa6b284e7720acbd027a50317f816a
+
+Count = 253
+Adata = b4cadb5f9cb66415c3a3b71421b926f147566a174160a0bcc0
+Payload = 64fb9322210fb7d8da8e762498b233b0eb172c91231c50cb
+CT = 52358693ffa55502f51f8b8aeb1aca923535674fe14fad937058e9c0164ca079668097fde19e5302
+
+Count = 254
+Adata = 48400d76ff882d6d5129c8674acc71f445356c9db9c91f8256
+Payload = 291aa463c4babc76b4a6faf2e27e9401586b1ac83e4b06a4
+CT = 1fd4b1d21a105eac9b37075c91d66d2386495116fc18fbfcf988611d5ce0f65b217bb4787bf59bbc
+
+Count = 255
+Adata = 749d369d837002ad33feb8aa22c3f68705eb4872e1b8f85a7f
+Payload = 141cdd7f964a78815be144a785c6a2a298c54230e73039e2
+CT = 22d2c8ce48e09a5b7470b909f66e5b8046e709ee2563c4bad6251a5fd375a48583a6d0f8eb75cbb4
+
+Count = 256
+Adata = 80214108b16d030feff6e056c9a07a00a1d5e3ebb07abd3f4a
+Payload = fa2441cb7f9d072b8a3f1a496b2be6728a38b94a4f44c9be
+CT = ccea547aa137e5f1a5aee7e718831f50541af2948d1734e6af1dab0f105414293cb130bea285fd6a
+
+Count = 257
+Adata = 8b9fabe29718a8f297c9bf6f199c80bbc71f94eb3034a11ecb
+Payload = c8ce88ab40b62229223d46cc44f21bb39cfef27aa9fdccad
+CT = fe009d1a9e1cc0f30dacbb62375ae29142dcb9a46bae31f51cc3f7640a42460be877fb7059a3ed61
+
+Count = 258
+Adata = 8812f28a0cd5fdaa226fdd44ed857241007377057be3bea577
+Payload = cf59f75ca4d6d216cf8862b44b5192c382c140f862def117
+CT = f997e2ed7a7c30cce0199f1a38f96be15ce30b26a08d0c4fbbe0ddd2e7f4aa2024b3fec9281b6cac
+
+Count = 259
+Adata = c8f05e96d703a4850bae1421ae9ff3aec7531baf9b899dfd75
+Payload = 4eed58f381e500902ba5c56864f6249d191e14d1b1fad3dd
+CT = 78234d425f4fe24a043438c6175eddbfc73c5f0f73a92e85e5df1e5e96bb84f730fcb253d468278f
+
+[Alen = 26]
+
+Key = e19eaddd9f1574447e7e6525f7fd67e3b42807e44fbb60e75d8c3e98abc18361
+Nonce = a8c459ce0223358826fb1ec0f0
+
+Count = 260
+Adata = ef88f4393d6c1e7b7be55a12144209ee051bb779e440432721ef
+Payload = b3b0de10b7c0996662f1b064e04e528b7d85ca1166985d33
+CT = d63e6082c95c6c5ff2bc0771321a4f883ef61cff7b99e0ea8a20a1abe7c842ebc08c8c81a2743c81
+
+Count = 261
+Adata = a4c891c9dd1fcc982c35bc74cfe71651bae424602519672b466d
+Payload = 4f0b40913f07269550b7b06ab9027a4d9331f8ef98a45dca
+CT = 2a85fe03419bd3acc0fa077f6b56674ed0422e0185a5e013845e2d6de83ab729dd200a21088a1ec3
+
+Count = 262
+Adata = 4db5730cb9794f3b1facc9d6738115d02ba9f27ba02330fbb856
+Payload = 841e032773d58bc72a3237bc9b24c61b9efdd850fc2ea605
+CT = e190bdb50d497efeba7f80a94970db18dd8e0ebee12f1bdc10ed272c732247a696a608ef67510f9c
+
+Count = 263
+Adata = 471a900ee49f2cfa1d3eb37c951d810c349364d4cc3b5b64fc47
+Payload = b4db42e523e65557157b93dc0281601f7997e6731543a914
+CT = d155fc775d7aa06e853624c9d0d57d1c3ae4309d084214cd15f0df52e392c37ec15f7458469dae84
+
+Count = 264
+Adata = 7b40b3443d00a0348a060db109e8882157612c43084ac5c3e9c5
+Payload = 73e0ed35c0e847188e607cde46586eb9e237fbdc5d59163c
+CT = 166e53a7be74b2211e2dcbcb940c73baa1442d324058abe5421433dafea2b5484ba87b5050e1fb49
+
+Count = 265
+Adata = d563f5c048a1b45265182b99ca7b9004fdc73a9cb07806dd44fc
+Payload = 4f7669caaedee961dbba6bde9d09fee1a20eee55baaf98f5
+CT = 2af8d758d0421c584bf7dccb4f5de3e2e17d38bba7ae252cdf91749fe3cd52a9431d9a847a8c2a9a
+
+Count = 266
+Adata = d301a61eb17366d4e70942ab69b4f4bcf8ff6a97f5972ee5780a
+Payload = 154454fb74e9565c56775a8e4654f75a38b954dd28c4e939
+CT = 70caea690a75a365c63aed9b9400ea597bca823335c554e07563d37846f5185bb44d71be1ea6a73c
+
+Count = 267
+Adata = f74b48d168f77fbd3429728c0b168ecbd854264eaef70b74fffb
+Payload = 716b371857e68a17b20ea06651cdcfd4560a741830ca8a13
+CT = 14e5898a297a7f2e224317738399d2d71579a2f62dcb37ca55e93bc2d3f05d7016747690fb920e12
+
+Count = 268
+Adata = 3a257ce3592a8f88162f0bb4ecd5db3bb79b54ab17b0bbc61506
+Payload = cfdb7363985aa01af6f8e8237dbfb7871eb39303b4135269
+CT = aa55cdf1e6c6552366b55f36afebaa845dc045eda912efb01c46822f839f09c41b7aa6dc06035c93
+
+Count = 269
+Adata = 21916ebeca9e66b77cf55d1cac80a4c85d8b6b014f268ffa73ca
+Payload = b4b67ac551d1966caa20d951351387f384c2e5d81a76a92c
+CT = d138c4572f4d63553a6d6e44e7479af0c7b13336077714f54f8e77600c5bbc6d028fa25ba61a1719
+
+[Alen = 27]
+
+Key = 9498f02e50487cfbda1ce6459e241233bd4c4cb10281dcb51915dbc7fb6545c0
+Nonce = e3bd4bc3a60cddd26c20aa8636
+
+Count = 270
+Adata = 70cfcb828d483216b46c3cd22e2f9ee879e9e3059b566179b6e16c
+Payload = 0d16cc69caa9f19b88b05e151b3d26accd018ca4a5786a80
+CT = f1c4bedb8d6f91676881daa37656a7e6402f472735b04a0f1f8332f4236437737438e7aa1b5100c7
+
+Count = 271
+Adata = e7e5779282db80f424dc050b2c1e7754b2a5d3a8beae77beb74e34
+Payload = 148de640f3c11591a6f8c5c48632c5fb79d3b7e1cef9159c
+CT = e85f94f2b407756d46c94172eb5944b1f4fd7c625e3135138be2f6f356c2eb401468be15104e7763
+
+Count = 272
+Adata = d17e8189a94a559b07be9549f73d653172740e8e978f5b0a38ad43
+Payload = 00a23b25bca7c206edd051814d81083db1cd00048ce8ead5
+CT = fc704997fb61a2fa0de1d53720ea89773ce3cb871c20ca5a9646f2b6c2455603f1a6f20ea5a4611a
+
+Count = 273
+Adata = fda37ff136895de7ebeaf81e701e5751245201baed2e13d7e1b591
+Payload = a89409b0977f60a029dc4c1560ba6dbe7c65b068633acf74
+CT = 54467b02d0b9005cc9edc8a30dd1ecf4f14b7bebf3f2effb303fa5d8321241b1c9e18a5909d6e428
+
+Count = 274
+Adata = 9c179fd0d6277a5e073e77dd6abb4cba00ad9c9932e6c002b951c7
+Payload = e16c69861efc206e85aab1255e69d6d33c52cf058dec9d0b
+CT = 1dbe1b34593a4092659b359333025799b17c04861d24bd849e8cb01db1da077502814db1610662ce
+
+Count = 275
+Adata = cf5703228e615428d3d3805e428e754961d205c5aa0297ecdea71d
+Payload = 62036cbed3666d85624d3dc9c1f437454b9ab5c03ce0de92
+CT = 9ed11e0c94a00d79827cb97fac9fb60fc6b47e43ac28fe1d40a02a49857d7b280330b8105efac854
+
+Count = 276
+Adata = bab7e36098d59d3a31d7784d549aebfc6938bbd0612c85c0edb796
+Payload = 790ac86c5e9d8ce8cbec1dfb7e4fc4dca3d0b1039adfe585
+CT = 85d8bade195bec142bdd994d132445962efe7a800a17c50a5ecfa9dd03e2db70aa212ee7dcb573fd
+
+Count = 277
+Adata = 96f0b7cd7439721d4c9cc4f69585f8c90a95bed8fea22150efffba
+Payload = 3cfacd61ea3398de20ca6bdb00e81af482320614bdfb8642
+CT = c028bfd3adf5f822c0fbef6d6d839bbe0f1ccd972d33a6cde17a7a0cd162945a3616892e101e3e93
+
+Count = 278
+Adata = ee71e53d0b4eef82575c2bd38d7bd21b41fabe58c6f571954fe159
+Payload = d75c153e34ae1c6d1fcf5b1052190d8882041e1f9c5490e2
+CT = 2b8e678c73687c91fffedfa63f728cc20f2ad59c0c9cb06d15fadc2d79841d230cd55c04379f22b4
+
+Count = 279
+Adata = 18a4aa894861c7720ddb43809c3d2ed2af2f1bfe8f9fd4f872c14c
+Payload = 0e728056c7c64214be8f1f1727408d8cca8c42e2ac7bf67e
+CT = f2a0f2e4800022e85ebe9ba14a2b0cc647a289613cb3d6f1b229b9bae4634eea6b723f432e19ae55
+
+[Alen = 28]
+
+Key = 3ac7d5bc4698c021e49a685cd71057e09821633957d1d59c3c30cbc3f2d1dbf8
+Nonce = 54c8ff5459702aac058bb3be04
+
+Count = 280
+Adata = ecbd7091732e49c0f4bda2e63235ea43bbf8c8730f955f9c049dd1ec
+Payload = 89198d3acc39b950f0d411119c478c60b2422ffe7e26e00b
+CT = 7717b8e4447afcea1eeebf3e39ffdab2f52828e7931ef27e475acd27900478f09fec1f479ab3a7c8
+
+Count = 281
+Adata = 9a04820205234795ecd540b6a0b2fbd0b19f18106c42f374a2b98425
+Payload = c0f61950f98110db4226e269cf197c7e2794c5b87ad68cf9
+CT = 3ef82c8e71c25561ac1c4c466aa12aac60fec2a197ee9e8cf7b7ed6e8ede6ef5a73b484bf13b3424
+
+Count = 282
+Adata = 0e4dbd167da0240298f4795102ef18ff9a8772c6fd73b3374cdfa30a
+Payload = 7960dbc9136880e2eea7956c3271adfe2aba7dca53da917d
+CT = 876eee179b2bc558009d3b4397c9fb2c6dd07ad3bee28308e47d08ea0788f7ca0ecd846689c8027a
+
+Count = 283
+Adata = 2de4291068a5d290b599a73c6a8ecff4f9fd6c9cc48f14c233e18581
+Payload = 0c5d7055bbfbd2bc213cfbbafa763b71b1fde6f4de96fa59
+CT = f253458b33b89706cf0655955fce6da3f697e1ed33aee82cd081f66b1c7b70718dc50367c3da6792
+
+Count = 284
+Adata = dedeb714f555575fcedbd9de8171484090e6466dd4fba3c6b7c42eae
+Payload = b5654edcc8f09e4f80d0258c9376d7c53fb68f78d333b18b
+CT = 4b6b7b0240b3dbf56eea8ba336ce811778dc88613e0ba3fece672883438da186741e6c542b3f805d
+
+Count = 285
+Adata = 03d340904ace1cd52d4b72a96d96afd77aee68ac3936415005ed0d56
+Payload = d796f3409a7eeb896c3d4ebef46e9c6e553aab28b1cc4a90
+CT = 2998c69e123dae338207e09151d6cabc1250ac315cf458e5cf58d4a5552bc8ed1b1dda46703a256e
+
+Count = 286
+Adata = c67f9aa8cf1be3b4377c30c175d33ab2af390982c6a015d99209acdd
+Payload = e4dd279a79a381c68de777df941a4779e50a1381c8aa9122
+CT = 1ad31244f1e0c47c63ddd9f031a211aba260149825928357f95cf2b57e06de4d01bbb6c0e39f37e1
+
+Count = 287
+Adata = fef1b2ccd661b9fac85ba005addebdf8317ab104920549d3a490a21a
+Payload = bbf0c267d952aeb6f810601b9cf1962a92dcaba7273e6902
+CT = 45fef7b95111eb0c162ace343949c0f8d5b6acbeca067b777589cd12984286af98908db88920323c
+
+Count = 288
+Adata = 693fae7af84aa397f0b2baaed9b3c7953f75e7424c49b6349c2fc20f
+Payload = e8b13a263e0c4fb5645e500e88ab8074ab7d92e5a8dac6aa
+CT = 16bf0ff8b64f0a0f8a64fe212d13d6a6ec1795fc45e2d4dfee8fc441da990dd92c0caeac9d956699
+
+Count = 289
+Adata = 85e5df4ddec99f0bea14b3338b2eb190ab6584f5253c6c2ee3064637
+Payload = 067de2869333ed22c7b63ed7eeba1301bbac69b0d430adb5
+CT = f873d7581b70a898298c90f84b0245d3fcc66ea93908bfc0d502f5434bea8c3c13ad5422ff90e218
+
+[Alen = 29]
+
+Key = 948882c3667caa81c9b900996e3d591e6fcb3d08333eeb29911e9c6338710c17
+Nonce = 43b0aca2f0a9030f90559fa6d3
+
+Count = 290
+Adata = a516ca8405e5c8854e667921b5c5e1968bdd052915b55ac9984b7eefb3
+Payload = 8b9130b0c3c15366831bbb19f377e3209a8dbf7619cd09bd
+CT = 4646b2acdeb11174171da23999cd54e297daa32bbc13d30512e57c576b315f48c11877178389aaa0
+
+Count = 291
+Adata = db3121ea71294983b185207a9d8de3e484a66c0431bf07c962eb82977c
+Payload = 7f369bbc99b6f08049eeb43566269a174829d4dddb05cb9b
+CT = b2e119a084c6b292dde8ad150c9c2dd5457ec8807edb112366775e693f93af6575dccc7903538065
+
+Count = 292
+Adata = 1651cf38fd9b2da65ebb4922b97dcb861128eeefa060d6c1c94b25eb4e
+Payload = fd0900b5fa72e2fba43d611bad25de40a3507a5cc5d186c7
+CT = 30de82a9e702a0e9303b783bc79f6982ae076601600f5c7fb70d8de40c2068de96a274d3b5086b5a
+
+Count = 293
+Adata = af87b347b59e37a424004a00907dcbcf6a554e6782a9be12cb3047625e
+Payload = 36318d80c02a1da41ef1652d9a752e155526b5f597fba226
+CT = fbe60f9cdd5a5fb68af77c0df0cf99d75871a9a83225789ee7da096d2fb28f20f64a000fe93e96e2
+
+Count = 294
+Adata = 0680d5bacefa2ab14aa12b0e517a1432862d4215dc72dc4d5ac6b96c1c
+Payload = 7a29aa2994d11215ab3ef3382b3db6ed581164a235c4b1d1
+CT = b7fe283589a150073f38ea184187012f554678ff901a6b69b88748a2de31261534cdb2237565bf8a
+
+Count = 295
+Adata = 9af701f0a9de52309267289bd170fb97c03c131c0a169d736137ff3d74
+Payload = 3542fbe0f59a6d5f3abf619b7d58b199f7caff0205093f8b
+CT = f89579fce8ea2f4daeb978bb17e2065bfa9de35fa0d7e5330c003eb65ceedc98ae4e38ef341ee47d
+
+Count = 296
+Adata = dab7845fb7ead205569475753c7e26540c09d3a74312f2de25181511f8
+Payload = 83c15520d9541c86b3dd809ede42de22bbb2b75ff18a023b
+CT = 4e16d73cc4245e9427db99beb4f869e0b6e5ab025454d8835c2fb596d8ff6a863604cd224fa3be42
+
+Count = 297
+Adata = a844d6dbd05545ecc736994dc9fc2260c5ab63ed6ffdc40b915f8744a1
+Payload = 793a188fa3efa32f41d6e4c5b42353b95024117d546c79ca
+CT = b4ed9a93be9fe13dd5d0fde5de99e47b5d730d20f1b2a3722ac782e2cd8ecb06172eef2cb9b0e331
+
+Count = 298
+Adata = f9112503884615c0e8a1d8414724b0d19298988f393a27c436b2b6734c
+Payload = 6b237444fb0e1f4150701546c4cb24021c5edad30d9b31dd
+CT = a6f4f658e67e5d53c4760c66ae7193c01109c68ea845eb65f814492b42571033f4dffc0282ea2f51
+
+Count = 299
+Adata = d633a5a3defdde6a68f959ef39a91c6ea6e13ef1a7859d2c2c94d3a5b4
+Payload = 6342312e8a72f71f2e5afe04cfcde4d60a41556111752103
+CT = ae95b3329702b50dba5ce724a57753140716493cb4abfbbb75999099df2de6e436bd99f0341423f4
+
+[Alen = 30]
+
+Key = 3bf52cc5ee86b9a0190f390a5c0366a560b557000dbe5115fd9ee11630a62769
+Nonce = f9fbd02f28ecc929d369182752
+
+Count = 300
+Adata = ebf0b3e3199a5c3773c761c725c7600add5f9d8321c9f8e5e5fd1c7a5d2f
+Payload = 094b538110495e938b08cf748a6bcf3e0c80ff9c66570237
+CT = 4d8b53016fc8bc9677184c0fa15bbd3d671b9366d82ecb67f8562eadcdcbcdbad1299bea1523f5d2
+
+Count = 301
+Adata = a865b88d512e485ab3f2844c29e6dde0cf1151efa9ad3b3021d06fffb74b
+Payload = 23edddd8732cdbf03af08162f0e4a24c9222bdbb4549c663
+CT = 672ddd580cad39f5c6e00219dbd4d04ff9b9d141fb300f3359ff77cf0962455b3539dbf91f3077cc
+
+Count = 302
+Adata = 16918dbc785d94a8f1720c5ad234dde860219874c9fb076a5c290903f85b
+Payload = 1798286c37c1504fc0d7402681f6f70711ef506dcc3e29d0
+CT = 535828ec4840b24a3cc7c35daac685047a743c977247e0806dbed76d94c90595b49d50c84c3efc76
+
+Count = 303
+Adata = a2969243b0955402ab45a430fef2ef9e0c025006732bf8e592e3d3884918
+Payload = 0d02778f90a164a4f9ada9dc7fd24eeb941069621418ef32
+CT = 49c2770fef2086a105bd2aa754e23ce8ff8b0598aa61266248fbe60c146056e5cb01268403e4b9f5
+
+Count = 304
+Adata = 2de5222a0609f058f60e9e581b6e4f0ddebed84fc8302c8e985d17b89241
+Payload = b0c3858231e284af6d231f043b95772f5e7b16a34ffcd2ec
+CT = f40385024e6366aa91339c7f10a5052c35e07a59f1851bbcacff35df1ec942b43eef5aef980cb038
+
+Count = 305
+Adata = 3fc7453df038a92829dc103d44b63ad097d7cd7f9ae7996547012090c7c4
+Payload = 319f396cc02834f8e69d65f77496d0eb31ce1a7b7e324820
+CT = 755f39ecbfa9d6fd1a8de68c5fa6a2e85a557681c04b817091a93f5fc28e5f4f351cfb888da763dc
+
+Count = 306
+Adata = 18f1e92bd3c4a597ed970911d03a78ff9a6790147c9bb0ca5f23b70cce7a
+Payload = 25550c03f8fa02b3781330f96e0fdc58681b0c0bc5e83fe9
+CT = 61950c83877be0b68403b382453fae5b038060f17b91f6b92c6a90ef2e9a969ec0576fae1d126a85
+
+Count = 307
+Adata = 09ecb2406054716418ff3600c3c5cacb0845a377a2d80542abc36ec81bb1
+Payload = 210ff7975e08388b9a46eb732230e3a3856a497549b5eb49
+CT = 65cff7172189da8e66566808090091a0eef1258ff7cc221959fd6aeb047200907911621e8756b45f
+
+Count = 308
+Adata = 62d515bb0525b565a6a3613ae20343c8da7424c8368e8cad6a862b7d37a5
+Payload = 5d867265965bb2aafebb0691de9e157a24066d06fe3cbd7c
+CT = 194672e5e9da50af02ab85eaf5ae67794f9d01fc4045742cc4db6d5fd910c83fd77aefba3f7665d8
+
+Count = 309
+Adata = 00617ca141e55b045a188e4934caf6db63d4577f634db92c22010e1cbf1e
+Payload = 396b27afd16a1081f37bbc1f742b549f5f68df799b93083f
+CT = 7dab272faeebf2840f6b3f645f1b269c34f3b38325eac16fdf5f21f32cbe5d272004f1c104cbcae9
+
+[Alen = 31]
+
+Key = e45bb1730d0d539aab3805350ac986540de9f0f6c239ee70395c291397b70309
+Nonce = d5c7824af715bb7822b6b340fe
+
+Count = 310
+Adata = 860f4a09ad8b3d345c2aa18ffb803f0bc3b734a4d047a1437701a5e3d95288
+Payload = bc8b3bc48c7a88c9fafde258b6ccaa9d4f0d018703d63871
+CT = 95f083ad6bbaee6ab540fe023858f8baf25e333fd3e89c00e678a392d228b210dc5c991905dacf3f
+
+Count = 311
+Adata = 8a84b57915bdbe7bf5a1c1a426512b3c178d883251cc46c95a8bbc8ed9e56b
+Payload = 9499ea48edab9bc21b91dd614f04934ca20db8630622f481
+CT = bde252210a6bfd61542cc13bc190c16b1f5e8adbd61c50f010fbdd3b305522dae6b652322d89d9ac
+
+Count = 312
+Adata = ed8540f7ce451c522c1ff5d2d1030d7b3fbd1219a21aaa84044c4f23c08f5d
+Payload = 73843a4e9e7937fed24bb1fae15822213b1aa86c07f1b5d1
+CT = 5aff822779b9515d9df6ada06fcc700686499ad4d7cf11a08b6b08548e794eaf85ad9f5de80b1c00
+
+Count = 313
+Adata = 61bb196b212feab645f05a8aa1986f6210a384c15bc749245d840b3565fb36
+Payload = a8e24266e5981b2ed14213a29f961cbbf7f02f63a33c987e
+CT = 8199fa0f02587d8d9eff0ff811024e9c4aa31ddb73023c0fcc73643a7ee9291e15137d7046a92f3f
+
+Count = 314
+Adata = a49c2df94ba65107f375ce1c53b72406143f6bcd270945de5b7811682fe361
+Payload = 3e3c402caeca41687d12897102e04312edf7b8c7d8567a22
+CT = 1747f845490a27cb32af952b8c74113550a48a7f0868de53204438662ea82f423a69c6e4e3c0623a
+
+Count = 315
+Adata = 7c48480e9bc87ba299e03899698b2259eef150ee0f2efff40a5583b80ab484
+Payload = cfa9292b9052ac6bb863205d3c0dc2d9e20d2ba6a680d2ed
+CT = e6d291427792cac8f7de3c07b29990fe5f5e191e76be769c6ea00b9cd881e3f4b1e838dfa31f6560
+
+Count = 316
+Adata = 5cf9744090366d828b477dc890eab8ebebd44f6aeaa5b101291bf67d12867e
+Payload = e0fe4e139ab0deb4fdf2145b719f35c50b869e6cb20608b5
+CT = c985f67a7d70b817b24f0801ff0b67e2b6d5acd46238acc4c59b3b87d722a58cd1de58f3963d12b3
+
+Count = 317
+Adata = 761d74be5fae170a1bdfa16081b44c1e49972e15ce0818df1390bf7204f619
+Payload = 665fdcdf55a1231e9912562eaa5a5011d69f6948e29e3f8f
+CT = 4f2464b6b26145bdd6af4a7424ce02366bcc5bf032a09bfe158759886124f1f0ce8147c94f4e7114
+
+Count = 318
+Adata = 9815353b69d0b4effa52cefff13703fa71a6296f9cca0f02568661be4b64cb
+Payload = 7b2d52a5186d912cf6b83ace7740ceda3f5f443530c5a49f
+CT = 5256eaccffadf78fb9052694f9d49cfd820c768de0fb00ee6310a79c9932456dbc00515b264f3168
+
+Count = 319
+Adata = 69dd1a050c8d79dafbbe3403af4dc1f070b9b2b980888aa796e6cff68d9060
+Payload = 3cea5ff50167c5641066852fd00061df35b1f66bedb894b7
+CT = 1591e79ce6a7a3c75fdb99755e9433f888e2c4d33d8630c6da7e97f9984a7db3b93aefb4316d9acb
+
+[Alen = 32]
+
+Key = 2e6e34070caf1b8820ed39edfa83459abe1c15a1827f1c39f7ac316c4c27910f
+Nonce = c49ccef869bb86d21932cb443b
+
+Count = 320
+Adata = d37e35d7cdccd9824a1ae4c787819735e4af798a3beb49d4705336d6496853ad
+Payload = 771a7baa9cf83aa253349f6475d5e74dba4525307b022ba7
+CT = eebac2475004970071dfa2cfb855c4e78b1add8dcbccfc0bd6b14027324b657a56263df148665393
+
+Count = 321
+Adata = ab22bc22bf2628b0e0ab245c3db2fc5128d13a011c2cc9b9fea05a79a3410704
+Payload = dad95a4b4d3754613f0542caa62cfe4e375dfbdd369ec32e
+CT = 4379e3a681cbf9c31dee7f616bacdde40602036086501482a8c810b6944815fd2e434193520b1d5b
+
+Count = 322
+Adata = c48c5aacf701137fc40fd0d3649641aaa5be427ceee702cf7ddf6408f458a581
+Payload = 3f28df9263e473be648fabad163aa4142b633388b16d8392
+CT = a688667faf18de1c46649606dbba87be1a3ccb3501a3543e8aa447b79284c588bef50b423de97908
+
+Count = 323
+Adata = 477c2484cf5c56b813313927be8387b1024f995e98fc87f1029091c01424bdc2
+Payload = f83107b50a1f192ed45cc43fa80e6b519bfd859173ea9ee9
+CT = 6191be58c6e3b48cf6b7f994658e48fbaaa27d2cc3244945d4f4a413eb3ac2c474134995d4db9a16
+
+Count = 324
+Adata = 143bc037f1d0bd4ec16825c58cb3796bf8989200d27bda9beabbbc49247f59f7
+Payload = dfeb324ba459ec4a5c54d2534e98002412e67db19cfc66bb
+CT = 464b8ba668a541e87ebfeff88318238e23b9850c2c32b11756a3fb2e06734b28fbd57942a609d914
+
+Count = 325
+Adata = ffc416f1dae4e43c1a01339a604c44d6a0f25ab9ca3978c6aacb6d270d510ee6
+Payload = 0765949e6f22c422ebd47dc1ed73f1b849d7a058a1656fc2
+CT = 9ec52d73a3de6980c93f406a20f3d212788858e511abb86edb94280d3c4a1cd8cb00705f60ae36f2
+
+Count = 326
+Adata = 6090b596b4082ec6926576137f6561cf13916860ad1cfc43650d1b5142a12041
+Payload = 6db320cbe76bc5b8cee9ef89aca11765571c6c501993195a
+CT = f41399262b97681aec02d222612134cf664394eda95dcef612caca26cc3bbb289da3be0616b3445f
+
+Count = 327
+Adata = 178ba75adb7c5bea6769270bb3b4f6ce208d4a786913d3ced7bb4090b5f65544
+Payload = 0875020959ed969cfb38636d1d5aabce9658b00171a7614e
+CT = 91d5bbe495113b3ed9d35ec6d0da8864a70748bcc169b6e26cc8c665289d907628eb0e299c2d411e
+
+Count = 328
+Adata = 90f0474dca998916075b1b1428df14d90be05491bb8d5d88e32e65ec890ba9d3
+Payload = 4f89ca6ad371f86a6e073ec12fb1b928bb10d6639233b918
+CT = d62973871f8d55c84cec036ae2319a828a4f2ede22fd6eb4f7e481607a2a0529f9cda1d5903325b7
+
+Count = 329
+Adata = 5ad8dd40ecdce52d5b30424ca0bccb666f34f66b0c9a4c1260051ac04ca06aab
+Payload = fe2009d0a4a1711b83057b948cd0b174a3a042fd97579ab8
+CT = 6780b03d685ddcb9a1ee463f415092de92ffba4027994d140a1b9ba2bfe5bf778b859f0ff0c29a67
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT128.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT128.rsp
new file mode 100644
index 0000000000..b796541cf5
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT128.rsp
@@ -0,0 +1,456 @@
+# CAVS 11.0
+# "CCM-VNT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Tlen = 16
+
+[Nlen = 7]
+
+Key = c0425ed20cd28fda67a2bcc0ab342a49
+
+Count = 0
+Nonce = 37667f334dce90
+Adata = 0b3e8d9785c74c8f41ea257d4d87495ffbbb335542b12e0d62bb177ec7a164d9
+Payload = 4f065a23eeca6b18d118e1de4d7e5ca1a7c0e556d786d407
+CT = 768fccdf4898bca099e33c3d40565497dec22dd6e33dcf4384d71be8565c21a455db45816da8158c
+
+Count = 1
+Nonce = f7a5098b2a4d92
+Adata = bc498326755503ff25d02805eb3517221b54eb4fd79af0fcdf9312b2a9ad95f7
+Payload = 3e2144e2a381b718962a77e167778bf579957a8fae29612c
+CT = 98ce91033fabaa8fe853d347be6cbe5de102fdccf042e7be697b41c9a69acaf8386140ee6e36f406
+
+Count = 2
+Nonce = 732d2dd64b4a25
+Adata = 495b03df82e317e4f351c5323d17c673f4c77856983179d7c7cb75c2b0573c72
+Payload = 4bb0d170bdcc70fd18f19605cf9c6181082c4367f1e6fbce
+CT = 9bd9304259962448fa8487bc15d950303621213afd88f1e32d442ff663242fa269c4a742a220edc5
+
+Count = 3
+Nonce = fefd3ac595428f
+Adata = 91ffb6be8e129cef9189f7e0fec8e937afcfc6083b6a79a778a724bb3e8d0794
+Payload = 9e8c4f1292e8d7e5179b34ae5d2ba2491d7754acc54bb91d
+CT = a5d012b3062cc93b831860d76539169c88854b85550c67fc564a2f1cb7d77e0223287740d5ff9003
+
+Count = 4
+Nonce = e14d81ee3b873a
+Adata = ecdc5249ceb48e8d5a4483043921c00c1acb1843fae00155a28f3a127150b1c4
+Payload = f99e23288e6b5ae85c14610994d90d5fcbcab62b4ed1333e
+CT = cc4ee711d0202deb58664e00cf0cf70b737f48ddadcefd6cd217fb611daeb66fa2d8e1bd43cb2131
+
+Count = 5
+Nonce = 2cbeaba94dbbd1
+Adata = d129674c6c91c1c89f4408139afe187026b8114893d0f172f16469b183fee97e
+Payload = 1b42cb685bd462fbd40e0273a81c767aa81cb43f17d3c0c9
+CT = 1a1b1c7130aa63098dea17ffbb2216d1d276cb10145b0762a45116736e95d823e579d73dc31dc487
+
+Count = 6
+Nonce = 8a961df9c23f6d
+Adata = 07185502bf6d275c84e3ac4f5f77c3d4b30d8e106603be84410c11849a3c18ea
+Payload = 434e182d04ecda519a6119fbaa4c45e8c9803a9a3eb51dae
+CT = 3f603939c6226d8208b2b0e675b82557609ceaeeee4032c7837ed517dbd7e6fe34ea42b01c69d370
+
+Count = 7
+Nonce = d3604d390faab3
+Adata = c95e7329d36145664da69d25f24b301d334e1bca2baa74b2d5c325ed7d04fae4
+Payload = ee104be898a225eb1da99163bbf768d8ae6d5850af6f8767
+CT = 3e6a7683d9d804f791f77d2b69996102ba82477ec4557747ef2e0b322f51abb366a1e8e37f4fe4ee
+
+Count = 8
+Nonce = db5004a1cdae8e
+Adata = 1370fc9d5bf1ad2d071be5a28b235402a85270f536b5601c221519a3b329c71a
+Payload = 59bee7d18fd4ba573f3e4f61076f5b9f6a3487e47d98c729
+CT = 6db54d6f5c3f3efa6da67aea1234d46e8b679a5c257c66d82e4ef944778281ed186b4a8099b47fff
+
+Count = 9
+Nonce = 783477f981ef05
+Adata = 04bbf2a826bdf3d55069b1936c4f8e8e08189f54066a035c950c7347604b1b65
+Payload = 6150f132b25727ebbaed9f16bd91ebce00c68e5b39bc0ef9
+CT = 36f78cef22cacaf9f3d4464821737f7fbacd79be517b4727bc5c098625c51ac7fdd15da2cc9ef4b6
+
+[Nlen = 8]
+
+Key = 0b6256bd328a4cda2510d527c0f73ed4
+
+Count = 10
+Nonce = 21fd9011d6d9484a
+Adata = 66ff35c4f86ad7755b149e14e299034763023e7384f4af8c35277d2c7e1a7de2
+Payload = 78a292662b8e05abc2d44fbefd0840795e7493028015d9f2
+CT = 5a0be834c57b59d47a4590d8d19a1206d3c06e937a9b57f74034d9fdb43c3f48932aa72177b23bf6
+
+Count = 11
+Nonce = 97f940d7c1230bd8
+Adata = 78337ddfe38be7897372b0f805603a9a9e55598452285764641c3bb7aeb54a3c
+Payload = 772aeff60eb3adf5a9589ad54dda0401cc9765589609dbd3
+CT = ef5c408dc6d0b501925a47def54d8deb9880a07a3e6380bca20a3995cf25c5a7b9477d8916adff73
+
+Count = 12
+Nonce = acfdf302ed116ac4
+Adata = fe9d9989bffae3c9e6161eb0aa9d54ee8f5051f0dcabb5a750c5478c11798ce1
+Payload = 99ffe16de323a9b65fe60305a2d062cae490ccca6d9fe9da
+CT = 1bbc2c7877d845591660636cb6ccf4edcd4c156996a26a707d0e2fe322f203c08f44d7f9bd7258c3
+
+Count = 13
+Nonce = c8d36e13b7459c47
+Adata = 3f3c3a4c26dba18f385274ac5ac3df73282686488d91bc8190b7f61071b07f62
+Payload = 316ee95430329f706348886b8ac7779e3056809e25da0a03
+CT = fd2db9611a26a3e90f4861467df60edcc595f442332b089905fdd72307c3355b19ea66d4a16ef17d
+
+Count = 14
+Nonce = 5822755a3e47c27d
+Adata = 1d72d6b371e85ca359483761704f80b3360f4d6610e6d5e490b0d509f73c3233
+Payload = af4ae8f19cf6cbd199677fe033859f56906f1979b1b5926d
+CT = d5ed6f8d5c42f4f3ea527094173b278724a2ba787e416ad759124db19ab1373a5376f46ec7095ef4
+
+Count = 15
+Nonce = 6c1c94c2e71b865b
+Adata = 298cac1e4684182786f386ef3de79c11e30b2dab7579b8ca18d0312200860403
+Payload = 6e4d992d7541e02a4aa167e56c7e47206abc25fea6c5125d
+CT = 560cd43a502a6e8b1af478a3b640a68937d1a83057110d38eaa52d69ab9790edc384b9a5d8c91dbf
+
+Count = 16
+Nonce = ce7ec65cfeda31da
+Adata = 13c1298cbf7fe6a9ab378f86d3c2207944cc2a232f9383513ceb3b202086d365
+Payload = 196c80d02b663bdd89fdaa31e329b5a8f7c596236ee8dd80
+CT = 00174dd83a7f8edc71afbe5da095160336be9184f693db3db1f45de395e021c6fb1b2991c91bd643
+
+Count = 17
+Nonce = ddb739acda6c56ec
+Adata = 7f89bbe513b9a7ebe9be3f6eb88782080593c83e8cbe47fbe15bdc3e5782090f
+Payload = e95e142217c838d1f998a52e342e4f2d80b1cfd35cf6b73d
+CT = 819d73dadaf095652cf39729b2e2cad7fc7783887a5acc15713d941b845d96a5bf65e9f80ae7f923
+
+Count = 18
+Nonce = d9bb71ad90152d5c
+Adata = 20bfcba120cdbeb07c5f4d70338ffce493822d78a03c9e80b5b934e16e39f70e
+Payload = f1fe98b50ea2f9f088f6f93910757cf744d5aabf3081966d
+CT = 36decda8ade6ab104a201c6d370412b907a559738eef59665e99761cb1ac77d772b9cce9345d9a75
+
+Count = 19
+Nonce = 2c9ec9f1f1358c50
+Adata = 96f0b1edec4ad14407dcaf30ed68942b46c48d58b2dd63af60fccd5bdd48e560
+Payload = d74badb8ad7f2c2bcdf67e497151d35a4fc2a3c4c871868a
+CT = 0e9066270da6e03cb4307c43adc71b4b596213a63fc8032085ce60506ac3bd97327904ad2e072a6a
+
+[Nlen = 9]
+
+Key = afdccc84f257cb768b7ad735edbd1990
+
+Count = 20
+Nonce = b7776aa998f4d1189b
+Adata = 9f9ac464de508b98e789243fdb32db458538f8a291ed93ddf8aeaacfbfc371aa
+Payload = 56d0942490e546798f30d3c60ad4e3e110fc04f5b1c1fa83
+CT = 96f124c74fd737819008ddef440320f4a3733d0062c83c893e259aecf12ba08f2a2e966a3341d6d4
+
+Count = 21
+Nonce = 278cf1f09b13f467fe
+Adata = af9627922758a9f7792345716782e8837ca78e8f9db16e3fe12a7124a3d4e99d
+Payload = aa9b9e80cef47b6db3816b1d665f233e696337e21bb8333a
+CT = 5eba7e3b3ecab78121b0d56acb9dbfc6756c1255b42f145d11751638ed36c1fd3c7268b71633c1cf
+
+Count = 22
+Nonce = 4ae701103c63deca5b
+Adata = 5872a1507c833c581ac2750b2b54add4b92be14e45d72db7679f8fa2b4d1eeeb
+Payload = e832b053854fbd40c0d8b6d6b8fd5de2da0c173f5fe594ef
+CT = 3b2b964c3a90d51c0ace186db79818b4d0f7b81236d36017d3635aa1d8167087600b01643b0a5ce5
+
+Count = 23
+Nonce = cfb5b12928e1c36849
+Adata = febe755bb8e4475d8d12f5e96269abd0d4e40d73cb966e2c523343e9a6d2d71a
+Payload = f46d6970dcc37d32d93ff062e68034c1906ee487fd28eefa
+CT = 0d5332a42fc583f4f81744b899cdf2a64cad1e78d577112fee6f8c4b252e10b42fbaf8c7af1e9f3e
+
+Count = 24
+Nonce = 68d5863cafc69e6ceb
+Adata = 048ba28abb191ded5449dfe9dc7d19f9b132a2a9fd779aab7da44d2887485954
+Payload = dd4438d7ba3edc73872e42dbbf78cf300fe4bf0eac9e16b6
+CT = 874d3ef7f916db2c2799b6892ef4bfbeb4729ecbf26ac4983a8639f21f8548fae45dc76de57bcee0
+
+Count = 25
+Nonce = ea09fbe5da0fa4fe91
+Adata = 63ee18eb720b21ee4c157dafcb8c7bcc6817f54d5c1b8dd7058c37228a03f8ad
+Payload = c1811d613bf0789beeef693611ef733cd173da703b66ab3c
+CT = cbe5c799952b28fadf414607a6cf8194e9f41194abace4541d3853a52971b0ab46cc0a3eded435c1
+
+Count = 26
+Nonce = 0021be18ed76b3a34c
+Adata = bb5eded483f0ae1106fd08c5e2b91cf06d3a7a73518ad4c479fb05e631ba5399
+Payload = 2d5531d1c51c6ea100b028596bf9f24dd90be14eab58f07b
+CT = 7af0449f7359b7f3e5f6c1e7bc264c7724037f4f16077fd0a2a8e3cfb827c7e6edabb34f7bbafd01
+
+Count = 27
+Nonce = 449b51ee0760179e35
+Adata = e99bdf783070a3a48431704e90277ca65a9704c12eeae2e2d70b62f816115267
+Payload = c4896d58442877c986e4f862a9f3a3179f0e9b96316a90d8
+CT = af7531c073df01077fd5c8ea9a5530c2fe1688d529e5c2f24aa8feae6a500919a336dbba1d9fb7e9
+
+Count = 28
+Nonce = 232114642e0c6b55b5
+Adata = da288d2014616f16a2abf5923dea49aded1748592adbcd97415c33ebfa57150d
+Payload = 11fd3f94b5a5ce94f2740a27a0771aeeac77f3155d2bc12c
+CT = f0c174a7927da0bb88e92917af8ae1df4ffc3527004e9e2d0b25cea7ed6e4fe9069a2ce49875230d
+
+Count = 29
+Nonce = 660cb6d654afcbdab4
+Adata = bd96c3c225099fc58cc1f97779304606b11efe9712fba13abf74fc1d7d44a900
+Payload = 793c0bc3deb6e0bec4c1d1fc17e455eb1aa5e9e25cada861
+CT = fa4b14a381ee41fec7b7279e58f0d06a3beec26d645f81336218635754d5563f2cd48bdbb267e5ca
+
+[Nlen = 10]
+
+Key = 6ccb68d3838d4ddf660b9cd904cad40f
+
+Count = 30
+Nonce = c4fb7519a19f13d9d1fc
+Adata = 092e64fef08b5655a86cdb8de63ffaa7772e8730844e9016141af8bad2216246
+Payload = 5ea35c082e2b190e9d98e6b2daad8672f587b4f2968072fc
+CT = cda5fe3d15d00150b99120c7f206b88a4c2c4a39ca9143425603ab284a73a38cc916f8b653c92ab4
+
+Count = 31
+Nonce = 45927852550961f1ae9e
+Adata = 53ae030474795ffda4d9ac0fc3c45afb592ddd761f7b5335c13a6747e21075a7
+Payload = 6c5f468077536b4c9a94ea4a6fe3cf621083a210daee45b6
+CT = 694847b6429cbc3902d9cb7049625aef1e97b569e1e3169035bb811491d142cf1b26350f8451bd14
+
+Count = 32
+Nonce = d8c54463dfcf02d0e327
+Adata = ff95c0ed0da32d1b5f57570b815a50592ecdc9c1c4e727e0f6dfd93fc10ce88d
+Payload = 7321a6de8d694ea05623206f5df438c5c2cdd6b1eccab4d8
+CT = 9cf8ef119aa5cf3d6305d50b2b520a0b10bcd240e27276749c68e8e641b0120f7dd66e8f0cfa4205
+
+Count = 33
+Nonce = f690f3a996928275050b
+Adata = 41c05fda535770699ed22cef253753b658437f833afe65c9c393581d835f0fea
+Payload = 56520a4bfd7b73a471e0446f9524a407e81c2681b7329e35
+CT = 14aa15f9f64c4c64f6e88094e012ecb24193249f044c033dda44a62f97c0fead3f65b28928bfbcc3
+
+Count = 34
+Nonce = 26eb9ef25be62148fa61
+Adata = 8f45608a07521de86ed5a84a851e629b579b51d7bf4cc7202a773e0f9e9d8748
+Payload = c68094c26c7f017b79f126dc26b3bbcb95f97535ca412da5
+CT = 7ba8a0c2fe2b230768d1c1874085ddff8926931961bc4558f0d5444466bcc631bef8e58fe5818af7
+
+Count = 35
+Nonce = fad21bc27dabafe7a4ae
+Adata = dc5d7fd97bb3243ba585fa0d71a07191667af418e30a6b76bedd05b32c673403
+Payload = c247fa8d8091cd3f299cdacba7fb7af93549e9e3160f9cf8
+CT = 3097d2ec0f8bf00b22504ab03a75e740d3e59c269c3ee3f00b5419293a67eb008aef0f9f675201df
+
+Count = 36
+Nonce = c911348848fe67406dea
+Adata = 50d50a0b5ed4d6904ec3045263af0255a6494b7a7e2e95ea806c4bb788423dc1
+Payload = d846c170ae0111348362901503b26d58f5efc17b6d296aba
+CT = 5d72562f7dfb47bf34b90ee4ea11ff9f726c915b07f4d843dec5a554f4bbecbf6943ffdab8d8a26a
+
+Count = 37
+Nonce = bb921b46a16d20ae4046
+Adata = 7d17f8f60ad1e61a168b5b0e7fbbc90cee79b612b6d6c0d7ff6ede042341e8a1
+Payload = 71bb6ae84262646c9be95e0f4289ffeab7555ec6746c6ae9
+CT = bac123320888b553666249756e6d63b3498760791cbe9e34e5b1162b7489a59a50c0f0f3618e6c2e
+
+Count = 38
+Nonce = 61a8b8cbfc9bdbadb2a3
+Adata = 51cf2a8949e13eaa087a34c9ec4d7fd92b862efd6a0b1fef8b016fa2c6933426
+Payload = 362f9a46aab59fb6213c83d791b2129b34367ac2de2048fb
+CT = b8a57e8714d8789f4ef2af29e0efec21b1ef67fdabc7cdf0ed5505f1f0ff77723771338585c456b7
+
+Count = 39
+Nonce = 6bc4cd23c32a913998a7
+Adata = 92fbc970b5e64198ce2a138de92767edff8d82f12f8832444b346d159657356b
+Payload = fa442383da234cf8f0c5fb667218bc3bea0c091b3a8e6b77
+CT = cdfe3e83aba43a9804c5a1832e0e47a9a153359cc32db907714025f485c7f40256049f16f859b859
+
+[Nlen = 11]
+
+Key = e6ab9e70a4fb51b01c2e262233e64c0d
+
+Count = 40
+Nonce = 74e689eb5af9441dd690a6
+Adata = 42f6518ee0fbe42f28e13b4bb2eb60517b37c9744394d9143393a879c3e107c7
+Payload = ba15916733550d7aa82b2f6b117cd3f54c83ddc16cd0288a
+CT = dcc151443288f35d39ed8fae6f0ce1d1eb656f4f7fd65c0b16f322ce85d7c54e71ac560fd4da9651
+
+Count = 41
+Nonce = eb118fb41284bfcb1bc338
+Adata = b5a6067fbac46578cfc8d3fe04108588c9de077eb009249374f205553bba9d02
+Payload = 863da00c7accf45418d47c1eda72338734dcc49cd599f328
+CT = d64de7a56146b971e21bf5784d67bab32dd837cfb81591da4a0177883346dc896eb39e8a32bc1393
+
+Count = 42
+Nonce = caba2716d07e95de83855e
+Adata = 0e0ff2c73ea5fa8f8726a3514cf906ce1610a1a6dc19b22682f9e4619f762d82
+Payload = 2af6d5636ab65db2058b2ba16df257369fc4e8aef8b9481c
+CT = 3c9e006c7d8eff5f448b0cc9c27c964713241aa7fed3665d775ea25fb272981de8b8aa0a637498fb
+
+Count = 43
+Nonce = 314c136999e41d137bd7ba
+Adata = 366c659bc45d0a88acd54ef7eeaa3e140e1cafb1b01474a065a9d460c5e83bfd
+Payload = 217b19ea6a431a1f66bd9d02b718e8507a08ab8e6f603e3f
+CT = 33d7b672b23e8b03a39ff3fd1e7b0f2be67163e3e3bae072f2aaa211dec623947a50b1252bc5aad3
+
+Count = 44
+Nonce = 6fe51f5013f53d4e4fd907
+Adata = ff182f2e179d790e827cbfd0bd8b9297ecae57ffcef9e25ef114474a22e4ec5b
+Payload = c6bf582b49dd4ab6cb33f3f88e8a4d14fe32b308ee3b4682
+CT = 26cd5dc5eac2acda283ca03354260ad57af79e20c5e92f5775ed171bb0fbaa6f431c5411cf9b536d
+
+Count = 45
+Nonce = 24bc8dc1e2354667b79ba4
+Adata = d0d48d01fc79685c6bee04d45e40d06cdf1f4607542b1ece556fc2d1bb2b03f1
+Payload = 90f52ebb1bd5439386faeaa194623285f750672a7baae64b
+CT = a7f43f56c50705a1a101044b954414fdfbe32b518e934d38f391749ea3acd624c01e4583ab1506b7
+
+Count = 46
+Nonce = 89ce46b3de3afaf2518d41
+Adata = 5767202c913584d653f37d926a0c5ac1c67db3efd1dc58fbff998778a6856254
+Payload = b2ab379a0dd15baf91415eee3a4e56e7eca54d4c1c3094f8
+CT = 9f530e455a54b86835eacd8801b34c884a3b2ac819ba38f894e43a6b1cf73cb2d6a1dd8331549520
+
+Count = 47
+Nonce = d3208eb695e84c7a925037
+Adata = 91d8fa65a6885f162a795afe2898f391990a8b3a87c11f94734dcbddf5f58da8
+Payload = f15e39f0e4eaa5bf81359d8e30186522f1a1a415436668cf
+CT = 7f1d9fcd9e5cce3a81e3495bfecec817fd7180d8bbfe0abab27fb6425fcc3537ce471425a5b17dcf
+
+Count = 48
+Nonce = 067de2869333ed22c7b63e
+Adata = c31e441fd551b3fdfbe23ceec5ec1f838f31a5300f6055ad2a936a9d0c1c856e
+Payload = 1536d9c9a09302d142c85638202f5bbf0c287f68115d51d8
+CT = b1a5c7a7fd23228dc7ea26885802daa0719f6a23681e1d65dfb879c21b46f3307ef22f1da579303f
+
+Count = 49
+Nonce = 15f61b4526d19bceae1093
+Adata = b97b122af73e928e617e98684f845be4cb80566345739b7a884c6a3eec5102bf
+Payload = 37c81988c07a5b01e2b40ff9f9ada5f50ca764efb717ff9e
+CT = 0d93a5c77482d573b7f1b8c5e283f2571efc9f54216a4c01900504a73c8817ff2b55618b2602bf38
+
+[Nlen = 12]
+
+Key = 005e8f4d8e0cbf4e1ceeb5d87a275848
+
+Count = 50
+Nonce = 0ec3ac452b547b9062aac8fa
+Adata = 2f1821aa57e5278ffd33c17d46615b77363149dbc98470413f6543a6b749f2ca
+Payload = b6f345204526439daf84998f380dcfb4b4167c959c04ff65
+CT = 9575e16f35da3c88a19c26a7b762044f4d7bbbafeff05d754829e2a7752fa3a14890972884b511d8
+
+Count = 51
+Nonce = 472711261a9262bef077c0b7
+Adata = 17c87889a2652636bcf712d111c86b9d68d64d18d531928030a5ec97c59931a4
+Payload = 9d63df773b3799e361c5328d44bbb12f4154747ecf7cc667
+CT = 53323b82d7a754d82cebf0d4bc930ef06d11e162c5c027c4715a641834bbb75bb6572ca5a45c3183
+
+Count = 52
+Nonce = 6a7b80b6738ff0a23ad58fb2
+Adata = 26c12e5cdfe225a5be56d7a8aaf9fd4eb327d2f29c2ebc7396022f884f33ce54
+Payload = ba1978d58492c7f827cafef87d00f1a137f3f05a2dedb14d
+CT = aa1d9eacabdcdd0f54681653ac44042a3dd47e338d15604e86a0e926daf21d17b359253d0d5d5d00
+
+Count = 53
+Nonce = d8e133e7ff8e0a0ec6c4096e
+Adata = ef9e432c15d8c93a4b5c0666608e61c824cd466d7940d642acd3dc33057c0395
+Payload = 2836de99c0f641cd55e89f5af76638947b8227377ef88bfb
+CT = 5edb056d85dafeaaf74bdf4caa47339d6a75bf1ee998565e9f9cdf6ab825f6e026f5be2ad895033e
+
+Count = 54
+Nonce = 2fa8120398d1a946f391367c
+Adata = 377cd407ad28dc02bd3835a31d92f8295c9dbe597f56662ceda112c588dc73a5
+Payload = 7a37255b682766a0bfecf78e5162528885a339174c2a4932
+CT = 701f5f506fc7e9ea4a27a4db5cb890f7be3b4f6bcb20f97ed3021f6ad620648b8196ab1693710398
+
+Count = 55
+Nonce = 8d638ef43f56dece910139e9
+Adata = 87ea7b095388de70ac0ed23e86f502400910028a8ab5e3bbb91d05821c0d2d61
+Payload = 7370d9b453936955b9c9d336f4b283237986232de007bf41
+CT = be2f03f6ce1731418a5f53b6f6e467b73992a0c8102d8ffc2d236162688096d80b8733d2afbcd244
+
+Count = 56
+Nonce = f479ea8812b6b2f6ac78fe9d
+Adata = 20c2b8f5d3a65a66ba8a25e2ee339a779a32d45f5db91077efae6cf308feef50
+Payload = 59ff9f7581a781808d36fed378080963f35c00ea5a6e3932
+CT = d127c956349c16e2186f55b72254c677f03c61f1c4ada9e661bb9415b32d6a58f5f7647ed41de685
+
+Count = 57
+Nonce = 423515f7bd592d6a7a240866
+Adata = 19eef6f798fc68086aad1cda6d7976cdcfe6b8af74598032972c939db300d8c1
+Payload = 3c379f90b11c622a765756a15efc8fc3ca7b08b3281945f5
+CT = 15792e01fc17f5294c3405484291082c00a8f46dd9af8ca230ba95c4058501234a1b97543c998e9d
+
+Count = 58
+Nonce = c3f3da69e13c5733039744b1
+Adata = eedf00aab5edefdd6549d37ed44358e11c588c24f141dc5731303fe0bd56b11e
+Payload = 9db6fe9adb8c0fee87cac9a7f01a7ed8a84f0512d09b1834
+CT = 9b6b829ca1dc4e90d4402188632ea3377cbec2ba60f0f072afca1b08b6dd589a17a32d49b6f7135b
+
+Count = 59
+Nonce = 0a57d59f21ead5b6d80cd2ce
+Adata = de5f2d413c98c6ea2a5640a7b1c424aebe75cbc78b06710b5bff8bec6afb5a76
+Payload = 0b5f6389f7c20f4ba326e8f05d373ca27b7ebe59e6d729f0
+CT = 0b704e14bc7d2977d89e0b2e7ed7fe3c9e0f2ea80d2d6165f344f2f1b2218d9b4283fe640a6d315b
+
+[Nlen = 13]
+
+Key = ac87fef3b76e725d66d905625a387e82
+
+Count = 60
+Nonce = 61bf06b9fa5a450d094f3ddcb5
+Adata = 0245484bcd987787fe97fda6c8ffb6e7058d7b8f7064f27514afaac4048767fd
+Payload = 959403e0771c21a416bd03f3898390e90d0a0899f69f9552
+CT = cabf8aa613d5357aa3e70173d43f1f202b628a61d18e8b572eb66bb8213a515aa61e5f0945cd57f4
+
+Count = 61
+Nonce = 2a27257bfaadf23a87df082c57
+Adata = 0001dc666c9daf3560daeaf514270db0b5075d295068e6caf231c1de0e1a9300
+Payload = 6cbbfa6d736fbcc4cf73ab4d7be537420e0e574ee1f2d1b5
+CT = 72d525e6bb312bf2c20b91f41108779789c25720797ebffa4cd9d735f51430275387c565cf1a69bc
+
+Count = 62
+Nonce = b94ac8ed14895c80a91fda8367
+Adata = e1eaf35fb266f243a3fa407cd41815ae6432ad79877bfa59d8f196cbf19bfbb2
+Payload = e6ec561496ce18d96b26d594a47ffad02d68ef25d2d2edb9
+CT = c63500445239bbdf71a8dfe3f8c01061d659cfeb038b825dc89fb5f507f5aeefaa9365f0b18dcb3c
+
+Count = 63
+Nonce = bbae10aa491ac9c668a3ba8d7a
+Adata = 981fc31e64fbad244ba1ef0303ba1e4beef5bacca74f60ffdb9142a25a1ad5a3
+Payload = b9bec3e2adc83620772048d6cbfb6f78e4fad74d754ffbbb
+CT = 9c629c375f014e162895cfc25a972c29839f97407e7c7cca83d0a61d453d596fbc5c2e315d9780bf
+
+Count = 64
+Nonce = e0b10e78e9fb41ee970143e9e3
+Adata = 399b71ecb41f4590abda79045cdf6495f27daaa559c1b34f513b5c4ac105ec10
+Payload = 4b81804d777a59b6a107cf3c99c9d1a35bd8e4ed36596789
+CT = 867799b30558697d6efb4afcfe458cfad8da21139a0b43128e8f8e13b7896b244d0c9aa52ed31a95
+
+Count = 65
+Nonce = 17b61109f5e37754e4e92a28d7
+Adata = 0bc2fdd890c19882640f8d4188b88b9db99cc1934cc3e98a5df08589287968a6
+Payload = 347c1eb4aff917bc0012f005e74caadc93f4f18f2b614ece
+CT = ee19f3120991b67b2389e6f36543d99590f2e6d785c9c8ecc40eb85585cc3b7520a940a4e993327d
+
+Count = 66
+Nonce = db3ca9e80ab761804349379961
+Adata = ce01369d08d37dcda2c899c9fc0d11ccf94a0051b2816a1d6c3ad07fc8dd02d7
+Payload = f0e1af1276d2918be91a191814660bfe735463d3983de1ed
+CT = 0f1b1228729b181772d7cf55ad257fbcb19cd46f7b31a885401358c7b44aea27617b429583103a1a
+
+Count = 67
+Nonce = 1f57959cecbd377374477e33b3
+Adata = de1c7c83ac61e1f99ae99b198f4af5d24f8de60ea98fe637f3a801fab38b2a4b
+Payload = 42a42b84df098ceb43519c4cb86c14c2fafca39346159e13
+CT = 12425453de653d0fe8103013fde1ebf4a8fe18f76f0c9d60e93525fe8048c3b2147a149f12eaecd3
+
+Count = 68
+Nonce = c9db03e2efbab713b0b6404210
+Adata = a2969243b0955402ab45a430fef2ef9e0c025006732bf8e592e3d3884918696a
+Payload = d633a5a3defdde6a68f959ef39a91c6ea6e13ef1a7859d2c
+CT = 5cdc183c32b4c1878eb83e8473a17c55c88e2ad6b944ab1f64ddee42614aa737231207636c114575
+
+Count = 69
+Nonce = 89ed296a3ac03fbfb71422b921
+Adata = 1ffbe1aff0a1e7fa3e68be31a74612a1519b59397e7007ef61fc015f316d55b5
+Payload = bff42516e30c92ed46710013c656600406a48a84c1fa32ce
+CT = e08c1ab4ae7edb5184c30ffb3e74689ea855f50b0e890392f26b130720f75c422fdf66fb174383b5
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT192.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT192.rsp
new file mode 100644
index 0000000000..06e9ff5655
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT192.rsp
@@ -0,0 +1,456 @@
+# CAVS 11.0
+# "CCM-VNT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Tlen = 16
+
+[Nlen = 7]
+
+Key = ceb009aea4454451feadf0e6b36f45555dd04723baa448e8
+
+Count = 0
+Nonce = 764043c49460b7
+Adata = 6e80dd7f1badf3a1c9ab25c75f10bde78c23fa0eb8f9aaa53adefbf4cbf78fe4
+Payload = c8d275f919e17d7fe69c2a1f58939dfe4d403791b5df1310
+CT = 8a0f3d8229e48e7487fd95a28ad392c80b3681d4fbc7bbfd2dd6ef1c45d4ccb723dc074414db506d
+
+Count = 1
+Nonce = 026a0b8b17be95
+Adata = 44caa8ecfaf38e5e773cb0366e1b04aa0b9fac5c34a362310f471960c4a1e1c9
+Payload = 0e52a384cedcdf7f179348de6e7336aa86f8855fbd903cfa
+CT = 3417044bad5fddd9455579123dda4fd342c273a57ff6333dfedf191496d88cbe17c6271b65096e66
+
+Count = 2
+Nonce = ea09fbe5da0fa4
+Adata = 1d9799f2bb0f7ab57fe3de27949ff64066131c81bfee172b308f9bb0b3171067
+Payload = 469ff9698cfc96b581d7115c822e4363d7355ec5daed2eae
+CT = 1dae7cc16f1b469290902cfad47b959784b4d6f48a79e690d47e30b635d10d1663477d61d7ffb55d
+
+Count = 3
+Nonce = 8d27bcbf9ebfd3
+Adata = a7070b85b7add9193c9dcd2e6c03f6e7ecc52ffe9e099866baf7472f20c03aab
+Payload = 225651d072dc9d93762dd79691ac2b6ddba00ec1252d69eb
+CT = 5da819adefbf794612eb458519debcd524c283763eb3d7252eca8766bdf0db6bb2dcc793e1749c21
+
+Count = 4
+Nonce = 13f560187b6077
+Adata = c4ab4244db75f8256e55c5b613a07b11c963c3cc24f66128aad4ba8b7ca99331
+Payload = a38231af405dc7b70c8dbc8cb84e6be8a0dc2e95fddc2ce8
+CT = 3aedcf8347aa23fd3325ce08b6b00462536baed69968a753feab6761c55431bb5668e1f5b7505e89
+
+Count = 5
+Nonce = 61e0e28bf344a9
+Adata = 5f998952de70449ad46428f2ff8a01c5af43c0107a1bcc6930f19d4112598666
+Payload = db21b37e875d7709a02239ce6ea529cf37255d5b617c153d
+CT = b8f5fed39c723d7643d6dcf2efd3bbd1ba0da1ec901305fd64b2302ace4f66216ca8b4d776197692
+
+Count = 6
+Nonce = f6be4aad63d33a
+Adata = 18339be863fb8a887d04ae9ff3b4a7db095075cd5d113a9ec87b41fe85ea405e
+Payload = e53101e6eabcda32c13d7b1dd1d88e7c2ca3ddc2064f64c6
+CT = b758858ab60e1630a0883d4d330119a593729a3015c42525effb985b9c2dd9ec954bd25d9c464c67
+
+Count = 7
+Nonce = 2c1c59aa0d8eff
+Adata = d44af86b89fda8448a9b2fcae20ea156dd8738c8251699c02b785811c830bf72
+Payload = 1fd7188a43dee7b059420e8634d71d2c0658f6d0d308dc73
+CT = d046f845a67800a5a58f461e5a8641e8fc9b4c53b32e61d172adafffbacb297d67f6b5c02b982e04
+
+Count = 8
+Nonce = 48e4598edd191e
+Adata = 61588bdc980ea2310e87dec4c651e9a55c27e3858b6505cbf3bf85e51931badc
+Payload = c25868f390af5e59c035cb5830e018c62c5b96bd35b764f1
+CT = 0ece161bd77b7f969b3b20c818769a98c178d84524544664500ff4cfe66ade1832babc019778acc3
+
+Count = 9
+Nonce = 6d576ce3c5fcb5
+Adata = 92c598cb5ca2926c11f67c3b3cf25493d77606fa60d7290430e0e975091644a6
+Payload = bcd97479db934357a163a9e5f5a85999ca987f8243d8017b
+CT = bee185e11b3d42bac846b9d92c70a078aebfa630ab763840391031b3a22b2adeb9791ee35765c8cc
+
+[Nlen = 8]
+
+Key = 1dd56442fa09a42890b1b4274b950770ea8beea2e048193d
+
+Count = 10
+Nonce = ad749d596d88a4b4
+Adata = c67219909828adef64422286008e1e306867a1c0b3da95444507a68b45c953e4
+Payload = bd92d6744cde446fc8621625658fc4bc00dcb97f06195ad7
+CT = 076cffd0ca978fe2bad411ced45a090abafb22a99896f6a75a1969276aa2b0cdb37ccaf2845dbf6e
+
+Count = 11
+Nonce = b1dc81d116d94f5e
+Adata = aa4b71906b6642f10f66c2391ec157c7cde97eb322db10045af4c5248807f691
+Payload = 9aa6dbe1cd3eb98d330c937d31ef93bee8938b6c5cfd38de
+CT = 720f6876ac91665f20147483f0655fdbe21963a01e36f1daa67e36d7cc8d54cfec0762514475127b
+
+Count = 12
+Nonce = e758738df5c89af3
+Adata = 5715fa238f432c926e62dd93708d0e3145428e0ed45e1efa8148d2c4ab6cba50
+Payload = ce80b99039a16e69018d1e3c239dd1bf06e94a78b0b1df37
+CT = acdf7ba3edca1563727ed85cabf085c2f0c8f27556c3c064ef50d85bc3ade6a773d956b2660ac367
+
+Count = 13
+Nonce = d586c4c67d535476
+Adata = 1e8dc63c6c54a540b6b02067ba7c719221cf289fa3897299722c9a2bd6eed05b
+Payload = 2f88305117f9a5d807d54b7e95ecfeb7327e52d9acac352f
+CT = e42b86e619be1a38973c934babeb4688243a9012c85d643d81e024aaf0a62b353f9bed36681288d2
+
+Count = 14
+Nonce = 77e83758f68d272b
+Adata = 25c80edef3d5bd8b049fa731215b80ca2ee9ee6fb051326e8c6d0b9e11e3d7ef
+Payload = 92e47b82b728d639777d5d5843de2a5c364956cb4b21cabd
+CT = 1b9177f5b76403cb8c690b39c3dd22b55da35cebccb9b64e05fe32f796f0b4a75a459fce6c7d740c
+
+Count = 15
+Nonce = 311dc245549206cd
+Adata = 87767f13bb4904d0df0d64eb22c9ddb65e81b5739baad86ad5e2c239ffde9f6c
+Payload = 8691c0301a216a5f3ed9123886d100309bd85630d6b845f5
+CT = f39fe3620a03b37a4bf457909e0770447b498ad2a2f0f9d7b75f9e4239e43bbf93066897e60f6fbe
+
+Count = 16
+Nonce = 2a17b70f10e120c0
+Adata = 981fc31e64fbad244ba1ef0303ba1e4beef5bacca74f60ffdb9142a25a1ad5a3
+Payload = b9bec3e2adc83620772048d6cbfb6f78e4fad74d754ffbbb
+CT = 92187955ee1ae702ef01a385537119b2bd4545402e8b2384a0c069a2439a2d8843302c6a9999e658
+
+Count = 17
+Nonce = e0b10e78e9fb41ee
+Adata = 9d072b8a3f1a496b2be6728a38b94a4f44c9be40c8793b69afd81d01696a6b4a
+Payload = cea28e7cd0eff0c5eafeec908d4aa8ba303e72ada33db087
+CT = c605e48f2e66e8e0a92471e466981ae5e31db3e4ad80b09f5005b06d15f63f2f015cfe447828da09
+
+Count = 18
+Nonce = 02d72dde23f9772c
+Adata = 2dc44c39940e2d9c94d2dbe40bbf5cca5efb4d4b250a31aa24f208b87e9c2453
+Payload = 809343e986f6ff47f54d4cac22ed39babd12271d4c7edb58
+CT = 0bb59581f22f6b15de76c0066645495a5c19e44381c349263ed92ebb789c314a89c83542b15ed694
+
+Count = 19
+Nonce = 28c4d6de3e2ce51b
+Adata = 913a8eda924589d3206ce0a951fef93668c6c0c454824b217997bff6b3026d54
+Payload = a19f65ffdafd6ad5ee43570f7e168f94a8b4a7b7402ac80b
+CT = f0c91a29f1222b906550ef5c7c0944c5c4236cb6c31122cfada8e796f2ce7f9449f42de504873868
+
+[Nlen = 9]
+
+Key = 8cc622645065c72d0d2aca75802cf1bbbd81096721627c08
+
+Count = 20
+Nonce = cd84acbe9abb6a990a
+Adata = 447b6f36acdad2d1cfd6e9a92f4055ad90142e61f4a19927caea9dbe634d3208
+Payload = 597b3614ff9cd567afd1aad4e5f52cc3fa4ca32b9b213c55
+CT = 2d7fb83e6621eed9073e0386d032c6941bef37b2cf36a4c6c5e36222d17c6fb0631c3f560a3ce4a4
+
+Count = 21
+Nonce = 1fc7a43ed124745d04
+Adata = c892b095173076a40e24522297be27fd3a765c8d417f24c71a9f03b3fe3d8e20
+Payload = 415cd8312dd20a1c26f4b90d98104cdfbe06739466fc0aa5
+CT = 7bebd6f55f15ae57ab73f92f7be6ff37ddd99740e988f01a7a2a13c22df4a156e6d6063235452c85
+
+Count = 22
+Nonce = 19ff5e7c1f2c594abc
+Adata = effcea4e4dbc57410426b39fcf51c9daecd9d310888590d77827973a29c4ebff
+Payload = 97fd2c259a4e672e9555a9a5b98f4c0ec8c4c49c7ade26a4
+CT = a460674c2f358762e97dfc958d90973e1e419dbc6a832e987579b2c4a6bcf0356f48cf8959cfa54a
+
+Count = 23
+Nonce = 64d9bd368ac2357cf2
+Adata = 62c5a16f946b4312517f67c80afe2614c822e3a01b87dc81538c00bbf3fc0108
+Payload = b6ada12f7a28211e9d2c07cbb3d39fa77aadc077b34c46f9
+CT = 8fb5e0954388b9b58519482962487e9b0768f0cee08afe9a92be2b06a0ecd2d00877abded7d9634c
+
+Count = 24
+Nonce = b4aaf2cd93efc0ce93
+Adata = 79d8841ab83279724ce35e1a8abd4e158168dcf388ab4c3d1ae70413e4e43d14
+Payload = dd42449da4c95e858b796085b6b5b3b5eef484dbf3c2bc8b
+CT = 893f86e29972928c1f3c3e25c73947c8d677814bca7fff2cf8d301ceace678f9bf91fc361dff5812
+
+Count = 25
+Nonce = 132f3e19e12f462a74
+Adata = 176cc5a280f6171d00e247edacc81f05c1b9faa87fc831163ac9d76aae59a6c3
+Payload = 8ea05a5033ab8b009664fa2800c24e217488ce6888cad147
+CT = 4771d210ea678dbfab96e320e9c44b68f47cb05b01826ccf42ca4f4ccf986eb6a6b85b99db2fcd93
+
+Count = 26
+Nonce = de709ba64cb75704c0
+Adata = 0cf8e9ab95766b6fa85e88d86e4f349a17c0d90509939e343eede988e7462255
+Payload = 51dd9fda9549f25dd868245a6a54b8d59346d2f336adf9af
+CT = fccc3e44afa6bd2fbcfc5c834db63dc9d152c04c0dc0b43d393162252ae91ca46fb8e8338cbeb75d
+
+Count = 27
+Nonce = b11b4c1b7a26387265
+Adata = 14ed867cc909c0619f366918a7d5ae25279fb137e1dee7fd98ddbe3bd19d841d
+Payload = e35ea4a16e274fcab457fd4dc7886c3d81fc668c19e0f374
+CT = dcca8aa2eab8ac3f5db9cd9560ae0758d7df40d7d868d1f71f498ea6ec8251a6d149c7ca38b25fe4
+
+Count = 28
+Nonce = 20d03227a7fcaef1ce
+Adata = c5c15245e641687d0ca9e913406acd2de3f21fbaf2dc5e4e8963222da61d02a6
+Payload = 6775e5faffd0b13e78da70a789042245d5ef31eab5245380
+CT = 4bb8ed2207f36f40f62d3a2c90f8e3bd8f589059b69037118ce3ab864545ea81943ef0ea9489d223
+
+Count = 29
+Nonce = 267f76b9ec0f5e7c6f
+Adata = 2b421be47d07dcb12a0706f7490d05024fce8f433079e18ec78f4c8678f5f155
+Payload = 9330bb23428ab45f573923e977db74882282cbe1371da68e
+CT = c6ae24f82ac5cf9c18a2d98e610027eb2566a1ccfcf99945655e14c7bc8be97ea47388cb7b18bcf0
+
+[Nlen = 10]
+
+Key = ab72eef2aba30205c986e2052d6e2c67881d24ae5fceaa8f
+
+Count = 30
+Nonce = d7a46e726ed43f1580eb
+Adata = baa86f14271b2be7dbb37ddc7c95ce4857e57aa94624d594d7bd6ceeaada8d5f
+Payload = 2a794b84fc9e4a7e6d70a82b5141fd132177a86b4e8fc13a
+CT = 2d7f76464417613bb61d3657481346b74fc9d6abc6a3babd39365dce86859cd82395d11bfc8cf188
+
+Count = 31
+Nonce = d0afcbc1b2524a4a4553
+Adata = 7c267223047af946b06f6a45ffde4a5ec49c28b81ca22da4a36bf523e89e9da8
+Payload = bfc5ce1316ccdbcd8ac62484e7656c87947ff98cbba8e1e9
+CT = 4772c121367d0e8d3edade883342395f3ea065fe7dd7be8c8355b915ca2633fd557ca7ed41e00926
+
+Count = 32
+Nonce = 6eecffd227e8d5349523
+Adata = df7736560b1a13aa8e536500ea6cdb9a6757309aadf25a6a9189055a309c3f8b
+Payload = 19eef017100dc82f26ed0815c55c122e0b1587302894c391
+CT = e2864c6e12ac089daaa1e94af4b2ed04060d7ef65d2f72f0e7d017514d498f1f3c07d650afde8293
+
+Count = 33
+Nonce = a67c0675753f725a8fd4
+Adata = 7dd546397a9a0129861fb6815d419a307f90d259d55f3503961754126cd1b776
+Payload = 80f1f1ea46c92d28f2d60eab39ce056a4aefe63fa688538e
+CT = 882c687c03eaaad9d7f591649e736f0c1c78f95e40d40cd77499a8544bc2a8fe95f55fefc7316f8d
+
+Count = 34
+Nonce = eb83928f0d5f7aa3a74f
+Adata = 060cd3e4aecdb03837dfa9f544318c0a16cdc37fa2a3135be7888ac67e7eb26b
+Payload = 81e9174e9472777b6b184707108c01d6ea6b5d108ec3c6c8
+CT = 243cfa0a0a36a4c20333968910e6f52acc04c6f74e704180623f3a13fc13db958cbac49f7421d6af
+
+Count = 35
+Nonce = 5757abe01f7a1183fdcf
+Adata = 744629263041f0eccfce4a1ebcc18c4c984010f9241d35966263a8b2f72ee26b
+Payload = 991049f26b529af8b0bee0cc83989cf817d248254182f332
+CT = b20469b5f33f0996e8de869ad10ce09924a0bdd7b67a89a09c447a3132fbe5213133650000d50b06
+
+Count = 36
+Nonce = d9adfc5b44ad7aa94b05
+Adata = aa6a5448c6ec87be75eca35725ad2e902dbccf840d25b2bdf7e62e4a8fa4a511
+Payload = 14682301a99bf680805d1ffe62e1506d48cee8c51ef1d255
+CT = 9b44efa185b0c10325bb4c3c0815e6a6e46eea366b9a416b5ae554cb440eadd875657fd5cecc214a
+
+Count = 37
+Nonce = dc3ca30782c9c0a7fe89
+Adata = e788c98ae85b11b3ae884eed6f3b8f5bcf5ab1b7b20ad3f44f760b2287cc5793
+Payload = f9cb86f24536931a1b095b426a07e4621c000cf09b472bf8
+CT = 463f9124d1cc387a0f8b971d1e2da448f0efffc3956ebb2af8312986315522081f0989838ef0429b
+
+Count = 38
+Nonce = 9523f53f92b6e4ba86e5
+Adata = c3b123ccc916d26a2e6a8b5e30041ad69a944217e9b402b7acc0170c31e8c2e4
+Payload = b9bdcac80f64175836ab51bb1a1bee5ffe3a6b9b71afe3ef
+CT = c356b5a78cebd123808fb740754dc47a8ec7c9448bfacf39768e94f062e86129cc9210dfcd3e6128
+
+Count = 39
+Nonce = 16bdf18c09d60f3a2a32
+Adata = eedd0796f23612749e9fd282c864f3118d0683409d3bef1fda352e1422273c7e
+Payload = cc96133e473d197be1bafdfc1a21d58e57d0d89b2ba1c3ff
+CT = f9d78e9e3a41b3bcbfe756385a3715776eb84bb7d8d15432978757883f07802b25e9a5b15c43b451
+
+[Nlen = 11]
+
+Key = af84c6f302c59aeee6d5728ed5da2e3c64a5a781c52c4d1b
+
+Count = 40
+Nonce = df990c42a268950677c433
+Adata = a6ab5d78427f297a4b7e21f1091ff3a5b20caa3fe1cbcb09459d9df596a6c8e1
+Payload = 6db41aeb5f7c24df8929dbc30483b3c7934b3bd1cdce5bb9
+CT = 8c9328258bf71970d33e23a3ff81cc1c9cbe196a1294264bfd6a7255e4801963bb30a63de3fc5b82
+
+Count = 41
+Nonce = b7ea72641bbe2dca6d85e7
+Adata = 4e0f2ddf183281ec131693bdcea3fc9743733c07a486a42d5737735b3f6e3fdf
+Payload = 726844e41b1e4d883024b32fee0dcea38c889cb328885b7c
+CT = 9a133e4582c2ebc445862a9c6f2f4e39223c84081e322c8f262de30da6ef505fe640c53d765f672c
+
+Count = 42
+Nonce = 446fee1e75e79c0dfc9ddc
+Adata = 42b598eaee271e06d9e98dd94152b28ef10f506d65bd660b2fb8b1be9a2d7254
+Payload = 0cdcf348ecc9c3588001802c2106fb64be9c301adcc66e73
+CT = 0c2657b0482b6ca92e1b1c8fdf75eae3b0cd3af205e9bca396ecb1e46beb16000d585e1d9559ee22
+
+Count = 43
+Nonce = 2e6e34070caf1b8820ed39
+Adata = 8bd1ef3a1831fcc8919d736fb23111ca3ef4cccaf20264fab8eb3b071e56667f
+Payload = ca0860cc1e96506c2beb25b53d2947fbab634f0372afc8ba
+CT = 19e4774030e43e6853ab5bf176ba9c4b59f29f285977e3c15198cbe3e34c884c3f56a732974aa1d6
+
+Count = 44
+Nonce = 428542ecfb94a745980aa6
+Adata = 8efe01716b9018084e2ea7616f85b7333d945c0c970f8cdd400130b98db67cda
+Payload = bc6b59120ba2845b0e41f65a55e2ef1c45a81485c926c14c
+CT = cb48b0af6fad251d409d14ce0fbfae9cd9c40bf4a0c1e2b7e7cec415030997e1ac5db974b617b5a7
+
+Count = 45
+Nonce = eff703e6d72ddd23ff52d9
+Adata = d7fc74035e66709d2590b7bb3276245dd43824c9896fbd801ec1d07018b39b6b
+Payload = 1a5432e8085511ddac1be91be3e2945f85f0cdcc3a1c9f8d
+CT = c0a00cbaec65b7ca525fb26e80ee0cd18c7ef47c39c704833e59bfecf263bfdb24686627fd95e120
+
+Count = 46
+Nonce = 6a652ce21334a40a259dcf
+Adata = 5d24d80f22afe713c4076c200c1bab36917907fde7b6d34e141066f543526db6
+Payload = eb8f1988cb405041bf48d138ad41da7ef364d4ac59a9e324
+CT = d4f23166c09a15466c7e0e2b30627ee5a84f22d7e6135b4a0652b67d559a84b4a915ca6a420fd300
+
+Count = 47
+Nonce = 9382e12d447c0ca23cc9c3
+Adata = 239129eb760f8a770410c160e4e13a6b9497077c3e463b65397393fcd3cb5c70
+Payload = b40e80564263c7f450c53ef84df67247d72e8a04dbb284bc
+CT = 6de2ba26caa80874814816154784912c55e3d6da83488e7250f5a52f82211542b4e2661cf870c80c
+
+Count = 48
+Nonce = 2c3a4148cbb02504a2483f
+Adata = 33c3bdbf185b580353de79e51e675b03b31e195f19ba1f063d44def0441dc528
+Payload = 60a31736d99c3dcf25b349f6110e1c152b93506e85a01e67
+CT = 4d5e705d08f3ed1ca6f1caa74b46e4b1eee18a0783686f207de16aaa41d06bc071657dacf14da754
+
+Count = 49
+Nonce = 691cdf6fe9ecc2154d0101
+Adata = dc096596644c4e09c44078b86e5e0887c45094042eb0d74a6a13aa2524463076
+Payload = 77e6441ee017a93dd876ff2c7980540c77ee15edb0f23933
+CT = 24cecc81c8ac7ca9906372dc5263f2220b4dd162f1e08283f07f23e65475a20fd96e45c6c695cd83
+
+[Nlen = 12]
+
+Key = d49b255aed8be1c02eb6d8ae2bac6dcd7901f1f61df3bbf5
+
+Count = 50
+Nonce = 1af29e721c98e81fb6286370
+Adata = 64f8a0eee5487a4958a489ed35f1327e2096542c1bdb2134fb942ca91804c274
+Payload = 062eafb0cd09d26e65108c0f56fcc7a305f31c34e0f3a24c
+CT = 721344e2fd05d2ee50713531052d75e4071103ab0436f65f0af2a663da51bac626c9f4128ba5ec0b
+
+Count = 51
+Nonce = ca650ed993c4010c1b0bd1f2
+Adata = 4efbd225553b541c3f53cabe8a1ac03845b0e846c8616b3ea2cc7d50d344340c
+Payload = fc375d984fa13af4a5a7516f3434365cd9473cd316e8964c
+CT = 5b300c718d5a64f537f6cbb4d212d0f903b547ab4b21af56ef7662525021c5777c2d74ea239a4c44
+
+Count = 52
+Nonce = 318adeb8d8df47878ca59117
+Adata = feccf08d8c3a9be9a2c0f93f888e486b0076e2e9e2fd068c04b2db735cbeb23a
+Payload = 610a52216f47a544ec562117e0741e5f8b2e02bc9bc9122e
+CT = 83f14f6ba09a6e6b50f0d94d7d79376561f891f9a6162d0f8925c37cc35c1c8530b0be4817814a8e
+
+Count = 53
+Nonce = b4cadb5f9cb66415c3a3b714
+Adata = c4384069e09a3d4de2c94e7e6055d8a00394e268398d6ea32914097aec37a1f4
+Payload = 22bade59214fa4b933cb5e3dc5f096e239af4c2f44f582b0
+CT = 2296e3f8a2245224d274f1b90ed1287cbeeb464c70a89ee475ecb546efb8872a3f8b0281b3901752
+
+Count = 54
+Nonce = 72e6cebdaf88205c4e744286
+Adata = feaf010f462ad40a38eefb788b648e1cc292cd4bb08ebeff3c39182862296042
+Payload = 30655a6b5a5965db992e7248d24141055e988d726abb8e72
+CT = 69b27f2bbaa61c4f24e1c25e0779147fef79ec1582486b4651cffa571570618e2ada3376bd9f3e5f
+
+Count = 55
+Nonce = d8030fb31eca2c43f3f5eb88
+Adata = 66704365ddd0145febeb33f68b228a3f09e1e5a4b68149e6e06d886301841295
+Payload = 9d014a02507a6f266bd1ace21b55ab8b73983ff503bb9adb
+CT = 233a883650538ab8c0da30b90527f880fcad5b16bd435e762beeeea7a638c717e63764b3a5118a0c
+
+Count = 56
+Nonce = 58038cc35ad3dcd75195e125
+Adata = 3da7a757e942409a3b39ccdc0669ce6401f7e133c07c4c42e366d70a8e9bdd49
+Payload = eccfd817fa5e3a0146967fae13fc2471ee3944cee37969f4
+CT = 415a36872a04f5b4b5372f63394ab9fb353e0eb9b430450133a87fa29e5fbfa9bc0430b0cac00b7e
+
+Count = 57
+Nonce = acd82ae31bfcabd90af5af45
+Adata = ce22126f01bde16249c47102b4da68ad3edebcd4a16c24a16ea7ccdd5d364d10
+Payload = 9d2126d34963d3ba12cd841bd321036cb82cfb78f2a6535f
+CT = 88a5b889e6fd74fc15336e23374b430988416c7e6b6e7248b336cbbeb64fbebf2e7076a98ecf5bbe
+
+Count = 58
+Nonce = d24457d567fd0a65fdabf219
+Adata = 0091d39f3478d2c59bf874b96db9ce0f7e8b85a9b805e07dc96b219819d51663
+Payload = 6da3ac85505e93c4f391ea367a9e15fa9b388ef7ae2693c1
+CT = 7039a8a49cfa6402b4ba3b840e69200c13ac4a3eb1c709a30ea909047af4998c660afbaf346ed65b
+
+Count = 59
+Nonce = 50c59ca54eb64575b82b13c6
+Adata = 5e4e42cbf172853c351d597c7d6d38b1a9cbb7ac92c00863a80ac4a2d9f0e7fd
+Payload = 25b2ba0a937b71f3ee68e7172cf2c4524b662efcd08ce2b3
+CT = e95fc44287ce39c5ad6b91c88582563fa68a9e304094deb8b193dd767f17783f0b51ac0fb7323301
+
+[Nlen = 13]
+
+Key = 36ad1e3fb630d1b1fbccfd685f44edd8984427b78deae7a9
+
+Count = 60
+Nonce = 3af625df8be9d7685a842f260e
+Adata = 308443033ecd4a814475672b814b7c6d813d0ec2a0caeecbcaba18a2840cdb6c
+Payload = 8b9db1c8f9b4892a5654c85467bcffa2e15e28392c938952
+CT = 6bc6890fee299c712fb8d9df9c141f24ee1572b8f15112c2f8c99ccf2d82788cf613a61d60dae458
+
+Count = 61
+Nonce = 24eaeaa437649e61b706942b8d
+Adata = fff75462f96157d9554bddb6aac156fefd88fd4a90a8536dfc28cc577f19c83a
+Payload = 49ff4ff85f7407ca383cfa4fd7177adb4dab26e642c8186d
+CT = 3647fae50c588d792442f43a20125e77ab5db3c469391d24d0a421bbbc002eb9ac9ad01f625f824b
+
+Count = 62
+Nonce = 7325932d6694aaf61a8204c172
+Adata = be20ceb8ca14e9bef7158b280a26bcac763da79cd0eba9b1833ea808c5e7a66a
+Payload = 2861494eb40b9d964d339797c1b6aac63c6674187768957c
+CT = 286dc74001e2a6000a23db164f4b2912de4afcf1df8c3aa5ee32a7ffd4e7bc303d3482fbac431828
+
+Count = 63
+Nonce = 61c9949df5853e42599e5ee0c7
+Adata = 243d09ceb16755cb58d62065df84890b840ad9b7eec1132c6427cd7c3d843fcc
+Payload = 943a49073db6ae94a88844ed895f8fd99ed25c3f42a2f78c
+CT = d3c56bd265a2cb0811dd218f248800ceade4f02b5403b9635eb30cbec49cbb51c41cd5032b7fd759
+
+Count = 64
+Nonce = 07b6c18dd3b0fd9e8ff026a436
+Adata = e85f141c3d1af7727fcdb00f8e2c34e42a436d04ac5b8ca9f321a178a2056806
+Payload = a18b0a4618063c0519818d113b8e5435aaf153f664058f1b
+CT = 69f933a2a5e774e8d013cbf78c6ab0b73e6ca323d0c52691acb5cf2631987d3d963349b035324aac
+
+Count = 65
+Nonce = 0c075df70630dec2fe81834945
+Adata = f3f5c5ffbfe8247bc0c33c793652f749fe91b6dd141cf0db56e71cef8a2fd266
+Payload = ddc4bac4115e8cb06d29d22e400674dbc615a667f933603d
+CT = 26bdd25c9f204fc7520d26c161464c28fb35e395b295b3db4e239d33283d18415b54c2aad4bde354
+
+Count = 66
+Nonce = 0c2d20375057fcd4241d290f6a
+Adata = 70ff1b9ff8ec08fdb18b0e7dbe01127ed0cfe0b0a449ca2ace4992b7b6248b71
+Payload = dacbdf1979e000d52b573e74800761b30acc26681f372acd
+CT = 6a642c389433a3464fc64783ae6a14a9a45f0998b56a5b9162d7e0320dc930df3640a786d7ea9ae4
+
+Count = 67
+Nonce = ea0801cb3dab853750a922dd25
+Adata = d83360d0896e022bf014bd33710ab212ddedda6d95a54996f33db304e5f12f01
+Payload = 46cc5653bbd8300dfb0df6d0af3fb7c7639a830bdc9f68c7
+CT = f1b0728920351d9edfdbe7df360b21f6cc5b628dcf43a3f10d06b4a545609a2128a95d4d73471559
+
+Count = 68
+Nonce = 97e6de379c90fccf3fa8f27013
+Adata = 539f8eb802bfecaa4fb5b19debbf3d4847db9c4e0473a308ab3f3c859e68fecf
+Payload = 8b013f52a828905013f250fb9c006a173f6c66a64b5ba317
+CT = 556a439bc979dac1cfea8c5b64aa78547f52a62896c19893f3512baf72cd79ba9301194be204bcc0
+
+Count = 69
+Nonce = e832b6330d3e5e190598cb9c61
+Adata = 093be516277e8b197ba5e9c85a831529befff0f3971510ab611dfe0dfb50a2ad
+Payload = 635d2d7894bb816f154210946a369df37ea492993ba23af9
+CT = d8e19c67e5aa7f14a16ecaaac414a2b15a15bb5f966932e6b0bfe9a5857fd36df94aeadda7f83a79
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT256.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT256.rsp
new file mode 100644
index 0000000000..2817684910
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT256.rsp
@@ -0,0 +1,456 @@
+# CAVS 11.0
+# "CCM-VNT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Tlen = 16
+
+[Nlen = 7]
+
+Key = 553521a765ab0c3fd203654e9916330e189bdf951feee9b44b10da208fee7acf
+
+Count = 0
+Nonce = aaa23f101647d8
+Adata = a355d4c611812e5f9258d7188b3df8851477094ffc2af2cf0c8670db903fbbe0
+Payload = 644eb34b9a126e437b5e015eea141ca1a88020f2d5d6cc2c
+CT = 27ed90668174ebf8241a3c74b35e1246b6617e4123578f153bdb67062a13ef4e986f5bb3d0bb4307
+
+Count = 1
+Nonce = 195c0b84baacc8
+Adata = c7d9557b2ed415652ce6faa8cff5217ac803530ec902890b31eaaf3eeb0aa98b
+Payload = fe012718481b2c4e1d7f9a7685e3daac43ccf22cad0df900
+CT = 893af0f130f1317de9f217234274b0c04fcc202cea9a0df882c00b5b463654adbf82888099a7d258
+
+Count = 2
+Nonce = 363e0e921c6f11
+Adata = 805678936d4e94746ab4818dc5f50c41e32cf32e7a8aafb300fb91af6406108c
+Payload = 7e7e33e1a07d4e8fde2f33304f21cb564d146860ccfeb49f
+CT = 645cdd11a1c232815ce1e07ca3ea83f372eba46cedafddd980adf2762a1617adfd4d8356bb48aa8a
+
+Count = 3
+Nonce = e323cc866af462
+Adata = 163c747f3ba4ffd68af87f2475f48f2714659a2ec43b9ed115e02fe0e3c8be99
+Payload = 2bfc76f3b108ba3118b07433c4d3d5f41564d22547c12822
+CT = 0db04c6b068e73e3c4d71059bdeee3d27622f99dfd07d868fb9c02753c57fec7e1a5fa8f3860501b
+
+Count = 4
+Nonce = 03ae777078b95d
+Adata = f1dacf9062dff9a6a3d0498f9d058782f891475684196bf2d8e7e905393acff7
+Payload = 38c4275a5f605fd1d99517e13deebf0c9794ef586070fa9a
+CT = df8f524872b5f06f3f219ba76524990b466409894930d7e0d104990e598eabd88cc8342ac16424b5
+
+Count = 5
+Nonce = 1c6c351d4fe9be
+Adata = 14285e97cc3cae452e1a52e2fa0bbe24df96abf2faf6b9779acc59764612eadd
+Payload = 9e2220f3c17532e1ce0d6f562b049fcef35bcaf9a7e196be
+CT = c274b28228a6b13b670c325080f88d188d40d78d385481eae004894b1861db5d2d8ae98ed8926c1e
+
+Count = 6
+Nonce = a121dc27479397
+Adata = 359421e9f78cc4a31f4f019977d7fd29780524e20288798c50002a682a6368b9
+Payload = d42b16b32e77637724144eaddb21ca8d7db4e7f73acbf707
+CT = 56e3e3e59e978161355e7d8573dc0657db400ca0b083dae8ed2ac2cb63e1b9d7dc598634198fe4fc
+
+Count = 7
+Nonce = b1f0e26b60bf1d
+Adata = 2ab4239fffd13762fb5391f5a4760d12d96ea12666a793b4d651e9f4891c22c1
+Payload = 9a2851083ad4e7b915bb0526bb4054e4c0b4adf8626edc90
+CT = 5b2e0215523ff37f0df46e84f996fc9fc779986c766fa51595b8a23ee377d5c2850f4ed95a385253
+
+Count = 8
+Nonce = 50412c6444bcf9
+Adata = 09cdcaa87ddf8bbe6db8411d14bb9064e4a121286cc8a6e97fce1844935f436b
+Payload = b28a5bc814e7f71ae94586b58281ff05a71191c92e45db74
+CT = 05cbc32a6ca797684636dedd16ce65a1eed69bcab1b1bdbd514ef5cbf9991a919fb4974d55506ce1
+
+Count = 9
+Nonce = 225557b0faca3d
+Adata = 21611da060fa90cf7fd68b721caf303307a56e56453326495b628c7dc93cd175
+Payload = e831b739e8eb9f787f63c0bb071ddcc9f44cab8d5b447d23
+CT = a97e0879407eb3b7f93118ca73f17eb34e9f4baf43b07be2e8a3f7b848054cb235e1b58d6a12c5cb
+
+[Nlen = 8]
+
+Key = 472bf7946bce1d3c6f168f4475e5bb3a67d5df2fa01e64bce8bb6e43a6c8b177
+
+Count = 10
+Nonce = 790134a8db83f2da
+Adata = a7a86a4407b7ecebc89434baa65ef173e88bd2dad9899b717ca578867c2d916f
+Payload = 59eb45bbbeb054b0b97334d53580ce03f699ac2a7e490143
+CT = db4961070f528ccd1a5a0681ee4d0ce3515fb890bccedc2dbc00b1d8b2bc393a8d09e87af7811f55
+
+Count = 11
+Nonce = fb2441d1594a488a
+Adata = 0875020959ed969cfb38636d1d5aabce9658b00171a7614ea9e5395331c7659c
+Payload = 451101250ec6f26652249d59dc974b7361d571a8101cdfd3
+CT = 1bca7b0d35a68c0ffc568ffc8221cca738b67b95e3ab26efee21c5738d1f7fddf3030d004a702704
+
+Count = 12
+Nonce = 0855263860043207
+Adata = c7fc24863c33f7e8cf97b337918495d52d864ac570c99cbb09d151758d6b504e
+Payload = 61fcd7ef9bf151b9d8a81dc1ba4f82c45e9c2e4784627acd
+CT = 9b939b6b188e1d0fe016f366fb01eb79a99ef7b1b57c6f7ab223454c57c714d96681cd4d55615afd
+
+Count = 13
+Nonce = 415cd251a5e36943
+Adata = 1a393c7e85fb286709f4eb50f09640e1d65ec1135cb4443820136b3cec69772a
+Payload = 66ae08d494dc9df9b7f8f53199fa37d0c88885458b168c57
+CT = 1731e260ae31b8068ad1099313b167d9e6cbe49f471da61a9af96d3ce4ea94213b60cb69d92050e6
+
+Count = 14
+Nonce = d95bd65242bb2265
+Adata = d0e20e1358be5cc1c45c1cf02c82d0a6d0824cfcb65774cf95f047b9f2cc1d3f
+Payload = 312c3791c64d79205a11eebfc14b2d7a6b00391793c9559b
+CT = c3fbe558ff9ea83ed86b7d66503ee38eee94e4a41fd53f0f627a352d056712e0d44404c61712e2ab
+
+Count = 15
+Nonce = 3f0bf0141dd3ace0
+Adata = 9dd4ed18209dd6cdf19cc76fee443827e7331aaf020960c15d7bbed0f6a3b1f7
+Payload = 08354480047eee3beeb5ab165da17d23f2f1a4ad98720611
+CT = 2db9d2c54134d37ebefcecb9e2076034b975677fde58ef6032645a322fa9bc8aace600f942a84db4
+
+Count = 16
+Nonce = 3fd8b3a3ff563a42
+Adata = e58327efebad3276a7cd1b1ccb56db0caddd02a303cd9fc7ea5c607a2ebefaae
+Payload = d1abd89351384e1a3c3366f77c3175f6390801554d7cd783
+CT = be284dcb357ae99ada7cc891730320ebb32ca627eb8c80623957a2a5b6164218fc83e12c42d5c532
+
+Count = 17
+Nonce = 14db1ffc1c87117f
+Adata = 6c2b091433833a0ed915354dcb70d982095b614dc51a95a22cec417184d8e786
+Payload = 0594307491f157821e63f50c94034f9284f095d5b897153c
+CT = a114c84a10071e359bba2b2ba4ea67f893e27e6ea880aa4b2cf16ce68a93f8839245baebb2278300
+
+Count = 18
+Nonce = 40b0f74ff27a3fc8
+Adata = 3b9e1f4e9b57a6dfb5e0ca7ef601fc6af30a1f8650228e51e0dc61180d0bec6b
+Payload = fc8b7dbceef6b0ffcbade789e09303044042cd671607e819
+CT = d00ef56074a8213740af8b8f974f778db560ac365d6ce916b8d191130e864bcfcd1dec94a1aaeaef
+
+Count = 19
+Nonce = 96cbe9cd19351359
+Adata = cf498fd042f9a07503e490cec4873d4df91162cfde60bd2cbb2b710c6681a9fd
+Payload = 315e81c9ce556dcf97a5b68503fd2228a7a6a174a15cd618
+CT = 7383c2de08bce3f0b7e504dc03d062f44396bcedd2180fd954e6ec9f6ae1e0976ecf04dbee6463c2
+
+[Nlen = 9]
+
+Key = 58ae7965a508e8dd2eda69b5d888a28a1cb3783bad55d59d5b0da87137b72e93
+
+Count = 20
+Nonce = caa3d928d2bf2b7f2c
+Adata = 304678b3ffd3200e33a8912bcb556b3cfec53ca17f70ecba00d359f9f51d3e3b
+Payload = e61bad17640ecff926d0b0238271ee4c9f8e801dd7243e9e
+CT = 7bb1137c14cb4d324a4a8f1115c619ebf74927f0bed60a8d5a9140ff50dc4da375c7d2de80de097f
+
+Count = 21
+Nonce = cf09ca67659a583bb1
+Adata = 5507c4c3107cb446d19975f91207dbf3e2a51d1dcfd7da2f082159dbc3f41547
+Payload = 1887bb0c02500093a30a44b99e137483704b06615d308c6b
+CT = 834d3b2e5f0915c2348c706b4d2ff2717983ab4490edcc63971f02b7122d1e4f78de9c3376520f5a
+
+Count = 22
+Nonce = 97f940d7c1230bd8d2
+Adata = 56be2c9e09b555373d58f6fe2a0ca9b4ddba899addddf12b0fda860ad791773a
+Payload = 5ac67c9bec9b95c54e187a4a6812f5d701c4ac8f847c005b
+CT = 9f372ba1c87a115847cd708aaf5b8a143b6981ffc2c61cefd30ece13481609809b218de04c4e5ed0
+
+Count = 23
+Nonce = 147c7ebb6c92245054
+Adata = f95d64a513a9f3e6c95c9ed27b22fafd7dd10da52636029523142149116aff53
+Payload = 08f199a8d7e3ea821dd3106e8947cd2e9d485342b25a6471
+CT = c438aa6d187643d030dfe4d6b5b578f84838f4dc5c396d700c0986ecd7dab44e5e97db37392a485a
+
+Count = 24
+Nonce = b9bad794d49cdac9b3
+Adata = de9ff2a43f49cdc502cd17a373989bafd13fa6ccff6660557ce05b6295186d47
+Payload = 40d1cd4063750184356a1d7cae1cf1824f552c5d59a62dc1
+CT = 9952b25f4f4f375440cd958456184fe61610381ba92ca48f38dd977042c4d97da84e4effa650799a
+
+Count = 25
+Nonce = bbe054fbef86db3ce7
+Adata = dcec76181e3b872a5a6e79f070354e38866c7f67fc428fbca29ae6d929b1dd7f
+Payload = 5f29808ba74b672a0f82b3b7581dc32478c6e790e2b8c61c
+CT = 4d176f48b09b772dde8adbdaef720aba128a8d38a902847ebf22c81a5d824b4916660be6f9b513e6
+
+Count = 26
+Nonce = 6a35e1a4307f6efc6d
+Adata = af28120505a84a75b0f6b18cc9d8c75c661bf143be29c11d8ede78b9bb98c98a
+Payload = 5e2f601395ec406fcf96785f768162e849f867dca77667ab
+CT = 4e305e26d34711c6aa775f490939cc6560d3cb6905f5b0f5588ace6fc303600abc8e5825cbaedc7c
+
+Count = 27
+Nonce = f6c237fb3cfe95ec84
+Adata = 038f8ed89444784417a9c23bf11e9b436174e6c10959e00faa1704ce2f7f2c7e
+Payload = dfd9cacbf7d73d688447ebab13d2e13f3613652379b386f6
+CT = fb16c17a6b22a8658f446203ad46a48b34808083b271cabb015a1f78abc287bd2a63381ead07c558
+
+Count = 28
+Nonce = 50d024a3e7455d7249
+Adata = 8513365786b7988b208984e11022c15573f978bbdc29e8a7a4745c8a81885a1d
+Payload = 400317786b7df63373ffe541efcee6318cfc95bb673aad3e
+CT = d33b3141fea3a9ebdeb80d1da32dae42680be78471fb3023721f714120162514555b60560afa4256
+
+Count = 29
+Nonce = 02769283d5a06c363c
+Adata = 292c0be3713c6c588cb4e29a1c43b3e6353e33556194e568e800e4e44e8281e0
+Payload = 12ba8eddff1c2a03ddd25bb924ff065a93fd712b2c4f61eb
+CT = b15b1789c323a68568f86f35483bd7e204beff8f318ae14351f5e62b3b923a937e6c307af202fab3
+
+[Nlen = 10]
+
+Key = aecc5e18088bf9fd7b17f089bdd5607b69903b04b726361f8a81e221b1c91891
+
+Count = 30
+Nonce = c527d309ab29ee91c5fc
+Adata = 8f9a73e7bc1c11e2919020ba3a404cbddf861e9e78477218e3be2cd4337b278d
+Payload = d4291c99901345afe29f58912a414a7498f37b44362bdf3c
+CT = 392784a9e0b14bcd37639ec5409d6ead3e75f855e5a92c33ffc040ef3977e0035ce6ea6d157c18d3
+
+Count = 31
+Nonce = eebc31a5813b4fb93b63
+Adata = 9c87ad77953bf8a811e001ddb946eefafbfaa598150e85f0701853fa307d77d6
+Payload = ebcfd71120b0f9a2cccb898e6dfa082998cbe10032de3e61
+CT = e38eaad1e2df77e85e7129a8ce0f82cfc32b0aef79ab651bade65aa17e4dfb0aafe18cf71a72b180
+
+Count = 32
+Nonce = 231b33dc406c9210f59a
+Adata = 38be46d271bf868c198052391f8a2147c663700d9bb25a0caaa36974f18dacea
+Payload = 9032f910347daf661092b5c1f15b5ffed1369b194d9e12f0
+CT = 868b85288828501cf1d06610fec25e8b8a4b437e2e4f5563b7f3b898a2356909784598f8a8916f5a
+
+Count = 33
+Nonce = f2a88c3ebc74e62f24c7
+Adata = 5f495c5da035cabeb77e8aef10e91a05bd5aa414d1a37fa1099af959b26e5403
+Payload = cfe8ee9b475e36058471e2984ae66f6ba1b3cb477b15155e
+CT = 22c16333ac651cd9c183e78aba3e9312fb3b77dd6f9199502788860aae5534cf84979e30c3327d37
+
+Count = 34
+Nonce = 9cbaf1c83ba60b1e90ea
+Adata = 7ef136bd9a5809676abbaa68016d6fc713e34ac4b768a8246b1198c959f43085
+Payload = c3bcb0aaea93893f05eeb6439c8619dec17670a6439e2921
+CT = ebd9fb86563aa8f10062624441336f982c161ce5717d990a599ca6ec1c61a14c37b5902389e47aee
+
+Count = 35
+Nonce = e25322845d87d8a76753
+Adata = 2a89b9f0e56a1cf87dd38ed78028b6286ef8b7141dd2b3c65c5a8e1ed79bf4aa
+Payload = ae622ff9381854f831892c318bae5c003e74b15199bc12c0
+CT = 144c920f0fe278f353d0b053563d907c7589e4f1479d7a93a0604deb3fd9cea2d89987833ff5c2f1
+
+Count = 36
+Nonce = f4d7978fad36223623cc
+Adata = 8671de7e994967f2521d263925e745af9273682d9c08ced07d4a98fc985f68a0
+Payload = ef9b4ff8da108cabc972192ffecd5f96594c6d0871ffa6aa
+CT = ae4948b3bc1e50beb9f5d005871fc0d3dbde295de1c9ec3cbc866ab47bea7a4d0070e52b492fb8f6
+
+Count = 37
+Nonce = 6597ffb9eaad0fd9d830
+Adata = d2967ddf69ef62a9e23c9118dfaa55df92b4116322f1c9275131e3875dc92faa
+Payload = 5015c894b2437ff15c46bca9236830ff4bb057cd5764f027
+CT = 0b1dcb3cb0b4c32f398f3c43eccfe8f4242f33c99a2a2283efcb3dacac25bed0304f227fd5b77b8f
+
+Count = 38
+Nonce = 80e376b87272d99cde28
+Adata = c9cc8f967dff45c05b9345d03813b6e30dace99556f7df75b7120bb6e5f55827
+Payload = 615f657e24129a3e0f119988959608821219ce8354c4be26
+CT = d3e8b8f7ff8faa666ffe2509187fa7befc7412fd4e3bdb06cd2f7494b1fb0a0c6a2184e5c4787fea
+
+Count = 39
+Nonce = 344cce96455541d403f3
+Adata = 748cce18fb40126ce125dbe341fbbc59d2aacc170ed5ef0293b15713c9184a07
+Payload = 828b6a4cd49f499a6e8e8508f9ab35255d8e9fed33ba4d91
+CT = b67e582a74d7f022a16ada2de7ec18caafdefa6b104baf4ed93b6f8c8a1bf72be75976e4ebe6dd1f
+
+[Nlen = 11]
+
+Key = 97bc7482a87ba005475dfa3448f59d4b3f9c4c969d08b39b1b21ef965c0f5125
+
+Count = 40
+Nonce = 0bcf78103ec52d6df28887
+Adata = 049c10f0cb37ae08eae2d0766563b7c5a8454f841c2061a4f71a0a2158ae6ce5
+Payload = b99bf4dc781795fc4d3a8467b06e1665d4e543657f23129f
+CT = 0d3891fa0caac1f7ebe41b480920ffd34d4155064c24f3b17a483163dd8f228d1f20cd4f86cf38fd
+
+Count = 41
+Nonce = ab6374c6b2faefd92fa3d3
+Adata = f19c044023e5cf339203738ee70e76527519763664c06ae00e002a5ba94c32c6
+Payload = a2e5c51f516db01688b64c173bb25645182a005018022ee1
+CT = f70c598df3c64d3527ebb7fc8408b7de2cfaa1da7984ec361f1ad61758d828b70d4881b7d6ae8cd0
+
+Count = 42
+Nonce = cfb89e7ddcba601e875110
+Adata = 052714010da516c896ac5842a839ae845324643cddb080e6206148432d0d0407
+Payload = 037f206cab78a6ca0745dc8fc137e22e14f3d7183917ef83
+CT = ccd675862502a2e2520a33250150b8b7b220e84db854888c316dd62075fc761e2bc80edc5c564bdf
+
+Count = 43
+Nonce = 967cb6f8530bf8a43adb42
+Adata = cf391a84d03e2e22aec1965cec821f99e7bf21a7c3580dffa531464b22d83225
+Payload = caa3d928d2bf2b7f2cd8a7f357055b6d6895a5e34f47972a
+CT = 4f4f509debe6e52eae4af8b1740dde0a5338f78711a3b4ebfc8b5aca6d606222d6af7cfea0d1f4e1
+
+Count = 44
+Nonce = f5b7b5dd2b5e1ec93710c9
+Adata = e7a6b228a67d37b9d29a38efc547e50b4a6d95d599b45ee189ece21101ac6b5b
+Payload = 4a74ff35418723f2cecec1012484b52114067b2b2393e7f4
+CT = 25b140922a9d4f2ce153a4ff86596a49d7de6a6184e931e8b2ff27a98029b23484e00c2a5d291887
+
+Count = 45
+Nonce = 713de00faff892977d99d0
+Adata = 14ea93488d4284d21d4c7ce14414adf45c1ed9d2d99db866d0e59accb6234dac
+Payload = 3820db475c7cb04a0f74d8e449f026ec951fa59667738698
+CT = e4d92ab8d1ffb0976670d891cc8338da12f86d5d79b334103d2ae816edf857c810b6fdc7f2c71f1d
+
+Count = 46
+Nonce = ba87934808de09b2ae829b
+Adata = 30e2ea2a505f19e8760a0a84961000c7a0b7fe3460a9d3f5a38f54149be2e9ee
+Payload = 0e52a384cedcdf7f179348de6e7336aa86f8855fbd903cfa
+CT = 6df893eed2be958e5f542f8cb4adb392b34786cb4ce821ec93fc57997b977948d55bdb026db5bc48
+
+Count = 47
+Nonce = ea09fbe5da0fa4fe911e18
+Adata = 237dc8512b29bccdeb8ee39cf83b9b6dd203823d175c44d5f605b194e7ec136e
+Payload = 41cee0ecaf9c65cef740440af37954ef49a585779d2abbca
+CT = 2f204ebcf549ee2a800d870e6341b9a89a41ab4ae91b6902ff704a2bcfb8becd0226f76d68fbb08b
+
+Count = 48
+Nonce = 5b80d7affc4ab4a4b68bdd
+Adata = 3a38dd7da30f5c312fb1e978d87b7a39792fd9ea3e9ab1565874e99df587327c
+Payload = 5ff92f6d3ca791421363e10cc84b4e8e21e0ebe5d8c55d6c
+CT = 05472db7875d59f8bed45606f355a516de93740aa2baeba18df9400df42baee6b9a0d75b45840104
+
+Count = 49
+Nonce = 514bba483fe7f2b7e555cc
+Adata = ac8beb419099cdb42a39e9b46fd900cc52eec4b43a96ed18b37b899b63fb931c
+Payload = b0b11dfca9b3936d1b4a423c5acd3d012b399a487c19c994
+CT = fa20629d514c4ce7bf727629bca5aa1c0c7e7851fc1bfc5c847729a70d7b4cff5281aece37006015
+
+[Nlen = 12]
+
+Key = d6ff67379a2ead2ca87aa4f29536258f9fb9fc2e91b0ed18e7b9f5df332dd1dc
+
+Count = 50
+Nonce = 2f1d0717a822e20c7cd28f0a
+Adata = d50741d34c8564d92f396b97be782923ff3c855ea9757bde419f632c83997630
+Payload = 98626ffc6c44f13c964e7fcb7d16e988990d6d063d012d33
+CT = 50e22db70ac2bab6d6af7059c90d00fbf0fb52eee5eb650e08aca7dec636170f481dcb9fefb85c05
+
+Count = 51
+Nonce = 819ecbe71f851743871163cc
+Adata = 48e06c3b2940819e58eb24122a2988c997697347a6e34c21267d76049febdcf8
+Payload = 8d164f598ea141082b1069776fccd87baf6a2563cbdbc9d1
+CT = 70fd9d3c7d9e8af610edb3d329f371cf3052d820e79775a932d42f9954f9d35d989a09e4292949fc
+
+Count = 52
+Nonce = 22168c66967d545823ea0b7a
+Adata = 7f596bc7a815d103ed9f6dc428b60e72aeadcb9382ccde4ac9f3b61e7e8047fd
+Payload = b28a5bc814e7f71ae94586b58281ff05a71191c92e45db74
+CT = 30254fe7c249c0125c56c90bad3983c7f852df91fa4e828b7522efcd96cd4de4cf41e9b67c708f9f
+
+Count = 53
+Nonce = 225557b0faca3d6cbaedec5c
+Adata = c7aafe7d3b419fa4ea06143897054846ac4b25e4744b62ba8a809cc19253a94b
+Payload = 0e71863c2962244c7d1a28fc755f0c73e5cbd630a8dbdeb3
+CT = 2369b56f21336aba9ac3e9ba428e0d648842a7971182d5ffac57f6ae1080efab4ed93f8b4ce1d355
+
+Count = 54
+Nonce = 78912be1a35e156a70fb72f7
+Adata = 12ba8eddff1c2a03ddd25bb924ff065a93fd712b2c4f61eb80d77fab2c4900e0
+Payload = 113efd182f683596862ccd5eba2e2d4ffa709d9b85c6f1d5
+CT = 835a22eb8d718c0ee1531a2d1bb95f58215c997c612908eeed3ccaeb7a814f69d3ec1fbf2ee9792d
+
+Count = 55
+Nonce = 91ad90b58d2044abacf957e1
+Adata = 4fc795b9126c23dd7fd514c2e5a8ca583e88a783b28cbb2a5df09f8b520ba0d1
+Payload = ed55f6b9eb8fe74474c037ede94ffd84ada846ede4ecff74
+CT = ecb595276fd5d412a7cc3f5cfe960f47a0d0e2df0b08a11ac257d67143722a976c9d7f44b09a767d
+
+Count = 56
+Nonce = 4bbe4ca29122c4892ca09b5b
+Adata = 367ecd1b71dfb96a84e2369f28705dfaebf0c73ed35d5364449b2391230be846
+Payload = 8dd497bb777bbc3e56e3af25a43545007bb00f2b9e9f815c
+CT = 563d61fc0a5b82804a580a7d752a8e61d3342fb39372b39b6843a685bde3175695796f6e64f35901
+
+Count = 57
+Nonce = 218e7b8a8fd62927f90b70e5
+Adata = 01815f599d6ba0d1c09f6f673bb6cca4c2a7a74f4e985be4c0f37842c7bbc5a4
+Payload = 80f3e4245c3eab16ef8bf001429122e46bde21735f63adba
+CT = aaceb16589b9de253c99d0d32409a631db71e8df8a7644bfd027e3466e8220144cb0552f9b2800e6
+
+Count = 58
+Nonce = eecc9f106a0721334cc7f5ba
+Adata = bf38d0ee11a796a517539bbc9ab00ff85a4ddbf0a612d46e2bc635180ad34c50
+Payload = 36cefa10af1a3446a2c8d4a1171144b9ddd8e33a7cd5a02d
+CT = 9bf3b2df93cf5b587ecc96f45fc75e6eb066cb286cb06f284c9027fc41bb8c848025fcf9d092a873
+
+Count = 59
+Nonce = e41af8ca408c4c12e37561a4
+Adata = e0b20892875f60b5d8763a04958487fa5b7cf8d67a456e430475b337245d671c
+Payload = 32a4da08bdd51336ed5798c7177b853a534bc98f2e6f7d4e
+CT = 95ffdc68f721cf2294d0d88002e3814167306fd906dbebdb7e6e0e5dc0a03826e51bd94269d7a41d
+
+[Nlen = 13]
+
+Key = 4a75ff2f66dae2935403cce27e829ad8be98185c73f8bc61d3ce950a83007e11
+
+Count = 60
+Nonce = 46eb390b175e75da6193d7edb6
+Adata = 282f05f734f249c0535ee396282218b7c4913c39b59ad2a03ffaf5b0e9b0f780
+Payload = 205f2a664a8512e18321a91c13ec13b9e6b633228c57cc1e
+CT = 58f1584f761983bef4d0060746b5d5ee610ecfda31101a7f5460e9b7856d60a5ad9803c0762f8176
+
+Count = 61
+Nonce = 8a56588fe5e125237b6cdc30f9
+Adata = b3aee5fbf409bcfe9b46ae68d570edbbed32c12d13926ffb5ddc60ff0bdb7f85
+Payload = eca81bbd12d3fd28df85e2cc3dcc2ecbd87408002fd00fe1
+CT = 9aad62a5443550d11f9efdab2de0eba74d47ae4f7d16adf4276664f6567f2f978bd4be4d80cd07be
+
+Count = 62
+Nonce = d908b04840caca2280e5293ade
+Adata = 314a202f836f9f257e22d8c11757832ae5131d357a72df88f3eff0ffcee0da4e
+Payload = ad1109ea5c79bb55d22e9713eb2df42767cb29a2eba3ad2c
+CT = 61fdcebb158cd03151697ae7871c0a998802997e0672e5886e5a9df1b1d6284ef657cde6f74734bb
+
+Count = 63
+Nonce = 6df8c5c28d1728975a0b766cd7
+Adata = 080f82469505118842e5fa70df5323de175a37609904ee5e76288f94ca84b3c5
+Payload = 1a95f06b821879df3fd3ac52fc99a7c1d3e9775263b7d036
+CT = 704f60f9cc3ef7bc00b4f7a271ca70a89f4d5605387b3e2f8cc80aa08572b90e9598d0a73712b720
+
+Count = 64
+Nonce = 6c6ebacce80dde9fefb7e5bb47
+Adata = 93f0fca0c8c84d5cc48160b25e246226d489225c0f8275e52856da592c715aa6
+Payload = 46820aec46ebd0d61706129584058a1498514928a87fe620
+CT = 00f6cccf45f046da1e6266afe61eed61c60c28515b2e1ab386b2c952055899184f0d95ffe3959f89
+
+Count = 65
+Nonce = b94bc20d8c9abca7645fc6bebf
+Adata = e1c083c93663f5a066ef337a61aa3fddde7c301a42463137c375cc2dcdd76954
+Payload = f1fca581d3dbbc61060c0c02adb47bc57954d25a283f66d6
+CT = 90c65d23e0e1786cebb95f9b1306d001b2e503842cdedb75e37a53d77b9e38605febdd7b2b666f98
+
+Count = 66
+Nonce = a4974791d417d7e9eea0f4ae8d
+Adata = 33602f308f3a0f7e1c75fc1e4321d545ffa278234958dbadd37f59a0f85349c3
+Payload = 41712c058d2d56b43b2c79278e790858a289320746c15a60
+CT = aab5656a1ef060c9b1ef7e2f3cc0bda40ff067900401182563ceb824708a20724c99c83f1caacd70
+
+Count = 67
+Nonce = 6003b771afe4e99e1ef1ed4a31
+Adata = f60d8362b2ebf523681bb051fd3ee13919ad86acd963c703c4178a5f01a84236
+Payload = b766022311c5e1d74a607fec7cb8ee805b8397a6c5f374c1
+CT = f73b2a6dbf8f798d4bfb489a6578c9c79152e42aa3b81b64a84e7af3116a18f7ce44ae93f420270b
+
+Count = 68
+Nonce = 27861168ac731a223dc35c03e8
+Adata = b7ba1c66282cb6092ba601407ff9578afdadf7ba7a4d08edef06dbbfd87171bf
+Payload = 0822e3e6ba982091d532cd5271fbde25305d1f6e71880f81
+CT = 5ab3e5296cd1f08704c82f6b42939702515b7733853d723d4009312bdae46958d844eca502bcb005
+
+Count = 69
+Nonce = ef284d1ddf35d1d23de6a2f84b
+Adata = 0b90b3a087b9a4d3267bc57c470695ef7cf658353f2f680ee00ccc32c2ba0bdc
+Payload = bf35ddbad5e059169468ae8537f00ec790cc038b9ed0a5d7
+CT = b702ad593b4169fd7011f0288e4e62620543095186b32c122389523b5ccc33c6b41b139108a99442
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT128.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT128.rsp
new file mode 100644
index 0000000000..f79db90b4d
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT128.rsp
@@ -0,0 +1,1383 @@
+# CAVS 11.0
+# "CCM-VPT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:24 2011
+
+Alen = 32
+Nlen = 13
+Tlen = 16
+
+[Plen = 0]
+
+Key = 2ebf60f0969013a54a3dedb19d20f6c8
+Nonce = 1de8c5e21f9db33123ff870add
+
+Count = 0
+Adata = e1de6c6119d7db471136285d10b47a450221b16978569190ef6a22b055295603
+Payload = 00
+CT = 0ead29ef205fbb86d11abe5ed704b880
+
+Count = 1
+Adata = 98d477b7ef0e4ded679b0bc8d880f09823ad80e9732fde59c3a87da6a1fcf70b
+Payload = 00
+CT = 5b85d144bb51d4927074d3536a2db83a
+
+Count = 2
+Adata = 28f32de10b6c9d3c3f46efec7aee24006208a54c4d1c2bba4b8cdce166cab7d9
+Payload = 00
+CT = 01045de4a09486eea5efa33ecc6cd299
+
+Count = 3
+Adata = af397a8b8dd73ab702ce8e53aa9f0189995c6c9e920dcb75795149550b499deb
+Payload = 00
+CT = dfd75400b59c3ad387bc86dfbbfb52ac
+
+Count = 4
+Adata = 3fa956bfaa27e249bf0a1276468d808259f3b8e2687851d780885d44cc2f04bd
+Payload = 00
+CT = 2b11d2549b4e2f0a81c07ee90af4d081
+
+Count = 5
+Adata = babbd1b44cae3af06e0150bf0e3d898f6fe862b71ea9f6b727accfc18848fc79
+Payload = 00
+CT = 10f76ab445f4ec158ccc1f7c6fee3ede
+
+Count = 6
+Adata = 7fba0bfda3b03c736c121cf9a257db55060b621be5168619ec4182f13ef6a408
+Payload = 00
+CT = 59e02d6a6aa3fb2692b04e65a0e735da
+
+Count = 7
+Adata = 057354a29808f4ed77671ed3dc36f8b03f5cd952caac5cb80dc3b319f3333e29
+Payload = 00
+CT = 367a2ade4087964dcb0ca2984d44657e
+
+Count = 8
+Adata = ec08b618602d091e9304715cb552b357c16fd1d7f7f023a28d84a98ba21ca0ab
+Payload = 00
+CT = 47cb92cd40bc89328d4dd44fbd727032
+
+Count = 9
+Adata = 45622834ea658b09b17f32777d18b34b387ef957bd344468f68e7178417a7c24
+Payload = 00
+CT = f5185afb8359b5ef995483c0bc4192c3
+
+[Plen = 1]
+
+Key = 6ae7a8e907b8720f4b0d5507c1d0dc41
+Nonce = 7f18ad442e536a0159e7aa8c0f
+
+Count = 10
+Adata = 9c9b0f11e020c6512a63dfa1a5ec8df8bd8e2ad83cf87b80b38635621c5dc0d7
+Payload = 0e
+CT = 4c201784bdab19e255787fecd02000c49d
+
+Count = 11
+Adata = 73616a428f1a567b2e9af86b1fc8aec6d597b1b55f2aa2219b3b662fa6bd3407
+Payload = 30
+CT = 72f14519f06b63fac3d5b2d9bbfa0cb758
+
+Count = 12
+Adata = 6d62f4e15e8bcc9ba4993bc50a046737121016f0d15020b90068250551167b1c
+Payload = 34
+CT = 7676b581a28ca0a0ba5178eba7fe028da6
+
+Count = 13
+Adata = 8f0b8289a1834ecc2167b59ce3c9d3b58465c4cfaad50c728d04360cb7e5bc41
+Payload = ec
+CT = aed99b805c0a4785ff2913cab3e50f6205
+
+Count = 14
+Adata = 477b2a6932f838f0d1bc420c0ca306981d8e2dab945b6f259e15fe888667220a
+Payload = ec
+CT = aeb50e41cd7af84a8fdb6aee144e904616
+
+Count = 15
+Adata = d6518d409b1f05708d0b44f18fb5721f20f3220f8d2f2718650aa9932e4579e0
+Payload = d1
+CT = 9312639c863974f077fe8236c943b464c4
+
+Count = 16
+Adata = 865e7cde73b558e9bfd05356923f8a697970811fc484acad2d5b3528baf1f986
+Payload = 24
+CT = 66d7265cde50bc7a3989458437baf06db5
+
+Count = 17
+Adata = f0c3c67a935eace53ed32435655dd0974fafe283622e8294a15d70977398eae2
+Payload = c5
+CT = 87063144b25d2268063815d1b42ebbac34
+
+Count = 18
+Adata = 341e71b2ef26e9db03882e06d06cde2c0617326cd157d5984d22f6f3407a9c39
+Payload = 34
+CT = 767da45c10d0d6498716bcf3f13ca7e26c
+
+Count = 19
+Adata = 31fce6735ba9a3385df11c153179b8e4141a3c6b8ad6eceaa211f3f17bfd0474
+Payload = 7d
+CT = 3fcb0a6f562974cfb3fb7c8d5cafd50f2b
+
+[Plen = 2]
+
+Key = 3d746ae6cac5cefd01f021c0bbf4bc3c
+Nonce = 597b3614ff9cd567afd1aad4e5
+
+Count = 20
+Adata = 90446190e1ff5e48e8a09d692b217de3ad0ab4a670e7f1b437f9c07a902cad60
+Payload = 4360
+CT = e38fdb77c1f8bbac2903a2ec7bc0f9c5654d
+
+Count = 21
+Adata = 6bc3d30925c67371573271f1a4273ad76e91e07dfab65f7bce0b241b5e4cd00e
+Payload = 17c6
+CT = b72955210d62e1393e4fda647c2b2e59a47d
+
+Count = 22
+Adata = d1bb4cdfc3f2c16d92576068543692aa4b5a427d688387af0f1583e91a0e8b3c
+Payload = 6575
+CT = c59ad54fd88a47b9f6e39cb4606af86d13e8
+
+Count = 23
+Adata = ae6136df9ab43631ef143515dacedbe759b3459e951bfaf4712a21c86352f1c0
+Payload = b1dd
+CT = 11326de841af64b55bb7ebe3fd30ba493c7d
+
+Count = 24
+Adata = ffead34ac26e21158212d07c367c3a7cb6b795887ee2d3d8ae25c60556ea88d3
+Payload = cd16
+CT = 6df93a206339de534271f6469edfa5ed07d3
+
+Count = 25
+Adata = e768e7d867820d46c1cc62ee0e51d4dac6f5c4b5785b5ccfbf05236871bdce2a
+Payload = 12f5
+CT = b21aa8f65144f2ec5809e2ccb38c8760f7bc
+
+Count = 26
+Adata = 402e802885e4119df17fe85f141c3d1af7727fcdb00f8e2c34e42a436d04ac5b
+Payload = 39c0
+CT = 992f9af825957abe7d89e175b6e8c0b84b5f
+
+Count = 27
+Adata = 8a3a622b3d347c0c5210d484adf77fa33205ba02224ddceea71d89c9ad8429ae
+Payload = 912f
+CT = 31c025d6a12e91e84e355934547f6b5dceb8
+
+Count = 28
+Adata = 636114e5e5f83cec94e1df21d6babb9f6a14a532fcbfc3bcf649fbd79ac1abbb
+Payload = cb6d
+CT = 6b826db959a21e9e4ebf25ca4f98501b560d
+
+Count = 29
+Adata = 04e84f9156998c2eca9e96079a6001f2947dc49a081b3d75e47d75f71ed4a606
+Payload = 5bd2
+CT = fb3d2006ff22ff231a6646ae561923818a21
+
+[Plen = 3]
+
+Key = 3e4fa1c6f8b00f1296956735ee86e310
+Nonce = c6a170936568651020edfe15df
+
+Count = 30
+Adata = 00d57896da2435a4271afb9c98f61a650e63a4955357c47d073c5165dd4ea318
+Payload = 3a6734
+CT = 384be657bfc5f385b179be7333eb3f57df546b
+
+Count = 31
+Adata = 50f6e6dd57bd3a24f6bfdc8b1c7b5a36ebdd07fd6d194e6e82da47151d9c88fb
+Payload = 4ffad3
+CT = 4dd601b8ca97bda492546d82dccdebef441f8b
+
+Count = 32
+Adata = 70e132023acae1f88c7a237b68f5bdce56bcfc92be9f403d95d3bcc93b4477a9
+Payload = 8a594b
+CT = 887599fa0f3e397d9a580aa39c7028e1a508c9
+
+Count = 33
+Adata = 08d2b011f36e05dc728c1a8bda3d92c779a3d2f27c4b041810bd6222c852b14d
+Payload = 1f89df
+CT = 1da50d593460d335e2f7a6d40b8fe305b0f690
+
+Count = 34
+Adata = b207eb870aeeab27c6201ef04650bdc7ea30028a243420f7d198f1c9c9a43023
+Payload = 72e9c1
+CT = 70c513a2d49e1a113767ea4219107819d88b65
+
+Count = 35
+Adata = 74294088721fc9e7aabd5f1c66b5369b1e2d2cdb3e73abaa28ecd1c37d4ecea2
+Payload = 016083
+CT = 034c51dab1c819778be8453db163c882063af8
+
+Count = 36
+Adata = abbd347999a1c26368cdb17ab08bf57a8e942d1248296e952f5f42f2cabbf0e6
+Payload = 25f665
+CT = 27dab7537eb435df8d0e48c3f7e0bd1877c866
+
+Count = 37
+Adata = 231b33dc406c9210f59a5df1cfd595c803474db34b9b1848f0bcbe7b28df33c2
+Payload = 158606
+CT = 17aad4da549fc63d55b5910bbbf64435b95220
+
+Count = 38
+Adata = 69b851e63a78baef90637978e3dfe8c47be4b21e85bb89bf67051cf251004376
+Payload = b07452
+CT = b25880d5ee29fb2af47f8040fad585921057f5
+
+Count = 39
+Adata = 9b1f786c887d310b8efd3e8192fe504f603024c94aaa4ec9123736a40bf1605d
+Payload = 65187c
+CT = 6734aebc3ee43e10205f83143e0d3794a6734c
+
+[Plen = 4]
+
+Key = 7ccbb8557f6e08f436d0957d4bbe7fdf
+Nonce = bb8e2ef2ed9484f9021cda7073
+
+Count = 40
+Adata = fba1d18a74a3bb38671ab2842ffaa434cd572a0b45320e4145930b3008d8d350
+Payload = 4cabeb02
+CT = 32501f4235c4dd96e83d5ab4c3c31c523453c317
+
+Count = 41
+Adata = 78b3faecb2bdf6ed14ac2b86ded07aa791b60f5d54f9e24a965a8453f5131898
+Payload = 5ff73653
+CT = 210cc2137907d6a03e66403a7d9330d30d934a8d
+
+Count = 42
+Adata = db1239528eb464dd063e2a97ee83a87d6002ebb4fbafa77036f72c14f3fe959b
+Payload = 062fa9ca
+CT = 78d45d8a44f4bc78fbb969935076134437df82b4
+
+Count = 43
+Adata = 0071f1edb3a0ce57af3c88bb0ccf138f752697a77e55695838fb39de04c78dfb
+Payload = cad710b4
+CT = b42ce4f459692911fea2e0034d06c3b2e89af3d1
+
+Count = 44
+Adata = 7381471a62b1fa6f5061c4c37e9721f07099d007ffaf8639aa2ae3f82da5a559
+Payload = 7ac716b4
+CT = 043ce2f468484e22381923bfcaed16e0cb85b0f8
+
+Count = 45
+Adata = 19bea6d92d5892216e8e4a30dda802387800bb046a6717817fc46c7edafe17b0
+Payload = 362da02c
+CT = 48d6546cd081de39c247df309c4b56c31c03690d
+
+Count = 46
+Adata = 8503c8eb9cebc6110f259e35e03a0740267768130ce6f61b1c7d1d25be942274
+Payload = de52b209
+CT = a0a94649c6c6bd7b3a9d7c4dfa2738847ea3cb33
+
+Count = 47
+Adata = d2445db6efecaa3f426b06de8d496ceed54a1d0171384cc762e21b31e265c6d5
+Payload = 8fe8b383
+CT = f11347c32ca874d18d0b790856837555f4d4699a
+
+Count = 48
+Adata = 8cda7d1e135cf5fde1ec9473c4b42c1bbb445c27fd87b5f73df61ceb2d0b6f75
+Payload = d8d6b2c9
+CT = a62d4689932c2f8d78e322aaffc90846025190f1
+
+Count = 49
+Adata = b506a6ba900c1147c806775324b36eb376aa01d4c3eef6f5a4c25393ecbf2025
+Payload = 6a029e53
+CT = 14f96a13c346a4084918081b4bbe53b50d896788
+
+[Plen = 5]
+
+Key = 3725c7905bfaca415908c617b78f8dee
+Nonce = c98ec4473e051a4d4ac56fd082
+
+Count = 50
+Adata = 11bc87f1c2d2076ba47c5cb530dd6c2a224f7a0f7f554e23d7d29077c7787680
+Payload = f5499a7082
+CT = e378b776242066751af249d521c6eaebdff40b2642
+
+Count = 51
+Adata = d54219ef4fb851bebd1c546011ae3922b8337e19c28d4d58428efd66f80edcf0
+Payload = 513c46fcce
+CT = 470d6bfa68e7258df363e0e9af67a543c86db3c994
+
+Count = 52
+Adata = a92e88edd297da8c7089e21822b3e6cffd6837c78b975c8413fd6cca1b99bcb0
+Payload = 9d62e557c3
+CT = 8b53c8516572b7573e5b27a1d0e15cdb7b06c8857f
+
+Count = 53
+Adata = 77d9c306aa257379053cf1f2043c388a301dac2a9e2bb89eb8bab6eb3f150fe3
+Payload = 7a05db235f
+CT = 6c34f625f9de691a412ad54bbdb6ceac45ed45902b
+
+Count = 54
+Adata = 081568ae0b948aa647b9d4dda5d42641ad5de72aa9874d8d0717d872007720a8
+Payload = 30a22ca0fc
+CT = 269301a65a8a1bb8ba3d6763dcb1bdd3400e3459f7
+
+Count = 55
+Adata = 695ba4dea0f84baf190ec25a25fc00cb9898902d7a17e6f5ff2df323b974f7c4
+Payload = 35e25aa51f
+CT = 23d377a3b9403897d496cabcd5bd9de3282199a8ed
+
+Count = 56
+Adata = 1f3ba0336a634efdd11f8168c0fe25039f9403bfa70b3898f4dbe577dbd52957
+Payload = 8bde704c74
+CT = 9def5d4ad270a81f7cb0ab7ab2b495f51d66abeee5
+
+Count = 57
+Adata = 097b9ebff3ff93a143678d59721fdf359e95cbc82585ae47727a773317925d38
+Payload = 428542ecfb
+CT = 54b46fea5dce68e9b01a4462a2221bd2f3cadf64c0
+
+Count = 58
+Adata = 76d0341dd44c39e43a23dbcf4cb602f15d5fb9fee20c3d0d262d539c3fd1dfd5
+Payload = bd6866ded0
+CT = ab594bd876f2545964ef3978cad3387d61104bab84
+
+Count = 59
+Adata = 7e7c40ad64b511005b4546f9ec61ca24829390fbc4bd8507225bc348ae0807d7
+Payload = 5822755a3e
+CT = 4e13585c98002c41938a935d51905b2a708a2c5194
+
+[Plen = 6]
+
+Key = 80bead98a05d1bb173cd4fca463b8fa3
+Nonce = 8a14a6d255aa4032ebff37a3d7
+
+Count = 60
+Adata = bb4e706e73d21df66f64173859d47e247527cd9832e20dccff8548ed5f554108
+Payload = e479990bf082
+CT = 89c9246238878427f36b1f6c633e4542f32b50ca8edb
+
+Count = 61
+Adata = 9db2182c8a4f5471082bfa1a8496602cbcdef2790f7e8f71f791303bd48dcb05
+Payload = 017a7fd1aecb
+CT = 6ccac2b866ced76fe54da69af5edf8309c7f013bb07e
+
+Count = 62
+Adata = bf483f59fb73681f27b68168c998c90ea8ceea997654c6fab2bd737dcdc884f9
+Payload = 512fc5e4973a
+CT = 3c9f788d5f3f662f53d17f7cb6673415bb2324ca0666
+
+Count = 63
+Adata = b91e641d8210e1ef705fec2beb9f58a391c7d1a38935cd1d13f2c00363388ff5
+Payload = 06212e989616
+CT = 6b9193f15e1340c86156b1065b64af1e4d6c89b32603
+
+Count = 64
+Adata = 5cebf908e232d797fcce8453c4c3000868d4172622a4ee0d6a1bdd876a0b7c96
+Payload = c45629069ebc
+CT = a9e6946f56b9c07ef5349903b928e39e99e2e32625de
+
+Count = 65
+Adata = ab92cbc97f3aa6f9ea4dae5d8c3d9e91231f43ffff548da7b668e61c183ac2cf
+Payload = b949ced37725
+CT = d4f973babf205e40654ea16e83cc6faeaad668c416f3
+
+Count = 66
+Adata = 2c3d2f9c7e89c2b9e07317c4db6e9f00f5faadfad531c5bea79d164ac24d4543
+Payload = 517ff7b383b7
+CT = 3ccf4ada4bb23102a502dbba0c280e1d5fc627fe3a9e
+
+Count = 67
+Adata = d798e77ab0f3697768f23014fd31b9e8762ae65b6aa8a4bbc17ecb8cbe78461f
+Payload = b40d863ca4ff
+CT = d9bd3b556cfa6745fd4c954396e696697731e1f9a262
+
+Count = 68
+Adata = 45b44e3dec57e24d960fd1767797ffdbbab81e38bab37e6974df262c3d932327
+Payload = 56e00289a003
+CT = 3b50bfe06806bdf2b2dd47077c98234eae5d47c3b594
+
+Count = 69
+Adata = 645d27970ccce096d082fccfc1183955bad2611af0dd7c58c9d54430f28bd992
+Payload = aa22bb1de579
+CT = c79206742d7cea66649ad7e204a344d3234125aa324b
+
+[Plen = 7]
+
+Key = dc8ec91184ba18eae31ac2d3b252673f
+Nonce = 0da4c988f521f5648259f2bec2
+
+Count = 70
+Adata = 6d5573c9279897d7d1602d8a95c04bb5ca3fad2dbe89a024b3651eb227e73bb5
+Payload = 2a5775986551c8
+CT = 4f259f2a718faea852a7c4358dfa9f5467357638acac90
+
+Count = 71
+Adata = ff0ab5021ef466e2e898b0993d691145168be558682c74914c172f2b5e863754
+Payload = 8db3c1ca0580f9
+CT = e8c12b78115e9f8767c76e707d48a2144e090812e0192d
+
+Count = 72
+Adata = 2ee03cc28f79773af139c4ea55ec4daa48bb2885b8adcd5f066eceda5c4ec27b
+Payload = 3c69e2e83236b6
+CT = 591b085a26e8d05486df740083c959fb62ef7e2e221602
+
+Count = 73
+Adata = f041504d4c1b3d5be358bd6d350af42921205d29ab22b44ffe221358adef5bb4
+Payload = 777828ab5ccb68
+CT = 120ac21948150ebdc4d2b86b2528f75db4a7f5423f4395
+
+Count = 74
+Adata = 81ea116832d69542ac8d3d22c16c82eecf2ccac39264dd933c4f9c13c8d0f1d4
+Payload = af556fef3584e3
+CT = ca27855d215a85a7b06d1b710baa15daef19069ecf46f0
+
+Count = 75
+Adata = 8a0a120ed290a62456f002da1c250a0ddb1ebd57185a733d8fb562aad482679d
+Payload = 98f26635351f14
+CT = fd808c8721c1723811129add52e1406d50cbff4aa82802
+
+Count = 76
+Adata = 12b5a76faedf6f855e328c2cb87be8aea78c5e926b32d828e167b46205c86de5
+Payload = bd22c1ec05dc26
+CT = d8502b5e1102401563d3da8a6cabb7515f642e42fb4b2e
+
+Count = 77
+Adata = 8dc32f35ef4bcbfd040ad25dc36d0bd2486f93d0cabb7704cd1582dc99f65449
+Payload = 2a87c0d64806fe
+CT = 4ff52a645cd89817609a21f703253e5e56beef4ac71759
+
+Count = 78
+Adata = 83ced632359a11eb0c4c99baad84df5cac15bc5453b6593d9ffb4c5e8c84037f
+Payload = f05f39eb0a3d64
+CT = 952dd3591ee302236c72f98da859b54be7c598d85c37eb
+
+Count = 79
+Adata = 771a818a24e7da7b98f4b4291ef34bec7e1656b0c6c6e9474a989a04ea7de385
+Payload = 59dad755af92c2
+CT = 3ca83de7bb4ca464c8cd38cbcc46e7f09bf3e1c6590c71
+
+[Plen = 8]
+
+Key = 19f97ef5318b8005fc7133fa31dd1236
+Nonce = 01ce9814c6329dbee1d02b1321
+
+Count = 80
+Adata = 85853f120981f33cf1d50fde6b8bc865fe988a9f12579acdb336f9f992b08b89
+Payload = 6d972a673fbe1ca1
+CT = 2f12a7e7acecae5d2563309efc19368cdee8266538ca89d3
+
+Count = 81
+Adata = a4ec5aee89e2cce2115b6c1f42570bc5062887cad08192a682d0b4508fcd936a
+Payload = 68b1b6367a15fe49
+CT = 2a343bb6e9474cb528096a5fec5e5359c369833eac3b7efb
+
+Count = 82
+Adata = f5499a7082bf1e6e2923211271f5f7f6d7c7b26db7963071705a58ddc4dca0dd
+Payload = 707023615563a40e
+CT = 32f5aee1c63116f2754a65863efb60c98dbb536e2b5a69d8
+
+Count = 83
+Adata = 765f267befe6fcfaaa4b46eda32e7bfab87f12ceb07fa3b37be74965bb664a21
+Payload = b56454bc50df3e28
+CT = f7e1d93cc38d8cd40b6e9b7f3b3541ffee66a1f668f67d28
+
+Count = 84
+Adata = 9ce65598cd1f86afc9aaaf172809570cc306333c25523f863c6d0e0154c55e40
+Payload = 962f765da3565bde
+CT = d4aafbdd3004e9227018c9db8baf6be349d93d4eef7d7c9d
+
+Count = 85
+Adata = d0125e30c36232a8c07cee9abc53453b276849a7c04ade80ad586ed8cbcede51
+Payload = 4f18bcc8ee0bbb80
+CT = 0d9d31487d59097c501b28887f05fd66f050525943d101f8
+
+Count = 86
+Adata = 90dfd9e7bb7bf8fb70c22a879ffa760d14cda7b79ce4968f69b8a7f2b7a59642
+Payload = ca293c9e1780b401
+CT = 88acb11e84d206fdda53dde2e1aef96b3658a7635ee54188
+
+Count = 87
+Adata = 58f518710e6b282482a7f1950fa353b13bdda10c9aaea6d5f0d7ea0a965d31e8
+Payload = b9df9fb4a6b299b4
+CT = fb5a123435e02b48b62a5ec234f1efd1b52c8fad1cf09890
+
+Count = 88
+Adata = df052e95aea3769a433ce4e4e800b8418649bbe8c6297eb07545e6802de7e807
+Payload = fb2441d1594a488a
+CT = b9a1cc51ca18fa76bc051ede6f37cf67543a7252d7d9b203
+
+Count = 89
+Adata = 0875020959ed969cfb38636d1d5aabce9658b00171a7614ea9e5395331c7659c
+Payload = 451101250ec6f266
+CT = 07948ca59d94409a5be4be6bc6b18104fac167b6e3fc15f7
+
+[Plen = 9]
+
+Key = c17944bfaeeb808eed66ae7242ab545f
+Nonce = 910b3db64df3728ca98219e01b
+
+Count = 90
+Adata = edf64f98b3ab593cbcf68ab37a8c9472e49cb849d4a744deae925a5a43faf262
+Payload = 7caae2640e734539d3
+CT = 0dae8b3ccf0b439f6ff8ee4a233dfb7753f6bfe321b3e26959
+
+Count = 91
+Adata = 29ac8fd6a20a5df4ec79660c44d373da42de7d7c5fc35982b6c29b480723b484
+Payload = e574b3a37af3bf2251
+CT = 9470dafbbb8bb984ed63b1477d9506a51ae23abbac179d8b02
+
+Count = 92
+Adata = 9ae5a04baa9d02c8854e609899c6240851cbc83f81f752bc04c71affa4eed385
+Payload = 2e3cf0af8c96c7b227
+CT = 5f3899f74deec1149bdb0986198bce2e486581c041029a81d9
+
+Count = 93
+Adata = cc8e789462879e348d20be4e1161d7b7fc6f8371d8f8cb2d25d13f0e07de47b0
+Payload = 16f22817c5b79f9fa6
+CT = 67f6414f04cf99391a0cbb2df2079a6eb964c3469f4f326122
+
+Count = 94
+Adata = c63061f2800228269015693336f78bb535ae8b88869e4ccf4ead2f3b0ea4e48a
+Payload = 64fe8076d4e8538e18
+CT = 15fae92e15905528a4a40ca7622acf7266b7c24cf0c3202e4c
+
+Count = 95
+Adata = 71c14a7031033db15bfe23b75fed9daf8886dd11392a0b787660e7b1a581af11
+Payload = 4814aaac48bdf43c92
+CT = 3910c3f489c5f29a2e7de20e98586cd5d684bf015a7abbe82c
+
+Count = 96
+Adata = 8f4947f8588ed866ed7477d7f1a28046430c6470806a50e3c9e80958c61f1b42
+Payload = 392a692b57a8a97f60
+CT = 482e007396d0afd9dc8d503f5d87818f7c0e173b857cef4288
+
+Count = 97
+Adata = 9d44f6df58c2b43db67e3daa95b176c81daff32e996d670e86405e15eae72e93
+Payload = cba1e00e345b0cb7eb
+CT = baa58956f5230a1157c85e2283d9e80700268a6459d1451d00
+
+Count = 98
+Adata = b6ada12f7a28211e9d2c07cbb3d39fa77aadc077b34c46f93006c1ca2ff66f87
+Payload = 22f5b6752582919dc1
+CT = 53f1df2de4fa973b7d1056aea3d3e4f7a5219170aaa52465e1
+
+Count = 99
+Adata = d6411fd5b25433f67ca75e4560ceb809d3721266beec358dde126b2f6a514137
+Payload = 6e1b55d6f5288c5451
+CT = 1f1f3c8e34508af2edfbfcf8200a8a3f8d995f50284a7280c8
+
+[Plen = 10]
+
+Key = 0fb9df6f638847f5de371f003dd938f4
+Nonce = c9ddf61c052f3502ad6b229819
+
+Count = 100
+Adata = 4f9938d5bc3dcbe47f6b256d5e99723d0891e50c6175aba41b011e4686113c49
+Payload = e10cc36bc1c5d3c646ab
+CT = 7f797367de50be6dc04e4cf0d8c24189affd35060cb7ca3dd136
+
+Count = 101
+Adata = e013a2edd5b86bab8df5c9940d0a0c864478c1ad42668304a643141855adac10
+Payload = 15841284c959febe63f9
+CT = 8bf1a288d6cc9315e51c4148ef85caab151488c1a6b3df540d21
+
+Count = 102
+Adata = 147d77d509f642189594df17574a0ce62b52a838feb62310e11533995ba4c851
+Payload = a8b4e5829069c335d1d8
+CT = 36c1558e8ffcae9e573ddaaa1e7c22b3efa8362abb3d31ee8884
+
+Count = 103
+Adata = 0bb09658e23fe8a08c01a6994ef36cb8dcc9a806297a09c67efe3558ca56bb5d
+Payload = 1bb2da0f1ae7e044deb0
+CT = 85c76a0305728def5855317b141383ad38dd78569d5f846f2520
+
+Count = 104
+Adata = 34eb2e6149bad764837f6f25ddd96865e5b05d5cbf233c4f6cc2aa654dfea3b7
+Payload = 63af538196add9b3fad2
+CT = fddae38d8938b4187c374e6432971aecf6bf7cf5244d21f7f173
+
+Count = 105
+Adata = b69f26fda6d1cd92897e03758cae020c4e1beb019ce5ad987f872940780a9468
+Payload = 6ef2df5a1688ae795537
+CT = f0876f56091dc3d2d3d2e4d0ffc0f0add38a80c7ffe6b4701e54
+
+Count = 106
+Adata = a7375ba32251af0138bd9fd8fcd56a7c43ab2ca9a7fc0117d25f6d4ef9c2fcbc
+Payload = 3f46c83021069ac488a1
+CT = a133783c3e93f76f0e4447fdd0b2f29f39094ba5a7375e278349
+
+Count = 107
+Adata = f9b91f7298b4e43843fc739a2f41c57c3f2cf36378fe4c34b574a43f9cedee7b
+Payload = 86c10a6dfdd6a06ef638
+CT = 18b4ba61e243cdc570dd57500f913ee3f46801e1bba9d4db7ecf
+
+Count = 108
+Adata = 9d35876d9449a1642b5062dfbfc7a26a7ac080b7198f4aeff2c79e463565cfd2
+Payload = 196c80d02b663bdd89fd
+CT = 871930dc34f356760f1856a6b87519b4807a2114ced587f72189
+
+Count = 109
+Adata = f2d5e927eb507f889efc6f21d783851f638f978c74960cc347f89f2703476114
+Payload = bd27ae3ade0781a33d5f
+CT = 23521e36c192ec08bbba2101012808adefe9b8166e04685bd537
+
+[Plen = 11]
+
+Key = 006ff7d3153caf906ec7929f5aef9276
+Nonce = 57db1541a185bd9cdc34d62025
+
+Count = 110
+Adata = 7d9681cac38e778fba11f4464f69ed9ebfea31b7ffcaf2925b3381c65d975974
+Payload = 31be1b241cae79c54c2446
+CT = 9dd8a4244fbdb30b624578a625c43233476bbb959acd9edebe2883
+
+Count = 111
+Adata = 1b0012c468009bd2851653013782c7b71ef43c393afd4dc0aec4d6d0c3fa11c5
+Payload = 8802831e22092b30110cf7
+CT = 24643c1e711ae1fe3f6dc9d477ca066ec2befa854a1faef018ea8b
+
+Count = 112
+Adata = 48b216375c00ca7e9c4048834b37944d2543e24fa091fb3c7290e11c53a6b6a0
+Payload = 3b3f782d637319d7fd161d
+CT = 9759c72d3060d319d37723eb6be9a78dfbd9e16181679b782969ad
+
+Count = 113
+Adata = f3e06a45fcf1f6abeb00727bf2c9bcea00ce621d38f7b7eba17c27e51f04c793
+Payload = e98f5e5a20d02c80372d6d
+CT = 45e9e15a73c3e64e194c533d9574d95b821a5170e9b61d8e6b2ff3
+
+Count = 114
+Adata = b36e27729f9a139d8ec4f61215b7bf1149cbb4d93a5c14bebd7cfb7c6fe585cb
+Payload = ceeed4fde3406ec40f7ac6
+CT = 62886bfdb053a40a211bf8aa193d257907be1330abaa56bc4f431a
+
+Count = 115
+Adata = 8886ed7fa414d74aef704a9751b197cbab02c41c6aedcaf65cda019dc2d2d815
+Payload = b38f03449883773135c0cd
+CT = 1fe9bc44cb90bdff1ba1f31d92029a6428748664b5c815f15ca1b7
+
+Count = 116
+Adata = 816d81af167d2294497d9b06a39fdf75e37cbacf4d10c3a444068c891b361bba
+Payload = 8efb141db7b77c521003cf
+CT = 229dab1de4a4b69c3e62f1386e4ad7c72ce0081a85d4cfd34254c7
+
+Count = 117
+Adata = f427c47e10c45bb3c7e75e9e604503b3560427691470358efdef48ddaf3794d2
+Payload = 6dc38e37d1379732df4dd5
+CT = c1a5313782245dfcf12ceb98eeb05bc376a1042735569d5b63f8fa
+
+Count = 118
+Adata = f3df712b5e8dd8e4aa8b7c5f41e93bd11b0df66a3456a01f3d0094ad91482cdb
+Payload = e0e358aff203369dd5960c
+CT = 4c85e7afa110fc53fbf732065b03ebeb68a9153cb4ed152ce0d64c
+
+Count = 119
+Adata = 264f2c7b095a296eb8ff6b5151ab3d9497ea8dc0002a9e5b09c2fd0ccd32b6ff
+Payload = 57b940550a383b40f3c308
+CT = fbdfff55592bf18edda236fcd16c8360a408e2787f930ed275bf3f
+
+[Plen = 12]
+
+Key = 026331e98aba9e8c23a9e8a91d0b0c97
+Nonce = bccfe69bba168b81cbdf7d018a
+
+Count = 120
+Adata = 26e011143a686a7224ddb8c5b1e5d31713fa22c386785e2c34f498ae56d07ed5
+Payload = a82200ef3a08c390dec5cbf9
+CT = adf4fc6f9be113066c09248fcb56a9c1a1c3bb16fbb9fbaedacdb12b
+
+Count = 121
+Adata = 97a720ae4720546e31263a1a538ce1d35c198c23bd4362e0023a67536328ab9a
+Payload = 7fc58d1bb450b396b9161f53
+CT = 7a13719b15b963000bdaf025002120b619a391fbd23402e5edd4949e
+
+Count = 122
+Adata = aff6c8cefda055c67262e9c68825d1ad2a7488e5b09640a111fabf6254d96cc0
+Payload = e9ea182d7f895f312b9738db
+CT = ec3ce4adde608fa7995bd7ad48b6e9a8de0099a28cebbf5c2bad42ff
+
+Count = 123
+Adata = 35a3963b43f47855ef3df12af5de3626e0c5c8d9cd2a534c737cd695609b05a9
+Payload = cfbc8bcbb5e5bb744bb1f340
+CT = ca6a774b140c6be2f97d1c36df80fd62e751757bb0a32a987980afe6
+
+Count = 124
+Adata = 46a2e6bd3fd5336abf02eace3cd1e1f6dde505ab976a9fa596edd6fbde7175de
+Payload = a334f8f41897cbcaeb5cffdf
+CT = a6e20474b97e1b5c599010a93b211350c70adf9bab5c01081bdc6a99
+
+Count = 125
+Adata = d110651c00ac5540f9d1ed9eb175e06b97163fc36d43f048565e5d0c30a069b1
+Payload = 3f781267290e8e73c6355e75
+CT = 3aaeeee788e75ee574f9b103d7f65690d9a2fb6759d658c9bdfdfc37
+
+Count = 126
+Adata = 978644dc4e36f1d98a2a63e19bbf8af11785d09fce58a95c00cc6bf6cecf6161
+Payload = 3dc39dbb91efe8b16396d488
+CT = 3815613b30063827d15a3bfe0d5df472f49e7f713cd1373293810906
+
+Count = 127
+Adata = 5ae7528c5e965880b1533cbd78c1e81a8187379327a2fc3f76ff45829049e183
+Payload = 6caa8c0764512baa39dabac0
+CT = 697c7087c5b8fb3c8b1655b64bfca9ef00b0f2bbb03c1a3f7a0862e7
+
+Count = 128
+Adata = afe754828be6e3731d3eee54b021b4fa182247bd958e9074fb0094a11030f5e8
+Payload = b19bc92e2305883580dd7742
+CT = b44d35ae82ec58a332119834a03be1d1d262b03c0ab425d533fe4ec1
+
+Count = 129
+Adata = 0650859c635654ca4d815963c0a99f9d2f47456ad37f739c425e924d4360bd7e
+Payload = dab87e79544df1cc98096b91
+CT = df6e82f9f5a4215a2ac584e7da61ca8461925996880e2874393232d6
+
+[Plen = 13]
+
+Key = d32088d50df9aba14d9022c870a0cb85
+Nonce = e16c69861efc206e85aab1255e
+
+Count = 130
+Adata = 0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa
+Payload = 4b10788c1a03bca656f04f1f98
+CT = 89f15b1cb665a8851da03b874ca6f73242f2f227350c0277e4e72cdaa6
+
+Count = 131
+Adata = a533b3279db530eaed425842b0d3528f5c5e4c16acfa0f49de43d6491f0060a9
+Payload = de6ea86d3641d916c4394fdd31
+CT = 1c8f8bfd9a27cd358f693b45e594271cc06f81d510075728cfeb89222c
+
+Count = 132
+Adata = 8e6c1cde142e18635c1b4f0cb54d3cf817f22ad7c25bf6a022501682f6a7da1c
+Payload = 6f3b32adc8c0314872947f3d31
+CT = adda113d64a6256b39c40ba5e5ab1aefed75400a41447b2bd8f0605542
+
+Count = 133
+Adata = 248a4389da2d51b87907dc11c46253515503ba80de5d06c9b505cb89906614a6
+Payload = 0cc992a8c736b44fedb4ad498f
+CT = ce28b1386b50a06ca6e4d9d15b46b3a6463876f1a43a287748f339e913
+
+Count = 134
+Adata = 2e2c8244a2cbf53816b59e413207fb75f9c5ce1af06e67d182d3250ea3283bcb
+Payload = 98104fd3f3413ad1f57ef4912c
+CT = 5af16c435f272ef2be2e8009f8f625786bdc58af24b17c1ba34fa87baa
+
+Count = 135
+Adata = 4ada86d88d5f49dfcde13fc30ba9a1af58d5254b47fb1885a20fad915c87952e
+Payload = 3b4fec79d52d8b2a533917b75f
+CT = f9aecfe9794b9f091869632f8bd4a918290cf97208232c76908514b07a
+
+Count = 136
+Adata = 9e3b23232e5a9e69747f8bcb148cd6d282fd9b7ecd6d97e8bb5cdc261b2fc86f
+Payload = f10c19c76ae7ed55e1651155df
+CT = 33ed3a57c681f976aa3565cd0b01d6306bb91c315bb4a23fe23d496d09
+
+Count = 137
+Adata = ccea2c815ea4efadc3007f511d633e98f9fa38b0e0fb572b282ed6a610adf7a9
+Payload = fa34af376868d9a49aa200f59a
+CT = 38d58ca7c40ecd87d1f2746d4e620d9d3004587c5d510e2a857fc857ea
+
+Count = 138
+Adata = f7277fb296e2c0d2c9ceb7013ea8b59fe37e26b3b42a0b8cd01aaaa8d35283d4
+Payload = abe2fd996bb6804ed3286c057d
+CT = 6903de09c7d0946d9878189da982d2438a5138977bde5f514e2335c28c
+
+Count = 139
+Adata = 14dd1810df3eeee78ed3836c77edf510d91ea28f119bf57111e580d70da94b74
+Payload = 395ea6979b77dabd2042aee4ff
+CT = fbbf85073711ce9e6b12da7c2b78100a05448fa6e74bd3ed16c3bd364e
+
+[Plen = 14]
+
+Key = 7301c907b9d2aaac355c5416ff25c59b
+Nonce = 7304b65b6dab466273862c88b9
+
+Count = 140
+Adata = 2c5d114eff62c527cc2e03c33c595a80fe609bfc0fe13ce3380efe05d85cceac
+Payload = 484300aa3a506afcd313b49ead8d
+CT = 928ca58b0d373dc50c52afac787ce8eeb5d5b493661259a9d91ea31a5f7e
+
+Count = 141
+Adata = d9ebc1cbfab9034317132a72e0f11c341331146a59e7a2f26bf4f3d778da52c4
+Payload = 8b318f75ed79a7978adc17c4d2d4
+CT = 51fe2a54da1ef0ae559d0cf60725552193439abfedda67d765d030cef30b
+
+Count = 142
+Adata = 9aea86b9fbd9bd4504ee2e25054942b33d3cdbd84215db7ea337e548cb706780
+Payload = 0256b0d154c768c85070da6ea8c7
+CT = d89915f063a03ff18f31c15c7d3615013c2bc9338868fad0d2fac11df019
+
+Count = 143
+Adata = 08afe10bbfbd65b948a6561bbeaf3ab46a8e3d0a861f1cfc46584156197f30a3
+Payload = 89ed296a3ac03fbfb71422b92117
+CT = 53228c4b0da768866855398bf4e66c3c4cb8c50891d6523245e4c619aa99
+
+Count = 144
+Adata = 7d653792bb8683e07c7d2c800db6f7f08343c85af2377115df4fc86ff7d8fcaa
+Payload = 414b6acb1db479028f5cc8800f2b
+CT = 9b84cfea2ad32e3b501dd3b2dada792d2cb93e45811a4c897ae9d907c9cf
+
+Count = 145
+Adata = 4d73c1484f9429eb15742f29ab05cbab6552abf40e127b93427d649d195ed25a
+Payload = 163f67b3766c3c650ce26c5bd8b5
+CT = ccf0c292410b6b5cd3a377690d441983a87812eaa7b66c5a0e54a01cb882
+
+Count = 146
+Adata = 2fba7a881f019a8745691343d79ef3656e25bb37b93fb5ab7311889f92010a5f
+Payload = 9c5b4aa703c27d16d82013853e16
+CT = 4694ef8634a52a2f076108b7ebe7b0afabd23b33765a63753cad66b0e6db
+
+Count = 147
+Adata = a640343fd4a866aec07b667d25176e11a32fb4d8bfc08fde2c46dc9b492fa010
+Payload = 99eb86b3202c7ce68a2339065f47
+CT = 43242392174b2bdf556222348ab639b8d0f97540373a7b9061aa3b2f7044
+
+Count = 148
+Adata = 9efd58d3ef5f74f663b2b5ca5e96c5a2fe85ca5eac1495d7f1751c7d8b412b3e
+Payload = 3f5c1d038161e65c9ed955c961af
+CT = e593b822b606b16541984efbb45e312c803e29f7be7c5eb236401037a320
+
+Count = 149
+Adata = a7d7ba684c0903323f7efc83dc32815195df325394162fb5a18f201047be7999
+Payload = be8dea2b4e602a787ecd28f2f7f0
+CT = 64424f0a79077d41a18c33c02201fd929c717d75388387dc25bfcf90b707
+
+[Plen = 15]
+
+Key = 38be46d271bf868c198052391f8a2147
+Nonce = 6758f67db9bfea5f0e0972e08b
+
+Count = 150
+Adata = c6de3be97f11d0e2ab85c9353b783f25b37366a78a2012cecf5b7a87138b3c86
+Payload = 61bd1385be92097e866550a55278f0
+CT = 7c9fa8d99b38f825315ece6a2613f55e902f296dcce870263ae50cda4fadae
+
+Count = 151
+Adata = 7c8cf9c650511f33af82e807e60336ec086bd2d9400a5f35652b8c3fcf968ead
+Payload = 7e5e51301fa44a21f2734731ee3710
+CT = 637cea6c3a0ebb7a4548d9fe9a5c15cae8a9e4b606f5fbeac2b829b42a150a
+
+Count = 152
+Adata = 5f8b1400920891e8057639618183c9c847821c1aae79f2a90d75f114db21e975
+Payload = 9cea3b061e5c402d48497ea4948d75
+CT = 81c8805a3bf6b176ff72e06be0e670f5419c6085e5434f056162cf80f6729d
+
+Count = 153
+Adata = 238d3c9d9de32f2040b1dd0dd040b921e456c3653263f4020cffdc552b948a46
+Payload = 20660408d6890aed84aa65dfe23032
+CT = 3d44bf54f323fbb63391fb10965b377fedcc743389a9d48e6b871dc0dd63b2
+
+Count = 154
+Adata = 3b5d61ca21953fdd22280747dd4ae908a511750127875da84dfe7d0063a318c9
+Payload = 9ab83c81f2d2c896c6596660c3974d
+CT = 879a87ddd77839cd7162f8afb7fc488137e0a856d3d911af9f420b68d8110d
+
+Count = 155
+Adata = 78c1751e86144a78285a30dc04f51742bd47e3d36b607bab48d91cddabfff4b7
+Payload = c1ec469aa9c73b677af225a9f5f6f8
+CT = dccefdc68c6dca3ccdc9bb66819dfd5644448fa8445b6cd185bdf9b3718033
+
+Count = 156
+Adata = add33e9a1d7e91e2c160c1123537e3f7e3535881cb4aac1a80ecbe367379212c
+Payload = 9df1d6b6debffdd316aeb27143508e
+CT = 80d36deafb150c88a1952cbe373b8bbd38e4dc44f768cef0c51344e3a7f7b8
+
+Count = 157
+Adata = df7736560b1a13aa8e536500ea6cdb9a6757309aadf25a6a9189055a309c3f8b
+Payload = 19eef017100dc82f26ed0815c55c12
+CT = 04cc4b4b35a7397491d696dab137172e7f2ec918099898b843a34c385f2a57
+
+Count = 158
+Adata = b40c8d22069b8a65cddb51c1ea3571160cacb19fd371552436b19c7122b28d08
+Payload = 2af5db43f2a5fe8b494b40661510bb
+CT = 37d7601fd70f0fd0fe70dea9617bbe94c2709685b0827cc42f3a25b579db28
+
+Count = 159
+Adata = 9de5559ea8ccc70f4375a436ce0b72551a75960ad5ed6a1949ee8f6c47548558
+Payload = 5de41a8ca8ed8011304fa9e9f36498
+CT = 40c6a1d08d47714a87743726870f9d63bf4b40ce7e672587816fdcda16efbe
+
+[Plen = 16]
+
+Key = 70010ed90e6186ecad41f0d3c7c42ff8
+Nonce = a5f4f4986e98472965f5abcc4b
+
+Count = 160
+Adata = 3fec0e5cc24d67139437cbc8112414fc8daccd1a94b49a4c76e2d39303547317
+Payload = be322f58efa7f8c68a635e0b9cce77f2
+CT = 8e4425ae573974f0f0693a188b525812eef08e3fb15f4227e0d989a4d587a8cf
+
+Count = 161
+Adata = b6fecd1edeb55a9a4148b1aefb716a1e162779a5ab2a682e4adce4479c527bd2
+Payload = 0e6118d0409751d36cb642504678535e
+CT = 3e171226f809dde516bc264351e47cbedf7f186e8d3d7c21c549c41ebcc7f505
+
+Count = 162
+Adata = 5c3933c30bf9d4841eff4000aaa1cb4d39cdf8ef1240e2aabbf9da95bdee5270
+Payload = 5c8a5fb36f860d00c21ae9e3f24097c4
+CT = 6cfc5545d7188136b8108df0e5dcb824810a68be1814f53c09aca4066527fef8
+
+Count = 163
+Adata = 7ca7ef30d3ac08aa51a9e5d3d84e8b6bb7fdde921e72b98ad6a93ebf2efc6b04
+Payload = ebd1cb4b35257790c9806be476bd25a3
+CT = dba7c1bd8dbbfba6b38a0ff761210a43cc30245a6e64625c4f6531d7497fb144
+
+Count = 164
+Adata = 90f1416768fca7dd48d01230dabf95f2f1a0c044bf2d755448aaf72316c8448c
+Payload = 842b7e5f22d921b2b8ab3131684b7eff
+CT = b45d74a99a47ad84c2a155227fd7511f10d85725dacc274034669acf7f34fed7
+
+Count = 165
+Adata = adc5c36849283d57acb2bcbc0e12465cb7c1830cb4e314b9ce6e25acbd8d460c
+Payload = f0c2cc5a1b4c4cbe839338fa0d7a3435
+CT = c0b4c6aca3d2c088f9995ce91ae61bd5f731b465eb59c4989e42020d86102a59
+
+Count = 166
+Adata = 80a7a483d1dbcdf00ed02a700e93d8b87fa6ac5c7368d1e81bd1b32cd1621cd7
+Payload = 2c1a5f906f2ae0373cc25e3519df2ba4
+CT = 1c6c5566d7b46c0146c83a260e43044484bcd2775448447ed801b3b0ff071c19
+
+Count = 167
+Adata = 13c02992992d2708250184a579c43bc29a3a8cf1e02dade4496cbd8b1214f97d
+Payload = 1da5190517546f1ad852f64263e1f679
+CT = 2dd313f3afcae32ca2589251747dd99901d1919f1451ad16f115cde863f15303
+
+Count = 168
+Adata = f6f18dfe093e4c0c3fbfa8a5b1f4a703c08addc2ab959741611a594b93d08bf7
+Payload = 13ccb08a580efea53dfba6a59626bbe2
+CT = 23baba7ce090729347f1c2b681ba9402ccae4f6ec07bf73d6f086cf09e2e14ed
+
+Count = 169
+Adata = 63708e12dfa14f192ec5ee5856dc3cf2403817d9628c31899b4613f65e1e61c2
+Payload = e0b5fbc6c2269d445a60273bf844892b
+CT = d0c3f1307ab81172206a4328efd8a6cb2bad8bf67d32a855c3940ac908397a5f
+
+[Plen = 17]
+
+Key = 79eae5baddc5887bdf3031fd1d65085b
+Nonce = 9da59614535d1fad35f2ece00f
+
+Count = 170
+Adata = 46603500af9e4e7a2f9545411a58b21a6efd21f2b5f315d02d964c09270145b3
+Payload = 001343e6191f5f1738e7d19d4eec2b9592
+CT = 2162e27bfbf1d00f2404754a254665fd9270f0edb415993588b2535e2e0e4fd086
+
+Count = 171
+Adata = 278afebc604bb7d87bed3574a2c5053de17eb8ca7e18ddc7892f2c54b38104a8
+Payload = ba47d5bfb36f6150a100e36caa116405c4
+CT = 9b3674225181ee48bde347bbc1bb2a6dc4778e3c4a11f3f9dc42554d45796379ef
+
+Count = 172
+Adata = 3239b2ce4efe4f6a6255dc53347400a6446ed3280c65422386fab471ef09eed6
+Payload = 96eccb7f9b0e16c6883de0a381e4767f5a
+CT = b79d6ae279e099de94de4474ea4e38175aab5540cc01d867f641c9b196fa159291
+
+Count = 173
+Adata = e2a5488d5f7930ea4ce399f2a6c0810265f7c0dc52fe824d19a0fa0d9ffd55e6
+Payload = d68f5990da1a2fe39ed81af145ab834fa4
+CT = f7fef80d38f4a0fb823bbe262e01cd27a46366fbe302e142dcf6aa16337d98550f
+
+Count = 174
+Adata = 0071f1edb3a0ce57af3c88bb0ccf138f752697a77e55695838fb39de04c78dfb
+Payload = cdd4d8b3d8f6e4742793b456cefc9e686d
+CT = eca5792e3a186b6c3b701081a556d0006df88c07797267bf5a49b3d0f601a225ce
+
+Count = 175
+Adata = f5d6989587e463969d97aadabea9538511f8d109cc2d3cecf09ba7cc346aaea0
+Payload = e7d7fc60ae852b68102e01b506f9dab986
+CT = c6a65dfd4c6ba4700ccda5626d5394d1865c9fbf69d81cef238ac513562d4a0dd5
+
+Count = 176
+Adata = e0b5fbc6c2269d445a60273bf844892b26fed03b82869edacd6dd7a63fd69e8d
+Payload = be9f51abfbe2da5a56db0f9a31b67c9f83
+CT = 9feef036190c55424a38ab4d5a1c32f783e2c748c8c9e3190de095de8eb0650203
+
+Count = 177
+Adata = e6bd0010c98e60b9af7cf905c58e0653bc425e2ccc809bd4f9cd7b1f95c18786
+Payload = 81b9c73029cea1936ef8755c80ba8d4093
+CT = a0c866adcb202e8b721bd18beb10c3289305cf563c5b4ba4ebd5bf107f2ad3555b
+
+Count = 178
+Adata = b1688cbc058816974694cd26c0f28ba9418e9912867fc8c5f4e7bd9c891a8d2e
+Payload = 618dc26853ee339689467ffbc2a77be69e
+CT = 40fc63f5b100bc8e95a5db2ca90d358e9e60dbbd8f46343c8442b03a472da4e23f
+
+Count = 179
+Adata = 469e004fee9878ed40621b41d04ec34af175f213d64d16e2f77d0bb2b6efe2e3
+Payload = 4f18bcc8ee0bbb80de30a9e08629323116
+CT = 6e691d550ce53498c2d30d37ed837c591643352e46995e8c1aee43dbdb26b46c30
+
+[Plen = 18]
+
+Key = c14eda0f958465246fe6ab541e5dfd75
+Nonce = 32b63ca7e269223f80a56baaaa
+
+Count = 180
+Adata = 733f8e7670de3446016916510dfe722ce671570121d91331a64feb3d03f210e6
+Payload = 617868ae91f705c6b583b5fd7e1e4086a1bb
+CT = b2dc1e548b3d3f225a34082f4391980a0788b4cc36852fd64a423fb8e872252b248e
+
+Count = 181
+Adata = b6ec659856866959ef6fd4e71ba930f0e3e5fd49d7465fd65f6813ab4ca1a770
+Payload = b8b342c49c28bffc2a1c457db0b537ad46bb
+CT = 6b17343e86e28518c5abf8af8d3aef21e08895a66eb5b902bb23a1a8584249409fda
+
+Count = 182
+Adata = 89eb3636fff80230352a3582be5698e3401c9e0579d48f2680c6e5e24d99f74b
+Payload = 37d694ba94d0af8df662134f20d142903839
+CT = e472e2408e1a956919d5ae9d1d5e9a1c9e0a7fa792fb7246218f7d56d5fa4a5476bd
+
+Count = 183
+Adata = 03434f3709e19a1e37edfcaabc215116763b71ab1c5e053dbdb599f86959f25d
+Payload = 90e4c0550cb7b279ef61f9140b7d94b8003d
+CT = 4340b6af167d889d00d644c636f24c34a60ea83dc3f0012ae6da32a15fd1684835ef
+
+Count = 184
+Adata = 0e2ddb65fcc72094ac388d53a1055c7e902285c4c3c33c13bb6fbb4f1956414a
+Payload = 69b851e63a78baef90637978e3dfe8c47be4
+CT = ba1c271c20b2800b7fd4c4aade503048ddd7f09d38d3dba01995e36bd685c8ea3371
+
+Count = 185
+Adata = a42b2538ee2fb5f6a85d4d00524b01ad3331f61c404069243f35f28e2c2d0a82
+Payload = b7dbf8382115199dd2a2d87938c6ae6c4241
+CT = 647f8ec23bdf23793d1565ab054976e0e472c89becf8d2bb935cb17f44b950df3ef5
+
+Count = 186
+Adata = 09bc5c426dc1faa4d71f50908bd6f297ec8e754d4d20def005585b4bc1fa31da
+Payload = d53698d719c51bf9eae346269c6a1da07162
+CT = 0692ee2d030f211d0554fbf4a1e5c52cd75196e28badf0202097e80561451796194d
+
+Count = 187
+Adata = 2ac87e59c2c86532cf165af3e8ff4871d730f5e742cccca38bbcdffff4472c93
+Payload = cfdb7363985aa01af6f8e8237dbfb7871eb3
+CT = 1c7f059982909afe194f55f140306f0bb880710d4d7f66660891ac655d6eca4a3f3e
+
+Count = 188
+Adata = 05d2fbc3d0ec81f52f31cb0c4bf960c2076867f6d9f0174ed9176e20177b2693
+Payload = 56fdf10dc0c1dfd10965b83938e557459c61
+CT = 855987f7da0be535e6d205eb056a8fc93a52f90ab18925fea6964490f364a975a473
+
+Count = 189
+Adata = c2c3902cfe8622254b3787cc13e79c5a3c388c2357c29f1c1ab5539a10bfae5c
+Payload = e7c9812eda2ed7dcfc80fc5fe0d43e1e5982
+CT = 346df7d4c0e4ed381337418ddd5be692ffb168a00e5e7a39b371024927d3ac98fe43
+
+[Plen = 19]
+
+Key = c5e7147f56ba4530b8799ababeb82772
+Nonce = bdd38e173fb20b981659c597d6
+
+Count = 190
+Adata = 3a069a2bfda44abbb0a82a97e5e9047258c803da2c66190d77149e0f010b3af9
+Payload = 2f3bf0b566440912a1e47a0c07f1cfd39cb440
+CT = bd6265dcba9e14c59e515e395dc60bd053345fa6d7568c738e3a7fdf142d8f2d1562c0
+
+Count = 191
+Adata = 7709132415c94960025cc39c950ead208703a9d5a71e224fd022dc0a1817d0f4
+Payload = 7c880d787726c4ddeb2304b5d161b4a257298e
+CT = eed19811abfcd90ad49620808b5670a198a991f22337efa5cb7db7240e7518b67ffbb1
+
+Count = 192
+Adata = aad77595f87a27f2c7995fc7149317f4cbebcece8336db2068380070784a4283
+Payload = 08c43bbfa706512aa39e2bfa5c365aca11e22e
+CT = 9a9daed67bdc4cfd9c2b0fcf06019ec9de623140bac6094528f02eeda093312fcf716f
+
+Count = 193
+Adata = bdb1b82ba864893c2ee8f7426c7b9a8460b00a50f164fc8f2ff2ae9cddab8657
+Payload = a531c0ed8840b2fcf08d76eca71036153b6e11
+CT = 37685584549aaf2bcf3852d9fd27f216f4ee0e0c041d86dd483c1d6da366e91bd826dd
+
+Count = 194
+Adata = 38b3b9f45041ceb743fc2655b409213fa081427e41c833a2321a09fbd566c80c
+Payload = 177946b4dc3b0b825a505f097a0a203eb21c00
+CT = 8520d3dd00e1165565e57b3c203de43d7d9c1ffde45ca2a83dec2f930bb652a6fcdc5f
+
+Count = 195
+Adata = ec9d8edff25645520801b6e8d14a2fc3b193db70d5e5e878742de83154a578da
+Payload = a2634ef20a2a418b2c3be64f0b5f79d7ea9b7b
+CT = 303adb9bd6f05c5c138ec27a5168bdd4251b648b89aa22cd7d0170a975565cd3a33dc1
+
+Count = 196
+Adata = 8f6c1de4efdc5ac2d6e5452b5b4f58416d618da672f521332fd297ede8350134
+Payload = 40e52edaad5acf2d4eedfb3f9ac2908112e9b1
+CT = d2bcbbb37180d2fa7158df0ac0f55482dd69aed960b33c3df5cd38a82980dc0950ada4
+
+Count = 197
+Adata = b0f1dc85fe223bcf29cdfa9319866bacd0a0a79c554e24d1f10889279e31c0af
+Payload = bf97780f498c23adcf1c49f60873780a235969
+CT = 2dceed6695563e7af0a96dc35244bc09ecd97638fa273c4102b5ca050b23044ac2064f
+
+Count = 198
+Adata = 7d02a323aa769a8201549bf48a520d940bf6f69ed6106f1ce68856c22a594216
+Payload = 58bfe1eb2d38d91f80b3467db94fdcb84ff5f3
+CT = cae67482f1e2c4c8bf066248e37818bb8075ecc15438af1bafac3eac61e1c24ed00ab7
+
+Count = 199
+Adata = d4b90ef8abad08c552c8c3b080b8c37df314d514049d45e27ec4527cb06cdf85
+Payload = a206a1eb70a9d24bb5e72f314e7d91de074f59
+CT = 305f3482ac73cf9c8a520b04144a55ddc8cf464422d9e2f4f84fde49e9701296294d5a
+
+[Plen = 20]
+
+Key = 78c46e3249ca28e1ef0531d80fd37c12
+Nonce = 5de41a86ce3f3fb1b685b3ca4d
+
+Count = 200
+Adata = e98a77f2a941b36232589486b05f4278275588665a06d98aec98915cc5607e06
+Payload = 4802422c9b3b4459ba26e7863ad87b0c172cfe4b
+CT = daea2234ea433533bf0716abe1aa3844b6d3c51e9d5ca3d8ec5065630d2de0717cdeb7d5
+
+Count = 201
+Adata = 5970a836de1f1e91d94d7eef79742cbbd46a759c413715eb0224fd6a27145333
+Payload = 796a69ad0e9379173ef6b66f44f5c84fa70a0e28
+CT = eb8209b57feb087d3bd747429f878b0706f5357d0ff0648ddb07f42f815b38bfc95688b1
+
+Count = 202
+Adata = e3f08834c4894f6fa66a55a280c0e677a79e97c1ef9488b21384e74e57b1b51f
+Payload = 98e1f8cf250183b13ad418024dc40c1a6a7ee8ac
+CT = 0a0998d75479f2db3ff5e92f96b64f52cb81d3f93ddd9a6977ea8e7adf5c5234346e560f
+
+Count = 203
+Adata = 18349be2894d49290339b97f4db28c92b3e112ffac77100abbf9c093935b1a46
+Payload = 4a856d9b50a5b40d6566b38eae6a53ed0c192805
+CT = d86d0d8321ddc567604742a3751810a5ade61350bdee05328a7ea8cc6c2e42bf3faeeda0
+
+Count = 204
+Adata = 7355e34ad13880de17a1d66b02672ea5c9f51774019f64ecbe36747ffcd9b671
+Payload = ad048eb2ad75266b43b59d9d1f073c44e4cbf25e
+CT = 3feceeaadc0d570146946cb0c4757f0c4534c90bafb1435cf929db35ec5986aabaf4a7d1
+
+Count = 205
+Adata = 4be21ba2eb26234ddcbb6aac6b4c3be7ef644af64edf51b7c29ffc3ddd80036b
+Payload = 5b527ac6cc6d1b4c3c56f8315bc96dae91632df9
+CT = c9ba1adebd156a263977091c80bb2ee6309c16ac736be6563cf9f5bce97486b7cc6f1c18
+
+Count = 206
+Adata = 266e0e3365e06d3b1e864c6e5897145df7bdde90eb744013a7b36632d4cf6580
+Payload = cee059cb0fe91a39faccc2914340baeab4b644ce
+CT = 5c0839d37e916b53ffed33bc9832f9a215497f9b2e90335fcea56b969b4fce65442768dd
+
+Count = 207
+Adata = 55a723883a340877d85ad1a5f264f2c834d824c7bbf207cdd8500c9d11ef9225
+Payload = 85321fef6a2b7d31cbd079c4bf2bfbbc979df90b
+CT = 17da7ff71b530c5bcef188e96459b8f43662c25eacd6afdb3578ebc75e8a408d32758931
+
+Count = 208
+Adata = 773864475a1a60a778468a66cbe13dfe3458094e62abb593f50c8495e3a8b81e
+Payload = e227b8d44320bd3ce9d3f7d688f3de887947b1e9
+CT = 70cfd8cc3258cc56ecf206fb53819dc0d8b88abca19fb73fc0488d9f29a09c1b47e3e066
+
+Count = 209
+Adata = f64f3b00c9117aed3c486aa4c8d574b44d679be4069e1078bb7100af38cdb190
+Payload = 206e9eb2bc3f8534d844a38debf1306df808744a
+CT = b286feaacd47f45edd6552a03083732559f74f1fce2c5ef8cdce76b358739e2a1b173fb3
+
+[Plen = 21]
+
+Key = 8883002bf13b3a94b2467225970df938
+Nonce = 818a702d5c8ee973b34e9acda1
+
+Count = 210
+Adata = 545aeac737c0ca2a3d5e1fd966840c3a0d71e0301abbe99c7af18d24cc7e9633
+Payload = d516bbff452e7706c91c7ace3e9baa76d65ff7050f
+CT = b85242fdc06344f2bd9a97b408902ebcd22aece3d42f2da4dd4d817c9fa2d44bc02163a0a9
+
+Count = 211
+Adata = f032db01da60ca078d35c3fb5d05d6750fce1c01911a0422e827e8976946e4dc
+Payload = 590d1aa655fed50ca2e402299f2da6fe20eed56071
+CT = 3449e3a4d0b3e6f8d662ef53a9262234249bce86aa180f41bccbcd47c8b7890754c032269b
+
+Count = 212
+Adata = 71ecb4252518997b53491cf42a3e0fe1496a2af2329a16f9fcd9c4f249900341
+Payload = ecd86cdb7d78d310dca5b477cd9da2612f5a05ab39
+CT = 819c95d9f835e0e4a823590dfb9626ab2b2f1e4de21d6ba58cc2eb474401851bf9502c3413
+
+Count = 213
+Adata = ec7abed9bda4a52fdf1bf278b6bdd6b0a27d4688deb9ff5ca9c8c865a4d2f730
+Payload = 0024b14c283df032cf80c22ad8d2c96289ee229092
+CT = 6d60484ead70c3c6bb062f50eed94da88d9b3976499b94d4b7a2044696c72322e850537b6d
+
+Count = 214
+Adata = c2c77d7ad7b27d7c0f976a1e28881ea4ec7ad03b63a4e67f47280a40b8f58086
+Payload = bc6965d8f62d066d118c14044c1fd2a224b9d95110
+CT = d12d9cda73603599650af97e7a14566820ccc2b7cb9d8da8e718570caf8bed7909fbff3ec6
+
+Count = 215
+Adata = 28929286bd1391468ac75f5c03689f74780ddd7585fc16f9a9bf7b00357a72e5
+Payload = da4a630cabaff0728a1cc3e6a79721a7176b708f1d
+CT = b70e9a0e2ee2c386fe9a2e9c919ca56d131e6b69c6e671012690c61fe3c9abd50a78eb4736
+
+Count = 216
+Adata = ed360d22081b019dc979420a3a45c21c8903c59daedd9f1b4ef2bfdedff0ec1d
+Payload = a95058f8e1f6bc0f143a9ca7e4425a2a63eb2f7e33
+CT = c414a1fa64bb8ffb60bc71ddd249dee0679e3498e8e657e2250427130acef7032454cde7b6
+
+Count = 217
+Adata = 2b4022d0b951fe48635d04fb3e2fa032c07c855fdd73f45670953bb9ddc77cb4
+Payload = fcbbc7f9d1ace60e830ca56ec84814fbd2579993d4
+CT = 91ff3efb54e1d5faf78a4814fe439031d62282750faac6ff0a264b8199550d93c1f06063da
+
+Count = 218
+Adata = 48e553a87a7d3c1bd68af39f96aca67583da86e06701d5e4c4ed404dc66d70f3
+Payload = b95d298d391c6b893c6cad66f9780534516e71455e
+CT = d419d08fbc51587d48ea401ccf7381fe551b6aa3857e68bf636e81c332f72063dc0d6fc2b6
+
+Count = 219
+Adata = e8e2835e47144365a2f218d4c95d7522e824fb43b66d4727ee570f8303dd6dd3
+Payload = bc79d444dff9d9e722effab07b068cb7723ae8fae0
+CT = d13d2d465ab4ea13566917ca4d0d087d764ff31c3bdf3af9e9c4e04bad261dc17cf00a00dd
+
+[Plen = 22]
+
+Key = 5cea00ee44cfb9cfbb598d3812e380ef
+Nonce = 948788a9c8188cb988430a7ebd
+
+Count = 220
+Adata = 50422c5e6a0fb8231b3bb6e2f89607019be6ad92a4dae8e0fe3f9e486476004b
+Payload = 33bfd0713f30fcac8f7f95920ac6d9b803ddd5480dd8
+CT = b168747dea3ae0fbede4402af9a3dc3185d6d162f859d828101682de32923788c70262b84814
+
+Count = 221
+Adata = bb0036b34b0c20094d335a8c74f6b3dea42eeccf4145192eada64ae00c726b2e
+Payload = 5576d94b577ed26820fb13c00ab0e2d1a1c3589bfdc4
+CT = d7a17d478274ce3f4260c678f9d5e75827c85cb10845bafc4ae4d31907def6f648b081174e2a
+
+Count = 222
+Adata = 5140324aa758dbbb5391b5e6edb8a2310c94a4ae51d4fba8a7458d7cc8488baa
+Payload = 13303e14068205cbfa992d4ccb6a265804ea64a15d7f
+CT = 91e79a18d388199c9802f8f4380f23d182e1608ba8fe314e378e9ed6e725a14c07632b02bdbd
+
+Count = 223
+Adata = 74da07d324060e590356988f27d9879fa3a3ade0fe71e2a0e49054211cfa1fe1
+Payload = 567e6d14b446add630d53ea86a537c0938537c4604a8
+CT = d4a9c918614cb181524eeb1099367980be58786cf1295bc2f2f9331536f7f70be09c41bda0ad
+
+Count = 224
+Adata = 0e403cff47adee3ec5bb6b178dabfc7d53b60a04eaad33a2fedd9db705358a4c
+Payload = 9f3d165d44cf1c5770346d211d4ff34ca2ecd6b28549
+CT = 1deab25191c5000012afb899ee2af6c524e7d29870c86b59cc9c3c008bc5876ef86327859cbe
+
+Count = 225
+Adata = 211e6ce3d0c3abdef069e6e4fa35015797bd8a9d64bc9b75f20b028b12cca04a
+Payload = d726e599db6a6d40629bc4bda5e3fa2e5aeda229cea4
+CT = 55f141950e607117000011055686ffa7dce6a6033b25135e6d59a5385a78658d60d254f99962
+
+Count = 226
+Adata = 3c5c67b083322115e1b3112c2b6968efc050094e23e646dce982eac9d6e67d10
+Payload = 42646cfb8a99e48a35cee3f5f9b3e6175695973f6de0
+CT = c0b3c8f75f93f8dd5755364d0ad6e39ed09e93159861e234e83d9a0570dbf2b2fa59ce3cdbd9
+
+Count = 227
+Adata = 37a931f1dd05755b376d1a164aa36b8de802e39f8108a0453c1114754665fe46
+Payload = e814c7b5c72d973a9bc7ccd463f107325ffa3321783b
+CT = 6ac363b912278b6df95c196c909402bbd9f1370b8dba2084e352b1b157267228576dd056c1a3
+
+Count = 228
+Adata = f1ddc2c49da7363526ba36c600c589b4c3121fbb8c5b9a8aa0de0e7453b30568
+Payload = 4f7a5618870945b89f194e31b1aa802c5350326dc691
+CT = cdadf214520359effd829b8942cf85a5d55b36473310bf88ad35ee338e489e55bb49732447cf
+
+Count = 229
+Adata = d14b3d3803df432488b5d66704abef6a500d397e855bc2c2574df746a515cf70
+Payload = f555216840a1f40b411d44128e567617e2694caf1621
+CT = 7782856495abe85c238691aa7d33739e64624885e3a07ab67f9397a81371ef6ebc775cb7007b
+
+[Plen = 23]
+
+Key = cb83f77751e72711401cbbf4f61aa0ed
+Nonce = c0b461b2e15b8b116ef9281704
+
+Count = 230
+Adata = 2bd112231f903fa0dff085db48a2e2a96ec0199249b005d5ab4c2eab753f9ad0
+Payload = eede01b08f9a303cdf14c99d7a45732972c6eff2a1db06
+CT = feb114b7bd3b43497b62454a675a632c3546d2802462c6af57647efda119c59862cd5dd3904efc
+
+Count = 231
+Adata = 864e0e728aea856fae6c6daa6357d1542cef7177f441ba21a563f6c4f6fdc1dd
+Payload = 8a56588fe5e125237b6cdc30f940b8d88b2863ec501a0c
+CT = 9a394d88d7405656df1a50e7e45fa8ddcca85e9ed5a3cc2af4027ca5824b41c7bb238d3e8eeebf
+
+Count = 232
+Adata = dac7f3cba0b5a47f67f85b226b66df695a8ae2501355e36aad105375bb95f732
+Payload = 66e34540d7accf377877aa2d3e6d2db0cfafc608a1eb3d
+CT = 768c5047e50dbc42dc0126fa23723db5882ffb7a2452fdf7fbd7044ce1d7b266bdf545247a3c2b
+
+Count = 233
+Adata = 07f48cdc12aa27119fbdfda4ec07ce6068c92ba7ba9c930905aadd156b1dd56e
+Payload = a9ebd04fba7155c39b5c29c5571b5354c9ae228f5e5b13
+CT = b984c54888d026b63f2aa5124a0443518e2e1ffddbe2d3afabc559b552cf7c7730c7dca25bc3ed
+
+Count = 234
+Adata = 2d24e79abd157af2c21b60932947fd9f9d6478f09ec56fffd341ea04a17b8e5f
+Payload = f179353aef342f0f691caf1fcb811e3f6504e14d6d9381
+CT = e116203ddd955c7acd6a23c8d69e0e3a2284dc3fe82a41488ca99e0f85ac388f981ce25560b8f9
+
+Count = 235
+Adata = fea280f710379e4665b5ed3d1620729a7bc164899dc83e6aee3612d538fa20db
+Payload = 6c19a18eab544acc883c5886eaa89f54d61ae5f1f1368c
+CT = 7c76b48999f539b92c4ad451f7b78f51919ad883748f4c9156faae3d8860bed216e8d497a75962
+
+Count = 236
+Adata = 18f2e3457127c35f2e0cff2d821af8178028fcc7803bc795c49f4a435b37abeb
+Payload = d0df1bdf1df6203241722fb9c9c1cf7405017497ae1545
+CT = c0b00ed82f575347e504a36ed4dedf71428149e52bac8588cd7791c544d1098b2de49d04b1e0c1
+
+Count = 237
+Adata = 35221f0efcb109cb93c38a62c58b5ab8b236437e171e8507cf417a569af1767c
+Payload = 479526b33c42c240b9a4549ca70cbfb691f16ae3be8888
+CT = 57fa33b40ee3b1351dd2d84bba13afb3d67157913b3148c523fd8a2524717f63dac75c22268fa6
+
+Count = 238
+Adata = 95f2ab02af01aeacce86b02cf846f9fbd516963d06e350e8b7f6df2778765a01
+Payload = aa6761148b254a2ff202b620c2ec2c5e623bf61f05e483
+CT = ba087413b984395a56743af7dff33c5b25bbcb6d805d4392904f05dc2397596543df73de5aa708
+
+Count = 239
+Adata = 3746a36154e42dd600049d506f5ce4d034864263b1a65cecd24c8e25fb9c82e1
+Payload = 2f298f106703b8a994cbb20acf47f9442e44f6b5e82c38
+CT = 3f469a1755a2cbdc30bd3eddd258e94169c4cbc76d95f8c3cbfecfa3f75fb111ef0011222b7948
+
+[Plen = 24]
+
+Key = 43c1142877d9f450e12d7b6db47a85ba
+Nonce = 76becd9d27ca8a026215f32712
+
+Count = 240
+Adata = 6a59aacadd416e465264c15e1a1e9bfa084687492710f9bda832e2571e468224
+Payload = b506a6ba900c1147c806775324b36eb376aa01d4c3eef6f5
+CT = 14b14fe5b317411392861638ec383ae40ba95fefe34255dc2ec067887114bc370281de6f00836ce4
+
+Count = 241
+Adata = e82fc3ffd276218a82aede65fe5abf4fd35c7059a26923f8dbb97a59c903a7f4
+Payload = eab8cef576816a82ed036f158e5036f5987b195e60582a6f
+CT = 4b0f27aa559a3ad6b7830e7e46db62a2e578476540f489460d2d30268e9f1ce0e7c762993297d828
+
+Count = 242
+Adata = 776aae7f62225556b6da522c0c9432ac70fe72ac6f3f361071ef3deb4a6715e8
+Payload = 566ef9ce1d397be2547c385639507a9e7d6f9eed9a3b1055
+CT = f7d910913e222bb60efc593df1db2ec9006cc0d6ba97b37c0939e56f0b7200d1b1409f3f8e8179cc
+
+Count = 243
+Adata = d9aef0955922f89747ba4a8ddcdb8c1c7579aefd3c2eb8ad0589c66576a8504c
+Payload = 8c28b6d93b23f1ea031d5020aa92f6608c3d3df0ee24a895
+CT = 2d9f5f861838a1be599d314b6219a237f13e63cbce880bbc138e3b817023993608be06fe92efca8b
+
+Count = 244
+Adata = 13c222a65ce30570ecac85a185a2a0922a8c96d633339a1ca067ce57ae426e1d
+Payload = f0c1cd60f5fa8d1efd5e2e1ab37c4f7e6aef76d15e8d6ac8
+CT = 5176243fd6e1dd4aa7de4f717bf71b2917ec28ea7e21c9e1f3ca13b4ab7fd0d4badf158972570c06
+
+Count = 245
+Adata = ce40fb0cbfdf07676ed55b040ae6be5db8f0a0f28816ae8ea71da3cbd71661d8
+Payload = 570d5f79aa8db14b1ac99ee567cc105ae9e238e482b52628
+CT = f6bab6268996e11f4049ff8eaf47440d94e166dfa21985010a79fa4e8b27a31ff360a1b6c05ff844
+
+Count = 246
+Adata = 446b01d09cbc41b6393ef81ca65ab7e099018187d5f9d22f5074dfc491e72077
+Payload = 7c267223047af946b06f6a45ffde4a5ec49c28b81ca22da4
+CT = dd919b7c2761a912eaef0b2e37551e09b99f76833c0e8e8d5d34ef0ca0b47d6a2ec7442cbb739504
+
+Count = 247
+Adata = 01ec87920b42639d4ba22adb1fbe5138d2849db670a2960fd94a399c1532ed75
+Payload = cbf112e4fb85276c4e09649f3de225b2398e86ac3fe48bc7
+CT = 6a46fbbbd89e7738148905f4f56971e5448dd8971f4828ee8f607d154393e35fd1efc1ae8cb244e4
+
+Count = 248
+Adata = 5032b818d202872f3fe2b08fc7940696df02cf393a6d6247f5c6f5f2125cb08b
+Payload = 4324a89788e8ddae5d560cf937df701743cbbc3bf980558c
+CT = e29341c8abf38dfa07d66d92ff5424403ec8e200d92cf6a5617d9cebea38591a00c9fba4ef9c8e71
+
+Count = 249
+Adata = 27b661861717f00a3ae22ead78f4dc3f32b40e8fcb8ed58167a31a61f2becd77
+Payload = db72d98d63fc10acff7dceec0e2691a80ecee50a0e957ad1
+CT = 7ac530d240e740f8a5fdaf87c6adc5ff73cdbb312e39d9f897062a1ec759a515b938780f902fa7c2
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT192.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT192.rsp
new file mode 100644
index 0000000000..abf1775dd1
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT192.rsp
@@ -0,0 +1,1383 @@
+# CAVS 11.0
+# "CCM-VPT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Nlen = 13
+Tlen = 16
+
+[Plen = 0]
+
+Key = 086e2967cde99e90faaea8a94e168bf0e066c503a849a9f3
+Nonce = 929542cd690f1babcf1696cb03
+
+Count = 0
+Adata = 58f70bab24e0a6137e5cd3eb18656f2b5ccddc3f538a0000c65190e4a3668e71
+Payload = 00
+CT = 3bf9d93af6ffac9ac84cd3202d4e0cc8
+
+Count = 1
+Adata = 760d065275e345900a7bbab451cc9309fb161e6cfec526538b98800e4102e14d
+Payload = 00
+CT = b0078a769ab68db44e723993da382abc
+
+Count = 2
+Adata = ffedc67efd355ea404fcbcb3993d3bae81386ded86230270771deb747163bf44
+Payload = 00
+CT = 31fbff2d715a2eb9af54e8320a8e42e1
+
+Count = 3
+Adata = 55153ff5e4d208d2e647794f382c788e0e36f293e63e7290ba9ff2657ae0f167
+Payload = 00
+CT = 945839d62c9d1b899f6dcd0ca9517e68
+
+Count = 4
+Adata = f8813985f59bf284bd3882e899ca9b67fb496f3eb78d7ebe6ffbad084f639915
+Payload = 00
+CT = 903f90d23321a6882d6c4c1955b14847
+
+Count = 5
+Adata = 7b95cd827ab93507f1819ae76627d6e2a31d29890c092e5c300f0e2f9e4ef4d2
+Payload = 00
+CT = 652ec5ab43088eb568186d0d9887b30f
+
+Count = 6
+Adata = bd144c9bb974729aaa1188ceefdf85e1d9fddc0b0c8afe8828ba204aa9293feb
+Payload = 00
+CT = e6c1455d1117eec49338c96f51007309
+
+Count = 7
+Adata = 92b911cdc3137a6f7f32651b788eb82975660aea52b2c03b4759755a6da4a0f8
+Payload = 00
+CT = 1cf3c32fb229dac209523eaa517bb59a
+
+Count = 8
+Adata = a8200dbbfe4086015cdbdec2fc8e4934d0d663527430c424627ed44065ade091
+Payload = 00
+CT = ee10bfeb1cf9b3cd5a0faebd4d8f3fe1
+
+Count = 9
+Adata = 3b7f37b6b8e3c1390a99d59c47f7c102cf659d361a132ef8b4e70b9585bafebb
+Payload = 00
+CT = c51ed994253adb9bb5b9a8c34a27f225
+
+[Plen = 1]
+
+Key = 992d38768b11a236945bd4b327c3728fac24c091238b6553
+Nonce = b248a90b84b0122a5ad8e12760
+
+Count = 10
+Adata = 27cabc40da0e1eda0ea5f8abbb7c179e30776250a7b30d711b0e106c5ee9d84a
+Payload = 1c
+CT = 1a96f58c3f38c44d1a345f3e2da6679f20
+
+Count = 11
+Adata = dc2e28d5ae726c1beadb1e7e92ae7d14f5546320deb81a910bf170cbe0210eaa
+Payload = e9
+CT = ef0579aee7c17482691f3f832d867ffea7
+
+Count = 12
+Adata = c579f912ac1b45d5aa8cf20f78f0a1ace32abd3dc7fd0b3f3a7182a008795c7f
+Payload = 97
+CT = 913452d8ece38ffa1d4107d6a053acd8c8
+
+Count = 13
+Adata = 69ea953dbb910ec589372d797c7379d3f3b9e9fd48894c9b55e6e8eb360a6211
+Payload = f4
+CT = f20d760b9fe29530738157db0ba2d253f0
+
+Count = 14
+Adata = 622835dea57b2c70cca8f7548d6210714070b55b36adde7a4c547269c07aba9c
+Payload = 9f
+CT = 996fc21f24dee7b52f51d69eea30819f4a
+
+Count = 15
+Adata = 67ebda0a3573a9a58751d4169e10c7e8663febb3a8cf769d81bc872113f0720f
+Payload = 43
+CT = 4594c5b8db0064426a77dc536814c56147
+
+Count = 16
+Adata = 255412e380e9a28cbcd345be172c40f72dec3e8a10adfd8a9ab147e9022524e1
+Payload = c1
+CT = c76d36c0b0d699a22da3116dfb8f453181
+
+Count = 17
+Adata = c7c8e7151eb6844a954d091b460f83add0f0a634aa5ac213b774f2451aa497fb
+Payload = 31
+CT = 370c3a1690acc3f0eb09c9cfd3396c7fa9
+
+Count = 18
+Adata = 63f00b2488809fdc49ca5f05d54e98468906308115f7e702da05ddfd970b5537
+Payload = a7
+CT = a1ad45070fe4c61270c13cc52247fee411
+
+Count = 19
+Adata = 8e2c5e55c0bf70014e9897b6f6940e4e738b1e84e8269b6382f0b1fe59b0e162
+Payload = 40
+CT = 46b2a2a8b283ff7eeff5c2670f77b8809d
+
+[Plen = 2]
+
+Key = 5012db40ff6ae23c1e1ce43768c5936c4400b0e79ae77f30
+Nonce = b67e500b35d60ad7264240027c
+
+Count = 20
+Adata = 40affd355416200191ba64edec8d7d27ead235a7b2e01a12662273deb36379b8
+Payload = 0c6c
+CT = c996ef3d6ef9f981557506ecc8797bbaaaa7
+
+Count = 21
+Adata = c5e12e17e02bcc12b3a4c14cf837250e2886db3ee1c717d28bd11e8a3b764ddf
+Payload = 23df
+CT = e6254405257a837c5343b59d5689d6de5269
+
+Count = 22
+Adata = 213b5b6015d472bd593be5acf85ebba6d6a09f3a962be302ba83c6d70c61f241
+Payload = 0dc2
+CT = c838e93e67d37d2367bb1f27f71b54b29317
+
+Count = 23
+Adata = fc1b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+Payload = dc88
+CT = 1972ca3744a4ab375af9060621a9dc4f4c32
+
+Count = 24
+Adata = 5b2eb1a6fa585d61d1fb3da68f5b93829c8e2d5e4fe03782617553d7a130ecf1
+Payload = 8179
+CT = 4483172626e930d24052bc056d8609c4175f
+
+Count = 25
+Adata = e2b3c3bf33cf847660929e48cce51d9d9289945169651aaecb1e939756e93105
+Payload = 01fd
+CT = c407852310207be8d3417de800b372700da2
+
+Count = 26
+Adata = 6051f12cd8aae68b4023aaf7178fd086aa582b8d8821e36637abc97025f5e858
+Payload = ca18
+CT = 0fe228553bc037954dbf4ce5db99792c2c7a
+
+Count = 27
+Adata = 2d3555faf285caaddfe95c010c2a7f233e09c2fc0cd30d644035269280527ad7
+Payload = a855
+CT = 6daf904725668634d6345bd8f90a3831b452
+
+Count = 28
+Adata = 4fca820dc545bf93bdffed33a04b67eb45384e696f092c2197e5d79cecd09913
+Payload = 5555
+CT = 90afdf6098cb3135c3045a54ffce88efaceb
+
+Count = 29
+Adata = 1789ae403e183d2225f431f001d475b53bccdec66572bb027340ae592839ba8b
+Payload = 11dd
+CT = d4278568e8c08ff5ee5ea0a608589c2fc029
+
+[Plen = 3]
+
+Key = fa15cc7f0de294d7341b1fd79326c8be78e67822343c1992
+Nonce = e5257aed2bda0495aa44591db4
+
+Count = 30
+Adata = 31a0338c3839931fa1dd5131cb796c4c6cfde9fb336d8a80ac35dec463be7a94
+Payload = bcb898
+CT = 68f08298d9a2147776dca9c1a42382bce323b2
+
+Count = 31
+Adata = 4863dd810ee70ef0f5da81f60c5ce550abb96454619032322e34657af25207de
+Payload = d1da2e
+CT = 059234a9a77755b324f3a557217752ade14ed7
+
+Count = 32
+Adata = 173594fc26b167f044aeaf9bfe920cab99a27eb2b01827d61f7553cb2018b5fe
+Payload = 394f31
+CT = ed072ba4441a79a90e228a28069fe109d5d876
+
+Count = 33
+Adata = 71cdd16eca9255aeedc23bd623513918ea97da21485074415fe75bcc42f454c0
+Payload = 868bda
+CT = 52c3c065f272f44c5210b5bcc571e819580910
+
+Count = 34
+Adata = e84418d332d16d2298e69e7ff3c37bc7b6e030cc822e73b3f4a0029bc2ea4d80
+Payload = 52d6bf
+CT = 869ea559c5f7f73a1b5f419c9f63ca401894a8
+
+Count = 35
+Adata = 42d962109bea1d50be0f3d83b4c2a6033d53b3d7112591866b1ae52dc84cb5d0
+Payload = 6f8d58
+CT = bbc542220b828cf5365137fb3f1df67cc8d2a1
+
+Count = 36
+Adata = 943b4327b5c70dba63c82f27e0412b3ada012bc0f7dd39ebb13db2f864daf80e
+Payload = fda286
+CT = 29ea9c422b0f41075ac79a0afa2d1047cbbfb5
+
+Count = 37
+Adata = 6076b94caabfa476ab7e6482e4fda9b29f2e2b2883efe44d668c7c74628505bb
+Payload = 8651fb
+CT = 5219e1ae68cd6d6815ecbfd01293d160d4d38a
+
+Count = 38
+Adata = 3e4bb5781f84b4bbd23583e3dae561c6ff4af8eff35e2a4f35b50d2f360d3469
+Payload = c3e179
+CT = 17a963fbaa81cfdbcaee476860cd5102f556e4
+
+Count = 39
+Adata = 364008acbad330d0b8d574641a97b0682c49279cfdc80ff309b7514514d18a44
+Payload = 4a97d5
+CT = 9edfcf7ad1520564b68824a3a939371c21a336
+
+[Plen = 4]
+
+Key = b5330a8447d74a7987fb718cfae246b5c7e057991064eeaf
+Nonce = 2ef29d62b40d8643848797cde8
+
+Count = 40
+Adata = 1225b036e6044df52314016760e92750de0936120395de750a2c54a7fa0cea82
+Payload = b46b343e
+CT = c2c39d6f9344e2de064f269d065a2a6108605916
+
+Count = 41
+Adata = aaa6257d6783936a4445833c2ac3bea8cb7334f22ade9c035d515bbc91d6a78a
+Payload = cb216301
+CT = bd89ca50693d90b8297b90bc41c231d08b0204fb
+
+Count = 42
+Adata = 1c1915fab09348b9a5536495c70d1a040305708c1124797e564b63e008e7b8ab
+Payload = 697a8696
+CT = 1fd22fc79d0146fe373437c529fb2eeb169e4bd7
+
+Count = 43
+Adata = 864d0f786497c7ce283762ca0959ec9c825ed445a5dbe5b4b2e5772fe88ce7f5
+Payload = 6bee3db9
+CT = 1d4694e8e389c549bfc4ede936d7896e544b23ad
+
+Count = 44
+Adata = d5388b0b548c58886dcd335dff2b1ed23ce3eebbb708fb5bbd831c83e959d3fa
+Payload = 85d95855
+CT = f371f10495177a9fe6d9329a585c8737c92a4d29
+
+Count = 45
+Adata = 83cddd189736f224cad6a29efba45e43c75450a14f1541713b7fb926ffc768c6
+Payload = e8b23340
+CT = 9e1a9a113914431a10b1f94a2b99b9e442f3dca4
+
+Count = 46
+Adata = 8fccbd1fc5240691cf24e8807bf3416c1b2d87fc86dbf3955fa2e52b9a3a8457
+Payload = 595c4d7c
+CT = 2ff4e42d383d8dc98b22010dd93cd0cbb396d9e3
+
+Count = 47
+Adata = 513d45f6f37f3f051667dc743215059e06e4fdc8945789b16d50556a2e839368
+Payload = 314e0c7d
+CT = 47e6a52c40c513bfc92d1a7db5ed7cab2d8212b0
+
+Count = 48
+Adata = 70828be102e554f0d4b07641fa3254bc8db06eefaf5b85a7c97e01c217fc8f3f
+Payload = 35753e32
+CT = 43dd9763ea98f4ac6b3eabd483f1e6ab92f3b83c
+
+Count = 49
+Adata = 343d5a4ad39acf81adcf24e9807618932abcb3bc076734f179174c77c8cb89e9
+Payload = a531c0ed
+CT = d39969bcf99fb67b1e2aba2d232db2445e6aec2a
+
+[Plen = 5]
+
+Key = 30419145ae966591b408c29e5fd14d9112542909be5363f7
+Nonce = 27e6b2a482bbc6f13702005708
+
+Count = 50
+Adata = e04e81e860daf9696098c723085d8023c240ebe7a643131e35359ab04bd650fe
+Payload = 8ceaeb89fd
+CT = ec9d5ed36243ddf77b33d8cf2963ba76fd4e19f3c5
+
+Count = 51
+Adata = 6217cd581d4b3b2f7bcf1b8dad9ad6430e2e3a0063cad52260e0a1cd6fc9e73a
+Payload = 7e51d6f870
+CT = 1e2663a2ef6b73fe9e638e205b27f78ed1bb9b0ed0
+
+Count = 52
+Adata = 8aa7847e496f5e9f1f87851442de844f27a21c1b48f82fe525f0dd5a88b8ec38
+Payload = e0023b674d
+CT = 80758e3dd25936115e23158aff1916edec241fad56
+
+Count = 53
+Adata = 3612abc865a4d8d7b86a84109388584df6526525adb1006ec6c8d00048d725bc
+Payload = e2b5b6f36e
+CT = 82c203a9f1f15aae4b70dbee244be1daa74475d7e2
+
+Count = 54
+Adata = 849a99c6f1cae0ad4bcde4bd0811e87ca5ed7b913de1a8285a206e980b4b7043
+Payload = 9a17e4a22a
+CT = fa6051f8b5bbff424487848385f8501ab5a77f327c
+
+Count = 55
+Adata = 9066367c784de0a4d1116bbe95ce55ded85edddb6273c2049ee24e0fb3429352
+Payload = d4e765fc78
+CT = b490d0a6e772d8d5da6f593a8d9956731b42645aa9
+
+Count = 56
+Adata = e7aa9f767fa8920f96f91c41d9e86755faaedaeda596a444b65f99b7a9e23e85
+Payload = 1074349e10
+CT = 700381c48fe3eca12b835dcfd08166ac8831585626
+
+Count = 57
+Adata = bc0db1ebf910b6f4dcad5401401d6bc2272e23130947dc236ca664d5b5ed6d66
+Payload = a46dd7fb58
+CT = c41a62a1c72bcce66018e9e552d2c8a229301361df
+
+Count = 58
+Adata = fcbeba2d0d73239d05f691a52b08152c9dd871f8dc76c2c18b8a638a74460d31
+Payload = 2e0ca09221
+CT = 4e7b15c8be3e41a50a28ea3be14baadf12964a37c4
+
+Count = 59
+Adata = dcdefce64ae4339f46c0759a4a10b29d59daaaf1e5dbf75cf11b4e4f73c5025f
+Payload = 2e108ce0fa
+CT = 4e6739ba65bee2ab25bfafa76dc3e54832b2f76864
+
+[Plen = 6]
+
+Key = 748ad503388a34041a7bdae6361d57894357c333bacf02ca
+Nonce = 518b79d194579b19f2d8845b70
+
+Count = 60
+Adata = 691dd98f61fd213b0840ec5a6f06ef9a1420be0d59bde5e43546347a2a865a94
+Payload = 24d6880aed7e
+CT = 270120f9634ec15536e21d961c675070ec4cff9037bc
+
+Count = 61
+Adata = d1fd047cdb18463766841abb1fcd25257f1458b595bfcf24066ff9385232fa97
+Payload = 2298028d0213
+CT = 214faa7e8c239b303af0b098f902dc24e66fe56adc6e
+
+Count = 62
+Adata = 65a480d120a0459dab69e8f23094801e10092666cc56f9fb2549662982bda6d0
+Payload = f248e5225e3d
+CT = f19f4dd1d00d1b657925a9740d6828bd85cd12205764
+
+Count = 63
+Adata = b738a53fbc9689dd49f68f97f5a99665258cd52e74dc653b594cffec045508aa
+Payload = 611dade00cec
+CT = 62ca051382dc395a1c49129ef6cce0ad5f6ef378aa1c
+
+Count = 64
+Adata = 7006f54184f0ff0ab215ca408d46325b86c1cbae6da7838435b1826ff81f55dd
+Payload = 5871a8300471
+CT = 5ba600c38a415e68468d1b2b516be3d688567d84ab80
+
+Count = 65
+Adata = 9e6e6675d4c6b1e0f3894aac071f4c99a364708edea12f319cbc27b40fabc0f1
+Payload = 3ca8a7520e94
+CT = 3f7f0fa180a40ba1af163049d16817021665d183bc9e
+
+Count = 66
+Adata = 10ceef716f54b74d7c8a435d6aa38a10ff23939ca29e2de7b6c3e0a8269a23c9
+Payload = 9c2a0070fbba
+CT = 9ffda883758a670f35869da9821b6ff1fab3e6062ad4
+
+Count = 67
+Adata = 3ee0865f29be50160273b4a94ec078932b9cd10a858e31838d5b607867e1ce69
+Payload = 436179c74fd2
+CT = 40b6d134c1e208f395250fd79087c858b83755411114
+
+Count = 68
+Adata = ec2b8bfe1ccd491b02aa4a9178fd6f099556963e39e2ca5fe6ecb6b5d2a46085
+Payload = ecfa41c614c5
+CT = ef2de9359af5afcbd9af2d584a0f638d066f2496d9be
+
+Count = 69
+Adata = 5b6f6369643d83b1db33d75257d7dea761e574e6e1f1ecead64e5e354a2f4235
+Payload = b48c10105dbc
+CT = b75bb8e3d38c17861882b8930296fd51d969a1e9489e
+
+[Plen = 7]
+
+Key = b930cca30a3fd230c237c8f3cc6792d0c4084dff5c18d775
+Nonce = 7574802fd82fe96c05431acd40
+
+Count = 70
+Adata = 1cf83928b6a9e525fe578c5c0f40c322be71b3092239bff954dd6883738d6d71
+Payload = 2a755e362373ef
+CT = f06238b0450fd1f4b6cab1383adb420c4724aa7bdfefb7
+
+Count = 71
+Adata = bb5450f66273f63b2f79dce177381ce846584ce4f7a0ad5a0171a56e149370bb
+Payload = fab43224bf8989
+CT = 20a354a2d9f5b7a1f99175d3dff5a73f0053a95c36fd8d
+
+Count = 72
+Adata = 3e5e1037bd2922eb20c34200c470b76e537baf7e7f1d8dd2f7a184a593c66554
+Payload = e3aed6715aa429
+CT = 39b9b0f73cd81734b4ad0e41117940abf530093dac648e
+
+Count = 73
+Adata = 3cc88a096a1a440827f5b7da675389e50b5cce35fa2cc36674d6bfc5a3a966b2
+Payload = e78db0f83997cb
+CT = 3d9ad67e5febf5663a8324014550430c7eaeffbd8568f7
+
+Count = 74
+Adata = 2cca33a10b9da7ba99a6b552d1405f2df3fdfd15358d8fdab5e15296b38f9135
+Payload = 726557906845b1
+CT = a87231160e398f34ab635c4eb5b38b86e71da8af3840ae
+
+Count = 75
+Adata = 2fe5dd58b17914187e29029c53cfe5b015ca74cab750d8f95e05f818c3cdf947
+Payload = 043a759b578be4
+CT = de2d131d31f7dabd9961766e03eaa7e8888227c98d1f42
+
+Count = 76
+Adata = 8b8e3d7c88fa16d70130cee290b7e2eecf0ce711118cd9265093b11467e63554
+Payload = f31f2fb4b3fd80
+CT = 29084932d581be637842d96d13c4aab97e296458745a9d
+
+Count = 77
+Adata = 6341370e126097f9721a13c977eb4875cf1286e15c3adfa4e7597e0e13d93b6a
+Payload = 7e3c8224104669
+CT = a42be4a2763a57a51ac46611366c666cab6bfd3d1baaa5
+
+Count = 78
+Adata = 227926b62f7cdd90e4d3b0cb5457e71fb087d329671f0fa891ec06eb8edeb58a
+Payload = 26a0528ae6f9c1
+CT = fcb7340c8085ff8c7d7e5aec14845f844ad38544a2f11d
+
+Count = 79
+Adata = 05b50c40b02e79b74b94d726a7ce8b2b7216ef8af6e7a42d041d2a692a58ad83
+Payload = 61dcf53d1a184e
+CT = bbcb93bb7c6470f1605ab8a2332012b759ccd2eedbed24
+
+[Plen = 8]
+
+Key = 314c136999e41d137bd7ba17201a9fa406025868334e39b3
+Nonce = 65f7a0f4c0f5bba9d26f7e0ddb
+
+Count = 80
+Adata = 5c7ce4819b30b975ae6ce58dcc1bfa29a8b6dda8f4b76c7e23516487745e829c
+Payload = 4d54d8b06b204445
+CT = 2baf90c490b11f9607482362ab3f157c42d0e9c6c5cffcf0
+
+Count = 81
+Adata = 90257ed88679197b8219bc4c2434a71a4e3664d5859c4ffb9a075654898ffedf
+Payload = b2a35df881cd63a2
+CT = d458158c7a5c38715389509b5b6f2df1faf7e8c39203970f
+
+Count = 82
+Adata = dff8ad83525d8235eacdccc91abeb80795e6b5f463fd28af35c46199f646ceb8
+Payload = e98f5e5a20d02c80
+CT = 8f74162edb41775395328747ca544e987df28883d0377b35
+
+Count = 83
+Adata = cde159c5343cd9d98001cd719d3e9ea25e47e1ff13fc87055d4a53b741f59285
+Payload = 90c3e48313cd4fe4
+CT = f638acf7e85c1437a4ba841883a0d7aeda398c043161966f
+
+Count = 84
+Adata = fa88cf5a08be4fb0c1a7960f45726c303eb559861fa60d17aa8dfe8bb5795382
+Payload = 8ad6d5a28ec075e6
+CT = ec2d9dd675512e3509195efe66c5faf413e0f68df8cb647d
+
+Count = 85
+Adata = fe9e93a9370b43efa1560aeb017ff04fca7f207191e6f707c1c35b2e90c44eb2
+Payload = eb83928f0d5f7aa3
+CT = 8d78dafbf6ce2170b51af067ad69ad96009e50ead3d03f02
+
+Count = 86
+Adata = 35792c854fdf1c8cf7f3f8ed2b8ec4f31fe17bf8d4ba49caec03f954bd8bb17a
+Payload = 4cd74ed2fd083011
+CT = 2a2c06a606996bc26b1cb03ee76587f84364825f7c1fcbe9
+
+Count = 87
+Adata = c084108f9c0a74cbf70f614dceae592546865006930db0401828a0eecff98671
+Payload = 52365f94579e0646
+CT = 34cd17e0ac0f5d958fa70c5e195f1f955d64892f532b7683
+
+Count = 88
+Adata = e8045949de61c5c18a63e628330a4d1d12782379a8f9187755409d1825f453c5
+Payload = 8fb85c857a3e38e7
+CT = e94314f181af63342ddf297bdad58083645a052815d29a83
+
+Count = 89
+Adata = 53cfdfd66d63c2924bd583487b90b1dd9ec199f90d660cb9c3a763a4776abfe1
+Payload = 43d2828e86f7856b
+CT = 2529cafa7d66deb81ad3b2be41dbc39df4c0145dcbae3e76
+
+[Plen = 9]
+
+Key = a19f6be062ec0aaf33046bd52734f3336c85d8368bef86ab
+Nonce = 7f2d07f8169c5672b4df7f6cac
+
+Count = 90
+Adata = d68d5f763db6111c5d6324d694cb0236beab877daae8115ecb75d60530777b58
+Payload = 13511ae5ff6c6860a1
+CT = b3859b757802ebd048467fd8e139eb9ee8fcdca45ed87dc1c8
+
+Count = 91
+Adata = f6e219b29884dab9ea9bad34d9ef8a50ae389c9a908de7154a1f2e894f27141f
+Payload = 7e7e33e1a07d4e8fde
+CT = deaab2712713cd3f3789d0ee8323ea2ee7a68aaaa9c49b98df
+
+Count = 92
+Adata = bcca002d69d9d1044c40ae741ea33ce6b8463f5a28d0514e044fdae2fe7d3c3b
+Payload = cc88980c73e6c5f0cd
+CT = 6c5c199cf48846402437c9fe3d9feb0485e6d7c04423b77a53
+
+Count = 93
+Adata = 39cac8f0825ffdb0668455933ad1581263a23b9e5f1305340528f0320d4b1269
+Payload = 34cb528f50d073cfdc
+CT = 941fd31fd7bef07f35b87e90a71ffe6c30bee1771078a701ab
+
+Count = 94
+Adata = 510a02a44d142c8e975d1d933f828fd7e47d28b88223f1698cf009dc3b079be6
+Payload = cbce3df86438a61065
+CT = 6b1abc68e35625a08c9e9c5be0657649448c38692e8d703d30
+
+Count = 95
+Adata = 40e0418cd52f74d78a8e18ed86210e3661a86d8574aedcee540340d8996d9852
+Payload = 80a2b835f8b0729a4b
+CT = 207639a57fdef12aa213e5f2bfd33101597cfae7cf334a8528
+
+Count = 96
+Adata = 1f2938b3bde19e1af91299c08638061dc3c1ea3284c259d415e996477cb37b0e
+Payload = dd04794e65ce34127a
+CT = 7dd0f8dee2a0b7a293516a7310fbd4ceb90d8db9a86cb6311b
+
+Count = 97
+Adata = cbae5b46e35fa2a279dcaa4c724b923805d4707412a84252b64228c91cedd019
+Payload = 00c4101052f54462d5
+CT = a0109180d59bc7d23cef6165af65f3522dfbfed0293db39ecd
+
+Count = 98
+Adata = d0f27c7f42892f3ad4c0029c5b698abb1d035ba5869a665b1de8861db6c055e8
+Payload = d0865445d3b26b6f49
+CT = 7052d5d554dce8dfa00726434c1349e3e874a2d6bf598d05fc
+
+Count = 99
+Adata = ab0f5a829a9319a74d5d5179aa0a410a0fcf52f344a7a896aeb1f7a6c5d398ea
+Payload = 7c7c8580b944ed3fd3
+CT = dca804103e2a6e8f3aab491e60fc97b3cb5248291e4866dcab
+
+[Plen = 10]
+
+Key = de1c8263345081d2dfa9afdf37675971135e178df554a4d8
+Nonce = a301bb82f91a582db01355c388
+
+Count = 100
+Adata = 9ad52c041390d0d4aaf65a4667c3239c95e7eae6178acc23fb4e70a852d483c6
+Payload = f777aba1fa70f94e6de9
+CT = 9d8bff6d2dcde77104ac6aba025abc01416a7ca9f096ab2529cb
+
+Count = 101
+Adata = b49c7e7b47870c1cc339c7c09aaacfd6115fa8a0f04990367eea10cfacb9d23c
+Payload = 349feebfbe58f93ea3c3
+CT = 5e63ba7369e5e701ca864acb200e85a0d4753a8ba226aca72f98
+
+Count = 102
+Adata = e61ca7310172eec16745a73e34516f65844eecd0dbc5566ac5213626b9096ef1
+Payload = 678a40b4c2c7df0e4c9d
+CT = 0d761478157ac13125d87869784e3321183d8c044657a020e9b9
+
+Count = 103
+Adata = 690f5e5d8da6cdb0f492e80449e152ffe88fea9742564d8383c79cef739a7f74
+Payload = 2b81e0533313664bf615
+CT = 417db49fe4ae78749f5070634d00b1facf0e9e9979ca257a71e2
+
+Count = 104
+Adata = 78e34b0a1d61ccd411cbfd306ea2ef3ce89c0b085deb4cfbaec2ab72ce16daa9
+Payload = 1ac63aa38a206d8e7d68
+CT = 703a6e6f5d9d73b1142d994630ed92e2973b22773f229b45bdad
+
+Count = 105
+Adata = 51bacfcf87ea11da34b76acba8c444792ec3db3c8ee6e600d69679975a682a54
+Payload = 027a7fd7897808ec7a56
+CT = 68862b1b5ec516d3131304571b015bb6b4651f1eb9f6fb3a7b74
+
+Count = 106
+Adata = 5159357a133e4743f903d05bd641da369a3675337760fcd2424a99221ba70b78
+Payload = 1086953d352e94a51a6d
+CT = 7a7ac1f1e2938a9a7328bb0e11ac4608081fd0702a137da0aea3
+
+Count = 107
+Adata = f567820865340314d46a17f520ff315efb6b33bdeda590ca9c4fad604c2d8e8d
+Payload = b8b148aafec4a035e9a7
+CT = d24d1c662979be0a80e252c9ec1317ce30dffeb4c9bf3fd0bbdd
+
+Count = 108
+Adata = 0cfec933831644b468724e808bb3d25fe8f15850ce513fc341da46089c845208
+Payload = 884242a87779d3921f8e
+CT = e2be1664a0c4cdad76cb691e32be3cdd9721a13aabad26dba58c
+
+Count = 109
+Adata = 8edc2b85d44297ac66bdd90d05d8df38124033d6a583bb8dda18a2246ba096e8
+Payload = 25c32770a299020d8500
+CT = 4f3f73bc75241c32ec45333a381be77800654aac335bf9220ac9
+
+[Plen = 11]
+
+Key = 248d36bd15f58e47fcf1c948272355821f8492e6e69f3661
+Nonce = 9e8d492c304cf6ad59102bca0e
+
+Count = 110
+Adata = 9ec08c7ed6b70823d819e9ab019e9929249f966fdb2069311a0ddc680ac468f5
+Payload = 33709d9c7906e2f82dd9e2
+CT = 9114d36b79b1918b2720f40cddce66df9b4802f737bea4bd8f5378
+
+Count = 111
+Adata = ba13974d95f2eeb367b63850609c53dc66c2710f682f10bef0142d48f851b430
+Payload = 84172985e7d194ba28a87c
+CT = 26736772e766e7c922516a12c94615be2bd81bd598f3022f5775a4
+
+Count = 112
+Adata = 5f16180bfac9b7483774cb0e1d57a43e9bf3cf03bf6fe758293aadcbbef25b80
+Payload = 9a34d32070c71d7de8f512
+CT = 38509dd770706e0ee20c042758e936750e335702542bc598e211c4
+
+Count = 113
+Adata = 4352057bdd1735a85dc0fc4dbeedc73279c27eb24a97641236f03f11cdafb8c0
+Payload = 2054a268b1f6fae4f15d91
+CT = 8230ec9fb1418997fba4870762bb2a7d04ba2ad251d595d0619dc4
+
+Count = 114
+Adata = ddf118ae403b2509e75eb7a26d17e73e527acbacfbe49a56fa3210169030144b
+Payload = f71afe9a60f08a0ef694aa
+CT = 557eb06d6047f97dfc6dbc27d85594da3fd35bd8498d7e389ee7cd
+
+Count = 115
+Adata = 973904409e8154132439926f0dc45c0d81bbbd5793f7f81e20eb818bfa374d58
+Payload = cdf5b47ff73306aa55c496
+CT = 6f91fa88f78475d95f3d80055936db383a8ad10b152046d721d3f7
+
+Count = 116
+Adata = 06bca7ef6f91355d19f90bf25590a44a24e5a782f92bc693c031e6de1e948008
+Payload = 9ebf93643854ea5c97a4f3
+CT = 3cdbdd9338e3992f9d5de5d57e228369e24fe955fd8924526af6e5
+
+Count = 117
+Adata = 8321f65baf9dc856ac1c24f3fee5c74d697eb0b50470d59d8f4a14b506e86c53
+Payload = 685116faa5cc527ac8bfa1
+CT = ca35580da57b2109c246b76c23abfb3b4eb39deb8da2064390dfa8
+
+Count = 118
+Adata = a4e7738038a5116592bb9d92d6d4ed191ab774310f6409e4e45fe907674c006f
+Payload = 9e8c4f1292e8d7e5179b34
+CT = 3ce801e5925fa4961d6222b4272c0639e8e6a1d356fb4fea86762c
+
+Count = 119
+Adata = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005adfe9faab253b572
+Payload = 3ecc2ba566c723462eb0ea
+CT = 9ca86552667050352449fc0633a0f9cdc9490231ec2dd69f6e35db
+
+[Plen = 12]
+
+Key = 77a67fb504b961028633321111aac2c30eb6d71a8cf72056
+Nonce = acadc0330194906f8c75ac287f
+
+Count = 120
+Adata = 8c18486d52571f70f2ba6a747aaa3d4b3ebc2e481ee1b70907dddb94bdfa0ca6
+Payload = 10554c062d269ff6dcd98493
+CT = 7f8b0cad79b545e5addf0b04ff4b0f2b2a5067283210aba8630d0306
+
+Count = 121
+Adata = 4e0b4771c7f6c66f9577c430611fdeec5702296ee3691b6bb8c6a81217edabe4
+Payload = 1c9e7875cf02129ac52daeb0
+CT = 734038de9b91c889b42b21275b16dbdf0b9be3c8c82ac652992d630d
+
+Count = 122
+Adata = 4a687e1d0a95ed2efb95b4c6b040999fcd35136811cd665f934d10224b6064c2
+Payload = 34575694dde459d195b7357a
+CT = 5b89163f897783c2e4b1baede629274d654ef5a4480e24f6bef3bc8c
+
+Count = 123
+Adata = b5330a8447d74a7987fb718cfae246b5c7e057991064eeaf823641a12bfce9f5
+Payload = ab20c8e8aab1aac1e4f64206
+CT = c4fe8843fe2270d295f0cd9142ab5407a08b648ce24e9955e28fe47e
+
+Count = 124
+Adata = 4f19bbc3135d7a216465b4c1df2616e8bfc3cc64af0bf52bdc42543f4d2448d4
+Payload = e556ca05bcd1991d2c9836a9
+CT = 8a888aaee842430e5d9eb93e151e94d311c7cd2c1b9048575076ceac
+
+Count = 125
+Adata = b6ffc7387b19786282bda7caad52eb37fbe7e557afcb80faaf57767e2a0f178a
+Payload = e5b665600a2aa413e117c538
+CT = 8a6825cb5eb97e0090114aaf61b71330d72506050368186a5619f180
+
+Count = 126
+Adata = 6a493c5ef3769ccc4101dbb2eb36e1e5bbc577a057ce0731203ba3f25b52497b
+Payload = 870864a611aa0475d120bc40
+CT = e8d6240d4539de66a02633d7ea21e36f99e5aab6ffa85994d13d5bb0
+
+Count = 127
+Adata = 8215753d9efc51325f182199e39f9082cc3fe524400f2a7434c68df7eb2b06d4
+Payload = 71afe8d00c6f2ea8c8b050d4
+CT = 1e71a87b58fcf4bbb9b6df437cc93a50dea11c5e0b19f14b9c8f16bd
+
+Count = 128
+Adata = eb8f198da6ee92a03913c6575343f6c749d2377a09430eb751b13c041e6edbea
+Payload = 7021f18b8f398a5999fcdcd1
+CT = 1fffb120dbaa504ae8fa534699cbfd1beafa2d2942f6812b8dfc88e6
+
+Count = 129
+Adata = de2ee30359e390db72f682c2ca0f14b72b60ff9bccd8c6fbd19a512b12add794
+Payload = affca856eb412f0b3276ae6e
+CT = c022e8fdbfd2f518437021f9337405235dce6161441caa25cc6007c6
+
+[Plen = 13]
+
+Key = 0d423519e4110c06063061323f8c7c95387776b6ee4e4b6e
+Nonce = 39abe53826d9b8e300fe747533
+
+Count = 130
+Adata = cdd9bf1b4f865e922c678ec4947ea0cb02e78bd5c1538f33aeb818ad3f47e519
+Payload = 4021ff104ff1dbd91e46db249f
+CT = 7953d3cd66d093785d123f65ba37f16761dd6aedbfc789ad96edf1490d
+
+Count = 131
+Adata = 342de5fe61e05c2e58ac2978a871fbdf186a7294ec5f85c4631c21b584231211
+Payload = 95050ca1d494bdb561d4840f8a
+CT = ac77207cfdb5f5142280604eaf8f8e855ae975a1fc64bcce3e7492e9d6
+
+Count = 132
+Adata = 7871482948d8d09d0a7491d915543082cb5fc7d6c1e82ee2218279f54c15c154
+Payload = c45823203b20821a48502f9c67
+CT = fd2a0ffd1201cabb0b04cbdd42017a6515156691b3161b747576078da4
+
+Count = 133
+Adata = 65781d018f27ca0c72a9fa9ab4648ed369646dd3ce45d7ad3a54f6b051f1b6e9
+Payload = e901661b7d47c9918244ee1077
+CT = d0734ac654668130c1100a515225cec7d2566a07cd78181ae94577befe
+
+Count = 134
+Adata = 05556b04dae5cde8525633d1862aa200c54af534e302d2cbd34ddc2b78532a60
+Payload = 5556f799d6a6cffb343f28c1a9
+CT = 6c24db44ff87875a776bcc808c133f51dac00f973fd42e0948fab70ea9
+
+Count = 135
+Adata = 151304e3e4f3c2d4d3227e035d849e0d3841ba00cf6cab1cf2e3e4d6cc760623
+Payload = 56bf26be81c7b55ef898e23981
+CT = 6fcd0a63a8e6fdffbbcc0678a4fe78bdeaa8d408ffe8fe64811aa87742
+
+Count = 136
+Adata = f870cc1fe67d6169279f905b0fe5fd9a0436c36498e4b7c6f584f00f7efe8784
+Payload = 36b304a72dbf4acfffa1d7d624
+CT = 0fc1287a049e026ebcf533970197228d155dda2bc814ff33ebeb9a7ffd
+
+Count = 137
+Adata = 5692c9d452ea1c067e62fdc554ddd2b18c8433d59067f971316797fd9853ae6a
+Payload = fb529eb5ae79a0830474ffbc98
+CT = c220b2688758e82247201bfdbde7ba03e144e34a4ab34791a372a2b8ab
+
+Count = 138
+Adata = dcf7fe16b7ca9e27ec3291103398eaa2e77c7b770b67f8858c215af4c523822d
+Payload = 6218c778955d9a56360f06c704
+CT = 5b6aeba5bc7cd2f7755be2862103c2eb5ef0657306d12b753a0694efcc
+
+Count = 139
+Adata = b0f1e2668611dca86e8d0f58c2a4cf4a9472d81ba013e271800b75841fe5ffde
+Payload = bf6b143fb713a81c965c5a9d8d
+CT = 861938e29e32e0bdd508bedca87cc6119151393461ecf65bfe06e0163b
+
+[Plen = 14]
+
+Key = a60cf7ceb62bf3118532bc61daa25ce946991047f951b536
+Nonce = 7499494faa44a7576f9ed5580d
+
+Count = 140
+Adata = baa482c64eefd09118549a8968f44cfea7a436913a428e30aa4ab44802a4ba35
+Payload = d64f9426febce6a84c954dd5ded5
+CT = f7580f17266d68237747bf57c7ed8242ac1a1979c5a9e7bc67d7698c7efa
+
+Count = 141
+Adata = 2ad8ecc5ac9437ace079419f17e6018625b10490120fbe2f12b41e64b73b653c
+Payload = fcd9b67717bcadeceddea336c671
+CT = ddce2d46cf6d2367d60c51b4df4918abced491c063d8bfd0e7341febddc3
+
+Count = 142
+Adata = 7585ee95e74d7a869bdc0b59ca9939dd57e7b09afab179079d467bfe0668416c
+Payload = 18232d7c792fb80e6ca1c8f2c3cc
+CT = 3934b64da1fe368557733a70daf4659ecbb3dbfbcdb0f913abedf8afab05
+
+Count = 143
+Adata = 41be6ca6188f34da1ce83fb8c27652848dc2a71e32bd3631fb9b33ae69e5d879
+Payload = 764dbefb42644d18d23e5e456868
+CT = 575a25ca9ab5c393e9ecacc77150a220d5ec0b5397d6b4e323b5dc7d1b63
+
+Count = 144
+Adata = 197cee3b15320d57996191dd13106fbd4546a5cc3d2bcf0c886af52ea3d9a855
+Payload = 8003586af34bdd0acae4f5547394
+CT = a114c35b2b9a5381f13607d66aac3a5f713f5d0793b732c6e114805cc9b3
+
+Count = 145
+Adata = ee0b647a47656a6e9e09c2d64f734a2cc3fd45b7ee52fea51c24af59ee22a006
+Payload = da143266516a4145cde92c93f961
+CT = fb03a95789bbcfcef63bde11e059ed90e8650bc16f590789dcc625b9e63d
+
+Count = 146
+Adata = 9f5bfffa01f1425d95465723735b49fc1dffbad06cf37a00ca4b59efa21739c1
+Payload = 3842b033f3ca31a6f8e5a638b39e
+CT = 19552b022b1bbf2dc33754baaaa6bda183dda1aef021d92210e27cdd7c5e
+
+Count = 147
+Adata = 64e92ba2748d07f602808f7c5ded15cb0e43140400d37107e59a01e7d45b4c9c
+Payload = cedf60b17185fc71b957cb759260
+CT = efc8fb80a95472fa828539f78b585e4087fb314f893937e95383e66745c0
+
+Count = 148
+Adata = 6ebcaeb4bd44ff4c990305ac64264dfe2ada5f7cd4b294eb9f492865cd28905c
+Payload = 035f449bb28f43365f4a0556096a
+CT = 2248dfaa6a5ecdbd6498f7d410520a71ce5813c578532b742d704fa92276
+
+Count = 149
+Adata = db617207dccd1f6baea5f2242d5e577adb8d69af3bb1707a7a53a8b75452455c
+Payload = 9a2a45424f4965a71270e77cc403
+CT = bb3dde739798eb2c29a215fedd3bb7fc45d15d6939668065d2282fc589c7
+
+[Plen = 15]
+
+Key = 82d4bc9aac298b09112073277205e1bf42176d1e6339b76c
+Nonce = 70325ef19e581b743095cd5eb1
+
+Count = 150
+Adata = 6d14bb2635c5d0ae83687f1824279cf141173527e1b32d1baf8a27f7fe34a542
+Payload = 25a53fd3e476dc0860eeeea25fcb0c
+CT = 4a1cfd0023557a184b929965b0a445cb3993ca35acf354cb2b4254ff672e7f
+
+Count = 151
+Adata = 9f8a56fecf32fa7d50f033b2524c3d798e254bc87245cce57e38edd6ee5d5f1a
+Payload = 797dca47597947c057789433309b67
+CT = 16c408949e5ae1d07c04e3f4dff42ea25b5eb103bac224cad66ec0f100875c
+
+Count = 152
+Adata = 86f15b8b677b7655f358a2c7fd5785bc84d31e079ed859b6af88e198debd36fc
+Payload = e61f9a663d3a2b50ea2f9475971270
+CT = 89a658b5fa198d40c153e3b2787d39b598cc6ec2295c586e7ae270a01846d1
+
+Count = 153
+Adata = 4de6bd43c28143ea5d40919cb5330a7e674f5bd8aeb7b178343a2851281c8668
+Payload = df990c42a268950677c433555319b3
+CT = b020ce91654b33165cb84492bc76fa97ff732093f7d0a96b30d8cdfd1bd583
+
+Count = 154
+Adata = a5c3a480dea1b2a1e3a0ce416148b04f60104217c9d24a5b267b4aa6aa07a4dd
+Payload = a7e72fb4bec3768594a2f6f5b4379e
+CT = c85eed6779e0d095bfde81325b58d7ad98e32a9156e125ff021ef6951b0c40
+
+Count = 155
+Adata = 51b041f1666c59045d333fe63d43457107e1adad34fcbf965e0d191f3e414776
+Payload = d3d1550047cf90eceaea7000d8e280
+CT = bc6897d380ec36fcc19607c7378dc9390f10df08a84c21031626861b201fbd
+
+Count = 156
+Adata = 22f8a3c9d85b2d53ffd92078d3c94373f855ecd01a8ac521d1abd0f2c7cba9ff
+Payload = 756412c4ee6416f2f4e0342011cde2
+CT = 1addd0172947b0e2df9c43e7fea2abdd5d840bb8c4348a9a548482e6b93043
+
+Count = 157
+Adata = da08b14e1b770b81faaf1e59851df1cba8838cd63bef141340ee378e65fdcbd4
+Payload = 666e4a4b3f6cf598aa763cdada4109
+CT = 09d78898f84f5388810a4b1d352e403f0d49927cd6103e3705ba201e8f73c6
+
+Count = 158
+Adata = 2db3ded385ef9c82fd39ea5782d9befe66e8a070066269b2aa7c4bbfac3711c3
+Payload = eb9013a74352b0677a88bd73052477
+CT = 8429d1748471167751f4cab4ea4b3e2d97f7c2b3b42bf570cce79bf30ccc50
+
+Count = 159
+Adata = 194c9e1eaa8e376f9c41bf33823efa28ee60a9213438665b7002cf0fcad7e644
+Payload = e3126400e3c571a4d39b37bc938a22
+CT = 8caba6d324e6d7b4f8e7407b7ce56bd3c2a4fc45d014a0c54edab2930a5bdc
+
+[Plen = 16]
+
+Key = 6873f1c6c30975aff6f08470264321130a6e5984ade324e9
+Nonce = 7c4d2f7cec04361f187f0726d5
+
+Count = 160
+Adata = 77743b5d83a00d2c8d5f7e10781531b496e09f3bc9295d7ae9799e64668ef8c5
+Payload = 5051a0b0b6766cd6ea29a672769d40fe
+CT = 0ce5ac8d6b256fb7580bf6acc76426af40bce58fd4cd6548df90a0337c842004
+
+Count = 161
+Adata = e883dd42e9ddf7bc64f460ba019c28597587d06e57c3b7242f84d5e7d124ab81
+Payload = b31dfa833b0cda20eaa84d2ecd18f49a
+CT = efa9f6bee65fd941588a1df07ce192cb8707b1a4d9ce3def33703e19eaab6dda
+
+Count = 162
+Adata = 409401eb49cd96b1aad2525c5124c509766ff86f88b2011c67a1d501d3485e31
+Payload = 24bc8dc1e2354667b79ba4d7061448ff
+CT = 780881fc3f66450605b9f409b7ed2eaefd9041ddce37d88e79fba28e385b2327
+
+Count = 163
+Adata = 83bf5c063bf1febf71688a832d615e09d6f14badedeaeb6ffbfe343fc7274e78
+Payload = d41d95a1d2326e12cba636910ddfca53
+CT = 88a9999c0f616d737984664fbc26ac0291d971893543868bd8c69078fc2bdb24
+
+Count = 164
+Adata = 8cdd70524e24318c64d681aa27752d4c86c5348c05c9e48f06ed41594785a6e6
+Payload = e8a4b80e081919f1912542d3136764f2
+CT = b410b433d54a1a902307120da29e02a3866b23e4c991f4007e56a1ee9265c6cf
+
+Count = 165
+Adata = 615985f63571c0f94ffcd4df77326abd41e84f388f061d97573a181da7ee5695
+Payload = 7fca7388058d6d1438b6eee0292131cb
+CT = 237e7fb5d8de6e758a94be3e98d8579a2abbea637996b954027efa9464ced6b9
+
+Count = 166
+Adata = 17aa90f2bff0419011b01dee62be31354431cbc89f22332704b096143d4743f4
+Payload = aa540554ee80dbffa475f702d862d6b6
+CT = f6e0096933d3d89e1657a7dc699bb0e757bc8d48d82ebefc76f17323c518ecc2
+
+Count = 167
+Adata = 85288b2be612e42335c144fb058a7dcd567c382fbcee3962bd5be4cc7a7000a8
+Payload = 6d745581831edba437e70ea89cad217d
+CT = 31c059bc5e4dd8c585c55e762d54472c65470c81e487a26cdc26830f2b51bd1c
+
+Count = 168
+Adata = 288f9f52824b54b608dd7226a0a89d43ae8c05107dbae761e1c756911a003b74
+Payload = 811a61869c7a6b2aa9ac0fcc523ef784
+CT = ddae6dbb4129684b1b8e5f12e3c791d5a3043722be9448c3ef144f2288066f75
+
+Count = 169
+Adata = 51dbaba180d4746edbb3420461919b5b735797bf7dd19f84d80475f5efc2748d
+Payload = 378a4e39817f308ed1e639f943b694c4
+CT = 6b3e42045c2c33ef63c46927f24ff29549aba95e04e11cf18ddf73773d395c1a
+
+[Plen = 17]
+
+Key = 3cf8da27d5be1af024158985f725fd7a6242cbe0041f2c17
+Nonce = 07f77f114d7264a122a7e9db4f
+
+Count = 170
+Adata = 30457e99616f0247f1339b101974ea231904d0ef7bd0d5ee9b57c6c16761a282
+Payload = f6dd2c64bf597e63263ccae1c54e0805fe
+CT = ce3031c3a70600e9340b2ddfe56aa72cffdc5e53e68c51ee55b276eb3f85d2cf63
+
+Count = 171
+Adata = 42370f115bbd4b31bb99fe82cca273b3c93072f96b2e09bdc6718d926d48db69
+Payload = f45fee3e086c28a7c590ec0cc05b972664
+CT = ccb2f3991033562dd7a70b32e07f380f65c6328a7476db2c10ec7bca3f6bd3df42
+
+Count = 172
+Adata = e2d692c5678124998a7862b8e87276b0a19e293a609103c99583b36305bcb2b0
+Payload = 4ad69a8ab433ed8909825c71f6081f64a7
+CT = 723b872dac6c93031bb5bb4fd62cb04da68080f0d51d3b8841683eff361984f7e4
+
+Count = 173
+Adata = b5b38791160959dd2836ec1ad25286c1ba410d7212347a95b5738a3d725bb651
+Payload = 3d47071c13f994cb42fb2887e5c6e53a54
+CT = 05aa1abb0ba6ea4150cccfb9c5e24a1355c1428ef5d40bc9e363817f219af2ed56
+
+Count = 174
+Adata = 02691171795a77d1e3bdad513b6fab5b50d1def81bcc1df15012de3433a6aa78
+Payload = e8a4b80e081919f1912542d3136764f264
+CT = d049a5a91046677b8312a5ed3343cbdb65fdfb37dfd1236198035c8461b304152b
+
+Count = 175
+Adata = 7371d8ae79e628f53ffede174eb068db2318c05e2f6d94ad2233a59369b16db0
+Payload = 549aa84bb182312dd016e3107f3b1f9c5b
+CT = 6c77b5eca9dd4fa7c221042e5f1fb0b55acefde0e84a3ce0cb702ceb73ca1dd9a5
+
+Count = 176
+Adata = bb1e1f51082e470f7245458ec902098e1e41d0ed28efa31be71d21ce86527ff7
+Payload = 31a12ca6d69db2e6e252474d7d59ed6552
+CT = 094c3101cec2cc6cf065a0735d7d424c53f8441d46dc5456a587b765e1a820c11c
+
+Count = 177
+Adata = 7584f57b49e95bbf5a67153e18b9b8c4722644e8f611613c39cbe8c679aba5b4
+Payload = 5bb121e70452a954f420a56aca8cd5c059
+CT = 635c3c401c0dd7dee6174254eaa87ae958d0daddcfcc92349ef059149c54a25cd0
+
+Count = 178
+Adata = 505687182c06e6f4effe7fe03c1f436199a9015380ff21d0b2aa9453cfa10b1d
+Payload = 5b80d1cf745b14cb71cbc8dfe0bc7c7358
+CT = 636dcc686c046a4163fc2fe1c098d35a5948c1242b89490c6ee69dedc1e91286ee
+
+Count = 179
+Adata = 7ebb051741145a3bad87131553375c6debcbcecee9b79ee451bd1429cbb33fc1
+Payload = 79ac204a26b9fee1132370c20f8c5bcada
+CT = 41413ded3ee6806b011497fc2fa8f4e3dba2ddd54e509bca0a45dcf2fd514e1496
+
+[Plen = 18]
+
+Key = b46a3a24c66eb846ca6413c001153dc6998970c12e7acd5a
+Nonce = b79c33c96a0a90030694163e2a
+
+Count = 180
+Adata = ea9405d6a46cac9783a7b48ac2e25cc9a3a519c4658b2a8770a37240d41587fb
+Payload = 56d18d3e2e496440d0a5c9e1bcb464faf5bc
+CT = 01baba2e0d5b49d600d03a7ed84ee878926c0ca478f40a6fbde01f584d938a1c91bf
+
+Count = 181
+Adata = 72340d595f3dbd23b46513f8f2b73b6249328c705e7968084bcb647fe734a967
+Payload = 7a76eac44486afdb112fc4aab939e4d1eedb
+CT = 2d1dddd46794824dc15a3735ddc36853890be4646492b6f4cb169383c075756073b6
+
+Count = 182
+Adata = d5c87c649579da3f632ba95cb0a07c924095e4bdd4e0376e06bb90e07460172e
+Payload = 48348c5ec996f7a97ef0ba2cd6885572fe64
+CT = 1f5fbb4eea84da3fae8549b3b272d9f099b4f584289f560cbf76606942fe1a92dd63
+
+Count = 183
+Adata = ffa6277395d31d5db13034d362228a87610e441c98ca3038e252a9db12bdbcef
+Payload = d5c58f10e1a03d8a2501d1eaf5fcdfff3ae5
+CT = 82aeb800c2b2101cf57422759106537d5d355964f5f5532d7cddd7207f0e9a6aace9
+
+Count = 184
+Adata = daf83d02a9bd992ea58c23e7ad18d41796314bae20e864e729f40ccc215454fc
+Payload = da2a863ab1c58ddde320ecadeecac9c5d2d8
+CT = 8d41b12a92d7a04b33551f328a304547b50890ae047e35aecfc38ffdc07e7d8f5705
+
+Count = 185
+Adata = 21ddad5f550044dc5cb123ade17eeef549c4e0173b216bcc602c1e736764cca8
+Payload = 4573969afa831c244817230406fe51183091
+CT = 1218a18ad99131b29862d09b6204dd9a5741b2bdf539ceaa35015712dd15265ca476
+
+Count = 186
+Adata = 9228265ae5c3daf1485ff8011738da508bf2a73731396c5d9aa56fc554e0c00b
+Payload = edf5557e15473b747a819398c9ac1459ffdb
+CT = ba9e626e365516e2aaf46007ad5698db980b241412124ae20b84c13b0c3671d305c9
+
+Count = 187
+Adata = c0a2ff0de21b3ba961e06015ccd71374856a65a4c57cf8cde0a1643aca8ed868
+Payload = e139263478900df806a0f3446bd6600c1aeb
+CT = b65211245b82206ed6d500db0f2cec8e7d3bee9803747bf9fa63412bfc4e10aea89e
+
+Count = 188
+Adata = b54378f031a31cf3985f573829c9ffca14616742e0a7e03b0a2d7f05eff0219e
+Payload = 660eaff0f113eaa2f5f7ad4b62bb849a3a25
+CT = 316598e0d201c73425825ed4064108185df55afdf430b57845dcf622d4f25cdeb2a3
+
+Count = 189
+Adata = e67f35c18a9336469eae23040f98f52338ca8d0cab269ac32fe6bc7605d3ea56
+Payload = 0f89897271f5d0349d57399005ea60c0cadc
+CT = 58e2be6252e7fda24d22ca0f6110ec42ad0c7ed4c04c4b4dd585891ecfddeab8cc87
+
+[Plen = 19]
+
+Key = 7b71045ccef735bd0c5bea3cf3b7e16e58d9c62061a204e0
+Nonce = 2b9ecfd179242c295fe6c6fa55
+
+Count = 190
+Adata = b89166f97deb9cc7fdeb63639eeafb145895b307749ec1a293b27115f3aa8232
+Payload = 890d05420d57e3b3d8dbef117fe60c3fa6a095
+CT = f842ff6662684de8785af275fa2d82d587de0687ebe35e883cbd53b82f2a4624c03894
+
+Count = 191
+Adata = 4392c3043287dd096b43b4a37ea7f5dc1d298b0623ccbf4fd650a49569a5b27b
+Payload = 6b425cdcdf8304e7fbb70b2973d55e6940025b
+CT = 1a0da6f8b0bcaabc5b36164df61ed083617cc807d4824f0a98db2d87365a42ca3b80e1
+
+Count = 192
+Adata = 9b4fc98fcdcf485205e7054bc9d1e02d0d8584420537e20d3821de2fd6824787
+Payload = c8bf145fcffbafd6cd1a4c5b6cedfe008aacb2
+CT = b9f0ee7ba0c4018d6d9b513fe92670eaabd221404e631735c544edeeb4c0105c55bf0b
+
+Count = 193
+Adata = 45622e1472542be2f63f463d253617eafd4f2ad609f9020884905dd5c22fba53
+Payload = 12b5a76faedf6f855e328c2cb87be8aea78c5e
+CT = 63fa5d4bc1e0c1defeb391483db0664486f2cdc16a4cf37e8e96eed1217d21133e83d1
+
+Count = 194
+Adata = 958689aea3c6cd19020eff9d635ef44ee0793424df38fdf13a238b969d429777
+Payload = f0927c3cb0a876d7877466507da8bfa0bd9a16
+CT = 81dd8618df97d88c27f57b34f863314a9ce4859facf81a636351f6e67d6ec12636ae0b
+
+Count = 195
+Adata = c22911efc36fa739048af0c951ef2449bb3605c52f65120c4d71fe5976026032
+Payload = d2c5d4e2362f19c99de66da7bd9c495c03d9a1
+CT = a38a2ec65910b7923d6770c33857c7b622a7327ce73a7e2db69d30441f89a03fd0e84e
+
+Count = 196
+Adata = 799da61e2c10ebb4783f618b8f69da7704a1b2b925cebc228af57d7ceebb9825
+Payload = 1c9d7f5b329ef4d384b8b7955a20f8a3fc15cd
+CT = 6dd2857f5da15a882439aaf1dfeb7649dd6b5e8d787a9d06b8533ca96fb1db8aecc8e5
+
+Count = 197
+Adata = 14a8e18afe0b9fe18ddfd754219a7e18ed36f419f8262d91678e10daffb31c81
+Payload = 3a64414c3588d7c26871d7d054ac6c8420d491
+CT = 4b2bbb685ab77999c8f0cab4d167e26e01aa028ff5f819d552c08054b5ac02063e102a
+
+Count = 198
+Adata = 7294a8b4ad97c81969e4a2876a3dc0ee322d554726997dc9ed98c5601985ee5b
+Payload = 545dd71bea9967e07a89f84a2027aacd132187
+CT = 25122d3f85a6c9bbda08e52ea5ec2427325f141cde5af8fada67c47cbb5787a6b2d9c9
+
+Count = 199
+Adata = 99294b22d73805805630fb416d20d4fca67419ab660ff45cd19a3729e81b9f69
+Payload = ec1b17b885c018272652453f47fa6e9ed972b9
+CT = 9d54ed9ceaffb67c86d3585bc231e074f80c2a7412640b179bd3e8a417dc38462c16e8
+
+[Plen = 20]
+
+Key = dc7c67715f2709e150cceff020aaacf88a1e7568191acbcf
+Nonce = da56ea046990c70fa216e5e6c4
+
+Count = 200
+Adata = f799818d91be7bab555a2e39f1f45810a94d07179f94fe1151d95ab963c47611
+Payload = f383bd3e6270876b74abbb5d35e7d4f11d83412c
+CT = 377b5df263c5c74f63603692cbb61ea37b6d686c743f71e15490ca41d245768988719ede
+
+Count = 201
+Adata = 69adcae8a1e9a3f2fe9e62591f7b4c5b19d3b50e769521f67e7ea8d7b58d9fc8
+Payload = 615d724ae94a5daf8d27ad5132d507504898f61e
+CT = a5a59286e8ff1d8b9aec209ecc84cd022e76df5ea9bc8cfaf2a1734a792076618c4b9690
+
+Count = 202
+Adata = 4586f73a1f162b2cdb65f6e798a60b5f48938d40b4612d84c1f39244f14efdce
+Payload = 6e923e1f404002aa5cf8f8aaf1b9772da425e21c
+CT = aa6aded341f5428e4b3375650fe8bd7fc2cbcb5cc5122df904b052e4d5580fdeddf5297c
+
+Count = 203
+Adata = 9f7ae892e5662803408d4d062265846441a43c1fa202da59f640ae722a692671
+Payload = 68115771505daa18bb3ce90054bfb7d077e1f37c
+CT = ace9b7bd51e8ea3cacf764cfaaee7d82110fda3ce0ba1bb1af18e15ade3316c21d6b41fb
+
+Count = 204
+Adata = 1f0769a7ae82bd985661e031c4a892c15d3ef37bdcfb45243d02f40fdb51d34b
+Payload = 681fd2a324b3fea4cfebed567ae4546ba373c8f1
+CT = ace7326f2506be80d820609984b59e39c59de1b1dc71e342fbc44289ef7e53e28edf3839
+
+Count = 205
+Adata = bf957ef5ab2805e58ea752da5793f7f23d98fce1b2b67738929e5de8a15f9801
+Payload = a7b9d2d069941e8b943706a02d2847ea713bb103
+CT = 6341321c68215eaf83fc8b6fd3798db817d59843ced1fb4a2a3e349aa590aabbfc3d13bc
+
+Count = 206
+Adata = 833264c1bebb597043b4158087cb651960915d9023189c9509c0d2aed84e7fe4
+Payload = 9b946e8198ce69d2173e970f4e0c103a47ee4160
+CT = 5f6c8e4d997b29f600f51ac0b05dda68210068205079f6c2739e2b789b6e3d3c60389374
+
+Count = 207
+Adata = 94c8414cbbec52e2d73bb8f02ef687c91432495c0c744666317d02e6d46706d2
+Payload = 81ac4618f3db6bcf9bbf67220b7671be4bb4f8a2
+CT = 4554a6d4f26e2beb8c74eaedf527bbec2d5ad1e22a02f287db7217148317d897f65f6a0c
+
+Count = 208
+Adata = fced1131dab3dabdc1a16d3409fa09a90ffe02f0e2c814a63f77f771c08c3389
+Payload = 90851933d4d3257137984cdb9cba2ca737322dac
+CT = 547df9ffd56665552053c11462ebe6f551dc04ec362df9f8b41b1dd4821f8f14e9e633d7
+
+Count = 209
+Adata = 495dfcf91f4735ab35c6bc4deef8468bd988e4099cd291a32b4707f93e13d82b
+Payload = c14ce6d57f0fe7367331c9fe159ae1fb8f1ccb2c
+CT = 05b406197ebaa71264fa4431ebcb2ba9e9f2e26cf61ffb51e56497ca9f39c6665fcbdfa8
+
+[Plen = 21]
+
+Key = f41e369a1599627e76983e9a4fc2e963dab4960b09ebe390
+Nonce = 68ef8285b90f28bcd3cb1bacea
+
+Count = 210
+Adata = dbe3e82e49624d968f5463ceb8af189fb3ad8b3b4122142b110d848a286dae71
+Payload = 81ad3f386bedcbf656ff535c63580d1f87e3c72326
+CT = 9f6028153e06d14d30b862a99a35413413c04a49dc6f68a03a11cf00d58f062a7b36465d13
+
+Count = 211
+Adata = d9acfd611e5bbb08c5d05d56791b8aebabf8d69734ec89153c91a1f65b2e1adb
+Payload = 35f6bb3f6a388f3a5a039b0a495b676d0b928aeb19
+CT = 2b3bac123fd395813c44aaffb0362b469fb10781e3ca1fb470b666523a19f83481f16481ed
+
+Count = 212
+Adata = 6003b771afe4e99e1ef1ed4a31b10540d95f4ac49885f0c8e5cdcb63d213127e
+Payload = 6aa7e3802b5a29d4f9ca88eb59f94af783d1054466
+CT = 746af4ad7eb1336f9f8db91ea09406dc17f2882e9c53cb05bfcd64da2b45c2e9a89a380b49
+
+Count = 213
+Adata = c371644275a6290821e7d308714bec2bf62d36c30f7fa77a0d60b28894f1c82a
+Payload = 13332b67ba5ba18137c306bd860dc3eb0a9a0b871a
+CT = 0dfe3c4aefb0bb3a518437487f608fc09eb986ede048f70fbc680cf7092b3dd90b943fc6e5
+
+Count = 214
+Adata = 8eceb15300ec4220510ed5b7deb3429de6ae5f618e1c222c28990a9ab4b4bac8
+Payload = 05981dc26a1db2d8e2c3d85ea9a4d1dc3432d9edc4
+CT = 1b550aef3ff6a8638484e9ab50c99df7a01154873ee386f33c0b8da8d0c5934e617dd618e5
+
+Count = 215
+Adata = 96d1cf3690c48c77a155ce13e67bbd62e6f03d88c893c1f7c30a6435d5ab36e0
+Payload = 60249343a8cd4d33c6edc583ea7e5c221ef3064787
+CT = 7ee9846efd265788a0aaf476131310098ad08b2d7d3d2db1360fb1121893f4d197731bce4f
+
+Count = 216
+Adata = 379bbc9f919dc2a8687f2a86cc9c3291804240a9b566c58519956848102e6155
+Payload = 79003a8d3d20d412f468f11712cec4d37cee847440
+CT = 67cd2da068cbcea9922fc0e2eba388f8e8cd091eba335ce1bfafc0948f2523e75f2aad86f9
+
+Count = 217
+Adata = 9bff9c9a8f94cd77e7016748da31f86d1b9c68465cbf954511c93a4776981524
+Payload = 7d078a8b200514a00628756250d410f7a0f8a769e6
+CT = 63ca9da675ee0e1b606f4497a9b95cdc34db2a031c7dc265e281307f0f4c38cddc556ac725
+
+Count = 218
+Adata = 25125a4668c31dc2e8a68b6c4c95ad7cf9322852e371b415a357d09acb01b587
+Payload = d9b0eaaff786165f882f41a98dbc0c355b3a1aaf40
+CT = c77dfd82a26d0ce4ee68705c74d1401ecf1997c5ba61c78a2f85a447c3e62b6197d65b9065
+
+Count = 219
+Adata = ad34d8f0902a5b79fb145b8206bb4d3b77e0bd8ae2d0964815389eacb33b4007
+Payload = 17b517ef577f588da374340d2522cc9ea642c8d8ae
+CT = 097800c202944236c53305f8dc4f80b5326145b2540312d067c08a9b4400e1df8bb7ed671a
+
+[Plen = 22]
+
+Key = 3289e59e3a7b29bf4a309afc253030bba4b9bdd64f0722f9
+Nonce = 30259ce106e9bd7a8bacbaf212
+
+Count = 220
+Adata = 2870bd9a26c510e9a256920899bbc77a4eb9b53f927045a943d5ed6b13638cf3
+Payload = 53911a67b65738f87fc7c20d6db8044bde1af95838d1
+CT = 70cf37d4b6f7e707376b1574ce17c040b5143da47abb2fe9afafc2fccd98ccf63b0fdec30eac
+
+Count = 221
+Adata = 611032a95ee87f89ad6be7c0fed8bd245c5f81076087b3bda4cde5587b8d14b6
+Payload = 46917e38b8a542296d290d065b0aa7c8aaa38950c386
+CT = 65cf538bb8059dd62585da7ff8a563c3c1ad4dac81ec102dfd8c231d6a355f079c213ce6858e
+
+Count = 222
+Adata = 2e7ea26d1cceaca3b7862a7a8469e366b52ec27ca127e3317222ee651d8da4a0
+Payload = b527828c89f674dc6f024f8cdd80c694bb3ebd57b2d9
+CT = 9679af3f8956ab2327ae98f57e2f029fd03079abf0b36df11febe34dd568da12c374674b9ac4
+
+Count = 223
+Adata = 0bf4413010daec585de34142224d1cad3072f9720f91ac664ad152820e838741
+Payload = 78230f73f9c0150f630eca4cd679818551d449db82e6
+CT = 5b7d22c0f960caf02ba21d3575d6458e3ada8d27c08cb2916540d9439b832aa44236a7e187ac
+
+Count = 224
+Adata = 2e7cae3306582eb5bad148247aa6c6ec943f8748e84b8a069ca9488b11844716
+Payload = 847bb12e0e56fa07a086eeda5907ae148148fa4107d2
+CT = a7259c9d0ef625f8e82a39a3faa86a1fea463ebd45b80d0768a18dead55700901408aa3f901a
+
+Count = 225
+Adata = 63036dc4ad13aee5dc1832e867f7538da108188fec7b08262af440d07579c451
+Payload = ec59e208c4bb429a371f1b3ffdf07fce5dea8a05f0ce
+CT = cf07cfbbc41b9d657fb3cc465e5fbbc536e44ef9b2a45f2073605d2a441805b6ff89d8beb68c
+
+Count = 226
+Adata = f9ec5ce4b63156d57e451eb67ab6d7a59cc397f43f6d26dc07d1036f0fb4a8cf
+Payload = fb12d94bd21b5748b23132a03065c78dae65a0bd2cfb
+CT = d84cf4f8d2bb88b7fa9de5d993ca0386c56b64416e91dcabef6907811c6b7df4e74c7a63d83b
+
+Count = 227
+Adata = e13a204e16f42bbf4716e95f1cb7e125ffac66a87f591c8ef2c7b8485ff707fd
+Payload = 239fa31d4a65de0318bfc5b60a06d706c129dcf255ac
+CT = 00c18eae4ac501fc501312cfa9a9130daa27180e17c626aa8aa37e858cd990f5593d9ef35f2a
+
+Count = 228
+Adata = c4591c3ad984a1e189c526b719212f8248289eeb277827272b8205d78191eb2d
+Payload = 57caadbb1a56cc5b8a5cf9584552e17e7af9542ba13e
+CT = 749480081af613a4c2f02e21e6fd257511f790d7e354d81e424d6b4528901ae46fb35f8b3106
+
+Count = 229
+Adata = cf4795bc7f43c30d3c3a8fd1b8a9d77d69bf59eb8b59d0f464315f40cb52335d
+Payload = a68c74e05f0a44d4a0372c0e5915b83d8e6729efacbb
+CT = 85d259535faa9b2be89bfb77faba7c36e569ed13eed1f25a4bfda35e1390f3f16f638dcd4047
+
+[Plen = 23]
+
+Key = 40f1aff2e44d05f12126097a0f07ac0359ba1a609356a4e6
+Nonce = 0df3fc6396f851785fca9aa5ff
+
+Count = 230
+Adata = e9699b20b0574fce8b5cbc4ef792eb96e2c1cce36b1b1f06ea2a95fe300633cc
+Payload = 8d98c580fb366f330dbfda20f91d99a0878b47efd14c6d
+CT = 579cdf9da62a2df471e03450516adb4ce99ae0f70b1776a39c3b429a1f922fac0b59e29a122e43
+
+Count = 231
+Adata = bd94c9ad6253c25dc417f87b6e52e03621ccf4b3bff5b402677aeb51e216335f
+Payload = 7391ba60fabe2c632bbaca16af9a235b2c7dae61691c0b
+CT = a995a07da7a26ea457e5246607ed61b7426c0979b3471067bf538e40f9366adf8758968f06ce8a
+
+Count = 232
+Adata = 4f263cda4a50b0e5379ec2fb546b326a07943527c1d175c029455a917753883b
+Payload = 7e1e93a6ca35a2c0e4f08fdb2e7ee22b9f486f0ab919e2
+CT = a41a89bb9729e00798af61ab8609a0c7f159c8126342f964a1199251b54f419720a30de83161de
+
+Count = 233
+Adata = 4d43702be4f0530319555d7f1a3356160f6cae48051f12e22a153d7e405c1149
+Payload = f94ff053c7413f34f96eae41fd1ac101151069af5a9428
+CT = 234bea4e9a5d7df385314031556d83ed7b01ceb780cf33b417e4cceb8dcf45ef33cc0007755bbc
+
+Count = 234
+Adata = f4d7978fad36223623ccb5bb18a7373cba8a6e3b1c921259e319266042db8887
+Payload = ba0716355fffb8ef947d2a15eb58375a1ff1084c566990
+CT = 60030c2802e3fa28e822c465432f75b671e0af548c328bd35aed57f49dcfecf248cf9d246ac024
+
+Count = 235
+Adata = 12e4fe727b1f27a619dd67bb976ddc2b18b2ef8b7184290d9553494a500d933e
+Payload = 872940780a94680a791c937994ceafd2c8b7a22b5f4927
+CT = 5d2d5a6557882acd05437d093cb9ed3ea6a6053385123c97cda0e04d2ff65c2e06a8276bdf6f97
+
+Count = 236
+Adata = 2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57
+Payload = d71864877f2578db092daba2d6a1f9f4698a9c356c7830
+CT = 0d1c7e9a22393a1c757245d27ed6bb18079b3b2db6232b3494dd2ee0a0fe5bfc9f69234c8142ed
+
+Count = 237
+Adata = cefc4f2fb796c2502329ca3d8f8af3200dd9edb8f164e15acec90536a15b6fdc
+Payload = cda681aa3109ebf5f21ee3a849098ea3a551e844fae4b4
+CT = 17a29bb76c15a9328e410dd8e17ecc4fcb404f5c20bfaf9008ead8e923997508eebf5e776198dc
+
+Count = 238
+Adata = 94fc7eb8febb832097ba6eecd2697da91b5a8a1f2248f67a7659e0ac55a09a0d
+Payload = d4f8d262870b5000a40b8fcce88f55c65c4d12e729975e
+CT = 0efcc87fda1712c7d85461bc40f8172a325cb5fff3cc45f136cc6ea1b0fdb554e0803053875b89
+
+Count = 239
+Adata = 459085184094e302b2e921cc04270b676e75bbcf0e4b53ed387df2bd0e75e0ac
+Payload = 732f211061c0a32c6ad124c58418d560ef5eab2602314c
+CT = a92b3b0d3cdce1eb168ecab52c6f978c814f0c3ed86a575da8ceccae093888daaf92c95817fc3d
+
+[Plen = 24]
+
+Key = 91f9d636a071c3aad1743137e0644a73de9e47bd76acd919
+Nonce = 1bf491ac320d660eb2dd45c6c3
+
+Count = 240
+Adata = 3bdfd7f18d2b6d0804d779f0679aaa2d7d32978c2df8015ae4b758d337be81dd
+Payload = 4eaf9384cad976f65f98042d561d760b5a787330dc658f6c
+CT = 635530cab14e3d0a135bb6eebb5829412676e6dd4995f99cb7e17f235bd660e7e17b2c65320e9fd4
+
+Count = 241
+Adata = 9de45b7e30bb67e88735b8fb7729d6f3de46c78921b228bad8f17cc9c709c387
+Payload = 59bee7d18fd4ba573f3e4f61076f5b9f6a3487e47d98c729
+CT = 7444449ff443f1ab73fdfda2ea2a04d5163a1209e868b1d99f40890c7d650afccda40fb2a4cd603b
+
+Count = 242
+Adata = 783477f981ef0551b5e7a714b640bbb38316c53756c96e30c898cdee3b72e6f4
+Payload = 4e7f3c86d846ff351db81dbe1d2e9ed73ec0450587ae681b
+CT = 63859fc8a3d1b4c9517baf7df06bc19d42ced0e8125e1eeb50236cf1a12a9e3542a4051788f9775a
+
+Count = 243
+Adata = 2851d40243512a43f70f9c25e9b18c122a1433f05c61e65017e197e88b129e43
+Payload = 2db7cb2739c839383b64c2c93c7d5c906d984756c3dedaa9
+CT = 004d6869425f72c477a7700ad13803da1196d2bb562eac59b1bbad9861192df356c6678b2f561ea3
+
+Count = 244
+Adata = 1cfa2d62cc1f6313fb0c6eb21803e09cdf61ee3ddb15192529560e5d8096cafb
+Payload = 2f2b82497c78369890809460d80a16be4f3330e8a0089165
+CT = 02d1210707ef7d64dc4326a3354f49f4333da50535f8e7951da4211d4c28d2d91568117fc99fd911
+
+Count = 245
+Adata = 5a14b556156191b2704936f64df0bf1dd2bd8d587418f4f85472338fcf86aa52
+Payload = 7cfefca725da1b6bb5d9545e3e50f5a624a8160bdb0e7d4e
+CT = 51045fe95e4d5097f91ae69dd315aaec58a683e64efe0bbeda99be0e054bb881a25a74b547d3ed5e
+
+Count = 246
+Adata = 148de640f3c11591a6f8c5c48632c5fb79d3b7e1cef9159c680d71fd1f9801fa
+Payload = 5205165c4e9612974dc92f60d1e328d68aa9466e27dbd499
+CT = 7fffb5123501596b010a9da33ca6779cf6a7d383b22ba2694c1fedb47fa30ff2ead6bf382431b2de
+
+Count = 247
+Adata = f852e38703097cc37c589b7860dbc333e091411462d5576dc9909a8cf6ac99d4
+Payload = f968f2833427abbc9fe1cab7e7a3f905a3b23a35802029ff
+CT = d49251cd4fb0e040d32278740ae6a64fdfbcafd815d05f0f338762a4e4299615c67130a28b56a383
+
+Count = 248
+Adata = 43df03a0e23c7ad0d13485150ca224c0b3f39d4e5f2d718db6308e003d3dc683
+Payload = 67da6ca42655188af0b8e389152b2a1b6e2c3ed88926afa5
+CT = 4a20cfea5dc25376bc7b514af86e75511222ab351cd6d9559dbdf61387294812f483aad76d48d899
+
+Count = 249
+Adata = b297dce04ada2ddebc7e94eff7c51b87eee2f98c410c5c0919d0652653ab7458
+Payload = 9777cf90dd7c7e863506686fc3ba6d3d05328f78b350f92f
+CT = ba8d6cdea6eb357a79c5daac2eff3277793c1a9526a08fdf078177541e19b11dfec995f40c99af70
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT256.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT256.rsp
new file mode 100644
index 0000000000..e9cd7eefe9
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT256.rsp
@@ -0,0 +1,1383 @@
+# CAVS 11.0
+# "CCM-VPT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Nlen = 13
+Tlen = 16
+
+[Plen = 0]
+
+Key = c6c14c655e52c8a4c7e8d54e974d698e1f21ee3ba717a0adfa6136d02668c476
+Nonce = 291e91b19de518cd7806de44f6
+
+Count = 0
+Adata = b4f8326944a45d95f91887c2a6ac36b60eea5edef84c1c358146a666b6878335
+Payload = 00
+CT = ca482c674b599046cc7d7ee0d00eec1e
+
+Count = 1
+Adata = 36c17fd901169e5b144fdb2c4bea8cd65ad8acf7b4d3dd39acf2ad83da7b1971
+Payload = 00
+CT = 67747defe5da5fecc00b9bf3b249f434
+
+Count = 2
+Adata = 9a37c654ab8e5a0c6bdfff9793457197d206ed207d768cbc8318cfb39f077b89
+Payload = 00
+CT = c57ef5d0faf49149c311707493a4cfd4
+
+Count = 3
+Adata = 5ab80169184541393a6975f442ee583cd432d71a6d1568fa51159df7c5b8f959
+Payload = 00
+CT = bc2fb5571a7563bb90689a229d2f63a7
+
+Count = 4
+Adata = c78a22a667aafab0c94047e03837d51b11490693d5c57ea27b901ff80b6a38f9
+Payload = 00
+CT = 428888c6420c56806f465b415a66e65a
+
+Count = 5
+Adata = e11e30cbf63623816379f578788b0c8e6b59ee3c9c50aa6e1dcd749172d48fed
+Payload = 00
+CT = 9f1b7520025e1075731adc946b80121d
+
+Count = 6
+Adata = 05716168829276ff7ab23b7dd373db361e6d9e1f11d0028d374a0d3fe62be19f
+Payload = 00
+CT = bd36b053b6a90f19e3b6622cba93105d
+
+Count = 7
+Adata = 3e915389639435629fcc01e1b7022d3574e2848e9151261ad801d03387425dd7
+Payload = 00
+CT = 458595a3413b965b189de46703760aa0
+
+Count = 8
+Adata = 2f496be73a9a5d9db5927e622e166c6ec946150687b21c51c8ca7e680f9775ac
+Payload = 00
+CT = 8b259b84a6ee5669e175affca8ba3b1a
+
+Count = 9
+Adata = 0a8725bd8c8eab9ed52ca47835837b9f00a6c8d834ab17105b01eb4eb30402e7
+Payload = 00
+CT = c5f35fdf2b63e77a18d154f0ddcfedbf
+
+[Plen = 1]
+
+Key = cc49d4a397887cb57bc92c8a8c26a7aac205c653ef4011c1f48390ad35f5df14
+Nonce = 6df8c5c28d1728975a0b766cd7
+
+Count = 10
+Adata = 080f82469505118842e5fa70df5323de175a37609904ee5e76288f94ca84b3c5
+Payload = 1a
+CT = a5f24e87a11a95374d4c190945bf08ef2f
+
+Count = 11
+Adata = f6cfb81373f1cbb0574dda514747d0099635b48cb809c6f1fa30cbb671baa505
+Payload = 40
+CT = ffd43c5f39be92778fdce3c832d2d3a019
+
+Count = 12
+Adata = 5a88b14bada16b513d4aa349b11ce4a77d4cda6f6322ff4939ad77d8ecb63748
+Payload = 41
+CT = fe753b7b661f1aad57c24c889b1c4fe513
+
+Count = 13
+Adata = a92b95b997cf9efded9ff5e1bff2e49d32e65f6283552ded4b05485b011f853f
+Payload = 06
+CT = b91c5ac66e89bf2769ef5f38a3f1738b24
+
+Count = 14
+Adata = a206a1eb70a9d24bb5e72f314e7d91de074f59055653bdd24aab5f2bbe112436
+Payload = c8
+CT = 773fe64379cea1a8ae3627418dd3e489a2
+
+Count = 15
+Adata = d3029f384fd7859c287e38c61a9475d5ddbfd64af93746b1dc86b8842a8c194c
+Payload = e2
+CT = 5dabc529442ff93005551b7689bcb748f7
+
+Count = 16
+Adata = 51ca3d3b70b5e354451a5177d7acfd8e7b44eae55e29d88b5e8eb8fc1e5c62fc
+Payload = 1a
+CT = a5ee68e416617ac974b3d1af7320cd51f6
+
+Count = 17
+Adata = 8c6c6791f1ac957b18bf008e260a0af4a5b7bfdb1e0008d6eaaa227f45cf4f62
+Payload = dd
+CT = 6243883d93d7066991e0fac453400b4fbf
+
+Count = 18
+Adata = b0a1af969a95025385b251afd1e89f353426ed6e5d71019cd73366aa31d5b464
+Payload = 4c
+CT = f3b940d416f3435812f9d1b18f441b7721
+
+Count = 19
+Adata = 7e72b2ca698a18cb0bf625f5daddb0d40643009db938340a9e4fe164a052fee1
+Payload = 88
+CT = 371d27e9a32feea28a6a7e7da2d27e1cc4
+
+[Plen = 2]
+
+Key = 36b0175379e7ae19c277fe656a2252a82796309be0f0d4e1c07fdde88aca4510
+Nonce = 021bd8b551947be4c18cf1a455
+
+Count = 20
+Adata = b5c6e8313b9c68e6bb84bffd65fa4108d243f580eab99bb80563ed1050c8266b
+Payload = be80
+CT = ecacc3152e43d9efea26e16c1d1793e2a8c4
+
+Count = 21
+Adata = 38e5032c5949c2668191ef1af5bb17eddc28abdb4e5bb41eaffec2523b2525d6
+Payload = 82c9
+CT = d0e5d06bf4b50ccce0b2acfd16ce90a8854d
+
+Count = 22
+Adata = 0b50f5173249fb7118f80d25874d6745d88e4ce265fa0dd141ad67ae26c31122
+Payload = 8239
+CT = d0158d784f486c1dc4a2bafd5b02ca1e1c05
+
+Count = 23
+Adata = 0296743a3125b103a2b2a78a109e825ea10834bd684215ab2e85cc4172e37348
+Payload = 16c1
+CT = 44eda3377002a48f9fe306d157358e6df37d
+
+Count = 24
+Adata = a94e64becb803e211785ba51db7f3db042fbf44a7a821509156a6828b0f207e9
+Payload = 2801
+CT = 7a2df6c09bf1dcb1c82bd98c6e2c13a8d7a5
+
+Count = 25
+Adata = 105358cc17b12107e023a23d57b44c66a2c58d8db05100311575e1ea152fc350
+Payload = 65e7
+CT = 37cb2ea363c0d8864363056467570959ba03
+
+Count = 26
+Adata = 669f9a63cf638a202dca1965c4116273249813ce0b39703887d89bdf5b3b12d6
+Payload = 819d
+CT = d3b16519377e6d0252b5f80cdf3d0253eccf
+
+Count = 27
+Adata = e288590a3eba28ac6847a50b0294ab6bd0a548716ff5102c44a5b656b2d9ddd6
+Payload = 761e
+CT = 24329a4dee6ca2cde473f08f76f779856c3c
+
+Count = 28
+Adata = 5b222aae3c7786c3b9021ba672f9136190ec931cf055f84c85706127f74c6d5b
+Payload = 56de
+CT = 04f29e65c0f01e644e74092253b470cd5511
+
+Count = 29
+Adata = 2082f96c7e36b204ad076d8b2f796cccf5cbc80b8384b53a504e07706b07f596
+Payload = b275
+CT = e059809fa107f379957b52ac29fe0bc8a1e2
+
+[Plen = 3]
+
+Key = ddb739acda6c56ec9aefc4f4cbc258587f443da4e76ddfa85dbe0813a8784944
+Nonce = 0bddf342121b82f906368b0d7b
+
+Count = 30
+Adata = 887486fff7922768186363ef17eb78e5cf2fab8f47a4eb327de8b16d63b02acb
+Payload = db457c
+CT = 54473c3f65d6be431e79700378049ac06f2599
+
+Count = 31
+Adata = 0683c20e82d3c66787cb047f0b1eb1c58cdde9fb99ee4e4494bbf27eb62777d1
+Payload = 62a6c5
+CT = eda4853b186edc15c22ba24e470eb5a072da9f
+
+Count = 32
+Adata = 413074619b598f8bed34cab51ddf59941861ba0169ebe7570a5ed01d790c08e5
+Payload = cc67bc
+CT = 4365fc52a1fb5a58bd51931230c1a7dfb1a8c1
+
+Count = 33
+Adata = 2d65a5175c29a095dc082dab9cfcf4b895efbfa715c57614589d4db159543ce9
+Payload = 33800b
+CT = bc824b7d3810f59176cb108c7e969da51d4d79
+
+Count = 34
+Adata = 6a831b6059456be98e6fce608d8c71cb8efb04a96b45c2dfbdaeabf5420a1482
+Payload = b2c826
+CT = 3dca6646ffea832595c9c86e6517215541ddbd
+
+Count = 35
+Adata = 3a04a01160402bf36f33337c340883597207972728c5014213980cd7744e9e41
+Payload = d7e620
+CT = 58e460e89a6725f0fc35622d89d2f3e34be90a
+
+Count = 36
+Adata = 64d8bd3c646f76dc6ce89defd40777fe17316729e22ba90f6a2443ee03f6390b
+Payload = 795af4
+CT = f658b4b1bd7ad5d81686aeb44caa6025d488bd
+
+Count = 37
+Adata = 7bef8d35616108922aab78936967204980b8a4945b31602f5ef2feec9b144841
+Payload = 66efcd
+CT = e9ed8d0553c801f37c2b6f82861a3cd68a75e3
+
+Count = 38
+Adata = 92f7dc22dcbbe6420aca303bd586e5a24f4c3ed923a6ebe01ec1b66eee216341
+Payload = 78b00d
+CT = f7b24de3eeb8ea6c08b466baf246b3667feb3f
+
+Count = 39
+Adata = 71bf573cf63b0022d8143780fc2d9c7dbd0505ac31e9dce0ad68c2428b0878a0
+Payload = 9dd5e1
+CT = 12d7a11db811640c533794bfec6eeb977233ec
+
+[Plen = 4]
+
+Key = 62b82637e567ad27c3066d533ed76e314522ac5c53851a8c958ce6c64b82ffd0
+Nonce = 5bc2896d8b81999546f88232ab
+
+Count = 40
+Adata = fffb40b0d18cb23018aac109bf62d849adca42629d8a9ad1299b83fe274f9a63
+Payload = 87294078
+CT = 2bc22735ab21dfdcfe95bd83592fb6b4168d9a23
+
+Count = 41
+Adata = 75c3b3059e59032067e9cd94d872e66f168e503bcf46bc78d82a4d4a15a29f6e
+Payload = 0f28ee1c
+CT = a3c38951b5de3331078aa13bd3742b59df4f661a
+
+Count = 42
+Adata = 8fb9569f18a256aff71601d8412d22863e5a6e6f639214d180b095fa3b18d60e
+Payload = d41c9c87
+CT = 78f7fbcae52afe7326a12a9aaf22255a38d4bd0d
+
+Count = 43
+Adata = 8b62d9adf6819c46c870df8a1486f0a329672f7d137bb7d8659f419c361a466c
+Payload = 046bc0d8
+CT = a880a7957543692a72f0d599de48b5e5f5a9413f
+
+Count = 44
+Adata = fd98f8f39dfa46ea5926e0ffacbabbe8c34205aade08aa0df82e1d4eaaf95515
+Payload = 39bd4db8
+CT = 95562af530fc357f5482b9004d466bf858586acb
+
+Count = 45
+Adata = 09bf4f77a9883733590a3cc7ee97f3c9b70f4db255620e88cd5080badc73684c
+Payload = b43cdd3a
+CT = 18d7ba77a9e8db046fdd548b52d40375c1e9a448
+
+Count = 46
+Adata = 40326d765e0f6cf4b4deccb128bebf65a7b3c3e5bcf1d58f6158e1e9153b7e85
+Payload = e0052e9b
+CT = 4cee49d64efbdd4ad8d3e863172d9372fca07c20
+
+Count = 47
+Adata = aa5ae6dcdc21b5446489bdabf5c6747bdf3bbfdb3de2c03170efefe5ccb06d69
+Payload = 696825f6
+CT = c58342bb95bd661b32bc18025808f8b4035acad6
+
+Count = 48
+Adata = d3d34f140a856e55b29471fde4c0e5f7306b76d03faab26db79c10f95ffb3122
+Payload = 7eb07739
+CT = d25b1074ac05b072264e31a4b2801a6d790512d7
+
+Count = 49
+Adata = 648a84813ca97aef4ab7e143ee29acb946388660f18eb671194646e0b0136432
+Payload = 9cad70b1
+CT = 304617fcc00514d260e1d211de361c254369e93a
+
+[Plen = 5]
+
+Key = bc29a16e19cfbe32bf4948e8e4484159bc819b7eec504e4441a1a98ca210e576
+Nonce = 4f18bcc8ee0bbb80de30a9e086
+
+Count = 50
+Adata = 574931ae4b24bdf7e9217eca6ce2a07287999e529f6e106e3721c42dacf00f5d
+Payload = 3e8c6d1b12
+CT = 45f3795fcf9c66e1a43103d9a18f5fba5fab83f994
+
+Count = 51
+Adata = 99cd9d15630a55e166114f04093bd1bb6dbb94ecaad126fe5c408dee5f012d9f
+Payload = 76fc98ec66
+CT = 0d838ca8bb6f3cd579294f706213ed0f0bf32f00c5
+
+Count = 52
+Adata = 1516fdf7a7a99f3c9acc7fff686203dec794c3e52272985449ddf5a268a47bc3
+Payload = 6564c247cc
+CT = 1e1bd603117d38e026f706c9273dbcb6dc982751d0
+
+Count = 53
+Adata = 0c9c35be98591bf6737fc8d5624dcdba1a3523c6029013363b9153f0de77725b
+Payload = c11b9c9d76
+CT = ba6488d9abc3e46166767c6ad2aeffb347168b1b55
+
+Count = 54
+Adata = e74afe3ba960e6409dba78ecb9457e2a4ce2e09792b1d2e3858f4c79f7ddba62
+Payload = 45a4e0d7dd
+CT = 3edbf4930033a7dca78bcbf4d75d651ee5fadff31b
+
+Count = 55
+Adata = 96cbe9cd193513599c81f5a520fabaff51ee8cbdb81063c8311b1a57a0b8c8fd
+Payload = e5861b2327
+CT = 9ef90f67fa11585167c83105ee16828a574c84ac86
+
+Count = 56
+Adata = 2e7ea84da4bc4d7cfb463e3f2c8647057afff3fbececa1d20024dac29e41e2cf
+Payload = f5b5bcc38e
+CT = 8ecaa88753ffaba456f78e431f4baa5665f14e1845
+
+Count = 57
+Adata = be125386f5be9532e36786d2e4011f1149abd227b9841150d1c00f7d0efbca4a
+Payload = b6cc89c75d
+CT = cdb39d838034714731f9503993df357954ecb19cd3
+
+Count = 58
+Adata = 3fa8628594b2645bc35530203dca640838037daeaf9cf8acaa0fb76abf27a733
+Payload = 3802f2aa9e
+CT = 437de6ee436c1b008b7572752f04362b2bfdc296bb
+
+Count = 59
+Adata = 642ae3466661ce1f51783deece86c38e986b8c0adea9e410e976f8a2fe0fe10f
+Payload = e082b8741c
+CT = 9bfdac30c1a3f7c3c29dc312c1f51a675400500e32
+
+[Plen = 6]
+
+Key = 5f4b4f97b6aa48adb3336c451aac377fde4adf47897fd9ccdf139f33be76b18c
+Nonce = 7a76eac44486afdb112fc4aab9
+
+Count = 60
+Adata = a66c980f6621e03ff93b55d5a148615c4ad36d6cbdd0b22b173b4b1479fb8ff7
+Payload = 1b62ad19dcac
+CT = 4ad1fcf57c12b14e0e659a6305b4aeffae82f8a66c94
+
+Count = 61
+Adata = c13f65bd491cb172a0f7bbc4a056c579484b62695e90383358d605307d5be0a5
+Payload = 3ef0faaa9b79
+CT = 6f43ab463bc779fa7932d365e2da9b05c00a7318384a
+
+Count = 62
+Adata = 59dcca8fc50740831f8f259eb55d4db11f763a83187d93758d78d166f4d73cd5
+Payload = 1a98ddbf35f1
+CT = 4b2b8c53954f813229912137b7a4945dc07cea24a974
+
+Count = 63
+Adata = 578509ca4f57aadb78056794bf18b0714090970db786e2e838105e672165761c
+Payload = f46a7b1c28ea
+CT = a5d92af088546e045f19f737a24c8addf832ed3f7a42
+
+Count = 64
+Adata = 696c0c6427273cf06be79f2206c43af9cbda0b884efaf04deba0c4bf0a25cb26
+Payload = e98f5e5a20d0
+CT = b83c0fb6806edaae8a7dcd3b0fbb59438f88743ec6e8
+
+Count = 65
+Adata = 95a66b60249ed086eecaeb9bc449afcee9de212619e87516ca947351b25120df
+Payload = 06319c0480e2
+CT = 5782cde8205cd9cb636ca6543c4e35964f47341f2814
+
+Count = 66
+Adata = 2b411bea57b51d10a4d2fb17ef0f204aa53cf112e1130c21d411cdf16a84176d
+Payload = f4c723433b7c
+CT = a57472af9bc2ec82eadf4eb1f055da1a92a82052ab8b
+
+Count = 67
+Adata = ff3bff3a26fc5a91252d795f7e1b06f352314eb676bff50dc9fbe881c446941e
+Payload = 02f809b01ce3
+CT = 534b585cbc5d01b10a7ae24a4ca2bfb07ea2a3b31a97
+
+Count = 68
+Adata = f6be4aad63d33a96c0b5e9c4be62323c9e2308b29961fff980ba0dbda0549274
+Payload = 2b6004823a29
+CT = 7ad3556e9a97231323a4b88af5d7d0b07c0e73ddce1d
+
+Count = 69
+Adata = c3706a28d7420b41e072dcecc06b6b13116cca110bde8faea8e51f5107352d71
+Payload = 236c60cba4fa
+CT = 72df31270444db30eb33d2ede33abbe22f37704fe68b
+
+[Plen = 7]
+
+Key = f7aaeff3a1dc0cc5ecf220c67ad9f6dda060b4f1be3cc609cb4f18b2342a88a2
+Nonce = d0d6871b9adc8623ac63faf00f
+
+Count = 70
+Adata = e97175c23c5b47da8ce67811c6d60a7499b3b7e1347ad860519285b67201fe38
+Payload = d48daa2919348d
+CT = eb32ab153a8e092fa325bafc176a07c31e6cc0a852d288
+
+Count = 71
+Adata = ba45e1859efae362a44a0116a14e488ba369da6c76c3913b6df8e69e5e1111fa
+Payload = f95b716bfe3475
+CT = c6e47057dd8ef1a24840f4f40a7963becde3a85968b29c
+
+Count = 72
+Adata = efcaa6f6cda3036b0b52ff9f36bc38ca74049c32c6b7cdfb8a46ca4144bacd64
+Payload = 4862e3677083f0
+CT = 77dde25b5339748f2a4a5c276727e0a210fc2efb5aeabe
+
+Count = 73
+Adata = 360bcb407603fe92f856bf677625b9882521e6dae8f35fdfc3dc737f9398f609
+Payload = 7f1ca0728f6d65
+CT = 40a3a14eacd7e1051734fc31232ab2ab63474020ab4dc9
+
+Count = 74
+Adata = f12ee9d37946cfd88516cbe4a046f08c9bbba76a3973ff1e2cb14493405bd384
+Payload = 67478ef73290fa
+CT = 58f88fcb112a7ec715244f307609ffa253e4e3659b0ece
+
+Count = 75
+Adata = 5833dde0c577b2be4eb4b3d01d7b0042fa8441ad7043ea462bbbbd56a59790ea
+Payload = 36bb9e511276c5
+CT = 09049f6d31cc41f11047da612d2987fa2e50ada5ae7f9d
+
+Count = 76
+Adata = 1e103c63d8ead36b985f921044cd32b8f9f04a2ba9fa154a09e676ffaa093970
+Payload = d68d6556c5a5b1
+CT = e932646ae61f35382f7648718127ebae7eb7443ebd2c2c
+
+Count = 77
+Adata = a1cfb61d45a140bdea6329ba0fe80429ff9aa4624a1d31bc752f7c97f1d390a0
+Payload = 0568cca4ff79dc
+CT = 3ad7cd98dcc358cc40a5e7fffb1fb9a5dd9d6ba91bede1
+
+Count = 78
+Adata = 116b5b015e44ceef0061b2d2e73fa0b386d5c1e187782beebdfc6efb5a1c6935
+Payload = bd93d08eea4263
+CT = 822cd1b2c9f8e7468d2b70c311732f11ed72b57d83e500
+
+Count = 79
+Adata = 3d55882e6f3f89309b6940a3b408e573458eedd10fc3d0e1f3170eb313367475
+Payload = 4fb62753024e92
+CT = 7009266f21f416b41a70f548e359add30c0e5746fbeb2b
+
+[Plen = 8]
+
+Key = 493e14623cd250058a7fc66a3fee0c24b6e363b966c2314aff53b276b6c2ea7b
+Nonce = fe2d8ae8da94a6df563f89ce00
+
+Count = 80
+Adata = 579a637e37a0974cd2fc3b735d9ed088e8e488ffe210f043e0f9d2079a015ad6
+Payload = e5653e512d8b0b70
+CT = 75d31f8d47bee5c4e2ba537355ae8ab25cc9ed3511ff5053
+
+Count = 81
+Adata = 1583138aa307401dddc40804ac0f414d338fc3ffb2946f09aaaa7079426fc1ee
+Payload = 2c4ba9ce52e01645
+CT = bcfd881238d5f8f1781a9e359804831f31a1efb1ae1cb71d
+
+Count = 82
+Adata = 78d3dda40e433bba7a330ca3e5bd5170f0895f2e3e438402344ced79fcb0c719
+Payload = 5eb2d054a0e58c62
+CT = ce04f188cad062d62dcc77c4e1fe2bafd477598977835f0c
+
+Count = 83
+Adata = dfc762466fa84c27326e0ee4320aa71103d1e9c8a5cf7d9fab5f27d79df94bd6
+Payload = bbbf7830d04ab907
+CT = 2b0959ecba7f57b308946723baf0dbf613359b6e040f9bd5
+
+Count = 84
+Adata = 7e8ea82d1137c1e233522da12626e90a5f66a988e70664cb014c12790d2ab520
+Payload = 10c654c78a9e3c06
+CT = 8070751be0abd2b2003bd62ca51f74088bbbd33e54ac9dd4
+
+Count = 85
+Adata = 873da112557935b3929f713d80744ed08b4b276b86331dbc386fba361726d565
+Payload = 668d32e322e1da3e
+CT = f63b133f48d4348a67e65e7f2cdedf6ef8cc0ee7a6dcfb02
+
+Count = 86
+Adata = cfba97919f703d864efc11eac5f260a5d920d780c52899e5d76f8fe66936ff82
+Payload = e39f6225e8eab6cc
+CT = 732943f982df58780532f8c6639e5d6c7b755fcf516724e3
+
+Count = 87
+Adata = 01abcfee196f9d74fcaa7b69ae24a275485c25af93cc2306d56e41e1eb7f5702
+Payload = 6021a00f6d0610a4
+CT = f09781d30733fe107fd7a33828413ebc252dd9d015773524
+
+Count = 88
+Adata = ce1c31e7121c071d89afab5a9676c9e96cac3d89dcae83136bbb6f5ca8f81e5d
+Payload = bbaf0ac4e77ee78d
+CT = 2b192b188d4b0939d3d51368799325ad1c8233fa071bade0
+
+Count = 89
+Adata = bb210ca5bc07e3c5b06f1d0084a5a72125f177d3e56c151221115ae020177739
+Payload = 98a2336549a23a76
+CT = 081412b92397d4c25d1ea568637f773174a7f920a51b1fe1
+
+[Plen = 9]
+
+Key = b23255372455c69244a0210e6a9e13b155a5ec9d6d0900e54a8f4d9f7a255e3a
+Nonce = 274846196d78f0af2df5860231
+
+Count = 90
+Adata = 69adcae8a1e9a3f2fe9e62591f7b4c5b19d3b50e769521f67e7ea8d7b58d9fc8
+Payload = 615d724ae94a5daf8d
+CT = f019ae51063239287d896e7127f17d13f98013b420219eb877
+
+Count = 91
+Adata = 162d0033c9ea8d8334d485b29eef727302135a07a934eea5fee6041e9f1f47c1
+Payload = 0d9168eeab3b27ba69
+CT = 9cd5b4f54443433d997cc2cd61da9358b4045fef32f8192cbf
+
+Count = 92
+Adata = 3f4ab57efa32f51a4c00790280e77c0e55b85bbda4f854e242368e9a289b5a81
+Payload = 6287dcffdd5fb97885
+CT = f3c300e43227ddff75d280f0ffdd560fb8915978e3bd6205bb
+
+Count = 93
+Adata = 945d18134c148f164b39fd7c4aef0335045553f6ea690a3b1726418d86f0de00
+Payload = 6e5e01b3fd71d16b9c
+CT = ff1adda81209b5ec6c7dbf90420a1ff2e24bd6303b80cfc199
+
+Count = 94
+Adata = 23af12893431b07c2922ab623aed901c0eaaeb9a24efc55273e96aea4dab7038
+Payload = b51521e689b5247362
+CT = 2451fdfd66cd40f492d741f4329ae7cc77d42bf7e5f2ec5ab6
+
+Count = 95
+Adata = b15a118b3132c20c31e6c9d09acdee0e15fcc59d6f18306442682512d22eb10f
+Payload = 7f973617e710fb76fe
+CT = eed3ea0c08689ff10ec9ffdcc2f36edac14613b1d85baf25a9
+
+Count = 96
+Adata = dcfbeb6490f5fa7eaf917462473a6cec98bebf8f17493fe9b994119a6d5a5457
+Payload = 7e909b6727ac3fd02f
+CT = efd4477cc8d45b57df5a61a28bb10265b26043d7a8dd357713
+
+Count = 97
+Adata = 77e9317294f046f315a0d79e3423f29f7d9ebcd36d6eaa2a3fb2f4500309478c
+Payload = a5075638932b5632f8
+CT = 34438a237c5332b508d321c371ae1fd01bdf3b6c75a597da6e
+
+Count = 98
+Adata = 3aa8f204eb127b547e13873ed0238018394e13686c8734e49e3e629deb352c77
+Payload = c10f15a0de78db8aa3
+CT = 504bc9bb3100bf0d539393d1635bc40ac62405a39155406c47
+
+Count = 99
+Adata = 7f67e6f97c6c258f014d721a4edaaa0ddb3f9f09993276ab7b714ea9356c231d
+Payload = 8294f830cfca42cfbe
+CT = 13d0242b20b226484eff89641e1bd5ad6cc827441b17c45ecf
+
+[Plen = 10]
+
+Key = dbf06366f766e2811ecd5d4384d6d08336adc37e0824d620cf0d9e7fd1e7afa9
+Nonce = b3503ed4e277ed9769b20c10c0
+
+Count = 100
+Adata = 9ae5a04baa9d02c8854e609899c6240851cbc83f81f752bc04c71affa4eed385
+Payload = 2e3cf0af8c96c7b22719
+CT = e317df43ab46eb31be7e76f2730d771d56099a0c8d2703d7a24e
+
+Count = 101
+Adata = da77c6d5627a2aa34911bd1f7cc5f8aa68a2c6546adc96a186b9af8e5baac4cf
+Payload = e081c43a07450ce0dfa2
+CT = 2daaebd62095206346c5bcc7a8260ef361dc39fdb776d041f0d4
+
+Count = 102
+Adata = 134d2d9726400d09dd3521326f96fbef993ddc0c4088770057b0f8d70356456f
+Payload = c381d2ae5e72fc82324a
+CT = 0eaafd4279a2d001ab2d19f0cbb0899f221aac9762f2650f8058
+
+Count = 103
+Adata = 0d065dfde1de1f21784c7869eb566c977f807cfbd53578f4616995b51d7dc045
+Payload = 737f4d00c54ddca80eec
+CT = be5462ece29df02b978b3dc92a9bd26b9653e5917359c331fcff
+
+Count = 104
+Adata = 95c54d187f2415535451cbb9cb35869749b171f7043216ce6886dd77baeecf60
+Payload = 4e9e251ebbbbe5dbc8ff
+CT = 83b50af29c6bc958519891dda72c27d272561e00f7041845d998
+
+Count = 105
+Adata = 0f98039e6a9fe360373b48c7850ce113a0ff7b2ae5ce773dd4c67ca967cd691b
+Payload = 0db72b281ab4046d15a6
+CT = c09c04c43d6428ee8cc1928ac628758ad58fc1b5a768d4722848
+
+Count = 106
+Adata = ad840bc55654762e5eba0e4a9e7998992d990a06d70da1b1ca922ef193dab19a
+Payload = 4f7b4f38ff1ba4df5a59
+CT = 825060d4d8cb885cc33ed11dad4dc8b265a53cf0bdd85c5f15f4
+
+Count = 107
+Adata = 911e9876ea98e1bcf710d8fd05b5bf000ea317d926b41b6015998ee1462ab615
+Payload = 58ce55379ef24b72d6d6
+CT = 95e57adbb92267f14fb18eb659a5a7084be48d099467da4395df
+
+Count = 108
+Adata = 3f68a4fb4043bcf9b6d277c97e11365d949c705bd6679c6f0aaf52e62330ad79
+Payload = a219028a953ce1544835
+CT = 6f322d66b2eccdd7d1523b2b2583fd117cec47b1c84d3863159e
+
+Count = 109
+Adata = 02f32242cba6204319075ea8ce806a57845355ae73e6b875955df510096ebff9
+Payload = 83b0ee9a52252c456105
+CT = 4e9bc17675f500c6f8625456eb2b6a2d35c649a84051f843153c
+
+[Plen = 11]
+
+Key = 4dd555bd3a5253a90b68b5d4d46bd050340ee07ddad3a72048c657b5d76bb207
+Nonce = bdb1b82ba864893c2ee8f7426c
+
+Count = 110
+Adata = 9bcc5848e928ba0068f7a867e79e83a6f93593354a8bfcfc306aeeb9821c1da1
+Payload = 8015c0f07a7acd4b1cbdd2
+CT = 8e9f80c726980b3d42e43a6512a0481255b729a10f9edb5f07c60c
+
+Count = 111
+Adata = c2e75952ab49216f305e3776865791ce877cef8c0229ca97561787093fddf1d8
+Payload = c97b62a719720b44b7779c
+CT = c7f122904590cd32e92e748c514444f00ffdb80a4bb7e9eb651946
+
+Count = 112
+Adata = c76a3ff4e6d1f742dd845be2d74c1a9b08e418909b15077deb20373ef55caf91
+Payload = cb7c17ef62464ecc8008f6
+CT = c5f657d83ea488bade511edb609dfc1929ac1ba5753fc83bf945b7
+
+Count = 113
+Adata = bdb69f99f9a144b9ad88c6cfd8ffb8304c201de9b2818552ce6379e6042c1951
+Payload = 893a690cc5221de597d0e8
+CT = 87b0293b99c0db93c9890053b74283296d0fca83b262915289163c
+
+Count = 114
+Adata = 01815f599d6ba0d1c09f6f673bb6cca4c2a7a74f4e985be4c0f37842c7bbc5a4
+Payload = 80f3e4245c3eab16ef8bf0
+CT = 8e79a41300dc6d60b1d21888a34955893059d66549795b3ac2105c
+
+Count = 115
+Adata = a9db62e9ab53c4a805c43838ce36b587d29b75b43fb34c17a22d3981120f3bc5
+Payload = 641c6914920a79943dca39
+CT = 6a962923cee8bfe26393d1377c4e2f20aaa872a9a0b1d1d7f56df0
+
+Count = 116
+Adata = f0c2cc5a1b4c4cbe839338fa0d7a343514801302aef2403530605cf4f44d2811
+Payload = 2286a1eddd80737a724ca9
+CT = 2c0ce1da8162b50c2c15415545aa0c1dd11551891ae553d3a91908
+
+Count = 117
+Adata = 9842922499ad4d487488b3731f48765efe0b4eb59e7b491ba5f6636f09ed564d
+Payload = d8c63e7d7d332198249c0c
+CT = d64c7e4a21d1e7ee7ac5e4d9e07ec5806360843676ef27d811b246
+
+Count = 118
+Adata = 399b71ecb41f4590abda79045cdf6495f27daaa559c1b34f513b5c4ac105ec10
+Payload = 4b81804d777a59b6a107cf
+CT = 450bc07a2b989fc0ff5e27483b8727c5753ede25e1fab0d86963be
+
+Count = 119
+Adata = 2c186c5c3463a4a8bad771feb71e2973c4f6dede2529827707bf4fa40672660f
+Payload = dfc762466fa84c27326e0e
+CT = d14d2271334a8a516c37e64b5c3c1dc577ee8fcf6ef3ebc0783430
+
+[Plen = 12]
+
+Key = d3ad8cda9a0d91a205c4c05665728bb255d50a83403c9ab9243fcbbe95ae7906
+Nonce = 0b5f69697eb1af24e8e6fcb605
+
+Count = 120
+Adata = ea26ea68facdac3c75ba0cdf7b1ad703c9474af83b3fbfc58e548d776b2529b9
+Payload = a203aeb635e195bc33fd42fa
+CT = 62666297a809c982b50722bd56bc555899345e0404b2938edf33168e
+
+Count = 121
+Adata = 0b32069fc7e676f229f1037d3026c93eef199913e426efd786b524ce1dbde543
+Payload = aac414fbad945a49ae178103
+CT = 6aa1d8da307c067728ede1449b15447c904b671824c2ca24c4fc7ad4
+
+Count = 122
+Adata = 7a8658302e5181552292aa56e8209de63b5d86934167549b0d936202681757e1
+Payload = 7ee0ce371329192618e3cda0
+CT = be8502168ec145189e19ade7ea13850e99ef9300c65f5abc9419d13a
+
+Count = 123
+Adata = 4f05600950664d5190a2ebc29c9edb89c20079a4d3e6bc3b27d75e34e2fa3d02
+Payload = b0a1af969a95025385b251af
+CT = 70c463b7077d5e6d034831e8486c93c31bbedc9e5ffa2f4154bceea9
+
+Count = 124
+Adata = 4530e4dc6a4c3733b8ab7e77e384223cc1a8c179fb66818c08aca47e5c705d89
+Payload = 9f6c6d60110fd3782bdf49b0
+CT = 5f09a1418ce78f46ad2529f7f18b556e7da59fd2549dc57a17bf64f8
+
+Count = 125
+Adata = f179353aef342f0f691caf1fcb811e3f6504e14d6d9381c5439b098ff978b01b
+Payload = 90958d7f458d98c48cbb464c
+CT = 50f0415ed865c4fa0a41260b30aad3a838680cbd313004685a5510c5
+
+Count = 126
+Adata = f6df267e5cbc9d2a67b1c0fd762f891ee3b7c435884cb87d8228091b34aeddae
+Payload = 9f7ae892e5662803408d4d06
+CT = 5f1f24b3788e743dc6772d411d57b89ed0c91251aed37a6ca68a50c7
+
+Count = 127
+Adata = 4372e152b1afd99c7f87c8a51dbc3a5c14c49d04ea1c482a45dfbcda54972912
+Payload = 817074e351455f23cb67883d
+CT = 4115b8c2ccad031d4d9de87ad79a3b0feea16ff5fbca16211ea6fdd9
+
+Count = 128
+Adata = 82b6cd1c6618c42ba74e746075dc28700333578131ca6fde6971d2f0c6e31e6a
+Payload = 1b7da3835e074fdf62f1eb3c
+CT = db186fa2c3ef13e1e40b8b7b49f22737c4b2f9fa0a7e3dd4b067fbaa
+
+Count = 129
+Adata = a5422e53975e43168726677930f6d3e13281bdbd13c67c168340ed67e45d15b0
+Payload = 57473e7a105c806867379194
+CT = 9722f25b8db4dc56e1cdf1d3ef43a48dbea8c1547455ad0197af88a2
+
+[Plen = 13]
+
+Key = e300fc7a5b96806382c35af5b2c2e8e26382751b59010d4b1cfc90a4a9cb06df
+Nonce = 55b59eb434dd1ba3723ee0dc72
+
+Count = 130
+Adata = 9b1d85384cb6f47c0b13514a303d4e1d95af4c6442691f314a401135f07829ec
+Payload = 8714eb9ecf8bdb13e919de40f9
+CT = ba6063824d314aa3cbab14b8c54c6520dac0f073856d9b9010b7857736
+
+Count = 131
+Adata = fa17c693d0997140fbc521d39e042d8e08388106874207ca81c85f45c035d6e6
+Payload = a0837676e091213890dc6e0a34
+CT = 9df7fe6a622bb088b26ea4f20820a423dd30796b6016baff106aaef206
+
+Count = 132
+Adata = 27663597b389b78e96c785ca2f5510c8963a5561d2b0b24c4dcdf8e58562c12c
+Payload = b8a2ce7e051b8d094ec43f2a7f
+CT = 85d6466287a11cb96c76f5d2436032bc79c4aef1f74da25e92b0aa7f8a
+
+Count = 133
+Adata = d8f1a83371487d611ce704e0a6731f97a933c43569690022fce33cb5aecdc0a7
+Payload = 9e4103ab1dfb77ae3494507332
+CT = a3358bb79f41e61e16269a8b0e658123d2e5bb324c7ead8897f8e32b0a
+
+Count = 134
+Adata = 05c57aab99f94b315cf8bdd2d6b54440c097fe33c62a96b98b1568cdee4ce62c
+Payload = fb3e3d1b6394d2daebf121f8ac
+CT = c64ab507e12e436ac943eb0090270758ab09f93fa3ba7d7a2aa8eac789
+
+Count = 135
+Adata = 1c1b0933c508c6a8a20846ebd0d0377e24f4abc0c900d3a92bc409ba14ef1434
+Payload = 549ba26a299391538b56ce4bd7
+CT = 69ef2a76ab2900e3a9e404b3eb2293813f1bcb96564f772e9308e42b2d
+
+Count = 136
+Adata = 9f5cf9149f556124d6bb4e3e243cca1502c02682709392cc2ec7eb262fd4d479
+Payload = 287f31e69880823df7798c7970
+CT = 150bb9fa1a3a138dd5cb46814c81877380d5cf097c2fb5177750f8b53a
+
+Count = 137
+Adata = 1a49aaea6fc6fae01a57d2fc207ef9f623dfd0bc2cf736c4a70aaaa0af5dafd3
+Payload = 040d18b128ae4a1935f9509266
+CT = 397990adaa14dba9174b9a6a5acf42c75787edc62a180568c6ef56545d
+
+Count = 138
+Adata = f29a0b2c602ff2cacb587292db301182e6c76c5110b97ca8b706198f0e1dbc26
+Payload = 92441cbe8d70820870bb01ad63
+CT = af3094a20fca13b85209cb555f56d47a0631f2038103e3904b556ba7a5
+
+Count = 139
+Adata = 01fcf5fef50e36175b0510874ea50a4d2005ad5e40e5889b61417700d827251e
+Payload = f11d814df217de96333dee1cbf
+CT = cc69095170ad4f26118f24e4835be15b7ae24edccd0b0934e3af513ed3
+
+[Plen = 14]
+
+Key = 3ae5be5904bae62609ac525e2d1cad90133447573d7b608975a6a2b16cb2efc0
+Nonce = 61bf06b9fa5a450d094f3ddcb5
+
+Count = 140
+Adata = 0245484bcd987787fe97fda6c8ffb6e7058d7b8f7064f27514afaac4048767fd
+Payload = 959403e0771c21a416bd03f38983
+CT = 37a346bc4909965c5497838251826385a52c68914e9d1f63fd297ee6e7ed
+
+Count = 141
+Adata = 52f6a10a022e5ee57eda3fcf53dcf0d922e9a3785b39fad9498327744f2852e4
+Payload = 23fe445efa5bcb318cc85e2ad1ac
+CT = 81c90102c44e7cc9cee2de5b09ad364b603de6afbc2d96d00510894ccbe7
+
+Count = 142
+Adata = d236e3841b9556b32dbd02886724d053a9b8488c5ad1b466b06482a62b79ebb6
+Payload = 762fdc3e0c30c7ecf2ec8808bb79
+CT = d418996232257014b0c6087963781a4321c2ddbc35ce4864457d611219e9
+
+Count = 143
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+Payload = b6813d5fe8afa68d646c197337a2
+CT = 14b67803d6ba117526469902efa3296e55efebb17fe145cdca9b31ea7bcc
+
+Count = 144
+Adata = 7f291aa463c4babc76b4a6faf2e27e9401586b1ac83e4b06a4090e94b3ef5fd4
+Payload = 4ce8b6578537215224eb9398c011
+CT = eedff30bbb2296aa66c113e9181059270a0510e7cc1b599705853af2144d
+
+Count = 145
+Adata = 06bca7ef6f91355d19f90bf25590a44a24e5a782f92bc693c031e6de1e948008
+Payload = 9ebf93643854ea5c97a4f38f50bd
+CT = 3c88d63806415da4d58e73fe88bcb55847573bf21e946ce9bdc5f569e3ff
+
+Count = 146
+Adata = 5a44ff94f817c7c028a8f3db35a4d01364d2598432469f09ded86e5127d42d35
+Payload = da989cc7d375ed5fac4d7f938d74
+CT = 78afd99bed605aa7ee67ffe25575b8a61c5687ea02f0276824b8316b76f1
+
+Count = 147
+Adata = 2a755e362373ef27a911c4d93ca07bc97135645442ad7ad6a8ef98146c71e9d7
+Payload = 6fbab5a0f98e21e4d15904af5948
+CT = cd8df0fcc79b961c937384de8149a07ee02791011129fcacffcfb1bf4145
+
+Count = 148
+Adata = f7988873f45a5de314e5381d3f14d8f8c48c9b649bf3e745ed5dc882d507da58
+Payload = b610349e8b370a7c195598573637
+CT = 142771c2b522bd845b7f1826ee36d34204b1ce23f5f58a8eb7cf1fa8cfa7
+
+Count = 149
+Adata = 95d2c8502e28ab3ee2cac52e975c3e7bccb1a93acc33d9c32786f66d6268d198
+Payload = 1d969fd81dab5ced3e6ee70be3bf
+CT = bfa1da8423beeb157c44677a3bbe9c618bb88bbcefb008a5ea6bed4ff949
+
+[Plen = 15]
+
+Key = fab62b3e5deda7a9c1128663cc81c44b74ab1bfe70bc1c9dec7c7fd08173b80a
+Nonce = a5c1b146c82c34b2e6ebeceb58
+
+Count = 150
+Adata = 5e60b02b26e2d5f752eb55ea5f50bb354a6f01b800cea5c815ff0030b8c7d475
+Payload = 54be71705e453177b53c92bbf2ab13
+CT = 788db949697b8cd9abbc74ed9aa40cd6852dc829469368491149d6bb140071
+
+Count = 151
+Adata = 210c04632341fbfc185bfe3cbf6fe272bbe971104173bcb11419b35ab3aaf200
+Payload = 22197f9ad14591e7a6d5f8b18c969a
+CT = 0e2ab7a3e67b2c49b8551ee7e4998556940dc5a7e44bf10234806d00a012b5
+
+Count = 152
+Adata = d3a205dd017e79a67400a937a20ef049f4c40d73311731f03ab857a3f93bd458
+Payload = 096b2f530933c1273304a6ad423726
+CT = 2558e76a3e0d7c892d8440fb2a38390898f7dbde25b0b70d335df71a06987b
+
+Count = 153
+Adata = 0c9b3ba4faf5fc2f310ad1bab06c4ca13474b714feeffb6ad615c1b850bbd6a3
+Payload = d44fdfd9da3a63c1083afe574e91bf
+CT = f87c17e0ed04de6f16ba1801269ea02fd10d1f21b6b963c05aeda8eb09e272
+
+Count = 154
+Adata = d9bb71ad90152d5c1af358c8501fa89ebd4b17bf4ff43841528cccb79fd791b3
+Payload = 8d836acc13ed83c2b2c706415c9679
+CT = a1b0a2f524d33e6cac47e0173499664491d23d90ff55abca17e9d943b98c7f
+
+Count = 155
+Adata = 69dc21eb6f295b12ba493ee8fe6c40d78af946067ce772db316a3cbf00d3c521
+Payload = 2a68e3fe746f593c1b97cb637079c3
+CT = 065b2bc74351e49205172d351876dc9616886c6b2adc97db5a673846b6662c
+
+Count = 156
+Adata = 095eb52135dc6d9c1f56a2571c1389852482e7aa3edc245a3904a0449db24a70
+Payload = 39799b001ed2c334c269acb0f2328c
+CT = 154a533929ec7e9adce94ae69a3d932441dcae1760db90379bd354fa99164e
+
+Count = 157
+Adata = efd7270e0396392fde8b0ddaab00544cbbd504f4d97d4e90d749d1946de90dcb
+Payload = 42143a2b9e1d0b354df3264d08f7b6
+CT = 6e27f212a923b69b5373c01b60f8a9c7c7deb28bdcf84886ef843216b94449
+
+Count = 158
+Adata = 8bc181ce2e66294e803a8dc3834958b5f173bc2123c0726e31f3fca25b622ed6
+Payload = a3dcf26327059a4245b79a38bb8db6
+CT = 8fef3a5a103b27ec5b377c6ed382a935061ae3cd892ba63c44b809d6d29421
+
+Count = 159
+Adata = c39ec70c2c71633ae0dccc41477ac32e47638c885cf59f34ebd4a096d32f91f9
+Payload = 3d54883449ecca8f153436c25a0a01
+CT = 1167400d7ed277210bb4d09432051e3c9ae69a4c59ff8e251c2fe022d065a9
+
+[Plen = 16]
+
+Key = ee8ce187169779d13e443d6428e38b38b55dfb90f0228a8a4e62f8f535806e62
+Nonce = 121642c4218b391c98e6269c8a
+
+Count = 160
+Adata = 718d13e47522ac4cdf3f828063980b6d452fcdcd6e1a1904bf87f548a5fd5a05
+Payload = d15f98f2c6d670f55c78a06648332bc9
+CT = cc17bf8794c843457d899391898ed22a6f9d28fcb64234e1cd793c4144f1da50
+
+Count = 161
+Adata = a371ca29b92ed676bab5dfc4d78631bb6d9bb23a29f822907084a1f0fe17721f
+Payload = 60d55a8d5ab591a51e87fdf6aaa2ad25
+CT = 7d9d7df808aba2153f76ce016b1f54c68b55bbe42d8c97504b97c34a5f16e6a6
+
+Count = 162
+Adata = 01ec87920b42639d4ba22adb1fbe5138d2849db670a2960fd94a399c1532ed75
+Payload = cbf112e4fb85276c4e09649f3de225b2
+CT = d6b93591a99b14dc6ff85768fc5fdc51017d8706acd676ae99e93d5312a4113c
+
+Count = 163
+Adata = eebd2bbf1e9f6d817cd8062a6a9680e7f10464eefeb50b07cb46b14b9b3fcb2c
+Payload = 865b89aa38ee1b5a3ce56620307e8937
+CT = 9b13aedf6af028ea1d1455d7f1c370d45982f0fe5d951a8c62c87894657301e4
+
+Count = 164
+Adata = 72863362612f146699f6b2f6ec3688f2ca6cb1505af7a309c91c1933e34d516a
+Payload = a8efc37d1b8b51f2a47b21dd14da383d
+CT = b5a7e40849956242858a122ad567c1de5addfddbb59f4985947fb3a9ab56333e
+
+Count = 165
+Adata = 9c9efc6593f96207678db813608f2b8bc33ed1bef974ed77ed7b6e74b621b819
+Payload = d9b0eaaff786165f882f41a98dbc0c35
+CT = c4f8cddaa59825efa9de725e4c01f5d6b651053516673402a57538db1a9ce7e9
+
+Count = 166
+Adata = dc482a051b58d8a3904d3af37c37b51983f634a504451bbba6f77d71337f8e78
+Payload = df49d972b6ebbbb18ee975ac635d847e
+CT = c201fe07e4f58801af18465ba2e07d9d86d772b1a1991b7be6589bbccad36171
+
+Count = 167
+Adata = 51ef065a43caa23faf750b02a41ad6ba701aeb8058f6d8738d6f6b005bec7f60
+Payload = 78318aa5cd16699b77bdcea2fc9d1d20
+CT = 6579add09f085a2b564cfd553d20e4c3569387a1a6bcc826e94012670820576e
+
+Count = 168
+Adata = 88e2a74d2920c89c6a101f5f06d0624a6d5eabd9bdb51395ee3983934c55c73d
+Payload = 8e20d65d02dd9a64379f75b6d8328f2d
+CT = 9368f12850c3a9d4166e4641198f76cee9c788b4aae9b2c6caf0c44aa9bd2ed0
+
+Count = 169
+Adata = ada3ed7db2dabbfbc441ef68a5656e628d6d5bd6c1574369688497179a77601a
+Payload = 97e8d8513af41b97801de98cc4269096
+CT = 8aa0ff2468ea2827a1ecda7b059b6975f1df0f01944641a1b04d753e6ab8d3cc
+
+[Plen = 17]
+
+Key = 7da6ef35ad594a09cb74daf27e50a6b30d6b4160cf0de41ee32bbf2a208b911d
+Nonce = 98a32d7fe606583e2906420297
+
+Count = 170
+Adata = 217d130408a738e6a833931e69f8696960c817407301560bbe5fbd92361488b4
+Payload = b0053d1f490809794250d856062d0aaa92
+CT = a6341ee3d60eb34a8a8bc2806d50dd57a3f628ee49a8c2005c7d07d354bf80994d
+
+Count = 171
+Adata = 4ae414bc888a42141d3060c71c2dbbffd425b6a952806982271a8e756b3c9e24
+Payload = 51eb190c6a9f46e8ec1628b090795470c0
+CT = 47da3af0f599fcdb24cd3266fb04838df13c1c5755a5a240c33b2b890a486aac8b
+
+Count = 172
+Adata = 7b7f78ae1a5ee96fdc49dacd71be1a6ac09a6a162d44dea0172886eca5674e46
+Payload = 25144e807e389bb0e45b6dc25558caf61a
+CT = 33256d7ce13e21832c8077143e251d0b2b4cfca1c19abf447d7bc0898d61885144
+
+Count = 173
+Adata = 03f31c6143b77f6ad44749e2256306b8bf82242f2821fad4075b09b388ba81ca
+Payload = dbe1ee14abfe2ecf4edf6db206cf9886ce
+CT = cdd0cde834f894fc860477646db24f7bff229cc7a390867a245dcb7c434f1db347
+
+Count = 174
+Adata = 030390adb572f2bd2a6a4454fd68236cd1d465574328aa001d553375cc63f8a2
+Payload = db6df31f12bf552f81deff5fa2a373fc22
+CT = cd5cd0e38db9ef1c4905e589c9dea401135361b539f9fe0fb7842907c2326aef63
+
+Count = 175
+Adata = 7294ae94358669f2ada4b64c125b248df7fe86c6715e3b6a7b9bb2bd99392c8a
+Payload = ff2a97b49fcc6a50d4549c979d53ccc51f
+CT = e91bb44800cad0631c8f8641f62e1b382e8ed10943929e7d7bf798b2ae8371aae5
+
+Count = 176
+Adata = 4d1513478fc1fb0a18eb6d2a9324fefbd975ecd1b409025de826bc397462acc1
+Payload = 73ddfa0185200a890b7690a7e3986d8818
+CT = 65ecd9fd1a26b0bac3ad8a7188e5ba7529f92b9e49ab83f113f8949dc9e4a36e0d
+
+Count = 177
+Adata = b26a7ff61bfe94864249af7cc9b4a723627dd4463f5a22f0ca6063769522eab7
+Payload = 5c7604f9ac8fdf30ee5820e5aeb75b65d7
+CT = 4a4727053389650326833a33c5ca8c98e6d0e53223adff22a08e3dddf66fff23e3
+
+Count = 178
+Adata = 960f9a85cfbfb6eab223a4139c72ce926a680ea8e8ecc3088cf123de659ad310
+Payload = d44fdfd9da3a63c1083afe574e91bf01c9
+CT = c27efc25453cd9f2c0e1e48125ec68fcf833f49a42521a7a2367f91bfcc2180b7c
+
+Count = 179
+Adata = 3718467effb5d5dc009aaefce84d8cb4fe8f80eb608f4c678f5d0de02ea11e59
+Payload = bb515dc227abb9acad8fefaa14771bb77b
+CT = ad607e3eb8ad039f6554f57c7f0acc4a4ac08bd395c6807223311070659f550934
+
+[Plen = 18]
+
+Key = 0786706f680c27b792d054faa63f499a8e6b5ddb90502946235bf74c022d772c
+Nonce = f61ef1c8c10a863efeb4a1de86
+
+Count = 180
+Adata = 67874c808600a27fcab34d6f69cc5c730831ad4589075dd82479823cb9b41dc3
+Payload = 6a26677836d65bd0d35a027d278b2534e7df
+CT = d1c1f3c60603359c7d6a707f05ecb2296f8e52f2210b7a798ad5c778ee7cfd7fe6e0
+
+Count = 181
+Adata = e0c27cddf919d3092d9a34766c89a5ae6dcf39fe954d1e6f1a70ddf96805def4
+Payload = 4021ff104ff1dbd91e46db249fd82198b0a1
+CT = fbc66bae7f24b595b076a926bdbfb68538f00923bb5a347af13df12f234fca5f03ef
+
+Count = 182
+Adata = 7ae9eca03f616ab39ebb3be26b848842b4aa584e5c8e5695065ad5af34951175
+Payload = 6a681f164efce199a787bccff223b8ae1a98
+CT = d18f8ba87e298fd509b7cecdd0442fb392c9d03ed7bffac83e890caceb6903d9cab5
+
+Count = 183
+Adata = b47c9bc4eb01c74f5db2e6a293bef80db18c58cf06feef7ee0f8a7a9a51c22bb
+Payload = 7861dac338ba3f8274dca04c8c6f92b6d44c
+CT = c3864e7d086f51cedaecd24eae0805ab5c1d4dd8f30870025b2bd1e2a2511574d3e7
+
+Count = 184
+Adata = f6afd661f218c7426b92ee53e65d14898cd0c78a7e594fcc6ac0e3fb5cab1c9c
+Payload = a3f0473c620d2739d5ba4f7156f88d0fb669
+CT = 1817d38252d849757b8a3d73749f1a123e386046d17f337f3cb49884d94995edbdc9
+
+Count = 185
+Adata = d3802911e341577046cfc61d9043b4af059fb4bef3c6a2ff46ccdcb05670af37
+Payload = 07c535d9456a6ff1e41321150d16dae3f7a3
+CT = bc22a16775bf01bd4a2353172f714dfe7ff25fdc77b43bca254d6459263cdfed8fbb
+
+Count = 186
+Adata = db60720db67a60ca286fe744d46173c231fbcc7deb4c9b0d87d52a2247e06b74
+Payload = 5ee220720a896249efdab2ce418318bb5ebf
+CT = e505b4cc3a5c0c0541eac0cc63e48fa6d6eedd1a1d36c8164c55d55dbf0ff1e9517a
+
+Count = 187
+Adata = 57f70ba5493265b30491decc726354e2065e7971a2efd56db9cf0f79b1d76859
+Payload = 98e4eb0361c8bf40bcbe0539b0850e4c35ff
+CT = 23037fbd511dd10c128e773b92e29951bdaeb476e2ca48fd52bec0539b00744a8a07
+
+Count = 188
+Adata = 4a29b9ad548964942f87f28ba267ec0d0e8f72c73b3823ee57693dd63c2605c1
+Payload = 7f0745bea62479c0080ecec52e37c1e32d72
+CT = c4e0d10096f1178ca63ebcc70c5056fea523fad68c62b81d62f2d490ae74f5bb1465
+
+Count = 189
+Adata = acbd2e9911b3218a230d9db5086d91dccac3fc93fc64b0f4a15d56954906b2b7
+Payload = e99ed2ac6c38e033061b5d85f3e77dd72518
+CT = 527946125ced8e7fa82b2f87d180eacaad4913b15d8000266c61ba5aec898eb35b52
+
+[Plen = 19]
+
+Key = bac55f9847d93325bf5071c220c0a3dfeb38f214292d47b4acb7b0a597fe056f
+Nonce = 05b50c458adbba16c55fcc454d
+
+Count = 190
+Adata = 89ad6ae1e550975eaa916a62615e6b6a66366a17a7e06380a95ea5cdcc1d3302
+Payload = c1a994dc198f5676ea85801cd27cc8f47267ec
+CT = 7c9b138177590edaafec4728c4663e77458ffbe3243faec177de4a2e4a293952073e43
+
+Count = 191
+Adata = dfddb719d00398bf48a6cefd27736389e654a93b8595cd5ac446af1996e0f161
+Payload = 791e232bfb42fb18197adc1967da1a83f70168
+CT = c42ca4769594a3b45c131b2d71c0ec00c0e97f8422f736fc435687634d42254b22fd99
+
+Count = 192
+Adata = 58ef310997dcaf067dd217274921504da6dbf0428a2b48a65fe8a02c616ac306
+Payload = 3d4127942459bb8682e662dfc862467582fa68
+CT = 8073a0c94a8fe32ac78fa5ebde78b0f6b5127f38a96e68ef7dbaef1b460cc0980eacd4
+
+Count = 193
+Adata = 511e5d5e100b595f6b20e791830bca37e23f7b785e482a58405bffe7a632a5b8
+Payload = 0e71863c2962244c7d1a28fc755f0c73e5cbd6
+CT = b343016147b47ce03873efc86345faf0d223c15c5c702a82d468929227502e4e35796f
+
+Count = 194
+Adata = e48dfaa53b6807ea6f01d8dca67960b9f321f7851f324459a9bf61fe0be73abb
+Payload = e0f1cd013e6aea4fa484fc3fa35d348b1a2399
+CT = 5dc34a5c50bcb2e3e1ed3b0bb547c2082dcb8e89188c0940182dd99a902d158c5b0810
+
+Count = 195
+Adata = c12c0423fe36e4c88775dd00b4af267b85b7dd2a37a742a3156923c8917c97a3
+Payload = b1cc1946b4fc1dbd033254cdf536f61e9f9cd7
+CT = 0cfe9e1bda2a4511465b93f9e32c009da874c015849acbb7af1892790300bb84fb0558
+
+Count = 196
+Adata = 4255f8af18df7237e0abe98421aec9634443561752d893aaffe76380e829ef32
+Payload = 87284658928208e3bddca83e3ceb13708d88d4
+CT = 3a1ac105fc54504ff8b56f0a2af1e5f3ba60c3e75aaf3077ac6dfb5454851ec3910de6
+
+Count = 197
+Adata = ab83567833d2f3461b5fbecc0e366694bb5ea00933b2b3e792ec3aefe20325df
+Payload = bdb79f931ef3035a33bdd1b032fd9de8f6b2ba
+CT = 008518ce70255bf676d4168424e76b6bc15aade70f42e3e1f2b5bb58433bd11f5dea1f
+
+Count = 198
+Adata = bd1446ba3185d1c16551730947c22142142caa8cc1c540e89ab734ec297401bc
+Payload = 1f9c3a8eb8bc59f3869e10f73883aa8f8990cb
+CT = a2aebdd3d66a015fc3f7d7c32e995c0cbe78dc564f6248cefe5fc7cfb547c90a558925
+
+Count = 199
+Adata = b87577755d2d9489194f6f7cfabf267dc3433a9c91954e81beb72c5e06870922
+Payload = 5f28809181f9a889894da8d6fe1fde6cce354a
+CT = e21a07ccef2ff025cc246fe2e80528eff9dd5db52249d812f7f235afa0732e984e91b2
+
+[Plen = 20]
+
+Key = 8beedeb85d42c2a7fa6f7237b05acb197dd8e1672471ac878064fe5319eab876
+Nonce = 8479bdfad28ebe781e9c01a3f6
+
+Count = 200
+Adata = 7aebdfd955d6e8a19a701d387447a4bdd59a9382156ab0c0dcd37b89419d6eff
+Payload = 7b125c3b9612a8b554913d0384f4795c90cd387c
+CT = 6cc611d816b18c6847b348e46a4119465104254a04e2dfeeeac9c3255f6227704848d5b2
+
+Count = 201
+Adata = d119f300fbd74e754a200ea2c3f9fabc1466d02078c84245db693eef3f5672a6
+Payload = 8b013f5782d5d1af8dbd451a4202866095dac975
+CT = 9cd572b40276f5729e9f30fdacb7e67a5413d44338d48329997c5981d678b5e24a6f01b0
+
+Count = 202
+Adata = d6204303b86acf62d5ab860ca70161288ede56e3cf017c08dca56fd2d6f8f6fe
+Payload = b2b1d82a5523b72ea366a680922ed3a4624536c4
+CT = a56595c9d58093f3b044d3677c9bb3bea38c2bf2a77e3ab68e0a73519591a33ed098b758
+
+Count = 203
+Adata = 8557e22eb4529b43f16b1f8ae47c714ac8a2c827c1408a47704778b4c5b52601
+Payload = f8c4eb4285d3d7744da52775bb44ca436a3154f7
+CT = ef10a6a10570f3a95e87529255f1aa59abf849c1cff6c24251c2fb7b8604dfa10c60ef4a
+
+Count = 204
+Adata = 8c1a4187efbb3d38332f608f2c8bbe64247d9afa2281ced56c586ecb4ab7a85e
+Payload = 6e7fe35fa39c937a0e6b3a8c072e218650f42b8d
+CT = 79abaebc233fb7a71d494f6be99b419c913d36bb6c3c39f915d081d34559179869b32d81
+
+Count = 205
+Adata = a41bb1f256228302cd0548ae2148ff42774d18c2d6d3e38b36bc4938da13bac3
+Payload = 917b467d841850fc6e648f1bc298a7f9f1ee38ca
+CT = 86af0b9e04bb74217d46fafc2c2dc7e3302725fc9389a6a6a74c6eb0e1f87562469f2082
+
+Count = 206
+Adata = b0b024e20c4f75a6dad54c21a9edbce846792e957878b1c8ed2d916c757e2b3c
+Payload = 2b4314fe1a6bfa786b7cfc13fbee861b348efbf6
+CT = 3c97591d9ac8dea5785e89f4155be601f547e6c03bed3a2f5dfdbfcc0d7ac26c88d1962c
+
+Count = 207
+Adata = 42153925c46fc9d5d328312d62f59bb99fdc4ac479a3386d5f88fefd4b32f577
+Payload = e19fa7f83c79920cbff45c41a9dee8fc99e97396
+CT = f64bea1bbcdab6d1acd629a6476b88e658206ea035ea1d99be344fa1467ee91c73bbca67
+
+Count = 208
+Adata = 37ab2a0b7b69942278e21032fc83eba6cdc34f5285a8b711a08da6acd42299fe
+Payload = 53e0475cf492b3d39dad600f5c58eb0bd0021554
+CT = 44340abf7431970e8e8f15e8b2ed8b1111cb08627936ec10a81b36768b606e9a38b2f4c5
+
+Count = 209
+Adata = 4a17522da707b4b2587a0ae367a2cd2831bb593a18ef442a7977eda6de045878
+Payload = c119a383d9a3d4bff4270a1d22076b346db5f61c
+CT = d6cdee605900f062e7057ffaccb20b2eac7ceb2a11575ae03ea8a57bbe4a67c060367b74
+
+[Plen = 21]
+
+Key = c3a0c126cad581012151c25cf85a44472c23f83b6095b6004f4f32cd60ec2db2
+Nonce = 94ab51ce75db8b046d6ab92830
+
+Count = 210
+Adata = 2a243246bfe5b5ab05f51bf5f401af52d5bbaa2549cf57a18e197597fe15dd8c
+Payload = 73b09d18554471309141aa33b687f9248b50fe3154
+CT = b7e8264ca70fd2a4fb76f20a8ad5da3c37f5893fb12abeeaef1187f815ca481ed8ddd3dd37
+
+Count = 211
+Adata = 0595306eb7441622a49800edee0134492d82320707fceba902af2e0c95fe634a
+Payload = b64d00f3a4df754fa4ee6376922fb67ccce0c6209f
+CT = 7215bba75694d6dbced93b4fae7d95647045b12e7accc2b55011dbe92ce7619e0ad48b4ccf
+
+Count = 212
+Adata = bd439dbefec589e120fb4f9825b315bf86523b85c61791cd4da4c8d474ba2714
+Payload = 2b11d1ac74ffe701ec733d32085b1054132726e622
+CT = ef496af886b444958644650b3409334caf8251e8c71e8b1f4d70d8f4c7df4f22847d36b394
+
+Count = 213
+Adata = cfebe1cf82267394065bcecfada6709c6c35a3ac835644f560d4c9a8c1848364
+Payload = a88f22424643a523aa3d7d88f4364f1290f49dd0a2
+CT = 6cd79916b40806b7c00a25b1c8646c0a2c51eade47a85e76a9d07b7b361ca56d53c34cda50
+
+Count = 214
+Adata = 7a37255b682766a0bfecf78e5162528885a339174c2a49325739d2bd8877e64f
+Payload = c81427bc84c6a3cfefd4c4cb210fe82212977e1947
+CT = 0c4c9ce8768d005b85e39cf21d5dcb3aae320917a2fddb010e7508ad03ad287068ecee6020
+
+Count = 215
+Adata = 619f2ae80070e278615466a3fd6c9acb7b510c5679bed7038889c77e78d8bd32
+Payload = 28c4d6de3e2ce51b849b135d9cfd3084f0e3155447
+CT = ec9c6d8acc67468feeac4b64a0af139c4c46625aa2ddea785e6c470c52c4fdf432fd78b66e
+
+Count = 216
+Adata = b2571e56f66a857daffbdc99370ceddd4a7bed3867d600cc797000a3b7b57a9d
+Payload = 4c88151cafef75832bacef43a06e862349d56b67ee
+CT = 88d0ae485da4d617419bb77a9c3ca53bf5701c690b91232cfbd7ffff252498b35274fb2995
+
+Count = 217
+Adata = db409636e3e3bcd606a91aeb7592009896f9ad2c4cc6b7f578e6ad59c0f8fa22
+Payload = 572855e22ce89bc2bcf09cb15a1765d99973449d61
+CT = 9370eeb6dea33856d6c7c488664546c125d633938472b2c50e5e391ad104f9ee33b94f2872
+
+Count = 218
+Adata = 62c89a835721207a182968c516dc8be45774ec846e8dcab9ab8611888f2a76a8
+Payload = 89ce46b3de3afaf2518d419b1a2ac24cabca269a96
+CT = 4d96fde72c7159663bba19a22678e154176f5194732d69c5d6db1b130102af3dae0690673b
+
+Count = 219
+Adata = 33f30ddd83002eea50fd4a8fae39d0980a04160a22ac88b755ac050f1d1f8639
+Payload = edf1682a626e9fbf3d57bb260e0876c6f92ba5b114
+CT = 29a9d37e90253c2b5760e31f325a55de458ed2bff1489903365970c2673c9fd457e1077aad
+
+[Plen = 22]
+
+Key = 9cdebaeee8690b68751070691f49593668a6de12d3a948b38ddbd3f75218b2d4
+Nonce = af1a97d43151f5ea9c48ad36a3
+
+Count = 220
+Adata = f5353fb6bfc8f09d556158132d6cbb97d9045eacdc71f782bcef62d258b1950a
+Payload = 3cbb08f133270e4454bcaaa0f20f6d63c38b6572e766
+CT = 3966930a2ae8fdd8f40e7007f3fde0bd6eb48a46e6d26eef83da9f6384b1a2bda10790dadb3f
+
+Count = 221
+Adata = e3a1555ffe5f34bb43c4a2dae9019b19f1e44a45fb577d495d2a57097612448d
+Payload = 946e86795c332031e2d1ee09d3d4a101fb6800d00911
+CT = 91b31d8245fcd3ad426334aed2262cdf5657efe408a5587bdd120a7d08cd3841cb117af444fb
+
+Count = 222
+Adata = 9c5d43c1a1269cde199509a1eff67cc83a1759b71c9e7a6ee99f76b98c6e23a6
+Payload = b76ce2ab0065ba1c0a754494991c8c452cb416f18ab1
+CT = b2b1795019aa4980aac79e3398ee019b818bf9c58b0545b32f81dcf03e2bcc2aaf62ad366e97
+
+Count = 223
+Adata = b07452a7900a289b91b2771dfdd5108852536659aa259def7b41e38f80bd03ab
+Payload = a3e0d8d0784155bfc45769c52711d4fa68e8bc390c20
+CT = a63d432b618ea62364e5b36226e35924c5d7530d0d94fea17d78533bc9e022dbfb460afdf499
+
+Count = 224
+Adata = 6b30f55c3101540523a92380390f3f84632f42962061b2724cde78ac39809397
+Payload = 6e6a88abbb52a709b47365ad6aa8016fa9a03a9bd834
+CT = 6bb71350a29d549514c1bf0a6b5a8cb1049fd5afd98056defc6dcaeec80b1c639350ab6f1fde
+
+Count = 225
+Adata = 9fc62d14f8b7a6026509275cff80312ff1ade2b5d9c274cb72a506a571439fc1
+Payload = eba1810d537041821121aeff8e0914ac26a550072c8c
+CT = ee7c1af64abfb21eb19374588ffb99728b9abf332d389d37b7251fb8c0ef2b37c36d51219d0f
+
+Count = 226
+Adata = 6b9389cc42113d639fd2b40cbc732ae0dc7c14513b88b36b45a6ea5a06fe4d2b
+Payload = dfc6692cd2442e5ff1f918c8812a27f81d107d16a12f
+CT = da1bf2d7cb8bddc3514bc26f80d8aa26b02f9222a09bd279d9da4437c8a2a252436508134c56
+
+Count = 227
+Adata = db72d98d63fc10acff7dceec0e2691a80ecee50a0e957ad166c77952a50318bd
+Payload = 9ad338cbfd1b52e6ae4178f05e00062274f8b0b25eae
+CT = 9f0ea330e4d4a17a0ef3a2575ff28bfcd9c75f865f1a63943543bc1c5f5991ecc5964a288f79
+
+Count = 228
+Adata = e98b710c47a4d12a73cd8aa2613fc2910c16f4195ea7f15650132493521d19be
+Payload = 9f5a05db89e0e336da066ce81b79ad9be1d0ec4fb7b8
+CT = 9a879e20902f10aa7ab4b64f1a8b20454cef037bb60c0a49ee2b7ceddcbd28abb24b77d5edee
+
+Count = 229
+Adata = 527817316fc48b105f8ab178dd2db1fefa09c50461aa9d8bdf3c03482343bbf9
+Payload = 58f31e5770070a5d4031fb795dc2d298561d3559960d
+CT = 5d2e85ac69c8f9c1e08321de5c305f46fb22da6d97b9b099a68cfa3572d974e03232e09f37fb
+
+[Plen = 23]
+
+Key = d34264a12c35cdd67ac105e2826b071e46f8131d1e325f8e0ae80a6447375135
+Nonce = 3891e308b9f44c5b5a8b59004a
+
+Count = 230
+Adata = 0cda000ed754456a844c9ed61843deea9dadf5e723ea1448057712996d660f8c
+Payload = 79ac1a6a9eca5e07ce635bfd666ef72b16f3f2e140d56c
+CT = 1abcc9b1649deaa0bfa7dcd23508282d9c50ca7fee72486950608d7bcb39dcf03a2cab01587f61
+
+Count = 231
+Adata = 3fb6ddb76809b8e6d703347664ef00a365955124c603900d5c8d4ff476138252
+Payload = 76d12e3c4c5d990bf563c60aa4999e52998d887f97477f
+CT = 15c1fde7b60a2dac84a74125f7ff4154132eb0e139e05b1c4fb40e5c8bc37152a173d4bbb18c3e
+
+Count = 232
+Adata = d9fc295082e8f48569eb073ac1b9566246728fc62ccaab4a5667c472c98b2626
+Payload = a027c28fbe22111fd4c8a226cfe8531c16d7790d561eca
+CT = c33711544475a5b8a50c25099c8e8c1a9c744193f8b9ee019c359008adae3070b5a543ead0effb
+
+Count = 233
+Adata = 7a459aadb48f1a528edae71fcf698b84ed64dc0e18cc23f27ab47eeabeaf833f
+Payload = fa597e37c26c38694abdcf450f9edc529160fa0d651979
+CT = 9949adec383b8cce3b79486a5cf803541bc3c293cbbe5dbd099ab134756b90746762a92a4a9f7f
+
+Count = 234
+Adata = 484207909dec4c35929ebe82fcacf20d2af6d850bd69364ebac9557adeadfbd4
+Payload = 9e4c8aa9b58a8eabc5586892f5541000b43f17d9a051a0
+CT = fd5c59724fdd3a0cb49cefbda632cf063e9c2f470ef684fa4f6adfec85d055310107ba89198afa
+
+Count = 235
+Adata = 88b5448372548e6aab1b262630a28a471d285514703f1bdb10c695850e18fe6d
+Payload = 7d9582cf9e3bb9ee34dce965f56b08e716589486b0641c
+CT = 1e855114646c0d4945186e4aa60dd7e19cfbac181ec338915d23eb2e952afcc89fbddb567d9d75
+
+Count = 236
+Adata = 0e71863c2962244c7d1a28fc755f0c73e5cbd630a8dbdeb38842d7795d830d2e
+Payload = 5a387e7cc22491fc556fe6a0c060b4911d01f0c11f801e
+CT = 3928ada73873255b24ab618f93066b9797a2c85fb1273aaad6c31828314e24198f005955ca8f5e
+
+Count = 237
+Adata = 2aa7a28da38c42fda2e578d9d6340cd8e80b9b32047c3db296d0640d517b0872
+Payload = 87946e910059cbaf48df63b220f397049c65ca10cd1920
+CT = e484bd4afa0e7f08391be49d7395480216c6f28e63be04e531ebbadccfe47182b41904bbfebcfe
+
+Count = 238
+Adata = 3382051c268891da04e6ca73adcead4029f6a1593be4acfe3968e7351a6a2fb5
+Payload = c62f67d208f1c8ffd5d57df9de15ef54f97fbc07d1630a
+CT = a53fb409f2a67c58a411fad68d73305273dc84997fc42e7c582414154236c09ee704cf4a5de411
+
+Count = 239
+Adata = c352828b1920e53bbb60f2ea6a5f15639659e6f3243405c26f6e48628d5519a9
+Payload = 697e73eaaf562d31bdbf7ce9e78c7426fe1c87e421def9
+CT = 0a6ea03155019996cc7bfbc6b4eaab2074bfbf7a8f79dd57c9990029c89d1b37988745fa5737a3
+
+[Plen = 24]
+
+Key = 4ad98dbef0fb2a188b6c49a859c920967214b998435a00b93d931b5acecaf976
+Nonce = 00d772b07788536b688ff2b84a
+
+Count = 240
+Adata = 5f8b1400920891e8057639618183c9c847821c1aae79f2a90d75f114db21e975
+Payload = 9cea3b061e5c402d48497ea4948d75b8af7746d4e570c848
+CT = f28ec535c2d834963c85814ec4173c0b8983dff8dc4a2d4e0f73bfb28ad42aa8f75f549a93594dd4
+
+Count = 241
+Adata = 1ae8108f216defea65d9426da8f8746a3ae408e563d62203063d49bf7e0d6bdf
+Payload = 2b223932fb2fd8433e4b1af9e8234a824569a141f6c96a69
+CT = 4546c70127abacf84a87e513b8b90331639d386dcff38f6f4de907a59c5e4d3f21e1348d7cdf92b6
+
+Count = 242
+Adata = 460f08114b1015fe8b7a9b5dd1b9e6a3d28367c4bd15f29b13c02a8cb9a53968
+Payload = 4d57cbe4a7e780d4ed17267d5ebc91750c2f0209e0444bd2
+CT = 233335d77b63f46f99dbd9970e26d8c62adb9b25d97eaed4ff4239544e2f354d6c6837cd9c23b884
+
+Count = 243
+Adata = 860f4428259d9c5b17698cc95363db6cfee603258582e3a3e8feb886599d4ac4
+Payload = fda8665f87c618646a89c7abdca275fd10c31453ad4b9c99
+CT = 93cc986c5b426cdf1e4538418c383c4e36378d7f9471799f3f6c6f7cc494201069344e2d6d41bd9b
+
+Count = 244
+Adata = 1b43c482f83780c21583f88e5afcf6938edd20f21b74d895161b60c27a6a42f0
+Payload = 98104fd3f3413ad1f57ef4912cb50097dca379a58c47b0d2
+CT = f674b1e02fc54e6a81b20b7b7c2f4924fa57e089b57d55d43787a15352cfceb028202c8730beaa7a
+
+Count = 245
+Adata = b082ccd964617c27a5607b7324faad237ee53acfc18c35502dbf7c1937a9dfcb
+Payload = b46b343e64d2d70e0bd909dbb3f6bedf7e4adc74321be526
+CT = da0fca0db856a3b57f15f631e36cf76c58be45580b210020f3a0ca3da647eb31893e867956097983
+
+Count = 246
+Adata = b8539ba93ef17254ec1d8d62e8f4eae4d41ee1e75345bf90c9cbb26c63bce501
+Payload = 8e12620bb575e6b167b085255b2b5631ff28e04cbef8826d
+CT = e0769c3869f1920a137c7acf0bb11f82d9dc796087c2676be663fbbebbc251b9f1760afa49e89e71
+
+Count = 247
+Adata = b6b09463b5ef5ead1f17f4021693a0d8452e98dcbb8e7590f9fde6394970a6f8
+Payload = 792aaa23b923d1b53173fe19853b9aa402a301d48529873e
+CT = 174e541065a7a50e45bf01f3d5a1d317245798f8bc136238da90cd87e9d9ca5d85430a150e682752
+
+Count = 248
+Adata = 390f6de14d5e1f2f78dbe757c00b89209d0cf8bc48cbbea035779f93de357905
+Payload = ddc5b4e48970ebd72869be6998e9103c014475e8ae6ea29c
+CT = b3a14ad755f49f6c5ca54183c873598f27b0ecc49754479afc0cc4601afb61efa7059cfe49ec9dde
+
+Count = 249
+Adata = 1d75c9e7acb09932db332498d30f82e4009025cb1827047c59a8f97812b568a4
+Payload = d2b66096c475a77648c27235e6972ba8f18761330d3c6adf
+CT = bcd29ea518f1d3cd3c0e8ddfb60d621bd773f81f34068fd9cf7474962c3602dcfcb50039f43e3d6f
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT128.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT128.rsp
new file mode 100644
index 0000000000..a05492b485
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT128.rsp
@@ -0,0 +1,393 @@
+# CAVS 11.0
+# "CCM-VTT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Nlen = 13
+
+[Tlen = 4]
+
+Key = 43b1a6bc8d0d22d6d1ca95c18593cca5
+Nonce = 9882578e750b9682c6ca7f8f86
+
+Count = 0
+Adata = 2084f3861c9ad0ccee7c63a7e05aece5db8b34bd8724cc06b4ca99a7f9c4914f
+Payload = a2b381c7d1545c408fe29817a21dc435a154c87256346b05
+CT = cc69ed76985e0ed4c8365a72775e5a19bfccc71aeb116c85a8c74677
+
+Count = 1
+Adata = 79db716e6b0b1627890d378c4560eba7871883d94527be3454dc3c257ea93556
+Payload = 47f4cdd574264f48716d02d616cf27c759fdf787cdcd43b1
+CT = 292ea1643d2c1ddc36b9c0b3c38cb9eb4765f8ef70e84431676e2df1
+
+Count = 2
+Adata = 0d02778f90a164a4f9ada9dc7fd24eeb941069621418ef32c3f9ca6bf6fb2c4a
+Payload = 5eadeaec29561244ede706b6eb30a1c371d74450a105c3f9
+CT = 3077865d605c40d0aa33c4d33e733fef6f4f4b381c20c479eb1321a1
+
+Count = 3
+Adata = 02e5a1306f612bdec098458cff3e691d93f050ba11ba627355dc7029d2cea5ab
+Payload = aac9fb69fed114c62db65090947096a2f5c85c271c6a6d53
+CT = c41397d8b7db46526a6292f54133088eeb50534fa14f6ad3dd8cb4ca
+
+Count = 4
+Adata = 25144e807e389bb0e45b6dc25558caf61a2263869c4d0e4079d07674d7091110
+Payload = fb6e8d38ce38a8c1e710f3a33c682e6dabf055fb33fe75f8
+CT = 95b4e1898732fa55a0c431c6e92bb041b5685a938edb7278b659a844
+
+Count = 5
+Adata = be303c1ed9327ad88dae7cb5930b5a786d4f5477ef9370a9fdb56501964cb8fa
+Payload = 87d81389a6062e8ed501ea964c2fe35b2d3de9fd676c04f7
+CT = e9027f38ef0c7c1a92d528f3996c7d7733a5e695da490377e9e5e005
+
+Count = 6
+Adata = 46dfb8f3e06c3f168e5ac9b341e7710d7b9c6a19b32389eafb58036de0a27756
+Payload = e1bd9095fa9bb811e4054643feea3eac13fb57b43a0502a0
+CT = 8f67fc24b391ea85a3d184262ba9a0800d6358dc87200520c9fc48e0
+
+Count = 7
+Adata = 19eb03c35c352b79e8c32fa40bb9759b0565e04a6c18519ace346e2e9987a250
+Payload = 92f7dc22dcbbe6420aca303bd586e5a24f4c3ed923a6ebe0
+CT = fc2db09395b1b4d64d1ef25e00c57b8e51d431b19e83ec60ac73022c
+
+Count = 8
+Adata = efa6ddd6fb8e4480a0f64414694e5f9e7f2e9b97cbe9cd145b65173d072ab001
+Payload = cecdf831c4044c8fe149e4cd579a1aecf222bf8e9dadba09
+CT = a01794808d0e1e1ba69d26a882d984c0ecbab0e62088bd895dc8d581
+
+Count = 9
+Adata = 1b156d7e2bf7c9a25ad91cff7b0b02161cb78ff9162286b0622fccda2e251c97
+Payload = 7cfb0973ea13dedc33ef6728db90f47559273ea6d3cd4db6
+CT = 122165c2a3198c48743ba54d0ed36a5947bf31ce6ee84a36b941b65b
+
+[Tlen = 6]
+
+Key = 44e89189b815b4649c4e9b38c4275a5a
+Nonce = 374c83e94384061ac01963f88d
+
+Count = 10
+Adata = cd149d17dba7ec50000b8c5390d114697fafb61025301f4e3eaa9f4535718a08
+Payload = 8db6ae1eb959963931d1c5224f29ef50019d2b0db7f5f76f
+CT = df952dce0f843374d33da94c969eff07b7bc2418ca9ee01e32bc2ffa8600
+
+Count = 11
+Adata = 463c65fa7becae5605af80d1feca59075ee88c0abfc72cb463312b3c772ec308
+Payload = bde3fc83287ddd1227bdab4305102c94d885412eb332bf6b
+CT = efc07f539ea0785fc551c72ddca73cc36ea44e3bce59a81a8b847d3a0c98
+
+Count = 12
+Adata = ab153b0a8933f2eb0d721621c86de0cfe100d13e09654824b09d54277912c79d
+Payload = 82176e573c6070faa08d18b5957f119bb1ff51d744b04240
+CT = d034ed878abdd5b7426174db4cc801cc07de5ec239db5531fb4f9d559a8e
+
+Count = 13
+Adata = b22aba8d3e9f4b4bf006e26062de15daf94597731a6009129bfd12957877b1ce
+Payload = bcfc4485eaf225d945146374b737cdf5301c7738ea9f142a
+CT = eedfc7555c2f8094a7f80f1a6e80dda2863d782d97f4035b1e09ff3d6a6c
+
+Count = 14
+Adata = eb80a43c5986deee6925d7c6d53cbdcbe11194843ea133f72d3590d8e8363efa
+Payload = aa182e3ec4fb2f7a905c03582b2ee100ab81a9a311a778bc
+CT = f83badee72268a3772b06f36f299f1571da0a6b66ccc6fcdb60ba1175f1b
+
+Count = 15
+Adata = 3ee186594f110fb788a8bf8aa8be5d4ad52d6e3bd5f406f080d9df0d7553a851
+Payload = 8ad6db8216af16bfda3261a220d078cc98c8ad134e4a80ca
+CT = d8f55852a072b3f238de0dccf967689b2ee9a206332197bb4a75860f3dd6
+
+Count = 16
+Adata = d36fc18b5b12662ff5f6ea55af7c7a82d25d386220e399a85a590b1505c0dcd5
+Payload = a65d24bd1ab92d8d294d654423412860e113c976f12ed76b
+CT = f47ea76dac6488c0cba1092afaf638375732c6638c45c01a00cf106d70a4
+
+Count = 17
+Adata = f0028503e7cd54474c56dc8b2416fe41f416eed73c63ddd141bdd51a0f8fe49c
+Payload = 6e9dc61dd9cf19a6eebc10c9b51c13970636de2c9ea33592
+CT = 3cbe45cd6f12bceb0c507ca76cab03c0b017d139e3c822e3c0193a87ddfb
+
+Count = 18
+Adata = 9a58a226a578bda012dbd7d04b11c879179aaaa36c6145418586cb103360c6c2
+Payload = b526896c11e514b5b4c26351859e2a33800fefd6fd9e6d1a
+CT = e7050abca738b1f8562e0f3f5c293a64362ee0c380f57a6b444d9b63ffab
+
+Count = 19
+Adata = c015fb08540755a8a8adc387d60553478667158964202eb2d25e28efd94c8c76
+Payload = 88907b639f3fd07f40bf6b9b6334b11b2852557975721bf3
+CT = dab3f8b329e27532a25307f5ba83a14c9e735a6c08190c82c339ba21fcf7
+
+[Tlen = 8]
+
+Key = 368f35a1f80eaaacd6bb136609389727
+Nonce = 842a8445847502ea77363a16b6
+
+Count = 20
+Adata = 34396dfcfa6f742aea7040976bd596497a7a6fa4fb85ee8e4ca394d02095b7bf
+Payload = 1cccd55825316a94c5979e049310d1d717cdfb7624289dac
+CT = 1a58094f0e8c6035a5584bfa8d1009c5f78fd2ca487ff222f6d1d897d6051618
+
+Count = 21
+Adata = 25865c1b89f1973bfa680d8458df35a56993a7e81e407e061794004068e481ab
+Payload = 36004342dd74e7966692a848b2c11e1fc311eac9d9cef616
+CT = 30949f55f6c9ed37065d7db6acc1c60d2353c375b5999998ceca422687f41550
+
+Count = 22
+Adata = e6209480da9e49172ba58a9048f2f1b0349030e8e7a79dcdf295eecd613f401a
+Payload = e81f4fb360bcae372d8be3f32655a29bc10a2f31876173cc
+CT = ee8b93a44b01a4964d44360d38557a892148068deb361c42d2b981fc741f2591
+
+Count = 23
+Adata = 112c969882e685b4ae1ee6b67f680e6a1d9d840e627d12118f991c1a3d71314c
+Payload = 27d6443e729d35d7a0690fcb7fe0b20892875f60b5d8763a
+CT = 2142982959203f76c0a6da3561e06a1a72c576dcd98f19b4a1fd47cd41fcf013
+
+Count = 24
+Adata = 73ef62870c50faca5d4e6c6ec45fa7b54bf79ed229fcf1fc8c79c9c09596039b
+Payload = 6c17ad5496dfccde8b877630e1e582dab52aaabe385a321f
+CT = 6a837143bd62c67feb48a3ceffe55ac855688302540d5d9143eb86ffa6958d71
+
+Count = 25
+Adata = b537f0f2981405f6069b401966656461b3516a32d181777121a60cea537e7cef
+Payload = dc4a1e39561f14321238272adff8b74a4e770c0a0c864a52
+CT = dadec22e7da21e9372f7f2d4c1f86f58ae3525b660d125dc1dfc38975c948d29
+
+Count = 26
+Adata = 96bd747ccdcd5fa6cd920514a2f38203e82ee9c7ec6e88080e9f6e2a6a812b0d
+Payload = c51958d7d7d39906b14d4ebb574db881355ec3e6b41838dd
+CT = c38d84c0fc6e93a7d1829b45494d6093d51cea5ad84f575320a48ee3845d9e7a
+
+Count = 27
+Adata = 690d6a2377314fc2f7dd06ae401e3585c79faf648a7af358ae4ef615669222eb
+Payload = 9eaf24f84e8818e286410de321d65ffbf25d1a14073c60da
+CT = 983bf8ef65351243e68ed81d3fd687e9121f33a86b6b0f54884188f946c9a317
+
+Count = 28
+Adata = 748dc83299a43033239ad2fef2dc3d72b76a38ca127607cef72de94a56d5e5c0
+Payload = 71c8eb0079559a306e236c49b7ce1b6cfe26c7888733eb7e
+CT = 775c371752e890910eecb9b7a9cec37e1e64ee34eb6484f00ae2dd33327f8459
+
+Count = 29
+Adata = 35a49535684637f67573fb0b4fdc1bdd8a57650a1d8f29b866fa552a6e0cdf91
+Payload = f09569906381138cc49e3fc2384c5d33c34abd3d617c487b
+CT = f601b587483c192da451ea3c264c8521230894810d2b27f5c50821a48b93d0ca
+
+[Tlen = 10]
+
+Key = 996a09a652fa6c82eae8be7886d7e75e
+Nonce = a8b3eb68f205a46d8f632c3367
+
+Count = 30
+Adata = c71620d0477c8137b77ec5c72ced4df3a1e987fd9af6b5b10853f0526d876cd5
+Payload = 84cdd7380f47524b86168ed95386faa402831f22045183d0
+CT = a7fbf9dd1b099ed3acf6bcbd0b6f7cae57bee99f9d084f826d86e69c07f053d1a607
+
+Count = 31
+Adata = 7b40b3443d00a0348a060db109e8882157612c43084ac5c3e9c5350c88bc165d
+Payload = 7ebb051741145a3bad87131553375c6debcbcecee9b79ee4
+CT = 5d8d2bf2555a96a3876721710bdeda67bef6387370ee52b694af9359a96acfb31a4a
+
+Count = 32
+Adata = 5cab3b84687070956916c11cab0ceea61adb6ea1f909be63d73df96fbfa3a9f4
+Payload = 35a29c1bcbe2182f34fe05f09dfb9ac4a496f95819ef11ec
+CT = 1694b2fedfacd4b71e1e3794c5121ccef1ab0fe580b6ddbe36d3920d1012bf093a5c
+
+Count = 33
+Adata = 6d440b44a069a6967f8750c3b4f8118798fe32d2eaa696ccc7f24e16d6366753
+Payload = a0e21d971876ae4048a61b43a3ac07c685005a20bccbe6ec
+CT = 83d433720c3862d862462927fb4581ccd03dac9d25922abec23025c1776811647f99
+
+Count = 34
+Adata = 06904325b8c6fc2b5a0412ba8062cd48d3af51beacb5ced9e2bdf8d0e056b738
+Payload = 8d333ed7d4b208e794e1673f6df692caee4e3a00fc49115e
+CT = ae051032c0fcc47fbe01555b351f14c0bb73ccbd6510dd0c6efeeaed29e65f1a8908
+
+Count = 35
+Adata = e5049e1c32f0a000024882e4fca9b77adb6c87fdbad96d0c8e97bdb8f46789dc
+Payload = 4189351b5caea375a0299e81c621bf434b6b97da68ad44be
+CT = 62bf1bfe48e06fed8ac9ace59ec839491e566167f1f488ec70d42f84a5411dfa43f9
+
+Count = 36
+Adata = 6f0be1905d1b5b607574ad93a1e7b4a536020fc6798acae862253916a0562707
+Payload = 5a063a24410b3d265c9a32a027cb2382a52bb8e35db15b98
+CT = 793014c15545f1be767a00c47f22a588f0164e5ec4e897caadd2256112d1f7d04934
+
+Count = 37
+Adata = a90f9f55ef22f5e6c542ed3573a9ab67d9c3b6775587fc2be70817479347ce00
+Payload = 0b72cb09a444be2d7b34cf9997fc5b885851d7e6092008b4
+CT = 2844e5ecb00a72b551d4fdfdcf15dd820d6c215b9079c4e6e187f5f37e8a5029ca4e
+
+Count = 38
+Adata = 4dd64fd7d8b571704cddabef854c51691ace4c30de74bfecad42eaed65284ebf
+Payload = ce2d996c9a4cf85edb888822773e03179feeb9e4b0928d6a
+CT = ed1bb7898e0234c6f168ba462fd7851dcad34f5929cb4138fbbb92009435f9ab6691
+
+Count = 39
+Adata = 75f4031d2e5098a9ea3eaa20c2423fbc1705ea18289efb96e311f3fefc153b67
+Payload = aa182e3ec4fb2f7a905c03582b2ee100ab81a9a311a778bc
+CT = 892e00dbd0b5e3e2babc313c73c7670afebc5f1e88feb4ee3cae38db7cc9d577b0ed
+
+[Tlen = 12]
+
+Key = 3ee186594f110fb788a8bf8aa8be5d4a
+Nonce = 44f705d52acf27b7f17196aa9b
+
+Count = 40
+Adata = 2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57
+Payload = d71864877f2578db092daba2d6a1f9f4698a9c356c7830a1
+CT = b4dd74e7a0cc51aea45dfb401a41d5822c96901a83247ea0d6965f5aa6e31302a9cc2b36
+
+Count = 41
+Adata = 78230f73f9c0150f630eca4cd679818551d449db82e665d8dc25fc53ebc11293
+Payload = 048ba28abb191ded5449dfe9dc7d19f9b132a2a9fd779aab
+CT = 674eb2ea64f03498f9398f0b109d358ff42eae86122bd4aa6356e2548a22e7cbee3b89d4
+
+Count = 42
+Adata = c09191a7d2fca98fca486f8843f275a78d57b8c9a6d330d5652ba641f928c6d8
+Payload = adf51386b3cc133ea9d18e679fe4bbf10ea780b7bed57d6a
+CT = ce3003e66c253a4b04a1de85530497874bbb8c985189336b35516f170a2aada38d1d94eb
+
+Count = 43
+Adata = ea46cc1a7ba5afaa6176f8dedc049283d2ac38fa74ef37ea1fc575328033b222
+Payload = f660a28551416b2f8e21466ba99daee280a91740d98219cf
+CT = 95a5b2e58ea8425a23511689657d8294c5b51b6f36de57ceea2d3237788a02ff15258351
+
+Count = 44
+Adata = 3093b74eb088bdd59999629d59509920938f4feabbd29df8e0b44364c8b55244
+Payload = b9a96f0e4c6dea8861e888bdd693b300017718da958aaa00
+CT = da6c7f6e9384c3fdcc98d85f1a739f76446b14f57ad6e40165fb6719509987930d350890
+
+Count = 45
+Adata = 5580672e52aacb9d714a34c31c33fc221e13e8f90849adbad3f6b3bec8571838
+Payload = cc4acdbd34ec9b7cbc3e23a53e0627c2a7c63206f3e0298d
+CT = af8fddddeb05b209114e7347f2e60bb4e2da3e291cbc678c8ecdf173444c334cfda5b22b
+
+Count = 46
+Adata = c7acf1b17609dc336df1006ffac6497777cdfd497c8c91525377c130accce0bc
+Payload = ed75d28be4794ad81bbc0f26a11c5466f23c0270d2d7b8f8
+CT = 8eb0c2eb3b9063adb6cc5fc46dfc7810b7200e5f3d8bf6f92221c860022d92b0f961c3e6
+
+Count = 47
+Adata = ac1adca686e1d129142c49f26b52941d037d8052b8a27d5215b7ffcfd2202481
+Payload = b8234b8bd34d9c6ceffebbb85722764e7d37e43c495256e0
+CT = dbe65beb0ca4b519428eeb5a9bc25a38382be813a60e18e11c73d6a695afc704228ed7a1
+
+Count = 48
+Adata = 472bf7946bce1d3c6f168f4475e5bb3a67d5df2fa01e64bce8bb6e43a6c8b177
+Payload = 790134a8db83f2da35dde832c3ae45ec62aff0274495d6e7
+CT = 1ac424c8046adbaf98adb8d00f4e699a27b3fc08abc998e6bf1e81950e44c63183a679d7
+
+Count = 49
+Adata = 1340ac7ff04dd7450afc13f8fa52df6d526c744a2dc2f76b0aadf284da270508
+Payload = 21ea2f778cf37aa02fea30e855c20a77909548da4ee7eb61
+CT = 422f3f17531a53d5829a600a99222601d58944f5a1bba560c2c3a1876e49a47a9b44b737
+
+[Tlen = 14]
+
+Key = 7b2d52a5186d912cf6b83ace7740ceda
+Nonce = f47be3a2b019d1beededf5b80c
+
+Count = 50
+Adata = 76cf3522aff97a44b4edd0eef3b81e3ab3cd1ccc93a767a133afd508315f05ed
+Payload = ea384b081f60bb450808e0c20dc2914ae14a320612c3e1e8
+CT = 79070f33114a980dfd48215051e224dfd01471ac293242afddb36e37da1ee8a88a77d7f12cc6
+
+Count = 51
+Adata = 41aa11ec55980609482575b97eee172590ff545d5798fd4246313da3fdbbcda6
+Payload = 811d54bad842a8b92b96fc03b4fff8b5f1939fd3a49876dc
+CT = 12221081d6688bf1ded63d91e8df4d20c0cddc799f69d59ba850b0116f3269b5e44e57de7166
+
+Count = 52
+Adata = dedfb02e93b975270f50cffa3351c85975a7b21fd89bbb921c40c1e5310e6702
+Payload = 8bbf87b490020b863fc596a8d169d79c0cb3506e1f1f5aa2
+CT = 1880c38f9e2828ceca85573a8d4962093ded13c424eef9e50f053627bd0c90714820c4fbe5ec
+
+Count = 53
+Adata = a727ed3d13331ee6a224ae4b73f0ccb04b997fcf88533a1f57e9b055275de92b
+Payload = 7294ae94358669f2ada4b64c125b248df7fe86c6715e3b6a
+CT = e1abeaaf3bac4aba58e477de4e7b9118c6a0c56c4aaf982df865a77d66f1232cd7e36af3d1be
+
+Count = 54
+Adata = 6704dc39a259152d2dc3f08b8799ffecf4e1bc38ce5b77c71cc293c6664ef2dd
+Payload = 48033c46389f6221fb9cdda1ecb8fc25fdec6afe4eaa5fd0
+CT = db3c787d36b541690edc1c33b09849b0ccb22954755bfc97e1fba154f6b166549d0d6bb9b573
+
+Count = 55
+Adata = 6cba004dfb5e5d9e1433bf1223039ae1d2df89cd2db68f550327a22c8f946ae9
+Payload = 01acc909b7d3bb3b3e1f72845f05238d2e1d9162976d3bd2
+CT = 92938d32b9f99873cb5fb316032596181f43d2c8ac9c9895c485e9e28ae33959f8acbb640fbf
+
+Count = 56
+Adata = dd5799710523aa1da0b1209fab1e6f2ed177444ed3880d462deebbd5f774c621
+Payload = 3706def87786e49baec2d13407865286cb4e05908cac430f
+CT = a4399ac379acc7d35b8210a65ba6e713fa10463ab75de0488ef976fa9bda9544ed94ef266ed2
+
+Count = 57
+Adata = 5d7505ff863d218f6822150455b977ad2df3c02be094f6832ee68872b1ae7a01
+Payload = f38d4b225d9b80a0c5fadc61476aef419ad3d18937d8661f
+CT = 60b20f1953b1a3e830ba1df31b4a5ad4ab8d92230c29c5580caadf1dbd07515e3bfb6992e2cd
+
+Count = 58
+Adata = 796b62c7abf797de7f6bad8bf5d549688ccb7ada62fff9469c14b08208b07a8a
+Payload = 993bb3a85f67f6c1a809d8094ee80e2ad9b694063af2fdb3
+CT = 0a04f793514dd5895d49199b12c8bbbfe8e8d7ac01035ef4733ad369e4a067b7976c9d6d0456
+
+Count = 59
+Adata = 84fd27557aeb283282366083e3586f3a59691ccd0d43ec81c4e5f4e85715eba8
+Payload = 1286506be19fb865a288b09dda8af4323567cd9a66e08643
+CT = 81b91450efb59b2d57c8710f86aa41a704398e305d11250439860d66891f32ce0a09788f5899
+
+[Tlen = 16]
+
+Key = 4189351b5caea375a0299e81c621bf43
+Nonce = 48c0906930561e0ab0ef4cd972
+
+Count = 60
+Adata = 40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951
+Payload = 4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef
+CT = 26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9
+
+Count = 61
+Adata = ac8dde7ba60e4ba226eecb0a789b1c4673ddffe8f371464389f52f767004f0a6
+Payload = 7c0889854658d3408c5d8043aad2f4ae4a89449a36f8a3b8
+CT = 1ff831cfc51ae62ea29b0791941972254cd0b846294d7be196363d27b9e11fee55111b273399f5ff
+
+Count = 62
+Adata = 8f2777ec4930f7e349c3bd4830120cebdd896db9d8a33d34f101672024bd737f
+Payload = c641cf589020b94026ae5ac0bfdc29822cc13862a54614c7
+CT = a5b1771213628c2e0868dd128117af092a98c4bebaf3cc9ef741e15ad9b2f5ab864ad94d3f9de562
+
+Count = 63
+Adata = a87426f83bf91bd3c3556bf859cd97f51c92609879f02dbca9c7ae637a3fbf05
+Payload = d204994c128d6204ef2939c22572daa56c12df2e4d3e33e9
+CT = b1f4210691cf576ac1efbe101bb95c2e6a4b23f2528bebb0652a083ea1b43b7da026692c7aa796d7
+
+Count = 64
+Adata = 7ff9ca86f820e4d57995d450611009ffaa726e6fbe4ce1558ca1e775daed9ec2
+Payload = aff9bb0238689255f54cd5fdebe6d3dff5f5604ab8d77038
+CT = cc090348bb2aa73bdb8a522fd52d5554f3ac9c96a762a861057e0faa2711cfa1e3da5499f9a1ee0b
+
+Count = 65
+Adata = faa6b7f8c6e076b5e5b981119b7ec2e0b9c73da4064f9704e303d5792f59674b
+Payload = 95d2cf30b6174b17278ad9f44079a2199082dab917f89763
+CT = f622777a35557e79094c5e267eb2249296db2665084d4f3a90b39704d8913391ebd3424117b93b68
+
+Count = 66
+Adata = b553e65640c1ad0d2ff748c5b2af9d970c74131cff4fa73384a33dfec056332e
+Payload = aaa53244520e157c4890a0e62100a12daa84f9be710242d7
+CT = c9558a0ed14c2012665627341fcb27a6acdd05626eb79a8ed0a6cb58733be0a3b608afdf78eaa70c
+
+Count = 67
+Adata = a9be73668b94bc6a212744522a0adff03d49fd495daadaf6cd32f4ca25ebc2b5
+Payload = 1066b96c3c44301073717520ea5c07adbac7759b88d52154
+CT = 73960126bf06057e5db7f2f2d4978126bc9e89479760f90daf20ce64e6a821e39ca96aded43f0875
+
+Count = 68
+Adata = 8b516c47e6630b2c31d8eefd8ba152d7315582a3f4d3f0e0eb2984a365b434db
+Payload = b5969813d0f892febe64ed52d429cc737b5df8d5e0c63207
+CT = d666205953baa79090a26a80eae24af87d040409ff73ea5ecf4699d23f5fc6742bffebbd16858f6e
+
+Count = 69
+Adata = 8ad3e84edbe7d9305848746cbd0f769bce47d5ae4609513210e54cd3b984db1f
+Payload = daa90a2de3937e7942e6711f165a89b9e077fe322cab597d
+CT = b959b26760d14b176c20f6cd28910f32e62e02ee331e81243713601bb16dc91af84ac19ebd43a1ec
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT192.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT192.rsp
new file mode 100644
index 0000000000..75b0c429f6
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT192.rsp
@@ -0,0 +1,393 @@
+# CAVS 11.0
+# "CCM-VTT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Nlen = 13
+
+[Tlen = 4]
+
+Key = 11fd45743d946e6d37341fec49947e8c70482494a8f07fcc
+Nonce = c6aeebcb146cfafaae66f78aab
+
+Count = 0
+Adata = 7dc8c52144a7cb65b3e5a846e8fd7eae37bf6996c299b56e49144ebf43a1770f
+Payload = ee7e6075ba52846de5d6254959a18affc4faf59c8ef63489
+CT = 137d9da59baf5cbfd46620c5f298fc766de10ac68e774edf1f2c5bad
+
+Count = 1
+Adata = edb8834974b02fc9ab29b4b3c49683426124e729b44e43cde4ab9bb1b30b5531
+Payload = d05410f42d4759f8cab3884785cf8f60ecbf902e525b92e8
+CT = 2d57ed240cba812afb038dcb2ef6f9e945a46f7452dae8be24285996
+
+Count = 2
+Adata = 8baf194e81e47a6ca82ca51b488339d014a0a494007793aa5201ac72fc3f808d
+Payload = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c
+CT = 2633df3f6d2b52301ae01015efb688a4730e3088e2d84b0a6c510570
+
+Count = 3
+Adata = c0b55acc7fbfa9d9af6e1f32b6626a1cd89b1c32513b5b50a18ddab028470953
+Payload = 7f0745bea62479c0080ecec52e37c1e32d72a6b3864da44a
+CT = 8204b86e87d9a11239becb49850eb76a846959e986ccde1cb418cfd2
+
+Count = 4
+Adata = 9dc672e64c468242ddeec318c71f9b8cbaa14639eba3c861acfc26463fb7d5d7
+Payload = 263dbe1bd5e9d9b29b316fe36ec8bb10f64543b4921c01f6
+CT = db3e43cbf4140160aa816a6fc5f1cd995f5ebcee929d7ba03e5b5794
+
+Count = 5
+Adata = 1798286c37c1504fc0d7402681f6f70711ef506dcc3e29d0183dc578ed976f92
+Payload = 22dbba2b1a39074ddac736767ebdedc37e4208b233e03b34
+CT = dfd847fb3bc4df9feb7733fad5849b4ad759f7e833614162f63b4847
+
+Count = 6
+Adata = ed2898d0bcb34eebf98b5279bc3e8a20214321a7e23bc55b2b7613b1a9b94f2c
+Payload = f0f1235ee88d04de3f3d1489ec6b28b285a6a4fbb344911a
+CT = 0df2de8ec970dc0c0e8d110547525e3b2cbd5ba1b3c5eb4c7ab29a40
+
+Count = 7
+Adata = 50c4a285d6a4e64efceb288b82e7c8277307cf1eaa4b8b9294f97a1c38926a60
+Payload = 0e50aa6a3079c0b8d61e51c3bd93b592a03719acb9f0252e
+CT = f35357ba1184186ae7ae544f16aac31b092ce6f6b9715f7868f40ff6
+
+Count = 8
+Adata = b48a16fb9a065d3aeb2bdf1860e4b0f1348c8f13cd00b1729ff8c19e4e9724f3
+Payload = 82f39f5207afcfd677a7544579f2b888a1eabdee4e835924
+CT = 7ff0628226521704461751c9d2cbce0108f142b44e022372ceeff92c
+
+Count = 9
+Adata = d92b80544f29aba52496e2c9a0aa4adeb89820be321cfd2f0a53585a15d04c7f
+Payload = bc3b08eec6506d1497572f901f0e5f3e9854b40b0f992d08
+CT = 4138f53ee7adb5c6a6e72a1cb43729b7314f4b510f18575e619c1124
+
+[Tlen = 6]
+
+Key = 146a163bbf10746e7c1201546ba46de769be23f9d7cc2c80
+Nonce = f5827e51707d8d64bb522985bb
+
+Count = 10
+Adata = 599b12ebd3347a5ad098772c44c49eed954ec27c3ba6206d899ddaabca23a762
+Payload = 473b6600559aefb67f7976f0a5cc744fb456efd86f615648
+CT = 26d2be30e171439d54a0fec291c6024d1de09d61b44f53258ba1360406f9
+
+Count = 11
+Adata = 3a8423feb661db30542dc3cfb596280429397f80755a4bc8d4d941d03b61aacc
+Payload = 7edfce3dedd65a8592aec2bfc7a751e2360f3137941fc960
+CT = 1f36160d593df6aeb9774a8df3ad27e09fb9438e4f31cc0db5e5938e8c75
+
+Count = 12
+Adata = 0dc79993047fd6e7260aac4d847fdb4d16483f28b13b5f17330744d401d2875b
+Payload = a9fb3ebba43c273cacbf0f7187030c69172f31382e9e059b
+CT = c812e68b10d78b1787668743b3097a6bbe994381f5b000f694f534b76f0b
+
+Count = 13
+Adata = 6546d9a90e0e763679d5469a1bcffcc4f18f35f50c7714d14c7329b76ce7984e
+Payload = a7573e5b7dd7f4ce9e4480f603c14145a27f7c7a9246a3cf
+CT = c6bee66bc93c58e5b59d08c437cb37470bc90ec34968a6a23c6c025faa1b
+
+Count = 14
+Adata = 7f398ff0d47e2c0fccd8a16cc9e79b4813abac42e346fa33ba033956f798d6ac
+Payload = 84370557e0bbf74fd0a4533185adfe202d9fa9d622bba72f
+CT = e5dedd6754505b64fb7ddb03b1a788228429db6ff995a242ae0f88d836be
+
+Count = 15
+Adata = d0f46fb37d516cc957aaefd3be2a8bede885330a8edb96f3e5e0ab8cd03a8c59
+Payload = 029575400bd3f2621c7d9ca9b6a09ea6f776968b19dc3f3e
+CT = 637cad70bf385e4937a4149b82aae8a45ec0e432c2f23a5366d09f64b4c2
+
+Count = 16
+Adata = 4abaa4260c864572e12553c5aabfe62e4e7038490d4ba160119fc5d646780cc6
+Payload = 448be3821d94452425fae41a06457260a2666e890fa94954
+CT = 25623bb2a97fe90f0e236c28324f04620bd01c30d4874c39677fd479c852
+
+Count = 17
+Adata = 686e0578eadd19583291a01e11a29fc95a2c156da100dd85429ad58ba65440c6
+Payload = aebfe3e15a876412ec9df714f1afa898e69004c1ef25732b
+CT = cf563bd1ee6cc839c7447f26c5a5de9a4f267678340b7646bbc332573774
+
+Count = 18
+Adata = e3d29f970667286a81586aa02bb490c72d8bb3a308eafec5da0d105fddd1a157
+Payload = 08b2ce5f7296016e86d02f8c7952d746703ee4f0429b8df3
+CT = 695b166fc67dad45ad09a7be4d58a144d988964999b5889e33171a8ccec1
+
+Count = 19
+Adata = 9e2ea8eb7f56087ee506925648661eeefffd643a056cd4f4fc5cc23172b5c637
+Payload = e73d7d23736db17cca816ab2440062a8051177d47feb514e
+CT = 86d4a513c7861d57e158e280700a14aaaca7056da4c55423bc8299cc9f95
+
+[Tlen = 8]
+
+Key = bdf277af2226f03ec1a0ba7a8532ade6aea9b3d519fe2d38
+Nonce = cc3c596be884e7caed503315c0
+
+Count = 20
+Adata = 4d6546167b3ed55f01c62bd384e02e1039c0d67ef7abe33291fecb136272f73b
+Payload = 0ff89eff92a530b66684cd75a39481e7e069a7d05e89b692
+CT = 6ef66a52c866bd5df20ec5096de92167ad83cab0e095ad0c778a299f1224f10c
+
+Count = 21
+Adata = 95722ef5e0cf9f482e4c359f1fd6b9efe2b6e0630413c40285b8958c31188ca4
+Payload = b1ea02e3721e44c327443fcf4b424cce19afbb9e8cf06b76
+CT = d0e4f64e28ddc928b3ce37b3853fec4e5445d6fe32ec70e8a5c2c6b097a04d50
+
+Count = 22
+Adata = f7b76a2a4fe0a1b07a6b193b4600aec02360eb35853d88fe8a4f31a8dda48ad9
+Payload = c1f9c7b2e0ba712b4d2b32e4693b145228213999703767fc
+CT = a0f7331fba79fcc0d9a13a98a746b4d265cb54f9ce2b7c62f62e74c2312f9243
+
+Count = 23
+Adata = 406f39cb77b8d8c63f7797d184b6ebde819af7d48de5003538c022fe96b841ce
+Payload = ebf3a717546199c6f6b14efe8888613ca7e075e8290b277c
+CT = 8afd53ba0ea2142d623b468246f5c1bcea0a188897173ce2f1cb228ffd2ff8e6
+
+Count = 24
+Adata = 3dd3110703a95b05b9b9cff92ab7244e6c6dcb4509522c305d5d33e03f1b0b60
+Payload = a0e317b790870e6703e6077dfb8ea327c12e29a17107284c
+CT = c1ede31aca44838c976c0f0135f303a78cc444c1cf1b33d21f38e2d280a8f3ff
+
+Count = 25
+Adata = 044ae4064156b6ebc0921cb2c3c607976339f824d4dc6902eac66910dce086b2
+Payload = 8a16990690717dc16eea24da39878a2ee7c1579976e5b173
+CT = eb186dabcab2f02afa602ca6f7fa2aaeaa2b3af9c8f9aaedafbcf46b4e75bb11
+
+Count = 26
+Adata = 5479cc7f92460ff7a3e500f76d70e3036c44300005058b5517e3f64ad41b46b3
+Payload = 1e7e51f0fa9a33ed618c26f5e37754df0f7de7778882c26c
+CT = 7f70a55da059be06f5062e892d0af45f42978a17369ed9f2fac11c84d08e918e
+
+Count = 27
+Adata = f950e96d65a55efb3be3a55daffb421afad1d5625e3440a16414085469effe1c
+Payload = 3ef1f4c438dce131990ba536d7a6166022ae7de4a436f87c
+CT = 5fff0069621f6cda0d81ad4a19dbb6e06f4410841a2ae3e2b50cb871173d9bb8
+
+Count = 28
+Adata = 52742be3969830ba9c2bce26c98c2fb44ac881ec55c85627b2c94ba17b0de8cf
+Payload = 3c7b4a68dfb766e24739f14932563fb81f24591f0e31e895
+CT = 5d75bec58574eb09d3b3f935fc2b9f3852ce347fb02df30b4ce29627efbc3523
+
+Count = 29
+Adata = e16e5dc034719e5d815f937b672cf34d5d420a3945c8f73645241779d2bec150
+Payload = 03038acd2d8351e4e5aa308e554abfcd0d0334d8f864ec60
+CT = 620d7e607740dc0f712038f29b371f4d40e959b84678f7fe095168ed90827db2
+
+[Tlen = 10]
+
+Key = 62f8eba1c2c5f66215493a6fa6ae007aae5be92f7880336a
+Nonce = 15769753f503aa324f4b0e8ee0
+
+Count = 30
+Adata = 1bc05440ee3e34d0f25e90ca1ecbb555d0fb92b311621d171be6f2b719923d23
+Payload = f5522e3405d9b77cbf3257db2b9675e618e8744a0ee03f0f
+CT = b9103942dbbb93e15086751c9bb0a3d33112b55f95b7d4f32ff0bb90a8879812683f
+
+Count = 31
+Adata = 25c32770a299020d8500d8a4b5d7621e4379dbd6ef34a9aceefd4055ea6144f5
+Payload = c8bf145fcffbafd6cd1a4c5b6cedfe008aacb2528ef51c80
+CT = 84fd032911998b4b22ae6e9cdccb2835a356734715a2f77c6982d0796e1bd1cc9879
+
+Count = 32
+Adata = cba0e0140f094e17652ea6f64c26f69dd9429bfefb41aaf104c38f3f6501f4f9
+Payload = f8813985f59bf284bd3882e899ca9b67fb496f3eb78d7ebe
+CT = b4c32ef32bf9d619528ca02f29ec4d52d2b3ae2b2cda9542fe08edf50e05d4d85faf
+
+Count = 33
+Adata = a846d0f56eb963b308ab8f697adca378ab6ccf9f739edcd7f5db197b2ffa99ac
+Payload = 72862d82d940748d54369e3143192453069b80d10f32e569
+CT = 3ec43af407225010bb82bcf6f33ff2662f6141c494650e95800ae2523c5f161ed96f
+
+Count = 34
+Adata = 1dc5f6d6103ed2ae7f4ecd7b1bae4d5b9c0adef9100527b1737e1cf57f1175ef
+Payload = 46f2199305ff4e1f21a89d96d3902c54939f52278ba7aa0e
+CT = 0ab00ee5db9d6a82ce1cbf5163b6fa61ba65933210f041f234a29547607846bc9834
+
+Count = 35
+Adata = 8c28bcb9c31191c347dd64e552af5aff500e6e6f39e866351dd7065501a2837d
+Payload = 18c38c41a4e70c3f7362249ea329059b0e026bce7ae976b0
+CT = 54819b377a8528a29cd60659130fd3ae27f8aadbe1be9d4c95f73957e86152df56bd
+
+Count = 36
+Adata = 1081afd5bf9f1a87169973ebdca85c2b69598154673d7ca9d6e2f63d52030fc1
+Payload = c89e388dd6124c41251e7422b420a71e4618f5cf9f0a63fc
+CT = 84dc2ffb087068dccaaa56e50406712b6fe234da045d8800b2b028cd785f4f964069
+
+Count = 37
+Adata = 079bc543c966734fa70814139ba8051271ee1c4f701579013c427f8efb141db7
+Payload = 68449bc3f6c8bd8f3a46a8e147522d979948c88ca791d204
+CT = 24068cb528aa9912d5f28a26f774fba2b0b209993cc639f8fd3ef357e5e69f504c95
+
+Count = 38
+Adata = e7094697b78d20174ec3c97a48abcf67c2ba6790b4db5fda82b454becd2a25ef
+Payload = 330088153204c3d5de7744047b60887c8c044e4eeaae4bab
+CT = 7f429f63ec66e74831c366c3cb465e49a5fe8f5b71f9a057e092ed15d1a074306a9e
+
+Count = 39
+Adata = f8d64ce2aa66e67de0f2fa584dec858983333b0570882ab628419bcee541395a
+Payload = 893c5c45db989bd39485caa05ed700bb17c526b426edf4ba
+CT = c57e4b3305fabf4e7b31e867eef1d68e3e3fe7a1bdba1f46afaad39e9183b2970027
+
+[Tlen = 12]
+
+Key = 5a5667197f46b8027980d0a3166c0a419713d4df0629a860
+Nonce = 6236b01079d180fce156fbaab4
+
+Count = 40
+Adata = 29bdf65b29394d363d5243d4249bad087520f8d733a763daa1356be458d487e5
+Payload = d0e4024d6e33daafc011fe463545ed20f172872f6f33cefa
+CT = 479f3d408bfa00d1cd1c8bf11a167ce7ae4bcdb011f04e38733013b8ebe5e92b1917640c
+
+Count = 41
+Adata = 314f069dd4ac5aa3fdc2a74e83daa1d5d18330cd3b90684a9260bb48f5626d49
+Payload = 9ebd994a9af0cb94552ffd749fdd97f75a1ebd0ad3de3a9a
+CT = 09c6a6477f3911ea582288c3b08e06300527f795ad1dba58425a1bad4381dc84fee903e3
+
+Count = 42
+Adata = 3aa7f30ac5bfbcb3f8de7c5e76269c608fbc76361d215e78abc0e308ddc3528f
+Payload = 590a27721a36987d1ffa15f23c6ca5cc556dfcfa6993a2fb
+CT = ce71187fffff420312f76045133f340b0a54b66517502239efcb43c6aaec88b51d0a378b
+
+Count = 43
+Adata = 5630345f662df248886f771b2b77cc0cbdc8fe4cc4a6cde52b1ea4e5d946cebe
+Payload = 65f4b3a00c1c1ef39445a69b2150b034705410140ff9dad0
+CT = f28f8cade9d5c48d9948d32c0e0321f32f6d5a8b713a5a12b9a60374d9304316e2fc50d9
+
+Count = 44
+Adata = 38ee97f0dc635c7416a024e3af5c95dd1d496db8a5a5c3bcc20b9093ca906dfb
+Payload = 0edea2afaeaf650704d2c6c6622aad82169807c983c17309
+CT = 99a59da24b66bf7909dfb3714d793c4549a14d56fd02f3cb07611163d6b0f1734292ed8c
+
+Count = 45
+Adata = ea3b3f3c5b28f7d48af2ccf97083937baccb0a6b1a041080a73b15b9640ccf44
+Payload = b80175a03dff1b10078ded64ed759e5453e3bc0657c68590
+CT = 2f7a4aadd836c16e0a8098d3c2260f930cdaf69929050552edefbcbb51d9d607b7b2e8f8
+
+Count = 46
+Adata = 287f31e69880823df7798c7970c0e42e600bf567ad78f5d559d0182d570c03cb
+Payload = 531c1e721e185f58b2c654b9098ce0c1338bab4149c7bef7
+CT = c467217ffbd18526bfcb210e26df71066cb2e1de37043e35f2b6d4dc8afae25ff400d73d
+
+Count = 47
+Adata = 1d4579c9410cc34ade1352ed433e0d4faaaa28200e359bcb4140d35939b3a792
+Payload = cead1c5af16ca89bc0821775f8cba8c25620a03dfd27d6f1
+CT = 59d6235714a572e5cd8f62c2d79839050919eaa283e4563319cd80c1ce0f9ed40f1e9dec
+
+Count = 48
+Adata = 3fec0e5cc24d67139437cbc8112414fc8daccd1a94b49a4c76e2d39303547317
+Payload = be322f58efa7f8c68a635e0b9cce77f28e3f8faaa76fcad4
+CT = 294910550a6e22b8876e2bbcb39de635d106c535d9ac4a16e53d5aeccfb4a6837b79a625
+
+Count = 49
+Adata = ec6857533675b5ed8d4315b0d5f59c826f3ccb2d0bd6f604bd54f7c9542123ce
+Payload = c222374d366baf2d0301340582aa056c04441ac766065ab1
+CT = 55590840d3a275530e0c41b2adf994ab5b7d505818c5da73385e080bf29ae097c328789a
+
+[Tlen = 14]
+
+Key = d2d4482ea8e98c1cf309671895a16610152ce283434bca38
+Nonce = 6ee177d48f59bd37045ec03731
+
+Count = 50
+Adata = 9ef2d0d556d05cf9d1ee9dab9b322a389c75cd4e9dee2c0d08eea961efce8690
+Payload = 78168e5cc3cddf4b90d5bc11613465030903e0196f1fe443
+CT = e2324a6d5643dfc8aea8c08cbbc245494a3dcbcb800c797c3abcdb0563978785bf7fd71c6c1f
+
+Count = 51
+Adata = 6f99d9ce00a4be502a5d2c76a07b914d56f49a1592c1ee2e46e11b3c9da0d083
+Payload = 3c3992cac792e019720d38f768beac3deb6a43e7e1f59f20
+CT = a61d56fb521ce09a4c70446ab2488c77a85468350ee6021fcb0e8ec0879db8ffa59125eac239
+
+Count = 52
+Adata = deae66f68bb18178d1bc0734f19fd3ab390049c2ca083a159f5c078fcb4f0a38
+Payload = 8eaae72e532943d66ce8250c6b434d299b6afbf8e2b4f8b1
+CT = 148e231fc6a7435552955991b1b56d63d854d02a0da7658e664a2d992f7cf821e19bb7d4dff8
+
+Count = 53
+Adata = e2d592cb412e65f9044257d78e7491f9f80c8b08102c2d5da20535cef74ad8c8
+Payload = 1b8096b79ace8c6ee5dbd8735f1287aa2c94865f382dc2da
+CT = 81a452860f408ceddba6a4ee85e4a7e06faaad8dd73e5fe546a4a816b709a55db450ac249c5c
+
+Count = 54
+Adata = 78a292662b8e05abc2d44fbefd0840795e7493028015d9f2aae7b3b7a4634437
+Payload = 014f15219463ac22820ba6a1fa04d7f686003ef24004da67
+CT = 9b6bd11001edaca1bc76da3c20f2f7bcc53e1520af174758fbebbdb2e35ebf682f7fe30996bc
+
+Count = 55
+Adata = de6ea86d3641d916c4394fdd31e6a50194993d6ef1d3dfd9fffca20b2f58107d
+Payload = cc8c855a4c122046916bdcf8089eba3ddb80483e201c7102
+CT = 56a8416bd99c20c5af16a065d2689a7798be63eccf0fec3deee137bb5b1e7385aa1bd5d69831
+
+Count = 56
+Adata = 87b937b1d36e8a9ab33a1d3eed617030923acaabc7e620dfcb3c388936030fc6
+Payload = 3fb7d1f17e7e36d5d4b816cc6db11d1d85848c577fdfe938
+CT = a59315c0ebf03656eac56a51b7473d57c6baa78590cc74079b13b729c70e1fa89c43a05a544b
+
+Count = 57
+Adata = 116f4855121d6aa53e8b8b43a2e23d468c8568c744f49de5f7f1a60cf4e16278
+Payload = 268fe424d6db30f680c10fe2684707a0778069958e9a3bf7
+CT = bcab201543553075bebc737fb2b127ea34be42476189a6c82d900340d90dc4f09a7171d331d6
+
+Count = 58
+Adata = e13e0c9cef1f86160a75ccb131586370b0edabbf8b3b63f21f3a6fee072dd926
+Payload = 9d64de7161895884e7fa3d6e9eb996e7ebe511b01fe19cd4
+CT = 07401a40f4075807d98741f3444fb6ada8db3a62f0f201ebe4ad0d90322ed2813a3343029e93
+
+Count = 59
+Adata = d4cd69b26ea43596278b8caec441fedcf0d729d4e0c27ed1332f48871c96e958
+Payload = e4abe343f98a2df09413c3defb85b56a6d34dba305dcce46
+CT = 7e8f27726c042d73aa6ebf43217395202e0af071eacf53790065601bb59972c35b580852e684
+
+[Tlen = 16]
+
+Key = a7177fd129674c6c91c1c89f4408139afe187026b8114893
+Nonce = 31bb28f0e1e63c36ca3959dd18
+
+Count = 60
+Adata = 2529a834668187213f5342a1f3deea0dc2765478c7d71c9c21b9eb1351a5f6cb
+Payload = 2cea0f7304860a4f40a28c8b890db60f3891b9982478495e
+CT = 5bb7aa6ab9c02a5712d62343fbe61f774e598d6b87545612380ea23dcffc9574f672bca92e306411
+
+Count = 61
+Adata = a4dbf26802b2dba1bf828f57618fd197d3e60b6efc9d884f965ce3b43e1dc008
+Payload = 2baf3d378942bd44f67fb787def50aaf446bf15c56243484
+CT = 5cf2982e34049d5ca40b184fac1ea3d732a3c5aff5082bc8b93605b46a8a6a9c7e02cb8feac67af4
+
+Count = 62
+Adata = cbd1302c9fffe29fe882838236f64fe9d9ba35db5499e90f0faa35f34c7490f2
+Payload = a0639aa4e7a8bda4e9e096d17c1c47d3786010fabe9c72d2
+CT = d73e3fbd5aee9dbcbb9439190ef7eeab0ea824091db06d9e82e411c052c0a025ab15767b0242ebf7
+
+Count = 63
+Adata = b6112eb8299b28445aca8f72e7170a1cd8bbfee4d2145fbe8d49c6af8831c4d4
+Payload = e2d78ce5df9284c045b84df33f551211ddccf7bb14cd4529
+CT = 958a29fc62d4a4d817cce23b4dbebb69ab04c348b7e15a65ab58a892f7142414d3f7cf10925a403a
+
+Count = 64
+Adata = c70a9fb811894b73e445b78db7a931705a181f3a8730341cbb50eaff43572c6e
+Payload = c3f1e735a6741aa481ad577a98dbac1f03cc80ea0dae1b94
+CT = b4ac422c1b323abcd3d9f8b2ea3005677504b419ae8204d8b5b3ce6bae6ecb060289508d6e9212fe
+
+Count = 65
+Adata = c7cbda495a7dc1d91837f652a9d084df9b717e99b29bf1ab7f6c17b3341ecd6c
+Payload = db8cd5d76e459afce765e07da98f4ac58231224238c293c7
+CT = acd170ced303bae4b5114fb5db64e3bdf4f916b19bee8c8ba16229a91a2298ffe104f9c032720abb
+
+Count = 66
+Adata = 4bd3a656796cb1fa87976f3a93471e33dd1209ce33d7a28aaca4d17c99d78c94
+Payload = fd66aebc94f2513b1b9218396b08c63a869b9c4dd0752a91
+CT = 8a3b0ba529b4712349e6b7f119e36f42f053a8be735935ddb9cacc4fdb44402971a0eee7f1ad90d7
+
+Count = 67
+Adata = 448cdd9cbbf863eb666fda36b825f3798827da3c1349611f45605ab734b24498
+Payload = 5831e9a6af0234d051ffd17a14b8e3c8da95067ab767901b
+CT = 2f6c4cbf124414c8038b7eb266534ab0ac5d3289144b8f5713306e7f0a61d4b3da372db669321143
+
+Count = 68
+Adata = f8f04f12174b5205866515ce3775bd8e11d50d8b96142be0c347a773379fb928
+Payload = 248a4969621cf291bec7f0d76d80b7f019d4eb002a22c46a
+CT = 53d7ec70df5ad289ecb35f1f1f6b1e886f1cdff3890edb2609726d3a3d04005dc13629658624d05b
+
+Count = 69
+Adata = 4ecd7c2188fb9cfc84a9ee2fab29ccbbd48a574ec20f1959eedfe96887fe0eb3
+Payload = 68f36fd96de8c57210f6f41da5b67d68533d722c604dda62
+CT = 1faecac0d0aee56a42825bd5d75dd41025f546dfc361c52e8631fb934e918210097f3cefc7f3b0ee
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT256.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT256.rsp
new file mode 100644
index 0000000000..dbe86fbb71
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT256.rsp
@@ -0,0 +1,393 @@
+# CAVS 11.0
+# "CCM-VTT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Nlen = 13
+
+[Tlen = 4]
+
+Key = 9074b1ae4ca3342fe5bf6f14bcf2f27904f0b15179d95a654f61e699692e6f71
+Nonce = 2e1e0132468500d4bd47862563
+
+Count = 0
+Adata = 3c5f5404370abdcb1edde99de60d0682c600b034e063b7d3237723da70ab7552
+Payload = 239029f150bccbd67edbb67f8ae456b4ea066a4beee065f9
+CT = 9c8d5dd227fd9f81237601830afee4f0115636c8e5d5fd743cb9afed
+
+Count = 1
+Adata = ab91d1aa072947d22f0dc322355a022fe7f0747f4a184b48446bd27999ef01fe
+Payload = 25a43fd8bf241d67dab9e3c106cd27b71fd45a87b9254a53
+CT = 9ab94bfbc86549308714543d86d795f3e4840604b210d2de169d7775
+
+Count = 2
+Adata = 4c3bdc6186297896097b3297ba90bcde78dc8a9efe3bd8b10a85eed1bf63a30c
+Payload = e63d8303fa5c51550e417e77ec1ec647c9e2a853cab00fee
+CT = 5920f7208d1d050253ecc98b6c04740332b2f4d0c1859763b9c2e299
+
+Count = 3
+Adata = 8587324c1ff6712aed8af134744de5df1f88c5d2cb33f4f888af9fd39eb8e813
+Payload = f27548ec1608d3b8a5bdcbccb7e09cf4b5c29d3661b13a61
+CT = 4d683ccf614987eff8107c3037fa2eb04e92c1b56a84a2ec02f73205
+
+Count = 4
+Adata = 58820fb68ba1cd73b05a6698b4394ba1b13e8e296480f5afe1154d9b8536007c
+Payload = ecbd7091732e49c0f4bda2e63235ea43bbf8c8730f955f9c
+CT = 53a004b2046f1d97a910151ab22f580740a894f004a0c7114e1dd81b
+
+Count = 5
+Adata = f3034031933e7807d47140cf5c7794e42a228a522a83883b0765b57a411bad85
+Payload = 3002c6fb49497c7d1d06e1bd4edd57a9e54bbbb74e948c79
+CT = 8f1fb2d83e08282a40ab5641cec7e5ed1e1be73445a114f446525bc4
+
+Count = 6
+Adata = 05981dc26a1db2d8e2c3d85ea9a4d1dc3432d9edc4795ca03ca4661d2fc35b8c
+Payload = 214acfb2613b266f2929d43c7666f3a23e61423061cdbec3
+CT = 9e57bb91167a7238748463c0f67c41e6c5311eb36af8264e651844a3
+
+Count = 7
+Adata = 968a302a27624c304e894633af600c3cc7c614b7da3af0bf2d3f239c7605338a
+Payload = 9c575d592a9622c014c1303329757a65a414a9ed0c1b1b3f
+CT = 234a297a5dd77697496c87cfa96fc8215f44f56e072e83b249fd550d
+
+Count = 8
+Adata = 9011231ec382ecaaae57f34de1ac6bbb50741014a978160ce59c60491e64f30d
+Payload = 426a4c83793abdcff5e2a99e161785dc27c6168a329ee465
+CT = fd7738a00e7be998a84f1e62960d3798dc964a0939ab7ce84137defa
+
+Count = 9
+Adata = 96f0b1edec4ad14407dcaf30ed68942b46c48d58b2dd63af60fccd5bdd48e560
+Payload = e04006b68c83a5dd4ceac3cde238e48895ae17728fdc7bbe
+CT = 5f5d7295fbc2f18a11477431622256cc6efe4bf184e9e33356a4953f
+
+[Tlen = 6]
+
+Key = 8596a69890b0e47d43aeeca54b52029331da06fae63aa3249faaca94e2605feb
+Nonce = 20442e1c3f3c88919c39978b78
+
+Count = 10
+Adata = 4e0d3aa502bd03fe1761b167c4e0df1d228301d3ebaa4a0281becd813266e255
+Payload = f0b065da6ecb9ddcab855152d3b4155037adfa758ba96070
+CT = d6a0f377f7c1b14dcdba729cae5271b027e71cc7850173ec265867a29eb3
+
+Count = 11
+Adata = aeef2d1e3d3c9920a4fdb5f9d963b88e78a5d0edae531e3b55e702ed609d9a3c
+Payload = f2a8855e34854656df0776e80255ad1d125841c727201509
+CT = d4b813f3ad8f6ac7b93855267fb3c9fd0212a7752988069566e89a72dc0e
+
+Count = 12
+Adata = 3051ffb19862370bc46ca94a8eb906a660d539b18e965583e95acc149190e3e9
+Payload = 20955a0ca3c9c10d4055406ec12226130ecdaf195b08d65e
+CT = 0685cca13ac3ed9c266a63a0bcc442f31e8749ab55a0c5c2dff4f6257e06
+
+Count = 13
+Adata = aafa45a107d909756b4a1956d5228b50316fc5852afdeecf401fa2a71aabea46
+Payload = 246b60d17ea70deb1380fbf4bd767d88f53069b0f4136511
+CT = 027bf67ce7ad217a75bfd83ac0901968e57a8f02fabb768def0017c9acc1
+
+Count = 14
+Adata = ccdeab6a28b1b9e9f0c67116a91f2215b229d0edcd35d696db2bcf54e77db743
+Payload = 5b735697c5577ee0e352cf6a1495c490d6f7e97c3898f0ee
+CT = 7d63c03a5c5d5271856deca46973a070c6bd0fce3630e372c73969437912
+
+Count = 15
+Adata = 33a1e7d4820ed6a76a6dab90b4ba830888caf12a262e4eb6d75a505b2207de36
+Payload = 1170416faf81896c7f00815f53c2be5f7246d4794895b4b1
+CT = 3760d7c2368ba5fd193fa2912e24dabf620c32cb463da72dd7cb3721fcdd
+
+Count = 16
+Adata = 3df3edd9fc93be9960b5a632e2847b30b10187c8f83de5b45fcb2e3ed475569a
+Payload = 556765ffe5c46015cbd8194e32abc41e8f711773e2bcac90
+CT = 7377f3527cce4c84ade73a804f4da0fe9f3bf1c1ec14bf0c82183448e643
+
+Count = 17
+Adata = 4cb8663a1a934b6b27cbc1ed3040fbb99fbb6812f8ca35ff73cc13feeb483af7
+Payload = 3070e269f3e87cd82af3896895a5dd6fbfa9898279e0f73b
+CT = 166074c46ae250494cccaaa6e843b98fafe36f307748e4a76069901b5e3a
+
+Count = 18
+Adata = 876df130c01d0b9b8ebe43e71046c365e13124169026876d50d7e155f0299676
+Payload = dd18d40728c561e24e6e54834348dde5683f067baf8df469
+CT = fb0842aab1cf4d732851774d3eaeb9057875e0c9a125e7f56d65c2b005d4
+
+Count = 19
+Adata = da08b14e1b770b81faaf1e59851df1cba8838cd63bef141340ee378e65fdcbd4
+Payload = 7064a2491f716f4a2969815e4a281a54690ced9f794b264e
+CT = 567434e4867b43db4f56a29037ce7eb479460b2d77e335d275b37e9fb9e9
+
+[Tlen = 8]
+
+Key = bae73483de27b581a7c13f178a6d7bda168c1b4a1cb9180512a13e3ab914eb61
+Nonce = daf54faef6e4fc7867624b76f2
+
+Count = 20
+Adata = 7022eaa52c9da821da72d2edd98f6b91dfe474999b75b34699aeb38465f70c1c
+Payload = 28ef408d57930086011b167ac04b866e5b58fe6690a0b9c3
+CT = 356367c6cee4453658418d9517f7c6faddcd7c65aef460138cf050f48c505151
+
+Count = 21
+Adata = a61b6c1f0293a7c35520abf158a995e5ae59b43ec5f38ff6fd6529970c9f83ac
+Payload = 1c5ad37d2a55afbc390b27cde0c42d6651fe191239bfaa27
+CT = 01d6f436b322ea0c6051bc2237786df2d76b9b1107eb73f76bca352f92f383e1
+
+Count = 22
+Adata = 0f1c6dffeda98f7a159f9cc61820bfb29910d8eaa41b751a41f9fe5648f02fba
+Payload = 6efe6652d46a84166d30befe2fbee0795e9475b401eedd60
+CT = 737241194d1dc1a6346a2511f802a0edd801f7b73fba04b014fd7c84052208d9
+
+Count = 23
+Adata = 151110a9ce7e44e5d76d9cad53c1819317527fcd169051f01c6a3efcc06ea999
+Payload = 55b791ee495299916ff3c2327b4990952bebd0a2da9acfc5
+CT = 483bb6a5d025dc2136a959ddacf5d001ad7e52a1e4ce1615c3ebc7214b9eef31
+
+Count = 24
+Adata = 0ba1210696d735eebc13b609d0ec33bc740805105dd82f065b82892b931f1e6d
+Payload = 794a86f5b20d344ad86fd5523d08f1864737be57731440c2
+CT = 64c6a1be2b7a71fa81354ebdeab4b112c1a23c544d409912eff08182f8a00f13
+
+Count = 25
+Adata = 5a3b71b0fdecce8bd759d3d72321b5c3e882c82627c14e0b59cc8c6d191f243f
+Payload = efa6ddd6fb8e4480a0f64414694e5f9e7f2e9b97cbe9cd14
+CT = f22afa9d62f90130f9acdffbbef21f0af9bb1994f5bd14c46894be1f8fa14538
+
+Count = 26
+Adata = 5d344c5b94695a66192b6692e420c8eaa3cb482502be837b2a0a91b787fbe48e
+Payload = 561dd3bf419ae33ff521a43898cf12c6a5c6163eec22abc1
+CT = 4b91f4f4d8eda68fac7b3fd74f7352522353943dd2767211f4393bca514c3336
+
+Count = 27
+Adata = 08344486df2b2f9a6880a03503a3986c485f067c480c31a51607553b875f91fa
+Payload = 6d3596f25401f2e3b099613236f1d88a2f3d8edc1f04bc0c
+CT = 70b9b1b9cd76b753e9c3fadde14d981ea9a80cdf215065dcb708ffd04c8c2da0
+
+Count = 28
+Adata = 9d0824a4dc7e67326c5b68a6ea99cb68298a2af2cc1952351454b038f6270603
+Payload = c563a43e4cc0f93d955432f68287e63400a7fdcae738ba84
+CT = d8ef8375d5b7bc8dcc0ea919553ba6a086327fc9d96c63541511d7d684d58762
+
+Count = 29
+Adata = c4384069e09a3d4de2c94e7e6055d8a00394e268398d6ea32914097aec37a1f4
+Payload = 18c5865b414b2a06b4d71ab9550985b4f3c3d7817e8a8d7c
+CT = 0549a110d83c6fb6ed8d815682b5c5207556558240de54acef0919c5f5daf093
+
+[Tlen = 10]
+
+Key = d5b321b0ac2fedce0933d57d12195c7b9941f4caa95529125ed21c41fac43374
+Nonce = b35fb2262edfa14938a0fba03e
+
+Count = 30
+Adata = ba762bbda601d711e2dfc9dbe3003d39df1043ca845612b8e9dc9ff5c5d06ec4
+Payload = 6aa6ea668df60b0db85592d0a819c9df9e1099916272aafb
+CT = 97027de5effd82c58f8dbfb909d7696fbe2d54916262912001a4d765bc1c95c90a95
+
+Count = 31
+Adata = 77a685958ca801dbcbf346d6bac72662d3870899d7bcdef6665d57bacd4e558f
+Payload = c2992096828325820e2d7acaa17ac789b6830ec3128dd7f9
+CT = 3f3db715e088ac4a39f557a300b4673996bec3c3129dec22288aecb4c38c2391c21d
+
+Count = 32
+Adata = 3a54d3e14bbd0549570ef12425c4b36fd25382d56b68e217bc711ab1625fe9bb
+Payload = e5151262cafdd2f4dea187372dacb9e5975065572446f2a5
+CT = 18b185e1a8f65b3ce979aa5e8c621955b76da8572456c97edb4bd2cb1f1222e0d64f
+
+Count = 33
+Adata = 5c7604f9ac8fdf30ee5820e5aeb75b65d7855e5d2ff9ccf021640707bf1f53e8
+Payload = 1fe786f52daab92a6aa5f43263bed74153d90579a34bceff
+CT = e24311764fa130e25d7dd95bc27077f173e4c879a35bf5249283c1a61e9113462325
+
+Count = 34
+Adata = 42b8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+Payload = 56c3130c5af210b5bcf7c58b968fc75fc92b9c339efb7aee
+CT = ab67848f38f9997d8b2fe8e2374167efe91651339eeb4135bd3ffe1b1051ec3206db
+
+Count = 35
+Adata = c5a369a8291f4278e797ff11ea5e777d69df3b9c0c32d46150ed4b3e2c3defdd
+Payload = daa716f3cd1e008b46318ec90d976c3fbf88c3ff73cf0052
+CT = 27038170af15894371e9a3a0ac59cc8f9fb50eff73df3b8910d5d255f193b29eb961
+
+Count = 36
+Adata = 63bdceb36a032d3e0e81b4e98ad9861e2c708cef4e870c5b88a87ecc24449be3
+Payload = 42477d7d44881dabccfce52efb8a2cc917b182a23b71fb49
+CT = bfe3eafe26839463fb24c8475a448c79378c4fa23b61c0924e524729fb06212508e6
+
+Count = 37
+Adata = b7f8e7b66726e07c3c73d74135f068bb8025c9da9ba70affb9ed9a69675f0eef
+Payload = 07f48cdc12aa27119fbdfda4ec07ce6068c92ba7ba9c9309
+CT = fa501b5f70a1aed9a865d0cd4dc96ed048f4e6a7ba8ca8d2222af86d91fb6a2b09d3
+
+Count = 38
+Adata = 09891ed14f4488069cd6a5744061e06f8ff8d1bc87b10448b3fbfc1a4e327787
+Payload = e2e7002b769fb5b4201053457158147d99b0d5147f3acac2
+CT = 1f4397a814943c7c17c87e2cd096b4cdb98d18147f2af1194cddcb65a76c40698017
+
+Count = 39
+Adata = 8f9786940943752c536548497f9dae2bd8d677b8bbcb0121a9c9f3c399b62e4b
+Payload = 86be1d1949fe03b8b80ef7abb3e27394273d7b76d7697f0e
+CT = 7b1a8a9a2bf58a708fd6dac2122cd3240700b676d77944d5ddb42d504b6fc47d6575
+
+[Tlen = 12]
+
+Key = 7f4af6765cad1d511db07e33aaafd57646ec279db629048aa6770af24849aa0d
+Nonce = dde2a362ce81b2b6913abc3095
+
+Count = 40
+Adata = 404f5df97ece7431987bc098cce994fc3c063b519ffa47b0365226a0015ef695
+Payload = 7ebef26bf4ecf6f0ebb2eb860edbf900f27b75b4a6340fdb
+CT = 353022db9c568bd7183a13c40b1ba30fcc768c54264aa2cd2927a053c9244d3217a7ad05
+
+Count = 41
+Adata = e9ed05813262fbe769c1104d8ba5c836dbd229a22a681de3565d17ac1129f96b
+Payload = fdf5a5fb377bb52ad07a971c6a9da3e1a68d279be9ac4ed7
+CT = b67b754b5fc1c80d23f26f5e6f5df9ee9880de7b69d2e3c11c000c9d88f047ca198c4e65
+
+Count = 42
+Adata = f246f1e948c81c98ea13f03dd8eea878449d0c3d5b5fe87c633bbe0106fcb899
+Payload = e5e6b57e74ce7afbde3697e2a69d61ca615aa3dfd32fe31f
+CT = ae6865ce1c7407dc2dbe6fa0a35d3bc55f575a3f53514e095c09878f1a963b795b29f4dd
+
+Count = 43
+Adata = e4683285695348ff04a61d51d90b868dfe4cf6ea246544727adeaeface571d57
+Payload = ef2c3a6bb8602d290045854a5f223e6f43bfd0bb9278fa88
+CT = a4a2eadbd0da500ef3cd7d085ae264607db2295b1206579e807d196d2628df1c384816f7
+
+Count = 44
+Adata = 42695369dbd69f07b46db282653704c34106aad82efdcc99b452598b5353f904
+Payload = beda29c7fe15c73ee5bef96485eb8c9e3cd3ea7ee633ef45
+CT = f554f97796afba1916360126802bd69102de139e664d4253961c666279394e1e28cf1b02
+
+Count = 45
+Adata = 58c3ce3906633475441229cfcdf05e02ff3738ae8d1b255974f431b3309ed41e
+Payload = 419c96ba8142b27e3377716358c97a8a636d7fe8403165e1
+CT = 0a12460ae9f8cf59c0ff89215d0920855d608608c04fc8f764efe624dd6c6f8b8cdc76e3
+
+Count = 46
+Adata = a9c06d8029f8da31629c3a6ddceb6009220a69fc614af1c231ae8702b3a85d6e
+Payload = 69bb441a7640f77e124d66af45a0e9f646658a838dfcb957
+CT = 223594aa1efa8a59e1c59eed4060b3f9786873630d8214410ef4b71970b9f80087533cf7
+
+Count = 47
+Adata = a92e88edd297da8c7089e21822b3e6cffd6837c78b975c8413fd6cca1b99bcb0
+Payload = a45b755658d38bdea57d1faae21d75428a17f2c74a33d2d5
+CT = efd5a5e63069f6f956f5e7e8e7dd2f4db41a0b27ca4d7fc36e27dfbf1ff7f08d1b213848
+
+Count = 48
+Adata = 421533453c8129fc8e681c68b9d7371adb0a19442ede7accd185129fcb7db648
+Payload = 2c3e28b61cede08121e80ee08c4f1f19dabb19add9d2dc8a
+CT = 67b0f80674579da6d260f6a2898f4516e4b6e04d59ac719ca48d1a0b815139fa28652d94
+
+Count = 49
+Adata = 55351bc7ddbc6b668d435088f1f9cf6f53caae16d4292b14bc0deec20f393ba0
+Payload = 81fa7fd41ba267bcbdf024cef1543b041cadd96b62a7cf1f
+CT = ca74af6473181a9b4e78dc8cf494610b22a0208be2d962091301c87a2a94df147c8cce4c
+
+[Tlen = 14]
+
+Key = 5c8b59d3e7986c277d5ad51e4a2233251076809ebf59463f47cd10b4aa951f8c
+Nonce = 21ff892b743d661189e205c7f3
+
+Count = 50
+Adata = f1e0af185180d2eb63e50e37ba692647cac2c6a149d70c81dbd34685ed78feaa
+Payload = 138ee53b1914d3322c2dd0a4e02faab2236555131d5eea08
+CT = 5b2f3026f30fdd50accc40ddd093b7997f23d7c6d3c8bc425f82c828413643b8794494cb5236
+
+Count = 51
+Adata = 45c5c284836414407268d7c8a89a0146759cfc92242004027d58d0828fad74e7
+Payload = fe3df84ee9b237f9edd77a5b8af96bc3e184579ac9c6e246
+CT = b69c2d5303a9399b6d36ea22ba4576e8bdc2d54f0750b40c6db5c92de5fb3aafba9537795e17
+
+Count = 52
+Adata = a41ea42692eac0914fef35e58409007342cef027de141223ffb46da7f58df034
+Payload = e0f5c02f9f84e57fada3f3575f1b1a748f360e0ea781b7b8
+CT = a8541532759feb1d2d42632e6fa7075fd3708cdb6917e1f21af6cf931ac943fd3affa6ad6fd1
+
+Count = 53
+Adata = 17dae00f2a9417780ecfef98f290a5ca9b17c873a9149cd81c18bd33164a0405
+Payload = 3a77a2ec5a1be6cbfbbfaab3e65427cb38d6798b132ff5c7
+CT = 72d677f1b000e8a97b5e3acad6e83ae06490fb5eddb9a38d38a3f09c56ae653be49b355fb938
+
+Count = 54
+Adata = 33b44873a7a1e5b0fdbb7e7347623e4fa1ccd937feb26fda2749b42f00744e50
+Payload = d0628b26019dad84de628d9dabf42cfb195165a369c22b49
+CT = 98c35e3beb86a3e65e831de49b4831d04517e776a7547d03974deec7ce2e1f296890bee795cb
+
+Count = 55
+Adata = f4fc5acff75d404849675b813cf7adcaeb8f3d56cb9a54a083f8ec07feb666bb
+Payload = 10b5ec41036e4bc5d61728e8811b520b7080c2177c122cbd
+CT = 5814395ce97545a756f6b891b1a74f202cc640c2b2847af798a3bc56f900bee7e8271c6dab22
+
+Count = 56
+Adata = ba051d1bc19b9a27520834fa3977b6413a319c9a52c8785e3e9594bd4265d911
+Payload = 648a84813ca97aef4ab7e143ee29acb946388660f18eb671
+CT = 2c2b519cd6b2748dca56713ade95b1921a7e04b53f18e03be6623d80c677633a9e4f999bb885
+
+Count = 57
+Adata = f5c629299d18901c8c34c42e8fc29a70c377c160fdea4a6068a36867707575f7
+Payload = 3ead49ed0b41de79c829098d034b666bce052d79bf1f56db
+CT = 760c9cf0e15ad01b48c899f433f77b409243afac71890091c65b88ff4fdd9b8187f7d71ba04b
+
+Count = 58
+Adata = da486fd2953a72838e67e1909ed4042df67c355b648a45bcd2cc1ba610659e76
+Payload = 4543457c8fdf463c4bf8515a762cdc83d9aaa887d3eaa2af
+CT = 0de2906165c4485ecb19c1234690c1a885ec2a521d7cf4e5727c3404564ed41528973d389c7c
+
+Count = 59
+Adata = a0b1d3600f6eba910a11537d61fa12184959f1c3ae386570cbbc9106f7a7ba07
+Payload = 22071ef5d204417f99bc2faf53ecc4c6cf795e77805633ee
+CT = 6aa6cbe8381f4f1d195dbfd66350d9ed933fdca24ec065a446ecb536703a7a97928f80fcc7cf
+
+[Tlen = 16]
+
+Key = 60823b64e0b2da3a7eb772bd5941c534e6ff94ea96b564e2b38f82c78bb54522
+Nonce = 48526f1bffc97dd65e42906983
+
+Count = 60
+Adata = fab62b3e5deda7a9c1128663cc81c44b74ab1bfe70bc1c9dec7c7fd08173b80a
+Payload = a8be794613835c4366e75817d228438f011a2ec8a86f9797
+CT = cc3efe04d84a4ec5cb6a6c28dc2c2d386a359d9550dbdec963ddd56464aed6d0613159d1aa181dcb
+
+Count = 61
+Adata = b3ff11e57eeab41bc597622c770c9eea333e178d5bd5689c6a30011187a965b8
+Payload = 7590769380dc91832da023798dfdd447b9f7adaa09d7e2d0
+CT = 1110f1d14b158305802d174683f9baf0d2d81ef7f163ab8e7c1273765bc5bfdeca429cc8ebd8aca2
+
+Count = 62
+Adata = 2a953a081c5d52bc500c9c12f56cd2aab5c920d73098335baa5d947100cb3411
+Payload = 30e4de5e8c275677f8f4f7bbf9d101f96b38d79968ea028c
+CT = 5464591c47ee44f15579c384f7d56f4e001764c4905e4bd2886229c09b986bee3a8a3025c150d3a3
+
+Count = 63
+Adata = 99cc9d1b3db79640dfdc4423af3ded03c329f7ba5b6b509269c10e59519053b8
+Payload = 852698f6ab4aa794b3d657c4a2ca7b9c8bfb5fc9b4ad0aca
+CT = e1a61fb46083b5121e5b63fbacce152be0d4ec944c19439480cd04041918c4071ea5ac263f36c544
+
+Count = 64
+Adata = b76aef71eaf03c2d0dc0623e90596fcb0bc4dbbed1d5bb24c8af37d778863e5b
+Payload = cd337fcf362d301d66916c7097bdeb31df8206e00f7ac106
+CT = a9b3f88dfde4229bcb1c584f99b98586b4adb5bdf7ce8858f001d6002eafaec49c472acdfaedf1de
+
+Count = 65
+Adata = 42a718d892e229a1807b74bd730fb15500ac4a790392100aef362cd7628d5806
+Payload = 0041a0cf48fcf870b21db6107cfd9ef91e409afc7562ffa7
+CT = 64c1278d8335eaf61f90822f72f9f04e756f29a18dd6b6f975d86cde91b6610496c3bb5276238741
+
+Count = 66
+Adata = e788c98ae85b11b3ae884eed6f3b8f5bcf5ab1b7b20ad3f44f760b2287cc5793
+Payload = fcc74ef1908dbcab9b05c76ee5a9941cdef933d433c0d25f
+CT = 9847c9b35b44ae2d3688f351ebadfaabb5d68089cb749b01db7d9f10e75d1b213beae0e0230dd82b
+
+Count = 67
+Adata = d330fc1ca406dd9528e9281aa1a3cdf013b698c14a4e55371e7539c9f6867dd4
+Payload = 611dade00cec14743be4e035cafe7507df5fb94b278875b1
+CT = 059d2aa2c72506f29669d40ac4fa1bb0b4700a16df3c3cefc63ba64291e73e6349ed089a53564291
+
+Count = 68
+Adata = 06bbadd5d22d1796d88415d7a4b024313f243bd0f58aafc75bb554a691d7e54f
+Payload = b67b5dd7f90ecd48a45853cb193e0d9702d78898f07e831d
+CT = d2fbda9532c7dfce09d567f4173a632069f83bc508caca43ac4d7bd964a2f9e2303df688dd0513da
+
+Count = 69
+Adata = 54da66d406f2d98edd999b673ef44d46ffd196091c8b7582ac2ed6bf13dc648f
+Payload = d092dc436c41836bdb815e473bc6a1906f37624e73b494f9
+CT = b4125b01a78891ed760c6a7835c2cf270418d1138b00dda7b4cd237cd9a7c9d93b9cc0f171818dae
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/ccmtestvectors.zip b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/ccmtestvectors.zip
new file mode 100644
index 0000000000..34bb67b1ac
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/ccmtestvectors.zip
Binary files differ
diff --git a/lib/crypto/test/engine_SUITE.erl b/lib/crypto/test/engine_SUITE.erl
new file mode 100644
index 0000000000..b083b30d70
--- /dev/null
+++ b/lib/crypto/test/engine_SUITE.erl
@@ -0,0 +1,875 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+-module(engine_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{seconds, 10}}
+ ].
+
+all() ->
+ [
+ get_all_possible_methods,
+ engine_load_all_methods,
+ engine_load_some_methods,
+ multiple_engine_load,
+ engine_list,
+ get_id_and_name,
+ engine_by_id,
+ bad_arguments,
+ unknown_engine,
+ pre_command_fail_bad_value,
+ pre_command_fail_bad_key,
+ failed_engine_init,
+ ctrl_cmd_string,
+ ctrl_cmd_string_optional,
+ ensure_load,
+ {group, engine_stored_key}
+ ].
+
+groups() ->
+ [{engine_stored_key, [],
+ [sign_verify_rsa,
+ sign_verify_dsa,
+ sign_verify_ecdsa,
+ sign_verify_rsa_pwd,
+ sign_verify_rsa_pwd_bad_pwd,
+ priv_encrypt_pub_decrypt_rsa,
+ priv_encrypt_pub_decrypt_rsa_pwd,
+ pub_encrypt_priv_decrypt_rsa,
+ pub_encrypt_priv_decrypt_rsa_pwd,
+ get_pub_from_priv_key_rsa,
+ get_pub_from_priv_key_rsa_pwd,
+ get_pub_from_priv_key_rsa_pwd_no_pwd,
+ get_pub_from_priv_key_rsa_pwd_bad_pwd,
+ get_pub_from_priv_key_dsa,
+ get_pub_from_priv_key_ecdsa
+ ]}].
+
+
+init_per_suite(Config) ->
+ case crypto:info_lib() of
+ [{_,_, <<"OpenSSL 1.0.1s-freebsd 1 Mar 2016">>}] ->
+ {skip, "Problem with engine on OpenSSL 1.0.1s-freebsd"};
+ Res ->
+ ct:log("crypto:info_lib() -> ~p\n", [Res]),
+ try crypto:start() of
+ ok ->
+ Config;
+ {error,{already_started,crypto}} ->
+ Config
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end
+ end.
+
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+init_per_group(engine_stored_key, Config) ->
+ case load_storage_engine(Config) of
+ {ok, E} ->
+ KeyDir = key_dir(Config),
+ [{storage_engine,E}, {storage_dir,KeyDir} | Config];
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {error, notsup} ->
+ {skip, "Engine not supported on this SSL version"};
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"};
+ Other ->
+ ct:log("Engine load failed: ~p",[Other]),
+ {fail, "Engine load failed"}
+ end;
+init_per_group(_Group, Config0) ->
+ Config0.
+
+end_per_group(engine_stored_key, Config) ->
+ case proplists:get_value(storage_engine, Config) of
+ undefined ->
+ ok;
+ E ->
+ ok = crypto:engine_unload(E)
+ end;
+end_per_group(_, _) ->
+ ok.
+
+%%--------------------------------------------------------------------
+init_per_testcase(_Case, Config) ->
+ Config.
+end_per_testcase(_Case, _Config) ->
+ ok.
+
+%%-------------------------------------------------------------------------
+%% Test cases starts here.
+%%-------------------------------------------------------------------------
+get_all_possible_methods() ->
+ [{doc, "Just fetch all possible engine methods supported."}].
+
+get_all_possible_methods(Config) when is_list(Config) ->
+ try
+ List = crypto:engine_get_all_methods(),
+ true = erlang:is_list(List),
+ ct:log("crypto:engine_get_all_methods() -> ~p\n", [List]),
+ ok
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end.
+
+engine_load_all_methods()->
+ [{doc, "Use a dummy md5 engine that does not implement md5"
+ "but rather returns a static binary to test that crypto:engine_load "
+ "functions works."}].
+
+engine_load_all_methods(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
+ Md5Hash1 = crypto:hash(md5, "Don't panic"),
+ Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:engine_unload(E),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash2 ->
+ ct:fail(fail_to_unload_still_test_engine);
+ Md5Hash1 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_unload_engine)
+ end;
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+engine_load_some_methods()->
+ [{doc, "Use a dummy md5 engine that does not implement md5"
+ "but rather returns a static binary to test that crypto:engine_load "
+ "functions works."}].
+
+engine_load_some_methods(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
+ Md5Hash1 = crypto:hash(md5, "Don't panic"),
+ Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
+ EngineMethods = crypto:engine_get_all_methods() --
+ [engine_method_dh, engine_method_rand,
+ engine_method_ciphers, engine_method_store,
+ engine_method_pkey_meths, engine_method_pkey_asn1_meths],
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ [],
+ EngineMethods) of
+ {ok, E} ->
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_engine_still_original);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:engine_unload(E),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash2 ->
+ ct:fail(fail_to_unload_still_test_engine);
+ Md5Hash1 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_unload_engine)
+ end;
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+multiple_engine_load()->
+ [{doc, "Use a dummy md5 engine that does not implement md5"
+ "but rather returns a static binary to test that crypto:engine_load "
+ "functions works when called multiple times."}].
+
+multiple_engine_load(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
+ Md5Hash1 = crypto:hash(md5, "Don't panic"),
+ Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ {ok, E1} = crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []),
+ {ok, E2} = crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:engine_unload(E2),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:engine_unload(E),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:engine_unload(E1),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash2 ->
+ ct:fail(fail_to_unload_still_test_engine);
+ Md5Hash1 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_unload_engine)
+ end;
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+engine_list()->
+ [{doc, "Test add and remove engine ID to the SSL internal engine list."}].
+
+engine_list(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ EngineList0 = crypto:engine_list(),
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ EngineList0 = crypto:engine_list(),
+ ok = crypto:engine_add(E),
+ [<<"MD5">>] = lists:subtract(crypto:engine_list(), EngineList0),
+ ok = crypto:engine_remove(E),
+ EngineList0 = crypto:engine_list(),
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+get_id_and_name()->
+ [{doc, "Test fetching id and name from an engine."}].
+
+get_id_and_name(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ <<"MD5">> = crypto:engine_get_id(E),
+ <<"MD5 test engine">> = crypto:engine_get_name(E),
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+engine_by_id()->
+ [{doc, "Test fetching a new reference the the engine when the"
+ "engine id is added to the SSL engine list."}].
+
+engine_by_id(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ case crypto:engine_by_id(<<"MD5">>) of
+ {error,bad_engine_id} ->
+ ok;
+ {ok, _} ->
+ ct:fail(fail_engine_found)
+ end,
+ ok = crypto:engine_add(E),
+ {ok, _E1} = crypto:engine_by_id(<<"MD5">>),
+ ok = crypto:engine_remove(E),
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+%%-------------------------------------------------------------------------
+%% Error cases
+bad_arguments()->
+ [{doc, "Test different arguments in bad format."}].
+
+bad_arguments(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ try
+ crypto:engine_load(fail_engine, [], [])
+ catch
+ error:badarg ->
+ ok
+ end,
+ try
+ crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ 1,
+ {<<"ID">>, <<"MD5">>},
+ <<"LOAD">>],
+ [])
+ catch
+ error:badarg ->
+ ok
+ end,
+ try
+ crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ {'ID', <<"MD5">>},
+ <<"LOAD">>],
+ [])
+ catch
+ error:badarg ->
+ ok
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+unknown_engine() ->
+ [{doc, "Try to load a non existent engine."}].
+
+unknown_engine(Config) when is_list(Config) ->
+ try
+ {error, bad_engine_id} = crypto:engine_load(<<"fail_engine">>, [], []),
+ ok
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end.
+
+pre_command_fail_bad_value() ->
+ [{doc, "Test pre command due to bad value"}].
+
+pre_command_fail_bad_value(Config) when is_list(Config) ->
+ DataDir = unicode:characters_to_binary(code:priv_dir(crypto)),
+ try
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>,
+ <<DataDir/binary, <<"/libfail_engine.so">>/binary >>},
+ {<<"ID">>, <<"MD5">>},
+ <<"LOAD">>],
+ []) of
+ {error, ctrl_cmd_failed} ->
+ ok;
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end.
+
+pre_command_fail_bad_key() ->
+ [{doc, "Test pre command due to bad key"}].
+
+pre_command_fail_bad_key(Config) when is_list(Config) ->
+ try
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_WRONG_PATH">>, Engine},
+ {<<"ID">>, <<"MD5">>},
+ <<"LOAD">>],
+ []) of
+ {error, ctrl_cmd_failed} ->
+ ok;
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end.
+
+failed_engine_init()->
+ [{doc, "Test failing engine init due to missed pre command"}].
+
+failed_engine_init(Config) when is_list(Config) ->
+ try
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ {<<"ID">>, <<"MD5">>}],
+ []) of
+ {error, engine_init_failed} ->
+ ok;
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end.
+
+
+%%-------------------------------------------------------------------------
+%% Test the optional flag in ctrl comands
+ctrl_cmd_string()->
+ [{doc, "Test that a not known optional ctrl comand do not fail"}].
+ctrl_cmd_string(Config) when is_list(Config) ->
+ try
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ {<<"ID">>, <<"MD5">>},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ case crypto:engine_ctrl_cmd_string(E, <<"TEST">>, <<"17">>) of
+ ok ->
+ ct:fail(fail_ctrl_cmd_should_fail);
+ {error,ctrl_cmd_failed} ->
+ ok
+ end,
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end.
+
+ctrl_cmd_string_optional()->
+ [{doc, "Test that a not known optional ctrl comand do not fail"}].
+ctrl_cmd_string_optional(Config) when is_list(Config) ->
+ try
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ {<<"ID">>, <<"MD5">>},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ case crypto:engine_ctrl_cmd_string(E, <<"TEST">>, <<"17">>, true) of
+ ok ->
+ ok;
+ _ ->
+ ct:fail(fail_ctrl_cmd_string)
+ end,
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end.
+
+ensure_load()->
+ [{doc, "Test the special ensure load function."}].
+
+ensure_load(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
+ Md5Hash1 = crypto:hash(md5, "Don't panic"),
+ Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
+ case crypto:ensure_engine_loaded(<<"MD5">>, Engine) of
+ {ok, E} ->
+ {ok, _E1} = crypto:ensure_engine_loaded(<<"MD5">>, Engine),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:ensure_engine_unloaded(E),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash2 ->
+ ct:fail(fail_to_unload_still_test_engine);
+ Md5Hash1 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_unload_engine)
+ end;
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+%%%----------------------------------------------------------------
+%%% Pub/priv key storage tests. Thoose are for testing the crypto.erl
+%%% support for using priv/pub keys stored in an engine.
+
+sign_verify_rsa(Config) ->
+ Priv = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_private_key.pem")},
+ Pub = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_public_key.pem")},
+ sign_verify(rsa, sha, Priv, Pub).
+
+sign_verify_dsa(Config) ->
+ Priv = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "dsa_private_key.pem")},
+ Pub = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "dsa_public_key.pem")},
+ sign_verify(dss, sha, Priv, Pub).
+
+sign_verify_ecdsa(Config) ->
+ Priv = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "ecdsa_private_key.pem")},
+ Pub = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "ecdsa_public_key.pem")},
+ sign_verify(ecdsa, sha, Priv, Pub).
+
+sign_verify_rsa_pwd(Config) ->
+ Priv = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_private_key_pwd.pem"),
+ password => "password"},
+ Pub = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_public_key_pwd.pem")},
+ sign_verify(rsa, sha, Priv, Pub).
+
+sign_verify_rsa_pwd_bad_pwd(Config) ->
+ Priv = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_private_key_pwd.pem"),
+ password => "Bad password"},
+ Pub = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_public_key_pwd.pem")},
+ try sign_verify(rsa, sha, Priv, Pub) of
+ _ -> {fail, "PWD prot pubkey sign succeded with no pwd!"}
+ catch
+ error:badarg -> ok
+ end.
+
+priv_encrypt_pub_decrypt_rsa(Config) ->
+ Priv = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_private_key.pem")},
+ Pub = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_public_key.pem")},
+ priv_enc_pub_dec(rsa, Priv, Pub, rsa_pkcs1_padding).
+
+priv_encrypt_pub_decrypt_rsa_pwd(Config) ->
+ Priv = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_private_key_pwd.pem"),
+ password => "password"},
+ Pub = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_public_key_pwd.pem")},
+ priv_enc_pub_dec(rsa, Priv, Pub, rsa_pkcs1_padding).
+
+pub_encrypt_priv_decrypt_rsa(Config) ->
+ Priv = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_private_key.pem")},
+ Pub = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_public_key.pem")},
+ pub_enc_priv_dec(rsa, Pub, Priv, rsa_pkcs1_padding).
+
+pub_encrypt_priv_decrypt_rsa_pwd(Config) ->
+ Priv = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_private_key_pwd.pem"),
+ password => "password"},
+ Pub = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_public_key_pwd.pem")},
+ pub_enc_priv_dec(rsa, Pub, Priv, rsa_pkcs1_padding).
+
+get_pub_from_priv_key_rsa(Config) ->
+ Priv = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_private_key.pem")},
+ case crypto:privkey_to_pubkey(rsa, Priv) of
+ {error, not_found} ->
+ {fail, "Key not found"};
+ {error, notsup} ->
+ {skip, "RSA not supported"};
+ {error, Error} ->
+ {fail, {wrong_error,Error}};
+ Pub ->
+ ct:log("rsa Pub = ~p",[Pub]),
+ sign_verify(rsa, sha, Priv, Pub)
+ end.
+
+get_pub_from_priv_key_rsa_pwd(Config) ->
+ Priv = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_private_key_pwd.pem"),
+ password => "password"},
+ case crypto:privkey_to_pubkey(rsa, Priv) of
+ {error, not_found} ->
+ {fail, "Key not found"};
+ {error, notsup} ->
+ {skip, "RSA not supported"};
+ {error, Error} ->
+ {fail, {wrong_error,Error}};
+ Pub ->
+ ct:log("rsa Pub = ~p",[Pub]),
+ sign_verify(rsa, sha, Priv, Pub)
+ end.
+
+get_pub_from_priv_key_rsa_pwd_no_pwd(Config) ->
+ Priv = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_private_key_pwd.pem")},
+ case crypto:privkey_to_pubkey(rsa, Priv) of
+ {error, not_found} ->
+ ok;
+ {error, notsup} ->
+ {skip, "RSA not supported"};
+ {error, Error} ->
+ {fail, {wrong_error,Error}};
+ Pub ->
+ ct:log("rsa Pub = ~p",[Pub]),
+ {fail, "PWD prot pubkey fetch succeded although no pwd!"}
+ end.
+
+get_pub_from_priv_key_rsa_pwd_bad_pwd(Config) ->
+ Priv = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "rsa_private_key_pwd.pem"),
+ password => "Bad password"},
+ case crypto:privkey_to_pubkey(rsa, Priv) of
+ {error, not_found} ->
+ ok;
+ {error, notsup} ->
+ {skip, "RSA not supported"};
+ {error, Error} ->
+ {fail, {wrong_error,Error}};
+ Pub ->
+ ct:log("rsa Pub = ~p",[Pub]),
+ {fail, "PWD prot pubkey fetch succeded with bad pwd!"}
+ end.
+
+get_pub_from_priv_key_dsa(Config) ->
+ Priv = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "dsa_private_key.pem")},
+ case crypto:privkey_to_pubkey(dss, Priv) of
+ {error, not_found} ->
+ {fail, "Key not found"};
+ {error, notsup} ->
+ {skip, "DSA not supported"};
+ {error, Error} ->
+ {fail, {wrong_error,Error}};
+ Pub ->
+ ct:log("dsa Pub = ~p",[Pub]),
+ sign_verify(dss, sha, Priv, Pub)
+ end.
+
+get_pub_from_priv_key_ecdsa(Config) ->
+ Priv = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "ecdsa_private_key.pem")},
+ case crypto:privkey_to_pubkey(ecdsa, Priv) of
+ {error, not_found} ->
+ {fail, "Key not found"};
+ {error, notsup} ->
+ {skip, "ECDSA not supported"};
+ {error, Error} ->
+ {fail, {wrong_error,Error}};
+ Pub ->
+ ct:log("ecdsa Pub = ~p",[Pub]),
+ sign_verify(ecdsa, sha, Priv, Pub)
+ end.
+
+%%%================================================================
+%%% Help for engine_stored_pub_priv_keys* test cases
+%%%
+load_storage_engine(_Config) ->
+ case crypto:get_test_engine() of
+ {ok, Engine} ->
+ try crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ [])
+ catch
+ error:notsup ->
+ {error, notsup}
+ end;
+
+ {error, Error} ->
+ {error, Error}
+ end.
+
+
+key_dir(Config) ->
+ DataDir = unicode:characters_to_binary(proplists:get_value(data_dir, Config)),
+ filename:join(DataDir, "pkcs8").
+
+
+engine_ref(Config) ->
+ proplists:get_value(storage_engine, Config).
+
+key_id(Config, File) ->
+ filename:join(proplists:get_value(storage_dir,Config), File).
+
+pubkey_alg_supported(Alg) ->
+ lists:member(Alg,
+ proplists:get_value(public_keys, crypto:supports())).
+
+
+pub_enc_priv_dec(Alg, KeyEnc, KeyDec, Padding) ->
+ case pubkey_alg_supported(Alg) of
+ true ->
+ PlainText = <<"Hej på dig">>,
+ CryptoText = crypto:public_encrypt(Alg, PlainText, KeyEnc, Padding),
+ case crypto:private_decrypt(Alg, CryptoText, KeyDec, Padding) of
+ PlainText -> ok;
+ _ -> {fail, "Encrypt-decrypt error"}
+ end;
+ false ->
+ {skip, lists:concat([Alg," is not supported by cryptolib"])}
+ end.
+
+priv_enc_pub_dec(Alg, KeyEnc, KeyDec, Padding) ->
+ case pubkey_alg_supported(Alg) of
+ true ->
+ PlainText = <<"Hej på dig">>,
+ CryptoText = crypto:private_encrypt(Alg, PlainText, KeyEnc, Padding),
+ case crypto:public_decrypt(Alg, CryptoText, KeyDec, Padding) of
+ PlainText -> ok;
+ _ -> {fail, "Encrypt-decrypt error"}
+ end;
+ false ->
+ {skip, lists:concat([Alg," is not supported by cryptolib"])}
+ end.
+
+sign_verify(Alg, Sha, KeySign, KeyVerify) ->
+ case pubkey_alg_supported(Alg) of
+ true ->
+ PlainText = <<"Hej på dig">>,
+ Signature = crypto:sign(Alg, Sha, PlainText, KeySign),
+ case crypto:verify(Alg, Sha, PlainText, Signature, KeyVerify) of
+ true -> ok;
+ _ -> {fail, "Sign-verify error"}
+ end;
+ false ->
+ {skip, lists:concat([Alg," is not supported by cryptolib"])}
+ end.
diff --git a/lib/crypto/test/engine_SUITE_data/pkcs8/dsa_private_key.pem b/lib/crypto/test/engine_SUITE_data/pkcs8/dsa_private_key.pem
new file mode 100644
index 0000000000..778ffac675
--- /dev/null
+++ b/lib/crypto/test/engine_SUITE_data/pkcs8/dsa_private_key.pem
@@ -0,0 +1,9 @@
+-----BEGIN PRIVATE KEY-----
+MIIBSwIBADCCASwGByqGSM44BAEwggEfAoGBAMyitTMR7vPbpqyAXJpqnB0AhFwQ
+F87IE+JKFl5bD/MSkhhRV5sM73HUU1ooXY0FjhZ+cdLUCATuZR5ta4ydANqWIcAB
+gX3IwF1B4zf5SXEKTWkUYneL9dOKtiZLtoG28swrk8xMxwX+0fLHkltCEj6FiTW9
+PFrv8GmIfV6DjcI9AhUAqXWbb3RtoN9Ld28fVMhGZrj3LJUCgYEAwnxGHGBMpJaF
+2w7zAw3jHjL8PMYlV6vnufGHQlwF0ZUXJxRsvagMb/X1qACTu2VPYEVoLQGM3cfH
+EhHoQmvSXGAyTfR7Bmn3gf1n/s/DcFbdZduUCZ/rAyIrfd0eSbc1I+kZk85UCsKK
+w/IYdlqcuYa4Cgm2TapT5uEMqH4jhzEEFgIULh8swEUWmU8aJNWsrWl4eCiuUUg=
+-----END PRIVATE KEY-----
diff --git a/lib/crypto/test/engine_SUITE_data/pkcs8/dsa_public_key.pem b/lib/crypto/test/engine_SUITE_data/pkcs8/dsa_public_key.pem
new file mode 100644
index 0000000000..0fa5428828
--- /dev/null
+++ b/lib/crypto/test/engine_SUITE_data/pkcs8/dsa_public_key.pem
@@ -0,0 +1,12 @@
+-----BEGIN PUBLIC KEY-----
+MIIBtzCCASwGByqGSM44BAEwggEfAoGBAMyitTMR7vPbpqyAXJpqnB0AhFwQF87I
+E+JKFl5bD/MSkhhRV5sM73HUU1ooXY0FjhZ+cdLUCATuZR5ta4ydANqWIcABgX3I
+wF1B4zf5SXEKTWkUYneL9dOKtiZLtoG28swrk8xMxwX+0fLHkltCEj6FiTW9PFrv
+8GmIfV6DjcI9AhUAqXWbb3RtoN9Ld28fVMhGZrj3LJUCgYEAwnxGHGBMpJaF2w7z
+Aw3jHjL8PMYlV6vnufGHQlwF0ZUXJxRsvagMb/X1qACTu2VPYEVoLQGM3cfHEhHo
+QmvSXGAyTfR7Bmn3gf1n/s/DcFbdZduUCZ/rAyIrfd0eSbc1I+kZk85UCsKKw/IY
+dlqcuYa4Cgm2TapT5uEMqH4jhzEDgYQAAoGAXPygOFYdeKgfLmuIC303cESYXvic
+e2GNJomv8vaWLZmbLVVDfwA1fNsuF1hZkWw8f7aYaN9iZ3yl9u4Yk4TbJKkqfJqd
+dgVt288SUqvi+NMHODUzYi9KAOXxupXffZSvdu54gKRaDuFTZ5XNcRqIJWGYlJYg
+NVHF5FPZ4Bk2FYA=
+-----END PUBLIC KEY-----
diff --git a/lib/crypto/test/engine_SUITE_data/pkcs8/ecdsa_private_key.pem b/lib/crypto/test/engine_SUITE_data/pkcs8/ecdsa_private_key.pem
new file mode 100644
index 0000000000..a45522064f
--- /dev/null
+++ b/lib/crypto/test/engine_SUITE_data/pkcs8/ecdsa_private_key.pem
@@ -0,0 +1,8 @@
+-----BEGIN PRIVATE KEY-----
+MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIBparGjr0KcdNrVM2J
+G0mW5ltP1QyvxDqBMyWLWo3fruRZv6Qoohl5skd1u4O+KJoM/UrrSTOXI/MDR7NN
+i1yl7O+hgYkDgYYABAG8K2XVsK0ahG9+HIIPwCO0pJY8ulwSTXwIjkCGyB2lpglh
+8qJmRzuyGcfRTslv8wfv0sPlT9H9PKDvgrTUL7rvQQDdOODNgVPXSecUoXoPn+X+
+eqxs77bjx+A5x0t/i3m5PfkaNPh5MZ1H/bWuOOdj2ZXZw0R4rlVc0zVrgnPU8L8S
+BQ==
+-----END PRIVATE KEY-----
diff --git a/lib/crypto/test/engine_SUITE_data/pkcs8/ecdsa_public_key.pem b/lib/crypto/test/engine_SUITE_data/pkcs8/ecdsa_public_key.pem
new file mode 100644
index 0000000000..6d22fe43fe
--- /dev/null
+++ b/lib/crypto/test/engine_SUITE_data/pkcs8/ecdsa_public_key.pem
@@ -0,0 +1,6 @@
+-----BEGIN PUBLIC KEY-----
+MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBvCtl1bCtGoRvfhyCD8AjtKSWPLpc
+Ek18CI5AhsgdpaYJYfKiZkc7shnH0U7Jb/MH79LD5U/R/Tyg74K01C+670EA3Tjg
+zYFT10nnFKF6D5/l/nqsbO+248fgOcdLf4t5uT35GjT4eTGdR/21rjjnY9mV2cNE
+eK5VXNM1a4Jz1PC/EgU=
+-----END PUBLIC KEY-----
diff --git a/lib/crypto/test/engine_SUITE_data/pkcs8/rsa_private_key.pem b/lib/crypto/test/engine_SUITE_data/pkcs8/rsa_private_key.pem
new file mode 100644
index 0000000000..ea0e3d3958
--- /dev/null
+++ b/lib/crypto/test/engine_SUITE_data/pkcs8/rsa_private_key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCwwb0/ddXGXTFK
+4FLxXdV6a/WJMSoPPS55RvZIAHFsiTtvPLbJ8LxDsZ6wSVZLN0/UQ4wdWn9jftyj
+U5/IxBVG8XOtKimTMvm3/ZOzVLueGHBbrLYscRv9oL85ulTKHWgrZDu0lBX5JJTI
+v5UTCErzJRQbka9DG1GaBgDb1PlXfkzBWMwfsBZmwoC77KvCcIGCgbW/XCY03TP2
+3Tg8drvpByMStddP2FQ4fZ91qFUzPu8uhZEsqSQTFlmhgGEx7dLlky0xvu62RuAD
+RTpINpcWZtWDHTdssOqu653LwwqBY8lBopCZ/4Af8QR3ZYkQhen1YLEbVheXRuzI
+LSCZIiJNAgMBAAECggEBAJH4/fxpqQkvr2Shy33Pu1xlyhnpw01gfn/jrcKasxEq
+aC4eWup86E2TY3U8q4pkfIXU3uLi+O9HNpmflwargNLc1mY8uqb44ygiv5bLNEKE
+9k2PXcdoBfC4jxPyoNFl5cBn/7LK1TazEjiTl15na9ZPWcLG1pG5/vMPYCgsQ1sP
+8J3c4E3aaXIj9QceYxBprl490OCzieGyZlRipncz3g4UShRc/b4cycvDZOJpmAy4
+zbWTcBcSMPVPi5coF0K8UcimiqZkotfb/2RLc433i34IdsIXMM+brdq+g8rmjg5a
++oQPy02M6tFApBruEhAz8DGgaLtDY6MLtyZAt3SjXnUCgYEA1zLgamdTHOqrrmIi
+eIQBnAJiyIfcY8B9SX1OsLGYFCHiPVwgUY35B2c7MavMsGcExJhtE+uxU7o5djtM
+R6r9cRHOXJ6EQwa8OwzzPqbM17/YqNDeK39bc9WOFUqRWrhDhVMPy6z8rmZr73mG
+IUC7mBNx/1GBdVYXIlsXzC96dI8CgYEA0kUAhz6I5nyPa70NDEUYHLHf3IW1BCmE
+UoVbraSePJtIEY/IqFx7oDuFo30d4n5z+8ICCtyid1h/Cp3mf3akOiqltYUfgV1G
+JgcEjKKYWEnO7cfFyO7LB7Y3GYYDJNy6EzVWPiwTGk9ZTfFJEESmHC45Unxgd17m
+Dx/R58rFgWMCgYBQXQWFdtSI5fH7C1bIHrPjKNju/h2FeurOuObcAVZDnmu4cmD3
+U8d9xkVKxVeJQM99A1coq0nrdI3k4zwXP3mp8fZYjDHkPe2pN6rW6L9yiohEcsuk
+/siON1/5/4DMmidM8LnjW9R45HLGWWGHpX7oyco2iJ+Jy/6Tq+T1MX3PbQKBgQCm
+hdsbQJ0u3CrBSmFQ/E9SOlRt0r4+45pVuCOY6yweF2QF9HcXTtbhWQJHLclDHJ5C
+Ha18aKuKFN3XzKFFBPKe1jOSBDGlQ/dQGnKx5fr8wMdObM3oiaTlIJuWbRmEUgJT
+QARjDIi8Z2b0YUhZx+Q9oSXoe3PyVYehJrQX+/BavQKBgQCIr7Zp0rQPbfqcTL+M
+OYHUoNcb14f9f8hXeXHQOqVpsGwxGdRQAU9wbx/4+obKB5xIkzBsVNcJwavisNja
+hegnGjTB/9Hc4m+5bMGwH0bhS2eQO4o+YYM2ypDmFQqDLRfFUlZ5PVHffm/aA9+g
+GanNBCsmtoHtV6CJ1UZ7NmBuIA==
+-----END PRIVATE KEY-----
diff --git a/lib/crypto/test/engine_SUITE_data/pkcs8/rsa_private_key_pwd.pem b/lib/crypto/test/engine_SUITE_data/pkcs8/rsa_private_key_pwd.pem
new file mode 100644
index 0000000000..501662fc35
--- /dev/null
+++ b/lib/crypto/test/engine_SUITE_data/pkcs8/rsa_private_key_pwd.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIh888Iq6gxuMCAggA
+MBQGCCqGSIb3DQMHBAic/11YZ8Nt5gSCBMjG/Jb4qiMoBS50iQvHXqcETPE+0NBr
+jhsn9w94LkdRBstMPAsoKmY98Er96Rnde/NfmqlU9CupKTkd7Ce5poBf72Y6KMED
+cPURyjbGRFsu6x9skXB2obhyKYEqAEF2oQAg4Qbe5v1qXBIgDuC/NgiJnM+w2zCZ
+LkHSZB2/NmcnvDzcgPF7TM8pTO23xCJ33m37qjfWvHsgocVqZmL9wQ4+wr/NMYjJ
+pJvX1OHW1vBsZsXh40WchalYRSB1VeO368QfsE8coRJztqbMzdce9EQdMB6Q6jlO
+cetd3moLIoMP4I7HW0/SgokbycTbRiYSvRyU1TGc2WbW6BrFZV24IckcnnVUFatf
+6HKUcaYLG68dJcRgs5QMGkcmgVvlddENHFmHZlo0eym/xSiUl/AT8/5odscm6ML8
+wW5sneax+TF4J2eYmiN7yjAUCodXVTNYNDVKo6uUhntlymbM0o4UitVIbPIfTDHl
+sxJAEZ7vpuPqeNMxUk6G6zipuEjqsVbnuFSBSZmgKiGYcifRPUmqqINa3DdS4WVx
+xaPWdHbHVRD//ze3h/FsA+1lIE5q2kUE0xXseJA1ISog++kJp14XeaaL2j/tx3Ob
+OsbcaOAD/IUw/ItDt9kn0qzfnar7sS0Wov8AmJQxHmH7Lm93jHTLM05yE0AR/eBr
+Mig2ZdC+9OqVC+GPuBkRjSs8NpltQIDroz6EV9IMwPwXm0szSYoyoPLmlHJUdnLs
+ZUef+au6hYkEJBrvuisagnq5eT/fCV3hsjD7yODebNU2CmBTo6X2PRx/xsBHRMWl
+QkoM9PBdSCnKv6HpHl4pchuoqU2NpFjN0BCaad6aHfZSTnqgzK4bEh1oO6dI8/rB
+/eh71JyFFG5J4xbpaqz5Su01V1iwU5leK5bDwqals4M4+ZGHGciou7qnXUmX2fJl
+r6DlMUa/xy+A2ZG0NuZR05yk2oB3+KVNMgp6zFty3XaxwoNtc8GTLtLnBnIh2rlP
+mE1+I65LRWwrNQalPeOAUrYuEzhyp2Df7a8Ykas5PUH7MGR/S0Ge/dLxtE2bJuK4
+znbLAsGhvo/SbNxYqIp6D4iDtd3va6yUGncy41paA/vTKFVvXZDrXcwJQYYCVOGT
+OwdzNuozU8Dc7oxsd8oakfC46kvmVaOrGvZbm56PFfprcaL/Hslska5xxEni/eZe
+WRxZbCBhAVqS1pn5zkDQVUe9uFlR/x39Qi01HIlKLBsjpSs6qQsFArMe8hgXmXLG
+xP+dyVuOE18NzSewdEjeqSRKIM7Qi8EOjZsI4HdSRBY7bh9VhmaVXDZiCSf33TTE
+3y8nimzQAeuGoYg6WqHmWWC2Qnpki2HlaIH/ayXEyQWkP/qvg61e8ovdg9Fy8JOO
+0AacXVt5zj0q00AW5bKx7usi4NIjZedi86hUm6H19aBm7r86BKjwYTEI/GOcdrbV
+9HC/8ayOimgwiAG3gq+aLioWym+Z6KnsbVd7XReVbvM/InQx54WA2y5im0A+/c67
+oQFFPV84XGX9waeqv/K4Wzkm6HW+qVAEM67482VGOf0PVrlQMno6dOotT/Y7ljoZ
+2iz0LmN9yylJnLPDrr1i6gzbs5OhhUgbF5LI2YP2wWdCZTl/DrKSIvQZWl8U+tw3
+ciA=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/lib/crypto/test/engine_SUITE_data/pkcs8/rsa_public_key.pem b/lib/crypto/test/engine_SUITE_data/pkcs8/rsa_public_key.pem
new file mode 100644
index 0000000000..d3fb5a2cc9
--- /dev/null
+++ b/lib/crypto/test/engine_SUITE_data/pkcs8/rsa_public_key.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsMG9P3XVxl0xSuBS8V3V
+emv1iTEqDz0ueUb2SABxbIk7bzy2yfC8Q7GesElWSzdP1EOMHVp/Y37co1OfyMQV
+RvFzrSopkzL5t/2Ts1S7nhhwW6y2LHEb/aC/ObpUyh1oK2Q7tJQV+SSUyL+VEwhK
+8yUUG5GvQxtRmgYA29T5V35MwVjMH7AWZsKAu+yrwnCBgoG1v1wmNN0z9t04PHa7
+6QcjErXXT9hUOH2fdahVMz7vLoWRLKkkExZZoYBhMe3S5ZMtMb7utkbgA0U6SDaX
+FmbVgx03bLDqruudy8MKgWPJQaKQmf+AH/EEd2WJEIXp9WCxG1YXl0bsyC0gmSIi
+TQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/lib/crypto/test/engine_SUITE_data/pkcs8/rsa_public_key_pwd.pem b/lib/crypto/test/engine_SUITE_data/pkcs8/rsa_public_key_pwd.pem
new file mode 100644
index 0000000000..f74361cead
--- /dev/null
+++ b/lib/crypto/test/engine_SUITE_data/pkcs8/rsa_public_key_pwd.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxquo1Na8C+kjeW0YESGm
+vE1bgNW9xh+SQjU1fv/97ePK8mQW2zO1h/vUNz23pfZAKjQu3rlFW/VgGJQ0LgCs
+8Gr/HbMwNcCJzuFMePUrnWn/qBeR7OKUZCJ3E1pp4kwsTdGDDO7jPtNzKf0bdKlg
+G2GHfZWhUediRX8NsRg12X1odVPuRGVRsyJ952YODk9PFjK7pro7Ynf3Icx7di9d
+PXL5vEcKSRdomXvt1rgM8XVHES94RQqoz60ZhfV2JnPfa9V8qu0KaGntpEr7p4rQ
+5BSiLFPjPOArjsD5tKyo8ldKCdQjLfisEp7AetfMjLPVVPw9o/SmCjDxsYWTVRQ2
+tQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk
index 796e3b6d84..64d593f64a 100644
--- a/lib/crypto/vsn.mk
+++ b/lib/crypto/vsn.mk
@@ -1 +1 @@
-CRYPTO_VSN = 4.0
+CRYPTO_VSN = 4.3.3
diff --git a/lib/debugger/doc/src/Makefile b/lib/debugger/doc/src/Makefile
index 0f724b6f17..56d6085e9c 100644
--- a/lib/debugger/doc/src/Makefile
+++ b/lib/debugger/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@ XML_APPLICATION_FILES = ref_man.xml
XML_REF3_FILES = debugger.xml i.xml int.xml
XML_PART_FILES = part.xml
-XML_CHAPTER_FILES = debugger_chapter.xml notes.xml
+XML_CHAPTER_FILES = introduction.xml debugger_chapter.xml notes.xml
BOOK_FILES = book.xml
@@ -99,6 +99,7 @@ gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/debugger/doc/src/fascicules.xml b/lib/debugger/doc/src/fascicules.xml
deleted file mode 100644
index 154c8a3b6d..0000000000
--- a/lib/debugger/doc/src/fascicules.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
-</fascicules>
-
diff --git a/lib/debugger/doc/src/notes.xml b/lib/debugger/doc/src/notes.xml
index fa85567a84..395b69973d 100644
--- a/lib/debugger/doc/src/notes.xml
+++ b/lib/debugger/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,6 +33,66 @@
<p>This document describes the changes made to the Debugger
application.</p>
+<section><title>Debugger 4.2.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Debugger 4.2.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug where calling a fun inside a binary would
+ crash the Debugger. </p>
+ <p>
+ Own Id: OTP-14957 Aux Id: PR-1741 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Debugger 4.2.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Do not quote variables and button names in Debugger
+ windows. The bug was introduced in Erlang/OTP 20.1. </p>
+ <p>
+ Own Id: OTP-14802</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Debugger 4.2.3</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Tools are updated to show Unicode atoms correctly.</p>
+ <p>
+ Own Id: OTP-14464</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Debugger 4.2.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/debugger/src/dbg_debugged.erl b/lib/debugger/src/dbg_debugged.erl
index e142af4ae0..5296b8d892 100644
--- a/lib/debugger/src/dbg_debugged.erl
+++ b/lib/debugger/src/dbg_debugged.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,32 +31,25 @@
%% Called via the error handler.
%%--------------------------------------------------------------------
eval(Mod, Func, Args) ->
- SaveStacktrace = erlang:get_stacktrace(),
Meta = dbg_ieval:eval(Mod, Func, Args),
Mref = erlang:monitor(process, Meta),
- msg_loop(Meta, Mref, SaveStacktrace).
+ msg_loop(Meta, Mref).
%%====================================================================
%% Internal functions
%%====================================================================
-msg_loop(Meta, Mref, SaveStacktrace) ->
+msg_loop(Meta, Mref) ->
receive
%% Evaluated function has returned a value
{sys, Meta, {ready, Val}} ->
erlang:demonitor(Mref, [flush]),
-
- %% Restore original stacktrace and return the value
- try erlang:raise(throw, stack, SaveStacktrace)
- catch
- throw:stack ->
- case Val of
- {dbg_apply,M,F,A} ->
- apply(M, F, A);
- _ ->
- Val
- end
+ case Val of
+ {dbg_apply,M,F,A} ->
+ apply(M, F, A);
+ _ ->
+ Val
end;
%% Evaluated function raised an (uncaught) exception
@@ -74,32 +67,25 @@ msg_loop(Meta, Mref, SaveStacktrace) ->
Meta ! {self(), rec_acked},
ok
end,
- msg_loop(Meta, Mref, SaveStacktrace);
+ msg_loop(Meta, Mref);
%% Meta needs something evaluated within context of real process
{sys, Meta, {command,Command}} ->
Reply = handle_command(Command),
Meta ! {sys, self(), Reply},
- msg_loop(Meta, Mref, SaveStacktrace);
+ msg_loop(Meta, Mref);
%% Meta has terminated
%% Must be due to int:stop() (or -heaven forbid- a debugger bug)
{'DOWN', Mref, _, _, Reason} ->
-
- %% Restore original stacktrace and return a dummy value
- try erlang:raise(throw, stack, SaveStacktrace)
- catch
- throw:stack ->
- {interpreter_terminated, Reason}
- end
+ {interpreter_terminated, Reason}
end.
handle_command(Command) ->
try
reply(Command)
- catch Class:Reason ->
- Stacktrace = stacktrace_f(erlang:get_stacktrace()),
- {exception,{Class,Reason,Stacktrace}}
+ catch Class:Reason:Stacktrace ->
+ {exception,{Class,Reason,stacktrace_f(Stacktrace)}}
end.
reply({apply,M,F,As}) ->
diff --git a/lib/debugger/src/dbg_icmd.erl b/lib/debugger/src/dbg_icmd.erl
index 4cd3dce670..ac901c5469 100644
--- a/lib/debugger/src/dbg_icmd.erl
+++ b/lib/debugger/src/dbg_icmd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -467,7 +467,7 @@ mark_break(Cm, LineNo, Le) ->
parse_cmd(Cmd, LineNo) ->
{ok,Tokens,_} = erl_scan:string(Cmd, LineNo, [text]),
- {ok,Forms,Bs} = lib:extended_parse_exprs(Tokens),
+ {ok,Forms,Bs} = erl_eval:extended_parse_exprs(Tokens),
{Forms, Bs}.
%%====================================================================
diff --git a/lib/debugger/src/dbg_ieval.erl b/lib/debugger/src/dbg_ieval.erl
index 88c7caacb0..b6703d5d9e 100644
--- a/lib/debugger/src/dbg_ieval.erl
+++ b/lib/debugger/src/dbg_ieval.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -353,15 +353,15 @@ format_trace(What, Args, P) ->
{Called, {Le,Li,M,F,As}} = Args,
case Called of
extern ->
- io_lib:format("++ (~w) <~w> ~w:~w~ts~n",
+ io_lib:format("++ (~w) <~w> ~w:~tw~ts~n",
[Le,Li,M,F,format_args(As, P)]);
local ->
- io_lib:format("++ (~w) <~w> ~w~ts~n",
+ io_lib:format("++ (~w) <~w> ~tw~ts~n",
[Le,Li,F,format_args(As, P)])
end;
call_fun ->
{Le,Li,F,As} = Args,
- io_lib:format("++ (~w) <~w> ~w~ts~n",
+ io_lib:format("++ (~w) <~w> ~tw~ts~n",
[Le, Li, F, format_args(As, P)]);
return ->
{Le,Val} = Args,
@@ -370,7 +370,7 @@ format_trace(What, Args, P) ->
bif ->
{Le,Li,M,F,As} = Args,
- io_lib:format("++ (~w) <~w> ~w:~w~ts~n",
+ io_lib:format("++ (~w) <~w> ~w:~tw~ts~n",
[Le, Li, M, F, format_args(As, P)])
end.
@@ -924,8 +924,7 @@ expr({dbg,Line,raise,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
trace(return, {Le,Error}),
{value,Error,Bs}
catch
- _:_ ->
- Stk = erlang:get_stacktrace(), %Possibly truncated.
+ _:_:Stk -> %Possibly truncated.
StkFun = fun(_) -> Stk end,
do_exception(Class, Reason, StkFun, Bs, Ieval)
end;
@@ -1034,7 +1033,7 @@ expr({send,Line,To0,Msg0}, Bs0, Ieval0) ->
%% Binary
expr({bin,Line,Fs}, Bs0, Ieval0) ->
- Ieval = Ieval0#ieval{line=Line},
+ Ieval = Ieval0#ieval{line=Line,top=false},
try
eval_bits:expr_grp(Fs, Bs0,
fun (E, B) -> expr(E, B, Ieval) end,
diff --git a/lib/debugger/src/dbg_wx_break_win.erl b/lib/debugger/src/dbg_wx_break_win.erl
index 770681510d..10e9272254 100644
--- a/lib/debugger/src/dbg_wx_break_win.erl
+++ b/lib/debugger/src/dbg_wx_break_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -159,7 +159,7 @@ create_win(Parent, Pos, Type, Mod, Line) ->
%%--------------------------------------------------------------------
update_functions(WinInfo, Funcs) ->
Items = lists:map(fun([N, A]) ->
- lists:flatten(io_lib:format("~p/~p", [N,A]))
+ lists:flatten(io_lib:format("~tw/~w", [N,A]))
end,
Funcs),
wxListBox:set(WinInfo#winInfo.listbox, Items),
diff --git a/lib/debugger/src/dbg_wx_mon.erl b/lib/debugger/src/dbg_wx_mon.erl
index a32a6894b8..08b20d3f69 100644
--- a/lib/debugger/src/dbg_wx_mon.erl
+++ b/lib/debugger/src/dbg_wx_mon.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -119,9 +119,9 @@ init(CallingPid, Mode, SFile) ->
init2(CallingPid, Mode, SFile, GS)
catch
exit:stop -> stop;
- Error:Reason ->
+ Error:Reason:Stacktrace ->
io:format("~p: Crashed {~p,~p} in~n ~p",
- [?MODULE, Error, Reason, erlang:get_stacktrace()])
+ [?MODULE, Error, Reason, Stacktrace])
end
end.
diff --git a/lib/debugger/src/dbg_wx_mon_win.erl b/lib/debugger/src/dbg_wx_mon_win.erl
index 9737c9e67f..fcd954454b 100644
--- a/lib/debugger/src/dbg_wx_mon_win.erl
+++ b/lib/debugger/src/dbg_wx_mon_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -342,7 +342,7 @@ add_process(WinInfo, Pid, Name, {Mod,Func,Args}, Status, Info) ->
Row = (WinInfo#winInfo.row),
Name2 = case Name of undefined -> ""; _ -> to_string(Name) end,
- FuncS = to_string("~w:~w/~w", [Mod, Func, length(Args)]),
+ FuncS = to_string("~w:~tw/~w", [Mod, Func, length(Args)]),
Info2 = case Info of {} -> ""; _ -> to_string(Info) end,
Pid2 = to_string("~p",[Pid]),
diff --git a/lib/debugger/src/dbg_wx_trace.erl b/lib/debugger/src/dbg_wx_trace.erl
index f4ee30618c..25f32ca7e7 100644
--- a/lib/debugger/src/dbg_wx_trace.erl
+++ b/lib/debugger/src/dbg_wx_trace.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -95,9 +95,9 @@ start(Pid, Env, Parent, TraceWin, BackTrace, Strings) ->
catch
_:stop ->
exit(stop);
- E:R ->
+ E:R:S ->
io:format("TraceWin Crashed ~p~n",[E]),
- io:format(" ~p in ~p~n",[R, erlang:get_stacktrace()]),
+ io:format(" ~p in ~p~n",[R, S]),
exit(R)
end;
error ->
@@ -345,11 +345,12 @@ gui_cmd('Back Trace', State) ->
P = p(State),
lists:foreach(
fun({Le, {Mod,Func,Args}}) ->
- Str = io_lib:format("~p > ~p:~p"++P++"~n",
- [Le, Mod, Func, Args]),
+ Str = io_lib:format("~p > ~w:~tw~ts\n",
+ [Le, Mod, Func, format_args(Args, P)]),
dbg_wx_trace_win:trace_output(State#state.win,Str);
({Le, {Fun,Args}}) ->
- Str = io_lib:format("~p > ~p"++P++"~n", [Le, Fun, Args]),
+ Str = io_lib:format("~p > ~p~ts~n",
+ [Le, Fun, format_args(Args, P)]),
dbg_wx_trace_win:trace_output(State#state.win,Str);
(_) -> ignore
end,
@@ -517,8 +518,8 @@ gui_cmd({user_command, Cmd}, State) ->
gui_cmd({edit, {Var, Value}}, State) ->
Window = dbg_wx_trace_win:get_window(State#state.win),
Val = case State#state.strings of
- [] -> dbg_wx_win:to_string("~999999lp",[Value]);
- [str_on] -> dbg_wx_win:to_string("~999999tp",[Value])
+ [] -> dbg_wx_win:to_string("~0lp",[Value]);
+ [str_on] -> dbg_wx_win:to_string("~0tp",[Value])
end,
case dbg_wx_win:entry(Window, "Edit variable", Var, {term, Val}) of
cancel ->
@@ -539,6 +540,18 @@ add_break(WI, Coords, Type, Mod, Line) ->
Win = dbg_wx_trace_win:get_window(WI),
dbg_wx_break:start(Win, Coords, Type, Mod, Line).
+format_args(As, P) when is_list(As) ->
+ [$(,format_args1(As, P),$)];
+format_args(A, P) ->
+ [$/,io_lib:format(P, [A])].
+
+format_args1([A], P) ->
+ [io_lib:format(P, [A])];
+format_args1([A|As], P) ->
+ [io_lib:format(P, [A]),$,|format_args1(As, P)];
+format_args1([], _) ->
+ [].
+
%%--Commands from the interpreter-------------------------------------
int_cmd({interpret, Mod}, State) ->
diff --git a/lib/debugger/src/dbg_wx_win.erl b/lib/debugger/src/dbg_wx_win.erl
index f1298154ab..4391ad1598 100644
--- a/lib/debugger/src/dbg_wx_win.erl
+++ b/lib/debugger/src/dbg_wx_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -275,7 +275,7 @@ entry(Parent, Title, Prompt, {Type, Value}) ->
verify(Type, Str) ->
case erl_scan:string(Str, 1, [text]) of
{ok, Tokens, _EndLine} when Type==term ->
- case lib:extended_parse_term(Tokens++[{dot, erl_anno:new(1)}]) of
+ case erl_eval:extended_parse_term(Tokens++[{dot, erl_anno:new(1)}]) of
{ok, Value} -> {edit, Value};
_Error ->
ignore
diff --git a/lib/debugger/src/debugger.app.src b/lib/debugger/src/debugger.app.src
index 446f2b9882..c8a8b0fd43 100644
--- a/lib/debugger/src/debugger.app.src
+++ b/lib/debugger/src/debugger.app.src
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -48,5 +48,5 @@
]},
{registered, [dbg_iserver, dbg_wx_mon, dbg_wx_winman]},
{applications, [kernel, stdlib]},
- {runtime_dependencies, ["wx-1.2","stdlib-2.5","kernel-3.0","erts-6.0",
+ {runtime_dependencies, ["wx-1.2","stdlib-3.4","kernel-5.3","erts-9.0",
"compiler-5.0"]}]}.
diff --git a/lib/debugger/src/i.erl b/lib/debugger/src/i.erl
index 2da3e77618..853fa529a0 100644
--- a/lib/debugger/src/i.erl
+++ b/lib/debugger/src/i.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@
-import(lists, [sort/1,foreach/2]).
iv() ->
- Vsn = string:substr(filename:basename(code:lib_dir(debugger)), 10),
+ Vsn = string:slice(filename:basename(code:lib_dir(debugger)), 9),
list_to_atom(Vsn).
%% -------------------------------------------
@@ -307,13 +307,13 @@ ip() ->
ip([{Pid,{M,F,A},Status,{}}|Stats]) ->
hformat(io_lib:format("~w",[Pid]),
- io_lib:format("~p:~p/~p",[M,F,length(A)]),
+ io_lib:format("~w:~tw/~w",[M,F,length(A)]),
io_lib:format("~w",[Status]),
""),
ip(Stats);
ip([{Pid,{M,F,A},Status,Info}|Stats]) ->
hformat(io_lib:format("~w",[Pid]),
- io_lib:format("~p:~p/~p",[M,F,length(A)]),
+ io_lib:format("~w:~tw/~w",[M,F,length(A)]),
io_lib:format("~w",[Status]),
io_lib:format("~w",[Info])),
ip(Stats);
@@ -321,7 +321,7 @@ ip([]) ->
ok.
hformat(A1, A2, A3, A4) ->
- format("~-12s ~-21s ~-9s ~-21s~n", [A1,A2,A3,A4]).
+ format("~-12s ~-21ts ~-9s ~-21s~n", [A1,A2,A3,A4]).
%% -------------------------------------------
diff --git a/lib/debugger/test/guard_SUITE.erl b/lib/debugger/test/guard_SUITE.erl
index f7874f79df..02a1bbd66b 100644
--- a/lib/debugger/test/guard_SUITE.erl
+++ b/lib/debugger/test/guard_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -390,7 +390,7 @@ all_types() ->
{atom, xxxx},
{ref, make_ref()},
{pid, self()},
- {port, open_port({spawn, efile}, [])},
+ {port, make_port()},
{function, fun(X) -> X+1, "" end},
{binary, list_to_binary([])}].
@@ -435,6 +435,9 @@ type_test(binary, X) when binary(X) ->
type_test(function, X) when function(X) ->
function.
+make_port() ->
+ hd(erlang:ports()).
+
const_guard(Config) when is_list(Config) ->
if
(0 == 0) and ((0 == 0) or (0 == 0)) ->
diff --git a/lib/debugger/test/int_eval_SUITE.erl b/lib/debugger/test/int_eval_SUITE.erl
index 27ca4852b5..0542e45142 100644
--- a/lib/debugger/test/int_eval_SUITE.erl
+++ b/lib/debugger/test/int_eval_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,8 @@
bifs_outside_erlang/1, spawning/1, applying/1,
catch_and_throw/1, external_call/1, test_module_info/1,
apply_interpreted_fun/1, apply_uninterpreted_fun/1,
- interpreted_exit/1, otp_8310/1, stacktrace/1, maps/1]).
+ interpreted_exit/1, otp_8310/1, stacktrace/1, maps/1,
+ call_inside_binary/1]).
%% Helpers.
-export([applier/3]).
@@ -45,7 +46,8 @@ all() ->
[bifs_outside_erlang, spawning, applying,
catch_and_throw, external_call, test_module_info,
apply_interpreted_fun, apply_uninterpreted_fun,
- interpreted_exit, otp_8310, stacktrace, maps].
+ interpreted_exit, otp_8310, stacktrace, maps,
+ call_inside_binary].
groups() ->
[].
@@ -275,6 +277,9 @@ maps(Config) when is_list(Config) ->
[#{hello := 0, price := 0}] = spawn_eval(fun () -> ?IM:update_in_fun() end),
ok.
+call_inside_binary(Config) when is_list(Config) ->
+ <<"1">> = ?IM:call_inside_binary(fun erlang:integer_to_binary/1),
+ ok.
do_eval(Config, Mod) ->
DataDir = proplists:get_value(data_dir, Config),
diff --git a/lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl b/lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl
index ca7929c10b..aa26a44686 100644
--- a/lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl
+++ b/lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@
-export([f/1, f_try/1, f_catch/1]).
-export([otp_5837/1, otp_8310/0]).
-export([empty_map_update/1, update_in_fun/0]).
+-export([call_inside_binary/1]).
%% Internal exports.
-export([echo/2,my_subtract/2,catch_a_ball/0,throw_a_ball/0]).
@@ -248,3 +249,6 @@ empty_map_update(Map) -> Map#{}.
update_in_fun() ->
lists:map(fun (X) -> X#{price := 0} end, [#{hello => 0, price => nil}]).
+
+call_inside_binary(Fun) ->
+ <<(Fun(1))/binary>>.
diff --git a/lib/debugger/vsn.mk b/lib/debugger/vsn.mk
index 3534570ef5..a3cbb497f8 100644
--- a/lib/debugger/vsn.mk
+++ b/lib/debugger/vsn.mk
@@ -1 +1 @@
-DEBUGGER_VSN = 4.2.2
+DEBUGGER_VSN = 4.2.6
diff --git a/lib/dialyzer/doc/src/Makefile b/lib/dialyzer/doc/src/Makefile
index 8fe6cd30eb..3ce777392b 100644
--- a/lib/dialyzer/doc/src/Makefile
+++ b/lib/dialyzer/doc/src/Makefile
@@ -9,11 +9,11 @@
# 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.
-#
+#
# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
# AB. All Rights Reserved.''
-#
+#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
@@ -36,7 +36,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
XML_APPLICATION_FILES = ref_man.xml
XML_REF3_FILES = dialyzer.xml typer.xml
-XML_PART_FILES = part.xml part_notes.xml
+XML_PART_FILES = part.xml
XML_CHAPTER_FILES = dialyzer_chapter.xml notes.xml
BOOK_FILES = book.xml
@@ -65,9 +65,9 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
+XML_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -85,19 +85,20 @@ html: gifs $(HTML_REF_MAN_FILE)
man: $(MAN3_FILES)
-gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
+gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-debug opt:
+debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
+ rm -f errs core *~
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
diff --git a/lib/dialyzer/doc/src/fascicules.xml b/lib/dialyzer/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/dialyzer/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/dialyzer/doc/src/note.gif b/lib/dialyzer/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/dialyzer/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml
index 0d2cb6c4df..3cf776e566 100644
--- a/lib/dialyzer/doc/src/notes.xml
+++ b/lib/dialyzer/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2006</year><year>2017</year>
+ <year>2006</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,173 @@
<p>This document describes the changes made to the Dialyzer
application.</p>
+<section><title>Dialyzer 3.3.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Optimize Dialyzer's handling of left-associative use
+ of <c>andalso</c> and <c>orelse</c> in guards. </p>
+ <p>
+ Own Id: OTP-15268 Aux Id: ERL-680 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Dialyzer 3.3</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Changed the default behaviour of <c>.erlang</c>
+ loading: <c>.erlang</c> is no longer loaded from the
+ current directory. <c>c:erlangrc(PathList)</c> can be
+ used to search and load an <c>.erlang</c> file from user
+ specified directories.</p> <p><c>escript</c>,
+ <c>erlc</c>, <c>dialyzer</c> and <c>typer</c> no longer
+ load an <c>.erlang</c> at all.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-14439</p>
+ </item>
+ <item>
+ <p> Dialyzer can no longer read BEAM files created with
+ OTP 19 or earlier. </p>
+ <p>
+ Own Id: OTP-14493 Aux Id: PR-1434 </p>
+ </item>
+ <item>
+ <p> Speed up the computation of MD5 sums. </p>
+ <p>
+ Own Id: OTP-14937 Aux Id: PR-1719 </p>
+ </item>
+ <item>
+ <p> Fix a situation where Dialyzer unnecessarily
+ discarded contract information, resulting in missed
+ warnings. </p>
+ <p>
+ Own Id: OTP-14970 Aux Id: PR-1722 </p>
+ </item>
+ <item>
+ <p> The (not recommended) option <c>-Woverspecs</c> is
+ somewhat refined, and generates warnings in a few more
+ cases. </p>
+ <p>
+ Own Id: OTP-14982 Aux Id: OTP-14970, PR-1722 </p>
+ </item>
+ <item>
+ <p> Do not emit warnings for fun expressions residing in
+ code that cannot be run. This is consistent with how
+ Dialyzer treats other code that cannot be run. </p>
+ <p>
+ Own Id: OTP-15079 Aux Id: ERL-593 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Dialyzer 3.2.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix bugs concerning <c>erlang:abs/1</c> and
+ <c>erlang:bsl/2</c>. </p>
+ <p>
+ Own Id: OTP-14858 Aux Id: ERL-551 </p>
+ </item>
+ <item>
+ <p> Fix a bug that caused Dialyzer to crash instead of
+ emitting a warning. </p>
+ <p>
+ Own Id: OTP-14911</p>
+ </item>
+ <item>
+ <p> Fix a bug concerning parameterized opaque types. </p>
+ <p>
+ Own Id: OTP-14925 Aux Id: ERL-565 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Dialyzer 3.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> The error message returned from Dialyzer when, for
+ example, a modified record field type is not a subtype of
+ the declared type, no longer includes a call stack. The
+ bug was introduced in Erlang/OTP 19.3. </p>
+ <p>
+ Own Id: OTP-14742</p>
+ </item>
+ <item>
+ <p> A bug relating to maps and never returning functions
+ has been fixed. </p>
+ <p>
+ Own Id: OTP-14743</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Dialyzer 3.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug regarding map types that caused Dialyzer to
+ go into an infinite loop. A consequence of the fix is
+ that compound map keys such as maps and tuples sometimes
+ are handled with less precision than before. </p>
+ <p>
+ Own Id: OTP-14572 Aux Id: seq13319 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ General Unicode improvements.</p>
+ <p>
+ Own Id: OTP-14462</p>
+ </item>
+ <item>
+ <p> The check for unknown remote types is improved. </p>
+ <p>
+ Own Id: OTP-14606 Aux Id: OTP-14218 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Dialyzer 3.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug where merging PLT:s could lose info. The
+ bug was introduced in Erlang/OTP 20.0. </p>
+ <p>
+ Own Id: OTP-14558 Aux Id: ERIERL-53 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Dialyzer 3.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/dialyzer/doc/src/part_notes.xml b/lib/dialyzer/doc/src/part_notes.xml
deleted file mode 100644
index 4a0a0af2d1..0000000000
--- a/lib/dialyzer/doc/src/part_notes.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2006</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Dialyzer Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- <file>part_notes.xml</file>
- </header>
- <description>
- <p><em>Dialyzer</em> is a static analysis tool that identifies software discrepancies such as type errors, unreachable code, unnecessary tests, etc in single Erlang modules or entire (sets of) applications.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/dialyzer/doc/src/warning.gif b/lib/dialyzer/doc/src/warning.gif
deleted file mode 100644
index 96af52360e..0000000000
--- a/lib/dialyzer/doc/src/warning.gif
+++ /dev/null
Binary files differ
diff --git a/lib/dialyzer/src/dialyzer.app.src b/lib/dialyzer/src/dialyzer.app.src
index 5f803875b0..e3a0fc967d 100644
--- a/lib/dialyzer/src/dialyzer.app.src
+++ b/lib/dialyzer/src/dialyzer.app.src
@@ -48,6 +48,6 @@
{registered, []},
{applications, [compiler, hipe, kernel, stdlib, wx]},
{env, []},
- {runtime_dependencies, ["wx-1.2","syntax_tools-2.0","stdlib-3.0",
- "kernel-5.0","hipe-3.15.4","erts-8.0",
+ {runtime_dependencies, ["wx-1.2","syntax_tools-2.0","stdlib-3.4",
+ "kernel-5.3","hipe-3.16.1","erts-9.0",
"compiler-7.0"]}]}.
diff --git a/lib/dialyzer/src/dialyzer.erl b/lib/dialyzer/src/dialyzer.erl
index c319acb2fb..185c8c9ae6 100644
--- a/lib/dialyzer/src/dialyzer.erl
+++ b/lib/dialyzer/src/dialyzer.erl
@@ -409,6 +409,10 @@ message_to_string({extra_range, [M, F, A, ExtraRanges, SigRange]}) ->
io_lib:format("The specification for ~w:~tw/~w states that the function"
" might also return ~ts but the inferred return is ~ts\n",
[M, F, A, ExtraRanges, SigRange]);
+message_to_string({missing_range, [M, F, A, ExtraRanges, ContrRange]}) ->
+ io_lib:format("The success typing for ~w:~tw/~w implies that the function"
+ " might also return ~ts but the specification return is ~ts\n",
+ [M, F, A, ExtraRanges, ContrRange]);
message_to_string({overlapping_contract, [M, F, A]}) ->
io_lib:format("Overloaded contract for ~w:~tw/~w has overlapping domains;"
" such contracts are currently unsupported and are simply ignored\n",
@@ -498,24 +502,24 @@ call_or_apply_to_string(ArgNs, FailReason, SigArgs, SigRet,
true ->
%% We do not know which argument(s) caused the failure
io_lib:format("will never return since the success typing arguments"
- " are ~s\n", [SigArgs]);
+ " are ~ts\n", [SigArgs]);
false ->
io_lib:format("will never return since it differs in the ~s argument"
- " from the success typing arguments: ~s\n",
+ " from the success typing arguments: ~ts\n",
[PositionString, SigArgs])
end;
only_contract ->
case (ArgNs =:= []) orelse IsOverloaded of
true ->
%% We do not know which arguments caused the failure
- io_lib:format("breaks the contract ~s\n", [Contract]);
+ io_lib:format("breaks the contract ~ts\n", [Contract]);
false ->
- io_lib:format("breaks the contract ~s in the ~s argument\n",
+ io_lib:format("breaks the contract ~ts in the ~s argument\n",
[Contract, PositionString])
end;
both ->
- io_lib:format("will never return since the success typing is ~s -> ~s"
- " and the contract is ~s\n", [SigArgs, SigRet, Contract])
+ io_lib:format("will never return since the success typing is ~ts -> ~ts"
+ " and the contract is ~ts\n", [SigArgs, SigRet, Contract])
end.
form_positions(ArgNs) ->
@@ -533,9 +537,9 @@ form_positions(ArgNs) ->
form_expected_without_opaque([{N, T, TStr}]) ->
case erl_types:t_is_opaque(T) of
true ->
- io_lib:format("an opaque term of type ~s as ", [TStr]);
+ io_lib:format("an opaque term of type ~ts as ", [TStr]);
false ->
- io_lib:format("a term of type ~s (with opaque subterms) as ", [TStr])
+ io_lib:format("a term of type ~ts (with opaque subterms) as ", [TStr])
end ++ form_position_string([N]) ++ " argument";
form_expected_without_opaque(ExpectedTriples) -> %% TODO: can do much better here
{ArgNs, _Ts, _TStrs} = lists:unzip3(ExpectedTriples),
@@ -546,8 +550,8 @@ form_expected(ExpectedArgs) ->
[T] ->
TS = erl_types:t_to_string(T),
case erl_types:t_is_opaque(T) of
- true -> io_lib:format("an opaque term of type ~s is expected", [TS]);
- false -> io_lib:format("a structured term of type ~s is expected", [TS])
+ true -> io_lib:format("an opaque term of type ~ts is expected", [TS]);
+ false -> io_lib:format("a structured term of type ~ts is expected", [TS])
end;
[_,_|_] -> "terms of different types are expected in these positions"
end.
diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
index a4b42c9367..9993c68fed 100644
--- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
+++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
@@ -165,7 +165,11 @@ analysis_start(Parent, Analysis, LegalWarnings) ->
remote_type_postprocessing(TmpCServer, Args) ->
Fun = fun() ->
- exit(remote_type_postproc(TmpCServer, Args))
+ exit(try remote_type_postproc(TmpCServer, Args) of
+ R -> R
+ catch
+ throw:{error,_}=Error -> Error
+ end)
end,
{Pid, Ref} = erlang:spawn_monitor(Fun),
dialyzer_codeserver:give_away(TmpCServer, Pid),
diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl
index 0617be6435..1e06d6e974 100644
--- a/lib/dialyzer/src/dialyzer_cl.erl
+++ b/lib/dialyzer/src/dialyzer_cl.erl
@@ -672,7 +672,7 @@ failed_anal_msg(Reason, LogCache) ->
%%
format_log_cache(LogCache) ->
Str = lists:append(lists:reverse(LogCache)),
- string:join(string:tokens(Str, "\n"), "\n ").
+ lists:join("\n ", string:lexemes(Str, "\n")).
-spec store_warnings(#cl_state{}, [raw_warning()]) -> #cl_state{}.
diff --git a/lib/dialyzer/src/dialyzer_cl_parse.erl b/lib/dialyzer/src/dialyzer_cl_parse.erl
index a456d38e64..f21eaed087 100644
--- a/lib/dialyzer/src/dialyzer_cl_parse.erl
+++ b/lib/dialyzer/src/dialyzer_cl_parse.erl
@@ -41,8 +41,8 @@ start() ->
Ret
catch
throw:{dialyzer_cl_parse_error, Msg} -> {error, Msg};
- _:R ->
- Msg = io_lib:format("~tp\n~tp\n", [R, erlang:get_stacktrace()]),
+ _:R:S ->
+ Msg = io_lib:format("~tp\n~tp\n", [R, S]),
{error, lists:flatten(Msg)}
end.
@@ -82,7 +82,7 @@ cl(["--get_warnings"|T]) ->
cl(["-D"|_]) ->
cl_error("No defines specified after -D");
cl(["-D"++Define|T]) ->
- Def = re:split(Define, "=", [{return, list}]),
+ Def = re:split(Define, "=", [{return, list}, unicode]),
append_defines(Def),
cl(T);
cl(["-h"|_]) ->
diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl
index b554ebc2cc..af7f4385ad 100644
--- a/lib/dialyzer/src/dialyzer_contracts.erl
+++ b/lib/dialyzer/src/dialyzer_contracts.erl
@@ -197,6 +197,12 @@ check_contracts(Contracts, Callgraph, FunTypes, ModOpaques) ->
false ->
[{MFA, Contract}|NewContracts]
end;
+ {range_warnings, _} ->
+ %% do not treat extra range, either in contract or
+ %% in success typing, as an error in this check
+ %% since that prevents discovering other actual
+ %% errors
+ [{MFA, Contract}|NewContracts];
{error, _Error} -> NewContracts
end;
error -> NewContracts
@@ -206,14 +212,26 @@ check_contracts(Contracts, Callgraph, FunTypes, ModOpaques) ->
end,
orddict:from_list(lists:foldl(FoldFun, [], orddict:to_list(FunTypes))).
+-type check_contract_return() ::
+ 'ok'
+ | {'error',
+ 'invalid_contract'
+ | {'opaque_mismatch', erl_types:erl_type()}
+ | {'overlapping_contract', [module() | atom() | byte()]}
+ | string()}
+ | {'range_warnings',
+ [{'error', {'extra_range' | 'missing_range',
+ erl_types:erl_type(),
+ erl_types:erl_type()}}]}.
+
%% Checks all components of a contract
--spec check_contract(#contract{}, erl_types:erl_type()) -> 'ok' | {'error', term()}.
+-spec check_contract(#contract{}, erl_types:erl_type()) -> check_contract_return().
check_contract(Contract, SuccType) ->
check_contract(Contract, SuccType, 'universe').
-spec check_contract(#contract{}, erl_types:erl_type(), erl_types:opaques()) ->
- 'ok' | {'error', term()}.
+ check_contract_return().
check_contract(#contract{contracts = Contracts}, SuccType, Opaques) ->
try
@@ -286,15 +304,23 @@ check_contract_inf_list([], _SuccType, _Opaques, OM) ->
check_extraneous([], _SuccType) -> ok;
check_extraneous([C|Cs], SuccType) ->
case check_extraneous_1(C, SuccType) of
- ok -> check_extraneous(Cs, SuccType);
- Error -> Error
+ {error, invalid_contract} = Error ->
+ Error;
+ {error, {extra_range, _, _}} = Error ->
+ {range_warnings, [Error | check_missing(C, SuccType)]};
+ ok ->
+ case check_missing(C, SuccType) of
+ [] -> check_extraneous(Cs, SuccType);
+ ErrorL -> {range_warnings, ErrorL}
+ end
end.
check_extraneous_1(Contract, SuccType) ->
CRng = erl_types:t_fun_range(Contract),
CRngs = erl_types:t_elements(CRng),
STRng = erl_types:t_fun_range(SuccType),
- ?debug("CR = ~tp\nSR = ~tp\n", [CRngs, STRng]),
+ ?debug("\nCR = ~ts\nSR = ~ts\n", [erl_types:t_to_string(CRng),
+ erl_types:t_to_string(STRng)]),
case [CR || CR <- CRngs,
erl_types:t_is_none(erl_types:t_inf(CR, STRng))] of
[] ->
@@ -337,6 +363,18 @@ map_part(Type) ->
is_empty_map(Type) ->
erl_types:t_is_equal(Type, erl_types:t_from_term(#{})).
+check_missing(Contract, SuccType) ->
+ CRng = erl_types:t_fun_range(Contract),
+ STRng = erl_types:t_fun_range(SuccType),
+ STRngs = erl_types:t_elements(STRng),
+ ?debug("\nCR = ~ts\nSR = ~ts\n", [erl_types:t_to_string(CRng),
+ erl_types:t_to_string(STRng)]),
+ case [STR || STR <- STRngs,
+ erl_types:t_is_none(erl_types:t_inf(STR, CRng))] of
+ [] -> [];
+ STRs -> [{error, {missing_range, erl_types:t_sup(STRs), CRng}}]
+ end.
+
%% This is the heart of the "range function"
-spec process_contracts([contract_pair()], [erl_types:erl_type()]) ->
erl_types:erl_type().
@@ -555,6 +593,9 @@ from_form_with_check(Form, ExpTypes, MFA, RecordTable, VarTable, Cache) ->
Site = {spec, MFA},
C1 = erl_types:t_check_record_fields(Form, ExpTypes, Site, RecordTable,
VarTable, Cache),
+ %% The check costs some time, and with the assumption that contracts
+ %% are not very deep, it does not add anything.
+ %% erl_types:t_from_form_check_remote(Form, ExpTypes, MFA, RecordTable),
erl_types:t_from_form(Form, ExpTypes, Site, RecordTable, VarTable, C1).
constraints_to_dict(Constrs, MFA, RecDict, ExpTypes, RecordTable,
@@ -705,22 +746,30 @@ get_invalid_contract_warnings_funs([{MFA, {FileLine, Contract, _Xtra}}|Left],
[W|Acc];
{error, {overlapping_contract, []}} ->
[overlapping_contract_warning(MFA, WarningInfo)|Acc];
- {error, {extra_range, ExtraRanges, STRange}} ->
- Warn =
- case t_from_forms_without_remote(Contract#contract.forms,
- MFA, RecDict) of
- {ok, NoRemoteType} ->
- CRet = erl_types:t_fun_range(NoRemoteType),
- erl_types:t_is_subtype(ExtraRanges, CRet);
- unsupported ->
- true
- end,
- case Warn of
- true ->
- [extra_range_warning(MFA, WarningInfo, ExtraRanges, STRange)|Acc];
- false ->
- Acc
- end;
+ {range_warnings, Errors} ->
+ Fun =
+ fun({error, {extra_range, ExtraRanges, STRange}}, Acc0) ->
+ Warn =
+ case t_from_forms_without_remote(Contract#contract.forms,
+ MFA, RecDict) of
+ {ok, NoRemoteType} ->
+ CRet = erl_types:t_fun_range(NoRemoteType),
+ erl_types:t_is_subtype(ExtraRanges, CRet);
+ unsupported ->
+ true
+ end,
+ case Warn of
+ true ->
+ [extra_range_warning(MFA, WarningInfo,
+ ExtraRanges, STRange)|Acc0];
+ false ->
+ Acc0
+ end;
+ ({error, {missing_range, ExtraRanges, CRange}}, Acc0) ->
+ [missing_range_warning(MFA, WarningInfo,
+ ExtraRanges, CRange)|Acc0]
+ end,
+ lists:foldl(Fun, Acc, Errors);
{error, Msg} ->
[{?WARN_CONTRACT_SYNTAX, WarningInfo, Msg}|Acc];
ok ->
@@ -738,6 +787,9 @@ get_invalid_contract_warnings_funs([{MFA, {FileLine, Contract, _Xtra}}|Left],
{error, _} ->
[invalid_contract_warning(MFA, WarningInfo, BifSig, RecDict)
|Acc];
+ {range_warnings, _} ->
+ picky_contract_check(CSig, BifSig, MFA, WarningInfo,
+ Contract, RecDict, Acc);
ok ->
picky_contract_check(CSig, BifSig, MFA, WarningInfo,
Contract, RecDict, Acc)
@@ -771,6 +823,12 @@ extra_range_warning({M, F, A}, WarningInfo, ExtraRanges, STRange) ->
{?WARN_CONTRACT_SUPERTYPE, WarningInfo,
{extra_range, [M, F, A, ERangesStr, STRangeStr]}}.
+missing_range_warning({M, F, A}, WarningInfo, ExtraRanges, CRange) ->
+ ERangesStr = erl_types:t_to_string(ExtraRanges),
+ CRangeStr = erl_types:t_to_string(CRange),
+ {?WARN_CONTRACT_SUBTYPE, WarningInfo,
+ {missing_range, [M, F, A, ERangesStr, CRangeStr]}}.
+
picky_contract_check(CSig0, Sig0, MFA, WarningInfo, Contract, RecDict, Acc) ->
CSig = erl_types:t_abstract_records(CSig0, RecDict),
Sig = erl_types:t_abstract_records(Sig0, RecDict),
@@ -840,7 +898,7 @@ is_remote_types_related(Contract, CSig, Sig, MFA, RecDict) ->
t_from_forms_without_remote([{FType, []}], MFA, RecDict) ->
Site = {spec, MFA},
- {Type1, _} = erl_types:t_from_form_without_remote(FType, Site, RecDict),
+ Type1 = erl_types:t_from_form_without_remote(FType, Site, RecDict),
{ok, erl_types:subst_all_vars_to_any(Type1)};
t_from_forms_without_remote([{_FType, _Constrs}], _MFA, _RecDict) ->
%% 'When' constraints
diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl
index 8367432ac5..45b4abb253 100644
--- a/lib/dialyzer/src/dialyzer_dataflow.erl
+++ b/lib/dialyzer/src/dialyzer_dataflow.erl
@@ -102,6 +102,8 @@
| 'undefined', % race
fun_homes :: dict:dict(label(), mfa())
| 'undefined', % race
+ reachable_funs :: sets:set(label())
+ | 'undefined', % race
plt :: dialyzer_plt:plt()
| 'undefined', % race
opaques :: [type()]
@@ -269,9 +271,11 @@ traverse(Tree, Map, State) ->
case state__warning_mode(State) of
true -> {State, Map, Type};
false ->
- State2 = state__add_work(get_label(Tree), State),
+ FunLbl = get_label(Tree),
+ State2 = state__add_work(FunLbl, State),
State3 = state__update_fun_env(Tree, Map, State2),
- {State3, Map, Type}
+ State4 = state__add_reachable(FunLbl, State3),
+ {State4, Map, Type}
end;
'let' ->
handle_let(Tree, Map, State);
@@ -299,6 +303,7 @@ traverse(Tree, Map, State) ->
match_fail -> t_none();
raise -> t_none();
bs_init_writable -> t_from_term(<<>>);
+ build_stacktrace -> erl_bif_types:type(erlang, build_stacktrace, 0);
Other -> erlang:error({'Unsupported primop', Other})
end,
{State, Map, Type};
@@ -1235,6 +1240,13 @@ handle_tuple(Tree, Map, State) ->
State2 = state__add_warning(State1, ?WARN_OPAQUE,
Tree, Msg),
{State2, Map1, t_none()};
+ {error, record, ErrorPat, ErrorType, _} ->
+ Msg = {record_match,
+ [format_patterns(ErrorPat),
+ format_type(ErrorType, State1)]},
+ State2 = state__add_warning(State1, ?WARN_MATCHING,
+ Tree, Msg),
+ {State2, Map1, t_none()};
{Map2, ETypes} ->
{State1, Map2, t_tuple(ETypes)}
end
@@ -3031,25 +3043,35 @@ state__new(Callgraph, Codeserver, Tree, Plt, Module, Records) ->
{TreeMap, FunHomes} = build_tree_map(Tree, Callgraph),
Funs = dict:fetch_keys(TreeMap),
FunTab = init_fun_tab(Funs, dict:new(), TreeMap, Callgraph, Plt),
- ExportedFuns =
- [Fun || Fun <- Funs--[top], dialyzer_callgraph:is_escaping(Fun, Callgraph)],
- Work = init_work(ExportedFuns),
+ ExportedFunctions =
+ [Fun ||
+ Fun <- Funs--[top],
+ dialyzer_callgraph:is_escaping(Fun, Callgraph),
+ dialyzer_callgraph:lookup_name(Fun, Callgraph) =/= error
+ ],
+ Work = init_work(ExportedFunctions),
Env = lists:foldl(fun(Fun, Env) -> dict:store(Fun, map__new(), Env) end,
dict:new(), Funs),
#state{callgraph = Callgraph, codeserver = Codeserver,
envs = Env, fun_tab = FunTab, fun_homes = FunHomes, opaques = Opaques,
plt = Plt, races = dialyzer_races:new(), records = Records,
warning_mode = false, warnings = [], work = Work, tree_map = TreeMap,
- module = Module}.
+ module = Module, reachable_funs = sets:new()}.
state__warning_mode(#state{warning_mode = WM}) ->
WM.
state__set_warning_mode(#state{tree_map = TreeMap, fun_tab = FunTab,
- races = Races} = State) ->
+ races = Races, callgraph = Callgraph,
+ reachable_funs = ReachableFuns} = State) ->
?debug("==========\nStarting warning pass\n==========\n", []),
Funs = dict:fetch_keys(TreeMap),
- State#state{work = init_work([top|Funs--[top]]),
+ Work =
+ [Fun ||
+ Fun <- Funs--[top],
+ dialyzer_callgraph:lookup_name(Fun, Callgraph) =/= error orelse
+ sets:is_element(Fun, ReachableFuns)],
+ State#state{work = init_work(Work),
fun_tab = FunTab, warning_mode = true,
races = dialyzer_races:put_race_analysis(true, Races)}.
@@ -3116,7 +3138,10 @@ state__add_warning(#state{warnings = Warnings, warning_mode = true} = State,
state__remove_added_warnings(OldState, NewState) ->
#state{warnings = OldWarnings} = OldState,
#state{warnings = NewWarnings} = NewState,
- {NewWarnings -- OldWarnings, NewState#state{warnings = OldWarnings}}.
+ case NewWarnings =:= OldWarnings of
+ true -> {[], NewState};
+ false -> {NewWarnings -- OldWarnings, NewState#state{warnings = OldWarnings}}
+ end.
state__add_warnings(Warns, #state{warnings = Warnings} = State) ->
State#state{warnings = Warns ++ Warnings}.
@@ -3138,7 +3163,8 @@ state__get_race_warnings(#state{races = Races} = State) ->
State1#state{races = Races1}.
state__get_warnings(#state{tree_map = TreeMap, fun_tab = FunTab,
- callgraph = Callgraph, plt = Plt} = State) ->
+ callgraph = Callgraph, plt = Plt,
+ reachable_funs = ReachableFuns} = State) ->
FoldFun =
fun({top, _}, AccState) -> AccState;
({FunLbl, Fun}, AccState) ->
@@ -3173,7 +3199,12 @@ state__get_warnings(#state{tree_map = TreeMap, fun_tab = FunTab,
GenRet = dialyzer_contracts:get_contract_return(C),
not t_is_unit(GenRet)
end,
- case Warn of
+ %% Do not output warnings for unreachable funs.
+ case
+ Warn andalso
+ (dialyzer_callgraph:lookup_name(FunLbl, Callgraph) =/= error
+ orelse sets:is_element(FunLbl, ReachableFuns))
+ of
true ->
case classify_returns(Fun) of
no_match ->
@@ -3244,6 +3275,10 @@ state__get_args_and_status(Tree, #state{fun_tab = FunTab}) ->
{ok, {ArgTypes, _}} -> {ArgTypes, true}
end.
+state__add_reachable(FunLbl, #state{reachable_funs = ReachableFuns}=State) ->
+ NewReachableFuns = sets:add_element(FunLbl, ReachableFuns),
+ State#state{reachable_funs = NewReachableFuns}.
+
build_tree_map(Tree, Callgraph) ->
Fun =
fun(T, {Dict, Homes, FunLbls} = Acc) ->
@@ -3433,19 +3468,19 @@ state__fun_info(Fun, #state{callgraph = CG, fun_tab = FunTab, plt = PLT}) ->
{Fun, Sig, Contract, LocalRet}.
forward_args(Fun, ArgTypes, #state{work = Work, fun_tab = FunTab} = State) ->
- {OldArgTypes, OldOut, Fixpoint} =
+ {NewArgTypes, OldOut, Fixpoint} =
case dict:find(Fun, FunTab) of
- {ok, {not_handled, {OldArgTypes0, OldOut0}}} ->
- {OldArgTypes0, OldOut0, false};
+ {ok, {not_handled, {_OldArgTypesAreNone, OldOut0}}} ->
+ {ArgTypes, OldOut0, false};
{ok, {OldArgTypes0, OldOut0}} ->
- {OldArgTypes0, OldOut0,
- t_is_subtype(t_product(ArgTypes), t_product(OldArgTypes0))}
+ NewArgTypes0 = [t_sup(X, Y) ||
+ {X, Y} <- lists:zip(ArgTypes, OldArgTypes0)],
+ {NewArgTypes0, OldOut0,
+ t_is_equal(t_product(NewArgTypes0), t_product(OldArgTypes0))}
end,
case Fixpoint of
true -> State;
false ->
- NewArgTypes = [t_sup(X, Y) ||
- {X, Y} <- lists:zip(ArgTypes, OldArgTypes)],
NewWork = add_work(Fun, Work),
?debug("~tw: forwarding args ~ts\n",
[state__lookup_name(Fun, State),
diff --git a/lib/dialyzer/src/dialyzer_gui_wx.erl b/lib/dialyzer/src/dialyzer_gui_wx.erl
index 538327d4d1..b8414b7d8b 100644
--- a/lib/dialyzer/src/dialyzer_gui_wx.erl
+++ b/lib/dialyzer/src/dialyzer_gui_wx.erl
@@ -475,7 +475,7 @@ gui_loop(#gui_state{backend_pid = BackendPid, doc_plt = DocPlt,
gui_loop(State);
{BackendPid, ext_types, ExtTypes} ->
Map = fun({M,F,A}) -> io_lib:format("~tp:~tp/~p",[M,F,A]) end,
- ExtTypeString = string:join(lists:map(Map, ExtTypes), "\n"),
+ ExtTypeString = lists:join("\n", lists:map(Map, ExtTypes)),
Msg = io_lib:format("The following remote types are being used "
"but information about them is not available.\n"
"The analysis might get more precise by including "
@@ -638,7 +638,7 @@ output_sms(#gui_state{frame = Frame}, Title, Message, Type) ->
free_editor(#gui_state{gui = Wx, frame = Frame}, Title, Contents0) ->
Contents = lists:flatten(Contents0),
- Tokens = string:tokens(Contents, "\n"),
+ Tokens = string:lexemes(Contents, "\n"),
NofLines = length(Tokens),
LongestLine = lists:max([length(X) || X <- Tokens]),
Height0 = NofLines * 25 + 80,
@@ -1093,7 +1093,7 @@ macro_loop(Options, Win, Box, MacroText, TermText, Frame) ->
Fun =
fun(X) ->
Val = wxControlWithItems:getString(Box,X),
- [MacroName|_] = re:split(Val, " ", [{return, list}]),
+ [MacroName|_] = re:split(Val, " ", [{return, list}, unicode]),
list_to_atom(MacroName)
end,
Delete = [Fun(X) || X <- List],
diff --git a/lib/dialyzer/src/dialyzer_plt.erl b/lib/dialyzer/src/dialyzer_plt.erl
index 47994fc35b..2af4534396 100644
--- a/lib/dialyzer/src/dialyzer_plt.erl
+++ b/lib/dialyzer/src/dialyzer_plt.erl
@@ -531,17 +531,19 @@ compute_md5_from_files(Files) ->
lists:keysort(1, [{F, compute_md5_from_file(F)} || F <- Files]).
compute_md5_from_file(File) ->
- case filelib:is_regular(File) of
- false ->
+ case beam_lib:all_chunks(File) of
+ {ok, _, Chunks} ->
+ %% We cannot use beam_lib:md5 because it does not consider
+ %% the debug_info chunk, where typespecs are likely stored.
+ %% So we consider almost all chunks except the useless ones.
+ Filtered = [[ID, Chunk] || {ID, Chunk} <- Chunks, ID =/= "CInf", ID =/= "Docs"],
+ erlang:md5(lists:sort(Filtered));
+ {error, beam_lib, {file_error, _, enoent}} ->
Msg = io_lib:format("Not a regular file: ~ts\n", [File]),
throw({dialyzer_error, Msg});
- true ->
- case dialyzer_utils:get_core_from_beam(File) of
- {error, Error} ->
- throw({dialyzer_error, Error});
- {ok, Core} ->
- erlang:md5(term_to_binary(Core))
- end
+ {error, beam_lib, _} ->
+ Msg = io_lib:format("Could not compute MD5 for .beam: ~ts\n", [File]),
+ throw({dialyzer_error, Msg})
end.
init_diff_list(RemoveFiles, AddFiles) ->
@@ -775,8 +777,13 @@ merge_tables(T1, T2) ->
tab_merge(ets:first(T1), T1, T2).
tab_merge('$end_of_table', T1, T2) ->
- true = ets:delete(T1),
- T2;
+ case ets:first(T1) of % no safe_fixtable()...
+ '$end_of_table' ->
+ true = ets:delete(T1),
+ T2;
+ Key ->
+ tab_merge(Key, T1, T2)
+ end;
tab_merge(K1, T1, T2) ->
Vs = ets:lookup(T1, K1),
NextK1 = ets:next(T1, K1),
diff --git a/lib/dialyzer/src/dialyzer_races.erl b/lib/dialyzer/src/dialyzer_races.erl
index 7fe64c3e11..7602faa21d 100644
--- a/lib/dialyzer/src/dialyzer_races.erl
+++ b/lib/dialyzer/src/dialyzer_races.erl
@@ -1270,8 +1270,8 @@ filter_named_tables(NamesList) ->
[] -> [];
[Head|Tail] ->
NewHead =
- case string:rstr(Head, "()") of
- 0 -> [Head];
+ case string:find(Head, "()", trailing) of
+ nomatch -> [Head];
_Other -> []
end,
NewHead ++ filter_named_tables(Tail)
@@ -1558,8 +1558,8 @@ any_args(StrList) ->
case StrList of
[] -> false;
[Head|Tail] ->
- case string:rstr(Head, "()") of
- 0 -> any_args(Tail);
+ case string:find(Head, "()", trailing) of
+ nomatch -> any_args(Tail);
_Other -> true
end
end.
@@ -1765,10 +1765,8 @@ ets_list_args(MaybeList) ->
end.
ets_list_argtypes(ListStr) ->
- ListStr1 = string:strip(ListStr, left, $[),
- ListStr2 = string:strip(ListStr1, right, $]),
- ListStr3 = string:strip(ListStr2, right, $.),
- string:strip(ListStr3, right, $,).
+ ListStr1 = string:trim(ListStr, leading, "$["),
+ string:trim(ListStr1, trailing, "$]$.$,").
ets_tuple_args(MaybeTuple) ->
case is_tuple(MaybeTuple) of
@@ -1810,7 +1808,7 @@ ets_tuple_argtypes2_helper(TupleStr, ElemStr, NestingLevel) ->
{[H|ElemStr], NestingLevel, false}
end,
case Return of
- true -> string:tokens(NewElemStr, " |");
+ true -> string:lexemes(NewElemStr, " |");
false ->
ets_tuple_argtypes2_helper(T, NewElemStr, NewNestingLevel)
end
@@ -1889,44 +1887,44 @@ format_args_2(StrArgList, Call) ->
case Call of
whereis ->
lists_key_replace(2, StrArgList,
- string:tokens(lists:nth(2, StrArgList), " |"));
+ string:lexemes(lists:nth(2, StrArgList), " |"));
register ->
lists_key_replace(2, StrArgList,
- string:tokens(lists:nth(2, StrArgList), " |"));
+ string:lexemes(lists:nth(2, StrArgList), " |"));
unregister ->
lists_key_replace(2, StrArgList,
- string:tokens(lists:nth(2, StrArgList), " |"));
+ string:lexemes(lists:nth(2, StrArgList), " |"));
ets_new ->
StrArgList1 = lists_key_replace(2, StrArgList,
- string:tokens(lists:nth(2, StrArgList), " |")),
+ string:lexemes(lists:nth(2, StrArgList), " |")),
lists_key_replace(4, StrArgList1,
- string:tokens(ets_list_argtypes(lists:nth(4, StrArgList1)), " |"));
+ string:lexemes(ets_list_argtypes(lists:nth(4, StrArgList1)), " |"));
ets_lookup ->
StrArgList1 = lists_key_replace(2, StrArgList,
- string:tokens(lists:nth(2, StrArgList), " |")),
+ string:lexemes(lists:nth(2, StrArgList), " |")),
lists_key_replace(4, StrArgList1,
- string:tokens(lists:nth(4, StrArgList1), " |"));
+ string:lexemes(lists:nth(4, StrArgList1), " |"));
ets_insert ->
StrArgList1 = lists_key_replace(2, StrArgList,
- string:tokens(lists:nth(2, StrArgList), " |")),
+ string:lexemes(lists:nth(2, StrArgList), " |")),
lists_key_replace(4, StrArgList1,
ets_tuple_argtypes2(
ets_tuple_argtypes1(lists:nth(4, StrArgList1), [], [], 0),
[]));
mnesia_dirty_read1 ->
lists_key_replace(2, StrArgList,
- [mnesia_tuple_argtypes(T) || T <- string:tokens(
+ [mnesia_tuple_argtypes(T) || T <- string:lexemes(
lists:nth(2, StrArgList), " |")]);
mnesia_dirty_read2 ->
lists_key_replace(2, StrArgList,
- string:tokens(lists:nth(2, StrArgList), " |"));
+ string:lexemes(lists:nth(2, StrArgList), " |"));
mnesia_dirty_write1 ->
lists_key_replace(2, StrArgList,
- [mnesia_record_tab(R) || R <- string:tokens(
+ [mnesia_record_tab(R) || R <- string:lexemes(
lists:nth(2, StrArgList), " |")]);
mnesia_dirty_write2 ->
lists_key_replace(2, StrArgList,
- string:tokens(lists:nth(2, StrArgList), " |"));
+ string:lexemes(lists:nth(2, StrArgList), " |"));
function_call -> StrArgList
end.
@@ -1943,18 +1941,16 @@ format_type(Type, State) ->
erl_types:t_to_string(Type, R).
mnesia_record_tab(RecordStr) ->
- case string:str(RecordStr, "#") =:= 1 of
- true ->
- "'" ++
- string:sub_string(RecordStr, 2, string:str(RecordStr, "{") - 1) ++
- "'";
- false -> RecordStr
+ case erl_scan:string(RecordStr) of
+ {ok, [{'#', _}, {atom, _, Name}|_], _} ->
+ io_lib:write_string(atom_to_list(Name), $');
+ _ -> RecordStr
end.
mnesia_tuple_argtypes(TupleStr) ->
- TupleStr1 = string:strip(TupleStr, left, ${),
- [TupleStr2|_T] = string:tokens(TupleStr1, " ,"),
- lists:flatten(string:tokens(TupleStr2, " |")).
+ TupleStr1 = string:trim(TupleStr, leading, "${"),
+ [TupleStr2|_T] = string:lexemes(TupleStr1, " ,"),
+ lists:flatten(string:lexemes(TupleStr2, " |")).
-spec race_var_map(var_to_map1(), var_to_map2(), dict:dict(), op()) ->
dict:dict().
@@ -2237,7 +2233,7 @@ var_type_analysis(FunDefArgs, FunCallTypes, WarnVarArgs, RaceWarnTag,
case lists_key_member_lists(Vars, FunVarArgs) of
0 -> [Vars, WVA2, WVA3, WVA4];
N when is_integer(N) ->
- NewWVA2 = string:tokens(lists:nth(N + 1, FunVarArgs), " |"),
+ NewWVA2 = string:lexemes(lists:nth(N + 1, FunVarArgs), " |"),
[Vars, NewWVA2, WVA3, WVA4]
end;
?WARN_WHEREIS_UNREGISTER ->
@@ -2246,7 +2242,7 @@ var_type_analysis(FunDefArgs, FunCallTypes, WarnVarArgs, RaceWarnTag,
case lists_key_member_lists(Vars, FunVarArgs) of
0 -> [Vars, WVA2];
N when is_integer(N) ->
- NewWVA2 = string:tokens(lists:nth(N + 1, FunVarArgs), " |"),
+ NewWVA2 = string:lexemes(lists:nth(N + 1, FunVarArgs), " |"),
[Vars, NewWVA2]
end;
?WARN_ETS_LOOKUP_INSERT ->
@@ -2256,7 +2252,7 @@ var_type_analysis(FunDefArgs, FunCallTypes, WarnVarArgs, RaceWarnTag,
case lists_key_member_lists(Vars1, FunVarArgs) of
0 -> [Vars1, WVA2];
N1 when is_integer(N1) ->
- NewWVA2 = string:tokens(lists:nth(N1 + 1, FunVarArgs), " |"),
+ NewWVA2 = string:lexemes(lists:nth(N1 + 1, FunVarArgs), " |"),
[Vars1, NewWVA2]
end,
Vars2 =
@@ -2286,10 +2282,10 @@ var_type_analysis(FunDefArgs, FunCallTypes, WarnVarArgs, RaceWarnTag,
NewWVA2 =
case Arity of
1 ->
- [mnesia_record_tab(R) || R <- string:tokens(
+ [mnesia_record_tab(R) || R <- string:lexemes(
lists:nth(2, FunVarArgs), " |")];
2 ->
- string:tokens(lists:nth(N + 1, FunVarArgs), " |")
+ string:lexemes(lists:nth(N + 1, FunVarArgs), " |")
end,
[Vars, NewWVA2|T]
end
diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl
index c4d8f45447..dede475f98 100644
--- a/lib/dialyzer/src/dialyzer_typesig.erl
+++ b/lib/dialyzer/src/dialyzer_typesig.erl
@@ -41,7 +41,7 @@
t_is_float/1, t_is_fun/1,
t_is_integer/1, t_non_neg_integer/0,
t_is_list/1, t_is_nil/1, t_is_none/1, t_is_number/1,
- t_is_singleton/1,
+ t_is_singleton/1, t_is_none_or_unit/1,
t_limit/2, t_list/0, t_list/1,
t_list_elements/1, t_nonempty_list/1, t_maybe_improper_list/0,
@@ -418,6 +418,11 @@ traverse(Tree, DefinedVars, State) ->
match_fail -> throw(error);
raise -> throw(error);
bs_init_writable -> {State, t_from_term(<<>>)};
+ build_stacktrace ->
+ V = mk_var(Tree),
+ Type = erl_bif_types:type(erlang, build_stacktrace, 0),
+ State1 = state__store_conj(V, sub, Type, State),
+ {State1, V};
Other -> erlang:error({'Unsupported primop', Other})
end;
'receive' ->
@@ -528,13 +533,14 @@ traverse(Tree, DefinedVars, State) ->
false -> t_any();
true ->
MT = t_inf(lookup_type(MapVar, Map), t_map()),
- case t_is_none(MT) of
+ case t_is_none_or_unit(MT) of
true -> t_none();
false ->
DisjointFromKeyType =
fun(ShadowKey) ->
- t_is_none(t_inf(lookup_type(ShadowKey, Map),
- KeyType))
+ ST = t_inf(lookup_type(ShadowKey, Map),
+ KeyType),
+ t_is_none_or_unit(ST)
end,
case lists:all(DisjointFromKeyType, ShadowKeys) of
true -> t_map_get(KeyType, MT);
@@ -567,7 +573,8 @@ traverse(Tree, DefinedVars, State) ->
case cerl:is_literal(OpTree) andalso
cerl:concrete(OpTree) =:= exact of
true ->
- case t_is_none(t_inf(ShadowedKeys, KeyType)) of
+ ST = t_inf(ShadowedKeys, KeyType),
+ case t_is_none_or_unit(ST) of
true ->
t_map_put({KeyType, t_any()}, AccType);
false ->
@@ -1893,9 +1900,8 @@ solver(Solver, SolveFun) ->
?debug("Solver ~w returned unexpected result:\n ~P\n",
[Solver, _R, 60]),
throw(error)
- catch E:R ->
- io:format("Solver ~w failed: ~w:~p\n ~tp\n",
- [Solver, E, R, erlang:get_stacktrace()]),
+ catch E:R:S ->
+ io:format("Solver ~w failed: ~w:~p\n ~tp\n", [Solver, E, R, S]),
throw(error)
end.
diff --git a/lib/dialyzer/src/dialyzer_utils.erl b/lib/dialyzer/src/dialyzer_utils.erl
index 511a6d66bf..abd89034f3 100644
--- a/lib/dialyzer/src/dialyzer_utils.erl
+++ b/lib/dialyzer/src/dialyzer_utils.erl
@@ -120,92 +120,10 @@ get_core_from_beam(File, Opts) ->
{error, " Could not get Core Erlang code for: " ++ File ++ "\n"}
end;
_ ->
- deprecated_get_core_from_beam(File, Opts)
+ {error, " Could not get Core Erlang code for: " ++ File ++ "\n" ++
+ " Recompile with +debug_info or analyze starting from source code"}
end.
-deprecated_get_core_from_beam(File, Opts) ->
- case get_abstract_code_from_beam(File) of
- error ->
- {error, " Could not get abstract code for: " ++ File ++ "\n" ++
- " Recompile with +debug_info or analyze starting from source code"};
- {ok, AbstrCode} ->
- case get_compile_options_from_beam(File) of
- error ->
- {error, " Could not get compile options for: " ++ File ++ "\n" ++
- " Recompile or analyze starting from source code"};
- {ok, CompOpts} ->
- case get_core_from_abstract_code(AbstrCode, Opts ++ CompOpts) of
- error ->
- {error, " Could not get core Erlang code for: " ++ File};
- {ok, _} = Core ->
- Core
- end
- end
- end.
-
-get_abstract_code_from_beam(File) ->
- case beam_lib:chunks(File, [abstract_code]) of
- {ok, {_, List}} ->
- case lists:keyfind(abstract_code, 1, List) of
- {abstract_code, {raw_abstract_v1, Abstr}} -> {ok, Abstr};
- _ -> error
- end;
- _ ->
- %% No or unsuitable abstract code.
- error
- end.
-
-get_compile_options_from_beam(File) ->
- case beam_lib:chunks(File, [compile_info]) of
- {ok, {_, List}} ->
- case lists:keyfind(compile_info, 1, List) of
- {compile_info, CompInfo} -> compile_info_to_options(CompInfo);
- _ -> error
- end;
- _ ->
- %% No or unsuitable compile info.
- error
- end.
-
-compile_info_to_options(CompInfo) ->
- case lists:keyfind(options, 1, CompInfo) of
- {options, CompOpts} -> {ok, CompOpts};
- _ -> error
- end.
-
-get_core_from_abstract_code(AbstrCode, Opts) ->
- %% We do not want the parse_transforms around since we already
- %% performed them. In some cases we end up in trouble when
- %% performing them again.
- AbstrCode1 = cleanup_parse_transforms(AbstrCode),
- %% Remove parse_transforms (and other options) from compile options.
- Opts2 = cleanup_compile_options(Opts),
- try compile:noenv_forms(AbstrCode1, Opts2 ++ src_compiler_opts()) of
- {ok, _, Core} -> {ok, Core};
- _What -> error
- catch
- error:_ -> error
- end.
-
-cleanup_parse_transforms([{attribute, _, compile, {parse_transform, _}}|Left]) ->
- cleanup_parse_transforms(Left);
-cleanup_parse_transforms([Other|Left]) ->
- [Other|cleanup_parse_transforms(Left)];
-cleanup_parse_transforms([]) ->
- [].
-
-cleanup_compile_options(Opts) ->
- lists:filter(fun keep_compile_option/1, Opts).
-
-%% Using abstract, not asm or core.
-keep_compile_option(from_asm) -> false;
-keep_compile_option(from_core) -> false;
-%% The parse transform will already have been applied, may cause
-%% problems if it is re-applied.
-keep_compile_option({parse_transform, _}) -> false;
-keep_compile_option(warnings_as_errors) -> false;
-keep_compile_option(_) -> true.
-
%% ============================================================================
%%
%% Typed Records
@@ -326,9 +244,12 @@ process_record_remote_types(CServer) ->
{record, Name} ->
FieldFun =
fun({Arity, Fields}, C4) ->
- Site = {record, {Module, Name, Arity}},
+ MRA = {Module, Name, Arity},
+ Site = {record, MRA},
{Fields1, C7} =
lists:mapfoldl(fun({FieldName, Field, _}, C5) ->
+ check_remote(Field, ExpTypes,
+ MRA, RecordTable),
{FieldT, C6} =
erl_types:t_from_form
(Field, ExpTypes, Site,
@@ -342,18 +263,12 @@ process_record_remote_types(CServer) ->
{FieldsList, C3} =
lists:mapfoldl(FieldFun, C2, orddict:to_list(Fields)),
{{Key, {FileLine, orddict:from_list(FieldsList)}}, C3};
- {type, Name, NArgs} ->
+ {_TypeOrOpaque, Name, NArgs} ->
%% Make sure warnings about unknown types are output
%% also for types unused by specs.
- Site = {type, {Module, Name, NArgs}},
- L = erl_anno:new(0),
- Args = lists:duplicate(NArgs, {var, L, '_'}),
- UserType = {user_type, L, Name, Args},
- {_NewType, C3} =
- erl_types:t_from_form(UserType, ExpTypes, Site,
- RecordTable, VarTable, C2),
- {{Key, Value}, C3};
- {opaque, _Name, _NArgs} ->
+ MTA = {Module, Name, NArgs},
+ {{_Module, _FileLine, Form, _ArgNames}, _Type} = Value,
+ check_remote(Form, ExpTypes, MTA, RecordTable),
{{Key, Value}, C2}
end
end,
@@ -454,6 +369,9 @@ msg_with_position(Fun, FileLine) ->
throw({error, NewMsg})
end.
+check_remote(Form, ExpTypes, What, RecordTable) ->
+ erl_types:t_from_form_check_remote(Form, ExpTypes, What, RecordTable).
+
-spec merge_types(codeserver(), dialyzer_plt:plt()) -> codeserver().
merge_types(CServer, Plt) ->
diff --git a/lib/dialyzer/src/typer.erl b/lib/dialyzer/src/typer.erl
index bf5484e5f6..4b99f5f72e 100644
--- a/lib/dialyzer/src/typer.erl
+++ b/lib/dialyzer/src/typer.erl
@@ -74,7 +74,8 @@
-spec start() -> no_return().
start() ->
-_ = io:setopts(standard_error, [{encoding,unicode}]),
+ _ = io:setopts(standard_error, [{encoding,unicode}]),
+ _ = io:setopts([{encoding,unicode}]),
{Args, Analysis} = process_cl_args(),
%% io:format("Args: ~p\n", [Args]),
%% io:format("Analysis: ~p\n", [Analysis]),
@@ -163,9 +164,9 @@ get_type_info(#analysis{callgraph = CallGraph,
CodeServer),
Analysis#analysis{callgraph = StrippedCallGraph, trust_plt = NewPlt}
catch
- error:What ->
+ error:What:Stacktrace ->
fatal_error(io_lib:format("Analysis failed with message: ~tp",
- [{What, erlang:get_stacktrace()}]));
+ [{What, Stacktrace}]));
throw:{dialyzer_succ_typing_error, Msg} ->
fatal_error(io_lib:format("Analysis failed with message: ~ts", [Msg]))
end.
@@ -400,7 +401,7 @@ get_type({{M, F, A} = MFA, Range, Arg}, CodeServer, Records) ->
Sig = erl_types:t_fun(Arg, Range),
case dialyzer_contracts:check_contract(Contract, Sig) of
ok -> {{F, A}, {contract, Contract}};
- {error, {extra_range, _, _}} ->
+ {range_warnings, _} ->
{{F, A}, {contract, Contract}};
{error, {overlapping_contract, []}} ->
{{F, A}, {contract, Contract}};
@@ -484,12 +485,12 @@ write_typed_file(File, Info) ->
write_typed_file(File, Info, NewFileName) ->
{ok, Binary} = file:read_file(File),
- Chars = binary_to_list(Binary),
+ Chars = unicode:characters_to_list(Binary),
write_typed_file(Chars, NewFileName, Info, 1, []),
io:format(" Saved as: ~tp\n", [NewFileName]).
write_typed_file(Chars, File, #info{functions = []}, _LNo, _Acc) ->
- ok = file:write_file(File, list_to_binary(Chars), [append]);
+ ok = file:write_file(File, unicode:characters_to_binary(Chars), [append]);
write_typed_file([Ch|Chs] = Chars, File, Info, LineNo, Acc) ->
[{Line,F,A}|RestFuncs] = Info#info.functions,
case Line of
@@ -519,7 +520,7 @@ write_typed_file([Ch|Chs] = Chars, File, Info, LineNo, Acc) ->
raw_write(F, A, Info, File, Content) ->
TypeInfo = get_type_string(F, A, Info, file),
ContentList = lists:reverse(Content) ++ TypeInfo ++ "\n",
- ContentBin = list_to_binary(ContentList),
+ ContentBin = unicode:characters_to_binary(ContentList),
file:write_file(File, ContentBin, [append]).
get_type_string(F, A, Info, Mode) ->
@@ -608,7 +609,7 @@ cl(["-D"++Def|Opts]) ->
case Def of
"" -> fatal_error("no variable name specified after -D");
_ ->
- DefPair = process_def_list(re:split(Def, "=", [{return, list}])),
+ DefPair = process_def_list(re:split(Def, "=", [{return, list}, unicode])),
{{def, DefPair}, Opts}
end;
cl(["-I",Dir|Opts]) -> {{inc, Dir}, Opts};
@@ -697,7 +698,7 @@ get_all_files(#args{files = Fs, files_r = Ds}) ->
test_erl_file_exclude_ann(File) ->
case is_erl_file(File) of
true -> %% Exclude files ending with ".ann.erl"
- case re:run(File, "[\.]ann[\.]erl$") of
+ case re:run(File, "[\.]ann[\.]erl$", [unicode]) of
{match, _} -> false;
nomatch -> true
end;
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args
index 1eb8cd455b..1be0ce0d8c 100644
--- a/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args
+++ b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args
@@ -1,5 +1,5 @@
gen_server_incorrect_args.erl:3: Undefined callback function handle_cast/2 (behaviour gen_server)
gen_server_incorrect_args.erl:3: Undefined callback function init/1 (behaviour gen_server)
-gen_server_incorrect_args.erl:7: The inferred return type of handle_call/3 ({'no'} | {'ok'}) has nothing in common with {'noreply',_} | {'noreply',_,'hibernate' | 'infinity' | non_neg_integer()} | {'reply',_,_} | {'stop',_,_} | {'reply',_,_,'hibernate' | 'infinity' | non_neg_integer()} | {'stop',_,_,_}, which is the expected return type for the callback of the gen_server behaviour
+gen_server_incorrect_args.erl:7: The inferred return type of handle_call/3 ({'no'} | {'ok'}) has nothing in common with {'noreply',_} | {'noreply',_,'hibernate' | 'infinity' | non_neg_integer() | {'continue',_}} | {'reply',_,_} | {'stop',_,_} | {'reply',_,_,'hibernate' | 'infinity' | non_neg_integer() | {'continue',_}} | {'stop',_,_,_}, which is the expected return type for the callback of the gen_server behaviour
gen_server_incorrect_args.erl:7: The inferred type for the 2nd argument of handle_call/3 ('boo' | 'foo') is not a supertype of {pid(),_}, which is expected type for this argument in the callback of the gen_server behaviour
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/proper/proper_typeserver.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/proper/proper_typeserver.erl
index b16075763f..12f6532c0c 100644
--- a/lib/dialyzer/test/behaviour_SUITE_data/src/proper/proper_typeserver.erl
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/proper/proper_typeserver.erl
@@ -539,7 +539,7 @@ apply_spec_test({Mod,Fun,_Arity}=MFA, {_Domain,Range}, SpecTimeout, FalsePositiv
try apply(Mod, Fun, Args) of
X -> {ok, X}
catch
- X:Y -> {X, Y}
+ X:Y:S -> {{X, Y}, S}
end,
case Result of
{ok, Z} ->
@@ -551,15 +551,15 @@ apply_spec_test({Mod,Fun,_Arity}=MFA, {_Domain,Range}, SpecTimeout, FalsePositiv
false ->
false
end;
- Exception when is_function(FalsePositiveMFAs) ->
+ {Exception, S2} when is_function(FalsePositiveMFAs) ->
case FalsePositiveMFAs(MFA, Args, Exception) of
true ->
true;
false ->
- error(Exception, erlang:get_stacktrace())
+ error(Exception, S2)
end;
- Exception ->
- error(Exception, erlang:get_stacktrace())
+ {Exception, S3} ->
+ error(Exception, S3)
end
end).
diff --git a/lib/dialyzer/test/dialyzer_common.erl b/lib/dialyzer/test/dialyzer_common.erl
index 48083a2731..1a8403f486 100644
--- a/lib/dialyzer/test/dialyzer_common.erl
+++ b/lib/dialyzer/test/dialyzer_common.erl
@@ -221,13 +221,9 @@ get_suites(Dir) ->
end.
suffix(String, Suffix) ->
- case string:rstr(String, Suffix) of
- 0 -> no;
- Index ->
- case string:substr(String, Index) =:= Suffix of
- true -> {yes, string:sub_string(String,1,Index-1)};
- false -> no
- end
+ case string:split(String, Suffix, trailing) of
+ [Prefix,[]] -> {yes, Prefix};
+ _ -> no
end.
-spec create_suite(string()) -> 'ok'.
diff --git a/lib/dialyzer/test/map_SUITE_data/results/loop b/lib/dialyzer/test/map_SUITE_data/results/loop
new file mode 100644
index 0000000000..2e956a5709
--- /dev/null
+++ b/lib/dialyzer/test/map_SUITE_data/results/loop
@@ -0,0 +1,4 @@
+
+loop.erl:63: The call loop:start_timer(#loop{state::'idle' | 'waiting',queues::#{'category1'=>#queue{limit::non_neg_integer(),buffer::[any()]}, 'category2'=>#queue{limit::non_neg_integer(),buffer::[any()]}},counters::#{'counter1':=10, 2:=10}}) does not have a term of type #loop{state::'idle' | 'waiting',timer::timer:tref(),queues::#{'category1'=>#queue{limit::non_neg_integer(),buffer::[any()]}, 'category2'=>#queue{limit::non_neg_integer(),buffer::[any()]}},counters::#{'counter1'=>non_neg_integer(), 2=>non_neg_integer()}} (with opaque subterms) as 1st argument
+loop.erl:67: Function wait/1 has no local return
+loop.erl:85: Record construction #loop{state::'idle' | 'waiting',timer::{'error',_} | {'ok',timer:tref()},queues::#{'category1'=>#queue{limit::non_neg_integer(),buffer::[any()]}, 'category2'=>#queue{limit::non_neg_integer(),buffer::[any()]}},counters::#{'counter1'=>non_neg_integer(), 2=>non_neg_integer()}} violates the declared type of field timer::'undefined' | timer:tref()
diff --git a/lib/dialyzer/test/map_SUITE_data/results/map_anon_fun b/lib/dialyzer/test/map_SUITE_data/results/map_anon_fun
new file mode 100644
index 0000000000..cfca5b1407
--- /dev/null
+++ b/lib/dialyzer/test/map_SUITE_data/results/map_anon_fun
@@ -0,0 +1,2 @@
+
+map_anon_fun.erl:4: Function g/1 will never be called
diff --git a/lib/dialyzer/test/map_SUITE_data/results/map_galore b/lib/dialyzer/test/map_SUITE_data/results/map_galore
index c34ba5cf30..9a140de255 100644
--- a/lib/dialyzer/test/map_SUITE_data/results/map_galore
+++ b/lib/dialyzer/test/map_SUITE_data/results/map_galore
@@ -1,11 +1,11 @@
map_galore.erl:1000: A key of type 42 cannot exist in a map of type #{1:='a', 2:='b', 4:='d', 5:='e', float()=>'c' | 'v'}
-map_galore.erl:1080: A key of type 'nonexisting' cannot exist in a map of type #{#{'map':='key', 'one':='small'}:=[32 | 49 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'second':='small'}:=[32 | 50 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'third':='small'}:=[32 | 51 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], 10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 16:='a6', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 26:='b6', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 36:=[54 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]} | #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], 'k16'=>'a6', 'k26'=>'b6', 'k36'=>[54 | 99,...], 16=>'a6', 26=>'b6', 36=>[54 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]}=>[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 100 | 101,...]}=>atom() | [1..255,...]}
-map_galore.erl:1082: A key of type 42 cannot exist in a map of type #{#{'map':='key', 'one':='small'}:=[32 | 49 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'second':='small'}:=[32 | 50 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'third':='small'}:=[32 | 51 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], 10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 16:='a6', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 26:='b6', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 36:=[54 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]} | #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], 'k16'=>'a6', 'k26'=>'b6', 'k36'=>[54 | 99,...], 16=>'a6', 26=>'b6', 36=>[54 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]}=>[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 100 | 101,...]}=>atom() | [1..255,...]}
-map_galore.erl:1140: The call map_galore:map_guard_sequence_1(#{'seq':=6, 'val':=[101,...]}) will never return since it differs in the 1st argument from the success typing arguments: (#{'seq':=1 | 2 | 3 | 4 | 5, 'val':=[97 | 98 | 99 | 100 | 101,...], #{'map':='key', 'one':='small'}=>[32 | 49 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'second':='small'}=>[32 | 50 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'third':='small'}=>[32 | 51 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[any(),...]} | #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 27:='b7', 28:='b8', 29:='b9', 30:=[any(),...], 31:=[any(),...], 32:=[any(),...], 33:=[any(),...], 34:=[any(),...], 35:=[any(),...], 37:=[any(),...], 38:=[any(),...], 39:=[any(),...], 'k16'=>'a6', 'k26'=>'b6', 'k36'=>[any(),...], 16=>'a6', 26=>'b6', 36=>[any(),...], <<_:16>> | [any(),...] | {_}=>[any(),...]}=>atom() | [1..255,...]})
-map_galore.erl:1141: The call map_galore:map_guard_sequence_2(#{'b':=5}) will never return since it differs in the 1st argument from the success typing arguments: (#{'a':='gg' | 'kk' | 'sc' | 3 | 4, 'b'=>'other' | 3 | 4 | 5, 'c'=>'sc2', #{'map':='key', 'one':='small'}=>[32 | 49 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'second':='small'}=>[32 | 50 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'third':='small'}=>[32 | 51 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[any(),...]} | #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 27:='b7', 28:='b8', 29:='b9', 30:=[any(),...], 31:=[any(),...], 32:=[any(),...], 33:=[any(),...], 34:=[any(),...], 35:=[any(),...], 37:=[any(),...], 38:=[any(),...], 39:=[any(),...], 'k16'=>'a6', 'k26'=>'b6', 'k36'=>[any(),...], 16=>'a6', 26=>'b6', 36=>[any(),...], <<_:16>> | [any(),...] | {_}=>[any(),...]}=>atom() | [1..255,...]})
-map_galore.erl:1209: The call map_galore:map_guard_sequence_1(#{'seq':=6, 'val':=[101,...], #{'map':='key', 'one':='small'}:=[32 | 49 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'second':='small'}:=[32 | 50 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'third':='small'}:=[32 | 51 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], 10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 16:='a6', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 26:='b6', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 36:=[54 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | 3,...]} | #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], 'k16'=>'a6', 'k26'=>'b6', 'k36'=>[54 | 99,...], 16=>'a6', 26=>'b6', 36=>[54 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]}=>[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 100 | 101,...]}=>atom() | [1..255,...]}) will never return since it differs in the 1st argument from the success typing arguments: (#{'seq':=1 | 2 | 3 | 4 | 5, 'val':=[97 | 98 | 99 | 100 | 101,...], #{'map':='key', 'one':='small'}=>[32 | 49 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'second':='small'}=>[32 | 50 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'third':='small'}=>[32 | 51 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[any(),...]} | #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 27:='b7', 28:='b8', 29:='b9', 30:=[any(),...], 31:=[any(),...], 32:=[any(),...], 33:=[any(),...], 34:=[any(),...], 35:=[any(),...], 37:=[any(),...], 38:=[any(),...], 39:=[any(),...], 'k16'=>'a6', 'k26'=>'b6', 'k36'=>[any(),...], 16=>'a6', 26=>'b6', 36=>[any(),...], <<_:16>> | [any(),...] | {_}=>[any(),...]}=>atom() | [1..255,...]})
-map_galore.erl:1210: The call map_galore:map_guard_sequence_2(#{'b':=5, #{'map':='key', 'one':='small'}:=[32 | 49 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'second':='small'}:=[32 | 50 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'third':='small'}:=[32 | 51 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], 10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 16:='a6', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 26:='b6', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 36:=[54 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | 3,...]} | #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], 'k16'=>'a6', 'k26'=>'b6', 'k36'=>[54 | 99,...], 16=>'a6', 26=>'b6', 36=>[54 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]}=>[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 100 | 101,...]}=>atom() | [1..255,...]}) will never return since it differs in the 1st argument from the success typing arguments: (#{'a':='gg' | 'kk' | 'sc' | 3 | 4, 'b'=>'other' | 3 | 4 | 5, 'c'=>'sc2', #{'map':='key', 'one':='small'}=>[32 | 49 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'second':='small'}=>[32 | 50 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'third':='small'}=>[32 | 51 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[any(),...]} | #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 27:='b7', 28:='b8', 29:='b9', 30:=[any(),...], 31:=[any(),...], 32:=[any(),...], 33:=[any(),...], 34:=[any(),...], 35:=[any(),...], 37:=[any(),...], 38:=[any(),...], 39:=[any(),...], 'k16'=>'a6', 'k26'=>'b6', 'k36'=>[any(),...], 16=>'a6', 26=>'b6', 36=>[any(),...], <<_:16>> | [any(),...] | {_}=>[any(),...]}=>atom() | [1..255,...]})
+map_galore.erl:1080: A key of type 'nonexisting' cannot exist in a map of type #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 16:='a6', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 26:='b6', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 36:=[54 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]} | #{'k16'=>'a6', 'k26'=>'b6', 'k36'=>[54 | 99,...], 'map'=>'key', 'one'=>'small', 'second'=>'small', 'third'=>'small', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]}=>[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 100 | 101,...]}=>atom() | [1..255,...]}
+map_galore.erl:1082: A key of type 42 cannot exist in a map of type #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 16:='a6', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 26:='b6', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 36:=[54 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]} | #{'k16'=>'a6', 'k26'=>'b6', 'k36'=>[54 | 99,...], 'map'=>'key', 'one'=>'small', 'second'=>'small', 'third'=>'small', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]}=>[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 100 | 101,...]}=>atom() | [1..255,...]}
+map_galore.erl:1140: The call map_galore:map_guard_sequence_1(#{'seq':=6, 'val':=[101,...]}) will never return since it differs in the 1st argument from the success typing arguments: (#{'seq':=1 | 2 | 3 | 4 | 5, 'val':=[97 | 98 | 99 | 100 | 101,...], 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[any(),...]} | #{'k16'=>'a6', 'k26'=>'b6', 'k36'=>[any(),...], 'map'=>'key', 'one'=>'small', 'second'=>'small', 'third'=>'small', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[any(),...], 31=>[any(),...], 32=>[any(),...], 33=>[any(),...], 34=>[any(),...], 35=>[any(),...], 36=>[any(),...], 37=>[any(),...], 38=>[any(),...], 39=>[any(),...], <<_:16>> | [any(),...] | {_}=>[any(),...]}=>atom() | [1..255,...]})
+map_galore.erl:1141: The call map_galore:map_guard_sequence_2(#{'b':=5}) will never return since it differs in the 1st argument from the success typing arguments: (#{'a':='gg' | 'kk' | 'sc' | 3 | 4, 'b'=>'other' | 3 | 4 | 5, 'c'=>'sc2', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[any(),...]} | #{'k16'=>'a6', 'k26'=>'b6', 'k36'=>[any(),...], 'map'=>'key', 'one'=>'small', 'second'=>'small', 'third'=>'small', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[any(),...], 31=>[any(),...], 32=>[any(),...], 33=>[any(),...], 34=>[any(),...], 35=>[any(),...], 36=>[any(),...], 37=>[any(),...], 38=>[any(),...], 39=>[any(),...], <<_:16>> | [any(),...] | {_}=>[any(),...]}=>atom() | [1..255,...]})
+map_galore.erl:1209: The call map_galore:map_guard_sequence_1(#{'seq':=6, 'val':=[101,...], 10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 16:='a6', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 26:='b6', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 36:=[54 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | 3,...]} | #{'k16'=>'a6', 'k26'=>'b6', 'k36'=>[54 | 99,...], 'map'=>'key', 'one'=>'small', 'second'=>'small', 'third'=>'small', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]}=>[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 100 | 101,...]}=>atom() | [1..255,...]}) will never return since it differs in the 1st argument from the success typing arguments: (#{'seq':=1 | 2 | 3 | 4 | 5, 'val':=[97 | 98 | 99 | 100 | 101,...], 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[any(),...]} | #{'k16'=>'a6', 'k26'=>'b6', 'k36'=>[any(),...], 'map'=>'key', 'one'=>'small', 'second'=>'small', 'third'=>'small', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[any(),...], 31=>[any(),...], 32=>[any(),...], 33=>[any(),...], 34=>[any(),...], 35=>[any(),...], 36=>[any(),...], 37=>[any(),...], 38=>[any(),...], 39=>[any(),...], <<_:16>> | [any(),...] | {_}=>[any(),...]}=>atom() | [1..255,...]})
+map_galore.erl:1210: The call map_galore:map_guard_sequence_2(#{'b':=5, 10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 16:='a6', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 26:='b6', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 36:=[54 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | 3,...]} | #{'k16'=>'a6', 'k26'=>'b6', 'k36'=>[54 | 99,...], 'map'=>'key', 'one'=>'small', 'second'=>'small', 'third'=>'small', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]}=>[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 100 | 101,...]}=>atom() | [1..255,...]}) will never return since it differs in the 1st argument from the success typing arguments: (#{'a':='gg' | 'kk' | 'sc' | 3 | 4, 'b'=>'other' | 3 | 4 | 5, 'c'=>'sc2', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[any(),...]} | #{'k16'=>'a6', 'k26'=>'b6', 'k36'=>[any(),...], 'map'=>'key', 'one'=>'small', 'second'=>'small', 'third'=>'small', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[any(),...], 31=>[any(),...], 32=>[any(),...], 33=>[any(),...], 34=>[any(),...], 35=>[any(),...], 36=>[any(),...], 37=>[any(),...], 38=>[any(),...], 39=>[any(),...], <<_:16>> | [any(),...] | {_}=>[any(),...]}=>atom() | [1..255,...]})
map_galore.erl:1418: Fun application with arguments (#{'s':='none', 'v':='none'}) will never return since it differs in the 1st argument from the success typing arguments: (#{'s':='l' | 't' | 'v', 'v':='none' | <<_:16>> | [<<_:16>>,...] | {<<_:16>>,<<_:16>>}})
map_galore.erl:1491: The test #{} =:= #{'a':=1} can never evaluate to 'true'
map_galore.erl:1492: The test #{'a':=1} =:= #{} can never evaluate to 'true'
diff --git a/lib/dialyzer/test/map_SUITE_data/results/opaque_key b/lib/dialyzer/test/map_SUITE_data/results/opaque_key
index 2ae0e0c5c6..8d6379b5e0 100644
--- a/lib/dialyzer/test/map_SUITE_data/results/opaque_key
+++ b/lib/dialyzer/test/map_SUITE_data/results/opaque_key
@@ -1,4 +1,5 @@
+opaque_key_adt.erl:35: Invalid type specification for function opaque_key_adt:s2/0. The success typing is () -> #{3:='a'}
opaque_key_adt.erl:41: Invalid type specification for function opaque_key_adt:s4/0. The success typing is () -> #{1:='a'}
opaque_key_adt.erl:44: Invalid type specification for function opaque_key_adt:s5/0. The success typing is () -> #{2:=3}
opaque_key_adt.erl:56: Invalid type specification for function opaque_key_adt:smt1/0. The success typing is () -> #{3:='a'}
diff --git a/lib/dialyzer/test/map_SUITE_data/src/loop.erl b/lib/dialyzer/test/map_SUITE_data/src/loop.erl
new file mode 100644
index 0000000000..c861052d9f
--- /dev/null
+++ b/lib/dialyzer/test/map_SUITE_data/src/loop.erl
@@ -0,0 +1,92 @@
+-module(loop).
+
+-export([timeout/2]).
+
+-export([idle/2, waiting/2]).
+
+-type request_category() :: category1 | category2.
+
+-type counter() :: counter1 | 2.
+
+-type counters() :: #{counter() => non_neg_integer()}.
+
+-record(queue, {limit = 0 :: non_neg_integer(),
+ buffer = [] :: list()}).
+
+-type request_queues() :: #{request_category() => #queue{}}.
+
+-record(?MODULE,
+ {state = idle :: idle | waiting,
+ timer = undefined :: undefined | timer:tref(),
+ queues = #{category1 => #queue{},
+ category2 => #queue{}} :: request_queues(),
+ counters = new_counters() :: counters()}).
+-spec timeout(Ref, Timer :: timer:tref()) -> {noreply, Ref}.
+timeout(Ref, Timer) ->
+ handle_message(Ref, {timeout, Timer}).
+
+-type message() :: {reset, request_category()}
+ | {timeout, timer:tref()}.
+
+-spec handle_message(Ref, Message :: message()) ->
+ {reply, boolean(), Ref} | {noreply, Ref}.
+handle_message(Ref, Msg) ->
+ MV = #?MODULE{state = State} = get(mv),
+ case apply(?MODULE, State, [Msg, MV]) of
+ {reply, Result, NewMV} ->
+ put(mv, NewMV),
+ {reply, Result, Ref};
+ {noreply, NewMV} ->
+ put(mv, NewMV),
+ {noreply, Ref}
+ end.
+
+-spec idle(Message :: message(), #?MODULE{}) ->
+ {reply, boolean(), #?MODULE{}} | {noreply, #?MODULE{}}.
+idle({reset, Category}, MV = #?MODULE{queues = Queues}) ->
+ case Queues of
+ #{Category := #queue{limit = 0}} ->
+ {reply, false, MV};
+ _ ->
+ wait(MV)
+ end;
+idle(_, MV) ->
+ {noreply, MV}.
+
+-spec waiting(Message :: message(), #?MODULE{}) ->
+ {reply, boolean(), #?MODULE{}} | {noreply, #?MODULE{}}.
+waiting({reset, _Category}, MV = #?MODULE{}) ->
+ NewMV = stop_timer(MV),
+ {noreply, NewMV#?MODULE{state = idle}};
+waiting({timeout, Timer}, #?MODULE{timer = Timer} = MV) ->
+ %% The opaque warning is an effect of the call to timer:send_after().
+ {noreply, start_timer(MV#?MODULE{timer = undefined,
+ counters = new_counters()})}.
+
+-spec wait(#?MODULE{}) -> {noreply, #?MODULE{}}.
+wait(MV) ->
+ {noreply, start_timer(MV#?MODULE{state = waiting})}.
+
+-spec stop_timer(#?MODULE{}) -> #?MODULE{}.
+stop_timer(MV) ->
+ case MV#?MODULE.timer of
+ undefined ->
+ MV;
+ Timer ->
+ timer:cancel(Timer),
+ MV#?MODULE{timer = undefined}
+ end.
+
+-spec start_timer(MV :: #?MODULE{}) -> #?MODULE{}.
+start_timer(MV) ->
+ case MV#?MODULE.timer of
+ undefined ->
+ %% Note: timer:send_after() returns {ok, TRef} | {error, _}.
+ MV#?MODULE{timer = timer:send_after(1000, ?MODULE)};
+ _Timer ->
+ start_timer(stop_timer(MV))
+ end.
+
+-spec new_counters() -> counters().
+new_counters() ->
+ #{counter1 => 10, 2 => 10}.
diff --git a/lib/dialyzer/test/map_SUITE_data/src/map_anon_fun.erl b/lib/dialyzer/test/map_SUITE_data/src/map_anon_fun.erl
new file mode 100644
index 0000000000..e77016d68a
--- /dev/null
+++ b/lib/dialyzer/test/map_SUITE_data/src/map_anon_fun.erl
@@ -0,0 +1,9 @@
+-module(map_anon_fun).
+
+%% Not exported.
+g(A) ->
+ maps:map(fun F(K, {V, _C}) ->
+ F(K, V);
+ F(_K, _V) ->
+ #{ system => {A} }
+ end, #{}).
diff --git a/lib/dialyzer/test/map_SUITE_data/src/opaque_key/opaque_key_adt.erl b/lib/dialyzer/test/map_SUITE_data/src/opaque_key/opaque_key_adt.erl
index b98c713c6b..9228cfa413 100644
--- a/lib/dialyzer/test/map_SUITE_data/src/opaque_key/opaque_key_adt.erl
+++ b/lib/dialyzer/test/map_SUITE_data/src/opaque_key/opaque_key_adt.erl
@@ -33,7 +33,7 @@ s0() -> #{}.
s1() -> #{3 => a}.
-spec s2() -> s(atom() | 3).
-s2() -> #{3 => a}. %% Contract breakage (not found)
+s2() -> #{3 => a}. %% Contract breakage
-spec s3() -> s(atom() | 3).
s3() -> #{3 => 5, a => 6, 7 => 8}.
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/para_bug/same.erl b/lib/dialyzer/test/opaque_SUITE_data/src/para_bug/same.erl
new file mode 100644
index 0000000000..44149f4199
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/para_bug/same.erl
@@ -0,0 +1,15 @@
+-module(same).
+
+-export([baz/1]).
+
+-record(bar, {
+ a :: same_type:st(integer()),
+ b :: same_type:st(atom())
+ }).
+
+baz(Bar) ->
+ _ = wrap_find(0, Bar#bar.a),
+ wrap_find(0, Bar#bar.b).
+
+wrap_find(K, D) ->
+ same_type:t(K, D).
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/para_bug/same_type.erl b/lib/dialyzer/test/opaque_SUITE_data/src/para_bug/same_type.erl
new file mode 100644
index 0000000000..855a5d30be
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/para_bug/same_type.erl
@@ -0,0 +1,13 @@
+-module(same_type).
+
+-export([t/2]).
+
+-export_type([st/1]).
+
+%% When unopaqued all specializations of st/1 are equal.
+-opaque st(_A) :: {st, tuple()}.
+
+-spec t(_, st(_)) -> _.
+
+t(K, V) ->
+ {K, V}.
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl b/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl
index 1677b4efb8..529f9fba72 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/proper/proper_typeserver.erl
@@ -533,7 +533,7 @@ apply_spec_test({Mod,Fun,_Arity}=MFA, {_Domain,Range}, SpecTimeout, FalsePositiv
try apply(Mod,Fun,Args) of
X -> {ok, X}
catch
- X:Y -> {X, Y}
+ X:Y:S -> {{X, Y}, S}
end,
case Result of
{ok, Z} ->
@@ -545,15 +545,15 @@ apply_spec_test({Mod,Fun,_Arity}=MFA, {_Domain,Range}, SpecTimeout, FalsePositiv
false ->
false
end;
- Exception when is_function(FalsePositiveMFAs) ->
+ {Exception, S2} when is_function(FalsePositiveMFAs) ->
case FalsePositiveMFAs(MFA, Args, Exception) of
true ->
true;
false ->
- error(Exception, erlang:get_stacktrace())
+ error(Exception, S2)
end;
- Exception ->
- error(Exception, erlang:get_stacktrace())
+ {Exception, S3} ->
+ error(Exception, S3)
end
end).
diff --git a/lib/dialyzer/test/options1_SUITE_data/results/compiler b/lib/dialyzer/test/options1_SUITE_data/results/compiler
index cbb5115c91..e1dc038800 100644
--- a/lib/dialyzer/test/options1_SUITE_data/results/compiler
+++ b/lib/dialyzer/test/options1_SUITE_data/results/compiler
@@ -28,7 +28,7 @@ cerl_inline.erl:2750: The pattern <{[], L, D}, Vs> can never match the type <[1.
cerl_inline.erl:2752: The pattern <{[], _L, D}, Vs> can never match the type <[1..255,...],[any()]>
cerl_inline.erl:2754: The pattern <{F, L, D}, Vs> can never match the type <[1..255,...],[any()]>
cerl_inline.erl:2756: The pattern <{F, _L, D}, Vs> can never match the type <[1..255,...],[any()]>
-compile.erl:788: The pattern {'error', Es} can never match the type {'ok',<<_:64,_:_*8>>}
+compile.erl:792: The pattern {'error', Es} can never match the type {'ok',<<_:64,_:_*8>>}
core_lint.erl:473: The pattern <{'c_atom', _, 'all'}, 'binary', _Def, St> can never match the type <_,#c_nil{} | {'c_atom' | 'c_char' | 'c_float' | 'c_int' | 'c_string' | 'c_tuple',_,_} | #c_cons{hd::#c_nil{} | {'c_atom' | 'c_char' | 'c_float' | 'c_int' | 'c_string' | 'c_tuple',_,_} | #c_cons{hd::{_,_} | {_,_,_} | {_,_,_,_},tl::{_,_} | {_,_,_} | {_,_,_,_}},tl::#c_nil{} | {'c_atom' | 'c_char' | 'c_float' | 'c_int' | 'c_string' | 'c_tuple',_,_} | #c_cons{hd::{_,_} | {_,_,_} | {_,_,_,_},tl::{_,_} | {_,_,_} | {_,_,_,_}}},[any()],_>
core_lint.erl:505: The pattern <_Req, 'unknown', St> can never match the type <non_neg_integer(),non_neg_integer(),_>
sys_pre_expand.erl:625: Call to missing or unexported function erlang:hash/2
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_validator.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_validator.erl
index 8fe43163f6..ea92613781 100644
--- a/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_validator.erl
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/beam_validator.erl
@@ -174,7 +174,7 @@ validate_error(Error, Name, Ar) ->
-endif.
validate_error_1(Error, Name, Ar) ->
{{'_',Name,Ar},
- {internal_error,'_',{Error,erlang:get_stacktrace()}}}.
+ {internal_error,'_',{Error,[]}}}.
-record(st, %Emulation state
{x=init_regs(0, term), %x register info.
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/compile.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/compile.erl
index 7e5ccde2fd..6838cf6734 100644
--- a/lib/dialyzer/test/options1_SUITE_data/src/compiler/compile.erl
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/compile.erl
@@ -228,11 +228,15 @@ os_process_size() ->
case os:type() of
{unix, sunos} ->
Size = os:cmd("ps -o vsz -p " ++ os:getpid() ++ " | tail -1"),
- list_to_integer(lib:nonl(Size));
+ list_to_integer(nonl(Size));
_ ->
0
end.
+nonl([$\n]) -> [];
+nonl([]) -> [];
+nonl([H|T]) -> [H|nonl(T)].
+
run_tc({Name,Fun}, St) ->
Before0 = statistics(runtime),
Val = (catch Fun(St)),
diff --git a/lib/dialyzer/test/options2_SUITE_data/results/unused_unknown_type b/lib/dialyzer/test/options2_SUITE_data/results/unused_unknown_type
index 110d896c76..74d2ac33ad 100644
--- a/lib/dialyzer/test/options2_SUITE_data/results/unused_unknown_type
+++ b/lib/dialyzer/test/options2_SUITE_data/results/unused_unknown_type
@@ -1,2 +1,2 @@
-:0: Unknown type unknown:type1/0:0: Unknown type unknown:type2/0:0: Unknown type unknown:type3/0 \ No newline at end of file
+:0: Unknown type foo:bar/0:0: Unknown type ofoo:obar/0:0: Unknown type owww:y/0:0: Unknown type rfoo:rbar/0:0: Unknown type unknown:type1/0:0: Unknown type unknown:type2/0:0: Unknown type unknown:type3/0:0: Unknown type xxx:y/0:0: Unknown type yyy:x/0:0: Unknown type zzz:arg/1:0: Unknown type zzz:x/0 \ No newline at end of file
diff --git a/lib/dialyzer/test/options2_SUITE_data/src/unused_unknown_type.erl b/lib/dialyzer/test/options2_SUITE_data/src/unused_unknown_type.erl
index 90df7d528a..e6f9d2392c 100644
--- a/lib/dialyzer/test/options2_SUITE_data/src/unused_unknown_type.erl
+++ b/lib/dialyzer/test/options2_SUITE_data/src/unused_unknown_type.erl
@@ -1,10 +1,40 @@
-module(unused_unknown_type).
+-export([t/0]).
+
-export_type([unused/0]).
+-export_type([wide/0, deep/0]).
+-export_type([owide/0, odeep/0]).
+-export_type([arg/0, rargs1/0, rargs2/0]).
+
-type unused() :: unknown:type1().
--record(unused_rec, {a :: unknown:type2()}).
+-record(unused_rec,
+ {a :: unknown:type2(),
+ b :: {{{{{{{{{{{{{{{{{{{{rfoo:rbar()}}}}}}}}}}}}}}}}}}}}}).
-record(rec, {a}).
-type unused_rec() :: #rec{a :: unknown:type3()}.
+
+-type wide() :: {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,xxx:y()}.
+-type owide() :: {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,owww:y()}.
+
+%% Deeper than the hardcoded limit in erl_types.erl of 16.
+-type deep() :: {{{{{{{{{{{{{{{{{{{{foo:bar()}}}}}}}}}}}}}}}}}}}}.
+-type odeep() :: {{{{{{{{{{{{{{{{{{{{ofoo:obar()}}}}}}}}}}}}}}}}}}}}.
+
+-type arg1(A) :: [A].
+-type arg() :: arg1({a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,yyy:x()}).
+
+%% No warning about www:x/0 because parameters are currently not
+%% handled if the parameterized type cannot be found.
+-type rargs1() :: zzz:arg({a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,www:x()}).
+
+-type rargs2() :: dict:dict({a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,zzz:x()},
+ any()).
+
+%% No warning. The check is commented out as it takes too long.
+-spec t() -> 'a' | {{{{{{{{{{{{{{{{{{{{sfoo:sbar()}}}}}}}}}}}}}}}}}}}}.
+t() ->
+ a.
diff --git a/lib/dialyzer/test/overspecs_SUITE_data/dialyzer_options b/lib/dialyzer/test/overspecs_SUITE_data/dialyzer_options
new file mode 100644
index 0000000000..ff4517e59d
--- /dev/null
+++ b/lib/dialyzer/test/overspecs_SUITE_data/dialyzer_options
@@ -0,0 +1 @@
+{dialyzer_options, [{warnings, [overspecs]}]}.
diff --git a/lib/dialyzer/test/overspecs_SUITE_data/results/iodata b/lib/dialyzer/test/overspecs_SUITE_data/results/iodata
new file mode 100644
index 0000000000..d9c70330ec
--- /dev/null
+++ b/lib/dialyzer/test/overspecs_SUITE_data/results/iodata
@@ -0,0 +1,2 @@
+
+iodata.erl:7: The success typing for iodata:encode/2 implies that the function might also return integer() but the specification return is binary() | maybe_improper_list(binary() | maybe_improper_list(any(),binary() | []) | byte(),binary() | [])
diff --git a/lib/dialyzer/test/overspecs_SUITE_data/results/iolist b/lib/dialyzer/test/overspecs_SUITE_data/results/iolist
new file mode 100644
index 0000000000..ca556f017c
--- /dev/null
+++ b/lib/dialyzer/test/overspecs_SUITE_data/results/iolist
@@ -0,0 +1,2 @@
+
+iolist.erl:7: The success typing for iolist:encode/2 implies that the function might also return integer() but the specification return is maybe_improper_list(binary() | maybe_improper_list(any(),binary() | []) | byte(),binary() | [])
diff --git a/lib/dialyzer/test/overspecs_SUITE_data/src/iodata.erl b/lib/dialyzer/test/overspecs_SUITE_data/src/iodata.erl
new file mode 100644
index 0000000000..caa44f6c91
--- /dev/null
+++ b/lib/dialyzer/test/overspecs_SUITE_data/src/iodata.erl
@@ -0,0 +1,41 @@
+-module(iodata).
+
+%% A small part of beam_asm.
+
+-export([encode/2]).
+
+-spec encode(non_neg_integer(), integer()) -> iodata(). % extra range binary()
+
+encode(Tag, N) when Tag >= 0, N < 0 ->
+ encode1(Tag, negative_to_bytes(N));
+encode(Tag, N) when Tag >= 0, N < 16 ->
+ (N bsl 4) bor Tag; % not in the specification
+encode(Tag, N) when Tag >= 0, N < 16#800 ->
+ [((N bsr 3) band 2#11100000) bor Tag bor 2#00001000, N band 16#ff];
+encode(Tag, N) when Tag >= 0 ->
+ encode1(Tag, to_bytes(N)).
+
+encode1(Tag, Bytes) ->
+ case iolist_size(Bytes) of
+ Num when 2 =< Num, Num =< 8 ->
+ [((Num-2) bsl 5) bor 2#00011000 bor Tag| Bytes];
+ Num when 8 < Num ->
+ [2#11111000 bor Tag, encode(0, Num-9)| Bytes]
+ end.
+
+to_bytes(N) ->
+ Bin = binary:encode_unsigned(N),
+ case Bin of
+ <<0:1,_/bits>> -> Bin;
+ <<1:1,_/bits>> -> [0,Bin]
+ end.
+
+negative_to_bytes(N) when N >= -16#8000 ->
+ <<N:16>>;
+negative_to_bytes(N) ->
+ Bytes = byte_size(binary:encode_unsigned(-N)),
+ Bin = <<N:Bytes/unit:8>>,
+ case Bin of
+ <<0:1,_/bits>> -> [16#ff,Bin];
+ <<1:1,_/bits>> -> Bin
+ end.
diff --git a/lib/dialyzer/test/overspecs_SUITE_data/src/iolist.erl b/lib/dialyzer/test/overspecs_SUITE_data/src/iolist.erl
new file mode 100644
index 0000000000..7cceeda24e
--- /dev/null
+++ b/lib/dialyzer/test/overspecs_SUITE_data/src/iolist.erl
@@ -0,0 +1,41 @@
+-module(iolist).
+
+%% A small part of beam_asm.
+
+-export([encode/2]).
+
+-spec encode(non_neg_integer(), integer()) -> iolist().
+
+encode(Tag, N) when Tag >= 0, N < 0 ->
+ encode1(Tag, negative_to_bytes(N));
+encode(Tag, N) when Tag >= 0, N < 16 ->
+ (N bsl 4) bor Tag; % not in the specification
+encode(Tag, N) when Tag >= 0, N < 16#800 ->
+ [((N bsr 3) band 2#11100000) bor Tag bor 2#00001000, N band 16#ff];
+encode(Tag, N) when Tag >= 0 ->
+ encode1(Tag, to_bytes(N)).
+
+encode1(Tag, Bytes) ->
+ case iolist_size(Bytes) of
+ Num when 2 =< Num, Num =< 8 ->
+ [((Num-2) bsl 5) bor 2#00011000 bor Tag| Bytes];
+ Num when 8 < Num ->
+ [2#11111000 bor Tag, encode(0, Num-9)| Bytes]
+ end.
+
+to_bytes(N) ->
+ Bin = binary:encode_unsigned(N),
+ case Bin of
+ <<0:1,_/bits>> -> Bin;
+ <<1:1,_/bits>> -> [0,Bin]
+ end.
+
+negative_to_bytes(N) when N >= -16#8000 ->
+ <<N:16>>;
+negative_to_bytes(N) ->
+ Bytes = byte_size(binary:encode_unsigned(-N)),
+ Bin = <<N:Bytes/unit:8>>,
+ case Bin of
+ <<0:1,_/bits>> -> [16#ff,Bin];
+ <<1:1,_/bits>> -> Bin
+ end.
diff --git a/lib/dialyzer/test/plt_SUITE.erl b/lib/dialyzer/test/plt_SUITE.erl
index ebe79b2a6d..680f5b5088 100644
--- a/lib/dialyzer/test/plt_SUITE.erl
+++ b/lib/dialyzer/test/plt_SUITE.erl
@@ -9,14 +9,14 @@
-export([suite/0, all/0, build_plt/1, beam_tests/1, update_plt/1,
local_fun_same_as_callback/1,
remove_plt/1, run_plt_check/1, run_succ_typings/1,
- bad_dialyzer_attr/1, merge_plts/1]).
+ bad_dialyzer_attr/1, merge_plts/1, bad_record_type/1]).
suite() ->
[{timetrap, ?plt_timeout}].
all() -> [build_plt, beam_tests, update_plt, run_plt_check,
remove_plt, run_succ_typings, local_fun_same_as_callback,
- bad_dialyzer_attr, merge_plts].
+ bad_dialyzer_attr, merge_plts, bad_record_type].
build_plt(Config) ->
OutDir = ?config(priv_dir, Config),
@@ -283,8 +283,8 @@ bad_dialyzer_attr(Config) ->
{dialyzer_error,
"Analysis failed with error:\n" ++ Str1} =
(catch dialyzer:run(Opts)),
- P1 = string:str(Str1, "dial.erl:2: function undef/0 undefined"),
- true = P1 > 0,
+ S1 = string:find(Str1, "dial.erl:2: function undef/0 undefined"),
+ true = is_list(S1),
Prog2 = <<"-module(dial).
-dialyzer({no_return, [{undef,1,2}]}).">>,
@@ -292,9 +292,9 @@ bad_dialyzer_attr(Config) ->
{dialyzer_error,
"Analysis failed with error:\n" ++ Str2} =
(catch dialyzer:run(Opts)),
- P2 = string:str(Str2, "dial.erl:2: badly formed dialyzer "
- "attribute: {no_return,{undef,1,2}}"),
- true = P2 > 0,
+ S2 = string:find(Str2, "dial.erl:2: badly formed dialyzer "
+ "attribute: {no_return,{undef,1,2}}"),
+ true = is_list(S2),
ok.
@@ -369,6 +369,32 @@ create_plts(Mod1, Mod2, Config) ->
%% End of merge_plts().
+bad_record_type(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ Source = lists:concat([bad_record_type, ".erl"]),
+ Filename = filename:join(PrivDir, Source),
+ PltFilename = dialyzer_common:plt_file(PrivDir),
+
+ Opts = [{files, [Filename]},
+ {check_plt, false},
+ {from, src_code},
+ {init_plt, PltFilename}],
+
+ Prog = <<"-module(bad_record_type).
+ -export([r/0]).
+ -record(r, {f = 3 :: integer()}).
+ -spec r() -> #r{f :: atom()}.
+ r() ->
+ #r{}.">>,
+ ok = file:write_file(Filename, Prog),
+ {dialyzer_error,
+ "Analysis failed with error:\n" ++ Str} =
+ (catch dialyzer:run(Opts)),
+ P = string:str(Str,
+ "bad_record_type.erl:4: Illegal declaration of #r{f}"),
+ true = P > 0,
+ ok.
+
erlang_beam() ->
case code:where_is_file("erlang.beam") of
non_existing ->
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_esi.erl b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_esi.erl
index a48f73274b..52db2d9096 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_esi.erl
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/inets/mod_esi.erl
@@ -285,7 +285,7 @@ eval(Info,"GET",CGIBody,Modules) ->
"~n Modules: ~p",[Modules]),
case auth(CGIBody,Modules) of
true ->
- case lib:eval_str(string:concat(CGIBody,". ")) of
+ case erl_eval:eval_str(string:concat(CGIBody,". ")) of
{error,Reason} ->
?vlog("eval -> error:"
"~n Reason: ~p",[Reason]),
diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_tm.erl b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_tm.erl
index 09e310530d..af49ceff72 100644
--- a/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_tm.erl
+++ b/lib/dialyzer/test/r9c_SUITE_data/src/mnesia/mnesia_tm.erl
@@ -2051,7 +2051,7 @@ display_pid_info(Pid) ->
Other
end,
Reds = fetch(reductions, Info),
- LM = length(fetch(messages, Info)),
+ LM = fetch(message_queue_len, Info),
pformat(io_lib:format("~p", [Pid]),
io_lib:format("~p", [Call]),
io_lib:format("~p", [Curr]), Reds, LM)
diff --git a/lib/dialyzer/test/small_SUITE_data/results/chars b/lib/dialyzer/test/small_SUITE_data/results/chars
index 2c1f8f8d17..72fbdb4528 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/chars
+++ b/lib/dialyzer/test/small_SUITE_data/results/chars
@@ -1,4 +1,4 @@
-chars.erl:29: Invalid type specification for function chars:f/1. The success typing is (#{'b':=50}) -> 'ok'
-chars.erl:32: Function t1/0 has no local return
-chars.erl:32: The call chars:f(#{'b':=50}) breaks the contract (#{'a':=49,'b'=>50,'c'=>51}) -> 'ok'
+chars.erl:37: Invalid type specification for function chars:f/1. The success typing is (#{'b':=50}) -> 'ok'
+chars.erl:40: Function t1/0 has no local return
+chars.erl:40: The call chars:f(#{'b':=50}) breaks the contract (#{'a':=49,'b'=>50,'c'=>51}) -> 'ok'
diff --git a/lib/dialyzer/test/small_SUITE_data/results/extra_range b/lib/dialyzer/test/small_SUITE_data/results/extra_range
new file mode 100644
index 0000000000..ec50c95c4e
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/extra_range
@@ -0,0 +1,4 @@
+
+extra_range.erl:29: The pattern 'ok' can never match the type 'error'
+extra_range.erl:43: The pattern 'no' can never match the type 'maybe' | 'yes'
+extra_range.erl:58: The pattern 'maybe' can never match the type 'no' | 'yes'
diff --git a/lib/dialyzer/test/small_SUITE_data/results/fun_arity b/lib/dialyzer/test/small_SUITE_data/results/fun_arity
index e916b2483f..8b7a538758 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/fun_arity
+++ b/lib/dialyzer/test/small_SUITE_data/results/fun_arity
@@ -1,37 +1,37 @@
-fun_arity.erl:100: Fun application will fail since _@c1 :: fun(() -> any()) is not a function of arity 1
+fun_arity.erl:100: Fun application will fail since _1 :: fun(() -> any()) is not a function of arity 1
fun_arity.erl:100: Function 'Mfa_0_ko'/1 has no local return
-fun_arity.erl:104: Fun application will fail since _@c1 :: fun((_) -> any()) is not a function of arity 0
+fun_arity.erl:104: Fun application will fail since _1 :: fun((_) -> any()) is not a function of arity 0
fun_arity.erl:104: Function 'Mfa_1_ko'/1 has no local return
-fun_arity.erl:111: Fun application will fail since _@c1 :: fun(() -> any()) is not a function of arity 1
+fun_arity.erl:111: Fun application will fail since _1 :: fun(() -> any()) is not a function of arity 1
fun_arity.erl:111: Function mFa_0_ko/1 has no local return
-fun_arity.erl:115: Fun application will fail since _@c1 :: fun((_) -> any()) is not a function of arity 0
+fun_arity.erl:115: Fun application will fail since _1 :: fun((_) -> any()) is not a function of arity 0
fun_arity.erl:115: Function mFa_1_ko/1 has no local return
-fun_arity.erl:122: Fun application will fail since _@c2 :: fun(() -> any()) is not a function of arity 1
+fun_arity.erl:122: Fun application will fail since _2 :: fun(() -> any()) is not a function of arity 1
fun_arity.erl:122: Function 'MFa_0_ko'/2 has no local return
-fun_arity.erl:126: Fun application will fail since _@c2 :: fun((_) -> any()) is not a function of arity 0
+fun_arity.erl:126: Fun application will fail since _2 :: fun((_) -> any()) is not a function of arity 0
fun_arity.erl:126: Function 'MFa_1_ko'/2 has no local return
-fun_arity.erl:35: Fun application will fail since _@c0 :: fun(() -> 'ok') is not a function of arity 1
+fun_arity.erl:35: Fun application will fail since _0 :: fun(() -> 'ok') is not a function of arity 1
fun_arity.erl:35: Function f_0_ko/0 has no local return
-fun_arity.erl:39: Fun application will fail since _@c0 :: fun((_) -> 'ok') is not a function of arity 0
+fun_arity.erl:39: Fun application will fail since _0 :: fun((_) -> 'ok') is not a function of arity 0
fun_arity.erl:39: Function f_1_ko/0 has no local return
-fun_arity.erl:48: Fun application will fail since _@c0 :: fun(() -> 'ok') is not a function of arity 1
+fun_arity.erl:48: Fun application will fail since _0 :: fun(() -> 'ok') is not a function of arity 1
fun_arity.erl:48: Function fa_0_ko/0 has no local return
-fun_arity.erl:53: Fun application will fail since _@c0 :: fun((_) -> 'ok') is not a function of arity 0
+fun_arity.erl:53: Fun application will fail since _0 :: fun((_) -> 'ok') is not a function of arity 0
fun_arity.erl:53: Function fa_1_ko/0 has no local return
-fun_arity.erl:63: Fun application will fail since _@c0 :: fun(() -> any()) is not a function of arity 1
+fun_arity.erl:63: Fun application will fail since _0 :: fun(() -> any()) is not a function of arity 1
fun_arity.erl:63: Function mfa_0_ko/0 has no local return
-fun_arity.erl:68: Fun application will fail since _@c0 :: fun((_) -> any()) is not a function of arity 0
+fun_arity.erl:68: Fun application will fail since _0 :: fun((_) -> any()) is not a function of arity 0
fun_arity.erl:68: Function mfa_1_ko/0 has no local return
-fun_arity.erl:76: Fun application will fail since _@c0 :: fun(() -> any()) is not a function of arity 1
+fun_arity.erl:76: Fun application will fail since _0 :: fun(() -> any()) is not a function of arity 1
fun_arity.erl:76: Function mfa_ne_0_ko/0 has no local return
fun_arity.erl:78: Function mf_ne/0 will never be called
-fun_arity.erl:81: Fun application will fail since _@c0 :: fun((_) -> any()) is not a function of arity 0
+fun_arity.erl:81: Fun application will fail since _0 :: fun((_) -> any()) is not a function of arity 0
fun_arity.erl:81: Function mfa_ne_1_ko/0 has no local return
fun_arity.erl:83: Function mf_ne/1 will never be called
-fun_arity.erl:89: Fun application will fail since _@c0 :: fun(() -> any()) is not a function of arity 1
+fun_arity.erl:89: Fun application will fail since _0 :: fun(() -> any()) is not a function of arity 1
fun_arity.erl:89: Function mfa_nd_0_ko/0 has no local return
fun_arity.erl:90: Call to missing or unexported function fun_arity:mf_nd/0
-fun_arity.erl:93: Fun application will fail since _@c0 :: fun((_) -> any()) is not a function of arity 0
+fun_arity.erl:93: Fun application will fail since _0 :: fun((_) -> any()) is not a function of arity 0
fun_arity.erl:93: Function mfa_nd_1_ko/0 has no local return
fun_arity.erl:94: Call to missing or unexported function fun_arity:mf_nd/1
diff --git a/lib/dialyzer/test/small_SUITE_data/results/left_assoc b/lib/dialyzer/test/small_SUITE_data/results/left_assoc
new file mode 100644
index 0000000000..58cdad29de
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/left_assoc
@@ -0,0 +1,2 @@
+
+left_assoc.erl:93: The variable __@2 can never match since previous clauses completely covered the type binary()
diff --git a/lib/dialyzer/test/small_SUITE_data/results/maps_sum b/lib/dialyzer/test/small_SUITE_data/results/maps_sum
index bd192bdb93..b29ac77d88 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/maps_sum
+++ b/lib/dialyzer/test/small_SUITE_data/results/maps_sum
@@ -1,4 +1,4 @@
-maps_sum.erl:15: Invalid type specification for function maps_sum:wrong1/1. The success typing is (map()) -> any()
+maps_sum.erl:15: Invalid type specification for function maps_sum:wrong1/1. The success typing is (maps:iterator() | map()) -> any()
maps_sum.erl:26: Function wrong2/1 has no local return
maps_sum.erl:27: The call lists:foldl(fun((_,_,_) -> any()),0,Data::any()) will never return since it differs in the 1st argument from the success typing arguments: (fun((_,_) -> any()),any(),[any()])
diff --git a/lib/dialyzer/test/small_SUITE_data/results/record_match b/lib/dialyzer/test/small_SUITE_data/results/record_match
new file mode 100644
index 0000000000..a0dd6f560a
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/record_match
@@ -0,0 +1,3 @@
+
+record_match.erl:16: Function select/0 has no local return
+record_match.erl:17: Matching of pattern {'b_literal', 'undefined'} tagged with a record name violates the declared type of #b_local{} | #b_remote{}
diff --git a/lib/dialyzer/test/small_SUITE_data/results/stacktrace b/lib/dialyzer/test/small_SUITE_data/results/stacktrace
new file mode 100644
index 0000000000..fd60881953
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/stacktrace
@@ -0,0 +1,5 @@
+
+stacktrace.erl:11: The pattern {'a', 'b'} can never match the type [{atom(),atom(),[any()] | byte(),[{'file',string()} | {'line',pos_integer()}]}]
+stacktrace.erl:19: The pattern ['a', 'b'] can never match the type [{atom(),atom(),[any()] | byte(),[{'file',string()} | {'line',pos_integer()}]}]
+stacktrace.erl:44: The pattern {'a', 'b'} can never match the type [{atom(),atom(),[any()] | byte(),[{'file',string()} | {'line',pos_integer()}]}]
+stacktrace.erl:53: The pattern ['a', 'b'] can never match the type [{atom(),atom(),[any()] | byte(),[{'file',string()} | {'line',pos_integer()}]}]
diff --git a/lib/dialyzer/test/small_SUITE_data/results/unused_funs b/lib/dialyzer/test/small_SUITE_data/results/unused_funs
new file mode 100644
index 0000000000..c468457ead
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/unused_funs
@@ -0,0 +1,5 @@
+
+unused_funs.erl:10: The pattern 'error' can never match the type 'other_error'
+unused_funs.erl:15: Function not_used/0 will never be called
+unused_funs.erl:19: Function foo/1 will never be called
+unused_funs.erl:7: Function test/0 has no local return
diff --git a/lib/dialyzer/test/small_SUITE_data/src/abs.erl b/lib/dialyzer/test/small_SUITE_data/src/abs.erl
index 251e24cdfc..0e38c3dbb7 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/abs.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/abs.erl
@@ -5,7 +5,7 @@
-export([t/0]).
t() ->
- Fs = [fun i1/0, fun i2/0, fun i3/0, fun i4/0, fun f1/0],
+ Fs = [fun i1/0, fun i2/0, fun i3/0, fun i4/0, fun f1/0, fun erl_551/0],
_ = [catch F() || F <- Fs],
ok.
@@ -60,6 +60,13 @@ f1() ->
f1(A) ->
abs(A).
+erl_551() ->
+ accept(9),
+ accept(-3).
+
+accept(Number) when abs(Number) >= 8 -> first;
+accept(_Number) -> second.
+
-spec int() -> integer().
int() ->
diff --git a/lib/dialyzer/test/small_SUITE_data/src/bsL.erl b/lib/dialyzer/test/small_SUITE_data/src/bsL.erl
new file mode 100644
index 0000000000..b2fdc16324
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/bsL.erl
@@ -0,0 +1,13 @@
+-module(bsL).
+
+-export([t/0]).
+
+%% Found in lib/observer/test/crashdump_helper.erl.
+
+t() ->
+ Size = 60,
+ <<H:16/unit:8>> = erlang:md5(<<Size:32>>),
+ true = H < 20,
+ true = H > 2,
+ Data = ((H bsl (8*150)) div (H+7919)),
+ <<Data:Size/unit:8>>.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/chars.erl b/lib/dialyzer/test/small_SUITE_data/src/chars.erl
index 1e9c8ab6b9..62b90cf54d 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/chars.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/chars.erl
@@ -12,17 +12,25 @@
-spec t() -> $0-$0..$9-$0| $?.
t() ->
- c(#r{f = $z - 3}),
+ r(#r{f = $z - 3}),
+ r(#r{f = 97}),
+ c($/),
c($z - 3),
c($B).
-spec c(cs()) -> $3-$0..$9-$0.
-
-c($A + 1) -> 2;
+c($A + 1) -> $9-$0;
c(C) ->
case C of
- $z - 3 -> 3;
- #r{f = $z - 3} -> 7
+ $z - 3 -> $3-$0;
+ _ -> $7-$0
+ end.
+
+-spec r(#r{f :: $a..$z}) -> ok | error.
+r(R) ->
+ case R of
+ #r{f = $z - 3} -> error;
+ _ -> ok
end.
%% Display contract with character in warning:
diff --git a/lib/dialyzer/test/small_SUITE_data/src/erl_tar_table.erl b/lib/dialyzer/test/small_SUITE_data/src/erl_tar_table.erl
new file mode 100644
index 0000000000..2dc00d272a
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/erl_tar_table.erl
@@ -0,0 +1,14 @@
+-module(erl_tar_table).
+
+%% OTP-14860, PR 1670.
+
+-export([t/0, v/0, x/0]).
+
+t() ->
+ {ok, ["file"]} = erl_tar:table("table.tar").
+
+v() ->
+ {ok, [{_,_,_,_,_,_,_}]} = erl_tar:table("table.tar", [verbose]).
+
+x() ->
+ {ok, ["file"]} = erl_tar:table("table.tar", []).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/extra_range.erl b/lib/dialyzer/test/small_SUITE_data/src/extra_range.erl
new file mode 100644
index 0000000000..9d6ba89c95
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/extra_range.erl
@@ -0,0 +1,59 @@
+%% Test that a spec containing more items than actually returned
+%% (whether by accident or by benign overspeccing) does not prevent
+%% detection of impossible matches.
+
+-module(extra_range).
+
+-export([t1/2, t2/2, t3/2, t4/2]).
+
+-dialyzer([no_return]).
+
+%% this spec matches the behaviour of the code
+-spec normal(integer()) -> ok | error.
+normal(1) -> ok;
+normal(2) -> error.
+
+t1(X, Y) when is_integer(X), is_integer(Y) ->
+ ok = normal(X),
+ error = normal(Y),
+ ok.
+
+
+%% this spec has a typo, which should cause anyone trying to match on
+%% `ok = typo(X)' to get a warning, because `ok' is not in the spec
+-spec typo(integer()) -> ook | error.
+typo(1) -> ok;
+typo(2) -> error.
+
+t2(X, Y) when is_integer(X), is_integer(Y) ->
+ ok = typo(X), % warning expected - not allowed according to spec
+ error = typo(Y),
+ ok.
+
+
+%% this is overspecified, and should cause a warning for trying
+%% to match on `no = over(X)', because it cannot succeed and either
+%% the spec should be updated or the code should be extended
+-spec over(integer()) -> yes | no | maybe.
+over(1) -> yes;
+over(_) -> maybe.
+
+t3(X, Y) when is_integer(X), is_integer(Y) ->
+ yes = over(X),
+ no = over(Y), % warning expected - spec or code needs fixing
+ maybe = over(X + Y),
+ ok.
+
+
+%% this is underspecified, which should cause anyone trying to match on
+%% `maybe = under(X)' to get a warning, because `maybe' is not in the spec
+-spec under(integer()) -> yes | no.
+under(1) -> yes;
+under(2) -> no;
+under(_) -> maybe.
+
+t4(X, Y) when is_integer(X), is_integer(Y) ->
+ yes = under(X),
+ no = under(Y),
+ maybe = under(X + Y), % warning expected - not in spec
+ ok.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/left_assoc.erl b/lib/dialyzer/test/small_SUITE_data/src/left_assoc.erl
new file mode 100644
index 0000000000..0250e4ab49
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/left_assoc.erl
@@ -0,0 +1,96 @@
+-module(left_assoc).
+
+%% As pointed out in ERL-680, analyzing guards with short circuit
+%% operators becomes very slow as the number of left associations
+%% grows.
+
+-spec from_iso8601('Elixir.String':t(), 'Elixir.Calendar':calendar()) ->
+ {ok, t()} | {error, atom()}.
+
+-export_type([t/0]).
+
+-type t() ::
+ #{'__struct__' := 'Elixir.Date',
+ calendar := 'Elixir.Calendar':calendar(),
+ day := 'Elixir.Calendar':day(),
+ month := 'Elixir.Calendar':month(),
+ year := 'Elixir.Calendar':year()}.
+
+-export([from_iso8601/1,
+ from_iso8601/2]).
+
+from_iso8601(__@1) ->
+ from_iso8601(__@1, 'Elixir.Calendar.ISO').
+
+from_iso8601(<<45/integer,_rest@1/binary>>, _calendar@1) ->
+ case raw_from_iso8601(_rest@1, _calendar@1) of
+ {ok,#{year := _year@1} = _date@1} ->
+ {ok,_date@1#{year := - _year@1}};
+ __@1 ->
+ __@1
+ end;
+from_iso8601(<<_rest@1/binary>>, _calendar@1) ->
+ raw_from_iso8601(_rest@1, _calendar@1).
+
+raw_from_iso8601(_string@1, _calendar@1) ->
+ case _string@1 of
+ <<_y1@1/integer,
+ _y2@1/integer,
+ _y3@1/integer,
+ _y4@1/integer,
+ 45/integer,
+ _m1@1/integer,
+ _m2@1/integer,
+ 45/integer,
+ _d1@1/integer,
+ _d2@1/integer>>
+ when
+ ((((((((((((((_y1@1 >= 48
+ andalso
+ _y1@1 =< 57)
+ andalso
+ _y2@1 >= 48)
+ andalso
+ _y2@1 =< 57)
+ andalso
+ _y3@1 >= 48)
+ andalso
+ _y3@1 =< 57)
+ andalso
+ _y4@1 >= 48)
+ andalso
+ _y4@1 =< 57)
+ andalso
+ _m1@1 >= 48)
+ andalso
+ _m1@1 =< 57)
+ andalso
+ _m2@1 >= 48)
+ andalso
+ _m2@1 =< 57)
+ andalso
+ _d1@1 >= 48)
+ andalso
+ _d1@1 =< 57)
+ andalso
+ _d2@1 >= 48)
+ andalso
+ _d2@1 =< 57 ->
+ {ok,
+ #{year => (_y1@1 - 48) * 1000 + (_y2@1 - 48) * 100
+ +
+ (_y3@1 - 48) * 10
+ +
+ (_y4@1 - 48),
+ month => (_m1@1 - 48) * 10 + (_m2@1 - 48),
+ day => (_d1@1 - 48) * 10 + (_d2@1 - 48),
+ calendar => _calendar@1,
+ '__struct__' => 'Elixir.Date'}};
+ __@1 ->
+ case __@1 of
+ _ ->
+ {error,invalid_format};
+ __@2 ->
+ error({with_clause,__@2})
+ end
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/record_match.erl b/lib/dialyzer/test/small_SUITE_data/src/record_match.erl
new file mode 100644
index 0000000000..8e9b91937f
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/record_match.erl
@@ -0,0 +1,17 @@
+-module(record_match).
+
+-export([select/0]).
+
+-record(b_literal, {val}).
+-record(b_remote, {mod,name,arity}).
+-record(b_local, {name,arity}).
+
+-type b_remote() :: #b_remote{}.
+-type b_local() :: #b_local{}.
+
+-type argument() :: b_remote() | b_local().
+
+-record(b_set, {args=[] :: [argument()]}).
+
+select() ->
+ #b_set{args=[#b_remote{},#b_literal{}]}.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/stacktrace.erl b/lib/dialyzer/test/small_SUITE_data/src/stacktrace.erl
new file mode 100644
index 0000000000..de79e710e9
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/stacktrace.erl
@@ -0,0 +1,73 @@
+-module(stacktrace).
+
+%% Check the stacktrace variable introduced in Erlang/OTP 21.0
+
+-export([t1/0, t2/0, t3/0, t4/0, s1/0, s2/0, s3/0, s4/0]).
+
+t1() ->
+ try foo:bar()
+ catch
+ E:P:S ->
+ {a,b} = S, % can never match
+ {E, P}
+ end.
+
+t2() ->
+ try foo:bar()
+ catch
+ E:P:S ->
+ [a,b] = S, % can never match
+ {E, P}
+ end.
+
+t3() ->
+ try foo:bar()
+ catch
+ E:P:S ->
+ [{m,f,[],[]}] = S,
+ {E, P}
+ end.
+
+t4() ->
+ try foo:bar()
+ catch
+ E:P:S ->
+ [{m,f,1,[{file,"tjo"},{line,95}]}] = S,
+ {E, P}
+ end.
+
+s1() ->
+ try foo:bar()
+ catch
+ E:P ->
+ S = erlang:get_stacktrace(),
+ {a,b} = S, % can never match
+ {E, P}
+ end.
+
+s2() ->
+ try foo:bar()
+ catch
+ E:P ->
+ S = erlang:get_stacktrace(),
+ [a,b] = S, % can never match
+ {E, P}
+ end.
+
+s3() ->
+ try foo:bar()
+ catch
+ E:P ->
+ S = erlang:get_stacktrace(),
+ [{m,f,[],[]}] = S,
+ {E, P}
+ end.
+
+s4() ->
+ try foo:bar()
+ catch
+ E:P ->
+ S = erlang:get_stacktrace(),
+ [{m,f,1,[{file,"tjo"},{line,95}]}] = S,
+ {E, P}
+ end.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/unused_funs.erl b/lib/dialyzer/test/small_SUITE_data/src/unused_funs.erl
new file mode 100644
index 0000000000..c24cf3ea81
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/unused_funs.erl
@@ -0,0 +1,21 @@
+%% See also ERL-593.
+
+-module(unused_funs).
+
+-export([test/0]).
+
+test() -> % "has no local return"
+ Var = outer_scope,
+ case other_error of
+ error -> % "can never match"
+ %% No warnings "no local return" and "_ = 1 can never match 0" (!)
+ foo(fun() -> {Var, 1 = 0} end)
+ end.
+
+not_used() -> % "will never be called"
+ %% No warnings "no local return" and "1 can never match 0".
+ foo(fun() -> 1 = 0 end).
+
+foo(Fun) -> % "will never be called"
+ 1 = 0, % No pattern match warning (foo/1 is not traversed at all).
+ Fun().
diff --git a/lib/dialyzer/test/specdiffs_SUITE_data/dialyzer_options b/lib/dialyzer/test/specdiffs_SUITE_data/dialyzer_options
new file mode 100644
index 0000000000..56b36f2ed4
--- /dev/null
+++ b/lib/dialyzer/test/specdiffs_SUITE_data/dialyzer_options
@@ -0,0 +1 @@
+{dialyzer_options, [{warnings, [specdiffs]}]}.
diff --git a/lib/dialyzer/test/specdiffs_SUITE_data/results/iodata b/lib/dialyzer/test/specdiffs_SUITE_data/results/iodata
new file mode 100644
index 0000000000..3fb12fe000
--- /dev/null
+++ b/lib/dialyzer/test/specdiffs_SUITE_data/results/iodata
@@ -0,0 +1,3 @@
+
+iodata.erl:7: The specification for iodata:encode/2 states that the function might also return binary() but the inferred return is nonempty_maybe_improper_list(<<_:8,_:_*8>> | nonempty_maybe_improper_list(<<_:8,_:_*8>> | nonempty_maybe_improper_list(any(),<<_:8,_:_*8>> | []) | byte(),<<_:8,_:_*8>> | []) | integer(),<<_:8,_:_*8>> | []) | integer()
+iodata.erl:7: The success typing for iodata:encode/2 implies that the function might also return integer() but the specification return is binary() | maybe_improper_list(binary() | maybe_improper_list(any(),binary() | []) | byte(),binary() | [])
diff --git a/lib/dialyzer/test/specdiffs_SUITE_data/results/iolist b/lib/dialyzer/test/specdiffs_SUITE_data/results/iolist
new file mode 100644
index 0000000000..ca556f017c
--- /dev/null
+++ b/lib/dialyzer/test/specdiffs_SUITE_data/results/iolist
@@ -0,0 +1,2 @@
+
+iolist.erl:7: The success typing for iolist:encode/2 implies that the function might also return integer() but the specification return is maybe_improper_list(binary() | maybe_improper_list(any(),binary() | []) | byte(),binary() | [])
diff --git a/lib/dialyzer/test/specdiffs_SUITE_data/src/iodata.erl b/lib/dialyzer/test/specdiffs_SUITE_data/src/iodata.erl
new file mode 100644
index 0000000000..caa44f6c91
--- /dev/null
+++ b/lib/dialyzer/test/specdiffs_SUITE_data/src/iodata.erl
@@ -0,0 +1,41 @@
+-module(iodata).
+
+%% A small part of beam_asm.
+
+-export([encode/2]).
+
+-spec encode(non_neg_integer(), integer()) -> iodata(). % extra range binary()
+
+encode(Tag, N) when Tag >= 0, N < 0 ->
+ encode1(Tag, negative_to_bytes(N));
+encode(Tag, N) when Tag >= 0, N < 16 ->
+ (N bsl 4) bor Tag; % not in the specification
+encode(Tag, N) when Tag >= 0, N < 16#800 ->
+ [((N bsr 3) band 2#11100000) bor Tag bor 2#00001000, N band 16#ff];
+encode(Tag, N) when Tag >= 0 ->
+ encode1(Tag, to_bytes(N)).
+
+encode1(Tag, Bytes) ->
+ case iolist_size(Bytes) of
+ Num when 2 =< Num, Num =< 8 ->
+ [((Num-2) bsl 5) bor 2#00011000 bor Tag| Bytes];
+ Num when 8 < Num ->
+ [2#11111000 bor Tag, encode(0, Num-9)| Bytes]
+ end.
+
+to_bytes(N) ->
+ Bin = binary:encode_unsigned(N),
+ case Bin of
+ <<0:1,_/bits>> -> Bin;
+ <<1:1,_/bits>> -> [0,Bin]
+ end.
+
+negative_to_bytes(N) when N >= -16#8000 ->
+ <<N:16>>;
+negative_to_bytes(N) ->
+ Bytes = byte_size(binary:encode_unsigned(-N)),
+ Bin = <<N:Bytes/unit:8>>,
+ case Bin of
+ <<0:1,_/bits>> -> [16#ff,Bin];
+ <<1:1,_/bits>> -> Bin
+ end.
diff --git a/lib/dialyzer/test/specdiffs_SUITE_data/src/iolist.erl b/lib/dialyzer/test/specdiffs_SUITE_data/src/iolist.erl
new file mode 100644
index 0000000000..7cceeda24e
--- /dev/null
+++ b/lib/dialyzer/test/specdiffs_SUITE_data/src/iolist.erl
@@ -0,0 +1,41 @@
+-module(iolist).
+
+%% A small part of beam_asm.
+
+-export([encode/2]).
+
+-spec encode(non_neg_integer(), integer()) -> iolist().
+
+encode(Tag, N) when Tag >= 0, N < 0 ->
+ encode1(Tag, negative_to_bytes(N));
+encode(Tag, N) when Tag >= 0, N < 16 ->
+ (N bsl 4) bor Tag; % not in the specification
+encode(Tag, N) when Tag >= 0, N < 16#800 ->
+ [((N bsr 3) band 2#11100000) bor Tag bor 2#00001000, N band 16#ff];
+encode(Tag, N) when Tag >= 0 ->
+ encode1(Tag, to_bytes(N)).
+
+encode1(Tag, Bytes) ->
+ case iolist_size(Bytes) of
+ Num when 2 =< Num, Num =< 8 ->
+ [((Num-2) bsl 5) bor 2#00011000 bor Tag| Bytes];
+ Num when 8 < Num ->
+ [2#11111000 bor Tag, encode(0, Num-9)| Bytes]
+ end.
+
+to_bytes(N) ->
+ Bin = binary:encode_unsigned(N),
+ case Bin of
+ <<0:1,_/bits>> -> Bin;
+ <<1:1,_/bits>> -> [0,Bin]
+ end.
+
+negative_to_bytes(N) when N >= -16#8000 ->
+ <<N:16>>;
+negative_to_bytes(N) ->
+ Bytes = byte_size(binary:encode_unsigned(-N)),
+ Bin = <<N:Bytes/unit:8>>,
+ case Bin of
+ <<0:1,_/bits>> -> [16#ff,Bin];
+ <<1:1,_/bits>> -> Bin
+ end.
diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk
index 4a1a7c25a0..98ab533a58 100644
--- a/lib/dialyzer/vsn.mk
+++ b/lib/dialyzer/vsn.mk
@@ -1 +1 @@
-DIALYZER_VSN = 3.2
+DIALYZER_VSN = 3.3.1
diff --git a/lib/diameter/bin/diameterc b/lib/diameter/bin/diameterc
index 3dbd238c19..4d415ece78 100755
--- a/lib/diameter/bin/diameterc
+++ b/lib/diameter/bin/diameterc
@@ -4,7 +4,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -78,8 +78,8 @@ compile(#argv{file = File, options = Opts, output = Out}) ->
error_msg(diameter_make:format_error(Reason), []),
1
catch
- error: Reason ->
- error_msg("ERROR: ~p~n ~p", [Reason, erlang:get_stacktrace()]),
+ error: Reason: Stack ->
+ error_msg("ERROR: ~p~n ~p", [Reason, Stack]),
2
end.
diff --git a/lib/diameter/doc/src/Makefile b/lib/diameter/doc/src/Makefile
index 7a7546fc4d..7c7fbeafef 100644
--- a/lib/diameter/doc/src/Makefile
+++ b/lib/diameter/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2016. All Rights Reserved.
+# Copyright Ericsson AB 2010-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -77,6 +77,7 @@ clean_man:
clean_html:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml
index 2cbe48ecce..dfa4c803ed 100644
--- a/lib/diameter/doc/src/diameter.xml
+++ b/lib/diameter/doc/src/diameter.xml
@@ -135,7 +135,7 @@ along with any
extra arguments to be appended to those documented.
Note that extra arguments specific to an outgoing request can be
specified to &call;, in which case
-those are are appended to any module-specific extra arguments.</p>
+those are appended to any module-specific extra arguments.</p>
<p>
Specifying a <c>#diameter_callback{}</c> record allows individual
@@ -150,7 +150,7 @@ See <c>diameter_callback.erl</c> for details.</p>
<p>
Options defining a Diameter application.
-Has one the following types.</p>
+Has one of the following types.</p>
<taglist>
@@ -397,10 +397,10 @@ from the peer offers it.</p>
Note that each tuple communicates one or more AVP values.
It is an error to specify duplicate tuples.</p>
-<marker id="evaluable"/>
+<marker id="eval"/>
</item>
-<tag><c>evaluable() = {M,F,A} | fun() | [evaluable() | A]</c></tag>
+<tag><c>eval() = {M,F,A} | fun() | [eval() | A]</c></tag>
<item>
<p>
An expression that can be evaluated as a function in the following
@@ -418,7 +418,7 @@ eval(F) ->
</pre>
<p>
-Applying an <c>&evaluable;</c>
+Applying an <c>&eval;</c>
<c>E</c> to an argument list <c>A</c>
is meant in the sense of <c>eval([E|A])</c>.</p>
@@ -484,11 +484,11 @@ Matches only those peers whose Origin-Realm has the
specified value, or all peers if the atom <c>any</c>.</p>
</item>
-<tag><c>{eval, &evaluable;}</c></tag>
+<tag><c>{eval, &eval;}</c></tag>
<item>
<p>
Matches only those peers for which the specified
-<c>&evaluable;</c> returns
+<c>&eval;</c> returns
<c>true</c> when applied to the connection's <c>diameter_caps</c>
record.
Any other return value or exception is equivalent to <c>false</c>.</p>
@@ -650,7 +650,7 @@ Result = ResultCode | {capabilities_cb, CB, ResultCode|discard}
Caps = #diameter_caps{}
Pkt = #diameter_packet{}
ResultCode = integer()
-CB = &evaluable;
+CB = &eval;
</pre>
<p>
@@ -798,15 +798,31 @@ be matched by corresponding &capability; configuration, of
</item>
<tag>
-<marker id="incoming_maxlen"/><c>{incoming_maxlen, 0..16777215}</c></tag>
+<marker id="decode_format"/>
+<c>{decode_format, record | list | map | none}</c></tag>
<item>
<p>
-Bound on the expected size of incoming Diameter messages.
-Messages larger than the specified number of bytes are discarded.</p>
+The format of decoded messages and grouped AVPs in the <c>msg</c> field
+of diameter_packet records and <c>value</c> field of diameter_avp
+records respectively.
+If <c>record</c> then a record whose definition is generated from the
+dictionary file in question.
+If <c>list</c> or <c>map</c> then a <c>[Name | Avps]</c> pair where
+<c>Avps</c> is a list of AVP name/values pairs or a map keyed on
+AVP names respectively.
+If <c>none</c> then the atom-value message name, or <c>undefined</c>
+for a Grouped AVP.
+See also &codec_message;.</p>
<p>
-Defaults to <c>16777215</c>, the maximum value of the 24-bit Message
-Length field in a Diameter Header.</p>
+Defaults to <c>record</c>.</p>
+
+<note>
+<p>
+AVPs are decoded into a list of diameter_avp records in <c>avps</c>
+field of diameter_packet records independently of
+<c>decode_format</c>.</p>
+</note>
</item>
@@ -814,7 +830,7 @@ Length field in a Diameter Header.</p>
| node
| nodes
| [node()]
- | evaluable()}</c></tag>
+ | eval()}</c></tag>
<item>
<p>
The degree to which the service allows multiple transport
@@ -825,7 +841,7 @@ at capabilities exchange.</p>
If <c>[node()]</c> then a connection is rejected if another already
exists on any of the specified nodes.
Types <c>false</c>, <c>node</c>, <c>nodes</c> and
-&evaluable; are equivalent to
+&eval; are equivalent to
<c>[]</c>, <c>[node()]</c>, <c>[node()|nodes()]</c> and the
evaluated value respectively, evaluation of each expression taking
place whenever a new connection is to be established.
@@ -840,7 +856,7 @@ by their own peer and watchdog state machines.</p>
Defaults to <c>nodes</c>.</p>
</item>
-<tag><c>{sequence, {H,N} | &evaluable;}</c></tag>
+<tag><c>{sequence, {H,N} | &eval;}</c></tag>
<item>
<p>
A constant value <c>H</c> for the topmost <c>32-N</c> bits of
@@ -875,7 +891,7 @@ outgoing requests.</p>
</warning>
</item>
-<tag><c>{share_peers, boolean() | [node()] | evaluable()}</c></tag>
+<tag><c>{share_peers, boolean() | [node()] | eval()}</c></tag>
<item>
<p>
Nodes to which peer connections established on the local
@@ -888,7 +904,7 @@ configured to use them: see <c>use_shared_peers</c> below.</p>
If <c>false</c> then peers are not shared.
If <c>[node()]</c> then peers are shared with the specified list of
nodes.
-If <c>evaluable()</c> then peers are shared with the nodes returned
+If <c>eval()</c> then peers are shared with the nodes returned
by the specified function, evaluated whenever a peer connection
becomes available or a remote service requests information about local
connections.
@@ -914,59 +930,36 @@ of a single Diameter node across multiple Erlang nodes.</p>
</note>
</item>
-<tag><c>{spawn_opt, [term()]}</c></tag>
-<item>
-<p>
-Options list passed to &spawn_opt; when spawning a process for an
-incoming Diameter request, unless the transport in question
-specifies another value.
-Options <c>monitor</c> and <c>link</c> are ignored.</p>
-
-<p>
-Defaults to the empty list.</p>
-</item>
-
<tag>
-<marker id="strict_mbit"/><c>{strict_mbit, boolean()}</c></tag>
+<marker id="strict_arities"/><c>{strict_arities, boolean()
+ | encode
+ | decode}</c></tag>
<item>
<p>
-Whether or not to regard an AVP setting the M-bit as erroneous when
-the command grammar in question does not explicitly allow the AVP.
-If <c>true</c> then such AVPs are regarded as 5001 errors,
-DIAMETER_AVP_UNSUPPORTED.
-If <c>false</c> then the M-bit is ignored and policing
-it becomes the receiver's responsibility.</p>
+Whether or not to require that the number of AVPs in a message or
+grouped AVP agree with those specified in the dictionary in question
+when passing messages to &man_app; callbacks.
+If <c>true</c> then mismatches in an outgoing messages cause message
+encoding to fail, while mismatches in an incoming message are reported
+as 5005/5009 errors in the errors field of the diameter_packet record
+passed to &app_handle_request; or &app_handle_answer; callbacks.
+If <c>false</c> then neither error is enforced/detected.
+If <c>encode</c> or <c>decode</c> then errors are only
+enforced/detected on outgoing or incoming messages respectively.</p>
<p>
Defaults to <c>true</c>.</p>
-<warning>
-<p>
-RFC 6733 is unclear about the semantics of the M-bit.
-One the one hand, the CCF specification in section 3.2 documents AVP
-in a command grammar as meaning <em>any</em> arbitrary AVP; on the
-other hand, 1.3.4 states that AVPs setting the M-bit cannot be added
-to an existing command: the modified command must instead be
-placed in a new Diameter application.</p>
-<p>
-The reason for the latter is presumably interoperability:
-allowing arbitrary AVPs setting the M-bit in a command makes its
-interpretation implementation-dependent, since there's no
-guarantee that all implementations will understand the same set of
-arbitrary AVPs in the context of a given command.
-However, interpreting <c>AVP</c> in a command grammar as any
-AVP, regardless of M-bit, renders 1.3.4 meaningless, since the receiver
-can simply ignore any AVP it thinks isn't relevant, regardless of the
-sender's intent.</p>
+<note>
<p>
-Beware of confusing mandatory in the sense of the M-bit with mandatory
-in the sense of the command grammar.
-The former is a semantic requirement: that the receiver understand the
-semantics of the AVP in the context in question.
-The latter is a syntactic requirement: whether or not the AVP must
-occur in the message in question.</p>
-</warning>
-
+Disabling arity checks affects the form of messages at encode/decode.
+In particular, decoded AVPs are represented as lists of values,
+regardless of the AVP's arity (ie. expected number in the message/AVP
+grammar in question), and values are expected to be supplied as lists
+at encode.
+This differs from the historic decode behaviour of representing AVPs
+of arity 1 as bare values, not wrapped in a list.</p>
+</note>
</item>
<tag>
@@ -993,7 +986,27 @@ The default value is for backwards compatibility.</p>
</item>
-<tag><c>{use_shared_peers, boolean() | [node()] | evaluable()}</c></tag>
+<tag>
+<marker id="traffic_counters"/><c>{traffic_counters, boolean()}</c></tag>
+<item>
+<p>
+Whether or not to count application-specific messages; those for which
+&man_app; callbacks take place.
+If false then only messages handled by diameter itself are counted:
+CER/CEA, DWR/DWA, DPR/DPA.</p>
+
+<p>
+Defaults to <c>true</c>.</p>
+
+<note>
+<p>
+Disabling counters is a performance improvement, but means that the
+omitted counters are not returned by &service_info;.</p>
+</note>
+
+</item>
+
+<tag><c>{use_shared_peers, boolean() | [node()] | eval()}</c></tag>
<item>
<p>
Nodes from which communicated peers are made available in
@@ -1003,7 +1016,7 @@ the remote candidates list of &app_pick_peer; callbacks.</p>
If <c>false</c> then remote peers are not used.
If <c>[node()]</c> then only peers from the specified list of nodes
are used.
-If <c>evaluable()</c> then only peers returned by the specified
+If <c>eval()</c> then only peers returned by the specified
function are used, evaluated whenever a remote service communicates
information about an available peer connection.
The value <c>true</c> is equivalent to <c>fun &nodes;</c>.
@@ -1028,6 +1041,15 @@ each node from which requests are sent.</p>
</warning>
</item>
+<tag><c>&transport_opt;</c></tag>
+<item>
+<p>
+Any transport option except <c>applications</c> or
+<c>capabilities</c>.
+Used as defaults for transport configuration, values passed to
+&add_transport; overriding values configured on the service.</p>
+</item>
+
</taglist>
<marker id="transport_opt"/>
@@ -1061,6 +1083,37 @@ implies having to set matching *-Application-Id AVPs in a
</item>
<tag>
+<marker id="avp_dictionaries"/><c>{avp_dictionaries, [module()]}</c></tag>
+<item>
+<p>
+A list of alternate dictionary modules with which to encode/decode
+AVPs that are not defined by the dictionary of the application in
+question.
+At decode, such AVPs are represented as diameter_avp records in the
+<c>'AVP'</c> field of a decoded message or Grouped AVP, the first
+alternate that succeeds in decoding the AVP setting the record's value
+field.
+At encode, values in an <c>'AVP'</c> list can be passed as AVP
+name/value 2-tuples, and it is an encode error for no alternate to
+define the AVP of such a tuple.</p>
+
+<p>
+Defaults to the empty list.</p>
+
+<note>
+<p>
+The motivation for alternate dictionaries is RFC 7683, Diameter
+Overload Indication Conveyance (DOIC), which defines AVPs to
+be piggybacked onto existing application messages rather than defining
+an application of its own.
+The DOIC dictionary is provided by the diameter application, as module
+<c>diameter_gen_doic_rfc7683</c>, but alternate dictionaries can be
+used to encode/decode any set of AVPs not known to an application
+dictionary.</p>
+</note>
+</item>
+
+<tag>
<marker id="capabilities"/><c>{capabilities, [&capability;]}</c></tag>
<item>
<p>
@@ -1075,7 +1128,7 @@ TLS is desired over TCP as implemented by &man_tcp;.</p>
</item>
<tag>
-<marker id="capabilities_cb"/><c>{capabilities_cb, &evaluable;}</c></tag>
+<marker id="capabilities_cb"/><c>{capabilities_cb, &eval;}</c></tag>
<item>
<p>
Callback invoked upon reception of CER/CEA during capabilities
@@ -1169,7 +1222,7 @@ transport.</p>
</item>
<tag>
-<marker id="disconnect_cb"/><c>{disconnect_cb, &evaluable;}</c></tag>
+<marker id="disconnect_cb"/><c>{disconnect_cb, &eval;}</c></tag>
<item>
<p>
Callback invoked prior to terminating the transport process of a
@@ -1269,6 +1322,19 @@ Defaults to 5000.</p>
</item>
<tag>
+<marker id="incoming_maxlen"/><c>{incoming_maxlen, 0..16777215}</c></tag>
+<item>
+<p>
+Bound on the expected size of incoming Diameter messages.
+Messages larger than the specified number of bytes are discarded.</p>
+
+<p>
+Defaults to <c>16777215</c>, the maximum value of the 24-bit Message
+Length field in a Diameter Header.</p>
+
+</item>
+
+<tag>
<marker id="length_errors"/><c>{length_errors, exit|handle|discard}</c></tag>
<item>
<p>
@@ -1326,7 +1392,64 @@ incoming Diameter request.
Options <c>monitor</c> and <c>link</c> are ignored.</p>
<p>
-Defaults to the list configured on the service if not specified.</p>
+Defaults to the empty list.</p>
+</item>
+
+<tag>
+<marker id="strict_capx"/><c>{strict_capx, boolean()]}</c></tag>
+<item>
+<p>
+Whether or not to enforce the RFC 6733 requirement that any message
+before capabilities exchange should close the peer connection.
+If false then unexpected messages are discarded.</p>
+
+<p>
+Defaults to true.
+Changing this results in non-standard behaviour, but can be useful in
+case peers are known to be behave badly.</p>
+</item>
+
+<tag>
+<marker id="strict_mbit"/><c>{strict_mbit, boolean()}</c></tag>
+<item>
+<p>
+Whether or not to regard an AVP setting the M-bit as erroneous when
+the command grammar in question does not explicitly allow the AVP.
+If <c>true</c> then such AVPs are regarded as 5001 errors,
+DIAMETER_AVP_UNSUPPORTED.
+If <c>false</c> then the M-bit is ignored and policing
+it becomes the receiver's responsibility.</p>
+
+<p>
+Defaults to <c>true</c>.</p>
+
+<warning>
+<p>
+RFC 6733 is unclear about the semantics of the M-bit.
+One the one hand, the CCF specification in section 3.2 documents AVP
+in a command grammar as meaning <em>any</em> arbitrary AVP; on the
+other hand, 1.3.4 states that AVPs setting the M-bit cannot be added
+to an existing command: the modified command must instead be
+placed in a new Diameter application.</p>
+<p>
+The reason for the latter is presumably interoperability:
+allowing arbitrary AVPs setting the M-bit in a command makes its
+interpretation implementation-dependent, since there's no
+guarantee that all implementations will understand the same set of
+arbitrary AVPs in the context of a given command.
+However, interpreting <c>AVP</c> in a command grammar as any
+AVP, regardless of M-bit, renders 1.3.4 meaningless, since the receiver
+can simply ignore any AVP it thinks isn't relevant, regardless of the
+sender's intent.</p>
+<p>
+Beware of confusing mandatory in the sense of the M-bit with mandatory
+in the sense of the command grammar.
+The former is a semantic requirement: that the receiver understand the
+semantics of the AVP in the context in question.
+The latter is a syntactic requirement: whether or not the AVP must
+occur in the message in question.</p>
+</warning>
+
</item>
<tag>
@@ -1742,8 +1865,8 @@ An example return value with for a client service with Origin-Host
{raddr,{127,0,0,1}},
{rport,3868},
{reuseaddr,true}]}]},
- {watchdog,{&lt;0.66.0>,{1346,171491,996448},okay}},
- {peer,{&lt;0.67.0>,{1346,171491,999906}}},
+ {watchdog,{&lt;0.66.0>,-576460736368485571,okay}},
+ {peer,{&lt;0.67.0>,-576460736357885808}},
{apps,[{0,common}]},
{caps,[{origin_host,{"client.example.com","server.example.com"}},
{origin_realm,{"example.com","example.com"}},
@@ -1823,8 +1946,8 @@ connection might look as follows.</p>
{transport_config,[{reuseaddr,true},
{ip,{127,0,0,1}},
{port,3868}]}]},
- {accept,[[{watchdog,{&lt;0.56.0>,{1346,171481,226895},okay}},
- {peer,{&lt;0.58.0>,{1346,171491,999511}}},
+ {accept,[[{watchdog,{&lt;0.56.0>,-576460739249514012,okay}},
+ {peer,{&lt;0.58.0>,-576460638229179167}},
{apps,[{0,common}]},
{caps,[{origin_host,{"server.example.com","client.example.com"}},
{origin_realm,{"example.com","example.com"}},
@@ -1853,7 +1976,7 @@ connection might look as follows.</p>
{send_max,148},
{send_avg,87},
{send_pend,0}]}]}],
- [{watchdog,{&lt;0.72.0>,{1346,171491,998404},initial}}]]},
+ [{watchdog,{&lt;0.72.0>,-576460638229717546,initial}}]]},
{statistics,[{{{0,280,0},recv},7},
{{{0,280,1},send},7},
{{{0,280,0},recv,{'Result-Code',2001}},7},
@@ -1901,8 +2024,8 @@ A return value for the server above might look as follows.</p>
{transport_config,[{reuseaddr,true},
{ip,{127,0,0,1}},
{port,3868}]}]},
- {watchdog,{&lt;0.56.0>,{1346,171481,226895},okay}},
- {peer,{&lt;0.58.0>,{1346,171491,999511}}},
+ {watchdog,{&lt;0.56.0>,-576460739249514012,okay}},
+ {peer,{&lt;0.58.0>,-576460638229179167}},
{apps,[{0,common}]},
{caps,[{origin_host,{"server.example.com","client.example.com"}},
{origin_realm,{"example.com","example.com"}},
@@ -2098,7 +2221,7 @@ Stop a diameter service.</p>
<p>
Stopping a service causes all associated transport connections to be
broken.
-A DPR message with be sent as in the case of &remove_transport;.</p>
+A DPR message will be sent as in the case of &remove_transport;.</p>
<note>
<p>
diff --git a/lib/diameter/doc/src/diameter_app.xml b/lib/diameter/doc/src/diameter_app.xml
index dfcd00975b..aa334beb21 100644
--- a/lib/diameter/doc/src/diameter_app.xml
+++ b/lib/diameter/doc/src/diameter_app.xml
@@ -13,7 +13,8 @@
<header>
<copyright>
-<year>2011</year><year>2016</year>
+<year>2011</year>
+<year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -319,7 +320,7 @@ or &peer_down; callback.</p>
<v>Action = Send | Discard | {eval_packet, Action, PostF}</v>
<v>Send = {send, &packet; | &message;}</v>
<v>Discard = {discard, Reason} | discard</v>
-<v>PostF = &mod_evaluable;}</v>
+<v>PostF = &mod_eval;}</v>
</type>
<desc>
<p>
@@ -371,7 +372,7 @@ discarded}</c>.</p>
<v>Action = Send | Discard | {eval_packet, Action, PostF}</v>
<v>Send = {send, &packet; | &message;}</v>
<v>Discard = {discard, Reason} | discard</v>
-<v>PostF = &mod_evaluable;}</v>
+<v>PostF = &mod_eval;}</v>
</type>
<desc>
<p>
@@ -478,7 +479,7 @@ not selected.</p>
| {answer_message, 3000..3999|5000..5999}
| {protocol_error, 3000..3999}</v>
<v>Opt = &mod_call_opt;</v>
-<v>PostF = &mod_evaluable;</v>
+<v>PostF = &mod_eval;</v>
</type>
<desc>
<p>
diff --git a/lib/diameter/doc/src/diameter_codec.xml b/lib/diameter/doc/src/diameter_codec.xml
index 0117c1c88a..0a34dd7ec7 100644
--- a/lib/diameter/doc/src/diameter_codec.xml
+++ b/lib/diameter/doc/src/diameter_codec.xml
@@ -4,7 +4,10 @@
'<seealso marker="diameter_dict#MESSAGE_RECORDS">diameter_dict(4)</seealso>'>
<!ENTITY types
'<seealso marker="diameter_dict#DATA_TYPES">diameter_dict(4)</seealso>'>
- <!ENTITY % also SYSTEM "seealso.ent" >
+ <!ENTITY decode_format
+ '<seealso marker="diameter#decode_format">decode format</seealso>'>
+
+<!ENTITY % also SYSTEM "seealso.ent" >
<!ENTITY % here SYSTEM "seehere.ent" >
%also;
%here;
@@ -145,7 +148,8 @@ question.</p>
<p>
The decoded value of an AVP.
Will be <c>undefined</c> on decode if the data bytes could
-not be decoded or the AVP is unknown.
+not be decoded, the AVP is unknown, or if the &decode_format; is
+<c>none</c>.
The type of a decoded value is as document in &types;.</p>
</item>
@@ -230,7 +234,8 @@ header.</p>
</item>
<tag>
-<marker id="message"/><c>message() = record() | list()</c></tag>
+<marker id="message"/><c>message() = record()
+ | maybe_improper_list()</c></tag>
<item>
<p>
The representation of a Diameter message as passed to
@@ -240,14 +245,17 @@ a message as defined in a dictionary file is encoded as a record with
one field for each component AVP.
Equivalently, a message can also be encoded as a list whose head is
the atom-valued message name (as specified in the relevant dictionary
-file) and whose tail is a list of <c>{AvpName, AvpValue}</c> pairs.</p>
+file) and whose tail is either a list of AVP name/values
+pairs or a map with values keyed on AVP names.
+The format at decode is determined by &mod_decode_format;.
+Any of the formats is accepted at encode.</p>
<p>
Another list-valued representation allows a message to be specified
as a list whose head is a &header; and whose tail is an &avp; list.
This representation is used by diameter itself when relaying requests
as directed by the return value of a &app_handle_request; callback.
-It differs from the other other two in that it bypasses the checks for
+It differs from the other two in that it bypasses the checks for
messages that do not agree with their definitions in the dictionary in
question: messages are sent exactly as specified.</p>
@@ -283,15 +291,16 @@ value other than <c>undefined</c>.</p>
<item>
<p>
The incoming/outgoing message.
-For an incoming message, a record if the message can be
-decoded in a non-relay application, <c>undefined</c> otherwise.
+For an incoming message, a term corresponding to the configured
+&decode_format; if the message can be decoded in a non-relay
+application, <c>undefined</c> otherwise.
For an outgoing message, setting a <c>[&header; | &avp;]</c> list is
equivalent to setting the <c>header</c> and <c>avps</c> fields to the
corresponding values.</p>
<warning>
<p>
-A record-valued <c>msg</c> field does <em>not</em> imply an absence of
+A value in the <c>msg</c> field does <em>not</em> imply an absence of
decode errors.
The <c>errors</c> field should also be examined.</p>
</warning>
diff --git a/lib/diameter/doc/src/diameter_dict.xml b/lib/diameter/doc/src/diameter_dict.xml
index 94016d9466..37d30b709b 100644
--- a/lib/diameter/doc/src/diameter_dict.xml
+++ b/lib/diameter/doc/src/diameter_dict.xml
@@ -486,9 +486,9 @@ will result in the following record definition given an empty
prefix.</p>
<pre>
--record('SIP-Deregistration-Reason' {'SIP-Reason-Code',
- 'SIP-Reason-Info',
- 'AVP'}).
+-record('SIP-Deregistration-Reason', {'SIP-Reason-Code',
+ 'SIP-Reason-Info',
+ 'AVP'}).
</pre>
<p>
diff --git a/lib/diameter/doc/src/diameter_sctp.xml b/lib/diameter/doc/src/diameter_sctp.xml
index 9b6d629f79..62e958870e 100644
--- a/lib/diameter/doc/src/diameter_sctp.xml
+++ b/lib/diameter/doc/src/diameter_sctp.xml
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd" [
+ <!ENTITY man_tcp_sender
+ '<seealso marker="diameter_tcp#sender">diameter_tcp(3)</seealso>'>
<!ENTITY gen_sctp '<seealso marker="kernel:gen_sctp">gen_sctp(3)</seealso>'>
<!ENTITY gen_sctp_open1
'<seealso marker="kernel:gen_sctp#open-1">gen_sctp:open/1</seealso>'>
@@ -16,7 +18,7 @@
<header>
<copyright>
<year>2011</year>
-<year>2016</year>
+<year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -78,7 +80,11 @@ and implements the behaviour documented in
<v>Reason = term()</v>
<v>OwnOpt = {raddr, &ip_address;}
| {rport, integer()}
- | {accept, Match}</v>
+ | {accept, Match}
+ | {unordered, boolean() | pos_integer()}
+ | {packet, boolean() | raw}
+ | {message_cb, &mod_eval;}
+ | {sender, boolean()}</v>
<v>SctpOpt = term()</v>
<v>Match = &ip_address; | string() | [Match]</v>
</type>
@@ -106,6 +112,41 @@ A string-valued <c>Match</c> that does not parse as an address is
interpreted as a regular expression.</p>
<p>
+Option <c>unordered</c> specifies whether or not to use unordered
+delivery, integer <c>N</c> being equivalent to <c>N =&lt; OS</c>,
+where <c>OS</c> is the number of outbound streams negotiated on the
+association in question.
+Regardless of configuration, sending is ordered on stream 0
+until reception of a second incoming message, to ensure that a peer
+receives capabilities exchange messages before any other.
+Defaults to <c>false</c>.</p>
+
+<p>
+Option <c>packet</c> determines how/if an incoming message is
+packaged into a diameter_packet record.
+If <c>false</c> then messages are received as binary().
+If <c>true</c> then as a record with the binary() message in the
+<c>bin</c> field and a <c>{stream, Id}</c> tuple in the
+<c>transport_data</c> field, where <c>Id</c> is the identifier of the
+inbound stream the message was received on.
+If <c>raw</c> then as a record with the received ancillary
+sctp_sndrcvinfo record in the <c>transport_data</c> field.
+Defaults to <c>true</c>.</p>
+
+<p>
+Options <c>message_cb</c> and <c>sender</c> have semantics identical
+to those documented in &man_tcp_sender;, but with the message argument
+to a <c>recv</c> callback being as directed by the <c>packet</c>
+option.</p>
+
+<p>
+An <c>{outstream, Id}</c> tuple in the <c>transport_data</c> field of
+a outgoing diameter_packet record sets the outbound stream on which
+the message is sent, modulo the negotiated number of outbound streams.
+Any other value causes successive such sends to cycle though all
+outbound streams.</p>
+
+<p>
Remaining options are any accepted by &gen_sctp_open1;, with the exception
of options <c>mode</c>, <c>binary</c>, <c>list</c>, <c>active</c>
and <c>sctp_events</c>.
@@ -116,35 +157,21 @@ and port respectively.</p>
Multiple <c>ip</c> options can be specified for a multihomed peer.
If none are specified then the values of <c>Host-IP-Address</c>
in the <c>diameter_service</c> record are used.
-(In particular, one of these must be specified.)
Option <c>port</c> defaults to 3868 for a listening transport and 0 for a
connecting transport.</p>
<warning>
<p>
-An insufficiently large receive buffer may result in a peer having to
+An small receive buffer may result in a peer having to
resend incoming messages: set the &inet; option <c>recbuf</c> to increase
the buffer size.</p>
<p>
-An insufficiently large send buffer may result in outgoing messages
+An small send buffer may result in outgoing messages
being discarded: set the &inet; option <c>sndbuf</c> to increase
the buffer size.</p>
</warning>
-<p>
-The <c>transport_data</c> field of record <c>diameter_packet</c>
-is used to communicate the stream on which an inbound message
-has been received, or on which an outbound message should be sent.
-The value will be of the form <c>{stream, Id}</c> for an inbound
-message passed to a &app_handle_request; or &app_handle_answer;
-callback.
-For an outbound message, <c>{outstream, Id}</c> in the return value of
-&app_handle_request; or &app_prepare_retransmit; sets the outbound
-stream, the stream id being interpreted modulo the number of outbound
-streams.
-Any other value, or not setting a value, causes successive such sends
-to cycle though all outbound streams.</p>
</desc>
</func>
diff --git a/lib/diameter/doc/src/diameter_soc.xml b/lib/diameter/doc/src/diameter_soc.xml
index ae404fcda4..2d2d66a243 100644
--- a/lib/diameter/doc/src/diameter_soc.xml
+++ b/lib/diameter/doc/src/diameter_soc.xml
@@ -1,15 +1,22 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd" [
+ <!ENTITY gen_sctp '<seealso marker="kernel:gen_sctp">gen_sctp(3)</seealso>'>
+ <!ENTITY gen_tcp '<seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso>'>
+ <!ENTITY service '<seealso marker="diameter#start_service-2">service</seealso>'>
+ <!ENTITY capabilities '<seealso marker="diameter#capability">capabilities</seealso>'>
+ <!ENTITY events '<seealso marker="diameter#service_event">events</seealso>'>
+ <!ENTITY NA '&#8212;'>
+ <!ENTITY BR '<br/>&nbsp;<br/>'>
<!ENTITY % also SYSTEM "seealso.ent" >
%also;
]>
-<chapter xmlns:xi="http://www.w3.org/2001/XInclude">
+<chapter>
<header>
<copyright>
<year>2011</year>
-<year>2016</year>
+<year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
@@ -41,63 +48,1285 @@ limitations under the License.
</header>
<p>
-Known points of questionable or non-compliance.</p>
+The table below summarizes the diameter application's compliance with
+&the_rfc;.
+Since the diameter application isn't a Diameter node on its own,
+compliance is strictly the responsibility of the user in many cases,
+diameter providing the means for the user to be compliant
+rather than being compliant on its own.</p>
-<!-- ===================================================================== -->
-
-<section>
-<title>&the_rfc;</title>
-
-<list>
-
-<item>
-<p>
-There is no support for DTLS over SCTP.</p>
-</item>
-
-<item>
<p>
-There is no explicit support for peer discovery (section 5.2).
-It can possibly be implemented on top of diameter as is but this is
-probably something that diameter should do.</p>
-</item>
+The Compliance column notes <em>C</em> (Compliant) if the required
+functionality is implemented, <em>PC</em> (Partially Compliant) if
+there are limitations, <em>NC</em> (Not Compliant) if functionality is
+not implemented, or a dash if text is informational or only places
+requirements that must be met by the user's implementation.</p>
-<item>
<p>
-The peer state machine's election process (section 5.6.4) isn't
-implemented as specified since it assumes knowledge of a
-peer's Origin-Host before sending it a CER. (The identity becoming known
-upon reception of CEA.)
-The possibility of configuring
-the peer's Origin-Host could be added, along with handling of the case
-that it sends something else, but for many applications this will
-just be unnecessary configuration of a value that it has no control over.</p>
-</item>
-<!-- Transport protocol plus address/port, which we do know when
- sending and receiving CER, is enough to definitely identify
- the peer. However, there's nothing stopping a peer from using
- different identities on different transport protocols, even
- if it's maybe a bit far-fetched. -->
-
-</list>
-
-<xi:include href="diameter_soc_rfc6733.xml"/>
-
-</section>
+Capitalized <em>Diameter</em> refers to the protocol, lowercase
+<em>diameter</em> to the Erlang application.</p>
<!-- ===================================================================== -->
<section>
-<title>RFC 3539</title>
+<title>&the_rfc; - Diameter Base Protocol</title>
-<p>
-RFC 3539 is more difficult to comply to since it discusses
-problems as much as it requires functionality but all the MUST's are
-covered, the watchdog state machine being the primary one.
-Of the optional functionality, load balancing is left to the
-diameter user (since it's the one deciding who to send to) and
-there is no Congestion Manager.</p>
+<table>
+<row>
+ <cell><em>Section</em></cell>
+ <cell><em>Title</em></cell>
+ <cell><em>Compliance</em></cell>
+ <cell><em>Notes</em></cell>
+</row>
+<row>
+ <cell>1</cell>
+ <cell>Introduction</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>1.1</cell>
+ <cell>Diameter Protocol</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>1.1.1</cell>
+ <cell>Description of the Document Set</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>1.1.2</cell>
+ <cell>Conventions Used in This Document</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>1.1.3</cell>
+ <cell>Changes from RFC 3588</cell>
+ <cell>&NA;</cell>
+ <cell>It is possible to configure a 3588 dictionary in
+ order to get 3588 semantics, where the differ from 6733.</cell>
+</row>
+<row>
+ <cell>1.2</cell>
+ <cell>Terminology</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>1.3</cell>
+ <cell>Approach to Extensibility</cell>
+ <cell>&NA;</cell>
+ <cell>The dictionary interface documented in &man_dict; provides
+ extensibility, allowing the user to defined new AVPs, commands, and
+ applications.
+ Ready dictionaries are provided for the &the_rfc; common message, base
+ accounting, and relay applications, as well as for RFC 7683,
+ Diameter Overload Indicator Conveyance.</cell>
+</row>
+<row>
+ <cell>1.3.1</cell>
+ <cell>Defining New AVP Values</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>1.3.2</cell>
+ <cell>Creating New AVPs</cell>
+ <cell>&NA;</cell>
+ <cell>New AVPs can be defined using the dictionary interface.
+ Both RFC data formats and extensions are supported.</cell>
+</row>
+<row>
+ <cell>1.3.3</cell>
+ <cell>Creating New Commands</cell>
+ <cell>&NA;</cell>
+ <cell>New commands can be defined using the dictionary interface.</cell>
+</row>
+<row>
+ <cell>1.3.4</cell>
+ <cell>Creating New Diameter Applications</cell>
+ <cell>&NA;</cell>
+ <cell>New applications can be defined using the dictionary interface.</cell>
+</row>
+<row>
+ <cell>2</cell>
+ <cell>Protocol Overview</cell>
+ <cell>&NA;</cell>
+ <cell>Session state is the responsibility of the user.&BR;
+ The role of a Diameter node is determined by the user's
+ implementation.</cell>
+</row>
+<row>
+ <cell>2.1</cell>
+ <cell>Transport</cell>
+ <cell>PC</cell>
+ <cell>Ports are configured by the user: diameter places no
+ restrictions.&BR;
+ The transport interface documented in &man_transport;
+ allows the user to implement their own methods.
+ Ready support is provided for TCP, TCP/TLS, and SCTP, but not
+ DTLS/SCTP.&BR;
+ Multiple connections to the same peer is possible.
+ ICMP messages are not interpreted.</cell>
+</row>
+<row>
+ <cell>2.1.1</cell>
+ <cell>SCTP Guidelines</cell>
+ <cell>C</cell>
+ <cell>Unordered sending is configurable in &man_sctp;.
+ There is no special handling of DPR/DPA: since a user that cares
+ about pending answers should wait for them before initiating
+ DPR.&BR;
+ A PPID can be configured with a a gen_sctp sctp_default_send_param
+ option.</cell>
+</row>
+<row>
+ <cell>2.2</cell>
+ <cell>Securing Diameter Messages</cell>
+ <cell>PC</cell>
+ <cell>DTLS is not supported by &man_sctp;. See also
+ 2.1.</cell>
+</row>
+<row>
+ <cell>2.3</cell>
+ <cell>Diameter Application Compliance</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>2.4</cell>
+ <cell>Application Identifiers</cell>
+ <cell>C</cell>
+ <cell>The user configures diameter with the identifiers to send at
+ capabilities exchange, along with corresponding dictionaries
+ defining the messages of the applications.</cell>
+</row>
+<row>
+ <cell>2.5</cell>
+ <cell>Connections vs. Sessions</cell>
+ <cell>C</cell>
+ <cell>Connections are realized by configuring transport. Sessions
+ are the responsibility of the user.</cell>
+</row>
+<row>
+ <cell>2.6</cell>
+ <cell>Peer Table</cell>
+ <cell>PC</cell>
+ <cell>Routing is implemented by the user in callbacks documented in
+ &man_app;.
+ A peer table of the documented form is not exposed to the user.</cell>
+</row>
+<row>
+ <cell>2.7</cell>
+ <cell>Routing Table</cell>
+ <cell>PC</cell>
+ <cell>See 2.6.
+ A routing table of the documented form is not exposed to
+ the user.</cell>
+</row>
+<row>
+ <cell>2.8</cell>
+ <cell>Role of Diameter Agents</cell>
+ <cell>C</cell>
+ <cell>Most role-specific behaviour is implemented by the user.
+ How a node advertises itself at capabilities exchange is determined
+ by user configuration.</cell>
+</row>
+<row>
+ <cell>2.8.1</cell>
+ <cell>Relay Agents</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>2.8.2</cell>
+ <cell>Proxy Agents</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>2.8.3</cell>
+ <cell>Redirect Agents</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>2.8.4</cell>
+ <cell>Translation Agents</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>2.9</cell>
+ <cell>Diameter Path Authorization</cell>
+ <cell>&NA;</cell>
+ <cell>Authorization is the responsibility of the user.</cell>
+</row>
+<row>
+ <cell>3</cell>
+ <cell>Diameter Header</cell>
+ <cell>C</cell>
+ <cell>Hop-by-Hop and End-to-End Identifiers are set by diameter when
+ sending outgoing requests.</cell>
+</row>
+<row>
+ <cell>3.1</cell>
+ <cell>Command Codes</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>3.2</cell>
+ <cell>Command Code Format Specification</cell>
+ <cell>C</cell>
+ <cell>Commands are defined as CCF specifications in dictionary
+ files.</cell>
+</row>
+<row>
+ <cell>3.3</cell>
+ <cell>Diameter Command Naming Conventions</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>4</cell>
+ <cell>Diameter AVPs</cell>
+ <cell>C</cell>
+ <cell>Any required padding is added by diameter when encoding
+ outgoing messages.</cell>
+</row>
+<row>
+ <cell>4.1</cell>
+ <cell>AVP Header</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>4.1.1</cell>
+ <cell>Optional Header Elements</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>4.2</cell>
+ <cell>Basic AVP Data Formats</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>4.3</cell>
+ <cell>Derived AVP Data Formats</cell>
+ <cell>C</cell>
+ <cell>Arbitrary derived data formats are supported by the dictionary
+ interface.</cell>
+</row>
+<row>
+ <cell>4.3.1</cell>
+ <cell>Common Derived AVP Data Formats</cell>
+ <cell>C</cell>
+ <cell>Beware that RFC 6733 changed the DiameterURI transport/port
+ defaults specified in RFC3588.
+ Relying on the defaults can result in interoperability
+ problems.</cell>
+</row>
+<row>
+ <cell>4.4</cell>
+ <cell>Grouped AVP Values</cell>
+ <cell>C</cell>
+ <cell>The M-bit on a component AVP of a Grouped AVP that does not
+ set M is ignored: such AVPs are not regarded as erroneous at
+ decode.&BR;
+ Grouped AVPs are defined as CCF specifications in dictionary
+ files.</cell>
+</row>
+<row>
+ <cell>4.4.1</cell>
+ <cell>Example AVP with a Grouped Data Type</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>4.5</cell>
+ <cell>Diameter Base Protocol AVPs</cell>
+ <cell>C</cell>
+ <cell>The base AVPs are defined in the common dictionary provided by
+ diameter.
+ There are common dictionaries for both RFC 3588 and RFC 6733 since
+ the latter made changes to both syntax and semantics.</cell>
+</row>
+<row>
+ <cell>5</cell>
+ <cell>Diameter Peers</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>5.1</cell>
+ <cell>Peer Connections</cell>
+ <cell>PC</cell>
+ <cell>A peer's DiameterIdentity is not required when initiating a
+ connection: the identify is received at capabilities exchange, at
+ which time the connection can be rejected if the identity is
+ objectionable.&BR;
+ The number of connections established depends on the user's
+ configuration. Multiple connections per peer is possible.</cell>
+</row>
+<row>
+ <cell>5.2</cell>
+ <cell>Diameter Peer Discovery</cell>
+ <cell>NC</cell>
+ <cell>No form of peer discovery is implemented.
+ The user can implement this independently of diameter if
+ required.</cell>
+</row>
+<row>
+ <cell>5.3</cell>
+ <cell>Capabilities Exchange</cell>
+ <cell>C</cell>
+ <cell>All supported applications are sent in CEA.
+ The user can reject an incoming CER or CEA in a configured
+ callback.&BR;
+ Both transport security at connection establishment and
+ negotiated via an Inband-Security AVP are supported.</cell>
+</row>
+<row>
+ <cell>5.3.1</cell>
+ <cell>Capabilities-Exchange-Request</cell>
+ <cell>C</cell>
+ <cell>CER is sent and received by diameter.</cell>
+</row>
+<row>
+ <cell>5.3.2</cell>
+ <cell>Capabilities-Exchange-Answer</cell>
+ <cell>C</cell>
+ <cell>CEA is sent and received by diameter.</cell>
+</row>
+<row>
+ <cell>5.3.3</cell>
+ <cell>Vendor-Id AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>5.3.4</cell>
+ <cell>Firmware-Revision AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>5.3.5</cell>
+ <cell>Host-IP-Address AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>5.3.6</cell>
+ <cell>Supported-Vendor-Id AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>5.3.7</cell>
+ <cell>Product-Name AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>5.4</cell>
+ <cell>Disconnecting Peer Connections</cell>
+ <cell>C</cell>
+ <cell>DPA will not be answered with error: a peer that wants to a
+ avoid a race can wait for pending answers before sending
+ DPR.</cell>
+</row>
+<row>
+ <cell>5.4.1</cell>
+ <cell>Disconnect-Peer-Request</cell>
+ <cell>C</cell>
+ <cell>DPR is sent by diameter in response to configuration
+ changes requiring a connection to be broken.
+ The user can also send DPR.</cell>
+</row>
+<row>
+ <cell>5.4.2</cell>
+ <cell>Disconnect-Peer-Answer</cell>
+ <cell>C</cell>
+ <cell>DPR is answered by diameter.</cell>
+</row>
+<row>
+ <cell>5.4.3</cell>
+ <cell>Disconnect-Cause AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>5.5</cell>
+ <cell>Transport Failure Detection</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>5.5.1</cell>
+ <cell>Device-Watchdog-Request</cell>
+ <cell>C</cell>
+ <cell>DWR is sent and received by diameter.
+ Callbacks notify the user of transitions into and out of the OKAY
+ state.</cell>
+</row>
+<row>
+ <cell>5.5.2</cell>
+ <cell>Device-Watchdog-Answer</cell>
+ <cell>C</cell>
+ <cell>DWA is sent and received by diameter.</cell>
+</row>
+<row>
+ <cell>5.5.3</cell>
+ <cell>Transport Failure Algorithm</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>5.5.4</cell>
+ <cell>Failover and Failback Procedures</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>5.6</cell>
+ <cell>Peer State Machine</cell>
+ <cell>PC</cell>
+ <cell>The election process is modified as described in 5.6.4.</cell>
+</row>
+<row>
+ <cell>5.6.1</cell>
+ <cell>Incoming Connections</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>5.6.2</cell>
+ <cell>Events</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>5.6.3</cell>
+ <cell>Actions</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>5.6.4</cell>
+ <cell>The Election Process</cell>
+ <cell>PC</cell>
+ <cell>As documented, the election assumes knowledge of a peer's
+ DiameterIdentity when initiating a connection, which diameter
+ doesn't require. Connections will be accepted if configuration
+ allows multiple connections per peer to be established or there is
+ no existing connection. Note that the election process is only
+ applicable when multiple connections per peer is
+ disallowed.</cell>
+</row>
+<row>
+ <cell>6</cell>
+ <cell>Diameter Message Processing</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>6.1</cell>
+ <cell>Diameter Request Routing Overview</cell>
+ <cell>&NA;</cell>
+ <cell>Routing is performed by the user.
+ A callback from diameter provides a list of available suitable peer
+ connections.</cell>
+</row>
+<row>
+ <cell>6.1.1</cell>
+ <cell>Originating a Request</cell>
+ <cell>C</cell>
+ <cell>Requests are constructed by the user; diameter sets header
+ fields as defined in the relevant dictionary.</cell>
+</row>
+<row>
+ <cell>6.1.2</cell>
+ <cell>Sending a Request</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>6.1.3</cell>
+ <cell>Receiving Requests</cell>
+ <cell>C</cell>
+ <cell>Loops are detected by diameter when the return value of a
+ request callback asks that a request be forwarded.
+ Loop detection in other cases is the responsibility of the
+ user.</cell>
+</row>
+<row>
+ <cell>6.1.4</cell>
+ <cell>Processing Local Requests</cell>
+ <cell>C</cell>
+ <cell>The user decides whether or not to process a request locally
+ in the request callback from diameter.</cell>
+</row>
+<row>
+ <cell>6.1.5</cell>
+ <cell>Request Forwarding</cell>
+ <cell>PC</cell>
+ <cell>See 2.6.</cell>
+</row>
+<row>
+ <cell>6.1.6</cell>
+ <cell>Request Routing</cell>
+ <cell>PC</cell>
+ <cell>See 2.7.</cell>
+</row>
+<row>
+ <cell>6.1.7</cell>
+ <cell>Predictive Loop Avoidance</cell>
+ <cell>C</cell>
+ <cell>See 6.1.3.</cell>
+</row>
+<row>
+ <cell>6.1.8</cell>
+ <cell>Redirecting Requests</cell>
+ <cell>PC</cell>
+ <cell>See 2.6.</cell>
+</row>
+<row>
+ <cell>6.1.9</cell>
+ <cell>Relaying and Proxying Requests</cell>
+ <cell>C</cell>
+ <cell>A Route-Record AVP is appended by diameter when the return
+ value of a request callback asks that a request be forwarded.
+ Appending the AVP in other cases is the responsibility of the
+ user.</cell>
+</row>
+<row>
+ <cell>6.2</cell>
+ <cell>Diameter Answer Processing</cell>
+ <cell>C</cell>
+ <cell>Answer message are constructed by the user, except in the case
+ of some protocol errors, in which case the procedures are
+ followed.</cell>
+</row>
+<row>
+ <cell>6.2.1</cell>
+ <cell>Processing Received Answers</cell>
+ <cell>C</cell>
+ <cell>Answers with an unknown Hop-by-Hop Identifier are
+ discarded.</cell>
+</row>
+<row>
+ <cell>6.2.2</cell>
+ <cell>Relaying and Proxying Answers</cell>
+ <cell>&NA;</cell>
+ <cell>Modifying answers is the responsibility of the user in
+ callbacks from diameter.</cell>
+</row>
+<row>
+ <cell>6.3</cell>
+ <cell>Origin-Host AVP</cell>
+ <cell>C</cell>
+ <cell>The order of AVPs in an encoded message is determined by
+ the CCF of the message in question.&BR;
+ AVPs defined in the RFC are defined in dictionaries provided by
+ diameter.
+ Their proper use in application messages is the responsibility of
+ the user.</cell>
+</row>
+<row>
+ <cell>6.4</cell>
+ <cell>Origin-Realm AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>6.5</cell>
+ <cell>Destination-Host AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>6.6</cell>
+ <cell>Destination-Realm AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>6.7</cell>
+ <cell>Routing AVPs</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>6.7.1</cell>
+ <cell>Route-Record AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>6.7.2</cell>
+ <cell>Proxy-Info AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>6.7.3</cell>
+ <cell>Proxy-Host AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>6.7.4</cell>
+ <cell>Proxy-State AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>6.8</cell>
+ <cell>Auth-Application-Id AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>6.9</cell>
+ <cell>Acct-Application-Id AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>6.10</cell>
+ <cell>Inband-Security-Id AVP</cell>
+ <cell>C</cell>
+ <cell>See 2.1.</cell>
+</row>
+<row>
+ <cell>6.11</cell>
+ <cell>Vendor-Specific-Application-Id AVP</cell>
+ <cell>C</cell>
+ <cell>Note that the CCF of this AVP is not the same as in RFC
+ 3588.</cell>
+</row>
+<row>
+ <cell>6.12</cell>
+ <cell>Redirect-Host AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>6.13</cell>
+ <cell>Redirect-Host-Usage AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>6.14</cell>
+ <cell>Redirect-Max-Cache-Time AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>7</cell>
+ <cell>Error Handling</cell>
+ <cell>C</cell>
+ <cell>Answers are formulated by the user in most cases.
+ Answers setting the E-bit can be sent by diameter itself in response
+ to a request that cannot be handled by the user.</cell>
+</row>
+<row>
+ <cell>7.1</cell>
+ <cell>Result-Code AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>7.1.1</cell>
+ <cell>Informational</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>7.1.2</cell>
+ <cell>Success</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>7.1.3</cell>
+ <cell>Protocol Errors</cell>
+ <cell>C</cell>
+ <cell>Result codes 3001, 3002, 3005, and 3007 can be sent in answers
+ formulated by diameter, if configured to do so.</cell>
+</row>
+<row>
+ <cell>7.1.4</cell>
+ <cell>Transient Failures</cell>
+ <cell>C</cell>
+ <cell>Result code 4003 is sent in CEA if there is an existing
+ connection to the peer in question and configuration does not allow
+ more than one.</cell>
+</row>
+<row>
+ <cell>7.1.5</cell>
+ <cell>Permanent Failures</cell>
+ <cell>C</cell>
+ <cell>Message reception detects 5001, 5004,
+ 5005, 5008, 5009, 5010, 5011, 5014, 5015, and 5017 errors.
+ It ignores 5013 errors at the admonition of sections 3 and 4.1.&BR;
+ Note that RFC 3588 did not allow 5xxx result codes in
+ answers setting the E-bit, while RFC 6733 does.
+ This is a potential interoperability problem since the Diameter
+ protocol version has not changed.</cell>
+</row>
+<row>
+ <cell>7.2</cell>
+ <cell>Error Bit</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>7.3</cell>
+ <cell>Error-Message AVP</cell>
+ <cell>C</cell>
+ <cell>The user can include this AVP as required.</cell>
+</row>
+<row>
+ <cell>7.4</cell>
+ <cell>Error-Reporting-Host AVP</cell>
+ <cell>C</cell>
+ <cell>The user can include this AVP as required.</cell>
+</row>
+<row>
+ <cell>7.5</cell>
+ <cell>Failed-AVP AVP</cell>
+ <cell>C</cell>
+ <cell>The user constructs application-specific messages, but
+ diameter provides failed AVPs in message callbacks. Failed component AVPs
+ are grouped within the relevant Grouped AVPs.</cell>
+</row>
+<row>
+ <cell>7.6</cell>
+ <cell>Experimental-Result AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>7.7</cell>
+ <cell>Experimental-Result-Code AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8</cell>
+ <cell>Diameter User Sessions</cell>
+ <cell>&NA;</cell>
+ <cell>Authorization and accounting AVPs are defined in provided
+ dictionaries. Their proper use is the responsibility of the
+ user.</cell>
+</row>
+<row>
+ <cell>8.1</cell>
+ <cell>Authorization Session State Machine</cell>
+ <cell>&NA;</cell>
+ <cell>Authorization is the responsibility of the user: diameter does
+ not implement this state machine.</cell>
+</row>
+<row>
+ <cell>8.2</cell>
+ <cell>Accounting Session State Machine</cell>
+ <cell>&NA;</cell>
+ <cell>Accounting is the responsibility of the user: diameter does
+ not implement this state machine.</cell>
+</row>
+<row>
+ <cell>8.3</cell>
+ <cell>Server-Initiated Re-Auth</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.3.1</cell>
+ <cell>Re-Auth-Request</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.3.2</cell>
+ <cell>Re-Auth-Answer</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.4</cell>
+ <cell>Session Termination</cell>
+ <cell>&NA;</cell>
+ <cell>Session-related messages and AVPs are defined in provided
+ dictionaries. Their proper use is the user's responsibility.</cell>
+</row>
+<row>
+ <cell>8.4.1</cell>
+ <cell>Session-Termination-Request</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.4.2</cell>
+ <cell>Session-Termination-Answer</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.5</cell>
+ <cell>Aborting a Session</cell>
+ <cell>&NA;</cell>
+ <cell>Session-related messages and AVPs are defined in provided
+ dictionaries. Their proper use is the user's responsibility.</cell>
+</row>
+<row>
+ <cell>8.5.1</cell>
+ <cell>Abort-Session-Request</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.5.2</cell>
+ <cell>Abort-Session-Answer</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.6</cell>
+ <cell>Inferring Session Termination from Origin-State-Id</cell>
+ <cell>&NA;</cell>
+ <cell>Session-related messages and AVPs are defined in provided
+ dictionaries. Their proper use is the user's responsibility.</cell>
+</row>
+<row>
+ <cell>8.7</cell>
+ <cell>Auth-Request-Type AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.8</cell>
+ <cell>Session-Id AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.9</cell>
+ <cell>Authorization-Lifetime AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.10</cell>
+ <cell>Auth-Grace-Period AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.11</cell>
+ <cell>Auth-Session-State AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.12</cell>
+ <cell>Re-Auth-Request-Type AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.13</cell>
+ <cell>Session-Timeout AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.14</cell>
+ <cell>User-Name AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.15</cell>
+ <cell>Termination-Cause AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.16</cell>
+ <cell>Origin-State-Id AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.17</cell>
+ <cell>Session-Binding AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.18</cell>
+ <cell>Session-Server-Failover AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.19</cell>
+ <cell>Multi-Round-Time-Out AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.20</cell>
+ <cell>Class AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>8.21</cell>
+ <cell>Event-Timestamp AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>9</cell>
+ <cell>Accounting</cell>
+ <cell>&NA;</cell>
+ <cell>Accounting-related messages and AVPs are defined in provided
+ dictionaries. Their proper use is the user's responsibility.</cell>
+</row>
+<row>
+ <cell>9.1</cell>
+ <cell>Server Directed Model</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>9.2</cell>
+ <cell>Protocol Messages</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>9.3</cell>
+ <cell>Accounting Application Extension and Requirements</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>9.4</cell>
+ <cell>Fault Resilience</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>9.5</cell>
+ <cell>Accounting Records</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>9.6</cell>
+ <cell>Correlation of Accounting Records</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>9.7</cell>
+ <cell>Accounting Command Codes</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>9.7.1</cell>
+ <cell>Accounting-Request</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>9.7.2</cell>
+ <cell>Accounting-Answer</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>9.8</cell>
+ <cell>Accounting AVPs</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>9.8.1</cell>
+ <cell>Accounting-Record-Type AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>9.8.2</cell>
+ <cell>Acct-Interim-Interval AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>9.8.3</cell>
+ <cell>Accounting-Record-Number AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>9.8.4</cell>
+ <cell>Acct-Session-Id AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>9.8.5</cell>
+ <cell>Acct-Multi-Session-Id AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>9.8.6</cell>
+ <cell>Accounting-Sub-Session-Id AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>9.8.7</cell>
+ <cell>Accounting-Realtime-Required AVP</cell>
+ <cell>C</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>10</cell>
+ <cell>AVP Occurrence Tables</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>10.1</cell>
+ <cell>Base Protocol Command AVP Table</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>10.2</cell>
+ <cell>Accounting AVP Table</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11</cell>
+ <cell>IANA Considerations</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.1</cell>
+ <cell>AVP Header</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.1.1</cell>
+ <cell>AVP Codes</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.1.2</cell>
+ <cell>AVP Flags</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.2</cell>
+ <cell>Diameter Header</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.2.1</cell>
+ <cell>Command Codes</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.2.2</cell>
+ <cell>Command Flags</cell>
+ <cell></cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.3</cell>
+ <cell>AVP Values</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.3.1</cell>
+ <cell>Experimental-Result-Code AVP</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.3.2</cell>
+ <cell>Result-Code AVP Values</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.3.3</cell>
+ <cell>Accounting-Record-Type AVP Values</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.3.4</cell>
+ <cell>Termination-Cause AVP Values</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.3.5</cell>
+ <cell>Redirect-Host-Usage AVP Values</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.3.6</cell>
+ <cell>Session-Server-Failover AVP Values</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.3.7</cell>
+ <cell>Session-Binding AVP Values</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.3.8</cell>
+ <cell>Disconnect-Cause AVP Values</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.3.9</cell>
+ <cell>Auth-Request-Type AVP Values</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.3.10</cell>
+ <cell>Auth-Session-State AVP Values</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.3.11</cell>
+ <cell>Re-Auth-Request-Type AVP Values</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.3.12</cell>
+ <cell>Accounting-Realtime-Required AVP Values</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.3.13</cell>
+ <cell>Inband-Security-Id AVP (code 299)</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.4</cell>
+ <cell>_diameters Service Name and Port Number Registration</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.5</cell>
+ <cell>SCTP Payload Protocol Identifiers</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>11.6</cell>
+ <cell>S-NAPTR Parameters</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>12</cell>
+ <cell>Diameter Protocol-Related Configurable Parameters</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>13</cell>
+ <cell>Security Considerations</cell>
+ <cell>PC</cell>
+ <cell>See 2.1.&BR;
+ IPsec is transparent to diameter.</cell>
+</row>
+<row>
+ <cell>13.1</cell>
+ <cell>TLS/TCP and DTLS/SCTP Usage</cell>
+ <cell>PC</cell>
+ <cell>See 2.1.</cell>
+</row>
+<row>
+ <cell>13.2</cell>
+ <cell>Peer-to-Peer Considerations</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>13.3</cell>
+ <cell>AVP Considerations</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>14</cell>
+ <cell>References</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>14.1</cell>
+ <cell>Normative References</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+<row>
+ <cell>14.2</cell>
+ <cell>Informative References</cell>
+ <cell>&NA;</cell>
+ <cell></cell>
+</row>
+
+<tcaption>RFC 6733 Compliance</tcaption>
+</table>
</section>
</chapter>
+
+<!-- LocalWords: AVP AVPs CCF DiameterIdentity CEA CER Inband IP
+-->
+<!-- LocalWords: DPA DPR DWR DWA Failover Failback Proxying Auth
+-->
+<!-- LocalWords: interoperability Multi Timestamp Realtime
+-->
diff --git a/lib/diameter/doc/src/diameter_soc_rfc6733.xml b/lib/diameter/doc/src/diameter_soc_rfc6733.xml
deleted file mode 100644
index 2098965706..0000000000
--- a/lib/diameter/doc/src/diameter_soc_rfc6733.xml
+++ /dev/null
@@ -1,8693 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-
-<!--
-
-<copyright>
-<year>2013</year><year>2016</year>
-<holder>Ericsson AB. All Rights Reserved.</holder>
-</copyright>
-
-<legalnotice>
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-</legalnotice>
-
--->
-
-<!DOCTYPE section SYSTEM "chapter.dtd" [
- <!ENTITY gen_sctp '<seealso marker="kernel:gen_sctp">gen_sctp(3)</seealso>'>
- <!ENTITY gen_tcp '<seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso>'>
- <!ENTITY service '<seealso marker="diameter#start_service-2">service</seealso>'>
- <!ENTITY capabilities '<seealso marker="diameter#capability">capabilities</seealso>'>
- <!ENTITY events '<seealso marker="diameter#service_event">events</seealso>'>
- <!ENTITY nada '<p>No comment.</p>'>
- <!ENTITY % also SYSTEM "seealso.ent" >
- %also;
-]>
-
-<section>
-<title>Commentary</title>
-
-<p>
-A more detailed commentary on &the_rfc; follows.
-Its purpose is to (hopefully) clarify not only what is supported but
-how, given that semantics and features discussed in the RFC are not
-solely the responsibility of the diameter application:
-in many cases much depends on the configuration a user passes to
-diameter, the implementation of &man_app; callback modules in
-particular.</p>
-
-<p>
-Comments apply to all text following the preceding comment.
-Be sure to distinguish between capitalized <em>Diameter</em>, the
-protocol defined by the RFC, and lowercase <em>diameter</em>, the
-Erlang application to which the commentary applies.</p>
-
-<warning>
-<p>
-The commentary is not yet complete.
-Comments currently stop at chapter 4.</p>
-</warning>
-
-<pre>
-Fajardo, et al. Standards Track [Page 6]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-1. Introduction
-
- Authentication, Authorization, and Accounting (AAA) protocols such as
- TACACS [RFC1492] and RADIUS [RFC2865] were initially deployed to
- provide dial-up PPP [RFC1661] and terminal server access. Over time,
- AAA support was needed on many new access technologies, the scale and
- complexity of AAA networks grew, and AAA was also used on new
- applications (such as voice over IP). This led to new demands on AAA
- protocols.
-</pre>
-
-<p>
-Note that diameter implements the Diameter protocol as defined in
-&the_rfc;.
-It also supported the previous version of the protocol, as defined in
-RFC 3588, when there are differences.
-(Which will be noted below.)
-It does not support RADIUS.</p>
-
-<pre>
-
- Network access requirements for AAA protocols are summarized in
- Aboba, et al. [RFC2989]. These include:
-
- Failover
-
- [RFC2865] does not define failover mechanisms and, as a result,
- failover behavior differs between implementations. In order to
- provide well-defined failover behavior, Diameter supports
- application-layer acknowledgements and defines failover algorithms
- and the associated state machine.
-</pre>
-
-&nada;
-
-<pre>
-
- Transmission-level security
-
- RADIUS [RFC2865] defines an application-layer authentication and
- integrity scheme that is required only for use with response
- packets. While [RFC2869] defines an additional authentication and
- integrity mechanism, use is only required during Extensible
- Authentication Protocol (EAP) [RFC3748] sessions. While attribute
- hiding is supported, [RFC2865] does not provide support for per-
- packet confidentiality. In accounting, [RFC2866] assumes that
- replay protection is provided by the backend billing server rather
- than within the protocol itself.
-
- While [RFC3162] defines the use of IPsec with RADIUS, support for
- IPsec is not required. In order to provide universal support for
- transmission-level security, and enable both intra- and inter-
- domain AAA deployments, Diameter provides support for TLS/TCP and
- DTLS/SCTP. Security is discussed in Section 13.
-</pre>
-
-<p>
-Whether or not IPsec is used is transparent to diameter.</p>
-
-<p>
-The transport protocol used on a given peer connection is also
-transparent to diameter in that transport to diameter is simply a
-module that implements the transport protocol documented in
-&man_transport;.
-A diameter user configures this module as the &mod_transport_opt;
-<c>transport_module</c>.</p>
-
-<p>
-While a user can implement their own transport modules, diameter
-includes implementations for TCP and SCTP:
-&man_tcp; based on &gen_tcp; and &man_sctp; based on &gen_sctp;.
-The former supports TLS but the latter does not currently support
-DTLS.</p>
-
-<pre>
-
- Reliable transport
-
- RADIUS runs over UDP, and does not define retransmission behavior;
- as a result, reliability varies between implementations. As
- described in [RFC2975], this is a major issue in accounting, where
- packet loss may translate directly into revenue loss. In order to
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 7]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- provide well-defined transport behavior, Diameter runs over
- reliable transport mechanisms (TCP, Stream Control Transmission
- Protocol (SCTP)) as defined in [RFC3539].
-
- Agent support
-
- RADIUS does not provide for explicit support for agents, including
- proxies, redirects, and relays. Since the expected behavior is
- not defined, it varies between implementations. Diameter defines
- agent behavior explicitly; this is described in Section 2.8.
-</pre>
-
-&nada;
-
-<pre>
-
- Server-initiated messages
-
- While server-initiated messages are defined in RADIUS [RFC5176],
- support is optional. This makes it difficult to implement
- features such as unsolicited disconnect or re-authentication/
- re-authorization on demand across a heterogeneous deployment. To
- address this issue, support for server-initiated messages is
- mandatory in Diameter.
-</pre>
-
-<p>
-A diameter user can both send and receive messages.</p>
-
-<pre>
-
- Transition support
-
- While Diameter does not share a common protocol data unit (PDU)
- with RADIUS, considerable effort has been expended in enabling
- backward compatibility with RADIUS so that the two protocols may
- be deployed in the same network. Initially, it is expected that
- Diameter will be deployed within new network devices, as well as
- within gateways enabling communication between legacy RADIUS
- devices and Diameter agents. This capability enables Diameter
- support to be added to legacy networks, by addition of a gateway
- or server speaking both RADIUS and Diameter.
-</pre>
-
-<p>
-RADIUS Attributes can be redefined as Diameter AVP's using diameter's
-&man_dict; interface but diameter provides no such definitions.</p>
-
-<pre>
-
- In addition to addressing the above requirements, Diameter also
- provides support for the following:
-
- Capability negotiation
-
- RADIUS does not support error messages, capability negotiation, or
- a mandatory/non-mandatory flag for attributes. Since RADIUS
- clients and servers are not aware of each other's capabilities,
- they may not be able to successfully negotiate a mutually
- acceptable service or, in some cases, even be aware of what
- service has been implemented. Diameter includes support for error
- handling (Section 7), capability negotiation (Section 5.3), and
- mandatory/non-mandatory Attribute-Value Pairs (AVPs)
- (Section 4.1).
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 8]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Peer discovery and configuration
-
- RADIUS implementations typically require that the name or address
- of servers or clients be manually configured, along with the
- corresponding shared secrets. This results in a large
- administrative burden and creates the temptation to reuse the
- RADIUS shared secret, which can result in major security
- vulnerabilities if the Request Authenticator is not globally and
- temporally unique as required in [RFC2865]. Through DNS, Diameter
- enables dynamic discovery of peers (see Section 5.2). Derivation
- of dynamic session keys is enabled via transmission-level
- security.
-
- Over time, the capabilities of Network Access Server (NAS) devices
- have increased substantially. As a result, while Diameter is a
- considerably more sophisticated protocol than RADIUS, it remains
- feasible to implement it within embedded devices.
-</pre>
-
-&nada;
-
-<pre>
-
-1.1. Diameter Protocol
-
- The Diameter base protocol provides the following facilities:
-
- o Ability to exchange messages and deliver AVPs
-</pre>
-
-<p>
-There are two interfaces directly involved in message exchange when
-using diameter: the function &mod_call; for sending outgoing requests,
-and the application callback interface, documented in &man_app; for
-receiving incoming request and answers.</p>
-
-<pre>
-
- o Capabilities negotiation
-</pre>
-
-<p>
-Capabilities negotiation is the responsibility of diameter:
-a user configures a diameter service and/or transport with
-&capabilities; to provide AVP values for CER and CEA messages but it
-is diameter itself that sends these messages.
-A user receives notification of a successful capabilities exchange by
-way of &app_peer_up; callbacks.</p>
-
-<pre>
-
- o Error notification
-</pre>
-
-<p>
-A user can subscribe to &events;, using &mod_subscribe;, in order to
-receive notification of various failures.
-Errors in Diameter messaging are communicated via the application
-callbacks &app_handle_request;, &app_handle_answer; and
-&app_handle_error;.</p>
-
-
-<pre>
-
- o Extensibility, required in [RFC2989], through addition of new
- applications, commands, and AVPs
-</pre>
-
-<p>
-Support for applications, commands and AVP's is extensible using
-diameter's dictionary interface, as documented in &man_dict;.
-Dictionaries are compiled to Erlang encode/decode modules using
-&man_compile; or &man_make;.</p>
-
-<pre>
-
- o Basic services necessary for applications, such as the handling of
- user sessions or accounting
-</pre>
-
-<p>
-Compiled dictionaries are provided for the RFC 3588 and RFC 6733
-Diameter applications: common, base accounting and relay.
-Dictionaries for a number of standardized
-applications are provided in uncompiled form below the <c>examples</c>
-subdirectory of the diameter application directory.</p>
-
-<pre>
-
- All data delivered by the protocol is in the form of AVPs. Some of
- these AVP values are used by the Diameter protocol itself, while
- others deliver data associated with particular applications that
- employ Diameter. AVPs may be arbitrarily added to Diameter messages,
- the only restriction being that the Command Code Format (CCF)
- specification (Section 3.2) be satisfied. AVPs are used by the base
- Diameter protocol to support the following required features:
-
- o Transporting of user authentication information, for the purposes
- of enabling the Diameter server to authenticate the user
-
- o Transporting of service-specific authorization information,
- between client and servers, allowing the peers to decide whether a
- user's access request should be granted
-
-
-
-Fajardo, et al. Standards Track [Page 9]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- o Exchanging resource usage information, which may be used for
- accounting purposes, capacity planning, etc.
-
- o Routing, relaying, proxying, and redirecting of Diameter messages
- through a server hierarchy
-
- The Diameter base protocol satisfies the minimum requirements for a
- AAA protocol, as specified by [RFC2989]. The base protocol may be
- used by itself for accounting purposes only, or it may be used with a
- Diameter application, such as Mobile IPv4 [RFC4004], or network
- access [RFC4005]. It is also possible for the base protocol to be
- extended for use in new applications, via the addition of new
- commands or AVPs. The initial focus of Diameter was network access
- and accounting applications. A truly generic AAA protocol used by
- many applications might provide functionality not provided by
- Diameter. Therefore, it is imperative that the designers of new
- applications understand their requirements before using Diameter.
- See Section 1.3.4 for more information on Diameter applications.
-
- Any node can initiate a request. In that sense, Diameter is a peer-
- to-peer protocol. In this document, a Diameter client is a device at
- the edge of the network that performs access control, such as a
- Network Access Server (NAS) or a Foreign Agent (FA). A Diameter
- client generates Diameter messages to request authentication,
- authorization, and accounting services for the user. A Diameter
- agent is a node that does not provide local user authentication or
- authorization services; agents include proxies, redirects, and relay
- agents. A Diameter server performs authentication and/or
- authorization of the user. A Diameter node may act as an agent for
- certain requests while acting as a server for others.
-
- The Diameter protocol also supports server-initiated messages, such
- as a request to abort service to a particular user.
-</pre>
-
-&nada;
-
-<pre>
-
-1.1.1. Description of the Document Set
-
- The Diameter specification consists of an updated version of the base
- protocol specification (this document) and the Transport Profile
- [RFC3539]. This document obsoletes both RFC 3588 and RFC 5719. A
- summary of the base protocol updates included in this document can be
- found in Section 1.1.3.
-
- This document defines the base protocol specification for AAA, which
- includes support for accounting. There are also a myriad of
- applications documents describing applications that use this base
- specification for Authentication, Authorization, and Accounting.
- These application documents specify how to use the Diameter protocol
- within the context of their application.
-
-
-
-Fajardo, et al. Standards Track [Page 10]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- The Transport Profile document [RFC3539] discusses transport layer
- issues that arise with AAA protocols and recommendations on how to
- overcome these issues. This document also defines the Diameter
- failover algorithm and state machine.
-
- "Clarifications on the Routing of Diameter Request Based on the
- Username and the Realm" [RFC5729] defines specific behavior on how to
- route requests based on the content of the User-Name AVP (Attribute
- Value Pair).
-
-1.1.2. Conventions Used in This Document
-
- The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
- "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
- document are to be interpreted as described in [RFC2119].
-</pre>
-
-&nada;
-
-<pre>
-
-1.1.3. Changes from RFC 3588
-
- This document obsoletes RFC 3588 but is fully backward compatible
- with that document. The changes introduced in this document focus on
- fixing issues that have surfaced during the implementation of
- Diameter (RFC 3588). An overview of some the major changes are given
- below.
-</pre>
-
-<p>
-RFC 6733 is not fully backwards compatible with RFC 3588.
-(For example, in what values of Result-Code values are permissible with
-the E-bit.)
-The implications of incompatibilities for diameter are noted where
-appropriate.</p>
-
-<pre>
-
- o Deprecated the use of the Inband-Security AVP for negotiating
- Transport Layer Security (TLS) [RFC5246]. It has been generally
- considered that bootstrapping of TLS via Inband-Security AVP
- creates certain security risks because it does not completely
- protect the information carried in the CER/CEA (Capabilities-
- Exchange-Request/Capabilities-Exchange-Answer). This version of
- Diameter adopts the common approach of defining a well-known
- secured port that peers should use when communicating via TLS/TCP
- and DTLS/SCTP. This new approach augments the existing in-band
- security negotiation, but it does not completely replace it. The
- old method is kept for backward compatibility reasons.
-</pre>
-
-<p>
-&man_tcp; supports both methods of negotiating TLS:
-bootstrapping via Inband-Security and directly following connection
-establishment.</p>
-
-<pre>
-
- o Deprecated the exchange of CER/CEA messages in the open state.
- This feature was implied in the peer state machine table of RFC
- 3588, but it was not clearly defined anywhere else in that
- document. As work on this document progressed, it became clear
- that the multiplicity of meaning and use of Application-Id AVPs in
- the CER/CEA messages (and the messages themselves) is seen as an
- abuse of the Diameter extensibility rules and thus required
- simplification. Capabilities exchange in the open state has been
- re-introduced in a separate specification [RFC6737], which clearly
- defines new commands for this feature.
-</pre>
-
-<p>
-Capabilities exchange in the open state is not supported: an incoming
-CER in the open state will cause diameter to ask the relevant
-transport process to terminate, which implies the loss of the peer
-connection in the case of &man_tcp; and &man_sctp;.</p>
-
-<p>
-Capabilities update, as defined by RFC 6737, is not yet supported.
-Support will require diameter to handle CUR/CUA in the same way that
-it handles CER/CEA.</p>
-
-<pre>
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 11]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- o Simplified security requirements. The use of a secured transport
- for exchanging Diameter messages remains mandatory. However, TLS/
- TCP and DTLS/SCTP have become the primary methods of securing
- Diameter with IPsec as a secondary alternative. See Section 13
- for details. The support for the End-to-End security framework
- (E2E-Sequence AVP and 'P'-bit in the AVP header) has also been
- deprecated.
-</pre>
-
-<p>
-The End-to-End security framework is not supported since it's use is
-largely unspecified: diameter will set the P-bit in outgoing AVP's as
-directed by the relevant dictionary and/or &app_prepare_request; or
-&app_handle_request; callbacks, but whether or not the P-bit is set on
-incoming AVP's has no consequence.</p>
-
-<p>
-As noted above, DTLS is not currently supported and whether or not
-IPsec is used is transparent to diameter.</p>
-
-<pre>
-
- o Changed Diameter extensibility. This includes fixes to the
- Diameter extensibility description (Section 1.3 and others) to
- better aid Diameter application designers; in addition, the new
- specification relaxes the policy with respect to the allocation of
- Command Codes for vendor-specific uses.
-
- o Clarified Application Id usage. Clarify the proper use of
- Application Id information, which can be found in multiple places
- within a Diameter message. This includes correlating Application
- Ids found in the message headers and AVPs. These changes also
- clearly specify the proper Application Id value to use for
- specific base protocol messages (ASR/ASA, STR/STA) as well as
- clarify the content and use of Vendor-Specific-Application-Id.
-
- o Clarified routing fixes. This document more clearly specifies
- what information (AVPs and Application Ids) can be used for making
- general routing decisions. A rule for the prioritization of
- redirect routing criteria when multiple route entries are found
- via redirects has also been added (see Section 6.13).
-
- o Simplified Diameter peer discovery. The Diameter discovery
- process now supports only widely used discovery schemes; the rest
- have been deprecated (see Section 5.2 for details).
-</pre>
-
-<p>
-Peer discover is not currently supported: peers to which a node should
-connect must be configured.
-Connection requests are accepted from arbitrary peers but a
-&mod_transport_opt; <c>capabilities_cb</c> can be used to reject a
-peer based on an incoming CER or CEA.</p>
-
-<pre>
-
- There are many other miscellaneous fixes that have been introduced in
- this document that may not be considered significant, but they have
- value nonetheless. Examples are removal of obsolete types, fixes to
- the state machine, clarification of the election process, message
- validation, fixes to Failed-AVP and Result-Code AVP values, etc. All
- of the errata filed against RFC 3588 prior to the publication of this
- document have been addressed. A comprehensive list of changes is not
- shown here for practical reasons.
-
-1.2. Terminology
-
- AAA
-
- Authentication, Authorization, and Accounting.
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 12]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- ABNF
-
- Augmented Backus-Naur Form [RFC5234]. A metalanguage with its own
- formal syntax and rules. It is based on the Backus-Naur Form and
- is used to define message exchanges in a bi-directional
- communications protocol.
-
- Accounting
-
- The act of collecting information on resource usage for the
- purpose of capacity planning, auditing, billing, or cost
- allocation.
-
- Accounting Record
-
- An accounting record represents a summary of the resource
- consumption of a user over the entire session. Accounting servers
- creating the accounting record may do so by processing interim
- accounting events or accounting events from several devices
- serving the same user.
-
- Authentication
-
- The act of verifying the identity of an entity (subject).
-
- Authorization
-
- The act of determining whether a requesting entity (subject) will
- be allowed access to a resource (object).
-
- Attribute-Value Pair (AVP)
-
- The Diameter protocol consists of a header followed by one or more
- Attribute-Value-Pairs (AVPs). An AVP includes a header and is
- used to encapsulate protocol-specific data (e.g., routing
- information) as well as authentication, authorization, or
- accounting information.
-</pre>
-
-&nada;
-
-<pre>
-
- Command Code Format (CCF)
-
- A modified form of ABNF used to define Diameter commands (see
- Section 3.2).
-</pre>
-
-<p>
-The <c>@messages</c> section of the &man_dict; format has the CCF as
-content.</p>
-
-<pre>
-
- Diameter Agent
-
- A Diameter Agent is a Diameter node that provides relay, proxy,
- redirect, or translation services.
-
-
-
-
-Fajardo, et al. Standards Track [Page 13]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Diameter Client
-
- A Diameter client is a Diameter node that supports Diameter client
- applications as well as the base protocol. Diameter clients are
- often implemented in devices situated at the edge of a network and
- provide access control services for that network. Typical
- examples of Diameter clients include the Network Access Server
- (NAS) and the Mobile IP Foreign Agent (FA).
-
- Diameter Node
-
- A Diameter node is a host process that implements the Diameter
- protocol and acts as either a client, an agent, or a server.
-
- Diameter Peer
-
- Two Diameter nodes sharing a direct TCP or SCTP transport
- connection are called Diameter peers.
-
- Diameter Server
-
- A Diameter server is a Diameter node that handles authentication,
- authorization, and accounting requests for a particular realm. By
- its very nature, a Diameter server must support Diameter server
- applications in addition to the base protocol.
-</pre>
-
-<p>
-A Diameter Node is implemented by configuring a service
-using &mod_start_service; and one or more transports using
-&mod_add_transport;.
-The service typically represents a Diameter Node but since
-capabilities can be configured on individual transports it's more
-accurate to say that the node is a collection of transports
-advertising the same Origin-Host.</p>
-
-<p>
-The role of a node (agent, client or server) is not something that's
-configured explicitly.
-Transports are either connecting or listening, depending on whether
-diameter should establish a peer connection and send CER or accept
-connections and receive CER, but the role a node implements depends
-largely on dictionary configuration and &man_app; callback
-implementation.</p>
-
-<pre>
-
- Downstream
-
- Downstream is used to identify the direction of a particular
- Diameter message from the home server towards the Diameter client.
-
- Home Realm
-
- A Home Realm is the administrative domain with which the user
- maintains an account relationship.
-
- Home Server
-
- A Diameter server that serves the Home Realm.
-
- Interim Accounting
-
- An interim accounting message provides a snapshot of usage during
- a user's session. Typically, it is implemented in order to
- provide for partial accounting of a user's session in case a
- device reboot or other network problem prevents the delivery of a
- session summary message or session record.
-
-
-
-
-Fajardo, et al. Standards Track [Page 14]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Local Realm
-
- A local realm is the administrative domain providing services to a
- user. An administrative domain may act as a local realm for
- certain users while being a home realm for others.
-
- Multi-session
-
- A multi-session represents a logical linking of several sessions.
- Multi-sessions are tracked by using the Acct-Multi-Session-Id. An
- example of a multi-session would be a Multi-link PPP bundle. Each
- leg of the bundle would be a session while the entire bundle would
- be a multi-session.
-
- Network Access Identifier
-
- The Network Access Identifier, or NAI [RFC4282], is used in the
- Diameter protocol to extract a user's identity and realm. The
- identity is used to identify the user during authentication and/or
- authorization while the realm is used for message routing
- purposes.
-
- Proxy Agent or Proxy
-
- In addition to forwarding requests and responses, proxies make
- policy decisions relating to resource usage and provisioning.
- Typically, this is accomplished by tracking the state of NAS
- devices. While proxies usually do not respond to client requests
- prior to receiving a response from the server, they may originate
- Reject messages in cases where policies are violated. As a
- result, proxies need to understand the semantics of the messages
- passing through them, and they may not support all Diameter
- applications.
-
- Realm
-
- The string in the NAI that immediately follows the '@' character.
- NAI realm names are required to be unique and are piggybacked on
- the administration of the DNS namespace. Diameter makes use of
- the realm, also loosely referred to as domain, to determine
- whether messages can be satisfied locally or whether they must be
- routed or redirected. In RADIUS, realm names are not necessarily
- piggybacked on the DNS namespace but may be independent of it.
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 15]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Real-Time Accounting
-
- Real-time accounting involves the processing of information on
- resource usage within a defined time window. Typically, time
- constraints are imposed in order to limit financial risk. The
- Diameter Credit-Control Application [RFC4006] is an example of an
- application that defines real-time accounting functionality.
-
- Relay Agent or Relay
-
- Relays forward requests and responses based on routing-related
- AVPs and routing table entries. Since relays do not make policy
- decisions, they do not examine or alter non-routing AVPs. As a
- result, relays never originate messages, do not need to understand
- the semantics of messages or non-routing AVPs, and are capable of
- handling any Diameter application or message type. Since relays
- make decisions based on information in routing AVPs and realm
- forwarding tables, they do not keep state on NAS resource usage or
- sessions in progress.
-
- Redirect Agent
-
- Rather than forwarding requests and responses between clients and
- servers, redirect agents refer clients to servers and allow them
- to communicate directly. Since redirect agents do not sit in the
- forwarding path, they do not alter any AVPs transiting between
- client and server. Redirect agents do not originate messages and
- are capable of handling any message type, although they may be
- configured only to redirect messages of certain types, while
- acting as relay or proxy agents for other types. As with relay
- agents, redirect agents do not keep state with respect to sessions
- or NAS resources.
-</pre>
-
-&nada;
-
-<pre>
-
- Session
-
- A session is a related progression of events devoted to a
- particular activity. Diameter application documents provide
- guidelines as to when a session begins and ends. All Diameter
- packets with the same Session-Id are considered to be part of the
- same session.
-</pre>
-
-<p>
-Sessions are not something that diameter is aware of.
-The function &mod_session_id; can be used to construct appropriate
-values for Session-Id AVP's but logic connecting events in the same
-session is the responsibility of the diameter user.</p>
-
-<pre>
-
- Stateful Agent
-
- A stateful agent is one that maintains session state information,
- by keeping track of all authorized active sessions. Each
- authorized session is bound to a particular service, and its state
- is considered active either until it is notified otherwise or
- until expiration.
-
-
-
-Fajardo, et al. Standards Track [Page 16]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Sub-session
-
- A sub-session represents a distinct service (e.g., QoS or data
- characteristics) provided to a given session. These services may
- happen concurrently (e.g., simultaneous voice and data transfer
- during the same session) or serially. These changes in sessions
- are tracked with the Accounting-Sub-Session-Id.
-
- Transaction State
-
- The Diameter protocol requires that agents maintain transaction
- state, which is used for failover purposes. Transaction state
- implies that upon forwarding a request, the Hop-by-Hop Identifier
- is saved; the field is replaced with a locally unique identifier,
- which is restored to its original value when the corresponding
- answer is received. The request's state is released upon receipt
- of the answer. A stateless agent is one that only maintains
- transaction state.
-
- Translation Agent
-
- A translation agent (TLA in Figure 4) is a stateful Diameter node
- that performs protocol translation between Diameter and another
- AAA protocol, such as RADIUS.
-
- Upstream
-
- Upstream is used to identify the direction of a particular
- Diameter message from the Diameter client towards the home server.
-
- User
-
- The entity or device requesting or using some resource, in support
- of which a Diameter client has generated a request.
-</pre>
-
-&nada;
-
-<pre>
-
-1.3. Approach to Extensibility
-
- The Diameter protocol is designed to be extensible, using several
- mechanisms, including:
-
- o Defining new AVP values
-
- o Creating new AVPs
-
- o Creating new commands
-
- o Creating new applications
-
-
-
-
-Fajardo, et al. Standards Track [Page 17]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- From the point of view of extensibility, Diameter authentication,
- authorization, and accounting applications are treated in the same
- way.
-</pre>
-
-<p>
-Extensibility in diameter is by way of the dictionary interface
-documented in &man_dict;: a diameter user creates applications,
-commands and AVP's by implementing a new dictionary,
-compiling the dictionary to a codec module using &man_compile; or
-&man_make;, and configuring the resulting dictionary module on a
-service.
-The dictionary modules provided with diameter are all implemented in
-this manner.</p>
-
-<pre>
- Note: Protocol designers should try to reuse existing functionality,
- namely AVP values, AVPs, commands, and Diameter applications. Reuse
- simplifies standardization and implementation. To avoid potential
- interoperability issues, it is important to ensure that the semantics
- of the reused features are well understood. Given that Diameter can
- also carry RADIUS attributes as Diameter AVPs, such reuse
- considerations also apply to existing RADIUS attributes that may be
- useful in a Diameter application.
-</pre>
-
-<p>
-Reuse in dictionary files is achieved by way of the <c>@inherits</c>
-section.
-AVP's are inherited, commands are not.</p>
-
-<pre>
-
-1.3.1. Defining New AVP Values
-
- In order to allocate a new AVP value for AVPs defined in the Diameter
- base protocol, the IETF needs to approve a new RFC that describes the
- AVP value. IANA considerations for these AVP values are discussed in
- Section 11.3.
-
- The allocation of AVP values for other AVPs is guided by the IANA
- considerations of the document that defines those AVPs. Typically,
- allocation of new values for an AVP defined in an RFC would require
- IETF Review [RFC5226], whereas values for vendor-specific AVPs can be
- allocated by the vendor.
-
-1.3.2. Creating New AVPs
-
- A new AVP being defined MUST use one of the data types listed in
- Sections 4.2 or 4.3. If an appropriate derived data type is already
- defined, it SHOULD be used instead of a base data type to encourage
- reusability and good design practice.
-
- In the event that a logical grouping of AVPs is necessary, and
- multiple "groups" are possible in a given command, it is recommended
- that a Grouped AVP be used (see Section 4.4).
-
- The creation of new AVPs can happen in various ways. The recommended
- approach is to define a new general-purpose AVP in a Standards Track
- RFC approved by the IETF. However, as described in Section 11.1.1,
- there are other mechanisms.
-</pre>
-
-<p>
-Creating new AVP's is an issue for the dictionary designer, not
-diameter.</p>
-
-<pre>
-
-1.3.3. Creating New Commands
-
- A new Command Code MUST be allocated when required AVPs (those
- indicated as {AVP} in the CCF definition) are added to, deleted from,
- or redefined in (for example, by changing a required AVP into an
- optional one) an existing command.
-
-
-
-Fajardo, et al. Standards Track [Page 18]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Furthermore, if the transport characteristics of a command are
- changed (for example, with respect to the number of round trips
- required), a new Command Code MUST be registered.
-
- A change to the CCF of a command, such as described above, MUST
- result in the definition of a new Command Code. This subsequently
- leads to the need to define a new Diameter application for any
- application that will use that new command.
-
- The IANA considerations for Command Codes are discussed in
- Section 3.1.
-</pre>
-
-<p>
-Creating new commands is an issue for the dictionary designer, not
-diameter.</p>
-
-<pre>
-
-1.3.4. Creating New Diameter Applications
-
- Every Diameter application specification MUST have an IANA-assigned
- Application Id (see Section 2.4). The managed Application ID space
- is flat, and there is no relationship between different Diameter
- applications with respect to their Application Ids. As such, there
- is no versioning support provided by these Application Ids
- themselves; every Diameter application is a standalone application.
- If the application has a relationship with other Diameter
- applications, such a relationship is not known to Diameter.
-</pre>
-
-<p>
-Creating new applications is an issue for the dictionary designer,
-not diameter.</p>
-
-<p>
-An application's Application Id is specified in the <c>@id</c> section
-of a dictionary file.</p>
-
-<pre>
-
- Before describing the rules for creating new Diameter applications,
- it is important to discuss the semantics of the AVP occurrences as
- stated in the CCF and the M-bit flag (Section 4.1) for an AVP. There
- is no relationship imposed between the two; they are set
- independently.
-
- o The CCF indicates what AVPs are placed into a Diameter command by
- the sender of that command. Often, since there are multiple modes
- of protocol interactions, many of the AVPs are indicated as
- optional.
-
- o The M-bit allows the sender to indicate to the receiver whether or
- not understanding the semantics of an AVP and its content is
- mandatory. If the M-bit is set by the sender and the receiver
- does not understand the AVP or the values carried within that AVP,
- then a failure is generated (see Section 7).
-</pre>
-
-<p>
-The M-bit is set on outgoing AVP's as directed by the relevant
-dictionary.
-For incoming AVP's, an M-bit set on an AVP that isn't
-explicitly included in the definition of the command in question is
-interpreted as a 5001 error, DIAMETER_AVP_UNSUPPORTED, the
-consequences of which depend on the value of the &mod_application_opt;
-<c>answer_errors</c> or <c>request_errors</c>.</p>
-
-<pre>
-
- It is the decision of the protocol designer when to develop a new
- Diameter application rather than extending Diameter in other ways.
- However, a new Diameter application MUST be created when one or more
- of the following criteria are met:
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 19]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- M-bit Setting
-
- An AVP with the M-bit in the MUST column of the AVP flag table is
- added to an existing Command/Application. An AVP with the M-bit
- in the MAY column of the AVP flag table is added to an existing
- Command/Application.
-
- Note: The M-bit setting for a given AVP is relevant to an
- Application and each command within that application that includes
- the AVP. That is, if an AVP appears in two commands for
- application Foo and the M-bit settings are different in each
- command, then there should be two AVP flag tables describing when
- to set the M-bit.
-
- Commands
-
- A new command is used within the existing application because
- either an additional command is added, an existing command has
- been modified so that a new Command Code had to be registered, or
- a command has been deleted.
-
- AVP Flag bits
-
- If an existing application changes the meaning/semantics of its
- AVP Flags or adds new flag bits, then a new Diameter application
- MUST be created.
-
- If the CCF definition of a command allows it, an implementation may
- add arbitrary optional AVPs with the M-bit cleared (including vendor-
- specific AVPs) to that command without needing to define a new
- application. Please refer to Section 11.1.1 for details.
-</pre>
-
-&nada;
-
-<pre>
-
-2. Protocol Overview
-
- The base Diameter protocol concerns itself with establishing
- connections to peers, capabilities negotiation, how messages are sent
- and routed through peers, and how the connections are eventually torn
- down. The base protocol also defines certain rules that apply to all
- message exchanges between Diameter nodes.
-
- Communication between Diameter peers begins with one peer sending a
- message to another Diameter peer. The set of AVPs included in the
- message is determined by a particular Diameter application. One AVP
- that is included to reference a user's session is the Session-Id.
-
- The initial request for authentication and/or authorization of a user
- would include the Session-Id AVP. The Session-Id is then used in all
- subsequent messages to identify the user's session (see Section 8 for
-
-
-
-Fajardo, et al. Standards Track [Page 20]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- more information). The communicating party may accept the request or
- reject it by returning an answer message with the Result-Code AVP set
- to indicate that an error occurred. The specific behavior of the
- Diameter server or client receiving a request depends on the Diameter
- application employed.
-
- Session state (associated with a Session-Id) MUST be freed upon
- receipt of the Session-Termination-Request, Session-Termination-
- Answer, expiration of authorized service time in the Session-Timeout
- AVP, and according to rules established in a particular Diameter
- application.
-</pre>
-
-<p>
-Like Session-Id, session state is maintained by the diameter user:
-diameter has no session state of its own and does not interpret
-STR/STA in any way.</p>
-
-<pre>
-
- The base Diameter protocol may be used by itself for accounting
- applications. For authentication and authorization, it is always
- extended for a particular application.
-
- Diameter clients MUST support the base protocol, which includes
- accounting. In addition, they MUST fully support each Diameter
- application that is needed to implement the client's service, e.g.,
- Network Access Server Requirements (NASREQ) [RFC2881] and/or Mobile
- IPv4. A Diameter client MUST be referred to as "Diameter X Client"
- where X is the application that it supports and not a "Diameter
- Client".
-
- Diameter servers MUST support the base protocol, which includes
- accounting. In addition, they MUST fully support each Diameter
- application that is needed to implement the intended service, e.g.,
- NASREQ and/or Mobile IPv4. A Diameter server MUST be referred to as
- "Diameter X Server" where X is the application that it supports, and
- not a "Diameter Server".
-
- Diameter relays and redirect agents are transparent to the Diameter
- applications, but they MUST support the Diameter base protocol, which
- includes accounting, and all Diameter applications.
-
- Diameter proxies MUST support the base protocol, which includes
- accounting. In addition, they MUST fully support each Diameter
- application that is needed to implement proxied services, e.g.,
- NASREQ and/or Mobile IPv4. A Diameter proxy MUST be referred to as
- "Diameter X Proxy" where X is the application which it supports, and
- not a "Diameter Proxy".
-
-</pre>
-
-&nada;
-
-<pre>
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 21]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-2.1. Transport
-
- The Diameter Transport profile is defined in [RFC3539].
-
- The base Diameter protocol is run on port 3868 for both TCP [RFC0793]
- and SCTP [RFC4960]. For TLS [RFC5246] and Datagram Transport Layer
- Security (DTLS) [RFC6347], a Diameter node that initiates a
- connection prior to any message exchanges MUST run on port 5658. It
- is assumed that TLS is run on top of TCP when it is used, and DTLS is
- run on top of SCTP when it is used.
-</pre>
-
-<p>
-Which port a transport connects to or listens on is a matter of
-configuration.
-Both &man_tcp; and &man_sctp; will default to 3868 if no other value
-is specified.</p>
-
-<pre>
-
- If the Diameter peer does not support receiving TLS/TCP and DTLS/SCTP
- connections on port 5658 (i.e., the peer complies only with RFC
- 3588), then the initiator MAY revert to using TCP or SCTP on port
- 3868. Note that this scheme is kept only for the purpose of backward
- compatibility and that there are inherent security vulnerabilities
- when the initial CER/CEA messages are sent unprotected (see
- Section 5.6).
-
- Diameter clients MUST support either TCP or SCTP; agents and servers
- SHOULD support both.
-
- A Diameter node MAY initiate connections from a source port other
- than the one that it declares it accepts incoming connections on, and
- it MUST always be prepared to receive connections on port 3868 for
- TCP or SCTP and port 5658 for TLS/TCP and DTLS/SCTP connections.
- When DNS-based peer discovery (Section 5.2) is used, the port numbers
- received from SRV records take precedence over the default ports
- (3868 and 5658).
-
- A given Diameter instance of the peer state machine MUST NOT use more
- than one transport connection to communicate with a given peer,
- unless multiple instances exist on the peer, in which, case a
- separate connection per process is allowed.
-</pre>
-
-<p>
-The &mod_service_opt; <c>restrict_connection</c> controls to what
-extent a diameter service allows multiple connections to the same
-peer.
-(As identified by the value of Origin-Host received from it
-during capabilities exchange.)</p>
-
-<pre>
-
- When no transport connection exists with a peer, an attempt to
- connect SHOULD be made periodically. This behavior is handled via
- the Tc timer (see Section 12 for details), whose recommended value is
- 30 seconds. There are certain exceptions to this rule, such as when
- a peer has terminated the transport connection stating that it does
- not wish to communicate.
-
-</pre>
-
-<p>
-The frequency of reconnection attempts is configured with the
-&mod_transport_opt; <c>connect_timer</c> and
-<c>watchdog_timer</c>.</p>
-
-<pre>
-
- When connecting to a peer and either zero or more transports are
- specified, TLS SHOULD be tried first, followed by DTLS, then by TCP,
- and finally by SCTP. See Section 5.2 for more information on peer
- discovery.
-</pre>
-
-<p>
-The order in which different transports are attempted depends on the
-order of &mod_transport_opt; <c>transport_module</c> and
-<c>transport_config</c> tuples in transport configuration.</p>
-
-<pre>
-
-
-
-Fajardo, et al. Standards Track [Page 22]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Diameter implementations SHOULD be able to interpret ICMP protocol
- port unreachable messages as explicit indications that the server is
- not reachable, subject to security policy on trusting such messages.
- Further guidance regarding the treatment of ICMP errors can be found
- in [RFC5927] and [RFC5461]. Diameter implementations SHOULD also be
- able to interpret a reset from the transport and timed-out connection
- attempts. If Diameter receives data from the lower layer that cannot
- be parsed or identified as a Diameter error made by the peer, the
- stream is compromised and cannot be recovered. The transport
- connection MUST be closed using a RESET call (send a TCP RST bit) or
- an SCTP ABORT message (graceful closure is compromised).
-</pre>
-
-<p>
-ICMP messages and other transport-level errors aren't directly
-visible to diameter but transport implementations like &man_tcp; and
-&man_sctp; propagate these as terminating transport processes.</p>
-
-<pre>
-
-2.1.1. SCTP Guidelines
-
- Diameter messages SHOULD be mapped into SCTP streams in a way that
- avoids head-of-the-line (HOL) blocking. Among different ways of
- performing the mapping that fulfill this requirement it is
- RECOMMENDED that a Diameter node send every Diameter message (request
- or response) over stream zero with the unordered flag set. However,
- Diameter nodes MAY select and implement other design alternatives for
- avoiding HOL blocking such as using multiple streams with the
- unordered flag cleared (as originally instructed in RFC 3588). On
- the receiving side, a Diameter entity MUST be ready to receive
- Diameter messages over any stream, and it is free to return responses
- over a different stream. This way, both sides manage the available
- streams in the sending direction, independently of the streams chosen
- by the other side to send a particular Diameter message. These
- messages can be out-of-order and belong to different Diameter
- sessions.
-</pre>
-
-<p>
-&man_sctp; allows the sender to specify a stream number explicitly.
-The stream on which an incoming message is received it passed to
-&app_handle_request; and &app_handle_answer; callbacks as
-<c>transport_data</c> in a <c>#diameter_packet{}</c>.</p>
-
-<p>
-Ordered or unordered delivery can be configured per transport.</p>
-
-<pre>
-
- Out-of-order delivery has special concerns during a connection
- establishment and termination. When a connection is established, the
- responder side sends a CEA message and moves to R-Open state as
- specified in Section 5.6. If an application message is sent shortly
- after the CEA and delivered out-of-order, the initiator side, still
- in Wait-I-CEA state, will discard the application message and close
- the connection. In order to avoid this race condition, the receiver
- side SHOULD NOT use out-of-order delivery methods until the first
- message has been received from the initiator, proving that it has
- moved to I-Open state. To trigger such a message, the receiver side
- could send a DWR immediately after sending a CEA. Upon reception of
- the corresponding DWA, the receiver side should start using out-of-
- order delivery methods to counter the HOL blocking.
-</pre>
-
-<p>
-&man_sctp; does not currently allow the user to switch between ordered
-and unordered delivery, or to specify the manner of sending per
-message: one or the other must be configured, the defaults being
-ordered.</p>
-
-<pre>
-
- Another race condition may occur when DPR and DPA messages are used.
- Both DPR and DPA are small in size; thus, they may be delivered to
- the peer faster than application messages when an out-of-order
- delivery mechanism is used. Therefore, it is possible that a DPR/DPA
-
-
-
-Fajardo, et al. Standards Track [Page 23]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- exchange completes while application messages are still in transit,
- resulting in a loss of these messages. An implementation could
- mitigate this race condition, for example, using timers, and wait for
- a short period of time for pending application level messages to
- arrive before proceeding to disconnect the transport connection.
- Eventually, lost messages are handled by the retransmission mechanism
- described in Section 5.5.4.
-
- A Diameter agent SHOULD use dedicated payload protocol identifiers
- (PPIDs) for clear text and encrypted SCTP DATA chunks instead of only
- using the unspecified payload protocol identifier (value 0). For
- this purpose, two PPID values are allocated: the PPID value 46 is for
- Diameter messages in clear text SCTP DATA chunks, and the PPID value
- 47 is for Diameter messages in protected DTLS/SCTP DATA chunks.
-</pre>
-
-&nada;
-
-<pre>
-
-2.2. Securing Diameter Messages
-
- Connections between Diameter peers SHOULD be protected by TLS/TCP and
- DTLS/SCTP. All Diameter base protocol implementations MUST support
- the use of TLS/TCP and DTLS/SCTP. If desired, alternative security
- mechanisms that are independent of Diameter, such as IPsec [RFC4301],
- can be deployed to secure connections between peers. The Diameter
- protocol MUST NOT be used without one of TLS, DTLS, or IPsec.
-</pre>
-
-<p>
-As noted above, DTLS is not currently supported and IPsec usage is
-transparent to diameter.
-Security is not enforced by diameter.</p>
-
-<pre>
-
-2.3. Diameter Application Compliance
-
- Application Ids are advertised during the capabilities exchange phase
- (see Section 5.3). Advertising support of an application implies
- that the sender supports the functionality specified in the
- respective Diameter application specification.
-
- Implementations MAY add arbitrary optional AVPs with the M-bit
- cleared (including vendor-specific AVPs) to a command defined in an
- application, but only if the command's CCF syntax specification
- allows for it. Please refer to Section 11.1.1 for details.
-</pre>
-
-&nada;
-
-<pre>
-
-2.4. Application Identifiers
-
- Each Diameter application MUST have an IANA-assigned Application ID.
- The base protocol does not require an Application Id since its
- support is mandatory. During the capabilities exchange, Diameter
- nodes inform their peers of locally supported applications.
- Furthermore, all Diameter messages contain an Application Id, which
- is used in the message forwarding process.
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 24]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- The following Application Id values are defined:
-
- Diameter common message 0
- Diameter base accounting 3
- Relay 0xffffffff
-</pre>
-
-<p>
-These applications are implemented in the dictionary modules
-<c>diameter_gen_base_rfc6733</c>, <c>diameter_gen_acct_rfc6733</c> and
-<c>diameter_relay</c> respectively.
-There are also RFC 3588 versions or the common and accounting
-dictionaries: <c>diameter_gen_base_rfc3588</c> and
-<c>diameter_base_accounting</c>.
-(The inconsistent naming is historical.)
-Dictionary modules are configured using the &mod_application_opt;
-<c>dictionary</c>.</p>
-
-<pre>
- Relay and redirect agents MUST advertise the Relay Application ID,
- while all other Diameter nodes MUST advertise locally supported
- applications. The receiver of a Capabilities Exchange message
- advertising relay service MUST assume that the sender supports all
- current and future applications.
-
- Diameter relay and proxy agents are responsible for finding an
- upstream server that supports the application of a particular
- message. If none can be found, an error message is returned with the
- Result-Code AVP set to DIAMETER_UNABLE_TO_DELIVER.
-</pre>
-
-&nada;
-
-<pre>
-
-2.5. Connections vs. Sessions
-
- This section attempts to provide the reader with an understanding of
- the difference between "connection" and "session", which are terms
- used extensively throughout this document.
-
- A connection refers to a transport-level connection between two peers
- that is used to send and receive Diameter messages. A session is a
- logical concept at the application layer that exists between the
- Diameter client and the Diameter server; it is identified via the
- Session-Id AVP.
-
- +--------+ +-------+ +--------+
- | Client | | Relay | | Server |
- +--------+ +-------+ +--------+
- &lt;----------> &lt;---------->
- peer connection A peer connection B
-
- &lt;----------------------------->
- User session x
-
- Figure 1: Diameter Connections and Sessions
-
- In the example provided in Figure 1, peer connection A is established
- between the client and the relay. Peer connection B is established
- between the relay and the server. User session X spans from the
- client via the relay to the server. Each "user" of a service causes
- an auth request to be sent, with a unique session identifier. Once
- accepted by the server, both the client and the server are aware of
- the session.
-
-
-
-
-Fajardo, et al. Standards Track [Page 25]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- It is important to note that there is no relationship between a
- connection and a session, and that Diameter messages for multiple
- sessions are all multiplexed through a single connection. Also, note
- that Diameter messages pertaining to the session, both application-
- specific and those that are defined in this document such as ASR/ASA,
- RAR/RAA, and STR/STA, MUST carry the Application Id of the
- application. Diameter messages pertaining to peer connection
- establishment and maintenance such as CER/CEA, DWR/DWA, and DPR/DPA
- MUST carry an Application Id of zero (0).
-</pre>
-
-<p>
-As noted above, diameter is not involved in session management.
-This is the responsibility of the diameter user.</p>
-
-<pre>
-
-2.6. Peer Table
-
- The Diameter peer table is used in message forwarding and is
- referenced by the routing table. A peer table entry contains the
- following fields:
-
- Host Identity
-
- Following the conventions described for the DiameterIdentity-
- derived AVP data format in Section 4.3.1, this field contains the
- contents of the Origin-Host (Section 6.3) AVP found in the CER or
- CEA message.
-
- StatusT
-
- This is the state of the peer entry, and it MUST match one of the
- values listed in Section 5.6.
-
- Static or Dynamic
-
- Specifies whether a peer entry was statically configured or
- dynamically discovered.
-
- Expiration Time
-
- Specifies the time at which dynamically discovered peer table
- entries are to be either refreshed or expired. If public key
- certificates are used for Diameter security (e.g., with TLS), this
- value MUST NOT be greater than the expiry times in the relevant
- certificates.
-
- TLS/TCP and DTLS/SCTP Enabled
-
- Specifies whether TLS/TCP and DTLS/SCTP is to be used when
- communicating with the peer.
-
- Additional security information, when needed (e.g., keys,
- certificates).
-</pre>
-
-<p>
-The Peer Table is not directly accessible to the diameter user.
-Information about connected peers can be retrieved using
-&mod_service_info;.</p>
-
-<pre>
-
-
-
-Fajardo, et al. Standards Track [Page 26]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-2.7. Routing Table
-
- All Realm-Based routing lookups are performed against what is
- commonly known as the routing table (see Section 12). Each routing
- table entry contains the following fields:
-
- Realm Name
-
- This is the field that MUST be used as a primary key in the
- routing table lookups. Note that some implementations perform
- their lookups based on longest-match-from-the-right on the realm
- rather than requiring an exact match.
-
- Application Identifier
-
- An application is identified by an Application Id. A route entry
- can have a different destination based on the Application Id in
- the message header. This field MUST be used as a secondary key
- field in routing table lookups.
-
- Local Action
-
- The Local Action field is used to identify how a message should be
- treated. The following actions are supported:
-
- 1. LOCAL - Diameter messages that can be satisfied locally and do
- not need to be routed to another Diameter entity.
-
- 2. RELAY - All Diameter messages that fall within this category
- MUST be routed to a next-hop Diameter entity that is indicated
- by the identifier described below. Routing is done without
- modifying any non-routing AVPs. See Section 6.1.9 for
- relaying guidelines.
-
- 3. PROXY - All Diameter messages that fall within this category
- MUST be routed to a next Diameter entity that is indicated by
- the identifier described below. The local server MAY apply
- its local policies to the message by including new AVPs to the
- message prior to routing. See Section 6.1.9 for proxying
- guidelines.
-
- 4. REDIRECT - Diameter messages that fall within this category
- MUST have the identity of the home Diameter server(s)
- appended, and returned to the sender of the message. See
- Section 6.1.8 for redirection guidelines.
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 27]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Server Identifier
-
- The identity of one or more servers to which the message is to be
- routed. This identity MUST also be present in the Host Identity
- field of the peer table (Section 2.6). When the Local Action is
- set to RELAY or PROXY, this field contains the identity of the
- server(s) to which the message MUST be routed. When the Local
- Action field is set to REDIRECT, this field contains the identity
- of one or more servers to which the message MUST be redirected.
-
- Static or Dynamic
-
- Specifies whether a route entry was statically configured or
- dynamically discovered.
-
- Expiration Time
-
- Specifies the time at which a dynamically discovered route table
- entry expires. If public key certificates are used for Diameter
- security (e.g., with TLS), this value MUST NOT be greater than the
- expiry time in the relevant certificates.
-
- It is important to note that Diameter agents MUST support at least
- one of the LOCAL, RELAY, PROXY, or REDIRECT modes of operation.
- Agents do not need to support all modes of operation in order to
- conform with the protocol specification, but they MUST follow the
- protocol compliance guidelines in Section 2. Relay agents and
- proxies MUST NOT reorder AVPs.
-
- The routing table MAY include a default entry that MUST be used for
- any requests not matching any of the other entries. The routing
- table MAY consist of only such an entry.
-
- When a request is routed, the target server MUST have advertised the
- Application Id (see Section 2.4) for the given message or have
- advertised itself as a relay or proxy agent. Otherwise, an error is
- returned with the Result-Code AVP set to DIAMETER_UNABLE_TO_DELIVER.
-</pre>
-
-<p>
-Routing does not need specific support in diameter: a user can
-maintain their own routing table if desired and implement any desired
-routing in &man_app; callbacks.
-However, it may be convenient to add more specific routing support to
-diameter in the future.</p>
-
-<pre>
-
-2.8. Role of Diameter Agents
-
- In addition to clients and servers, the Diameter protocol introduces
- relay, proxy, redirect, and translation agents, each of which is
- defined in Section 1.2. Diameter agents are useful for several
- reasons:
-</pre>
-
-<p>
-An noted above, the role a node plays is largely a question of
-configuration and &man_app; callback implementation.</p>
-
-<pre>
-
- o They can distribute administration of systems to a configurable
- grouping, including the maintenance of security associations.
-
-
-
-
-Fajardo, et al. Standards Track [Page 28]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- o They can be used for concentration of requests from a number of
- co-located or distributed NAS equipment sets to a set of like user
- groups.
-
- o They can do value-added processing to the requests or responses.
-
- o They can be used for load balancing.
-
- o A complex network will have multiple authentication sources, they
- can sort requests and forward towards the correct target.
-
- The Diameter protocol requires that agents maintain transaction
- state, which is used for failover purposes. Transaction state
- implies that upon forwarding a request, its Hop-by-Hop Identifier is
- saved; the field is replaced with a locally unique identifier, which
- is restored to its original value when the corresponding answer is
- received. The request's state is released upon receipt of the
- answer. A stateless agent is one that only maintains transaction
- state.
-
- The Proxy-Info AVP allows stateless agents to add local state to a
- Diameter request, with the guarantee that the same state will be
- present in the answer. However, the protocol's failover procedures
- require that agents maintain a copy of pending requests.
-
- A stateful agent is one that maintains session state information by
- keeping track of all authorized active sessions. Each authorized
- session is bound to a particular service, and its state is considered
- active until either the agent is notified otherwise or the session
- expires. Each authorized session has an expiration, which is
- communicated by Diameter servers via the Session-Timeout AVP.
-
- Maintaining session state may be useful in certain applications, such
- as:
-
- o Protocol translation (e.g., RADIUS &lt;-> Diameter)
-
- o Limiting resources authorized to a particular user
-
- o Per-user or per-transaction auditing
-
- A Diameter agent MAY act in a stateful manner for some requests and
- be stateless for others. A Diameter implementation MAY act as one
- type of agent for some requests and as another type of agent for
- others.
-</pre>
-
-&nada;
-
-<pre>
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 29]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-2.8.1. Relay Agents
-
- Relay agents are Diameter agents that accept requests and route
- messages to other Diameter nodes based on information found in the
- messages (e.g., the value of the Destination-Realm AVP Section 6.6).
- This routing decision is performed using a list of supported realms
- and known peers. This is known as the routing table, as is defined
- further in Section 2.7.
-
- Relays may, for example, be used to aggregate requests from multiple
- Network Access Servers (NASes) within a common geographical area
- (Point of Presence, POP). The use of relays is advantageous since it
- eliminates the need for NASes to be configured with the necessary
- security information they would otherwise require to communicate with
- Diameter servers in other realms. Likewise, this reduces the
- configuration load on Diameter servers that would otherwise be
- necessary when NASes are added, changed, or deleted.
-
- Relays modify Diameter messages by inserting and removing routing
- information, but they do not modify any other portion of a message.
- Relays SHOULD NOT maintain session state but MUST maintain
- transaction state.
-
- +------+ ---------> +------+ ---------> +------+
- | | 1. Request | | 2. Request | |
- | NAS | | DRL | | HMS |
- | | 4. Answer | | 3. Answer | |
- +------+ &lt;--------- +------+ &lt;--------- +------+
- example.net example.net example.com
-
- Figure 2: Relaying of Diameter messages
-
- The example provided in Figure 2 depicts a request issued from a NAS,
- which is an access device, for the user [email protected]. Prior to
- issuing the request, the NAS performs a Diameter route lookup, using
- "example.com" as the key, and determines that the message is to be
- relayed to a DRL, which is a Diameter relay. The DRL performs the
- same route lookup as the NAS, and relays the message to the HMS,
- which is example.com's home server. The HMS identifies that the
- request can be locally supported (via the realm), processes the
- authentication and/or authorization request, and replies with an
- answer, which is routed back to the NAS using saved transaction
- state.
-
- Since relays do not perform any application-level processing, they
- provide relaying services for all Diameter applications; therefore,
- they MUST advertise the Relay Application Id.
-</pre>
-
-<p>
-Requests are relayed by returning a <c>relay</c> tuple from a
-&app_handle_request; callback.</p>
-
-<pre>
-
-
-
-Fajardo, et al. Standards Track [Page 30]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-2.8.2. Proxy Agents
-
- Similar to relays, proxy agents route Diameter messages using the
- Diameter routing table. However, they differ since they modify
- messages to implement policy enforcement. This requires that proxies
- maintain the state of their downstream peers (e.g., access devices)
- to enforce resource usage, provide admission control, and provide
- provisioning.
-
- Proxies may, for example, be used in call control centers or access
- ISPs that provide outsourced connections; they can monitor the number
- and type of ports in use and make allocation and admission decisions
- according to their configuration.
-
- Since enforcing policies requires an understanding of the service
- being provided, proxies MUST only advertise the Diameter applications
- they support.
-</pre>
-
-&nada;
-
-<pre>
-
-2.8.3. Redirect Agents
-
- Redirect agents are useful in scenarios where the Diameter routing
- configuration needs to be centralized. An example is a redirect
- agent that provides services to all members of a consortium, but does
- not wish to be burdened with relaying all messages between realms.
- This scenario is advantageous since it does not require that the
- consortium provide routing updates to its members when changes are
- made to a member's infrastructure.
-
- Since redirect agents do not relay messages, and only return an
- answer with the information necessary for Diameter agents to
- communicate directly, they do not modify messages. Since redirect
- agents do not receive answer messages, they cannot maintain session
- state.
-
- The example provided in Figure 3 depicts a request issued from the
- access device, NAS, for the user [email protected]. The message is
- forwarded by the NAS to its relay, DRL, which does not have a routing
- entry in its Diameter routing table for example.com. The DRL has a
- default route configured to DRD, which is a redirect agent that
- returns a redirect notification to DRL, as well as the HMS' contact
- information. Upon receipt of the redirect notification, the DRL
- establishes a transport connection with the HMS, if one doesn't
- already exist, and forwards the request to it.
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 31]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- +------+
- | |
- | DRD |
- | |
- +------+
- ^ |
- 2. Request | | 3. Redirection
- | | Notification
- | v
- +------+ ---------> +------+ ---------> +------+
- | | 1. Request | | 4. Request | |
- | NAS | | DRL | | HMS |
- | | 6. Answer | | 5. Answer | |
- +------+ &lt;--------- +------+ &lt;--------- +------+
- example.net example.net example.com
-
- Figure 3: Redirecting a Diameter Message
-
- Since redirect agents do not perform any application-level
- processing, they provide relaying services for all Diameter
- applications; therefore, they MUST advertise the Relay Application
- ID.
-</pre>
-
-&nada;
-
-<pre>
-
-2.8.4. Translation Agents
-
- A translation agent is a device that provides translation between two
- protocols (e.g., RADIUS&lt;->Diameter, TACACS+&lt;->Diameter). Translation
- agents are likely to be used as aggregation servers to communicate
- with a Diameter infrastructure, while allowing for the embedded
- systems to be migrated at a slower pace.
-
- Given that the Diameter protocol introduces the concept of long-lived
- authorized sessions, translation agents MUST be session stateful and
- MUST maintain transaction state.
-
- Translation of messages can only occur if the agent recognizes the
- application of a particular request; therefore, translation agents
- MUST only advertise their locally supported applications.
-
- +------+ ---------> +------+ ---------> +------+
- | | RADIUS Request | | Diameter Request | |
- | NAS | | TLA | | HMS |
- | | RADIUS Answer | | Diameter Answer | |
- +------+ &lt;--------- +------+ &lt;--------- +------+
- example.net example.net example.com
-
- Figure 4: Translation of RADIUS to Diameter
-</pre>
-
-&nada;
-
-<pre>
-
-
-
-
-Fajardo, et al. Standards Track [Page 32]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-2.9. Diameter Path Authorization
-
- As noted in Section 2.2, Diameter provides transmission-level
- security for each connection using TLS/TCP and DTLS/SCTP. Therefore,
- each connection can be authenticated and can be replay and integrity
- protected.
-
- In addition to authenticating each connection, the entire session
- MUST also be authorized. Before initiating a connection, a Diameter
- peer MUST check that its peers are authorized to act in their roles.
- For example, a Diameter peer may be authentic, but that does not mean
- that it is authorized to act as a Diameter server advertising a set
- of Diameter applications.
-
- Prior to bringing up a connection, authorization checks are performed
- at each connection along the path. Diameter capabilities negotiation
- (CER/CEA) also MUST be carried out, in order to determine what
- Diameter applications are supported by each peer. Diameter sessions
- MUST be routed only through authorized nodes that have advertised
- support for the Diameter application required by the session.
-
- As noted in Section 6.1.9, a relay or proxy agent MUST append a
- Route-Record AVP to all requests forwarded. The AVP contains the
- identity of the peer from which the request was received.
-
- The home Diameter server, prior to authorizing a session, MUST check
- the Route-Record AVPs to make sure that the route traversed by the
- request is acceptable. For example, administrators within the home
- realm may not wish to honor requests that have been routed through an
- untrusted realm. By authorizing a request, the home Diameter server
- is implicitly indicating its willingness to engage in the business
- transaction as specified by any contractual relationship between the
- server and the previous hop. A DIAMETER_AUTHORIZATION_REJECTED error
- message (see Section 7.1.5) is sent if the route traversed by the
- request is unacceptable.
-
- A home realm may also wish to check that each accounting request
- message corresponds to a Diameter response authorizing the session.
- Accounting requests without corresponding authorization responses
- SHOULD be subjected to further scrutiny, as should accounting
- requests indicating a difference between the requested and provided
- service.
-
- Forwarding of an authorization response is considered evidence of a
- willingness to take on financial risk relative to the session. A
- local realm may wish to limit this exposure, for example, by
- establishing credit limits for intermediate realms and refusing to
- accept responses that would violate those limits. By issuing an
-
-
-
-Fajardo, et al. Standards Track [Page 33]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- accounting request corresponding to the authorization response, the
- local realm implicitly indicates its agreement to provide the service
- indicated in the authorization response. If the service cannot be
- provided by the local realm, then a DIAMETER_UNABLE_TO_COMPLY error
- message MUST be sent within the accounting request; a Diameter client
- receiving an authorization response for a service that it cannot
- perform MUST NOT substitute an alternate service and then send
- accounting requests for the alternate service instead.
-</pre>
-
-&nada;
-
-<pre>
-
-3. Diameter Header
-
- A summary of the Diameter header format is shown below. The fields
- are transmitted in network byte order.
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Version | Message Length |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Command Flags | Command Code |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Application-ID |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Hop-by-Hop Identifier |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | End-to-End Identifier |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | AVPs ...
- +-+-+-+-+-+-+-+-+-+-+-+-+-
-</pre>
-
-<p>
-The Diameter Header is represented by the <c>diameter_header</c>
-record defined in <c>diameter.hrl</c>.
-The <c>diameter_packet</c> record contains a <c>header</c> field whose
-value will be a decoded <c>#diameter_header{}</c> for incoming
-messages passed to &app_handle_request; and &app_handle_answer;
-callbacks.
-In the case of outgoing messages, diameter and the relevant
-dictionary populate the Diameter Header appropriately, although
-&app_prepare_request; and &app_handle_request; callbacks can modify
-header values.
-(Which can be useful in test.)</p>
-
-<pre>
-
- Version
-
- This Version field MUST be set to 1 to indicate Diameter Version
- 1.
-
- Message Length
-
- The Message Length field is three octets and indicates the length
- of the Diameter message including the header fields and the padded
- AVPs. Thus, the Message Length field is always a multiple of 4.
-
- Command Flags
-
- The Command Flags field is eight bits. The following bits are
- assigned:
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 34]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- 0 1 2 3 4 5 6 7
- +-+-+-+-+-+-+-+-+
- |R P E T r r r r|
- +-+-+-+-+-+-+-+-+
-
- R(equest)
-
- If set, the message is a request. If cleared, the message is
- an answer.
-
- P(roxiable)
-
- If set, the message MAY be proxied, relayed, or redirected. If
- cleared, the message MUST be locally processed.
-
- E(rror)
-
- If set, the message contains a protocol error, and the message
- will not conform to the CCF described for this command.
- Messages with the 'E' bit set are commonly referred to as error
- messages. This bit MUST NOT be set in request messages (see
- Section 7.2).
-
- T(Potentially retransmitted message)
-
- This flag is set after a link failover procedure, to aid the
- removal of duplicate requests. It is set when resending
- requests not yet acknowledged, as an indication of a possible
- duplicate due to a link failure. This bit MUST be cleared when
- sending a request for the first time; otherwise, the sender
- MUST set this flag. Diameter agents only need to be concerned
- about the number of requests they send based on a single
- received request; retransmissions by other entities need not be
- tracked. Diameter agents that receive a request with the T
- flag set, MUST keep the T flag set in the forwarded request.
- This flag MUST NOT be set if an error answer message (e.g., a
- protocol error) has been received for the earlier message. It
- can be set only in cases where no answer has been received from
- the server for a request, and the request has been sent again.
- This flag MUST NOT be set in answer messages.
-
- r(eserved)
-
- These flag bits are reserved for future use; they MUST be set
- to zero and ignored by the receiver.
-</pre>
-
-<p>
-Reserved bits are set to 0 in outgoing messages.</p>
-
-<pre>
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 35]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Command Code
-
- The Command Code field is three octets and is used in order to
- communicate the command associated with the message. The 24-bit
- address space is managed by IANA (see Section 3.1). Command Code
- values 16,777,214 and 16,777,215 (hexadecimal values FFFFFE-
- FFFFFF) are reserved for experimental use (see Section 11.2).
-
- Application-ID
-
- Application-ID is four octets and is used to identify for which
- application the message is applicable. The application can be an
- authentication application, an accounting application, or a
- vendor-specific application.
-
- The value of the Application-ID field in the header MUST be the
- same as any relevant Application-Id AVPs contained in the message.
-
- Hop-by-Hop Identifier
-
- The Hop-by-Hop Identifier is an unsigned 32-bit integer field (in
- network byte order) that aids in matching requests and replies.
- The sender MUST ensure that the Hop-by-Hop Identifier in a request
- is unique on a given connection at any given time, and it MAY
- attempt to ensure that the number is unique across reboots. The
- sender of an answer message MUST ensure that the Hop-by-Hop
- Identifier field contains the same value that was found in the
- corresponding request. The Hop-by-Hop Identifier is normally a
- monotonically increasing number, whose start value was randomly
- generated. An answer message that is received with an unknown
- Hop-by-Hop Identifier MUST be discarded.
-
- End-to-End Identifier
-
- The End-to-End Identifier is an unsigned 32-bit integer field (in
- network byte order) that is used to detect duplicate messages.
- Upon reboot, implementations MAY set the high order 12 bits to
- contain the low order 12 bits of current time, and the low order
- 20 bits to a random value. Senders of request messages MUST
- insert a unique identifier on each message. The identifier MUST
- remain locally unique for a period of at least 4 minutes, even
- across reboots. The originator of an answer message MUST ensure
- that the End-to-End Identifier field contains the same value that
- was found in the corresponding request. The End-to-End Identifier
- MUST NOT be modified by Diameter agents of any kind. The
- combination of the Origin-Host AVP (Section 6.3) and this field is
- used to detect duplicates. Duplicate requests SHOULD cause the
- same answer to be transmitted (modulo the Hop-by-Hop Identifier
-
-
-
-Fajardo, et al. Standards Track [Page 36]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- field and any routing AVPs that may be present), and they MUST NOT
- affect any state that was set when the original request was
- processed. Duplicate answer messages that are to be locally
- consumed (see Section 6.2) SHOULD be silently discarded.
-
- AVPs
-
- AVPs are a method of encapsulating information relevant to the
- Diameter message. See Section 4 for more information on AVPs.
-</pre>
-
-&nada;
-
-<pre>
-
-3.1. Command Codes
-
- Each command Request/Answer pair is assigned a Command Code, and the
- sub-type (i.e., request or answer) is identified via the 'R' bit in
- the Command Flags field of the Diameter header.
-
- Every Diameter message MUST contain a Command Code in its header's
- Command Code field, which is used to determine the action that is to
- be taken for a particular message. The following Command Codes are
- defined in the Diameter base protocol:
-
- Section
- Command Name Abbrev. Code Reference
- --------------------------------------------------------
- Abort-Session-Request ASR 274 8.5.1
- Abort-Session-Answer ASA 274 8.5.2
- Accounting-Request ACR 271 9.7.1
- Accounting-Answer ACA 271 9.7.2
- Capabilities-Exchange- CER 257 5.3.1
- Request
- Capabilities-Exchange- CEA 257 5.3.2
- Answer
- Device-Watchdog-Request DWR 280 5.5.1
- Device-Watchdog-Answer DWA 280 5.5.2
- Disconnect-Peer-Request DPR 282 5.4.1
- Disconnect-Peer-Answer DPA 282 5.4.2
- Re-Auth-Request RAR 258 8.3.1
- Re-Auth-Answer RAA 258 8.3.2
- Session-Termination- STR 275 8.4.1
- Request
- Session-Termination- STA 275 8.4.2
- Answer
-</pre>
-
-<p>
-These messages are all defined in diameter's implementation of the
-common dictionary in modules <c>diameter_gen_base_rfc6733</c> and
-<c>diameter_gen_base_rfc3588</c>.
-Corresponding record definitions are found in
-<c>diameter_gen_base_rfc6733.hrl</c> and
-<c>diameter_gen_base_rfc3588.hrl</c>.</p>
-
-<pre>
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 37]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-3.2. Command Code Format Specification
-
- Every Command Code defined MUST include a corresponding Command Code
- Format (CCF) specification, which is used to define the AVPs that
- MUST or MAY be present when sending the message. The following ABNF
- specifies the CCF used in the definition:
-</pre>
-
-<p>
-The CCF is what is specified in the <c>@messages</c> section of the
-&man_dict; format, except as noted below.</p>
-
-<pre>
-
- command-def = "&lt;" command-name ">" "::=" diameter-message
-</pre>
-
-<p>
-Angle brackets are currently not allowed here.
-This was a change between RFC 3588 and RFC 6733: the former disallowed
-them in the grammar but included them in its own command definitions.</p>
-
-<pre>
-
- command-name = diameter-name
-
- diameter-name = ALPHA *(ALPHA / DIGIT / "-")
-
- diameter-message = header *fixed *required *optional
-
- header = "&lt;Diameter-Header:" command-id
- [r-bit] [p-bit] [e-bit] [application-id]">"
-
- application-id = 1*DIGIT
-
- command-id = 1*DIGIT
- ; The Command Code assigned to the command.
-
- r-bit = ", REQ"
- ; If present, the 'R' bit in the Command
- ; Flags is set, indicating that the message
- ; is a request as opposed to an answer.
-
- p-bit = ", PXY"
- ; If present, the 'P' bit in the Command
- ; Flags is set, indicating that the message
- ; is proxiable.
-
- e-bit = ", ERR"
- ; If present, the 'E' bit in the Command
- ; Flags is set, indicating that the answer
- ; message contains a Result-Code AVP in
- ; the "protocol error" class.
-
- fixed = [qual] "&lt;" avp-spec ">"
- ; Defines the fixed position of an AVP.
-
- required = [qual] "{" avp-spec "}"
- ; The AVP MUST be present and can appear
- ; anywhere in the message.
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 38]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- optional = [qual] "[" avp-name "]"
- ; The avp-name in the 'optional' rule cannot
- ; evaluate to any AVP Name that is included
- ; in a fixed or required rule. The AVP can
- ; appear anywhere in the message.
- ;
- ; NOTE: "[" and "]" have a slightly different
- ; meaning than in ABNF. These braces
- ; cannot be used to express optional fixed rules
- ; (such as an optional ICV at the end). To do
- ; this, the convention is '0*1fixed'.
-
- qual = [min] "*" [max]
- ; See ABNF conventions, RFC 5234, Section 4.
- ; The absence of any qualifier depends on
- ; whether it precedes a fixed, required, or
- ; optional rule. If a fixed or required rule has
- ; no qualifier, then exactly one such AVP MUST
- ; be present. If an optional rule has no
- ; qualifier, then 0 or 1 such AVP may be
- ; present. If an optional rule has a qualifier,
- ; then the value of min MUST be 0 if present.
-
- min = 1*DIGIT
- ; The minimum number of times the element may
- ; be present. If absent, the default value is 0
- ; for fixed and optional rules and 1 for
- ; required rules. The value MUST be at least 1
- ; for required rules.
-
- max = 1*DIGIT
- ; The maximum number of times the element may
- ; be present. If absent, the default value is
- ; infinity. A value of 0 implies the AVP MUST
- ; NOT be present.
-
- avp-spec = diameter-name
- ; The avp-spec has to be an AVP Name, defined
- ; in the base or extended Diameter
- ; specifications.
-
- avp-name = avp-spec / "AVP"
- ; The string "AVP" stands for *any* arbitrary AVP
- ; Name, not otherwise listed in that Command Code
- ; definition. The inclusion of this string
- ; is recommended for all CCFs to allow for
- ; extensibility.
-
-
-
-
-Fajardo, et al. Standards Track [Page 39]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- The following is a definition of a fictitious Command Code:
-
- Example-Request ::= &lt; Diameter Header: 9999999, REQ, PXY >
- { User-Name }
- 1* { Origin-Host }
- * [ AVP ]
-</pre>
-
-&nada;
-
-<pre>
-
-3.3. Diameter Command Naming Conventions
-
- Diameter command names typically includes one or more English words
- followed by the verb "Request" or "Answer". Each English word is
- delimited by a hyphen. A three-letter acronym for both the request
- and answer is also normally provided.
-
- An example is a message set used to terminate a session. The command
- name is Session-Terminate-Request and Session-Terminate-Answer, while
- the acronyms are STR and STA, respectively.
-
- Both the request and the answer for a given command share the same
- Command Code. The request is identified by the R(equest) bit in the
- Diameter header set to one (1), to ask that a particular action be
- performed, such as authorizing a user or terminating a session. Once
- the receiver has completed the request, it issues the corresponding
- answer, which includes a result code that communicates one of the
- following:
-
- o The request was successful
-
- o The request failed
-
- o An additional request has to be sent to provide information the
- peer requires prior to returning a successful or failed answer.
-
- o The receiver could not process the request, but provides
- information about a Diameter peer that is able to satisfy the
- request, known as redirect.
-
- Additional information, encoded within AVPs, may also be included in
- answer messages.
-</pre>
-
-<p>
-The &man_dict; format places no requirement on the naming of commands.</p>
-
-<pre>
-
-4. Diameter AVPs
-
- Diameter AVPs carry specific authentication, accounting,
- authorization, and routing information as well as configuration
- details for the request and reply.
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 40]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Each AVP of type OctetString MUST be padded to align on a 32-bit
- boundary, while other AVP types align naturally. A number of zero-
- valued bytes are added to the end of the AVP Data field until a word
- boundary is reached. The length of the padding is not reflected in
- the AVP Length field.
-
-4.1. AVP Header
-
- The fields in the AVP header MUST be sent in network byte order. The
- format of the header is:
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | AVP Code |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- |V M P r r r r r| AVP Length |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Vendor-ID (opt) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Data ...
- +-+-+-+-+-+-+-+-+
-
- AVP Code
-
- The AVP Code, combined with the Vendor-Id field, identifies the
- attribute uniquely. AVP numbers 1 through 255 are reserved for
- reuse of RADIUS attributes, without setting the Vendor-Id field.
- AVP numbers 256 and above are used for Diameter, which are
- allocated by IANA (see Section 11.1.1).
-
- AVP Flags
-
- The AVP Flags field informs the receiver how each attribute must
- be handled. New Diameter applications SHOULD NOT define
- additional AVP Flag bits. However, note that new Diameter
- applications MAY define additional bits within the AVP header, and
- an unrecognized bit SHOULD be considered an error. The sender of
- the AVP MUST set 'R' (reserved) bits to 0 and the receiver SHOULD
- ignore all 'R' (reserved) bits. The 'P' bit has been reserved for
- future usage of end-to-end security. At the time of writing,
- there are no end-to-end security mechanisms specified; therefore,
- the 'P' bit SHOULD be set to 0.
-
- The 'M' bit, known as the Mandatory bit, indicates whether the
- receiver of the AVP MUST parse and understand the semantics of the
- AVP including its content. The receiving entity MUST return an
- appropriate error message if it receives an AVP that has the M-bit
-
-
-
-Fajardo, et al. Standards Track [Page 41]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- set but does not understand it. An exception applies when the AVP
- is embedded within a Grouped AVP. See Section 4.4 for details.
- Diameter relay and redirect agents MUST NOT reject messages with
- unrecognized AVPs.
-
- The 'M' bit MUST be set according to the rules defined in the
- application specification that introduces or reuses this AVP.
- Within a given application, the M-bit setting for an AVP is
- defined either for all command types or for each command type.
-
- AVPs with the 'M' bit cleared are informational only; a receiver
- that receives a message with such an AVP that is not supported, or
- whose value is not supported, MAY simply ignore the AVP.
-
- The 'V' bit, known as the Vendor-Specific bit, indicates whether
- the optional Vendor-ID field is present in the AVP header. When
- set, the AVP Code belongs to the specific vendor code address
- space.
-
- AVP Length
-
- The AVP Length field is three octets, and indicates the number of
- octets in this AVP including the AVP Code field, AVP Length field,
- AVP Flags field, Vendor-ID field (if present), and the AVP Data
- field. If a message is received with an invalid attribute length,
- the message MUST be rejected.
-
-4.1.1. Optional Header Elements
-
- The AVP header contains one optional field. This field is only
- present if the respective bit-flag is enabled.
-
- Vendor-ID
-
- The Vendor-ID field is present if the 'V' bit is set in the AVP
- Flags field. The optional four-octet Vendor-ID field contains the
- IANA-assigned "SMI Network Management Private Enterprise Codes"
- [ENTERPRISE] value, encoded in network byte order. Any vendors or
- standardization organizations that are also treated like vendors
- in the IANA-managed "SMI Network Management Private Enterprise
- Codes" space wishing to implement a vendor-specific Diameter AVP
- MUST use their own Vendor-ID along with their privately managed
- AVP address space, guaranteeing that they will not collide with
- any other vendor's vendor-specific AVP(s) or with future IETF
- AVPs.
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 42]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- A Vendor-ID value of zero (0) corresponds to the IETF-adopted AVP
- values, as managed by IANA. Since the absence of the Vendor-ID
- field implies that the AVP in question is not vendor specific,
- implementations MUST NOT use the value of zero (0) for the
- Vendor-ID field.
-
-4.2. Basic AVP Data Formats
-
- The Data field is zero or more octets and contains information
- specific to the Attribute. The format and length of the Data field
- is determined by the AVP Code and AVP Length fields. The format of
- the Data field MUST be one of the following base data types or a data
- type derived from the base data types. In the event that a new Basic
- AVP Data Format is needed, a new version of this RFC MUST be created.
-
- OctetString
-
- The data contains arbitrary data of variable length. Unless
- otherwise noted, the AVP Length field MUST be set to at least 8
- (12 if the 'V' bit is enabled). AVP values of this type that are
- not a multiple of 4 octets in length are followed by the necessary
- padding so that the next AVP (if any) will start on a 32-bit
- boundary.
-
- Integer32
-
- 32-bit signed value, in network byte order. The AVP Length field
- MUST be set to 12 (16 if the 'V' bit is enabled).
-
- Integer64
-
- 64-bit signed value, in network byte order. The AVP Length field
- MUST be set to 16 (20 if the 'V' bit is enabled).
-
- Unsigned32
-
- 32-bit unsigned value, in network byte order. The AVP Length
- field MUST be set to 12 (16 if the 'V' bit is enabled).
-
- Unsigned64
-
- 64-bit unsigned value, in network byte order. The AVP Length
- field MUST be set to 16 (20 if the 'V' bit is enabled).
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 43]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Float32
-
- This represents floating point values of single precision as
- described by [FLOATPOINT]. The 32-bit value is transmitted in
- network byte order. The AVP Length field MUST be set to 12 (16 if
- the 'V' bit is enabled).
-
- Float64
-
- This represents floating point values of double precision as
- described by [FLOATPOINT]. The 64-bit value is transmitted in
- network byte order. The AVP Length field MUST be set to 16 (20 if
- the 'V' bit is enabled).
-
- Grouped
-
- The Data field is specified as a sequence of AVPs. These AVPs are
- concatenated -- including their headers and padding -- in the
- order in which they are specified and the result encapsulated in
- the Data field. The AVP Length field is set to 8 (12 if the 'V'
- bit is enabled) plus the total length of all included AVPs,
- including their headers and padding. Thus, the AVP Length field
- of an AVP of type Grouped is always a multiple of 4.
-
-4.3. Derived AVP Data Formats
-
- In addition to using the Basic AVP Data Formats, applications may
- define data formats derived from the Basic AVP Data Formats. An
- application that defines new Derived AVP Data Formats MUST include
- them in a section titled "Derived AVP Data Formats", using the same
- format as the definitions below. Each new definition MUST be either
- defined or listed with a reference to the RFC that defines the
- format.
-
-4.3.1. Common Derived AVP Data Formats
-
- The following are commonly used Derived AVP Data Formats.
-
- Address
-
- The Address format is derived from the OctetString Basic AVP
- Format. It is a discriminated union representing, for example, a
- 32-bit (IPv4) [RFC0791] or 128-bit (IPv6) [RFC4291] address, most
- significant octet first. The first two octets of the Address AVP
- represent the AddressType, which contains an Address Family,
- defined in [IANAADFAM]. The AddressType is used to discriminate
- the content and format of the remaining octets.
-
-
-
-
-Fajardo, et al. Standards Track [Page 44]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Time
-
- The Time format is derived from the OctetString Basic AVP Format.
- The string MUST contain four octets, in the same format as the
- first four bytes are in the NTP timestamp format. The NTP
- timestamp format is defined in Section 3 of [RFC5905].
-
- This represents the number of seconds since 0h on 1 January 1900
- with respect to the Coordinated Universal Time (UTC).
-
- On 6h 28m 16s UTC, 7 February 2036, the time value will overflow.
- Simple Network Time Protocol (SNTP) [RFC5905] describes a
- procedure to extend the time to 2104. This procedure MUST be
- supported by all Diameter nodes.
-
- UTF8String
-
- The UTF8String format is derived from the OctetString Basic AVP
- Format. This is a human-readable string represented using the
- ISO/IEC IS 10646-1 character set, encoded as an OctetString using
- the UTF-8 transformation format [RFC3629].
-
- Since additional code points are added by amendments to the 10646
- standard from time to time, implementations MUST be prepared to
- encounter any code point from 0x00000001 to 0x7fffffff. Byte
- sequences that do not correspond to the valid encoding of a code
- point into UTF-8 charset or are outside this range are prohibited.
-
- The use of control codes SHOULD be avoided. When it is necessary
- to represent a new line, the control code sequence CR LF SHOULD be
- used.
-
- The use of leading or trailing white space SHOULD be avoided.
-
- For code points not directly supported by user interface hardware
- or software, an alternative means of entry and display, such as
- hexadecimal, MAY be provided.
-
- For information encoded in 7-bit US-ASCII, the UTF-8 charset is
- identical to the US-ASCII charset.
-
- UTF-8 may require multiple bytes to represent a single character /
- code point; thus, the length of a UTF8String in octets may be
- different from the number of characters encoded.
-
- Note that the AVP Length field of an UTF8String is measured in
- octets not characters.
-
-
-
-
-Fajardo, et al. Standards Track [Page 45]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- DiameterIdentity
-
- The DiameterIdentity format is derived from the OctetString Basic
- AVP Format.
-
- DiameterIdentity = FQDN/Realm
-
- The DiameterIdentity value is used to uniquely identify either:
-
- * A Diameter node for purposes of duplicate connection and
- routing loop detection.
-
- * A Realm to determine whether messages can be satisfied locally
- or whether they must be routed or redirected.
-
- When a DiameterIdentity value is used to identify a Diameter node,
- the contents of the string MUST be the Fully Qualified Domain Name
- (FQDN) of the Diameter node. If multiple Diameter nodes run on
- the same host, each Diameter node MUST be assigned a unique
- DiameterIdentity. If a Diameter node can be identified by several
- FQDNs, a single FQDN should be picked at startup and used as the
- only DiameterIdentity for that node, whatever the connection on
- which it is sent. In this document, note that DiameterIdentity is
- in ASCII form in order to be compatible with existing DNS
- infrastructure. See Appendix D for interactions between the
- Diameter protocol and Internationalized Domain Names (IDNs).
-
- DiameterURI
-
- The DiameterURI MUST follow the Uniform Resource Identifiers (RFC
- 3986) syntax [RFC3986] rules specified below:
-
- "aaa://" FQDN [ port ] [ transport ] [ protocol ]
-
- ; No transport security
-
- "aaas://" FQDN [ port ] [ transport ] [ protocol ]
-
- ; Transport security used
-
- FQDN = &lt; Fully Qualified Domain Name >
-
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 46]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- port = ":" 1*DIGIT
-
- ; One of the ports used to listen for
- ; incoming connections.
- ; If absent, the default Diameter port
- ; (3868) is assumed if no transport
- ; security is used and port 5658 when
- ; transport security (TLS/TCP and DTLS/SCTP)
- ; is used.
-
- transport = ";transport=" transport-protocol
-
- ; One of the transports used to listen
- ; for incoming connections. If absent,
- ; the default protocol is assumed to be TCP.
- ; UDP MUST NOT be used when the aaa-protocol
- ; field is set to diameter.
-
- transport-protocol = ( "tcp" / "sctp" / "udp" )
-
- protocol = ";protocol=" aaa-protocol
-
- ; If absent, the default AAA protocol
- ; is Diameter.
-
- aaa-protocol = ( "diameter" / "radius" / "tacacs+" )
-
- The following are examples of valid Diameter host identities:
-
- aaa://host.example.com;transport=tcp
- aaa://host.example.com:6666;transport=tcp
- aaa://host.example.com;protocol=diameter
- aaa://host.example.com:6666;protocol=diameter
- aaa://host.example.com:6666;transport=tcp;protocol=diameter
- aaa://host.example.com:1813;transport=udp;protocol=radius
-
- Enumerated
-
- The Enumerated format is derived from the Integer32 Basic AVP
- Format. The definition contains a list of valid values and their
- interpretation and is described in the Diameter application
- introducing the AVP.
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 47]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- IPFilterRule
-
- The IPFilterRule format is derived from the OctetString Basic AVP
- Format and uses the ASCII charset. The rule syntax is a modified
- subset of ipfw(8) from FreeBSD. Packets may be filtered based on
- the following information that is associated with it:
-
- Direction (in or out)
- Source and destination IP address (possibly masked)
- Protocol
- Source and destination port (lists or ranges)
- TCP flags
- IP fragment flag
- IP options
- ICMP types
-
- Rules for the appropriate direction are evaluated in order, with the
- first matched rule terminating the evaluation. Each packet is
- evaluated once. If no rule matches, the packet is dropped if the
- last rule evaluated was a permit, and passed if the last rule was a
- deny.
-
- IPFilterRule filters MUST follow the format:
-
- action dir proto from src to dst [options]
-
- action permit - Allow packets that match the rule.
- deny - Drop packets that match the rule.
-
- dir "in" is from the terminal, "out" is to the
- terminal.
-
- proto An IP protocol specified by number. The "ip"
- keyword means any protocol will match.
-
- src and dst &lt;address/mask> [ports]
-
- The &lt;address/mask> may be specified as:
- ipno An IPv4 or IPv6 number in dotted-
- quad or canonical IPv6 form. Only
- this exact IP number will match the
- rule.
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 48]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- ipno/bits An IP number as above with a mask
- width of the form 192.0.2.10/24. In
- this case, all IP numbers from
- 192.0.2.0 to 192.0.2.255 will match.
- The bit width MUST be valid for the
- IP version, and the IP number MUST
- NOT have bits set beyond the mask.
- For a match to occur, the same IP
- version must be present in the
- packet that was used in describing
- the IP address. To test for a
- particular IP version, the bits part
- can be set to zero. The keyword
- "any" is 0.0.0.0/0 or the IPv6
- equivalent. The keyword "assigned"
- is the address or set of addresses
- assigned to the terminal. For IPv4,
- a typical first rule is often "deny
- in ip! assigned".
-
- The sense of the match can be inverted by
- preceding an address with the not modifier (!),
- causing all other addresses to be matched
- instead. This does not affect the selection of
- port numbers.
-
- With the TCP, UDP, and SCTP protocols, optional
- ports may be specified as:
-
- {port/port-port}[,ports[,...]]
-
- The '-' notation specifies a range of ports
- (including boundaries).
-
- Fragmented packets that have a non-zero offset
- (i.e., not the first fragment) will never match
- a rule that has one or more port
- specifications. See the frag option for
- details on matching fragmented packets.
-
- options:
- frag Match if the packet is a fragment and this is not
- the first fragment of the datagram. frag may not
- be used in conjunction with either tcpflags or
- TCP/UDP port specifications.
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 49]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- ipoptions spec
- Match if the IP header contains the comma-separated
- list of options specified in spec. The
- supported IP options are:
-
- ssrr (strict source route), lsrr (loose source
- route), rr (record packet route), and ts
- (timestamp). The absence of a particular option
- may be denoted with a '!'.
-
- tcpoptions spec
- Match if the TCP header contains the comma-separated
- list of options specified in spec. The
- supported TCP options are:
-
- mss (maximum segment size), window (tcp window
- advertisement), sack (selective ack), ts (rfc1323
- timestamp), and cc (rfc1644 t/tcp connection
- count). The absence of a particular option may
- be denoted with a '!'.
-
- established
- TCP packets only. Match packets that have the RST
- or ACK bits set.
-
- setup TCP packets only. Match packets that have the SYN
- bit set but no ACK bit.
-
-
- tcpflags spec
- TCP packets only. Match if the TCP header
- contains the comma-separated list of flags
- specified in spec. The supported TCP flags are:
-
- fin, syn, rst, psh, ack, and urg. The absence of a
- particular flag may be denoted with a '!'. A rule
- that contains a tcpflags specification can never
- match a fragmented packet that has a non-zero
- offset. See the frag option for details on
- matching fragmented packets.
-
- icmptypes types
- ICMP packets only. Match if the ICMP type is in
- the list types. The list may be specified as any
- combination of ranges or individual types
- separated by commas. Both the numeric values and
- the symbolic values listed below can be used. The
- supported ICMP types are:
-
-
-
-Fajardo, et al. Standards Track [Page 50]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- echo reply (0), destination unreachable (3),
- source quench (4), redirect (5), echo request
- (8), router advertisement (9), router
- solicitation (10), time-to-live exceeded (11), IP
- header bad (12), timestamp request (13),
- timestamp reply (14), information request (15),
- information reply (16), address mask request (17),
- and address mask reply (18).
-
- There is one kind of packet that the access device MUST always
- discard, that is an IP fragment with a fragment offset of one. This
- is a valid packet, but it only has one use, to try to circumvent
- firewalls.
-
- An access device that is unable to interpret or apply a deny rule
- MUST terminate the session. An access device that is unable to
- interpret or apply a permit rule MAY apply a more restrictive rule.
- An access device MAY apply deny rules of its own before the supplied
- rules, for example to protect the access device owner's
- infrastructure.
-
-4.4. Grouped AVP Values
-
- The Diameter protocol allows AVP values of type 'Grouped'. This
- implies that the Data field is actually a sequence of AVPs. It is
- possible to include an AVP with a Grouped type within a Grouped type,
- that is, to nest them. AVPs within an AVP of type Grouped have the
- same padding requirements as non-Grouped AVPs, as defined in
- Section 4.4.
-
- The AVP Code numbering space of all AVPs included in a Grouped AVP is
- the same as for non-Grouped AVPs. Receivers of a Grouped AVP that
- does not have the 'M' (mandatory) bit set and one or more of the
- encapsulated AVPs within the group has the 'M' (mandatory) bit set
- MAY simply be ignored if the Grouped AVP itself is unrecognized. The
- rule applies even if the encapsulated AVP with its 'M' (mandatory)
- bit set is further encapsulated within other sub-groups, i.e., other
- Grouped AVPs embedded within the Grouped AVP.
-
- Every Grouped AVP definition MUST include a corresponding grammar,
- using ABNF [RFC5234] (with modifications), as defined below.
-
- grouped-avp-def = "&lt;" name ">" "::=" avp
-
- name-fmt = ALPHA *(ALPHA / DIGIT / "-")
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 51]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- name = name-fmt
- ; The name has to be the name of an AVP,
- ; defined in the base or extended Diameter
- ; specifications.
-
- avp = header *fixed *required *optional
-
- header = "&lt;" "AVP-Header:" avpcode [vendor] ">"
-
- avpcode = 1*DIGIT
- ; The AVP Code assigned to the Grouped AVP.
-
- vendor = 1*DIGIT
- ; The Vendor-ID assigned to the Grouped AVP.
- ; If absent, the default value of zero is
- ; used.
-
-4.4.1. Example AVP with a Grouped Data Type
-
- The Example-AVP (AVP Code 999999) is of type Grouped and is used to
- clarify how Grouped AVP values work. The Grouped Data field has the
- following CCF grammar:
-
- Example-AVP ::= &lt; AVP Header: 999999 >
- { Origin-Host }
- 1*{ Session-Id }
- *[ AVP ]
-
- An Example-AVP with Grouped Data follows.
-
- The Origin-Host AVP (Section 6.3) is required. In this case:
-
- Origin-Host = "example.com".
-
- One or more Session-Ids must follow. Here there are two:
-
- Session-Id =
- "grump.example.com:33041;23432;893;0AF3B81"
-
- Session-Id =
- "grump.example.com:33054;23561;2358;0AF3B82"
-
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 52]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- optional AVPs included are
-
- Recovery-Policy = &lt;binary>
- 2163bc1d0ad82371f6bc09484133c3f09ad74a0dd5346d54195a7cf0b35
- 2cabc881839a4fdcfbc1769e2677a4c1fb499284c5f70b48f58503a45c5
- c2d6943f82d5930f2b7c1da640f476f0e9c9572a50db8ea6e51e1c2c7bd
- f8bb43dc995144b8dbe297ac739493946803e1cee3e15d9b765008a1b2a
- cf4ac777c80041d72c01e691cf751dbf86e85f509f3988e5875dc905119
- 26841f00f0e29a6d1ddc1a842289d440268681e052b30fb638045f7779c
- 1d873c784f054f688f5001559ecff64865ef975f3e60d2fd7966b8c7f92
-
- Futuristic-Acct-Record = &lt;binary>
- fe19da5802acd98b07a5b86cb4d5d03f0314ab9ef1ad0b67111ff3b90a0
- 57fe29620bf3585fd2dd9fcc38ce62f6cc208c6163c008f4258d1bc88b8
- 17694a74ccad3ec69269461b14b2e7a4c111fb239e33714da207983f58c
- 41d018d56fe938f3cbf089aac12a912a2f0d1923a9390e5f789cb2e5067
- d3427475e49968f841
-
- The data for the optional AVPs is represented in hexadecimal form
- since the format of these AVPs is not known at the time of definition
- of the Example-AVP group nor (likely) at the time when the example
- instance of this AVP is interpreted -- except by Diameter
- implementations that support the same set of AVPs. The encoding
- example illustrates how padding is used and how length fields are
- calculated. Also, note that AVPs may be present in the Grouped AVP
- value that the receiver cannot interpret (here, the Recover-Policy
- and Futuristic-Acct-Record AVPs). The length of the Example-AVP is
- the sum of all the length of the member AVPs, including their
- padding, plus the Example-AVP header size.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 53]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- This AVP would be encoded as follows:
-
- 0 1 2 3 4 5 6 7
- +-------+-------+-------+-------+-------+-------+-------+-------+
- 0 | Example AVP Header (AVP Code = 999999), Length = 496 |
- +-------+-------+-------+-------+-------+-------+-------+-------+
- 8 | Origin-Host AVP Header (AVP Code = 264), Length = 19 |
- +-------+-------+-------+-------+-------+-------+-------+-------+
- 16 | 'e' | 'x' | 'a' | 'm' | 'p' | 'l' | 'e' | '.' |
- +-------+-------+-------+-------+-------+-------+-------+-------+
- 24 | 'c' | 'o' | 'm' |Padding| Session-Id AVP Header |
- +-------+-------+-------+-------+-------+-------+-------+-------+
- 32 | (AVP Code = 263), Length = 49 | 'g' | 'r' | 'u' | 'm' |
- +-------+-------+-------+-------+-------+-------+-------+-------+
- . . .
- +-------+-------+-------+-------+-------+-------+-------+-------+
- 72 | 'F' | '3' | 'B' | '8' | '1' |Padding|Padding|Padding|
- +-------+-------+-------+-------+-------+-------+-------+-------+
- 80 | Session-Id AVP Header (AVP Code = 263), Length = 50 |
- +-------+-------+-------+-------+-------+-------+-------+-------+
- 88 | 'g' | 'r' | 'u' | 'm' | 'p' | '.' | 'e' | 'x' |
- +-------+-------+-------+-------+-------+-------+-------+-------+
- . . .
- +-------+-------+-------+-------+-------+-------+-------+-------+
- 120| '5' | '8' | ';' | '0' | 'A' | 'F' | '3' | 'B' |
- +-------+-------+-------+-------+-------+-------+-------+-------+
- 128| '8' | '2' |Padding|Padding| Recovery-Policy Header (AVP |
- +-------+-------+-------+-------+-------+-------+-------+-------+
- 136| Code = 8341), Length = 223 | 0x21 | 0x63 | 0xbc | 0x1d |
- +-------+-------+-------+-------+-------+-------+-------+-------+
- 144| 0x0a | 0xd8 | 0x23 | 0x71 | 0xf6 | 0xbc | 0x09 | 0x48 |
- +-------+-------+-------+-------+-------+-------+-------+-------+
- . . .
- +-------+-------+-------+-------+-------+-------+-------+-------+
- 352| 0x8c | 0x7f | 0x92 |Padding| Futuristic-Acct-Record Header |
- +-------+-------+-------+-------+-------+-------+-------+-------+
- 328|(AVP Code = 15930),Length = 137| 0xfe | 0x19 | 0xda | 0x58 |
- +-------+-------+-------+-------+-------+-------+-------+-------+
- 336| 0x02 | 0xac | 0xd9 | 0x8b | 0x07 | 0xa5 | 0xb8 | 0xc6 |
- +-------+-------+-------+-------+-------+-------+-------+-------+
- . . .
- +-------+-------+-------+-------+-------+-------+-------+-------+
- 488| 0xe4 | 0x99 | 0x68 | 0xf8 | 0x41 |Padding|Padding|Padding|
- +-------+-------+-------+-------+-------+-------+-------+-------+
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 54]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-4.5. Diameter Base Protocol AVPs
-
- The following table describes the Diameter AVPs defined in the base
- protocol, their AVP Code values, types, and possible flag values.
-
- Due to space constraints, the short form DiamIdent is used to
- represent DiameterIdentity.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 55]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- +----------+
- | AVP Flag |
- | rules |
- |----+-----|
- AVP Section | |MUST |
- Attribute Name Code Defined Data Type |MUST| NOT |
- -----------------------------------------|----+-----|
- Acct- 85 9.8.2 Unsigned32 | M | V |
- Interim-Interval | | |
- Accounting- 483 9.8.7 Enumerated | M | V |
- Realtime-Required | | |
- Acct- 50 9.8.5 UTF8String | M | V |
- Multi-Session-Id | | |
- Accounting- 485 9.8.3 Unsigned32 | M | V |
- Record-Number | | |
- Accounting- 480 9.8.1 Enumerated | M | V |
- Record-Type | | |
- Acct- 44 9.8.4 OctetString| M | V |
- Session-Id | | |
- Accounting- 287 9.8.6 Unsigned64 | M | V |
- Sub-Session-Id | | |
- Acct- 259 6.9 Unsigned32 | M | V |
- Application-Id | | |
- Auth- 258 6.8 Unsigned32 | M | V |
- Application-Id | | |
- Auth-Request- 274 8.7 Enumerated | M | V |
- Type | | |
- Authorization- 291 8.9 Unsigned32 | M | V |
- Lifetime | | |
- Auth-Grace- 276 8.10 Unsigned32 | M | V |
- Period | | |
- Auth-Session- 277 8.11 Enumerated | M | V |
- State | | |
- Re-Auth-Request- 285 8.12 Enumerated | M | V |
- Type | | |
- Class 25 8.20 OctetString| M | V |
- Destination-Host 293 6.5 DiamIdent | M | V |
- Destination- 283 6.6 DiamIdent | M | V |
- Realm | | |
- Disconnect-Cause 273 5.4.3 Enumerated | M | V |
- Error-Message 281 7.3 UTF8String | | V,M |
- Error-Reporting- 294 7.4 DiamIdent | | V,M |
- Host | | |
- Event-Timestamp 55 8.21 Time | M | V |
- Experimental- 297 7.6 Grouped | M | V |
- Result | | |
- -----------------------------------------|----+-----|
-
-
-
-
-Fajardo, et al. Standards Track [Page 56]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- +----------+
- | AVP Flag |
- | rules |
- |----+-----|
- AVP Section | |MUST |
- Attribute Name Code Defined Data Type |MUST| NOT |
- -----------------------------------------|----+-----|
- Experimental- 298 7.7 Unsigned32 | M | V |
- Result-Code | | |
- Failed-AVP 279 7.5 Grouped | M | V |
- Firmware- 267 5.3.4 Unsigned32 | | V,M |
- Revision | | |
- Host-IP-Address 257 5.3.5 Address | M | V |
- Inband-Security | M | V |
- -Id 299 6.10 Unsigned32 | | |
- Multi-Round- 272 8.19 Unsigned32 | M | V |
- Time-Out | | |
- Origin-Host 264 6.3 DiamIdent | M | V |
- Origin-Realm 296 6.4 DiamIdent | M | V |
- Origin-State-Id 278 8.16 Unsigned32 | M | V |
- Product-Name 269 5.3.7 UTF8String | | V,M |
- Proxy-Host 280 6.7.3 DiamIdent | M | V |
- Proxy-Info 284 6.7.2 Grouped | M | V |
- Proxy-State 33 6.7.4 OctetString| M | V |
- Redirect-Host 292 6.12 DiamURI | M | V |
- Redirect-Host- 261 6.13 Enumerated | M | V |
- Usage | | |
- Redirect-Max- 262 6.14 Unsigned32 | M | V |
- Cache-Time | | |
- Result-Code 268 7.1 Unsigned32 | M | V |
- Route-Record 282 6.7.1 DiamIdent | M | V |
- Session-Id 263 8.8 UTF8String | M | V |
- Session-Timeout 27 8.13 Unsigned32 | M | V |
- Session-Binding 270 8.17 Unsigned32 | M | V |
- Session-Server- 271 8.18 Enumerated | M | V |
- Failover | | |
- Supported- 265 5.3.6 Unsigned32 | M | V |
- Vendor-Id | | |
- Termination- 295 8.15 Enumerated | M | V |
- Cause | | |
- User-Name 1 8.14 UTF8String | M | V |
- Vendor-Id 266 5.3.3 Unsigned32 | M | V |
- Vendor-Specific- 260 6.11 Grouped | M | V |
- Application-Id | | |
- -----------------------------------------|----+-----|
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 57]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-5. Diameter Peers
-
- This section describes how Diameter nodes establish connections and
- communicate with peers.
-
-5.1. Peer Connections
-
- Connections between diameter peers are established using their valid
- DiameterIdentity. A Diameter node initiating a connection to a peer
- MUST know the peer's DiameterIdentity. Methods for discovering a
- Diameter peer can be found in Section 5.2.
-
- Although a Diameter node may have many possible peers with which it
- is able to communicate, it may not be economical to have an
- established connection to all of them. At a minimum, a Diameter node
- SHOULD have an established connection with two peers per realm, known
- as the primary and secondary peers. Of course, a node MAY have
- additional connections, if it is deemed necessary. Typically, all
- messages for a realm are sent to the primary peer but, in the event
- that failover procedures are invoked, any pending requests are sent
- to the secondary peer. However, implementations are free to load
- balance requests between a set of peers.
-
- Note that a given peer MAY act as a primary for a given realm while
- acting as a secondary for another realm.
-
- When a peer is deemed suspect, which could occur for various reasons,
- including not receiving a DWA within an allotted time frame, no new
- requests should be forwarded to the peer, but failover procedures are
- invoked. When an active peer is moved to this mode, additional
- connections SHOULD be established to ensure that the necessary number
- of active connections exists.
-
- There are two ways that a peer is removed from the suspect peer list:
-
- 1. The peer is no longer reachable, causing the transport connection
- to be shut down. The peer is moved to the closed state.
-
- 2. Three watchdog messages are exchanged with accepted round-trip
- times, and the connection to the peer is considered stabilized.
-
- In the event the peer being removed is either the primary or
- secondary, an alternate peer SHOULD replace the deleted peer and
- assume the role of either primary or secondary.
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 58]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-5.2. Diameter Peer Discovery
-
- Allowing for dynamic Diameter agent discovery makes possible simpler
- and more robust deployment of Diameter services. In order to promote
- interoperable implementations of Diameter peer discovery, the
- following mechanisms (manual configuration and DNS) are described.
- These are based on existing IETF standards. Both mechanisms MUST be
- supported by all Diameter implementations; either MAY be used.
-
- There are two cases where Diameter peer discovery may be performed.
- The first is when a Diameter client needs to discover a first-hop
- Diameter agent. The second case is when a Diameter agent needs to
- discover another agent for further handling of a Diameter operation.
- In both cases, the following 'search order' is recommended:
-
- 1. The Diameter implementation consults its list of statically
- (manually) configured Diameter agent locations. These will be
- used if they exist and respond.
-
- 2. The Diameter implementation performs a NAPTR query for a server
- in a particular realm. The Diameter implementation has to know,
- in advance, in which realm to look for a Diameter agent. This
- could be deduced, for example, from the 'realm' in an NAI on
- which a Diameter implementation needed to perform a Diameter
- operation.
-
- The NAPTR usage in Diameter follows the S-NAPTR DDDS application
- [RFC3958] in which the SERVICE field includes tags for the
- desired application and supported application protocol. The
- application service tag for a Diameter application is 'aaa' and
- the supported application protocol tags are 'diameter.tcp',
- 'diameter.sctp', 'diameter.dtls', or 'diameter.tls.tcp'
- [RFC6408].
-
- The client can follow the resolution process defined by the
- S-NAPTR DDDS [RFC3958] application to find a matching SRV, A, or
- AAAA record of a suitable peer. The domain suffixes in the NAPTR
- replacement field SHOULD match the domain of the original query.
- An example can be found in Appendix B.
-
- 3. If no NAPTR records are found, the requester directly queries for
- one of the following SRV records: for Diameter over TCP, use
- "_diameter._tcp.realm"; for Diameter over TLS, use
- "_diameters._tcp.realm"; for Diameter over SCTP, use
- "_diameter._sctp.realm"; for Diameter over DTLS, use
- "_diameters._sctp.realm". If SRV records are found, then the
- requester can perform address record query (A RR's and/or AAAA
-
-
-
-
-Fajardo, et al. Standards Track [Page 59]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- RR's) for the target hostname specified in the SRV records
- following the rules given in [RFC2782]. If no SRV records are
- found, the requester gives up.
-
- If the server is using a site certificate, the domain name in the
- NAPTR query and the domain name in the replacement field MUST both be
- valid based on the site certificate handed out by the server in the
- TLS/TCP and DTLS/SCTP or Internet Key Exchange Protocol (IKE)
- exchange. Similarly, the domain name in the SRV query and the domain
- name in the target in the SRV record MUST both be valid based on the
- same site certificate. Otherwise, an attacker could modify the DNS
- records to contain replacement values in a different domain, and the
- client could not validate whether this was the desired behavior or
- the result of an attack.
-
- Also, the Diameter peer MUST check to make sure that the discovered
- peers are authorized to act in its role. Authentication via IKE or
- TLS/TCP and DTLS/SCTP, or validation of DNS RRs via DNSSEC is not
- sufficient to conclude this. For example, a web server may have
- obtained a valid TLS/TCP and DTLS/SCTP certificate, and secured RRs
- may be included in the DNS, but this does not imply that it is
- authorized to act as a Diameter server.
-
- Authorization can be achieved, for example, by the configuration of a
- Diameter server Certification Authority (CA). The server CA issues a
- certificate to the Diameter server, which includes an Object
- Identifier (OID) to indicate the subject is a Diameter server in the
- Extended Key Usage extension [RFC5280]. This certificate is then
- used during TLS/TCP, DTLS/SCTP, or IKE security negotiation.
- However, note that, at the time of writing, no Diameter server
- Certification Authorities exist.
-
- A dynamically discovered peer causes an entry in the peer table (see
- Section 2.6) to be created. Note that entries created via DNS MUST
- expire (or be refreshed) within the DNS Time to Live (TTL). If a
- peer is discovered outside of the local realm, a routing table entry
- (see Section 2.7) for the peer's realm is created. The routing table
- entry's expiration MUST match the peer's expiration value.
-
-5.3. Capabilities Exchange
-
- When two Diameter peers establish a transport connection, they MUST
- exchange the Capabilities Exchange messages, as specified in the peer
- state machine (see Section 5.6). This message allows the discovery
- of a peer's identity and its capabilities (protocol version number,
- the identifiers of supported Diameter applications, security
- mechanisms, etc.).
-
-
-
-
-Fajardo, et al. Standards Track [Page 60]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- The receiver only issues commands to its peers that have advertised
- support for the Diameter application that defines the command. A
- Diameter node MUST cache the supported Application Ids in order to
- ensure that unrecognized commands and/or AVPs are not unnecessarily
- sent to a peer.
-
- A receiver of a Capabilities-Exchange-Request (CER) message that does
- not have any applications in common with the sender MUST return a
- Capabilities-Exchange-Answer (CEA) with the Result-Code AVP set to
- DIAMETER_NO_COMMON_APPLICATION and SHOULD disconnect the transport
- layer connection. Note that receiving a CER or CEA from a peer
- advertising itself as a relay (see Section 2.4) MUST be interpreted
- as having common applications with the peer.
-
- The receiver of the Capabilities-Exchange-Request (CER) MUST
- determine common applications by computing the intersection of its
- own set of supported Application Ids against all of the
- Application-Id AVPs (Auth-Application-Id, Acct-Application-Id, and
- Vendor-Specific-Application-Id) present in the CER. The value of the
- Vendor-Id AVP in the Vendor-Specific-Application-Id MUST NOT be used
- during computation. The sender of the Capabilities-Exchange-Answer
- (CEA) SHOULD include all of its supported applications as a hint to
- the receiver regarding all of its application capabilities.
-
- Diameter implementations SHOULD first attempt to establish a TLS/TCP
- and DTLS/SCTP connection prior to the CER/CEA exchange. This
- protects the capabilities information of both peers. To support
- older Diameter implementations that do not fully conform to this
- document, the transport security MAY still be negotiated via an
- Inband-Security AVP. In this case, the receiver of a Capabilities-
- Exchange-Request (CER) message that does not have any security
- mechanisms in common with the sender MUST return a Capabilities-
- Exchange-Answer (CEA) with the Result-Code AVP set to
- DIAMETER_NO_COMMON_SECURITY and SHOULD disconnect the transport layer
- connection.
-
- CERs received from unknown peers MAY be silently discarded, or a CEA
- MAY be issued with the Result-Code AVP set to DIAMETER_UNKNOWN_PEER.
- In both cases, the transport connection is closed. If the local
- policy permits receiving CERs from unknown hosts, a successful CEA
- MAY be returned. If a CER from an unknown peer is answered with a
- successful CEA, the lifetime of the peer entry is equal to the
- lifetime of the transport connection. In case of a transport
- failure, all the pending transactions destined to the unknown peer
- can be discarded.
-
- The CER and CEA messages MUST NOT be proxied, redirected, or relayed.
-
-
-
-
-Fajardo, et al. Standards Track [Page 61]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Since the CER/CEA messages cannot be proxied, it is still possible
- that an upstream agent will receive a message for which it has no
- available peers to handle the application that corresponds to the
- Command Code. In such instances, the 'E' bit is set in the answer
- message (Section 7) with the Result-Code AVP set to
- DIAMETER_UNABLE_TO_DELIVER to inform the downstream agent to take
- action (e.g., re-routing request to an alternate peer).
-
- With the exception of the Capabilities-Exchange-Request message, a
- message of type Request that includes the Auth-Application-Id or
- Acct-Application-Id AVPs, or a message with an application-specific
- Command Code MAY only be forwarded to a host that has explicitly
- advertised support for the application (or has advertised the Relay
- Application Id).
-
-5.3.1. Capabilities-Exchange-Request
-
- The Capabilities-Exchange-Request (CER), indicated by the Command
- Code set to 257 and the Command Flags' 'R' bit set, is sent to
- exchange local capabilities. Upon detection of a transport failure,
- this message MUST NOT be sent to an alternate peer.
-
- When Diameter is run over SCTP [RFC4960] or DTLS/SCTP [RFC6083],
- which allow for connections to span multiple interfaces and multiple
- IP addresses, the Capabilities-Exchange-Request message MUST contain
- one Host-IP-Address AVP for each potential IP address that MAY be
- locally used when transmitting Diameter messages.
-
- Message Format
-
- &lt;CER> ::= &lt; Diameter Header: 257, REQ >
- { Origin-Host }
- { Origin-Realm }
- 1* { Host-IP-Address }
- { Vendor-Id }
- { Product-Name }
- [ Origin-State-Id ]
- * [ Supported-Vendor-Id ]
- * [ Auth-Application-Id ]
- * [ Inband-Security-Id ]
- * [ Acct-Application-Id ]
- * [ Vendor-Specific-Application-Id ]
- [ Firmware-Revision ]
- * [ AVP ]
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 62]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-5.3.2. Capabilities-Exchange-Answer
-
- The Capabilities-Exchange-Answer (CEA), indicated by the Command Code
- set to 257 and the Command Flags' 'R' bit cleared, is sent in
- response to a CER message.
-
- When Diameter is run over SCTP [RFC4960] or DTLS/SCTP [RFC6083],
- which allow connections to span multiple interfaces, hence, multiple
- IP addresses, the Capabilities-Exchange-Answer message MUST contain
- one Host-IP-Address AVP for each potential IP address that MAY be
- locally used when transmitting Diameter messages.
-
- Message Format
-
- &lt;CEA> ::= &lt; Diameter Header: 257 >
- { Result-Code }
- { Origin-Host }
- { Origin-Realm }
- 1* { Host-IP-Address }
- { Vendor-Id }
- { Product-Name }
- [ Origin-State-Id ]
- [ Error-Message ]
- [ Failed-AVP ]
- * [ Supported-Vendor-Id ]
- * [ Auth-Application-Id ]
- * [ Inband-Security-Id ]
- * [ Acct-Application-Id ]
- * [ Vendor-Specific-Application-Id ]
- [ Firmware-Revision ]
- * [ AVP ]
-
-5.3.3. Vendor-Id AVP
-
- The Vendor-Id AVP (AVP Code 266) is of type Unsigned32 and contains
- the IANA "SMI Network Management Private Enterprise Codes"
- [ENTERPRISE] value assigned to the Diameter Software vendor. It is
- envisioned that the combination of the Vendor-Id, Product-Name
- (Section 5.3.7), and Firmware-Revision (Section 5.3.4) AVPs may
- provide useful debugging information.
-
- A Vendor-Id value of zero in the CER or CEA message is reserved and
- indicates that this field is ignored.
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 63]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-5.3.4. Firmware-Revision AVP
-
- The Firmware-Revision AVP (AVP Code 267) is of type Unsigned32 and is
- used to inform a Diameter peer of the firmware revision of the
- issuing device.
-
- For devices that do not have a firmware revision (general-purpose
- computers running Diameter software modules, for instance), the
- revision of the Diameter software module may be reported instead.
-
-5.3.5. Host-IP-Address AVP
-
- The Host-IP-Address AVP (AVP Code 257) is of type Address and is used
- to inform a Diameter peer of the sender's IP address. All source
- addresses that a Diameter node expects to use with SCTP [RFC4960] or
- DTLS/SCTP [RFC6083] MUST be advertised in the CER and CEA messages by
- including a Host-IP-Address AVP for each address.
-
-5.3.6. Supported-Vendor-Id AVP
-
- The Supported-Vendor-Id AVP (AVP Code 265) is of type Unsigned32 and
- contains the IANA "SMI Network Management Private Enterprise Codes"
- [ENTERPRISE] value assigned to a vendor other than the device vendor
- but including the application vendor. This is used in the CER and
- CEA messages in order to inform the peer that the sender supports (a
- subset of) the Vendor-Specific AVPs defined by the vendor identified
- in this AVP. The value of this AVP MUST NOT be set to zero.
- Multiple instances of this AVP containing the same value SHOULD NOT
- be sent.
-
-5.3.7. Product-Name AVP
-
- The Product-Name AVP (AVP Code 269) is of type UTF8String and
- contains the vendor-assigned name for the product. The Product-Name
- AVP SHOULD remain constant across firmware revisions for the same
- product.
-
-5.4. Disconnecting Peer Connections
-
- When a Diameter node disconnects one of its transport connections,
- its peer cannot know the reason for the disconnect and will most
- likely assume that a connectivity problem occurred or that the peer
- has rebooted. In these cases, the peer may periodically attempt to
- reconnect, as stated in Section 2.1. In the event that the
- disconnect was a result of either a shortage of internal resources or
- simply that the node in question has no intentions of forwarding any
- Diameter messages to the peer in the foreseeable future, a periodic
-
-
-
-
-Fajardo, et al. Standards Track [Page 64]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- connection request would not be welcomed. The Disconnection-Reason
- AVP contains the reason the Diameter node issued the Disconnect-Peer-
- Request message.
-
- The Disconnect-Peer-Request message is used by a Diameter node to
- inform its peer of its intent to disconnect the transport layer and
- that the peer shouldn't reconnect unless it has a valid reason to do
- so (e.g., message to be forwarded). Upon receipt of the message, the
- Disconnect-Peer-Answer message is returned, which SHOULD contain an
- error if messages have recently been forwarded, and are likely in
- flight, which would otherwise cause a race condition.
-
- The receiver of the Disconnect-Peer-Answer message initiates the
- transport disconnect. The sender of the Disconnect-Peer-Answer
- message should be able to detect the transport closure and clean up
- the connection.
-
-5.4.1. Disconnect-Peer-Request
-
- The Disconnect-Peer-Request (DPR), indicated by the Command Code set
- to 282 and the Command Flags' 'R' bit set, is sent to a peer to
- inform it of its intentions to shut down the transport connection.
- Upon detection of a transport failure, this message MUST NOT be sent
- to an alternate peer.
-
- Message Format
-
- &lt;DPR> ::= &lt; Diameter Header: 282, REQ >
- { Origin-Host }
- { Origin-Realm }
- { Disconnect-Cause }
- * [ AVP ]
-
-5.4.2. Disconnect-Peer-Answer
-
- The Disconnect-Peer-Answer (DPA), indicated by the Command Code set
- to 282 and the Command Flags' 'R' bit cleared, is sent as a response
- to the Disconnect-Peer-Request message. Upon receipt of this
- message, the transport connection is shut down.
-
-
-
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 65]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Message Format
-
- &lt;DPA> ::= &lt; Diameter Header: 282 >
- { Result-Code }
- { Origin-Host }
- { Origin-Realm }
- [ Error-Message ]
- [ Failed-AVP ]
- * [ AVP ]
-
-
-5.4.3. Disconnect-Cause AVP
-
- The Disconnect-Cause AVP (AVP Code 273) is of type Enumerated. A
- Diameter node MUST include this AVP in the Disconnect-Peer-Request
- message to inform the peer of the reason for its intention to shut
- down the transport connection. The following values are supported:
-
- REBOOTING 0
- A scheduled reboot is imminent. A receiver of a DPR with
- above result code MAY attempt reconnection.
-
- BUSY 1
- The peer's internal resources are constrained, and it has
- determined that the transport connection needs to be closed.
- A receiver of a DPR with above result code SHOULD NOT attempt
- reconnection.
-
- DO_NOT_WANT_TO_TALK_TO_YOU 2
- The peer has determined that it does not see a need for the
- transport connection to exist, since it does not expect any
- messages to be exchanged in the near future. A receiver of a
- DPR with above result code SHOULD NOT attempt reconnection.
-
-5.5. Transport Failure Detection
-
- Given the nature of the Diameter protocol, it is recommended that
- transport failures be detected as soon as possible. Detecting such
- failures will minimize the occurrence of messages sent to unavailable
- agents, resulting in unnecessary delays, and will provide better
- failover performance. The Device-Watchdog-Request and Device-
- Watchdog-Answer messages, defined in this section, are used to pro-
- actively detect transport failures.
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 66]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-5.5.1. Device-Watchdog-Request
-
- The Device-Watchdog-Request (DWR), indicated by the Command Code set
- to 280 and the Command Flags' 'R' bit set, is sent to a peer when no
- traffic has been exchanged between two peers (see Section 5.5.3).
- Upon detection of a transport failure, this message MUST NOT be sent
- to an alternate peer.
-
- Message Format
-
- &lt;DWR> ::= &lt; Diameter Header: 280, REQ >
- { Origin-Host }
- { Origin-Realm }
- [ Origin-State-Id ]
- * [ AVP ]
-
-5.5.2. Device-Watchdog-Answer
-
- The Device-Watchdog-Answer (DWA), indicated by the Command Code set
- to 280 and the Command Flags' 'R' bit cleared, is sent as a response
- to the Device-Watchdog-Request message.
-
- Message Format
-
- &lt;DWA> ::= &lt; Diameter Header: 280 >
- { Result-Code }
- { Origin-Host }
- { Origin-Realm }
- [ Error-Message ]
- [ Failed-AVP ]
- [ Origin-State-Id ]
- * [ AVP ]
-
-5.5.3. Transport Failure Algorithm
-
- The transport failure algorithm is defined in [RFC3539]. All
- Diameter implementations MUST support the algorithm defined in that
- specification in order to be compliant to the Diameter base protocol.
-
-5.5.4. Failover and Failback Procedures
-
- In the event that a transport failure is detected with a peer, it is
- necessary for all pending request messages to be forwarded to an
- alternate agent, if possible. This is commonly referred to as
- "failover".
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 67]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- In order for a Diameter node to perform failover procedures, it is
- necessary for the node to maintain a pending message queue for a
- given peer. When an answer message is received, the corresponding
- request is removed from the queue. The Hop-by-Hop Identifier field
- is used to match the answer with the queued request.
-
- When a transport failure is detected, if possible, all messages in
- the queue are sent to an alternate agent with the T flag set. On
- booting a Diameter client or agent, the T flag is also set on any
- remaining records in non-volatile storage that are still waiting to
- be transmitted. An example of a case where it is not possible to
- forward the message to an alternate server is when the message has a
- fixed destination, and the unavailable peer is the message's final
- destination (see Destination-Host AVP). Such an error requires that
- the agent return an answer message with the 'E' bit set and the
- Result-Code AVP set to DIAMETER_UNABLE_TO_DELIVER.
-
- It is important to note that multiple identical requests or answers
- MAY be received as a result of a failover. The End-to-End Identifier
- field in the Diameter header along with the Origin-Host AVP MUST be
- used to identify duplicate messages.
-
- As described in Section 2.1, a connection request should be
- periodically attempted with the failed peer in order to re-establish
- the transport connection. Once a connection has been successfully
- established, messages can once again be forwarded to the peer. This
- is commonly referred to as "failback".
-
-5.6. Peer State Machine
-
- This section contains a finite state machine that MUST be observed by
- all Diameter implementations. Each Diameter node MUST follow the
- state machine described below when communicating with each peer.
- Multiple actions are separated by commas, and may continue on
- succeeding lines, as space requires. Similarly, state and next state
- may also span multiple lines, as space requires.
-
- This state machine is closely coupled with the state machine
- described in [RFC3539], which is used to open, close, failover,
- probe, and reopen transport connections. In particular, note that
- [RFC3539] requires the use of watchdog messages to probe connections.
- For Diameter, DWR and DWA messages are to be used.
-
- The I- prefix is used to represent the initiator (connecting)
- connection, while the R- prefix is used to represent the responder
- (listening) connection. The lack of a prefix indicates that the
- event or action is the same regardless of the connection on which the
- event occurred.
-
-
-
-Fajardo, et al. Standards Track [Page 68]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- The stable states that a state machine may be in are Closed, I-Open,
- and R-Open; all other states are intermediate. Note that I-Open and
- R-Open are equivalent except for whether the initiator or responder
- transport connection is used for communication.
-
- A CER message is always sent on the initiating connection immediately
- after the connection request is successfully completed. In the case
- of an election, one of the two connections will shut down. The
- responder connection will survive if the Origin-Host of the local
- Diameter entity is higher than that of the peer; the initiator
- connection will survive if the peer's Origin-Host is higher. All
- subsequent messages are sent on the surviving connection. Note that
- the results of an election on one peer are guaranteed to be the
- inverse of the results on the other.
-
- For TLS/TCP and DTLS/SCTP usage, a TLS/TCP and DTLS/SCTP handshake
- SHOULD begin when both ends are in the closed state prior to any
- Diameter message exchanges. The TLS/TCP and DTLS/SCTP connection
- SHOULD be established before sending any CER or CEA message to secure
- and protect the capabilities information of both peers. The TLS/TCP
- and DTLS/SCTP connection SHOULD be disconnected when the state
- machine moves to the closed state. When connecting to responders
- that do not conform to this document (i.e., older Diameter
- implementations that are not prepared to received TLS/TCP and DTLS/
- SCTP connections in the closed state), the initial TLS/TCP and DTLS/
- SCTP connection attempt will fail. The initiator MAY then attempt to
- connect via TCP or SCTP and initiate the TLS/TCP and DTLS/SCTP
- handshake when both ends are in the open state. If the handshake is
- successful, all further messages will be sent via TLS/TCP and DTLS/
- SCTP. If the handshake fails, both ends move to the closed state.
-
- The state machine constrains only the behavior of a Diameter
- implementation as seen by Diameter peers through events on the wire.
-
- Any implementation that produces equivalent results is considered
- compliant.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 69]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- state event action next state
- -----------------------------------------------------------------
- Closed Start I-Snd-Conn-Req Wait-Conn-Ack
- R-Conn-CER R-Accept, R-Open
- Process-CER,
- R-Snd-CEA
-
- Wait-Conn-Ack I-Rcv-Conn-Ack I-Snd-CER Wait-I-CEA
- I-Rcv-Conn-Nack Cleanup Closed
- R-Conn-CER R-Accept, Wait-Conn-Ack/
- Process-CER Elect
- Timeout Error Closed
-
- Wait-I-CEA I-Rcv-CEA Process-CEA I-Open
- R-Conn-CER R-Accept, Wait-Returns
- Process-CER,
- Elect
- I-Peer-Disc I-Disc Closed
- I-Rcv-Non-CEA Error Closed
- Timeout Error Closed
-
- Wait-Conn-Ack/ I-Rcv-Conn-Ack I-Snd-CER,Elect Wait-Returns
- Elect I-Rcv-Conn-Nack R-Snd-CEA R-Open
- R-Peer-Disc R-Disc Wait-Conn-Ack
- R-Conn-CER R-Reject Wait-Conn-Ack/
- Elect
- Timeout Error Closed
-
- Wait-Returns Win-Election I-Disc,R-Snd-CEA R-Open
- I-Peer-Disc I-Disc, R-Open
- R-Snd-CEA
- I-Rcv-CEA R-Disc I-Open
- R-Peer-Disc R-Disc Wait-I-CEA
- R-Conn-CER R-Reject Wait-Returns
- Timeout Error Closed
-
- R-Open Send-Message R-Snd-Message R-Open
- R-Rcv-Message Process R-Open
- R-Rcv-DWR Process-DWR, R-Open
- R-Snd-DWA
- R-Rcv-DWA Process-DWA R-Open
- R-Conn-CER R-Reject R-Open
- Stop R-Snd-DPR Closing
- R-Rcv-DPR R-Snd-DPA Closing
- R-Peer-Disc R-Disc Closed
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 70]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- I-Open Send-Message I-Snd-Message I-Open
- I-Rcv-Message Process I-Open
- I-Rcv-DWR Process-DWR, I-Open
- I-Snd-DWA
- I-Rcv-DWA Process-DWA I-Open
- R-Conn-CER R-Reject I-Open
- Stop I-Snd-DPR Closing
- I-Rcv-DPR I-Snd-DPA Closing
- I-Peer-Disc I-Disc Closed
-
- Closing I-Rcv-DPA I-Disc Closed
- R-Rcv-DPA R-Disc Closed
- Timeout Error Closed
- I-Peer-Disc I-Disc Closed
- R-Peer-Disc R-Disc Closed
-
-5.6.1. Incoming Connections
-
- When a connection request is received from a Diameter peer, it is
- not, in the general case, possible to know the identity of that peer
- until a CER is received from it. This is because host and port
- determine the identity of a Diameter peer; the source port of an
- incoming connection is arbitrary. Upon receipt of a CER, the
- identity of the connecting peer can be uniquely determined from the
- Origin-Host.
-
- For this reason, a Diameter peer must employ logic separate from the
- state machine to receive connection requests, accept them, and await
- the CER. Once the CER arrives on a new connection, the Origin-Host
- that identifies the peer is used to locate the state machine
- associated with that peer, and the new connection and CER are passed
- to the state machine as an R-Conn-CER event.
-
- The logic that handles incoming connections SHOULD close and discard
- the connection if any message other than a CER arrives or if an
- implementation-defined timeout occurs prior to receipt of CER.
-
- Because handling of incoming connections up to and including receipt
- of a CER requires logic, separate from that of any individual state
- machine associated with a particular peer, it is described separately
- in this section rather than in the state machine above.
-
-5.6.2. Events
-
- Transitions and actions in the automaton are caused by events. In
- this section, we will ignore the I- and R- prefixes, since the actual
- event would be identical, but it would occur on one of two possible
- connections.
-
-
-
-Fajardo, et al. Standards Track [Page 71]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Start The Diameter application has signaled that a
- connection should be initiated with the peer.
-
- R-Conn-CER An acknowledgement is received stating that the
- transport connection has been established, and the
- associated CER has arrived.
-
- Rcv-Conn-Ack A positive acknowledgement is received confirming that
- the transport connection is established.
-
- Rcv-Conn-Nack A negative acknowledgement was received stating that
- the transport connection was not established.
-
- Timeout An application-defined timer has expired while waiting
- for some event.
-
- Rcv-CER A CER message from the peer was received.
-
- Rcv-CEA A CEA message from the peer was received.
-
- Rcv-Non-CEA A message, other than a CEA, from the peer was
- received.
-
- Peer-Disc A disconnection indication from the peer was received.
-
- Rcv-DPR A DPR message from the peer was received.
-
- Rcv-DPA A DPA message from the peer was received.
-
- Win-Election An election was held, and the local node was the
- winner.
-
- Send-Message A message is to be sent.
-
- Rcv-Message A message other than CER, CEA, DPR, DPA, DWR, or DWA
- was received.
-
- Stop The Diameter application has signaled that a
- connection should be terminated (e.g., on system
- shutdown).
-
-5.6.3. Actions
-
- Actions in the automaton are caused by events and typically indicate
- the transmission of packets and/or an action to be taken on the
- connection. In this section, we will ignore the I- and R- prefixes,
- since the actual action would be identical, but it would occur on one
- of two possible connections.
-
-
-
-Fajardo, et al. Standards Track [Page 72]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Snd-Conn-Req A transport connection is initiated with the peer.
-
- Accept The incoming connection associated with the R-Conn-CER
- is accepted as the responder connection.
-
- Reject The incoming connection associated with the R-Conn-CER
- is disconnected.
-
- Process-CER The CER associated with the R-Conn-CER is processed.
-
- Snd-CER A CER message is sent to the peer.
-
- Snd-CEA A CEA message is sent to the peer.
-
- Cleanup If necessary, the connection is shut down, and any
- local resources are freed.
-
- Error The transport layer connection is disconnected,
- either politely or abortively, in response to
- an error condition. Local resources are freed.
-
- Process-CEA A received CEA is processed.
-
- Snd-DPR A DPR message is sent to the peer.
-
- Snd-DPA A DPA message is sent to the peer.
-
- Disc The transport layer connection is disconnected,
- and local resources are freed.
-
- Elect An election occurs (see Section 5.6.4 for more
- information).
-
- Snd-Message A message is sent.
-
- Snd-DWR A DWR message is sent.
-
- Snd-DWA A DWA message is sent.
-
- Process-DWR The DWR message is serviced.
-
- Process-DWA The DWA message is serviced.
-
- Process A message is serviced.
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 73]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-5.6.4. The Election Process
-
- The election is performed on the responder. The responder compares
- the Origin-Host received in the CER with its own Origin-Host as two
- streams of octets. If the local Origin-Host lexicographically
- succeeds the received Origin-Host, a Win-Election event is issued
- locally. Diameter identities are in ASCII form; therefore, the
- lexical comparison is consistent with DNS case insensitivity, where
- octets that fall in the ASCII range 'a' through 'z' MUST compare
- equally to their uppercase counterparts between 'A' and 'Z'. See
- Appendix D for interactions between the Diameter protocol and
- Internationalized Domain Name (IDNs).
-
- The winner of the election MUST close the connection it initiated.
- Historically, maintaining the responder side of a connection was more
- efficient than maintaining the initiator side. However, current
- practices makes this distinction irrelevant.
-
-6. Diameter Message Processing
-
- This section describes how Diameter requests and answers are created
- and processed.
-
-6.1. Diameter Request Routing Overview
-
- A request is sent towards its final destination using one of the
- following three combinations of the Destination-Realm and
- Destination-Host AVPs:
-
- o A request that is not able to be proxied (such as a CER) MUST NOT
- contain either Destination-Realm or Destination-Host AVPs.
-
- o A request that needs to be sent to a home server serving a
- specific realm, but not to a specific server (such as the first
- request of a series of round trips), MUST contain a Destination-
- Realm AVP but MUST NOT contain a Destination-Host AVP. For
- Diameter clients, the value of the Destination-Realm AVP MAY be
- extracted from the User-Name AVP, or other methods.
-
- o Otherwise, a request that needs to be sent to a specific home
- server among those serving a given realm MUST contain both the
- Destination-Realm and Destination-Host AVPs.
-
- The Destination-Host AVP is used as described above when the
- destination of the request is fixed, which includes:
-
- o Authentication requests that span multiple round trips.
-
-
-
-
-Fajardo, et al. Standards Track [Page 74]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- o A Diameter message that uses a security mechanism that makes use
- of a pre-established session key shared between the source and the
- final destination of the message.
-
- o Server-initiated messages that MUST be received by a specific
- Diameter client (e.g., access device), such as the Abort-Session-
- Request message, which is used to request that a particular user's
- session be terminated.
-
- Note that an agent can only forward a request to a host described in
- the Destination-Host AVP if the host in question is included in its
- peer table (see Section 2.6). Otherwise, the request is routed based
- on the Destination-Realm only (see Section 6.1.6).
-
- When a message is received, the message is processed in the following
- order:
-
- o If the message is destined for the local host, the procedures
- listed in Section 6.1.4 are followed.
-
- o If the message is intended for a Diameter peer with whom the local
- host is able to directly communicate, the procedures listed in
- Section 6.1.5 are followed. This is known as "Request
- Forwarding".
-
- o The procedure listed in Section 6.1.6 is followed, which is known
- as "Request Routing".
-
- o If none of the above are successful, an answer is returned with
- the Result-Code set to DIAMETER_UNABLE_TO_DELIVER, with the 'E'
- bit set.
-
- For routing of Diameter messages to work within an administrative
- domain, all Diameter nodes within the realm MUST be peers.
-
- The overview contained in this section (6.1) is intended to provide
- general guidelines to Diameter developers. Implementations are free
- to use different methods than the ones described here as long as they
- conform to the requirements specified in Sections 6.1.1 through
- 6.1.9. See Section 7 for more details on error handling.
-
-6.1.1. Originating a Request
-
- When creating a request, in addition to any other procedures
- described in the application definition for that specific request,
- the following procedures MUST be followed:
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 75]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- o the Command Code is set to the appropriate value;
-
- o the 'R' bit is set;
-
- o the End-to-End Identifier is set to a locally unique value;
-
- o the Origin-Host and Origin-Realm AVPs MUST be set to the
- appropriate values, used to identify the source of the message;
- and
-
- o the Destination-Host and Destination-Realm AVPs MUST be set to the
- appropriate values, as described in Section 6.1.
-
-6.1.2. Sending a Request
-
- When sending a request, originated either locally or as the result of
- a forwarding or routing operation, the following procedures SHOULD be
- followed:
-
- o The Hop-by-Hop Identifier SHOULD be set to a locally unique value.
-
- o The message SHOULD be saved in the list of pending requests.
-
- Other actions to perform on the message based on the particular role
- the agent is playing are described in the following sections.
-
-6.1.3. Receiving Requests
-
- A relay or proxy agent MUST check for forwarding loops when receiving
- requests. A loop is detected if the server finds its own identity in
- a Route-Record AVP. When such an event occurs, the agent MUST answer
- with the Result-Code AVP set to DIAMETER_LOOP_DETECTED.
-
-6.1.4. Processing Local Requests
-
- A request is known to be for local consumption when one of the
- following conditions occurs:
-
- o The Destination-Host AVP contains the local host's identity;
-
- o The Destination-Host AVP is not present, the Destination-Realm AVP
- contains a realm the server is configured to process locally, and
- the Diameter application is locally supported; or
-
- o Both the Destination-Host and the Destination-Realm are not
- present.
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 76]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- When a request is locally processed, the rules in Section 6.2 should
- be used to generate the corresponding answer.
-
-6.1.5. Request Forwarding
-
- Request forwarding is done using the Diameter peer table. The
- Diameter peer table contains all of the peers with which the local
- node is able to directly communicate.
-
- When a request is received, and the host encoded in the Destination-
- Host AVP is one that is present in the peer table, the message SHOULD
- be forwarded to the peer.
-
-6.1.6. Request Routing
-
- Diameter request message routing is done via realms and Application
- Ids. A Diameter message that may be forwarded by Diameter agents
- (proxies, redirect agents, or relay agents) MUST include the target
- realm in the Destination-Realm AVP. Request routing SHOULD rely on
- the Destination-Realm AVP and the Application Id present in the
- request message header to aid in the routing decision. The realm MAY
- be retrieved from the User-Name AVP, which is in the form of a
- Network Access Identifier (NAI). The realm portion of the NAI is
- inserted in the Destination-Realm AVP.
-
- Diameter agents MAY have a list of locally supported realms and
- applications, and they MAY have a list of externally supported realms
- and applications. When a request is received that includes a realm
- and/or application that is not locally supported, the message is
- routed to the peer configured in the routing table (see Section 2.7).
-
- Realm names and Application Ids are the minimum supported routing
- criteria, additional information may be needed to support redirect
- semantics.
-
-6.1.7. Predictive Loop Avoidance
-
- Before forwarding or routing a request, Diameter agents, in addition
- to performing the processing described in Section 6.1.3, SHOULD check
- for the presence of a candidate route's peer identity in any of the
- Route-Record AVPs. In the event of the agent detecting the presence
- of a candidate route's peer identity in a Route-Record AVP, the agent
- MUST ignore such a route for the Diameter request message and attempt
- alternate routes if any exist. In case all the candidate routes are
- eliminated by the above criteria, the agent SHOULD return a
- DIAMETER_UNABLE_TO_DELIVER message.
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 77]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-6.1.8. Redirecting Requests
-
- When a redirect agent receives a request whose routing entry is set
- to REDIRECT, it MUST reply with an answer message with the 'E' bit
- set, while maintaining the Hop-by-Hop Identifier in the header, and
- include the Result-Code AVP to DIAMETER_REDIRECT_INDICATION. Each of
- the servers associated with the routing entry are added in a separate
- Redirect-Host AVP.
-
- +------------------+
- | Diameter |
- | Redirect Agent |
- +------------------+
- ^ | 2. command + 'E' bit
- 1. Request | | Result-Code =
- [email protected] | | DIAMETER_REDIRECT_INDICATION +
- | | Redirect-Host AVP(s)
- | v
- +-------------+ 3. Request +-------------+
- | example.com |------------->| example.net |
- | Relay | | Diameter |
- | Agent |&lt;-------------| Server |
- +-------------+ 4. Answer +-------------+
-
- Figure 5: Diameter Redirect Agent
-
- The receiver of an answer message with the 'E' bit set and the
- Result-Code AVP set to DIAMETER_REDIRECT_INDICATION uses the Hop-by-
- Hop Identifier in the Diameter header to identify the request in the
- pending message queue (see Section 5.5.4) that is to be redirected.
- If no transport connection exists with the new peer, one is created,
- and the request is sent directly to it.
-
- Multiple Redirect-Host AVPs are allowed. The receiver of the answer
- message with the 'E' bit set selects exactly one of these hosts as
- the destination of the redirected message.
-
- When the Redirect-Host-Usage AVP included in the answer message has a
- non-zero value, a route entry for the redirect indications is created
- and cached by the receiver. The redirect usage for such a route
- entry is set by the value of Redirect-Host-Usage AVP and the lifetime
- of the cached route entry is set by Redirect-Max-Cache-Time AVP
- value.
-
- It is possible that multiple redirect indications can create multiple
- cached route entries differing only in their redirect usage and the
- peer to forward messages to. As an example, two(2) route entries
- that are created by two(2) redirect indications results in two(2)
-
-
-
-Fajardo, et al. Standards Track [Page 78]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- cached routes for the same realm and Application Id. However, one
- has a redirect usage of ALL_SESSION, where matching requests will be
- forwarded to one peer; the other has a redirect usage of ALL_REALM,
- where request are forwarded to another peer. Therefore, an incoming
- request that matches the realm and Application Id of both routes will
- need additional resolution. In such a case, a routing precedence
- rule MUST be used against the redirect usage value to resolve the
- contention. The precedence rule can be found in Section 6.13.
-
-6.1.9. Relaying and Proxying Requests
-
- A relay or proxy agent MUST append a Route-Record AVP to all requests
- forwarded. The AVP contains the identity of the peer from which the
- request was received.
-
- The Hop-by-Hop Identifier in the request is saved and replaced with a
- locally unique value. The source of the request is also saved, which
- includes the IP address, port, and protocol.
-
- A relay or proxy agent MAY include the Proxy-Info AVP in requests if
- it requires access to any local state information when the
- corresponding response is received. The Proxy-Info AVP has security
- implications as state information is distributed to other entities.
- As such, it is RECOMMENDED that the content of the Proxy-Info AVP be
- protected with cryptographic mechanisms, for example, by using a
- keyed message digest such as HMAC-SHA1 [RFC2104]. Such a mechanism,
- however, requires the management of keys, although only locally at
- the Diameter server. Still, a full description of the management of
- the keys used to protect the Proxy-Info AVP is beyond the scope of
- this document. Below is a list of common recommendations:
-
- o The keys should be generated securely following the randomness
- recommendations in [RFC4086].
-
- o The keys and cryptographic protection algorithms should be at
- least 128 bits in strength.
-
- o The keys should not be used for any other purpose than generating
- and verifying instances of the Proxy-Info AVP.
-
- o The keys should be changed regularly.
-
- o The keys should be changed if the AVP format or cryptographic
- protection algorithms change.
-
- The message is then forwarded to the next hop, as identified in the
- routing table.
-
-
-
-
-Fajardo, et al. Standards Track [Page 79]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Figure 6 provides an example of message routing using the procedures
- listed in these sections.
-
- (Origin-Host=nas.example.net) (Origin-Host=nas.example.net)
- (Origin-Realm=example.net) (Origin-Realm=example.net)
- (Destination-Realm=example.com) (Destination-Realm=example.com)
- (Route-Record=nas.example.net)
- +------+ ------> +------+ ------> +------+
- | | (Request) | | (Request) | |
- | NAS +-------------------+ DRL +-------------------+ HMS |
- | | | | | |
- +------+ &lt;------ +------+ &lt;------ +------+
- example.net (Answer) example.net (Answer) example.com
- (Origin-Host=hms.example.com) (Origin-Host=hms.example.com)
- (Origin-Realm=example.com) (Origin-Realm=example.com)
-
- Figure 6: Routing of Diameter messages
-
- Relay and proxy agents are not required to perform full inspection of
- incoming messages. At a minimum, validation of the message header
- and relevant routing AVPs has to be done when relaying messages.
- Proxy agents may optionally perform more in-depth message validation
- for applications in which it is interested.
-
-6.2. Diameter Answer Processing
-
- When a request is locally processed, the following procedures MUST be
- applied to create the associated answer, in addition to any
- additional procedures that MAY be discussed in the Diameter
- application defining the command:
-
- o The same Hop-by-Hop Identifier in the request is used in the
- answer.
-
- o The local host's identity is encoded in the Origin-Host AVP.
-
- o The Destination-Host and Destination-Realm AVPs MUST NOT be
- present in the answer message.
-
- o The Result-Code AVP is added with its value indicating success or
- failure.
-
- o If the Session-Id is present in the request, it MUST be included
- in the answer.
-
- o Any Proxy-Info AVPs in the request MUST be added to the answer
- message, in the same order they were present in the request.
-
-
-
-
-Fajardo, et al. Standards Track [Page 80]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- o The 'P' bit is set to the same value as the one in the request.
-
- o The same End-to-End identifier in the request is used in the
- answer.
-
- Note that the error messages (see Section 7) are also subjected to
- the above processing rules.
-
-6.2.1. Processing Received Answers
-
- A Diameter client or proxy MUST match the Hop-by-Hop Identifier in an
- answer received against the list of pending requests. The
- corresponding message should be removed from the list of pending
- requests. It SHOULD ignore answers received that do not match a
- known Hop-by-Hop Identifier.
-
-6.2.2. Relaying and Proxying Answers
-
- If the answer is for a request that was proxied or relayed, the agent
- MUST restore the original value of the Diameter header's Hop-by-Hop
- Identifier field.
-
- If the last Proxy-Info AVP in the message is targeted to the local
- Diameter server, the AVP MUST be removed before the answer is
- forwarded.
-
- If a relay or proxy agent receives an answer with a Result-Code AVP
- indicating a failure, it MUST NOT modify the contents of the AVP.
- Any additional local errors detected SHOULD be logged but not
- reflected in the Result-Code AVP. If the agent receives an answer
- message with a Result-Code AVP indicating success, and it wishes to
- modify the AVP to indicate an error, it MUST modify the Result-Code
- AVP to contain the appropriate error in the message destined towards
- the access device as well as include the Error-Reporting-Host AVP; it
- MUST also issue an STR on behalf of the access device towards the
- Diameter server.
-
- The agent MUST then send the answer to the host that it received the
- original request from.
-
-6.3. Origin-Host AVP
-
- The Origin-Host AVP (AVP Code 264) is of type DiameterIdentity, and
- it MUST be present in all Diameter messages. This AVP identifies the
- endpoint that originated the Diameter message. Relay agents MUST NOT
- modify this AVP.
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 81]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- The value of the Origin-Host AVP is guaranteed to be unique within a
- single host.
-
- Note that the Origin-Host AVP may resolve to more than one address as
- the Diameter peer may support more than one address.
-
- This AVP SHOULD be placed as close to the Diameter header as
- possible.
-
-6.4. Origin-Realm AVP
-
- The Origin-Realm AVP (AVP Code 296) is of type DiameterIdentity.
- This AVP contains the Realm of the originator of any Diameter message
- and MUST be present in all messages.
-
- This AVP SHOULD be placed as close to the Diameter header as
- possible.
-
-6.5. Destination-Host AVP
-
- The Destination-Host AVP (AVP Code 293) is of type DiameterIdentity.
- This AVP MUST be present in all unsolicited agent initiated messages,
- MAY be present in request messages, and MUST NOT be present in answer
- messages.
-
- The absence of the Destination-Host AVP will cause a message to be
- sent to any Diameter server supporting the application within the
- realm specified in Destination-Realm AVP.
-
- This AVP SHOULD be placed as close to the Diameter header as
- possible.
-
-6.6. Destination-Realm AVP
-
- The Destination-Realm AVP (AVP Code 283) is of type DiameterIdentity
- and contains the realm to which the message is to be routed. The
- Destination-Realm AVP MUST NOT be present in answer messages.
- Diameter clients insert the realm portion of the User-Name AVP.
- Diameter servers initiating a request message use the value of the
- Origin-Realm AVP from a previous message received from the intended
- target host (unless it is known a priori). When present, the
- Destination-Realm AVP is used to perform message routing decisions.
-
- The CCF for a request message that includes the Destination-Realm AVP
- SHOULD list the Destination-Realm AVP as a required AVP (an AVP
- indicated as {AVP}); otherwise, the message is inherently a non-
- routable message.
-
-
-
-
-Fajardo, et al. Standards Track [Page 82]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- This AVP SHOULD be placed as close to the Diameter header as
- possible.
-
-6.7. Routing AVPs
-
- The AVPs defined in this section are Diameter AVPs used for routing
- purposes. These AVPs change as Diameter messages are processed by
- agents.
-
-6.7.1. Route-Record AVP
-
- The Route-Record AVP (AVP Code 282) is of type DiameterIdentity. The
- identity added in this AVP MUST be the same as the one received in
- the Origin-Host of the Capabilities Exchange message.
-
-6.7.2. Proxy-Info AVP
-
- The Proxy-Info AVP (AVP Code 284) is of type Grouped. This AVP
- contains the identity and local state information of the Diameter
- node that creates and adds it to a message. The Grouped Data field
- has the following CCF grammar:
-
- Proxy-Info ::= &lt; AVP Header: 284 >
- { Proxy-Host }
- { Proxy-State }
- * [ AVP ]
-
-6.7.3. Proxy-Host AVP
-
- The Proxy-Host AVP (AVP Code 280) is of type DiameterIdentity. This
- AVP contains the identity of the host that added the Proxy-Info AVP.
-
-6.7.4. Proxy-State AVP
-
- The Proxy-State AVP (AVP Code 33) is of type OctetString. It
- contains state information that would otherwise be stored at the
- Diameter entity that created it. As such, this AVP MUST be treated
- as opaque data by other Diameter entities.
-
-6.8. Auth-Application-Id AVP
-
- The Auth-Application-Id AVP (AVP Code 258) is of type Unsigned32 and
- is used in order to advertise support of the Authentication and
- Authorization portion of an application (see Section 2.4). If
- present in a message other than CER and CEA, the value of the Auth-
- Application-Id AVP MUST match the Application Id present in the
- Diameter message header.
-
-
-
-
-Fajardo, et al. Standards Track [Page 83]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-6.9. Acct-Application-Id AVP
-
- The Acct-Application-Id AVP (AVP Code 259) is of type Unsigned32 and
- is used in order to advertise support of the accounting portion of an
- application (see Section 2.4). If present in a message other than
- CER and CEA, the value of the Acct-Application-Id AVP MUST match the
- Application Id present in the Diameter message header.
-
-6.10. Inband-Security-Id AVP
-
- The Inband-Security-Id AVP (AVP Code 299) is of type Unsigned32 and
- is used in order to advertise support of the security portion of the
- application. The use of this AVP in CER and CEA messages is NOT
- RECOMMENDED. Instead, discovery of a Diameter entity's security
- capabilities can be done either through static configuration or via
- Diameter Peer Discovery as described in Section 5.2.
-
- The following values are supported:
-
-
- NO_INBAND_SECURITY 0
-
- This peer does not support TLS/TCP and DTLS/SCTP. This is the
- default value, if the AVP is omitted.
-
- TLS 1
-
- This node supports TLS/TCP [RFC5246] and DTLS/SCTP [RFC6083]
- security.
-
-6.11. Vendor-Specific-Application-Id AVP
-
- The Vendor-Specific-Application-Id AVP (AVP Code 260) is of type
- Grouped and is used to advertise support of a vendor-specific
- Diameter application. Exactly one instance of either Auth-
- Application-Id or Acct-Application-Id AVP MUST be present. The
- Application Id carried by either Auth-Application-Id or Acct-
- Application-Id AVP MUST comply with vendor-specific Application Id
- assignment described in Section 11.3. It MUST also match the
- Application Id present in the Diameter header except when used in a
- CER or CEA message.
-
- The Vendor-Id AVP is an informational AVP pertaining to the vendor
- who may have authorship of the vendor-specific Diameter application.
- It MUST NOT be used as a means of defining a completely separate
- vendor-specific Application Id space.
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 84]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- The Vendor-Specific-Application-Id AVP SHOULD be placed as close to
- the Diameter header as possible.
-
- AVP Format
-
- &lt;Vendor-Specific-Application-Id> ::= &lt; AVP Header: 260 >
- { Vendor-Id }
- [ Auth-Application-Id ]
- [ Acct-Application-Id ]
-
- A Vendor-Specific-Application-Id AVP MUST contain exactly one of
- either Auth-Application-Id or Acct-Application-Id. If a Vendor-
- Specific-Application-Id is received without one of these two AVPs,
- then the recipient SHOULD issue an answer with a Result-Code set to
- DIAMETER_MISSING_AVP. The answer SHOULD also include a Failed-AVP,
- which MUST contain an example of an Auth-Application-Id AVP and an
- Acct-Application-Id AVP.
-
- If a Vendor-Specific-Application-Id is received that contains both
- Auth-Application-Id and Acct-Application-Id, then the recipient MUST
- issue an answer with Result-Code set to
- DIAMETER_AVP_OCCURS_TOO_MANY_TIMES. The answer MUST also include a
- Failed-AVP, which MUST contain the received Auth-Application-Id AVP
- and Acct-Application-Id AVP.
-
-6.12. Redirect-Host AVP
-
- The Redirect-Host AVP (AVP Code 292) is of type DiameterURI. One or
- more instances of this AVP MUST be present if the answer message's
- 'E' bit is set and the Result-Code AVP is set to
- DIAMETER_REDIRECT_INDICATION.
-
- Upon receiving the above, the receiving Diameter node SHOULD forward
- the request directly to one of the hosts identified in these AVPs.
- The server contained in the selected Redirect-Host AVP SHOULD be used
- for all messages matching the criteria set by the Redirect-Host-Usage
- AVP.
-
-6.13. Redirect-Host-Usage AVP
-
- The Redirect-Host-Usage AVP (AVP Code 261) is of type Enumerated.
- This AVP MAY be present in answer messages whose 'E' bit is set and
- the Result-Code AVP is set to DIAMETER_REDIRECT_INDICATION.
-
- When present, this AVP provides hints about how the routing entry
- resulting from the Redirect-Host is to be used. The following values
- are supported:
-
-
-
-
-Fajardo, et al. Standards Track [Page 85]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- DONT_CACHE 0
-
- The host specified in the Redirect-Host AVP SHOULD NOT be cached.
- This is the default value.
-
- ALL_SESSION 1
-
- All messages within the same session, as defined by the same value
- of the Session-ID AVP SHOULD be sent to the host specified in the
- Redirect-Host AVP.
-
- ALL_REALM 2
-
- All messages destined for the realm requested SHOULD be sent to
- the host specified in the Redirect-Host AVP.
-
- REALM_AND_APPLICATION 3
-
- All messages for the application requested to the realm specified
- SHOULD be sent to the host specified in the Redirect-Host AVP.
-
- ALL_APPLICATION 4
-
- All messages for the application requested SHOULD be sent to the
- host specified in the Redirect-Host AVP.
-
- ALL_HOST 5
-
- All messages that would be sent to the host that generated the
- Redirect-Host SHOULD be sent to the host specified in the
- Redirect-Host AVP.
-
- ALL_USER 6
-
- All messages for the user requested SHOULD be sent to the host
- specified in the Redirect-Host AVP.
-
- When multiple cached routes are created by redirect indications and
- they differ only in redirect usage and peers to forward requests to
- (see Section 6.1.8), a precedence rule MUST be applied to the
- redirect usage values of the cached routes during normal routing to
- resolve contentions that may occur. The precedence rule is the order
- that dictate which redirect usage should be considered before any
- other as they appear. The order is as follows:
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 86]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- 1. ALL_SESSION
-
- 2. ALL_USER
-
- 3. REALM_AND_APPLICATION
-
- 4. ALL_REALM
-
- 5. ALL_APPLICATION
-
- 6. ALL_HOST
-
-6.14. Redirect-Max-Cache-Time AVP
-
- The Redirect-Max-Cache-Time AVP (AVP Code 262) is of type Unsigned32.
- This AVP MUST be present in answer messages whose 'E' bit is set,
- whose Result-Code AVP is set to DIAMETER_REDIRECT_INDICATION, and
- whose Redirect-Host-Usage AVP set to a non-zero value.
-
- This AVP contains the maximum number of seconds the peer and route
- table entries, created as a result of the Redirect-Host, SHOULD be
- cached. Note that once a host is no longer reachable, any associated
- cache, peer, and routing table entries MUST be deleted.
-
-7. Error Handling
-
- There are two different types of errors in Diameter; protocol errors
- and application errors. A protocol error is one that occurs at the
- base protocol level and MAY require per-hop attention (e.g., a
- message routing error). Application errors, on the other hand,
- generally occur due to a problem with a function specified in a
- Diameter application (e.g., user authentication, missing AVP).
-
- Result-Code AVP values that are used to report protocol errors MUST
- only be present in answer messages whose 'E' bit is set. When a
- request message is received that causes a protocol error, an answer
- message is returned with the 'E' bit set, and the Result-Code AVP is
- set to the appropriate protocol error value. As the answer is sent
- back towards the originator of the request, each proxy or relay agent
- MAY take action on the message.
-
-
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 87]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- 1. Request +---------+ Link Broken
- +-------------------------->|Diameter |----///----+
- | +---------------------| | v
- +------+--+ | 2. answer + 'E' set | Relay 2 | +--------+
- |Diameter |&lt;-+ (Unable to Forward) +---------+ |Diameter|
- | | | Home |
- | Relay 1 |--+ +---------+ | Server |
- +---------+ | 3. Request |Diameter | +--------+
- +-------------------->| | ^
- | Relay 3 |-----------+
- +---------+
-
- Figure 7: Example of Protocol Error Causing Answer Message
-
- Figure 7 provides an example of a message forwarded upstream by a
- Diameter relay. When the message is received by Relay 2, and it
- detects that it cannot forward the request to the home server, an
- answer message is returned with the 'E' bit set and the Result-Code
- AVP set to DIAMETER_UNABLE_TO_DELIVER. Given that this error falls
- within the protocol error category, Relay 1 would take special
- action, and given the error, attempt to route the message through its
- alternate Relay 3.
-
- +---------+ 1. Request +---------+ 2. Request +---------+
- | Access |------------>|Diameter |------------>|Diameter |
- | | | | | Home |
- | Device |&lt;------------| Relay |&lt;------------| Server |
- +---------+ 4. Answer +---------+ 3. Answer +---------+
- (Missing AVP) (Missing AVP)
-
- Figure 8: Example of Application Error Answer Message
-
- Figure 8 provides an example of a Diameter message that caused an
- application error. When application errors occur, the Diameter
- entity reporting the error clears the 'R' bit in the Command Flags
- and adds the Result-Code AVP with the proper value. Application
- errors do not require any proxy or relay agent involvement;
- therefore, the message would be forwarded back to the originator of
- the request.
-
- In the case where the answer message itself contains errors, any
- related session SHOULD be terminated by sending an STR or ASR
- message. The Termination-Cause AVP in the STR MAY be filled with the
- appropriate value to indicate the cause of the error. An application
- MAY also send an application-specific request instead of an STR or
- ASR message to signal the error in the case where no state is
- maintained or to allow for some form of error recovery with the
- corresponding Diameter entity.
-
-
-
-Fajardo, et al. Standards Track [Page 88]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- There are certain Result-Code AVP application errors that require
- additional AVPs to be present in the answer. In these cases, the
- Diameter node that sets the Result-Code AVP to indicate the error
- MUST add the AVPs. Examples are as follows:
-
- o A request with an unrecognized AVP is received with the 'M' bit
- (Mandatory bit) set causes an answer to be sent with the Result-
- Code AVP set to DIAMETER_AVP_UNSUPPORTED and the Failed-AVP AVP
- containing the offending AVP.
-
- o A request with an AVP that is received with an unrecognized value
- causes an answer to be returned with the Result-Code AVP set to
- DIAMETER_INVALID_AVP_VALUE, with the Failed-AVP AVP containing the
- AVP causing the error.
-
- o A received command that is missing AVPs that are defined as
- required in the commands CCF; examples are AVPs indicated as
- {AVP}. The receiver issues an answer with the Result-Code set to
- DIAMETER_MISSING_AVP and creates an AVP with the AVP Code and
- other fields set as expected in the missing AVP. The created AVP
- is then added to the Failed-AVP AVP.
-
- The Result-Code AVP describes the error that the Diameter node
- encountered in its processing. In case there are multiple errors,
- the Diameter node MUST report only the first error it encountered
- (detected possibly in some implementation-dependent order). The
- specific errors that can be described by this AVP are described in
- the following section.
-
-7.1. Result-Code AVP
-
- The Result-Code AVP (AVP Code 268) is of type Unsigned32 and
- indicates whether a particular request was completed successfully or
- an error occurred. All Diameter answer messages in IETF-defined
- Diameter application specifications MUST include one Result-Code AVP.
- A non-successful Result-Code AVP (one containing a non-2xxx value
- other than DIAMETER_REDIRECT_INDICATION) MUST include the Error-
- Reporting-Host AVP if the host setting the Result-Code AVP is
- different from the identity encoded in the Origin-Host AVP.
-
- The Result-Code data field contains an IANA-managed 32-bit address
- space representing errors (see Section 11.3.2). Diameter provides
- the following classes of errors, all identified by the thousands
- digit in the decimal notation:
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 89]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- o 1xxx (Informational)
-
- o 2xxx (Success)
-
- o 3xxx (Protocol Errors)
-
- o 4xxx (Transient Failures)
-
- o 5xxx (Permanent Failure)
-
- An unrecognized class (one whose first digit is not defined in this
- section) MUST be handled as a permanent failure.
-
-7.1.1. Informational
-
- Errors that fall within this category are used to inform the
- requester that a request could not be satisfied, and additional
- action is required on its part before access is granted.
-
- DIAMETER_MULTI_ROUND_AUTH 1001
-
- This informational error is returned by a Diameter server to
- inform the access device that the authentication mechanism being
- used requires multiple round trips, and a subsequent request needs
- to be issued in order for access to be granted.
-
-7.1.2. Success
-
- Errors that fall within the Success category are used to inform a
- peer that a request has been successfully completed.
-
- DIAMETER_SUCCESS 2001
-
- The request was successfully completed.
-
- DIAMETER_LIMITED_SUCCESS 2002
-
- When returned, the request was successfully completed, but
- additional processing is required by the application in order to
- provide service to the user.
-
-7.1.3. Protocol Errors
-
- Errors that fall within the Protocol Error category SHOULD be treated
- on a per-hop basis, and Diameter proxies MAY attempt to correct the
- error, if it is possible. Note that these errors MUST only be used
- in answer messages whose 'E' bit is set.
-
-
-
-
-Fajardo, et al. Standards Track [Page 90]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- DIAMETER_COMMAND_UNSUPPORTED 3001
-
- This error code is used when a Diameter entity receives a message
- with a Command Code that it does not support.
-
- DIAMETER_UNABLE_TO_DELIVER 3002
-
- This error is given when Diameter cannot deliver the message to
- the destination, either because no host within the realm
- supporting the required application was available to process the
- request or because the Destination-Host AVP was given without the
- associated Destination-Realm AVP.
-
- DIAMETER_REALM_NOT_SERVED 3003
-
- The intended realm of the request is not recognized.
-
- DIAMETER_TOO_BUSY 3004
-
- When returned, a Diameter node SHOULD attempt to send the message
- to an alternate peer. This error MUST only be used when a
- specific server is requested, and it cannot provide the requested
- service.
-
- DIAMETER_LOOP_DETECTED 3005
-
- An agent detected a loop while trying to get the message to the
- intended recipient. The message MAY be sent to an alternate peer,
- if one is available, but the peer reporting the error has
- identified a configuration problem.
-
- DIAMETER_REDIRECT_INDICATION 3006
-
- A redirect agent has determined that the request could not be
- satisfied locally, and the initiator of the request SHOULD direct
- the request directly to the server, whose contact information has
- been added to the response. When set, the Redirect-Host AVP MUST
- be present.
-
- DIAMETER_APPLICATION_UNSUPPORTED 3007
-
- A request was sent for an application that is not supported.
-
- DIAMETER_INVALID_HDR_BITS 3008
-
- A request was received whose bits in the Diameter header were set
- either to an invalid combination or to a value that is
- inconsistent with the Command Code's definition.
-
-
-
-Fajardo, et al. Standards Track [Page 91]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- DIAMETER_INVALID_AVP_BITS 3009
-
- A request was received that included an AVP whose flag bits are
- set to an unrecognized value or that is inconsistent with the
- AVP's definition.
-
- DIAMETER_UNKNOWN_PEER 3010
-
- A CER was received from an unknown peer.
-
-7.1.4. Transient Failures
-
- Errors that fall within the transient failures category are used to
- inform a peer that the request could not be satisfied at the time it
- was received but MAY be able to satisfy the request in the future.
- Note that these errors MUST be used in answer messages whose 'E' bit
- is not set.
-
- DIAMETER_AUTHENTICATION_REJECTED 4001
-
- The authentication process for the user failed, most likely due to
- an invalid password used by the user. Further attempts MUST only
- be tried after prompting the user for a new password.
-
- DIAMETER_OUT_OF_SPACE 4002
-
- A Diameter node received the accounting request but was unable to
- commit it to stable storage due to a temporary lack of space.
-
- ELECTION_LOST 4003
-
- The peer has determined that it has lost the election process and
- has therefore disconnected the transport connection.
-
-7.1.5. Permanent Failures
-
- Errors that fall within the permanent failures category are used to
- inform the peer that the request failed and should not be attempted
- again. Note that these errors SHOULD be used in answer messages
- whose 'E' bit is not set. In error conditions where it is not
- possible or efficient to compose application-specific answer grammar,
- answer messages with the 'E' bit set and which comply to the grammar
- described in Section 7.2 MAY also be used for permanent errors.
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 92]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- DIAMETER_AVP_UNSUPPORTED 5001
-
- The peer received a message that contained an AVP that is not
- recognized or supported and was marked with the 'M' (Mandatory)
- bit. A Diameter message with this error MUST contain one or more
- Failed-AVP AVPs containing the AVPs that caused the failure.
-
- DIAMETER_UNKNOWN_SESSION_ID 5002
-
- The request contained an unknown Session-Id.
-
- DIAMETER_AUTHORIZATION_REJECTED 5003
-
- A request was received for which the user could not be authorized.
- This error could occur if the service requested is not permitted
- to the user.
-
- DIAMETER_INVALID_AVP_VALUE 5004
-
- The request contained an AVP with an invalid value in its data
- portion. A Diameter message indicating this error MUST include
- the offending AVPs within a Failed-AVP AVP.
-
- DIAMETER_MISSING_AVP 5005
-
- The request did not contain an AVP that is required by the Command
- Code definition. If this value is sent in the Result-Code AVP, a
- Failed-AVP AVP SHOULD be included in the message. The Failed-AVP
- AVP MUST contain an example of the missing AVP complete with the
- Vendor-Id if applicable. The value field of the missing AVP
- should be of correct minimum length and contain zeroes.
-
- DIAMETER_RESOURCES_EXCEEDED 5006
-
- A request was received that cannot be authorized because the user
- has already expended allowed resources. An example of this error
- condition is when a user that is restricted to one dial-up PPP
- port attempts to establish a second PPP connection.
-
- DIAMETER_CONTRADICTING_AVPS 5007
-
- The Home Diameter server has detected AVPs in the request that
- contradicted each other, and it is not willing to provide service
- to the user. The Failed-AVP AVP MUST be present, which contain
- the AVPs that contradicted each other.
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 93]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- DIAMETER_AVP_NOT_ALLOWED 5008
-
- A message was received with an AVP that MUST NOT be present. The
- Failed-AVP AVP MUST be included and contain a copy of the
- offending AVP.
-
- DIAMETER_AVP_OCCURS_TOO_MANY_TIMES 5009
-
- A message was received that included an AVP that appeared more
- often than permitted in the message definition. The Failed-AVP
- AVP MUST be included and contain a copy of the first instance of
- the offending AVP that exceeded the maximum number of occurrences.
-
- DIAMETER_NO_COMMON_APPLICATION 5010
-
- This error is returned by a Diameter node that receives a CER
- whereby no applications are common between the CER sending peer
- and the CER receiving peer.
-
- DIAMETER_UNSUPPORTED_VERSION 5011
-
- This error is returned when a request was received, whose version
- number is unsupported.
-
- DIAMETER_UNABLE_TO_COMPLY 5012
-
- This error is returned when a request is rejected for unspecified
- reasons.
-
- DIAMETER_INVALID_BIT_IN_HEADER 5013
-
- This error is returned when a reserved bit in the Diameter header
- is set to one (1) or the bits in the Diameter header are set
- incorrectly.
-
- DIAMETER_INVALID_AVP_LENGTH 5014
-
- The request contained an AVP with an invalid length. A Diameter
- message indicating this error MUST include the offending AVPs
- within a Failed-AVP AVP. In cases where the erroneous AVP length
- value exceeds the message length or is less than the minimum AVP
- header length, it is sufficient to include the offending AVP
- header and a zero filled payload of the minimum required length
- for the payloads data type. If the AVP is a Grouped AVP, the
- Grouped AVP header with an empty payload would be sufficient to
- indicate the offending AVP. In the case where the offending AVP
- header cannot be fully decoded when the AVP length is less than
-
-
-
-
-Fajardo, et al. Standards Track [Page 94]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- the minimum AVP header length, it is sufficient to include an
- offending AVP header that is formulated by padding the incomplete
- AVP header with zero up to the minimum AVP header length.
-
- DIAMETER_INVALID_MESSAGE_LENGTH 5015
-
- This error is returned when a request is received with an invalid
- message length.
-
- DIAMETER_INVALID_AVP_BIT_COMBO 5016
-
- The request contained an AVP with which is not allowed to have the
- given value in the AVP Flags field. A Diameter message indicating
- this error MUST include the offending AVPs within a Failed-AVP
- AVP.
-
- DIAMETER_NO_COMMON_SECURITY 5017
-
- This error is returned when a CER message is received, and there
- are no common security mechanisms supported between the peers. A
- Capabilities-Exchange-Answer (CEA) message MUST be returned with
- the Result-Code AVP set to DIAMETER_NO_COMMON_SECURITY.
-
-7.2. Error Bit
-
- The 'E' (Error Bit) in the Diameter header is set when the request
- caused a protocol-related error (see Section 7.1.3). A message with
- the 'E' bit MUST NOT be sent as a response to an answer message.
- Note that a message with the 'E' bit set is still subjected to the
- processing rules defined in Section 6.2. When set, the answer
- message will not conform to the CCF specification for the command;
- instead, it and will conform to the following CCF:
-
- Message Format
-
- &lt;answer-message> ::= &lt; Diameter Header: code, ERR [, PXY] >
- 0*1&lt; Session-Id >
- { Origin-Host }
- { Origin-Realm }
- { Result-Code }
- [ Origin-State-Id ]
- [ Error-Message ]
- [ Error-Reporting-Host ]
- [ Failed-AVP ]
- [ Experimental-Result ]
- * [ Proxy-Info ]
- * [ AVP ]
-
-
-
-
-Fajardo, et al. Standards Track [Page 95]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Note that the code used in the header is the same than the one found
- in the request message, but with the 'R' bit cleared and the 'E' bit
- set. The 'P' bit in the header is set to the same value as the one
- found in the request message.
-
-7.3. Error-Message AVP
-
- The Error-Message AVP (AVP Code 281) is of type UTF8String. It MAY
- accompany a Result-Code AVP as a human-readable error message. The
- Error-Message AVP is not intended to be useful in an environment
- where error messages are processed automatically. It SHOULD NOT be
- expected that the content of this AVP be parsed by network entities.
-
-7.4. Error-Reporting-Host AVP
-
- The Error-Reporting-Host AVP (AVP Code 294) is of type
- DiameterIdentity. This AVP contains the identity of the Diameter
- host that sent the Result-Code AVP to a value other than 2001
- (Success), only if the host setting the Result-Code is different from
- the one encoded in the Origin-Host AVP. This AVP is intended to be
- used for troubleshooting purposes, and it MUST be set when the
- Result-Code AVP indicates a failure.
-
-7.5. Failed-AVP AVP
-
- The Failed-AVP AVP (AVP Code 279) is of type Grouped and provides
- debugging information in cases where a request is rejected or not
- fully processed due to erroneous information in a specific AVP. The
- value of the Result-Code AVP will provide information on the reason
- for the Failed-AVP AVP. A Diameter answer message SHOULD contain an
- instance of the Failed-AVP AVP that corresponds to the error
- indicated by the Result-Code AVP. For practical purposes, this
- Failed-AVP would typically refer to the first AVP processing error
- that a Diameter node encounters.
-
- The possible reasons for this AVP are the presence of an improperly
- constructed AVP, an unsupported or unrecognized AVP, an invalid AVP
- value, the omission of a required AVP, the presence of an explicitly
- excluded AVP (see tables in Section 10) or the presence of two or
- more occurrences of an AVP that is restricted to 0, 1, or 0-1
- occurrences.
-
- A Diameter message SHOULD contain one Failed-AVP AVP, containing the
- entire AVP that could not be processed successfully. If the failure
- reason is omission of a required AVP, an AVP with the missing AVP
- code, the missing Vendor-Id, and a zero-filled payload of the minimum
- required length for the omitted AVP will be added. If the failure
- reason is an invalid AVP length where the reported length is less
-
-
-
-Fajardo, et al. Standards Track [Page 96]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- than the minimum AVP header length or greater than the reported
- message length, a copy of the offending AVP header and a zero-filled
- payload of the minimum required length SHOULD be added.
-
- In the case where the offending AVP is embedded within a Grouped AVP,
- the Failed-AVP MAY contain the grouped AVP, which in turn contains
- the single offending AVP. The same method MAY be employed if the
- grouped AVP itself is embedded in yet another grouped AVP and so on.
- In this case, the Failed-AVP MAY contain the grouped AVP hierarchy up
- to the single offending AVP. This enables the recipient to detect
- the location of the offending AVP when embedded in a group.
-
- AVP Format
-
- &lt;Failed-AVP> ::= &lt; AVP Header: 279 >
- 1* {AVP}
-
-7.6. Experimental-Result AVP
-
- The Experimental-Result AVP (AVP Code 297) is of type Grouped, and
- indicates whether a particular vendor-specific request was completed
- successfully or whether an error occurred. This AVP has the
- following structure:
-
- AVP Format
-
- Experimental-Result ::= &lt; AVP Header: 297 >
- { Vendor-Id }
- { Experimental-Result-Code }
-
- The Vendor-Id AVP (see Section 5.3.3) in this grouped AVP identifies
- the vendor responsible for the assignment of the result code that
- follows. All Diameter answer messages defined in vendor-specific
- applications MUST include either one Result-Code AVP or one
- Experimental-Result AVP.
-
-7.7. Experimental-Result-Code AVP
-
- The Experimental-Result-Code AVP (AVP Code 298) is of type Unsigned32
- and contains a vendor-assigned value representing the result of
- processing the request.
-
- It is recommended that vendor-specific result codes follow the same
- conventions given for the Result-Code AVP regarding the different
- types of result codes and the handling of errors (for non-2xxx
- values).
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 97]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-8. Diameter User Sessions
-
- In general, Diameter can provide two different types of services to
- applications. The first involves authentication and authorization,
- and it can optionally make use of accounting. The second only makes
- use of accounting.
-
- When a service makes use of the authentication and/or authorization
- portion of an application, and a user requests access to the network,
- the Diameter client issues an auth request to its local server. The
- auth request is defined in a service-specific Diameter application
- (e.g., NASREQ). The request contains a Session-Id AVP, which is used
- in subsequent messages (e.g., subsequent authorization, accounting,
- etc.) relating to the user's session. The Session-Id AVP is a means
- for the client and servers to correlate a Diameter message with a
- user session.
-
- When a Diameter server authorizes a user to implement network
- resources for a finite amount of time, and it is willing to extend
- the authorization via a future request, it MUST add the
- Authorization- Lifetime AVP to the answer message. The
- Authorization-Lifetime AVP defines the maximum number of seconds a
- user MAY make use of the resources before another authorization
- request is expected by the server. The Auth-Grace-Period AVP
- contains the number of seconds following the expiration of the
- Authorization-Lifetime, after which the server will release all state
- information related to the user's session. Note that if payment for
- services is expected by the serving realm from the user's home realm,
- the Authorization-Lifetime AVP, combined with the Auth-Grace-Period
- AVP, implies the maximum length of the session for which the home
- realm is willing to be fiscally responsible. Services provided past
- the expiration of the Authorization-Lifetime and Auth-Grace-Period
- AVPs are the responsibility of the access device. Of course, the
- actual cost of services rendered is clearly outside the scope of the
- protocol.
-
- An access device that does not expect to send a re-authorization or a
- session termination request to the server MAY include the Auth-
- Session-State AVP with the value set to NO_STATE_MAINTAINED as a hint
- to the server. If the server accepts the hint, it agrees that since
- no session termination message will be received once service to the
- user is terminated, it cannot maintain state for the session. If the
- answer message from the server contains a different value in the
- Auth-Session-State AVP (or the default value if the AVP is absent),
- the access device MUST follow the server's directives. Note that the
- value NO_STATE_MAINTAINED MUST NOT be set in subsequent re-
- authorization requests and answers.
-
-
-
-
-Fajardo, et al. Standards Track [Page 98]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- The base protocol does not include any authorization request
- messages, since these are largely application-specific and are
- defined in a Diameter application document. However, the base
- protocol does define a set of messages that are used to terminate
- user sessions. These are used to allow servers that maintain state
- information to free resources.
-
- When a service only makes use of the accounting portion of the
- Diameter protocol, even in combination with an application, the
- Session-Id is still used to identify user sessions. However, the
- session termination messages are not used, since a session is
- signaled as being terminated by issuing an accounting stop message.
-
- Diameter may also be used for services that cannot be easily
- categorized as authentication, authorization, or accounting (e.g.,
- certain Third Generation Partnership Project Internet Multimedia
- System (3GPP IMS) interfaces). In such cases, the finite state
- machine defined in subsequent sections may not be applicable.
- Therefore, the application itself MAY need to define its own finite
- state machine. However, such application-specific state machines
- SHOULD follow the general state machine framework outlined in this
- document such as the use of Session-Id AVPs and the use of STR/STA,
- ASR/ASA messages for stateful sessions.
-
-8.1. Authorization Session State Machine
-
- This section contains a set of finite state machines, which represent
- the life cycle of Diameter sessions and which MUST be observed by all
- Diameter implementations that make use of the authentication and/or
- authorization portion of a Diameter application. The term "Service-
- Specific" below refers to a message defined in a Diameter application
- (e.g., Mobile IPv4, NASREQ).
-
- There are four different authorization session state machines
- supported in the Diameter base protocol. The first two describe a
- session in which the server is maintaining session state, indicated
- by the value of the Auth-Session-State AVP (or its absence). One
- describes the session from a client perspective, the other from a
- server perspective. The second two state machines are used when the
- server does not maintain session state. Here again, one describes
- the session from a client perspective, the other from a server
- perspective.
-
- When a session is moved to the Idle state, any resources that were
- allocated for the particular session must be released. Any event not
- listed in the state machines MUST be considered an error condition,
- and an answer, if applicable, MUST be returned to the originator of
- the message.
-
-
-
-Fajardo, et al. Standards Track [Page 99]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- In the case that an application does not support re-auth, the state
- transitions related to server-initiated re-auth, when both client and
- server sessions maintain state (e.g., Send RAR, Pending, Receive
- RAA), MAY be ignored.
-
- In the state table, the event "Failure to send X" means that the
- Diameter agent is unable to send command X to the desired
- destination. This could be due to the peer being down or due to the
- peer sending back a transient failure or temporary protocol error
- notification DIAMETER_TOO_BUSY or DIAMETER_LOOP_DETECTED in the
- Result-Code AVP of the corresponding Answer command. The event 'X
- successfully sent' is the complement of 'Failure to send X'.
-
- The following state machine is observed by a client when state is
- maintained on the server:
-
- CLIENT, STATEFUL
- State Event Action New State
- ---------------------------------------------------------------
- Idle Client or device requests Send Pending
- access service-
- specific
- auth req
-
- Idle ASR Received Send ASA Idle
- for unknown session with
- Result-Code =
- UNKNOWN_
- SESSION_ID
-
- Idle RAR Received Send RAA Idle
- for unknown session with
- Result-Code =
- UNKNOWN_
- SESSION_ID
-
- Pending Successful service-specific Grant Open
- authorization answer Access
- received with default
- Auth-Session-State value
-
- Pending Successful service-specific Sent STR Discon
- authorization answer received,
- but service not provided
-
- Pending Error processing successful Sent STR Discon
- service-specific authorization
- answer
-
-
-
-Fajardo, et al. Standards Track [Page 100]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Pending Failed service-specific Clean up Idle
- authorization answer received
-
- Open User or client device Send Open
- requests access to service service-
- specific
- auth req
-
- Open Successful service-specific Provide Open
- authorization answer received service
-
- Open Failed service-specific Discon. Idle
- authorization answer user/device
- received.
-
- Open RAR received and client will Send RAA Open
- perform subsequent re-auth with
- Result-Code =
- SUCCESS
-
- Open RAR received and client will Send RAA Idle
- not perform subsequent with
- re-auth Result-Code !=
- SUCCESS,
- Discon.
- user/device
-
- Open Session-Timeout expires on Send STR Discon
- access device
-
- Open ASR received, Send ASA Discon
- client will comply with
- with request to end the Result-Code =
- session = SUCCESS,
- Send STR.
-
- Open ASR Received, Send ASA Open
- client will not comply with
- with request to end the Result-Code !=
- session != SUCCESS
-
- Open Authorization-Lifetime + Send STR Discon
- Auth-Grace-Period expires on
- access device
-
- Discon ASR received Send ASA Discon
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 101]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Discon STA received Discon. Idle
- user/device
-
- The following state machine is observed by a server when it is
- maintaining state for the session:
-
- SERVER, STATEFUL
- State Event Action New State
- ---------------------------------------------------------------
- Idle Service-specific authorization Send Open
- request received, and successful
- user is authorized service-
- specific
- answer
-
- Idle Service-specific authorization Send Idle
- request received, and failed
- user is not authorized service-
- specific
- answer
-
- Open Service-specific authorization Send Open
- request received, and user successful
- is authorized service-
- specific
- answer
-
- Open Service-specific authorization Send Idle
- request received, and user failed
- is not authorized service-
- specific
- answer,
- Clean up
-
- Open Home server wants to confirm Send RAR Pending
- authentication and/or
- authorization of the user
-
- Pending Received RAA with a failed Clean up Idle
- Result-Code
-
- Pending Received RAA with Result-Code Update Open
- = SUCCESS session
-
- Open Home server wants to Send ASR Discon
- terminate the service
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 102]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Open Authorization-Lifetime (and Clean up Idle
- Auth-Grace-Period) expires
- on home server
-
- Open Session-Timeout expires on Clean up Idle
- home server
-
- Discon Failure to send ASR Wait, Discon
- resend ASR
-
- Discon ASR successfully sent and Clean up Idle
- ASA Received with Result-Code
-
- Not ASA Received None No Change
- Discon
-
- Any STR Received Send STA, Idle
- Clean up
-
- The following state machine is observed by a client when state is not
- maintained on the server:
-
- CLIENT, STATELESS
- State Event Action New State
- ---------------------------------------------------------------
- Idle Client or device requests Send Pending
- access service-
- specific
- auth req
-
- Pending Successful service-specific Grant Open
- authorization answer access
- received with Auth-Session-
- State set to
- NO_STATE_MAINTAINED
-
- Pending Failed service-specific Clean up Idle
- authorization answer
- received
-
- Open Session-Timeout expires on Discon. Idle
- access device user/device
-
- Open Service to user is terminated Discon. Idle
- user/device
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 103]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- The following state machine is observed by a server when it is not
- maintaining state for the session:
-
- SERVER, STATELESS
- State Event Action New State
- ---------------------------------------------------------------
- Idle Service-specific authorization Send Idle
- request received, and service-
- successfully processed specific
- answer
-
-8.2. Accounting Session State Machine
-
- The following state machines MUST be supported for applications that
- have an accounting portion or that require only accounting services.
- The first state machine is to be observed by clients.
-
- See Section 9.7 for Accounting Command Codes and Section 9.8 for
- Accounting AVPs.
-
- The server side in the accounting state machine depends in some cases
- on the particular application. The Diameter base protocol defines a
- default state machine that MUST be followed by all applications that
- have not specified other state machines. This is the second state
- machine in this section described below.
-
- The default server side state machine requires the reception of
- accounting records in any order and at any time, and it does not
- place any standards requirement on the processing of these records.
- Implementations of Diameter may perform checking, ordering,
- correlation, fraud detection, and other tasks based on these records.
- AVPs may need to be inspected as a part of these tasks. The tasks
- can happen either immediately after record reception or in a post-
- processing phase. However, as these tasks are typically application
- or even policy dependent, they are not standardized by the Diameter
- specifications. Applications MAY define requirements on when to
- accept accounting records based on the used value of Accounting-
- Realtime-Required AVP, credit-limit checks, and so on.
-
- However, the Diameter base protocol defines one optional server side
- state machine that MAY be followed by applications that require
- keeping track of the session state at the accounting server. Note
- that such tracking is incompatible with the ability to sustain long
- duration connectivity problems. Therefore, the use of this state
- machine is recommended only in applications where the value of the
- Accounting-Realtime-Required AVP is DELIVER_AND_GRANT; hence,
- accounting connectivity problems are required to cause the serviced
- user to be disconnected. Otherwise, records produced by the client
-
-
-
-Fajardo, et al. Standards Track [Page 104]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- may be lost by the server, which no longer accepts them after the
- connectivity is re-established. This state machine is the third
- state machine in this section. The state machine is supervised by a
- supervision session timer Ts, whose value should be reasonably higher
- than the Acct_Interim_Interval value. Ts MAY be set to two times the
- value of the Acct_Interim_Interval so as to avoid the accounting
- session in the Diameter server to change to Idle state in case of
- short transient network failure.
-
- Any event not listed in the state machines MUST be considered as an
- error condition, and a corresponding answer, if applicable, MUST be
- returned to the originator of the message.
-
- In the state table, the event "Failure to send" means that the
- Diameter client is unable to communicate with the desired
- destination. This could be due to the peer being down, or due to the
- peer sending back a transient failure or temporary protocol error
- notification DIAMETER_OUT_OF_SPACE, DIAMETER_TOO_BUSY, or
- DIAMETER_LOOP_DETECTED in the Result-Code AVP of the Accounting
- Answer command.
-
- The event "Failed answer" means that the Diameter client received a
- non-transient failure notification in the Accounting Answer command.
-
- Note that the action "Disconnect user/dev" MUST also have an effect
- on the authorization session state table, e.g., cause the STR message
- to be sent, if the given application has both authentication/
- authorization and accounting portions.
-
- The states PendingS, PendingI, PendingL, PendingE, and PendingB stand
- for pending states to wait for an answer to an accounting request
- related to a Start, Interim, Stop, Event, or buffered record,
- respectively.
-
- CLIENT, ACCOUNTING
- State Event Action New State
- ---------------------------------------------------------------
- Idle Client or device requests Send PendingS
- access accounting
- start req.
-
- Idle Client or device requests Send PendingE
- a one-time service accounting
- event req
-
- Idle Records in storage Send PendingB
- record
-
-
-
-
-Fajardo, et al. Standards Track [Page 105]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- PendingS Successful accounting Open
- start answer received
-
- PendingS Failure to send and buffer Store Open
- space available and real time Start
- not equal to DELIVER_AND_GRANT Record
-
- PendingS Failure to send and no buffer Open
- space available and real time
- equal to GRANT_AND_LOSE
-
- PendingS Failure to send and no Disconnect Idle
- buffer space available and user/dev
- real time not equal to
- GRANT_AND_LOSE
-
- PendingS Failed accounting start answer Open
- received and real time equal
- to GRANT_AND_LOSE
-
- PendingS Failed accounting start answer Disconnect Idle
- received and real time not user/dev
- equal to GRANT_AND_LOSE
-
- PendingS User service terminated Store PendingS
- stop
- record
-
- Open Interim interval elapses Send PendingI
- accounting
- interim
- record
-
- Open User service terminated Send PendingL
- accounting
- stop req.
-
- PendingI Successful accounting interim Open
- answer received
-
- PendingI Failure to send and (buffer Store Open
- space available or old interim
- record can be overwritten) record
- and real time not equal to
- DELIVER_AND_GRANT
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 106]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- PendingI Failure to send and no buffer Open
- space available and real time
- equal to GRANT_AND_LOSE
-
- PendingI Failure to send and no Disconnect Idle
- buffer space available and user/dev
- real time not equal to
- GRANT_AND_LOSE
-
- PendingI Failed accounting interim Open
- answer received and real time
- equal to GRANT_AND_LOSE
-
- PendingI Failed accounting interim Disconnect Idle
- answer received and user/dev
- real time not equal to
- GRANT_AND_LOSE
-
- PendingI User service terminated Store PendingI
- stop
- record
- PendingE Successful accounting Idle
- event answer received
-
- PendingE Failure to send and buffer Store Idle
- space available event
- record
-
- PendingE Failure to send and no buffer Idle
- space available
-
- PendingE Failed accounting event answer Idle
- received
-
- PendingB Successful accounting answer Delete Idle
- received record
-
- PendingB Failure to send Idle
-
- PendingB Failed accounting answer Delete Idle
- received record
-
- PendingL Successful accounting Idle
- stop answer received
-
- PendingL Failure to send and buffer Store Idle
- space available stop
- record
-
-
-
-Fajardo, et al. Standards Track [Page 107]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- PendingL Failure to send and no buffer Idle
- space available
-
- PendingL Failed accounting stop answer Idle
- received
-
-
- SERVER, STATELESS ACCOUNTING
- State Event Action New State
- ---------------------------------------------------------------
-
- Idle Accounting start request Send Idle
- received and successfully accounting
- processed. start
- answer
-
- Idle Accounting event request Send Idle
- received and successfully accounting
- processed. event
- answer
-
- Idle Interim record received Send Idle
- and successfully processed. accounting
- interim
- answer
-
- Idle Accounting stop request Send Idle
- received and successfully accounting
- processed stop answer
-
- Idle Accounting request received; Send Idle
- no space left to store accounting
- records answer;
- Result-Code =
- OUT_OF_
- SPACE
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 108]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- SERVER, STATEFUL ACCOUNTING
- State Event Action New State
- ---------------------------------------------------------------
-
- Idle Accounting start request Send Open
- received and successfully accounting
- processed. start
- answer;
- Start Ts
-
- Idle Accounting event request Send Idle
- received and successfully accounting
- processed. event
- answer
- Idle Accounting request received; Send Idle
- no space left to store accounting
- records answer;
- Result-Code =
- OUT_OF_
- SPACE
-
- Open Interim record received Send Open
- and successfully processed. accounting
- interim
- answer;
- Restart Ts
-
- Open Accounting stop request Send Idle
- received and successfully accounting
- processed stop answer;
- Stop Ts
-
- Open Accounting request received; Send Idle
- no space left to store accounting
- records answer;
- Result-Code =
- OUT_OF_
- SPACE;
- Stop Ts
-
- Open Session supervision timer Ts Stop Ts Idle
- expired
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 109]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-8.3. Server-Initiated Re-Auth
-
- A Diameter server may initiate a re-authentication and/or re-
- authorization service for a particular session by issuing a Re-Auth-
- Request (RAR).
-
- For example, for prepaid services, the Diameter server that
- originally authorized a session may need some confirmation that the
- user is still using the services.
-
- An access device that receives an RAR message with the Session-Id
- equal to a currently active session MUST initiate a re-auth towards
- the user, if the service supports this particular feature. Each
- Diameter application MUST state whether server-initiated re-auth is
- supported, since some applications do not allow access devices to
- prompt the user for re-auth.
-
-8.3.1. Re-Auth-Request
-
- The Re-Auth-Request (RAR), indicated by the Command Code set to 258
- and the message flags' 'R' bit set, may be sent by any server to the
- access device that is providing session service, to request that the
- user be re-authenticated and/or re-authorized.
-
-
- Message Format
-
- &lt;RAR> ::= &lt; Diameter Header: 258, REQ, PXY >
- &lt; Session-Id >
- { Origin-Host }
- { Origin-Realm }
- { Destination-Realm }
- { Destination-Host }
- { Auth-Application-Id }
- { Re-Auth-Request-Type }
- [ User-Name ]
- [ Origin-State-Id ]
- * [ Proxy-Info ]
- * [ Route-Record ]
- * [ AVP ]
-
-8.3.2. Re-Auth-Answer
-
- The Re-Auth-Answer (RAA), indicated by the Command Code set to 258
- and the message flags' 'R' bit clear, is sent in response to the RAR.
- The Result-Code AVP MUST be present, and it indicates the disposition
- of the request.
-
-
-
-
-Fajardo, et al. Standards Track [Page 110]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- A successful RAA message MUST be followed by an application-specific
- authentication and/or authorization message.
-
- Message Format
-
- &lt;RAA> ::= &lt; Diameter Header: 258, PXY >
- &lt; Session-Id >
- { Result-Code }
- { Origin-Host }
- { Origin-Realm }
- [ User-Name ]
- [ Origin-State-Id ]
- [ Error-Message ]
- [ Error-Reporting-Host ]
- [ Failed-AVP ]
- * [ Redirect-Host ]
- [ Redirect-Host-Usage ]
- [ Redirect-Max-Cache-Time ]
- * [ Proxy-Info ]
- * [ AVP ]
-
-8.4. Session Termination
-
- It is necessary for a Diameter server that authorized a session, for
- which it is maintaining state, to be notified when that session is no
- longer active, both for tracking purposes as well as to allow
- stateful agents to release any resources that they may have provided
- for the user's session. For sessions whose state is not being
- maintained, this section is not used.
-
- When a user session that required Diameter authorization terminates,
- the access device that provided the service MUST issue a Session-
- Termination-Request (STR) message to the Diameter server that
- authorized the service, to notify it that the session is no longer
- active. An STR MUST be issued when a user session terminates for any
- reason, including user logoff, expiration of Session-Timeout,
- administrative action, termination upon receipt of an Abort-Session-
- Request (see below), orderly shutdown of the access device, etc.
-
- The access device also MUST issue an STR for a session that was
- authorized but never actually started. This could occur, for
- example, due to a sudden resource shortage in the access device, or
- because the access device is unwilling to provide the type of service
- requested in the authorization, or because the access device does not
- support a mandatory AVP returned in the authorization, etc.
-
- It is also possible that a session that was authorized is never
- actually started due to action of a proxy. For example, a proxy may
-
-
-
-Fajardo, et al. Standards Track [Page 111]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- modify an authorization answer, converting the result from success to
- failure, prior to forwarding the message to the access device. If
- the answer did not contain an Auth-Session-State AVP with the value
- NO_STATE_MAINTAINED, a proxy that causes an authorized session not to
- be started MUST issue an STR to the Diameter server that authorized
- the session, since the access device has no way of knowing that the
- session had been authorized.
-
- A Diameter server that receives an STR message MUST clean up
- resources (e.g., session state) associated with the Session-Id
- specified in the STR and return a Session-Termination-Answer.
-
- A Diameter server also MUST clean up resources when the Session-
- Timeout expires, or when the Authorization-Lifetime and the Auth-
- Grace-Period AVPs expire without receipt of a re-authorization
- request, regardless of whether an STR for that session is received.
- The access device is not expected to provide service beyond the
- expiration of these timers; thus, expiration of either of these
- timers implies that the access device may have unexpectedly shut
- down.
-
-8.4.1. Session-Termination-Request
-
- The Session-Termination-Request (STR), indicated by the Command Code
- set to 275 and the Command Flags' 'R' bit set, is sent by a Diameter
- client or by a Diameter proxy to inform the Diameter server that an
- authenticated and/or authorized session is being terminated.
-
- Message Format
-
- &lt;STR> ::= &lt; Diameter Header: 275, REQ, PXY >
- &lt; Session-Id >
- { Origin-Host }
- { Origin-Realm }
- { Destination-Realm }
- { Auth-Application-Id }
- { Termination-Cause }
- [ User-Name ]
- [ Destination-Host ]
- * [ Class ]
- [ Origin-State-Id ]
- * [ Proxy-Info ]
- * [ Route-Record ]
- * [ AVP ]
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 112]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-8.4.2. Session-Termination-Answer
-
- The Session-Termination-Answer (STA), indicated by the Command Code
- set to 275 and the message flags' 'R' bit clear, is sent by the
- Diameter server to acknowledge the notification that the session has
- been terminated. The Result-Code AVP MUST be present, and it MAY
- contain an indication that an error occurred while servicing the STR.
-
- Upon sending or receipt of the STA, the Diameter server MUST release
- all resources for the session indicated by the Session-Id AVP. Any
- intermediate server in the Proxy-Chain MAY also release any
- resources, if necessary.
-
- Message Format
-
- &lt;STA> ::= &lt; Diameter Header: 275, PXY >
- &lt; Session-Id >
- { Result-Code }
- { Origin-Host }
- { Origin-Realm }
- [ User-Name ]
- * [ Class ]
- [ Error-Message ]
- [ Error-Reporting-Host ]
- [ Failed-AVP ]
- [ Origin-State-Id ]
- * [ Redirect-Host ]
- [ Redirect-Host-Usage ]
- [ Redirect-Max-Cache-Time ]
- * [ Proxy-Info ]
- * [ AVP ]
-
-8.5. Aborting a Session
-
- A Diameter server may request that the access device stop providing
- service for a particular session by issuing an Abort-Session-Request
- (ASR).
-
- For example, the Diameter server that originally authorized the
- session may be required to cause that session to be stopped for lack
- of credit or other reasons that were not anticipated when the session
- was first authorized.
-
- An access device that receives an ASR with Session-ID equal to a
- currently active session MAY stop the session. Whether the access
- device stops the session or not is implementation and/or
- configuration dependent. For example, an access device may honor
- ASRs from certain agents only. In any case, the access device MUST
-
-
-
-Fajardo, et al. Standards Track [Page 113]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- respond with an Abort-Session-Answer, including a Result-Code AVP to
- indicate what action it took.
-
-8.5.1. Abort-Session-Request
-
- The Abort-Session-Request (ASR), indicated by the Command Code set to
- 274 and the message flags' 'R' bit set, may be sent by any Diameter
- server or any Diameter proxy to the access device that is providing
- session service, to request that the session identified by the
- Session-Id be stopped.
-
- Message Format
-
- &lt;ASR> ::= &lt; Diameter Header: 274, REQ, PXY >
- &lt; Session-Id >
- { Origin-Host }
- { Origin-Realm }
- { Destination-Realm }
- { Destination-Host }
- { Auth-Application-Id }
- [ User-Name ]
- [ Origin-State-Id ]
- * [ Proxy-Info ]
- * [ Route-Record ]
- * [ AVP ]
-
-8.5.2. Abort-Session-Answer
-
- The Abort-Session-Answer (ASA), indicated by the Command Code set to
- 274 and the message flags' 'R' bit clear, is sent in response to the
- ASR. The Result-Code AVP MUST be present and indicates the
- disposition of the request.
-
- If the session identified by Session-Id in the ASR was successfully
- terminated, the Result-Code is set to DIAMETER_SUCCESS. If the
- session is not currently active, the Result-Code is set to
- DIAMETER_UNKNOWN_SESSION_ID. If the access device does not stop the
- session for any other reason, the Result-Code is set to
- DIAMETER_UNABLE_TO_COMPLY.
-
-
-
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 114]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Message Format
-
- &lt;ASA> ::= &lt; Diameter Header: 274, PXY >
- &lt; Session-Id >
- { Result-Code }
- { Origin-Host }
- { Origin-Realm }
- [ User-Name ]
- [ Origin-State-Id ]
- [ Error-Message ]
- [ Error-Reporting-Host ]
- [ Failed-AVP ]
- * [ Redirect-Host ]
- [ Redirect-Host-Usage ]
- [ Redirect-Max-Cache-Time ]
- * [ Proxy-Info ]
- * [ AVP ]
-
-8.6. Inferring Session Termination from Origin-State-Id
-
- The Origin-State-Id is used to allow detection of terminated sessions
- for which no STR would have been issued, due to unanticipated
- shutdown of an access device.
-
- A Diameter client or access device increments the value of the
- Origin-State-Id every time it is started or powered up. The new
- Origin-State-Id is then sent in the CER/CEA message immediately upon
- connection to the server. The Diameter server receiving the new
- Origin-State-Id can determine whether the sending Diameter client had
- abruptly shut down by comparing the old value of the Origin-State-Id
- it has kept for that specific client is less than the new value and
- whether it has un-terminated sessions originating from that client.
-
- An access device can also include the Origin-State-Id in request
- messages other than the CER if there are relays or proxies in between
- the access device and the server. In this case, however, the server
- cannot discover that the access device has been restarted unless and
- until it receives a new request from it. Therefore, this mechanism
- is more opportunistic across proxies and relays.
-
- The Diameter server may assume that all sessions that were active
- prior to detection of a client restart have been terminated. The
- Diameter server MAY clean up all session state associated with such
- lost sessions, and it MAY also issue STRs for all such lost sessions
- that were authorized on upstream servers, to allow session state to
- be cleaned up globally.
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 115]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-8.7. Auth-Request-Type AVP
-
- The Auth-Request-Type AVP (AVP Code 274) is of type Enumerated and is
- included in application-specific auth requests to inform the peers
- whether a user is to be authenticated only, authorized only, or both.
- Note any value other than both MAY cause RADIUS interoperability
- issues. The following values are defined:
-
- AUTHENTICATE_ONLY 1
-
- The request being sent is for authentication only, and it MUST
- contain the relevant application-specific authentication AVPs that
- are needed by the Diameter server to authenticate the user.
-
- AUTHORIZE_ONLY 2
-
- The request being sent is for authorization only, and it MUST
- contain the application-specific authorization AVPs that are
- necessary to identify the service being requested/offered.
-
- AUTHORIZE_AUTHENTICATE 3
-
- The request contains a request for both authentication and
- authorization. The request MUST include both the relevant
- application-specific authentication information and authorization
- information necessary to identify the service being requested/
- offered.
-
-8.8. Session-Id AVP
-
- The Session-Id AVP (AVP Code 263) is of type UTF8String and is used
- to identify a specific session (see Section 8). All messages
- pertaining to a specific session MUST include only one Session-Id
- AVP, and the same value MUST be used throughout the life of a
- session. When present, the Session-Id SHOULD appear immediately
- following the Diameter header (see Section 3).
-
- The Session-Id MUST be globally and eternally unique, as it is meant
- to uniquely identify a user session without reference to any other
- information, and it may be needed to correlate historical
- authentication information with accounting information. The
- Session-Id includes a mandatory portion and an implementation-defined
- portion; a recommended format for the implementation-defined portion
- is outlined below.
-
- The Session-Id MUST begin with the sender's identity encoded in the
- DiameterIdentity type (see Section 4.3.1). The remainder of the
- Session-Id is delimited by a ";" character, and it MAY be any
-
-
-
-Fajardo, et al. Standards Track [Page 116]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- sequence that the client can guarantee to be eternally unique;
- however, the following format is recommended, (square brackets []
- indicate an optional element):
-
- &lt;DiameterIdentity>;&lt;high 32 bits>;&lt;low 32 bits>[;&lt;optional value>]
-
- &lt;high 32 bits> and &lt;low 32 bits> are decimal representations of the
- high and low 32 bits of a monotonically increasing 64-bit value. The
- 64-bit value is rendered in two part to simplify formatting by 32-bit
- processors. At startup, the high 32 bits of the 64-bit value MAY be
- initialized to the time in NTP format [RFC5905], and the low 32 bits
- MAY be initialized to zero. This will for practical purposes
- eliminate the possibility of overlapping Session-Ids after a reboot,
- assuming the reboot process takes longer than a second.
- Alternatively, an implementation MAY keep track of the increasing
- value in non-volatile memory.
-
-
- &lt;optional value> is implementation specific, but it may include a
- modem's device Id, a Layer 2 address, timestamp, etc.
-
- Example, in which there is no optional value:
-
- accesspoint7.example.com;1876543210;523
-
- Example, in which there is an optional value:
-
- accesspoint7.example.com;1876543210;523;[email protected]
-
- The Session-Id is created by the Diameter application initiating the
- session, which, in most cases, is done by the client. Note that a
- Session-Id MAY be used for both the authentication, authorization,
- and accounting commands of a given application.
-
-8.9. Authorization-Lifetime AVP
-
- The Authorization-Lifetime AVP (AVP Code 291) is of type Unsigned32
- and contains the maximum number of seconds of service to be provided
- to the user before the user is to be re-authenticated and/or re-
- authorized. Care should be taken when the Authorization-Lifetime
- value is determined, since a low, non-zero value could create
- significant Diameter traffic, which could congest both the network
- and the agents.
-
- A value of zero (0) means that immediate re-auth is necessary by the
- access device. The absence of this AVP, or a value of all ones
- (meaning all bits in the 32-bit field are set to one) means no re-
- auth is expected.
-
-
-
-Fajardo, et al. Standards Track [Page 117]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- If both this AVP and the Session-Timeout AVP are present in a
- message, the value of the latter MUST NOT be smaller than the
- Authorization-Lifetime AVP.
-
- An Authorization-Lifetime AVP MAY be present in re-authorization
- messages, and it contains the number of seconds the user is
- authorized to receive service from the time the re-auth answer
- message is received by the access device.
-
- This AVP MAY be provided by the client as a hint of the maximum
- lifetime that it is willing to accept. The server MUST return a
- value that is equal to, or smaller than, the one provided by the
- client.
-
-8.10. Auth-Grace-Period AVP
-
- The Auth-Grace-Period AVP (AVP Code 276) is of type Unsigned32 and
- contains the number of seconds the Diameter server will wait
- following the expiration of the Authorization-Lifetime AVP before
- cleaning up resources for the session.
-
-8.11. Auth-Session-State AVP
-
- The Auth-Session-State AVP (AVP Code 277) is of type Enumerated and
- specifies whether state is maintained for a particular session. The
- client MAY include this AVP in requests as a hint to the server, but
- the value in the server's answer message is binding. The following
- values are supported:
-
- STATE_MAINTAINED 0
-
- This value is used to specify that session state is being
- maintained, and the access device MUST issue a session termination
- message when service to the user is terminated. This is the
- default value.
-
- NO_STATE_MAINTAINED 1
-
- This value is used to specify that no session termination messages
- will be sent by the access device upon expiration of the
- Authorization-Lifetime.
-
-8.12. Re-Auth-Request-Type AVP
-
- The Re-Auth-Request-Type AVP (AVP Code 285) is of type Enumerated and
- is included in application-specific auth answers to inform the client
- of the action expected upon expiration of the Authorization-Lifetime.
-
-
-
-
-Fajardo, et al. Standards Track [Page 118]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- If the answer message contains an Authorization-Lifetime AVP with a
- positive value, the Re-Auth-Request-Type AVP MUST be present in an
- answer message. The following values are defined:
-
- AUTHORIZE_ONLY 0
-
- An authorization only re-auth is expected upon expiration of the
- Authorization-Lifetime. This is the default value if the AVP is
- not present in answer messages that include the Authorization-
- Lifetime.
-
- AUTHORIZE_AUTHENTICATE 1
-
- An authentication and authorization re-auth is expected upon
- expiration of the Authorization-Lifetime.
-
-8.13. Session-Timeout AVP
-
- The Session-Timeout AVP (AVP Code 27) [RFC2865] is of type Unsigned32
- and contains the maximum number of seconds of service to be provided
- to the user before termination of the session. When both the
- Session-Timeout and the Authorization-Lifetime AVPs are present in an
- answer message, the former MUST be equal to or greater than the value
- of the latter.
-
- A session that terminates on an access device due to the expiration
- of the Session-Timeout MUST cause an STR to be issued, unless both
- the access device and the home server had previously agreed that no
- session termination messages would be sent (see Section 8).
-
- A Session-Timeout AVP MAY be present in a re-authorization answer
- message, and it contains the remaining number of seconds from the
- beginning of the re-auth.
-
- A value of zero, or the absence of this AVP, means that this session
- has an unlimited number of seconds before termination.
-
- This AVP MAY be provided by the client as a hint of the maximum
- timeout that it is willing to accept. However, the server MAY return
- a value that is equal to, or smaller than, the one provided by the
- client.
-
-8.14. User-Name AVP
-
- The User-Name AVP (AVP Code 1) [RFC2865] is of type UTF8String, which
- contains the User-Name, in a format consistent with the NAI
- specification [RFC4282].
-
-
-
-
-Fajardo, et al. Standards Track [Page 119]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-8.15. Termination-Cause AVP
-
- The Termination-Cause AVP (AVP Code 295) is of type Enumerated, and
- is used to indicate the reason why a session was terminated on the
- access device. The currently assigned values for this AVP can be
- found in the IANA registry for Termination-Cause AVP Values
- [IANATCV].
-
-8.16. Origin-State-Id AVP
-
- The Origin-State-Id AVP (AVP Code 278), of type Unsigned32, is a
- monotonically increasing value that is advanced whenever a Diameter
- entity restarts with loss of previous state, for example, upon
- reboot. Origin-State-Id MAY be included in any Diameter message,
- including CER.
-
- A Diameter entity issuing this AVP MUST create a higher value for
- this AVP each time its state is reset. A Diameter entity MAY set
- Origin-State-Id to the time of startup, or it MAY use an incrementing
- counter retained in non-volatile memory across restarts.
-
- The Origin-State-Id, if present, MUST reflect the state of the entity
- indicated by Origin-Host. If a proxy modifies Origin-Host, it MUST
- either remove Origin-State-Id or modify it appropriately as well.
- Typically, Origin-State-Id is used by an access device that always
- starts up with no active sessions; that is, any session active prior
- to restart will have been lost. By including Origin-State-Id in a
- message, it allows other Diameter entities to infer that sessions
- associated with a lower Origin-State-Id are no longer active. If an
- access device does not intend for such inferences to be made, it MUST
- either not include Origin-State-Id in any message or set its value to
- 0.
-
-8.17. Session-Binding AVP
-
- The Session-Binding AVP (AVP Code 270) is of type Unsigned32, and it
- MAY be present in application-specific authorization answer messages.
- If present, this AVP MAY inform the Diameter client that all future
- application-specific re-auth and Session-Termination-Request messages
- for this session MUST be sent to the same authorization server.
-
-
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 120]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- This field is a bit mask, and the following bits have been defined:
-
- RE_AUTH 1
-
- When set, future re-auth messages for this session MUST NOT
- include the Destination-Host AVP. When cleared, the default
- value, the Destination-Host AVP MUST be present in all re-auth
- messages for this session.
-
- STR 2
-
- When set, the STR message for this session MUST NOT include the
- Destination-Host AVP. When cleared, the default value, the
- Destination-Host AVP MUST be present in the STR message for this
- session.
-
- ACCOUNTING 4
-
- When set, all accounting messages for this session MUST NOT
- include the Destination-Host AVP. When cleared, the default
- value, the Destination-Host AVP, if known, MUST be present in all
- accounting messages for this session.
-
-8.18. Session-Server-Failover AVP
-
- The Session-Server-Failover AVP (AVP Code 271) is of type Enumerated
- and MAY be present in application-specific authorization answer
- messages that either do not include the Session-Binding AVP or
- include the Session-Binding AVP with any of the bits set to a zero
- value. If present, this AVP MAY inform the Diameter client that if a
- re-auth or STR message fails due to a delivery problem, the Diameter
- client SHOULD issue a subsequent message without the Destination-Host
- AVP. When absent, the default value is REFUSE_SERVICE.
-
- The following values are supported:
-
- REFUSE_SERVICE 0
-
- If either the re-auth or the STR message delivery fails, terminate
- service with the user and do not attempt any subsequent attempts.
-
-
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 121]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- TRY_AGAIN 1
-
- If either the re-auth or the STR message delivery fails, resend
- the failed message without the Destination-Host AVP present.
-
- ALLOW_SERVICE 2
-
- If re-auth message delivery fails, assume that re-authorization
- succeeded. If STR message delivery fails, terminate the session.
-
- TRY_AGAIN_ALLOW_SERVICE 3
-
- If either the re-auth or the STR message delivery fails, resend
- the failed message without the Destination-Host AVP present. If
- the second delivery fails for re-auth, assume re-authorization
- succeeded. If the second delivery fails for STR, terminate the
- session.
-
-8.19. Multi-Round-Time-Out AVP
-
- The Multi-Round-Time-Out AVP (AVP Code 272) is of type Unsigned32 and
- SHOULD be present in application-specific authorization answer
- messages whose Result-Code AVP is set to DIAMETER_MULTI_ROUND_AUTH.
- This AVP contains the maximum number of seconds that the access
- device MUST provide the user in responding to an authentication
- request.
-
-8.20. Class AVP
-
- The Class AVP (AVP Code 25) is of type OctetString and is used by
- Diameter servers to return state information to the access device.
- When one or more Class AVPs are present in application-specific
- authorization answer messages, they MUST be present in subsequent re-
- authorization, session termination and accounting messages. Class
- AVPs found in a re-authorization answer message override the ones
- found in any previous authorization answer message. Diameter server
- implementations SHOULD NOT return Class AVPs that require more than
- 4096 bytes of storage on the Diameter client. A Diameter client that
- receives Class AVPs whose size exceeds local available storage MUST
- terminate the session.
-
-8.21. Event-Timestamp AVP
-
- The Event-Timestamp (AVP Code 55) is of type Time and MAY be included
- in an Accounting-Request and Accounting-Answer messages to record the
- time that the reported event occurred, in seconds since January 1,
- 1900 00:00 UTC.
-
-
-
-
-Fajardo, et al. Standards Track [Page 122]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-9. Accounting
-
- This accounting protocol is based on a server directed model with
- capabilities for real-time delivery of accounting information.
- Several fault resilience methods [RFC2975] have been built into the
- protocol in order minimize loss of accounting data in various fault
- situations and under different assumptions about the capabilities of
- the used devices.
-
-9.1. Server Directed Model
-
- The server directed model means that the device generating the
- accounting data gets information from either the authorization server
- (if contacted) or the accounting server regarding the way accounting
- data shall be forwarded. This information includes accounting record
- timeliness requirements.
-
- As discussed in [RFC2975], real-time transfer of accounting records
- is a requirement, such as the need to perform credit-limit checks and
- fraud detection. Note that batch accounting is not a requirement,
- and is therefore not supported by Diameter. Should batched
- accounting be required in the future, a new Diameter application will
- need to be created, or it could be handled using another protocol.
- Note, however, that even if at the Diameter layer, accounting
- requests are processed one by one; transport protocols used under
- Diameter typically batch several requests in the same packet under
- heavy traffic conditions. This may be sufficient for many
- applications.
-
- The authorization server (chain) directs the selection of proper
- transfer strategy, based on its knowledge of the user and
- relationships of roaming partnerships. The server (or agents) uses
- the Acct-Interim-Interval and Accounting-Realtime-Required AVPs to
- control the operation of the Diameter peer operating as a client.
- The Acct-Interim-Interval AVP, when present, instructs the Diameter
- node acting as a client to produce accounting records continuously
- even during a session. Accounting-Realtime-Required AVP is used to
- control the behavior of the client when the transfer of accounting
- records from the Diameter client is delayed or unsuccessful.
-
- The Diameter accounting server MAY override the interim interval or
- the real-time requirements by including the Acct-Interim-Interval or
- Accounting-Realtime-Required AVP in the Accounting-Answer message.
- When one of these AVPs is present, the latest value received SHOULD
- be used in further accounting activities for the same session.
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 123]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-9.2. Protocol Messages
-
- A Diameter node that receives a successful authentication and/or
- authorization message from the Diameter server SHOULD collect
- accounting information for the session. The Accounting-Request
- message is used to transmit the accounting information to the
- Diameter server, which MUST reply with the Accounting-Answer message
- to confirm reception. The Accounting-Answer message includes the
- Result-Code AVP, which MAY indicate that an error was present in the
- accounting message. The value of the Accounting-Realtime-Required
- AVP received earlier for the session in question may indicate that
- the user's session has to be terminated when a rejected Accounting-
- Request message was received.
-
-9.3. Accounting Application Extension and Requirements
-
- Each Diameter application (e.g., NASREQ, Mobile IP) SHOULD define its
- service-specific AVPs that MUST be present in the Accounting-Request
- message in a section titled "Accounting AVPs". The application MUST
- assume that the AVPs described in this document will be present in
- all Accounting messages, so only their respective service-specific
- AVPs need to be defined in that section.
-
- Applications have the option of using one or both of the following
- accounting application extension models:
-
- Split Accounting Service
-
- The accounting message will carry the Application Id of the
- Diameter base accounting application (see Section 2.4).
- Accounting messages may be routed to Diameter nodes other than the
- corresponding Diameter application. These nodes might be
- centralized accounting servers that provide accounting service for
- multiple different Diameter applications. These nodes MUST
- advertise the Diameter base accounting Application Id during
- capabilities exchange.
-
- Coupled Accounting Service
-
- The accounting message will carry the Application Id of the
- application that is using it. The application itself will process
- the received accounting records or forward them to an accounting
- server. There is no accounting application advertisement required
- during capabilities exchange, and the accounting messages will be
- routed the same way as any of the other application messages.
-
- In cases where an application does not define its own accounting
- service, it is preferred that the split accounting model be used.
-
-
-
-Fajardo, et al. Standards Track [Page 124]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-9.4. Fault Resilience
-
- Diameter base protocol mechanisms are used to overcome small message
- loss and network faults of a temporary nature.
-
- Diameter peers acting as clients MUST implement the use of failover
- to guard against server failures and certain network failures.
- Diameter peers acting as agents or related off-line processing
- systems MUST detect duplicate accounting records caused by the
- sending of the same record to several servers and duplication of
- messages in transit. This detection MUST be based on the inspection
- of the Session-Id and Accounting-Record-Number AVP pairs. Appendix C
- discusses duplicate detection needs and implementation issues.
-
- Diameter clients MAY have non-volatile memory for the safe storage of
- accounting records over reboots or extended network failures, network
- partitions, and server failures. If such memory is available, the
- client SHOULD store new accounting records there as soon as the
- records are created and until a positive acknowledgement of their
- reception from the Diameter server has been received. Upon a reboot,
- the client MUST start sending the records in the non-volatile memory
- to the accounting server with the appropriate modifications in
- termination cause, session length, and other relevant information in
- the records.
-
- A further application of this protocol may include AVPs to control
- the maximum number of accounting records that may be stored in the
- Diameter client without committing them to the non-volatile memory or
- transferring them to the Diameter server.
-
- The client SHOULD NOT remove the accounting data from any of its
- memory areas before the correct Accounting-Answer has been received.
- The client MAY remove the oldest, undelivered, or as yet
- unacknowledged accounting data if it runs out of resources such as
- memory. It is an implementation-dependent matter for the client to
- accept new sessions under this condition.
-
-9.5. Accounting Records
-
- In all accounting records, the Session-Id AVP MUST be present; the
- User-Name AVP MUST be present if it is available to the Diameter
- client.
-
- Different types of accounting records are sent depending on the
- actual type of accounted service and the authorization server's
- directions for interim accounting. If the accounted service is a
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 125]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- one-time event, meaning that the start and stop of the event are
- simultaneous, then the Accounting-Record-Type AVP MUST be present and
- set to the value EVENT_RECORD.
-
- If the accounted service is of a measurable length, then the AVP MUST
- use the values START_RECORD, STOP_RECORD, and possibly,
- INTERIM_RECORD. If the authorization server has not directed interim
- accounting to be enabled for the session, two accounting records MUST
- be generated for each service of type session. When the initial
- Accounting-Request for a given session is sent, the Accounting-
- Record-Type AVP MUST be set to the value START_RECORD. When the last
- Accounting-Request is sent, the value MUST be STOP_RECORD.
-
- If the authorization server has directed interim accounting to be
- enabled, the Diameter client MUST produce additional records between
- the START_RECORD and STOP_RECORD, marked INTERIM_RECORD. The
- production of these records is directed by Acct-Interim-Interval as
- well as any re-authentication or re-authorization of the session.
- The Diameter client MUST overwrite any previous interim accounting
- records that are locally stored for delivery, if a new record is
- being generated for the same session. This ensures that only one
- pending interim record can exist on an access device for any given
- session.
-
- A particular value of Accounting-Sub-Session-Id MUST appear only in
- one sequence of accounting records from a Diameter client, except for
- the purposes of retransmission. The one sequence that is sent MUST
- be either one record with Accounting-Record-Type AVP set to the value
- EVENT_RECORD or several records starting with one having the value
- START_RECORD, followed by zero or more INTERIM_RECORDs and a single
- STOP_RECORD. A particular Diameter application specification MUST
- define the type of sequences that MUST be used.
-
-9.6. Correlation of Accounting Records
-
- If an application uses accounting messages, it can correlate
- accounting records with a specific application session by using the
- Session-Id of the particular application session in the accounting
- messages. Accounting messages MAY also use a different Session-Id
- from that of the application sessions, in which case, other session-
- related information is needed to perform correlation.
-
- In cases where an application requires multiple accounting sub-
- sessions, an Accounting-Sub-Session-Id AVP is used to differentiate
- each sub-session. The Session-Id would remain constant for all sub-
- sessions and is used to correlate all the sub-sessions to a
- particular application session. Note that receiving a STOP_RECORD
-
-
-
-
-Fajardo, et al. Standards Track [Page 126]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- with no Accounting-Sub-Session-Id AVP when sub-sessions were
- originally used in the START_RECORD messages implies that all sub-
- sessions are terminated.
-
- There are also cases where an application needs to correlate multiple
- application sessions into a single accounting record; the accounting
- record may span multiple different Diameter applications and sessions
- used by the same user at a given time. In such cases, the Acct-
- Multi-Session-Id AVP is used. The Acct-Multi-Session-Id AVP SHOULD
- be signaled by the server to the access device (typically, during
- authorization) when it determines that a request belongs to an
- existing session. The access device MUST then include the Acct-
- Multi-Session-Id AVP in all subsequent accounting messages.
-
- The Acct-Multi-Session-Id AVP MAY include the value of the original
- Session-Id. Its contents are implementation specific, but the MUST
- be globally unique across other Acct-Multi-Session-Ids and MUST NOT
- change during the life of a session.
-
- A Diameter application document MUST define the exact concept of a
- session that is being accounted, and it MAY define the concept of a
- multi-session. For instance, the NASREQ DIAMETER application treats
- a single PPP connection to a Network Access Server as one session and
- a set of Multilink PPP sessions as one multi-session.
-
-9.7. Accounting Command Codes
-
- This section defines Command Code values that MUST be supported by
- all Diameter implementations that provide accounting services.
-
-9.7.1. Accounting-Request
-
- The Accounting-Request (ACR) command, indicated by the Command Code
- field set to 271 and the Command Flags' 'R' bit set, is sent by a
- Diameter node, acting as a client, in order to exchange accounting
- information with a peer.
-
- In addition to the AVPs listed below, Accounting-Request messages
- SHOULD include service-specific accounting AVPs.
-
-
-
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 127]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Message Format
-
- &lt;ACR> ::= &lt; Diameter Header: 271, REQ, PXY >
- &lt; Session-Id >
- { Origin-Host }
- { Origin-Realm }
- { Destination-Realm }
- { Accounting-Record-Type }
- { Accounting-Record-Number }
- [ Acct-Application-Id ]
- [ Vendor-Specific-Application-Id ]
- [ User-Name ]
- [ Destination-Host ]
- [ Accounting-Sub-Session-Id ]
- [ Acct-Session-Id ]
- [ Acct-Multi-Session-Id ]
- [ Acct-Interim-Interval ]
- [ Accounting-Realtime-Required ]
- [ Origin-State-Id ]
- [ Event-Timestamp ]
- * [ Proxy-Info ]
- * [ Route-Record ]
- * [ AVP ]
-
-9.7.2. Accounting-Answer
-
- The Accounting-Answer (ACA) command, indicated by the Command Code
- field set to 271 and the Command Flags' 'R' bit cleared, is used to
- acknowledge an Accounting-Request command. The Accounting-Answer
- command contains the same Session-Id as the corresponding request.
-
- Only the target Diameter server, known as the home Diameter server,
- SHOULD respond with the Accounting-Answer command.
-
- In addition to the AVPs listed below, Accounting-Answer messages
- SHOULD include service-specific accounting AVPs.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 128]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Message Format
-
- &lt;ACA> ::= &lt; Diameter Header: 271, PXY >
- &lt; Session-Id >
- { Result-Code }
- { Origin-Host }
- { Origin-Realm }
- { Accounting-Record-Type }
- { Accounting-Record-Number }
- [ Acct-Application-Id ]
- [ Vendor-Specific-Application-Id ]
- [ User-Name ]
- [ Accounting-Sub-Session-Id ]
- [ Acct-Session-Id ]
- [ Acct-Multi-Session-Id ]
- [ Error-Message ]
- [ Error-Reporting-Host ]
- [ Failed-AVP ]
- [ Acct-Interim-Interval ]
- [ Accounting-Realtime-Required ]
- [ Origin-State-Id ]
- [ Event-Timestamp ]
- * [ Proxy-Info ]
- * [ AVP ]
-
-9.8. Accounting AVPs
-
- This section contains AVPs that describe accounting usage information
- related to a specific session.
-
-9.8.1. Accounting-Record-Type AVP
-
- The Accounting-Record-Type AVP (AVP Code 480) is of type Enumerated
- and contains the type of accounting record being sent. The following
- values are currently defined for the Accounting-Record-Type AVP:
-
- EVENT_RECORD 1
-
- An Accounting Event Record is used to indicate that a one-time
- event has occurred (meaning that the start and end of the event
- are simultaneous). This record contains all information relevant
- to the service, and it is the only record of the service.
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 129]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- START_RECORD 2
-
- Accounting Start, Interim, and Stop Records are used to indicate
- that a service of a measurable length has been given. An
- Accounting Start Record is used to initiate an accounting session
- and contains accounting information that is relevant to the
- initiation of the session.
-
- INTERIM_RECORD 3
-
- An Interim Accounting Record contains cumulative accounting
- information for an existing accounting session. Interim
- Accounting Records SHOULD be sent every time a re-authentication
- or re-authorization occurs. Further, additional interim record
- triggers MAY be defined by application-specific Diameter
- applications. The selection of whether to use INTERIM_RECORD
- records is done by the Acct-Interim-Interval AVP.
-
- STOP_RECORD 4
-
- An Accounting Stop Record is sent to terminate an accounting
- session and contains cumulative accounting information relevant to
- the existing session.
-
-9.8.2. Acct-Interim-Interval AVP
-
- The Acct-Interim-Interval AVP (AVP Code 85) is of type Unsigned32 and
- is sent from the Diameter home authorization server to the Diameter
- client. The client uses information in this AVP to decide how and
- when to produce accounting records. With different values in this
- AVP, service sessions can result in one, two, or two+N accounting
- records, based on the needs of the home organization. The following
- accounting record production behavior is directed by the inclusion of
- this AVP:
-
- 1. The omission of the Acct-Interim-Interval AVP or its inclusion
- with Value field set to 0 means that EVENT_RECORD, START_RECORD,
- and STOP_RECORD are produced, as appropriate for the service.
-
- 2. The inclusion of the AVP with Value field set to a non-zero value
- means that INTERIM_RECORD records MUST be produced between the
- START_RECORD and STOP_RECORD records. The Value field of this
- AVP is the nominal interval between these records in seconds.
- The Diameter node that originates the accounting information,
- known as the client, MUST produce the first INTERIM_RECORD record
- roughly at the time when this nominal interval has elapsed from
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 130]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- the START_RECORD, the next one again as the interval has elapsed
- once more, and so on until the session ends and a STOP_RECORD
- record is produced.
-
- The client MUST ensure that the interim record production times
- are randomized so that large accounting message storms are not
- created either among records or around a common service start
- time.
-
-9.8.3. Accounting-Record-Number AVP
-
- The Accounting-Record-Number AVP (AVP Code 485) is of type Unsigned32
- and identifies this record within one session. As Session-Id AVPs
- are globally unique, the combination of Session-Id and Accounting-
- Record-Number AVPs is also globally unique and can be used in
- matching accounting records with confirmations. An easy way to
- produce unique numbers is to set the value to 0 for records of type
- EVENT_RECORD and START_RECORD and set the value to 1 for the first
- INTERIM_RECORD, 2 for the second, and so on until the value for
- STOP_RECORD is one more than for the last INTERIM_RECORD.
-
-9.8.4. Acct-Session-Id AVP
-
- The Acct-Session-Id AVP (AVP Code 44) is of type OctetString is only
- used when RADIUS/Diameter translation occurs. This AVP contains the
- contents of the RADIUS Acct-Session-Id attribute.
-
-9.8.5. Acct-Multi-Session-Id AVP
-
- The Acct-Multi-Session-Id AVP (AVP Code 50) is of type UTF8String,
- following the format specified in Section 8.8. The Acct-Multi-
- Session-Id AVP is used to link multiple related accounting sessions,
- where each session would have a unique Session-Id but the same Acct-
- Multi-Session-Id AVP. This AVP MAY be returned by the Diameter
- server in an authorization answer, and it MUST be used in all
- accounting messages for the given session.
-
-9.8.6. Accounting-Sub-Session-Id AVP
-
- The Accounting-Sub-Session-Id AVP (AVP Code 287) is of type
- Unsigned64 and contains the accounting sub-session identifier. The
- combination of the Session-Id and this AVP MUST be unique per sub-
- session, and the value of this AVP MUST be monotonically increased by
- one for all new sub-sessions. The absence of this AVP implies no
- sub-sessions are in use, with the exception of an Accounting-Request
- whose Accounting-Record-Type is set to STOP_RECORD. A STOP_RECORD
- message with no Accounting-Sub-Session-Id AVP present will signal the
- termination of all sub-sessions for a given Session-Id.
-
-
-
-Fajardo, et al. Standards Track [Page 131]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-9.8.7. Accounting-Realtime-Required AVP
-
- The Accounting-Realtime-Required AVP (AVP Code 483) is of type
- Enumerated and is sent from the Diameter home authorization server to
- the Diameter client or in the Accounting-Answer from the accounting
- server. The client uses information in this AVP to decide what to do
- if the sending of accounting records to the accounting server has
- been temporarily prevented due to, for instance, a network problem.
-
- DELIVER_AND_GRANT 1
-
- The AVP with Value field set to DELIVER_AND_GRANT means that the
- service MUST only be granted as long as there is a connection to
- an accounting server. Note that the set of alternative accounting
- servers are treated as one server in this sense. Having to move
- the accounting record stream to a backup server is not a reason to
- discontinue the service to the user.
-
- GRANT_AND_STORE 2
-
- The AVP with Value field set to GRANT_AND_STORE means that service
- SHOULD be granted if there is a connection, or as long as records
- can still be stored as described in Section 9.4.
-
- This is the default behavior if the AVP isn't included in the
- reply from the authorization server.
-
- GRANT_AND_LOSE 3
-
- The AVP with Value field set to GRANT_AND_LOSE means that service
- SHOULD be granted even if the records cannot be delivered or
- stored.
-
-10. AVP Occurrence Tables
-
- The following tables present the AVPs defined in this document and
- specify in which Diameter messages they MAY or MAY NOT be present.
- AVPs that occur only inside a Grouped AVP are not shown in these
- tables.
-
- The tables use the following symbols:
-
- 0 The AVP MUST NOT be present in the message.
-
- 0+ Zero or more instances of the AVP MAY be present in the
- message.
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 132]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- 0-1 Zero or one instance of the AVP MAY be present in the message.
- It is considered an error if there are more than one instance
- of the AVP.
-
- 1 One instance of the AVP MUST be present in the message.
-
- 1+ At least one instance of the AVP MUST be present in the
- message.
-
-10.1. Base Protocol Command AVP Table
-
- The table in this section is limited to the non-Accounting Command
- Codes defined in this specification.
-
- +-----------------------------------------------+
- | Command Code |
- +---+---+---+---+---+---+---+---+---+---+---+---+
- Attribute Name |CER|CEA|DPR|DPA|DWR|DWA|RAR|RAA|ASR|ASA|STR|STA|
- --------------------+---+---+---+---+---+---+---+---+---+---+---+---+
- Acct-Interim- |0 |0 |0 |0 |0 |0 |0-1|0 |0 |0 |0 |0 |
- Interval | | | | | | | | | | | | |
- Accounting-Realtime-|0 |0 |0 |0 |0 |0 |0-1|0 |0 |0 |0 |0 |
- Required | | | | | | | | | | | | |
- Acct-Application-Id |0+ |0+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
- Auth-Application-Id |0+ |0+ |0 |0 |0 |0 |1 |0 |1 |0 |1 |0 |
- Auth-Grace-Period |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
- Auth-Request-Type |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
- Auth-Session-State |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
- Authorization- |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
- Lifetime | | | | | | | | | | | | |
- Class |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0+ |0+ |
- Destination-Host |0 |0 |0 |0 |0 |0 |1 |0 |1 |0 |0-1|0 |
- Destination-Realm |0 |0 |0 |0 |0 |0 |1 |0 |1 |0 |1 |0 |
- Disconnect-Cause |0 |0 |1 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
- Error-Message |0 |0-1|0 |0-1|0 |0-1|0 |0-1|0 |0-1|0 |0-1|
- Error-Reporting-Host|0 |0 |0 |0 |0 |0 |0 |0-1|0 |0-1|0 |0-1|
- Failed-AVP |0 |0-1|0 |0-1|0 |0-1|0 |0-1|0 |0-1|0 |0-1|
- Firmware-Revision |0-1|0-1|0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
- Host-IP-Address |1+ |1+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
- Inband-Security-Id |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
- Multi-Round-Time-Out|0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
-
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 133]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Origin-Host |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |
- Origin-Realm |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |
- Origin-State-Id |0-1|0-1|0 |0 |0-1|0-1|0-1|0-1|0-1|0-1|0-1|0-1|
- Product-Name |1 |1 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
- Proxy-Info |0 |0 |0 |0 |0 |0 |0+ |0+ |0+ |0+ |0+ |0+ |
- Redirect-Host |0 |0 |0 |0 |0 |0 |0 |0+ |0 |0+ |0 |0+ |
- Redirect-Host-Usage |0 |0 |0 |0 |0 |0 |0 |0-1|0 |0-1|0 |0-1|
- Redirect-Max-Cache- |0 |0 |0 |0 |0 |0 |0 |0-1|0 |0-1|0 |0-1|
- Time | | | | | | | | | | | | |
- Result-Code |0 |1 |0 |1 |0 |1 |0 |1 |0 |1 |0 |1 |
- Re-Auth-Request-Type|0 |0 |0 |0 |0 |0 |1 |0 |0 |0 |0 |0 |
- Route-Record |0 |0 |0 |0 |0 |0 |0+ |0 |0+ |0 |0+ |0 |
- Session-Binding |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
- Session-Id |0 |0 |0 |0 |0 |0 |1 |1 |1 |1 |1 |1 |
- Session-Server- |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
- Failover | | | | | | | | | | | | |
- Session-Timeout |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
- Supported-Vendor-Id |0+ |0+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
- Termination-Cause |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |1 |0 |
- User-Name |0 |0 |0 |0 |0 |0 |0-1|0-1|0-1|0-1|0-1|0-1|
- Vendor-Id |1 |1 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
- Vendor-Specific- |0+ |0+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
- Application-Id | | | | | | | | | | | | |
- --------------------+---+---+---+---+---+---+---+---+---+---+---+---+
-
-10.2. Accounting AVP Table
-
- The table in this section is used to represent which AVPs defined in
- this document are to be present in the Accounting messages. These
- AVP occurrence requirements are guidelines, which may be expanded,
- and/or overridden by application-specific requirements in the
- Diameter applications documents.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 134]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- +-----------+
- | Command |
- | Code |
- +-----+-----+
- Attribute Name | ACR | ACA |
- ------------------------------+-----+-----+
- Acct-Interim-Interval | 0-1 | 0-1 |
- Acct-Multi-Session-Id | 0-1 | 0-1 |
- Accounting-Record-Number | 1 | 1 |
- Accounting-Record-Type | 1 | 1 |
- Acct-Session-Id | 0-1 | 0-1 |
- Accounting-Sub-Session-Id | 0-1 | 0-1 |
- Accounting-Realtime-Required | 0-1 | 0-1 |
- Acct-Application-Id | 0-1 | 0-1 |
- Auth-Application-Id | 0 | 0 |
- Class | 0+ | 0+ |
- Destination-Host | 0-1 | 0 |
- Destination-Realm | 1 | 0 |
- Error-Reporting-Host | 0 | 0+ |
- Event-Timestamp | 0-1 | 0-1 |
- Failed-AVP | 0 | 0-1 |
- Origin-Host | 1 | 1 |
- Origin-Realm | 1 | 1 |
- Proxy-Info | 0+ | 0+ |
- Route-Record | 0+ | 0 |
- Result-Code | 0 | 1 |
- Session-Id | 1 | 1 |
- Termination-Cause | 0 | 0 |
- User-Name | 0-1 | 0-1 |
- Vendor-Specific-Application-Id| 0-1 | 0-1 |
- ------------------------------+-----+-----+
-
-11. IANA Considerations
-
- This section provides guidance to the Internet Assigned Numbers
- Authority (IANA) regarding registration of values related to the
- Diameter protocol, in accordance with [RFC5226]. Existing IANA
- registries and assignments put in place by RFC 3588 remain the same
- unless explicitly updated or deprecated in this section.
-
-11.1. AVP Header
-
- As defined in Section 4, the AVP header contains three fields that
- require IANA namespace management: the AVP Code, Vendor-ID, and Flags
- fields.
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 135]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-11.1.1. AVP Codes
-
- There are multiple namespaces. Vendors can have their own AVP Codes
- namespace that will be identified by their Vendor-ID (also known as
- Enterprise-Number), and they control the assignments of their vendor-
- specific AVP Codes within their own namespace. The absence of a
- Vendor-ID or a Vendor-ID value of zero (0) identifies the IETF AVP
- Codes namespace, which is under IANA control. The AVP Codes and
- sometimes possible values in an AVP are controlled and maintained by
- IANA. AVP Code 0 is not used. AVP Codes 1-255 are managed
- separately as RADIUS Attribute Types. Where a Vendor-Specific AVP is
- implemented by more than one vendor, allocation of global AVPs should
- be encouraged instead.
-
- AVPs may be allocated following Expert Review (by a Designated
- Expert) with Specification Required [RFC5226]. A block allocation
- (release of more than three AVPs at a time for a given purpose)
- requires IETF Review [RFC5226].
-
-11.1.2. AVP Flags
-
- Section 4.1 describes the existing AVP Flags. The remaining bits can
- only be assigned via a Standards Action [RFC5226].
-
-11.2. Diameter Header
-
-11.2.1. Command Codes
-
- For the Diameter header, the Command Code namespace allocation has
- changed. The new allocation rules are as follows:
-
- The Command Code values 256 - 8,388,607 (0x100 to 0x7fffff) are
- for permanent, standard commands, allocated by IETF Review
- [RFC5226].
-
- The values 8,388,608 - 16,777,213 (0x800000 - 0xfffffd) are
- reserved for vendor-specific Command Codes, to be allocated on a
- First Come, First Served basis by IANA [RFC5226]. The request to
- IANA for a Vendor-Specific Command Code SHOULD include a reference
- to a publicly available specification that documents the command
- in sufficient detail to aid in interoperability between
- independent implementations. If the specification cannot be made
- publicly available, the request for a vendor-specific Command Code
- MUST include the contact information of persons and/or entities
- responsible for authoring and maintaining the command.
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 136]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- The values 16,777,214 and 16,777,215 (hexadecimal values 0xfffffe
- - 0xffffff) are reserved for experimental commands. As these
- codes are only for experimental and testing purposes, no guarantee
- is made for interoperability between Diameter peers using
- experimental commands.
-
-11.2.2. Command Flags
-
- Section 3 describes the existing Command Flags field. The remaining
- bits can only be assigned via a Standards Action [RFC5226].
-
-11.3. AVP Values
-
- For AVP values, the Experimental-Result-Code AVP value allocation has
- been added; see Section 11.3.1. The old AVP value allocation rule,
- IETF Consensus, has been updated to IETF Review as per [RFC5226], and
- affected AVPs are listed as reminders.
-
-11.3.1. Experimental-Result-Code AVP
-
- Values for this AVP are purely local to the indicated vendor, and no
- IANA registry is maintained for them.
-
-11.3.2. Result-Code AVP Values
-
- New values are available for assignment via IETF Review [RFC5226].
-
-11.3.3. Accounting-Record-Type AVP Values
-
- New values are available for assignment via IETF Review [RFC5226].
-
-11.3.4. Termination-Cause AVP Values
-
- New values are available for assignment via IETF Review [RFC5226].
-
-11.3.5. Redirect-Host-Usage AVP Values
-
- New values are available for assignment via IETF Review [RFC5226].
-
-11.3.6. Session-Server-Failover AVP Values
-
- New values are available for assignment via IETF Review [RFC5226].
-
-11.3.7. Session-Binding AVP Values
-
- New values are available for assignment via IETF Review [RFC5226].
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 137]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-11.3.8. Disconnect-Cause AVP Values
-
- New values are available for assignment via IETF Review [RFC5226].
-
-11.3.9. Auth-Request-Type AVP Values
-
- New values are available for assignment via IETF Review [RFC5226].
-
-11.3.10. Auth-Session-State AVP Values
-
- New values are available for assignment via IETF Review [RFC5226].
-
-11.3.11. Re-Auth-Request-Type AVP Values
-
- New values are available for assignment via IETF Review [RFC5226].
-
-11.3.12. Accounting-Realtime-Required AVP Values
-
- New values are available for assignment via IETF Review [RFC5226].
-
-11.3.13. Inband-Security-Id AVP (code 299)
-
- The use of this AVP has been deprecated.
-
-11.4. _diameters Service Name and Port Number Registration
-
- IANA has registered the "_diameters" service name and assigned port
- numbers for TLS/TCP and DTLS/SCTP according to the guidelines given
- in [RFC6335].
-
- Service Name: _diameters
-
- Transport Protocols: TCP, SCTP
-
- Assignee: IESG &lt;[email protected]>
-
- Contact: IETF Chair &lt;[email protected]>
-
- Description: Diameter over TLS/TCP and DTLS/SCTP
-
- Reference: RFC 6733
-
- Port Number: 5868, from the User Range
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 138]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-11.5. SCTP Payload Protocol Identifiers
-
- Two SCTP payload protocol identifiers have been registered in the
- SCTP Payload Protocol Identifiers registry:
-
-
- Value | SCTP Payload Protocol Identifier
- -------|-----------------------------------
- 46 | Diameter in a SCTP DATA chunk
- 47 | Diameter in a DTLS/SCTP DATA chunk
-
-
-11.6. S-NAPTR Parameters
-
- The following tag has been registered in the S-NAPTR Application
- Protocol Tags registry:
-
- Tag | Protocol
- -------------------|---------
- diameter.dtls.sctp | DTLS/SCTP
-
-12. Diameter Protocol-Related Configurable Parameters
-
- This section contains the configurable parameters that are found
- throughout this document:
-
- Diameter Peer
-
- A Diameter entity MAY communicate with peers that are statically
- configured. A statically configured Diameter peer would require
- that either the IP address or the fully qualified domain name
- (FQDN) be supplied, which would then be used to resolve through
- DNS.
-
- Routing Table
-
- A Diameter proxy server routes messages based on the realm portion
- of a Network Access Identifier (NAI). The server MUST have a
- table of Realm Names, and the address of the peer to which the
- message must be forwarded. The routing table MAY also include a
- "default route", which is typically used for all messages that
- cannot be locally processed.
-
- Tc timer
-
- The Tc timer controls the frequency that transport connection
- attempts are done to a peer with whom no active transport
- connection exists. The recommended value is 30 seconds.
-
-
-
-Fajardo, et al. Standards Track [Page 139]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-13. Security Considerations
-
- The Diameter base protocol messages SHOULD be secured by using TLS
- [RFC5246] or DTLS/SCTP [RFC6083]. Additional security mechanisms
- such as IPsec [RFC4301] MAY also be deployed to secure connections
- between peers. However, all Diameter base protocol implementations
- MUST support the use of TLS/TCP and DTLS/SCTP, and the Diameter
- protocol MUST NOT be used without one of TLS, DTLS, or IPsec.
-
- If a Diameter connection is to be protected via TLS/TCP and DTLS/SCTP
- or IPsec, then TLS/TCP and DTLS/SCTP or IPsec/IKE SHOULD begin prior
- to any Diameter message exchange. All security parameters for TLS/
- TCP and DTLS/SCTP or IPsec are configured independent of the Diameter
- protocol. All Diameter messages will be sent through the TLS/TCP and
- DTLS/SCTP or IPsec connection after a successful setup.
-
- For TLS/TCP and DTLS/SCTP connections to be established in the open
- state, the CER/CEA exchange MUST include an Inband-Security-ID AVP
- with a value of TLS/TCP and DTLS/SCTP. The TLS/TCP and DTLS/SCTP
- handshake will begin when both ends successfully reach the open
- state, after completion of the CER/CEA exchange. If the TLS/TCP and
- DTLS/SCTP handshake is successful, all further messages will be sent
- via TLS/TCP and DTLS/SCTP. If the handshake fails, both ends MUST
- move to the closed state. See Section 13.1 for more details.
-
-13.1. TLS/TCP and DTLS/SCTP Usage
-
- Diameter nodes using TLS/TCP and DTLS/SCTP for security MUST mutually
- authenticate as part of TLS/TCP and DTLS/SCTP session establishment.
- In order to ensure mutual authentication, the Diameter node acting as
- the TLS/TCP and DTLS/SCTP server MUST request a certificate from the
- Diameter node acting as TLS/TCP and DTLS/SCTP client, and the
- Diameter node acting as the TLS/TCP and DTLS/SCTP client MUST be
- prepared to supply a certificate on request.
-
- Diameter nodes MUST be able to negotiate the following TLS/TCP and
- DTLS/SCTP cipher suites:
-
- TLS_RSA_WITH_RC4_128_MD5
- TLS_RSA_WITH_RC4_128_SHA
- TLS_RSA_WITH_3DES_EDE_CBC_SHA
-
- Diameter nodes SHOULD be able to negotiate the following TLS/TCP and
- DTLS/SCTP cipher suite:
-
- TLS_RSA_WITH_AES_128_CBC_SHA
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 140]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- Note that it is quite possible that support for the
- TLS_RSA_WITH_AES_128_CBC_SHA cipher suite will be REQUIRED at some
- future date. Diameter nodes MAY negotiate other TLS/TCP and DTLS/
- SCTP cipher suites.
-
- If public key certificates are used for Diameter security (for
- example, with TLS), the value of the expiration times in the routing
- and peer tables MUST NOT be greater than the expiry time in the
- relevant certificates.
-
-13.2. Peer-to-Peer Considerations
-
- As with any peer-to-peer protocol, proper configuration of the trust
- model within a Diameter peer is essential to security. When
- certificates are used, it is necessary to configure the root
- certificate authorities trusted by the Diameter peer. These root CAs
- are likely to be unique to Diameter usage and distinct from the root
- CAs that might be trusted for other purposes such as Web browsing.
- In general, it is expected that those root CAs will be configured so
- as to reflect the business relationships between the organization
- hosting the Diameter peer and other organizations. As a result, a
- Diameter peer will typically not be configured to allow connectivity
- with any arbitrary peer. With certificate authentication, Diameter
- peers may not be known beforehand and therefore peer discovery may be
- required.
-
-13.3. AVP Considerations
-
- Diameter AVPs often contain security-sensitive data; for example,
- user passwords and location data, network addresses and cryptographic
- keys. The following AVPs defined in this document are considered to
- be security-sensitive:
-
- o Acct-Interim-Interval
-
- o Accounting-Realtime-Required
-
- o Acct-Multi-Session-Id
-
- o Accounting-Record-Number
-
- o Accounting-Record-Type
-
- o Accounting-Session-Id
-
- o Accounting-Sub-Session-Id
-
- o Class
-
-
-
-Fajardo, et al. Standards Track [Page 141]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- o Session-Id
-
- o Session-Binding
-
- o Session-Server-Failover
-
- o User-Name
-
- Diameter messages containing these or any other AVPs considered to be
- security-sensitive MUST only be sent protected via mutually
- authenticated TLS or IPsec. In addition, those messages MUST NOT be
- sent via intermediate nodes unless there is end-to-end security
- between the originator and recipient or the originator has locally
- trusted configuration that indicates that end-to-end security is not
- needed. For example, end-to-end security may not be required in the
- case where an intermediary node is known to be operated as part of
- the same administrative domain as the endpoints so that an ability to
- successfully compromise the intermediary would imply a high
- probability of being able to compromise the endpoints as well. Note
- that no end-to-end security mechanism is specified in this document.
-
-14. References
-
-14.1. Normative References
-
- [FLOATPOINT]
- Institute of Electrical and Electronics Engineers, "IEEE
- Standard for Binary Floating-Point Arithmetic, ANSI/IEEE
- Standard 754-1985", August 1985.
-
- [IANAADFAM]
- IANA, "Address Family Numbers",
- &lt;http://www.iana.org/assignments/address-family-numbers>.
-
- [RFC0791] Postel, J., "Internet Protocol", STD 5, RFC 791,
- September 1981.
-
- [RFC0793] Postel, J., "Transmission Control Protocol", STD 7,
- RFC 793, September 1981.
-
- [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
- Requirement Levels", BCP 14, RFC 2119, March 1997.
-
- [RFC3492] Costello, A., "Punycode: A Bootstring encoding of Unicode
- for Internationalized Domain Names in Applications
- (IDNA)", RFC 3492, March 2003.
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 142]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- [RFC3539] Aboba, B. and J. Wood, "Authentication, Authorization and
- Accounting (AAA) Transport Profile", RFC 3539, June 2003.
-
- [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO
- 10646", STD 63, RFC 3629, November 2003.
-
- [RFC3958] Daigle, L. and A. Newton, "Domain-Based Application
- Service Location Using SRV RRs and the Dynamic Delegation
- Discovery Service (DDDS)", RFC 3958, January 2005.
-
- [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
- Resource Identifier (URI): Generic Syntax", STD 66,
- RFC 3986, January 2005.
-
- [RFC4004] Calhoun, P., Johansson, T., Perkins, C., Hiller, T., and
- P. McCann, "Diameter Mobile IPv4 Application", RFC 4004,
- August 2005.
-
- [RFC4005] Calhoun, P., Zorn, G., Spence, D., and D. Mitton,
- "Diameter Network Access Server Application", RFC 4005,
- August 2005.
-
- [RFC4006] Hakala, H., Mattila, L., Koskinen, J-P., Stura, M., and J.
- Loughney, "Diameter Credit-Control Application", RFC 4006,
- August 2005.
-
- [RFC4086] Eastlake, D., Schiller, J., and S. Crocker, "Randomness
- Requirements for Security", BCP 106, RFC 4086, June 2005.
-
- [RFC4282] Aboba, B., Beadles, M., Arkko, J., and P. Eronen, "The
- Network Access Identifier", RFC 4282, December 2005.
-
- [RFC4291] Hinden, R. and S. Deering, "IP Version 6 Addressing
- Architecture", RFC 4291, February 2006.
-
- [RFC4960] Stewart, R., "Stream Control Transmission Protocol",
- RFC 4960, September 2007.
-
- [RFC5226] Narten, T. and H. Alvestrand, "Guidelines for Writing an
- IANA Considerations Section in RFCs", BCP 26, RFC 5226,
- May 2008.
-
- [RFC5234] Crocker, D. and P. Overell, "Augmented BNF for Syntax
- Specifications: ABNF", STD 68, RFC 5234, January 2008.
-
- [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security
- (TLS) Protocol Version 1.2", RFC 5246, August 2008.
-
-
-
-
-Fajardo, et al. Standards Track [Page 143]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- [RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S.,
- Housley, R., and W. Polk, "Internet X.509 Public Key
- Infrastructure Certificate and Certificate Revocation List
- (CRL) Profile", RFC 5280, May 2008.
-
- [RFC5729] Korhonen, J., Jones, M., Morand, L., and T. Tsou,
- "Clarifications on the Routing of Diameter Requests Based
- on the Username and the Realm", RFC 5729, December 2009.
-
- [RFC5890] Klensin, J., "Internationalized Domain Names for
- Applications (IDNA): Definitions and Document Framework",
- RFC 5890, August 2010.
-
- [RFC5891] Klensin, J., "Internationalized Domain Names in
- Applications (IDNA): Protocol", RFC 5891, August 2010.
-
- [RFC6083] Tuexen, M., Seggelmann, R., and E. Rescorla, "Datagram
- Transport Layer Security (DTLS) for Stream Control
- Transmission Protocol (SCTP)", RFC 6083, January 2011.
-
- [RFC6347] Rescorla, E. and N. Modadugu, "Datagram Transport Layer
- Security Version 1.2", RFC 6347, January 2012.
-
- [RFC6408] Jones, M., Korhonen, J., and L. Morand, "Diameter
- Straightforward-Naming Authority Pointer (S-NAPTR) Usage",
- RFC 6408, November 2011.
-
-14.2. Informative References
-
- [ENTERPRISE] IANA, "SMI Network Management Private Enterprise
- Codes",
- &lt;http://www.iana.org/assignments/enterprise-numbers>.
-
- [IANATCV] IANA, "Termination-Cause AVP Values (code 295)",
- &lt;http://www.iana.org/assignments/aaa-parameters/
- aaa-parameters.xml#aaa-parameters-16>.
-
- [RFC1492] Finseth, C., "An Access Control Protocol, Sometimes
- Called TACACS", RFC 1492, July 1993.
-
- [RFC1661] Simpson, W., "The Point-to-Point Protocol (PPP)",
- STD 51, RFC 1661, July 1994.
-
- [RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC:
- Keyed-Hashing for Message Authentication", RFC 2104,
- February 1997.
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 144]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- [RFC2782] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR
- for specifying the location of services (DNS SRV)",
- RFC 2782, February 2000.
-
- [RFC2865] Rigney, C., Willens, S., Rubens, A., and W. Simpson,
- "Remote Authentication Dial In User Service (RADIUS)",
- RFC 2865, June 2000.
-
- [RFC2866] Rigney, C., "RADIUS Accounting", RFC 2866, June 2000.
-
- [RFC2869] Rigney, C., Willats, W., and P. Calhoun, "RADIUS
- Extensions", RFC 2869, June 2000.
-
- [RFC2881] Mitton, D. and M. Beadles, "Network Access Server
- Requirements Next Generation (NASREQNG) NAS Model",
- RFC 2881, July 2000.
-
- [RFC2975] Aboba, B., Arkko, J., and D. Harrington, "Introduction
- to Accounting Management", RFC 2975, October 2000.
-
- [RFC2989] Aboba, B., Calhoun, P., Glass, S., Hiller, T., McCann,
- P., Shiino, H., Walsh, P., Zorn, G., Dommety, G.,
- Perkins, C., Patil, B., Mitton, D., Manning, S.,
- Beadles, M., Chen, X., Sivalingham, S., Hameed, A.,
- Munson, M., Jacobs, S., Lim, B., Hirschman, B., Hsu,
- R., Koo, H., Lipford, M., Campbell, E., Xu, Y., Baba,
- S., and E. Jaques, "Criteria for Evaluating AAA
- Protocols for Network Access", RFC 2989, November 2000.
-
- [RFC3162] Aboba, B., Zorn, G., and D. Mitton, "RADIUS and IPv6",
- RFC 3162, August 2001.
-
- [RFC3748] Aboba, B., Blunk, L., Vollbrecht, J., Carlson, J., and
- H. Levkowetz, "Extensible Authentication Protocol
- (EAP)", RFC 3748, June 2004.
-
- [RFC4301] Kent, S. and K. Seo, "Security Architecture for the
- Internet Protocol", RFC 4301, December 2005.
-
- [RFC4690] Klensin, J., Faltstrom, P., Karp, C., and IAB, "Review
- and Recommendations for Internationalized Domain Names
- (IDNs)", RFC 4690, September 2006.
-
- [RFC5176] Chiba, M., Dommety, G., Eklund, M., Mitton, D., and B.
- Aboba, "Dynamic Authorization Extensions to Remote
- Authentication Dial In User Service (RADIUS)",
- RFC 5176, January 2008.
-
-
-
-
-Fajardo, et al. Standards Track [Page 145]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- [RFC5461] Gont, F., "TCP's Reaction to Soft Errors", RFC 5461,
- February 2009.
-
- [RFC5905] Mills, D., Martin, J., Burbank, J., and W. Kasch,
- "Network Time Protocol Version 4: Protocol and
- Algorithms Specification", RFC 5905, June 2010.
-
- [RFC5927] Gont, F., "ICMP Attacks against TCP", RFC 5927,
- July 2010.
-
- [RFC6335] Cotton, M., Eggert, L., Touch, J., Westerlund, M., and
- S. Cheshire, "Internet Assigned Numbers Authority
- (IANA) Procedures for the Management of the Service
- Name and Transport Protocol Port Number Registry",
- BCP 165, RFC 6335, August 2011.
-
- [RFC6737] Kang, J. and G. Zorn, "The Diameter Capabilities Update
- Application", RFC 6737, October 2012.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Fajardo, et al. Standards Track [Page 146]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
-Appendix A. Acknowledgements
-
-A.1. This Document
-
- The authors would like to thank the following people that have
- provided proposals and contributions to this document:
-
- To Vishnu Ram and Satendra Gera for their contributions on
- capabilities updates, predictive loop avoidance, as well as many
- other technical proposals. To Tolga Asveren for his insights and
- contributions on almost all of the proposed solutions incorporated
- into this document. To Timothy Smith for helping on the capabilities
- Update and other topics. To Tony Zhang for providing fixes to
- loopholes on composing Failed-AVPs as well as many other issues and
- topics. To Jan Nordqvist for clearly stating the usage of
- Application Ids. To Anders Kristensen for providing needed technical
- opinions. To David Frascone for providing invaluable review of the
- document. To Mark Jones for providing clarifying text on vendor
- command codes and other vendor-specific indicators. To Victor
- Pascual and Sebastien Decugis for new text and recommendations on
- SCTP/DTLS. To Jouni Korhonen for taking over the editing task and
- resolving last bits from versions 27 through 29.
-
- Special thanks to the Diameter extensibility design team, which
- helped resolve the tricky question of mandatory AVPs and ABNF
- semantics. The members of this team are as follows:
-
- Avi Lior, Jari Arkko, Glen Zorn, Lionel Morand, Mark Jones, Tolga
- Asveren, Jouni Korhonen, and Glenn McGregor.
-
- Special thanks also to people who have provided invaluable comments
- and inputs especially in resolving controversial issues:
-
- Glen Zorn, Yoshihiro Ohba, Marco Stura, Stephen Farrel, Pete Resnick,
- Peter Saint-Andre, Robert Sparks, Krishna Prasad, Sean Turner, Barry
- Leiba, and Pasi Eronen.
-
- Finally, we would like to thank the original authors of this
- document:
-
- Pat Calhoun, John Loughney, Jari Arkko, Erik Guttman, and Glen Zorn.
-
- Their invaluable knowledge and experience has given us a robust and
- flexible AAA protocol that many people have seen great value in
- adopting. We greatly appreciate their support and stewardship for
- the continued improvements of Diameter as a protocol. We would also
- like to extend our gratitude to folks aside from the authors who have
-
-
-
-
-Fajardo, et al. Standards Track [Page 147]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- assisted and contributed to the original version of this document.
- Their efforts significantly contributed to the success of Diameter.
-
-A.2. RFC 3588
-
- The authors would like to thank Nenad Trifunovic, Tony Johansson and
- Pankaj Patel for their participation in the pre-IETF Document Reading
- Party. Allison Mankin, Jonathan Wood, and Bernard Aboba provided
- invaluable assistance in working out transport issues and this was
- also the case with Steven Bellovin in the security area.
-
- Paul Funk and David Mitton were instrumental in getting the Peer
- State Machine correct, and our deep thanks go to them for their time.
-
- Text in this document was also provided by Paul Funk, Mark Eklund,
- Mark Jones, and Dave Spence. Jacques Caron provided many great
- comments as a result of a thorough review of the spec.
-
- The authors would also like to acknowledge the following people for
- their contribution in the development of the Diameter protocol:
-
- Allan C. Rubens, Haseeb Akhtar, William Bulley, Stephen Farrell,
- David Frascone, Daniel C. Fox, Lol Grant, Ignacio Goyret, Nancy
- Greene, Peter Heitman, Fredrik Johansson, Mark Jones, Martin Julien,
- Bob Kopacz, Paul Krumviede, Fergal Ladley, Ryan Moats, Victor Muslin,
- Kenneth Peirce, John Schnizlein, Sumit Vakil, John R. Vollbrecht, and
- Jeff Weisberg.
-
- Finally, Pat Calhoun would like to thank Sun Microsystems since most
- of the effort put into this document was done while he was in their
- employ.
-
-Appendix B. S-NAPTR Example
-
- As an example, consider a client that wishes to resolve aaa:
- ex1.example.com. The client performs a NAPTR query for that domain,
- and the following NAPTR records are returned:
-
- ;; order pref flags service regexp replacement
- IN NAPTR 50 50 "s" "aaa:diameter.tls.tcp" ""
- _diameter._tls.ex1.example.com
- IN NAPTR 100 50 "s" "aaa:diameter.tcp" ""
- _aaa._tcp.ex1.example.com
- IN NAPTR 150 50 "s" "aaa:diameter.sctp" ""
- _diameter._sctp.ex1.example.com
-
- This indicates that the server supports TLS, TCP, and SCTP in that
- order. If the client supports TLS, TLS will be used, targeted to a
-
-
-
-Fajardo, et al. Standards Track [Page 148]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- host determined by an SRV lookup of _diameter._tls.ex1.example.com.
- That lookup would return:
-
- ;; Priority Weight Port Target
- IN SRV 0 1 5060 server1.ex1.example.com
- IN SRV 0 2 5060 server2.ex1.example.com
-
- As an alternative example, a client that wishes to resolve aaa:
- ex2.example.com. The client performs a NAPTR query for that domain,
- and the following NAPTR records are returned:
-
- ;; order pref flags service regexp replacement
- IN NAPTR 150 50 "a" "aaa:diameter.tls.tcp" ""
- server1.ex2.example.com
- IN NAPTR 150 50 "a" "aaa:diameter.tls.tcp" ""
- server2.ex2.example.com
-
- This indicates that the server supports TCP available at the returned
- host names.
-
-Appendix C. Duplicate Detection
-
- As described in Section 9.4, accounting record duplicate detection is
- based on session identifiers. Duplicates can appear for various
- reasons:
-
- o Failover to an alternate server. Where close to real-time
- performance is required, failover thresholds need to be kept low.
- This may lead to an increased likelihood of duplicates. Failover
- can occur at the client or within Diameter agents.
-
- o Failure of a client or agent after sending a record from non-
- volatile memory, but prior to receipt of an application-layer ACK
- and deletion of the record to be sent. This will result in
- retransmission of the record soon after the client or agent has
- rebooted.
-
- o Duplicates received from RADIUS gateways. Since the
- retransmission behavior of RADIUS is not defined within [RFC2865],
- the likelihood of duplication will vary according to the
- implementation.
-
- o Implementation problems and misconfiguration.
-
- The T flag is used as an indication of an application-layer
- retransmission event, e.g., due to failover to an alternate server.
- It is defined only for request messages sent by Diameter clients or
- agents. For instance, after a reboot, a client may not know whether
-
-
-
-Fajardo, et al. Standards Track [Page 149]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- it has already tried to send the accounting records in its non-
- volatile memory before the reboot occurred. Diameter servers MAY use
- the T flag as an aid when processing requests and detecting duplicate
- messages. However, servers that do this MUST ensure that duplicates
- are found even when the first transmitted request arrives at the
- server after the retransmitted request. It can be used only in cases
- where no answer has been received from the server for a request and
- the request is sent again, (e.g., due to a failover to an alternate
- peer, due to a recovered primary peer or due to a client re-sending a
- stored record from non-volatile memory such as after reboot of a
- client or agent).
-
- In some cases, the Diameter accounting server can delay the duplicate
- detection and accounting record processing until a post-processing
- phase takes place. At that time records are likely to be sorted
- according to the included User-Name and duplicate elimination is easy
- in this case. In other situations, it may be necessary to perform
- real-time duplicate detection, such as when credit limits are imposed
- or real-time fraud detection is desired.
-
- In general, only generation of duplicates due to failover or re-
- sending of records in non-volatile storage can be reliably detected
- by Diameter clients or agents. In such cases, the Diameter client or
- agents can mark the message as a possible duplicate by setting the T
- flag. Since the Diameter server is responsible for duplicate
- detection, it can choose whether or not to make use of the T flag, in
- order to optimize duplicate detection. Since the T flag does not
- affect interoperability, and it may not be needed by some servers,
- generation of the T flag is REQUIRED for Diameter clients and agents,
- but it MAY be implemented by Diameter servers.
-
- As an example, it can be usually be assumed that duplicates appear
- within a time window of longest recorded network partition or device
- fault, perhaps a day. So only records within this time window need
- to be looked at in the backward direction. Secondly, hashing
- techniques or other schemes, such as the use of the T flag in the
- received messages, may be used to eliminate the need to do a full
- search even in this set except for rare cases.
-
- The following is an example of how the T flag may be used by the
- server to detect duplicate requests.
-
- A Diameter server MAY check the T flag of the received message to
- determine if the record is a possible duplicate. If the T flag is
- set in the request message, the server searches for a duplicate
- within a configurable duplication time window backward and
- forward. This limits database searching to those records where
- the T flag is set. In a well-run network, network partitions and
-
-
-
-Fajardo, et al. Standards Track [Page 150]
-
-RFC 6733 Diameter Base Protocol October 2012
-
-
- device faults will presumably be rare events, so this approach
- represents a substantial optimization of the duplicate detection
- process. During failover, it is possible for the original record
- to be received after the T-flag-marked record, due to differences
- in network delays experienced along the path by the original and
- duplicate transmissions. The likelihood of this occurring
- increases as the failover interval is decreased. In order to be
- able to detect duplicates that are out of order, the Diameter
- server should use backward and forward time windows when
- performing duplicate checking for the T-flag-marked request. For
- example, in order to allow time for the original record to exit
- the network and be recorded by the accounting server, the Diameter
- server can delay processing records with the T flag set until a
- time period TIME_WAIT + RECORD_PROCESSING_TIME has elapsed after
- the closing of the original transport connection. After this time
- period, it may check the T-flag-marked records against the
- database with relative assurance that the original records, if
- sent, have been received and recorded.
-
-Appendix D. Internationalized Domain Names
-
- To be compatible with the existing DNS infrastructure and simplify
- host and domain name comparison, Diameter identities (FQDNs) are
- represented in ASCII form. This allows the Diameter protocol to fall
- in-line with the DNS strategy of being transparent from the effects
- of Internationalized Domain Names (IDNs) by following the
- recommendations in [RFC4690] and [RFC5890]. Applications that
- provide support for IDNs outside of the Diameter protocol but
- interacting with it SHOULD use the representation and conversion
- framework described in [RFC5890], [RFC5891], and [RFC3492].
-</pre>
-
-</section>
diff --git a/lib/diameter/doc/src/diameter_tcp.xml b/lib/diameter/doc/src/diameter_tcp.xml
index 6ca280c52b..9f84eeb9fd 100644
--- a/lib/diameter/doc/src/diameter_tcp.xml
+++ b/lib/diameter/doc/src/diameter_tcp.xml
@@ -27,7 +27,8 @@
<erlref>
<header>
<copyright>
-<year>2011</year><year>2016</year>
+<year>2011</year>
+<year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -99,7 +100,9 @@ before configuring TLS capability on diameter transports.</p>
| {rport, integer()}
| {accept, Match}
| {port, integer()}
- | {fragment_timer, infinity | 0..16#FFFFFFFF}</v>
+ | {fragment_timer, infinity | 0..16#FFFFFFFF}
+ | {message_cb, &mod_eval;}
+ | {sender, boolean()}</v>
<v>SslOpt = {ssl_options, true | list()}</v>
<v>TcpOpt = term()</v>
<v>Match = &ip_address; | string() | [Match]</v>
@@ -140,6 +143,44 @@ such a message is received over the transport interface after
two successive timeouts without the reception of additional bytes.
Defaults to 1000.</p>
+<marker id="sender"/>
+<p>
+Option <c>sender</c> specifies whether or not to use a dedicated
+process for sending outgoing messages, which avoids the possibility of
+send blocking reception.
+Defaults to <c>false</c>.
+If set to <c>true</c> then a <c>message_cb</c> that avoids the
+possibility of messages being queued in the sender process without
+bound should be configured.</p>
+
+<p>
+Option <c>message_cb</c> specifies a callback that is invoked on
+incoming and outgoing messages, that can be used to implement
+flow control.
+It is applied to two arguments: an atom indicating the
+reason for the callback (<c>send</c>, <c>recv</c>, or <c>ack</c> after
+a completed send), and the message in question (binary() on
+<c>recv</c>, binary() or diameter_packet record on <c>send</c> or
+<c>ack</c>, or <c>false</c> on <c>ack</c> when an incoming request has
+been discarded).
+It should return a list of actions and a new callback as
+tail; eg. <c>[fun cb/3, State]</c>.
+Valid actions are the atoms <c>send</c> or <c>recv</c>, to
+cause a following message-valued action to be sent/received,
+a message to send/receive (binary() or
+diameter_packet record), or a boolean() to enable/disable reading on
+the socket.
+More than one <c>send</c>/<c>recv</c>/message sequence can be
+returned from the same callback, and an initial
+<c>send</c>/<c>recv</c> can be omitted if the same as the value passed
+as the callback's first argument.
+Reading is initially enabled, and returning <c>false</c> does not
+imply there cannot be subsequent <c>recv</c> callbacks since
+messages may already have been read.
+An empty tail is equivalent to the prevailing callback.
+Defaults to a callback equivalent to <c>fun(ack, _) -> []; (_, Msg) ->
+[Msg] end</c>.</p>
+
<p>
Remaining options are any accepted by &ssl_connect3; or
&gen_tcp_connect3; for
@@ -170,14 +211,11 @@ that will not be forthcoming, which will eventually cause the RFC 3539
watchdog to take down the connection.</p>
<p>
-If an <c>ip</c> option is not specified then the first element of a
-non-empty <c>Host-IP-Address</c> list in <c>Svc</c> provides the local
-IP address.
-If neither is specified then the default address selected by &gen_tcp;
-is used.
-In all cases, the selected address is either returned from
-&start; or passed in a <c>connected</c> message over the transport
-interface.</p>
+The first element of a non-empty <c>Host-IP-Address</c> list in
+<c>Svc</c> provides the local IP address if an <c>ip</c> option is not
+specified.
+The local address is either returned from&start; or passed in a
+<c>connected</c> message over the transport interface.</p>
</desc>
</func>
diff --git a/lib/diameter/doc/src/files.mk b/lib/diameter/doc/src/files.mk
index cb4f88a375..4c1297f6cc 100644
--- a/lib/diameter/doc/src/files.mk
+++ b/lib/diameter/doc/src/files.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2016. All Rights Reserved.
+# Copyright Ericsson AB 2010-2017. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -40,8 +40,7 @@ XML_PART_FILES = \
user_man.xml
XML_EXTRA_FILES = \
- seealso.ent \
- diameter_soc_rfc6733.xml
+ seealso.ent
XML_CHAPTER_FILES = \
diameter_intro.xml \
diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml
index 60478606ad..4bfc98de40 100644
--- a/lib/diameter/doc/src/notes.xml
+++ b/lib/diameter/doc/src/notes.xml
@@ -11,7 +11,7 @@
<header>
<copyright>
<year>2011</year>
-<year>2017</year>
+<year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -43,6 +43,319 @@ first.</p>
<!-- ===================================================================== -->
+<section><title>diameter 2.1.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix function_clause when sending an outgoing request
+ after DPA has been sent in response to an incoming DPR.
+ The caused the diameter_peer_fsm gen_server associated
+ with the peer connection to fail, which could then result
+ in the transport connection being reset before the peer
+ closed it upon reception of DPA.</p>
+ <p>
+ Own Id: OTP-15198 Aux Id: ERIERL-213 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>diameter 2.1.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix documentation typos.</p>
+ <p>
+ Own Id: OTP-15045</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>diameter 2.1.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix close of diameter_tcp/sctp listening socket at
+ diameter:remove_transport/2, that was broken in diameter
+ 2.1. A reconfigured transport could not listen on the
+ same endpoint as a result.</p>
+ <p>
+ Own Id: OTP-14839</p>
+ </item>
+ <item>
+ <p>
+ Fix handling of SUSPECT connections at service
+ termination. A connection with this watchdog state caused
+ diameter_service:terminate/2 to fail.</p>
+ <p>
+ Own Id: OTP-14947 Aux Id: ERIERL-124 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>diameter 2.1.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix documentation typo: peer_up/3 was written where
+ peer_down/3 was intended.</p>
+ <p>
+ Own Id: OTP-14805</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>diameter 2.1.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A fault introduced in diameter 2.1 could cause decode
+ errors to be ignored in AVPs following the header of a
+ Grouped AVP.</p>
+ <p>
+ Own Id: OTP-14684 Aux Id: ERIERL-85 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>diameter 2.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ An inadvertently removed monitor in diameter 2.1 caused
+ the ets table diameter_reg to leak entries, and caused
+ service restart and more to fail.</p>
+ <p>
+ Own Id: OTP-14668 Aux Id: ERIERL-83 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>diameter 2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix handling of Proxy-Info in answer messages setting the
+ E-bit.</p>
+ <p>
+ RFC 6733 requires that Proxy-Info AVPs in an incoming
+ request be echoed in an outgoing answer. This was not
+ done in answers formulated by diameter; for example, as a
+ result of a handle_request callback having returned an
+ 'answer-message' or protocol_error tuple.</p>
+ <p>
+ Own Id: OTP-9869</p>
+ </item>
+ <item>
+ <p>
+ React to nodeup/nodedown when sharing peer connections.</p>
+ <p>
+ Service configuration share_peers and use_shared_peers
+ did not respond to the coming and going of remote nodes.</p>
+ <p>
+ Own Id: OTP-14011</p>
+ </item>
+ <item>
+ <p>
+ Fix inappropriate message callbacks.</p>
+ <p>
+ An incoming CER or DPR was regarded as discarded,
+ resulting in a corresponding message callback (if
+ configured) in diameter_tcp/sctp.</p>
+ <p>
+ Own Id: OTP-14486</p>
+ </item>
+ <item>
+ <p>
+ Fix handling of 5009 errors (DIAMETER_AVP_OCCURS_TOO_MANY
+ TIMES).</p>
+ <p>
+ RFC 6733 says that the first AVP that exceeds the bound
+ should be reported, but the suggestions in the errors
+ field of a diameter_packet record counted AVPs from the
+ rear of the message, not the front. Additionally,
+ diameter 2.0 in OTP 20.0 broke the counting by accepting
+ one more AVP than the message grammar in question
+ allowed.</p>
+ <p>
+ Own Id: OTP-14512</p>
+ </item>
+ <item>
+ <p>
+ Match case insensitively in diameter_tcp/sctp accept
+ tuple.</p>
+ <p>
+ Matching of remote addresses when accepting connections
+ in a listening transport was case-sensitive, causing the
+ semantics to change as a consequence of (kernel)
+ OTP-13006.</p>
+ <p>
+ Own Id: OTP-14535 Aux Id: OTP-13006 </p>
+ </item>
+ <item>
+ <p>
+ Fix backwards incompatibility of remote send when sharing
+ transports.</p>
+ <p>
+ The sending of requests over a transport connection on a
+ remote node running an older version of diameter was
+ broken by diameter 2.0 in OTP 20.0.</p>
+ <p>
+ Own Id: OTP-14552</p>
+ </item>
+ <item>
+ <p>
+ Fix diameter_packet.avps decode of Grouped AVP errors in
+ Failed-AVP.</p>
+ <p>
+ Decode didn't produce a list of diameter_avp records, so
+ information about faulty component AVPs was lost.</p>
+ <p>
+ Own Id: OTP-14607</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Let unordered delivery be configured in diameter_sctp.</p>
+ <p>
+ With option {unordered, boolean() | pos_integer()}, with
+ false the default, and N equivalent to OS =&lt; N, where
+ OS is the number of outbound streams negotiated on the
+ association in question. If configured, unordered sending
+ commences upon reception of a second message, outgoing
+ messages being sent on stream 0 before this.</p>
+ <p>
+ The default false is for backwards compatibility, but
+ false or 1 should be set to follow RFC 6733's
+ recommendation on the use of unordered sending to avoid
+ head-of-line blocking. There is typically no meaningful
+ order to preserve, since the order in which outgoing
+ messages are received by a transport process isn't known
+ to the sender.</p>
+ <p>
+ Own Id: OTP-10889</p>
+ </item>
+ <item>
+ <p>
+ Complete/simplify Standards Compliance in User's Guide.</p>
+ <p>
+ Own Id: OTP-10927</p>
+ </item>
+ <item>
+ <p>
+ Add service option decode_format.</p>
+ <p>
+ To allow incoming messages to be decoded into maps or
+ lists instead of records. Messages can be presented in
+ any of the formats for encode.</p>
+ <p>
+ Decode performance has also been improved.</p>
+ <p>
+ Own Id: OTP-14511 Aux Id: OTP-14343 </p>
+ </item>
+ <item>
+ <p>
+ Add service option traffic_counters.</p>
+ <p>
+ To let message-related counters be disabled, which can be
+ a performance improvement in some usecases.</p>
+ <p>
+ Own Id: OTP-14521</p>
+ </item>
+ <item>
+ <p>
+ Allow loopback/any as local addresses in
+ diameter_tcp/sctp.</p>
+ <p>
+ The atoms were implied by documentation, but not handled
+ in code.</p>
+ <p>
+ Own Id: OTP-14544</p>
+ </item>
+ <item>
+ <p>
+ Add transport option strict_capx.</p>
+ <p>
+ To allow the RFC 6733 requirement that a transport
+ connection be closed if a message is received before
+ capabilities exchange to be relaxed.</p>
+ <p>
+ Own Id: OTP-14546</p>
+ </item>
+ <item>
+ <p>
+ Be consistent with service/transport configuration.</p>
+ <p>
+ For options for which it's meaningful, defaults values
+ for transport options can now be configured on a service.
+ This was previously the case only for an arbitrary subset
+ of options.</p>
+ <p>
+ Own Id: OTP-14555</p>
+ </item>
+ <item>
+ <p>
+ Add service/transport option avp_dictionaries.</p>
+ <p>
+ To provide better support for AVPs that are not defined
+ in the application dictionary: configuring additional
+ dictionaries in an avp_dictionaries tuple allows their
+ AVPs to be encoded/decoded in much the same fashion as
+ application AVPs.</p>
+ <p>
+ The motivation is RFC 7683 Diameter Overload, Indicator
+ Conveyance (DOIC), that defines AVPs intended to be
+ piggybacked onto arbitrary messages. A DOIC dictionary
+ has been included in the installation, in module
+ diameter_gen_doic_rfc7683.</p>
+ <p>
+ Own Id: OTP-14588</p>
+ </item>
+ <item>
+ <p>
+ Decode application AVPs in answers setting the E-bit.</p>
+ <p>
+ AVPs defined in the application of the message being sent
+ were previously not decoded, only those in the common
+ application that defines the answer-message grammar.</p>
+ <p>
+ Own Id: OTP-14596</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>diameter 2.0</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/diameter/doc/src/seealso.ent b/lib/diameter/doc/src/seealso.ent
index e5c284c6e8..72d74c103c 100644
--- a/lib/diameter/doc/src/seealso.ent
+++ b/lib/diameter/doc/src/seealso.ent
@@ -4,7 +4,7 @@
%CopyrightBegin%
-Copyright Ericsson AB 2012-2015. All Rights Reserved.
+Copyright Ericsson AB 2012-2017. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -53,7 +53,7 @@ significant.
<!ENTITY mod_application_opt '<seealso marker="diameter#application_opt">diameter:application_opt()</seealso>'>
<!ENTITY mod_call_opt '<seealso marker="diameter#call_opt">diameter:call_opt()</seealso>'>
<!ENTITY mod_capability '<seealso marker="diameter#capability">diameter:capability()</seealso>'>
-<!ENTITY mod_evaluable '<seealso marker="diameter#evaluable">diameter:evaluable()</seealso>'>
+<!ENTITY mod_eval '<seealso marker="diameter#eval">diameter:eval()</seealso>'>
<!ENTITY mod_peer_filter '<seealso marker="diameter#peer_filter">diameter:peer_filter()</seealso>'>
<!ENTITY mod_service_event '<seealso marker="diameter#service_event">diameter:service_event()</seealso>'>
<!ENTITY mod_service_event_info '<seealso marker="diameter#service_event_info">diameter:service_event_info()</seealso>'>
@@ -72,13 +72,14 @@ significant.
<!ENTITY watchdog_timer '<seealso marker="#watchdog_timer">watchdog_timer</seealso>'>
<!ENTITY mod_string_decode '<seealso marker="diameter#service_opt">diameter:service_opt()</seealso> <seealso marker="diameter#string_decode">string_decode</seealso>'>
+<!ENTITY mod_decode_format '<seealso marker="diameter#service_opt">diameter:service_opt()</seealso> <seealso marker="diameter#decode_format">decode_format</seealso>'>
<!-- diameter_app -->
<!ENTITY app_handle_answer '<seealso marker="diameter_app#Mod:handle_answer-4">handle_answer/4</seealso>'>
<!ENTITY app_handle_request '<seealso marker="diameter_app#Mod:handle_request-3">handle_request/3</seealso>'>
<!ENTITY app_handle_error '<seealso marker="diameter_app#Mod:handle_error-4">handle_error/4</seealso>'>
-<!ENTITY app_peer_down '<seealso marker="diameter_app#Mod:peer_down-3">peer_up/3</seealso>'>
+<!ENTITY app_peer_down '<seealso marker="diameter_app#Mod:peer_down-3">peer_down/3</seealso>'>
<!ENTITY app_peer_up '<seealso marker="diameter_app#Mod:peer_up-3">peer_up/3</seealso>'>
<!ENTITY app_pick_peer '<seealso marker="diameter_app#Mod:pick_peer-4">pick_peer/4</seealso>'>
<!ENTITY app_prepare_retransmit '<seealso marker="diameter_app#Mod:prepare_retransmit-3">prepare_retransmit/3</seealso>'>
diff --git a/lib/diameter/doc/standard/rfc7683.txt b/lib/diameter/doc/standard/rfc7683.txt
new file mode 100644
index 0000000000..ab2392c6c0
--- /dev/null
+++ b/lib/diameter/doc/standard/rfc7683.txt
@@ -0,0 +1,2355 @@
+
+
+
+
+
+
+Internet Engineering Task Force (IETF) J. Korhonen, Ed.
+Request for Comments: 7683 Broadcom Corporation
+Category: Standards Track S. Donovan, Ed.
+ISSN: 2070-1721 B. Campbell
+ Oracle
+ L. Morand
+ Orange Labs
+ October 2015
+
+
+ Diameter Overload Indication Conveyance
+
+Abstract
+
+ This specification defines a base solution for Diameter overload
+ control, referred to as Diameter Overload Indication Conveyance
+ (DOIC).
+
+Status of This Memo
+
+ This is an Internet Standards Track document.
+
+ This document is a product of the Internet Engineering Task Force
+ (IETF). It represents the consensus of the IETF community. It has
+ received public review and has been approved for publication by the
+ Internet Engineering Steering Group (IESG). Further information on
+ Internet Standards is available in Section 2 of RFC 5741.
+
+ Information about the current status of this document, any errata,
+ and how to provide feedback on it may be obtained at
+ http://www.rfc-editor.org/info/rfc7683.
+
+Copyright Notice
+
+ Copyright (c) 2015 IETF Trust and the persons identified as the
+ document authors. All rights reserved.
+
+ This document is subject to BCP 78 and the IETF Trust's Legal
+ Provisions Relating to IETF Documents
+ (http://trustee.ietf.org/license-info) in effect on the date of
+ publication of this document. Please review these documents
+ carefully, as they describe your rights and restrictions with respect
+ to this document. Code Components extracted from this document must
+ include Simplified BSD License text as described in Section 4.e of
+ the Trust Legal Provisions and are provided without warranty as
+ described in the Simplified BSD License.
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 1]
+
+RFC 7683 DOIC October 2015
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Terminology and Abbreviations . . . . . . . . . . . . . . . . 3
+ 3. Conventions Used in This Document . . . . . . . . . . . . . . 5
+ 4. Solution Overview . . . . . . . . . . . . . . . . . . . . . . 5
+ 4.1. Piggybacking . . . . . . . . . . . . . . . . . . . . . . 6
+ 4.2. DOIC Capability Announcement . . . . . . . . . . . . . . 7
+ 4.3. DOIC Overload Condition Reporting . . . . . . . . . . . . 9
+ 4.4. DOIC Extensibility . . . . . . . . . . . . . . . . . . . 11
+ 4.5. Simplified Example Architecture . . . . . . . . . . . . . 12
+ 5. Solution Procedures . . . . . . . . . . . . . . . . . . . . . 12
+ 5.1. Capability Announcement . . . . . . . . . . . . . . . . . 12
+ 5.1.1. Reacting Node Behavior . . . . . . . . . . . . . . . 13
+ 5.1.2. Reporting Node Behavior . . . . . . . . . . . . . . . 13
+ 5.1.3. Agent Behavior . . . . . . . . . . . . . . . . . . . 14
+ 5.2. Overload Report Processing . . . . . . . . . . . . . . . 15
+ 5.2.1. Overload Control State . . . . . . . . . . . . . . . 15
+ 5.2.2. Reacting Node Behavior . . . . . . . . . . . . . . . 19
+ 5.2.3. Reporting Node Behavior . . . . . . . . . . . . . . . 20
+ 5.3. Protocol Extensibility . . . . . . . . . . . . . . . . . 22
+ 6. Loss Algorithm . . . . . . . . . . . . . . . . . . . . . . . 23
+ 6.1. Overview . . . . . . . . . . . . . . . . . . . . . . . . 23
+ 6.2. Reporting Node Behavior . . . . . . . . . . . . . . . . . 24
+ 6.3. Reacting Node Behavior . . . . . . . . . . . . . . . . . 24
+ 7. Attribute Value Pairs . . . . . . . . . . . . . . . . . . . . 25
+ 7.1. OC-Supported-Features AVP . . . . . . . . . . . . . . . . 25
+ 7.2. OC-Feature-Vector AVP . . . . . . . . . . . . . . . . . . 25
+ 7.3. OC-OLR AVP . . . . . . . . . . . . . . . . . . . . . . . 26
+ 7.4. OC-Sequence-Number AVP . . . . . . . . . . . . . . . . . 26
+ 7.5. OC-Validity-Duration AVP . . . . . . . . . . . . . . . . 26
+ 7.6. OC-Report-Type AVP . . . . . . . . . . . . . . . . . . . 27
+ 7.7. OC-Reduction-Percentage AVP . . . . . . . . . . . . . . . 27
+ 7.8. AVP Flag Rules . . . . . . . . . . . . . . . . . . . . . 28
+ 8. Error Response Codes . . . . . . . . . . . . . . . . . . . . 28
+ 9. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 29
+ 9.1. AVP Codes . . . . . . . . . . . . . . . . . . . . . . . . 29
+ 9.2. New Registries . . . . . . . . . . . . . . . . . . . . . 29
+ 10. Security Considerations . . . . . . . . . . . . . . . . . . . 30
+ 10.1. Potential Threat Modes . . . . . . . . . . . . . . . . . 30
+ 10.2. Denial-of-Service Attacks . . . . . . . . . . . . . . . 31
+ 10.3. Noncompliant Nodes . . . . . . . . . . . . . . . . . . . 32
+ 10.4. End-to-End Security Issues . . . . . . . . . . . . . . . 32
+ 11. References . . . . . . . . . . . . . . . . . . . . . . . . . 34
+ 11.1. Normative References . . . . . . . . . . . . . . . . . . 34
+ 11.2. Informative References . . . . . . . . . . . . . . . . . 34
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 2]
+
+RFC 7683 DOIC October 2015
+
+
+ Appendix A. Issues Left for Future Specifications . . . . . . . 35
+ A.1. Additional Traffic Abatement Algorithms . . . . . . . . . 35
+ A.2. Agent Overload . . . . . . . . . . . . . . . . . . . . . 35
+ A.3. New Error Diagnostic AVP . . . . . . . . . . . . . . . . 35
+ Appendix B. Deployment Considerations . . . . . . . . . . . . . 35
+ Appendix C. Considerations for Applications Integrating the DOIC
+ Solution . . . . . . . . . . . . . . . . . . . . . . 36
+ C.1. Application Classification . . . . . . . . . . . . . . . 36
+ C.2. Implications of Application Type Overload . . . . . . . . 37
+ C.3. Request Transaction Classification . . . . . . . . . . . 38
+ C.4. Request Type Overload Implications . . . . . . . . . . . 39
+ Contributors . . . . . . . . . . . . . . . . . . . . . . . . . . 41
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 42
+
+1. Introduction
+
+ This specification defines a base solution for Diameter overload
+ control, referred to as Diameter Overload Indication Conveyance
+ (DOIC), based on the requirements identified in [RFC7068].
+
+ This specification addresses Diameter overload control between
+ Diameter nodes that support the DOIC solution. The solution, which
+ is designed to apply to existing and future Diameter applications,
+ requires no changes to the Diameter base protocol [RFC6733] and is
+ deployable in environments where some Diameter nodes do not implement
+ the Diameter overload control solution defined in this specification.
+
+ A new application specification can incorporate the overload control
+ mechanism specified in this document by making it mandatory to
+ implement for the application and referencing this specification
+ normatively. It is the responsibility of the Diameter application
+ designers to define how overload control mechanisms work on that
+ application.
+
+ Note that the overload control solution defined in this specification
+ does not address all the requirements listed in [RFC7068]. A number
+ of features related to overload control are left for future
+ specifications. See Appendix A for a list of extensions that are
+ currently being considered.
+
+2. Terminology and Abbreviations
+
+ Abatement
+
+ Reaction to receipt of an overload report resulting in a reduction
+ in traffic sent to the reporting node. Abatement actions include
+ diversion and throttling.
+
+
+
+
+Korhonen, et al. Standards Track [Page 3]
+
+RFC 7683 DOIC October 2015
+
+
+ Abatement Algorithm
+
+ An extensible method requested by reporting nodes and used by
+ reacting nodes to reduce the amount of traffic sent during an
+ occurrence of overload control.
+
+ Diversion
+
+ An overload abatement treatment where the reacting node selects
+ alternate destinations or paths for requests.
+
+ Host-Routed Requests
+
+ Requests that a reacting node knows will be served by a particular
+ host, either due to the presence of a Destination-Host Attribute
+ Value Pair (AVP) or by some other local knowledge on the part of
+ the reacting node.
+
+ Overload Control State (OCS)
+
+ Internal state maintained by a reporting or reacting node
+ describing occurrences of overload control.
+
+ Overload Report (OLR)
+
+ Overload control information for a particular overload occurrence
+ sent by a reporting node.
+
+ Reacting Node
+
+ A Diameter node that acts upon an overload report.
+
+ Realm-Routed Requests
+
+ Requests sent by a reacting node where the reacting node does not
+ know to which host the request will be routed.
+
+ Reporting Node
+
+ A Diameter node that generates an overload report. (This may or
+ may not be the overloaded node.)
+
+
+
+
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 4]
+
+RFC 7683 DOIC October 2015
+
+
+ Throttling
+
+ An abatement treatment that limits the number of requests sent by
+ the reacting node. Throttling can include a Diameter Client
+ choosing to not send requests, or a Diameter Agent or Server
+ rejecting requests with appropriate error responses. In both
+ cases, the result of the throttling is a permanent rejection of
+ the transaction.
+
+3. Conventions Used in This Document
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [RFC2119].
+
+ The interpretation from RFC 2119 [RFC2119] does not apply for the
+ above listed words when they are not used in all caps.
+
+4. Solution Overview
+
+ The Diameter Overload Information Conveyance (DOIC) solution allows
+ Diameter nodes to request that other Diameter nodes perform overload
+ abatement actions, that is, actions to reduce the load offered to the
+ overloaded node or realm.
+
+ A Diameter node that supports DOIC is known as a "DOIC node". Any
+ Diameter node can act as a DOIC node, including Diameter Clients,
+ Diameter Servers, and Diameter Agents. DOIC nodes are further
+ divided into "Reporting Nodes" and "Reacting Nodes." A reporting
+ node requests overload abatement by sending Overload Reports (OLRs).
+
+ A reacting node acts upon OLRs and performs whatever actions are
+ needed to fulfill the abatement requests included in the OLRs. A
+ reporting node may report overload on its own behalf or on behalf of
+ other nodes. Likewise, a reacting node may perform overload
+ abatement on its own behalf or on behalf of other nodes.
+
+ A Diameter node's role as a DOIC node is independent of its Diameter
+ role. For example, Diameter Agents may act as DOIC nodes, even
+ though they are not endpoints in the Diameter sense. Since Diameter
+ enables bidirectional applications, where Diameter Servers can send
+ requests towards Diameter Clients, a given Diameter node can
+ simultaneously act as both a reporting node and a reacting node.
+
+ Likewise, a Diameter Agent may act as a reacting node from the
+ perspective of upstream nodes, and a reporting node from the
+ perspective of downstream nodes.
+
+
+
+
+Korhonen, et al. Standards Track [Page 5]
+
+RFC 7683 DOIC October 2015
+
+
+ DOIC nodes do not generate new messages to carry DOIC-related
+ information. Rather, they "piggyback" DOIC information over existing
+ Diameter messages by inserting new AVPs into existing Diameter
+ requests and responses. Nodes indicate support for DOIC, and any
+ needed DOIC parameters, by inserting an OC-Supported-Features AVP
+ (Section 7.1) into existing requests and responses. Reporting nodes
+ send OLRs by inserting OC-OLR AVPs (Section 7.3).
+
+ A given OLR applies to the Diameter realm and application of the
+ Diameter message that carries it. If a reporting node supports more
+ than one realm and/or application, it reports independently for each
+ combination of realm and application. Similarly, the OC-Supported-
+ Features AVP applies to the realm and application of the enclosing
+ message. This implies that a node may support DOIC for one
+ application and/or realm, but not another, and may indicate different
+ DOIC parameters for each application and realm for which it supports
+ DOIC.
+
+ Reacting nodes perform overload abatement according to an agreed-upon
+ abatement algorithm. An abatement algorithm defines the meaning of
+ some of the parameters of an OLR and the procedures required for
+ overload abatement. An overload abatement algorithm separates
+ Diameter requests into two sets. The first set contains the requests
+ that are to undergo overload abatement treatment of either throttling
+ or diversion. The second set contains the requests that are to be
+ given normal routing treatment. This document specifies a single
+ "must-support" algorithm, namely, the "loss" algorithm (Section 6).
+ Future specifications may introduce new algorithms.
+
+ Overload conditions may vary in scope. For example, a single
+ Diameter node may be overloaded, in which case, reacting nodes may
+ attempt to send requests to other destinations. On the other hand,
+ an entire Diameter realm may be overloaded, in which case, such
+ attempts would do harm. DOIC OLRs have a concept of "report type"
+ (Section 7.6), where the type defines such behaviors. Report types
+ are extensible. This document defines report types for overload of a
+ specific host and for overload of an entire realm.
+
+ DOIC works through non-supporting Diameter Agents that properly pass
+ unknown AVPs unchanged.
+
+4.1. Piggybacking
+
+ There is no new Diameter application defined to carry overload-
+ related AVPs. The overload control AVPs defined in this
+ specification have been designed to be piggybacked on top of existing
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 6]
+
+RFC 7683 DOIC October 2015
+
+
+ application messages. This is made possible by adding the optional
+ overload control AVPs OC-OLR and OC-Supported-Features into existing
+ commands.
+
+ Reacting nodes indicate support for DOIC by including the
+ OC-Supported-Features AVP in all request messages originated or
+ relayed by the reacting node.
+
+ Reporting nodes indicate support for DOIC by including the
+ OC-Supported-Features AVP in all answer messages that are originated
+ or relayed by the reporting node and that are in response to a
+ request that contained the OC-Supported-Features AVP. Reporting
+ nodes may include overload reports using the OC-OLR AVP in answer
+ messages.
+
+ Note that the overload control solution does not have fixed server
+ and client roles. The DOIC node role is determined based on the
+ message type: whether the message is a request (i.e., sent by a
+ "reacting node") or an answer (i.e., sent by a "reporting node").
+ Therefore, in a typical client-server deployment, the Diameter Client
+ may report its overload condition to the Diameter Server for any
+ Diameter-Server-initiated message exchange. An example of such is
+ the Diameter Server requesting a re-authentication from a Diameter
+ Client.
+
+4.2. DOIC Capability Announcement
+
+ The DOIC solution supports the ability for Diameter nodes to
+ determine if other nodes in the path of a request support the
+ solution. This capability is referred to as DOIC Capability
+ Announcement (DCA) and is separate from the Diameter Capability
+ Exchange.
+
+ The DCA mechanism uses the OC-Supported-Features AVPs to indicate the
+ Diameter overload features supported.
+
+ The first node in the path of a Diameter request that supports the
+ DOIC solution inserts the OC-Supported-Features AVP in the request
+ message.
+
+ The individual features supported by the DOIC nodes are indicated in
+ the OC-Feature-Vector AVP. Any semantics associated with the
+ features will be defined in extension specifications that introduce
+ the features.
+
+ Note: As discussed elsewhere in the document, agents in the path
+ of the request can modify the OC-Supported-Features AVP.
+
+
+
+
+Korhonen, et al. Standards Track [Page 7]
+
+RFC 7683 DOIC October 2015
+
+
+ Note: The DOIC solution must support deployments where Diameter
+ Clients and/or Diameter Servers do not support the DOIC solution.
+ In this scenario, Diameter Agents that support the DOIC solution
+ may handle overload abatement for the non-supporting Diameter
+ nodes. In this case, the DOIC agent will insert the OC-Supported-
+ Features AVP in requests that do not already contain one, telling
+ the reporting node that there is a DOIC node that will handle
+ overload abatement. For transactions where there was an
+ OC-Supporting-Features AVP in the request, the agent will insert
+ the OC-Supported-Features AVP in answers, telling the reacting
+ node that there is a reporting node.
+
+ The OC-Feature-Vector AVP will always contain an indication of
+ support for the loss overload abatement algorithm defined in this
+ specification (see Section 6). This ensures that a reporting node
+ always supports at least one of the advertised abatement algorithms
+ received in a request messages.
+
+ The reporting node inserts the OC-Supported-Features AVP in all
+ answer messages to requests that contained the OC-Supported-Features
+ AVP. The contents of the reporting node's OC-Supported-Features AVP
+ indicate the set of Diameter overload features supported by the
+ reporting node. This specification defines one exception -- the
+ reporting node only includes an indication of support for one
+ overload abatement algorithm, independent of the number of overload
+ abatement algorithms actually supported by the reacting node. The
+ overload abatement algorithm indicated is the algorithm that the
+ reporting node intends to use should it enter an overload condition.
+ Reacting nodes can use the indicated overload abatement algorithm to
+ prepare for possible overload reports and must use the indicated
+ overload abatement algorithm if traffic reduction is actually
+ requested.
+
+ Note that the loss algorithm defined in this document is a
+ stateless abatement algorithm. As a result, it does not require
+ any actions by reacting nodes prior to the receipt of an overload
+ report. Stateful abatement algorithms that base the abatement
+ logic on a history of request messages sent might require reacting
+ nodes to maintain state in advance of receiving an overload report
+ to ensure that the overload reports can be properly handled.
+
+ While it should only be done in exceptional circumstances and not
+ during an active occurrence of overload, a reacting node that wishes
+ to transition to a different abatement algorithm can stop advertising
+ support for the algorithm indicated by the reporting node, as long as
+ support for the loss algorithm is always advertised.
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 8]
+
+RFC 7683 DOIC October 2015
+
+
+ The DCA mechanism must also allow the scenario where the set of
+ features supported by the sender of a request and by agents in the
+ path of a request differ. In this case, the agent can update the
+ OC-Supported-Features AVP to reflect the mixture of the two sets of
+ supported features.
+
+ Note: The logic to determine if the content of the OC-Supported-
+ Features AVP should be changed is out of scope for this document,
+ as is the logic to determine the content of a modified
+ OC-Supported-Features AVP. These are left to implementation
+ decisions. Care must be taken not to introduce interoperability
+ issues for downstream or upstream DOIC nodes. As such, the agent
+ must act as a fully compliant reporting node to the downstream
+ reacting node and as a fully compliant reacting node to the
+ upstream reporting node.
+
+4.3. DOIC Overload Condition Reporting
+
+ As with DOIC capability announcement, overload condition reporting
+ uses new AVPs (Section 7.3) to indicate an overload condition.
+
+ The OC-OLR AVP is referred to as an overload report. The OC-OLR AVP
+ includes the type of report, a sequence number, the length of time
+ that the report is valid, and AVPs specific to the abatement
+ algorithm.
+
+ Two types of overload reports are defined in this document: host
+ reports and realm reports.
+
+ A report of type "HOST_REPORT" is sent to indicate the overload of a
+ specific host, identified by the Origin-Host AVP of the message
+ containing the OLR, for the Application-ID indicated in the
+ transaction. When receiving an OLR of type "HOST_REPORT", a reacting
+ node applies overload abatement treatment to the host-routed requests
+ identified by the overload abatement algorithm (as defined in
+ Section 2) sent for this application to the overloaded host.
+
+ A report of type "REALM_REPORT" is sent to indicate the overload of a
+ realm for the Application-ID indicated in the transaction. The
+ overloaded realm is identified by the Destination-Realm AVP of the
+ message containing the OLR. When receiving an OLR of type
+ "REALM_REPORT", a reacting node applies overload abatement treatment
+ to realm-routed requests identified by the overload abatement
+ algorithm (as defined in Section 2) sent for this application to the
+ overloaded realm.
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 9]
+
+RFC 7683 DOIC October 2015
+
+
+ This document assumes that there is a single source for realm reports
+ for a given realm, or that if multiple nodes can send realm reports,
+ that each such node has full knowledge of the overload state of the
+ entire realm. A reacting node cannot distinguish between receiving
+ realm reports from a single node or from multiple nodes.
+
+ Note: Known issues exist if there are multiple sources for
+ overload reports that apply to the same Diameter entity. Reacting
+ nodes have no way of determining the source and, as such, will
+ treat them as coming from a single source. Variance in sequence
+ numbers between the two sources can then cause incorrect overload
+ abatement treatment to be applied for indeterminate periods of
+ time.
+
+ Reporting nodes are responsible for determining the need for a
+ reduction of traffic. The method for making this determination is
+ implementation specific and depends on the type of overload report
+ being generated. A host report might be generated by tracking use of
+ resources required by the host to handle transactions for the
+ Diameter application. A realm report generally impacts the traffic
+ sent to multiple hosts and, as such, requires tracking the capacity
+ of all servers able to handle realm-routed requests for the
+ application and realm.
+
+ Once a reporting node determines the need for a reduction in traffic,
+ it uses the DOIC-defined AVPs to report on the condition. These AVPs
+ are included in answer messages sent or relayed by the reporting
+ node. The reporting node indicates the overload abatement algorithm
+ that is to be used to handle the traffic reduction in the
+ OC-Supported-Features AVP. The OC-OLR AVP is used to communicate
+ information about the requested reduction.
+
+ Reacting nodes, upon receipt of an overload report, apply the
+ overload abatement algorithm to traffic impacted by the overload
+ report. The method used to determine the requests that are to
+ receive overload abatement treatment is dependent on the abatement
+ algorithm. The loss abatement algorithm is defined in this document
+ (Section 6). Other abatement algorithms can be defined in extensions
+ to the DOIC solution.
+
+ Two types of overload abatement treatment are defined, diversion and
+ throttling. Reacting nodes are responsible for determining which
+ treatment is appropriate for individual requests.
+
+ As the conditions that lead to the generation of the overload report
+ change, the reporting node can send new overload reports requesting
+ greater reduction if the condition gets worse or less reduction if
+ the condition improves. The reporting node sends an overload report
+
+
+
+Korhonen, et al. Standards Track [Page 10]
+
+RFC 7683 DOIC October 2015
+
+
+ with a duration of zero to indicate that the overload condition has
+ ended and abatement is no longer needed.
+
+ The reacting node also determines when the overload report expires
+ based on the OC-Validity-Duration AVP in the overload report and
+ stops applying the abatement algorithm when the report expires.
+
+ Note that erroneous overload reports can be used for DoS attacks.
+ This includes the ability to indicate that a significant reduction in
+ traffic, up to and including a request for no traffic, should be sent
+ to a reporting node. As such, care should be taken to verify the
+ sender of overload reports.
+
+4.4. DOIC Extensibility
+
+ The DOIC solution is designed to be extensible. This extensibility
+ is based on existing Diameter-based extensibility mechanisms, along
+ with the DOIC capability announcement mechanism.
+
+ There are multiple categories of extensions that are expected. This
+ includes the definition of new overload abatement algorithms, the
+ definition of new report types, and the definition of new scopes of
+ messages impacted by an overload report.
+
+ A DOIC node communicates supported features by including them in the
+ OC-Feature-Vector AVP, as a sub-AVP of OC-Supported-Features. Any
+ non-backwards-compatible DOIC extensions define new values for the
+ OC-Feature-Vector AVP. DOIC extensions also have the ability to add
+ new AVPs to the OC-Supported-Features AVP, if additional information
+ about the new feature is required.
+
+ Overload reports can also be extended by adding new sub-AVPs to the
+ OC-OLR AVP, allowing reporting nodes to communicate additional
+ information about handling an overload condition.
+
+ If necessary, new extensions can also define new AVPs that are not
+ part of the OC-Supported-Features and OC-OLR group AVPs. It is,
+ however, recommended that DOIC extensions use the OC-Supported-
+ Features AVP and OC-OLR AVP to carry all DOIC-related AVPs.
+
+
+
+
+
+
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 11]
+
+RFC 7683 DOIC October 2015
+
+
+4.5. Simplified Example Architecture
+
+ Figure 1 illustrates the simplified architecture for Diameter
+ overload information conveyance.
+
+ Realm X Same or other Realms
+ <--------------------------------------> <---------------------->
+
+
+ +--------+ : (optional) :
+ |Diameter| : :
+ |Server A|--+ .--. : +--------+ : .--.
+ +--------+ | _( `. : |Diameter| : _( `. +--------+
+ +--( )--:-| Agent |-:--( )--|Diameter|
+ +--------+ | ( ` . ) ) : +--------+ : ( ` . ) ) | Client |
+ |Diameter|--+ `--(___.-' : : `--(___.-' +--------+
+ |Server B| : :
+ +--------+ : :
+
+ End-to-end Overload Indication
+ 1) <----------------------------------------------->
+ Diameter Application Y
+
+ Overload Indication A Overload Indication A'
+ 2) <----------------------> <---------------------->
+ Diameter Application Y Diameter Application Y
+
+ Figure 1: Simplified Architecture Choices for Overload Indication
+ Delivery
+
+ In Figure 1, the Diameter overload indication can be conveyed (1)
+ end-to-end between servers and clients or (2) between servers and the
+ Diameter Agent inside the realm and then between the Diameter Agent
+ and the clients.
+
+5. Solution Procedures
+
+ This section outlines the normative behavior for the DOIC solution.
+
+5.1. Capability Announcement
+
+ This section defines DOIC Capability Announcement (DCA) behavior.
+
+ Note: This specification assumes that changes in DOIC node
+ capabilities are relatively rare events that occur as a result of
+ administrative action. Reacting nodes ought to minimize changes
+ that force the reporting node to change the features being used,
+ especially during active overload conditions. But even if
+
+
+
+Korhonen, et al. Standards Track [Page 12]
+
+RFC 7683 DOIC October 2015
+
+
+ reacting nodes avoid such changes, reporting nodes still have to
+ be prepared for them to occur. For example, differing
+ capabilities between multiple reacting nodes may still force a
+ reporting node to select different features on a per-transaction
+ basis.
+
+5.1.1. Reacting Node Behavior
+
+ A reacting node MUST include the OC-Supported-Features AVP in all
+ requests. It MAY include the OC-Feature-Vector AVP, as a sub-AVP of
+ OC-Supported-Features. If it does so, it MUST indicate support for
+ the "loss" algorithm. If the reacting node is configured to support
+ features (including other algorithms) in addition to the loss
+ algorithm, it MUST indicate such support in an OC-Feature-Vector AVP.
+
+ An OC-Supported-Features AVP in answer messages indicates there is a
+ reporting node for the transaction. The reacting node MAY take
+ action, for example, creating state for some stateful abatement
+ algorithm, based on the features indicated in the OC-Feature-Vector
+ AVP.
+
+ Note: The loss abatement algorithm does not require stateful
+ behavior when there is no active overload report.
+
+ Reacting nodes need to be prepared for the reporting node to change
+ selected algorithms. This can happen at any time, including when the
+ reporting node has sent an active overload report. The reacting node
+ can minimize the potential for changes by modifying the advertised
+ abatement algorithms sent to an overloaded reporting node to the
+ currently selected algorithm and loss (or just loss if it is the
+ currently selected algorithm). This has the effect of limiting the
+ potential change in abatement algorithm from the currently selected
+ algorithm to loss, avoiding changes to more complex abatement
+ algorithms that require state to operate properly.
+
+5.1.2. Reporting Node Behavior
+
+ Upon receipt of a request message, a reporting node determines if
+ there is a reacting node for the transaction based on the presence of
+ the OC-Supported-Features AVP in the request message.
+
+ If the request message contains an OC-Supported-Features AVP, then a
+ reporting node MUST include the OC-Supported-Features AVP in the
+ answer message for that transaction.
+
+ Note: Capability announcement is done on a per-transaction basis.
+ The reporting node cannot assume that the capabilities announced
+ by a reacting node will be the same between transactions.
+
+
+
+Korhonen, et al. Standards Track [Page 13]
+
+RFC 7683 DOIC October 2015
+
+
+ A reporting node MUST NOT include the OC-Supported-Features AVP,
+ OC-OLR AVP, or any other overload control AVPs defined in extension
+ documents in response messages for transactions where the request
+ message does not include the OC-Supported-Features AVP. Lack of the
+ OC-Supported-Features AVP in the request message indicates that there
+ is no reacting node for the transaction.
+
+ A reporting node knows what overload control functionality is
+ supported by the reacting node based on the content or absence of the
+ OC-Feature-Vector AVP within the OC-Supported-Features AVP in the
+ request message.
+
+ A reporting node MUST select a single abatement algorithm in the
+ OC-Feature-Vector AVP. The abatement algorithm selected MUST
+ indicate the abatement algorithm the reporting node wants the
+ reacting node to use when the reporting node enters an overload
+ condition.
+
+ The abatement algorithm selected MUST be from the set of abatement
+ algorithms contained in the request message's OC-Feature-Vector AVP.
+
+ A reporting node that selects the loss algorithm may do so by
+ including the OC-Feature-Vector AVP with an explicit indication of
+ the loss algorithm, or it MAY omit the OC-Feature-Vector AVP. If it
+ selects a different algorithm, it MUST include the OC-Feature-Vector
+ AVP with an explicit indication of the selected algorithm.
+
+ The reporting node SHOULD indicate support for other DOIC features
+ defined in extension documents that it supports and that apply to the
+ transaction. It does so using the OC-Feature-Vector AVP.
+
+ Note: Not all DOIC features will apply to all Diameter
+ applications or deployment scenarios. The features included in
+ the OC-Feature-Vector AVP are based on local policy of the
+ reporting node.
+
+5.1.3. Agent Behavior
+
+ Diameter Agents that support DOIC can ensure that all messages
+ relayed by the agent contain the OC-Supported-Features AVP.
+
+ A Diameter Agent MAY take on reacting node behavior for Diameter
+ endpoints that do not support the DOIC solution. A Diameter Agent
+ detects that a Diameter endpoint does not support DOIC reacting node
+ behavior when there is no OC-Supported-Features AVP in a request
+ message.
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 14]
+
+RFC 7683 DOIC October 2015
+
+
+ For a Diameter Agent to be a reacting node for a non-supporting
+ Diameter endpoint, the Diameter Agent MUST include the OC-Supported-
+ Features AVP in request messages it relays that do not contain the
+ OC-Supported-Features AVP.
+
+ A Diameter Agent MAY take on reporting node behavior for Diameter
+ endpoints that do not support the DOIC solution. The Diameter Agent
+ MUST have visibility to all traffic destined for the non-supporting
+ host in order to become the reporting node for the Diameter endpoint.
+ A Diameter Agent detects that a Diameter endpoint does not support
+ DOIC reporting node behavior when there is no OC-Supported-Features
+ AVP in an answer message for a transaction that contained the
+ OC-Supported-Features AVP in the request message.
+
+ If a request already has the OC-Supported-Features AVP, a Diameter
+ Agent MAY modify it to reflect the features appropriate for the
+ transaction. Otherwise, the agent relays the OC-Supported-Features
+ AVP without change.
+
+ Example: If the agent supports a superset of the features reported
+ by the reacting node, then the agent might choose, based on local
+ policy, to advertise that superset of features to the reporting
+ node.
+
+ If the Diameter Agent changes the OC-Supported-Features AVP in a
+ request message, then it is likely it will also need to modify the
+ OC-Supported-Features AVP in the answer message for the transaction.
+ A Diameter Agent MAY modify the OC-Supported-Features AVP carried in
+ answer messages.
+
+ When making changes to the OC-Supported-Features or OC-OLR AVPs, the
+ Diameter Agent needs to ensure consistency in its behavior with both
+ upstream and downstream DOIC nodes.
+
+5.2. Overload Report Processing
+
+5.2.1. Overload Control State
+
+ Both reacting and reporting nodes maintain Overload Control State
+ (OCS) for active overload conditions. The following sections define
+ behavior associated with that OCS.
+
+ The contents of the OCS in the reporting node and in the reacting
+ node represent logical constructs. The actual internal physical
+ structure of the state included in the OCS is an implementation
+ decision.
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 15]
+
+RFC 7683 DOIC October 2015
+
+
+5.2.1.1. Overload Control State for Reacting Nodes
+
+ A reacting node maintains the following OCS per supported Diameter
+ application:
+
+ o a host-type OCS entry for each Destination-Host to which it sends
+ host-type requests and
+
+ o a realm-type OCS entry for each Destination-Realm to which it
+ sends realm-type requests.
+
+ A host-type OCS entry is identified by the pair of Application-ID and
+ the node's DiameterIdentity.
+
+ A realm-type OCS entry is identified by the pair of Application-ID
+ and realm.
+
+ The host-type and realm-type OCS entries include the following
+ information (the actual information stored is an implementation
+ decision):
+
+ o Sequence number (as received in OC-OLR; see Section 7.3)
+
+ o Time of expiry (derived from OC-Validity-Duration AVP received in
+ the OC-OLR AVP and time of reception of the message carrying
+ OC-OLR AVP)
+
+ o Selected abatement algorithm (as received in the OC-Supported-
+ Features AVP)
+
+ o Input data that is abatement algorithm specific (as received in
+ the OC-OLR AVP -- for example, OC-Reduction-Percentage for the
+ loss abatement algorithm)
+
+5.2.1.2. Overload Control State for Reporting Nodes
+
+ A reporting node maintains OCS entries per supported Diameter
+ application, per supported (and eventually selected) abatement
+ algorithm, and per report type.
+
+ An OCS entry is identified by the tuple of Application-ID, report
+ type, and abatement algorithm, and it includes the following
+ information (the actual information stored is an implementation
+ decision):
+
+ o Sequence number
+
+ o Validity duration
+
+
+
+Korhonen, et al. Standards Track [Page 16]
+
+RFC 7683 DOIC October 2015
+
+
+ o Expiration time
+
+ o Input data that is algorithm specific (for example, the reduction
+ percentage for the loss abatement algorithm)
+
+5.2.1.3. Reacting Node's Maintenance of Overload Control State
+
+ When a reacting node receives an OC-OLR AVP, it MUST determine if it
+ is for an existing or new overload condition.
+
+ Note: For the remainder of this section, the term "OLR" refers to
+ the combination of the contents of the received OC-OLR AVP and the
+ abatement algorithm indicated in the received OC-Supported-
+ Features AVP.
+
+ When receiving an answer message with multiple OLRs of different
+ supported report types, a reacting node MUST process each received
+ OLR.
+
+ The OLR is for an existing overload condition if a reacting node has
+ an OCS that matches the received OLR.
+
+ For a host report, this means it matches the Application-ID and the
+ host's DiameterIdentity in an existing host OCS entry.
+
+ For a realm report, this means it matches the Application-ID and the
+ realm in an existing realm OCS entry.
+
+ If the OLR is for an existing overload condition, then a reacting
+ node MUST determine if the OLR is a retransmission or an update to
+ the existing OLR.
+
+ If the sequence number for the received OLR is greater than the
+ sequence number stored in the matching OCS entry, then a reacting
+ node MUST update the matching OCS entry.
+
+ If the sequence number for the received OLR is less than or equal to
+ the sequence number in the matching OCS entry, then a reacting node
+ MUST silently ignore the received OLR. The matching OCS MUST NOT be
+ updated in this case.
+
+ If the reacting node determines that the sequence number has rolled
+ over, then the reacting node MUST update the matching OCS entry.
+ This can be determined by recognizing that the number has changed
+ from a value within 1% of the maximum value in the OC-Sequence-Number
+ AVP to a value within 1% of the minimum value in the OC-Sequence-
+ Number AVP.
+
+
+
+
+Korhonen, et al. Standards Track [Page 17]
+
+RFC 7683 DOIC October 2015
+
+
+ If the received OLR is for a new overload condition, then a reacting
+ node MUST generate a new OCS entry for the overload condition.
+
+ For a host report, this means a reacting node creates an OCS entry
+ with the Application-ID in the received message and DiameterIdentity
+ of the Origin-Host in the received message.
+
+ Note: This solution assumes that the Origin-Host AVP in the answer
+ message included by the reporting node is not changed along the
+ path to the reacting node.
+
+ For a realm report, this means a reacting node creates an OCS entry
+ with the Application-ID in the received message and realm of the
+ Origin-Realm in the received message.
+
+ If the received OLR contains a validity duration of zero ("0"), then
+ a reacting node MUST update the OCS entry as being expired.
+
+ Note: It is not necessarily appropriate to delete the OCS entry,
+ as the recommended behavior is that the reacting node slowly
+ returns to full traffic when ending an overload abatement period.
+
+ The reacting node does not delete an OCS when receiving an answer
+ message that does not contain an OC-OLR AVP (i.e., absence of OLR
+ means "no change").
+
+5.2.1.4. Reporting Node's Maintenance of Overload Control State
+
+ A reporting node SHOULD create a new OCS entry when entering an
+ overload condition.
+
+ Note: If a reporting node knows through absence of the
+ OC-Supported-Features AVP in received messages that there are no
+ reacting nodes supporting DOIC, then the reporting node can choose
+ to not create OCS entries.
+
+ When generating a new OCS entry, the sequence number SHOULD be set to
+ zero ("0").
+
+ When generating sequence numbers for new overload conditions, the new
+ sequence number MUST be greater than any sequence number in an active
+ (unexpired) overload report for the same application and report type
+ previously sent by the reporting node. This property MUST hold over
+ a reboot of the reporting node.
+
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 18]
+
+RFC 7683 DOIC October 2015
+
+
+ Note: One way of addressing this over a reboot of a reporting node
+ is to use a timestamp for the first overload condition that occurs
+ after the report and to start using sequences beginning with zero
+ for subsequent overload conditions.
+
+ A reporting node MUST update an OCS entry when it needs to adjust the
+ validity duration of the overload condition at reacting nodes.
+
+ Example: If a reporting node wishes to instruct reacting nodes to
+ continue overload abatement for a longer period of time than
+ originally communicated. This also applies if the reporting node
+ wishes to shorten the period of time that overload abatement is to
+ continue.
+
+ A reporting node MUST update an OCS entry when it wishes to adjust
+ any parameters specific to the abatement algorithm, including, for
+ example, the reduction percentage used for the loss abatement
+ algorithm.
+
+ Example: If a reporting node wishes to change the reduction
+ percentage either higher (if the overload condition has worsened)
+ or lower (if the overload condition has improved), then the
+ reporting node would update the appropriate OCS entry.
+
+ A reporting node MUST increment the sequence number associated with
+ the OCS entry anytime the contents of the OCS entry are changed.
+ This will result in a new sequence number being sent to reacting
+ nodes, instructing them to process the OC-OLR AVP.
+
+ A reporting node SHOULD update an OCS entry with a validity duration
+ of zero ("0") when the overload condition ends.
+
+ Note: If a reporting node knows that the OCS entries in the
+ reacting nodes are near expiration, then the reporting node might
+ decide not to send an OLR with a validity duration of zero.
+
+ A reporting node MUST keep an OCS entry with a validity duration of
+ zero ("0") for a period of time long enough to ensure that any
+ unexpired reacting node's OCS entry created as a result of the
+ overload condition in the reporting node is deleted.
+
+5.2.2. Reacting Node Behavior
+
+ When a reacting node sends a request, it MUST determine if that
+ request matches an active OCS.
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 19]
+
+RFC 7683 DOIC October 2015
+
+
+ If the request matches an active OCS, then the reacting node MUST use
+ the overload abatement algorithm indicated in the OCS to determine if
+ the request is to receive overload abatement treatment.
+
+ For the loss abatement algorithm defined in this specification, see
+ Section 6 for the overload abatement algorithm logic applied.
+
+ If the overload abatement algorithm selects the request for overload
+ abatement treatment, then the reacting node MUST apply overload
+ abatement treatment on the request. The abatement treatment applied
+ depends on the context of the request.
+
+ If diversion abatement treatment is possible (i.e., a different path
+ for the request can be selected where the overloaded node is not part
+ of the different path), then the reacting node SHOULD apply diversion
+ abatement treatment to the request. The reacting node MUST apply
+ throttling abatement treatment to requests identified for abatement
+ treatment when diversion treatment is not possible or was not
+ applied.
+
+ Note: This only addresses the case where there are two defined
+ abatement treatments, diversion and throttling. Any extension
+ that defines a new abatement treatment must also define its
+ interaction with existing treatments.
+
+ If the overload abatement treatment results in throttling of the
+ request and if the reacting node is an agent, then the agent MUST
+ send an appropriate error as defined in Section 8.
+
+ Diameter endpoints that throttle requests need to do so according to
+ the rules of the client application. Those rules will vary by
+ application and are beyond the scope of this document.
+
+ In the case that the OCS entry indicated no traffic was to be sent to
+ the overloaded entity and the validity duration expires, then
+ overload abatement associated with the overload report MUST be ended
+ in a controlled fashion.
+
+5.2.3. Reporting Node Behavior
+
+ If there is an active OCS entry, then a reporting node SHOULD include
+ the OC-OLR AVP in all answers to requests that contain the
+ OC-Supported-Features AVP and that match the active OCS entry.
+
+ Note: A request matches 1) if the Application-ID in the request
+ matches the Application-ID in any active OCS entry and 2) if the
+ report type in the OCS entry matches a report type supported by
+ the reporting node as indicated in the OC-Supported-Features AVP.
+
+
+
+Korhonen, et al. Standards Track [Page 20]
+
+RFC 7683 DOIC October 2015
+
+
+ The contents of the OC-OLR AVP depend on the selected algorithm.
+
+ A reporting node MAY choose to not resend an overload report to a
+ reacting node if it can guarantee that this overload report is
+ already active in the reacting node.
+
+ Note: In some cases (e.g., when there are one or more agents in
+ the path between reporting and reacting nodes, or when overload
+ reports are discarded by reacting nodes), a reporting node may not
+ be able to guarantee that the reacting node has received the
+ report.
+
+ A reporting node MUST NOT send overload reports of a type that has
+ not been advertised as supported by the reacting node.
+
+ Note: A reacting node implicitly advertises support for the host
+ and realm report types by including the OC-Supported-Features AVP
+ in the request. Support for other report types will be explicitly
+ indicated by new feature bits in the OC-Feature-Vector AVP.
+
+ A reporting node SHOULD explicitly indicate the end of an overload
+ occurrence by sending a new OLR with OC-Validity-Duration set to a
+ value of zero ("0"). The reporting node SHOULD ensure that all
+ reacting nodes receive the updated overload report.
+
+ A reporting node MAY rely on the OC-Validity-Duration AVP values for
+ the implicit cleanup of overload control state on the reacting node.
+
+ Note: All OLRs sent have an expiration time calculated by adding
+ the validity duration contained in the OLR to the time the message
+ was sent. Transit time for the OLR can be safely ignored. The
+ reporting node can ensure that all reacting nodes have received
+ the OLR by continuing to send it in answer messages until the
+ expiration time for all OLRs sent for that overload condition have
+ expired.
+
+ When a reporting node sends an OLR, it effectively delegates any
+ necessary throttling to downstream nodes. If the reporting node also
+ locally throttles the same set of messages, the overall number of
+ throttled requests may be higher than intended. Therefore, before
+ applying local message throttling, a reporting node needs to check if
+ these messages match existing OCS entries, indicating that these
+ messages have survived throttling applied by downstream nodes that
+ have received the related OLR.
+
+ However, even if the set of messages match existing OCS entries, the
+ reporting node can still apply other abatement methods such as
+ diversion. The reporting node might also need to throttle requests
+
+
+
+Korhonen, et al. Standards Track [Page 21]
+
+RFC 7683 DOIC October 2015
+
+
+ for reasons other than overload. For example, an agent or server
+ might have a configured rate limit for each client and might throttle
+ requests that exceed that limit, even if such requests had already
+ been candidates for throttling by downstream nodes. The reporting
+ node also has the option to send new OLRs requesting greater
+ reductions in traffic, reducing the need for local throttling.
+
+ A reporting node SHOULD decrease requested overload abatement
+ treatment in a controlled fashion to avoid oscillations in traffic.
+
+ Example: A reporting node might wait some period of time after
+ overload ends before terminating the OLR, or it might send a
+ series of OLRs indicating progressively less overload severity.
+
+5.3. Protocol Extensibility
+
+ The DOIC solution can be extended. Types of potential extensions
+ include new traffic abatement algorithms, new report types, or other
+ new functionality.
+
+ When defining a new extension that requires new normative behavior,
+ the specification must define a new feature for the OC-Feature-Vector
+ AVP. This feature bit is used to communicate support for the new
+ feature.
+
+ The extension may define new AVPs for use in the DOIC Capability
+ Announcement and for use in DOIC overload reporting. These new AVPs
+ SHOULD be defined to be extensions to the OC-Supported-Features or
+ OC-OLR AVPs defined in this document.
+
+ The Grouped AVP extension mechanisms defined in [RFC6733] apply.
+ This allows, for example, defining a new feature that is mandatory to
+ be understood even when piggybacked on an existing application.
+
+ When defining new report type values, the corresponding specification
+ must define the semantics of the new report types and how they affect
+ the OC-OLR AVP handling.
+
+ The OC-Supported-Feature and OC-OLR AVPs can be expanded with
+ optional sub-AVPs only if a legacy DOIC implementation can safely
+ ignore them without breaking backward compatibility for the given
+ OC-Report-Type AVP value. Any new sub-AVPs must not require that the
+ M-bit be set.
+
+ Documents that introduce new report types must describe any
+ limitations on their use across non-supporting agents.
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 22]
+
+RFC 7683 DOIC October 2015
+
+
+ As with any Diameter specification, RFC 6733 requires all new AVPs to
+ be registered with IANA. See Section 9 for the required procedures.
+ New features (feature bits in the OC-Feature-Vector AVP) and report
+ types (in the OC-Report-Type AVP) MUST be registered with IANA.
+
+6. Loss Algorithm
+
+ This section documents the Diameter overload loss abatement
+ algorithm.
+
+6.1. Overview
+
+ The DOIC specification supports the ability for multiple overload
+ abatement algorithms to be specified. The abatement algorithm used
+ for any instance of overload is determined by the DOIC Capability
+ Announcement process documented in Section 5.1.
+
+ The loss algorithm described in this section is the default algorithm
+ that must be supported by all Diameter nodes that support DOIC.
+
+ The loss algorithm is designed to be a straightforward and stateless
+ overload abatement algorithm. It is used by reporting nodes to
+ request a percentage reduction in the amount of traffic sent. The
+ traffic impacted by the requested reduction depends on the type of
+ overload report.
+
+ Reporting nodes request the stateless reduction of the number of
+ requests by an indicated percentage. This percentage reduction is in
+ comparison to the number of messages the node otherwise would send,
+ regardless of how many requests the node might have sent in the past.
+
+ From a conceptual level, the logic at the reacting node could be
+ outlined as follows.
+
+ 1. An overload report is received, and the associated OCS is either
+ saved or updated (if required) by the reacting node.
+
+ 2. A new Diameter request is generated by the application running on
+ the reacting node.
+
+ 3. The reacting node determines that an active overload report
+ applies to the request, as indicated by the corresponding OCS
+ entry.
+
+ 4. The reacting node determines if overload abatement treatment
+ should be applied to the request. One approach that could be
+ taken for each request is to select a uniformly selected random
+ number between 1 and 100. If the random number is less than or
+
+
+
+Korhonen, et al. Standards Track [Page 23]
+
+RFC 7683 DOIC October 2015
+
+
+ equal to the indicated reduction percentage, then the request is
+ given abatement treatment; otherwise, the request is given normal
+ routing treatment.
+
+6.2. Reporting Node Behavior
+
+ The method a reporting node uses to determine the amount of traffic
+ reduction required to address an overload condition is an
+ implementation decision.
+
+ When a reporting node that has selected the loss abatement algorithm
+ determines the need to request a reduction in traffic, it includes an
+ OC-OLR AVP in answer messages as described in Section 5.2.3.
+
+ When sending the OC-OLR AVP, the reporting node MUST indicate a
+ percentage reduction in the OC-Reduction-Percentage AVP.
+
+ The reporting node MAY change the reduction percentage in subsequent
+ overload reports. When doing so, the reporting node must conform to
+ overload report handling specified in Section 5.2.3.
+
+6.3. Reacting Node Behavior
+
+ The method a reacting node uses to determine which request messages
+ are given abatement treatment is an implementation decision.
+
+ When receiving an OC-OLR in an answer message where the algorithm
+ indicated in the OC-Supported-Features AVP is the loss algorithm, the
+ reacting node MUST apply abatement treatment to the requested
+ percentage of request messages sent.
+
+ Note: The loss algorithm is a stateless algorithm. As a result,
+ the reacting node does not guarantee that there will be an
+ absolute reduction in traffic sent. Rather, it guarantees that
+ the requested percentage of new requests will be given abatement
+ treatment.
+
+ If the reacting node comes out of the 100% traffic reduction
+ (meaning, it has received an OLR indicating that no traffic should be
+ sent, as a result of the overload report timing out), the reacting
+ node sending the traffic SHOULD be conservative and, for example,
+ first send "probe" messages to learn the overload condition of the
+ overloaded node before converging to any traffic amount/rate decided
+ by the sender. Similar concerns apply in all cases when the overload
+ report times out, unless the previous overload report stated 0%
+ reduction.
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 24]
+
+RFC 7683 DOIC October 2015
+
+
+ Note: The goal of this behavior is to reduce the probability of
+ overload condition thrashing where an immediate transition from
+ 100% reduction to 0% reduction results in the reporting node
+ moving quickly back into an overload condition.
+
+7. Attribute Value Pairs
+
+ This section describes the encoding and semantics of the Diameter
+ Overload Indication Attribute Value Pairs (AVPs) defined in this
+ document.
+
+ Refer to Section 4 of [RFC6733] for more information on AVPs and AVP
+ data types.
+
+7.1. OC-Supported-Features AVP
+
+ The OC-Supported-Features AVP (AVP Code 621) is of type Grouped and
+ serves two purposes. First, it announces a node's support for the
+ DOIC solution in general. Second, it contains the description of the
+ supported DOIC features of the sending node. The OC-Supported-
+ Features AVP MUST be included in every Diameter request message a
+ DOIC supporting node sends.
+
+ OC-Supported-Features ::= < AVP Header: 621 >
+ [ OC-Feature-Vector ]
+ * [ AVP ]
+
+7.2. OC-Feature-Vector AVP
+
+ The OC-Feature-Vector AVP (AVP Code 622) is of type Unsigned64 and
+ contains a 64-bit flags field of announced capabilities of a DOIC
+ node. The value of zero (0) is reserved.
+
+ The OC-Feature-Vector sub-AVP is used to announce the DOIC features
+ supported by the DOIC node, in the form of a flag-bits field in which
+ each bit announces one feature or capability supported by the node.
+ The absence of the OC-Feature-Vector AVP in request messages
+ indicates that only the default traffic abatement algorithm described
+ in this specification is supported. The absence of the OC-Feature-
+ Vector AVP in answer messages indicates that the default traffic
+ abatement algorithm described in this specification is selected
+ (while other traffic abatement algorithms may be supported), and no
+ features other than abatement algorithms are supported.
+
+
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 25]
+
+RFC 7683 DOIC October 2015
+
+
+ The following capability is defined in this document:
+
+ OLR_DEFAULT_ALGO (0x0000000000000001)
+
+ When this flag is set by the a DOIC reacting node, it means that
+ the default traffic abatement (loss) algorithm is supported. When
+ this flag is set by a DOIC reporting node, it means that the loss
+ algorithm will be used for requested overload abatement.
+
+7.3. OC-OLR AVP
+
+ The OC-OLR AVP (AVP Code 623) is of type Grouped and contains the
+ information necessary to convey an overload report on an overload
+ condition at the reporting node. The application the OC-OLR AVP
+ applies to is identified by the Application-ID found in the Diameter
+ message header. The host or realm the OC-OLR AVP concerns is
+ determined from the Origin-Host AVP and/or Origin-Realm AVP found in
+ the encapsulating Diameter command. The OC-OLR AVP is intended to be
+ sent only by a reporting node.
+
+ OC-OLR ::= < AVP Header: 623 >
+ < OC-Sequence-Number >
+ < OC-Report-Type >
+ [ OC-Reduction-Percentage ]
+ [ OC-Validity-Duration ]
+ * [ AVP ]
+
+7.4. OC-Sequence-Number AVP
+
+ The OC-Sequence-Number AVP (AVP Code 624) is of type Unsigned64. Its
+ usage in the context of overload control is described in Section 5.2.
+
+ From the functionality point of view, the OC-Sequence-Number AVP is
+ used as a nonvolatile increasing counter for a sequence of overload
+ reports between two DOIC nodes for the same overload occurrence.
+ Sequence numbers are treated in a unidirectional manner, i.e., two
+ sequence numbers in each direction between two DOIC nodes are not
+ related or correlated.
+
+7.5. OC-Validity-Duration AVP
+
+ The OC-Validity-Duration AVP (AVP Code 625) is of type Unsigned32 and
+ indicates in seconds the validity time of the overload report. The
+ number of seconds is measured after reception of the first OC-OLR AVP
+ with a given value of OC-Sequence-Number AVP. The default value for
+ the OC-Validity-Duration AVP is 30 seconds. When the OC-Validity-
+ Duration AVP is not present in the OC-OLR AVP, the default value
+ applies. The maximum value for the OC-Validity-Duration AVP is
+
+
+
+Korhonen, et al. Standards Track [Page 26]
+
+RFC 7683 DOIC October 2015
+
+
+ 86,400 seconds (24 hours). If the value received in the OC-Validity-
+ Duration is greater than the maximum value, then the default value
+ applies.
+
+7.6. OC-Report-Type AVP
+
+ The OC-Report-Type AVP (AVP Code 626) is of type Enumerated. The
+ value of the AVP describes what the overload report concerns. The
+ following values are initially defined:
+
+ HOST_REPORT 0
+ The overload report is for a host. Overload abatement treatment
+ applies to host-routed requests.
+
+ REALM_REPORT 1
+ The overload report is for a realm. Overload abatement treatment
+ applies to realm-routed requests.
+
+ The values 2-4294967295 are unassigned.
+
+7.7. OC-Reduction-Percentage AVP
+
+ The OC-Reduction-Percentage AVP (AVP Code 627) is of type Unsigned32
+ and describes the percentage of the traffic that the sender is
+ requested to reduce, compared to what it otherwise would send. The
+ OC-Reduction-Percentage AVP applies to the default (loss) algorithm
+ specified in this specification. However, the AVP can be reused for
+ future abatement algorithms, if its semantics fit into the new
+ algorithm.
+
+ The value of the Reduction-Percentage AVP is between zero (0) and one
+ hundred (100). Values greater than 100 are ignored. The value of
+ 100 means that all traffic is to be throttled, i.e., the reporting
+ node is under a severe load and ceases to process any new messages.
+ The value of 0 means that the reporting node is in a stable state and
+ has no need for the reacting node to apply any traffic abatement.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 27]
+
+RFC 7683 DOIC October 2015
+
+
+7.8. AVP Flag Rules
+
+ +---------+
+ |AVP flag |
+ |rules |
+ +----+----+
+ AVP Section | |MUST|
+ Attribute Name Code Defined Value Type |MUST| NOT|
+ +--------------------------------------------------+----+----+
+ |OC-Supported-Features 621 7.1 Grouped | | V |
+ +--------------------------------------------------+----+----+
+ |OC-Feature-Vector 622 7.2 Unsigned64 | | V |
+ +--------------------------------------------------+----+----+
+ |OC-OLR 623 7.3 Grouped | | V |
+ +--------------------------------------------------+----+----+
+ |OC-Sequence-Number 624 7.4 Unsigned64 | | V |
+ +--------------------------------------------------+----+----+
+ |OC-Validity-Duration 625 7.5 Unsigned32 | | V |
+ +--------------------------------------------------+----+----+
+ |OC-Report-Type 626 7.6 Enumerated | | V |
+ +--------------------------------------------------+----+----+
+ |OC-Reduction | | |
+ | -Percentage 627 7.7 Unsigned32 | | V |
+ +--------------------------------------------------+----+----+
+
+ As described in the Diameter base protocol [RFC6733], the M-bit usage
+ for a given AVP in a given command may be defined by the application.
+
+8. Error Response Codes
+
+ When a DOIC node rejects a Diameter request due to overload, the DOIC
+ node MUST select an appropriate error response code. This
+ determination is made based on the probability of the request
+ succeeding if retried on a different path.
+
+ Note: This only applies for DOIC nodes that are not the originator
+ of the request.
+
+ A reporting node rejecting a Diameter request due to an overload
+ condition SHOULD send a DIAMETER_TOO_BUSY error response, if it can
+ assume that the same request may succeed on a different path.
+
+ If a reporting node knows or assumes that the same request will not
+ succeed on a different path, the DIAMETER_UNABLE_TO_COMPLY error
+ response SHOULD be used. Retrying would consume valuable resources
+ during an occurrence of overload.
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 28]
+
+RFC 7683 DOIC October 2015
+
+
+ For instance, if the request arrived at the reporting node without
+ a Destination-Host AVP, then the reporting node might determine
+ that there is an alternative Diameter node that could successfully
+ process the request and that retrying the transaction would not
+ negatively impact the reporting node. DIAMETER_TOO_BUSY would be
+ sent in this case.
+
+ If the request arrived at the reporting node with a Destination-
+ Host AVP populated with its own Diameter identity, then the
+ reporting node can assume that retrying the request would result
+ in it coming to the same reporting node.
+ DIAMETER_UNABLE_TO_COMPLY would be sent in this case.
+
+ A second example is when an agent that supports the DOIC solution
+ is performing the role of a reacting node for a non-supporting
+ client. Requests that are rejected as a result of DOIC throttling
+ by the agent in this scenario would generally be rejected with a
+ DIAMETER_UNABLE_TO_COMPLY response code.
+
+9. IANA Considerations
+
+9.1. AVP Codes
+
+ New AVPs defined by this specification are listed in Section 7. All
+ AVP codes are allocated from the "AVP Codes" sub-registry under the
+ "Authentication, Authorization, and Accounting (AAA) Parameters"
+ registry.
+
+9.2. New Registries
+
+ Two new registries have been created in the "AVP Specific Values"
+ sub-registry under the "Authentication, Authorization, and Accounting
+ (AAA) Parameters" registry.
+
+ A new "OC-Feature-Vector AVP Values (code 622)" registry has been
+ created. This registry contains the following:
+
+ Feature Vector Value Name
+
+ Feature Vector Value
+
+ Specification defining the new value
+
+ See Section 7.2 for the initial Feature Vector Value in the registry.
+ This specification defines the value. New values can be added to the
+ registry using the Specification Required policy [RFC5226].
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 29]
+
+RFC 7683 DOIC October 2015
+
+
+ A new "OC-Report-Type AVP Values (code 626)" registry has been
+ created. This registry contains the following:
+
+ Report Type Value Name
+
+ Report Type Value
+
+ Specification defining the new value
+
+ See Section 7.6 for the initial assignment in the registry. New
+ types can be added using the Specification Required policy [RFC5226].
+
+10. Security Considerations
+
+ DOIC gives Diameter nodes the ability to request that downstream
+ nodes send fewer Diameter requests. Nodes do this by exchanging
+ overload reports that directly effect this reduction. This exchange
+ is potentially subject to multiple methods of attack and has the
+ potential to be used as a denial-of-service (DoS) attack vector. For
+ instance, a series of injected realm OLRs with a requested reduction
+ percentage of 100% could be used to completely eliminate any traffic
+ from being sent to that realm.
+
+ Overload reports may contain information about the topology and
+ current status of a Diameter network. This information is
+ potentially sensitive. Network operators may wish to control
+ disclosure of overload reports to unauthorized parties to avoid their
+ use for competitive intelligence or to target attacks.
+
+ Diameter does not include features to provide end-to-end
+ authentication, integrity protection, or confidentiality. This may
+ cause complications when sending overload reports between non-
+ adjacent nodes.
+
+10.1. Potential Threat Modes
+
+ The Diameter protocol involves transactions in the form of requests
+ and answers exchanged between clients and servers. These clients and
+ servers may be peers, that is, they may share a direct transport
+ (e.g., TCP or SCTP) connection, or the messages may traverse one or
+ more intermediaries, known as Diameter Agents. Diameter nodes use
+ TLS, DTLS, or IPsec to authenticate peers and to provide
+ confidentiality and integrity protection of traffic between peers.
+ Nodes can make authorization decisions based on the peer identities
+ authenticated at the transport layer.
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 30]
+
+RFC 7683 DOIC October 2015
+
+
+ When agents are involved, this presents an effectively transitive
+ trust model. That is, a Diameter client or server can authorize an
+ agent for certain actions, but it must trust that agent to make
+ appropriate authorization decisions about its peers, and so on.
+ Since confidentiality and integrity protection occur at the transport
+ layer, agents can read, and perhaps modify, any part of a Diameter
+ message, including an overload report.
+
+ There are several ways an attacker might attempt to exploit the
+ overload control mechanism. An unauthorized third party might inject
+ an overload report into the network. If this third party is upstream
+ of an agent, and that agent fails to apply proper authorization
+ policies, downstream nodes may mistakenly trust the report. This
+ attack is at least partially mitigated by the assumption that nodes
+ include overload reports in Diameter answers but not in requests.
+ This requires an attacker to have knowledge of the original request
+ in order to construct an answer. Such an answer would also need to
+ arrive at a Diameter node via a protected transport connection.
+ Therefore, implementations MUST validate that an answer containing an
+ overload report is a properly constructed response to a pending
+ request prior to acting on the overload report, and that the answer
+ was received via an appropriate transport connection.
+
+ A similar attack involves a compromised but otherwise authorized node
+ that sends an inappropriate overload report. For example, a server
+ for the realm "example.com" might send an overload report indicating
+ that a competitor's realm "example.net" is overloaded. If other
+ nodes act on the report, they may falsely believe that "example.net"
+ is overloaded, effectively reducing that realm's capacity.
+ Therefore, it's critical that nodes validate that an overload report
+ received from a peer actually falls within that peer's responsibility
+ before acting on the report or forwarding the report to other peers.
+ For example, an overload report from a peer that applies to a realm
+ not handled by that peer is suspect. This may require out-of-band,
+ non-Diameter agreements and/or mechanisms.
+
+ This attack is partially mitigated by the fact that the
+ application, as well as host and realm, for a given OLR is
+ determined implicitly by respective AVPs in the enclosing answer.
+ If a reporting node modifies any of those AVPs, the enclosing
+ transaction will also be affected.
+
+10.2. Denial-of-Service Attacks
+
+ Diameter overload reports, especially realm reports, can cause a node
+ to cease sending some or all Diameter requests for an extended
+ period. This makes them a tempting vector for DoS attacks.
+ Furthermore, since Diameter is almost always used in support of other
+
+
+
+Korhonen, et al. Standards Track [Page 31]
+
+RFC 7683 DOIC October 2015
+
+
+ protocols, a DoS attack on Diameter is likely to impact those
+ protocols as well. In the worst case, where the Diameter application
+ is being used for access control into an IP network, a coordinated
+ DoS attack could result in the blockage of all traffic into that
+ network. Therefore, Diameter nodes MUST NOT honor or forward OLRs
+ received from peers that are not trusted to send them.
+
+ An attacker might use the information in an OLR to assist in DoS
+ attacks. For example, an attacker could use information about
+ current overload conditions to time an attack for maximum effect, or
+ use subsequent overload reports as a feedback mechanism to learn the
+ results of a previous or ongoing attack. Operators need the ability
+ to ensure that OLRs are not leaked to untrusted parties.
+
+10.3. Noncompliant Nodes
+
+ In the absence of an overload control mechanism, Diameter nodes need
+ to implement strategies to protect themselves from floods of
+ requests, and to make sure that a disproportionate load from one
+ source does not prevent other sources from receiving service. For
+ example, a Diameter server might throttle a certain percentage of
+ requests from sources that exceed certain limits. Overload control
+ can be thought of as an optimization for such strategies, where
+ downstream nodes never send the excess requests in the first place.
+ However, the presence of an overload control mechanism does not
+ remove the need for these other protection strategies.
+
+ When a Diameter node sends an overload report, it cannot assume that
+ all nodes will comply, even if they indicate support for DOIC. A
+ noncompliant node might continue to send requests with no reduction
+ in load. Such noncompliance could be done accidentally or
+ maliciously to gain an unfair advantage over compliant nodes.
+ Requirement 28 in [RFC7068] indicates that the overload control
+ solution cannot assume that all Diameter nodes in a network are
+ trusted. It also requires that malicious nodes not be allowed to
+ take advantage of the overload control mechanism to get more than
+ their fair share of service.
+
+10.4. End-to-End Security Issues
+
+ The lack of end-to-end integrity features makes it difficult to
+ establish trust in overload reports received from non-adjacent nodes.
+ Any agents in the message path may insert or modify overload reports.
+ Nodes must trust that their adjacent peers perform proper checks on
+ overload reports from their peers, and so on, creating a transitive-
+ trust requirement extending for potentially long chains of nodes.
+ Network operators must determine if this transitive trust requirement
+ is acceptable for their deployments. Nodes supporting Diameter
+
+
+
+Korhonen, et al. Standards Track [Page 32]
+
+RFC 7683 DOIC October 2015
+
+
+ overload control MUST give operators the ability to select which
+ peers are trusted to deliver overload reports and whether they are
+ trusted to forward overload reports from non-adjacent nodes. DOIC
+ nodes MUST strip DOIC AVPs from messages received from peers that are
+ not trusted for DOIC purposes.
+
+ The lack of end-to-end confidentiality protection means that any
+ Diameter Agent in the path of an overload report can view the
+ contents of that report. In addition to the requirement to select
+ which peers are trusted to send overload reports, operators MUST be
+ able to select which peers are authorized to receive reports. A node
+ MUST NOT send an overload report to a peer not authorized to receive
+ it. Furthermore, an agent MUST remove any overload reports that
+ might have been inserted by other nodes before forwarding a Diameter
+ message to a peer that is not authorized to receive overload reports.
+
+ A DOIC node cannot always automatically detect that a peer also
+ supports DOIC. For example, a node might have a peer that is a
+ non-supporting agent. If nodes on the other side of that agent
+ send OC-Supported-Features AVPs, the agent is likely to forward
+ them as unknown AVPs. Messages received across the non-supporting
+ agent may be indistinguishable from messages received across a
+ DOIC supporting agent, giving the false impression that the non-
+ supporting agent actually supports DOIC. This complicates the
+ transitive-trust nature of DOIC. Operators need to be careful to
+ avoid situations where a non-supporting agent is mistakenly
+ trusted to enforce DOIC-related authorization policies.
+
+ It is expected that work on end-to-end Diameter security might make
+ it easier to establish trust in non-adjacent nodes for overload
+ control purposes. Readers should be reminded, however, that the
+ overload control mechanism allows Diameter Agents to modify AVPs in,
+ or insert additional AVPs into, existing messages that are originated
+ by other nodes. If end-to-end security is enabled, there is a risk
+ that such modification could violate integrity protection. The
+ details of using any future Diameter end-to-end security mechanism
+ with overload control will require careful consideration, and are
+ beyond the scope of this document.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 33]
+
+RFC 7683 DOIC October 2015
+
+
+11. References
+
+11.1. Normative References
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119,
+ DOI 10.17487/RFC2119, March 1997,
+ <http://www.rfc-editor.org/info/rfc2119>.
+
+ [RFC5226] Narten, T. and H. Alvestrand, "Guidelines for Writing an
+ IANA Considerations Section in RFCs", BCP 26, RFC 5226,
+ DOI 10.17487/RFC5226, May 2008,
+ <http://www.rfc-editor.org/info/rfc5226>.
+
+ [RFC6733] Fajardo, V., Ed., Arkko, J., Loughney, J., and G. Zorn,
+ Ed., "Diameter Base Protocol", RFC 6733,
+ DOI 10.17487/RFC6733, October 2012,
+ <http://www.rfc-editor.org/info/rfc6733>.
+
+11.2. Informative References
+
+ [Cx] 3GPP, "Cx and Dx interfaces based on the Diameter
+ protocol; Protocol details", 3GPP TS 29.229 12.7.0,
+ September 2015.
+
+ [PCC] 3GPP, "Policy and charging control architecture", 3GPP
+ TS 23.203 12.10.0, September 2015.
+
+ [RFC4006] Hakala, H., Mattila, L., Koskinen, J-P., Stura, M., and J.
+ Loughney, "Diameter Credit-Control Application", RFC 4006,
+ DOI 10.17487/RFC4006, August 2005,
+ <http://www.rfc-editor.org/info/rfc4006>.
+
+ [RFC7068] McMurry, E. and B. Campbell, "Diameter Overload Control
+ Requirements", RFC 7068, DOI 10.17487/RFC7068, November
+ 2013, <http://www.rfc-editor.org/info/rfc7068>.
+
+ [S13] 3GPP, "Evolved Packet System (EPS); Mobility Management
+ Entity (MME) and Serving GPRS Support Node (SGSN) related
+ interfaces based on Diameter protocol", 3GPP TS 29.272
+ 12.8.0, September 2015.
+
+
+
+
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 34]
+
+RFC 7683 DOIC October 2015
+
+
+Appendix A. Issues Left for Future Specifications
+
+ The base solution for overload control does not cover all possible
+ use cases. A number of solution aspects were intentionally left for
+ future specification and protocol work. The following subsections
+ define some of the potential extensions to the DOIC solution.
+
+A.1. Additional Traffic Abatement Algorithms
+
+ This specification describes only means for a simple loss-based
+ algorithm. Future algorithms can be added using the designed
+ solution extension mechanism. The new algorithms need to be
+ registered with IANA. See Sections 7.2 and 9 for the required IANA
+ steps.
+
+A.2. Agent Overload
+
+ This specification focuses on Diameter endpoint (server or client)
+ overload. A separate extension will be required to outline the
+ handling of the case of agent overload.
+
+A.3. New Error Diagnostic AVP
+
+ This specification indicates the use of existing error messages when
+ nodes reject requests due to overload. There is an expectation that
+ additional error codes or AVPs will be defined in a separate
+ specification to indicate that overload was the reason for the
+ rejection of the message.
+
+Appendix B. Deployment Considerations
+
+ Non-supporting Agents
+
+ Due to the way that realm-routed requests are handled in Diameter
+ networks with the server selection for the request done by an
+ agent, network operators should enable DOIC at agents that perform
+ server selection first.
+
+ Topology-Hiding Interactions
+
+ There exist proxies that implement what is referred to as Topology
+ Hiding. This can include cases where the agent modifies the
+ Origin-Host in answer messages. The behavior of the DOIC solution
+ is not well understood when this happens. As such, the DOIC
+ solution does not address this scenario.
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 35]
+
+RFC 7683 DOIC October 2015
+
+
+ Inter-Realm/Administrative Domain Considerations
+
+ There are likely to be special considerations for handling DOIC
+ signaling across administrative boundaries. This includes
+ considerations for whether or not information included in the DOIC
+ signaling should be sent across those boundaries. In addition,
+ consideration should be taken as to whether or not a reacting node
+ in one realm can be trusted to implement the requested overload
+ abatement handling for overload reports received from a separately
+ administered realm.
+
+Appendix C. Considerations for Applications Integrating the DOIC
+ Solution
+
+ This section outlines considerations to be taken into account when
+ integrating the DOIC solution into Diameter applications.
+
+C.1. Application Classification
+
+ The following is a classification of Diameter applications and
+ request types. This discussion is meant to document factors that
+ play into decisions made by the Diameter entity responsible for
+ handling overload reports.
+
+ Section 8.1 of [RFC6733] defines two state machines that imply two
+ types of applications, session-less and session-based applications.
+ The primary difference between these types of applications is the
+ lifetime of Session-Ids.
+
+ For session-based applications, the Session-Id is used to tie
+ multiple requests into a single session.
+
+ The Credit-Control application defined in [RFC4006] is an example of
+ a Diameter session-based application.
+
+ In session-less applications, the lifetime of the Session-Id is a
+ single Diameter transaction, i.e., the session is implicitly
+ terminated after a single Diameter transaction and a new Session-Id
+ is generated for each Diameter request.
+
+
+
+
+
+
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 36]
+
+RFC 7683 DOIC October 2015
+
+
+ For the purposes of this discussion, session-less applications are
+ further divided into two types of applications:
+
+ Stateless Applications:
+
+ Requests within a stateless application have no relationship to
+ each other. The 3GPP-defined S13 application is an example of a
+ stateless application [S13], where only a Diameter command is
+ defined between a client and a server and no state is maintained
+ between two consecutive transactions.
+
+ Pseudo-Session Applications:
+
+ Applications that do not rely on the Session-Id AVP for
+ correlation of application messages related to the same session
+ but use other session-related information in the Diameter requests
+ for this purpose. The 3GPP-defined Cx application [Cx] is an
+ example of a pseudo-session application.
+
+ The handling of overload reports must take the type of application
+ into consideration, as discussed in Appendix C.2.
+
+C.2. Implications of Application Type Overload
+
+ This section discusses considerations for mitigating overload
+ reported by a Diameter entity. This discussion focuses on the type
+ of application. Appendix C.3 discusses considerations for handling
+ various request types when the target server is known to be in an
+ overloaded state.
+
+ These discussions assume that the strategy for mitigating the
+ reported overload is to reduce the overall workload sent to the
+ overloaded entity. The concept of applying overload treatment to
+ requests targeted for an overloaded Diameter entity is inherent to
+ this discussion. The method used to reduce offered load is not
+ specified here, but it could include routing requests to another
+ Diameter entity known to be able to handle them, or it could mean
+ rejecting certain requests. For a Diameter Agent, rejecting requests
+ will usually mean generating appropriate Diameter error responses.
+ For a Diameter client, rejecting requests will depend upon the
+ application. For example, it could mean giving an indication to the
+ entity requesting the Diameter service that the network is busy and
+ to try again later.
+
+
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 37]
+
+RFC 7683 DOIC October 2015
+
+
+ Stateless Applications:
+
+ By definition, there is no relationship between individual
+ requests in a stateless application. As a result, when a request
+ is sent or relayed to an overloaded Diameter entity -- either a
+ Diameter Server or a Diameter Agent -- the sending or relaying
+ entity can choose to apply the overload treatment to any request
+ targeted for the overloaded entity.
+
+ Pseudo-session Applications:
+
+ For pseudo-session applications, there is an implied ordering of
+ requests. As a result, decisions about which requests towards an
+ overloaded entity to reject could take the command code of the
+ request into consideration. This generally means that
+ transactions later in the sequence of transactions should be given
+ more favorable treatment than messages earlier in the sequence.
+ This is because more work has already been done by the Diameter
+ network for those transactions that occur later in the sequence.
+ Rejecting them could result in increasing the load on the network
+ as the transactions earlier in the sequence might also need to be
+ repeated.
+
+ Session-Based Applications:
+
+ Overload handling for session-based applications must take into
+ consideration the work load associated with setting up and
+ maintaining a session. As such, the entity sending requests
+ towards an overloaded Diameter entity for a session-based
+ application might tend to reject new session requests prior to
+ rejecting intra-session requests. In addition, session-ending
+ requests might be given a lower probability of being rejected, as
+ rejecting session-ending requests could result in session status
+ being out of sync between the Diameter clients and servers.
+ Application designers that would decide to reject mid-session
+ requests will need to consider whether the rejection invalidates
+ the session and any resulting session cleanup procedures.
+
+C.3. Request Transaction Classification
+
+ Independent Request:
+
+ An independent request is not correlated to any other requests,
+ and, as such, the lifetime of the Session-Id is constrained to an
+ individual transaction.
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 38]
+
+RFC 7683 DOIC October 2015
+
+
+ Session-Initiating Request:
+
+ A session-initiating request is the initial message that
+ establishes a Diameter session. The ACR message defined in
+ [RFC6733] is an example of a session-initiating request.
+
+ Correlated Session-Initiating Request:
+
+ There are cases when multiple session-initiated requests must be
+ correlated and managed by the same Diameter server. It is notably
+ the case in the 3GPP Policy and Charging Control (PCC)
+ architecture [PCC], where multiple apparently independent Diameter
+ application sessions are actually correlated and must be handled
+ by the same Diameter server.
+
+ Intra-session Request:
+
+ An intra-session request is a request that uses the same Session-
+ Id as the one used in a previous request. An intra-session
+ request generally needs to be delivered to the server that handled
+ the session-creating request for the session. The STR message
+ defined in [RFC6733] is an example of an intra-session request.
+
+ Pseudo-session Requests:
+
+ Pseudo-session requests are independent requests and do not use
+ the same Session-Id but are correlated by other session-related
+ information contained in the request. There exist Diameter
+ applications that define an expected ordering of transactions.
+ This sequencing of independent transactions results in a pseudo-
+ session. The AIR, MAR, and SAR requests in the 3GPP-defined Cx
+ [Cx] application are examples of pseudo-session requests.
+
+C.4. Request Type Overload Implications
+
+ The request classes identified in Appendix C.3 have implications on
+ decisions about which requests should be throttled first. The
+ following list of request treatments regarding throttling is provided
+ as guidelines for application designers when implementing the
+ Diameter overload control mechanism described in this document. The
+ exact behavior regarding throttling is a matter of local policy,
+ unless specifically defined for the application.
+
+ Independent Requests:
+
+ Independent requests can generally be given equal treatment when
+ making throttling decisions, unless otherwise indicated by
+ application requirements or local policy.
+
+
+
+Korhonen, et al. Standards Track [Page 39]
+
+RFC 7683 DOIC October 2015
+
+
+ Session-Initiating Requests:
+
+ Session-initiating requests often represent more work than
+ independent or intra-session requests. Moreover, session-
+ initiating requests are typically followed by other session-
+ related requests. Since the main objective of overload control is
+ to reduce the total number of requests sent to the overloaded
+ entity, throttling decisions might favor allowing intra-session
+ requests over session-initiating requests. In the absence of
+ local policies or application-specific requirements to the
+ contrary, individual session-initiating requests can be given
+ equal treatment when making throttling decisions.
+
+ Correlated Session-Initiating Requests:
+
+ A request that results in a new binding; where the binding is used
+ for routing of subsequent session-initiating requests to the same
+ server, it represents more work load than other requests. As
+ such, these requests might be throttled more frequently than other
+ request types.
+
+ Pseudo-session Requests:
+
+ Throttling decisions for pseudo-session requests can take into
+ consideration where individual requests fit into the overall
+ sequence of requests within the pseudo-session. Requests that are
+ earlier in the sequence might be throttled more aggressively than
+ requests that occur later in the sequence.
+
+ Intra-session Requests:
+
+ There are two types of intra-sessions requests, requests that
+ terminate a session and the remainder of intra-session requests.
+ Implementers and operators may choose to throttle session-
+ terminating requests less aggressively in order to gracefully
+ terminate sessions, allow cleanup of the related resources (e.g.,
+ session state), and avoid the need for additional intra-session
+ requests. Favoring session termination requests may reduce the
+ session management impact on the overloaded entity. The default
+ handling of other intra-session requests might be to treat them
+ equally when making throttling decisions. There might also be
+ application-level considerations whether some request types are
+ favored over others.
+
+
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 40]
+
+RFC 7683 DOIC October 2015
+
+
+Contributors
+
+ The following people contributed substantial ideas, feedback, and
+ discussion to this document:
+
+ o Eric McMurry
+
+ o Hannes Tschofenig
+
+ o Ulrich Wiehe
+
+ o Jean-Jacques Trottin
+
+ o Maria Cruz Bartolome
+
+ o Martin Dolly
+
+ o Nirav Salot
+
+ o Susan Shishufeng
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 41]
+
+RFC 7683 DOIC October 2015
+
+
+Authors' Addresses
+
+ Jouni Korhonen (editor)
+ Broadcom Corporation
+ 3151 Zanker Road
+ San Jose, CA 95134
+ United States
+
+
+
+ Steve Donovan (editor)
+ Oracle
+ 7460 Warren Parkway
+ Frisco, Texas 75034
+ United States
+
+
+
+ Ben Campbell
+ Oracle
+ 7460 Warren Parkway
+ Frisco, Texas 75034
+ United States
+
+
+
+ Lionel Morand
+ Orange Labs
+ 38/40 rue du General Leclerc
+ Issy-Les-Moulineaux Cedex 9 92794
+ France
+
+ Phone: +33145296257
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Korhonen, et al. Standards Track [Page 42]
+
diff --git a/lib/diameter/examples/code/client.erl b/lib/diameter/examples/code/client.erl
index 6fb90b1c09..0864919cdd 100644
--- a/lib/diameter/examples/code/client.erl
+++ b/lib/diameter/examples/code/client.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -39,7 +39,6 @@
-module(client).
-include_lib("diameter/include/diameter.hrl").
--include_lib("diameter/include/diameter_gen_base_rfc6733.hrl").
-export([start/1, %% start a service
start/2, %%
@@ -71,6 +70,7 @@
{'Product-Name', "Client"},
{'Auth-Application-Id', [0]},
{string_decode, false},
+ {decode_format, map},
{application, [{alias, common},
{dictionary, diameter_gen_base_rfc6733},
{module, client_cb}]}]).
@@ -108,9 +108,9 @@ connect(T) ->
call(Name) ->
SId = diameter:session_id(?L(Name)),
- RAR = #diameter_base_RAR{'Session-Id' = SId,
- 'Auth-Application-Id' = 0,
- 'Re-Auth-Request-Type' = 0},
+ RAR = ['RAR' | #{'Session-Id' => SId,
+ 'Auth-Application-Id' => 0,
+ 'Re-Auth-Request-Type' => 0}],
diameter:call(Name, common, RAR, []).
call() ->
diff --git a/lib/diameter/examples/code/client_cb.erl b/lib/diameter/examples/code/client_cb.erl
index ed1d3b9b7b..af2d4d6da7 100644
--- a/lib/diameter/examples/code/client_cb.erl
+++ b/lib/diameter/examples/code/client_cb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -55,21 +55,18 @@ prepare_request(#diameter_packet{msg = ['RAR' = T | Avps]}, _, {_, Caps}) ->
origin_realm = {OR, DR}}
= Caps,
- {send, [T, {'Origin-Host', OH},
- {'Origin-Realm', OR},
- {'Destination-Host', DH},
- {'Destination-Realm', DR}
- | Avps]};
-
-prepare_request(#diameter_packet{msg = Rec}, _, {_, Caps}) ->
- #diameter_caps{origin_host = {OH, DH},
- origin_realm = {OR, DR}}
- = Caps,
-
- {send, Rec#diameter_base_RAR{'Origin-Host' = OH,
- 'Origin-Realm' = OR,
- 'Destination-Host' = DH,
- 'Destination-Realm' = DR}}.
+ {send, [T | if is_map(Avps) ->
+ Avps#{'Origin-Host' => OH,
+ 'Origin-Realm' => OR,
+ 'Destination-Host' => DH,
+ 'Destination-Realm' => DR};
+ is_list(Avps) ->
+ [{'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Destination-Host', DH},
+ {'Destination-Realm', DR}
+ | Avps]
+ end]}.
%% prepare_retransmit/3
diff --git a/lib/diameter/examples/code/node.erl b/lib/diameter/examples/code/node.erl
index 246be4194b..77810bf893 100644
--- a/lib/diameter/examples/code/node.erl
+++ b/lib/diameter/examples/code/node.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,6 +30,8 @@
connect/2,
stop/1]).
+-export([message/3]).
+
-type protocol()
:: tcp | sctp.
@@ -128,6 +130,8 @@ stop(Name) ->
server_opts({T, Addr, Port}) ->
[{transport_module, tmod(T)},
{transport_config, [{reuseaddr, true},
+ {sender, true},
+ {message_cb, [fun ?MODULE:message/3, 0]},
{ip, addr(Addr)},
{port, Port}]}];
@@ -173,3 +177,26 @@ addr(loopback) ->
{127,0,0,1};
addr(A) ->
A.
+
+%% ---------------------------------------------------------------------------
+
+%% message/3
+%%
+%% Simple message callback that limits the number of concurrent
+%% requests on the peer connection in question.
+
+%% Incoming request.
+message(recv, <<_:32, 1:1, _/bits>> = Bin, N) ->
+ [Bin, N < 32, fun ?MODULE:message/3, N+1];
+
+%% Outgoing request.
+message(ack, <<_:32, 1:1, _/bits>>, _) ->
+ [];
+
+%% Incoming answer or request discarded.
+message(ack, _, N) ->
+ [N =< 32, fun ?MODULE:message/3, N-1];
+
+%% Outgoing message or incoming answer.
+message(_, Bin, _) ->
+ [Bin].
diff --git a/lib/diameter/include/diameter_gen.hrl b/lib/diameter/include/diameter_gen.hrl
index fb6370fe54..548763ec7d 100644
--- a/lib/diameter/include/diameter_gen.hrl
+++ b/lib/diameter/include/diameter_gen.hrl
@@ -26,13 +26,13 @@
%% encode_avps/3
-encode_avps(Name, Vals, Opts) ->
- diameter_gen:encode_avps(Name, Vals, Opts#{module => ?MODULE}).
+encode_avps(Name, Avps, Opts) ->
+ diameter_gen:encode_avps(Name, Avps, Opts#{module => ?MODULE}).
%% decode_avps/2
-decode_avps(Name, Recs, Opts) ->
- diameter_gen:decode_avps(Name, Recs, Opts#{module => ?MODULE}).
+decode_avps(Name, Avps, Opts) ->
+ diameter_gen:decode_avps(Name, Avps, Opts#{module => ?MODULE}).
%% avp/5
diff --git a/lib/diameter/src/Makefile b/lib/diameter/src/Makefile
index 6bf748a727..98636ed6e2 100644
--- a/lib/diameter/src/Makefile
+++ b/lib/diameter/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2016. All Rights Reserved.
+# Copyright Ericsson AB 2010-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -149,7 +149,7 @@ gen/$(DICT_YRL).erl: compiler/$(DICT_YRL).yrl
$(ERLC) -Werror -o $(@D) $<
# Generate the app file.
-$(APP_TARGET): $(APP_SRC) ../vsn.mk modules.mk app.sed
+$(APP_TARGET): $(APP_SRC) ../vsn.mk modules.mk
$(gen_verbose) \
M=`echo $(notdir $(APP_MODULES)) | tr ' ' ,`; \
C=`echo $(COMPILER_MODULES) | tr ' ' ,`; \
@@ -160,8 +160,7 @@ $(APP_TARGET): $(APP_SRC) ../vsn.mk modules.mk app.sed
-e "s;%COMPILER%;$$C;" \
-e "s;%INFO%;$$I;" \
-e "s;%REGISTERED%;$$R;" \
- $< \
- | sed -f app.sed > $@
+ $< > $@
$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
$(vsn_verbose) \
@@ -274,9 +273,7 @@ gen/diameter_gen_base_accounting.erl gen/diameter_gen_base_accounting.hrl: \
gen/diameter_gen_acct_rfc6733.erl gen/diameter_gen_acct_rfc6733.hrl: \
$(EBIN)/diameter_gen_base_rfc6733.$(EMULATOR)
-gen/diameter_gen_relay.erl gen/diameter_gen_relay.hrl \
-gen/diameter_gen_base_rfc3588.erl gen/diameter_gen_base_rfc3588.hrl \
-gen/diameter_gen_base_rfc6733.erl gen/diameter_gen_base_rfc6733.hrl: \
+$(DICT_ERLS) $(DICT_HRLS): \
$(COMPILER_MODULES:%=$(EBIN)/%.$(EMULATOR))
$(DICT_MODULES:gen/%=$(EBIN)/%.$(EMULATOR)): \
diff --git a/lib/diameter/src/app.sed b/lib/diameter/src/app.sed
deleted file mode 100644
index dd3806f5f1..0000000000
--- a/lib/diameter/src/app.sed
+++ /dev/null
@@ -1,41 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2014-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-
-#
-# Generate runtime_dependencies from applications to avoid having to
-# specify the same application more than once.
-#
-
-/{runtime_dependencies,/b v
-/{[-a-z]*, "[0-9.]*"}/!b
-/{vsn,/b
-
-/%%/!H
-s/{\([^,]*\)[^}]*}/\1/g
-s/%%/%,/
-b
-
-:v
-
-p
-x
-s/\n//
-s/%//g
-s/\n */ /g
-s/{\([^,]*\), "\([^"]*"\)}/"\1-\2/g
diff --git a/lib/diameter/src/base/diameter.erl b/lib/diameter/src/base/diameter.erl
index bd92e16fba..b90b794611 100644
--- a/lib/diameter/src/base/diameter.erl
+++ b/lib/diameter/src/base/diameter.erl
@@ -46,7 +46,10 @@
-export([start/0,
stop/0]).
--export_type([evaluable/0,
+-export_type([eval/0,
+ evaluable/0, %% deprecated
+ decode_format/0,
+ strict_arities/0,
restriction/0,
message_length/0,
remotes/0,
@@ -299,7 +302,7 @@ call(SvcName, App, Message) ->
| realm
| {host, any|'DiameterIdentity'()}
| {realm, any|'DiameterIdentity'()}
- | {eval, evaluable()}
+ | {eval, eval()}
| {neg, peer_filter()}
| {all, [peer_filter()]}
| {any, [peer_filter()]}.
@@ -307,10 +310,13 @@ call(SvcName, App, Message) ->
-opaque peer_ref()
:: pid().
--type evaluable()
+-type eval()
:: {module(), atom(), list()}
| fun()
- | maybe_improper_list(evaluable(), list()).
+ | maybe_improper_list(eval(), list()).
+
+-type evaluable()
+ :: eval().
-type sequence()
:: {'Unsigned32'(), 0..32}.
@@ -320,29 +326,61 @@ call(SvcName, App, Message) ->
| node
| nodes
| [node()]
- | evaluable().
+ | eval().
-type remotes()
:: boolean()
| [node()]
- | evaluable().
+ | eval().
-type message_length()
:: 0..16#FFFFFF.
+-type decode_format()
+ :: record
+ | list
+ | map
+ | none
+ | record_from_map.
+
+-type strict_arities()
+ :: false
+ | encode
+ | decode.
+
+%% Options common to both start_service/2 and add_transport/2.
+
+-type common_opt()
+ :: {pool_size, pos_integer()}
+ | {capabilities_cb, eval()}
+ | {capx_timeout, 'Unsigned32'()}
+ | {strict_capx, boolean()}
+ | {strict_mbit, boolean()}
+ | {avp_dictionaries, [module()]}
+ | {disconnect_cb, eval()}
+ | {dpr_timeout, 'Unsigned32'()}
+ | {dpa_timeout, 'Unsigned32'()}
+ | {incoming_maxlen, message_length()}
+ | {length_errors, exit | handle | discard}
+ | {connect_timer, 'Unsigned32'()}
+ | {watchdog_timer, 'Unsigned32'() | {module(), atom(), list()}}
+ | {watchdog_config, [{okay|suspect, non_neg_integer()}]}
+ | {spawn_opt, list()}.
+
%% Options passed to start_service/2
-type service_opt()
:: capability()
| {application, [application_opt()]}
| {restrict_connections, restriction()}
- | {sequence, sequence() | evaluable()}
+ | {sequence, sequence() | eval()}
| {share_peers, remotes()}
+ | {decode_format, decode_format()}
+ | {traffic_counters, boolean()}
| {string_decode, boolean()}
- | {strict_mbit, boolean()}
- | {incoming_maxlen, message_length()}
+ | {strict_arities, true | strict_arities()}
| {use_shared_peers, remotes()}
- | {spawn_opt, list()}.
+ | common_opt().
-type application_opt()
:: {alias, app_alias()}
@@ -372,20 +410,9 @@ call(SvcName, App, Message) ->
:: {transport_module, atom()}
| {transport_config, any()}
| {transport_config, any(), 'Unsigned32'() | infinity}
- | {pool_size, pos_integer()}
| {applications, [app_alias()]}
| {capabilities, [capability()]}
- | {capabilities_cb, evaluable()}
- | {capx_timeout, 'Unsigned32'()}
- | {capx_strictness, boolean()}
- | {disconnect_cb, evaluable()}
- | {dpr_timeout, 'Unsigned32'()}
- | {dpa_timeout, 'Unsigned32'()}
- | {length_errors, exit | handle | discard}
- | {connect_timer, 'Unsigned32'()}
- | {watchdog_timer, 'Unsigned32'() | {module(), atom(), list()}}
- | {watchdog_config, [{okay|suspect, non_neg_integer()}]}
- | {spawn_opt, list()}
+ | common_opt()
| {private, any()}.
%% Predicate passed to remove_transport/2
diff --git a/lib/diameter/src/base/diameter_callback.erl b/lib/diameter/src/base/diameter_callback.erl
index f9cdc66c70..d04a416bef 100644
--- a/lib/diameter/src/base/diameter_callback.erl
+++ b/lib/diameter/src/base/diameter_callback.erl
@@ -26,16 +26,16 @@
%% as the Diameter application callback in question. The record has
%% one field for each callback function as well as 'default' and
%% 'extra' fields. A function-specific field can be set to a
-%% diameter:evaluable() in order to redirect the callback
+%% diameter:eval() in order to redirect the callback
%% corresponding to that field, or to 'false' to request the default
%% callback implemented in this module. If neither of these fields are
%% set then the 'default' field determines the form of the callback: a
%% module name results in the usual callback as if the module had been
-%% configured directly as the callback module, a diameter_evaluable()
+%% configured directly as the callback module, a diameter_eval()
%% in a callback applied to the atom-valued callback name and argument
%% list. For all callbacks not to this module, the 'extra' field is a
%% list of additional arguments, following arguments supplied by
-%% diameter but preceding those of the diameter:evaluable() being
+%% diameter but preceding those of the diameter:eval() being
%% applied.
%%
%% For example, the following config to diameter:start_service/2, in
diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl
index 82fa796e69..493a6ab1e3 100644
--- a/lib/diameter/src/base/diameter_codec.erl
+++ b/lib/diameter/src/base/diameter_codec.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,7 @@
msg_name/2,
msg_id/1]).
-%% Towards generated encoders (from diameter_gen.hrl).
+%% towards diameter_gen
-export([pack_data/2,
pack_avp/2]).
@@ -92,8 +92,8 @@ encode(Mod, Opts, #diameter_packet{} = Pkt) ->
%% count encode errors.
?LOG(encode_error, {Reason, Stack, H}),
exit({?MODULE, encode, T});
- error: Reason ->
- T = {Reason, diameter_lib:get_stacktrace()},
+ error: Reason: Stack ->
+ T = {Reason, diameter_lib:stacktrace(Stack)},
?LOG(encode_error, T),
exit({?MODULE, encode, T})
end;
@@ -110,7 +110,7 @@ encode(Mod, Opts, Msg) ->
enc(_, Opts, #diameter_packet{msg = [#diameter_header{} = Hdr | As]}
= Pkt) ->
- try encode_avps(reorder(As), Opts) of
+ try encode_avps(As, Opts) of
Avps ->
Bin = list_to_binary(Avps),
Len = 20 + size(Bin),
@@ -134,8 +134,8 @@ enc(_, Opts, #diameter_packet{msg = [#diameter_header{} = Hdr | As]}
Eid:32,
Bin/binary>>}
catch
- error: Reason ->
- exit({Reason, diameter_lib:get_stacktrace(), Hdr})
+ error: Reason: Stack ->
+ exit({Reason, diameter_lib:stacktrace(Stack), Hdr})
end;
enc(Mod, Opts, #diameter_packet{header = Hdr0, msg = Msg} = Pkt) ->
@@ -179,14 +179,14 @@ enc(Mod, Opts, #diameter_packet{header = Hdr0, msg = Msg} = Pkt) ->
Eid:32,
Bin/binary>>}
catch
- error: Reason ->
+ error: Reason: Stack ->
Hdr = Hdr0#diameter_header{cmd_code = Code,
application_id = Aid,
is_request = RB,
is_proxiable = PB,
is_error = EB,
is_retransmitted = TB},
- exit({Reason, diameter_lib:get_stacktrace(), Hdr})
+ exit({Reason, diameter_lib:stacktrace(Stack), Hdr})
end.
%% values/1
@@ -206,51 +206,12 @@ values(Avps) ->
%% Message as a list of #diameter_avp{} ...
encode_avps(_, _, [#diameter_avp{} | _] = Avps, Opts) ->
- encode_avps(reorder(Avps), Opts);
+ encode_avps(Avps, Opts);
%% ... or as a tuple list or record.
encode_avps(Mod, MsgName, Values, Opts) ->
Mod:encode_avps(MsgName, Values, Opts).
-%% reorder/1
-%%
-%% Reorder AVPs for the relay case using the index field of
-%% diameter_avp records. Decode populates this field in collect_avps
-%% and presents AVPs in reverse order. A relay then sends the reversed
-%% list with a Route-Record AVP prepended. The goal here is just to do
-%% lists:reverse/1 in Grouped AVPs and the outer list, but only in the
-%% case there are indexed AVPs at all, so as not to reverse lists that
-%% have been explicilty sent (unindexed, in the desired order) as a
-%% diameter_avp list. The effect is the same as lists:keysort/2, but
-%% only on the cases we expect, not a general sort.
-
-reorder(Avps) ->
- case reorder(Avps, []) of
- false ->
- Avps;
- Sorted ->
- Sorted
- end.
-
-%% reorder/3
-
-%% In case someone has reversed the list already. (Not likely.)
-reorder([#diameter_avp{index = 0} | _] = Avps, Acc) ->
- Avps ++ Acc;
-
-%% Assume indexed AVPs are in reverse order.
-reorder([#diameter_avp{index = N} = A | Avps], Acc)
- when is_integer(N) ->
- lists:reverse(Avps, [A | Acc]);
-
-%% An unindexed AVP.
-reorder([H | T], Acc) ->
- reorder(T, [H | Acc]);
-
-%% No indexed members.
-reorder([], _) ->
- false.
-
%% encode_avps/2
encode_avps(Avps, Opts) ->
@@ -287,7 +248,8 @@ rec2msg(Mod, Rec) ->
%% longer *the* decode.
decode(Mod, Pkt) ->
- Opts = #{string_decode => true,
+ Opts = #{decode_format => record,
+ string_decode => true,
strict_mbit => true,
rfc => 6733},
decode(Mod, Opts, Pkt).
@@ -326,13 +288,7 @@ decode(Mod, AppMod, Opts, Pkt) ->
%% Relay application: just extract the avp's without any decoding of
%% their data since we don't know the application in question.
decode(?APP_ID_RELAY, _, _, _, #diameter_packet{} = Pkt) ->
- case collect_avps(Pkt) of
- {E, As} ->
- Pkt#diameter_packet{avps = As,
- errors = [E]};
- As ->
- Pkt#diameter_packet{avps = As}
- end;
+ collect_avps(Pkt);
%% Otherwise decode using the dictionary.
decode(_, Mod, AppMod, Opts, #diameter_packet{header = Hdr} = Pkt) ->
@@ -341,44 +297,50 @@ decode(_, Mod, AppMod, Opts, #diameter_packet{header = Hdr} = Pkt) ->
is_error = IsError}
= Hdr,
- MsgName = if IsError andalso not IsRequest ->
+ MsgName = if IsError, not IsRequest ->
'answer-message';
true ->
Mod:msg_name(CmdCode, IsRequest)
end,
- decode_avps(MsgName, Mod, AppMod, Opts, Pkt, collect_avps(Pkt));
+ decode_avps(MsgName, Mod, AppMod, Opts, Pkt);
decode(Id, Mod, AppMod, Opts, Bin)
when is_binary(Bin) ->
decode(Id, Mod, AppMod, Opts, #diameter_packet{header = decode_header(Bin),
bin = Bin}).
-%% decode_avps/6
-
-decode_avps(MsgName, Mod, AppMod, Opts, Pkt, {E, Avps}) ->
- ?LOG(invalid_avp_length, Pkt#diameter_packet.header),
- #diameter_packet{errors = Failed}
- = P
- = decode_avps(MsgName, Mod, AppMod, Opts, Pkt, Avps),
- P#diameter_packet{errors = [E | Failed]};
+%% decode_avps/5
-decode_avps('', _, _, _, Pkt, Avps) -> %% unknown message ...
- ?LOG(unknown_message, Pkt#diameter_packet.header),
- Pkt#diameter_packet{avps = lists:reverse(Avps),
- errors = [3001]}; %% DIAMETER_COMMAND_UNSUPPORTED
+decode_avps('', _, _, _, #diameter_packet{header = H, %% unknown message
+ bin = Bin}
+ = Pkt) ->
+ ?LOG(unknown_message, H),
+ Pkt#diameter_packet{avps = collect_avps(Bin),
+ errors = [3001]}; %% DIAMETER_COMMAND_UNSUPPORTED
%% msg = undefined identifies this case.
-decode_avps(MsgName, Mod, AppMod, Opts, Pkt, Avps) -> %% ... or not
+decode_avps(MsgName, Mod, AppMod, Opts, #diameter_packet{bin = Bin} = Pkt) ->
+ {_, Avps} = split_binary(Bin, 20),
{Rec, As, Errors} = Mod:decode_avps(MsgName,
Avps,
- Opts#{dictionary => AppMod,
+ Opts#{app_dictionary => AppMod,
failed_avp => false}),
?LOGC([] /= Errors, decode_errors, Pkt#diameter_packet.header),
- Pkt#diameter_packet{msg = Rec,
+ Pkt#diameter_packet{msg = reformat(MsgName, Rec, Opts),
errors = Errors,
avps = As}.
+%% reformat/3
+
+reformat(MsgName, Avps, #{decode_format := T})
+ when T == map;
+ T == list ->
+ [MsgName | Avps];
+
+reformat(_, Msg, _) ->
+ Msg.
+
%%% ---------------------------------------------------------------------------
%%% # decode_header/1
%%% ---------------------------------------------------------------------------
@@ -515,24 +477,21 @@ msg_id(<<_:32, Rbit:1, _:7, CmdCode:24, ApplId:32, _/binary>>) ->
%%% # collect_avps/1
%%% ---------------------------------------------------------------------------
-%% Note that the returned list of AVP's is reversed relative to their
-%% order in the binary. Note also that grouped avp's aren't unraveled,
-%% only those at the top level.
+%% This is only used for the relay decode. Note that grouped avp's
+%% aren't unraveled, only those at the top level.
--spec collect_avps(#diameter_packet{} | binary())
- -> [Avp]
- | {Error, [Avp]}
- when Avp :: #diameter_avp{},
- Error :: {5014, #diameter_avp{}}.
+-spec collect_avps(#diameter_packet{})
+ -> #diameter_packet{};
+ (binary())
+ -> [#diameter_avp{}].
-collect_avps(#diameter_packet{bin = <<_:20/binary, Avps/binary>>}) ->
- collect_avps(Avps, 0, []);
+collect_avps(#diameter_packet{bin = Bin} = Pkt) ->
+ Pkt#diameter_packet{avps = collect_avps(Bin)};
-collect_avps(Bin)
- when is_binary(Bin) ->
- collect_avps(Bin, 0, []).
+collect_avps(<<_:20/binary, Avps/binary>>) ->
+ collect(Avps).
-%% collect_avps/3
+%% collect/1
%% 0 1 2 3
%% 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@@ -546,66 +505,48 @@ collect_avps(Bin)
%% | Data ...
%% +-+-+-+-+-+-+-+-+
-collect_avps(<<Code:32, V:1, M:1, P:1, _:5, Len:24, I:V/unit:32, Rest/binary>>,
- N,
- Acc) ->
- collect_avps(Code,
- if 1 == V -> I; 0 == V -> undefined end,
- 1 == M,
- 1 == P,
- Len - 8 - V*4, %% Might be negative, which ensures
- ?PAD(Len), %% failure of the Data match below.
- Rest,
- N,
- Acc);
-
-collect_avps(<<>>, _, Acc) ->
- Acc;
+collect(<<Code:32, V:1, M:1, P:1, _:5, Len:24, I:V/unit:32, Rest/binary>>) ->
+ collect(Rest,
+ Code,
+ if 1 == V -> I; 0 == V -> undefined end,
+ Len - 8 - V*4, %% Might be negative, which ensures
+ ?PAD(Len), %% failure of the match below.
+ 1 == M,
+ 1 == P);
+
+collect(<<>>) ->
+ [];
%% Header is truncated. pack_avp/1 will pad this at encode if sent in
%% a Failed-AVP.
-collect_avps(Bin, _, Acc) ->
- {{5014, #diameter_avp{data = Bin}}, Acc}.
+collect(Bin) ->
+ [#diameter_avp{data = {5014, Bin}}].
-%% collect_avps/9
+%% collect/7
-%% Duplicate the diameter_avp creation in each branch below to avoid
-%% modifying the record, which profiling has shown to be a relatively
-%% costly part of building the list.
-
-collect_avps(Code, VendorId, M, P, Len, Pad, Rest, N, Acc) ->
- case Rest of
- <<Data:Len/binary, _:Pad/binary, T/binary>> ->
+collect(Bin, Code, Vid, DataLen, Pad, M, P) ->
+ case Bin of
+ <<Data:DataLen/binary, _:Pad/binary, Rest/binary>> ->
Avp = #diameter_avp{code = Code,
- vendor_id = VendorId,
+ vendor_id = Vid,
is_mandatory = M,
need_encryption = P,
- data = Data,
- index = N},
- collect_avps(T, N+1, [Avp | Acc]);
+ data = Data},
+ [Avp | collect(Rest)];
_ ->
%% Length in header points past the end of the message, or
- %% doesn't span the header. As stated in the 6733 text
- %% above, it's sufficient to return a zero-filled minimal
- %% payload if this is a request. Do this (in cases that we
- %% know the type) by inducing a decode failure and letting
- %% the dictionary's decode (in diameter_gen) deal with it.
- %%
- %% Note that the extra bit can only occur in the trailing
- %% AVP of a message or Grouped AVP, since a faulty AVP
- %% Length is otherwise indistinguishable from a correct
- %% one here, as we don't know the types of the AVPs being
- %% extracted.
- Avp = #diameter_avp{code = Code,
- vendor_id = VendorId,
- is_mandatory = M,
- need_encryption = P,
- data = {5014, Rest},
- index = N},
- [Avp | Acc]
+ %% doesn't span the header. Note that an length error can
+ %% only occur in the trailing AVP of a message or Grouped
+ %% AVP, since a faulty AVP Length is otherwise
+ %% indistinguishable from a correct one here, as we don't
+ %% know the types of the AVPs being extracted.
+ [#diameter_avp{code = Code,
+ vendor_id = Vid,
+ is_mandatory = M,
+ need_encryption = P,
+ data = {5014, Bin}}]
end.
-
%% 3588:
%%
%% DIAMETER_INVALID_AVP_LENGTH 5014
@@ -673,8 +614,8 @@ pack_avp(#diameter_avp{data = {T, {Type, Value}}}, Opts) ->
pack_avp(#diameter_avp{data = {T, Data}}, _) ->
pack_data(T, Data);
-pack_avp(#diameter_avp{data = {Dict, Name, Data}}, Opts) ->
- pack_data(Dict:avp_header(Name), Dict:avp(encode, Data, Name, Opts));
+pack_avp(#diameter_avp{data = {Dict, Name, Value}}, Opts) ->
+ pack_data(Dict:avp_header(Name), Dict:avp(encode, Value, Name, Opts));
%% ... with a truncated header ...
pack_avp(#diameter_avp{code = undefined, data = B}, _)
diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl
index 34018ae6d3..36ae4c2276 100644
--- a/lib/diameter/src/base/diameter_config.erl
+++ b/lib/diameter/src/base/diameter_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -102,9 +102,6 @@
-record(monitor, {mref = make_ref() :: reference(),
service}). %% name
-%% The default sequence mask.
--define(NOMASK, {0,32}).
-
%% Time to lay low before restarting a dead service.
-define(RESTART_SLEEP, 2000).
@@ -560,87 +557,186 @@ add(SvcName, Type, Opts0) ->
end.
transport_opts(Opts) ->
- lists:map(fun topt/1, Opts).
+ [setopt(transport, T) || T <- Opts].
+
+%% setopt/2
-topt(T) ->
- case opt(T) of
+setopt(K, T) ->
+ case opt(K, T) of
{value, X} ->
X;
true ->
T;
false ->
- ?THROW({invalid, T})
+ ?THROW({invalid, T});
+ {error, Reason} ->
+ ?THROW({invalid, T, Reason})
end.
-opt({transport_module, M}) ->
+%% opt/2
+
+opt(_, {incoming_maxlen, N}) ->
+ is_integer(N) andalso 0 =< N andalso N < 1 bsl 24;
+
+opt(service, {K, B})
+ when K == string_decode;
+ K == traffic_counters ->
+ is_boolean(B);
+
+opt(service, {K, false})
+ when K == share_peers;
+ K == use_shared_peers;
+ K == monitor;
+ K == restrict_connections;
+ K == strict_arities ->
+ true;
+
+opt(service, {K, true})
+ when K == share_peers;
+ K == use_shared_peers;
+ K == strict_arities ->
+ true;
+
+opt(service, {decode_format, T})
+ when T == record;
+ T == list;
+ T == map;
+ T == none;
+ T == record_from_map ->
+ true;
+
+opt(service, {strict_arities, T})
+ when T == encode;
+ T == decode ->
+ true;
+
+opt(service, {restrict_connections, T})
+ when T == node;
+ T == nodes ->
+ true;
+
+opt(service, {K, T})
+ when (K == share_peers
+ orelse K == use_shared_peers
+ orelse K == restrict_connections), ([] == T
+ orelse is_atom(hd(T))) ->
+ true;
+
+opt(service, {monitor, P}) ->
+ is_pid(P);
+
+opt(service, {K, F})
+ when K == restrict_connections;
+ K == share_peers;
+ K == use_shared_peers ->
+ try diameter_lib:eval(F) of %% but no guarantee that it won't fail later
+ Nodes ->
+ is_list(Nodes) orelse {error, Nodes}
+ catch
+ E:R:Stack ->
+ {error, {E, R, Stack}}
+ end;
+
+opt(service, {sequence, {H,N}}) ->
+ 0 =< N andalso N =< 32
+ andalso is_integer(H)
+ andalso 0 =< H
+ andalso 0 == H bsr (32-N);
+
+opt(service = S, {sequence = K, F}) ->
+ try diameter_lib:eval(F) of
+ {_,_} = T ->
+ KT = {K,T},
+ opt(S, KT) andalso {value, KT};
+ V ->
+ {error, V}
+ catch
+ E:R:Stack ->
+ {error, {E, R, Stack}}
+ end;
+
+opt(transport, {transport_module, M}) ->
is_atom(M);
-opt({transport_config, _, Tmo}) ->
+opt(transport, {transport_config, _, Tmo}) ->
?IS_UINT32(Tmo) orelse Tmo == infinity;
-opt({applications, As}) ->
+opt(transport, {applications, As}) ->
is_list(As);
-opt({capabilities, Os}) ->
- is_list(Os) andalso ok == encode_CER(Os);
+opt(transport, {capabilities, Os}) ->
+ is_list(Os) andalso try ok = encode_CER(Os), true
+ catch ?FAILURE(No) -> {error, No}
+ end;
-opt({K, Tmo})
+opt(_, {K, Tmo})
when K == capx_timeout;
K == dpr_timeout;
K == dpa_timeout ->
?IS_UINT32(Tmo);
-opt({capx_strictness, B}) ->
+opt(_, {capx_strictness, B}) ->
+ is_boolean(B) andalso {value, {strict_capx, B}};
+opt(_, {K, B})
+ when K == strict_capx;
+ K == strict_mbit ->
is_boolean(B);
-opt({length_errors, T}) ->
+opt(_, {avp_dictionaries, Mods}) ->
+ is_list(Mods) andalso lists:all(fun erlang:is_atom/1, Mods);
+
+opt(_, {length_errors, T}) ->
lists:member(T, [exit, handle, discard]);
-opt({K, Tmo})
- when K == reconnect_timer; %% deprecated
- K == connect_timer ->
+opt(transport, {reconnect_timer, Tmo}) -> %% deprecated
+ ?IS_UINT32(Tmo) andalso {value, {connect_timer, Tmo}};
+opt(_, {connect_timer, Tmo}) ->
?IS_UINT32(Tmo);
-opt({watchdog_timer, {M,F,A}})
+opt(_, {watchdog_timer, {M,F,A}})
when is_atom(M), is_atom(F), is_list(A) ->
true;
-opt({watchdog_timer, Tmo}) ->
+opt(_, {watchdog_timer, Tmo}) ->
?IS_UINT32(Tmo);
-opt({watchdog_config, L}) ->
- is_list(L) andalso lists:all(fun wdopt/1, L);
+opt(_, {watchdog_config, L}) ->
+ is_list(L) andalso lists:all(fun wd/1, L);
-opt({spawn_opt, {M,F,A}})
+opt(_, {spawn_opt, {M,F,A}})
when is_atom(M), is_atom(F), is_list(A) ->
true;
-opt({spawn_opt = K, Opts}) ->
+opt(_, {spawn_opt = K, Opts}) ->
if is_list(Opts) ->
{value, {K, spawn_opts(Opts)}};
true ->
false
end;
-opt({pool_size, N}) ->
+opt(_, {pool_size, N}) ->
is_integer(N) andalso 0 < N;
-%% Options that we can't validate.
-opt({K, _})
+%% Options we can't validate.
+opt(_, {K, _})
+ when K == disconnect_cb;
+ K == capabilities_cb ->
+ true;
+opt(transport, {K, _})
when K == transport_config;
- K == capabilities_cb;
- K == disconnect_cb;
K == private ->
true;
-%% Anything else, which is ignored by us. This makes options sensitive
-%% to spelling mistakes but arbitrary options are passed by some users
-%% as a way to identify transports. (That is, can't just do away with
-%% it.)
-opt(_) ->
- true.
+%% Anything else, which is ignored in transport config. This makes
+%% options sensitive to spelling mistakes, but arbitrary options are
+%% passed by some users as a way to identify transports so can't just
+%% do away with it.
+opt(K, _) ->
+ K == transport.
+
+%% wd/1
-wdopt({K,N}) ->
+wd({K,N}) ->
(K == okay orelse K == suspect) andalso is_integer(N) andalso 0 =< N;
-wdopt(_) ->
+wd(_) ->
false.
%% start_transport/2
@@ -705,16 +801,7 @@ make_config(SvcName, Opts) ->
ok = encode_CER(CapOpts),
- SvcOpts = make_opts((Opts -- AppOpts) -- CapOpts,
- [{false, share_peers},
- {false, use_shared_peers},
- {false, monitor},
- {?NOMASK, sequence},
- {nodes, restrict_connections},
- {16#FFFFFF, incoming_maxlen},
- {true, strict_mbit},
- {true, string_decode},
- {[], spawn_opt}]),
+ SvcOpts = service_opts((Opts -- AppOpts) -- CapOpts),
D = proplists:get_value(string_decode, SvcOpts, true),
@@ -728,98 +815,22 @@ binary_caps(Caps, true) ->
binary_caps(Caps, false) ->
diameter_capx:binary_caps(Caps).
-%% make_opts/2
-
-make_opts(Opts, Defs) ->
- Known = [{K, get_opt(K, Opts, D)} || {D,K} <- Defs],
- Unknown = Opts -- Known,
-
- [] == Unknown orelse ?THROW({invalid, hd(Unknown)}),
-
- [{K, opt(K,V)} || {K,V} <- Known].
-
-opt(incoming_maxlen, N)
- when 0 =< N, N < 1 bsl 24 ->
- N;
-
-opt(spawn_opt, {M,F,A} = T)
- when is_atom(M), is_atom(F), is_list(A) ->
- T;
-
-opt(spawn_opt, L)
- when is_list(L) ->
- spawn_opts(L);
-
-opt(K, false = B)
- when K == share_peers;
- K == use_shared_peers;
- K == monitor;
- K == restrict_connections;
- K == strict_mbit;
- K == string_decode ->
- B;
-
-opt(K, true = B)
- when K == share_peers;
- K == use_shared_peers;
- K == strict_mbit;
- K == string_decode ->
- B;
+%% service_opts/1
-opt(restrict_connections, T)
- when T == node;
- T == nodes ->
- T;
-
-opt(K, T)
- when (K == share_peers
- orelse K == use_shared_peers
- orelse K == restrict_connections), ([] == T
- orelse is_atom(hd(T))) ->
- T;
-
-opt(monitor, P)
- when is_pid(P) ->
- P;
-
-opt(K, F)
- when K == restrict_connections;
- K == share_peers;
- K == use_shared_peers ->
- try diameter_lib:eval(F) of %% but no guarantee that it won't fail later
- Nodes when is_list(Nodes) ->
- F;
- V ->
- ?THROW({value, {K,V}})
- catch
- E:R ->
- ?THROW({value, {K, E, R, ?STACK}})
- end;
-
-opt(sequence, {_,_} = T) ->
- sequence(T);
-
-opt(sequence = K, F) ->
- try diameter_lib:eval(F) of
- T -> sequence(T)
- catch
- E:R ->
- ?THROW({value, {K, E, R, ?STACK}})
- end;
-
-opt(K, _) ->
- ?THROW({value, K}).
+service_opts(Opts) ->
+ Res = [setopt(service, T) || T <- Opts],
+ Keys = sets:to_list(sets:from_list([K || {K,_} <- Res])), %% unique
+ Dups = lists:foldl(fun(K,A) -> lists:keydelete(K, 1, A) end, Res, Keys),
+ [] == Dups orelse ?THROW({duplicate, Dups}),
+ Res.
+%% Reject duplicates on a service, but not on a transport. There's no
+%% particular reason for the inconsistency, but the historic behaviour
+%% ignores all but the first of a transport_opt(), and there's no real
+%% reason to change it.
spawn_opts(L) ->
[T || T <- L, T /= link, T /= monitor].
-sequence({H,N} = T)
- when 0 =< N, N =< 32, 0 =< H, 0 == H bsr (32-N) ->
- T;
-
-sequence(_) ->
- ?THROW({value, sequence}).
-
make_caps(Caps, Opts) ->
case diameter_capx:make_caps(Caps, Opts) of
{ok, T} ->
@@ -921,8 +932,8 @@ cb(M,F) ->
try M:F() of
V -> V
catch
- E: Reason ->
- ?THROW({callback, E, Reason, ?STACK})
+ E: Reason: Stack ->
+ ?THROW({callback, E, Reason, Stack})
end.
%% call/1
diff --git a/lib/diameter/src/base/diameter_gen.erl b/lib/diameter/src/base/diameter_gen.erl
index e832832876..d110a3015e 100644
--- a/lib/diameter/src/base/diameter_gen.erl
+++ b/lib/diameter/src/base/diameter_gen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,6 +26,14 @@
-module(diameter_gen).
+-compile({inline, [incr/8,
+ incr/4,
+ field/1,
+ setopts/4,
+ avp_arity/5,
+ set_failed/2,
+ set_strict/3]}).
+
-export([encode_avps/3,
decode_avps/3,
grouped_avp/4,
@@ -37,7 +45,7 @@
-define(THROW(T), throw({?MODULE, T})).
-type parent_name() :: atom(). %% parent = Message or AVP
--type parent_record() :: tuple(). %%
+-type parent_record() :: tuple() | avp_values() | map().
-type avp_name() :: atom().
-type avp_record() :: tuple().
-type avp_values() :: [{avp_name(), term()}].
@@ -46,17 +54,21 @@
-type grouped_avp() :: nonempty_improper_list(#diameter_avp{}, [avp()]).
-type avp() :: non_grouped_avp() | grouped_avp().
+%% The arbitrary arity returned from dictionary avp_arity functions.
+-define(ANY, {0, '*'}).
+
%% ---------------------------------------------------------------------------
%% # encode_avps/3
%% ---------------------------------------------------------------------------
--spec encode_avps(parent_name(), parent_record() | avp_values(), map())
+-spec encode_avps(parent_name(), parent_record(), map())
-> iolist()
| no_return().
encode_avps(Name, Vals, #{module := Mod} = Opts) ->
+ Strict = mget(strict_arities, Opts, encode),
try
- encode(Name, Vals, Opts, Mod)
+ encode(Name, Vals, Opts, Strict, Mod)
catch
throw: {?MODULE, Reason} ->
diameter_lib:log({encode, error},
@@ -64,8 +76,7 @@ encode_avps(Name, Vals, #{module := Mod} = Opts) ->
?LINE,
{Reason, Name, Vals, Mod}),
erlang:error(list_to_tuple(Reason ++ [Name]));
- error: Reason ->
- Stack = erlang:get_stacktrace(),
+ error: Reason: Stack ->
diameter_lib:log({encode, failure},
?MODULE,
?LINE,
@@ -73,128 +84,340 @@ encode_avps(Name, Vals, #{module := Mod} = Opts) ->
erlang:error({encode_failure, Reason, Name, Stack})
end.
-%% encode/4
+%% encode/5
-encode(Name, Vals, #{ordered_encode := false} = Opts, Mod)
+encode(Name, Vals, Opts, Strict, Mod)
when is_list(Vals) ->
- lists:map(fun({F,V}) -> encode(Name, F, V, Opts, Mod) end, Vals);
+ case Opts of
+ #{ordered_encode := false} ->
+ lists:map(fun({F,V}) -> encode(Name, F, V, Opts, Strict, Mod) end,
+ Vals);
+ _ ->
+ Rec = Mod:'#set-'(Vals, newrec(Mod, Name)),
+ encode(Name, Rec, Opts, Strict, Mod)
+ end;
-encode(Name, Vals, Opts, Mod)
- when is_list(Vals) ->
- encode(Name, Mod:'#set-'(Vals, newrec(Mod, Name)), Opts, Mod);
+encode(Name, Map, Opts, Strict, Mod)
+ when is_map(Map) ->
+ [enc(F, A, V, Opts, Strict, Mod) || {F,A} <- Mod:avp_arity(Name),
+ V <- [mget(F, Map, undefined)]];
-encode(Name, Rec, Opts, Mod) ->
- [encode(Name, F, V, Opts, Mod) || {F,V} <- Mod:'#get-'(Rec)].
+encode(Name, Rec, Opts, Strict, Mod) ->
+ [encode(Name, F, V, Opts, Strict, Mod) || {F,V} <- Mod:'#get-'(Rec)].
-%% encode/5
+%% encode/6
+
+encode(_, AvpName, Values, Opts, Strict, Mod)
+ when Strict /= encode ->
+ enc(AvpName, ?ANY, Values, Opts, Strict, Mod);
-encode(Name, AvpName, Values, Opts, Mod) ->
- enc(Name, AvpName, Mod:avp_arity(Name, AvpName), Values, Opts, Mod).
+encode(Name, AvpName, Values, Opts, Strict, Mod) ->
+ Arity = Mod:avp_arity(Name, AvpName),
+ enc(AvpName, Arity, Values, Opts, Strict, Mod).
%% enc/6
-enc(_, AvpName, 1, undefined, _, _) ->
+enc(AvpName, Arity, Values, Opts, Strict, Mod)
+ when Strict /= encode, Arity /= ?ANY ->
+ enc(AvpName, ?ANY, Values, Opts, Strict, Mod);
+
+enc(AvpName, 1, undefined, _, _, _) ->
?THROW([mandatory_avp_missing, AvpName]);
-enc(Name, AvpName, 1, Value, Opts, Mod) ->
- enc(Name, AvpName, [Value], Opts, Mod);
+enc(AvpName, 1, Value, Opts, _, Mod) ->
+ H = avp_header(AvpName, Mod),
+ enc(AvpName, H, Value, Opts, Mod);
+
+enc(_, {0,_}, [], _, _, _) ->
+ [];
+
+enc(_, _, undefined, _, _, _) ->
+ [];
+
+%% Be forgiving when a list of values is expected. If the value itself
+%% is a list then the user has to wrap it to avoid each member from
+%% being interpreted as an individual AVP value.
+enc(AvpName, Arity, V, Opts, Strict, Mod)
+ when not is_list(V) ->
+ enc(AvpName, Arity, [V], Opts, Strict, Mod);
-enc(_, _, {0,_}, [], _, _) ->
+enc(AvpName, {Min, Max}, Values, Opts, Strict, Mod) ->
+ H = avp_header(AvpName, Mod),
+ enc(AvpName, H, Min, 0, Max, Values, Opts, Strict, Mod).
+
+%% enc/9
+
+enc(AvpName, H, Min, N, Max, Vs, Opts, Strict, Mod)
+ when Strict /= encode;
+ Max == '*', Min =< N ->
+ [enc(AvpName, H, V, Opts, Mod) || V <- Vs];
+
+enc(AvpName, _, Min, N, _, [], _, _, _)
+ when N < Min ->
+ ?THROW([repeated_avp_insufficient_arity, AvpName, Min, N]);
+
+enc(_, _, _, _, _, [], _, _, _) ->
[];
-enc(_, AvpName, _, T, _, _)
- when not is_list(T) ->
- ?THROW([repeated_avp_as_non_list, AvpName, T]);
+enc(AvpName, _, _, N, Max, _, _, _, _)
+ when Max =< N ->
+ ?THROW([repeated_avp_excessive_arity, AvpName, Max]);
+
+enc(AvpName, H, Min, N, Max, [V|Vs], Opts, Strict, Mod) ->
+ [enc(AvpName, H, V, Opts, Mod)
+ | enc(AvpName, H, Min, N+1, Max, Vs, Opts, Strict, Mod)].
-enc(_, AvpName, {Min, _}, L, _, _)
- when length(L) < Min ->
- ?THROW([repeated_avp_insufficient_arity, AvpName, Min, L]);
+%% avp_header/2
-enc(_, AvpName, {_, Max}, L, _, _)
- when Max < length(L) ->
- ?THROW([repeated_avp_excessive_arity, AvpName, Max, L]);
+avp_header('AVP', _) ->
+ false;
-enc(Name, AvpName, _, Values, Opts, Mod) ->
- enc(Name, AvpName, Values, Opts, Mod).
+avp_header(AvpName, Mod) ->
+ {_,_,_} = Mod:avp_header(AvpName).
%% enc/5
-enc(Name, 'AVP', Values, Opts, Mod) ->
- [enc_AVP(Name, A, Opts, Mod) || A <- Values];
+enc('AVP', false, Value, Opts, Mod) ->
+ enc_AVP(Value, Opts, Mod);
-enc(_, AvpName, Values, Opts, Mod) ->
- enc(AvpName, Values, Opts, Mod).
+enc(AvpName, Hdr, Value, Opts, Mod) ->
+ enc1(AvpName, Hdr, Value, Opts, Mod).
-%% enc/4
+%% enc1/5
-enc(AvpName, Values, Opts, Mod) ->
- H = Mod:avp_header(AvpName),
- [diameter_codec:pack_data(H, Mod:avp(encode, V, AvpName, Opts))
- || V <- Values].
+enc1(AvpName, {_,_,_} = Hdr, Value, Opts, Mod) ->
+ diameter_codec:pack_data(Hdr, Mod:avp(encode, Value, AvpName, Opts)).
-%% enc_AVP/4
+%% enc1/6
+
+enc1(AvpName, {_,_,_} = Hdr, Value, Opts, Mod, Dict) ->
+ diameter_codec:pack_data(Hdr, avp(encode, Value, AvpName, Opts, Mod, Dict)).
+
+%% enc_AVP/3
%% No value: assume AVP data is already encoded. The normal case will
%% be when this is passed back from #diameter_packet.errors as a
%% consequence of a failed decode. Any AVP can be encoded this way
%% however, which side-steps any arity checks for known AVP's and
%% could potentially encode something unfortunate.
-enc_AVP(_, #diameter_avp{value = undefined} = A, Opts, _) ->
+enc_AVP(#diameter_avp{value = undefined} = A, Opts, _) ->
diameter_codec:pack_avp(A, Opts);
-%% Missing name for value encode.
-enc_AVP(_, #diameter_avp{name = N, value = V}, _, _)
- when N == undefined;
- N == 'AVP' ->
- ?THROW([value_with_nameless_avp, N, V]);
+%% Encode a name/value pair using an alternate dictionary if need be ...
+enc_AVP(#diameter_avp{name = AvpName, value = Value}, Opts, Mod) ->
+ enc_AVP(AvpName, Value, Opts, Mod);
+enc_AVP({AvpName, Value}, Opts, Mod) ->
+ enc_AVP(AvpName, Value, Opts, Mod);
+
+%% ... or with a specified dictionary.
+enc_AVP({Dict, AvpName, Value}, Opts, Mod) ->
+ enc1(AvpName, Dict:avp_header(AvpName), Value, Opts, Mod, Dict).
+
+%% Don't guard against anything being sent as a generic 'AVP', which
+%% allows arity restrictions to be abused.
+
+%% enc_AVP/4
+
+enc_AVP(AvpName, Value, Opts, Mod) ->
+ try Mod:avp_header(AvpName) of
+ H ->
+ enc1(AvpName, H, Value, Opts, Mod)
+ catch
+ error: _ ->
+ Dicts = mget(avp_dictionaries, Opts, []),
+ enc_AVP(Dicts, AvpName, Value, Opts, Mod)
+ end.
-%% Or not. Ensure that 'AVP' is the appropriate field. Note that if we
-%% don't know this AVP at all then the encode will fail.
-enc_AVP(Name, #diameter_avp{name = AvpName, value = Data}, Opts, Mod) ->
- 0 == Mod:avp_arity(Name, AvpName)
- orelse ?THROW([known_avp_as_AVP, Name, AvpName, Data]),
- enc(AvpName, [Data], Opts, Mod);
+%% enc_AVP/5
-%% The backdoor ...
-enc_AVP(_, {AvpName, Value}, Opts, Mod) ->
- enc(AvpName, [Value], Opts, Mod);
+enc_AVP([Dict | Rest], AvpName, Value, Opts, Mod) ->
+ try Dict:avp_header(AvpName) of
+ H ->
+ enc1(AvpName, H, Value, Opts, Mod, Dict)
+ catch
+ error: _ ->
+ enc_AVP(Rest, AvpName, Value, Opts, Mod)
+ end;
-%% ... and the side door.
-enc_AVP(_Name, {_Dict, _AvpName, _Data} = T, Opts, _) ->
- diameter_codec:pack_avp(#diameter_avp{data = T}, Opts).
+enc_AVP([], AvpName, _, _, _) ->
+ ?THROW([no_dictionary, AvpName]).
%% ---------------------------------------------------------------------------
%% # decode_avps/3
%% ---------------------------------------------------------------------------
--spec decode_avps(parent_name(), [#diameter_avp{}], map())
- -> {parent_record(), [avp()], Failed}
+-spec decode_avps(parent_name(), binary(), map())
+ -> {parent_record() | parent_name(), [avp()], Failed}
when Failed :: [{5000..5999, #diameter_avp{}}].
-decode_avps(Name, Recs, #{module := Mod} = Opts) ->
- {Avps, {Rec, Failed}}
- = mapfoldl(fun(T,A) -> decode(Name, Opts, Mod, T, A) end,
- {newrec(Mod, Name), []},
- Recs),
- {Rec, Avps, Failed ++ missing(Rec, Name, Failed, Opts, Mod)}.
-%% Append 5005 errors so that errors are reported in the order
+decode_avps(Name, Bin, #{module := Mod, decode_format := Fmt} = Opts) ->
+ Strict = mget(strict_arities, Opts, decode),
+ [AM, Avps, Failed | Rec]
+ = decode(Bin, Name, Mod, Fmt, Strict, Opts, 0, #{}),
+ %% AM counts the number of top-level AVPs, which missing/5 then
+ %% uses when appending 5005 errors.
+ {reformat(Name, Rec, Strict, Mod, Fmt),
+ Avps,
+ Failed ++ missing(Name, Strict, Mod, Opts, AM)}.
+
+%% Append arity errors so that errors are reported in the order
%% encountered. Failed-AVP should typically contain the first
-%% encountered error accordg to the RFC.
+%% error encountered.
+
+%% decode/8
+
+decode(<<Code:32, V:1, M:1, P:1, _:5, Len:24, I:V/unit:32, Rest/binary>>,
+ Name,
+ Mod,
+ Fmt,
+ Strict,
+ Opts,
+ Idx,
+ AM) ->
+ decode(Rest,
+ Code,
+ if 1 == V -> I; true -> undefined end,
+ Len - 8 - 4*V, %% possibly negative, causing case match to fail
+ (4 - (Len rem 4)) rem 4,
+ 1 == M,
+ 1 == P,
+ Name,
+ Mod,
+ Fmt,
+ Strict,
+ Opts,
+ Idx,
+ AM);
+
+decode(<<>>, Name, Mod, Fmt, Strict, _, _, AM) ->
+ [AM, [], [] | newrec(Fmt, Mod, Name, Strict)];
+
+decode(Bin, Name, Mod, Fmt, Strict, _, Idx, AM) ->
+ Avp = #diameter_avp{data = Bin, index = Idx},
+ [AM, [Avp], [{5014, Avp}] | newrec(Fmt, Mod, Name, Strict)].
+
+%% decode/14
+
+decode(Bin, Code, Vid, DataLen, Pad, M, P, Name, Mod, Fmt, Strict, Opts0,
+ Idx, AM0) ->
+ case Bin of
+ <<Data:DataLen/binary, _:Pad/binary, T/binary>> ->
+ {NameT, Field, Arity, {I, AM}}
+ = incr(Name, Code, Vid, M, Mod, Strict, Opts0, AM0),
+
+ Opts = setopts(NameT, Name, M, Opts0),
+ %% Not AvpName or else a failed Failed-AVP
+ %% decode is packed into 'AVP'.
+
+ Avp = #diameter_avp{code = Code,
+ vendor_id = Vid,
+ is_mandatory = M,
+ need_encryption = P,
+ data = Data,
+ name = name(NameT),
+ type = type(NameT),
+ index = Idx},
+
+ Dec = dec(Data, Name, NameT, Mod, Fmt, Opts, Avp),
+ Acc = decode(T, Name, Mod, Fmt, Strict, Opts0, Idx+1, AM),%% recurse
+ acc(Acc, Dec, I, Field, Arity, Strict, Mod);
+ _ ->
+ {NameT, _Field, _Arity, {_, AM}}
+ = incr(Name, Code, Vid, M, Mod, Strict, Opts0, AM0),
+
+ Avp = #diameter_avp{code = Code,
+ vendor_id = Vid,
+ is_mandatory = M,
+ need_encryption = P,
+ data = Bin,
+ name = name(NameT),
+ type = type(NameT),
+ index = Idx},
+
+ [AM, [Avp], [{5014, Avp}] | newrec(Fmt, Mod, Name, Strict)]
+ end.
+
+%% incr/8
-%% mapfoldl/3
+incr(Name, Code, Vid, M, Mod, Strict, Opts, AM0) ->
+ NameT = Mod:avp_name(Code, Vid), %% {AvpName, Type} | 'AVP'
+ Field = field(NameT), %% AvpName | 'AVP'
+ Arity = avp_arity(Name, Field, Mod, Opts, M),
+ if 0 == Arity, 'AVP' /= Field ->
+ A = pack_arity(Name, Field, Opts, Mod, M),
+ {NameT, 'AVP', A, incr('AVP', A, Strict, AM0)};
+ true ->
+ {NameT, Field, Arity, incr(Field, Arity, Strict, AM0)}
+ end.
+
+%% Data is a truncated header if command_code = undefined, otherwise
+%% payload bytes. The former is padded to the length of a header if
+%% the AVP reaches an outgoing encode.
%%
-%% Like lists:mapfoldl/3, but don't reverse the list.
+%% RFC 6733 says that an AVP returned with 5014 can contain a minimal
+%% payload for the AVP's type, but don't always know the type.
-mapfoldl(F, Acc, List) ->
- mapfoldl(F, Acc, List, []).
+setopts('AVP', _, _, Opts) ->
+ Opts;
-mapfoldl(F, Acc0, [T|Rest], List) ->
- {B, Acc} = F(T, Acc0),
- mapfoldl(F, Acc, Rest, [B|List]);
-mapfoldl(_, Acc, [], List) ->
- {List, Acc}.
+setopts({_, Type}, Name, M, Opts) ->
+ set_failed(Name, set_strict(Type, M, Opts)).
-%% 3588:
+%% incr/4
+
+incr(_, A, SA, AM)
+ when A == ?ANY;
+ A == 0;
+ SA /= decode ->
+ {undefined, AM};
+
+incr(AvpName, _, _, AM) ->
+ case AM of
+ #{AvpName := N} ->
+ {N, AM#{AvpName => N+1}};
+ _ ->
+ {0, AM#{AvpName => 1}}
+ end.
+
+%% mget/3
+%%
+%% Measurably faster than maps:get/3.
+
+mget(Key, Map, Def) ->
+ case Map of
+ #{Key := V} ->
+ V;
+ _ ->
+ Def
+ end.
+
+%% name/1
+
+name({Name, _}) ->
+ Name;
+name(_) ->
+ undefined.
+
+%% type/1
+
+type({_, Type}) ->
+ Type;
+type(_) ->
+ undefined.
+
+%% missing/5
+
+missing(Name, decode, Mod, Opts, AM) ->
+ [{5005, empty_avp(N, Opts, Mod)} || {N,A} <- Mod:avp_arity(Name),
+ N /= 'AVP',
+ Mn <- [min_arity(A)],
+ 0 < Mn,
+ mget(N, AM, 0) < Mn];
+
+missing(_, _, _, _, _) ->
+ [].
+
+%% 3588/6733:
%%
%% DIAMETER_MISSING_AVP 5005
%% The request did not contain an AVP that is required by the Command
@@ -204,57 +427,20 @@ mapfoldl(_, Acc, [], List) ->
%% Vendor-Id if applicable. The value field of the missing AVP
%% should be of correct minimum length and contain zeros.
-missing(Rec, Name, Failed, Opts, Mod) ->
- Avps = lists:foldl(fun({_, #diameter_avp{code = C, vendor_id = V}}, A) ->
- maps:put({C,V}, true, A)
- end,
- maps:new(),
- Failed),
- missing(Mod:avp_arity(Name), tl(tuple_to_list(Rec)), Avps, Opts, Mod, []).
-
-missing([{Name, Arity} | As], [Value | Vs], Avps, Opts, Mod, Acc) ->
- missing(As,
- Vs,
- Avps,
- Opts,
- Mod,
- case
- [H || missing_arity(Arity, Value),
- {C,_,V} = H <- [Mod:avp_header(Name)],
- not maps:is_key({C,V}, Avps)]
- of
- [H] ->
- [{5005, empty_avp(Name, H, Opts, Mod)} | Acc];
- [] ->
- Acc
- end);
-
-missing([], [], _, _, _, Acc) ->
- Acc.
-
-%% Maximum arities have already been checked in building the record.
-
-missing_arity(1, V) ->
- V == undefined;
-missing_arity({0, _}, _) ->
- false;
-missing_arity({1, _}, L) ->
- [] == L;
-missing_arity({Min, _}, L) ->
- not has_prefix(Min, L).
-
-%% Compare a non-negative integer and the length of a list without
-%% computing the length.
-has_prefix(0, _) ->
- true;
-has_prefix(_, []) ->
- false;
-has_prefix(N, [_|L]) ->
- has_prefix(N-1, L).
+%% min_arity/1
+
+min_arity(1) ->
+ 1;
+min_arity({Mn,_}) ->
+ Mn.
-%% empty_avp/4
+%% empty_avp/3
-empty_avp(Name, {Code, Flags, VId}, Opts, Mod) ->
+empty_avp('AVP', _, _) ->
+ #diameter_avp{data = <<0:64>>};
+
+empty_avp(Name, Opts, Mod) ->
+ {Code, Flags, VId} = Mod:avp_header(Name),
{Name, Type} = Mod:avp_name(Code, VId),
#diameter_avp{name = Name,
code = Code,
@@ -273,21 +459,19 @@ empty_avp(Name, {Code, Flags, VId}, Opts, Mod) ->
%% specific errors that can be described by this AVP are described in
%% the following section.
-%% decode/5
+%% field/1
-decode(Name,
- Opts,
- Mod,
- #diameter_avp{code = Code, vendor_id = Vid}
- = Avp,
- Acc) ->
- decode(Name, Opts, Mod, Mod:avp_name(Code, Vid), Avp, Acc).
+field({AvpName, _}) ->
+ AvpName;
+field(_) ->
+ 'AVP'.
-%% decode/6
+%% dec/7
-%% AVP not in dictionary.
-decode(Name, Opts, Mod, 'AVP', Avp, Acc) ->
- decode_AVP(Name, Avp, Opts, Mod, Acc);
+%% AVP not in dictionary: try an alternate.
+
+dec(Data, Name, 'AVP', Mod, Fmt, Opts, Avp) ->
+ dec_AVP(dicts(Mod, Opts), Data, Name, Mod, Fmt, Opts, Avp);
%% 6733, 4.4:
%%
@@ -336,130 +520,151 @@ decode(Name, Opts, Mod, 'AVP', Avp, Acc) ->
%% defined the RFC's "unrecognized", which is slightly stronger than
%% "not defined".)
-decode(Name, Opts0, Mod, {AvpName, Type}, Avp, Acc) ->
- #diameter_avp{data = Data, is_mandatory = M}
- = Avp,
+dec(Data, Name, {AvpName, Type}, Mod, Fmt, Opts, Avp) ->
+ #{app_dictionary := AppMod, failed_avp := Failed}
+ = Opts,
- %% Whether or not to ignore an M-bit on an encapsulated AVP, or on
- %% all AVPs with the service_opt() strict_mbit.
- Opts1 = set_strict(Type, M, Opts0),
+ %% Reset the dictionary for best-effort decode of Failed-AVP.
+ Dict = if Failed -> AppMod;
+ true -> Mod
+ end,
- %% Whether or not we're decoding within Failed-AVP and should
- %% ignore decode errors.
- #{dictionary := AppMod, failed_avp := Failed}
- = Opts
- = set_failed(Name, Opts1), %% Not AvpName or else a failed Failed-AVP
- %% decode is packed into 'AVP'.
+ dec(Data, Name, AvpName, Type, Mod, Dict, Fmt, Failed, Opts, Avp).
- %% Reset the dictionary for best-effort decode of Failed-AVP.
- DecMod = if Failed ->
- AppMod;
- true ->
- Mod
- end,
-
- %% On decode, a Grouped AVP is represented as a #diameter_avp{}
- %% list with AVP as head and component AVPs as tail. On encode,
- %% data can be a list of component AVPs.
-
- try avp_decode(Data, AvpName, Opts, DecMod, Mod) of
- {Rec, As} when Type == 'Grouped' ->
- A = Avp#diameter_avp{name = AvpName,
- value = Rec,
- type = Type},
- {[A|As], pack_avp(Name, A, Opts, Mod, Acc)};
+%% dicts/2
- V when Type /= 'Grouped' ->
- A = Avp#diameter_avp{name = AvpName,
- value = V,
- type = Type},
- {A, pack_avp(Name, A, Opts, Mod, Acc)}
+dicts(Mod, #{app_dictionary := Mod, avp_dictionaries := Dicts}) ->
+ Dicts;
+
+dicts(_, #{app_dictionary := Dict, avp_dictionaries := Dicts}) ->
+ [Dict | Dicts];
+
+dicts(Mod, #{app_dictionary := Mod}) ->
+ [];
+
+dicts(_, #{app_dictionary := Dict}) ->
+ [Dict].
+
+%% dec/10
+
+dec(Data, Name, AvpName, Type, Mod, Dict, Fmt, Failed, Opts, Avp) ->
+ try avp(decode, Data, AvpName, Opts, Mod, Dict) of
+ V ->
+ set(Type, Fmt, Avp, V)
catch
- throw: {?MODULE, {grouped, Error, ComponentAvps}} ->
- decode_error(Name,
- Error,
- ComponentAvps,
- Opts,
- Mod,
- Avp#diameter_avp{name = AvpName,
- data = trim(Avp#diameter_avp.data),
- type = Type},
- Acc);
-
- error: Reason ->
- decode_error(Name,
- Reason,
- Opts,
- Mod,
- Avp#diameter_avp{name = AvpName,
- data = trim(Avp#diameter_avp.data),
- type = Type},
- Acc)
+ throw: {?MODULE, T} ->
+ decode_error(Failed, Fmt, T, Avp);
+ error: Reason: Stack ->
+ decode_error(Failed, Reason, Stack, Name, Mod, Opts, Avp)
end.
-%% avp_decode/5
+%% dec_AVP/7
-avp_decode(Data, AvpName, Opts, Mod, Mod) ->
- Mod:avp(decode, Data, AvpName, Opts);
+dec_AVP([], _, _, _, _, _, Avp) ->
+ Avp;
-avp_decode(Data, AvpName, Opts, Mod, _) ->
- Mod:avp(decode, Data, AvpName, Opts, Mod).
+dec_AVP(Dicts, Data, Name, Mod, Fmt, Opts, #diameter_avp{code = Code,
+ vendor_id = Vid}
+ = Avp) ->
+ dec_AVP(Dicts, Data, Name, Mod, Fmt, Opts, Code, Vid, Avp).
-%% trim/1
+%% dec_AVP/9
%%
-%% Remove any extra bit that was added in diameter_codec to induce a
-%% 5014 error.
+%% Try to decode an AVP in the first alternate dictionary that defines
+%% it.
-trim(#diameter_avp{data = Data} = Avp) ->
- Avp#diameter_avp{data = trim(Data)};
+dec_AVP([Dict | Rest], Data, Name, Mod, Fmt, Opts0, Code, Vid, Avp) ->
+ case Dict:avp_name(Code, Vid) of
+ {AvpName, Type} = NameT ->
+ A = Avp#diameter_avp{name = AvpName,
+ type = Type},
+ #{failed_avp := Failed}
+ = Opts
+ = setopts(NameT, Name, Avp#diameter_avp.is_mandatory, Opts0),
+ dec(Data, Name, AvpName, Type, Mod, Dict, Fmt, Failed, Opts, A);
+ _ ->
+ dec_AVP(Rest, Data, Name, Mod, Fmt, Opts0, Code, Vid, Avp)
+ end;
+
+dec_AVP([], _, _, _, _, _, _, _, Avp) ->
+ Avp.
-trim({5014, Bin}) ->
- Bin;
+%% set/4
+%%
+%% A Grouped AVP is represented as a #diameter_avp{} list with AVP
+%% as head and component AVPs as tail.
-trim(Avps)
- when is_list(Avps) ->
- lists:map(fun trim/1, Avps);
+set('Grouped', Fmt, Avp, V) ->
+ {Rec, As} = V,
+ [set(Fmt, Avp, Rec) | As];
-trim(Avp) ->
- Avp.
+set(_, _, Avp, V) ->
+ Avp#diameter_avp{value = V}.
-%% decode_error/7
+%% decode_error/4
+%%
+%% Error when decoding a grouped AVP.
-decode_error(Name, [_ | Rec], _, #{failed_avp := true} = Opts, Mod, Avp, Acc) ->
- decode_AVP(Name, Avp#diameter_avp{value = Rec}, Opts, Mod, Acc);
+%% Ignoring errors in Failed-AVP.
+decode_error(true, Fmt, {Rec, ComponentAvps, _Errors}, Avp) ->
+ [set(Fmt, Avp, Rec) | ComponentAvps];
-decode_error(Name, _, _, #{failed_avp := true} = Opts, Mod, Avp, Acc) ->
- decode_AVP(Name, Avp, Opts, Mod, Acc);
+%% Or not. A faulty component is encoded by itself in Failed-AVP, as
+%% suggested by 7.5 of RFC 6733 (quoted below), so that errors are
+%% reported unambigiously.
+decode_error(false, _, {_, ComponentAvps, [{RC,A} | _]}, Avp) ->
+ {RC, [Avp | ComponentAvps], Avp#diameter_avp{data = [A]}}.
-decode_error(_, [Error | _], ComponentAvps, _, _, Avp, Acc) ->
- decode_error(Error, Avp, Acc, ComponentAvps);
+%% set/3
-decode_error(_, Error, ComponentAvps, _, _, Avp, Acc) ->
- decode_error(Error, Avp, Acc, ComponentAvps).
+set(none, Avp, _Name) ->
+ Avp;
+set(_, Avp, Rec) ->
+ Avp#diameter_avp{value = Rec}.
-%% decode_error/5
+%% decode_error/7
+%%
+%% Error when decoding a non-grouped AVP.
-decode_error(Name, _Reason, #{failed_avp := true} = Opts, Mod, Avp, Acc) ->
- decode_AVP(Name, Avp, Opts, Mod, Acc);
+decode_error(true, _, _, _, _, _, Avp) ->
+ Avp;
-decode_error(Name, Reason, Opts, Mod, Avp, {Rec, Failed}) ->
- Stack = diameter_lib:get_stacktrace(),
+decode_error(false, Reason, Stack, Name, Mod, Opts, Avp) ->
+ Z = diameter_lib:stacktrace(Stack),
diameter_lib:log(decode_error,
?MODULE,
?LINE,
- {Reason, Name, Avp#diameter_avp.name, Mod, Stack}),
- {Avp, {Rec, [rc(Reason, Avp, Opts, Mod) | Failed]}}.
+ {Reason, Name, Avp#diameter_avp.name, Mod, Z}),
+ case Reason of
+ {'DIAMETER', 5014 = RC, _} ->
+ %% Length error communicated from diameter_types or a
+ %% @custom_types/@codecs module.
+ AvpName = Avp#diameter_avp.name,
+ {RC, Avp#diameter_avp{data = Mod:empty_value(AvpName, Opts)}};
+ _ ->
+ {5004, Avp}
+ end.
-%% decode_error/4
+%% 3588/6733:
+%%
+%% DIAMETER_INVALID_AVP_VALUE 5004
+%% The request contained an AVP with an invalid value in its data
+%% portion. A Diameter message indicating this error MUST include
+%% the offending AVPs within a Failed-AVP AVP.
-decode_error({RC, ErrorData}, Avp, {Rec, Failed}, ComponentAvps) ->
- E = Avp#diameter_avp{data = [ErrorData]},
- {[Avp | trim(ComponentAvps)], {Rec, [{RC, E} | Failed]}}.
+%% avp/6
-%% set_strict/3
+avp(T, Data, AvpName, Opts, Mod, Mod) ->
+ Mod:avp(T, Data, AvpName, Opts);
+
+avp(T, Data, AvpName, Opts, _, Mod) ->
+ Mod:avp(T, Data, AvpName, Opts#{module := Mod}).
+%% set_strict/3
+%%
%% Set false as soon as we see a Grouped AVP that doesn't set the
%% M-bit, to ignore the M-bit on an encapsulated AVP.
+
set_strict('Grouped', false = M, #{strict_mbit := true} = Opts) ->
Opts#{strict_mbit := M};
set_strict(_, _, Opts) ->
@@ -476,102 +681,84 @@ set_failed('Failed-AVP', #{failed_avp := false} = Opts) ->
set_failed(_, Opts) ->
Opts.
-%% decode_AVP/5
-%%
-%% Don't know this AVP: see if it can be packed in an 'AVP' field
-%% undecoded. Note that the type field is 'undefined' in this case.
-
-decode_AVP(Name, Avp, Opts, Mod, Acc) ->
- {trim(Avp), pack_AVP(Name, Avp, Opts, Mod, Acc)}.
-
-%% rc/2
-
-%% diameter_types will raise an error of this form to communicate
-%% DIAMETER_INVALID_AVP_LENGTH (5014). A module specified to a
-%% @custom_types tag in a dictionary file can also raise an error of
-%% this form.
-rc({'DIAMETER', 5014 = RC, _}, #diameter_avp{name = AvpName} = Avp, Opts, Mod) ->
- {RC, Avp#diameter_avp{data = Mod:empty_value(AvpName, Opts)}};
-
-%% 3588:
-%%
-%% DIAMETER_INVALID_AVP_VALUE 5004
-%% The request contained an AVP with an invalid value in its data
-%% portion. A Diameter message indicating this error MUST include
-%% the offending AVPs within a Failed-AVP AVP.
-rc(_, Avp, _, _) ->
- {5004, Avp}.
-
-%% pack_avp/5
-
-pack_avp(Name, #diameter_avp{name = AvpName} = Avp, Opts, Mod, Acc) ->
- pack_avp(Name, Mod:avp_arity(Name, AvpName), Avp, Opts, Mod, Acc).
-
-%% pack_avp/6
-
-pack_avp(Name, 0, Avp, Opts, Mod, Acc) ->
- pack_AVP(Name, Avp, Opts, Mod, Acc);
-
-pack_avp(_, Arity, #diameter_avp{name = AvpName} = Avp, _Opts, Mod, Acc) ->
- pack(Arity, AvpName, Avp, Mod, Acc).
-
-%% pack_AVP/5
+%% acc/7
+
+acc([AM | Acc], As, I, Field, Arity, Strict, Mod) ->
+ [AM | acc1(Acc, As, I, Field, Arity, Strict, Mod)].
+
+%% acc1/7
+
+%% Faulty AVP, not grouped.
+acc1(Acc, {_RC, Avp} = E, _, _, _, _, _) ->
+ [Avps, Failed | Rec] = Acc,
+ [[Avp | Avps], [E | Failed] | Rec];
+
+%% Faulty component in grouped AVP.
+acc1(Acc, {RC, As, Avp}, _, _, _, _, _) ->
+ [Avps, Failed | Rec] = Acc,
+ [[As | Avps], [{RC, Avp} | Failed] | Rec];
+
+%% Grouped AVP ...
+acc1([Avps | Acc], [Avp|_] = As, I, Field, Arity, Strict, Mod) ->
+ [[As|Avps] | acc2(Acc, Avp, I, Field, Arity, Strict, Mod)];
+
+%% ... or not.
+acc1([Avps | Acc], Avp, I, Field, Arity, Strict, Mod) ->
+ [[Avp|Avps] | acc2(Acc, Avp, I, Field, Arity, Strict, Mod)].
+
+%% The component list of a Grouped AVP is discarded when packing into
+%% the record (or equivalent): the values in an 'AVP' field are
+%% diameter_avp records, not a list of records in the Grouped case,
+%% and the decode into the value field is best-effort. The reason is
+%% history more than logic: it would probably have made more sense to
+%% retain the same structure as in diameter_packet.avps, but an 'AVP'
+%% list has always been flat.
+
+%% acc2/7
+
+%% No errors, but nowhere to pack.
+acc2(Acc, Avp, _, 'AVP', 0, _, _) ->
+ [Failed | Rec] = Acc,
+ [[{rc(Avp), Avp} | Failed] | Rec];
+
+%% Relaxed arities.
+acc2(Acc, Avp, _, Field, Arity, Strict, Mod)
+ when Strict /= decode ->
+ pack(Arity, Field, Avp, Mod, Acc);
+
+%% No maximum arity.
+acc2(Acc, Avp, _, Field, {_,'*'} = Arity, _, Mod) ->
+ pack(Arity, Field, Avp, Mod, Acc);
+
+%% Or check.
+acc2(Acc, Avp, I, Field, Arity, _, Mod) ->
+ Mx = max_arity(Arity),
+ if Mx =< I ->
+ [Failed | Rec] = Acc,
+ [[{5009, Avp} | Failed] | Rec];
+ true ->
+ pack(Arity, Field, Avp, Mod, Acc)
+ end.
-%% Length failure was induced because of a header/payload length
-%% mismatch. The AVP Length is reset to match the received data if
-%% this AVP is encoded in an answer message, since the length is
-%% computed.
-%%
-%% Data is a truncated header if command_code = undefined, otherwise
-%% payload bytes. The former is padded to the length of a header if
-%% the AVP reaches an outgoing encode in diameter_codec.
+%% 3588/6733:
%%
-%% RFC 6733 says that an AVP returned with 5014 can contain a minimal
-%% payload for the AVP's type, but in this case we don't know the
-%% type.
-
-pack_AVP(_, #diameter_avp{data = {5014 = RC, Data}} = Avp, _, _, Acc) ->
- {Rec, Failed} = Acc,
- {Rec, [{RC, Avp#diameter_avp{data = Data}} | Failed]};
-
-pack_AVP(Name, Avp, Opts, Mod, Acc) ->
- pack_arity(Name, pack_arity(Name, Opts, Mod, Avp), Avp, Mod, Acc).
-
-%% pack_arity/5
-
-pack_arity(_, 0, #diameter_avp{is_mandatory = M} = Avp, _, Acc) ->
- {Rec, Failed} = Acc,
- {Rec, [{if M -> 5001; true -> 5008 end, Avp} | Failed]};
-
-pack_arity(_, Arity, Avp, Mod, Acc) ->
- pack(Arity, 'AVP', Avp, Mod, Acc).
+%% DIAMETER_AVP_OCCURS_TOO_MANY_TIMES 5009
+%% A message was received that included an AVP that appeared more
+%% often than permitted in the message definition. The Failed-AVP
+%% AVP MUST be included and contain a copy of the first instance of
+%% the offending AVP that exceeded the maximum number of occurrences
-%% Give Failed-AVP special treatment since (1) it'll contain any
-%% unrecognized mandatory AVP's and (2) the RFC 3588 grammar failed to
-%% allow for Failed-AVP in an answer-message.
+%% max_arity/1
-pack_arity(Name,
- #{strict_mbit := Strict,
- failed_avp := Failed},
- Mod,
- #diameter_avp{is_mandatory = M,
- name = AvpName}) ->
+max_arity(1) ->
+ 1;
+max_arity({_,Mx}) ->
+ Mx.
- %% Not testing just Name /= 'Failed-AVP' means we're changing the
- %% packing of AVPs nested within Failed-AVP, but the point of
- %% ignoring errors within Failed-AVP is to decode as much as
- %% possible, and failing because a mandatory AVP couldn't be
- %% packed into a dedicated field defeats that point.
+%% rc/1
- if Failed == true;
- Name == 'Failed-AVP';
- Name == 'answer-message', AvpName == 'Failed-AVP';
- not M;
- not Strict ->
- Mod:avp_arity(Name, 'AVP');
- true ->
- 0
- end.
+rc(#diameter_avp{is_mandatory = M}) ->
+ if M -> 5001; true -> 5008 end.
%% 3588:
%%
@@ -586,75 +773,99 @@ pack_arity(Name,
%% Failed-AVP AVP MUST be included and contain a copy of the
%% offending AVP.
+%% pack_arity/5
+
+%% Give Failed-AVP special treatment since (1) it'll contain any
+%% unrecognized mandatory AVP's and (2) the RFC 3588 grammar failed to
+%% allow for Failed-AVP in an answer-message.
+
+pack_arity(Name, AvpName, _, Mod, M)
+ when Name == 'Failed-AVP';
+ Name == 'answer-message', AvpName == 'Failed-AVP';
+ not M ->
+ Mod:avp_arity(Name, 'AVP');
+%% Not testing just Name /= 'Failed-AVP' means we're changing the
+%% packing of AVPs nested within Failed-AVP, but the point of
+%% ignoring errors within Failed-AVP is to decode as much as
+%% possible, and failing because a mandatory AVP couldn't be
+%% packed into a dedicated field defeats that point.
+
+pack_arity(Name, _, #{strict_mbit := Strict, failed_avp := Failed}, Mod, _)
+ when not Strict;
+ Failed ->
+ Mod:avp_arity(Name, 'AVP');
+
+pack_arity(_, _, _, _, _) ->
+ 0.
+
+%% avp_arity/5
+
+avp_arity(Name, 'AVP' = AvpName, Mod, Opts, M) ->
+ pack_arity(Name, AvpName, Opts, Mod, M);
+
+avp_arity(Name, AvpName, Mod, _, _) ->
+ Mod:avp_arity(Name, AvpName).
+
%% pack/5
-pack(Arity, FieldName, Avp, Mod, {Rec, _} = Acc) ->
- pack(Mod:'#get-'(FieldName, Rec), Arity, FieldName, Avp, Mod, Acc).
+pack(Arity, F, Avp, Mod, [Failed | Rec]) ->
+ [Failed | set(Arity, F, value(F, Avp), Mod, Rec)].
-%% pack/6
+%% set/5
-pack(undefined, 1, 'AVP' = F, Avp, Mod, {Rec, Failed}) -> %% unlikely
- {Mod:'#set-'({F, Avp}, Rec), Failed};
+set(_, _, _, _, Name)
+ when is_atom(Name) ->
+ Name;
-pack(undefined, 1, F, #diameter_avp{value = V}, Mod, {Rec, Failed}) ->
- {Mod:'#set-'({F, V}, Rec), Failed};
+set(1, F, Value, _, Map)
+ when is_map(Map) ->
+ Map#{F => Value};
-%% 3588:
-%%
-%% DIAMETER_AVP_OCCURS_TOO_MANY_TIMES 5009
-%% A message was received that included an AVP that appeared more
-%% often than permitted in the message definition. The Failed-AVP
-%% AVP MUST be included and contain a copy of the first instance of
-%% the offending AVP that exceeded the maximum number of occurrences
-%%
+set(_, F, V, _, Map)
+ when is_map(Map) ->
+ maps:update_with(F, fun(Vs) -> [V|Vs] end, [V], Map);
-pack(_, 1, _, Avp, _, {Rec, Failed}) ->
- {Rec, [{5009, Avp} | Failed]};
-
-pack(L, {_, Max}, F, Avp, Mod, {Rec, Failed}) ->
- case '*' /= Max andalso has_prefix(Max+1, L) of
- true ->
- {Rec, [{5009, Avp} | Failed]};
- false when F == 'AVP' ->
- {Mod:'#set-'({F, [Avp | L]}, Rec), Failed};
- false ->
- {Mod:'#set-'({F, [Avp#diameter_avp.value | L]}, Rec), Failed}
- end.
+set(1, F, Value, Mod, Rec) ->
+ Mod:'#set-'({F, Value}, Rec);
+
+set(_, F, V, Mod, Rec) ->
+ Vs = Mod:'#get-'(F, Rec),
+ Mod:'#set-'({F, [V|Vs]}, Rec).
+
+%% value/2
+
+value('AVP', Avp) ->
+ Avp;
+
+value(_, #diameter_avp{value = V}) ->
+ V.
%% ---------------------------------------------------------------------------
%% # grouped_avp/3
%% ---------------------------------------------------------------------------
--spec grouped_avp(decode, avp_name(), binary() | {5014, binary()}, term())
+%% Note that Grouped is the only AVP type that doesn't just return a
+%% decoded value, also returning the list of component diameter_avp
+%% records.
+
+-spec grouped_avp(decode, avp_name(), binary(), term())
-> {avp_record(), [avp()]};
(encode, avp_name(), avp_record() | avp_values(), term())
-> iolist()
| no_return().
-%% Length error induced by diameter_codec:collect_avps/1: the AVP
-%% length in the header was too short (insufficient for the extracted
-%% header) or too long (past the end of the message). An empty payload
-%% is sufficient according to the RFC text for 5014.
-grouped_avp(decode, _Name, {5014 = RC, _Bin}, _) ->
- ?THROW({grouped, {RC, []}, []});
-
-grouped_avp(decode, Name, Data, Opts) ->
- grouped_decode(Name, diameter_codec:collect_avps(Data), Opts);
+%% An error in decoding a component AVP throws the first faulty
+%% component, which a catch wraps in the Grouped AVP in question. A
+%% partially decoded record is only used when ignoring errors in
+%% Failed-AVP.
+grouped_avp(decode, Name, Bin, Opts) ->
+ {Rec, Avps, Es} = T = decode_avps(Name, Bin, Opts),
+ [] == Es orelse ?THROW(T),
+ {Rec, Avps};
grouped_avp(encode, Name, Data, Opts) ->
encode_avps(Name, Data, Opts).
-%% grouped_decode/2
-%%
-%% Note that Grouped is the only AVP type that doesn't just return a
-%% decoded value, also returning the list of component diameter_avp
-%% records.
-
-%% Length error in trailing component AVP.
-grouped_decode(_Name, {Error, Acc}, _) ->
- {5014, Avp} = Error,
- ?THROW({grouped, Error, [Avp | Acc]});
-
%% 7.5. Failed-AVP AVP
%% In the case where the offending AVP is embedded within a Grouped AVP,
@@ -665,15 +876,6 @@ grouped_decode(_Name, {Error, Acc}, _) ->
%% to the single offending AVP. This enables the recipient to detect
%% the location of the offending AVP when embedded in a group.
-%% An error in decoding a component AVP throws the first faulty
-%% component, which the catch in d/3 wraps in the Grouped AVP in
-%% question. A partially decoded record is only used when ignoring
-%% errors in Failed-AVP.
-grouped_decode(Name, ComponentAvps, Opts) ->
- {Rec, Avps, Es} = decode_avps(Name, ComponentAvps, Opts),
- [] == Es orelse ?THROW({grouped, [{_,_} = hd(Es) | Rec], Avps}),
- {Rec, Avps}.
-
%% ---------------------------------------------------------------------------
%% # empty_group/2
%% ---------------------------------------------------------------------------
@@ -705,5 +907,45 @@ empty(Name, #{module := Mod} = Opts) ->
%% ------------------------------------------------------------------------------
+%% newrec/4
+
+newrec(none, _, Name, _) ->
+ Name;
+
+newrec(record, Mod, Name, T)
+ when T /= decode ->
+ RecName = Mod:name2rec(Name),
+ Sz = Mod:'#info-'(RecName, size),
+ erlang:make_tuple(Sz, [], [{1, RecName}]);
+
+newrec(record, Mod, Name, _) ->
+ newrec(Mod, Name);
+
+newrec(_, _, _, _) ->
+ #{}.
+
+%% newrec/2
+
newrec(Mod, Name) ->
Mod:'#new-'(Mod:name2rec(Name)).
+
+%% reformat/5
+
+reformat(Name, Map, _Strict, Mod, list) ->
+ [{F,V} || {F,_} <- Mod:avp_arity(Name), #{F := V} <- [Map]];
+
+reformat(Name, Map, Strict, Mod, record_from_map) ->
+ RecName = Mod:name2rec(Name),
+ list_to_tuple([RecName | [mget(F, Map, def(A, Strict))
+ || {F,A} <- Mod:avp_arity(Name)]]);
+
+reformat(_, Rec, _, _, _) ->
+ Rec.
+
+%% def/2
+
+def(1, decode) ->
+ undefined;
+
+def(_, _) ->
+ [].
diff --git a/lib/diameter/src/base/diameter_internal.hrl b/lib/diameter/src/base/diameter_internal.hrl
index a0f4a8567d..4a678643c2 100644
--- a/lib/diameter/src/base/diameter_internal.hrl
+++ b/lib/diameter/src/base/diameter_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,9 +35,6 @@
%% A corresponding error when failure is the best option.
-define(ERROR(T), erlang:error({T, ?MODULE, ?LINE})).
-%% Failure reports always get a stack trace.
--define(STACK, erlang:get_stacktrace()).
-
%% Warning report for unexpected messages in various processes.
-define(UNEXPECTED(F,A),
diameter_lib:warning_report(unexpected, {?MODULE, F, A})).
diff --git a/lib/diameter/src/base/diameter_lib.erl b/lib/diameter/src/base/diameter_lib.erl
index 8792e97621..edd9d5a4ce 100644
--- a/lib/diameter/src/base/diameter_lib.erl
+++ b/lib/diameter/src/base/diameter_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@
time/1,
eval/1,
eval_name/1,
- get_stacktrace/0,
+ stacktrace/1,
ipaddr/1,
spawn_opts/2,
wait/1,
@@ -42,16 +42,13 @@
log/4]).
%% ---------------------------------------------------------------------------
-%% # get_stacktrace/0
+%% # stacktrace/1
%% ---------------------------------------------------------------------------
%% Return a stacktrace with a leading, potentially large, argument
-%% list replaced by an arity. Trace on stacktrace/0 to see the
+%% list replaced by an arity. Trace on stacktrace/1 to see the
%% original.
-get_stacktrace() ->
- stacktrace(erlang:get_stacktrace()).
-
stacktrace([{M,F,A,L} | T]) when is_list(A) ->
[{M, F, length(A), L} | T];
stacktrace(L) ->
@@ -268,8 +265,8 @@ ipaddr(Addr) ->
try
ip(Addr)
catch
- error: _ ->
- erlang:error({invalid_address, erlang:get_stacktrace()})
+ error: _: Stack ->
+ erlang:error({invalid_address, Stack})
end.
%% Already a tuple: ensure non-negative integers of the right size.
@@ -283,7 +280,7 @@ ip(T)
%% Or not: convert from '.'/':'-separated decimal/hex.
ip(Addr) ->
- {ok, A} = inet_parse:address(Addr), %% documented in inet(3)
+ {ok, A} = inet:parse_address(Addr),
A.
%% ---------------------------------------------------------------------------
diff --git a/lib/diameter/src/base/diameter_peer.erl b/lib/diameter/src/base/diameter_peer.erl
index 2759f17e64..4cb5a57a54 100644
--- a/lib/diameter/src/base/diameter_peer.erl
+++ b/lib/diameter/src/base/diameter_peer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -202,10 +202,10 @@ match1(Addr, Match) ->
match(Addr, {ok, A}, _) ->
Addr == A;
match(Addr, {error, _}, RE) ->
- match == re:run(inet_parse:ntoa(Addr), RE, [{capture, none}]).
+ match == re:run(inet:ntoa(Addr), RE, [{capture, none}, caseless]).
addr([_|_] = A) ->
- inet_parse:address(A);
+ inet:parse_address(A);
addr(A) ->
{ok, A}.
diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl
index 1b0dc417e5..cf5e7f21d3 100644
--- a/lib/diameter/src/base/diameter_peer_fsm.erl
+++ b/lib/diameter/src/base/diameter_peer_fsm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -128,7 +128,8 @@
%% outgoing DPR; boolean says whether or not
%% the request was sent explicitly with
%% diameter:call/4.
- codec :: #{string_decode := boolean(),
+ codec :: #{decode_format := diameter:decode_format(),
+ string_decode := boolean(),
strict_mbit := boolean(),
rfc := 3588 | 6733,
ordered_encode := false},
@@ -237,7 +238,7 @@ i({Ack, WPid, {M, Ref} = T, Opts, {SvcOpts, Nodes, Dict0, Svc}}) ->
proplists:get_value(dpa_timeout, Opts, ?DPA_TIMEOUT)}),
Tmo = proplists:get_value(capx_timeout, Opts, ?CAPX_TIMEOUT),
- Strictness = proplists:get_value(capx_strictness, Opts, true),
+ Strict = proplists:get_value(strict_capx, Opts, true),
LengthErr = proplists:get_value(length_errors, Opts, exit),
{TPid, Addrs} = start_transport(T, Rest, Svc),
@@ -251,9 +252,10 @@ i({Ack, WPid, {M, Ref} = T, Opts, {SvcOpts, Nodes, Dict0, Svc}}) ->
mode = M,
service = svc(Svc, Addrs),
length_errors = LengthErr,
- strict = Strictness,
+ strict = Strict,
incoming_maxlen = Maxlen,
- codec = maps:with([string_decode,
+ codec = maps:with([decode_format,
+ string_decode,
strict_mbit,
rfc,
ordered_encode],
@@ -542,11 +544,11 @@ put_route(Pid) ->
MRef = monitor(process, Pid),
put(Pid, MRef).
-%% get_route/2
+%% get_route/3
-%% incoming answer
-get_route(_, #diameter_packet{header = #diameter_header{is_request = false}}
- = Pkt) ->
+%% Incoming answer.
+get_route(_, _, #diameter_packet{header = #diameter_header{is_request = false}}
+ = Pkt) ->
Seqs = diameter_codec:sequence_numbers(Pkt),
case erase(Seqs) of
{Pid, Ref, MRef} ->
@@ -557,8 +559,14 @@ get_route(_, #diameter_packet{header = #diameter_header{is_request = false}}
false
end;
-%% incoming request
-get_route(Ack, _) ->
+%% Requests answered here ...
+get_route(_, N, _)
+ when N == 'CER';
+ N == 'DPR' ->
+ false;
+
+%% ... or not.
+get_route(Ack, _, _) ->
Ack.
%% erase_route/1
@@ -649,10 +657,6 @@ encode(Rec, Opts, Dict) ->
%% incoming/2
-incoming({recv = T, Name, Pkt}, #state{parent = Pid, ack = Ack} = S) ->
- Pid ! {T, self(), get_route(Ack, Pkt), Name, Pkt},
- rcv(Name, Pkt, S);
-
incoming(#diameter_header{is_request = R}, #state{transport = TPid,
ack = Ack}) ->
R andalso Ack andalso send(TPid, false),
@@ -670,98 +674,97 @@ incoming(T, _) ->
%% recv/2
-recv(#diameter_packet{header = #diameter_header{} = Hdr}
- = Pkt,
- #state{dictionary = Dict0}
- = S) ->
- recv1(diameter_codec:msg_name(Dict0, Hdr), Pkt, S);
-
-recv(#diameter_packet{header = undefined,
- bin = Bin}
- = Pkt,
- S) ->
- recv(diameter_codec:decode_header(Bin), Pkt, S);
+recv(#diameter_packet{bin = Bin} = Pkt, S) ->
+ recv(Bin, Pkt, S);
recv(Bin, S) ->
- recv(#diameter_packet{bin = Bin}, S).
+ recv(Bin, Bin, S).
+
+%% recv/3
+
+recv(Bin, Msg, S) ->
+ recv(diameter_codec:decode_header(Bin), Bin, Msg, S).
-%% recv1/3
+%% recv/4
-recv1(_,
- #diameter_packet{header = H, bin = Bin},
- #state{incoming_maxlen = M})
+recv(false, Bin, _, #state{length_errors = E}) ->
+ invalid(E, truncated_header, Bin),
+ Bin;
+
+recv(#diameter_header{length = Len} = H, Bin, Msg, #state{length_errors = E,
+ incoming_maxlen = M,
+ dictionary = Dict0}
+ = S)
+ when E == handle;
+ 0 == Len rem 4, bit_size(Bin) == 8*Len, size(Bin) =< M ->
+ recv1(diameter_codec:msg_name(Dict0, H), H, Msg, S);
+
+recv(H, Bin, _, #state{incoming_maxlen = M})
when M < size(Bin) ->
invalid(false, incoming_maxlen_exceeded, {size(Bin), H}),
H;
+recv(H, Bin, _, #state{length_errors = E}) ->
+ T = {size(Bin), bit_size(Bin) rem 8, H},
+ invalid(E, message_length_mismatch, T),
+ H.
+
+%% recv1/4
+
%% Ignore anything but an expected CER/CEA if so configured. This is
%% non-standard behaviour.
-recv1(Name, #diameter_packet{header = H}, #state{state = {'Wait-CEA', _, _},
- strict = false})
+recv1(Name, H, _, #state{state = {'Wait-CEA', _, _},
+ strict = false})
when Name /= 'CEA' ->
H;
-recv1(Name, #diameter_packet{header = H}, #state{state = recv_CER,
- strict = false})
+recv1(Name, H, _, #state{state = recv_CER,
+ strict = false})
when Name /= 'CER' ->
H;
%% Incoming request after outgoing DPR: discard. Don't discard DPR, so
%% both ends don't do so when sending simultaneously.
-recv1(Name,
- #diameter_packet{header = #diameter_header{is_request = true} = H},
- #state{dpr = {_,_,_}})
+recv1(Name, #diameter_header{is_request = true} = H, _, #state{dpr = {_,_,_}})
when Name /= 'DPR' ->
invalid(false, recv_after_outgoing_dpr, H),
H;
%% Incoming request after incoming DPR: discard.
-recv1(_,
- #diameter_packet{header = #diameter_header{is_request = true} = H},
- #state{dpr = true}) ->
+recv1(_, #diameter_header{is_request = true} = H, _, #state{dpr = true}) ->
invalid(false, recv_after_incoming_dpr, H),
H;
%% DPA with identifier mismatch, or in response to a DPR initiated by
%% the service.
-recv1('DPA' = N,
- #diameter_packet{header = #diameter_header{hop_by_hop_id = Hid,
- end_to_end_id = Eid}}
- = Pkt,
- #state{dpr = {X,H,E}}
+recv1('DPA' = Name,
+ #diameter_header{hop_by_hop_id = Hid, end_to_end_id = Eid}
+ = H,
+ Msg,
+ #state{dpr = {X,HI,EI}}
= S)
- when H /= Hid;
- E /= Eid;
+ when HI /= Hid;
+ EI /= Eid;
not X ->
- rcv(N, Pkt, S);
+ Pkt = pkt(H, Msg),
+ handle(Name, Pkt, S);
-%% Any other message with a header and no length errors: send to the
-%% parent.
-recv1(Name, Pkt, #state{}) ->
- {recv, Name, Pkt}.
+%% Any other message with a header and no length errors.
+recv1(Name, H, Msg, #state{parent = Pid, ack = Ack} = S) ->
+ Pkt = pkt(H, Msg),
+ Pid ! {recv, self(), get_route(Ack, Name, Pkt), Name, Pkt},
+ handle(Name, Pkt, S).
-%% recv/3
+%% pkt/2
-recv(#diameter_header{length = Len}
- = H,
- #diameter_packet{bin = Bin}
- = Pkt,
- #state{length_errors = E}
- = S)
- when E == handle;
- 0 == Len rem 4, bit_size(Bin) == 8*Len ->
- recv(Pkt#diameter_packet{header = H}, S);
+pkt(H, Bin)
+ when is_binary(Bin) ->
+ #diameter_packet{header = H,
+ bin = Bin};
-recv(#diameter_header{}
- = H,
- #diameter_packet{bin = Bin},
- #state{length_errors = E}) ->
- T = {size(Bin), bit_size(Bin) rem 8, H},
- invalid(E, message_length_mismatch, T),
- Bin;
+pkt(H, Pkt) ->
+ Pkt#diameter_packet{header = H}.
-recv(false, #diameter_packet{bin = Bin}, #state{length_errors = E}) ->
- invalid(E, truncated_header, Bin),
- Bin.
+%% invalid/3
%% Note that counters here only count discarded messages.
invalid(E, Reason, T) ->
@@ -770,39 +773,39 @@ invalid(E, Reason, T) ->
?LOG(Reason, T),
ok.
-%% rcv/3
+%% handle/3
%% Incoming CEA.
-rcv('CEA' = N,
- #diameter_packet{header = #diameter_header{end_to_end_id = Eid,
- hop_by_hop_id = Hid}}
- = Pkt,
- #state{state = {'Wait-CEA', Hid, Eid}}
- = S) ->
+handle('CEA' = N,
+ #diameter_packet{header = #diameter_header{end_to_end_id = Eid,
+ hop_by_hop_id = Hid}}
+ = Pkt,
+ #state{state = {'Wait-CEA', Hid, Eid}}
+ = S) ->
?LOG(recv, N),
handle_CEA(Pkt, S);
%% Incoming CER
-rcv('CER' = N, Pkt, #state{state = recv_CER} = S) ->
+handle('CER' = N, Pkt, #state{state = recv_CER} = S) ->
handle_request(N, Pkt, S);
%% Anything but CER/CEA in a non-Open state is an error, as is
%% CER/CEA in anything but recv_CER/Wait-CEA.
-rcv(Name, _, #state{state = PS})
+handle(Name, _, #state{state = PS})
when PS /= 'Open';
Name == 'CER';
Name == 'CEA' ->
{stop, {Name, PS}};
-rcv('DPR' = N, Pkt, S) ->
+handle('DPR' = N, Pkt, S) ->
handle_request(N, Pkt, S);
%% DPA in response to DPR, with the expected identifiers.
-rcv('DPA' = N,
- #diameter_packet{header = #diameter_header{end_to_end_id = Eid,
- hop_by_hop_id = Hid}
- = H}
- = Pkt,
+handle('DPA' = N,
+ #diameter_packet{header = #diameter_header{end_to_end_id = Eid,
+ hop_by_hop_id = Hid}
+ = H}
+ = Pkt,
#state{dictionary = Dict0,
transport = TPid,
dpr = {X, Hid, Eid},
@@ -813,7 +816,8 @@ rcv('DPA' = N,
%% service: explicit DPR is counted in the same way
%% as other explicitly sent requests.
incr(recv, H, Dict0),
- incr_rc(recv, diameter_codec:decode(Dict0, Opts, Pkt), Dict0)
+ {_, RecPkt} = decode(Dict0, Opts, Pkt),
+ incr_rc(recv, RecPkt, Dict0)
end,
diameter_peer:close(TPid),
{stop, N};
@@ -821,13 +825,13 @@ rcv('DPA' = N,
%% Ignore an unsolicited DPA in particular. Note that dpa_timeout
%% deals with the case in which the peer sends the wrong identifiers
%% in DPA.
-rcv('DPA' = N, #diameter_packet{header = H}, _) ->
+handle('DPA' = N, #diameter_packet{header = H}, _) ->
?LOG(ignored, N),
%% Note that these aren't counted in the normal recv counter.
diameter_stats:incr({diameter_codec:msg_id(H), recv, ignored}),
ok;
-rcv(_, _, _) ->
+handle(_, _, _) ->
ok.
%% incr/3
@@ -897,7 +901,7 @@ outgoing(#diameter_packet{header = #diameter_header{is_request = false}}
ok;
%% Outgoing request: discard.
-outgoing(Msg, #state{dpr = {_,_,_}}) ->
+outgoing(Msg, #state{}) ->
invalid(false, send_after_dpr, header(Msg)).
header(#diameter_packet{header = H}) ->
@@ -917,21 +921,30 @@ handle_request(Name,
= S) ->
?LOG(recv, Name),
incr(recv, H, Dict0),
- send_answer(Name, diameter_codec:decode(Dict0, Opts, Pkt), S).
+ send_answer(Name, decode(Dict0, Opts, Pkt), S).
+
+%% decode/3
+%%
+%% Decode the message as record for diameter_capx, and in the
+%% configured format for events.
+
+decode(Dict0, Opts, Pkt) ->
+ {diameter_codec:decode(Dict0, Opts, Pkt),
+ diameter_codec:decode(Dict0, Opts#{decode_format := record}, Pkt)}.
%% send_answer/3
-send_answer(Type, ReqPkt, #state{transport = TPid,
- dictionary = Dict,
- codec = Opts}
- = S) ->
- incr_error(recv, ReqPkt, Dict),
+send_answer(Type, {DecPkt, RecPkt}, #state{transport = TPid,
+ dictionary = Dict,
+ codec = Opts}
+ = S) ->
+ incr_error(recv, RecPkt, Dict),
#diameter_packet{header = H,
transport_data = TD}
- = ReqPkt,
+ = RecPkt,
- {Msg, PostF} = build_answer(Type, ReqPkt, S),
+ {Msg, PostF} = build_answer(Type, DecPkt, RecPkt, S),
%% An answer message clears the R and T flags and retains the P
%% flag. The E flag is set at encode.
@@ -959,15 +972,15 @@ eval([F|A], S) ->
eval(T, _) ->
close(T).
-%% build_answer/3
+%% build_answer/4
build_answer('CER',
+ DecPkt,
#diameter_packet{msg = CER,
header = #diameter_header{version
= ?DIAMETER_VERSION,
is_error = false},
- errors = []}
- = Pkt,
+ errors = []},
#state{dictionary = Dict0}
= S) ->
{SupportedApps, RCaps, CEA} = recv_CER(CER, S),
@@ -985,25 +998,25 @@ build_answer('CER',
orelse ?THROW(4003), %% DIAMETER_ELECTION_LOST
caps_cb(Caps)
of
- N -> {cea(CEA, N, Dict0), [fun open/5, Pkt,
+ N -> {cea(CEA, N, Dict0), [fun open/5, DecPkt,
SupportedApps,
Caps,
{accept, inband_security(IS)}]}
catch
?FAILURE(Reason) ->
- rejected(Reason, {'CER', Reason, Caps, Pkt}, S)
+ rejected(Reason, {'CER', Reason, Caps, DecPkt}, S)
end;
%% The error checks below are similar to those in diameter_traffic for
%% other messages. Should factor out the commonality.
build_answer(Type,
+ DecPkt,
#diameter_packet{header = H,
- errors = Es}
- = Pkt,
+ errors = Es},
S) ->
{RC, FailedAVP} = result_code(Type, H, Es),
- {answer(Type, RC, FailedAVP, S), post(Type, RC, Pkt, S)}.
+ {answer(Type, RC, FailedAVP, S), post(Type, RC, DecPkt, S)}.
inband_security([]) ->
?NO_INBAND_SECURITY;
@@ -1175,12 +1188,10 @@ handle_CEA(#diameter_packet{header = H}
= S) ->
incr(recv, H, Dict0),
- #diameter_packet{}
- = DPkt
- = diameter_codec:decode(Dict0, Opts, Pkt),
+ {DecPkt, RecPkt} = decode(Dict0, Opts, Pkt),
- RC = result_code(incr_rc(recv, DPkt, Dict0)),
- {SApps, IS, RCaps} = recv_CEA(DPkt, S),
+ RC = result_code(incr_rc(recv, RecPkt, Dict0)),
+ {SApps, IS, RCaps} = recv_CEA(RecPkt, S),
#diameter_caps{origin_host = {OH, DH}}
= Caps
@@ -1203,9 +1214,9 @@ handle_CEA(#diameter_packet{header = H}
orelse ?THROW(election_lost),
caps_cb(Caps)
of
- _ -> open(DPkt, SApps, Caps, {connect, hd([_] = IS)}, S)
+ _ -> open(DecPkt, SApps, Caps, {connect, hd([_] = IS)}, S)
catch
- ?FAILURE(Reason) -> close({'CEA', Reason, Caps, DPkt})
+ ?FAILURE(Reason) -> close({'CEA', Reason, Caps, DecPkt})
end.
%% Check more than the result code since the peer could send success
%% regardless. If not 2001 then a peer_up callback could do anything
diff --git a/lib/diameter/src/base/diameter_reg.erl b/lib/diameter/src/base/diameter_reg.erl
index 97e74657bd..c1762a07e3 100644
--- a/lib/diameter/src/base/diameter_reg.erl
+++ b/lib/diameter/src/base/diameter_reg.erl
@@ -19,10 +19,11 @@
%%
%%
-%% The module implements a simple term -> pid registry.
+%% A simple term -> pid registry.
%%
-module(diameter_reg).
+
-behaviour(gen_server).
-export([add/1,
@@ -57,18 +58,18 @@
-type key() :: term().
-type from() :: {pid(), term()}.
+-type rcvr() :: [pid() | term()] %% subscribe
+ | from(). %% wait
-type pattern() :: term().
-record(state, {id = diameter_lib:now(),
- receivers = dict:new()
- :: dict:dict(pattern(), [[pid() | term()]%% subscribe
- | from()]), %% wait
+ notify = #{} :: #{pattern() => [rcvr()]},
monitors = sets:new() :: sets:set(pid())}).
%% The ?TABLE bag contains the Key -> Pid mapping, as {Key, Pid}
%% tuples. Each pid is stored in the monitors set to ensure only one
%% monitor for each pid: more are harmless, but unnecessary. A pattern
-%% is added to receivers a result of calls to wait/1 or subscribe/2:
+%% is added to notify a result of calls to wait/1 or subscribe/2:
%% changes to ?TABLE causes processes to be notified as required.
%% ===========================================================================
@@ -156,7 +157,7 @@ wait(Pat) ->
%% # subscribe(Pat, T)
%%
%% Like match/1, but additionally receive messages of the form
-%% {T, add|remove, {term(), pid()} when associations are added
+%% {T, add|remove, {term(), pid()}} when associations are added
%% or removed.
%% ===========================================================================
@@ -186,15 +187,12 @@ uptime() ->
-> [{pid(), [key()]}].
pids() ->
- to_list(fun swap/1).
-
-to_list(Fun) ->
- ets:foldl(fun(T,D) -> append(Fun(T), D) end, orddict:new(), ?TABLE).
-
-append({K,V}, Dict) ->
- orddict:append(K, V, Dict).
+ append(ets:select(?TABLE, [{{'$1','$2'}, [], [{{'$2', '$1'}}]}])).
-id(T) -> T.
+append(Pairs) ->
+ dict:to_list(lists:foldl(fun({K,V}, D) -> dict:append(K, V, D) end,
+ dict:new(),
+ Pairs)).
%% terms/0
@@ -202,9 +200,7 @@ id(T) -> T.
-> [{key(), [pid()]}].
terms() ->
- to_list(fun id/1).
-
-swap({X,Y}) -> {Y,X}.
+ append(ets:tab2list(?TABLE)).
%% subs/0
@@ -212,31 +208,19 @@ swap({X,Y}) -> {Y,X}.
-> [{pattern(), [{pid(), term()}]}].
subs() ->
- #state{receivers = RD} = state(),
- dict:fold(fun sub/3, orddict:new(), RD).
-
-sub(Pat, Ps, Dict) ->
- lists:foldl(fun([P|T], D) -> orddict:append(Pat, {P,T}, D);
- (_, D) -> D
- end,
- Dict,
- Ps).
+ #state{notify = Dict} = state(),
+ [{K, Ts} || {K,Ps} <- maps:to_list(Dict),
+ Ts <- [[{P,T} || [P|T] <- Ps]]].
%% waits/0
-spec waits()
- -> [{pattern(), [{from(), term()}]}].
+ -> [{pattern(), [from()]}].
waits() ->
- #state{receivers = RD} = state(),
- dict:fold(fun wait/3, orddict:new(), RD).
-
-wait(Pat, Ps, Dict) ->
- lists:foldl(fun({_,_} = F, D) -> orddict:append(Pat, F, D);
- (_, D) -> D
- end,
- Dict,
- Ps).
+ #state{notify = Dict} = state(),
+ [{K, Ts} || {K,Ps} <- maps:to_list(Dict),
+ Ts <- [[T || {_,_} = T <- Ps]]].
%% ----------------------------------------------------------
%% # init/1
@@ -250,33 +234,35 @@ init(_) ->
%% # handle_call/3
%% ----------------------------------------------------------
-handle_call({add, Uniq, Key}, {Pid, _}, S0) ->
+handle_call({add, Uniq, Key}, {Pid, _}, S) ->
Rec = {Key, Pid},
- S1 = flush(Uniq, Rec, S0),
+ NS = flush(Uniq, Rec, S), %% before insert
{Res, New} = insert(Uniq, Rec),
- {Recvs, S} = add(New, Rec, S1),
- notify(Recvs, Rec),
- {reply, Res, S};
+ {reply, Res, notify(add, New andalso Rec, if New ->
+ add_monitor(Pid, NS);
+ true ->
+ NS
+ end)};
handle_call({remove, Key}, {Pid, _}, S) ->
Rec = {Key, Pid},
- Recvs = delete([Rec], S),
- ets:delete_object(?TABLE, Rec),
- notify(Recvs, remove),
- {reply, true, S};
+ {reply, true, try
+ notify(remove, Rec, S)
+ after
+ ets:delete_object(?TABLE, Rec)
+ end};
-handle_call({wait, Pat}, {Pid, _} = From, #state{receivers = RD} = S) ->
+handle_call({wait, Pat}, {Pid, _} = From, S) ->
NS = add_monitor(Pid, S),
case match(Pat) of
- [_|_] = L ->
- {reply, L, NS};
+ [_|_] = Recs ->
+ {reply, Recs, NS};
[] ->
- {noreply, NS#state{receivers = dict:append(Pat, From, RD)}}
+ {noreply, queue(Pat, From, NS)}
end;
-handle_call({subscribe, Pat, T}, {Pid, _}, #state{receivers = RD} = S) ->
- NS = add_monitor(Pid, S),
- {reply, match(Pat), NS#state{receivers = dict:append(Pat, [Pid | T], RD)}};
+handle_call({subscribe, Pat, T}, {Pid, _}, S) ->
+ {reply, match(Pat), queue(Pat, [Pid | T], add_monitor(Pid, S))};
handle_call(state, _, S) ->
{reply, S, S};
@@ -315,6 +301,11 @@ terminate(_Reason, _State)->
%% # code_change/3
%% ----------------------------------------------------------
+code_change(_, State, "2.1") ->
+ {ok, lists:foldl(fun add_monitor/2,
+ State,
+ ets:select(?TABLE, [{{'_', '$1'}, [], ['$1']}]))};
+
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
@@ -332,106 +323,62 @@ insert(true, Rec) ->
B = ets:insert_new(?TABLE, Rec), %% entry inserted?
{B, B}.
-%% add/3
-
+%% add_monitor/2
+%%
%% Only add a single monitor for any given process, since there's no
%% use to more.
-add(true, {_Key, Pid} = Rec, S) ->
- NS = add_monitor(Pid, S),
- {Recvs, RD} = add(Rec, NS),
- {Recvs, S#state{receivers = RD}};
-
-add(false = No, _, S) ->
- {No, S}.
-%% add/2
+add_monitor(Pid, #state{monitors = Ps} = S) ->
+ case sets:is_element(Pid, Ps) of
+ false ->
+ monitor(process, Pid),
+ S#state{monitors = sets:add_element(Pid, Ps)};
+ true ->
+ S
+ end.
-%% Notify processes whose patterns match the inserted key.
-add({_Key, Pid} = Rec, #state{receivers = RD}) ->
- dict:fold(fun(Pt, Ps, A) ->
- add(lists:member(Rec, match(Pt, Pid)), Pt, Ps, Rec, A)
- end,
- {sets:new(), RD},
- RD).
+%% notify/3
-%% add/5
-
-add(true, Pat, Recvs, {_,_} = Rec, {Set, Dict}) ->
- {lists:foldl(fun sets:add_element/2, Set, Recvs),
- remove(fun erlang:is_list/1, Pat, Recvs, Dict)};
-
-add(false, _, _, _, Acc) ->
- Acc.
-
-%% add_monitor/2
+notify(_, false, S) ->
+ S;
-add_monitor(Pid, #state{monitors = MS} = S) ->
- add_monitor(sets:is_element(Pid, MS), Pid, S).
+notify(Op, {_,_} = Rec, #state{notify = Dict} = S) ->
+ S#state{notify = maps:fold(fun(P,Rs,D) -> notify(Op, Rec, P, Rs, D) end,
+ Dict,
+ Dict)}.
-%% add_monitor/3
+%% notify/5
-add_monitor(false, Pid, #state{monitors = MS} = S) ->
- monitor(process, Pid),
- S#state{monitors = sets:add_element(Pid, MS)};
-
-add_monitor(true, _, S) ->
- S.
-
-%% delete/2
-
-delete(Recs, #state{receivers = RD}) ->
- lists:foldl(fun(R,S) -> delete(R, RD, S) end, sets:new(), Recs).
-
-%% delete/3
-
-delete({_Key, Pid} = Rec, RD, Set) ->
- dict:fold(fun(Pt, Ps, S) ->
- delete(lists:member(Rec, match(Pt, Pid)), Rec, Ps, S)
- end,
- Set,
- RD).
-
-%% delete/4
-
-%% Entry matches a pattern ...
-delete(true, Rec, Recvs, Set) ->
- lists:foldl(fun(R,S) -> sets:add_element({R, Rec}, S) end,
- Set,
- Recvs);
-
-%% ... or not.
-delete(false, _, _, Set) ->
- Set.
-
-%% notify/2
-
-notify(false = No, _) ->
- No;
-
-notify(Recvs, remove = Op) ->
- sets:fold(fun({P,R}, N) -> send(P, R, Op), N+1 end, 0, Recvs);
-
-notify(Recvs, {_,_} = Rec) ->
- sets:fold(fun(P,N) -> send(P, Rec, add), N+1 end, 0, Recvs).
+notify(Op, {_, Pid} = Rec, Pat, Rcvrs, Dict) ->
+ case lists:member(Rec, match(Pat, Pid)) of
+ true ->
+ reset(Pat, Dict, [P || P <- Rcvrs, send(P, Op, Rec)]);
+ false ->
+ Dict
+ end.
%% send/3
-%% No processes waiting on remove, by construction: they've either
-%% received notification at add or aren't waiting.
-send([Pid | T], Rec, Op) ->
- Pid ! {T, Op, Rec};
+send([Pid | T], Op, Rec) ->
+ Pid ! {T, Op, Rec},
+ true;
-send({_,_} = From, Rec, add) ->
- gen_server:reply(From, [Rec]).
+%% No processes wait on remove: they receive notification immediately
+%% or at add, by construction.
+send({_,_} = From, add, Rec) ->
+ gen_server:reply(From, [Rec]),
+ false.
%% down/2
-down(Pid, #state{monitors = MS} = S) ->
- NS = flush(Pid, S),
- Recvs = delete(match('_', Pid), NS),
- ets:match_delete(?TABLE, {'_', Pid}),
- notify(Recvs, remove),
- NS#state{monitors = sets:del_element(Pid, MS)}.
+down(Pid, #state{monitors = Ps} = S) ->
+ Recs = match('_', Pid),
+ Acc0 = flush(Pid, S#state{monitors = sets:del_element(Pid, Ps)}),
+ try
+ lists:foldl(fun(R,NS) -> notify(remove, R, NS) end, Acc0, Recs)
+ after
+ ets:match_delete(?TABLE, {'_', Pid})
+ end.
%% flush/3
@@ -452,16 +399,15 @@ flush(false, _, S) ->
%% flush/2
%% Process has died and should no longer receive messages/replies.
-flush(Pid, #state{receivers = RD} = S)
- when is_pid(Pid) ->
- S#state{receivers = dict:fold(fun(Pt,Ps,D) -> flush(Pid, Pt, Ps, D) end,
- RD,
- RD)}.
+flush(Pid, #state{notify = Dict} = S) ->
+ S#state{notify = maps:fold(fun(P,Rs,D) -> flush(Pid, P, Rs, D) end,
+ Dict,
+ Dict)}.
%% flush/4
-flush(Pid, Pat, Recvs, Dict) ->
- remove(fun(T) -> Pid /= head(T) end, Pat, Recvs, Dict).
+flush(Pid, Pat, Rcvrs, Dict) ->
+ reset(Pat, Dict, [T || T <- Rcvrs, Pid /= head(T)]).
%% head/1
@@ -471,15 +417,18 @@ head([P|_]) ->
head({P,_}) ->
P.
-%% remove/4
+%% reset/3
+
+reset(Key, Map, []) ->
+ maps:remove(Key, Map);
+
+reset(Key, Map, List) ->
+ maps:put(Key, List, Map).
+
+%% queue/3
-remove(Pred, Key, Values, Dict) ->
- case lists:filter(Pred, Values) of
- [] ->
- dict:erase(Key, Dict);
- Rest ->
- dict:store(Key, Rest, Dict)
- end.
+queue(Pat, Rcvr, #state{notify = Dict} = S) ->
+ S#state{notify = maps:put(Pat, [Rcvr | maps:get(Pat, Dict, [])], Dict)}.
%% call/1
diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl
index a976a8b998..77d184cfc7 100644
--- a/lib/diameter/src/base/diameter_service.erl
+++ b/lib/diameter/src/base/diameter_service.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -112,8 +112,24 @@
use_shared_peers := diameter:remotes(),%% use from
restrict_connections := diameter:restriction(),
incoming_maxlen := diameter:message_length(),
+ strict_arities => diameter:strict_arities(),
strict_mbit := boolean(),
+ decode_format := diameter:decode_format(),
+ avp_dictionaries => nonempty_list(module()),
+ traffic_counters := boolean(),
string_decode := boolean(),
+ capabilities_cb => diameter:evaluable(),
+ pool_size => pos_integer(),
+ capx_timeout => diameter:'Unsigned32'(),
+ strict_capx => boolean(),
+ disconnect_cb => diameter:evaluable(),
+ dpr_timeout => diameter:'Unsigned32'(),
+ dpa_timeout => diameter:'Unsigned32'(),
+ length_errors => exit | handle | discard,
+ connect_timer => diameter:'Unsigned32'(),
+ watchdog_timer => diameter:'Unsigned32'()
+ | {module(), atom(), list()},
+ watchdog_config => [{okay|suspect, non_neg_integer()}],
spawn_opt := list() | {module(), atom(), list()}}}).
%% Record representing an RFC 3539 watchdog process implemented by
@@ -135,7 +151,7 @@
apps :: match([{0..16#FFFFFFFF, diameter:app_alias()}] %% {Id, Alias}
| [diameter:app_alias()]), %% remote
caps :: match(#diameter_caps{}),
- started = diameter_lib:now(), %% at process start or sharing
+ started = diameter_lib:now(), %% at connection_up
watchdog :: match(pid() %% key into watchdogT
| undefined)}). %% undefined if remote
@@ -514,6 +530,13 @@ transition({tc_timeout, T}, S) ->
tc_timeout(T, S),
ok;
+transition({nodeup, Node, _}, S) ->
+ nodeup(Node, S),
+ ok;
+
+transition({nodedown, _Node, _}, _) ->
+ ok;
+
transition(Req, S) ->
unexpected(handle_info, [Req], S),
ok.
@@ -531,15 +554,25 @@ terminate(Reason, #state{service_name = Name, local = {PeerT, _, _}} = S) ->
%% wait for watchdog state changes to take care of if. That this
%% takes place after deleting the state entry ensures that the
%% resulting failover by request processes accomplishes nothing.
- ets:foldl(fun(#peer{pid = TPid}, _) ->
- diameter_traffic:peer_down(TPid)
- end,
- ok,
- PeerT),
+ ets:foldl(fun peer_down/2, ok, PeerT),
shutdown == Reason %% application shutdown
andalso shutdown(application, S).
+%% peer_down/1
+%%
+%% Entries with watchdog state SUSPECT are already down: ignore the
+%% expected failure. This assumes the current implementation, but
+%% double the number of lookups (in the typical case) could be the
+%% greater evil if there are many peer connections.
+
+peer_down(#peer{pid = TPid}, _) ->
+ try
+ diameter_traffic:peer_down(TPid)
+ catch
+ error: {badmatch, []} -> ok
+ end.
+
%% ---------------------------------------------------------------------------
%% # code_change/3
%% ---------------------------------------------------------------------------
@@ -679,12 +712,15 @@ i(SvcName) ->
cfg_acc({SvcName, #diameter_service{applications = Apps} = Rec, Opts},
{false, Acc}) ->
lists:foreach(fun init_mod/1, Apps),
+ #{monitor := M}
+ = SvcOpts
+ = service_opts(Opts),
S = #state{service_name = SvcName,
service = Rec#diameter_service{pid = self()},
local = init_peers(),
remote = init_peers(),
- monitor = mref(get_value(monitor, Opts)),
- options = service_options(lists:keydelete(monitor, 1, Opts))},
+ monitor = mref(M),
+ options = maps:remove(monitor, SvcOpts)},
{S, Acc};
cfg_acc({_Ref, Type, _Opts} = T, {S, Acc})
@@ -699,8 +735,29 @@ init_peers() ->
%% Alias,
%% TPid}
-service_options(Opts) ->
- maps:from_list(Opts).
+service_opts(Opts) ->
+ remove([{strict_arities, true},
+ {avp_dictionaries, []}],
+ maps:merge(maps:from_list([{monitor, false} | def_opts()]),
+ maps:from_list(Opts))).
+
+remove(List, Map) ->
+ maps:filter(fun(K,V) -> not lists:member({K,V}, List) end,
+ Map).
+
+def_opts() -> %% defaults on the service map
+ [{share_peers, false},
+ {use_shared_peers, false},
+ {sequence, {0,32}},
+ {restrict_connections, nodes},
+ {incoming_maxlen, 16#FFFFFF},
+ {strict_arities, true},
+ {strict_mbit, true},
+ {decode_format, record},
+ {avp_dictionaries, []},
+ {traffic_counters, true},
+ {string_decode, true},
+ {spawn_opt, []}].
mref(false = No) ->
No;
@@ -709,6 +766,8 @@ mref(P) ->
init_shared(#state{options = #{use_shared_peers := T},
service_name = Svc}) ->
+ T == false orelse net_kernel:monitor_nodes(true, [{node_type, visible},
+ nodedown_reason]),
notify(T, Svc, {service, self()}).
init_mod(#diameter_app{alias = Alias,
@@ -718,16 +777,17 @@ init_mod(#diameter_app{alias = Alias,
start_fsm({Ref, Type, Opts}, S) ->
start(Ref, {Type, Opts}, S).
-get_value(Key, Vs) ->
- {_, V} = lists:keyfind(Key, 1, Vs),
- V.
-
notify(Share, SvcName, T) ->
Nodes = remotes(Share),
[] /= Nodes andalso diameter_peer:notify(Nodes, SvcName, T).
%% Test for the empty list for upgrade reasons: there's no
%% diameter_peer:notify/3 in old code.
+nodeup(Node, #state{options = #{share_peers := SP},
+ service_name = SvcName}) ->
+ lists:member(Node, remotes(SP))
+ andalso diameter_peer:notify([Node], SvcName, {service, self()}).
+
remotes(false) ->
[];
@@ -748,8 +808,8 @@ remotes(F) ->
error_report(invalid_return, share_peers, F),
[]
catch
- E:R ->
- ?LOG(failure, {E, R, F, diameter_lib:get_stacktrace()}),
+ E:R:S ->
+ ?LOG(failure, {E, R, F, diameter_lib:stacktrace(S)}),
error_report(failure, share_peers, F),
[]
end.
@@ -806,7 +866,7 @@ start(Ref, Type, Opts, State) ->
start(Ref, Type, Opts, N, #state{watchdogT = WatchdogT,
local = {PeerT, _, _},
options = #{string_decode := SD}
- = SvcOpts0,
+ = SvcOpts,
service_name = SvcName,
service = Svc0})
when Type == connect;
@@ -815,12 +875,12 @@ start(Ref, Type, Opts, N, #state{watchdogT = WatchdogT,
= Svc1
= merge_service(Opts, Svc0),
Svc = binary_caps(Svc1, SD),
- SvcOpts = merge_options(Opts, SvcOpts0),
- RecvData = diameter_traffic:make_recvdata([SvcName, PeerT, Apps, SvcOpts]),
- T = {Opts, SvcOpts, RecvData, Svc},
+ {SOpts, TOpts} = merge_opts(SvcOpts, Opts),
+ RecvData = diameter_traffic:make_recvdata([SvcName, PeerT, Apps, SOpts]),
+ T = {TOpts, SOpts, RecvData, Svc},
Rec = #watchdog{type = Type,
ref = Ref,
- options = Opts},
+ options = TOpts},
diameter_lib:fold_n(fun(_,A) ->
[wd(Type, Ref, T, WatchdogT, Rec) | A]
@@ -828,10 +888,14 @@ start(Ref, Type, Opts, N, #state{watchdogT = WatchdogT,
[],
N).
-merge_options(Opts, SvcOpts) ->
- Keys = maps:keys(SvcOpts),
- Map = maps:from_list([KV || {K,_} = KV <- Opts, lists:member(K, Keys)]),
- maps:merge(SvcOpts, Map).
+merge_opts(SvcOpts, Opts) ->
+ Keys = [K || {K,_} <- def_opts()],
+ SO = [T || {K,_} = T <- Opts, lists:member(K, Keys)],
+ TO = Opts -- SO,
+ {maps:merge(maps:with(Keys, SvcOpts), maps:from_list(SO)),
+ TO ++ [T || {K,_} = T <- maps:to_list(SvcOpts),
+ not lists:member(K, Keys),
+ not lists:keymember(K, 1, Opts)]}.
binary_caps(Svc, true) ->
Svc;
@@ -1082,11 +1146,11 @@ peer_cb(App, F, A) ->
mod_state(App#diameter_app.alias, ModS),
true
catch
- E:R ->
+ E:R:S ->
%% Don't include arguments since a #diameter_caps{} strings
%% from the peer, which could be anything (especially, large).
[Mod|X] = App#diameter_app.module,
- ?LOG(failure, {E, R, Mod, F, diameter_lib:get_stacktrace()}),
+ ?LOG(failure, {E, R, Mod, F, diameter_lib:stacktrace(S)}),
error_report(failure, F, {Mod, F, A ++ X}),
false
end.
@@ -1312,9 +1376,9 @@ cm([#diameter_app{alias = Alias} = App], Req, From, Svc) ->
?LOG(invalid_return, {ModX, handle_call, Args, T}),
invalid
catch
- E: Reason ->
+ E: Reason: S ->
ModX = App#diameter_app.module,
- Stack = diameter_lib:get_stacktrace(),
+ Stack = diameter_lib:stacktrace(S),
?LOG(failure, {E, Reason, ModX, handle_call, Stack}),
failure
end;
@@ -1400,9 +1464,15 @@ is_remote(Pid, T) ->
%% # remote_peer_up/4
%% ---------------------------------------------------------------------------
-remote_peer_up(TPid, Aliases, Caps, #state{options = #{use_shared_peers := T}}
+remote_peer_up(TPid, Aliases, Caps, #state{options = #{use_shared_peers := T},
+ remote = {PeerT, _, _}}
= S) ->
- is_remote(TPid, T) andalso rpu(TPid, Aliases, Caps, S).
+ is_remote(TPid, T)
+ andalso not ets:member(PeerT, TPid)
+ andalso rpu(TPid, Aliases, Caps, S).
+
+%% Notification can be duplicate since remote nodes push and the local
+%% node pulls.
rpu(TPid, Aliases, Caps, #state{service = Svc, remote = RT}) ->
#diameter_service{applications = Apps} = Svc,
@@ -1412,6 +1482,7 @@ rpu(TPid, Aliases, Caps, #state{service = Svc, remote = RT}) ->
rpu(_, [] = No, _, _) ->
No;
+
rpu(TPid, Aliases, Caps, {PeerT, _, _} = RT) ->
monitor(process, TPid),
ets:insert(PeerT, #peer{pid = TPid,
@@ -1514,10 +1585,10 @@ pick_peer(Local,
?LOG(invalid_return, {ModX, pick_peer, T}),
false
catch
- E: Reason when M ->
+ E: Reason: Stack when M ->
ModX = App#diameter_app.module,
- Stack = diameter_lib:get_stacktrace(),
- ?LOG(failure, {E, Reason, ModX, pick_peer, Stack}),
+ Z = diameter_lib:stacktrace(Stack),
+ ?LOG(failure, {E, Reason, ModX, pick_peer, Z}),
false
end.
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index 85378babea..d2856ae530 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -70,13 +70,17 @@
timeout = 5000 :: 0..16#FFFFFFFF, %% for outgoing requests
detach = false :: boolean()}).
-%% Term passed back to receive_message/6 with every incoming message.
+%% Term passed back to receive_message/5 with every incoming message.
-record(recvdata,
{peerT :: ets:tid(),
service_name :: diameter:service_name(),
apps :: [#diameter_app{}],
sequence :: diameter:sequence(),
- codec :: #{string_decode := boolean(),
+ counters :: boolean(),
+ codec :: #{decode_format := diameter:decode_format(),
+ avp_dictionaries => nonempty_list(module()),
+ string_decode := boolean(),
+ strict_arities => diameter:strict_arities(),
strict_mbit := boolean(),
incoming_maxlen := diameter:message_length()}}).
%% Note that incoming_maxlen is currently handled in diameter_peer_fsm,
@@ -89,6 +93,7 @@
caller :: pid() | undefined, %% calling process
handler :: pid(), %% request process
peer :: undefined | {pid(), #diameter_caps{}},
+ caps :: undefined, %% no longer used
packet :: #diameter_packet{} | undefined}). %% of request
%% ---------------------------------------------------------------------------
@@ -96,13 +101,17 @@
%% ---------------------------------------------------------------------------
make_recvdata([SvcName, PeerT, Apps, SvcOpts | _]) ->
- #{sequence := {_,_} = Mask, spawn_opt := Opts}
+ #{sequence := {_,_} = Mask, spawn_opt := Opts, traffic_counters := B}
= SvcOpts,
{Opts, #recvdata{service_name = SvcName,
peerT = PeerT,
apps = Apps,
sequence = Mask,
- codec = maps:with([string_decode,
+ counters = B,
+ codec = maps:with([decode_format,
+ avp_dictionaries,
+ string_decode,
+ strict_arities,
strict_mbit,
ordered_encode,
incoming_maxlen],
@@ -182,7 +191,7 @@ incr_error(Dir, Id, TPid) ->
%% ---------------------------------------------------------------------------
-spec incr_rc(send|recv, Pkt, TPid, DictT)
- -> {Counter, non_neg_integer()}
+ -> Counter
| Reason
when Pkt :: #diameter_packet{},
TPid :: pid(),
@@ -193,18 +202,26 @@ incr_error(Dir, Id, TPid) ->
| {'Experimental-Result', integer(), integer()},
Reason :: atom().
-incr_rc(Dir, Pkt, TPid, {_, AppDict, _} = DictT) ->
- try
- incr_result(Dir, Pkt, TPid, DictT)
+incr_rc(Dir, Pkt, TPid, {MsgDict, AppDict, Dict0}) ->
+ incr_rc(Dir, Pkt, TPid, MsgDict, AppDict, Dict0);
+
+incr_rc(Dir, Pkt, TPid, Dict0) ->
+ incr_rc(Dir, Pkt, TPid, Dict0, Dict0, Dict0).
+
+%% incr_rc/6
+
+incr_rc(Dir, Pkt, TPid, MsgDict, AppDict, Dict0) ->
+ try get_result(Dir, MsgDict, Dict0, Pkt) of
+ false ->
+ unknown;
+ Avp ->
+ incr_result(Dir, Avp, Pkt, TPid, AppDict)
catch
exit: {E,_} when E == no_result_code;
E == invalid_error_bit ->
incr(TPid, {msg_id(Pkt#diameter_packet.header, AppDict), Dir, E}),
E
- end;
-
-incr_rc(Dir, Pkt, TPid, Dict0) ->
- incr_rc(Dir, Pkt, TPid, {Dict0, Dict0, Dict0}).
+ end.
%% ---------------------------------------------------------------------------
%% receive_message/5
@@ -216,13 +233,13 @@ incr_rc(Dir, Pkt, TPid, Dict0) ->
-> pid() %% request handler
| boolean() %% answer, known request or not
| discard %% request discarded by MFA
- when Route :: {Handler, RequestRef, Seqs}
+ when Route :: {Handler, RequestRef, TPid}
| Ack,
RecvData :: {[SpawnOpt], #recvdata{}},
SpawnOpt :: term(),
Handler :: pid(),
RequestRef :: reference(),
- Seqs :: {0..16#FFFFFFFF, 0..16#FFFFFFFF},
+ TPid :: pid(),
Ack :: boolean().
receive_message(TPid, Route, Pkt, Dict0, RecvData) ->
@@ -303,14 +320,15 @@ recv_request(Ack,
= Pkt,
Dict0,
#recvdata{peerT = PeerT,
- apps = Apps}
+ apps = Apps,
+ counters = Count}
= RecvData) ->
Ack andalso (TPid ! {handler, self()}),
case diameter_service:find_incoming_app(PeerT, TPid, Id, Apps) of
{#diameter_app{id = Aid, dictionary = AppDict} = App, Caps} ->
- incr(recv, Pkt, TPid, AppDict),
+ Count andalso incr(recv, Pkt, TPid, AppDict),
DecPkt = decode(Aid, AppDict, RecvData, Pkt),
- incr_error(recv, DecPkt, TPid, AppDict),
+ Count andalso incr_error(recv, DecPkt, TPid, AppDict),
send_A(recv_R(App, TPid, Dict0, Caps, RecvData, DecPkt),
TPid,
App,
@@ -323,9 +341,7 @@ recv_request(Ack,
%% A request was sent for an application that is not
%% supported.
RC = 3007,
- Es = Pkt#diameter_packet.errors,
- DecPkt = Pkt#diameter_packet{avps = collect_avps(Pkt),
- errors = [RC | Es]},
+ DecPkt = diameter_codec:collect_avps(Pkt),
send_answer(answer_message(RC, Dict0, Caps, DecPkt),
TPid,
Dict0,
@@ -338,17 +354,11 @@ recv_request(Ack,
No
end.
+%% decode/4
+
decode(Id, Dict, #recvdata{codec = Opts}, Pkt) ->
errors(Id, diameter_codec:decode(Id, Dict, Opts, Pkt)).
-collect_avps(Pkt) ->
- case diameter_codec:collect_avps(Pkt) of
- {_Error, Avps} ->
- Avps;
- Avps ->
- Avps
- end.
-
%% send_A/7
send_A([T | Fs], TPid, App, Dict0, RecvData, DecPkt, Caps) ->
@@ -541,6 +551,7 @@ send_A({call, Opts}, TPid, App, Dict0, RecvData, Pkt, Caps, Fs) ->
MsgDict,
AppDict,
Dict0,
+ RecvData#recvdata.counters,
Fs);
RC ->
send_answer(answer_message(RC, Dict0, Caps, Pkt),
@@ -584,14 +595,22 @@ send_answer(Ans, TPid, MsgDict, AppDict, Dict0, RecvData, DecPkt, Fs) ->
TPid,
RecvData#recvdata.codec,
make_answer_packet(Ans, DecPkt, MsgDict, Dict0)),
- send_answer(Pkt, TPid, MsgDict, AppDict, Dict0, Fs).
+ send_answer(Pkt,
+ TPid,
+ MsgDict,
+ AppDict,
+ Dict0,
+ RecvData#recvdata.counters,
+ Fs).
-%% send_answer/6
+%% send_answer/7
-send_answer(Pkt, TPid, MsgDict, AppDict, Dict0, [EvalPktFs | EvalFs]) ->
+send_answer(Pkt, TPid, MsgDict, AppDict, Dict0, Count, [EvalPktFs | EvalFs]) ->
eval_packet(Pkt, EvalPktFs),
- incr(send, Pkt, TPid, AppDict),
- incr_rc(send, Pkt, TPid, {MsgDict, AppDict, Dict0}), %% count outgoing
+ Count andalso begin
+ incr(send, Pkt, TPid, AppDict),
+ incr_rc(send, Pkt, TPid, MsgDict, AppDict, Dict0)
+ end,
send(TPid, z(Pkt), _Route = self()),
lists:foreach(fun diameter_lib:eval/1, EvalFs).
@@ -619,7 +638,7 @@ is_answer_message(#diameter_packet{msg = Msg}, Dict0) ->
is_answer_message([#diameter_header{is_request = R, is_error = E} | _], _) ->
E andalso not R;
-%% Message sent as a tagged avp/value list.
+%% Message sent as a map or tagged avp/value list.
is_answer_message([Name | _], _) ->
Name == 'answer-message';
@@ -665,7 +684,7 @@ resend(false,
Route = #diameter_avp{data = {Dict0, 'Route-Record', OH}},
Seq = diameter_session:sequence(Mask),
Hdr = Hdr0#diameter_header{hop_by_hop_id = Seq},
- Msg = [Hdr, Route | Avps], %% reordered at encode
+ Msg = [Hdr | Avps ++ [Route]],
case send_request(SvcName, App, Msg, Opts) of
#diameter_packet{} = Ans ->
Ans;
@@ -867,7 +886,10 @@ reset(Msg, [RC | Avps], Dict) ->
%% set/3
-%% Reply as name and tuple list ...
+%% Reply as name/values list ...
+set([Name|As], Avps, _)
+ when is_map(As) ->
+ [Name | maps:merge(As, maps:from_list(Avps))];
set([_|_] = Ans, Avps, _) ->
Ans ++ Avps; %% Values nearer tail take precedence.
@@ -900,33 +922,44 @@ failed_avp(_, [] = No, _) ->
failed_avp(Msg, [_|_] = Avps, Dict) ->
[failed(Msg, [{'AVP', Avps}], Dict)].
-%% Reply as name and tuple list ...
-failed([MsgName | Values], FailedAvp, Dict) ->
- RecName = Dict:msg2rec(MsgName),
+%% failed/3
+
+failed(Msg, FailedAvp, Dict) ->
+ RecName = msg2rec(Msg, Dict),
try
- Dict:'#info-'(RecName, {index, 'Failed-AVP'}),
+ Dict:'#info-'(RecName, {index, 'Failed-AVP'}), %% assert existence
{'Failed-AVP', [FailedAvp]}
catch
error: _ ->
- Avps = proplists:get_value('AVP', Values, []),
+ Avps = values(Msg, 'AVP', Dict),
A = #diameter_avp{name = 'Failed-AVP',
value = FailedAvp},
{'AVP', [A|Avps]}
+ end.
+
+%% msg2rec/2
+
+%% Message as name/values list ...
+msg2rec([MsgName | _], Dict) ->
+ Dict:msg2rec(MsgName);
+
+%% ... or record.
+msg2rec(Rec, _) ->
+ element(1, Rec).
+
+%% values/2
+
+%% Message as name/values list ...
+values([_ | Avps], F, _) ->
+ if is_map(Avps) ->
+ maps:get(F, Avps, []);
+ is_list(Avps) ->
+ proplists:get_value(F, Avps, [])
end;
%% ... or record.
-failed(Rec, FailedAvp, Dict) ->
- try
- RecName = element(1, Rec),
- Dict:'#info-'(RecName, {index, 'Failed-AVP'}),
- {'Failed-AVP', [FailedAvp]}
- catch
- error: _ ->
- Avps = Dict:'#get-'('AVP', Rec),
- A = #diameter_avp{name = 'Failed-AVP',
- value = FailedAvp},
- {'AVP', [A|Avps]}
- end.
+values(Rec, F, Dict) ->
+ Dict:'#get-'(F, Rec).
%% 3. Diameter Header
%%
@@ -1003,15 +1036,15 @@ answer_message(RC,
origin_realm = {OR,_}},
#diameter_packet{avps = Avps,
errors = Es}) ->
- {Code, _, Vid} = Dict0:avp_header('Session-Id'),
['answer-message', {'Origin-Host', OH},
{'Origin-Realm', OR},
- {'Result-Code', RC}]
- ++ session_id(Code, Vid, Avps)
- ++ failed_avp(RC, Es).
+ {'Result-Code', RC}
+ | session_id(Dict0, Avps)
+ ++ failed_avp(RC, Es)
+ ++ proxy_info(Dict0, Avps)].
-session_id(Code, Vid, Avps)
- when is_list(Avps) ->
+session_id(Dict0, Avps) ->
+ {Code, _, Vid} = Dict0:avp_header('Session-Id'),
try
#diameter_avp{data = Bin} = find_avp(Code, Vid, Avps),
[{'Session-Id', [Bin]}]
@@ -1029,6 +1062,14 @@ failed_avp(RC, [_ | Es]) ->
failed_avp(_, [] = No) ->
No.
+proxy_info(Dict0, Avps) ->
+ {Code, _, Vid} = Dict0:avp_header('Proxy-Info'),
+ [{'AVP', [A#diameter_avp{value = undefined}
+ || [#diameter_avp{code = C, vendor_id = I} = A | _]
+ <- Avps,
+ C == Code,
+ I == Vid]}].
+
%% find_avp/3
%% Grouped ...
@@ -1102,48 +1143,31 @@ find_avp(Code, VId, [_ | Avps]) ->
%% Message sent as a header/avps list.
incr_result(send = Dir,
- #diameter_packet{msg = [#diameter_header{} = H | _]}
- = Pkt,
+ Avp,
+ #diameter_packet{msg = [#diameter_header{} = H | _]},
TPid,
- DictT) ->
- incr_res(Dir, Pkt#diameter_packet{header = H}, TPid, DictT);
-
-%% Outgoing message as binary: don't count. (Sending binaries is only
-%% partially supported.)
-incr_result(send, #diameter_packet{header = undefined = No}, _, _) ->
- No;
+ AppDict) ->
+ incr_result(Dir, Avp, H, [], TPid, AppDict);
%% Incoming or outgoing. Outgoing with encode errors never gets here
%% since encode fails.
-incr_result(Dir, Pkt, TPid, DictT) ->
- incr_res(Dir, Pkt, TPid, DictT).
-
-incr_res(Dir,
- #diameter_packet{header = #diameter_header{is_error = E}
- = Hdr,
- errors = Es}
- = Pkt,
- TPid,
- DictT) ->
- {MsgDict, AppDict, Dict0} = DictT,
+incr_result(Dir, Avp, Pkt, TPid, AppDict) ->
+ #diameter_packet{header = H, errors = Es}
+ = Pkt,
+ incr_result(Dir, Avp, H, Es, TPid, AppDict).
+
+%% incr_result/6
+incr_result(Dir, Avp, Hdr, Es, TPid, AppDict) ->
Id = msg_id(Hdr, AppDict),
%% Could be {relay, 0}, in which case the R-bit is redundant since
%% only answers are being counted. Let it be however, so that the
%% same tuple is in both send/recv and result code counters.
%% Count incoming decode errors.
- recv /= Dir orelse [] == Es orelse incr_error(Dir, Id, TPid, AppDict),
-
- %% Exit on a missing result code.
- T = rc_counter(MsgDict, Dir, Pkt),
- T == false andalso ?LOGX(no_result_code, {MsgDict, Dir, Hdr}),
- {Ctr, RC, Avp} = T,
-
- %% Or on an inappropriate value.
- is_result(RC, E, Dict0)
- orelse ?LOGX(invalid_error_bit, {MsgDict, Dir, Hdr, Avp}),
+ send == Dir orelse [] == Es orelse incr_error(Dir, Id, TPid, AppDict),
+ Ctr = rcc(Avp),
incr(TPid, {Id, Dir, Ctr}),
Ctr.
@@ -1188,7 +1212,50 @@ is_result(RC, true, _) ->
incr(TPid, Counter) ->
diameter_stats:incr(Counter, TPid, 1).
-%% rc_counter/3
+%% rcc/1
+
+rcc(#diameter_avp{name = 'Result-Code' = Name, value = V}) ->
+ {Name, head(V)};
+
+rcc(#diameter_avp{name = 'Experimental-Result', value = V}) ->
+ head(V).
+
+%% head/1
+
+head([V|_]) ->
+ V;
+head(V) ->
+ V.
+
+%% rcv/1
+
+rcv(#diameter_avp{name = N, value = V}) ->
+ rcv(N, head(V)).
+
+%% rcv/2
+
+rcv('Experimental-Result', {_,_,N}) ->
+ N;
+
+rcv('Result-Code', N) ->
+ N.
+
+%% get_result/4
+
+%% Message sent as binary: no checks or counting.
+get_result(_, _, _, #diameter_packet{header = undefined}) ->
+ false;
+
+get_result(Dir, MsgDict, Dict0, Pkt) ->
+ Avp = get_result(MsgDict, msg(Dir, Pkt)),
+ Hdr = Pkt#diameter_packet.header,
+ %% Exit on a missing result code or inappropriate value.
+ Avp == false
+ andalso ?LOGX(no_result_code, {MsgDict, Dir, Hdr}),
+ E = Hdr#diameter_header.is_error,
+ is_result(rcv(Avp), E, Dict0)
+ orelse ?LOGX(invalid_error_bit, {MsgDict, Dir, Hdr, Avp}),
+ Avp.
%% RFC 3588, 7.6:
%%
@@ -1196,46 +1263,29 @@ incr(TPid, Counter) ->
%% applications MUST include either one Result-Code AVP or one
%% Experimental-Result AVP.
-rc_counter(Dict, Dir, #diameter_packet{header = H,
- avps = As,
- msg = Msg})
+%% msg/2
+
+msg(Dir, #diameter_packet{header = H,
+ avps = As,
+ msg = Msg})
when Dir == recv; %% decoded incoming
Msg == undefined -> %% relayed outgoing
- rc_counter(Dict, [H|As]);
-
-rc_counter(Dict, _, #diameter_packet{msg = Msg}) ->
- rc_counter(Dict, Msg).
-
-rc_counter(Dict, Msg) ->
- rcc(get_result(Dict, Msg)).
-
-rcc(#diameter_avp{name = 'Result-Code' = Name, value = N} = A)
- when is_integer(N) ->
- {{Name, N}, N, A};
-
-rcc(#diameter_avp{name = 'Result-Code' = Name, value = [N|_]} = A)
- when is_integer(N) ->
- {{Name, N}, N, A};
+ [H|As];
-rcc(#diameter_avp{name = 'Experimental-Result', value = {_,_,N} = T} = A)
- when is_integer(N) ->
- {T, N, A};
-
-rcc(#diameter_avp{name = 'Experimental-Result', value = [{_,_,N} = T|_]} = A)
- when is_integer(N) ->
- {T, N, A};
-
-rcc(_) ->
- false.
+msg(_, #diameter_packet{msg = Msg}) ->
+ Msg.
%% get_result/2
get_result(Dict, Msg) ->
try
[throw(A) || N <- ['Result-Code', 'Experimental-Result'],
- #diameter_avp{} = A <- [get_avp(Dict, N, Msg)]]
+ #diameter_avp{} = A <- [get_avp(Dict, N, Msg)],
+ is_integer(catch rcv(A))],
+ false
catch
- #diameter_avp{} = A -> A
+ #diameter_avp{} = A ->
+ A
end.
x(T) ->
@@ -1359,7 +1409,7 @@ make_opts([T | _], _, _, _, _, _) ->
send_request({{TPid, _Caps} = TC, App}
= Transport,
- #{sequence := Mask}
+ #{sequence := Mask, traffic_counters := Count}
= SvcOpts,
Msg0,
CallOpts,
@@ -1375,9 +1425,15 @@ send_request({{TPid, _Caps} = TC, App}
SvcOpts,
ReqPkt),
eval_packet(EncPkt, Fs),
- T = send_R(ReqPkt, EncPkt, Transport, CallOpts, Caller, SvcName),
+ T = send_R(ReqPkt,
+ EncPkt,
+ Transport,
+ CallOpts,
+ Caller,
+ Count,
+ SvcName),
Ans = recv_answer(SvcName, App, CallOpts, T),
- handle_answer(SvcName, SvcOpts, App, Ans);
+ handle_answer(SvcName, Count, SvcOpts, App, Ans);
{discard, Reason} ->
{error, Reason};
discard ->
@@ -1520,6 +1576,7 @@ send_R(ReqPkt,
{{TPid, _Caps} = TC, #diameter_app{dictionary = AppDict}},
#options{timeout = Timeout},
{Pid, Ref},
+ Count,
SvcName) ->
Req = #request{ref = Ref,
caller = Pid,
@@ -1527,7 +1584,7 @@ send_R(ReqPkt,
peer = TC,
packet = ReqPkt},
- incr(send, EncPkt, TPid, AppDict),
+ Count andalso incr(send, EncPkt, TPid, AppDict),
{TRef, MRef} = zend_requezt(TPid, EncPkt, Req, SvcName, Timeout),
Pid ! Ref, %% tell caller a send has been attempted
{TRef, MRef, Req}.
@@ -1559,15 +1616,16 @@ failover(SvcName, App, Req, CallOpts) ->
CallOpts,
SvcName).
-%% handle_answer/4
+%% handle_answer/5
-handle_answer(SvcName, _, App, {error, Req, Reason}) ->
+handle_answer(SvcName, _, _, App, {error, Req, Reason}) ->
#request{packet = Pkt,
peer = {_TPid, _Caps} = TC}
= Req,
cb(App, handle_error, [Reason, msg(Pkt), SvcName, TC]);
handle_answer(SvcName,
+ Count,
SvcOpts,
#diameter_app{id = Id,
dictionary = AppDict,
@@ -1581,43 +1639,50 @@ handle_answer(SvcName,
#request{peer = {TPid, _}}
= Req,
- incr(recv, DecPkt, TPid, AppDict),
-
- AnsPkt = try
- incr_result(recv, DecPkt, TPid, {MsgDict, AppDict, Dict0})
- of
- _ -> DecPkt
- catch
- exit: {no_result_code, _} ->
- %% RFC 6733 requires one of Result-Code or
- %% Experimental-Result, but the decode will have
- %% detected a missing AVP. If both are optional in
- %% the dictionary then this isn't a decode error:
- %% just continue on.
- DecPkt;
- exit: {invalid_error_bit, {_, _, _, Avp}} ->
- #diameter_packet{errors = Es}
- = DecPkt,
- E = {5004, Avp},
- DecPkt#diameter_packet{errors = [E|Es]}
- end,
-
- handle_answer(AnsPkt, SvcName, App, AE, Req).
+ answer(answer(DecPkt, TPid, MsgDict, AppDict, Dict0, Count),
+ SvcName,
+ App,
+ AE,
+ Req).
+
+%% answer/6
+
+answer(DecPkt, TPid, MsgDict, AppDict, Dict0, Count) ->
+ Count andalso incr(recv, DecPkt, TPid, AppDict),
+ try get_result(recv, MsgDict, Dict0, DecPkt) of
+ Avp ->
+ Count andalso false /= Avp
+ andalso incr_result(recv, Avp, DecPkt, TPid, AppDict),
+ DecPkt
+ catch
+ exit: {no_result_code, _} ->
+ %% RFC 6733 requires one of Result-Code or
+ %% Experimental-Result, but the decode will have
+ %% detected a missing AVP. If both are optional in
+ %% the dictionary then this isn't a decode error:
+ %% just continue on.
+ DecPkt;
+ exit: {invalid_error_bit, {_, _, _, Avp}} ->
+ #diameter_packet{errors = Es}
+ = DecPkt,
+ E = {5004, Avp},
+ DecPkt#diameter_packet{errors = [E|Es]}
+ end.
-%% handle_answer/5
+%% answer/5
-handle_answer(#diameter_packet{errors = Es}
- = Pkt,
- SvcName,
- App,
- AE,
- #request{peer = {_TPid, _Caps} = TC,
- packet = P})
+answer(#diameter_packet{errors = Es}
+ = Pkt,
+ SvcName,
+ App,
+ AE,
+ #request{peer = {_TPid, _Caps} = TC,
+ packet = P})
when callback == AE;
[] == Es ->
cb(App, handle_answer, [Pkt, msg(P), SvcName, TC]);
-handle_answer(#diameter_packet{header = H}, SvcName, _, AE, _) ->
+answer(#diameter_packet{header = H}, SvcName, _, AE, _) ->
handle_error(H, SvcName, AE).
%% handle_error/3
@@ -1830,10 +1895,8 @@ get_destination(Dict, Msg) ->
[str(get_avp_value(Dict, D, Msg)) || D <- ['Destination-Realm',
'Destination-Host']].
-%% This is not entirely correct. The avp could have an arity 1, in
-%% which case an empty list is a DiameterIdentity of length 0 rather
-%% than the list of no values we treat it as by mapping to undefined.
-%% This behaviour is documented.
+%% A DiameterIdentity has length at least one, so an empty list is not
+%% a Realm/Host.
str([]) ->
undefined;
str(T) ->
@@ -1841,16 +1904,12 @@ str(T) ->
%% get_avp/3
%%
-%% Find an AVP in a message of one of three forms:
-%%
-%% - a message record (as generated from a .dia spec) or
-%% - a list of an atom message name followed by 2-tuple, avp name/value pairs.
-%% - a list of a #diameter_header{} followed by #diameter_avp{} records,
-%%
-%% In the first two forms a dictionary module is used at encode to
-%% identify the type of the AVP and its arity in the message in
-%% question. The third form allows messages to be sent as is, without
-%% a dictionary, which is needed in the case of relay agents, for one.
+%% Find an AVP in a message in one of the decoded formats, or as a
+%% header/avps list. There are only four AVPs that are extracted here:
+%% Result-Code and Experimental-Result in order when constructing
+%% counter keys, and Destination-Host/Realm when selecting a next-hop
+%% peer. Experimental-Result is the only of type Grouped, and is given
+%% special treatment in order to return the value as a record.
%% Messages will be header/avps list as a relay and the only AVP's we
%% look for are in the common dictionary. This is required since the
@@ -1859,37 +1918,58 @@ str(T) ->
get_avp(?RELAY, Name, Msg) ->
get_avp(?BASE, Name, Msg);
-%% Message as a header/avps list.
+%% Message as header/avps list.
get_avp(Dict, Name, [#diameter_header{} | Avps]) ->
try
- {Code, _, VId} = Dict:avp_header(Name),
- find_avp(Code, VId, Avps)
- of
- A ->
- (avp_decode(Dict, Name, ungroup(A)))#diameter_avp{name = Name}
+ {Code, _, Vid} = Dict:avp_header(Name),
+ A = find_avp(Code, Vid, Avps),
+ avp_decode(Dict, Name, ungroup(A))
catch
error: _ ->
undefined
end;
-%% Outgoing message as a name/values list.
+%% Message as name/values list ...
get_avp(_, Name, [_MsgName | Avps]) ->
- case lists:keyfind(Name, 1, Avps) of
+ case find(Name, Avps) of
{_, V} ->
- #diameter_avp{name = Name, value = V};
+ #diameter_avp{name = Name, value = value(Name, V)};
_ ->
undefined
end;
-%% Message is typically a record but not necessarily.
+%% ... or record.
get_avp(Dict, Name, Rec) ->
- try
- #diameter_avp{name = Name, value = Dict:'#get-'(Name, Rec)}
+ try Dict:'#get-'(Name, Rec) of
+ V ->
+ #diameter_avp{name = Name, value = value(Name, V)}
catch
error:_ ->
undefined
end.
+value('Experimental-Result' = N, #{'Vendor-Id' := Vid,
+ 'Experimental-Result-Code' := RC}) ->
+ {N, Vid, RC};
+value('Experimental-Result' = N, [{'Experimental-Result-Code', RC},
+ {'Vendor-Id', Vid}]) ->
+ {N, Vid, RC};
+value('Experimental-Result' = N, [{'Vendor-Id', Vid},
+ {'Experimental-Result-Code', RC}]) ->
+ {N, Vid, RC};
+value(_, V) ->
+ V.
+
+%% find/2
+
+find(Key, Map)
+ when is_map(Map) ->
+ maps:find(Key, Map);
+
+find(Key, List)
+ when is_list(List) ->
+ lists:keyfind(Key, 1, List).
+
%% get_avp_value/3
get_avp_value(Dict, Name, Msg) ->
@@ -1909,18 +1989,25 @@ ungroup(Avp) ->
%% avp_decode/3
+%% Ensure Experimental-Result is decoded as record, since this format
+%% is used for counter keys.
+avp_decode(Dict, 'Experimental-Result' = N, #diameter_avp{data = Bin}
+ = Avp)
+ when is_binary(Bin) ->
+ {V,_} = Dict:avp(decode, Bin, N, decode_opts(Dict)),
+ Avp#diameter_avp{name = N, value = V};
+
avp_decode(Dict, Name, #diameter_avp{value = undefined,
data = Bin}
- = Avp) ->
- try Dict:avp(decode, Bin, Name, decode_opts(Dict)) of
- V ->
- Avp#diameter_avp{value = V}
- catch
- error:_ ->
- Avp
- end;
-avp_decode(_, _, #diameter_avp{} = Avp) ->
- Avp.
+ = Avp)
+ when is_binary(Bin) ->
+ V = Dict:avp(decode, Bin, Name, decode_opts(Dict)),
+ Avp#diameter_avp{name = Name, value = V};
+
+avp_decode(_, Name, #diameter_avp{} = Avp) ->
+ Avp#diameter_avp{name = Name}.
+
+%% cb/3
cb(#diameter_app{module = [_|_] = M}, F, A) ->
eval(M, F, A).
@@ -1933,7 +2020,9 @@ choose(false, _, X) -> X.
%% Decode options sufficient for AVP extraction.
decode_opts(Dict) ->
- #{string_decode => false,
+ #{decode_format => record,
+ string_decode => false,
strict_mbit => false,
failed_avp => false,
- dictionary => Dict}.
+ module => Dict,
+ app_dictionary => Dict}.
diff --git a/lib/diameter/src/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl
index a63425d92a..43623334a9 100644
--- a/lib/diameter/src/base/diameter_watchdog.erl
+++ b/lib/diameter/src/base/diameter_watchdog.erl
@@ -72,12 +72,11 @@
restrict := boolean(),
suspect := non_neg_integer(), %% OKAY -> SUSPECT
okay := non_neg_integer()}, %% REOPEN -> OKAY
- codec :: #{string_decode := false,
+ codec :: #{decode_format := none,
+ string_decode := false,
strict_mbit := boolean(),
- failed_avp := false,
rfc := 3588 | 6733,
- ordered_encode := false,
- incoming_maxlen := diameter:message_length()},
+ ordered_encode := false},
shutdown = false :: boolean()}).
%% ---------------------------------------------------------------------------
@@ -135,13 +134,6 @@ i({Ack, T, Pid, {Opts,
putr(restart, {T, Opts, Svc, SvcOpts}), %% save seeing it in trace
putr(dwr, dwr(Caps)), %%
Nodes = restrict_nodes(Restrict),
- CodecKeys = [string_decode,
- strict_mbit,
- incoming_maxlen,
- spawn_opt,
- rfc,
- ordered_encode],
-
#watchdog{parent = Pid,
transport = start(T, Opts, SvcOpts, Nodes, Dict0, Svc),
tw = proplists:get_value(watchdog_timer,
@@ -149,14 +141,23 @@ i({Ack, T, Pid, {Opts,
?DEFAULT_TW_INIT),
receive_data = RecvData,
dictionary = Dict0,
- config =
- maps:without(CodecKeys,
- config(SvcOpts#{restrict => restrict(Nodes),
- suspect => 1,
- okay => 3},
- Opts)),
- codec = maps:with(CodecKeys, SvcOpts#{string_decode := false,
- ordered_encode => false})}.
+ config = maps:with([sequence,
+ restrict_connections,
+ restrict,
+ suspect,
+ okay],
+ config(SvcOpts#{restrict => restrict(Nodes),
+ suspect => 1,
+ okay => 3},
+ Opts)),
+ codec = maps:with([decode_format,
+ strict_mbit,
+ string_decode,
+ rfc,
+ ordered_encode],
+ SvcOpts#{decode_format := none,
+ string_decode := false,
+ ordered_encode => false})}.
wait(Ref, Pid) ->
receive
diff --git a/lib/diameter/src/compiler/diameter_codegen.erl b/lib/diameter/src/compiler/diameter_codegen.erl
index f56e4a5249..4e6fe32d69 100644
--- a/lib/diameter/src/compiler/diameter_codegen.erl
+++ b/lib/diameter/src/compiler/diameter_codegen.erl
@@ -21,15 +21,14 @@
-module(diameter_codegen).
%%
-%% This module generates erl/hrl files for encode/decode modules
-%% from the orddict parsed from a dictionary file (.dia) by
-%% diameter_dict_util. The generated code is simple (one-liners),
-%% the generated functions being called by code included iin the
-%% generated modules from diameter_gen.hrl. The orddict itself is
-%% returned by dict/0 in the generated module and diameter_dict_util
-%% calls this function when importing dictionaries as a consequence
-%% of @inherits sections. That is, @inherits introduces a dependency
-%% on the beam file of another dictionary.
+%% This module generates erl/hrl files for encode/decode modules from
+%% the orddict parsed from a dictionary file by diameter_dict_util.
+%% The generated code is simple (one-liners), and is called from
+%% diameter_gen. The orddict itself is returned by dict/0 in the
+%% generated module and diameter_dict_util calls this function when
+%% importing dictionaries as a consequence of @inherits sections. That
+%% is, @inherits introduces a dependency on the beam file of another
+%% dictionary.
%%
-export([from_dict/4,
diff --git a/lib/diameter/src/compiler/diameter_dict_util.erl b/lib/diameter/src/compiler/diameter_dict_util.erl
index f9f2b02e94..7b53e51cb6 100644
--- a/lib/diameter/src/compiler/diameter_dict_util.erl
+++ b/lib/diameter/src/compiler/diameter_dict_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -923,7 +923,7 @@ xa([D|_] = Ds, [[Qual, D, {_, Line, AvpName}] | Avps], Dict, Key, Name) ->
store_new({Key, {Name, AvpName}},
[Line, Qual, D],
Dict,
- [Name, Line],
+ [AvpName, Line],
avp_already_referenced),
Key,
Name);
diff --git a/lib/diameter/src/compiler/diameter_exprecs.erl b/lib/diameter/src/compiler/diameter_exprecs.erl
index 9a0cb6baf2..ded07f2353 100644
--- a/lib/diameter/src/compiler/diameter_exprecs.erl
+++ b/lib/diameter/src/compiler/diameter_exprecs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -110,9 +110,9 @@
%% parse_transform/2
parse_transform(Forms, _Options) ->
- Rs = [R || {attribute, _, record, R} <- Forms],
- Es = lists:append([E || {attribute, _, export_records, E} <- Forms]),
{H,T} = lists:splitwith(fun is_head/1, Forms),
+ Rs = [R || {attribute, _, record, R} <- H],
+ Es = lists:append([E || {attribute, _, export_records, E} <- H]),
H ++ [a_export(Es) | f_accessors(Es, Rs)] ++ T.
is_head(T) ->
diff --git a/lib/diameter/src/compiler/diameter_make.erl b/lib/diameter/src/compiler/diameter_make.erl
index eae40dbafd..03cfc03edc 100644
--- a/lib/diameter/src/compiler/diameter_make.erl
+++ b/lib/diameter/src/compiler/diameter_make.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -271,6 +271,6 @@ make(File, Opts, Dict, Mode) ->
try
diameter_codegen:from_dict(File, Dict, Opts, Mode)
catch
- error: Reason ->
- erlang:error({Reason, Mode, erlang:get_stacktrace()})
+ error: Reason: Stack ->
+ erlang:error({Reason, Mode, Stack})
end.
diff --git a/lib/diameter/src/diameter.app.src b/lib/diameter/src/diameter.app.src
index 9a6e47006b..18202f033e 100644
--- a/lib/diameter/src/diameter.app.src
+++ b/lib/diameter/src/diameter.app.src
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,14 +28,21 @@
]},
{registered, [%REGISTERED%]},
{applications, [
- {stdlib, "2.4"}, {kernel, "3.2"}%, {erts, "6.4"}
- %% {syntax-tools, "1.6,18"}
- %% {runtime-tools, "1.8.16"}
- %, {ssl, "6.0"}
+ stdlib,
+ kernel
+ %, ssl
+ %, syntax-tools
+ %, runtime-tools
]},
{env, []},
{mod, {diameter_app, []}},
{runtime_dependencies, [
+ "erts-10.0",
+ "stdlib-2.4",
+ "kernel-3.2",
+ "ssl-9.0"
+ %, "syntax-tools-1.6.18"
+ %, "runtime-tools-1.8.16"
]}
%%
%% Note that ssl is only required if configured on TCP transports,
diff --git a/lib/diameter/src/diameter.appup.src b/lib/diameter/src/diameter.appup.src
index 07d0389bfd..51830f5276 100644
--- a/lib/diameter/src/diameter.appup.src
+++ b/lib/diameter/src/diameter.appup.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -52,7 +52,14 @@
{"1.11.2", [{restart_application, diameter}]}, %% 18.3
{"1.12", [{restart_application, diameter}]}, %% 19.0
{"1.12.1", [{restart_application, diameter}]}, %% 19.1
- {"1.12.2", [{restart_application, diameter}]} %% 19.3
+ {"1.12.2", [{restart_application, diameter}]}, %% 19.3
+ {"2.0", [{restart_application, diameter}]}, %% 20.0
+ {"2.1", [{restart_application, diameter}]}, %% 20.1
+ {"2.1.1", [{restart_application, diameter}]}, %% 20.1.2
+ {"2.1.2", [{restart_application, diameter}]}, %% 20.1.3
+ {"2.1.3", [{restart_application, diameter}]}, %% 20.2
+ {"2.1.4", [{restart_application, diameter}]}, %% 20.3
+ {"2.1.5", [{update, diameter_peer_fsm}]} %% 21.0
],
[
{"0.9", [{restart_application, diameter}]},
@@ -86,6 +93,13 @@
{"1.11.2", [{restart_application, diameter}]},
{"1.12", [{restart_application, diameter}]},
{"1.12.1", [{restart_application, diameter}]},
- {"1.12.2", [{restart_application, diameter}]}
+ {"1.12.2", [{restart_application, diameter}]},
+ {"2.0", [{restart_application, diameter}]},
+ {"2.1", [{restart_application, diameter}]},
+ {"2.1.1", [{restart_application, diameter}]},
+ {"2.1.2", [{restart_application, diameter}]},
+ {"2.1.3", [{restart_application, diameter}]},
+ {"2.1.4", [{restart_application, diameter}]},
+ {"2.1.5", [{update, diameter_peer_fsm}]}
]
}.
diff --git a/lib/diameter/src/dict/doic_rfc7683.dia b/lib/diameter/src/dict/doic_rfc7683.dia
new file mode 100644
index 0000000000..2b7804115e
--- /dev/null
+++ b/lib/diameter/src/dict/doic_rfc7683.dia
@@ -0,0 +1,50 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Copyright Ericsson AB 2017. All Rights Reserved.
+;;
+;; Licensed under the Apache License, Version 2.0 (the "License");
+;; you may not use this file except in compliance with the License.
+;; You may obtain a copy of the License at
+;;
+;; http://www.apache.org/licenses/LICENSE-2.0
+;;
+;; Unless required by applicable law or agreed to in writing, software
+;; distributed under the License is distributed on an "AS IS" BASIS,
+;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;; See the License for the specific language governing permissions and
+;; limitations under the License.
+;;
+;; %CopyrightEnd%
+;;
+
+@name diameter_gen_doic_rfc7683
+@prefix diameter_doic
+
+@avp_types
+
+ OC-Supported-Features 621 Grouped -
+ OC-Feature-Vector 622 Unsigned64 -
+ OC-OLR 623 Grouped -
+ OC-Sequence-Number 624 Unsigned64 -
+ OC-Validity-Duration 625 Unsigned32 -
+ OC-Report-Type 626 Enumerated -
+ OC-Reduction-Percentage 627 Unsigned32 -
+
+@enum OC-Report-Type
+
+ HOST_REPORT 0
+ REALM_REPORT 1
+
+@grouped
+
+ OC-Supported-Features ::= < AVP Header: 621 >
+ [ OC-Feature-Vector ]
+ * [ AVP ]
+
+ OC-OLR ::= < AVP Header: 623 >
+ < OC-Sequence-Number >
+ < OC-Report-Type >
+ [ OC-Reduction-Percentage ]
+ [ OC-Validity-Duration ]
+ * [ AVP ]
diff --git a/lib/diameter/src/modules.mk b/lib/diameter/src/modules.mk
index bb3b234d20..bb86de016a 100644
--- a/lib/diameter/src/modules.mk
+++ b/lib/diameter/src/modules.mk
@@ -24,6 +24,7 @@ DICTS = \
base_rfc6733 \
base_accounting \
acct_rfc6733 \
+ doic_rfc7683 \
relay
# The yecc grammar for the dictionary parser.
diff --git a/lib/diameter/src/transport/diameter_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl
index 6a9f1f940b..64b34da690 100644
--- a/lib/diameter/src/transport/diameter_sctp.erl
+++ b/lib/diameter/src/transport/diameter_sctp.erl
@@ -79,7 +79,7 @@
-type option() :: {sender, boolean()}
| sender
| {packet, boolean() | raw}
- | {message_cb, false | diameter:evaluable()}.
+ | {message_cb, false | diameter:eval()}.
-type uint() :: non_neg_integer().
@@ -102,9 +102,12 @@
streams :: {uint(), uint()} %% {InStream, OutStream} counts
| undefined,
os = 0 :: uint(), %% next output stream
+ rotate = 1 :: boolean() | 0 | 1, %% rotate os?
+ unordered = false :: boolean() %% always send unordered?
+ | pos_integer(),% or if =< N outbound streams?
packet = true :: boolean() %% legacy transport_data?
| raw,
- message_cb = false :: false | diameter:evaluable(),
+ message_cb = false :: false | diameter:eval(),
send = false :: pid() | boolean()}). %% sending process
%% Monitor process state.
@@ -112,7 +115,7 @@
{transport :: pid(),
ack = false :: boolean(),
socket :: gen_sctp:sctp_socket(),
- assoc_id :: gen_sctp:assoc_id()}). %% next output stream
+ assoc_id :: gen_sctp:assoc_id()}).
%% Listener process state.
-record(listener,
@@ -120,7 +123,7 @@
socket :: gen_sctp:sctp_socket(),
service :: pid(), %% service process
pending = {0, queue:new()},
- opts :: [[match()] | boolean() | diameter:evaluable()]}).
+ opts :: [[match()] | boolean() | diameter:eval()]}).
%% Field pending implements two queues: the first of transport-to-be
%% processes to which an association has been assigned but for which
%% diameter hasn't yet spawned a transport process, a short-lived
@@ -156,12 +159,7 @@ start(T, Svc, Opts)
= Svc,
diameter_sctp_sup:start(), %% start supervisors on demand
Addrs = Caps#diameter_caps.host_ip_address,
- s(T, Addrs, Pid, lists:map(fun ip/1, Opts)).
-
-ip({ifaddr, A}) ->
- {ip, A};
-ip(T) ->
- T.
+ s(T, Addrs, Pid, Opts).
%% A listener spawns transports either as a consequence of this call
%% when there is not yet an association to assign it, or at comm_up on
@@ -246,8 +244,11 @@ i(#monitor{transport = TPid} = S) ->
i({listen, Ref, {Opts, SvcPid, Addrs}}) ->
monitor(process, SvcPid),
[_] = diameter_config:subscribe(Ref, transport), %% assert existence
- {Split, Rest}
- = proplists:split(Opts, [accept, packet, sender, message_cb]),
+ {Split, Rest} = proplists:split(Opts, [accept,
+ packet,
+ sender,
+ message_cb,
+ unordered]),
OwnOpts = lists:append(Split),
{LAs, Sock} = AS = open(Addrs, Rest, ?DEFAULT_PORT),
ok = gen_sctp:listen(Sock, true),
@@ -259,12 +260,16 @@ i({listen, Ref, {Opts, SvcPid, Addrs}}) ->
opts = [[[M] || {accept, M} <- OwnOpts],
proplists:get_value(packet, OwnOpts, true)
| [proplists:get_value(K, OwnOpts, false)
- || K <- [sender, message_cb]]]};
+ || K <- [sender, message_cb, unordered]]]};
%% A connecting transport.
i({connect, Pid, Opts, Addrs, Ref}) ->
- {[Ps | Split], Rest}
- = proplists:split(Opts, [rport, raddr, packet, sender, message_cb]),
+ {[Ps | Split], Rest} = proplists:split(Opts, [rport,
+ raddr,
+ packet,
+ sender,
+ message_cb,
+ unordered]),
OwnOpts = lists:append(Split),
CB = proplists:get_value(message_cb, OwnOpts, false),
false == CB orelse (Pid ! {diameter, ack}),
@@ -278,6 +283,7 @@ i({connect, Pid, Opts, Addrs, Ref}) ->
mode = {connect, connect(Sock, RAs, RP, [])},
socket = Sock,
message_cb = CB,
+ unordered = proplists:get_value(ordered, OwnOpts, false),
packet = proplists:get_value(packet, OwnOpts, true),
send = proplists:get_value(sender, OwnOpts, false)};
@@ -315,12 +321,13 @@ i({K, Ref}, #transport{mode = {accept, _}} = S) ->
S#transport{parent = Pid};
{K, T, Opts} when K == peeloff -> %% association
{sctp, Sock, _RA, _RP, _Data} = T,
- [Matches, Packet, Sender, CB] = Opts,
+ [Matches, Packet, Sender, CB, Unordered] = Opts,
ok = accept_peer(Sock, Matches),
demonitor(Ref, [flush]),
false == CB orelse (S#transport.parent ! {diameter, ack}),
t(T, S#transport{socket = Sock,
message_cb = CB,
+ unordered = Unordered,
packet = Packet,
send = Sender});
accept_timeout = T ->
@@ -354,23 +361,35 @@ l([], Ref, T) ->
%% open/3
open(Addrs, Opts, PortNr) ->
- {LAs, Os} = addrs(Addrs, Opts),
- {LAs, case gen_sctp:open(gen_opts(portnr(Os, PortNr))) of
- {ok, Sock} ->
- Sock;
- {error, Reason} ->
- x({open, Reason})
- end}.
+ case gen_sctp:open(gen_opts(portnr(addrs(Addrs, Opts), PortNr))) of
+ {ok, Sock} ->
+ {addrs(Sock), Sock};
+ {error, Reason} ->
+ x({open, Reason})
+ end.
addrs(Addrs, Opts) ->
- case proplists:split(Opts, [ip]) of
- {[[]], _} ->
- {Addrs, Opts ++ [{ip, A} || A <- Addrs]};
- {[As], Os} ->
- LAs = [diameter_lib:ipaddr(A) || {ip, A} <- As],
- {LAs, Os ++ [{ip, A} || A <- LAs]}
+ case lists:mapfoldl(fun ipaddr/2, false, Opts) of
+ {Os, true} ->
+ Os;
+ {_, false} ->
+ Opts ++ [{ip, A} || A <- Addrs]
end.
+ipaddr({K,A}, _)
+ when K == ifaddr;
+ K == ip ->
+ {{ip, ipaddr(A)}, true};
+ipaddr(T, B) ->
+ {T, B}.
+
+ipaddr(A)
+ when A == loopback;
+ A == any ->
+ A;
+ipaddr(A) ->
+ diameter_lib:ipaddr(A).
+
portnr(Opts, PortNr) ->
case proplists:get_value(port, Opts) of
undefined ->
@@ -379,6 +398,14 @@ portnr(Opts, PortNr) ->
Opts
end.
+addrs(Sock) ->
+ case inet:socknames(Sock) of
+ {ok, As} ->
+ [A || {A,_} <- As];
+ {error, Reason} ->
+ x({socknames, Reason})
+ end.
+
%% x/1
x(Reason) ->
@@ -565,7 +592,7 @@ transition(Msg, S)
%% Deferred actions from a message_cb.
transition({actions, Dir, Acts}, S) ->
- actions(Acts, Dir, S);
+ setopts(ok, actions(Acts, Dir, S));
%% Request to close the transport connection.
transition({diameter, {close, Pid}}, #transport{parent = Pid}) ->
@@ -677,11 +704,16 @@ send(#diameter_packet{transport_data = {outstream, SId}}
= S) ->
send(SId rem OS, Msg, S);
-%% ... or not: rotate through all streams.
-send(Msg, #transport{streams = {_, OS},
+%% ... or not: rotate when sending on multiple streams ...
+send(Msg, #transport{rotate = true,
+ streams = {_, OS},
os = N}
= S) ->
- send(N, Msg, S#transport{os = (N + 1) rem OS}).
+ send(N, Msg, S#transport{os = (N + 1) rem OS});
+
+%% ... or send on the only stream available.
+send(Msg, S) ->
+ send(0, Msg, S).
%% send/3
@@ -749,7 +781,7 @@ recv({[#sctp_sndrcvinfo{assoc_id = Id}], _Bin}
%% Inbound Diameter message.
recv({[#sctp_sndrcvinfo{}], Bin} = Msg, S)
when is_binary(Bin) ->
- message(recv, Msg, S);
+ message(recv, Msg, recv(S));
recv({_, #sctp_shutdown_event{}}, _) ->
stop;
@@ -769,6 +801,41 @@ recv({_, #sctp_paddr_change{}}, _) ->
recv({_, #sctp_pdapi_event{}}, _) ->
ok.
+%% recv/1
+%%
+%% Start sending unordered after the second reception, so that an
+%% outgoing CER/CEA will arrive at the peer before another request.
+
+recv(#transport{rotate = B} = S)
+ when is_boolean(B) ->
+ S;
+
+recv(#transport{rotate = 0,
+ streams = {_,OS},
+ socket = Sock,
+ unordered = B}
+ = S) ->
+ ok = unordered(Sock, OS, B),
+ S#transport{rotate = 1 < OS};
+
+recv(#transport{rotate = N} = S) ->
+ S#transport{rotate = N-1}.
+
+%% unordered/3
+
+unordered(Sock, OS, B)
+ when B;
+ is_integer(B), OS =< B ->
+ inet:setopts(Sock, [{sctp_default_send_param,
+ #sctp_sndrcvinfo{flags = [unordered]}}]);
+
+unordered(_, OS, B)
+ when not B;
+ is_integer(B), B < OS ->
+ ok.
+
+%% publish/4
+
publish(T, Ref, Id, Sock) ->
true = diameter_reg:add_new({?MODULE, T, {Ref, {Id, Sock}}}),
putr(?INFO_KEY, {gen_sctp, Sock}). %% for info/1
diff --git a/lib/diameter/src/transport/diameter_tcp.erl b/lib/diameter/src/transport/diameter_tcp.erl
index a2f393d5d4..da059fa7d6 100644
--- a/lib/diameter/src/transport/diameter_tcp.erl
+++ b/lib/diameter/src/transport/diameter_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -87,8 +87,7 @@
module :: module() | undefined}).
-type length() :: 0..16#FFFFFF. %% message length from Diameter header
--type size() :: non_neg_integer(). %% accumulated binary size
--type frag() :: {length(), size(), binary(), list(binary())}
+-type frag() :: maybe_improper_list(length(), binary())
| binary().
-type connect_option() :: {raddr, inet:ip_address()}
@@ -111,7 +110,7 @@
-type option() :: {port, non_neg_integer()}
| {sender, boolean()}
| sender
- | {message_cb, false | diameter:evaluable()}
+ | {message_cb, false | diameter:eval()}
| {fragment_timer, 0..16#FFFFFFFF}.
%% Accepting/connecting transport process state.
@@ -126,7 +125,7 @@
timeout :: infinity | 0..16#FFFFFFFF, %% fragment timeout
tref = false :: false | reference(), %% fragment timer reference
flush = false :: boolean(), %% flush fragment at timeout?
- message_cb :: false | diameter:evaluable(),
+ message_cb :: false | diameter:eval(),
send :: pid() | false}). %% sending process
%% The usual transport using gen_tcp can be replaced by anything
@@ -143,8 +142,7 @@
-> {ok, pid(), [inet:ip_address()]}
when Ref :: diameter:transport_ref();
({connect, Ref}, #diameter_service{}, [connect_option()])
- -> {ok, pid(), [inet:ip_address()]}
- | {ok, pid()}
+ -> {ok, pid()}
when Ref :: diameter:transport_ref().
start({T, Ref}, Svc, Opts) ->
@@ -259,22 +257,14 @@ i(#monitor{parent = Pid, transport = TPid} = S) ->
i({listen, Ref, {Mod, Opts, Addrs}}) ->
[_] = diameter_config:subscribe(Ref, transport), %% assert existence
- {[LA, LP], Rest} = proplists:split(Opts, [ip, port]),
- LAddrOpt = get_addr(LA, Addrs),
- LPort = get_port(LP),
- {ok, LSock} = Mod:listen(LPort, gen_opts(LAddrOpt, Rest)),
- LAddr = laddr(LAddrOpt, Mod, LSock),
+ {[LP], Rest} = proplists:split(Opts, [port]),
+ {ok, LSock} = Mod:listen(get_port(LP), gen_opts(Addrs, Rest)),
+ {ok, {LAddr, _}} = sockname(Mod, LSock),
true = diameter_reg:add_new({?MODULE, listener, {Ref, {LAddr, LSock}}}),
proc_lib:init_ack({ok, self(), {LAddr, LSock}}),
#listener{socket = LSock,
module = Mod}.
-laddr([], Mod, Sock) ->
- {ok, {Addr, _Port}} = sockname(Mod, Sock),
- Addr;
-laddr([{ip, Addr}], _, _) ->
- Addr.
-
ssl_opts([]) ->
false;
ssl_opts([{ssl_options, true}]) ->
@@ -309,24 +299,16 @@ init(accept = T, Ref, Mod, Pid, Opts, Addrs, SvcPid) ->
Sock;
init(connect = T, Ref, Mod, Pid, Opts, Addrs, _SvcPid) ->
- {[LA, RA, RP], Rest} = proplists:split(Opts, [ip, raddr, rport]),
- LAddrOpt = get_addr(LA, Addrs),
+ {[RA, RP], Rest} = proplists:split(Opts, [raddr, rport]),
RAddr = get_addr(RA),
RPort = get_port(RP),
- proc_lib:init_ack(init_rc(LAddrOpt)),
- Sock = ok(connect(Mod, RAddr, RPort, gen_opts(LAddrOpt, Rest))),
+ proc_lib:init_ack({ok, self()}),
+ Sock = ok(connect(Mod, RAddr, RPort, gen_opts(Addrs, Rest))),
publish(Mod, T, Ref, Sock),
- up(Pid, {RAddr, RPort}, LAddrOpt, Mod, Sock),
+ up(Pid, {RAddr, RPort}, Mod, Sock),
Sock.
-init_rc([{ip, Addr}]) ->
- {ok, self(), [Addr]};
-init_rc([]) ->
- {ok, self()}.
-
-up(Pid, Remote, [{ip, _Addr}], _, _) ->
- diameter_peer:up(Pid, Remote);
-up(Pid, Remote, [], Mod, Sock) ->
+up(Pid, Remote, Mod, Sock) ->
{Addr, _Port} = ok(sockname(Mod, Sock)),
diameter_peer:up(Pid, Remote, [Addr]).
@@ -383,25 +365,41 @@ l([{{?MODULE, listener, {_, AS}}, LPid}], _, _) ->
l([], Ref, T) ->
diameter_tcp_sup:start_child({listen, Ref, T}).
-%% get_addr/1
+%% addrs/2
+%%
+%% Take the first address from the service if several are specified
+%% and not address is configured.
+
+addrs(Addrs, Opts) ->
+ case lists:mapfoldr(fun ipaddr/2, [], Opts) of
+ {Os, [_]} ->
+ Os;
+ {_, []} ->
+ Opts ++ [{ip, A} || [A|_] <- [Addrs]];
+ {_, As} ->
+ ?ERROR({invalid_addrs, As, Addrs})
+ end.
-get_addr(As) ->
- diameter_lib:ipaddr(addr(As, [])).
+ipaddr({K,A}, As)
+ when K == ifaddr;
+ K == ip ->
+ {{ip, ipaddr(A)}, [A | As]};
+ipaddr(T, B) ->
+ {T, B}.
-%% get_addr/2
+ipaddr(A)
+ when A == loopback;
+ A == any ->
+ A;
+ipaddr(A) ->
+ diameter_lib:ipaddr(A).
-get_addr([], []) ->
- [];
-get_addr(As, Def) ->
- [{ip, diameter_lib:ipaddr(addr(As, Def))}].
+%% get_addr/1
-%% Take the first address from the service if several are unspecified.
-addr([], [Addr | _]) ->
- Addr;
-addr([{_, Addr}], _) ->
- Addr;
-addr(As, Addrs) ->
- ?ERROR({invalid_addrs, As, Addrs}).
+get_addr([{_, Addr}]) ->
+ diameter_lib:ipaddr(Addr);
+get_addr(Addrs) ->
+ ?ERROR({invalid_addrs, Addrs}).
%% get_port/1
@@ -414,10 +412,15 @@ get_port(Ps) ->
%% gen_opts/2
-gen_opts(LAddrOpt, Opts) ->
+gen_opts(Addrs, Opts) ->
+ gen_opts(addrs(Addrs, Opts)).
+
+%% gen_opts/1
+
+gen_opts(Opts) ->
{L,_} = proplists:split(Opts, [binary, packet, active]),
[[],[],[]] == L orelse ?ERROR({reserved_options, Opts}),
- [binary, {packet, 0}, {active, false}] ++ LAddrOpt ++ Opts.
+ [binary, {packet, 0}, {active, false} | Opts].
%% ---------------------------------------------------------------------------
%% # ports/1
@@ -599,11 +602,12 @@ t(T,S) ->
%% Incoming packets.
transition({P, Sock, Bin}, #transport{socket = Sock,
- ssl = B}
+ ssl = B,
+ frag = Frag}
= S)
when P == ssl, true == B;
P == tcp ->
- recv(Bin, S#transport{active = false});
+ recv(acc(Frag, Bin), S);
%% Capabilties exchange has decided on whether or not to run over TLS.
transition({diameter, {tls, Ref, Type, B}}, #transport{parent = Pid}
@@ -640,7 +644,7 @@ transition(Msg, S)
%% Deferred actions from a message_cb.
transition({actions, Dir, Acts}, S) ->
- actions(Acts, Dir, S);
+ setopts(actions(Acts, Dir, S));
%% Request to close the transport connection.
transition({diameter, {close, Pid}}, #transport{parent = Pid,
@@ -712,7 +716,7 @@ tls_handshake(_, false, S) ->
tls(connect, Sock, Opts) ->
ssl:connect(Sock, Opts);
tls(accept, Sock, Opts) ->
- ssl:ssl_accept(Sock, Opts).
+ ssl:handshake(Sock, Opts). %% assume no handshake option
%% recv/2
%%
@@ -720,86 +724,77 @@ tls(accept, Sock, Opts) ->
%% using Nagle.
%% Receive packets until a full message is received,
-recv(Bin, #transport{frag = Head} = S) ->
- case rcv(Head, Bin) of
- {Msg, B} -> %% have a complete message ...
- message(recv, Msg, S#transport{frag = B});
- Frag -> %% read more on the socket
- start_fragment_timer(setopts(S#transport{frag = Frag,
- flush = false}))
- end.
-%% rcv/2
+recv({Msg, Rest}, S) -> %% have a complete message ...
+ recv(acc(Rest), message(recv, Msg, S));
+
+recv(Frag, #transport{recv = B,
+ socket = Sock,
+ module = M}
+ = S) -> %% or not
+ B andalso setopts(M, Sock),
+ start_fragment_timer(S#transport{frag = Frag,
+ flush = false,
+ active = B}).
-%% No previous fragment.
-rcv(<<>>, Bin) ->
- rcv(Bin);
+%% acc/2
-%% Not even the first four bytes of the header.
-rcv(Head, Bin)
- when is_binary(Head) ->
- rcv(<<Head/binary, Bin/binary>>);
+%% Know how many bytes to extract.
+acc([Len | Acc], Bin) ->
+ acc1(Len, <<Acc/binary, Bin/binary>>);
-%% Or enough to know how many bytes to extract.
-rcv({Len, N, Head, Acc}, Bin) ->
- rcv(Len, N + size(Bin), Head, [Bin | Acc]).
+%% Or not.
+acc(Head, Bin) ->
+ acc(<<Head/binary, Bin/binary>>).
-%% rcv/4
+%% acc1/3
%% Extract a message for which we have all bytes.
-rcv(Len, N, Head, Acc)
- when Len =< N ->
- recv1(Len, bin(Head, Acc));
+acc1(Len, Bin)
+ when Len =< byte_size(Bin) ->
+ split_binary(Bin, Len);
%% Wait for more packets.
-rcv(Len, N, Head, Acc) ->
- {Len, N, Head, Acc}.
-
-%% rcv/1
-
-%% Nothing left.
-rcv(<<>> = Bin) ->
- Bin;
-
-%% The Message Length isn't even sufficient for a header. Chances are
-%% things will go south from here but if we're lucky then the bytes we
-%% have extend to an intended message boundary and we can recover by
-%% simply receiving them. Make it so.
-rcv(<<_:1/binary, Len:24, _/binary>> = Bin)
- when Len < 20 ->
- {Bin, <<>>};
-
-%% Enough bytes to extract a message.
-rcv(<<_:1/binary, Len:24, _/binary>> = Bin)
- when Len =< size(Bin) ->
- recv1(Len, Bin);
-
-%% Or not: wait for more packets.
-rcv(<<_:1/binary, Len:24, _/binary>> = Head) ->
- {Len, size(Head), Head, []};
+acc1(Len, Bin) ->
+ [Len | Bin].
+
+%% acc/1
+
+%% Don't match on Bin since this results in it being copied at the
+%% next append according to the Efficiency Guide. This is also the
+%% reason that the Len is extracted and maintained when accumulating
+%% messages. The simplest implementation is just to accumulate a
+%% binary and match <<_, Len:24, _/binary>> each time the length is
+%% required, but the performance of this decays quadratically with the
+%% message length, since the binary is then copied with each append of
+%% additional bytes from gen_tcp.
+
+acc(Bin)
+ when 3 < byte_size(Bin) ->
+ {Head, _} = split_binary(Bin, 4),
+ [_,A,B,C] = binary_to_list(Head),
+ Len = (A bsl 16) bor (B bsl 8) bor C,
+ if Len < 20 ->
+ %% Message length isn't sufficient for a Diameter Header.
+ %% Chances are things will go south from here but if we're
+ %% lucky then the bytes we have extend to an intended
+ %% message boundary and we can recover by simply receiving
+ %% them. Make it so.
+ {Bin, <<>>};
+ true ->
+ acc1(Len, Bin)
+ end;
%% Not even 4 bytes yet.
-rcv(Head) ->
- Head.
-
-%% recv1/2
-
-recv1(Len, Bin) ->
- <<Msg:Len/binary, Rest/binary>> = Bin,
- {Msg, Rest}.
-
-%% bin/2
-
-bin(Head, Acc) ->
- list_to_binary([Head | lists:reverse(Acc)]).
+acc(Bin) ->
+ Bin.
%% bin/1
-bin({_, _, Head, Acc}) ->
- bin(Head, Acc);
+bin([_ | Bin]) ->
+ Bin;
-bin(Bin)
- when is_binary(Bin) ->
+bin(Bin) ->
Bin.
%% flush/1
@@ -844,7 +839,7 @@ start_fragment_timer(#transport{timeout = Tmo} = S) ->
accept(ssl, LSock) ->
case ssl:transport_accept(LSock) of
{ok, Sock} ->
- {ssl:ssl_accept(Sock), Sock};
+ ssl:handshake(Sock);
{error, _} = No ->
No
end;
@@ -911,14 +906,20 @@ setopts(#transport{socket = Sock,
module = M}
= S)
when B, not A ->
- case setopts(M, Sock, [{active, once}]) of
- ok -> S#transport{active = true};
- X -> x({setopts, Sock, M, X}) %% possibly on peer disconnect
- end;
+ setopts(M, Sock),
+ S#transport{active = true};
setopts(S) ->
S.
+%% setopts/2
+
+setopts(M, Sock) ->
+ case setopts(M, Sock, [{active, once}]) of
+ ok -> ok;
+ X -> x({setopts, Sock, M, X}) %% possibly on peer disconnect
+ end.
+
%% portnr/2
portnr(gen_tcp, Sock) ->
@@ -988,7 +989,7 @@ message(ack, _, #transport{message_cb = false} = S) ->
S;
message(Dir, Msg, #transport{message_cb = CB} = S) ->
- recv(<<>>, actions(cb(CB, Dir, Msg), Dir, S)).
+ setopts(actions(cb(CB, Dir, Msg), Dir, S)).
%% actions/3
diff --git a/lib/diameter/test/diameter_app_SUITE.erl b/lib/diameter/test/diameter_app_SUITE.erl
index 71256020f5..ef4a28d3f4 100644
--- a/lib/diameter/test/diameter_app_SUITE.erl
+++ b/lib/diameter/test/diameter_app_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -208,9 +208,9 @@ xref(Config) ->
CTmods = CTmods -- Mods,
%% Ensure that runtime modules only call other runtime modules, or
- %% applications declared as in runtime_dependencies in the app
- %% file. Note that the declared application versions are ignored
- %% since we only know what we can see now.
+ %% applications declared in runtime_dependencies in the app file.
+ %% The declared application versions are ignored since we only
+ %% know what we see now.
[] = lists:filter(fun(M) -> not lists:member(app(M), Deps) end,
RTdeps -- Mods).
@@ -261,8 +261,12 @@ app(Mod) ->
case code:which(Mod) of
preloaded ->
"erts";
+ Reason when is_atom(Reason) ->
+ error({Reason, Mod});
Path ->
- unversion(lists:nth(3, lists:reverse(filename:split(Path))))
+ %% match to identify an unexpectedly short path
+ {_, _, [_,_,_|_] = Split} = {Mod, Path, filename:split(Path)},
+ unversion(lists:nth(3, lists:reverse(Split)))
end.
add_application(XRef, App) ->
diff --git a/lib/diameter/test/diameter_codec_SUITE.erl b/lib/diameter/test/diameter_codec_SUITE.erl
index 9f08f49f9f..17112794e4 100644
--- a/lib/diameter/test/diameter_codec_SUITE.erl
+++ b/lib/diameter/test/diameter_codec_SUITE.erl
@@ -291,7 +291,8 @@ recode(Msg, Dict) ->
recode(#diameter_packet{msg = Msg}, Dict).
opts(Mod) ->
- #{dictionary => Mod,
+ #{app_dictionary => Mod,
+ decode_format => record,
string_decode => false,
strict_mbit => true,
rfc => 6733,
diff --git a/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl b/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
index 700910878c..c6bba75f09 100644
--- a/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
+++ b/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
@@ -77,7 +77,8 @@ dec('BR', #diameter_packet
ok.
opts(Mod) ->
- #{dictionary => Mod,
+ #{app_dictionary => Mod,
+ decode_format => record,
string_decode => true,
strict_mbit => true,
rfc => 6733,
diff --git a/lib/diameter/test/diameter_codec_test.erl b/lib/diameter/test/diameter_codec_test.erl
index b548f85cb8..70e910ffa6 100644
--- a/lib/diameter/test/diameter_codec_test.erl
+++ b/lib/diameter/test/diameter_codec_test.erl
@@ -44,7 +44,8 @@ base() ->
[] = run([[fun base/1, T] || T <- [zero, decode]]).
gen(Mod) ->
- Fs = [{Mod, F, []} || F <- [name, id, vendor_id, vendor_name]],
+ Fs = [{Mod, F, []} || Mod /= diameter_gen_doic_rfc7683,
+ F <- [name, id, vendor_id, vendor_name]],
[] = run(Fs ++ [[fun gen/2, Mod, T] || T <- [messages,
command_codes,
avp_types,
@@ -216,10 +217,11 @@ avp(Mod, encode = X, V, Name, _) ->
opts(Mod) ->
(opts())#{module => Mod,
- dictionary => Mod}.
+ app_dictionary => Mod}.
opts() ->
- #{string_decode => true,
+ #{decode_format => record,
+ string_decode => true,
strict_mbit => true,
rfc => 6733,
failed_avp => false}.
diff --git a/lib/diameter/test/diameter_event_SUITE.erl b/lib/diameter/test/diameter_event_SUITE.erl
index 57d3427037..a291dde6be 100644
--- a/lib/diameter/test/diameter_event_SUITE.erl
+++ b/lib/diameter/test/diameter_event_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -63,7 +63,8 @@
{'Host-IP-Address', [?ADDR]},
{'Vendor-Id', 12345},
{'Product-Name', "OTP/diameter"},
- {'Acct-Application-Id', [D:id() || D <- Dicts]}
+ {'Acct-Application-Id', [D:id() || D <- Dicts]},
+ {decode_format, map}
| [{application, [{dictionary, D},
{module, #diameter_callback{}}]}
|| D <- Dicts]]).
@@ -111,7 +112,8 @@ up(Config) ->
{Svc, Ref} = connect(Config, [{connect_timer, 5000},
{watchdog_timer, 15000}]),
start = event(Svc),
- {up, Ref, {TPid, Caps}, Cfg, #diameter_packet{}} = event(Svc),
+ {up, Ref, {TPid, Caps}, Cfg, #diameter_packet{msg = M}} = event(Svc),
+ ['CEA' | #{}] = M, %% assert
{watchdog, Ref, _, {initial, okay}, _} = event(Svc),
%% Kill the transport process and see that the connection is
%% reestablished after a watchdog timeout, not after connect_timer
@@ -131,8 +133,9 @@ down(Config) ->
{connect_timer, 5000},
{watchdog_timer, 20000}]),
start = event(Svc),
- {closed, Ref, {'CEA', ?NO_COMMON_APP, _, #diameter_packet{}}, _}
+ {closed, Ref, {'CEA', ?NO_COMMON_APP, _, #diameter_packet{msg = M}}, _}
= event(Svc),
+ ['CEA' | #{}] = M, %% assert
{reconnect, Ref, _} = event(Svc, 4000, 10000).
%% Connect with matching capabilities but have the server delay its
diff --git a/lib/diameter/test/diameter_examples_SUITE.erl b/lib/diameter/test/diameter_examples_SUITE.erl
index eb99f10fe6..ee44ed8dc9 100644
--- a/lib/diameter/test/diameter_examples_SUITE.erl
+++ b/lib/diameter/test/diameter_examples_SUITE.erl
@@ -344,7 +344,7 @@ top(Dir, LibDir) ->
start({server, Prot}) ->
ok = diameter:start(),
ok = server:start(),
- {ok, Ref} = server:listen(Prot),
+ {ok, Ref} = server:listen({Prot, any, 3868}),
[_] = ?util:lport(Prot, Ref),
ok;
@@ -352,7 +352,7 @@ start({client = Svc, Prot}) ->
ok = diameter:start(),
true = diameter:subscribe(Svc),
ok = client:start(),
- {ok, Ref} = client:connect(Prot),
+ {ok, Ref} = client:connect({Prot, loopback, loopback, 3868}),
receive #diameter_event{info = {up, Ref, _, _, _}} -> ok end;
start(Config) ->
diff --git a/lib/diameter/test/diameter_reg_SUITE.erl b/lib/diameter/test/diameter_reg_SUITE.erl
index e2a1ca00c3..cd9242faa8 100644
--- a/lib/diameter/test/diameter_reg_SUITE.erl
+++ b/lib/diameter/test/diameter_reg_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@
-export([add/1,
add_new/1,
remove/1,
+ down/1,
terms/1,
pids/1]).
@@ -56,6 +57,7 @@ tc() ->
[add,
add_new,
remove,
+ down,
terms,
pids].
@@ -88,6 +90,13 @@ remove(_) ->
[{Ref, Pid}] = ?reg:match(Ref),
Pid = self().
+down(_) ->
+ Ref = make_ref(),
+ {_, MRef} = spawn_monitor(fun() -> ?reg:add_new(Ref), timer:sleep(1000) end),
+ receive {'DOWN', MRef, process, _, _} -> ok end,
+ timer:sleep(1000),
+ [] = ?reg:match(Ref).
+
terms(_) ->
Ref = make_ref(),
true = ?reg:add_new(Ref),
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 84b41f14b7..434aef01dd 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
%%
%% Tests of traffic between two Diameter nodes, one client, one server.
+%% The traffic isn't meant to be sensible, just to exercise code.
%%
-module(diameter_traffic_SUITE).
@@ -27,15 +28,18 @@
-export([suite/0,
all/0,
groups/0,
+ init_per_suite/0,
init_per_suite/1,
end_per_suite/1,
+ init_per_group/1,
init_per_group/2,
end_per_group/2,
init_per_testcase/2,
end_per_testcase/2]).
%% testcases
--export([start/1,
+-export([rfc4005/1,
+ start/1,
start_services/1,
add_transports/1,
result_codes/1,
@@ -46,6 +50,7 @@
send_protocol_error/1,
send_experimental_result/1,
send_arbitrary/1,
+ send_proxy_info/1,
send_unknown/1,
send_unknown_short/1,
send_unknown_mandatory/1,
@@ -63,6 +68,7 @@
send_invalid_reject/1,
send_unexpected_mandatory_decode/1,
send_unexpected_mandatory/1,
+ send_too_many/1,
send_long/1,
send_maxlen/1,
send_nopeer/1,
@@ -98,18 +104,20 @@
stop/1]).
%% diameter callbacks
--export([peer_up/3,
- peer_down/3,
- pick_peer/6, pick_peer/7,
- prepare_request/5, prepare_request/6,
- prepare_retransmit/5,
- handle_answer/6, handle_answer/7,
- handle_error/6,
- handle_request/3]).
+-export([peer_up/4,
+ peer_down/4,
+ pick_peer/7, pick_peer/8,
+ prepare_request/6, prepare_request/7,
+ prepare_retransmit/6,
+ handle_answer/7, handle_answer/8,
+ handle_error/7,
+ handle_request/4]).
%% diameter_{tcp,sctp} callbacks
-export([message/3]).
+-include_lib("kernel/include/inet_sctp.hrl").
+
-include("diameter.hrl").
-include("diameter_gen_base_rfc3588.hrl").
-include("diameter_gen_base_accounting.hrl").
@@ -119,13 +127,22 @@
%% ===========================================================================
+%% Fraction of shuffle/parallel groups to randomly skip.
+-define(SKIP, 0.25).
+
+%% Positive number of testcases from which to select (randomly) from
+%% tc(), the list of testcases to run, or [] to run all. The random
+%% selection is to limit the time it takes for the suite to run.
+-define(LIMIT, #{tcp => 42, sctp => 5}).
+
-define(util, diameter_util).
-define(A, list_to_atom).
-define(L, atom_to_list).
+-define(B, iolist_to_binary).
%% Don't use is_record/2 since dictionary hrl's aren't included.
-%% (Since they define conflicting reqcords with the same names.)
+%% (Since they define conflicting records with the same names.)
-define(is_record(Rec, Name), (Name == element(1, Rec))).
-define(ADDR, {127,0,0,1}).
@@ -138,14 +155,14 @@
%% Sequence mask for End-to-End and Hop-by-Hop identifiers.
-define(CLIENT_MASK, {1,26}). %% 1 in top 6 bits
-%% How to construct messages, as record or list.
--define(ENCODINGS, [list, record]).
+%% How to construct outgoing messages.
+-define(ENCODINGS, [list, record, map]).
-%% How to send answers, in a diameter_packet or not.
--define(CONTAINERS, [pkt, msg]).
+%% How to decode incoming messages.
+-define(DECODINGS, [record, none, map, list, record_from_map]).
-%% Which common dictionary to use in the clients.
--define(RFCS, [rfc3588, rfc6733]).
+%% Which dictionary to use in the clients.
+-define(RFCS, [rfc3588, rfc6733, rfc4005]).
%% Whether to decode stringish Diameter types to strings, or leave
%% them as binary.
@@ -163,13 +180,12 @@
-record(group,
{transport,
strings,
+ encoding,
client_service,
- client_encoding,
- client_dict0,
+ client_dict,
client_sender,
server_service,
- server_encoding,
- server_container,
+ server_decoding,
server_sender,
server_throttle}).
@@ -182,34 +198,37 @@
%% A common match when receiving answers in a client.
-define(answer_message(SessionId, ResultCode),
- ['answer-message',
- {'Session-Id', SessionId},
- {'Origin-Host', _},
- {'Origin-Realm', _},
- {'Result-Code', ResultCode}
- | _]).
+ ['answer-message' | #{'Session-Id' := SessionId,
+ 'Origin-Host' := _,
+ 'Origin-Realm' := _,
+ 'Result-Code' := ResultCode}]).
-define(answer_message(ResultCode),
- ?answer_message(_, ResultCode)).
+ ['answer-message' | #{'Origin-Host' := _,
+ 'Origin-Realm' := _,
+ 'Result-Code' := ResultCode}]).
%% Config for diameter:start_service/2.
--define(SERVICE(Name, Decode),
+-define(SERVICE(Name, Grp),
[{'Origin-Host', Name ++ "." ++ ?REALM},
{'Origin-Realm', ?REALM},
{'Host-IP-Address', [?ADDR]},
{'Vendor-Id', 12345},
{'Product-Name', "OTP/diameter"},
- {'Auth-Application-Id', [?DIAMETER_APP_ID_COMMON]},
- {'Acct-Application-Id', [?DIAMETER_APP_ID_ACCOUNTING]},
+ {'Auth-Application-Id', [0]}, %% common messages
+ {'Acct-Application-Id', [3]}, %% base accounting
{restrict_connections, false},
- {string_decode, Decode},
+ {string_decode, Grp#group.strings},
+ {avp_dictionaries, [diameter_gen_doic_rfc7683]},
{incoming_maxlen, 1 bsl 21}
| [{application, [{dictionary, D},
- {module, ?MODULE},
+ {module, [?MODULE, Grp]},
{answer_errors, callback}]}
|| D <- [diameter_gen_base_rfc3588,
diameter_gen_base_accounting,
diameter_gen_base_rfc6733,
- diameter_gen_acct_rfc6733]]]).
+ diameter_gen_acct_rfc6733,
+ nas4005],
+ D /= nas4005 orelse have_nas()]]).
-define(SUCCESS,
?'DIAMETER_BASE_RESULT-CODE_SUCCESS').
@@ -227,6 +246,8 @@
?'DIAMETER_BASE_RESULT-CODE_AVP_UNSUPPORTED').
-define(UNSUPPORTED_VERSION,
?'DIAMETER_BASE_RESULT-CODE_UNSUPPORTED_VERSION').
+-define(TOO_MANY,
+ ?'DIAMETER_BASE_RESULT-CODE_AVP_OCCURS_TOO_MANY_TIMES').
-define(REALM_NOT_SERVED,
?'DIAMETER_BASE_RESULT-CODE_REALM_NOT_SERVED').
-define(UNABLE_TO_DELIVER,
@@ -254,64 +275,75 @@ suite() ->
[{timetrap, {seconds, 10}}].
all() ->
- [start, result_codes, {group, traffic}, empty, stop].
+ [rfc4005, start, result_codes, {group, traffic}, empty, stop].
+%% Redefine this to run one or more groups for debugging purposes.
+-define(GROUPS, []).
+%-define(GROUPS, [[tcp,rfc6733,record,map,false,false,false,false]]).
+
+%% Issues with gen_sctp sporadically cause huge numbers of failed
+%% testcases when running testcases in parallel.
groups() ->
- [{P, [P], Ts} || Ts <- [tc(tc())], P <- [shuffle, parallel]]
+ Names = names(),
+ [{P, [P], Ts} || Ts <- [tc()], P <- [shuffle, parallel]]
++
- [{?util:name([T,R,D,A,C,S,SS,ST,CS]),
- [],
- [{group, if S -> shuffle; not S -> parallel end}]}
- || T <- ?TRANSPORTS,
- R <- ?ENCODINGS,
- D <- ?RFCS,
- A <- ?ENCODINGS,
- C <- ?CONTAINERS,
- S <- ?STRING_DECODES,
- SS <- ?SENDERS,
- ST <- ?CALLBACKS,
- CS <- ?SENDERS]
+ [{?util:name(N), [], [{group, if T == sctp; S -> shuffle;
+ true -> parallel end}]}
+ || [T,_,_,_,S|_] = N <- Names]
++
- [{T, [], groups([[T,R,D,A,C,S,SS,ST,CS]
- || R <- ?ENCODINGS,
- D <- ?RFCS,
- A <- ?ENCODINGS,
- C <- ?CONTAINERS,
- S <- ?STRING_DECODES,
- SS <- ?SENDERS,
- ST <- ?CALLBACKS,
- CS <- ?SENDERS,
- SS orelse CS])} %% avoid deadlock
+ [{T, [], [{group, ?util:name(N)} || N <- names(Names, ?GROUPS),
+ T == hd(N)]}
|| T <- ?TRANSPORTS]
++
[{traffic, [], [{group, T} || T <- ?TRANSPORTS]}].
-%groups(_) -> %% debug
-% Name = [sctp,record,rfc6733,record,pkt,false,false,false,false],
-% [{group, ?util:name(Name)}];
-groups(Names) ->
- [{group, ?util:name(L)} || L <- Names].
+names() ->
+ [[T,R,E,D,S,ST,SS,CS] || T <- ?TRANSPORTS,
+ R <- ?RFCS,
+ E <- ?ENCODINGS,
+ D <- ?DECODINGS,
+ S <- ?STRING_DECODES,
+ ST <- ?CALLBACKS,
+ SS <- ?SENDERS,
+ CS <- ?SENDERS].
+
+names(Names, []) ->
+ [N || N <- Names,
+ [CS,SS|_] <- [lists:reverse(N)],
+ SS orelse CS]; %% avoid deadlock
-%tc([N|_]) -> %% debug
-% [N];
-tc(L) ->
- L.
+names(_, Names) ->
+ Names.
%% --------------------
+init_per_suite() ->
+ [{timetrap, {seconds, 60}}].
+
init_per_suite(Config) ->
- [{sctp, ?util:have_sctp()} | Config].
+ [{rfc4005, compile_and_load()}, {sctp, ?util:have_sctp()} | Config].
end_per_suite(_Config) ->
+ code:delete(nas4005),
+ code:purge(nas4005),
ok.
%% --------------------
+init_per_group(_) ->
+ [{timetrap, {seconds, 30}}].
+
init_per_group(Name, Config)
when Name == shuffle;
Name == parallel ->
- start_services(Config),
- add_transports(Config);
+ case rand:uniform() < ?SKIP of
+ true ->
+ {skip, random};
+ false ->
+ start_services(Config),
+ add_transports(Config),
+ replace({sleep, Name == parallel}, Config)
+ end;
init_per_group(sctp = Name, Config) ->
{_, Sctp} = lists:keyfind(Name, 1, Config),
@@ -322,24 +354,22 @@ init_per_group(sctp = Name, Config) ->
end;
init_per_group(Name, Config) ->
+ Nas = proplists:get_value(rfc4005, Config, false),
case ?util:name(Name) of
- [T,R,D,A,C,S,SS,ST,CS] ->
+ [_,R,_,_,_,_,_,_] when R == rfc4005, true /= Nas ->
+ {skip, rfc4005};
+ [T,R,E,D,S,ST,SS,CS] ->
G = #group{transport = T,
strings = S,
+ encoding = E,
client_service = [$C|?util:unique_string()],
- client_encoding = R,
- client_dict0 = dict0(D),
+ client_dict = appdict(R),
client_sender = CS,
server_service = [$S|?util:unique_string()],
- server_encoding = A,
- server_container = C,
+ server_decoding = D,
server_sender = SS,
server_throttle = ST},
- %% Limit the number of testcase, since the number of
- %% groups is large.
- All = ?util:scramble(tc()),
- TCs = lists:sublist(All, rand:uniform(32)),
- [{group, G}, {runlist, TCs} | Config];
+ replace([{group, G}, {runlist, select(T)}], Config);
_ ->
Config
end.
@@ -353,8 +383,26 @@ end_per_group(Name, Config)
end_per_group(_, _) ->
ok.
+select(T) ->
+ try maps:get(T, ?LIMIT) of
+ N ->
+ lists:sublist(?util:scramble(tc()), max(5, rand:uniform(N)))
+ catch
+ error:_ -> ?LIMIT
+ end.
+
%% --------------------
+%% Work around common_test accumulating Config improperly, causing
+%% testcases to get Config from groups and suites they're not in.
+init_per_testcase(N, Config)
+ when N == rfc4005;
+ N == start;
+ N == result_codes;
+ N == empty;
+ N == stop ->
+ Config;
+
%% Skip testcases that can reasonably fail under SCTP.
init_per_testcase(Name, Config) ->
TCs = proplists:get_value(runlist, Config, []),
@@ -368,12 +416,26 @@ init_per_testcase(Name, Config) ->
_ when not Run ->
{skip, random};
_ ->
+ proplists:get_value(sleep, Config, false)
+ andalso timer:sleep(rand:uniform(200)),
[{testcase, Name} | Config]
end.
end_per_testcase(_, _) ->
ok.
+%% replace/2
+%%
+%% Work around common_test running init functions inappropriately, and
+%% this accumulating more config than expected.
+
+replace(Pairs, Config)
+ when is_list(Pairs) ->
+ lists:foldl(fun replace/2, Config, Pairs);
+
+replace({Key, _} = T, Config) ->
+ [T | lists:keydelete(Key, 1, Config)].
+
%% --------------------
%% Testcases to run when services are started and connections
@@ -386,6 +448,7 @@ tc() ->
send_protocol_error,
send_experimental_result,
send_arbitrary,
+ send_proxy_info,
send_unknown,
send_unknown_short,
send_unknown_mandatory,
@@ -403,6 +466,7 @@ tc() ->
send_invalid_reject,
send_unexpected_mandatory_decode,
send_unexpected_mandatory,
+ send_too_many,
send_long,
send_maxlen,
send_nopeer,
@@ -440,16 +504,26 @@ start(_Config) ->
ok = diameter:start().
start_services(Config) ->
- #group{strings = S,
- client_service = CN,
- server_service = SN}
+ #group{client_service = CN,
+ server_service = SN,
+ server_decoding = SD}
+ = Grp
= group(Config),
- ok = diameter:start_service(SN, ?SERVICE(SN, S)),
- ok = diameter:start_service(CN, [{sequence, ?CLIENT_MASK}
- | ?SERVICE(CN, S)]).
+ ok = diameter:start_service(SN, [{traffic_counters, bool()},
+ {decode_format, SD}
+ | ?SERVICE(SN, Grp)]),
+ ok = diameter:start_service(CN, [{traffic_counters, bool()},
+ {sequence, ?CLIENT_MASK},
+ {decode_format, map},
+ {strict_arities, decode}
+ | ?SERVICE(CN, Grp)]).
+
+bool() ->
+ 0.5 =< rand:uniform().
add_transports(Config) ->
#group{transport = T,
+ encoding = E,
client_service = CN,
client_sender = CS,
server_service = SN,
@@ -459,30 +533,59 @@ add_transports(Config) ->
LRef = ?util:listen(SN,
[T,
{sender, SS},
- {message_cb, ST andalso {?MODULE, message, [4]}}
- | [{packet, hd(?util:scramble([false, raw]))}
- || T == sctp andalso CS]],
+ {message_cb, ST andalso {?MODULE, message, [0]}}]
+ ++ [{packet, hd(?util:scramble([false, raw]))}
+ || T == sctp andalso CS]
+ ++ [{unordered, unordered()} || T == sctp],
[{capabilities_cb, fun capx/2},
- {pool_size, 8},
- {applications, apps(rfc3588)}]
+ {pool_size, 8}
+ | server_apps()]
++ [{spawn_opt, {erlang, spawn, []}} || CS]),
Cs = [?util:connect(CN,
- [T, {sender, CS}],
+ [T, {sender, CS} | client_opts(T)],
LRef,
- [{id, Id},
- {capabilities, [{'Origin-State-Id', origin(Id)}]},
- {applications, apps(D)}])
- || A <- ?ENCODINGS,
- C <- ?CONTAINERS,
- D <- ?RFCS,
- Id <- [{A,C}]],
- %% The server uses the client's Origin-State-Id to decide how to
- %% answer.
+ [{id, Id}
+ | client_apps(R, [{'Origin-State-Id', origin(Id)}])])
+ || D <- ?DECODINGS, %% for multiple candidate peers
+ R <- ?RFCS,
+ R /= rfc4005 orelse have_nas(),
+ Id <- [{D,E}]],
?util:write_priv(Config, "transport", [LRef | Cs]).
-apps(D0) ->
- D = dict0(D0),
- [acct(D), D].
+unordered() ->
+ element(rand:uniform(4), {true, false, 1, 2}).
+
+client_opts(tcp) ->
+ [];
+client_opts(sctp) ->
+ [{unordered, unordered()}
+ | [{sctp_initmsg, #sctp_initmsg{num_ostreams = N,
+ max_instreams = 5}}
+ || N <- [rand:uniform(8)],
+ N =< 6]].
+
+server_apps() ->
+ B = have_nas(),
+ [{applications, [diameter_gen_base_rfc3588,
+ diameter_gen_base_accounting]
+ ++ [nas4005 || B]},
+ {capabilities, [{'Auth-Application-Id', [0] ++ [1 || B]}, %% common, NAS
+ {'Acct-Application-Id', [3]}]}]. %% accounting
+
+client_apps(D, Caps) ->
+ if D == rfc4005 ->
+ [{applications, [nas4005]},
+ {capabilities, [{'Auth-Application-Id', [1]}, %% NAS
+ {'Acct-Application-Id', []}
+ | Caps]}];
+ true ->
+ D0 = dict0(D),
+ [{applications, [acct(D0), D0]},
+ {capabilities, Caps}]
+ end.
+
+have_nas() ->
+ false /= code:is_loaded(nas4005).
remove_transports(Config) ->
#group{client_service = CN,
@@ -515,9 +618,16 @@ capx(_, #diameter_caps{origin_host = {OH,DH}}) ->
%% ===========================================================================
+%% Fail only this testcase if the RFC 4005 dictionary hasn't been
+%% successfully compiled and loaded.
+rfc4005(Config) ->
+ true = proplists:get_value(rfc4005, Config).
+
%% Ensure that result codes have the expected values.
result_codes(_Config) ->
- {2001, 3001, 3002, 3003, 3004, 3007, 3008, 3009, 5001, 5011, 5014}
+ {2001,
+ 3001, 3002, 3003, 3004, 3007, 3008, 3009,
+ 5001, 5009, 5011, 5014}
= {?SUCCESS,
?COMMAND_UNSUPPORTED,
?UNABLE_TO_DELIVER,
@@ -527,6 +637,7 @@ result_codes(_Config) ->
?INVALID_HDR_BITS,
?INVALID_AVP_BITS,
?AVP_UNSUPPORTED,
+ ?TOO_MANY,
?UNSUPPORTED_VERSION,
?INVALID_AVP_LENGTH}.
@@ -534,8 +645,8 @@ result_codes(_Config) ->
send_ok(Config) ->
Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
{'Accounting-Record-Number', 1}],
-
- ['ACA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
+ ['ACA' | #{'Result-Code' := ?SUCCESS,
+ 'Session-Id' := _}]
= call(Config, Req).
%% Send an accounting ACR that the server answers badly to.
@@ -551,7 +662,8 @@ send_eval(Config) ->
Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
{'Accounting-Record-Number', 3}],
- ['ACA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
+ ['ACA' | #{'Result-Code' := ?SUCCESS,
+ 'Session-Id' := _}]
= call(Config, Req).
%% Send an accounting ACR that the server tries to answer with an
@@ -564,20 +676,87 @@ send_bad_answer(Config) ->
= call(Config, Req).
%% Send an ACR that the server callback answers explicitly with a
-%% protocol error.
+%% protocol error and some AVPs to check the decoding of.
send_protocol_error(Config) ->
Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
{'Accounting-Record-Number', 4}],
- ?answer_message(?TOO_BUSY)
- = call(Config, Req).
+ ['answer-message' | #{'Result-Code' := ?TOO_BUSY,
+ 'AVP' := [OLR | _]} = Avps]
+ = call(Config, Req),
+
+ #diameter_avp{name = 'OC-OLR',
+ value = #{'OC-Sequence-Number' := 1,
+ 'OC-Report-Type' := 0, %% HOST_REPORT
+ 'OC-Reduction-Percentage' := [25],
+ 'OC-Validity-Duration' := [60],
+ 'AVP' := [OSF]}}
+ = OLR,
+ #diameter_avp{name = 'OC-Supported-Features',
+ value = #{} = Fs}
+ = OSF,
+ 0 = maps:size(Fs),
+
+ #group{client_dict = D} = group(Config),
+
+ if D == nas4005 ->
+ error = maps:find('Failed-AVP', Avps),
+ #{'AVP' := [_,Failed]}
+ = Avps,
+ #diameter_avp{name = 'Failed-AVP',
+ value = #{'AVP' := [NP,FR,AP]}}
+ = Failed,
+ #diameter_avp{name = 'NAS-Port',
+ value = 44}
+ = NP,
+ #diameter_avp{name = 'Firmware-Revision',
+ value = 12}
+ = FR,
+ #diameter_avp{name = 'Auth-Grace-Period',
+ value = 13}
+ = AP;
+
+ D == diameter_gen_base_rfc3588;
+ D == diameter_gen_basr_accounting ->
+ error = maps:find('Failed-AVP', Avps),
+ #{'AVP' := [_,Failed]}
+ = Avps,
+
+ #diameter_avp{name = 'Failed-AVP',
+ value = #{'AVP' := [NP,FR,AP]}}
+ = Failed,
+ #diameter_avp{name = undefined,
+ value = undefined}
+ = NP,
+ #diameter_avp{name = 'Firmware-Revision',
+ value = 12}
+ = FR,
+ #diameter_avp{name = 'Auth-Grace-Period',
+ value = 13}
+ = AP;
+
+ D == diameter_gen_base_rfc6733;
+ D == diameter_gen_acct_rfc6733 ->
+ #{'Failed-AVP' := [#{'AVP' := [NP,FR,AP]}],
+ 'AVP' := [_]}
+ = Avps,
+ #diameter_avp{name = undefined,
+ value = undefined}
+ = NP,
+ #diameter_avp{name = 'Firmware-Revision',
+ value = 12}
+ = FR,
+ #diameter_avp{name = 'Auth-Grace-Period',
+ value = 13}
+ = AP
+ end.
%% Send a 3xxx Experimental-Result in an answer not setting the E-bit
%% and missing a Result-Code.
send_experimental_result(Config) ->
Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
{'Accounting-Record-Number', 5}],
- ['ACA', {'Session-Id', _} | _]
+ ['ACA' | #{'Session-Id' := _}]
= call(Config, Req).
%% Send an ASR with an arbitrary non-mandatory AVP and expect success
@@ -585,24 +764,37 @@ send_experimental_result(Config) ->
send_arbitrary(Config) ->
Req = ['ASR', {'AVP', [#diameter_avp{name = 'Product-Name',
value = "XXX"}]}],
- ['ASA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | Avps]
+ ['ASA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS,
+ 'AVP' := [#diameter_avp{name = 'Product-Name',
+ value = V}]}]
= call(Config, Req),
- {'AVP', [#diameter_avp{name = 'Product-Name',
- value = V}]}
- = lists:last(Avps),
"XXX" = string(V, Config).
+%% Send Proxy-Info in an ASR that the peer answers with 3xxx, and
+%% ensure that the AVP is returned.
+send_proxy_info(Config) ->
+ H0 = ?B(?util:unique_string()),
+ S0 = ?B(?util:unique_string()),
+ Req = ['ASR', {'Proxy-Info', #{'Proxy-Host' => H0,
+ 'Proxy-State' => S0}}],
+ ['answer-message' | #{'Result-Code' := 3999,
+ 'Proxy-Info' := [#{'Proxy-Host' := H,
+ 'Proxy-State' := S}]}]
+ = call(Config, Req),
+ [H0, S0] = [?B(X) || X <- [H,S]].
+
%% Send an unknown AVP (to some client) and check that it comes back.
send_unknown(Config) ->
Req = ['ASR', {'AVP', [#diameter_avp{code = 999,
is_mandatory = false,
data = <<17>>}]}],
- ['ASA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | Avps]
- = call(Config, Req),
- {'AVP', [#diameter_avp{code = 999,
- is_mandatory = false,
- data = <<17>>}]}
- = lists:last(Avps).
+ ['ASA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS,
+ 'AVP' := [#diameter_avp{code = 999,
+ is_mandatory = false,
+ data = <<17>>}]}]
+ = call(Config, Req).
%% Ditto, and point the AVP length past the end of the message. Expect
%% 5014.
@@ -613,28 +805,28 @@ send_unknown_short(Config, M, RC) ->
Req = ['ASR', {'AVP', [#diameter_avp{code = 999,
is_mandatory = M,
data = <<17>>}]}],
- ['ASA', {'Session-Id', _}, {'Result-Code', RC} | Avps]
+ ['ASA' | #{'Session-Id' := _,
+ 'Result-Code' := RC,
+ 'Failed-AVP' := [#{'AVP' := [Avp]}]}]
= call(Config, Req),
- [#'diameter_base_Failed-AVP'{'AVP' = As}]
- = proplists:get_value('Failed-AVP', Avps),
- [#diameter_avp{code = 999,
- is_mandatory = M,
- data = <<17, _/binary>>}] %% extra bits from padding
- = As.
+ #diameter_avp{code = 999,
+ is_mandatory = M,
+ data = <<17, _/binary>>} %% extra bits from padding
+ = Avp.
%% Ditto but set the M flag.
send_unknown_mandatory(Config) ->
Req = ['ASR', {'AVP', [#diameter_avp{code = 999,
is_mandatory = true,
data = <<17>>}]}],
- ['ASA', {'Session-Id', _}, {'Result-Code', ?AVP_UNSUPPORTED} | Avps]
+ ['ASA' | #{'Session-Id' := _,
+ 'Result-Code' := ?AVP_UNSUPPORTED,
+ 'Failed-AVP' := [#{'AVP' := [Avp]}]}]
= call(Config, Req),
- [#'diameter_base_Failed-AVP'{'AVP' = As}]
- = proplists:get_value('Failed-AVP', Avps),
- [#diameter_avp{code = 999,
- is_mandatory = true,
- data = <<17>>}]
- = As.
+ #diameter_avp{code = 999,
+ is_mandatory = true,
+ data = <<17>>}
+ = Avp.
%% Ditto, and point the AVP length past the end of the message. Expect
%% 5014 instead of 5001.
@@ -647,15 +839,27 @@ send_unexpected_mandatory_decode(Config) ->
Req = ['ASR', {'AVP', [#diameter_avp{code = 27, %% Session-Timeout
is_mandatory = true,
data = <<12:32>>}]}],
- ['ASA', {'Session-Id', _}, {'Result-Code', ?AVP_UNSUPPORTED} | Avps]
+ ['ASA' | #{'Session-Id' := _,
+ 'Result-Code' := ?AVP_UNSUPPORTED,
+ 'Failed-AVP' := [#{'AVP' := [Avp]}]}]
+ = call(Config, Req),
+ #diameter_avp{code = 27,
+ is_mandatory = true,
+ value = 12,
+ data = <<12:32>>}
+ = Avp.
+
+%% Try to two Auth-Application-Id in ASR expect 5009.
+send_too_many(Config) ->
+ Req = ['ASR', {'Auth-Application-Id', [?APP_ID, 44]}],
+
+ ['ASA' | #{'Session-Id' := _,
+ 'Result-Code' := ?TOO_MANY,
+ 'Failed-AVP' := [#{'AVP' := [Avp]}]}]
= call(Config, Req),
- [#'diameter_base_Failed-AVP'{'AVP' = As}]
- = proplists:get_value('Failed-AVP', Avps),
- [#diameter_avp{code = 27,
- is_mandatory = true,
- value = 12,
- data = <<12:32>>}]
- = As.
+ #diameter_avp{name = 'Auth-Application-Id',
+ value = 44}
+ = Avp.
%% Send an containing a faulty Grouped AVP (empty Proxy-Host in
%% Proxy-Info) and expect that only the faulty AVP is sent in
@@ -665,16 +869,13 @@ send_unexpected_mandatory_decode(Config) ->
send_grouped_error(Config) ->
Req = ['ASR', {'Proxy-Info', [[{'Proxy-Host', "abcd"},
{'Proxy-State', ""}]]}],
- ['ASA', {'Session-Id', _}, {'Result-Code', ?INVALID_AVP_LENGTH} | Avps]
+ ['ASA' | #{'Session-Id' := _,
+ 'Result-Code' := ?INVALID_AVP_LENGTH,
+ 'Failed-AVP' := [#{'AVP' := [Avp]}]}]
= call(Config, Req),
- [#'diameter_base_Failed-AVP'{'AVP' = As}]
- = proplists:get_value('Failed-AVP', Avps),
- [#diameter_avp{name = 'Proxy-Info',
- value = #'diameter_base_Proxy-Info'
- {'Proxy-Host' = Empty,
- 'Proxy-State' = undefined}}]
- = As,
- <<0>> = iolist_to_binary(Empty).
+ #diameter_avp{name = 'Proxy-Info', value = #{'Proxy-Host' := H}}
+ = Avp,
+ <<0>> = ?B(H).
%% Send an STR that the server ignores.
send_noreply(Config) ->
@@ -702,7 +903,8 @@ send_error_bit(Config) ->
%% Send a bad version and check that we get 5011.
send_unsupported_version(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
- ['STA', {'Session-Id', _}, {'Result-Code', ?UNSUPPORTED_VERSION} | _]
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?UNSUPPORTED_VERSION}]
= call(Config, Req).
%% Send a request containing an AVP length > data size.
@@ -722,16 +924,11 @@ send_zero_avp_length(Config) ->
send_invalid_avp_length(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
- ['STA', {'Session-Id', _},
- {'Result-Code', ?INVALID_AVP_LENGTH},
- {'Origin-Host', _},
- {'Origin-Realm', _},
- {'User-Name', _},
- {'Class', _},
- {'Error-Message', _},
- {'Error-Reporting-Host', _},
- {'Failed-AVP', [#'diameter_base_Failed-AVP'{'AVP' = [_]}]}
- | _]
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?INVALID_AVP_LENGTH,
+ 'Origin-Host' := _,
+ 'Origin-Realm' := _,
+ 'Failed-AVP' := [#{'AVP' := [_]}]}]
= call(Config, Req).
%% Send a request containing 5xxx errors that the server rejects with
@@ -747,14 +944,16 @@ send_invalid_reject(Config) ->
send_unexpected_mandatory(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
- ['STA', {'Session-Id', _}, {'Result-Code', ?AVP_UNSUPPORTED} | _]
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?AVP_UNSUPPORTED}]
= call(Config, Req).
%% Send something long that will be fragmented by TCP.
send_long(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT},
{'User-Name', [binary:copy(<<$X>>, 1 bsl 20)]}],
- ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}]
= call(Config, Req).
%% Send something longer than the configure incoming_maxlen.
@@ -797,7 +996,8 @@ send_any_2(Config) ->
send_all_1(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
Realm = lists:foldr(fun(C,A) -> [C,A] end, [], ?REALM),
- ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}]
= call(Config, Req, [{filter, {all, [{host, any},
{realm, Realm}]}}]).
send_all_2(Config) ->
@@ -826,13 +1026,13 @@ send_detach(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
Ref = make_ref(),
ok = call(Config, Req, [{extra, [{self(), Ref}]}, detach]),
- Ans = receive {Ref, T} -> T end,
- ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
- = Ans.
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}]
+ = receive {Ref, T} -> T end.
%% Send a request which can't be encoded and expect {error, encode}.
send_encode_error(Config) ->
- {error, encode} = call(Config, ['STR']). %% No Termination-Cause
+ {error, encode} = call(Config, ['STR', {'Termination-Cause', huh}]).
%% Send with filtering and expect success.
send_destination_1(Config) ->
@@ -840,25 +1040,27 @@ send_destination_1(Config) ->
= group(Config),
Req = ['STR', {'Termination-Cause', ?LOGOUT},
{'Destination-Host', [?HOST(SN, ?REALM)]}],
- ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}]
= call(Config, Req, [{filter, {all, [host, realm]}}]).
send_destination_2(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
- ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}]
= call(Config, Req, [{filter, {all, [host, realm]}}]).
%% Send with filtering on and expect failure when specifying an
%% unknown host or realm.
send_destination_3(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT},
- {'Destination-Realm', "unknown.org"}],
+ {'Destination-Realm', <<"unknown.org">>}],
{error, no_connection}
= call(Config, Req, [{filter, {all, [host, realm]}}]).
send_destination_4(Config) ->
#group{server_service = SN}
= group(Config),
Req = ['STR', {'Termination-Cause', ?LOGOUT},
- {'Destination-Host', [?HOST(SN, "unknown.org")]}],
+ {'Destination-Host', [?HOST(SN, ["unknown.org"])]}],
{error, no_connection}
= call(Config, Req, [{filter, {all, [host, realm]}}]).
@@ -866,7 +1068,7 @@ send_destination_4(Config) ->
%% an unknown host or realm.
send_destination_5(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT},
- {'Destination-Realm', "unknown.org"}],
+ {'Destination-Realm', [<<"unknown.org">>]}],
?answer_message(?REALM_NOT_SERVED)
= call(Config, Req).
send_destination_6(Config) ->
@@ -908,7 +1110,8 @@ send_bad_filter(Config, F) ->
%% Specify multiple filter options and expect them be conjunctive.
send_multiple_filters_1(Config) ->
Fun = fun(#diameter_caps{}) -> true end,
- ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}]
= send_multiple_filters(Config, [host, {eval, Fun}]).
send_multiple_filters_2(Config) ->
E = {erlang, is_tuple, []},
@@ -919,7 +1122,8 @@ send_multiple_filters_3(Config) ->
E2 = {erlang, is_tuple, []},
E3 = {erlang, is_record, [diameter_caps]},
E4 = [{erlang, is_record, []}, diameter_caps],
- ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}]
= send_multiple_filters(Config, [{eval, E} || E <- [E1,E2,E3,E4]]).
send_multiple_filters(Config, Fs) ->
@@ -930,7 +1134,8 @@ send_multiple_filters(Config, Fs) ->
%% only the return value from the prepare_request callback being
%% significant.
send_anything(Config) ->
- ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}]
= call(Config, anything).
%% ===========================================================================
@@ -954,58 +1159,137 @@ call(Config, Req) ->
call(Config, Req, Opts) ->
Name = proplists:get_value(testcase, Config),
- #group{client_service = CN,
- client_encoding = ReqEncoding,
- client_dict0 = Dict0}
- = Group
+ #group{encoding = Enc,
+ client_service = CN,
+ client_dict = Dict0}
= group(Config),
diameter:call(CN,
dict(Req, Dict0),
- msg(Req, ReqEncoding, Dict0),
- [{extra, [{Name, Group}, diameter_lib:now()]} | Opts]).
+ msg(Req, Enc, Dict0),
+ [{extra, [Name, diameter_lib:now()]} | Opts]).
-origin({A,C}) ->
- 2*codec(A) + container(C);
+origin({D,E}) ->
+ 4*decode(D) + encode(E);
origin(N) ->
- {codec(N band 2), container(N rem 2)}.
-
-%% Map booleans, but the readable atoms are part of (constructed)
-%% group names, so it's good that they're readable.
-
-codec(record) -> 0;
-codec(list) -> 1;
-codec(0) -> record;
-codec(_) -> list.
-
-container(pkt) -> 0;
-container(msg) -> 1;
-container(0) -> pkt;
-container(_) -> msg.
+ {decode(N bsr 2), encode(N rem 4)}.
+
+%% Map atoms. The atoms are part of (constructed) group names, so it's
+%% good that they're readable.
+
+decode(record) -> 0;
+decode(list) -> 1;
+decode(map) -> 2;
+decode(none) -> 3;
+decode(record_from_map) -> 4;
+decode(0) -> record;
+decode(1) -> list;
+decode(2) -> map;
+decode(3) -> none;
+decode(4) -> record_from_map.
+
+encode(record) -> 0;
+encode(list) -> 1;
+encode(map) -> 2;
+encode(0) -> record;
+encode(1) -> list;
+encode(2) -> map.
msg([H|_] = Msg, record = E, diameter_gen_base_rfc3588)
when H == 'ACR';
H == 'ACA' ->
msg(Msg, E, diameter_gen_base_accounting);
+
msg([H|_] = Msg, record = E, diameter_gen_base_rfc6733)
when H == 'ACR';
H == 'ACA' ->
msg(Msg, E, diameter_gen_acct_rfc6733);
+
msg([H|T], record, Dict) ->
Dict:'#new-'(Dict:msg2rec(H), T);
+
+msg([H|As], map, _)
+ when is_list(As) ->
+ [H | maps:from_list(As)];
+
msg(Msg, _, _) ->
Msg.
+to_map(#diameter_packet{msg = [_MsgName | Avps] = Msg},
+ #group{server_decoding = map})
+ when is_map(Avps) ->
+ Msg;
+
+to_map(#diameter_packet{msg = [MsgName | Avps]},
+ #group{server_decoding = list}) ->
+ [MsgName | maps:from_list(Avps)];
+
+to_map(#diameter_packet{header = H, msg = Rec},
+ #group{server_decoding = D})
+ when D == record;
+ D == record_from_map ->
+ rec_to_map(Rec, dict(H));
+
+%% No record decode: do it ourselves.
+to_map(#diameter_packet{header = H,
+ msg = Name,
+ bin = Bin},
+ #group{server_decoding = none,
+ strings = B}) ->
+ Opts = #{decode_format => map,
+ string_decode => B,
+ avp_dictionaries => [diameter_gen_doic_rfc7683],
+ strict_mbit => true,
+ rfc => 6733},
+ #diameter_packet{msg = [MsgName | _Map] = Msg}
+ = diameter_codec:decode(dict(H), Opts, Bin),
+ {MsgName, _} = {Name, Msg}, %% assert
+ Msg.
+
+dict(#diameter_header{application_id = Id,
+ cmd_code = Code}) ->
+ if Id == 1 ->
+ nas4005;
+ Code == 271 ->
+ diameter_gen_base_accounting;
+ true ->
+ diameter_gen_base_rfc3588
+ end.
+
+rec_to_map(Rec, Dict) ->
+ [R | Vs] = Dict:'#get-'(Rec),
+ [Dict:rec2msg(R) | maps:from_list([T || {_,V} = T <- Vs,
+ V /= undefined,
+ V /= []])].
+
+appdict(rfc4005) ->
+ nas4005;
+appdict(D) ->
+ dict0(D).
+
dict0(D) ->
?A("diameter_gen_base_" ++ ?L(D)).
-dict(Msg, Dict0)
- when 'ACR' == hd(Msg);
- 'ACA' == hd(Msg);
- ?is_record(Msg, diameter_base_accounting_ACR);
- ?is_record(Msg, diameter_base_accounting_ACA) ->
+dict(Msg, Dict) ->
+ d(name(Msg), Dict).
+
+d(N, nas4005 = D) ->
+ if N == {list, 'answer-message'};
+ N == {map, 'answer-message'};
+ N == {record, 'diameter_base_answer-message'} ->
+ diameter_gen_base_rfc3588;
+ true ->
+ D
+ end;
+d(N, Dict0)
+ when N == {list, 'ACR'};
+ N == {list, 'ACA'};
+ N == {map, 'ACR'};
+ N == {map, 'ACA'};
+ N == {record, diameter_base_accounting_ACR};
+ N == {record, diameter_base_accounting_ACA} ->
acct(Dict0);
-dict(_, Dict0) ->
+d(_, Dict0) ->
Dict0.
acct(diameter_gen_base_rfc3588) ->
@@ -1014,53 +1298,60 @@ acct(diameter_gen_base_rfc6733) ->
diameter_gen_acct_rfc6733.
%% Set only values that aren't already.
-set(_, [H|T], Vs) ->
- [H | Vs ++ T];
-set(#group{client_dict0 = Dict0} = _Group, Rec, Vs) ->
+
+set(_, [N | As], Vs) ->
+ [N | if is_map(As) ->
+ maps:merge(maps:from_list(Vs), As);
+ is_list(As) ->
+ Vs ++ As
+ end];
+
+set(#group{client_dict = Dict0} = _Group, Rec, Vs) ->
Dict = dict(Rec, Dict0),
lists:foldl(fun({F,_} = FV, A) ->
- set(Dict, Dict:'#get-'(F, A), FV, A)
+ reset(Dict, Dict:'#get-'(F, A), FV, A)
end,
Rec,
Vs).
-set(Dict, E, FV, Rec)
+reset(Dict, E, FV, Rec)
when E == undefined;
E == [] ->
Dict:'#set-'(FV, Rec);
-set(_, _, _, Rec) ->
+
+reset(_, _, _, Rec) ->
Rec.
%% ===========================================================================
%% diameter callbacks
-%% peer_up/3
+%% peer_up/4
-peer_up(_SvcName, _Peer, State) ->
+peer_up(_SvcName, _Peer, State, _Group) ->
State.
%% peer_down/3
-peer_down(_SvcName, _Peer, State) ->
+peer_down(_SvcName, _Peer, State, _Group) ->
State.
-%% pick_peer/6-7
+%% pick_peer/7-8
-pick_peer(Peers, _, [$C|_], _State, {Name, Group}, _)
+pick_peer(Peers, _, [$C|_], _State, Group, Name, _)
when Name /= send_detach ->
find(Group, Peers).
-pick_peer(_Peers, _, [$C|_], _State, {send_nopeer, _}, _, ?EXTRA) ->
+pick_peer(_Peers, _, [$C|_], _State, _Group, send_nopeer, _, ?EXTRA) ->
false;
-pick_peer(Peers, _, [$C|_], _State, {send_detach, Group}, _, {_,_}) ->
+pick_peer(Peers, _, [$C|_], _State, Group, send_detach, _, {_,_}) ->
find(Group, Peers).
-find(#group{client_service = CN,
- server_encoding = A,
- server_container = C},
+find(#group{encoding = E,
+ client_service = CN,
+ server_decoding = D},
[_|_] = Peers) ->
- Id = {A,C},
+ Id = {D,E},
[P] = [P || P <- Peers, id(Id, P, CN)],
{ok, P}.
@@ -1069,15 +1360,15 @@ id(Id, {Pid, _Caps}, SvcName) ->
= diameter:service_info(SvcName, Pid),
lists:member({id, Id}, Opts).
-%% prepare_request/5-6
+%% prepare_request/6-7
-prepare_request(_Pkt, [$C|_], {_Ref, _Caps}, {send_discard, _}, _) ->
+prepare_request(_Pkt, [$C|_], {_Ref, _Caps}, _, send_discard, _) ->
{discard, unprepared};
-prepare_request(Pkt, [$C|_], {_Ref, Caps}, {Name, Group}, _) ->
+prepare_request(Pkt, [$C|_], {_Ref, Caps}, Group, Name, _) ->
{send, prepare(Pkt, Caps, Name, Group)}.
-prepare_request(Pkt, [$C|_], {_Ref, Caps}, {send_detach, Group}, _, _) ->
+prepare_request(Pkt, [$C|_], {_Ref, Caps}, Group, send_detach, _, _) ->
{eval_packet, {send, prepare(Pkt, Caps, Group)}, [fun log/2, detach]}.
log(#diameter_packet{bin = Bin} = P, T)
@@ -1086,7 +1377,7 @@ log(#diameter_packet{bin = Bin} = P, T)
%% prepare/4
-prepare(Pkt, Caps, N, #group{client_dict0 = Dict0} = Group)
+prepare(Pkt, Caps, N, #group{client_dict = Dict0} = Group)
when N == send_unknown_short_mandatory;
N == send_unknown_short ->
Req = prepare(Pkt, Caps, Group),
@@ -1106,7 +1397,7 @@ prepare(Pkt, Caps, N, #group{client_dict0 = Dict0} = Group)
<<H:Offset/binary, Len:24, T/binary>> = Bin,
E#diameter_packet{bin = <<H/binary, (Len+9):24, T/binary>>};
-prepare(Pkt, Caps, N, #group{client_dict0 = Dict0} = Group)
+prepare(Pkt, Caps, N, #group{client_dict = Dict0} = Group)
when N == send_long_avp_length;
N == send_short_avp_length;
N == send_zero_avp_length ->
@@ -1132,7 +1423,7 @@ prepare(Pkt, Caps, N, #group{client_dict0 = Dict0} = Group)
T/binary,
Hdr/binary, AL:24, Data/binary>>};
-prepare(Pkt, Caps, N, #group{client_dict0 = Dict0} = Group)
+prepare(Pkt, Caps, N, #group{client_dict = Dict0} = Group)
when N == send_invalid_avp_length;
N == send_invalid_reject ->
Req = prepare(Pkt, Caps, Group),
@@ -1147,7 +1438,7 @@ prepare(Pkt, Caps, N, #group{client_dict0 = Dict0} = Group)
<<V, L:24, H/binary>> = H0, %% assert
E#diameter_packet{bin = <<V, (L+4):24, H/binary, 16:24, 0:32, T/binary>>};
-prepare(Pkt, Caps, send_unexpected_mandatory, #group{client_dict0 = Dict0}
+prepare(Pkt, Caps, send_unexpected_mandatory, #group{client_dict = Dict0}
= Group) ->
Req = prepare(Pkt, Caps, Group),
#diameter_packet{bin = <<V, Len:24, T/binary>>}
@@ -1157,7 +1448,7 @@ prepare(Pkt, Caps, send_unexpected_mandatory, #group{client_dict0 = Dict0}
Avp = <<Code:32, Flags, 8:24>>,
E#diameter_packet{bin = <<V, (Len+8):24, T/binary, Avp/binary>>};
-prepare(Pkt, Caps, send_grouped_error, #group{client_dict0 = Dict0}
+prepare(Pkt, Caps, send_grouped_error, #group{client_dict = Dict0}
= Group) ->
Req = prepare(Pkt, Caps, Group),
#diameter_packet{bin = Bin}
@@ -1189,14 +1480,14 @@ prepare(Pkt, Caps, send_grouped_error, #group{client_dict0 = Dict0}
Payload/binary,
T/binary>>};
-prepare(Pkt, Caps, send_unsupported, #group{client_dict0 = Dict0} = Group) ->
+prepare(Pkt, Caps, send_unsupported, #group{client_dict = Dict0} = Group) ->
Req = prepare(Pkt, Caps, Group),
#diameter_packet{bin = <<H:5/binary, _CmdCode:3/binary, T/binary>>}
= E
= diameter_codec:encode(Dict0, Pkt#diameter_packet{msg = Req}),
E#diameter_packet{bin = <<H/binary, 42:24, T/binary>>};
-prepare(Pkt, Caps, send_unsupported_app, #group{client_dict0 = Dict0}
+prepare(Pkt, Caps, send_unsupported_app, #group{client_dict = Dict0}
= Group) ->
Req = prepare(Pkt, Caps, Group),
#diameter_packet{bin = <<H:8/binary, _ApplId:4/binary, T/binary>>}
@@ -1223,93 +1514,120 @@ prepare(Pkt, Caps, _Name, Group) ->
%% prepare/3
-prepare(#diameter_packet{msg = Req}, Caps, Group)
- when ?is_record(Req, diameter_base_accounting_ACR);
- 'ACR' == hd(Req) ->
+prepare(#diameter_packet{msg = Req} = Pkt, Caps, Group) ->
+ set(name(Req), Pkt, Caps, Group).
+
+%% set/4
+
+set(N, #diameter_packet{msg = Req}, Caps, Group)
+ when N == {record, diameter_base_accounting_ACR};
+ N == {record, nas_ACR};
+ N == {map, 'ACR'};
+ N == {list, 'ACR'} ->
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, DR}}
= Caps,
- set(Group, Req, [{'Session-Id', diameter:session_id(OH)},
- {'Origin-Host', OH},
- {'Origin-Realm', OR},
- {'Destination-Realm', DR}]);
+ set(Group, Req, [{'Session-Id', [diameter:session_id(OH)]},
+ {'Origin-Host', [OH]},
+ {'Origin-Realm', [OR]},
+ {'Destination-Realm', [DR]}]);
-prepare(#diameter_packet{msg = Req}, Caps, Group)
- when ?is_record(Req, diameter_base_ASR);
- 'ASR' == hd(Req) ->
+set(N, #diameter_packet{msg = Req}, Caps, Group)
+ when N == {record, diameter_base_ASR};
+ N == {record, nas_ASR};
+ N == {map, 'ASR'};
+ N == {list, 'ASR'} ->
#diameter_caps{origin_host = {OH, DH},
origin_realm = {OR, DR}}
= Caps,
- set(Group, Req, [{'Session-Id', diameter:session_id(OH)},
- {'Origin-Host', OH},
- {'Origin-Realm', OR},
- {'Destination-Host', DH},
- {'Destination-Realm', DR},
+ set(Group, Req, [{'Session-Id', [diameter:session_id(OH)]},
+ {'Origin-Host', [OH]},
+ {'Origin-Realm', [OR]},
+ {'Destination-Host', [DH]},
+ {'Destination-Realm', [DR]},
{'Auth-Application-Id', ?APP_ID}]);
-prepare(#diameter_packet{msg = Req}, Caps, Group)
- when ?is_record(Req, diameter_base_STR);
- 'STR' == hd(Req) ->
+set(N, #diameter_packet{msg = Req}, Caps, Group)
+ when N == {record, diameter_base_STR};
+ N == {record, nas_STR};
+ N == {map, 'STR'};
+ N == {list, 'STR'} ->
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, DR}}
= Caps,
- set(Group, Req, [{'Session-Id', diameter:session_id(OH)},
- {'Origin-Host', OH},
- {'Origin-Realm', OR},
- {'Destination-Realm', DR},
+ set(Group, Req, [{'Session-Id', [diameter:session_id(OH)]},
+ {'Origin-Host', [OH]},
+ {'Origin-Realm', [OR]},
+ {'Destination-Realm', [DR]},
{'Auth-Application-Id', ?APP_ID}]);
-prepare(#diameter_packet{msg = Req}, Caps, Group)
- when ?is_record(Req, diameter_base_RAR);
- 'RAR' == hd(Req) ->
+set(N, #diameter_packet{msg = Req}, Caps, Group)
+ when N == {record, diameter_base_RAR};
+ N == {record, nas_RAR};
+ N == {map, 'RAR'};
+ N == {list, 'RAR'} ->
#diameter_caps{origin_host = {OH, DH},
origin_realm = {OR, DR}}
= Caps,
- set(Group, Req, [{'Session-Id', diameter:session_id(OH)},
- {'Origin-Host', OH},
- {'Origin-Realm', OR},
- {'Destination-Host', DH},
- {'Destination-Realm', DR},
+ set(Group, Req, [{'Session-Id', [diameter:session_id(OH)]},
+ {'Origin-Host', [OH]},
+ {'Origin-Realm', [OR]},
+ {'Destination-Host', [DH]},
+ {'Destination-Realm', [DR]},
{'Auth-Application-Id', ?APP_ID}]).
-%% prepare_retransmit/5
+%% name/1
+
+name([H|#{}]) ->
+ {map, H};
+
+name([H|_]) ->
+ {list, H};
+
+name(Rec) ->
+ try
+ {record, element(1, Rec)}
+ catch
+ error: badarg ->
+ false
+ end.
-prepare_retransmit(_Pkt, false, _Peer, _Name, _Group) ->
+%% prepare_retransmit/6
+
+prepare_retransmit(_Pkt, false, _Peer, _Group, _Name, _) ->
discard.
-%% handle_answer/6-7
+%% handle_answer/7-8
-handle_answer(Pkt, Req, [$C|_], Peer, {Name, Group}, _) ->
+handle_answer(Pkt, Req, [$C|_], Peer, Group, Name, _) ->
answer(Pkt, Req, Peer, Name, Group).
-handle_answer(Pkt, Req, [$C|_], Peer, {send_detach = Name, Group}, _, X) ->
+handle_answer(Pkt, Req, [$C|_], Peer, Group, send_detach = Name, _, X) ->
{Pid, Ref} = X,
Pid ! {Ref, answer(Pkt, Req, Peer, Name, Group)}.
-answer(Pkt, Req, _Peer, Name, #group{client_dict0 = Dict0}) ->
+answer(Pkt, Req, _Peer, Name, #group{client_dict = Dict0}) ->
#diameter_packet{header = H, msg = Ans, errors = Es} = Pkt,
ApplId = app(Req, Name, Dict0),
#diameter_header{application_id = ApplId} = H, %% assert
- Dict = dict(Ans, Dict0),
- [R | Vs] = Dict:'#get-'(answer(Ans, Es, Name)),
- [Dict:rec2msg(R) | Vs].
+ answer(Ans, Es, Name).
%% Missing Result-Code and inappropriate Experimental-Result-Code.
-answer(Rec, Es, send_experimental_result) ->
+answer(Ans, Es, send_experimental_result) ->
[{5004, #diameter_avp{name = 'Experimental-Result'}},
{5005, #diameter_avp{name = 'Result-Code'}}]
= Es,
- Rec;
+ Ans;
%% An inappropriate E-bit results in a decode error ...
-answer(Rec, Es, send_bad_answer) ->
+answer(Ans, Es, send_bad_answer) ->
[{5004, #diameter_avp{name = 'Result-Code'}} | _] = Es,
- Rec;
+ Ans;
%% ... while other errors are reflected in Failed-AVP.
-answer(Rec, [], _) ->
- Rec.
+answer(Ans, [], _) ->
+ Ans.
app(_, send_unsupported_app, _) ->
?BAD_APP;
@@ -1317,25 +1635,29 @@ app(Req, _, Dict0) ->
Dict = dict(Req, Dict0),
Dict:id().
-%% handle_error/6
+%% handle_error/7
-handle_error(timeout = Reason, _Req, [$C|_], _Peer, _, Time) ->
+handle_error(timeout = Reason, _Req, [$C|_], _Peer, _, _, Time) ->
Now = diameter_lib:now(),
{Reason, {diameter_lib:timestamp(Time),
diameter_lib:timestamp(Now),
diameter_lib:micro_diff(Now, Time)}};
-handle_error(Reason, _Req, [$C|_], _Peer, _, _Time) ->
+handle_error(Reason, _Req, [$C|_], _Peer, _, _, _Time) ->
{error, Reason}.
-%% handle_request/3
+%% handle_request/4
%% Note that diameter will set Result-Code and Failed-AVPs if
%% #diameter_packet.errors is non-null.
-handle_request(#diameter_packet{header = H, msg = M, avps = As},
+handle_request(#diameter_packet{header = H, avps = As}
+ = Pkt,
_,
- {_Ref, Caps}) ->
+ {_Ref, Caps},
+ #group{encoding = E,
+ server_decoding = D}
+ = Grp) ->
#diameter_header{end_to_end_id = EI,
hop_by_hop_id = HI}
= H,
@@ -1343,24 +1665,62 @@ handle_request(#diameter_packet{header = H, msg = M, avps = As},
V = EI bsr B, %% assert
V = HI bsr B, %%
#diameter_caps{origin_state_id = {_,[Id]}} = Caps,
- answer(origin(Id), request(M, [H|As], Caps)).
+ {D,E} = T = origin(Id), %% assert
+ wrap(T, H, request(to_map(Pkt, Grp), [H|As], Caps)).
+
+wrap(Id, H, {Tag, Action, Post}) ->
+ {Tag, wrap(Id, H, Action), Post};
-answer(T, {Tag, Action, Post}) ->
- {Tag, answer(T, Action), Post};
-answer(_, {reply, [#diameter_header{} | _]} = T) ->
+wrap(_, _, {reply, [#diameter_header{} | _]} = T) ->
T;
-answer({A,C}, {reply, Ans}) ->
- answer(C, {reply, msg(Ans, A, diameter_gen_base_rfc3588)});
-answer(pkt, {reply, Ans})
- when not is_record(Ans, diameter_packet) ->
- {reply, #diameter_packet{msg = Ans}};
-answer(_, T) ->
+
+wrap({_,E}, H, {reply, Ans}) ->
+ Msg = base_to_nas(msg(Ans, E, diameter_gen_base_rfc3588), H),
+ {reply, wrap(Msg)};
+
+wrap(_, _, T) ->
T.
+%% Randomly wrap the answer in a diameter_packet.
+
+wrap(#diameter_packet{} = Pkt) ->
+ Pkt;
+
+wrap(Msg) ->
+ case rand:uniform(2) of
+ 1 -> #diameter_packet{msg = Msg};
+ 2 -> Msg
+ end.
+
+%% base_to_nas/2
+
+base_to_nas(#diameter_packet{msg = Msg} = Pkt, H) ->
+ Pkt#diameter_packet{msg = base_to_nas(Msg, H)};
+
+base_to_nas(Rec, #diameter_header{application_id = 1})
+ when is_tuple(Rec), not ?is_record(Rec, 'diameter_base_answer-message') ->
+ D = case element(1, Rec) of
+ diameter_base_accounting_ACA ->
+ diameter_gen_base_accounting;
+ _ ->
+ diameter_gen_base_rfc3588
+ end,
+ [R | Values] = D:'#get-'(Rec),
+ "diameter_base_" ++ N = ?L(R),
+ Name = ?A("nas_" ++ if N == "accounting_ACA" ->
+ "ACA";
+ true ->
+ N
+ end),
+ nas4005:'#new-'([Name | Values]);
+
+base_to_nas(Msg, _) ->
+ Msg.
+
%% request/3
%% send_experimental_result
-request(#diameter_base_accounting_ACR{'Accounting-Record-Number' = 5},
+request(['ACR' | #{'Accounting-Record-Number' := 5}],
[Hdr | Avps],
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
@@ -1393,14 +1753,14 @@ request(Msg, _Avps, Caps) ->
%% request/2
%% send_nok
-request(#diameter_base_accounting_ACR{'Accounting-Record-Number' = 0},
+request(['ACR' | #{'Accounting-Record-Number' := 0}],
_) ->
{eval_packet, {protocol_error, ?INVALID_AVP_BITS}, [fun log/2, invalid]};
%% send_bad_answer
-request(#diameter_base_accounting_ACR{'Session-Id' = SId,
- 'Accounting-Record-Type' = RT,
- 'Accounting-Record-Number' = 2 = RN},
+request(['ACR' | #{'Session-Id' := SId,
+ 'Accounting-Record-Type' := RT,
+ 'Accounting-Record-Number' := 2 = RN}],
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
Ans = ['ACA', {'Result-Code', ?SUCCESS},
@@ -1414,9 +1774,9 @@ request(#diameter_base_accounting_ACR{'Session-Id' = SId,
msg = Ans}};
%% send_eval
-request(#diameter_base_accounting_ACR{'Session-Id' = SId,
- 'Accounting-Record-Type' = RT,
- 'Accounting-Record-Number' = 3 = RN},
+request(['ACR' | #{'Session-Id' := SId,
+ 'Accounting-Record-Type' := RT,
+ 'Accounting-Record-Number' := 3 = RN}],
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
Ans = ['ACA', {'Result-Code', ?SUCCESS},
@@ -1428,9 +1788,9 @@ request(#diameter_base_accounting_ACR{'Session-Id' = SId,
{eval, {reply, Ans}, {erlang, now, []}};
%% send_ok
-request(#diameter_base_accounting_ACR{'Session-Id' = SId,
- 'Accounting-Record-Type' = RT,
- 'Accounting-Record-Number' = 1 = RN},
+request(['ACR' | #{'Session-Id' := SId,
+ 'Accounting-Record-Type' := RT,
+ 'Accounting-Record-Number' := 1 = RN}],
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
{reply, ['ACA', {'Result-Code', ?SUCCESS},
@@ -1441,48 +1801,69 @@ request(#diameter_base_accounting_ACR{'Session-Id' = SId,
{'Accounting-Record-Number', RN}]};
%% send_protocol_error
-request(#diameter_base_accounting_ACR{'Accounting-Record-Number' = 4},
+request(['ACR' | #{'Accounting-Record-Number' := 4}],
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
+ %% Include a DOIC AVP that will be encoded/decoded because of
+ %% avp_dictionaries config.
+ OLR = #{'OC-Sequence-Number' => 1,
+ 'OC-Report-Type' => 0, %% HOST_REPORT
+ 'OC-Reduction-Percentage' => [25],
+ 'OC-Validity-Duration' => [60],
+ 'AVP' => [{'OC-Supported-Features', []}]},
+ %% Include a NAS Failed-AVP AVP that will only be decoded under
+ %% that application. Encode as 'AVP' since RFC 3588 doesn't list
+ %% Failed-AVP in the answer-message grammar while RFC 6733 does.
+ NP = #diameter_avp{data = {nas4005, 'NAS-Port', 44}},
+ FR = #diameter_avp{name = 'Firmware-Revision', value = 12}, %% M=0
+ AP = #diameter_avp{name = 'Auth-Grace-Period', value = 13}, %% M=1
+ Failed = #diameter_avp{data = {diameter_gen_base_rfc3588,
+ 'Failed-AVP',
+ [{'AVP', [NP,FR,AP]}]}},
Ans = ['answer-message', {'Result-Code', ?TOO_BUSY},
{'Origin-Host', OH},
- {'Origin-Realm', OR}],
+ {'Origin-Realm', OR},
+ {'AVP', [{'OC-OLR', OLR}, Failed]}],
{reply, Ans};
-request(#diameter_base_ASR{'Session-Id' = SId,
- 'AVP' = Avps},
+%% send_proxy_info
+request(['ASR' | #{'Proxy-Info' := _}],
+ _) ->
+ {protocol_error, 3999};
+
+request(['ASR' | #{'Session-Id' := SId} = Avps],
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
{reply, ['ASA', {'Result-Code', ?SUCCESS},
{'Session-Id', SId},
{'Origin-Host', OH},
{'Origin-Realm', OR},
- {'AVP', Avps}]};
+ {'AVP', maps:get('AVP', Avps, [])}]};
%% send_invalid_reject
-request(#diameter_base_STR{'Termination-Cause' = ?USER_MOVED},
+request(['STR' | #{'Termination-Cause' := ?USER_MOVED}],
_Caps) ->
{protocol_error, ?TOO_BUSY};
%% send_noreply
-request(#diameter_base_STR{'Termination-Cause' = T},
+request(['STR' | #{'Termination-Cause' := T}],
_Caps)
when T /= ?LOGOUT ->
discard;
%% send_destination_5
-request(#diameter_base_STR{'Destination-Realm' = R},
+request(['STR' | #{'Destination-Realm' := R}],
#diameter_caps{origin_realm = {OR, _}})
when R /= undefined, R /= OR ->
{protocol_error, ?REALM_NOT_SERVED};
%% send_destination_6
-request(#diameter_base_STR{'Destination-Host' = [H]},
+request(['STR' | #{'Destination-Host' := [H]}],
#diameter_caps{origin_host = {OH, _}})
when H /= OH ->
{protocol_error, ?UNABLE_TO_DELIVER};
-request(#diameter_base_STR{'Session-Id' = SId},
+request(['STR' | #{'Session-Id' := SId}],
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
{reply, ['STA', {'Result-Code', ?SUCCESS},
@@ -1491,7 +1872,7 @@ request(#diameter_base_STR{'Session-Id' = SId},
{'Origin-Realm', OR}]};
%% send_error/send_timeout
-request(#diameter_base_RAR{}, _Caps) ->
+request(['RAR' | #{}], _Caps) ->
receive after 2000 -> {protocol_error, ?TOO_BUSY} end.
%% message/3
@@ -1505,8 +1886,8 @@ message(Dir, #diameter_packet{bin = Bin}, N) ->
message(Dir, Bin, N);
%% incoming request
-message(recv, <<_:32, 1, _/bits>> = Bin, N) ->
- [Bin, 1 < N, fun ?MODULE:message/3, N-1];
+message(recv, <<_:32, 1:1, _/bits>> = Bin, N) ->
+ [Bin, N < 16, fun ?MODULE:message/3, N+1];
%% incoming answer
message(recv, Bin, _) ->
@@ -1517,9 +1898,35 @@ message(send, Bin, _) ->
[Bin];
%% sent request
-message(ack, <<_:32, 1, _/bits>>, _) ->
+message(ack, <<_:32, 1:1, _/bits>>, _) ->
[];
%% sent answer or discarded request
message(ack, _, N) ->
- [0 =< N, fun ?MODULE:message/3, N+1].
+ [N =< 16, fun ?MODULE:message/3, N-1].
+
+%% ------------------------------------------------------------------------
+
+compile_and_load() ->
+ try
+ Path = hd([P || H <- [[here(), ".."], [code:lib_dir(diameter)]],
+ P <- [filename:join(H ++ ["examples",
+ "dict",
+ "rfc4005_nas.dia"])],
+ {ok, _} <- [file:read_file_info(P)]]),
+ {ok, [Forms]}
+ = diameter_make:codec(Path, [return,
+ forms,
+ {name, "nas4005"},
+ {prefix, "nas"},
+ {inherits, "common/diameter_gen_base_rfc3588"}]),
+ {ok, nas4005, Bin, []} = compile:forms(Forms, [debug_info, return]),
+ {module, nas4005} = code:load_binary(nas4005, "nas4005", Bin),
+ true
+ catch
+ E:R:Stack ->
+ {E, R, Stack}
+ end.
+
+here() ->
+ filename:dirname(code:which(?MODULE)).
diff --git a/lib/diameter/test/diameter_transport_SUITE.erl b/lib/diameter/test/diameter_transport_SUITE.erl
index 9d981d0a2b..284d2b9566 100644
--- a/lib/diameter/test/diameter_transport_SUITE.erl
+++ b/lib/diameter/test/diameter_transport_SUITE.erl
@@ -349,35 +349,40 @@ rand_bytes(N) ->
%% start_connect/3
start_connect(Prot, PortNr, Ref) ->
- {ok, TPid, [?ADDR]} = start_connect(Prot,
- {connect, Ref},
- ?SVC([]),
- [{raddr, ?ADDR},
- {rport, PortNr},
- {ip, ?ADDR},
- {port, 0}]),
- ?RECV(?TMSG({TPid, connected, _})),
+ {ok, TPid} = start_connect(Prot,
+ {connect, Ref},
+ ?SVC([]),
+ [{raddr, ?ADDR},
+ {rport, PortNr},
+ {ip, ?ADDR},
+ {port, 0}]),
+ connected(Prot, TPid),
TPid.
+connected(sctp, TPid) ->
+ ?RECV(?TMSG({TPid, connected, _}));
+connected(tcp, TPid) ->
+ ?RECV(?TMSG({TPid, connected, _, [?ADDR]})).
+
start_connect(sctp, T, Svc, Opts) ->
- diameter_sctp:start(T, Svc, [{sctp_initmsg, ?SCTP_INIT} | Opts]);
+ {ok, TPid, [?ADDR]}
+ = diameter_sctp:start(T, Svc, [{sctp_initmsg, ?SCTP_INIT} | Opts]),
+ {ok, TPid};
start_connect(tcp, T, Svc, Opts) ->
diameter_tcp:start(T, Svc, Opts).
%% start_accept/2
start_accept(Prot, Ref) ->
- {Mod, Opts} = tmod(Prot),
- {ok, TPid, [?ADDR]} = Mod:start({accept, Ref},
- ?SVC([?ADDR]),
- [{port, 0} | Opts]),
+ {ok, TPid, [?ADDR]}
+ = start_accept(Prot, {accept, Ref}, ?SVC([?ADDR]), [{port, 0}]),
?RECV(?TMSG({TPid, connected})),
TPid.
-tmod(sctp) ->
- {diameter_sctp, [{sctp_initmsg, ?SCTP_INIT}]};
-tmod(tcp) ->
- {diameter_tcp, []}.
+start_accept(sctp, T, Svc, Opts) ->
+ diameter_sctp:start(T, Svc, [{sctp_initmsg, ?SCTP_INIT} | Opts]);
+start_accept(tcp, T, Svc, Opts) ->
+ diameter_tcp:start(T, Svc, Opts).
%% ===========================================================================
diff --git a/lib/diameter/test/diameter_util.erl b/lib/diameter/test/diameter_util.erl
index 03f79096ac..d249b0e4fa 100644
--- a/lib/diameter/test/diameter_util.erl
+++ b/lib/diameter/test/diameter_util.erl
@@ -32,7 +32,8 @@
foldl/3,
scramble/1,
unique_string/0,
- have_sctp/0]).
+ have_sctp/0,
+ eprof/1]).
%% diameter-specific
-export([lport/2,
@@ -48,6 +49,16 @@
-define(L, atom_to_list).
+%% ---------------------------------------------------------------------------
+
+eprof(start) ->
+ eprof:start(),
+ eprof:start_profiling([self()]);
+
+eprof(stop) ->
+ eprof:stop_profiling(),
+ eprof:analyze(),
+ eprof:stop().
%% ---------------------------------------------------------------------------
%% name/2
diff --git a/lib/diameter/test/diameter_watchdog_SUITE.erl b/lib/diameter/test/diameter_watchdog_SUITE.erl
index 39c4f051a5..f3f168e671 100644
--- a/lib/diameter/test/diameter_watchdog_SUITE.erl
+++ b/lib/diameter/test/diameter_watchdog_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -638,10 +638,9 @@ run1([F|A]) ->
apply(?MODULE, F, A),
ok
catch
- E:R ->
- S = erlang:get_stacktrace(),
- ?WARN("~p", [{A, E, R, S}]),
- S
+ E:R:Stack ->
+ ?WARN("~p", [{A, E, R, Stack}]),
+ Stack
end.
%% jitter/2
diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk
index 4801f542fb..8c75c9e55e 100644
--- a/lib/diameter/vsn.mk
+++ b/lib/diameter/vsn.mk
@@ -1,6 +1,6 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2017. All Rights Reserved.
+# Copyright Ericsson AB 2010-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -17,5 +17,5 @@
# %CopyrightEnd%
APPLICATION = diameter
-DIAMETER_VSN = 2.0
+DIAMETER_VSN = 2.1.6
APP_VSN = $(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN)
diff --git a/lib/edoc/doc/src/Makefile b/lib/edoc/doc/src/Makefile
index ce7945a1bb..aba94a6802 100644
--- a/lib/edoc/doc/src/Makefile
+++ b/lib/edoc/doc/src/Makefile
@@ -9,11 +9,11 @@
# 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.
-#
+#
# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
# AB. All Rights Reserved.''
-#
+#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
@@ -47,16 +47,17 @@ XML_REF3_FILES = \
edoc_lib.xml \
edoc_run.xml
-XML_PART_FILES = part.xml part_notes.xml
+XML_PART_FILES = part.xml
XML_CHAPTER_FILES = chapter.xml
XML_NOTES_FILES = notes.xml
BOOK_FILES = book.xml
XML_FILES=\
- $(BOOK_FILES) $(XML_CHAPTER_FILES) \
- $(XML_PART_FILES) $(XML_REF3_FILES) $(XML_APPLICATION_FILES) \
- $(XML_NOTES_FILES)
+ $(BOOK_FILES) $(XML_APPLICATION_FILES) \
+ $(XML_PART_FILES) $(XML_NOTES_FILES)
+
+XML_GEN_FILES=$(XML_REF3_FILES:%=$(XMLDIR)/%) $(XML_CHAPTER_FILES:%=$(XMLDIR)/%)
# ----------------------------------------------------
INFO_FILE = ../../info
@@ -80,10 +81,10 @@ TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
+XML_FLAGS +=
+DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -101,27 +102,28 @@ html: gifs $(HTML_REF_MAN_FILE)
man: $(MAN3_FILES)
-$(XML_REF3_FILES):
- escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(EDOC_VSN) -i $(ERL_TOP)/lib/edoc/include $(SRC_DIR)/$(@:%.xml=%.erl)
+$(XML_REF3_FILES:%=$(XMLDIR)/%):
+ $(gen_verbose)escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(EDOC_VSN) -i $(ERL_TOP)/lib/edoc/include -dir $(XMLDIR) $(SRC_DIR)/$(@:$(XMLDIR)/%.xml=%.erl)
-$(XML_CHAPTER_FILES): ../overview.edoc
- escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(EDOC_VSN) -chapter ../overview.edoc
+$(XML_CHAPTER_FILES:%=$(XMLDIR)/%): ../overview.edoc
+ $(gen_verbose)escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(EDOC_VSN) -chapter -dir $(XMLDIR) $<
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-debug opt:
+debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(XML_REF3_FILES) $(XML_CHAPTER_FILES) *.html
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
+ rm -f errs core *~
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
diff --git a/lib/edoc/doc/src/fascicules.xml b/lib/edoc/doc/src/fascicules.xml
deleted file mode 100644
index 154c8a3b6d..0000000000
--- a/lib/edoc/doc/src/fascicules.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
-</fascicules>
-
diff --git a/lib/edoc/doc/src/notes.xml b/lib/edoc/doc/src/notes.xml
index 7894811c78..e818887eb8 100644
--- a/lib/edoc/doc/src/notes.xml
+++ b/lib/edoc/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2007</year><year>2017</year>
+ <year>2007</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,78 @@
<p>This document describes the changes made to the EDoc
application.</p>
+<section><title>Edoc 0.9.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Edoc 0.9.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Types and function specifications including the
+ <c>map()</c> type are pretty-printed correctly. </p>
+ <p>
+ Own Id: OTP-15117</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Update to use the new string api instead of the old.</p>
+ <p>
+ Own Id: OTP-15036</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Edoc 0.9.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> The map type is correctly denoted as <c>map()</c> in
+ function specifications and types. </p>
+ <p>
+ Own Id: OTP-14777</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Edoc 0.9.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Tools are updated to show Unicode atoms correctly.</p>
+ <p>
+ Own Id: OTP-14464</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Edoc 0.9</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/edoc/doc/src/part_notes.xml b/lib/edoc/doc/src/part_notes.xml
deleted file mode 100644
index 6a79435ff0..0000000000
--- a/lib/edoc/doc/src/part_notes.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2007</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>EDoc Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p><em>EDoc</em> is the Erlang program documentation generator.
- Inspired by the Javadoc (TM) tool for the Java (TM) programming
- language, EDoc is adapted to the conventions of the Erlang world,
- and has several features not found in Javadoc.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/edoc/priv/Makefile b/lib/edoc/priv/Makefile
index 9873136201..45bff37b39 100644
--- a/lib/edoc/priv/Makefile
+++ b/lib/edoc/priv/Makefile
@@ -1,6 +1,6 @@
#
# Copyright (C) 2004, Ericsson Telecommunications
-# Author: Richard Carlsson, Bertil Karlsson
+# Author: Richard Carlsson, Bertil Karlsson
#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
@@ -9,9 +9,6 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# Application version
# ----------------------------------------------------
include ../vsn.mk
-include ../../xmerl/vsn.mk
-include ../../syntax_tools/vsn.mk
-
# ----------------------------------------------------
# Release directory specification
@@ -23,21 +20,12 @@ RELSYSDIR = $(RELEASE_PATH)/lib/edoc-$(EDOC_VSN)
# Common Macros
#
-GEN_SCRIPT_SRC = edoc_generate.src
GEN_SCRIPT = edoc_generate
PRIV_FILES = stylesheet.css erlang.png edoc.dtd
-debug opt: $(GEN_SCRIPT)
-
-$(GEN_SCRIPT): ../vsn.mk ../../xmerl/vsn.mk ../../syntax_tools/vsn.mk \
- $(GEN_SCRIPT_SRC)
- $(vsn_verbose)sed -e "s/%EDOC_VSN%/$(EDOC_VSN)/g" \
- -e "s/%XMERL_VSN%/$(XMERL_VSN)/g" \
- -e "s/%SYNTAX_TOOLS_VSN%/$(SYNTAX_TOOLS_VSN)/g" \
- $(GEN_SCRIPT_SRC) > $(GEN_SCRIPT)
+debug opt:
clean:
- rm -f $(GEN_SCRIPT)
rm -f core *~
docs:
@@ -54,4 +42,3 @@ release_spec: opt
release_docs_spec:
-
diff --git a/lib/edoc/priv/edoc_generate b/lib/edoc/priv/edoc_generate
new file mode 100644
index 0000000000..0492623c7f
--- /dev/null
+++ b/lib/edoc/priv/edoc_generate
@@ -0,0 +1,50 @@
+#!/bin/sh
+# ``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.
+#
+# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+# Portions created by Ericsson are Copyright 1999-2000, Ericsson
+# Utvecklings AB. All Rights Reserved.''
+#
+
+APP=
+TITLE=
+VSN=
+
+while [ $# -gt 0 ]; do
+ case $1 in
+ -app)
+ APP=$2;
+ shift;
+ shift;;
+ -title)
+ TITLE=$2;
+ shift;
+ shift;;
+ -vsn)
+ VSN=$2;
+ shift;
+ shift;;
+ esac
+done
+
+if [ -n "$APP" -a -n "$TITLE" ] ; then
+ erl -boot start_clean -noshell \
+ -run edoc_run application $APP "\".\"" "[{title,$TITLE}]" \
+ -s erlang halt
+elif [ -n "$APP" -a -n "$VSN" ] ; then
+ erl -boot start_clean -noshell \
+ -run edoc_run application $APP "\".\"" "[{def,{vsn,\"$VSN\"}}]" \
+ -s erlang halt
+else
+ echo "Usage: edoc_generate [-app Appname [-title Title |-vsn Vsn]]"
+fi
diff --git a/lib/edoc/priv/edoc_generate.src b/lib/edoc/priv/edoc_generate.src
deleted file mode 100644
index eeaa20f959..0000000000
--- a/lib/edoc/priv/edoc_generate.src
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/bin/sh
-# ``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.
-#
-# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-# Portions created by Ericsson are Copyright 1999-2000, Ericsson
-# Utvecklings AB. All Rights Reserved.''
-#
-
-#EDOC_DIR=/clearcase/otp/internal_tools/edoc
-EDOC_DIR=/home/otp/sgml/edoc-%EDOC_VSN%
-SYNTAX_TOOLS_DIR=/home/otp/sgml/syntax_tools-%SYNTAX_TOOLS_VSN%
-XMERL_DIR=/home/otp/sgml/xmerl-%XMERL_VSN%
-
-FILE=
-APP=
-TITLE=
-VSN=
-
-while [ $# -gt 0 ]; do
- case $1 in
- -file)
- FILE=$2;
- shift;
- shift;;
- -app)
- APP=$2;
- shift;
- shift;;
- -title)
- TITLE=$2;
- shift;
- shift;;
- -vsn)
- VSN=$2;
- shift;
- shift;;
- esac
-done
-
-if [ -n "$FILE" ] ; then
- EDOC_ARGS="[{layout,otpsgml_layout},{dir,\".\"},{file_suffix,\".sgml\"},{preprocess,true},{includes,[\"$XMERL_DIR/include\"]}]"
- erl -boot start_clean -noshell \
- -pa $EDOC_DIR/ebin \
- -pa $SYNTAX_TOOLS_DIR/ebin \
- -pa $XMERL_DIR/ebin \
- -run edoc_run file $FILE $EDOC_ARGS \
- -s erlang halt
-elif [ -n "$APP" -a -n "$TITLE" ] ; then
- erl -boot start_clean -noshell \
- -pa $EDOC_DIR/ebin \
- -pa $SYNTAX_TOOLS_DIR/ebin \
- -pa $XMERL_DIR/ebin \
- -run edoc_run application $APP "\".\"" "[{title,$TITLE}]" \
- -s erlang halt
-elif [ -n "$APP" -a -n "$VSN" ] ; then
- erl -boot start_clean -noshell \
- -pa $EDOC_DIR/ebin \
- -pa $SYNTAX_TOOLS_DIR/ebin \
- -pa $XMERL_DIR/ebin \
- -run edoc_run application $APP "\".\"" "[{def,{vsn,\"$VSN\"}}]" \
- -s erlang halt
-else
- echo "Usage: docb_edoc [-file Filename] | [-app Appname [-title Title |-vsn Vsn]]"
-fi
diff --git a/lib/edoc/src/Makefile b/lib/edoc/src/Makefile
index 4e5a4182da..ea2f45dc4c 100644
--- a/lib/edoc/src/Makefile
+++ b/lib/edoc/src/Makefile
@@ -29,8 +29,7 @@ SOURCES= \
edoc.erl edoc_data.erl edoc_doclet.erl edoc_extract.erl \
edoc_layout.erl edoc_lib.erl edoc_macros.erl edoc_parser.erl \
edoc_refs.erl edoc_report.erl edoc_run.erl edoc_scanner.erl \
- edoc_specs.erl edoc_tags.erl edoc_types.erl edoc_wiki.erl \
- otpsgml_layout.erl
+ edoc_specs.erl edoc_tags.erl edoc_types.erl edoc_wiki.erl
OBJECTS=$(SOURCES:%.erl=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
diff --git a/lib/edoc/src/edoc.app.src b/lib/edoc/src/edoc.app.src
index e4b9040c78..43343e2ae8 100644
--- a/lib/edoc/src/edoc.app.src
+++ b/lib/edoc/src/edoc.app.src
@@ -18,8 +18,7 @@
edoc_specs,
edoc_tags,
edoc_types,
- edoc_wiki,
- otpsgml_layout]},
+ edoc_wiki]},
{registered,[]},
{applications, [compiler,kernel,stdlib,syntax_tools]},
{env, []},
diff --git a/lib/edoc/src/edoc_doclet.erl b/lib/edoc/src/edoc_doclet.erl
index 6e17ec0af0..6cb3095507 100644
--- a/lib/edoc/src/edoc_doclet.erl
+++ b/lib/edoc/src/edoc_doclet.erl
@@ -40,7 +40,7 @@
-import(edoc_report, [report/2, warning/2]).
-%% @headerfile "edoc_doclet.hrl"
+%% @headerfile "../include/edoc_doclet.hrl"
-include("../include/edoc_doclet.hrl").
-define(EDOC_APP, edoc).
@@ -198,7 +198,7 @@ source({M, Name, Path}, Dir, Suffix, Env, Set, Private, Hidden,
{Set, Error}
end;
R ->
- report("skipping source file '~ts': ~P.", [File, R, 15]),
+ report("skipping source file '~ts': ~tP.", [File, R, 15]),
{Set, true}
end.
@@ -255,7 +255,7 @@ modules_frame(Dir, Ms, Title, CSS) ->
?NL,
{table, [{width, "100%"}, {border, 0},
{summary, "list of modules"}],
- lists:concat(
+ lists:append(
[[?NL,
{tr, [{td, [],
[{a, [{href, module_ref(M)},
@@ -448,7 +448,7 @@ application_frame(Dir, Apps, Title, CSS) ->
{h2, ["Applications"]},
?NL,
{table, [{width, "100%"}, {border, 0}],
- lists:concat(
+ lists:append(
[[{tr, [{td, [], [{a, [{href,app_ref(Path,App)},
{target,"_top"}],
[App]}]}]}]
diff --git a/lib/edoc/src/edoc_layout.erl b/lib/edoc/src/edoc_layout.erl
index eafab0588e..47ff7b21fc 100644
--- a/lib/edoc/src/edoc_layout.erl
+++ b/lib/edoc/src/edoc_layout.erl
@@ -608,7 +608,7 @@ etypef([Cs | L], St, O, R, Opts) ->
app_fix(L, Opts) ->
try
{"//" ++ R1,L2} = app_fix1(L, 1),
- [App, Mod] = string:tokens(R1, "/"),
+ [App, Mod] = string:lexemes(R1, "/"),
"//" ++ atom(App, Opts) ++ "/" ++ atom(Mod, Opts) ++ L2
catch _:_ -> L
end.
@@ -1120,13 +1120,13 @@ ot_integer(E) ->
{integer,0,list_to_integer(get_attrval(value, E))}.
ot_range(E) ->
- [I1, I2] = string:tokens(get_attrval(value, E), "."),
+ [I1, I2] = string:lexemes(get_attrval(value, E), "."),
{type,0,range,[{integer,0,list_to_integer(I1)},
{integer,0,list_to_integer(I2)}]}.
ot_binary(E) ->
{Base, Unit} =
- case string:tokens(get_attrval(value, E), ",:*><") of
+ case string:lexemes(get_attrval(value, E), ",:*><") of
[] ->
{0, 0};
["_",B] ->
@@ -1193,6 +1193,8 @@ ot_name(Es, T) ->
{atom,0,list_to_atom(Atom)},T]};
"tuple" when T =:= [] ->
{type,0,tuple,any};
+ "map" when T =:= [] ->
+ {type,0,map,any};
Atom ->
{type,0,list_to_atom(Atom),T}
end.
diff --git a/lib/edoc/src/edoc_lib.erl b/lib/edoc/src/edoc_lib.erl
index ebdb0f79f6..d00a283794 100644
--- a/lib/edoc/src/edoc_lib.erl
+++ b/lib/edoc/src/edoc_lib.erl
@@ -541,13 +541,13 @@ uri_get_http_1(Result, URI) ->
Reason = inet:format_error(R),
{error, http_errmsg(Reason, URI)};
{ok, R} ->
- Reason = io_lib:format("bad return value ~P", [R, 5]),
+ Reason = io_lib:format("bad return value ~tP", [R, 5]),
{error, http_errmsg(Reason, URI)};
{'EXIT', R} ->
- Reason = io_lib:format("crashed with reason ~w", [R]),
+ Reason = io_lib:format("crashed with reason ~tw", [R]),
{error, http_errmsg(Reason, URI)};
R ->
- Reason = io_lib:format("uncaught throw: ~w", [R]),
+ Reason = io_lib:format("uncaught throw: ~tw", [R]),
{error, http_errmsg(Reason, URI)}
end.
@@ -603,7 +603,7 @@ filename([]) ->
filename(N) when is_atom(N) ->
atom_to_list(N);
filename(N) ->
- report("bad filename: `~P'.", [N, 25]),
+ report("bad filename: `~tP'.", [N, 25]),
exit(error).
%% @private
@@ -1000,7 +1000,7 @@ run_plugin(Name, Key, Default, Fun, Opts) when is_atom(Name) ->
{ok, Value} ->
Value;
R ->
- report("error in ~ts '~w': ~P.", [Name, Module, R, 20]),
+ report("error in ~ts '~w': ~tP.", [Name, Module, R, 20]),
exit(error)
end.
@@ -1009,7 +1009,7 @@ get_plugin(Key, Default, Opts) ->
M when is_atom(M) ->
M;
Other ->
- report("bad value for option '~w': ~P.", [Key, Other, 10]),
+ report("bad value for option '~w': ~tP.", [Key, Other, 10]),
exit(error)
end.
diff --git a/lib/edoc/src/edoc_run.erl b/lib/edoc/src/edoc_run.erl
index c88c6cfd78..50aba0a930 100644
--- a/lib/edoc/src/edoc_run.erl
+++ b/lib/edoc/src/edoc_run.erl
@@ -150,7 +150,7 @@ file(Args) ->
-spec invalid_args(string(), args()) -> no_return().
invalid_args(Where, Args) ->
- report("invalid arguments to ~ts: ~w.", [Where, Args]),
+ report("invalid arguments to ~ts: ~tw.", [Where, Args]),
shutdown_error().
run(F) ->
@@ -159,10 +159,10 @@ run(F) ->
{ok, _} ->
shutdown_ok();
{'EXIT', E} ->
- report("edoc terminated abnormally: ~P.", [E, 10]),
+ report("edoc terminated abnormally: ~tP.", [E, 10]),
shutdown_error();
Thrown ->
- report("internal error: throw without catch in edoc: ~P.",
+ report("internal error: throw without catch in edoc: ~tP.",
[Thrown, 15]),
shutdown_error()
end.
diff --git a/lib/edoc/src/edoc_specs.erl b/lib/edoc/src/edoc_specs.erl
index fb04bfce0e..7b451c43f8 100644
--- a/lib/edoc/src/edoc_specs.erl
+++ b/lib/edoc/src/edoc_specs.erl
@@ -83,7 +83,7 @@ spec(Form, Clause) ->
%% the given Erlang spec and an empty list of arguments.
dummy_spec(Form) ->
{#t_name{name = Name}, Arity, TypeSpecs} = get_spec(Form),
- As = string:join(lists:duplicate(Arity, "_X"), ","),
+ As = lists:join(",", lists:duplicate(Arity, "_X")),
S = lists:flatten(io_lib:format("~p(~s) -> true\n", [Name, As])),
#tag{name = spec, line = get_line(element(2, hd(TypeSpecs))),
origin = code, data = S}.
@@ -372,7 +372,7 @@ d2e({type,_,binary,[Base,Unit]}, _Prec) ->
{integer,_,U} = erl_eval:partial_eval(Unit),
#t_binary{base_size = B, unit_size = U};
d2e({type,_,map,any}, _Prec) ->
- #t_map{types = []};
+ #t_type{name = #t_name{name = map}, args = []};
d2e({type,_,map,Es}, _Prec) ->
#t_map{types = d2e(Es) };
d2e({type,_,map_field_assoc,[K,V]}, Prec) ->
diff --git a/lib/edoc/src/edoc_types.erl b/lib/edoc/src/edoc_types.erl
index ccc3169767..510f9513b2 100644
--- a/lib/edoc/src/edoc_types.erl
+++ b/lib/edoc/src/edoc_types.erl
@@ -107,7 +107,7 @@ to_xml(#t_paren{type = T}, Env) ->
to_xml(#t_nonempty_list{type = T}, Env) ->
{nonempty_list, [wrap_utype(T, Env)]};
to_xml(#t_atom{val = V}, _Env) ->
- {atom, [{value, io_lib:write(V)}], []};
+ {atom, [{value, atom_to_list(V)}], []};
to_xml(#t_integer{val = V}, _Env) ->
{integer, [{value, integer_to_list(V)}], []};
to_xml(#t_integer_range{from = From, to = To}, _Env) ->
diff --git a/lib/edoc/src/otpsgml_layout.erl b/lib/edoc/src/otpsgml_layout.erl
deleted file mode 100644
index 295daed551..0000000000
--- a/lib/edoc/src/otpsgml_layout.erl
+++ /dev/null
@@ -1,836 +0,0 @@
-%% =====================================================================
-%% 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.
-%%
-%% Alternatively, you may use this file under the terms of the GNU Lesser
-%% General Public License (the "LGPL") as published by the Free Software
-%% Foundation; either version 2.1, or (at your option) any later version.
-%% If you wish to allow use of your version of this file only under the
-%% terms of the LGPL, you should delete the provisions above and replace
-%% them with the notice and other provisions required by the LGPL; see
-%% <http://www.gnu.org/licenses/>. If you do not delete the provisions
-%% above, a recipient may use your version of this file under the terms of
-%% either the Apache License or the LGPL.
-%%
-%% @author Richard Carlsson <[email protected]>
-%% @author Kenneth Lundin <[email protected]>
-%% @copyright 2001-2004 Richard Carlsson
-%% @see edoc_layout
-%% @end
-%% =====================================================================
-
-%% @doc The OTP SGML layout module for EDoc. See the module {@link edoc}
-%% for details on usage.
-
-%% Note that this is written so that it is *not* depending on edoc.hrl!
-
--module(otpsgml_layout).
-
--export([module/2, overview/2,type/1]).
-
--import(edoc_report, [report/2]).
-
--include_lib("xmerl/include/xmerl.hrl").
-
--define(SGML_EXPORT, xmerl_otpsgml).
--define(DEFAULT_XML_EXPORT, ?SGML_EXPORT).
--define(STYLESHEET, "stylesheet.css").
--define(NL, "\n").
--define(DESCRIPTION_TITLE, "Description").
--define(DESCRIPTION_LABEL, "description").
--define(DATA_TYPES_TITLE, "Data Types").
--define(DATA_TYPES_LABEL, "types").
--define(FUNCTION_INDEX_TITLE, "Function Index").
--define(FUNCTION_INDEX_LABEL, "index").
--define(FUNCTIONS_TITLE, "Function Details").
--define(FUNCTIONS_LABEL, "functions").
-
-
-%% @doc The layout function.
-%%
-%% Options:
-%% <dl>
-%% <dt>{@type {index_columns, integer()@}}
-%% </dt>
-%% <dd>Specifies the number of column pairs used for the function
-%% index tables. The default value is 1.
-%% </dd>
-%% <dt>{@type {stylesheet, string()@}}
-%% </dt>
-%% <dd>Specifies the URI used for referencing the stylesheet. The
-%% default value is `"stylesheet.css"'. If an empty string is
-%% specified, no stylesheet reference will be generated.
-%% </dd>
-%% <dt>{@type {xml_export, Module::atom()@}}
-%% </dt>
-%% <dd>Specifies an {@link //xmerl. `xmerl'} callback module to be
-%% used for exporting the documentation. See {@link
-%% //xmerl/xmerl:export_simple/3} for details.
-%% </dd>
-%% </dl>
-%%
-%% @see edoc:layout/2
-
--record(opts, {root, stylesheet, index_columns}).
-
-module(Element, Options) ->
- XML = layout_module(Element, init_opts(Element, Options)),
- Export = proplists:get_value(xml_export, Options,
- ?DEFAULT_XML_EXPORT),
- xmerl:export_simple([XML], Export, []).
-
-% Put layout options in a data structure for easier access.
-
-init_opts(Element, Options) ->
- R = #opts{root = get_attrval(root, Element),
- index_columns = proplists:get_value(index_columns,
- Options, 1)
- },
- case proplists:get_value(stylesheet, Options) of
- undefined ->
- S = edoc_lib:join_uri(R#opts.root, ?STYLESHEET),
- R#opts{stylesheet = S};
- "" ->
- R; % don't use any stylesheet
- S when is_list(S) ->
- R#opts{stylesheet = S};
- _ ->
- report("bad value for option `stylesheet'.", []),
- exit(error)
- end.
-
-
-%% =====================================================================
-%% XML-BASED LAYOUT ENGINE
-%% =====================================================================
-
-%% We assume that we have expanded XML data.
-
-%% <!ELEMENT module (moduleName, moduleFullName, behaviour*, description?,
-%% author*, version?, since?, copyright?, deprecated?,
-%% see*, reference*, typedecls?, functions)>
-%% <!ATTLIST module
-%% root CDATA #IMPLIED>
-%% <!ELEMENT moduleName (#PCDATA)>
-%% <!ELEMENT moduleFullName (#PCDATA)>
-%% <!ELEMENT behaviour (#PCDATA)>
-%% <!ATTLIST behaviour
-%% href CDATA #IMPLIED>
-%% <!ELEMENT description (briefDescription, fullDescription?)>
-%% <!ELEMENT briefDescription (#PCDATA)>
-%% <!ELEMENT fullDescription (#PCDATA)>
-%% <!ELEMENT author EMPTY>
-%% <!ATTLIST author
-%% name CDATA #REQUIRED
-%% email CDATA #IMPLIED
-%% website CDATA #IMPLIED>
-%% <!ELEMENT version (#PCDATA)>
-%% <!ELEMENT since (#PCDATA)>
-%% <!ELEMENT copyright (#PCDATA)>
-%% <!ELEMENT deprecated (description)>
-%% <!ELEMENT see (#PCDATA)>
-%% <!ATTLIST see
-%% name CDATA #REQUIRED
-%% href CDATA #IMPLIED>
-%% <!ELEMENT reference (#PCDATA)>
-%% <!ELEMENT typedecls (typedecl+)>
-%% <!ELEMENT functions (function+)>
-
-layout_module(#xmlElement{name = module, content = Es}=E, _Opts) ->
- Name = get_attrval(name, E),
- Desc = get_content(description, Es),
- ShortDesc = get_content(briefDescription, Desc),
- FullDesc = get_content(fullDescription, Desc),
- Functions = [E || E <- get_content(functions, Es)],
- SortedFs = lists:sort([{function_name(E), E} || E <- Functions]),
- Types = get_content(typedecls, Es),
- SortedTs = lists:sort([{type_name(E), E} || E <- Types]),
- Header = {header, [
- ?NL,{title, [Name]},
- ?NL,{prepared, [""]},
- ?NL,{responsible, [""]},
- ?NL,{docno, ["1"]},
- ?NL,{approved, [""]},
- ?NL,{checked, [""]},
- ?NL,{date, [""]},
- ?NL,{rev, ["A"]},
- ?NL,{file, [Name++".sgml"]}
- ]},
- Module = {module, [Name]},
- ModuleSummary = {modulesummary, ShortDesc},
- {Short,Long} = find_first_p(FullDesc,[]),
- Description = {description, [?NL,{p,Short}|Long]++[?NL|types(SortedTs)]},
- Funcs = functions(SortedFs),
- Authors = {authors, authors(Es)},
- See = sees1(Es),
- {erlref, [
- ?NL,Header,
- ?NL,Module,
- ?NL,ModuleSummary,
- ?NL,Description,
- ?NL,Funcs,
- ?NL,See,
- ?NL,Authors
- ]
- }.
-
-stylesheet(Opts) ->
- case Opts#opts.stylesheet of
- undefined ->
- [];
- CSS ->
- [{link, [{rel, "stylesheet"},
- {type, "text/css"},
- {href, CSS}], []},
- ?NL]
- end.
-
-% doc_index(FullDesc, Functions, Types) ->
-% case doc_index_rows(FullDesc, Functions, Types) of
-% [] -> [];
-% Rs ->
-% [{ul, [{li, [{a, [{href, local_label(R)}], [T]}]}
-% || {T, R} <- Rs]}]
-% end.
-
-% doc_index_rows(FullDesc, Functions, Types) ->
-% (if FullDesc == [] -> [];
-% true -> [{?DESCRIPTION_TITLE, ?DESCRIPTION_LABEL}]
-% end
-% ++ if Types == [] -> [];
-% true -> [{?DATA_TYPES_TITLE, ?DATA_TYPES_LABEL}]
-% end
-% ++ if Functions == [] -> [];
-% true -> [{?FUNCTION_INDEX_TITLE, ?FUNCTION_INDEX_LABEL},
-% {?FUNCTIONS_TITLE, ?FUNCTIONS_LABEL}]
-% end).
-
-% function_index(Fs, Cols) ->
-% case function_index_rows(Fs, Cols, []) of
-% [] -> [];
-% Rows ->
-% [?NL,
-% {h2, [{a, [{name, ?FUNCTION_INDEX_LABEL}],
-% [?FUNCTION_INDEX_TITLE]}]},
-% ?NL,
-% {table, [{width, "100%"}, {border, 1}], Rows},
-% ?NL]
-% end.
-
-% function_index_rows(Fs, Cols, Title) ->
-% Rows = (length(Fs) + (Cols - 1)) div Cols,
-% (if Title == [] -> [];
-% true -> [{tr, [{th, [{colspan, Cols * 2}, {align, left}],
-% [Title]}]},
-% ?NL]
-% end
-% ++ lists:flatmap(fun index_row/1,
-% edoc_lib:transpose(edoc_lib:segment(Fs, Rows)))).
-
-% index_row(Fs) ->
-% [{tr, lists:flatmap(fun index_col/1, Fs)}, ?NL].
-
-% index_col({Name, F=#xmlElement{content = Es}}) ->
-% [{td, [{valign, "top"}], label_href([Name], F)},
-% {td, index_desc(Es)}].
-
-index_desc(Es) ->
- Desc = get_content(description, Es),
- case get_content(briefDescription, Desc) of
- [] ->
- equiv(Es); % no description at all if no equiv
- ShortDesc ->
- ShortDesc
- end.
-
-% label_href(Content, F) ->
-% case get_attrval(label, F) of
-% "" -> Content;
-% Ref -> [{a, [{href, local_label(Ref)}], Content}]
-% end.
-
-
-%% <!ELEMENT function (args, typespec?, equiv?, description?, since?,
-%% deprecated?, see*)>
-%% <!ATTLIST function
-%% name CDATA #REQUIRED
-%% arity CDATA #REQUIRED
-%% exported NMTOKEN(yes | no) #REQUIRED
-%% label CDATA #IMPLIED>
-%% <!ELEMENT args (arg*)>
-%% <!ELEMENT arg description?>
-%% <!ATTLIST arg name CDATA #REQUIRED>
-
-
-%% <!ELEMENT equiv (expr, see?)>
-%% <!ELEMENT expr (#PCDATA)>
-
-% functions(Fs) ->
-% Es = lists:flatmap(fun ({Name, E}) -> function(Name, E) end, Fs),
-% if Es == [] -> [];
-% true ->
-% [?NL,
-% {h2, [{a, [{name, ?FUNCTIONS_LABEL}], [?FUNCTIONS_TITLE]}]},
-% ?NL | Es]
-% end.
-
-functions(Fs) ->
- Es = lists:flatmap(fun ({Name, E}) -> function(Name, E) end, Fs),
- if Es == [] -> [];
- true ->
- {funcs, Es}
- end.
-
-% is_exported(E) ->
-% case get_attrval(exported, E) of
-% "yes" -> true;
-% _ -> false
-% end.
-
-% function(Name, E=#xmlElement{content = Es}) ->
-% ([?NL, {h3, label_anchor([Name], E)}, ?NL]
-% ++ case typespec(get_content(typespec, Es)) of
-% [] ->
-% signature(get_content(arguments, Es),
-% get_text(functionName, Es));
-% Spec -> Spec
-% end
-% ++ equiv(Es)
-% ++ deprecated(Es, "function")
-% ++ fulldesc(Es)
-% ++ since(Es)
-% ++ sees(Es)).
-
-function(_Name, E=#xmlElement{content = Es}) ->
- TypeSpec = get_content(typespec, Es),
- [?NL,{func, [ ?NL,
- {name,
-% case typespec(get_content(typespec, Es)) of
- case funcheader(TypeSpec) of
- [] ->
- signature(get_content(args, Es),
- get_attrval(name, E));
- Spec -> Spec
- end
- },
- ?NL,{fsummary, fsummary(Es)},
-% ?NL,{type, local_types(TypeSpec)},
- ?NL,local_types(TypeSpec),
- ?NL,{desc, label_anchor(E)++fulldesc(Es)++sees(Es)}
- ]}].
-
-fsummary([]) -> ["\s"];
-fsummary(Es) ->
- Desc = get_content(description, Es),
- case get_content(briefDescription, Desc) of
- [] ->
- fsummary_equiv(Es); % no description at all if no equiv
- ShortDesc ->
- ShortDesc
- end.
-
-
-fsummary_equiv(Es) ->
- case get_content(equiv, Es) of
- [] -> ["\s"];
- Es1 ->
- case get_content(expr, Es1) of
- [] -> ["\s"];
- [Expr] ->
- ["Equivalent to ", Expr, ".",?NL]
- end
- end.
-
-
-function_name(E) ->
- get_attrval(name, E) ++ "/" ++ get_attrval(arity, E).
-
-label_anchor(E) ->
- case get_attrval(label, E) of
- "" -> [];
- Ref -> [{marker, [{id, Ref}],[]},?NL]
- end.
-
-label_anchor(Content, E) ->
- case get_attrval(label, E) of
- "" -> Content;
- Ref -> {p,[{marker, [{id, Ref}],[]},
- {em, Content}]}
- end.
-
-%% <!ELEMENT args (arg*)>
-%% <!ELEMENT arg (argName, description?)>
-%% <!ELEMENT argName (#PCDATA)>
-
-%% This is currently only done for functions without type spec.
-
-signature(Es, Name) ->
-% [{tt, [Name, "("] ++ seq(fun arg/1, Es) ++ [") -> term()", ?NL]}].
- [Name, "("] ++ seq(fun arg/1, Es) ++ [") -> term()", ?NL].
-
-arg(#xmlElement{content = Es}) ->
- [get_text(argName, Es)].
-
-%% <!ELEMENT typespec (erlangName, type, localdef*)>
-
-% typespec([]) -> [];
-% typespec(Es) ->
-% [{p, ([{tt, ([t_name(get_elem(qualifiedName, Es))]
-% ++ t_type(get_content(type, Es)))}]
-% ++ local_defs(get_elem(definition, Es)))},
-% ?NL].
-
-funcheader([]) -> [];
-funcheader(Es) ->
- [t_name(get_elem(erlangName, Es))] ++ t_utype(get_elem(type, Es)).
-
-local_types([]) -> [];
-local_types(Es) ->
- local_defs2(get_elem(localdef, Es)).
-
-local_defs2([]) -> [];
-local_defs2(Es) ->
- {type,[?NL | [{v, localdef(E)} || E <- Es]]}.
-
-%% <!ELEMENT typedecl (typedef, description?)>
-%% <!ELEMENT typedef (erlangName, argtypes, type?, localdef*)>
-
-types([]) -> [];
-types(Ts) ->
- Es = lists:flatmap(fun ({Name, E}) -> typedecl(Name, E) end, Ts),
- [?NL,
-% {h2, [{a, [{name, ?DATA_TYPES_LABEL}],
-% [?DATA_TYPES_TITLE]}]},
-% ?NL | Es]
- {p,[{marker, [{id, ?DATA_TYPES_LABEL}],[]},
- {em,[?DATA_TYPES_TITLE]}]},
- ?NL, {taglist,[?NL|Es]}].
-
-%%type(Name, E=#xmlElement{content = Es}) ->
-%% ([?NL, {h3, label_anchor([Name, "()"], E)}, ?NL]
-%% ++ [{p, typedef(get_content(typedef, Es))}, ?NL]
-%% ++ fulldesc(Es)).
-typedecl(_Name, #xmlElement{content = Es}) ->
- [{tag, typedef(get_content(typedef, Es))},?NL,{item,fulldesc(Es)},?NL].
-
-
-type_name(#xmlElement{content = Es}) ->
- t_name(get_elem(erlangName, get_content(typedef, Es))).
-
-typedef(Es) ->
- Name = ([t_name(get_elem(erlangName, Es)), "("]
- ++ seq(fun t_utype_elem/1, get_content(argtypes, Es), [")"])),
- (case get_elem(type, Es) of
- [] -> [{b, ["abstract datatype"]}, ": ", {tt, Name}];
- Type ->
- [{tt, Name ++ [" = "] ++ t_utype(Type)}]
- end
- ++ local_defs(get_elem(localdef, Es))).
-
-local_defs([]) -> [];
-local_defs(Es) ->
- [?NL, {ul, [{li, [{tt, localdef(E)}]} || E <- Es]}].
-
-localdef(E = #xmlElement{content = Es}) ->
- (case get_elem(typevar, Es) of
- [] ->
- label_anchor(t_abstype(get_content(abstype, Es)), E);
- [V] ->
- t_var(V)
- end
- ++ [" = "] ++ t_utype(get_elem(type, Es))).
-
-fulldesc(Es) ->
- case get_content(fullDescription, get_content(description, Es)) of
-% [] -> [?NL];
- [] -> index_desc(Es);
-% Desc -> [{p, Desc}, ?NL]
- Desc ->
- {Short,Long} = find_first_p(Desc,[]),
- [?NL,{p,Short}|Long] ++[?NL]
- end.
-
-find_first_p([#xmlElement{name=p}|_]=Long,Short) ->
- {lists:reverse(Short),Long};
-find_first_p([H|T],Short) ->
- find_first_p(T,[H|Short]);
-find_first_p([],Short) ->
- {lists:reverse(Short),[]}.
-
-
-sees1(Es) ->
- case get_elem(see, Es) of
- [] -> [];
- Es1 ->
- {section,[{title,["See also"]},{p,seq(fun see/1, Es1, [])}]}
- end.
-
-sees(Es) ->
- case get_elem(see, Es) of
- [] -> [];
- Es1 ->
- [{p, [{em, ["See also:"]}, " "] ++ seq(fun see/1, Es1, ["."])},
- ?NL]
- end.
-
-see(E=#xmlElement{content = Es}) ->
- see(E,Es).
-
-see(E, Es) ->
- case get_attrval(href, E) of
- "" -> Es;
- Ref ->
- case lists:reverse(Ref) of
- "lmgs.ppa_"++Ppa ->
- App = lists:reverse(Ppa),
- [{seealso, [{marker, App++"_app"}], [App]},"(6)"];
- "lmgs."++Dom ->
- Mod = lists:reverse(Dom),
- [{seealso, [{marker, Mod}], [Mod]},"(3)"];
- _ ->
- [{seealso, [{marker, Ref}], Es}]
- end
- end.
-
-equiv(Es) ->
- case get_content(equiv, Es) of
- [] -> ["\s"];
- Es1 ->
- case get_content(expr, Es1) of
- [] -> [];
- [Expr] ->
-% Expr1 = {tt, [Expr]},
-% Expr1 = {c, [Expr]},
- Expr1 = [Expr],
- Expr2 = case get_elem(see, Es1) of
- [] ->
- {c,Expr1};
- [E=#xmlElement{}] ->
-% see(E,Expr1)
- case get_attrval(href, E) of
- "" ->
- {c,Expr1};
- Ref ->
- {seealso, [{marker, Ref}], Expr1}
- end
- end,
- [{p, ["Equivalent to ", Expr2, "."]}, ?NL]
- end
- end.
-
-% replace_minus_with_percent([$-|T]) ->
-% [$%|T];
-% replace_minus_with_percent([H|T]) ->
-% [H|replace_minus_with_percent(T)].
-
-copyright(Es) ->
- case get_content(copyright, Es) of
- [] -> [];
- Es1 ->
- [{p, ["Copyright \251 " | Es1]}, ?NL]
- end.
-
-version(Es) ->
- case get_content(version, Es) of
- [] -> [];
- Es1 ->
- [{p, [{b, ["Version:"]}, " " | Es1]}, ?NL]
- end.
-
-since(Es) ->
- case get_content(since, Es) of
- [] -> [];
- Es1 ->
- [{p, [{b, ["Introduced in:"]}, " " | Es1]}, ?NL]
- end.
-
-deprecated(Es, S) ->
- Es1 = get_content(description, get_content(deprecated, Es)),
- case get_content(fullDescription, Es1) of
- [] -> [];
- Es2 ->
- [{p, [{b, ["This " ++ S ++ " is deprecated:"]}, " " | Es2]},
- ?NL]
- end.
-
-% behaviours(Es) ->
-% case get_elem(behaviour, Es) of
-% [] -> [];
-% Es1 ->
-% [{p, [{b, ["Behaviour:"]}, " "] ++ seq(fun behaviour/1, Es1, ["."])},
-% ?NL]
-% end.
-
-% behaviour(E=#xmlElement{content = Es}) ->
-% case get_attrval(href, E) of
-% "" -> [{tt, Es}];
-% Ref -> [{a, [{href, Ref}], [{tt, Es}]}]
-% end.
-
-authors(Es) ->
- case get_elem(author, Es) of
- [] -> [?NL,{aname,["\s"]},?NL,{email,["\s"]}];
- Es1 -> [?NL|seq(fun author/1, Es1, [])]
-%
-% [{p, [{b, ["Authors:"]}, " "] ++ seq(fun author/1, Es1, ["."])},
-% ?NL]
- end.
-
-
-%% <!ATTLIST author
-%% name CDATA #REQUIRED
-%% email CDATA #IMPLIED
-%% website CDATA #IMPLIED>
-
-author(E=#xmlElement{}) ->
- Name = case get_attrval(name, E) of
- [] -> "\s";
- N -> N
- end,
- Mail = case get_attrval(email, E) of
- [] -> "\s";
- M -> M
- end,
- [?NL,{aname,[Name]},?NL,{email,[Mail]}].
-
-% author(E=#xmlElement{}) ->
-% Name = get_attrval(name, E),
-% Mail = get_attrval(email, E),
-% URI = get_attrval(website, E),
-% (if Name == Mail ->
-% [{a, [{href, "mailto:" ++ Mail}],[{tt, [Mail]}]}];
-% true ->
-% if Mail == "" -> [Name];
-% true -> [Name, " (", {a, [{href, "mailto:" ++ Mail}],
-% [{tt, [Mail]}]}, ")"]
-% end
-% end
-% ++ if URI == "" -> [];
-% true -> [" [", {em, ["web site:"]}, " ",
-% {tt, [{a, [{href, URI}], [URI]}]}, "]"]
-% end).
-
-references(Es) ->
- case get_elem(reference, Es) of
- [] -> [];
- Es1 ->
- [{p, [{b, ["References"]},
- {ul, [{li, C} || #xmlElement{content = C} <- Es1]}]},
- ?NL]
- end.
-
-t_name([E]) ->
- N = get_attrval(name, E),
- case get_attrval(module, E) of
- "" -> N;
- M ->
- S = M ++ ":" ++ N,
- case get_attrval(app, E) of
- "" -> S;
- A -> "//" ++ A ++ "/" ++ S
- end
- end.
-
-t_utype([E]) ->
- t_utype_elem(E).
-
-t_utype_elem(E=#xmlElement{content = Es}) ->
- case get_attrval(name, E) of
- "" -> t_type(Es);
- Name ->
- T = t_type(Es),
- case T of
- [Name] -> T; % avoid generating "Foo::Foo"
- T -> [Name] ++ ["::"] ++ T
- end
- end.
-
-t_type([E=#xmlElement{name = typevar}]) ->
- t_var(E);
-t_type([E=#xmlElement{name = atom}]) ->
- t_atom(E);
-t_type([E=#xmlElement{name = integer}]) ->
- t_integer(E);
-t_type([E=#xmlElement{name = float}]) ->
- t_float(E);
-t_type([#xmlElement{name = nil}]) ->
- t_nil();
-t_type([#xmlElement{name = list, content = Es}]) ->
- t_list(Es);
-t_type([#xmlElement{name = tuple, content = Es}]) ->
- t_tuple(Es);
-t_type([#xmlElement{name = 'fun', content = Es}]) ->
- t_fun(Es);
-t_type([E = #xmlElement{name = abstype, content = Es}]) ->
- T = t_abstype(Es),
-% see(E,T);
- case get_attrval(href, E) of
- "" -> T;
- % Ref -> [{seealso, [{marker, Ref}], T}]
- _Ref -> T
- end;
-t_type([#xmlElement{name = union, content = Es}]) ->
- t_union(Es).
-
-t_var(E) ->
- [get_attrval(name, E)].
-
-
-t_atom(E) ->
- [get_attrval(value, E)].
-
-t_integer(E) ->
- [get_attrval(value, E)].
-
-t_float(E) ->
- [get_attrval(value, E)].
-
-t_nil() ->
- ["[]"].
-
-t_list(Es) ->
- ["["] ++ t_utype(get_elem(type, Es)) ++ ["]"].
-
-t_tuple(Es) ->
- ["{"] ++ seq(fun t_utype_elem/1, Es, ["}"]).
-
-t_fun(Es) ->
- ["("] ++ seq(fun t_utype_elem/1, get_content(argtypes, Es),
- [") -> "] ++ t_utype(get_elem(type, Es))).
-
-t_abstype(Es) ->
-% ([t_name(get_elem(qualifiedName, Es)), "("]
-% ++ seq(fun t_type_elem/1, get_elem(type, Es), [")"])).
- case split_at_colon(t_name(get_elem(erlangName, Es)),[]) of
- {Mod,Type} ->
- [Type, "("] ++
- seq(fun t_utype_elem/1, get_elem(type, Es), [")"]) ++
- [" (see module ", Mod, ")"];
- Type ->
- [Type, "("] ++
- seq(fun t_utype_elem/1, get_elem(type, Es), [")"])
- end.
-
-%% Split at one colon, but not at two (or more)
-split_at_colon([$:,$:|_]=Rest,Acc) ->
- lists:reverse(Acc)++Rest;
-split_at_colon([$:|Type],Acc) ->
- {lists:reverse(Acc),Type};
-split_at_colon([Char|Rest],Acc) ->
- split_at_colon(Rest,[Char|Acc]);
-split_at_colon([],Acc) ->
- lists:reverse(Acc).
-
-% t_par(Es) ->
-% T = t_type(get_content(type, Es)),
-% case get_elem(variable, Es) of
-% [] -> T;
-% [V0] -> case t_variable(V0) of
-% T -> T;
-% V -> V ++ ["::"] ++ T
-% end
-% end.
-
-% t_par_elem(#xmlElement{content = Es}) -> t_par(Es).
-
-t_union(Es) ->
- seq(fun t_utype_elem/1, Es, " | ", []).
-
-seq(F, Es) ->
- seq(F, Es, []).
-
-seq(F, Es, Tail) ->
- seq(F, Es, ", ", Tail).
-
-seq(F, [E], _Sep, Tail) ->
- F(E) ++ Tail;
-seq(F, [E | Es], Sep, Tail) ->
- F(E) ++ [Sep] ++ seq(F, Es, Sep, Tail);
-seq(_F, [], _Sep, Tail) ->
- Tail.
-
-get_elem(Name, [#xmlElement{name = Name} = E | Es]) ->
- [E | get_elem(Name, Es)];
-get_elem(Name, [_ | Es]) ->
- get_elem(Name, Es);
-get_elem(_, []) ->
- [].
-
-get_attr(Name, [#xmlAttribute{name = Name} = A | As]) ->
- [A | get_attr(Name, As)];
-get_attr(Name, [_ | As]) ->
- get_attr(Name, As);
-get_attr(_, []) ->
- [].
-
-get_attrval(Name, #xmlElement{attributes = As}) ->
- case get_attr(Name, As) of
- [#xmlAttribute{value = V}] ->
- V;
- [] -> ""
- end.
-
-get_content(Name, Es) ->
- case get_elem(Name, Es) of
- [#xmlElement{content = Es1}] ->
- Es1;
- [] -> []
- end.
-
-get_text(Name, Es) ->
- case get_content(Name, Es) of
- [#xmlText{value = Text}] ->
- Text;
- [] -> ""
- end.
-
-% local_label(R) ->
-% "#" ++ R.
-
-xml(Title, CSS, Body) ->
- {html, [?NL,
- {head, [?NL,
- {title, [Title]},
- ?NL] ++ CSS},
- ?NL,
- {body, [{bgcolor, "white"}], Body},
- ?NL]
- }.
-
-%% ---------------------------------------------------------------------
-
- type(E) ->
- type(E, []).
-
-% type(E, Ds) ->
-% xmerl:export_simple_content(t_utype_elem(E) ++ local_defs(Ds),
-% ?HTML_EXPORT).
- type(E, Ds) ->
- xmerl:export_simple_content(t_utype_elem(E) ++ local_defs(Ds),
- ?SGML_EXPORT).
-
-overview(E=#xmlElement{name = overview, content = Es}, Options) ->
- Opts = init_opts(E, Options),
- Title = get_text(title, Es),
- Desc = get_content(description, Es),
-% ShortDesc = get_content(briefDescription, Desc),
- FullDesc = get_content(fullDescription, Desc),
- Body = ([?NL, {h1, [Title]}, ?NL]
-% ++ ShortDesc
- ++ copyright(Es)
- ++ version(Es)
- ++ since(Es)
- ++ deprecated(Es, "application")
- ++ authors(Es)
- ++ references(Es)
- ++ sees(Es)
- ++ FullDesc),
- XML = xml(Title, stylesheet(Opts), Body),
- xmerl:export_simple([XML], ?SGML_EXPORT, []).
diff --git a/lib/edoc/vsn.mk b/lib/edoc/vsn.mk
index 1a933b2ad8..0b3636f030 100644
--- a/lib/edoc/vsn.mk
+++ b/lib/edoc/vsn.mk
@@ -1 +1 @@
-EDOC_VSN = 0.9
+EDOC_VSN = 0.9.4
diff --git a/lib/eldap/doc/src/Makefile b/lib/eldap/doc/src/Makefile
index ac869e446f..bf1eca267a 100644
--- a/lib/eldap/doc/src/Makefile
+++ b/lib/eldap/doc/src/Makefile
@@ -37,7 +37,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
XML_APPLICATION_FILES = ref_man.xml
XML_REF3_FILES = eldap.xml
-XML_PART_FILES = release_notes.xml usersguide.xml
+XML_PART_FILES = usersguide.xml
XML_CHAPTER_FILES = notes.xml
BOOK_FILES = book.xml
@@ -89,6 +89,7 @@ debug opt valgrind:
clean clean_docs clean_tex:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/lib/eldap/doc/src/fascicules.xml b/lib/eldap/doc/src/fascicules.xml
deleted file mode 100644
index cbc266cd30..0000000000
--- a/lib/eldap/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="usersguide" href="usersguide_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="release_notes" href="release_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/eldap/doc/src/note.gif b/lib/eldap/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/eldap/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/eldap/doc/src/notes.xml b/lib/eldap/doc/src/notes.xml
index 7aad745f67..07c2b0a3e8 100644
--- a/lib/eldap/doc/src/notes.xml
+++ b/lib/eldap/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2012</year><year>2016</year>
+ <year>2012</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,51 @@
</header>
<p>This document describes the changes made to the Eldap application.</p>
+<section><title>Eldap 1.2.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Eldap 1.2.4</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Update to use the new string api instead of the old.</p>
+ <p>
+ Own Id: OTP-15036</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Eldap 1.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Eldap 1.2.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/eldap/doc/src/warning.gif b/lib/eldap/doc/src/warning.gif
deleted file mode 100644
index 96af52360e..0000000000
--- a/lib/eldap/doc/src/warning.gif
+++ /dev/null
Binary files differ
diff --git a/lib/eldap/src/eldap.erl b/lib/eldap/src/eldap.erl
index 625309271b..2b84872b92 100644
--- a/lib/eldap/src/eldap.erl
+++ b/lib/eldap/src/eldap.erl
@@ -1368,9 +1368,9 @@ rm_leading_slash(Tail) -> Tail.
parse_attributes([$?|Tail]) ->
case split_string(Tail,$?) of
{[],Attributes} ->
- {[],{attributes,string:tokens(Attributes,",")}};
+ {[],{attributes,string:lexemes(Attributes,",")}};
{Attributes,Rest} ->
- {Rest,{attributes,string:tokens(Attributes,",")}}
+ {Rest,{attributes,string:lexemes(Attributes,",")}}
end.
parse_hostport(Str) ->
diff --git a/lib/eldap/test/eldap_basic_SUITE.erl b/lib/eldap/test/eldap_basic_SUITE.erl
index 4bfb0dd291..b871eda19c 100644
--- a/lib/eldap/test/eldap_basic_SUITE.erl
+++ b/lib/eldap/test/eldap_basic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/eldap/vsn.mk b/lib/eldap/vsn.mk
index 721387d97d..6e8951aba4 100644
--- a/lib/eldap/vsn.mk
+++ b/lib/eldap/vsn.mk
@@ -1 +1 @@
-ELDAP_VSN = 1.2.2
+ELDAP_VSN = 1.2.5
diff --git a/lib/erl_docgen/doc/src/Makefile b/lib/erl_docgen/doc/src/Makefile
index a9110e4635..d6d2550425 100644
--- a/lib/erl_docgen/doc/src/Makefile
+++ b/lib/erl_docgen/doc/src/Makefile
@@ -106,6 +106,7 @@ html: gifs examples $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/erl_docgen/doc/src/fasc_dtds.xml b/lib/erl_docgen/doc/src/fasc_dtds.xml
deleted file mode 100644
index 390ae6c5d1..0000000000
--- a/lib/erl_docgen/doc/src/fasc_dtds.xml
+++ /dev/null
@@ -1,116 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2007</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Fascicules DTDs</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- <file>fasc_dtds.xml</file>
- </header>
-
- <section>
- <title>The fascicules DTD</title>
-
- <p>The <c>fascicules</c> DTD is a special kind of DTD which can be
- used to specify the different parts of the documentation, and
- which one of those should be shown as default.</p>
-
- <p>Example:</p>
-
- <pre><![CDATA[
-<?xml version="1.0" encoding="latin1" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
-</fascicules>
- ]]></pre>
-
- <p>In the example, it is specified that the documentation for this
- application consists of three parts: User's Guide, where
- the "cover page" (with the two frames) is located in
- <c>part_frame.html</c>, Reference Manual with the cover page
- <c>ref_man_frame.html</c> and Release Notes with the cover page
- <c>part_notes_frame.html</c>.</p>
-
- <p>As a result, at the top of the left frame in the generated HTML
- documentation, there will be corresponding links to User's Guide,
- Reference Manual and Release Notes.</p>
-
- <p>The attribute <c>entry="yes"</c> specifies that it is
- the Reference Manual which should be shown as default. This means
- that when generating the HTML files, <c>application_frame.html</c>
- will be copied to <c>index.html</c>.</p>
-
- <note>
- <p>DocBuilder assumes that the XML file written according to
- the <c>fascicules</c> DTD is called <c>fascicules.xml</c>.</p>
- </note>
-
- <p>This file is optional. If it does not exist, there are no links
- to other parts of the documentation (as they are not known) in
- the left frame, and no <c>index.html</c> is created.</p>
- </section>
-
- <section>
- <marker id="fasciculesTAG"></marker>
- <title>&lt;fascicules&gt;</title>
-
- <p>Top level tag for the <c>fascicules</c> DTD.</p>
-
- <p>Contains one or more
- <seealso marker="#fasciculeTAG">&lt;fascicule&gt;</seealso>.</p>
- </section>
-
- <section>
- <marker id="fasciculeTAG"></marker>
- <title>&lt;fascicule&gt;</title>
-
- <p>Specifies properties for one "part" of the documentation for an
- application.</p>
-
- <p>Contains plain text, the name of this part.</p>
-
- <p>The <c>file</c> attribute should specify the file name for
- the corresponding <c>part</c> or <c>application</c>, without
- the <c>.xml</c> extension.</p>
-
- <p>The <c>href</c> attribute should specify the file name for
- the corresponding HTML cover page file, without the <c>.html</c>
- extension.</p>
-
- <p>The optional <c>entry="yes"|"no"</c> attribute specifies if
- the HTML cover page should be copied to <c>index.html</c> or
- not. Default is <c>"no"</c>.</p>
- </section>
-</chapter>
-
diff --git a/lib/erl_docgen/doc/src/fascicules.xml b/lib/erl_docgen/doc/src/fascicules.xml
deleted file mode 100644
index 154c8a3b6d..0000000000
--- a/lib/erl_docgen/doc/src/fascicules.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
-</fascicules>
-
diff --git a/lib/erl_docgen/doc/src/notes.xml b/lib/erl_docgen/doc/src/notes.xml
index 59a268d6ac..97c842a324 100644
--- a/lib/erl_docgen/doc/src/notes.xml
+++ b/lib/erl_docgen/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,7 +31,93 @@
</header>
<p>This document describes the changes made to the <em>erl_docgen</em> application.</p>
- <section><title>Erl_Docgen 0.7</title>
+ <section><title>Erl_Docgen 0.8.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Indexing for the online search function has been
+ corrected for CREF documents.</p>
+ <p>
+ Own Id: OTP-14406</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Docgen 0.8</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add a hoverable element to the titles in the html
+ documentation with a link to github where the
+ documentation can be edited.</p>
+ <p>
+ Make the anchors in the html User's Guide and system
+ documentation use the title of the sections instead of a
+ generated id.</p>
+ <p>
+ Own Id: OTP-14979</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Docgen 0.7.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Update makefile so db_funcs.xsl is a part of the
+ installed application. </p>
+ <p>
+ Own Id: OTP-15091</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Docgen 0.7.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> The style for code, warning and note tags in the pdf
+ have been changed so they look like the html version.
+ <br/> The spacing around code blocks have been changed
+ for both html and pdf so it's the same regardless if the
+ user have a newline after the start tag (or before the
+ end tag) or not. </p>
+ <p>
+ Own Id: OTP-14674</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Docgen 0.7.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ General Unicode improvements.</p>
+ <p>
+ Own Id: OTP-14462</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Docgen 0.7</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/erl_docgen/priv/bin/codeline_preprocessing.escript b/lib/erl_docgen/priv/bin/codeline_preprocessing.escript
index 8e1e35bcdd..ce9303f86e 100755
--- a/lib/erl_docgen/priv/bin/codeline_preprocessing.escript
+++ b/lib/erl_docgen/priv/bin/codeline_preprocessing.escript
@@ -2,7 +2,7 @@
%% -*- erlang -*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@
%% Function: main/1
%% Description:
%%----------------------------------------------------------------------
-main([InFile, OutFile]) ->
+main([CPath, InFile, OutFile]) ->
InDev =
case file:open(InFile, [read]) of
{ok,ID} ->
@@ -38,7 +38,6 @@ main([InFile, OutFile]) ->
_ ->
halt(5)
end,
- CPath=filename:dirname(InFile),
OutDev =
case file:open(OutFile, [write]) of
{ok,OD} ->
diff --git a/lib/erl_docgen/priv/bin/github_link.escript b/lib/erl_docgen/priv/bin/github_link.escript
new file mode 100755
index 0000000000..e0f5a2f471
--- /dev/null
+++ b/lib/erl_docgen/priv/bin/github_link.escript
@@ -0,0 +1,51 @@
+#!/usr/bin/env escript
+%% -*- erlang -*-
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%----------------------------------------------------------------------
+%% File : github_link.escript
+%%
+%% Created : 12 Dec 2017 by Lukas Larsson
+%%----------------------------------------------------------------------
+
+main([In, Filename, Sha, Out]) ->
+ {ok, Bin} = file:read_file(In),
+
+ TagsToAnnotate = ["description", "func", "datatype", "section"],
+
+ Subs = subs(TagsToAnnotate, Filename, Sha, re:split(Bin,[$\n])),
+
+ file:write_file(Out, Subs).
+
+subs([], _, _, Bin) ->
+ lists:join("\n", Bin);
+subs([Pat|Pats], Fn, Sha, Bin) ->
+ subs(Pats, Fn, Sha, sub(Bin, Pat, Fn, Sha)).
+
+sub(Bin, Pat, Fn, Sha) ->
+ sub(Bin, Pat, Fn, Sha, 1).
+sub([], _Pat, _Fn, _Sha, _Cnt) ->
+ [];
+sub([H|T], Pat, Fn, Sha, Cnt) ->
+ %% We use the maint branch here, it is not as exact as the tag,
+ %% but it is the best we can do as github does not allow doing
+ %% pullrequests on anything but branches.
+ [re:replace(H,["<",Pat,">"],
+ ["<",Pat," ghlink=\"maint/",Fn,"#L",
+ integer_to_list(Cnt),"\">"],[{return,list}]) |
+ sub(T, Pat, Fn, Sha, Cnt+1)].
diff --git a/lib/erl_docgen/priv/bin/xml_from_edoc.escript b/lib/erl_docgen/priv/bin/xml_from_edoc.escript
index b930ae3818..38e4f2d923 100755
--- a/lib/erl_docgen/priv/bin/xml_from_edoc.escript
+++ b/lib/erl_docgen/priv/bin/xml_from_edoc.escript
@@ -2,7 +2,7 @@
%% -*- erlang -*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@
%% Records
%%======================================================================
-record(args, {suffix=".xml",
+ dir=".",
layout=docgen_edoc_xml_cb,
def=[],
includes=[],
@@ -85,7 +86,7 @@ module(File, Args) ->
{app_default, "OTPROOT"},
{file_suffix, Args#args.suffix},
- {dir, "."},
+ {dir, Args#args.dir},
{layout, Args#args.layout}],
edoc:file(File, Opts);
false ->
@@ -118,7 +119,7 @@ users_guide(File, Args) ->
Text = edoc_lib:run_layout(F, Opts),
OutFile = "chapter" ++ Args#args.suffix,
- edoc_lib:write_file(Text, ".", OutFile, Encoding);
+ edoc_lib:write_file(Text, Args#args.dir, OutFile, Encoding);
false ->
io:format("~s: not a regular file\n", [File]),
usage()
@@ -139,6 +140,8 @@ parse(["-def", Key, Val |RawOpts], Type, Args) ->
parse(["-i", Dir |RawOpts], Type, Args) ->
Args2 = Args#args{includes=Args#args.includes++[Dir]},
parse(RawOpts, Type, Args2);
+parse(["-dir", Dir |RawOpts], Type, Args) ->
+ parse(RawOpts, Type, Args#args{dir=Dir});
parse(["-preprocess", Bool |RawOpts], Type, Args) when Bool == "true";
Bool == "false" ->
parse(RawOpts, Type, Args#args{preprocess=list_to_atom(Bool)});
diff --git a/lib/erl_docgen/priv/css/otp_doc.css b/lib/erl_docgen/priv/css/otp_doc.css
index 844aad2945..34c6befb0e 100644
--- a/lib/erl_docgen/priv/css/otp_doc.css
+++ b/lib/erl_docgen/priv/css/otp_doc.css
@@ -242,8 +242,25 @@ th {
font-size: small;
}
-h3>a{
- color: #1a1a1a !important;
+.title_link {
+ color: #1a1a1a !important;
+ outline: none;
+}
+
+.ghlink {
+ margin-left: -2.7em; /* .pencil.font-size + .pencil.padding.left + .pencil.padding.right = 2.7 */
+ visibility: hidden;
+}
+
+.pencil:before {
+ transform: rotateZ(90deg);
+ content: "\270E";
+ color: #1a1a1a !important;
+ font-weight: bold;
+ font-size: 1.5em;
+ padding: .3em .6em .6em;
+ line-height: 1em;
+ font-family: mono;
}
hr{
diff --git a/lib/erl_docgen/priv/dtd/chapter.dtd b/lib/erl_docgen/priv/dtd/chapter.dtd
index a4c9e4040d..3e9113d798 100644
--- a/lib/erl_docgen/priv/dtd/chapter.dtd
+++ b/lib/erl_docgen/priv/dtd/chapter.dtd
@@ -31,7 +31,8 @@
<!-- Structure -->
<!ELEMENT chapter (header,(%block;|quote|warning|note|dont|do|br|
- image|marker|table)*,section+) >
+ image|marker|table)*,section*) >
<!ELEMENT section (marker*,title,
(%block;|quote|warning|note|dont|do|br|image|marker|
table|section)*) >
+<!ATTLIST section ghlink CDATA #IMPLIED>
diff --git a/lib/erl_docgen/priv/dtd/common.image.dtd b/lib/erl_docgen/priv/dtd/common.image.dtd
index d97057590e..138da3609b 100644
--- a/lib/erl_docgen/priv/dtd/common.image.dtd
+++ b/lib/erl_docgen/priv/dtd/common.image.dtd
@@ -18,5 +18,7 @@
$Id$
-->
<!ELEMENT image (icaption) >
-<!ATTLIST image file CDATA #REQUIRED >
+<!ATTLIST image
+ file CDATA #REQUIRED
+ width CDATA #IMPLIED >
<!ELEMENT icaption (#PCDATA) >
diff --git a/lib/erl_docgen/priv/dtd/common.refs.dtd b/lib/erl_docgen/priv/dtd/common.refs.dtd
index 4f87007a09..07c876a17f 100644
--- a/lib/erl_docgen/priv/dtd/common.refs.dtd
+++ b/lib/erl_docgen/priv/dtd/common.refs.dtd
@@ -26,8 +26,10 @@
%common.header;
<!ELEMENT description (%block;|quote|br|marker|warning|note|dont|do)* >
+<!ATTLIST description ghlink CDATA #IMPLIED>
<!ELEMENT funcs (func)+ >
<!ELEMENT func (name+,fsummary,(type|type_desc)*,desc?) >
+<!ATTLIST func ghlink CDATA #IMPLIED>
<!-- ELEMENT name is defined in each ref dtd -->
<!ELEMENT fsummary (#PCDATA|c|i|em|anno)* >
<!ELEMENT type (v,d?)* >
@@ -42,8 +44,11 @@
<!ELEMENT email (#PCDATA) >
<!ELEMENT section (marker*,title,(%block;|quote|br|marker|
warning|note|dont|do|section)*) >
-<!ELEMENT datatypes (datatype)+ >
+<!ATTLIST section ghlink CDATA #IMPLIED>
+<!ELEMENT datatypes (datatype_title?,datatype)+ >
+<!ELEMENT datatype_title (#PCDATA) >
<!ELEMENT datatype (name+,desc?) >
+<!ATTLIST datatype ghlink CDATA #IMPLIED>
<!ELEMENT type_desc (#PCDATA|anno|c|seealso)* >
<!ATTLIST type_desc variable CDATA #IMPLIED
name CDATA #IMPLIED>
diff --git a/lib/erl_docgen/priv/dtd/erlref.dtd b/lib/erl_docgen/priv/dtd/erlref.dtd
index 615b88b61a..78d6771f52 100644
--- a/lib/erl_docgen/priv/dtd/erlref.dtd
+++ b/lib/erl_docgen/priv/dtd/erlref.dtd
@@ -33,4 +33,5 @@
<!ATTLIST name name CDATA #IMPLIED
arity CDATA #IMPLIED
clause_i CDATA #IMPLIED
+ anchor CDATA #IMPLIED
n_vars CDATA #IMPLIED>
diff --git a/lib/erl_docgen/priv/xsl/Makefile b/lib/erl_docgen/priv/xsl/Makefile
index d0dd227169..d381bd4cf7 100644
--- a/lib/erl_docgen/priv/xsl/Makefile
+++ b/lib/erl_docgen/priv/xsl/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2016. All Rights Reserved.
+# Copyright Ericsson AB 2009-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -44,7 +44,8 @@ XSL_FILES = \
db_html.xsl \
db_html_params.xsl \
db_man.xsl \
- db_eix.xsl
+ db_eix.xsl \
+ db_funcs.xsl
# ----------------------------------------------------
diff --git a/lib/erl_docgen/priv/xsl/db_eix.xsl b/lib/erl_docgen/priv/xsl/db_eix.xsl
index b496614854..6bce577f08 100644
--- a/lib/erl_docgen/priv/xsl/db_eix.xsl
+++ b/lib/erl_docgen/priv/xsl/db_eix.xsl
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
- # Copyright Ericsson AB 2009-2016. All Rights Reserved.
+ # Copyright Ericsson AB 2009-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -199,11 +199,34 @@
<xsl:template name="name">
<xsl:param name="lastfuncsblock"/>
+ <xsl:variable name="signature">
+ <xsl:variable name="signature1">
+ <xsl:choose>
+ <xsl:when test="ancestor::cref">
+ <xsl:value-of
+ select="normalize-space(nametext)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of
+ select="normalize-space(substring-before(., '->'))"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($signature1) > 0">
+ <xsl:value-of select="$signature1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="normalize-space(.)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
<xsl:variable name="tmpstring">
- <xsl:value-of select="substring-before(substring-after(., '('), '->')"/>
+ <xsl:value-of select="substring-after($signature, '(')"/>
</xsl:variable>
- <xsl:variable name="ustring">
+ <xsl:variable name="argstring">
<xsl:choose>
<xsl:when test="string-length($tmpstring) > 0">
<xsl:call-template name="remove-paren">
@@ -219,10 +242,19 @@
</xsl:variable>
<xsl:variable name="arity">
- <xsl:call-template name="calc-arity">
- <xsl:with-param name="string" select="substring-before($ustring, ')')"/>
- <xsl:with-param name="no-of-pars" select="0"/>
- </xsl:call-template>
+ <xsl:choose>
+ <xsl:when
+ test="string-length(substring-before(., '->')) > 0">
+ <xsl:call-template name="calc-arity">
+ <xsl:with-param
+ name="string"
+ select="substring-before($argstring, ')')"/>
+ <xsl:with-param name="no-of-pars" select="0"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+
</xsl:variable>
<xsl:variable name="fname">
@@ -250,10 +282,18 @@
</xsl:variable>
<xsl:text> {"</xsl:text><xsl:value-of select="$fname"/>
+ <xsl:text>", "</xsl:text>
+ <xsl:call-template name="escape-doublequotes">
+ <xsl:with-param name="string" select="$signature"/>
+ </xsl:call-template>
<xsl:text>", "</xsl:text><xsl:value-of select="$fname"/>
- <xsl:text>(</xsl:text><xsl:value-of select="normalize-space($tmpstring)"/>
- <xsl:text>", "</xsl:text><xsl:value-of select="$fname"/>
- <xsl:text>-</xsl:text><xsl:value-of select="$arity"/><xsl:text>"}</xsl:text>
+ <xsl:choose>
+ <xsl:when test="string-length($arity) > 0">
+ <xsl:text>-</xsl:text><xsl:value-of select="$arity"/>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ <xsl:text>"}</xsl:text>
<xsl:choose>
<xsl:when test="($lastfuncsblock = 'true') and (position() = last())">
@@ -345,6 +385,27 @@
</xsl:template>
+ <xsl:template name="escape-doublequotes">
+ <xsl:param name="string"/>
+ <xsl:param name="pPat">"</xsl:param>
+ <xsl:param name="pRep">\"</xsl:param>
+
+ <xsl:choose>
+ <xsl:when test="not(contains($string, $pPat))">
+ <xsl:copy-of select="$string"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:copy-of select="substring-before($string, $pPat)"/>
+ <xsl:copy-of select="$pRep"/>
+ <xsl:call-template name="escape-doublequotes">
+ <xsl:with-param
+ name="string"
+ select="substring-after($string, $pPat)"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
<!-- default content handling -->
<xsl:template match="text()"/>
diff --git a/lib/erl_docgen/priv/xsl/db_funcs.xsl b/lib/erl_docgen/priv/xsl/db_funcs.xsl
new file mode 100644
index 0000000000..8178ce44fb
--- /dev/null
+++ b/lib/erl_docgen/priv/xsl/db_funcs.xsl
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ #
+ # %CopyrightBegin%
+ #
+ # Copyright Ericsson AB 2009-2017. All Rights Reserved.
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+ #
+ # %CopyrightEnd%
+
+ -->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:erl="http://erlang.org"
+ xmlns:func="http://exslt.org/functions"
+ extension-element-prefixes="func"
+ xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ xmlns:fn="http://www.w3.org/2005/02/xpath-functions">
+
+ <!-- Used from code template to trim the newline/cr after the tag
+ and spaces/tabs between them
+ -->
+ <xsl:variable name="newlinechars" select="'&#10;&#13;'" />
+ <xsl:variable name="spacechars" select="'&#09; '" />
+
+ <func:function name="erl:code_trim">
+ <xsl:param name="string" />
+
+ <xsl:variable name="leftresult" select="erl:code_ltrim($string, $string)"/>
+ <xsl:variable name="result" select="erl:code_rtrim($leftresult, $leftresult)"/>
+
+ <func:result select="$result"/>
+ </func:function>
+
+ <func:function name="erl:code_rtrim">
+ <xsl:param name="string" />
+ <xsl:param name="origstring" />
+
+ <xsl:variable name="length" select="string-length($string)" />
+
+ <xsl:variable name="result">
+ <xsl:if test="$length &gt; 0">
+ <xsl:choose>
+ <xsl:when test="contains($spacechars, substring($string, $length, 1))">
+ <xsl:value-of select="erl:code_rtrim(substring($string, 1, $length - 1), $origstring)" />
+ </xsl:when>
+ <xsl:when test="contains($newlinechars, substring($string, $length, 1))">
+ <xsl:value-of select="erl:code_rtrim_1(substring($string, 1, $length - 1))" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$origstring" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:variable>
+
+ <func:result select="$result" />
+ </func:function>
+
+ <func:function name="erl:code_rtrim_1">
+ <xsl:param name="string" />
+
+ <xsl:variable name="length" select="string-length($string)" />
+
+ <xsl:variable name="result">
+ <xsl:if test="$length &gt; 0">
+ <xsl:choose>
+ <xsl:when test="contains($newlinechars, substring($string, $length, 1))">
+ <xsl:value-of select="erl:code_rtrim_1(substring($string, 1, $length - 1))" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="erl:code_rtrim($string, $string)" />
+ <!--xsl:value-of select="$string" /-->
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:variable>
+
+ <func:result select="$result" />
+ </func:function>
+
+ <func:function name="erl:code_ltrim">
+ <xsl:param name="string" />
+ <xsl:param name="origstring" />
+
+ <xsl:variable name="result">
+ <xsl:if test="string-length($string) &gt; 0">
+ <xsl:choose>
+ <xsl:when test="contains($spacechars, substring($string, 1, 1))">
+ <xsl:value-of select="erl:code_ltrim(substring($string, 2), $origstring)" />
+ </xsl:when>
+ <xsl:when test="contains($newlinechars, substring($string, 1, 1))">
+ <xsl:value-of select="erl:code_ltrim_1(substring($string, 2))" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$origstring" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:variable>
+
+ <func:result select="$result" />
+ </func:function>
+
+ <func:function name="erl:code_ltrim_1">
+ <xsl:param name="string" />
+
+ <xsl:variable name="result">
+ <xsl:if test="string-length($string) &gt; 0">
+ <xsl:choose>
+ <xsl:when test="contains($newlinechars, substring($string, 1, 1))">
+ <xsl:value-of select="erl:code_ltrim_1(substring($string, 2))" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="erl:code_ltrim($string, $string)" />
+ <!--xsl:value-of select="$string" /-->
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:variable>
+
+ <func:result select="$result" />
+ </func:function>
+
+</xsl:stylesheet>
diff --git a/lib/erl_docgen/priv/xsl/db_html.xsl b/lib/erl_docgen/priv/xsl/db_html.xsl
index d863c056e9..a0a922216b 100644
--- a/lib/erl_docgen/priv/xsl/db_html.xsl
+++ b/lib/erl_docgen/priv/xsl/db_html.xsl
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
- # Copyright Ericsson AB 2009-2017. All Rights Reserved.
+ # Copyright Ericsson AB 2009-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@
xmlns:fn="http://www.w3.org/2005/02/xpath-functions">
<xsl:include href="db_html_params.xsl"/>
+ <xsl:include href="db_funcs.xsl"/>
<func:function name="erl:flip_first_char">
<xsl:param name="in"/>
@@ -53,6 +54,24 @@
<func:result select="$result"/>
</func:function>
+ <func:function name="erl:lower-case">
+ <xsl:param name="str"/>
+
+ <xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
+ <xsl:variable name="lowercase" select="'abcdefghijklmnopqrstuvwxyz'"/>
+
+ <xsl:variable name="result">
+ <xsl:value-of select="translate($str, $uppercase, $lowercase)"/>
+ </xsl:variable>
+
+ <func:result select="$result"/>
+ </func:function>
+
+ <func:function name="erl:to-link">
+ <xsl:param name="text"/>
+ <func:result select="translate(erl:lower-case($text),'?: /()&quot;&#10;','--------')"/>
+ </func:function>
+
<!-- Used from template menu.funcs to sort a module's functions for the lefthand index list,
from the module's .xml file. Returns a value on which to sort the entity in question
(a <name> element).
@@ -171,6 +190,7 @@
<xsl:template name="spec_name">
<xsl:variable name="name" select="@name"/>
<xsl:variable name="arity" select="@arity"/>
+ <xsl:variable name="anchor" select="@anchor"/>
<xsl:variable name="spec0">
<xsl:call-template name="find_spec"/>
</xsl:variable>
@@ -197,10 +217,16 @@
</xsl:otherwise>
</xsl:choose>
+ <!-- Insert an anchor for "anchor" attribute -->
+ <xsl:if test="string-length($anchor) > 0">
+ <a name="{$anchor}"></a>
+ </xsl:if>
+
<xsl:variable name="global_types" select="ancestor::erlref/datatypes"/>
<xsl:variable name="local_types"
select="../type[string-length(@name) > 0]"/>
<xsl:apply-templates select="$spec/contract/clause/head">
+ <xsl:with-param name="ghlink" select="ancestor-or-self::*[@ghlink]/@ghlink"/>
<xsl:with-param name="local_types" select="$local_types"/>
<xsl:with-param name="global_types" select="$global_types"/>
</xsl:apply-templates>
@@ -209,9 +235,17 @@
</xsl:template>
<xsl:template match="head">
+ <xsl:param name="ghlink"/>
<xsl:param name="local_types"/>
<xsl:param name="global_types"/>
- <div class="bold_code func-head">
+ <xsl:variable name="id" select="concat(concat(concat(concat(../../../name,'-'),../../../arity),'-'),generate-id(.))"/>
+ <div class="bold_code func-head"
+ onMouseOver="document.getElementById('ghlink-{$id}').style.visibility = 'visible';"
+ onMouseOut="document.getElementById('ghlink-{$id}').style.visibility = 'hidden';">
+ <xsl:call-template name="ghlink">
+ <xsl:with-param name="ghlink" select="$ghlink"/>
+ <xsl:with-param name="id" select="$id"/>
+ </xsl:call-template>
<xsl:apply-templates mode="local_type">
<xsl:with-param name="local_types" select="$local_types"/>
<xsl:with-param name="global_types" select="$global_types"/>
@@ -396,18 +430,37 @@
<!-- Datatypes -->
<xsl:template match="datatypes">
- <h3>
- <a name="data-types" href="#data-types"><xsl:text>Data Types</xsl:text></a>
- </h3>
- <div class="data-types-body">
- <xsl:apply-templates/>
- </div>
+ <xsl:call-template name="h3_title_link">
+ <xsl:with-param name="title">Data Types</xsl:with-param>
+ </xsl:call-template>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <!-- Datatype Title, is the really needed? not used by anything -->
+ <xsl:template match="datatype_title">
+ <xsl:variable name="title" select="."/>
+ <h4>
+ <xsl:call-template name="title_link">
+ <xsl:with-param name="title"><xsl:apply-templates/></xsl:with-param>
+ <xsl:with-param name="link" select="$title"/>
+ </xsl:call-template>
+ </h4>
</xsl:template>
<!-- Datatype -->
<xsl:template match="datatype">
- <div class="data-type-name"><xsl:apply-templates select="name"/></div>
- <div class="data-type-desc"><xsl:apply-templates select="desc"/></div>
+ <xsl:variable name="id" select="concat('type-',name/@name)"/>
+ <div class="data-types-body">
+ <div class="data-type-name"
+ onMouseOver="document.getElementById('ghlink-{$id}').style.visibility = 'visible';"
+ onMouseOut="document.getElementById('ghlink-{$id}').style.visibility = 'hidden';">
+ <xsl:call-template name="ghlink">
+ <xsl:with-param name="id" select="$id"/>
+ </xsl:call-template>
+ <xsl:apply-templates select="name"/>
+ </div>
+ <div class="data-type-desc"><xsl:apply-templates select="desc"/></div>
+ </div>
</xsl:template>
<!-- The "mode" attribute of apply has been used to separate the case
@@ -889,7 +942,7 @@
<!-- Header -->
<xsl:template match="header"/>
-
+
<!-- Section/Title -->
<xsl:template match="section/title"/>
@@ -902,10 +955,12 @@
<xsl:for-each select="marker">
<xsl:call-template name="marker-before-title"/>
</xsl:for-each>
- <a name="{generate-id(title)}">
- <xsl:value-of select="$chapnum"/>.<xsl:number/>&#160;
- <xsl:value-of select="title"/>
- </a>
+ <xsl:call-template name="title_link">
+ <xsl:with-param name="title">
+ <xsl:value-of select="$chapnum"/>.<xsl:number/>&#160;
+ <xsl:value-of select="title"/>
+ </xsl:with-param>
+ </xsl:call-template>
</h3>
<xsl:apply-templates>
<xsl:with-param name="chapnum" select="$chapnum"/>
@@ -922,7 +977,9 @@
<xsl:call-template name="marker-before-title"/>
</xsl:for-each>
<!-- xsl:value-of select="$partnum"/>.<xsl:value-of select="$chapnum"/>.<xsl:value-of select="$sectnum"/>.<xsl:number/ -->
- <xsl:value-of select="title"/>
+ <xsl:call-template name="title_link">
+ <xsl:with-param name="title" select="title"/>
+ </xsl:call-template>
</h4>
<xsl:apply-templates>
<xsl:with-param name="chapnum" select="$chapnum"/>
@@ -952,9 +1009,9 @@
<xsl:for-each select="marker">
<xsl:call-template name="marker-before-title"/>
</xsl:for-each>
- <a name="{generate-id(title)}">
- <xsl:value-of select="title"/>
- </a>
+ <xsl:call-template name="title_link">
+ <xsl:with-param name="title" select="title"/>
+ </xsl:call-template>
</h3>
<div class="REFBODY rb-3">
<xsl:apply-templates>
@@ -1132,7 +1189,14 @@
<xsl:variable name="codenum">
<xsl:number level="any" from="chapter" count="code"/>
</xsl:variable>
- <div class="example"><pre><xsl:apply-templates/></pre></div>
+ <xsl:choose>
+ <xsl:when test="not(descendant::anno)">
+ <div class="example"><pre><xsl:value-of select="erl:code_trim(text())"/></pre></div>
+ </xsl:when>
+ <xsl:otherwise>
+ <div class="example"><pre><xsl:apply-templates/></pre></div>
+ </xsl:otherwise>
+ </xsl:choose>
</xsl:template>
<!-- Pre -->
@@ -1200,7 +1264,14 @@
</xsl:variable>
<div class="doc-image-wrapper">
- <img alt="IMAGE MISSING" src="{@file}" class="doc-image"/>
+ <xsl:choose>
+ <xsl:when test="@width">
+ <img alt="IMAGE MISSING" width="{@width}" src="{@file}" class="doc-image"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <img alt="IMAGE MISSING" src="{@file}" class="doc-image"/>
+ </xsl:otherwise>
+ </xsl:choose>
<xsl:apply-templates>
<xsl:with-param name="chapnum" select="$chapnum"/>
@@ -1337,7 +1408,7 @@
<xsl:param name="chapter_file"/>
<xsl:for-each select="$entries">
<li title="{title}">
- <a href="{$chapter_file}.html#{generate-id(title)}">
+ <a href="{$chapter_file}.html#{erl:to-link(title)}">
<xsl:value-of select="title"/>
</a>
</li>
@@ -1791,7 +1862,9 @@
<!-- Module -->
<xsl:template match="module">
<xsl:param name="partnum"/>
- <h3><a name="module" href="#module">Module</a></h3>
+ <xsl:call-template name="h3_title_link">
+ <xsl:with-param name="title">Module</xsl:with-param>
+ </xsl:call-template>
<div class="REFBODY module-body">
<xsl:apply-templates>
<xsl:with-param name="partnum" select="$partnum"/>
@@ -1803,7 +1876,9 @@
<!-- Modulesummary -->
<xsl:template match="modulesummary">
<xsl:param name="partnum"/>
- <h3><a name="module-sumary" href="#module-sumary">Module Summary</a></h3>
+ <xsl:call-template name="h3_title_link">
+ <xsl:with-param name="title">Module Summary</xsl:with-param>
+ </xsl:call-template>
<div class="REFBODY module-summary-body">
<xsl:apply-templates>
<xsl:with-param name="partnum" select="$partnum"/>
@@ -1814,7 +1889,9 @@
<!-- Lib -->
<xsl:template match="lib">
<xsl:param name="partnum"/>
- <h3><a name="c-library" href="#c-library">C Library</a></h3>
+ <xsl:call-template name="h3_title_link">
+ <xsl:with-param name="title">C Library</xsl:with-param>
+ </xsl:call-template>
<div class="REFBODY c-library-body">
<xsl:apply-templates>
<xsl:with-param name="partnum" select="$partnum"/>
@@ -1826,7 +1903,9 @@
<!-- Libsummary -->
<xsl:template match="libsummary">
<xsl:param name="partnum"/>
- <h3><a name="library-sumary" href="#library-sumary">Library Summary</a></h3>
+ <xsl:call-template name="h3_title_link">
+ <xsl:with-param name="title">Library Summary</xsl:with-param>
+ </xsl:call-template>
<div class="REFBODY library-summary-body">
<xsl:apply-templates>
<xsl:with-param name="partnum" select="$partnum"/>
@@ -1837,7 +1916,9 @@
<!-- Com -->
<xsl:template match="com">
<xsl:param name="partnum"/>
- <h3><a name="command" href="#command">Command</a></h3>
+ <xsl:call-template name="h3_title_link">
+ <xsl:with-param name="title">Command</xsl:with-param>
+ </xsl:call-template>
<div class="REFBODY command-body">
<xsl:apply-templates>
<xsl:with-param name="partnum" select="$partnum"/>
@@ -1849,7 +1930,9 @@
<!-- Comsummary -->
<xsl:template match="comsummary">
<xsl:param name="partnum"/>
- <h3><a name="command-summary" href="#command-summary">Command Summary</a></h3>
+ <xsl:call-template name="h3_title_link">
+ <xsl:with-param name="title">Command Summary</xsl:with-param>
+ </xsl:call-template>
<div class="REFBODY command-summary-body">
<xsl:apply-templates>
<xsl:with-param name="partnum" select="$partnum"/>
@@ -1860,7 +1943,9 @@
<!-- File -->
<xsl:template match="file">
<xsl:param name="partnum"/>
- <h3><a name="file" href="#file">File</a></h3>
+ <xsl:call-template name="h3_title_link">
+ <xsl:with-param name="title">File</xsl:with-param>
+ </xsl:call-template>
<div class="REFBODY file-body">
<xsl:apply-templates>
<xsl:with-param name="partnum" select="$partnum"/>
@@ -1872,7 +1957,9 @@
<!-- Filesummary -->
<xsl:template match="filesummary">
<xsl:param name="partnum"/>
- <h3><a name="file-summary" href="#file-summary">File Summary</a></h3>
+ <xsl:call-template name="h3_title_link">
+ <xsl:with-param name="title">File Summary</xsl:with-param>
+ </xsl:call-template>
<div class="REFBODY file-summary-body">
<xsl:apply-templates>
<xsl:with-param name="partnum" select="$partnum"/>
@@ -1884,7 +1971,9 @@
<!-- App -->
<xsl:template match="app">
<xsl:param name="partnum"/>
- <h3><a name="application" href="#application">Application</a></h3>
+ <xsl:call-template name="h3_title_link">
+ <xsl:with-param name="title">Application</xsl:with-param>
+ </xsl:call-template>
<div class="REFBODY application-body">
<xsl:apply-templates>
<xsl:with-param name="partnum" select="$partnum"/>
@@ -1896,7 +1985,9 @@
<!-- Appsummary -->
<xsl:template match="appsummary">
<xsl:param name="partnum"/>
- <h3><a name="application-summary" href="#application-summary">Application Summary</a></h3>
+ <xsl:call-template name="h3_title_link">
+ <xsl:with-param name="title">Application Summary</xsl:with-param>
+ </xsl:call-template>
<div class="REFBODY application-summary-body">
<xsl:apply-templates>
<xsl:with-param name="partnum" select="$partnum"/>
@@ -1907,7 +1998,9 @@
<!-- Description -->
<xsl:template match="description">
<xsl:param name="partnum"/>
- <h3><a name="description" href="#description">Description</a></h3>
+ <xsl:call-template name="h3_title_link">
+ <xsl:with-param name="title">Description</xsl:with-param>
+ </xsl:call-template>
<div class="REFBODY description-body">
<p>
<xsl:apply-templates>
@@ -1921,7 +2014,9 @@
<xsl:template match="funcs">
<xsl:param name="partnum"/>
- <h3><a name="exports" href="#exports"><xsl:text>Exports</xsl:text></a></h3>
+ <xsl:call-template name="h3_title_link">
+ <xsl:with-param name="title">Exports</xsl:with-param>
+ </xsl:call-template>
<div class="exports-body">
<xsl:apply-templates>
@@ -1938,7 +2033,8 @@
<p><xsl:apply-templates select="name"/>
<xsl:apply-templates
select="name[string-length(@arity) > 0 and position()=last()]"
- mode="types"/></p>
+ mode="types"/>
+ </p>
<xsl:apply-templates select="fsummary|type|desc">
<xsl:with-param name="partnum" select="$partnum"/>
@@ -1997,14 +2093,19 @@
<xsl:choose>
<xsl:when test="ancestor::cref">
- <a name="{substring-before(nametext, '(')}">
- <span class="bold_code bc-7">
- <xsl:value-of select="ret"/>
- <xsl:call-template name="maybe-space-after-ret">
- <xsl:with-param name="s" select="ret"/>
- </xsl:call-template>
- <xsl:value-of select="nametext"/>
- </span></a><br/>
+ <span class="bold_code bc-7">
+ <xsl:call-template name="title_link">
+ <xsl:with-param name="link" select="substring-before(nametext, '(')"/>
+ <xsl:with-param name="title">
+ <xsl:value-of select="ret"/>
+ <xsl:call-template name="maybe-space-after-ret">
+ <xsl:with-param name="s" select="ret"/>
+ </xsl:call-template>
+ <xsl:value-of select="nametext"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </span>
+ <br/>
</xsl:when>
<xsl:when test="ancestor::erlref">
<xsl:variable name="fname">
@@ -2025,15 +2126,29 @@
</xsl:variable>
<xsl:choose>
<xsl:when test="ancestor::datatype">
- <a name="type-{$fname}"></a><span class="bold_code bc-8"><xsl:apply-templates/></span><br/>
+ <div class="bold_code bc-8">
+ <xsl:call-template name="title_link">
+ <xsl:with-param name="link" select="concat('type-',$fname)"/>
+ <xsl:with-param name="title">
+ <xsl:apply-templates/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </div>
</xsl:when>
<xsl:otherwise>
- <a name="{$fname}-{$arity}"></a><span class="bold_code fun-type"><xsl:apply-templates/></span><br/>
+ <div class="bold_code fun-type">
+ <xsl:call-template name="title_link">
+ <xsl:with-param name="link" select="concat(concat($fname,'-'),$arity)"/>
+ <xsl:with-param name="title">
+ <xsl:apply-templates/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </div>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
- <span class="bold_code bc-10"><xsl:value-of select="."/></span>
+ <div class="bold_code bc-10"><xsl:value-of select="."/></div>
</xsl:otherwise>
</xsl:choose>
@@ -2093,6 +2208,49 @@
</div>
</xsl:template>
+ <xsl:template name="h3_title_link">
+ <xsl:param name="title"/>
+ <h3>
+ <xsl:call-template name="title_link">
+ <xsl:with-param name="title" select="$title"/>
+ <xsl:with-param name="link" select="erl:to-link($title)"/>
+ </xsl:call-template>
+ </h3>
+ </xsl:template>
+
+ <xsl:template name="title_link">
+ <xsl:param name="title"/>
+ <xsl:param name="link" select="erl:to-link(title)"/>
+ <xsl:param name="ghlink" select="ancestor-or-self::*[@ghlink][position() = 1]/@ghlink"/>
+ <xsl:variable name="id" select="concat(concat($link,'-'), generate-id(.))"/>
+ <span onMouseOver="document.getElementById('ghlink-{$id}').style.visibility = 'visible';"
+ onMouseOut="document.getElementById('ghlink-{$id}').style.visibility = 'hidden';">
+ <xsl:call-template name="ghlink">
+ <xsl:with-param name="id" select="$id"/>
+ <xsl:with-param name="ghlink" select="$ghlink"/>
+ </xsl:call-template>
+ <a class="title_link" name="{$link}" href="#{$link}"><xsl:value-of select="$title"/></a>
+ </span>
+ </xsl:template>
+
+ <xsl:template name="ghlink">
+ <xsl:param name="id"/>
+ <xsl:param name="ghlink" select="ancestor-or-self::*[@ghlink][position() = 1]/@ghlink"/>
+ <xsl:choose>
+ <xsl:when test="string-length($ghlink) > 0">
+ <span id="ghlink-{$id}" class="ghlink">
+ <a href="https://github.com/erlang/otp/edit/{$ghlink}"
+ title="Found an issue with the documentation? Fix it by clicking here!">
+ <span class="pencil"/>
+ </a>
+ </span>
+ </xsl:when>
+ <xsl:otherwise>
+ <span id="ghlink-{$id}"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
<!-- Desc -->
<xsl:template match="desc">
<xsl:param name="partnum"/>
diff --git a/lib/erl_docgen/priv/xsl/db_man.xsl b/lib/erl_docgen/priv/xsl/db_man.xsl
index 03b6b0691d..27b2bd4066 100644
--- a/lib/erl_docgen/priv/xsl/db_man.xsl
+++ b/lib/erl_docgen/priv/xsl/db_man.xsl
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
- # Copyright Ericsson AB 2009-2016. All Rights Reserved.
+ # Copyright Ericsson AB 2009-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -271,6 +271,12 @@
<xsl:apply-templates/>
</xsl:template>
+ <!-- Datatype Title-->
+ <xsl:template match="datatype_title">
+ <xsl:text>&#10;.SS </xsl:text>
+ <xsl:apply-templates/>
+ </xsl:template>
+
<!-- Datatype -->
<xsl:template match="datatype">
<xsl:apply-templates/>
diff --git a/lib/erl_docgen/priv/xsl/db_pdf.xsl b/lib/erl_docgen/priv/xsl/db_pdf.xsl
index 99263847fb..1b91d768e3 100644
--- a/lib/erl_docgen/priv/xsl/db_pdf.xsl
+++ b/lib/erl_docgen/priv/xsl/db_pdf.xsl
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
- # Copyright Ericsson AB 2009-2016. All Rights Reserved.
+ # Copyright Ericsson AB 2009-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -23,12 +23,16 @@
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
- extension-element-prefixes="exsl"
- xmlns:fo="http://www.w3.org/1999/XSL/Format">
+ xmlns:func="http://exslt.org/functions"
+ xmlns:erl="http://erlang.org"
+ extension-element-prefixes="exsl func"
+ xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ xmlns:fn="http://www.w3.org/2005/02/xpath-functions">
<xsl:output method="xml" indent="yes"/>
<xsl:include href="db_pdf_params.xsl"/>
+ <xsl:include href="db_funcs.xsl"/>
<!-- Start of Dialyzer type/spec tags.
See also the templates matching "name" and "seealso" as well as
@@ -295,6 +299,13 @@
<xsl:apply-templates/>
</xsl:template>
+ <!-- Datatype Title-->
+ <xsl:template match="datatype_title">
+ <fo:block xsl:use-attribute-sets="h4">
+ <xsl:apply-templates/>
+ </fo:block>
+ </xsl:template>
+
<!-- Datatype -->
<xsl:template match="datatype">
<fo:block xsl:use-attribute-sets="function-name">
@@ -687,7 +698,7 @@
<fo:block xsl:use-attribute-sets="cover.inner.copyrightnotice">
<xsl:value-of select="/book/header/legalnotice"/>
- <!--
+ <!--
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -744,12 +755,12 @@
<fo:bookmark internal-destination="{generate-id(header/title)}"
starting-state="hide">
<fo:bookmark-title><xsl:value-of select="header/title"/></fo:bookmark-title>
-
+
<xsl:call-template name="bookmarks2">
<xsl:with-param name="entries"
select="chapter[header/title]"/>
</xsl:call-template>
-
+
</fo:bookmark>
</xsl:for-each>
</xsl:if>
@@ -1122,52 +1133,60 @@
<!-- Note -->
<xsl:template match="note">
<xsl:param name="partnum"/>
- <fo:block xsl:use-attribute-sets="note">
- <fo:block xsl:use-attribute-sets="note-warning-title">
- <xsl:text>Note:</xsl:text>
- </fo:block>
- <xsl:apply-templates>
- <xsl:with-param name="partnum" select="$partnum"/>
- </xsl:apply-templates>
+ <fo:block xsl:use-attribute-sets="note-warning">
+ <fo:block xsl:use-attribute-sets="note-title">
+ <xsl:text>Note:</xsl:text>
+ </fo:block>
+ <fo:block xsl:use-attribute-sets="note-warning-content">
+ <xsl:apply-templates>
+ <xsl:with-param name="partnum" select="$partnum"/>
+ </xsl:apply-templates>
+ </fo:block>
</fo:block>
</xsl:template>
<!-- Warning -->
<xsl:template match="warning">
<xsl:param name="partnum"/>
- <fo:block xsl:use-attribute-sets="warning">
- <fo:block xsl:use-attribute-sets="note-warning-title">
- <xsl:text>Warning:</xsl:text>
- </fo:block>
- <xsl:apply-templates>
- <xsl:with-param name="partnum" select="$partnum"/>
- </xsl:apply-templates>
+ <fo:block xsl:use-attribute-sets="note-warning">
+ <fo:block xsl:use-attribute-sets="warning-title">
+ <xsl:text>Warning:</xsl:text>
+ </fo:block>
+ <fo:block xsl:use-attribute-sets="note-warning-content">
+ <xsl:apply-templates>
+ <xsl:with-param name="partnum" select="$partnum"/>
+ </xsl:apply-templates>
+ </fo:block>
</fo:block>
</xsl:template>
<!-- Do -->
<xsl:template match="do">
<xsl:param name="partnum"/>
- <fo:block xsl:use-attribute-sets="do">
- <fo:block xsl:use-attribute-sets="note-warning-title">
- <xsl:text>Do:</xsl:text>
- </fo:block>
- <xsl:apply-templates>
- <xsl:with-param name="partnum" select="$partnum"/>
- </xsl:apply-templates>
+ <fo:block xsl:use-attribute-sets="note-warning">
+ <fo:block xsl:use-attribute-sets="note-title">
+ <xsl:text>Do:</xsl:text>
+ </fo:block>
+ <fo:block xsl:use-attribute-sets="note-warning-content">
+ <xsl:apply-templates>
+ <xsl:with-param name="partnum" select="$partnum"/>
+ </xsl:apply-templates>
+ </fo:block>
</fo:block>
</xsl:template>
<!-- Dont -->
<xsl:template match="dont">
<xsl:param name="partnum"/>
- <fo:block xsl:use-attribute-sets="dont">
- <fo:block xsl:use-attribute-sets="note-warning-title">
- <xsl:text>Don't:</xsl:text>
- </fo:block>
- <xsl:apply-templates>
- <xsl:with-param name="partnum" select="$partnum"/>
- </xsl:apply-templates>
+ <fo:block xsl:use-attribute-sets="note-warning">
+ <fo:block xsl:use-attribute-sets="warning-title">
+ <xsl:text>Don't:</xsl:text>
+ </fo:block>
+ <fo:block xsl:use-attribute-sets="note-warning-content">
+ <xsl:apply-templates>
+ <xsl:with-param name="partnum" select="$partnum"/>
+ </xsl:apply-templates>
+ </fo:block>
</fo:block>
</xsl:template>
@@ -1226,7 +1245,14 @@
</xsl:variable>
<fo:block xsl:use-attribute-sets="code">
- <xsl:apply-templates select="text()"/>
+ <xsl:choose>
+ <xsl:when test="not(descendant::anno)">
+ <xsl:value-of select="erl:code_trim(text())"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates/>
+ </xsl:otherwise>
+ </xsl:choose>
</fo:block>
<xsl:if test="@caption">
@@ -1630,8 +1656,14 @@
</xsl:variable>
<fo:block xsl:use-attribute-sets="image">
- <fo:external-graphic content-width="scale-down-to-fit" inline-progression-dimension.maximum="100%" src="{@file}"/>
-
+ <xsl:choose>
+ <xsl:when test="@width">
+ <fo:external-graphic content-width="scale-to-fit" width="{@width}" inline-progression-dimension.maximum="100%" src="{@file}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <fo:external-graphic content-width="scale-down-to-fit" inline-progression-dimension.maximum="100%" src="{@file}"/>
+ </xsl:otherwise>
+ </xsl:choose>
<xsl:apply-templates>
<xsl:with-param name="chapnum" select="$chapnum"/>
<xsl:with-param name="fignum" select="$fignum"/>
diff --git a/lib/erl_docgen/priv/xsl/db_pdf_params.xsl b/lib/erl_docgen/priv/xsl/db_pdf_params.xsl
index d9a150d2d9..9bfa991b54 100644
--- a/lib/erl_docgen/priv/xsl/db_pdf_params.xsl
+++ b/lib/erl_docgen/priv/xsl/db_pdf_params.xsl
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
+<!--
#
# %CopyrightBegin%
#
- # Copyright Ericsson AB 2009-2016. All Rights Reserved.
+ # Copyright Ericsson AB 2009-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
# limitations under the License.
#
# %CopyrightEnd%
-
+
-->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
@@ -45,7 +45,7 @@
<xsl:param name="page-width">210mm</xsl:param>
<!-- Paper size: US Letter (279x216 mm) -->
- <!--
+ <!--
<xsl:param name="page-height">11in</xsl:param>
<xsl:param name="page-width">8.5in</xsl:param>
-->
@@ -139,6 +139,7 @@
<xsl:attribute-set name="image">
<xsl:attribute name="space-after">0.5em</xsl:attribute>
<xsl:attribute name="space-before">0.5em</xsl:attribute>
+ <xsl:attribute name="text-align">center</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="listblock">
@@ -248,86 +249,82 @@
</xsl:attribute-set>
<xsl:attribute-set name="code">
- <xsl:attribute name="background-color">#e0e0ff</xsl:attribute>
+ <xsl:attribute name="background-color">#f1f3f5</xsl:attribute>
+ <xsl:attribute name="border-style">solid</xsl:attribute>
+ <xsl:attribute name="border-color">#dee2e6</xsl:attribute><!-- dee2e6-->
+ <xsl:attribute name="border-width">0.3mm</xsl:attribute>
<xsl:attribute name="font-family">DejaVuSansMono, monospace</xsl:attribute>
<xsl:attribute name="font-size">0.8em</xsl:attribute>
- <xsl:attribute name="keep-together.within-page">auto</xsl:attribute>
+ <xsl:attribute name="keep-together.within-page">3</xsl:attribute>
<xsl:attribute name="linefeed-treatment">preserve</xsl:attribute>
- <xsl:attribute name="padding-before">0em</xsl:attribute>
- <xsl:attribute name="padding-after">1em</xsl:attribute>
- <xsl:attribute name="space-after">1em</xsl:attribute>
- <xsl:attribute name="space-before">2em</xsl:attribute>
- <xsl:attribute name="margin-left">0.5em</xsl:attribute>
- <xsl:attribute name="margin-right">0.5em</xsl:attribute>
+ <xsl:attribute name="padding-before">1.5mm</xsl:attribute>
+ <xsl:attribute name="padding-after">1mm</xsl:attribute>
+ <xsl:attribute name="padding-left">1mm</xsl:attribute>
+ <xsl:attribute name="padding-right">1mm</xsl:attribute>
+ <xsl:attribute name="margin-left">1mm</xsl:attribute>
+ <xsl:attribute name="margin-right">1mm</xsl:attribute>
<xsl:attribute name="white-space-collapse">false</xsl:attribute>
<xsl:attribute name="white-space-treatment">preserve</xsl:attribute>
<xsl:attribute name="wrap-option">no-wrap</xsl:attribute>
+ <xsl:attribute name="space-after">0.5em</xsl:attribute>
+ <xsl:attribute name="space-before">0.5em</xsl:attribute>
</xsl:attribute-set>
-
-
<xsl:attribute-set name="toc.level1">
<xsl:attribute name="space-before">1em</xsl:attribute>
- </xsl:attribute-set>
-
-<xsl:attribute-set name="note">
- <xsl:attribute name="background-color">#d0fed0</xsl:attribute>
- <xsl:attribute name="space-after">1em</xsl:attribute>
- <xsl:attribute name="space-before">2em</xsl:attribute>
- <xsl:attribute name="text-align">justify</xsl:attribute>
- <xsl:attribute name="padding-before">1em</xsl:attribute>
- <xsl:attribute name="padding-after">0.3em</xsl:attribute>
- <xsl:attribute name="padding-left">0.5em</xsl:attribute>
- <xsl:attribute name="padding-right">0.5em</xsl:attribute>
- <xsl:attribute name="margin-left">0.5em</xsl:attribute>
- <xsl:attribute name="margin-right">0.5em</xsl:attribute>
- <xsl:attribute name="keep-together.within-page">always</xsl:attribute>
</xsl:attribute-set>
-<xsl:attribute-set name="warning">
- <xsl:attribute name="background-color">#ffd6d6</xsl:attribute>
- <xsl:attribute name="space-after">1em</xsl:attribute>
- <xsl:attribute name="space-before">2em</xsl:attribute>
- <xsl:attribute name="text-align">justify</xsl:attribute>
- <xsl:attribute name="padding-before">1em</xsl:attribute>
- <xsl:attribute name="padding-after">0.3em</xsl:attribute>
- <xsl:attribute name="padding-left">0.5em</xsl:attribute>
- <xsl:attribute name="padding-right">0.5em</xsl:attribute>
- <xsl:attribute name="margin-left">0.5em</xsl:attribute>
- <xsl:attribute name="margin-right">0.5em</xsl:attribute>
- <xsl:attribute name="keep-together.within-page">always</xsl:attribute>
+ <xsl:attribute-set name="note-title">
+ <xsl:attribute name="space-before">0.5em</xsl:attribute>
+ <xsl:attribute name="border-style">solid</xsl:attribute>
+ <xsl:attribute name="border-bottom-width">0mm</xsl:attribute>
+ <xsl:attribute name="border-color">#495057</xsl:attribute>
+ <xsl:attribute name="background-color">#2b8a3e</xsl:attribute>
+ <xsl:attribute name="font-weight">bold</xsl:attribute>
+ <xsl:attribute name="color">#fefefe</xsl:attribute>
+ <xsl:attribute name="padding-before">1mm</xsl:attribute>
+ <xsl:attribute name="padding-after">0.5mm</xsl:attribute>
+ <xsl:attribute name="padding-left">1mm</xsl:attribute>
+ <xsl:attribute name="padding-right">1mm</xsl:attribute>
+ <xsl:attribute name="margin-left">1mm</xsl:attribute>
+ <xsl:attribute name="margin-right">1mm</xsl:attribute>
+ <xsl:attribute name="font-size">1.33em</xsl:attribute>
</xsl:attribute-set>
-<xsl:attribute-set name="do">
- <xsl:attribute name="background-color">#d0fed0</xsl:attribute>
- <xsl:attribute name="space-after">1em</xsl:attribute>
- <xsl:attribute name="space-before">2em</xsl:attribute>
- <xsl:attribute name="text-align">justify</xsl:attribute>
- <xsl:attribute name="padding-before">1em</xsl:attribute>
- <xsl:attribute name="padding-after">0.3em</xsl:attribute>
- <xsl:attribute name="padding-left">0.5em</xsl:attribute>
- <xsl:attribute name="padding-right">0.5em</xsl:attribute>
- <xsl:attribute name="margin-left">0.5em</xsl:attribute>
- <xsl:attribute name="margin-right">0.5em</xsl:attribute>
+ <xsl:attribute-set name="note-warning">
<xsl:attribute name="keep-together.within-page">always</xsl:attribute>
</xsl:attribute-set>
-<xsl:attribute-set name="dont">
- <xsl:attribute name="background-color">#ffd6d6</xsl:attribute>
- <xsl:attribute name="space-after">1em</xsl:attribute>
- <xsl:attribute name="space-before">2em</xsl:attribute>
- <xsl:attribute name="text-align">justify</xsl:attribute>
- <xsl:attribute name="padding-before">1em</xsl:attribute>
- <xsl:attribute name="padding-after">0.3em</xsl:attribute>
- <xsl:attribute name="padding-left">0.5em</xsl:attribute>
- <xsl:attribute name="padding-right">0.5em</xsl:attribute>
- <xsl:attribute name="margin-left">0.5em</xsl:attribute>
- <xsl:attribute name="margin-right">0.5em</xsl:attribute>
- <xsl:attribute name="keep-together.within-page">always</xsl:attribute>
+ <xsl:attribute-set name="warning-title">
+ <xsl:attribute name="space-before">0.5em</xsl:attribute>
+ <xsl:attribute name="border-style">solid</xsl:attribute>
+ <xsl:attribute name="border-bottom-width">0mm</xsl:attribute>
+ <xsl:attribute name="border-color">#495057</xsl:attribute>
+ <xsl:attribute name="background-color">#c92a2a</xsl:attribute>
+ <xsl:attribute name="font-weight">bold</xsl:attribute>
+ <xsl:attribute name="color">#fefefe</xsl:attribute>
+ <xsl:attribute name="padding-before">1mm</xsl:attribute>
+ <xsl:attribute name="padding-after">0.5mm</xsl:attribute>
+ <xsl:attribute name="padding-left">1mm</xsl:attribute>
+ <xsl:attribute name="padding-right">1mm</xsl:attribute>
+ <xsl:attribute name="margin-left">1mm</xsl:attribute>
+ <xsl:attribute name="margin-right">1mm</xsl:attribute>
+ <xsl:attribute name="font-size">1.33em</xsl:attribute>
</xsl:attribute-set>
- <xsl:attribute-set name="note-warning-title">
- <xsl:attribute name="font-size">1.33em</xsl:attribute>
+ <xsl:attribute-set name="note-warning-content">
+ <xsl:attribute name="space-after">0.5em</xsl:attribute>
+ <xsl:attribute name="border-style">solid</xsl:attribute>
+ <xsl:attribute name="border-top-width">0mm</xsl:attribute>
+ <xsl:attribute name="border-color">#495057</xsl:attribute>
+ <xsl:attribute name="background-color">#f8f9fa</xsl:attribute>
+ <xsl:attribute name="text-align">justify</xsl:attribute>
+ <xsl:attribute name="padding-before">1mm</xsl:attribute>
+ <xsl:attribute name="padding-after">0.5mm</xsl:attribute>
+ <xsl:attribute name="padding-left">1mm</xsl:attribute>
+ <xsl:attribute name="padding-right">1mm</xsl:attribute>
+ <xsl:attribute name="margin-left">1mm</xsl:attribute>
+ <xsl:attribute name="margin-right">1mm</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="module-header">
@@ -354,7 +351,7 @@
<xsl:attribute name="keep-with-next.within-page">always</xsl:attribute>
<xsl:attribute name="space-after">0.25em</xsl:attribute>
<!-- xsl:attribute name="space-before">1.5em</xsl:attribute -->
- </xsl:attribute-set>
+ </xsl:attribute-set>
<xsl:attribute-set name="type-listblock">
<xsl:attribute name="provisional-distance-between-starts">1.8em</xsl:attribute>
diff --git a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl
index 7cdbb502d9..b065c18cda 100644
--- a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl
+++ b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl
@@ -11,7 +11,7 @@
%% limitations under the License.
%%
%% Copyright (c) 2001-2016 Richard Carlsson. Parts written by Ericsson
-%% are Copyright (c) Ericsson AB 2001-2012. All Rights Reserved.
+%% are Copyright (c) Ericsson AB 2001-2017. All Rights Reserved.
%%
-module(docgen_edoc_xml_cb).
@@ -113,7 +113,7 @@ root_attributes(Element, Opts) ->
%% epp:default_encoding/0 returns 'utf8'
reformat_encoding(utf8) -> "UTF-8";
reformat_encoding(List) when is_list(List) ->
- case string:to_lower(List) of
+ case string:lowercase(List) of
"utf8" -> "UTF-8";
_ -> List
end;
@@ -489,6 +489,8 @@ otp_xmlify_a_href("#"++_ = Marker, Es0) -> % <seealso marker="#what">
{Marker, Es0};
otp_xmlify_a_href("http:"++_ = URL, Es0) -> % external URL
{URL, Es0};
+otp_xmlify_a_href("https:"++_ = URL, Es0) -> % external URL
+ {URL, Es0};
otp_xmlify_a_href("OTPROOT"++AppRef, Es0) -> % <.. marker="App:FileRef
[AppS, "doc", FileRef1] = split(AppRef, "/"),
FileRef = AppS++":"++otp_xmlify_a_fileref(FileRef1, AppS),
diff --git a/lib/erl_docgen/src/docgen_otp_specs.erl b/lib/erl_docgen/src/docgen_otp_specs.erl
index 6c41147e27..311ec1471a 100644
--- a/lib/erl_docgen/src/docgen_otp_specs.erl
+++ b/lib/erl_docgen/src/docgen_otp_specs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -297,7 +297,7 @@ indent(L) ->
app_fix(L) ->
try
{"//" ++ R1,L2} = app_fix(L, 1),
- [App, Mod] = string:tokens(R1, "/"),
+ [App, Mod] = string:lexemes(R1, "/"),
"//" ++ atom(App) ++ "/" ++ atom(Mod) ++ L2
catch _:_ -> L
end.
@@ -406,7 +406,7 @@ t_var(E) ->
[get_attrval(name, E)].
t_atom(E) ->
- [get_attrval(value, E)].
+ [io_lib:write(list_to_atom(get_attrval(value, E)))].
t_integer(E) ->
[get_attrval(value, E)].
@@ -578,20 +578,20 @@ ot_var(E) ->
{var,0,list_to_atom(get_attrval(name, E))}.
ot_atom(E) ->
- {ok, [{atom,A,Name}], _} = erl_scan:string(get_attrval(value, E), 0),
+ {ok, [{atom,A,Name}], _} = erl_scan:string(lists:flatten(t_atom(E)), 0),
{atom,erl_anno:line(A),Name}.
ot_integer(E) ->
{integer,0,list_to_integer(get_attrval(value, E))}.
ot_range(E) ->
- [I1, I2] = string:tokens(get_attrval(value, E), "."),
+ [I1, I2] = string:lexemes(get_attrval(value, E), "."),
{type,0,range,[{integer,0,list_to_integer(I1)},
{integer,0,list_to_integer(I2)}]}.
ot_binary(E) ->
{Base, Unit} =
- case string:tokens(get_attrval(value, E), ",:*><") of
+ case string:lexemes(get_attrval(value, E), ",:*><") of
[] ->
{0, 0};
["_",B] ->
@@ -658,6 +658,8 @@ ot_name(Es, T) ->
{atom,0,list_to_atom(Atom)},T]};
"tuple" when T =:= [] ->
{type,0,tuple,any};
+ "map" when T =:= [] ->
+ {type,0,map,any};
Atom ->
{type,0,list_to_atom(Atom),T}
end.
diff --git a/lib/erl_docgen/src/erl_docgen.app.src b/lib/erl_docgen/src/erl_docgen.app.src
index d63d880d89..171c697585 100644
--- a/lib/erl_docgen/src/erl_docgen.app.src
+++ b/lib/erl_docgen/src/erl_docgen.app.src
@@ -9,6 +9,6 @@
{registered,[]},
{applications, [kernel,stdlib]},
{env, []},
- {runtime_dependencies, ["xmerl-1.3.7","stdlib-2.5","edoc-0.7.13","erts-6.0"]}
+ {runtime_dependencies, ["xmerl-1.3.7","stdlib-3.4","edoc-0.7.13","erts-9.0"]}
]
}.
diff --git a/lib/erl_docgen/vsn.mk b/lib/erl_docgen/vsn.mk
index 8fad061b26..3b2f6db6a1 100644
--- a/lib/erl_docgen/vsn.mk
+++ b/lib/erl_docgen/vsn.mk
@@ -1 +1 @@
-ERL_DOCGEN_VSN = 0.7
+ERL_DOCGEN_VSN = 0.8.1
diff --git a/lib/erl_interface/configure.in b/lib/erl_interface/configure.in
index 0a8fbf513c..a155ceef7e 100644
--- a/lib/erl_interface/configure.in
+++ b/lib/erl_interface/configure.in
@@ -1,7 +1,7 @@
# -*- Autoconf -*-
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
+# Copyright Ericsson AB 2000-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -106,6 +106,19 @@ if test $ac_cv_sizeof_long = 8; then
CFLAGS="$CFLAGS -DEI_64BIT"
fi
+LM_HARDWARE_ARCH
+
+AC_MSG_CHECKING(for unaligned word access)
+case "$ARCH" in
+ x86|amd64)
+ AC_MSG_RESULT(yes: x86 or amd64)
+ AC_DEFINE(HAVE_UNALIGNED_WORD_ACCESS, 1, [Define if hw supports unaligned word access])
+ ;;
+ *)
+ AC_MSG_RESULT(no)
+ ;;
+esac
+
AC_CHECK_TOOL(AR, ar, false)
if test "$AR" = false; then
AC_MSG_ERROR([No 'ar' command found in PATH])
diff --git a/lib/erl_interface/doc/src/Makefile b/lib/erl_interface/doc/src/Makefile
index 204a6051b2..507a84a453 100644
--- a/lib/erl_interface/doc/src/Makefile
+++ b/lib/erl_interface/doc/src/Makefile
@@ -1,8 +1,8 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1998-2016. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 1998-2018. All Rights Reserved.
+#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -14,7 +14,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
+#
# %CopyrightEnd%
#
include $(ERL_TOP)/make/target.mk
@@ -36,7 +36,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# Target Specs
# ----------------------------------------------------
-XML_REF1_FILES = erl_call.xml
+XML_REF1_FILES = erl_call.xml
XML_REF3_FILES = erl_connect.xml \
erl_error.xml \
erl_eterm.xml \
@@ -46,16 +46,14 @@ XML_REF3_FILES = erl_connect.xml \
erl_global.xml \
ei.xml \
ei_connect.xml \
- registry.xml
+ registry.xml
BOOK_FILES = book.xml
-XML_APPLICATION_FILES = ref_man.xml
+XML_APPLICATION_FILES = ref_man.xml
#ref_man_ei.xml ref_man_erl_interface.xml
XML_PART_FILES = \
- part.xml \
- part_notes.xml \
- part_notes_history.xml
-XML_CHAPTER_FILES = ei_users_guide.xml notes.xml notes_history.xml
+ part.xml
+XML_CHAPTER_FILES = ei_users_guide.xml notes.xml
XML_FILES = $(XML_REF1_FILES) $(XML_REF3_FILES) $(BOOK_FILES) \
$(XML_APPLICATION_FILES) $(XML_PART_FILES) $(XML_CHAPTER_FILES)
@@ -66,7 +64,7 @@ HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
INFO_FILE = ../../info
-GIF_FILES =
+GIF_FILES =
MAN1_FILES = $(XML_REF1_FILES:%.xml=$(MAN1DIR)/%.1)
MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
@@ -76,9 +74,9 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
+XML_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -98,10 +96,11 @@ man: $(MAN1_FILES) $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-debug opt:
+debug opt:
clean clean_docs clean_tex:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN1DIR)/*
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
@@ -110,7 +109,7 @@ clean clean_docs clean_tex:
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
@@ -127,4 +126,3 @@ release_docs_spec: docs
release_spec:
-
diff --git a/lib/erl_interface/doc/src/note.gif b/lib/erl_interface/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/erl_interface/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml
index ec20f3c67f..07ddd82718 100644
--- a/lib/erl_interface/doc/src/notes.xml
+++ b/lib/erl_interface/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,147 @@
</header>
<p>This document describes the changes made to the Erl_interface application.</p>
+<section><title>Erl_Interface 3.10.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Make <c>ei_connect</c> and friends also accept state
+ <c>ok_simultaneous</c> during handshake, which means the
+ other node has initiated a connection setup that will be
+ cancelled in favor of this connection.</p>
+ <p>
+ Own Id: OTP-15161 Aux Id: ERIERL-191 </p>
+ </item>
+ <item>
+ <p>
+ Fixed bug in <c>ei_receive_msg</c>,
+ <c>ei_xreceive_msg</c>, <c>ei_receive_msg_tmo</c> and
+ <c>ei_xreceive_msg_tmo</c>. The <c>x-&gt;index</c> was
+ set to entire buffer size instead of the number of bytes
+ actually received.</p>
+ <p>
+ Own Id: OTP-15171</p>
+ </item>
+ <item>
+ <p>
+ Fixed bug in <c>ei_connect_init</c> which could be
+ provoked if called by concurrent threads.
+ <c>ei_connect_init</c> called posix interface
+ <c>gethostbyname</c> which is documented as not thread
+ safe.</p>
+ <p>
+ Own Id: OTP-15191</p>
+ </item>
+ <item>
+ <p>
+ Fixed bug in erl_compare_ext() ignoring the tail of lists
+ of otherwise equal content. Example: <c>[a | b]</c> and
+ <c>[a | c]</c> compared equal and <c>{[a], b}</c> and
+ <c>{[a], c}</c> compared equal.</p>
+ <p>
+ Own Id: OTP-15277 Aux Id: PR-1929 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Interface 3.10.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix bug where calling erl_init on certain platforms could
+ result in a buffer overflow bug.</p>
+ <p>
+ Own Id: OTP-15033</p>
+ </item>
+ <item>
+ <p>
+ Fixed <c>erl_call -m</c> to not deallocate module source
+ binary before it has been read.</p>
+ <p>
+ Own Id: OTP-15105 Aux Id: ERL-629 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> The program <c>erl_call</c> calls
+ <c>erl_eval:eval_str/1</c> when it used to call
+ <c>lib:eval_str/1</c>. This means that <c>erl_call</c>
+ will fail when trying interact with an Erlang node
+ running Erlang/OTP 20 or earlier. </p>
+ <p>
+ Own Id: OTP-15114 Aux Id: OTP-15072, ERL-634 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Interface 3.10.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Make <c>ei_connect</c> and friends also accept state
+ <c>ok_simultaneous</c> during handshake, which means the
+ other node has initiated a connection setup that will be
+ cancelled in favor of this connection.</p>
+ <p>
+ Own Id: OTP-15161 Aux Id: ERIERL-191 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Interface 3.10.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix bug in <c>ei_connect</c> functions that may cause
+ failure due to insufficient buffer space for
+ gethostbyname_r.</p>
+ <p>
+ Own Id: OTP-15022 Aux Id: ERIERL-163 </p>
+ </item>
+ <item>
+ <p>
+ Optimize encoding/decoding for pure 7-bit ascii atoms.</p>
+ <p>
+ Own Id: OTP-15023 Aux Id: ERIERL-150 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Interface 3.10.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erl_Interface 3.10</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/erl_interface/doc/src/part_notes.xml b/lib/erl_interface/doc/src/part_notes.xml
deleted file mode 100644
index facdf821ee..0000000000
--- a/lib/erl_interface/doc/src/part_notes.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Erl_Interface Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p><em>Erl_Interface</em> is a C interface library for communication
- with Erlang.</p>
- <p>For information about older versions, see
- <url href="part_notes_history_frame.html">Release Notes History</url>.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/erl_interface/doc/src/part_notes_history.xml b/lib/erl_interface/doc/src/part_notes_history.xml
deleted file mode 100644
index 401fea4dd4..0000000000
--- a/lib/erl_interface/doc/src/part_notes_history.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2006</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Erl_Interface Release Notes History</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p><em>Erl_Interface</em> is a C interface library for communication
- with Erlang.</p>
- </description>
- <xi:include href="notes_history.xml"/>
-</part>
-
diff --git a/lib/erl_interface/doc/src/warning.gif b/lib/erl_interface/doc/src/warning.gif
deleted file mode 100644
index 96af52360e..0000000000
--- a/lib/erl_interface/doc/src/warning.gif
+++ /dev/null
Binary files differ
diff --git a/lib/erl_interface/src/Makefile b/lib/erl_interface/src/Makefile
index 31f34d4bba..800557fbfe 100644
--- a/lib/erl_interface/src/Makefile
+++ b/lib/erl_interface/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2016. All Rights Reserved.
+# Copyright Ericsson AB 1996-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -29,5 +29,5 @@ include $(ERL_TOP)/make/target.mk
debug opt shared purify quantify purecov gcov:
$(make_verbose)$(MAKE) -f $(TARGET)/Makefile TYPE=$@
-clean depend docs release release_docs tests release_tests check:
+clean depend docs release release_docs tests release_tests check xmllint:
$(make_verbose)$(MAKE) -f $(TARGET)/Makefile $@
diff --git a/lib/erl_interface/src/Makefile.in b/lib/erl_interface/src/Makefile.in
index 4f393e952c..614e7325a9 100644
--- a/lib/erl_interface/src/Makefile.in
+++ b/lib/erl_interface/src/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -854,3 +854,5 @@ endif
release_docs:
release_tests:
+
+xmllint:
diff --git a/lib/erl_interface/src/connect/ei_connect.c b/lib/erl_interface/src/connect/ei_connect.c
index ea9ecb31d5..9df4fa3b6c 100644
--- a/lib/erl_interface/src/connect/ei_connect.c
+++ b/lib/erl_interface/src/connect/ei_connect.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2017. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -138,6 +138,11 @@ static int recv_name(int fd,
unsigned *version,
unsigned *flags, ErlConnect *namebuf, unsigned ms);
+static struct hostent*
+dyn_gethostbyname_r(const char *name, struct hostent *hostp, char **buffer_p,
+ int buflen, int *h_errnop);
+
+
/***************************************************************************
*
@@ -480,10 +485,14 @@ int ei_connect_xinit(ei_cnode* ec, const char *thishostname,
int ei_connect_init(ei_cnode* ec, const char* this_node_name,
const char *cookie, short creation)
{
- struct hostent *hp;
char thishostname[EI_MAXHOSTNAMELEN+1];
char thisnodename[MAXNODELEN+1];
char thisalivename[EI_MAXALIVELEN+1];
+ struct hostent host, *hp;
+ char buffer[1024];
+ char *buf = buffer;
+ int ei_h_errno;
+ int res;
#ifdef __WIN32__
if (!initWinSock()) {
@@ -517,10 +526,13 @@ int ei_connect_init(ei_cnode* ec, const char* this_node_name,
strcpy(thisalivename, this_node_name);
}
- if ((hp = ei_gethostbyname(thishostname)) == 0) {
+ hp = dyn_gethostbyname_r(thishostname,&host,&buf,sizeof(buffer),&ei_h_errno);
+ if (hp == NULL) {
/* Looking up IP given hostname fails. We must be on a standalone
host so let's use loopback for communication instead. */
- if ((hp = ei_gethostbyname("localhost")) == 0) {
+ hp = dyn_gethostbyname_r("localhost", &host, &buf, sizeof(buffer),
+ &ei_h_errno);
+ if (hp == NULL) {
#ifdef __WIN32__
char reason[1024];
@@ -549,8 +561,11 @@ int ei_connect_init(ei_cnode* ec, const char* this_node_name,
sprintf(thisnodename, "%s@%s", this_node_name, hp->h_name);
}
}
- return ei_connect_xinit(ec, thishostname, thisalivename, thisnodename,
- (struct in_addr *)*hp->h_addr_list, cookie, creation);
+ res = ei_connect_xinit(ec, thishostname, thisalivename, thisnodename,
+ (struct in_addr *)*hp->h_addr_list, cookie, creation);
+ if (buf != buffer)
+ free(buf);
+ return res;
}
@@ -583,6 +598,62 @@ static int cnct(uint16 port, struct in_addr *ip_addr, int addr_len, unsigned ms)
return s;
} /* cnct */
+
+/*
+ * Same as ei_gethostbyname_r, but also handles ERANGE error
+ * and may allocate larger buffer with malloc.
+ */
+static
+struct hostent *dyn_gethostbyname_r(const char *name,
+ struct hostent *hostp,
+ char **buffer_p,
+ int buflen,
+ int *h_errnop)
+{
+#ifdef __WIN32__
+ /*
+ * Apparently ei_gethostbyname_r not implemented for Windows (?)
+ * Fall back on ei_gethostbyname like before.
+ */
+ return ei_gethostbyname(name);
+#else
+ char* buf = *buffer_p;
+ struct hostent *hp;
+
+ while (1) {
+ hp = ei_gethostbyname_r(name, hostp, buf, buflen, h_errnop);
+ if (hp) {
+ *buffer_p = buf;
+ break;
+ }
+
+ if (*h_errnop != ERANGE) {
+ if (buf != *buffer_p)
+ free(buf);
+ break;
+ }
+
+ buflen *= 2;
+ if (buf == *buffer_p)
+ buf = malloc(buflen);
+ else {
+ char* buf2 = realloc(buf, buflen);
+ if (buf2)
+ buf = buf2;
+ else {
+ free(buf);
+ buf = NULL;
+ }
+ }
+ if (!buf) {
+ *h_errnop = ENOMEM;
+ break;
+ }
+ }
+ return hp;
+#endif
+}
+
/*
* Set up a connection to a given Node, and
* interchange hand shake messages with it.
@@ -597,8 +668,10 @@ int ei_connect_tmo(ei_cnode* ec, char *nodename, unsigned ms)
/* these are needed for the call to gethostbyname_r */
struct hostent host;
char buffer[1024];
+ char *buf = buffer;
int ei_h_errno;
#endif /* !win32 */
+ int res;
/* extract the host and alive parts from nodename */
if (!(hostname = strchr(nodename,'@'))) {
@@ -611,7 +684,7 @@ int ei_connect_tmo(ei_cnode* ec, char *nodename, unsigned ms)
}
#ifndef __WIN32__
- hp = ei_gethostbyname_r(hostname,&host,buffer,1024,&ei_h_errno);
+ hp = dyn_gethostbyname_r(hostname,&host,&buf,sizeof(buffer),&ei_h_errno);
if (hp == NULL) {
char thishostname[EI_MAXHOSTNAMELEN+1];
/* gethostname requies len to be max(hostname) + 1*/
@@ -627,7 +700,7 @@ int ei_connect_tmo(ei_cnode* ec, char *nodename, unsigned ms)
}
if (strcmp(hostname,thishostname) == 0)
/* Both nodes on same standalone host, use loopback */
- hp = ei_gethostbyname_r("localhost",&host,buffer,1024,&ei_h_errno);
+ hp = dyn_gethostbyname_r("localhost",&host,&buf,sizeof(buffer),&ei_h_errno);
if (hp == NULL) {
EI_TRACE_ERR2("ei_connect",
"Can't find host for %s: %d\n",nodename,ei_h_errno);
@@ -663,7 +736,14 @@ int ei_connect_tmo(ei_cnode* ec, char *nodename, unsigned ms)
}
}
#endif /* win32 */
- return ei_xconnect_tmo(ec, (Erl_IpAddr) *hp->h_addr_list, alivename, ms);
+
+ res = ei_xconnect_tmo(ec, (Erl_IpAddr) *hp->h_addr_list, alivename, ms);
+
+#ifndef __WIN32__
+ if (buf != buffer)
+ free(buf);
+#endif
+ return res;
} /* ei_connect */
int ei_connect(ei_cnode* ec, char *nodename)
@@ -942,7 +1022,7 @@ int ei_do_receive_msg(int fd, int staticbuffer_p,
erl_errno = EMSGSIZE;
return ERL_ERROR;
}
- x->index = x->buffsz;
+ x->index = msglen;
switch (msg->msgtype) { /* FIXME does not handle trace tokens and monitors */
case ERL_SEND:
case ERL_REG_SEND:
@@ -1300,11 +1380,14 @@ static int recv_status(int fd, unsigned ms)
"<- RECV_STATUS socket read failed (%d)", rlen);
goto error;
}
- if (rlen == 3 && buf[0] == 's' && buf[1] == 'o' &&
- buf[2] == 'k') {
+
+ EI_TRACE_CONN2("recv_status",
+ "<- RECV_STATUS (%.*s)", (rlen>20 ? 20 : rlen), buf);
+
+ if (rlen >= 3 && buf[0] == 's' && buf[1] == 'o' && buf[2] == 'k') {
+ /* Expecting "sok" or "sok_simultaneous" */
if (!is_static)
free(buf);
- EI_TRACE_CONN0("recv_status","<- RECV_STATUS (ok)");
return 0;
}
error:
diff --git a/lib/erl_interface/src/connect/ei_resolve.c b/lib/erl_interface/src/connect/ei_resolve.c
index fd0c659373..022a43d255 100644
--- a/lib/erl_interface/src/connect/ei_resolve.c
+++ b/lib/erl_interface/src/connect/ei_resolve.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2016. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -645,8 +645,11 @@ struct hostent *ei_gethostbyname_r(const char *name,
#else
#if (defined(__GLIBC__) || defined(__linux__) || (__FreeBSD_version >= 602000) || defined(__DragonFly__) || defined(__ANDROID__))
struct hostent *result;
+ int err;
- gethostbyname_r(name, hostp, buffer, buflen, &result, h_errnop);
+ err = gethostbyname_r(name, hostp, buffer, buflen, &result, h_errnop);
+ if (err == ERANGE)
+ *h_errnop = err;
return result;
#else
diff --git a/lib/erl_interface/src/decode/decode_atom.c b/lib/erl_interface/src/decode/decode_atom.c
index b3bba82434..2bf8ab0552 100644
--- a/lib/erl_interface/src/decode/decode_atom.c
+++ b/lib/erl_interface/src/decode/decode_atom.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -92,6 +92,51 @@ int ei_decode_atom_as(const char *buf, int *index, char* p, int destlen,
}
+
+#ifdef HAVE_UNALIGNED_WORD_ACCESS
+
+#if SIZEOF_VOID_P == SIZEOF_LONG
+typedef unsigned long AsciiWord;
+#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG
+typedef unsigned long long AsciiWord;
+#else
+# error "Uknown word type"
+#endif
+
+#if SIZEOF_VOID_P == 4
+# define ASCII_CHECK_MASK ((AsciiWord)0x80808080U)
+#elif SIZEOF_VOID_P == 8
+# define ASCII_CHECK_MASK ((AsciiWord)0x8080808080808080U)
+#endif
+
+static int ascii_fast_track(char* dst, const char* src, int slen, int destlen)
+{
+ const AsciiWord* src_word = (AsciiWord*) src;
+ const AsciiWord* const src_word_end = src_word + (slen / sizeof(AsciiWord));
+
+ if (destlen < slen)
+ return 0;
+
+ if (dst) {
+ AsciiWord* dst_word = (AsciiWord*)dst;
+
+ while (src_word < src_word_end) {
+ if ((*src_word & ASCII_CHECK_MASK) != 0)
+ break;
+ *dst_word++ = *src_word++;
+ }
+ }
+ else {
+ while (src_word < src_word_end) {
+ if ((*src_word & ASCII_CHECK_MASK) != 0)
+ break;
+ src_word++;
+ }
+ }
+ return (char*)src_word - src;
+}
+#endif /* HAVE_UNALIGNED_WORD_ACCESS */
+
int utf8_to_latin1(char* dst, const char* src, int slen, int destlen,
erlang_char_encoding* res_encp)
{
@@ -99,6 +144,15 @@ int utf8_to_latin1(char* dst, const char* src, int slen, int destlen,
const char* const dst_end = dst + destlen;
int found_non_ascii = 0;
+#ifdef HAVE_UNALIGNED_WORD_ACCESS
+ {
+ int aft = ascii_fast_track(dst, src, slen, destlen);
+ src += aft;
+ slen -= aft;
+ dst += aft;
+ }
+#endif
+
while (slen > 0) {
if (dst >= dst_end) return -1;
if ((src[0] & 0x80) == 0) {
@@ -136,6 +190,14 @@ int latin1_to_utf8(char* dst, const char* src, int slen, int destlen,
const char* const dst_end = dst + destlen;
int found_non_ascii = 0;
+#ifdef HAVE_UNALIGNED_WORD_ACCESS
+ {
+ int aft = ascii_fast_track(dst, src, slen, destlen);
+ dst += aft;
+ src += aft;
+ }
+#endif
+
while (src < src_end) {
if (dst >= dst_end) return -1;
if ((src[0] & 0x80) == 0) {
diff --git a/lib/erl_interface/src/legacy/erl_marshal.c b/lib/erl_interface/src/legacy/erl_marshal.c
index caa171858d..932bba43bf 100644
--- a/lib/erl_interface/src/legacy/erl_marshal.c
+++ b/lib/erl_interface/src/legacy/erl_marshal.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2017. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -107,7 +107,7 @@ static int init_cmp_num_class_p=1; /* initialize array, the first time */
void erl_init_marshal(void)
{
if (init_cmp_array_p) {
- memset(cmp_array, 0, CMP_ARRAY_SIZE);
+ memset(cmp_array, 0, sizeof cmp_array);
cmp_array[ERL_SMALL_INTEGER_EXT] = ERL_NUM_CMP;
cmp_array[ERL_INTEGER_EXT] = ERL_NUM_CMP;
cmp_array[ERL_FLOAT_EXT] = ERL_NUM_CMP;
@@ -1803,7 +1803,7 @@ static int cmp_exe2(unsigned char **e1, unsigned char **e2)
k = 0;
while (1) {
if (k++ == min){
- if (i == j) return 0;
+ if (i == j) return compare_top_ext(e1 , e2);
if (i < j) return -1;
return 1;
}
diff --git a/lib/erl_interface/src/misc/ei_pthreads.c b/lib/erl_interface/src/misc/ei_pthreads.c
index 25608edeec..ec1c8d956f 100644
--- a/lib/erl_interface/src/misc/ei_pthreads.c
+++ b/lib/erl_interface/src/misc/ei_pthreads.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -206,6 +206,7 @@ volatile int *__erl_errno_place(void)
use_fallback = 1;
return &fallback_errno;
}
+ *erl_errno_p = 0;
if (pthread_setspecific(erl_errno_key, erl_errno_p) != 0 ||
(erl_errno_p = pthread_getspecific(erl_errno_key)) == NULL) {
diff --git a/lib/erl_interface/src/prog/erl_call.c b/lib/erl_interface/src/prog/erl_call.c
index 7577a07a3e..52ad6885e8 100644
--- a/lib/erl_interface/src/prog/erl_call.c
+++ b/lib/erl_interface/src/prog/erl_call.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2017. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -517,6 +517,15 @@ int erl_call(int argc, char **argv)
}
}
+
+ /*
+ * If we loaded any module source code, we can free the buffer
+ * now. This buffer was allocated in read_stdin().
+ */
+ if (module != NULL) {
+ free(module);
+ }
+
/*
* Eval the Erlang functions read from stdin/
*/
@@ -545,7 +554,7 @@ int erl_call(int argc, char **argv)
/* erl_format("[~w]", erl_mk_binary(evalbuf,len))) */
- if (ei_rpc(&ec, fd, "lib", "eval_str", p, i, &reply) < 0) {
+ if (ei_rpc(&ec, fd, "erl_eval", "eval_str", p, i, &reply) < 0) {
fprintf(stderr,"erl_call: evaluating input failed: %s\n",
evalbuf);
free(p);
@@ -795,8 +804,6 @@ static int get_module(char **mbuf, char **mname)
*mname = (char *) ei_chk_calloc(i+1, sizeof(char));
memcpy(*mname, start, i);
}
- if (*mbuf)
- free(*mbuf); /* Allocated in read_stdin() */
return len;
diff --git a/lib/erl_interface/test/ei_accept_SUITE.erl b/lib/erl_interface/test/ei_accept_SUITE.erl
index e06ee762d7..78a433d21b 100644
--- a/lib/erl_interface/test/ei_accept_SUITE.erl
+++ b/lib/erl_interface/test/ei_accept_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,7 +25,9 @@
-include("ei_accept_SUITE_data/ei_accept_test_cases.hrl").
-export([all/0, suite/0,
- ei_accept/1, ei_threaded_accept/1]).
+ init_per_testcase/2,
+ ei_accept/1, ei_threaded_accept/1,
+ monitor_ei_process/1]).
-import(runner, [get_term/1,send_term/2]).
@@ -34,43 +36,46 @@ suite() ->
{timetrap, {seconds, 30}}].
all() ->
- [ei_accept, ei_threaded_accept].
+ [ei_accept, ei_threaded_accept,
+ monitor_ei_process].
+
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
ei_accept(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
Myname = hd(tl(string:tokens(atom_to_list(node()), "@"))),
io:format("Myname ~p ~n", [Myname]),
EINode = list_to_atom("c42@"++Myname),
io:format("EINode ~p ~n", [EINode]),
+
+ %% We take this opportunity to also test export-funs and bit-strings
+ %% with (ugly) tuple fallbacks.
+ %% Test both toward pending connection and established connection.
+ RealTerms = [<<1:1>>, fun lists:map/2],
+ Fallbacks = [{<<128>>,1}, {lists,map}],
+
Self = self(),
- TermToSend= {call, Self, "Test"},
- F= fun() ->
- case waitfornode("c42",20) of
- true ->
- {any, EINode} ! TermToSend,
- Self ! sent_ok;
- false ->
- Self ! never_published
- end,
- ok
- end,
-
- spawn(F),
+ Funny = fun() -> hello end,
+ TermToSend = {call, Self, "Test", Funny, RealTerms},
+ TermToGet = {call, Self, "Test", Funny, Fallbacks},
Port = 6543,
- {ok, Fd, _Node} = ei_accept(P, Port),
- TermReceived= ei_receive(P, Fd),
- io:format("Sent ~p received ~p ~n", [TermToSend, TermReceived]),
- TermToSend= TermReceived,
- receive
- sent_ok ->
- ok;
- Unknown ->
- io:format("~p ~n", [Unknown])
- after 1000 ->
- io:format("timeout ~n")
- end,
+ {ok, ListenFd} = ei_publish(P, Port),
+ {any, EINode} ! TermToSend,
+
+ {ok, Fd, _Node} = ei_accept(P, ListenFd),
+ Got1 = ei_receive(P, Fd),
+
+ %% Send again, now without auto-connect
+ {any, EINode} ! TermToSend,
+ Got2 = ei_receive(P, Fd),
+
+ io:format("Sent ~p~nExp. ~p~nGot1 ~p~nGot2 ~p~n", [TermToSend, TermToGet, Got1, Got2]),
+ TermToGet = Got1,
+ TermToGet = Got2,
+
runner:finish(P),
ok.
@@ -87,6 +92,40 @@ ei_threaded_accept(Config) when is_list(Config) ->
[receive I -> ok end || I <- lists:seq(0, N-1) ],
ok.
+
+%% Test erlang:monitor toward erl_interface "processes"
+monitor_ei_process(Config) when is_list(Config) ->
+ P = runner:start(Config, ?interpret),
+ 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
+
+ Myname = hd(tl(string:tokens(atom_to_list(node()), "@"))),
+ io:format("Myname ~p ~n", [Myname]),
+ EINode = list_to_atom("c42@"++Myname),
+ io:format("EINode ~p ~n", [EINode]),
+
+ Port = 6543,
+ {ok, ListenFd} = ei_publish(P, Port),
+ MRef1 = erlang:monitor(process, {any, EINode}),
+ {any, EINode} ! hello,
+
+ {ok, Fd, _Node} = ei_accept(P, ListenFd),
+ hello = ei_receive(P, Fd),
+
+ %% Again, now on an established connection.
+ MRef2 = erlang:monitor(process, {any, EINode}),
+ {any, EINode} ! hello,
+ hello = ei_receive(P, Fd),
+
+ ok = receive M -> M after 0 -> ok end,
+
+ runner:finish(P),
+
+ [{'DOWN', MRef1, process, {any, EINode}, noconnection},
+ {'DOWN', MRef2, process, {any, EINode}, noconnection}
+ ] = lists:sort(flush(2, 1000)),
+
+ ok.
+
waitfornode(String,0) ->
io:format("~s never published itself.~n",[String]),
false;
@@ -137,8 +176,15 @@ ei_connect_init(P, Num, Cookie, Creation) ->
{term,Int} when is_integer(Int) -> Int
end.
-ei_accept(P, PortNo) ->
- send_command(P, ei_accept, [PortNo]),
+ei_publish(P, PortNo) ->
+ send_command(P, ei_publish, [PortNo]),
+ case get_term(P) of
+ {term,{ListenFd, EpmdFd, _}} when ListenFd >= 0, EpmdFd >= 0 -> {ok, ListenFd};
+ {term,{_, _, Errno}} -> {error,Errno}
+ end.
+
+ei_accept(P, ListenFd) ->
+ send_command(P, ei_accept, [ListenFd]),
case get_term(P) of
{term,{Fd, _, Node}} when Fd >= 0 -> {ok, Fd, Node};
{term,{_Fd, Errno, _Node}} -> {error,Errno}
@@ -151,3 +197,12 @@ ei_receive(P, Fd) ->
send_command(P, Name, Args) ->
runner:send_term(P, {Name,list_to_tuple(Args)}).
+
+flush(0, Timeout) ->
+ flush(1, Timeout div 10);
+flush(Expected, Timeout) ->
+ receive M ->
+ [M | flush(Expected-1, Timeout)]
+ after Timeout ->
+ []
+ end.
diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c b/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c
index 7b81ee5491..50df848b69 100644
--- a/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c
+++ b/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,6 +43,7 @@
#include "ei_runner.h"
static void cmd_ei_connect_init(char* buf, int len);
+static void cmd_ei_publish(char* buf, int len);
static void cmd_ei_accept(char* buf, int len);
static void cmd_ei_receive(char* buf, int len);
static void cmd_ei_unpublish(char* buf, int len);
@@ -58,6 +59,7 @@ static struct {
void (*func)(char* buf, int len);
} commands[] = {
"ei_connect_init", 3, cmd_ei_connect_init,
+ "ei_publish", 1, cmd_ei_publish,
"ei_accept", 1, cmd_ei_accept,
"ei_receive", 1, cmd_ei_receive,
"ei_unpublish", 0, cmd_ei_unpublish
@@ -73,11 +75,7 @@ TESTCASE(interpret)
ei_term term;
ei_x_new(&x);
- for (;;) {
- if (get_bin_term(&x, &term)) {
- report(1);
- return;
- } else {
+ while (get_bin_term(&x, &term) == 0) {
char* buf = x.buff, func[MAXATOMLEN];
int index = x.index, arity;
if (term.ei_type != ERL_SMALL_TUPLE_EXT || term.arity != 2)
@@ -98,8 +96,9 @@ TESTCASE(interpret)
message("\"%d\" \n", func);
fail("bad command");
}
- }
- }
+ }
+ report(1);
+ ei_x_free(&x);
}
static void cmd_ei_connect_init(char* buf, int len)
@@ -149,11 +148,10 @@ static int my_listen(int port)
return listen_fd;
}
-static void cmd_ei_accept(char* buf, int len)
+static void cmd_ei_publish(char* buf, int len)
{
int index = 0;
int listen, r;
- ErlConnect conn;
long port;
ei_x_buff x;
int i;
@@ -170,6 +168,29 @@ static void cmd_ei_accept(char* buf, int len)
#ifdef VXWORKS
save_fd(i);
#endif
+ /* send listen-fd, result and errno */
+ ei_x_new_with_version(&x);
+ ei_x_encode_tuple_header(&x, 3);
+ ei_x_encode_long(&x, listen);
+ ei_x_encode_long(&x, i);
+ ei_x_encode_long(&x, erl_errno);
+ send_bin_term(&x);
+ ei_x_free(&x);
+}
+
+static void cmd_ei_accept(char* buf, int len)
+{
+ int index = 0;
+ int r;
+ ErlConnect conn;
+ long listen;
+ ei_x_buff x;
+ int i;
+
+ /* get port */
+ if (ei_decode_long(buf, &index, &listen) < 0)
+ fail("expected int (listen fd)");
+
r = ei_accept(&ec, listen, &conn);
#ifdef VXWORKS
save_fd(r);
@@ -200,7 +221,7 @@ static void cmd_ei_receive(char* buf, int len)
if (got == ERL_TICK)
continue;
if (got == ERL_ERROR)
- fail("ei_xreceive_msg");
+ fail1("ei_xreceive_msg, got==%d", got);
break;
}
index = 1;
diff --git a/lib/erl_interface/test/ei_connect_SUITE.erl b/lib/erl_interface/test/ei_connect_SUITE.erl
index 66498deadc..75b6bf18da 100644
--- a/lib/erl_interface/test/ei_connect_SUITE.erl
+++ b/lib/erl_interface/test/ei_connect_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("ei_connect_SUITE_data/ei_connect_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
ei_send/1,
ei_reg_send/1,
ei_format_pid/1,
@@ -44,8 +45,11 @@ all() ->
[ei_send, ei_reg_send, ei_rpc, ei_format_pid, ei_send_funs,
ei_threaded_send, ei_set_get_tracelevel].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
ei_send(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = ei_connect(P, node()),
@@ -58,7 +62,7 @@ ei_send(Config) when is_list(Config) ->
ei_format_pid(Config) when is_list(Config) ->
S = self(),
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = ei_connect(P, node()),
@@ -70,7 +74,7 @@ ei_format_pid(Config) when is_list(Config) ->
ok.
ei_send_funs(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = ei_connect(P, node()),
@@ -88,7 +92,7 @@ ei_send_funs(Config) when is_list(Config) ->
ok.
ei_reg_send(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = ei_connect(P, node()),
@@ -137,7 +141,7 @@ start_einode(Einode, N, Host) ->
ok.
ei_rpc(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = ei_connect(P, node()),
@@ -150,7 +154,7 @@ ei_rpc(Config) when is_list(Config) ->
ok.
ei_set_get_tracelevel(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
5 = ei_set_get_tracelevel(P, 5),
0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = ei_connect(P, node()),
diff --git a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
index 6a3796dd24..29c03d7604 100644
--- a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
+++ b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -74,11 +74,7 @@ TESTCASE(interpret)
ei_term term;
ei_x_new(&x);
- for (;;) {
- if (get_bin_term(&x, &term)) {
- report(1);
- return;
- } else {
+ while (get_bin_term(&x, &term) == 0) {
char* buf = x.buff, func[MAXATOMLEN];
int index = x.index, arity;
if (term.ei_type != ERL_SMALL_TUPLE_EXT || term.arity != 2)
@@ -99,8 +95,10 @@ TESTCASE(interpret)
message("\"%d\" \n", func);
fail("bad command");
}
- }
- }
+ }
+ report(1);
+ ei_x_free(&x);
+ return;
}
diff --git a/lib/erl_interface/test/ei_decode_SUITE.erl b/lib/erl_interface/test/ei_decode_SUITE.erl
index 74fb9b8916..75560ea7c9 100644
--- a/lib/erl_interface/test/ei_decode_SUITE.erl
+++ b/lib/erl_interface/test/ei_decode_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("ei_decode_SUITE_data/ei_decode_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
test_ei_decode_long/1,
test_ei_decode_ulong/1,
test_ei_decode_longlong/1,
@@ -42,6 +43,9 @@ all() ->
test_ei_decode_char, test_ei_decode_nonoptimal,
test_ei_decode_misc, test_ei_decode_utf8_atom].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%% ---------------------------------------------------------------------------
% NOTE: for historical reasons we don't pach as tight as we can,
@@ -51,7 +55,7 @@ all() ->
%% ######################################################################## %%
test_ei_decode_long(Config) when is_list(Config) ->
- P = runner:start(?test_ei_decode_long),
+ P = runner:start(Config, ?test_ei_decode_long),
send_integers(P),
runner:recv_eot(P),
ok.
@@ -60,7 +64,7 @@ test_ei_decode_long(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_decode_ulong(Config) when is_list(Config) ->
- P = runner:start(?test_ei_decode_ulong),
+ P = runner:start(Config, ?test_ei_decode_ulong),
send_integers(P),
runner:recv_eot(P),
ok.
@@ -77,7 +81,7 @@ test_ei_decode_longlong(Config) when is_list(Config) ->
vxworks ->
{skip,"Skipped on VxWorks"};
_ ->
- P = runner:start(?test_ei_decode_longlong),
+ P = runner:start(Config, ?test_ei_decode_longlong),
send_integers2(P),
runner:recv_eot(P),
ok
@@ -91,7 +95,7 @@ test_ei_decode_ulonglong(Config) when is_list(Config) ->
vxworks ->
{skip,"Skipped on VxWorks"};
_ ->
- P = runner:start(?test_ei_decode_ulonglong),
+ P = runner:start(Config, ?test_ei_decode_ulonglong),
send_integers2(P),
runner:recv_eot(P),
ok
@@ -104,7 +108,7 @@ test_ei_decode_ulonglong(Config) when is_list(Config) ->
%% FIXME maybe the API should change to use "unsigned char" to be clear?!
test_ei_decode_char(Config) when is_list(Config) ->
- P = runner:start(?test_ei_decode_char),
+ P = runner:start(Config, ?test_ei_decode_char),
send_term_as_binary(P,0),
send_term_as_binary(P,16#7f),
@@ -119,7 +123,7 @@ test_ei_decode_char(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_decode_nonoptimal(Config) when is_list(Config) ->
- P = runner:start(?test_ei_decode_nonoptimal),
+ P = runner:start(Config, ?test_ei_decode_nonoptimal),
send_non_optimal_pos(P), % decode_char
send_non_optimal(P), % decode_long
@@ -168,7 +172,7 @@ send_non_optimal_neg(P) ->
%% ######################################################################## %%
test_ei_decode_misc(Config) when is_list(Config) ->
- P = runner:start(?test_ei_decode_misc),
+ P = runner:start(Config, ?test_ei_decode_misc),
send_term_as_binary(P,0.0),
send_term_as_binary(P,-1.0),
@@ -199,7 +203,7 @@ test_ei_decode_misc(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_decode_utf8_atom(Config) ->
- P = runner:start(?test_ei_decode_utf8_atom),
+ P = runner:start(Config, ?test_ei_decode_utf8_atom),
send_latin1_atom_as_binary(P,"å"),
send_latin1_atom_as_binary(P,"ä"),
diff --git a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
index b7a2c4bb8b..f945a7d378 100644
--- a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
+++ b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2017. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -105,6 +105,7 @@ int ei_decode_my_string(const char *buf, int *index, char *to,
fail1("size of encoded data (%d) is incorrect", size1); \
return; \
} \
+ free_packet(buf); \
} \
#define EI_DECODE_2_FAIL(FUNC,SIZE,TYPE,VAL) \
@@ -148,6 +149,7 @@ int ei_decode_my_string(const char *buf, int *index, char *to,
fail("size of encoded data should be 0"); \
return; \
} \
+ free_packet(buf); \
} \
#define dump(arr, num) { \
@@ -205,6 +207,7 @@ int ei_decode_my_string(const char *buf, int *index, char *to,
fail("size of encoded data is incorrect"); \
return; \
} \
+ free_packet(buf); \
} \
#define EI_DECODE_STRING(FUNC,SIZE,VAL) \
@@ -248,6 +251,7 @@ int ei_decode_my_string(const char *buf, int *index, char *to,
fail("size of encoded data should be 0"); \
return; \
} \
+ free_packet(buf); \
} \
//#define EI_DECODE_UTF8_STRING(FUNC,SIZE,VAL)
@@ -310,6 +314,7 @@ int ei_decode_my_string(const char *buf, int *index, char *to,
fail("size of encoded data is incorrect"); \
return; \
} \
+ free_packet(buf); \
} \
/* ******************************************************************** */
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE.erl b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
index 160720b413..0f23cdfbb9 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE.erl
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("ei_decode_encode_SUITE_data/ei_decode_encode_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
test_ei_decode_encode/1]).
suite() ->
@@ -33,6 +34,9 @@ suite() ->
all() ->
[test_ei_decode_encode].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%% ---------------------------------------------------------------------------
% NOTE: these types have no meaning on the C side so we pass them
@@ -42,7 +46,7 @@ all() ->
%% ######################################################################## %%
test_ei_decode_encode(Config) when is_list(Config) ->
- P = runner:start(?test_ei_decode_encode),
+ P = runner:start(Config, ?test_ei_decode_encode),
Fun = fun (X) -> {X,true} end,
Pid = self(),
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
index 467f789fdb..9977683d59 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -466,6 +466,7 @@ void decode_encode_big(struct Type* t)
send_buffer(arg.buff, arg.index);
ei_x_free(&arg);
ei_free_big(p);
+ free_packet(buf);
}
diff --git a/lib/erl_interface/test/ei_encode_SUITE.erl b/lib/erl_interface/test/ei_encode_SUITE.erl
index 8857b092f3..0267a5126f 100644
--- a/lib/erl_interface/test/ei_encode_SUITE.erl
+++ b/lib/erl_interface/test/ei_encode_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("ei_encode_SUITE_data/ei_encode_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
test_ei_encode_long/1,
test_ei_encode_ulong/1,
test_ei_encode_longlong/1,
@@ -45,6 +46,9 @@ all() ->
test_ei_encode_fails, test_ei_encode_utf8_atom,
test_ei_encode_utf8_atom_len].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%% ---------------------------------------------------------------------------
@@ -55,7 +59,7 @@ all() ->
%% ######################################################################## %%
test_ei_encode_long(Config) when is_list(Config) ->
- P = runner:start(?test_ei_encode_long),
+ P = runner:start(Config, ?test_ei_encode_long),
{<<97,0>> ,0} = get_buf_and_term(P),
{<<97,255>> ,255} = get_buf_and_term(P),
@@ -77,7 +81,7 @@ test_ei_encode_long(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_encode_ulong(Config) when is_list(Config) ->
- P = runner:start(?test_ei_encode_ulong),
+ P = runner:start(Config, ?test_ei_encode_ulong),
{<<97,0>> ,0} = get_buf_and_term(P),
{<<97,255>> ,255} = get_buf_and_term(P),
@@ -101,7 +105,7 @@ test_ei_encode_longlong(Config) when is_list(Config) ->
vxworks ->
{skip,"Skipped on VxWorks"};
_ ->
- P = runner:start(?test_ei_encode_longlong),
+ P = runner:start(Config, ?test_ei_encode_longlong),
{<<97,0>> ,0} = get_buf_and_term(P),
{<<97,255>> ,255} = get_buf_and_term(P),
@@ -132,7 +136,7 @@ test_ei_encode_ulonglong(Config) when is_list(Config) ->
vxworks ->
{skip,"Skipped on VxWorks"};
_ ->
- P = runner:start(?test_ei_encode_ulonglong),
+ P = runner:start(Config, ?test_ei_encode_ulonglong),
{<<97,0>> ,0} = get_buf_and_term(P),
{<<97,255>> ,255} = get_buf_and_term(P),
@@ -158,7 +162,7 @@ test_ei_encode_ulonglong(Config) when is_list(Config) ->
%% FIXME maybe the API should change to use "unsigned char" to be clear?!
test_ei_encode_char(Config) when is_list(Config) ->
- P = runner:start(?test_ei_encode_char),
+ P = runner:start(Config, ?test_ei_encode_char),
{<<97, 0>>,0} = get_buf_and_term(P),
{<<97,127>>,16#7f} = get_buf_and_term(P),
@@ -171,7 +175,7 @@ test_ei_encode_char(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_encode_misc(Config) when is_list(Config) ->
- P = runner:start(?test_ei_encode_misc),
+ P = runner:start(Config, ?test_ei_encode_misc),
<<131>> = get_binaries(P),
@@ -217,7 +221,7 @@ test_ei_encode_misc(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_encode_fails(Config) when is_list(Config) ->
- P = runner:start(?test_ei_encode_fails),
+ P = runner:start(Config, ?test_ei_encode_fails),
XAtom = list_to_atom(lists:duplicate(255, $x)),
YAtom = list_to_atom(lists:duplicate(255, $y)),
@@ -236,7 +240,7 @@ test_ei_encode_fails(Config) when is_list(Config) ->
%% ######################################################################## %%
test_ei_encode_utf8_atom(Config) ->
- P = runner:start(?test_ei_encode_utf8_atom),
+ P = runner:start(Config, ?test_ei_encode_utf8_atom),
{<<119,2,195,133>>,'Å'} = get_buf_and_term(P),
{<<119,2,195,133>>,'Å'} = get_buf_and_term(P),
@@ -251,7 +255,7 @@ test_ei_encode_utf8_atom(Config) ->
%% ######################################################################## %%
test_ei_encode_utf8_atom_len(Config) ->
- P = runner:start(?test_ei_encode_utf8_atom_len),
+ P = runner:start(Config, ?test_ei_encode_utf8_atom_len),
{<<119,2,195,133>>,'Å'} = get_buf_and_term(P),
{<<119,4,195,133,195,132>>,'ÅÄ'} = get_buf_and_term(P),
diff --git a/lib/erl_interface/test/ei_format_SUITE.erl b/lib/erl_interface/test/ei_format_SUITE.erl
index 07ee479b1f..e074c184c1 100644
--- a/lib/erl_interface/test/ei_format_SUITE.erl
+++ b/lib/erl_interface/test/ei_format_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
-export([format_wo_ver/1,
all/0, suite/0,
+ init_per_testcase/2,
atoms/1,
tuples/1,
lists/1]).
@@ -41,10 +42,13 @@ suite() ->
all() ->
[format_wo_ver, atoms, tuples, lists].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%% Tests formatting various atoms.
atoms(Config) when is_list(Config) ->
- P = runner:start(?atoms),
+ P = runner:start(Config, ?atoms),
{term, ''} = get_term(P),
{term, 'a'} = get_term(P),
@@ -84,7 +88,7 @@ atoms(Config) when is_list(Config) ->
%% Tests formatting various tuples
tuples(Config) when is_list(Config) ->
- P = runner:start(?tuples),
+ P = runner:start(Config, ?tuples),
{term, {}} = get_term(P),
{term, {a}} = get_term(P),
@@ -105,7 +109,7 @@ tuples(Config) when is_list(Config) ->
%% Tests formatting various lists
lists(Config) when is_list(Config) ->
- P = runner:start(?lists),
+ P = runner:start(Config, ?lists),
{term, []} = get_term(P),
{term, [a]} = get_term(P),
@@ -146,7 +150,7 @@ lists(Config) when is_list(Config) ->
format_wo_ver(Config) when is_list(Config) ->
- P = runner:start(?format_wo_ver),
+ P = runner:start(Config, ?format_wo_ver),
{term, [-1, 2, $c, {a, "b"}, {c, 10}]} = get_term(P),
diff --git a/lib/erl_interface/test/ei_print_SUITE.erl b/lib/erl_interface/test/ei_print_SUITE.erl
index 6d5c341eae..c75ce55a7d 100644
--- a/lib/erl_interface/test/ei_print_SUITE.erl
+++ b/lib/erl_interface/test/ei_print_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("ei_print_SUITE_data/ei_print_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
atoms/1, tuples/1, lists/1, strings/1]).
-import(runner, [get_term/1]).
@@ -38,10 +39,13 @@ suite() ->
all() ->
[atoms, tuples, lists, strings].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%% Tests formatting various atoms.
atoms(Config) when is_list(Config) ->
- P = runner:start(?atoms),
+ P = runner:start(Config, ?atoms),
{term, "''"} = get_term(P),
{term, "a"} = get_term(P),
@@ -79,7 +83,7 @@ atoms(Config) when is_list(Config) ->
%% Tests formatting various tuples
tuples(Config) when is_list(Config) ->
- P = runner:start(?tuples),
+ P = runner:start(Config, ?tuples),
{term, "{}"} = get_term(P),
{term, "{a}"} = get_term(P),
@@ -100,7 +104,7 @@ tuples(Config) when is_list(Config) ->
%% Tests formatting various lists
lists(Config) when is_list(Config) ->
- P = runner:start(?lists),
+ P = runner:start(Config, ?lists),
{term, "[]"} = get_term(P),
{term, "[a]"} = get_term(P),
@@ -125,7 +129,7 @@ lists(Config) when is_list(Config) ->
ok.
strings(Config) when is_list(Config) ->
- P = runner:start(?strings),
+ P = runner:start(Config, ?strings),
{term, "\"\\n\""} = get_term(P),
{term, "\"\\r\\n\""} = get_term(P),
diff --git a/lib/erl_interface/test/ei_tmo_SUITE.erl b/lib/erl_interface/test/ei_tmo_SUITE.erl
index 003fe20594..5b9de80128 100644
--- a/lib/erl_interface/test/ei_tmo_SUITE.erl
+++ b/lib/erl_interface/test/ei_tmo_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -39,14 +39,16 @@ all() ->
[framework_check, ei_accept_tmo, ei_connect_tmo,
ei_send_tmo, ei_recv_tmo].
-init_per_testcase(_Case, Config) ->
+init_per_testcase(Case, Config) ->
+ Config1 = runner:init_per_testcase(?MODULE, Case, Config),
+
% test if platform is vxworks_simso
{_,Host} = split(node()),
Bool = case atom_to_list(Host) of
[$v,$x,$s,$i,$m | _] -> true;
_ -> false
end,
- [{vxsim,Bool}|Config].
+ [{vxsim,Bool} | Config1].
end_per_testcase(_Case, _Config) ->
ok.
@@ -55,7 +57,7 @@ end_per_testcase(_Case, _Config) ->
framework_check(Config) when is_list(Config) ->
%%dbg:tracer(),
%%dbg:p(self()),
- P = runner:start(?framework_check),
+ P = runner:start(Config, ?framework_check),
runner:send_term(P,{hello,world}),
{term, {hello,world}} = runner:get_term(P),
runner:recv_eot(P),
@@ -71,7 +73,7 @@ ei_recv_tmo(Config) when is_list(Config) ->
do_one_recv(Config,CNode) ->
{_,Host} = split(node()),
- P1 = runner:start(?recv_tmo),
+ P1 = runner:start(Config, ?recv_tmo),
runner:send_term(P1,{CNode,
erlang:get_cookie(),
node()}),
@@ -84,7 +86,7 @@ do_one_recv(Config,CNode) ->
runner:recv_eot(P1).
do_one_recv_failure(Config,CNode) ->
- P1 = runner:start(?recv_tmo),
+ P1 = runner:start(Config, ?recv_tmo),
runner:send_term(P1,{CNode,
erlang:get_cookie(),
node()}),
@@ -110,7 +112,7 @@ ei_send_tmo(Config) when is_list(Config) ->
do_one_send(Config,From,CNode) ->
{_,Host} = split(node()),
- P1 = runner:start(?send_tmo),
+ P1 = runner:start(Config, ?send_tmo),
runner:send_term(P1,{CNode,
erlang:get_cookie(),
node()}),
@@ -139,7 +141,7 @@ do_one_send_failure(Config,From,FakeName,CName,VxSim) ->
exit(Else)
end,
EpmdSocket = register(OurName, LSocket, 1, 5),
- P3 = runner:start(?send_tmo),
+ P3 = runner:start(Config, ?send_tmo),
Cookie = kaksmula_som_ingen_bryr_sig_om,
runner:send_term(P3,{CName,
Cookie,
@@ -202,7 +204,7 @@ ei_connect_tmo(Config) when is_list(Config) ->
%dbg:p(self()),
VxSim = proplists:get_value(vxsim, Config),
DummyNode = make_and_check_dummy(),
- P = runner:start(?connect_tmo),
+ P = runner:start(Config, ?connect_tmo),
runner:send_term(P,{c_nod_connect_tmo_1,
kaksmula_som_ingen_bryr_sig_om,
DummyNode}),
@@ -219,7 +221,7 @@ ei_connect_tmo(Config) when is_list(Config) ->
end
end,
runner:recv_eot(P),
- P2 = runner:start(?connect_tmo),
+ P2 = runner:start(Config, ?connect_tmo),
runner:send_term(P2,{c_nod_connect_tmo_2,
erlang:get_cookie(),
node()}),
@@ -237,7 +239,7 @@ ei_connect_tmo(Config) when is_list(Config) ->
exit(Else)
end,
EpmdSocket = register(OurName, LSocket, 1, 5),
- P3 = runner:start(?connect_tmo),
+ P3 = runner:start(Config, ?connect_tmo),
Cookie = kaksmula_som_ingen_bryr_sig_om,
runner:send_term(P3,{c_nod_connect_tmo_3,
Cookie,
@@ -266,12 +268,12 @@ ei_connect_tmo(Config) when is_list(Config) ->
ei_accept_tmo(Config) when is_list(Config) ->
%%dbg:tracer(),
%%dbg:p(self()),
- P = runner:start(?accept_tmo),
+ P = runner:start(Config, ?accept_tmo),
runner:send_term(P,{c_nod_som_ingen_kontaktar_1,
kaksmula_som_ingen_bryr_sig_om}),
{term,{-1,ETimedout,ETimedout}} = runner:get_term(P, 10000),
runner:recv_eot(P),
- P2 = runner:start(?accept_tmo),
+ P2 = runner:start(Config, ?accept_tmo),
runner:send_term(P2,{c_nod_som_vi_kontaktar_1,
erlang:get_cookie()}),
receive after 1000 -> ok end,
@@ -280,7 +282,7 @@ ei_accept_tmo(Config) when is_list(Config) ->
{term, X} = runner:get_term(P2, 10000),
runner:recv_eot(P2),
true = is_integer(X),
- P3 = runner:start(?accept_tmo),
+ P3 = runner:start(Config, ?accept_tmo),
runner:send_term(P3,{c_nod_som_vi_kontaktar_2,
erlang:get_cookie()}),
receive after 1000 -> ok end,
diff --git a/lib/erl_interface/test/ei_tmo_SUITE_data/ei_tmo_test.c b/lib/erl_interface/test/ei_tmo_SUITE_data/ei_tmo_test.c
index 0079ef8c86..39846e4a58 100644
--- a/lib/erl_interface/test/ei_tmo_SUITE_data/ei_tmo_test.c
+++ b/lib/erl_interface/test/ei_tmo_SUITE_data/ei_tmo_test.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2003-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2003-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
*/
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#ifdef VXWORKS
#include "reclaim.h"
diff --git a/lib/erl_interface/test/erl_connect_SUITE.erl b/lib/erl_interface/test/erl_connect_SUITE.erl
index cd73f07b8f..782691b8fb 100644
--- a/lib/erl_interface/test/erl_connect_SUITE.erl
+++ b/lib/erl_interface/test/erl_connect_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("erl_connect_SUITE_data/erl_connect_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
erl_send/1, erl_reg_send/1,
erl_send_cookie_file/1]).
@@ -38,8 +39,11 @@ all() ->
[erl_send, erl_reg_send, erl_send_cookie_file].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
erl_send(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
1 = erl_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = erl_connect(P, node()),
@@ -56,7 +60,7 @@ erl_send_cookie_file(Config) when is_list(Config) ->
vxworks ->
{skip,"Skipped on VxWorks"};
_ ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
1 = erl_connect_init(P, 42, '', 0),
{ok,Fd} = erl_connect(P, node()),
@@ -70,7 +74,7 @@ erl_send_cookie_file(Config) when is_list(Config) ->
end.
erl_reg_send(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
1 = erl_connect_init(P, 42, erlang:get_cookie(), 0),
{ok,Fd} = erl_connect(P, node()),
diff --git a/lib/erl_interface/test/erl_eterm_SUITE.erl b/lib/erl_interface/test/erl_eterm_SUITE.erl
index 3d1e33081b..77910a9fc7 100644
--- a/lib/erl_interface/test/erl_eterm_SUITE.erl
+++ b/lib/erl_interface/test/erl_eterm_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-export([all/0, suite/0,
+ init_per_testcase/2,
build_terms/1, round_trip_conversion/1,
decode_terms/1, decode_float/1,
t_erl_mk_int/1, t_erl_mk_list/1,
@@ -94,6 +95,9 @@ all() ->
high_chaparal, broken_data, cnode_1].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
%%% 1. B a s i c t e s t s
@@ -104,7 +108,7 @@ all() ->
%% a list and verifies that the result is as expected.
build_terms(Config) when is_list(Config) ->
- P = runner:start(?build_terms),
+ P = runner:start(Config, ?build_terms),
{term, Term} = get_term(P),
io:format("Received: ~p", [Term]),
[ARefLN, ARef, APortLN, APort, APidLN, APid,
@@ -136,7 +140,7 @@ build_terms(Config) when is_list(Config) ->
%% This test is run entirely in C code.
round_trip_conversion(Config) when is_list(Config) ->
- runner:test(?round_trip_conversion),
+ runner:test(Config, ?round_trip_conversion),
ok.
%% This test sends a list of all data types to the C code function,
@@ -156,7 +160,7 @@ decode_terms(Config) when is_list(Config) ->
{element1, 42, 767}, "A string",
1, -1, 0, 3.0, ABinary, 'I am an atom'],
- P = runner:start(?decode_terms),
+ P = runner:start(Config, ?decode_terms),
runner:send_term(P, Terms),
runner:recv_eot(P),
@@ -165,7 +169,7 @@ decode_terms(Config) when is_list(Config) ->
%% Decodes the floating point number 3.1415.
decode_float(Config) when is_list(Config) ->
- P = runner:start(?decode_float),
+ P = runner:start(Config, ?decode_float),
runner:send_term(P, 3.1415),
runner:recv_eot(P),
ok.
@@ -173,7 +177,7 @@ decode_float(Config) when is_list(Config) ->
%% Tests the erl_free_compound() function.
t_erl_free_compound(Config) when is_list(Config) ->
- runner:test(?t_erl_free_compound),
+ runner:test(Config, ?t_erl_free_compound),
ok.
@@ -186,7 +190,7 @@ t_erl_free_compound(Config) when is_list(Config) ->
%% This tests the erl_mk_list() function.
t_erl_mk_list(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_list),
+ P = runner:start(Config, ?t_erl_mk_list),
{term, []} = get_term(P),
{term, [abc]} = get_term(P),
@@ -200,7 +204,7 @@ t_erl_mk_list(Config) when is_list(Config) ->
%% This tests the erl_mk_int() function.
t_erl_mk_int(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_int),
+ P = runner:start(Config, ?t_erl_mk_int),
{term, 0} = get_term(P),
{term, 127} = get_term(P),
@@ -255,14 +259,14 @@ t_erl_mk_int(Config) when is_list(Config) ->
%% Basic test of erl_copy_term().
basic_copy(Config) when is_list(Config) ->
- runner:test(?basic_copy),
+ runner:test(Config, ?basic_copy),
ok.
%% This tests the erl_mk_tuple() function.
t_erl_mk_tuple(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_tuple),
+ P = runner:start(Config, ?t_erl_mk_tuple),
{term, {madonna, 21, 'mad donna', 12}} = get_term(P),
{term, {'Madonna',21,{children,{"Isabella",2}},
@@ -275,7 +279,7 @@ t_erl_mk_tuple(Config) when is_list(Config) ->
%% This tests the erl_mk_atom() function.
t_erl_mk_atom(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_atom),
+ P = runner:start(Config, ?t_erl_mk_atom),
{term, madonna} = (get_term(P)),
{term, 'Madonna'} = (get_term(P)),
@@ -295,7 +299,7 @@ t_erl_mk_atom(Config) when is_list(Config) ->
%% This tests the erl_mk_binary() function.
t_erl_mk_binary(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_binary),
+ P = runner:start(Config, ?t_erl_mk_binary),
{term, Bin} = (get_term(P)),
"{madonna,21,'mad donna',1234.567.890, !#$%&/()=?+-@, \" \\}" = binary_to_list(Bin),
@@ -307,7 +311,7 @@ t_erl_mk_binary(Config) when is_list(Config) ->
%% This tests the erl_mk_empty_list() function.
t_erl_mk_empty_list(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_empty_list),
+ P = runner:start(Config, ?t_erl_mk_empty_list),
{term, []} = get_term(P),
@@ -322,7 +326,7 @@ t_erl_mk_float(Config) when is_list(Config) ->
vxworks ->
{skipped, "Floating point numbers never compare equal on PPC"};
_ ->
- P = runner:start(?t_erl_mk_float),
+ P = runner:start(Config, ?t_erl_mk_float),
{term, {3.1415, 1.999999, 2.000000, 2.000001,
2.000002, 12345.67890}} = get_term(P),
runner:recv_eot(P),
@@ -333,7 +337,7 @@ t_erl_mk_float(Config) when is_list(Config) ->
%% This tests the erl_mk_pid() function.
t_erl_mk_pid(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_pid),
+ P = runner:start(Config, ?t_erl_mk_pid),
{term, A_pid} = (get_term(P)),
{pid, kalle@localhost, 3, 2} = nc2vinfo(A_pid),
@@ -342,7 +346,7 @@ t_erl_mk_pid(Config) when is_list(Config) ->
ok.
t_erl_mk_xpid(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_xpid),
+ P = runner:start(Config, ?t_erl_mk_xpid),
{term, A_pid} = (get_term(P)),
{pid, kalle@localhost, 32767, 8191} = nc2vinfo(A_pid),
@@ -354,7 +358,7 @@ t_erl_mk_xpid(Config) when is_list(Config) ->
%% This tests the erl_mk_port() function.
t_erl_mk_port(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_port),
+ P = runner:start(Config, ?t_erl_mk_port),
{term, A_port} = (get_term(P)),
{port, kalle@localhost, 4} = nc2vinfo(A_port),
@@ -363,7 +367,7 @@ t_erl_mk_port(Config) when is_list(Config) ->
ok.
t_erl_mk_xport(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_xport),
+ P = runner:start(Config, ?t_erl_mk_xport),
{term, A_port} = (get_term(P)),
{port, kalle@localhost, 268435455} = nc2vinfo(A_port),
@@ -375,7 +379,7 @@ t_erl_mk_xport(Config) when is_list(Config) ->
%% This tests the erl_mk_ref() function.
t_erl_mk_ref(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_ref),
+ P = runner:start(Config, ?t_erl_mk_ref),
{term, A_ref} = (get_term(P)),
{ref, kalle@localhost, _Length, [6]} = nc2vinfo(A_ref),
@@ -384,7 +388,7 @@ t_erl_mk_ref(Config) when is_list(Config) ->
ok.
t_erl_mk_long_ref(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_long_ref),
+ P = runner:start(Config, ?t_erl_mk_long_ref),
{term, A_ref} = (get_term(P)),
{ref, kalle@localhost, _Length, [4294967295,4294967295,262143]}
@@ -397,7 +401,7 @@ t_erl_mk_long_ref(Config) when is_list(Config) ->
%% This tests the erl_mk_string() function.
t_erl_mk_string(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_string),
+ P = runner:start(Config, ?t_erl_mk_string),
{term, "madonna"} = (get_term(P)),
{term, "Madonna"} = (get_term(P)),
@@ -417,7 +421,7 @@ t_erl_mk_string(Config) when is_list(Config) ->
%% This tests the erl_mk_estring() function.
t_erl_mk_estring(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_estring),
+ P = runner:start(Config, ?t_erl_mk_estring),
{term, "madonna"} = (get_term(P)),
{term, "Madonna"} = (get_term(P)),
@@ -437,7 +441,7 @@ t_erl_mk_estring(Config) when is_list(Config) ->
%% This tests the erl_mk_uint() function.
t_erl_mk_uint(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_uint),
+ P = runner:start(Config, ?t_erl_mk_uint),
{term, 54321} = (get_term(P)),
{term, 2147483647} = (get_term(P)),
@@ -453,7 +457,7 @@ t_erl_mk_uint(Config) when is_list(Config) ->
%% This tests the erl_mk_var() function.
t_erl_mk_var(Config) when is_list(Config) ->
- P = runner:start(?t_erl_mk_var),
+ P = runner:start(Config, ?t_erl_mk_var),
{term, 1} = (get_term(P)),
{term, 0} = (get_term(P)),
@@ -470,7 +474,7 @@ t_erl_mk_var(Config) when is_list(Config) ->
%% This tests the erl_cons() function.
t_erl_cons(Config) when is_list(Config) ->
- P = runner:start(?t_erl_cons),
+ P = runner:start(Config, ?t_erl_cons),
{term, [madonna, 21]} = get_term(P),
@@ -490,7 +494,7 @@ t_erl_cons(Config) when is_list(Config) ->
%% Tests the erl_length() function.
t_erl_length(Config) when is_list(Config) ->
- P = runner:start(?t_erl_length),
+ P = runner:start(Config, ?t_erl_length),
0 = erl_length(P, []),
1 = erl_length(P, [a]),
@@ -513,7 +517,7 @@ erl_length(Port, List) ->
%% Tests the erl_hd() function.
t_erl_hd(Config) when is_list(Config) ->
- P = runner:start(?t_erl_hd),
+ P = runner:start(Config, ?t_erl_hd),
'NULL' = erl_hd(P, 42),
'NULL' = erl_hd(P, abc),
@@ -537,7 +541,7 @@ erl_hd(Port, List) ->
%% Tests the erl_tail() function.
t_erl_tl(Config) when is_list(Config) ->
- P = runner:start(?t_erl_tl),
+ P = runner:start(Config, ?t_erl_tl),
'NULL' = erl_tl(P, 42),
'NULL' = erl_tl(P, abc),
@@ -561,20 +565,20 @@ erl_tl(Port, List) ->
%% Tests the type checking macros (done in the C program).
type_checks(Config) when is_list(Config) ->
- runner:test(?type_checks),
+ runner:test(Config, ?type_checks),
ok.
%% Tests the extractor macros (done in the C program).
extractor_macros(Config) when is_list(Config) ->
- runner:test(?extractor_macros),
+ runner:test(Config, ?extractor_macros),
ok.
%% This tests the erl_size() function.
t_erl_size(Config) when is_list(Config) ->
- P = runner:start(?t_erl_size),
+ P = runner:start(Config, ?t_erl_size),
{term, 0} = (get_term(P)),
{term, 4} = (get_term(P)),
@@ -589,7 +593,7 @@ t_erl_size(Config) when is_list(Config) ->
%% This tests the erl_var_content() function.
t_erl_var_content(Config) when is_list(Config) ->
- P = runner:start(?t_erl_var_content),
+ P = runner:start(Config, ?t_erl_var_content),
{term, 17} = (get_term(P)),
{term, "http://www.madonna.com"} = (get_term(P)),
@@ -604,7 +608,7 @@ t_erl_var_content(Config) when is_list(Config) ->
%% This tests the erl_element() function.
t_erl_element(Config) when is_list(Config) ->
- P = runner:start(?t_erl_element),
+ P = runner:start(Config, ?t_erl_element),
{term, madonna} = get_term(P),
{term, 21} = get_term(P),
@@ -630,7 +634,7 @@ t_erl_element(Config) when is_list(Config) ->
%% Tests the erl_iolist_length() function.
t_erl_iolist_length(Config) when is_list(Config) ->
- P = runner:start(?t_erl_iolist_length),
+ P = runner:start(Config, ?t_erl_iolist_length),
%% Flat lists.
@@ -697,7 +701,7 @@ erl_iolist_length(Port, List) ->
%% Tests the erl_iolist_to_binary() function.
t_erl_iolist_to_binary(Config) when is_list(Config) ->
- P = runner:start(?t_erl_iolist_to_binary),
+ P = runner:start(Config, ?t_erl_iolist_to_binary),
%% Flat lists.
@@ -768,7 +772,7 @@ iolist_to_list(Port, Term) ->
%% Tests the erl_iolist_to_string() function.
t_erl_iolist_to_string(Config) when is_list(Config) ->
- P = runner:start(?t_erl_iolist_to_string),
+ P = runner:start(Config, ?t_erl_iolist_to_string),
%% Flat lists.
@@ -947,14 +951,14 @@ collect_line1([C|Rest], Result) ->
%% Test case submitted by Per Lundgren, ERV.
high_chaparal(Config) when is_list(Config) ->
- P = runner:start(?high_chaparal),
+ P = runner:start(Config, ?high_chaparal),
{term, [hello, world]} = get_term(P),
runner:recv_eot(P),
ok.
%% OTP-7448
broken_data(Config) when is_list(Config) ->
- P = runner:start(?broken_data),
+ P = runner:start(Config, ?broken_data),
runner:recv_eot(P),
ok.
diff --git a/lib/erl_interface/test/erl_ext_SUITE.erl b/lib/erl_interface/test/erl_ext_SUITE.erl
index afaba1fd93..ff3b495f7b 100644
--- a/lib/erl_interface/test/erl_ext_SUITE.erl
+++ b/lib/erl_interface/test/erl_ext_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("erl_ext_SUITE_data/ext_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
compare_tuple/1,
compare_list/1,
compare_string/1,
@@ -40,28 +41,30 @@ all() ->
[compare_tuple, compare_list, compare_string,
compare_list_string, compare_nc_ext].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
compare_tuple(Config) when is_list(Config) ->
- P = runner:start(?compare_tuple),
+ P = runner:start(Config, ?compare_tuple),
runner:recv_eot(P),
ok.
compare_list(Config) when is_list(Config) ->
- P = runner:start(?compare_list),
+ P = runner:start(Config, ?compare_list),
runner:recv_eot(P),
ok.
compare_string(Config) when is_list(Config) ->
- P = runner:start(?compare_string),
+ P = runner:start(Config, ?compare_string),
runner:recv_eot(P),
ok.
compare_list_string(Config) when is_list(Config) ->
- P = runner:start(?compare_list_string),
+ P = runner:start(Config, ?compare_list_string),
runner:recv_eot(P),
ok.
compare_nc_ext(Config) when is_list(Config) ->
- P = runner:start(?compare_nc_ext),
+ P = runner:start(Config, ?compare_nc_ext),
runner:recv_eot(P),
ok.
diff --git a/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c b/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c
index 1e986feacf..6b47c3e510 100644
--- a/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c
+++ b/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2017. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -88,6 +88,11 @@ TESTCASE(compare_list) {
// erlang:term_to_binary([0, 1000])
unsigned char term4[] = {131,108,0,0,0,2,97,0,98,0,0,3,232,106};
+ // erlang:term_to_binary([a|b])
+ unsigned char term5a[] = {131,108,0,0,0,1,100,0,1,97,100,0,1,98};
+ // erlang:term_to_binary([a|c])
+ unsigned char term5b[] = {131,108,0,0,0,1,100,0,1,97,100,0,1,99};
+
erl_init(NULL, 0);
start_a = term1;
start_b = term2;
@@ -103,6 +108,13 @@ TESTCASE(compare_list) {
test_compare_ext("lists1", start_a, end_a, start_b, end_b, -1);
+ start_a = term5a;
+ start_b = term5b;
+ end_a = term5a + sizeof(term5a);
+ end_b = term5b + sizeof(term5b);
+
+ test_compare_ext("lists5", start_a, end_a, start_b, end_b, -1);
+
report(1);
}
diff --git a/lib/erl_interface/test/erl_format_SUITE.erl b/lib/erl_interface/test/erl_format_SUITE.erl
index c1a7d8377e..69dfdcc4c8 100644
--- a/lib/erl_interface/test/erl_format_SUITE.erl
+++ b/lib/erl_interface/test/erl_format_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("erl_format_SUITE_data/format_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
atoms/1, tuples/1, lists/1]).
-import(runner, [get_term/1]).
@@ -38,10 +39,13 @@ suite() ->
all() ->
[atoms, tuples, lists].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
+
%% Tests formatting various atoms.
atoms(Config) when is_list(Config) ->
- P = runner:start(?atoms),
+ P = runner:start(Config, ?atoms),
{term, ''} = get_term(P),
{term, 'a'} = get_term(P),
@@ -79,7 +83,7 @@ atoms(Config) when is_list(Config) ->
%% Tests formatting various tuples
tuples(Config) when is_list(Config) ->
- P = runner:start(?tuples),
+ P = runner:start(Config, ?tuples),
{term, {}} = get_term(P),
{term, {a}} = get_term(P),
@@ -100,7 +104,7 @@ tuples(Config) when is_list(Config) ->
%% Tests formatting various lists
lists(Config) when is_list(Config) ->
- P = runner:start(?lists),
+ P = runner:start(Config, ?lists),
{term, []} = get_term(P),
{term, [a]} = get_term(P),
diff --git a/lib/erl_interface/test/erl_global_SUITE.erl b/lib/erl_interface/test/erl_global_SUITE.erl
index ecc6753c7f..6d3a75c8d7 100644
--- a/lib/erl_interface/test/erl_global_SUITE.erl
+++ b/lib/erl_interface/test/erl_global_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("erl_global_SUITE_data/erl_global_test_cases.hrl").
-export([all/0,suite/0,
+ init_per_testcase/2,
erl_global_registration/1,
erl_global_whereis/1, erl_global_names/1]).
@@ -39,9 +40,11 @@ suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap, {seconds, 30}}].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
erl_global_registration(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
{ok, Fd} = erl_connect(P, node(), 42, erlang:get_cookie(), 0),
ok = erl_global_register(P, Fd, ?GLOBAL_NAME),
@@ -53,7 +56,7 @@ erl_global_registration(Config) when is_list(Config) ->
ok.
erl_global_whereis(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
{ok, Fd} = erl_connect(P, node(), 42, erlang:get_cookie(), 0),
Self = self(),
@@ -66,7 +69,7 @@ erl_global_whereis(Config) when is_list(Config) ->
ok.
erl_global_names(Config) when is_list(Config) ->
- P = runner:start(?interpret),
+ P = runner:start(Config, ?interpret),
{ok, Fd} = erl_connect(P, node(), 42, erlang:get_cookie(), 0),
Self = self(),
diff --git a/lib/erl_interface/test/erl_match_SUITE.erl b/lib/erl_interface/test/erl_match_SUITE.erl
index 5566714092..bb62d6288d 100644
--- a/lib/erl_interface/test/erl_match_SUITE.erl
+++ b/lib/erl_interface/test/erl_match_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-include("erl_match_SUITE_data/match_test_cases.hrl").
-export([all/0, suite/0,
+ init_per_testcase/2,
atoms/1, lists/1, tuples/1, references/1, pids/1, ports/1,
bind/1, integers/1, floats/1, binaries/1, strings/1]).
@@ -40,6 +41,8 @@ all() ->
[atoms, lists, tuples, references, pids, ports, bind,
integers, floats, binaries, strings].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
atoms(Config) when is_list(Config) ->
P = start_matcher(Config),
@@ -239,7 +242,7 @@ bind(Config) when is_list(Config) ->
ok.
start_bind(Config) ->
- runner:start(?erl_match_bind).
+ runner:start(Config, ?erl_match_bind).
bind_ok(Port, Bind, Term) ->
true = erl_bind(Port, Bind, Term).
@@ -258,7 +261,7 @@ erl_bind(Port, Pattern, Term) ->
start_matcher(Config) ->
- runner:start(?erl_match_server).
+ runner:start(Config, ?erl_match_server).
eq(Port, Pattern, Term) ->
true = erl_match(Port, Pattern, Term).
diff --git a/lib/erl_interface/test/port_call_SUITE.erl b/lib/erl_interface/test/port_call_SUITE.erl
index fb10bd895f..5c4f5f3cee 100644
--- a/lib/erl_interface/test/port_call_SUITE.erl
+++ b/lib/erl_interface/test/port_call_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,9 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--export([all/0, suite/0, basic/1]).
+-export([all/0, suite/0,
+ init_per_testcase/2,
+ basic/1]).
% Private exports
-include_lib("common_test/include/ct.hrl").
@@ -44,6 +46,8 @@ suite() ->
all() ->
[basic].
+init_per_testcase(Case, Config) ->
+ runner:init_per_testcase(?MODULE, Case, Config).
basic(Config) when is_list(Config) ->
case os:type() of
diff --git a/lib/erl_interface/test/runner.erl b/lib/erl_interface/test/runner.erl
index 1084eec2a3..484890006e 100644
--- a/lib/erl_interface/test/runner.erl
+++ b/lib/erl_interface/test/runner.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,8 +21,9 @@
%%
-module(runner).
--export([test/1, test/2,
- start/1, send_term/2, finish/1, send_eot/1, recv_eot/1,
+-export([test/2, test/3,
+ init_per_testcase/3,
+ start/2, send_term/2, finish/1, send_eot/1, recv_eot/1,
get_term/1, get_term/2]).
-define(default_timeout, 5000).
@@ -32,11 +33,11 @@
%% This function is useful for test cases written in C which requires
%% no further input, and only returns a result by calling report().
-test(Tc) ->
- test(Tc, ?default_timeout).
+test(Config, Tc) ->
+ test(Config, Tc, ?default_timeout).
-test(Tc, Timeout) ->
- Port = start(Tc),
+test(Config, Tc, Timeout) ->
+ Port = start(Config, Tc),
case get_term(Port, Timeout) of
eot ->
@@ -54,12 +55,51 @@ test(Tc, Timeout) ->
%%
%% Returns: {ok, Port}
-start({Prog, Tc}) when is_list(Prog), is_integer(Tc) ->
- Port = open_port({spawn, Prog}, [{packet, 4}, exit_status]),
+start(Config, {Prog, Tc}) when is_list(Prog), is_integer(Tc) ->
+ Port = open_port({spawn, prog_cmd(Config, Prog)},
+ [{packet, 4}, exit_status]),
Command = [Tc div 256, Tc rem 256],
Port ! {self(), {command, Command}},
Port.
+prog_cmd(Config, Prog) ->
+ case proplists:get_value(valgrind_cmd_fun, Config) of
+ undefined ->
+ Prog;
+ Fun when is_function(Fun) ->
+ Fun(Prog)
+ end.
+
+init_per_testcase(Suite, Case, Config) ->
+ case os:getenv("VALGRIND_LOG_DIR") of
+ false ->
+ Config;
+ LogDir ->
+ Valgrind = case os:find_executable("valgrind") of
+ false ->
+ ct:fail("VALGRIND_LOG_DIR set, "
+ "but no valgrind executable found");
+ VG -> VG
+ end,
+
+ LogFileOpt = case os:getenv("VALGRIND_LOG_XML") of
+ false ->
+ " --log-file=";
+ "yes" ->
+ " --xml=yes --xml-file="
+ end,
+ Fun = fun(Prog) ->
+ LogFile = io_lib:format("erl_interface-~w.~w-~s.log.%p",
+ [Suite, Case, filename:basename(Prog)]),
+ Valgrind
+ ++ LogFileOpt ++ filename:join(LogDir,LogFile)
+ ++ " " ++ os:getenv("VALGRIND_MISC_FLAGS","")
+ ++ " " ++ Prog
+ end,
+ [{valgrind_cmd_fun, Fun} | Config]
+ end.
+
+
%% Finishes a test case by send an 'eot' message to the C program
%% and waiting for an 'eot'.
%%
@@ -67,7 +107,12 @@ start({Prog, Tc}) when is_list(Prog), is_integer(Tc) ->
finish(Port) when is_port(Port) ->
send_eot(Port),
- recv_eot(Port).
+ ok = recv_eot(Port),
+ 0 = receive
+ {Port,{exit_status,Status}} ->
+ Status
+ end,
+ ok.
%% Sends an Erlang term to a C program.
diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk
index 01fcee86dd..06ef907d6c 100644
--- a/lib/erl_interface/vsn.mk
+++ b/lib/erl_interface/vsn.mk
@@ -1,2 +1,2 @@
-EI_VSN = 3.10
+EI_VSN = 3.10.4
ERL_INTERFACE_VSN = $(EI_VSN)
diff --git a/lib/et/doc/src/Makefile b/lib/et/doc/src/Makefile
index 0257a8f817..93e2f8eeee 100644
--- a/lib/et/doc/src/Makefile
+++ b/lib/et/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2002-2016. All Rights Reserved.
+# Copyright Ericsson AB 2002-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -45,8 +45,11 @@ include files.mk
XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \
$(XML_PART_FILES) $(XML_CHAPTER_FILES)
+XML_GEN_FILES = $(GEN_XML:%=$(XMLDIR)/%)
+
HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
+ $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html) \
+ $(GEN_XML:%.xml=$(HTMLDIR)/%.html)
INFO_FILE = ../../info
@@ -82,6 +85,7 @@ clean clean_docs:
fi \
done
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/et/doc/src/et_collector.xml b/lib/et/doc/src/et_collector.xml
index 6a85b81ec2..fd90ecfc41 100644
--- a/lib/et/doc/src/et_collector.xml
+++ b/lib/et/doc/src/et_collector.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2002</year><year>2016</year>
+ <year>2002</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -46,7 +46,8 @@
<v>option() = {parent_pid, pid()} | {event_order, event_order()} | {dict_insert, {filter, collector}, collector_fun()} | {dict_insert, {filter, event_filter_name()}, event_filter_fun()} | {dict_insert, {subscriber, pid()}, dict_val()} | {dict_insert, dict_key(), dict_val()} | {dict_delete, dict_key()} | {trace_client, trace_client()} | {trace_global, boolean()} | {trace_pattern, trace_pattern()} | {trace_port, integer()} | {trace_max_queue, integer()}</v>
<v>event_order() = trace_ts | event_ts</v>
<v>trace_pattern() = {report_module(), extended_dbg_match_spec()} | undefined</v>
- <v>report_module() = atom() | undefined &lt;v>extended_dbg_match_spec()() = detail_level() | dbg_match_spec()</v>
+ <v>report_module() = atom() | undefined</v>
+ <v>extended_dbg_match_spec() = detail_level() | dbg_match_spec()</v>
<v>detail_level() = min | max | integer(X) when X =&lt; 0, X >= 100</v>
<v>trace_client() = {event_file, file_name()} | {dbg_trace_type(), dbg_trace_parameters()}</v>
<v>file_name() = string()</v>
@@ -221,7 +222,7 @@
<v>CollectorPid = pid()</v>
<v>RawPattern = {report_module(), extended_dbg_match_spec()}</v>
<v>report_module() = atom() | undefined</v>
- <v>extended_dbg_match_spec()() = detail_level() | dbg_match_spec()</v>
+ <v>extended_dbg_match_spec() = detail_level() | dbg_match_spec()</v>
<v>RawPattern = detail_level()</v>
<v>detail_level() = min | max | integer(X) when X =&lt; 0, X >= 100</v>
<v>TracePattern = {report_module(), dbg_match_spec_match_spec()}</v>
@@ -348,7 +349,8 @@
<v>done() = 0</v>
<v>forward() = infinity | integer(X) where X > 0</v>
<v>backward() = '-infinity' | integer(X) where X &lt; 0</v>
- <v>Fun = fun(Event, Acc) -> NewAcc &lt;v>Acc = NewAcc = term()</v>
+ <v>Fun = fun(Event, Acc) -> NewAcc</v>
+ <v>Acc = NewAcc = term()</v>
</type>
<desc>
<p>Iterate over the currently stored events.</p>
diff --git a/lib/et/doc/src/et_selector.xml b/lib/et/doc/src/et_selector.xml
index 441a4dd278..30ca74c872 100644
--- a/lib/et/doc/src/et_selector.xml
+++ b/lib/et/doc/src/et_selector.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2002</year><year>2016</year>
+ <year>2002</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -90,7 +90,9 @@
<fsummary>Transforms trace data and makes an event record out of it</fsummary>
<type>
- <v>Mod = module_name() | undefined &lt;v>module_name() = atom() &lt;v>ValidTraceData = erlang_trace_data() | record(event)</v>
+ <v>Mod = module_name() | undefined</v>
+ <v>module_name() = atom()</v>
+ <v>ValidTraceData = erlang_trace_data() | record(event)</v>
<v>erlang_trace_data() = {trace, Pid, Label, Info} | {trace, Pid, Label, Info, Extra} | {trace_ts, Pid, Label, Info, ReportedTS} | {trace_ts, Pid, Label, Info, Extra, ReportedTS} | {seq_trace, Label, Info} | {seq_trace, Label, Info, ReportedTS} | {drop, NumberOfDroppedItems}</v>
</type>
diff --git a/lib/et/doc/src/files.mk b/lib/et/doc/src/files.mk
index e0ea9b0b76..c9041caa81 100644
--- a/lib/et/doc/src/files.mk
+++ b/lib/et/doc/src/files.mk
@@ -1,7 +1,7 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2002-2016. All Rights Reserved.
+# Copyright Ericsson AB 2002-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -31,10 +31,13 @@ XML_PART_FILES = \
XML_CHAPTER_FILES = \
et_intro.xml \
+ notes.xml
+
+GEN_XML = \
et_tutorial.xml \
et_desc.xml \
- et_examples.xml \
- notes.xml
+ et_examples.xml
+
BOOK_FILES = book.xml
diff --git a/lib/et/doc/src/notes.xml b/lib/et/doc/src/notes.xml
index 5300d2e4ef..110d3b2110 100644
--- a/lib/et/doc/src/notes.xml
+++ b/lib/et/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2002</year><year>2016</year>
+ <year>2002</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -37,6 +37,51 @@
one section in this document. The title of each section is the
version number of <c>Event Tracer (ET)</c>.</p>
+<section><title>ET 1.6.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>ET 1.6.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Calls to <c>erlang:get_stacktrace()</c> are removed.
+ </p>
+ <p>
+ Own Id: OTP-14861</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>ET 1.6.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Tools are updated to show Unicode atoms correctly.</p>
+ <p>
+ Own Id: OTP-14464</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>ET 1.6</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/et/src/et.app.src b/lib/et/src/et.app.src
index 7a5928d6ab..8cea1ba842 100644
--- a/lib/et/src/et.app.src
+++ b/lib/et/src/et.app.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,6 +33,6 @@
{registered, [et_collector]},
{applications, [stdlib, kernel]},
{env, []},
- {runtime_dependencies, ["wx-1.2","stdlib-2.0","runtime_tools-1.10",
- "kernel-3.0","erts-8.0"]}
+ {runtime_dependencies, ["wx-1.2","stdlib-3.4","runtime_tools-1.10",
+ "kernel-5.3","erts-9.0"]}
]}.
diff --git a/lib/et/src/et_collector.erl b/lib/et/src/et_collector.erl
index aba90b0be1..3609238509 100644
--- a/lib/et/src/et_collector.erl
+++ b/lib/et/src/et_collector.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -509,7 +509,7 @@ get_global_pid() ->
%% CollectorPid = pid()
%% RawPattern = {report_module(), extended_dbg_match_spec()}
%% report_module() = atom() | undefined
-%% extended_dbg_match_spec()() = detail_level() | dbg_match_spec()
+%% extended_dbg_match_spec() = detail_level() | dbg_match_spec()
%% RawPattern = detail_level()
%% detail_level() = min | max | integer(X) when X =< 0, X >= 100
%% TracePattern = {report_module(), dbg_match_spec_match_spec()}
@@ -750,7 +750,7 @@ next_iterate(TH, Prev = first, Limit, Fun, Acc) ->
'$end_of_table' ->
Acc;
{'EXIT', _} = Error ->
- io:format("~p(~p): First ~p~n", [?MODULE, ?LINE, Error]),
+ io:format("~p(~p): First ~tp~n", [?MODULE, ?LINE, Error]),
iterate(TH#table_handle.collector_pid, Prev, Limit, Fun, Acc);
First ->
lookup_and_apply(TH, Prev, First, Limit, -1, Fun, Acc)
@@ -761,7 +761,7 @@ next_iterate(TH, Prev = last, Limit, Fun, Acc) ->
'$end_of_table' ->
Acc;
{'EXIT', _} = Error ->
- io:format("~p(~p): Last ~p~n", [?MODULE, ?LINE, Error]),
+ io:format("~p(~p): Last ~tp~n", [?MODULE, ?LINE, Error]),
iterate(TH#table_handle.collector_pid, Prev, Limit, Fun, Acc);
Last ->
lookup_and_apply(TH, Prev, Last, Limit, -1, Fun, Acc)
@@ -773,7 +773,7 @@ next_iterate(TH, Prev, Limit, Fun, Acc) ->
'$end_of_table' ->
Acc;
{'EXIT', _} = Error ->
- io:format("~p(~p): Next ~p -> ~p~n", [?MODULE, ?LINE, Key, Error]),
+ io:format("~p(~p): Next ~tp -> ~tp~n", [?MODULE, ?LINE, Key, Error]),
iterate(TH#table_handle.collector_pid, Prev, Limit, Fun, Acc);
Next ->
lookup_and_apply(TH, Prev, Next, Limit, -1, Fun, Acc)
@@ -785,7 +785,7 @@ prev_iterate(TH, Prev = first, Limit, Fun, Acc) ->
'$end_of_table' ->
Acc;
{'EXIT', _} = Error ->
- io:format("~p(~p): First ~p~n", [?MODULE, ?LINE, Error]),
+ io:format("~p(~p): First ~tp~n", [?MODULE, ?LINE, Error]),
iterate(TH#table_handle.collector_pid, Prev, Limit, Fun, Acc);
First ->
lookup_and_apply(TH, Prev, First, Limit, 1, Fun, Acc)
@@ -796,7 +796,7 @@ prev_iterate(TH, Prev = last, Limit, Fun, Acc) ->
'$end_of_table' ->
Acc;
{'EXIT', _} = Error ->
- io:format("~p(~p): Last ~p~n", [?MODULE, ?LINE, Error]),
+ io:format("~p(~p): Last ~tp~n", [?MODULE, ?LINE, Error]),
iterate(TH#table_handle.collector_pid, Prev, Limit, Fun, Acc);
Last ->
lookup_and_apply(TH, Prev, Last, Limit, 1, Fun, Acc)
@@ -808,7 +808,7 @@ prev_iterate(TH, Prev, Limit, Fun, Acc) ->
'$end_of_table' ->
Acc;
{'EXIT', _} = Error ->
- io:format("~p(~p): Prev ~p -> ~p~n", [?MODULE, ?LINE, Key, Error]),
+ io:format("~p(~p): Prev ~tp -> ~tp~n", [?MODULE, ?LINE, Key, Error]),
iterate(TH#table_handle.collector_pid, Prev, Limit, Fun, Acc);
Next ->
lookup_and_apply(TH, Prev, Next, Limit, 1, Fun, Acc)
@@ -1049,7 +1049,7 @@ handle_call(stop, _From, S) ->
end,
{stop, shutdown, ok, S};
handle_call(Request, From, S) ->
- ok = error_logger:format("~p(~p): handle_call(~p, ~p, ~p)~n",
+ ok = error_logger:format("~p(~p): handle_call(~tp, ~tp, ~tp)~n",
[?MODULE, self(), Request, From, S]),
reply({error, {bad_request, Request}}, S).
@@ -1061,7 +1061,7 @@ handle_call(Request, From, S) ->
%%----------------------------------------------------------------------
handle_cast(Msg, S) ->
- ok = error_logger:format("~p(~p): handle_cast(~p, ~p)~n",
+ ok = error_logger:format("~p(~p): handle_cast(~tp, ~tp)~n",
[?MODULE, self(), Msg, S]),
noreply(S).
@@ -1083,18 +1083,18 @@ handle_info({nodeup, Node}, S) ->
S2 = listen_on_trace_port(Node, Port, S),
noreply(S2);
{error, Reason} when Reason =:= already_started->
- ok = error_logger:format("~p(~p): producer ignored(~p:~p):~n ~p~n",
+ ok = error_logger:format("~p(~p): producer ignored(~p:~p):~n ~tp~n",
[?MODULE, self(), Node, Port, Reason]),
S2 = S#state{trace_port = Port + 1},
noreply(S2);
{badrpc, Reason} ->
- ok = error_logger:format("~p(~p): producer ignored(~p:~p):~n ~p~n",
+ ok = error_logger:format("~p(~p): producer ignored(~p:~p):~n ~tp~n",
[?MODULE, self(), Node, Port, Reason]),
S2 = S#state{trace_port = Port + 1},
noreply(S2);
{error, Reason} ->
self() ! {nodeup, Node},
- ok = error_logger:format("~p(~p): producer retry(~p:~p):~n ~p~n",
+ ok = error_logger:format("~p(~p): producer retry(~p:~p):~n ~tp~n",
[?MODULE, self(), Node, Port, Reason]),
S2 = S#state{trace_port = Port + 1},
noreply(S2)
@@ -1125,17 +1125,17 @@ handle_info(Info = {'EXIT', Pid, Reason}, S) ->
opt_unlink(S#state.parent_pid),
{stop, Reason, S};
false ->
- ok = error_logger:format("~p(~p): handle_info(~p, ~p)~n",
+ ok = error_logger:format("~p(~p): handle_info(~tp, ~tp)~n",
[?MODULE, self(), Info, S]),
noreply(S)
end;
handle_info(Info, S) ->
- ok = error_logger:format("~p(~p): handle_info(~p, ~p)~n",
+ ok = error_logger:format("~p(~p): handle_info(~tp, ~tp)~n",
[?MODULE, self(), Info, S]),
noreply(S).
listen_on_trace_port(Node, Port, S) ->
- [_Name, Host] = string:tokens(atom_to_list(Node), [$@]),
+ [_Name, Host] = string:lexemes(atom_to_list(Node), [$@]),
case catch start_trace_client(self(), ip, {Host, Port}) of
{trace_client_pid, RemotePid} ->
rpc:call(Node, et_selector, change_pattern, [S#state.trace_pattern]),
@@ -1143,12 +1143,12 @@ listen_on_trace_port(Node, Port, S) ->
S#state{trace_nodes = [Node | S#state.trace_nodes],
trace_port = Port + 1};
{'EXIT', Reason} when Reason =:= already_started->
- ok = error_logger:format("~p(~p): consumer ignored(~p:~p): ~p~n",
+ ok = error_logger:format("~p(~p): consumer ignored(~p:~p): ~tp~n",
[?MODULE, self(), Node, Port, Reason]),
S#state{trace_port = Port + 1};
{'EXIT', Reason} ->
self() ! {nodeup, Node},
- ok = error_logger:format("~p(~p): consumer retry(~p:~p):~n ~p~n",
+ ok = error_logger:format("~p(~p): consumer retry(~p:~p):~n ~tp~n",
[?MODULE, self(), Node, Port, Reason]),
S#state{trace_port = Port + 1}
end.
@@ -1247,7 +1247,7 @@ file_open(F) ->
{ok, _} ->
{ok, Fd};
{repaired, _, _, BadBytes} ->
- ok = error_logger:format("~p: Skipped ~p bad bytes in file: ~p~n",
+ ok = error_logger:format("~p: Skipped ~p bad bytes in file: ~tp~n",
[?MODULE, BadBytes, F#file.name]),
{ok, Fd};
{error,Reason} ->
diff --git a/lib/et/src/et_selector.erl b/lib/et/src/et_selector.erl
index a0297c21d1..35db07cd99 100644
--- a/lib/et/src/et_selector.erl
+++ b/lib/et/src/et_selector.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -208,7 +208,7 @@ parse_event(Mod, Trace) ->
{to, undefined},
{drop, NumberOfDroppedItems}]}};
_ ->
- error_logger:format("~p(~p): Ignoring unknown trace type -> ~p~n~n",
+ error_logger:format("~p(~p): Ignoring unknown trace type -> ~tp~n~n",
[?MODULE, ?LINE, Trace]),
false
end.
@@ -258,7 +258,7 @@ parse_seq_event(Trace, ParsedTS, ReportedTS, Label, Info) ->
{serial, Serial},
{user_info, UserInfo}]}};
_ ->
- error_logger:format("~p(~p): Ignoring unknown trace type -> ~p~n~n",
+ error_logger:format("~p(~p): Ignoring unknown trace type -> ~tp~n~n",
[?MODULE, ?LINE, Trace]),
false
end.
@@ -590,7 +590,7 @@ parse_event(Mod, Trace, ParsedTS, ReportedTS, From, Label, Contents) ->
{to, From},
{gc_items, GcKeyValueList}]}};
_ ->
- error_logger:format("~p(~p): Ignoring unknown trace type -> ~p~n~n",
+ error_logger:format("~p(~p): Ignoring unknown trace type -> ~tp~n~n",
[?MODULE, ?LINE, Trace]),
false
end.
diff --git a/lib/et/src/et_wx_contents_viewer.erl b/lib/et/src/et_wx_contents_viewer.erl
index 247dd4c7ba..580c921139 100644
--- a/lib/et/src/et_wx_contents_viewer.erl
+++ b/lib/et/src/et_wx_contents_viewer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -93,8 +93,8 @@ start_link(Options) ->
end,
{ok, Pid}
catch
- error:Reason ->
- {error, {'EXIT', Reason, erlang:get_stacktrace()}}
+ error:Reason:Stacktrace ->
+ {error, {'EXIT', Reason, Stacktrace}}
end;
{error, Reason} ->
{error, Reason}
@@ -213,7 +213,7 @@ init([S]) when is_record(S, state) ->
%%----------------------------------------------------------------------
handle_call(Request, From, S) ->
- ok = error_logger:format("~p(~p): handle_call(~p, ~p, ~p)~n",
+ ok = error_logger:format("~p(~p): handle_call(~tp, ~tp, ~tp)~n",
[?MODULE, self(), Request, From, S]),
Reply = {error, {bad_request, Request}},
{reply, Reply, S}.
@@ -226,7 +226,7 @@ handle_call(Request, From, S) ->
%%----------------------------------------------------------------------
handle_cast(Msg, S) ->
- ok = error_logger:format("~p(~p): handle_cast(~p, ~p)~n",
+ ok = error_logger:format("~p(~p): handle_cast(~tp, ~tp)~n",
[?MODULE, self(), Msg, S]),
{noreply, S}.
@@ -272,10 +272,11 @@ handle_event(#wx{id = Id,
end,
FileName = lists:flatten(["et_contents_viewer_", now_to_string(TimeStamp), ".txt"]),
Style = ?wxFD_SAVE bor ?wxFD_OVERWRITE_PROMPT,
- Msg = "Select a file to the events to",
+ Msg = "Select a file to save events to",
case select_file(S#state.frame, Msg, filename:absname(FileName), Style) of
{ok, FileName2} ->
- Bin = list_to_binary(event_to_string(Event, S#state.event_order)),
+ EventString = event_to_string(Event, S#state.event_order),
+ Bin = unicode:characters_to_binary(EventString),
ok = file:write_file(FileName2, Bin);
cancel ->
ok
@@ -381,7 +382,7 @@ handle_event(#wx{event = #wxSize{size = {W, H}}}, S) ->
S2 = S#state{width = W, height = H},
{noreply, S2};
handle_event(Wx = #wx{}, S) ->
- io:format("~p got an unexpected event: ~p\n", [self(), Wx]),
+ io:format("~p got an unexpected event: ~tp\n", [self(), Wx]),
{noreply, S}.
%%----------------------------------------------------------------------
@@ -405,7 +406,7 @@ handle_info({'EXIT', Pid, Reason}, S) ->
{noreply, S}
end;
handle_info(Info, S) ->
- ok = error_logger:format("~p(~p): handle_info(~p, ~p)~n",
+ ok = error_logger:format("~p(~p): handle_info(~tp, ~tp)~n",
[?MODULE, self(), Info, S]),
{noreply, S}.
@@ -606,8 +607,8 @@ do_config_editor(Editor, Event, _Colour, TsKey) ->
%%%----------------------------------------------------------------------
term_to_string(Term) ->
- case catch io_lib:format("~s", [Term]) of
- {'EXIT', _} -> io_lib:format("~p", [Term]);
+ case catch io_lib:format("~ts", [Term]) of
+ {'EXIT', _} -> io_lib:format("~tp", [Term]);
GoodString -> GoodString
end.
@@ -659,7 +660,7 @@ pad_string(Int, MinLen, Char, Dir) when is_integer(Int) ->
pad_string(Atom, MinLen, Char, Dir) when is_atom(Atom) ->
pad_string(atom_to_list(Atom), MinLen, Char, Dir);
pad_string(String, MinLen, Char, Dir) when is_integer(MinLen), MinLen >= 0 ->
- Len = length(String),
+ Len = string:length(String),
case {Len >= MinLen, Dir} of
{true, _} ->
String;
diff --git a/lib/et/src/et_wx_viewer.erl b/lib/et/src/et_wx_viewer.erl
index 9613299e6b..4dd44e7a4c 100644
--- a/lib/et/src/et_wx_viewer.erl
+++ b/lib/et/src/et_wx_viewer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -352,7 +352,7 @@ handle_call({open_event, N}, _From, S) when is_integer(N), N > 0->
Reply = do_open_event(S, N),
reply(Reply, S);
handle_call(Request, From, S) ->
- ok = error_logger:format("~p(~p): handle_call(~p, ~p, ~p)~n",
+ ok = error_logger:format("~p(~p): handle_call(~tp, ~tp, ~tp)~n",
[?MODULE, self(), Request, From, S]),
Reply = {error, {bad_request, Request}},
reply(Reply, S).
@@ -365,7 +365,7 @@ handle_call(Request, From, S) ->
%%----------------------------------------------------------------------
handle_cast(Msg, S) ->
- ok = error_logger:format("~p(~p): handle_cast(~p, ~p)~n",
+ ok = error_logger:format("~p(~p): handle_cast(~tp, ~tp)~n",
[?MODULE, self(), Msg, S]),
noreply(S).
@@ -803,7 +803,7 @@ handle_info(timeout, S) ->
handle_info({'EXIT', Pid, Reason}, S) ->
if
Pid =:= S#state.collector_pid ->
- io:format("collector died: ~p\n\n", [Reason]),
+ io:format("collector died: ~tp\n\n", [Reason]),
wxFrame:destroy(S#state.frame),
{stop, Reason, S};
Pid =:= S#state.parent_pid ->
@@ -853,10 +853,10 @@ handle_info(#wx{event = #wxPaint{}}, S) ->
S2 = refresh_main_window(S),
noreply(S2);
handle_info(#wx{event = #wxMouse{type = T, x=X,y=Y}}, S) ->
- io:format("~p ~p\n", [T, {X,Y}]),
+ io:format("~tp ~tp\n", [T, {X,Y}]),
noreply(S);
handle_info(Info, S) ->
- ok = error_logger:format("~p(~p): handle_info(~p, ~p)~n",
+ ok = error_logger:format("~p(~p): handle_info(~tp, ~tp)~n",
[?MODULE, self(), Info, S]),
noreply(S).
@@ -1162,7 +1162,7 @@ open_viewer(Scale, FilterName, Actors, S) ->
%% unlink(ViewerPid),
ok;
{error, Reason} ->
- ok = error_logger:format("~p: Failed to start a new window: ~p~n",
+ ok = error_logger:format("~p: Failed to start a new window: ~tp~n",
[?MODULE, Reason])
end.
@@ -1393,7 +1393,7 @@ create_filter_menu(S=#state{filter_menu = {Menu,Data}}, ActiveFilterName, Filter
wxMenu:delete(Menu,I)
catch
_:Reason ->
- io:format("Could not delete item: ~p, because ~p.\n", [I, Reason])
+ io:format("Could not delete item: ~tp, because ~tp.\n", [I, Reason])
end
end,
Data),
@@ -1872,7 +1872,7 @@ create_contents_window(Event, {S, Res}) ->
{ok, Pid} ->
{S, [{ok, Pid} | Res]};
{error, Reason} ->
- ok = error_logger:format("~p(~p): create_contents_window(~p) ->~n ~p~n",
+ ok = error_logger:format("~p(~p): create_contents_window(~tp) ->~n ~tp~n",
[?MODULE, self(), Options, Reason]),
{S, [{error, Reason} | Res]};
Stuff ->
@@ -2069,15 +2069,15 @@ create_actor(Name) ->
#actor{name = Name, string = String, include = false, exclude = false}.
name_to_string(Name) ->
- case catch io_lib:format("~s", [Name]) of
- {'EXIT', _} -> lists:flatten(io_lib:format("~w", [Name]));
+ case catch io_lib:format("~ts", [Name]) of
+ {'EXIT', _} -> lists:flatten(io_lib:format("~tw", [Name]));
GoodString -> lists:flatten(GoodString)
end.
pad_string(Atom, MinLen) when is_atom(Atom) ->
pad_string(atom_to_list(Atom), MinLen);
pad_string(String, MinLen) when is_integer(MinLen), MinLen >= 0 ->
- Len = length(String),
+ Len = string:length(String),
case Len >= MinLen of
true ->
String;
diff --git a/lib/et/test/et_test_lib.erl b/lib/et/test/et_test_lib.erl
index df2c308b28..4addcd7ca8 100644
--- a/lib/et/test/et_test_lib.erl
+++ b/lib/et/test/et_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
-module(et_test_lib).
--compile(export_all).
+-compile([export_all, nowarn_export_all]).
-include("et_test_lib.hrl").
diff --git a/lib/et/test/ett.erl b/lib/et/test/ett.erl
index b1b769b7ac..dd274ec317 100644
--- a/lib/et/test/ett.erl
+++ b/lib/et/test/ett.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
-module(ett).
--compile(export_all).
+-compile([export_all, nowarn_export_all]).
%% Modules or suites can be shortcuts, for example wx expands to et_wx_SUITE.
%%
diff --git a/lib/et/vsn.mk b/lib/et/vsn.mk
index a37fec083b..9563a38000 100644
--- a/lib/et/vsn.mk
+++ b/lib/et/vsn.mk
@@ -1 +1 @@
-ET_VSN = 1.6
+ET_VSN = 1.6.3
diff --git a/lib/eunit/doc/src/Makefile b/lib/eunit/doc/src/Makefile
index f1491eb873..117542cb37 100644
--- a/lib/eunit/doc/src/Makefile
+++ b/lib/eunit/doc/src/Makefile
@@ -1,5 +1,5 @@
#<copyright>
-# <year>2004-2007</year>
+# <year>2004-2017</year>
# <holder>Ericsson AB, All Rights Reserved</holder>
#</copyright>
#<legalnotice>
@@ -51,11 +51,10 @@ EUNIT_MODULES = \
XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = $(EUNIT_MODULES:=.xml)
+XML_REF3_FILES = $(EUNIT_MODULES:=.xml)
XML_PART_FILES = \
- part.xml \
- part_notes.xml
+ part.xml
XML_CHAPTER_FILES = \
chapter.xml
@@ -63,7 +62,7 @@ XML_CHAPTER_FILES = \
XML_NOTES_FILES = \
notes.xml
-HTML_EXAMPLE_FILES =
+HTML_EXAMPLE_FILES =
HTML_STYLESHEET_FILES = \
../stylesheet.css
@@ -71,9 +70,10 @@ HTML_STYLESHEET_FILES = \
BOOK_FILES = book.xml
XML_FILES = \
- $(BOOK_FILES) $(XML_CHAPTER_FILES) $(XML_NOTES_FILES) \
- $(XML_PART_FILES) $(XML_REF3_FILES) $(XML_APPLICATION_FILES)
+ $(BOOK_FILES) $(XML_NOTES_FILES) \
+ $(XML_PART_FILES) $(XML_APPLICATION_FILES)
+XML_GEN_FILES = $(XML_REF3_FILES:%=$(XMLDIR)/%) $(XML_CHAPTER_FILES:%=$(XMLDIR)/%)
# ----------------------------------------------------
INFO_FILE = ../../info
@@ -99,10 +99,10 @@ TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
+XML_FLAGS +=
+DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -123,11 +123,11 @@ man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-$(XML_REF3_FILES):
- escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(EUNIT_VSN) -i $(EUNIT_INC_DIR) $(EUNIT_DIR)/$(@:%.xml=%.erl)
+$(XML_REF3_FILES:%=$(XMLDIR)/%):
+ $(gen_verbose)escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(EUNIT_VSN) -i $(EUNIT_INC_DIR) -dir $(XMLDIR) $(EUNIT_DIR)/$(@:$(XMLDIR)/%.xml=%.erl)
-$(XML_CHAPTER_FILES):
- escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(EUNIT_VSN) -chapter ../overview.edoc
+$(XML_CHAPTER_FILES:%=$(XMLDIR)/%):
+ $(gen_verbose)escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(EUNIT_VSN) -chapter -dir $(XMLDIR) ../overview.edoc
info:
@echo "XML_PART_FILES: $(XML_PART_FILES)"
@@ -142,19 +142,20 @@ info:
xml: $(XML_REF3_FILES) $(XML_CHAPTER_FILES)
-debug opt:
+debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(XML_REF3_FILES) $(XML_CHAPTER_FILES) *.html
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
+ rm -f errs core *~
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
@@ -169,6 +170,3 @@ release_docs_spec: docs
release_spec:
-
-
-
diff --git a/lib/eunit/doc/src/fascicules.xml b/lib/eunit/doc/src/fascicules.xml
deleted file mode 100644
index 217228785c..0000000000
--- a/lib/eunit/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/eunit/doc/src/notes.xml b/lib/eunit/doc/src/notes.xml
index 2a4ca6d12c..67a9ae5fcb 100644
--- a/lib/eunit/doc/src/notes.xml
+++ b/lib/eunit/doc/src/notes.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2008</year>
- <year>2017</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -33,6 +33,66 @@
</header>
<p>This document describes the changes made to the EUnit application.</p>
+<section><title>Eunit 2.3.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Eunit 2.3.6</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Calls to <c>erlang:get_stacktrace()</c> are removed.
+ </p>
+ <p>
+ Own Id: OTP-14861</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Eunit 2.3.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Eunit 2.3.4</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Tools are updated to show Unicode atoms correctly.</p>
+ <p>
+ Own Id: OTP-14464</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Eunit 2.3.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/eunit/doc/src/part_notes.xml b/lib/eunit/doc/src/part_notes.xml
deleted file mode 100644
index 7db65083e0..0000000000
--- a/lib/eunit/doc/src/part_notes.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2008</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>EUnit Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date>2008-10-29</date>
- <rev></rev>
-
- </header>
- <description>
- <p>The <em>EUnit</em> application
- contains modules with support for unit testing</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/eunit/src/eunit.app.src b/lib/eunit/src/eunit.app.src
index b4ff6c9242..cc75a0f790 100644
--- a/lib/eunit/src/eunit.app.src
+++ b/lib/eunit/src/eunit.app.src
@@ -19,4 +19,4 @@
{registered,[]},
{applications, [kernel,stdlib]},
{env, []},
- {runtime_dependencies, ["stdlib-2.5","kernel-3.0","erts-6.0"]}]}.
+ {runtime_dependencies, ["stdlib-3.4","kernel-5.3","erts-9.0"]}]}.
diff --git a/lib/eunit/src/eunit_lib.erl b/lib/eunit/src/eunit_lib.erl
index aa2cffc66d..771541354c 100644
--- a/lib/eunit/src/eunit_lib.erl
+++ b/lib/eunit/src/eunit_lib.erl
@@ -107,7 +107,7 @@ format_stacktrace(Trace) ->
format_stacktrace(Trace, "in function", "in call from").
format_stacktrace([{M,F,A,L}|Fs], Pre, Pre1) when is_integer(A) ->
- [io_lib:fwrite("~ts ~w:~w/~w~ts\n",
+ [io_lib:fwrite("~ts ~w:~tw/~w~ts\n",
[Pre, M, F, A, format_stacktrace_location(L)])
| format_stacktrace(Fs, Pre1, Pre1)];
format_stacktrace([{M,F,As,L}|Fs], Pre, Pre1) when is_list(As) ->
@@ -121,9 +121,9 @@ format_stacktrace([{M,F,As,L}|Fs], Pre, Pre1) when is_list(As) ->
io_lib:fwrite("~ts ~ts ~ts",
[format_arg(A1),F,format_arg(A2)]);
false ->
- io_lib:fwrite("~w(~ts)", [F,format_arglist(As)])
+ io_lib:fwrite("~tw(~ts)", [F,format_arglist(As)])
end,
- [io_lib:fwrite("~ts ~w:~w/~w~ts\n called as ~ts\n",
+ [io_lib:fwrite("~ts ~w:~tw/~w~ts\n called as ~ts\n",
[Pre,M,F,A,format_stacktrace_location(L),C])
| format_stacktrace(Fs,Pre1,Pre1)];
format_stacktrace([{M,F,As}|Fs], Pre, Pre1) ->
@@ -162,15 +162,15 @@ is_op(_M, _F, _A) ->
format_error({bad_test, Term}) ->
error_msg("bad test descriptor", "~tP", [Term, 15]);
format_error({bad_generator, {{M,F,A}, Term}}) ->
- error_msg(io_lib:format("result from generator ~w:~w/~w is not a test",
+ error_msg(io_lib:format("result from generator ~w:~tw/~w is not a test",
[M,F,A]),
"~tP", [Term, 15]);
format_error({generator_failed, {{M,F,A}, Exception}}) ->
- error_msg(io_lib:format("test generator ~w:~w/~w failed",[M,F,A]),
+ error_msg(io_lib:format("test generator ~w:~tw/~w failed",[M,F,A]),
"~ts", [format_exception(Exception)]);
format_error({no_such_function, {M,F,A}})
when is_atom(M), is_atom(F), is_integer(A) ->
- error_msg(io_lib:format("no such function: ~w:~w/~w", [M,F,A]),
+ error_msg(io_lib:format("no such function: ~w:~tw/~w", [M,F,A]),
"", []);
format_error({module_not_found, M}) ->
error_msg("test module not found", "~tp", [M]);
@@ -185,7 +185,7 @@ format_error({cleanup_failed, Exception}) ->
error_msg("context cleanup failed", "~ts",
[format_exception(Exception)]);
format_error({{bad_instantiator, {{M,F,A}, Term}}, _DummyException}) ->
- error_msg(io_lib:format("result from instantiator ~w:~w/~w is not a test",
+ error_msg(io_lib:format("result from instantiator ~w:~tw/~w is not a test",
[M,F,A]),
"~tP", [Term, 15]);
format_error({instantiation_failed, Exception}) ->
@@ -202,13 +202,13 @@ format_exception_test_() ->
"\nymmud:rorre"++_,
lists:reverse(lists:flatten(
format_exception(try erlang:error(dummy)
- catch C:R -> {C, R, erlang:get_stacktrace()}
+ catch C:R:S -> {C, R, S}
end)))),
?_assertMatch(
"\nymmud:rorre"++_,
lists:reverse(lists:flatten(
format_exception(try erlang:error(dummy, [a])
- catch C:R -> {C, R, erlang:get_stacktrace()}
+ catch C:R:S -> {C, R, S}
end))))].
-endif.
@@ -384,16 +384,14 @@ fun_parent(F) ->
{arity, A} = erlang:fun_info(F, arity),
{M, N, A};
{type, local} ->
- [$-|S] = atom_to_list(N),
- C1 = string:chr(S, $/),
- C2 = string:chr(S, $-),
- {M, list_to_atom(string:sub_string(S, 1, C1 - 1)),
- list_to_integer(string:sub_string(S, C1 + 1, C2 - 1))}
+ [$-|S] = atom_to_list(N),
+ [S2, T] = string:split(S, "/", trailing),
+ {M, list_to_atom(S2), element(1, string:to_integer(T))}
end.
-ifdef(TEST).
fun_parent_test() ->
- {?MODULE,fun_parent_test,0} = fun_parent(fun () -> ok end).
+ {?MODULE,fun_parent_test,0} = fun_parent(fun (A) -> {ok,A} end).
-endif.
%% ---------------------------------------------------------------------
diff --git a/lib/eunit/src/eunit_listener.erl b/lib/eunit/src/eunit_listener.erl
index e652c5b2f6..75aa05c543 100644
--- a/lib/eunit/src/eunit_listener.erl
+++ b/lib/eunit/src/eunit_listener.erl
@@ -137,8 +137,7 @@ call(F, As, St) when is_atom(F) ->
try apply(St#state.callback, F, As) of
Substate -> St#state{state = Substate}
catch
- Class:Term ->
- Trace = erlang:get_stacktrace(),
+ Class:Term:Trace ->
if F =/= terminate ->
call(terminate, [{error, {Class, Term, Trace}},
St#state.state], St);
diff --git a/lib/eunit/src/eunit_proc.erl b/lib/eunit/src/eunit_proc.erl
index e075005238..96bdcf88b6 100644
--- a/lib/eunit/src/eunit_proc.erl
+++ b/lib/eunit/src/eunit_proc.erl
@@ -628,7 +628,7 @@ io_request({put_chars, M, F, As}, Buf) ->
try apply(M, F, As) of
Chars -> {ok, [Chars | Buf]}
catch
- C:T -> {{error, {C,T,erlang:get_stacktrace()}}, Buf}
+ C:T:S -> {{error, {C,T,S}}, Buf}
end;
io_request({put_chars, _Enc, Chars}, Buf) ->
io_request({put_chars, Chars}, Buf);
diff --git a/lib/eunit/src/eunit_test.erl b/lib/eunit/src/eunit_test.erl
index 6036537178..6fe85ae70a 100644
--- a/lib/eunit/src/eunit_test.erl
+++ b/lib/eunit/src/eunit_test.erl
@@ -39,11 +39,11 @@
%% somewhat, but you can't have everything.) Note that we assume that
%% this particular module is the boundary between eunit and user code.
-get_stacktrace() ->
- get_stacktrace([]).
+get_stacktrace(Trace) ->
+ get_stacktrace(Trace, []).
-get_stacktrace(Ts) ->
- eunit_lib:uniq(prune_trace(erlang:get_stacktrace(), Ts)).
+get_stacktrace(Trace, Ts) ->
+ eunit_lib:uniq(prune_trace(Trace, Ts)).
-dialyzer({no_match, prune_trace/2}).
prune_trace([{eunit_data, _, _} | Rest], Tail) ->
@@ -75,8 +75,8 @@ run_testfun(F) ->
{eunit_internal, Term} ->
%% Internally generated: re-throw Term (lose the trace)
throw(Term);
- Class:Reason ->
- {error, {Class, Reason, get_stacktrace()}}
+ Class:Reason:Trace ->
+ {error, {Class, Reason, Trace}}
end.
@@ -272,7 +272,7 @@ mf_wrapper(M, F) ->
fun () ->
try M:F()
catch
- error:undef ->
+ error:undef:Trace ->
%% Check if it was M:F/0 that was undefined
case erlang:module_loaded(M) of
false ->
@@ -282,14 +282,14 @@ mf_wrapper(M, F) ->
false ->
fail({no_such_function, {M,F,0}});
true ->
- rethrow(error, undef, [{M,F,0}])
+ rethrow(error, undef, Trace, [{M,F,0}])
end
end
end
end.
-rethrow(Class, Reason, Trace) ->
- erlang:raise(Class, Reason, get_stacktrace(Trace)).
+rethrow(Class, Reason, Trace, Ts) ->
+ erlang:raise(Class, Reason, get_stacktrace(Trace, Ts)).
fail(Term) ->
throw({eunit_internal, Term}).
@@ -332,12 +332,14 @@ enter_context(Setup, Cleanup, Instantiate, Callback) ->
T ->
case eunit_lib:is_not_test(T) of
true ->
- catch throw(error), % generate a stack trace
+ {_, Stacktrace} =
+ erlang:process_info(self(),
+ current_stacktrace),
{module,M} = erlang:fun_info(Instantiate, module),
{name,N} = erlang:fun_info(Instantiate, name),
{arity,A} = erlang:fun_info(Instantiate, arity),
context_error({bad_instantiator, {{M,N,A},T}},
- error, badarg);
+ error, Stacktrace, badarg);
false ->
ok
end,
@@ -346,21 +348,22 @@ enter_context(Setup, Cleanup, Instantiate, Callback) ->
%% Always run cleanup; client may be an idiot
try Cleanup(R)
catch
- Class:Term ->
- context_error(cleanup_failed, Class, Term)
+ Class:Term:Trace ->
+ context_error(cleanup_failed,
+ Class, Trace, Term)
end
end
catch
- Class:Term ->
- context_error(instantiation_failed, Class, Term)
+ Class:Term:Trace ->
+ context_error(instantiation_failed, Class, Trace, Term)
end
catch
- Class:Term ->
- context_error(setup_failed, Class, Term)
+ Class:Term:Trace ->
+ context_error(setup_failed, Class, Trace, Term)
end.
-context_error(Type, Class, Term) ->
- throw({context_error, Type, {Class, Term, get_stacktrace()}}).
+context_error(Type, Class, Trace, Term) ->
+ throw({context_error, Type, {Class, Term, get_stacktrace(Trace)}}).
%% This generates single setup/cleanup functions from a list of tuples
%% on the form {Tag, Setup, Cleanup}, where the setup function always
@@ -378,8 +381,8 @@ multi_setup([{Tag, S, C} | Es], CleanupPrev) ->
try C(R) of
_ -> CleanupPrev(Rs)
catch
- Class:Term ->
- throw({Tag, {Class, Term, get_stacktrace()}})
+ Class:Term:Trace ->
+ throw({Tag, {Class, Term, Trace}})
end
end,
{SetupRest, CleanupAll} = multi_setup(Es, Cleanup),
@@ -388,9 +391,9 @@ multi_setup([{Tag, S, C} | Es], CleanupPrev) ->
R ->
SetupRest([R|Rs])
catch
- Class:Term ->
+ Class:Term:Trace ->
CleanupPrev(Rs),
- throw({Tag, {Class, Term, get_stacktrace()}})
+ throw({Tag, {Class, Term, Trace}})
end
end,
CleanupAll};
diff --git a/lib/eunit/src/eunit_tty.erl b/lib/eunit/src/eunit_tty.erl
index 77a7cf1fd5..2c9a598628 100644
--- a/lib/eunit/src/eunit_tty.erl
+++ b/lib/eunit/src/eunit_tty.erl
@@ -235,7 +235,7 @@ print_test_error({skipped, Reason}, _) ->
format_skipped({module_not_found, M}) ->
io_lib:fwrite("missing module: ~w", [M]);
format_skipped({no_such_function, {M,F,A}}) ->
- io_lib:fwrite("no such function: ~w:~w/~w", [M,F,A]).
+ io_lib:fwrite("no such function: ~w:~tw/~w", [M,F,A]).
print_test_cancel(Reason) ->
fwrite(format_cancel(Reason)).
diff --git a/lib/eunit/vsn.mk b/lib/eunit/vsn.mk
index 107ad5c101..46ef5eea3c 100644
--- a/lib/eunit/vsn.mk
+++ b/lib/eunit/vsn.mk
@@ -1 +1 @@
-EUNIT_VSN = 2.3.3
+EUNIT_VSN = 2.3.7
diff --git a/lib/ftp/AUTHORS b/lib/ftp/AUTHORS
new file mode 100644
index 0000000000..88dcbf602a
--- /dev/null
+++ b/lib/ftp/AUTHORS
@@ -0,0 +1,11 @@
+Original Authors:
+
+Peter Högfeldt - first version of ftp
+
+Contributors:
+
+Ingela Anderton Andin
+Martin Gustafsson
+Johan Blom
+Torbjörn Törnkvist
+Joe Armstrong \ No newline at end of file
diff --git a/lib/ftp/Makefile b/lib/ftp/Makefile
new file mode 100644
index 0000000000..e0c9de42e4
--- /dev/null
+++ b/lib/ftp/Makefile
@@ -0,0 +1,78 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1996-2018. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# %CopyrightEnd%
+#
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Macros
+# ----------------------------------------------------
+
+SUB_DIRECTORIES = src doc/src
+
+include vsn.mk
+VSN = $(FTP_VSN)
+
+SPECIAL_TARGETS =
+
+DIA_PLT = ./priv/plt/$(APPLICATION).plt
+DIA_ANALYSIS = $(basename $(DIA_PLT)).dialyzer_analysis
+
+
+# ----------------------------------------------------
+# Default Subdir Targets
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_subdir.mk
+
+.PHONY: info gclean dialyzer dialyzer_plt dclean
+
+info:
+ @echo "OS: $(OS)"
+ @echo "DOCB: $(DOCB)"
+ @echo ""
+ @echo "FTP_VSN: $(FTP_VSN)"
+ @echo "APP_VSN: $(APP_VSN)"
+ @echo ""
+ @echo "DIA_PLT: $(DIA_PLT)"
+ @echo "DIA_ANALYSIS: $(DIA_ANALYSIS)"
+ @echo ""
+
+gclean:
+ git clean -fXd
+
+dclean:
+ rm -f $(DIA_PLT)
+ rm -f $(DIA_ANALYSIS)
+
+dialyzer_plt: $(DIA_PLT)
+
+$(DIA_PLT):
+ @echo "Building $(APPLICATION) plt file"
+ @dialyzer --build_plt \
+ --output_plt $@ \
+ -r ../$(APPLICATION)/ebin \
+ --output $(DIA_ANALYSIS) \
+ --verbose
+
+dialyzer: $(DIA_PLT)
+ @echo "Running dialyzer on $(APPLICATION)"
+ @dialyzer --plt $< \
+ ../$(APPLICATION)/ebin \
+ --verbose
diff --git a/lib/inets/doc/archive/rfc2428.txt b/lib/ftp/doc/archive/rfc2428.txt
index a6ec3535ed..a6ec3535ed 100644
--- a/lib/inets/doc/archive/rfc2428.txt
+++ b/lib/ftp/doc/archive/rfc2428.txt
diff --git a/lib/inets/doc/archive/rfc2577.txt b/lib/ftp/doc/archive/rfc2577.txt
index 83ba203130..83ba203130 100644
--- a/lib/inets/doc/archive/rfc2577.txt
+++ b/lib/ftp/doc/archive/rfc2577.txt
diff --git a/lib/inets/doc/archive/rfc959.txt b/lib/ftp/doc/archive/rfc959.txt
index 5c9f11af5d..5c9f11af5d 100644
--- a/lib/inets/doc/archive/rfc959.txt
+++ b/lib/ftp/doc/archive/rfc959.txt
diff --git a/lib/cosEvent/doc/html/.gitignore b/lib/ftp/doc/html/.gitignore
index e69de29bb2..e69de29bb2 100644
--- a/lib/cosEvent/doc/html/.gitignore
+++ b/lib/ftp/doc/html/.gitignore
diff --git a/lib/cosEvent/doc/man3/.gitignore b/lib/ftp/doc/man3/.gitignore
index e69de29bb2..e69de29bb2 100644
--- a/lib/cosEvent/doc/man3/.gitignore
+++ b/lib/ftp/doc/man3/.gitignore
diff --git a/lib/cosEvent/doc/man6/.gitignore b/lib/ftp/doc/man6/.gitignore
index e69de29bb2..e69de29bb2 100644
--- a/lib/cosEvent/doc/man6/.gitignore
+++ b/lib/ftp/doc/man6/.gitignore
diff --git a/lib/cosEvent/doc/pdf/.gitignore b/lib/ftp/doc/pdf/.gitignore
index e69de29bb2..e69de29bb2 100644
--- a/lib/cosEvent/doc/pdf/.gitignore
+++ b/lib/ftp/doc/pdf/.gitignore
diff --git a/lib/ftp/doc/src/Makefile b/lib/ftp/doc/src/Makefile
new file mode 100644
index 0000000000..20fbbc73a9
--- /dev/null
+++ b/lib/ftp/doc/src/Makefile
@@ -0,0 +1,155 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# %CopyrightEnd%
+#
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../../vsn.mk
+VSN=$(FTP_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
+
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+XML_APPLICATION_FILES = ref_man.xml
+
+XML_CHAPTER_FILES = \
+ introduction.xml \
+ ftp_client.xml \
+ notes.xml
+
+XML_REF3_FILES = \
+ ftp.xml
+
+XML_PART_FILES = \
+ part.xml
+
+BOOK_FILES = book.xml
+
+XML_FILES = \
+ $(BOOK_FILES) \
+ $(XML_CHAPTER_FILES) \
+ $(XML_PART_FILES) \
+ $(XML_REF6_FILES) \
+ $(XML_REF3_FILES) \
+ $(XML_APPLICATION_FILES)
+
+# GIF_FILES = ftp.gif
+
+
+# ----------------------------------------------------
+
+HTML_FILES = \
+ $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
+ $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
+
+INFO_FILE = ../../info
+EXTRA_FILES = \
+ $(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html) \
+ $(XML_REF6_FILES:%.xml=$(HTMLDIR)/%.html) \
+ $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html)
+
+MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
+
+HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
+
+TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+XML_FLAGS +=
+DVIPS_FLAGS +=
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+$(HTMLDIR)/%.gif: %.gif
+ $(INSTALL_DATA) $< $@
+
+docs: pdf html man
+
+ldocs: local_docs
+
+$(TOP_PDF_FILE): $(XML_FILES)
+
+pdf: $(TOP_PDF_FILE)
+
+html: gifs $(HTML_REF_MAN_FILE)
+
+clean clean_docs: clean_html clean_man clean_pdf
+ rm -rf $(XMLDIR)
+ rm -f errs core *~
+
+man: $(MAN3_FILES)
+
+gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
+
+debug opt:
+
+clean_pdf:
+ rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+
+clean_html:
+ rm -rf $(TOP_HTML_FILES) $(HTMLDIR)/*
+
+clean_man:
+ rm -f $(MAN3_FILES)
+
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_docs_spec: docs
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(HTMLDIR)/* "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
+
+release_spec:
+
+info:
+ @echo "GIF_FILES:\n$(GIF_FILES)"
+ @echo ""
+ @echo "EXTRA_FILES:\n$(EXTRA_FILES)"
+ @echo ""
+ @echo "HTML_FILES:\n$(HTML_FILES)"
+ @echo ""
+ @echo "TOP_HTML_FILES:\n$(TOP_HTML_FILES)"
+ @echo ""
+ @echo "XML_REF3_FILES:\n$(XML_REF3_FILES)"
+ @echo ""
+ @echo "XML_REF6_FILES:\n$(XML_REF6_FILES)"
+ @echo ""
+ @echo "XML_CHAPTER_FILES:\n$(XML_CHAPTER_FILES)"
+ @echo ""
diff --git a/lib/ftp/doc/src/book.xml b/lib/ftp/doc/src/book.xml
new file mode 100644
index 0000000000..1268af64bf
--- /dev/null
+++ b/lib/ftp/doc/src/book.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE book SYSTEM "book.dtd">
+
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
+ <header titlestyle="normal">
+ <copyright>
+ <year>1997</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>FTP</title>
+ <prepared>Péter Dimitrov</prepared>
+ <docno></docno>
+ <date>2018-02-26</date>
+ <rev>1.0</rev>
+ <file>book.sgml</file>
+ </header>
+ <insidecover>
+ </insidecover>
+ <pagetext>FTP</pagetext>
+ <preamble>
+ <contents level="2"></contents>
+ </preamble>
+ <parts lift="no">
+ <xi:include href="part.xml"/>
+ </parts>
+ <applications>
+ <xi:include href="ref_man.xml"/>
+ </applications>
+ <releasenotes>
+ <xi:include href="notes.xml"/>
+ </releasenotes>
+ <listofterms></listofterms>
+ <index></index>
+</book>
diff --git a/lib/ftp/doc/src/ftp.xml b/lib/ftp/doc/src/ftp.xml
new file mode 100644
index 0000000000..34e3ff84b0
--- /dev/null
+++ b/lib/ftp/doc/src/ftp.xml
@@ -0,0 +1,983 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>1997</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>ftp</title>
+ <prepared>Peter H&ouml;gfeldt</prepared>
+ <docno></docno>
+ <date>1997-11-05</date>
+ <rev>B</rev>
+ <file>ftp.xml</file>
+ </header>
+ <module>ftp</module>
+ <modulesummary>A File Transfer Protocol client.</modulesummary>
+
+ <description>
+
+ <p>This module implements a client for file transfer
+ according to a subset of the File Transfer Protocol (FTP), see
+ <url href="http://www.ietf.org/rfc/rfc959.txt">RFC 959</url>.</p>
+
+ <p>The FTP client always tries to use passive FTP mode and only resort
+ to active FTP mode if this fails. This default behavior can be
+ changed by start option <seealso marker="#mode">mode</seealso>.</p>
+
+ <marker id="two_start"></marker>
+
+ <p>An FTP client can be started in two ways. One is using the
+ <seealso marker="#service_start">service_start</seealso> function,
+ the other is to start it directly as a standalone process
+ using function <seealso marker="#open">open</seealso>.</p>
+
+ <p>For a simple example of an FTP session, see
+ <seealso marker="ftp_client">FTP User's Guide</seealso>.</p>
+
+ <p>In addition to the ordinary functions for receiving and sending
+ files (see <c>recv/2</c>, <c>recv/3</c>, <c>send/2</c>, and
+ <c>send/3</c>) there are functions for receiving remote files as
+ binaries (see <c>recv_bin/2</c>) and for sending binaries to be
+ stored as remote files (see <c>send_bin/3</c>).</p>
+
+ <p>A set of functions is provvided for sending and receiving
+ contiguous parts of a file to be stored in a remote file. For send,
+ see <c>send_chunk_start/2</c>, <c>send_chunk/2</c>, and
+ <c>send_chunk_end/1</c>. For receive, see
+ <c>recv_chunk_start/2</c> and <c>recv_chunk/</c>).</p>
+
+ <p>The return values of the following functions depend
+ much on the implementation of the FTP server at the remote
+ host. In particular, the results from <c>ls</c> and <c>nlist</c>
+ varies. Often real errors are not reported as errors by <c>ls</c>,
+ even if, for example, a file or directory does not
+ exist. <c>nlist</c> is usually more strict, but some
+ implementations have the peculiar behaviour of responding with an
+ error if the request is a listing of the contents of a directory
+ that exists but is empty.</p>
+
+ <marker id="service_start"></marker>
+ </description>
+
+ <section>
+ <title>FTP CLIENT SERVICE START/STOP</title>
+
+ <p>The FTP client can be started and stopped dynamically in runtime by
+ calling the <c>ftp</c> application API
+ <c>ftp:start_service(ServiceConfig)</c> and
+ <c>ftp:stop_service(Pid)</c>.</p>
+
+ <p>The available configuration options are as follows:</p>
+
+ <taglist>
+ <tag>{host, Host}</tag>
+ <item>
+ <marker id="host"></marker>
+ <p>Host = <c>string() | ip_address()</c></p>
+ </item>
+
+ <tag>{port, Port}</tag>
+ <item>
+ <marker id="port"></marker>
+ <p>Port = <c>integer() > 0</c></p>
+ <p>Default is <c>21</c>.</p>
+ </item>
+
+ <tag>{mode, Mode}</tag>
+ <item>
+ <marker id="mode"></marker>
+ <p>Mode = <c>active | passive</c></p>
+ <p>Default is <c>passive</c>.</p>
+ </item>
+
+ <tag>{verbose, Verbose}</tag>
+ <item>
+ <marker id="verbose"></marker>
+ <p>Verbose = <c>boolean()</c> </p>
+ <p>Determines if the FTP communication is to be
+ verbose or not.</p>
+ <p>Default is <c>false</c>.</p>
+ </item>
+
+ <tag>{debug, Debug}</tag>
+ <item>
+ <marker id="debug"></marker>
+ <p>Debug = <c>trace | debug | disable</c> </p>
+ <p>Debugging using the dbg toolkit. </p>
+ <p>Default is <c>disable</c>.</p>
+ </item>
+
+ <tag>{ipfamily, IpFamily}</tag>
+ <item>
+ <marker id="ipfamily"></marker>
+ <p>IpFamily = <c>inet | inet6 | inet6fb4</c> </p>
+ <p>With <c>inet6fb4</c> the client behaves as before, that is,
+ tries to use IPv6, and only if that does not work it
+ uses IPv4).</p>
+ <p>Default is <c>inet</c> (IPv4).</p>
+ </item>
+
+ <tag>{timeout, Timeout}</tag>
+ <item>
+ <marker id="timeout"></marker>
+ <p>Timeout = <c>non_neg_integer()</c></p>
+ <p>Connection time-out.</p>
+ <p>Default is <c>60000</c> (milliseconds).</p>
+ </item>
+
+ <tag>{dtimeout, DTimeout}</tag>
+ <item>
+ <marker id="dtimeout"></marker>
+ <p>DTimeout = <c>non_neg_integer() | infinity</c> </p>
+ <p>Data connect time-out.
+ The time the client waits for the server to connect to the
+ data socket.</p>
+ <p>Default is <c>infinity</c>. </p>
+ </item>
+
+ <tag>{progress, Progress}</tag>
+ <item>
+ <marker id="progress"></marker>
+ <p>Progress = <c>ignore | {CBModule, CBFunction, InitProgress}</c></p>
+ <p><c>CBModule = atom()</c>, <c>CBFunction = atom()</c></p>
+ <p><c>InitProgress = term()</c></p>
+ <p>Default is <c>ignore</c>.</p>
+ </item>
+
+ </taglist>
+
+ <p>Option <c>progress</c> is intended to be used by applications that
+ want to create some type of progress report, such as a progress bar in
+ a GUI. Default for the progress option is <c>ignore</c>,
+ that is, the option is not used. When the progress option is
+ specified, the following happens when <c>ftp:send/[3,4]</c> or
+ <c>ftp:recv/[3,4]</c> are called:</p>
+
+ <list type="bulleted">
+ <item>
+ <p>Before a file is transferred, the following call is
+ made to indicate the start of the file transfer and how large
+ the file is. The return value of the callback function
+ is to be a new value for the <c>UserProgressTerm</c> that will
+ be used as input the next time the callback function is
+ called.</p>
+ <p><c>
+ CBModule:CBFunction(InitProgress, File, {file_size, FileSize})
+ </c></p>
+ </item>
+
+ <item>
+ <p>Every time a chunk of bytes is transferred the
+ following call is made:</p>
+ <p><c>
+ CBModule:CBFunction(UserProgressTerm, File, {transfer_size, TransferSize})
+ </c></p>
+ </item>
+
+ <item>
+ <p>At the end of the file the following call is
+ made to indicate the end of the transfer:</p>
+ <p><c>
+ CBModule:CBFunction(UserProgressTerm, File, {transfer_size, 0})
+ </c></p>
+ </item>
+ </list>
+
+ <p>The callback function is to be defined as follows:</p>
+
+ <p><c>
+ CBModule:CBFunction(UserProgressTerm, File, Size) -> UserProgressTerm
+ </c></p>
+
+ <p><c>
+ CBModule = CBFunction = atom()
+ </c></p>
+
+ <p><c>
+ UserProgressTerm = term()
+ </c></p>
+
+ <p><c>
+ File = string()
+ </c></p>
+
+ <p><c>
+ Size = {transfer_size, integer()} | {file_size, integer()} | {file_size, unknown}
+ </c></p>
+
+ <p>For remote files, <c>ftp</c> cannot determine the
+ file size in a platform independent way. In this case the size
+ becomes <c>unknown</c> and it is left to the application to
+ determine the size.</p>
+
+ <note>
+ <p>The callback is made by a middleman process, hence the
+ file transfer is not affected by the code in the progress
+ callback function. If the callback crashes, this is
+ detected by the FTP connection process, which then prints an
+ info-report and goes on as if the progress option was set
+ to <c>ignore</c>.</p>
+ </note>
+
+ <p>The file transfer type is set to the default of the FTP server
+ when the session is opened. This is usually ASCCI mode.
+ </p>
+
+ <p>The current local working directory (compare <c>lpwd/1</c>) is set
+ to the value reported by <c>file:get_cwd/1</c>, the wanted
+ local directory.
+ </p>
+
+ <p>The return value <c>Pid</c> is used as a reference to the
+ newly created FTP client in all other functions, and they are to
+ be called by the process that created the connection. The FTP
+ client process monitors the process that created it and
+ terminates if that process terminates.</p>
+ </section>
+
+ <section>
+ <title>DATA TYPES</title>
+ <p>The following type definitions are used by more than one
+ function in the FTP client API:</p>
+ <p><c>pid()</c> = identifier of an FTP connection</p>
+ <p><c>string()</c> = list of ASCII characters</p>
+ <p><c>shortage_reason()</c> = <c>etnospc | epnospc</c></p>
+ <p><c>restriction_reason()</c> = <c>epath | efnamena | elogin | enotbinary</c>
+ - all restrictions are not always relevant to all functions
+ </p>
+ <p><c>common_reason()</c> = <c>econn | eclosed | term()</c>
+ - some explanation of what went wrong</p>
+
+ <marker id="account"></marker>
+ </section>
+
+ <funcs>
+
+ <func>
+ <name>account(Pid, Account) -> ok | {error, Reason}</name>
+ <fsummary>Specifies which account to use.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Account = string()</v>
+ <v>Reason = eacct | common_reason()</v>
+ </type>
+ <desc>
+ <p>Sets the account for an operation, if needed.</p>
+
+ <marker id="append"></marker>
+ <marker id="append2"></marker>
+ <marker id="append3"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>append(Pid, LocalFile) -> </name>
+ <name>append(Pid, LocalFile, RemoteFile) -> ok | {error, Reason}</name>
+ <fsummary>Transfers a file to remote server, and appends it to
+ <c>Remotefile</c>.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>LocalFile = RemoteFile = string()</v>
+ <v>Reason = epath | elogin | etnospc | epnospc | efnamena | common_reason</v>
+ </type>
+ <desc>
+ <p>Transfers the file <c>LocalFile</c> to the remote server. If
+ <c>RemoteFile</c> is specified, the name of the remote file that the
+ file is appended to is set to <c>RemoteFile</c>, otherwise
+ to <c>LocalFile</c>. If the file does not exists,
+ it is created.</p>
+
+ <marker id="append_bin"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>append_bin(Pid, Bin, RemoteFile) -> ok | {error, Reason}</name>
+ <fsummary>Transfers a binary into a remote file.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Bin = binary()</v>
+ <v>RemoteFile = string()</v>
+ <v>Reason = restriction_reason()| shortage_reason() | common_reason()</v>
+ </type>
+ <desc>
+ <p>Transfers the binary <c>Bin</c> to the remote server and appends
+ it to the file <c>RemoteFile</c>. If the file does not exist, it
+ is created.</p>
+
+ <marker id="append_chunk"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>append_chunk(Pid, Bin) -> ok | {error, Reason}</name>
+ <fsummary>Appends a chunk to the remote file.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Bin = binary()</v>
+ <v>Reason = echunk | restriction_reason() | common_reason()</v>
+ </type>
+ <desc>
+ <p>Transfers the chunk <c>Bin</c> to the remote server, which
+ appends it to the file specified in the call to
+ <c>append_chunk_start/2</c>.</p>
+ <p>For some errors, for example, file system full, it is
+ necessary to call <c>append_chunk_end</c> to get the
+ proper reason.</p>
+
+ <marker id="append_chunk_start"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>append_chunk_start(Pid, File) -> ok | {error, Reason}</name>
+ <fsummary>Starts transfer of file chunks for appending to <c>File</c>.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>File = string()</v>
+ <v>Reason = restriction_reason() | common_reason()</v>
+ </type>
+ <desc>
+ <p>Starts the transfer of chunks for appending to the file
+ <c>File</c> at the remote server. If the file does not exist,
+ it is created.</p>
+
+ <marker id="append_chunk_end"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>append_chunk_end(Pid) -> ok | {error, Reason}</name>
+ <fsummary>Stops transfer of chunks for appending.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Reason = echunk | restriction_reason() | shortage_reason() </v>
+ </type>
+ <desc>
+ <p>Stops transfer of chunks for appending to the remote server.
+ The file at the remote server, specified in the call to
+ <c>append_chunk_start/2</c>, is closed by the server.</p>
+
+ <marker id="cd"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>cd(Pid, Dir) -> ok | {error, Reason}</name>
+ <fsummary>Changes remote working directory.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Dir = string()</v>
+ <v>Reason = restriction_reason() | common_reason() </v>
+ </type>
+ <desc>
+ <p>Changes the working directory at the remote server to
+ <c>Dir</c>.</p>
+
+ <marker id="close"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>close(Pid) -> ok</name>
+ <fsummary>Ends the FTP session.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ </type>
+ <desc>
+ <p>Ends an FTP session, created using function
+ <seealso marker="#open">open</seealso>.</p>
+
+ <marker id="delete"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>delete(Pid, File) -> ok | {error, Reason}</name>
+ <fsummary>Deletes a file at the remote server.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>File = string()</v>
+ <v>Reason = restriction_reason() | common_reason()</v>
+ </type>
+ <desc>
+ <p>Deletes the file <c>File</c> at the remote server.</p>
+
+ <marker id="append"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>formaterror(Tag) -> string()</name>
+ <fsummary>Returns error diagnostics.</fsummary>
+ <type>
+ <v>Tag = {error, atom()} | atom()</v>
+ </type>
+ <desc>
+ <p>Given an error return value <c>{error, AtomReason}</c>,
+ this function returns a readable string describing the error.</p>
+
+ <marker id="lcd"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>lcd(Pid, Dir) -> ok | {error, Reason}</name>
+ <fsummary>Changes local working directory.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Dir = string()</v>
+ <v>Reason = restriction_reason()</v>
+ </type>
+ <desc>
+ <p>Changes the working directory to <c>Dir</c> for the local client.</p>
+
+ <marker id="lpwd"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>lpwd(Pid) -> {ok, Dir}</name>
+ <fsummary>Gets local current working directory.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ </type>
+ <desc>
+ <p>Returns the current working directory at the local client.</p>
+
+ <marker id="ls"></marker>
+ <marker id="ls1"></marker>
+ <marker id="ls2"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>ls(Pid) -> </name>
+ <name>ls(Pid, Pathname) -> {ok, Listing} | {error, Reason}</name>
+ <fsummary>List of files.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Pathname = string()</v>
+ <v>Listing = string()</v>
+ <v>Reason = restriction_reason() | common_reason()</v>
+ </type>
+ <desc>
+ <p>Returns a list of files in long format.</p>
+ <p><c>Pathname</c> can be a directory, a group of files, or
+ a file. The <c>Pathname</c> string can contain wildcards.</p>
+ <p><c>ls/1</c> implies the current remote directory of the user.</p>
+ <p>The format of <c>Listing</c> depends on the operating system.
+ On UNIX, it is typically produced from the output of the
+ <c>ls -l</c> shell command.</p>
+
+ <marker id="mkdir"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>mkdir(Pid, Dir) -> ok | {error, Reason}</name>
+ <fsummary>Creates a remote directory.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Dir = string()</v>
+ <v>Reason = restriction_reason() | common_reason()</v>
+ </type>
+ <desc>
+ <p>Creates the directory <c>Dir</c> at the remote server.</p>
+
+ <marker id="nlist"></marker>
+ <marker id="nlist1"></marker>
+ <marker id="nlist2"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>nlist(Pid) -> </name>
+ <name>nlist(Pid, Pathname) -> {ok, Listing} | {error, Reason}</name>
+ <fsummary>List of files.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Pathname = string()</v>
+ <v>Listing = string()</v>
+ <v>Reason = restriction_reason() | common_reason()</v>
+ </type>
+ <desc>
+ <p>Returns a list of files in short format.</p>
+ <p><c>Pathname</c> can be a directory, a group of files, or
+ a file. The <c>Pathname</c> string can contain wildcards.</p>
+ <p><c>nlist/1</c> implies the current remote directory of the user.</p>
+ <p>The format of <c>Listing</c> is a stream of
+ filenames where each filename is separated by &lt;CRLF&gt; or
+ &lt;NL&gt;. Contrary to function <c>ls</c>, the purpose of
+ <c>nlist</c> is to enable a program to
+ process filename information automatically.</p>
+
+ <marker id="open"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>open(Host) -> {ok, Pid} | {error, Reason}</name>
+ <name>open(Host, Opts) -> {ok, Pid} | {error, Reason}</name>
+ <fsummary>Starts a standalone FTP client.</fsummary>
+ <type>
+ <v>Host = string() | ip_address()</v>
+ <v>Opts = options()</v>
+ <v>options() = [option()]</v>
+ <v>option() = start_option() | open_option()</v>
+ <v>start_option() = {verbose, verbose()} | {debug, debug()}</v>
+ <v>verbose() = boolean() (default is false)</v>
+ <v>debug() = disable | debug | trace (default is disable)</v>
+ <v>open_option() = {ipfamily, ipfamily()} | {port, port()} | {mode, mode()} | {tls, tls_options()} | {timeout, timeout()} | {dtimeout, dtimeout()} | {progress, progress() | {sock_ctrl, sock_opts()} | {sock_data_act, sock_opts()} | {sock_data_pass, sock_opts()} }</v>
+ <v>ipfamily() = inet | inet6 | inet6fb4 (default is inet)</v>
+ <v>port() = integer() > 0 (default is 21)</v>
+ <v>mode() = active | passive (default is passive)</v>
+ <v>tls_options() = [<seealso marker="ssl:ssl#type-ssloption">ssl:ssloption()</seealso>]</v>
+ <v>sock_opts() = [<seealso marker="kernel:gen_tcp#type-option">gen_tcp:option()</seealso> except for ipv6_v6only, active, packet, mode, packet_size and header</v>
+ <v>timeout() = integer() > 0 (default is 60000 milliseconds)</v>
+ <v>dtimeout() = integer() > 0 | infinity (default is infinity)</v>
+ <v>pogress() = ignore | {module(), function(), initial_data()} (default is ignore)</v>
+ <v>module() = atom()</v>
+ <v>function() = atom()</v>
+ <v>initial_data() = term()</v>
+ <v>Reason = ehost | term()</v>
+ </type>
+
+ <desc>
+ <p>Starts a standalone FTP client process
+ (without the <c>ftp</c> service framework) and
+ opens a session with the FTP server at <c>Host</c>. </p>
+
+ <p>If option <c>{tls, tls_options()}</c> is present, the FTP session
+ is transported over <c>tls</c> (<c>ftps</c>, see
+ <url href="http://www.ietf.org/rfc/rfc4217.txt">RFC 4217</url>).
+ The list <c>tls_options()</c> can be empty. The function
+ <seealso marker="ssl:ssl#connect/3"><c>ssl:connect/3</c></seealso>
+ is used for securing both the control connection and the data sessions.
+ </p>
+
+ <p>The options <c>sock_ctrl</c>, <c>sock_data_act</c> and <c>sock_data_pass</c> passes options down to
+ the underlying transport layer (tcp). The default value for <c>sock_ctrl</c> is <c>[]</c>. Both
+ <c>sock_data_act</c> and <c>sock_data_pass</c> uses the value of <c>sock_ctrl</c> as default value.
+ </p>
+
+ <p>A session opened in this way is closed using function
+ <seealso marker="#close">close</seealso>.</p>
+
+ <marker id="pwd"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>pwd(Pid) -> {ok, Dir} | {error, Reason}</name>
+ <fsummary>Gets the remote current working directory.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Reason = restriction_reason() | common_reason()</v>
+ </type>
+ <desc>
+ <p>Returns the current working directory at the remote server.</p>
+
+ <marker id="recv"></marker>
+ <marker id="recv2"></marker>
+ <marker id="recv3"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>recv(Pid, RemoteFile) -> </name>
+ <name>recv(Pid, RemoteFile, LocalFile) -> ok | {error, Reason}</name>
+ <fsummary>Transfers a file from remote server.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>RemoteFile = LocalFile = string()</v>
+ <v>Reason = restriction_reason() | common_reason() | file_write_error_reason() </v>
+ <v>file_write_error_reason() = see file:write/2</v>
+ </type>
+ <desc>
+ <p>Transfers the file <c>RemoteFile</c> from the remote server
+ to the file system of the local client. If
+ <c>LocalFile</c> is specified, the local file will be
+ <c>LocalFile</c>, otherwise
+ <c>RemoteFile</c>.</p>
+ <p>If the file write fails (for example, <c>enospc</c>), the command is
+ aborted and <c>{error, file_write_error_reason()}</c> is returned.
+ However, the file is <em>not</em> removed.</p>
+
+ <marker id="recv_bin"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>recv_bin(Pid, RemoteFile) -> {ok, Bin} | {error, Reason}</name>
+ <fsummary>Transfers a file from remote server as a binary.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Bin = binary()</v>
+ <v>RemoteFile = string()</v>
+ <v>Reason = restriction_reason() | common_reason()</v>
+ </type>
+ <desc>
+ <p>Transfers the file <c>RemoteFile</c> from the remote server and
+ receives it as a binary.</p>
+
+ <marker id="recv_chunk_start"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>recv_chunk_start(Pid, RemoteFile) -> ok | {error, Reason}</name>
+ <fsummary>Starts chunk-reading of the remote file.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>RemoteFile = string()</v>
+ <v>Reason = restriction_reason() | common_reason()</v>
+ </type>
+ <desc>
+ <p>Starts transfer of the file <c>RemoteFile</c> from the
+ remote server.</p>
+
+ <marker id="recv_chunk"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>recv_chunk(Pid) -> ok | {ok, Bin} | {error, Reason}</name>
+ <fsummary>Receives a chunk of the remote file.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Bin = binary()</v>
+ <v>Reason = restriction_reason() | common_reason()</v>
+ </type>
+ <desc>
+ <p>Receives a chunk of the remote file (<c>RemoteFile</c> of
+ <c>recv_chunk_start</c>). The return values have the following
+ meaning:</p>
+ <list type="bulleted">
+ <item><c>ok</c> = the transfer is complete.</item>
+ <item><c>{ok, Bin}</c> = just another chunk of the file.</item>
+ <item><c>{error, Reason}</c> = transfer failed.</item>
+ </list>
+
+ <marker id="rename"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>rename(Pid, Old, New) -> ok | {error, Reason}</name>
+ <fsummary>Renames a file at the remote server.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>CurrFile = NewFile = string()</v>
+ <v>Reason = restriction_reason() | common_reason()</v>
+ </type>
+ <desc>
+ <p>Renames <c>Old</c> to <c>New</c> at the remote server.</p>
+
+ <marker id="rmdir"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>rmdir(Pid, Dir) -> ok | {error, Reason}</name>
+ <fsummary>Removes a remote directory.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Dir = string()</v>
+ <v>Reason = restriction_reason() | common_reason()</v>
+ </type>
+ <desc>
+ <p>Removes directory <c>Dir</c> at the remote server.</p>
+
+ <marker id="send"></marker>
+ <marker id="send2"></marker>
+ <marker id="send3"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>send(Pid, LocalFile) -></name>
+ <name>send(Pid, LocalFile, RemoteFile) -> ok | {error, Reason}</name>
+ <fsummary>Transfers a file to the remote server.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>LocalFile = RemoteFile = string()</v>
+ <v>Reason = restriction_reason() | common_reason() | shortage_reason()</v>
+ </type>
+ <desc>
+ <p>Transfers the file <c>LocalFile</c> to the remote server. If
+ <c>RemoteFile</c> is specified, the name of the remote file is set
+ to <c>RemoteFile</c>, otherwise to <c>LocalFile</c>.</p>
+
+ <marker id="send_bin"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>send_bin(Pid, Bin, RemoteFile) -> ok | {error, Reason}</name>
+ <fsummary>Transfers a binary into a remote file.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Bin = binary()</v>
+ <v>RemoteFile = string()</v>
+ <v>Reason = restriction_reason() | common_reason() | shortage_reason()</v>
+ </type>
+ <desc>
+ <p>Transfers the binary <c>Bin</c> into the file <c>RemoteFile</c>
+ at the remote server.</p>
+
+ <marker id="send_chunk"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>send_chunk(Pid, Bin) -> ok | {error, Reason}</name>
+ <fsummary>Writes a chunk to the remote file.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Bin = binary()</v>
+ <v>Reason = echunk | restriction_reason() | common_reason()</v>
+ </type>
+ <desc>
+ <p>Transfers the chunk <c>Bin</c> to the remote server, which
+ writes it into the file specified in the call to
+ <c>send_chunk_start/2</c>.</p>
+ <p>For some errors, for example, file system full, it is
+ necessary to to call <c>send_chunk_end</c> to get the
+ proper reason.</p>
+
+ <marker id="send_chunk_start"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>send_chunk_start(Pid, File) -> ok | {error, Reason}</name>
+ <fsummary>Starts transfer of file chunks.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>File = string()</v>
+ <v>Reason = restriction_reason() | common_reason()</v>
+ </type>
+ <desc>
+ <p>Starts transfer of chunks into the file <c>File</c> at the
+ remote server.</p>
+
+ <marker id="send_chunk_end"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>send_chunk_end(Pid) -> ok | {error, Reason}</name>
+ <fsummary>Stops transfer of chunks.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Reason = restriction_reason() | common_reason() | shortage_reason()</v>
+ </type>
+ <desc>
+ <p>Stops transfer of chunks to the remote server. The file at the
+ remote server, specified in the call to <c>send_chunk_start/2</c>
+ is closed by the server.</p>
+
+ <marker id="type"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>start_service(ServiceConfig) -> {ok, Pid} | {error, Reason}</name>
+ <fsummary>Dynamically starts an <c>FTP</c>
+ session after the <c>ftp</c> application has been started.</fsummary>
+ <type>
+ <v>ServiceConfig = [{Option, Value}]</v>
+ <v>Option = property()</v>
+ <v>Value = term()</v>
+ </type>
+ <desc>
+ <p>Dynamically starts an <c>FTP</c> session after the <c>ftp</c>
+ application has been started.</p>
+ <note>
+ <p>As long as the <c>ftp</c> application is operational,
+ the FTP sessions are supervised and can be soft code upgraded.</p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
+ <name>stop_service(Reference) -> ok | {error, Reason} </name>
+ <fsummary>Stops an FTP session.</fsummary>
+ <type>
+ <v>Reference = pid() | term() - service-specified reference</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Stops a started FTP session.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>type(Pid, Type) -> ok | {error, Reason}</name>
+ <fsummary>Sets transfer type to <c>ascii</c>or <c>binary</c>.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Type = ascii | binary</v>
+ <v>Reason = etype | restriction_reason() | common_reason()</v>
+ </type>
+ <desc>
+ <p>Sets the file transfer type to <c>ascii</c> or <c>binary</c>. When
+ an FTP session is opened, the default transfer type of the
+ server is used, most often <c>ascii</c>, which is default
+ according to <url href="http://www.ietf.org/rfc/rfc959.txt">RFC 959</url>.</p>
+ <marker id="user3"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>user(Pid, User, Password) -> ok | {error, Reason}</name>
+ <fsummary>User login.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>User = Password = string()</v>
+ <v>Reason = euser | common_reason()</v>
+ </type>
+ <desc>
+ <p>Performs login of <c>User</c> with <c>Password</c>.</p>
+
+ <marker id="user4"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>user(Pid, User, Password, Account) -> ok | {error, Reason}</name>
+ <fsummary>User login.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>User = Password = string()</v>
+ <v>Reason = euser | common_reason() </v>
+ </type>
+ <desc>
+ <p>Performs login of <c>User</c> with <c>Password</c> to the account
+ specified by <c>Account</c>.</p>
+
+ <marker id="quote"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>quote(Pid, Command) -> [FTPLine]</name>
+ <fsummary>Sends an arbitrary FTP command.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Command = string()</v>
+ <v>FTPLine = string(</v>
+ </type>
+ <desc><note><p>The telnet end of line characters, from the FTP
+ protocol definition, CRLF, for example, "\\r\\n" has been removed.</p></note>
+ <p>Sends an arbitrary FTP command and returns verbatim a list
+ of the lines sent back by the FTP server. This function is
+ intended to give application accesses to FTP commands
+ that are server-specific or that cannot be provided by
+ this FTP client.</p>
+ <note>
+ <p>FTP commands requiring a data connection cannot be
+ successfully issued with this function.</p>
+ </note>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <title>ERRORS</title>
+ <p>The possible error reasons and the corresponding diagnostic strings
+ returned by <c>formaterror/1</c> are as follows:
+ </p>
+ <taglist>
+ <tag><c>echunk</c></tag>
+ <item>
+ <p>Synchronization error during chunk sending according to one
+ of the following:
+ </p><list type="bulleted">
+ <item>A call is made to <c>send_chunk/2</c> or <c>send_chunk_end/1</c>
+ before a call to <c>send_chunk_start/2</c>.</item>
+ <item>A call has been made to another transfer function during chunk
+ sending, that is, before a call to <c>send_chunk_end/1</c>.</item>
+ </list>
+ </item>
+ <tag><c>eclosed</c></tag>
+ <item>
+ <p>The session is closed.</p>
+ </item>
+ <tag><c>econn</c></tag>
+ <item>
+ <p>Connection to the remote server is prematurely closed.</p>
+ </item>
+ <tag><c>ehost</c></tag>
+ <item>
+ <p>Host is not found, FTP server is not found, or connection is rejected
+ by FTP server.</p>
+ </item>
+ <tag><c>elogin</c></tag>
+ <item>
+ <p>User is not logged in.</p>
+ </item>
+ <tag><c>enotbinary</c></tag>
+ <item>
+ <p>Term is not a binary.</p>
+ </item>
+ <tag><c>epath</c></tag>
+ <item>
+ <p>No such file or directory, or directory already exists, or
+ permission denied.</p>
+ </item>
+ <tag><c>etype</c></tag>
+ <item>
+ <p>No such type.</p>
+ </item>
+ <tag><c>euser</c></tag>
+ <item>
+ <p>Invalid username or password.</p>
+ </item>
+ <tag><c>etnospc</c></tag>
+ <item>
+ <p>Insufficient storage space in system [452].</p>
+ </item>
+ <tag><c>epnospc</c></tag>
+ <item>
+ <p>Exceeded storage allocation (for current directory or
+ dataset) [552].</p>
+ </item>
+ <tag><c>efnamena</c></tag>
+ <item>
+ <p>Filename not allowed [553].</p>
+ </item>
+ </taglist>
+ </section>
+
+ <section>
+ <title>SEE ALSO</title>
+ <p><seealso marker="kernel:file">file(3)</seealso>
+ <seealso marker="stdlib:filename">filename(3)</seealso>
+ and J. Postel and J. Reynolds: File Transfer Protocol
+ (<url href="http://www.ietf.org/rfc/rfc959.txt">RFC 959</url>).
+ </p>
+ </section>
+
+</erlref>
+
+
diff --git a/lib/ftp/doc/src/ftp_client.xml b/lib/ftp/doc/src/ftp_client.xml
new file mode 100644
index 0000000000..047b055be7
--- /dev/null
+++ b/lib/ftp/doc/src/ftp_client.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2004</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>FTP Client</title>
+ <prepared>Péter Dimitrov</prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev></rev>
+ <file>ftp_client.xml</file>
+ </header>
+
+ <section>
+ <title>Getting Started</title>
+
+ <p>FTP clients are considered to be rather temporary. Thus,
+ they are only started and stopped during runtime and cannot
+ be started at application startup.
+ The FTP client API is designed to allow some functions to
+ return intermediate results. This implies that only the process
+ that started the FTP client can access it with
+ preserved sane semantics.
+ If the process that started the FTP session
+ dies, the FTP client process terminates.</p>
+
+ <p>The client supports IPv6 as long as the underlying mechanisms
+ also do so.</p>
+
+ <p>The following is a simple example of an FTP session, where
+ the user <c>guest</c> with password <c>password</c> logs on to
+ the remote host <c>erlang.org</c>:</p>
+ <code type="erl"><![CDATA[
+ 1> ftp:start().
+ ok
+ 2> {ok, Pid} = ftp:start_service([{host, "erlang.org"}]).
+ {ok,<0.22.0>}
+ 3> ftp:user(Pid, "guest", "password").
+ ok
+ 4> ftp:pwd(Pid).
+ {ok, "/home/guest"}
+ 5> ftp:cd(Pid, "appl/examples").
+ ok
+ 6> ftp:lpwd(Pid).
+ {ok, "/home/fred"}.
+ 7> ftp:lcd(Pid, "/home/eproj/examples").
+ ok
+ 8> ftp:recv(Pid, "appl.erl").
+ ok
+ 9> ftp:stop_service(Pid).
+ ok
+ 10> ftp:stop().
+ ok
+ ]]></code>
+ <p> The file
+ <c>appl.erl</c> is transferred from the remote to the local
+ host. When the session is opened, the current directory at
+ the remote host is <c>/home/guest</c>, and <c>/home/fred</c>
+ at the local host. Before transferring the file, the current
+ local directory is changed to <c>/home/eproj/examples</c>, and
+ the remote directory is set to
+ <c>/home/guest/appl/examples</c>.</p>
+ </section>
+</chapter>
diff --git a/lib/ftp/doc/src/introduction.xml b/lib/ftp/doc/src/introduction.xml
new file mode 100644
index 0000000000..cc3673a0fc
--- /dev/null
+++ b/lib/ftp/doc/src/introduction.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>1997</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>Introduction</title>
+ <prepared>Péter Dimitrov</prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date>2018-02-26</date>
+ <rev>A</rev>
+ <file>introduction.xml</file>
+ </header>
+
+ <section>
+ <title>Purpose</title>
+ <p>An <c>FTP</c> client.</p>
+ </section>
+
+ <section>
+ <title>Prerequisites</title>
+ <p>It is assumed that the reader is familiar with the Erlang
+ programming language, concepts of OTP, and has a basic
+ understanding of the FTP protocol.</p>
+ </section>
+</chapter>
diff --git a/lib/ftp/doc/src/notes.xml b/lib/ftp/doc/src/notes.xml
new file mode 100644
index 0000000000..01c1f88cf1
--- /dev/null
+++ b/lib/ftp/doc/src/notes.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2002</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>FTP Release Notes</title>
+ <prepared></prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date>2018-02-26</date>
+ <rev>A</rev>
+ <file>notes.xml</file>
+ </header>
+
+ <section><title>Ftp 1.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>FTP 1.0</title>
+
+ <section><title>First released version</title>
+ <list>
+ <item>
+ <p>
+ Inets application was split into multiple smaller protocol specific applications.
+ The FTP application is a standalone FTP client with the same functionality as
+ FTP client in Inets.</p>
+ <p>
+ Own Id: OTP-14113</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+</chapter>
diff --git a/lib/ftp/doc/src/part.xml b/lib/ftp/doc/src/part.xml
new file mode 100644
index 0000000000..ec05f5ac76
--- /dev/null
+++ b/lib/ftp/doc/src/part.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE part SYSTEM "part.dtd">
+
+<part xmlns:xi="http://www.w3.org/2001/XInclude">
+ <header>
+ <copyright>
+ <year>2004</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>FTP User's Guide</title>
+ <prepared>Péter Dimitrov</prepared>
+ <docno></docno>
+ <date>2018-02-26</date>
+ <rev>A</rev>
+ <file>part.sgml</file>
+ </header>
+ <description>
+ <p>The <c>FTP</c> application provides an FTP client.</p>
+ </description>
+ <xi:include href="introduction.xml"/>
+ <xi:include href="ftp_client.xml"/>
+</part>
diff --git a/lib/ftp/doc/src/ref_man.xml b/lib/ftp/doc/src/ref_man.xml
new file mode 100644
index 0000000000..925842610d
--- /dev/null
+++ b/lib/ftp/doc/src/ref_man.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE application SYSTEM "application.dtd">
+
+<application xmlns:xi="http://www.w3.org/2001/XInclude">
+ <header>
+ <copyright>
+ <year>1997</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>FTP Reference Manual</title>
+ <prepared>Péter Dimitrov</prepared>
+ <docno></docno>
+ <date>2018-03-09</date>
+ <rev>1.0</rev>
+ <file>ref_man.xml</file>
+ </header>
+ <description>
+ <p>An <c>FTP</c> client.</p>
+ </description>
+ <xi:include href="ftp.xml"/>
+</application>
diff --git a/lib/cosEvent/ebin/.gitignore b/lib/ftp/ebin/.gitignore
index e69de29bb2..e69de29bb2 100644
--- a/lib/cosEvent/ebin/.gitignore
+++ b/lib/ftp/ebin/.gitignore
diff --git a/lib/ftp/info b/lib/ftp/info
new file mode 100644
index 0000000000..f6c62d19c2
--- /dev/null
+++ b/lib/ftp/info
@@ -0,0 +1,2 @@
+group: comm
+short: FTP client
diff --git a/lib/ftp/src/Makefile b/lib/ftp/src/Makefile
new file mode 100644
index 0000000000..93e3c4a8e5
--- /dev/null
+++ b/lib/ftp/src/Makefile
@@ -0,0 +1,118 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1999-2018. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# %CopyrightEnd%
+#
+
+#
+
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+VSN=$(FTP_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/ftp-$(VSN)
+
+# ----------------------------------------------------
+# Common Macros
+# ----------------------------------------------------
+
+BEHAVIOUR_MODULES=
+
+MODULES= \
+ ftp \
+ ftp_app \
+ ftp_progress \
+ ftp_response \
+ ftp_sup
+
+
+INTERNAL_HRL_FILES =
+
+ERL_FILES= \
+ $(MODULES:%=%.erl) \
+ $(BEHAVIOUR_MODULES:%=%.erl)
+
+
+TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+BEHAVIOUR_TARGET_FILES= $(BEHAVIOUR_MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+APP_FILE= ftp.app
+APPUP_FILE= ftp.appup
+
+APP_SRC= $(APP_FILE).src
+APP_TARGET= $(EBIN)/$(APP_FILE)
+APPUP_SRC= $(APPUP_FILE).src
+APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+EXTRA_ERLC_FLAGS = +warn_unused_vars
+ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/kernel/src \
+ -pz $(EBIN) \
+ -pz $(ERL_TOP)/lib/public_key/ebin \
+ $(EXTRA_ERLC_FLAGS) -DVSN=\"$(VSN)\"
+
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+$(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES)
+
+debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+
+clean:
+ rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(BEHAVIOUR_TARGET_FILES)
+ rm -f errs core *~
+
+$(APP_TARGET): $(APP_SRC) ../vsn.mk
+ $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
+
+$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
+ $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
+
+docs:
+
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(BEHAVIOUR_TARGET_FILES) $(TARGET_FILES) $(APP_TARGET) \
+ $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
+
+release_docs_spec:
+
+# ----------------------------------------------------
+# Dependencies
+# ----------------------------------------------------
+
diff --git a/lib/ftp/src/ftp.app.src b/lib/ftp/src/ftp.app.src
new file mode 100644
index 0000000000..66ccace390
--- /dev/null
+++ b/lib/ftp/src/ftp.app.src
@@ -0,0 +1,19 @@
+{application, ftp,
+ [{description, "FTP client"},
+ {vsn, "%VSN%"},
+ {registered, []},
+ {mod, { ftp_app, []}},
+ {applications,
+ [kernel,
+ stdlib
+ ]},
+ {env,[]},
+ {modules, [
+ ftp,
+ ftp_app,
+ ftp_progress,
+ ftp_response,
+ ftp_sup
+ ]},
+ {runtime_dependencies, ["erts-7.0","stdlib-3.5","kernel-6.0"]}
+ ]}.
diff --git a/lib/ftp/src/ftp.appup.src b/lib/ftp/src/ftp.appup.src
new file mode 100644
index 0000000000..d79c7b60ff
--- /dev/null
+++ b/lib/ftp/src/ftp.appup.src
@@ -0,0 +1,26 @@
+%% -*- erlang -*-
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+{"%VSN%",
+ [
+ {<<".*">>,[{restart_application, ftp}]}
+ ],
+ [
+ {<<".*">>,[{restart_application, ftp}]}
+ ]
+}.
diff --git a/lib/ftp/src/ftp.erl b/lib/ftp/src/ftp.erl
new file mode 100644
index 0000000000..40f6b53fa3
--- /dev/null
+++ b/lib/ftp/src/ftp.erl
@@ -0,0 +1,2618 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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(ftp).
+
+-behaviour(gen_server).
+
+-export([start/0,
+ start_service/1,
+ stop/0,
+ stop_service/1,
+ services/0,
+ service_info/1
+ ]).
+
+%% Added for backward compatibility
+-export([start_standalone/1]).
+
+-export([start_link/1, start_link/2]).
+
+%% API - Client interface
+-export([cd/2, close/1, delete/2, formaterror/1,
+ lcd/2, lpwd/1, ls/1, ls/2,
+ mkdir/2, nlist/1, nlist/2,
+ open/1, open/2,
+ pwd/1, quote/2,
+ recv/2, recv/3, recv_bin/2,
+ recv_chunk_start/2, recv_chunk/1,
+ rename/3, rmdir/2,
+ send/2, send/3, send_bin/3,
+ send_chunk_start/2, send_chunk/2, send_chunk_end/1,
+ type/2, user/3, user/4, account/2,
+ append/3, append/2, append_bin/3,
+ append_chunk/2, append_chunk_end/1, append_chunk_start/2,
+ info/1, latest_ctrl_response/1]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2,
+ handle_info/2, terminate/2, code_change/3]).
+
+-include("ftp_internal.hrl").
+
+%% Constants used in internal state definition
+-define(CONNECTION_TIMEOUT, 60*1000).
+-define(DATA_ACCEPT_TIMEOUT, infinity).
+-define(DEFAULT_MODE, passive).
+-define(PROGRESS_DEFAULT, ignore).
+-define(FTP_EXT_DEFAULT, false).
+
+%% Internal Constants
+-define(FTP_PORT, 21).
+-define(FILE_BUFSIZE, 4096).
+
+
+%%%=========================================================================
+%%% Data Types
+%%%=========================================================================
+
+%% Internal state
+-record(state, {
+ csock = undefined, % socket() - Control connection socket
+ dsock = undefined, % socket() - Data connection socket
+ tls_options = undefined, % list()
+ verbose = false, % boolean()
+ ldir = undefined, % string() - Current local directory
+ type = ftp_server_default, % atom() - binary | ascii
+ chunk = false, % boolean() - Receiving data chunks
+ mode = ?DEFAULT_MODE, % passive | active
+ timeout = ?CONNECTION_TIMEOUT, % integer()
+ %% Data received so far on the data connection
+ data = <<>>, % binary()
+ %% Data received so far on the control connection
+ %% {BinStream, AccLines}. If a binary sequence
+ %% ends with ?CR then keep it in the binary to
+ %% be able to detect if the next received byte is ?LF
+ %% and hence the end of the response is reached!
+ ctrl_data = {<<>>, [], start}, % {binary(), [bytes()], LineStatus}
+ %% pid() - Client pid (note not the same as "From")
+ latest_ctrl_response = "",
+ owner = undefined,
+ client = undefined, % "From" to be used in gen_server:reply/2
+ %% Function that activated a connection and maybe some
+ %% data needed further on.
+ caller = undefined, % term()
+ ipfamily, % inet | inet6 | inet6fb4
+ sockopts_ctrl = [],
+ sockopts_data_passive = [],
+ sockopts_data_active = [],
+ progress = ignore, % ignore | pid()
+ dtimeout = ?DATA_ACCEPT_TIMEOUT, % non_neg_integer() | infinity
+ tls_upgrading_data_connection = false,
+ ftp_extension = ?FTP_EXT_DEFAULT
+ }).
+
+-record(recv_chunk_closing, {
+ dconn_closed = false,
+ pos_compl_received = false,
+ client_called_us = false
+ }).
+
+
+-type shortage_reason() :: 'etnospc' | 'epnospc'.
+-type restriction_reason() :: 'epath' | 'efnamena' | 'elogin' | 'enotbinary'.
+-type common_reason() :: 'econn' | 'eclosed' | term().
+-type file_write_error_reason() :: term(). % See file:write for more info
+
+-define(DBG(F,A), 'n/a').
+%%-define(DBG(F,A), io:format(F,A)).
+%%-define(DBG(F,A), ct:pal("~p:~p " ++ if is_list(F) -> F; is_atom(F) -> atom_to_list(F) end, [?MODULE,?LINE|A])).
+
+
+%%%=========================================================================
+%%% API
+%%%=========================================================================
+
+start() ->
+ application:start(ftp).
+
+start_standalone(Options) ->
+ try
+ {ok, StartOptions} = start_options(Options),
+ {ok, OpenOptions} = open_options(Options),
+ {ok, SocketOptions} = socket_options(Options),
+ case start_link(StartOptions, []) of
+ {ok, Pid} ->
+ call(Pid, {open, ip_comm, OpenOptions, SocketOptions}, plain);
+ Error1 ->
+ Error1
+ end
+ catch
+ throw:Error2 ->
+ Error2
+ end.
+
+start_service(Options) ->
+ try
+ {ok, StartOptions} = start_options(Options),
+ {ok, OpenOptions} = open_options(Options),
+ {ok, SocketOptions} = socket_options(Options),
+ case ftp_sup:start_child([[[{client, self()} | StartOptions], []]]) of
+ {ok, Pid} ->
+ call(Pid, {open, ip_comm, OpenOptions, SocketOptions}, plain);
+ Error1 ->
+ Error1
+ end
+ catch
+ throw:Error2 ->
+ Error2
+ end.
+
+stop() ->
+ application:stop(ftp).
+
+stop_service(Pid) ->
+ close(Pid).
+
+services() ->
+ [{ftpc, Pid} || {_, Pid, _, _} <-
+ supervisor:which_children(ftp_sup)].
+service_info(Pid) ->
+ {ok, Info} = call(Pid, info, list),
+ {ok, [proplists:lookup(mode, Info),
+ proplists:lookup(local_port, Info),
+ proplists:lookup(peer, Info),
+ proplists:lookup(peer_port, Info)]}.
+
+
+%%%=========================================================================
+%%% API - CLIENT FUNCTIONS
+%%%=========================================================================
+
+%%--------------------------------------------------------------------------
+%% open(HostOrOtpList, <Port>, <Flags>) -> {ok, Pid} | {error, ehost}
+%% HostOrOtpList = string() | [{option_list, Options}]
+%% Port = integer(),
+%% Flags = [Flag],
+%% Flag = verbose | debug | trace
+%%
+%% Description: Start an ftp client and connect to a host.
+%%--------------------------------------------------------------------------
+
+-spec open(Host :: string() | inet:ip_address()) ->
+ {'ok', Pid :: pid()} | {'error', Reason :: 'ehost' | term()}.
+
+%% <BACKWARD-COMPATIBILLITY>
+open({option_list, Options}) when is_list(Options) ->
+ try
+ {ok, StartOptions} = start_options(Options),
+ {ok, OpenOptions} = open_options(Options),
+ {ok, SockOpts} = socket_options(Options),
+ case ftp_sup:start_child([[[{client, self()} | StartOptions], []]]) of
+ {ok, Pid} ->
+ call(Pid, {open, ip_comm, OpenOptions, SockOpts}, plain);
+ Error1 ->
+ Error1
+ end
+ catch
+ throw:Error2 ->
+ Error2
+ end;
+%% </BACKWARD-COMPATIBILLITY>
+
+open(Host) ->
+ open(Host, []).
+
+-spec open(Host :: string() | inet:ip_address(), Opts :: list()) ->
+ {'ok', Pid :: pid()} | {'error', Reason :: 'ehost' | term()}.
+
+%% <BACKWARD-COMPATIBILLITY>
+open(Host, Port) when is_integer(Port) ->
+ open(Host, [{port, Port}]);
+%% </BACKWARD-COMPATIBILLITY>
+
+open(Host, Opts) when is_list(Opts) ->
+ try
+ {ok, StartOptions} = start_options(Opts),
+ {ok, OpenOptions} = open_options([{host, Host}|Opts]),
+ {ok, SocketOptions} = socket_options(Opts),
+ case start_link(StartOptions, []) of
+ {ok, Pid} ->
+ do_open(Pid, OpenOptions, SocketOptions, tls_options(Opts));
+ Error1 ->
+ Error1
+ end
+ catch
+ throw:Error2 ->
+ Error2
+ end.
+
+do_open(Pid, OpenOptions, SocketOptions, TLSOpts) ->
+ case call(Pid, {open, ip_comm, OpenOptions, SocketOptions}, plain) of
+ {ok, Pid} ->
+ maybe_tls_upgrade(Pid, TLSOpts);
+ Error ->
+ Error
+ end.
+%%--------------------------------------------------------------------------
+%% user(Pid, User, Pass, <Acc>) -> ok | {error, euser} | {error, econn}
+%% | {error, eacct}
+%% Pid = pid(),
+%% User = Pass = Acc = string()
+%%
+%% Description: Login with or without a supplied account name.
+%%--------------------------------------------------------------------------
+-spec user(Pid :: pid(),
+ User :: string(),
+ Pass :: string()) ->
+ 'ok' | {'error', Reason :: 'euser' | common_reason()}.
+
+user(Pid, User, Pass) ->
+ case {is_name_sane(User), is_name_sane(Pass)} of
+ {true, true} ->
+ call(Pid, {user, User, Pass}, atom);
+ _ ->
+ {error, euser}
+ end.
+
+-spec user(Pid :: pid(),
+ User :: string(),
+ Pass :: string(),
+ Acc :: string()) ->
+ 'ok' | {'error', Reason :: 'euser' | common_reason()}.
+
+user(Pid, User, Pass, Acc) ->
+ case {is_name_sane(User), is_name_sane(Pass), is_name_sane(Acc)} of
+ {true, true, true} ->
+ call(Pid, {user, User, Pass, Acc}, atom);
+ _ ->
+ {error, euser}
+ end.
+
+
+%%--------------------------------------------------------------------------
+%% account(Pid, Acc) -> ok | {error, eacct}
+%% Pid = pid()
+%% Acc= string()
+%%
+%% Description: Set a user Account.
+%%--------------------------------------------------------------------------
+
+-spec account(Pid :: pid(), Acc :: string()) ->
+ 'ok' | {'error', Reason :: 'eacct' | common_reason()}.
+
+account(Pid, Acc) ->
+ case is_name_sane(Acc) of
+ true ->
+ call(Pid, {account, Acc}, atom);
+ _ ->
+ {error, eacct}
+ end.
+
+
+%%--------------------------------------------------------------------------
+%% pwd(Pid) -> {ok, Dir} | {error, elogin} | {error, econn}
+%% Pid = pid()
+%% Dir = string()
+%%
+%% Description: Get the current working directory at remote server.
+%%--------------------------------------------------------------------------
+
+-spec pwd(Pid :: pid()) ->
+ {'ok', Dir :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
+pwd(Pid) ->
+ call(Pid, pwd, ctrl).
+
+
+%%--------------------------------------------------------------------------
+%% lpwd(Pid) -> {ok, Dir}
+%% Pid = pid()
+%% Dir = string()
+%%
+%% Description: Get the current working directory at local server.
+%%--------------------------------------------------------------------------
+
+-spec lpwd(Pid :: pid()) ->
+ {'ok', Dir :: string()}.
+
+lpwd(Pid) ->
+ call(Pid, lpwd, string).
+
+
+%%--------------------------------------------------------------------------
+%% cd(Pid, Dir) -> ok | {error, epath} | {error, elogin} | {error, econn}
+%% Pid = pid()
+%% Dir = string()
+%%
+%% Description: Change current working directory at remote server.
+%%--------------------------------------------------------------------------
+
+-spec cd(Pid :: pid(), Dir :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
+cd(Pid, Dir) ->
+ case is_name_sane(Dir) of
+ true ->
+ call(Pid, {cd, Dir}, atom);
+ _ ->
+ {error, efnamena}
+ end.
+
+
+%%--------------------------------------------------------------------------
+%% lcd(Pid, Dir) -> ok | {error, epath}
+%% Pid = pid()
+%% Dir = string()
+%%
+%% Description: Change current working directory for the local client.
+%%--------------------------------------------------------------------------
+
+-spec lcd(Pid :: pid(), Dir :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason()}.
+
+lcd(Pid, Dir) ->
+ call(Pid, {lcd, Dir}, string).
+
+
+%%--------------------------------------------------------------------------
+%% ls(Pid) -> Result
+%% ls(Pid, <Dir>) -> Result
+%%
+%% Pid = pid()
+%% Dir = string()
+%% Result = {ok, Listing} | {error, Reason}
+%% Listing = string()
+%% Reason = epath | elogin | econn
+%%
+%% Description: Returns a list of files in long format.
+%%--------------------------------------------------------------------------
+
+-spec ls(Pid :: pid()) ->
+ {'ok', Listing :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
+ls(Pid) ->
+ ls(Pid, "").
+
+-spec ls(Pid :: pid(), Dir :: string()) ->
+ {'ok', Listing :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
+ls(Pid, Dir) ->
+ case is_name_sane(Dir) of
+ true ->
+ call(Pid, {dir, long, Dir}, string);
+ _ ->
+ {error, efnamena}
+ end.
+
+
+%%--------------------------------------------------------------------------
+%% nlist(Pid) -> Result
+%% nlist(Pid, Pathname) -> Result
+%%
+%% Pid = pid()
+%% Pathname = string()
+%% Result = {ok, Listing} | {error, Reason}
+%% Listing = string()
+%% Reason = epath | elogin | econn
+%%
+%% Description: Returns a list of files in short format
+%%--------------------------------------------------------------------------
+
+-spec nlist(Pid :: pid()) ->
+ {'ok', Listing :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
+nlist(Pid) ->
+ nlist(Pid, "").
+
+-spec nlist(Pid :: pid(), Pathname :: string()) ->
+ {'ok', Listing :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
+nlist(Pid, Dir) ->
+ case is_name_sane(Dir) of
+ true ->
+ call(Pid, {dir, short, Dir}, string);
+ _ ->
+ {error, efnamena}
+ end.
+
+
+%%--------------------------------------------------------------------------
+%% rename(Pid, Old, New) -> ok | {error, epath} | {error, elogin}
+%% | {error, econn}
+%% Pid = pid()
+%% CurrFile = NewFile = string()
+%%
+%% Description: Rename a file at remote server.
+%%--------------------------------------------------------------------------
+
+-spec rename(Pid :: pid(), Old :: string(), New :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
+rename(Pid, Old, New) ->
+ case {is_name_sane(Old), is_name_sane(New)} of
+ {true, true} ->
+ call(Pid, {rename, Old, New}, string);
+ _ ->
+ {error, efnamena}
+ end.
+
+
+%%--------------------------------------------------------------------------
+%% delete(Pid, File) -> ok | {error, epath} | {error, elogin} |
+%% {error, econn}
+%% Pid = pid()
+%% File = string()
+%%
+%% Description: Remove file at remote server.
+%%--------------------------------------------------------------------------
+
+-spec delete(Pid :: pid(), File :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
+delete(Pid, File) ->
+ case is_name_sane(File) of
+ true ->
+ call(Pid, {delete, File}, string);
+ _ ->
+ {error, efnamena}
+ end.
+
+
+%%--------------------------------------------------------------------------
+%% mkdir(Pid, Dir) -> ok | {error, epath} | {error, elogin} | {error, econn}
+%% Pid = pid(),
+%% Dir = string()
+%%
+%% Description: Make directory at remote server.
+%%--------------------------------------------------------------------------
+
+-spec mkdir(Pid :: pid(), Dir :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
+mkdir(Pid, Dir) ->
+ case is_name_sane(Dir) of
+ true ->
+ call(Pid, {mkdir, Dir}, atom);
+ _ ->
+ {error, efnamena}
+ end.
+
+
+%%--------------------------------------------------------------------------
+%% rmdir(Pid, Dir) -> ok | {error, epath} | {error, elogin} | {error, econn}
+%% Pid = pid(),
+%% Dir = string()
+%%
+%% Description: Remove directory at remote server.
+%%--------------------------------------------------------------------------
+
+-spec rmdir(Pid :: pid(), Dir :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
+rmdir(Pid, Dir) ->
+ case is_name_sane(Dir) of
+ true ->
+ call(Pid, {rmdir, Dir}, atom);
+ _ ->
+ {error, efnamena}
+ end.
+
+
+%%--------------------------------------------------------------------------
+%% type(Pid, Type) -> ok | {error, etype} | {error, elogin} | {error, econn}
+%% Pid = pid()
+%% Type = ascii | binary
+%%
+%% Description: Set transfer type.
+%%--------------------------------------------------------------------------
+
+-spec type(Pid :: pid(), Type :: ascii | binary) ->
+ 'ok' |
+ {'error', Reason :: 'etype' | restriction_reason() | common_reason()}.
+
+type(Pid, Type) ->
+ call(Pid, {type, Type}, atom).
+
+
+%%--------------------------------------------------------------------------
+%% recv(Pid, RemoteFileName [, LocalFileName]) -> ok | {error, epath} |
+%% {error, elogin} | {error, econn}
+%% Pid = pid()
+%% RemoteFileName = LocalFileName = string()
+%%
+%% Description: Transfer file from remote server.
+%%--------------------------------------------------------------------------
+
+-spec recv(Pid :: pid(), RemoteFileName :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() |
+ common_reason() |
+ file_write_error_reason()}.
+
+recv(Pid, RemotFileName) ->
+ recv(Pid, RemotFileName, RemotFileName).
+
+-spec recv(Pid :: pid(),
+ RemoteFileName :: string(),
+ LocalFileName :: string()) ->
+ 'ok' | {'error', Reason :: term()}.
+
+recv(Pid, RemotFileName, LocalFileName) ->
+ case is_name_sane(RemotFileName) of
+ true ->
+ call(Pid, {recv, RemotFileName, LocalFileName}, atom);
+ _ ->
+ {error, efnamena}
+ end.
+
+
+%%--------------------------------------------------------------------------
+%% recv_bin(Pid, RemoteFile) -> {ok, Bin} | {error, epath} | {error, elogin}
+%% | {error, econn}
+%% Pid = pid()
+%% RemoteFile = string()
+%% Bin = binary()
+%%
+%% Description: Transfer file from remote server into binary.
+%%--------------------------------------------------------------------------
+
+-spec recv_bin(Pid :: pid(),
+ RemoteFile :: string()) ->
+ {'ok', Bin :: binary()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
+recv_bin(Pid, RemoteFile) ->
+ case is_name_sane(RemoteFile) of
+ true ->
+ call(Pid, {recv_bin, RemoteFile}, bin);
+ _ ->
+ {error, efnamena}
+ end.
+
+
+%%--------------------------------------------------------------------------
+%% recv_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} | {error, epath}
+%% | {error, econn}
+%% Pid = pid()
+%% RemoteFile = string()
+%%
+%% Description: Start receive of chunks of remote file.
+%%--------------------------------------------------------------------------
+
+-spec recv_chunk_start(Pid :: pid(),
+ RemoteFile :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
+recv_chunk_start(Pid, RemoteFile) ->
+ case is_name_sane(RemoteFile) of
+ true ->
+ call(Pid, {recv_chunk_start, RemoteFile}, atom);
+ _ ->
+ {error, efnamena}
+ end.
+
+
+%%--------------------------------------------------------------------------
+%% recv_chunk(Pid, RemoteFile) -> ok | {ok, Bin} | {error, Reason}
+%% Pid = pid()
+%% RemoteFile = string()
+%%
+%% Description: Transfer file from remote server into binary in chunks
+%%--------------------------------------------------------------------------
+
+-spec recv_chunk(Pid :: pid()) ->
+ 'ok' |
+ {'ok', Bin :: binary()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
+
+recv_chunk(Pid) ->
+ call(Pid, recv_chunk, atom).
+
+
+%%--------------------------------------------------------------------------
+%% send(Pid, LocalFileName [, RemotFileName]) -> ok | {error, epath}
+%% | {error, elogin}
+%% | {error, econn}
+%% Pid = pid()
+%% LocalFileName = RemotFileName = string()
+%%
+%% Description: Transfer file to remote server.
+%%--------------------------------------------------------------------------
+
+-spec send(Pid :: pid(), LocalFileName :: string()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
+ shortage_reason()}.
+
+send(Pid, LocalFileName) ->
+ send(Pid, LocalFileName, LocalFileName).
+
+-spec send(Pid :: pid(),
+ LocalFileName :: string(),
+ RemoteFileName :: string()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
+ shortage_reason()}.
+
+send(Pid, LocalFileName, RemotFileName) ->
+ case is_name_sane(RemotFileName) of
+ true ->
+ call(Pid, {send, LocalFileName, RemotFileName}, atom);
+ _ ->
+ {error, efnamena}
+ end.
+
+
+%%--------------------------------------------------------------------------
+%% send_bin(Pid, Bin, RemoteFile) -> ok | {error, epath} | {error, elogin}
+%% | {error, enotbinary} | {error, econn}
+%% Pid = pid()
+%% Bin = binary()
+%% RemoteFile = string()
+%%
+%% Description: Transfer a binary to a remote file.
+%%--------------------------------------------------------------------------
+
+-spec send_bin(Pid :: pid(), Bin :: binary(), RemoteFile :: string()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
+ shortage_reason()}.
+
+send_bin(Pid, Bin, RemoteFile) when is_binary(Bin) ->
+ case is_name_sane(RemoteFile) of
+ true ->
+ call(Pid, {send_bin, Bin, RemoteFile}, atom);
+ _ ->
+ {error, efnamena}
+ end;
+send_bin(_Pid, _Bin, _RemoteFile) ->
+ {error, enotbinary}.
+
+
+%%--------------------------------------------------------------------------
+%% send_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} | {error, epath}
+%% | {error, econn}
+%% Pid = pid()
+%% RemoteFile = string()
+%%
+%% Description: Start transfer of chunks to remote file.
+%%--------------------------------------------------------------------------
+
+-spec send_chunk_start(Pid :: pid(), RemoteFile :: string()) ->
+ 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
+
+send_chunk_start(Pid, RemoteFile) ->
+ case is_name_sane(RemoteFile) of
+ true ->
+ call(Pid, {send_chunk_start, RemoteFile}, atom);
+ _ ->
+ {error, efnamena}
+ end.
+
+
+%%--------------------------------------------------------------------------
+%% append_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} |
+%% {error, epath} | {error, econn}
+%% Pid = pid()
+%% RemoteFile = string()
+%%
+%% Description: Start append chunks of data to remote file.
+%%--------------------------------------------------------------------------
+
+-spec append_chunk_start(Pid :: pid(), RemoteFile :: string()) ->
+ 'ok' | {'error', Reason :: term()}.
+
+append_chunk_start(Pid, RemoteFile) ->
+ case is_name_sane(RemoteFile) of
+ true ->
+ call(Pid, {append_chunk_start, RemoteFile}, atom);
+ _ ->
+ {error, efnamena}
+ end.
+
+
+%%--------------------------------------------------------------------------
+%% send_chunk(Pid, Bin) -> ok | {error, elogin} | {error, enotbinary}
+%% | {error, echunk} | {error, econn}
+%% Pid = pid()
+%% Bin = binary().
+%%
+%% Purpose: Send chunk to remote file.
+%%--------------------------------------------------------------------------
+
+-spec send_chunk(Pid :: pid(), Bin :: binary()) ->
+ 'ok' |
+ {'error', Reason :: 'echunk' |
+ restriction_reason() |
+ common_reason()}.
+
+send_chunk(Pid, Bin) when is_binary(Bin) ->
+ call(Pid, {transfer_chunk, Bin}, atom);
+send_chunk(_Pid, _Bin) ->
+ {error, enotbinary}.
+
+
+%%--------------------------------------------------------------------------
+%% append_chunk(Pid, Bin) -> ok | {error, elogin} | {error, enotbinary}
+%% | {error, echunk} | {error, econn}
+%% Pid = pid()
+%% Bin = binary()
+%%
+%% Description: Append chunk to remote file.
+%%--------------------------------------------------------------------------
+
+-spec append_chunk(Pid :: pid(), Bin :: binary()) ->
+ 'ok' |
+ {'error', Reason :: 'echunk' |
+ restriction_reason() |
+ common_reason()}.
+
+append_chunk(Pid, Bin) when is_binary(Bin) ->
+ call(Pid, {transfer_chunk, Bin}, atom);
+append_chunk(_Pid, _Bin) ->
+ {error, enotbinary}.
+
+
+%%--------------------------------------------------------------------------
+%% send_chunk_end(Pid) -> ok | {error, elogin} | {error, echunk}
+%% | {error, econn}
+%% Pid = pid()
+%%
+%% Description: End sending of chunks to remote file.
+%%--------------------------------------------------------------------------
+
+-spec send_chunk_end(Pid :: pid()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
+ shortage_reason()}.
+
+send_chunk_end(Pid) ->
+ call(Pid, chunk_end, atom).
+
+
+%%--------------------------------------------------------------------------
+%% append_chunk_end(Pid) -> ok | {error, elogin} | {error, echunk}
+%% | {error, econn}
+%% Pid = pid()
+%%
+%% Description: End appending of chunks to remote file.
+%%--------------------------------------------------------------------------
+
+-spec append_chunk_end(Pid :: pid()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
+ shortage_reason()}.
+
+append_chunk_end(Pid) ->
+ call(Pid, chunk_end, atom).
+
+
+%%--------------------------------------------------------------------------
+%% append(Pid, LocalFileName [, RemotFileName]) -> ok | {error, epath}
+%% | {error, elogin}
+%% | {error, econn}
+%% Pid = pid()
+%% LocalFileName = RemotFileName = string()
+%%
+%% Description: Append the local file to the remote file
+%%--------------------------------------------------------------------------
+
+-spec append(Pid :: pid(), LocalFileName :: string()) ->
+ 'ok' |
+ {'error', Reason :: 'epath' |
+ 'elogin' |
+ 'etnospc' |
+ 'epnospc' |
+ 'efnamena' | common_reason()}.
+
+append(Pid, LocalFileName) ->
+ append(Pid, LocalFileName, LocalFileName).
+
+-spec append(Pid :: pid(),
+ LocalFileName :: string(),
+ RemoteFileName :: string()) ->
+ 'ok' | {'error', Reason :: term()}.
+
+append(Pid, LocalFileName, RemotFileName) ->
+ case is_name_sane(RemotFileName) of
+ true ->
+ call(Pid, {append, LocalFileName, RemotFileName}, atom);
+ _ ->
+ {error, efnamena}
+ end.
+
+
+%%--------------------------------------------------------------------------
+%% append_bin(Pid, Bin, RemoteFile) -> ok | {error, epath} | {error, elogin}
+%% | {error, enotbinary} | {error, econn}
+%% Pid = pid()
+%% Bin = binary()
+%% RemoteFile = string()
+%%
+%% Purpose: Append a binary to a remote file.
+%%--------------------------------------------------------------------------
+
+-spec append_bin(Pid :: pid(),
+ Bin :: binary(),
+ RemoteFile :: string()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
+ shortage_reason()}.
+
+append_bin(Pid, Bin, RemoteFile) when is_binary(Bin) ->
+ case is_name_sane(RemoteFile) of
+ true ->
+ call(Pid, {append_bin, Bin, RemoteFile}, atom);
+ _ ->
+ {error, efnamena}
+ end;
+append_bin(_Pid, _Bin, _RemoteFile) ->
+ {error, enotbinary}.
+
+
+%%--------------------------------------------------------------------------
+%% quote(Pid, Cmd) -> list()
+%% Pid = pid()
+%% Cmd = string()
+%%
+%% Description: Send arbitrary ftp command.
+%%--------------------------------------------------------------------------
+
+-spec quote(Pid :: pid(), Cmd :: string()) -> list().
+
+quote(Pid, Cmd) when is_list(Cmd) ->
+ call(Pid, {quote, Cmd}, atom).
+
+
+%%--------------------------------------------------------------------------
+%% close(Pid) -> ok
+%% Pid = pid()
+%%
+%% Description: End the ftp session.
+%%--------------------------------------------------------------------------
+
+-spec close(Pid :: pid()) -> 'ok'.
+
+close(Pid) ->
+ cast(Pid, close),
+ ok.
+
+
+%%--------------------------------------------------------------------------
+%% formaterror(Tag) -> string()
+%% Tag = atom() | {error, atom()}
+%%
+%% Description: Return diagnostics.
+%%--------------------------------------------------------------------------
+
+-spec formaterror(Tag :: term()) -> string().
+
+formaterror(Tag) ->
+ ftp_response:error_string(Tag).
+
+
+info(Pid) ->
+ call(Pid, info, list).
+
+
+%%--------------------------------------------------------------------------
+%% latest_ctrl_response(Pid) -> string()
+%% Pid = pid()
+%%
+%% Description: The latest received response from the server
+%%--------------------------------------------------------------------------
+
+-spec latest_ctrl_response(Pid :: pid()) -> string().
+
+latest_ctrl_response(Pid) ->
+ call(Pid, latest_ctrl_response, string).
+
+
+%%%========================================================================
+%%% gen_server callback functions
+%%%========================================================================
+
+%%-------------------------------------------------------------------------
+%% init(Args) -> {ok, State} | {ok, State, Timeout} | {stop, Reason}
+%% Description: Initiates the erlang process that manages a ftp connection.
+%%-------------------------------------------------------------------------
+init(Options) ->
+ process_flag(trap_exit, true),
+
+ %% Keep track of the client
+ {value, {client, Client}} = lists:keysearch(client, 1, Options),
+ erlang:monitor(process, Client),
+
+ %% Make sure inet is started
+ _ = inet_db:start(),
+
+ %% Where are we
+ {ok, Dir} = file:get_cwd(),
+
+ %% Maybe activate dbg
+ case key_search(debug, Options, disable) of
+ trace ->
+ dbg:tracer(),
+ dbg:p(all, [call]),
+ {ok, _} = dbg:tpl(ftp, [{'_', [], [{return_trace}]}]),
+ {ok, _} = dbg:tpl(ftp_response, [{'_', [], [{return_trace}]}]),
+ {ok, _} = dbg:tpl(ftp_progress, [{'_', [], [{return_trace}]}]),
+ ok;
+ debug ->
+ dbg:tracer(),
+ dbg:p(all, [call]),
+ {ok, _} = dbg:tp(ftp, [{'_', [], [{return_trace}]}]),
+ {ok, _} = dbg:tp(ftp_response, [{'_', [], [{return_trace}]}]),
+ {ok, _} = dbg:tp(ftp_progress, [{'_', [], [{return_trace}]}]),
+ ok;
+ _ ->
+ %% Keep silent
+ ok
+ end,
+
+ %% Verbose?
+ Verbose = key_search(verbose, Options, false),
+
+ %% IpFamily?
+ IpFamily = key_search(ipfamily, Options, inet),
+
+ State = #state{owner = Client,
+ verbose = Verbose,
+ ipfamily = IpFamily,
+ ldir = Dir},
+
+ %% Set process prio
+ Priority = key_search(priority, Options, low),
+ process_flag(priority, Priority),
+
+ %% And we are done
+ {ok, State}.
+
+
+%%--------------------------------------------------------------------------
+%% handle_call(Request, From, State) -> {reply, Reply, State} |
+%% {reply, Reply, State, Timeout} |
+%% {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, Reply, State} |
+%% Description: Handle incoming requests.
+%%-------------------------------------------------------------------------
+
+%% Anyone can ask this question
+handle_call({_, info}, _, #state{verbose = Verbose,
+ mode = Mode,
+ timeout = Timeout,
+ ipfamily = IpFamily,
+ csock = Socket,
+ progress = Progress} = State) ->
+ {ok, {_, LocalPort}} = sockname(Socket),
+ {ok, {Address, Port}} = peername(Socket),
+ Options = [{verbose, Verbose},
+ {ipfamily, IpFamily},
+ {mode, Mode},
+ {peer, Address},
+ {peer_port, Port},
+ {local_port, LocalPort},
+ {timeout, Timeout},
+ {progress, Progress}],
+ {reply, {ok, Options}, State};
+
+handle_call({_,latest_ctrl_response}, _, #state{latest_ctrl_response=Resp} = State) ->
+ {reply, {ok,Resp}, State};
+
+%% But everything else must come from the owner
+handle_call({Pid, _}, _, #state{owner = Owner} = State) when Owner =/= Pid ->
+ {reply, {error, not_connection_owner}, State};
+
+handle_call({_, {open, ip_comm, Opts, {CtrlOpts, DataPassOpts, DataActOpts}}}, From, State) ->
+ case key_search(host, Opts, undefined) of
+ undefined ->
+ {stop, normal, {error, ehost}, State};
+ Host ->
+ Mode = key_search(mode, Opts, ?DEFAULT_MODE),
+ Port = key_search(port, Opts, ?FTP_PORT),
+ Timeout = key_search(timeout, Opts, ?CONNECTION_TIMEOUT),
+ DTimeout = key_search(dtimeout, Opts, ?DATA_ACCEPT_TIMEOUT),
+ Progress = key_search(progress, Opts, ignore),
+ IpFamily = key_search(ipfamily, Opts, inet),
+ FtpExt = key_search(ftp_extension, Opts, ?FTP_EXT_DEFAULT),
+
+ State2 = State#state{client = From,
+ mode = Mode,
+ progress = progress(Progress),
+ ipfamily = IpFamily,
+ sockopts_ctrl = CtrlOpts,
+ sockopts_data_passive = DataPassOpts,
+ sockopts_data_active = DataActOpts,
+ dtimeout = DTimeout,
+ ftp_extension = FtpExt},
+
+ case setup_ctrl_connection(Host, Port, Timeout, State2) of
+ {ok, State3, WaitTimeout} ->
+ {noreply, State3, WaitTimeout};
+ {error, _Reason} ->
+ gen_server:reply(From, {error, ehost}),
+ {stop, normal, State2#state{client = undefined}}
+ end
+ end;
+
+handle_call({_, {open, tls_upgrade, TLSOptions}}, From, State) ->
+ _ = send_ctrl_message(State, mk_cmd("AUTH TLS", [])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{client = From, caller = open, tls_options = TLSOptions}};
+
+handle_call({_, {user, User, Password}}, From,
+ #state{csock = CSock} = State) when (CSock =/= undefined) ->
+ handle_user(User, Password, "", State#state{client = From});
+
+handle_call({_, {user, User, Password, Acc}}, From,
+ #state{csock = CSock} = State) when (CSock =/= undefined) ->
+ handle_user(User, Password, Acc, State#state{client = From});
+
+handle_call({_, {account, Acc}}, From, State)->
+ handle_user_account(Acc, State#state{client = From});
+
+handle_call({_, pwd}, From, #state{chunk = false} = State) ->
+ _ = send_ctrl_message(State, mk_cmd("PWD", [])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{client = From, caller = pwd}};
+
+handle_call({_, lpwd}, From, #state{ldir = LDir} = State) ->
+ {reply, {ok, LDir}, State#state{client = From}};
+
+handle_call({_, {cd, Dir}}, From, #state{chunk = false} = State) ->
+ _ = send_ctrl_message(State, mk_cmd("CWD ~s", [Dir])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{client = From, caller = cd}};
+
+handle_call({_,{lcd, Dir}}, _From, #state{ldir = LDir0} = State) ->
+ LDir = filename:absname(Dir, LDir0),
+ case file:read_file_info(LDir) of %% FIX better check that LDir is a dir.
+ {ok, _ } ->
+ {reply, ok, State#state{ldir = LDir}};
+ _ ->
+ {reply, {error, epath}, State}
+ end;
+
+handle_call({_, {dir, Len, Dir}}, {_Pid, _} = From,
+ #state{chunk = false} = State) ->
+ setup_data_connection(State#state{caller = {dir, Dir, Len},
+ client = From});
+handle_call({_, {rename, CurrFile, NewFile}}, From,
+ #state{chunk = false} = State) ->
+ _ = send_ctrl_message(State, mk_cmd("RNFR ~s", [CurrFile])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = {rename, NewFile}, client = From}};
+
+handle_call({_, {delete, File}}, {_Pid, _} = From,
+ #state{chunk = false} = State) ->
+ _ = send_ctrl_message(State, mk_cmd("DELE ~s", [File])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{client = From}};
+
+handle_call({_, {mkdir, Dir}}, From, #state{chunk = false} = State) ->
+ _ = send_ctrl_message(State, mk_cmd("MKD ~s", [Dir])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{client = From}};
+
+handle_call({_,{rmdir, Dir}}, From, #state{chunk = false} = State) ->
+ _ = send_ctrl_message(State, mk_cmd("RMD ~s", [Dir])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{client = From}};
+
+handle_call({_,{type, Type}}, From, #state{chunk = false} = State) ->
+ case Type of
+ ascii ->
+ _ = send_ctrl_message(State, mk_cmd("TYPE A", [])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = type, type = ascii,
+ client = From}};
+ binary ->
+ _ = send_ctrl_message(State, mk_cmd("TYPE I", [])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = type, type = binary,
+ client = From}};
+ _ ->
+ {reply, {error, etype}, State}
+ end;
+
+handle_call({_,{recv, RemoteFile, LocalFile}}, From,
+ #state{chunk = false, ldir = LocalDir} = State) ->
+ progress_report({remote_file, RemoteFile}, State),
+ NewLocalFile = filename:absname(LocalFile, LocalDir),
+
+ case file_open(NewLocalFile, write) of
+ {ok, Fd} ->
+ setup_data_connection(State#state{client = From,
+ caller =
+ {recv_file,
+ RemoteFile, Fd}});
+ {error, _What} ->
+ {reply, {error, epath}, State}
+ end;
+
+handle_call({_, {recv_bin, RemoteFile}}, From, #state{chunk = false} =
+ State) ->
+ setup_data_connection(State#state{caller = {recv_bin, RemoteFile},
+ client = From});
+
+handle_call({_,{recv_chunk_start, RemoteFile}}, From, #state{chunk = false}
+ = State) ->
+ setup_data_connection(State#state{caller = {start_chunk_transfer,
+ "RETR", RemoteFile},
+ client = From});
+
+handle_call({_, recv_chunk}, _, #state{chunk = false} = State) ->
+ {reply, {error, "ftp:recv_chunk_start/2 not called"}, State};
+
+handle_call({_, recv_chunk}, _From, #state{chunk = true,
+ caller = #recv_chunk_closing{dconn_closed = true,
+ pos_compl_received = true
+ }
+ } = State0) ->
+ %% The ftp:recv_chunk call was the last event we waited for, finnish and clean up
+ ?DBG("recv_chunk_closing ftp:recv_chunk, last event",[]),
+ activate_ctrl_connection(State0),
+ {reply, ok, State0#state{caller = undefined,
+ chunk = false,
+ client = undefined}};
+
+handle_call({_, recv_chunk}, From, #state{chunk = true,
+ caller = #recv_chunk_closing{} = R
+ } = State) ->
+ %% Waiting for more, don't care what
+ ?DBG("recv_chunk_closing ftp:recv_chunk, get more",[]),
+ {noreply, State#state{client = From, caller = R#recv_chunk_closing{client_called_us=true}}};
+
+handle_call({_, recv_chunk}, From, #state{chunk = true} = State0) ->
+ State = activate_data_connection(State0),
+ {noreply, State#state{client = From, caller = recv_chunk}};
+
+handle_call({_, {send, LocalFile, RemoteFile}}, From,
+ #state{chunk = false, ldir = LocalDir} = State) ->
+ progress_report({local_file, filename:absname(LocalFile, LocalDir)},
+ State),
+ setup_data_connection(State#state{caller = {transfer_file,
+ {"STOR",
+ LocalFile, RemoteFile}},
+ client = From});
+handle_call({_, {append, LocalFile, RemoteFile}}, From,
+ #state{chunk = false} = State) ->
+ setup_data_connection(State#state{caller = {transfer_file,
+ {"APPE",
+ LocalFile, RemoteFile}},
+ client = From});
+handle_call({_, {send_bin, Bin, RemoteFile}}, From,
+ #state{chunk = false} = State) ->
+ setup_data_connection(State#state{caller = {transfer_data,
+ {"STOR", Bin, RemoteFile}},
+ client = From});
+handle_call({_,{append_bin, Bin, RemoteFile}}, From,
+ #state{chunk = false} = State) ->
+ setup_data_connection(State#state{caller = {transfer_data,
+ {"APPE", Bin, RemoteFile}},
+ client = From});
+handle_call({_, {send_chunk_start, RemoteFile}}, From, #state{chunk = false}
+ = State) ->
+ setup_data_connection(State#state{caller = {start_chunk_transfer,
+ "STOR", RemoteFile},
+ client = From});
+handle_call({_, {append_chunk_start, RemoteFile}}, From, #state{chunk = false}
+ = State) ->
+ setup_data_connection(State#state{caller = {start_chunk_transfer,
+ "APPE", RemoteFile},
+ client = From});
+handle_call({_, {transfer_chunk, Bin}}, _, #state{chunk = true} = State) ->
+ send_data_message(State, Bin),
+ {reply, ok, State};
+
+handle_call({_, {transfer_chunk, _}}, _, #state{chunk = false} = State) ->
+ {reply, {error, echunk}, State};
+
+handle_call({_, chunk_end}, From, #state{chunk = true} = State) ->
+ close_data_connection(State),
+ activate_ctrl_connection(State),
+ {noreply, State#state{client = From, dsock = undefined,
+ caller = end_chunk_transfer, chunk = false}};
+
+handle_call({_, chunk_end}, _, #state{chunk = false} = State) ->
+ {reply, {error, echunk}, State};
+
+handle_call({_, {quote, Cmd}}, From, #state{chunk = false} = State) ->
+ _ = send_ctrl_message(State, mk_cmd(Cmd, [])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{client = From, caller = quote}};
+
+handle_call({_, _Req}, _From, #state{csock = CSock} = State)
+ when (CSock =:= undefined) ->
+ {reply, {error, not_connected}, State};
+
+handle_call(_, _, #state{chunk = true} = State) ->
+ {reply, {error, echunk}, State};
+
+%% Catch all - This can only happen if the application programmer writes
+%% really bad code that violates the API.
+handle_call(Request, _Timeout, State) ->
+ {stop, {'API_violation_connection_closed', Request},
+ {error, {connection_terminated, 'API_violation'}}, State}.
+
+%%--------------------------------------------------------------------------
+%% handle_cast(Request, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% Description: Handles cast messages.
+%%-------------------------------------------------------------------------
+handle_cast({Pid, close}, #state{owner = Pid} = State) ->
+ _ = send_ctrl_message(State, mk_cmd("QUIT", [])),
+ close_ctrl_connection(State),
+ close_data_connection(State),
+ {stop, normal, State#state{csock = undefined, dsock = undefined}};
+
+handle_cast({Pid, close}, State) ->
+ Report = io_lib:format("A none owner process ~p tried to close an "
+ "ftp connection: ~n", [Pid]),
+ error_logger:info_report(Report),
+ {noreply, State};
+
+%% Catch all - This can oly happen if the application programmer writes
+%% really bad code that violates the API.
+handle_cast(Msg, State) ->
+ {stop, {'API_violation_connection_closed', Msg}, State}.
+
+%%--------------------------------------------------------------------------
+%% handle_info(Msg, State) -> {noreply, State} | {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% Description: Handles tcp messages from the ftp-server.
+%% Note: The order of the function clauses is significant.
+%%--------------------------------------------------------------------------
+
+handle_info(timeout, #state{caller = open} = State) ->
+ {stop, timeout, State};
+
+handle_info(timeout, State) ->
+ {noreply, State};
+
+%%% Data socket messages %%%
+handle_info({Trpt, Socket, Data},
+ #state{dsock = {Trpt,Socket},
+ caller = {recv_file, Fd}} = State0) when Trpt==tcp;Trpt==ssl ->
+ ?DBG('L~p --data ~p ----> ~s~p~n',[?LINE,Socket,Data,State0]),
+ ok = file_write(binary_to_list(Data), Fd),
+ progress_report({binary, Data}, State0),
+ State = activate_data_connection(State0),
+ {noreply, State};
+
+handle_info({Trpt, Socket, Data}, #state{dsock = {Trpt,Socket}, client = From,
+ caller = recv_chunk}
+ = State) when Trpt==tcp;Trpt==ssl ->
+ ?DBG('L~p --data ~p ----> ~s~p~n',[?LINE,Socket,Data,State]),
+ gen_server:reply(From, {ok, Data}),
+ {noreply, State#state{client = undefined, data = <<>>}};
+
+handle_info({Trpt, Socket, Data}, #state{dsock = {Trpt,Socket}} = State0) when Trpt==tcp;Trpt==ssl ->
+ ?DBG('L~p --data ~p ----> ~s~p~n',[?LINE,Socket,Data,State0]),
+ State = activate_data_connection(State0),
+ {noreply, State#state{data = <<(State#state.data)/binary,
+ Data/binary>>}};
+
+handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket},
+ caller = {recv_file, Fd}} = State)
+ when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
+ file_close(Fd),
+ progress_report({transfer_size, 0}, State),
+ activate_ctrl_connection(State),
+ ?DBG("Data channel close",[]),
+ {noreply, State#state{dsock = undefined, data = <<>>}};
+
+handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket},
+ client = Client,
+ caller = recv_chunk} = State)
+ when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
+ ?DBG("Data channel close recv_chunk",[]),
+ activate_ctrl_connection(State),
+ {noreply, State#state{dsock = undefined,
+ caller = #recv_chunk_closing{dconn_closed = true,
+ client_called_us = Client =/= undefined}
+ }};
+
+handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket}, caller = recv_bin,
+ data = Data} = State)
+ when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
+ ?DBG("Data channel close",[]),
+ activate_ctrl_connection(State),
+ {noreply, State#state{dsock = undefined, data = <<>>,
+ caller = {recv_bin, Data}}};
+
+handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket}, data = Data,
+ caller = {handle_dir_result, Dir}}
+ = State) when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
+ ?DBG("Data channel close",[]),
+ activate_ctrl_connection(State),
+ {noreply, State#state{dsock = undefined,
+ caller = {handle_dir_result, Dir, Data},
+% data = <<?CR,?LF>>}};
+ data = <<>>}};
+
+handle_info({Err, Socket, Reason}, #state{dsock = {Trpt,Socket},
+ client = From} = State)
+ when {Err,Trpt}=={tcp_error,tcp} ; {Err,Trpt}=={ssl_error,ssl} ->
+ gen_server:reply(From, {error, Reason}),
+ close_data_connection(State),
+ {noreply, State#state{dsock = undefined, client = undefined,
+ data = <<>>, caller = undefined, chunk = false}};
+
+%%% Ctrl socket messages %%%
+handle_info({Transport, Socket, Data}, #state{csock = {Transport, Socket},
+ verbose = Verbose,
+ caller = Caller,
+ client = From,
+ ctrl_data = {CtrlData, AccLines,
+ LineStatus}}
+ = State) ->
+ ?DBG('--ctrl ~p ----> ~s~p~n',[Socket,<<CtrlData/binary, Data/binary>>,State]),
+ case ftp_response:parse_lines(<<CtrlData/binary, Data/binary>>,
+ AccLines, LineStatus) of
+ {ok, Lines, NextMsgData} ->
+ verbose(Lines, Verbose, 'receive'),
+ CtrlResult = ftp_response:interpret(Lines),
+ case Caller of
+ quote ->
+ gen_server:reply(From, string:tokens(Lines, [?CR, ?LF])),
+ {noreply, State#state{client = undefined,
+ caller = undefined,
+ latest_ctrl_response = Lines,
+ ctrl_data = {NextMsgData, [],
+ start}}};
+ _ ->
+ ?DBG(' ...handle_ctrl_result(~p,...) ctrl_data=~p~n',[CtrlResult,{NextMsgData, [], start}]),
+ handle_ctrl_result(CtrlResult,
+ State#state{latest_ctrl_response = Lines,
+ ctrl_data =
+ {NextMsgData, [], start}})
+ end;
+ {continue, NewCtrlData} ->
+ ?DBG(' ...Continue... ctrl_data=~p~n',[NewCtrlData]),
+ activate_ctrl_connection(State),
+ {noreply, State#state{ctrl_data = NewCtrlData}}
+ end;
+
+%% If the server closes the control channel it is
+%% the expected behavior that connection process terminates.
+handle_info({Cls, Socket}, #state{csock = {Trpt, Socket}})
+ when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
+ exit(normal); %% User will get error message from terminate/2
+
+handle_info({Err, Socket, Reason}, _) when Err==tcp_error ; Err==ssl_error ->
+ Report =
+ io_lib:format("~p on socket: ~p for reason: ~p~n",
+ [Err, Socket, Reason]),
+ error_logger:error_report(Report),
+ %% If tcp does not work the only option is to terminate,
+ %% this is the expected behavior under these circumstances.
+ exit(normal); %% User will get error message from terminate/2
+
+%% Monitor messages - if the process owning the ftp connection goes
+%% down there is no point in continuing.
+handle_info({'DOWN', _Ref, _Type, _Process, normal}, State) ->
+ {stop, normal, State#state{client = undefined}};
+
+handle_info({'DOWN', _Ref, _Type, _Process, shutdown}, State) ->
+ {stop, normal, State#state{client = undefined}};
+
+handle_info({'DOWN', _Ref, _Type, _Process, timeout}, State) ->
+ {stop, normal, State#state{client = undefined}};
+
+handle_info({'DOWN', _Ref, _Type, Process, Reason}, State) ->
+ {stop, {stopped, {'EXIT', Process, Reason}},
+ State#state{client = undefined}};
+
+handle_info({'EXIT', Pid, Reason}, #state{progress = Pid} = State) ->
+ Report = io_lib:format("Progress reporting stopped for reason ~p~n",
+ [Reason]),
+ error_logger:info_report(Report),
+ {noreply, State#state{progress = ignore}};
+
+%% Catch all - throws away unknown messages (This could happen by "accident"
+%% so we do not want to crash, but we make a log entry as it is an
+%% unwanted behaviour.)
+handle_info(Info, State) ->
+ Report = io_lib:format("ftp : ~p : Unexpected message: ~p~nState: ~p~n",
+ [self(), Info, State]),
+ error_logger:info_report(Report),
+ {noreply, State}.
+
+%%--------------------------------------------------------------------------
+%% terminate/2 and code_change/3
+%%--------------------------------------------------------------------------
+terminate(normal, State) ->
+ %% If terminate reason =/= normal the progress reporting process will
+ %% be killed by the exit signal.
+ progress_report(stop, State),
+ do_terminate({error, econn}, State);
+terminate(Reason, State) ->
+ Report = io_lib:format("Ftp connection closed due to: ~p~n", [Reason]),
+ error_logger:error_report(Report),
+ do_terminate({error, eclosed}, State).
+
+do_terminate(ErrorMsg, State) ->
+ close_data_connection(State),
+ close_ctrl_connection(State),
+ case State#state.client of
+ undefined ->
+ ok;
+ From ->
+ gen_server:reply(From, ErrorMsg)
+ end,
+ ok.
+
+code_change(_Vsn, State1, upgrade_from_pre_5_12) ->
+ {state, CSock, DSock, Verbose, LDir, Type, Chunk, Mode, Timeout,
+ Data, CtrlData, Owner, Client, Caller, IPv6Disable, Progress} = State1,
+ IpFamily =
+ if
+ (IPv6Disable =:= true) ->
+ inet;
+ true ->
+ inet6fb4
+ end,
+ State2 = #state{csock = CSock,
+ dsock = DSock,
+ verbose = Verbose,
+ ldir = LDir,
+ type = Type,
+ chunk = Chunk,
+ mode = Mode,
+ timeout = Timeout,
+ data = Data,
+ ctrl_data = CtrlData,
+ owner = Owner,
+ client = Client,
+ caller = Caller,
+ ipfamily = IpFamily,
+ progress = Progress},
+ {ok, State2};
+
+code_change(_Vsn, State1, downgrade_to_pre_5_12) ->
+ #state{csock = CSock,
+ dsock = DSock,
+ verbose = Verbose,
+ ldir = LDir,
+ type = Type,
+ chunk = Chunk,
+ mode = Mode,
+ timeout = Timeout,
+ data = Data,
+ ctrl_data = CtrlData,
+ owner = Owner,
+ client = Client,
+ caller = Caller,
+ ipfamily = IpFamily,
+ progress = Progress} = State1,
+ IPv6Disable =
+ if
+ (IpFamily =:= inet) ->
+ true;
+ true ->
+ false
+ end,
+ State2 =
+ {state, CSock, DSock, Verbose, LDir, Type, Chunk, Mode, Timeout,
+ Data, CtrlData, Owner, Client, Caller, IPv6Disable, Progress},
+ {ok, State2};
+
+code_change(_Vsn, State, _Extra) ->
+ {ok, State}.
+
+
+%%%=========================================================================
+%% Start/stop
+%%%=========================================================================
+%%--------------------------------------------------------------------------
+%% start_link([Opts, GenServerOptions]) -> {ok, Pid} | {error, Reason}
+%%
+%% Description: Callback function for the ftp supervisor. It is called
+%% : when start_service/1 calls ftp_sup:start_child/1 to start an
+%% : instance of the ftp process. Also called by start_standalone/1
+%%--------------------------------------------------------------------------
+start_link([Opts, GenServerOptions]) ->
+ start_link(Opts, GenServerOptions).
+
+start_link(Opts, GenServerOptions) ->
+ case lists:keysearch(client, 1, Opts) of
+ {value, _} ->
+ %% Via the supervisor
+ gen_server:start_link(?MODULE, Opts, GenServerOptions);
+ false ->
+ Opts2 = [{client, self()} | Opts],
+ gen_server:start_link(?MODULE, Opts2, GenServerOptions)
+ end.
+
+
+%%% Stop functionality is handled by close/1
+
+%%%========================================================================
+%%% Internal functions
+%%%========================================================================
+
+%%--------------------------------------------------------------------------
+%%% Help functions to handle_call and/or handle_ctrl_result
+%%--------------------------------------------------------------------------
+%% User handling
+handle_user(User, Password, Acc, State) ->
+ _ = send_ctrl_message(State, mk_cmd("USER ~s", [User])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = {handle_user, Password, Acc}}}.
+
+handle_user_passwd(Password, Acc, State) ->
+ _ = send_ctrl_message(State, mk_cmd("PASS ~s", [Password])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = {handle_user_passwd, Acc}}}.
+
+handle_user_account(Acc, State) ->
+ _ = send_ctrl_message(State, mk_cmd("ACCT ~s", [Acc])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = handle_user_account}}.
+
+
+%%--------------------------------------------------------------------------
+%% handle_ctrl_result
+%%--------------------------------------------------------------------------
+handle_ctrl_result({tls_upgrade, _}, #state{csock = {tcp, Socket},
+ tls_options = TLSOptions,
+ timeout = Timeout,
+ caller = open, client = From}
+ = State0) ->
+ ?DBG('<--ctrl ssl:connect(~p, ~p)~n~p~n',[Socket,TLSOptions,State0]),
+ case ssl:connect(Socket, TLSOptions, Timeout) of
+ {ok, TLSSocket} ->
+ State = State0#state{csock = {ssl,TLSSocket}},
+ _ = send_ctrl_message(State, mk_cmd("PBSZ 0", [])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{tls_upgrading_data_connection = {true, pbsz}} };
+ {error, _} = Error ->
+ gen_server:reply(From, {Error, self()}),
+ {stop, normal, State0#state{client = undefined,
+ caller = undefined,
+ tls_upgrading_data_connection = false}}
+ end;
+
+handle_ctrl_result({pos_compl, _}, #state{tls_upgrading_data_connection = {true, pbsz}} = State) ->
+ _ = send_ctrl_message(State, mk_cmd("PROT P", [])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{tls_upgrading_data_connection = {true, prot}}};
+
+handle_ctrl_result({pos_compl, _}, #state{tls_upgrading_data_connection = {true, prot},
+ client = From} = State) ->
+ gen_server:reply(From, {ok, self()}),
+ {noreply, State#state{client = undefined,
+ caller = undefined,
+ tls_upgrading_data_connection = false}};
+
+handle_ctrl_result({pos_compl, _}, #state{caller = open, client = From}
+ = State) ->
+ gen_server:reply(From, {ok, self()}),
+ {noreply, State#state{client = undefined,
+ caller = undefined }};
+handle_ctrl_result({_, Lines}, #state{caller = open} = State) ->
+ ctrl_result_response(econn, State, {error, Lines});
+
+%%--------------------------------------------------------------------------
+%% Data connection setup active mode
+handle_ctrl_result({pos_compl, _Lines},
+ #state{mode = active,
+ caller = {setup_data_connection,
+ {LSock, Caller}}} = State) ->
+ handle_caller(State#state{caller = Caller, dsock = {lsock, LSock}});
+
+handle_ctrl_result({Status, _Lines},
+ #state{mode = active,
+ caller = {setup_data_connection, {LSock, _}}}
+ = State) ->
+ close_connection({tcp,LSock}),
+ ctrl_result_response(Status, State, {error, Status});
+
+%% Data connection setup passive mode
+handle_ctrl_result({pos_compl, Lines},
+ #state{mode = passive,
+ ipfamily = inet6,
+ client = From,
+ caller = {setup_data_connection, Caller},
+ csock = CSock,
+ sockopts_data_passive = SockOpts,
+ timeout = Timeout}
+ = State) ->
+ [_, PortStr | _] = lists:reverse(string:tokens(Lines, "|")),
+ {ok, {IP, _}} = peername(CSock),
+ case connect(IP, list_to_integer(PortStr), SockOpts, Timeout, State) of
+ {ok, _, Socket} ->
+ handle_caller(State#state{caller = Caller, dsock = {tcp, Socket}});
+ {error, _Reason} = Error ->
+ gen_server:reply(From, Error),
+ {noreply, State#state{client = undefined, caller = undefined}}
+ end;
+
+handle_ctrl_result({pos_compl, Lines},
+ #state{mode = passive,
+ ipfamily = inet,
+ client = From,
+ caller = {setup_data_connection, Caller},
+ timeout = Timeout,
+ sockopts_data_passive = SockOpts,
+ ftp_extension = false} = State) ->
+
+ {_, [?LEFT_PAREN | Rest]} =
+ lists:splitwith(fun(?LEFT_PAREN) -> false; (_) -> true end, Lines),
+ {NewPortAddr, _} =
+ lists:splitwith(fun(?RIGHT_PAREN) -> false; (_) -> true end, Rest),
+ [A1, A2, A3, A4, P1, P2] =
+ lists:map(fun(X) -> list_to_integer(X) end,
+ string:tokens(NewPortAddr, [$,])),
+ IP = {A1, A2, A3, A4},
+ Port = (P1 * 256) + P2,
+
+ ?DBG('<--data tcp connect to ~p:~p, Caller=~p~n',[IP,Port,Caller]),
+ case connect(IP, Port, SockOpts, Timeout, State) of
+ {ok, _, Socket} ->
+ handle_caller(State#state{caller = Caller, dsock = {tcp,Socket}});
+ {error, _Reason} = Error ->
+ gen_server:reply(From, Error),
+ {noreply,State#state{client = undefined, caller = undefined}}
+ end;
+
+handle_ctrl_result({pos_compl, Lines},
+ #state{mode = passive,
+ ipfamily = inet,
+ client = From,
+ caller = {setup_data_connection, Caller},
+ csock = CSock,
+ timeout = Timeout,
+ sockopts_data_passive = SockOpts,
+ ftp_extension = true} = State) ->
+
+ [_, PortStr | _] = lists:reverse(string:tokens(Lines, "|")),
+ {ok, {IP, _}} = peername(CSock),
+
+ ?DBG('<--data tcp connect to ~p:~p, Caller=~p~n',[IP,PortStr,Caller]),
+ case connect(IP, list_to_integer(PortStr), SockOpts, Timeout, State) of
+ {ok, _, Socket} ->
+ handle_caller(State#state{caller = Caller, dsock = {tcp, Socket}});
+ {error, _Reason} = Error ->
+ gen_server:reply(From, Error),
+ {noreply, State#state{client = undefined, caller = undefined}}
+ end;
+
+
+%% FTP server does not support passive mode: try to fallback on active mode
+handle_ctrl_result(_,
+ #state{mode = passive,
+ caller = {setup_data_connection, Caller}} = State) ->
+ setup_data_connection(State#state{mode = active, caller = Caller});
+
+
+%%--------------------------------------------------------------------------
+%% User handling
+handle_ctrl_result({pos_interm, _},
+ #state{caller = {handle_user, PassWord, Acc}} = State) ->
+ handle_user_passwd(PassWord, Acc, State);
+handle_ctrl_result({Status, _},
+ #state{caller = {handle_user, _, _}} = State) ->
+ ctrl_result_response(Status, State, {error, euser});
+
+%% Accounts
+handle_ctrl_result({pos_interm_acct, _},
+ #state{caller = {handle_user_passwd, Acc}} = State)
+ when Acc =/= "" ->
+ handle_user_account(Acc, State);
+handle_ctrl_result({Status, _},
+ #state{caller = {handle_user_passwd, _}} = State) ->
+ ctrl_result_response(Status, State, {error, euser});
+
+%%--------------------------------------------------------------------------
+%% Print current working directory
+handle_ctrl_result({pos_compl, Lines},
+ #state{caller = pwd, client = From} = State) ->
+ Dir = pwd_result(Lines),
+ gen_server:reply(From, {ok, Dir}),
+ {noreply, State#state{client = undefined, caller = undefined}};
+
+%%--------------------------------------------------------------------------
+%% Directory listing
+handle_ctrl_result({pos_prel, _}, #state{caller = {dir, Dir}} = State0) ->
+ case accept_data_connection(State0) of
+ {ok, State1} ->
+ State = activate_data_connection(State1),
+ {noreply, State#state{caller = {handle_dir_result, Dir}}};
+ {error, _Reason} = ERROR ->
+ case State0#state.client of
+ undefined ->
+ {stop, ERROR, State0};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State0#state{client = undefined}}
+ end
+ end;
+
+handle_ctrl_result({pos_compl, _}, #state{caller = {handle_dir_result, Dir,
+ Data}, client = From}
+ = State) ->
+ case Dir of
+ "" -> % Current directory
+ gen_server:reply(From, {ok, Data}),
+ {noreply, State#state{client = undefined,
+ caller = undefined}};
+ _ ->
+ %% <WTF>
+ %% Dir cannot be assumed to be a dir. It is a string that
+ %% could be a dir, but could also be a file or even a string
+ %% containing wildcards (*).
+ %%
+ %% %% If there is only one line it might be a directory with one
+ %% %% file but it might be an error message that the directory
+ %% %% was not found. So in this case we have to endure a little
+ %% %% overhead to be able to give a good return value. Alas not
+ %% %% all ftp implementations behave the same and returning
+ %% %% an error string is allowed by the FTP RFC.
+ %% case lists:dropwhile(fun(?CR) -> false;(_) -> true end,
+ %% binary_to_list(Data)) of
+ %% L when (L =:= [?CR, ?LF]) orelse (L =:= []) ->
+ %% send_ctrl_message(State, mk_cmd("PWD", [])),
+ %% activate_ctrl_connection(State),
+ %% {noreply,
+ %% State#state{caller = {handle_dir_data, Dir, Data}}};
+ %% _ ->
+ %% gen_server:reply(From, {ok, Data}),
+ %% {noreply, State#state{client = undefined,
+ %% caller = undefined}}
+ %% end
+ %% </WTF>
+ gen_server:reply(From, {ok, Data}),
+ {noreply, State#state{client = undefined,
+ caller = undefined}}
+ end;
+
+handle_ctrl_result({pos_compl, Lines},
+ #state{caller = {handle_dir_data, Dir, DirData}} =
+ State) ->
+ OldDir = pwd_result(Lines),
+ _ = send_ctrl_message(State, mk_cmd("CWD ~s", [Dir])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = {handle_dir_data_second_phase, OldDir,
+ DirData}}};
+handle_ctrl_result({Status, _},
+ #state{caller = {handle_dir_data, _, _}} = State) ->
+ ctrl_result_response(Status, State, {error, epath});
+
+handle_ctrl_result(S={_Status, _},
+ #state{caller = {handle_dir_result, _, _}} = State) ->
+ %% OTP-5731, macosx
+ ctrl_result_response(S, State, {error, epath});
+
+handle_ctrl_result({pos_compl, _},
+ #state{caller = {handle_dir_data_second_phase, OldDir,
+ DirData}} = State) ->
+ _ = send_ctrl_message(State, mk_cmd("CWD ~s", [OldDir])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = {handle_dir_data_third_phase, DirData}}};
+handle_ctrl_result({Status, _},
+ #state{caller = {handle_dir_data_second_phase, _, _}}
+ = State) ->
+ ctrl_result_response(Status, State, {error, epath});
+handle_ctrl_result(_, #state{caller = {handle_dir_data_third_phase, DirData},
+ client = From} = State) ->
+ gen_server:reply(From, {ok, DirData}),
+ {noreply, State#state{client = undefined, caller = undefined}};
+
+handle_ctrl_result({Status, _}, #state{caller = cd} = State) ->
+ ctrl_result_response(Status, State, {error, Status});
+
+handle_ctrl_result(Status={epath, _}, #state{caller = {dir,_}} = State) ->
+ ctrl_result_response(Status, State, {error, epath});
+
+%%--------------------------------------------------------------------------
+%% File renaming
+handle_ctrl_result({pos_interm, _}, #state{caller = {rename, NewFile}}
+ = State) ->
+ _ = send_ctrl_message(State, mk_cmd("RNTO ~s", [NewFile])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = rename_second_phase}};
+
+handle_ctrl_result({Status, _},
+ #state{caller = {rename, _}} = State) ->
+ ctrl_result_response(Status, State, {error, Status});
+
+handle_ctrl_result({Status, _},
+ #state{caller = rename_second_phase} = State) ->
+ ctrl_result_response(Status, State, {error, Status});
+
+%%--------------------------------------------------------------------------
+%% File handling - recv_bin
+handle_ctrl_result({pos_prel, _}, #state{caller = recv_bin} = State0) ->
+ case accept_data_connection(State0) of
+ {ok, State1} ->
+ State = activate_data_connection(State1),
+ {noreply, State};
+ {error, _Reason} = ERROR ->
+ case State0#state.client of
+ undefined ->
+ {stop, ERROR, State0};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State0#state{client = undefined}}
+ end
+ end;
+
+handle_ctrl_result({pos_compl, _}, #state{caller = {recv_bin, Data},
+ client = From} = State) ->
+ gen_server:reply(From, {ok, Data}),
+ close_data_connection(State),
+ {noreply, State#state{client = undefined, caller = undefined}};
+
+handle_ctrl_result({Status, _}, #state{caller = recv_bin} = State) ->
+ close_data_connection(State),
+ ctrl_result_response(Status, State#state{dsock = undefined},
+ {error, epath});
+
+handle_ctrl_result({Status, _}, #state{caller = {recv_bin, _}} = State) ->
+ close_data_connection(State),
+ ctrl_result_response(Status, State#state{dsock = undefined},
+ {error, epath});
+%%--------------------------------------------------------------------------
+%% File handling - start_chunk_transfer
+handle_ctrl_result({pos_prel, _}, #state{client = From,
+ caller = start_chunk_transfer}
+ = State0) ->
+ case accept_data_connection(State0) of
+ {ok, State1} ->
+ State = start_chunk(State1),
+ {noreply, State};
+ {error, _Reason} = ERROR ->
+ case State0#state.client of
+ undefined ->
+ {stop, ERROR, State0};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State0#state{client = undefined}}
+ end
+ end;
+
+%%--------------------------------------------------------------------------
+%% File handling - chunk_transfer complete
+
+handle_ctrl_result({pos_compl, _}, #state{client = From,
+ caller = #recv_chunk_closing{dconn_closed = true,
+ client_called_us = true,
+ pos_compl_received = false
+ }}
+ = State0) when From =/= undefined ->
+ %% The pos_compl was the last event we waited for, finnish and clean up
+ ?DBG("recv_chunk_closing pos_compl, last event",[]),
+ gen_server:reply(From, ok),
+ activate_ctrl_connection(State0),
+ {noreply, State0#state{caller = undefined,
+ chunk = false,
+ client = undefined}};
+
+handle_ctrl_result({pos_compl, _}, #state{caller = #recv_chunk_closing{}=R}
+ = State0) ->
+ %% Waiting for more, don't care what
+ ?DBG("recv_chunk_closing pos_compl, wait more",[]),
+ {noreply, State0#state{caller = R#recv_chunk_closing{pos_compl_received=true}}};
+
+
+%%--------------------------------------------------------------------------
+%% File handling - recv_file
+handle_ctrl_result({pos_prel, _}, #state{caller = {recv_file, _}} = State0) ->
+ case accept_data_connection(State0) of
+ {ok, State1} ->
+ State = activate_data_connection(State1),
+ {noreply, State};
+ {error, _Reason} = ERROR ->
+ case State0#state.client of
+ undefined ->
+ {stop, ERROR, State0};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State0#state{client = undefined}}
+ end
+ end;
+
+handle_ctrl_result({Status, _}, #state{caller = {recv_file, Fd}} = State) ->
+ file_close(Fd),
+ close_data_connection(State),
+ ctrl_result_response(Status, State#state{dsock = undefined},
+ {error, epath});
+%%--------------------------------------------------------------------------
+%% File handling - transfer_*
+handle_ctrl_result({pos_prel, _}, #state{caller = {transfer_file, Fd}}
+ = State0) ->
+ case accept_data_connection(State0) of
+ {ok, State1} ->
+ send_file(State1, Fd);
+ {error, _Reason} = ERROR ->
+ case State0#state.client of
+ undefined ->
+ {stop, ERROR, State0};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State0#state{client = undefined}}
+ end
+ end;
+
+handle_ctrl_result({pos_prel, _}, #state{caller = {transfer_data, Bin}}
+ = State0) ->
+ case accept_data_connection(State0) of
+ {ok, State} ->
+ send_bin(State, Bin);
+ {error, _Reason} = ERROR ->
+ case State0#state.client of
+ undefined ->
+ {stop, ERROR, State0};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State0#state{client = undefined}}
+ end
+ end;
+
+%%--------------------------------------------------------------------------
+%% Default
+handle_ctrl_result({Status, _Lines}, #state{client = From} = State)
+ when From =/= undefined ->
+ ctrl_result_response(Status, State, {error, Status}).
+
+%%--------------------------------------------------------------------------
+%% Help functions to handle_ctrl_result
+%%--------------------------------------------------------------------------
+ctrl_result_response(pos_compl, #state{client = From} = State, _) ->
+ gen_server:reply(From, ok),
+ {noreply, State#state{client = undefined, caller = undefined}};
+
+ctrl_result_response(enofile, #state{client = From} = State, _) ->
+ gen_server:reply(From, {error, enofile}),
+ {noreply, State#state{client = undefined, caller = undefined}};
+
+ctrl_result_response(Status, #state{client = From} = State, _)
+ when (Status =:= etnospc) orelse
+ (Status =:= epnospc) orelse
+ (Status =:= efnamena) orelse
+ (Status =:= econn) ->
+ gen_server:reply(From, {error, Status}),
+%% {stop, normal, {error, Status}, State#state{client = undefined}};
+ {stop, normal, State#state{client = undefined}};
+
+ctrl_result_response(_, #state{client = From} = State, ErrorMsg) ->
+ gen_server:reply(From, ErrorMsg),
+ {noreply, State#state{client = undefined, caller = undefined}}.
+
+%%--------------------------------------------------------------------------
+handle_caller(#state{caller = {dir, Dir, Len}} = State) ->
+ Cmd = case Len of
+ short -> "NLST";
+ long -> "LIST"
+ end,
+ _ = case Dir of
+ "" ->
+ send_ctrl_message(State, mk_cmd(Cmd, ""));
+ _ ->
+ send_ctrl_message(State, mk_cmd(Cmd ++ " ~s", [Dir]))
+ end,
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = {dir, Dir}}};
+
+handle_caller(#state{caller = {recv_bin, RemoteFile}} = State) ->
+ _ = send_ctrl_message(State, mk_cmd("RETR ~s", [RemoteFile])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = recv_bin}};
+
+handle_caller(#state{caller = {start_chunk_transfer, Cmd, RemoteFile}} =
+ State) ->
+ _ = send_ctrl_message(State, mk_cmd("~s ~s", [Cmd, RemoteFile])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = start_chunk_transfer}};
+
+handle_caller(#state{caller = {recv_file, RemoteFile, Fd}} = State) ->
+ _ = send_ctrl_message(State, mk_cmd("RETR ~s", [RemoteFile])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = {recv_file, Fd}}};
+
+handle_caller(#state{caller = {transfer_file, {Cmd, LocalFile, RemoteFile}},
+ ldir = LocalDir, client = From} = State) ->
+ case file_open(filename:absname(LocalFile, LocalDir), read) of
+ {ok, Fd} ->
+ _ = send_ctrl_message(State, mk_cmd("~s ~s", [Cmd, RemoteFile])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = {transfer_file, Fd}}};
+ {error, _} ->
+ gen_server:reply(From, {error, epath}),
+ {noreply, State#state{client = undefined, caller = undefined,
+ dsock = undefined}}
+ end;
+
+handle_caller(#state{caller = {transfer_data, {Cmd, Bin, RemoteFile}}} =
+ State) ->
+ _ = send_ctrl_message(State, mk_cmd("~s ~s", [Cmd, RemoteFile])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = {transfer_data, Bin}}}.
+
+%% ----------- FTP SERVER COMMUNICATION -------------------------
+
+%% Connect to FTP server at Host (default is TCP port 21)
+%% in order to establish a control connection.
+setup_ctrl_connection(Host, Port, Timeout, #state{sockopts_ctrl = SockOpts} = State) ->
+ MsTime = erlang:monotonic_time(),
+ case connect(Host, Port, SockOpts, Timeout, State) of
+ {ok, IpFam, CSock} ->
+ NewState = State#state{csock = {tcp, CSock}, ipfamily = IpFam},
+ activate_ctrl_connection(NewState),
+ case Timeout - millisec_passed(MsTime) of
+ Timeout2 when (Timeout2 >= 0) ->
+ {ok, NewState#state{caller = open}, Timeout2};
+ _ ->
+ %% Oups: Simulate timeout
+ {ok, NewState#state{caller = open}, 0}
+ end;
+ Error ->
+ Error
+ end.
+
+setup_data_connection(#state{mode = active,
+ caller = Caller,
+ csock = CSock,
+ sockopts_data_active = SockOpts,
+ ftp_extension = FtpExt} = State) ->
+ case (catch sockname(CSock)) of
+ {ok, {{_, _, _, _, _, _, _, _} = IP0, _}} ->
+ IP = proplists:get_value(ip, SockOpts, IP0),
+ {ok, LSock} =
+ gen_tcp:listen(0, [{ip, IP}, {active, false},
+ inet6, binary, {packet, 0} |
+ lists:keydelete(ip,1,SockOpts)]),
+ {ok, {_, Port}} = sockname({tcp,LSock}),
+ IpAddress = inet_parse:ntoa(IP),
+ Cmd = mk_cmd("EPRT |2|~s|~p|", [IpAddress, Port]),
+ _ = send_ctrl_message(State, Cmd),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = {setup_data_connection,
+ {LSock, Caller}}}};
+ {ok, {{_,_,_,_} = IP0, _}} ->
+ IP = proplists:get_value(ip, SockOpts, IP0),
+ {ok, LSock} = gen_tcp:listen(0, [{ip, IP}, {active, false},
+ binary, {packet, 0} |
+ lists:keydelete(ip,1,SockOpts)]),
+ {ok, Port} = inet:port(LSock),
+ _ = case FtpExt of
+ false ->
+ {IP1, IP2, IP3, IP4} = IP,
+ {Port1, Port2} = {Port div 256, Port rem 256},
+ send_ctrl_message(State,
+ mk_cmd("PORT ~w,~w,~w,~w,~w,~w",
+ [IP1, IP2, IP3, IP4, Port1, Port2]));
+ true ->
+ IpAddress = inet_parse:ntoa(IP),
+ Cmd = mk_cmd("EPRT |1|~s|~p|", [IpAddress, Port]),
+ send_ctrl_message(State, Cmd)
+ end,
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = {setup_data_connection,
+ {LSock, Caller}}}}
+ end;
+
+setup_data_connection(#state{mode = passive, ipfamily = inet6,
+ caller = Caller} = State) ->
+ _ = send_ctrl_message(State, mk_cmd("EPSV", [])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = {setup_data_connection, Caller}}};
+
+setup_data_connection(#state{mode = passive, ipfamily = inet,
+ caller = Caller,
+ ftp_extension = false} = State) ->
+ _ = send_ctrl_message(State, mk_cmd("PASV", [])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = {setup_data_connection, Caller}}};
+
+setup_data_connection(#state{mode = passive, ipfamily = inet,
+ caller = Caller,
+ ftp_extension = true} = State) ->
+ _ = send_ctrl_message(State, mk_cmd("EPSV", [])),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = {setup_data_connection, Caller}}}.
+
+connect(Host, Port, SockOpts, Timeout, #state{ipfamily = inet = IpFam}) ->
+ connect2(Host, Port, IpFam, SockOpts, Timeout);
+
+connect(Host, Port, SockOpts, Timeout, #state{ipfamily = inet6 = IpFam}) ->
+ connect2(Host, Port, IpFam, SockOpts, Timeout);
+
+connect(Host, Port, SockOpts, Timeout, #state{ipfamily = inet6fb4}) ->
+ case inet:getaddr(Host, inet6) of
+ {ok, {0, 0, 0, 0, 0, 16#ffff, _, _} = IPv6} ->
+ case inet:getaddr(Host, inet) of
+ {ok, IPv4} ->
+ IpFam = inet,
+ connect2(IPv4, Port, IpFam, SockOpts, Timeout);
+
+ _ ->
+ IpFam = inet6,
+ connect2(IPv6, Port, IpFam, SockOpts, Timeout)
+ end;
+
+ {ok, IPv6} ->
+ IpFam = inet6,
+ connect2(IPv6, Port, IpFam, SockOpts, Timeout);
+
+ _ ->
+ case inet:getaddr(Host, inet) of
+ {ok, IPv4} ->
+ IpFam = inet,
+ connect2(IPv4, Port, IpFam, SockOpts, Timeout);
+ Error ->
+ Error
+ end
+ end.
+
+connect2(Host, Port, IpFam, SockOpts, Timeout) ->
+ Opts = [IpFam, binary, {packet, 0}, {active, false} | SockOpts],
+ case gen_tcp:connect(Host, Port, Opts, Timeout) of
+ {ok, Sock} ->
+ {ok, IpFam, Sock};
+ Error ->
+ Error
+ end.
+
+
+accept_data_connection(#state{mode = active,
+ dtimeout = DTimeout,
+ tls_options = TLSOptions,
+ dsock = {lsock, LSock}} = State0) ->
+ case gen_tcp:accept(LSock, DTimeout) of
+ {ok, Socket} when is_list(TLSOptions) ->
+ gen_tcp:close(LSock),
+ ?DBG('<--data ssl:connect(~p, ~p)~n~p~n',[Socket,TLSOptions,State0]),
+ case ssl:connect(Socket, TLSOptions, DTimeout) of
+ {ok, TLSSocket} ->
+ {ok, State0#state{dsock={ssl,TLSSocket}}};
+ {error, Reason} ->
+ {error, {ssl_connect_failed, Reason}}
+ end;
+ {ok, Socket} ->
+ gen_tcp:close(LSock),
+ {ok, State0#state{dsock={tcp,Socket}}};
+ {error, Reason} ->
+ {error, {data_connect_failed, Reason}}
+ end;
+
+accept_data_connection(#state{mode = passive,
+ dtimeout = DTimeout,
+ dsock = {tcp,Socket},
+ tls_options = TLSOptions} = State) when is_list(TLSOptions) ->
+ ?DBG('<--data ssl:connect(~p, ~p)~n~p~n',[Socket,TLSOptions,State]),
+ case ssl:connect(Socket, TLSOptions, DTimeout) of
+ {ok, TLSSocket} ->
+ {ok, State#state{dsock={ssl,TLSSocket}}};
+ {error, Reason} ->
+ {error, {ssl_connect_failed, Reason}}
+ end;
+accept_data_connection(#state{mode = passive} = State) ->
+ {ok,State}.
+
+
+send_ctrl_message(_S=#state{csock = Socket, verbose = Verbose}, Message) ->
+ verbose(lists:flatten(Message),Verbose,send),
+ ?DBG('<--ctrl ~p ---- ~s~p~n',[Socket,Message,_S]),
+ _ = send_message(Socket, Message).
+
+send_data_message(_S=#state{dsock = Socket}, Message) ->
+ ?DBG('<==data ~p ==== ~s~n~p~n',[Socket,Message,_S]),
+ case send_message(Socket, Message) of
+ ok ->
+ ok;
+ {error, Reason} ->
+ Report = io_lib:format("send/2 for socket ~p failed with "
+ "reason ~p~n", [Socket, Reason]),
+ error_logger:error_report(Report),
+ %% If tcp/ssl does not work the only option is to terminate,
+ %% this is the expected behavior under these circumstances.
+ exit(normal) %% User will get error message from terminate/2
+ end.
+
+send_message({tcp, Socket}, Message) ->
+ gen_tcp:send(Socket, Message);
+send_message({ssl, Socket}, Message) ->
+ ssl:send(Socket, Message).
+
+activate_ctrl_connection(#state{csock = CSock, ctrl_data = {<<>>, _, _}}) ->
+ activate_connection(CSock);
+activate_ctrl_connection(#state{csock = CSock}) ->
+ activate_connection(CSock),
+ %% We have already received at least part of the next control message,
+ %% that has been saved in ctrl_data, process this first.
+ self() ! {socket_type(CSock), unwrap_socket(CSock), <<>>},
+ ok.
+
+activate_data_connection(#state{dsock = DSock} = State) ->
+ activate_connection(DSock),
+ State.
+
+activate_connection(Socket) ->
+ ignore_return_value(
+ case socket_type(Socket) of
+ tcp -> inet:setopts(unwrap_socket(Socket), [{active, once}]);
+ ssl -> ssl:setopts(unwrap_socket(Socket), [{active, once}])
+ end).
+
+
+ignore_return_value(_) -> ok.
+
+unwrap_socket({tcp,Socket}) -> Socket;
+unwrap_socket({ssl,Socket}) -> Socket.
+
+socket_type({tcp,_Socket}) -> tcp;
+socket_type({ssl,_Socket}) -> ssl.
+
+close_ctrl_connection(#state{csock = undefined}) -> ok;
+close_ctrl_connection(#state{csock = Socket}) -> close_connection(Socket).
+
+close_data_connection(#state{dsock = undefined}) -> ok;
+close_data_connection(#state{dsock = Socket}) -> close_connection(Socket).
+
+close_connection({lsock,Socket}) -> ignore_return_value( gen_tcp:close(Socket) );
+close_connection({tcp, Socket}) -> ignore_return_value( gen_tcp:close(Socket) );
+close_connection({ssl, Socket}) -> ignore_return_value( ssl:close(Socket) ).
+
+%% ------------ FILE HANDLING ----------------------------------------
+send_file(#state{tls_upgrading_data_connection = {true, CTRL, _}} = State, Fd) ->
+ {noreply, State#state{tls_upgrading_data_connection = {true, CTRL, ?MODULE, send_file, Fd}}};
+send_file(State, Fd) ->
+ case file_read(Fd) of
+ {ok, N, Bin} when N > 0 ->
+ send_data_message(State, Bin),
+ progress_report({binary, Bin}, State),
+ send_file(State, Fd);
+ {ok, _, _} ->
+ file_close(Fd),
+ close_data_connection(State),
+ progress_report({transfer_size, 0}, State),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = transfer_file_second_phase,
+ dsock = undefined}};
+ {error, Reason} ->
+ gen_server:reply(State#state.client, {error, Reason}),
+ {stop, normal, State#state{client = undefined}}
+ end.
+
+file_open(File, Option) ->
+ file:open(File, [raw, binary, Option]).
+
+file_close(Fd) ->
+ ignore_return_value( file:close(Fd) ).
+
+file_read(Fd) ->
+ case file:read(Fd, ?FILE_BUFSIZE) of
+ {ok, Bytes} ->
+ {ok, size(Bytes), Bytes};
+ eof ->
+ {ok, 0, []};
+ Other ->
+ Other
+ end.
+
+file_write(Bytes, Fd) ->
+ file:write(Fd, Bytes).
+
+%% -------------- MISC ----------------------------------------------
+
+call(GenServer, Msg, Format) ->
+ call(GenServer, Msg, Format, infinity).
+call(GenServer, Msg, Format, Timeout) ->
+ Req = {self(), Msg},
+ case (catch gen_server:call(GenServer, Req, Timeout)) of
+ {ok, Bin} when is_binary(Bin) andalso (Format =:= string) ->
+ {ok, binary_to_list(Bin)};
+ {'EXIT', _} ->
+ {error, eclosed};
+ Result ->
+ Result
+ end.
+
+cast(GenServer, Msg) ->
+ gen_server:cast(GenServer, {self(), Msg}).
+
+send_bin(#state{tls_upgrading_data_connection = {true, CTRL, _}} = State, Bin) ->
+ State#state{tls_upgrading_data_connection = {true, CTRL, ?MODULE, send_bin, Bin}};
+send_bin(State, Bin) ->
+ send_data_message(State, Bin),
+ close_data_connection(State),
+ activate_ctrl_connection(State),
+ {noreply, State#state{caller = transfer_data_second_phase,
+ dsock = undefined}}.
+
+mk_cmd(Fmt, Args) ->
+ [io_lib:format(Fmt, Args)| [?CR, ?LF]]. % Deep list ok.
+
+is_name_sane([]) ->
+ true;
+is_name_sane([?CR| _]) ->
+ false;
+is_name_sane([?LF| _]) ->
+ false;
+is_name_sane([_| Rest]) ->
+ is_name_sane(Rest).
+
+pwd_result(Lines) ->
+ {_, [?DOUBLE_QUOTE | Rest]} =
+ lists:splitwith(fun(?DOUBLE_QUOTE) -> false; (_) -> true end, Lines),
+ {Dir, _} =
+ lists:splitwith(fun(?DOUBLE_QUOTE) -> false; (_) -> true end, Rest),
+ Dir.
+
+
+key_search(Key, List, Default) ->
+ case lists:keysearch(Key, 1, List) of
+ {value, {_,Val}} ->
+ Val;
+ false ->
+ Default
+ end.
+
+verbose(Lines, true, Direction) ->
+ DirStr =
+ case Direction of
+ send ->
+ "Sending: ";
+ _ ->
+ "Receiving: "
+ end,
+ Str = string:strip(string:strip(Lines, right, ?LF), right, ?CR),
+ erlang:display(DirStr++Str);
+verbose(_, false,_) ->
+ ok.
+
+progress(Options) ->
+ ftp_progress:start_link(Options).
+
+progress_report(_, #state{progress = ignore}) ->
+ ok;
+progress_report(stop, #state{progress = ProgressPid}) ->
+ ftp_progress:stop(ProgressPid);
+progress_report({binary, Data}, #state{progress = ProgressPid}) ->
+ ftp_progress:report(ProgressPid, {transfer_size, size(Data)});
+progress_report(Report, #state{progress = ProgressPid}) ->
+ ftp_progress:report(ProgressPid, Report).
+
+
+peername({tcp, Socket}) -> inet:peername(Socket);
+peername({ssl, Socket}) -> ssl:peername(Socket).
+
+sockname({tcp, Socket}) -> inet:sockname(Socket);
+sockname({ssl, Socket}) -> ssl:sockname(Socket).
+
+maybe_tls_upgrade(Pid, undefined) ->
+ {ok, Pid};
+maybe_tls_upgrade(Pid, TLSOptions) ->
+ catch ssl:start(),
+ call(Pid, {open, tls_upgrade, TLSOptions}, plain).
+
+start_chunk(#state{tls_upgrading_data_connection = {true, CTRL, _}} = State) ->
+ State#state{tls_upgrading_data_connection = {true, CTRL, ?MODULE, start_chunk, undefined}};
+start_chunk(#state{client = From} = State) ->
+ gen_server:reply(From, ok),
+ State#state{chunk = true,
+ client = undefined,
+ caller = undefined}.
+
+
+%% This function extracts the start options from the
+%% Valid options:
+%% debug,
+%% verbose
+%% ipfamily
+%% priority
+%% flags (for backward compatibillity)
+start_options(Options) ->
+ case lists:keysearch(flags, 1, Options) of
+ {value, {flags, Flags}} ->
+ Verbose = lists:member(verbose, Flags),
+ IsTrace = lists:member(trace, Flags),
+ IsDebug = lists:member(debug, Flags),
+ DebugLevel =
+ if
+ (IsTrace =:= true) ->
+ trace;
+ IsDebug =:= true ->
+ debug;
+ true ->
+ disable
+ end,
+ {ok, [{verbose, Verbose},
+ {debug, DebugLevel},
+ {priority, low}]};
+ false ->
+ ValidateVerbose =
+ fun(true) -> true;
+ (false) -> true;
+ (_) -> false
+ end,
+ ValidateDebug =
+ fun(trace) -> true;
+ (debug) -> true;
+ (disable) -> true;
+ (_) -> false
+ end,
+ ValidatePriority =
+ fun(low) -> true;
+ (normal) -> true;
+ (high) -> true;
+ (_) -> false
+ end,
+ ValidOptions =
+ [{verbose, ValidateVerbose, false, false},
+ {debug, ValidateDebug, false, disable},
+ {priority, ValidatePriority, false, low}],
+ validate_options(Options, ValidOptions, [])
+ end.
+
+
+%% This function extracts and validates the open options from the
+%% Valid options:
+%% mode
+%% host
+%% port
+%% timeout
+%% dtimeout
+%% progress
+%% ftp_extension
+
+open_options(Options) ->
+ ValidateMode =
+ fun(active) -> true;
+ (passive) -> true;
+ (_) -> false
+ end,
+ ValidateHost =
+ fun(Host) when is_list(Host) ->
+ true;
+ (Host) when is_tuple(Host) andalso
+ ((size(Host) =:= 4) orelse (size(Host) =:= 8)) ->
+ true;
+ (_) ->
+ false
+ end,
+ ValidatePort =
+ fun(Port) when is_integer(Port) andalso (Port > 0) -> true;
+ (_) -> false
+ end,
+ ValidateIpFamily =
+ fun(inet) -> true;
+ (inet6) -> true;
+ (inet6fb4) -> true;
+ (_) -> false
+ end,
+ ValidateTimeout =
+ fun(Timeout) when is_integer(Timeout) andalso (Timeout >= 0) -> true;
+ (_) -> false
+ end,
+ ValidateDTimeout =
+ fun(DTimeout) when is_integer(DTimeout) andalso (DTimeout >= 0) -> true;
+ (infinity) -> true;
+ (_) -> false
+ end,
+ ValidateProgress =
+ fun(ignore) ->
+ true;
+ ({Mod, Func, _InitProgress}) when is_atom(Mod) andalso
+ is_atom(Func) ->
+ true;
+ (_) ->
+ false
+ end,
+ ValidateFtpExtension =
+ fun(true) -> true;
+ (false) -> true;
+ (_) -> false
+ end,
+ ValidOptions =
+ [{mode, ValidateMode, false, ?DEFAULT_MODE},
+ {host, ValidateHost, true, ehost},
+ {port, ValidatePort, false, ?FTP_PORT},
+ {ipfamily, ValidateIpFamily, false, inet},
+ {timeout, ValidateTimeout, false, ?CONNECTION_TIMEOUT},
+ {dtimeout, ValidateDTimeout, false, ?DATA_ACCEPT_TIMEOUT},
+ {progress, ValidateProgress, false, ?PROGRESS_DEFAULT},
+ {ftp_extension, ValidateFtpExtension, false, ?FTP_EXT_DEFAULT}],
+ validate_options(Options, ValidOptions, []).
+
+socket_options(Options) ->
+ CtrlOpts = proplists:get_value(sock_ctrl, Options, []),
+ DataActOpts = proplists:get_value(sock_data_act, Options, CtrlOpts),
+ DataPassOpts = proplists:get_value(sock_data_pass, Options, CtrlOpts),
+ case [O || O <- lists:usort(CtrlOpts++DataPassOpts++DataActOpts),
+ not valid_socket_option(O)] of
+ [] ->
+ {ok, {CtrlOpts, DataPassOpts, DataActOpts}};
+ Invalid ->
+ throw({error,{sock_opts,Invalid}})
+ end.
+
+
+valid_socket_option(inet ) -> false;
+valid_socket_option(inet6 ) -> false;
+valid_socket_option({ipv6_v6only, _}) -> false;
+valid_socket_option({active,_} ) -> false;
+valid_socket_option({packet,_} ) -> false;
+valid_socket_option({mode,_} ) -> false;
+valid_socket_option(binary ) -> false;
+valid_socket_option(list ) -> false;
+valid_socket_option({header,_} ) -> false;
+valid_socket_option({packet_size,_} ) -> false;
+valid_socket_option(_) -> true.
+
+
+tls_options(Options) ->
+ %% Options will be validated by ssl application
+ proplists:get_value(tls, Options, undefined).
+
+validate_options([], [], Acc) ->
+ {ok, lists:reverse(Acc)};
+validate_options([], ValidOptions, Acc) ->
+ %% Check if any mandatory options are missing!
+ case [{Key, Reason} || {Key, _, true, Reason} <- ValidOptions] of
+ [] ->
+ Defaults =
+ [{Key, Default} || {Key, _, _, Default} <- ValidOptions],
+ {ok, lists:reverse(Defaults ++ Acc)};
+ [{_, Reason}|_Missing] ->
+ throw({error, Reason})
+ end;
+validate_options([{Key, Value}|Options], ValidOptions, Acc) ->
+ case lists:keysearch(Key, 1, ValidOptions) of
+ {value, {Key, Validate, _, Default}} ->
+ case (catch Validate(Value)) of
+ true ->
+ NewValidOptions = lists:keydelete(Key, 1, ValidOptions),
+ validate_options(Options, NewValidOptions,
+ [{Key, Value} | Acc]);
+ _ ->
+ NewValidOptions = lists:keydelete(Key, 1, ValidOptions),
+ validate_options(Options, NewValidOptions,
+ [{Key, Default} | Acc])
+ end;
+ false ->
+ validate_options(Options, ValidOptions, Acc)
+ end;
+validate_options([_|Options], ValidOptions, Acc) ->
+ validate_options(Options, ValidOptions, Acc).
+
+%% Help function, elapsed milliseconds since T0
+millisec_passed(T0) ->
+ %% OTP 18
+ erlang:convert_time_unit(erlang:monotonic_time() - T0,
+ native,
+ micro_seconds) div 1000.
diff --git a/lib/ftp/src/ftp_app.erl b/lib/ftp/src/ftp_app.erl
new file mode 100644
index 0000000000..d647d9fce3
--- /dev/null
+++ b/lib/ftp/src/ftp_app.erl
@@ -0,0 +1,47 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%
+%%
+
+%%%-------------------------------------------------------------------
+%% @doc ftp public API
+%% @end
+%%%-------------------------------------------------------------------
+
+-module(ftp_app).
+
+-behaviour(application).
+
+%% Application callbacks
+-export([start/2, stop/1]).
+
+%%====================================================================
+%% API
+%%====================================================================
+
+start(_StartType, _StartArgs) ->
+ ftp_sup:start_link().
+
+%%--------------------------------------------------------------------
+stop(_State) ->
+ ok.
+
+%%====================================================================
+%% Internal functions
+%%====================================================================
diff --git a/lib/ftp/src/ftp_internal.hrl b/lib/ftp/src/ftp_internal.hrl
new file mode 100644
index 0000000000..84f980e8fd
--- /dev/null
+++ b/lib/ftp/src/ftp_internal.hrl
@@ -0,0 +1,35 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%
+%%
+
+-ifndef(ftp_internal_hrl).
+-define(ftp_internal_hrl, true).
+
+-define(CR, $\r).
+-define(LF, $\n).
+-define(CRLF, [$\r,$\n]).
+-define(SP, $\s).
+-define(TAB, $\t).
+-define(LEFT_PAREN, $().
+-define(RIGHT_PAREN, $)).
+-define(WHITE_SPACE, $ ).
+-define(DOUBLE_QUOTE, $").
+
+-endif. % -ifdef(ftp_internal_hrl).
diff --git a/lib/ftp/src/ftp_progress.erl b/lib/ftp/src/ftp_progress.erl
new file mode 100644
index 0000000000..64c612519d
--- /dev/null
+++ b/lib/ftp/src/ftp_progress.erl
@@ -0,0 +1,136 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%
+%%
+%% Description: This module impements a temporary process that
+%% performes progress reporting during file transfer calling a user
+%% defined callback function. Its life span is as long as the ftp connection
+%% processes that spawned it lives. The purpose of this process is to
+%% shild the ftp connection process from errors and time consuming operations
+%% in the user defined callback function.
+
+-module(ftp_progress).
+
+%% Internal API
+-export([start_link/1, report/2, stop/1]).
+
+%% Spawn export
+-export([init/1]).
+
+-include_lib("kernel/include/file.hrl").
+
+-record(progress, {
+ file :: string() | 'undefined',
+ cb_module :: module(),
+ cb_function :: atom(),
+ init_progress_term :: term(),
+ current_progress_term :: term()
+ }).
+
+%%%=========================================================================
+%%% Internal application API
+%%%=========================================================================
+%%--------------------------------------------------------------------------
+%% start_link(Options) -> ignore | pid()
+%% Options = ignore | {CBModule, CBFunction, InitProgressTerm}
+%%
+%% Description: Starts the progress report process unless progress reporting
+%% should not be performed.
+%%--------------------------------------------------------------------------
+-type options() :: 'ignore' | {module(), atom(), term()}.
+-spec start_link(options()) -> 'ignore' | pid().
+start_link(ignore) ->
+ ignore;
+start_link(Options) ->
+ spawn_link(?MODULE, init, [Options]).
+
+%%--------------------------------------------------------------------------
+%% report_progress(Pid, Report) -> ok
+%% Pid = pid()
+%% Report = {local_file, File} | {remote_file, File} |
+%% {transfer_size, Size}
+%% Size = integer()
+%%
+%% Description: Reports progress to the reporting process that calls the
+%% user defined callback function.
+%%--------------------------------------------------------------------------
+-type report() :: {'local_file', string()} | {'remote_file', string()}
+ | {'transfer_size', non_neg_integer()}.
+-spec report(pid(), report()) -> 'ok'.
+report(Pid, Report) ->
+ Pid ! {progress_report, Report},
+ ok.
+
+%%--------------------------------------------------------------------------
+%% stop(Pid) -> ok
+%% Pid = pid()
+%%
+%% Description:
+%%--------------------------------------------------------------------------
+-spec stop(pid()) -> 'ok'.
+stop(Pid) ->
+ Pid ! stop,
+ ok.
+
+%%%=========================================================================
+%%% Internal functions
+%%%=========================================================================
+init(Options) ->
+ loop(progress(Options)).
+
+loop(Progress) ->
+ receive
+ {progress_report, Report} ->
+ NewProgress = report_progress(Report, Progress),
+ loop(NewProgress);
+ stop ->
+ ok
+ end.
+
+progress({CBModule, CBFunction, InitProgressTerm}) when is_atom(CBModule),
+ is_atom(CBFunction) ->
+ #progress{cb_module = CBModule,
+ cb_function = CBFunction,
+ init_progress_term = InitProgressTerm,
+ current_progress_term = InitProgressTerm}.
+
+report_progress({local_file, File}, Progress) ->
+ {ok, FileInfo} = file:read_file_info(File),
+ report_progress({file_size, FileInfo#file_info.size},
+ Progress#progress{file = File});
+
+report_progress({remote_file, File}, Progress) ->
+ report_progress({file_size, unknown}, Progress#progress{file = File});
+
+report_progress(Size, #progress{file = File,
+ cb_module = CBModule,
+ cb_function = CBFunction,
+ current_progress_term = Term,
+ init_progress_term = InitTerm} = Progress) ->
+
+ NewProgressTerm = CBModule:CBFunction(Term, File, Size),
+
+ case Size of
+ {transfer_size, 0} ->
+ %% Transfer is compleat reset initial values
+ Progress#progress{current_progress_term = InitTerm,
+ file = undefined};
+ _ ->
+ Progress#progress{current_progress_term = NewProgressTerm}
+ end.
diff --git a/lib/ftp/src/ftp_response.erl b/lib/ftp/src/ftp_response.erl
new file mode 100644
index 0000000000..8d00153ba8
--- /dev/null
+++ b/lib/ftp/src/ftp_response.erl
@@ -0,0 +1,203 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%
+%%
+%% Description: This module impements handling of ftp server responses.
+
+-module(ftp_response).
+
+%% Internal API
+-export([parse_lines/3, interpret/1, error_string/1]).
+
+-include("ftp_internal.hrl").
+
+%% First group of reply code digits
+-define(POS_PREL, 1).
+-define(POS_COMPL, 2).
+-define(POS_INTERM, 3).
+-define(TRANS_NEG_COMPL, 4).
+-define(PERM_NEG_COMPL, 5).
+%% Second group of reply code digits
+-define(SYNTAX,0).
+-define(INFORMATION,1).
+-define(CONNECTION,2).
+-define(AUTH_ACC,3).
+-define(UNSPEC,4).
+-define(FILE_SYSTEM,5).
+
+%%%=========================================================================
+%%% INTERNAL API
+%%%=========================================================================
+
+%%--------------------------------------------------------------------------
+%% parse_lines(Data, AccLines, StatusCode) -> {ok, Lines} |
+%% {continue, {Data,
+%% AccLines, StatusCode}}
+%%
+%% Data = binary() - data recived on the control connection from the
+%% ftp-server.
+%% AccLines = [string()]
+%% StatusCode = start | {byte(), byte(), byte()} | finish -
+%% Indicates where in the parsing process we are.
+%% start - (looking for the status code of the message)
+%% {byte(), byte(), byte()} - status code found, now
+%% looking for the last line indication.
+%% finish - now on the last line.
+%% Description: Parses a ftp control response message.
+%% "A reply is defined to contain the 3-digit code, followed by Space
+%% <SP>, followed by one line of text (where some maximum line length
+%% has been specified), and terminated by the Telnet end-of-line
+%% code (CRLF), or a so called multilined reply for example:
+%%
+%% 123-First line
+%% Second line
+%% 234 A line beginning with numbers
+%% 123 The last line
+%%
+%% The user-process then simply needs to search for the second
+%% occurrence of the same reply code, followed by <SP> (Space), at
+%% the beginning of a line, and ignore all intermediary lines. If
+%% an intermediary line begins with a 3-digit number, the Server
+%% will pad the front to avoid confusion.
+%%--------------------------------------------------------------------------
+
+%% Make sure we received the first 4 bytes so we know how to parse
+%% the FTP server response e.i. is the response composed of one
+%% or multiple lines.
+parse_lines(Bin, Lines, start) when size(Bin) < 4 ->
+ {continue, {Bin, Lines, start}};
+%% Multiple lines exist
+parse_lines(<<C1, C2, C3, $-, Rest/binary>>, Lines, start) ->
+ parse_lines(Rest, [$-, C3, C2, C1 | Lines], {C1, C2, C3});
+%% Only one line exists
+parse_lines(<<C1, C2, C3, ?WHITE_SPACE, Bin/binary>>, Lines, start) ->
+ parse_lines(Bin, [?WHITE_SPACE, C3, C2, C1 | Lines], finish);
+
+%% Last line found
+parse_lines(<<?CR, ?LF, C1, C2, C3, ?WHITE_SPACE, Rest/binary>>, Lines, {C1, C2, C3}) ->
+ parse_lines(Rest, [?WHITE_SPACE, C3, C2, C1, ?LF, ?CR | Lines], finish);
+%% Potential end found wait for more data
+parse_lines(<<?CR, ?LF, C1, C2, C3>> = Bin, Lines, {C1, C2, C3}) ->
+ {continue, {Bin, Lines, {C1, C2, C3}}};
+%% Intermidate line begining with status code
+parse_lines(<<?CR, ?LF, C1, C2, C3, Rest/binary>>, Lines, {C1, C2, C3}) ->
+ parse_lines(Rest, [C3, C2, C1, ?LF, ?CR | Lines], {C1, C2, C3});
+
+%% Potential last line wait for more data
+parse_lines(<<?CR, ?LF, C1, C2>> = Data, Lines, {C1, C2, _} = StatusCode) ->
+ {continue, {Data, Lines, StatusCode}};
+parse_lines(<<?CR, ?LF, C1>> = Data, Lines, {C1, _, _} = StatusCode) ->
+ {continue, {Data, Lines, StatusCode}};
+parse_lines(<<?CR, ?LF>> = Data, Lines, {_,_,_} = StatusCode) ->
+ {continue, {Data, Lines, StatusCode}};
+parse_lines(<<?LF>> = Data, Lines, {_,_,_} = StatusCode) ->
+ {continue, {Data, Lines, StatusCode}};
+parse_lines(<<>> = Data, Lines, {_,_,_} = StatusCode) ->
+ {continue, {Data, Lines, StatusCode}};
+%% Part of the multiple lines
+parse_lines(<<Octet, Rest/binary>>, Lines, {_,_, _} = StatusCode) ->
+ parse_lines(Rest, [Octet | Lines], StatusCode);
+
+%% End of FTP server response found
+parse_lines(<<?CR, ?LF>>, Lines, finish) ->
+ {ok, lists:reverse([?LF, ?CR | Lines]), <<>>};
+parse_lines(<<?CR, ?LF, Rest/binary>>, Lines, finish) ->
+ {ok, lists:reverse([?LF, ?CR | Lines]), Rest};
+
+%% Potential end found wait for more data
+parse_lines(<<?CR>> = Data, Lines, finish) ->
+ {continue, {Data, Lines, finish}};
+parse_lines(<<>> = Data, Lines, finish) ->
+ {continue, {Data, Lines, finish}};
+%% Part of last line
+parse_lines(<<Octet, Rest/binary>>, Lines, finish) ->
+ parse_lines(Rest, [Octet | Lines], finish).
+
+%%--------------------------------------------------------------------------
+%% interpret(Lines) -> {Status, Text}
+%% Lines = [byte(), byte(), byte() | Text] - ftp server response as
+%% returned by parse_lines/3
+%% Stauts = atom() (see interpret_status/3)
+%% Text = [string()]
+%%
+%% Description: Create nicer data to match on.
+%%--------------------------------------------------------------------------
+interpret([Didgit1, Didgit2, Didgit3 | Data]) ->
+ Code1 = Didgit1 - $0,
+ Code2 = Didgit2 - $0,
+ Code3 = Didgit3 - $0,
+ {interpret_status(Code1, Code2, Code3), Data}.
+
+%%--------------------------------------------------------------------------
+%% error_string(Error) -> string()
+%% Error = {error, term()} | term()
+%%
+%% Description: Translates error codes into strings intended for
+%% human interpretation.
+%%--------------------------------------------------------------------------
+error_string({error, Reason}) ->
+ error_string(Reason);
+
+error_string(echunk) -> "Synchronisation error during chunk sending.";
+error_string(eclosed) -> "Session has been closed.";
+error_string(econn) -> "Connection to remote server prematurely closed.";
+error_string(eexists) ->"File or directory already exists.";
+error_string(ehost) -> "Host not found, FTP server not found, "
+ "or connection rejected.";
+error_string(elogin) -> "User not logged in.";
+error_string(enotbinary) -> "Term is not a binary.";
+error_string(epath) -> "No such file or directory, already exists, "
+ "or permission denied.";
+error_string(etype) -> "No such type.";
+error_string(euser) -> "User name or password not valid.";
+error_string(etnospc) -> "Insufficient storage space in system.";
+error_string(enofile) -> "No files found or file unavailable";
+error_string(epnospc) -> "Exceeded storage allocation "
+ "(for current directory or dataset).";
+error_string(efnamena) -> "File name not allowed.";
+error_string(Reason) ->
+ lists:flatten(io_lib:format("Unknown error: ~w", [Reason])).
+
+%%%========================================================================
+%%% Internal functions
+%%%========================================================================
+
+%% Positive Preleminary Reply
+interpret_status(?POS_PREL,_,_) -> pos_prel;
+%%FIXME ??? 3??? interpret_status(?POS_COMPL, ?AUTH_ACC, 3) -> tls_upgrade;
+interpret_status(?POS_COMPL, ?AUTH_ACC, 4) -> tls_upgrade;
+%% Positive Completion Reply
+interpret_status(?POS_COMPL,_,_) -> pos_compl;
+%% Positive Intermediate Reply nedd account
+interpret_status(?POS_INTERM,?AUTH_ACC,2) -> pos_interm_acct;
+%% Positive Intermediate Reply
+interpret_status(?POS_INTERM,_,_) -> pos_interm;
+%% No files found or file not available
+interpret_status(?TRANS_NEG_COMPL,?FILE_SYSTEM,0) -> enofile;
+%% No storage area no action taken
+interpret_status(?TRANS_NEG_COMPL,?FILE_SYSTEM,2) -> etnospc;
+%% Temporary Error, no action taken
+interpret_status(?TRANS_NEG_COMPL,_,_) -> trans_neg_compl;
+%% Permanent disk space error, the user shall not try again
+interpret_status(?PERM_NEG_COMPL,?FILE_SYSTEM,0) -> epath;
+interpret_status(?PERM_NEG_COMPL,?FILE_SYSTEM,2) -> epnospc;
+interpret_status(?PERM_NEG_COMPL,?FILE_SYSTEM,3) -> efnamena;
+interpret_status(?PERM_NEG_COMPL,?AUTH_ACC,0) -> elogin;
+interpret_status(?PERM_NEG_COMPL,_,_) -> perm_neg_compl.
+
diff --git a/lib/ftp/src/ftp_sup.erl b/lib/ftp/src/ftp_sup.erl
new file mode 100644
index 0000000000..f30046802f
--- /dev/null
+++ b/lib/ftp/src/ftp_sup.erl
@@ -0,0 +1,68 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%
+%%
+
+%%%-------------------------------------------------------------------
+%% @doc ftp top level supervisor.
+%% @end
+%%%-------------------------------------------------------------------
+
+-module(ftp_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_child/1, start_link/0]).
+
+%% Supervisor callbacks
+-export([init/1]).
+
+-define(SERVER, ?MODULE).
+
+%%====================================================================
+%% API functions
+%%====================================================================
+
+start_link() ->
+ supervisor:start_link({local, ?SERVER}, ?MODULE, []).
+
+start_child(Args) ->
+ supervisor:start_child(?MODULE, Args).
+
+%%====================================================================
+%% Supervisor callbacks
+%%====================================================================
+init(_) ->
+ SupFlags = #{strategy => simple_one_for_one,
+ intensity => 0,
+ period => 3600},
+ {ok, {SupFlags, child_specs()}}.
+
+
+%%====================================================================
+%% Internal functions
+%%====================================================================
+child_specs() ->
+ [#{id => undefined,
+ start => {ftp, start_link, []},
+ restart => temporary,
+ shutdown => 4000,
+ type => worker,
+ modules => [ftp]}].
diff --git a/lib/ftp/test/Makefile b/lib/ftp/test/Makefile
new file mode 100644
index 0000000000..147f8e5dd6
--- /dev/null
+++ b/lib/ftp/test/Makefile
@@ -0,0 +1,251 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# 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%
+#
+#
+# For an outline of how this all_SUITE_data stuff works, see the
+# make file ../../ssl/test/Makefile.
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+VSN = $(FTP_VSN)
+
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
+
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+INCLUDES = -I. \
+ -I$(ERL_TOP)/lib/ftp/src
+
+CP = cp
+
+ifeq ($(TESTROOT_DIR),)
+TESTROOT_DIR = /ldisk/tests/$(USER)/ftp
+endif
+
+ifeq ($(FTP_DATA_DIR),)
+FTP_DATA_DIR = $(TESTROOT_DIR)/data_dir
+endif
+
+ifeq ($(FTP_PRIV_DIR),)
+FTP_PRIV_DIR = $(TESTROOT_DIR)/priv_dir
+endif
+
+FTP_FLAGS = -Dftp__data_dir='"$(FTP_DATA_DIR)"' \
+ -Dftp_priv_dir='"$(FTP_PRIV_DIR)"'
+
+
+###
+### test suite debug flags
+###
+ifeq ($(FTP_DEBUG_CLIENT),)
+ FTP_DEBUG_CLIENT = y
+endif
+
+ifeq ($(FTP_DEBUG_CLIENT),)
+ FTP_FLAGS += -Dftp_debug_client
+endif
+
+ifeq ($(FTP_TRACE_CLIENT),)
+ FTP_DEBUG_CLIENT = y
+endif
+
+ifeq ($(FTP_TRACE_CLIENT),y)
+ FTP_FLAGS += -Dftp_trace_client
+endif
+
+ifneq ($(FTP_DEBUG),)
+ FTP_DEBUG = s
+endif
+
+ifeq ($(FTP_DEBUG),l)
+ FTP_FLAGS += -Dftp_log
+endif
+
+ifeq ($(FTP_DEBUG),d)
+ FTP_FLAGS += -Dftp_debug -Dftp_log
+endif
+
+
+FTP_FLAGS += -pa ../ftp/ebin
+
+FTP_ROOT = ../ftp
+
+MODULES = \
+ erl_make_certs \
+ ftp_SUITE \
+ ftp_format_SUITE \
+ ftp_test_lib
+
+
+EBIN = .
+
+HRL_FILES = \
+ ftp_internal.hrl
+
+ERL_FILES = $(MODULES:%=%.erl)
+
+SOURCE = $(ERL_FILES) $(HRL_FILES)
+
+TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+FTP_SPECS = ftp.spec ftp_bench.spec
+COVER_FILE = ftp.cover
+FTP_FILES = ftp.config $(FTP_SPECS)
+
+
+FTP_DATADIRS = ftp_SUITE_data
+
+DATADIRS = $(FTP_DATADIRS)
+
+EMAKEFILE = Emakefile
+MAKE_EMAKE = $(wildcard $(ERL_TOP)/make/make_emakefile)
+
+ifeq ($(MAKE_EMAKE),)
+BUILDTARGET = $(TARGET_FILES)
+RELTEST_FILES = $(COVER_FILE) $(FTP_SPECS) $(SOURCE)
+else
+BUILDTARGET = emakebuild
+RELTEST_FILES = $(EMAKEFILE) $(COVER_FILE) $(FTP_SPECS) $(SOURCE)
+endif
+
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+
+RELTESTSYSDIR = "$(RELEASE_PATH)/ftp_test"
+RELTESTSYSALLDATADIR = $(RELTESTSYSDIR)/all_SUITE_data
+RELTESTSYSBINDIR = $(RELTESTSYSALLDATADIR)/bin
+
+
+# ----------------------------------------------------
+# FLAGS
+# The path to the test_server ebin dir is needed when
+# running the target "targets".
+# ----------------------------------------------------
+ERL_COMPILE_FLAGS += \
+ $(INCLUDES) \
+ $(FTP_FLAGS)
+
+# ----------------------------------------------------
+# Targets
+# erl -sname kalle -pa ../ebin
+# If you intend to run the test suite locally (private), then
+# there is some requirements:
+# 1) FTP_PRIV_DIR must be created
+# ----------------------------------------------------
+
+tests debug opt: $(BUILDTARGET)
+
+targets: $(TARGET_FILES)
+
+.PHONY: emakebuild
+
+emakebuild: $(EMAKEFILE)
+
+$(EMAKEFILE):
+ $(MAKE_EMAKE) $(ERL_COMPILE_FLAGS) -o$(EBIN) '*_SUITE_make' | grep -v Warning > $(EMAKEFILE)
+ $(MAKE_EMAKE) $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) | grep -v Warning >> $(EMAKEFILE)
+
+clean:
+ rm -f $(EMAKEFILE)
+ rm -f $(TARGET_FILES)
+ rm -f core *~
+
+docs:
+
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+ $(INSTALL_DIR) "$(RELSYSDIR)/test"
+ $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) "$(RELSYSDIR)/test"
+ $(INSTALL_DATA) $(FTP_FILES) "$(RELSYSDIR)/test"
+ @for d in $(DATADIRS); do \
+ echo "installing data dir $$d"; \
+ if test -f $$d/TAR.exclude; then \
+ echo $$d/TAR.exclude2 > $$d/TAR.exclude2; \
+ cat $$d/TAR.exclude >> $$d/TAR.exclude2; \
+ find $$d -name '*.contrib*' >> $$d/TAR.exclude2; \
+ find $$d -name '*.keep*' >> $$d/TAR.exclude2; \
+ find $$d -name '*.mkelem*' >> $$d/TAR.exclude2; \
+ find $$d -name '*~' >> $$d/TAR.exclude2; \
+ find $$d -name 'erl_crash.dump' >> $$d/TAR.exclude2; \
+ find $$d -name 'core' >> $$d/TAR.exclude2; \
+ find $$d -name '.cmake.state' >> $$d/TAR.exclude2; \
+ tar cfX - $$d/TAR.exclude2 $$d | (cd "$(RELSYSDIR)/test"; tar xf -); \
+ else \
+ tar cf - $$d | (cd "$(RELSYSDIR)/test"; tar xf -); \
+ fi; \
+ done
+
+release_tests_spec: opt
+ $(INSTALL_DIR) $(RELTESTSYSDIR)
+ $(INSTALL_DATA) $(RELTEST_FILES) $(RELTESTSYSDIR)
+ chmod -R u+w $(RELTESTSYSDIR)
+ tar chf - $(DATADIRS) | (cd $(RELTESTSYSDIR); tar xf -)
+ $(INSTALL_DIR) $(RELTESTSYSALLDATADIR)
+ $(INSTALL_DIR) $(RELTESTSYSBINDIR)
+ chmod -R +x $(RELTESTSYSBINDIR)
+ $(INSTALL_DIR) $(RELTESTSYSALLDATADIR)/win32/lib
+
+release_docs_spec:
+
+info:
+ @echo "MAKE_EMAKE = $(MAKE_EMAKE)"
+ @echo "EMAKEFILE = $(EMAKEFILE)"
+ @echo "BUILDTARGET = $(BUILDTARGET)"
+ @echo ""
+ @echo "MODULES = $(MODULES)"
+ @echo "ERL_FILES = $(ERL_FILES)"
+ @echo "SOURCE = $(SOURCE)"
+ @echo "TARGET_FILES = $(TARGET_FILES)"
+ @echo ""
+ @echo "FTP_SPECS = $(FTP_SPECS)"
+ @echo "FTP_FILES = $(FTP_FILES)"
+ @echo ""
+ @echo "RELEASE_PATH = "$(RELEASE_PATH)""
+ @echo "RELSYSDIR = "$(RELSYSDIR)""
+ @echo "RELTESTSYSDIR = $(RELTESTSYSDIR)"
+ @echo "RELTESTSYSALLDATADIR = $(RELTESTSYSALLDATADIR)"
+ @echo "RELTESTSYSBINDIR = $(RELTESTSYSBINDIR)"
+ @echo ""
+ @echo "DATADIRS = $(DATADIRS)"
+ @echo "REL_DATADIRS = $(REL_DATADIRS)"
+ @echo ""
+ @echo "FTP_DATA_DIR = $(FTP_DATA_DIR)"
+ @echo "FTP_PRIV_DIR = $(FTP_PRIV_DIR)"
+ @echo "FTP_ROOT = $(FTP_ROOT)"
+ @echo "FTP_FLAGS = $(FTP_FLAGS)"
+
+
diff --git a/lib/ftp/test/erl_make_certs.erl b/lib/ftp/test/erl_make_certs.erl
new file mode 100644
index 0000000000..e10ecf01f9
--- /dev/null
+++ b/lib/ftp/test/erl_make_certs.erl
@@ -0,0 +1,475 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%
+
+%% Create test certificates
+
+-module(erl_make_certs).
+-include_lib("public_key/include/public_key.hrl").
+
+-export([make_cert/1, gen_rsa/1, verify_signature/3, write_pem/3]).
+-compile(export_all).
+
+%%--------------------------------------------------------------------
+%% @doc Create and return a der encoded certificate
+%% Option Default
+%% -------------------------------------------------------
+%% digest sha1
+%% validity {date(), date() + week()}
+%% version 3
+%% subject [] list of the following content
+%% {name, Name}
+%% {email, Email}
+%% {city, City}
+%% {state, State}
+%% {org, Org}
+%% {org_unit, OrgUnit}
+%% {country, Country}
+%% {serial, Serial}
+%% {title, Title}
+%% {dnQualifer, DnQ}
+%% issuer = {Issuer, IssuerKey} true (i.e. a ca cert is created)
+%% (obs IssuerKey migth be {Key, Password}
+%% key = KeyFile|KeyBin|rsa|dsa|ec Subject PublicKey rsa, dsa or ec generates key
+%%
+%%
+%% (OBS: The generated keys are for testing only)
+%% @spec ([{::atom(), ::term()}]) -> {Cert::binary(), Key::binary()}
+%% @end
+%%--------------------------------------------------------------------
+
+make_cert(Opts) ->
+ SubjectPrivateKey = get_key(Opts),
+ {TBSCert, IssuerKey} = make_tbs(SubjectPrivateKey, Opts),
+ Cert = public_key:pkix_sign(TBSCert, IssuerKey),
+ true = verify_signature(Cert, IssuerKey, undef), %% verify that the keys where ok
+ {Cert, encode_key(SubjectPrivateKey)}.
+
+%%--------------------------------------------------------------------
+%% @doc Writes pem files in Dir with FileName ++ ".pem" and FileName ++ "_key.pem"
+%% @spec (::string(), ::string(), {Cert,Key}) -> ok
+%% @end
+%%--------------------------------------------------------------------
+write_pem(Dir, FileName, {Cert, Key = {_,_,not_encrypted}}) when is_binary(Cert) ->
+ ok = der_to_pem(filename:join(Dir, FileName ++ ".pem"),
+ [{'Certificate', Cert, not_encrypted}]),
+ ok = der_to_pem(filename:join(Dir, FileName ++ "_key.pem"), [Key]).
+
+%%--------------------------------------------------------------------
+%% @doc Creates a rsa key (OBS: for testing only)
+%% the size are in bytes
+%% @spec (::integer()) -> {::atom(), ::binary(), ::opaque()}
+%% @end
+%%--------------------------------------------------------------------
+gen_rsa(Size) when is_integer(Size) ->
+ Key = gen_rsa2(Size),
+ {Key, encode_key(Key)}.
+
+%%--------------------------------------------------------------------
+%% @doc Creates a dsa key (OBS: for testing only)
+%% the sizes are in bytes
+%% @spec (::integer()) -> {::atom(), ::binary(), ::opaque()}
+%% @end
+%%--------------------------------------------------------------------
+gen_dsa(LSize,NSize) when is_integer(LSize), is_integer(NSize) ->
+ Key = gen_dsa2(LSize, NSize),
+ {Key, encode_key(Key)}.
+
+%%--------------------------------------------------------------------
+%% @doc Creates a ec key (OBS: for testing only)
+%% the sizes are in bytes
+%% @spec (::integer()) -> {::atom(), ::binary(), ::opaque()}
+%% @end
+%%--------------------------------------------------------------------
+gen_ec(Curve) when is_atom(Curve) ->
+ Key = gen_ec2(Curve),
+ {Key, encode_key(Key)}.
+
+%%--------------------------------------------------------------------
+%% @doc Verifies cert signatures
+%% @spec (::binary(), ::tuple()) -> ::boolean()
+%% @end
+%%--------------------------------------------------------------------
+verify_signature(DerEncodedCert, DerKey, _KeyParams) ->
+ Key = decode_key(DerKey),
+ case Key of
+ #'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} ->
+ public_key:pkix_verify(DerEncodedCert,
+ #'RSAPublicKey'{modulus=Mod, publicExponent=Exp});
+ #'DSAPrivateKey'{p=P, q=Q, g=G, y=Y} ->
+ public_key:pkix_verify(DerEncodedCert, {Y, #'Dss-Parms'{p=P, q=Q, g=G}});
+ #'ECPrivateKey'{version = _Version, privateKey = _PrivKey,
+ parameters = Params, publicKey = {0, PubKey}} ->
+ public_key:pkix_verify(DerEncodedCert, {#'ECPoint'{point = PubKey}, Params})
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%% Implementation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+get_key(Opts) ->
+ case proplists:get_value(key, Opts) of
+ undefined -> make_key(rsa, Opts);
+ rsa -> make_key(rsa, Opts);
+ dsa -> make_key(dsa, Opts);
+ ec -> make_key(ec, Opts);
+ Key ->
+ Password = proplists:get_value(password, Opts, no_passwd),
+ decode_key(Key, Password)
+ end.
+
+decode_key({Key, Pw}) ->
+ decode_key(Key, Pw);
+decode_key(Key) ->
+ decode_key(Key, no_passwd).
+
+
+decode_key(#'RSAPublicKey'{} = Key,_) ->
+ Key;
+decode_key(#'RSAPrivateKey'{} = Key,_) ->
+ Key;
+decode_key(#'DSAPrivateKey'{} = Key,_) ->
+ Key;
+decode_key(#'ECPrivateKey'{} = Key,_) ->
+ Key;
+decode_key(PemEntry = {_,_,_}, Pw) ->
+ public_key:pem_entry_decode(PemEntry, Pw);
+decode_key(PemBin, Pw) ->
+ [KeyInfo] = public_key:pem_decode(PemBin),
+ decode_key(KeyInfo, Pw).
+
+encode_key(Key = #'RSAPrivateKey'{}) ->
+ {ok, Der} = 'OTP-PUB-KEY':encode('RSAPrivateKey', Key),
+ {'RSAPrivateKey', Der, not_encrypted};
+encode_key(Key = #'DSAPrivateKey'{}) ->
+ {ok, Der} = 'OTP-PUB-KEY':encode('DSAPrivateKey', Key),
+ {'DSAPrivateKey', Der, not_encrypted};
+encode_key(Key = #'ECPrivateKey'{}) ->
+ {ok, Der} = 'OTP-PUB-KEY':encode('ECPrivateKey', Key),
+ {'ECPrivateKey', Der, not_encrypted}.
+
+make_tbs(SubjectKey, Opts) ->
+ Version = list_to_atom("v"++integer_to_list(proplists:get_value(version, Opts, 3))),
+
+ IssuerProp = proplists:get_value(issuer, Opts, true),
+ {Issuer, IssuerKey} = issuer(IssuerProp, Opts, SubjectKey),
+
+ {Algo, Parameters} = sign_algorithm(IssuerKey, Opts),
+
+ SignAlgo = #'SignatureAlgorithm'{algorithm = Algo,
+ parameters = Parameters},
+ Subject = case IssuerProp of
+ true -> %% Is a Root Ca
+ Issuer;
+ _ ->
+ subject(proplists:get_value(subject, Opts),false)
+ end,
+
+ {#'OTPTBSCertificate'{serialNumber = trunc(random:uniform()*100000000)*10000 + 1,
+ signature = SignAlgo,
+ issuer = Issuer,
+ validity = validity(Opts),
+ subject = Subject,
+ subjectPublicKeyInfo = publickey(SubjectKey),
+ version = Version,
+ extensions = extensions(Opts)
+ }, IssuerKey}.
+
+issuer(true, Opts, SubjectKey) ->
+ %% Self signed
+ {subject(proplists:get_value(subject, Opts), true), SubjectKey};
+issuer({Issuer, IssuerKey}, _Opts, _SubjectKey) when is_binary(Issuer) ->
+ {issuer_der(Issuer), decode_key(IssuerKey)};
+issuer({File, IssuerKey}, _Opts, _SubjectKey) when is_list(File) ->
+ {ok, [{cert, Cert, _}|_]} = pem_to_der(File),
+ {issuer_der(Cert), decode_key(IssuerKey)}.
+
+issuer_der(Issuer) ->
+ Decoded = public_key:pkix_decode_cert(Issuer, otp),
+ #'OTPCertificate'{tbsCertificate=Tbs} = Decoded,
+ #'OTPTBSCertificate'{subject=Subject} = Tbs,
+ Subject.
+
+subject(undefined, IsRootCA) ->
+ User = if IsRootCA -> "RootCA"; true -> os:getenv("USER", "test_user") end,
+ Opts = [{email, User ++ "@erlang.org"},
+ {name, User},
+ {city, "Stockholm"},
+ {country, "SE"},
+ {org, "erlang"},
+ {org_unit, "testing dep"}],
+ subject(Opts);
+subject(Opts, _) ->
+ subject(Opts).
+
+subject(SubjectOpts) when is_list(SubjectOpts) ->
+ Encode = fun(Opt) ->
+ {Type,Value} = subject_enc(Opt),
+ [#'AttributeTypeAndValue'{type=Type, value=Value}]
+ end,
+ {rdnSequence, [Encode(Opt) || Opt <- SubjectOpts]}.
+
+%% Fill in the blanks
+subject_enc({name, Name}) -> {?'id-at-commonName', {printableString, Name}};
+subject_enc({email, Email}) -> {?'id-emailAddress', Email};
+subject_enc({city, City}) -> {?'id-at-localityName', {printableString, City}};
+subject_enc({state, State}) -> {?'id-at-stateOrProvinceName', {printableString, State}};
+subject_enc({org, Org}) -> {?'id-at-organizationName', {printableString, Org}};
+subject_enc({org_unit, OrgUnit}) -> {?'id-at-organizationalUnitName', {printableString, OrgUnit}};
+subject_enc({country, Country}) -> {?'id-at-countryName', Country};
+subject_enc({serial, Serial}) -> {?'id-at-serialNumber', Serial};
+subject_enc({title, Title}) -> {?'id-at-title', {printableString, Title}};
+subject_enc({dnQualifer, DnQ}) -> {?'id-at-dnQualifier', DnQ};
+subject_enc(Other) -> Other.
+
+
+extensions(Opts) ->
+ case proplists:get_value(extensions, Opts, []) of
+ false ->
+ asn1_NOVALUE;
+ Exts ->
+ lists:flatten([extension(Ext) || Ext <- default_extensions(Exts)])
+ end.
+
+default_extensions(Exts) ->
+ Def = [{key_usage,undefined},
+ {subject_altname, undefined},
+ {issuer_altname, undefined},
+ {basic_constraints, default},
+ {name_constraints, undefined},
+ {policy_constraints, undefined},
+ {ext_key_usage, undefined},
+ {inhibit_any, undefined},
+ {auth_key_id, undefined},
+ {subject_key_id, undefined},
+ {policy_mapping, undefined}],
+ Filter = fun({Key, _}, D) -> lists:keydelete(Key, 1, D) end,
+ Exts ++ lists:foldl(Filter, Def, Exts).
+
+extension({_, undefined}) -> [];
+extension({basic_constraints, Data}) ->
+ case Data of
+ default ->
+ #'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue = #'BasicConstraints'{cA=true},
+ critical=true};
+ false ->
+ [];
+ Len when is_integer(Len) ->
+ #'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue = #'BasicConstraints'{cA=true, pathLenConstraint=Len},
+ critical=true};
+ _ ->
+ #'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue = Data}
+ end;
+extension({Id, Data, Critical}) ->
+ #'Extension'{extnID = Id, extnValue = Data, critical = Critical}.
+
+
+publickey(#'RSAPrivateKey'{modulus=N, publicExponent=E}) ->
+ Public = #'RSAPublicKey'{modulus=N, publicExponent=E},
+ Algo = #'PublicKeyAlgorithm'{algorithm= ?rsaEncryption, parameters='NULL'},
+ #'OTPSubjectPublicKeyInfo'{algorithm = Algo,
+ subjectPublicKey = Public};
+publickey(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) ->
+ Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa',
+ parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}},
+ #'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y};
+publickey(#'ECPrivateKey'{version = _Version,
+ privateKey = _PrivKey,
+ parameters = Params,
+ publicKey = {0, PubKey}}) ->
+ Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-ecPublicKey', parameters=Params},
+ #'OTPSubjectPublicKeyInfo'{algorithm = Algo,
+ subjectPublicKey = #'ECPoint'{point = PubKey}}.
+
+validity(Opts) ->
+ DefFrom0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())-1),
+ DefTo0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())+7),
+ {DefFrom, DefTo} = proplists:get_value(validity, Opts, {DefFrom0, DefTo0}),
+ Format = fun({Y,M,D}) -> lists:flatten(io_lib:format("~w~2..0w~2..0w000000Z",[Y,M,D])) end,
+ #'Validity'{notBefore={generalTime, Format(DefFrom)},
+ notAfter ={generalTime, Format(DefTo)}}.
+
+sign_algorithm(#'RSAPrivateKey'{}, Opts) ->
+ Type = case proplists:get_value(digest, Opts, sha1) of
+ sha1 -> ?'sha1WithRSAEncryption';
+ sha512 -> ?'sha512WithRSAEncryption';
+ sha384 -> ?'sha384WithRSAEncryption';
+ sha256 -> ?'sha256WithRSAEncryption';
+ md5 -> ?'md5WithRSAEncryption';
+ md2 -> ?'md2WithRSAEncryption'
+ end,
+ {Type, 'NULL'};
+sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) ->
+ {?'id-dsa-with-sha1', {params,#'Dss-Parms'{p=P, q=Q, g=G}}};
+sign_algorithm(#'ECPrivateKey'{}, Opts) ->
+ Type = case proplists:get_value(digest, Opts, sha1) of
+ sha1 -> ?'ecdsa-with-SHA1';
+ sha512 -> ?'ecdsa-with-SHA512';
+ sha384 -> ?'ecdsa-with-SHA384';
+ sha256 -> ?'ecdsa-with-SHA256'
+ end,
+ {Type, 'NULL'}.
+
+make_key(rsa, _Opts) ->
+ %% (OBS: for testing only)
+ gen_rsa2(64);
+make_key(dsa, _Opts) ->
+ gen_dsa2(128, 20); %% Bytes i.e. {1024, 160}
+make_key(ec, _Opts) ->
+ %% (OBS: for testing only)
+ gen_ec2(secp256k1).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% RSA key generation (OBS: for testing only)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-define(SMALL_PRIMES, [65537,97,89,83,79,73,71,67,61,59,53,
+ 47,43,41,37,31,29,23,19,17,13,11,7,5,3]).
+
+gen_rsa2(Size) ->
+ P = prime(Size),
+ Q = prime(Size),
+ N = P*Q,
+ Tot = (P - 1) * (Q - 1),
+ [E|_] = lists:dropwhile(fun(Candidate) -> (Tot rem Candidate) == 0 end, ?SMALL_PRIMES),
+ {D1,D2} = extended_gcd(E, Tot),
+ D = erlang:max(D1,D2),
+ case D < E of
+ true ->
+ gen_rsa2(Size);
+ false ->
+ {Co1,Co2} = extended_gcd(Q, P),
+ Co = erlang:max(Co1,Co2),
+ #'RSAPrivateKey'{version = 'two-prime',
+ modulus = N,
+ publicExponent = E,
+ privateExponent = D,
+ prime1 = P,
+ prime2 = Q,
+ exponent1 = D rem (P-1),
+ exponent2 = D rem (Q-1),
+ coefficient = Co
+ }
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% DSA key generation (OBS: for testing only)
+%% See http://en.wikipedia.org/wiki/Digital_Signature_Algorithm
+%% and the fips_186-3.pdf
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+gen_dsa2(LSize, NSize) ->
+ Q = prime(NSize), %% Choose N-bit prime Q
+ X0 = prime(LSize),
+ P0 = prime((LSize div 2) +1),
+
+ %% Choose L-bit prime modulus P such that p-1 is a multiple of q.
+ case dsa_search(X0 div (2*Q*P0), P0, Q, 1000) of
+ error ->
+ gen_dsa2(LSize, NSize);
+ P ->
+ G = crypto:mod_pow(2, (P-1) div Q, P), % Choose G a number whose multiplicative order modulo p is q.
+ %% such that This may be done by setting g = h^(p-1)/q mod p, commonly h=2 is used.
+
+ X = prime(20), %% Choose x by some random method, where 0 < x < q.
+ Y = crypto:mod_pow(G, X, P), %% Calculate y = g^x mod p.
+
+ #'DSAPrivateKey'{version=0, p = P, q = Q,
+ g = crypto:bytes_to_integer(G), y = crypto:bytes_to_integer(Y), x = X}
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% EC key generation (OBS: for testing only)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+gen_ec2(CurveId) ->
+ {PubKey, PrivKey} = crypto:generate_key(ecdh, CurveId),
+
+ #'ECPrivateKey'{version = 1,
+ privateKey = binary_to_list(PrivKey),
+ parameters = {namedCurve, pubkey_cert_records:namedCurves(CurveId)},
+ publicKey = {0, PubKey}}.
+
+%% See fips_186-3.pdf
+dsa_search(T, P0, Q, Iter) when Iter > 0 ->
+ P = 2*T*Q*P0 + 1,
+ case is_prime(P, 50) of
+ true -> P;
+ false -> dsa_search(T+1, P0, Q, Iter-1)
+ end;
+dsa_search(_,_,_,_) ->
+ error.
+
+
+%%%%%%% Crypto Math %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+prime(ByteSize) ->
+ Rand = odd_rand(ByteSize),
+ prime_odd(Rand, 0).
+
+prime_odd(Rand, N) ->
+ case is_prime(Rand, 50) of
+ true ->
+ Rand;
+ false ->
+ prime_odd(Rand+2, N+1)
+ end.
+
+%% see http://en.wikipedia.org/wiki/Fermat_primality_test
+is_prime(_, 0) -> true;
+is_prime(Candidate, Test) ->
+ CoPrime = odd_rand(10000, Candidate),
+ Result = crypto:mod_pow(CoPrime, Candidate, Candidate) ,
+ is_prime(CoPrime, crypto:bytes_to_integer(Result), Candidate, Test).
+
+is_prime(CoPrime, CoPrime, Candidate, Test) ->
+ is_prime(Candidate, Test-1);
+is_prime(_,_,_,_) ->
+ false.
+
+odd_rand(Size) ->
+ Min = 1 bsl (Size*8-1),
+ Max = (1 bsl (Size*8))-1,
+ odd_rand(Min, Max).
+
+odd_rand(Min,Max) ->
+ Rand = crypto:rand_uniform(Min,Max),
+ case Rand rem 2 of
+ 0 ->
+ Rand + 1;
+ _ ->
+ Rand
+ end.
+
+extended_gcd(A, B) ->
+ case A rem B of
+ 0 ->
+ {0, 1};
+ N ->
+ {X, Y} = extended_gcd(B, N),
+ {Y, X-Y*(A div B)}
+ end.
+
+pem_to_der(File) ->
+ {ok, PemBin} = file:read_file(File),
+ public_key:pem_decode(PemBin).
+
+der_to_pem(File, Entries) ->
+ PemBin = public_key:pem_encode(Entries),
+ file:write_file(File, PemBin).
+
diff --git a/lib/ftp/test/ftp.config b/lib/ftp/test/ftp.config
new file mode 100644
index 0000000000..2600237da9
--- /dev/null
+++ b/lib/ftp/test/ftp.config
@@ -0,0 +1 @@
+[]. \ No newline at end of file
diff --git a/lib/ftp/test/ftp.cover b/lib/ftp/test/ftp.cover
new file mode 100644
index 0000000000..5b155991bc
--- /dev/null
+++ b/lib/ftp/test/ftp.cover
@@ -0,0 +1,2 @@
+{incl_app,ftp,details}.
+
diff --git a/lib/ftp/test/ftp.spec b/lib/ftp/test/ftp.spec
new file mode 100644
index 0000000000..faf1e532a8
--- /dev/null
+++ b/lib/ftp/test/ftp.spec
@@ -0,0 +1 @@
+{suites,"../ftp_test", all}.
diff --git a/lib/ftp/test/ftp_SUITE.erl b/lib/ftp/test/ftp_SUITE.erl
new file mode 100644
index 0000000000..7c87d5cbdb
--- /dev/null
+++ b/lib/ftp/test/ftp_SUITE.erl
@@ -0,0 +1,1263 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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(ftp_SUITE).
+
+-include_lib("kernel/include/file.hrl").
+-include_lib("common_test/include/ct.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-define(FTP_USER, "anonymous").
+-define(FTP_PASS(Cmnt), (fun({ok,__H}) -> "ftp_SUITE_"++Cmnt++"@" ++ __H;
+ (_) -> "ftp_SUITE_"++Cmnt++"@localhost"
+ end)(inet:gethostname())
+ ).
+
+-define(BAD_HOST, "badhostname").
+-define(BAD_USER, "baduser").
+-define(BAD_DIR, "baddirectory").
+
+-record(progress, {
+ current = 0,
+ total
+ }).
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,20}}].
+
+all() ->
+ [
+ {group, ftp_passive},
+ {group, ftp_active},
+ {group, ftps_passive},
+ {group, ftps_active},
+ {group, ftp_sup},
+ app,
+ appup,
+ error_ehost,
+ clean_shutdown
+ ].
+
+groups() ->
+ [
+ {ftp_passive, [], ftp_tests()},
+ {ftp_active, [], ftp_tests()},
+ {ftps_passive, [], ftp_tests()},
+ {ftps_active, [], ftp_tests()},
+ {ftp_sup, [], ftp_sup_tests()}
+ ].
+
+ftp_tests()->
+ [
+ user,
+ bad_user,
+ pwd,
+ cd,
+ lcd,
+ ls,
+ nlist,
+ rename,
+ delete,
+ mkdir,
+ rmdir,
+ send,
+ send_3,
+ send_bin,
+ send_chunk,
+ append,
+ append_bin,
+ append_chunk,
+ recv,
+ recv_3,
+ recv_bin,
+ recv_bin_twice,
+ recv_chunk,
+ recv_chunk_twice,
+ recv_chunk_three_times,
+ type,
+ quote,
+ error_elogin,
+ progress_report_send,
+ progress_report_recv,
+ not_owner,
+ unexpected_call,
+ unexpected_cast,
+ unexpected_bang
+ ].
+
+ftp_sup_tests() ->
+ [
+ start_ftp,
+ ftp_worker
+ ].
+
+%%--------------------------------------------------------------------
+
+%%% Config
+%%% key meaning
+%%% ................................................................
+%%% ftpservers list of servers to check if they are available
+%%% The element is:
+%%% {Name, % string(). The os command name
+%%% Path, % string(). The os PATH syntax, e.g "/bin:/usr/bin"
+%%% StartCommand, % fun()->{ok,start_result()} | {error,string()}.
+%%% % The command to start the daemon with.
+%%% ChkUp, % fun(start_result()) -> string(). Os command to check
+%%% % if the server is running. [] if not running.
+%%% % The string in string() is suitable for logging.
+%%% StopCommand, % fun(start_result()) -> void(). The command to stop the daemon with.
+%%% AugmentFun, % fun(config()) -> config() Adds two funs for transforming names of files
+%%% % and directories to the form they are returned from this server
+%%% ServerHost, % string(). Mostly "localhost"
+%%% ServerPort % pos_integer()
+%%% }
+%%%
+
+-define(default_ftp_servers,
+ [{"vsftpd",
+ "/sbin:/usr/sbin:/usr/local/sbin",
+ fun(__CONF__, AbsName) ->
+ DataDir = proplists:get_value(data_dir,__CONF__),
+ ConfFile = filename:join(DataDir, "vsftpd.conf"),
+ PrivDir = proplists:get_value(priv_dir,__CONF__),
+ AnonRoot = PrivDir,
+ Cmd = [AbsName ++" "++filename:join(DataDir,"vsftpd.conf"),
+ " -oftpd_banner=erlang_otp_testing",
+ " -oanon_root=\"",AnonRoot,"\"",
+ " -orsa_cert_file=\"",filename:join(DataDir,"server-cert.pem"),"\"",
+ " -orsa_private_key_file=\"",filename:join(DataDir,"server-key.pem"),"\""
+ ],
+ Result = os:cmd(Cmd),
+ ct:log("Config file:~n~s~n~nServer start command:~n ~s~nResult:~n ~p",
+ [case file:read_file(ConfFile) of
+ {ok,X} -> X;
+ _ -> ""
+ end,
+ Cmd, Result
+ ]),
+ case Result of
+ [] -> {ok,'dont care'};
+ [Msg] -> {error,Msg}
+ end
+ end,
+ fun(_StartResult) -> os:cmd("ps ax | grep erlang_otp_testing | grep -v grep")
+ end,
+ fun(_StartResult) -> os:cmd("kill `ps ax | grep erlang_otp_testing | awk '/vsftpd/{print $1}'`")
+ end,
+ fun(__CONF__) ->
+ AnonRoot = proplists:get_value(priv_dir,__CONF__),
+ [{id2ftp, fun(Id) -> filename:join(AnonRoot,Id) end},
+ {id2ftp_result,fun(Id) -> filename:join(AnonRoot,Id) end} | __CONF__]
+ end,
+ "localhost",
+ 9999
+ }
+ ]
+ ).
+
+
+init_per_suite(Config) ->
+ case find_executable(Config) of
+ false ->
+ {skip, "No ftp server found"};
+ {ok,Data} ->
+ TstDir = filename:join(proplists:get_value(priv_dir,Config), "test"),
+ file:make_dir(TstDir),
+ %% make_cert_files(dsa, rsa, "server-", proplists:get_value(data_dir,Config)),
+ ftp_test_lib:make_cert_files(proplists:get_value(data_dir,Config)),
+ start_ftpd([{test_dir,TstDir},
+ {ftpd_data,Data}
+ | Config])
+ end.
+
+end_per_suite(Config) ->
+ ps_ftpd(Config),
+ stop_ftpd(Config),
+ ps_ftpd(Config),
+ ok.
+
+%%--------------------------------------------------------------------
+init_per_group(Group, Config) when Group == ftps_active,
+ Group == ftps_passive ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ Config
+ catch
+ _:_ ->
+ {skip, "Crypto did not start"}
+ end;
+init_per_group(ftp_sup, Config) ->
+ try ftp:start() of
+ ok ->
+ Config
+ catch
+ _:_ ->
+ {skip, "Ftp did not start"}
+ end;
+init_per_group(_Group, Config) ->
+ Config.
+
+
+end_per_group(ftp_sup, Config) ->
+ ftp:stop(),
+ Config;
+end_per_group(_Group, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+init_per_testcase(T, Config0) when T =:= app; T =:= appup ->
+ Config0;
+init_per_testcase(Case, Config0) ->
+ Group = proplists:get_value(name, proplists:get_value(tc_group_properties,Config0)),
+
+ %% Workaround for interoperability issues with vsftpd =< 3.0.2:
+ %%
+ %% vsftpd =< 3.0.2 does not support ECDHE ciphers and the ssl application
+ %% removed ciphers with RSA key exchange from its default cipher list.
+ %% To allow interoperability with old versions of vsftpd, cipher suites
+ %% with RSA key exchange are appended to the default cipher list.
+ All = ssl:cipher_suites(all, 'tlsv1.2'),
+ Default = ssl:cipher_suites(default, 'tlsv1.2'),
+ RSASuites =
+ ssl:filter_cipher_suites(All, [{key_exchange, fun(rsa) -> true;
+ (_) -> false end}]),
+ Suites = ssl:append_cipher_suites(RSASuites, Default),
+ TLS = [{tls,[{reuse_sessions,true},{ciphers, Suites}]}],
+ ACTIVE = [{mode,active}],
+ PASSIVE = [{mode,passive}],
+ CaseOpts = case Case of
+ progress_report_send -> [{progress, {?MODULE,progress,#progress{}}}];
+ progress_report_recv -> [{progress, {?MODULE,progress,#progress{}}}];
+ _ -> []
+ end,
+ ExtraOpts = [verbose | CaseOpts],
+ Config =
+ case Group of
+ ftp_active -> ftp__open(Config0, ACTIVE ++ ExtraOpts);
+ ftps_active -> ftp__open(Config0, TLS++ ACTIVE ++ ExtraOpts);
+ ftp_passive -> ftp__open(Config0, PASSIVE ++ ExtraOpts);
+ ftps_passive -> ftp__open(Config0, TLS++PASSIVE ++ ExtraOpts);
+ ftp_sup -> ftp_start_service(Config0, ACTIVE ++ ExtraOpts);
+ undefined -> Config0
+ end,
+ case Case of
+ user -> Config;
+ bad_user -> Config;
+ error_elogin -> Config;
+ error_ehost -> Config;
+ clean_shutdown -> Config;
+ _ ->
+ Pid = proplists:get_value(ftp,Config),
+ ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS(atom_to_list(Group)++"-"++atom_to_list(Case)) ),
+ ok = ftp:cd(Pid, proplists:get_value(priv_dir,Config)),
+ Config
+ end.
+
+end_per_testcase(T, _Config) when T =:= app; T =:= appup -> ok;
+end_per_testcase(user, _Config) -> ok;
+end_per_testcase(bad_user, _Config) -> ok;
+end_per_testcase(error_elogin, _Config) -> ok;
+end_per_testcase(error_ehost, _Config) -> ok;
+end_per_testcase(clean_shutdown, _Config) -> ok;
+end_per_testcase(_Case, Config) ->
+ case proplists:get_value(tc_status,Config) of
+ ok -> ok;
+ _ ->
+ try ftp:latest_ctrl_response(proplists:get_value(ftp,Config))
+ of
+ {ok,S} -> ct:log("***~n*** Latest ctrl channel response:~n*** ~p~n***",[S])
+ catch
+ _:_ -> ok
+ end
+ end,
+ Group = proplists:get_value(name, proplists:get_value(tc_group_properties,Config)),
+ case Group of
+ ftp_sup ->
+ ftp_stop_service(Config);
+ _Else ->
+ ftp__close(Config)
+ end.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+app() ->
+ [{doc, "Test that the ftp app file is ok"}].
+app(Config) when is_list(Config) ->
+ ok = ?t:app_test(ftp).
+
+%%--------------------------------------------------------------------
+appup() ->
+ [{doc, "Test that the ftp appup file is ok"}].
+appup(Config) when is_list(Config) ->
+ ok = ?t:appup_test(ftp).
+
+%%--------------------------------------------------------------------
+
+user() -> [
+ {doc, "Open an ftp connection to a host, and logon as anonymous ftp,"
+ " then logoff"}].
+user(Config) ->
+ Pid = proplists:get_value(ftp, Config),
+ ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS("")),% logon
+ ok = ftp:close(Pid), % logoff
+ {error,eclosed} = ftp:pwd(Pid), % check logoff result
+ ok.
+
+%%-------------------------------------------------------------------------
+bad_user() ->
+ [{doc, "Open an ftp connection to a host, and logon with bad user."}].
+bad_user(Config) ->
+ Pid = proplists:get_value(ftp, Config),
+ {error, euser} = ftp:user(Pid, ?BAD_USER, ?FTP_PASS("")),
+ ok.
+
+%%-------------------------------------------------------------------------
+pwd() ->
+ [{doc, "Test ftp:pwd/1 & ftp:lpwd/1"}].
+pwd(Config0) ->
+ Config = set_state([reset], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ {ok, PWD} = ftp:pwd(Pid),
+ {ok, PathLpwd} = ftp:lpwd(Pid),
+ PWD = id2ftp_result("", Config),
+ PathLpwd = id2ftp_result("", Config).
+
+%%-------------------------------------------------------------------------
+cd() ->
+ ["Open an ftp connection, log on as anonymous ftp, and cd to a"
+ "directory and to a non-existent directory."].
+cd(Config0) ->
+ Dir = "test",
+ Config = set_state([reset,{mkdir,Dir}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ ok = ftp:cd(Pid, id2ftp(Dir,Config)),
+ {ok, PWD} = ftp:pwd(Pid),
+ ExpectedPWD = id2ftp_result(Dir, Config),
+ PWD = ExpectedPWD,
+ {error, epath} = ftp:cd(Pid, ?BAD_DIR),
+ ok.
+
+%%-------------------------------------------------------------------------
+lcd() ->
+ [{doc, "Test api function ftp:lcd/2"}].
+lcd(Config0) ->
+ Dir = "test",
+ Config = set_state([reset,{mkdir,Dir}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ ok = ftp:lcd(Pid, id2ftp(Dir,Config)),
+ {ok, PWD} = ftp:lpwd(Pid),
+ ExpectedPWD = id2ftp_result(Dir, Config),
+ PWD = ExpectedPWD,
+ {error, epath} = ftp:lcd(Pid, ?BAD_DIR).
+
+%%-------------------------------------------------------------------------
+ls() ->
+ [{doc, "Open an ftp connection; ls the current directory, and the "
+ "\"test\" directory. We assume that ls never fails, since "
+ "it's output is meant to be read by humans. "}].
+ls(Config0) ->
+ Config = set_state([reset,{mkdir,"test"}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ {ok, _R1} = ftp:ls(Pid),
+ {ok, _R2} = ftp:ls(Pid, id2ftp("test",Config)),
+ %% neither nlist nor ls operates on a directory
+ %% they operate on a pathname, which *can* be a
+ %% directory, but can also be a filename or a group
+ %% of files (including wildcards).
+ case proplists:get_value(wildcard_support, Config) of
+ true ->
+ {ok, _R3} = ftp:ls(Pid, id2ftp("te*",Config));
+ _ ->
+ ok
+ end.
+
+%%-------------------------------------------------------------------------
+nlist() ->
+ [{doc,"Open an ftp connection; nlist the current directory, and the "
+ "\"test\" directory. Nlist does not behave consistenly over "
+ "operating systems. On some it is an error to have an empty "
+ "directory."}].
+nlist(Config0) ->
+ Config = set_state([reset,{mkdir,"test"}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ {ok, _R1} = ftp:nlist(Pid),
+ {ok, _R2} = ftp:nlist(Pid, id2ftp("test",Config)),
+ %% neither nlist nor ls operates on a directory
+ %% they operate on a pathname, which *can* be a
+ %% directory, but can also be a filename or a group
+ %% of files (including wildcards).
+ case proplists:get_value(wildcard_support, Config) of
+ true ->
+ {ok, _R3} = ftp:nlist(Pid, id2ftp("te*",Config));
+ _ ->
+ ok
+ end.
+
+%%-------------------------------------------------------------------------
+rename() ->
+ [{doc, "Rename a file."}].
+rename(Config0) ->
+ Contents = <<"ftp_SUITE test ...">>,
+ OldFile = "old.txt",
+ NewFile = "new.txt",
+ Config = set_state([reset,{mkfile,OldFile,Contents}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+
+ ok = ftp:rename(Pid,
+ id2ftp(OldFile,Config),
+ id2ftp(NewFile,Config)),
+
+ true = (chk_file(NewFile,Contents,Config)
+ and chk_no_file([OldFile],Config)),
+ {error,epath} = ftp:rename(Pid,
+ id2ftp("non_existing_file",Config),
+ id2ftp(NewFile,Config)),
+ ok.
+
+%%-------------------------------------------------------------------------
+send() ->
+ [{doc, "Transfer a file with ftp using send/2."}].
+send(Config0) ->
+ Contents = <<"ftp_SUITE test ...">>,
+ SrcDir = "data",
+ File = "file.txt",
+ Config = set_state([reset,{mkfile,[SrcDir,File],Contents}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+
+ chk_no_file([File],Config),
+ chk_file([SrcDir,File],Contents,Config),
+
+ ok = ftp:lcd(Pid, id2ftp(SrcDir,Config)),
+ ok = ftp:cd(Pid, id2ftp("",Config)),
+ ok = ftp:send(Pid, File),
+ chk_file(File, Contents, Config),
+
+ {error,epath} = ftp:send(Pid, "non_existing_file"),
+ ok.
+
+%%-------------------------------------------------------------------------
+send_3() ->
+ [{doc, "Transfer a file with ftp using send/3."}].
+send_3(Config0) ->
+ Contents = <<"ftp_SUITE test ...">>,
+ Dir = "incoming",
+ File = "file.txt",
+ RemoteFile = "remfile.txt",
+ Config = set_state([reset,{mkfile,File,Contents},{mkdir,Dir}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+
+ ok = ftp:cd(Pid, id2ftp(Dir,Config)),
+ ok = ftp:lcd(Pid, id2ftp("",Config)),
+ ok = ftp:send(Pid, File, RemoteFile),
+ chk_file([Dir,RemoteFile], Contents, Config),
+
+ {error,epath} = ftp:send(Pid, "non_existing_file", RemoteFile),
+ ok.
+
+%%-------------------------------------------------------------------------
+send_bin() ->
+ [{doc, "Send a binary."}].
+send_bin(Config0) ->
+ BinContents = <<"ftp_SUITE test ...">>,
+ File = "file.txt",
+ Config = set_state([reset], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ {error, enotbinary} = ftp:send_bin(Pid, "some string", id2ftp(File,Config)),
+ ok = ftp:send_bin(Pid, BinContents, id2ftp(File,Config)),
+ chk_file(File, BinContents, Config),
+ {error, efnamena} = ftp:send_bin(Pid, BinContents, "/nothere"),
+ ok.
+
+%%-------------------------------------------------------------------------
+send_chunk() ->
+ [{doc, "Send a binary using chunks."}].
+send_chunk(Config0) ->
+ Contents1 = <<"1: ftp_SUITE test ...">>,
+ Contents2 = <<"2: ftp_SUITE test ...">>,
+ File = "file.txt",
+ Config = set_state([reset,{mkdir,"incoming"}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+
+ ok = ftp:send_chunk_start(Pid, id2ftp(File,Config)),
+ {error, echunk} = ftp:send_chunk_start(Pid, id2ftp(File,Config)),
+ {error, echunk} = ftp:cd(Pid, "incoming"),
+ {error, enotbinary} = ftp:send_chunk(Pid, "some string"),
+ ok = ftp:send_chunk(Pid, Contents1),
+ ok = ftp:send_chunk(Pid, Contents2),
+ ok = ftp:send_chunk_end(Pid),
+ chk_file(File, <<Contents1/binary,Contents2/binary>>, Config),
+
+ {error, echunk} = ftp:send_chunk(Pid, Contents1),
+ {error, echunk} = ftp:send_chunk_end(Pid),
+ {error, efnamena} = ftp:send_chunk_start(Pid, "/"),
+ ok.
+
+%%-------------------------------------------------------------------------
+delete() ->
+ [{doc, "Delete a file."}].
+delete(Config0) ->
+ Contents = <<"ftp_SUITE test ...">>,
+ File = "file.txt",
+ Config = set_state([reset,{mkfile,File,Contents}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ ok = ftp:delete(Pid, id2ftp(File,Config)),
+ chk_no_file([File], Config),
+ {error,epath} = ftp:delete(Pid, id2ftp(File,Config)),
+ ok.
+
+%%-------------------------------------------------------------------------
+mkdir() ->
+ [{doc, "Make a remote directory."}].
+mkdir(Config0) ->
+ NewDir = "new_dir",
+ Config = set_state([reset], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ ok = ftp:mkdir(Pid, id2ftp(NewDir,Config)),
+ chk_dir([NewDir], Config),
+ {error,epath} = ftp:mkdir(Pid, id2ftp(NewDir,Config)),
+ ok.
+
+%%-------------------------------------------------------------------------
+rmdir() ->
+ [{doc, "Remove a directory."}].
+rmdir(Config0) ->
+ Dir = "dir",
+ Config = set_state([reset,{mkdir,Dir}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ ok = ftp:rmdir(Pid, id2ftp(Dir,Config)),
+ chk_no_dir([Dir], Config),
+ {error,epath} = ftp:rmdir(Pid, id2ftp(Dir,Config)),
+ ok.
+
+%%-------------------------------------------------------------------------
+append() ->
+ [{doc, "Append a local file twice to a remote file"}].
+append(Config0) ->
+ SrcFile = "f_src.txt",
+ DstFile = "f_dst.txt",
+ Contents = <<"ftp_SUITE test ...">>,
+ Config = set_state([reset,{mkfile,SrcFile,Contents}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ ok = ftp:append(Pid, id2ftp(SrcFile,Config), id2ftp(DstFile,Config)),
+ ok = ftp:append(Pid, id2ftp(SrcFile,Config), id2ftp(DstFile,Config)),
+ chk_file(DstFile, <<Contents/binary,Contents/binary>>, Config),
+ {error,epath} = ftp:append(Pid, id2ftp("non_existing_file",Config), id2ftp(DstFile,Config)),
+ ok.
+
+%%-------------------------------------------------------------------------
+append_bin() ->
+ [{doc, "Append a local file twice to a remote file using append_bin"}].
+append_bin(Config0) ->
+ DstFile = "f_dst.txt",
+ Contents = <<"ftp_SUITE test ...">>,
+ Config = set_state([reset], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ ok = ftp:append_bin(Pid, Contents, id2ftp(DstFile,Config)),
+ ok = ftp:append_bin(Pid, Contents, id2ftp(DstFile,Config)),
+ chk_file(DstFile, <<Contents/binary,Contents/binary>>, Config).
+
+%%-------------------------------------------------------------------------
+append_chunk() ->
+ [{doc, "Append chunks."}].
+append_chunk(Config0) ->
+ File = "f_dst.txt",
+ Contents = [<<"ER">>,<<"LE">>,<<"RL">>],
+ Config = set_state([reset], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ ok = ftp:append_chunk_start(Pid, id2ftp(File,Config)),
+ {error, enotbinary} = ftp:append_chunk(Pid, binary_to_list(lists:nth(1,Contents))),
+ ok = ftp:append_chunk(Pid,lists:nth(1,Contents)),
+ ok = ftp:append_chunk(Pid,lists:nth(2,Contents)),
+ ok = ftp:append_chunk(Pid,lists:nth(3,Contents)),
+ ok = ftp:append_chunk_end(Pid),
+ chk_file(File, <<"ERLERL">>, Config).
+
+%%-------------------------------------------------------------------------
+recv() ->
+ [{doc, "Receive a file using recv/2"}].
+recv(Config0) ->
+ File1 = "f_dst1.txt",
+ File2 = "f_dst2.txt",
+ SrcDir = "a_dir",
+ Contents1 = <<"1 ftp_SUITE test ...">>,
+ Contents2 = <<"2 ftp_SUITE test ...">>,
+ Config = set_state([reset, {mkfile,[SrcDir,File1],Contents1}, {mkfile,[SrcDir,File2],Contents2}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ ok = ftp:cd(Pid, id2ftp(SrcDir,Config)),
+ ok = ftp:lcd(Pid, id2ftp("",Config)),
+ ok = ftp:recv(Pid, File1),
+ chk_file(File1, Contents1, Config),
+ ok = ftp:recv(Pid, File2),
+ chk_file(File2, Contents2, Config),
+ {error,epath} = ftp:recv(Pid, "non_existing_file"),
+ ok.
+
+%%-------------------------------------------------------------------------
+recv_3() ->
+ [{doc,"Receive a file using recv/3"}].
+recv_3(Config0) ->
+ DstFile = "f_src.txt",
+ SrcFile = "f_dst.txt",
+ Contents = <<"ftp_SUITE test ...">>,
+ Config = set_state([reset, {mkfile,SrcFile,Contents}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ ok = ftp:cd(Pid, id2ftp("",Config)),
+ ok = ftp:recv(Pid, SrcFile, id2abs(DstFile,Config)),
+ chk_file(DstFile, Contents, Config).
+
+%%-------------------------------------------------------------------------
+recv_bin() ->
+ [{doc, "Receive a file as a binary."}].
+recv_bin(Config0) ->
+ File = "f_dst.txt",
+ Contents = <<"ftp_SUITE test ...">>,
+ Config = set_state([reset, {mkfile,File,Contents}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ {ok,Received} = ftp:recv_bin(Pid, id2ftp(File,Config)),
+ find_diff(Received, Contents),
+ {error,epath} = ftp:recv_bin(Pid, id2ftp("non_existing_file",Config)),
+ ok.
+
+%%-------------------------------------------------------------------------
+recv_bin_twice() ->
+ [{doc, "Receive two files as a binaries."}].
+recv_bin_twice(Config0) ->
+ File1 = "f_dst1.txt",
+ File2 = "f_dst2.txt",
+ Contents1 = <<"1 ftp_SUITE test ...">>,
+ Contents2 = <<"2 ftp_SUITE test ...">>,
+ Config = set_state([reset, {mkfile,File1,Contents1}, {mkfile,File2,Contents2}], Config0),
+ ct:log("First transfer",[]),
+ Pid = proplists:get_value(ftp, Config),
+ {ok,Received1} = ftp:recv_bin(Pid, id2ftp(File1,Config)),
+ find_diff(Received1, Contents1),
+ ct:log("Second transfer",[]),
+ {ok,Received2} = ftp:recv_bin(Pid, id2ftp(File2,Config)),
+ find_diff(Received2, Contents2),
+ ct:log("Transfers ready!",[]),
+ {error,epath} = ftp:recv_bin(Pid, id2ftp("non_existing_file",Config)),
+ ok.
+%%-------------------------------------------------------------------------
+recv_chunk() ->
+ [{doc, "Receive a file using chunk-wise."}].
+recv_chunk(Config0) ->
+ File = "big_file.txt",
+ Contents = list_to_binary( lists:duplicate(1000, lists:seq(0,255)) ),
+ Config = set_state([reset, {mkfile,File,Contents}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ {{error, "ftp:recv_chunk_start/2 not called"},_} = recv_chunk(Pid, <<>>),
+ ok = ftp:recv_chunk_start(Pid, id2ftp(File,Config)),
+ {ok, ReceivedContents, _Ncunks} = recv_chunk(Pid, <<>>),
+ find_diff(ReceivedContents, Contents).
+
+recv_chunk_twice() ->
+ [{doc, "Receive two files using chunk-wise."}].
+recv_chunk_twice(Config0) ->
+ File1 = "big_file1.txt",
+ File2 = "big_file2.txt",
+ Contents1 = list_to_binary( lists:duplicate(1000, lists:seq(0,255)) ),
+ Contents2 = crypto:strong_rand_bytes(1200),
+ Config = set_state([reset, {mkfile,File1,Contents1}, {mkfile,File2,Contents2}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ {{error, "ftp:recv_chunk_start/2 not called"},_} = recv_chunk(Pid, <<>>),
+ ok = ftp:recv_chunk_start(Pid, id2ftp(File1,Config)),
+ {ok, ReceivedContents1, _Ncunks1} = recv_chunk(Pid, <<>>),
+ ok = ftp:recv_chunk_start(Pid, id2ftp(File2,Config)),
+ {ok, ReceivedContents2, _Ncunks2} = recv_chunk(Pid, <<>>),
+ find_diff(ReceivedContents1, Contents1),
+ find_diff(ReceivedContents2, Contents2).
+
+recv_chunk_three_times() ->
+ [{doc, "Receive two files using chunk-wise."},
+ {timetrap,{seconds,120}}].
+recv_chunk_three_times(Config0) ->
+ File1 = "big_file1.txt",
+ File2 = "big_file2.txt",
+ File3 = "big_file3.txt",
+ Contents1 = list_to_binary( lists:duplicate(1000, lists:seq(0,255)) ),
+ Contents2 = crypto:strong_rand_bytes(1200),
+ Contents3 = list_to_binary( lists:duplicate(1000, lists:seq(255,0,-1)) ),
+
+ Config = set_state([reset, {mkfile,File1,Contents1}, {mkfile,File2,Contents2}, {mkfile,File3,Contents3}], Config0),
+ Pid = proplists:get_value(ftp, Config),
+ {{error, "ftp:recv_chunk_start/2 not called"},_} = recv_chunk(Pid, <<>>),
+
+ ok = ftp:recv_chunk_start(Pid, id2ftp(File1,Config)),
+ {ok, ReceivedContents1, Nchunks1} = recv_chunk(Pid, <<>>),
+
+ ok = ftp:recv_chunk_start(Pid, id2ftp(File2,Config)),
+ {ok, ReceivedContents2, _Nchunks2} = recv_chunk(Pid, <<>>),
+
+ ok = ftp:recv_chunk_start(Pid, id2ftp(File3,Config)),
+ {ok, ReceivedContents3, _Nchunks3} = recv_chunk(Pid, <<>>, 10000, 0, Nchunks1),
+
+ find_diff(ReceivedContents1, Contents1),
+ find_diff(ReceivedContents2, Contents2),
+ find_diff(ReceivedContents3, Contents3).
+
+
+
+recv_chunk(Pid, Acc) ->
+ recv_chunk(Pid, Acc, 0, 0, undefined).
+
+
+
+%% ExpectNchunks :: integer() | undefined
+recv_chunk(Pid, Acc, DelayMilliSec, N, ExpectNchunks) when N+1 < ExpectNchunks ->
+ %% for all I in integer(), I < undefined
+ recv_chunk1(Pid, Acc, DelayMilliSec, N, ExpectNchunks);
+
+recv_chunk(Pid, Acc, DelayMilliSec, N, ExpectNchunks) ->
+ %% N >= ExpectNchunks-1
+ timer:sleep(DelayMilliSec),
+ recv_chunk1(Pid, Acc, DelayMilliSec, N, ExpectNchunks).
+
+
+recv_chunk1(Pid, Acc, DelayMilliSec, N, ExpectNchunks) ->
+ ct:log("Call ftp:recv_chunk",[]),
+ case ftp:recv_chunk(Pid) of
+ ok -> {ok, Acc, N};
+ {ok, Bin} -> recv_chunk(Pid, <<Acc/binary, Bin/binary>>, DelayMilliSec, N+1, ExpectNchunks);
+ Error -> {Error, N}
+ end.
+
+%%-------------------------------------------------------------------------
+type() ->
+ [{doc,"Test that we can change btween ASCCI and binary transfer mode"}].
+type(Config) ->
+ Pid = proplists:get_value(ftp, Config),
+ ok = ftp:type(Pid, ascii),
+ ok = ftp:type(Pid, binary),
+ ok = ftp:type(Pid, ascii),
+ {error, etype} = ftp:type(Pid, foobar).
+
+%%-------------------------------------------------------------------------
+quote(Config) ->
+ Pid = proplists:get_value(ftp, Config),
+ ["257 \""++_Rest] = ftp:quote(Pid, "pwd"), %% 257
+ [_| _] = ftp:quote(Pid, "help"),
+ %% This negativ test causes some ftp servers to hang. This test
+ %% is not important for the client, so we skip it for now.
+ %%["425 Can't build data connection: Connection refused."]
+ %% = ftp:quote(Pid, "list"),
+ ok.
+
+%%-------------------------------------------------------------------------
+progress_report_send() ->
+ [{doc, "Test the option progress for ftp:send/[2,3]"}].
+progress_report_send(Config) when is_list(Config) ->
+ ReportPid =
+ spawn_link(?MODULE, progress_report_receiver_init, [self(), 1]),
+ send(Config),
+ receive
+ {ReportPid, ok} ->
+ ok
+ end.
+
+%%-------------------------------------------------------------------------
+progress_report_recv() ->
+ [{doc, "Test the option progress for ftp:recv/[2,3]"}].
+progress_report_recv(Config) when is_list(Config) ->
+ ReportPid =
+ spawn_link(?MODULE, progress_report_receiver_init, [self(), 3]),
+ recv(Config),
+ receive
+ {ReportPid, ok} ->
+ ok
+ end.
+
+%%-------------------------------------------------------------------------
+
+not_owner() ->
+ [{doc, "Test what happens if a process that not owns the connection tries "
+ "to use it"}].
+not_owner(Config) when is_list(Config) ->
+ Pid = proplists:get_value(ftp, Config),
+
+ Parent = self(),
+ OtherPid = spawn_link(
+ fun() ->
+ {error, not_connection_owner} = ftp:pwd(Pid),
+ ftp:close(Pid),
+ Parent ! {self(), ok}
+ end),
+ receive
+ {OtherPid, ok} ->
+ {ok, _} = ftp:pwd(Pid)
+ end.
+
+
+%%-------------------------------------------------------------------------
+
+
+unexpected_call()->
+ [{doc, "Test that behaviour of the ftp process if the api is abused"}].
+unexpected_call(Config) when is_list(Config) ->
+ Flag = process_flag(trap_exit, true),
+ Pid = proplists:get_value(ftp, Config),
+
+ %% Serious programming fault, connetion will be shut down
+ case (catch gen_server:call(Pid, {self(), foobar, 10}, infinity)) of
+ {error, {connection_terminated, 'API_violation'}} ->
+ ok;
+ Unexpected1 ->
+ exit({unexpected_result, Unexpected1})
+ end,
+ ct:sleep(500),
+ undefined = process_info(Pid, status),
+ process_flag(trap_exit, Flag).
+%%-------------------------------------------------------------------------
+
+unexpected_cast()->
+ [{doc, "Test that behaviour of the ftp process if the api is abused"}].
+unexpected_cast(Config) when is_list(Config) ->
+ Flag = process_flag(trap_exit, true),
+ Pid = proplists:get_value(ftp, Config),
+ %% Serious programming fault, connetion will be shut down
+ gen_server:cast(Pid, {self(), foobar, 10}),
+ ct:sleep(500),
+ undefined = process_info(Pid, status),
+ process_flag(trap_exit, Flag).
+%%-------------------------------------------------------------------------
+
+unexpected_bang()->
+ [{doc, "Test that connection ignores unexpected bang"}].
+unexpected_bang(Config) when is_list(Config) ->
+ Flag = process_flag(trap_exit, true),
+ Pid = proplists:get_value(ftp, Config),
+ %% Could be an innocent misstake the connection lives.
+ Pid ! foobar,
+ ct:sleep(500),
+ {status, _} = process_info(Pid, status),
+ process_flag(trap_exit, Flag).
+
+%%-------------------------------------------------------------------------
+
+clean_shutdown() ->
+ [{doc, "Test that owning process that exits with reason "
+ "'shutdown' does not cause an error message. OTP 6035"}].
+
+clean_shutdown(Config) ->
+ Parent = self(),
+ HelperPid = spawn(
+ fun() ->
+ ftp__open(Config, [verbose]),
+ Parent ! ok,
+ receive
+ nothing -> ok
+ end
+ end),
+ receive
+ ok ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ LogFile = filename:join([PrivDir,"ticket_6035.log"]),
+ error_logger:logfile({open, LogFile}),
+ exit(HelperPid, shutdown),
+ timer:sleep(2000),
+ error_logger:logfile(close),
+ case is_error_report_6035(LogFile) of
+ true -> ok;
+ false -> {fail, "Bad logfile"}
+ end
+ end.
+
+%%-------------------------------------------------------------------------
+start_ftp() ->
+ [{doc, "Start/stop of ftp service"}].
+start_ftp(Config) ->
+ Pid0 = proplists:get_value(ftp,Config),
+ Pids0 = [ServicePid || {_, ServicePid} <- ftp:services()],
+ true = lists:member(Pid0, Pids0),
+ {ok, [_|_]} = ftp:service_info(Pid0),
+ ftp:stop_service(Pid0),
+ ct:sleep(100),
+ Pids1 = [ServicePid || {_, ServicePid} <- ftp:services()],
+ false = lists:member(Pid0, Pids1),
+
+ Host = proplists:get_value(ftpd_host,Config),
+ Port = proplists:get_value(ftpd_port,Config),
+
+ {ok, Pid1} = ftp:start_standalone([{host, Host},{port, Port}]),
+ Pids2 = [ServicePid || {_, ServicePid} <- ftp:services()],
+ false = lists:member(Pid1, Pids2).
+
+%%-------------------------------------------------------------------------
+ftp_worker() ->
+ [{doc, "Makes sure the ftp worker processes are added and removed "
+ "appropriatly to/from the supervison tree."}].
+ftp_worker(Config) ->
+ Pid = proplists:get_value(ftp,Config),
+ case supervisor:which_children(ftp_sup) of
+ [{_,_, worker, [ftp]}] ->
+ ftp:stop_service(Pid),
+ ct:sleep(5000),
+ [] = supervisor:which_children(ftp_sup),
+ ok;
+ Children ->
+ ct:fail("Unexpected children: ~p",[Children])
+ end.
+
+
+%%%----------------------------------------------------------------
+%%% Error codes not tested elsewhere
+
+error_elogin(Config0) ->
+ Dir = "test",
+ OldFile = "old.txt",
+ NewFile = "new.txt",
+ SrcDir = "data",
+ File = "file.txt",
+ Config = set_state([reset,
+ {mkdir,Dir},
+ {mkfile,OldFile,<<"Contents..">>},
+ {mkfile,[SrcDir,File],<<"Contents..">>}], Config0),
+
+ Pid = proplists:get_value(ftp, Config),
+ ok = ftp:lcd(Pid, id2ftp(SrcDir,Config)),
+ {error,elogin} = ftp:send(Pid, File),
+ ok = ftp:lcd(Pid, id2ftp("",Config)),
+ {error,elogin} = ftp:pwd(Pid),
+ {error,elogin} = ftp:cd(Pid, id2ftp(Dir,Config)),
+ {error,elogin} = ftp:rename(Pid,
+ id2ftp(OldFile,Config),
+ id2ftp(NewFile,Config)),
+ ok.
+
+error_ehost(_Config) ->
+ {error, ehost} = ftp:open("nohost.nodomain"),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Internal functions -----------------------------------------------
+%%--------------------------------------------------------------------
+
+chk_file(Path=[C|_], ExpectedContents, Config) when 0<C,C=<255 ->
+ chk_file([Path], ExpectedContents, Config);
+
+chk_file(PathList, ExpectedContents, Config) ->
+ Path = filename:join(PathList),
+ AbsPath = id2abs(Path,Config),
+ case file:read_file(AbsPath) of
+ {ok,ExpectedContents} ->
+ true;
+ {ok,ReadContents} ->
+ {error,{diff,Pos,RC,LC}} = find_diff(ReadContents, ExpectedContents, 1),
+ ct:log("Bad contents of ~p.~nGot:~n~p~nExpected:~n~p~nDiff at pos ~p ~nRead: ~p~nExp : ~p",
+ [AbsPath,ReadContents,ExpectedContents,Pos,RC,LC]),
+ ct:fail("Bad contents of ~p", [Path]);
+ {error,Error} ->
+ try begin
+ {ok,CWD} = file:get_cwd(),
+ ct:log("file:get_cwd()=~p~nfiles:~n~p",[CWD,file:list_dir(CWD)])
+ end
+ of _ -> ok
+ catch _:_ ->ok
+ end,
+ ct:fail("Error reading ~p: ~p",[Path,Error])
+ end.
+
+
+chk_no_file(Path=[C|_], Config) when 0<C,C=<255 ->
+ chk_no_file([Path], Config);
+
+chk_no_file(PathList, Config) ->
+ Path = filename:join(PathList),
+ AbsPath = id2abs(Path,Config),
+ case file:read_file(AbsPath) of
+ {error,enoent} ->
+ true;
+ {ok,Contents} ->
+ ct:log("File ~p exists although it shouldn't. Contents:~n~p",
+ [AbsPath,Contents]),
+ ct:fail("File exists: ~p", [Path]);
+ {error,Error} ->
+ ct:fail("Unexpected error reading ~p: ~p",[Path,Error])
+ end.
+
+
+chk_dir(Path=[C|_], Config) when 0<C,C=<255 ->
+ chk_dir([Path], Config);
+
+chk_dir(PathList, Config) ->
+ Path = filename:join(PathList),
+ AbsPath = id2abs(Path,Config),
+ case file:read_file_info(AbsPath) of
+ {ok, #file_info{type=directory}} ->
+ true;
+ {ok, #file_info{type=Type}} ->
+ ct:fail("Expected dir ~p is a ~p",[Path,Type]);
+ {error,Error} ->
+ ct:fail("Expected dir ~p: ~p",[Path,Error])
+ end.
+
+chk_no_dir(PathList, Config) ->
+ Path = filename:join(PathList),
+ AbsPath = id2abs(Path,Config),
+ case file:read_file_info(AbsPath) of
+ {error,enoent} ->
+ true;
+ {ok, #file_info{type=directory}} ->
+ ct:fail("Dir ~p erroneously exists",[Path]);
+ {ok, #file_info{type=Type}} ->
+ ct:fail("~p ~p erroneously exists",[Type,Path]);
+ {error,Error} ->
+ ct:fail("Unexpected error for ~p: ~p",[Path,Error])
+ end.
+
+%%--------------------------------------------------------------------
+find_executable(Config) ->
+ search_executable(proplists:get_value(ftpservers, Config, ?default_ftp_servers)).
+
+
+search_executable([{Name,Paths,_StartCmd,_ChkUp,_StopCommand,_ConfigUpd,_Host,_Port}|Srvrs]) ->
+ case os_find(Name,Paths) of
+ false ->
+ ct:log("~p not found",[Name]),
+ search_executable(Srvrs);
+ AbsName ->
+ ct:comment("Found ~p",[AbsName]),
+ {ok, {AbsName,_StartCmd,_ChkUp,_StopCommand,_ConfigUpd,_Host,_Port}}
+ end;
+search_executable([]) ->
+ false.
+
+
+os_find(Name, Paths) ->
+ case os:find_executable(Name, Paths) of
+ false -> os:find_executable(Name);
+ AbsName -> AbsName
+ end.
+
+%%%----------------------------------------------------------------
+start_ftpd(Config0) ->
+ {AbsName,StartCmd,_ChkUp,_StopCommand,ConfigRewrite,Host,Port} =
+ proplists:get_value(ftpd_data, Config0),
+ case StartCmd(Config0, AbsName) of
+ {ok,StartResult} ->
+ Config = [{ftpd_host,Host},
+ {ftpd_port,Port},
+ {ftpd_start_result,StartResult} | ConfigRewrite(Config0)],
+ try
+ ftp__close(ftp__open(Config,[verbose]))
+ of
+ Config1 when is_list(Config1) ->
+ ct:log("Usuable ftp server ~p started on ~p:~p",[AbsName,Host,Port]),
+ Config
+ catch
+ Class:Exception ->
+ ct:log("Ftp server ~p started on ~p:~p but is unusable:~n~p:~p",
+ [AbsName,Host,Port,Class,Exception]),
+ {skip, [AbsName," started but unusuable"]}
+ end;
+ {error,Msg} ->
+ {skip, [AbsName," not started: ",Msg]}
+ end.
+
+stop_ftpd(Config) ->
+ {_Name,_StartCmd,_ChkUp,StopCommand,_ConfigUpd,_Host,_Port} = proplists:get_value(ftpd_data, Config),
+ StopCommand(proplists:get_value(ftpd_start_result,Config)).
+
+ps_ftpd(Config) ->
+ {_Name,_StartCmd,ChkUp,_StopCommand,_ConfigUpd,_Host,_Port} = proplists:get_value(ftpd_data, Config),
+ ct:log( ChkUp(proplists:get_value(ftpd_start_result,Config)) ).
+
+
+ftpd_running(Config) ->
+ {_Name,_StartCmd,ChkUp,_StopCommand,_ConfigUpd,_Host,_Port} = proplists:get_value(ftpd_data, Config),
+ ChkUp(proplists:get_value(ftpd_start_result,Config)).
+
+ftp__open(Config, Options) ->
+ Host = proplists:get_value(ftpd_host,Config),
+ Port = proplists:get_value(ftpd_port,Config),
+ ct:log("Host=~p, Port=~p",[Host,Port]),
+ {ok,Pid} = ftp:open(Host, [{port,Port} | Options]),
+ [{ftp,Pid}|Config].
+
+ftp__close(Config) ->
+ ok = ftp:close(proplists:get_value(ftp,Config)),
+ Config.
+
+ftp_start_service(Config, Options) ->
+ Host = proplists:get_value(ftpd_host,Config),
+ Port = proplists:get_value(ftpd_port,Config),
+ ct:log("Host=~p, Port=~p",[Host,Port]),
+ {ok,Pid} = ftp:start_service([{host, Host},{port,Port} | Options]),
+ [{ftp,Pid}|Config].
+
+ftp_stop_service(Config) ->
+ ok = ftp:stop_service(proplists:get_value(ftp,Config)),
+ Config.
+
+split(Cs) -> string:tokens(Cs, "\r\n").
+
+find_diff(Bin1, Bin2) ->
+ case find_diff(Bin1, Bin2, 1) of
+ {error, {diff,Pos,RC,LC}} ->
+ ct:log("Contents differ at position ~p.~nOp1: ~p~nOp2: ~p",[Pos,RC,LC]),
+ ct:fail("Contents differ at pos ~p",[Pos]);
+ Other ->
+ Other
+ end.
+
+find_diff(A, A, _) -> true;
+find_diff(<<H,T1/binary>>, <<H,T2/binary>>, Pos) -> find_diff(T1, T2, Pos+1);
+find_diff(RC, LC, Pos) -> {error, {diff, Pos, RC, LC}}.
+
+set_state(Ops, Config) when is_list(Ops) -> lists:foldl(fun set_state/2, Config, Ops);
+
+set_state(reset, Config) ->
+ rm('*', id2abs("",Config)),
+ PrivDir = proplists:get_value(priv_dir,Config),
+ file:set_cwd(PrivDir),
+ ftp:lcd(proplists:get_value(ftp,Config),PrivDir),
+ set_state({mkdir,""},Config);
+set_state({mkdir,Id}, Config) ->
+ Abs = id2abs(Id, Config),
+ mk_path(Abs),
+ file:make_dir(Abs),
+ Config;
+set_state({mkfile,Id,Contents}, Config) ->
+ Abs = id2abs(Id, Config),
+ mk_path(Abs),
+ ok = file:write_file(Abs, Contents),
+ Config.
+
+mk_path(Abs) -> lists:foldl(fun mk_path/2, [], filename:split(filename:dirname(Abs))).
+
+mk_path(F, Pfx) ->
+ case file:read_file_info(AbsName=filename:join(Pfx,F)) of
+ {ok,#file_info{type=directory}} ->
+ AbsName;
+ {error,eexist} ->
+ AbsName;
+ {error,enoent} ->
+ ok = file:make_dir(AbsName),
+ AbsName
+ end.
+
+rm('*', Pfx) ->
+ {ok,Fs} = file:list_dir(Pfx),
+ lists:foreach(fun(F) -> rm(F, Pfx) end, Fs);
+rm(F, Pfx) ->
+ case file:read_file_info(AbsName=filename:join(Pfx,F)) of
+ {ok,#file_info{type=directory}} ->
+ {ok,Fs} = file:list_dir(AbsName),
+ lists:foreach(fun(F1) -> rm(F1,AbsName) end, Fs),
+ ok = file:del_dir(AbsName);
+
+ {ok,#file_info{type=regular}} ->
+ ok = file:delete(AbsName);
+
+ {error,enoent} ->
+ ok
+ end.
+
+id2abs(Id, Conf) -> filename:join(proplists:get_value(priv_dir,Conf),ids(Id)).
+id2ftp(Id, Conf) -> (proplists:get_value(id2ftp,Conf))(ids(Id)).
+id2ftp_result(Id, Conf) -> (proplists:get_value(id2ftp_result,Conf))(ids(Id)).
+
+ids([[_|_]|_]=Ids) -> filename:join(Ids);
+ids(Id) -> Id.
+
+
+is_expected_absName(Id, File, Conf) -> File = (proplists:get_value(id2abs,Conf))(Id).
+is_expected_ftpInName(Id, File, Conf) -> File = (proplists:get_value(id2ftp,Conf))(Id).
+is_expected_ftpOutName(Id, File, Conf) -> File = (proplists:get_value(id2ftp_result,Conf))(Id).
+
+
+%%%----------------------------------------------------------------
+%%% Help functions for the option '{progress,Progress}'
+%%%
+
+%%%----------------
+%%% Callback:
+
+progress(#progress{} = P, _File, {file_size, Total} = M) ->
+ ct:pal("Progress: ~p",[M]),
+ progress_report_receiver ! start,
+ P#progress{total = Total};
+
+progress(#progress{current = Current} = P, _File, {transfer_size, 0} = M) ->
+ ct:pal("Progress: ~p",[M]),
+ progress_report_receiver ! finish,
+ case P#progress.total of
+ unknown -> P;
+ Current -> P;
+ Total -> ct:fail({error, {progress, {total,Total}, {current,Current}}}),
+ P
+ end;
+
+progress(#progress{current = Current} = P, _File, {transfer_size, Size} = M) ->
+ ct:pal("Progress: ~p",[M]),
+ progress_report_receiver ! update,
+ P#progress{current = Current + Size};
+
+progress(P, _File, M) ->
+ ct:pal("Progress **** Strange: ~p",[M]),
+ P.
+
+
+%%%----------------
+%%% Help process that counts the files transferred:
+
+progress_report_receiver_init(Parent, N) ->
+ register(progress_report_receiver, self()),
+ progress_report_receiver_expect_N_files(Parent, N).
+
+progress_report_receiver_expect_N_files(_Parent, 0) ->
+ ct:pal("progress_report got all files!", []);
+progress_report_receiver_expect_N_files(Parent, N) ->
+ ct:pal("progress_report expects ~p more files",[N]),
+ receive
+ start -> ok
+ end,
+ progress_report_receiver_loop(Parent, N-1).
+
+
+progress_report_receiver_loop(Parent, N) ->
+ ct:pal("progress_report expect update | finish. N = ~p",[N]),
+ receive
+ update ->
+ ct:pal("progress_report got update",[]),
+ progress_report_receiver_loop(Parent, N);
+ finish ->
+ ct:pal("progress_report got finish, send ~p to ~p",[{self(),ok}, Parent]),
+ Parent ! {self(), ok},
+ progress_report_receiver_expect_N_files(Parent, N)
+ end.
+
+%%%----------------------------------------------------------------
+%%% Help functions for bug OTP-6035
+
+is_error_report_6035(LogFile) ->
+ case file:read_file(LogFile) of
+ {ok, Bin} ->
+ nomatch =/= binary:match(Bin, <<"=ERROR REPORT====">>);
+ _ ->
+ false
+ end.
+
diff --git a/lib/inets/test/ftp_SUITE_data/ftpd_hosts.skel b/lib/ftp/test/ftp_SUITE_data/ftpd_hosts.skel
index 75096ce687..75096ce687 100644
--- a/lib/inets/test/ftp_SUITE_data/ftpd_hosts.skel
+++ b/lib/ftp/test/ftp_SUITE_data/ftpd_hosts.skel
diff --git a/lib/ftp/test/ftp_SUITE_data/vsftpd.conf b/lib/ftp/test/ftp_SUITE_data/vsftpd.conf
new file mode 100644
index 0000000000..4568fad147
--- /dev/null
+++ b/lib/ftp/test/ftp_SUITE_data/vsftpd.conf
@@ -0,0 +1,33 @@
+
+###
+### Some parameters are given in the vsftpd start command.
+###
+### Typical command-line paramters are such that has a file path
+### component like cert files.
+###
+
+
+listen=YES
+listen_port=9999
+run_as_launching_user=YES
+ssl_enable=YES
+ssl_ciphers=HIGH:!aNULL:!MD5
+allow_anon_ssl=YES
+
+background=YES
+
+write_enable=YES
+anonymous_enable=YES
+anon_upload_enable=YES
+anon_mkdir_write_enable=YES
+anon_other_write_enable=YES
+anon_world_readable_only=NO
+
+### Shouldn't be necessary....
+require_ssl_reuse=NO
+
+### Logging
+#vsftpd_log_file=/devel/otp/vsftpd.log
+#xferlog_enable=YES
+#xferlog_std_format=NO
+#log_ftp_protocol=YES \ No newline at end of file
diff --git a/lib/ftp/test/ftp_bench.spec b/lib/ftp/test/ftp_bench.spec
new file mode 100644
index 0000000000..4d1ecf8891
--- /dev/null
+++ b/lib/ftp/test/ftp_bench.spec
@@ -0,0 +1 @@
+{suites,"../ftp_test",[]}.
diff --git a/lib/ftp/test/ftp_format_SUITE.erl b/lib/ftp/test/ftp_format_SUITE.erl
new file mode 100644
index 0000000000..e1d0de2390
--- /dev/null
+++ b/lib/ftp/test/ftp_format_SUITE.erl
@@ -0,0 +1,328 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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(ftp_format_SUITE).
+-author('[email protected]').
+
+-include_lib("common_test/include/ct.hrl").
+-include("ftp_internal.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{seconds,5}}
+ ].
+
+all() ->
+ [{group, ftp_response}, format_error].
+
+groups() ->
+ [{ftp_response, [],
+ [ftp_150, ftp_200, ftp_220, ftp_226, ftp_257, ftp_331,
+ ftp_425, ftp_other_status_codes, ftp_multiple_lines_status_in_msg,
+ ftp_multiple_lines, ftp_multipel_ctrl_messages]}].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+init_per_testcase(_, Config) ->
+ Config.
+end_per_testcase(_, _) ->
+ ok.
+
+%%-------------------------------------------------------------------------
+%% Test cases starts here.
+%%-------------------------------------------------------------------------
+
+ftp_150() ->
+ [{doc, "Especially check that respons can be devided in a random place."}].
+ftp_150(Config) when is_list(Config) ->
+ FtpResponse = ["150 ASCII data conn", "ection for /bin/ls ",
+ "(134.138.177", ".89,50434) (0 bytes).\r\n"],
+
+ "150 ASCII data connection for /bin/ls "
+ "(134.138.177.89,50434) (0 bytes).\r\n" = Msg =
+ parse(ftp_response, parse_lines, [[], start], FtpResponse),
+ {pos_prel, _} = ftp_response:interpret(Msg).
+
+ftp_200() ->
+ [{doc, "Especially check that respons can be devided after the first status "
+ "code character and in the end delimiter."}].
+ftp_200(Config) when is_list(Config) ->
+ FtpResponse = ["2", "00 PORT command successful.", [?CR], [?LF]],
+
+ "200 PORT command successful.\r\n" = Msg =
+ parse(ftp_response, parse_lines, [[], start], FtpResponse),
+ {pos_compl, _} = ftp_response:interpret(Msg),
+ ok.
+
+ftp_220() ->
+ [{doc, "Especially check that respons can be devided after the "
+ "first with space "}].
+ftp_220(Config) when is_list(Config) ->
+ FtpResponse = ["220 ","fingon FTP server (SunOS 5.8) ready.\r\n"],
+
+ "220 fingon FTP server (SunOS 5.8) ready.\r\n" = Msg =
+ parse(ftp_response, parse_lines, [[], start], FtpResponse),
+ {pos_compl, _} = ftp_response:interpret(Msg),
+ ok.
+
+ftp_226() ->
+ [{doc, "Especially check that respons can be devided after second status code"
+ " character and in the end delimiter."}].
+ftp_226(Config) when is_list(Config) ->
+ FtpResponse = ["22" "6 Transfer complete.\r", [?LF]],
+
+ "226 Transfer complete.\r\n" = Msg =
+ parse(ftp_response, parse_lines, [[], start], FtpResponse),
+ {pos_compl, _} = ftp_response:interpret(Msg),
+ ok.
+
+ftp_257() ->
+ [{doc, "Especially check that quoted chars do not cause a problem."}].
+ftp_257(Config) when is_list(Config) ->
+ FtpResponse = ["257 \"/\" is current directory.\r\n"],
+
+ "257 \"/\" is current directory.\r\n" = Msg =
+ parse(ftp_response, parse_lines, [[], start], FtpResponse),
+ {pos_compl, _} = ftp_response:interpret(Msg),
+ ok.
+
+ftp_331() ->
+ [{doc, "Especially check that respons can be devided after the third status "
+ " status code character."}].
+ftp_331(Config) when is_list(Config) ->
+ %% Brake before white space after code
+ FtpResponse =
+ ["331"," Guest login ok, send ient as password.\r\n"],
+
+ "331 Guest login ok, send ient as password.\r\n" = Msg =
+ parse(ftp_response, parse_lines, [[], start], FtpResponse),
+ {pos_interm, _} = ftp_response:interpret(Msg),
+ ok.
+
+ftp_425() ->
+ [{doc, "Especially check a message that was received in only one part."}].
+ftp_425(Config) when is_list(Config) ->
+ FtpResponse =
+ ["425 Can't build data connection: Connection refused.\r\n"],
+
+ "425 Can't build data connection: Connection refused.\r\n"
+ = Msg = parse(ftp_response, parse_lines, [[], start], FtpResponse),
+ {trans_neg_compl, _} = ftp_response:interpret(Msg),
+ ok.
+
+ftp_multiple_lines_status_in_msg() ->
+ [{doc, "check that multiple lines gets parsed correct, even if we have "
+ " the status code within the msg being sent"}].
+ftp_multiple_lines_status_in_msg(Config) when is_list(Config) ->
+ ML = "230-User usr-230 is logged in\r\n" ++
+ "230 OK. Current directory is /\r\n",
+ {ok, ML, <<>>} = ftp_response:parse_lines(list_to_binary(ML), [], start),
+ ok.
+
+ftp_multiple_lines() ->
+ [{doc, "Especially check multiple lines devided in significant places"}].
+ftp_multiple_lines(Config) when is_list(Config) ->
+ FtpResponse = ["21", "4","-The",
+ " following commands are recognized:\r\n"
+ " USER EPRT STRU MAIL* ALLO CWD",
+ " STAT* XRMD \r\n"
+ " PASS LPRT MODE MSND* "
+ " REST* XCWD HELP PWD ", [?CRLF],
+ " ACCT* EPSV RETR MSOM* RNFR LIST "
+ " NOOP XPWD \r\n",
+ " REIN* LPSV STOR MSAM* RNTO NLST "
+ " MKD CDUP \r\n"
+ " QUIT PASV APPE MRSQ* ABOR SITE* "
+ " XMKD XCUP \r\n"
+ " PORT TYPE MLFL* MRCP* DELE SYST "
+ " RMD STOU \r\n"
+ "214 (*'s => unimplemented)", [?CR], [?LF]],
+
+
+ FtpResponse1 = ["214-", "The",
+ " following commands are recognized:\r\n"
+ " USER EPRT STRU MAIL* ALLO CWD",
+ " STAT* XRMD \r\n"
+ " PASS LPRT MODE MSND* "
+ " REST* XCWD HELP PWD ", [?CRLF],
+ " ACCT* EPSV RETR MSOM* RNFR LIST "
+ " NOOP XPWD \r\n",
+ " REIN* LPSV STOR MSAM* RNTO NLST "
+ " MKD CDUP \r\n"
+ " QUIT PASV APPE MRSQ* ABOR SITE* "
+ " XMKD XCUP \r\n"
+ " PORT TYPE MLFL* MRCP* DELE SYST "
+ " RMD STOU \r\n"
+ "2", "14 (*'s => unimplemented)", [?CR], [?LF]],
+
+ FtpResponse2 = ["214-", "The",
+ " following commands are recognized:\r\n"
+ " USER EPRT STRU MAIL* ALLO CWD",
+ " STAT* XRMD \r\n"
+ " PASS LPRT MODE MSND* "
+ " REST* XCWD HELP PWD ", [?CRLF],
+ " ACCT* EPSV RETR MSOM* RNFR LIST "
+ " NOOP XPWD \r\n",
+ " REIN* LPSV STOR MSAM* RNTO NLST "
+ " MKD CDUP \r\n"
+ " QUIT PASV APPE MRSQ* ABOR SITE* "
+ " XMKD XCUP \r\n"
+ " PORT TYPE MLFL* MRCP* DELE SYST "
+ " RMD STOU \r\n"
+ "21", "4"," (*'s => unimplemented)", [?CR], [?LF]],
+
+ MultiLineResultStr =
+ "214-The following commands are recognized:\r\n"
+ " USER EPRT STRU MAIL* ALLO CWD STAT* "
+ "XRMD \r\n"
+ " PASS LPRT MODE MSND* REST* XCWD HELP "
+ "PWD \r\n"
+ " ACCT* EPSV RETR MSOM* RNFR LIST NOOP "
+ "XPWD \r\n"
+ " REIN* LPSV STOR MSAM* RNTO NLST MKD "
+ "CDUP \r\n"
+ " QUIT PASV APPE MRSQ* ABOR SITE* XMKD "
+ "XCUP \r\n"
+ " PORT TYPE MLFL* MRCP* DELE SYST RMD "
+ "STOU \r\n"
+ "214 (*'s => unimplemented)\r\n",
+
+ MultiLineResultStr =
+ parse(ftp_response, parse_lines, [[], start], FtpResponse),
+ {pos_compl, _} = ftp_response:interpret(MultiLineResultStr),
+
+ MultiLineResultStr = parse(ftp_response, parse_lines, [[], start],
+ FtpResponse1),
+
+ MultiLineResultStr = parse(ftp_response, parse_lines, [[], start],
+ FtpResponse2),
+ ok.
+
+ftp_other_status_codes() ->
+ [{doc, "Check that other valid status codes, than the ones above, are handled"
+ "by ftp_response:interpret/1. Note there are som ftp status codes"
+ "that will not be received with the current ftp instruction support,"
+ "they are not included here."}].
+ftp_other_status_codes(Config) when is_list(Config) ->
+
+ %% 1XX
+ {pos_prel, _ } = ftp_response:interpret("120 Foobar\r\n"),
+
+ %% 2XX
+ {pos_compl, _ } = ftp_response:interpret("202 Foobar\r\n"),
+ {pos_compl, _ } = ftp_response:interpret("221 Foobar\r\n"),
+ {pos_compl, _ } = ftp_response:interpret("227 Foobar\r\n"),
+ {pos_compl, _ } = ftp_response:interpret("230 Foobar\r\n"),
+ {pos_compl, _ } = ftp_response:interpret("250 Foobar\r\n"),
+
+ %% 3XX
+ {pos_interm_acct, _ } = ftp_response:interpret("332 Foobar\r\n"),
+ {pos_interm, _ } = ftp_response:interpret("350 Foobar\r\n"),
+
+ %% 4XX
+ {trans_neg_compl, _ } = ftp_response:interpret("421 Foobar\r\n"),
+ {trans_neg_compl, _ } = ftp_response:interpret("426 Foobar\r\n"),
+ {enofile, _ } = ftp_response:interpret("450 Foobar\r\n"),
+ {trans_neg_compl, _ } = ftp_response:interpret("451 Foobar\r\n"),
+ {etnospc, _ } = ftp_response:interpret("452 Foobar\r\n"),
+
+ %% 5XX
+ {perm_neg_compl, _ } = ftp_response:interpret("500 Foobar\r\n"),
+ {perm_neg_compl, _ } = ftp_response:interpret("501 Foobar\r\n"),
+ {perm_neg_compl, _ } = ftp_response:interpret("503 Foobar\r\n"),
+ {perm_neg_compl, _ } = ftp_response:interpret("504 Foobar\r\n"),
+ {elogin, _ } = ftp_response:interpret("530 Foobar\r\n"),
+ {perm_neg_compl, _ } = ftp_response:interpret("532 Foobar\r\n"),
+ {epath, _ } = ftp_response:interpret("550 Foobar\r\n"),
+ {epnospc, _ } = ftp_response:interpret("552 Foobar\r\n"),
+ {efnamena, _ } = ftp_response:interpret("553 Foobar\r\n"),
+ ok.
+
+ftp_multipel_ctrl_messages() ->
+ [{doc, "The ftp server may send more than one control message as a reply,"
+ "check that they are handled one at the time."}].
+ftp_multipel_ctrl_messages(Config) when is_list(Config) ->
+ FtpResponse = ["200 PORT command successful.\r\n200 Foobar\r\n"],
+
+ {"200 PORT command successful.\r\n" = Msg, NextMsg} =
+ parse(ftp_response, parse_lines, [[], start], FtpResponse),
+ {pos_compl, _} = ftp_response:interpret(Msg),
+ NewMsg = parse(ftp_response, parse_lines, [[], start], NextMsg),
+ {pos_compl, _} = ftp_response:interpret(NewMsg),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+format_error(Config) when is_list(Config) ->
+ "Synchronisation error during chunk sending." =
+ ftp:formaterror(echunk),
+ "Session has been closed." = ftp:formaterror(eclosed),
+ "Connection to remote server prematurely closed." =
+ ftp:formaterror(econn),
+ "File or directory already exists." = ftp:formaterror(eexists),
+ "Host not found, FTP server not found, or connection rejected." =
+ ftp:formaterror(ehost),
+ "User not logged in." = ftp:formaterror(elogin),
+ "Term is not a binary." = ftp:formaterror(enotbinary),
+ "No such file or directory, already exists, or permission denied."
+ = ftp:formaterror(epath),
+ "No such type." = ftp:formaterror(etype),
+ "User name or password not valid." = ftp:formaterror(euser),
+ "Insufficient storage space in system." = ftp:formaterror(etnospc),
+ "Exceeded storage allocation (for current directory or dataset)."
+ = ftp:formaterror(epnospc),
+ "File name not allowed." = ftp:formaterror(efnamena),
+ "Unknown error: foobar" = ftp:formaterror({error, foobar}).
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+parse(Module, Function, Args, Bin) when is_binary(Bin) ->
+ parse(Module, Function, Args, [binary_to_list(Bin)]);
+
+parse(Module, Function, [AccLines, StatusCode], [Data | Rest]) ->
+ case Module:Function(list_to_binary(Data), AccLines, StatusCode) of
+ {ok, Result, <<>>} ->
+ Result;
+ {ok, Result, Next} ->
+ {Result, Next};
+ {continue, {NewData, NewAccLines, NewStatusCode}} ->
+ case Rest of
+ [] ->
+ ct:fail({wrong_input, Data, Rest});
+ [_ | _] ->
+ parse(Module, Function, [NewAccLines, NewStatusCode],
+ [binary_to_list(NewData) ++ hd(Rest) | tl(Rest)])
+ end
+ end.
diff --git a/lib/ftp/test/ftp_internal.hrl b/lib/ftp/test/ftp_internal.hrl
new file mode 120000
index 0000000000..2ae5c46460
--- /dev/null
+++ b/lib/ftp/test/ftp_internal.hrl
@@ -0,0 +1 @@
+../src/ftp_internal.hrl \ No newline at end of file
diff --git a/lib/ftp/test/ftp_property_test_SUITE.erl b/lib/ftp/test/ftp_property_test_SUITE.erl
new file mode 100644
index 0000000000..cd43613b9e
--- /dev/null
+++ b/lib/ftp/test/ftp_property_test_SUITE.erl
@@ -0,0 +1,55 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%
+%%
+
+%%% Run like this:
+%%% ct:run_test([{suite,"ftp_property_test_SUITE"}, {logdir,"/ldisk/OTP/LOG"}]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% %%%
+%%% WARNING %%%
+%%% %%%
+%%% This is experimental code which may be changed or removed %%%
+%%% anytime without any warning. %%%
+%%% %%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-module(ftp_property_test_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+all() -> [prop_ftp_case].
+
+
+init_per_suite(Config) ->
+ ftp:start(),
+ ct_property_test:init_per_suite(Config).
+
+end_per_suite(Config) ->
+ Config.
+
+%%%---- test case
+prop_ftp_case(Config) ->
+ ct_property_test:quickcheck(
+ ftp_simple_client_server:prop_ftp(Config),
+ Config
+ ).
diff --git a/lib/ftp/test/ftp_test_lib.erl b/lib/ftp/test/ftp_test_lib.erl
new file mode 100644
index 0000000000..f5fbc39037
--- /dev/null
+++ b/lib/ftp/test/ftp_test_lib.erl
@@ -0,0 +1,126 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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(ftp_test_lib).
+
+-include_lib("public_key/include/public_key.hrl").
+
+-export([make_cert_files/1]).
+
+
+make_cert_files(Dir) ->
+ #{server_config := ServerConf,
+ client_config := _} =
+ public_key:pkix_test_data(#{server_chain =>
+ #{root => [{key, hardcode_rsa_key(1)}],
+ intermediates => [[{key, hardcode_rsa_key(2)}]],
+ peer => [{key, hardcode_rsa_key(3)}]},
+ client_chain =>
+ #{root => [{key, hardcode_rsa_key(1)}],
+ intermediates => [[{key, hardcode_rsa_key(3)}]],
+ peer => [{key, hardcode_rsa_key(2)}]}}),
+
+ CaCertFile = filename:join(Dir, "server-cacerts.pem"),
+ CertFile = filename:join(Dir, "server-cert.pem"),
+ KeyFile = filename:join(Dir, "server-key.pem"),
+
+ CAs = proplists:get_value(cacerts, ServerConf),
+ Cert = proplists:get_value(cert, ServerConf),
+ Key = proplists:get_value(key, ServerConf),
+ der_to_pem(CertFile, [cert_entry(Cert)]),
+ der_to_pem(KeyFile, [key_entry(Key)]),
+ der_to_pem(CaCertFile, ca_entries(CAs)).
+
+cert_entry(Cert) ->
+ {'Certificate', Cert, not_encrypted}.
+
+key_entry({'RSAPrivateKey', DERKey}) ->
+ {'RSAPrivateKey', DERKey, not_encrypted};
+key_entry({'DSAPrivateKey', DERKey}) ->
+ {'DSAPrivateKey', DERKey, not_encrypted};
+key_entry({'ECPrivateKey', DERKey}) ->
+ {'ECPrivateKey', DERKey, not_encrypted}.
+
+ca_entries(CAs) ->
+ [{'Certificate', CACert, not_encrypted} || CACert <- CAs].
+
+der_to_pem(File, Entries) ->
+ PemBin = public_key:pem_encode(Entries),
+ file:write_file(File, PemBin).
+
+hardcode_rsa_key(1) ->
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus =
+23995666614853919027835084074500048897452890537492185072956789802729257783422306095699263934587064480357348855732149402060270996295002843755712064937715826848741191927820899197493902093529581182351132392364214171173881547273475904587683433713767834856230531387991145055273426806331200574039205571401702219159773947658558490957010003143162250693492642996408861265758000254664396313741422909188635443907373976005987612936763564996605457102336549804831742940035613780926178523017685712710473543251580072875247250504243621640157403744718833162626193206685233710319205099867303242759099560438381385658382486042995679707669,
+ publicExponent = 17,
+ privateExponent =
+11292078406990079542510627799764728892919007311761028269626724613049062486316379339152594792746853873109340637991599718616598115903530750002688030558925094987642913848386305504703012749896273497577003478759630198199473669305165131570674557041773098755873191241407597673069847908861741446606684974777271632545629600685952292605647052193819136445675100211504432575554351515262198132231537860917084269870590492135731720141577986787033006338680118008484613510063003323516659048210893001173583018220214626635609151105287049126443102976056146630518124476470236027123782297108342869049542023328584384300970694412006494684657,
+prime1 =
+169371138592582642967021557955633494538845517070305333860805485424261447791289944610138334410987654265476540480228705481960508520379619587635662291973699651583489223555422528867090299996446070521801757353675026048850480903160224210802452555900007597342687137394192939372218903554801584969667104937092080815197,
+ prime2 =
+141675062317286527042995673340952251894209529891636708844197799307963834958115010129693036021381525952081167155681637592199810112261679449166276939178032066869788822014115556349519329537177920752776047051833616197615329017439297361972726138285974555338480581117881706656603857310337984049152655480389797687577,
+ exponent1 =
+119556097830058336212015217380447172615655659108450823901745048534772786676204666783627059584226579481512852103690850928442711896738555003036938088452023283470698275450886490965004917644550167427154181661417665446247398284583687678213495921811770068712485038160606780733330990744565824684470897602653233516609,
+ exponent2 =
+41669135975672507953822256864985956439473391144599032012999352737636422046504414744027363535700448809435637398729893409470532385959317485048904982111185902020526124121798693043976273393287623750816484427009887116945685005129205106462566511260580751570141347387612266663707016855981760014456663376585234613993,
+ coefficient =
+76837684977089699359024365285678488693966186052769523357232308621548155587515525857011429902602352279058920284048929101483304120686557782043616693940283344235057989514310975192908256494992960578961614059245280827077951132083993754797053182279229469590276271658395444955906108899267024101096069475145863928441,
+ otherPrimeInfos = asn1_NOVALUE};
+
+hardcode_rsa_key(2) ->
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus =
+21343679768589700771839799834197557895311746244621307033143551583788179817796325695589283169969489517156931770973490560582341832744966317712674900833543896521418422508485833901274928542544381247956820115082240721897193055368570146764204557110415281995205343662628196075590438954399631753508888358737971039058298703003743872818150364935790613286541190842600031570570099801682794056444451081563070538409720109449780410837763602317050353477918147758267825417201591905091231778937606362076129350476690460157227101296599527319242747999737801698427160817755293383890373574621116766934110792127739174475029121017282777887777,
+ publicExponent = 17,
+ privateExponent =
+18832658619343853622211588088997845201745658451136447382185486691577805721584993260814073385267196632785528033211903435807948675951440868570007265441362261636545666919252206383477878125774454042314841278013741813438699754736973658909592256273895837054592950290554290654932740253882028017801960316533503857992358685308186680144968293076156011747178275038098868263178095174694099811498968993700538293188879611375604635940554394589807673542938082281934965292051746326331046224291377703201248790910007232374006151098976879987912446997911775904329728563222485791845480864283470332826504617837402078265424772379987120023773,
+ prime1 =
+146807662748886761089048448970170315054939768171908279335181627815919052012991509112344782731265837727551849787333310044397991034789843793140419387740928103541736452627413492093463231242466386868459637115999163097726153692593711599245170083315894262154838974616739452594203727376460632750934355508361223110419,
+ prime2 =
+145385325050081892763917667176962991350872697916072592966410309213561884732628046256782356731057378829876640317801978404203665761131810712267778698468684631707642938779964806354584156202882543264893826268426566901882487709510744074274965029453915224310656287149777603803201831202222853023280023478269485417083,
+ exponent1 =
+51814469205489445090252393754177758254684624060673510353593515699736136004585238510239335081623236845018299924941168250963996835808180162284853901555621683602965806809675350150634081614988136541809283687999704622726877773856604093851236499993845033701707873394143336209718962603456693912094478414715725803677,
+ exponent2 =
+51312467664734785681382706062457526359131540440966797517556579722433606376221663384746714140373192528191755406283051201483646739222992016094510128871300458249756331334105225772206172777487956446433115153562317730076172132768497908567634716277852432109643395464627389577600646306666889302334125933506877206029,
+ coefficient =
+30504662229874176232343608562807118278893368758027179776313787938167236952567905398252901545019583024374163153775359371298239336609182249464886717948407152570850677549297935773605431024166978281486607154204888016179709037883348099374995148481968169438302456074511782717758301581202874062062542434218011141540,
+ otherPrimeInfos = asn1_NOVALUE};
+
+hardcode_rsa_key(3) ->
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus =
+25089040456112869869472694987833070928503703615633809313972554887193090845137746668197820419383804666271752525807484521370419854590682661809972833718476098189250708650325307850184923546875260207894844301992963978994451844985784504212035958130279304082438876764367292331581532569155681984449177635856426023931875082020262146075451989132180409962870105455517050416234175675478291534563995772675388370042873175344937421148321291640477650173765084699931690748536036544188863178325887393475703801759010864779559318631816411493486934507417755306337476945299570726975433250753415110141783026008347194577506976486290259135429,
+ publicExponent = 17,
+ privateExponent =
+8854955455098659953931539407470495621824836570223697404931489960185796768872145882893348383311931058684147950284994536954265831032005645344696294253579799360912014817761873358888796545955974191021709753644575521998041827642041589721895044045980930852625485916835514940558187965584358347452650930302268008446431977397918214293502821599497633970075862760001650736520566952260001423171553461362588848929781360590057040212831994258783694027013289053834376791974167294527043946669963760259975273650548116897900664646809242902841107022557239712438496384819445301703021164043324282687280801738470244471443835900160721870265,
+ prime1 =
+171641816401041100605063917111691927706183918906535463031548413586331728772311589438043965564336865070070922328258143588739626712299625805650832695450270566547004154065267940032684307994238248203186986569945677705100224518137694769557564475390859269797990555863306972197736879644001860925483629009305104925823,
+ prime2
+=146170909759497809922264016492088453282310383272504533061020897155289106805616042710009332510822455269704884883705830985184223718261139908416790475825625309815234508695722132706422885088219618698987115562577878897003573425367881351537506046253616435685549396767356003663417208105346307649599145759863108910523,
+ exponent1 =
+60579464612132153154728441333538327425711971378777222246428851853999433684345266860486105493295364142377972586444050678378691780811632637288529186629507258781295583787741625893888579292084087601124818789392592131211843947578009918667375697196773859928702549128225990187436545756706539150170692591519448797349,
+ exponent2 =
+137572620950115585809189662580789132500998007785886619351549079675566218169991569609420548245479957900898715184664311515467504676010484619686391036071176762179044243478326713135456833024206699951987873470661533079532774988581535389682358631768109586527575902839864474036157372334443583670210960715165278974609,
+ coefficient =
+15068630434698373319269196003209754243798959461311186548759287649485250508074064775263867418602372588394608558985183294561315208336731894947137343239541687540387209051236354318837334154993136528453613256169847839789803932725339395739618592522865156272771578671216082079933457043120923342632744996962853951612,
+ otherPrimeInfos = asn1_NOVALUE}.
diff --git a/lib/ftp/test/property_test/README b/lib/ftp/test/property_test/README
new file mode 100644
index 0000000000..57602bf719
--- /dev/null
+++ b/lib/ftp/test/property_test/README
@@ -0,0 +1,12 @@
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% %%%
+%%% WARNING %%%
+%%% %%%
+%%% This is experimental code which may be changed or removed %%%
+%%% anytime without any warning. %%%
+%%% %%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+The test in this directory are written assuming that the user has a QuickCheck license. They are to be run manually. Some may be possible to be run with other tools, e.g. PropEr.
+
diff --git a/lib/ftp/test/property_test/ftp_simple_client_server.erl b/lib/ftp/test/property_test/ftp_simple_client_server.erl
new file mode 100644
index 0000000000..d304478b47
--- /dev/null
+++ b/lib/ftp/test/property_test/ftp_simple_client_server.erl
@@ -0,0 +1,307 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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(ftp_simple_client_server).
+
+-compile(export_all).
+
+-ifndef(EQC).
+-ifndef(PROPER).
+-define(EQC,true).
+%%-define(PROPER,true).
+-endif.
+-endif.
+
+
+-ifdef(EQC).
+
+-include_lib("eqc/include/eqc.hrl").
+-include_lib("eqc/include/eqc_statem.hrl").
+-define(MOD_eqc, eqc).
+-define(MOD_eqc_gen, eqc_gen).
+-define(MOD_eqc_statem, eqc_statem).
+
+-else.
+-ifdef(PROPER).
+
+-include_lib("proper/include/proper.hrl").
+-define(MOD_eqc, proper).
+-define(MOD_eqc_gen, proper_gen).
+-define(MOD_eqc_statem, proper_statem).
+
+-endif.
+-endif.
+
+-record(state, {
+ initialized = false,
+ priv_dir,
+ data_dir,
+ servers = [], % [ {IP,Port,Userid,Pwd} ]
+ clients = [], % [ client_ref() ]
+ store = [] % [ {Name,Contents} ]
+ }).
+
+-define(fmt(F,A), io:format(F,A)).
+%%-define(fmt(F,A), ok).
+
+-define(v(K,L), proplists:get_value(K,L)).
+
+%%%================================================================
+%%%
+%%% Properties
+%%%
+
+%% This function is for normal eqc calls:
+prop_ftp() ->
+ {ok,PWD} = file:get_cwd(),
+ prop_ftp(filename:join([PWD,?MODULE_STRING++"_data"]),
+ filename:join([PWD,?MODULE_STRING,"_files"])).
+
+%% This function is for calls from common_test test cases:
+prop_ftp(Config) ->
+ prop_ftp(filename:join([?v(property_dir,Config), ?MODULE_STRING++"_data"]),
+ ?v(priv_dir,Config) ).
+
+
+prop_ftp(DataDir, PrivDir) ->
+ S0 = #state{data_dir = DataDir,
+ priv_dir = PrivDir},
+ ?FORALL(Cmds, more_commands(10,commands(?MODULE,S0)),
+ aggregate(command_names(Cmds),
+ begin {_H,S,Result} = run_commands(?MODULE,Cmds),
+ % io:format('**** Result=~p~n',[Result]),
+ % io:format('**** S=~p~n',[S]),
+ % io:format('**** _H=~p~n',[_H]),
+ % io:format('**** Cmds=~p~n',[Cmds]),
+ [cmnd_stop_server(X) || X <- S#state.servers],
+ [ftp:stop_service(X) || {ok,X} <- S#state.clients],
+ Result==ok
+ end)
+ ).
+
+%%%================================================================
+%%%
+%%% State model
+%%%
+
+%% @doc Returns the state in which each test case starts. (Unless a different
+%% initial state is supplied explicitly to, e.g. commands/2.)
+-spec initial_state() ->?MOD_eqc_statem:symbolic_state().
+initial_state() ->
+ ?fmt("Initial_state()~n",[]),
+ #state{}.
+
+%% @doc Command generator, S is the current state
+-spec command(S :: ?MOD_eqc_statem:symbolic_state()) -> ?MOD_eqc_gen:gen(eqc_statem:call()).
+
+command(#state{initialized=false,
+ priv_dir=PrivDir}) ->
+ {call,?MODULE,cmnd_init,[PrivDir]};
+
+command(#state{servers=[],
+ priv_dir=PrivDir,
+ data_dir=DataDir}) ->
+ {call,?MODULE,cmnd_start_server,[PrivDir,DataDir]};
+
+command(#state{servers=Ss=[_|_],
+ clients=[]}) ->
+ {call,?MODULE,cmnd_start_client,[oneof(Ss)]};
+
+command(#state{servers=Ss=[_|_],
+ clients=Cs=[_|_],
+ store=Store=[_|_]
+ }) ->
+ frequency([
+ { 5, {call,?MODULE,cmnd_start_client,[oneof(Ss)]}},
+ { 5, {call,?MODULE,cmnd_stop_client,[oneof(Cs)]}},
+ {10, {call,?MODULE,cmnd_put,[oneof(Cs),file_path(),file_contents()]}},
+ {20, {call,?MODULE,cmnd_get,[oneof(Cs),oneof(Store)]}},
+ {10, {call,?MODULE,cmnd_delete,[oneof(Cs),oneof(Store)]}}
+ ]);
+
+command(#state{servers=Ss=[_|_],
+ clients=Cs=[_|_],
+ store=[]
+ }) ->
+ frequency([
+ {5, {call,?MODULE,cmnd_start_client,[oneof(Ss)]}},
+ {5, {call,?MODULE,cmnd_stop_client,[oneof(Cs)]}},
+ {10, {call,?MODULE,cmnd_put,[oneof(Cs),file_path(),file_contents()]}}
+ ]).
+
+%% @doc Precondition, checked before command is added to the command sequence.
+-spec precondition(S :: ?MOD_eqc_statem:symbolic_state(), C :: ?MOD_eqc_statem:call()) -> boolean().
+
+precondition(#state{clients=Cs}, {call, _, cmnd_put, [C,_,_]}) -> lists:member(C,Cs);
+
+precondition(#state{clients=Cs, store=Store},
+ {call, _, cmnd_get, [C,X]}) -> lists:member(C,Cs) andalso lists:member(X,Store);
+
+precondition(#state{clients=Cs, store=Store},
+ {call, _, cmnd_delete, [C,X]}) -> lists:member(C,Cs) andalso lists:member(X,Store);
+
+precondition(#state{servers=Ss}, {call, _, cmnd_start_client, _}) -> Ss =/= [];
+
+precondition(#state{clients=Cs}, {call, _, cmnd_stop_client, [C]}) -> lists:member(C,Cs);
+
+precondition(#state{initialized=IsInit}, {call, _, cmnd_init, _}) -> IsInit==false;
+
+precondition(_S, {call, _, _, _}) -> true.
+
+
+%% @doc Postcondition, checked after command has been evaluated
+%% Note: S is the state before next_state(S,_,C)
+-spec postcondition(S :: ?MOD_eqc_statem:dynamic_state(), C :: ?MOD_eqc_statem:call(),
+ Res :: term()) -> boolean().
+
+postcondition(_S, {call, _, cmnd_get, [_,{_Name,Expected}]}, {ok,Value}) ->
+ Value == Expected;
+
+postcondition(S, {call, _, cmnd_delete, [_,{Name,_Expected}]}, ok) ->
+ ?fmt("file:read_file(..) = ~p~n",[file:read_file(filename:join(S#state.priv_dir,Name))]),
+ {error,enoent} == file:read_file(filename:join(S#state.priv_dir,Name));
+
+postcondition(S, {call, _, cmnd_put, [_,Name,Value]}, ok) ->
+ {ok,Bin} = file:read_file(filename:join(S#state.priv_dir,Name)),
+ Bin == unicode:characters_to_binary(Value);
+
+postcondition(_S, {call, _, cmnd_stop_client, _}, ok) -> true;
+
+postcondition(_S, {call, _, cmnd_start_client, _}, {ok,_}) -> true;
+
+postcondition(_S, {call, _, cmnd_init, _}, ok) -> true;
+
+postcondition(_S, {call, _, cmnd_start_server, _}, {ok,_}) -> true.
+
+
+%% @doc Next state transformation, S is the current state. Returns next state.
+-spec next_state(S :: ?MOD_eqc_statem:symbolic_state(),
+ V :: ?MOD_eqc_statem:var(),
+ C :: ?MOD_eqc_statem:call()) -> ?MOD_eqc_statem:symbolic_state().
+
+next_state(S, _V, {call, _, cmnd_put, [_,Name,Val]}) ->
+ S#state{store = [{Name,Val} | lists:keydelete(Name,1,S#state.store)]};
+
+next_state(S, _V, {call, _, cmnd_delete, [_,{Name,_Val}]}) ->
+ S#state{store = lists:keydelete(Name,1,S#state.store)};
+
+next_state(S, V, {call, _, cmnd_start_client, _}) ->
+ S#state{clients = [V | S#state.clients]};
+
+next_state(S, V, {call, _, cmnd_start_server, _}) ->
+ S#state{servers = [V | S#state.servers]};
+
+next_state(S, _V, {call, _, cmnd_stop_client, [C]}) ->
+ S#state{clients = S#state.clients -- [C]};
+
+next_state(S, _V, {call, _, cmnd_init, _}) ->
+ S#state{initialized=true};
+
+next_state(S, _V, {call, _, _, _}) ->
+ S.
+
+%%%================================================================
+%%%
+%%% Data model
+%%%
+
+file_path() -> non_empty(list(alphanum_char())).
+%%file_path() -> non_empty( list(oneof([alphanum_char(), utf8_char()])) ).
+
+%%file_contents() -> list(alphanum_char()).
+file_contents() -> list(oneof([alphanum_char(), utf8_char()])).
+
+alphanum_char() -> oneof(lists:seq($a,$z) ++ lists:seq($A,$Z) ++ lists:seq($0,$9)).
+
+utf8_char() -> oneof("åäöÅÄÖ話话カタカナひらがな").
+
+%%%================================================================
+%%%
+%%% Commands doing something with the System Under Test
+%%%
+
+cmnd_init(PrivDir) ->
+ ?fmt('Call cmnd_init(~p)~n',[PrivDir]),
+ os:cmd("killall vsftpd"),
+ clear_files(PrivDir),
+ ok.
+
+cmnd_start_server(PrivDir, DataDir) ->
+ ?fmt('Call cmnd_start_server(~p, ~p)~n',[PrivDir,DataDir]),
+ Cmnd = ["vsftpd ", filename:join(DataDir,"vsftpd.conf"),
+ " -oftpd_banner=erlang_otp_testing"
+ " -oanon_root=",PrivDir
+ ],
+ ?fmt("Cmnd=~s~n",[Cmnd]),
+ case os:cmd(Cmnd) of
+ [] ->
+ {ok,{"localhost",9999,"ftp","[email protected]"}};
+ Other ->
+ {error,Other}
+ end.
+
+cmnd_stop_server({ok,{_Host,Port,_Usr,_Pwd}}) ->
+ os:cmd("kill `netstat -tpln | grep "++integer_to_list(Port)++" | awk '{print $7}' | awk -F/ '{print $1}'`").
+
+cmnd_start_client({ok,{Host,Port,Usr,Pwd}}) ->
+ ?fmt('Call cmnd_start_client(~p)...',[{Host,Port,Usr,Pwd}]),
+ case ftp:start_service([{host,Host},{port,Port}]) of
+ {ok,Client} ->
+ ?fmt("~p...",[{ok,Client}]),
+ case ftp:user(Client, Usr, Pwd) of
+ ok ->
+ ?fmt("OK!~n",[]),
+ {ok,Client};
+ Other ->
+ ?fmt("Other1=~p~n",[Other]),
+ ftp:stop_service(Client), Other
+ end;
+ Other ->
+ ?fmt("Other2=~p~n",[Other]),
+ Other
+ end.
+
+cmnd_stop_client({ok,Client}) ->
+ ?fmt('Call cmnd_stop_client(~p)~n',[Client]),
+ ftp:stop_service(Client). %% -> ok | Other
+
+cmnd_delete({ok,Client}, {Name,_ExpectedValue}) ->
+ ?fmt('Call cmnd_delete(~p, ~p)~n',[Client,Name]),
+ R=ftp:delete(Client, Name),
+ ?fmt("R=~p~n",[R]),
+ R.
+
+cmnd_put({ok,Client}, Name, Value) ->
+ ?fmt('Call cmnd_put(~p, ~p, ~p)...',[Client, Name, Value]),
+ R = ftp:send_bin(Client, unicode:characters_to_binary(Value), Name), % ok | {error,Error}
+ ?fmt('~p~n',[R]),
+ R.
+
+cmnd_get({ok,Client}, {Name,_ExpectedValue}) ->
+ ?fmt('Call cmnd_get(~p, ~p)~n',[Client,Name]),
+ case ftp:recv_bin(Client, Name) of
+ {ok,Bin} -> {ok, unicode:characters_to_list(Bin)};
+ Other -> Other
+ end.
+
+
+clear_files(Dir) ->
+ os:cmd(["rm -fr ",filename:join(Dir,"*")]).
diff --git a/lib/ftp/test/property_test/ftp_simple_client_server_data/vsftpd.conf b/lib/ftp/test/property_test/ftp_simple_client_server_data/vsftpd.conf
new file mode 100644
index 0000000000..fd48e2abf0
--- /dev/null
+++ b/lib/ftp/test/property_test/ftp_simple_client_server_data/vsftpd.conf
@@ -0,0 +1,26 @@
+
+###
+### Some parameters are given in the vsftpd start command.
+###
+### Typical command-line paramters are such that has a file path
+### component like cert files.
+###
+
+
+listen=YES
+listen_port=9999
+run_as_launching_user=YES
+ssl_enable=NO
+#allow_anon_ssl=YES
+
+background=YES
+
+write_enable=YES
+anonymous_enable=YES
+anon_upload_enable=YES
+anon_mkdir_write_enable=YES
+anon_other_write_enable=YES
+anon_world_readable_only=NO
+
+### Shouldn't be necessary....
+require_ssl_reuse=NO
diff --git a/lib/ftp/vsn.mk b/lib/ftp/vsn.mk
new file mode 100644
index 0000000000..d5d6c45b28
--- /dev/null
+++ b/lib/ftp/vsn.mk
@@ -0,0 +1,24 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2001-2018. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# 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%
+
+APPLICATION = ftp
+FTP_VSN = 1.0.1
+PRE_VSN =
+APP_VSN = "$(APPLICATION)-$(FTP_VSN)$(PRE_VSN)"
diff --git a/lib/hipe/cerl/Makefile b/lib/hipe/cerl/Makefile
index 9f50d6bf91..f653dce36f 100644
--- a/lib/hipe/cerl/Makefile
+++ b/lib/hipe/cerl/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2016. All Rights Reserved.
+# Copyright Ericsson AB 2003-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -44,7 +44,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/hipe-$(VSN)
# Target Specs
# ----------------------------------------------------
MODULES = cerl_cconv cerl_closurean cerl_hipeify cerl_lib \
- cerl_messagean cerl_pmatch cerl_prettypr cerl_to_icode \
+ cerl_pmatch cerl_prettypr cerl_to_icode \
cerl_typean erl_bif_types erl_types
HRL_FILES= cerl_hipe_primops.hrl
diff --git a/lib/hipe/cerl/cerl_cconv.erl b/lib/hipe/cerl/cerl_cconv.erl
index 122e6ef039..2cd0e261d5 100644
--- a/lib/hipe/cerl/cerl_cconv.erl
+++ b/lib/hipe/cerl/cerl_cconv.erl
@@ -258,7 +258,7 @@ bind_module_defs([], Env, S) ->
check_function_name(Name, S) ->
case s__is_function_name(Name, S) of
true ->
- error_msg("multiple definitions of function `~w'.", [Name]),
+ error_msg("multiple definitions of function `~tw'.", [Name]),
exit(error);
false ->
ok
diff --git a/lib/hipe/cerl/cerl_messagean.erl b/lib/hipe/cerl/cerl_messagean.erl
deleted file mode 100644
index c79e045bd0..0000000000
--- a/lib/hipe/cerl/cerl_messagean.erl
+++ /dev/null
@@ -1,1095 +0,0 @@
-%% 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.
-%%
-%% @copyright 2002 Richard Carlsson
-%% @author Richard Carlsson <[email protected]>
-%% @doc Message analysis of Core Erlang programs.
-
-%% TODO: might need a "top" (`any') element for any-length value lists.
-
--module(cerl_messagean).
-
--export([annotate/1]).
-
--import(cerl, [alias_pat/1, alias_var/1, ann_c_var/2, ann_c_fun/3,
- apply_args/1, apply_op/1, atom_val/1, bitstr_size/1,
- bitstr_val/1, binary_segments/1, c_letrec/2,
- ann_c_tuple/2, c_nil/0, call_args/1, call_module/1,
- call_name/1, case_arg/1, case_clauses/1, catch_body/1,
- clause_body/1, clause_guard/1, clause_pats/1, cons_hd/1,
- cons_tl/1, fun_body/1, fun_vars/1, get_ann/1, int_val/1,
- is_c_atom/1, is_c_int/1, let_arg/1, let_body/1,
- let_vars/1, letrec_body/1, letrec_defs/1, module_defs/1,
- module_defs/1, module_exports/1, pat_vars/1,
- primop_args/1, primop_name/1, receive_action/1,
- receive_clauses/1, receive_timeout/1, seq_arg/1,
- seq_body/1, set_ann/2, try_arg/1, try_body/1, try_vars/1,
- try_evars/1, try_handler/1, tuple_es/1, type/1,
- values_es/1]).
-
--import(cerl_trees, [get_label/1]).
-
--define(DEF_LIMIT, 4).
-
-%% -export([test/1, test1/1, ttest/1]).
-
-%% ttest(F) ->
-%% {T, _} = cerl_trees:label(user_default:read(F)),
-%% {Time0, _} = erlang:statistics(runtime),
-%% analyze(T),
-%% {Time1, _} = erlang:statistics(runtime),
-%% Time1 - Time0.
-
-%% test(F) ->
-%% {T, _} = cerl_trees:label(user_default:read(F)),
-%% {Time0, _} = erlang:statistics(runtime),
-%% {Esc, _Vars} = analyze(T),
-%% {Time1, _} = erlang:statistics(runtime),
-%% io:fwrite("messages: ~p.\n", [Esc]),
-%% Set = sets:from_list(Esc),
-%% H = fun (Node, Ctxt, Cont) ->
-%% Doc = case get_ann(Node) of
-%% [{label, L} | _] ->
-%% B = sets:is_element(L, Set),
-%% bf(Node, Ctxt, Cont, B);
-%% _ ->
-%% bf(Node, Ctxt, Cont, false)
-%% end,
-%% case type(Node) of
-%% cons -> color(Doc);
-%% tuple -> color(Doc);
-%% _ -> Doc
-%% end
-%% end,
-%% {ok, FD} = file:open("out.html",[write]),
-%% Txt = cerl_prettypr:format(T, [{hook, H},{user,false}]),
-%% io:put_chars(FD, "<pre>\n"),
-%% io:put_chars(FD, html(Txt)),
-%% io:put_chars(FD, "</pre>\n"),
-%% file:close(FD),
-%% {ok, Time1 - Time0}.
-
-%% test1(F) ->
-%% {T, _} = cerl_trees:label(user_default:read(F)),
-%% {Time0, _} = erlang:statistics(runtime),
-%% {T1, Esc, Vars} = annotate(T),
-%% {Time1, _} = erlang:statistics(runtime),
-%% io:fwrite("messages: ~p.\n", [Esc]),
-%% %%% io:fwrite("vars: ~p.\n", [[X || X <- dict:to_list(Vars)]]),
-%% T2 = hhl_transform:transform(T1, Vars),
-%% Set = sets:from_list(Esc),
-%% H = fun (Node, Ctxt, Cont) ->
-%% case get_ann(Node) of
-%% [{label, L} | _] ->
-%% B = sets:is_element(L, Set),
-%% bf(Node, Ctxt, Cont, B);
-%% _ ->
-%% bf(Node, Ctxt, Cont, false)
-%% end
-%% end,
-%% {ok, FD} = file:open("out.html",[write]),
-%% Txt = cerl_prettypr:format(T2, [{hook, H},{user,false}]),
-%% io:put_chars(FD, "<pre>\n"),
-%% io:put_chars(FD, html(Txt)),
-%% io:put_chars(FD, "</pre>\n"),
-%% file:close(FD),
-%% {ok, Time1 - Time0}.
-
-%% html(Cs) ->
-%% html(Cs, []).
-
-%% html([$#, $< | Cs], As) ->
-%% html_1(Cs, [$< | As]);
-%% html([$< | Cs], As) ->
-%% html(Cs, ";tl&" ++ As);
-%% html([$> | Cs], As) ->
-%% html(Cs, ";tg&" ++ As);
-%% html([$& | Cs], As) ->
-%% html(Cs, ";pma&" ++ As);
-%% html([C | Cs], As) ->
-%% html(Cs, [C | As]);
-%% html([], As) ->
-%% lists:reverse(As).
-
-%% html_1([$> | Cs], As) ->
-%% html(Cs, [$> | As]);
-%% html_1([C | Cs], As) ->
-%% html_1(Cs, [C | As]).
-
-%% bf(Node, Ctxt, Cont, B) ->
-%% B0 = cerl_prettypr:get_ctxt_user(Ctxt),
-%% if B /= B0 ->
-%% Ctxt1 = cerl_prettypr:set_ctxt_user(Ctxt, B),
-%% Doc = Cont(Node, Ctxt1),
-%% case B of
-%% true ->
-%% Start = "<b>",
-%% End = "</b>";
-%% false ->
-%% Start = "</b>",
-%% End = "<b>"
-%% end,
-%% markup(Doc, Start, End);
-%% true ->
-%% Cont(Node, Ctxt)
-%% end.
-
-%% color(Doc) ->
-%% % Doc.
-%% markup(Doc, "<font color=blue>", "</font>").
-
-%% markup(Doc, Start, End) ->
-%% prettypr:beside(
-%% prettypr:null_text([$# | Start]),
-%% prettypr:beside(Doc,
-%% prettypr:null_text([$# | End]))).
-
-
-%% =====================================================================
-%% annotate(Tree) -> {Tree1, Escapes, Vars}
-%%
-%% Tree = cerl:cerl()
-%%
-%% Analyzes `Tree' (see `analyze') and appends a term 'escapes', to
-%% the annotation list of each constructor expression node and of
-%% `Tree', corresponding to the escape information derived by the
-%% analysis. Any previous such annotations are removed from `Tree'.
-%% `Tree1' is the modified tree; for details on `OutList',
-%% `Outputs' , `Dependencies', `Escapes' and `Parents', see
-%% `analyze'.
-%%
-%% Note: `Tree' must be annotated with labels in order to use this
-%% function; see `analyze' for details.
-
--type label() :: integer() | 'external' | 'top'.
--type ordset(X) :: [X]. % XXX: TAKE ME OUT
-
--spec annotate(cerl:cerl()) -> {cerl:cerl(), ordset(label()), dict:dict()}.
-
-annotate(Tree) ->
- {Esc0, Vars} = analyze(Tree),
- Esc = sets:from_list(Esc0),
- F = fun (T) ->
- case type(T) of
- literal -> T;
-%%% var ->
-%%% L = get_label(T),
-%%% T1 = ann_escape(T, L, Esc),
-%%% X = dict:fetch(L, Vars),
-%%% set_ann(T1, append_ann({s,X}, get_ann(T1)));
- _ ->
- L = get_label(T),
- ann_escape(T, L, Esc)
- end
- end,
- {cerl_trees:map(F, Tree), Esc0, Vars}.
-
-ann_escape(T, L, Esc) ->
- case sets:is_element(L, Esc) of
- true ->
- set_ann(T, append_ann(escapes, get_ann(T)));
- false ->
- T
- end.
-
-append_ann(Tag, [X | Xs]) ->
- if tuple_size(X) >= 1, element(1, X) =:= Tag ->
- append_ann(Tag, Xs);
- true ->
- [X | append_ann(Tag, Xs)]
- end;
-append_ann(Tag, []) ->
- [Tag].
-
-
-%% =====================================================================
-%% analyze(Tree) -> Escapes
-%%
-%% Tree = cerl:cerl()
-%% Escapes = ordset(Label)
-%% Label = integer() | external | top
-%%
-%% Analyzes a module or an expression represented by `Tree'.
-%%
-%% `Escapes' is the set of labels of constructor expressions in
-%% `Tree' such that the created values may be accessed from outside
-%% `Tree'.
-%%
-%% Note: `Tree' must be annotated with labels (as done by the
-%% function `cerl_trees:label/1') in order to use this function.
-%% The label annotation `{label, L}' (where L should be an integer)
-%% must be the first element of the annotation list of each node in
-%% the tree. Instances of variables bound in `Tree' which denote
-%% the same variable must have the same label; apart from this,
-%% labels should be unique. Constant literals do not need to be
-%% labeled.
-
--record(state, {vars, out, dep, work, funs, k}).
-
-%% Note: We assume that all remote calls and primops return a single
-%% value.
-
-%% The analysis determines which objects (identified by the
-%% corresponding "cons-point" labels in the code) are likely to be
-%% passed in a message. (If so, we say that they "escape".) It is always
-%% safe to assume either case, because the send operation will assure
-%% that things are copied if necessary. This analysis tries to
-%% anticipate that copying will be done.
-%%
-%% Rules:
-%% 1) An object passed as message argument (or part of such an
-%% argument) to a known send-operation, will probably be a message.
-%% 2) A received value is always a message (safe).
-%% 3) The external function can return any object (unsafe).
-%% 4) A function called from the external function can receive any
-%% object (unsafe) as argument.
-%% 5) Unknown functions/operations can return any object (unsafe).
-
-%% We wrap the given syntax tree T in a fun-expression labeled `top',
-%% which is initially in the set of escaped labels. `top' will be
-%% visited at least once.
-%%
-%% We create a separate function labeled `external', defined as:
-%% "'external'/1 = fun () -> Any", which will represent any and all
-%% functions outside T, and which returns the 'unsafe' value.
-
-analyze(Tree) ->
- analyze(Tree, ?DEF_LIMIT).
-
-analyze(Tree, Limit) ->
- {_, _, Esc, Dep, _Par} = cerl_closurean:analyze(Tree),
-%%% io:fwrite("dependencies: ~w.\n", [dict:to_list(Dep)]),
- analyze(Tree, Limit, Dep, Esc).
-
-analyze(Tree, Limit, Dep0, Esc0) ->
- %% Note that we use different name spaces for variable labels and
- %% function/call site labels, so we can reuse some names here. We
- %% assume that the labeling of Tree only uses integers, not atoms.
- Any = ann_c_var([{label, any}], 'Any'),
- External = ann_c_var([{label, external}], {external, 1}),
- ExtFun = ann_c_fun([{label, external}], [], Any),
-%%% io:fwrite("external fun:\n~s.\n",
-%%% [cerl_prettypr:format(ExtFun, [noann, {paper, 80}])]),
- Top = ann_c_var([{label, top}], {top, 0}),
- TopFun = ann_c_fun([{label, top}], [], Tree),
-
- %% The "start fun" just makes the initialisation easier. It is not
- %% itself in the call graph.
- StartFun = ann_c_fun([{label, start}], [],
- c_letrec([{External, ExtFun}, {Top, TopFun}],
- c_nil())),
-%%% io:fwrite("start fun:\n~s.\n",
-%%% [cerl_prettypr:format(StartFun, [{paper, 80}])]),
-
- %% Initialise the Any and Escape variables. Gather a database of all
- %% fun-expressions in Tree and initialise their outputs and parameter
- %% variables. All escaping functions can receive any values as
- %% inputs. Bind all module- and letrec-defined variables to their
- %% corresponding labels.
- Esc = sets:from_list(Esc0),
- Unsafe = unsafe(),
- Empty = empty(),
- Funs0 = dict:new(),
- Vars0 = dict:store(escape, empty(),
- dict:store(any, Unsafe, dict:new())),
- Out0 = dict:new(),
- F = fun (T, S = {Fs, Vs, Os}) ->
- case type(T) of
- 'fun' ->
- L = get_label(T),
- As = fun_vars(T),
- X = case sets:is_element(L, Esc) of
- true -> Unsafe;
- false -> Empty
- end,
- {dict:store(L, T, Fs),
- bind_vars_single(As, X, Vs),
- dict:store(L, none, Os)};
- letrec ->
- {Fs, bind_defs(letrec_defs(T), Vs), Os};
- module ->
- {Fs, bind_defs(module_defs(T), Vs), Os};
- _ ->
- S
- end
- end,
- {Funs, Vars, Out} = cerl_trees:fold(F, {Funs0, Vars0, Out0}, StartFun),
-
- %% Add the dependency for the loop in 'external':
- Dep = add_dep(loop, external, Dep0),
-
- %% Enter the fixpoint iteration at the StartFun.
- St = loop(StartFun, start, #state{vars = Vars,
- out = Out,
- dep = Dep,
- work = init_work(),
- funs = Funs,
- k = Limit}),
- Ms = labels(dict:fetch(escape, St#state.vars)),
- {Ms, St#state.vars}.
-
-loop(T, L, St0) ->
-%%% io:fwrite("analyzing: ~w.\n",[L]),
-%%% io:fwrite("work: ~w.\n", [St0#state.work]),
- Xs0 = dict:fetch(L, St0#state.out),
- {Xs1, St1} = visit(fun_body(T), L, St0),
- Xs = limit(Xs1, St1#state.k),
- {W, M} = case equal(Xs0, Xs) of
- true ->
- {St1#state.work, St1#state.out};
- false ->
-%%% io:fwrite("out (~w) changed: ~w <- ~w.\n",
-%%% [L, Xs, Xs0]),
- M1 = dict:store(L, Xs, St1#state.out),
- case dict:find(L, St1#state.dep) of
- {ok, S} ->
- {add_work(set__to_list(S), St1#state.work),
- M1};
- error ->
- {St1#state.work, M1}
- end
- end,
- St2 = St1#state{out = M},
- case take_work(W) of
- {ok, L1, W1} ->
- T1 = dict:fetch(L1, St2#state.funs),
- loop(T1, L1, St2#state{work = W1});
- none ->
- St2
- end.
-
-visit(T, L, St) ->
-%%% io:fwrite("visiting: ~w.\n",[type(T)]),
- case type(T) of
- literal ->
- %% This is (or should be) a constant, even if it's compound,
- %% so it's bugger all whether it is sent or not.
- case cerl:concrete(T) of
- [] -> {[empty()], St};
- X when is_atom(X) -> {[empty()], St};
- X when is_integer(X) -> {[empty()], St};
- X when is_float(X) -> {[empty()], St};
- _ ->
- exit({not_literal, T})
- end;
- var ->
- %% If a variable is not already in the store here, it must
- %% be free in the program.
- L1 = get_label(T),
- Vars = St#state.vars,
- case dict:find(L1, Vars) of
- {ok, X} ->
- {[X], St};
- error ->
-%%% io:fwrite("free var: ~w.\n",[L1]),
- X = unsafe(),
- St1 = St#state{vars = dict:store(L1, X, Vars)},
- {[X], St1}
- end;
- 'fun' ->
- %% Must revisit the fun also, because its environment might
- %% have changed. (We don't keep track of such dependencies.)
- L1 = get_label(T),
- St1 = St#state{work = add_work([L1], St#state.work)},
- %% Currently, lambda expressions can only be locally
- %% allocated, and therefore we have to force copying by
- %% treating them as "unsafe" for now.
- {[unsafe()], St1};
- %% {[singleton(L1)], St1};
- values ->
- visit_list(values_es(T), L, St);
- cons ->
- {[X1, X2], St1} = visit_list([cons_hd(T), cons_tl(T)], L, St),
- L1 = get_label(T),
- X = make_cons(L1, X1, X2),
- %% Also store the values of the elements.
- Hd = get_hd(X),
- Tl = get_tl(X),
- St2 = St1#state{vars = dict:store(L1, [Hd, Tl], St1#state.vars)},
- {[X], St2};
- tuple ->
- {Xs, St1} = visit_list(tuple_es(T), L, St),
- L1 = get_label(T),
- %% Also store the values of the elements.
- St2 = St1#state{vars = dict:store(L1, Xs, St1#state.vars)},
- {[struct(L1, Xs)], St2};
- 'let' ->
- {Xs, St1} = visit(let_arg(T), L, St),
- Vars = bind_vars(let_vars(T), Xs, St1#state.vars),
- visit(let_body(T), L, St1#state{vars = Vars});
- seq ->
- {_, St1} = visit(seq_arg(T), L, St),
- visit(seq_body(T), L, St1);
- apply ->
- {_F, St1} = visit(apply_op(T), L, St),
- {As, St2} = visit_list(apply_args(T), L, St1),
- L1 = get_label(T),
- Ls = get_deps(L1, St#state.dep),
- Out = St2#state.out,
- Xs1 = join_list([dict:fetch(X, Out) || X <- Ls]),
- {Xs1, call_site(Ls, As, St2)};
- call ->
- M = call_module(T),
- F = call_name(T),
- As = call_args(T),
- {_, St1} = visit(M, L, St),
- {_, St2} = visit(F, L, St1),
- {Xs, St3} = visit_list(As, L, St2),
- L1 = get_label(T),
- remote_call(M, F, Xs, As, L1, St3);
- primop ->
- As = primop_args(T),
- {Xs, St1} = visit_list(As, L, St),
- F = atom_val(primop_name(T)),
- primop_call(F, length(Xs), Xs, As, St1);
- 'case' ->
- {Xs, St1} = visit(case_arg(T), L, St),
- visit_clauses(Xs, case_clauses(T), L, St1);
- 'receive' ->
- %% The received value is of course a message, so it
- %% is 'empty()', not 'unsafe()'.
- X = empty(),
- {Xs1, St1} = visit_clauses([X], receive_clauses(T), L, St),
- {_, St2} = visit(receive_timeout(T), L, St1),
- {Xs2, St3} = visit(receive_action(T), L, St2),
- {join(Xs1, Xs2), St3};
- 'try' ->
- {Xs1, St1} = visit(try_arg(T), L, St),
- X = unsafe(),
- Vars = bind_vars(try_vars(T), Xs1, St1#state.vars),
- {Xs2, St2} = visit(try_body(T), L, St1#state{vars = Vars}),
- EVars = bind_vars(try_evars(T), [X, X, X], St2#state.vars),
- {Xs3, St3} = visit(try_handler(T), L, St2#state{vars = EVars}),
- {join(Xs2, Xs3), St3};
- 'catch' ->
- %% If we catch an exception, we can get unsafe data.
- {Xs, St1} = visit(catch_body(T), L, St),
- {join([unsafe()], Xs), St1};
- binary ->
- %% Binaries are heap objects, but we don't have special
- %% shared-heap allocation operators for them at the moment.
- %% They must therefore be treated as unsafe.
- {_, St1} = visit_list(binary_segments(T), L, St),
- {[unsafe()], St1};
- bitstr ->
- %% The other fields are constant literals.
- {_, St1} = visit(bitstr_val(T), L, St),
- {_, St2} = visit(bitstr_size(T), L, St1),
- {none, St2};
- letrec ->
- %% All the bound funs should be revisited, because the
- %% environment might have changed.
- Ls = [get_label(F) || {_, F} <- letrec_defs(T)],
- St1 = St#state{work = add_work(Ls, St#state.work)},
- visit(letrec_body(T), L, St1);
- module ->
- %% We regard a module as a tuple of function variables in
- %% the body of a `letrec'.
- visit(c_letrec(module_defs(T),
- ann_c_tuple([{label, get_label(T)}],
- module_exports(T))),
- L, St)
- end.
-
-visit_clause(T, Xs, L, St) ->
- Vars = bind_pats(clause_pats(T), Xs, St#state.vars),
- {_, St1} = visit(clause_guard(T), L, St#state{vars = Vars}),
- visit(clause_body(T), L, St1).
-
-%% We assume correct value-list typing.
-
-visit_list([T | Ts], L, St) ->
- {Xs, St1} = visit(T, L, St),
- {Xs1, St2} = visit_list(Ts, L, St1),
- X = case Xs of
- [X1] -> X1;
- _ -> empty()
- end,
- {[X | Xs1], St2};
-visit_list([], _L, St) ->
- {[], St}.
-
-visit_clauses(Xs, [T | Ts], L, St) ->
- {Xs1, St1} = visit_clause(T, Xs, L, St),
- {Xs2, St2} = visit_clauses(Xs, Ts, L, St1),
- {join(Xs1, Xs2), St2};
-visit_clauses(_, [], _L, St) ->
- {none, St}.
-
-bind_defs([{V, F} | Ds], Vars) ->
- bind_defs(Ds, dict:store(get_label(V), singleton(get_label(F)), Vars));
-bind_defs([], Vars) ->
- Vars.
-
-bind_pats(Ps, none, Vars) ->
- bind_pats_single(Ps, empty(), Vars);
-bind_pats(Ps, Xs, Vars) ->
- if length(Xs) =:= length(Ps) ->
- bind_pats_list(Ps, Xs, Vars);
- true ->
- bind_pats_single(Ps, empty(), Vars)
- end.
-
-%% The lists might not be of the same length.
-
-bind_pats_list([P | Ps], [X | Xs], Vars) ->
- bind_pats_list(Ps, Xs, bind_pat_vars(P, X, Vars));
-bind_pats_list(Ps, [], Vars) ->
- bind_pats_single(Ps, empty(), Vars);
-bind_pats_list([], _, Vars) ->
- Vars.
-
-bind_pats_single([P | Ps], X, Vars) ->
- bind_pats_single(Ps, X, bind_pat_vars(P, X, Vars));
-bind_pats_single([], _X, Vars) ->
- Vars.
-
-bind_pat_vars(P, X, Vars) ->
- case type(P) of
- var ->
- dict:store(get_label(P), X, Vars);
- literal ->
- Vars;
- cons ->
- bind_pats_list([cons_hd(P), cons_tl(P)],
- [get_hd(X), get_tl(X)], Vars);
- tuple ->
- case elements(X) of
- none ->
- bind_vars_single(pat_vars(P), X, Vars);
- Xs ->
- bind_pats_list(tuple_es(P), Xs, Vars)
- end;
- binary ->
- %% See the handling of binary-expressions.
- bind_pats_single(binary_segments(P), unsafe(), Vars);
- bitstr ->
- %% See the handling of binary-expressions.
- bind_pats_single([bitstr_val(P), bitstr_size(P)],
- unsafe(), Vars);
- alias ->
- P1 = alias_pat(P),
- Vars1 = bind_pat_vars(P1, X, Vars),
- dict:store(get_label(alias_var(P)), X, Vars1)
- end.
-
-%%% %% This is the "exact" version of list representation, which simply
-%%% %% mimics the actual cons, head and tail operations.
-%%% make_cons(L, X1, X2) ->
-%%% struct(L1, [X1, X2]).
-%%% get_hd(X) ->
-%%% case elements(X) of
-%%% none -> X;
-%%% [X1 | _] -> X1;
-%%% _ -> empty()
-%%% end.
-%%% get_tl(X) ->
-%%% case elements(X) of
-%%% none -> X;
-%%% [_, X2 | _] -> X2;
-%%% _ -> empty()
-%%% end.
-
-%% This version does not unnecessarily confuse spine labels with element
-%% labels, and is safe. However, it loses precision if cons cells are
-%% used for other things than proper lists.
-
-make_cons(L, X1, X2) ->
- %% join subtypes and cons locations
- join_single(struct(L, [X1]), X2).
-
-get_hd(X) ->
- case elements(X) of
- none -> X;
- [X1 | _] -> X1; % First element represents list subtype.
- _ -> empty()
- end.
-
-get_tl(X) -> X. % Tail of X has same type as X.
-
-bind_vars(Vs, none, Vars) ->
- bind_vars_single(Vs, empty(), Vars);
-bind_vars(Vs, Xs, Vars) ->
- if length(Vs) =:= length(Xs) ->
- bind_vars_list(Vs, Xs, Vars);
- true ->
- bind_vars_single(Vs, empty(), Vars)
- end.
-
-bind_vars_list([V | Vs], [X | Xs], Vars) ->
- bind_vars_list(Vs, Xs, dict:store(get_label(V), X, Vars));
-bind_vars_list([], [], Vars) ->
- Vars.
-
-bind_vars_single([V | Vs], X, Vars) ->
- bind_vars_single(Vs, X, dict:store(get_label(V), X, Vars));
-bind_vars_single([], _X, Vars) ->
- Vars.
-
-%% This handles a call site, updating parameter variables with respect
-%% to the actual parameters. The 'external' function is handled
-%% specially, since it can get an arbitrary number of arguments. For our
-%% purposes here, calls to the external function can be ignored.
-
-call_site(Ls, Xs, St) ->
-%%% io:fwrite("call site: ~w -> ~w (~w).\n", [L, Ls, Xs]),
- {W, V} = call_site(Ls, Xs, St#state.work, St#state.vars,
- St#state.funs, St#state.k),
- St#state{work = W, vars = V}.
-
-call_site([external | Ls], Xs, W, V, Fs, Limit) ->
- call_site(Ls, Xs, W, V, Fs, Limit);
-call_site([L | Ls], Xs, W, V, Fs, Limit) ->
- Vs = fun_vars(dict:fetch(L, Fs)),
- case bind_args(Vs, Xs, V, Limit) of
- {V1, true} ->
- call_site(Ls, Xs, add_work([L], W), V1, Fs, Limit);
- {V1, false} ->
- call_site(Ls, Xs, W, V1, Fs, Limit)
- end;
-call_site([], _, W, V, _, _) ->
- {W, V}.
-
-add_dep(Source, Target, Deps) ->
- case dict:find(Source, Deps) of
- {ok, X} ->
- case set__is_member(Target, X) of
- true ->
- Deps;
- false ->
-%%% io:fwrite("new dep: ~w <- ~w.\n", [Target, Source]),
- dict:store(Source, set__add(Target, X), Deps)
- end;
- error ->
-%%% io:fwrite("new dep: ~w <- ~w.\n", [Target, Source]),
- dict:store(Source, set__singleton(Target), Deps)
- end.
-
-%% If the arity does not match the call, nothing is done here.
-
-bind_args(Vs, Xs, Vars, Limit) ->
- if length(Vs) =:= length(Xs) ->
- bind_args(Vs, Xs, Vars, Limit, false);
- true ->
- {Vars, false}
- end.
-
-bind_args([V | Vs], [X | Xs], Vars, Limit, Ch) ->
- L = get_label(V),
- {Vars1, Ch1} = bind_arg(L, X, Vars, Limit, Ch),
- bind_args(Vs, Xs, Vars1, Limit, Ch1);
-bind_args([], [], Vars, _Limit, Ch) ->
- {Vars, Ch}.
-
-%% bind_arg(L, X, Vars, Limit) ->
-%% bind_arg(L, X, Vars, Limit, false).
-
-bind_arg(L, X, Vars, Limit, Ch) ->
- X0 = dict:fetch(L, Vars),
- X1 = limit_single(join_single(X, X0), Limit),
- case equal_single(X0, X1) of
- true ->
- {Vars, Ch};
- false ->
-%%% io:fwrite("arg (~w) changed: ~w <- ~w + ~w.\n",
-%%% [L, X1, X0, X]),
- {dict:store(L, X1, Vars), true}
- end.
-
-%% This handles escapes from things like primops and remote calls.
-
-escape(Xs, Ns, St) ->
- escape(Xs, Ns, 1, St).
-
-escape([_ | Xs], Ns=[N1 | _], N, St) when is_integer(N1), N1 > N ->
- escape(Xs, Ns, N + 1, St);
-escape([X | Xs], [N | Ns], N, St) ->
- Vars = St#state.vars,
- X0 = dict:fetch(escape, Vars),
- X1 = join_single(X, X0),
- case equal_single(X0, X1) of
- true ->
- escape(Xs, Ns, N + 1, St);
- false ->
-%%% io:fwrite("escape changed: ~w <- ~w + ~w.\n", [X1, X0, X]),
- Vars1 = dict:store(escape, X1, Vars),
- escape(Xs, Ns, N + 1, St#state{vars = Vars1})
- end;
-escape(Xs, [_ | Ns], N, St) ->
- escape(Xs, Ns, N + 1, St);
-escape(_, _, _, St) ->
- St.
-
-%% Handle primop calls: (At present, we assume that all unknown calls
-%% yield exactly one value. This might have to be changed.)
-
-primop_call(F, A, Xs, _As, St0) ->
- %% St1 = case is_escape_op(F, A) of
- %% [] -> St0;
- %% Ns -> escape(Xs, Ns, St0)
- %% end,
- St1 = St0,
- case is_imm_op(F, A) of
- true ->
- {[empty()], St1};
- false ->
- call_unknown(Xs, St1)
- end.
-
-%% Handle remote-calls: (At present, we assume that all unknown calls
-%% yield exactly one value. This might have to be changed.)
-
-remote_call(M, F, Xs, As, L, St) ->
- case is_c_atom(M) andalso is_c_atom(F) of
- true ->
- remote_call_1(atom_val(M), atom_val(F), length(Xs),
- Xs, As, L, St);
- false ->
- %% Unknown function
- call_unknown(Xs, St)
- end.
-
-%% When calling an unknown function, we assume that the result does
-%% *not* contain any of the constructors in its arguments (but it could
-%% return locally allocated data that we don't know about). Note that
-%% even a "pure" function can still cons up new data.
-
-call_unknown(_Xs, St) ->
- {[unsafe()], St}.
-
-%% We need to handle some important standard functions in order to get
-%% decent precision.
-%% TODO: foldl, map, mapfoldl
-
-remote_call_1(erlang, hd, 1, [X], _As, _L, St) ->
- {[get_hd(X)], St};
-remote_call_1(erlang, tl, 1, [X], _As, _L, St) ->
- {[get_tl(X)], St};
-remote_call_1(erlang, element, 2, [_,X], [N|_], _L, St) ->
- case elements(X) of
- none -> {[X], St};
- Xs ->
- case is_c_int(N) of
- true ->
- N1 = int_val(N),
- if is_integer(N1), 1 =< N1, N1 =< length(Xs) ->
- {[nth(N1, Xs)], St};
- true ->
- {none, St}
- end;
- false ->
- %% Even if we don't know which element is selected,
- %% we know that the top level is never part of the
- %% returned value.
- {[join_single_list(Xs)], St}
- end
- end;
-remote_call_1(erlang, setelement, 3, [_,X, Y], [N|_], L, St) ->
- %% The constructor gets the label of the call operation.
- case elements(X) of
- none -> {[join_single(singleton(L), join_single(X, Y))], St};
- Xs ->
- case is_c_int(N) of
- true ->
- N1 = int_val(N),
- if is_integer(N1), 1 =< N1, N1 =< length(Xs) ->
- Xs1 = set_nth(N1, Y, Xs),
- {[struct(L, Xs1)], St};
- true ->
- {none, St}
- end;
- false ->
- %% Even if we don't know which element is selected,
- %% we know that the top level is never part of the
- %% returned value (a new tuple is always created).
- Xs1 = [join_single(Y, X1) || X1 <- Xs],
- {[struct(L, Xs1)], St}
- end
- end;
-remote_call_1(erlang, '++', 2, [X1,X2], _As, _L, St) ->
- %% Note: this is unsafe for non-proper lists! (See make_cons/3).
- %% No safe version is implemented.
- {[join_single(X1, X2)], St};
-remote_call_1(erlang, '--', 2, [X1,_X2], _As, _L, St) ->
- {[X1], St};
-remote_call_1(lists, append, 2, Xs, As, L, St) ->
- remote_call_1(erlang, '++', 2, Xs, As, L, St);
-remote_call_1(lists, subtract, 2, Xs, As, L, St) ->
- remote_call_1(erlang, '--', 2, Xs, As, L, St);
-remote_call_1(M, F, A, Xs, _As, _L, St0) ->
- St1 = case is_escape_op(M, F, A) of
- [] -> St0;
- Ns -> escape(Xs, Ns, St0)
- end,
- case is_imm_op(M, F, A) of
- true ->
- {[empty()], St1};
- false ->
- call_unknown(Xs, St1)
- end.
-
-%% 1-based n:th-element list selector and update function.
-
-nth(1, [X | _Xs]) -> X;
-nth(N, [_X | Xs]) when N > 1 -> nth(N - 1, Xs).
-
-set_nth(1, Y, [_X | Xs]) -> [Y | Xs];
-set_nth(N, Y, [X | Xs]) when N > 1 -> [X | set_nth(N - 1, Y, Xs)].
-
-%% Domain: none | [V], where V = {S, none} | {S, [V]}, S = set(integer()).
-
-join(none, Xs2) -> Xs2;
-join(Xs1, none) -> Xs1;
-join(Xs1, Xs2) ->
- if length(Xs1) =:= length(Xs2) ->
- join_1(Xs1, Xs2);
- true ->
- none
- end.
-
-join_1([X1 | Xs1], [X2 | Xs2]) ->
- [join_single(X1, X2) | join_1(Xs1, Xs2)];
-join_1([], []) ->
- [].
-
-join_list([Xs | Xss]) ->
- join(Xs, join_list(Xss));
-join_list([]) ->
- none.
-
-empty() -> {set__new(), []}.
-
-singleton(X) -> {set__singleton(X), []}.
-
-struct(X, Xs) -> {set__singleton(X), Xs}.
-
-elements({_, Xs}) -> Xs.
-
-unsafe() -> {set__singleton(unsafe), none}.
-
-equal(none, none) -> true;
-equal(none, _) -> false;
-equal(_, none) -> false;
-equal(X1, X2) -> equal_1(X1, X2).
-
-equal_1([X1 | Xs1], [X2 | Xs2]) ->
- equal_single(X1, X2) andalso equal_1(Xs1, Xs2);
-equal_1([], []) -> true;
-equal_1(_, _) -> false.
-
-equal_single({S1, none}, {S2, none}) ->
- set__equal(S1, S2);
-equal_single({_, none}, _) ->
- false;
-equal_single(_, {_, none}) ->
- false;
-equal_single({S1, Vs1}, {S2, Vs2}) ->
- set__equal(S1, S2) andalso equal_single_lists(Vs1, Vs2).
-
-equal_single_lists([X1 | Xs1], [X2 | Xs2]) ->
- equal_single(X1, X2) andalso equal_single_lists(Xs1, Xs2);
-equal_single_lists([], []) ->
- true;
-equal_single_lists(_, _) ->
- false.
-
-join_single({S, none}, V) ->
- {set__union(S, labels(V)), none};
-join_single(V, {S, none}) ->
- {set__union(S, labels(V)), none};
-join_single({S1, Vs1}, {S2, Vs2}) ->
- {set__union(S1, S2), join_single_lists(Vs1, Vs2)}.
-
-join_single_list([V | Vs]) ->
- join_single(V, join_single_list(Vs));
-join_single_list([]) ->
- empty().
-
-%% If one list has more elements that the other, and N is the length of
-%% the longer list, then the result has N elements.
-
-join_single_lists([V1], [V2]) ->
- [join_single(V1, V2)];
-join_single_lists([V1 | Vs1], [V2 | Vs2]) ->
- [join_single(V1, V2) | join_single_lists(Vs1, Vs2)];
-join_single_lists([], Vs) -> Vs;
-join_single_lists(Vs, []) -> Vs.
-
-collapse(V) ->
- {labels(V), none}.
-
-%% collapse_list([]) ->
-%% empty();
-%% collapse_list(Vs) ->
-%% {labels_list(Vs), none}.
-
-labels({S, none}) -> S;
-labels({S, []}) -> S;
-labels({S, Vs}) -> set__union(S, labels_list(Vs)).
-
-labels_list([V]) ->
- labels(V);
-labels_list([V | Vs]) ->
- set__union(labels(V), labels_list(Vs)).
-
-limit(none, _K) -> none;
-limit(X, K) -> limit_list(X, K).
-
-limit_list([X | Xs], K) ->
- [limit_single(X, K) | limit_list(Xs, K)];
-limit_list([], _) ->
- [].
-
-limit_single({_, none} = V, _K) ->
- V;
-limit_single({_, []} = V, _K) ->
- V;
-limit_single({S, Vs}, K) when K > 0 ->
- {S, limit_list(Vs, K - 1)};
-limit_single(V, _K) ->
- collapse(V).
-
-%% Set abstraction for label sets in the domain.
-
-%% set__is_empty([]) -> true;
-%% set__is_empty(_) -> false.
-
-set__new() -> [].
-
-set__singleton(X) -> [X].
-
-set__to_list(S) -> S.
-
-%% set__from_list(S) -> ordsets:from_list(S).
-
-set__union(X, Y) -> ordsets:union(X, Y).
-
-set__add(X, S) -> ordsets:add_element(X, S).
-
-set__is_member(X, S) -> ordsets:is_element(X, S).
-
-%% set__subtract(X, Y) -> ordsets:subtract(X, Y).
-
-set__equal(X, Y) -> X =:= Y.
-
-%% A simple but efficient functional queue.
-
-queue__new() -> {[], []}.
-
-queue__put(X, {In, Out}) -> {[X | In], Out}.
-
-queue__get({In, [X | Out]}) -> {ok, X, {In, Out}};
-queue__get({[], _}) -> empty;
-queue__get({In, _}) ->
- [X | In1] = lists:reverse(In),
- {ok, X, {[], In1}}.
-
-%% The work list - a queue without repeated elements.
-
-init_work() ->
- {queue__new(), sets:new()}.
-
-add_work(Ls, {Q, Set}) ->
- add_work(Ls, Q, Set).
-
-%% Note that the elements are enqueued in order.
-
-add_work([L | Ls], Q, Set) ->
- case sets:is_element(L, Set) of
- true ->
- add_work(Ls, Q, Set);
- false ->
- add_work(Ls, queue__put(L, Q), sets:add_element(L, Set))
- end;
-add_work([], Q, Set) ->
- {Q, Set}.
-
-take_work({Queue0, Set0}) ->
- case queue__get(Queue0) of
- {ok, L, Queue1} ->
- Set1 = sets:del_element(L, Set0),
- {ok, L, {Queue1, Set1}};
- empty ->
- none
- end.
-
-get_deps(L, Dep) ->
- case dict:find(L, Dep) of
- {ok, Ls} -> Ls;
- error -> []
- end.
-
-%% Escape operators may let their arguments escape. For this analysis,
-%% only send-operations are considered as causing escapement, and only
-%% in specific arguments.
-
-%% is_escape_op(_F, _A) -> [].
-
--spec is_escape_op(atom(), atom(), arity()) -> [arity()].
-
-is_escape_op(erlang, '!', 2) -> [2];
-is_escape_op(erlang, send, 2) -> [2];
-is_escape_op(erlang, spawn, 1) -> [1];
-is_escape_op(erlang, spawn, 3) -> [3];
-is_escape_op(erlang, spawn, 4) -> [4];
-is_escape_op(erlang, spawn_link, 3) -> [3];
-is_escape_op(erlang, spawn_link, 4) -> [4];
-is_escape_op(_M, _F, _A) -> [].
-
-%% "Immediate" operators will never return heap allocated data. This is
-%% of course true for operators that never return, like 'exit/1'. (Note
-%% that floats are always heap allocated objects, and that most integer
-%% arithmetic can return a bignum on the heap.)
-
--spec is_imm_op(atom(), arity()) -> boolean().
-
-is_imm_op(match_fail, 1) -> true;
-is_imm_op(_, _) -> false.
-
--spec is_imm_op(atom(), atom(), arity()) -> boolean().
-
-is_imm_op(erlang, self, 0) -> true;
-is_imm_op(erlang, '=:=', 2) -> true;
-is_imm_op(erlang, '==', 2) -> true;
-is_imm_op(erlang, '=/=', 2) -> true;
-is_imm_op(erlang, '/=', 2) -> true;
-is_imm_op(erlang, '<', 2) -> true;
-is_imm_op(erlang, '=<', 2) -> true;
-is_imm_op(erlang, '>', 2) -> true;
-is_imm_op(erlang, '>=', 2) -> true;
-is_imm_op(erlang, 'and', 2) -> true;
-is_imm_op(erlang, 'or', 2) -> true;
-is_imm_op(erlang, 'xor', 2) -> true;
-is_imm_op(erlang, 'not', 1) -> true;
-is_imm_op(erlang, is_alive, 0) -> true;
-is_imm_op(erlang, is_atom, 1) -> true;
-is_imm_op(erlang, is_binary, 1) -> true;
-is_imm_op(erlang, is_builtin, 3) -> true;
-is_imm_op(erlang, is_float, 1) -> true;
-is_imm_op(erlang, is_function, 1) -> true;
-is_imm_op(erlang, is_integer, 1) -> true;
-is_imm_op(erlang, is_list, 1) -> true;
-is_imm_op(erlang, is_number, 1) -> true;
-is_imm_op(erlang, is_pid, 1) -> true;
-is_imm_op(erlang, is_port, 1) -> true;
-is_imm_op(erlang, is_process_alive, 1) -> true;
-is_imm_op(erlang, is_reference, 1) -> true;
-is_imm_op(erlang, is_tuple, 1) -> true;
-is_imm_op(erlang, length, 1) -> true; % never a bignum
-is_imm_op(erlang, list_to_atom, 1) -> true;
-is_imm_op(erlang, node, 0) -> true;
-is_imm_op(erlang, node, 1) -> true;
-is_imm_op(erlang, throw, 1) -> true;
-is_imm_op(erlang, exit, 1) -> true;
-is_imm_op(erlang, error, 1) -> true;
-is_imm_op(erlang, error, 2) -> true;
-is_imm_op(_M, _F, _A) -> false.
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl
index a3a936322a..48ce641ab9 100644
--- a/lib/hipe/cerl/erl_bif_types.erl
+++ b/lib/hipe/cerl/erl_bif_types.erl
@@ -585,6 +585,13 @@ type(erlang, float, 1, Xs, Opaques) ->
%% Guard bif, needs to be here.
type(erlang, floor, 1, Xs, Opaques) ->
strict(erlang, floor, 1, Xs, fun (_) -> t_integer() end, Opaques);
+%% Primop, needs to be somewhere.
+type(erlang, build_stacktrace, 0, _, _Opaques) ->
+ t_list(t_tuple([t_module(),
+ t_atom(),
+ t_sup([t_arity(),t_list()]),
+ t_list(t_sup([t_tuple([t_atom('file'),t_string()]),
+ t_tuple([t_atom('line'),t_pos_integer()])]))]));
%% Guard bif, needs to be here.
type(erlang, hd, 1, Xs, Opaques) ->
strict(erlang, hd, 1, Xs, fun ([X]) -> t_cons_hd(X) end, Opaques);
@@ -658,6 +665,8 @@ type(erlang, is_map, 1, Xs, Opaques) ->
check_guard(X, fun (Y) -> t_is_map(Y, Opaques) end,
t_map(), Opaques) end,
strict(erlang, is_map, 1, Xs, Fun, Opaques);
+type(erlang, is_map_key, 2, Xs, Opaques) ->
+ type(maps, is_key, 2, Xs, Opaques);
type(erlang, is_number, 1, Xs, Opaques) ->
Fun = fun (X) ->
check_guard(X, fun (Y) -> t_is_number(Y, Opaques) end,
@@ -763,6 +772,9 @@ type(erlang, length, 1, Xs, Opaques) ->
%% Guard bif, needs to be here.
type(erlang, map_size, 1, Xs, Opaques) ->
type(maps, size, 1, Xs, Opaques);
+%% Guard bif, needs to be here.
+type(erlang, map_get, 2, Xs, Opaques) ->
+ type(maps, get, 2, Xs, Opaques);
type(erlang, make_fun, 3, Xs, Opaques) ->
strict(erlang, make_fun, 3, Xs,
fun ([_, _, Arity]) ->
@@ -1701,24 +1713,6 @@ type(maps, size, 1, Xs, Opaques) ->
t_from_range(LowerBound, UpperBound)
end
end, Opaques);
-type(maps, to_list, 1, Xs, Opaques) ->
- strict(maps, to_list, 1, Xs,
- fun ([Map]) ->
- DefK = t_map_def_key(Map, Opaques),
- DefV = t_map_def_val(Map, Opaques),
- Pairs = t_map_entries(Map, Opaques),
- EType = lists:foldl(
- fun({K,_,V},EType0) ->
- case t_is_none(V) of
- true -> t_subtract(EType0, t_tuple([K,t_any()]));
- false -> t_sup(EType0, t_tuple([K,V]))
- end
- end, t_tuple([DefK, DefV]), Pairs),
- case t_is_none(EType) of
- true -> t_nil();
- false -> t_list(EType)
- end
- end, Opaques);
type(maps, update, 3, Xs, Opaques) ->
strict(maps, update, 3, Xs,
fun ([Key, Value, Map]) ->
@@ -1903,7 +1897,8 @@ infinity_div(Number1, Number2) when is_integer(Number1), is_integer(Number2) ->
infinity_bsl(pos_inf, _) -> pos_inf;
infinity_bsl(neg_inf, _) -> neg_inf;
-infinity_bsl(Number, pos_inf) when is_integer(Number), Number >= 0 -> pos_inf;
+infinity_bsl(0, pos_inf) -> 0;
+infinity_bsl(Number, pos_inf) when is_integer(Number), Number > 0 -> pos_inf;
infinity_bsl(Number, pos_inf) when is_integer(Number) -> neg_inf;
infinity_bsl(Number, neg_inf) when is_integer(Number), Number >= 0 -> 0;
infinity_bsl(Number, neg_inf) when is_integer(Number) -> -1;
@@ -1992,9 +1987,11 @@ arith_abs(X1, Opaques) ->
case infinity_geq(Min1, 0) of
true -> {Min1, Max1};
false ->
+ NegMin1 = infinity_inv(Min1),
+ NegMax1 = infinity_inv(Max1),
case infinity_geq(Max1, 0) of
- true -> {0, infinity_inv(Min1)};
- false -> {infinity_inv(Max1), infinity_inv(Min1)}
+ true -> {0, max(NegMin1, Max1)};
+ false -> {NegMax1, NegMin1}
end
end,
t_from_range(NewMin, NewMax)
@@ -2351,6 +2348,9 @@ arg_types(erlang, float, 1) ->
%% Guard bif, needs to be here.
arg_types(erlang, floor, 1) ->
[t_number()];
+%% Primop, needs to be somewhere.
+arg_types(erlang, build_stacktrace, 0) ->
+ [];
%% Guard bif, needs to be here.
arg_types(erlang, hd, 1) ->
[t_cons()];
@@ -2376,6 +2376,8 @@ arg_types(erlang, is_list, 1) ->
[t_any()];
arg_types(erlang, is_map, 1) ->
[t_any()];
+arg_types(erlang, is_map_key, 2) ->
+ [t_any(), t_map()];
arg_types(erlang, is_number, 1) ->
[t_any()];
arg_types(erlang, is_pid, 1) ->
@@ -2396,6 +2398,9 @@ arg_types(erlang, length, 1) ->
%% Guard bif, needs to be here.
arg_types(erlang, map_size, 1) ->
[t_map()];
+%% Guard bif, needs to be here.
+arg_types(erlang, map_get, 2) ->
+ [t_any(), t_map()];
arg_types(erlang, make_fun, 3) ->
[t_atom(), t_atom(), t_arity()];
arg_types(erlang, make_tuple, 2) ->
@@ -2648,8 +2653,6 @@ arg_types(maps, put, 3) ->
[t_any(), t_any(), t_map()];
arg_types(maps, size, 1) ->
[t_map()];
-arg_types(maps, to_list, 1) ->
- [t_map()];
arg_types(maps, update, 3) ->
[t_any(), t_any(), t_map()];
arg_types(M, F, A) when is_atom(M), is_atom(F),
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index 0883a69918..9abb4d31d9 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -74,6 +74,7 @@
t_form_to_string/1,
t_from_form/6,
t_from_form_without_remote/3,
+ t_from_form_check_remote/4,
t_check_record_fields/6,
t_from_range/2,
t_from_range_unsafe/2,
@@ -107,13 +108,14 @@
t_is_bitstr/1, t_is_bitstr/2,
t_is_bitwidth/1,
t_is_boolean/1, t_is_boolean/2,
- %% t_is_byte/1,
- %% t_is_char/1,
+ t_is_byte/1,
+ t_is_char/1,
t_is_cons/1, t_is_cons/2,
t_is_equal/2,
t_is_fixnum/1,
t_is_float/1, t_is_float/2,
t_is_fun/1, t_is_fun/2,
+ t_is_identifier/1,
t_is_instance/2,
t_is_integer/1, t_is_integer/2,
t_is_list/1,
@@ -215,18 +217,7 @@
cache__new/0
]).
-%%-define(DO_ERL_TYPES_TEST, true).
--compile({no_auto_import,[min/2,max/2]}).
-
--ifdef(DO_ERL_TYPES_TEST).
--export([test/0]).
--else.
--define(NO_UNUSED, true).
--endif.
-
--ifndef(NO_UNUSED).
--export([t_is_identifier/1]).
--endif.
+-compile({no_auto_import,[min/2,max/2,map_get/2]}).
-export_type([erl_type/0, opaques/0, type_table/0,
var_table/0, cache/0]).
@@ -1189,12 +1180,10 @@ is_fun(_) -> false.
t_identifier() ->
?identifier(?any).
--ifdef(DO_ERL_TYPES_TEST).
--spec t_is_identifier(erl_type()) -> erl_type().
+-spec t_is_identifier(erl_type()) -> boolean().
t_is_identifier(?identifier(_)) -> true;
t_is_identifier(_) -> false.
--endif.
%%------------------------------------
@@ -1365,7 +1354,6 @@ is_integer1(_) -> false.
t_byte() ->
?byte.
--ifdef(DO_ERL_TYPES_TEST).
-spec t_is_byte(erl_type()) -> boolean().
t_is_byte(?int_range(neg_inf, _)) -> false;
@@ -1375,7 +1363,6 @@ t_is_byte(?int_range(From, To))
t_is_byte(?int_set(Set)) ->
(set_min(Set) >= 0) andalso (set_max(Set) =< ?MAX_BYTE);
t_is_byte(_) -> false.
--endif.
%%------------------------------------
@@ -1629,8 +1616,8 @@ lift_list_to_pos_empty(?list(Content, Termination, _)) ->
%% * The keys in Pairs are singleton types.
%% * The values of Pairs must not be unit, and may only be none if the
%% mandatoriness tag is 'optional'.
-%% * Optional must contain no pair {K,V} s.t. K is a subtype of DefaultKey and
-%% V is equal to DefaultKey.
+%% * There is no pair {K, 'optional', V} in Pairs s.t.
+%% K is a subtype of DefaultKey and V is equal to DefaultValue.
%% * DefaultKey must be the empty type iff DefaultValue is the empty type.
%% * DefaultKey must not be a singleton type.
%% * For every key K in Pairs, DefaultKey - K must not be representable; i.e.
@@ -1876,6 +1863,7 @@ t_map_put(KV, Map, Opaques) ->
%% Key and Value are *not* unopaqued, but the map is
map_put(_, ?none, _) -> ?none;
+map_put(_, ?unit, _) -> ?none;
map_put({Key, Value}, ?map(Pairs,DefK,DefV), Opaques) ->
case t_is_none_or_unit(Key) orelse t_is_none_or_unit(Value) of
true -> ?none;
@@ -1901,6 +1889,7 @@ t_map_update(KV, Map) ->
-spec t_map_update({erl_type(), erl_type()}, erl_type(), opaques()) -> erl_type().
t_map_update(_, ?none, _) -> ?none;
+t_map_update(_, ?unit, _) -> ?none;
t_map_update(KV={Key, _}, M, Opaques) ->
case t_is_subtype(t_atom('true'), t_map_is_key(Key, M, Opaques)) of
false -> ?none;
@@ -1921,6 +1910,7 @@ t_map_get(Key, Map, Opaques) ->
end).
map_get(_, ?none) -> ?none;
+map_get(_, ?unit) -> ?none;
map_get(Key, ?map(Pairs, DefK, DefV)) ->
DefRes =
case t_do_overlap(DefK, Key) of
@@ -1956,6 +1946,7 @@ t_map_is_key(Key, Map, Opaques) ->
end).
map_is_key(_, ?none) -> ?none;
+map_is_key(_, ?unit) -> ?none;
map_is_key(Key, ?map(Pairs, DefK, _DefV)) ->
case is_singleton_type(Key) of
true ->
@@ -2346,6 +2337,8 @@ t_from_range(X, Y) ->
-else.
+t_from_range(pos_inf, pos_inf) -> ?integer_pos;
+t_from_range(neg_inf, neg_inf) -> ?integer_neg;
t_from_range(neg_inf, pos_inf) -> t_integer();
t_from_range(neg_inf, Y) when is_integer(Y), Y < 0 -> ?integer_neg;
t_from_range(neg_inf, Y) when is_integer(Y), Y >= 0 -> t_integer();
@@ -2378,6 +2371,8 @@ t_from_range(pos_inf, neg_inf) -> t_none().
-spec t_from_range_unsafe(rng_elem(), rng_elem()) -> erl_type().
+t_from_range_unsafe(pos_inf, pos_inf) -> ?integer_pos;
+t_from_range_unsafe(neg_inf, neg_inf) -> ?integer_neg;
t_from_range_unsafe(neg_inf, pos_inf) -> t_integer();
t_from_range_unsafe(neg_inf, Y) -> ?int_range(neg_inf, Y);
t_from_range_unsafe(X, pos_inf) -> ?int_range(X, pos_inf);
@@ -4248,13 +4243,13 @@ t_to_string(?identifier(Set), _RecDict) ->
case Set of
?any -> "identifier()";
_ ->
- string:join([flat_format("~w()", [T]) || T <- set_to_list(Set)], " | ")
+ flat_join([flat_format("~w()", [T]) || T <- set_to_list(Set)], " | ")
end;
t_to_string(?opaque(Set), RecDict) ->
- string:join([opaque_type(Mod, Name, Args, S, RecDict) ||
- #opaque{mod = Mod, name = Name, struct = S, args = Args}
- <- set_to_list(Set)],
- " | ");
+ flat_join([opaque_type(Mod, Name, Args, S, RecDict) ||
+ #opaque{mod = Mod, name = Name, struct = S, args = Args}
+ <- set_to_list(Set)],
+ " | ");
t_to_string(?matchstate(Pres, Slots), RecDict) ->
flat_format("ms(~ts,~ts)", [t_to_string(Pres, RecDict),
t_to_string(Slots,RecDict)]);
@@ -4345,9 +4340,9 @@ t_to_string(?map(Pairs0,DefK,DefV), RecDict) ->
end end,
StrMand = [{Tos(K),Tos(V)}||{K,?mand,V}<-Pairs],
StrOpt = [{Tos(K),Tos(V)}||{K,?opt,V}<-Pairs],
- "#{" ++ string:join([K ++ ":=" ++ V||{K,V}<-StrMand]
- ++ [K ++ "=>" ++ V||{K,V}<-StrOpt]
- ++ ExtraEl, ", ") ++ "}";
+ "#{" ++ flat_join([K ++ ":=" ++ V||{K,V}<-StrMand]
+ ++ [K ++ "=>" ++ V||{K,V}<-StrOpt]
+ ++ ExtraEl, ", ") ++ "}";
t_to_string(?tuple(?any, ?any, ?any), _RecDict) -> "tuple()";
t_to_string(?tuple(Elements, _Arity, ?any), RecDict) ->
"{" ++ comma_sequence(Elements, RecDict) ++ "}";
@@ -4370,7 +4365,7 @@ t_to_string(?var(Id), _RecDict) when is_integer(Id) ->
record_to_string(Tag, [_|Fields], FieldNames, RecDict) ->
FieldStrings = record_fields_to_string(Fields, FieldNames, RecDict, []),
- "#" ++ atom_to_string(Tag) ++ "{" ++ string:join(FieldStrings, ",") ++ "}".
+ "#" ++ atom_to_string(Tag) ++ "{" ++ flat_join(FieldStrings, ",") ++ "}".
record_fields_to_string([F|Fs], [{FName, _Abstr, DefType}|FDefs],
RecDict, Acc) ->
@@ -4396,7 +4391,7 @@ record_field_diffs_to_string(?tuple([_|Fs], Arity, Tag), RecDict) ->
{ok, FieldNames} = lookup_record(TagAtom, Arity-1, RecDict),
%% io:format("RecCElems = ~p\nRecTypes = ~p\n", [Fs, FieldNames]),
FieldDiffs = field_diffs(Fs, FieldNames, RecDict, []),
- string:join(FieldDiffs, " and ").
+ flat_join(FieldDiffs, " and ").
field_diffs([F|Fs], [{FName, _Abstr, DefType}|FDefs], RecDict, Acc) ->
%% Don't care about opacity for now.
@@ -4416,11 +4411,11 @@ comma_sequence(Types, RecDict) ->
true -> "_";
false -> t_to_string(T, RecDict)
end || T <- Types],
- string:join(List, ",").
+ flat_join(List, ",").
union_sequence(Types, RecDict) ->
List = [t_to_string(T, RecDict) || T <- Types],
- string:join(List, " | ").
+ flat_join(List, " | ").
-ifdef(DEBUG).
opaque_type(Mod, Name, _Args, S, RecDict) ->
@@ -4471,7 +4466,7 @@ t_from_form(Form, ExpTypes, Site, RecDict, VarTab, Cache) ->
%% Replace external types with with none().
-spec t_from_form_without_remote(parse_form(), site(), type_table()) ->
- {erl_type(), cache()}.
+ erl_type().
t_from_form_without_remote(Form, Site, TypeTable) ->
Module = site_module(Site),
@@ -4480,38 +4475,57 @@ t_from_form_without_remote(Form, Site, TypeTable) ->
VarTab = var_table__new(),
Cache0 = cache__new(),
Cache = Cache0#cache{mod_recs = {mrecs, ModRecs}},
- t_from_form1(Form, ExpTypes, Site, undefined, VarTab, Cache).
-
-%% REC_TYPE_LIMIT is used for limiting the depth of recursive types.
-%% EXPAND_LIMIT is used for limiting the size of types by
-%% limiting the number of elements of lists within one type form.
-%% EXPAND_DEPTH is used in conjunction with EXPAND_LIMIT to make the
-%% types balanced (unions will otherwise collapse to any()) by limiting
-%% the depth the same way as t_limit/2 does.
+ {Type, _} = t_from_form1(Form, ExpTypes, Site, undefined, VarTab, Cache),
+ Type.
-type expand_limit() :: integer().
-type expand_depth() :: integer().
--record(from_form, {site :: site(),
+-record(from_form, {site :: site() | {'check', mta()},
xtypes :: sets:set(mfa()) | 'replace_by_none',
mrecs :: 'undefined' | mod_type_table(),
vtab :: var_table(),
tnames :: type_names()}).
+-spec t_from_form_check_remote(parse_form(), sets:set(mfa()), mta(),
+ mod_type_table()) -> 'ok'.
+t_from_form_check_remote(Form, ExpTypes, MTA, RecDict) ->
+ State = #from_form{site = {check, MTA},
+ xtypes = ExpTypes,
+ mrecs = RecDict,
+ vtab = var_table__new(),
+ tnames = []},
+ D = (1 bsl 25), % unlimited
+ L = (1 bsl 25),
+ Cache0 = cache__new(),
+ _ = t_from_form2(Form, State, D, L, Cache0),
+ ok.
+
+%% REC_TYPE_LIMIT is used for limiting the depth of recursive types.
+%% EXPAND_LIMIT is used for limiting the size of types by
+%% limiting the number of elements of lists within one type form.
+%% EXPAND_DEPTH is used in conjunction with EXPAND_LIMIT to make the
+%% types balanced (unions will otherwise collapse to any()) by limiting
+%% the depth the same way as t_limit/2 does.
+
-spec t_from_form1(parse_form(), sets:set(mfa()) | 'replace_by_none',
site(), 'undefined' | mod_type_table(), var_table(),
cache()) -> {erl_type(), cache()}.
t_from_form1(Form, ET, Site, MR, V, C) ->
TypeNames = initial_typenames(Site),
+ D = ?EXPAND_DEPTH,
+ L = ?EXPAND_LIMIT,
State = #from_form{site = Site,
xtypes = ET,
mrecs = MR,
vtab = V,
tnames = TypeNames},
- L = ?EXPAND_LIMIT,
- {T0, L0, C0} = from_form(Form, State, ?EXPAND_DEPTH, L, C),
+ t_from_form2(Form, State, D, L, C).
+
+t_from_form2(Form, State, D, L, C) ->
+ {T0, L0, C0} = from_form(Form, State, D, L, C),
if
L0 =< 0 ->
{T1, _, C1} = from_form(Form, State, 1, L, C0),
@@ -4655,7 +4669,8 @@ from_form({type, _L, map, List}, S, D0, L, C) ->
end
end(List, L, C),
try
- {Pairs, DefK, DefV} = map_from_form(Pairs1, [], [], [], ?none, ?none),
+ Pairs2 = singleton_elements(Pairs1),
+ {Pairs, DefK, DefV} = map_from_form(Pairs2, [], [], [], ?none, ?none),
{t_map(Pairs, DefK, DefV), L5, C5}
catch none -> {t_none(), L5, C5}
end;
@@ -4767,14 +4782,18 @@ type_from_form(Name, Args, S, D, L, C) ->
case can_unfold_more(TypeName, TypeNames) of
true ->
{R, C1} = lookup_module_types(Module, MR, C),
- type_from_form1(Name, Args, ArgsLen, R, TypeName, TypeNames,
+ type_from_form1(Name, Args, ArgsLen, R, TypeName, TypeNames, Site,
S, D, L, C1);
false ->
{t_any(), L, C}
end.
-type_from_form1(Name, Args, ArgsLen, R, TypeName, TypeNames, S, D, L, C) ->
+type_from_form1(Name, Args, ArgsLen, R, TypeName, TypeNames, Site,
+ S, D, L, C) ->
case lookup_type(Name, ArgsLen, R) of
+ {_, {_, _}} when element(1, Site) =:= check ->
+ {_ArgTypes, L1, C1} = list_from_form(Args, S, D, L, C),
+ {t_any(), L1, C1};
{Tag, {{Module, _FileName, Form, ArgNames}, Type}} ->
NewTypeNames = [TypeName|TypeNames],
S1 = S#from_form{tnames = NewTypeNames},
@@ -4813,7 +4832,7 @@ type_from_form1(Name, Args, ArgsLen, R, TypeName, TypeNames, S, D, L, C) ->
end.
remote_from_form(RemMod, Name, Args, S, D, L, C) ->
- #from_form{xtypes = ET, mrecs = MR, tnames = TypeNames} = S,
+ #from_form{site = Site, xtypes = ET, mrecs = MR, tnames = TypeNames} = S,
if
ET =:= replace_by_none ->
{t_none(), L, C};
@@ -4831,7 +4850,7 @@ remote_from_form(RemMod, Name, Args, S, D, L, C) ->
case can_unfold_more(RemType, TypeNames) of
true ->
remote_from_form1(RemMod, Name, Args, ArgsLen, RemDict,
- RemType, TypeNames, S, D, L, C1);
+ RemType, TypeNames, Site, S, D, L, C1);
false ->
{t_any(), L, C1}
end;
@@ -4843,14 +4862,16 @@ remote_from_form(RemMod, Name, Args, S, D, L, C) ->
end.
remote_from_form1(RemMod, Name, Args, ArgsLen, RemDict, RemType, TypeNames,
- S, D, L, C) ->
+ Site, S, D, L, C) ->
case lookup_type(Name, ArgsLen, RemDict) of
+ {_, {_, _}} when element(1, Site) =:= check ->
+ {_ArgTypes, L1, C1} = list_from_form(Args, S, D, L, C),
+ {t_any(), L1, C1};
{Tag, {{Mod, _FileLine, Form, ArgNames}, Type}} ->
NewTypeNames = [RemType|TypeNames],
S1 = S#from_form{tnames = NewTypeNames},
{ArgTypes, L1, C1} = list_from_form(Args, S1, D, L, C),
CKey = cache_key(RemMod, Name, ArgTypes, TypeNames, D),
- %% case error of
case cache_find(CKey, C) of
{CachedType, DeltaL} ->
{CachedType, L - DeltaL, C};
@@ -4914,6 +4935,8 @@ record_from_form({atom, _, Name}, ModFields, S, D0, L0, C) ->
M = site_module(Site),
{R, C1} = lookup_module_types(M, MR, C),
case lookup_record(Name, R) of
+ {ok, _} when element(1, Site) =:= check ->
+ {t_any(), L0, C1};
{ok, DeclFields} ->
NewTypeNames = [RecordType|TypeNames],
Site1 = {record, {M, Name, length(DeclFields)}},
@@ -4998,6 +5021,30 @@ list_from_form([H|Tail], S, D, L, C) ->
{T1, L2, C2} = list_from_form(Tail, S, D, L1, C1),
{[H1|T1], L2, C2}.
+%% Separates singleton types in keys (see is_singleton_type/1).
+singleton_elements([]) ->
+ [];
+singleton_elements([{K,?mand,V}=Pair|Pairs]) ->
+ case is_singleton_type(K) of
+ true ->
+ [Pair|singleton_elements(Pairs)];
+ false ->
+ singleton_elements([{K,?opt,V}|Pairs])
+ end;
+singleton_elements([{Key0,MNess,Val}|Pairs]) ->
+ [{Key,MNess,Val} || Key <- separate_key(Key0)] ++ singleton_elements(Pairs).
+
+%% To be in sync with is_singleton_type/1.
+%% Does not separate tuples and maps as doing that has potential
+%% to be very expensive.
+separate_key(?atom(Atoms)) when Atoms =/= ?any ->
+ [t_atom(A) || A <- Atoms];
+separate_key(?number(_, _) = T) ->
+ t_elements(T);
+separate_key(?union(List)) ->
+ lists:append([separate_key(K) || K <- List, not t_is_none(K)]);
+separate_key(Key) -> [Key].
+
%% Sorts, combines non-singleton pairs, and applies precendence and
%% mandatoriness rules.
map_from_form([], ShdwPs, MKs, Pairs, DefK, DefV) ->
@@ -5208,7 +5255,7 @@ t_form_to_string({ann_type, _L, [Var, Type]}) ->
t_form_to_string({paren_type, _L, [Type]}) ->
flat_format("(~ts)", [t_form_to_string(Type)]);
t_form_to_string({remote_type, _L, [{atom, _, Mod}, {atom, _, Name}, Args]}) ->
- ArgString = "(" ++ string:join(t_form_to_string_list(Args), ",") ++ ")",
+ ArgString = "(" ++ flat_join(t_form_to_string_list(Args), ",") ++ ")",
flat_format("~w:~tw", [Mod, Name]) ++ ArgString;
t_form_to_string({type, _L, arity, []}) -> "arity()";
t_form_to_string({type, _L, binary, []}) -> "binary()";
@@ -5231,7 +5278,7 @@ t_form_to_string({type, _L, 'fun', []}) -> "fun()";
t_form_to_string({type, _L, 'fun', [{type, _, any}, Range]}) ->
"fun(...) -> " ++ t_form_to_string(Range);
t_form_to_string({type, _L, 'fun', [{type, _, product, Domain}, Range]}) ->
- "fun((" ++ string:join(t_form_to_string_list(Domain), ",") ++ ") -> "
+ "fun((" ++ flat_join(t_form_to_string_list(Domain), ",") ++ ") -> "
++ t_form_to_string(Range) ++ ")";
t_form_to_string({type, _L, iodata, []}) -> "iodata()";
t_form_to_string({type, _L, iolist, []}) -> "iolist()";
@@ -5239,7 +5286,7 @@ t_form_to_string({type, _L, list, [Type]}) ->
"[" ++ t_form_to_string(Type) ++ "]";
t_form_to_string({type, _L, map, any}) -> "map()";
t_form_to_string({type, _L, map, Args}) ->
- "#{" ++ string:join(t_form_to_string_list(Args), ",") ++ "}";
+ "#{" ++ flat_join(t_form_to_string_list(Args), ",") ++ "}";
t_form_to_string({type, _L, map_field_assoc, [Key, Val]}) ->
t_form_to_string(Key) ++ "=>" ++ t_form_to_string(Val);
t_form_to_string({type, _L, map_field_exact, [Key, Val]}) ->
@@ -5251,7 +5298,7 @@ t_form_to_string({type, _L, nonempty_list, [Type]}) ->
"[" ++ t_form_to_string(Type) ++ ",...]";
t_form_to_string({type, _L, nonempty_string, []}) -> "nonempty_string()";
t_form_to_string({type, _L, product, Elements}) ->
- "<" ++ string:join(t_form_to_string_list(Elements), ",") ++ ">";
+ "<" ++ flat_join(t_form_to_string_list(Elements), ",") ++ ">";
t_form_to_string({type, _L, range, [From, To]} = Type) ->
case {erl_eval:partial_eval(From), erl_eval:partial_eval(To)} of
{{integer, _, FromVal}, {integer, _, ToVal}} ->
@@ -5261,7 +5308,7 @@ t_form_to_string({type, _L, range, [From, To]} = Type) ->
t_form_to_string({type, _L, record, [{atom, _, Name}]}) ->
flat_format("#~tw{}", [Name]);
t_form_to_string({type, _L, record, [{atom, _, Name}|Fields]}) ->
- FieldString = string:join(t_form_to_string_list(Fields), ","),
+ FieldString = flat_join(t_form_to_string_list(Fields), ","),
flat_format("#~tw{~ts}", [Name, FieldString]);
t_form_to_string({type, _L, field_type, [{atom, _, Name}, Type]}) ->
flat_format("~tw::~ts", [Name, t_form_to_string(Type)]);
@@ -5269,9 +5316,9 @@ t_form_to_string({type, _L, term, []}) -> "term()";
t_form_to_string({type, _L, timeout, []}) -> "timeout()";
t_form_to_string({type, _L, tuple, any}) -> "tuple()";
t_form_to_string({type, _L, tuple, Args}) ->
- "{" ++ string:join(t_form_to_string_list(Args), ",") ++ "}";
+ "{" ++ flat_join(t_form_to_string_list(Args), ",") ++ "}";
t_form_to_string({type, _L, union, Args}) ->
- string:join(t_form_to_string_list(Args), " | ");
+ flat_join(t_form_to_string_list(Args), " | ");
t_form_to_string({type, _L, Name, []} = T) ->
try
M = mod,
@@ -5289,7 +5336,7 @@ t_form_to_string({type, _L, Name, []} = T) ->
end;
t_form_to_string({user_type, _L, Name, List}) ->
flat_format("~tw(~ts)",
- [Name, string:join(t_form_to_string_list(List), ",")]);
+ [Name, flat_join(t_form_to_string_list(List), ",")]);
t_form_to_string({type, L, Name, List}) ->
%% Compatibility: modules compiled before Erlang/OTP 18.0.
t_form_to_string({user_type, L, Name, List}).
@@ -5447,7 +5494,8 @@ t_is_singleton(Type) ->
t_is_singleton(Type, Opaques) ->
do_opaque(Type, Opaques, fun is_singleton_type/1).
-%% Incomplete; not all representable singleton types are included.
+%% To be in sync with separate_key/1.
+%% Used to also recognize maps and tuples.
is_singleton_type(?nil) -> true;
is_singleton_type(?atom(?any)) -> false;
is_singleton_type(?atom(Set)) ->
@@ -5455,13 +5503,6 @@ is_singleton_type(?atom(Set)) ->
is_singleton_type(?int_range(V, V)) -> true;
is_singleton_type(?int_set(Set)) ->
ordsets:size(Set) =:= 1;
-is_singleton_type(?tuple(Types, Arity, _)) when is_integer(Arity) ->
- lists:all(fun is_singleton_type/1, Types);
-is_singleton_type(?tuple_set([{Arity, [OnlyTuple]}])) when is_integer(Arity) ->
- is_singleton_type(OnlyTuple);
-is_singleton_type(?map(Pairs, ?none, ?none)) ->
- lists:all(fun({_,MNess,V}) -> MNess =:= ?mand andalso is_singleton_type(V)
- end, Pairs);
is_singleton_type(_) ->
false.
@@ -5556,7 +5597,7 @@ set_to_string(Set) ->
true -> io_lib:write_string(atom_to_list(X), $'); % stupid emacs '
false -> flat_format("~tw", [X])
end || X <- set_to_list(Set)],
- string:join(L, " | ").
+ flat_join(L, " | ").
set_min([H|_]) -> H.
@@ -5566,6 +5607,9 @@ set_max(Set) ->
flat_format(F, S) ->
lists:flatten(io_lib:format(F, S)).
+flat_join(List, Sep) ->
+ lists:flatten(lists:join(Sep, List)).
+
%%=============================================================================
%%
%% Utilities for the binary type
@@ -5635,173 +5679,3 @@ family(L) ->
var_table__new() ->
maps:new().
-
-%%=============================================================================
-%% Consistency-testing function(s) below
-%%=============================================================================
-
--ifdef(DO_ERL_TYPES_TEST).
-
-test() ->
- Atom1 = t_atom(),
- Atom2 = t_atom(foo),
- Atom3 = t_atom(bar),
- true = t_is_atom(Atom2),
-
- True = t_atom(true),
- False = t_atom(false),
- Bool = t_boolean(),
- true = t_is_boolean(True),
- true = t_is_boolean(Bool),
- false = t_is_boolean(Atom1),
-
- Binary = t_binary(),
- true = t_is_binary(Binary),
-
- Bitstr = t_bitstr(),
- true = t_is_bitstr(Bitstr),
-
- Bitstr1 = t_bitstr(7, 3),
- true = t_is_bitstr(Bitstr1),
- false = t_is_binary(Bitstr1),
-
- Bitstr2 = t_bitstr(16, 8),
- true = t_is_bitstr(Bitstr2),
- true = t_is_binary(Bitstr2),
-
- ?bitstr(8, 16) = t_subtract(t_bitstr(4, 12), t_bitstr(8, 12)),
- ?bitstr(8, 16) = t_subtract(t_bitstr(4, 12), t_bitstr(8, 12)),
-
- Int1 = t_integer(),
- Int2 = t_integer(1),
- Int3 = t_integer(16#ffffffff),
- true = t_is_integer(Int2),
- true = t_is_byte(Int2),
- false = t_is_byte(Int3),
- false = t_is_byte(t_from_range(-1, 1)),
- true = t_is_byte(t_from_range(1, ?MAX_BYTE)),
-
- Tuple1 = t_tuple(),
- Tuple2 = t_tuple(3),
- Tuple3 = t_tuple([Atom1, Int1]),
- Tuple4 = t_tuple([Tuple1, Tuple2]),
- Tuple5 = t_tuple([Tuple3, Tuple4]),
- Tuple6 = t_limit(Tuple5, 2),
- Tuple7 = t_limit(Tuple5, 3),
- true = t_is_tuple(Tuple1),
-
- Port = t_port(),
- Pid = t_pid(),
- Ref = t_reference(),
- Identifier = t_identifier(),
- false = t_is_reference(Port),
- true = t_is_identifier(Port),
-
- Function1 = t_fun(),
- Function2 = t_fun(Pid),
- Function3 = t_fun([], Pid),
- Function4 = t_fun([Port, Pid], Pid),
- Function5 = t_fun([Pid, Atom1], Int2),
- true = t_is_fun(Function3),
-
- List1 = t_list(),
- List2 = t_list(t_boolean()),
- List3 = t_cons(t_boolean(), List2),
- List4 = t_cons(t_boolean(), t_atom()),
- List5 = t_cons(t_boolean(), t_nil()),
- List6 = t_cons_tl(List5),
- List7 = t_sup(List4, List5),
- List8 = t_inf(List7, t_list()),
- List9 = t_cons(),
- List10 = t_cons_tl(List9),
- true = t_is_boolean(t_cons_hd(List5)),
- true = t_is_list(List5),
- false = t_is_list(List4),
-
- Product1 = t_product([Atom1, Atom2]),
- Product2 = t_product([Atom3, Atom1]),
- Product3 = t_product([Atom3, Atom2]),
-
- Union1 = t_sup(Atom2, Atom3),
- Union2 = t_sup(Tuple2, Tuple3),
- Union3 = t_sup(Int2, Atom3),
- Union4 = t_sup(Port, Pid),
- Union5 = t_sup(Union4, Int1),
- Union6 = t_sup(Function1, Function2),
- Union7 = t_sup(Function4, Function5),
- Union8 = t_sup(True, False),
- true = t_is_boolean(Union8),
- Union9 = t_sup(Int2, t_integer(2)),
- true = t_is_byte(Union9),
- Union10 = t_sup(t_tuple([t_atom(true), ?any]),
- t_tuple([t_atom(false), ?any])),
-
- ?any = t_sup(Product3, Function5),
-
- Atom3 = t_inf(Union3, Atom1),
- Union2 = t_inf(Union2, Tuple1),
- Int2 = t_inf(Int1, Union3),
- Union4 = t_inf(Union4, Identifier),
- Port = t_inf(Union5, Port),
- Function4 = t_inf(Union7, Function4),
- ?none = t_inf(Product2, Atom1),
- Product3 = t_inf(Product1, Product2),
- Function5 = t_inf(Union7, Function5),
- true = t_is_byte(t_inf(Union9, t_number())),
- true = t_is_char(t_inf(Union9, t_number())),
-
- io:format("3? ~p ~n", [?int_set([3])]),
-
- RecDict = dict:store({foo, 2}, [bar, baz], dict:new()),
- Record1 = t_from_term({foo, [1,2], {1,2,3}}),
-
- Types = [
- Atom1,
- Atom2,
- Atom3,
- Binary,
- Int1,
- Int2,
- Tuple1,
- Tuple2,
- Tuple3,
- Tuple4,
- Tuple5,
- Tuple6,
- Tuple7,
- Ref,
- Port,
- Pid,
- Identifier,
- List1,
- List2,
- List3,
- List4,
- List5,
- List6,
- List7,
- List8,
- List9,
- List10,
- Function1,
- Function2,
- Function3,
- Function4,
- Function5,
- Product1,
- Product2,
- Record1,
- Union1,
- Union2,
- Union3,
- Union4,
- Union5,
- Union6,
- Union7,
- Union8,
- Union10,
- t_inf(Union10, t_tuple([t_atom(true), t_integer()]))
- ],
- io:format("~p\n", [[t_to_string(X, RecDict) || X <- Types]]).
-
--endif.
diff --git a/lib/hipe/doc/src/Makefile b/lib/hipe/doc/src/Makefile
index a5edb80381..104c15f2bb 100644
--- a/lib/hipe/doc/src/Makefile
+++ b/lib/hipe/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2006-2016. All Rights Reserved.
+# Copyright Ericsson AB 2006-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -36,9 +36,9 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# Target Specs
# ----------------------------------------------------
XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES =
+XML_REF3_FILES =
-XML_PART_FILES = part_notes.xml
+XML_PART_FILES = hipe_app.xml
XML_CHAPTER_FILES = notes.xml
BOOK_FILES = book.xml
@@ -47,7 +47,7 @@ XML_FILES = \
$(BOOK_FILES) $(XML_CHAPTER_FILES) \
$(XML_PART_FILES) $(XML_REF3_FILES) $(XML_APPLICATION_FILES)
-GIF_FILES =
+GIF_FILES =
# ----------------------------------------------------
@@ -68,9 +68,9 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
+XML_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -90,20 +90,21 @@ man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-debug opt:
+debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
+ rm -f errs core *~
distclean: clean
realclean: clean
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
diff --git a/lib/hipe/doc/src/fascicules.xml b/lib/hipe/doc/src/fascicules.xml
deleted file mode 100644
index b15610fa8b..0000000000
--- a/lib/hipe/doc/src/fascicules.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="yes">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/hipe/doc/src/hipe_app.xml b/lib/hipe/doc/src/hipe_app.xml
index e489d155c3..63bc6ea2d7 100644
--- a/lib/hipe/doc/src/hipe_app.xml
+++ b/lib/hipe/doc/src/hipe_app.xml
@@ -4,7 +4,7 @@
<appref>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -35,6 +35,14 @@
<app>HiPE</app>
<appsummary>The HiPE Application</appsummary>
<description>
+ <note>
+ <p>
+ HiPE and execution of HiPE compiled code only have limited support by
+ the OTP team at Ericsson. The OTP team only does limited maintenance
+ of HiPE and does not actively develop HiPE. HiPE is mainly supported
+ by the HiPE team at Uppsala University.
+ </p>
+ </note>
<p>
The normal way to native-compile an Erlang module using HiPE is to include the atom native
in the Erlang compiler options, as in:</p>
@@ -47,6 +55,130 @@
Details on HiPE compiler options are given by <c>hipe:help_options()</c>.</p>
</description>
<section>
+ <title>Feature Limitations</title>
+ <p>
+ The HiPE compiler is in general compliant with the normal BEAM compiler,
+ with respect to semantic behavior. There are however features in the BEAM compiler
+ and the runtime system that have limited or no support for HiPE compiled modules.
+ </p>
+ <taglist>
+ <tag>Stack traces</tag>
+ <item><p>Stack traces returned from <seealso marker="erts:erlang#get_stacktrace/0">
+ <c>erlang:get_stacktrace/0</c></seealso> or as part of <c>'EXIT'</c> terms
+ can look incomplete if HiPE compiled functions are involved. Typically a stack trace
+ will contain only BEAM compiled functions or only HiPE compiled functions, depending
+ on where the exception was raised.</p>
+ <p>Source code line numbers in stack traces are also not supported by HiPE compiled functions.</p>
+ </item>
+
+ <tag>Tracing</tag>
+ <item><p>Erlang call trace is not supported by HiPE. Calling
+ <seealso marker="erts:erlang#trace_pattern/3"><c>erlang:trace_pattern({M,F,A}, ...)</c></seealso>
+ does not have any effect on HiPE compiled modules.</p>
+ </item>
+
+ <tag>NIFs</tag>
+ <item><p>Modules compiled with HiPE can not call <seealso marker="erts:erlang#load_nif-2">
+ <c>erlang:load_nif/2</c></seealso> to load NIFs.</p>
+ </item>
+
+ <tag>-on_load</tag>
+ <item><p>Modules compiled with HiPE can not use
+ <seealso marker="doc/reference_manual:code_loading#on_load"><c>-on_load()</c></seealso>
+ directives.</p>
+ </item>
+ </taglist>
+
+ </section>
+ <section>
+ <title>Performance Limitations</title>
+ <p>
+ The HiPE compiler does in general produce faster code than the
+ BEAM compiler. There are however some situation when HiPE
+ compiled code will perform worse than BEAM code.
+ </p>
+ <taglist>
+ <tag>Mode switches</tag>
+ <item><p>Every time a process changes from executing code in a
+ HiPE compiled module to a BEAM compiled module (or vice versa),
+ it will do a mode switch. This involves a certain amount of
+ CPU overhead which can have a negative net impact if the
+ process is switching back and forth without getting enough done in
+ each mode.</p>
+ </item>
+
+ <tag>Optimization for <c>receive</c> with unique references</tag>
+ <item>
+ <p>
+ The BEAM compiler can do an optimization when a receive
+ statement is only waiting for messages containing a reference
+ created before the receive. All messages that existed in the
+ queue when the reference was created will be bypassed, as they
+ cannot possibly contain the reference. HiPE currently has an
+ optimization similar this, but it is not guaranteed to
+ bypass all messages. In the worst case scenario, it cannot
+ bypass any messages at all.
+ </p>
+ <p>
+ An example of this is when <c>gen_server:call()</c> waits for
+ the reply message.
+ </p>
+ </item>
+
+ <tag>Garbage collection after BIFs</tag>
+ <item>
+ <p>
+ The condition for determining whether a garbage collection
+ is needed or not has changed in later releases. HiPE has not
+ been updated regarding this which may cause premature garbage
+ collections after BIF calls.
+ </p>
+ </item>
+
+ </taglist>
+ </section>
+ <section>
+ <title>Stability Issues</title>
+ <taglist>
+ <tag>Not checking reduction count on function returns</tag>
+ <item>
+ <p>
+ BEAM checks the reduction count and schedules out the executing
+ process if needed both when calling a function and when returning
+ from a function call that was not called using a tail call.
+ HiPE only checks the reduction count when calling a function.
+ </p>
+ <p>
+ The runtime system might need to schedule out a process
+ in order to reclaim memory. If the process isn't scheduled
+ out soon after the process has entered this state, memory
+ consumption will quickly grow. Maintaining this state is also
+ quite expensive performance wise.
+ </p>
+ <p>
+ Processes executing code that performs large recursions and
+ produce data after returning from recursive calls may have to
+ be scheduled out when returning from a function call. Since
+ HiPE does not check reductions on returns, processes executing
+ such HiPE compiled code may cause huge peeks in memory
+ consumption as well as severe performance degradation.
+ </p>
+ </item>
+
+ <tag>Not bumping appropriate amount of reductions in <c>receive</c> statements</tag>
+ <item>
+ <p>
+ The process signaling improvements made in ERTS version
+ 10.0 moved potentially significant amounts of work into the
+ receive statement from other places. In order to account for
+ this work, the reduction count should be bumped on the
+ executing process. Reductions are not bumped when entering
+ the <c>receive</c> statement from HiPE compiled code.
+ </p>
+ </item>
+ </taglist>
+ </section>
+ <section>
<title>SEE ALSO</title>
<p>
<seealso marker="stdlib:c">c(3)</seealso>,
diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml
index 9167d0aaec..d9f58382bc 100644
--- a/lib/hipe/doc/src/notes.xml
+++ b/lib/hipe/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2006</year><year>2017</year>
+ <year>2006</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,167 @@
</header>
<p>This document describes the changes made to HiPE.</p>
+<section><title>Hipe 3.18.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Hipe 3.18</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Optimize <c>receive</c> statements that are only waiting
+ for messages containing a reference created before the
+ receive. All messages that existed in the queue when the
+ reference was created will be bypassed, as they cannot
+ possibly contain the reference. This optimization has
+ existed for vanilla BEAM since OTP R14.</p>
+ <p>
+ Own Id: OTP-14785 Aux Id: PR-1632 </p>
+ </item>
+ <item>
+ <p>
+ Add validation pass to hipe compiler to detect internal
+ errors causing primop calls that may trigger an unsafe GC
+ at run-time. The pass can be disabled with option
+ <c>no_verify_gcsafe</c>.</p>
+ <p>
+ Own Id: OTP-14900 Aux Id: PR-1685, PR-1621 </p>
+ </item>
+ <item>
+ <p>
+ Make hipe compiled code work on x86_64 (amd64) with OS
+ security feature PIE, where executable code can be loaded
+ into a random location. Old behavior, if hipe was
+ enabled, was to disable PIE build options for the VM.</p>
+ <p>
+ Own Id: OTP-14903</p>
+ </item>
+ <item>
+ <p>
+ Inline more type test BIFs; <c>is_number</c>,
+ <c>is_bitstring</c>, <c>is_map</c>.</p>
+ <p>
+ Own Id: OTP-14941 Aux Id: PR-1718 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Hipe 3.17.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix HiPE bug for binary constructs like
+ <c>&lt;&lt;X/utf8&gt;&gt;</c> which could in rare cases
+ cause faulty results or VM crash.</p>
+ <p>
+ This fix affects both the <c>hipe</c> compiler and
+ <c>erts</c> runtime in an <em>incompatible</em> way. Old
+ hipe compiled files need to be recompiled to load and run
+ properly as native.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-14850 Aux Id: PR-1664 </p>
+ </item>
+ <item>
+ <p>The BEAM compiler chooses not to perform tailcall
+ optimisations for some calls in tail position, for
+ example to some built-in functions. However, when the
+ ErLLVM HiPE backend is used, LLVM may choose to perform
+ tailcall optimisation on these calls, breaking the
+ expected semantics.</p>
+ <p>To preserve the precise semantics exhibited by BEAM,
+ the 'notail' marker, present in LLVM since version 3.8,
+ is added to call instructions that BEAM has not turned
+ into tail calls, which inhibits LLVM from performing
+ tail-call optimisation in turn.</p>
+ <p>
+ Own Id: OTP-14886</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Hipe 3.17</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix bug for hipe compiled code using
+ <c>&lt;&lt;X/utf32&gt;&gt;</c> binary construction that
+ could cause faulty result or even VM crash.</p>
+ <p>
+ On architectures other than x86_64, code need to be
+ recompiled to benefit from this fix.</p>
+ <p>
+ Own Id: OTP-14740</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added documentation about limitations of hipe compared to
+ beam compiled code.</p>
+ <p>
+ Own Id: OTP-14767</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Hipe 3.16.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug regarding map types that caused Dialyzer to
+ go into an infinite loop. A consequence of the fix is
+ that compound map keys such as maps and tuples sometimes
+ are handled with less precision than before. </p>
+ <p>
+ Own Id: OTP-14572 Aux Id: seq13319 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ General Unicode improvements.</p>
+ <p>
+ Own Id: OTP-14462</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Hipe 3.16</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/hipe/doc/src/part_notes.xml b/lib/hipe/doc/src/part_notes.xml
deleted file mode 100644
index 828c304fb5..0000000000
--- a/lib/hipe/doc/src/part_notes.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2006</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>HiPE Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p><em>HiPE</em> - High Performance Erlang.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl
index 2abecf7f18..f429d40272 100644
--- a/lib/hipe/icode/hipe_beam_to_icode.erl
+++ b/lib/hipe/icode/hipe_beam_to_icode.erl
@@ -415,11 +415,13 @@ trans_fun([{wait_timeout,{_,Lbl},Reg}|Instructions], Env) ->
SuspTmout = hipe_icode:mk_if(suspend_msg_timeout,[],
map_label(Lbl),hipe_icode:label_name(DoneLbl)),
Movs ++ [SetTmout, SuspTmout, DoneLbl | trans_fun(Instructions,Env1)];
-%%--- recv_mark/1 & recv_set/1 --- XXX: Handle better??
+%%--- recv_mark/1 & recv_set/1 ---
trans_fun([{recv_mark,{f,_}}|Instructions], Env) ->
- trans_fun(Instructions,Env);
+ Mark = hipe_icode:mk_primop([],recv_mark,[]),
+ [Mark | trans_fun(Instructions,Env)];
trans_fun([{recv_set,{f,_}}|Instructions], Env) ->
- trans_fun(Instructions,Env);
+ Set = hipe_icode:mk_primop([],recv_set,[]),
+ [Set | trans_fun(Instructions,Env)];
%%--------------------------------------------------------------------
%%--- Translation of arithmetics {bif,ArithOp, ...} ---
%%--------------------------------------------------------------------
@@ -603,6 +605,16 @@ trans_fun([{get_list,List,Head,Tail}|Instructions], Env) ->
?error_msg("hd and tl regs identical in get_list~n",[]),
erlang:error(not_handled)
end;
+%%--- get_hd ---
+trans_fun([{get_hd,List,Head}|Instructions], Env) ->
+ TransList = [trans_arg(List)],
+ I = hipe_icode:mk_primop([mk_var(Head)],unsafe_hd,TransList),
+ [I | trans_fun(Instructions,Env)];
+%%--- get_tl ---
+trans_fun([{get_tl,List,Tail}|Instructions], Env) ->
+ TransList = [trans_arg(List)],
+ I = hipe_icode:mk_primop([mk_var(Tail)],unsafe_tl,TransList),
+ [I | trans_fun(Instructions,Env)];
%%--- get_tuple_element ---
trans_fun([{get_tuple_element,Xreg,Index,Dst}|Instructions], Env) ->
I = hipe_icode:mk_primop([mk_var(Dst)],
@@ -794,7 +806,7 @@ trans_fun([{bs_append,{f,Lbl},Size,W,R,U,Binary,{field_flags,F},Dst}|
SizeArg = trans_arg(Size),
BinArg = trans_arg(Binary),
IcodeDst = mk_var(Dst),
- Offset = mk_var(reg),
+ Offset = mk_var(reg_gcsafe),
Base = mk_var(reg),
trans_bin_call({hipe_bs_primop,{bs_append,W,R,U,F}},Lbl,[SizeArg,BinArg],
[IcodeDst,Base,Offset],
@@ -805,7 +817,7 @@ trans_fun([{bs_private_append,{f,Lbl},Size,U,Binary,{field_flags,F},Dst}|
SizeArg = trans_arg(Size),
BinArg = trans_arg(Binary),
IcodeDst = mk_var(Dst),
- Offset = mk_var(reg),
+ Offset = mk_var(reg_gcsafe),
Base = mk_var(reg),
trans_bin_call({hipe_bs_primop,{bs_private_append,U,F}},
Lbl,[SizeArg,BinArg],
@@ -844,7 +856,7 @@ trans_fun([{bs_init2,{f,Lbl},Size,_Words,_LiveRegs,{field_flags,Flags0},X}|
Instructions], Env) ->
Dst = mk_var(X),
Flags = resolve_native_endianess(Flags0),
- Offset = mk_var(reg),
+ Offset = mk_var(reg_gcsafe),
Base = mk_var(reg),
{Name, Args} =
case Size of
@@ -860,7 +872,7 @@ trans_fun([{bs_init_bits,{f,Lbl},Size,_Words,_LiveRegs,{field_flags,Flags0},X}|
Instructions], Env) ->
Dst = mk_var(X),
Flags = resolve_native_endianess(Flags0),
- Offset = mk_var(reg),
+ Offset = mk_var(reg_gcsafe),
Base = mk_var(reg),
{Name, Args} =
case Size of
@@ -1157,6 +1169,17 @@ trans_fun([{put_map_exact,{f,Lbl},Map,Dst,_N,{list,Pairs}}|Instructions], Env) -
gen_put_map_instrs(new, exact, TempMapVar, Dst, new, Pairs, Env1)
end,
[MapMove, TempMapMove, PutInstructions | trans_fun(Instructions, Env2)];
+%%--- build_stacktrace ---
+trans_fun([build_stacktrace|Instructions], Env) ->
+ Vars = [mk_var({x,0})], %{x,0} is implict arg and dst
+ [hipe_icode:mk_primop(Vars,build_stacktrace,Vars),
+ trans_fun(Instructions, Env)];
+%%--- raw_raise ---
+trans_fun([raw_raise|Instructions], Env) ->
+ Vars = [mk_var({x,0}),mk_var({x,1}),mk_var({x,2})],
+ Dst = [mk_var({x,0})],
+ [hipe_icode:mk_primop(Dst,raw_raise,Vars) |
+ trans_fun(Instructions, Env)];
%%--------------------------------------------------------------------
%%--- ERROR HANDLING ---
%%--------------------------------------------------------------------
@@ -1505,7 +1528,10 @@ clone_dst(Dest) ->
New =
case hipe_icode:is_reg(Dest) of
true ->
- mk_var(reg);
+ case hipe_icode:reg_is_gcsafe(Dest) of
+ true -> mk_var(reg_gcsafe);
+ false -> mk_var(reg)
+ end;
false ->
true = hipe_icode:is_var(Dest),
mk_var(new)
@@ -2126,7 +2152,12 @@ mk_var(reg) ->
T = hipe_gensym:new_var(icode),
V = (5*T)+4,
hipe_gensym:update_vrange(icode,V),
- hipe_icode:mk_reg(V).
+ hipe_icode:mk_reg(V);
+mk_var(reg_gcsafe) ->
+ T = hipe_gensym:new_var(icode),
+ V = (5*T)+4, % same namespace as 'reg'
+ hipe_gensym:update_vrange(icode,V),
+ hipe_icode:mk_reg_gcsafe(V).
%%-----------------------------------------------------------------------
%% Make an icode label of proper type
@@ -2296,6 +2327,12 @@ split_code([First|Code], Label, Instr) ->
split_code([Instr|Code], Label, Instr, Prev, As) when Prev =:= Label ->
split_code_final(Code, As); % drop both label and instruction
+split_code([{icode_end_try}|_]=Code, Label, {try_case,_}, Prev, As)
+ when Prev =:= Label ->
+ %% The try_case has been replaced with try_end as an optimization.
+ %% Keep this instruction, since it might be the only try_end instruction
+ %% for this try/catch block.
+ split_code_final(Code, As); % drop label
split_code([Other|_Code], Label, Instr, Prev, _As) when Prev =:= Label ->
?EXIT({missing_instr_after_label, Label, Instr, [Other, Prev | _As]});
split_code([Other|Code], Label, Instr, Prev, As) ->
diff --git a/lib/hipe/icode/hipe_icode.erl b/lib/hipe/icode/hipe_icode.erl
index 24b7ac4783..bc3403b0c5 100644
--- a/lib/hipe/icode/hipe_icode.erl
+++ b/lib/hipe/icode/hipe_icode.erl
@@ -515,10 +515,12 @@
annotate_variable/2, %% annotate_var_or_reg(VarOrReg, Type)
unannotate_variable/1,%% unannotate_var_or_reg(VarOrReg)
mk_reg/1, %% mk_reg(Id)
+ mk_reg_gcsafe/1, %% mk_reg_gcsafe(Id)
mk_fvar/1, %% mk_fvar(Id)
mk_new_var/0, %% mk_new_var()
mk_new_fvar/0, %% mk_new_fvar()
mk_new_reg/0, %% mk_new_reg()
+ mk_new_reg_gcsafe/0, %% mk_new_reg_gcsafe()
mk_phi/1, %% mk_phi(Id)
mk_phi/2 %% mk_phi(Id, ArgList)
]).
@@ -1260,14 +1262,22 @@ is_var(_) -> false.
-spec mk_reg(non_neg_integer()) -> #icode_variable{kind::'reg'}.
mk_reg(V) -> #icode_variable{name=V, kind=reg}.
--spec reg_name(#icode_variable{kind::'reg'}) -> non_neg_integer().
-reg_name(#icode_variable{name=Name, kind=reg}) -> Name.
+-spec mk_reg_gcsafe(non_neg_integer()) -> #icode_variable{kind::'reg_gcsafe'}.
+mk_reg_gcsafe(V) -> #icode_variable{name=V, kind=reg_gcsafe}.
--spec reg_is_gcsafe(#icode_variable{kind::'reg'}) -> 'false'.
-reg_is_gcsafe(#icode_variable{kind=reg}) -> false. % for now
+-spec reg_name(#icode_variable{kind::'reg'|'reg_gcsafe'})
+ -> non_neg_integer().
+reg_name(#icode_variable{name=Name, kind=reg}) -> Name;
+reg_name(#icode_variable{name=Name, kind=reg_gcsafe}) -> Name.
+
+-spec reg_is_gcsafe(#icode_variable{kind::'reg'}) -> 'false';
+ (#icode_variable{kind::'reg_gcsafe'}) -> 'true'.
+reg_is_gcsafe(#icode_variable{kind=reg}) -> false;
+reg_is_gcsafe(#icode_variable{kind=reg_gcsafe}) -> true.
-spec is_reg(icode_argument()) -> boolean().
-is_reg(#icode_variable{kind=reg}) -> true;
+is_reg(#icode_variable{kind=reg}) -> true;
+is_reg(#icode_variable{kind=reg_gcsafe}) -> true;
is_reg(_) -> false.
-spec mk_fvar(non_neg_integer()) -> #icode_variable{kind::'fvar'}.
@@ -1676,6 +1686,16 @@ mk_new_reg() ->
mk_reg(hipe_gensym:get_next_var(icode)).
%%
+%% @doc Makes a new gcsafe register; that is, a register that is allowed to be
+%% live over calls and other operations that might cause GCs and thus move heap
+%% data around.
+%%
+
+-spec mk_new_reg_gcsafe() -> icode_reg().
+mk_new_reg_gcsafe() ->
+ mk_reg_gcsafe(hipe_gensym:get_next_var(icode)).
+
+%%
%% @doc Makes a new label.
%%
diff --git a/lib/hipe/icode/hipe_icode.hrl b/lib/hipe/icode/hipe_icode.hrl
index 380ddd8371..7ed80a9ed4 100644
--- a/lib/hipe/icode/hipe_icode.hrl
+++ b/lib/hipe/icode/hipe_icode.hrl
@@ -41,9 +41,9 @@
-type variable_annotation() :: {atom(), any(), fun((any()) -> string())}.
--record(icode_variable, {name :: non_neg_integer(),
- kind :: 'var' | 'reg' | 'fvar',
- annotation = [] :: [] | variable_annotation()}).
+-record(icode_variable, {name :: non_neg_integer(),
+ kind :: 'var' | 'reg' | 'reg_gcsafe' | 'fvar',
+ annotation = [] :: [] | variable_annotation()}).
%%---------------------------------------------------------------------
%% Type declarations for Icode instructions
@@ -66,7 +66,7 @@
-type icode_funcall() :: mfa() | icode_primop().
-type icode_var() :: #icode_variable{kind::'var'}.
--type icode_reg() :: #icode_variable{kind::'reg'}.
+-type icode_reg() :: #icode_variable{kind::'reg'|'reg_gcsafe'}.
-type icode_fvar() :: #icode_variable{kind::'fvar'}.
-type icode_argument() :: #icode_const{} | #icode_variable{}.
-type icode_term_arg() :: icode_var() | #icode_const{}.
diff --git a/lib/hipe/icode/hipe_icode_inline_bifs.erl b/lib/hipe/icode/hipe_icode_inline_bifs.erl
index 7a6947f190..16a95991e7 100644
--- a/lib/hipe/icode/hipe_icode_inline_bifs.erl
+++ b/lib/hipe/icode/hipe_icode_inline_bifs.erl
@@ -24,8 +24,9 @@
%% Currently inlined BIFs:
%% and, or, xor, not, <, >, >=, =<, ==, /=, =/=, =:=
-%% is_atom, is_boolean, is_binary, is_float, is_function,
-%% is_integer, is_list, is_pid, is_port, is_reference, is_tuple
+%% is_atom, is_binary, is_bitstring, is_boolean, is_float,
+%% is_function, is_integer, is_list, is_map, is_number,
+%% is_pid, is_port, is_reference, is_tuple
-module(hipe_icode_inline_bifs).
@@ -116,17 +117,20 @@ try_type_tests(I) -> I.
is_type_test(Name) ->
case Name of
- is_integer -> {true, integer};
+ is_atom -> {true, atom};
+ is_binary -> {true, binary};
+ is_bitstring -> {true, bitstr};
+ is_boolean -> {true, boolean};
is_float -> {true, float};
- is_tuple -> {true, tuple};
- is_binary -> {true, binary};
+ is_function -> {true, function};
+ is_integer -> {true, integer};
is_list -> {true, list};
+ is_map -> {true, map};
+ is_number -> {true, number};
is_pid -> {true, pid};
- is_atom -> {true, atom};
- is_boolean -> {true, boolean};
- is_function -> {true, function};
- is_reference -> {true, reference};
is_port -> {true, port};
+ is_reference -> {true, reference};
+ is_tuple -> {true, tuple};
_ -> false
end.
diff --git a/lib/hipe/icode/hipe_icode_liveness.erl b/lib/hipe/icode/hipe_icode_liveness.erl
index 51e2855108..e61529a1bb 100644
--- a/lib/hipe/icode/hipe_icode_liveness.erl
+++ b/lib/hipe/icode/hipe_icode_liveness.erl
@@ -77,6 +77,7 @@ print_var(#icode_variable{name=V, kind=Kind, annotation=T}) ->
case Kind of
var -> io:format("v~p", [V]);
reg -> io:format("r~p", [V]);
+ reg_gcsafe -> io:format("rs~p", [V]);
fvar -> io:format("fv~p", [V])
end,
case T of
diff --git a/lib/hipe/icode/hipe_icode_pp.erl b/lib/hipe/icode/hipe_icode_pp.erl
index 5b017dca32..33d1e62884 100644
--- a/lib/hipe/icode/hipe_icode_pp.erl
+++ b/lib/hipe/icode/hipe_icode_pp.erl
@@ -230,7 +230,10 @@ pp_arg(Dev, Arg) ->
case hipe_icode:is_reg(Arg) of
true ->
N = hipe_icode:reg_name(Arg),
- io:format(Dev, "r~p", [N]);
+ case hipe_icode:reg_is_gcsafe(Arg) of
+ true -> io:format(Dev, "rs~p", [N]);
+ false -> io:format(Dev, "r~p", [N])
+ end;
false ->
N = hipe_icode:fvar_name(Arg),
io:format(Dev, "fv~p", [N])
diff --git a/lib/hipe/icode/hipe_icode_primops.erl b/lib/hipe/icode/hipe_icode_primops.erl
index 50ece05259..a1f1128124 100644
--- a/lib/hipe/icode/hipe_icode_primops.erl
+++ b/lib/hipe/icode/hipe_icode_primops.erl
@@ -67,6 +67,8 @@ is_safe(fp_mul) -> false;
is_safe(fp_sub) -> false;
is_safe(mktuple) -> true;
is_safe(next_msg) -> false;
+is_safe(recv_mark) -> false;
+is_safe(recv_set) -> false;
is_safe(redtest) -> false;
is_safe(select_msg) -> false;
is_safe(self) -> true;
@@ -130,6 +132,7 @@ is_safe({hipe_bs_primop, {bs_match_string, _, _}}) -> false;
is_safe({hipe_bs_primop, {bs_append, _, _, _, _}}) -> false;
is_safe({hipe_bs_primop, {bs_private_append, _, _}}) -> false;
is_safe({hipe_bs_primop, bs_init_writable}) -> true;
+is_safe(build_stacktrace) -> true;
is_safe(#mkfun{}) -> true;
is_safe(#unsafe_element{}) -> true;
is_safe(#unsafe_update_element{}) -> true;
@@ -165,6 +168,8 @@ fails(fp_mul) -> false;
fails(fp_sub) -> false;
fails(mktuple) -> false;
fails(next_msg) -> false;
+fails(recv_mark) -> false;
+fails(recv_set) -> false;
fails(redtest) -> false;
fails(select_msg) -> false;
fails(self) -> false;
@@ -230,6 +235,8 @@ fails({hipe_bs_primop, bs_final}) -> false;
fails({hipe_bs_primop, {bs_append, _, _, _, _}}) -> true;
fails({hipe_bs_primop, {bs_private_append, _, _}}) -> true;
fails({hipe_bs_primop, bs_init_writable}) -> true;
+fails(build_stacktrace) -> false;
+fails(raw_raise) -> true;
fails(#mkfun{}) -> false;
fails(#unsafe_element{}) -> false;
fails(#unsafe_update_element{}) -> false;
@@ -709,6 +716,10 @@ type(Primop, Args) ->
erl_types:t_any();
next_msg ->
erl_types:t_any();
+ recv_mark ->
+ erl_types:t_any();
+ recv_set ->
+ erl_types:t_any();
select_msg ->
erl_types:t_any();
set_timeout ->
@@ -723,6 +734,10 @@ type(Primop, Args) ->
erl_types:t_any();
debug_native_called ->
erl_types:t_any();
+ build_stacktrace ->
+ erl_types:t_list();
+ raw_raise ->
+ erl_types:t_atom();
{M, F, A} ->
erl_bif_types:type(M, F, A, Args)
end.
@@ -883,6 +898,10 @@ type(Primop) ->
erl_types:t_any();
next_msg ->
erl_types:t_any();
+ recv_mark ->
+ erl_types:t_any();
+ recv_set ->
+ erl_types:t_any();
select_msg ->
erl_types:t_any();
set_timeout ->
@@ -891,6 +910,10 @@ type(Primop) ->
erl_types:t_any();
%%% -----------------------------------------------------
%%% Other
+ build_stacktrace ->
+ erl_types:t_any();
+ raw_raise ->
+ erl_types:t_any();
#closure_element{} ->
erl_types:t_any();
redtest ->
diff --git a/lib/hipe/icode/hipe_icode_range.erl b/lib/hipe/icode/hipe_icode_range.erl
index 287b1c80fe..34b18acccd 100644
--- a/lib/hipe/icode/hipe_icode_range.erl
+++ b/lib/hipe/icode/hipe_icode_range.erl
@@ -1160,6 +1160,8 @@ basic_type(#gc_test{}) -> not_analysed;
%% Message handling
basic_type(check_get_msg) -> not_analysed;
basic_type(next_msg) -> not_analysed;
+basic_type(recv_mark) -> not_analysed;
+basic_type(recv_set) -> not_analysed;
basic_type(select_msg) -> not_analysed;
basic_type(suspend_msg) -> not_analysed;
%% Functions
@@ -1184,7 +1186,9 @@ basic_type(unsafe_hd) -> not_analysed;
basic_type(unsafe_tl) -> not_int;
basic_type(#element{}) -> not_analysed;
basic_type(#unsafe_element{}) -> not_analysed;
-basic_type(#unsafe_update_element{}) -> not_analysed.
+basic_type(#unsafe_update_element{}) -> not_analysed;
+basic_type(build_stacktrace) -> not_int;
+basic_type(raw_raise) -> not_int.
-spec analyse_bs_get_integer(integer(), integer(), boolean()) -> range_tuple().
diff --git a/lib/hipe/llvm/hipe_llvm.erl b/lib/hipe/llvm/hipe_llvm.erl
index 641d3fda0a..343ca94cb1 100644
--- a/lib/hipe/llvm/hipe_llvm.erl
+++ b/lib/hipe/llvm/hipe_llvm.erl
@@ -934,7 +934,7 @@ pp_ins(Dev, Ver, I) ->
end,
case call_is_tail(I) of
true -> write(Dev, "tail ");
- false -> ok
+ false -> write(Dev, "notail ")
end,
write(Dev, ["call ", call_cconv(I), " "]),
pp_options(Dev, call_ret_attrs(I)),
@@ -1005,11 +1005,12 @@ pp_ins(Dev, Ver, I) ->
write(Dev, [" ", adj_stack_offset(I),")\n"]);
#llvm_meta{} ->
write(Dev, ["!", meta_id(I), " = !{ "]),
- write(Dev, string:join([if is_list(Op) -> ["!\"", Op, "\""];
- is_integer(Op) -> ["i32 ", integer_to_list(Op)];
- is_record(Op, llvm_meta) ->
- ["!", meta_id(Op)]
- end || Op <- meta_operands(I)], ", ")),
+ write(Dev, lists:join(", ",
+ [if is_list(Op) -> ["!\"", Op, "\""];
+ is_integer(Op) -> ["i32 ", integer_to_list(Op)];
+ is_record(Op, llvm_meta) ->
+ ["!", meta_id(Op)]
+ end || Op <- meta_operands(I)])),
write(Dev, " }\n");
Other ->
exit({?MODULE, pp_ins, {"Unknown LLVM instruction", Other}})
diff --git a/lib/hipe/llvm/hipe_llvm_main.erl b/lib/hipe/llvm/hipe_llvm_main.erl
index 4eec0c752b..54c435c127 100644
--- a/lib/hipe/llvm/hipe_llvm_main.erl
+++ b/lib/hipe/llvm/hipe_llvm_main.erl
@@ -154,7 +154,7 @@ compiler_target_opt() ->
%% @doc Join options.
fix_opts(Opts) ->
- string:join(Opts, " ").
+ lists:flatten(lists:join(" ", Opts)).
%% @doc Translate optimization-level flag (default is "O2").
trans_optlev_flag(Tool, Options) ->
diff --git a/lib/hipe/llvm/hipe_rtl_to_llvm.erl b/lib/hipe/llvm/hipe_rtl_to_llvm.erl
index 79e1bfd381..934717efc1 100644
--- a/lib/hipe/llvm/hipe_rtl_to_llvm.erl
+++ b/lib/hipe/llvm/hipe_rtl_to_llvm.erl
@@ -1537,7 +1537,7 @@ declare_switch_table({Name, {switch, {TableType, Labels, _, _}, _}}, FunName) ->
LabelList = [mk_jump_label(L) || L <- Labels],
Fun1 = fun(X) -> "i8* blockaddress(@" ++ FunName ++ ", " ++ X ++ ")" end,
List2 = lists:map(Fun1, LabelList),
- List3 = string:join(List2, ",\n"),
+ List3 = lists:flatten(lists:join(",\n", List2)),
List4 = "[\n" ++ List3 ++ "\n]\n",
hipe_llvm:mk_const_decl("@" ++ Name, "constant", TableType, List4).
@@ -1553,7 +1553,7 @@ declare_closure_labels(ClosureLabels, Relocs, Fun) ->
Relocs1 = relocs_store("table_closures", {table_closures, ArityList}, Relocs),
List2 =
["i8* blockaddress(@" ++ FunName ++ ", " ++ L ++ ")" || L <- LabelList],
- List3 = string:join(List2, ",\n"),
+ List3 = lists:flatten(lists:join(",\n", List2)),
List4 = "[\n" ++ List3 ++ "\n]\n",
NrLabels = length(LabelList),
ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(?BITS_IN_BYTE)),
diff --git a/lib/hipe/main/hipe.app.src b/lib/hipe/main/hipe.app.src
index 3c3a1004f1..4684ab49ea 100644
--- a/lib/hipe/main/hipe.app.src
+++ b/lib/hipe/main/hipe.app.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,6 @@
cerl_closurean,
cerl_hipeify,
cerl_lib,
- cerl_messagean,
cerl_pmatch,
cerl_prettypr,
cerl_to_icode,
@@ -179,6 +178,7 @@
hipe_rtl_to_sparc,
hipe_rtl_to_x86,
hipe_rtl_varmap,
+ hipe_rtl_verify_gcsafe,
hipe_segment_trees,
hipe_sdi,
hipe_sparc,
@@ -235,5 +235,5 @@
{registered,[]},
{applications, [kernel,stdlib]},
{env, []},
- {runtime_dependencies, ["syntax_tools-1.6.14","stdlib-2.5","kernel-3.0",
- "erts-9.0","compiler-5.0"]}]}.
+ {runtime_dependencies, ["syntax_tools-1.6.14","stdlib-3.4","kernel-5.3",
+ "erts-9.3","compiler-5.0"]}]}.
diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl
index 19b4e8bfe2..ac2e6c1e3b 100644
--- a/lib/hipe/main/hipe.erl
+++ b/lib/hipe/main/hipe.erl
@@ -669,8 +669,8 @@ run_compiler_1(Name, DisasmFun, IcodeFun, Options) ->
{Icode, WholeModule} = IcodeFun(Code, Opts),
CompRes = compile_finish(Icode, WholeModule, Opts),
compiler_return(CompRes, Parent)
- catch error:Error ->
- print_crash_message(Name, Error),
+ catch error:Error:StackTrace ->
+ print_crash_message(Name, Error, StackTrace),
exit(Error)
end
end),
@@ -757,8 +757,8 @@ finalize(OrigList, Mod, Exports, WholeModule, Opts) ->
TargetArch = get(hipe_target_arch),
{ok, {TargetArch,Bin}}
catch
- error:Error ->
- {error,Error,erlang:get_stacktrace()}
+ error:Error:StackTrace ->
+ {error,Error,StackTrace}
end
end.
@@ -843,17 +843,17 @@ finalize_fun_sequential({MFA, Icode}, Opts, Servers) ->
{llvm_binary, Binary} ->
{MFA, Binary}
catch
- error:Error ->
+ error:Error:StackTrace ->
?when_option(verbose, Opts, ?debug_untagged_msg("\n", [])),
- print_crash_message(MFA, Error),
+ print_crash_message(MFA, Error, StackTrace),
exit(Error)
end.
-print_crash_message(What, Error) ->
+print_crash_message(What, Error, StackTrace) ->
StackFun = fun(_,_,_) -> false end,
FormatFun = fun (Term, _) -> io_lib:format("~p", [Term]) end,
- StackTrace = lib:format_stacktrace(1, erlang:get_stacktrace(),
- StackFun, FormatFun),
+ StackTraceS = erl_error:format_stacktrace(1, StackTrace,
+ StackFun, FormatFun),
WhatS = case What of
{M,F,A} -> io_lib:format("~w:~w/~w", [M,F,A]);
Mod -> io_lib:format("~w", [Mod])
@@ -862,7 +862,7 @@ print_crash_message(What, Error) ->
"while compiling ~s~n"
"crash reason: ~p~n"
"~s~n",
- [WhatS, Error, StackTrace]).
+ [WhatS, Error, StackTraceS]).
pp_server_start(Opts) ->
set_architecture(Opts),
@@ -1414,6 +1414,7 @@ opt_keys() ->
use_clusters,
use_jumptable,
verbose,
+ verify_gcsafe,
%% verbose_spills,
x87].
@@ -1510,7 +1511,8 @@ opt_negations() ->
{no_use_callgraph, use_callgraph},
{no_use_clusters, use_clusters},
{no_use_inline_atom_search, use_inline_atom_search},
- {no_use_indexing, use_indexing}].
+ {no_use_indexing, use_indexing},
+ {no_verify_gcsafe, verify_gcsafe}].
%% Don't use negative forms in right-hand sides of aliases and expansions!
%% We only expand negations once, before the other expansions are done.
@@ -1616,11 +1618,11 @@ llvm_support_available() ->
get_llvm_version() ->
OptStr = os:cmd("opt -version"),
SubStr = "LLVM version ", N = length(SubStr),
- case string:str(OptStr, SubStr) of
- 0 -> % No opt available
+ case string:find(OptStr, SubStr) of
+ nomatch -> % No opt available
{0, 0};
S ->
- case string:tokens(string:sub_string(OptStr, S + N), ".") of
+ case string:lexemes(string:slice(S, N), ".") of
[MajorS, MinorS | _] ->
case {string:to_integer(MajorS), string:to_integer(MinorS)} of
{{Major, ""}, {Minor, _}}
diff --git a/lib/hipe/main/hipe_main.erl b/lib/hipe/main/hipe_main.erl
index dca6fddec3..6e48f0cffd 100644
--- a/lib/hipe/main/hipe_main.erl
+++ b/lib/hipe/main/hipe_main.erl
@@ -410,6 +410,11 @@ icode_to_rtl(MFA, Icode, Options, Servers) ->
hipe_llvm_liveness:analyze(RtlCfg4)
end,
pp(RtlCfg5, MFA, rtl, pp_rtl, Options, Servers),
+ case proplists:get_bool(no_verify_gcsafe, Options) of
+ true -> ok;
+ false ->
+ ok = hipe_rtl_verify_gcsafe:check(RtlCfg5)
+ end,
LinearRTL1 = hipe_rtl_cfg:linearize(RtlCfg5),
LinearRTL2 = hipe_rtl_cleanup_const:cleanup(LinearRTL1),
%% hipe_rtl:pp(standard_io, LinearRTL2),
diff --git a/lib/hipe/opt/hipe_schedule.erl b/lib/hipe/opt/hipe_schedule.erl
deleted file mode 100644
index 0f25940e3d..0000000000
--- a/lib/hipe/opt/hipe_schedule.erl
+++ /dev/null
@@ -1,1483 +0,0 @@
-%% 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.
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% INSTRUCTION SCHEDULER
-%%
-%% This is a basic ILP cycle scheduler:
-%% * set cycle = 0
-%% * while ready[cycle] nonempty do
-%% - take x with greatest priority from ready[cycle]
-%% - try to schedule x;
-%% * if scheduling x was possible,
-%% - reserve resources
-%% - add x to schedule and delete x from dag
-%% - update earliest-time for all successor nodes
-%% as max[earliest[y],cycle+latency[x]]
-%% - if some node y now has no predecessors,
-%% add y to ready[earliest[y]]
-%% * if it was impossible, put x in ready[cycle+1]
-%% (= try again)
-%%
-%% We use the following data structures:
-%% 1. all nodes are numbered and indices used as array keys
-%% 2. priority per node can be computed statically or dynamically
-%% * statically: before scheduling, each node gets a priority value
-%% * dynamically: at each cycle, compute priorities for all ready nodes
-%% 3. earliest: earliest cycle of issue, starts at 0
-%% and is updated as predecessors issue
-%% 4. predecessors: number of predecessors (0 = ready to issue)
-%% 5. successors: list of {Latency,NodeID}
-%% 6. ready: an array indexed by cycle-time (integer), where
-%% ready nodes are kept.
-%% 7. resources: a resource representation (ADT) that answers
-%% certain queries, e.g., "can x be scheduled this cycle"
-%% and "reserve resources for x".
-%% 8. schedule: list of scheduled instructions {Instr,Cycle}
-%% in the order of issue
-%% 9. instructions: maps IDs back to instructions
-%%
-%% Inputs:
-%% - a list of {ID,Node} pairs (where ID is a unique key)
-%% - a dependence list {ID0,Latency,ID1}, which is used to
-%% build the DAG.
-%%
-%% Note that there is some leeway in how things are represented
-%% from here.
-%%
-%% MODIFICATIONS:
-%% - Some basic blocks are not worth scheduling (e.g., GC save/restore code)
-%% yet are pretty voluminous. How do we skip them?
-%% - Scheduling should be done at finalization time: when basic block is
-%% linearized and is definitely at Sparc assembly level, THEN reorder
-%% stuff.
-
--module(hipe_schedule).
--export([cfg/1, est_cfg/1, delete_node/5]).
-
--include("../sparc/hipe_sparc.hrl").
-
-%%-define(debug1,true).
-
--define(debug2(Str,Args),ok).
-%%-define(debug2(Str,Args),io:format(Str,Args)).
-
--define(debug3(Str,Args),ok).
-%%-define(debug3(Str,Args),io:format(Str,Args)).
-
--define(debug4(Str,Args),ok).
-%%-define(debug4(Str,Args),io:format(Str,Args)).
-
--define(debug5(Str,Args),ok).
-%%-define(debug5(Str,Args),io:format(Str,Args)).
-
--define(debug(Str,Args),ok).
-%%-define(debug(Str,Args),io:format(Str,Args)).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : cfg
-%% Argument : CFG - the control flow graph
-%% Returns : CFG - A new cfg with scheduled blocks
-%% Description : Takes each basic block and schedules them one by one.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-cfg(CFG) ->
- ?debug3("CFG: ~n~p", [CFG]),
- update_all( [ {L,
- hipe_bb:mk_bb(
- block(L,hipe_bb:code(hipe_sparc_cfg:bb(CFG,L))) )}
- || L <- hipe_sparc_cfg:labels(CFG) ], CFG).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : update_all
-%% Argument : Blocks - [{Label, Block}] , a list with labels and new code
-%% used for updating the old CFG.
-%% CFG - The old controlflow graph
-%% Returns : An updated controlflow graph.
-%% Description : Just swappes the basic blocks in the CFG to the scheduled one.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-update_all([],CFG) -> CFG;
-update_all([{L,NewB}|Ls],CFG) ->
- update_all(Ls,hipe_sparc_cfg:bb_add(CFG,L,NewB)).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-est_cfg(CFG) ->
- update_all([ {L, hipe_bb:mk_bb(est_block(hipe_bb:code(hipe_sparc_cfg:bb(CFG,L))))}
- || L <- hipe_sparc_cfg:labels(CFG) ], CFG).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Provides an estimation of how quickly a block will execute.
-%% This is done by chaining all instructions in sequential order
-%% by 0-cycle dependences (which means they will never be reordered),
-%% then scheduling the mess.
-
-est_block([]) -> [];
-est_block([I]) -> [I];
-est_block(Blk) ->
- {IxBlk,DAG} = est_deps(Blk),
- Sch = bb(IxBlk,DAG),
- separate_block(Sch,IxBlk).
-
-est_deps(Blk) ->
- IxBlk = indexed_bb(Blk),
- DAG = deps(IxBlk),
- {IxBlk, chain_instrs(IxBlk,DAG)}.
-
-chain_instrs([{N,_}|Xs],DAG) ->
- chain_i(N,Xs,DAG).
-
-chain_i(_,[],DAG) -> DAG;
-chain_i(N,[{M,_}|Xs],DAG) ->
- NewDAG = dep_arc(N,zero_latency(),M,DAG),
- chain_i(M,Xs,NewDAG).
-
-zero_latency() -> 0.
-
-lookup_instr([{N,I}|_], N) -> I;
-lookup_instr([_|Xs], N) -> lookup_instr(Xs, N).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : block
-%% Argument : Instrs - [Instr], list of all the instructions in a basic
-%% block.
-%% Returns : A new scheduled block
-%% Description : Schedule a basic block
-%%
-%% Note: does not consider delay slots!
-%% (another argument for using only annulled delay slots?)
-%% * how do we add delay slots? somewhat tricky to
-%% reconcile with the sort of scheduling we consider.
-%% (as-early-as-possible)
-%% => rewrite scheduler into as-late-as-possible?
-%% (=> just reverse the dependence arcs??)
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% Don't fire up the scheduler if there's no work to do.
-block(_, []) ->
- [];
-block(_L, [I]) ->
- case hipe_sparc:is_any_branch(I) of
- true -> [hipe_sparc:nop_create(), I];
- false -> [I]
- end;
-block(_L, Blk) ->
- IxBlk = indexed_bb(Blk),
- case IxBlk of
- [{_N, I}] -> % comments and nops may have been removed.
- case hipe_sparc:is_any_branch(I) of
- true -> [hipe_sparc:nop_create(), I];
- false -> [I]
- end;
- _ ->
- Sch = bb(IxBlk, {DAG, _Preds} = deps(IxBlk)),
- {NewSch, NewIxBlk} = fill_delays(Sch, IxBlk, DAG),
- X = finalize_block(NewSch, NewIxBlk),
- debug1_stuff(Blk, DAG, IxBlk, Sch, X),
- X
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : fill_delays
-%% Argument : Sch - List of {{cycle, C}, {node, N}} : C = current cycle
-%% N = node index
-%% IxBlk - Indexed block [{N, Instr}]
-%% DAG - Dependence graph
-%% Returns : {NewSch, NewIxBlk} - vector with new schedule and vector
-%% with {N, Instr}
-%% Description : Goes through the schedule from back to front looking for
-%% branches/jumps. If one is found fill_del tries to find
-%% an instr to fill the delayslot.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-fill_delays(Sch, IxBlk, DAG) ->
- NewIxBlk = hipe_vectors:list_to_vector(IxBlk),
- %% NewSch = hipe_vectors:list_to_vector(Sch),
- NewSch = fill_del(length(Sch), hipe_vectors:list_to_vector(Sch),
- NewIxBlk, DAG),
- {NewSch, NewIxBlk}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : fill_del
-%% Argument : N - current index in the schedule
-%% Sch - schedule
-%% IxBlk - indexed block
-%% DAG - dependence graph
-%% Returns : Sch - New schedule with possibly a delay instr in the last
-%% position.
-%% Description : If a call/jump is found fill_branch_delay/fill_call_delay
-%% is called to find a delay-filler.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-fill_del(N, Sch, _IxBlk, _DAG) when N < 1 -> Sch;
-fill_del(N, Sch, IxBlk, DAG) ->
- Index = get_index(Sch, N),
- ?debug2("Index for ~p: ~p~nInstr: ~p~n",
- [N, Index, get_instr(IxBlk, Index)]),
- NewSch =
- case get_instr(IxBlk, Index) of
- #call_link{} ->
- fill_branch_delay(N - 1, N, Sch, IxBlk, DAG);
- #jmp_link{} ->
- fill_call_delay(N - 1, N, Sch, IxBlk, DAG);
- #jmp{} ->
- fill_call_delay(N - 1, N, Sch, IxBlk, DAG);
- #b{} ->
- fill_branch_delay(N - 1, N, Sch, IxBlk, DAG);
- #br{} ->
- fill_branch_delay(N - 1, N, Sch, IxBlk, DAG);
- #goto{} ->
- fill_branch_delay(N - 1, N, Sch, IxBlk, DAG);
- _Other ->
- Sch
- end,
- NewSch.
- %% fill_del(N - 1, NewSch, IxBlk, DAG).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : fill_call_delay
-%% Argument : Cand - index in schedule of delay-candidate
-%% Call - index in schedule of call
-%% Sch - schedule vector: < {{cycle,Ci},{node,Nj}}, ... >
-%% IxBlk - block vector: < {N, Instr1}, {N+1, Instr2} ... >
-%% DAG - dependence graph
-%% Returns : Sch - new updated schedule.
-%% Description : Searches backwards through the schedule trying to find an
-%% instr without conflicts with the Call-instr.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-fill_call_delay(Cand, _Call, Sch, _IxBlk, _DAG) when Cand < 1 -> Sch;
-fill_call_delay(Cand, Call, Sch, IxBlk, DAG) ->
- CandIndex = get_index(Sch, Cand),
- CallIndex = get_index(Sch, Call),
- CandI = get_instr(IxBlk, CandIndex),
- case move_or_alu(CandI) of
- true ->
- case single_depend(CandIndex, CallIndex, DAG) of
- false -> % Other instrs depends on Cand ...
- fill_call_delay(Cand - 1, Call, Sch, IxBlk, DAG);
-
- true ->
- CallI = get_instr(IxBlk, CallIndex),
-
- CandDefs = ordsets:from_list(hipe_sparc:defines(CandI)),
- %% CandUses = ordsets:from_list(hipe_sparc:uses(CandI)),
- %% CallDefs = ordsets:from_list(hipe_sparc:defines(CallI)),
- CallUses = ordsets:from_list(hipe_sparc:uses(CallI)),
-
- Args = case CallI of
- #jmp_link{} ->
- ordsets:from_list(
- hipe_sparc:jmp_link_args(CallI));
- #jmp{} ->
- ordsets:from_list(hipe_sparc:jmp_args(CallI));
- #call_link{} ->
- ordsets:from_list(
- hipe_sparc:call_link_args(CallI))
- end,
- CallUses2 = ordsets:subtract(CallUses, Args),
- Conflict = ordsets:intersection(CandDefs, CallUses2),
- %% io:format("single_depend -> true:~n ~p~n, ~p~n,~p~n",[CandI,CallI,DAG]),
- %% io:format("Cand = ~p~nCall = ~p~n",[CandI,CallI]),
- %% io:format("CandDefs = ~p~nCallDefs = ~p~n",[CandDefs,CallDefs]),
- %% io:format("CandUses = ~p~nCallUses = ~p~n",[CandUses,CallUses]),
- %% io:format("Args = ~p~nCallUses2 = ~p~n",[Args,CallUses2]),
- %% io:format("Conflict = ~p~n",[Conflict]),
-
- case Conflict of
- [] -> % No conflicts ==> Cand can fill delayslot after Call
- update_schedule(Cand, Call, Sch);
- _ -> % Conflict: try with preceeding instrs
- fill_call_delay(Cand - 1, Call, Sch, IxBlk, DAG)
- end
- end;
- false ->
- fill_call_delay(Cand - 1, Call, Sch, IxBlk, DAG)
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : fill_branch_delay
-%% Argument : Cand - index in schedule of delay-candidate
-%% Branch - index in schedule of branch
-%% Sch - schedule
-%% IxBlk - indexed block
-%% DAG - dependence graph
-%% Returns : Sch - new updated schedule.
-%% Description : Searches backwards through the schedule trying to find an
-%% instr without conflicts with the Branch-instr.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-fill_branch_delay(Cand, _Br, Sch, _IxBlk, _DAG) when Cand < 1 -> Sch;
-fill_branch_delay(Cand, Br, Sch, IxBlk, DAG) ->
- CandIndex = get_index(Sch, Cand),
- BrIndex = get_index(Sch, Br),
- CandI = get_instr(IxBlk, CandIndex),
- case move_or_alu(CandI) of
- true ->
- case single_depend(CandIndex, BrIndex, DAG) of
- false -> % Other instrs depends on Cand ...
- fill_branch_delay(Cand - 1, Br, Sch, IxBlk, DAG);
-
- true ->
- BrI = get_instr(IxBlk, BrIndex),
- CandDefs = ordsets:from_list(hipe_sparc:defines(CandI)),
- %% CandUses = ordsets:from_list(hipe_sparc:uses(CandI)),
- %% BrDefs = ordsets:from_list(hipe_sparc:defines(BrI)),
- BrUses = ordsets:from_list(hipe_sparc:uses(BrI)),
-
- Conflict = ordsets:intersection(CandDefs, BrUses),
- %% io:format("single_depend -> true: ~p~n, ~p~n,~p~n", [CandI, BrI, DAG]),
- %% io:format("Cand = ~p~nBr = ~p~n",[CandI,BrI]),
- %% io:format("CandDefs = ~p~nBrDefs = ~p~n",[CandDefs,BrDefs]),
- %% io:format("CandUses = ~p~nBrUses = ~p~n",[CandUses,BrUses]),
- %% io:format("Conflict = ~p~n",[Conflict]);
-
- case Conflict of
- [] -> % No conflicts ==>
- % Cand can fill delayslot after Branch
- update_schedule(Cand, Br, Sch);
- _ -> % Conflict: try with preceeding instrs
- fill_branch_delay(Cand - 1, Br, Sch, IxBlk, DAG)
- end
- end;
- false ->
- fill_branch_delay(Cand - 1, Br, Sch, IxBlk, DAG)
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : update_schedule
-%% Argument : From - the position from where to switch indexes in Sch
-%% To - the position to where to switch indexes in Sch
-%% Sch - schedule
-%% Returns : Sch - an updated schedule
-%% Description : If From is the delay-filler and To is the Call/jump, the
-%% schedule is updated so From gets index To, To gets index
-%% To - 1, and the nodes between From and To gets old_index - 1.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-update_schedule(To, To, Sch) ->
- {{cycle, C}, {node, _N} = Node} = hipe_vectors:get(Sch, To-1),
- hipe_vectors:set(Sch, To-1, {{cycle, C+1}, Node});
-update_schedule(From, To, Sch) ->
- Temp = hipe_vectors:get(Sch, From-1),
- Sch1 = hipe_vectors:set(Sch, From-1, hipe_vectors:get(Sch, From)),
- update_schedule(From + 1, To, hipe_vectors:set(Sch1, From, Temp)).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : single_depend
-%% Argument : N - Index of the delayslot candidate
-%% M - Index of the node that N possibly has a single
-%% depend to.
-%% DAG - The dependence graph
-%% Returns : true if no other nodes than N os depending on N
-%% Description : Checks that no other nodes than M depends on N and that the
-%% latency between them is zero or 1.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-single_depend(N, M, DAG) ->
- Deps = hipe_vectors:get(DAG, N-1),
- single_depend(M, Deps).
-
-single_depend(_N, []) -> true;
-single_depend(N, [{0, N}]) -> true;
-single_depend(N, [{1, N}]) -> true;
-single_depend(_N, [{_Lat, _}|_]) -> false.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : get_index
-%% Argument : Sch - schedule
-%% N - index in schedule
-%% Returns : Index - index of the node
-%% Description : Returns the index of the node on position N in the schedule.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-get_index(Sch, N) ->
- {{cycle, _C}, {node, Index}} = hipe_vectors:get(Sch,N-1),
- Index.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : get_instr
-%% Argument : IxBlk - indexed block
-%% N - index in block
-%% Returns : Instr
-%% Description : Returns the instr on position N in the indexed block.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-get_instr(IxBlk, N) ->
- {_, Instr} = hipe_vectors:get(IxBlk, N-1),
- Instr.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : get_instr
-%% Argument : Sch - schedule
-%% IxBlk - indexed block
-%% N - index in schedule
-%% Returns : Instr
-%% Description : Returns the instr on position N in the schedule.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-get_instr(Sch, IxBlk, N) ->
- {{cycle, _C}, {node, Index}} = hipe_vectors:get(Sch, N-1),
- {_, Instr} = hipe_vectors:get(IxBlk, Index-1),
- Instr.
-
-separate_block(Sch,IxBlk) ->
- sep_comments([{C,lookup_instr(IxBlk,N)} || {{cycle,C},{node,N}} <- Sch]).
-
-sep_comments([]) -> [];
-sep_comments([{C,I}|Xs]) ->
- [hipe_sparc:comment_create({cycle,C}), I | sep_comments(Xs,C)].
-
-sep_comments([], _) -> [];
-sep_comments([{C1,I}|Xs], C0) ->
- if
- C1 > C0 ->
- [hipe_sparc:comment_create({cycle,C1}),I|sep_comments(Xs,C1)];
- true ->
- [I|sep_comments(Xs, C0)]
- end.
-
-finalize_block(Sch, IxBlk) ->
- ?debug5("Sch: ~p~nIxBlk: ~p~n",[Sch,IxBlk]),
- finalize_block(1, hipe_vectors:size(Sch), 1, Sch, IxBlk, []).
-
-finalize_block(N, End, _C, Sch, IxBlk, _Instrs) when N =:= End - 1 ->
- NextLast = get_instr(Sch, IxBlk, N),
- Last = get_instr(Sch, IxBlk, End),
- ?debug5("NextLast: ~p~nLast: ~p~n",[NextLast,Last]),
- case hipe_sparc:is_any_branch(Last) of
- true -> % Couldn't fill delayslot ==> add NOP
- [NextLast , hipe_sparc:nop_create(), Last];
- false -> % Last is a delayslot-filler ==> change order...
- [Last, NextLast]
- end;
-finalize_block(N, End, C0, Sch, IxBlk, Instrs) ->
- {{cycle, _C1}, {node, _M}} = hipe_vectors:get(Sch, N-1),
- Instr = get_instr(Sch, IxBlk, N),
- ?debug5("Instr: ~p~n~n",[Instr]),
- [Instr | finalize_block(N + 1, End, C0, Sch, IxBlk, Instrs)].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : bb
-%% Argument : IxBlk - indexed block
-%% DAG - {Dag, Preds} where Dag is dependence graph and
-%% Preds is number of predecessors for each node.
-%% Returns : Sch
-%% Description : Initializes earliest-list, ready-list, priorities, resources
-%% and so on, and calls the cycle_sched which does the scheduling
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-bb(IxBlk,DAG) ->
- bb(length(IxBlk), IxBlk, DAG).
-
-bb(N,IxBlk,{DAG, Preds}) ->
- Earliest = init_earliest(N),
- BigArray = N*10, % "nothing" is this big :-)
- Ready = hipe_schedule_prio:init_ready(BigArray,Preds),
- I_res = init_instr_resources(N, IxBlk),
-
- Prio = hipe_schedule_prio:init_instr_prio(N,DAG),
- Rsrc = init_resources(BigArray),
- ?debug4("I_res: ~n~p~nPrio: ~n~p~nRsrc: ~n~p~n", [I_res,Prio,Rsrc]),
- ?debug('cycle 1~n',[]),
- Sch = empty_schedule(),
- cycle_sched(1,Ready,DAG,Preds,Earliest,Rsrc,I_res,Prio,Sch,N,IxBlk).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : cycle_sched
-%% Argument : - C is current cycle, 1 or more.
-%% - Ready is an array (Cycle -> [Node])
-%% yielding the collection of nodes ready to be
-%% scheduled in a cycle.
-%% - DAG is an array (Instr -> [{Latency,Instr}])
-%% represents the dependence DAG.
-%% - Preds is an array (Instr -> NumPreds)
-%% counts the number of predecessors
-%% (0 preds = ready to be scheduled).
-%% - Earl is an array (Instr -> EarliestCycle)
-%% holds the earliest cycle an instruction can be scheduled.
-%% - Rsrc is a 'resource ADT' that handles scheduler resource
-%% management checks whether instruction can be scheduled
-%% this cycle without a stall.
-%% - I_res is an array (Instr -> Required_resources)
-%% holds the resources required to schedule an instruction.
-%% - Sch is the representation of the schedule current schedule.
-%% - N is the number of nodes remaining to be scheduled
-%% tells us when to stop the scheduler.
-%% - IxBlk is the indexed block with instrs
-%% Returns : present schedule
-%% Description : Scheduler main loop.
-%% Pick next ready node in priority order for cycle C until
-%% none remain.
-%% * check each node if it can be scheduled w/o stalling
-%% * if so, schedule it
-%% * otherwise, bump the node to the next cycle
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-cycle_sched(C,Ready,DAG,Preds,Earl,Rsrc,I_res,Prio,Sch,N,IxBlk) ->
- case hipe_schedule_prio:next_ready(C,Ready,Prio,IxBlk,DAG,Preds,Earl) of
-% case hipe_schedule_prio:next_ready(C,Ready,Prio,IxBlk) of
- {next,I,Ready1} ->
- ?debug('try ~p~n==> ready = ~p~n',[I, Ready1]),
- case resources_available(C,I,Rsrc,I_res) of
- {yes,NewRsrc} ->
- ?debug(' scheduled~n==> Rscrs = ~p~n',[NewRsrc]),
- NewSch = add_to_schedule(I,C,Sch),
- {ReadyNs,NewDAG,NewPreds,NewEarl} =
- delete_node(C,I,DAG,Preds,Earl),
- ?debug("NewPreds : ~p~n",[Preds]),
- ?debug(' ReadyNs: ~p~n',[ReadyNs]),
- NewReady = hipe_schedule_prio:add_ready_nodes(ReadyNs,
- Ready1),
- ?debug(' New ready: ~p~n',[NewReady]),
- cycle_sched(C,NewReady,NewDAG,NewPreds,NewEarl,
- NewRsrc,I_res,Prio,NewSch,N-1, IxBlk);
- no ->
- ?debug(' resource conflict~n',[]),
- NewReady = hipe_schedule_prio:insert_node(C+1,I,Ready1),
- cycle_sched(C,NewReady,DAG,Preds,Earl,Rsrc,
- I_res,Prio,Sch,N,IxBlk)
- end;
- none -> % schedule next cycle if some node remains
- if
- N > 0 ->
- ?debug('cycle ~p~n',[C+1]),
- cycle_sched(C+1,Ready,DAG,Preds,Earl,
- advance_cycle(Rsrc),
- I_res,Prio,Sch,N, IxBlk);
- true ->
- present_schedule(Sch)
- end
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : init_earliest
-%% Argument : N - number of instrs
-%% Returns :
-%% Description :
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-init_earliest(N) ->
- hipe_vectors:new(N,1).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Schedule is kept reversed until the end.
-
--define(present_node(I,Cycle),{{cycle,Cycle},{node,I}}).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : empty_schedule
-%% Description : Returns an empty schedule.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-empty_schedule() -> [].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : add_to_schedule
-%% Argument : I - instr
-%% Cycle - cycle when I was placed
-%% Sch - schedule
-%% Description : Adds instr to schedule
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-add_to_schedule(I,Cycle,Sch) ->
- [?present_node(I,Cycle)|Sch].
-
-present_schedule(Sch) -> lists:reverse(Sch).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Interface to resource manager:
-%%
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : init_resources
-%% Description : Yields a 'big enough' array mapping (Cycle -> Resources);
-%% this array is called Rsrc below.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-init_resources(S) ->
- hipe_target_machine:init_resources(S).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : init_instr_resources
-%% Argument : Nodes - a list of the instructions
-%% N - is the number of nodes
-%% Description : return a vector (NodeID -> Resource_requirements)
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-init_instr_resources(N,Nodes) ->
- hipe_target_machine:init_instr_resources(N,Nodes).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : resources_available
-%% Argument : Cycle - the current cycle
-%% I - the current instruction (index = NodeID)
-%% Rsrc - a map (Cycle -> Resources)
-%% I_res - maps (NodeID -> Resource_requirements)
-%% Description : returns {yes,NewResTab} | no
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-resources_available(Cycle,I,Rsrc,I_res) ->
- hipe_target_machine:resources_available(Cycle,I,Rsrc,I_res).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : advance_cycle
-%% Argument : Rsrc - resources
-%% Description : Returns an empty resources-state
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-advance_cycle(Rsrc) ->
- hipe_target_machine:advance_cycle(Rsrc).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : delete_node
-%% Argument : Cycle - current cycle
-%% I - index of instr
-%% DAG - dependence dag
-%% Preds - array with number of predecessors for nodes
-%% Earl - array with earliest-times for nodes
-%% Returns : {ReadyNs,NewDAG,NewPreds,NewEarl}
-%% Description : Deletes node I and updates earliest times for the rest.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-delete_node(Cycle,I,DAG,Preds,Earl) ->
- Succ = hipe_vectors:get(DAG,I-1),
- NewDAG = hipe_vectors:set(DAG,I-1,scheduled), % provides debug 'support'
- {ReadyNs,NewPreds,NewEarl} = update_earliest(Succ,Cycle,Preds,Earl,[]),
- ?debug('earliest after ~p: ~p~n',[I,[{Ix+1,V} || {Ix,V} <- hipe_vectors:list(NewEarl)]]),
- {ReadyNs,NewDAG,NewPreds,NewEarl}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : update_earliest
-%% Argument : Succ - successor list
-%% Cycle - current cycle
-%% Preds - predecessors
-%% Earl - earliest times for nodes
-%% Ready - array with readynodes for cycles
-%% Returns : {Ready,Preds,Earl}
-%% Description : Updates the earliest times for nodes and updates number of
-%% predecessors for nodes
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-update_earliest([],_Cycle,Preds,Earl,Ready) ->
- {Ready,Preds,Earl};
-update_earliest([{Lat,N}|Xs],Cycle,Preds,Earl,Ready) ->
- Old_earl = hipe_vectors:get(Earl,N-1),
- New_earl = erlang:max(Old_earl,Cycle+Lat),
- NewEarl = hipe_vectors:set(Earl,N-1,New_earl),
- Num_preds = hipe_vectors:get(Preds,N-1),
- NewPreds = hipe_vectors:set(Preds,N-1,Num_preds-1),
- if
- Num_preds =:= 0 ->
- ?debug('inconsistent DAG~n',[]),
- exit({update_earliest,N});
- Num_preds =:= 1 ->
- NewReady = [{New_earl,N}|Ready],
- NewPreds2 = hipe_vectors:set(NewPreds,N-1,0),
- update_earliest(Xs,Cycle,NewPreds2,NewEarl,NewReady);
- is_integer(Num_preds), Num_preds > 1 ->
- update_earliest(Xs,Cycle,NewPreds,NewEarl,Ready)
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Collect instruction dependences.
-%%
-%% Three forms:
-%% - data/register
-%% * insert RAW, WAR, WAW dependences
-%% - memory
-%% * stores serialize memory references
-%% * alias analysis may allow loads to bypass stores
-%% - control
-%% * unsafe operations are 'trapped' between branches
-%% * branches are ordered
-%%
-%% returns { [{Index,Instr}], DepDAG }
-%% DepDAG is defined below.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : deps
-%% Argument : BB - Basic block
-%% Returns : {IxBB,DAG} - indexed block and dependence graph. DAG consists
-%% of both Dag and Preds, where Preds is number
-%% of predecessors for nodes.
-%% Description : Collect instruction dependences.
-%%
-%% Three forms:
-%% - data/register
-%% * insert RAW, WAR, WAW dependences
-%% - memory
-%% * stores serialize memory references
-%% * alias analysis may allow loads to bypass stores
-%% - control
-%% * unsafe operations are 'trapped' between branches
-%% * branches are ordered
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-deps(IxBB) ->
- N = length(IxBB),
- DAG = empty_dag(N), % The DAG contains both dependence-arcs and
- % number of predeccessors...
- {_DepTab,DAG1} = dd(IxBB, DAG),
- DAG2 = md(IxBB, DAG1),
- cd(IxBB, DAG2).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : empty_dag
-%% Argument : N - number of nodes
-%% Returns : empty DAG
-%% Description : DAG consists of dependence graph and predeccessors
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-empty_dag(N) ->
- {hipe_vectors:new(N, []), hipe_vectors:new(N, 0)}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : indexed_bb
-%% Argument : BB - basic block
-%% Returns : [{N, Instr}]
-%% Description : Puts indexes to all instrs of a block, removes comments.
-%% NOP's are also removed because if both sparc_schedule and
-%% sparc_post_schedule options are used, the first pass will
-%% add nop's before the branch if necessary, and these are
-%% removed before scheduling the second pass.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-indexed_bb(BB) ->
- indexed_bb(BB,1).
-
-indexed_bb([],_N) -> [];
-indexed_bb([X|Xs],N) ->
- case X of
- #comment{} ->
- indexed_bb(Xs,N);
- #nop{} ->
- indexed_bb(Xs,N);
- _Other ->
- [{N,X}|indexed_bb(Xs,N+1)]
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : dep_arc
-%% Argument : N - Current node
-%% Lat - Latency from current node to M
-%% M - The dependent node
-%% DAG - The dependence graph. Consists of both DAG and
-%% predeccessors
-%% Returns : A new DAG with the arc added and number of predeccessors for
-%% M increased.
-%% Description : Adds a new arc to the graph, if an older arc goes from N to M
-%% it will be replaced with a new arc {max(OldLat, NewLat), M}.
-%% Number of predeccessors for node M is increased.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-dep_arc(N, Lat, M, {Dag,Preds}) ->
- OldDeps = hipe_vectors:get(Dag, N-1),
- %% io:format("{OldDeps} = {~p}~n",[OldDeps]),
- {NewDeps, Status} = add_arc(Lat, M, OldDeps),
- %% io:format("{NewDeps, Status} = {~p, ~p}~n",[NewDeps, Status]),
- NewDag = hipe_vectors:set(Dag, N-1, NewDeps),
- NewPreds = case Status of
- added -> % just increase preds if new arc was added
- OldPreds = hipe_vectors:get(Preds, M-1),
- hipe_vectors:set(Preds, M-1, OldPreds + 1);
- non_added ->
- Preds
- end,
- {NewDag, NewPreds}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : add_arc
-%% Argument : Lat - The latency from current node to To.
-%% To - The instr-id of the node which the dependence goes to
-%% Arcs - The dependecies that are already in the dep-graph
-%% Returns : A dependence graph sorted by To.
-%% Description : A new arc that is added is sorted in the right place, and if
-%% there is already an arc between nodes A and B, the one with
-%% the greatest latency is chosen.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-add_arc(Lat,To, []) -> {[{Lat, To}], added};
-add_arc(Lat1, To, [{Lat2, To} | Arcs]) ->
- {[{erlang:max(Lat1, Lat2), To} | Arcs], non_added};
-add_arc(Lat1,To1, [{Lat2, To2} | Arcs]) when To1 < To2 ->
- {[{Lat1, To1}, {Lat2, To2} | Arcs], added};
-add_arc(Lat1 ,To1, [{Lat2, To2} | Arcs]) ->
- {Arcs1, Status} = add_arc(Lat1, To1, Arcs),
- {[{Lat2, To2} | Arcs1], Status}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% The register/data dependence DAG of a block is represented
-%% as a mapping (Variable -> {NextWriter,NextReaders})
-%% where NextWriter is a pair {Ix,Type}
-%% and NextReaders is a list of pairs {Ix,Type}.
-%%
-%% Type is used to determine latencies of operations; on the UltraSparc,
-%% latencies of arcs (n -> m) are determined by both n and m. (E.g., if
-%% n is an integer op and m is a store, then latency is 0; if m is an
-%% integer op, it's 1.)
-
-dd([],DAG) -> { empty_deptab(), DAG };
-dd([{N,I}|Is],DAG0) ->
- {DepTab,DAG1} = dd(Is,DAG0),
- add_deps(N,I,DepTab,DAG1).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : add_deps
-%% Argument : N - current node
-%% Instr - current instr
-%% DepTab - hashtable with {next-writer, next-readers} for reg
-%% DAG - dependence graph
-%% Returns : {DepTab, BlockInfo, DAG} - with new values
-%% Description : Adds dependencies for node N to the graph. The registers that
-%% node N defines and uses are used for computing the
-%% dependencies to the following nodes.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-add_deps(N,Instr,DepTab,DAG) ->
- {Ds,Us} = def_use(Instr),
- Type = dd_type(Instr),
- {DepTab1,DAG1} = add_write_deps(Ds,N,Type,DepTab,DAG),
- add_read_deps(Us,N,Type,DepTab1,DAG1).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Instructions are classified into symbolic categories,
-%% which are subsequently used to determine operation latencies
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-dd_type(Instr) ->
- case Instr of
- #b{} -> branch;
- %% #br{} -> branch;
- #call_link{} -> branch;
- #jmp_link{} -> branch;
- #jmp{} -> branch;
- #goto{} -> branch;
- #load{} -> load;
- #store{} -> store;
- #alu{} -> alu;
- #move{} -> alu;
- #multimove{} ->
- Src = hipe_sparc:multimove_src(Instr),
- Lat = round(length(Src)/2),
- {mmove,Lat};
- #sethi{} -> alu;
- #alu_cc{} -> alu_cc;
- %% #cmov_cc{} -> cmov_cc;
- %% #cmov_r{} -> alu;
- #load_atom{} -> alu;
- #load_address{} -> alu;
- #pseudo_enter{} -> pseudo;
- #pseudo_pop{} -> pseudo;
- #pseudo_return{} -> pseudo;
- #pseudo_spill{} -> pseudo;
- #pseudo_unspill{} -> pseudo
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : add_write_deps
-%% Argument : Defs - registers that node N defines.
-%% N - current node
-%% Ty - the type of current instr
-%% DepTab - Dependence-table
-%% DAG - The dependence graph.
-%% Returns : {DepTab,DAG} - with new values
-%% Description : Adds dependencies to the graph for nodes that depends on the
-%% registers that N defines.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-add_write_deps([],_N,_Ty,DepTab,DAG) -> {DepTab,DAG};
-add_write_deps([D|Ds],N,Ty,DepTab,DAG) ->
- {NewDepTab,NewDAG} = add_write_dep(D,N,Ty,DepTab,DAG),
- add_write_deps(Ds,N,Ty,NewDepTab,NewDAG).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : add_write_dep
-%% Description : Updates the dependence table with N as next writer, and
-%% updates the DAG with the dependencies from N to subsequent
-%% nodes.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-add_write_dep(X,N,Ty,DepTab,DAG) ->
- {NxtWriter,NxtReaders} = lookup(X,DepTab),
- NewDepTab = writer(X,N,Ty,DepTab),
- NewDAG = write_deps(N,Ty,NxtWriter,NxtReaders,DAG),
- {NewDepTab, NewDAG}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : write_deps
-%% Argument : Instr - Current instr
-%% Ty - Type of current instr
-%% NxtWriter - The node that is the next writer of the ragister
-%% that Instr defines.
-%% NxtReaders - The nodes that are subsequent readers of the
-%% register that N defines.
-%% DAG - The dependence graph
-%% Returns : Calls raw_deps that finally returns a new DAG with the new
-%% dependence arcs added.
-%% Description : If a next writer exists a dependence arc for this node is
-%% added, and after this raw_deps is called to compute the
-%% arcs for read-after-write dependencies.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-write_deps(Instr,Ty,NxtWriter,NxtReaders,DAG) ->
- DAG1 = case NxtWriter of
- none ->
- DAG;
- {Instr,_} ->
- DAG;
- {Wr,WrTy} ->
- dep_arc(Instr,
- hipe_target_machine:waw_latency(Ty,WrTy),
- Wr, DAG)
- end,
- raw_deps(Instr,Ty,NxtReaders,DAG1).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : raw_deps
-%% Argument : Instr - current instr
-%% Type - type of instr
-%% Readers - subsequent readers
-%% DAG - dependence graph
-%% Returns : DAG - A new DAG with read-after-write dependencies added
-%% Description : Updates the DAG with the dependence-arcs from Instr to the
-%% subsequent readers, with the appropriate latencies.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-raw_deps(_Instr,_Type,[],DAG) -> DAG;
-raw_deps(Instr,Ty,[{Rd,RdTy}|Xs],DAG) ->
- raw_deps(Instr,Ty,Xs,
- dep_arc(Instr,hipe_target_machine:raw_latency(Ty,RdTy),
- Rd,DAG)).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : add_read_deps
-%% Argument : Uses - The registers that node N uses.
-%% N - Index of the current node.
-%% Ty - Type of current node.
-%% DepTab - Dependence table
-%% DAG - Dependence graph
-%% Returns : {DepTab, DAG} - with updated values.
-%% Description : Adds the read dependencies from node N to subsequent ones,
-%% according to the registers that N uses.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-add_read_deps([],_N,_Ty,DepTab,DAG) -> {DepTab,DAG};
-add_read_deps([U|Us],N,Ty,DepTab,DAG) ->
- {NewDepTab,NewDAG} = add_read_dep(U,N,Ty,DepTab,DAG),
- add_read_deps(Us,N,Ty,NewDepTab,NewDAG).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : add_read_dep
-%% Argument : X - Used register
-%% N - Index of checked instr
-%% Ty - Type of checked instr
-%% DepTab - Hashtable with {next-writer, next-readers}
-%% DAG - Dependence graph
-%% Returns : {DepTab, DAG} - with updated values
-%% Description : Looks up what the next-writer/next-readers are, and adjusts
-%% the table with current node as new reader. Finally
-%% read-dependencies are added to the DAG.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-add_read_dep(X,N,Ty,DepTab,DAG) ->
- {NxtWriter,_NxtReaders} = lookup(X,DepTab),
- NewDepTab = reader(X,N,Ty,DepTab),
- NewDAG = read_deps(N,Ty,NxtWriter,DAG),
- {NewDepTab, NewDAG}.
-
-% If NxtWriter is 'none', then this var is not written subsequently
-% Add WAR from Instr to NxtWriter (if it exists)
-% *** UNFINISHED ***
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : read_deps
-%% Argument : N - Index of current node
-%% Ty - Type of current node
-%% Writer - tuple {NextWriter, WrType} where NextWriter is the
-%% subsequent instr that writes this register next time,
-%% and WrType is the type of that instr.
-%% DAG - The dependence graph
-%% Returns : DAG
-%% Description : Returns a new DAG if a next-writer exists, otherwise the old
-%% DAG is returned.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-read_deps(_Instr,_Ty,none,DAG) ->
- DAG;
-read_deps(_Instr,_Ty,{_Instr,_},DAG) ->
- DAG;
-read_deps(Instr,Ty,{NxtWr,NxtWrTy},DAG) ->
- dep_arc(Instr,hipe_target_machine:war_latency(Ty,NxtWrTy),NxtWr,
- DAG).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : empty_deptab
-%% Description : Creates an empty dependence table (hash-table)
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-empty_deptab() ->
- gb_trees:empty().
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : lookup
-%% Argument : X - key (register)
-%% DepTab - dependence table
-%% Returns : {NextWriter, NextReaders}
-%% Description : Returns next writer and a list of following readers on
-%% register X.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-lookup(X, DepTab) ->
- case gb_trees:lookup(X, DepTab) of
- none ->
- {none, []};
- {value, {W, Rs} = Val} ->
- Val
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : writer
-%% Argument : X - key (register)
-%% N - index of writer
-%% Ty - type of writer
-%% DepTab - dependence table to be updated
-%% Returns : DepTab - new dependence table
-%% Description : Sets N tobe next writer on X
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-writer(X, N, Ty, DepTab) ->
- gb_trees:enter(X, {{N, Ty}, []}, DepTab).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : reader
-%% Argument : X - key (register)
-%% N - index of reader
-%% Ty - type of reader
-%% DepTab - dependence table to be updated
-%% Returns : DepTab - new dependence table
-%% Description : Adds N to the dependence table as a reader.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-reader(X,N,Ty,DepTab) ->
- {W,Rs} = lookup(X,DepTab),
- gb_trees:enter(X,{W,[{N,Ty}|Rs]},DepTab).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% The following version of md/2 separates heap- and stack operations,
-%% which allows for greater reordering.
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : md
-%% Argument : IxBB - indexed block
-%% DAG - dependence graph
-%% Returns : DAG - new dependence graph
-%% Description : Adds arcs for load/store dependencies to the DAG.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-md(IxBB, DAG) ->
- md(IxBB,empty_md_state(),DAG).
-
-md([],_,DAG) -> DAG;
-md([{N,I}|Is],St,DAG) ->
- case md_type(I) of
- other ->
- md(Is,St,DAG);
- {st,T} ->
- { WAW_nodes, WAR_nodes, NewSt } = st_overlap(N,T,St),
- md(Is,NewSt,
- md_war_deps(WAR_nodes,N,md_waw_deps(WAW_nodes,N,DAG)));
- {ld,T} ->
- { RAW_nodes, NewSt } = ld_overlap(N,T,St),
- md(Is,NewSt,
- md_raw_deps(RAW_nodes,N,DAG))
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : md_war_deps
-%% Argument : WAR_nodes - write-after-read nodes depending on N
-%% N - index of current instr
-%% DAG - dependence graph
-%% Returns : DAG - updated DAG
-%% Description : Adds arcs for write-after-read dependencies for N
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-md_war_deps([],_,DAG) -> DAG;
-md_war_deps([M|Ms],N,DAG) ->
- md_war_deps(Ms,N,dep_arc(M,hipe_target_machine:m_war_latency(),N,DAG)).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : md_waw_deps
-%% Argument : WAW_nodes - write-after-write nodes depending on N
-%% N - index of current instr
-%% DAG - dependence graph
-%% Returns : DAG - updated DAG
-%% Description : Adds arcs for write-after-write dependencies for N
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-md_waw_deps([],_,DAG) -> DAG;
-md_waw_deps([M|Ms],N,DAG) ->
- md_waw_deps(Ms,N,dep_arc(M,hipe_target_machine:m_waw_latency(),N,DAG)).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : md_raw_deps
-%% Argument : RAW_nodes - read-after-write nodes depending on N
-%% N - index of current instr
-%% DAG - dependence graph
-%% Returns : DAG - updated DAG
-%% Description : Adds arcs for read-after-write dependencies for N
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-md_raw_deps([],_,DAG) -> DAG;
-md_raw_deps([M|Ms],N,DAG) ->
- md_raw_deps(Ms,N,dep_arc(M,hipe_target_machine:m_raw_latency(),N,DAG)).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : empty_md_state
-%% Description : Returns an empty memorydependence state, eg. 4 lists
-%% representing {StackStores, HeapStores, StackLoads, HeapLoads}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-empty_md_state() -> {[], [], [], []}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : md_type
-%% Argument : I - instr
-%% Description : Maps the instr-type to a simplified type, telling if it's
-%% store/load resp. heap or stack.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-md_type(I) ->
- case I of
- #load{} ->
- Sp = hipe_sparc_registers:stack_pointer(),
- Src = hipe_sparc:load_src(I),
- N = hipe_sparc:reg_nr(Src),
- Off = hipe_sparc:load_off(I),
- if
- N =:= Sp -> % operation on stack
- {ld,{sp,Off}};
- true ->
- {ld,{hp,Src,Off}}
- end;
- #store{} ->
- Sp = hipe_sparc_registers:stack_pointer(),
- Dst = hipe_sparc:store_dest(I),
- N = hipe_sparc:reg_nr(Dst),
- Off = hipe_sparc:store_off(I),
- if
- N =:= Sp ->
- {st,{sp,Off}};
- true ->
- {st,{hp,Dst,Off}}
- end;
- _ ->
- other
- end.
-
-%% Given a memory operation and a 'memory op state',
-%% overlap(N,MemOp,State) returns { Preceding_Dependent_Ops, NewState }.
-%% which are either a tuple { WAW_deps, WAR_deps } or a list RAW_deps.
-%%
-%% NOTES:
-%% Note that Erlang's semantics ("heap stores never overwrite existing data")
-%% means we can be quite free in reordering stores to the heap.
-%% Ld/St to the stack are simply handled by their offsets; since we do not
-%% rename the stack pointer, this is sufficient.
-%% *** We assume all memory ops have uniform size = 4 ***
-%%
-%% NOTES:
-%% The method mentioned above has now been changed because the assumption that
-%% "heap stores never overwrite existing data" caused a bug when the
-%% process-pointer was treated the same way as the heap. We were also told
-%% that the semantics can possibly change in the future, so it would be more
-%% safe to treat the heap store/loads as the stack.
-%% A future improvement can be to do an alias analysis to give more freedom
-%% in reordering stuff...
-%%
-%% Alias state:
-%% { [StackOp], [HeapOp], [StackOp], [HeapOp] }
-%% where StackOp = {InstrID, Offset}
-%% HeapOp = {InstrID, Reg, Offset}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : st_overlap
-%% Argument : N - Index of current node
-%% Type - {sp,Off} or {hp,Dst,Off}, store on stack or heap
-%% State - { [StackStrs], [HeapStrs], [StackLds], [HeapLds] }
-%% where StackStrs/StackLds = {InstrID, Offset}
-%% and HeapStrs/HeapLds = {InstrID, Reg, Offset}
-%% Returns : { DepStrs, DepLds, State } -
-%% where DepStrs/DepLds = [NodeId]
-%% and State is the new state
-%% Description : Adds dependencies for overlapping stores.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-st_overlap(N, {sp, Off}, {St_Sp, St_Hp, Ld_Sp, Ld_Hp}) ->
- {DepSt, IndepSt_Sp} = st_sp_dep(St_Sp, Off),
- {DepLd, IndepLd_Sp} = ld_sp_dep(Ld_Sp, Off),
- {DepSt, DepLd, {[{N, Off}|IndepSt_Sp], St_Hp, IndepLd_Sp, Ld_Hp}};
-st_overlap(N, {hp, Dst, Off}, {St_Sp, St_Hp, Ld_Sp, Ld_Hp}) ->
- DstOff = {Dst, Off},
- {DepSt,_IndepSt_Hp} = st_hp_dep(St_Hp, DstOff),
- {DepLd, IndepLd_Hp} = ld_hp_dep(Ld_Hp, DstOff),
- {DepSt, DepLd, {St_Sp, [{N, Dst, Off}|St_Hp], Ld_Sp, IndepLd_Hp}}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : ld_overlap
-%% Argument : N - Index of current node
-%% Type - {sp,Off} or {hp,Dst,Off}, store on stack or heap
-%% State - { [StackStrs], [HeapStrs], [StackLds], [HeapLds] }
-%% where StackStrs/StackLds = {InstrID, Offset}
-%% and HeapStrs/HeapLds = {InstrID, Reg, Offset}
-%% Returns : { DepStrs, State }
-%% Description : Adds dependencies for overlapping laods
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-ld_overlap(N, {sp, Off}, {St_Sp, St_Hp, Ld_Sp, Ld_Hp}) ->
- DepSt = sp_dep_only(St_Sp, Off),
- {DepSt, {St_Sp, St_Hp, [{N, Off}|Ld_Sp], Ld_Hp}};
-ld_overlap(N, {hp, Src, Off}, {St_Sp, St_Hp, Ld_Sp, Ld_Hp}) ->
- DepSt = hp_dep_only(St_Hp, Src, Off),
- {DepSt, {St_Sp, St_Hp, Ld_Sp, [{N, Src, Off}|Ld_Hp]}}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : st_sp_dep
-%% Description : Adds dependencies that are depending on a stack store
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-st_sp_dep(Stores, Off) ->
- sp_dep(Stores, Off, [], []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : ld_sp_dep
-%% Description : Adds dependencies that are depending on a stack load
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-ld_sp_dep(Loads, Off) ->
- sp_dep(Loads, Off, [], []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : st_hp_dep
-%% Description : Adds dependencies that are depending on a heap store
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-st_hp_dep(Stores, {_Reg, _Off} = RegOff) ->
- hp_dep(Stores, RegOff, [], []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : ld_hp_dep
-%% Description : Adds dependencies that are depending on a heap load
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-ld_hp_dep(Loads, {_Reg, _Off} = RegOff) ->
- hp_dep(Loads, RegOff, [], []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : sp_dep
-%% Description : Returns {Dependent, Independent} which are lists of nodes
-%% that depends or not on a stack load/store
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-sp_dep([], _Off, Dep, Indep) -> {Dep, Indep};
-sp_dep([{N,Off}|Xs], Off, Dep, Indep) ->
- sp_dep(Xs, Off, [N|Dep], Indep);
-sp_dep([X|Xs], Off, Dep, Indep) ->
- sp_dep(Xs, Off, Dep, [X|Indep]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : hp_dep
-%% Description : Returns {Dependent, Independent} which are lists of nodes
-%% that depends or not on a heap load/store
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-hp_dep([], {_Reg,_Off}, Dep, Indep) -> {Dep,Indep};
-hp_dep([{N,Reg,Off1}|Xs], {Reg,Off}, Dep, Indep) when Off1 =/= Off ->
- hp_dep(Xs, {Reg,Off}, Dep, [{N,Reg,Off1}|Indep]);
-hp_dep([{N,_,_}|Xs], {Reg,Off}, Dep, Indep) ->
- hp_dep(Xs, {Reg,Off}, [N|Dep], Indep).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : sp_dep_only
-%% Description : Returns a list of nodes that are depending on a stack store
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-sp_dep_only(Stores, Off) ->
- [N || {N,Off0} <- Stores, Off =:= Off0].
-
-%% Dependences from heap stores to heap loads.
-%% *** UNFINISHED ***
-%% - but works
-%% This is somewhat subtle:
-%% - a heap load can only bypass a heap store if we KNOW it won't
-%% load the stored value
-%% - unfortunately, we do not know the relationships between registers
-%% at this point, so we can't say that store(p+4) is independent of
-%% load(q+0).
-%% (OR CAN WE? A bit closer reasoning might show that it's possible?)
-%% - We can ONLY say that st(p+c) and ld(p+c') are independent when c /= c'
-%%
-%% (As said before, it might be possible to lighten this restriction?)
-
-hp_dep_only([], _Reg, _Off) -> [];
-hp_dep_only([{_N,Reg,Off_1}|Xs], Reg, Off) when Off_1 =/= Off ->
- hp_dep_only(Xs, Reg, Off);
-hp_dep_only([{N,_,_}|Xs], Reg, Off) ->
- [N|hp_dep_only(Xs, Reg, Off)].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Control dependences:
-%% - add dependences so that
-%% * branches are performed in order
-%% * unsafe operations are 'fenced in' by surrounding branches
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : cd
-%% Argument : IxBB - indexed block
-%% DAG - dependence graph
-%% Returns : DAG - new dependence graph
-%% Description : Adds conditional dependencies to the DAG
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-cd(IxBB,DAG) ->
- cd(IxBB, DAG, none, [], []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : cd
-%% Argument : IxBB - indexed block
-%% DAG - dependence graph
-%% PrevBr - previous branch
-%% PrevUnsafe - previous unsafe instr (mem-op)
-%% PrevOthers - previous other instrs, used to "fix" preceeding
-%% instrs so they don't bypass a branch.
-%% Returns : DAG - new dependence graph
-%% Description : Adds conditional dependencies to the graph.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-cd([], DAG, _PrevBr, _PrevUnsafe, _PrevOthers) ->
- DAG;
-cd([{N,I}|Xs], DAG, PrevBr, PrevUnsafe, PrevOthers) ->
- case cd_type(I) of
- {branch,Ty} ->
- DAG1 = cd_branch_to_other_deps(N, PrevOthers, DAG),
- NewDAG = cd_branch_deps(PrevBr, PrevUnsafe, N, Ty, DAG1),
- cd(Xs,NewDAG,{N,Ty},[],[]);
- {unsafe,Ty} ->
- NewDAG = cd_unsafe_deps(PrevBr,N,Ty,DAG),
- cd(Xs, NewDAG, PrevBr, [{N,Ty}|PrevUnsafe], PrevOthers);
- {other,_Ty} ->
- cd(Xs, DAG, PrevBr, PrevUnsafe, [N|PrevOthers])
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : cd_branch_to_other_deps
-%% Argument : N - index of branch
-%% Ms - list of indexes of "others" preceding instrs
-%% DAG - dependence graph
-%% Returns : DAG - new graph
-%% Description : Makes preceding instrs fixed so they don't bypass a branch
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-cd_branch_to_other_deps(_, [], DAG) ->
- DAG;
-cd_branch_to_other_deps(N, [M | Ms], DAG) ->
- cd_branch_to_other_deps(N, Ms, dep_arc(M, zero_latency(), N, DAG)).
-
-%% Is the operation a branch, an unspeculable op or something else?
-
-%% Returns
-%% {branch,BranchType}
-%% {unsafe,OpType}
-%% {other,OpType}
-
-%% *** UNFINISHED ***
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : cd_type
-%% Argument : I - instr
-%% Description : Maps instrs to a simpler type.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-cd_type(I) ->
- case I of
- #goto{} ->
- {branch,uncond};
- #br{} ->
- {branch,'cond'};
- #b{} ->
- {branch,'cond'};
- #call_link{} ->
- {branch,call};
- #jmp_link{} ->
- {branch,call};
- #jmp{} ->
- {branch,call};
- #load{} ->
- {unsafe,load};
- #store{} ->
- {unsafe,load};
- T ->
- {other,T}
- end.
-
-%% add dependences to keep order of branches + unspeculable ops:
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : cd_branch_deps
-%% Argument : PrevBr - preceeding branch
-%% PrevUnsafe - preceeding unsafe ops, eg, mem-ops
-%% N - current id.
-%% Ty - type of current instr
-%% DAG - dependence graph
-%% Returns : DAG - new DAG
-%% Description : Adds arcs between branches and calls deps_to_unsafe that adds
-%% arcs between branches and unsafe ops.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-cd_branch_deps(PrevBr, PrevUnsafe, N, Ty, DAG) ->
- DAG1 = case PrevBr of
- none ->
- DAG;
- {Br,BrTy} ->
- dep_arc(Br,
- hipe_target_machine:br_br_latency(BrTy,Ty),
- N, DAG)
- end,
- deps_to_unsafe(PrevUnsafe, N, Ty, DAG1).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : deps_to_unsafe
-%% Description : Adds dependencies between unsafe's and branches
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-deps_to_unsafe([], _, _, DAG) -> DAG;
-deps_to_unsafe([{M,UTy}|Us], N, Ty, DAG) ->
- deps_to_unsafe(Us,N,Ty,
- dep_arc(M, hipe_target_machine:unsafe_to_br_latency(UTy,Ty),
- N, DAG)).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : cd_unsafe_deps
-%% Description : Adds dependencies between branches and unsafe's
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-cd_unsafe_deps(none, _, _, DAG) ->
- DAG;
-cd_unsafe_deps({Br,BrTy}, N, Ty, DAG) ->
- dep_arc(Br, hipe_target_machine:br_to_unsafe_latency(BrTy, Ty), N, DAG).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : def_use
-%% Argument : Instr
-%% Description : Returns the registers that Instr defines resp. uses as 2 lists
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-def_use(Instr) ->
- {hipe_sparc:defines(Instr), hipe_sparc:uses(Instr)}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : move_or_alu
-%% Description : True if the instruction is a move or an alu; false otherwise
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-move_or_alu(#move{}) -> true;
-move_or_alu(#alu{}) -> true;
-move_or_alu(_) -> false.
-
-%% Debugging stuff below %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
--ifdef(debug1).
-debug1_stuff(Blk, DAG, IxBlk, Sch, X) ->
- io:format("Blk: ~p~n",[Blk]),
- io:format("DAG: ~n~p~n~p",[DAG,IxBlk]),
- io:format("~n"),
- print_instrs(IxBlk),
- print_sch(Sch, IxBlk),
- print_instrs2(X).
-
-print_instrs([]) ->
- io:format("~n");
-print_instrs([{N,Instr} | Instrs]) ->
- io:format("(~p): ",[N]),
- hipe_sparc_pp:pp_instr(Instr),
- io:format("~p~n",[element(1,Instr)]),
- print_instrs(Instrs).
-
-print_instrs2([]) ->
- io:format("~n");
-print_instrs2([Instr | Instrs]) ->
- hipe_sparc_pp:pp_instr(Instr),
- print_instrs2(Instrs).
-
-print_sch([],_) -> io:format("~n");
-print_sch([{{cycle,Cycle},{node,I}} | Rest], IxBlk) ->
- io:format("{C~p, N~p} ",[Cycle,I]),
- print_node(I, IxBlk),
- print_sch(Rest, IxBlk).
-
-print_node(_, []) ->
- io:format("~n");
-print_node(I, [{I, Instr} | _]) ->
- hipe_sparc_pp:pp_instr(Instr);
-print_node(I, [_ | IxBlk]) ->
- print_node(I, IxBlk).
--else.
-debug1_stuff(_Blk, _DAG, _IxBlk, _Sch, _X) ->
- ok.
--endif.
diff --git a/lib/hipe/opt/hipe_schedule_prio.erl b/lib/hipe/opt/hipe_schedule_prio.erl
deleted file mode 100644
index 339bb82aab..0000000000
--- a/lib/hipe/opt/hipe_schedule_prio.erl
+++ /dev/null
@@ -1,53 +0,0 @@
-%% -*- erlang-indent-level: 2 -*-
-%%
-%% 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.
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% PRIORITY HANDLING AND PRIORITY CALCULATION
-%%
-%% Handling of ready nodes and priorities.
-%% - at present, all nodes have the same priority and so on.
-%%
-%% *** UNFINISHED ***
-%% - should compute a static priority estimate
-%% - should dynamically modify priorities + possibly insert NOPs
-%% (e.g., to separate branches, etc.)
-%% - thus, ought to be passed the current schedule and/or resources as well
-
--module(hipe_schedule_prio).
--export([init_ready/2,
- init_instr_prio/2,
- %% initial_ready_set/4,
- next_ready/7,
- add_ready_nodes/2,
- insert_node/3
- ]).
-
-init_ready(Size,Preds) ->
- hipe_ultra_prio:init_ready(Size,Preds).
-
-init_instr_prio(N,DAG) ->
- hipe_ultra_prio:init_instr_prio(N,DAG).
-
-%% initial_ready_set(M,N,Preds,Ready) ->
-%% hipe_ultra_prio:initial_ready_set(M,N,Preds,Ready).
-
-next_ready(C,Ready,Prio,Nodes,DAG,Preds,Earl) ->
- hipe_ultra_prio:next_ready(C,Ready,Prio,Nodes,DAG,Preds,Earl).
-
-add_ready_nodes(NodeLst,Ready) ->
- hipe_ultra_prio:add_ready_nodes(NodeLst,Ready).
-
-insert_node(C,I,Ready) ->
- hipe_ultra_prio:insert_node(C,I,Ready).
diff --git a/lib/hipe/opt/hipe_target_machine.erl b/lib/hipe/opt/hipe_target_machine.erl
deleted file mode 100644
index 75993cb95e..0000000000
--- a/lib/hipe/opt/hipe_target_machine.erl
+++ /dev/null
@@ -1,87 +0,0 @@
-%% 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.
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% INTERFACE TO TARGET MACHINE MODEL
-%%
-%% Interfaces the instruction scheduler to the (resource) machine model.
-
--module(hipe_target_machine).
--export([init_resources/1,
- init_instr_resources/2,
- resources_available/4,
- advance_cycle/1
- ]).
--export([raw_latency/2,
- war_latency/2,
- waw_latency/2,
- %% m_raw_latency/2,
- %% m_war_latency/2,
- %% m_waw_latency/2,
- m_raw_latency/0,
- m_war_latency/0,
- m_waw_latency/0,
- br_to_unsafe_latency/2,
- unsafe_to_br_latency/2,
- br_br_latency/2
- ]).
-
--define(target,hipe_ultra_mod2).
-
-init_resources(X) ->
- ?target:init_resources(X).
-
-init_instr_resources(X,Y) ->
- ?target:init_instr_resources(X,Y).
-
-resources_available(X,Y,Z,W) ->
- ?target:resources_available(X,Y,Z,W).
-
-advance_cycle(X) ->
- ?target:advance_cycle(X).
-
-raw_latency(From,To) ->
- ?target:raw_latency(From,To).
-
-war_latency(From,To) ->
- ?target:war_latency(From,To).
-
-waw_latency(From,To) ->
- ?target:waw_latency(From,To).
-
-%% m_raw_latency(From,To) ->
-%% ?target:m_raw_latency(From,To).
-
-%% m_war_latency(From,To) ->
-%% ?target:m_war_latency(From,To).
-
-%% m_waw_latency(From,To) ->
-%% ?target:m_waw_latency(From,To).
-
-m_raw_latency() ->
- ?target:m_raw_latency().
-
-m_war_latency() ->
- ?target:m_war_latency().
-
-m_waw_latency() ->
- ?target:m_waw_latency().
-
-br_to_unsafe_latency(Br,U) ->
- ?target:br_to_unsafe_latency(Br,U).
-
-unsafe_to_br_latency(U,Br) ->
- ?target:unsafe_to_br_latency(U,Br).
-
-br_br_latency(Br1,Br2) ->
- ?target:br_br_latency(Br1,Br2).
diff --git a/lib/hipe/opt/hipe_ultra_mod2.erl b/lib/hipe/opt/hipe_ultra_mod2.erl
deleted file mode 100644
index cec9c56a1e..0000000000
--- a/lib/hipe/opt/hipe_ultra_mod2.erl
+++ /dev/null
@@ -1,233 +0,0 @@
-%% 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.
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% ULTRASPARC MACHINE MODEL
-%%
-%% This module is used by the scheduler.
-%% The following interface is used:
-%% ...
-%%
-%% NOTES:
-%% - the machine model is simple (on the verge of simplistic)
-%% * all FUs are pipelined => model only one cycle at a time
-%% * instruction latencies are mostly 1
-%% * floating point is left for later (I _think_ it works, but ...)
-%% - conservative: instructions that require multiple resources are
-%% modelled as 'single'; instead, they could reserve IEU+BR or whatever
-%% - possibly inefficient: I think machine state model could be turned into
-%% a bitvector.
-
--module(hipe_ultra_mod2).
--export([init_resources/1,
- init_instr_resources/2,
- resources_available/4,
- advance_cycle/1
- ]).
--export([raw_latency/2,
- war_latency/2,
- waw_latency/2,
- %% m_raw_latency/2,
- %% m_war_latency/2,
- %% m_waw_latency/2,
- m_raw_latency/0,
- m_war_latency/0,
- m_waw_latency/0,
- br_to_unsafe_latency/2,
- unsafe_to_br_latency/2,
- br_br_latency/2
- ]).
-
--include("../sparc/hipe_sparc.hrl").
-
--define(debug(Str,Args),ok).
-%-define(debug(Str,Args),io:format(Str,Args)).
-
--define(debug_ultra(Str,Args),ok).
-%-define(debug_ultra(Str,Args),io:format(Str,Args)).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Straightforward and somewhat simplistic model for UltraSparc:
-%% - only one cycle at a time is modelled
-%% - resources are simplified:
-%% * ieu0, ieu1, ieu, mem, br, single
-%% * per-cycle state = done | { I0, I1, NumI, X, Mem, Br }
-%% * unoptimized representation (could be bit vector)
-
-init_resources(_Size) ->
- ?debug_ultra('init res ~p~n',[_Size]),
- empty_state().
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-init_instr_resources(N,Nodes) ->
- ultra_instr_rsrcs(Nodes,hipe_vectors:new(N, '')).
-
-ultra_instr_rsrcs([],I_res) -> I_res;
-ultra_instr_rsrcs([N|Ns],I_res) ->
- ultra_instr_rsrcs(Ns,ultra_instr_type(N,I_res)).
-
-ultra_instr_type({N,I},I_res) ->
- hipe_vectors:set(I_res,N-1,instr_type(I)).
-
-instr_type(I) ->
- case I of
- #move{} ->
- ieu;
- #multimove{} -> %% TODO: expand multimoves before scheduling
- ieu;
- #alu{} ->
- case hipe_sparc:alu_operator(I) of
- '>>' -> ieu0;
- '<<' -> ieu0;
- _ -> ieu
- end;
- #alu_cc{} ->
- ieu1;
- #sethi{} ->
- ieu;
- #load{} ->
- mem;
- #store{} ->
- mem;
- #b{} ->
- br;
- #br{} ->
- br;
- #goto{} ->
- br;
- #jmp_link{} -> % imprecise; should be mem+br?
- single;
- #jmp{} -> % imprecise
- br;
- #call_link{} -> % imprecise; should be mem+br?
- single;
- #cmov_cc{} -> % imprecise
- single;
- #cmov_r{} -> % imprecise
- single;
- #load_atom{} -> % should be resolved to sethi/or
- single;
- #load_address{} -> % should be resolved to sethi/or
- single;
- #load_word_index{} -> % should be resolved to sethi/or
- single;
- %% uncommon types:
- #label{} ->
- none;
- #nop{} ->
- none;
- #comment{} ->
- none;
- _ ->
- exit({ultrasparc_instr_type,{cant_schedule,I}})
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-resources_available(_Cycle, I, Rsrc, I_res) ->
- res_avail(instruction_resource(I_res, I), Rsrc).
-
-instruction_resource(I_res, I) ->
- hipe_vectors:get(I_res, I-1).
-
-%% The following function checks resource availability.
-%% * all function units are assumed to be fully pipelined, so only
-%% one cycle at a time is modelled.
-%% * for IEU0 and IEU1, these must precede all generic IEU instructions
-%% (handled by X bit)
-%% * at most 2 integer instructions can issue in a cycle
-%% * mem is straightforward
-%% * br closes the cycle (= returns done).
-%% * single requires an entirely empty state and closes the cycle
-
-res_avail(ieu0, { free, I1, NumI, free, Mem, Br })
- when is_integer(NumI), NumI < 2 ->
- { yes, { occ, I1, NumI+1, free, Mem, Br }};
-res_avail(ieu1, { _I0, free, NumI, free, Mem, Br })
- when is_integer(NumI), NumI < 2 ->
- { yes, { free, occ, NumI+1, free, Mem, Br }};
-res_avail(ieu, { I0, I1, NumI, _X, Mem, Br })
- when is_integer(NumI), NumI < 2 ->
- { yes, { I0, I1, NumI+1, occ, Mem, Br }};
-res_avail(mem, { I0, I1, NumI, X, free, Br }) ->
- { yes, { I0, I1, NumI, X, occ, Br }};
-res_avail(br, { _I0, _I1, _NumI, _X, _Mem, free }) ->
- { yes, done };
-res_avail(single, { free, free, 0, free, free, free }) ->
- { yes, done };
-res_avail(_, _) ->
- no.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-advance_cycle(_Rsrc) ->
- empty_state().
-
-empty_state() -> { free, free, 0, free, free, free }.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Latencies are taken from UltraSparc hardware manual
-%%
-%% *** UNFINISHED ***
-%% more precisely, they are taken from my memory of the US-manual
-%% at the moment.
-%%
-%% Note: all ld/st are assumed to hit in the L1 cache (D-cache),
-%% which is sort of imprecise.
-
-raw_latency(alu, store) -> 0;
-raw_latency(load, _) -> 2; % only if load is L1 hit
-raw_latency(alu_cc, b) -> 0;
-raw_latency(_I0, _I1) ->
- 1.
-
-war_latency(_I0, _I1) ->
- 0.
-
-waw_latency(_I0, _I1) ->
- 1.
-
-%% *** UNFINISHED ***
-%% At present, all load/stores are assumed to hit in the L1 cache,
-%% which isn't really satisfying.
-
-%% m_raw_latency(_St, _Ld) ->
-%% 1.
-%%
-%% m_war_latency(_Ld, _St) ->
-%% 1.
-%%
-%% m_waw_latency(_St1, _St2) ->
-%% 1.
-
-%% Use these for 'default latencies' = do not permit reordering.
-
-m_raw_latency() ->
- 1.
-
-m_war_latency() ->
- 1.
-
-m_waw_latency() ->
- 1.
-
-br_to_unsafe_latency(_BrTy, _UTy) ->
- 0.
-
-unsafe_to_br_latency(_UTy, _BrTy) ->
- 0.
-
-br_br_latency(_BrTy1, _BrTy2) ->
- 0.
diff --git a/lib/hipe/opt/hipe_ultra_prio.erl b/lib/hipe/opt/hipe_ultra_prio.erl
deleted file mode 100644
index 6dd240a33a..0000000000
--- a/lib/hipe/opt/hipe_ultra_prio.erl
+++ /dev/null
@@ -1,298 +0,0 @@
-%% 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.
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% PRIORITY HANDLING AND PRIORITY CALCULATION
-%%
-%% Handling of ready nodes and priorities.
-%% Priorities are mainly from the critical path. More priorities are added.
-%% * One version is adding priorities just depending on the instr, so
-%% for example loads get higher priority than stores, and ordered
-%% after reg's and offset for better cache performance.
-%% * The other version gives higher priority to a node that adds more new
-%% nodes to the ready list. This one is maybe not so effectively
-%% implemented, but was added too late for smarter solutions.
-%% One version is commented away
-
--module(hipe_ultra_prio).
--export([init_ready/2,
- init_instr_prio/2,
- %% initial_ready_set/4,
- next_ready/7,
- add_ready_nodes/2,
- insert_node/3
- ]).
-
--include("../sparc/hipe_sparc.hrl").
-
-% At first, only nodes with no predecessors are selected.
-% - if R is empty, there is an error (unless BB itself is empty)
-
-%% Arguments : Size - size of ready-array
-%% Preds - array with number of predecessors for each node
-%% Returns : An array with list of ready-nodes for each cycle.
-
-init_ready(Size, Preds) ->
- P = hipe_vectors:size(Preds),
- Ready = hipe_vectors:new(Size, []),
- R = initial_ready_set(1, P, Preds, []),
- hipe_vectors:set(Ready, 0, R).
-
-init_instr_prio(N, DAG) ->
- critical_path(N, DAG).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : initial_ready_set
-%% Argument : M - current node-index
-%% N - where to stop
-%% Preds - array with number of predecessors for each node
-%% Ready - list with ready-nodes
-%% Returns : Ready - list with ready-nodes
-%% Description : Finds all nodes with no predecessors and adds them to ready.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-initial_ready_set(M, N, Preds, Ready) ->
- if
- M > N ->
- Ready;
- true ->
- case hipe_vectors:get(Preds, M-1) of
- 0 ->
- initial_ready_set(M+1, N, Preds, [M|Ready]);
- V when is_integer(V), V > 0 ->
- initial_ready_set(M+1, N, Preds, Ready)
- end
- end.
-
-%% The following handles the nodes ready to schedule:
-%% 1. select the ready queue of given cycle
-%% 2. if queue empty, return none
-%% 3. otherwise, remove entry with highest priority
-%% and return {next,Highest_Prio,NewReady}
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : next_ready
-%% Argument : C - current cycle
-%% Ready - array with ready nodes
-%% Prio - array with cpath-priorities for all nodes
-%% Nodes - indexed list [{N, Instr}]
-%% Returns : none / {next,Highest_Prio,NewReady}
-%% Description : 1. select the ready queue of given cycle
-%% 2. if queue empty, return none
-%% 3. otherwise, remove entry with highest priority
-%% and return {next,Highest_Prio,NewReady} where Highest_Prio
-%% = Id of instr and NewReady = updated ready-array.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-next_ready(C, Ready, Prio, Nodes, DAG, Preds, Earl) ->
- Curr = hipe_vectors:get(Ready, C-1),
- case Curr of
- [] ->
- none;
- Instrs ->
- {BestI,RestIs} =
- get_best_instr(Instrs, Prio, Nodes, DAG, Preds, Earl, C),
- {next,BestI,hipe_vectors:set(Ready,C-1,RestIs)}
- end.
-
-% next_ready(C,Ready,Prio,Nodes) ->
-% Curr = hipe_vectors:get(Ready,C-1),
-% case Curr of
-% [] ->
-% none;
-% Instrs ->
-% {BestInstr,RestInstrs} = get_best_instr(Instrs, Prio, Nodes),
-% {next,BestInstr,hipe_vectors:set(Ready,C-1,RestInstrs)}
-% end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : get_best_instr
-%% Argument : Instrs - list of node-id's
-%% Prio - array with cpath-priorities for the nodes
-%% Nodes - indexed list [{Id, Instr}]
-%% Returns : {BestSoFar, Rest} - Id of best instr and the rest of id's
-%% Description : Returns the id of the instr that is the best choice.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-get_best_instr([Instr|Instrs], Prio, Nodes, DAG, Preds, Earl, C) ->
- get_best_instr(Instrs, [], Instr, Prio, Nodes, DAG, Preds, Earl, C).
-
-get_best_instr([], Rest, BestSoFar, _Prio, _Nodes, _DAG, _Preds, _Earl, _C) ->
- {BestSoFar, Rest};
-get_best_instr([Instr|Instrs], PassedInstrs, BestSoFar, Prio, Nodes,
- DAG, Preds, Earl, C) ->
- case better(Instr, BestSoFar, Prio, Nodes, DAG, Preds, Earl, C) of
- true ->
- get_best_instr(Instrs, [BestSoFar|PassedInstrs],
- Instr, Prio, Nodes, DAG, Preds, Earl, C);
- false ->
- get_best_instr(Instrs, [Instr|PassedInstrs], BestSoFar, Prio,
- Nodes, DAG, Preds, Earl, C)
- end.
-
-% get_best_instr([Instr|Instrs], Prio, Nodes) ->
-% get_best_instr(Instrs, [], Instr, Prio, Nodes).
-
-% get_best_instr([], Rest, BestSoFar, Prio, Nodes) -> {BestSoFar, Rest};
-% get_best_instr([Instr|Instrs], PassedInstrs, BestSoFar, Prio, Nodes) ->
-% case better(Instr, BestSoFar, Prio, Nodes) of
-% true ->
-% get_best_instr(Instrs, [BestSoFar|PassedInstrs],
-% Instr, Prio, Nodes);
-% false ->
-% get_best_instr(Instrs, [Instr|PassedInstrs],BestSoFar, Prio, Nodes)
-% end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : better
-%% Argument : Instr1 - Id of instr 1
-%% Instr2 - Id of instr 2
-%% Prio - array with cpath-priorities for the nodes
-%% Nodes - indexed list [{Id, Instr}]
-%% Returns : true if Instr1 has higher priority than Instr2
-%% Description : Checks if Instr1 is a better choice than Instr2 for scheduling
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-better(Instr1, Instr2, Prio, Nodes, DAG, Preds, Earl, C) ->
- better_hlp(priority(Instr1, Prio, Nodes, DAG, Preds, Earl, C),
- priority(Instr2, Prio, Nodes, DAG, Preds, Earl, C)).
-
-better_hlp([], []) -> false;
-better_hlp([], [_|_]) -> false;
-better_hlp([_|_], []) -> true;
-better_hlp([X|Xs], [Y|Ys]) -> (X > Y) or ((X =:= Y) and better_hlp(Xs,Ys)).
-
-%%
-%% Returns the instr corresponding to id
-%%
-get_instr(InstrId, [{InstrId,Instr}|_]) -> Instr;
-get_instr(InstrId, [_|Xs]) -> get_instr(InstrId, Xs).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : priority
-%% Argument : InstrId - Id
-%% Prio - array with cpath-priorities for the nodes
-%% Nodes - indexed list [{Id, Instr}]
-%% Returns : PrioList - list of priorities [MostSignificant, LessSign, ...]
-%% Description : Returns a list of priorities where the first element is the
-%% cpath-priority and the rest are added depending on what kind
-%% of instr it is. Used to order loads/stores sequentially and
-%% there is possibility to add whatever stuff...
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-priority(InstrId, Prio, Nodes, DAG, Preds, Earl, C) ->
- {ReadyNodes,_,_,_} = hipe_schedule:delete_node(C,InstrId,DAG,Preds,Earl),
- Instr = get_instr(InstrId, Nodes),
- Prio1 = hipe_vectors:get(Prio, InstrId-1),
- Prio2 = length(ReadyNodes),
- PrioRest =
- case Instr of
- #load_atom{} ->
- [3];
- #move{} ->
- [3];
- #load{} ->
- Src = hipe_sparc:load_src(Instr),
- Off = hipe_sparc:load_off(Instr),
- case hipe_sparc:is_reg(Off) of
- false -> [3,
- -(hipe_sparc:reg_nr(Src)),
- -(hipe_sparc:imm_value(Off))];
- true -> [1]
- end;
- #store{} ->
- Src = hipe_sparc:store_dest(Instr),
- Off = hipe_sparc:store_off(Instr),
- case hipe_sparc:is_reg(Off) of
- false -> [2,
- -(hipe_sparc:reg_nr(Src)),
- -(hipe_sparc:imm_value(Off))];
- true -> [1]
- end;
- _ -> [0]
- end,
- [Prio1,Prio2|PrioRest].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : add_ready_nodes
-%% Argument : Nodes - list of [{Cycle,Id}]
-%% Ready - array of ready nodes for all cycles
-%% Returns : NewReady - updated ready-array
-%% Description : Gets a list of instrs and adds them to the ready-array
-%% to the corresponding cycle.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-add_ready_nodes([], Ready) -> Ready;
-add_ready_nodes([{C,I}|Xs], Ready) ->
- add_ready_nodes(Xs, insert_node(C, I, Ready)).
-
-insert_node(C, I, Ready) ->
- Old = hipe_vectors:get(Ready, C-1),
- hipe_vectors:set(Ready, C-1, [I|Old]).
-
-%%
-%% Computes the latency for the "most expensive" way through the graph
-%% for all nodes. Returns an array of priorities for all nodes.
-%%
-critical_path(N, DAG) ->
- critical_path(1, N, DAG, hipe_vectors:new(N, -1)).
-
-critical_path(M, N, DAG, Prio) ->
- if
- M > N ->
- Prio;
- true ->
- critical_path(M+1, N, DAG, cpath(M, DAG, Prio))
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function : cpath
-%% Argument : M - current node id
-%% DAG - the dependence graph
-%% Prio - array of priorities for all nodes
-%% Returns : Prio - updated prio array
-%% Description : If node has prio -1, it has not been visited
-%% - otherwise, compute priority as max of priorities of
-%% successors (+ latency)
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-cpath(M, DAG, Prio) ->
- InitPrio = hipe_vectors:get(Prio, M-1),
- if
- InitPrio =:= -1 ->
- cpath_node(M, DAG, Prio);
- true ->
- Prio
- end.
-
-cpath_node(N, DAG, Prio) ->
- SuccL = dag_succ(DAG, N),
- {Max, NewPrio} = cpath_succ(SuccL, DAG, Prio),
- hipe_vectors:set(NewPrio, N-1, Max).
-
-cpath_succ(SuccL, DAG, Prio) ->
- cpath_succ(SuccL, DAG, Prio, 0).
-
-%% performs an unnecessary lookup of priority of Succ, but that might
-%% not be such a big deal
-
-cpath_succ([], _DAG, Prio, NodePrio) -> {NodePrio,Prio};
-cpath_succ([{Lat,Succ}|Xs], DAG, Prio, NodePrio) ->
- NewPrio = cpath(Succ, DAG, Prio),
- NewNodePrio = erlang:max(hipe_vectors:get(NewPrio, Succ - 1) + Lat, NodePrio),
- cpath_succ(Xs, DAG, NewPrio, NewNodePrio).
-
-dag_succ(DAG, N) when is_integer(N) ->
- hipe_vectors:get(DAG, N-1).
-
diff --git a/lib/hipe/rtl/Makefile b/lib/hipe/rtl/Makefile
index 5abc9ec049..becdd0b7d8 100644
--- a/lib/hipe/rtl/Makefile
+++ b/lib/hipe/rtl/Makefile
@@ -50,7 +50,7 @@ HIPE_MODULES = hipe_rtl hipe_rtl_cfg \
hipe_rtl_ssa hipe_rtl_ssa_const_prop \
hipe_rtl_cleanup_const hipe_rtl_symbolic hipe_rtl_lcm \
hipe_rtl_ssapre hipe_rtl_binary hipe_rtl_ssa_avail_expr \
- hipe_rtl_arch hipe_tagscheme
+ hipe_rtl_arch hipe_tagscheme hipe_rtl_verify_gcsafe
else
HIPE_MODULES =
endif
diff --git a/lib/hipe/rtl/hipe_rtl.erl b/lib/hipe/rtl/hipe_rtl.erl
index 04c9728d5c..33027f3259 100644
--- a/lib/hipe/rtl/hipe_rtl.erl
+++ b/lib/hipe/rtl/hipe_rtl.erl
@@ -1740,7 +1740,10 @@ pp_reg(Dev, Arg) ->
true ->
pp_hard_reg(Dev, reg_index(Arg));
false ->
- io:format(Dev, "r~w", [reg_index(Arg)])
+ case reg_is_gcsafe(Arg) of
+ true -> io:format(Dev, "rs~w", [reg_index(Arg)]);
+ false -> io:format(Dev, "r~w", [reg_index(Arg)])
+ end
end.
pp_var(Dev, Arg) ->
diff --git a/lib/hipe/rtl/hipe_rtl_binary_construct.erl b/lib/hipe/rtl/hipe_rtl_binary_construct.erl
index 52ea5db382..111dda3d82 100644
--- a/lib/hipe/rtl/hipe_rtl_binary_construct.erl
+++ b/lib/hipe/rtl/hipe_rtl_binary_construct.erl
@@ -168,9 +168,13 @@ gen_rtl(BsOP, Dst, Args, TrueLblName, FalseLblName, SystemLimitLblName, ConstTab
bs_put_utf8 ->
[_Src, _Base, _Offset] = Args,
- NewDsts = get_real(Dst),
- [hipe_rtl:mk_call(NewDsts, bs_put_utf8, Args,
- TrueLblName, FalseLblName, not_remote)];
+ [NewOffs] = get_real(Dst),
+ RetLbl = hipe_rtl:mk_new_label(),
+ [hipe_rtl:mk_call([NewOffs], bs_put_utf8, Args,
+ hipe_rtl:label_name(RetLbl), [], not_remote),
+ RetLbl,
+ hipe_rtl:mk_branch(NewOffs, ne, hipe_rtl:mk_imm(0),
+ TrueLblName, FalseLblName, 0.99)];
bs_utf16_size ->
case Dst of
@@ -195,8 +199,13 @@ gen_rtl(BsOP, Dst, Args, TrueLblName, FalseLblName, SystemLimitLblName, ConstTab
bs_validate_unicode ->
[_Arg] = Args,
- [hipe_rtl:mk_call([], bs_validate_unicode, Args,
- TrueLblName, FalseLblName, not_remote)];
+ [IsUnicode] = create_regs(1),
+ RetLbl = hipe_rtl:mk_new_label(),
+ [hipe_rtl:mk_call([IsUnicode], is_unicode, Args,
+ hipe_rtl:label_name(RetLbl), [], not_remote),
+ RetLbl,
+ hipe_rtl:mk_branch(IsUnicode, ne, hipe_rtl:mk_imm(0),
+ TrueLblName, FalseLblName, 0.99)];
bs_final ->
Zero = hipe_rtl:mk_imm(0),
@@ -354,7 +363,8 @@ not_writable_code(Bin, SizeReg, Dst, Base, Offset, Unit,
allocate_writable(Dst, Base, UsedBytes, TotBytes, TotSize) ->
Zero = hipe_rtl:mk_imm(0),
[NextLbl] = create_lbls(1),
- [EndSubSize, EndSubBitSize, ProcBin] = create_regs(3),
+ [EndSubSize, EndSubBitSize] = create_regs(2),
+ [ProcBin] = create_unsafe_regs(1),
[hipe_rtl:mk_call([Base], bs_allocate, [UsedBytes],
hipe_rtl:label_name(NextLbl), [], not_remote),
NextLbl,
@@ -581,12 +591,12 @@ const_init2(Size, Dst, Base, Offset, TrueLblName) ->
false ->
ByteSize = hipe_rtl:mk_new_reg(),
[hipe_rtl:mk_gctest(?PROC_BIN_WORDSIZE+?SUB_BIN_WORDSIZE),
- hipe_rtl:mk_move(Offset, hipe_rtl:mk_imm(0)),
hipe_rtl:mk_move(ByteSize, hipe_rtl:mk_imm(Size)),
hipe_rtl:mk_call([Base], bs_allocate, [ByteSize],
hipe_rtl:label_name(NextLbl), [], not_remote),
NextLbl,
hipe_tagscheme:create_refc_binary(Base, ByteSize, Dst),
+ hipe_rtl:mk_move(Offset, hipe_rtl:mk_imm(0)),
hipe_rtl:mk_goto(TrueLblName)]
end.
@@ -629,13 +639,12 @@ var_init2(Size, Dst, Base, Offset, TrueLblName, SystemLimitLblName, FalseLblName
Log2WordSize = hipe_rtl_arch:log2_word_size(),
WordSize = hipe_rtl_arch:word_size(),
[ContLbl, HeapLbl, REFCLbl, NextLbl] = create_lbls(4),
- [USize, Tmp] = create_unsafe_regs(2),
+ [USize, Tmp] = create_regs(2),
[get_word_integer(Size, USize, SystemLimitLblName, FalseLblName),
hipe_rtl:mk_branch(USize, leu, hipe_rtl:mk_imm(?MAX_BINSIZE),
hipe_rtl:label_name(ContLbl),
SystemLimitLblName),
ContLbl,
- hipe_rtl:mk_move(Offset, hipe_rtl:mk_imm(0)),
hipe_rtl:mk_branch(USize, leu, hipe_rtl:mk_imm(?MAX_HEAP_BIN_SIZE),
hipe_rtl:label_name(HeapLbl),
hipe_rtl:label_name(REFCLbl)),
@@ -645,6 +654,7 @@ var_init2(Size, Dst, Base, Offset, TrueLblName, SystemLimitLblName, FalseLblName
hipe_rtl:mk_alu(Tmp, Tmp, add, hipe_rtl:mk_imm(?SUB_BIN_WORDSIZE)),
hipe_rtl:mk_gctest(Tmp),
hipe_tagscheme:create_heap_binary(Base, USize, Dst),
+ hipe_rtl:mk_move(Offset, hipe_rtl:mk_imm(0)),
hipe_rtl:mk_goto(TrueLblName),
REFCLbl,
hipe_rtl:mk_gctest(?PROC_BIN_WORDSIZE+?SUB_BIN_WORDSIZE),
@@ -652,6 +662,7 @@ var_init2(Size, Dst, Base, Offset, TrueLblName, SystemLimitLblName, FalseLblName
hipe_rtl:label_name(NextLbl), [], not_remote),
NextLbl,
hipe_tagscheme:create_refc_binary(Base, USize, Dst),
+ hipe_rtl:mk_move(Offset, hipe_rtl:mk_imm(0)),
hipe_rtl:mk_goto(TrueLblName)].
var_init_bits(Size, Dst, Base, Offset, TrueLblName, SystemLimitLblName, FalseLblName) ->
@@ -858,7 +869,7 @@ get_base_offset_size(Binary, SrcBase, SrcOffset, SrcSize, FLName) ->
JoinLbl,
hipe_tagscheme:test_heap_binary(Orig, HeapLblName, REFCLblName),
HeapLbl,
- hipe_rtl:mk_alu(SrcBase, Orig, add, hipe_rtl:mk_imm(?HEAP_BIN_DATA-2)),
+ hipe_tagscheme:get_field_addr_from_term({heap_bin, {data, 0}}, Orig, SrcBase),
hipe_rtl:mk_goto(EndLblName),
REFCLbl,
hipe_tagscheme:get_field_from_term({proc_bin,bytes}, Orig, SrcBase),
@@ -1205,6 +1216,12 @@ is_divisible(Dividend, Divisor, SuccLbl, FailLbl) ->
[hipe_rtl:mk_branch(Dividend, 'and', Mask, eq, SuccLbl, FailLbl, 0.99)];
false ->
%% We need division, fall back to a primop
- [hipe_rtl:mk_call([], is_divisible, [Dividend, hipe_rtl:mk_imm(Divisor)],
- SuccLbl, FailLbl, not_remote)]
+ [Tmp] = create_regs(1),
+ RetLbl = hipe_rtl:mk_new_label(),
+ [hipe_rtl:mk_call([Tmp], is_divisible,
+ [Dividend, hipe_rtl:mk_imm(Divisor)],
+ hipe_rtl:label_name(RetLbl), [], not_remote),
+ RetLbl,
+ hipe_rtl:mk_branch(Tmp, ne, hipe_rtl:mk_imm(0),
+ SuccLbl, FailLbl, 0.99)]
end.
diff --git a/lib/hipe/rtl/hipe_rtl_binary_match.erl b/lib/hipe/rtl/hipe_rtl_binary_match.erl
index 362a52f8fe..4575213838 100644
--- a/lib/hipe/rtl/hipe_rtl_binary_match.erl
+++ b/lib/hipe/rtl/hipe_rtl_binary_match.erl
@@ -730,7 +730,7 @@ get_base(Orig,Base) ->
[hipe_tagscheme:test_heap_binary(Orig, hipe_rtl:label_name(HeapLbl),
hipe_rtl:label_name(REFCLbl)),
HeapLbl,
- hipe_rtl:mk_alu(Base, Orig, 'add', hipe_rtl:mk_imm(?HEAP_BIN_DATA-2)),
+ hipe_tagscheme:get_field_addr_from_term({heap_bin, {data, 0}}, Orig, Base),
hipe_rtl:mk_goto(hipe_rtl:label_name(EndLbl)),
REFCLbl,
get_field_from_term({proc_bin, flags}, Orig, Flags),
@@ -740,7 +740,7 @@ get_base(Orig,Base) ->
WritableLbl,
hipe_rtl:mk_call([], emasculate_binary, [Orig], [], [], 'not_remote'),
NotWritableLbl,
- hipe_rtl:mk_load(Base, Orig, hipe_rtl:mk_imm(?PROC_BIN_BYTES-2)),
+ get_field_from_term({proc_bin, bytes}, Orig, Base),
EndLbl].
extract_matchstate_var(binsize, Ms) ->
@@ -842,12 +842,12 @@ make_dyn_prep(SizeReg, CCode) ->
%%------------------------------------------------------------------------
get_unaligned_int(Dst1, Size, Base, Offset, Shiftr, Type, TrueLblName) ->
- [Reg] = create_regs(1),
+ [Reg] = create_gcsafe_regs(1),
[get_maybe_unaligned_int_to_reg(Reg, Size, Base, Offset, Shiftr, Type),
do_bignum_code(Size, Type, Reg, Dst1, TrueLblName)].
get_maybe_unaligned_int_to_reg(Reg, Size, Base, Offset, Shiftr, Type) ->
- [LowBits] = create_regs(1),
+ [LowBits] = create_gcsafe_regs(1),
[AlignedLbl, UnAlignedLbl, EndLbl] = create_lbls(3),
[hipe_rtl:mk_alub(LowBits, Offset, 'and', hipe_rtl:mk_imm(?LOW_BITS),
eq, hipe_rtl:label_name(AlignedLbl),
@@ -1001,7 +1001,7 @@ do_bignum_code(Size, {Signedness,_}, Src, Dst1, TrueLblName)
end.
signed_bignum(Dst1, Src, TrueLblName) ->
- Tmp1 = hipe_rtl:mk_new_reg(),
+ Tmp1 = hipe_rtl:mk_new_reg_gcsafe(),
BignumLabel = hipe_rtl:mk_new_label(),
[hipe_tagscheme:realtag_fixnum(Dst1, Src),
hipe_tagscheme:realuntag_fixnum(Tmp1, Dst1),
diff --git a/lib/hipe/rtl/hipe_rtl_cleanup_const.erl b/lib/hipe/rtl/hipe_rtl_cleanup_const.erl
index bfa6b9682e..00cc2bcb37 100644
--- a/lib/hipe/rtl/hipe_rtl_cleanup_const.erl
+++ b/lib/hipe/rtl/hipe_rtl_cleanup_const.erl
@@ -69,9 +69,9 @@ cleanup_instr([Const|Left], I, Acc) ->
case I of
X when is_record(X, fp_unop) orelse is_record(X, fp) ->
Fdst = hipe_rtl:mk_new_fpreg(),
- Fconv = hipe_tagscheme:unsafe_untag_float(Fdst, Dst),
+ Fconv = lists:flatten(hipe_tagscheme:unsafe_untag_float(Fdst, Dst)),
NewI = hipe_rtl:subst_uses([{Const, Fdst}], I),
- cleanup_instr(Left, NewI, Fconv ++ [Load|Acc]);
+ cleanup_instr(Left, NewI, lists:reverse(Fconv, [Load|Acc]));
_ ->
NewI = hipe_rtl:subst_uses([{Const, Dst}], I),
cleanup_instr(Left, NewI, [Load|Acc])
diff --git a/lib/hipe/rtl/hipe_rtl_lcm.erl b/lib/hipe/rtl/hipe_rtl_lcm.erl
index 9dcdd05fb1..2c8cc80e56 100644
--- a/lib/hipe/rtl/hipe_rtl_lcm.erl
+++ b/lib/hipe/rtl/hipe_rtl_lcm.erl
@@ -182,42 +182,41 @@ delete_exprs(Code, _, _, []) ->
Code;
delete_exprs(Code, ExprMap, IdMap, [ExprId|Exprs]) ->
Expr = expr_id_map_get_expr(IdMap, ExprId),
- %% Perform a foldl that goes through the code and deletes all
- %% occurences of the expression.
- NewCode =
- lists:reverse
- (lists:foldl(fun(CodeExpr, Acc) ->
- case is_expr(CodeExpr) of
- true ->
- case expr_clear_dst(CodeExpr) =:= Expr of
- true ->
- pp_debug(" Deleting: ", []),
- pp_debug_instr(CodeExpr),
- %% Lookup expression entry.
- Defines =
- case expr_map_lookup(ExprMap, Expr) of
- {value, {_, _, Defs}} ->
- Defs;
- none ->
- exit({?MODULE, expr_map_lookup,
- "expression missing"})
- end,
- MoveCode =
- mk_expr_move_instr(hipe_rtl:defines(CodeExpr),
- Defines),
- pp_debug(" Replacing with: ", []),
- pp_debug_instr(MoveCode),
- [MoveCode|Acc];
- false ->
- [CodeExpr|Acc]
- end;
- false ->
- [CodeExpr|Acc]
- end
- end,
- [], Code)),
+ %% Lookup expression entry.
+ {value, {_, _, Defines}} = expr_map_lookup(ExprMap, Expr),
+ %% Go through the code and deletes all occurences of the expression.
+ NewCode = delete_expr(Code, Expr, Defines, []),
delete_exprs(NewCode, ExprMap, IdMap, Exprs).
+delete_expr([], _Expr, _Defines, Acc) -> lists:reverse(Acc);
+delete_expr([CodeExpr|Code], Expr, Defines, Acc) ->
+ case exp_kill_expr(CodeExpr, [Expr]) of
+ [] -> % Expr was killed; deleting stops here
+ pp_debug(" Stopping before: ", []),
+ pp_debug_instr(CodeExpr),
+ lists:reverse(Acc, [CodeExpr|Code]);
+ [Expr] ->
+ NewCodeExpr =
+ case is_expr(CodeExpr) of
+ true ->
+ case expr_clear_dst(CodeExpr) =:= Expr of
+ true ->
+ pp_debug(" Deleting: ", []),
+ pp_debug_instr(CodeExpr),
+ MoveCode = mk_expr_move_instr(hipe_rtl:defines(CodeExpr),
+ Defines),
+ pp_debug(" Replacing with: ", []),
+ pp_debug_instr(MoveCode),
+ MoveCode;
+ false ->
+ CodeExpr
+ end;
+ false ->
+ CodeExpr
+ end,
+ delete_expr(Code, Expr, Defines, [NewCodeExpr|Acc])
+ end.
+
%%=============================================================================
%% Goes through the given list of expressions and inserts them at
%% appropriate places in the code.
@@ -226,13 +225,12 @@ insert_exprs(CFG, _, _, _, _, BetweenMap, []) ->
insert_exprs(CFG, Pred, Succ, ExprMap, IdMap, BetweenMap, [ExprId|Exprs]) ->
Expr = expr_id_map_get_expr(IdMap, ExprId),
Instr = expr_map_get_instr(ExprMap, Expr),
- case hipe_rtl_cfg:succ(CFG, Pred) of
- [_] ->
+ case try_insert_expr_last(CFG, Pred, Instr) of
+ {ok, NewCFG} ->
pp_debug(" Inserted last: ", []),
pp_debug_instr(Instr),
- NewCFG = insert_expr_last(CFG, Pred, Instr),
insert_exprs(NewCFG, Pred, Succ, ExprMap, IdMap, BetweenMap, Exprs);
- _ ->
+ not_safe ->
case hipe_rtl_cfg:pred(CFG, Succ) of
[_] ->
pp_debug(" Inserted first: ", []),
@@ -252,25 +250,34 @@ insert_exprs(CFG, Pred, Succ, ExprMap, IdMap, BetweenMap, [ExprId|Exprs]) ->
%% Recursively goes through the code in a block and returns a new block
%% with the new code inserted second to last (assuming the last expression
%% is a branch operation).
-insert_expr_last(CFG0, Label, Instr) ->
- Code0 = hipe_bb:code(hipe_rtl_cfg:bb(CFG0, Label)),
- %% FIXME: Use hipe_bb:butlast() instead?
- Code1 = insert_expr_last_work(Label, Instr, Code0),
- hipe_rtl_cfg:bb_add(CFG0, Label, hipe_bb:mk_bb(Code1)).
+try_insert_expr_last(CFG0, Label, Instr) ->
+ case hipe_rtl_cfg:succ(CFG0, Label) of
+ [_] ->
+ Code0 = hipe_bb:code(hipe_rtl_cfg:bb(CFG0, Label)),
+ case insert_expr_last_work(Instr, Code0) of
+ not_safe -> not_safe;
+ Code1 ->
+ {ok, hipe_rtl_cfg:bb_add(CFG0, Label, hipe_bb:mk_bb(Code1))}
+ end;
+ _ -> not_safe
+ end.
%%=============================================================================
%% Recursively goes through the code in a block and returns a new block
%% with the new code inserted second to last (assuming the last expression
%% is a branch operation).
-insert_expr_last_work(_, Instr, []) ->
- %% This case should not happen since this means that block was completely
- %% empty when the function was called. For compatibility we insert it last.
- [Instr];
-insert_expr_last_work(_, Instr, [Code1]) ->
+insert_expr_last_work(_Instr, [#call{}]) ->
+ %% Call instructions clobber all expressions; we must not insert the
+ %% expression before it
+ not_safe;
+insert_expr_last_work(Instr, [Code1]) ->
%% We insert the code next to last.
[Instr, Code1];
-insert_expr_last_work(Label, Instr, [Code|Codes]) ->
- [Code|insert_expr_last_work(Label, Instr, Codes)].
+insert_expr_last_work(Instr, [Code|Codes]) ->
+ case insert_expr_last_work(Instr, Codes) of
+ not_safe -> not_safe;
+ NewCodes -> [Code|NewCodes]
+ end.
%%=============================================================================
%% Inserts expression first in the block for the given label.
@@ -305,7 +312,8 @@ insert_expr_between(CFG0, BetweenMap, Pred, Succ, Instr) ->
{value, Label} ->
pp_debug(" Using existing new bb for edge (~w,~w) with label ~w~n",
[Pred, Succ, Label]),
- {insert_expr_last(CFG0, Label, Instr), BetweenMap}
+ {ok, NewCfg} = try_insert_expr_last(CFG0, Label, Instr),
+ {NewCfg, BetweenMap}
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/hipe/rtl/hipe_rtl_primops.erl b/lib/hipe/rtl/hipe_rtl_primops.erl
index 850a75f71b..ce5433379e 100644
--- a/lib/hipe/rtl/hipe_rtl_primops.erl
+++ b/lib/hipe/rtl/hipe_rtl_primops.erl
@@ -291,6 +291,10 @@ gen_primop({Op,Dst,Args,Cont,Fail}, IsGuard, ConstTab) ->
gen_select_msg(Dst, Cont);
clear_timeout ->
gen_clear_timeout(Dst, GotoCont);
+ recv_mark ->
+ gen_recv_mark(Dst, GotoCont);
+ recv_set ->
+ gen_recv_set(Dst, Cont);
set_timeout ->
%% BIF call: am_set_timeout -> nbif_set_timeout -> hipe_set_timeout
[hipe_rtl:mk_call(Dst, set_timeout, Args, Cont, Fail, not_remote)];
@@ -390,6 +394,10 @@ gen_primop({Op,Dst,Args,Cont,Fail}, IsGuard, ConstTab) ->
end;
debug_native_called ->
[hipe_rtl:mk_call(Dst, Op, Args, Cont, Fail, not_remote)];
+ build_stacktrace ->
+ [hipe_rtl:mk_call(Dst, Op, Args, Cont, Fail, not_remote)];
+ raw_raise ->
+ [hipe_rtl:mk_call(Dst, Op, Args, Cont, Fail, not_remote)];
%% Only names listed above are accepted! MFA:s are not primops!
_ ->
@@ -1064,6 +1072,27 @@ gen_tuple_header(Ptr, Arity) ->
%%%
%%% Receives
+%%% recv_mark is:
+%%% p->msg.saved_last = p->msg.last;
+gen_recv_mark([], GotoCont) ->
+ TmpLast = hipe_rtl:mk_new_reg(),
+ [load_p_field(TmpLast, ?P_MSG_LAST),
+ store_p_field(TmpLast, ?P_MSG_SAVED_LAST),
+ GotoCont].
+
+%%% recv_set is:
+%%% if (p->msg.saved_last)
+%%% p->msg.save = p->msg.saved_last;
+gen_recv_set([], Cont) ->
+ TmpSave = hipe_rtl:mk_new_reg(),
+ TrueLbl = hipe_rtl:mk_new_label(),
+ [load_p_field(TmpSave, ?P_MSG_SAVED_LAST),
+ hipe_rtl:mk_branch(TmpSave, ne, hipe_rtl:mk_imm(0),
+ hipe_rtl:label_name(TrueLbl), Cont),
+ TrueLbl,
+ store_p_field(TmpSave, ?P_MSG_SAVE),
+ hipe_rtl:mk_goto(Cont)].
+
gen_check_get_msg(Dsts, GotoCont, Fail) ->
gen_check_get_msg_outofline(Dsts, GotoCont, Fail).
diff --git a/lib/hipe/rtl/hipe_rtl_varmap.erl b/lib/hipe/rtl/hipe_rtl_varmap.erl
index 375a8f85c0..f34c66ab85 100644
--- a/lib/hipe/rtl/hipe_rtl_varmap.erl
+++ b/lib/hipe/rtl/hipe_rtl_varmap.erl
@@ -105,7 +105,7 @@ icode_var2rtl_var(Var, Map) ->
{reg, IsGcSafe} ->
NewVar =
case IsGcSafe of
- %% true -> hipe_rtl:mk_new_reg_gcsafe();
+ true -> hipe_rtl:mk_new_reg_gcsafe();
false -> hipe_rtl:mk_new_reg()
end,
{NewVar, insert(Var, NewVar, Map)}
diff --git a/lib/hipe/rtl/hipe_rtl_verify_gcsafe.erl b/lib/hipe/rtl/hipe_rtl_verify_gcsafe.erl
new file mode 100644
index 0000000000..01d7e89ccd
--- /dev/null
+++ b/lib/hipe/rtl/hipe_rtl_verify_gcsafe.erl
@@ -0,0 +1,89 @@
+%% -*- mode: erlang; erlang-indent-level: 2 -*-
+%%
+%% 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.
+%%
+-module(hipe_rtl_verify_gcsafe).
+
+-export([check/1]).
+
+-include("../flow/cfg.hrl"). %% needed for the specs
+-include("hipe_rtl.hrl").
+
+check(CFG) ->
+ Liveness = hipe_rtl_liveness:analyze(CFG),
+ put({?MODULE, 'fun'}, CFG#cfg.info#cfg_info.'fun'),
+ lists:foreach(
+ fun(Lb) ->
+ put({?MODULE, label}, Lb),
+ Liveout = hipe_rtl_liveness:liveout(Liveness, Lb),
+ BB = hipe_rtl_cfg:bb(CFG, Lb),
+ check_instrs(lists:reverse(hipe_bb:code(BB)), Liveout)
+ end, hipe_rtl_cfg:labels(CFG)),
+ erase({?MODULE, 'fun'}),
+ erase({?MODULE, label}),
+ erase({?MODULE, instr}),
+ ok.
+
+check_instrs([], _Livein) -> ok;
+check_instrs([I|Is], LiveOut) ->
+ Def = ordsets:from_list(hipe_rtl:defines(I)),
+ Use = ordsets:from_list(hipe_rtl:uses(I)),
+ LiveOver = ordsets:subtract(LiveOut, Def),
+ LiveIn = ordsets:union(LiveOver, Use),
+ case (hipe_rtl:is_call(I)
+ andalso not safe_primop(hipe_rtl:call_fun(I)))
+ orelse is_record(I, gctest)
+ of
+ false -> ok;
+ true ->
+ put({?MODULE, instr}, I),
+ lists:foreach(fun verify_live/1, LiveOver)
+ end,
+ check_instrs(Is, LiveIn).
+
+verify_live(T) ->
+ case hipe_rtl:is_reg(T) of
+ false -> ok;
+ true ->
+ case hipe_rtl:reg_is_gcsafe(T) of
+ true -> ok;
+ false ->
+ error({gcunsafe_live_over_call,
+ get({?MODULE, 'fun'}),
+ {label, get({?MODULE, label})},
+ get({?MODULE, instr}),
+ T})
+ end
+ end.
+
+%% Primops that can't gc
+%% Note: This information is essentially duplicated from hipe_bif_list.m4
+safe_primop(is_divisible) -> true;
+safe_primop(is_unicode) -> true;
+safe_primop(cmp_2) -> true;
+safe_primop(eq_2) -> true;
+safe_primop(bs_allocate) -> true;
+safe_primop(bs_reallocate) -> true;
+safe_primop(bs_utf8_size) -> true;
+safe_primop(bs_get_utf8) -> true;
+safe_primop(bs_put_utf8) -> true;
+safe_primop(bs_utf16_size) -> true;
+safe_primop(bs_get_utf16) -> true;
+safe_primop(bs_validate_unicode_retract) -> true;
+safe_primop(bs_put_small_float) -> true;
+safe_primop(bs_put_bits) -> true;
+safe_primop(emasculate_binary) -> true;
+safe_primop(atomic_inc) -> true;
+%% Not noproc but manually verified
+safe_primop(bs_put_big_integer) -> true;
+safe_primop(_) -> false.
diff --git a/lib/hipe/rtl/hipe_tagscheme.erl b/lib/hipe/rtl/hipe_tagscheme.erl
index 68cbe75e85..737f0ec5e3 100644
--- a/lib/hipe/rtl/hipe_tagscheme.erl
+++ b/lib/hipe/rtl/hipe_tagscheme.erl
@@ -53,7 +53,8 @@
-export([test_subbinary/3, test_heap_binary/3]).
-export([create_heap_binary/3, create_refc_binary/3, create_refc_binary/4]).
-export([create_matchstate/6, convert_matchstate/1, compare_matchstate/4]).
--export([get_field_from_term/3, get_field_from_pointer/3,
+-export([get_field_addr_from_term/3,
+ get_field_from_term/3, get_field_from_pointer/3,
set_field_from_term/3, set_field_from_pointer/3,
extract_matchbuffer/2, extract_binary_bytes/2]).
@@ -76,6 +77,10 @@
-define(TAG_PRIMARY_BOXED, 16#2).
-define(TAG_PRIMARY_IMMED1, 16#3).
+%% Only when ?ERTS_USE_LITERAL_TAG =:= 1
+-define(TAG_PTR_MASK__, 16#7).
+-define(TAG_LITERAL_PTR, 16#4).
+
-define(TAG_IMMED1_SIZE, 4).
-define(TAG_IMMED1_MASK, 16#F).
-define(TAG_IMMED1_PID, ((16#0 bsl ?TAG_PRIMARY_SIZE) bor ?TAG_PRIMARY_IMMED1)).
@@ -157,6 +162,38 @@ tag_cons(Res, X) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ptr_val(Res, X) ->
+ hipe_rtl:mk_alu(Res, X, 'and', hipe_rtl:mk_imm(bnot ?TAG_PTR_MASK__)).
+
+%% Returns {Base, Offset, Untag}. To be used like, for example:
+%% {Base, Offset, Untag} = untag_ptr(X, ?TAG_PRIMARY_BOXED),
+%% ...
+%% [Untag, hipe_rtl:mk_load(Dst, Base, hipe_rtl:mk_imm(Offset))].
+%%
+%% NB: Base might either be X or a new temp. It must thus not be modified.
+untag_ptr(X, Tag) ->
+ case ?ERTS_USE_LITERAL_TAG of
+ 0 ->
+ {X, -Tag, []};
+ 1 ->
+ Base = hipe_rtl:mk_new_reg(),
+ Untag = ptr_val(Base, X),
+ {Base, 0, Untag}
+ end.
+
+untag_ptr_nooffset(Dst, X, Tag) ->
+ %% We could just use ptr_val in all cases, but subtraction can use LEA on x86
+ %% and can be inlined into effective address computations on several
+ %% architectures.
+ case ?ERTS_USE_LITERAL_TAG of
+ 0 ->
+ hipe_rtl:mk_alu(Dst, X, 'sub', hipe_rtl:mk_imm(Tag));
+ 1 ->
+ ptr_val(Dst, X)
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
%%% Operations to test if an object has a known type T.
test_nil(X, TrueLab, FalseLab, Pred) ->
@@ -171,7 +208,8 @@ test_is_boxed(X, TrueLab, FalseLab, Pred) ->
hipe_rtl:mk_branch(X, 'and', Mask, 'eq', TrueLab, FalseLab, Pred).
get_header(Res, X) ->
- hipe_rtl:mk_load(Res, X, hipe_rtl:mk_imm(-(?TAG_PRIMARY_BOXED))).
+ {Base, Offset, Untag} = untag_ptr(X, ?TAG_PRIMARY_BOXED),
+ [Untag, hipe_rtl:mk_load(Res, Base, hipe_rtl:mk_imm(Offset))].
mask_and_compare(X, Mask, Value, TrueLab, FalseLab, Pred) ->
Tmp = hipe_rtl:mk_new_reg_gcsafe(),
@@ -617,21 +655,25 @@ test_either_immed(Arg1, Arg2, TrueLab, FalseLab) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
unsafe_car(Dst, Arg) ->
- hipe_rtl:mk_load(Dst, Arg, hipe_rtl:mk_imm(-(?TAG_PRIMARY_LIST))).
+ {Base, Offset, Untag} = untag_ptr(Arg, ?TAG_PRIMARY_LIST),
+ [Untag, hipe_rtl:mk_load(Dst, Base, hipe_rtl:mk_imm(Offset))].
unsafe_cdr(Dst, Arg) ->
+ {Base, Offset, Untag} = untag_ptr(Arg, ?TAG_PRIMARY_LIST),
WordSize = hipe_rtl_arch:word_size(),
- hipe_rtl:mk_load(Dst, Arg, hipe_rtl:mk_imm(-(?TAG_PRIMARY_LIST)+WordSize)).
+ [Untag, hipe_rtl:mk_load(Dst, Base, hipe_rtl:mk_imm(Offset+WordSize))].
unsafe_constant_element(Dst, Index, Tuple) -> % Index is an immediate
WordSize = hipe_rtl_arch:word_size(),
- Offset = -(?TAG_PRIMARY_BOXED) + WordSize * hipe_rtl:imm_value(Index),
- hipe_rtl:mk_load(Dst, Tuple, hipe_rtl:mk_imm(Offset)).
+ {Base, Offset0, Untag} = untag_ptr(Tuple, ?TAG_PRIMARY_BOXED),
+ Offset = Offset0 + WordSize * hipe_rtl:imm_value(Index),
+ [Untag, hipe_rtl:mk_load(Dst, Base, hipe_rtl:mk_imm(Offset))].
unsafe_update_element(Tuple, Index, Value) -> % Index is an immediate
WordSize = hipe_rtl_arch:word_size(),
- Offset = -(?TAG_PRIMARY_BOXED) + WordSize * hipe_rtl:imm_value(Index),
- hipe_rtl:mk_store(Tuple, hipe_rtl:mk_imm(Offset), Value).
+ {Base, Offset0, Untag} = untag_ptr(Tuple, ?TAG_PRIMARY_BOXED),
+ Offset = Offset0 + WordSize * hipe_rtl:imm_value(Index),
+ [Untag, hipe_rtl:mk_store(Base, hipe_rtl:mk_imm(Offset), Value)].
%%% wrong semantics
%% unsafe_variable_element(Dst, Index, Tuple) -> % Index is an unknown fixnum
@@ -644,10 +686,12 @@ unsafe_update_element(Tuple, Index, Value) -> % Index is an immediate
%% Tmp1 = hipe_rtl:mk_new_reg_gcsafe(),
%% Tmp2 = hipe_rtl:mk_new_reg_gcsafe(),
%% Shift = ?TAG_IMMED1_SIZE - 2,
-%% OffAdj = (?TAG_IMMED1_SMALL bsr Shift) + ?TAG_PRIMARY_BOXED,
+%% {Base, Off0, Untag} = untag_ptr(Tuple, ?TAG_PRIMARY_BOXED),
+%% OffAdj = (?TAG_IMMED1_SMALL bsr Shift) - Off0,
%% [hipe_rtl:mk_alu(Tmp1, Index, 'srl', hipe_rtl:mk_imm(Shift)),
%% hipe_rtl:mk_alu(Tmp2, Tmp1, 'sub', hipe_rtl:mk_imm(OffAdj)),
-%% hipe_rtl:mk_load(Dst, Tuple, Tmp2)].
+%% Untag,
+%% hipe_rtl:mk_load(Base, Tuple, Tmp2)].
element(Dst, Index, Tuple, FailLabName, {tuple, A}, IndexInfo) ->
FixnumOkLab = hipe_rtl:mk_new_label(),
@@ -660,7 +704,7 @@ element(Dst, Index, Tuple, FailLabName, {tuple, A}, IndexInfo) ->
Offset = hipe_rtl:mk_new_reg_gcsafe(),
Ptr = hipe_rtl:mk_new_reg(), % offset from Tuple
[untag_fixnum(UIndex, Index),
- hipe_rtl:mk_alu(Ptr, Tuple, 'sub', hipe_rtl:mk_imm(?TAG_PRIMARY_BOXED)),
+ untag_ptr_nooffset(Ptr, Tuple, ?TAG_PRIMARY_BOXED),
hipe_rtl:mk_alu(Offset, UIndex, 'sll',
hipe_rtl:mk_imm(hipe_rtl_arch:log2_word_size())),
hipe_rtl:mk_load(Dst, Ptr, Offset)];
@@ -769,7 +813,7 @@ gen_element_tail(Dst, Tuple, Arity, UIndex, FailLabName, IndexOkLab) ->
hipe_rtl:mk_branch(ZeroIndex, 'geu', Arity, FailLabName,
hipe_rtl:label_name(IndexOkLab), 0.01),
IndexOkLab,
- hipe_rtl:mk_alu(Ptr, Tuple, 'sub', hipe_rtl:mk_imm(?TAG_PRIMARY_BOXED)),
+ untag_ptr_nooffset(Ptr, Tuple, ?TAG_PRIMARY_BOXED),
hipe_rtl:mk_alu(Offset, UIndex, 'sll',
hipe_rtl:mk_imm(hipe_rtl_arch:log2_word_size())),
hipe_rtl:mk_load(Dst, Ptr, Offset)].
@@ -777,11 +821,13 @@ gen_element_tail(Dst, Tuple, Arity, UIndex, FailLabName, IndexOkLab) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
unsafe_closure_element(Dst, Index, Closure) -> % Index is an immediate
- Offset = -(?TAG_PRIMARY_BOXED) %% Untag
+ %% XXX: Can there even be closure literals?
+ {Base, Offset0, Untag} = untag_ptr(Closure, ?TAG_PRIMARY_BOXED),
+ Offset = Offset0 %% Untag
+ ?EFT_ENV %% Field offset
%% Index from 1 to N hence -1)
+ (hipe_rtl_arch:word_size() * (hipe_rtl:imm_value(Index)-1)),
- hipe_rtl:mk_load(Dst, Closure, hipe_rtl:mk_imm(Offset)).
+ [Untag, hipe_rtl:mk_load(Dst, Base, hipe_rtl:mk_imm(Offset))].
mk_fun_header() ->
hipe_rtl:mk_imm(?HEADER_FUN).
@@ -790,7 +836,7 @@ tag_fun(Res, X) ->
tag_boxed(Res, X).
%% untag_fun(Res, X) ->
-%% hipe_rtl:mk_alu(Res, X, 'sub', hipe_rtl:mk_imm(?TAG_PRIMARY_BOXED)).
+%% untag_ptr_nooffset(Res, X, ?TAG_PRIMARY_BOXED).
if_fun_get_arity_and_address(ArityReg, AddressReg, FunP, BadFunLab, Pred) ->
%% EmuAddressPtrReg = hipe_rtl:mk_new_reg(),
@@ -801,15 +847,15 @@ if_fun_get_arity_and_address(ArityReg, AddressReg, FunP, BadFunLab, Pred) ->
TrueLab0 = hipe_rtl:mk_new_label(),
%% TrueLab1 = hipe_rtl:mk_new_label(),
IsFunCode = test_closure(FunP, hipe_rtl:label_name(TrueLab0), BadFunLab, Pred),
+ {Base, Offset, Untag} = untag_ptr(FunP, ?TAG_PRIMARY_BOXED),
GetArityCode =
[TrueLab0,
%% Funp->arity contains the arity
- hipe_rtl:mk_load(ArityReg, FunP,
- hipe_rtl:mk_imm(-(?TAG_PRIMARY_BOXED)+
- ?EFT_ARITY)),
- hipe_rtl:mk_load(FEPtrReg, FunP,
- hipe_rtl:mk_imm(-(?TAG_PRIMARY_BOXED)+
- ?EFT_FE)),
+ Untag,
+ hipe_rtl:mk_load(ArityReg, Base,
+ hipe_rtl:mk_imm(Offset+?EFT_ARITY)),
+ hipe_rtl:mk_load(FEPtrReg, Base,
+ hipe_rtl:mk_imm(Offset+?EFT_FE)),
hipe_rtl:mk_load(AddressReg, FEPtrReg,
hipe_rtl:mk_imm(?EFE_NATIVE_ADDRESS))],
IsFunCode ++ GetArityCode.
@@ -927,20 +973,24 @@ test_subbinary(Binary, TrueLblName, FalseLblName) ->
unsafe_load_float(DstLo, DstHi, Src) ->
WordSize = hipe_rtl_arch:word_size(),
- Offset1 = -(?TAG_PRIMARY_BOXED) + WordSize,
+ {Base, Offset0, Untag} = untag_ptr(Src, ?TAG_PRIMARY_BOXED),
+ Offset1 = Offset0 + WordSize,
Offset2 = Offset1 + 4, %% This should really be 4 and not WordSize
case hipe_rtl_arch:endianess() of
little ->
- [hipe_rtl:mk_load(DstLo, Src, hipe_rtl:mk_imm(Offset1), int32, unsigned),
- hipe_rtl:mk_load(DstHi, Src, hipe_rtl:mk_imm(Offset2), int32, unsigned)];
+ [Untag,
+ hipe_rtl:mk_load(DstLo, Base, hipe_rtl:mk_imm(Offset1), int32, unsigned),
+ hipe_rtl:mk_load(DstHi, Base, hipe_rtl:mk_imm(Offset2), int32, unsigned)];
big ->
- [hipe_rtl:mk_load(DstHi, Src, hipe_rtl:mk_imm(Offset1), int32, unsigned),
- hipe_rtl:mk_load(DstLo, Src, hipe_rtl:mk_imm(Offset2), int32, unsigned)]
+ [Untag,
+ hipe_rtl:mk_load(DstHi, Base, hipe_rtl:mk_imm(Offset1), int32, unsigned),
+ hipe_rtl:mk_load(DstLo, Base, hipe_rtl:mk_imm(Offset2), int32, unsigned)]
end.
unsafe_untag_float(Dst, Src) ->
- Offset = -(?TAG_PRIMARY_BOXED) + hipe_rtl_arch:word_size(),
- [hipe_rtl:mk_fload(Dst, Src, hipe_rtl:mk_imm(Offset))].
+ {Base, Offset0, Untag} = untag_ptr(Src, ?TAG_PRIMARY_BOXED),
+ Offset = Offset0 + hipe_rtl_arch:word_size(),
+ [Untag, hipe_rtl:mk_fload(Dst, Base, hipe_rtl:mk_imm(Offset))].
unsafe_tag_float(Dst, Src) ->
{GetHPInsn, HP, PutHPInsn} = hipe_rtl_arch:heap_pointer(),
@@ -999,8 +1049,9 @@ get_one_word_pos_bignum(USize, Size, Fail) ->
unsafe_get_one_word_pos_bignum(USize, Size) ->
WordSize = hipe_rtl_arch:word_size(),
- Imm = hipe_rtl:mk_imm(1*WordSize-?TAG_PRIMARY_BOXED),
- [hipe_rtl:mk_load(USize, Size, Imm)].
+ {Base, Offset, Untag} = untag_ptr(Size, ?TAG_PRIMARY_BOXED),
+ Imm = hipe_rtl:mk_imm(1*WordSize+Offset),
+ [Untag, hipe_rtl:mk_load(USize, Base, Imm)].
-spec bignum_sizeneed(non_neg_integer()) -> non_neg_integer().
@@ -1040,7 +1091,7 @@ create_matchstate(Max, BinSize, Base, Offset, Orig, Ms) ->
SizeInWords = ((ByteSize div WordSize) - 1),
Header = hipe_rtl:mk_imm(mk_header(SizeInWords, ?TAG_HEADER_BIN_MATCHSTATE)),
[GetHPInsn,
- hipe_rtl:mk_alu(Ms, HP, add, hipe_rtl:mk_imm(?TAG_PRIMARY_BOXED)),
+ tag_boxed(Ms, HP),
set_field_from_term({matchstate,thing_word}, Ms, Header),
set_field_from_term({matchstate,{matchbuffer,orig}}, Ms, Orig),
set_field_from_term({matchstate,{matchbuffer,base}}, Ms, Base),
@@ -1078,7 +1129,10 @@ convert_matchstate(Ms) ->
size_from_header(SizeInWords, Header),
hipe_rtl:mk_alu(Hole, SizeInWords, sub, hipe_rtl:mk_imm(?SUB_BIN_WORDSIZE)),
mk_var_header(BigIntHeader, Hole, ?TAG_HEADER_POS_BIG),
- hipe_rtl:mk_store(Ms, hipe_rtl:mk_imm(?SUB_BIN_WORDSIZE*WordSize-?TAG_PRIMARY_BOXED),
+ %% Matchstates can't be literals; so untagging with ?TAG_PRIMARY_BOXED is
+ %% fine here
+ hipe_rtl:mk_store(Ms, hipe_rtl:mk_imm(?SUB_BIN_WORDSIZE*WordSize
+ -?TAG_PRIMARY_BOXED),
BigIntHeader)].
compare_matchstate(Max, Ms, LargeEnough, TooSmall) ->
@@ -1087,8 +1141,10 @@ compare_matchstate(Max, Ms, LargeEnough, TooSmall) ->
SizeInWords = ((ByteSize div WordSize) - 1),
Header = hipe_rtl:mk_imm(mk_header(SizeInWords, ?TAG_HEADER_BIN_MATCHSTATE)),
RealHeader = hipe_rtl:mk_new_reg_gcsafe(),
- [hipe_rtl:mk_load(RealHeader, Ms, hipe_rtl:mk_imm(-?TAG_PRIMARY_BOXED)),
- hipe_rtl:mk_branch(RealHeader, ge, Header, LargeEnough, TooSmall)].
+ %% Matchstates can't be literals; so untagging with ?TAG_PRIMARY_BOXED is fine
+ %% here
+ [hipe_rtl:mk_load(RealHeader, Ms, hipe_rtl:mk_imm(-?TAG_PRIMARY_BOXED)),
+ hipe_rtl:mk_branch(RealHeader, ge, Header, LargeEnough, TooSmall)].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
@@ -1207,15 +1263,22 @@ get_field_size1({matchbuffer, base}) ->
get_field_size1({matchbuffer, binsize}) ->
?MB_SIZE_SIZE.
+get_field_addr_from_term(Struct, Term, Dst) ->
+ {Base, Offset0, Untag} = untag_ptr(Term, ?TAG_PRIMARY_BOXED),
+ Offset = hipe_rtl:mk_imm(get_field_offset(Struct) + Offset0),
+ [Untag, hipe_rtl:mk_alu(Dst, Base, add, Offset)].
+
get_field_from_term(Struct, Term, Dst) ->
- Offset = hipe_rtl:mk_imm(get_field_offset(Struct) - ?TAG_PRIMARY_BOXED),
+ {Base, Offset0, Untag} = untag_ptr(Term, ?TAG_PRIMARY_BOXED),
+ Offset = hipe_rtl:mk_imm(get_field_offset(Struct) + Offset0),
Size = get_field_size(Struct),
- hipe_rtl:mk_load(Dst, Term, Offset, Size, unsigned).
+ [Untag, hipe_rtl:mk_load(Dst, Base, Offset, Size, unsigned)].
set_field_from_term(Struct, Term, Value) ->
- Offset = hipe_rtl:mk_imm(get_field_offset(Struct) - ?TAG_PRIMARY_BOXED),
+ {Base, Offset0, Untag} = untag_ptr(Term, ?TAG_PRIMARY_BOXED),
+ Offset = hipe_rtl:mk_imm(get_field_offset(Struct) + Offset0),
Size = get_field_size(Struct),
- hipe_rtl:mk_store(Term, Offset, Value, Size).
+ [Untag, hipe_rtl:mk_store(Base, Offset, Value, Size)].
get_field_from_pointer(Struct, Term, Dst) ->
Offset = hipe_rtl:mk_imm(get_field_offset(Struct)),
@@ -1229,6 +1292,8 @@ set_field_from_pointer(Struct, Term, Value) ->
extract_matchbuffer(Mb, Ms) ->
What = {matchstate, matchbuffer},
+ %% Matchstates can't be literals; so untagging with ?TAG_PRIMARY_BOXED is fine
+ %% here
Offset = hipe_rtl:mk_imm(get_field_offset(What) - ?TAG_PRIMARY_BOXED),
hipe_rtl:mk_alu(Mb, Ms, add, Offset).
diff --git a/lib/hipe/ssa/hipe_ssa.inc b/lib/hipe/ssa/hipe_ssa.inc
index c7c1a8e1d7..29e8b92266 100644
--- a/lib/hipe/ssa/hipe_ssa.inc
+++ b/lib/hipe/ssa/hipe_ssa.inc
@@ -463,20 +463,20 @@ updateStatementDefs([], Statement, Current, Acc) ->
%%----------------------------------------------------------------------
updateIndices(Current, Variable) ->
- case ?CODE:is_var(Variable) of
- true ->
- NewVar = ?CODE:mk_new_var(),
- {NewVar,gb_trees:enter(Variable, NewVar, Current)};
- false ->
- case is_fp_temp(Variable) of
- true ->
- NewFVar = mk_new_fp_temp(),
- {NewFVar,gb_trees:enter(Variable, NewFVar, Current)};
- false ->
- NewReg = ?CODE:mk_new_reg(),
- {NewReg,gb_trees:enter(Variable, NewReg, Current)}
- end
- end.
+ New =
+ case ?CODE:is_var(Variable) of
+ true -> ?CODE:mk_new_var();
+ false ->
+ case is_fp_temp(Variable) of
+ true -> mk_new_fp_temp();
+ false ->
+ case ?CODE:reg_is_gcsafe(Variable) of
+ true -> ?CODE:mk_new_reg_gcsafe();
+ false -> ?CODE:mk_new_reg()
+ end
+ end
+ end,
+ {New, gb_trees:enter(Variable, New, Current)}.
%%----------------------------------------------------------------------
%% Procedure : updateSuccPhi/4
diff --git a/lib/hipe/test/Makefile b/lib/hipe/test/Makefile
index 544888719f..efeb0887ab 100644
--- a/lib/hipe/test/Makefile
+++ b/lib/hipe/test/Makefile
@@ -7,7 +7,8 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
MODULES= \
hipe_SUITE \
- opt_verify_SUITE
+ opt_verify_SUITE \
+ erl_types_SUITE
# .erl files for these modules are automatically generated
GEN_MODULES= \
diff --git a/lib/hipe/test/basic_SUITE_data/basic_exceptions.erl b/lib/hipe/test/basic_SUITE_data/basic_exceptions.erl
index 229a0516dc..ba9c03d4ba 100644
--- a/lib/hipe/test/basic_SUITE_data/basic_exceptions.erl
+++ b/lib/hipe/test/basic_SUITE_data/basic_exceptions.erl
@@ -6,12 +6,13 @@
%%%-------------------------------------------------------------------
-module(basic_exceptions).
--export([test/0, test_catches/0]).
+-export([test/0]).
%% functions used as arguments to spawn/3
-export([bad_guy/2]).
test() ->
+ ok = test_catches(),
ok = test_catch_exit(42),
ok = test_catch_throw(42),
ok = test_catch_element(),
@@ -22,6 +23,8 @@ test() ->
ok = test_pending_errors(),
ok = test_bad_fun_call(),
ok = test_guard_bif(),
+ ok = test_eclectic(),
+ ok = test_raise(),
ok.
%%--------------------------------------------------------------------
@@ -463,3 +466,213 @@ guard_bif('node/0', X, Y) when node() == Y ->
{'node/0', X, Y};
guard_bif('node/1', X, Y) when node(X) == Y ->
{'node/1', X, Y}.
+
+%%--------------------------------------------------------------------
+%% Taken from trycatch_SUITE.erl (compiler test suite).
+%%
+%% Cases that are commented out contain exception information that was
+%% added to Erlang/OTP in commit e8d45ae14c6c3bdfcbbc7964228b004ef4f11ea6
+%% (May 2017) only in the BEAM emulator. Thus, part of this test fails
+%% when compiled in native code.
+%% The remaining cases are uncommented so that they are properly tested
+%% in native code too.
+%%--------------------------------------------------------------------
+
+test_eclectic() ->
+ V = {make_ref(),3.1415926535,[[]|{}]},
+ {{value,{value,V},V},V} =
+ eclectic_1({foo,{value,{value,V}}}, undefined, {value,V}),
+ {{'EXIT',{V,[{?MODULE,foo,1,_}|_]}},V} =
+ eclectic_1({catch_foo,{error,V}}, undefined, {value,V}),
+ {{error,{exit,V},{'EXIT',V}},V} =
+ eclectic_1({foo,{error,{exit,V}}}, error, {value,V}),
+ %% {{value,{value,V},V},
+ %% {'EXIT',{badarith,[{erlang,'+',[0,a],_},{?MODULE,my_add,2,_}|_]}}} =
+ %% eclectic_1({foo,{value,{value,V}}}, undefined, {'add',{0,a}}),
+ {{'EXIT',V},V} =
+ eclectic_1({catch_foo,{exit,V}}, undefined, {throw,V}),
+ %% {{error,{'div',{1,0}},{'EXIT',{badarith,[{erlang,'div',[1,0],_},{?MODULE,my_div,2,_}|_]}}},
+ %% {'EXIT',V}} =
+ %% eclectic_1({foo,{error,{'div',{1,0}}}}, error, {exit,V}),
+ {{{error,V},{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},
+ {'EXIT',V}} =
+ eclectic_1({catch_foo,{throw,{error,V}}}, undefined, {exit,V}),
+ %%
+ {{value,{value,{value,V},V}},V} =
+ eclectic_2({value,{value,V}}, undefined, {value,V}),
+ {{value,{throw,{value,V},V}},V} =
+ eclectic_2({throw,{value,V}}, throw, {value,V}),
+ {{caught,{'EXIT',V}},undefined} =
+ eclectic_2({value,{value,V}}, undefined, {exit,V}),
+ {{caught,{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},undefined} =
+ eclectic_2({error,{value,V}}, throw, {error,V}),
+ %% The following fails in native code
+ %% %% {{caught,{'EXIT',{badarg,[{erlang,abs,[V],_}|_]}}},V} =
+ %% %% eclectic_2({value,{'abs',V}}, undefined, {value,V}),
+ %% {{caught,{'EXIT',{badarith,[{erlang,'+',[0,a],_},{?MODULE,my_add,2,_}|_]}}},V} =
+ %% eclectic_2({exit,{'add',{0,a}}}, exit, {value,V}),
+ {{caught,{'EXIT',V}},undefined} =
+ eclectic_2({value,{error,V}}, undefined, {exit,V}),
+ {{caught,{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},undefined} =
+ eclectic_2({throw,{'div',{1,0}}}, throw, {error,V}),
+ ok.
+
+eclectic_1(X, C, Y) ->
+ erase(eclectic),
+ Done = make_ref(),
+ Try =
+ try case X of
+ {catch_foo,V} -> catch {Done,foo(V)};
+ {foo,V} -> {Done,foo(V)}
+ end of
+ {Done,D} -> {value,D,catch foo(D)};
+ {'EXIT',_}=Exit -> Exit;
+ D -> {D,catch foo(D)}
+ catch
+ C:D -> {C,D,catch foo(D)}
+ after
+ put(eclectic, catch foo(Y))
+ end,
+ {Try,erase(eclectic)}.
+
+eclectic_2(X, C, Y) ->
+ Done = make_ref(),
+ erase(eclectic),
+ Catch =
+ case
+ catch
+ {Done,
+ try foo(X) of
+ V -> {value,V,foo(V)}
+ catch
+ C:D -> {C,D,foo(D)}
+ after
+ put(eclectic, foo(Y))
+ end} of
+ {Done,Z} -> {value,Z};
+ Z -> {caught,Z}
+ end,
+ {Catch,erase(eclectic)}.
+
+foo({value,Value}) -> Value;
+foo({'div',{A,B}}) ->
+ my_div(A, B);
+foo({'add',{A,B}}) ->
+ my_add(A, B);
+foo({'abs',X}) ->
+ my_abs(X);
+foo({error,Error}) ->
+ erlang:error(Error);
+foo({throw,Throw}) ->
+ erlang:throw(Throw);
+foo({exit,Exit}) ->
+ erlang:exit(Exit);
+foo({raise,{Class,Reason}}) ->
+ erlang:raise(Class, Reason);
+foo(Term) when not is_atom(Term) -> Term.
+%%foo(Atom) when is_atom(Atom) -> % must not be defined!
+
+my_div(A, B) ->
+ A div B.
+
+my_add(A, B) ->
+ A + B.
+
+my_abs(X) ->
+ abs(X).
+
+test_raise() ->
+ test_raise(fun() -> exit({exit,tuple}) end),
+ test_raise(fun() -> abs(id(x)) end),
+ test_raise(fun() -> throw({was,thrown}) end),
+
+ badarg = bad_raise(fun() -> abs(id(x)) end),
+
+ ok.
+
+bad_raise(Expr) ->
+ try
+ Expr()
+ catch
+ _:E:Stk ->
+ erlang:raise(bad_class, E, Stk)
+ end.
+
+test_raise(Expr) ->
+ test_raise_1(Expr),
+ test_raise_2(Expr),
+ test_raise_3(Expr).
+
+test_raise_1(Expr) ->
+ erase(exception),
+ try
+ do_test_raise_1(Expr)
+ catch
+ C:E:Stk ->
+ {C,E,Stk} = erase(exception)
+ end.
+
+do_test_raise_1(Expr) ->
+ try
+ Expr()
+ catch
+ C:E:Stk ->
+ %% Here the stacktrace must be built.
+ put(exception, {C,E,Stk}),
+ erlang:raise(C, E, Stk)
+ end.
+
+test_raise_2(Expr) ->
+ erase(exception),
+ try
+ do_test_raise_2(Expr)
+ catch
+ C:E:Stk ->
+ {C,E} = erase(exception),
+ try
+ Expr()
+ catch
+ _:_:S ->
+ [StkTop|_] = S,
+ [StkTop|_] = Stk
+ end
+ end.
+
+do_test_raise_2(Expr) ->
+ try
+ Expr()
+ catch
+ C:E:Stk ->
+ %% Here it is possible to replace erlang:raise/3 with
+ %% the raw_raise/3 instruction since the stacktrace is
+ %% not actually used.
+ put(exception, {C,E}),
+ erlang:raise(C, E, Stk)
+ end.
+
+test_raise_3(Expr) ->
+ try
+ do_test_raise_3(Expr)
+ catch
+ exit:{exception,C,E}:Stk ->
+ try
+ Expr()
+ catch
+ C:E:S ->
+ [StkTop|_] = S,
+ [StkTop|_] = Stk
+ end
+ end.
+
+do_test_raise_3(Expr) ->
+ try
+ Expr()
+ catch
+ C:E:Stk ->
+ %% Here it is possible to replace erlang:raise/3 with
+ %% the raw_raise/3 instruction since the stacktrace is
+ %% not actually used.
+ erlang:raise(exit, {exception,C,E}, Stk)
+ end.
+
+id(I) -> I.
diff --git a/lib/hipe/test/basic_SUITE_data/basic_issues_hipe.erl b/lib/hipe/test/basic_SUITE_data/basic_issues_hipe.erl
index e71045bfe2..fc87abb54e 100644
--- a/lib/hipe/test/basic_SUITE_data/basic_issues_hipe.erl
+++ b/lib/hipe/test/basic_SUITE_data/basic_issues_hipe.erl
@@ -8,8 +8,9 @@
-export([test/0]).
-%% functions that need to be exported so that they are retained.
--export([auth/4]).
+%% functions that need to be exported so that they are retained and/or
+%% not specialized away by the compiler.
+-export([auth/4, wxSizer_replace/2, parent_class/1]).
test() ->
ok = test_dominance_trees(),
@@ -18,6 +19,7 @@ test() ->
ok = test_bif_fails(),
ok = test_find_catches(),
ok = test_heap_allocate_trim(),
+ ok = wxSizer_replace(),
ok.
%%--------------------------------------------------------------------
@@ -151,3 +153,25 @@ get_next_retry(Error, Count) ->
end.
pair(A, B) -> {A, B}.
+
+%%--------------------------------------------------------------------
+%% Date: June 11, 2018
+%%
+%% Stripped down test case (from `wxSizer') that crashed the lazy code
+%% motion pass of the HiPE compiler in a pre-release of Erlang/OTP 21.
+%% A similar crash existed in `ssl_correction'.
+%%--------------------------------------------------------------------
+
+wxSizer_replace() ->
+ wxSizer_replace(?MODULE, ?MODULE).
+
+-define(CLASS(Type, Class), ((Type) =:= Class) orelse (Type):parent_class(Class)).
+
+wxSizer_replace(OldwinT, NewwinT) -> % this function was the culprit
+ ?CLASS(OldwinT, ?MODULE),
+ ?CLASS(NewwinT, ?MODULE),
+ ok.
+
+parent_class(wxWindow) -> true;
+parent_class(wxEvtHandler) -> true;
+parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
diff --git a/lib/hipe/test/basic_SUITE_data/basic_receive.erl b/lib/hipe/test/basic_SUITE_data/basic_receive.erl
index 5f865d7b7a..20e3f350e8 100644
--- a/lib/hipe/test/basic_SUITE_data/basic_receive.erl
+++ b/lib/hipe/test/basic_SUITE_data/basic_receive.erl
@@ -12,6 +12,7 @@ test() ->
ok = test_wait_timeout(),
ok = test_double_timeout(),
ok = test_reschedule(),
+ ok = test_recv_mark(),
ok.
%%--------------------------------------------------------------------
@@ -54,3 +55,91 @@ doit(First) ->
erts_debug:set_internal_state(hipe_test_reschedule_suspend, 1).
%%--------------------------------------------------------------------
+%% Check that we cannot cause a recv_mark,recv_set pair to misbehave and
+%% deadlock the process.
+
+test_recv_mark() ->
+ ok = test_recv_mark(fun disturber_nop/0),
+ ok = test_recv_mark(fun disturber_receive/0),
+ ok = test_recv_mark(fun disturber_other/0),
+ ok = test_recv_mark(fun disturber_recurse/0),
+ ok = test_recv_mark_after(self(), fun disturber_after_recurse/0, false),
+ ok = test_recv_mark(fun disturber_other_recurse/0),
+ ok = test_recv_mark(fun disturber_other_after/0),
+ ok = test_recv_mark_nested().
+
+test_recv_mark(Disturber) ->
+ Ref = make_ref(),
+ self() ! Ref,
+ Disturber(),
+ receive Ref -> ok
+ after 0 -> error(failure)
+ end.
+
+disturber_nop() -> ok.
+
+disturber_receive() ->
+ self() ! message,
+ receive message -> ok end.
+
+disturber_other() ->
+ Ref = make_ref(),
+ self() ! Ref,
+ receive Ref -> ok end.
+
+disturber_recurse() ->
+ aborted = (catch test_recv_mark(fun() -> throw(aborted) end)),
+ ok.
+
+test_recv_mark_after(Recipient, Disturber, IsInner) ->
+ Ref = make_ref(),
+ Recipient ! Ref,
+ Disturber(),
+ receive
+ Ref -> ok
+ after 0 ->
+ case IsInner of
+ true -> expected;
+ false -> error(failure)
+ end
+ end.
+
+disturber_after_recurse() ->
+ NoOp = fun() -> ok end,
+ BlackHole = spawn(NoOp),
+ expected = test_recv_mark_after(BlackHole, NoOp, true),
+ ok.
+
+disturber_other_recurse() ->
+ aborted = (catch disturber_other_recurse(fun() -> throw(aborted) end)),
+ ok.
+
+disturber_other_recurse(InnerD) ->
+ Ref = make_ref(),
+ self() ! Ref,
+ InnerD(),
+ receive Ref -> ok
+ after 0 -> error(failure)
+ end.
+
+disturber_other_after() ->
+ BlackHole = spawn(fun() -> ok end),
+ Ref = make_ref(),
+ BlackHole ! Ref,
+ receive Ref -> error(imposible)
+ after 0 -> ok
+ end.
+
+test_recv_mark_nested() ->
+ Ref1 = make_ref(),
+ self() ! Ref1,
+ begin
+ Ref2 = make_ref(),
+ self() ! Ref2,
+ receive Ref2 -> ok end
+ end,
+ receive Ref1 -> ok
+ after 0 -> error(failure)
+ end.
+
+%%--------------------------------------------------------------------
diff --git a/lib/hipe/test/bs_SUITE_data/bs_construct.erl b/lib/hipe/test/bs_SUITE_data/bs_construct.erl
index b9e7d93570..aa85626857 100644
--- a/lib/hipe/test/bs_SUITE_data/bs_construct.erl
+++ b/lib/hipe/test/bs_SUITE_data/bs_construct.erl
@@ -279,13 +279,22 @@ bad_floats() ->
%% (incorrectly) signed.
huge_binaries() ->
- AlmostIllegal = id(<<0:(id((1 bsl 32)-8))>>),
case erlang:system_info(wordsize) of
- 4 -> huge_binaries_32(AlmostIllegal);
+ 4 ->
+ Old = erts_debug:set_internal_state(available_internal_state, true),
+ case erts_debug:set_internal_state(binary, (1 bsl 29)-1) of
+ false ->
+ io:format("\nNot enough memory to create 512Mb binary\n",[]);
+ Bin->
+ huge_binaries_32(Bin)
+ end,
+ erts_debug:set_internal_state(available_internal_state, Old);
+
8 -> ok
end,
garbage_collect(),
id(<<0:(id((1 bsl 31)-1))>>),
+ garbage_collect(),
id(<<0:(id((1 bsl 30)-1))>>),
garbage_collect(),
ok.
diff --git a/lib/hipe/test/erl_types_SUITE.erl b/lib/hipe/test/erl_types_SUITE.erl
new file mode 100644
index 0000000000..7d7c144b69
--- /dev/null
+++ b/lib/hipe/test/erl_types_SUITE.erl
@@ -0,0 +1,197 @@
+%% -*- erlang-indent-level: 4 -*-
+%%
+%% 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.
+%%
+-module(erl_types_SUITE).
+
+-export([all/0,
+ consistency_and_to_string/1]).
+
+%% Simplify calls into erl_types and avoid importing the entire module.
+-define(M, erl_types).
+
+-include_lib("common_test/include/ct.hrl").
+
+all() ->
+ [consistency_and_to_string].
+
+consistency_and_to_string(_Config) ->
+ %% Check consistency of types
+ Atom1 = ?M:t_atom(),
+ Atom2 = ?M:t_atom(foo),
+ Atom3 = ?M:t_atom(bar),
+ true = ?M:t_is_atom(Atom2),
+
+ True = ?M:t_atom(true),
+ False = ?M:t_atom(false),
+ Bool = ?M:t_boolean(),
+ true = ?M:t_is_boolean(True),
+ true = ?M:t_is_boolean(Bool),
+ false = ?M:t_is_boolean(Atom1),
+
+ Binary = ?M:t_binary(),
+ true = ?M:t_is_binary(Binary),
+
+ Bitstr = ?M:t_bitstr(),
+ true = ?M:t_is_bitstr(Bitstr),
+
+ Bitstr1 = ?M:t_bitstr(7, 3),
+ true = ?M:t_is_bitstr(Bitstr1),
+ false = ?M:t_is_binary(Bitstr1),
+
+ Bitstr2 = ?M:t_bitstr(16, 8),
+ true = ?M:t_is_bitstr(Bitstr2),
+ true = ?M:t_is_binary(Bitstr2),
+
+ BitStr816 = ?M:t_bitstr(8,16),
+ BitStr816 = ?M:t_subtract(?M:t_bitstr(4, 12), ?M:t_bitstr(8, 12)),
+
+ Int1 = ?M:t_integer(),
+ Int2 = ?M:t_integer(1),
+ Int3 = ?M:t_integer(16#ffffffff),
+ true = ?M:t_is_integer(Int2),
+ true = ?M:t_is_byte(Int2),
+ false = ?M:t_is_byte(Int3),
+ false = ?M:t_is_byte(?M:t_from_range(-1, 1)),
+ true = ?M:t_is_byte(?M:t_from_range(1, 255)),
+
+ Tuple1 = ?M:t_tuple(),
+ Tuple2 = ?M:t_tuple(3),
+ Tuple3 = ?M:t_tuple([Atom1, Int1]),
+ Tuple4 = ?M:t_tuple([Tuple1, Tuple2]),
+ Tuple5 = ?M:t_tuple([Tuple3, Tuple4]),
+ Tuple6 = ?M:t_limit(Tuple5, 2),
+ Tuple7 = ?M:t_limit(Tuple5, 3),
+ true = ?M:t_is_tuple(Tuple1),
+
+ Port = ?M:t_port(),
+ Pid = ?M:t_pid(),
+ Ref = ?M:t_reference(),
+ Identifier = ?M:t_identifier(),
+ false = ?M:t_is_reference(Port),
+ true = ?M:t_is_identifier(Port),
+
+ Function1 = ?M:t_fun(),
+ Function2 = ?M:t_fun(Pid),
+ Function3 = ?M:t_fun([], Pid),
+ Function4 = ?M:t_fun([Port, Pid], Pid),
+ Function5 = ?M:t_fun([Pid, Atom1], Int2),
+ true = ?M:t_is_fun(Function3),
+
+ List1 = ?M:t_list(),
+ List2 = ?M:t_list(?M:t_boolean()),
+ List3 = ?M:t_cons(?M:t_boolean(), List2),
+ List4 = ?M:t_cons(?M:t_boolean(), ?M:t_atom()),
+ List5 = ?M:t_cons(?M:t_boolean(), ?M:t_nil()),
+ List6 = ?M:t_cons_tl(List5),
+ List7 = ?M:t_sup(List4, List5),
+ List8 = ?M:t_inf(List7, ?M:t_list()),
+ List9 = ?M:t_cons(),
+ List10 = ?M:t_cons_tl(List9),
+ true = ?M:t_is_boolean(?M:t_cons_hd(List5)),
+ true = ?M:t_is_list(List5),
+ false = ?M:t_is_list(List4),
+
+ Product1 = ?M:t_product([Atom1, Atom2]),
+ Product2 = ?M:t_product([Atom3, Atom1]),
+ Product3 = ?M:t_product([Atom3, Atom2]),
+
+ Union1 = ?M:t_sup(Atom2, Atom3),
+ Union2 = ?M:t_sup(Tuple2, Tuple3),
+ Union3 = ?M:t_sup(Int2, Atom3),
+ Union4 = ?M:t_sup(Port, Pid),
+ Union5 = ?M:t_sup(Union4, Int1),
+ Union6 = ?M:t_sup(Function1, Function2),
+ Union7 = ?M:t_sup(Function4, Function5),
+ Union8 = ?M:t_sup(True, False),
+ true = ?M:t_is_boolean(Union8),
+ Union9 = ?M:t_sup(Int2, ?M:t_integer(2)),
+ true = ?M:t_is_byte(Union9),
+ Union10 = ?M:t_sup(?M:t_tuple([?M:t_atom(true), ?M:t_any()]),
+ ?M:t_tuple([?M:t_atom(false), ?M:t_any()])),
+
+ Any = ?M:t_any(),
+ Any = ?M:t_sup(Product3, Function5),
+
+ Atom3 = ?M:t_inf(Union3, Atom1),
+ Union2 = ?M:t_inf(Union2, Tuple1),
+ Int2 = ?M:t_inf(Int1, Union3),
+ Union4 = ?M:t_inf(Union4, Identifier),
+ Port = ?M:t_inf(Union5, Port),
+ Function4 = ?M:t_inf(Union7, Function4),
+ None = ?M:t_none(),
+ None = ?M:t_inf(Product2, Atom1),
+ Product3 = ?M:t_inf(Product1, Product2),
+ Function5 = ?M:t_inf(Union7, Function5),
+ true = ?M:t_is_byte(?M:t_inf(Union9, ?M:t_number())),
+ true = ?M:t_is_char(?M:t_inf(Union9, ?M:t_number())),
+
+ RecDict = #{{record, foo} => {{?FILE, ?LINE}, [{2, [{bar, [], ?M:t_any()},
+ {baz, [], ?M:t_any()}]}]}},
+ Record1 = ?M:t_from_term({foo, [1,2], {1,2,3}}),
+
+ %% Check string representations
+ "atom()" = ?M:t_to_string(Atom1),
+ "'foo'" = ?M:t_to_string(Atom2),
+ "'bar'" = ?M:t_to_string(Atom3),
+
+ "binary()" = ?M:t_to_string(Binary),
+
+ "integer()" = ?M:t_to_string(Int1),
+ "1" = ?M:t_to_string(Int2),
+
+ "tuple()" = ?M:t_to_string(Tuple1),
+ "{_,_,_}" = ?M:t_to_string(Tuple2),
+ "{atom(),integer()}" = ?M:t_to_string(Tuple3),
+ "{tuple(),{_,_,_}}" = ?M:t_to_string(Tuple4),
+ "{{atom(),integer()},{tuple(),{_,_,_}}}" = ?M:t_to_string(Tuple5),
+ "{{_,_},{_,_}}" = ?M:t_to_string(Tuple6),
+ "{{atom(),integer()},{tuple(),{_,_,_}}}" = ?M:t_to_string(Tuple7),
+
+ "reference()" = ?M:t_to_string(Ref),
+ "port()" = ?M:t_to_string(Port),
+ "pid()" = ?M:t_to_string(Pid),
+ "identifier()" = ?M:t_to_string(Identifier),
+
+ "[any()]" = ?M:t_to_string(List1),
+ "[boolean()]" = ?M:t_to_string(List2),
+ "[boolean(),...]" = ?M:t_to_string(List3),
+ "nonempty_improper_list(boolean(),atom())" = ?M:t_to_string(List4),
+ "[boolean(),...]" = ?M:t_to_string(List5),
+ "[boolean()]" = ?M:t_to_string(List6),
+ "nonempty_maybe_improper_list(boolean(),atom() | [])" = ?M:t_to_string(List7),
+ "[boolean(),...]" = ?M:t_to_string(List8),
+ "nonempty_maybe_improper_list()" = ?M:t_to_string(List9),
+ "any()" = ?M:t_to_string(List10),
+
+ "fun()" = ?M:t_to_string(Function1),
+ "fun((...) -> pid())" = ?M:t_to_string(Function2),
+ "fun(() -> pid())" = ?M:t_to_string(Function3),
+ "fun((port(),pid()) -> pid())" = ?M:t_to_string(Function4),
+ "fun((pid(),atom()) -> 1)" = ?M:t_to_string(Function5),
+
+ "<atom(),'foo'>" = ?M:t_to_string(Product1),
+ "<'bar',atom()>" = ?M:t_to_string(Product2),
+
+ "#foo{bar::[1 | 2,...],baz::{1,2,3}}" = ?M:t_to_string(Record1, RecDict),
+
+ "'bar' | 'foo'" = ?M:t_to_string(Union1),
+ "{atom(),integer()} | {_,_,_}" = ?M:t_to_string(Union2),
+ "'bar' | 1" = ?M:t_to_string(Union3),
+ "pid() | port()" = ?M:t_to_string(Union4),
+ "pid() | port() | integer()" = ?M:t_to_string(Union5),
+ "fun()" = ?M:t_to_string(Union6),
+ "fun((pid() | port(),atom() | pid()) -> pid() | 1)" = ?M:t_to_string(Union7),
+ "boolean()" = ?M:t_to_string(Union8),
+ "{'false',_} | {'true',_}" = ?M:t_to_string(Union10),
+ "{'true',integer()}" = ?M:t_to_string(?M:t_inf(Union10, ?M:t_tuple([?M:t_atom(true), ?M:t_integer()]))).
diff --git a/lib/hipe/test/hipe_testsuite_driver.erl b/lib/hipe/test/hipe_testsuite_driver.erl
index 88576775ca..8813af5dfc 100644
--- a/lib/hipe/test/hipe_testsuite_driver.erl
+++ b/lib/hipe/test/hipe_testsuite_driver.erl
@@ -29,13 +29,9 @@ get_suites(SuitesWithSuiteSuffix) ->
[S || {yes, S} <- Prefixes].
suffix(String, Suffix) ->
- case string:rstr(String, Suffix) of
- 0 -> no;
- Index ->
- case string:substr(String, Index) =:= Suffix of
- true -> {yes, string:sub_string(String, 1, Index-1)};
- false -> no
- end
+ case string:split(String, Suffix, trailing) of
+ [Prefix,[]] -> {yes, Prefix};
+ _ -> no
end.
-spec file_type(file:filename()) -> {ok, file_type()} | {error, ext_posix()}.
@@ -165,7 +161,8 @@ run(TestCase, Dir, _OutDir) ->
%% end, DataFiles),
%% try
ok = TestCase:test(),
- HiPEOpts = try TestCase:hipe_options() catch error:undef -> [] end,
+ HiPEOpts0 = try TestCase:hipe_options() catch error:undef -> [] end,
+ HiPEOpts = HiPEOpts0 ++ hipe_options(),
{ok, TestCase} = hipe:c(TestCase, HiPEOpts),
ok = TestCase:test(),
{ok, TestCase} = hipe:c(TestCase, [o1|HiPEOpts]),
@@ -183,3 +180,6 @@ run(TestCase, Dir, _OutDir) ->
%% lists:foreach(fun (DF) -> ok end, % = file:delete(DF) end,
%% [filename:join(OutDir, D) || D <- DataFiles])
%% end.
+
+hipe_options() ->
+ [verify_gcsafe].
diff --git a/lib/hipe/test/opt_verify_SUITE.erl b/lib/hipe/test/opt_verify_SUITE.erl
index 86083fa02b..24f43af275 100644
--- a/lib/hipe/test/opt_verify_SUITE.erl
+++ b/lib/hipe/test/opt_verify_SUITE.erl
@@ -44,7 +44,7 @@ call_elim(Config) ->
Icode5 = call_elim_test_file(Config, F3, icode_call_elim),
0 = substring_count(binary:bin_to_list(Icode5), "is_key"),
Icode6 = call_elim_test_file(Config, F3, no_icode_call_elim),
- 3 = substring_count(binary:bin_to_list(Icode6), "is_key"),
+ 2 = substring_count(binary:bin_to_list(Icode6), "is_key"),
ok.
call_elim_test_file(Config, FileName, Option) ->
@@ -59,7 +59,7 @@ call_elim_test_file(Config, FileName, Option) ->
substring_count(Icode, Substring) ->
substring_count(Icode, Substring, 0).
substring_count(Icode, Substring, N) ->
- case string:str(Icode, Substring) of
- 0 -> N;
- I -> substring_count(lists:nthtail(I, Icode), Substring, N+1)
+ case string:find(Icode, Substring) of
+ nomatch -> N;
+ Prefix -> substring_count(string:prefix(Prefix, Substring), Substring, N+1)
end.
diff --git a/lib/hipe/test/opt_verify_SUITE_data/call_elim_test_branches_opt_poss.erl b/lib/hipe/test/opt_verify_SUITE_data/call_elim_test_branches_opt_poss.erl
index c8ddfa1e75..12875f41af 100644
--- a/lib/hipe/test/opt_verify_SUITE_data/call_elim_test_branches_opt_poss.erl
+++ b/lib/hipe/test/opt_verify_SUITE_data/call_elim_test_branches_opt_poss.erl
@@ -6,17 +6,11 @@ test(A) ->
if A > 0 ->
true = has_a_field(#{a=>true}),
true = has_a_field(#{b=>1, a=>"2"}),
- true = has_a_field(#{a=>5, c=>4}),
- true = has_tuple_field(#{{ab, 1}=><<"qq">>, 1 =>0}),
- true = has_tuple_field(#{up =>down, {ab, 1}=>[]}),
- true = has_tuple_field(#{{ab, 1}=>42});
+ true = has_a_field(#{a=>5, c=>4});
A =< 0 ->
true = has_a_field(#{a=>q, 'A' =>nej}),
true = has_a_field(#{a=>"hej", false=>true}),
- true = has_a_field(#{a=>3}),
- true = has_tuple_field(#{{ab, 1}=>q, 'A' =>nej}),
- true = has_tuple_field(#{{ab, 1}=>"hej", false=>true}),
- true = has_tuple_field(#{{ab, 1}=>3})
+ true = has_a_field(#{a=>3})
end,
true = has_nil_field(#{[] =>3, b =>"seven"}),
true = has_nil_field(#{"seventeen"=>17, []=>nil}),
diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk
index 0ef4aa7f09..b51f17aff0 100644
--- a/lib/hipe/vsn.mk
+++ b/lib/hipe/vsn.mk
@@ -1 +1 @@
-HIPE_VSN = 3.16
+HIPE_VSN = 3.18.1
diff --git a/lib/hipe/x86/hipe_rtl_to_x86.erl b/lib/hipe/x86/hipe_rtl_to_x86.erl
index 31e4f6e4ac..22947da148 100644
--- a/lib/hipe/x86/hipe_rtl_to_x86.erl
+++ b/lib/hipe/x86/hipe_rtl_to_x86.erl
@@ -646,7 +646,7 @@ conv_imm(Opnd, Map) ->
is_imm64(Value) when is_integer(Value) ->
(Value < -(1 bsl (32 - 1))) or (Value > (1 bsl (32 - 1)) - 1);
is_imm64({_,atom}) -> false; % Atoms are 32 bits.
-is_imm64({_,c_const}) -> false; % c_consts are 32 bits.
+is_imm64({_,c_const}) -> true; % c_consts are 64 bits.
is_imm64({_,_}) -> true . % Other relocs are 64 bits.
-else.
conv_imm(Opnd, Map) ->
@@ -777,6 +777,18 @@ conv_fconv(Dst, Src) ->
%%% Finalise the conversion of a 2-address FP operation.
+-ifdef(HIPE_AMD64).
+conv_fp_unary(Dst, Src, 'fchs') ->
+ Tmp = new_untagged_temp(),
+ case same_opnd(Dst, Src) of
+ true ->
+ [];
+ _ ->
+ [hipe_x86:mk_fmove(Src, Dst)]
+ end ++
+ mk_load_address(c_const, hipe_x86:mk_imm({sse2_fnegate_mask, c_const}), Tmp) ++
+ [hipe_x86:mk_fp_binop('xorpd', hipe_x86:mk_mem(Tmp, hipe_x86:mk_imm(0), double), Dst)].
+-else.
conv_fp_unary(Dst, Src, FpUnOp) ->
case same_opnd(Dst, Src) of
true ->
@@ -785,6 +797,7 @@ conv_fp_unary(Dst, Src, FpUnOp) ->
[hipe_x86:mk_fmove(Src, Dst),
hipe_x86:mk_fp_unop(FpUnOp, Dst)]
end.
+-endif.
conv_fp_unop(RtlFpUnOp) ->
case RtlFpUnOp of
@@ -854,13 +867,8 @@ mk_jmp_switch(Index, JTabLab, Labels) ->
%%% Finalise the translation of a load_address instruction.
-ifdef(HIPE_AMD64).
-mk_load_address(Type, Src, Dst) ->
- case Type of
- c_const -> % 32 bits
- [hipe_x86:mk_move(Src, Dst)];
- _ ->
- [hipe_x86:mk_move64(Src, Dst)]
- end.
+mk_load_address(_Type, Src, Dst) ->
+ [hipe_x86:mk_move64(Src, Dst)].
-else.
mk_load_address(_Type, Src, Dst) ->
[hipe_x86:mk_move(Src, Dst)].
diff --git a/lib/hipe/x86/hipe_x86_assemble.erl b/lib/hipe/x86/hipe_x86_assemble.erl
index 50919bdf4e..9d2586a14d 100644
--- a/lib/hipe/x86/hipe_x86_assemble.erl
+++ b/lib/hipe/x86/hipe_x86_assemble.erl
@@ -735,6 +735,7 @@ resolve_sse2_op(Op) ->
fdiv -> divsd;
fmul -> mulsd;
fsub -> subsd;
+ xorpd -> xorpd;
_ -> exit({?MODULE, unknown_sse2_operator, Op})
end.
diff --git a/lib/ic/AUTHORS b/lib/ic/AUTHORS
deleted file mode 100644
index f3791aabaa..0000000000
--- a/lib/ic/AUTHORS
+++ /dev/null
@@ -1,8 +0,0 @@
-Original Authors:
-
-Peter Lundel
-Lars Thorsen
-Babbis Xagorarakis
-
-
-Contributors:
diff --git a/lib/ic/Makefile b/lib/ic/Makefile
deleted file mode 100644
index 624aa62a6e..0000000000
--- a/lib/ic/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1998-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include vsn.mk
-VSN=$(ORBER_VSN)
-
-# ----------------------------------------------------
-# Common Macros
-# ----------------------------------------------------
-
-SUB_DIRECTORIES = src c_src java_src doc/src examples/pre_post_condition
-
-SPECIAL_TARGETS =
-
-# ----------------------------------------------------
-# Default Subdir Targets
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_subdir.mk
-
diff --git a/lib/ic/c_src/Makefile b/lib/ic/c_src/Makefile
deleted file mode 100644
index 35d6013279..0000000000
--- a/lib/ic/c_src/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1998-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-#
-# Invoke with GNU make or clearmake -C gnu.
-#
-
-include $(ERL_TOP)/make/run_make.mk
diff --git a/lib/ic/c_src/Makefile.in b/lib/ic/c_src/Makefile.in
deleted file mode 100644
index c0dad59557..0000000000
--- a/lib/ic/c_src/Makefile.in
+++ /dev/null
@@ -1,165 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1998-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-CC = @CC@
-LIBS = @LIBS@
-
-LIBDIR = ../priv/lib/$(TARGET)
-OBJDIR = ../priv/obj/$(TARGET)
-INCDIR = ../include
-ERL_INTERFACE_FLAGS = \
- -I$(ERL_TOP)/lib/erl_interface/include \
- -I$(ERL_TOP)/lib/erl_interface/src
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(IC_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/ic-$(VSN)
-
-# ----------------------------------------------------
-# File Specs
-# ----------------------------------------------------
-
-IDL_FILES = \
- $(INCDIR)/erlang.idl
-
-ifeq ($(findstring win32,$(TARGET)),win32)
-USING_MINGW=@MIXED_CYGWIN_MINGW@
-ifeq ($(USING_MINGW),yes)
-AR_OUT = rcv
-CC_FLAGS =
-LIBRARY = $(LIBDIR)/libic.a
-SKIP_BUILDING_BINARIES := false
-else
-LIBRARY = $(LIBDIR)/ic.lib
-AR_OUT = -out:
-CC_FLAGS = -MT
-endif
-ifeq ($(HOST_OS),)
-HOST_OS := $(shell $(ERL_TOP)/erts/autoconf/config.guess)
-endif
-ifeq ($(findstring solaris,$(HOST_OS)),solaris)
-SKIP_BUILDING_BINARIES := true
-endif
-else
-ifeq ($(V),0)
-AR_OUT = rc
-else
-AR_OUT = rcv
-endif
-CC_FLAGS = @DED_CFLAGS@
-LIBRARY = $(LIBDIR)/libic.a
-SKIP_BUILDING_BINARIES := false
-endif
-
-C_FILES = \
- ic.c \
- ic_tmo.c \
- oe_ei_encode_version.c \
- oe_ei_encode_long.c \
- oe_ei_encode_ulong.c \
- oe_ei_encode_double.c \
- oe_ei_encode_char.c \
- oe_ei_encode_string.c \
- oe_ei_encode_atom.c \
- oe_ei_encode_pid.c \
- oe_ei_encode_port.c \
- oe_ei_encode_ref.c \
- oe_ei_encode_term.c \
- oe_ei_encode_tuple_header.c \
- oe_ei_encode_list_header.c \
- oe_ei_encode_longlong.c \
- oe_ei_encode_ulonglong.c \
- oe_ei_encode_wchar.c \
- oe_ei_encode_wstring.c \
- oe_ei_decode_longlong.c \
- oe_ei_decode_ulonglong.c \
- oe_ei_decode_wchar.c \
- oe_ei_decode_wstring.c \
- oe_ei_code_erlang_binary.c
-
-H_FILES = $(INCDIR)/ic.h
-
-OBJ_FILES= $(C_FILES:%.c=$(OBJDIR)/%.o)
-
-ALL_CFLAGS = @CFLAGS@ @DEFS@ -I$(INCDIR) $(ERL_INTERFACE_FLAGS) $(CFLAGS)
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-ifeq ($(SKIP_BUILDING_BINARIES), true)
-debug opt:
-else
-debug opt: $(LIBRARY)
-endif
-
-clean:
- rm -f $(LIBRARY) $(OBJ_FILES)
- rm -f core *~
-
-docs:
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
-
-$(LIBRARY): $(OBJ_FILES)
- -$(V_AR) $(AR_OUT) $@ $(OBJ_FILES)
- -$(V_RANLIB) $@
-
-$(OBJDIR)/%.o: %.c
- $(V_CC) $(CC_FLAGS) -c -o $@ $(ALL_CFLAGS) $<
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/c_src"
- $(INSTALL_DIR) "$(RELSYSDIR)/include"
- $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
- $(INSTALL_DIR) "$(RELEASE_PATH)/usr/include"
- $(INSTALL_DIR) "$(RELEASE_PATH)/usr/lib"
- $(INSTALL_DATA) ic.c ic_tmo.c "$(RELSYSDIR)/c_src"
- $(INSTALL_DATA) $(IDL_FILES) $(H_FILES) "$(RELSYSDIR)/include"
- $(INSTALL_DATA) $(LIBRARY) "$(RELSYSDIR)/priv/lib"
- $(INSTALL_DATA) $(IDL_FILES) $(H_FILES) "$(RELEASE_PATH)/usr/include"
- $(INSTALL_DATA) $(LIBRARY) "$(RELEASE_PATH)/usr/lib"
-
-release_docs_spec:
-
-
-
-
-
-
diff --git a/lib/ic/c_src/Makefile.win32 b/lib/ic/c_src/Makefile.win32
deleted file mode 100644
index 670a17f958..0000000000
--- a/lib/ic/c_src/Makefile.win32
+++ /dev/null
@@ -1,109 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-
-CC = cl.exe
-LIBRARIAN = lib.exe /nologo
-
-IC_INCLUDE = ..\include
-EI_INCLUDE = \erts\lib\erl_interface\src
-
-CFLAGS = /MT /nologo /Ox /I$(IC_INCLUDE) /I$(EI_INCLUDE)
-TARGET = win32
-OBJDIR = ..\priv\obj\$(TARGET)
-LIBDIR = ..\priv\lib\$(TARGET)
-
-
-C_FILES = \
- ic.c \
- oe_ei_encode_version.c \
- oe_ei_encode_long.c \
- oe_ei_encode_ulong.c \
- oe_ei_encode_double.c \
- oe_ei_encode_char.c \
- oe_ei_encode_string.c \
- oe_ei_encode_atom.c \
- oe_ei_encode_pid.c \
- oe_ei_encode_port.c \
- oe_ei_encode_ref.c \
- oe_ei_encode_term.c \
- oe_ei_encode_tuple_header.c \
- oe_ei_encode_list_header.c \
- oe_ei_encode_longlong.c \
- oe_ei_encode_ulonglong.c \
- oe_ei_encode_wchar.c \
- oe_ei_encode_wstring.c \
- oe_ei_decode_longlong.c \
- oe_ei_decode_ulonglong.c \
- oe_ei_decode_wchar.c \
- oe_ei_decode_wstring.c
-
-OBJ_FILES = \
- $(OBJDIR)\ic.obj \
- $(OBJDIR)\oe_ei_encode_version.obj \
- $(OBJDIR)\oe_ei_encode_long.obj \
- $(OBJDIR)\oe_ei_encode_ulong.obj \
- $(OBJDIR)\oe_ei_encode_double.obj \
- $(OBJDIR)\oe_ei_encode_char.obj \
- $(OBJDIR)\oe_ei_encode_string.obj \
- $(OBJDIR)\oe_ei_encode_atom.obj \
- $(OBJDIR)\oe_ei_encode_pid.obj \
- $(OBJDIR)\oe_ei_encode_port.obj \
- $(OBJDIR)\oe_ei_encode_ref.obj \
- $(OBJDIR)\oe_ei_encode_term.obj \
- $(OBJDIR)\oe_ei_encode_tuple_header.obj \
- $(OBJDIR)\oe_ei_encode_list_header.obj \
- $(OBJDIR)\oe_ei_encode_longlong.obj \
- $(OBJDIR)\oe_ei_encode_ulonglong.obj \
- $(OBJDIR)\oe_ei_encode_wchar.obj \
- $(OBJDIR)\oe_ei_encode_wstring.obj \
- $(OBJDIR)\oe_ei_decode_longlong.obj \
- $(OBJDIR)\oe_ei_decode_ulonglong.obj \
- $(OBJDIR)\oe_ei_decode_wchar.obj \
- $(OBJDIR)\oe_ei_decode_wstring.obj
-
-
-LIBRARY = $(LIBDIR)\ic.lib
-
-
-all: $(OBJDIR) $(LIBDIR) $(LIBRARY)
-
-release:
- echo "Nothing to do"
-
-clean:
- -del $(OBJ_FILES) $(LIBRARY)
-
-$(LIBRARY): $(OBJ_FILES)
- $(LIBRARIAN) /OUT:$@ $**
-
-{}.c{$(OBJDIR)}.obj:
- $(CC) $(CFLAGS) /c /Fo$@ $<
-
-$(OBJDIR):
- -mkdir $(OBJDIR)
-
-$(LIBDIR):
- -mkdir $(LIBDIR)
-
-$(LIBRARY):
-
-
-{}.c: $(EI_INCLUDE)\ei.h $(IC_INCLUDE)\ic.
diff --git a/lib/ic/c_src/ic.c b/lib/ic/c_src/ic.c
deleted file mode 100644
index 6e55a13f4f..0000000000
--- a/lib/ic/c_src/ic.c
+++ /dev/null
@@ -1,613 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-static int oe_send(CORBA_Environment *env);
-
-void CORBA_free(void *p)
-{
- if (p != NULL)
- free(p);
-}
-
-
-CORBA_char *CORBA_string_alloc(CORBA_unsigned_long len)
-{
- return (CORBA_char *) malloc(len+1);
-}
-
-
-CORBA_wchar *CORBA_wstring_alloc(CORBA_unsigned_long len)
-{
- return (CORBA_wchar *) malloc(len*(__OE_WCHAR_SIZE_OF__+1));
-}
-
-
-CORBA_Environment *CORBA_Environment_alloc(int inbufsz, int outbufsz)
-{
- CORBA_Environment *env;
-
- env = malloc(sizeof(CORBA_Environment));
-
- if (env != NULL) {
-
- /* CORBA */
- env->_major = CORBA_NO_EXCEPTION;
-
- /* Set by user */
- env->_fd= -1;
- env->_inbufsz = inbufsz;
- env->_inbuf = malloc(inbufsz);
- env->_outbufsz = outbufsz;
- env->_outbuf = malloc(outbufsz);
- env->_memchunk = __OE_MEMCHUNK__;
- env->_regname[0] = '\0';
- env->_to_pid = NULL;
- env->_from_pid = NULL;
-
- /* Set by client or server */
- env->_iin = 0;
- env->_iout = 0;
- env->_operation[0] = '\0';
- env->_received = 0;
- /* env->_caller */
- /* env->_unique */
- env->_exc_id = NULL;
- env->_exc_value = NULL;
- env->_ref_counter_1 = 0;
- env->_ref_counter_2 = 0;
- env->_ref_counter_3 = 0;
- }
-
- return env;
-}
-
-#if 0
-/* NOT EXPORTED SO FAR */
-void CORBA_Environment_free(CORBA_Environment *env)
-{
-
- CORBA_free(env->_inbuf);
- CORBA_free(env->_outbuf);
- CORBA_exception_free(env);
- CORBA_free(env);
-}
-#endif
-
-
-CORBA_char *CORBA_exception_id(CORBA_Environment *env)
-{
-
- return env->_exc_id;
-}
-
-void *CORBA_exception_value(CORBA_Environment *env)
-{
-
- return env->_exc_value;
-}
-
-void CORBA_exception_free(CORBA_Environment *env)
-{
-
- /* Setting major value */
- env->_major=CORBA_NO_EXCEPTION;
-
- /* Freeing storage */
- CORBA_free(env->_exc_id);
- CORBA_free(env->_exc_value);
- env->_exc_id = env->_exc_value = NULL;
-}
-
-void CORBA_exc_set(CORBA_Environment *env,
- CORBA_exception_type Major,
- CORBA_char *Id,
- CORBA_char *Value)
-{
- int ilen,vlen;
-
- /* Create exception only if exception not already set */
- if (env->_major == CORBA_NO_EXCEPTION) {
-
- /* Counting lengths */
- ilen = strlen(Id)+1;
- vlen = strlen(Value)+1;
-
- /* Allocating storage */
- env->_exc_id = (CORBA_char *) malloc(ilen);
- env->_exc_value = (CORBA_char *) malloc(vlen);
-
- /* Initiating */
- env->_major = Major;
- strcpy(env->_exc_id,Id);
- strcpy(env->_exc_value,Value);
- }
-}
-
-#define ERLANG_REF_NUM_SIZE 18
-#define ERLANG_REF_MASK (~(~((unsigned int)0) << ERLANG_REF_NUM_SIZE))
-
-/* Initiating message reference */
-void ic_init_ref(CORBA_Environment *env, erlang_ref *ref)
-{
-
- strcpy(ref->node, erl_thisnodename());
-
- ref->len = 3;
-
- ++env->_ref_counter_1;
- env->_ref_counter_1 &= ERLANG_REF_MASK;
- if (env->_ref_counter_1 == 0)
- if (++env->_ref_counter_2 == 0)
- ++env->_ref_counter_3;
- ref->n[0] = env->_ref_counter_1;
- ref->n[1] = env->_ref_counter_2;
- ref->n[2] = env->_ref_counter_3;
-
- ref->creation = erl_thiscreation();
-}
-
-/* Comparing message references */
-int ic_compare_refs(erlang_ref *ref1, erlang_ref *ref2)
-{
- int i;
-
- if(strcmp(ref1->node, ref2->node) != 0)
- return -1;
-
- if (ref1->len != ref2->len)
- return -1;
-
- for (i = 0; i < ref1->len; i++)
- if (ref1->n[i] != ref2->n[i])
- return -1;
-
- return 0;
-}
-
-/* Length counter for wide strings */
-int ic_wstrlen(CORBA_wchar * p)
-{
- int len = 0;
-
- while(1) {
- if (p[len] == 0)
- return len;
-
- len+=1;
- }
-}
-
-
-/* Wide string compare function */
-int ic_wstrcmp(CORBA_wchar * ws1, CORBA_wchar * ws2)
-{
- int index = 0;
-
- while(1) {
- if (ws1[index] == ws2[index]) {
-
- if (ws1[index] == 0)
- return 0;
-
- index += 1;
-
- } else
- return -1;
- }
-}
-
-/* For backward compatibility -- replaced by prepare_request_decoding() */
-int ___call_info___(CORBA_Object obj, CORBA_Environment *env)
-{
- return oe_prepare_request_decoding(env);
-}
-
-/* #define DEBUG_MAP */
-
-#if defined(DEBUG_MAP)
-
-#define PRINT_MAPS(P, M, S) print_maps(P, M, S)
-#define PRINT_MAP(T, M) print_map(T, "", M)
-
-static void print_map(char *title, char *prefix, oe_map_t *map)
-{
- if (map == NULL) {
- fprintf(stdout, "%s => NULL\n", title);
- return;
- }
-
- fprintf(stdout, "%s%s\n", prefix, title);
-
- {
- int j, len = map->length;
-
- fprintf(stdout, "%s length: %d\n", prefix, len);
- fprintf(stdout, "%s operations: 0x%X%d\n", prefix, map->operations);
-
- for (j = 0 ; j < len ; j++) {
- fprintf(stdout, "%s operation[%d]:\n", prefix, j);
-
- if (map->operations[j].interface != NULL) {
- fprintf(stdout, "%s intf: %s\n", prefix,
- map->operations[j].interface);
- } else {
- fprintf(stdout, "%s intf: NULL\n", prefix);
- }
- fprintf(stdout, "%s name: %s\n", prefix,
- map->operations[j].name);
- fprintf(stdout, "%s func: 0x%X\n", prefix,
- map->operations[j].function);
- }
- }
- fflush(stdout);
-}
-
-static void print_maps(char* title, oe_map_t * maps, int size)
-{
- int i;
- char p[64];
-
- fprintf(stdout, "%s\n", title);
-
- for (i = 0 ; i < size ; i++) {
- sprintf(p, "map[%d]:", i);
- print_map(p, " ", &maps[i]);
- }
- fprintf(stdout, "\n");
- fflush(stdout);
-}
-
-#else
-
-#define PRINT_MAPS(P, M, S)
-#define PRINT_MAP(T, M)
-
-#endif /* if defined(DEBUG_MAP) */
-
-
-/* Generic server switch */
-int oe_exec_switch(CORBA_Object obj, CORBA_Environment *env, oe_map_t *map)
-{
- /* Setting local variables */
- int res = 0;
- int index = 0;
-
- /* XXX map may be NULL !! */
- int length = map->length;
- char* op = env->_operation;
-
- PRINT_MAP("switching on map", map);
-
- /* Initiating exception indicator */
- env->_major = CORBA_NO_EXCEPTION;
-
- if ((res = oe_prepare_request_decoding(env) < 0))
- return res;
-#if defined(DEBUG_MAP)
- fprintf(stdout, "looking for operation: %s\n", op); fflush(stdout);
-#endif
- for (index = 0; index < length; index++) {
-#if defined(DEBUG_MAP)
- fprintf(stdout, "map->operations[%d].name: %s\n",
- index, map->operations[index].name);
- fflush(stdout);
-#endif
- if(strcmp(map->operations[index].name, op) == 0) {
-#if defined(DEBUG_MAP)
- fprintf(stdout, "calling map->operations[%d].function: 0x%X\n",
- index, map->operations[index].function);
- fflush(stdout);
-#endif
- return map->operations[index].function(obj, env);
- }
- }
- /* Bad call */
- CORBA_exc_set(env, CORBA_SYSTEM_EXCEPTION, BAD_OPERATION,
- "Invalid operation");
- return -1;
-}
-
-/* For backward compatibility */
-int ___switch___(CORBA_Object obj, CORBA_Environment *env, oe_map_t *map)
-{
- return oe_exec_switch(obj, env, map);
-}
-
-
-oe_map_t* oe_merge_maps(oe_map_t *maps, int size)
-{
- int i, j, length, len, maplen, malloc_size;
- void *memp;
- oe_map_t *merged;
-
- if ((maps == NULL) || (size <= 0))
- return NULL;
-
- PRINT_MAPS("merging maps", maps, size);
-
- length = 0;
- for (i = 0; i < size; i++)
- length += (maps[i].length);
-
- maplen = OE_ALIGN(sizeof(oe_map_t));
- malloc_size = maplen + OE_ALIGN(length*sizeof(oe_operation_t));
- if ((memp = malloc(malloc_size)) == NULL)
- return NULL;
-
- merged = memp;
- merged->length = length;
- merged->operations = (oe_operation_t *)((char*)memp + maplen);
-
- for (i = 0, len = 0; i < size; i++) {
- for(j = 0 ; j < maps[i].length; j++)
- merged->operations[len+j] = maps[i].operations[j];
- len += maps[i].length;
- }
- PRINT_MAP("merged map", merged);
- return merged;
-}
-
-/* For backward compatibility */
-oe_map_t* ___merge___(oe_map_t *maps, int size)
-{
- return oe_merge_maps(maps, size);
-}
-
-/* Client send message (Erlang distribution protocol) */
-static int oe_send(CORBA_Environment *env)
-{
- if (strlen(env->_regname) == 0) {
- if (ei_send_encoded(env->_fd, env->_to_pid, env->_outbuf,
- env->_iout) < 0) {
- /* XXX Cannot send to peer? */
- CORBA_exc_set(env, CORBA_SYSTEM_EXCEPTION, NO_RESPONSE,
- "Cannot connect to server");
- return -1;
- }
- } else {
- if (ei_send_reg_encoded(env->_fd, env->_from_pid,
- env->_regname, env->_outbuf,
- env->_iout) < 0) {
- /* XXX Cannot send to peer? */
- CORBA_exc_set(env, CORBA_SYSTEM_EXCEPTION, NO_RESPONSE,
- "Cannot connect to server");
- return -1;
- }
- }
- return 0;
-}
-
-/* Send notification (gen_server client) */
-int oe_send_notification(CORBA_Environment *env)
-{
- return oe_send(env);
-}
-
-/* Send request and receive reply (gen_server client) */
-int oe_send_request_and_receive_reply(CORBA_Environment *env)
-{
- int msgType = 0;
- erlang_msg msg;
-
- if (oe_send(env) < 0)
- return -1;
-
- do {
- if ((msgType = ei_receive_encoded(env->_fd,
- &env->_inbuf,
- &env->_inbufsz,
- &msg, &env->_iin)) < 0) {
- CORBA_exc_set(env, CORBA_SYSTEM_EXCEPTION, MARSHAL,
- "Cannot decode message");
- return -1;
- }
- } while (msgType != ERL_SEND && msgType != ERL_REG_SEND);
-
- /* Extracting return message header */
- if (oe_prepare_reply_decoding(env) < 0) {
- CORBA_exc_set(env, CORBA_SYSTEM_EXCEPTION, MARSHAL, "Bad message");
- return -1;
- }
- return 0;
-}
-
-/* Prepare notification encoding (gen_server client) */
-int oe_prepare_notification_encoding(CORBA_Environment *env)
-{
- env->_iout = 0;
- oe_ei_encode_version(env);
- oe_ei_encode_tuple_header(env, 2);
- oe_ei_encode_atom(env, "$gen_cast");
- return 0;
-}
-
-/* Prepare request encoding (gen_server client) */
-int oe_prepare_request_encoding(CORBA_Environment *env)
-{
- int error = 0;
-
- env->_iout = 0;
- oe_ei_encode_version(env);
- oe_ei_encode_tuple_header(env, 3);
- oe_ei_encode_atom(env, "$gen_call");
- oe_ei_encode_tuple_header(env, 2);
- if ((error = oe_ei_encode_pid(env, env->_from_pid)) < 0)
- return error;
- if ((error = oe_ei_encode_ref(env, &env->_unique)) < 0)
- return error;
- return 0;
-}
-
-/* Prepare reply decoding (gen_server client) */
-int oe_prepare_reply_decoding(CORBA_Environment *env)
-{
- int error = 0;
- int version = 0;
- erlang_ref unique;
-
- env->_iin = 0;
- env->_received = 0;
-
- if ((error = ei_decode_version(env->_inbuf,
- &env->_iin,
- &version)) < 0)
- return error;
- if ((error = ei_decode_tuple_header(env->_inbuf,
- &env->_iin,
- &env->_received)) < 0)
- return error;
- if ((error = ei_decode_ref(env->_inbuf,
- &env->_iin,
- &unique)) < 0)
- return error;
- return ic_compare_refs(&env->_unique, &unique);
-}
-
-
-/* Prepare request decoding (gen_server server) */
-int oe_prepare_request_decoding(CORBA_Environment *env)
-{
- char gencall_atom[10];
- int error = 0;
- int version = 0;
-
- env->_iin = 0;
- env->_received = 0;
- memset(gencall_atom, 0, 10);
- ei_decode_version(env->_inbuf, &env->_iin, &version);
- ei_decode_tuple_header(env->_inbuf, &env->_iin, &env->_received);
- ei_decode_atom(env->_inbuf, &env->_iin, gencall_atom);
-
- if (strcmp(gencall_atom, "$gen_cast") == 0) {
- if ((error = ei_decode_atom(env->_inbuf, &env->_iin,
- env->_operation)) < 0) {
- ei_decode_tuple_header(env->_inbuf, &env->_iin, &env->_received);
- if ((error = ei_decode_atom(env->_inbuf, &env->_iin,
- env->_operation)) < 0) {
- CORBA_exc_set(env, CORBA_SYSTEM_EXCEPTION, BAD_OPERATION,
- "Bad Message, cannot extract operation");
- return error;
- }
- env->_received -= 1;
- } else
- env->_received -= 2;
- return 0;
- }
- if (strcmp(gencall_atom, "$gen_call") == 0) {
- ei_decode_tuple_header(env->_inbuf, &env->_iin, &env->_received);
- if ((error = ei_decode_pid(env->_inbuf, &env->_iin,
- &env->_caller)) < 0) {
- CORBA_exc_set(env, CORBA_SYSTEM_EXCEPTION, MARSHAL,
- "Bad Message, bad caller identity");
- return error;
- }
- if ((error = ei_decode_ref(env->_inbuf, &env->_iin,
- &env->_unique)) < 0) {
- CORBA_exc_set(env, CORBA_SYSTEM_EXCEPTION, MARSHAL,
- "Bad Message, bad message reference");
- return error;
- }
- if ((error = ei_decode_atom(env->_inbuf, &env->_iin,
- env->_operation)) < 0) {
-
- ei_decode_tuple_header(env->_inbuf, &env->_iin, &env->_received);
-
- if ((error = ei_decode_atom(env->_inbuf, &env->_iin,
- env->_operation)) < 0) {
- CORBA_exc_set(env, CORBA_SYSTEM_EXCEPTION, BAD_OPERATION,
- "Bad Message, cannot extract operation");
- return error;
- }
- env->_received -= 1;
- return 0;
- }
- else {
- env->_received -= 2;
- return 0;
- }
- }
-
- CORBA_exc_set(env, CORBA_SYSTEM_EXCEPTION, MARSHAL,
- "Bad message, neither cast nor call");
- return -1;
-}
-
-/* Prepare reply encoding (gen_server server) */
-int oe_prepare_reply_encoding(CORBA_Environment *env)
-{
- env->_iout = 0;
- oe_ei_encode_version(env);
- oe_ei_encode_tuple_header(env, 2);
- oe_ei_encode_ref(env, &env->_unique);
- return 0;
-}
-
-/* ---- Function for making it more easy to implement a server */
-/* Server receive (possibly) send reply (gen_server server) */
-
-int oe_server_receive(CORBA_Environment *env, oe_map_t *map)
-{
- int res = 0, loop = 1;
- erlang_msg msg;
-
- while (res >= 0 && loop > 0) {
- res = ei_receive_encoded(env->_fd, &env->_inbuf, &env->_inbufsz,
- &msg, &env->_iin);
- switch(res) {
- case ERL_SEND:
- case ERL_REG_SEND:
- oe_exec_switch(NULL, env, map);
- switch(env->_major) {
- case CORBA_NO_EXCEPTION:
- break;
- case CORBA_SYSTEM_EXCEPTION:
- /* XXX stderr */
- fprintf(stderr, "Request failure, reason : %s\n",
- (char *) CORBA_exception_value(env));
- CORBA_exception_free(env);
- break;
- default: /* Should not happen */
- CORBA_exception_free(env);
- break;
- }
- /* send reply */
- /* XXX We are required to set env->_iout = 0 if oneway?? */
- if (env->_iout > 0)
- ei_send_encoded(env->_fd, &env->_caller, env->_outbuf,
- env->_iout);
- loop = 0;
- break;
- case ERL_TICK:
- break;
- default:
- /* XXX */
- if (res < 0) {
- fprintf(stderr, "Result negative: %d\n", res);
- loop = 0;
- }
- break;
- }
- }
-
- return 0;
-}
-
diff --git a/lib/ic/c_src/ic_tmo.c b/lib/ic/c_src/ic_tmo.c
deleted file mode 100644
index ef66f67d55..0000000000
--- a/lib/ic/c_src/ic_tmo.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2004-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-static int oe_send_tmo(CORBA_Environment *env, unsigned int ms);
-
-/* Client send message (Erlang distribution protocol) */
-static int oe_send_tmo(CORBA_Environment *env, unsigned int ms)
-{
- if (strlen(env->_regname) == 0) {
- if (ei_send_encoded_tmo(env->_fd, env->_to_pid, env->_outbuf,
- env->_iout, ms) < 0) {
- /* XXX Cannot send to peer? */
- CORBA_exc_set(env, CORBA_SYSTEM_EXCEPTION, NO_RESPONSE,
- "Cannot connect to server");
- return -1;
- }
- } else {
- if (ei_send_reg_encoded_tmo(env->_fd, env->_from_pid,
- env->_regname, env->_outbuf,
- env->_iout, ms) < 0) {
- /* XXX Cannot send to peer? */
- CORBA_exc_set(env, CORBA_SYSTEM_EXCEPTION, NO_RESPONSE,
- "Cannot connect to server");
- return -1;
- }
- }
- return 0;
-}
-
-/* Send notification (gen_server client) */
-int oe_send_notification_tmo(CORBA_Environment *env, unsigned int send_ms)
-{
- return oe_send_tmo(env, send_ms);
-}
-
-/* Send request and receive reply (gen_server client) */
-int oe_send_request_and_receive_reply_tmo(CORBA_Environment *env,
- unsigned int send_ms,
- unsigned int recv_ms)
-{
- int msgType = 0;
- erlang_msg msg;
-
- if (oe_send_tmo(env, send_ms) < 0)
- return -1;
-
- do {
- if ((msgType = ei_receive_encoded_tmo(env->_fd,
- &env->_inbuf,
- &env->_inbufsz,
- &msg, &env->_iin,
- recv_ms)) < 0) {
- CORBA_exc_set(env, CORBA_SYSTEM_EXCEPTION, MARSHAL,
- "Cannot decode message");
- return -1;
- }
- } while (msgType != ERL_SEND && msgType != ERL_REG_SEND);
-
- /* Extracting return message header */
- if (oe_prepare_reply_decoding(env) < 0) {
- CORBA_exc_set(env, CORBA_SYSTEM_EXCEPTION, MARSHAL, "Bad message");
- return -1;
- }
- return 0;
-}
-
-/* Server receive (possibly) send reply (gen_server server) */
-
-int oe_server_receive_tmo(CORBA_Environment *env, oe_map_t *map,
- unsigned int send_ms,
- unsigned int recv_ms)
-{
- int res = 0, loop = 1;
- erlang_msg msg;
-
- while (res >= 0 && loop > 0) {
- res = ei_receive_encoded_tmo(env->_fd, &env->_inbuf, &env->_inbufsz,
- &msg, &env->_iin, recv_ms);
- switch(res) {
- case ERL_SEND:
- case ERL_REG_SEND:
- oe_exec_switch(NULL, env, map);
- switch(env->_major) {
- case CORBA_NO_EXCEPTION:
- break;
- case CORBA_SYSTEM_EXCEPTION:
- /* XXX stderr */
- fprintf(stderr, "Request failure, reason : %s\n",
- (char *) CORBA_exception_value(env));
- CORBA_exception_free(env);
- break;
- default: /* Should not happen */
- CORBA_exception_free(env);
- break;
- }
- /* send reply */
- /* XXX We are required to set env->_iout = 0 if oneway?? */
- if (env->_iout > 0)
- ei_send_encoded_tmo(env->_fd, &env->_caller, env->_outbuf,
- env->_iout, send_ms);
- loop = 0;
- break;
- case ERL_TICK:
- break;
- default:
- /* XXX */
- if (res < 0) {
- fprintf(stderr, "Result negative: %d\n", res);
- loop = 0;
- }
- break;
- }
- }
-
- return 0;
-}
-
diff --git a/lib/ic/c_src/oe_ei_code_erlang_binary.c b/lib/ic/c_src/oe_ei_code_erlang_binary.c
deleted file mode 100644
index 81610facbc..0000000000
--- a/lib/ic/c_src/oe_ei_code_erlang_binary.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2001-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_encode_erlang_binary(CORBA_Environment *ev, erlang_binary *binary) {
-
- int size = ev->_iout;
-
- ei_encode_binary(0, &size, binary->_buffer, binary->_length);
-
- if (size >= ev->_outbufsz) {
- char *buf = ev->_outbuf;
- int bufsz = ev->_outbufsz + ev->_memchunk;
-
- while (size >= bufsz)
- bufsz += ev->_memchunk;
-
- if ((buf = realloc(buf, bufsz)) == NULL) {
- CORBA_exc_set(ev, CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "End of heap memory while encoding");
- return -1; /* OUT OF MEMORY */
- }
-
- ev->_outbuf = buf;
- ev->_outbufsz = bufsz;
- }
-
- return ei_encode_binary(ev->_outbuf, &ev->_iout, binary->_buffer, binary->_length);
-}
-
-
-
-int oe_sizecalc_erlang_binary(CORBA_Environment *ev, int* _index, int* _size) {
-
- long _malloc_size = 0;
- int _error = 0;
-
- if(*_size == 0)
- *_size = ((*_size + sizeof(erlang_binary))+sizeof(double)-1)&~(sizeof(double)-1);
-
- if ((_error = ei_decode_binary(ev->_inbuf, _index, 0, &_malloc_size)) < 0)
- return _error;
-
- *_size = ((*_size + (int)_malloc_size)+sizeof(double)-1)&~(sizeof(double)-1);
-
- return 0;
-}
-
-
-int oe_decode_erlang_binary(CORBA_Environment *ev, char *_first, int* _index, erlang_binary *binary) {
-
- long _length = 0;
- int _error = 0;
-
- if((char*) binary == _first)
- *_index = ((*_index + sizeof(erlang_binary))+sizeof(double)-1)&~(sizeof(double)-1);
-
- binary->_buffer = (CORBA_octet *)(_first+*_index);
-
- if ((_error = ei_decode_binary(ev->_inbuf, &ev->_iin, binary->_buffer, &_length)) < 0)
- return _error;
-
- binary->_length = (CORBA_unsigned_long)_length;
-
- *_index = ((*_index)+_length+sizeof(double)-1)&~(sizeof(double)-1);
-
- return 0;
-}
-
-
-
-int print_erlang_binary(erlang_binary *binary) {
-
- int i=0;
-
- if (binary == NULL)
- return -1;
-
- fprintf(stdout,"binary->_length : %ld\n",binary->_length);
- fprintf(stdout,"binary->_buffer : ");
- if(binary->_buffer != NULL) {
- for (i=0; i<binary->_length; i++)
- fprintf(stdout,"%c",binary->_buffer[i]);
- fprintf(stdout,"\n");
- } else
- fprintf(stdout,"NULL\n");
- return 0;
-}
diff --git a/lib/ic/c_src/oe_ei_decode_longlong.c b/lib/ic/c_src/oe_ei_decode_longlong.c
deleted file mode 100644
index 7d872ce94f..0000000000
--- a/lib/ic/c_src/oe_ei_decode_longlong.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_decode_longlong(const char *buf, int *index, CORBA_long_long *p) {
- return ei_decode_long(buf, index, p);
-}
diff --git a/lib/ic/c_src/oe_ei_decode_ulonglong.c b/lib/ic/c_src/oe_ei_decode_ulonglong.c
deleted file mode 100644
index d071d09a43..0000000000
--- a/lib/ic/c_src/oe_ei_decode_ulonglong.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_decode_ulonglong(const char *buf, int *index, CORBA_unsigned_long_long *p) {
- return ei_decode_ulong(buf, index, p);
-}
diff --git a/lib/ic/c_src/oe_ei_decode_wchar.c b/lib/ic/c_src/oe_ei_decode_wchar.c
deleted file mode 100644
index bb6899b7b3..0000000000
--- a/lib/ic/c_src/oe_ei_decode_wchar.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_decode_wchar(const char *buf, int *index, CORBA_wchar *p) {
- return ei_decode_ulong(buf, index, p);
-}
diff --git a/lib/ic/c_src/oe_ei_decode_wstring.c b/lib/ic/c_src/oe_ei_decode_wstring.c
deleted file mode 100644
index 5b676fd579..0000000000
--- a/lib/ic/c_src/oe_ei_decode_wstring.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-/* Scratch function */
-int oe_ei_decode_wstring(const char *buf, int *index, CORBA_wchar *p) {
-
- int length,error_code,type,tmp=0;
- char * tmp_space = NULL;
-
-
- if ((error_code = ei_get_type(buf, index, &type, &length)) < 0)
- return error_code;
-
- switch(type) {
-
- case ERL_LIST_EXT: /* A list */
- case ERL_NIL_EXT: /* An empty list */
-
- if (p) { /* Decoding part */
-
- if ((error_code = ei_decode_list_header(buf, index, &length)) < 0)
- return error_code;
-
- if (length != 0) {
- for(tmp = 0; tmp < length; tmp++)
- if ((error_code = oe_ei_decode_wchar(buf, index, &(p[tmp]))) < 0)
- return error_code;
-
- /* Read list tail also */
- if ((error_code = ei_decode_list_header(buf, index, &length)) < 0)
- return error_code;
- }
-
- p[tmp] = 0; /* Wide NULL */
-
- } else { /* Allocation counting part */
-
- if ((error_code = ei_decode_list_header(buf, index, &length)) < 0)
- return error_code;
-
- if (length != 0) {
- for(tmp = 0; tmp < length; tmp++)
- if ((error_code = oe_ei_decode_wchar(buf, index, 0)) < 0)
- return error_code;
-
- /* Read list tail also */
- if ((error_code = ei_decode_list_header(buf, index, &length)) < 0)
- return error_code;
- }
- }
-
- break;
-
- case ERL_STRING_EXT: /* A string */
-
- if (p) { /* Decoding part */
-
- /* Allocate temporary string */
- tmp_space = (char*) malloc(length*(__OE_WCHARSZ__+1));
-
- if ((error_code = ei_decode_string(buf, index, tmp_space)) < 0)
- return error_code;
-
- /* Assign characters to wide characters */
- for(tmp = 0; tmp < length; tmp++)
- p[tmp] = tmp_space[tmp];
-
- p[tmp] = 0; /* Wide NULL */
-
- /* Free temporary string */
- CORBA_free(tmp_space);
-
- } else { /* Allocation counting part */
-
- if ((error_code = ei_decode_string(buf, index, 0)) < 0)
- return error_code;
-
- }
- break;
-
- default: /* Bad header */
- return -1;
- }
-
- return 0;
-}
-
-
diff --git a/lib/ic/c_src/oe_ei_encode_atom.c b/lib/ic/c_src/oe_ei_encode_atom.c
deleted file mode 100644
index 758586d1d4..0000000000
--- a/lib/ic/c_src/oe_ei_encode_atom.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_encode_atom(CORBA_Environment *ev, const char *p) {
- int size = ev->_iout;
-
- ei_encode_atom(0,&size,p);
-
- if (size >= ev->_outbufsz) {
- char *buf = ev->_outbuf;
- int bufsz = ev->_outbufsz + ev->_memchunk;
-
- while (size >= bufsz)
- bufsz += ev->_memchunk;
-
- if ((buf = realloc(buf, bufsz)) == NULL) {
- CORBA_exc_set(ev, CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "End of heap memory while encoding");
- return -1; /* OUT OF MEMORY */
- }
-
- ev->_outbuf = buf;
- ev->_outbufsz = bufsz;
- }
-
- return ei_encode_atom(ev->_outbuf,&ev->_iout,p);
-}
-
diff --git a/lib/ic/c_src/oe_ei_encode_char.c b/lib/ic/c_src/oe_ei_encode_char.c
deleted file mode 100644
index 9079cb4ecc..0000000000
--- a/lib/ic/c_src/oe_ei_encode_char.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_encode_char(CORBA_Environment *ev, char p) {
- int size = ev->_iout + __OE_CHARSZ__;
-
- if (size >= ev->_outbufsz) {
- char *buf = ev->_outbuf;
- int bufsz = ev->_outbufsz + ev->_memchunk;
-
- if ((buf = realloc(buf,bufsz)) != NULL) {
- ev->_outbuf = buf;
- ev->_outbufsz += ev->_memchunk;
- }
- else {
- CORBA_exc_set(ev, CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "End of heap memory while encoding");
- return -1; /* OUT OF MEMORY */
- }
- }
-
- return ei_encode_char(ev->_outbuf, &ev->_iout, p);
-}
-
-
-
diff --git a/lib/ic/c_src/oe_ei_encode_double.c b/lib/ic/c_src/oe_ei_encode_double.c
deleted file mode 100644
index 95fed6ff25..0000000000
--- a/lib/ic/c_src/oe_ei_encode_double.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_encode_double(CORBA_Environment *ev, double p) {
- int size = ev->_iout + __OE_DOUBLESZ__;
-
- if (size >= ev->_outbufsz) {
- char *buf = ev->_outbuf;
- int bufsz = ev->_outbufsz + ev->_memchunk;
-
- if ((buf = realloc(buf,bufsz)) != NULL) {
- ev->_outbuf = buf;
- ev->_outbufsz += ev->_memchunk;
- }
- else {
- CORBA_exc_set(ev, CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "End of heap memory while encoding");
- return -1; /* OUT OF MEMORY */
- }
- }
-
- return ei_encode_double(ev->_outbuf, &ev->_iout, p);
-}
-
-
diff --git a/lib/ic/c_src/oe_ei_encode_list_header.c b/lib/ic/c_src/oe_ei_encode_list_header.c
deleted file mode 100644
index 57a0fc0d0f..0000000000
--- a/lib/ic/c_src/oe_ei_encode_list_header.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_encode_list_header(CORBA_Environment *ev, int arity) {
- int size = ev->_iout + __OE_LISTHDRSZ__;
-
- if (size >= ev->_outbufsz) {
- char *buf = ev->_outbuf;
- int bufsz = ev->_outbufsz + ev->_memchunk;
-
- if ((buf = realloc(buf,bufsz)) != NULL) {
- ev->_outbuf = buf;
- ev->_outbufsz += ev->_memchunk;
- }
- else {
- CORBA_exc_set(ev, CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "End of heap memory while encoding");
- return -1; /* OUT OF MEMORY */
- }
- }
-
- return ei_encode_list_header(ev->_outbuf, &ev->_iout, arity);
-}
diff --git a/lib/ic/c_src/oe_ei_encode_long.c b/lib/ic/c_src/oe_ei_encode_long.c
deleted file mode 100644
index c0d8599b95..0000000000
--- a/lib/ic/c_src/oe_ei_encode_long.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_encode_long(CORBA_Environment *ev, long p) {
- int size = ev->_iout + __OE_LONGSZ__;
-
- if (size >= ev->_outbufsz) {
- char *buf = ev->_outbuf;
- int bufsz = ev->_outbufsz + ev->_memchunk;
-
- if ((buf = realloc(buf,bufsz)) != NULL) {
- ev->_outbuf = buf;
- ev->_outbufsz += ev->_memchunk;
- }
- else {
- CORBA_exc_set(ev, CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "End of heap memory while encoding");
- return -1; /* OUT OF MEMORY */
- }
- }
-
- return ei_encode_long(ev->_outbuf, &ev->_iout, p);
-}
-
-
-
diff --git a/lib/ic/c_src/oe_ei_encode_longlong.c b/lib/ic/c_src/oe_ei_encode_longlong.c
deleted file mode 100644
index ac208f1982..0000000000
--- a/lib/ic/c_src/oe_ei_encode_longlong.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_encode_longlong(CORBA_Environment *ev, CORBA_long_long p) {
- int size = ev->_iout + __OE_LONGLONGSZ__;
-
- if (size >= ev->_outbufsz) {
- char *buf = ev->_outbuf;
- int bufsz = ev->_outbufsz + ev->_memchunk;
-
- if ((buf = realloc(buf,bufsz)) != NULL) {
- ev->_outbuf = buf;
- ev->_outbufsz += ev->_memchunk;
- }
- else {
- CORBA_exc_set(ev, CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "End of heap memory while encoding");
- return -1; /* OUT OF MEMORY */
- }
- }
-
- /* CORBA_long_long = long because of erl_interface limitation */
- return ei_encode_long(ev->_outbuf, &ev->_iout, p);
-}
-
-
diff --git a/lib/ic/c_src/oe_ei_encode_pid.c b/lib/ic/c_src/oe_ei_encode_pid.c
deleted file mode 100644
index ebd0d0b6ef..0000000000
--- a/lib/ic/c_src/oe_ei_encode_pid.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_encode_pid(CORBA_Environment *ev, const erlang_pid *p) {
- int size = ev->_iout;
-
- ei_encode_pid(NULL, &size, p);
-
- if (size >= ev->_outbufsz) {
- char *buf = ev->_outbuf;
- int bufsz = ev->_outbufsz + ev->_memchunk;
-
- while (size >= bufsz)
- bufsz += ev->_memchunk;
-
- if ((buf = realloc(buf, bufsz)) == NULL) {
- CORBA_exc_set(ev, CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "End of heap memory while encoding");
- return -1; /* OUT OF MEMORY */
- }
-
- ev->_outbuf = buf;
- ev->_outbufsz = bufsz;
- }
-
- return ei_encode_pid(ev->_outbuf, &ev->_iout, p);
-}
diff --git a/lib/ic/c_src/oe_ei_encode_port.c b/lib/ic/c_src/oe_ei_encode_port.c
deleted file mode 100644
index a4ecf846b7..0000000000
--- a/lib/ic/c_src/oe_ei_encode_port.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_encode_port(CORBA_Environment *ev, const erlang_port *p) {
- int size = ev->_iout;
-
- ei_encode_port(NULL, &size, p);
-
- if (size >= ev->_outbufsz) {
- char *buf = ev->_outbuf;
- int bufsz = ev->_outbufsz + ev->_memchunk;
-
- while (size >= bufsz)
- bufsz += ev->_memchunk;
-
- if ((buf = realloc(buf, bufsz)) == NULL) {
- CORBA_exc_set(ev, CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "End of heap memory while encoding");
- return -1; /* OUT OF MEMORY */
- }
-
- ev->_outbuf = buf;
- ev->_outbufsz = bufsz;
- }
-
- return ei_encode_port(ev->_outbuf, &ev->_iout, p);
-}
-
diff --git a/lib/ic/c_src/oe_ei_encode_ref.c b/lib/ic/c_src/oe_ei_encode_ref.c
deleted file mode 100644
index 8dcbc3aeb7..0000000000
--- a/lib/ic/c_src/oe_ei_encode_ref.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_encode_ref(CORBA_Environment *ev, const erlang_ref *p) {
- int size = ev->_iout;
-
- ei_encode_ref(NULL, &size, p);
-
- if (size >= ev->_outbufsz) {
- char *buf = ev->_outbuf;
- int bufsz = ev->_outbufsz + ev->_memchunk;
-
- while (size >= bufsz)
- bufsz += ev->_memchunk;
-
- if ((buf = realloc(buf, bufsz)) == NULL) {
- CORBA_exc_set(ev, CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "End of heap memory while encoding");
- return -1; /* OUT OF MEMORY */
- }
-
- ev->_outbuf = buf;
- ev->_outbufsz = bufsz;
- }
-
- return ei_encode_ref(ev->_outbuf, &ev->_iout, p);
-}
-
diff --git a/lib/ic/c_src/oe_ei_encode_string.c b/lib/ic/c_src/oe_ei_encode_string.c
deleted file mode 100644
index 8612835e2b..0000000000
--- a/lib/ic/c_src/oe_ei_encode_string.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_encode_string(CORBA_Environment *ev, const char *p) {
- int size = ev->_iout;
-
- ei_encode_string(0,&size,p);
-
- if (size >= ev->_outbufsz) {
- char *buf = ev->_outbuf;
- int bufsz = ev->_outbufsz + ev->_memchunk;
-
- while (size >= bufsz)
- bufsz += ev->_memchunk;
-
- if ((buf = realloc(buf, bufsz)) == NULL) {
- CORBA_exc_set(ev, CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "End of heap memory while encoding");
- return -1; /* OUT OF MEMORY */
- }
-
- ev->_outbuf = buf;
- ev->_outbufsz = bufsz;
- }
-
- return ei_encode_string(ev->_outbuf,&ev->_iout,p);
-}
-
-
diff --git a/lib/ic/c_src/oe_ei_encode_term.c b/lib/ic/c_src/oe_ei_encode_term.c
deleted file mode 100644
index c36edbf493..0000000000
--- a/lib/ic/c_src/oe_ei_encode_term.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_encode_term(CORBA_Environment *ev, void *t) {
- int size = ev->_iout;
-
- ei_encode_term(NULL, &size, t);
-
- if (size >= ev->_outbufsz) {
- char *buf = ev->_outbuf;
- int bufsz = ev->_outbufsz + ev->_memchunk;
-
- while (size >= bufsz)
- bufsz += ev->_memchunk;
-
- if ((buf = realloc(buf, bufsz)) == NULL) {
- CORBA_exc_set(ev, CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "End of heap memory while encoding");
- return -1; /* OUT OF MEMORY */
- }
-
- ev->_outbuf = buf;
- ev->_outbufsz = bufsz;
- }
-
- return ei_encode_term(ev->_outbuf, &ev->_iout, t);
-}
-
-
-
diff --git a/lib/ic/c_src/oe_ei_encode_tuple_header.c b/lib/ic/c_src/oe_ei_encode_tuple_header.c
deleted file mode 100644
index 64f8b4b873..0000000000
--- a/lib/ic/c_src/oe_ei_encode_tuple_header.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_encode_tuple_header(CORBA_Environment *ev, int arity) {
- int size = ev->_iout + __OE_TUPLEHDRSZ__;
-
- if (size >= ev->_outbufsz) {
- char *buf = ev->_outbuf;
- int bufsz = ev->_outbufsz + ev->_memchunk;
-
- if ((buf = realloc(buf,bufsz)) != NULL) {
- ev->_outbuf = buf;
- ev->_outbufsz += ev->_memchunk;
- }
- else {
- CORBA_exc_set(ev, CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "End of heap memory while encoding");
- return -1; /* OUT OF MEMORY */
- }
- }
-
- return ei_encode_tuple_header(ev->_outbuf, &ev->_iout, arity);
-}
-
-
-
diff --git a/lib/ic/c_src/oe_ei_encode_ulong.c b/lib/ic/c_src/oe_ei_encode_ulong.c
deleted file mode 100644
index 249235935e..0000000000
--- a/lib/ic/c_src/oe_ei_encode_ulong.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_encode_ulong(CORBA_Environment *ev, unsigned long p) {
- int size = ev->_iout + __OE_ULONGSZ__;
-
- if (size >= ev->_outbufsz) {
- char *buf = ev->_outbuf;
- int bufsz = ev->_outbufsz + ev->_memchunk;
-
- if ((buf = realloc(buf,bufsz)) != NULL) {
- ev->_outbuf = buf;
- ev->_outbufsz += ev->_memchunk;
- }
- else {
- CORBA_exc_set(ev, CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "End of heap memory while encoding");
- return -1; /* OUT OF MEMORY */
- }
- }
-
- return ei_encode_ulong(ev->_outbuf, &ev->_iout, p);
-}
-
-
diff --git a/lib/ic/c_src/oe_ei_encode_ulonglong.c b/lib/ic/c_src/oe_ei_encode_ulonglong.c
deleted file mode 100644
index 7997f4ea39..0000000000
--- a/lib/ic/c_src/oe_ei_encode_ulonglong.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_encode_ulonglong(CORBA_Environment *ev, CORBA_unsigned_long_long p) {
- int size = ev->_iout + __OE_ULONGLONGSZ__;
-
- if (size >= ev->_outbufsz) {
- char *buf = ev->_outbuf;
- int bufsz = ev->_outbufsz + ev->_memchunk;
-
- if ((buf = realloc(buf,bufsz)) != NULL) {
- ev->_outbuf = buf;
- ev->_outbufsz += ev->_memchunk;
- }
- else {
- CORBA_exc_set(ev, CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "End of heap memory while encoding");
- return -1; /* OUT OF MEMORY */
- }
- }
-
- /* CORBA_long_long = long because of erl_interface limitation */
- return ei_encode_ulong(ev->_outbuf, &ev->_iout, p);
-}
-
-
diff --git a/lib/ic/c_src/oe_ei_encode_version.c b/lib/ic/c_src/oe_ei_encode_version.c
deleted file mode 100644
index 4bc6256c32..0000000000
--- a/lib/ic/c_src/oe_ei_encode_version.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_encode_version(CORBA_Environment *ev) {
- int size = ev->_iout + __OE_VSNSZ__;
-
- if (size >= ev->_outbufsz) {
- char *buf = ev->_outbuf;
- int bufsz = ev->_outbufsz + ev->_memchunk;
-
- if ((buf = realloc(buf,bufsz)) != NULL) {
- ev->_outbuf = buf;
- ev->_outbufsz += ev->_memchunk;
- }
- else {
- CORBA_exc_set(ev, CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "End of heap memory while encoding");
- return -1; /* OUT OF MEMORY */
- }
- }
-
- return ei_encode_version(ev->_outbuf, &ev->_iout);
-}
-
diff --git a/lib/ic/c_src/oe_ei_encode_wchar.c b/lib/ic/c_src/oe_ei_encode_wchar.c
deleted file mode 100644
index 0fd4027886..0000000000
--- a/lib/ic/c_src/oe_ei_encode_wchar.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_encode_wchar(CORBA_Environment *ev, CORBA_wchar p) {
- return oe_ei_encode_ulong(ev, p);
-}
-
-
diff --git a/lib/ic/c_src/oe_ei_encode_wstring.c b/lib/ic/c_src/oe_ei_encode_wstring.c
deleted file mode 100644
index a799d475e7..0000000000
--- a/lib/ic/c_src/oe_ei_encode_wstring.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <ic.h>
-
-
-int oe_ei_encode_wstring(CORBA_Environment *ev, CORBA_wchar *p) {
-
- int len,wchar,size,tmp,error_code;
-
- len = ic_wstrlen(p);
- size = ev->_iout + __OE_LISTHDRSZ__ +(len * __OE_WCHARSZ__);
-
- if (size >= ev->_outbufsz) {
- char *buf = ev->_outbuf;
- int bufsz = ev->_outbufsz + ev->_memchunk;
-
- while (size >= bufsz)
- bufsz += ev->_memchunk;
-
- if ((buf = realloc(buf, bufsz)) == NULL) {
- CORBA_exc_set(ev, CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "End of heap memory while encoding");
- return -1; /* OUT OF MEMORY */
- }
-
- ev->_outbuf = buf;
- ev->_outbufsz = bufsz;
- }
-
- /* Encode the wide string */
- error_code = 0;
-
- if ((error_code = oe_ei_encode_list_header(ev, len)) < 0)
- return error_code;
-
- for(tmp = 0; tmp < len; tmp++)
- if ((error_code = oe_ei_encode_wchar(ev, p[tmp])) < 0)
- return error_code;
-
- if ((error_code = oe_ei_encode_empty_list(ev)) < 0)
- return error_code;
-
- return 0;
-}
-
-
diff --git a/lib/ic/doc/html/.gitignore b/lib/ic/doc/html/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ic/doc/html/.gitignore
+++ /dev/null
diff --git a/lib/ic/doc/man1/.gitignore b/lib/ic/doc/man1/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ic/doc/man1/.gitignore
+++ /dev/null
diff --git a/lib/ic/doc/man3/.gitignore b/lib/ic/doc/man3/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ic/doc/man3/.gitignore
+++ /dev/null
diff --git a/lib/ic/doc/pdf/.gitignore b/lib/ic/doc/pdf/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ic/doc/pdf/.gitignore
+++ /dev/null
diff --git a/lib/ic/doc/src/CORBA_Environment_alloc.xml b/lib/ic/doc/src/CORBA_Environment_alloc.xml
deleted file mode 100644
index 357d9c2e8a..0000000000
--- a/lib/ic/doc/src/CORBA_Environment_alloc.xml
+++ /dev/null
@@ -1,143 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE cref SYSTEM "cref.dtd">
-
-<cref>
- <header>
- <copyright>
- <year>1998</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CORBA_Environment_alloc</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>1998-12-01</date>
- <rev>A</rev>
- </header>
- <lib>CORBA_Environment_alloc</lib>
- <libsummary>Allocation function for the CORBA_Environement struct</libsummary>
- <description>
- <p>The <em>CORBA_Environment_alloc()</em> function is the
- function used to allocate and initiate the <em>CORBA_Environment</em>
- structure.</p>
- </description>
- <funcs>
- <func>
- <name><ret>CORBA_Environment *</ret><nametext>CORBA_Environment_alloc(inbufsz, outbufsz)</nametext></name>
- <fsummary>Initialize communication</fsummary>
- <type>
- <v>int inbufsz;</v>
- <v>int outbufsz;</v>
- </type>
- <desc>
- <p>This function is used to create and initiate the <c>CORBA_Environment</c>
- structure. In particular, it is used to dynamically allocate a CORBA_Environment
- structure and set the default values for the structure's fields. </p>
- <p><em>inbufsize</em> is the wished size of input buffer.</p>
- <p><em>outbufsize</em> is the wished size of output buffer.</p>
- <p><em>CORBA_Environment</em> is the CORBA 2.0 state structure used by the
- generated stub.</p>
- <p>This function will set all needed default values and allocate buffers equal
- to the values passed, but will not allocate space for the _to_pid and _from_pid fields.</p>
- <p>To free the space allocated by CORBA_Environment_alloc/2 :</p>
- <list type="bulleted">
- <item>
- <p>First call CORBA_free for the input and output buffers.</p>
- </item>
- <item>
- <p>After freeing the buffer space, call CORBA_free for the CORBA_Environment space. </p>
- </item>
- </list>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>The CORBA_Environment structure</title>
- <p>Here is the complete definition of the CORBA_Environment structure,
- defined in file <em>ic.h</em> : </p>
- <code type="none">
-/* Environment definition */
-typedef struct {
-
- /*----- CORBA compatibility part ------------------------*/
- /* Exception tag, initially set to CORBA_NO_EXCEPTION ---*/
- CORBA_exception_type _major;
-
- /*----- External Implementation part - initiated by the user ---*/
- /* File descriptor */
- int _fd;
- /* Size of input buffer */
- int _inbufsz;
- /* Pointer to always dynamically allocated buffer for input */
- char *_inbuf;
- /* Size of output buffer */
- int _outbufsz;
- /* Pointer to always dynamically allocated buffer for output */
- char *_outbuf;
- /* Size of memory chunks in bytes, used for increasing the output
- buffer, set to >= 32, should be around >= 1024 for performance
- reasons */
- int _memchunk;
- /* Pointer for registered name */
- char _regname[256];
- /* Process identity for caller */
- erlang_pid *_to_pid;
- /* Process identity for callee */
- erlang_pid *_from_pid;
-
- /*- Internal Implementation part - used by the server/client ---*/
- /* Index for input buffer */
- int _iin;
- /* Index for output buffer */
- int _iout;
- /* Pointer for operation name */
- char _operation[256];
- /* Used to count parameters */
- int _received;
- /* Used to identify the caller */
- erlang_pid _caller;
- /* Used to identify the call */
- erlang_ref _unique;
- /* Exception id field */
- CORBA_char *_exc_id;
- /* Exception value field */
- void *_exc_value;
-
-
-} CORBA_Environment;
- </code>
- <note>
- <p>Remember to set the field values <em>_fd </em>, <em>_regname </em>, <em>*_to_pid </em> and/or
- <em>*_from_pid </em> to the appropriate application values. These are not automatically
- set by the stubs.</p>
- </note>
- <warning>
- <p>Never assign static buffers to the buffer pointers, never set the <em>_memchunk</em> field to
- a value less than <em>32</em>.</p>
- </warning>
- </section>
-
- <section>
- <title>SEE ALSO</title>
- <p>ic(3)</p>
- </section>
-
-</cref>
-
-
diff --git a/lib/ic/doc/src/Makefile b/lib/ic/doc/src/Makefile
deleted file mode 100644
index 19f12ac6b9..0000000000
--- a/lib/ic/doc/src/Makefile
+++ /dev/null
@@ -1,232 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1998-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(IC_VSN)
-APPLICATION=ic
-
-# ----------------------------------------------------
-# Java specific
-# ----------------------------------------------------
-JAVADOC=javadoc
-JAVA_INCL_ROOT = $(ERL_TOP)/lib/jinterface/priv/
-JAVA_SRC_ROOT = $(ERL_TOP)/lib/ic/java_src/
-JAVA_CLASS_SUBDIR = com/ericsson/otp/ic/
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = ic.xml \
- ic_clib.xml \
- ic_c_protocol.xml
-
-XML_PART_FILES = part.xml \
- part_notes.xml
-
-XML_CHAPTER_FILES = \
- ch_introduction.xml \
- ch_basic_idl.xml \
- ch_ic_protocol.xml \
- ch_erl_plain.xml \
- ch_erl_genserv.xml \
- ch_c_mapping.xml \
- ch_c_client.xml \
- ch_c_server.xml \
- ch_c_corba_env.xml \
- ch_java.xml \
- notes.xml
-
-BOOK_FILES = book.xml
-
-XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \
- $(XML_PART_FILES) $(XML_CHAPTER_FILES)
-
-GIF_FILES = \
- book.gif \
- notes.gif \
- ref_man.gif \
- user_guide.gif
-
-# ----------------------------------------------------
-
-HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
-
-INFO_FILE = ../../info
-EXTRA_FILES = summary.html.src \
- $(DEFAULT_GIF_FILES) \
- $(DEFAULT_HTML_FILES) \
- $(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html)
-
-MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-
-HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
-
-TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-
-JAVA_SOURCE_FILES = \
- Holder.java \
- BooleanHolder.java \
- ByteHolder.java \
- CharHolder.java \
- DoubleHolder.java \
- FloatHolder.java \
- IntHolder.java \
- LongHolder.java \
- ShortHolder.java \
- StringHolder.java \
- Environment.java \
- Any.java \
- AnyHelper.java \
- AnyHolder.java \
- TypeCode.java \
- TCKind.java \
- Pid.java \
- PidHolder.java \
- PidHelper.java \
- Ref.java \
- RefHolder.java \
- RefHelper.java \
- Port.java \
- PortHolder.java \
- PortHelper.java \
- Term.java \
- TermHolder.java \
- TermHelper.java
-
-
-JD_INDEX_HTML_FILES = \
- allclasses-frame.html \
- allclasses-noframe.html \
- deprecated-list.html \
- index-all.html \
- overview-tree.html \
- stylesheet.css \
- help-doc.html \
- index.html \
- package-list \
- serialized-form.html \
- constant-values.html
-
-JD_GIF_FILES = \
- ../html/java/resources/inherit.gif
-
-
-PACK_DIR = com/ericsson/otp/ic
-JAVA_SOURCE_DIR = ../../java_src/$(PACK_DIR)
-JAVA_OUT_DIR = ../html/java
-
-JD_PACK_HTML_FILES = \
- package-frame.html \
- package-summary.html \
- package-tree.html
-
-JAVADOC_PACK_HTML_FILES = \
- $(JAVA_SOURCE_FILES:%.java=$(JAVA_OUT_DIR)/$(PACK_DIR)/%.html) \
- $(JD_PACK_HTML_FILES:%=$(JAVA_OUT_DIR)/$(PACK_DIR)/%)
-
-JAVADOC_INDEX_HTML_FILES = $(JD_INDEX_HTML_FILES:%=$(JAVA_OUT_DIR)/%)
-
-JAVADOC_GENERATED_FILES = $(JAVADOC_PACK_HTML_FILES) $(JAVADOC_INDEX_HTML_FILES)
-
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-CLASSPATH = $(JAVA_SRC_ROOT):$(JAVA_INCL_ROOT)
-
-XML_FLAGS +=
-DVIPS_FLAGS +=
-JAVADOCFLAGS = \
- -classpath $(CLASSPATH) \
- -d ../doc/html/java \
- -windowtitle "Package com.ericsson.otp.ic version $(IC_VSN)" \
- -public \
- -footer "<CENTER><FONT SIZE=-1>Copyright &copy; 1991-2007 Ericsson AB<BR> </FONT> </CENTER>"
-
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-$(HTMLDIR)/%.gif: %.gif
- $(INSTALL_DATA) $< $@
-
-ifneq (,$(JAVA))
-docs: pdf html man $(JAVADOC_GENERATED_FILES)
-else
-docs: pdf html man
-endif
-
-$(TOP_PDF_FILE): $(XML_FILES)
-
-pdf: $(TOP_PDF_FILE)
-
-html: gifs $(HTML_REF_MAN_FILE)
-
-clean clean_docs:
- rm -rf $(HTMLDIR)/*
- rm -f $(MAN3DIR)/*
- rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
-
-$(JAVADOC_GENERATED_FILES): JAVADOC-GENERATED
-
-JAVADOC-GENERATED: $(JAVA_SOURCE_FILES:%=$(JAVA_SOURCE_DIR)/%)
- @(cd ../../java_src; $(JAVADOC) $(JAVADOCFLAGS) com.ericsson.otp.ic)
- >JAVADOC-GENERATED
-
-man: $(MAN3_FILES)
-
-gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-
-$(INDEX_TARGET): $(INDEX_SRC) ../../vsn.mk
- sed -e 's;%VSN%;$(VSN);' $< > $@
-
-debug opt:
-
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_docs_spec: docs
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
- ($(CP) -rf $(HTMLDIR) "$(RELSYSDIR)/doc")
- $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
- $(INSTALL_DATA) $(MAN3_FILES) "$(RELEASE_PATH)/man/man3"
-
-release_spec:
diff --git a/lib/ic/doc/src/book.gif b/lib/ic/doc/src/book.gif
deleted file mode 100644
index 94b3868792..0000000000
--- a/lib/ic/doc/src/book.gif
+++ /dev/null
Binary files differ
diff --git a/lib/ic/doc/src/book.xml b/lib/ic/doc/src/book.xml
deleted file mode 100644
index f6ef824f63..0000000000
--- a/lib/ic/doc/src/book.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book xmlns:xi="http://www.w3.org/2001/XInclude">
- <header titlestyle="normal">
- <copyright>
- <year>1998</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>ic</title>
- <prepared></prepared>
- <docno></docno>
- <date>1998-09-29</date>
- <rev>4.0.4</rev>
- <file>book.sgml</file>
- </header>
- <insidecover>
- </insidecover>
- <pagetext>ic</pagetext>
- <preamble>
- <contents level="2"></contents>
- </preamble>
- <parts lift="no">
- <xi:include href="part.xml"/>
- </parts>
- <applications>
- <xi:include href="ref_man.xml"/>
- </applications>
- <releasenotes>
- <xi:include href="notes.xml"/>
- </releasenotes>
- <listofterms></listofterms>
- <index></index>
-</book>
-
diff --git a/lib/ic/doc/src/c-part.xml b/lib/ic/doc/src/c-part.xml
deleted file mode 100644
index 968dd3135f..0000000000
--- a/lib/ic/doc/src/c-part.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2002</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>IDL to C language Mapping</title>
- <prepared></prepared>
- <docno></docno>
- <date>2002-06-25</date>
- <rev>A</rev>
- </header>
- <description>
- <p>IDL to C</p>
- </description>
- <include file="ch_c_mapping"></include>
- <include file="ch_c_client"></include>
- <include file="ch_c_server"></include>
- <include file="ch_c_corba_env"></include>
-</part>
-
diff --git a/lib/ic/doc/src/ch_basic_idl.xml b/lib/ic/doc/src/ch_basic_idl.xml
deleted file mode 100644
index 485a0c44e5..0000000000
--- a/lib/ic/doc/src/ch_basic_idl.xml
+++ /dev/null
@@ -1,164 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2002</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>OMG IDL</title>
- <prepared></prepared>
- <docno></docno>
- <date>2002-07-15</date>
- <rev></rev>
- <file>ch_basic_idl.xml</file>
- </header>
-
- <section>
- <title>OMG IDL - Overview</title>
- <p>The purpose of OMG IDL, <em>Interface Definition Language</em>, mapping
- is to act as translator between platforms and languages. An IDL
- specification is supposed to describe data types, object types etc.</p>
- <p>Since the <c>C</c> and <c>Java</c> IC backends only supports a subset of the
- IDL types supported by the other backends, the mapping is divided into
- different parts. For more information about IDL to Erlang mapping,
- i.e., <c>CORBA</c>, plain Erlang and generic Erlang Server, see the Orber
- User's Guide. How to use the plain Erlang and generic Erlang Server is
- found in this User's Guide.</p>
-
- <section>
- <title>Reserved Compiler Names and Keywords</title>
- <p>The use of some names is strongly discouraged due to
- ambiguities. However, the use of some names is prohibited
- when using the Erlang mapping , as they are strictly reserved for IC.</p>
- <p>IC reserves all identifiers starting with <c>OE_</c> and <c>oe_</c>
- for internal use.</p>
- <p>Note also, that an identifier in IDL can contain alphabetic,
- digits and underscore characters, but the first character
- <em>must</em> be alphabetic.
- </p>
- <p>Using underscores in IDL names can lead to ambiguities
- due to the name mapping described above. It is advisable to
- avoid the use of underscores in identifiers.</p>
- <p>The OMG defines a set of reserved words, shown below, for use as keywords.
- These may <em>not</em> be used as, for example, identifiers.</p>
- <table>
- <row>
- <cell align="left" valign="middle">abstract</cell>
- <cell align="left" valign="middle">double</cell>
- <cell align="left" valign="middle">local</cell>
- <cell align="left" valign="middle">raises</cell>
- <cell align="left" valign="middle">typedef</cell>
- </row>
- <row>
- <cell align="left" valign="middle">any</cell>
- <cell align="left" valign="middle">exception</cell>
- <cell align="left" valign="middle">long</cell>
- <cell align="left" valign="middle">readonly</cell>
- <cell align="left" valign="middle">unsigned</cell>
- </row>
- <row>
- <cell align="left" valign="middle">attribute</cell>
- <cell align="left" valign="middle">enum</cell>
- <cell align="left" valign="middle">module</cell>
- <cell align="left" valign="middle">sequence</cell>
- <cell align="left" valign="middle">union</cell>
- </row>
- <row>
- <cell align="left" valign="middle">boolean</cell>
- <cell align="left" valign="middle">factory</cell>
- <cell align="left" valign="middle">native</cell>
- <cell align="left" valign="middle">short</cell>
- <cell align="left" valign="middle">ValueBase</cell>
- </row>
- <row>
- <cell align="left" valign="middle">case</cell>
- <cell align="left" valign="middle">FALSE</cell>
- <cell align="left" valign="middle">Object</cell>
- <cell align="left" valign="middle">string</cell>
- <cell align="left" valign="middle">valuetype</cell>
- </row>
- <row>
- <cell align="left" valign="middle">char</cell>
- <cell align="left" valign="middle">fixed</cell>
- <cell align="left" valign="middle">octet</cell>
- <cell align="left" valign="middle">struct</cell>
- <cell align="left" valign="middle">void</cell>
- </row>
- <row>
- <cell align="left" valign="middle">const</cell>
- <cell align="left" valign="middle">float</cell>
- <cell align="left" valign="middle">oneway</cell>
- <cell align="left" valign="middle">supports</cell>
- <cell align="left" valign="middle">wchar</cell>
- </row>
- <row>
- <cell align="left" valign="middle">context</cell>
- <cell align="left" valign="middle">in</cell>
- <cell align="left" valign="middle">out</cell>
- <cell align="left" valign="middle">switch</cell>
- <cell align="left" valign="middle">wstring</cell>
- </row>
- <row>
- <cell align="left" valign="middle">custom</cell>
- <cell align="left" valign="middle">inout</cell>
- <cell align="left" valign="middle">private</cell>
- <cell align="left" valign="middle">TRUE</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">default</cell>
- <cell align="left" valign="middle">interface</cell>
- <cell align="left" valign="middle">public</cell>
- <cell align="left" valign="middle">truncatable</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <tcaption>OMG IDL keywords</tcaption>
- </table>
- <p>The keywords listed above must be written exactly as shown. Any usage
- of identifiers that collide with a keyword is illegal. For example,
- <em>long</em> is a valid keyword; <em>Long</em> and <em>LONG</em> are
- illegal as keywords and identifiers. But, since the OMG must be able
- to expand the IDL grammar, it is possible to use <em>Escaped Identifiers</em>. For example, it is not unlikely that <c>native</c>
- have been used in IDL-specifications as identifiers. One option is to
- change all occurrences to <c>myNative</c>. Usually, it is necessary
- to change programming language code that depends upon that IDL as well.
- Since Escaped Identifiers just disable type checking (i.e. if it is a reserved
- word or not) and leaves everything else unchanged, it is only necessary to
- update the IDL-specification. To escape an identifier, simply prefix it
- with <c>_</c>. The following IDL-code is illegal:</p>
- <code type="none">
-typedef string native;
-interface i {
- void foo(in native Arg);
- };
-};
- </code>
- <p>With Escaped Identifiers the code will look like:</p>
- <code type="none">
-typedef string _native;
-interface i {
- void foo(in _native Arg);
- };
-};
- </code>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/ic/doc/src/ch_c_client.xml b/lib/ic/doc/src/ch_c_client.xml
deleted file mode 100644
index e304c8acf4..0000000000
--- a/lib/ic/doc/src/ch_c_client.xml
+++ /dev/null
@@ -1,150 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1998</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>The C Client Back-end</title>
- <prepared></prepared>
- <docno></docno>
- <date>2004-01-14</date>
- <rev>C</rev>
- <file>ch_c_client.xml</file>
- </header>
-
- <section>
- <title>Introduction</title>
- <p>With the option <c>{be, c_client}</c> the IDL Compiler generates
- C client stubs according to the IDL to C mapping, on top of the
- Erlang distribution and gen_server protocols.</p>
- <p>The developer has to write additional code, that together with
- the generated C client stubs, form a hidden Erlang node. That
- additional code uses <c>erl_interface</c> functions for defining
- the hidden node, and for establishing connections to other
- Erlang nodes.</p>
- </section>
-
- <section>
- <title>Generated Stub Files</title>
- <p>The generated stub files are:</p>
- <list type="bulleted">
- <item>
- <p>For each IDL interface, a C source file, the name of which
- is <c><![CDATA[<Scoped Interface Name>.c]]></c>. Each operation of the
- IDL interface is mapped to a C function (with scoped name)
- in that file;</p>
- </item>
- <item>
- <p>C source files that contain functions for type conversion,
- memory allocation, and data encoding/decoding;</p>
- </item>
- <item>
- <p>C header files that contain function prototypes and type
- definitions.</p>
- </item>
- </list>
- <p>All C functions are exported (i.e. not declared static).</p>
- </section>
-
- <section>
- <title>C Interface Functions</title>
- <p>For each IDL operation a C interface function is
- generated, the prototype of which is:</p>
- <p><c><![CDATA[<Return Value> <Scoped Function Name>(<Interface Object> oe_obj, <Parameters>, CORBA_Environment *oe_env);]]></c></p>
- <p>where</p>
- <list type="bulleted">
- <item>
- <p><c><![CDATA[<Return Value>]]></c> is the value to be returned as defined
- by the IDL specification;</p>
- </item>
- <item>
- <p><c><![CDATA[<Interface Object> oe_obj]]></c> is the client interface
- object;</p>
- </item>
- <item>
- <p><c><![CDATA[<Parameters>]]></c> is a list of parameters of the
- operation, defined in the same order as defined by the IDL
- specification;</p>
- </item>
- <item>
- <p><c>CORBA_Environment *oe_env</c> is a pointer to the current
- client environment. It contains the current file descriptor,
- the current input and output buffers, etc. For details see
- <seealso marker="ch_c_corba_env#corbaenv">CORBA_Environment C Structure</seealso>.</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Generating, Compiling and Linking</title>
- <p>To generate the C client stubs type the following in an
- appropriate shell:</p>
- <p><c><![CDATA[erlc -I ICROOT/include "+{be, c_client}" File.idl]]></c>,</p>
- <p>where <c>ICROOT</c> is the root of the IC application. The
- <c>-I ICROOT/include</c> is only needed if <c>File.idl</c>
- refers to <c>erlang.idl</c>.</p>
- <p>When compiling a generated C stub file, the directories
- <c>ICROOT/include</c> and <c>EICROOT/include</c>, have to be
- specified as include directories, where <c>EIROOT</c> is the
- root directory of the Erl_interface application.</p>
- <p>When linking object files the <c>EIROOT/lib</c> and
- <c>ICROOT/priv/lib</c> directories have to be specified. </p>
- </section>
-
- <section>
- <title>An Example</title>
- <p>In this example the IDL specification file "random.idl" is used
- for generating C client stubs (the file is contained in the IC
- <c>/examples/c-client</c> directory):</p>
- <code type="none"><![CDATA[
-module rmod {
-
- interface random {
-
- double produce();
-
- oneway void init(in long seed1, in long seed2, in long seed3);
-
- };
-
-}; ]]></code>
- <p>Generate the C client stubs:</p>
-
- <code type="none"><![CDATA[
-erlc '+{be, c_client}' random.idl
-Erlang IDL compiler version X.Y.Z ]]></code>
-
- <p>Six files are generated. </p>
- <p>Compile the C client stubs:</p>
- <p>Please read the <c>ReadMe</c> file att the
- <c>examples/c-client</c> directory</p>
- <p>In the same
- directory you can find all the code for this example.</p>
- <p>In particular you will find the <c>client.c</c> file that contains
- all the additional code that must be written to obtain a complete
- client. </p>
- <p>In the <c>examples/c-client</c> directory you will also find
- source code for an Erlang server, which can be used for testing
- the C client.</p>
- </section>
-</chapter>
-
-
diff --git a/lib/ic/doc/src/ch_c_corba_env.xml b/lib/ic/doc/src/ch_c_corba_env.xml
deleted file mode 100644
index 1bd829307e..0000000000
--- a/lib/ic/doc/src/ch_c_corba_env.xml
+++ /dev/null
@@ -1,386 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1998</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CORBA_Environment C Structure</title>
- <prepared></prepared>
- <docno></docno>
- <date>2003-12-15</date>
- <rev>PC1</rev>
- <file>ch_c_corba_env.xml</file>
- </header>
- <marker id="corbaenv"></marker>
- <p>This chapter describes the CORBA_Environment C structure.</p>
-
- <section>
- <title>C Structure</title>
- <p>Here is the complete definition of the CORBA_Environment
- C structure, defined in file "ic.h" : </p>
- <code type="none">
-/* Environment definition */
-typedef struct {
-
- /*----- CORBA compatibility part ------------------------*/
- /* Exception tag, initially set to CORBA_NO_EXCEPTION ---*/
- CORBA_exception_type _major;
-
- /*----- External Implementation part - initiated by the user ---*/
- /* File descriptor */
- int _fd;
- /* Size of input buffer */
- int _inbufsz;
- /* Pointer to always dynamically allocated buffer for input */
- char *_inbuf;
- /* Size of output buffer */
- int _outbufsz;
- /* Pointer to always dynamically allocated buffer for output */
- char *_outbuf;
- /* Size of memory chunks in bytes, used for increasing the output
- buffer, set to >= 32, should be around >= 1024 for performance
- reasons */
- int _memchunk;
- /* Pointer for registered name */
- char _regname[256];
- /* Process identity for caller */
- erlang_pid *_to_pid;
- /* Process identity for callee */
- erlang_pid *_from_pid;
-
- /*- Internal Implementation part - used by the server/client ---*/
- /* Index for input buffer */
- int _iin;
- /* Index for output buffer */
- int _iout;
- /* Pointer for operation name */
- char _operation[256];
- /* Used to count parameters */
- int _received;
- /* Used to identify the caller */
- erlang_pid _caller;
- /* Used to identify the call */
- erlang_ref _unique;
- /* Exception id field */
- CORBA_char *_exc_id;
- /* Exception value field */
- void *_exc_value;
-
-
-} CORBA_Environment;
- </code>
- <p>The structure is divided into three parts:</p>
- <list type="bulleted">
- <item>
- <p>The CORBA Compatibility part, demanded by the standard OMG
- IDL mapping v2.0.</p>
- </item>
- <item>
- <p>The external implementation part used for generated
- client/server code.</p>
- </item>
- <item>
- <p>The internal part useful for those who wish to define their
- own functions.</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>The CORBA Compatibility Part</title>
- <p>Contains only one field <c>_major</c> defined as a
- CORBA_Exception_type. The CORBA_Exception type is an integer
- which can be one of:</p>
- <list type="bulleted">
- <item>
- <p><em>CORBA_NO_EXCEPTION</em>, by default equal to 0, can be
- set by the application programmer to another value.</p>
- </item>
- <item>
- <p><em>CORBA_SYSTEM_EXCEPTION</em>, by default equal to -1, can
- be set by the application programmer to another value.</p>
- </item>
- </list>
- <p>The current definition of these values are:</p>
- <code type="none">
- #define CORBA_NO_EXCEPTION 0
- #define CORBA_SYSTEM_EXCEPTION -1
- </code>
- </section>
-
- <section>
- <title>The External Part</title>
- <p>This part contains the following fields:</p>
- <list type="bulleted">
- <item>
- <p>int <em>_fd</em> - a file descriptor returned from
- erl_connect. Used for connection setting.</p>
- </item>
- <item>
- <p>char* <em>_inbuf</em> - pointer to a buffer used for
- input. Buffer size checks are done under runtime that
- prevent buffer overflows. This is done by expanding the
- buffer to fit the input message. In order to allow buffer
- reallocation, the output buffer must always be dynamically
- allocated. The pointer value can change under runtime in
- case of buffer reallocation.</p>
- </item>
- <item>
- <p>int <em>_inbufsz</em> - start size of input buffer. Used
- for setting the input buffer size under initialization of
- the Erl_Interface function ei_receive_encoded/5. The value
- of this field can change under runtime in case of input
- buffer expansion to fit larger messages</p>
- </item>
- <item>
- <p>int <em>_outbufsz</em> - start size of output buffer. The
- value of this field can change under runtime in case of
- input buffer expansion to fit larger messages</p>
- </item>
- <item>
- <p>char* <em>_outbuf</em> - pointer to a buffer used for
- output. Buffer size checks prevent buffer overflows under
- runtime, by expanding the buffer to fit the output message
- in cases of lack of space in buffer. In order to allow
- buffer reallocation, the output buffer must always be
- dynamically allocated. The pointer value can change under
- runtime in case of buffer reallocation.</p>
- </item>
- <item>
- <p>int <em>_memchunk</em> - expansion unit size for the output
- buffer. This is the size of memory chunks in bytes used for
- increasing the output in case of buffer expansion. The value
- of this field must be always set to &gt;= 32, should be at
- least 1024 for performance reasons.</p>
- </item>
- <item>
- <p>char <em>regname[256]</em> - a registered name for a process. </p>
- </item>
- <item>
- <p>erlang_pid* <em>_to_pid</em> - an Erlang process identifier,
- is only used if the registered_name parameter is the empty
- string.</p>
- </item>
- <item>
- <p>erlang_pid* <em>_from_pid</em> - your own process id so the
- answer can be returned.</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>The Internal Part</title>
- <p>This part contains the following fields:</p>
- <list type="bulleted">
- <item>
- <p>int <em>_iin</em> - Index for input buffer. Initially set
- to zero. Updated to agree with the length of the received
- encoded message.</p>
- </item>
- <item>
- <p>int <em>_iout</em> - Index for output buffer Initially set
- to zero. Updated to agree with the length of the message
- encoded to the communication counterpart.</p>
- </item>
- <item>
- <p>char <em>_operation[256]</em> - Pointer for operation name.
- Set to the operation to be called.</p>
- </item>
- <item>
- <p>int <em>_received</em> - Used to count parameters.
- Initially set to zero.</p>
- </item>
- <item>
- <p>erlang_pid <em>_caller</em> - Used to identify the caller.
- Initiated to a value that identifies the caller.</p>
- </item>
- <item>
- <p>erlang_ref <em>_unique</em> - Used to identify the call.
- Set to a default value in the case of generated functions.</p>
- </item>
- <item>
- <p>CORBA_char* <em>_exc_id</em> - Exception id field.
- Initially set to NULL to agree with the initial value of
- _major (CORBA_NO_EXCEPTION).</p>
- </item>
- <item>
- <p>void* <em>_exc_value</em> - Exception value field Initially
- set to <em>NULL</em> to agree with the initial value of
- _major (CORBA_NO_EXCEPTION).</p>
- </item>
- </list>
- <p>The advanced user who defines his own functions has to
- update/support these values in a way similar to how they are
- updated in the generated code.</p>
- </section>
-
- <section>
- <title>Creating and Initiating the CORBA_Environment Structure</title>
- <p>There are two ways to set the CORBA_Environment structure:</p>
- <list type="bulleted">
- <item>
- <p>Manually</p>
- <p>The following default values must be set to the
- CORBA_Environment *<em>ev</em> fields, when buffers for
- input/output should have the size <em>inbufsz</em>/
- <em>outbufsz</em>:</p>
- <list type="bulleted">
- <item>
- <p><em>ev->_inbufsz</em> = <em>inbufsz</em>;</p>
- <p>The value for this field can be between 0 and maximum
- size of a signed integer.</p>
- </item>
- <item>
- <p><em>ev->_inbuf</em> = malloc(<em>inbufsz</em>);</p>
- <p>The size of the allocated buffer must be equal to the
- value of its corresponding index, _inbufsz.</p>
- </item>
- <item>
- <p><em>ev->_outbufsz</em> = <em>outbufsz</em>;</p>
- <p>The value for this field can be between 0 and maximum
- size of a signed integer.</p>
- </item>
- <item>
- <p><em>ev->_outbuf</em> = malloc(<em>outbufsz</em>);</p>
- <p>The size of the allocated buffer must be equal to the
- value of its corresponding index, _outbufsz.</p>
- </item>
- <item>
- <p><em>ev->_memchunk</em> = <em>__OE_MEMCHUNK__</em>;</p>
- <p>Please note that __OE_MEMCHUNK__ is equal to
- <em>1024</em>, you can set this value to a value bigger
- than 32 yourself.</p>
- </item>
- <item>
- <p><em>ev->_to_pid</em> = <em>NULL</em>;</p>
- </item>
- <item>
- <p><em>ev->_from_pid</em> = <em>NULL</em>;</p>
- </item>
- </list>
- <p></p>
- </item>
- <item>
- <p>By using the <em>CORBA_Environment_alloc</em>/2 function. </p>
- <p>The CORBA_Environment_alloc function is defined as:</p>
- <code type="none">
- CORBA_Environment *CORBA_Environment_alloc(int inbufsz,
- int outbufsz);
- </code>
- <p>where:</p>
- <list type="bulleted">
- <item>
- <p><em>inbufsz</em> is the desired size of input buffer</p>
- </item>
- <item>
- <p><em>outbufsz</em> is the desired size of output
- buffer</p>
- </item>
- <item>
- <p>return value is a <em>pointer</em> to an allocated and
- initialized <em>CORBA_Environment</em> structure.</p>
- <p></p>
- </item>
- </list>
- <p>This function will set all needed default values and
- allocate buffers equal to the values passed, but will not
- allocate space for the _to_pid and _from_pid fields.</p>
- <p>To free the space allocated by CORBA_Environment_alloc/2:</p>
- <list type="bulleted">
- <item>
- <p>First call CORBA_free for the input and output buffers.</p>
- </item>
- <item>
- <p>After freeing the buffer space, call CORBA_free for
- the CORBA_Environment space.</p>
- </item>
- </list>
- </item>
- </list>
- <note>
- <p>Remember to set the fields <em>_fd</em>, <em>_regname</em>,
- <em>*_to_pid</em> and/or <em>*_from_pid</em> to the
- appropriate application values. These are not automatically
- set by the stubs.</p>
- </note>
- <warning>
- <p>Never assign static buffers to the buffer pointers. Never set
- the <em>_memchunk</em> field to a value less than
- <em>32</em>.</p>
- </warning>
- </section>
-
- <section>
- <title>Setting System Exceptions</title>
- <p>If the user wishes to set own system exceptions at critical
- positions on the code, it is strongly recommended to use one of
- the current values:</p>
- <list type="bulleted">
- <item>
- <p>CORBA_NO_EXCEPTION upon success. The value of the _exc_id
- field should be then set to NULL. The value of the
- _exc_value field should be then set to NULL.</p>
- </item>
- <item>
- <p>CORBA_SYSTEM_EXCEPTION upon system failure. The value of
- the _exc_id field should be then set to one of the values
- defined in "ic.h" :</p>
- <code type="none">
- #define UNKNOWN "UNKNOWN"
- #define BAD_PARAM "BAD_PARAM"
- #define NO_MEMORY "NO_MEMORY"
- #define IMPL_LIMIT "IMP_LIMIT"
- #define COMM_FAILURE "COMM_FAILURE"
- #define INV_OBJREF "INV_OBJREF"
- #define NO_PERMISSION "NO_PERMISSION"
- #define INTERNAL "INTERNAL"
- #define MARSHAL "MARSHAL"
- #define INITIALIZE "INITIALIZE"
- #define NO_IMPLEMENT "NO_IMPLEMENT"
- #define BAD_TYPECODE "BAD_TYPECODE"
- #define BAD_OPERATION "BAD_OPERATION"
- #define NO_RESOURCES "NO_RESOURCES"
- #define NO_RESPONSE "NO_RESPONSE"
- #define PERSIST_STORE "PERSIST_STORE"
- #define BAD_INV_ORDER "BAD_INV_ORDER"
- #define TRANSIENT "TRANSIENT"
- #define FREE_MEM "FREE_MEM"
- #define INV_IDENT "INV_IDENT"
- #define INV_FLAG "INV_FLAG"
- #define INTF_REPOS "INTF_REPOS"
- #define BAD_CONTEXT "BAD_CONTEXT"
- #define OBJ_ADAPTER "OBJ_ADAPTER"
- #define DATA_CONVERSION "DATA_CONVERSION"
- #define OBJ_NOT_EXIST "OBJECT_NOT_EXIST"
- </code>
- </item>
- </list>
- <p>The value of the _exc_value field should be then set to a string
- that explains the problem in an informative way. The user
- should use the functions CORBA_exc_set/4 and
- CORBA_exception_free/1 to free the exception.
- The user has to use CORBA_exception_id/1 and
- CORBA_exception_value/1 to access exception information.
- Prototypes for these functions are declared in "ic.h"</p>
- </section>
-</chapter>
-
-
diff --git a/lib/ic/doc/src/ch_c_mapping.xml b/lib/ic/doc/src/ch_c_mapping.xml
deleted file mode 100644
index 1ea0ace91f..0000000000
--- a/lib/ic/doc/src/ch_c_mapping.xml
+++ /dev/null
@@ -1,893 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1998</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>IDL to C mapping</title>
- <prepared></prepared>
- <docno></docno>
- <date>2002-08-06</date>
- <rev>PB1</rev>
- <file>ch_c_mapping.xml</file>
- </header>
-
- <section>
- <title>Introduction</title>
- <p>The IC C mapping (used by the C client and C server back-ends) follows
- the <em>OMG C Language Mapping Specification</em>. </p>
- <p>The C mapping supports the following:</p>
- <list type="bulleted">
- <item>
- <p>All OMG IDL basic types except <c>long double</c> and <c>any</c>.</p>
- </item>
- <item>
- <p>All OMG IDL constructed types.</p>
- </item>
- <item>
- <p>OMG IDL constants.</p>
- </item>
- <item>
- <p>Operations with passing of parameters and receiving of
- results. <c>inout</c> parameters are not supported.</p>
- </item>
- </list>
- <p>The following is not supported:
- </p>
- <list type="bulleted">
- <item>
- <p>Access to attributes.</p>
- </item>
- <item>
- <p>User defined exceptions.</p>
- <p></p>
- </item>
- <item>
- <p>User defined objects.</p>
- <p></p>
- </item>
- </list>
- </section>
-
- <section>
- <title>C Mapping Characteristics</title>
-
- <section>
- <title>Reserved Names</title>
- <p>The IDL compiler reserves all identifiers starting with
- <c>OE_</c> and <c>oe_</c> for internal use.</p>
- </section>
-
- <section>
- <title>Scoped Names</title>
- <p>The C programmer must always use the global name for a type,
- constant or operation. The C global name corresponding to an
- OMG IDL global name is derived by converting occurrences of
- "::" to underscore, and eliminating the leading "::". So, for
- example, an operation <c>op1</c> defined in interface
- <c>I1</c> which is defined in module <c>M1</c> would be
- written as <c>M1::I1::op1</c> in IDL and as <c>M1_I1_op1</c>
- in C.</p>
- <warning>
- <p>If underscores are used in IDL names it can lead to
- ambiguities due to the name mapping described above,
- therefore it is advisable to avoid underscores in
- identifiers.</p>
- </warning>
- </section>
-
- <section>
- <title>Generated Files</title>
- <p>Two files will be generated for each scope. One set of files
- will be generated for each module and each interface scope.
- An extra set is generated for those definitions at top
- level scope. One of the files is a header file(<c>.h</c>), and the
- other file is a C source code file (<c>.c</c>). In addition to these
- files a number of C source files will be generated for type encodings,
- they are named according to the following template:
- <c><![CDATA[oe_code_<type>.c]]></c>.</p>
- <p>For example:</p>
- <code type="none"><![CDATA[
-// IDL, in the file "spec.idl"
-module m1 {
-
- typedef sequence<long> lseq;
-
- interface i1 {
- ...
- };
- ...
-};
- ]]></code>
- <p>XXX This is C client specific.
- Will produce the files <c>oe_spec.h</c> and
- <c>oe_spec.c</c> for the top scope level. Then the files
- <c>m1.h</c> and <c>m1.c</c> for the module <c>m1</c> and
- files <c>m1_i1.h</c> and <c>m1_i1.c</c> for the interface
- <c>i1</c>. The typedef will produce <c>oe_code_m1_lseq.c</c>.</p>
- <p>The header file contains type definitions for all
- <c>struct</c> types and sequences and constants in the IDL file. The
- c file contains all operation stubs if the the scope is an interface.</p>
- <p>In addition to the scope-related files a C source file will
- be generated for encoding operations of all <c>struct</c> and
- sequence types.</p>
- </section>
- </section>
-
- <section>
- <title>Basic OMG IDL Types</title>
- <p>The mapping of basic types is as follows.</p>
- <table>
- <row>
- <cell align="left" valign="middle"><em>OMG IDL type</em></cell>
- <cell align="left" valign="middle"><em>C type</em></cell>
- <cell align="left" valign="middle"><em>Mapped to C type</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">float</cell>
- <cell align="left" valign="middle">CORBA_float</cell>
- <cell align="left" valign="middle">float</cell>
- </row>
- <row>
- <cell align="left" valign="middle">double</cell>
- <cell align="left" valign="middle">CORBA_double</cell>
- <cell align="left" valign="middle">double</cell>
- </row>
- <row>
- <cell align="left" valign="middle">short</cell>
- <cell align="left" valign="middle">CORBA_short</cell>
- <cell align="left" valign="middle">short</cell>
- </row>
- <row>
- <cell align="left" valign="middle">unsigned short</cell>
- <cell align="left" valign="middle">CORBA_unsigned_short</cell>
- <cell align="left" valign="middle">unsigned short</cell>
- </row>
- <row>
- <cell align="left" valign="middle">long</cell>
- <cell align="left" valign="middle">CORBA_long</cell>
- <cell align="left" valign="middle">long</cell>
- </row>
- <row>
- <cell align="left" valign="middle">long long</cell>
- <cell align="left" valign="middle">CORBA_long_long</cell>
- <cell align="left" valign="middle">long</cell>
- </row>
- <row>
- <cell align="left" valign="middle">unsigned long</cell>
- <cell align="left" valign="middle">CORBA_unsigned_long</cell>
- <cell align="left" valign="middle">unsigned long</cell>
- </row>
- <row>
- <cell align="left" valign="middle">unsigned long long</cell>
- <cell align="left" valign="middle">CORBA_unsigned_long_long</cell>
- <cell align="left" valign="middle">unsigned long</cell>
- </row>
- <row>
- <cell align="left" valign="middle">char</cell>
- <cell align="left" valign="middle">CORBA_char</cell>
- <cell align="left" valign="middle">char</cell>
- </row>
- <row>
- <cell align="left" valign="middle">wchar</cell>
- <cell align="left" valign="middle">CORBA_wchar</cell>
- <cell align="left" valign="middle">unsigned long</cell>
- </row>
- <row>
- <cell align="left" valign="middle">boolean</cell>
- <cell align="left" valign="middle">CORBA_boolean</cell>
- <cell align="left" valign="middle">unsigned char</cell>
- </row>
- <row>
- <cell align="left" valign="middle">octet</cell>
- <cell align="left" valign="middle">CORBA_octet</cell>
- <cell align="left" valign="middle">char</cell>
- </row>
- <row>
- <cell align="left" valign="middle">any</cell>
- <cell align="left" valign="middle">Not supported</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">long double</cell>
- <cell align="left" valign="middle">Not supported</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">Object</cell>
- <cell align="left" valign="middle">Not supported</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">void</cell>
- <cell align="left" valign="middle">void</cell>
- <cell align="left" valign="middle">void</cell>
- </row>
- <tcaption>OMG IDL Basic Types</tcaption>
- </table>
- <p>XXX Note that several mappings are not according to OMG C Language
- mapping.</p>
- </section>
-
- <section>
- <title>Constructed OMG IDL Types</title>
- <p>Constructed types have mappings as shown in the following table.</p>
- <table>
- <row>
- <cell align="left" valign="middle">OMG IDL type</cell>
- <cell align="left" valign="middle">Mapped to C type</cell>
- </row>
- <row>
- <cell align="left" valign="middle">string</cell>
- <cell align="left" valign="middle">CORBA_char*</cell>
- </row>
- <row>
- <cell align="left" valign="middle">wstring</cell>
- <cell align="left" valign="middle">CORBA_wchar*</cell>
- </row>
- <row>
- <cell align="left" valign="middle">struct</cell>
- <cell align="left" valign="middle">struct</cell>
- </row>
- <row>
- <cell align="left" valign="middle">union</cell>
- <cell align="left" valign="middle">union</cell>
- </row>
- <row>
- <cell align="left" valign="middle">enum</cell>
- <cell align="left" valign="middle">enum</cell>
- </row>
- <row>
- <cell align="left" valign="middle">sequence</cell>
- <cell align="left" valign="middle">struct (see below)</cell>
- </row>
- <row>
- <cell align="left" valign="middle">array</cell>
- <cell align="left" valign="middle">array</cell>
- </row>
- <tcaption>OMG IDL Constructed Types</tcaption>
- </table>
- <p>An OMG IDL sequence (an array of variable length), </p>
- <code type="none"><![CDATA[
-// IDL
-typedef sequence <IDL_TYPE> NAME;
- ]]></code>
- <p>is mapped to a C struct as follows:</p>
- <code type="none">
-/* C */
-typedef struct {
- CORBA_unsigned_long _maximum;
- CORBA_unsigned_long _length;
- C_TYPE* _buffer;
-} C_NAME;
- </code>
- <p>where <c>C_TYPE</c> is the mapping of <c>IDL_TYPE</c>, and where
- <c>C_NAME</c> is the scoped name of <c>NAME</c>.</p>
- </section>
-
- <section>
- <title>OMG IDL Constants</title>
- <p>An IDL constant is mapped to a C constant through a C
- <c>#define</c> macro, where the name of the macro is scoped.
- Example:</p>
- <code type="none">
-// IDL
-module M1 {
- const long c1 = 99;
-};
- </code>
- <p>results in the following:</p>
- <code type="none">
-/* C */
-#define M1_c1 99
- </code>
- </section>
-
- <section>
- <title>OMG IDL Operations</title>
- <p>An OMG IDL operation is mapped to C function. Each C operation
- function has two mandatory parameters: a first parameter of
- <em>interface object</em> type, and a last parameter of
- <em>environment</em> type.</p>
- <p></p>
- <p>In a C operation function the the <c>in</c> and <c>out</c>
- parameters are located between the first and last parameters
- described above, and they appear in the same order as in the IDL
- operation declaration.</p>
- <p>Notice that <c>inout</c> parameters are not supported. </p>
- <p></p>
- <p>The return value of an OMG IDL operation is mapped to a
- corresponding return value of the C operation function.</p>
- <p>Mandatory C operation function parameters:</p>
- <list type="bulleted">
- <item><c>CORBA_Object oe_obj</c> - the first parameter of a C
- operation function. This parameter is required by the <em>OMG C Language Mapping Specification</em>, but in the current
- implementation there is no particular use for it.</item>
- <item>
- <p><c>CORBA_Environment* oe_env</c> - the last parameter of a C
- operation function. The parameter is defined in the C header
- file <c>ic.h</c> and has the following public fields:</p>
- <list type="bulleted">
- <item>
- <p><c>CORBA_Exception_type _major</c> - indicates if an
- operation invocation was successful which will be one of
- the following:</p>
- <list type="bulleted">
- <item>CORBA_NO_EXCEPTION</item>
- <item>CORBA_SYSTEM_EXCEPTION</item>
- </list>
- </item>
- <item>int <em>_fd</em> - a file descriptor returned from
- <em>erl_connect</em> function.</item>
- <item>int <em>_inbufsz</em> - size of input buffer.</item>
- <item>char* <em>_inbuf</em> - pointer to a buffer used for
- input.</item>
- <item>int <em>_outbufsz</em> - size of output buffer.</item>
- <item>char* <em>_outbuf</em> - pointer to a buffer used for
- output.</item>
- <item>
- <p>int <em>_memchunk</em> - expansion unit size for the
- output buffer. This is the size of memory chunks in
- bytes used for increasing the output in case of buffer
- expansion. The value of this field must be always set
- to &gt;= 32, should be at least 1024 for performance
- reasons.</p>
- </item>
- <item>char <em>regname[256]</em> - a registered name for a
- process.</item>
- <item>erlang_pid* <em>_to_pid</em> - an Erlang process
- identifier, is only used if the registered_name parameter
- is the empty string.</item>
- <item>erlang_pid* <em>_from_pid</em> - your own process id so
- the answer can be returned</item>
- </list>
- <p>Beside the public fields, other private fields
- are internally used but are not mentioned here. </p>
- </item>
- </list>
- <p>Example:</p>
- <code type="none">
-// IDL
-interface i1 {
- long op1(in long a);
- long op2(in string s, out long count);
-};
- </code>
- <p>Is mapped to the following C functions</p>
- <code type="none">
-/* C */
-CORBA_long i1_op1(i1 oe_obj, CORBA_long a, CORBA_Environment* oe_env)
-{
- ...
-}
-CORBA_long i1_op2(i1 oe_obj, CORBA_char* s, CORBA_long *count,
-CORBA_Environment* oe_env)
-{
- ...
-}
- </code>
- <marker id="op_impl"></marker>
-
- <section>
- <title>Operation Implementation</title>
- <p>There is no standard CORBA mapping for the C-server side,
- as it is implementation-dependent but built in a similar way.
- The current server side mapping is different from the client
- side mapping in several ways:</p>
- <list type="bulleted">
- <item>Argument mappings</item>
- <item>Result values</item>
- <item>Structure</item>
- <item>Usage</item>
- <item>Exception handling</item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Exceptions</title>
- <p>Although exception mapping is not implemented, the stubs will
- generate CORBA system exceptions in case of operation failure.
- Thus, the only exceptions propagated by the system are built in
- system exceptions.</p>
- </section>
-
- <section>
- <title>Access to Attributes</title>
- <p>Not Supported</p>
- </section>
-
- <section>
- <title>Summary of Argument/Result Passing for the C-client</title>
- <p>The user-defined parameters can only be <c>in</c> or <c>out</c>
- parameters, as
- <c>inout</c> parameters are not supported.</p>
- <p>This table summarize the types a client passes as arguments to
- a stub, and receives as a result.</p>
- <table>
- <row>
- <cell align="left" valign="middle">OMG IDL type</cell>
- <cell align="left" valign="middle">In</cell>
- <cell align="left" valign="middle">Out</cell>
- <cell align="left" valign="middle">Return</cell>
- </row>
- <row>
- <cell align="left" valign="middle">short</cell>
- <cell align="left" valign="middle">CORBA_short</cell>
- <cell align="left" valign="middle">CORBA_short*</cell>
- <cell align="left" valign="middle">CORBA_short</cell>
- </row>
- <row>
- <cell align="left" valign="middle">long</cell>
- <cell align="left" valign="middle">CORBA_long</cell>
- <cell align="left" valign="middle">CORBA_long*</cell>
- <cell align="left" valign="middle">CORBA_long</cell>
- </row>
- <row>
- <cell align="left" valign="middle">long long</cell>
- <cell align="left" valign="middle">CORBA_long_long</cell>
- <cell align="left" valign="middle">CORBA_long_long*</cell>
- <cell align="left" valign="middle">CORBA_long_long</cell>
- </row>
- <row>
- <cell align="left" valign="middle">unsigned short</cell>
- <cell align="left" valign="middle">CORBA_unsigned_short</cell>
- <cell align="left" valign="middle">CORBA_unsigned_short*</cell>
- <cell align="left" valign="middle">CORBA_unsigned_short</cell>
- </row>
- <row>
- <cell align="left" valign="middle">unsigned long</cell>
- <cell align="left" valign="middle">CORBA_unsigned_long</cell>
- <cell align="left" valign="middle">CORBA_unsigned_long*</cell>
- <cell align="left" valign="middle">CORBA_unsigned_long</cell>
- </row>
- <row>
- <cell align="left" valign="middle">unsigned long long</cell>
- <cell align="left" valign="middle">CORBA_unsigned_long_long</cell>
- <cell align="left" valign="middle">CORBA_unsigned_long_long*</cell>
- <cell align="left" valign="middle">CORBA_unsigned_long_long</cell>
- </row>
- <row>
- <cell align="left" valign="middle">float</cell>
- <cell align="left" valign="middle">CORBA_float</cell>
- <cell align="left" valign="middle">CORBA_float*</cell>
- <cell align="left" valign="middle">CORBA_float</cell>
- </row>
- <row>
- <cell align="left" valign="middle">double</cell>
- <cell align="left" valign="middle">CORBA_double</cell>
- <cell align="left" valign="middle">CORBA_double*</cell>
- <cell align="left" valign="middle">CORBA_double</cell>
- </row>
- <row>
- <cell align="left" valign="middle">boolean</cell>
- <cell align="left" valign="middle">CORBA_boolean</cell>
- <cell align="left" valign="middle">CORBA_boolean*</cell>
- <cell align="left" valign="middle">CORBA_boolean</cell>
- </row>
- <row>
- <cell align="left" valign="middle">char</cell>
- <cell align="left" valign="middle">CORBA_char</cell>
- <cell align="left" valign="middle">CORBA_char*</cell>
- <cell align="left" valign="middle">CORBA_char</cell>
- </row>
- <row>
- <cell align="left" valign="middle">wchar</cell>
- <cell align="left" valign="middle">CORBA_wchar</cell>
- <cell align="left" valign="middle">CORBA_wchar*</cell>
- <cell align="left" valign="middle">CORBA_wchar</cell>
- </row>
- <row>
- <cell align="left" valign="middle">octet</cell>
- <cell align="left" valign="middle">CORBA_octet</cell>
- <cell align="left" valign="middle">CORBA_octet*</cell>
- <cell align="left" valign="middle">CORBA_octet</cell>
- </row>
- <row>
- <cell align="left" valign="middle">enum</cell>
- <cell align="left" valign="middle">CORBA_enum</cell>
- <cell align="left" valign="middle">CORBA_enum*</cell>
- <cell align="left" valign="middle">CORBA_enum</cell>
- </row>
- <row>
- <cell align="left" valign="middle">struct, fixed</cell>
- <cell align="left" valign="middle">struct*</cell>
- <cell align="left" valign="middle">struct*</cell>
- <cell align="left" valign="middle">struct</cell>
- </row>
- <row>
- <cell align="left" valign="middle">struct, variable</cell>
- <cell align="left" valign="middle">struct*</cell>
- <cell align="left" valign="middle">struct**</cell>
- <cell align="left" valign="middle">struct*</cell>
- </row>
- <row>
- <cell align="left" valign="middle">union, fixed</cell>
- <cell align="left" valign="middle">union*</cell>
- <cell align="left" valign="middle">union*</cell>
- <cell align="left" valign="middle">union</cell>
- </row>
- <row>
- <cell align="left" valign="middle">union, variable</cell>
- <cell align="left" valign="middle">union*</cell>
- <cell align="left" valign="middle">union**</cell>
- <cell align="left" valign="middle">union*</cell>
- </row>
- <row>
- <cell align="left" valign="middle">string</cell>
- <cell align="left" valign="middle">CORBA_char*</cell>
- <cell align="left" valign="middle">CORBA_char**</cell>
- <cell align="left" valign="middle">CORBA_char*</cell>
- </row>
- <row>
- <cell align="left" valign="middle">wstring</cell>
- <cell align="left" valign="middle">CORBA_wchar*</cell>
- <cell align="left" valign="middle">CORBA_wchar**</cell>
- <cell align="left" valign="middle">CORBA_wchar*</cell>
- </row>
- <row>
- <cell align="left" valign="middle">sequence</cell>
- <cell align="left" valign="middle">sequence*</cell>
- <cell align="left" valign="middle">sequence**</cell>
- <cell align="left" valign="middle">sequence*</cell>
- </row>
- <row>
- <cell align="left" valign="middle">array, fixed</cell>
- <cell align="left" valign="middle">array</cell>
- <cell align="left" valign="middle">array</cell>
- <cell align="left" valign="middle">array_slice*</cell>
- </row>
- <row>
- <cell align="left" valign="middle">array, variable</cell>
- <cell align="left" valign="middle">array</cell>
- <cell align="left" valign="middle">array_slice**</cell>
- <cell align="left" valign="middle">array_slice*</cell>
- </row>
- <tcaption>Basic Argument and Result passing</tcaption>
- </table>
- <p>A client is responsible for providing storage of all arguments passed
- as <em>in</em> arguments.</p>
- <table>
- <row>
- <cell align="left" valign="middle">OMG IDL type</cell>
- <cell align="left" valign="middle">Out</cell>
- <cell align="left" valign="middle">Return</cell>
- </row>
- <row>
- <cell align="left" valign="middle">short</cell>
- <cell align="left" valign="middle">1</cell>
- <cell align="left" valign="middle">1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">long</cell>
- <cell align="left" valign="middle">1</cell>
- <cell align="left" valign="middle">1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">long long</cell>
- <cell align="left" valign="middle">1</cell>
- <cell align="left" valign="middle">1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">unsigned short</cell>
- <cell align="left" valign="middle">1</cell>
- <cell align="left" valign="middle">1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">unsigned long</cell>
- <cell align="left" valign="middle">1</cell>
- <cell align="left" valign="middle">1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">unsigned long long</cell>
- <cell align="left" valign="middle">1</cell>
- <cell align="left" valign="middle">1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">float</cell>
- <cell align="left" valign="middle">1</cell>
- <cell align="left" valign="middle">1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">double</cell>
- <cell align="left" valign="middle">1</cell>
- <cell align="left" valign="middle">1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">boolean</cell>
- <cell align="left" valign="middle">1</cell>
- <cell align="left" valign="middle">1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">char</cell>
- <cell align="left" valign="middle">1</cell>
- <cell align="left" valign="middle">1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">wchar</cell>
- <cell align="left" valign="middle">1</cell>
- <cell align="left" valign="middle">1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">octet</cell>
- <cell align="left" valign="middle">1</cell>
- <cell align="left" valign="middle">1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">enum</cell>
- <cell align="left" valign="middle">1</cell>
- <cell align="left" valign="middle">1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">struct, fixed</cell>
- <cell align="left" valign="middle">1</cell>
- <cell align="left" valign="middle">1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">struct, variable</cell>
- <cell align="left" valign="middle">2</cell>
- <cell align="left" valign="middle">2</cell>
- </row>
- <row>
- <cell align="left" valign="middle">string</cell>
- <cell align="left" valign="middle">2</cell>
- <cell align="left" valign="middle">2</cell>
- </row>
- <row>
- <cell align="left" valign="middle">wstring</cell>
- <cell align="left" valign="middle">2</cell>
- <cell align="left" valign="middle">2</cell>
- </row>
- <row>
- <cell align="left" valign="middle">sequence</cell>
- <cell align="left" valign="middle">2</cell>
- <cell align="left" valign="middle">2</cell>
- </row>
- <row>
- <cell align="left" valign="middle">array, fixed</cell>
- <cell align="left" valign="middle">1</cell>
- <cell align="left" valign="middle">3</cell>
- </row>
- <row>
- <cell align="left" valign="middle">array, variable</cell>
- <cell align="left" valign="middle">3</cell>
- <cell align="left" valign="middle">3</cell>
- </row>
- <tcaption>Client argument storage responsibility</tcaption>
- </table>
- <table>
- <row>
- <cell align="left" valign="middle">Case</cell>
- <cell align="left" valign="middle">Description</cell>
- </row>
- <row>
- <cell align="left" valign="middle">1</cell>
- <cell align="left" valign="middle">Caller allocates all necessary storage, except that which may be encapsulated and managed within the parameter itself.</cell>
- </row>
- <row>
- <cell align="left" valign="middle">2</cell>
- <cell align="left" valign="middle">The caller allocates a pointer and passes it by reference to the callee. The callee sets the pointer to point to a valid instance of the parameter's type. The caller is responsible for releasing the returned storage. Following completion of a request, the caller is not allowed to modify any values in the returned storage. To do so the caller must first copy the returned instance into a new instance, then modify the new instance. </cell>
- </row>
- <row>
- <cell align="left" valign="middle">3</cell>
- <cell align="left" valign="middle">The caller allocates a pointer to an array slice which has all the same dimensions of the original array except the first, and passes it by reference to the callee. The callee sets the pointer to point to a valid instance of the array. The caller is responsible for releasing the returned storage. Following completion of a request, the caller is not allowed to modify any values in the returned storage. To do so the caller must first copy the returned instance into a new instance, then modify the new instance. </cell>
- </row>
- <tcaption>Argument passing cases</tcaption>
- </table>
- <p>The returned storage in case 2 and 3 is allocated as one block of memory
- so it is possible to deallocate it with one call of CORBA_free.</p>
- </section>
-
- <section>
- <title>Supported Memory Allocation Functions</title>
- <list type="bulleted">
- <item>
- <p><em>CORBA_Environment</em> can be allocated from the user by calling
- <em>CORBA_Environment_alloc()</em>.</p>
- <p>The interface for this function is </p>
- <p><c>CORBA_Environment *CORBA_Environment_alloc(int inbufsz, int outbufsz);</c></p>
- <p>where :</p>
- <list type="bulleted">
- <item>
- <p><em>inbufsz</em> is the desired size of input buffer</p>
- </item>
- <item>
- <p><em>outbufsz</em> is the desired size of output buffer</p>
- </item>
- <item>
- <p>return value is a <em>pointer</em> to an allocated and initialized
- <em>CORBA_Environment</em> structure</p>
- <p></p>
- </item>
- </list>
- </item>
- <item>
- <p>Strings can be allocated from the user by calling <em>CORBA_string_alloc()</em>.</p>
- <p>The interface for this function is </p>
- <p><c>CORBA_char *CORBA_string_alloc(CORBA_unsigned_long len);</c></p>
- <p>where :</p>
- <list type="bulleted">
- <item>
- <p><em>len</em> is the length of the string to be allocated.</p>
- </item>
- </list>
- </item>
- </list>
- <p>Thus far, no other type allocation function is supported.</p>
- </section>
-
- <section>
- <title>Special Memory Deallocation Functions</title>
- <list type="bulleted">
- <item>
- <p><c>void CORBA_free(void *storage)</c></p>
- <p>This function will free storage allocated by the stub.</p>
- </item>
- <item>
- <p><c>void CORBA_exception_free(CORBA_environment *ev)</c></p>
- <p>This function will free storage allocated under exception propagation. </p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Exception Access Functions</title>
- <list type="bulleted">
- <item>
- <p><c>CORBA_char *CORBA_exception_id(CORBA_Environment *ev)</c></p>
- <p>This function will return raised exception identity.</p>
- </item>
- <item>
- <p><c>void *CORBA_exception_value(CORBA_Environment *ev)</c></p>
- <p>This function will return the value of a raised exception. </p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Special Types</title>
- <list type="bulleted">
- <item>
- <p>The erlang binary type has some special features.</p>
- <p></p>
- <p>While the <c>erlang::binary</c> idl type has the same C-definition as
- a generated sequence of octets :</p>
- <code type="none"><![CDATA[
- module erlang
- {
-
- ....
-
- // an erlang binary
- typedef sequence<octet> binary;
-
- };
- ]]></code>
- <p>it provides a way on sending trasparent data between C and Erlang.</p>
- <p>The C-definition (ic.h) for an erlang binary is :</p>
- <code type="none">
- typedef struct {
- CORBA_unsigned_long _maximum;
- CORBA_unsigned_long _length;
- CORBA_octet* _buffer;
- } erlang_binary; /* ERLANG BINARY */
- </code>
- <p>The differences (between <c>erlang::binary</c> and <c><![CDATA[sequence< octet >]]></c>) are :</p>
- <list type="bulleted">
- <item>
- <p>on the erlang side the user is sending/receiving typical
- built in erlang binaries, using <c>term_to_binary() / binary_to_term()</c>
- to create / extract binary structures.</p>
- </item>
- <item>
- <p>no encoding/decoding functions are generated</p>
- </item>
- <item>
- <p>the underlying protocol is more efficient than usual sequences of
- octets</p>
- </item>
- </list>
- <p>The erlang binary IDL type is defined in <c>erlang.idl</c>, while its
- C definition is located in the <c>ic.h</c> header file, both in the
- <c><![CDATA[IC-< vsn >/include]]></c> directory.
- The user will have to include the file <c>erlang.idl</c> in order to use the
- <c>erlang::binary</c> type.</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>A Mapping Example</title>
- <p> <marker id="stack_idl"></marker>
-
- This is a small example of a simple stack. There are two
- operations on the stack, push and pop. The example shows all
- generated files as well as conceptual usage of the stack.</p>
- <code type="none">
-// The source IDL file: stack.idl
-
-struct s {
- long l;
- string s;
-};
-
-interface stack {
- void push(in s val);
- s pop();
-};
- </code>
- <p>When this file is compiled it produces four files, two for the
- top scope and two for the stack interface scope. The important parts
- of the generated C code for the stack API is shown below. <marker id="stack_serv"></marker>
-</p>
- <p>stack.c</p>
- <code type="none">
-
-void push(stack oe_obj, s val, CORBA_Environment* oe_env) {
- ...
-}
-
-
-s* pop(stack oe_obj, CORBA_Environment* oe_env) {
- ...
-}
- </code>
- <p>oe_stack.h</p>
- <code type="none">
-#ifndef OE_STACK_H
-#define OE_STACK_H
-
-
-/*------------------------------------------------------------
- * Struct definition: s
- */
-typedef struct {
- long l;
- char *s;
-} s;
-
-
-
-#endif
- </code>
- <p>stack.h just contains an include statement of <c>oe_stack.h</c>.</p>
- <p>oe_code_s.c</p>
- <code type="none">
-
-int oe_sizecalc_s(CORBA_Environment
- *oe_env, int* oe_size_count_index, int* oe_size) {
- ...
-}
-
-int oe_encode_s(CORBA_Environment *oe_env, s* oe_rec) {
- ...
-}
-
-int oe_decode_s(CORBA_Environment *oe_env, char *oe_first,
- int* oe_outindex, s *oe_out) {
- ...
-}
- </code>
- <p>The only files that are really important are the <c>.h</c>
- files and the stack.c file.</p>
- </section>
-</chapter>
-
diff --git a/lib/ic/doc/src/ch_c_server.xml b/lib/ic/doc/src/ch_c_server.xml
deleted file mode 100644
index df25927c90..0000000000
--- a/lib/ic/doc/src/ch_c_server.xml
+++ /dev/null
@@ -1,149 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1998</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>The C Server Back-end</title>
- <prepared></prepared>
- <docno></docno>
- <date>2004-01-14</date>
- <rev>C</rev>
- <file>ch_c_server.xml</file>
- </header>
-
- <section>
- <title>Introduction</title>
- <p>With the option <c>{be, c_server}</c> the IDL Compiler generates
- C server skeletons according to the IDL to C mapping, on top of
- the Erlang distribution and gen_server protocols.</p>
- <p>The developer has to write additional code, that together with
- the generated C server skeletons, form a hidden Erlang
- node. That additional code contains implementations of call-back
- functions that implement the true server functionality, and also
- code uses <c>erl_interface</c> functions for defining the hidden
- node and for establishing connections to other Erlang nodes.</p>
- </section>
-
- <section>
- <title>Generated Stub Files</title>
- <p>The generated stub files are:</p>
- <list type="bulleted">
- <item>
- <p>For each IDL interface, a C source file, the name of which
- is <c><![CDATA[<Scoped Interface Name>__s.c]]></c>. Each operation of the
- IDL interface is mapped to a C function (with scoped name)
- in that file;</p>
- </item>
- <item>
- <p>C source files that contain functions for type conversion,
- memory allocation, and data encoding/decoding;</p>
- </item>
- <item>
- <p>C header files that contain function prototypes and type
- definitions.</p>
- </item>
- </list>
- <p>All C functions are exported (i.e. not declared static).</p>
- </section>
-
- <section>
- <title>C Skeleton Functions</title>
- <p>For each IDL operation a C skeleton function is generated, the
- prototype of which is <c><![CDATA[int <Scoped Function Name>__exec(<Interface Object> oe_obj, CORBA_Environment *oe_env)]]></c>, where <c><![CDATA[<Interface Object>]]></c>, and
- <c>CORBA_Environment</c> are of the same type as for the
- generated C client stubs code.</p>
- <p>Each <c><![CDATA[<Scoped Function Name>__exec()]]></c> function calls the
- call-back function</p>
- <p><c><![CDATA[<Scoped Function Name>_rs* <Scoped Function Name>__cb(<Interface Object> oe_obj, <Parameters>, CORBA_Environment *oe_env)]]></c></p>
- <p>where the arguments are of the same type as those generated for
- C client stubs. </p>
- <p>The return value <c><![CDATA[<Scoped Function Name>_rs* ]]></c> is a pointer
- to a function with the same signature as the call-back function
- <c><![CDATA[<Scoped Function Name>_cb]]></c>, and is called after the call-back
- function has been evaluated (provided that the pointer is not equal
- to <c>NULL</c>). </p>
- </section>
-
- <section>
- <title>The Server Loop</title>
- <p>The developer has to implement code for establishing connections
- with other Erlang nodes, code for call-back functions and restore
- functions. </p>
- <p></p>
- <p>In addition, the developer also has to implement code for a
- server loop, that receives messages and calls the relevant
- <c>__exec</c> function. For that purpose the IC library function
- <c>oe_server_receive()</c> function can be used.</p>
- </section>
-
- <section>
- <title>Generating, Compiling and Linking</title>
- <p>To generate the C server skeletons type the following in an
- appropriate shell:</p>
- <p><c>erlc -I ICROOT/include "+{be, c_server}" File.idl</c>,</p>
- <p>where <c>ICROOT</c> is the root of the IC application. The
- <c>-I ICROOT/include</c> is only needed if <c>File.idl</c>
- refers to <c>erlang.idl</c>.</p>
- <p>When compiling a generated C skeleton file, the directories
- <c>ICROOT/include</c> and <c>EICROOT/include</c>, have to be
- specified as include directories, where <c>EIROOT</c> is the
- root directory of the Erl_interface application.</p>
- <p>When linking object files the <c>EIROOT/lib</c> and
- <c>ICROOT/priv/lib</c> directories have to be specified. </p>
- </section>
-
- <section>
- <title>An Example</title>
- <p>In this example the IDL specification file "random.idl" is used
- for generating C server skeletons (the file is contained in the IC
- <c>/examples/c-server</c> directory):</p>
- <code type="none">
-module rmod {
-
- interface random {
-
- double produce();
-
- oneway void init(in long seed1, in long seed2, in long seed3);
-
- };
-
-}; </code>
- <p>Generate the C server skeletons:</p>
- <code type="none">
-erlc '+{be, c_server}' random.idl
-Erlang IDL compiler version X.Y.Z </code>
- <p>Six files are generated. </p>
- <p>Compile the C server skeletons:</p>
- <p>Please read the <c>ReadMe</c> file in the
- <c>examples/c-server</c> directory.</p>
- <p>In the same directory you can find all the code for this
- example. In particular you will find the <c>server.c</c> file
- that contains all the additional code that must be written to
- obtain a complete server.</p>
- <p>In the <c>examples/c-server</c> directory you will also find
- source code for an Erlang client, which can be used for testing
- the C server.</p>
- </section>
-</chapter>
-
-
diff --git a/lib/ic/doc/src/ch_erl_genserv.xml b/lib/ic/doc/src/ch_erl_genserv.xml
deleted file mode 100644
index aa162b3652..0000000000
--- a/lib/ic/doc/src/ch_erl_genserv.xml
+++ /dev/null
@@ -1,206 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1998</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Using the Erlang Generic Server Back-end</title>
- <prepared></prepared>
- <docno></docno>
- <date>98-08-06</date>
- <rev>B</rev>
- <file>ch_erl_genserver.xml</file>
- </header>
-
- <section>
- <title>Introduction</title>
- <p>The mapping of OMG IDL to the Erlang programming language when Erlang
- generic server is the back-end of choice is similar to the one used in
- the chapter 'OMG IDL Mapping'.
- The only difference is in the generated code, a client stub and
- server skeleton to an Erlang <c>gen_server</c>. Orber's User's Guide
- contain a more detailed description of IDL to Erlang mapping.</p>
- </section>
-
- <section>
- <title>Compiling the Code</title>
- <p>The <c>ic:gen/2</c> function can be called from the command
- line as follows:</p>
- <p></p>
- <code type="none">
-shell> erlc "+{be, erl_genserv}" MyFile.idl
- </code>
- </section>
-
- <section>
- <title>Writing the Implementation File</title>
- <p>For each IDL interface <c><![CDATA[<interface name>]]></c> defined in the IDL file :</p>
- <list type="bulleted">
- <item>Create the corresponding Erlang file that will hold the
- Erlang implementation of the IDL definitions. </item>
- <item>Call the implementation file after the scope of the IDL interface,
- followed by the suffix <c>_impl</c>.</item>
- <item>Export the implementation functions.</item>
- </list>
- <p>For each function defined in the IDL interface :</p>
- <list type="bulleted">
- <item>Implement an Erlang function that uses as arguments in the same
- order, as the input arguments described in the IDL file, and returns
- the value described in the interface.</item>
- <item>When using the function, follow the mapping described in chapter 2.</item>
- </list>
- </section>
-
- <section>
- <title>An Example</title>
- <p>In this example, a file <c>random.idl</c> generates code for the Erlang
- gen_server back-end:</p>
- <code type="none">
-// Filename random.idl
-module rmod {
-
- interface random {
- // Generate a new random number
- double produce();
- // Initialize random generator
- oneway void init(in long seed1, in long seed2, in long seed3);
-
- };
-};
- </code>
- <p>When the file "random.idl" is compiled (e.g., <c>shell> erlc "+{be, erl_genserv}" random.idl</c>)
- five files are produced; two for the top scope, two for the interface scope,
- and one for the module scope. The header files for top scope and interface
- are empty and not shown here. In this case, the stub/skeleton file
- <c>rmod_random.erl</c> is the most important. This module exports two kinds of
- operations:</p>
- <list type="bulleted">
- <item><em>Administrative</em> - used when, for example, creating and
- terminating the server.</item>
- <item><em>IDL dependent</em> - operations defined in the IDL
- specification. In this case, <c>produce</c> and <c>init</c>.</item>
- </list>
-
- <section>
- <title>Administrative Operations</title>
- <p>To create a new server instance, one of the following functions should
- be used:</p>
- <list type="bulleted">
- <item><em>oe_create/0/1/2</em> - create a new instance of the object.
- Accepts <c>Env</c> and <c>RegName</c>, in that order, as parameters.
- The former is passed uninterpreted to the initialization operation
- of the call-back module, while the latter must be as the
- <c>gen_server</c> parameter <c>ServerName</c>. If <c>Env</c> is
- left out, an empty list will be passed.</item>
- <item><em>oe_create_link/0/1/2</em> - similar to <c>oe_create/0/1/2</c>,
- but create a linked server.</item>
- <item><em>typeID/0</em> - returns the scooped id compliant with the
- OMG standard. In this case the string
- <c>"IDL:rmod/random:1.0"</c>.</item>
- <item><em>stop/1</em> - asynchronously terminate the server. The required
- argument is the return value from any of the start functions.</item>
- </list>
- </section>
-
- <section>
- <title>IDL Dependent Operations</title>
- <p>Operations can either be synchronous or asynchronous
- (i.e., <c>oneway</c>). These are, respectively, mapped to
- <c>gen_server:call/2/3</c> and <c>gen_server:cast/2</c>.
- Consult the <c>gen_server</c> documentation for valid return values.</p>
- <p>The IDL dependent operations in this example are listed below.
- The first argument must be the whatever the create operation returned.</p>
- <list type="bulleted">
- <item><em>init(ServerReference, Seed1, Seed2, Seed3)</em> - initialize
- the random number generator.</item>
- <item><em>produce(ServerReference)</em> - generate a new random number.</item>
- </list>
- </section>
- <p>If the compile option <c>timeout</c> is used a timeout must be added
- (e.g., <c>produce(ServerReference, 5000)</c>). For more information, see
- the <c>gen_server</c> documentation.</p>
-
- <section>
- <title>Implementation Module</title>
- <p>The implementation module shall, unless the compile option
- <c>impl</c> is used, be named <c>rmod_random_impl.erl</c>.
- and could look like this:</p>
- <code type="none">
--module('rmod_random_impl').
-%% Mandatory gen_server operations
--export([init/1, terminate/2, code_change/3]).
-%% Add if 'handle_info' compile option used
--export([handle_info/2]).
-%% API defined in IDL specification
--export([produce/1,init/4]).
-
-%% Mandatory operations
-init(Env) ->
- {ok, []}.
-
-terminate(From, Reason) ->
- ok.
-
-code_change(OldVsn, State, Extra) ->
- {ok, State}.
-
-%% Optional
-handle_info(Info, State) ->
- {noreply, NewState}.
-
-%% IDL specification
-produce(State) ->
- case catch random:uniform() of
- {'EXIT',_} ->
- {stop, normal, "random:uniform/0 - EXIT", State};
- RUnif ->
- {reply, RUnif, State}
- end.
-
-
-init(State, S1, S2, S3) ->
- case catch random:seed(S1, S2, S3) of
- {'EXIT',_} ->
- {stop, normal, State};
- _ ->
- {noreply, State}
- end.
- </code>
- <p>Compile the code and run the example:</p>
- <code type="none"><![CDATA[
-1> make:all().
-Recompile: rmod_random
-Recompile: oe_random
-Recompile: rmod_random_impl
-up_to_date
-2> {ok,R} = rmod_random:oe_create().
-{ok,<0.30.0>}
-3> rmod_random:init(R, 1, 2, 3).
-ok
-4> rmod_random:produce(R).
-1.97963e-4
-5>
- ]]></code>
- </section>
- </section>
-</chapter>
-
-
diff --git a/lib/ic/doc/src/ch_erl_plain.xml b/lib/ic/doc/src/ch_erl_plain.xml
deleted file mode 100644
index 27387d1624..0000000000
--- a/lib/ic/doc/src/ch_erl_plain.xml
+++ /dev/null
@@ -1,176 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1998</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Using the Plain Erlang Back-end</title>
- <prepared></prepared>
- <docno></docno>
- <date>98-05-06</date>
- <rev>B</rev>
- <file>ch_erl_plain.xml</file>
- </header>
-
- <section>
- <title>Introduction</title>
- <p>The mapping of OMG IDL to the Erlang programming language when
- Plain Erlang
- is the back-end of choice is similar to the one used in pure Erlang IDL
- mapping. The only difference is on the generated code and the extended
- use of pragmas for code generation: IDL functions are translated
- to Erlang
- module function calls.</p>
- </section>
-
- <section>
- <title>Compiling the Code</title>
- <p>In the Erlang shell type :</p>
- <p>ic:gen(<c><![CDATA[<filename>, [{be, erl_plain}])]]></c>.</p>
- </section>
-
- <section>
- <title>Writing the Implementation File</title>
- <p>For each IDL interface <c><![CDATA[<interface name>]]></c> defined in the IDL file:</p>
- <list type="bulleted">
- <item>Create the corresponding Erlang file that will hold the
- Erlang implementation of the IDL definitions. </item>
- <item>Call the implementation file after the scope of the IDL interface,
- followed by the suffix <c>_impl</c>.</item>
- <item>Export the implementation functions.</item>
- </list>
- <p>For each function defined in the IDL interface :</p>
- <list type="bulleted">
- <item>Implement an Erlang function that uses as arguments in the same
- order, as the input arguments described in the IDL file, and returns
- the value described in the interface.</item>
- <item>When using the function, follow the mapping described in chapter 2.</item>
- </list>
- </section>
-
- <section>
- <title>An Example</title>
- <p> <marker id="plain_idl"></marker>
-
- In this example, a file "random.idl" is generates code for the plain Erlang
- back-end :</p>
- <list type="bulleted">
- <item>
- <p>Main file : "plain.idl"</p>
- <code type="none">
-
-module rmod {
-
- interface random {
-
- double produce();
-
- oneway void init(in long seed1, in long seed2, in long seed3);
-
- };
-
-};
- </code>
- </item>
- </list>
- <p>Compile the file :</p>
- <code type="none">
- Erlang (BEAM) emulator version 4.9
-
- Eshell V4.9 (abort with ^G)
- 1> ic:gen(random,[{be, erl_plain}]).
- Erlang IDL compiler version 2.5.1
- ok
- 2>
- </code>
- <p></p>
- <p>When the file "random.idl" is compiled it produces five files: two for
- the top scope, two for the interface scope, and one for the module
- scope. The header files for top scope and interface
- are empty and not shown here. In this case only the file for the interface
- <c>rmod_random.erl</c> is important :.
- <marker id="generated files"></marker>
-</p>
- <list type="bulleted">
- <item>
- <p>Erlang file for interface : "rmod_random.erl"</p>
- <code type="none">
-
--module(rmod_random).
-
-
-
-%% Interface functions
--export([produce/0, init/3]).
-
-%%------------------------------------------------------------
-%% Operation: produce
-%%
-%% Returns: RetVal
-%%
-produce() ->
- rmod_random_impl:produce().
-
-%%------------------------------------------------------------
-%% Operation: init
-%%
-%% Returns: RetVal
-%%
-init(Seed1, Seed2, Seed3) ->
- rmod_random_impl:init(Seed1, Seed2, Seed3).
- </code>
- </item>
- </list>
- <p>The implementation file should be called <c>rmod_random_impl.erl</c>
- and could look like this:</p>
- <code type="none">
- -module('rmod_random_impl').
-
- -export([produce/0,init/3]).
-
-
- produce() ->
- random:uniform().
-
-
- init(S1,S2,S3) ->
- random:seed(S1,S2,S3).
- </code>
- <p>Compiling the code : </p>
- <code type="none">
-2> make:all().
-Recompile: rmod_random
-Recompile: oe_random
-Recompile: rmod_random_impl
-up_to_date
- </code>
- <p></p>
- <p>Running the example : </p>
- <code type="none">
-3> rmod_random:init(1,2,3).
-ok
-4> rmod_random:produce().
-1.97963e-4
-5>
- </code>
- </section>
-</chapter>
-
diff --git a/lib/ic/doc/src/ch_ic_protocol.xml b/lib/ic/doc/src/ch_ic_protocol.xml
deleted file mode 100644
index cb64500f6e..0000000000
--- a/lib/ic/doc/src/ch_ic_protocol.xml
+++ /dev/null
@@ -1,234 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2003</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>IC Protocol</title>
- <prepared></prepared>
- <docno></docno>
- <date>2003-12-11</date>
- <rev>PA1</rev>
- <file>ch_ic_protocol.xml</file>
- </header>
- <p>The purpose of this chapter is to explain the bits and bytes of the
- IC protocol, which is a composition of the Erlang distribution protocol
- and the Erlang/OTP gen_server protocol. If you do not intend to replace
- the Erlang distribution protocol, or replace the gen_server protocol,
- skip over this chapter.
- </p>
-
- <section>
- <title>Introduction</title>
- <p>The IDL Compiler (IC) transforms Interface Definition Language
- (IDL) specifications files to interface code for Erlang, C, and
- Java. The Erlang language mapping is described in the Orber
- documentation, while the other mappings are described in the IC
- documentation (they are of course in accordance with the CORBA C
- and Java language mapping specifications, with some restrictions).
- </p>
- <p>The most important parts of an IDL specification are the operation
- declarations. An operation defines what information a client
- provides to a server, and what information (if any) the client
- gets back from the server. We consider IDL operations and language
- mappings in section 2.
- </p>
- <p>What we here call the IC protocol, is the description of messages
- exchanged between IC end-points (client and servers). It is valid
- for all IC back-ends, except the 'erl_plain' and 'erl_corba'
- back-ends.
- The IC protocol is in turn embedded into the Erlang gen_server
- protocol, which is described below.
- Finally, the gen_server protocol is embedded in the Erlang
- distribution protocol. Pertinent parts of that protocol is
- described further below.
- </p>
- </section>
-
- <section>
- <title>Language mappings and IDL operations</title>
-
- <section>
- <title>IDL Operations</title>
- <p>An IDL operation is declared as follows:</p>
- <code type="none">
- [oneway] RetType Op(in IType1 I1, in IType2 I2, ..., in ITypeN IN,
- out OType1 O1, out OType2 O2, ..., out OTypeM OM)
- N, M = 0, 1, 2, ... (2.1.1)
- </code>
- <p>`Op' is the operation name, RetType is the return type, and ITypei,
- i = 1, 2, ..., N, and OTypej, j = 1, 2, ..., M, are the `in' types
- and `out' types, respectively. The values I1, I2, ..., IN are
- provided by the caller, and the value of RetType, and the values
- O1, O2, ..., OM, are provided as results to the caller.
- </p>
- <p>The types can be any basic types or derived types declared in the
- IDL specification of which the operation declaration is a part.
- </p>
- <p>If the RetType has the special name `void' there is no return
- value (but there might still be result values O1, 02, ..., OM).
- </p>
- <p>The `in' and `out' parameters can be declared in any order, but
- for clarity we have listed all `in' parameters before the `out'
- parameters in the declaration above.
- </p>
- <p>If the keyword `oneway' is present, the operation is a cast, i.e.
- there is no confirmation of the operation, and consequently there
- must be no result values: RetType must be equal to `void', and M =
- 0 must hold.
- </p>
- <p>Otherwise the operation is a call, i.e. it is confirmed (or else
- an exception is raised).
- </p>
- <p>Note carefully that an operation declared without `oneway' is
- always a call, even if RetType is `void' and M = 0.
- </p>
- </section>
-
- <section>
- <title>Language Mappings</title>
- <p>There are several CORBA Language Mapping specifications. These are
- about mapping interfaces to various programming languages. IC
- supports the CORBA C and Java mapping specifications, and the
- Erlang language mapping specified in the Orber documentation.
- </p>
- <p>Excerpt from "6.4 Basic OMG IDL Types" in the Orber User's Guide:
- </p>
- <list type="bulleted">
- <item>
- <p>Functions with return type void will return the atom ok.</p>
- </item>
- </list>
- <p>Excerpt from "6.13 Invocations of Operations" in the Orber User's
- Guide:
- </p>
- <list type="bulleted">
- <item>
- <p>A function call will invoke an operation. The first parameter
- of the function should be the object reference and then all in
- and inout parameters follow in the same order as specified in
- the IDL specification. The result will be a return value
- unless the function has inout or out parameters specified; in
- which case, a tuple of the return value, followed by the
- parameters will be returned.</p>
- </item>
- </list>
- <p>Hence the function that is mapped from an IDL operation to Erlang
- always have a return value (an Erlang function always has). That
- fact has influenced the IC protocol, in that there is always a
- return value (which is 'ok' if the return type was declared 'void'). </p>
- </section>
- </section>
-
- <section>
- <title>IC Protocol</title>
- <p>Given the operation declaration (2.1.1) the IC protocol maps to
- messages as follows, defined in terms of Erlang terms.
- </p>
-
- <section>
- <title>Call (Request/Reply, i.e. not oneway)</title>
- <code type="none">
- request: Op atom() N = 0
- {Op, I1, I2, ..., IN} tuple() N > 0
- (3.1.1)
-
- reply: Ret M = 0
- {Ret, O1, O2, ..., OM} M > 0
- (3.1.2)</code>
- <p><em>Notice:</em> Even if the RetType of the operation Op is
- declared to be 'void', a return value 'ok' is returned in
- the reply message. That
- return value is of no significance, and is therefore ignored (note
- however that a C server back-end returns the atom 'void' instead
- of 'ok').
- </p>
- </section>
-
- <section>
- <title>Cast (oneway)</title>
- <code type="none">
-
- notification: Op atom() N = 0
- {Op, I1, I2, ..., IN} tuple() N > 0
- (3.2.1)</code>
- <p>(There is of course no return message).
- </p>
- </section>
- </section>
-
- <section>
- <title>Gen_server Protocol</title>
- <p>Most of the IC generated code deals with encoding and decoding the
- gen_server protocol.
- </p>
-
- <section>
- <title>Call</title>
- <code type="none">
-
- request: {'$gen_call', {self(), Ref}, Request} (4.1.1)
-
- reply: {Ref, Reply} (4.1.2)</code>
- <p>where Request and Reply are the messages defined in the previous
- chapter.
- </p>
- </section>
-
- <section>
- <title>Cast</title>
- <code type="none">
- notification: {'$gen_cast', Notification} (4.2.1) </code>
- <p>where Notification is the message defined in the previous chapter.
- </p>
- </section>
- </section>
-
- <section>
- <title>Erlang Distribution Protocol</title>
- <p>Messages (of interest here) between Erlang nodes are of the form: </p>
- <code type="none">
- Len(4), Type(1), CtrlBin(N), MsgBin(M) (5.1) </code>
- <p>Type is equal to 112 = PASS_THROUGH.
- </p>
- <p>CtrlBin and MsgBin are Erlang terms in binary form (as if created
- by term_to_binary/1), whence for each of them the first byte is
- equal to 131 = VERSION_MAGIC.
- </p>
- <p>CtrlBin (of interest here) contains the SEND and REG_SEND control
- messages, which are binary forms of the Erlang terms</p>
- <code type="none">
- {2, Cookie, ToPid} , (5.2) </code>
- <p>and</p>
- <code type="none">
- {6, FromPid, Cookie, ToName} , (5.3) </code>
- <p>respectively.
- </p>
- <p>The CtrlBin(N) message is read and written by erl_interface code
- (C), j_interface code (Java), or the Erlang distribution
- implementation, which are invoked from IC generated code.
- </p>
- <p>The MsgBin(N) is the "real" message, i.e. of the form described
- in the previous section.
- </p>
- </section>
-</chapter>
-
diff --git a/lib/ic/doc/src/ch_introduction.xml b/lib/ic/doc/src/ch_introduction.xml
deleted file mode 100644
index 9ac2f96a95..0000000000
--- a/lib/ic/doc/src/ch_introduction.xml
+++ /dev/null
@@ -1,149 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1998</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Using the IC Compiler</title>
- <prepared></prepared>
- <docno></docno>
- <date>2002-08-02</date>
- <rev>PB1</rev>
- <file>ch_introduction.xml</file>
- </header>
-
- <section>
- <title>Introduction</title>
- <p>The IC application is an IDL compiler implemented in Erlang.
- The IDL compiler generates client stubs and server skeletons.
- Several back-ends are supported, and they fall into three main
- groups.</p>
- <p>The first group consists of a CORBA back-end:</p>
- <taglist>
- <tag>IDL to Erlang CORBA</tag>
- <item>
- <p>This back-end is for CORBA communication and implementation,
- and the generated code uses the CORBA specific protocol for
- communication between clients and servers. See the
- <em>Orber</em> application User's Guide and manuals for
- further details.</p>
- </item>
- </taglist>
- <p>The second group consists of a simple Erlang back-end:</p>
- <taglist>
- <tag>IDL to plain Erlang</tag>
- <item>
- <p>This back-end provides a very simple Erlang client
- interface. It can only be used within an Erlang node,
- and the communication between client and "server" is
- therefore in terms of ordinary function calls. </p>
- <p>This back-end can be considered a short-circuit version of
- the IDL to Erlang gen_server back-end (see further below).</p>
- </item>
- </taglist>
- <p>The third group consists of backends for Erlang, C, and
- Java. The communication between clients and servers is by the
- Erlang distribution protocol, facilitated by
- <em>erl_interface</em> and <em>jinterface</em> for C and Java,
- respectively.</p>
- <p>All back-ends of the third group generate code compatible with
- the Erlang gen_server behavior protocol. Thus generated client
- code corresponds to <c>call()</c> or <c>cast()</c> of an Erlang
- <c>gen_server</c>. Similarly, generated server code corresponds
- to <c>handle_call()</c> or <c>handle_cast()</c> of an Erlang
- <c>gen_server</c>.</p>
- <p>The back-ends of the third group are:
- </p>
- <taglist>
- <tag>IDL to Erlang gen_server</tag>
- <item>
- <p>Client stubs and server skeletons are generated. Data types
- are mapped according to the IDL to Erlang mapping described
- in the <em>Orber User's Guide</em>.</p>
- <p></p>
- </item>
- <tag>IDL to C client</tag>
- <item>
- <p>Client stubs are generated. The mapping of data types is
- described further on in the C client part of this guide.</p>
- </item>
- <tag>IDL to C server</tag>
- <item>
- <p>Server skeletons are generated. The mapping of data types is
- described further on in the C server part of this guide.</p>
- </item>
- <tag>IDL to Java</tag>
- <item>
- <p>Client stubs and server skeletons are generated. The mapping
- of data types is described further on in the Java part of
- this guide.</p>
- </item>
- </taglist>
- </section>
-
- <section>
- <title>Compilation of IDL Files</title>
- <p>The IC compiler is invoked by executing the generic <c>erlc</c>
- compiler from a shell:</p>
- <code type="none">
-%> erlc +'{be,BackEnd}' File.idl
- </code>
- <p>where <c>BackEnd</c> is according to the table below, and
- <c>File.idl</c> is the IDL file to be compiled.</p>
- <table>
- <row>
- <cell align="left" valign="middle"><em>Back-end</em></cell>
- <cell align="left" valign="middle"><c>BackEnd</c>option</cell>
- </row>
- <row>
- <cell align="left" valign="middle">IDL to CORBA</cell>
- <cell align="left" valign="middle"><c>erl_corba</c></cell>
- </row>
- <row>
- <cell align="left" valign="middle">IDL to CORBA template</cell>
- <cell align="left" valign="middle"><c>erl_template</c></cell>
- </row>
- <row>
- <cell align="left" valign="middle">IDL to plain Erlang</cell>
- <cell align="left" valign="middle"><c>erl_plain</c></cell>
- </row>
- <row>
- <cell align="left" valign="middle">IDL to Erlang gen_server</cell>
- <cell align="left" valign="middle"><c>erl_genserv</c></cell>
- </row>
- <row>
- <cell align="left" valign="middle">IDL to C client</cell>
- <cell align="left" valign="middle"><c>c_client</c></cell>
- </row>
- <row>
- <cell align="left" valign="middle">IDL to C server</cell>
- <cell align="left" valign="middle"><c>c_server</c></cell>
- </row>
- <row>
- <cell align="left" valign="middle">IDL to Java</cell>
- <cell align="left" valign="middle"><c>java</c></cell>
- </row>
- <tcaption>Compiler back-ends and options</tcaption>
- </table>
- <p>For more details on IC compiler options consult the ic(3) manual page.</p>
- </section>
-</chapter>
-
diff --git a/lib/ic/doc/src/ch_java.xml b/lib/ic/doc/src/ch_java.xml
deleted file mode 100644
index a733adaf65..0000000000
--- a/lib/ic/doc/src/ch_java.xml
+++ /dev/null
@@ -1,738 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>IDL to Java language Mapping</title>
- <prepared></prepared>
- <docno></docno>
- <date>98-09-24</date>
- <rev>A</rev>
- <file>ch_java.xml</file>
- </header>
-
- <section>
- <title>Introduction</title>
- <p>This chapter describes the mapping of OMG IDL constructs to the Java
- programming language for the generation of native Java - Erlang
- communication. </p>
- <p>This language mapping defines the following:</p>
- <list type="bulleted">
- <item>
- <p>All OMG IDL basic types</p>
- </item>
- <item>
- <p>All OMG IDL constructed types</p>
- </item>
- <item>
- <p>References to constants defined in OMG IDL</p>
- </item>
- <item>
- <p>Invocations of operations, including passing of
- parameters and receiving of result</p>
- </item>
- <item>
- <p>Access to attributes</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Specialties in the Mapping</title>
-
- <section>
- <title>Names Reserved by the Compiler</title>
- <p>The IDL compiler reserves all identifiers starting with
- <c>OE_</c> and <c>oe_</c> for internal use.</p>
- </section>
- </section>
-
- <section>
- <title>Basic OMG IDL Types</title>
- <p>The mapping of basic types are according to the standard. All basic types have
- a special Holder class.</p>
- <table>
- <row>
- <cell align="left" valign="middle">OMG IDL type</cell>
- <cell align="left" valign="middle">Java type</cell>
- </row>
- <row>
- <cell align="left" valign="middle">float</cell>
- <cell align="left" valign="middle">float</cell>
- </row>
- <row>
- <cell align="left" valign="middle">double</cell>
- <cell align="left" valign="middle">double</cell>
- </row>
- <row>
- <cell align="left" valign="middle">short</cell>
- <cell align="left" valign="middle">short</cell>
- </row>
- <row>
- <cell align="left" valign="middle">unsigned short</cell>
- <cell align="left" valign="middle">short</cell>
- </row>
- <row>
- <cell align="left" valign="middle">long</cell>
- <cell align="left" valign="middle">int</cell>
- </row>
- <row>
- <cell align="left" valign="middle">long long</cell>
- <cell align="left" valign="middle">long</cell>
- </row>
- <row>
- <cell align="left" valign="middle">unsigned long</cell>
- <cell align="left" valign="middle">long</cell>
- </row>
- <row>
- <cell align="left" valign="middle">unsigned long long</cell>
- <cell align="left" valign="middle">long</cell>
- </row>
- <row>
- <cell align="left" valign="middle">char</cell>
- <cell align="left" valign="middle">char</cell>
- </row>
- <row>
- <cell align="left" valign="middle">wchar</cell>
- <cell align="left" valign="middle">char</cell>
- </row>
- <row>
- <cell align="left" valign="middle">boolean</cell>
- <cell align="left" valign="middle">boolean</cell>
- </row>
- <row>
- <cell align="left" valign="middle">octet</cell>
- <cell align="left" valign="middle">octet</cell>
- </row>
- <row>
- <cell align="left" valign="middle">string</cell>
- <cell align="left" valign="middle">java.lang.String</cell>
- </row>
- <row>
- <cell align="left" valign="middle">wstring</cell>
- <cell align="left" valign="middle">java.lang.String</cell>
- </row>
- <row>
- <cell align="left" valign="middle">any</cell>
- <cell align="left" valign="middle">Any</cell>
- </row>
- <row>
- <cell align="left" valign="middle">long double</cell>
- <cell align="left" valign="middle">Not supported</cell>
- </row>
- <row>
- <cell align="left" valign="middle">Object</cell>
- <cell align="left" valign="middle">Not supported</cell>
- </row>
- <row>
- <cell align="left" valign="middle">void</cell>
- <cell align="left" valign="middle">void</cell>
- </row>
- <tcaption>OMG IDL basic types</tcaption>
- </table>
- </section>
-
- <section>
- <title>Constructed OMG IDL Types</title>
- <p>All constructed types are according to the standard with three (3) major exceptions.</p>
- <p></p>
- <list type="bulleted">
- <item>
- <p>The IDL Exceptions are not implemented in this Java mapping.</p>
- <p></p>
- </item>
- <item>
- <p>The functions used for read/write to streams, defined in <c>Helper</c> functions
- are named unmarshal (instead for read) and marshal (instead for write). </p>
- <p></p>
- </item>
- <item>
- <p>The streams used in <c>Helper</c> functions are <c>OtpInputStream</c> for
- input and <c>OtpOutputStream</c> for output.</p>
- <p></p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Mapping for Constants</title>
- <p>Constants are mapped according to the standard.</p>
- </section>
-
- <section>
- <title>Invocations of Operations</title>
- <p>Operation invocation is implemented according to the standard.
- The implementation is in the class <c><![CDATA[_<nterfacename>Stub.java]]></c> which implements
- the interface in <c><![CDATA[<nterfacename>.java]]></c>.</p>
- <code type="none">
-test._iStub client;
-
-client.op(10);
- </code>
-
- <section>
- <title>Operation Implementation</title>
- <p>The server is implemented through extension of the class
- <c><![CDATA[_<nterfacename>ImplBase.java]]></c> and implementation of all the methods in the
- interface.</p>
- <code type="none">
-public class server extends test._iImplBase {
-
- public void op(int i) throws java.lang.Exception {
- System.out.println("Received call op()");
- o.value = i;
- return i;
- }
-
-}
- </code>
- </section>
- </section>
-
- <section>
- <title>Exceptions</title>
- <p>While exception mapping is not implemented, the stubs will
- generate some Java exceptions in case of operation failure.
- No exceptions are propagated through the communication.</p>
- </section>
-
- <section>
- <title>Access to Attributes</title>
- <p>Attributes are supported according to the standard.</p>
- </section>
-
- <section>
- <title>Summary of Argument/Result Passing for Java</title>
- <p>All types (<c>in</c>, <c>out</c> or <c>inout</c>) of user defined parameters are supported
- in the Java mapping. This is also the case in the Erlang mappings but <em>not</em> in the C
- mapping. <c>inout</c> parameters are not supported in the C mapping so if you are going to
- do calls to or from a C program <c>inout</c> cannot be used in the IDL specifications.</p>
- <p><c>out</c> and <c>inout</c> parameters must be of Holder types. There is a jar file ( <c>ic.jar</c>)
- with Holder classes for the basic types in the <c>ic</c> application. This library is in the directory
- <c><![CDATA[$OTPROOT/lib/ic_<version number>/priv]]></c>.</p>
- </section>
-
- <section>
- <title>Communication Toolbox</title>
- <p>The generated client and server stubs use the classes
- defined in the <c>jinterface</c> package to communicate
- with other nodes.
- The most important classes are :</p>
- <list type="bulleted">
- <item>
- <p><c>OtpInputStream</c> which is the stream class used for incoming message storage</p>
- <p></p>
- </item>
- <item>
- <p><c>OtpOutputStream</c> which is the stream class used for outgoing message storage</p>
- <p></p>
- </item>
- <item>
- <p><c>OtpErlangPid</c> which is the process identification class used to identify processes inside
- a java node.</p>
- <p>The recommended constructor function for the OtpErlangPid is
- <c>OtpErlangPid(String node, int id, int serial, int creation)</c> where :</p>
- <p></p>
- <list type="bulleted">
- <item>
- <p><c>String node</c>, is the name of the node where this process runs.</p>
- <p></p>
- </item>
- <item>
- <p><c>int id</c>, is the identification number for this identity.</p>
- <p></p>
- </item>
- <item>
- <p><c>int serial</c>, internal information, must be an 18-bit integer.</p>
- <p></p>
- </item>
- <item>
- <p><c>int creation</c>, internal information, must have value in range 0..3.</p>
- <p></p>
- </item>
- </list>
- </item>
- <item>
- <p><c>OtpConnection</c> which is used to define a connection between nodes.</p>
- <p>While the connection object is stub side constructed in client stubs, it is
- returned after calling the <c>accept</c> function from an OtpErlangServer object
- in server stubs.
- The following methods used for node connection :</p>
- <p></p>
- <list type="bulleted">
- <item>
- <p><c>OtpInputStream receiveBuf()</c>, which returns the incoming streams that
- contain the message arrived.</p>
- <p></p>
- </item>
- <item>
- <p><c>void sendBuf(OtpErlangPid client, OtpOutputStream reply)</c>, which sends
- a reply message (in an OtpOutputStream form) to the client node.</p>
- <p></p>
- </item>
- <item>
- <p><c>void close()</c>, which closes a connection.</p>
- <p></p>
- </item>
- </list>
- </item>
- <item>
- <p><c>OtpServer</c> which is used to define a server node.</p>
- <p>The recommended constructor function for the OtpServer is :</p>
- <p></p>
- <list type="bulleted">
- <item>
- <p><c>OtpServer(String node, String cookie)</c>. where :</p>
- <p></p>
- <list type="bulleted">
- <item>
- <p><c>node</c> is the requested name for the new java node,
- represented as a String object.</p>
- <p></p>
- </item>
- <item>
- <p><c>cookie</c> is the requested cookie name for the new java node,
- represented as a String object.</p>
- <p></p>
- </item>
- </list>
- </item>
- </list>
- <p>The following methods used for node registration and connection acceptance :</p>
- <p></p>
- <list type="bulleted">
- <item>
- <p><c>boolean publishPort()</c>, which registers the server node to <c>epmd</c> daemon.</p>
- <p></p>
- </item>
- <item>
- <p><c>OtpConnection accept()</c>, which waits for a connection and returns the
- OtpConnection object which is unique for each client node.</p>
- <p></p>
- </item>
- </list>
- </item>
- </list>
- </section>
-
- <section>
- <title>The Package com.ericsson.otp.ic</title>
- <p>The package <seealso marker="java/com/ericsson/otp/ic/package-summary">com.ericsson.otp.ic</seealso>
- contains a number of java classes specially designed for the IC generated java-back-ends :</p>
- <list type="bulleted">
- <item>
- <p>Standard java classes defined through OMG-IDL java mapping :</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="java/com/ericsson/otp/ic/BooleanHolder">BooleanHolder</seealso></p>
- </item>
- <item>
- <p><seealso marker="java/com/ericsson/otp/ic/ByteHolder">ByteHolder</seealso></p>
- </item>
- <item>
- <p><seealso marker="java/com/ericsson/otp/ic/CharHolder">CharHolder</seealso></p>
- </item>
- <item>
- <p><seealso marker="java/com/ericsson/otp/ic/ShortHolder">ShortHolder</seealso></p>
- </item>
- <item>
- <p><seealso marker="java/com/ericsson/otp/ic/IntHolder">IntHolder</seealso></p>
- </item>
- <item>
- <p><seealso marker="java/com/ericsson/otp/ic/LongHolder">LongHolder</seealso></p>
- </item>
- <item>
- <p><seealso marker="java/com/ericsson/otp/ic/FloatHolder">FloatHolder</seealso></p>
- </item>
- <item>
- <p><seealso marker="java/com/ericsson/otp/ic/DoubleHolder">DoubleHolder</seealso></p>
- </item>
- <item>
- <p><seealso marker="java/com/ericsson/otp/ic/StringHolder">StringHolder</seealso></p>
- </item>
- <item>
- <p><seealso marker="java/com/ericsson/otp/ic/Any">Any</seealso>,
- <seealso marker="java/com/ericsson/otp/ic/AnyHelper">AnyHelper</seealso>,
- <seealso marker="java/com/ericsson/otp/ic/AnyHolder">AnyHolder</seealso></p>
- </item>
- <item>
- <p><seealso marker="java/com/ericsson/otp/ic/TypeCode">TypeCode</seealso></p>
- </item>
- <item>
- <p><seealso marker="java/com/ericsson/otp/ic/TCKind">TCKind</seealso></p>
- <p></p>
- </item>
- </list>
- </item>
- <item>
- <p>Implementation-dependant classes :</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="java/com/ericsson/otp/ic/Environment">Environment</seealso></p>
- </item>
- <item>
- <p><seealso marker="java/com/ericsson/otp/ic/Holder">Holder</seealso></p>
- <p></p>
- </item>
- </list>
- </item>
- <item>
- <p>Erlang compatibility classes :</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="java/com/ericsson/otp/ic/Pid">Pid</seealso>,
- <seealso marker="java/com/ericsson/otp/ic/PidHelper">PidHelper</seealso>,
- <seealso marker="java/com/ericsson/otp/ic/PidHolder">PidHolder</seealso></p>
- <p>The Pid class originates from <c>OtpErlangPid</c> and is used to
- represent the Erlang built-in <c>pid</c> type, a process's identity.
- PidHelper and PidHolder are helper respectively holder classes for Pid.</p>
- <p></p>
- </item>
- <item>
- <p><seealso marker="java/com/ericsson/otp/ic/Ref">Ref</seealso>,
- <seealso marker="java/com/ericsson/otp/ic/RefHelper">RefHelper</seealso>,
- <seealso marker="java/com/ericsson/otp/ic/RefHolder">RefHolder</seealso></p>
- <p>The Ref class originates from <c>OtpErlangRef</c> and is used to
- represent the Erlang built-in <c>ref</c> type, an Erlang reference.
- RefHelper and RefHolder are helper respectively holder classes for Ref.</p>
- <p></p>
- </item>
- <item>
- <p><seealso marker="java/com/ericsson/otp/ic/Port">Port</seealso>,
- <seealso marker="java/com/ericsson/otp/ic/PortHelper">PortHelper</seealso>,
- <seealso marker="java/com/ericsson/otp/ic/PortHolder">PortHolder</seealso></p>
- <p>The Port class originates from <c>OtpErlangPort</c> and is used to
- represent the Erlang built-in <c>port</c> type, an Erlang port.
- PortHelper and PortHolder are helper respectively holder classes for Port.</p>
- <p></p>
- </item>
- <item>
- <p><seealso marker="java/com/ericsson/otp/ic/Term">Term</seealso>,
- <seealso marker="java/com/ericsson/otp/ic/TermHelper">TermHelper</seealso>,
- <seealso marker="java/com/ericsson/otp/ic/TermHolder">TermHolder</seealso></p>
- <p>The Term class originates from <c>Any</c> and is used to
- represent the Erlang built-in <c>term</c> type, an Erlang term.
- TermHelper and TermHolder are helper respectively holder classes for Term.</p>
- <p></p>
- </item>
- </list>
- <p>To use the Erlang build-in classes, you will have to include the file <c>erlang.idl</c>
- located under <c>$OTPROOT/lib/ic/include</c>.</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>The Term Class</title>
- <p>The <c>Term</c> class is intended to represent the Erlang term generic type.
- It extends the <c>Any</c> class and it is basically used in the same way as
- in the Any type.</p>
- <p>The big difference between Term and Any is the use of <c>guard</c> methods
- instead of <c>TypeCode</c> to determine the data included in the Term.
- This is especially true when the Term's value class cannot be
- determined at compilation time. The guard methods found in Term :</p>
- <list type="bulleted">
- <item>
- <p><c>boolean isAtom()</c> returns <c>true</c> if the Term is an OtpErlangAtom, <c>false</c> otherwise</p>
- <p></p>
- </item>
- <item>
- <p><c>boolean isConstant()</c> returns <c>true</c> if the Term is neither an OtpErlangList nor an OtpErlangTuple, <c>false</c> otherwise</p>
- <p></p>
- </item>
- <item>
- <p><c>boolean isFloat()</c> returns <c>true</c> if the Term is an OtpErlangFloat, <c>false</c> otherwise</p>
- <p></p>
- </item>
- <item>
- <p><c>boolean isInteger()</c> returns <c>true</c> if the Term is an OtpErlangInt, <c>false</c> otherwise</p>
- <p></p>
- </item>
- <item>
- <p><c>boolean isList()</c> returns <c>true</c> if the Term is an OtpErlangList, <c>false</c> otherwise</p>
- <p></p>
- </item>
- <item>
- <p><c>boolean isString()</c> returns <c>true</c> if the Term is an OtpErlangString, <c>false</c> otherwise</p>
- <p></p>
- </item>
- <item>
- <p><c>boolean isNumber()</c> returns <c>true</c> if the Term is an OtpErlangInteger or an OtpErlangFloat, <c>false</c> otherwise</p>
- <p></p>
- </item>
- <item>
- <p><c>boolean isPid()</c> returns <c>true</c> if the Term is an OtpErlangPid or Pid, <c>false</c> otherwise</p>
- <p></p>
- </item>
- <item>
- <p><c>boolean isPort()</c> returns <c>true</c> if the Term is an OtpErlangPort or Port, <c>false</c> otherwise</p>
- <p></p>
- </item>
- <item>
- <p><c>boolean isReference()</c> returns <c>true</c> if the Term is an OtpErlangRef, <c>false</c> otherwise</p>
- <p></p>
- </item>
- <item>
- <p><c>boolean isTuple()</c> returns <c>true</c> if the Term is an OtpErlangTuple, <c>false</c> otherwise</p>
- <p></p>
- </item>
- <item>
- <p><c>boolean isBinary()</c> returns <c>true</c> if the Term is an OtpErlangBinary, <c>false</c> otherwise</p>
- <p></p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Stub File Types</title>
- <p>For each interface, three (3) stub/skeleton files are generated :</p>
- <list type="bulleted">
- <item>
- <p>A java interface file, named after the idl interface.</p>
- <p></p>
- </item>
- <item>
- <p>A client stub file, named after the convention <c><![CDATA[_< interface name >Stub]]></c>
- which implements the java interface. Example : <c>_stackStub</c>.java</p>
- <p></p>
- </item>
- <item>
- <p>A server stub file, named after the convention <c><![CDATA[_< interface name >ImplBase]]></c>
- which implements the java interface. Example : <c>_stackImplBase</c>.java</p>
- <p></p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Client Stub Initialization, Methods Exported</title>
- <p>The recommended constructor function for client stubs accepts four (4) parameters :</p>
- <p></p>
- <list type="bulleted">
- <item>
- <p><c>String selfNode</c>, the node identification name to be used in the new
- client node.</p>
- <p></p>
- </item>
- <item>
- <p><c>String peerNode</c>, the node identification name where the client process is running.</p>
- <p></p>
- </item>
- <item>
- <p><c>String cookie</c>, the cookie to be used.</p>
- <p></p>
- </item>
- <item>
- <p><c>Object server</c>, where the java Object can be one of:</p>
- <p></p>
- <list type="bulleted">
- <item>
- <p><c>OtpErlangPid</c>, the server's process identity under the node where the server
- process is running.</p>
- <p></p>
- </item>
- <item>
- <p><c>String</c>, the server's registered name under the node where the server
- process is running.</p>
- <p></p>
- </item>
- </list>
- </item>
- </list>
- <p>The methods exported from the generated client stub are :</p>
- <p></p>
- <list type="bulleted">
- <item>
- <p><c>void __disconnect()</c>, which disconnects the server connection.</p>
- <p></p>
- </item>
- <item>
- <p><c>void __reconnect()</c>, which disconnects the server connection if open,
- and then connects to the same peer.</p>
- <p></p>
- </item>
- <item>
- <p><c>void __stop()</c>, which sends the standard stop termination call.
- When connected to an Erlang server, the server will be terminated.
- When connected to a java server, this will set a stop flag that
- denotes that the server must be terminated.</p>
- <p></p>
- </item>
- <item>
- <p><c>com.ericsson.otp.erlang.OtpErlangRef __getRef()</c>, will return the message reference
- received from a server that denotes which call it is referring to.
- This is useful when building asynchronous clients.</p>
- <p></p>
- </item>
- <item>
- <p><c>java.lang.Object __server()</c>, which returns the server for the current connection.</p>
- <p></p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Server Skeleton Initialization, Server Stub Implementation, Methods Exported</title>
- <p>The constructor function for server skeleton accepts no parameters.</p>
- <p>The server skeleton file contains a server <c>switch</c> which
- decodes messages from the input stream and calls implementation
- (<c>callback</c>) functions.
- As the server skeleton is declared <c>abstract</c>, the application
- programmer will have to create a stub class that <c>extends</c> the
- skeleton file. In this class, all operations defined in the interface
- class, generated under compiling the idl file, are implemented.</p>
- <p>The server skeleton file exports the following methods:</p>
- <p></p>
- <list type="bulleted">
- <item>
- <p><c>OtpOutputStrem invoke(OtpInputStream request)</c>, where the input
- stream <c>request</c> is unmarshalled, the implementation function is called
- and a reply stream is marshalled.</p>
- <p></p>
- </item>
- <item>
- <p><c>boolean __isStopped()</c>, which returns true if a stop message is received.
- The implementation of the stub should always check if such a message is received
- and terminate if so.</p>
- <p></p>
- </item>
- <item>
- <p><c>boolean __isStopped(com.ericsson.otp.ic.Environment)</c>, which returns true if
- a stop message is received for a certain Environment and Connection.
- The implementation of the stub should always check if such a message is received
- and terminate if so.</p>
- <p></p>
- </item>
- <item>
- <p><c>OtpErlangPid __getCallerPid()</c>, which returns the caller identity for the latest call.</p>
- <p></p>
- </item>
- <item>
- <p><c>OtpErlangPid __getCallerPid(com.ericsson.otp.ic.Environment)</c>, which returns the caller
- identity for the latest call on a certain Environment.</p>
- <p></p>
- </item>
- <item>
- <p><c>java.util.Dictionary __operations()</c>, which returns the operation dictionary which
- holds all operations supported by the server skeleton.</p>
- <p></p>
- </item>
- </list>
- </section>
-
- <section>
- <title>A Mapping Example</title>
- <p> <marker id="stack_idl"></marker>
-
- This is a small example of a simple stack. There are two
- operations on the stack, push and pop. The example shows some of the
- generated files.</p>
- <code type="none">
-// The source IDL file: stack.idl
-
-struct s {
- long l;
- string s;
-};
-
-interface stack {
- void push(in s val);
- s pop();
-};
- </code>
- <p>When this file is compiled it produces eight files. Three important files
- are shown below. <marker id="stack_serv"></marker>
-</p>
- <p>The public interface is in <em>stack.java</em>.</p>
- <code type="none">
-
-public interface stack {
-
-/****
- * Operation "stack::push" interface functions
- *
- */
-
- void push(s val) throws java.lang.Exception;
-
-/****
- * Operation "stack::pop" interface functions
- *
- */
-
- s pop() throws java.lang.Exception;
-
-}
- </code>
- <p>For the IDL struct s three files are generated, a public class in <em>s.java</em>.</p>
- <code type="none">
-
-final public class s {
- // instance variables
- public int l;
- public java.lang.String s;
-
- // constructors
- public s() {};
- public s(int _l, java.lang.String _s) {
- l = _l;
- s = _s;
- };
-
-};
- </code>
- <p>A holder class in <em>sHolder.java</em> and a helper class in <em>sHelper.java</em>.
- The helper class is used for marshalling.</p>
- <code type="none">
-
-public class sHelper {
-
- // constructors
- private sHelper() {};
-
- // methods
- public static s unmarshal(OtpInputStream in)
- throws java.lang.Exception {
- :
- :
- };
-
- public static void marshal(OtpOutputStream out, s value)
- throws java.lang.Exception {
- :
- :
- };
-
-};
- </code>
- </section>
-
- <section>
- <title>Running the Compiled Code</title>
- <p>When using the generated java code you must have added
- <c><![CDATA[$OTPROOT/lib/ic_<version number>/priv]]></c> and
- <c><![CDATA[$OTPROOT/lib/jinterface_<version number>/priv]]></c> to your
- <c>CLASSPATH</c> variable to get
- basic Holder types and the communication classes.</p>
- </section>
-</chapter>
-
diff --git a/lib/ic/doc/src/erl-part.xml b/lib/ic/doc/src/erl-part.xml
deleted file mode 100644
index 9c9cb6a574..0000000000
--- a/lib/ic/doc/src/erl-part.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2002</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>IDL to Erlang language Mapping</title>
- <prepared></prepared>
- <docno></docno>
- <date>2002-06-25</date>
- <rev>A</rev>
- </header>
- <description>
- <p>Tjosan Erlang</p>
- </description>
- <include file="ch_erl_plain"></include>
- <include file="ch_erl_genserv"></include>
-</part>
-
diff --git a/lib/ic/doc/src/fascicules.xml b/lib/ic/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/ic/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/ic/doc/src/ic.gif b/lib/ic/doc/src/ic.gif
deleted file mode 100644
index d78cf7d8ed..0000000000
--- a/lib/ic/doc/src/ic.gif
+++ /dev/null
Binary files differ
diff --git a/lib/ic/doc/src/ic.xml b/lib/ic/doc/src/ic.xml
deleted file mode 100644
index 98e8414a4e..0000000000
--- a/lib/ic/doc/src/ic.xml
+++ /dev/null
@@ -1,468 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>ic</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>2004-01-08</date>
- <rev>B</rev>
- </header>
- <module>ic</module>
- <modulesummary>The Erlang IDL Compiler</modulesummary>
- <description>
- <p>The ic module is an Erlang implementation of an OMG IDL
- compiler. Depending on the choice of back-end the code will map
- to Erlang, C, or Java. The compiler generates client stubs and
- server skeletons.</p>
- <p>Two kinds of files are generated for each scope: Ordinary code
- files and header files. The latter are used for defining record
- definitions, while the ordinary files contain the object
- interface functions.</p>
- </description>
- <funcs>
- <func>
- <name>ic:gen(FileName) -> Result</name>
- <name>ic:gen(FileName, [Option]) -> Result</name>
- <fsummary>Generate stub and server code according to the OMG CORBA standard.</fsummary>
- <type>
- <v>Result = ok | error | {ok, [Warning]} | {error, [Warning], [Error]}</v>
- <v></v>
- <v>Option = [ GeneralOption | CodeOption | WarningOption | BackendOption]</v>
- <v></v>
- <v>GeneralOption = </v>
- <v>{outdir, String()} | {cfgfile, String()} | {use_preproc, bool()} |</v>
- <v>{preproc_cmd, String()} | {preproc_flags, String()}</v>
- <v></v>
- <v>CodeOption =</v>
- <v>{gen_hrl, bool()} | {serv_last_call, exception | exit} | {{impl, String()}, String()} | {light_ifr, bool()}</v>
- <v>this | {this, String()} | {{this, String()}, bool()} |</v>
- <v>from | {from, String()} | {{from, String()}, bool()} |</v>
- <v>handle_info | {handle_info, String()} | {{handle_info, String()}, bool()} |</v>
- <v>timeout | {timeout, String()} | {{timeout, String()}, bool()} |</v>
- <v>{scoped_op_calls, bool()} | {scl, bool()} |</v>
- <v>{user_protocol, Prefix} |</v>
- <v>{c_timeout, {SendTimeout, RecvTimeout}} |</v>
- <v>{c_report, bool()} |</v>
- <v>{precond, {atom(), atom()}} | {{precond, String()} {atom(), atom()}} |</v>
- <v>{postcond, {atom(), atom()}} | {{postcond, String()} {atom(), atom()}}</v>
- <v></v>
- <v>WarningOption =</v>
- <v>{'Wall', bool()} | {maxerrs, int() | infinity} |</v>
- <v>{maxwarns, int() | infinity} | {nowarn, bool()} |</v>
- <v>{warn_name_shadow, bool()} | {pedantic, bool()} |</v>
- <v>{silent, bool()}</v>
- <v></v>
- <v>BackendOption = {be, Backend}</v>
- <v></v>
- <v>Backend = erl_corba | erl_template | erl_plain | erl_genserv | c_client | c_server | java</v>
- <v></v>
- <v>DirNAme = string() | atom()</v>
- <v>FileName = string() | atom()</v>
- </type>
- <desc>
- <p>The tuple <c>{Option, true}</c> can be replaced by
- <c>Option</c> for boolean values.</p>
- <p>The <c>ic:gen/2</c> function can be called from the command
- line as follows:</p>
- <p><c>erlc "+Option" ... File.idl</c></p>
- <p>Example:</p>
- <p><c>erlc "+{be,c_client}" '+{outdir, "../out"}' File.idl</c></p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>General options</title>
- <taglist>
- <tag><em>outdir</em></tag>
- <item>
- <p>Places all output files in the directory given by the option.
- The directory will be created if it does not already exist.</p>
- <p>Example option: <c>{outdir, "output/generated"}</c>.</p>
- </item>
- <tag><em>cfgfile</em></tag>
- <item>
- <p>Uses <em>FileName</em> as configuration file. Options will
- override compiler defaults but can be overridden by command line
- options. Default value is <c>".ic_config"</c>.</p>
- <p>Example option: <c>{cfgfile, "special.cfg"}</c>.</p>
- </item>
- <tag><em>use_preproc</em></tag>
- <item>
- <p>Uses a preprocessor. Default value is true.</p>
- </item>
- <tag><em>preproc_cmd</em></tag>
- <item>
- <p>Command string to invoke the preprocessor. The actual
- command will be built as
- <c>preproc_cmd++preproc_flags++FileName</c></p>
- <p>Example option: <c>{preproc_cmd, "erl"})</c>.</p>
- <p>Example option: <c>{preproc_cmd, "gcc -x c++ -E"}</c>.</p>
- </item>
- <tag><em>preproc_flags</em></tag>
- <item>
- <p>Flags given to the preprocessor.</p>
- <p>Example option: <c>{preproc_flags, "-I../include"}</c>.</p>
- </item>
- </taglist>
- </section>
-
- <section>
- <title>Code options</title>
- <taglist>
- <tag><em>light_ifr</em></tag>
- <item>
- <p>Currently, the default setting is <c>false</c>. To be able to
- use this option Orber must be configured to use Light IFR (see
- Orber's User's Guide). When this options is used, the size of the
- generated files used to register the API in the IFR DB are minimized.</p>
- <p>Example option: <c>{light_ifr, true}</c>.</p>
- </item>
- <tag><em>gen_hrl</em></tag>
- <item>
- <p>Generate header files. Default is true.</p>
- </item>
- <tag><em>serv_last_call</em></tag>
- <item>
- <p>Makes the last <c>gen_server handle_call</c> either raise a
- CORBA exception or just exit plainly. Default is the exception.
- </p>
- </item>
- <tag><em>{{impl, IntfName}, ModName}</em></tag>
- <item>
- <p>Assumes that the interface with name <em>IntfName</em> is
- implemented by the module with name <em>ModName</em> and
- will generate calls to the <em>ModName</em> module in the
- server behavior. Note that the <em>IntfName</em> must be a
- fully scoped name as in <c>"M1::I1"</c>.</p>
- <p></p>
- </item>
- <tag><em>this</em></tag>
- <item>
- <p>Adds the object reference as the first parameter to the
- object implementation functions. This makes the
- implementation aware of its own object reference.
- <br></br>
-The option
- comes in three varieties: <c>this</c> which activates the
- parameter for all interfaces in the source file, <c>{this, IntfName}</c> which activates the parameter for a specified
- interface and <c>{{this, IntfName}, false}</c> which
- deactivates the parameter for a specified
- interface.</p>
- <p>Example option: <c>this)</c> activates the parameter for
- all interfaces.</p>
- <p>Example option: <c>{this, "M1::I1"}</c> activates the
- parameter for all functions of <c>M1::I1</c>.</p>
- <p>Example options: <c>[this, {{this, "M1::I2"}, false}]</c>
- activates the parameter for all interfaces except
- <c>M1::I2</c>.</p>
- </item>
- <tag><em>from</em></tag>
- <item>
- <p>Adds the invokers reference as the first parameter to the
- object implementation two-way functions. If both
- <c>from</c> and <c>this</c> options are used the invokers
- reference parameter will be passed as the second
- parameter. This makes it possible for the implementation to
- respond to a request and continue executing
- afterwards. Consult the <c>gen_server</c> and <c>Orber</c>
- documentation how this option may be used. <br></br>
-The option
- comes in three varieties: <c>from</c> which activates the
- parameter for all interfaces in the source file, <c>{from, IntfName}</c> which activates the parameter for a specified
- interface and <c>{{from, IntfName}, false}</c> which
- deactivates the parameter for a specified interface.</p>
- <p>Example option: <c>from)</c> activates the parameter for
- all interfaces.</p>
- <p>Example options: <c>[{from, "M1::I1"}]</c> activates the
- parameter for all functions of <c>M1::I1</c>.</p>
- <p>Example options: <c>[from, {{from, "M1::I2"}, false}]</c>
- activates the parameter for all interfaces except
- <c>M1::I2</c>.</p>
- </item>
- <tag><em>handle_info</em></tag>
- <item>
- <p>Makes the object server call a function <c>handle_info</c>
- in the object implementation module on all unexpected
- messages. Useful if the object implementation need to trap
- exits.</p>
- <p>Example option: <c>handle_info</c> will activates module
- implementation <c>handle_info</c> for all interfaces in the
- source file.</p>
- <p>Example option: <c>{{handle_info, "M1::I1"}, true}</c>
- will activates module implementation <c>handle_info</c> for
- the specified interface.</p>
- <p>Example options: <c>[handle_info, {{handle_info, "M1::I1"}, false}]</c> will generate the <c>handle_info</c>
- call for all interfaces except <c>M1::I1</c>.</p>
- </item>
- <tag><em>timeout</em></tag>
- <item>
- <p>Used to allow a server response time limit to be set by the user.
- This should be a string that represents the scope for the interface
- which should have an extra variable for wait time initialization.</p>
- <p>Example option: <c>{timeout,"M::I"})</c> produces server
- stub which will has an extra timeout parameter in the initialization
- function for that interface.</p>
- <p>Example option: <c>timeout</c> produces server
- stub which will has an extra timeout parameter in the initialization
- function for all interfaces in the source file.</p>
- <p>Example options: <c>[timeout, {{timeout,"M::I"}, false}]</c>
- produces server stub which will has an extra timeout
- parameter in the initialization function for all interfaces
- except <c>M1::I1</c>.</p>
- </item>
- <tag><em>scoped_op_calls</em></tag>
- <item>
- <p>Used to produce more refined request calls to server. When
- this option is set to true, the operation name which was
- mentioned in the call is scoped. This is essential to avoid
- name clashes when communicating with c-servers. This option
- is available for the c-client, c-server and the Erlang
- gen_server back ends. <c>All</c> of the parts generated by ic
- have to agree in the use of this option. Default is
- <c>false</c>. </p>
- <p>Example options:
- <c>[{be,c_genserv},{scoped_op_calls,true}])</c> produces
- client stubs which sends "scoped" requests to a gen_server
- or a c-server.</p>
- </item>
- <tag><em>user_protocol</em></tag>
- <item>
- <p>Used to define a own protocol different from the default
- Erlang distribution + gen_server protocol. Currently only
- valid for C back-ends. For further details see <seealso marker="ic_c_protocol">IC C protocol</seealso>.</p>
- <p>Example options:
- <c>[{be,c_client},{user_protocol, "my_special"}])</c> produces
- client stubs which use C protocol functions with the prefix
- "my_special".</p>
- </item>
- <tag><em>c_timeout</em></tag>
- <item>
- <p>Makes sends and receives to have timeouts (C back-ends only). These
- timeouts are specified in milliseconds. </p>
- <p>Example options:
- <c>[{be,c_client},{c_timeout, {10000, 20000}}])</c> produces
- client stubs which use a 10 seconds send timeout, and a
- 20 seconds receive timeout.</p>
- </item>
- <tag><em>c_report</em></tag>
- <item>
- <p>Generates code for writing encode/decode errors to <c>stderr</c> (C back-ends only).
- timeouts are specified in milliseconds. </p>
- <p>Example options:
- <c>[{be,c_client}, c_report])</c>.</p>
- </item>
- <tag><em>scl</em></tag>
- <item>
- <p>Used for compatibility with previous compiler versions up
- to <c>3.3</c>. Due to better semantic checks on enumerants,
- the compiler discovers name clashes between user defined
- types and enumerant values in the same name space. By
- enabling this option the compiler turns off the extended
- semantic check on enumerant values. Default is
- <c>false</c>. </p>
- <p>Example option: <c>{scl,true}</c></p>
- </item>
- <tag><em>precond</em></tag>
- <item>
- <p>Adds a precondition call before the call to the operation
- implementation on the server side.</p>
- <p>The option comes in three varieties: <c>{precond, {M, F}}</c> which activates the call for operations in all
- interfaces in the source file, <c>{{precond, IntfName}, {M, F}}</c> which activates the call for all operations in a
- specific interface and <c>{{precond, OpName}, {M, F}}</c>
- which activates the call for a specific operation.</p>
- <p>The precondition function has the following signature
- <c>m:f(Module, Function, Args)</c>.</p>
- <p>Example option: <c>{precond, {mod, fun}}</c> adds the call
- of m:f for all operations in the idl file.</p>
- <p>Example options: <c>[{{precond, "M1::I"}, {mod, fun}}]</c>
- adds the call of <c>m:f</c> for all operations in the
- interface <c>M1::I1</c>.</p>
- <p>Example options: <c>[{{precond, "M1::I::Op"}, {mod, fun}}]</c> adds the call of <c>m:f</c> for the operation
- <c>M1::I::Op</c>.</p>
- </item>
- <tag><em>postcond</em></tag>
- <item>
- <p>Adds a postcondition call after the call to the operation
- implementation on the server side. </p>
- <p>The option comes in three varieties: <c>{postcond, {M, F}}</c> which activates the call for operations in all
- interfaces in the source file, <c>{{postcond, IntfName}, {M, F}}</c> which activates the call for all operations in a
- specific interface and <c>{{postcond, OpName}, {M, F}}</c>
- which activates the call for a specific operation.</p>
- <p>The postcondition function has the following signature
- <c>m:f(Module, Function, Args, Result)</c>.</p>
- <p>Example option: <c>{postcond, {mod, fun}}</c> adds the call
- of m:f for all operations in the idl file.</p>
- <p>Example options: <c>[{{postcond, "M1::I"}, {mod, fun}}]</c>
- adds the call of <c>m:f</c> for all operations in the
- interface <c>M1::I1</c>.</p>
- <p>Example options: <c>[{{postcond, "M1::I::Op"}, {mod, fun}}]</c> adds the call of <c>m:f</c> for the operation
- <c>M1::I::Op</c>.</p>
- </item>
- </taglist>
- </section>
-
- <section>
- <title>Warning options</title>
- <taglist>
- <tag><em>'Wall'</em></tag>
- <item>
- <p>The option activates all reasonable warning messages in
- analogy with the gcc -Wall option. Default value is true.</p>
- </item>
- <tag><em>maxerrs</em></tag>
- <item>
- <p>The maximum numbers of errors that can be detected before
- the compiler gives up. The option can either have an integer
- value or the atom <c>infinity</c>. Default number is 10.</p>
- </item>
- <tag><em>maxwarns</em></tag>
- <item>
- <p>The maximum numbers of warnings that can be detected before
- the compiler gives up. The option can either have an integer
- value or the atom <c>infinity</c>. Default value is
- infinity.</p>
- </item>
- <tag><em>nowarn</em></tag>
- <item>
- <p>Suppresses all warnings. Default value is false.</p>
- </item>
- <tag><em>warn_name_shadow</em></tag>
- <item>
- <p>Warning appears whenever names are shadowed due to
- inheritance; for example, if a type name is redefined from a
- base interface. Note that it is illegal to overload
- operation and attribute names as this causes an error to be
- produced. Default value is true. </p>
- </item>
- <tag><em>pedantic</em></tag>
- <item>
- <p>Activates all warning options. Default value is false.</p>
- </item>
- <tag><em>silent</em></tag>
- <item>
- <p>Suppresses compiler printed output. Default value is false.</p>
- </item>
- </taglist>
- </section>
-
- <section>
- <title>Back-End options</title>
- <p>Which back-end IC will generate code for is determined by the supplied
- <c>{be,atom()}</c> option. If left out, <c>erl_corba</c> is used.
- Currently, IC support the following back-ends:</p>
- <taglist>
- <tag><em>erl_corba</em></tag>
- <item>
- <p>This option switches to the IDL generation for CORBA.</p>
- </item>
- <tag><em>erl_template</em></tag>
- <item>
- <p>Generate CORBA call-back module templates for each interface in the target
- IDL file. Note, will overwrite existing files.</p>
- </item>
- <tag><em>erl_plain</em></tag>
- <item>
- <p>Will produce plain Erlang modules which contain functions that
- map to the corresponding interface functions on the input file.</p>
- </item>
- <tag><em>erl_genserv</em></tag>
- <item>
- <p>This is an IDL to Erlang generic server generation option.</p>
- </item>
- <tag><em>c_client</em></tag>
- <item>
- <p>Will produce a C client to the generic Erlang server.</p>
- </item>
- <tag><em>c_server</em></tag>
- <item>
- <p>Will produce a C server switch with functionality of a
- generic Erlang server.</p>
- </item>
- <tag><em>java</em></tag>
- <item>
- <p>Will produce Java client stubs and server skeletons with
- functionality of a generic Erlang server.</p>
- </item>
- <tag><em>c_genserv</em></tag>
- <item>
- <p>Deprecated. Use <c>c_client</c> instead.</p>
- </item>
- </taglist>
- </section>
-
- <section>
- <title>Preprocessor</title>
- <p>The IDL compiler allows several preprocessors to be used, the
- <c>Erlang IDL preprocessor</c> or other standard <c>C</c> preprocessors.
- Options can be used to provide extra flags such as include
- directories to the preprocessor. The build in the Erlang IDL
- preprocessor is used by default, but any standard C preprocessor
- such as <c>gcc</c> is adequate.</p>
- <p>The preprocessor command is formed by appending the prepoc_cmd
- to the preproc_flags option and then appending the input IDL
- file name.</p>
- </section>
-
- <section>
- <title>Configuration</title>
- <p>The compiler can be configured in two ways:</p>
- <list type="ordered">
- <item>
- <p>Configuration file</p>
- </item>
- <item>
- <p>Command line options</p>
- </item>
- </list>
- <p>The configuration file is optional and overrides the compiler
- defaults and is in turn overridden by the command line options.
- The configuration file shall contain options in the form of
- Erlang terms. The configuration file is read using
- <c>file:consult</c>.</p>
- <p>An example of a configuration file, note the "." after each
- line.</p>
- <code type="none">
-{outdir, gen_dir}.
-{{impl, "M1::M2::object"}, "obj"}.
- </code>
- </section>
-
- <section>
- <title>Output files</title>
- <p>The compiler will produce output in several files depending on
- scope declarations found in the IDL file. At most
- three file types will be generated for each scope (including the top scope),
- depending on the compiler back-end and the compiled interface.
- Generally, the output per interface will be a header file (<c>.hrl</c>/
- <c>.h</c>) and one or more Erlang/C files (<c>.erl</c>/<c>.c</c>).
- Please look at the language mapping for each back-end for details.</p>
- <p>There will be at least one set of files for an IDL file, for the
- file level scope. Modules and interfaces also have their own set
- of generated files.</p>
- </section>
-
-</erlref>
-
diff --git a/lib/ic/doc/src/ic_c_protocol.xml b/lib/ic/doc/src/ic_c_protocol.xml
deleted file mode 100644
index ed4f21d661..0000000000
--- a/lib/ic/doc/src/ic_c_protocol.xml
+++ /dev/null
@@ -1,157 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE cref SYSTEM "cref.dtd">
-
-<cref>
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>IC C Protocol Functions</title>
- <prepared></prepared>
- <docno></docno>
- <date>2004-04-06</date>
- <rev>A</rev>
- </header>
- <lib>ic_c_protocol</lib>
- <libsummary>IC C Protocol Functions</libsummary>
- <description>
- <p>This manual page lists some of the functions of the IC C runtime
- library that are used internally for the IC protocol.
- </p>
- <p>The listed functions are used internally by generated C client
- and server code. They are documented here for <em>the advanced user</em> that want to replace the default protocol (Erlang
- distribution + gen_server) by his own protocol, For each set of
- client or sever functions below with prefix <c>oe</c>, the user
- has to implement his own set of functions, the names of which
- are obtained by replacing the <c>oe</c> prefix by <c>Prefix</c>.
- The <c>Prefix</c> has to be set with the option
- <c>{user_protocol, Prefix}</c> at compile time.</p>
- <p>The following terminology is used (reflected in names of
- functions): a <em>notification</em> is a message send from
- client to server, without any reply back (i.e. a
- <em>oneway</em> operation); a <em>request</em> is a message sent
- from client to server, and where a <em>reply</em> message is
- sent back from the server to the client.</p>
- <p>In order to understand how the functions work and what they do
- the user <em>must</em> study their implementation in the IC C
- library (source file is <c>ic.c</c>), and also consider how they
- are used in the C code of ordinary generated client stubs or
- server skeletons.</p>
- <p></p>
- </description>
-
- <section>
- <title>Client Protocol Functions</title>
- <p>The following functions are used internally by generated C
- client code.</p>
- </section>
- <funcs>
- <func>
- <name><ret>int</ret><nametext>oe_prepare_notification_encoding(CORBA_Environment *env)</nametext></name>
- <fsummary>Prepare client notification encoding.</fsummary>
- <desc>
- <p>The result of this function is the beginning of a binary of
- in external format of the tuple <c>{'$gen_cast', X}</c> where
- <c>X</c> is not yet filled in. </p>
- <p>In generated client code this function is the first to be called
- in the encoding function for each oneway operation.</p>
- </desc>
- </func>
- <func>
- <name><ret>int</ret><nametext>oe_send_notification(CORBA_Environment *env)</nametext></name>
- <name><ret>int</ret><nametext>oe_send_notification_tmo(CORBA_Environment *env, unsigned int send_ms)</nametext></name>
- <fsummary>Send client notification.</fsummary>
- <desc>
- <p>Sends a client notification to a server according to the
- Erlang distribution + gen_server protocol.</p>
- <p>The <c>send_ms</c> parameter specified a timeout in milliseconds.</p>
- </desc>
- </func>
- <func>
- <name><ret>int</ret><nametext>oe_prepare_request_encoding(CORBA_Environment *env)</nametext></name>
- <fsummary>Prepare client request encoding.</fsummary>
- <desc>
- <p>The result of this function is the beginning of a binary in
- the external format of the tuple <c>{'$gen_call', {Pid, Ref}, X}</c> where <c>X</c> is not yet filled in.</p>
- <p>In generated client code this function is the first to be called
- in the encoding function for each twoway operation.</p>
- </desc>
- </func>
- <func>
- <name><ret>int</ret><nametext>oe_send_request_and_receive_reply(CORBA_Environment *env)</nametext></name>
- <name><ret>int</ret><nametext>oe_send_request_and_receive_reply_tmo(CORBA_Environment *env, unsigned int send_ms, unsigned int recv_ms)</nametext></name>
- <fsummary>Send client request and receive reply.</fsummary>
- <desc>
- <p>Sends a client request and receives the reply according to
- the Erlang distribution + gen_server protocol. This function
- calls the <c>oe_prepare_reply_decoding</c> function in order
- to obtain the gen_server reply.
- </p>
- <p><c>send_ms</c> and <c>recv_ms</c> specify timeouts for send
- and receive, respectively, in milliseconds.</p>
- </desc>
- </func>
- <func>
- <name><ret>int</ret><nametext>oe_prepare_reply_decoding(CORBA_Environment *env)</nametext></name>
- <fsummary>Prepare client decoding of reply.</fsummary>
- <desc>
- <p>Decodes the binary version of the tuple <c>{Ref, X}</c>,
- where <c>X</c> is to be decoded later by the specific client
- decoding function.</p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>Server Protocol Functions</title>
- <p>The following functions are used internally by generated C
- server code.</p>
- </section>
- <funcs>
- <func>
- <name><ret>int</ret><nametext>oe_prepare_request_decoding(CORBA_Environment *env)</nametext></name>
- <fsummary>Prepare server decoding of request.</fsummary>
- <desc>
- <p>Decodes the binary version of the tuple <c>{'$gen_cast', Op}</c> (<c>Op</c> an atom), or the tuple <c>{'$gen_cast', {Op, X}}</c>, where <c>Op</c> is the operation name, and
- where <c>X</c> is to be decoded later by the specific
- operation decoding function; or</p>
- <p>decodes the binary version of the tuple <c>{'$gen_call', {Pid, Ref}, Op}</c> (<c>Op</c> an atom), or the tuple
- <c>{'$gen_call', {Pid, Ref}, {Op, X}}</c>, where <c>Op></c>
- is the operation name, and <c>X</c> is to be decode later by
- the specific operation decoding function.</p>
- </desc>
- </func>
- <func>
- <name><ret>int</ret><nametext>oe_prepare_reply_encoding(CORBA_Environment *env)</nametext></name>
- <fsummary>Prepare server encoding of reply.</fsummary>
- <desc>
- <p>Encodes the beginning of the binary version of the tuple
- <c>{{Ref,X}</c>, where <c>X</c> is to be filled in by the
- specific server encoding function.</p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>SEE ALSO</title>
- <p>ic(3), ic_clib(3), <seealso marker="ch_ic_protocol">IC Protocol</seealso></p>
- </section>
-
-</cref>
-
diff --git a/lib/ic/doc/src/ic_clib.xml b/lib/ic/doc/src/ic_clib.xml
deleted file mode 100644
index 50b20d2ca8..0000000000
--- a/lib/ic/doc/src/ic_clib.xml
+++ /dev/null
@@ -1,247 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE cref SYSTEM "cref.dtd">
-
-<cref>
- <header>
- <copyright>
- <year>2003</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>IC C Library Functions</title>
- <prepared></prepared>
- <docno></docno>
- <date>2003-12-16</date>
- <rev>PB1</rev>
- </header>
- <lib>ic_clib</lib>
- <libsummary>IC C Library Functions</libsummary>
- <description>
- <p>This manual page lists some of the functions in the IC C runtime
- library. </p>
- </description>
-
- <section>
- <title>Allocation and Deallocation Functions</title>
- <p>The following functions are used for allocating and
- deallocating a <em>CORBA_Environment</em> structure.</p>
- </section>
- <funcs>
- <func>
- <name><ret>CORBA_Environment *</ret><nametext>CORBA_Environment_alloc(int inbufsz, int outbufsz)</nametext></name>
- <fsummary>Allocate environment data.</fsummary>
- <desc>
- <p>This function is used to allocate and initiate the
- <c>CORBA_Environment</c> structure. In particular, it is used
- to dynamically allocate a CORBA_Environment structure and set
- the default values for the structure's fields.</p>
- <p><em>inbufsize</em> is the initial size of the input
- buffer.</p>
- <p><em>outbufsize</em> is the initial size of the output
- buffer.</p>
- <p><em>CORBA_Environment</em> is the CORBA 2.0 state structure
- used by the generated stub.</p>
- <p>This function will set all needed default values and
- allocate buffers the lengths of which are equal to the
- values passed, but will not allocate space for the _to_pid
- and _from_pid fields.</p>
- <p>To free the space allocated by CORBA_Environment_alloc() do
- as follows.</p>
- <list type="bulleted">
- <item>
- <p>First call CORBA_free for the input and output buffers.</p>
- </item>
- <item>
- <p>After freeing the buffer space, call CORBA_free for the
- CORBA_Environment space.</p>
- </item>
- </list>
- </desc>
- </func>
- <func>
- <name><ret>void</ret><nametext>CORBA_free(void *p)</nametext></name>
- <fsummary>Free any allocated data.</fsummary>
- <desc>
- <p>Frees allocated space pointed to by <c>p</c>.</p>
- </desc>
- </func>
- <func>
- <name><ret>CORBA_char *</ret><nametext>CORBA_string_alloc(CORBA_unsigned_long len)</nametext></name>
- <fsummary>Allocate a string.</fsummary>
- <desc>
- <p>Allocates a (simple) CORBA character string of length <c>len + 1</c>.</p>
- </desc>
- </func>
- <func>
- <name><ret>CORBA_wchar *</ret><nametext>CORBA_wstring_alloc(CORBA_unsigned_long len)</nametext></name>
- <fsummary>Allocate a wide string.</fsummary>
- <desc>
- <p>Allocates a CORBA wide string of length <c>len + 1</c>.</p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>Exception Functions</title>
- <p>Functions for retrieving exception ids and values, and for setting
- exceptions. </p>
- </section>
- <funcs>
- <func>
- <name><ret>CORBA_char *</ret><nametext>CORBA_exception_id(CORBA_Environment *env)</nametext></name>
- <fsummary>Get exception identity.</fsummary>
- <desc>
- <p>Returns the exception identity if an exception is set, otherwise
- it returns <c>NULL</c>.</p>
- </desc>
- </func>
- <func>
- <name><ret>void *</ret><nametext>CORBA_exception_value(CORBA_Environment *env)</nametext></name>
- <fsummary>Get exception value.</fsummary>
- <desc>
- <p>Returns the exception value, if an exception is set, otherwise
- it returns <c>NULL</c>.</p>
- </desc>
- </func>
- <func>
- <name><ret>void</ret><nametext>CORBA_exc_set(CORBA_Environment *env, CORBA_exception_type Major, CORBA_char *Id, CORBA_char *Value)</nametext></name>
- <fsummary>Set exception.</fsummary>
- <desc>
- <p>Sets the exception type, exception identity, and exception value
- in the environment pointed to by <c>env</c>.</p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>Server Reception</title>
- <p>The following function is provided for convenience. </p>
- </section>
- <funcs>
- <func>
- <name><ret>int</ret><nametext>oe_server_receive(CORBA_Environment *env, oe_map_t *map)</nametext></name>
- <name><ret>int</ret><nametext>oe_server_receive_tmo(CORBA_Environment *env, oe_map_t *map, unsigned int send_ms, unsigned int recv_ms)</nametext></name>
- <fsummary>Server receive of notification or request, and sending of reply (in case of request).</fsummary>
- <desc>
- <p>Provides a loop that receives one message, executes the
- operation in question, and in case of a two-way operation
- sends a reply.</p>
- <p><c>send_ms</c> and <c>recv_ms</c> specify timeout values
- in milliseconds for send and receive, respectively.</p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>Generic Execution Switch and Map Merging</title>
- <p>Function for searching for server operation function, and for
- calling it if found. Function for merging maps (see the include
- file <c>ic.h</c> for definitions). </p>
- </section>
- <funcs>
- <func>
- <name><ret>int</ret><nametext>oe_exec_switch(CORBA_Object obj, CORBA_Environment *env, oe_map_t *map)</nametext></name>
- <fsummary>Search for server operation and execute it.</fsummary>
- <desc>
- <p>Search for server operation and execute it.</p>
- </desc>
- </func>
- <func>
- <name><ret>oe_map_t *</ret><nametext>oe_merge_maps(oe_map_t *maps, int size)</nametext></name>
- <fsummary>Merge an array of server maps to one single map.</fsummary>
- <desc>
- <p>Merge an array of server maps to one single map.</p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>The CORBA_Environment structure</title>
- <p>Here is the complete definition of the CORBA_Environment structure,
- defined in file <em>ic.h</em>: </p>
- <code type="none">
- /* Environment definition */
- typedef struct {
-
- /*----- CORBA compatibility part ------------------------*/
- /* Exception tag, initially set to CORBA_NO_EXCEPTION ---*/
- CORBA_exception_type _major;
-
- /*----- External Implementation part - initiated by the user ---*/
- /* File descriptor */
- int _fd;
- /* Size of input buffer */
- int _inbufsz;
- /* Pointer to always dynamically allocated buffer for input */
- char *_inbuf;
- /* Size of output buffer */
- int _outbufsz;
- /* Pointer to always dynamically allocated buffer for output */
- char *_outbuf;
- /* Size of memory chunks in bytes, used for increasing the output
- buffer, set to >= 32, should be around >= 1024 for performance
- reasons */
- int _memchunk;
- /* Pointer for registered name */
- char _regname[256];
- /* Process identity for caller */
- erlang_pid *_to_pid;
- /* Process identity for callee */
- erlang_pid *_from_pid;
-
- /*- Internal Implementation part - used by the server/client ---*/
- /* Index for input buffer */
- int _iin;
- /* Index for output buffer */
- int _iout;
- /* Pointer for operation name */
- char _operation[256];
- /* Used to count parameters */
- int _received;
- /* Used to identify the caller */
- erlang_pid _caller;
- /* Used to identify the call */
- erlang_ref _unique;
- /* Exception id field */
- CORBA_char *_exc_id;
- /* Exception value field */
- void *_exc_value;
-
-
- } CORBA_Environment;
- </code>
- <note>
- <p>Always set the field values <em>_fd</em>, <em>_regname</em>,
- <em>_to_pid</em> and/or <em>*_from_pid</em> to appropriate
- application values. These are not automatically set by the
- stubs.</p>
- </note>
- <warning>
- <p>Never assign static buffers to the buffer pointers, and never
- set the <em>_memchunk</em> field to a value less than
- <em>32</em>.</p>
- </warning>
- </section>
-
- <section>
- <title>SEE ALSO</title>
- <p>ic(3), ic_c_protocol(3)
- </p>
- </section>
-
-</cref>
-
diff --git a/lib/ic/doc/src/java-part.xml b/lib/ic/doc/src/java-part.xml
deleted file mode 100644
index 14b58a1df5..0000000000
--- a/lib/ic/doc/src/java-part.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2002</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>IDL to Java language Mapping</title>
- <prepared></prepared>
- <docno></docno>
- <date>2002-06-25</date>
- <rev>A</rev>
- </header>
- <description>
- <p></p>
- </description>
- <include file="ch_java"></include>
-</part>
-
diff --git a/lib/ic/doc/src/notes.gif b/lib/ic/doc/src/notes.gif
deleted file mode 100644
index e000cca26a..0000000000
--- a/lib/ic/doc/src/notes.gif
+++ /dev/null
Binary files differ
diff --git a/lib/ic/doc/src/notes.xml b/lib/ic/doc/src/notes.xml
deleted file mode 100644
index ea8bf758cf..0000000000
--- a/lib/ic/doc/src/notes.xml
+++ /dev/null
@@ -1,776 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1998</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>IDL Compiler Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>2004-04-06</date>
- <rev>AC</rev>
- <file>notes.xml</file>
- </header>
-
- <section><title>IC 4.4.2</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p> Correct bugs when path to mib or idl spec files
- contains UTF-8 characters. </p>
- <p>
- Own Id: OTP-13718 Aux Id: ERL-179 </p>
- </item>
- <item>
- <p>
- Update build scripts to not make assumtions about where
- env, cp and perl are located.</p>
- <p>
- Own Id: OTP-13800</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>IC 4.4.1</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Internal changes</p>
- <p>
- Own Id: OTP-13551</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>IC 4.4</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Change license text from Erlang Public License to Apache
- Public License v2</p>
- <p>
- Own Id: OTP-12845</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>IC 4.3.6</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Fix compiler warnings reported by LLVM</p>
- <p>
- Own Id: OTP-12138</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>IC 4.3.5</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p> Added Latin-1 code directive in the generated files
- to keep old behaviour. Updated IC so it can handle
- Unicode characters in the path. </p>
- <p>
- Own Id: OTP-11783</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>IC 4.3.4</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Fix two small silent rules omissions. Thanks to Anthony
- Ramine.</p>
- <p>
- Own Id: OTP-11351</p>
- </item>
- <item>
- <p>
- Silence warnings (Thanks to Anthony Ramine)</p>
- <p>
- Own Id: OTP-11517</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>IC 4.3.3</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Header and library files from ic and erl_interface are
- now installed into usr/{include,lib}. Note that these
- directories are unversioned, so the latest installed
- version will be the one in the directory.</p>
- <p>
- Own Id: OTP-11284</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>IC 4.3.2</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Fixed some compilation warnings on miscellaneous
- platforms. Thanks to Anthony Ramine.</p>
- <p>
- Own Id: OTP-11086</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>IC 4.3.1</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Revert the structs <c>erlang_pid</c>, <c>erlang_port</c>
- and <c>erlang_ref</c> as they were before R16A (without
- <c>node_org_enc</c>) in order to be backward compatible
- with user code that accesses the fields of these structs.</p>
- <p>
- Own Id: OTP-10885 Aux Id: seq12256 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>IC 4.3</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Misc build updates</p>
- <p>
- Own Id: OTP-10784</p>
- </item>
- <item>
- <p>
- Adapt ic for changes in erl_interface and jinterface due
- to utf8 atom support. This change makes ic dependent on
- erl_interface-3.7.10 (R16) or later in order to build.</p>
- <p>
- Own Id: OTP-10785</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>IC 4.2.31</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Fix bug where the ic pre-processor would ignore
- whitespace quoting.</p>
- <p>
- Own Id: OTP-10109</p>
- </item>
- <item>
- <p> A bug regarding spaces in C function prototypes has
- been fixed. (Thanks to Richard O'Keefe.) </p>
- <p>
- Own Id: OTP-10138</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>IC 4.2.30</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Add generation of Erlang callback functions to generated
- Erlang source code to avoid compiler warnings.</p>
- <p>
- Own Id: OTP-9998</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>IC 4.2.29</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>Erlang/OTP can now be built using parallel make if you
- limit the number of jobs, for instance using '<c>make
- -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
- work at the moment because of some missing
- dependencies.</p>
- <p>
- Own Id: OTP-9451</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section>
- <title>IC 4.2.28</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>
- Incorrect use of ets:match changed to ets:match_object.</p>
- <p>
- Own Id: OTP-9630 </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.27</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Reduced compile overhead (Thanks to Haitao Li).</p>
- <p>
- Own Id: OTP-9460 </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.26</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Partial support for recursive structs and unions. Only available
- for the erl_corba backend and requires that Light IFR is used.
- I.e. the IC option {light_ifr, true} and that Orber is configured
- in such a way that Light IFR is activated. Recursive TypeCode is
- currently not supported.</p>
- <p>
- Own Id: OTP-8868 Aux Id: seq11633</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.25</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- The documentation can now be built and installed without Java.</p>
- <p>
- Own Id: OTP-8639 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.24</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>Removed superfluous VT in the documentation.</p>
- <p>Own id: OTP-8353 Aux Id:</p>
- </item>
- <item>
- <p>The option c_timeout was not correctly documented.</p>
- <p>Own id: OTP-8307 Aux Id: seq11390</p>
- </item>
- <item>
- <p>Removed superfluous backslash in the documentation.</p>
- <p>Own id: OTP-8354 Aux Id:</p>
- </item>
- <item>
- <p>The documentation EIX file was not generated.</p>
- <p>Own id: OTP-8355 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.23</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- The documentation is now built with open source tools (xsltproc and fop)
- that exists on most platforms. One visible change is that the frames are removed.</p>
- <p>
- Own Id: OTP-8201 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.22</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The 64-bit version of libic was not compiled with the -fPIC flag.</p>
- <p>Own id: OTP-8088</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.21</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The function print_erlang_binary (oe_ei_code_erlang_binary.c)
- updated to avoid compiler warning.</p>
- <p>Own id: OTP-7982</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.20</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Updated file headers.</p>
- <p>Own id: OTP-7837</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.19</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Documentation source included in open source releases.</p>
- <p>Own id: OTP-7595</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.18</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>Insufficient buffer allocated when passing wide strings
- using the C backend on a 64-bit architecture.</p>
- <p>Own Id: OTP-7313 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.17</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Updated file headers.</p>
- <p>Own id: OTP-7011</p>
- </item>
- <item>
- <p>IC no longer use the obsolete function file:rawopen/2.</p>
- <p>Own id: OTP-7182</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.16</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Added links to classes inherited from Jinterface in the
- User's Guide.</p>
- <p>Own Id: OTP-6965 Aux Id: </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.15</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>If an inherited function name begun with a capital letter
- the generated stub/skeleton oe_tc/1 function was incorrect.</p>
- <p>Own Id: OTP-6855 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.14</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The documentation source has been converted from SGML to XML.</p>
- <p>Own Id: OTP-6754 Aux Id: </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.13</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Minor Makefile changes.</p>
- <p>Own Id: OTP-6701 Aux Id: </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.12</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Dead code was deleted from the following modules:
- ic_cclient, ic_code, ic_cserver, ic_erlbe, ic_java_type,
- ic_noc, ic_plainbe, ic_pp, ic_pragma, icscan, icstruct,
- ictype, icunion.</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.11</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Changed code generation to avoid warnings such as unused
- variables.</p>
- <p>Own Id: OTP-5930 Aux Id: </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.10</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The FD_SETSIZE limit has been increased to 2048 for
- VxWorks/PPC603.</p>
- <p>Own Id: OTP-5395 Aux Id: seq9751</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.9</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>In C back-ends, the compiler crashed when generating C code
- for error reports when a scoped name was used as a type
- in a union.</p>
- <p>Own Id: OTP-5375 Aux Id: seq9740 </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.8</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>In C back-ends, when decoding a sequence of "small"
- integers, which from Erlang is sent as a string (i.e.
- each element between 0 and 255), each string element was
- considered to be of signed character type. Each such
- element is now correctly treated as an unsigned character
- type.</p>
- <p>Own Id: OTP-5205 Aux Id: seq9241 </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.7</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>A new compiler option <c>c_report</c> has been introduced
- for C back-ends (client and server). If that option is
- set, encoding/decoding errors will be reported to
- <c>stderr</c>.</p>
- <p>Own Id: OTP-4977</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.6</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The size of modules, used then registering data in the
- IFR DB (e.g., oe_MyModule:oe_register()), can be minimized
- if the compile option light_ifr is used and Orber is
- configured to use Light IFR. Requires that orber-3.5.1, or
- later, is used.</p>
- <p>Own Id: OTP-5036</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Incompatibilities</title>
- <list type="bulleted">
- <item>
- <p>The compile option <c>multiple_be</c> is no longer supported.</p>
- <p>Own Id: OTP-5049</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.5</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Send and receive functions with timeouts have been added
- to the C back-ends for the standard protocol (i.e. Erlang
- distribution + gen_server protocol).</p>
- <p>Accordingly a new compiler option <c>{c_timeout, {SendTimeout, RecvTimeout}}</c> has been added. Timeouts
- are specified in milliseconds.</p>
- <p>A user that want to implement its own protocols with
- function timeouts has to implement the following functions.</p>
- <p>For C clients the functions <c>int PFX_send_notification(CORBA_Environment *env, unsigned int send_ms)</c>, and <c>int PFX_send_request_and_receive_reply(CORBA_Environment *env, unsigned int send_ms, unsigned int recv_ms)</c>
- have to be additionally implemented, where PFX is the
- user defined prefix.</p>
- <p>For C servers no additional functions have to be
- implemented, but a clone of the <c>int oe_server_receive_tmo(CORBA_Environment *env, oe_map_t *map, unsigned int send_ms, unsigned int recv_ms)</c>
- might be handy.</p>
- <p>Own Id: OTP-4972</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.4</title>
-
- <section>
- <title>Improvements and new features</title>
- <list type="bulleted">
- <item>
- <p>The C back-ends has been opened up, so that a user can
- define his own protocol, differing from the Erlang
- distribution + gen_server protocol. <br></br>
-
- For C clients it means to replace the library functions
- <c>int oe_prepare_notification_encoding(CORBA_Environment *env)</c>, <c>int oe_send_notification(CORBA_Environment *env)</c>, <c>int oe_prepare_request_encoding(CORBA_Environment *env)</c>,
- <c>int oe_send_request_and_receive_reply(CORBA_Environment *env)</c>, and <c>int oe_prepare_reply_decoding(CORBA_Environment *env)</c>,
- with functions of the same signature, but with the prefix
- "oe" replaced by a user defined prefix.
- For C servers the functions <c>int oe_prepare_request_decoding(CORBA_Environment *env)</c>,
- and <c>int oe_prepare_reply_encoding(CORBA_Environment *env)</c>, are similarly replaced. <br></br>
-
- The new compiler option <c>{user_protocol, Prefix}</c> has
- been added.</p>
- <p>Own Id: OTP-4834</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.3</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>In generated code for the C server back-end, the naming scope
- was in error for prototypes in C header files for interfaces
- inheriting base interfaces.</p>
- <p>Own Id: OTP-4881</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.2</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>IDL long long and unsigned long long could not
- be used in a struct for the Java backend.</p>
- <p>All unsigned integer types for the Java backend
- had broken marshalling for large values.</p>
- <p>Own Id: OTP-4763</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2.1</title>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>A scoping problem (IC could not find typedefs contained
- inherited interfaces) in the C-backend solved.</p>
- <p>Own Id: OTP-4758</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>IC 4.2</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The CORBA stub/skeleton-files generated by IC have been improved,
- i.e., depending on the IDL-files, reduced the size of the
- erl- and beam-files and decreased dependencies off Orber's
- Interface Repository. It is necessary to re-compile all IDL-files
- and use COS-applications, including Orber, compiled with
- IC-4.2.</p>
- <p>Own Id: OTP-4576</p>
- </item>
- </list>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/ic/doc/src/part.xml b/lib/ic/doc/src/part.xml
deleted file mode 100644
index 0bb7858745..0000000000
--- a/lib/ic/doc/src/part.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>1998</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>IC User's Guide</title>
- <prepared></prepared>
- <docno></docno>
- <date>1998-08-07</date>
- <rev>2.1</rev>
- </header>
- <description>
- <p>The <em>IC</em> application is an Erlang implementation of an IDL
- compiler.</p>
- </description>
- <xi:include href="ch_introduction.xml"/>
- <xi:include href="ch_basic_idl.xml"/>
- <xi:include href="ch_ic_protocol.xml"/>
- <xi:include href="ch_erl_plain.xml"/>
- <xi:include href="ch_erl_genserv.xml"/>
- <xi:include href="ch_c_mapping.xml"/>
- <xi:include href="ch_c_client.xml"/>
- <xi:include href="ch_c_server.xml"/>
- <xi:include href="ch_c_corba_env.xml"/>
- <xi:include href="ch_java.xml"/>
-</part>
-
diff --git a/lib/ic/doc/src/part_notes.xml b/lib/ic/doc/src/part_notes.xml
deleted file mode 100644
index 305b2c558d..0000000000
--- a/lib/ic/doc/src/part_notes.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>1998</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Idl Compiler Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date>1998-05-06</date>
- <rev>2.1</rev>
- </header>
- <description>
- <p>The IDL
- Compiler Application is an Erlang implementation of a compiler for the IDL language.
- </p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/ic/doc/src/ref_man.gif b/lib/ic/doc/src/ref_man.gif
deleted file mode 100644
index b13c4efd53..0000000000
--- a/lib/ic/doc/src/ref_man.gif
+++ /dev/null
Binary files differ
diff --git a/lib/ic/doc/src/ref_man.xml b/lib/ic/doc/src/ref_man.xml
deleted file mode 100644
index a6a4f187b3..0000000000
--- a/lib/ic/doc/src/ref_man.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE application SYSTEM "application.dtd">
-
-<application xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>1998</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>IC Reference Manual</title>
- <prepared></prepared>
- <docno></docno>
- <date>2003-12-16</date>
- <rev>PB1</rev>
- </header>
- <description>
- <p>The <em>IC</em> application is an Erlang implementation of an IDL
- compiler.</p>
- </description>
- <xi:include href="ic.xml"/>
- <xi:include href="ic_clib.xml"/>
- <xi:include href="ic_c_protocol.xml"/>
-</application>
-
diff --git a/lib/ic/doc/src/summary.html.src b/lib/ic/doc/src/summary.html.src
deleted file mode 100644
index cb92e51791..0000000000
--- a/lib/ic/doc/src/summary.html.src
+++ /dev/null
@@ -1 +0,0 @@
-IDL compiler
diff --git a/lib/ic/doc/src/user_guide.gif b/lib/ic/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/ic/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/ic/ebin/.gitignore b/lib/ic/ebin/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ic/ebin/.gitignore
+++ /dev/null
diff --git a/lib/ic/examples/all-against-all/Makefile b/lib/ic/examples/all-against-all/Makefile
deleted file mode 100644
index e772cab94e..0000000000
--- a/lib/ic/examples/all-against-all/Makefile
+++ /dev/null
@@ -1,118 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-# Point this at your version of OTP
-OTPROOT=/usr/local/otp/releases/otp_beam_sunos5_r7a
-
-# Type actual IC Version
-ICVSN=4.0.4
-
-# Type actual Erl Interface Vesrion
-EIVSN=3.2.2
-
-# Type actual Erl Interface Vesrion
-JIVSN=1.2
-
-# IDL file(s)
-IDLS=random.idl
-
-# Own C-server files
-CSRV=server callbacks
-
-# Own C-client files
-CCL=client
-
-# Generated C-server files
-GCSRVS=rmod_random__s
-
-# Generated C-server files
-GCCLS=rmod_random
-
-# Includes
-IFLAGS=-I$(OTPROOT)/lib/ic-$(ICVSN)/include \
- -I$(OTPROOT)/lib/erl_interface-$(EIVSN)/include
-
-LDFLAGS=-L$(OTPROOT)/lib/ic-$(ICVSN)/priv/lib \
- -L$(OTPROOT)/lib/erl_interface-$(EIVSN)/lib
-
-LDLIBS=-lic -lerl_interface -lei -lnsl -lsocket
-
-
-# Erlang compiler
-ERLC=$(OTPROOT)/bin/erlc
-
-# Erlang compiler flags.
-EFLAGS='+{scoped_op_calls,true}'
-
-# C compiler
-CC=gcc
-
-# C compiler flags
-CFLAGS=-ggdb -O2 -Wall $(IFLAGS)
-
-# Java compiler
-JAVAC=javac
-
-CLASSPATH= "./:$(OTPROOT)/lib/ic-$(ICVSN)/priv/ic.jar:$(OTPROOT)/lib/jinterface-$(JIVSN)/priv/OtpErlang.jar"
-JFLAGS=-classpath $(CLASSPATH) -O
-
-JGENJFILES = \
- ./rmod/_randomImplBase.java \
- ./rmod/random.java \
- ./rmod/randomHolder.java \
- ./rmod/_randomStub.java \
- ./rmod/randomHelper.java
-
-
-all: server client eall jall
-
-
-server:
- $(ERLC) $(EFLAGS) '+{be,c_server}' $(IDLS)
- $(CC) $(IFLAGS) -c $(CSRV:=.c) $(GCSRVS:=.c)
- $(CC) $(CSRV:=.o) $(GCSRVS:=.o) -o $@ $(LDFLAGS) $(LDLIBS)
-
-client:
- $(ERLC) $(EFLAGS) '+{be,c_client}' $(IDLS)
- $(CC) $(IFLAGS) -c $(CCL:=.c) $(GCCLS:=.c)
- $(CC) $(CCL:=.o) $(GCCLS:=.o) -o $@ $(LDFLAGS) $(LDLIBS)
-
-eall:
- $(ERLC) $(EFLAGS) '+{be,erl_genserv}' $(IDLS)
- $(ERLC) *.erl
-
-jall:
- $(ERLC) $(EFLAGS) '+{be,java}' $(IDLS)
- $(JAVAC) $(JFLAGS) */*.java *.java
-
-
-clean:
- /bin/rm -rf $(GCCLS:=.o) $(GCCLS:=.c) $(GCSRVS:=.o) $(GCSRVS:=.c) $(CCL:=.o) $(CSRV:=.o) rmod.erl rmod_random.erl *.jam *.beam oe* *.h *.hrl *~ core server client *.class
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/examples/all-against-all/Makefile.win32 b/lib/ic/examples/all-against-all/Makefile.win32
deleted file mode 100644
index a8e480fd1f..0000000000
--- a/lib/ic/examples/all-against-all/Makefile.win32
+++ /dev/null
@@ -1,139 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-# Point this at your version of OTP
-OTPROOT=c:\Progra~1\erl5.0.1\
-
-# Type actual IC Version
-ICVSN=4.0.4
-
-# Type actual Erl Interface Vesrion
-EIVSN=3.2.2
-
-# Type actual Erl Interface Vesrion
-JIVSN=1.2
-
-# IDL file(s)
-IDLS=random.idl
-
-# Own C-server files
-CSRV=server.c callbacks.c
-CSRVO=server.obj callbacks.obj
-
-# Own C-client files
-CCL=client.c
-CCLO=client.obj
-
-# Generated C-server files
-GCSRVS=rmod_random__s.c
-GCSRVSO=rmod_random__s.obj
-
-# Generated C-client files
-GCCLS=rmod_random.c
-GCCLSO=rmod_random.obj
-
-# Includes
-IFLAGS=-I"$(OTPROOT)\lib\ic-$(ICVSN)\include" \
- -I"$(OTPROOT)\lib\erl_interface-$(EIVSN)\include"
-
-LDFLAGS=/LIBPATH:"$(OTPROOT)\lib\ic-$(ICVSN)\priv\lib" \
- /LIBPATH:"$(OTPROOT)\lib\erl_interface-$(EIVSN)\lib"
-
-LDLIBS=ic.lib erl_interface.lib ei.lib ws2_32.lib
-
-
-# Erlang compiler
-ERLC=$(OTPROOT)\bin\erlc
-
-# Erlang compiler flags.
-EFLAGS="+{scoped_op_calls,true}"
-
-
-# C compiler
-CC=cl
-
-# C compiler flags
-CFLAGS=-MT -D__WIN32__ $(IFLAGS)
-
-
-# Java compiler
-JAVAC=c:\Progra~1\jdk1.3\bin\javac
-
-# Java
-JAVA=c:\Progra~1\jdk1.3\bin\java
-
-
-# Java compiler flags
-CLASSPATH= ".;$(OTPROOT)\lib\ic-$(ICVSN)\priv\ic.jar;$(OTPROOT)\lib\jinterface-$(JIVSN)\priv\OtpErlang.jar"
-JFLAGS=-classpath $(CLASSPATH) -O
-
-
-all: server.exe client.exe client.beam client.class
-
-
-server.exe:
- $(ERLC) $(EFLAGS) "+{be,c_server}" $(IDLS)
- $(CC) -c $(CFLAGS) $(CSRV) $(GCSRVS)
- $(CC) -o server.exe $(CSRVO) $(GCSRVSO) -link $(LDFLAGS) $(LDLIBS)
-
-
-client.exe:
- $(ERLC) $(EFLAGS) "+{be,c_client}" $(IDLS)
- $(CC) -c $(CFLAGS) $(CCL) $(GCCLS)
- $(CC) -o client.exe $(CCLO) $(GCCLSO) -link $(LDFLAGS) $(LDLIBS)
-
-client.beam:
- $(ERLC) $(EFLAGS) "+{be,erl_genserv}" $(IDLS)
- $(ERLC) *.erl
-
-client.class:
- $(ERLC) $(EFLAGS) "+{be,java}" $(IDLS)
- $(JAVAC) $(JFLAGS) rmod/*.java
- $(JAVAC) $(JFLAGS) *.java
-
-jclient.run:
- $(JAVA) -classpath $(CLASSPATH) client
-
-jserver.run:
- $(JAVA) -classpath $(CLASSPATH) server
-
-
-clean:
- -@del /f /q rmod
- -@rmdir rmod
- -@del *.jam
- -@del *.beam
- -@del oe*
- -@del *.h
- -@del *.hrl
- -@del server.exe
- -@del client.exe
- -@del *.obj
- -@del rmod_random*.c
- -@del *~
- -@del *class
- -@del rmod.erl
- -@del rmod_random.erl
-
-
-
-
-
-
diff --git a/lib/ic/examples/all-against-all/ReadMe b/lib/ic/examples/all-against-all/ReadMe
deleted file mode 100644
index 7503291344..0000000000
--- a/lib/ic/examples/all-against-all/ReadMe
+++ /dev/null
@@ -1,122 +0,0 @@
-This is a short description on the use of Erlang,C or Java
-client and servers against each other.
-The base is a client that initiates and uses a random number
-generator that lies on an server.
-
-There are two make files, one for Unix and one for Windows,
-the Unix make file is just named "Makefile", while the Windows
-is named "Makefile.win32".
-
-Instructions.
-
-1) On Makefile :
- * Modify the OTPROOT variable on the Makefile to point
- to the root for your erlang instalation.
- * Modify IC and Erl_Interface versions to agree your
- OTP version.
-
-2) Type "make" to build the example.
-
-
-3) Start the empd deamon by using the command :
-
- epmd -daemon
-
-
-4) Do this when you want to run :
-
- * an Erlang server.
-
- Start erlang with the options
-
- -setcookie <Some Cookie> -sname <SomeNodeName>
-
- In this example you should use :
-
- erl -setcookie flash -sname babbis
-
- * a C server.
-
- Just type :
-
- server
-
- * a Java server.
-
- Set and export the CLASSPATH variable to
- point to the java classes located in java development kit,
- the Otp's classes and the current directory.
- Your classpath should look like this :
-
- .:<OTPROOT>/lib/ic-3.8.1/priv/ic.jar:<OTPROOT>/lib/jinterface_0.9.2/priv/OtpErlang.jar
-
- where :
-
- <OTPROOT> is the location there OTP is installed
-
- Then type :
-
- java server
-
-
-5) Do this when you want to run :
-
- * an Erlang client.
-
- ** If you have no valid named erlang node,
- start erlang with the options
-
- -setcookie <Some Cookie> -sname <SomeNodeName>
-
- In this example you should use :
-
- erl -setcookie flash -sname client
-
- On the erlang shell, type
-
- client:start().
-
- ** If you have a valid named erlang node, started
- whith the same "cookie", on the erlang shell, type
-
- client:start().
-
-
- * a C client, just type
-
- client
-
-
- * a Java client.
-
-
- Set and export the CLASSPATH variable to
- point to the java classes located in java development kit,
- the Otp's classes and the current directory.
- Your classpath should look like this :
-
- .:<OTPROOT>/lib/ic-4.0/priv/ic.jar:<OTPROOT>/lib/jinterface_1.1/priv/OtpErlang.jar
-
- where :
-
- <OTPROOT> is the location there OTP is installed
-
- Then type :
-
- java client
-
-
-
-6) Please note that :
-
- * you must always have the same cookie in order to eastablish connection
- between clients and servers.
-
- * you cannot start two servers with the same name.
- In this example all servers share the same name in order to test
- several constallations. Kill a server before starting another one.
-
-
-
-
-
diff --git a/lib/ic/examples/all-against-all/callbacks.c b/lib/ic/examples/all-against-all/callbacks.c
deleted file mode 100644
index 4e6edeb5e0..0000000000
--- a/lib/ic/examples/all-against-all/callbacks.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-
-#include <stdlib.h>
-#include "rmod_random__s.h"
-
-
-rmod_random_produce__rs*
-rmod_random_produce__cb(rmod_random oe_obj, double *rs, CORBA_Environment *oe_env)
-
-{
- *rs = (double) rand();
-
- return (rmod_random_produce__rs*) NULL;
-}
-
-
-rmod_random_init__rs*
-rmod_random_init__cb(rmod_random oe_obj, long* seed1, long* seed2, long* seed3, CORBA_Environment *oe_env)
-
-{
- srand(*seed1 * *seed2 * *seed3);
-
- return (rmod_random_init__rs*) NULL;
-}
-
-
-
diff --git a/lib/ic/examples/all-against-all/client.c b/lib/ic/examples/all-against-all/client.c
deleted file mode 100644
index 4f2f7e3eff..0000000000
--- a/lib/ic/examples/all-against-all/client.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-
-/* Just include the interface function */
-#include "rmod_random.h"
-
-
-/* Assign your own node name here */
-#define CLNODENAME "c50"
-#define SNODENAME "babbis"
-#define SREGNAME "rmod_random_impl"
-#define COOKIE "flash"
-#define INBUFSZ 1024
-#define OUTBUFSZ 1024
-#define HOSTNAMESZ 256
-
-
-
-/* Stopping node */
-void client_exit(CORBA_Environment *env) {
-
- /* Free env & buffers */
- CORBA_free(env->_inbuf);
- CORBA_free(env->_outbuf);
- CORBA_free(env);
-
- erl_close_connection(env->_fd);
- exit(1);
-}
-
-
-int main(){
-
- double result=0;
- int i=0;
- int error = 0;
- erlang_pid pid;
- char host[HOSTNAMESZ];
- char server_node[HOSTNAMESZ];
- char client_node[HOSTNAMESZ];
- CORBA_Environment *env;
-
- /* Initiate names */
-#ifdef __WIN32__
- WORD wVersionRequested;
- WSADATA wsaData;
-
- wVersionRequested = MAKEWORD(1, 1);
- if ((error = WSAStartup(wVersionRequested, &wsaData))) {
- fprintf(stderr,"Can't initialize windows sockets: %d",error);
- return 0;
- }
-#endif
- error = gethostname(host,HOSTNAMESZ);
- if (error) {
-#ifdef __WIN32__
- fprintf(stderr,"can't find own hostname (error = %ld) !\n",WSAGetLastError());
-#else /* not __WIN32__ */
- fprintf(stderr,"can't find own hostname !\n");
-#endif
- }
- sprintf(client_node,"%s@%s",CLNODENAME,host);
- sprintf(server_node,"%s@%s",SNODENAME,host);
-
- /* Create and init CORBA_Environment */
- env = CORBA_Environment_alloc(INBUFSZ,OUTBUFSZ);
-
- /* Initiating the connection */
- erl_init(NULL,0);
- erl_connect_init(50,COOKIE,0);
-
- /* Initiating pid*/
- strcpy(pid.node,client_node);
- pid.num = 99;
- pid.serial = 0;
- pid.creation = 0;
-
- /* Fixing environment variable */
- env->_fd=erl_connect(server_node);
- strcpy(env->_regname,SREGNAME);
- env->_to_pid = NULL;
- env->_from_pid = &pid;
-
- if (env->_fd < 0) {
- fprintf(stderr,"Error : Cannot connect to Server\n");
-
- /* Free env & buffers */
- CORBA_free(env->_inbuf);
- CORBA_free(env->_outbuf);
- CORBA_free(env);
- exit(1);
- }
-
- /* Calling the init function */
- rmod_random_init(NULL, 1, 2, 3, env);
-
- switch(env->_major) {
- case CORBA_NO_EXCEPTION: /* Success */
- printf("Init complete !\n");
- break;
- case CORBA_SYSTEM_EXCEPTION: /* System exception */
- printf("Init call failure, reason : %s\n",(char *) CORBA_exception_value(env));
- CORBA_exception_free(env);
- client_exit(env);
- default: /* Should not come here */
- client_exit(env);
- }
-
- /* Calling the produce function */
- for(i=1; i<=10; i++) {
- result = rmod_random_produce(NULL, env);
-
- switch(env->_major) {
- case CORBA_NO_EXCEPTION: /* Success */
- break;
- case CORBA_SYSTEM_EXCEPTION: /* System exception */
- printf("Init call failure, reason : %s\n",(char *) CORBA_exception_value(env));
- CORBA_exception_free(env);
- client_exit(env);
- default: /* Should not come here */
- client_exit(env);
- }
-
- printf("the random number nr%d is %f\n",i,result);
- }
-
- /* Closing the connection */
- erl_close_connection(env->_fd);
-
- /* Free env & buffers */
- CORBA_free(env->_inbuf);
- CORBA_free(env->_outbuf);
- CORBA_free(env);
-
- return 0;
-}
diff --git a/lib/ic/examples/all-against-all/client.erl b/lib/ic/examples/all-against-all/client.erl
deleted file mode 100644
index 3c147037a0..0000000000
--- a/lib/ic/examples/all-against-all/client.erl
+++ /dev/null
@@ -1,54 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : client.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module(client).
-
--export([produce/0,init/3,call/0]).
-
--define(SERVER,{rmod_random_impl,
- list_to_atom("babbis@"++hd(tl(string:tokens(atom_to_list(node()),"@"))))}).
--define(CLIENTMOD,'rmod_random').
-
-produce() ->
- ?CLIENTMOD:produce(?SERVER).
-
-
-init(Seed1, Seed2, Seed3) ->
- io:format("Init..."),
- ?CLIENTMOD:init(?SERVER,Seed1, Seed2, Seed3),
- io:format("ok\n").
-
-
-call() ->
- init(1,2,3),
- produce(0).
-
-
-produce(10) ->
- ok;
-produce(Ctr) ->
- N = produce(),
- io:format("Random~p = ~p\n",[Ctr,N]),
- produce(Ctr+1).
diff --git a/lib/ic/examples/all-against-all/client.java b/lib/ic/examples/all-against-all/client.java
deleted file mode 100644
index 48b5bc4f60..0000000000
--- a/lib/ic/examples/all-against-all/client.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-public class client {
-
- private static java.lang.String SNode = "client";
- private static java.lang.String PNode = "babbis";
- private static java.lang.String Cookie = "flash";
- private static java.lang.String Server = "rmod_random_impl";
-
- private static rmod._randomStub stub;
-
- public static void main(String[] args) {
-
- try {
-
- stub = new rmod._randomStub(SNode,PNode,Cookie,Server);
- int seed1 = 1;
- int seed2 = 2;
- int seed3 = 3;
- double random = 0;
-
- System.out.print("\nClient initialization....");
- stub.init(seed1,seed2,seed3);
- System.out.println("ok\n");
-
-
- for (int i = 0; i < 10; i++) {
- random = stub.produce();
- System.out.println("Random" + i + " = " + random);
- }
- System.out.println("\nClient terminated.\n");
-
- stub.__disconnect();
-
- } catch( Exception e) {
- System.out.println("Exception :");
- e.printStackTrace();
- }
-
- }
-
-}
-
diff --git a/lib/ic/examples/all-against-all/random.idl b/lib/ic/examples/all-against-all/random.idl
deleted file mode 100644
index 3402dfee2c..0000000000
--- a/lib/ic/examples/all-against-all/random.idl
+++ /dev/null
@@ -1,51 +0,0 @@
-// ``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.
-//
-// The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-// Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-// AB. All Rights Reserved.''
-//
-// $Id$
-//
-
-#ifndef _RANDOM_IDL
-#define _RANDOM_IDL
-
-module rmod {
-
- interface random {
-
- double produce();
-
- oneway void init(in long seed1, in long seed2, in long seed3);
-
- };
-
-};
-
-
-#endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/examples/all-against-all/rmod_random_impl.erl b/lib/ic/examples/all-against-all/rmod_random_impl.erl
deleted file mode 100644
index 36b280c0b2..0000000000
--- a/lib/ic/examples/all-against-all/rmod_random_impl.erl
+++ /dev/null
@@ -1,49 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(rmod_random_impl).
--export([init/1, terminate/2]).
--export([produce/1,init/4]).
-
-
-init(Env) ->
- {ok, []}.
-
-terminate(From, Reason) ->
- ok.
-
-
-produce(_Random) ->
- case catch random:uniform() of
- {'EXIT',_} ->
- true;
- RUnif ->
- {reply,RUnif,[]}
- end.
-
-
-init(_Random,S1,S2,S3) ->
- case catch random:seed(S1,S2,S3) of
- {'EXIT',_} ->
- true;
- _ ->
- {noreply,[]}
- end.
-
diff --git a/lib/ic/examples/all-against-all/server.c b/lib/ic/examples/all-against-all/server.c
deleted file mode 100644
index 6d46ea7673..0000000000
--- a/lib/ic/examples/all-against-all/server.c
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <string.h>
-#ifdef __WIN32__
-#include <winsock2.h>
-#include <direct.h>
-#include <windows.h>
-#include <winbase.h>
-#else /* not __WIN32__ */
-#include <errno.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#endif
-#include "rmod_random__s.h"
-
-/* Used functions */
-static int getport(int sockd);
-static int getlisten(int port);
-static int init(int *sd, int *portnr, int *epmd_fd);
-void terminate(int *fd, int *sd, int *epmd_fd);
-static void server_loop(int fd, int sd);
-
-/* change these, or even better, make command-line args to program... */
-#define COOKIE "flash"
-#define SERVER "babbis"
-#define NODENAMESZ 512
-#define HOSTNAMESZ 256
-#define INBUFSZ 1024
-#define OUTBUFSZ 1024
-
-
-int main(int argc, char **argv)
-{
- int sd;
- int portnr;
- int epmd_fd;
-
- /* crate file descriptors */
- if (init(&sd, &portnr, &epmd_fd) < 0)
- return -1;
-
- /* start server loop */
- server_loop(sd,epmd_fd);
-
- return 0;
-}
-
-
-
-static void server_loop(int sd, int epmd_fd)
-{
- ErlConnect conn;
- erlang_msg msg;
- int status=1;
- CORBA_Environment *env;
-
- /* Create and init CORBA_Environment */
- env = CORBA_Environment_alloc(INBUFSZ,OUTBUFSZ);
-
- while (status >= 0) {
-
- status = 1;
-
- if ((env->_fd = erl_accept(sd,&conn)) < 0) {
- /* error */
- fprintf(stderr,"Accept failed: %s\n",strerror(errno));
- }
- else {
- /* connection */
- fprintf(stderr,"Accepted connection from %s\n",conn.nodename);
-
- while (status >= 0) {
-
- /* write message to buffer */
- status = ei_receive_encoded(env->_fd, &env->_inbuf, &env->_inbufsz, &msg, &env->_iin);
- switch(status) {
- case ERL_SEND:
- case ERL_REG_SEND :
- /* do transaction with fd */
- rmod_random__switch(NULL,env);
-
- switch(env->_major) {
- case CORBA_NO_EXCEPTION: /* Success */
- break;
- case CORBA_SYSTEM_EXCEPTION: /* System exception */
- printf("Request failure, reason : %s\n",(char *) CORBA_exception_value(env));
- CORBA_exception_free(env);
- break;
- default: /* Should not come here */
- CORBA_exception_free(env);
- break;
- }
-
- /* send outdata */
- if (env->_iout > 0)
- ei_send_encoded(env->_fd,&env->_caller,env->_outbuf,env->_iout);
- break;
-
- case ERL_TICK :
- break;
- default : /* < 0 */
- printf("Connection terminated\n");
- break;
- }
- }
- }
- status=0; /* restart */
- }
-
- /* close file descriptors */
- terminate(&env->_fd, &sd, &epmd_fd);
-
- /* Free env & buffers */
- CORBA_free(env->_inbuf);
- CORBA_free(env->_outbuf);
- CORBA_free(env);
-}
-
-
-
-static int init(int *sd, int *portnr, int *epmd_fd)
-{
- char host[HOSTNAMESZ];
- char servernode[NODENAMESZ];
- struct hostent *h;
- int error = 0;
-
-#ifdef __WIN32__
- WORD wVersionRequested;
- WSADATA wsaData;
-
- wVersionRequested = MAKEWORD(1, 1);
- if ((error = WSAStartup(wVersionRequested, &wsaData))) {
- fprintf(stderr,"Can't initialize windows sockets: %d",error);
- }
-#endif
- /* get the host name */
- error = gethostname(host,HOSTNAMESZ);
- if (error) {
-#ifdef __WIN32__
- fprintf(stderr,"can't find own hostname (error = %ld) !\n",WSAGetLastError());
-#else /* not __WIN32__ */
- fprintf(stderr,"can't find own hostname !\n");
-#endif
- }
- else {
- /* identify host */
- if (!(h = erl_gethostbyname(host)))
- fprintf(stdout,"can't find own ip address\n");
- else {
-
- /* get a listen port. 0 means let system choose port number */
- *sd = getlisten(0);
-
- /* what port did we get? */
- /* this call not necessary if we specified port in call to getlisten() */
- *portnr = getport(*sd);
-
- /* make the nodename server@host */
- sprintf(servernode,"%s@%s",SERVER,host);
-
- /* initiate */
- erl_init(NULL,0);
-
- /* host, alive, alive@host, addr, cookie, creation */
- erl_connect_xinit(host,SERVER,servernode,(Erl_IpAddr)(h->h_addr_list[0]),COOKIE,0);
-
- /* let epmd know we are here */
- *epmd_fd = erl_publish(*portnr);
-
- return 0;
- }
- }
- return -1;
-}
-
-
-void terminate(int *fd, int *sd, int *epmd_fd) {
-
- close(*fd);
-
- /* remove info from epnd */
- close(*epmd_fd);
-
- /* return socket */
- close(*sd);
-
-}
-
-
-
-/* tells you what port you are using on given socket */
-static int getport(int sockd)
-{
- struct sockaddr_in addr;
- int namelen = sizeof(addr);
- int i;
-
- memset(&addr,0,sizeof(addr));
-
- if ((i = getsockname(sockd,(struct sockaddr *)&addr,&namelen))<0)
- return i;
-
- return ntohs(addr.sin_port);
-}
-
-
-
-/* return a listen socket, bound to given port */
-/* specify port = 0 to let system assign port */
-static int getlisten(int port)
-{
- int sockd;
- struct sockaddr_in inaddr;
- int opt = 1;
- int i;
-
- /* get listen socket */
- if ((sockd = socket(AF_INET,SOCK_STREAM,0)) < 0) return sockd;
-
- if ((i=setsockopt(sockd,SOL_SOCKET,SO_REUSEADDR,(void *)&opt,sizeof(opt)))<0)
- return i;
-
- /* bind to requested port */
- memset(&inaddr,0,sizeof(inaddr));
- inaddr.sin_family = AF_INET;
- inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- inaddr.sin_port = htons(port);
-
- if ((i = bind(sockd,(struct sockaddr*) &inaddr, sizeof(inaddr))) < 0)
- return i;
-
- listen(sockd,5);
-
- return sockd;
-}
-
diff --git a/lib/ic/examples/all-against-all/server.erl b/lib/ic/examples/all-against-all/server.erl
deleted file mode 100644
index c5fa2589ae..0000000000
--- a/lib/ic/examples/all-against-all/server.erl
+++ /dev/null
@@ -1,41 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(server).
--export([start/0]).
-
-
-
-%% This starts up the random number server
-start() ->
- %% Start the gen server
- {ok,Pid} = rmod_random:oe_create([],{local,'rmod_random_impl'}),
- true.
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/examples/all-against-all/server.java b/lib/ic/examples/all-against-all/server.java
deleted file mode 100644
index 79618ba8be..0000000000
--- a/lib/ic/examples/all-against-all/server.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-public class server {
-
- private static java.lang.String SNode = "babbis";
- private static java.lang.String Cookie = "flash";
- private static java.lang.String RegName = "rmod_random_impl";
-
- public static void main(String[] args) {
-
-
- System.out.println("\nServer running.\n");
- boolean serverState = true;
- boolean recState = true;
-
- try {
-
- com.ericsson.otp.erlang.OtpServer self = new com.ericsson.otp.erlang.OtpServer(SNode, Cookie);
- self.publishPort();
-
- /* Server loop */
- while(serverState == true) {
-
- com.ericsson.otp.erlang.OtpConnection connection = self.accept();
- serverImpl srv = new serverImpl();
- com.ericsson.otp.erlang.OtpInputStream request;
- com.ericsson.otp.erlang.OtpOutputStream reply;
- com.ericsson.otp.erlang.OtpErlangPid client;
-
- /* Server loop */
- while(recState == true) {
-
- if (connection.isConnected() == true)
- try {
-
- request = connection.receiveBuf();
-
- reply = srv.invoke(request);
-
- if (reply != null) {
- client = srv.__getCallerPid();
-
- connection.sendBuf(client,reply);
- }
-
- } catch( Exception e) {
- System.out.println("Server terminated.\n\n");
- recState = false;
- serverState = false;
- }
- }
-
- connection.close();
- }
-
- } catch( Exception e) {
- System.out.println("Initialization exception :");
- e.printStackTrace();
- }
- }
-}
-
-
-
-
diff --git a/lib/ic/examples/all-against-all/serverImpl.java b/lib/ic/examples/all-against-all/serverImpl.java
deleted file mode 100644
index 336bc7e327..0000000000
--- a/lib/ic/examples/all-against-all/serverImpl.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-public class serverImpl extends rmod._randomImplBase {
-
- java.util.Random random = null;
-
-
- public void init(int seed1, int seed2, int seed3) throws java.lang.Exception {
-
- random = new java.util.Random(seed1+seed2+seed3);
- };
-
-
- public double produce() throws java.lang.Exception {
-
- return random.nextDouble();
- }
-
-}
-
-
-
-
-
-
diff --git a/lib/ic/examples/c-client/Makefile b/lib/ic/examples/c-client/Makefile
deleted file mode 100644
index 1bfaaed477..0000000000
--- a/lib/ic/examples/c-client/Makefile
+++ /dev/null
@@ -1,87 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1998-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-# Point this at your version of OTP
-OTPROOT=/usr/local/otp/daily_build/otp_beam_sunos5_r8a.latest
-
-# Type actual IC Version
-ICVSN=4.1.1
-
-# Type actual Erl Interface Vesrion
-EIVSN=3.3.0
-
-# IDL file(s)
-IDLS=random.idl
-
-# Own C-client files
-CCL=client
-
-# Generated C-server files
-GCCLS=oe_code_seed rmod_random
-
-# Includes
-IFLAGS=-I$(OTPROOT)/lib/ic-$(ICVSN)/include \
- -I$(OTPROOT)/lib/erl_interface-$(EIVSN)/include
-
-LDFLAGS=-L$(OTPROOT)/lib/ic-$(ICVSN)/priv/lib \
- -L$(OTPROOT)/lib/erl_interface-$(EIVSN)/lib
-
-LDLIBS=-lic -lerl_interface -lei -lnsl -lsocket
-
-
-# Erlang compiler
-ERLC=$(OTPROOT)/bin/erlc
-
-# Erlang compiler flags.
-EFLAGS='+{preproc_flags,"-I $(OTPROOT)/usr/include"}' '+{scoped_op_calls,true}'
-
-
-# C compiler
-CC=gcc
-
-# C compiler flags
-CFLAGS=-ggdb -O2 -Wall $(IFLAGS)
-
-
-all: server client
-
-
-server:
- $(ERLC) $(EFLAGS) '+{be,erl_genserv}' $(IDLS)
- $(ERLC) *.erl
-
-client:
- $(ERLC) $(EFLAGS) '+{be,c_client}' $(IDLS)
- $(CC) $(IFLAGS) -c $(CCL:=.c) $(GCCLS:=.c)
- $(CC) $(CCL:=.o) $(GCCLS:=.o) -o $@ $(LDFLAGS) $(LDLIBS)
-
-
-
-clean:
- /bin/rm -f $(GCCLS:=.o) $(GCCLS:=.c) $(CCL:=.o) *.jam *.beam oe* rmod_random.erl *.h *.hrl *~ core client
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/examples/c-client/ReadMe b/lib/ic/examples/c-client/ReadMe
deleted file mode 100644
index 28372c3be2..0000000000
--- a/lib/ic/examples/c-client/ReadMe
+++ /dev/null
@@ -1,46 +0,0 @@
-This is a short description on the use of the c-client demo,
-a client that initiates and uses a random number generator
-that lies on an Erlang-genserver.
-
-Instructions.
-
-1) On Makefile :
- * Modify the OTPROOT variable on the Makefile to point
- to the root for your erlang instalation.
- * Modify IC and Erl_Interface versions to agree your
- OTP version.
-
-2) Type "make" to build the example.
-
-
-3) Start erlang with the options
- -setcookie <Some Cookie> -sname <SomeNodeName>
-
- In this example you should use :
-
- erl -setcookie flash -sname babbis
-
-
-4) On the erlang shell type :
- --------------------------
-
- rmod_random:oe_create([],{local,rmod_random_impl}). ( initializes the server )
-
- or
-
- test:start().
-
-
- Then start a new terminal window and type :
- -------------------------------------------
-
- client ( calls the client )
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/examples/c-client/client.c b/lib/ic/examples/c-client/client.c
deleted file mode 100644
index 652d8376fd..0000000000
--- a/lib/ic/examples/c-client/client.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-
-/* Include the interface function and ei_connect */
-#include "rmod_random.h"
-#include "ei_connect.h"
-
-/* Assign your own node name here */
-#define SNODE "babbis@balin"
-#define SERVER "rmod_random_impl"
-#define COOKIE "flash"
-#define CLNODE "c47@balin"
-#define INBUFSZ 1024
-#define OUTBUFSZ 1024
-
-/* Stopping node */
-void client_exit(CORBA_Environment *env) {
-
- /* Free env & buffers */
- CORBA_free(env->_inbuf);
- CORBA_free(env->_outbuf);
- CORBA_free(env);
-
- close(env->_fd);
- exit(1);
-}
-
-int main()
-{
- double result=0;
- int i=0;
- erlang_pid pid;
- CORBA_Environment *env;
- seed idata;
- ei_cnode ec;
-
- /* Create and init CORBA_Environment */
- env = CORBA_Environment_alloc(INBUFSZ,OUTBUFSZ);
-
- /* Initialize seed */
- idata.seed1 = 1;
- idata.seed2 = 2;
- idata.seed3 = 3;
-
- /* Initiating the connection */
- ei_connect_init(&ec, "c47", COOKIE, 0);
-
- /* Initiating pid*/
- strcpy(pid.node,CLNODE);
- pid.num = 99;
- pid.serial = 0;
- pid.creation = 0;
-
- /* Fixing environment variable */
- env->_fd = ei_connect(&ec, SNODE);
- strcpy(env->_regname, SERVER);
- env->_to_pid = NULL;
- env->_from_pid = &pid;
-
- if (env->_fd < 0) {
- fprintf(stderr,"Error : Cannot connect to Server\n");
-
- /* Free env & buffers */
- CORBA_free(env->_inbuf);
- CORBA_free(env->_outbuf);
- CORBA_free(env);
- exit(1);
- }
-
- /* Calling the init function */
- rmod_random_init(NULL, &idata, env);
-
- switch(env->_major) {
- case CORBA_NO_EXCEPTION: /* Success */
- printf("Init complete !\n");
- break;
- case CORBA_SYSTEM_EXCEPTION: /* System exception */
- printf("Init call failure, reason : %s\n",(char *) CORBA_exception_value(env));
- CORBA_exception_free(env);
- client_exit(env);
- default: /* Should not come here */
- client_exit(env);
- }
-
- /* Calling the produce function */
- for(i=1; i<=10; i++) {
- result = rmod_random_produce(NULL, env);
-
- switch(env->_major) {
- case CORBA_NO_EXCEPTION: /* Success */
- break;
- case CORBA_SYSTEM_EXCEPTION: /* System exception */
- printf("Init call failure, reason : %s\n",(char *) CORBA_exception_value(env));
- CORBA_exception_free(env);
- client_exit(env);
- default: /* Should not come here */
- client_exit(env);
- }
-
- printf("the random number nr%d is %f\n",i,result);
- }
-
- /* Closing the connection */
- close(env->_fd);
-
- /* Free env & buffers */
- CORBA_free(env->_inbuf);
- CORBA_free(env->_outbuf);
- CORBA_free(env);
-
- return 0;
-}
-
diff --git a/lib/ic/examples/c-client/random.idl b/lib/ic/examples/c-client/random.idl
deleted file mode 100644
index 8f54058e2b..0000000000
--- a/lib/ic/examples/c-client/random.idl
+++ /dev/null
@@ -1,52 +0,0 @@
-// ``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.
-//
-// The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-// Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-// AB. All Rights Reserved.''
-//
-// $Id$
-//
-#ifndef _RANDOM_IDL
-#define _RANDOM_IDL
-
-struct seed {
- long seed1;
- long seed2;
- long seed3;
-};
-
-module rmod {
-
- interface random {
-
- double produce();
-
- oneway void init(in seed idata);
-
- };
-
-};
-
-#endif
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/examples/c-client/rmod_random_impl.erl b/lib/ic/examples/c-client/rmod_random_impl.erl
deleted file mode 100644
index 2948115f8d..0000000000
--- a/lib/ic/examples/c-client/rmod_random_impl.erl
+++ /dev/null
@@ -1,53 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module('rmod_random_impl').
--include("oe_random.hrl").
--export([init/1, terminate/2]).
--export([produce/1,init/2]).
-
-
-init(Env) ->
- {ok, []}.
-
-terminate(From, Reason) ->
- ok.
-
-
-produce(_Random) ->
- case catch random:uniform() of
- {'EXIT',_} ->
- true;
- RUnif ->
- {reply,RUnif,[]}
- end.
-
-
-init(_Random,IData) ->
- S1 = IData#seed.seed1,
- S2 = IData#seed.seed2,
- S3 = IData#seed.seed3,
- case catch random:seed(S1,S2,S3) of
- {'EXIT',_} ->
- true;
- _ ->
- {noreply,[]}
- end.
-
diff --git a/lib/ic/examples/c-client/test.erl b/lib/ic/examples/c-client/test.erl
deleted file mode 100644
index d1fa40ff44..0000000000
--- a/lib/ic/examples/c-client/test.erl
+++ /dev/null
@@ -1,44 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-% Start Erlang with : erl -sname <your name> -setcookie <your cookie>
-
--module(test).
-
--export([start/0,exec/0]).
-
-
-start() ->
- io:format("Starting server~n"),
- rmod_random:oe_create([],{local,'rmod_random_impl'}).
-
-exec() ->
- io:format("Running client~n"),
- OutPut = os:cmd("client"),
- io:format("~s",[OutPut]).
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/examples/c-server/Makefile b/lib/ic/examples/c-server/Makefile
deleted file mode 100644
index be23d3ddf9..0000000000
--- a/lib/ic/examples/c-server/Makefile
+++ /dev/null
@@ -1,90 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1998-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-# Point this at your version of OTP
-OTPROOT=/usr/local/otp/daily_build/otp_beam_sunos5_r8a.latest
-
-# Type actual IC Version
-ICVSN=4.1.1
-
-# Type actual Erl Interface Vesrion
-EIVSN=3.3.0
-
-# IDL file(s)
-IDLS=random.idl
-
-# Own C-server files
-CSRV=server callbacks
-
-# Own C-client files
-CCL=client
-
-# Generated C-server files
-GCSRVS=rmod_random__s
-
-# Generated C-server files
-GCCLS=rmod_random
-
-# Includes
-IFLAGS=-I$(OTPROOT)/lib/ic-$(ICVSN)/include \
- -I$(OTPROOT)/lib/erl_interface-$(EIVSN)/include
-
-LDFLAGS=-L$(OTPROOT)/lib/ic-$(ICVSN)/priv/lib \
- -L$(OTPROOT)/lib/erl_interface-$(EIVSN)/lib
-
-LDLIBS=-lic -lerl_interface -lei -lnsl -lsocket
-
-
-# Erlang compiler
-ERLC=$(OTPROOT)/bin/erlc
-
-# Erlang compiler flags.
-EFLAGS='+{preproc_flags,"-I $(OTPROOT)/usr/include"}' '+{scoped_op_calls,true}'
-
-
-# C compiler
-CC=gcc
-
-# C compiler flags
-CFLAGS=-ggdb -O2 -Wall $(IFLAGS)
-
-
-all: server client erlclient
-
-
-server:
- $(ERLC) $(EFLAGS) '+{be,c_server}' $(IDLS)
- $(CC) $(IFLAGS) -c $(CSRV:=.c) $(GCSRVS:=.c)
- $(CC) $(CSRV:=.o) $(GCSRVS:=.o) -o $@ $(LDFLAGS) $(LDLIBS)
-
-client:
- $(ERLC) $(EFLAGS) '+{be,c_client}' $(IDLS)
- $(CC) $(IFLAGS) -c $(CCL:=.c) $(GCCLS:=.c)
- $(CC) $(CCL:=.o) $(GCCLS:=.o) -o $@ $(LDFLAGS) $(LDLIBS)
-
-erlclient:
- $(ERLC) $(EFLAGS) '+{be,erl_genserv}' $(IDLS)
- $(ERLC) *.erl
-
-
-clean:
- /bin/rm -f $(GCCLS:=.o) $(GCCLS:=.c) $(GCSRVS:=.o) $(GCSRVS:=.c) $(CCL:=.o) $(CSRV:=.o) *.jam *.beam oe* *.h *.hrl *~ core server client
-
-
diff --git a/lib/ic/examples/c-server/ReadMe b/lib/ic/examples/c-server/ReadMe
deleted file mode 100644
index 69fce4cd07..0000000000
--- a/lib/ic/examples/c-server/ReadMe
+++ /dev/null
@@ -1,45 +0,0 @@
-This is a short description on the use of the client demo,
-a client that initiates and uses a random number generator
-that lies on a C-server.
-
-Instructions.
-
-1) Modify the OTPROOT variable on the Makefile to point
- to the root for your erlang instalation.
- Modify IC and Erl_Interface versions to agree your
- OTP version.
-
-2)
- Type :
- ------
-
- make ( generates and compiles all code )
-
- server ( starts the c-server )
-
-
- To test the c-client against the c-server start a new terminal window and type :
- --------------------------------------------------------------------------------
-
- client ( calls the server )
-
-
- To test the erlang-client against the c-server start a new terminal window and type :
- -------------------------------------------------------------------------------------
-
-
- erl -sname client -setcookie flash ( start erlang )
-
- client:init(1,2,3). ( initiates the random generator )
-
- client:produce(). ( calls the random generator )
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/examples/c-server/callbacks.c b/lib/ic/examples/c-server/callbacks.c
deleted file mode 100644
index 2deca145f4..0000000000
--- a/lib/ic/examples/c-server/callbacks.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-
-#include <stdlib.h>
-#include "rmod_random__s.h"
-
-
-rmod_random_produce__rs*
-rmod_random_produce__cb(rmod_random oe_obj, double *rs, CORBA_Environment *oe_env)
-
-{
- *rs = (double) rand();
-
- return (rmod_random_produce__rs*) NULL;
-}
-
-
-rmod_random_init__rs*
-rmod_random_init__cb(rmod_random oe_obj, long* seed1, long* seed2, long* seed3, CORBA_Environment *oe_env)
-
-{
- srand(*seed1 * *seed2 * *seed3);
-
- return (rmod_random_init__rs*) NULL;
-}
-
-
-
diff --git a/lib/ic/examples/c-server/client.c b/lib/ic/examples/c-server/client.c
deleted file mode 100644
index c1d7a1c5a7..0000000000
--- a/lib/ic/examples/c-server/client.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-
-/* Include the interface function, and ei_connect */
-#include "rmod_random.h"
-#include "ei_connect.h"
-
-/* Assign your own node name here */
-#define SNODE "babbis@balin"
-#define SERVER "rmod_random_impl"
-#define COOKIE "flash"
-#define CLNODE "c47@balin"
-#define INBUFSZ 1024
-#define OUTBUFSZ 1024
-
-/* Stopping node */
-void client_exit(CORBA_Environment *env) {
-
- /* Free env & buffers */
- CORBA_free(env->_inbuf);
- CORBA_free(env->_outbuf);
- CORBA_free(env);
-
- close(env->_fd);
- exit(1);
-}
-
-int main()
-{
- double result=0;
- int i=0;
- erlang_pid pid;
- CORBA_Environment *env;
- ei_cnode ec;
-
- /* Create and init CORBA_Environment */
- env = CORBA_Environment_alloc(INBUFSZ,OUTBUFSZ);
-
- /* Initiating the connection */
- ei_connect_init(&ec, "c47", COOKIE, 0);
-
- /* Initiating pid*/
- strcpy(pid.node, CLNODE);
- pid.num = 99;
- pid.serial = 0;
- pid.creation = 0;
-
- /* Fixing environment variable */
- env->_fd = ei_connect(&ec, SNODE);
- strcpy(env->_regname,SERVER);
- env->_to_pid = NULL;
- env->_from_pid = &pid;
-
- if (env->_fd < 0) {
- fprintf(stderr,"Error : Cannot connect to Server\n");
-
- /* Free env & buffers */
- CORBA_free(env->_inbuf);
- CORBA_free(env->_outbuf);
- CORBA_free(env);
- exit(1);
- }
-
- /* Calling the init function */
- rmod_random_init(NULL, 1, 2, 3, env);
-
- switch(env->_major) {
- case CORBA_NO_EXCEPTION: /* Success */
- printf("Init complete !\n");
- break;
- case CORBA_SYSTEM_EXCEPTION: /* System exception */
- printf("Init call failure, reason : %s\n",(char *) CORBA_exception_value(env));
- CORBA_exception_free(env);
- client_exit(env);
- default: /* Should not come here */
- client_exit(env);
- }
-
- /* Calling the produce function */
- for(i=1; i<=10; i++) {
- result = rmod_random_produce(NULL, env);
-
- switch(env->_major) {
- case CORBA_NO_EXCEPTION: /* Success */
- break;
- case CORBA_SYSTEM_EXCEPTION: /* System exception */
- printf("Init call failure, reason : %s\n",(char *) CORBA_exception_value(env));
- CORBA_exception_free(env);
- client_exit(env);
- default: /* Should not come here */
- client_exit(env);
- }
-
- printf("the random number nr%d is %f\n",i,result);
- }
-
- /* Closing the connection */
- close(env->_fd);
-
- /* Free env & buffers */
- CORBA_free(env->_inbuf);
- CORBA_free(env->_outbuf);
- CORBA_free(env);
-
- return 0;
-}
-
diff --git a/lib/ic/examples/c-server/client.erl b/lib/ic/examples/c-server/client.erl
deleted file mode 100644
index da28cd504b..0000000000
--- a/lib/ic/examples/c-server/client.erl
+++ /dev/null
@@ -1,45 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%%----------------------------------------------------------------------
-%%% File : client.erl
-%%% Author : Babbis Xagorarakis <babbis@balin>
-%%% Purpose :
-%%% Created : 22 Oct 1998 by Babbis Xagorarakis <babbis@balin>
-%%%----------------------------------------------------------------------
-
--module(client).
--author('babbis@balin').
-
--export([produce/0,init/3]).
-
--define(SERVER,{rmod_random_impl,'babbis@balin'}).
--define(CLIENTMOD,'rmod_random').
-
-produce() ->
- ?CLIENTMOD:produce(?SERVER).
-
-
-init(Seed1, Seed2, Seed3) ->
- ?CLIENTMOD:init(?SERVER, Seed1, Seed2, Seed3).
-
-
-
-
diff --git a/lib/ic/examples/c-server/random.idl b/lib/ic/examples/c-server/random.idl
deleted file mode 100644
index 7ce302a2e7..0000000000
--- a/lib/ic/examples/c-server/random.idl
+++ /dev/null
@@ -1,50 +0,0 @@
-// ``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.
-//
-// The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-// Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-// AB. All Rights Reserved.''
-//
-// $Id$
-//
-
-#ifndef _RANDOM_IDL
-#define _RANDOM_IDL
-
-module rmod {
-
- interface random {
-
- double produce();
-
- oneway void init(in long seed1, in long seed2, in long seed3);
-
- };
-
-};
-
-#endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/examples/c-server/server.c b/lib/ic/examples/c-server/server.c
deleted file mode 100644
index a04d60e9b1..0000000000
--- a/lib/ic/examples/c-server/server.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <string.h>
-#ifdef __WIN32__
-#include <winsock2.h>
-#include <direct.h>
-#include <windows.h>
-#include <winbase.h>
-#else /* not __WIN32__ */
-#include <errno.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#endif
-#include "rmod_random__s.h"
-#include "ei_connect.h"
-
-/* Used functions */
-extern int gethostname(char *buf, int buflen);
-static int getport(int sockd);
-static int getlisten(int port);
-static int init(ei_cnode *ec, int *sd, int *portnr, int *epmd_fd);
-void terminate(int *fd, int *sd, int *epmd_fd);
-static void server_loop(ei_cnode *ec, int fd, int sd);
-
-/* change these, or even better, make command-line args to program... */
-#define COOKIE "flash"
-#define SERVER "babbis"
-#define NODENAMESZ 512
-#define HOSTNAMESZ 256
-#define INBUFSZ 1024
-#define OUTBUFSZ 1024
-
-
-int main(int argc, char **argv)
-{
- int sd;
- int portnr;
- int epmd_fd;
- ei_cnode ec;
-
- /* crate file descriptors */
- if (init(&ec, &sd, &portnr, &epmd_fd) < 0)
- return -1;
-
- /* start server loop */
- server_loop(&ec, sd, epmd_fd);
-
- return 0;
-}
-
-
-
-static void server_loop(ei_cnode *ec, int sd, int epmd_fd)
-{
- ErlConnect conn;
- erlang_msg msg;
- int status=1;
- CORBA_Environment *env;
-
- /* Create and init CORBA_Environment */
- env = CORBA_Environment_alloc(INBUFSZ,OUTBUFSZ);
-
- while (status >= 0) {
- status = 1;
-
- if ((env->_fd = ei_accept(ec, sd, &conn)) < 0) {
- /* error */
- fprintf(stderr,"Accept failed: %s\n",strerror(errno));
- } else {
- /* connection */
- fprintf(stderr,"Accepted connection from %s\n",conn.nodename);
-
- while (status >= 0) {
-
- /* write message to buffer */
- status = ei_receive_encoded(env->_fd, &env->_inbuf, &env->_inbufsz, &msg, &env->_iin);
- switch(status) {
- case ERL_SEND:
- case ERL_REG_SEND :
- /* do transaction with fd */
- rmod_random__switch(NULL,env);
-
- switch(env->_major) {
- case CORBA_NO_EXCEPTION: /* Success */
- break;
- case CORBA_SYSTEM_EXCEPTION: /* System exception */
- printf("Request failure, reason : %s\n",(char *) CORBA_exception_value(env));
- CORBA_exception_free(env);
- break;
- default: /* Should not come here */
- CORBA_exception_free(env);
- break;
- }
-
- /* send outdata */
- if (env->_iout > 0)
- ei_send_encoded(env->_fd,&env->_caller,env->_outbuf,env->_iout);
- break;
-
- case ERL_TICK :
- break;
- default : /* < 0 */
- printf("Connection terminated\n");
- break;
- }
- }
- }
- status=0; /* restart */
- }
-
- /* close file descriptors */
- terminate(&env->_fd, &sd, &epmd_fd);
-
- /* Free env & buffers */
- CORBA_free(env->_inbuf);
- CORBA_free(env->_outbuf);
- CORBA_free(env);
-}
-
-
-
-static int init(int *sd, int *portnr, int *epmd_fd)
-{
- char host[HOSTNAMESZ];
- char servernode[NODENAMESZ];
- struct hostent *h;
-
- /* get the host name */
- if ((gethostname(host,HOSTNAMESZ)))
- fprintf(stderr,"can't find own hostname\n");
- else {
- /* identify host */
- if (!(h = erl_gethostbyname(host)))
- fprintf(stdout,"can't find own ip address\n");
- else {
-
- /* get a listen port. 0 means let system choose port number */
- *sd = getlisten(0);
-
- /* what port did we get? */
- /* this call not necessary if we specified port in call to getlisten() */
- *portnr = getport(*sd);
-
- /* make the nodename server@host */
- sprintf(servernode,"%s@%s",SERVER,host);
-
- /* initiate */
- /* cnode, host, alive, alive@host, addr, cookie, creation */
- if (ei_connect_xinit(ec, host, SERVER, servernode,
- (Erl_IpAddr)(h->h_addr_list[0]),
- COOKIE, 0) == 0) {
- /* let epmd know we are here */
- *epmd_fd = ei_publish(ec, *portnr);
- if (*epmd_fd >= 0)
- return 0;
- }
- }
- }
- return -1;
-}
-
-
-void terminate(int *fd, int *sd, int *epmd_fd) {
-
- close(*fd);
-
- /* remove info from epnd */
- close(*epmd_fd);
-
- /* return socket */
- close(*sd);
-
-}
-
-
-
-/* tells you what port you are using on given socket */
-static int getport(int sockd)
-{
- struct sockaddr_in addr;
- int namelen = sizeof(addr);
- int i;
-
- memset(&addr,0,sizeof(addr));
-
- if ((i = getsockname(sockd,(struct sockaddr *)&addr,&namelen))<0)
- return i;
-
- return ntohs(addr.sin_port);
-}
-
-
-
-/* return a listen socket, bound to given port */
-/* specify port = 0 to let system assign port */
-static int getlisten(int port)
-{
- int sockd;
- struct sockaddr_in inaddr;
- int opt = 1;
- int i;
-
- /* get listen socket */
- if ((sockd = socket(AF_INET,SOCK_STREAM,0)) < 0) return sockd;
-
- if ((i=setsockopt(sockd,SOL_SOCKET,SO_REUSEADDR,(void *)&opt,sizeof(opt)))<0)
- return i;
-
- /* bind to requested port */
- memset(&inaddr,0,sizeof(inaddr));
- inaddr.sin_family = AF_INET;
- inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- inaddr.sin_port = htons(port);
-
- if ((i = bind(sockd,(struct sockaddr*) &inaddr, sizeof(inaddr))) < 0)
- return i;
-
- listen(sockd,5);
-
- return sockd;
-}
diff --git a/lib/ic/examples/erl-genserv/ReadMe b/lib/ic/examples/erl-genserv/ReadMe
deleted file mode 100644
index cde588e269..0000000000
--- a/lib/ic/examples/erl-genserv/ReadMe
+++ /dev/null
@@ -1,30 +0,0 @@
-This is a short description on the use of the c-client demo,
-a client that initiates and uses a random number generator
-that lies on an Erlang-genserver.
-
-Instructions.
-
- On the erlang shell type :
- --------------------------
-
- ic:gen(random,[{be,erl_genserv}]). ( generates the plain code )
-
- make:all(). ( compiles the erlang code )
-
- {ok,R} = rmod_random:oe_create(). ( initializes the server )
-
-
- Running the example :
- ---------------------
-
- rmod_random:init(R,1,2,3). ( initializes the generator )
-
- rmod_random:produce(R). ( generates a random number )
-
-
-
-
-
-
-
-
diff --git a/lib/ic/examples/erl-genserv/random.idl b/lib/ic/examples/erl-genserv/random.idl
deleted file mode 100644
index 969b24b749..0000000000
--- a/lib/ic/examples/erl-genserv/random.idl
+++ /dev/null
@@ -1,51 +0,0 @@
-// ``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.
-//
-// The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-// Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-// AB. All Rights Reserved.''
-//
-// $Id$
-//
-
-#ifndef _RANDOM_IDL
-#define _RANDOM_IDL
-
-
-module rmod {
-
- interface random {
-
- double produce();
-
- oneway void init(in long seed1, in long seed2, in long seed3);
-
- };
-
-};
-
-#endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/examples/erl-genserv/rmod_random_impl.erl b/lib/ic/examples/erl-genserv/rmod_random_impl.erl
deleted file mode 100644
index 9d9ca8afd4..0000000000
--- a/lib/ic/examples/erl-genserv/rmod_random_impl.erl
+++ /dev/null
@@ -1,64 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module('rmod_random_impl').
--export([init/1, terminate/2, start/0]).
--export([produce/1,init/4]).
-
-
-init(Env) ->
- {ok, []}.
-
-terminate(From, Reason) ->
- ok.
-
-
-produce(_Random) ->
- case catch random:uniform() of
- {'EXIT',_} ->
- true;
- RUnif ->
- {reply,RUnif,[]}
- end.
-
-
-init(_Random,S1,S2,S3) ->
- case catch random:seed(S1,S2,S3) of
- {'EXIT',_} ->
- true;
- _ ->
- {noreply,[]}
- end.
-
-
-%% This starts up the random number server
-start() ->
- %% Start the gen server
- {ok,Pid} = rmod_random:oe_create([],{local,'rmod_random_impl'}),
- true.
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/examples/erl-plain/ReadMe b/lib/ic/examples/erl-plain/ReadMe
deleted file mode 100644
index 26440b4d4f..0000000000
--- a/lib/ic/examples/erl-plain/ReadMe
+++ /dev/null
@@ -1,27 +0,0 @@
-This is a short description on the use of the erl-plain demo,
-a client that initiates and uses a random number generator
-that lies on an Erlang-genserver.
-
-Instructions.
-
- On the erlang shell type :
- --------------------------
-
- ic:gen(random,[{be,erl_plain}]). ( generates the plain code )
-
- make:all(). ( compiles the erlang code )
-
-
- Running the example :
- ---------------------
-
- rmod_random:init(1,2,3). ( initializes the generator )
-
- rmod_random:produce(). ( generates a random number )
-
-
-
-
-
-
-
diff --git a/lib/ic/examples/erl-plain/random.idl b/lib/ic/examples/erl-plain/random.idl
deleted file mode 100644
index 606d91f6c5..0000000000
--- a/lib/ic/examples/erl-plain/random.idl
+++ /dev/null
@@ -1,53 +0,0 @@
-// ``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.
-//
-// The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-// Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-// AB. All Rights Reserved.''
-//
-// $Id$
-//
-#pragma CODEOPT "[{be,c_genserv}]"
-
-
-#ifndef _RANDOM_IDL
-#define _RANDOM_IDL
-
-
-module rmod {
-
- interface random {
-
- double produce();
-
- oneway void init(in long seed1, in long seed2, in long seed3);
-
- };
-
-};
-
-#endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/examples/erl-plain/rmod_random_impl.erl b/lib/ic/examples/erl-plain/rmod_random_impl.erl
deleted file mode 100644
index ee8623f82d..0000000000
--- a/lib/ic/examples/erl-plain/rmod_random_impl.erl
+++ /dev/null
@@ -1,33 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module('rmod_random_impl').
-
--export([produce/0,init/3]).
-
-
-produce() ->
- random:uniform().
-
-
-init(S1,S2,S3) ->
- random:seed(S1,S2,S3),
- ok.
-
diff --git a/lib/ic/examples/java-client-server/ReadMe b/lib/ic/examples/java-client-server/ReadMe
deleted file mode 100644
index 9fde464e09..0000000000
--- a/lib/ic/examples/java-client-server/ReadMe
+++ /dev/null
@@ -1,69 +0,0 @@
-This is a short description on the use of the java demo,
-a client that initiates and uses a random number generator
-that lies on a java-server. You will be able to shift the
-existing client/server with the ones refered to the other
-examples.
-
-Instructions.
-
-1) Start erlang
-
- On the erlang shell type :
- --------------------------
-
- ic:gen(random,[{be,java}]). ( generates the java code )
-
-
-2) Modify the "SNode" string on file "server.java" to the server
- node name thet suites for your machine.
-
-
-3) Modify the "SNode" string on file "client.java" to the client
- node for your machine and the "PNode" string for the server
- node ( = the same as the SNode for the "server.java" file ).
-
-
-4) Set and export the CLASSPATH variable to point to the
- java classes located in java development kit, the
- Otp's classes and the current directory.
- Your classpath should look like this :
-
- .:<OTPROOT>/lib/ic-4.0/priv/ic.jar:<OTPROOT>/lib/jinterface_1.1/priv/OtpErlang.jar
-
- where :
-
- <OTPROOT> is the location there OTP is installed
-
-
-5) Start the empd deamon by using the command :
-
- epmd -daemon
-
-
-6) Compile the generated java code :
-
- javac rmod/*.java ( compiles all generated java code )
-
- javac *.java ( compiles all manually writen java code )
-
-
-7) Start the java on an terminal window :
-
- java server ( starts the java-server )
-
-
-8) Start the client on an terminal window :
-
- java client ( calls the server )
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/examples/java-client-server/client.java b/lib/ic/examples/java-client-server/client.java
deleted file mode 100644
index 48b5bc4f60..0000000000
--- a/lib/ic/examples/java-client-server/client.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-public class client {
-
- private static java.lang.String SNode = "client";
- private static java.lang.String PNode = "babbis";
- private static java.lang.String Cookie = "flash";
- private static java.lang.String Server = "rmod_random_impl";
-
- private static rmod._randomStub stub;
-
- public static void main(String[] args) {
-
- try {
-
- stub = new rmod._randomStub(SNode,PNode,Cookie,Server);
- int seed1 = 1;
- int seed2 = 2;
- int seed3 = 3;
- double random = 0;
-
- System.out.print("\nClient initialization....");
- stub.init(seed1,seed2,seed3);
- System.out.println("ok\n");
-
-
- for (int i = 0; i < 10; i++) {
- random = stub.produce();
- System.out.println("Random" + i + " = " + random);
- }
- System.out.println("\nClient terminated.\n");
-
- stub.__disconnect();
-
- } catch( Exception e) {
- System.out.println("Exception :");
- e.printStackTrace();
- }
-
- }
-
-}
-
diff --git a/lib/ic/examples/java-client-server/random.idl b/lib/ic/examples/java-client-server/random.idl
deleted file mode 100644
index 7ce302a2e7..0000000000
--- a/lib/ic/examples/java-client-server/random.idl
+++ /dev/null
@@ -1,50 +0,0 @@
-// ``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.
-//
-// The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-// Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-// AB. All Rights Reserved.''
-//
-// $Id$
-//
-
-#ifndef _RANDOM_IDL
-#define _RANDOM_IDL
-
-module rmod {
-
- interface random {
-
- double produce();
-
- oneway void init(in long seed1, in long seed2, in long seed3);
-
- };
-
-};
-
-#endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/examples/java-client-server/server.java b/lib/ic/examples/java-client-server/server.java
deleted file mode 100644
index 79618ba8be..0000000000
--- a/lib/ic/examples/java-client-server/server.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-public class server {
-
- private static java.lang.String SNode = "babbis";
- private static java.lang.String Cookie = "flash";
- private static java.lang.String RegName = "rmod_random_impl";
-
- public static void main(String[] args) {
-
-
- System.out.println("\nServer running.\n");
- boolean serverState = true;
- boolean recState = true;
-
- try {
-
- com.ericsson.otp.erlang.OtpServer self = new com.ericsson.otp.erlang.OtpServer(SNode, Cookie);
- self.publishPort();
-
- /* Server loop */
- while(serverState == true) {
-
- com.ericsson.otp.erlang.OtpConnection connection = self.accept();
- serverImpl srv = new serverImpl();
- com.ericsson.otp.erlang.OtpInputStream request;
- com.ericsson.otp.erlang.OtpOutputStream reply;
- com.ericsson.otp.erlang.OtpErlangPid client;
-
- /* Server loop */
- while(recState == true) {
-
- if (connection.isConnected() == true)
- try {
-
- request = connection.receiveBuf();
-
- reply = srv.invoke(request);
-
- if (reply != null) {
- client = srv.__getCallerPid();
-
- connection.sendBuf(client,reply);
- }
-
- } catch( Exception e) {
- System.out.println("Server terminated.\n\n");
- recState = false;
- serverState = false;
- }
- }
-
- connection.close();
- }
-
- } catch( Exception e) {
- System.out.println("Initialization exception :");
- e.printStackTrace();
- }
- }
-}
-
-
-
-
diff --git a/lib/ic/examples/java-client-server/serverImpl.java b/lib/ic/examples/java-client-server/serverImpl.java
deleted file mode 100644
index 336bc7e327..0000000000
--- a/lib/ic/examples/java-client-server/serverImpl.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-public class serverImpl extends rmod._randomImplBase {
-
- java.util.Random random = null;
-
-
- public void init(int seed1, int seed2, int seed3) throws java.lang.Exception {
-
- random = new java.util.Random(seed1+seed2+seed3);
- };
-
-
- public double produce() throws java.lang.Exception {
-
- return random.nextDouble();
- }
-
-}
-
-
-
-
-
-
diff --git a/lib/ic/examples/pre_post_condition/Makefile b/lib/ic/examples/pre_post_condition/Makefile
deleted file mode 100644
index cd7e630724..0000000000
--- a/lib/ic/examples/pre_post_condition/Makefile
+++ /dev/null
@@ -1,135 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-# ``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.
-#
-# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-# AB. All Rights Reserved.''
-#
-# $Id$
-#
-include $(ERL_TOP)/make/target.mk
-
-EBIN= ./
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(IC_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/ic-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-IDL_FILES = \
- ex.idl
-
-GEN_ERL_MODULES = \
- oe_ex \
- m_i \
- m_NotAnInteger
-
-MODULES= \
- m_i_impl \
- tracer
-
-GEN_HRL_FILES = \
- oe_ex.hrl \
- m.hrl \
- m_i.hrl
-
-HRL_FILES =
-TXT_FILES = ReadMe.txt
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-
-TARGET_FILES = \
- $(GEN_ERL_MODULES:%=$(EBIN)/%.$(EMULATOR)) \
- $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_LOCAL_FLAGS += -pa $(ERL_TOP)/lib/orber/ebin -pa $(ERL_TOP)/lib/ic/ebin
-# The -pa option is just used temporary until erlc can handle
-# includes from other directories than ../include .
-ERL_COMPILE_FLAGS += \
- $(ERL_LOCAL_FLAGS) \
- -pa $(ERL_TOP)/lib/orber -I$(ERL_TOP)/lib/orber
-YRL_FLAGS =
-
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
-
-clean:
- rm -f $(TARGET_FILES) $(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES) $(CLASS_FILES) IDL-GENERATED
- rm -f errs core *~
-
-docs:
-
-test: $(TEST_TARGET_FILES)
-
-
-IDL-GENERATED: ex.idl
- $(gen_verbose)erlc $(ERL_LOCAL_FLAGS) +'{precond,{tracer,pre}}' \
- +'{{postcond,"m::i::f"},{tracer,post}}' ex.idl
- $(V_at)>IDL-GENERATED
-
-$(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES): IDL-GENERATED
-
-$(TARGET_FILES): IDL-GENERATED
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/examples/pre_post_condition"
- $(INSTALL_DATA) $(ERL_FILES) $(IDL_FILES) $(TXT_FILES) "$(RELSYSDIR)/examples/pre_post_condition"
-
-
-release_docs_spec:
-
-
diff --git a/lib/ic/examples/pre_post_condition/ReadMe.txt b/lib/ic/examples/pre_post_condition/ReadMe.txt
deleted file mode 100644
index 2fb3f0a04f..0000000000
--- a/lib/ic/examples/pre_post_condition/ReadMe.txt
+++ /dev/null
@@ -1,74 +0,0 @@
- ``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.
-
- The Initial Developer of the Original Code is Ericsson Utvecklings AB.
- Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
- AB. All Rights Reserved.''
-
- $Id$
-
-
-This example shows how pre and post condition can be used for a Corba server object.
-
-
-The example consists of three files;
-
-ex.idl - the interface specification
-m_i_impl.erl - the server implementation
-tracer.erl - a module which contains a pre and a post condition
-
-
-The IDL file can for example be compiled with the following options:
-
-ic:gen(ex, [{precond, {tracer, pre}},{{postcond, "m::i::f"}, {tracer, post}}]).
-
-The result is that the function m::i::f gets both a pre and post condition call while
-the function m::i::g just get a pre condition call.
-
-
-A pre/post condition function should always return the atom ok and if something is wrong
-it should raise an exception ( ex: corba:raise(#userexception{}) ).
-
-
-
-
-Compile all erlang files and test the application.
-
-First start an erlang node, then type the following commands in the erlang shell.
-
-1> mnesia:create_schema([]).
-2> orber:install([]).
-3> orber:start().
-3>
-3> X = m_i:oe_create().
-4> catch m_i:f(X, 17).
-Precond called in process <0.139.0>: m_i:f() [[],17]
-f working ....
-Postcond called in process <0.139.0>: m_i:f() [[],17] {reply,{17,17},[]}
-17
-5>
-5> catch m_i:f(X, q).
-6> {'EXCEPTION',{m_NotAnInteger,"IDL:m/NotAnInteger:1.0"}}
-7>
-7>m_i:g(X, 17).
-Precond called in process <0.139.0>: m_i:g() [[],17]
-ok
-g working ....
-8>
-8>corba_boa:dispose(X).
-9> orber:stop().
-10>
-
-
-
-
-
diff --git a/lib/ic/examples/pre_post_condition/ex.idl b/lib/ic/examples/pre_post_condition/ex.idl
deleted file mode 100644
index 29298c8efb..0000000000
--- a/lib/ic/examples/pre_post_condition/ex.idl
+++ /dev/null
@@ -1,30 +0,0 @@
-// ``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.
-//
-// The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-// Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-// AB. All Rights Reserved.''
-//
-// $Id$
-//
-
-module m {
-
- exception NotAnInteger {};
-
- interface i {
- short f(in short i);
- oneway void g(in long i);
- };
-
-};
-
diff --git a/lib/ic/examples/pre_post_condition/m_i_impl.erl b/lib/ic/examples/pre_post_condition/m_i_impl.erl
deleted file mode 100644
index fa6d9675a2..0000000000
--- a/lib/ic/examples/pre_post_condition/m_i_impl.erl
+++ /dev/null
@@ -1,50 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%------------------------------------------------------------
-%%
-%% Example
-%%
-%%------------------------------------------------------------
--module(m_i_impl).
-
-%% Standard functions
--export([init/1, terminate/2]).
-%% Interface functions
--export([f/2, g/2]).
-
-init(_Env) ->
- {ok, []}.
-
-terminate(_From, _Reason) ->
- ok.
-
-f(State, In) ->
- io:format("f working ....\n", []),
- {reply, In, State}.
-
-g(State, _In) ->
- io:format("g working ....\n", []),
- {noreply, State}.
-
-
-
-
-
diff --git a/lib/ic/examples/pre_post_condition/tracer.erl b/lib/ic/examples/pre_post_condition/tracer.erl
deleted file mode 100644
index c64459f4fd..0000000000
--- a/lib/ic/examples/pre_post_condition/tracer.erl
+++ /dev/null
@@ -1,57 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: tracer.erl
-%%
-%% Description:
-%% This file contains an example of pre and post conditions for
-%% the corba backend.
-%%
-%%-----------------------------------------------------------------
--module(tracer).
--include("m.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([pre/3, post/4]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-pre(M, F, [State, I]) when is_integer(I) ->
- io:format("Precond called in process ~p: ~s:~s() ~p\n", [self(), M, F, [State, I]]),
- ok;
-pre(_M, _F, _A) -> %% Just an silly example to get an exception case
- corba:raise(#'m_NotAnInteger'{}).
-
-post(M, F, A, R) ->
- io:format("Postcond called in process ~p: ~s:~s() ~p ~p\n", [self(), M, F, A, R]),
- ok.
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
diff --git a/lib/ic/include/erlang.idl b/lib/ic/include/erlang.idl
deleted file mode 100644
index 87d1247b87..0000000000
--- a/lib/ic/include/erlang.idl
+++ /dev/null
@@ -1,58 +0,0 @@
-// ``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.
-//
-// The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-// Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-// AB. All Rights Reserved.''
-//
-// $Id$
-//
-
-#ifndef _ERLANG_IDL_
-#define _ERLANG_IDL_
-
-module erlang
-{
-
- // an erlang pid
- struct pid {
- string<256> node;
- unsigned long num;
- unsigned long serial;
- unsigned long creation;
- };
-
- // an erlang port
- struct port {
- string<256> node;
- unsigned long id;
- unsigned long creation;
- };
-
- // port and ref have identical structure
- struct ref {
- string<256> node;
- unsigned long id;
- unsigned long creation;
- };
-
-
- // an erlang term
- typedef any term;
-
-
- // an erlang binary
- typedef sequence<octet> binary;
-
-};
-
-#endif
diff --git a/lib/ic/include/ic.h b/lib/ic/include/ic.h
deleted file mode 100644
index 3dc5dbd4b5..0000000000
--- a/lib/ic/include/ic.h
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <ei.h>
-#include <erl_interface.h>
-
-#ifdef __WIN32__
-/* Windows.h #defines interface to struct, get rid of it! */
-#ifdef interface
-#undef interface
-#endif
-#endif
-
-#ifndef __IC_H__
-#define __IC_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Standard type mapping */
-
-#ifndef __CORBA_SHORT__
-#define __CORBA_SHORT__
- typedef short CORBA_short;
-#endif
-
-#ifndef __CORBA_LONG__
-#define __CORBA_LONG__
- typedef long CORBA_long;
-#endif
-
-/* CORBA_long_long = long because of erl_interface limitation */
-#ifndef __CORBA_LONG_LONG__
-#define __CORBA_LONG_LONG__
- typedef long CORBA_long_long; /* LONG LONG */
-#endif
-
-#ifndef __CORBA_UNSIGNED_SHORT__
-#define __CORBA_UNSIGNED_SHORT__
- typedef unsigned short CORBA_unsigned_short;
-#endif
-
-#ifndef __CORBA_UNSIGNED_LONG__
-#define __CORBA_UNSIGNED_LONG__
- typedef unsigned long CORBA_unsigned_long;
-#endif
-
-/* CORBA_unsigned long_long = unsigned long because of erl_interface
- limitation */
-
-#ifndef __CORBA_UNSIGNED_LONG_LONG__
-#define __CORBA_UNSIGNED_LONG_LONG__
- typedef unsigned long CORBA_unsigned_long_long;
-#endif
-
-#ifndef __CORBA_FLOAT__
-#define __CORBA_FLOAT__
- typedef float CORBA_float;
-#endif
-
-#ifndef __CORBA_DOUBLE__
-#define __CORBA_DOUBLE__
- typedef double CORBA_double;
-#endif
-
-
-#ifndef __CORBA_LONG_DOUBLE__
-#define __CORBA_LONG_DOUBLE__
- typedef double CORBA_long_double;
-#endif
-
-#ifndef __CORBA_CHAR__
-#define __CORBA_CHAR__
- typedef char CORBA_char;
-#endif
-
-#ifndef __CORBA_WCHAR__
-#define __CORBA_WCHAR__
- typedef unsigned long CORBA_wchar;
-#endif
-
-#ifndef __CORBA_BOOLEAN__
-#define __CORBA_BOOLEAN__
- typedef unsigned char CORBA_boolean;
-#endif
-
-#ifndef __CORBA_OCTET__
-#define __CORBA_OCTET__
- typedef char CORBA_octet;
-#endif
-
-#ifndef CORBA_enum
-#define CORBA_enum enum
-#endif
-
-#ifndef __ERLANG_BINARY__
-#define __ERLANG_BINARY__
- typedef struct {
- CORBA_unsigned_long _maximum;
- CORBA_unsigned_long _length;
- CORBA_octet* _buffer;
- } erlang_binary;
-#endif
-
-
-/* Object definition */
- typedef void* CORBA_Object;
-
-
-/* Exception discriminators */
-#ifndef CORBA_NO_EXCEPTION
-#define CORBA_NO_EXCEPTION 0
-#endif
-
-#ifndef CORBA_SYSTEM_EXCEPTION
-#define CORBA_SYSTEM_EXCEPTION -1
-#endif
-
-#ifndef CORBA_USER_EXCEPTION
-#define CORBA_USER_EXCEPTION -2
-#endif
-
-/* System exceptions */
-
-#define UNKNOWN "UNKNOWN"
-#define BAD_PARAM "BAD_PARAM"
-#define NO_MEMORY "NO_MEMORY"
-#define IMPL_LIMIT "IMP_LIMIT"
-#define COMM_FAILURE "COMM_FAILURE"
-#define INV_OBJREF "INV_OBJREF"
-#define NO_PERMISSION "NO_PERMISSION"
-#define INTERNAL "INTERNAL"
-#define MARSHAL "MARSHAL"
-#define INITIALIZE "INITIALIZE"
-#define NO_IMPLEMENT "NO_IMPLEMENT"
-#define BAD_TYPECODE "BAD_TYPECODE"
-#define BAD_OPERATION "BAD_OPERATION"
-#define NO_RESOURCES "NO_RESOURCES"
-#define NO_RESPONSE "NO_RESPONSE"
-#define PERSIST_STORE "PERSIST_STORE"
-#define BAD_INV_ORDER "BAD_INV_ORDER"
-#define TRANSIENT "TRANSIENT"
-#define FREE_MEM "FREE_MEM"
-#define INV_IDENT "INV_IDENT"
-#define INV_FLAG "INV_FLAG"
-#define INTF_REPOS "INTF_REPOS"
-#define BAD_CONTEXT "BAD_CONTEXT"
-#define OBJ_ADAPTER "OBJ_ADAPTER"
-#define DATA_CONVERSION "DATA_CONVERSION"
-#define OBJ_NOT_EXIST "OBJECT_NOT_EXIST"
-
-
-
-/* Exception type */
- typedef int CORBA_exception_type;
-
-
-#ifndef __CORBA_ENVIRONMENT__
-#define __CORBA_ENVIRONMENT__
-
-/* Environment definition */
- typedef struct {
-
- /*----- CORBA compatibility part ------------------------------------*/
- CORBA_exception_type _major; /* Exception tag, initially set
- to CORBA_NO_EXCEPTION */
-
- /*----- External Implementation part - initiated by the user --------*/
- int _fd; /* File descriptor */
- int _inbufsz; /* Size of input buffer */
- char *_inbuf; /* Pointer to always
- dynamically allocated
- buffer for input */
- int _outbufsz; /* Size of output buffer */
- char *_outbuf; /* Pointer to always
- dynamically
- allocated buffer
- for output */
- int _memchunk; /* Size of memory
- chunks in bytes,
- used for increasing
- the output buffer,
- set to >= 32,
- should be around >=
- 1024 for
- performance reasons */
- char _regname[256]; /* Pointer for
- registered name */
- erlang_pid *_to_pid; /* Process identity
- for caller */
- erlang_pid *_from_pid; /* Process identity
- for callee */
- /*----- Internal Implementation part - used by the server/client ----*/
- int _iin; /* Index for input buffer */
- int _iout; /* Index for output buffer */
- char _operation[256]; /* Pointer for operation name*/
- int _received; /* Used to count parameters */
- erlang_pid _caller; /* Used to identify
- the caller*/
- erlang_ref _unique; /* Used to identify the call */
- CORBA_char *_exc_id; /* Exception id field */
- void *_exc_value; /* Exception value field */
-
- unsigned int _ref_counter_1; /* Counter for reference */
- unsigned int _ref_counter_2; /* Counter for reference */
- unsigned int _ref_counter_3; /* Counter for reference */
-
- } CORBA_Environment;
-
-#endif
-
-
-/* Corba standard functions */
-
- void CORBA_free(void *);
- CORBA_char *CORBA_string_alloc(CORBA_unsigned_long);
- CORBA_wchar *CORBA_wstring_alloc(CORBA_unsigned_long);
- CORBA_char *CORBA_exception_id(CORBA_Environment *env);
- void *CORBA_exception_value(CORBA_Environment *env);
- void CORBA_exception_free(CORBA_Environment *env);
- void CORBA_exc_set(CORBA_Environment *env,
- CORBA_exception_type Major,
- CORBA_char *Id,
- CORBA_char *Value);
- CORBA_Environment *CORBA_Environment_alloc(int inbufsz, int outbufsz);
- void ic_init_ref(CORBA_Environment *env, erlang_ref *ref);
- int ic_compare_refs(erlang_ref *ref1, erlang_ref *ref2);
-
-/* Used internally */
-
-#define __OE_MEMCHUNK__ 1024
-#define __OE_VSNSZ__ 1
-#define __OE_LONGSZ__ 7
-#define __OE_LONGLONGSZ__ 7
-#define __OE_ULONGSZ__ 7
-#define __OE_ULONGLONGSZ__ 7
-#define __OE_DOUBLESZ__ 32
-#define __OE_CHARSZ__ 2
-#define __OE_WCHARSZ__ 7
-#define __OE_TUPLEHDRSZ__ 5
-#define __OE_LISTHDRSZ__ 5
-
-/* The actual size of a wide char (used to be #define __OE_WCHAR_SIZE_OF__ 4) */
-#define __OE_WCHAR_SIZE_OF__ sizeof(CORBA_wchar)
-
-/* Size check macro */
-#define OE_MALLOC_SIZE_CHECK(env,x) { \
- assert((x) > 0); \
- if (!((x) > 0)) { \
- CORBA_exc_set((env), CORBA_SYSTEM_EXCEPTION, INTERNAL, \
- "Bad malloc size calculation"); \
- return -1; \
- } \
-}
-
-/* Exec function -- probably not needed */
- typedef int oe_exec_function_t(CORBA_Object, CORBA_Environment*);
-/* These are for backward compatibility */
- typedef oe_exec_function_t ___exec_function___;
- typedef oe_exec_function_t ___generic___;
-
-/* Operation declaration */
- typedef struct {
- char *interface;
- char *name;
- oe_exec_function_t *function;
- } oe_operation_t;
-
-/* For backward compatibility */
- typedef oe_operation_t ___operation___;
-
-/* Map declaration */
- typedef struct {
- int length;
- oe_operation_t *operations;
- } oe_map_t;
-/* For backward compatibility */
- typedef oe_map_t ___map___;
-
-/* Align macro */
-#define OE_ALIGN(x) (((x) + sizeof(double) - 1) & ~(sizeof(double) - 1))
-
-/* Encoders */
- int oe_ei_encode_version(CORBA_Environment *env);
- int oe_ei_encode_long(CORBA_Environment *env, long p);
- int oe_ei_encode_longlong(CORBA_Environment *env, CORBA_long_long p);
- int oe_ei_encode_ulong(CORBA_Environment *env, unsigned long p);
- int oe_ei_encode_ulonglong(CORBA_Environment *env,
- CORBA_unsigned_long_long p);
- int oe_ei_encode_double(CORBA_Environment *env, double p);
- int oe_ei_encode_char(CORBA_Environment *env, char p);
- int oe_ei_encode_wchar(CORBA_Environment *env, CORBA_wchar p);
- int oe_ei_encode_string(CORBA_Environment *env, const char *p);
- int oe_ei_encode_wstring(CORBA_Environment *env, CORBA_wchar *p);
- int oe_ei_encode_atom(CORBA_Environment *env, const char *p);
- int oe_ei_encode_pid(CORBA_Environment *env, const erlang_pid *p);
- int oe_ei_encode_port(CORBA_Environment *env, const erlang_port *p);
- int oe_ei_encode_ref(CORBA_Environment *env, const erlang_ref *p);
- int oe_ei_encode_term(CORBA_Environment *env, void *t);
- int oe_ei_encode_tuple_header(CORBA_Environment *env, int arity);
- int oe_ei_encode_list_header(CORBA_Environment *env, int arity);
- int oe_encode_erlang_binary(CORBA_Environment *env, erlang_binary *binary);
-
-#define oe_ei_encode_empty_list(ev) oe_ei_encode_list_header(ev,0)
-
-/* Decoders */
- int oe_ei_decode_wchar(const char *buf, int *index, CORBA_wchar *p);
- int oe_ei_decode_wstring(const char *buf, int *index, CORBA_wchar *p);
- int oe_ei_decode_longlong(const char *buf, int *index, CORBA_long_long *p);
- int oe_ei_decode_ulonglong(const char *buf, int *index,
- CORBA_unsigned_long_long *p);
- int oe_decode_erlang_binary(CORBA_Environment *env, char *buf, int *index,
- erlang_binary *binary);
-
-/* Generic client encoders (gen_server protocol) */
- int oe_prepare_notification_encoding(CORBA_Environment *env);
- int oe_prepare_request_encoding(CORBA_Environment *env);
-
-/* Generic client decoders (gen_server protocol) */
- int oe_prepare_reply_decoding(CORBA_Environment *env);
-
-/* Generic client send and receive functions (Erlang distribution protocol) */
- int oe_send_notification(CORBA_Environment *env);
- int oe_send_notification_tmo(CORBA_Environment *env, unsigned int send_ms);
- int oe_send_request_and_receive_reply(CORBA_Environment *env);
- int oe_send_request_and_receive_reply_tmo(CORBA_Environment *env,
- unsigned int send_ms,
- unsigned int recv_ms);
-
-/* Generic server decoder */
- int oe_prepare_request_decoding(CORBA_Environment *env);
-
-/* Generic server encoder */
- int oe_prepare_reply_encoding(CORBA_Environment *env);
-
-/* -------- */
-
-/* Generic server receive (possibly send reply) */
- int oe_server_receive(CORBA_Environment *env, oe_map_t *map);
- int oe_server_receive_tmo(CORBA_Environment *env, oe_map_t *map,
- unsigned int send_ms,
- unsigned int recv_ms);
-
-/* -------- */
-
-/* Size calculators */
- int oe_sizecalc_erlang_binary(CORBA_Environment *env, int *index,
- int *size);
-/* Print functions */
- int print_erlang_binary(erlang_binary*);
-
-/* Length counter for wide strings */
- int ic_wstrlen(CORBA_wchar * p);
-
-/* Wide string comparison */
- int ic_wstrcmp(CORBA_wchar * ws1, CORBA_wchar * ws2);
-
-/* Put for 64-bits integer type */
-#define put64le(s,n) do { \
- (s)[0] = (n) & 0xff; \
- (s)[1] = ((n) >> 8) & 0xff; \
- (s)[2] = ((n) >> 16) & 0xff; \
- (s)[3] = ((n) >> 24) & 0xff; \
- (s)[4] = ((n) >> 32) & 0xff; \
- (s)[5] = ((n) >> 40) & 0xff; \
- (s)[6] = ((n) >> 48) & 0xff; \
- (s)[7] = ((n) >> 56) & 0xff; \
- (s)[8] = ((n) >> 64) & 0xff; \
- (s) += 8; \
-} while (0)
-
-/* Get for 64-bits integer type */
-#define get64le(s) \
- ((s) += 8, \
- ((((unsigned char *)(s))[-1] << 56) | \
- (((unsigned char *)(s))[-2] << 48) | \
- (((unsigned char *)(s))[-3] << 40) | \
- (((unsigned char *)(s))[-4] << 32) | \
- (((unsigned char *)(s))[-5] << 24) | \
- (((unsigned char *)(s))[-6] << 16) | \
- (((unsigned char *)(s))[-7] << 8) | \
- ((unsigned char *)(s))[-8]))
-
-
-
-/* Exec function switch */
- int oe_exec_switch(CORBA_Object, CORBA_Environment*, oe_map_t*);
-/* For backward compatibility */
- int ___switch___(CORBA_Object, CORBA_Environment*, oe_map_t*);
-
-/* For backward compatibility -- replaced by oe_prepare_request_decoding() */
- int ___call_info___(CORBA_Object, CORBA_Environment*);
-
-/* Map merging */
- oe_map_t* oe_merge_maps(oe_map_t*, int);
-/* For backward compatibility */
- oe_map_t* ___merge___(oe_map_t*, int);
-
-/* Macro for error reporting */
-
-#ifdef OE_C_REPORT
-#define OE_RPT_ERR(x) fprintf(stderr, (x))
-#else
-#define OE_RPT_ERR(x)
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/lib/ic/info b/lib/ic/info
deleted file mode 100644
index 96cb88d01f..0000000000
--- a/lib/ic/info
+++ /dev/null
@@ -1,2 +0,0 @@
-group: orb Object Request Broker & IDL Applications
-short: IDL compiler
diff --git a/lib/ic/internal_doc/c-improvements-1.txt b/lib/ic/internal_doc/c-improvements-1.txt
deleted file mode 100644
index ccfdec7cbe..0000000000
--- a/lib/ic/internal_doc/c-improvements-1.txt
+++ /dev/null
@@ -1,84 +0,0 @@
-Peter Hogfeldt 2003-08-14 PA1
-
-IC C BACK-ENDS IMPROVEMENTS
-
-1 C CLIENT
-
-1.1 Cast
-
- Each oneway operation roughly consists of the following code
- parts:
-
- - encoding the cast message
- - setting index of the out buffer to zero (1.1.1)
- - encoding the magic (1.1.1)
- - encoding a tuple header of size 2 (1.1.1)
- - encoding '$gen_cast' (1.1.1)
- - encoding the operation parameters (1.1.2)
- - sending the cast message (1.1.3)
-
- Only (1.1.2) is unique for the operation in question.
-
-1.1.1 Todo
-
- Define functions:
-
- int oe_ei_encode_cast(CORBA_environment *) that performs (1.1.1)
-
- int oe_ei_cast(CORBA_environment *) that performs (1.1.3)
-
- This will reduce code size.
-
- As compiler options
-
- oe_ei_encode_cast(), and
- oe_ei_cast()
-
- may be replaced by user defined functions.
-
-1.2 Call
-
- Each (non-oneway) operation roughly consists of the following code
- parts:
-
- - encoding the call message
- - setting index of the out buffer to zero (1.2.1)
- - encoding the magic (1.2.1)
- - encoding a tuple header of size 3 (1.2.1)
- - encoding '$gen_call' (1.2.1)
- - encoding a tuple header of size 2 (1.2.1)
- - encoding the from pid (1.2.1)
- - encoding the unique ref (1.2.1)
- - encoding the operation parameters (1.2.2)
- - sending the call message (1.2.3)
- - receiving the reply message (1.2.3)
- - decoding the reply parameters (1.2.4)
-
- Only (1.2.2) and (1.2.4) are unique for the operation in question.
-
-1.2.1 Todo
-
- Define functions:
-
- int oe_ei_encode_send(CORBA_environment *) that performs (1.2.1)
-
- int oe_ei_send_and_receive(CORBA_environment *) that performs (1.2.3)
-
- This will reduce code size.
-
- As compiler options
-
- oe_ei_encode_send(), and
- oe_ei_send_and_receive()
-
- may be replaced by user defined function.
-
-
-2 SERVER
-
- We do not provide any code for receiving operation messages, execute
- operations, and send the result back. Should we not do that?
-
-
-
- \ No newline at end of file
diff --git a/lib/ic/internal_doc/protocol.txt b/lib/ic/internal_doc/protocol.txt
deleted file mode 100644
index 54e1ef55cf..0000000000
--- a/lib/ic/internal_doc/protocol.txt
+++ /dev/null
@@ -1,182 +0,0 @@
-Peter Hogfeldt 2003-08-18 PA3
-
-THE IC PROTOCOL
-
-1 INTRODUCTION
-
- The IDL Compiler (IC) transforms Interface Definition Language
- (IDL) specifications files to interface code for Erlang, C, and
- Java. The Erlang language mapping is described in the Orber
- documentation, while the other mappings are described in the IC
- documentation (they are of course in accordance with the CORBA C
- and Java language mapping specifications, with some restrictions).
-
- The most important parts of an IDL specification are the operation
- declarations. An operation defines what information a client
- provides to a server, and what information (if any) the client
- gets back from the server. We consider IDL operations and language
- mappings in section 2.
-
- What we here call the IC protocol, is the description of messages
- exchanged between IC end-points (client and servers). It is valid
- for all IC back-ends, except the 'erl_plain' and 'erl_corba'
- back-ends. The protocol is described in section 3.
-
- The IC protocol is in turn embedded into the Erlang gen_server
- protocol, which is described in section 4.
-
- Finally, the gen_server protocol is embedded in the Erlang
- distribution protocol. Pertinent parts of that protocol is
- described in section 5.
-
-
-2 LANGUAGE MAPPINGS AND IDL OPERATIONS
-
-2.1 IDL Operations
-
- An IDL operation is declared as follows:
-
- [oneway] RetType Op(in IType1 I1, in IType2 I2, ..., in ITypeN IN,
- out OType1 O1, out OType2 O2, ..., out OTypeM OM)
- N, M = 0, 1, 2, ... (2.1.1)
-
- `Op' is the operation name, RetType is the return type, and ITypei,
- i = 1, 2, ..., N, and OTypej, j = 1, 2, ..., M, are the `in' types
- and `out' types, respectively. The values I1, I2, ..., IN are
- provided by the caller, and the value of RetType, and the values
- O1, O2, ..., OM, are provided as results to the caller.
-
- The types can be any basic types or derived types declared in the
- IDL specification of which the operation declaration is a part.
-
- If the RetType has the special name `void' there is no return
- value (but there might still be result values O1, 02, ..., OM).
-
- The `in' and `out' parameters can be declared in any order, but
- for clarity we have listed all `in' parameters before the `out'
- parameters in the declaration above.
-
- If the keyword `oneway' is present, the operation is a cast, i.e.
- there is no confirmation of the operation, and consequently there
- must be no result values: RetType must be equal to `void', and M =
- 0 must hold.
-
- Otherwise the operation is a call, i.e. it is confirmed (or else
- an exception is raised).
-
- Note carefully that an operation declared without `oneway' is
- always a call, even if RetType is `void' and M = 0.
-
-2.2 Language Mappings
-
- There are several CORBA Language Mapping specifications. These are
- about mapping interfaces to various programming languages. IC
- supports the CORBA C and Java mapping specifications, and the
- Erlang language mapping specified in the Orber documentation.
-
- Excerpt from "6.4 Basic OMG IDL Types" in the Orber User's Guide:
-
- Functions with return type void will return the atom ok.
-
- Excerpt from "6.13 Invocations of Operations" in the Orber User's Guide:
-
- A function call will invoke an operation. The first parameter
- of the function should be the object reference and then all in
- and inout parameters follow in the same order as specified in
- the IDL specification. The result will be a return value
- unless the function has inout or out parameters specified; in
- which case, a tuple of the return value, followed by the
- parameters will be returned.
-
- Hence the function that is mapped from an IDL operation to Erlang
- always have a return value (an Erlang function always has). That
- fact has influenced the IC protocol, in that there is always a
- return value (which is 'ok' if the return type was declared 'void').
-
-
-3 IC PROTOCOL
-
- Given the operation declaration (2.1.1) the IC protocol maps to
- messages as follows, defined in terms of Erlang terms.
-
-3.1 Call (Request/Reply, i.e. not oneway)
-
- request: Op atom() N = 0
- {Op, I1, I2, ..., IN} tuple() N > 0
- (3.1.1)
-
- reply: Ret M = 0
- {Ret, O1, O2, ..., OM} M > 0
- (3.1.2)
-
- Notice; Even if the RetType of the operation Op is declared to be
- 'void', a return value 'ok' is returned in the reply message. That
- return value is of no significance, and is therefore ignored (note
- however that a C server back-end returns the atom 'void' instead
- of 'ok').
-
-3.2 Cast (oneway)
-
- notification: Op atom() N = 0
- {Op, I1, I2, ..., IN} tuple() N > 0
- (3.2.1)
- (There is of course no return message).
-
-3.3 Propagation of Exceptions
-
- Currently there is no propagation of exceptions from the server to
- the client. As it is now a an exception detected by the server
- will hang the client in a receive. That is unacceptable.
-
- Exception propagation is only meaningful for Call (request/reply).
-
-
-4 GEN_SERVER PROTOCOL
-
- Most of the IC generated code deals with encoding and decoding the
- gen_server protocol.
-
-4.1 Call
-
- request: {'$gen_call', {self(), Ref}, Request} (4.1.1)
-
- reply: {Ref, Reply} (4.1.2)
-
- where Request and Reply are the messages defined in 3.1 Call.
-
-4.2 Cast
-
- notification: {'$gen_cast', Notification} (4.2.1)
-
- where Notification is the message defined in 3.2 Cast.
-
-
-5 ERLANG DISTRIBUTION PROTOCOL
-
- Messages (of interest here) between Erlang nodes are of the form:
-
- Len(4), Type(1), CtrlBin(N), MsgBin(M) (5.1)
-
- Type is equal to 112 = PASS_THROUGH.
-
- CtrlBin and MsgBin are Erlang terms in binary form (as if created
- by term_to_binary/1), whence for each of them the first byte is
- equal to 131 = VERSION_MAGIC.
-
- CtrlBin (of interest here) contains the SEND and REG_SEND control
- messages, which are binary forms of the Erlang terms
-
- {2, Cookie, ToPid} , (5.2)
-
- and
-
- {6, FromPid, Cookie, ToName} , (5.3)
-
- respectively.
-
- The CtrlBin(N) message is read and written by erl_interface code
- (C), j_interface code (Java), or the Erlang distribution
- implementation, which are invoked from IC generated code.
-
- The MsgBin(N) is the "real" message, i.e. of the form described
- in section 4.
diff --git a/lib/ic/java_src/Makefile b/lib/ic/java_src/Makefile
deleted file mode 100644
index 86d1e54fff..0000000000
--- a/lib/ic/java_src/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(ORBER_VSN)
-
-# ----------------------------------------------------
-# Common Macros
-# ----------------------------------------------------
-
-SUB_DIRECTORIES = com/ericsson/otp/ic
-
-SPECIAL_TARGETS =
-
-# ----------------------------------------------------
-# Default Subdir Targets
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_subdir.mk
-
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/Any.java b/lib/ic/java_src/com/ericsson/otp/ic/Any.java
deleted file mode 100644
index d90b942877..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/Any.java
+++ /dev/null
@@ -1,1026 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-package com.ericsson.otp.ic;
-
-
-/**
-
-The Any class is the java mapping of the any OMG-IDL type.
-
-
-**/
-
-
-public class Any {
-
- // Typecode value holder
- protected TypeCode tcV;
-
- // Primitive value holder
- protected java.lang.String stringV;
- protected byte byteV;
- protected boolean booleanV;
- protected char charV;
- protected short shortV;
- protected int intV;
- protected long longV;
- protected float floatV;
- protected double doubleV;
-
- // Streams used for user defined types
- protected com.ericsson.otp.erlang.OtpInputStream is;
- protected com.ericsson.otp.erlang.OtpOutputStream os;
-
-
- // Constructor
- public Any() {
- tcV = null;
- }
-
- // Equal function
-
- /**
- Any comparison method
- @return true if the input Any is equal to the object, false otherwize
- **/
- public boolean equal(com.ericsson.otp.ic.Any _any) {
-
- int _is1Len,_is2Len;
- byte _compressed[];
- com.ericsson.otp.erlang.OtpInputStream _is1,_is2;
- TypeCode _tc = _any.type();
-
- if (!tcV.equal(_tc))
- return false;
-
- try {
-
- TCKind _tck = _tc.kind();
-
- switch (_tck.value()) {
-
- case TCKind._tk_short:
- return (_any.extract_short() == shortV);
-
- case TCKind._tk_ushort:
- return (_any.extract_ushort() == shortV);
-
- case TCKind._tk_long:
- return (_any.extract_long() == intV);
-
- case TCKind._tk_longlong:
- return (_any.extract_longlong() == longV);
-
- case TCKind._tk_ulong:
- return (_any.extract_ulong() == intV);
-
- case TCKind._tk_ulonglong:
- return (_any.extract_ulonglong() == longV);
-
- case TCKind._tk_float:
- return equal(_any.extract_float(),floatV);
-
- case TCKind._tk_double:
- return equal(_any.extract_double(),doubleV);
-
- case TCKind._tk_boolean:
- return (_any.extract_boolean() == booleanV);
-
- case TCKind._tk_char:
- return (_any.extract_char() == charV);
-
- case TCKind._tk_wchar:
- return (_any.extract_wchar() == charV);
-
- case TCKind._tk_octet:
- return (_any.extract_octet() == byteV);
-
- case TCKind._tk_string:
- return (_any.extract_string().compareTo(stringV) == 0);
-
- case TCKind._tk_wstring:
- return (_any.extract_wstring().compareTo(stringV) == 0);
-
- case TCKind._tk_sequence:
-
- _is1 = new com.ericsson.otp.erlang.OtpInputStream(os.toByteArray());
-
- _is2 = _any.extract_Streamable();
-
- if (_is1.peek() != _is2.peek()) {
-
- // _is1's sequence is compressed to string
- if(_is1.peek() == com.ericsson.otp.erlang.OtpExternal.stringTag) {
-
- _compressed = (_is1.read_string()).getBytes();
- _is1Len = _compressed.length;
-
- _is2.read_list_head();
-
- for(int i = 0; i < _is1Len; i++) {
- if ((long)(_compressed[i] & 0xff) != _is2.read_long())
- return false;
- }
-
- _is2.read_nil();
- }
- else { // _is2's sequence is compressed to string
-
- _compressed = (_is2.read_string()).getBytes();
- _is2Len = _compressed.length;
-
- _is1.read_list_head();
-
- for(int i = 0; i < _is2Len; i++)
- if ((long)(_compressed[i] & 0xff) != _is1.read_long())
- return false;
-
- _is1.read_nil();
- }
- }
- else { // None of them is compressed
-
- _is2Len = _is2.available();
-
- if (_is1.available() != _is2Len)
- return false;
-
- for(int i = 0; i < _is2Len; i++) {
- if (_is1.read() != _is2.read())
- return false;
- }
- }
-
- return true;
-
- case TCKind._tk_struct:
- case TCKind._tk_union:
- case TCKind._tk_array:
- case TCKind._tk_enum:
-
- _is1 = new com.ericsson.otp.erlang.OtpInputStream(os.toByteArray());
-
- _is2 = _any.extract_Streamable();
-
- _is2Len = _is2.available();
-
- if (_is1.available() != _is2Len)
- return false;
-
- for(int i = 0; i < _is2Len; i++) {
- if (_is1.read() != _is2.read())
- return false;
- }
-
- return true;
-
- // Not used in real
- case TCKind._tk_any:
- case TCKind._tk_void:
- case TCKind._tk_atom:
- case TCKind._tk_null:
- case TCKind._tk_TypeCode:
- case TCKind._tk_Principal:
- case TCKind._tk_objref:
- case TCKind._tk_alias:
- case TCKind._tk_except:
- case TCKind._tk_longdouble:
- case TCKind._tk_fixed:
- return true;
-
- default :
- return false;
-
- }
- } catch (Exception e) {
- //e.printStackTrace();
- return false;
- }
-
- }
-
-
- /* Equal function for floats ( relative diff ) */
- boolean equal(float x, float y) {
-
- if (x != 0)
- return (java.lang.Math.abs((x-y)/x) < 1.0E-15);
-
- if (y != 0)
- return (java.lang.Math.abs((y-x)/y) < 1.0E-15);
-
- return (x==y);
- }
-
- /* Equal function for doubles ( relative diff ) */
- boolean equal(double x, double y) {
-
- if (x != 0)
- return (java.lang.Math.abs((x-y)/x) < 1.0E-15);
-
- if (y != 0)
- return (java.lang.Math.abs((y-x)/y) < 1.0E-15);
-
- return (x==y);
- }
-
-
-
- /**
- TypeCode accessor method
- @return the Any's TypeCode
- **/
- public TypeCode type() {
- return tcV;
- }
-
-
- /**
- TypeCode insertion method
- **/
- public void type(TypeCode _tc) {
- tcV = _tc;
- }
-
-
- /* Value accessors */
-
- /**
- Reads a value from the stream, according to the inserted TypeCode
- **/
- public void read_value(com.ericsson.otp.erlang.OtpInputStream _is,
- TypeCode _tc)
- throws java.lang.Exception {
-
- tcV = _tc;
-
- switch(tcV.kind().value()) {
-
- case TCKind._tk_short :
- shortV = _is.read_short();
- break;
- case TCKind._tk_ushort :
- shortV = _is.read_ushort();
- break;
- case TCKind._tk_long :
- intV = _is.read_int();
- break;
- case TCKind._tk_ulong :
- intV = _is.read_uint();
- break;
- case TCKind._tk_longlong :
- longV = _is.read_long();
- break;
- case TCKind._tk_ulonglong :
- longV = _is.read_ulong();
- break;
- case TCKind._tk_float :
- floatV = _is.read_float();
- break;
- case TCKind._tk_double :
- doubleV = _is.read_double();
- break;
- case TCKind._tk_boolean :
- booleanV = _is.read_boolean();
- break;
- case TCKind._tk_char :
- case TCKind._tk_wchar :
- charV = _is.read_char();
- break;
- case TCKind._tk_octet :
- byteV = _is.read_byte();
- break;
- case TCKind._tk_string :
- case TCKind._tk_wstring :
- stringV = _is.read_string();
- break;
- case TCKind._tk_atom :
- stringV = _is.read_atom();
- break;
- case TCKind._tk_void :
- _is.read_atom();
- break;
-
- /*
- * Not supported types
- */
- case TCKind._tk_any :
- case TCKind._tk_null :
- case TCKind._tk_TypeCode :
- case TCKind._tk_Principal :
- case TCKind._tk_objref :
- case TCKind._tk_alias :
- case TCKind._tk_except :
- case TCKind._tk_longdouble :
- case TCKind._tk_fixed :
- throw new java.lang.Exception("Unsupported type");
-
- default: // User defined type
-
- if (os == null)
- os = new com.ericsson.otp.erlang.OtpOutputStream();
- else
- os.reset();
-
- try {
- read_user_defined(_is, _tc);
- is = new com.ericsson.otp.erlang.OtpInputStream(os.toByteArray());
- } catch (Exception e) {
- throw new java.lang.Exception("BAD VALUE");
- }
- }
-
- }
-
- void read_user_defined(com.ericsson.otp.erlang.OtpInputStream _is, TypeCode _tc)
- throws java.lang.Exception {
-
- TypeCode memberTC = null;
- int len = -1;
- int __tag;
-
- switch(_tc.kind().value()) {
-
- case TCKind._tk_short :
- os.write_short(_is.read_short());
- break;
- case TCKind._tk_ushort :
- os.write_ushort(_is.read_ushort());
- break;
- case TCKind._tk_long :
- os.write_int(_is.read_int());
- break;
- case TCKind._tk_longlong :
- os.write_long(_is.read_long());
- break;
- case TCKind._tk_ulong :
- os.write_uint(_is.read_uint());
- break;
- case TCKind._tk_ulonglong :
- os.write_ulong(_is.read_ulong());
- break;
- case TCKind._tk_float :
- os.write_float(_is.read_float());
- break;
- case TCKind._tk_double :
- os.write_double(_is.read_double());
- break;
- case TCKind._tk_boolean :
- os.write_boolean(_is.read_boolean());
- break;
- case TCKind._tk_char :
- case TCKind._tk_wchar :
- os.write_char(_is.read_char());
- break;
- case TCKind._tk_octet :
- os.write_byte(_is.read_byte());
- break;
- case TCKind._tk_string :
- case TCKind._tk_wstring :
- os.write_string(_is.read_string());
- break;
-
- case TCKind._tk_struct:
- len = _is.read_tuple_head();
- os.write_tuple_head(len);
- os.write_atom(_is.read_atom());
- // Member list
- len -=1;
- for(int i=0; i<len; i++)
- read_user_defined(_is,_tc.member_type(i));
- break;
-
- case TCKind._tk_union:
- os.write_tuple_head(_is.read_tuple_head());
- os.write_atom(_is.read_atom());
-
- int __mlen = _tc.member_count();
- __tag = _is.peek();
- boolean __found = false;
-
- switch (__tag) {
- case (com.ericsson.otp.erlang.OtpExternal.atomTag):
- case (com.ericsson.otp.erlang.OtpExternal.atomUtf8Tag):
- case (com.ericsson.otp.erlang.OtpExternal.smallAtomUtf8Tag):
- java.lang.String __elabel = _is.read_atom(); // Enumerant or Boolean
- os.write_atom(__elabel);
-
- for (int i=0; i<__mlen; i++) {
- java.lang.String __mlabel;
- if (_tc.member_label(i).type().kind().value() == TCKind._tk_string)
- __mlabel = _tc.member_label(i).extract_string();
- else // Default
- __mlabel = _tc.member_label(i).extract_atom();
-
- if (__elabel.compareTo(__mlabel)==0) {
- read_user_defined(_is,_tc.member_type(i));
- i = __mlen;
- __found = true;
- }
- }
- break;
-
- default: // Integer type
- long __ilabel = _is.read_long();
- os.write_long(__ilabel);
-
- for (int i=0; i<__mlen; i++) {
- boolean __itype = true;
- long __mlabel = 0;
-
- switch (_tc.member_label(i).type().kind().value()) {
-
- case TCKind._tk_short :
- __mlabel = _tc.member_label(i).extract_short();
- break;
- case TCKind._tk_ushort :
- __mlabel = _tc.member_label(i).extract_ushort();
- break;
- case TCKind._tk_long :
- __mlabel = _tc.member_label(i).extract_long();
- break;
- case TCKind._tk_longlong :
- __mlabel = _tc.member_label(i).extract_longlong();
- break;
- case TCKind._tk_ulong :
- __mlabel = _tc.member_label(i).extract_ulong();
- break;
- case TCKind._tk_ulonglong :
- __mlabel = _tc.member_label(i).extract_ulonglong();
- break;
- case TCKind._tk_char :
- __mlabel = _tc.member_label(i).extract_char();
- break;
- case TCKind._tk_wchar :
- __mlabel = _tc.member_label(i).extract_wchar();
- break;
-
- default : // Default label
- __itype = false;
-
- }
-
- if (__itype) {
- if (__ilabel == __mlabel) {
- read_user_defined(_is,_tc.member_type(i));
- i = __mlen;
- __found = true;
- }
- }
- }
- }
-
- // Use the default label instead
- if (!__found)
- read_user_defined(_is,_tc.member_type(_tc.default_index()));
-
- break;
-
- case TCKind._tk_sequence:
- __tag = _is.peek();
-
- switch(__tag) {
- case com.ericsson.otp.erlang.OtpExternal.stringTag:
- os.write_string(_is.read_string());
- break;
- default:
- len = _is.read_list_head();
- os.write_list_head(len);
-
- for (int i=0; i<len; i++)
- read_user_defined(_is,_tc.content_type());
-
- _is.read_nil();
- os.write_nil();
- }
- break;
-
- case TCKind._tk_array:
- len = _is.read_tuple_head();
- os.write_tuple_head(len);
- for (int i=0; i<len; i++)
- read_user_defined(_is,_tc.content_type());
- break;
-
- case TCKind._tk_enum:
- os.write_atom(_is.read_atom());
- break;
-
- case TCKind._tk_void :
- os.write_atom(_is.read_atom());
- break;
-
- case TCKind._tk_any :
- AnyHelper.marshal(os,AnyHelper.unmarshal(_is));
- break;
-
- /*
- * Not supported types
- */
- default :
- throw new java.lang.Exception("");
-
- }
-
- }
-
-
- /**
- Writes the Any's value to the ouput stream
- **/
- public void write_value(com.ericsson.otp.erlang.OtpOutputStream _os)
- throws java.lang.Exception {
-
- switch(tcV.kind().value()) {
-
- case TCKind._tk_short :
- _os.write_short(shortV);
- break;
- case TCKind._tk_ushort :
- _os.write_ushort(shortV);
- break;
- case TCKind._tk_long :
- _os.write_int(intV);
- break;
- case TCKind._tk_ulong :
- _os.write_uint(intV);
- break;
- case TCKind._tk_longlong :
- _os.write_long(longV);
- break;
- case TCKind._tk_ulonglong :
- _os.write_ulong(longV);
- break;
- case TCKind._tk_float :
- _os.write_float(floatV);
- break;
- case TCKind._tk_double :
- _os.write_double(doubleV);
- break;
- case TCKind._tk_boolean :
- _os.write_boolean(booleanV);
- break;
- case TCKind._tk_char :
- case TCKind._tk_wchar :
- _os.write_char(charV);
- break;
- case TCKind._tk_octet :
- _os.write_byte(byteV);
- break;
- case TCKind._tk_string :
- case TCKind._tk_wstring :
- _os.write_string(stringV);
- break;
- case TCKind._tk_atom :
- _os.write_atom(stringV);
- break;
- case TCKind._tk_void :
- _os.write_atom("ok");
- break;
-
- /*
- * Not supported types
- */
- case TCKind._tk_any :
- case TCKind._tk_null :
- case TCKind._tk_TypeCode :
- case TCKind._tk_Principal :
- case TCKind._tk_objref :
- case TCKind._tk_alias :
- case TCKind._tk_except :
- case TCKind._tk_longdouble :
- case TCKind._tk_fixed :
- throw new java.lang.Exception("BAD KIND");
-
- default:
- _os.write(os.toByteArray());
- }
- }
-
-
- /*
- * Insert and extract each primitive type
- */
-
- /* short */
-
- /**
- Short value extractor method
- @return short, the value of Any
- **/
- public short extract_short()
- throws java.lang.Exception {
- if (tcV.kind() == TCKind.tk_short)
- return shortV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Short value insertion method
- **/
- public void insert_short(short s) {
- shortV = s;
- tcV = new TypeCode(TCKind.tk_short);
- };
-
-
- /* long */
- /**
- Long value extractor method
- @return int, the value of Any
- **/
- public int extract_long()
- throws java.lang.Exception {
- if (tcV.kind() == TCKind.tk_long)
- return intV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Long value insertion method
- **/
- public void insert_long(int i){
- intV = i;
- tcV = new TypeCode(TCKind.tk_long);
- }
-
-
-
- /* long long */
- /**
- Long Long value extractor method
- @return long, the value of Any
- **/
- public long extract_longlong()
- throws java.lang.Exception {
- if (tcV.kind() == TCKind.tk_longlong)
- return longV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Long Long value insertion method
- **/
- public void insert_longlong(long l){
- longV = l;
- tcV = new TypeCode(TCKind.tk_longlong);
- }
-
-
- /* ushort */
- /**
- Unsigned Short value extractor method
- @return short, the value of Any
- **/
- public short extract_ushort()
- throws java.lang.Exception {
- if (tcV.kind() == TCKind.tk_ushort)
- return shortV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Unsigned Short value insertion method
- **/
- public void insert_ushort(short s){
- shortV = s;
- tcV = new TypeCode(TCKind.tk_ushort);
- }
-
-
- /* ulong */
-
- /**
- Unsigned Long value extractor method
- @return int, the value of Any
- **/
- public int extract_ulong()
- throws java.lang.Exception{
- if (tcV.kind() == TCKind.tk_ulong)
- return intV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Unsigned Long value insertion method
- **/
- public void insert_ulong(int i){
- intV = i;
- tcV = new TypeCode(TCKind.tk_ulong);
- }
-
-
-
-
- /* unsigned long long */
- /**
- Unsigned Long Long value extractor method
- @return long, the value of Any
- **/
- public long extract_ulonglong()
- throws java.lang.Exception {
- if (tcV.kind() == TCKind.tk_ulonglong)
- return longV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Unsigned Long Long value insertion method
- **/
- public void insert_ulonglong(long l){
- longV = l;
- tcV = new TypeCode(TCKind.tk_ulonglong);
- }
-
-
- /* float */
- /**
- Float value extractor method
- @return float, the value of Any
- **/
- public float extract_float()
- throws java.lang.Exception{
- if (tcV.kind() == TCKind.tk_float)
- return floatV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Float value insertion method
- **/
- public void insert_float(float f){
- floatV = f;
- tcV = new TypeCode(TCKind.tk_float);
- }
-
-
- /* double */
- /**
- Double value extractor method
- @return double, the value of Any
- **/
- public double extract_double()
- throws java.lang.Exception{
- if (tcV.kind() == TCKind.tk_double)
- return doubleV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Double value insertion method
- **/
- public void insert_double(double d){
- doubleV = d;
- tcV = new TypeCode(TCKind.tk_double);
- }
-
-
- /* boolean */
- /**
- Boolean value extractor method
- @return boolean, the value of Any
- **/
- public boolean extract_boolean()
- throws java.lang.Exception{
- if (tcV.kind() == TCKind.tk_boolean)
- return booleanV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Boolean value insertion method
- **/
- public void insert_boolean(boolean b){
- booleanV = b;
- tcV = new TypeCode(TCKind.tk_boolean);
- }
-
-
-
- /* char */
- /**
- Char value extractor method
- @return char, the value of Any
- **/
- public char extract_char()
- throws java.lang.Exception{
- if (tcV.kind() == TCKind.tk_char)
- return charV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Char value insertion method
- **/
- public void insert_char(char c) {
- charV = c;
- tcV = new TypeCode(TCKind.tk_char);
- }
-
-
- /* wchar */
- /**
- Wchar value extractor method
- @return char, the value of Any
- **/
- public char extract_wchar()
- throws java.lang.Exception{
- if (tcV.kind() == TCKind.tk_wchar)
- return charV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Wchar value insertion method
- **/
- public void insert_wchar(char c) {
- charV = c;
- tcV = new TypeCode(TCKind.tk_wchar);
- }
-
-
-
- /* octet */
- /**
- Octet value extractor method
- @return byte, the value of Any
- **/
- public byte extract_octet()
- throws java.lang.Exception{
- if (tcV.kind() == TCKind.tk_octet)
- return byteV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Octet value insertion method
- **/
- public void insert_octet(byte b){
- byteV = b;
- tcV = new TypeCode(TCKind.tk_octet);
- }
-
-
- /* string */
- /**
- String value extractor method
- @return String, the value of Any
- **/
- public java.lang.String extract_string()
- throws java.lang.Exception{
- if (tcV.kind() == TCKind.tk_string)
- return stringV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- String value insertion method
- **/
- public void insert_string(java.lang.String s) {
- stringV = s;
- tcV = new TypeCode(TCKind.tk_string);
- }
-
-
-
- /* wstring */
- /**
- Wstring value extractor method
- @return String, the value of Any
- **/
- public java.lang.String extract_wstring()
- throws java.lang.Exception{
- if (tcV.kind() == TCKind.tk_wstring)
- return stringV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Wstring value insertion method
- **/
- public void insert_wstring(java.lang.String s) {
- stringV = s;
- tcV = new TypeCode(TCKind.tk_wstring);
- }
-
-
-
- /* atom */
- /**
- Atom value extractor method
- @return atom, the value of Any
- **/
- public java.lang.String extract_atom()
- throws java.lang.Exception{
- if (tcV.kind() == TCKind.tk_atom)
- return stringV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Atom value insertion method
- **/
- public void insert_atom(java.lang.String s) {
- stringV = s;
- tcV = new TypeCode(TCKind.tk_atom);
- }
-
-
- /**
- Object Stream insertion method
- **/
- public void insert_Streamable(com.ericsson.otp.erlang.OtpOutputStream _os) {
- os = _os;
- }
-
- /**
- Object Stream extractor method
- @return OtpInputStream, the stream value of Any
- **/
- public com.ericsson.otp.erlang.OtpInputStream extract_Streamable() {
-
- if (is == null) {
- if (os == null)
- return null;
- else {
- is = new com.ericsson.otp.erlang.OtpInputStream(os.toByteArray());
- }
- }
-
- is.reset();
- return is;
- }
-
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/AnyHelper.java b/lib/ic/java_src/com/ericsson/otp/ic/AnyHelper.java
deleted file mode 100644
index 518087a1ed..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/AnyHelper.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-package com.ericsson.otp.ic;
-
-/**
-
-Helper class for Any, according to OMG-IDL java mapping.
-<p>Instead for write,read methods, the methods marshal respective
-unmarshal are used to denote the implementation difference.
-
-**/
-
-
-public class AnyHelper {
-
- // Constructors
- private AnyHelper() {}
-
- // Methods
- /**
- Marshal method for the Any class, encodes the Any object to the output stream.
- **/
- public static void marshal(com.ericsson.otp.erlang.OtpOutputStream _out, Any _any)
- throws java.lang.Exception {
-
- TypeCode _tc = _any.type();
-
- _out.write_tuple_head(3);
- _out.write_atom("any");
-
- TypeCode.marshal(_out, _tc);
- _any.write_value(_out);
-
- }
-
- /**
- Unmarshal method for the Any class, decodes an Any object from the stream.
- @return Any, read from the input stream
- **/
- public static Any unmarshal(com.ericsson.otp.erlang.OtpInputStream _in)
- throws java.lang.Exception {
-
- Any _value;
- TypeCode _tc;
-
- _in.read_tuple_head();
-
- if ((_in.read_atom()).compareTo("any") != 0)
- throw new java.lang.Exception("");
-
- _tc = TypeCode.unmarshal(_in);
- _value = new Any();
- _value.read_value(_in,_tc);
-
- return _value;
- }
-
-}
-
-
-
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/AnyHolder.java b/lib/ic/java_src/com/ericsson/otp/ic/AnyHolder.java
deleted file mode 100644
index e22876f51e..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/AnyHolder.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-package com.ericsson.otp.ic;
-
-/**
-
-Holder class for Any, according to OMG-IDL java mapping.
-<p>Instead for _write,_read methods, the methods _marshal respective
-_unmarshal are used to denote the implementation difference.
-
-**/
-
-final public class AnyHolder {
-
- // Instance variables
- public Any value;
-
- // Constructors
- public AnyHolder() {}
-
- public AnyHolder(Any initial) {
- value = initial;
- }
-
- // Methods
- /**
- Marshal method for the Any class, encodes the Any object to the output stream.
- **/
- public void _marshal(com.ericsson.otp.erlang.OtpOutputStream out)
- throws java.lang.Exception {
- AnyHelper.marshal(out, value);
- }
-
- /**
- Unmarshal method for the Any class, decodes an Any object from the stream and
- assigns it to the Holder value.
- **/
- public void _unmarshal(com.ericsson.otp.erlang.OtpInputStream in)
- throws java.lang.Exception {
- value = AnyHelper.unmarshal(in);
- }
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/BooleanHolder.java b/lib/ic/java_src/com/ericsson/otp/ic/BooleanHolder.java
deleted file mode 100644
index b71da196de..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/BooleanHolder.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/**
- * A Holder class for IDL's out/inout argument passing modes for boolean
- *
- */
-package com.ericsson.otp.ic;
-
-/**
-
-Holder class for Boolean, according to OMG-IDL java mapping.
-
-**/
-
-
-final public class BooleanHolder implements Holder {
- public boolean value;
-
- public BooleanHolder() {}
-
- public BooleanHolder(boolean initial) {
- value = initial;
- }
-
- /* Extra methods not in standard. */
- /**
- Comparisson method for Booleans.
- @return true if the input object equals the current object, false otherwize
- **/
- public boolean equals( Object obj ) {
- if( obj instanceof Boolean )
- return ( value == ((Boolean)obj).booleanValue());
- else
- return false;
- }
-
- /**
- Comparisson method for Booleans.
- @return true if the input boolean value equals the value of the current object, false otherwize
- **/
- public boolean equals( boolean b ) {
- return ( value == b );
- }
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/ByteHolder.java b/lib/ic/java_src/com/ericsson/otp/ic/ByteHolder.java
deleted file mode 100644
index 7c79e8f90d..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/ByteHolder.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/**
- * A Holder class for IDL's out/inout argument passing modes for byte
- *
- */
-package com.ericsson.otp.ic;
-
-/**
-
-Holder class for Byte, according to OMG-IDL java mapping.
-
-**/
-
-final public class ByteHolder implements Holder {
- public byte value;
-
- public ByteHolder() {}
-
- public ByteHolder(byte initial) {
- value = initial;
- }
-
- /* Extra methods not in standard. */
- /**
- Comparisson method for Bytes.
- @return true if the input object equals the current object, false otherwize
- **/
- public boolean equals( Object obj ) {
- if( obj instanceof Byte )
- return ( value == ((Byte)obj).byteValue());
- else
- return false;
- }
-
- /**
- Comparisson method for Byte.
- @return true if the input boolean value equals the value of the current object, false otherwize
- **/
- public boolean equals( byte b ) {
- return ( value == b);
- }
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/CharHolder.java b/lib/ic/java_src/com/ericsson/otp/ic/CharHolder.java
deleted file mode 100644
index 81d8c6ac73..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/CharHolder.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/**
- * A Holder class for IDL's out/inout argument passing modes for char
- *
- */
-package com.ericsson.otp.ic;
-
-
-/**
-
-Holder class for Char, according to OMG-IDL java mapping.
-
-**/
-
-
-final public class CharHolder implements Holder {
- public char value;
-
- public CharHolder() {}
-
- public CharHolder(char initial) {
- value = initial;
- }
-
- /* Extra methods not in standard. */
- /**
- Comparisson method for Chars.
- @return true if the input object equals the current object, false otherwize
- **/
- public boolean equals( Object obj ) {
- if( obj instanceof Character )
- return ( value == ((Character)obj).charValue());
- else
- return false;
- }
-
- /**
- Comparisson method for Chars.
- @return true if the input char value equals the value of the current object, false otherwize
- **/
- public boolean equals( char c ) {
- return ( value == c);
- }
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/DoubleHolder.java b/lib/ic/java_src/com/ericsson/otp/ic/DoubleHolder.java
deleted file mode 100644
index 6daaa25aa8..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/DoubleHolder.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/**
- * A Holder class for IDL's out/inout argument passing modes for double
- *
- */
-package com.ericsson.otp.ic;
-
-/**
-
-Holder class for Double, according to OMG-IDL java mapping.
-
-**/
-
-final public class DoubleHolder implements Holder {
- public double value;
-
- public DoubleHolder() {}
-
- public DoubleHolder(double initial) {
- value = initial;
- }
-
- /* Extra methods not in standard. */
- /**
- Comparisson method for Doubles.
- @return true if the input object equals the current object, false otherwize
- **/
- public boolean equals( Object obj ) {
- if( obj instanceof Double )
- return ( value == ((Double)obj).doubleValue());
- else
- return false;
- }
-
- /**
- Comparisson method for Doubles.
- @return true if the input double value equals the value of the current object, false otherwize
- **/
- public boolean equals( double d ) {
- return ( value == d);
- }
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/Environment.java b/lib/ic/java_src/com/ericsson/otp/ic/Environment.java
deleted file mode 100644
index bffa0e27e6..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/Environment.java
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/**
- * The Environment class for Java IDL
- *
- */
-package com.ericsson.otp.ic;
-
-/**
-
- The Environment class handles communication
- setup and stub state. The methods of this class
- are specially designed for the generated stubs.
- This class must be used when designing asynchronous
- message passing.
-
- **/
-
-
-public class Environment {
-
- // Private variables
- private com.ericsson.otp.erlang.OtpSelf self;
- private com.ericsson.otp.erlang.OtpPeer peer;
- private java.lang.Object server;
- private java.lang.String cookie;
- private com.ericsson.otp.erlang.OtpConnection connection;
- private com.ericsson.otp.erlang.OtpErlangRef send_ref; /* Client side send reference */
- private com.ericsson.otp.erlang.OtpErlangRef receive_ref; /* Client side received reference */
- private com.ericsson.otp.erlang.OtpErlangPid clientP;
- private com.ericsson.otp.erlang.OtpErlangPid serverP;
- private com.ericsson.otp.erlang.OtpOutputStream os; /* Output stream */
- private com.ericsson.otp.erlang.OtpInputStream is; /* Input stream */
- private boolean stopped;
-
- // Private variables used by server only
- private int tag;
- private java.lang.String operation;
- private java.lang.String type;
- private com.ericsson.otp.erlang.OtpErlangRef ref; /* Server side client reference */
- private com.ericsson.otp.erlang.OtpErlangPid caller; /* Server side client pid */
-
- // Tags to distiguish client / server environments
- private boolean clientT;
- private boolean serverT;
-
-
- /**
- Client stub side constructor.
- **/
- public Environment(com.ericsson.otp.erlang.OtpSelf _Self,
- com.ericsson.otp.erlang.OtpPeer _Peer,
- java.lang.Object _Server) throws java.lang.Exception {
-
- init();
- clientT = true;
- self = _Self;
- peer = _Peer;
- server = _Server;
- os = new com.ericsson.otp.erlang.OtpOutputStream();
- }
-
-
- /**
- Client stub side constructor.
- **/
- public Environment(java.lang.String _SelfNode,
- java.lang.String _PeerNode,
- java.lang.String _Cookie,
- java.lang.Object _Server) throws java.lang.Exception {
-
- init();
- clientT = true;
- self = new com.ericsson.otp.erlang.OtpSelf(_SelfNode, _Cookie);
- peer = new com.ericsson.otp.erlang.OtpPeer(_PeerNode);
- cookie = _Cookie;
- server = _Server;
- os = new com.ericsson.otp.erlang.OtpOutputStream();
- }
-
-
- /**
- Client stub side constructor.
- **/
- public Environment(com.ericsson.otp.erlang.OtpConnection _connection,
- java.lang.Object _Server) throws java.lang.Exception {
-
- init();
- clientT = true;
- self = _connection.self();
- peer = _connection.peer();
- connection = _connection;
- server = _Server;
- os = new com.ericsson.otp.erlang.OtpOutputStream();
- }
-
-
- /**
- Server skeleton side constructor.
- **/
- public Environment() throws java.lang.Exception {
-
- init();
- serverT = true;
- stopped = false;
- os = new com.ericsson.otp.erlang.OtpOutputStream();
-
- }
-
-
- /* Communication toolbox */
-
- /**
- Client stub side connector.
- **/
- public void connect() throws java.lang.Exception {
-
- if (connection == null)
- connection = self.connect(peer);
-
- clientP = self.createPid(); /* This is not perfect */
- send_ref = self.createRef();
-
- }
-
- /**
- Reconnects a client by closing existing connection
- and connecting.
- **/
- public void reconnect() throws java.lang.Exception {
-
- if (connection.isConnected())
- connection.close();
-
- connection = self.connect(peer);
-
- }
-
- /**
- Closes the established connection.
- **/
- public void disconnect() {
-
- connection.close();
-
- }
-
-
- /**
- Client side message sender.
- **/
- public void send() throws java.lang.Exception {
-
- if (server instanceof java.lang.String)
- connection.sendBuf((java.lang.String)server, os);
- else
- connection.sendBuf((com.ericsson.otp.erlang.OtpErlangPid)server, os);
-
- }
-
-
- /**
- Client message receiver.
- **/
- public void receive() throws java.lang.Exception {
-
- is = connection.receiveBuf();
-
- if (clientT) { // If client, decode message reference too
- is.read_tuple_head();
- receive_ref = is.read_ref();
- }
- }
-
-
- /**
- Universal message receiver.
- **/
- public void receive(com.ericsson.otp.erlang.OtpConnection _connection) throws java.lang.Exception {
-
- is = _connection.receiveBuf();
-
- if (clientT) { // If client, decode message reference too
- is.read_tuple_head();
- receive_ref = is.read_ref();
- }
- }
-
-
- /* Accessors */
-
- /**
- Server RegName/OtpErlangPid accessor.
- Used to access the server Reg/Pid, which
- initiated the connection.
- @return java.lang.Object, the server for the active OtpConnection.
- **/
- public java.lang.Object server() {
-
- return server;
-
- }
-
- /**
- Caller identity accessor. Used by a server stub to access the
- caller identity of the received message.
- @return OtpErlangPid, the caller identity.
- **/
- public com.ericsson.otp.erlang.OtpErlangPid caller_pid() {
-
- return clientP;
-
- }
-
-
- /**
- Received message reference accessor. Used by a server stub to access the
- reference of the received message.
- @return OtpErlangRef, the reference of the received message.
- **/
- public com.ericsson.otp.erlang.OtpErlangRef received_ref() {
-
- return receive_ref;
-
- }
-
-
- /* Encoders */
-
- /**
- Client Pid Encoder. Used by a server stub to encode the
- enclosed client process identity.
- **/
- public void write_client_pid() {
-
- os.write_pid(clientP.node(),clientP.id(),clientP.serial(),clientP.creation());
-
- }
-
- /**
- Client Ref Encoder. Used by a server stub to encode the
- enclosed client message reference.
- **/
- public void write_client_ref() {
-
- os.write_ref(send_ref.node(),send_ref.id(),send_ref.creation());
-
- }
-
-
-
- /* Field access functions */
-
- /**
- Output Stream accessor.
- @return OtpOutputStream, the enclosed output stream.
- **/
- public com.ericsson.otp.erlang.OtpOutputStream getOs() {
- return os;
- }
-
- /**
- Input Stream accessor.
- @return OtpInputStream, the enclosed input stream.
- **/
- public com.ericsson.otp.erlang.OtpInputStream getIs() {
- return is;
- }
-
- /**
- Server skeleton side client (caller) pid accessor.
- @return OtpErlangPid, the caller process identity.
- **/
- public com.ericsson.otp.erlang.OtpErlangPid getScaller() {
- return caller;
- }
-
- /**
- Server skeleton side client call reference accessor.
- @return OtpErlangRef, the latest call message reference.
- **/
- public com.ericsson.otp.erlang.OtpErlangRef getSref() {
- return ref;
- }
-
-
-
- /* Field modifiers */
-
-
-
- /* Decoders */
-
- /**
- Decodes the message head from existing stream.
- Assignes message data to private variables of the Environment Object.
- **/
- public void uHead() throws java.lang.Exception {
- uHead(is);
- }
-
- /**
- Decodes the message head and writes over input stream.
- Assignes message data to private variables of the Environment Object.
- **/
- public void uHead(com.ericsson.otp.erlang.OtpInputStream _is) throws java.lang.Exception {
-
- is = _is;
- is.read_tuple_head();
- type = is.read_atom();
-
- if (type.equals("$gen_call")) { // Call type operation
- is.read_tuple_head();
- caller = is.read_pid();
- ref = is.read_ref();
- tag = is.peek();
-
- switch (tag) {
- case com.ericsson.otp.erlang.OtpExternal.atomTag:
- case com.ericsson.otp.erlang.OtpExternal.atomUtf8Tag:
- case com.ericsson.otp.erlang.OtpExternal.smallAtomUtf8Tag:
- operation = is.read_atom();
- break;
- default:
- is.read_tuple_head();
- operation = is.read_atom();
- }
- } else { // Cast type operation
- tag = is.peek();
- switch (tag) {
- case com.ericsson.otp.erlang.OtpExternal.atomTag:
- case com.ericsson.otp.erlang.OtpExternal.atomUtf8Tag:
- case com.ericsson.otp.erlang.OtpExternal.smallAtomUtf8Tag:
- operation = is.read_atom();
- break;
- default:
- is.read_tuple_head();
- operation = is.read_atom();
- }
- }
- }
-
- /**
- Operation label accessor.
- @return int, the label hash value.
- **/
- public int uLabel(java.util.Dictionary _operations) {
-
- java.lang.Integer __label =
- (java.lang.Integer) _operations.get(operation);
-
- if(__label == null)
- return -1;
-
- return __label.intValue();
- }
-
-
-
- /* Controllers */
-
- /**
- Operation controller.
- @return boolean, true if the operation variable found in Environment class
- is supported in the input operation dictionary, false otherwize.
- **/
- public boolean validOp(java.util.Dictionary _operations) {
-
- if((_operations.get(operation)) == null)
- return false;
-
- return true;
- }
-
-
- /**
- Server stop request controller.
- @return boolean, true if there is a client request for the server
- to be stopped, false otherwize.
- **/
- public boolean isStopped() {
- return stopped;
- };
-
-
-
- /* Destroy functions */
-
- /*
- Creates and sends a stop message.
- Called by client stub to terminate the server.
- */
- public void client_stop_server()
- throws java.lang.Exception {
-
- // Message header assembly
- os.reset();
- os.write_tuple_head(2);
- os.write_atom("$gen_cast");
-
- os.write_atom("stop");
-
- send();
-
- }
-
- /*
- Sets the stop flag for the server.
- Called by server skeleton when stop message is received.
- */
- public void server_stop_server() {
-
- // Note at server is dead !
- stopped = true;
- }
-
-
- /* Private methods */
-
- /**
- Private variable initialization.
- **/
- public void init() {
-
- clientT = false;
- serverT = false;
- stopped = false;
- self = null;
- peer = null;
- server = null;
- cookie = null;
- connection = null;
- clientP = null;
- serverP = null;
- send_ref = null;
- receive_ref = null;
- os = null;
- is = null;
-
- tag = -1;
- operation = null;
- type = null;
-
- };
-
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/FloatHolder.java b/lib/ic/java_src/com/ericsson/otp/ic/FloatHolder.java
deleted file mode 100644
index c804973ad6..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/FloatHolder.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/**
- * A Holder class for IDL's out/inout argument passing modes for float
- *
- */
-package com.ericsson.otp.ic;
-
-/**
-
-Holder class for Float, according to OMG-IDL java mapping.
-
-**/
-
-
-final public class FloatHolder implements Holder {
- public float value;
-
- public FloatHolder() {}
-
- public FloatHolder(float initial) {
- value = initial;
- }
-
- /* Extra methods not in standard. */
- /**
- Comparisson method for Floats.
- @return true if the input object equals the current object, false otherwize
- **/
- public boolean equals( Object obj ) {
- if( obj instanceof Float )
- return ( value == ((Float)obj).floatValue());
- else
- return false;
- }
-
- /**
- Comparisson method for Floats.
- @return true if the input float value equals the value of the current object, false otherwize
- **/
- public boolean equals( float f ) {
- return ( value == f);
- }
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/Holder.java b/lib/ic/java_src/com/ericsson/otp/ic/Holder.java
deleted file mode 100644
index a2888539a9..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/Holder.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/**
- * Holder interface class.
-*/
-package com.ericsson.otp.ic;
-import java.io.Serializable;
-
-/**
- Holder interface class.
- **/
-
-public interface Holder extends Serializable
-{
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/IntHolder.java b/lib/ic/java_src/com/ericsson/otp/ic/IntHolder.java
deleted file mode 100644
index 7327d03843..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/IntHolder.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/**
- * A Holder class for IDL's out/inout argument passing modes for long
- *
- */
-package com.ericsson.otp.ic;
-
-/**
-
-Holder class for Int, according to OMG-IDL java mapping.
-
-**/
-
-final public class IntHolder implements Holder {
- public int value;
-
- public IntHolder() {}
-
- public IntHolder(int initial) {
- value = initial;
- }
-
- /* Extra methods not in standard. */
-
- /**
- Comparisson method for Ints.
- @return true if the input object equals the current object, false otherwize
- **/
- public boolean equals( Object obj ) {
- if( obj instanceof Integer )
- return ( value == ((Integer)obj).intValue());
- else
- return false;
- }
-
- /**
- Comparisson method for Ints.
- @return true if the input int value equals the value of the current object, false otherwize
- **/
- public boolean equals( int i ) {
- return ( value == i);
- }
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/LongHolder.java b/lib/ic/java_src/com/ericsson/otp/ic/LongHolder.java
deleted file mode 100644
index 34af201b42..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/LongHolder.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/**
- * A Holder class for IDL's out/inout argument passing modes for long
- *
- */
-package com.ericsson.otp.ic;
-
-/**
-
-Holder class for Long, used by the Term class.
-
-**/
-
-final public class LongHolder implements Holder {
- public long value;
-
- public LongHolder() {}
-
- public LongHolder(long initial) {
- value = initial;
- }
-
- /**
- Comparisson method for Longs.
- @return true if the input object equals the current object, false otherwize
- **/
- public boolean equals( Object obj ) {
- if( obj instanceof Long )
- return ( value == ((Long)obj).longValue());
- else
- return false;
- }
-
- /**
- Comparisson method for Longs.
- @return true if the input long value equals the value of the current object, false otherwize
- **/
- public boolean equals( long l ) {
- return ( value == l);
- }
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/Makefile b/lib/ic/java_src/com/ericsson/otp/ic/Makefile
deleted file mode 100644
index 21c38e54b5..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/Makefile
+++ /dev/null
@@ -1,122 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-
-
-JAVA_DEST_ROOT = $(ERL_TOP)/lib/ic/priv/
-JAVA_SRC_ROOT = $(ERL_TOP)/lib/ic/java_src/
-JAVA_CLASS_SUBDIR = com/ericsson/otp/ic/
-JAVA_INCL_ROOT = $(ERL_TOP)/lib/jinterface/priv/
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include $(ERL_TOP)/lib/ic/vsn.mk
-VSN=$(IC_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/ic-$(VSN)
-
-#
-# JAVA macros
-#
-JAVA_CLASSES = \
- Holder \
- BooleanHolder \
- ByteHolder \
- CharHolder \
- DoubleHolder \
- FloatHolder \
- IntHolder \
- LongHolder \
- ShortHolder \
- StringHolder \
- Environment \
- Any \
- AnyHelper \
- AnyHolder \
- TypeCode \
- TCKind \
- Pid \
- PidHolder \
- PidHelper \
- Ref \
- RefHolder \
- RefHelper \
- Port \
- PortHolder \
- PortHelper \
- Term \
- TermHolder \
- TermHelper
-
-TARGET_FILES= $(JAVA_CLASSES:%=$(JAVA_DEST_ROOT)$(JAVA_CLASS_SUBDIR)%.class)
-JAVA_FILES= $(JAVA_CLASSES:%=%.java)
-
-JARFILE= ic.jar
-
-# ----------------------------------------------------
-# Programs and Flags
-# ----------------------------------------------------
-CLASSPATH = $(JAVA_SRC_ROOT):$(JAVA_INCL_ROOT)
-
-JAR= jar
-
-JAVADOCFLAGS=-d $(DOCDIR)
-JAVAFLAGS=-d $(JAVA_DEST_ROOT)
-JARFLAGS= -cf
-ifneq ($(V),0)
-JARFLAGS= -cfv
-endif
-
-JAVA_OPTIONS =
-
-# ----------------------------------------------------
-# Make Rules
-# ----------------------------------------------------
-
-debug opt: $(JAVA_DEST_ROOT)$(JARFILE)
-
-$(JAVA_DEST_ROOT)$(JARFILE): $(TARGET_FILES)
- @(cd $(JAVA_DEST_ROOT) ; $(JAR) $(JARFLAGS) $(JARFILE) $(JAVA_CLASS_SUBDIR))
-
-clean:
- rm -f $(TARGET_FILES) *~
-
-docs:
-
-# ----------------------------------------------------
-# Release Targets
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/java_src/com/ericsson/otp/ic"
- $(INSTALL_DATA) $(JAVA_FILES) "$(RELSYSDIR)/java_src/com/ericsson/otp/ic"
- $(INSTALL_DIR) "$(RELSYSDIR)/priv"
- $(INSTALL_DATA) $(JAVA_DEST_ROOT)$(JARFILE) "$(RELSYSDIR)/priv"
-
-release_docs_spec:
-
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/Pid.java b/lib/ic/java_src/com/ericsson/otp/ic/Pid.java
deleted file mode 100644
index 0f26c32aef..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/Pid.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-package com.ericsson.otp.ic;
-
-
-/**
-
-Pid class mapps the built-in erlang type pid, a process identity.
-
-**/
-
-
-final public class Pid extends com.ericsson.otp.erlang.OtpErlangPid {
-
- public Pid(com.ericsson.otp.erlang.OtpSelf self) {
- super(self);
- }
-
- public Pid(com.ericsson.otp.erlang.OtpInputStream buf)
- throws com.ericsson.otp.erlang.OtpErlangDecodeException {
- super(buf);
- }
-
-
- public Pid(String node, int id, int serial, int creation) {
- super(node,id,serial,creation);
- }
-
-
- /**
- Comparisson method for Pid.
- @return true if the input Pid value equals the value of the current object, false otherwize
- **/
- public boolean equal(Pid _pid) {
- return super.equals(_pid);
- }
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/PidHelper.java b/lib/ic/java_src/com/ericsson/otp/ic/PidHelper.java
deleted file mode 100644
index 4c51035738..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/PidHelper.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-package com.ericsson.otp.ic;
-
-/**
- Helper class for Pid.
- **/
-
-public class PidHelper {
-
- // constructors
- private PidHelper() {}
-
- // methods
- /**
- Marshal method for the Pid class, encodes the Pid object to the output stream.
- **/
- public static void marshal(com.ericsson.otp.erlang.OtpOutputStream _out, Pid _value)
- throws java.lang.Exception {
-
- _out.write_pid(_value.node(),_value.id(),_value.serial(),_value.creation());
- }
-
- /**
- Unmarshal method for the Pid class, decodes a Pid object from the stream.
- @return Pid, read from the input stream
- **/
- public static Pid unmarshal(com.ericsson.otp.erlang.OtpInputStream _in)
- throws java.lang.Exception {
-
- // Double job is done here, there should be
- // a function returning a Pid instead of an
- // OtpErlangPid
- com.ericsson.otp.erlang.OtpErlangPid oep = _in.read_pid();
-
- return new Pid(oep.node(),oep.id(),oep.serial(),oep.creation());
- }
-
- /**
- Standard method that returns the interface repository identity.
- @return String containing the interface repository identity of Pid
- **/
- public static String id() {
- return "IDL:com/ericsson/otp/ic/Pid:1.0";
- }
-
- /**
- Standard method that returns the Pid class name.
- @return String containing the class name of Pid
- **/
- public static String name() {
- return "Pid";
- }
-
- /**
- Holds the TypeCode
- **/
- private static com.ericsson.otp.ic.TypeCode _tc;
-
- /**
- Standard TypeCode accessor method.
- @return the TypeCode for Pid
- **/
- synchronized public static com.ericsson.otp.ic.TypeCode type() {
-
- if (_tc != null)
- return _tc;
-
- com.ericsson.otp.ic.TypeCode _tc0 =
- new com.ericsson.otp.ic.TypeCode();
- _tc0.kind(com.ericsson.otp.ic.TCKind.tk_struct);
- _tc0.id("IDL:com/ericsson/otp/ic/Pid:1.0");
- _tc0.name("Pid");
- _tc0.member_count(4);
- _tc0.member_name(0,"node");
- com.ericsson.otp.ic.TypeCode _tc1 =
- new com.ericsson.otp.ic.TypeCode();
- _tc1.kind(com.ericsson.otp.ic.TCKind.tk_string);
- _tc1.length(256);
- _tc0.member_type(0,_tc1);
- _tc0.member_name(1,"num");
- com.ericsson.otp.ic.TypeCode _tc2 =
- new com.ericsson.otp.ic.TypeCode();
- _tc2.kind(com.ericsson.otp.ic.TCKind.tk_ulong);
- _tc0.member_type(1,_tc2);
- _tc0.member_name(2,"serial");
- com.ericsson.otp.ic.TypeCode _tc3 =
- new com.ericsson.otp.ic.TypeCode();
- _tc3.kind(com.ericsson.otp.ic.TCKind.tk_ulong);
- _tc0.member_type(2,_tc3);
- _tc0.member_name(3,"creation");
- com.ericsson.otp.ic.TypeCode _tc4 =
- new com.ericsson.otp.ic.TypeCode();
- _tc4.kind(com.ericsson.otp.ic.TCKind.tk_ulong);
- _tc0.member_type(3,_tc4);
-
- _tc = _tc0;
-
- return _tc0;
- }
-
-
- /**
- Standard method for inserting a Pid to an Any.
- **/
- public static void insert(com.ericsson.otp.ic.Any _any, Pid _this)
- throws java.lang.Exception {
-
- com.ericsson.otp.erlang.OtpOutputStream _os =
- new com.ericsson.otp.erlang.OtpOutputStream();
-
- _any.type(type());
- marshal(_os, _this);
- _any.insert_Streamable(_os);
- }
-
- /**
- Standard method for extracting a Pid from an Any.
- @return Pid, the value found in an Any contained stream.
- **/
- public static Pid extract(com.ericsson.otp.ic.Any _any)
- throws java.lang.Exception {
-
- return unmarshal(_any.extract_Streamable());
- }
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/PidHolder.java b/lib/ic/java_src/com/ericsson/otp/ic/PidHolder.java
deleted file mode 100644
index f5dfd81576..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/PidHolder.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-package com.ericsson.otp.ic;
-
-/**
- Holder class for Pid.
- **/
-
-final public class PidHolder {
-
- /**
- Pid instance variable.
- **/
- public Pid value;
-
- // constructors
- public PidHolder() {}
- public PidHolder(Pid initial) {
- value = initial;
- }
-
- // methods
- /**
- Marshal method for the PidHolder class, encodes the Pid object value to the output stream.
- **/
- public void _marshal(com.ericsson.otp.erlang.OtpOutputStream out) throws java.lang.Exception {
- PidHelper.marshal(out, value);
- }
-
- /**
- Unmarshal method for the PidHolder class, decodes a Pid object from the output stream
- and assigns it to the Holder value field.
- **/
- public void _unmarshal(com.ericsson.otp.erlang.OtpInputStream in) throws java.lang.Exception {
- value = PidHelper.unmarshal(in);
- }
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/Port.java b/lib/ic/java_src/com/ericsson/otp/ic/Port.java
deleted file mode 100644
index 34edbea362..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/Port.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-package com.ericsson.otp.ic;
-
-/**
-
-Port class mapps the built-in erlang type port, a process port.
-
-**/
-
-final public class Port extends com.ericsson.otp.erlang.OtpErlangPort {
-
- public Port(com.ericsson.otp.erlang.OtpInputStream buf)
- throws com.ericsson.otp.erlang.OtpErlangDecodeException {
- super(buf);
- }
-
- public Port(String node, int id, int creation) {
- super(node,id,creation);
- }
-
- /**
- Comparisson method for Port.
- @return true if the input Port value equals the value of the current object, false otherwize
- **/
- public boolean equal(Port _port) {
- return super.equals(_port);
- }
-
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/PortHelper.java b/lib/ic/java_src/com/ericsson/otp/ic/PortHelper.java
deleted file mode 100644
index 3e74758739..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/PortHelper.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-package com.ericsson.otp.ic;
-
-/**
- Helper class for Port.
- **/
-
-public class PortHelper {
-
- // constructors
- private PortHelper() {}
-
- // methods
-
- /**
- Marshal method for the Port class, encodes the Port object to the output stream.
- **/
- public static void marshal(com.ericsson.otp.erlang.OtpOutputStream _out, Port _value)
- throws java.lang.Exception {
-
- _out.write_port(_value.node(),_value.id(),_value.creation());
- }
-
- /**
- Unmarshal method for the Port class, decodes a Port object from the stream.
- @return Port, read from the input stream
- **/
- public static Port unmarshal(com.ericsson.otp.erlang.OtpInputStream _in)
- throws java.lang.Exception {
-
- // Double job is done here, there should be
- // a function returning a Port instead of an
- // OtpErlangPort
- com.ericsson.otp.erlang.OtpErlangPort oep = _in.read_port();
-
- return new Port(oep.node(),oep.id(),oep.creation());
- }
-
- /**
- Standard method that returns the interface repository identity.
- @return String containing the interface repository identity of Port
- **/
- public static String id() {
- return "IDL:com/ericsson/otp/ic/Port:1.0";
- }
-
- /**
- Standard method that returns the Port class name.
- @return String containing the class name of Port
- **/
- public static String name() {
- return "Port";
- }
-
- /**
- Holds the TypeCode
- **/
- private static com.ericsson.otp.ic.TypeCode _tc;
-
- /**
- Standard TypeCode accessor method.
- @return the TypeCode for Port
- **/
- synchronized public static com.ericsson.otp.ic.TypeCode type() {
-
- if (_tc != null)
- return _tc;
-
- com.ericsson.otp.ic.TypeCode _tc0 =
- new com.ericsson.otp.ic.TypeCode();
- _tc0.kind(com.ericsson.otp.ic.TCKind.tk_struct);
- _tc0.id("IDL:com/ericsson/otp/ic/Port:1.0");
- _tc0.name("Port");
- _tc0.member_count(3);
- _tc0.member_name(0,"node");
- com.ericsson.otp.ic.TypeCode _tc1 =
- new com.ericsson.otp.ic.TypeCode();
- _tc1.kind(com.ericsson.otp.ic.TCKind.tk_string);
- _tc1.length(256);
- _tc0.member_type(0,_tc1);
- _tc0.member_name(1,"id");
- com.ericsson.otp.ic.TypeCode _tc2 =
- new com.ericsson.otp.ic.TypeCode();
- _tc2.kind(com.ericsson.otp.ic.TCKind.tk_ulong);
- _tc0.member_type(1,_tc2);
- _tc0.member_name(2,"creation");
- com.ericsson.otp.ic.TypeCode _tc3 =
- new com.ericsson.otp.ic.TypeCode();
- _tc3.kind(com.ericsson.otp.ic.TCKind.tk_ulong);
- _tc0.member_type(2,_tc3);
-
- _tc = _tc0;
-
- return _tc0;
- }
-
-
- /**
- Standard method for inserting a Port to an Any.
- **/
- public static void insert(com.ericsson.otp.ic.Any _any, Port _this)
- throws java.lang.Exception {
-
- com.ericsson.otp.erlang.OtpOutputStream _os =
- new com.ericsson.otp.erlang.OtpOutputStream();
-
- _any.type(type());
- marshal(_os, _this);
- _any.insert_Streamable(_os);
- }
-
- /**
- Standard method for extracting a Port from an Any.
- @return Port, the value found in an Any contained stream.
- **/
- public static Port extract(com.ericsson.otp.ic.Any _any)
- throws java.lang.Exception {
-
- return unmarshal(_any.extract_Streamable());
- }
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/PortHolder.java b/lib/ic/java_src/com/ericsson/otp/ic/PortHolder.java
deleted file mode 100644
index da0df3bbc7..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/PortHolder.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-package com.ericsson.otp.ic;
-
-/**
- Holder class for Port.
- **/
-
-final public class PortHolder {
-
- /**
- Port instance variable.
- **/
- public Port value;
-
- // constructors
- public PortHolder() {}
- public PortHolder(Port initial) {
- value = initial;
- }
-
- // methods
- /**
- Marshal method for the PortHolder class, encodes the Port object value to the output stream.
- **/
- public void _marshal(com.ericsson.otp.erlang.OtpOutputStream out)
- throws java.lang.Exception {
- PortHelper.marshal(out, value);
- }
-
- /**
- Unmarshal method for the PortHolder class, decodes a Port object from the output stream
- and assigns it to the Holder value field.
- **/
- public void _unmarshal(com.ericsson.otp.erlang.OtpInputStream in)
- throws java.lang.Exception {
- value = PortHelper.unmarshal(in);
- }
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/Ref.java b/lib/ic/java_src/com/ericsson/otp/ic/Ref.java
deleted file mode 100644
index a55da87d0d..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/Ref.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-package com.ericsson.otp.ic;
-
-/**
-
-Ref class mapps the built-in erlang type Ref, a message reference.
-
-**/
-
-final public class Ref extends com.ericsson.otp.erlang.OtpErlangRef {
-
- public Ref(com.ericsson.otp.erlang.OtpSelf self) {
- super(self);
- }
-
-
- public Ref(com.ericsson.otp.erlang.OtpInputStream buf)
- throws com.ericsson.otp.erlang.OtpErlangDecodeException {
- super(buf);
- }
-
- /**
- Old style Ref costructor. Costructs an Ref that coresponds to the
- old erlang Ref type.
- **/
- public Ref(String node, int id, int creation) {
- super(node,id,creation);
- }
-
- public Ref(String node, int[] ids, int creation) {
- super(node,ids,creation);
- }
-
- /**
- Comparisson method for Ref.
- @return true if the input Ref value equals the value of the current object, false otherwize
- **/
- public boolean equal(Ref _ref) {
- return super.equals(_ref);
- }
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/RefHelper.java b/lib/ic/java_src/com/ericsson/otp/ic/RefHelper.java
deleted file mode 100644
index cb145bbbb2..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/RefHelper.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-package com.ericsson.otp.ic;
-
-/**
- Helper class for Ref.
- **/
-
-public class RefHelper {
-
- // constructors
- private RefHelper() {}
-
- // methods
- /**
- Marshal method for the Ref class, encodes the Ref object to the output stream.
- **/
- public static void marshal(com.ericsson.otp.erlang.OtpOutputStream _out, Ref _value)
- throws java.lang.Exception {
-
- _out.write_ref(_value.node(),_value.id(),_value.creation());
- }
-
- /**
- Unmarshal method for the Ref class, decodes a Ref object from the stream.
- @return Ref, read from the input stream
- **/
- public static Ref unmarshal(com.ericsson.otp.erlang.OtpInputStream _in)
- throws java.lang.Exception {
-
- // Double job is done here, there should be
- // a function returning a Ref instead of an
- // OtpErlangRef
- com.ericsson.otp.erlang.OtpErlangRef oer = _in.read_ref();
-
- if (oer.isNewRef())
- return new Ref(oer.node(),oer.ids(),oer.creation());
- else
- return new Ref(oer.node(),oer.id(),oer.creation());
- }
-
- /**
- Standard method that returns the interface repository identity.
- @return String containing the interface repository identity of Ref
- **/
- public static String id() {
- return "IDL:com/ericsson/otp/ic/Ref:1.0";
- }
-
- /**
- Standard method that returns the Ref class name.
- @return String containing the class name of Ref
- **/
- public static String name() {
- return "Ref";
- }
-
- /**
- Holds the TypeCode
- **/
- private static com.ericsson.otp.ic.TypeCode _tc;
-
- /**
- Standard TypeCode accessor method.
- @return the TypeCode for Ref
- **/
- synchronized public static com.ericsson.otp.ic.TypeCode type() {
-
- if (_tc != null)
- return _tc;
-
- com.ericsson.otp.ic.TypeCode _tc0 =
- new com.ericsson.otp.ic.TypeCode();
- _tc0.kind(com.ericsson.otp.ic.TCKind.tk_struct);
- _tc0.id("IDL:com/ericsson/otp/ic/Ref:1.0");
- _tc0.name("Ref");
- _tc0.member_count(3);
- _tc0.member_name(0,"node");
- com.ericsson.otp.ic.TypeCode _tc1 =
- new com.ericsson.otp.ic.TypeCode();
- _tc1.kind(com.ericsson.otp.ic.TCKind.tk_string);
- _tc1.length(256);
- _tc0.member_type(0,_tc1);
- _tc0.member_name(1,"id");
- com.ericsson.otp.ic.TypeCode _tc2 =
- new com.ericsson.otp.ic.TypeCode();
- _tc2.kind(com.ericsson.otp.ic.TCKind.tk_ulong);
- _tc0.member_type(1,_tc2);
- _tc0.member_name(2,"creation");
- com.ericsson.otp.ic.TypeCode _tc3 =
- new com.ericsson.otp.ic.TypeCode();
- _tc3.kind(com.ericsson.otp.ic.TCKind.tk_ulong);
- _tc0.member_type(2,_tc3);
-
- _tc = _tc0;
-
- return _tc0;
- }
-
- /**
- Standard method for inserting a Ref to an Any.
- **/
- public static void insert(com.ericsson.otp.ic.Any _any, Ref _this)
- throws java.lang.Exception {
-
- com.ericsson.otp.erlang.OtpOutputStream _os =
- new com.ericsson.otp.erlang.OtpOutputStream();
-
- _any.type(type());
- marshal(_os, _this);
- _any.insert_Streamable(_os);
- }
-
- /**
- Standard method for extracting a Ref from an Any.
- @return Ref, the value found in an Any contained stream.
- **/
- public static Ref extract(com.ericsson.otp.ic.Any _any)
- throws java.lang.Exception {
-
- return unmarshal(_any.extract_Streamable());
- }
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/RefHolder.java b/lib/ic/java_src/com/ericsson/otp/ic/RefHolder.java
deleted file mode 100644
index 9ef2eacea1..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/RefHolder.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-package com.ericsson.otp.ic;
-
-/**
- Holder class for Ref.
- **/
-
-final public class RefHolder {
-
- /**
- Ref instance variable.
- **/
- public Ref value;
-
- // constructors
- public RefHolder() {}
- public RefHolder(Ref initial) {
- value = initial;
- }
-
- // methods
- /**
- Marshal method for the RefHolder class, encodes the Ref object value to the output stream.
- **/
- public void _marshal(com.ericsson.otp.erlang.OtpOutputStream out) throws java.lang.Exception {
- RefHelper.marshal(out, value);
- }
-
- /**
- Unmarshal method for the RefHolder class, decodes a Ref object from the output stream
- and assigns it to the Holder value field.
- **/
- public void _unmarshal(com.ericsson.otp.erlang.OtpInputStream in) throws java.lang.Exception {
- value = RefHelper.unmarshal(in);
- }
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/ShortHolder.java b/lib/ic/java_src/com/ericsson/otp/ic/ShortHolder.java
deleted file mode 100644
index 3b191dd633..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/ShortHolder.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/**
- * A Holder class for IDL's out/inout argument passing modes for long
- *
- */
-package com.ericsson.otp.ic;
-
-/**
-
-Holder class for Short, according to OMG-IDL java mapping.
-
-**/
-
-final public class ShortHolder implements Holder {
- public short value;
-
- public ShortHolder() {}
-
- public ShortHolder(short initial) {
- value = initial;
- }
-
- /* Extra methods not in standard. */
- /**
- Comparisson method for Shorts.
- @return true if the input object equals the current object, false otherwize
- **/
- public boolean equals( Object obj ) {
- if( obj instanceof Short )
- return ( value == ((Short)obj).shortValue());
- else
- return false;
- }
-
- /**
- Comparisson method for Shorts.
- @return true if the input short value equals the value of the current object, false otherwize
- **/
- public boolean equals( short s ) {
- return ( value == s);
- }
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/StringHolder.java b/lib/ic/java_src/com/ericsson/otp/ic/StringHolder.java
deleted file mode 100644
index f4cd069148..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/StringHolder.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/**
- * A Holder class for IDL's out/inout argument passing modes for string
- *
- */
-package com.ericsson.otp.ic;
-
-
-/**
-
-Holder class for String, according to OMG-IDL java mapping.
-
-**/
-
-final public class StringHolder implements Holder {
- public String value;
-
- public StringHolder() {}
-
- public StringHolder(String initial) {
- value = initial;
- }
-
- /* Extra methods not in standard. */
- /**
- Comparisson method for Strings.
- @return true if the input object equals the current object, false otherwize
- **/
- public boolean equals( Object obj ) {
- if( obj instanceof String )
- return ( value == obj);
- else
- return false;
- }
-
- /**
- Comparisson method for Strings.
- @return true if the input String value equals the value of the current object, false otherwize
- **/
- public boolean equals( String s ) {
- return ( value == s);
- }
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/TCKind.java b/lib/ic/java_src/com/ericsson/otp/ic/TCKind.java
deleted file mode 100644
index e6265ae586..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/TCKind.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/**
- * The TCKind class for Java IDL
- *
- */
-package com.ericsson.otp.ic;
-
-/**
- The TCKind class is the implementation of the OMG-IDL enumerant type TCKind.
- **/
-
-final public class TCKind {
-
- // instance variables
- public static final int _tk_null = 0,
- _tk_void = 1,
- _tk_short = 2,
- _tk_long = 3,
- _tk_ushort = 4,
- _tk_ulong = 5,
- _tk_float = 6,
- _tk_double = 7,
- _tk_boolean = 8,
- _tk_char = 9,
- _tk_octet = 10,
- _tk_any = 11,
- _tk_TypeCode = 12,
- _tk_Principal = 13,
- _tk_objref = 14,
- _tk_struct = 15,
- _tk_union = 16,
- _tk_enum = 17,
- _tk_string = 18,
- _tk_sequence = 19,
- _tk_array = 20,
- _tk_alias = 21,
- _tk_except = 22,
- _tk_longlong = 23,
- _tk_ulonglong = 24,
- _tk_longdouble = 25,
- _tk_wchar = 26,
- _tk_wstring = 27,
- _tk_fixed = 28,
- _tk_atom = 20000, /* Used for union label default value only */
- _tk_pid = 20001, /* Used for special pid struct */
- _tk_port = 20002, /* Used for special port struct */
- _tk_ref = 20003, /* Used for special ref struct */
- _tk_term = 20004; /* Used for special term struct */
-
- public static final TCKind tk_null = new TCKind(_tk_null);
- public static final TCKind tk_void = new TCKind(_tk_void);
- public static final TCKind tk_short = new TCKind(_tk_short);
- public static final TCKind tk_long = new TCKind(_tk_long);
- public static final TCKind tk_ushort = new TCKind(_tk_ushort);
- public static final TCKind tk_ulong = new TCKind(_tk_ulong);
- public static final TCKind tk_float = new TCKind(_tk_float);
- public static final TCKind tk_double = new TCKind(_tk_double);
- public static final TCKind tk_boolean = new TCKind(_tk_boolean);
- public static final TCKind tk_char = new TCKind(_tk_char);
- public static final TCKind tk_octet = new TCKind(_tk_octet);
- public static final TCKind tk_any = new TCKind(_tk_any);
- public static final TCKind tk_TypeCode = new TCKind(_tk_TypeCode);
- public static final TCKind tk_Principal = new TCKind(_tk_Principal);
- public static final TCKind tk_objref = new TCKind(_tk_objref);
- public static final TCKind tk_struct = new TCKind(_tk_struct);
- public static final TCKind tk_union = new TCKind(_tk_union);
- public static final TCKind tk_enum = new TCKind(_tk_enum);
- public static final TCKind tk_string = new TCKind(_tk_string);
- public static final TCKind tk_sequence = new TCKind(_tk_sequence);
- public static final TCKind tk_array = new TCKind(_tk_array);
- public static final TCKind tk_alias = new TCKind(_tk_alias);
- public static final TCKind tk_except = new TCKind(_tk_except);
- public static final TCKind tk_longlong = new TCKind(_tk_longlong);
- public static final TCKind tk_ulonglong = new TCKind(_tk_ulonglong);
- public static final TCKind tk_longdouble = new TCKind(_tk_longdouble);
- public static final TCKind tk_wchar = new TCKind(_tk_wchar);
- public static final TCKind tk_wstring = new TCKind(_tk_wstring);
- public static final TCKind tk_fixed = new TCKind(_tk_fixed);
- protected static final TCKind tk_atom = new TCKind(_tk_atom);
- protected static final TCKind tk_pid = new TCKind(_tk_pid);
- protected static final TCKind tk_port = new TCKind(_tk_port);
- protected static final TCKind tk_ref = new TCKind(_tk_ref);
- protected static final TCKind tk_term = new TCKind(_tk_term);
- private int _value;
-
- // constructors
- private TCKind(int __value) {
- _value = __value;
- }
-
- // methods
-
- /**
- Accessor method for the value of TCKind.
- @return int, the value of TCKind object
- **/
- public int value() {
- return _value;
- }
-
- /**
- Translator method for TCKind.
- Traslates the input integer value to a TCKind enumerant object.
- @return TCKind, a TCKind object
- **/
- public static final TCKind from_int(int __value) throws java.lang.Exception {
- switch (__value) {
- case _tk_null:
- return tk_null;
- case _tk_void:
- return tk_void;
- case _tk_short:
- return tk_short;
- case _tk_long:
- return tk_long;
- case _tk_ushort:
- return tk_ushort;
- case _tk_ulong:
- return tk_ulong;
- case _tk_float:
- return tk_float;
- case _tk_double:
- return tk_double;
- case _tk_boolean:
- return tk_boolean;
- case _tk_char:
- return tk_char;
- case _tk_octet:
- return tk_octet;
- case _tk_any:
- return tk_any;
- case _tk_TypeCode:
- return tk_TypeCode;
- case _tk_Principal:
- return tk_Principal;
- case _tk_objref:
- return tk_objref;
- case _tk_struct:
- return tk_struct;
- case _tk_union:
- return tk_union;
- case _tk_enum:
- return tk_enum;
- case _tk_string:
- return tk_string;
- case _tk_sequence:
- return tk_sequence;
- case _tk_array:
- return tk_array;
- case _tk_alias:
- return tk_alias;
- case _tk_except:
- return tk_except;
- case _tk_longlong:
- return tk_longlong;
- case _tk_ulonglong:
- return tk_ulonglong;
- case _tk_longdouble:
- return tk_longdouble;
- case _tk_wchar:
- return tk_wchar;
- case _tk_wstring:
- return tk_wstring;
- case _tk_fixed:
- return tk_fixed;
- case _tk_atom:
- return tk_atom;
- case _tk_pid:
- return tk_pid;
- case _tk_port:
- return tk_port;
- case _tk_ref:
- return tk_ref;
- case _tk_term:
- return tk_term;
- default:
- throw new java.lang.Exception("");
- }
- }
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/Term.java b/lib/ic/java_src/com/ericsson/otp/ic/Term.java
deleted file mode 100644
index 7a27905fcd..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/Term.java
+++ /dev/null
@@ -1,1113 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-package com.ericsson.otp.ic;
-
-/**
-
-The Term class is intended to represent the erlang term generic type.
-It extends the Any class and is basically used the same way as the Any class.
-<p>The main difference between Term and Any is the use of guard methods
-instead for TypeCode to determine the data included in the Term.
-This actual when cannot determine a Term's value class returned at compile time.
-
-**/
-
-final public class Term extends Any {
-
- // Primitive value holder
- protected java.lang.String atomV;
- protected long longV;
- protected Pid PidV;
- protected Ref RefV;
- protected Port PortV;
- protected com.ericsson.otp.erlang.OtpErlangObject ObjV;
- protected int tag;
-
- /**
- Tag accessor method
- @return int, the tag of the Object that denotes the erlang external format tag
- **/
- public int tag() {
- return tag;
- }
-
- /* Guards */
-
- /**
- Guard method
- @return true if the Term is an OtpErlangAtom, false otherwize
- **/
- public boolean isAtom() {
-
- if (ObjV == null) {
- if (tag == com.ericsson.otp.erlang.OtpExternal.atomTag ||
- tag == com.ericsson.otp.erlang.OtpExternal.atomUtf8Tag ||
- tag == com.ericsson.otp.erlang.OtpExternal.smallAtomUtf8Tag)
-
- return true;
-
- return false;
- }
-
- return (ObjV instanceof com.ericsson.otp.erlang.OtpErlangAtom) ;
- }
-
- /**
- Guard method
- @return true if the Term is not an OtpErlangList nor an OtpErlangTuple, false otherwize
- **/
- public boolean isConstant() {
- if (isList())
- return false;
-
- if (isTuple())
- return false;
-
- return true;
- }
-
- /**
- Guard method
- @return true if the Term is an OtpErlangFloat, false otherwize
- **/
- public boolean isFloat() {
- if (tag == com.ericsson.otp.erlang.OtpExternal.floatTag)
- return true;
-
- return false;
- }
-
- /**
- Guard method
- @return true if the Term is an OtpErlangInt, false otherwize
- **/
- public boolean isInteger() {
- switch(tag) {
- case com.ericsson.otp.erlang.OtpExternal.smallIntTag:
- case com.ericsson.otp.erlang.OtpExternal.intTag:
- case com.ericsson.otp.erlang.OtpExternal.smallBigTag:
- return true;
- default:
- return false;
- }
- }
-
- /**
- Guard method
- @return true if the Term is an OtpErlangList, false otherwize
- **/
- public boolean isList() {
-
- if (ObjV == null) {
- switch(tag) {
- case com.ericsson.otp.erlang.OtpExternal.listTag:
- case com.ericsson.otp.erlang.OtpExternal.stringTag:
- case com.ericsson.otp.erlang.OtpExternal.nilTag:
- return true;
- default:
- return false;
- }
- }
-
- if (ObjV instanceof com.ericsson.otp.erlang.OtpErlangList)
- return true;
-
- if (ObjV instanceof com.ericsson.otp.erlang.OtpErlangString)
- return true;
-
- return false;
- }
-
-
- /**
- Guard method
- @return true if the Term is an OtpErlangString, false otherwize
- **/
- public boolean isString() {
-
- if (ObjV == null) {
- switch(tag) {
- case com.ericsson.otp.erlang.OtpExternal.stringTag:
- case com.ericsson.otp.erlang.OtpExternal.nilTag:
- return true;
- default:
- try {
- stringV = extract_string();
- return true;
- } catch (Exception e) {
- return false;
- }
- }
- }
-
- if (ObjV instanceof com.ericsson.otp.erlang.OtpErlangString)
- return true;
-
- try {
- stringV = extract_string();
- return true;
- } catch (Exception e) {
- return false;
- }
- }
-
- /**
- Guard method
- @return true if the Term is an OtpErlangInteger or an OtpErlangFloat, false otherwize
- **/
- public boolean isNumber() {
- switch(tag) {
- case com.ericsson.otp.erlang.OtpExternal.smallIntTag:
- case com.ericsson.otp.erlang.OtpExternal.intTag:
- case com.ericsson.otp.erlang.OtpExternal.smallBigTag:
- case com.ericsson.otp.erlang.OtpExternal.floatTag:
- return true;
- default :
- return false;
- }
- }
-
-
- /**
- Guard method
- @return true if the Term is an OtpErlangPid or Pid, false otherwize
- **/
- public boolean isPid() {
-
- if (ObjV == null) {
- if (tag == com.ericsson.otp.erlang.OtpExternal.pidTag)
- return true;
-
- return false;
- }
-
- return (ObjV instanceof com.ericsson.otp.erlang.OtpErlangPid) ;
- }
-
-
- /**
- Guard method
- @return true if the Term is an OtpErlangPort or Port, false otherwize
- **/
- public boolean isPort() {
- if (ObjV == null) {
- if (tag == com.ericsson.otp.erlang.OtpExternal.portTag)
- return true;
-
- return false;
- }
-
- return (ObjV instanceof com.ericsson.otp.erlang.OtpErlangPort);
- }
-
-
- /**
- Guard method
- @return true if the Term is an OtpErlangRef, false otherwize
- **/
- public boolean isReference() {
- if (ObjV == null) {
- switch(tag) {
- case com.ericsson.otp.erlang.OtpExternal.refTag:
- case com.ericsson.otp.erlang.OtpExternal.newRefTag:
- return true;
- default :
- return false;
- }
- }
-
- return (ObjV instanceof com.ericsson.otp.erlang.OtpErlangRef) ;
- }
-
-
- /**
- Guard method
- @return true if the Term is an OtpErlangTuple, false otherwize
- **/
- public boolean isTuple() {
- if (ObjV == null) {
- switch(tag) {
- case com.ericsson.otp.erlang.OtpExternal.smallTupleTag:
- case com.ericsson.otp.erlang.OtpExternal.largeTupleTag:
- return true;
- default :
- return false;
- }
- }
-
- return (ObjV instanceof com.ericsson.otp.erlang.OtpErlangTuple);
- }
-
-
- /**
- Guard method
- @return true if the Term is an OtpErlangBinary, false otherwize
- **/
- public boolean isBinary() {
- if (ObjV == null) {
- if (tag == com.ericsson.otp.erlang.OtpExternal.binTag)
- return true;
-
- return false;
- }
-
- return (ObjV instanceof com.ericsson.otp.erlang.OtpErlangBinary);
- }
-
-
-
-
- // Equal function
- /**
- Term comparison method
- @return true if the input Term is equal to the object, false otherwize
- **/
- public boolean equal(Term _any) {
-
- try {
-
- /* Pids */
- if ((PidV != null) && (_any.PidV != null))
- if (PidV.equal(_any.PidV))
- return true;
-
- /* Refs */
- if ((RefV != null) && (_any.RefV != null))
- if (RefV.equal(_any.RefV))
- return true;
-
- /* Ports */
- if ((PortV != null) && (_any.PortV != null))
- if (PortV.equals(_any.PortV))
- return true;
-
- /* strings */
- if ((stringV != null) && (_any.stringV != null))
- if (stringV.equals(_any.stringV))
- return true;
-
- /* atoms and booleans */
- if ((atomV != null) && (_any.atomV != null))
- if (atomV.equals(_any.atomV))
- return true;
-
- /* booleans */
- if (atomV != null)
- if (_any.booleanV == Boolean.valueOf(atomV).booleanValue())
- return true;
-
- if (_any.atomV != null)
- if (booleanV == Boolean.valueOf(_any.atomV).booleanValue())
- return true;
-
- /* integer types plus floating point types */
- double _ownNS =
- longV+doubleV;
-
- double _othersNS =
- _any.longV+_any.doubleV;
-
- if ((equal(_ownNS,_othersNS)) &&
- (!equal(_ownNS,0)))
- return true;
-
- /* All together, 0 or false */
- if ((equal(_ownNS,_othersNS)) &&
- booleanV == _any.booleanV)
- return true;
-
-
- return false;
-
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
-
- /**
- Writes the value of Term to a stream
- **/
- public void write_value(com.ericsson.otp.erlang.OtpOutputStream _os)
- throws java.lang.Exception {
-
- if ((tcV == null) && (ObjV != null))
- _os.write_any(ObjV); // Type not generated by IC
-
- else {
-
- switch(tcV.kind().value()) {
-
- case TCKind._tk_octet :
- case TCKind._tk_char :
- case TCKind._tk_wchar :
- case TCKind._tk_short :
- case TCKind._tk_ushort :
- case TCKind._tk_long :
- case TCKind._tk_longlong :
- case TCKind._tk_ulong :
- case TCKind._tk_ulonglong :
- _os.write_long(longV);
- break;
-
- case TCKind._tk_float :
- _os.write_double(doubleV);
- break;
-
- case TCKind._tk_double :
- _os.write_double(doubleV);
- break;
-
- case TCKind._tk_boolean :
- _os.write_boolean(booleanV);
- break;
-
- case TCKind._tk_string :
- case TCKind._tk_wstring :
- _os.write_string(stringV);
- break;
-
- case TCKind._tk_atom :
- _os.write_atom(stringV);
- break;
-
- case TCKind._tk_struct:
- if (isPid())
- PidHelper.marshal(_os, PidV);
- else {
- if (isReference())
- RefHelper.marshal(_os, RefV);
- else {
- if (isPort())
- PortHelper.marshal(_os, PortV);
- else
- _os.write(os.toByteArray());
- }
- }
- break;
-
- case TCKind._tk_union:
- case TCKind._tk_array:
- case TCKind._tk_sequence:
- case TCKind._tk_enum:
- _os.write(os.toByteArray());
- break;
-
- case TCKind._tk_void :
- _os.write_atom("ok");
- break;
-
- /*
- * Not supported types
- */
- default:
- throw new java.lang.Exception("BAD KIND");
- }
- }
- }
-
-
-
- /*
- * Insert and extract each primitive type
- */
-
-
- /* short */
-
- /**
- Short value extractor method
- @return short, the value of Term
- **/
- public short extract_short()
- throws java.lang.Exception {
-
- if (tcV == null)
- return (short) longV;
-
- if (tcV.kind() == TCKind.tk_short)
- return (short) longV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Short value insertion method
- **/
- public void insert_short(short s) {
- longV = s;
- tag = com.ericsson.otp.erlang.OtpExternal.intTag;
- tcV = new TypeCode(TCKind.tk_short);
- };
-
- /**
- Short value insertion method
- **/
- public void insert_short(long l) {
- longV = l;
- tag = com.ericsson.otp.erlang.OtpExternal.intTag;
- tcV = new TypeCode(TCKind.tk_short);
- };
-
-
- /* long */
-
- /**
- Long value extractor method
- @return int, the value of Term
- **/
- public int extract_long()
- throws java.lang.Exception {
-
- if (tcV == null)
- return (int) longV;
-
- if (tcV.kind() == TCKind.tk_long)
- return (int) longV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Long value insertion method
- **/
- public void insert_long(int i){
- longV = i;
- tag = com.ericsson.otp.erlang.OtpExternal.intTag;
- tcV = new TypeCode(TCKind.tk_long);
- }
-
- /**
- Long value insertion method
- **/
- public void insert_long(long l){
- longV = l;
- tag = com.ericsson.otp.erlang.OtpExternal.intTag;
- tcV = new TypeCode(TCKind.tk_long);
- }
-
-
- /* longlong */
-
- /**
- Long Long value extractor method
- @return long, the value of Term
- **/
- public long extract_longlong()
- throws java.lang.Exception {
-
- if (tcV == null)
- return longV;
-
- if (tcV.kind() == TCKind.tk_longlong)
- return longV;
-
- throw new java.lang.Exception("");
- }
-
-
- /**
- Long Long value insertion method
- **/
- public void insert_longlong(long l){
- longV = l;
- tag = com.ericsson.otp.erlang.OtpExternal.intTag;
- tcV = new TypeCode(TCKind.tk_longlong);
- }
-
-
- /* ushort */
-
- /**
- Unsigned Short value extractor method
- @return short, the value of Term
- **/
- public short extract_ushort()
- throws java.lang.Exception {
-
- if (tcV == null)
- return (short) longV;
-
- if (tcV.kind() == TCKind.tk_ushort)
- return (short) longV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Unsigned Short value insertion method
- **/
- public void insert_ushort(short s){
- longV = s;
- tag = com.ericsson.otp.erlang.OtpExternal.intTag;
- tcV = new TypeCode(TCKind.tk_ushort);
- }
-
- /**
- Unsigned Short value insertion method
- **/
- public void insert_ushort(long l){
- longV = l;
- tag = com.ericsson.otp.erlang.OtpExternal.intTag;
- tcV = new TypeCode(TCKind.tk_ushort);
- }
-
-
- /* ulong */
-
- /**
- Unsigned Long value extractor method
- @return int, the value of Term
- **/
- public int extract_ulong()
- throws java.lang.Exception{
-
- if (tcV == null)
- return (int) longV;
-
- if (tcV.kind() == TCKind.tk_ulong)
- return (int) longV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Unsigned Long value insertion method
- **/
- public void insert_ulong(int i){
- longV = i;
- tag = com.ericsson.otp.erlang.OtpExternal.intTag;
- tcV = new TypeCode(TCKind.tk_ulong);
- }
-
-
- /**
- Unsigned Long value insertion method
- **/
- public void insert_ulong(long l){
- longV = l;
- tag = com.ericsson.otp.erlang.OtpExternal.intTag;
- tcV = new TypeCode(TCKind.tk_ulong);
- }
-
-
-
- /* ulonglong */
-
- /**
- Unsigned Long Long value extractor method
- @return long, the value of Term
- **/
- public long extract_ulonglong()
- throws java.lang.Exception {
-
- if (tcV == null)
- return longV;
-
- if (tcV.kind() == TCKind.tk_ulonglong)
- return longV;
-
- throw new java.lang.Exception("");
- }
-
-
- /**
- Unsigned Long Long value insertion method
- **/
- public void insert_ulonglong(long l){
- longV = l;
- tag = com.ericsson.otp.erlang.OtpExternal.intTag;
- tcV = new TypeCode(TCKind.tk_ulonglong);
- }
-
-
-
- /* float */
- /**
- Float value extractor method
- @return float, the value of Term
- **/
- public float extract_float()
- throws java.lang.Exception{
-
- if (tcV == null)
- return (float) doubleV;
-
- if (tcV.kind() == TCKind.tk_float)
- return (float) doubleV;
-
- throw new java.lang.Exception("");
- }
-
-
- /**
- Float value insertion method
- **/
- public void insert_float(float f){
- doubleV = f;
- tag = com.ericsson.otp.erlang.OtpExternal.floatTag;
- tcV = new TypeCode(TCKind.tk_float);
- }
-
- /**
- Float value insertion method
- **/
- public void insert_float(double f){
- doubleV = f;
- tag = com.ericsson.otp.erlang.OtpExternal.floatTag;
- tcV = new TypeCode(TCKind.tk_float);
- }
-
-
- /* double */
- /**
- Double value extractor method
- @return double, the value of Term
- **/
- public double extract_double()
- throws java.lang.Exception{
-
- if (tcV == null)
- return doubleV;
-
- if (tcV.kind() == TCKind.tk_double)
- return doubleV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Double value insertion method
- **/
- public void insert_double(double d){
- doubleV = d;
- tag = com.ericsson.otp.erlang.OtpExternal.floatTag;
- tcV = new TypeCode(TCKind.tk_double);
- }
-
-
- /* boolean */
- /**
- Boolean value extractor method
- @return boolean, the value of Term
- **/
- public boolean extract_boolean()
- throws java.lang.Exception{
-
- if ((tcV == null) && (atomV != null))
- return Boolean.valueOf(atomV).booleanValue();
-
- if (tcV.kind() == TCKind.tk_boolean)
- return booleanV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Boolean value insertion method
- **/
- public void insert_boolean(boolean b){
- booleanV = b;
- tag = com.ericsson.otp.erlang.OtpExternal.atomTag;
- tcV = new TypeCode(TCKind.tk_boolean);
- }
-
-
- /* char */
- /**
- Char value extractor method
- @return char, the value of Term
- **/
- public char extract_char()
- throws java.lang.Exception{
-
- if (tcV == null)
- return (char) longV;
-
- if (tcV.kind() == TCKind.tk_char)
- return (char) longV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Char value insertion method
- **/
- public void insert_char(char c) {
- longV = c;
- tag = com.ericsson.otp.erlang.OtpExternal.smallIntTag;
- tcV = new TypeCode(TCKind.tk_char);
- }
-
- /**
- Char value insertion method
- **/
- public void insert_char(long l) {
- longV = l;
- tag = com.ericsson.otp.erlang.OtpExternal.smallIntTag;
- tcV = new TypeCode(TCKind.tk_char);
- }
-
-
-
- /* wchar */
- /**
- Wchar value extractor method
- @return char, the value of Term
- **/
- public char extract_wchar()
- throws java.lang.Exception{
-
- if (tcV == null)
- return (char) longV;
-
- if (tcV.kind() == TCKind.tk_wchar)
- return (char) longV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Wchar value insertion method
- **/
- public void insert_wchar(char c) {
- longV = c;
- tag = com.ericsson.otp.erlang.OtpExternal.smallIntTag;
- tcV = new TypeCode(TCKind.tk_wchar);
- }
-
- /**
- Wchar value insertion method
- **/
- public void insert_wchar(long l) {
- longV = l;
- tag = com.ericsson.otp.erlang.OtpExternal.smallIntTag;
- tcV = new TypeCode(TCKind.tk_wchar);
- }
-
-
- /* octet */
- /**
- Octet value extractor method
- @return byte, the value of Term
- **/
- public byte extract_octet()
- throws java.lang.Exception{
-
- if (tcV == null)
- return (byte) longV;
-
- if (tcV.kind() == TCKind.tk_octet)
- return (byte) longV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Octet value insertion method
- **/
- public void insert_octet(byte b){
- longV = b;
- tag = com.ericsson.otp.erlang.OtpExternal.smallIntTag;
- tcV = new TypeCode(TCKind.tk_octet);
- }
-
- /**
- Octet value insertion method
- **/
- public void insert_octet(long l){
- longV = l;
- tag = com.ericsson.otp.erlang.OtpExternal.smallIntTag;
- tcV = new TypeCode(TCKind.tk_octet);
- }
-
-
-
- /* string */
-
- /**
- String value extractor method
- @return String, the value of Term
- **/
- public java.lang.String extract_string()
- throws java.lang.Exception{
-
- if (tcV == null) {
- if (stringV != null)
- return stringV;
- else {
- is = this.extract_Streamable();
- stringV = is.read_string();
- return stringV;
- }
- }
- else
- if (tcV.kind() == TCKind.tk_string)
- return stringV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- String value insertion method
- **/
- public void insert_string(java.lang.String s) {
- stringV = s;
- tag = com.ericsson.otp.erlang.OtpExternal.stringTag;
- tcV = new TypeCode(TCKind.tk_string);
- }
-
-
-
- /* wstring */
- /**
- Wstring value extractor method
- @return String, the value of Term
- **/
- public java.lang.String extract_wstring()
- throws java.lang.Exception{
-
- if (tcV == null) {
- if (stringV != null)
- return stringV;
- else {
- is = this.extract_Streamable();
- stringV = is.read_string();
- return stringV;
- }
- }
- else
- if (tcV.kind() == TCKind.tk_wstring)
- return stringV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Wstring value insertion method
- **/
- public void insert_wstring(java.lang.String s) {
- stringV = s;
- tag = com.ericsson.otp.erlang.OtpExternal.stringTag;
- tcV = new TypeCode(TCKind.tk_wstring);
- }
-
-
-
- /* atom */
- /**
- Atom value extractor method
- @return atom, the value of Term
- **/
- public java.lang.String extract_atom()
- throws java.lang.Exception{
-
- if ((tcV == null) && (atomV != null))
- return atomV;
-
- if (tcV.kind() == TCKind.tk_atom)
- return stringV;
-
- throw new java.lang.Exception("");
- }
-
-
- /**
- Atom value insertion method
- **/
- public void insert_atom(java.lang.String s) {
- stringV = s;
- tag = com.ericsson.otp.erlang.OtpExternal.atomTag;
- tcV = new TypeCode(TCKind.tk_atom);
- }
-
-
- /* Pid */
- /**
- Pid value extractor method
- @return Pid, the value of Term
- **/
- public Pid extract_Pid()
- throws java.lang.Exception{
-
- if ((tcV == null) && (PidV != null))
- return PidV;
-
- if (tcV.equal(PidHelper.type()))
- return PidV;
-
- throw new java.lang.Exception("");
- }
-
-
- /**
- Pid value insertion method
- **/
- public void insert_Pid(Pid p) {
- PidV = p;
- tag = com.ericsson.otp.erlang.OtpExternal.pidTag;
- tcV = PidHelper.type();
- }
-
-
-
- /* Ref */
- /**
- Ref value extractor method
- @return Ref, the value of Term
- **/
- public Ref extract_Ref()
- throws java.lang.Exception{
-
- if ((tcV == null) && (RefV != null))
- return RefV;
-
- if (tcV.equal(RefHelper.type()))
- return RefV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Ref value insertion method
- **/
- public void insert_Ref(Ref r) {
- RefV = r;
-
- if (r.isNewRef())
- tag = com.ericsson.otp.erlang.OtpExternal.newRefTag;
- else
- tag = com.ericsson.otp.erlang.OtpExternal.refTag;
-
- tcV = RefHelper.type();
- }
-
-
-
- /* Port */
- /**
- Port value extractor method
- @return Port, the value of Term
- **/
- public Port extract_Port()
- throws java.lang.Exception{
-
- if ((tcV == null) && (PortV != null))
- return PortV;
-
- if (tcV.equal(PortHelper.type()))
- return PortV;
-
- throw new java.lang.Exception("");
- }
-
- /**
- Port value insertion method
- **/
- public void insert_Port(Port p) {
- PortV = p;
- tag = com.ericsson.otp.erlang.OtpExternal.portTag;
- tcV = PortHelper.type();
- }
-
-
- /**
- Object Stream extractor method
- @return OtpInputStream, the stream value of Term
- **/
- public com.ericsson.otp.erlang.OtpInputStream extract_Streamable() {
-
- if (is == null) {
- if (os == null) {
- if (stringV == null)
- return null;
- else {
- // A sequence that become a string !
- os = new com.ericsson.otp.erlang.OtpOutputStream();
- os.write_string(stringV);
- is = new com.ericsson.otp.erlang.OtpInputStream(os.toByteArray());
- }
- }
- else {
- is = new com.ericsson.otp.erlang.OtpInputStream(os.toByteArray());
- }
- }
-
- is.reset();
- return is;
- }
-
- /**
- Inserts Objects to Term
- **/
- public void insert_Object(com.ericsson.otp.erlang.OtpErlangObject o) {
- ObjV = o;
- }
-
- /**
- Extract Object value from Term
- @return OtpErlangObject, the Object value of Term
- **/
- public com.ericsson.otp.erlang.OtpErlangObject extract_Object() {
- return ObjV;
- }
-
-
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/TermHelper.java b/lib/ic/java_src/com/ericsson/otp/ic/TermHelper.java
deleted file mode 100644
index 1a6271d9c0..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/TermHelper.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-package com.ericsson.otp.ic;
-
-/**
- Helper class for Term.
- **/
-
-public class TermHelper {
-
- // Constructors
- private TermHelper() {}
-
- // Methods
- /**
- Marshal method for the Term class, encodes the Term object to the output stream.
- **/
- public static void marshal(com.ericsson.otp.erlang.OtpOutputStream _out, Term _any)
- throws java.lang.Exception {
-
- _any.write_value(_out);
- }
-
- /**
- Unmarshal method for the Term class, decodes a Term object from the stream.
- @return Term, read from the input stream
- **/
- public static Term unmarshal(com.ericsson.otp.erlang.OtpInputStream _in)
- throws java.lang.Exception {
-
- Term _value = new Term();
-
- int tag = _in.peek();
- if (tag == com.ericsson.otp.erlang.OtpExternal.versionTag) {
- _in.read1();
- tag = _in.peek();
- }
- _value.tag = tag;
-
-
- // Allways save the object in OtpErlangObject form
- _in.mark(0);
- com.ericsson.otp.erlang.OtpErlangObject _obj = _in.read_any();
- _value.insert_Object(_obj);
-
- switch (tag) {
- case com.ericsson.otp.erlang.OtpExternal.smallIntTag:
- case com.ericsson.otp.erlang.OtpExternal.intTag:
- case com.ericsson.otp.erlang.OtpExternal.smallBigTag:
- _in.reset();
- _value.longV = _in.read_long();
- break;
-
- case com.ericsson.otp.erlang.OtpExternal.atomTag:
- case com.ericsson.otp.erlang.OtpExternal.atomUtf8Tag:
- case com.ericsson.otp.erlang.OtpExternal.smallAtomUtf8Tag:
- _in.reset();
- _value.atomV = _in.read_atom();
- break;
-
- case com.ericsson.otp.erlang.OtpExternal.floatTag:
- _in.reset();
- _value.doubleV = _in.read_double();
- break;
-
- case com.ericsson.otp.erlang.OtpExternal.refTag:
- case com.ericsson.otp.erlang.OtpExternal.newRefTag:
- _in.reset();
- com.ericsson.otp.erlang.OtpErlangRef _eref =
- _in.read_ref();
-
- if (_eref.isNewRef())
- _value.RefV = new Ref(_eref.node(),_eref.ids(),_eref.creation());
- else
- _value.RefV = new Ref(_eref.node(),_eref.id(),_eref.creation());
-
- break;
-
- case com.ericsson.otp.erlang.OtpExternal.portTag:
- _in.reset();
- com.ericsson.otp.erlang.OtpErlangPort _eport =
- _in.read_port();
-
- _value.PortV = new Port(_eport.node(),_eport.id(),_eport.creation());
- break;
-
- case com.ericsson.otp.erlang.OtpExternal.pidTag:
- _in.reset();
- com.ericsson.otp.erlang.OtpErlangPid _epid =
- _in.read_pid();
-
- _value.PidV = new Pid(_epid.node(),_epid.id(),_epid.serial(),_epid.creation());
- break;
-
- case com.ericsson.otp.erlang.OtpExternal.stringTag:
- _in.reset();
- _value.stringV = _in.read_string();
- break;
-
- case com.ericsson.otp.erlang.OtpExternal.listTag:
- case com.ericsson.otp.erlang.OtpExternal.nilTag:
- case com.ericsson.otp.erlang.OtpExternal.smallTupleTag:
- case com.ericsson.otp.erlang.OtpExternal.largeTupleTag:
- case com.ericsson.otp.erlang.OtpExternal.binTag:
-
- com.ericsson.otp.erlang.OtpOutputStream _os =
- new com.ericsson.otp.erlang.OtpOutputStream();
-
- _obj.encode(_os);
- _value.insert_Streamable(_os);
- break;
-
- case com.ericsson.otp.erlang.OtpExternal.largeBigTag:
- default:
- throw new com.ericsson.otp.erlang.OtpErlangDecodeException("Uknown data type: " + tag);
- }
-
- return _value;
- }
-
-}
-
-
-
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/TermHolder.java b/lib/ic/java_src/com/ericsson/otp/ic/TermHolder.java
deleted file mode 100644
index 6a30bad5ea..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/TermHolder.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-package com.ericsson.otp.ic;
-
-/**
- Holder class for Term.
- **/
-
-final public class TermHolder {
-
- /**
- Term instance variable.
- **/
- public Term value;
-
- // Constructors
- public TermHolder() {}
-
- public TermHolder(Term initial) {
- value = initial;
- }
-
- // Methods
- /**
- Marshal method for the TermHolder class, encodes the Term object value to the output stream.
- **/
- public void _marshal(com.ericsson.otp.erlang.OtpOutputStream out)
- throws java.lang.Exception {
- TermHelper.marshal(out, value);
- }
-
- /**
- Unmarshal method for the TermHolder class, decodes a Term object from the output stream
- and assigns it to the Holder value field.
- **/
- public void _unmarshal(com.ericsson.otp.erlang.OtpInputStream in)
- throws java.lang.Exception {
- value = TermHelper.unmarshal(in);
- }
-
-}
diff --git a/lib/ic/java_src/com/ericsson/otp/ic/TypeCode.java b/lib/ic/java_src/com/ericsson/otp/ic/TypeCode.java
deleted file mode 100644
index da036fea54..0000000000
--- a/lib/ic/java_src/com/ericsson/otp/ic/TypeCode.java
+++ /dev/null
@@ -1,883 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/**
- * The TypeCode class for Java IDL
- *
- */
-package com.ericsson.otp.ic;
-
-/**
- The TypeCode class is the implementation of the OMG-IDL TypeCode type.
- **/
-
-public class TypeCode {
-
- private TCKind _kind;
- private java.lang.String _id,_name;
- private int _length,_member_count,_default_index;
- private TypeCode _member_type,_discriminator_type,_content_type;
- private Any _member_label;
- private boolean extracted;
- private TypeCode _members[];
- private java.lang.String _member_names[];
- private Any _member_labels[];
-
-
-
- /*
- * Constructors
- */
- public TypeCode() {
- extracted = false;
- _members = null;
- _member_names = null;
- _member_labels = null;
- _kind = null;
- _id = null;
- _name = null;
- _length = -1;
- _member_count = -1;
- _default_index = -1;
- _member_type = null;
- _content_type = null;
- _discriminator_type = null;
- _member_label = null;
- }
-
- public TypeCode(TCKind __kind) {
- _kind = __kind;
- }
-
-
- /*
- * Operation "TypeCode::equal"
- */
-
- /**
- Comparisson method for TypeCode.
- @return true if the input TypeCode value equals the value of the current object, false otherwize
- **/
- public boolean equal(TypeCode tc) {
-
- try {
-
- TCKind tck = tc.kind();
-
- switch (tck.value()) {
-
- case TCKind._tk_short:
- case TCKind._tk_long:
- case TCKind._tk_longlong:
- case TCKind._tk_ushort:
- case TCKind._tk_ulong:
- case TCKind._tk_ulonglong:
- case TCKind._tk_float:
- case TCKind._tk_double:
- case TCKind._tk_boolean:
- case TCKind._tk_char:
- case TCKind._tk_wchar:
- case TCKind._tk_octet:
- case TCKind._tk_string:
- case TCKind._tk_wstring:
- case TCKind._tk_any:
- case TCKind._tk_void:
- case TCKind._tk_atom:
-
- return (tck.value() == _kind.value());
-
- case TCKind._tk_struct:
-
- if((tc.id().compareTo(_id) == 0) &&
- (tc.name().compareTo(_name) == 0) &&
- (tc.member_count() == _member_count)){
-
- for (int i = 0; i < _member_count; i++)
- if (!tc.member_type(i).equal(_members[i]))
- return false;
-
- return true;
- }
- else
- return false;
-
- case TCKind._tk_union:
-
- if((tc.id().compareTo(_id) == 0) &&
- (tc.name().compareTo(_name) == 0) &&
- (tc.member_count() == _member_count) &&
- (tc.discriminator_type().equal(_discriminator_type))){
-
- for (int i = 0; i < _member_count; i++)
- if ((!tc.member_type(i).equal(_members[i])) &&
- (tc.member_name(i).compareTo(_member_names[i]) != 0))
- return false;
-
- return true;
- }
- else
- return false;
-
- case TCKind._tk_sequence:
- case TCKind._tk_array:
-
- if((tck.value() == _kind.value()) &&
- (tc.content_type().equal(_content_type)))
- return true;
- else
- return false;
-
- case TCKind._tk_enum:
- if((tck.value() == _kind.value()) &&
- (tc.member_count() == _member_count)) {
-
- for (int i = 0; i < _member_count; i++)
- if (tc.member_name(i).compareTo(_member_names[i]) != 0)
- return false;
-
- return true;
- }
- else
- return false;
-
- // Not used in real
- case TCKind._tk_null:
- case TCKind._tk_TypeCode:
- case TCKind._tk_Principal:
- case TCKind._tk_objref:
- case TCKind._tk_alias:
- case TCKind._tk_except:
- case TCKind._tk_longdouble:
- case TCKind._tk_fixed:
-
- return (tck.value() == _kind.value());
-
- default :
- return false;
-
- }
- } catch (Exception e) {
- return false;
- }
-
- }
-
-
- /*
- * Operation "TypeCode::kind"
- */
-
- /**
- Accessor method for the TCKind value of TypeCode.
- @return TCKind, the TCKind value of the TypeCode object.
- **/
- public TCKind kind() {
- return _kind;
- }
-
- /**
- Insertion method for the TCKind value of TypeCode.
- Sets the TCKind value of the object.
- **/
- public void kind(TCKind __kind) {
- _kind = __kind;
- }
-
- /**
- Insertion method for the TCKind value of TypeCode.
- Sets the TCKind value of the object.
- **/
- public static TCKind kind(java.lang.String atom)
- throws java.lang.Exception {
-
- if (atom.equals("tk_null"))
- return TCKind.tk_null;
- else
- if (atom.equals("tk_void"))
- return TCKind.tk_void;
- else
- if (atom.equals("tk_short"))
- return TCKind.tk_short;
- else
- if (atom.equals("tk_long"))
- return TCKind.tk_long;
- else
- if (atom.equals("tk_ushort"))
- return TCKind.tk_ushort;
- else
- if (atom.equals("tk_ulong"))
- return TCKind.tk_ulong;
- else
- if (atom.equals("tk_float"))
- return TCKind.tk_float;
- else
- if (atom.equals("tk_double"))
- return TCKind.tk_double;
- else
- if (atom.equals("tk_boolean"))
- return TCKind.tk_boolean;
- else
- if (atom.equals("tk_char"))
- return TCKind.tk_char;
- else
- if (atom.equals("tk_octet"))
- return TCKind.tk_octet;
- else
- if (atom.equals("tk_any"))
- return TCKind.tk_any;
- else
- if (atom.equals("tk_TypeCode"))
- return TCKind.tk_TypeCode;
- else
- if (atom.equals("tk_Principal"))
- return TCKind.tk_Principal;
- else
- if (atom.equals("tk_objref"))
- return TCKind.tk_objref;
- else
- if (atom.equals("tk_struct"))
- return TCKind.tk_struct;
- else
- if (atom.equals("tk_union"))
- return TCKind.tk_union;
- else
- if (atom.equals("tk_enum"))
- return TCKind.tk_enum;
- else
- if (atom.equals("tk_string"))
- return TCKind.tk_string;
- else
- if (atom.equals("tk_sequence"))
- return TCKind.tk_sequence;
- else
- if (atom.equals("tk_array"))
- return TCKind.tk_array;
- else
- if (atom.equals("tk_alias"))
- return TCKind.tk_alias;
- else
- if (atom.equals("tk_except"))
- return TCKind.tk_except;
- else
- if (atom.equals("tk_longlong"))
- return TCKind.tk_longlong;
- else
- if (atom.equals("tk_ulonglong"))
- return TCKind.tk_ulonglong;
- else
- if (atom.equals("tk_longdouble"))
- return TCKind.tk_longdouble;
- else
- if (atom.equals("tk_wchar"))
- return TCKind.tk_wchar;
- else
- if (atom.equals("tk_wstring"))
- return TCKind.tk_wstring;
- else
- if (atom.equals("tk_fixed"))
- return TCKind.tk_fixed;
- else
- if (atom.equals("tk_atom"))
- return TCKind.tk_atom;
- else
- throw new java.lang.Exception("BAD KIND");
-
- }
-
-
-
- /*
- * Operation "TypeCode::id"
- */
-
- /**
- Accessor method for the id value of TypeCode.
- @return String, the id value of TypeCode object
- **/
- public java.lang.String id()
- throws java.lang.Exception{
-
- if (_id == null)
- throw new java.lang.Exception("BAD KIND");
-
- return _id;
- }
-
-
- /**
- Insertion method for the id value of TypeCode.
- Sets the id value of the object.
- **/
- public void id(java.lang.String __id) {
-
- _id = __id;
- }
-
-
-
- /*
- * Operation "TypeCode::name"
- */
-
- /**
- Accessor method for the name value of TypeCode.
- @return String, the name value of TypeCode object
- **/
- public java.lang.String name()
- throws java.lang.Exception{
-
- if (_name == null)
- throw new java.lang.Exception("BAD KIND");
-
- return _name;
- }
-
- /**
- Insertion method for the name value of TypeCode.
- Sets the name value of the object.
- **/
- public void name(java.lang.String __name) {
- _name = __name;
- }
-
-
-
- /*
- * Operation "TypeCode::member_count"
- */
-
- /**
- Accessor method for the member number value of TypeCode.
- @return int, the number of members of TypeCode object
- **/
- public int member_count()
- throws java.lang.Exception{
-
- if (_member_count == -1)
- throw new java.lang.Exception("BAD KIND");
-
- return _member_count;
- }
-
- /**
- Insertion method for the member number value of TypeCode.
- Sets the number of members value of the object.
- **/
- public void member_count(int __member_count) {
-
- switch(_kind.value()) {
- case TCKind._tk_struct:
- _members = new TypeCode[__member_count];
- _member_names = new java.lang.String[__member_count];
- _member_count = __member_count;
- break;
- case TCKind._tk_union:
- _members = new TypeCode[__member_count];
- _member_names = new java.lang.String[__member_count];
- _member_labels = new Any[__member_count];
- _member_count = __member_count;
- break;
- case TCKind._tk_enum:
- _member_names = new java.lang.String[__member_count];
- _member_count = __member_count;
- break;
- default :
- // Do nothing
- }
- }
-
-
- /*
- * Operation "TypeCode::member_name"
- */
-
- /**
- Member name accessor method for TypeCode.
- @return String, the name value of the member of the TypeCode object
- on the selected index
- **/
- public java.lang.String member_name(int __index)
- throws java.lang.Exception{
-
- return _member_names[__index];
- }
-
- /**
- Insertion method for the indexed member name of TypeCode.
- Sets the name of a member value of the object at the selected index..
- **/
- public void member_name(int __index, java.lang.String __member_name) {
- _member_names[__index] = __member_name;
- }
-
-
- /*
- * Operation "TypeCode::member_type"
- */
-
- /**
- Member type accessor method for TypeCode.
- @return TypeCOde, the type of the member of the TypeCode object
- on the selected index
- **/
- public TypeCode member_type(int __index)
- throws java.lang.Exception{
-
- return _members[__index];
- }
-
- /**
- Insertion method for the indexed member type of TypeCode.
- Sets the type of a member value of the object at the selected index..
- **/
- public void member_type(int __index, TypeCode __member_type) {
- _members[__index] = __member_type;
- }
-
-
- /*
- * Operation "TypeCode::member_label"
- */
-
- /**
- Member label accessor method for TypeCode.
- @return Any, the label of the member of the TypeCode object
- on the selected index
- **/
- public Any member_label(int __index)
- throws java.lang.Exception{
-
- return _member_labels[__index];
- }
-
- /**
- Insertion method for the indexed member label of TypeCode.
- Sets the label of a member value of the object at the selected index.
- **/
- public void member_label(int __index, Any __member_label) {
- _member_labels[__index] = __member_label;
- }
-
-
- /*
- * Operation "TypeCode::discriminator_type"
- */
-
- /**
- Discriminator type accessor method for TypeCode.
- @return TypeCode, the type of the discriminator of the TypeCode object
- **/
- public TypeCode discriminator_type()
- throws java.lang.Exception{
-
- if (_discriminator_type == null)
- throw new java.lang.Exception("BAD KIND");
-
- return _discriminator_type;
- }
-
- /**
- Insertion method for the type of the discriminator value of TypeCode.
- Sets the discriminator type value of the object.
- **/
- public void discriminator_type(TypeCode __discriminator_type) {
- _discriminator_type = __discriminator_type;
- }
-
-
- /*
- * Operation "TypeCode::default_index"
- */
-
- /**
- Index accessor method for TypeCode.
- @return int, the default index value of the member of the TypeCode object
- **/
- public int default_index()
- throws java.lang.Exception{
-
- if (_default_index == -1)
- throw new java.lang.Exception("BAD KIND");
-
- return _default_index;
- }
-
- /**
- Insertion method for the default index value of TypeCode.
- Sets the default index value of the object.
- **/
- public void default_index(int __default_index) {
- _default_index = __default_index;
- }
-
-
- /*
- * Operation "TypeCode::length"
- */
-
- /**
- Length accessor method for TypeCode.
- @return int, the length of the TypeCode object
- **/
- public int length()
- throws java.lang.Exception{
-
- if (_length == -1)
- throw new java.lang.Exception("BAD KIND");
-
- return _length;
- }
-
- /**
- Insertion method for the length value of TypeCode.
- Sets the length value of the object.
- **/
- public void length(int __length) {
- _length = __length;
- }
-
-
- /*
- * Operation "TypeCode::content_type"
- */
-
- /**
- Content type accessor method for TypeCode.
- @return TypeCode, the content type of the TypeCode object
- **/
- public TypeCode content_type()
- throws java.lang.Exception {
-
- if (_content_type == null)
- throw new java.lang.Exception("BAD KIND");
-
- return _content_type;
- }
-
- /**
- Insertion method for the content type value of TypeCode.
- Sets the content type value of the object.
- **/
- public void content_type(TypeCode __content_type) {
- _content_type = __content_type;
- }
-
-
- /**
- Marshal operation for TypeCode.
- **/
- public static void marshal(com.ericsson.otp.erlang.OtpOutputStream _os, TypeCode _tc)
- throws java.lang.Exception {
-
- TypeCode memberTC = null;
- int len = -1;
-
- switch(_tc.kind().value()) {
-
- case TCKind._tk_short :
- _os.write_atom("tk_short");
- break;
- case TCKind._tk_ushort :
- _os.write_atom("tk_ushort");
- break;
- case TCKind._tk_long :
- _os.write_atom("tk_long");
- break;
- case TCKind._tk_longlong :
- _os.write_atom("tk_longlong");
- break;
- case TCKind._tk_ulong :
- _os.write_atom("tk_ulong");
- break;
- case TCKind._tk_ulonglong :
- _os.write_atom("tk_ulonglong");
- break;
- case TCKind._tk_float :
- _os.write_atom("tk_float");
- break;
- case TCKind._tk_double :
- _os.write_atom("tk_double");
- break;
- case TCKind._tk_boolean :
- _os.write_atom("tk_boolean");
- break;
- case TCKind._tk_char :
- _os.write_atom("tk_char");
- break;
- case TCKind._tk_wchar :
- _os.write_atom("tk_wchar");
- break;
- case TCKind._tk_octet :
- _os.write_atom("tk_octet");
- break;
- case TCKind._tk_string :
- _os.write_tuple_head(2);
- _os.write_atom("tk_string");
- _os.write_ulong(_tc.length());
- break;
- case TCKind._tk_wstring :
- _os.write_tuple_head(2);
- _os.write_atom("tk_wstring");
- _os.write_ulong(_tc.length());
- break;
- case TCKind._tk_struct:
- len = _tc.member_count();
- _os.write_tuple_head(4);
- _os.write_atom("tk_struct");
- _os.write_string(_tc.id());
- _os.write_string(_tc.name());
- // Member list
- _os.write_list_head(len);
- for(int i=0; i<len; i++) {
- _os.write_tuple_head(2);
- _os.write_string(_tc.member_name(i));
- marshal(_os,_tc.member_type(i));
- }
- _os.write_nil();
- break;
- case TCKind._tk_union:
- len = _tc.member_count();
- _os.write_tuple_head(6);
- _os.write_atom("tk_union");
- _os.write_string(_tc.id());
- _os.write_string(_tc.name());
- marshal(_os,_tc.discriminator_type());
- _os.write_int(_tc.default_index());
- // Member list
- _os.write_list_head(len);
- for(int i=0; i<len; i++) {
- _os.write_tuple_head(3);
- _tc.member_label(i).write_value(_os);
- _os.write_string(_tc.member_name(i));
- marshal(_os,_tc.member_type(i));
- }
- _os.write_nil();
- break;
- case TCKind._tk_sequence:
- _os.write_tuple_head(3);
- _os.write_atom("tk_sequence");
- marshal(_os,_tc.content_type());
- _os.write_int(_tc.length());
- break;
- case TCKind._tk_array:
- _os.write_tuple_head(3);
- _os.write_atom("tk_array");
- marshal(_os,_tc.content_type());
- _os.write_int(_tc.length());
- break;
- case TCKind._tk_enum:
- len = _tc.member_count();
- _os.write_tuple_head(4);
- _os.write_atom("tk_enum");
- _os.write_string(_tc.id());
- _os.write_string(_tc.name());
- _os.write_list_head(len);
- for(int i=0; i<len; i++)
- _os.write_string(_tc.member_name(i));
- _os.write_nil();
- break;
- case TCKind._tk_any:
- _os.write_atom("tk_any");
- break;
- case TCKind._tk_void :
- _os.write_atom("tk_void");
- break;
- /*
- * Not supported types
- */
- default :
- throw new java.lang.Exception("Unsupported type");
-
- }
-
- }
-
-
- /**
- Unmarshal operation for TypeCode.
- @return TypeCode, the TypeCode read from the input stream.
- **/
- public static TypeCode unmarshal(com.ericsson.otp.erlang.OtpInputStream _is)
- throws java.lang.Exception {
-
- TypeCode _tc, __member;
- TCKind __kind;
- int __len;
- int __tag = _is.peek();
-
- switch(__tag) {
- case (com.ericsson.otp.erlang.OtpExternal.atomTag):
- case (com.ericsson.otp.erlang.OtpExternal.atomUtf8Tag):
- case (com.ericsson.otp.erlang.OtpExternal.smallAtomUtf8Tag):
- __kind = TypeCode.kind(_is.read_atom());
-
- switch(__kind.value()) {
- case TCKind._tk_short :
- case TCKind._tk_ushort :
- case TCKind._tk_long :
- case TCKind._tk_longlong :
- case TCKind._tk_ulong :
- case TCKind._tk_ulonglong :
- case TCKind._tk_float :
- case TCKind._tk_double :
- case TCKind._tk_boolean :
- case TCKind._tk_char :
- case TCKind._tk_wchar :
- case TCKind._tk_octet :
- case TCKind._tk_void :
- case TCKind._tk_any :
- _tc = new TypeCode();
- _tc.kind(__kind);
-
- return _tc;
- default :
- throw new java.lang.Exception("Unsupported type");
- }
-
- case (com.ericsson.otp.erlang.OtpExternal.smallTupleTag):
- case (com.ericsson.otp.erlang.OtpExternal.largeTupleTag):
-
- __len = _is.read_tuple_head();
- __tag = _is.peek();
-
- switch(__tag) {
-
- case (com.ericsson.otp.erlang.OtpExternal.atomTag):
- case (com.ericsson.otp.erlang.OtpExternal.atomUtf8Tag):
- case (com.ericsson.otp.erlang.OtpExternal.smallAtomUtf8Tag):
-
- __kind = TypeCode.kind(_is.read_atom());
- _tc = new TypeCode();
- _tc.kind(__kind);
-
- switch(__kind.value()) {
-
- case TCKind._tk_string :
- _tc.length((int)_is.read_ulong());
- return _tc;
-
- case TCKind._tk_wstring :
- _tc.length((int)_is.read_ulong());
- return _tc;
-
- case TCKind._tk_struct:
-
- _tc.id(_is.read_string());
- _tc.name(_is.read_string());
- __len = _is.read_list_head();
- _tc.member_count(__len);
-
- for(int i=0; i<__len; i++) {
- _is.read_tuple_head();
- _tc.member_name(i,_is.read_string());
- _tc.member_type(i,unmarshal(_is));
- }
- _is.read_nil();
-
- return _tc;
-
-
- case TCKind._tk_union:
-
- _tc.id(_is.read_string());
- _tc.name(_is.read_string());
- _tc.discriminator_type(unmarshal(_is));
- _tc.default_index(_is.read_int());
- __len = _is.read_list_head();
- _tc.member_count(__len);
-
- for(int i=0; i<__len; i++) {
- _is.read_tuple_head();
-
- __tag = _is.peek();
- Any __label = new Any();
- TypeCode __label_type = new TypeCode();
-
- __label_type.kind(com.ericsson.otp.ic.TCKind.tk_long);
- __label.type(__label_type);
-
- switch(__tag) {
- case (com.ericsson.otp.erlang.OtpExternal.stringTag):
- java.lang.String __enum = _is.read_string();
- __label.insert_string(__enum);
- break;
- case (com.ericsson.otp.erlang.OtpExternal.atomTag):
- case (com.ericsson.otp.erlang.OtpExternal.atomUtf8Tag):
- case (com.ericsson.otp.erlang.OtpExternal.smallAtomUtf8Tag):
-
- java.lang.String __default = _is.read_atom();
- __label.insert_atom(__default);
- break;
- default:
- __label.insert_long(_is.read_int());
- }
-
- _tc.member_label(i,__label);
- _tc.member_name(i,_is.read_string());
- _tc.member_type(i,unmarshal(_is));
- }
- _is.read_nil();
-
- return _tc;
-
-
- case TCKind._tk_sequence:
- _tc.content_type(unmarshal(_is));
- _tc.length(_is.read_int());
- return _tc;
-
-
- case TCKind._tk_array:
- _tc.content_type(unmarshal(_is));
- _tc.length(_is.read_int());
- return _tc;
-
-
- case TCKind._tk_enum:
-
- _tc.id(_is.read_string());
- _tc.name(_is.read_string());
- __len = _is.read_list_head();
- _tc.member_count(__len);
-
- for(int i=0; i<__len; i++)
- _tc.member_name(i,_is.read_string());
-
- _is.read_nil();
-
- return _tc;
-
- default:
- throw new java.lang.Exception("Unsupported type");
-
- }
-
- default:
- throw new java.lang.Exception("Unsupported type");
- }
-
- }
-
- return null;
- }
-
-}
-
-
diff --git a/lib/ic/prebuild.skip b/lib/ic/prebuild.skip
deleted file mode 100644
index 8d1ef24091..0000000000
--- a/lib/ic/prebuild.skip
+++ /dev/null
@@ -1 +0,0 @@
-priv
diff --git a/lib/ic/priv/lib/.gitignore b/lib/ic/priv/lib/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ic/priv/lib/.gitignore
+++ /dev/null
diff --git a/lib/ic/priv/obj/.gitignore b/lib/ic/priv/obj/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/ic/priv/obj/.gitignore
+++ /dev/null
diff --git a/lib/ic/src/Makefile b/lib/ic/src/Makefile
deleted file mode 100644
index 6ad2fbeeb7..0000000000
--- a/lib/ic/src/Makefile
+++ /dev/null
@@ -1,219 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1998-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-
-ifeq ($(TYPE),debug)
-ERL_COMPILE_FLAGS += -Ddebug -W
-endif
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(IC_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/ic-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES= \
- ic \
- ic_erlbe \
- ic_cbe \
- icscan \
- icparse \
- iceval \
- ictype \
- ictk \
- icstruct \
- icenum \
- icpreproc \
- icunion \
- ic_pp \
- ic_pragma \
- ic_noc \
- ic_plainbe \
- ic_cclient \
- ic_cserver \
- ic_fetch \
- ic_code \
- ic_codegen \
- ic_error \
- ic_file \
- ic_forms \
- ic_genobj \
- ic_options \
- ic_symtab \
- ic_util \
- ic_jbe \
- ic_struct_java \
- ic_union_java \
- ic_enum_java \
- ic_constant_java \
- ic_sequence_java \
- ic_array_java \
- ic_attribute_java \
- ic_java_type \
- ic_erl_template
-
-
-CCL_EX_FILES = \
- ../examples/c-client/ReadMe \
- ../examples/c-client/Makefile \
- ../examples/c-client/client.c \
- ../examples/c-client/random.idl \
- ../examples/c-client/rmod_random_impl.erl \
- ../examples/c-client/test.erl
-
-CSRV_EX_FILES = \
- ../examples/c-server/ReadMe \
- ../examples/c-server/Makefile \
- ../examples/c-server/client.c \
- ../examples/c-server/client.erl \
- ../examples/c-server/server.c \
- ../examples/c-server/callbacks.c \
- ../examples/c-server/random.idl
-
-EPL_EX_FILES = \
- ../examples/erl-plain/ReadMe \
- ../examples/erl-plain/rmod_random_impl.erl \
- ../examples/erl-plain/random.idl
-
-
-ESRV_EX_FILES = \
- ../examples/erl-genserv/ReadMe \
- ../examples/erl-genserv/rmod_random_impl.erl \
- ../examples/erl-genserv/random.idl
-
-JAVA_EX_FILES = \
- ../examples/java-client-server/ReadMe \
- ../examples/java-client-server/client.java \
- ../examples/java-client-server/server.java \
- ../examples/java-client-server/serverImpl.java \
- ../examples/java-client-server/random.idl
-
-MIXED_EX_FILES = \
- ../examples/all-against-all/ReadMe \
- ../examples/all-against-all/Makefile \
- ../examples/all-against-all/client.erl \
- ../examples/all-against-all/server.erl \
- ../examples/all-against-all/client.c \
- ../examples/all-against-all/server.c \
- ../examples/all-against-all/callbacks.c \
- ../examples/all-against-all/client.java \
- ../examples/all-against-all/server.java \
- ../examples/all-against-all/serverImpl.java \
- ../examples/all-against-all/random.idl
-
-
-EXTERNAL_HRL_FILES=
-
-INTERNAL_HRL_FILES = \
- ic.hrl \
- ic_debug.hrl \
- icforms.hrl
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-YRL_FILE = icparse.yrl
-
-GEN_FILES = icparse.erl
-
-APP_FILE = ic.app
-APP_SRC = $(APP_FILE).src
-APP_TARGET = $(EBIN)/$(APP_FILE)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_LOCAL_FLAGS += -pa ../../ic/ebin
-# The -pa option is just used temporary until erlc can handle
-# includes from other directories than ../include .
-ERL_COMPILE_FLAGS += \
- $(ERL_LOCAL_FLAGS) \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,app_vsn,"ic_$(VSN)"}' \
- -D'COMPILERVSN="$(VSN)"'
-YRL_FLAGS = -Iicyeccpre.hrl
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-debug:
- @${MAKE} TYPE=debug opt
-
-opt: $(TARGET_FILES) $(APP_TARGET)
-
-clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET)
- rm -f errs core *~
-
-$(APP_TARGET): $(APP_SRC) ../vsn.mk
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
-
-docs:
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-../ebin/icparse.beam: icparse.erl
- $(V_ERLC) $(ERL_COMPILE_FLAGS) +nowarn_unused_vars +nowarn_unused_function -o$(EBIN) +pj $<
-
-icparse.erl: icparse.yrl icyeccpre.hrl
-
-### $(ERLC) $(YRL_FLAGS) $<
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) "$(RELSYSDIR)/ebin"
- $(INSTALL_DIR) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(ERL_FILES) $(YRL_FILE) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src"
- $(INSTALL_DIR) "$(RELSYSDIR)/examples"
- $(INSTALL_DIR) "$(RELSYSDIR)/examples/c-client"
- $(INSTALL_DATA) $(CCL_EX_FILES) "$(RELSYSDIR)/examples/c-client"
- $(INSTALL_DIR) "$(RELSYSDIR)/examples/c-server"
- $(INSTALL_DATA) $(CSRV_EX_FILES) "$(RELSYSDIR)/examples/c-server"
- $(INSTALL_DIR) "$(RELSYSDIR)/examples/erl-plain"
- $(INSTALL_DATA) $(EPL_EX_FILES) "$(RELSYSDIR)/examples/erl-plain"
- $(INSTALL_DIR) "$(RELSYSDIR)/examples/erl-genserv"
- $(INSTALL_DATA) $(ESRV_EX_FILES) "$(RELSYSDIR)/examples/erl-genserv"
- $(INSTALL_DIR) "$(RELSYSDIR)/examples/java-client-server"
- $(INSTALL_DATA) $(JAVA_EX_FILES) "$(RELSYSDIR)/examples/java-client-server"
- $(INSTALL_DIR) "$(RELSYSDIR)/examples/all-against-all"
- $(INSTALL_DATA) $(MIXED_EX_FILES) "$(RELSYSDIR)/examples/all-against-all"
-
-release_docs_spec:
-
diff --git a/lib/ic/src/ic.app.src b/lib/ic/src/ic.app.src
deleted file mode 100644
index 7dd47ac9c6..0000000000
--- a/lib/ic/src/ic.app.src
+++ /dev/null
@@ -1,53 +0,0 @@
-{application, ic,
- [{description, "The IDL Compiler"},
- {vsn, "%VSN%"},
- {modules,
- [
- ic,
- ic_cclient,
- ic_cbe,
- ic_cserver,
- ic_erlbe,
- ic_fetch,
- ic_noc,
- ic_plainbe,
- ic_pp,
- ic_pragma,
- icenum,
- iceval,
- icparse,
- icpreproc,
- icscan,
- icstruct,
- ictk,
- ictype,
- ic_array_java,
- ic_attribute_java,
- ic_code,
- ic_codegen,
- ic_constant_java,
- ic_enum_java,
- ic_error,
- ic_file,
- ic_forms,
- ic_genobj,
- ic_java_type,
- ic_jbe,
- ic_options,
- ic_sequence_java,
- ic_struct_java,
- ic_symtab,
- ic_union_java,
- ic_util,
- icunion,
- ic_erl_template
- ]
- },
- {registered, []},
- {applications, [stdlib, kernel]},
- {env, []},
- {mod, {ic, []}},
- {runtime_dependencies, ["stdlib-2.0","kernel-3.0","erts-6.0"]}
-]}.
-
-
diff --git a/lib/ic/src/ic.erl b/lib/ic/src/ic.erl
deleted file mode 100644
index 062fbef435..0000000000
--- a/lib/ic/src/ic.erl
+++ /dev/null
@@ -1,415 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(ic).
-
-
--export([sgen/1, gen/1, gen/2, help/0, compile/3]).
-
-
-%%------------------------------------------------------------
-%%
-%% Internal stuff
-%%
-%%------------------------------------------------------------
-
--export([filter_params/2, handle_preproc/4, do_gen/4]).
-
--import(lists, [foldr/3]).
-
-
--include("icforms.hrl").
--include("ic.hrl").
-
--include_lib("stdlib/include/erl_compile.hrl").
-
--export([make_erl_options/1]). % For erlc
-
--export([main/3, do_scan/1, do_parse/2, do_type/2]).
-
-
-%%------------------------------------------------------------
-%%
-%% Entry point
-%%
-%%------------------------------------------------------------
-
-%% compile(AbsFileName, Outfile, Options)
-%% Compile entry point for erl_compile.
-
-compile(File, _OutFile, Options) ->
- case gen(File, make_erl_options(Options)) of
- ok -> ok;
- Other -> Other
- end.
-
-
-%% Entry for the -s switch
-sgen(ArgList) ->
-%%% io:format("sgen called w ~p~n", [ArgList]),
- apply(?MODULE, gen, ArgList).
-
-
-gen(File) ->
- gen(File, []).
-
-gen(File, Opts) ->
- G = ic_genobj:new(Opts),
- IdlFile = ic_file:add_dot_idl(File),
- case ic_options:get_opt(G, show_opts) of
- true ->
- io:format("Opts: ~p~n", [ic_options:which_opts(G)]);
- _ -> ok
- end,
- ic_genobj:set_idlfile(G, IdlFile),
- case catch gen2(G, File, Opts) of
- {_, {'EXIT', R}} ->
- ic_genobj:free_table_space(G), %% Free space for all ETS tables
- io:format("Fatal error : ~p~n",[R]),
- error;
- {_, {'EXIT', _, R}} ->
- ic_genobj:free_table_space(G), %% Free space for all ETS tables
- io:format("Fatal error : ~p~n",[R]),
- error;
- {'EXIT', R} ->
- ic_genobj:free_table_space(G), %% Free space for all ETS tables
- io:format("Fatal error : ~p~n",[R]),
- error;
- {'EXIT', _, R} ->
- ic_genobj:free_table_space(G), %% Free space for all ETS tables
- io:format("Fatal error : ~p~n",[R]),
- error;
- %% In this case, the pragma registration
- %% found errors so this should return error.
- error ->
- ic_genobj:free_table_space(G), %% Free space for all ETS tables
- error;
- _ ->
- X = ic_error:return(G),
- ic_genobj:free_table_space(G), %% Free space for all ETS tables
- X
- end.
-
-
-gen2(G, File, Opts) ->
- case ic_options:get_opt(G, time) of
- true ->
- time("TOTAL ", ic, main, [G, File, Opts]);
- _ ->
- case main(G, File, Opts) of
- error ->
- error;
- _ ->
- ok
- end
- end.
-
-
-
-do_gen(erl_corba, G, File, T) ->
- ic_erlbe:do_gen(G, File, T);
-do_gen(erl_template, G, File, T) ->
- ic_erl_template:do_gen(G, File, T);
-do_gen(erl_genserv, G, File, T) ->
- ic_erlbe:do_gen(G, File, T);
-do_gen(c_genserv, G, File, T) ->
- ic_cclient:do_gen(G, File, T);
-do_gen(noc, G, File, T) ->
- ic_noc:do_gen(G, File, T);
-do_gen(erl_plain, G, File, T) ->
- ic_plainbe:do_gen(G, File, T);
-do_gen(c_server, G, File, T) ->
- ic_cserver:do_gen(G, File, T);
-do_gen(c_client, G, File, T) ->
- ic_cclient:do_gen(G, File, T);
-%% Java backend
-do_gen(java, G, File, T) ->
- ic_jbe:do_gen(G, File, T);
-%% No language choice
-do_gen(_,_,_,_) ->
- ok.
-
-do_scan(G) ->
- icscan:scan(G, ic_genobj:idlfile(G)).
-
-
-do_parse(G, Tokens) ->
- case icparse:parse(Tokens) of
- {ok, L} -> L;
- X when element(1, X) == error ->
- Err = element(2, X),
- ic_error:fatal_error(G, {parse_error, element(1, Err),
- element(3, Err)});
- X -> exit(X)
- end.
-
-
-do_type(G, Form) ->
- ictype:type_check(G, Form).
-
-time(STR,M,F,A) ->
- case timer:tc(M, F, A) of
- {_, {'EXIT', R}} -> exit(R);
- {_, {'EXIT', _, R}} -> exit(R);
- {_, _X} when element(1, _X)==error -> throw(_X);
- {_T, _R} ->
- io:format("Time for ~s: ~10.2f~n", [STR, _T/1000000]),
- _R
- end.
-
-
-
-%% Filters parameters so that only those with certain attributes are
-%% seen. The filter parameter is a list of attributes that will be
-%% seen, ex. [in] or [inout, out]
-filter_params(Filter, Params) ->
- lists:filter(fun(P) ->
- lists:member(get_param_attr(P#param.inout), Filter) end,
- Params).
-
-
-%% Access primitive to get the attribute name (and discard the line
-%% number).
-get_param_attr({A, _N}) -> A.
-
-
-%%
-%% Fixing the preproc directives
-%%
-handle_preproc(G, _N, line_nr, X) ->
- Id = ic_forms:get_id2(X),
- Flags = X#preproc.aux,
- case Flags of
- [] -> ic_genobj:push_file(G, Id);
- _ ->
- foldr(fun({_, _, "1"}, Gprim) -> ic_genobj:push_file(Gprim, Id);
- ({_, _, "2"}, Gprim) -> ic_genobj:pop_file(Gprim, Id);
- ({_, _, "3"}, Gprim) -> ic_genobj:sys_file(Gprim, Id) end,
- G, Flags)
- end;
-handle_preproc(G, _N, _Other, _X) ->
- G.
-
-
-
-%%------------------------------------------------------------
-%%
-%% The help department
-%%
-%%
-%%
-%%------------------------------------------------------------
-
-help() ->
- io:format("No help available at the moment~n", []),
- ok.
-
-print_version_str(G) ->
- case {ic_options:get_opt(G, silent), ic_options:get_opt(G, silent2)} of
- {true, _} -> ok;
- {_, true} -> ok;
- _ ->
- io:format("Erlang IDL compiler version ~s~n", [?COMPILERVSN])
- end.
-
-
-
-%%
-%% Converts generic compiler options to specific options.
-%%
-%% Used by erlc
-%%
-
-make_erl_options(Opts) ->
-
- %% This way of extracting will work even if the record passed
- %% has more fields than known during compilation.
-
- Includes1 = Opts#options.includes,
- Defines = Opts#options.defines,
- Outdir = Opts#options.outdir,
- Warning = Opts#options.warning,
- Verbose = Opts#options.verbose,
- Specific = Opts#options.specific,
- Optimize = Opts#options.optimize,
- PreProc =
- lists:flatten(
- lists:map(fun(D) -> io_lib:format("-I\"~ts\" ", [ic_util:to_list(D)]) end,
- Includes1)++
- lists:map(
- fun ({Name, Value}) ->
- io_lib:format("-D~s=~s ", [ic_util:to_list(Name), ic_util:to_list(Value)]);
- (Name) ->
- io_lib:format("-D~s ", [ic_util:to_list(Name)])
- end,
- Defines)),
- Options =
- case Verbose of
- true -> [];
- false -> []
- end ++
- case Warning of
- 0 -> [nowarn];
- _ -> ['Wall']
- end ++
- case Optimize of
- 0 -> [];
- _ -> []
- end,
-
- Options++[{outdir, Outdir}, {preproc_flags, PreProc}]++Specific.
-
-
-%%%
-%%% NEW main, avoids memory fragmentation
-%%%
-main(G, File, _Opts) ->
- print_version_str(G),
- ?ifopt(G, time, io:format("File ~p compilation started : ~p/~p/~p ~p:~2.2.0p~n",
- [ic_genobj:idlfile(G),
- element(1,date()),
- element(2, date()),
- element(3, date()),
- element(1, time()),
- element(2, time())])),
-
- case ic_options:get_opt(G, help) of
- true -> help();
-
- _ ->
- scanning(G, File)
- end.
-
-
-
-scanning(G, File) ->
- S = ?ifopt2(G, time,
- time("input file scanning ", ic, do_scan, [G]),
- ic:do_scan(G)),
- ?ifopt2(G, tokens, io:format("TOKENS: ~p~n", [S]),
- parsing(G, File, S)).
-
-parsing(G, File, S) ->
- T = ?ifopt2(G,
- time,
- time("input file parsing ", ic, do_parse, [G,S]),
- ic:do_parse(G,S)),
- ?ifopt2(G, form, io:format("PARSE FORM: ~p~n", [T]),
- pragma(G, File, T)).
-
-
-
-pragma(G, File, T) ->
- case ?ifopt2(G,
- time,
- time("pragma registration ", ic_pragma, pragma_reg, [G,T]),
- ic_pragma:pragma_reg(G,T)) of
- %% All pragmas were successfully applied
- {ok,Clean} ->
- typing(G, File, Clean);
-
- error ->
- error
- end.
-
-
-typing(G, File, Clean) ->
- case catch ?ifopt2(G,
- time,
- time("type code appliance ", ic, do_type, [G,Clean]),
- ic:do_type(G,Clean)) of
- {'EXIT',Reason} ->
- io:format("Error under type appliance : ~p~n",[Reason]),
- error;
-
- T2 ->
- ?ifopt2(G, tform, io:format("TYPE FORM: ~p~n", [T2]),
- generation(G, File, T2))
- end.
-
-
-
-generation(G, File, T2) ->
- case ic_options:get_opt(G, multiple_be) of
- false ->
- single_generation(G, File, T2);
- List ->
- OutDir =
- case ic_options:get_opt(G, outdir) of
- false ->
- [];
- Dir ->
- Dir
- end,
-
- case ic_options:get_opt(G, be) of
- false ->
- ok;
- Be ->
- %% Generate this first
- ic_options:add_opt(G,[{outdir,OutDir++atom_to_list(Be)}],true),
- single_generation(G, File, T2)
- end,
- multiple_generation(G, File, T2, OutDir, List)
- end.
-
-multiple_generation(_G, _File, _T2, _RootDir, []) ->
- ok;
-multiple_generation(G, File, T2, RootDir, [Be|Bes]) ->
- ic_options:add_opt(G,[{outdir,RootDir++atom_to_list(Be)}],true),
- ic_options:add_opt(G,[{be,Be}],true),
- single_generation(G, File, T2),
-
- case ic_error:get_error_count(G) of
- 0 ->
- multiple_generation(G,File,T2,RootDir,Bes);
- _ ->
- %% Errors reported, abort
- ok
- end.
-
-
-single_generation(G, File, T2) ->
- case ic_error:get_error_count(G) of
- 0 ->
- %% Check if user has sett backend option
- case ic_options:get_opt(G, be) of
- false ->
- %% Use default backend option
- DefaultBe = ic_options:defaultBe(),
- ic_options:add_opt(G,[{be,DefaultBe}],true),
-
- ?ifopt2(G,
- time,
- time("code generation ", ic, do_gen, [DefaultBe, G, File, T2]),
- ic:do_gen(DefaultBe, G, File, T2));
- Be ->
- %% Use user defined backend
- ?ifopt2(G,
- time,
- time("code generation ", ic, do_gen, [Be, G, File, T2]),
- ic:do_gen(Be, G, File, T2))
- end;
- _ ->
- ok %% Does not matter
- end.
-
-
-
diff --git a/lib/ic/src/ic.hrl b/lib/ic/src/ic.hrl
deleted file mode 100644
index cf4b6a50d6..0000000000
--- a/lib/ic/src/ic.hrl
+++ /dev/null
@@ -1,159 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-
-%%------------------------------------------------------------
-%% Configuration macros
--define(CORBAMOD, corba).
--define(ORBNAME, orber).
--define(CORBAHRL, "corba.hrl").
--define(CALL, "call").
--define(CAST, "cast").
--define(IFRREGID, "register").
--define(IFRTYPESHRL, "ifr_types.hrl").
-
--define(GENSERVMOD, gen_server).
-
-%%------------------------------------------------------------
-%% Flags. NOTE! Once assigned value may NOT be changed. Deprecate ok.
-%% Default flags. Can be changed if we change the default behavior.
--define(IC_FLAG_TEMPLATE_1, 16#01).
--define(IC_FLAG_TEMPLATE_2, 16#02).
-
--define(IC_INIT_FLAGS, 16#00).
-
-%% Flag operations
-%% USAGE: Boolean = ?IC_FLAG_TEST(Flags, ?IC_ATTRIBUTE)
--define(IC_FLAG_TEST(_F1, _I1), ((_F1 band _I1) == _I1)).
-
-%% USAGE: NewFlags = ?IC_SET_TRUE(Flags, ?IC_ATTRIBUTE)
--define(IC_SET_TRUE(_F2, _I2), (_I2 bor _F2)).
-
-%% USAGE: NewFlags = ?IC_SET_FALSE(Flags, ?IC_ATTRIBUTE)
--define(IC_SET_FALSE(_F3, _I3), ((_I3 bxor 16#ff) band _F3)).
-
-%% USAGE: NewFlags = ?IC_SET_FALSE_LIST(Flags, [?IC_SEC_ATTRIBUTE, ?IC_SOME])
--define(IC_SET_FALSE_LIST(_F4, _IList1),
- lists:foldl(fun(_I4, _F5) ->
- ((_I4 bxor 16#ff) band _F5)
- end,
- _F4, _IList1)).
-
-%% USAGE: NewFlags = ?IC_SET_TRUE_LIST(Flags, [?IC_ATTRIBUTE, ?IC_SOME])
--define(IC_SET_TRUE_LIST(_F6, _IList2),
- lists:foldl(fun(_I6, _F7) ->
- (_I6 bor _F7)
- end,
- _F6, _IList2)).
-
-%% USAGE: Boolean = ?IC_FLAG_TEST_LIST(Flags, [?IC_CONTEXT, ?IC_THING])
--define(IC_FLAG_TEST_LIST(_F8, _IList3),
- lists:all(fun(_I7) ->
- ((_F8 band _I7) == _I7)
- end,
- _IList3)).
-
-
-%%------------------------------------------------------------
-%% Usefull macros
-
--define(ifthen(P,ACTION), if P -> ACTION; true->true end).
-
-
-%%------------------------------------------------------------
-%% Option macros
-
--define(ifopt(G,OPT,ACTION),
- case ic_options:get_opt(G,OPT) of true -> ACTION; _ -> ok end).
-
--define(ifopt2(G,OPT,ACT1,ACT2),
- case ic_options:get_opt(G,OPT) of true -> ACT1; _ -> ACT2 end).
-
--define(ifnopt(G,OPT,ACTION),
- case ic_options:get_opt(G,OPT) of false -> ACTION; _ -> ok end).
-
-
-%% Internal record
--record(id_of, {id, type, tk}).
-
-%%--------------------------------------------------------------------
-%% The generator object definition
-
--record(genobj, {symtab, impl, options, warnings, auxtab,
- tktab, pragmatab, c_typedeftab,
- skelfile=[], skelfiled=[], skelscope=[],
- stubfile=[], stubfiled=[], stubscope=[],
- includefile=[], includefiled=[],
- interfacefile=[],interfacefiled=[],
- helperfile=[],helperfiled=[],
- holderfile=[],holderfiled=[],
- filestack=0, do_gen=true, sysfile=false}).
-
-%%--------------------------------------------------------------------
-%% The scooped id definition
--record(scoped_id, {type=local, line=-1, id=""}).
-
-
-
-
-
-
-
-
-%%--------------------------------------------------------------------
-%% Secret macros
-%%
-%% NOTE these macros are not general, they cannot be used
-%% everywhere.
-%%
--define(lookup(T,K), case ets:lookup(T, K) of [{_X, _Y}] -> _Y; _->[] end).
--define(insert(T,K,V), ets:insert(T, {K, V})).
-
-
-%%---------------------------------------------------------------------
-%%
-%% Java specific macros
-%%
-%%
--define(ERLANGPACKAGE,"com.ericsson.otp.erlang.").
--define(ICPACKAGE,"com.ericsson.otp.ic.").
-
-
-%%
-%% Macros for reporting encode/decode errors in C back-ends.
-%%
-%%
-
--define(emit_c_enc_rpt(Fd, Fill, Fmt, Vals),
- begin
- CType = ic_cbe:mk_c_type2(G, N, T),
- ic_codegen:emit_c_enc_rpt(Fd, Fill, "~s : " ++ Fmt, [CType| Vals])
- end).
--define(emit_c_dec_rpt(Fd, Fill, Fmt, Vals),
- begin
- CType = ic_cbe:mk_c_type2(G, N, T),
- ic_codegen:emit_c_dec_rpt(Fd, Fill, "~s : " ++ Fmt, [CType| Vals])
- end).
-
-
-
-
-
diff --git a/lib/ic/src/ic_array_java.erl b/lib/ic/src/ic_array_java.erl
deleted file mode 100644
index 64d1b8a9ba..0000000000
--- a/lib/ic/src/ic_array_java.erl
+++ /dev/null
@@ -1,296 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ic_array_java).
-
--export([gen/4]).
-
--include("ic.hrl").
--include("icforms.hrl").
-
-
-gen(G, N, X, Array) when is_record(X, member) ->
- ArrayName = ic_forms:get_java_id(Array),
- ArrayElement = ic_forms:get_type(X),
- emit_holder_class(G, N, X, Array, ArrayName, ArrayElement),
- emit_helper_class(G, N, X, Array, ArrayName, ArrayElement);
-gen(G, N, X, Array) when is_record(X, case_dcl) ->
- ArrayName = ic_forms:get_java_id(Array),
- ArrayElement = ic_forms:get_type(X),
- emit_holder_class(G, N, X, Array, ArrayName, ArrayElement),
- emit_helper_class(G, N, X, Array, ArrayName, ArrayElement);
-gen(G, N, X, Array) ->
- ArrayName = ic_forms:get_java_id(Array),
- ArrayElement = ic_forms:get_body(X),
- emit_holder_class(G, N, X, Array, ArrayName, ArrayElement),
- emit_helper_class(G, N, X, Array, ArrayName, ArrayElement).
-
-
-
-%%-----------------------------------------------------------------
-%% Func: emit_holder_class/4
-%%-----------------------------------------------------------------
-emit_holder_class(G, N, _X, Array, ArrayName, ArrayElement) ->
- SName = string:concat(ArrayName, "Holder"),
- {Fd, _}= ic_file:open_java_file(G, N, SName),
-
- ArrayElementName = ic_java_type:getType(G, N, ArrayElement),
- EmptyDim = arrayEmptyDim(Array),
-
- ic_codegen:emit(Fd, "final public class ~sHolder {\n",[ArrayName]),
-
- ic_codegen:emit(Fd, " // instance variables\n", []),
- ic_codegen:emit(Fd, " public ~s~s value;\n\n",
- [ArrayElementName,EmptyDim]),
-
- ic_codegen:emit(Fd, " // constructors\n", []),
- ic_codegen:emit(Fd, " public ~sHolder() {}\n", [ArrayName]),
- ic_codegen:emit(Fd, " public ~sHolder(~s~s initial) {\n",
- [ArrayName,ArrayElementName,EmptyDim]),
- ic_codegen:emit(Fd, " value = initial;\n", []),
- ic_codegen:emit(Fd, " }\n", []),
- ic_codegen:nl(Fd),
-
- ic_codegen:emit(Fd, " // methods\n", []),
-
- ic_codegen:emit(Fd, " public void _marshal(~sOtpOutputStream out)\n", [?ERLANGPACKAGE]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n"),
- ic_codegen:emit(Fd, " ~sHelper.marshal(out, value);\n", [ArrayName]),
- ic_codegen:emit(Fd, " }\n"),
- ic_codegen:nl(Fd),
- ic_codegen:emit(Fd, " public void _unmarshal(~sOtpInputStream in)\n", [?ERLANGPACKAGE]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n"),
- ic_codegen:emit(Fd, " value = ~sHelper.unmarshal(in);\n", [ArrayName]),
- ic_codegen:emit(Fd, " }\n", []),
- ic_codegen:nl(Fd),
-
- ic_codegen:emit(Fd, "}\n", []),
- file:close(Fd).
-
-
-%%-----------------------------------------------------------------
-%% Func: emit_helper_class/4
-%%-----------------------------------------------------------------
-emit_helper_class(G, N, X, Array, ArrayName, ArrayElement) ->
- SName = string:concat(ArrayName, "Helper"),
- {Fd, _}= ic_file:open_java_file(G, N, SName),
-
- ArrayElementName = ic_java_type:getType(G, N, ArrayElement),
- EmptyDim = arrayEmptyDim(Array),
-% Dim = arrayDim(G,N,Array),
-
- ic_codegen:emit(Fd, "public class ~sHelper {\n",[ArrayName]),
-
- ic_codegen:emit(Fd, " // constructors\n"),
- ic_codegen:emit(Fd, " private ~sHelper() {}\n\n", [ArrayName]),
-
- ic_codegen:emit(Fd, " // methods\n"),
-
- ic_codegen:emit(Fd, " public static void marshal(~sOtpOutputStream _out, ~s~s _value)\n",
- [?ERLANGPACKAGE,ArrayElementName,EmptyDim]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
- emit_array_marshal_loop(G,N,X,Array,ArrayElement,Fd),
- ic_codegen:emit(Fd, " }\n"),
- ic_codegen:nl(Fd),
- ic_codegen:emit(Fd, " public static ~s~s unmarshal(~sOtpInputStream _in)\n",
- [ArrayElementName,EmptyDim,?ERLANGPACKAGE]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
- ic_codegen:emit(Fd, " ~s~s _value = new ~s;\n\n",
- [ArrayElementName,EmptyDim,ic_java_type:getFullType(G, N, X, Array)]),
- emit_array_unmarshal_loop(G,N,X,Array,ArrayElement,Fd),
- ic_codegen:emit(Fd, " return _value;\n"),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public static String id() {\n", []),
- ic_codegen:emit(Fd, " return ~p;\n",[ictk:get_IR_ID(G, N, Array)]),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public static String name() {\n", []),
- ic_codegen:emit(Fd, " return ~p;\n",[ArrayName]),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_jbe:emit_type_function(G, N, X, Fd),
-
- ic_codegen:emit(Fd, " public static void insert(~sAny _any, ~s~s _this)\n",
- [?ICPACKAGE,ArrayElementName,EmptyDim]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
-
- ic_codegen:emit(Fd, " ~sOtpOutputStream _os = \n",[?ERLANGPACKAGE]),
- ic_codegen:emit(Fd, " new ~sOtpOutputStream();\n\n",[?ERLANGPACKAGE]),
-
- ic_codegen:emit(Fd, " _any.type(type());\n"),
- ic_codegen:emit(Fd, " marshal(_os, _this);\n"),
- ic_codegen:emit(Fd, " _any.insert_Streamable(_os);\n"),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public static ~s~s extract(~sAny _any)\n",
- [ArrayElementName,EmptyDim,?ICPACKAGE]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
-
- ic_codegen:emit(Fd, " return unmarshal(_any.extract_Streamable());\n"),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, "}\n"),
- file:close(Fd).
-
-
-
-
-emit_array_marshal_loop(G,N,X,Array,AEl,Fd) ->
- DimList = mk_array_dim_list(G,N,Array),
- emit_array_marshal_loop_1(G,N,X,Array,AEl,DimList,0,Fd).
-
-
-emit_array_marshal_loop_1(G,N,X,Array,AEl,[D],C,Fd) ->
-
- DimList = mk_array_dim_list(G,N,Array),
-
- ic_codegen:emit(Fd, " _out.write_tuple_head(~s);\n\n",[D]),
-
- ic_codegen:emit(Fd, " for(int _tmp~p = 0; _tmp~p < ~s; _tmp~p++)\n",[C,C,D,C]),
-
- case ic_java_type:isBasicType(G, N, AEl) of
- true ->
- ic_codegen:emit(Fd, " _out~s(_value",
- [ic_java_type:marshalFun(G, N, X, AEl)]);
- false ->
- ic_codegen:emit(Fd, " ~s(_out, _value",
- [ic_java_type:marshalFun(G, N, X, AEl)])
- end,
-
- emit_array_dimensions(DimList,0,Fd),
-
- ic_codegen:emit(Fd, ");\n\n");
-
-emit_array_marshal_loop_1(G,N,X,Array,AEl,[D|Ds],C,Fd) ->
-% DimList = mk_array_dim_list(G,N,Array),
-
- ic_codegen:emit(Fd, " _out.write_tuple_head(~s);\n\n",[D]),
-
- ic_codegen:emit(Fd, " for(int _tmp~p = 0; _tmp~p < ~s; _tmp~p++) {\n",[C,C,D,C]),
-
- emit_array_marshal_loop_1(G,N,X,Array,AEl,Ds,C+1,Fd),
-
- ic_codegen:emit(Fd, " }\n\n").
-
-
-
-
-
-emit_array_unmarshal_loop(G,N,X,Array,AEl,Fd) ->
- DimList = mk_array_dim_list(G,N,Array),
- case length(DimList) > 0 of
- true ->
- ic_codegen:emit(Fd, " _in.read_tuple_head();\n\n"),
-
- ic_codegen:emit(Fd, " for(int _tmp0 = 0; _tmp0 < ~s; _tmp0++) {\n\n",[hd(DimList)]),
- emit_array_unmarshal_loop_1(G,N,X,Array,AEl,tl(DimList),1,Fd),
- ic_codegen:emit(Fd, " }\n\n");
- false ->
- emit_array_unmarshal_loop_1(G,N,X,Array,AEl,DimList,0,Fd)
- end.
-
-emit_array_unmarshal_loop_1(G,N,X,_Array,AEl,[],1,Fd) -> %% One dimensional array
- case ic_java_type:isBasicType(G, N, AEl) of
- true ->
- ic_codegen:emit(Fd, " _value[_tmp0] = _in~s;\n",
- [ic_java_type:unMarshalFun(G, N, X, AEl)]);
- false ->
- ic_codegen:emit(Fd, " _value[_tmp0] = ~s.unmarshal(_in);\n\n",
- [ic_java_type:getUnmarshalType(G, N, X, AEl)])
- end;
-emit_array_unmarshal_loop_1(G,N,X,Array,AEl,[],_C,Fd) ->
- DimList = mk_array_dim_list(G,N,Array),
- ic_codegen:emit(Fd, " _value"),
- emit_array_dimensions(DimList,0,Fd),
- case ic_java_type:isBasicType(G,N,AEl) of
- true ->
- ic_codegen:emit(Fd, " = _in~s;\n",
- [ic_java_type:unMarshalFun(G, N, X, AEl)]);
- false ->
- ic_codegen:emit(Fd, " = ~s.unmarshal(_in);\n",
- [ic_java_type:getUnmarshalType(G, N, X, AEl)])
- end;
-emit_array_unmarshal_loop_1(G,N,X,Array,AEl,[D|Ds],C,Fd) ->
- ic_codegen:emit(Fd, " _in.read_tuple_head();\n\n"),
-
- ic_codegen:emit(Fd, " for(int _tmp~p = 0; _tmp~p < ~s; _tmp~p++) {\n\n",[C,C,D,C]),
- emit_array_unmarshal_loop_1(G,N,X,Array,AEl,Ds,C+1,Fd),
- ic_codegen:emit(Fd, " }\n").
-
-
-
-
-
-%%---------------------------------------------------
-%% Utilities
-%%---------------------------------------------------
-
-mk_array_dim_list(G,N,Array) ->
- mk_array_dim_list2(G,N,Array#array.size).
-
-
-mk_array_dim_list2(_G,_N,[]) ->
- [];
-
-mk_array_dim_list2(G,N,[D |Ds]) when is_record(D,scoped_id) ->
- {FSN, _, _, _} = ic_symtab:get_full_scoped_name(G, N, D),
- [ ic_util:to_dot(G,FSN) | mk_array_dim_list2(G,N,Ds)];
-
-mk_array_dim_list2(G,N,[D |Ds]) ->
- [ic_util:eval_java(G,N,D) | mk_array_dim_list2(G,N,Ds)].
-
-
-
-%% Array dimension string
-%arrayDim(G,N,X) ->
-% arrayDim2(G,N,X#array.size).
-
-%arrayDim2(_G,_N,[]) ->
-% "";
-%arrayDim2(G,N,[D|Ds]) when record(D,scoped_id) ->
-% {FSN, _, _, _} = ic_symtab:get_full_scoped_name(G, N, D),
-% "[" ++ ic_util:to_dot(G,FSN) ++ "]" ++ arrayDim2(G,N,Ds);
-%arrayDim2(G,N,[D|Ds]) ->
-% "[" ++ ic_util:eval_java(G,N,D) ++ "]" ++ arrayDim2(G,N,Ds).
-
-
-%% Array Empty dimension string
-arrayEmptyDim(X) ->
- arrayEmptyDim2(X#array.size).
-
-arrayEmptyDim2([_D]) ->
- "[]";
-arrayEmptyDim2([_D |Ds]) ->
- "[]" ++ arrayEmptyDim2(Ds).
-
-
-emit_array_dimensions([_D],C,Fd) ->
- ic_codegen:emit(Fd, "[_tmp~p]",[C]);
-emit_array_dimensions([_D|Ds],C,Fd) ->
- ic_codegen:emit(Fd, "[_tmp~p]",[C]),
- emit_array_dimensions(Ds,C+1,Fd).
-
-
-
-
-
-
diff --git a/lib/ic/src/ic_attribute_java.erl b/lib/ic/src/ic_attribute_java.erl
deleted file mode 100644
index ddbc6d24f5..0000000000
--- a/lib/ic/src/ic_attribute_java.erl
+++ /dev/null
@@ -1,413 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ic_attribute_java).
-
--include("icforms.hrl").
--include("ic.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([emit_attribute_prototype/4,
- emit_attribute_stub_code/4,
- emit_atrribute_on_dictionary/5,
- emit_attribute_switch_case/5]).
-
-
-
-
-
-%%%-----------------------------------------------------
-%%%
-%%% Generates operation in interface
-%%%
-%%%-----------------------------------------------------
-emit_attribute_prototype(G, N, X, Fd) ->
- emit_attribute_prototype(G, N, X, Fd, ic_forms:get_idlist(X)).
-
-emit_attribute_prototype(_G, _N, _X, _Fd, []) ->
- ok;
-emit_attribute_prototype(G, N, X, Fd, [V|Vs]) ->
- WireAttrName = ic_forms:get_id(V),
- AttrName = ic_forms:get_java_id(WireAttrName),
- emit_attr_prototype(G, N, X, Fd, AttrName,WireAttrName),
- emit_attribute_prototype(G, N, X, Fd, Vs).
-
-
-emit_attr_prototype(G, N, X, Fd, OpName, WireOpName) ->
-
- ic_codegen:emit(Fd, "/****\n"),
- ic_codegen:emit(Fd, " * Attribute ~p interface functions \n", [ic_util:to_colon([WireOpName|N])]),
- ic_codegen:emit(Fd, " *\n"),
- ic_codegen:emit(Fd, " */\n\n"),
-
- AT = ic_forms:get_type(X),
- Type = ic_java_type:getType(G, N, AT),
-% HolderType = ic_java_type:getHolderType(G, N, AT),
-
- ic_codegen:emit(Fd, " ~s ~s() throws java.lang.Exception;\n\n",[Type, OpName]),
-
- case X#attr.readonly of
- {readonly, _} ->
- ok;
- _ ->
- ic_codegen:emit(Fd, " void ~s(~s _value) throws java.lang.Exception;\n\n",[OpName, Type])
- end.
-
-
-
-%%%-----------------------------------------------------
-%%%
-%%% Generates attribute insertion in dictionary
-%%%
-%%%-----------------------------------------------------
-emit_atrribute_on_dictionary(G, N, X, Fd, C) ->
- emit_atrribute_on_dictionary(G, N, X, Fd, C, ic_forms:get_idlist(X)).
-
-emit_atrribute_on_dictionary(_G, _N, _X, _Fd, C, []) ->
- C;
-emit_atrribute_on_dictionary(G, N, X, Fd, C, [V|Vs]) ->
-
- WireAttrName = ic_forms:get_id(V),
-
- ic_codegen:emit(Fd, " _operations.put(\"_get_~s\", new java.lang.Integer(~p));\n",
- [WireAttrName,C]),
-
- case X#attr.readonly of
- {readonly, _} ->
-
- emit_atrribute_on_dictionary(G, N, X, Fd, C+1, Vs);
-
- _ ->
-
- ic_codegen:emit(Fd, " _operations.put(\"_set_~s\", new java.lang.Integer(~p));\n",
- [WireAttrName,C+1]),
-
- emit_atrribute_on_dictionary(G, N, X, Fd, C+2, Vs)
- end.
-
-
-
-%%%-----------------------------------------------------
-%%%
-%%% Generates attribute case in server switch
-%%%
-%%%-----------------------------------------------------
-emit_attribute_switch_case(G, N, X, Fd, C) ->
- Tk = ic_forms:get_tk(X),
- emit_attribute_switch_case(G, N, X, Fd, Tk, C, ic_forms:get_idlist(X)).
-
-emit_attribute_switch_case(_G, _N, _X, _Fd, _Tk, C, []) ->
- C;
-emit_attribute_switch_case(G, N, X, Fd, Tk, C, [V|Vs]) ->
- AttrName = ic_forms:get_java_id(V),
-
- emit_attribute_switch_case1(G,N,X,Fd,"_get_",AttrName,Tk,C),
-
- case X#attr.readonly of
- {readonly, _} ->
- emit_attribute_switch_case(G, N, X, Fd, Tk, C+1, Vs);
-
- _ ->
- emit_attribute_switch_case1(G,N,X,Fd,"_set_",AttrName,Tk,C+1),
- emit_attribute_switch_case(G, N, X, Fd, Tk, C+2, Vs)
- end.
-
-
-emit_attribute_switch_case1(G, N, X, Fd, "_get_", Name, _Tk, C) ->
-
- R = ic_forms:get_type(X),
- RT = ic_java_type:getParamType(G,N,R,ret),
-
- ic_codegen:emit(Fd, " case ~p: { // Get operation for attribute ~s\n\n",[C,ic_util:to_dot([Name|N])]),
-
- ic_codegen:emit(Fd, " // Calling implementation function\n"),
- ic_codegen:emit(Fd, " ~s _result = this.~s();\n\n", [RT, Name]),
-
- ic_codegen:emit(Fd, " // Marshalling output\n"),
- ic_codegen:emit(Fd, " ~sOtpErlangRef __ref = __env.getSref();\n",[?ERLANGPACKAGE]),
- ic_codegen:emit(Fd, " __os.write_tuple_head(2);\n"),
- ic_codegen:emit(Fd, " __os.write_ref(__ref.node(),__ref.id(),__ref.creation()); // Call reference\n"),
-
- case ic_java_type:isBasicType(G,N,R) of
- true ->
- ic_codegen:emit(Fd, " __os~s(_result); // Return value\n\n",
- [ic_java_type:marshalFun(G,N,X,R)]);
- false ->
- ic_codegen:emit(Fd, " ~s(__os,_result); // Return value\n\n",
- [ic_java_type:marshalFun(G,N,X,R)])
- end,
-
- ic_codegen:emit(Fd, " } break;\n\n");
-
-
-emit_attribute_switch_case1(G, N, X, Fd, "_set_", Name, _Tk, C) ->
- ic_codegen:emit(Fd, " case ~p: { // Set operation for attribute ~s\n\n",[C,ic_util:to_dot([Name|N])]),
-
- Type = ic_forms:get_type(X),
-
- ic_codegen:emit(Fd, " // Preparing input\n"),
- ic_codegen:emit(Fd, " ~sOtpInputStream __is = __env.getIs();\n",[?ERLANGPACKAGE]),
-
- case ic_java_type:isBasicType(G,N,Type) of
- true ->
- ic_codegen:emit(Fd, " ~s _value = __is~s; // In value\n\n",
- [ic_java_type:getParamType(G,N,Type,in),
- ic_java_type:unMarshalFun(G,N,X,Type)]);
- false ->
- ic_codegen:emit(Fd, " ~s _value = ~s.unmarshal(__is); // In value\n\n",
- [ic_java_type:getParamType(G,N,Type,in),
- ic_java_type:getUnmarshalType(G,N,X,Type)])
- end,
-
-
- ic_codegen:emit(Fd, " // Calling implementation function\n"),
- ic_codegen:emit(Fd, " this.~s(_value);\n\n", [Name]),
-
- ic_codegen:emit(Fd, " // Marshalling output\n"),
- ic_codegen:emit(Fd, " ~sOtpErlangRef __ref = __env.getSref();\n",[?ERLANGPACKAGE]),
- ic_codegen:emit(Fd, " __os.write_tuple_head(2);\n"),
- ic_codegen:emit(Fd, " __os.write_ref(__ref.node(),__ref.id(),__ref.creation()); // Call reference\n"),
- ic_codegen:emit(Fd, " __os.write_atom(\"ok\");\n\n"),
-
- ic_codegen:emit(Fd, " } break;\n\n").
-
-
-
-
-
-
-
-%%%-----------------------------------------------------
-%%%
-%%% Generates attribute function in stub
-%%%
-%%%-----------------------------------------------------
-emit_attribute_stub_code(G, N, X, Fd) ->
- emit_attribute_stub_code(G, N, X, Fd, ic_forms:get_idlist(X)).
-
-emit_attribute_stub_code(_G, _N, _X, _Fd, []) ->
- ok;
-emit_attribute_stub_code(G, N, X, Fd, [V|Vs]) ->
- WireAttrName = ic_forms:get_id(V),
- AttrName = ic_forms:get_java_id(WireAttrName),
-
- emit_attribute_stub_code1(G,N,X,Fd,"_get_",AttrName,WireAttrName),
-
- case X#attr.readonly of
- {readonly, _} ->
- emit_attribute_stub_code(G, N, X, Fd, Vs);
-
- _ ->
- emit_attribute_stub_code1(G,N,X,Fd,"_set_",AttrName,WireAttrName),
- emit_attribute_stub_code(G, N, X, Fd, Vs)
- end.
-
-
-emit_attribute_stub_code1(G,N,X,Fd,"_get_",Name,WireName) ->
-
- Type = ic_forms:get_type(X),
- RT = ic_java_type:getType(G,N,Type),
-
- %%
- %% Main get operation
- %%
- ic_codegen:emit(Fd, " // Attribute ~p get operation implementation\n", [ic_util:to_colon([WireName|N])]),
- ic_codegen:emit(Fd, " public ~s ~s() throws java.lang.Exception {\n\n", [RT, Name]),
-
- %% Function marshal call
- ic_codegen:emit(Fd, " // Calling the marshal function\n"),
- ic_codegen:emit(Fd, " _~s_marshal(_env);\n\n", [Name]),
-
- %% Sending call
- ic_codegen:emit(Fd, " // Message send\n"),
- ic_codegen:emit(Fd, " _env.send();\n\n"),
-
- %% Receiving return value
- ic_codegen:emit(Fd, " // Message receive\n"),
- ic_codegen:emit(Fd, " _env.receive();\n\n"),
-
- ic_codegen:emit(Fd, " // Calling the unmarshal function\n"),
- ic_codegen:emit(Fd, " return _~s_get_unmarshal(_env);\n", [Name]),
- ic_codegen:emit(Fd, " }\n\n"),
-
-
- %%
- %% Marshal get operation
- %%
- ic_codegen:emit(Fd, " // Marshal operation for get attribute ~p\n", [Name]),
- ic_codegen:emit(Fd, " public static void _~s_marshal(~sEnvironment __env)\n",
- [Name, ?ICPACKAGE]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
-
- ic_codegen:emit(Fd, " // Get output stream\n"),
- ic_codegen:emit(Fd, " ~sOtpOutputStream __os = __env.getOs();\n\n",[?ERLANGPACKAGE]),
-
- %% Initiating Message header
- ic_codegen:emit(Fd, " // Message header assembly\n"),
- ic_codegen:emit(Fd, " __os.reset();\n"),
- ic_codegen:emit(Fd, " __os.write_tuple_head(3);\n"),
- ic_codegen:emit(Fd, " __os.write_atom(\"$gen_call\");\n\n"),
-
-
- %% Creating call identity tuple
- ic_codegen:emit(Fd, " // Message identity part creation\n"),
- ic_codegen:emit(Fd, " __os.write_tuple_head(2);\n"),
- ic_codegen:emit(Fd, " __env.write_client_pid();\n"),
- ic_codegen:emit(Fd, " __env.write_client_ref();\n\n"),
-
- OpCallName = case ic_options:get_opt(G, scoped_op_calls) of
- true ->
- ic_util:to_undersc(["_get_"++WireName|N]);
- false ->
- "_get_"++WireName
- end,
-
- %% Creating operation identity
- ic_codegen:emit(Fd, " // Message operation part creation\n"),
- ic_codegen:emit(Fd, " __os.write_atom(~p);\n\n",[OpCallName]),
-
- ic_codegen:emit(Fd, " }\n\n"),
-
-
- %%
- %% Unmarshal get operation
- %%
- MRT = ic_java_type:getParamType(G,N,Type,ret),
-
- ic_codegen:emit(Fd, " // Unmarshal operation for get attribute ~p\n", [Name]),
- ic_codegen:emit(Fd, " public static ~s _~s_get_unmarshal(~sEnvironment __env)\n",
- [MRT, Name, ?ICPACKAGE]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
-
-
- ic_codegen:emit(Fd, " // Get input stream\n"),
- ic_codegen:emit(Fd, " ~sOtpInputStream __is = __env.getIs();\n\n",[?ERLANGPACKAGE]),
-
- ic_codegen:emit(Fd, " // Extracting return value\n"),
- case ic_java_type:isBasicType(G, N, Type) of
- true ->
- ic_codegen:emit(Fd, " return __is~s;\n",
- [ic_java_type:unMarshalFun(G, N, X, Type)]);
- false ->
- ic_codegen:emit(Fd, " return ~s.unmarshal(__is);\n",
- [ic_java_type:getUnmarshalType(G, N, X, Type)])
- end,
-
- ic_codegen:emit(Fd, " }\n\n");
-
-
-emit_attribute_stub_code1(G,N,X,Fd,"_set_",Name,WireName) ->
-
- Type = ic_forms:get_type(X),
-
- %%
- %% Main set operation
- %%
- IT = ic_java_type:getType(G,N,Type),
-
- ic_codegen:emit(Fd, " // Attribute ~p set operation implementation\n", [ic_util:to_colon([WireName|N])]),
- ic_codegen:emit(Fd, " public void ~s(~s _value) throws java.lang.Exception {\n\n", [Name,IT]),
-
- %% Function marshal call
- ic_codegen:emit(Fd, " // Calling the marshal function\n"),
- ic_codegen:emit(Fd, " _~s_marshal(_env, _value);\n\n", [Name]),
-
- %% Sending call
- ic_codegen:emit(Fd, " // Message send\n"),
- ic_codegen:emit(Fd, " _env.send();\n\n"),
-
- %% Receiving return value
- ic_codegen:emit(Fd, " // Message receive\n"),
- ic_codegen:emit(Fd, " _env.receive();\n\n"),
-
- ic_codegen:emit(Fd, " // Calling the unmarshal function\n"),
- ic_codegen:emit(Fd, " _~s_set_unmarshal(_env);\n", [Name]),
-
- ic_codegen:emit(Fd, " }\n\n"),
-
-
- %%
- %% Marshal set operation
- %%
- IP = ic_java_type:getParamType(G, N, Type, in),
- OpCallName = case ic_options:get_opt(G, scoped_op_calls) of
- true ->
- ic_util:to_undersc(["_set_"++WireName|N]);
- false ->
- "_set_"++WireName
- end,
-
- ic_codegen:emit(Fd, " // Marshal operation for set attribute ~p\n", [Name]),
- ic_codegen:emit(Fd, " public static void _~s_marshal(~sEnvironment __env, ~s _value)\n",
- [Name, ?ICPACKAGE, IP]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
-
- ic_codegen:emit(Fd, " // Get output stream\n"),
- ic_codegen:emit(Fd, " ~sOtpOutputStream __os = __env.getOs();\n\n",[?ERLANGPACKAGE]),
-
- %% Initiating Message header
- ic_codegen:emit(Fd, " // Message header assembly\n"),
- ic_codegen:emit(Fd, " __os.reset();\n"),
- ic_codegen:emit(Fd, " __os.write_tuple_head(3);\n"),
- ic_codegen:emit(Fd, " __os.write_atom(\"$gen_call\");\n\n"),
-
-
- %% Creating call identity tuple
- ic_codegen:emit(Fd, " // Message identity part creation\n"),
- ic_codegen:emit(Fd, " __os.write_tuple_head(2);\n"),
- ic_codegen:emit(Fd, " __env.write_client_pid();\n"),
- ic_codegen:emit(Fd, " __env.write_client_ref();\n\n"),
-
-
- %% Creating operation identity
- ic_codegen:emit(Fd, " // Message operation part creation\n"),
- ic_codegen:emit(Fd, " __os.write_tuple_head(2);\n"),
- ic_codegen:emit(Fd, " __os.write_atom(~p);\n",[OpCallName]),
-
- case ic_java_type:isBasicType(G, N, Type) of
- true ->
- ic_codegen:emit(Fd, " __os~s(_value);\n\n",
- [ic_java_type:marshalFun(G, N, X, Type)]);
- false ->
- ic_codegen:emit(Fd, " ~s(__os, _value);\n\n",
- [ic_java_type:marshalFun(G, N, X, Type)])
- end,
- ic_codegen:emit(Fd, " }\n\n"),
-
-
- ic_codegen:emit(Fd, " // Unmarshal operation for set attribute ~p\n", [Name]),
- ic_codegen:emit(Fd, " public static void _~s_set_unmarshal(~sEnvironment __env)\n",
- [Name, ?ICPACKAGE]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
-
- ic_codegen:emit(Fd, " // Get input stream\n"),
- ic_codegen:emit(Fd, " ~sOtpInputStream __is = __env.getIs();\n\n",[?ERLANGPACKAGE]),
-
- ic_codegen:emit(Fd, " __is.read_atom();\n"),
- ic_codegen:emit(Fd, " }\n\n").
-
-
-
-
-
-
diff --git a/lib/ic/src/ic_cbe.erl b/lib/ic/src/ic_cbe.erl
deleted file mode 100644
index f6e64d23a0..0000000000
--- a/lib/ic/src/ic_cbe.erl
+++ /dev/null
@@ -1,1307 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-%%------------------------------------------------------------
-%%
-%% This module is a main module for generation of C code, both
-%% for ic_cclient and ic_cserver.
-%%
-%% The former role of this module (ic_cbe) was to generate client
-%% code only.
-%%
--module(ic_cbe).
-
--export([emit_malloc_size_stmt/7, emit_encoding_stmt/6,
- emit_encoding_stmt/7, emit_decoding_stmt/10,
- emit_decoding_stmt/11, emit_dealloc_stmts/3,
- mk_variable_name/1, mk_c_type/3, mk_c_type/4, mk_c_type2/3,
- is_variable_size/1, is_variable_size/3, mk_dim/1,
- mk_slice_dim/1, emit_tmp_variables/1, store_tmp_decl/2,
- extract_info/3, normalize_type/1]).
-
-%%------------------------------------------------------------
-%%
-%% Internal stuff
-%%
-%%------------------------------------------------------------
-
--import(ic_codegen, [emit/2, emit/3, emit/4, emit_c_enc_rpt/4, emit_c_dec_rpt/4]).
-
--include("icforms.hrl").
--include ("ic.hrl").
-
-%%------------------------------------------------------------
-%% ENCODING
-%%------------------------------------------------------------
-
-emit_encoding_stmt(G, N, Fd, T, LName, OutBuffer) when element(1, T) == scoped_id ->
- case mk_c_type(G, N, T, evaluate_not) of
- "erlang_pid" ->
- %% Note prefix: oe_ei
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_pid(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
- "erlang_port" ->
- %% Note prefix: oe_ei
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_port(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n} \n");
- "erlang_ref" ->
- %% Note prefix: oe_ei
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_ref(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
- "ETERM*" ->
- %% Note prefix: oe_ei
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_term(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
- {enum, FSN} ->
- emit_encoding_stmt(G, N, Fd, FSN, LName, OutBuffer);
- FSN ->
- emit_encoding_stmt(G, N, Fd, FSN, LName, OutBuffer)
- end;
-
-%% XXX T is a string
-emit_encoding_stmt(G, N, Fd, T, LName, _OutBuffer) when is_list(T) ->
- %% Already a fullscoped name
- Type = ictype:name2type(G,T),
- case ictype:isBasicType(Type) of
- true ->
- emit_encoding_stmt_for_basic_type(G, N, T, Fd, Type, LName);
- false ->
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, ~s))"
- " < 0) {\n",
- [ic_util:mk_oe_name(G, "encode_"), T, LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]), % XXX list
- emit(Fd, " return oe_error_code;\n }\n")
- end;
-emit_encoding_stmt(G, N, Fd, T, LName, _OutBuffer) when is_record(T, string) ->
- %% Note prefix: oe_ei
- emit(Fd, " if ((oe_error_code = oe_ei_encode_string(oe_env, "
- " ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
-emit_encoding_stmt(G, N, Fd, T, LName, _OutBuffer) when is_record(T, wstring) ->
- %% Note prefix: oe_ei
- emit(Fd, " if ((oe_error_code = oe_ei_encode_wstring(oe_env, "
- "~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
-emit_encoding_stmt(G, N, Fd, T, LName, _OutBuffer) ->
- case normalize_type(T) of
- {basic, Type} ->
- emit_encoding_stmt_for_basic_type(G, N, T, Fd, Type, LName);
- %% XXX Why only returns?
- {void, _} ->
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
- {sequence, _, _} ->
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
- {_ArrayType, {array, _, _}} ->
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
- {union, _, _, _, _} ->
- %% Union as a member in struct !
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
- {struct, _, _, _} ->
- %% Struct as a member in struct !
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
- _ ->
- ic_error:fatal_error(G, {illegal_typecode_for_c, T, N})
- end.
-
-%% Arity = 7.
-%%
-emit_encoding_stmt(G, N, X, Fd, T, LName, OutBuffer) when element(1, T) == scoped_id ->
- case mk_c_type(G, N, T, evaluate_not) of
- "erlang_pid" ->
- %% Note prefix: oe_ei
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_pid(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
- "erlang_port" ->
- %% Note prefix: oe_ei
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_port(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
- "erlang_ref" ->
- %% Note prefix: oe_ei
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_ref(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
- "ETERM*" ->
- %% Note prefix: oe_ei
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_term(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
- {enum, FSN} ->
- emit_encoding_stmt(G, N, X, Fd, FSN, LName, OutBuffer);
- FSN ->
- emit_encoding_stmt(G, N, X, Fd, FSN, LName, OutBuffer)
- end;
-
-%% XXX T is a string
-emit_encoding_stmt(G, N, X, Fd, T, LName, _OutBuffer) when is_list(T) ->
- %% Already a fullscoped name
- case get_param_tk(LName,X) of
- error ->
- emit(Fd, " if ((oe_error_code = "
- "~s~s(oe_env, ~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "encode_"), T, LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
- ParamTK ->
- case is_variable_size(ParamTK) of
- true ->
- if is_tuple(ParamTK) ->
- case element(1,ParamTK) of
- tk_array ->
- %% Array of dynamic data
- emit(Fd,
- " if ((oe_error_code = "
- "~s~s(oe_env, ~s)) < 0) {\n",
- [ic_util:mk_oe_name(G,
- "encode_"),
- T, LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd,
- " return "
- "oe_error_code;\n }\n");
- _ ->
- emit(Fd,
- " if ((oe_error_code = "
- "~s~s(oe_env, ~s)) < 0) {\n",
- [ic_util:mk_oe_name(G,
- "encode_"),
- T, LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return "
- "oe_error_code;\n }\n")
- end;
- true ->
- emit(Fd,
- " if ((oe_error_code = "
- "~s~s(oe_env, ~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "encode_"),
- T, LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n")
- end;
- false ->
- if is_atom(ParamTK) ->
- case normalize_type(ParamTK) of
- {basic, Type} ->
- emit_encoding_stmt_for_basic_type(G, N, T, Fd,
- Type,
- LName);
- _ ->
- %% Why only return?
- ?emit_c_enc_rpt(Fd, " ", "~/slist/~s", [T, LName]),
- emit(Fd, " return oe_error_code;\n }\n"),
- ok
- end;
- true ->
- case element(1,ParamTK) of
- tk_enum ->
- emit(Fd, " if ((oe_error_code = "
- "~s~s(oe_env, ~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "encode_"),
- T, LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
- tk_array ->
- emit(Fd, " if ((oe_error_code = "
- "~s~s(oe_env, ~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "encode_"),
- T, LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
- tk_struct ->
- emit(Fd, " if ((oe_error_code = "
- "~s~s(oe_env, ~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "encode_"),
- T, LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
- tk_union ->
- emit(Fd, " if ((oe_error_code = "
- "~s~s(oe_env, ~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "encode_"),
- T, LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
- _ ->
- emit(Fd, " if ((oe_error_code = "
- "~s~s(oe_env, &~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "encode_"),
- T, LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n")
- end
- end
- end
- end;
-emit_encoding_stmt(G, N, _X, Fd, T, LName, _OutBuffer) when is_record(T, string) ->
- %% Note prefix: oe_ei
- emit(Fd, " if ((oe_error_code = oe_ei_encode_string(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
-emit_encoding_stmt(G, N, _X, Fd, T, LName, _OutBuffer) when is_record(T, wstring) ->
- %% Note prefix: oe_ei
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_wstring(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n");
-emit_encoding_stmt(G, N, _X, Fd, T, LName, _OutBuffer) ->
- case normalize_type(T) of
- {basic, Type} ->
- emit_encoding_stmt_for_basic_type(G, N, T, Fd, Type, LName);
- {void, _} ->
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n"),
- ok;
- {sequence, _, _} ->
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n"),
- ok;
- {_ArrayType, {array, _, _}} ->
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n"),
- ok;
- {struct, _, _, _} -> %% Struct as a member in struct !
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n"),
- ok;
- _ ->
- %%io:format("2 ------------> ~p~n", [T]),
- ic_error:fatal_error(G, {illegal_typecode_for_c, T, N})
- end.
-
-%%------------------------------------------------------------
-emit_encoding_stmt_for_basic_type(G, N, T, Fd, Type, LName) ->
- {Cast, DecType} =
- case Type of
- ushort -> {"(unsigned long) ", "ulong"};
- ulong -> {"", "ulong"};
- ulonglong -> {"", "ulonglong"};
- short -> {"(long) ", "long"};
- long -> {"", "long"};
- longlong -> {"", "longlong"};
- float -> {"(double) ", "double"};
- double -> {"", "double"};
- boolean -> {"", "atom"};
- char -> {"", "char"};
- wchar -> {"", "wchar"};
- octet -> {"", "char"};
- any -> {"", "long"} % Fix for any
- end,
- case Type of
- boolean ->
- %% Note prefix: oe_ei
- emit(Fd, " switch(~s) {\n",[LName]),
- emit(Fd, " case 0 :\n"),
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_atom(oe_env, "
- "\"false\")) < 0) {\n"),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " break;\n"),
- emit(Fd, " case 1 :\n"),
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_atom(oe_env, "
- "\"true\")) < 0) {\n"),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " break;\n"),
- emit(Fd, " default :\n"),
- emit(Fd, " return -1;\n"),
- emit(Fd, " }\n\n");
- _ ->
- Fmt =
- " if ((oe_error_code = oe_ei_encode_~s(oe_env, ~s~s)) < 0) {\n",
- emit(Fd, Fmt, [DecType, Cast, LName]),
- ?emit_c_enc_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n }\n")
- end.
-
-
-%%------------------------------------------------------------
-%% MALLOC SIZE (for Decode)
-%%------------------------------------------------------------
-
-emit_malloc_size_stmt(G, N, Fd, T, InBuffer,
- Align, CalcType) when element(1, T) == scoped_id ->
- case mk_c_type(G, N, T, evaluate_not) of
- "erlang_pid" ->
- emit(Fd, " oe_malloc_size += sizeof(erlang_pid);\n\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_pid(~s, "
- "oe_size_count_index, NULL)) < 0) {\n", [InBuffer]),
- ?emit_c_dec_rpt(Fd, " ", "erlang_pid", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "erlang_port" ->
- emit(Fd, " oe_malloc_size += sizeof(erlang_port);\n\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_port(~s, "
- "oe_size_count_index, NULL)) < 0) {\n", [InBuffer]),
- ?emit_c_dec_rpt(Fd, " ", "erlang_port", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "erlang_ref" ->
- emit(Fd, " oe_malloc_size += sizeof(erlang_ref);\n\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_ref(~s, "
- "oe_size_count_index, NULL)) < 0) {\n", [InBuffer]),
- ?emit_c_dec_rpt(Fd, " ", "erlang_ref", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "ETERM*" ->
- emit(Fd, " oe_malloc_size += sizeof(char*);\n\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_term(~s, "
- "oe_size_count_index, NULL)) < 0) {\n", [InBuffer]),
- ?emit_c_dec_rpt(Fd, " ", "ETERM*", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {enum, FSN} ->
- emit_malloc_size_stmt(G, N, Fd, FSN, InBuffer, Align, CalcType);
- FSN ->
- %% io:format("emit_malloc_size_stmt: ~p ~p~n",[FSN,
- %% CalcType]),
- emit_malloc_size_stmt(G, N, Fd, FSN, InBuffer, Align, CalcType)
- end;
-
-%% XXX T is a string
-emit_malloc_size_stmt(G, N, Fd, T, InBuffer,
- _Align, CalcType) when is_list(T) ->
- %% Already a fullscoped name
- Type = ictype:name2type(G,T),
- case ictype:isBasicType(Type) of
- true ->
- emit_malloc_size_stmt_for_basic_type(G, N, T, Fd, Type, InBuffer);
- false ->
- case CalcType of
- generator ->
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, "
- "oe_size_count_index, &oe_malloc_size)) < 0) {\n",
- [ic_util:mk_oe_name(G, "sizecalc_"), T]),
- ?emit_c_dec_rpt(Fd, " ", "~s", [T]),
- emit(Fd, " return oe_error_code;\n }\n");
- _ ->
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, "
- "&oe_size_count_index, &oe_malloc_size)) < 0) {\n",
- [ic_util:mk_oe_name(G, "sizecalc_"), T]),
- ?emit_c_dec_rpt(Fd, " ", "~s", [T]),
- emit(Fd, " return oe_error_code;\n }\n")
- end
- end;
-emit_malloc_size_stmt(G, N, Fd, T, InBuffer, _Align,
- CalcType) when is_record(T, string) ->
- Tname = mk_variable_name(op_variable_count),
- store_tmp_decl(" int ~s = 0;\n",[Tname]),
- case CalcType of
- generator ->
- emit(Fd, " if ((oe_error_code = ei_get_type(~s, "
- "oe_size_count_index, &oe_type, &~s)) < 0) {\n",
- [InBuffer, Tname]);
- _ ->
- emit(Fd, " int oe_type = 0;\n"),
- emit(Fd, " int oe_temp = 0;\n\n"),
- emit(Fd, " if ((oe_error_code = ei_get_type(~s, "
- "&oe_size_count_index, &oe_type, &oe_temp)) < 0) {\n",
- [InBuffer])
- end,
- ?emit_c_dec_rpt(Fd, " ", "ei_get_type", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- if
- T#string.length == 0 ->
- ok;
- true ->
- Length = ic_util:eval_c(G, N, T#string.length),
- case CalcType of
- generator ->
- emit(Fd, " if (~s > ~s)\n",[Tname, Length]),
- emit(Fd, " return -1;\n\n");
- _ ->
- emit(Fd, " if (oe_temp > ~s)\n",[Length]),
- emit(Fd, " return -1;\n\n")
- end
- end,
- case CalcType of
- generator ->
- emit(Fd, " if ((oe_error_code = ei_decode_string(~s, "
- "oe_size_count_index, NULL)) < 0) {\n", [InBuffer]);
- _ ->
- emit(Fd, " if ((oe_error_code = ei_decode_string(~s, "
- "&oe_size_count_index, NULL)) < 0) {\n", [InBuffer])
- end,
- ?emit_c_dec_rpt(Fd, " ", "ei_decode_string", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- case CalcType of
- generator ->
- emit(Fd, " oe_malloc_size = ~s;\n\n",
- [ic_util:mk_align("oe_malloc_size + " ++ Tname ++"+1")]);
- _ ->
- emit(Fd, " oe_malloc_size = ~s;\n\n",
- [ic_util:mk_align("oe_malloc_size + oe_temp+1")])
- end;
-emit_malloc_size_stmt(G, N, Fd, T, InBuffer, _Align,
- CalcType) when is_record(T, wstring) ->
- Tname = mk_variable_name(op_variable_count),
- store_tmp_decl(" int ~s = 0;\n",[Tname]),
- case CalcType of
- generator ->
- emit(Fd, " if ((oe_error_code = ei_get_type(~s, "
- "oe_size_count_index, &oe_type, &~s)) < 0) {\n",
- [InBuffer, Tname]);
- _ ->
- emit(Fd, " int oe_type = 0;\n"),
- emit(Fd, " int oe_temp = 0;\n\n"),
- emit(Fd, " if ((oe_error_code = ei_get_type(~s, "
- "&oe_size_count_index, &oe_type, &oe_temp)) < 0) {\n",
- [InBuffer])
- end,
- ?emit_c_dec_rpt(Fd, " ", "ei_get_type", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- if
- T#wstring.length == 0 ->
- ok;
- true ->
- Length = ic_util:eval_c(G, N, T#wstring.length),
- case CalcType of
- generator ->
- emit(Fd, " if (~s > ~s)\n",[Tname, Length]),
- emit(Fd, " return -1;\n\n");
- _ ->
- emit(Fd, " if (oe_temp > ~s)\n",[Length]),
- emit(Fd, " return -1;\n\n")
- end
- end,
- case CalcType of
- generator ->
- %% Note prefix: oe_ei
- emit(Fd, " if ((oe_error_code = oe_ei_decode_wstring(~s, "
- "oe_size_count_index, NULL)) < 0) {\n", [InBuffer]);
- _ ->
- %% Note prefix: oe_ei
- emit(Fd, " if ((oe_error_code = oe_ei_decode_wstring(~s, "
- "&oe_size_count_index, NULL)) < 0) {\n", [InBuffer])
- end,
- ?emit_c_dec_rpt(Fd, " ", "oe_ei_decode_wstring", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- case CalcType of
- generator ->
- emit(Fd, " oe_malloc_size =\n ~s;\n\n",
- [ic_util:mk_align("oe_malloc_size + (("
- ++ Tname
- ++"+ 1) * __OE_WCHAR_SIZE_OF__)")]);
- _ ->
- emit(Fd, " oe_malloc_size =\n ~s;\n\n",
- [ic_util:mk_align("oe_malloc_size + (("
- "oe_temp + 1) * __OE_WCHAR_SIZE_OF__)")])
- end;
-emit_malloc_size_stmt(G, N, Fd, T, InBuffer, Align, CalcType) ->
- case Align of
- 0 ->
- emit(Fd, " oe_malloc_size += sizeof(~s);\n\n",
- [mk_c_type(G, N, T)]);
- _ ->
- ok
- end,
- case normalize_type(T) of
- {basic, Type} ->
- emit_malloc_size_stmt_for_basic_type(G, N, T, Fd, Type, InBuffer);
- {void, _} ->
- ok;
- {sequence, _, _} ->
- ok;
- {_, {array, SId, _}} ->
- case CalcType of
- generator ->
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, "
- "oe_size_count_index, &oe_malloc_size)) < 0) {\n",
- [ic_util:mk_oe_name(G, "sizecalc_"),
- ic_forms:get_id2(SId)]),
- ?emit_c_dec_rpt(Fd, " ", "array1", []),
- emit(Fd, " return oe_error_code;\n\n");
- _ ->
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, "
- "&oe_size_count_index, &oe_malloc_size)) < 0) {\n",
- [ic_util:mk_oe_name(G, "sizecalc_"),
- ic_forms:get_id2(SId)]),
- ?emit_c_dec_rpt(Fd, " ", "array2", []),
- emit(Fd, " return oe_error_code;\n\n")
- end;
- {union, UId, _, _, _} ->
- case CalcType of
- generator ->
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, "
- "oe_size_count_index, &oe_malloc_size)) < 0) {\n",
- [ic_util:mk_oe_name(G, "sizecalc_"),
- ic_forms:get_id2(UId)]),
- ?emit_c_dec_rpt(Fd, " ", "union1", []),
- emit(Fd, " return oe_error_code;\n\n");
- _ ->
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, "
- "&oe_size_count_index, &oe_malloc_size)) < 0) {\n",
- [ic_util:mk_oe_name(G, "sizecalc_"),
- ic_forms:get_id2(UId)]),
- ?emit_c_dec_rpt(Fd, " ", "union2", []),
- emit(Fd, " return oe_error_code;\n\n")
- end;
- {struct, UId, _, _} -> %% Struct as a member in struct !
- case CalcType of
- generator ->
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, "
- "oe_size_count_index, &oe_malloc_size)) < 0) {\n",
- [ic_util:mk_oe_name(G, "sizecalc_"),
- ic_forms:get_id2(UId)]),
- ?emit_c_dec_rpt(Fd, " ", "struct1", []),
- emit(Fd, " return oe_error_code;\n\n");
- _ ->
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, "
- "&oe_size_count_index, &oe_malloc_size)) < 0) {\n",
- [ic_util:mk_oe_name(G, "sizecalc_"),
- ic_forms:get_id2(UId)]),
- ?emit_c_dec_rpt(Fd, " ", "struct2", []),
- emit(Fd, " return oe_error_code;\n\n")
- end;
- {any, _} -> %% Fix for any type
- emit(Fd, " if ((oe_error_code = ei_decode_long(~s, "
- "oe_size_count_index, NULL)) < 0) {\n",
- [InBuffer]),
- ?emit_c_dec_rpt(Fd, " ", "any", []),
- emit(Fd, " return oe_error_code;\n }\n");
- _ ->
- ic_error:fatal_error(G, {illegal_typecode_for_c, T, N})
- end.
-
-%%------------------------------------------------------------
-
-emit_malloc_size_stmt_for_basic_type(G, N, T, Fd, Type, InBuffer) ->
- {Pre, DecType} =
- case Type of
- ushort -> {"", "ulong"};
- ulong -> {"", "ulong"};
- ulonglong -> {"oe_", "ulonglong"};
- short -> {"", "long"};
- long -> {"", "long"};
- longlong -> {"oe_", "longlong"};
- float -> {"", "double"};
- double -> {"", "double"};
- boolean -> {"", "atom"};
- char -> {"", "char"};
- wchar -> {"oe_", "wchar"};
- octet -> {"", "char"};
- any -> {"", "long"}
- end,
- Fmt =
- " if ((oe_error_code = ~sei_decode_~s(~s, oe_size_count_index, "
- "NULL)) < 0) {\n",
- emit(Fd, Fmt, [Pre, DecType, InBuffer]),
- ?emit_c_dec_rpt(Fd, " ", "~s", [DecType]),
- emit(Fd, " return oe_error_code;\n }\n").
-
-%%------------------------------------------------------------
-%% DECODING
-%%------------------------------------------------------------
-
-emit_decoding_stmt(G, N, Fd, T, LName, IndOp, InBuffer, Align,
- NextPos, DecType) ->
- emit_decoding_stmt(G, N, Fd, T, LName, IndOp, InBuffer, Align,
- NextPos, DecType, []).
-
-emit_decoding_stmt(G, N, Fd, T, LName, IndOp, InBuffer, Align, NextPos,
- DecType, AllocedPars) when element(1, T) == scoped_id ->
- Fmt =
- " if ((oe_error_code = ei_decode_~s(~s, &oe_env->_iin, ~s~s)) < 0)"
- " {\n",
- Emit = fun(Type) ->
- emit(Fd, Fmt, [Type, InBuffer, IndOp, LName]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n")
- end,
- case mk_c_type(G, N, T, evaluate_not) of
- "erlang_pid" ->
- Emit("pid");
- "erlang_port" ->
- Emit("port");
- "erlang_ref" ->
- Emit("ref");
- "ETERM*" ->
- Emit("term");
- {enum, FSN} ->
- emit_decoding_stmt(G, N, Fd, FSN, LName, IndOp, InBuffer,
- Align, NextPos, DecType, AllocedPars);
- FSN ->
- emit_decoding_stmt(G, N, Fd, FSN, LName, IndOp, InBuffer,
- Align, NextPos, DecType, AllocedPars)
- end;
-
-%% XXX T is a string
-emit_decoding_stmt(G, N, Fd, T, LName, IndOp, InBuffer, _Align, NextPos,
- DecType, AllocedPars) when is_list(T) ->
- %% Already a fullscoped name
- Type = ictype:name2type(G,T),
- case ictype:isBasicType(Type) of
- true ->
- emit_decoding_stmt_for_basic_type(G, N, T, Fd, Type, InBuffer, IndOp,
- LName, AllocedPars);
- false ->
- case DecType of
- generator ->
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, oe_first, "
- "~s, ~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "decode_"),
- T, NextPos, LName]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n");
- caller -> %% No malloc used, define oe_first
- emit(Fd, " {\n"),
- emit(Fd, " void *oe_first = NULL;\n"),
- emit(Fd, " int oe_outindex = 0;\n\n"),
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, "
- "oe_first, ~s, ~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "decode_"),
- T, NextPos, LName]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n"),
- emit(Fd, " }\n");
- caller_dyn -> %% Malloc used
- emit(Fd, " {\n"),
- emit(Fd, " int oe_outindex = 0;\n\n"),
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, "
- "oe_first, ~s, ~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "decode_"),
- T, NextPos, LName]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n"),
- emit(Fd, " }\n");
- array_dyn -> %% Malloc used
- emit(Fd, " {\n"),
- emit(Fd, " int oe_outindex = 0;\n\n"),
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, "
- "oe_first, ~s, ~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "decode_"),
- T, NextPos, LName]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n"),
- emit(Fd, " }\n");
- array_fix_ret ->
- emit(Fd, " {\n"),
- emit(Fd, " int oe_outindex = 0;\n\n"),
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, "
- "oe_first, ~s,*~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "decode_"),
- T, NextPos, LName]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n"),
- emit(Fd, " }\n");
- array_fix_out -> %% No malloc used, define oe_first
- emit(Fd, " {\n"),
- emit(Fd, " void *oe_first = NULL;\n"),
- emit(Fd, " int oe_outindex = 0;\n\n"),
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, "
- "oe_first, ~s, ~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "decode_"),
- T, NextPos, LName]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n"),
- emit(Fd, " }\n")
- end
- end;
-emit_decoding_stmt(G, N, Fd, T, LName, IndOp, InBuffer, _Align, _NextPos,
- DecType, AllocedPars) when is_record(T, string) ->
- case DecType of
- caller_dyn ->
- emit(Fd, " if ((oe_error_code = ei_decode_string(~s, "
- "&oe_env->_iin, ~s~s)) < 0) {\n",
- [InBuffer, IndOp, LName]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n");
- _ ->
- emit(Fd, " ~s~s = oe_first + *oe_outindex;\n\n",
- [IndOp, LName]),
- emit(Fd, " {\n"),
- emit(Fd, " int oe_type=0;\n"),
- emit(Fd, " int oe_string_ctr=0;\n\n"),
-
- emit(Fd, " (int) ei_get_type(~s, "
- "&oe_env->_iin, &oe_type, &oe_string_ctr);\n\n",
- [InBuffer]),
-
- emit(Fd, " if ((oe_error_code = ei_decode_string(~s, "
- "&oe_env->_iin, ~s~s)) < 0) {\n",
- [InBuffer, IndOp, LName]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n"),
- emit(Fd, " *oe_outindex = ~s;\n",
- [ic_util:mk_align("*oe_outindex+oe_string_ctr+1")]),
- emit(Fd, " }\n\n")
- end;
-emit_decoding_stmt(G, N, Fd, T, LName, IndOp, InBuffer, _Align, _NextPos,
- DecType, AllocedPars) when is_record(T, wstring) ->
- case DecType of
- caller_dyn ->
- %% Note prefix: oe_ei
- emit(Fd, " if ((oe_error_code = oe_ei_decode_wstring(~s, "
- "&oe_env->_iin, ~s~s)) < 0) {\n",
- [InBuffer, IndOp, LName]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }/* --- */\n"); % XXX
- _ ->
- emit(Fd, " ~s~s = oe_first + *oe_outindex;\n\n",
- [IndOp, LName]),
-
- emit(Fd, " {\n"),
- emit(Fd, " int oe_type=0;\n"),
- emit(Fd, " int oe_string_ctr=0;\n\n"),
- emit(Fd, " (int) ei_get_type(~s, "
- "&oe_env->_iin, &oe_type, &oe_string_ctr);\n\n",
- [InBuffer]),
- %% Note prefix: oe_ei
- emit(Fd, " if ((oe_error_code = oe_ei_decode_wstring(~s, "
- "&oe_env->_iin, ~s~s)) < 0) {\n",
- [InBuffer, IndOp, LName]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n"),
- emit(Fd, " *oe_outindex = ~s;\n",
- [ic_util:mk_align("*oe_outindex+oe_string_ctr+1")]),
- emit(Fd, " }\n")
- end;
-emit_decoding_stmt(G, N, Fd, T, LName, IndOp, InBuffer, _Align, NextPos,
- _DecType, AllocedPars) ->
- case normalize_type(T) of
- {basic, Type} ->
- emit_decoding_stmt_for_basic_type(G, N, T, Fd, Type, InBuffer, IndOp,
- LName, AllocedPars);
- {void, _} ->
- emit(Fd, " if ((oe_error_code = ei_decode_atom(~s, "
- "&oe_env->_iin, NULL)) < 0) {\n",
- [InBuffer]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n");
- {sequence, _, _} ->
- ok;
- {_, {array, SId, Dims}} ->
- AName = ic_forms:get_id2({array, SId, Dims}),
- Ptr = "oe_out->"++AName,
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, "
- "oe_first, ~s, ~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "decode_"),
- ic_forms:get_id2(SId),
- NextPos, Ptr]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n");
- {struct, _, _, _} -> %% Struct as a member in struct !
- ok;
- _ ->
- %%io:format("3 ------------> ~p~n", [T]),
- ic_error:fatal_error(G, {illegal_typecode_for_c, T, N})
- end.
-
-%% XXX DecType used in two senses in this file.
-emit_decoding_stmt_for_basic_type(G, N, T, Fd, Type, InBuffer, IndOp,
- LName, AllocedPars) ->
- Fmt =
- " if ((oe_error_code = ~sei_decode_~s(~s, &oe_env->_iin, "
- "~s~s)) < 0) {\n",
- Ret =
- " return oe_error_code;\n"
- "}\n",
-
- {Pre, DecType} =
- case Type of
- ushort -> {"", "ulong"};
- ulong -> {"", "ulong"};
- ulonglong -> {"oe_", "ulonglong"};
- short -> {"", "long"};
- long -> {"", "long"};
- longlong -> {"oe_", "longlong"};
- float -> {"", "double"};
- double -> {"", "double"};
- boolean -> {"", "atom"};
- char -> {"", "char"};
- wchar -> {"oe_", "wchar"};
- octet -> {"", "char"};
- any -> {"", "long"}
- end,
- case Type of
- ushort ->
- emit(Fd, " {\n"),
- emit(Fd, " unsigned long oe_ulong;\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_ulong(~s, "
- "&oe_env->_iin, &oe_ulong)) < 0) {\n",
- [InBuffer]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, "}\n"),
- emit(Fd, " *(~s) = (unsigned short) oe_ulong;\n\n",
- [LName]),
- emit(Fd, " if (*(~s) != oe_ulong){\n",
- [LName]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return -1;\n"),
- emit(Fd, " }\n"),
- emit(Fd, " }\n\n");
- short ->
- emit(Fd, " {\n"),
- emit(Fd, " long oe_long;\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_long(~s, "
- "&oe_env->_iin, &oe_long)) < 0){\n",
- [InBuffer]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n\n"),
- emit(Fd, "}\n"),
- emit(Fd, " *(~s) = (short) oe_long;\n\n",[LName]),
- emit(Fd, " if (*(~s) != oe_long){\n", [LName]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return -1;\n"),
- emit(Fd, " }\n"),
- emit(Fd, " }\n");
- float ->
- emit(Fd, " {\n"),
- emit(Fd, " double oe_double;\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_double(~s, "
- "&oe_env->_iin, &oe_double)) < 0){\n",
- [InBuffer]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n\n"),
- emit(Fd, "}\n"),
- emit(Fd, " *(~s) = (float) oe_double;\n",[LName]),
- emit(Fd, " }\n");
- boolean ->
- emit(Fd, " {\n"),
- emit(Fd, " char oe_bool[25];\n\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_atom(~s, "
- "&oe_env->_iin, oe_bool)) < 0){\n",[InBuffer]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, "}\n"),
- emit(Fd, " if (strcmp(oe_bool, \"false\") == 0) {\n"),
- emit(Fd, " *(~s) = 0;\n",[LName]),
- emit(Fd, " }\n"),
- emit(Fd, " else if (strcmp(oe_bool, \"true\") == 0)"
- " {\n"),
- emit(Fd, " *(~s) = 1;\n",[LName]),
- emit(Fd, " }\n"),
- emit(Fd, " else {\n"),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit(Fd, " return -1;\n"),
- emit(Fd, " }\n"),
- emit(Fd, " }\n");
- _ ->
- emit(Fd, Fmt, [Pre, DecType, InBuffer, IndOp, LName]),
- ?emit_c_dec_rpt(Fd, " ", "~s", [LName]),
- emit_dealloc_stmts(Fd, " ", AllocedPars),
- emit(Fd, Ret)
- end.
-
-%%------------------------------------------------------------
-%%
-%%------------------------------------------------------------
-emit_dealloc_stmts(Fd, Prefix, AllocedPars) ->
- Fmt = Prefix ++ "CORBA_free(~s);\n",
- lists:foreach(
- fun(Par) -> emit(Fd, Fmt, [Par]) end,
- AllocedPars).
-
-
-%%------------------------------------------------------------
-%%
-%%------------------------------------------------------------
-
-mk_variable_name(Var) ->
- Nr = get(Var),
- put(Var, Nr + 1),
- "oe_tmp" ++ integer_to_list(Nr).
-
-%% IDL to C type conversion
-%%------------------------------------------------------------
-mk_c_type(G, N, S) ->
- mk_c_type(G, N, S, evaluate).
-
-mk_c_type(G, N, S, evaluate) when element(1, S) == scoped_id ->
- {FullScopedName, _T, _TK, _} = ic_symtab:get_full_scoped_name(G, N, S),
- BT = ic_code:get_basetype(G, ic_util:to_undersc(FullScopedName)),
- case BT of
- "erlang_binary" ->
- "erlang_binary";
- "erlang_pid" ->
- "erlang_pid";
- "erlang_port" ->
- "erlang_port";
- "erlang_ref" ->
- "erlang_ref";
- "erlang_term" ->
- "ETERM*";
- {enum, Type} ->
- mk_c_type(G, N, Type, evaluate);
- Type ->
- mk_c_type(G, N, Type, evaluate)
- end;
-
-mk_c_type(G, N, S, evaluate_not) when element(1, S) == scoped_id ->
- {FullScopedName, _T, _TK, _} = ic_symtab:get_full_scoped_name(G, N, S),
- BT = ic_code:get_basetype(G, ic_util:to_undersc(FullScopedName)),
- case BT of
- "erlang_binary" ->
- "erlang_binary";
- "erlang_pid" ->
- "erlang_pid";
- "erlang_port" ->
- "erlang_port";
- "erlang_ref" ->
- "erlang_ref";
- "erlang_term" ->
- "ETERM*";
- Type ->
- Type
- end;
-mk_c_type(_G, _N, S, _) when is_list(S) ->
- S;
-mk_c_type(_G, _N, S, _) when is_record(S, string) ->
- "CORBA_char *";
-mk_c_type(_G, _N, S, _) when is_record(S, wstring) ->
- "CORBA_wchar *";
-mk_c_type(_G, _N, {boolean, _}, _) ->
- "CORBA_boolean";
-mk_c_type(_G, _N, {octet, _}, _) ->
- "CORBA_octet";
-mk_c_type(_G, _N, {void, _}, _) ->
- "void";
-mk_c_type(_G, _N, {unsigned, U}, _) ->
- case U of
- {short,_} ->
- "CORBA_unsigned_short";
- {long,_} ->
- "CORBA_unsigned_long";
- {'long long',_} ->
- "CORBA_unsigned_long_long"
- end;
-
-mk_c_type(_G, _N, {'long long', _}, _) ->
- "CORBA_long_long";
-
-mk_c_type(_G, _N, S, _) when is_record(S, union)->
- ic_forms:get_id2(S);
-
-mk_c_type(_G, N, S, _) when is_record(S, struct) -> %% Locally defined member
- Fullname = [ic_forms:get_id2(S) | N],
- ic_util:to_undersc(Fullname);
-
-mk_c_type(_G, _N, {'any', _}, _) -> %% Fix for any type
- "CORBA_long";
-
-mk_c_type(_G, _N, {T, _}, _) ->
- "CORBA_" ++ atom_to_list(T).
-
-%%-------------------------------------------------------------------
-%% IDL to C type conversion used by the emit_c_*_rpt macros.
-%%-------------------------------------------------------------------
-mk_c_type2(G, N, S) when element(1, S) == scoped_id ->
- {FullScopedName, _T, _TK, _} = ic_symtab:get_full_scoped_name(G, N, S),
- BT = ic_code:get_basetype(G, ic_util:to_undersc(FullScopedName)),
- case BT of
- "erlang_binary" ->
- "erlang_binary";
- "erlang_pid" ->
- "erlang_pid";
- "erlang_port" ->
- "erlang_port";
- "erlang_ref" ->
- "erlang_ref";
- "erlang_term" ->
- "ETERM*";
- {enum, Type} ->
- mk_c_type2(G, N, Type);
- Type ->
- mk_c_type2(G, N, Type)
- end;
-
-mk_c_type2(_G, _N, S) when is_list(S) ->
- S;
-mk_c_type2(_G, _N, S) when is_record(S, string) ->
- "CORBA_char *";
-mk_c_type2(_G, _N, S) when is_record(S, wstring) ->
- "CORBA_wchar *";
-mk_c_type2(_G, _N, {boolean, _}) ->
- "CORBA_boolean";
-mk_c_type2(_G, _N, {octet, _}) ->
- "CORBA_octet";
-mk_c_type2(_G, _N, {void, _}) ->
- "void";
-mk_c_type2(_G, _N, {unsigned, U}) ->
- case U of
- {short,_} ->
- "CORBA_unsigned_short";
- {long,_} ->
- "CORBA_unsigned_long";
- {'long long',_} ->
- "CORBA_unsigned_long_long"
- end;
-
-mk_c_type2(_G, _N, {'long long', _}) ->
- "CORBA_long_long";
-
-mk_c_type2(_G, _N, S) when is_record(S, union)->
- ic_forms:get_id2(S);
-
-mk_c_type2(_G, N, S) when is_record(S, struct) ->
- Fullname = [ic_forms:get_id2(S) | N],
- ic_util:to_undersc(Fullname);
-
-mk_c_type2(_G, _N, S) when is_record(S, sequence) ->
- mk_c_type2(_G, _N, S#sequence.type);
-
-mk_c_type2(_G, _N, {'any', _}) -> %% Fix for any type
- "CORBA_long";
-
-mk_c_type2(_G, _N, {T, _}) ->
- "CORBA_" ++ atom_to_list(T).
-
-%%-----
-
-is_variable_size_rec(Es) ->
- lists:any(
- fun({_N, T}) -> is_variable_size(T);
- ({_, _N, T}) -> is_variable_size(T)
- end, Es).
-
-is_variable_size({'tk_struct', _IFRId, "port", _ElementList}) ->
- false;
-is_variable_size({'tk_struct', _IFRId, "pid", _ElementList}) ->
- false;
-is_variable_size({'tk_struct', _IFRId, "ref", _ElementList}) ->
- false;
-is_variable_size({'tk_struct', _IFRId, "term", _ElementList}) ->
- false;
-is_variable_size({'tk_struct', _IFRId, _Name, ElementList}) ->
- is_variable_size_rec(ElementList);
-is_variable_size({'tk_array', ElemTC, _Length}) ->
- is_variable_size(ElemTC);
-is_variable_size({'tk_string', _}) ->
- true;
-is_variable_size({'tk_wstring', _}) ->
- true;
-is_variable_size({'tk_sequence', _ElemTC, _MaxLsextractength}) ->
- true;
-is_variable_size({'tk_union', _IFRId, _Name, _, _, ElementList}) ->
- is_variable_size_rec(ElementList);
-is_variable_size(_Other) ->
- false.
-
-
-is_variable_size(_G, _N, T) when is_record(T, string) ->
- true;
-is_variable_size(_G, _N, T) when is_record(T, wstring) ->
- true;
-is_variable_size(_G, _N, T) when is_record(T, sequence) ->
- true;
-is_variable_size(G, N, T) when is_record(T, union) ->
- %%io:format("~n~p = ~p~n",[ic_forms:get_id2(T),ictype:fetchTk(G, N, T)]),
- is_variable_size(ictype:fetchTk(G, N, T));
-is_variable_size(G, N, T) when is_record(T, struct) ->
- is_variable_size(ictype:fetchTk(G, N, T));
-is_variable_size(G, N, T) when element(1, T) == scoped_id ->
- case ic_symtab:get_full_scoped_name(G, N, T) of
- {_FullScopedName, _, TK, _} ->
- is_variable_size(TK);
- _ ->
- ic_error:fatal_error(G, {name_not_found, T})
- end;
-is_variable_size(_G, _N, _Other) ->
- false.
-
-%% mk_dim produces
-mk_dim([Arg | Args]) ->
- "[" ++ Arg ++ "]" ++ mk_dim(Args);
-mk_dim([]) -> [].
-
-mk_slice_dim(Args) ->
- mk_dim(tl(Args)).
-
-
-emit_tmp_variables(Fd) ->
- DeclList = get(tmp_declarations),
- emit_tmp_variables(Fd, DeclList),
- ok.
-
-emit_tmp_variables(Fd, [Decl |Rest]) ->
- emit_tmp_variables(Fd, Rest),
- emit(Fd, "~s", [Decl]);
-emit_tmp_variables(_Fd, []) ->
- ok.
-
-store_tmp_decl(Format, Args) ->
- Decl = io_lib:format(Format, Args),
- DeclList = get(tmp_declarations),
- put(tmp_declarations, [Decl |DeclList]).
-
-%%------------------------------------------------------------
-%%
-%% Parser utilities
-%%
-%% Called from the yecc parser. Expands the identifier list of an
-%% attribute so that the attribute generator never has to handle
-%% lists.
-%%
-%%------------------------------------------------------------
-
-extract_info(_G, N, X) when is_record(X, op) ->
- Name = ic_util:to_undersc([ic_forms:get_id2(X) | N]),
- Args = X#op.params,
- ArgNames = mk_c_vars(Args),
- TypeList = {ic_forms:get_type(X),
- lists:map(fun(Y) -> ic_forms:get_type(Y) end, Args),
- []
- },
- {Name, ArgNames, TypeList};
-extract_info(_G, N, X) ->
- Name = ic_util:to_undersc([ic_forms:get_id2(X) | N]),
- {Name, [], []}.
-
-
-
-%% Usefull functions
-get_param_tk(Name, Op) ->
- case get_param(Name, Op) of
- error ->
- error;
- Param ->
- ic_forms:get_tk(Param)
- end.
-
-get_param(Name, Op) when is_record(Op, op) ->
- get_param_loop(Name, Op#op.params);
-get_param(_Name, _Op) ->
- error.
-
-get_param_loop(Name,[Param|Params]) ->
- case ic_forms:get_id2(Param) of
- Name ->
- Param;
- _ ->
- get_param_loop(Name,Params)
- end;
-get_param_loop(_Name, []) ->
- error.
-
-
-%% Input is a list of parameters (in parse form) and output is a list
-%% of parameter attribute and variable names.
-mk_c_vars(Params) ->
- lists:map(fun(P) -> {A, _} = P#param.inout,
- {A, ic_forms:get_id(P#param.id)}
- end,
- Params).
-
-normalize_type({unsigned, {short, _}}) -> {basic, ushort};
-normalize_type({unsigned, {long, _}}) -> {basic, ulong};
-normalize_type({unsigned, {'long long', _}}) -> {basic, ulonglong};
-normalize_type({short,_}) -> {basic, short};
-normalize_type({long, _}) -> {basic, long};
-normalize_type({'long long', _}) -> {basic, longlong};
-normalize_type({float,_}) -> {basic, float};
-normalize_type({double, _}) -> {basic, double};
-normalize_type({boolean, _}) -> {basic, boolean};
-normalize_type({char, _}) -> {basic, char};
-normalize_type({wchar, _}) -> {basic, wchar};
-normalize_type({octet, _}) -> {basic, octet};
-normalize_type({any, _}) -> {basic, any};
-normalize_type(tk_ushort) -> {basic, ushort};
-normalize_type(tk_ulong) -> {basic, ulong};
-normalize_type(tk_ulonglong) -> {basic, ulonglong};
-normalize_type(tk_short) -> {basic, short};
-normalize_type(tk_long) -> {basic, long};
-normalize_type(tk_longlong) -> {basic, longlong};
-normalize_type(tk_float) -> {basic, float};
-normalize_type(tk_double) -> {basic, double};
-normalize_type(tk_boolean) -> {basic, boolean};
-normalize_type(tk_char) -> {basic, char};
-normalize_type(tk_wchar) -> {basic, wchar};
-normalize_type(tk_octet) -> {basic, octet};
-normalize_type(tk_any) -> {basic, any};
-normalize_type(ushort) -> {basic, ushort};
-normalize_type(ulong) -> {basic, ulong};
-normalize_type(ulonglong) -> {basic, ulonglong};
-normalize_type(short) -> {basic, short};
-normalize_type(long) -> {basic, long};
-normalize_type(longlong) -> {basic, longlong};
-normalize_type(float) -> {basic, float};
-normalize_type(double) -> {basic, double};
-normalize_type(boolean) -> {basic, boolean};
-normalize_type(char) -> {basic, char};
-normalize_type(wchar) -> {basic, wchar};
-normalize_type(octet) -> {basic, octet};
-normalize_type(any) -> {basic, any};
-normalize_type(Type) -> Type.
-
diff --git a/lib/ic/src/ic_cclient.erl b/lib/ic/src/ic_cclient.erl
deleted file mode 100644
index 8591acf33f..0000000000
--- a/lib/ic/src/ic_cclient.erl
+++ /dev/null
@@ -1,1210 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(ic_cclient).
-
-%% This module implements generation of C client code, where the
-%% client acts as an Erlang C-node, and where the communication thus
-%% is according to the Erlang distribution protocol.
-%%
-
--export([do_gen/3]).
-
-%%------------------------------------------------------------
-%% IMPLEMENTATION CONVENTIONS
-%%------------------------------------------------------------
-%% Functions:
-%%
-%% mk_* returns things to be used. No side effects.
-%% emit_* Writes to file. Has Fd in arguments.
-%% gen_* Same, but has no Fd. Usually for larger things.
-%%
-%% Terminology for generating C:
-%%
-%% par_list list of identifiers with types, types only, or with
-%% parameters (arguments) only.
-%% arg_list list of identifiers only (for function calls)
-%%
-
-%%------------------------------------------------------------
-%% Internal stuff
-%%------------------------------------------------------------
-
--import(lists, [foreach/2, foldl/3, foldr/3]).
--import(ic_codegen, [emit/2, emit/3, emit/4, emit_c_enc_rpt/4, emit_c_dec_rpt/4]).
-
--include("icforms.hrl").
--include("ic.hrl").
--include_lib("stdlib/include/erl_compile.hrl").
-
--define(IC_HEADER, "ic.h").
--define(ERL_INTERFACEHEADER, "erl_interface.h").
--define(EICONVHEADER, "ei.h").
--define(ERLANGATOMLENGTH, "256").
-
-
-%%------------------------------------------------------------
-%% ENTRY POINT
-%%------------------------------------------------------------
-do_gen(G, File, Form) ->
- OeName = ic_util:mk_oe_name(G, remove_ext(ic_util:to_list(File))),
- G2 = ic_file:filename_push(G, [], OeName, c),
- gen_headers(G2, [], Form),
- R = gen(G2, [], Form),
- ic_file:filename_pop(G2, c),
- R.
-
-remove_ext(File) ->
- filename:rootname(filename:basename(File)).
-
-%%------------------------------------------------------------
-%%
-%% Generate client side C stubs.
-%%
-%% - each module definition results in a separate file.
-%% - each interface definition results in a separate file.
-%%
-%% G = record(genobj) (see ic.hrl)
-%% N = scoped names in reverse
-%% X = current form to consider.
-%%------------------------------------------------------------
-
-gen(G, N, [X| Xs]) when is_record(X, preproc) ->
- G1 = change_file_stack(G, N, X),
- gen(G1, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, module) ->
- CD = ic_code:codeDirective(G, X),
- G2 = ic_file:filename_push(G, N, X, CD),
- N2 = [ic_forms:get_id2(X)| N],
- gen_headers(G2, N2, X),
- gen(G2, N2, ic_forms:get_body(X)),
- G3 = ic_file:filename_pop(G2, CD),
- gen(G3, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, interface) ->
-
- G2 = ic_file:filename_push(G, N, X, c),
- N2 = [ic_forms:get_id2(X)| N],
-
- %% Sets the temporary variable counter.
- put(op_variable_count, 0),
- put(tmp_declarations, []),
-
- gen_headers(G2, N2, X),
-
- gen(G2, N2, ic_forms:get_body(X)),
-
- lists:foreach(
- fun({_Name, Body}) ->
- gen(G2, N2, Body) end,
- X#interface.inherit_body),
-
- %% Generate Prototypes
- gen_prototypes(G2, N2, X),
-
- %% Generate generic preparation for decoding
- gen_receive_info(G2, N2, X),
-
- G3 = ic_file:filename_pop(G2, c),
-
- gen(G3, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, const) ->
- emit_constant(G, N, X),
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, op) ->
- {OpName, ArgNames, RetParTypes} = ic_cbe:extract_info(G, N, X),
- %% XXX Note: N is the list of scoped ids of the *interface*.
- gen_operation(G, N, X, OpName, ArgNames, RetParTypes),
- gen_encoder(G, N, X, OpName, ArgNames, RetParTypes),
- gen_decoder(G, N, X, OpName, ArgNames, RetParTypes),
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, attr) ->
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, except) ->
- icstruct:except_gen(G, N, X, c),
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, enum) ->
- icenum:enum_gen(G, N, X, c),
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, typedef) ->
- icstruct:struct_gen(G, N, X, c),
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, struct) ->
- icstruct:struct_gen(G, N, X, c),
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, union) ->
- icstruct:struct_gen(G, N, X, c),
- gen(G, N, Xs);
-
-gen(G, N, [_X| Xs]) ->
- %% XXX Should have debug message here.
- gen(G, N, Xs);
-
-gen(_G, _N, []) ->
- ok.
-
-%%------------------------------------------------------------
-%% Change file stack
-%%------------------------------------------------------------
-
-change_file_stack(G, _N, X) when X#preproc.cat == line_nr ->
- Id = ic_forms:get_id2(X),
- Flags = X#preproc.aux,
- case Flags of
- [] ->
- ic_genobj:push_file(G, Id);
- _ ->
- foldr(
- fun({_, _, "1"}, G1) ->
- ic_genobj:push_file(G1, Id);
- ({_, _, "2"}, G1) ->
- ic_genobj:pop_file(G1, Id);
- ({_, _, "3"}, G1) ->
- ic_genobj:sys_file(G1, Id)
- end, G, Flags)
- end;
-change_file_stack(G, _N, _X) ->
- G.
-
-%%------------------------------------------------------------
-%% Generate headers in stubfiles and header files
-%%------------------------------------------------------------
-
-gen_headers(G, N, X) when is_record(X, interface) ->
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- %% Set the temporary variable counter
- put(op_variable_count, 0),
- put(tmp_declarations, []),
- HFd = ic_genobj:hrlfiled(G),
- IncludeFileStack = ic_genobj:include_file_stack(G),
- L = length(N),
- Filename =
- if
- L < 2 ->
- lists:nth(L + 1, IncludeFileStack);
- true ->
- lists:nth(2, IncludeFileStack)
- end,
- emit(HFd, "#include \"~s\"\n", [filename:basename(Filename)]),
- ic_code:gen_includes(HFd, G, X, c_client),
-
- IfName = ic_util:to_undersc(N),
- IfNameUC = ic_util:to_uppercase(IfName),
- emit(HFd, "\n#ifndef __~s__\n", [IfNameUC]),
- emit(HFd, "#define __~s__\n", [IfNameUC]),
- LCmt = io_lib:format("Interface object definition: ~s", [IfName]),
- ic_codegen:mcomment_light(HFd, [LCmt], c),
- case get_c_timeout(G, "") of
- "" ->
- ok;
- {SendTmo, RecvTmo} ->
- emit(HFd, "#define OE_~s_SEND_TIMEOUT ~s\n",
- [IfNameUC, SendTmo]),
- emit(HFd, "#define OE_~s_RECV_TIMEOUT ~s\n",
- [IfNameUC, RecvTmo]),
- emit(HFd, "#ifndef EI_HAVE_TIMEOUT\n"),
- emit(HFd, "#error Functions for send and receive with "
- "timeout not defined in erl_interface\n"),
- emit(HFd, "#endif\n\n")
- end,
-
- emit(HFd, "typedef CORBA_Object ~s;\n", [IfName]),
- emit(HFd, "#endif\n\n");
-
- false -> ok
- end,
- case ic_genobj:is_stubfile_open(G) of
- true ->
- Fd = ic_genobj:stubfiled(G),
- ic_codegen:nl(Fd),
- emit(Fd, "#include <stdlib.h>\n"),
- emit(Fd, "#include <string.h>\n"),
- case ic_options:get_opt(G, c_report) of
- true ->
- emit(Fd, "#ifndef OE_C_REPORT\n"),
- emit(Fd, "#define OE_C_REPORT\n"),
- emit(Fd, "#include <stdio.h>\n"),
- emit(Fd, "#endif\n");
- _ ->
- ok
- end,
- emit(Fd, "#include \"~s\"\n", [?IC_HEADER]),
- emit(Fd, "#include \"~s\"\n", [?ERL_INTERFACEHEADER]),
- emit(Fd, "#include \"~s\"\n", [?EICONVHEADER]),
- emit(Fd, "#include \"~s\"\n",
- [filename:basename(ic_genobj:include_file(G))]),
- ic_codegen:nl(Fd), ic_codegen:nl(Fd),
- Fd; % XXX ??
- false ->
- ok
- end;
-
-%% Some items have extra includes
-gen_headers(G, N, X) when is_record(X, module) ->
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- HFd = ic_genobj:hrlfiled(G),
- IncludeFileStack = ic_genobj:include_file_stack(G),
- Filename = lists:nth(length(N) + 1, IncludeFileStack),
- emit(HFd, "#include \"~s\"\n", [filename:basename(Filename)]),
- ic_code:gen_includes(HFd, G, X, c_client);
- false -> ok
- end;
-gen_headers(G, [], _X) ->
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- HFd = ic_genobj:hrlfiled(G),
- case ic_options:get_opt(G, c_report) of
- true ->
- emit(HFd, "#ifndef OE_C_REPORT\n"),
- emit(HFd, "#define OE_C_REPORT\n"),
- emit(HFd, "#include <stdio.h>\n"),
- emit(HFd, "#endif\n");
- _ ->
- ok
- end,
- emit(HFd, "#include \"~s\"\n", [?IC_HEADER]),
- emit(HFd, "#include \"~s\"\n", [?ERL_INTERFACEHEADER]),
- emit(HFd, "#include \"~s\"\n", [?EICONVHEADER]),
- ic_code:gen_includes(HFd, G, c_client);
- false -> ok
- end;
-gen_headers(_G, _N, _X) ->
- ok.
-
-
-%%------------------------------------------------------------
-%% Generate all prototypes (for interface)
-%%------------------------------------------------------------
-gen_prototypes(G, N, X) ->
- case ic_genobj:is_hrlfile_open(G) of
- false ->
- ok;
- true ->
- HFd = ic_genobj:hrlfiled(G),
- IfName = ic_util:to_undersc(N),
-
- %% Emit generated function prototypes
- emit(HFd, "\n/* Operation functions */\n"),
- lists:foreach(fun({_Name, Body}) ->
- emit_operation_prototypes(G, HFd, N, Body)
- end, [{x, ic_forms:get_body(X)}|
- X#interface.inherit_body]),
-
- UserProto = get_user_proto(G, false),
- %% Emit generic function prototypes
- case UserProto of
- false ->
- ok;
- UserProto ->
- emit(HFd,
- "\n/* Generic user defined encoders */\n"),
- emit(HFd,
- "int ~s_prepare_notification_encoding("
- "CORBA_Environment*);"
- "\n", [UserProto]),
- emit(HFd,
- "int ~s_prepare_request_encoding(CORBA_Environment*);"
- "\n", [UserProto])
- end,
- %% Emit encoding function prototypes
- emit(HFd, "\n/* Input encoders */\n"),
- lists:foreach(fun({_Name, Body}) ->
- emit_encoder_prototypes(G, HFd, N, Body)
- end,
- [{x, ic_forms:get_body(X)}|
- X#interface.inherit_body]),
-
- %% Emit generic function prototypes
- emit(HFd, "\n/* Generic decoders */\n"),
- emit(HFd, "int ~s__receive_info(~s, CORBA_Environment*);\n",
- [IfName, IfName]),
-
- case UserProto of
- false ->
- ok;
- UserProto ->
- emit(HFd, "\n/* Generic user defined decoders */\n"),
- emit(HFd,
- "int ~s_prepare_reply_decoding(CORBA_Environment*);"
- "\n", [UserProto])
- end,
- %% Emit decode function prototypes
- emit(HFd, "\n/* Result decoders */\n"),
- lists:foreach(fun({_Name, Body}) ->
- emit_decoder_prototypes(G, HFd, N, Body)
- end, [{x, ic_forms:get_body(X)}|
- X#interface.inherit_body]),
- case UserProto of
- false ->
- ok;
- UserProto ->
- %% Emit generic send and receive_prototypes
- {Sfx, TmoType} = case get_c_timeout(G, "") of
- "" ->
- {"", ""};
- _ ->
- {"_tmo", ", unsigned int"}
- end,
- emit(HFd,
- "\n/* Generic user defined send and receive "
- "functions */\n"),
- emit(HFd,
- "int ~s_send_notification~s(CORBA_Environment*~s);\n",
- [UserProto, Sfx, TmoType]),
- emit(HFd,
- "int ~s_send_request_and_receive_reply~s("
- "CORBA_Environment*~s~s);\n",
- [UserProto, Sfx, TmoType, TmoType])
- end
- end.
-
-%%------------------------------------------------------------
-%% Generate receive_info() (generic part for message reception)
-%% (for interface). For backward compatibility only.
-%%------------------------------------------------------------
-
-gen_receive_info(G, N, _X) ->
- case ic_genobj:is_stubfile_open(G) of
- false ->
- ok;
- true ->
- Fd = ic_genobj:stubfiled(G),
- IfName = ic_util:to_undersc(N),
- UserProto = get_user_proto(G, oe),
- Code =
- "
-/*
- * Generic function, used to return received message information.
- * Not used by oneways. Always generated. For backward compatibility only.
- */
-
-int ~s__receive_info(~s oe_obj, CORBA_Environment *oe_env)
-{
- return ~s_prepare_reply_decoding(oe_env);
-}\n",
- emit(Fd, Code, [IfName, IfName, UserProto])
-end.
-
-%%------------------------------------------------------------
-%% Emit constant
-%%------------------------------------------------------------
-
-emit_constant(G, N, ConstRecord) ->
- case ic_genobj:is_hrlfile_open(G) of
- false -> ok;
- true ->
- Fd = ic_genobj:hrlfiled(G),
- CName = ic_util:to_undersc(
- [ic_forms:get_id(ConstRecord#const.id)| N]),
- UCName = ic_util:to_uppercase(CName),
-
- emit(Fd, "\n#ifndef __~s__\n", [UCName]),
- emit(Fd, "#define __~s__\n", [UCName]),
-
- emit(Fd, "/* Constant: ~s */\n", [CName]),
-
- if is_record(ConstRecord#const.type, wstring) ->
- %% If wstring, add 'L'
- emit(Fd, "#define ~s L~p\n",
- [CName, ConstRecord#const.val]);
- true ->
- emit(Fd, "#define ~s ~p\n",
- [CName, ConstRecord#const.val])
- end,
- emit(Fd, "#endif\n\n")
- end.
-
-%%------------------------------------------------------------
-%% Generate operation (for interface)
-%%------------------------------------------------------------
-
-%% N is the list of scoped ids of the *interface*.
-%% X is the operation
-gen_operation(G, N, X, OpName, ArgNames, RetParTypes) ->
- case ic_genobj:is_stubfile_open(G) of
- true ->
- do_gen_operation(G, N, X, OpName, ArgNames, RetParTypes);
- false ->
- ok
- end.
-
-do_gen_operation(G, N, X, OpName, ArgNames, RetParTypes) ->
- Fd = ic_genobj:stubfiled(G),
- IfName = ic_util:to_undersc(N),
- IfNameUC = ic_util:to_uppercase(IfName),
-
- {R, ParTypes, _} = RetParTypes,
-
- IsOneway = ic_forms:is_oneway(X),
-
- emit(Fd, "\n"
- "/***\n"
- " *** Operation function \"~s\" ~s\n"
- " ***/\n\n",
- [OpName, ifelse(IsOneway, "(oneway)", "")]),
-
- RV = element(1, R),
- Ret = case IsOneway of
- false ->
- if RV /= void ->
- mk_ret_type(G, N, R);
- true ->
- "void"
- end;
- true ->
- "void"
- end,
- ParListStr = ic_util:chain(mk_par_type_list(G, N, X, [in, out],
- [types, args],
- ParTypes, ArgNames), ", "),
- emit(Fd,
- "~s ~s(~s, ~sCORBA_Environment *oe_env)\n{\n",
- [Ret, OpName, [IfName, " ", "oe_obj"], ParListStr]),
-
- case IsOneway of
- true ->
- ok;
- false ->
- case ictype:isArray(G, N, R) of
- true ->
- emit(Fd, " ~s oe_return = NULL;\n\n",
- [mk_ret_type(G, N, R)]);
- false ->
- if RV /= void ->
- emit(Fd, " ~s oe_return;\n\n",
- [Ret]);
- true ->
- ok
- end
- end,
- emit(Fd,
- " /* Initiating the message reference */\n"
- " ic_init_ref(oe_env, &oe_env->_unique);\n")
- end,
-
- emit(Fd,
- " /* Initiating exception indicator */ \n"
- " oe_env->_major = CORBA_NO_EXCEPTION;\n"),
-
- %% XXX Add pointer checks: checks of in-parameter
- %% pointers, and non-variable out-parameter pointers.
-
- emit(Fd," /* Creating ~s message */ \n",
- [ifelse(IsOneway, "cast", "call")]),
-
- EncParListStr = ic_util:chain(mk_arg_list_for_encoder(G, N, X,
- ParTypes, ArgNames),
- ", "),
- emit(Fd,
- " if (~s__client_enc(oe_obj, ~s""oe_env) < 0) {\n",
- [OpName, EncParListStr]),
- emit(Fd,
- " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "DATA_CONVERSION, \"Cannot encode message\");\n"),
-
- RetVar = ifelse(RV /= void, " oe_return", ""),
- emit_c_enc_rpt(Fd, " ", "client operation ~s\\n====\\n", [OpName]),
-
- emit(Fd, " return~s;\n }\n", [RetVar]),
-
- emit(Fd," /* Sending ~s message */ \n",
- [ifelse(IsOneway, "cast", "call")]),
-
- UserProto = get_user_proto(G, oe),
- {Sfx, SendTmo, RecvTmo} = case get_c_timeout(G, "") of
- "" ->
- {"", "", ""};
- _ ->
- {"_tmo",
- [", OE_", IfNameUC, "_SEND_TIMEOUT"],
- [", OE_", IfNameUC, "_RECV_TIMEOUT"]}
- end,
-
- case IsOneway of
- true ->
- emit(Fd,
- " if (~s_send_notification~s(oe_env~s) < 0)\n"
- " return~s;\n", [UserProto, Sfx, SendTmo, RetVar]);
- false ->
- emit(Fd,
- " if (~s_send_request_and_receive_reply~s(oe_env~s~s) < 0)\n"
- " return~s;\n",
- [UserProto, Sfx, SendTmo, RecvTmo, RetVar]),
-
- DecParList0 = mk_arg_list_for_decoder(G, N, X,
- ParTypes, ArgNames),
- DecParList1 = case mk_ret_type(G, N, R) of
- "void" ->
- DecParList0;
- _ ->
- ["&oe_return"| DecParList0]
- end,
-
- DecParListStr = ic_util:chain(DecParList1, ", "),
- %% YYY Extracting results
- emit(Fd,
- " /* Extracting result value(s) */ \n"
- " if (~s__client_dec(oe_obj, ~s""oe_env) < 0) {\n",
- [OpName, DecParListStr]),
- emit(Fd,
- " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, DATA_CONVERSION, "
- "\"Bad result value(s)\");\n"),
- emit_c_dec_rpt(Fd, " ", "client operation ~s\\n=====\\n", [OpName]),
- emit(Fd,
- " return~s;\n"
- " }\n", [RetVar])
- end,
- emit(Fd, " return~s;\n", [RetVar]),
- emit(Fd, "}\n\n\n").
-
-%%------------------------------------------------------------
-%% Generate encoder
-%%------------------------------------------------------------
-%% N is the list of scoped ids of the *interface*.
-%% X is the operation
-gen_encoder(G, N, X, OpName, ArgNames, RetParTypes)->
- case ic_genobj:is_stubfile_open(G) of
- true ->
- Fd = ic_genobj:stubfiled(G),
- IfName = ic_util:to_undersc(N),
- {_R, ParTypes, _} = RetParTypes,
- TypeAttrArgs = mk_type_attr_arg_list(ParTypes, ArgNames),
- emit(Fd, "/*\n * Encode operation input for \"~s\"\n */\n\n",
- [OpName]),
- ParList = ic_util:chain(
- mk_par_type_list(G, N, X, [in], [types, args],
- ParTypes, ArgNames), ", "),
- emit(Fd,
- "int ~s__client_enc(~s oe_obj, ~s"
- "CORBA_Environment *oe_env)\n{\n",
- [OpName, IfName, ParList]),
-
- InTypeAttrArgs = lists:filter(fun({_, in, _}) -> true;
- ({_, _, _}) -> false
- end, TypeAttrArgs),
- case InTypeAttrArgs of
- [] ->
- ok;
- _ ->
- emit(Fd,
- " int oe_error_code = 0;\n\n")
- end,
-
- emit_encodings(G, N, Fd, X, InTypeAttrArgs,
- ic_forms:is_oneway(X)),
- emit(Fd, " return 0;\n}\n\n"),
- ok;
-
- false ->
- ok
- end.
-
-%%------------------------------------------------------------
-%% Generate decoder
-%%------------------------------------------------------------
-%% N is the list of scoped ids of the *interface*.
-%% X is the operation
-gen_decoder(G, N, X, OpName, ArgNames, RetParTypes)->
- case ic_forms:is_oneway(X) of
- true ->
- ok;
- false ->
- case ic_genobj:is_stubfile_open(G) of
- true ->
- Fd = ic_genobj:stubfiled(G),
- IfName = ic_util:to_undersc(N),
- {R, ParTypes, _} = RetParTypes,
- TypeAttrArgs = mk_type_attr_arg_list(ParTypes, ArgNames),
- emit(Fd, "/*\n * Decode operation results for "
- "\"~s\"\n */\n\n", [OpName]),
- ParList0 = mk_par_type_list(G, N, X, [out],
- [types, args],
- ParTypes, ArgNames),
- PARLIST = case mk_ret_type(G, N, R) of
- "void" ->
- ParList0;
- Else ->
- [Else ++ "* oe_return"| ParList0]
- end,
- PLFCD = ic_util:chain(PARLIST, ", "),
- emit(Fd,
- "int ~s__client_dec(~s oe_obj, ~s"
- "CORBA_Environment *oe_env)\n{\n",
- [OpName, IfName, PLFCD]),
- emit(Fd, " int oe_error_code = 0;\n"),
- OutTypeAttrArgs = lists:filter(fun({_, out, _}) -> true;
- ({_, _, _}) -> false
- end, TypeAttrArgs),
- emit_decodings(G, N, Fd, R, OutTypeAttrArgs),
- emit(Fd, " return 0;\n}\n\n"),
- ok;
-
- false ->
- ok
- end
- end.
-
-%%------------------------------------------------------------
-%% EMIT ENCODINGS/DECODINGS
-%%------------------------------------------------------------
-%%------------------------------------------------------------
-%% Emit encodings
-%%------------------------------------------------------------
-%% N is the list of scoped ids of the *interface*.
-%% X is the operation
-%% emit_encodings(G, N, Fd, X, TypeAttrArgs, IsOneWay)
-%%
-emit_encodings(G, N, Fd, X, TypeAttrArgs, true) ->
- %% Cast
- UserProto = get_user_proto(G, oe),
- emit(Fd,
- " if (~s_prepare_notification_encoding(oe_env) < 0)\n"
- " return -1;\n", [UserProto]),
- emit_encodings_1(G, N, Fd, X, TypeAttrArgs);
-emit_encodings(G, N, Fd, X, TypeAttrArgs, false) ->
- %% Call
- UserProto = get_user_proto(G, oe),
- emit(Fd,
- " if (~s_prepare_request_encoding(oe_env) < 0)\n"
- " return -1;\n", [UserProto]),
- emit_encodings_1(G, N, Fd, X, TypeAttrArgs).
-
-emit_encodings_1(G, N, Fd, X, TypeAttrArgs) ->
- {ScopedName, _, _} = ic_cbe:extract_info(G, N, X),
- Name = case ic_options:get_opt(G, scoped_op_calls) of
- true ->
- ScopedName;
- false ->
- ic_forms:get_id2(X)
- end,
- if
- TypeAttrArgs /= [] ->
- emit(Fd, " if (oe_ei_encode_tuple_header(oe_env, ~p) < 0) {\n",
- [length(TypeAttrArgs) + 1]),
- emit_c_enc_rpt(Fd, " ", "ei_encode_tuple_header", []),
- emit(Fd, " return -1;\n }\n");
- true ->
- ok
- end,
- emit(Fd, " if (oe_ei_encode_atom(oe_env, ~p) < 0) {\n", [Name]),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_atom", []),
- emit(Fd, " return -1;\n }\n"),
-
- foreach(fun({{'void', _}, _, _}) ->
- ok;
- ({T1, A1, N1}) ->
- IndOp = mk_ind_op(A1),
- emit_coding_comment(G, N, Fd, "Encode", IndOp,
- T1, N1),
- ic_cbe:emit_encoding_stmt(G, N, X, Fd, T1, IndOp ++ N1,
- "oe_env->_outbuf")
- end, TypeAttrArgs),
- ok.
-
-%%------------------------------------------------------------
-%% Emit dedodings
-%%------------------------------------------------------------
-%% XXX Unfortunately we have to retain the silly `oe_first' variable,
-%% since its name is hardcoded in other modules (icstruct, icunion,
-%% etc).
-%% N is the list of scoped ids of the *interface*.
-%% X is the operation
-emit_decodings(G, N, Fd, RetType, TypeAttrArgs) ->
- if
- TypeAttrArgs /= [] ->
- %% Only if there are out parameters
- emit(Fd, " if ((oe_error_code = ei_decode_tuple_header("
- "oe_env->_inbuf, &oe_env->_iin, "
- "&oe_env->_received)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_decode_tuple_header", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- Len = length(TypeAttrArgs) + 1,
- emit(Fd, " if (oe_env->_received != ~p) {\n", [Len]),
- emit_c_dec_rpt(Fd, " ", "tuple header size != ~p", [Len]),
- emit(Fd, " return -1;\n }\n");
- true ->
- ok
- end,
-
- %% Fetch the return value
- emit_coding_comment(G, N, Fd, "Decode return value", "*", RetType, "oe_return"),
- APars =
- case ic_cbe:is_variable_size(G, N, RetType) of
- true ->
- emit(Fd,
- " {\n"
- " int oe_size_count_index = oe_env->_iin;\n"
- " int oe_malloc_size = 0;\n"
- " void *oe_first = NULL;\n"),
- ic_cbe:emit_malloc_size_stmt(G, N, Fd, RetType,
- "oe_env->_inbuf",
- 1, caller),
- %% XXX Add malloc prefix from option
- emit(Fd,
- " OE_MALLOC_SIZE_CHECK(oe_env, oe_malloc_size);\n"
- " if ((*oe_return = oe_first = "
- "malloc(oe_malloc_size)) == NULL) {\n"
- " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "NO_MEMORY, \"Cannot malloc\");\n"
- " return -1;\n"
- " }\n"),
- Pars = ["*oe_return"],
- DecType = case ictype:isArray(G, N, RetType) of
- true -> array_dyn;
- false -> caller_dyn
- end,
- ic_cbe:emit_decoding_stmt(G, N, Fd, RetType,
- "(*oe_return)",
- "", "oe_env->_inbuf", 1,
- "&oe_outindex", DecType,
- Pars),
- emit(Fd, " }\n"),
- Pars;
- false ->
- case ictype:isArray(G, N, RetType) of
- true ->
- Pars = ["*oe_return"],
- emit(Fd,
- " {\n"
- " int oe_size_count_index = oe_env->_iin;\n"
- " int oe_malloc_size = 0;\n"
- " void *oe_first = NULL;\n"),
- ic_cbe:emit_malloc_size_stmt(G, N, Fd, RetType,
- "oe_env->_inbuf",
- 1, caller),
- %% XXX Add malloc prefix from option
- emit(Fd,
- " OE_MALLOC_SIZE_CHECK(oe_env, "
- "oe_malloc_size);\n"
- " if ((*oe_return = oe_first = "
- "malloc(oe_malloc_size)) == NULL) {\n"
- " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, NO_MEMORY, "
- "\"Cannot malloc\");\n"
- " return -1;"
- " }\n"),
- ic_cbe:emit_decoding_stmt(G, N, Fd, RetType,
- "oe_return", "",
- "oe_env->_inbuf", 1,
- "&oe_outindex",
- array_fix_ret,
- Pars),
- emit(Fd, " }\n"),
- Pars;
- false ->
- Pars = [],
- %% The last parameter "oe_outindex" is not interesting
- %% in the static case.
- ic_cbe:emit_decoding_stmt(G, N, Fd, RetType,
- "oe_return", "",
- "oe_env->_inbuf", 1,
- "&oe_outindex",
- caller, Pars),
- ic_codegen:nl(Fd),
- Pars
- end
- end,
-
- foldl(fun({{'void', _}, _, _}, Acc) ->
- Acc;
- ({T, A, N1}, Acc) ->
- emit_one_decoding(G, N, Fd, T, A, N1, Acc)
- end, APars, TypeAttrArgs),
- ok.
-
-emit_one_decoding(G, N, Fd, T, A, N1, Acc) ->
- IndOp = mk_ind_op(A),
- case ic_cbe:is_variable_size(G, N, T) of
- true ->
- emit_coding_comment(G, N, Fd, "Decode", IndOp,
- T, N1),
- emit(Fd,
- " {\n"
- " int oe_size_count_index = oe_env->_iin;\n"
- " int oe_malloc_size = 0;\n"
- " void *oe_first = NULL;\n"),
- ic_cbe:emit_malloc_size_stmt(G, N, Fd, T,
- "oe_env->_inbuf",
- 1, caller),
- %% XXX Add malloc prefix from option
- emit(Fd,
- " OE_MALLOC_SIZE_CHECK(oe_env, oe_malloc_size);\n"
- " if ((~s~s = oe_first = "
- "malloc(oe_malloc_size)) == NULL) {\n", [IndOp, N1]),
- ic_cbe:emit_dealloc_stmts(Fd, " ", Acc),
- emit(Fd,
- " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "NO_MEMORY, \"Cannot malloc\");\n"
- " return -1;\n"
- " }\n"),
- NAcc = [IndOp ++ N1| Acc],
- DecType = case ictype:isArray(G, N, T) of
- true ->
- array_dyn;
- false ->
- caller_dyn
- end,
- ic_cbe:emit_decoding_stmt(G, N, Fd, T,
- "(" ++ IndOp
- ++ N1 ++ ")", "",
- "oe_env->_inbuf", 1,
- "&oe_outindex",
- DecType, NAcc),
- emit(Fd, " }\n"),
- NAcc;
- false ->
- case ictype:isArray(G, N, T) of
- true ->
- emit_coding_comment(G, N, Fd, "Decode", "",
- T, N1),
- ic_cbe:emit_decoding_stmt(G, N, Fd, T, N1,
- "", "oe_env->_inbuf",
- 1, "&oe_outindex",
- array_fix_out, Acc),
- ic_codegen:nl(Fd),
- [N1| Acc];
- false ->
- %% The last parameter "oe_outindex" is
- %% not interesting in the static case, but
- %% must be present anyhow.
- emit_coding_comment(G, N, Fd, "Decode",
- IndOp, T, N1),
- ic_cbe:emit_decoding_stmt(G, N, Fd, T, N1,
- "", "oe_env->_inbuf",
- 1, "&oe_outindex",
- caller, Acc),
- ic_codegen:nl(Fd),
- Acc
- end
- end.
-
-%%------------------------------------------------------------
-%% GENERATE PROTOTYPES
-%%------------------------------------------------------------
-%%------------------------------------------------------------
-%% Generate operation prototypes
-%%------------------------------------------------------------
-emit_operation_prototypes(G, Fd, N, Xs) ->
- lists:foreach(
- fun(X) when is_record(X, op) ->
- {ScopedName, ArgNames, RetParTypes} =
- ic_cbe:extract_info(G, N, X),
- {R, ParTypes, _} = RetParTypes,
- IfName = ic_util:to_undersc(N),
- RT = mk_ret_type(G, N, R),
- ParList =
- ic_util:chain(
- mk_par_type_list(G, N, X, [in, out], [types],
- ParTypes, ArgNames),
- ", "),
- emit(Fd, "~s ~s(~s, ~sCORBA_Environment*);\n",
- [RT, ScopedName, IfName, ParList]);
- (_) ->
- ok
- end, Xs).
-
-%%------------------------------------------------------------
-%% Generate encoder prototypes
-%%------------------------------------------------------------
-emit_encoder_prototypes(G, Fd, N, Xs) ->
- lists:foreach(
- fun(X) when is_record(X, op) ->
- {ScopedName, ArgNames, RetParTypes} =
- ic_cbe:extract_info(G, N, X),
- {_R, ParTypes, _} = RetParTypes,
- IfName = ic_util:to_undersc(N),
- ParList = ic_util:chain(
- mk_par_type_list(G, N, X, [in], [types],
- ParTypes, ArgNames),
- ", "),
- emit(Fd, "int ~s__client_enc(~s, ~sCORBA_Environment*);\n",
- [ScopedName, IfName, ParList]);
- (_) ->
- ok
- end, Xs).
-
-%%------------------------------------------------------------
-%% Generate decoder prototypes
-%%------------------------------------------------------------
-emit_decoder_prototypes(G, Fd, N, Xs) ->
- lists:foreach(
- fun(X) when is_record(X, op) ->
- case ic_forms:is_oneway(X) of
- true ->
- true;
- false ->
- IfName = ic_util:to_undersc(N),
- {ScopedName, ArgNames, RetParTypes} =
- ic_cbe:extract_info(G, N, X),
- {R, ParTypes, _} = RetParTypes,
- ParList0 =
- mk_par_type_list(G, N, X, [out], [types],
- ParTypes, ArgNames),
- PARLIST = case mk_ret_type(G, N, R) of
- "void" ->
- ParList0;
- Else ->
- [Else ++ "*"| ParList0]
- end,
- ParList = ic_util:chain(PARLIST, ", "),
- emit(Fd, "int ~s__client_dec(~s, ~s"
- "CORBA_Environment*);\n",
- [ScopedName, IfName, ParList])
- end;
- (_) ->
- ok
- end, Xs).
-
-%%------------------------------------------------------------
-%% PARAMETER TYPE LISTS
-%%------------------------------------------------------------
-%%------------------------------------------------------------
-%% Make parameter type list
-%%
-%% InOrOut = in | out | [in | out]
-%% TypesOrArgs = types | args | [types | args]
-%%------------------------------------------------------------
-mk_par_type_list(G, N, X, InOrOut, TypesOrArgs, Types, Args) ->
- TypeAttrArgs =
- filterzip(
- fun(_, {inout, Arg}) ->
- ic_error:error(G, {inout_spec_for_c, X, Arg}),
- false;
- (Type, {Attr, Arg}) ->
- case lists:member(Attr, InOrOut) of
- true ->
- {true, {Type, Attr, Arg}};
- false ->
- false
- end
- end, Types, Args),
- lists:map(
- fun({Type, Attr, Arg}) ->
- Ctype = ic_cbe:mk_c_type(G, N, Type),
- IsArray = ictype:isArray(G, N, Type),
- IsStruct = ictype:isStruct(G, N, Type),
- IsUnion = ictype:isUnion(G, N, Type),
- Dyn =
- case ic_cbe:is_variable_size(G, N, Type) of
- true ->
- if
- is_record(Type, string) -> "";
- Ctype == "CORBA_char *" -> "";
- is_record(Type, wstring) -> "";
- Ctype == "CORBA_wchar *" -> "";
- true ->
- case IsArray of
- true ->
- "_slice*";
- false ->
- "*"
- end
- end;
- false ->
- if
- Attr == in, Ctype == "erlang_pid" ->
- "*";
- Attr == in, Ctype == "erlang_port" ->
- "*";
- Attr == in, Ctype == "erlang_ref" ->
- "*";
- Attr == in, IsStruct == true ->
- "*";
- Attr == in, IsUnion == true ->
- "*";
- Attr == in, IsArray == true ->
- "_slice*";
- Attr == out, IsArray == true ->
- "_slice";
- true ->
- ""
- end
- end,
- IndOp = mk_ind_op(Attr),
- case {lists:member(types, TypesOrArgs),
- lists:member(args, TypesOrArgs)} of
- {true, true} ->
- Ctype ++ Dyn ++ IndOp ++ " " ++ Arg;
- {true, false} ->
- Ctype ++ Dyn ++ IndOp;
- {false, true} ->
- Arg;
- {false, false} ->
- ""
- end
- end, TypeAttrArgs).
-
-%%------------------------------------------------------------
-%% ENCODER ARG LIST
-%%------------------------------------------------------------
-%%------------------------------------------------------------
-%% Make encoder argument list XXX
-%%------------------------------------------------------------
-mk_arg_list_for_encoder(G, _N, X, Types, Args) ->
- filterzip(
- fun(_, {out, _}) ->
- false;
- (_, {inout, Arg}) ->
- ic_error:error(G, {inout_spec_for_c, X, Arg}),
- false;
- (_Type, {in, Arg}) ->
- {true, Arg}
- end, Types, Args).
-
-%%------------------------------------------------------------
-%% DECODER ARG LIST
-%%------------------------------------------------------------
-%%------------------------------------------------------------
-%% Make decoder argument list XXX
-%%------------------------------------------------------------
-mk_arg_list_for_decoder(G, _N, X, Types, Args) ->
- filterzip(fun(_, {in, _}) ->
- false;
- (_, {inout, Arg}) ->
- ic_error:error(G, {inout_spec_for_c, X, Arg}),
- false;
- (_, {out, Arg}) ->
- {true, Arg}
- end, Types, Args).
-
-%%------------------------------------------------------------
-%% MISC
-%%------------------------------------------------------------
-%%------------------------------------------------------------
-%% Make list of {Type, Attr, Arg}
-%%------------------------------------------------------------
-mk_type_attr_arg_list(Types, Args) ->
- filterzip(fun(Type, {Attr, Arg}) ->
- {true, {Type, Attr, Arg}}
- end, Types, Args).
-
-%%------------------------------------------------------------
-%% Make return type
-%%------------------------------------------------------------
-mk_ret_type(G, N, Type) ->
- Ctype = ic_cbe:mk_c_type(G, N, Type),
- Dyn = case ic_cbe:is_variable_size(G, N, Type) of
- true ->
- if
- is_record(Type, string) ->
- "";
- Ctype == "CORBA_char *" ->
- "";
- is_record(Type, wstring) ->
- "";
- Ctype == "CORBA_wchar *" ->
- "";
- true ->
- case ictype:isArray(G, N, Type) of
- true ->
- "_slice*";
- false ->
- "*"
- end
- end;
- false ->
- case ictype:isArray(G, N, Type) of
- true ->
- "_slice*";
- false ->
- ""
- end
- end,
- Ctype ++ Dyn.
-
-
-%%------------------------------------------------------------
-%% Make indirection operator (to "*" or not to "*").
-%%------------------------------------------------------------
-mk_ind_op(in) ->
- "";
-mk_ind_op(inout) ->
- error;
-mk_ind_op(out) ->
- "*".
-
-%%------------------------------------------------------------
-%% Emit encoding/decoding comment
-%%------------------------------------------------------------
-emit_coding_comment(G, N, Fd, String, RefOrVal, Type, Name) ->
- emit(Fd, " /* ~s parameter: ~s~s ~s */\n",
- [String, ic_cbe:mk_c_type(G, N, Type), RefOrVal, Name]).
-
-%%------------------------------------------------------------
-%% User protocol prefix for generic functions
-%%------------------------------------------------------------
-get_user_proto(G, Default) ->
- case ic_options:get_opt(G, user_protocol) of
- false ->
- Default;
- Pfx ->
- Pfx
- end.
-
-%%------------------------------------------------------------
-%% Timeout. Returns a string (or Default).
-%%------------------------------------------------------------
-get_c_timeout(G, Default) ->
- case ic_options:get_opt(G, c_timeout) of
- Tmo when is_integer(Tmo) ->
- TmoStr = integer_to_list(Tmo),
- {TmoStr, TmoStr};
- {SendTmo, RecvTmo} when is_integer(SendTmo) andalso is_integer(RecvTmo) ->
- {integer_to_list(SendTmo), integer_to_list(RecvTmo)};
- false ->
- Default
- end.
-
-%%------------------------------------------------------------
-%% ZIPPERS (merging of successive elements of two lists).
-%%------------------------------------------------------------
-
-%% zip([H1| T1], [H2| T2]) ->
-%% [{H1, H2}| zip(T1, T2)];
-%% zip([], []) ->
-%% [].
-
-filterzip(F, [H1| T1], [H2| T2]) ->
- case F(H1, H2) of
- false ->
- filterzip(F, T1, T2);
- {true, Val} ->
- [Val| filterzip(F, T1, T2)]
- end;
-filterzip(_, [], []) ->
- [].
-
-
-ifelse(true, A, _) ->
- A;
-ifelse(false, _, B) ->
- B.
diff --git a/lib/ic/src/ic_code.erl b/lib/ic/src/ic_code.erl
deleted file mode 100644
index 98d57db93b..0000000000
--- a/lib/ic/src/ic_code.erl
+++ /dev/null
@@ -1,585 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ic_code).
-
-
--include_lib("ic/src/ic.hrl").
--include_lib("ic/src/icforms.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([get_basetype/2, insert_typedef/3, codeDirective/2]).
--export([gen_includes/3, gen_includes/4, mk_list/1]).
-
--export([type_expand_op/4, type_expand_handle_op/4]).
--export([ type_expand_op_exec/4, type_expand_all/6, type_expand/7]).
-
--export([type_expand_null/3, type_expand_void/3, type_expand_float/3, type_expand_double/3]).
--export([type_expand_short/3, type_expand_ushort/3, type_expand_long/3, type_expand_ulong/3]).
--export([type_expand_longlong/3, type_expand_ulonglong/3]).
--export([type_expand_char/3, type_expand_wchar/3, type_expand_boolean/3]).
--export([type_expand_octet/3, type_expand_any/3, type_expand_wstring/3]).
--export([type_expand_object/3, type_expand_string/3, type_expand_struct/7, type_expand_union/7]).
--export([type_expand_enum/4, type_expand_sequence/7, type_expand_array/7, type_expand_error/3]).
-
--export([type_expand_struct_rule/3, type_expand_union_rule/2, type_expand_enum_rule/4]).
--export([type_expand_enum_elements/3, type_expand_longdouble/3, type_expand_typecode/3]).
--export([type_expand_principal/3, type_expand_exception/7]).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-
-%%-------------------------------------------------------------------------------------
-%%
-%% Trackrecording of generated sequence type structs, thist is just used for C today.
-%%
-%%-------------------------------------------------------------------------------------
-
-get_basetype(G, MyId) ->
- case ?lookup(ic_genobj:typedeftab(G), MyId) of
- [] ->
- MyId;
- X ->
- get_basetype(G, X)
- end.
-
-insert_typedef(_G, "erlang_term", _) ->
- ok;
-insert_typedef(G, MyId, DefinedAsId) ->
- ?insert(ic_genobj:typedeftab(G), MyId, DefinedAsId).
-
-codeDirective(G,X) ->
- case produceCode(X) of
- true ->
- case ic_options:get_opt(G, be) of
- c_genserv ->
- c;
- c_client ->
- c;
- c_server ->
- c_server;
- _ ->
- erlang
- end;
- false ->
- case ic_options:get_opt(G, be) of
- c_genserv ->
- c_no_stub;
- c_client ->
- c_no_stub;
- c_server ->
- c_server_no_stub;
- _ ->
- erlang_no_stub
- end
- end.
-
-%% Checks if X should produce code
-produceCode(X) when is_record(X, module) ->
- case ic_forms:get_body(X) of
- [] ->
- true;
- List ->
- produceModuleCode(List)
- end;
-produceCode(_X) ->
- false.
-
-produceModuleCode([]) ->
- false;
-produceModuleCode([X|_Xs]) when is_record(X, const) ->
- true;
-produceModuleCode([_X|Xs]) ->
- produceModuleCode(Xs).
-
-%% Includes needed c file headers for included idl files
-gen_includes(Fd,G,Type) ->
- case Type of
- c_client ->
- IncludeList =
- ic_pragma:get_included_c_headers(G),
- gen_includes_loop(Fd,IncludeList,Type);
- c_server ->
- IncludeList =
- ic_pragma:get_included_c_headers(G),
- gen_includes_loop(Fd,IncludeList,Type);
- _ ->
- ok
- end,
- ic_codegen:nl(Fd),
- ic_codegen:emit(Fd, "#ifdef __cplusplus\n"),
- ic_codegen:emit(Fd, "extern \"C\" {\n"),
- ic_codegen:emit(Fd, "#endif\n\n").
-
-
-%% Includes needed c file headers for local interfaces
-gen_includes(Fd,G,X,Type) ->
- case Type of
- c_client ->
- IncludeList =
- ic_pragma:get_local_c_headers(G,X),
- gen_includes_loop(Fd,IncludeList,Type);
- c_server ->
- IncludeList =
- ic_pragma:get_local_c_headers(G,X),
- gen_includes_loop(Fd,IncludeList,Type);
- _ ->
- ok
- end,
- ic_codegen:nl(Fd),
- ic_codegen:emit(Fd, "#ifdef __cplusplus\n"),
- ic_codegen:emit(Fd, "extern \"C\" {\n"),
- ic_codegen:emit(Fd, "#endif\n\n").
-
-
-gen_includes_loop(_,[],_) ->
- ok;
-gen_includes_loop(Fd,[I|Is],Type) ->
- L = string:tokens(I,"/"),
- File = lists:last(L),
- case File of
- "erlang" -> % Erlang is NOT generated that way !
- gen_includes_loop(Fd,Is,Type);
- "oe_erlang" -> % Erlang is NOT generated that way !
- gen_includes_loop(Fd,Is,Type);
- _ ->
- case Type of
- c_client ->
- ic_codegen:emit(Fd, "#include \"~s.h\"\n", [File]);
- c_server ->
- ic_codegen:emit(Fd, "#include \"~s__s.h\"\n", [File])
- end,
- gen_includes_loop(Fd,Is,Type)
- end.
-
-
-
-
-%%
-%% Used in NOC only
-%%
-
-
-%%
-%% Type expand on function head comments
-%%
-type_expand_op(G,N,X,Fd) ->
- case catch type_expand_op_exec(G,N,X,Fd) of
- {'EXIT',_Reason} ->
- ic_codegen:nl(Fd),
- ic_codegen:emit(Fd,"%% Error under type expansion, does not affect generated code.~n",[]),
- ic_codegen:emit(Fd,"%%------------------------------------------------------------~n",[]);
- _ ->
- ic_codegen:emit(Fd,"%%------------------------------------------------------------~n",[])
- end.
-
-
-type_expand_op_exec(G,N,X,Fd) ->
- InArgs = ic:filter_params([in,inout], X#op.params),
- OutArgs = ic:filter_params([out,inout], X#op.params),
- ParamNr = length(InArgs)+1,
- Tabs = "",
-
- ic_codegen:nl(Fd),
- ic_codegen:emit(Fd,"%%------------------------------------------------------------~n",[]),
-
- case ic_forms:is_oneway(X) of
- false ->
- ic_codegen:emit(Fd,"%% Operation: ~s/~p~n",[ic_forms:get_id2(X),ParamNr]);
- true ->
- ic_codegen:emit(Fd,"%% Operation: ~s/~p (oneway)~n",[ic_forms:get_id2(X),ParamNr])
- end,
-
- if X#op.raises == [] -> [];
- true ->
- ic_codegen:emit(Fd,"%%~n",[]),
- RaisesList=["%% Raises: " ++
- mk_list(lists:map(fun(E) -> ic_util:to_colon(E) end,
- X#op.raises))],
- ic_codegen:emit(Fd,RaisesList,[]),
- ic_codegen:nl(Fd)
- end,
-
- %% Print argument names
- ic_codegen:emit(Fd,"%%\n",[]),
- InArgNames = ["OE_Ref"]++[ic_util:mk_var(ic_forms:get_id(InArg#param.id)) || InArg <- InArgs ],
- OutArgNames = ["Ret"]++[ic_util:mk_var(ic_forms:get_id(OutArg#param.id)) || OutArg <- OutArgs ],
- case length(InArgNames) > 1 of
- true ->
- ic_codegen:emit(Fd,"%% Input value(s) : ~s~n",[mk_list(InArgNames)]);
- false ->
- ic_codegen:emit(Fd,"%% Input value : ~s~n",[mk_list(InArgNames)])
- end,
- case length(OutArgNames) > 1 of
- true ->
- ic_codegen:emit(Fd,"%% Return value(s) : ~s~n",[mk_list(OutArgNames)]);
- false ->
- ic_codegen:emit(Fd,"%% Return value : ~s~n",[mk_list(OutArgNames)])
- end,
- ic_codegen:emit(Fd,"%%\n",[]),
-
- InArgsTypeList =
- [{ic_util:mk_var(ic_forms:get_id(InArg#param.id)),ic_forms:get_tk(InArg)} || InArg <- InArgs ],
- case InArgsTypeList of
- [] -> %% no input parameters
- ok;
- _ ->
- ic_codegen:emit(Fd,"%% --input-params-~n",[]),
- type_expand_all(G,N,X,Fd,Tabs,InArgsTypeList)
- end,
-
- ReturnTypeList =[{"Ret",X#op.tk}],
- ic_codegen:emit(Fd,"%% --return-value-~n",[]),
- type_expand_all(G,N,X,Fd,Tabs,ReturnTypeList),
-
- OutArgsTypeList =
- [{ic_util:mk_var(ic_forms:get_id(OutArg#param.id)),ic_forms:get_tk(OutArg)} || OutArg <- OutArgs ],
- case OutArgsTypeList of
- [] -> %% no input parameters
- ok;
- _ ->
- ic_codegen:emit(Fd,"%% -output-values-~n",[]),
- type_expand_all(G,N,X,Fd,Tabs,OutArgsTypeList)
- end.
-
-
-
-
-type_expand_handle_op(G,N,X,Fd) ->
- case catch type_expand_handle_op_exec(G,N,X,Fd) of
- {'EXIT',_Reason} ->
- ic_codegen:nl(Fd),
- ic_codegen:emit(Fd,"%% Error under type expansion, does not affect generated code.~n",[]),
- ic_codegen:emit(Fd,"%%------------------------------------------------------------~n",[]);
- _ ->
- ic_codegen:emit(Fd,"%%------------------------------------------------------------~n",[])
- end.
-
-
-type_expand_handle_op_exec(_G,_N,X,Fd) ->
- InArgs = ic:filter_params([in,inout], X#op.params),
- ParamNr = length(InArgs)+1,
-
- ic_codegen:nl(Fd),
- ic_codegen:emit(Fd,"%%------------------------------------------------------------~n",[]),
-
- case ic_forms:is_oneway(X) of
- false ->
- ic_codegen:emit(Fd,"%% Handle operation: handle_call/3~n",[]);
- true ->
- ic_codegen:emit(Fd,"%% Handle operation: handle_cast/3~n",[])
- end,
- ic_codegen:emit(Fd,"%%~n",[]),
- ic_codegen:emit(Fd,"%% Used for operation ~s/~p implementation~n",[ic_forms:get_id2(X),ParamNr]).
-
-
-
-type_expand_all(_G,_N,_X,_Fd,_Tabs,[]) ->
- ok;
-type_expand_all(G,N,X,Fd,Tabs,[{ArgName,Type}|Rest]) ->
- type_expand(G,N,X,Fd,Tabs,ArgName,Type),
- type_expand_all(G,N,X,Fd,Tabs,Rest);
-type_expand_all(G,N,X,Fd,Tabs,[{default,_ArgName,Type}|Rest]) ->
- type_expand(G,N,X,Fd,Tabs,"Def",Type),
- type_expand_all(G,N,X,Fd,Tabs,Rest);
-type_expand_all(G,N,X,Fd,Tabs,[{LabelNr,_ArgName,Type}|Rest]) when is_integer(LabelNr) ->
- type_expand(G,N,X,Fd,Tabs,"V" ++ integer_to_list(LabelNr),Type),
- type_expand_all(G,N,X,Fd,Tabs,Rest);
-type_expand_all(G,N,X,Fd,Tabs,[{Label,_ArgName,Type}|Rest]) ->
- type_expand(G,N,X,Fd,Tabs,Label,Type),
- type_expand_all(G,N,X,Fd,Tabs,Rest).
-
-
-
-type_expand(_G,_N,_X,Fd,Tabs,Name,tk_null) ->
- type_expand_null(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,tk_void) ->
- type_expand_void(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,tk_float) ->
- type_expand_float(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,tk_double) ->
- type_expand_double(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,tk_longdouble) ->
- type_expand_longdouble(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,tk_short) ->
- type_expand_short(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,tk_ushort) ->
- type_expand_ushort(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,tk_long) ->
- type_expand_long(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,tk_longlong) ->
- type_expand_longlong(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,tk_ulong) ->
- type_expand_ulong(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,tk_ulonglong) ->
- type_expand_ulonglong(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,tk_char) ->
- type_expand_char(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,tk_wchar) ->
- type_expand_wchar(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,tk_boolean) ->
- type_expand_boolean(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,tk_octet) ->
- type_expand_octet(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,tk_any) ->
- type_expand_any(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,tk_TypeCode) ->
- type_expand_typecode(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,tk_Principal) ->
- type_expand_principal(Fd,Tabs,Name);
-type_expand(G, N, X,Fd,Tabs,Name, {tk_except, Id, ExcName, ElementList}) ->
- type_expand_exception(G, N, X, Fd,Tabs,Name,
- {tk_except, Id, ExcName, ElementList});
-type_expand(_G,_N,_X,Fd,Tabs,Name,{tk_fixed, _Digits, _Scale}) ->
- type_expand_fixed(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,{tk_objref, _IFRId, _ObjTabs, _ObjName}) ->
- type_expand_object(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,{tk_objref, _IFRId, _ObjName}) ->
- type_expand_object(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,{tk_string, _Length}) ->
- type_expand_string(Fd,Tabs,Name);
-type_expand(_G,_N,_X,Fd,Tabs,Name,{tk_wstring, _Length}) ->
- type_expand_wstring(Fd,Tabs,Name);
-type_expand(G,N,X,Fd,Tabs,Name,{tk_union, IFRId, UnionName, DTC, DNr, LblList}) ->
- type_expand_union(G,N,X,Fd,Tabs,Name,{tk_union, IFRId, UnionName, DTC, DNr, LblList});
-type_expand(_G,_N,_X,Fd,Tabs,Name,{tk_enum, IFRId, EnumName, ElemNameList}) ->
- type_expand_enum(Fd,Tabs,Name,{tk_enum, IFRId, EnumName, ElemNameList});
-type_expand(G,N,X,Fd,Tabs,Name,{tk_sequence, ElemTC, Length}) ->
- type_expand_sequence(G,N,X,Fd,Tabs,Name,{tk_sequence, ElemTC, Length});
-type_expand(G,N,X,Fd,Tabs,Name,{tk_array, ElemTC, Length}) ->
- type_expand_array(G,N,X,Fd,Tabs,Name,{tk_array, ElemTC, Length});
-type_expand(G,N,X,Fd,Tabs,Name,{tk_struct, IFRId, StructName, TcList}) ->
- type_expand_struct(G,N,X,Fd,Tabs,Name,{tk_struct, IFRId, StructName, TcList});
-type_expand(_G,_N,_X,Fd,Tabs,Name,_) ->
- type_expand_error(Fd,Tabs,Name).
-
-
-%% Basic OMG IDL types
-
-type_expand_null(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = null()~n",[Tabs,Name]).
-
-type_expand_void(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = void()~n",[Tabs,Name]).
-
-type_expand_float(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = float()~n",[Tabs,Name]).
-
-type_expand_double(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = double()~n",[Tabs,Name]).
-
-type_expand_longdouble(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = long_double()~n",[Tabs,Name]).
-
-type_expand_short(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = short()~n",[Tabs,Name]).
-
-type_expand_ushort(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = unsigned_Short()~n",[Tabs,Name]).
-
-type_expand_long(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = long()~n",[Tabs,Name]).
-
-type_expand_longlong(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = long_Long()~n",[Tabs,Name]).
-
-type_expand_ulong(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = unsigned_Long()~n",[Tabs,Name]).
-
-type_expand_ulonglong(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = unsigned_Long_Long()~n",[Tabs,Name]).
-
-type_expand_char(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = char()~n",[Tabs,Name]).
-
-type_expand_wchar(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = wchar()~n",[Tabs,Name]).
-
-type_expand_boolean(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = boolean()~n",[Tabs,Name]).
-
-type_expand_octet(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = octet()~n",[Tabs,Name]).
-
-type_expand_any(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = any()~n",[Tabs,Name]).
-
-type_expand_typecode(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = TypeCode()~n",[Tabs,Name]).
-
-type_expand_principal(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = principal()~n",[Tabs,Name]).
-
-
-type_expand_fixed(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = fixed()~n",[Tabs,Name]).
-
-type_expand_object(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = Object_Ref()~n",[Tabs,Name]).
-
-
-%% Constructed OMG IDL types
-
-type_expand_string(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = String()~n",[Tabs,Name]).
-
-type_expand_wstring(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = WString()~n",[Tabs,Name]).
-
-type_expand_exception(G, N, X, Fd, Tabs, Name, {tk_except, Id, ExcName, ElementList}) ->
- ScopedStructName = getScopedName(G, N, ExcName, Id),
- ic_codegen:emit(Fd,"%%~s ~s = ",[Tabs, Name]),
- type_expand_exception_rule(Fd, ScopedStructName, ElementList),
- type_expand_all(G, N, X, Fd, Tabs, ElementList).
-
-type_expand_struct(G,N,X,Fd,Tabs,Name,{tk_struct, IFRId, StructName, TcList}) ->
- ScopedStructName = getScopedName(G,N,StructName,IFRId),
- ic_codegen:emit(Fd,"%%~s ~s = ",[Tabs,Name]),
- type_expand_struct_rule(Fd,ScopedStructName,TcList),
- type_expand_all(G,N,X,Fd,Tabs,TcList).
-
-type_expand_union(G,N,X,Fd,Tabs,Name,{tk_union, IFRId, UnionName, DTC, _DNr, LblList}) ->
- ScopedUnionName = getScopedName(G,N,UnionName,IFRId),
- ic_codegen:emit(Fd,"%%~s ~s = #'~s'{label, value}\n",[Tabs,Name,ScopedUnionName]),
- type_expand(G,N,X,Fd,Tabs,"label",DTC),
- ic_codegen:emit(Fd,"%%~s value = ",[Tabs]),
- type_expand_union_rule(Fd,LblList),
- type_expand_all(G,N,X,Fd,Tabs,LblList).
-
-type_expand_enum(Fd,Tabs,Name,{tk_enum, _IFRId, EnumName, ElemNameList}) ->
- ic_codegen:emit(Fd,"%%~s ~s = ~s~n",[Tabs,Name,EnumName]),
- type_expand_enum_rule(Fd,Tabs,EnumName,ElemNameList).
-
-type_expand_sequence(G,N,X,Fd,Tabs,Name,{tk_sequence, ElemTC, _Length}) ->
- ic_codegen:emit(Fd,"%%~s ~s = [ ~sElem ]~n",[Tabs,Name,Name]),
- type_expand(G,N,X,Fd,Tabs,Name++"Elem",ElemTC).
-
-type_expand_array(G,N,X,Fd,Tabs,Name,{tk_array, ElemTC, _Length}) ->
- ic_codegen:emit(Fd,"%%~s ~s = { ~sElem[,..~sElem] }~n",[Tabs,Name,Name,Name]),
- type_expand(G,N,X,Fd,Tabs,Name++"Elem",ElemTC).
-
-type_expand_error(Fd,Tabs,Name) ->
- ic_codegen:emit(Fd,"%%~s ~s = ????~n",[Tabs,Name]).
-
-
-type_expand_exception_rule(Fd,_Name,[]) ->
- ic_codegen:emit(Fd," ???? ");
-type_expand_exception_rule(Fd,Name,TcList) ->
- ic_codegen:emit(Fd,"#'~s'{",[Name]),
- type_expand_exception_rule(Fd,TcList).
-
-type_expand_exception_rule(Fd,[{Name,_TC}]) ->
- ic_codegen:emit(Fd,"~s}~n",[Name]);
-type_expand_exception_rule(Fd,[{Name,_TC}|Rest]) ->
- ic_codegen:emit(Fd,"~s,",[Name]),
- type_expand_exception_rule(Fd,Rest).
-
-type_expand_struct_rule(Fd,_Name,[]) ->
- ic_codegen:emit(Fd," ???? ");
-type_expand_struct_rule(Fd,Name,TcList) ->
- ic_codegen:emit(Fd,"#'~s'{",[Name]),
- type_expand_struct_rule(Fd,TcList).
-
-type_expand_struct_rule(Fd,[{Name,_TC}]) ->
- ic_codegen:emit(Fd,"~s}~n",[Name]);
-type_expand_struct_rule(Fd,[{Name,_TC}|Rest]) ->
- ic_codegen:emit(Fd,"~s,",[Name]),
- type_expand_struct_rule(Fd,Rest).
-
-
-type_expand_union_rule(Fd,[]) ->
- ic_codegen:emit(Fd," ????");
-type_expand_union_rule(Fd,[{default,_Name,_TC}]) ->
- ic_codegen:emit(Fd,"Def~n",[]);
-type_expand_union_rule(Fd,[{LNr,_Name,_TC}]) when is_integer(LNr)->
- ic_codegen:emit(Fd,"V~p~n",[LNr]);
-type_expand_union_rule(Fd,[{Label,_Name,_TC}]) ->
- ic_codegen:emit(Fd,"~s~n",[Label]);
-type_expand_union_rule(Fd,[{default,_Name,_TC}|Rest]) ->
- ic_codegen:emit(Fd,"Default | "),
- type_expand_union_rule(Fd,Rest);
-type_expand_union_rule(Fd,[{LNr,_Name,_TC}|Rest]) when is_integer(LNr) ->
- ic_codegen:emit(Fd,"V~p | ",[LNr]),
- type_expand_union_rule(Fd,Rest);
-type_expand_union_rule(Fd,[{Label,_Name,_TC}|Rest]) ->
- ic_codegen:emit(Fd,"~s | ",[Label]),
- type_expand_union_rule(Fd,Rest).
-
-
-type_expand_enum_rule(Fd,Tabs,Name,[]) ->
- ic_codegen:emit(Fd,"%%~s ~s = ????",[Tabs,Name]);
-type_expand_enum_rule(Fd,Tabs,Name,ElList) ->
- ic_codegen:emit(Fd,"%%~s ~s = ",[Tabs,Name]),
- type_expand_enum_rule(Fd,ElList).
-
-type_expand_enum_rule(Fd,[ElName]) ->
- ic_codegen:emit(Fd,"'~s' ~n",[ElName]);
-type_expand_enum_rule(Fd,[First|Rest]) ->
- ic_codegen:emit(Fd,"'~s' | ",[First]),
- type_expand_enum_rule(Fd,Rest).
-
-type_expand_enum_elements(_Fd,_Tabs,[]) ->
- ok;
-type_expand_enum_elements(Fd,Tabs,[Elem|Elems]) ->
- ic_codegen:emit(Fd,"%%~s ~s = Atom()~n",[Tabs,Elem]),
- type_expand_enum_elements(Fd,Tabs,Elems).
-
-
-
-%% Returns the right scoped name to be used
-%% along with the expansion comments
-getScopedName(G,N,Name,IfrId) ->
- PTab = ic_genobj:pragmatab(G),
- case ets:match(PTab,{alias,'$0',IfrId}) of
- [] -> %% No Alias - should never happen
- ic_util:to_undersc(ic_pragma:mk_scope(IfrId));
- [[[_S|N]]] -> %% An alias
- ic_util:to_undersc([Name|N]);
- [[[S|FoundScope]]] -> %% Maybe inherited
- case ic_pragma:is_inherited_by(FoundScope,N,PTab) of
- false -> %% Not inherited
- ic_util:to_undersc([S|FoundScope]);
- true -> %% inherited
- ic_util:to_undersc([Name|N])
- end
- end.
-
-
-%% mk_list produces a nice comma separated
-%% string of variable names
-mk_list([]) -> [];
-mk_list([Arg | Args]) ->
- Arg ++ mk_list2(Args).
-mk_list2([Arg | Args]) ->
- ", " ++ Arg ++ mk_list2(Args);
-mk_list2([]) -> [].
-
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-
-
-
diff --git a/lib/ic/src/ic_codegen.erl b/lib/ic/src/ic_codegen.erl
deleted file mode 100644
index a3f141f606..0000000000
--- a/lib/ic/src/ic_codegen.erl
+++ /dev/null
@@ -1,423 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ic_codegen).
-
--include_lib("ic/src/ic.hrl").
--include_lib("ic/src/icforms.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([emit/2, emit/3]).
--export([emit_c_enc_rpt/4, emit_c_dec_rpt/4]).
--export([comment/2, comment/3, comment/4, comment_inlined/5, comment_prefixed/4]).
--export([mcomment/2, mcomment/3, mcomment_inlined/5, mcomment_prefixed/3]).
--export([mcomment_light/2, mcomment_light/3, mcomment_light_inlined/5, mcomment_light_prefixed/3]).
--export([nl/1, export/2]).
--export([record/5]).
--export([emit_stub_head/4, emit_hrl_head/4, emit_hrl_foot/2]).
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-
-%%--------------------------------------------------------------------
-%% Emit output as a formatted string, (old emit)
-%%--------------------------------------------------------------------
-emit(nil, _) -> ok;
-emit(Fd, Str) ->
- file:write(Fd, Str).
-
-emit(nil, _, _) -> ok;
-emit(Fd, Fmt, Args) ->
- file:write(Fd, io_lib:format(Fmt, Args)).
-
-emit_c_enc_rpt(Fd, Prefix, Fmt, Args) ->
- emit(Fd, Prefix ++ "OE_RPT_ERR(\"Encode error: " ++ Fmt ++ "\");\n", Args).
-
-emit_c_dec_rpt(Fd, Prefix, Fmt, Args) ->
- emit(Fd, Prefix ++ "OE_RPT_ERR(\"Decode error: " ++ Fmt ++ "\");\n", Args).
-
-%%--------------------------------------------------------------------
-%% Emit comments
-%%--------------------------------------------------------------------
-comment(Fd, C) ->
- comment_prefixed(Fd, C, [], "%%").
-
-comment(Fd, C, A) ->
- comment_prefixed(Fd, C, A, "%%").
-
-comment(Fd, C, A, c) ->
- comment_inlined(Fd, C, A, "/*", "*/");
-comment(Fd, C, A, erl) ->
- comment_prefixed(Fd, C, A, "%%");
-comment(Fd, C, A, java) ->
- comment_prefixed(Fd, C, A, "//");
-%% Should be removed after a check if it's used !!!!! (LTH)
-comment(Fd, C, A, CommentSequence) when is_list(CommentSequence) ->
- comment_prefixed(Fd, C, A, CommentSequence).
-
-comment_inlined(Fd, C, A, Start, End) ->
- emit(Fd, Start ++ " " ++ C ++ " " ++ End ++"\n", A).
-
-comment_prefixed(Fd, C, A, Prefix) ->
- emit(Fd, Prefix ++ " " ++ C ++ "\n", A).
-
-%%--------------------------------------------------------------------
-%% Emit multiline comments with nice delimiters
-%%--------------------------------------------------------------------
-mcomment(Fd, List) ->
- mcomment_prefixed(Fd, List, "%%").
-
-mcomment(Fd, List, c) ->
- mcomment_inlined(Fd, List, "/*", "*/", " *");
-mcomment(Fd, List, erl) ->
- mcomment_prefixed(Fd, List, "%%");
-mcomment(Fd, List, java) ->
- mcomment_prefixed(Fd, List, "//").
-
-mcomment_inlined(Fd, List, Start, End, Intermediate) ->
- emit(Fd, Start ++
- "------------------------------------------------------------\n"),
- emit(Fd, Intermediate ++ "\n"),
- lists:foreach(fun(C) -> comment(Fd, C, [], Intermediate) end, List),
- emit(Fd, Intermediate ++ "\n"),
- emit(Fd, Intermediate ++
- "------------------------------------------------------------" ++ End ++ "\n"),
- ok.
-mcomment_prefixed(Fd, List, Prefix) ->
- emit(Fd, Prefix ++
- "------------------------------------------------------------\n"),
- emit(Fd, Prefix ++ "\n"),
- lists:foreach(fun(C) -> comment(Fd, C, [], Prefix) end, List),
- emit(Fd, Prefix ++ "\n"),
- emit(Fd, Prefix ++
- "------------------------------------------------------------\n"),
- ok.
-
-
-%%--------------------------------------------------------------------
-%% Emit multiline comments with nice delimiters as above but a
-%% little lighter
-%%--------------------------------------------------------------------
-mcomment_light(Fd, List) ->
- mcomment_light_prefixed(Fd, List, "%%").
-
-mcomment_light(Fd, List, c) ->
- mcomment_light_inlined(Fd, List, "/*", " */", " *");
-mcomment_light(Fd, List, erl) ->
- mcomment_light_prefixed(Fd, List, "%%");
-mcomment_light(Fd, List, java) ->
- mcomment_light_prefixed(Fd, List, "//");
-%% Should be removed after a check if it's used !!!!! (LTH)
-mcomment_light(Fd, List, Prefix) when is_list(Prefix) ->
- mcomment_light_prefixed(Fd, List, Prefix).
-
-mcomment_light_inlined(Fd, List, Start, End, Intermediate) ->
- emit(Fd, "\n" ++ Start ++ "\n"),
- lists:foreach(fun(C) -> comment(Fd, C, [], Intermediate) end, List),
- emit(Fd, End ++ "\n"),
- ok.
-
-mcomment_light_prefixed(Fd, List, Prefix) ->
- emit(Fd, Prefix),
- lists:foreach(fun(C) -> comment(Fd, C, [], Prefix) end, List),
- emit(Fd, Prefix ++ "\n"),
- ok.
-
-%%--------------------------------------------------------------------
-%% New line
-%%--------------------------------------------------------------------
-nl(Fd) ->
- emit(Fd, "\n").
-
-
-%%--------------------------------------------------------------------
--define(IFRIDFIELD(G), ic_util:mk_name(G, "ID")).
-
-%%--------------------------------------------------------------------
-%% Emit record definitions for erlang
-%%--------------------------------------------------------------------
-record(G, X, Name, _IFRID, Recs) when is_record(X, struct) ->
- F = ic_genobj:hrlfiled(G),
- emit(F, "-record(~p, {~p", [ic_util:to_atom(Name),hd(Recs)]),
- lists:foreach(fun(Y) -> emit(F, ", ~p", [Y]) end, tl(Recs)),
- emit(F, "}).\n");
-record(G, X, Name, _IFRID, _Recs) when is_record(X, union) ->
- F = ic_genobj:hrlfiled(G),
- emit(F, "-record(~p, {label, value}).\n",[ic_util:to_atom(Name)]);
-record(G, _X, Name, IFRID, Recs) when length(Recs) > 3 ->
- F = ic_genobj:hrlfiled(G),
- emit(F, "-record(~p,~n {~p=~p",
- [ic_util:to_atom(Name), ic_util:to_atom(?IFRIDFIELD(G)), IFRID]),
- rec2(F, "", ", ", Recs),
- emit(F, "}).\n");
-record(G, _X, Name, IFRID, Recs) ->
- F = ic_genobj:hrlfiled(G),
- emit(F, "-record(~p, {~p=~p", [ic_util:to_atom(Name),
- ic_util:to_atom(?IFRIDFIELD(G)),
- IFRID]),
- lists:foreach(fun(Y) -> emit(F, ", ~p", [Y]) end, Recs),
- emit(F, "}).\n").
-
-
-rec2(F, Align, Delim, [M1 , M2, M3 | Ms]) ->
- emit(F, "~s~s~p, ~p, ~p", [Delim, Align, M1, M2, M3]),
- rec2(F, " ", ",\n", Ms);
-rec2(F, Align, Delim, [M1 , M2]) ->
- emit(F, "~s~s~p, ~p", [Delim, Align, M1, M2]);
-rec2(F, Align, Delim, [M]) ->
- emit(F, "~s~s~p", [Delim, Align, M]);
-rec2(_F, _Align, _Delim, []) ->
- ok.
-
-
-%%--------------------------------------------------------------------
-%% Emit export lists for erlang
-%%--------------------------------------------------------------------
-export(F, [E1, E2, E3 | Exports]) ->
- emit(F, "-export([~s]).\n", [exp_list([E1, E2, E3])]),
- export(F, Exports);
-export(_F, []) -> ok;
-export(F, Exports) ->
- emit(F, "-export([~s]).\n", [exp_list(Exports)]).
-
-exp_list([E1 | L]) ->
- exp_to_string(E1) ++
- lists:map(fun(E) -> ", " ++ exp_to_string(E) end, L).
-
-
-exp_to_string({F,N}) -> io_lib:format("~p/~p", [ic_util:to_atom(F), N]).
-
-
-%%--------------------------------------------------------------------
-%% Emit Stub file header
-%%--------------------------------------------------------------------
-emit_stub_head(_G, ignore, _Name, _) -> ignore;
-emit_stub_head(G, F1, Name, erlang) ->
- comment(F1, " coding: latin-1", []),
- mcomment(F1, stub_header(G, Name)),
- nl(F1),
- emit(F1, "-module(~p).\n", [list_to_atom(Name)]),
- emit(F1, "-ic_compiled(~p).\n", [compiler_vsn(?COMPILERVSN)]),
- emit(F1, "\n\n"), F1;
-emit_stub_head(G, F1, Name, erlang_template) ->
- comment(F1, " coding: latin-1", []),
- ic_erl_template:emit_header(G, F1, Name),
- F1;
-emit_stub_head(_G, F1, _Name, erlang_template_no_gen) ->
- F1;
-emit_stub_head(G, F1, Name, c) ->
- mcomment(F1, stub_header(G, Name), c),
- emit(F1, "int ic_compiled_~s_~s;\n", [compiler_vsn(?COMPILERVSN), Name]),
- emit(F1, "\n\n"), F1;
-emit_stub_head(G, F1, Name, c_server) ->
- CSName = [Name, "__s"],
- mcomment(F1, stub_header(G, CSName), c),
- emit(F1, "int ic_compiled_~s_~s;\n", [compiler_vsn(?COMPILERVSN), CSName]),
- emit(F1, "\n\n"), F1;
-emit_stub_head(G, F1, Name, java) ->
- mcomment(F1, stub_header(G, Name), java),
- emit(F1, "\n\n"), F1.
-
-stub_header(G, Name) ->
- ["Implementation stub file",
- "",
- io_lib:format("Target: ~ts", [Name]),
- io_lib:format("Source: ~ts", [ic_genobj:idlfile(G)]),
- io_lib:format("IC vsn: ~s", [?COMPILERVSN]),
- "",
- "This file is automatically generated. DO NOT EDIT IT."].
-
-compiler_vsn(Vsn) ->
- lists:map(fun($.) -> $_;
- (C) -> C
- end, Vsn).
-
-%%--------------------------------------------------------------------
-%% Emit include file header
-%%--------------------------------------------------------------------
-%% Name is Fully scoped (undescore) name of interface or module
-emit_hrl_head(_G, ignore, _Name, _) -> ignore;
-emit_hrl_head(G, Fd, Name, erlang) ->
- comment(Fd, " coding: latin-1", []),
- mcomment(Fd, ["Erlang header file" |
- hrl_header(G, Name)]),
- nl(Fd),
- nl(Fd),
- IfdefName = ic_util:to_uppercase(Name++"_HRL"),
- emit(Fd, "-ifndef(~s).~n", [IfdefName]),
- emit(Fd, "-define(~s, true).~n", [IfdefName]),
- nl(Fd),
- nl(Fd),
- Fd;
-emit_hrl_head(G, Fd, Name, c) ->
- mcomment(Fd, ["C header file" |
- hrl_header(G, Name)], c),
- nl(Fd),
- nl(Fd),
- IfdefName = ic_util:to_uppercase(Name++"_H"),
- emit(Fd, "#ifndef ~s~n", [IfdefName]),
- emit(Fd, "#define ~s ~n", [IfdefName]),
- nl(Fd),
- nl(Fd),
- Fd;
-emit_hrl_head(G, Fd, Name, c_server) ->
- mcomment(Fd, ["C header file" |
- hrl_header(G, [Name, "__s"])], c),
- nl(Fd),
- nl(Fd),
- IfdefName = ic_util:to_uppercase(Name++"__S_H"),
- emit(Fd, "#ifndef ~s~n", [IfdefName]),
- emit(Fd, "#define ~s ~n", [IfdefName]),
- nl(Fd),
- nl(Fd),
- Fd.
-
-hrl_header(G, Name) ->
- ["",
- io_lib:format("Target: ~ts", [Name]),
- io_lib:format("Source: ~ts", [ic_genobj:idlfile(G)]),
- io_lib:format("IC vsn: ~s", [?COMPILERVSN]),
- "",
- "This file is automatically generated. DO NOT EDIT IT."].
-
-
-
-
-%%--------------------------------------------------------------------
-%% Emit include file footer
-%%--------------------------------------------------------------------
-emit_hrl_foot(_G, erlang_template) ->
- ok;
-emit_hrl_foot(_G, erlang_template_no_gen) ->
- ok;
-emit_hrl_foot(G, erlang) ->
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- Fd = ic_genobj:hrlfiled(G),
- nl(Fd),
- nl(Fd),
- emit(Fd, "-endif.\n"),
- nl(Fd),
- nl(Fd),
- Fd;
- false ->
- ok
- end;
-emit_hrl_foot(G, erlang_no_stub) ->
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- Fd = ic_genobj:hrlfiled(G),
- nl(Fd),
- nl(Fd),
- emit(Fd, "-endif.\n"),
- nl(Fd),
- nl(Fd),
- Fd;
- false ->
- ok
- end;
-emit_hrl_foot(G, c) ->
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- Fd = ic_genobj:hrlfiled(G),
- nl(Fd),
- nl(Fd),
- emit(Fd, "#ifdef __cplusplus\n"),
- emit(Fd, "}\n"),
- emit(Fd, "#endif\n"),
- nl(Fd),
- emit(Fd, "#endif\n"),
- nl(Fd),
- nl(Fd),
- Fd;
- false ->
- ok
- end;
-emit_hrl_foot(G, c_server) ->
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- Fd = ic_genobj:hrlfiled(G),
- nl(Fd),
- nl(Fd),
- emit(Fd, "#ifdef __cplusplus\n"),
- emit(Fd, "}\n"),
- emit(Fd, "#endif\n"),
- nl(Fd),
- emit(Fd, "#endif\n"),
- nl(Fd),
- nl(Fd),
- Fd;
- false ->
- ok
- end;
-emit_hrl_foot(G, c_no_stub) ->
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- Fd = ic_genobj:hrlfiled(G),
- nl(Fd),
- nl(Fd),
- emit(Fd, "#ifdef __cplusplus\n"),
- emit(Fd, "}\n"),
- emit(Fd, "#endif\n"),
- nl(Fd),
- emit(Fd, "#endif\n"),
- nl(Fd),
- nl(Fd),
- Fd;
- false ->
- ok
- end;
-emit_hrl_foot(G, c_server_no_stub) ->
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- Fd = ic_genobj:hrlfiled(G),
- nl(Fd),
- nl(Fd),
- emit(Fd, "#ifdef __cplusplus\n"),
- emit(Fd, "}\n"),
- emit(Fd, "#endif\n"),
- nl(Fd),
- emit(Fd, "#endif\n"),
- nl(Fd),
- nl(Fd),
- Fd;
- false ->
- ok
- end.
-
-
-
-
-
-
-
-
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
diff --git a/lib/ic/src/ic_constant_java.erl b/lib/ic/src/ic_constant_java.erl
deleted file mode 100644
index 49150f96ac..0000000000
--- a/lib/ic/src/ic_constant_java.erl
+++ /dev/null
@@ -1,100 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(ic_constant_java).
-
-
--include("icforms.hrl").
--include("ic.hrl").
--include("ic_debug.hrl").
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([gen/3]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% Func: gen/3
-%%-----------------------------------------------------------------
-gen(G, N, X) when is_record(X, const) ->
- ConstantName = ic_forms:get_java_id(X),
- case inInterface(G, N) of
- true ->
- emit_constant(G, N, X, ConstantName);
- false ->
- emit_constant_interface(G, N, X, ConstantName)
- end;
-gen(_G, _N, _X) ->
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% Func: emit_constant/4
-%%-----------------------------------------------------------------
-emit_constant(G, N, X, ConstantName) ->
- Fd = ic_genobj:interfacefiled(G),
- %%?PRINTDEBUG2("~p", [Fd]),
- Type = ic_java_type:getType(G, N, ic_forms:get_type(X)),
- ic_codegen:emit(Fd, " public static final ~s ~s = (~s) ~p;\n",
- [Type, ConstantName, Type, X#const.val]),
- ic_codegen:nl(Fd).
-
-%%-----------------------------------------------------------------
-%% Func: emit_constant_interface/4
-%%-----------------------------------------------------------------
-emit_constant_interface(G, N, X, ConstantName) ->
- {Fd, _} = ic_file:open_java_file(G, N, ConstantName),
-
- ic_codegen:emit(Fd, "final public class ~s {\n",[ConstantName]),
-
- Type = ic_java_type:getType(G, N, ic_forms:get_type(X)),
- ic_codegen:emit(Fd, " public static final ~s value = (~s) ~p;\n",
- [Type, Type, X#const.val]),
- ic_codegen:emit(Fd, "}\n", []),
- file:close(Fd).
-
-%%-----------------------------------------------------------------
-%% Func: emit_constant_interface/4
-%%-----------------------------------------------------------------
-inInterface(_G, []) -> % Global constant
- false;
-inInterface(G, N) ->
- [N1 |Ns] = N,
- {_FullScopedName, T, _TK, _} =
- ic_symtab:get_full_scoped_name(G, Ns, ic_symtab:scoped_id_new(N1)),
- case T of
- interface -> % Constant declare in an interface
- true;
- _ -> % Constant declared in a module
- false
- end.
-
diff --git a/lib/ic/src/ic_cserver.erl b/lib/ic/src/ic_cserver.erl
deleted file mode 100644
index 7c7506367e..0000000000
--- a/lib/ic/src/ic_cserver.erl
+++ /dev/null
@@ -1,2420 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(ic_cserver).
-
-%% This module implements generation of C server code, where the
-%% server acts as an Erlang C-node, where the functionality is that of
-%% a gen_server (in C), and where the communication thus is according
-%% to the Erlang distribution protocol.
-%%
-
--export([do_gen/3]).
-
-%% Silly dialyzer.
--export([filterzip/3]).
-
-%%------------------------------------------------------------
-%%
-%% Internal stuff
-%%
-%%------------------------------------------------------------
-
--import(lists, [foreach/2, foldl/3, foldr/3, map/2]).
--import(ic_codegen, [emit/2, emit/3, emit/4, emit_c_enc_rpt/4, emit_c_dec_rpt/4]).
-
--include("icforms.hrl").
--include("ic.hrl").
--include_lib("stdlib/include/erl_compile.hrl").
-
--define(IC_HEADER, "ic.h").
--define(ERL_INTERFACEHEADER, "erl_interface.h").
--define(EICONVHEADER, "ei.h").
--define(OE_MSGBUFSIZE, "OE_MSGBUFSIZE").
--define(ERLANGATOMLENGTH, "256").
-
-%%------------------------------------------------------------
-%%
-%% Entry point
-%%
-%%------------------------------------------------------------
-do_gen(G, File, Form) ->
- OeName = ic_util:mk_oe_name(G, remove_ext(ic_util:to_list(File))),
- G2 = ic_file:filename_push(G, [], OeName, c_server),
- gen_headers(G2, [], Form),
- R = gen(G2, [], Form),
- ic_file:filename_pop(G2, c),
- R.
-
-remove_ext(File) ->
- filename:rootname(filename:basename(File)).
-
-%%------------------------------------------------------------
-%%
-%% Generate the server side C stub and header files.
-%%
-%% For each module a separate file is generated.
-%%
-%%
-%%------------------------------------------------------------
-
-gen(G, N, [X| Xs]) when is_record(X, preproc) ->
- NewG = change_file_stack(G, N, X#preproc.cat, X),
- gen(NewG, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, module) ->
- CD = ic_code:codeDirective(G, X),
- G2 = ic_file:filename_push(G, N, X, CD),
- N2 = [ic_forms:get_id2(X)| N],
- gen_headers(G2, N2, X),
- gen(G2, N2, ic_forms:get_body(X)),
- G3 = ic_file:filename_pop(G2, CD),
- gen(G3, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, interface) ->
- G2 = ic_file:filename_push(G, N, X, c_server),
- N2 = [ic_forms:get_id2(X)| N],
- gen_prototypes(G2, N2, X),
- gen_serv(G2, N2, X),
- G3 = ic_file:filename_pop(G2, c),
- gen(G3, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, const) ->
- emit_constant(G, N, X),
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, op) ->
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, attr) ->
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, except) ->
- icstruct:except_gen(G, N, X, c),
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, enum) ->
- icenum:enum_gen(G, N, X, c),
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, typedef) ->
- icstruct:struct_gen(G, N, X, c),
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, struct) ->
- icstruct:struct_gen(G, N, X, c),
- gen(G, N, Xs);
-
-gen(G, N, [X| Xs]) when is_record(X, union) ->
- icstruct:struct_gen(G, N, X, c),
- gen(G, N, Xs);
-
-gen(G, N, [_| Xs]) ->
- gen(G, N, Xs);
-
-gen(_G, _N, []) ->
- ok.
-
-%%------------------------------------------------------------
-%% Change file stack
-%%------------------------------------------------------------
-
-change_file_stack(G, _N, line_nr, X) ->
- Id = ic_forms:get_id2(X),
- Flags = X#preproc.aux,
- case Flags of
- [] -> ic_genobj:push_file(G, Id);
- _ ->
- foldr(
- fun({_, _, "1"}, G1) -> ic_genobj:push_file(G1, Id);
- ({_, _, "2"}, G1) -> ic_genobj:pop_file(G1, Id);
- ({_, _, "3"}, G1) -> ic_genobj:sys_file(G1, Id)
- end, G, Flags)
- end;
-change_file_stack(G, _N, _Other, _X) ->
- G.
-
-%%------------------------------------------------------------
-%% Generate headers
-%%------------------------------------------------------------
-
-%% Some items have extra includes
-gen_headers(G, N, X) when is_record(X, module) ->
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- HFd = ic_genobj:hrlfiled(G),
- IncludeFileStack = ic_genobj:include_file_stack(G),
- Filename = lists:nth(length(N) + 1, IncludeFileStack),
- emit(HFd, "#include \"~s\"\n", [filename:basename(Filename)]),
- ic_code:gen_includes(HFd, G, X, c_server);
- false -> ok
- end;
-gen_headers(G, [], _X) ->
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- HFd = ic_genobj:hrlfiled(G),
- emit(HFd, "#include <stdlib.h>\n"),
- case ic_options:get_opt(G, c_report) of
- true ->
- emit(HFd, "#ifndef OE_C_REPORT\n"),
- emit(HFd, "#define OE_C_REPORT\n"),
- emit(HFd, "#include <stdio.h>\n"),
- emit(HFd, "#endif\n");
- _ ->
- ok
- end,
- emit(HFd, "#include \"~s\"\n", [?IC_HEADER]),
- emit(HFd, "#include \"~s\"\n", [?ERL_INTERFACEHEADER]),
- emit(HFd, "#include \"~s\"\n", [?EICONVHEADER]),
- ic_code:gen_includes(HFd, G, c_server);
- false -> ok
- end;
-gen_headers(_G, _N, _X) ->
- ok.
-
-%%------------------------------------------------------------
-%% Generate prototypes
-%%------------------------------------------------------------
-
-gen_prototypes(G, N, X) ->
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- HFd = ic_genobj:hrlfiled(G),
- IncludeFileStack = ic_genobj:include_file_stack(G),
- L = length(N),
- Filename =
- if
- L < 2 ->
- lists:nth(L + 1, IncludeFileStack);
- true ->
- lists:nth(2, IncludeFileStack)
- end,
-
- IName = ic_util:to_undersc(N),
- INameUC = ic_util:to_uppercase(IName),
-
- emit(HFd, "#include \"~s\"\n", [filename:basename(Filename)]),
- ic_code:gen_includes(HFd, G, X, c_server),
- ic_codegen:nl(HFd),
-
- emit(HFd, "\n#ifndef __~s__\n", [ic_util:to_uppercase(IName)]),
- emit(HFd, "#define __~s__\n", [ic_util:to_uppercase(IName)]),
- ic_codegen:mcomment_light(HFd,
- [io_lib:format("Interface "
- "object "
- "definition: ~s",
- [IName])], c),
- case get_c_timeout(G, "") of
- "" ->
- ok;
- {SendTmo, RecvTmo} ->
- emit(HFd, "#define OE_~s_SEND_TIMEOUT ~s\n",
- [INameUC, SendTmo]),
- emit(HFd, "#define OE_~s_RECV_TIMEOUT ~s\n",
- [INameUC, RecvTmo]),
- emit(HFd, "#ifndef EI_HAVE_TIMEOUT\n"),
- emit(HFd, "#error Functions for send and receive with "
- "timeout not defined in erl_interface\n"),
- emit(HFd, "#endif\n\n")
- end,
-
- emit(HFd, "typedef CORBA_Object ~s;\n\n", [IName]),
- emit(HFd, "#endif\n\n"),
-
- Bodies = [{N, ic_forms:get_body(X)}| X#interface.inherit_body],
-
- emit(HFd, "\n/* Structure definitions */\n", []),
- foreach(fun({N2, Body}) ->
- emit_structs_inside_module(G, HFd, N2, Body) end,
- Bodies),
-
- emit(HFd, "\n/* Switch and exec functions */\n", []),
- emit(HFd, "int ~s__switch(~s oe_obj, CORBA_Environment "
- "*oe_env);\n", [IName, IName]),
- foreach(fun({_N2, Body}) ->
- emit_exec_prototypes(G, HFd, N, Body) end,
- Bodies),
-
- emit(HFd, "\n/* Generic decoder */\n", []),
- emit(HFd, "int ~s__call_info(~s oe_obj, CORBA_Environment "
- "*oe_env);\n", [IName, IName]),
-
- emit(HFd, "\n/* Restore function typedefs */\n", []),
- foreach(fun({_N2, Body}) ->
- emit_restore_typedefs(G, HFd, N, Body) end,
- Bodies),
-
- emit(HFd, "\n/* Callback functions */\n", []),
- foreach(fun({_N2, Body}) ->
- emit_callback_prototypes(G, HFd, N, Body) end,
- Bodies),
-
- emit(HFd, "\n/* Parameter decoders */\n", []),
- foreach(fun({_N2, Body}) ->
- emit_decoder_prototypes(G, HFd, N, Body) end,
- Bodies),
-
- emit(HFd, "\n/* Message encoders */\n", []),
- foreach(fun({_N2, Body}) ->
- emit_encoder_prototypes(G, HFd, N, Body) end,
- Bodies),
-
- %% Emit operation mapping structures
- emit_operation_mapping_declaration(G, HFd, N, Bodies),
-
- ok;
-
- false ->
- ok
- end.
-
-%%------------------------------------------------------------
-%% Generate the server encoding/decoding function
-%%------------------------------------------------------------
-
-
-gen_serv(G, N, X) ->
- case ic_genobj:is_stubfile_open(G) of
- true ->
- Fd = ic_genobj:stubfiled(G),
-
- emit_switch(G, Fd, N, X),
- emit_server_generic_decoding(G, Fd, N),
-
- %% Sets the temporary variable counter.
- put(op_variable_count, 0),
- put(tmp_declarations, []),
-
- %% Generate exec, decode and encoding functions, and
- %% table of exec functions.
- Bodies = [{N, ic_forms:get_body(X)}|
- X#interface.inherit_body],
-
- foreach(fun({_N2, Body}) ->
- emit_dispatch(G, Fd, N, Body) end,
- Bodies),
- emit_operation_mapping(G, Fd, N, Bodies);
- false ->
- ok
- end.
-
-%%------------------------------------------------------------
-%% Emit structs inside module
-%%------------------------------------------------------------
-
-emit_structs_inside_module(G, _Fd, N, Xs)->
- lists:foreach(
- fun(X) when is_record(X, enum) ->
- icenum:enum_gen(G, N, X, c);
- (X) when is_record(X, typedef) ->
- icstruct:struct_gen(G, N, X, c);
- (X) when is_record(X, struct) ->
- icstruct:struct_gen(G, N, X, c);
- (X) when is_record(X, union) ->
- icstruct:struct_gen(G, N, X, c);
- (_) ->
- ok
- end, Xs).
-
-%%------------------------------------------------------------
-%% Emit exec prototypes
-%%------------------------------------------------------------
-
-emit_exec_prototypes(G, Fd, N, Xs) ->
- lists:foreach(
- fun(X) when is_record(X, op) ->
- {ScopedName, _, _} = ic_cbe:extract_info(G, N, X),
- emit(Fd,
- "int ~s__exec(~s oe_obj, CORBA_Environment *oe_env);\n",
- [ScopedName, ic_util:to_undersc(N)]);
- (X) when is_record(X, const) ->
- emit_constant(G, N, X);
- (_) ->
- ok
- end, Xs).
-
-%%------------------------------------------------------------
-%% Emit restore typedefs
-%%------------------------------------------------------------
-
-emit_restore_typedefs(G, Fd, N, [X| Xs]) when is_record(X, op) ->
- %% Check if to use scoped call names
- {ScopedName, ArgNames, Types} = ic_cbe:extract_info(G, N, X),
- {RetType, ParTypes, _} = Types,
- TypeAttrArgs = mk_type_attr_arg_list(ParTypes, ArgNames),
- RT = mk_c_ret_type(G, N, RetType),
-
- PL = ic_util:mk_list(mk_par_list_for_callback_prototypes(G, N, X,
- TypeAttrArgs)),
- RPL = case PL of
- "" ->
- "";
- _PL ->
- ", " ++ PL
- end,
-
- case RT of
- "void" ->
- case PL of
- "" ->
- emit(Fd, "typedef void (*~s__rs(~s oe_obj, "
- "CORBA_Environment *oe_env));\n",
- [ScopedName, ic_util:to_undersc(N)]);
- _ ->
- emit(Fd, "typedef void (*~s__rs(~s oe_obj, ~s, "
- "CORBA_Environment *oe_env));\n",
- [ScopedName, ic_util:to_undersc(N), PL])
- end;
-
- "erlang_port*" ->
- emit(Fd, "typedef void (*~s__rs(~s oe_obj, ~s~s, "
- "CORBA_Environment *oe_env));\n",
- [ScopedName, ic_util:to_undersc(N), RT, RPL]);
-
- "erlang_pid*" ->
- emit(Fd, "typedef void (*~s__rs(~s oe_obj, ~s~s, "
- "CORBA_Environment *oe_env));\n",
- [ScopedName, ic_util:to_undersc(N), RT, RPL]);
-
- "erlang_ref*" ->
- emit(Fd, "typedef void (*~s__rs(~s oe_obj, ~s~s, "
- "CORBA_Environment *oe_env));\n",
- [ScopedName, ic_util:to_undersc(N), RT, RPL]);
-
- _ ->
- case ictype:isArray(G, N, RetType) of
- true ->
- emit(Fd, "typedef void (*~s__rs(~s oe_obj, ~s~s, "
- "CORBA_Environment *oe_env));\n",
- [ScopedName, ic_util:to_undersc(N), RT, RPL]);
- false ->
- emit(Fd, "typedef void (*~s__rs(~s oe_obj, ~s*~s, "
- "CORBA_Environment *oe_env));\n",
- [ScopedName, ic_util:to_undersc(N), RT, RPL])
- end
- end,
- emit_restore_typedefs(G, Fd, N, Xs);
-emit_restore_typedefs(G, Fd, N, [X| Xs]) when is_record(X, attr) ->
- emit_restore_typedefs(G, Fd, N, Xs);
-emit_restore_typedefs(G, Fd, N, [_X| Xs]) ->
- emit_restore_typedefs(G, Fd, N, Xs);
-emit_restore_typedefs(_G, _Fd, _N, []) -> ok.
-
-
-%%------------------------------------------------------------
-%% Emit call-back prototypes
-%%------------------------------------------------------------
-
-emit_callback_prototypes(G, Fd, N, [X| Xs]) when is_record(X, op) ->
- %% Check scoped names XXX
- {ScopedName, ArgNames, Types} = ic_cbe:extract_info(G, N, X),
- {RetType, ParTypes, _} = Types,
- TypeAttrArgs = mk_type_attr_arg_list(ParTypes, ArgNames),
- RT = mk_c_ret_type(G, N, RetType),
-
- PL = ic_util:mk_list(mk_par_list_for_callback_prototypes(G, N, X,
- TypeAttrArgs)),
- CBPL = case PL of
- "" ->
- "";
- _PL ->
- ", " ++ PL
- end,
- case RT of
- "void" ->
- case PL of
- "" ->
- emit(Fd, "~s__rs* ~s__cb(~s oe_obj, "
- "CORBA_Environment *oe_env);\n",
- [ScopedName, ScopedName, ic_util:to_undersc(N)]);
- _ ->
- emit(Fd, "~s__rs* ~s__cb(~s oe_obj, ~s, "
- "CORBA_Environment *oe_env);\n",
- [ScopedName, ScopedName, ic_util:to_undersc(N), PL])
- end;
- "erlang_port*" ->
- emit(Fd, "~s__rs* ~s__cb(~s oe_obj, ~s~s, "
- "CORBA_Environment *oe_env);\n",
- [ScopedName, ScopedName, ic_util:to_undersc(N), RT, CBPL]);
-
- "erlang_pid*" ->
- emit(Fd, "~s__rs* ~s__cb(~s oe_obj, ~s~s, "
- "CORBA_Environment *oe_env);\n",
- [ScopedName, ScopedName, ic_util:to_undersc(N), RT, CBPL]);
-
- "erlang_ref*" ->
- emit(Fd, "~s__rs* ~s__cb(~s oe_obj, ~s~s, "
- "CORBA_Environment *oe_env);\n",
- [ScopedName, ScopedName, ic_util:to_undersc(N), RT, CBPL]);
-
- _ ->
- case ictype:isArray(G, N, RetType) of
- true ->
- emit(Fd, "~s__rs* ~s__cb(~s oe_obj, ~s~s, "
- "CORBA_Environment *oe_env);\n",
- [ScopedName, ScopedName, ic_util:to_undersc(N), RT,
- CBPL]);
- false ->
- emit(Fd, "~s__rs* ~s__cb(~s oe_obj, ~s*~s, "
- "CORBA_Environment *oe_env);\n",
- [ScopedName, ScopedName, ic_util:to_undersc(N), RT,
- CBPL])
- end
- end,
- emit_callback_prototypes(G, Fd, N, Xs);
-emit_callback_prototypes(G, Fd, N, [X| Xs]) when is_record(X, attr) ->
- emit_callback_prototypes(G, Fd, N, Xs);
-emit_callback_prototypes(G, Fd, N, [_X| Xs]) ->
- emit_callback_prototypes(G, Fd, N, Xs);
-emit_callback_prototypes(_G, _Fd, _N, []) -> ok.
-
-%%------------------------------------------------------------
-%% Emit decoder prototypes
-%%------------------------------------------------------------
-
-emit_decoder_prototypes(G, Fd, N, [X| Xs]) when is_record(X, op) ->
- %% Check if to use scoped call names
- {ScopedName, ArgNames, Types} = ic_cbe:extract_info(G, N, X),
- {_RetType, ParTypes, _} = Types,
- TypeAttrArgs = mk_type_attr_arg_list(ParTypes, ArgNames),
- case ic_util:mk_list(mk_par_list_for_decoder_prototypes(G, N, X,
- TypeAttrArgs)) of
- "" ->
- ok;
- PLFDP ->
- emit(Fd, "int ~s__dec(~s oe_obj, ~s, CORBA_Environment "
- "*oe_env);\n",
- [ScopedName, ic_util:to_undersc(N), PLFDP])
- end,
- emit_decoder_prototypes(G, Fd, N, Xs);
-emit_decoder_prototypes(G, Fd, N, [X| Xs]) when is_record(X, attr) ->
- emit_decoder_prototypes(G, Fd, N, Xs);
-emit_decoder_prototypes(G, Fd, N, [_X| Xs]) ->
- emit_decoder_prototypes(G, Fd, N, Xs);
-emit_decoder_prototypes(_G, _Fd, _N, []) -> ok.
-
-
-%%------------------------------------------------------------
-%% Emit encoder prototypes
-%%------------------------------------------------------------
-
-emit_encoder_prototypes(G, Fd, N, [X| Xs]) when is_record(X, op) ->
- case ic_forms:is_oneway(X) of
- true ->
- emit_encoder_prototypes(G, Fd, N, Xs);
- false ->
- %% Check if to use scoped call names
- {ScopedName, ArgNames, Types} = ic_cbe:extract_info(G, N, X),
- {RetType, ParTypes, _} = Types,
- TypeAttrArgs = mk_type_attr_arg_list(ParTypes, ArgNames),
- RType = mk_c_ret_type(G, N, RetType),
- case ic_util:mk_list(mk_par_list_for_encoder_prototypes(
- G, N, X, TypeAttrArgs)) of
- "" ->
- case RType of
- "void" ->
- emit(Fd, "int ~s__enc(~s oe_obj, "
- "CORBA_Environment *oe_env);\n",
- [ScopedName, ic_util:to_undersc(N)]);
- _ ->
- emit(Fd, "int ~s__enc(~s oe_obj, ~s, "
- "CORBA_Environment *oe_env);\n",
- [ScopedName, ic_util:to_undersc(N), RType])
- end;
- PLFEP ->
- case RType of
- "void" ->
- emit(Fd, "int ~s__enc(~s oe_obj, ~s, "
- "CORBA_Environment *oe_env);\n",
- [ScopedName, ic_util:to_undersc(N), PLFEP]);
- _ ->
- emit(Fd, "int ~s__enc(~s oe_obj, ~s, ~s, "
- "CORBA_Environment *oe_env);\n",
- [ScopedName, ic_util:to_undersc(N), RType,
- PLFEP])
- end
- end,
- emit_encoder_prototypes(G, Fd, N, Xs)
- end;
-emit_encoder_prototypes(G, Fd, N, [X| Xs]) when is_record(X, attr) ->
- emit_encoder_prototypes(G, Fd, N, Xs);
-emit_encoder_prototypes(G, Fd, N, [_X| Xs]) ->
- emit_encoder_prototypes(G, Fd, N, Xs);
-emit_encoder_prototypes(_G, _Fd, _N, []) -> ok.
-
-%%------------------------------------------------------------
-%% Emit operation mapping declaration
-%%------------------------------------------------------------
-
-emit_operation_mapping_declaration(G, Fd, N, Bodies) ->
- Interface = ic_util:to_undersc(N),
- Length = erlang:length(get_all_opnames(G, N, Bodies)),
- emit(Fd, "\n/* Operation mapping */\n", []),
- emit(Fd, "extern oe_map_t oe_~s_map;\n", [Interface]),
- emit(Fd, "/* For backward compatibility */\n"),
- emit(Fd, "#define ___~s_map___ oe_~s_map\n",
- [Interface, Interface]),
- case Length of
- 0 ->
- ok;
- _ ->
- emit(Fd, "extern oe_operation_t oe_~s_operations[];\n",
- [Interface]),
- emit(Fd, "/* For backward compatibility */\n"),
- emit(Fd, "#define ___~s_operations___ oe_~s_operations\n",
- [Interface, Interface])
- end.
-
-
-%% Returns a list of {OpName, ScopedOpName} for all operations, where
-%% OpName == ScopedOpName in case the `scoped_op_calls' option has
-%% been set.
-%%
-get_all_opnames(G, N, Bodies) ->
- ScNF = fun(X) ->
- {ScName, _, _} = ic_cbe:extract_info(G, N, X),
- ScName
- end,
- NF = case ic_options:get_opt(G, scoped_op_calls) of
- true ->
- ScNF;
- false ->
- fun(X) -> ic_forms:get_id2(X) end
- end,
- Filter = fun(X) when is_record(X, op) ->
- {true, {NF(X), ScNF(X)}};
- (_) ->
- false
- end,
- %% zf == filtermap
- lists:flatmap(fun({_, Xs}) -> lists:zf(Filter, Xs) end, Bodies).
-
-%%------------------------------------------------------------
-%% Emit switch
-%%------------------------------------------------------------
-
-emit_switch(G, Fd, N, _X) ->
- emit(Fd, "#include <string.h>\n"),
- case ic_options:get_opt(G, c_report) of
- true ->
- emit(Fd, "#ifndef OE_C_REPORT\n"),
- emit(Fd, "#define OE_C_REPORT\n"),
- emit(Fd, "#include <stdio.h>\n"),
- emit(Fd, "#endif\n");
- _ ->
- ok
- end,
- StartCode =
- "#include \"ic.h\"\n"
- "#include \"erl_interface.h\"\n"
- "#include \"ei.h\"\n"
- "#include \"~s__s.h\"\n\n"
- "/*\n"
- " * Main switch\n"
- " */\n\n"
- "int ~s__switch(~s oe_obj, CORBA_Environment *oe_env)\n"
- "{\n"
- " return oe_exec_switch(oe_obj, oe_env, &oe_~s_map);\n"
- "}\n\n",
- ScopedName = ic_util:to_undersc(N),
- emit(Fd, StartCode, [ScopedName, ScopedName, ScopedName, ScopedName]).
-
-%%------------------------------------------------------------
-%% Emit server generic decoding.
-%%------------------------------------------------------------
-
-emit_server_generic_decoding(G, Fd, N) ->
- UserProto = get_user_proto(G, oe),
- Code =
- "/*\n"
- " * Returns call identity (left only for backward compatibility)\n"
- " */\n\n"
- "int ~s__call_info(~s oe_obj, CORBA_Environment *oe_env)\n"
- "{\n"
- " return ~s_prepare_request_decoding(oe_env);\n"
- "}\n\n",
- IName = ic_util:to_undersc(N),
- emit(Fd, Code, [IName, IName, UserProto]).
-
-%%------------------------------------------------------------
-%% Emit dispatch
-%%------------------------------------------------------------
-
-emit_dispatch(G, Fd, N, Xs) ->
- lists:foreach(
- fun(X) when is_record(X, op) ->
- {Name, ArgNames, Types} = ic_cbe:extract_info(G, N, X),
- {RetType, ParTypes, _} = Types,
- TypeAttrArgs = mk_type_attr_arg_list(ParTypes, ArgNames),
- emit_exec_function(G, Fd, N, X, Name, RetType, TypeAttrArgs),
- emit_parameter_decoder(G, Fd, N, X, Name, RetType, TypeAttrArgs),
- emit_message_encoder(G, Fd, N, X, Name, RetType, TypeAttrArgs);
- (_) ->
- ok
- end, Xs).
-
-%%------------------------------------------------------------
-%% Emit operation mapping
-%%------------------------------------------------------------
-
-emit_operation_mapping(G, Fd, N, Bodies) ->
- OpNames = get_all_opnames(G, N, Bodies),
- Interface = ic_util:to_undersc(N),
- Length = erlang:length(OpNames),
- emit(Fd, "\n/* Operation mapping */\n\n", []),
- case Length of
- 0 ->
- emit(Fd, "oe_map_t oe_~s_map = { 0, NULL };\n\n", [Interface]);
- _ ->
- emit(Fd, "\noe_operation_t oe_~s_operations[~p] = {\n",
- [Interface, Length]),
- Members = lists:map(
- fun({OpN, ScOpN}) ->
- Name = ic_util:to_undersc([OpN]),
- ScName = ic_util:to_undersc([ScOpN]),
- io_lib:fwrite(" {~p, ~p, ~s__exec}",
- [Interface, Name, ScName])
- end, OpNames),
- emit(Fd, ic_util:join(Members, ",\n")),
- emit(Fd, "};\n\n", []),
- emit(Fd, "oe_map_t oe_~s_map = "
- "{~p, oe_~s_operations};\n\n",
- [Interface, Length, Interface])
- end.
-
-%%------------------------------------------------------------
-%% Emit constant
-%%------------------------------------------------------------
-
-emit_constant(G, N, ConstRecord) ->
- case ic_genobj:is_hrlfile_open(G) of
- false -> ok;
- true ->
- Fd = ic_genobj:hrlfiled(G),
- CName = ic_util:to_undersc(
- [ic_forms:get_id(ConstRecord#const.id)| N]),
- UCName = ic_util:to_uppercase(CName),
-
- emit(Fd, "\n#ifndef __~s__\n", [UCName]),
- emit(Fd, "#define __~s__\n\n", [UCName]),
-
- emit(Fd, "/* Constant: ~s */\n", [CName]),
-
- if is_record(ConstRecord#const.type, wstring) ->
- %% If wstring, add 'L'
- emit(Fd, "#define ~s L~p\n\n", [CName,
- ConstRecord#const.val]);
- true ->
- emit(Fd, "#define ~s ~p\n\n", [CName,
- ConstRecord#const.val])
- end,
-
- emit(Fd, "#endif\n\n")
- end.
-
-%%------------------------------------------------------------
-%% Emit exec function
-%%------------------------------------------------------------
-
-emit_exec_function(G, Fd, N, X, Name, RetType, TypeAttrArgs) ->
- %% Decoding operation specific part
- InTypeAttrArgs = lists:filter(fun({_, in, _}) -> true;
- ({_, _, _}) -> false
- end, TypeAttrArgs),
- ic_codegen:nl(Fd),
-
- emit(Fd,
- "int ~s__exec(~s oe_obj, CORBA_Environment *oe_env)\n"
- "{\n",
- [Name, ic_util:to_undersc(N)]),
-
- emit(Fd, " if (oe_env->_received != ~p) {\n", [length(InTypeAttrArgs)]),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, BAD_PARAM, "
- "\"Wrong number of operation parameters\");\n"),
- emit_c_dec_rpt(Fd, " ", "wrong number of parameters", []),
- emit_c_dec_rpt(Fd, " ", "server exec ~s\\n====\\n", [Name]),
- emit(Fd, " return -1;\n", []),
- emit(Fd, " }\n"),
- emit(Fd, " else {\n", []),
-
- case InTypeAttrArgs of
- [] ->
- true;
- _ ->
- emit(Fd, " int oe_error_code = 0;\n")
- end,
-
- %% Callback variable definition
- emit_variable_defs(G, Fd, N, X, Name, RetType, TypeAttrArgs),
-
- %% Call to parameter decoder
- emit_parameter_decoder_call(G, Fd, N, X, Name, RetType, TypeAttrArgs),
-
- %% Callback to user code
- emit_callback(G, Fd, N, X, Name, RetType, TypeAttrArgs),
-
- %% Call to return message encoder
- case ic_forms:is_oneway(X) of
- true ->
- true;
- false ->
- emit_message_encoder_call(G, Fd, N, X, Name, RetType, TypeAttrArgs)
- end,
-
- %% Restore function call
- emit_restore(G, Fd, N, X, Name, RetType, TypeAttrArgs),
-
- emit(Fd, " }\n return 0;\n}\n\n").
-
-%%------------------------------------------------------------
-%% Emit parameter decoder
-%%------------------------------------------------------------
-
-emit_parameter_decoder(G, Fd, N, X, Name, _RetType, TypeAttrArgs) ->
- %% Decoding operation specific part
- InTypeAttrArgs =
- lists:filter(fun({_, in, _}) -> true;
- ({_, _, _}) -> false
- end, TypeAttrArgs),
- case InTypeAttrArgs of
- [] ->
- ok;
- _ ->
- case ic_util:mk_list(mk_par_list_for_decoder(G, N, X,
- TypeAttrArgs)) of
- "" ->
- emit(Fd, "int ~s__dec(~s oe_obj, CORBA_Environment "
- "*oe_env)\n{\n int oe_error_code;\n\n",
- [Name, ic_util:to_undersc(N)]);
- PLFD ->
- emit(Fd, "int ~s__dec(~s oe_obj, ~s, CORBA_Environment "
- "*oe_env)\n{\n",
- [Name, ic_util:to_undersc(N), PLFD]),
- emit(Fd, " int oe_error_code;\n\n")
- end,
-
- APars = [], % XXX Alloced parameters
- foldl(
- fun({{'void', _}, _, _}, _Acc) ->
- ok;
- ({T1, A1, N1}, Acc) ->
- emit_one_decoding(G, N, Fd, T1, A1, N1, Acc)
- end, APars, InTypeAttrArgs),
-
- emit(Fd, " return 0;\n}\n\n")
- end.
-
-%%------------------------------------------------------------
-%% Emit one decoding
-%%------------------------------------------------------------
-
-emit_one_decoding(G, N, Fd, T1, A1, N1, AllocedPars) ->
- IndOp = mk_ind_op(A1),
- case ic_cbe:is_variable_size(G, N, T1) of
- false ->
- %% The last parameter "oe_outindex" is not used in
- %% the static case but must be there anyhow.
- emit_decoding_stmt(G, N, Fd, T1,
- N1, "", "oe_env->_inbuf", 1, "&oe_outindex",
- caller, AllocedPars),
- ic_codegen:nl(Fd),
- AllocedPars;
- true ->
- emit_encoding_comment(G, N, Fd, "Decode", IndOp, T1, N1),
- emit(Fd, " {\n"),
- emit(Fd, " int oe_size_count_index = oe_env->_iin;\n"),
- emit(Fd, " int oe_malloc_size = 0;\n"),
- emit(Fd, " void *oe_first = NULL;\n"),
- ic_cbe:emit_malloc_size_stmt(G, N, Fd, T1,
- "oe_env->_inbuf", 1, caller),
- %% This is the only malloc call in this file
- emit(Fd,
- " OE_MALLOC_SIZE_CHECK(oe_env, oe_malloc_size);\n"
- " if ((*~s = oe_first = "
- "malloc(oe_malloc_size)) == NULL) {\n", [N1]),
- ic_cbe:emit_dealloc_stmts(Fd, " ", AllocedPars),
- emit(Fd,
- " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "NO_MEMORY, \"Cannot malloc\");\n"
- " return -1;\n"
- " }\n"),
- ParName = "*" ++ N1, % XXX Why not IndOp?
- NAllocedPars = [ParName| AllocedPars],
- case ictype:isArray(G, N, T1) of
- true ->
- emit_decoding_stmt(G, N, Fd, T1,
- "(*" ++ IndOp ++ N1 ++ ")", "",
- "oe_env->_inbuf", 1, "&oe_outindex",
- array_dyn, NAllocedPars);
- false ->
- emit_decoding_stmt(G, N, Fd, T1,
- "(*" ++ IndOp ++ N1 ++ ")", "",
- "oe_env->_inbuf", 1, "&oe_outindex",
- caller_dyn, NAllocedPars)
- end,
- emit(Fd, " }\n\n"),
- NAllocedPars
- end.
-
-%%------------------------------------------------------------
-%% Emit message encoder
-%%------------------------------------------------------------
-
-emit_message_encoder(G, Fd, N, X, Name, RetType, TypeAttrArgs) ->
- case ic_forms:is_oneway(X) of
- false ->
- %% Encoding operation specific part
- emit(Fd,
- "\nint ~s__enc(~s oe_obj",
- [Name, ic_util:to_undersc(N)]),
- RType = mk_c_ret_type(G, N, RetType),
- ParList = mk_par_list_for_encoder(G, N, X, TypeAttrArgs),
- case ic_util:mk_list(ParList) of
- "" ->
- case RType of
- "void" ->
- emit(Fd, ", CORBA_Environment *oe_env)\n{");
- _ ->
- emit(Fd, ", ~s oe_return, CORBA_Environment "
- "*oe_env)\n{", [RType])
- end;
- PLFD ->
- case RType of
- "void" ->
- emit(Fd, ", ~s, CORBA_Environment "
- "*oe_env)\n{", [PLFD]);
- _ ->
- emit(Fd, ", ~s oe_return~s, CORBA_Environment "
- "*oe_env)\n{", [RType, ", " ++ PLFD])
- end
- end,
-
-
- emit(Fd, "\n"),
- emit(Fd, " int oe_error_code;\n\n"),
- UserProto = get_user_proto(G, oe),
- emit(Fd, " ~s_prepare_reply_encoding(oe_env);\n", [UserProto]),
-
- OutTypeAttrArgs =
- lists:filter(fun({_, out, _}) -> true;
- ({_, _, _}) -> false
- end, TypeAttrArgs),
-
- OutLength = length(OutTypeAttrArgs),
- case OutLength > 0 of
- false ->
- ic_codegen:nl(Fd);
- true ->
- emit(Fd, " oe_ei_encode_tuple_header(oe_env, ~p);\n\n",
- [OutLength+1])
-
- end,
-
- emit_encoding_comment(G, N, Fd, "Encode", "", RetType,
- "oe_return"),
- emit_encoding_stmt(G, N, X, Fd, RetType, "oe_return"),
-
- foreach(fun({T1, _A1, N1}) ->
- case T1 of
- {'void', _} ->
- ok;
- _ ->
- emit_encoding_comment(G, N, Fd, "Encode",
- "", T1, N1),
- emit_encoding_stmt(G, N, X, Fd, T1, N1)
- end
- end, OutTypeAttrArgs),
- emit(Fd, " return 0;\n}\n\n");
- _ ->
- %% Oneway
- ok
- end.
-
-%%------------------------------------------------------------
-%% Emit message encoder call
-%%------------------------------------------------------------
-
-emit_message_encoder_call(G, Fd, N, X, Name, RetType, TypeAttrArgs) ->
- emit(Fd, " /* Encoding reply message */\n"),
- RType = mk_c_ret_type(G, N, RetType),
- case ic_util:mk_list(mk_enc_par_list(G, N, X, TypeAttrArgs)) of
- "" ->
- case RType of
- "void" ->
- emit(Fd, " ~s(oe_obj, oe_env);\n",
- [Name ++ "__enc"]);
- "erlang_pid*" ->
- emit(Fd, " ~s(oe_obj, &oe_return, oe_env);\n",
- [Name ++ "__enc"]);
- "erlang_port*" ->
- emit(Fd, " ~s(oe_obj, &oe_return, oe_env);\n",
- [Name ++ "__enc"]);
- "erlang_ref*" ->
- emit(Fd, " ~s(oe_obj, &oe_return, oe_env);\n",
- [Name ++ "__enc"]);
- _ ->
- emit(Fd, " ~s(oe_obj, oe_return, oe_env);\n",
- [Name ++ "__enc"])
- end;
-
- PLFE ->
- case RType of
- "void" ->
- emit(Fd, " ~s(oe_obj, ~s, oe_env);\n",
- [Name ++ "__enc", PLFE]);
- "erlang_pid*" ->
- emit(Fd, " ~s(oe_obj, &oe_return, ~s, oe_env);\n",
- [Name ++ "__enc", PLFE]);
- "erlang_port*" ->
- emit(Fd, " ~s(oe_obj, &oe_return, ~s, oe_env);\n",
- [Name ++ "__enc", PLFE]);
- "erlang_ref*" ->
- emit(Fd, " ~s(oe_obj, &oe_return, ~s, oe_env);\n",
- [Name ++ "__enc", PLFE]);
- _ ->
- emit(Fd, " ~s(oe_obj, oe_return, ~s, oe_env);\n",
- [Name ++ "__enc", PLFE])
- end
- end,
- ic_codegen:nl(Fd).
-
-%%------------------------------------------------------------
-%% Emit parameter decoding call
-%%------------------------------------------------------------
-
-emit_parameter_decoder_call(G, Fd, N, X, Name, _R, TypeAttrArgs) ->
- case ic_util:mk_list(mk_dec_par_list(G, N, X, TypeAttrArgs)) of
- "" -> %% No parameters ! skip it !
- ok;
- PLFDC ->
- ParDecName = Name ++ "__dec",
- emit(Fd,
- " /* Decode parameters */\n"
- " if((oe_error_code = ~s(oe_obj, ~s, oe_env)) < 0) {\n",
- [ParDecName, PLFDC]),
- emit_c_dec_rpt(Fd, " ", "parmeters", []),
- emit(Fd,
- " if(oe_env->_major == CORBA_NO_EXCEPTION)\n"
- " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad parameter on decode\");\n"
- " return oe_error_code;\n }\n\n")
- end.
-
-%%------------------------------------------------------------
-%% Emit call-back
-%%------------------------------------------------------------
-
-emit_callback(G, Fd, N, X, Name, RetType, TypeAttrArgs) ->
- CallBackName = Name ++ "__cb",
- emit(Fd, " /* Callback function call */\n"),
- PL = ic_util:mk_list(mk_cb_par_list(G, N, X, TypeAttrArgs)),
- case ic_forms:is_oneway(X) of
- true ->
- case PL of
- "" ->
- emit(Fd, " oe_restore = ~s(oe_obj, oe_env);\n\n",
- [CallBackName]);
- _ ->
- emit(Fd, " oe_restore = ~s(oe_obj, ~s, oe_env);\n\n",
- [CallBackName, PL])
- end;
- false ->
- CBPL = case PL of
- "" ->
- "";
- _PL ->
- ", " ++ PL
- end,
- case mk_c_ret_type(G, N, RetType) of
- "void" ->
- case PL of
- "" ->
- emit(Fd, " oe_restore = ~s(oe_obj, oe_env);"
- "\n\n", [CallBackName]);
- _ ->
- emit(Fd, " oe_restore = ~s(oe_obj, ~s, oe_env);"
- "\n\n", [CallBackName, PL])
- end;
- _ ->
- case ictype:isArray(G, N, RetType) of
- true ->
- emit(Fd,
- " oe_restore = ~s(oe_obj, oe_return~s, "
- " oe_env);\n\n", [CallBackName, CBPL]);
- false ->
- emit(Fd, " oe_restore = ~s(oe_obj, "
- "&oe_return~s, oe_env);\n\n",
- [CallBackName, CBPL])
- end
- end
- end.
-
-%%------------------------------------------------------------
-%% Emit restore
-%%------------------------------------------------------------
-
-emit_restore(G, Fd, N, X, _Name, RetType, TypeAttrArgs) ->
- emit(Fd, " /* Restore function call */\n"),
- emit(Fd, " if (oe_restore != NULL)\n"),
- PL = ic_util:mk_list(mk_cb_par_list(G, N, X, TypeAttrArgs)),
- case ic_forms:is_oneway(X) of
- true ->
- case PL of
- "" ->
- emit(Fd, " (*oe_restore)(oe_obj, oe_env);\n\n");
- _ ->
- emit(Fd, " (*oe_restore)(oe_obj, ~s, oe_env);\n\n",
- [PL])
- end;
- false ->
- RPL = case PL of
- "" ->
- "";
- _PL ->
- ", " ++ PL
- end,
- case mk_c_ret_type(G, N, RetType) of
- "void" ->
- case PL of
- "" ->
- emit(Fd, " (*oe_restore)(oe_obj, oe_env);"
- "\n\n");
- _ ->
- emit(Fd, " (*oe_restore)(oe_obj, ~s, oe_env);"
- "\n\n", [PL])
- end;
- _ ->
- case ictype:isArray(G, N, RetType) of
- true ->
- emit(Fd,
- " (*oe_restore)(oe_obj, oe_return~s, "
- " oe_env);\n\n", [RPL]);
- false ->
- emit(Fd, " (*oe_restore)(oe_obj, "
- "&oe_return~s, oe_env);\n\n", [RPL])
- end
- end
- end.
-
-%%------------------------------------------------------------
-%% Emit variable defs
-%%------------------------------------------------------------
-
-emit_variable_defs(G, Fd, N, X, _Name, RetType, TypeAttrArgs) ->
- {ScopedName, _, _} = ic_cbe:extract_info(G, N, X),
- emit(Fd, " ~s__rs* oe_restore = NULL;\n", [ScopedName]),
- RestVars = mk_var_list(mk_var_decl_list(G, N, X, TypeAttrArgs)),
- case ic_forms:is_oneway(X) of
- true ->
- emit(Fd, "~s\n\n", [RestVars]);
- false ->
- RType = mk_c_ret_type(G, N, RetType),
- case RType of
- "void" ->
- emit(Fd, "~s\n\n", [RestVars]);
- "CORBA_unsigned_long" ->
- emit(Fd, "~s ~s oe_return = 0;\n\n", [RestVars, RType]);
- "CORBA_unsigned_long_long" ->
- emit(Fd, "~s ~s oe_return = 0;\n\n", [RestVars, RType]);
- "CORBA_unsigned_short" ->
- emit(Fd, "~s ~s oe_return = 0;\n\n", [RestVars, RType]);
- "CORBA_short" ->
- emit(Fd, "~s ~s oe_return = 0;\n\n", [RestVars, RType]);
- "CORBA_long" ->
- emit(Fd, "~s ~s oe_return = 0;\n\n", [RestVars, RType]);
- "CORBA_long_long" ->
- emit(Fd, "~s ~s oe_return = 0;\n\n", [RestVars, RType]);
- "CORBA_float" ->
- emit(Fd, "~s ~s oe_return = 0;\n\n", [RestVars, RType]);
- "CORBA_double" ->
- emit(Fd, "~s ~s oe_return = 0;\n\n", [RestVars, RType]);
- "CORBA_char" ->
- emit(Fd, "~s ~s oe_return = 0;\n\n", [RestVars, RType]);
- "CORBA_wchar" -> %% WCHAR
- emit(Fd, "~s ~s oe_return = 0;\n\n", [RestVars, RType]);
- "CORBA_boolean" ->
- emit(Fd, "~s ~s oe_return = 0;\n\n", [RestVars, RType]);
- "CORBA_octet" ->
- emit(Fd, "~s ~s oe_return = 0;\n\n", [RestVars, RType]);
- _ ->
- case ic_cbe:is_variable_size(G, N, RetType) of
- true ->
- emit(Fd, "~s ~s oe_return;\n\n",
- [RestVars, RType]);
- false ->
- TK = ic_forms:get_tk(X),
- case TK of
- {tk_enum, _, _, _List} ->
- emit(Fd, "~s ~s oe_return;\n\n",
- [RestVars, RType]);
- _ ->
- case RType of
- "erlang_binary*" ->
- emit(Fd, "~s erlang_binary "
- "oe_return;\n\n", [RestVars]);
- "erlang_pid*" ->
- emit(Fd, "~s erlang_pid "
- "oe_return;\n\n", [RestVars]);
- "erlang_port*" ->
- emit(Fd, "~s erlang_port "
- "oe_return;\n\n", [RestVars]);
- "erlang_ref*" ->
- emit(Fd, "~s erlang_ref "
- "oe_return;\n\n", [RestVars]);
- _ ->
- %% Structures are
- %% initiated by memset
- emit(Fd, "~s ~s "
- "oe_return;\n\n",
- [RestVars, RType])
- end,
- emit(Fd, " memset(&oe_return, 0, "
- "sizeof(oe_return));\n\n")
- end
- end
- end
- end.
-
-%%------------------------------------------------------------
-%% Make variable list
-%%------------------------------------------------------------
-
-%% XXX Modify
-mk_var_list([]) ->
- "";
-mk_var_list([Arg| Args]) ->
- " " ++ Arg ++ ";\n" ++ mk_var_list(Args).
-
-%%------------------------------------------------------------
-%% Make return type
-%%------------------------------------------------------------
-
-mk_c_ret_type(G, N, Type) ->
- Ctype = mk_c_type(G, N, Type),
- Dyn = case ic_cbe:is_variable_size(G, N, Type) of
- true ->
- if
- is_record(Type, string) ->
- "*";
- Ctype == "CORBA_char *" ->
- "";
- is_record(Type, wstring) -> %% WSTRING
- "*";
- Ctype == "CORBA_wchar *" -> %% WSTRING
- "";
- true ->
- case ictype:isArray(G, N, Type) of
- true ->
- "";
- _ ->
- "*"
- end
- end;
- false ->
- if
- Ctype == "erlang_pid" ->
- "*";
- Ctype == "erlang_port" ->
- "*";
- Ctype == "erlang_ref" ->
- "*";
- true ->
- ""
- end
- end,
- Ctype ++ Dyn.
-
-%%------------------------------------------------------------
-%% Make call-back parameter list
-%%------------------------------------------------------------
-
-mk_cb_par_list(G, N, X, TypeAttrArgs0) ->
- TypeAttrArgs1 = filter_type_attr_arg_list(G, X, [in, out], TypeAttrArgs0),
- lists:map(
- fun({Type, Attr, Arg}) ->
- case ic_cbe:is_variable_size(G, N, Type) of
- true ->
- case Attr of
- in ->
- Arg;
- out ->
- case ictype:isArray(G, N, Type) of
- true ->
- Arg;
- _ ->
- "&" ++ Arg
- end
- end;
- false ->
- case ictype:isArray(G, N, Type) of
- true ->
- Arg;
- _ ->
- "&" ++ Arg
- end
- end
- end, TypeAttrArgs1).
-
-%%------------------------------------------------------------
-%% Make decoder parameter list
-%%------------------------------------------------------------
-
-mk_dec_par_list(G, N, X, TypeAttrArgs0) ->
- TypeAttrArgs1 = filter_type_attr_arg_list(G, X, [in],
- TypeAttrArgs0),
- lists:map(
- fun({Type, _Attr, Arg}) ->
- Ctype = mk_c_type(G, N, Type),
- case ic_cbe:is_variable_size(G, N, Type) of
- true ->
- if
- is_record(Type, string) ->
- "&" ++ Arg;
- Ctype == "CORBA_char *" ->
- Arg;
- is_record(Type, wstring) ->
- "&" ++ Arg;
- Ctype == "CORBA_wchar *" ->
- Arg;
- true ->
- "&" ++ Arg
- end;
- false ->
- case ictype:isArray(G, N, Type) of
- true ->
- Arg;
- _ ->
- "&" ++ Arg
- end
- end
- end, TypeAttrArgs1).
-
-%%------------------------------------------------------------
-%% Make encoder parameter list
-%%------------------------------------------------------------
-
-mk_enc_par_list(G, N, X, TypeAttrArgs0) ->
- TypeAttrArgs1 = filter_type_attr_arg_list(G, X, [out],
- TypeAttrArgs0),
- lists:map(
- fun({Type, _Attr, Arg}) ->
- Ctype = mk_c_type(G, N, Type),
- case Ctype of
- "erlang_pid" ->
- "&" ++ Arg;
- "erlang_port" ->
- "&" ++ Arg;
- "erlang_ref" ->
- "&" ++ Arg;
- _ ->
- Arg
- end
- end, TypeAttrArgs1).
-
-%%------------------------------------------------------------
-%% Make type argument list
-%%------------------------------------------------------------
-
-mk_type_attr_arg_list(Types, Args) ->
- filterzip(
- fun(Type, {Attr, Arg}) ->
- {true, {Type, Attr, Arg}}
- end, Types, Args).
-
-%%------------------------------------------------------------
-%% Filter type argument list
-%%------------------------------------------------------------
-
-filter_type_attr_arg_list(G, X, InOrOut, TypeAttrArgs) ->
- lists:filter(
-
- fun({_Type, inout, Arg}) ->
- ic_error:error(G, {inout_spec_for_c, X, Arg}),
- false;
- ({_Type, Attr, _Arg}) ->
- lists:member(Attr, InOrOut)
- end, TypeAttrArgs).
-
-%%------------------------------------------------------------
-%% Make indirection operator
-%%------------------------------------------------------------
-
-mk_ind_op(in) ->
- "";
-mk_ind_op(inout) ->
- error;
-mk_ind_op(_) ->
- "*".
-
-%%------------------------------------------------------------
-%% Make parameter list for decoder
-%%------------------------------------------------------------
-
-mk_par_list_for_decoder(G, N, X, TypeAttrArgs0) ->
- TypeAttrArgs1 = filter_type_attr_arg_list(G, X, [in], TypeAttrArgs0),
- lists:map(
- fun({Type, Attr, Arg}) ->
- Ctype = mk_c_type(G, N, Type),
- Dyn = case ic_cbe:is_variable_size(G, N, Type) of
- true ->
- if
- is_record(Type, string) ->
- "**";
- Ctype == "CORBA_char *" ->
- "";
- is_record(Type, wstring) -> %% WSTRING
- "**";
- Ctype == "CORBA_wchar *" -> %% WSTRING
- "";
- true ->
- case ictype:isArray(G, N, Type) of
- true ->
- slice(Attr) ++ "*";
- _ ->
- "**"
- end
- end;
- false ->
- case ictype:isArray(G, N, Type) of
- true ->
- "";
- _ ->
- "*"
- end
- end,
- Ctype ++ Dyn ++ " " ++ Arg
- end, TypeAttrArgs1).
-
-%%------------------------------------------------------------
-%% Make parameter list for encoder
-%%------------------------------------------------------------
-
-mk_par_list_for_encoder(G, N, X, TypeAttrArgs0) ->
- TypeAttrArgs1 = filter_type_attr_arg_list(G, X, [out], TypeAttrArgs0),
- lists:map(
- fun({Type, _Attr, Arg}) ->
- Ctype = mk_c_type(G, N, Type),
- Dyn = case ic_cbe:is_variable_size(G, N, Type) of
- true ->
- if
- is_record(Type, string) ->
- "*";
- Ctype == "CORBA_char *" ->
- "";
- is_record(Type, wstring) -> %% WSTRING
- "*";
- Ctype == "CORBA_wchar *" -> %% WSTRING
- "";
- true ->
- case ictype:isArray(G, N, Type) of
- true ->
- "";
- _ ->
- "*"
- end
- end;
- false ->
- if
- Ctype == "erlang_pid" ->
- "*";
- Ctype == "erlang_port" ->
- "*";
- Ctype == "erlang_ref" ->
- "*";
- true ->
- ""
- end
- end,
- Ctype ++ " " ++ Dyn ++ Arg
- end, TypeAttrArgs1).
-
-%%------------------------------------------------------------
-%% Make parameter list for decoder prototypes
-%%------------------------------------------------------------
-
-mk_par_list_for_decoder_prototypes(G, N, X, TypeAttrArgs0) ->
- TypeAttrArgs1 = filter_type_attr_arg_list(G, X, [in], TypeAttrArgs0),
- lists:map(
- fun({Type, Attr, _Arg}) ->
- Ctype = mk_c_type(G, N, Type),
- Dyn = case ic_cbe:is_variable_size(G, N, Type) of
- true ->
- if
- is_record(Type, string) ->
- "**";
- Ctype == "CORBA_char *" ->
- "";
- is_record(Type, wstring) -> %% WSTRING
- "**";
- Ctype == "CORBA_wchar *" -> %% WSTRING
- "";
- true ->
- case ictype:isArray(G, N, Type) of
- true ->
- slice(Attr) ++ "*";
- _ ->
- "**"
- end
- end;
- false ->
- case ictype:isArray(G, N, Type) of
- true ->
- "";
- _ ->
- "*"
- end
- end,
- Ctype ++ Dyn
- end, TypeAttrArgs1).
-
-%%------------------------------------------------------------
-%% Make parameter list for encoder prototypes
-%%------------------------------------------------------------
-
-mk_par_list_for_encoder_prototypes(G, N, X, TypeAttrArgs0) ->
- TypeAttrArgs1 = filter_type_attr_arg_list(G, X, [out], TypeAttrArgs0),
- lists:map(
- fun({Type, _Attr, _Arg}) ->
- Ctype = mk_c_type(G, N, Type),
- Dyn = case ic_cbe:is_variable_size(G, N, Type) of
- true ->
- if
- is_record(Type, string) ->
- "*";
- Ctype == "CORBA_char *" ->
- "";
- is_record(Type, wstring) -> %% WSTRING
- "*";
- Ctype == "CORBA_wchar *" -> %% WSTRING
- "";
- true ->
- case ictype:isArray(G, N, Type) of
- true ->
- "";
- _ ->
- "*"
- end
- end;
- false ->
- if
- Ctype == "erlang_pid" ->
- "*";
- Ctype == "erlang_port" ->
- "*";
- Ctype == "erlang_ref" ->
- "*";
- true ->
- ""
- end
- end,
- Ctype ++ Dyn
- end, TypeAttrArgs1).
-
-%%------------------------------------------------------------
-%% Make parameter list for call-back prototypes
-%%------------------------------------------------------------
-
-mk_par_list_for_callback_prototypes(G, N, X, TypeAttrArgs0) ->
- TypeAttrArgs1 = filter_type_attr_arg_list(G, X, [in, out],
- TypeAttrArgs0),
- lists:map(
- fun({Type, Attr, _Arg}) ->
- IndOp = mk_ind_op(Attr),
- Ctype = mk_c_type(G, N, Type),
- Dyn = case ic_cbe:is_variable_size(G, N, Type) of
- true ->
- if
- is_record(Type, string) ->
- "*" ++ IndOp;
- Ctype == "CORBA_char *" ->
- "" ++ IndOp;
- is_record(Type, wstring) -> %% WSTRING
- "*" ++ IndOp;
- Ctype == "CORBA_wchar *" -> %% WSTRING
- "" ++ IndOp;
- true ->
- case ictype:isArray(G, N, Type) of
- true ->
- "";
- _ ->
- "*" ++ IndOp
- end
- end;
- false ->
- case ictype:isArray(G, N, Type) of
- true ->
- "";
- _ ->
- case Attr of %% Should just be IndOp
- in ->
- "*" ++ IndOp;
- out ->
- IndOp
- end
- end
- end,
- Ctype ++ Dyn
- end, TypeAttrArgs1).
-
-%%------------------------------------------------------------
-%% Make variable declaration list
-%%------------------------------------------------------------
-
-mk_var_decl_list(G, N, X, TypeAttrArgs0) ->
- TypeAttrArgs1 = filter_type_attr_arg_list(G, X, [in, out],
- TypeAttrArgs0),
- lists:map(
- fun({Type, Attr, Arg}) ->
- Ctype = mk_c_type(G, N, Type),
- VarDecl = case ic_cbe:is_variable_size(G, N, Type) of
- true ->
- if
- is_record(Type, string) ->
- Ctype ++ "* " ++ Arg ++ " = NULL";
- Ctype == "CORBA_char *" ->
- Ctype ++ " " ++ Arg ++ " = NULL";
- is_record(Type, wstring) -> %% WSTRING
- Ctype ++ "* " ++ Arg ++ " = NULL";
- Ctype == "CORBA_wchar *" -> %% WSTRING
- Ctype ++ " " ++ Arg ++ " = NULL";
- true ->
- case ictype:isArray(G, N, Type) of
- true ->
- Ctype ++ slice(Attr) ++ " " ++
- Arg;
- _ ->
- Ctype ++ "* " ++ Arg
- end
- end;
- false ->
- Ctype ++ " " ++ Arg
- end,
-
- VarDecl
- end, TypeAttrArgs1).
-
-%%------------------------------------------------------------
-%% Slice
-%%------------------------------------------------------------
-
-slice(in) ->
- "_slice*";
-slice(_) ->
- "".
-
-%%------------------------------------------------------------
-%% Special comment functions
-%%------------------------------------------------------------
-
-emit_encoding_comment(G, N, F, String, RefOrVal, Type, Name) ->
- emit(F, [io_lib:format(" /* ~s parameter: ~s~s ~s */\n",
- [String, mk_c_type(G, N, Type),
- RefOrVal, Name])]).
-
-
-%%------------------------------------------------------------
-%% Make C type
-%%------------------------------------------------------------
-
-%%
-%% Warning this is NOT identical to mk_c_type in ic_cbe.erl
-%%
-mk_c_type(G, N, S) ->
- mk_c_type(G, N, S, evaluate).
-
-mk_c_type(G, N, S, evaluate) when element(1, S) == scoped_id ->
- {FullScopedName, _T, _TK, _} = ic_symtab:get_full_scoped_name(G, N, S),
- BT = ic_code:get_basetype(G, ic_util:to_undersc(FullScopedName)),
- case BT of
- "erlang_binary" ->
- "erlang_binary";
- "erlang_pid" ->
- "erlang_pid";
- "erlang_port" ->
- "erlang_port";
- "erlang_ref" ->
- "erlang_ref";
- "erlang_term" ->
- "ETERM*";
- {enum, Type} ->
- mk_c_type(G, N, Type, evaluate);
- Type ->
- mk_c_type(G, N, Type, evaluate)
- end;
-mk_c_type(G, N, S, evaluate_not) when element(1, S) == scoped_id ->
- {FullScopedName, _T, _TK, _} = ic_symtab:get_full_scoped_name(G, N, S),
- BT = ic_code:get_basetype(G, ic_util:to_undersc(FullScopedName)),
- case BT of
- "erlang_binary" ->
- "erlang_binary";
- "erlang_pid" ->
- "erlang_pid";
- "erlang_port" ->
- "erlang_port";
- "erlang_ref" ->
- "erlang_ref";
- "erlang_term" ->
- "ETERM*";
- Type ->
- Type
- end;
-mk_c_type(_G, _N, S, _) when is_list(S) ->
- S;
-mk_c_type(_G, _N, S, _) when is_record(S, string) ->
- "CORBA_char";
-mk_c_type(_G, _N, S, _) when is_record(S, wstring) -> %% WSTRING
- "CORBA_wchar";
-mk_c_type(_G, _N, {boolean, _}, _) ->
- "CORBA_boolean";
-mk_c_type(_G, _N, {octet, _}, _) ->
- "CORBA_octet";
-mk_c_type(_G, _N, {void, _}, _) ->
- "void";
-mk_c_type(_G, _N, {unsigned, U}, _) ->
- case U of
- {short, _} ->
- "CORBA_unsigned_short";
- {long, _} ->
- "CORBA_unsigned_long";
- {'long long', _} ->
- "CORBA_unsigned_long_long"
- end;
-mk_c_type(_G, _N, {'long long', _}, _) ->
- "CORBA_long_long";
-mk_c_type(_G, _N, {'any', _}, _) -> %% Fix for any type
- "CORBA_long";
-mk_c_type(_G, _N, {T, _}, _) ->
- "CORBA_" ++ atom_to_list(T).
-
-%%------------------------------------------------------------
-%% Emit encoding statement
-%%------------------------------------------------------------
-
-%% emit_encoding_stmt(G, N, X, Fd, T, LName)
-%%
-%%
-emit_encoding_stmt(G, N, X, Fd, T, LName) when element(1, T) == scoped_id ->
- case mk_c_type(G, N, T, evaluate_not) of
- "erlang_pid" ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_pid(oe_env, ~s)) < 0) {\n",
- [LName]),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_pid", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "erlang_port" ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_port(oe_env, ~s)) < 0) {\n",
- [LName]),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_port", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "erlang_ref" ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_ref(oe_env, ~s)) < 0) {\n",
- [LName]),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_ref", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "ETERM*" ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_term(oe_env, ~s)) < 0) {\n",
- [LName]),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_term", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {enum, FSN} ->
- emit_encoding_stmt(G, N, X, Fd, FSN, LName);
- FSN ->
- emit_encoding_stmt(G, N, X, Fd, FSN, LName)
- end;
-emit_encoding_stmt(G, N, X, Fd, T, LName) when is_list(T) ->
- %% Already a fullscoped name
- case get_param_tk(LName, X) of
- error ->
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, ~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "encode_"), T, LName]);
- ParamTK ->
- case ic_cbe:is_variable_size(ParamTK) of
- true ->
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, ~s)) < 0)"
- " {\n",
- [ic_util:mk_oe_name(G, "encode_"), T, LName]),
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation parameter on encode\");"
- "\n"),
- ?emit_c_enc_rpt(Fd, " ", "", []),
- emit(Fd, " return oe_error_code;\n }\n\n");
- false ->
- if is_atom(ParamTK) ->
- case ParamTK of
- tk_ushort ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_ulong(oe_env, "
- "(unsigned long) ~s)) < 0) {\n",
- [LName]),
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation "
- "parameter on encode\");\n"),
- ?emit_c_enc_rpt(Fd, " ", "ushort", []),
- emit(Fd, " return "
- "oe_error_code;\n }\n\n");
- tk_ulong ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_ulong(oe_env, "
- "~s)) < 0) {\n", [LName]),
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation "
- "parameter on encode\");\n"),
- ?emit_c_enc_rpt(Fd, " ", "ulong", []),
- emit(Fd, " return "
- "oe_error_code;\n }\n\n");
- tk_ulonglong ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_ulonglong(oe_env, "
- "~s)) < 0) {\n", [LName]),
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation "
- "parameter on encode\");\n"),
- ?emit_c_enc_rpt(Fd, " ", "ulonglong", []),
- emit(Fd, " return "
- "oe_error_code;\n }\n\n");
- tk_short ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_long(oe_env, "
- "(long) ~s)) < 0) {\n", [LName]),
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation "
- "parameter on encode\");\n"),
- ?emit_c_enc_rpt(Fd, " ", "short", []),
- emit(Fd, " return "
- "oe_error_code;\n }\n\n");
- tk_long ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_long(oe_env, "
- "~s)) < 0) {\n", [LName]),
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation "
- "parameter on encode\");\n"),
- ?emit_c_enc_rpt(Fd, " ", "long", []),
- emit(Fd, " return "
- "oe_error_code;\n }\n\n");
- tk_longlong ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_longlong(oe_env, "
- "~s)) < 0) {\n", [LName]),
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation "
- "parameter on encode\");\n"),
- ?emit_c_enc_rpt(Fd, " ", "longlong", []),
- emit(Fd, " return "
- "oe_error_code;\n }\n\n");
- tk_float ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_double(oe_env, "
- "(double) ~s)) < 0) {\n", [LName]),
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation "
- "parameter on encode\");\n"),
- ?emit_c_enc_rpt(Fd, " ", "float", []),
- emit(Fd, " return "
- "oe_error_code;\n }\n\n");
- tk_double ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_double(oe_env, "
- "~s)) < 0) {\n", [LName]),
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation "
- "parameter on encode\");\n"),
- ?emit_c_enc_rpt(Fd, " ", "double", []),
- emit(Fd, " return "
- "oe_error_code;\n }\n\n");
- tk_boolean ->
- emit(Fd, " switch(~s) {\n", [LName]),
- emit(Fd, " case 0 :\n"),
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_atom(oe_env, "
- "\"false\")) < 0) {\n"),
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation "
- "parameter on encode\");\n"),
- ?emit_c_enc_rpt(Fd, " ", "boolean", []),
- emit(Fd, " return "
- "oe_error_code;\n }\n"),
- emit(Fd, " break;\n"),
- emit(Fd, " case 1 :\n"),
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_atom(oe_env, "
- "\"true\")) < 0) {\n"),
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation "
- "parameter on encode\");\n"),
- ?emit_c_enc_rpt(Fd, " ", "boolean", []),
- emit(Fd, " return "
- "oe_error_code;\n }\n"),
- emit(Fd, " break;\n"),
- emit(Fd, " default :\n"),
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation "
- "parameter on encode\");\n"),
- ?emit_c_enc_rpt(Fd, " ", "boolean", []),
- emit(Fd, " return -1;\n"),
- emit(Fd, " }\n\n");
- tk_char ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_char(oe_env, "
- "~s)) < 0) {\n", [LName]),
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation "
- "parameter on encode\");\n"),
- ?emit_c_enc_rpt(Fd, " ", "char", []),
- emit(Fd, " return "
- "oe_error_code;\n }\n\n");
- tk_wchar -> %% WCHAR
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_wchar(oe_env, "
- "~s)) < 0) {\n", [LName]),
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation "
- "parameter on encode\");\n"),
- ?emit_c_enc_rpt(Fd, " ", "wchar", []),
- emit(Fd, " return "
- "oe_error_code;\n }\n\n");
- tk_octet ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_char(oe_env, "
- "~s)) < 0) {\n", [LName]),
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation "
- "parameter on encode\");\n"),
- ?emit_c_enc_rpt(Fd, " ", "octet", []),
- emit(Fd, " return "
- "oe_error_code;\n }\n\n");
- tk_any ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_long(oe_env, "
- "~s)) < 0) {\n", [LName]),
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation "
- "parameter on encode\");\n"),
- ?emit_c_enc_rpt(Fd, " ", "any", []),
- emit(Fd, " return "
- "oe_error_code;\n }\n\n");
- _ ->
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation "
- "parameter on encode\");\n"),
- ?emit_c_enc_rpt(Fd, " ", "tk_unknown", []),
- emit(Fd, " return "
- "oe_error_code;\n }\n\n"),
- ok
- end;
- true ->
- case element(1, ParamTK) of
- tk_enum ->
- emit(Fd, " if ((oe_error_code = "
- "~s~s(oe_env, ~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "encode_"),
- T, LName]),
- ?emit_c_enc_rpt(Fd, " ", "enum", []);
- tk_array ->
- emit(Fd, " if ((oe_error_code = "
- "~s~s(oe_env, ~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "encode_"),
- T, LName]),
- ?emit_c_enc_rpt(Fd, " ", "array", []);
- _ ->
- emit(Fd, " if ((oe_error_code = "
- "~s~s(oe_env, &~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "encode_"),
- T, LName]),
- ?emit_c_enc_rpt(Fd, " ", "", [])
- end,
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation "
- "parameter on encode\");\n"),
- emit(Fd, " return oe_error_code;\n }\n\n")
- end
- end
- end;
-emit_encoding_stmt(G, N, _X, Fd, T, LName) when is_record(T, string) ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_string(oe_env, (const char*) ~s)) < 0) {\n",
- [LName]),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Cannot encode string\");\n"),
- ?emit_c_enc_rpt(Fd, " ", "string", []),
- emit(Fd, " return oe_error_code;\n }\n\n");
-emit_encoding_stmt(G, N, _X, Fd, T, LName) when is_record(T, wstring) ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_wstring(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "wstring", []),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Cannot encode string\");\n"),
- emit(Fd, " return oe_error_code;\n }\n\n");
-emit_encoding_stmt(G, N, _X, Fd, T, LName) ->
- case T of
- {unsigned, {short, _}} ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_ulong(oe_env, (unsigned long) ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "ushort", []),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation parameter on encode\");\n"),
- emit(Fd, " return oe_error_code;\n }\n\n");
- {unsigned, {long, _}} ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_ulong(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "ulong", []),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation parameter on encode\");\n"),
- emit(Fd, " return oe_error_code;\n }\n\n");
- {unsigned, {'long long', _}} ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_ulonglong(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "ulonglong", []),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation parameter on encode\");\n"),
- emit(Fd, " return oe_error_code;\n }\n\n");
- {short, _} ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_long(oe_env, (long) ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "short", []),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation parameter on encode\");\n"),
- emit(Fd, " return oe_error_code;\n }\n\n");
- {long, _} ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_long(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "long", []),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation parameter on encode\");\n"),
- emit(Fd, " return oe_error_code;\n }\n\n");
- {'long long', _} ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_longlong(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "longlong", []),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation parameter on encode\");\n"),
- emit(Fd, " return oe_error_code;\n }\n\n");
- {float, _} ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_double(oe_env, (double) ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "float", []),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation parameter on encode\");\n"),
- emit(Fd, " return oe_error_code;\n }\n\n");
- {double, _} ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_double(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "double", []),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation parameter on encode\");\n"),
- emit(Fd, " return oe_error_code;\n }\n\n");
- {boolean, _} ->
- emit(Fd, " switch(~s) {\n", [LName]),
- emit(Fd, " case 0 :\n"),
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_atom(oe_env, \"false\")) < 0) {\n"),
- ?emit_c_enc_rpt(Fd, " ", "boolean", []),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation parameter on encode\");\n"),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " break;\n"),
- emit(Fd, " case 1 :\n"),
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_atom(oe_env, \"true\")) < 0) {\n"),
- ?emit_c_enc_rpt(Fd, " ", "boolean", []),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation parameter on encode\");\n"),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " break;\n"),
- emit(Fd, " default :\n"),
- ?emit_c_enc_rpt(Fd, " ", "boolean", []),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation parameter on encode\");\n"),
- emit(Fd, " return -1;\n"),
- emit(Fd, " }\n\n");
- {char, _} ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_char(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "char", []),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation parameter on encode\");\n"),
- emit(Fd, " return oe_error_code;\n }\n\n");
- {wchar, _} -> %% WCHAR
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_wchar(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "wchar", []),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation parameter on encode\");\n"),
- emit(Fd, " return oe_error_code;\n }\n\n");
- {octet, _} ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_char(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "octet", []),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation parameter on encode\");\n"),
- emit(Fd, " return oe_error_code;\n }\n\n");
- {void, _} ->
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_atom(oe_env, \"void\")) < 0) {\n"),
- ?emit_c_enc_rpt(Fd, " ", "void", []),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation parameter on encode\");\n"),
- emit(Fd, " return oe_error_code;\n }\n\n");
- {sequence, _, _} ->
- ?emit_c_enc_rpt(Fd, " ", "sequence", []),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation parameter on encode\");\n"),
- emit(Fd, " return oe_error_code;\n }\n\n");
- {any, _} -> %% Fix for any type
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_long(oe_env, ~s)) < 0) {\n",
- [LName]),
- ?emit_c_enc_rpt(Fd, " ", "any", []),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "BAD_PARAM, \"Bad operation parameter on encode\");\n"),
- emit(Fd, " return oe_error_code;\n }\n\n");
- _ ->
- ic_error:fatal_error(G, {illegal_typecode_for_c, T, N})
- end.
-
-%%------------------------------------------------------------
-%% Get type kind parameter
-%%------------------------------------------------------------
-
-%% Useful functions
-get_param_tk("oe_return", Op) ->
- ic_forms:get_tk(Op);
-get_param_tk(Name, Op) ->
- case get_param(Name, Op) of
- error ->
- error;
- Param ->
- ic_forms:get_tk(Param)
- end.
-
-%%------------------------------------------------------------
-%% Get parameter (for what? XXX)
-%%------------------------------------------------------------
-
-get_param(Name, Op) when is_record(Op, op) ->
- get_param_loop(Name, Op#op.params);
-get_param(_Name, _Op) ->
- error.
-
-get_param_loop(_Name, []) ->
- error;
-get_param_loop(Name, [Param| Params]) ->
- case ic_forms:get_id2(Param) of
- Name ->
- Param;
- _ ->
- get_param_loop(Name, Params)
- end.
-
-%%------------------------------------------------------------
-%% Emit decoding statement
-%%------------------------------------------------------------
-
-emit_decoding_stmt(G, N, Fd, T, LName, IndOp, InBuffer, Align, NextPos,
- DecType, AllocedPars) when element(1, T) == scoped_id ->
- case mk_c_type(G, N, T, evaluate_not) of
- "erlang_pid" ->
- emit(Fd, " if ((oe_error_code = ei_decode_pid(~s, "
- "&oe_env->_iin, ~s~s)) < 0) {\n",
- [InBuffer, IndOp, LName]),
- ic_cbe:emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "", []),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n\n");
- "erlang_port" ->
- emit(Fd, " if ((oe_error_code = ei_decode_port(~s, "
- "&oe_env->_iin, ~s~s)) < 0) {\n",
- [InBuffer, IndOp, LName]),
- ic_cbe:emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "", []),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n\n");
- "erlang_ref" ->
- emit(Fd, " if ((oe_error_code = ei_decode_ref(~s, "
- "&oe_env->_iin, ~s~s)) < 0) {\n",
- [InBuffer, IndOp, LName]),
- ic_cbe:emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "", []),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n\n");
- "ETERM*" ->
- emit(Fd, " if ((oe_error_code = ei_decode_term(~s, "
- "&oe_env->_iin, (void**)~s~s)) < 0) {\n",
- [InBuffer, IndOp, LName]),
- ic_cbe:emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "", []),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n\n");
- {enum, FSN} ->
- emit_decoding_stmt(G, N, Fd, FSN, LName, IndOp,
- InBuffer, Align, NextPos, DecType, AllocedPars);
- FSN ->
- emit_decoding_stmt(G, N, Fd, FSN, LName, IndOp,
- InBuffer, Align, NextPos, DecType, AllocedPars)
- end;
-emit_decoding_stmt(G, N, Fd, T, LName, IndOp, InBuffer, _Align, NextPos,
- DecType, AllocedPars) when is_list(T) ->
- %% Already a fullscoped name
- Type = ictype:name2type(G, T),
- case ictype:isBasicType(Type) of
- true ->
- emit_decoding_stmt_for_basic_type(Fd, Type, InBuffer, IndOp,
- LName, AllocedPars);
- false ->
- emit(Fd, " {\n"),
- case DecType of
- caller -> %% No malloc used, define oe_first anyhow.
- emit(Fd, " void *oe_first = NULL;\n"),
- emit(Fd, " int oe_outindex = 0;\n\n");
- array_dyn -> %% Malloc used
- emit(Fd, " int oe_outindex = 0;\n\n");
- %% [ic_util:mk_align(io_lib:format("sizeof(~s)", [T]))]);
- caller_dyn -> %% Malloc used
- emit(Fd, " int oe_outindex = 0;\n\n")
- end,
- emit(Fd, " if ((oe_error_code = ~s~s(oe_env, oe_first, "
- "~s, ~s)) < 0) {\n",
- [ic_util:mk_oe_name(G, "decode_"),
- T, NextPos, LName]),
- ic_cbe:emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "", []),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n"),
- emit(Fd, " }\n")
- end;
-emit_decoding_stmt(G, N, Fd, T, LName, IndOp, InBuffer, _Align, _NextPos,
- _DecType, AllocedPars) when is_record(T, string) ->
- emit(Fd, " if ((oe_error_code = ei_decode_string(~s, "
- "&oe_env->_iin, ~s~s)) < 0) {\n",
- [InBuffer, IndOp, LName]),
- ic_cbe:emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "", []),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n");
-emit_decoding_stmt(G, N, Fd, T, LName, IndOp, InBuffer, _Align, _NextPos,
- _DecType, AllocedPars) when is_record(T, wstring) ->
- %% WSTRING
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_decode_wstring(~s, "
- "&oe_env->_iin, ~s~s)) < 0) {\n",
- [InBuffer, IndOp, LName]),
- ic_cbe:emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "", []),
- emit(Fd, " return oe_error_code;\n\n"),
- emit(Fd, " }\n");
-emit_decoding_stmt(G, N, Fd, T, LName, IndOp, InBuffer, _Align, _NextPos,
- _DecType, AllocedPars) ->
- case ic_cbe:normalize_type(T) of
- {basic, Type} ->
- emit_decoding_stmt_for_basic_type(Fd, Type, InBuffer, IndOp,
- LName, AllocedPars);
- _ ->
- case T of
- {void, _} ->
- emit(Fd,
- " if ((oe_error_code = ei_decode_atom(~s, "
- "&oe_env->_iin, 0)) < 0) {\n",
- [InBuffer]),
- ic_cbe:emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "", []),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n");
- {sequence, _, _} ->
- %% XXX XXX Why?
- ?emit_c_dec_rpt(Fd, " ", "", []),
- emit(Fd, " return oe_error_code;\n\n");
- {any, _} -> %% Fix for any type
- emit(Fd,
- " if ((oe_error_code = ei_decode_long(~s, "
- "&oe_env->_iin, ~s~s)) < 0) {\n",
- [InBuffer, IndOp, LName]),
- ic_cbe:emit_dealloc_stmts(Fd, " ", AllocedPars),
- ?emit_c_dec_rpt(Fd, " ", "", []),
- emit(Fd, " return oe_error_code;\n\n"),
- emit(Fd, " }\n");
- _ ->
- ic_error:fatal_error(G, {illegal_typecode_for_c, T, N})
- end
- end.
-
-emit_decoding_stmt_for_basic_type(Fd, Type, InBuffer, IndOp,
- LName, AllocedPars) ->
- Fmt =
- " if ((oe_error_code = ~sei_decode_~s(~s, &oe_env->_iin, "
- "~s~s)) < 0) {\n",
- Ret =
- " return oe_error_code;\n"
- "}\n",
-
- {Pre, DecType} =
- case Type of
- ushort -> {"", "ulong"};
- ulong -> {"", "ulong"};
- ulonglong -> {"oe_", "ulonglong"};
- short -> {"", "long"};
- long -> {"", "long"};
- longlong -> {"oe_", "longlong"};
- float -> {"", "double"};
- double -> {"", "double"};
- boolean -> {"", "atom"};
- char -> {"", "char"};
- wchar -> {"oe_", "wchar"};
- octet -> {"", "char"};
- any -> {"", "long"}
- end,
- case Type of
- ushort ->
- emit(Fd, " {\n"),
- emit(Fd, " unsigned long oe_ulong;\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_ulong(~s, "
- "&oe_env->_iin, &oe_ulong)) < 0) {\n", [InBuffer]),
- ic_cbe:emit_dealloc_stmts(Fd, " ", AllocedPars),
- emit_c_dec_rpt(Fd, " ", "ushort", []),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n"),
- emit(Fd, " *~s = (unsigned short) oe_ulong;\n", [LName]),
- emit(Fd, " }\n\n");
- short ->
- emit(Fd, " {\n"),
- emit(Fd, " long oe_long;\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_long(~s, "
- "&oe_env->_iin, &oe_long)) < 0) {\n", [InBuffer]),
- ic_cbe:emit_dealloc_stmts(Fd, " ", AllocedPars),
- emit_c_dec_rpt(Fd, " ", "short", []),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n"),
- emit(Fd, " *~s = (short) oe_long;\n", [LName]),
- emit(Fd, " }\n\n");
- float ->
- emit(Fd, " {\n"),
- emit(Fd, " double oe_double;\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_double(~s, "
- "&oe_env->_iin, &oe_double)) < 0) {\n", [InBuffer]),
- ic_cbe:emit_dealloc_stmts(Fd, " ", AllocedPars),
- emit_c_dec_rpt(Fd, " ", "float", []),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n"),
- emit(Fd, " *~s = (float) oe_double;\n", [LName]),
- emit(Fd, " }\n\n");
- boolean ->
- emit(Fd, " {\n"),
- emit(Fd, " char oe_bool[25];\n\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_atom(~s, "
- "&oe_env->_iin, oe_bool)) < 0) {\n", [InBuffer]),
- ic_cbe:emit_dealloc_stmts(Fd, " ", AllocedPars),
- emit_c_dec_rpt(Fd, " ", "boolean", []),
- emit(Fd, " return oe_error_code;\n"),
- emit(Fd, " }\n"),
- emit(Fd, " if (strcmp(oe_bool, \"false\") == 0) {\n"),
- emit(Fd, " *(~s) = 0;\n", [LName]),
- emit(Fd, " }\n"),
- emit(Fd, " else if (strcmp(oe_bool, \"true\") == 0) {\n"),
- emit(Fd, " *(~s) = 1;\n", [LName]),
- emit(Fd, " } else {\n"),
- ic_cbe:emit_dealloc_stmts(Fd, " ", AllocedPars),
- emit_c_dec_rpt(Fd, " ", "boolean", []),
- emit(Fd, " return -1;\n"),
- emit(Fd, " }\n"),
- emit(Fd, " }\n\n");
- _ ->
- emit(Fd, Fmt, [Pre, DecType, InBuffer, IndOp, LName]),
- ic_cbe:emit_dealloc_stmts(Fd, " ", AllocedPars),
- emit(Fd, Ret)
- end.
-
-
-%%------------------------------------------------------------
-%% Prefix for generic functions
-%%------------------------------------------------------------
-get_user_proto(G, Default) ->
- case ic_options:get_opt(G, user_protocol) of
- false ->
- Default;
- Pfx ->
- Pfx
- end.
-
-%%------------------------------------------------------------
-%% Timeout. Returns a string (or Default).
-%%------------------------------------------------------------
-get_c_timeout(G, Default) ->
- case ic_options:get_opt(G, c_timeout) of
- Tmo when is_integer(Tmo) ->
- TmoStr = integer_to_list(Tmo),
- {TmoStr, TmoStr};
- {SendTmo, RecvTmo} when is_integer(SendTmo) andalso is_integer(RecvTmo) ->
- {integer_to_list(SendTmo), integer_to_list(RecvTmo)};
- false ->
- Default
- end.
-
-%%------------------------------------------------------------
-%% ZIPPERS (merging of successive elements of two lists).
-%%------------------------------------------------------------
-
-%% zip([H1| T1], [H2| T2]) ->
-%% [{H1, H2}| zip(T1, T2)];
-%% zip([], []) ->
-%% [].
-
-filterzip(F, [H1| T1], [H2| T2]) ->
- case F(H1, H2) of
- false ->
- filterzip(F, T1, T2);
- {true, Val} ->
- [Val| filterzip(F, T1, T2)]
- end;
-filterzip(_, [], []) ->
- [].
-
-
diff --git a/lib/ic/src/ic_debug.hrl b/lib/ic/src/ic_debug.hrl
deleted file mode 100644
index 97a56743d8..0000000000
--- a/lib/ic/src/ic_debug.hrl
+++ /dev/null
@@ -1,38 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-%%----------------------------------------------------------------------
-%% Debug macro
-%%----------------------------------------------------------------------
--ifndef(ic_debug_hrl).
--define(ic_debug_hrl, true).
-
--ifdef(debug).
- -define(PRINTDEBUG(Msg),
- io:format("~p :~p ~p~n", [Msg, ?FILE, ?LINE])).
- -define(PRINTDEBUG2(F, A),
- io:format(F ++ ":~p ~p~n", A ++ [?FILE, ?LINE])).
--else.
- -define(PRINTDEBUG(Msg), ok).
- -define(PRINTDEBUG2(F, A), ok).
--endif.
-
--endif.
diff --git a/lib/ic/src/ic_enum_java.erl b/lib/ic/src/ic_enum_java.erl
deleted file mode 100644
index dbfa110089..0000000000
--- a/lib/ic/src/ic_enum_java.erl
+++ /dev/null
@@ -1,313 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ic_enum_java).
-
--include("icforms.hrl").
--include("ic.hrl").
--include("ic_debug.hrl").
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([gen/3]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% Func: gen/3
-%%-----------------------------------------------------------------
-gen(G, N, X) when is_record(X, enum) ->
- %%?PRINTDEBUG2("enum: ~p", [X]),
- EnumName = ic_forms:get_java_id(X),
- N2 = ["_" ++ EnumName |N],
- ic_jbe:gen(G, N2, ic_forms:get_body(X)),
-
- emit_enum_class(G, N, X, EnumName),
- emit_holder_class(G, N, X, EnumName),
- emit_helper_class(G, N, X, EnumName);
-gen(_G, _N, _X) ->
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% Func: emit_enum_class/4
-%%-----------------------------------------------------------------
-emit_enum_class(G, N, X, EnumName) ->
- {Fd, _} = ic_file:open_java_file(G, N, EnumName),
-
- EList = enum_member_name_list(G, N, X),
- %%?PRINTDEBUG2("EList: ~p", [EList]),
- ic_codegen:emit(Fd, ["final public class ",EnumName," {\n\n"
-
- " // instance variables\n"]),
-
- emit_enum_member_int_values_initialization(G, N, X, Fd, EList),
- emit_enum_public_instance_variables(G, N, X, Fd, EnumName, EList),
-
- ic_codegen:emit(Fd, [" private int _value;\n\n"
-
- " // constructors\n"
- " private ",EnumName,"(int __value) {\n"
- " _value = __value;\n"
- " }\n\n"
-
- " // methods\n"
- " public int value() {\n"
- " return _value;\n"
- " }\n"]),
-
- emit_enum_from_int_function(G, N, X, Fd, EnumName, EList),
-
- ic_codegen:emit(Fd, "\n}\n"),
- file:close(Fd).
-
-%%-----------------------------------------------------------------
-%% Func: emit_holder_class/4
-%%-----------------------------------------------------------------
-emit_holder_class(G, N, _X, EnumName) ->
- EName = string:concat(EnumName, "Holder"),
- {Fd, _} = ic_file:open_java_file(G, N, EName),
-
- ic_codegen:emit(Fd, ["final public class ",EnumName,"Holder {\n\n"
-
- " // instance variables\n"
- " public ",EnumName," value;\n\n"
-
- " // constructors\n"
- " public ",EnumName,"Holder() {}\n\n"
-
- " public ",EnumName,"Holder(",EnumName," initial) {\n"
- " value = initial;\n"
- " }\n\n"
-
- " // methods\n"
- " public void _marshal(",?ERLANGPACKAGE,"OtpOutputStream out) throws java.lang.Exception {\n"
- " ",EnumName,"Helper.marshal(out, value);\n"
- " }\n\n"
-
- " public void _unmarshal(",?ERLANGPACKAGE,"OtpInputStream in) throws java.lang.Exception {\n"
- " value = ",EnumName,"Helper.unmarshal(in);\n"
- " }\n\n"
- "}\n"]),
- file:close(Fd).
-
-
-%%-----------------------------------------------------------------
-%% Func: emit_helper_class/4
-%%-----------------------------------------------------------------
-emit_helper_class(G, N, X, EnumName) ->
- EName = string:concat(EnumName, "Helper"),
- WEList = enum_member_atom_list(G, N, X),
- {Fd, _} = ic_file:open_java_file(G, N, EName),
-
- ic_codegen:emit(Fd, ["public class ",EnumName,"Helper {\n\n"
-
- " // constructors\n"
- " private ",EnumName,"Helper() {}\n\n"
-
- " // methods\n"
-
- " public static void marshal(",?ERLANGPACKAGE,"OtpOutputStream _out, ",EnumName," _value)\n"
- " throws java.lang.Exception {\n\n"]),
-
- emit_enum_write_function(G, N, X, Fd, EnumName),
-
- ic_codegen:emit(Fd, [" }\n\n"
-
- " public static ",EnumName," unmarshal(",?ERLANGPACKAGE,"OtpInputStream _in)\n"
- " throws java.lang.Exception {\n\n"]),
-
- emit_enum_read_function(G, N, X, Fd, EnumName),
-
- ic_codegen:emit(Fd, "\n }\n\n"),
-
- emit_enum_private_member_variables(Fd, WEList),
-
- ic_codegen:emit(Fd, ["\n // Get integer value of enum from string\n"
- " private static int _getIntFromName(String name) throws java.lang.Exception {\n"
- " for(int i = 0; i < _memberCount; i++) {\n"
- " if (name.equals(_members[i]))\n"
- " return i;\n"
- " }\n"
- " throw new java.lang.Exception(\"\");\n"
- " }\n\n"
-
- " public static String id() {\n"
- " return \"",ictk:get_IR_ID(G, N, X),"\";\n"
- " }\n\n"
-
- " public static String name() {\n"
- " return \"",EnumName,"\";\n"
- " }\n\n"]),
-
- ic_jbe:emit_type_function(G, N, X, Fd),
-
- ic_codegen:emit(Fd, [" public static void insert(",?ICPACKAGE,"Any _any, ",EnumName," _this)\n"
- " throws java.lang.Exception {\n\n"
-
- " ",?ERLANGPACKAGE,"OtpOutputStream _os = \n"
- " new ",?ERLANGPACKAGE,"OtpOutputStream();\n\n"
-
- " _any.type(type());\n"
- " marshal(_os, _this);\n"
- " _any.insert_Streamable(_os);\n"
- " }\n\n"
-
- " public static ",EnumName," extract(",?ICPACKAGE,"Any _any)\n"
- " throws java.lang.Exception {\n\n"
-
- " return unmarshal(_any.extract_Streamable());\n"
- " }\n\n"
-
- "}\n"]),
- file:close(Fd).
-
-%%-----------------------------------------------------------------
-%% Func: emit_enum_public_instance_variables/6
-%%-----------------------------------------------------------------
-emit_enum_public_instance_variables(_G, _N, _X, _Fd, _EnumName, []) ->
- ok;
-emit_enum_public_instance_variables(G, N, X, Fd, EnumName, [Enumerator |EList]) ->
- ic_codegen:emit(Fd, [" public static final ",EnumName," ",Enumerator," = new ",EnumName,"(_",Enumerator,");\n"]),
- emit_enum_public_instance_variables(G, N, X, Fd, EnumName, EList).
-
-%%-----------------------------------------------------------------
-%% Func: emit_enum_member_int_values_initialization/5
-%%-----------------------------------------------------------------
-emit_enum_member_int_values_initialization(G, N, X, Fd, EList) ->
- InitString = emit_enum_member_int_values_initialization_1(G, N, X, Fd, EList, 0),
- ic_codegen:emit(Fd, [" public static final int ",InitString,";\n"]).
-
-
-%%-----------------------------------------------------------------
-%% Func: emit_enum_member_int_values_initialization_1/6
-%%-----------------------------------------------------------------
-emit_enum_member_int_values_initialization_1(_G, _N, _X, _Fd, [Enumerator], Num) ->
- " _" ++ Enumerator ++ " = " ++ ic_util:to_list(Num);
-emit_enum_member_int_values_initialization_1(G, N, X, Fd, [Enumerator |EList], Num) ->
- Spaces = if
- Num == 0 ->
- "";
- true ->
- " "
- end,
- Spaces ++ "_" ++ Enumerator ++ " = " ++ ic_util:to_list(Num) ++ ",\n" ++
- emit_enum_member_int_values_initialization_1(G, N, X, Fd, EList, Num + 1).
-
-%%-----------------------------------------------------------------
-%% Func: emit_enum_from_int_function/6
-%%-----------------------------------------------------------------
-emit_enum_from_int_function(_G, _N, _X, Fd, EnumName, EList) ->
- ic_codegen:emit(Fd,
- [" public static final ",EnumName," from_int(int __value) throws java.lang.Exception {\n"
- " switch (__value) {\n"]),
- emit_enum_from_int_function_switchbody(Fd, EList),
- ic_codegen:emit(Fd, [" }\n"
- " }\n"]).
-
-%%-----------------------------------------------------------------
-%% Func: emit_enum_from_int_function_switchbody/2
-%%-----------------------------------------------------------------
-emit_enum_from_int_function_switchbody(Fd, []) ->
- ic_codegen:emit(Fd, [" default:\n"
- " throw new java.lang.Exception(\"\");\n"]);
-emit_enum_from_int_function_switchbody(Fd, [Enumerator |EList]) ->
- ic_codegen:emit(Fd, [" case _",Enumerator,":\n"
- " return ",Enumerator,";\n"]),
- emit_enum_from_int_function_switchbody(Fd, EList).
-
-%%-----------------------------------------------------------------
-%% Func: emit_enum_private_member_variables/2
-%%-----------------------------------------------------------------
-emit_enum_private_member_variables(Fd, EList) ->
- ic_codegen:emit(Fd, [" private static final int _memberCount = ",integer_to_list(length(EList)),";\n"
- " private static String[] _members = {\n"]),
- emit_enum_private_member_variables_1(Fd, EList),
- ic_codegen:emit(Fd, " };\n").
-
-%%-----------------------------------------------------------------
-%% Func: emit_enum_private_member_variables_1/2
-%%-----------------------------------------------------------------
-emit_enum_private_member_variables_1(Fd, [Enumerator]) ->
- ic_codegen:emit(Fd, [" \"",Enumerator,"\"\n"]);
-emit_enum_private_member_variables_1(Fd, [Enumerator |EList]) ->
- ic_codegen:emit(Fd, [" \"",Enumerator,"\",\n"]),
- emit_enum_private_member_variables_1(Fd, EList).
-
-%%-----------------------------------------------------------------
-%% Func: emit_enum_read_function/5
-%%-----------------------------------------------------------------
-emit_enum_read_function(_G, _N, _X, Fd, EnumName) ->
- ic_codegen:emit(Fd, [" return ",EnumName,".from_int(_getIntFromName(_in.read_atom()));"]).
-
-%%-----------------------------------------------------------------
-%% Func: emit_enum_write_function/5
-%%-----------------------------------------------------------------
-emit_enum_write_function(_G, _N, _X, Fd, _EnumName) ->
- ic_codegen:emit(Fd, " _out.write_atom(_members[_value.value()]);\n").
-
-
-%%-----------------------------------------------------------------
-%% Func: enum_member_name_list/3
-%%
-%% Note: The names generated are checked for name coalition
-%% with java keywords. If so the name is always prefixed
-%% by "_"
-%%-----------------------------------------------------------------
-enum_member_name_list(_G, _N, X) ->
- lists:map(
- fun(Enumerator) ->
- ic_forms:get_java_id(Enumerator)
- end,
- ic_forms:get_body(X)).
-
-%%-----------------------------------------------------------------
-%% Func: enum_member_atom_list/3
-%%
-%% Note : Similar to the emit_member_list/3 but does not
-%% solves name coalitions with java keywords.
-%% Used for wire encoding only
-%%-----------------------------------------------------------------
-enum_member_atom_list(_G, _N, X) ->
- lists:map(
- fun(Enumerator) ->
- ic_forms:get_id2(Enumerator)
- end,
- ic_forms:get_body(X)).
-
-
-
-
-
-
-
-
diff --git a/lib/ic/src/ic_erl_template.erl b/lib/ic/src/ic_erl_template.erl
deleted file mode 100644
index 0839577701..0000000000
--- a/lib/ic/src/ic_erl_template.erl
+++ /dev/null
@@ -1,640 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(ic_erl_template).
-
-
--export([do_gen/3, emit_header/3]).
-
--import(ic_codegen, [emit/2, emit/3, nl/1]).
-
--include("icforms.hrl").
--include("ic.hrl").
-
--include_lib("stdlib/include/erl_compile.hrl").
-
--define(TAB, " ").
--define(TAB2, "% ").
-
--define(TEMPLATE_1_A,
- "%%----------------------------------------------------------------------\n"
- "%% <LICENSE>\n"
- "%% \n"
- "%% $Id$\n"
- "%%\n"
- "%%----------------------------------------------------------------------\n"
- "%% Module : ~s.erl\n"
- "%% \n"
- "%% Source : ~s\n"
- "%% \n"
- "%% Description : \n"
- "%% \n"
- "%% Creation date: ~s\n"
- "%%\n"
- "%%----------------------------------------------------------------------\n"
- "-module(~p).\n\n").
-
--define(TEMPLATE_1_B,
- "%%----------------------------------------------------------------------\n"
- "%% Internal Exports\n"
- "%%----------------------------------------------------------------------\n"
- "-export([init/1,\n"
- " terminate/2,\n"
- " code_change/3,\n"
- " handle_info/2]).\n\n"
- "%%----------------------------------------------------------------------\n"
- "%% Include Files\n"
- "%%----------------------------------------------------------------------\n"
- "\n\n"
- "%%----------------------------------------------------------------------\n"
- "%% Macros\n"
- "%%----------------------------------------------------------------------\n"
- "\n\n"
- "%%----------------------------------------------------------------------\n"
- "%% Records\n"
- "%%----------------------------------------------------------------------\n"
- "-record(state, {}).\n\n"
- "%%======================================================================\n"
- "%% API Functions\n"
- "%%======================================================================\n").
-
--define(TEMPLATE_1_C,
- "%%======================================================================\n"
- "%% Internal Functions\n"
- "%%======================================================================\n"
- "%%----------------------------------------------------------------------\n"
- "%% Function : init/1\n"
- "%% Arguments : Env = term()\n"
- "%% Returns : {ok, State} |\n"
- "%% {ok, State, Timeout} |\n"
- "%% ignore |\n"
- "%% {stop, Reason}\n"
- "%% Raises : -\n"
- "%% Description: Initiates the server\n"
- "%%----------------------------------------------------------------------\n"
- "init(_Env) ->\n"
- "\t{ok, #state{}}.\n\n\n"
- "%%----------------------------------------------------------------------\n"
- "%% Function : terminate/2\n"
- "%% Arguments : Reason = normal | shutdown | term()\n"
- "%% State = term()\n"
- "%% Returns : ok\n"
- "%% Raises : -\n"
- "%% Description: Invoked when the object is terminating.\n"
- "%%----------------------------------------------------------------------\n"
- "terminate(_Reason, _State) ->\n"
- "\tok.\n\n\n"
- "%%----------------------------------------------------------------------\n"
- "%% Function : code_change/3\n"
- "%% Arguments : OldVsn = undefined | term()\n"
- "%% State = NewState = term()\n"
- "%% Extra = term()\n"
- "%% Returns : {ok, NewState}\n"
- "%% Raises : -\n"
- "%% Description: Invoked when the object should update its internal state\n"
- "%% due to code replacement.\n"
- "%%----------------------------------------------------------------------\n"
- "code_change(_OldVsn, State, _Extra) ->\n"
- "\t{ok, State}.\n\n\n"
- "%%----------------------------------------------------------------------\n"
- "%% Function : handle_info/2\n"
- "%% Arguments : Info = normal | shutdown | term()\n"
- "%% State = NewState = term()\n"
- "%% Returns : {noreply, NewState} |\n"
- "%% {noreply, NewState, Timeout} |\n"
- "%% {stop, Reason, NewState}\n"
- "%% Raises : -\n"
- "%% Description: Invoked when, for example, the server traps exits.\n"
- "%%----------------------------------------------------------------------\n"
- "handle_info(_Info, State) ->\n"
- "\t{noreply, State}.\n\n\n").
-
--define(TEMPLATE_2_A,
- "%%% #0. BASIC INFORMATION\n"
- "%%% ----------------------------------------------------------------------\n"
- "%%% %CCaseFile : ~s.erl %\n"
- "%%% Author : \n"
- "%%% Description : \n"
- "%%%\n"
- "%%% Modules used: \n"
- "%%%\n"
- "%%%\n"
- "%%% ----------------------------------------------------------------------\n"
- "-module(~p).\n"
- "-author('unknown').\n"
- "-id('').\n"
- "-vsn('').\n"
- "-date('~s').\n\n"
- "%%% ----------------------------------------------------------------------\n"
- "%%% Template Id: <ID>\n"
- "%%%\n"
- "%%% #Copyright (C) 2004\n"
- "%%% by <COMPANY>\n"
- "%%% <ADDRESS>\n"
- "%%% <OTHER INFORMATION>\n"
- "%%% \n"
- "%%% <LICENSE>\n"
- "%%% \n"
- "%%% \n"
- "%%% ----------------------------------------------------------------------\n"
- "%%% #1. REVISION LOG\n"
- "%%% ----------------------------------------------------------------------\n"
- "%%% Rev Date Name What\n"
- "%%% ----- ------- -------- --------------------------\n"
- "%%% \n"
- "%%% ----------------------------------------------------------------------\n"
- "%%%\n"
- "%%% \n"
- "%%% #2. EXPORT LISTS\n"
- "%%% ----------------------------------------------------------------------\n"
- "%%% #2.1 EXPORTED INTERFACE FUNCTIONS\n"
- "%%% ----------------------------------------------------------------------\n").
-
--define(TEMPLATE_2_B,
- "%%% ----------------------------------------------------------------------\n"
- "%%% #2.2 EXPORTED INTERNAL FUNCTIONS\n"
- "%%% ----------------------------------------------------------------------\n"
- "-export([init/1,\n"
- " terminate/2,\n"
- " code_change/3,\n"
- " handle_info/2]).\n\n"
- "%%% ----------------------------------------------------------------------\n"
- "%%% #2.3 INCLUDE FILES\n"
- "%%% ----------------------------------------------------------------------\n"
- "\n\n"
- "%%% ----------------------------------------------------------------------\n"
- "%%% #2.4 MACROS\n"
- "%%% ----------------------------------------------------------------------\n"
- "\n\n"
- "%%% ----------------------------------------------------------------------\n"
- "%%% #2.5 RECORDS\n"
- "%%% ----------------------------------------------------------------------\n"
- "-record(state, {}).\n\n"
- "%%% ----------------------------------------------------------------------\n"
- "%%% #3. CODE\n"
- "%%% #---------------------------------------------------------------------\n"
- "%%% #3.1 CODE FOR EXPORTED INTERFACE FUNCTIONS\n"
- "%%% #---------------------------------------------------------------------\n").
-
--define(TEMPLATE_2_C,
- "%%% ----------------------------------------------------------------------\n"
- "%%% #3.3 CODE FOR INTERNAL FUNCTIONS\n"
- "%%% ----------------------------------------------------------------------\n"
- "%%% ----------------------------------------------------------------------\n"
- "%%% # init/1\n"
- "%%% Input : Env = term()\n"
- "%%% Output : {ok, State} |\n"
- "%%% {ok, State, Timeout} |\n"
- "%%% ignore |\n"
- "%%% {stop, Reason}\n"
- "%%% Exceptions : -\n"
- "%%% Description: Initiates the server\n"
- "%%% ----------------------------------------------------------------------\n"
- "init(_Env) ->\n"
- "\t{ok, #state{}}.\n\n\n"
- "%%% ----------------------------------------------------------------------\n"
- "%%% # terminate/2\n"
- "%%% Input : Reason = normal | shutdown | term()\n"
- "%%% State = term()\n"
- "%%% Output : ok\n"
- "%%% Exceptions : -\n"
- "%%% Description: Invoked when the object is terminating.\n"
- "%%% ----------------------------------------------------------------------\n"
- "terminate(_Reason, _State) ->\n"
- "\tok.\n\n\n"
- "%%% ----------------------------------------------------------------------\n"
- "%%% # code_change/3\n"
- "%%% Input : OldVsn = undefined | term()\n"
- "%%% State = NewState = term()\n"
- "%%% Extra = term()\n"
- "%%% Output : {ok, NewState}\n"
- "%%% Exceptions : -\n"
- "%%% Description: Invoked when the object should update its internal state\n"
- "%%% due to code replacement.\n"
- "%%% ----------------------------------------------------------------------\n"
- "code_change(_OldVsn, State, _Extra) ->\n"
- "\t{ok, State}.\n\n\n"
- "%%% ----------------------------------------------------------------------\n"
- "%%% # handle_info/2\n"
- "%%% Input : Info = normal | shutdown | term()\n"
- "%%% State = NewState = term()\n"
- "%%% Output : {noreply, NewState} |\n"
- "%%% {noreply, NewState, Timeout} |\n"
- "%%% {stop, Reason, NewState}\n"
- "%%% Exceptions : -\n"
- "%%% Description: Invoked when, for example, the server traps exits.\n"
- "%%% ----------------------------------------------------------------------\n"
- "handle_info(_Info, State) ->\n"
- "\t{noreply, State}.\n\n\n"
- "%%% ----------------------------------------------------------------------\n"
- "%%% #4 CODE FOR TEMPORARY CORRECTIONS\n"
- "%%% ----------------------------------------------------------------------\n\n").
-
-
-%%------------------------------------------------------------
-%%
-%% Generate the client side Erlang stubs.
-%%
-%% Each module is generated to a separate file.
-%%
-%% Export declarations for all interface functions must be
-%% generated. Each function then needs to generate a function head and
-%% a body. IDL parameters must be converted into Erlang parameters
-%% (variables, capitalised) and a type signature list must be
-%% generated (for later encode/decode).
-%%
-%%------------------------------------------------------------
-do_gen(G, _File, Form) ->
- gen_head(G, [], Form),
- gen(G, [], Form).
-
-
-gen(G, N, [X|Xs]) when is_record(X, preproc) ->
- NewG = ic:handle_preproc(G, N, X#preproc.cat, X),
- gen(NewG, N, Xs);
-gen(G, N, [X|Xs]) when is_record(X, module) ->
- G2 = ic_file:filename_push(G, N, X, erlang_template_no_gen),
- N2 = [ic_forms:get_id2(X) | N],
- gen_head(G2, N2, X),
- gen(G2, N2, ic_forms:get_body(X)),
- G3 = ic_file:filename_pop(G2, erlang_template_no_gen),
- gen(G3, N, Xs);
-gen(G, N, [X|Xs]) when is_record(X, interface) ->
- G2 = ic_file:filename_push(G, N, X, erlang_template),
- N2 = [ic_forms:get_id2(X) | N],
- gen_head(G2, N2, X),
- gen(G2, N2, ic_forms:get_body(X)),
- lists:foreach(fun({_Name, Body}) -> gen(G2, N2, Body) end,
- X#interface.inherit_body),
- Fd = ic_genobj:stubfiled(G2),
- case get_template_version(G2) of
- ?IC_FLAG_TEMPLATE_2 ->
- emit(Fd, ?TEMPLATE_2_C, []);
- _ ->
- emit(Fd, ?TEMPLATE_1_C, [])
- end,
- G3 = ic_file:filename_pop(G2, erlang_template),
- gen(G3, N, Xs);
-gen(G, N, [X|Xs]) when is_record(X, op) ->
- {Name, InArgNames, OutArgNames, Reply} = extract_info(X),
- emit_function(G, N, X, ic_genobj:is_stubfile_open(G),
- ic_forms:is_oneway(X), Name, InArgNames, OutArgNames, Reply),
- gen(G, N, Xs);
-gen(G, N, [X|Xs]) when is_record(X, attr) ->
- emit_attr(G, N, X, ic_genobj:is_stubfile_open(G), fun emit_function/9),
- gen(G, N, Xs);
-gen(G, N, [_X|Xs]) ->
- gen(G, N, Xs);
-gen(_G, _N, []) ->
- ok.
-
-%% Module Header
-emit_header(G, Fd, Name) ->
- Date = get_date(),
- case get_template_version(G) of
- ?IC_FLAG_TEMPLATE_2 ->
- emit(Fd, ?TEMPLATE_2_A, [Name, list_to_atom(Name), Date]);
- _ ->
- IDLFile = ic_genobj:idlfile(G),
- emit(Fd, ?TEMPLATE_1_A, [Name, IDLFile, Date, list_to_atom(Name)])
- end.
-
-
-emit_attr(G, N, X, Open, F) ->
- XX = #id_of{type=X},
- lists:foreach(fun(Id) ->
- X2 = XX#id_of{id=Id},
- IsOneWay = ic_forms:is_oneway(X2),
- {Get, Set} = mk_attr_func_names(N, ic_forms:get_id(Id)),
- F(G, N, X2, Open, IsOneWay, Get, [], [],
- [{ic_util:mk_var(ic_forms:get_id(Id)),
- ic_forms:get_tk(X)}]),
- case X#attr.readonly of
- {readonly, _} ->
- ok;
- _ ->
- F(G, N, X2, Open, IsOneWay, Set,
- [{ic_util:mk_var(ic_forms:get_id(Id)),
- ic_forms:get_tk(X)}], [], ["ok"])
- end
- end, ic_forms:get_idlist(X)).
-
-
-%% The automaticly generated get and set operation names for an
-%% attribute.
-mk_attr_func_names(_Scope, Name) ->
- {"_get_" ++ Name, "_set_" ++ Name}.
-
-
-extract_info(X) when is_record(X, op) ->
- Name = ic_forms:get_id2(X),
- InArgs = ic:filter_params([in,inout], X#op.params),
- OutArgs = ic:filter_params([out,inout], X#op.params),
- Reply = case ic_forms:get_tk(X) of
- tk_void ->
- ["ok"];
- Type ->
- [{"OE_Reply", Type}]
- end,
- InArgsTypeList =
- [{ic_util:mk_var(ic_forms:get_id(InArg#param.id)),
- ic_forms:get_tk(InArg)} || InArg <- InArgs ],
- OutArgsTypeList =
- [{ic_util:mk_var(ic_forms:get_id(OutArg#param.id)),
- ic_forms:get_tk(OutArg)} || OutArg <- OutArgs ],
- {Name, InArgsTypeList, OutArgsTypeList, Reply}.
-
-get_template_version(G) ->
- case ic_options:get_opt(G, flags) of
- Flags when is_integer(Flags) ->
- case ?IC_FLAG_TEST(Flags, ?IC_FLAG_TEMPLATE_2) of
- true ->
- ?IC_FLAG_TEMPLATE_2;
- false ->
- ?IC_FLAG_TEMPLATE_1
- end;
- _ ->
- ?IC_FLAG_TEMPLATE_1
- end.
-
-
-get_date() ->
- {{Y,M,D}, _} = calendar:now_to_datetime(now()),
- if
- M < 10, D < 10 ->
- lists:concat([Y, "-0", M, "-0",D]);
- M < 10 ->
- lists:concat([Y, "-0", M, "-", D]);
- D < 10 ->
- lists:concat([Y, "-", M, "-0", D]);
- true ->
- lists:concat([Y, "-", M, "-", D])
- end.
-
-
-%%------------------------------------------------------------
-%%
-%% Export stuff
-%%
-%% Gathering of all names that should be exported from a stub
-%% file.
-%%
-
-
-gen_head_special(G, N, X) when is_record(X, interface) ->
- Fd = ic_genobj:stubfiled(G),
- lists:foreach(fun({_Name, Body}) ->
- ic_codegen:export(Fd, exp_top(G, N, Body, []))
- end, X#interface.inherit_body),
- nl(Fd),
- ok;
-gen_head_special(_G, _N, _X) ->
- ok.
-
-
-%% Generate all export declarations
-gen_head(G, N, X) ->
- case ic_genobj:is_stubfile_open(G) of
- true ->
- Fd = ic_genobj:stubfiled(G),
- ic_codegen:export(Fd, exp_top(G, N, X, [])),
- gen_head_special(G, N, X),
- case get_template_version(G) of
- ?IC_FLAG_TEMPLATE_2 ->
- emit(Fd, ?TEMPLATE_2_B, []);
- _ ->
- emit(Fd, ?TEMPLATE_1_B, [])
- end;
- false ->
- ok
- end.
-
-exp_top(_G, _N, X, Acc) when element(1, X) == preproc ->
- Acc;
-exp_top(G, N, L, Acc) when is_list(L) ->
- exp_list(G, N, L, Acc);
-exp_top(G, N, M, Acc) when is_record(M, module) ->
- exp_list(G, N, ic_forms:get_body(M), Acc);
-exp_top(G, N, I, Acc) when is_record(I, interface) ->
- exp_list(G, N, ic_forms:get_body(I), Acc);
-exp_top(G, N, X, Acc) ->
- exp3(G, N, X, Acc).
-
-exp3(G, N, Op, Acc) when is_record(Op, op) ->
- FuncName = ic_forms:get_id(Op#op.id),
- Arity = length(ic:filter_params([in, inout], Op#op.params)) + 1 +
- count_extras(G, N, Op),
- [{FuncName, Arity} | Acc];
-exp3(G, N, A, Acc) when is_record(A, attr) ->
- Extra = count_extras(G, N, A),
- lists:foldr(fun(Id, Acc2) ->
- {Get, Set} = mk_attr_func_names([], ic_forms:get_id(Id)),
- case A#attr.readonly of
- {readonly, _} ->
- [{Get, 1 + Extra} | Acc2];
- _ ->
- [{Get, 1 + Extra}, {Set, 2 + Extra} | Acc2]
- end
- end, Acc, ic_forms:get_idlist(A));
-exp3(_G, _N, _X, Acc) ->
- Acc.
-
-exp_list(G, N, L, OrigAcc) ->
- lists:foldr(fun(X, Acc) ->
- exp3(G, N, X, Acc)
- end, OrigAcc, L).
-
-count_extras(G, N, Op) ->
- case {use_this(G, N, Op), use_from(G, N, Op)} of
- {[], []} ->
- 0;
- {[], _} ->
- 1;
- {_, []} ->
- 1;
- _ ->
- 2
- end.
-
-%%------------------------------------------------------------
-%%
-%% Emit stuff
-%%
-%% Low level generation primitives
-%%
-
-emit_function(_G, _N, _X, false, _, _, _, _, _) ->
- ok;
-emit_function(G, N, X, true, false, Name, InArgs, OutArgs, Reply) ->
- Fd = ic_genobj:stubfiled(G),
- This = use_this(G, N, Name),
- From = use_from(G, N, Name),
- State = ["State"],
- Vers = get_template_version(G),
- case OutArgs of
- [] ->
- ReplyString = create_string(Reply),
- emit_function_header(G, Fd, X, N, Name, create_extra(This, From, Vers),
- InArgs, length(InArgs), OutArgs, Reply,
- ReplyString, Vers),
- emit(Fd, "~p(~s) ->\n\t{reply, ~s, State}.\n\n",
- [ic_util:to_atom(Name), create_string(This ++ From ++ State ++ InArgs),
- ReplyString]);
- _ ->
- ReplyString = "{" ++ create_string(Reply ++ OutArgs) ++ "}",
- emit_function_header(G, Fd, X, N, Name, create_extra(This, From, Vers),
- InArgs, length(InArgs), OutArgs, Reply,
- ReplyString, Vers),
- emit(Fd, "~p(~s) ->\n\t{reply, ~s, State}.\n\n",
- [ic_util:to_atom(Name), create_string(This ++ From ++ State ++ InArgs),
- ReplyString])
- end;
-emit_function(G, N, X, true, true, Name, InArgs, _OutArgs, _Reply) ->
- Fd = ic_genobj:stubfiled(G),
- This = use_this(G, N, Name),
- State = ["State"],
- Vers = get_template_version(G),
- emit_function_header(G, Fd, X, N, Name, create_extra(This, [], Vers),
- InArgs, length(InArgs), "", "", "", Vers),
- emit(Fd, "~p(~s) ->\n\t{noreply, State}.\n\n",
- [ic_util:to_atom(Name), create_string(This ++ State ++ InArgs)]).
-
-create_string([]) ->
- "";
-create_string([{Name, _Type}|T]) ->
- Name ++ create_string2(T);
-create_string([Name|T]) ->
- Name ++ create_string2(T).
-
-create_string2([{Name, _Type}|T]) ->
- ", " ++ Name ++ create_string2(T);
-create_string2([Name|T]) ->
- ", " ++ Name ++ create_string2(T);
-create_string2([]) ->
- "".
-
-create_extra([], [], _Vers) ->
- {"State - term()", 1};
-create_extra([], _From, ?IC_FLAG_TEMPLATE_2) ->
- {"OE_From - term()\n%%% " ++ ?TAB ++ "State - term()", 2};
-create_extra([], _From, _Vers) ->
- {"OE_From - term()\n%% " ++ ?TAB ++ "State - term()", 2};
-create_extra(_This, [], ?IC_FLAG_TEMPLATE_2) ->
- {"OE_This - #objref{} (i.e., self())\n%%% " ++ ?TAB ++ "State - term()", 2};
-create_extra(_This, [], _Vers) ->
- {"OE_This - #objref{} (i.e., self())\n%% " ++ ?TAB ++ "State - term()", 2};
-create_extra(_This, _From, ?IC_FLAG_TEMPLATE_2) ->
- {"OE_This - #objref{} (i.e., self())\n%%% " ++ ?TAB ++
- "OE_From - term()\n%%% " ++ ?TAB ++ "State - term()", 3};
-create_extra(_This, _From, _Vers) ->
- {"OE_This - #objref{} (i.e., self())\n%% " ++ ?TAB ++
- "OE_From - term()\n%% " ++ ?TAB ++ "State - term()", 3}.
-
-use_this(G, N, OpName) ->
- FullOp = ic_util:to_colon([OpName|N]),
- FullIntf = ic_util:to_colon(N),
- case {ic_options:get_opt(G, {this, FullIntf}),
- ic_options:get_opt(G, {this, FullOp}),
- ic_options:get_opt(G, {this, true})} of
- {_, force_false, _} ->
- [];
- {force_false, false, _} ->
- [];
- {false, false, false} ->
- [];
- _ ->
- ["OE_This"]
- end.
-
-use_from(G, N, OpName) ->
- FullOp = ic_util:to_colon([OpName|N]),
- FullIntf = ic_util:to_colon(N),
- case {ic_options:get_opt(G, {from, FullIntf}),
- ic_options:get_opt(G, {from, FullOp}),
- ic_options:get_opt(G, {from, true})} of
- {_, force_false, _} ->
- [];
- {force_false, false, _} ->
- [];
- {false, false, false} ->
- [];
- _ ->
- ["OE_From"]
- end.
-
-
-emit_function_header(G, Fd, X, N, Name, {Extra, ExtraNo}, InP, Arity, OutP,
- Reply, ReplyString, ?IC_FLAG_TEMPLATE_2) ->
- emit(Fd,
- "%%% ----------------------------------------------------------------------\n"
- "%%% # ~p/~p\n"
- "%%% Input : ~s\n",
- [ic_util:to_atom(Name), (ExtraNo+Arity), Extra]),
- ic_code:type_expand_all(G, N, X, Fd, ?TAB2, InP),
- case Reply of
- ["ok"] ->
- emit(Fd, "%%% Output : ReturnValue = ~s\n", [ReplyString]);
- _ ->
- emit(Fd, "%%% Output : ReturnValue = ~s\n", [ReplyString]),
- ic_code:type_expand_all(G, N, X, Fd, "% ", Reply)
- end,
- ic_code:type_expand_all(G, N, X, Fd, ?TAB2, OutP),
- emit(Fd,
- "%%% Exceptions : ~s\n"
- "%%% Description: \n"
- "%%% ----------------------------------------------------------------------\n",
- [get_raises(X, ?IC_FLAG_TEMPLATE_2)]);
-emit_function_header(G, Fd, X, N, Name, {Extra, ExtraNo}, InP, Arity, OutP,
- Reply, ReplyString, Vers) ->
- emit(Fd,
- "%%----------------------------------------------------------------------\n"
- "%% Function : ~p/~p\n"
- "%% Arguments : ~s\n",
- [ic_util:to_atom(Name), (ExtraNo+Arity), Extra]),
- ic_code:type_expand_all(G, N, X, Fd, ?TAB, InP),
- case Reply of
- ["ok"] ->
- emit(Fd, "%% Returns : ReturnValue = ~s\n", [ReplyString]);
- _ ->
- emit(Fd, "%% Returns : ReturnValue = ~s\n", [ReplyString]),
- ic_code:type_expand_all(G, N, X, Fd, " ", Reply)
- end,
- ic_code:type_expand_all(G, N, X, Fd, ?TAB, OutP),
- emit(Fd,
- "%% Raises : ~s\n"
- "%% Description: \n"
- "%%----------------------------------------------------------------------\n",
- [get_raises(X, Vers)]).
-
-get_raises(#op{raises = []}, _Vers) ->
- "";
-get_raises(#op{raises = ExcList}, Vers) ->
- get_raises2(ExcList, [], Vers);
-get_raises(_X, _Vers) ->
- [].
-
-get_raises2([H], Acc, _Vers) ->
- lists:flatten(lists:reverse([ic_util:to_colon(H)|Acc]));
-get_raises2([H|T], Acc, ?IC_FLAG_TEMPLATE_2) ->
- get_raises2(T, ["\n%%% ", ic_util:to_colon(H) |Acc],
- ?IC_FLAG_TEMPLATE_2);
-get_raises2([H|T], Acc, _Vers) ->
- get_raises2(T, ["\n%% ", ic_util:to_colon(H) |Acc], _Vers).
-
diff --git a/lib/ic/src/ic_erlbe.erl b/lib/ic/src/ic_erlbe.erl
deleted file mode 100644
index d315a17e7c..0000000000
--- a/lib/ic/src/ic_erlbe.erl
+++ /dev/null
@@ -1,1142 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(ic_erlbe).
-
-
--export([do_gen/3]).
-%%------------------------------------------------------------
-%%
-%% Internal stuff
-%%
-%%------------------------------------------------------------
-
--export([unfold/1, mk_attr_func_names/2]).
-
-
--import(ic_util, [mk_name/2, mk_var/1, mk_oe_name/2, to_atom/1, to_list/1]).
--import(ic_forms, [get_id/1, get_id2/1, get_body/1, is_oneway/1]).
--import(ic_codegen, [emit/2, emit/3, nl/1]).
--import(ic_options, [get_opt/2]).
-
--import(lists, [foreach/2, foldr/3, map/2]).
-
-
--include("icforms.hrl").
--include("ic.hrl").
-
--include_lib("stdlib/include/erl_compile.hrl").
-
-
-%%------------------------------------------------------------
-%%
-%% Generate the client side Erlang stubs.
-%%
-%% Each module is generated to a separate file.
-%%
-%% Export declarations for all interface functions must be
-%% generated. Each function then needs to generate a function head and
-%% a body. IDL parameters must be converted into Erlang parameters
-%% (variables, capitalised) and a type signature list must be
-%% generated (for later encode/decode).
-%%
-%%------------------------------------------------------------
-do_gen(G, File, Form) ->
- GT = get_opt(G, be),
- G2 = ic_file:filename_push(G, [], mk_oe_name(G,
- ic_file:remove_ext(to_list(File))),
- erlang),
- Light = ic_options:get_opt(G, light_ifr),
- R = if
- GT == erl_corba, Light == false ->
- case ic_genobj:is_stubfile_open(G2) of
- true ->
- emit(ic_genobj:stubfiled(G2), "-include_lib(\"~s/include/~s\").\n\n",
- [?ORBNAME, ?IFRTYPESHRL]);
- false -> ok
- end,
- gen_head(G2, [], Form),
- ic_codegen:export(ic_genobj:stubfiled(G2),
- [{ictk:register_name(G2), 0},
- {ictk:unregister_name(G2), 0},
- {oe_get_module,5},
- {oe_dependency,0}]),
- R0= gen(G2, [], Form),
- ictk:reg_gen(G2, [], Form),
- ictk:unreg_gen(G2, [], Form), % "new" unreg_gen/3
- genDependency(G2), % creates code for dependency list
- R0;
- GT == erl_corba, Light == true ->
- case ic_genobj:is_stubfile_open(G2) of
- true ->
- emit(ic_genobj:stubfiled(G2), "-include_lib(\"~s/include/~s\").\n\n",
- [?ORBNAME, ?IFRTYPESHRL]);
- false -> ok
- end,
- gen_head(G2, [], Form),
- ic_codegen:export(ic_genobj:stubfiled(G2),
- [{ictk:register_name(G2), 0},
- {ictk:register_name(G2), 1},
- {ictk:unregister_name(G2), 0},
- {ictk:unregister_name(G2), 1}]),
- R0= gen(G2, [], Form),
- ictk:reg_gen(G2, [], Form),
- ictk:unreg_gen(G2, [], Form), % "new" unreg_gen/3
- R0;
- true ->
- gen_head(G2, [], Form),
- gen(G2, [], Form)
- end,
- ic_file:filename_pop(G2, erlang),
- R.
-
-
-gen(G, N, [X|Xs]) when is_record(X, preproc) ->
- NewG = ic:handle_preproc(G, N, X#preproc.cat, X),
- gen(NewG, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, module) ->
- CD = ic_code:codeDirective(G,X),
- G2 = ic_file:filename_push(G, N, X, CD),
- N2 = [get_id2(X) | N],
- gen_head(G2, N2, X),
- gen(G2, N2, get_body(X)),
- G3 = ic_file:filename_pop(G2, CD),
- gen(G3, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, interface) ->
- G2 = ic_file:filename_push(G, N, X, erlang),
- N2 = [get_id2(X) | N],
- gen_head(G2, N2, X),
- gen(G2, N2, get_body(X)),
- foreach(fun({_Name, Body}) -> gen(G2, N2, Body) end,
- X#interface.inherit_body),
- gen_serv(G2, N, X),
- G3 = ic_file:filename_pop(G2, erlang),
- gen(G3, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, const) ->
-% N2 = [get_id2(X) | N],
- emit_constant_func(G, X#const.id, X#const.val),
- gen(G, N, Xs); %% N2 or N?
-
-gen(G, N, [X|Xs]) when is_record(X, op) ->
- {Name, ArgNames, TypeList, OutArgs} = extract_info(G, N, X),
- emit_stub_func(G, N, X, Name, ArgNames, TypeList, OutArgs,
- is_oneway(X), get_opt(G, be)),
- gen(G, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, attr) ->
- emit_attr(G, N, X, fun emit_stub_func/9),
- gen(G, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, except) ->
- icstruct:except_gen(G, N, X, erlang),
- gen(G, N, Xs);
-
-gen(G, N, [X|Xs]) ->
- case may_contain_structs(X) of
- true -> icstruct:struct_gen(G, N, X, erlang);
- false -> ok
- end,
- gen(G, N, Xs);
-
-gen(_G, _N, []) -> ok.
-
-
-may_contain_structs(X) when is_record(X, typedef) -> true;
-may_contain_structs(X) when is_record(X, struct) -> true;
-may_contain_structs(X) when is_record(X, union) -> true;
-may_contain_structs(_X) -> false.
-
-
-
-%%--------------------------------------------------------------------
-%%
-%% Generate the server side (handle_call and handle_cast)
-%%
-
-gen_serv(G, N, X) ->
- case ic_genobj:is_stubfile_open(G) of
- true ->
- GT = get_opt(G, be),
- gen_oe_is_a(G, N, X, GT),
- N2 = [get_id2(X) | N],
- gen_oe_tc(G, N2, X, GT),
-
- emit_serv_std(GT, G, N, X),
-
- gen_calls(G, N2, get_body(X)),
- lists:foreach(fun({_Name, Body}) ->
- gen_calls(G, N2, Body) end,
- X#interface.inherit_body),
- gen_end_of_call(GT, G),
-
- gen_casts(G, N2, get_body(X)),
- lists:foreach(fun({_Name, Body}) ->
- gen_casts(G, N2, Body) end,
- X#interface.inherit_body),
- gen_end_of_cast(GT, G),
- emit_skel_footer(GT, G, N, X); % Note N instead of N2
- false ->
- ok
- end.
-
-gen_oe_is_a(G, N, X, erl_corba) when is_record(X, interface) ->
- Fd = ic_genobj:stubfiled(G),
- ic_codegen:mcomment(Fd, ["Inherited Interfaces"]),
- emit(Fd, "oe_is_a(~p) -> true;\n", [ictk:get_IR_ID(G, N, X)]),
- lists:foreach(fun(ScopedName) ->
- emit(Fd, "oe_is_a(~p) -> true;\n",
- [ic_pragma:scope2id(G, ScopedName)])
- end, X#interface.inherit),
- emit(Fd, "oe_is_a(_) -> false.\n"),
- nl(Fd),
- ok;
-gen_oe_is_a(_G, _N, _X, _BE) -> ok.
-
-
-%% Generates the oe_tc function
-gen_oe_tc(G, N, X, erl_corba) ->
- Fd = ic_genobj:stubfiled(G),
- ic_codegen:mcomment(Fd, ["Interface TypeCode"]),
- LocalInterface = gen_oe_tc2(G, N, get_body(X), Fd, []),
- CompleteInterface =
- lists:foldl(fun({Name, Body}, FunAcc) ->
- AName = ic_util:to_atom(ic_util:to_undersc(Name)),
- gen_oe_tc3(G, AName, Body, Fd, FunAcc)
- end, LocalInterface, X#interface.inherit_body),
- emit(Fd, "oe_tc(_) -> undefined.\n"),
- nl(Fd),
- emit(Fd, "oe_get_interface() -> \n\t["),
- emit_oe_get_interface(Fd, CompleteInterface),
- nl(Fd),
- ok;
-gen_oe_tc(_, _, _, _) ->
- ok.
-
-emit_oe_get_interface(Fd, []) ->
- emit(Fd, "].\n");
-emit_oe_get_interface(Fd, [Item]) ->
- emit(Fd, "~s].\n", [lists:flatten(Item)]);
-emit_oe_get_interface(Fd, [H|T]) ->
- emit(Fd, "~s,\n\t", [lists:flatten(H)]),
- emit_oe_get_interface(Fd, T).
-
-gen_oe_tc2(_,_,[],_, Acc) ->
- Acc;
-gen_oe_tc2(G, N, [X|Rest], Fd, Acc) when is_record(X, op) ->
- R = ic_forms:get_tk(X),
- IN = lists:map(fun(P) -> ic_forms:get_tk(P) end,
- ic:filter_params([in, inout], X#op.params)),
- OUT = lists:map(fun(P) -> ic_forms:get_tk(P) end,
- ic:filter_params([out, inout], X#op.params)),
- Function = get_id2(X),
- FunctionAtom = ic_util:to_atom(Function),
- emit(Fd, "oe_tc(~p) -> \n\t~p;\n",[FunctionAtom, {R, IN, OUT}]),
- GI = io_lib:format("{~p, oe_tc(~p)}",[Function, FunctionAtom]),
- gen_oe_tc2(G, N, Rest, Fd, [GI|Acc]);
-
-gen_oe_tc2(G, N, [X|Rest], Fd, Acc) when is_record(X, attr) ->
- {GetT, SetT} = mk_attr_func_types([], X),
- NewAcc =
- lists:foldl(fun(Id, FunAcc) ->
- {Get, Set} = mk_attr_func_names([], get_id(Id)),
- GetAttrAtom = ic_util:to_atom(Get),
- emit(Fd, "oe_tc(~p) -> \n\t~p;\n",
- [GetAttrAtom, GetT]),
- case X#attr.readonly of
- {readonly, _} ->
- GI = io_lib:format("{~p, oe_tc(~p)}",
- [Get, GetAttrAtom]),
- [GI|FunAcc];
- _ ->
- SetAttrAtom = ic_util:to_atom(Set),
-
- emit(Fd, "oe_tc(~p) -> \n\t~p;\n",
- [SetAttrAtom, SetT]),
- GetGI = io_lib:format("{~p, oe_tc(~p)}",
- [Get, GetAttrAtom]),
- SetGI = io_lib:format("{~p, oe_tc(~p)}",
- [Set, SetAttrAtom]),
- [GetGI, SetGI|FunAcc]
- end
- end, Acc, ic_forms:get_idlist(X)),
- gen_oe_tc2(G, N, Rest, Fd, NewAcc);
-
-gen_oe_tc2(G,N,[_X|Rest], Fd, Acc) ->
- gen_oe_tc2(G,N,Rest, Fd, Acc).
-
-
-gen_oe_tc3(_,_,[],_, Acc) ->
- Acc;
-gen_oe_tc3(G, N, [X|Rest], Fd, Acc) when is_record(X, op) ->
- Function = get_id2(X),
- FunctionAtom = ic_util:to_atom(get_id2(X)),
- GI = io_lib:format("{~p, ~p:oe_tc(~p)}",[Function, N, FunctionAtom]),
- emit(Fd, "oe_tc(~p) -> ~p:oe_tc(~p);\n",
- [FunctionAtom, N, FunctionAtom]),
- gen_oe_tc3(G, N, Rest, Fd, [GI|Acc]);
-
-gen_oe_tc3(G, N, [X|Rest], Fd, Acc) when is_record(X, attr) ->
- NewAcc = lists:foldl(fun(Id, FunAcc) ->
- {Get, Set} = mk_attr_func_names([], get_id(Id)),
- GetAttrAtom = ic_util:to_atom(Get),
- emit(Fd, "oe_tc(~p) -> ~p:oe_tc(~p);\n",
- [GetAttrAtom, N, GetAttrAtom]),
- case X#attr.readonly of
- {readonly, _} ->
- [io_lib:format("{~p, ~p:oe_tc(~p)}",
- [Get, N, GetAttrAtom])|FunAcc];
- _ ->
- SetAttrAtom = ic_util:to_atom(Set),
- emit(Fd, "oe_tc(~p) -> ~p:oe_tc(~p);\n",
- [SetAttrAtom, N, SetAttrAtom]),
- [io_lib:format("{~p, ~p:oe_tc(~p)}",
- [Get, N, GetAttrAtom]),
- io_lib:format("{~p, ~p:oe_tc(~p)}",
- [Set, N, SetAttrAtom])|FunAcc]
- end
- end, Acc, ic_forms:get_idlist(X)),
- gen_oe_tc3(G, N, Rest, Fd, NewAcc);
-
-gen_oe_tc3(G,N,[_X|Rest], Fd, Acc) ->
- gen_oe_tc3(G,N,Rest, Fd, Acc).
-
-gen_calls(G, N, [X|Xs]) when is_record(X, op) ->
- case is_oneway(X) of
- false ->
- {Name, ArgNames, TypeList, OutArgs} = extract_info(G, N, X),
- emit_skel_func(G, N, X, Name, ArgNames, TypeList, OutArgs, false,
- get_opt(G, be)),
- gen_calls(G, N, Xs);
- true ->
- gen_calls(G, N, Xs)
- end;
-
-gen_calls(G, N, [X|Xs]) when is_record(X, attr) ->
- emit_attr(G, N, X, fun emit_skel_func/9),
- gen_calls(G, N, Xs);
-
-gen_calls(G, N, [_X|Xs]) -> gen_calls(G, N, Xs);
-gen_calls(_G, _N, []) -> ok.
-
-gen_casts(G, N, [X|Xs]) when is_record(X, op) ->
- case is_oneway(X) of
- true ->
- {Name, ArgNames, TypeList, OutArgs} = extract_info(G, N, X),
- emit_skel_func(G, N, X, Name, ArgNames, TypeList, OutArgs, true,
- get_opt(G, be)),
- gen_casts(G, N, Xs);
- false ->
- gen_casts(G, N, Xs)
- end;
-
-gen_casts(G, N, [_X|Xs]) -> gen_casts(G, N, Xs);
-gen_casts(_G, _N, []) -> ok.
-
-emit_attr(G, N, X, F) ->
- XX = #id_of{type=X},
- BE = get_opt(G, be),
- {GetType, SetType} = mk_attr_func_types(N, X),
- lists:foreach(fun(Id) ->
- X2 = XX#id_of{id=Id},
- {Get, Set} = mk_attr_func_names(N, get_id(Id)),
- F(G, N, X2, Get, [], GetType, [],
- is_oneway(X2), BE),
- case X#attr.readonly of
- {readonly, _} -> ok;
- _ ->
- F(G, N, X2, Set, [mk_name(G, "Value")],
- SetType, [],
- is_oneway(X2), BE)
- end end, ic_forms:get_idlist(X)).
-
-
-extract_info(G, _N, X) when is_record(X, op) ->
- Name = get_id2(X),
- InArgs = ic:filter_params([in,inout], X#op.params),
- OutArgs = ic:filter_params([out,inout], X#op.params),
- ArgNames = mk_erl_vars(G, InArgs),
- TypeList = {ic_forms:get_tk(X),
- map(fun(Y) -> ic_forms:get_tk(Y) end, InArgs),
- map(fun(Y) -> ic_forms:get_tk(Y) end, OutArgs)
- },
- {Name, ArgNames, TypeList, OutArgs}.
-
-
-
-%% This function generates the standard functions of an object
-%% gen_server
-emit_serv_std(erl_corba, G, N, X) ->
- Fd = ic_genobj:stubfiled(G),
- Impl = ic_genobj:impl(G),
- TypeID = ictk:get_IR_ID(G, N, X),
-
- nl(Fd), nl(Fd), nl(Fd),
- ic_codegen:mcomment(Fd, ["Object server implementation."]),
- nl(Fd), nl(Fd),
- ic_codegen:mcomment(Fd, ["Function for fetching the interface type ID."]),
- nl(Fd),
- emit(Fd, "typeID() ->\n"),
- emit(Fd, " \"~s\".\n", [TypeID]),
- nl(Fd), nl(Fd),
- ic_codegen:mcomment(Fd, ["Object creation functions."]),
- nl(Fd),
- emit(Fd, "oe_create() ->\n"),
- emit(Fd, " corba:create(?MODULE, \"~s\").\n", [TypeID]),
- nl(Fd),
- emit(Fd, "oe_create_link() ->\n"),
- emit(Fd, " corba:create_link(?MODULE, \"~s\").\n", [TypeID]),
- nl(Fd),
- emit(Fd, "oe_create(Env) ->\n"),
- emit(Fd, " corba:create(?MODULE, \"~s\", Env).\n", [TypeID]),
- nl(Fd),
- emit(Fd, "oe_create_link(Env) ->\n"),
- emit(Fd, " corba:create_link(?MODULE, \"~s\", Env).\n", [TypeID]),
- nl(Fd),
- emit(Fd, "oe_create(Env, RegName) ->\n"),
- emit(Fd, " corba:create(?MODULE, \"~s\", Env, RegName).\n", [TypeID]),
- nl(Fd),
- emit(Fd, "oe_create_link(Env, RegName) ->\n"),
- emit(Fd, " corba:create_link(?MODULE, \"~s\", Env, RegName).\n", [TypeID]),
- nl(Fd),
- ic_codegen:mcomment(Fd, ["Init & terminate functions."]),
- nl(Fd),
- emit(Fd, "init(Env) ->\n"),
- ic_codegen:comment(Fd, "Call to implementation init"),
- emit(Fd, " corba:handle_init(~p, Env).\n", [to_atom(Impl)]),
- nl(Fd),
- emit(Fd, "terminate(Reason, State) ->\n"),
- emit(Fd, " corba:handle_terminate(~p, Reason, State).\n",
- [to_atom(Impl)]),
- nl(Fd), nl(Fd),
- Fd;
-emit_serv_std(erl_genserv, G, N, X) ->
- Fd = ic_genobj:stubfiled(G),
- Impl = ic_genobj:impl(G),
- TypeID = ictk:get_IR_ID(G, N, X),
-
- nl(Fd), nl(Fd), nl(Fd),
- ic_codegen:mcomment(Fd, ["Server implementation."]),
- nl(Fd), nl(Fd),
- ic_codegen:mcomment(Fd, ["Function for fetching the interface type ID."]),
- nl(Fd),
- emit(Fd, "typeID() ->\n"),
- emit(Fd, " \"~s\".\n", [TypeID]),
- nl(Fd), nl(Fd),
- ic_codegen:mcomment(Fd, ["Server creation functions."]),
- nl(Fd),
- emit(Fd, "oe_create() ->\n"),
- emit(Fd, " start([], []).\n", []),
- nl(Fd),
- emit(Fd, "oe_create_link() ->\n"),
- emit(Fd, " start_link([], []).\n", []),
- nl(Fd),
- emit(Fd, "oe_create(Env) ->\n"),
- emit(Fd, " start(Env, []).\n", []),
- nl(Fd),
- emit(Fd, "oe_create_link(Env) ->\n"),
- emit(Fd, " start_link(Env, []).\n", []),
- nl(Fd),
- emit(Fd, "oe_create(Env, RegName) ->\n"),
- emit(Fd, " start(RegName, Env, []).\n", []),
- nl(Fd),
- emit(Fd, "oe_create_link(Env, RegName) ->\n"),
- emit(Fd, " start_link(RegName, Env, []).\n", []),
- nl(Fd),
- ic_codegen:mcomment(Fd, ["Start functions."]),
- nl(Fd),
- emit(Fd, "start(Env, Opt) ->\n"),
- emit(Fd, " gen_server:start(?MODULE, Env, Opt).\n"),
- nl(Fd),
- emit(Fd, "start_link(Env, Opt) ->\n"),
- emit(Fd, " gen_server:start_link(?MODULE, Env, Opt).\n"),
- nl(Fd),
- emit(Fd, "start(RegName, Env, Opt) ->\n"),
- emit(Fd, " gen_server:start(RegName, ?MODULE, Env, Opt).\n"),
- nl(Fd),
- emit(Fd, "start_link(RegName, Env, Opt) ->\n"),
- emit(Fd, " gen_server:start_link(RegName, ?MODULE, Env, Opt).\n"),
- nl(Fd),
- ic_codegen:comment(Fd, "Standard gen_server termination"),
- emit(Fd, "stop(OE_THIS) ->\n"),
- emit(Fd, " gen_server:cast(OE_THIS,stop).\n"),
- nl(Fd),
- ic_codegen:comment(Fd, "Call to implementation init"),
- emit(Fd, "init(Env) ->\n"),
- emit(Fd, " ~p:~p(Env).\n", [to_atom(Impl), init]),
- nl(Fd),
- emit(Fd, "terminate(Reason, State) ->\n"),
- emit(Fd, " ~p:~p(Reason, State).\n",
- [to_atom(Impl), terminate]),
- nl(Fd), nl(Fd),
- Fd.
-
-gen_end_of_call(erl_corba, G) ->
- Fd = ic_genobj:stubfiled(G),
- nl(Fd), nl(Fd),
- ic_codegen:mcomment_light(Fd, ["Standard gen_server call handle"]),
- emit(Fd, "handle_call(stop, _, State) ->\n"),
- emit(Fd, " {stop, normal, ok, State}"),
- case get_opt(G, serv_last_call) of
- exception ->
- emit(Fd, ";\n"),
- nl(Fd),
- emit(Fd, "handle_call(_, _, State) ->\n"),
- emit(Fd, " {reply, catch corba:raise(#'BAD_OPERATION'{minor=1163001857, completion_status='COMPLETED_NO'}), State}.\n");
- exit ->
- emit(Fd, ".\n"),
- nl(Fd),
- nl(Fd)
- end,
- ok;
-gen_end_of_call(erl_genserv, G) ->
- Fd = ic_genobj:stubfiled(G),
- nl(Fd), nl(Fd),
- ic_codegen:mcomment_light(Fd, ["Standard gen_server call handle"]),
- emit(Fd, "handle_call(stop, _, State) ->\n"),
- emit(Fd, " {stop, normal, ok, State}"),
- emit(Fd, ".\n"),
- nl(Fd), nl(Fd),
- ok.
-
-gen_end_of_cast(erl_corba, G) ->
- Fd = ic_genobj:stubfiled(G),
- nl(Fd), nl(Fd),
- ic_codegen:mcomment_light(Fd, ["Standard gen_server cast handle"]),
- emit(Fd, "handle_cast(stop, State) ->\n"),
- emit(Fd, " {stop, normal, State}"),
- case get_opt(G, serv_last_call) of
- exception ->
- emit(Fd, ";\n"),
- nl(Fd),
- emit(Fd, "handle_cast(_, State) ->\n"),
- emit(Fd, " {noreply, State}.\n");
- exit ->
- emit(Fd, ".\n"),
- nl(Fd), nl(Fd)
- end,
- ok;
-gen_end_of_cast(erl_genserv, G) ->
- Fd = ic_genobj:stubfiled(G),
- nl(Fd), nl(Fd),
- ic_codegen:mcomment_light(Fd, ["Standard gen_server cast handle"]),
- emit(Fd, "handle_cast(stop, State) ->\n"),
- emit(Fd, " {stop, normal, State}"),
- emit(Fd, ".\n"),
- nl(Fd), nl(Fd),
- ok.
-
-emit_skel_footer(erl_corba, G, N, X) ->
- Fd = ic_genobj:stubfiled(G),
- nl(Fd), nl(Fd),
- ic_codegen:mcomment_light(Fd, ["Standard gen_server handles"]),
- case use_impl_handle_info(G, N, X) of
- true ->
- emit(Fd, "handle_info(Info, State) ->\n"),
- emit(Fd, " corba:handle_info(~p, Info, State).\n\n",
- [list_to_atom(ic_genobj:impl(G))]);
- false ->
- emit(Fd, "handle_info(_, State) ->\n"),
- emit(Fd, " {noreply, State}.\n\n")
- end,
- nl(Fd),
- case get_opt(G, no_codechange) of
- false ->
- emit(Fd, "code_change(OldVsn, State, Extra) ->\n"),
- emit(Fd, " corba:handle_code_change(~p, OldVsn, State, Extra).\n\n",
- [list_to_atom(ic_genobj:impl(G))]);
- true ->
- emit(Fd, "code_change(_, State, _) ->\n"),
- emit(Fd, " {ok, State}.\n\n")
- end,
- ok;
-emit_skel_footer(erl_genserv, G, N, X) ->
- Fd = ic_genobj:stubfiled(G),
- nl(Fd), nl(Fd),
- ic_codegen:mcomment_light(Fd, ["Standard gen_server handles"]),
- case use_impl_handle_info(G, N, X) of
- true ->
- emit(Fd, "handle_info(Info, State) ->\n"),
- emit(Fd, " ~p:handle_info(Info, State).\n\n",
- [list_to_atom(ic_genobj:impl(G))]);
- false ->
- emit(Fd, "handle_info(_, State) ->\n"),
- emit(Fd, " {noreply, State}.\n\n")
- end,
- nl(Fd), nl(Fd),
- case get_opt(G, no_codechange) of
- false ->
- emit(Fd, "code_change(OldVsn, State, Extra) ->\n"),
- emit(Fd, " ~p:code_change(OldVsn, State, Extra).\n\n",
- [list_to_atom(ic_genobj:impl(G))]);
- true ->
- emit(Fd, "code_change(_, State, _) ->\n"),
- emit(Fd, " {ok, State}.\n\n")
- end,
- ok.
-
-
-use_impl_handle_info(G, N, X) ->
- FullName = ic_util:to_colon([get_id2(X) | N]),
- case {get_opt(G, {handle_info, true}), get_opt(G, {handle_info, FullName})} of
- {_, force_false} -> false;
- {false, false} -> false;
- _ -> true
- end.
-
-use_timeout(G, N, _X) ->
- FullName = ic_util:to_colon(N),
- case {get_opt(G, {timeout, true}), get_opt(G, {timeout, FullName})} of
- {_, force_false} -> false;
- {false, false} -> false;
- _ -> true
- end.
-
-use_precond(G, N, X) ->
- FullName = ic_util:to_colon([get_id2(X) | N]),
- case get_opt(G, {precond, FullName}) of
- false ->
- InterfaceName = ic_util:to_colon(N),
- case get_opt(G, {precond, InterfaceName}) of
- false ->
- case get_opt(G, precond) of
- false -> false;
- V2 -> V2
- end;
- V2 -> V2
- end;
- V1 -> V1
- end.
-
-use_postcond(G, N, X) ->
- FullName = ic_util:to_colon([get_id2(X) | N]),
- case get_opt(G, {postcond, FullName}) of
- false ->
- InterfaceName = ic_util:to_colon(N),
- case get_opt(G, {postcond, InterfaceName}) of
- false ->
- case get_opt(G, postcond) of
- false -> false;
- V3 -> V3
- end;
- V2 -> V2
- end;
- V1 -> V1
- end.
-
-
-%%------------------------------------------------------------
-%%
-%% Export stuff
-%%
-%% Gathering of all names that should be exported from a stub
-%% file.
-%%
-
-
-gen_head_special(G, N, X) when is_record(X, interface) ->
- Fd = ic_genobj:stubfiled(G),
-
- foreach(fun({Name, Body}) ->
- ic_codegen:comment(Fd, "Exports from ~p",
- [ic_util:to_colon(Name)]),
- ic_codegen:export(Fd, exp_top(G, N, Body, [], get_opt(G, be))),
- nl(Fd)
- end, X#interface.inherit_body),
-
- ic_codegen:comment(Fd, "Type identification function"),
- ic_codegen:export(Fd, [{typeID, 0}]),
- nl(Fd),
- ic_codegen:comment(Fd, "Used to start server"),
- ic_codegen:export(Fd, [{oe_create, 0}, {oe_create_link, 0}, {oe_create, 1}, {oe_create_link, 1},
- {oe_create, 2}, {oe_create_link, 2}]),
- nl(Fd),
- case get_opt(G, be) of
- erl_corba ->
- ic_codegen:comment(Fd, "TypeCode Functions and inheritance"),
- ic_codegen:export(Fd, [{oe_tc, 1}, {oe_is_a, 1}, {oe_get_interface, 0}]);
- _ ->
- ic_codegen:export(Fd, [{start, 2}, {start_link, 3}])
- end,
- nl(Fd),
- ic_codegen:comment(Fd, "gen server export stuff"),
- emit(Fd, "-behaviour(gen_server).\n"),
-
- case get_opt(G, be) of
- erl_genserv -> %% stop/1 is only for erl_genserv backend
- ic_codegen:export(Fd, [{stop, 1}, {init, 1}, {terminate, 2}, {handle_call, 3},
- {handle_cast, 2}, {handle_info, 2}, {code_change, 3}]);
- _ ->
- ic_codegen:export(Fd, [{init, 1}, {terminate, 2}, {handle_call, 3},
- {handle_cast, 2}, {handle_info, 2}, {code_change, 3}])
- end,
-
- case get_opt(G, be) of
- erl_corba ->
- nl(Fd),
- emit(Fd, "-include_lib(\"~s/include/~s\").\n", [?ORBNAME, ?CORBAHRL]);
- _ ->
- ok
- end,
- nl(Fd), nl(Fd),
- ic_codegen:mcomment(Fd, ["Object interface functions."]),
- nl(Fd), nl(Fd), nl(Fd),
- Fd;
-gen_head_special(_G, _N, _X) -> ok.
-
-
-
-%% Shall generate all export declarations
-gen_head(G, N, X) ->
- case ic_genobj:is_stubfile_open(G) of
- true ->
- F = ic_genobj:stubfiled(G),
- ic_codegen:comment(F, "Interface functions"),
- ic_codegen:export(F, exp_top(G, N, X, [], get_opt(G, be))),
- nl(F),
- gen_head_special(G, N, X);
- false -> ok
- end.
-
-exp_top(_G, _N, X, Acc, _) when element(1, X) == preproc ->
- Acc;
-exp_top(G, N, L, Acc, BE) when is_list(L) ->
- exp_list(G, N, L, Acc, BE);
-exp_top(G, N, M, Acc, BE) when is_record(M, module) ->
- exp_list(G, N, get_body(M), Acc, BE);
-exp_top(G, N, I, Acc, BE) when is_record(I, interface) ->
- exp_list(G, N, get_body(I), Acc, BE);
-exp_top(G, N, X, Acc, BE) ->
- exp3(G, N, X, Acc, BE).
-
-exp3(_G, _N, C, Acc, _BE) when is_record(C, const) ->
- [{get_id(C#const.id), 0} | Acc];
-exp3(_G, _N, Op, Acc, erl_corba) when is_record(Op, op) ->
- FuncName = get_id(Op#op.id),
- Arity = length(ic:filter_params([in, inout], Op#op.params)) + 1,
- [{FuncName, Arity}, {FuncName, Arity+1} | Acc];
-exp3(G, N, Op, Acc, _BE) when is_record(Op, op) ->
- FuncName = get_id(Op#op.id),
- Arity =
- case use_timeout(G,N,Op) of
- true ->
- %% NO TimeOut on ONEWAYS here !!!!
- case is_oneway(Op) of
- true ->
- length(ic:filter_params([in, inout], Op#op.params)) + 1;
- false ->
- length(ic:filter_params([in, inout], Op#op.params)) + 2
- end;
- false ->
- length(ic:filter_params([in, inout], Op#op.params)) + 1
- end,
- [{FuncName, Arity} | Acc];
-
-exp3(_G, _N, A, Acc, erl_corba) when is_record(A, attr) ->
- lists:foldr(fun(Id, Acc2) ->
- {Get, Set} = mk_attr_func_names([], get_id(Id)),
- case A#attr.readonly of
- {readonly, _} -> [{Get, 1}, {Get, 2} | Acc2];
- _ -> [{Get, 1}, {Get, 2},
- {Set, 2}, {Set, 3} | Acc2]
- end end, Acc, ic_forms:get_idlist(A));
-exp3(_G, _N, A, Acc, _BE) when is_record(A, attr) ->
- lists:foldr(fun(Id, Acc2) ->
- {Get, Set} = mk_attr_func_names([], get_id(Id)),
- case A#attr.readonly of
- {readonly, _} -> [{Get, 1} | Acc2];
- _ -> [{Get, 1}, {Set, 2} | Acc2]
- end end, Acc, ic_forms:get_idlist(A));
-
-exp3(_G, _N, _X, Acc, _BE) -> Acc.
-
-exp_list(G, N, L, OrigAcc, BE) ->
- lists:foldr(fun(X, Acc) -> exp3(G, N, X, Acc, BE) end, OrigAcc, L).
-
-
-
-
-%%------------------------------------------------------------
-%%
-%% Emit stuff
-%%
-%% Low level generation primitives
-%%
-
-emit_stub_func(G, N, X, Name, ArgNames, _TypeList, OutArgs, Oneway, Backend) ->
- case ic_genobj:is_stubfile_open(G) of
- false ->
- ok;
- true ->
- Fd = ic_genobj:stubfiled(G),
- StubName = list_to_atom(Name),
- UsingTimeout = use_timeout(G, N, X),
- Timeout = case UsingTimeout of
- true ->
- mk_name(G, "Timeout");
- false ->
- "infinity"
- end,
- Options = mk_name(G, "Options"),
- This = mk_name(G, "THIS"),
- CallOrCast =
- case is_oneway(X) of
- true -> ?CAST;
- _ -> ?CALL
- end,
- emit_op_comment(G, Fd, X, StubName, ArgNames, OutArgs),
- case Backend of
- erl_corba ->
- emit(Fd, "~p(~s) ->\n",
- [StubName, mk_list([This | ArgNames])]),
- emit(Fd, " ~s:~s(~s, ~p, [~s], ?MODULE).\n\n",
- [?CORBAMOD, CallOrCast, This, StubName, mk_list(ArgNames)]),
- emit(Fd, "~p(~s) ->\n",
- [StubName, mk_list([This, Options| ArgNames])]),
- emit(Fd, " ~s:~s(~s, ~p, [~s], ?MODULE, ~s).\n\n",
- [?CORBAMOD, CallOrCast, This, StubName, mk_list(ArgNames),
- Options]);
- _ ->
- FunName = case ic_options:get_opt(G, scoped_op_calls) of
- true ->
- list_to_atom(ic_util:to_undersc([Name | N]));
- false ->
- StubName
- end,
- %% NO TimeOut on ONEWAYS here !!!!
- case Oneway of
- true ->
- emit(Fd, "~p(~s) ->\n",
- [StubName, mk_list([This | ArgNames])]);
- false ->
- case UsingTimeout of
- true ->
- emit(Fd, "~p(~s) ->\n",
- [StubName, mk_list([This, Timeout| ArgNames])]);
- false ->
- emit(Fd, "~p(~s) ->\n",
- [StubName, mk_list([This | ArgNames])])
- end
- end,
-
- %% NO TimeOut on ONEWAYS here !!!!
- if
- length(ArgNames) == 0 ->
- case is_oneway(X) of
- true ->
- emit(Fd, " ~s:~s(~s, ~p).\n\n",
- [?GENSERVMOD, CallOrCast, This, FunName]);
- false ->
- emit(Fd, " ~s:~s(~s, ~p, ~s).\n\n",
- [?GENSERVMOD, CallOrCast, This, FunName, Timeout])
- end;
- true ->
- case is_oneway(X) of
- true ->
- emit(Fd, " ~s:~s(~s, {~p, ~s}).\n\n",
- [?GENSERVMOD, CallOrCast, This, FunName,
- mk_list(ArgNames)]);
- false ->
- emit(Fd, " ~s:~s(~s, {~p, ~s}, ~s).\n\n",
- [?GENSERVMOD, CallOrCast, This, FunName,
- mk_list(ArgNames), Timeout])
- end
- end
- end
- end.
-
-emit_skel_func(G, N, X, OpName, ArgNames, TypeList, OutArgs, Oneway, Backend) ->
- case ic_genobj:is_stubfile_open(G) of
- false ->
- ok;
- true ->
- emit_skel_func_helper(G, N, X, OpName, ArgNames, TypeList, OutArgs,
- Oneway, Backend)
- end.
-
-emit_skel_func_helper(G, N, X, OpName, ArgNames, _TypeList, OutArgs, Oneway,
- erl_corba) ->
- Fd = ic_genobj:stubfiled(G),
- Name = list_to_atom(OpName),
- ImplF = Name,
- ImplM = list_to_atom(ic_genobj:impl(G)),
- ThisStr = mk_name(G, "THIS"),
- FromStr = mk_name(G, "From"),
- State = mk_name(G, "State"),
- Context = mk_name(G, "Context"),
-
- {UseFrom, From} =
- case Oneway of
- false ->
- case use_from(G, N, OpName) of
- true ->
- {FromStr, FromStr};
- false ->
- {"false", "_"}
- end;
- true ->
- {"false", "_"}
- end,
- {UseThis, This} =
- case use_this(G, N, OpName) of
- true ->
- {ThisStr, ThisStr};
- false ->
- {"false", "_"}
- end,
- %% Create argument list string
- CallArgs = mk_list(ArgNames),
- emit_op_comment(G, Fd, X, Name, ArgNames, OutArgs),
-
- %% Check if pre and post conditions are specified for this operation
- Precond = use_precond(G, N, X),
- Postcond = use_postcond(G, N, X),
-
- case Oneway of
- true ->
- emit(Fd, "handle_cast({~s, ~s, ~p, [~s]}, ~s) ->\n",
- [This, Context, Name, CallArgs, State]),
- case {Precond, Postcond} of
- {false, false} ->
- emit(Fd, " corba:handle_cast(~p, ~p, [~s], ~s, ~s, ~s);\n\n",
- [ImplM, ImplF, CallArgs, State, Context, UseThis]);
- _ ->
- emit(Fd, " corba:handle_cast(~p, ~p, [~s], ~s, ~s, ~s, ~p, ~p, ?MODULE);\n\n",
- [ImplM, ImplF, CallArgs, State, Context, UseThis,
- Precond, Precond])
- end;
- false ->
- emit(Fd, "handle_call({~s, ~s, ~p, [~s]}, ~s, ~s) ->\n",
- [This, Context, Name, CallArgs, From, State]),
- case {Precond, Postcond} of
- {false, false} ->
- emit(Fd, " corba:handle_call(~p, ~p, [~s], ~s, ~s, ~s, ~s);\n\n",
- [ImplM, ImplF, CallArgs, State, Context, UseThis, UseFrom]);
- _->
- emit(Fd, " corba:handle_call(~p, ~p, [~s], ~s, ~s, ~s, ~s, ~p, ~p, ?MODULE);\n\n",
- [ImplM, ImplF, CallArgs, State, Context, UseThis, UseFrom,
- Precond, Postcond])
- end
- end;
-emit_skel_func_helper(G, N, X, OpName, ArgNames, _TypeList, OutArgs, Oneway,
- _Backend) ->
- Fd = ic_genobj:stubfiled(G),
- Name = list_to_atom(OpName),
- ImplF = Name,
- ImplM = list_to_atom(ic_genobj:impl(G)),
- FromStr = mk_name(G, "From"),
- State = mk_name(G, "State"),
-
- %% Create argument list
- CallArgs1 = [State | ArgNames],
- {CallArgs2, From} =
- case is_oneway(X) of
- false ->
- case use_from(G, N, OpName) of
- true ->
- {[FromStr | CallArgs1], FromStr};
- false ->
- {CallArgs1, "_"}
- end;
- true ->
- {CallArgs1, "_"}
- end,
- %% Create argument list string
- CallArgs = mk_list(CallArgs2),
- emit_op_comment(G, Fd, X, Name, ArgNames, OutArgs),
- FunName = case ic_options:get_opt(G, scoped_op_calls) of
- true ->
- list_to_atom(ic_util:to_undersc([OpName | N]));
- false ->
- list_to_atom(OpName)
- end,
- case Oneway of
- true ->
- if
- length(ArgNames) == 0 ->
- emit(Fd, "handle_cast(~p, ~s) ->\n", [FunName, State]);
- true ->
- emit(Fd, "handle_cast({~p, ~s}, ~s) ->\n",
- [FunName, mk_list(ArgNames), State])
- end,
- emit(Fd, " ~p:~p(~s);\n\n", [ImplM, ImplF, CallArgs]);
- false ->
- if
- length(ArgNames) == 0 ->
- emit(Fd, "handle_call(~p, ~s, ~s) ->\n",
- [FunName, From, State]);
- true ->
- emit(Fd, "handle_call({~p, ~s}, ~s, ~s) ->\n",
- [FunName, mk_list(ArgNames), From, State])
- end,
- emit(Fd, " ~p:~p(~s);\n\n", [ImplM, ImplF, CallArgs])
- end.
-
-use_this(G, N, OpName) ->
- FullOp = ic_util:to_colon([OpName|N]),
- FullIntf = ic_util:to_colon(N),
- case {get_opt(G, {this, FullIntf}), get_opt(G, {this, FullOp}),
- get_opt(G, {this, true})} of
- {_, force_false, _} -> false;
- {force_false, false, _} -> false;
- {false, false, false} -> false;
- _ -> true
- end.
-
-use_from(G, N, OpName) ->
- FullOp = ic_util:to_colon([OpName|N]),
- FullIntf = ic_util:to_colon(N),
- case {get_opt(G, {from, FullIntf}), get_opt(G, {from, FullOp}),
- get_opt(G, {from, true})} of
- {_, force_false, _} -> false;
- {force_false, false, _} -> false;
- {false, false, false} -> false;
- _ -> true
- end.
-
-
-emit_constant_func(G, Id, Val) ->
- case ic_genobj:is_stubfile_open(G) of
- false -> ok;
- true ->
- Fd = ic_genobj:stubfiled(G),
- N = list_to_atom(get_id(Id)),
- emit_const_comment(G, Fd, Id, N),
- emit(Fd, "~p() -> ~p.\n\n", [N, Val])
- end.
-
-
-
-emit_const_comment(_G, F, _X, Name) ->
- ic_codegen:mcomment_light(F,
- [io_lib:format("Constant: ~p", [Name])]).
-
-
-emit_op_comment(G, F, X, Name, InP, OutP) ->
- ic_codegen:mcomment_light(F,
- [io_lib:format("~s: ~p", [get_title(X), Name]),
- "",
- get_returns(G, X, InP, OutP) |
- get_raises(X)]).
-
-get_title(X) when is_record(X, attr) -> "Attribute Operation";
-get_title(_X) -> "Operation".
-
-get_raises(X) when is_record(X, op) ->
- if X#op.raises == [] -> [];
- true ->
- [" Raises: " ++
- mk_list(lists:map(fun(E) -> ic_util:to_colon(E) end,
- X#op.raises))]
- end;
-get_raises(_X) -> [].
-
-get_returns(_G, _X, _InP, []) ->
- " Returns: RetVal";
-get_returns(G, _X, _InP, OutP) ->
- " Returns: "++mk_list(["RetVal" | mk_erl_vars(G, OutP)]).
-
-
-
-
-%%------------------------------------------------------------
-%%
-%% Utilities
-%%
-%% Convenient little go-get functions
-%%
-%%------------------------------------------------------------
-
-%% The automaticly generated get and set operation names for an
-%% attribute.
-mk_attr_func_names(_Scope, Name) ->
- {"_get_" ++ Name, "_set_" ++ Name}.
-%% {scoped_name(Scope, "_get_"++Name), scoped_name(Scope, "_set_"++Name)}.
-
-%% Returns TK of the Get and Set attribute functions.
-mk_attr_func_types(_N, X) ->
- TK = ic_forms:get_tk(X),
- {{TK, [], []}, {tk_void, [TK], []}}.
-
-
-
-%%------------------------------------------------------------
-%%
-%% Generation utilities and common stuff
-%%
-%% Convenient stuff for generation
-%%
-%%------------------------------------------------------------
-
-
-%% Input is a list of parameters (in parse form) and output is a list
-%% of capitalised variable names. mk_var is in icgen
-mk_erl_vars(_G, Params) ->
- map(fun(P) -> mk_var(get_id(P#param.id)) end, Params).
-
-
-%% mk_list produces a nice comma separated string of variable names
-mk_list([]) -> [];
-mk_list([Arg | Args]) ->
- Arg ++ mk_list2(Args).
-mk_list2([Arg | Args]) ->
- ", " ++ Arg ++ mk_list2(Args);
-mk_list2([]) -> [].
-
-
-%%------------------------------------------------------------
-%%
-%% Parser utilities
-%%
-%% Called from the yecc parser. Expands the identifier list of an
-%% attribute so that the attribute generator never has to handle
-%% lists.
-%%
-%%------------------------------------------------------------
-
-
-%% Unfold identifier lists or nested lists. Note that many records
-%% contain an entry named id that is a list before unfold and a single
-%% id afterwards.
-unfold(L) when is_list(L) ->
- lists:flatten(map(fun(X) -> unfold2(X) end, L));
-unfold(X) -> unfold2(X).
-
-unfold2(A) when is_record(A, attr) ->
- map(fun(Id) -> A#attr{id=Id} end, A#attr.id);
-unfold2(M) when is_record(M, member) ->
- map(fun(Id) -> M#member{id=Id} end, M#member.id);
-unfold2(M) when is_record(M, case_dcl) ->
- map(fun(Id) -> M#case_dcl{label=Id} end, M#case_dcl.label);
-unfold2(T) when is_record(T, typedef) ->
- map(fun(Id) -> T#typedef{id=Id} end, T#typedef.id).
-
-
-
-
-%% Code produce for dependency function
-genDependency(G) ->
- Fd = ic_genobj:stubfiled(G),
- nl(Fd),nl(Fd),
- ic_codegen:comment(Fd, "Idl file dependency list function"),
- emit(Fd, "oe_dependency() ->\n\n", []),
- emit(Fd, " ~p.\n\n", [ic_pragma:get_dependencies(G)]).
diff --git a/lib/ic/src/ic_error.erl b/lib/ic/src/ic_error.erl
deleted file mode 100644
index 790e1f0539..0000000000
--- a/lib/ic/src/ic_error.erl
+++ /dev/null
@@ -1,376 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ic_error).
-
--include_lib("ic/src/ic.hrl").
--include_lib("ic/src/ic_debug.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([error/2,
- fatal_error/2,
- init_errors/1,
- return/1,
- warn/2,
- get_error_count/1]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-
-%%--------------------------------------------------------------------
-%%
-%% Error and warning utilities.
-%%
-%% Note that errors are somewhat brutal and that warnings are kept in
-%% a list for the user to extract at a later stage. The handling of
-%% warnings is entirely up to the user while handling of errors is
-%% never left to the user.
-%%
-%%--------------------------------------------------------------------
-
-return(G) ->
- case ic_options:get_opt(G, silent2) of
- true ->
- case get_error_count(G) of
- 0 -> {ok, get_list(G, warn_list)};
- _X -> {error, get_list(G, warn_list), get_list(G, error_list)}
- end;
- false ->
- case get_error_count(G) of
- 0 -> ok;
- X -> print_error(G, {error, g, ic_genobj:idlfile(G), {error_count, X}}),
- error
- end
- end.
-
-
-get_list(G, ListName) ->
- ?lookup(G#genobj.options, ListName).
-
-
-%% Public function for reporting an error
-error(G, Err) ->
- Error = {error, g, ic_genobj:idlfile(G), Err},
- case insert_in_list(G, Error, error_list) of
- new ->
- print_error(G, Error),
- MaxErrs = ic_options:get_opt(G, maxerrs),
- case incr_counter(G, error_count) of
- X when X >= MaxErrs ->
- fatal_error(G, {error_count_exceeded, X});
- _ -> Error
- end;
- old ->
- Error
- end.
-
-%% Public function for reporting an error. NOTE: also stops execution
-fatal_error(G, Err) ->
- Error = {error, g, ic_genobj:idlfile(G), Err},
- insert_in_list(G, Error, error_list),
- incr_counter(G, error_count),
- print_error(G, Error),
- throw(Error).
-
-
-%% Public function for reporting a warning
-warn(G, Warn) ->
- Warning = {warn, g, ic_genobj:idlfile(G), Warn},
- case insert_in_list(G, Warning, warn_list) of
- new ->
- print_warn(G, Warning),
- MaxErrs = ic_options:get_opt(G, maxwarns),
- case incr_counter(G, warn_count) of
- X when X >= MaxErrs ->
- fatal_error(G, {warn_count_exceeded, X});
- _ -> ok
- end;
- old -> ok
-end.
-
-
-%% Initialisation of all counters and lists associated with errors and
-%% warnings.
-init_errors(G) ->
- reset_counter(G, error_count),
- reset_counter(G, warn_count),
- reset_list(G, error_list),
- reset_list(G, warn_list),
- ok.
-
-
-
-%%--------------------------------------------------------------------
-%% Counter and list (warn and error) handling
-%%
-
-incr_counter(G, Counter) ->
- Num = ?lookup(G#genobj.options, Counter) + 1,
- ?insert(G#genobj.options, Counter, Num),
- Num.
-
-reset_counter(G, Counter) ->
- ?insert(G#genobj.options, Counter, 0).
-
-get_error_count(G) ->
- ?lookup(G#genobj.options, error_count).
-
-reset_list(G, ListName) ->
- ?insert(G#genobj.options, ListName, []).
-
-insert_in_list(G, Item, ListName) ->
- List = ?lookup(G#genobj.options, ListName),
- case lists:member(Item, List) of
- true -> old;
- false ->
- ?insert(G#genobj.options, ListName, [Item| List]),
- new
- end.
-
-
-%%--------------------------------------------------------------------
-%%
-%% Nice printouts of errors and warnings
-%%
-
-
-%% Errors
-
-print_error(G, Error) ->
- case {ic_options:get_opt(G, silent), ic_options:get_opt(G, silent2)} of
- {true, _} -> ok;
- {_, true} -> ok;
- _ -> format_error(Error)
- end,
- error.
-
-format_error({error, _, File, {parse_error, Line, Args}}) ->
- Fmt = lists:foldl(fun(_, Acc) -> [$~, $s | Acc] end, [], Args),
- display(File, Line, Fmt, Args);
-format_error({error, _, File, {error_count, X}}) ->
- display(File, "~p errors found", [X]);
-format_error({error, _, File, {error_count_exceeded, X}}) ->
- display(File, "too many errors found (~p)", [X]);
-format_error({error, _, File, {warn_count_exceeded, X}}) ->
- display(File, "too many warnings found (~p)", [X]);
-format_error({error, _, File, {inherit_name_collision,
- {Orig, Item}, {Base, NewItem}}}) ->
- display(File, ic_forms:get_line(Item), "~s collides with ~s",
- [pp([ic_forms:get_id2(Item) | Orig]), pp([ic_forms:get_id2(NewItem) | Base])]);
-format_error({error, _, File, {unsupported_op, {'~', Line}}}) ->
- display(File, Line, "unsupported unary operation ~~", []);
-format_error({error, _, File, {multiply_defined, X}}) ->
- display(File, ic_forms:get_line(X), "multiple defined identifier ~p", [ic_forms:get_id2(X)]);
-format_error({error, _, File, {illegal_spelling, X}}) ->
- display(File, ic_forms:get_line(X),
-% "illegal spelling of identifier ~s (capitalisation?)",
- "identifier ~p multiply declared - differs in case only",
- [ic_forms:get_id2(X)]);
-format_error({error, _, File, {illegal_enumerant_value, X}}) ->
- display(File, ic_forms:get_line(X),
- "Enumerant ~s's value collide by name with other type",
- [ic_forms:get_id2(X)]);
-format_error({error, _, File, {illegal_forward, X}}) ->
- display(File, ic_forms:get_line(X),
- "cannot inherit from forwarded interface ~s", [ic_forms:get_id2(X)]);
-format_error({error, _, File, {illegal_const_t, X, Type}}) ->
- display(File, ic_forms:get_line(X),
- "Illegal constant type ~s of ~s", [pp(Type), ic_forms:get_id2(X)]);
-format_error({error, _, File, {multiple_cases, X}}) ->
- display(File, ic_forms:get_line(X), "multiple case values ~s", [pp(X)]);
-format_error({error, _, File, {symtab_not_found, X}}) ->
- display(File, ic_forms:get_line(X), "undeclared identifier ~s", [ic_forms:get_id2(X)]);
-format_error({error, _, File, {preproc, Lines}}) ->
- display(File, "preprocessor error: ~s", [hd(Lines)]);
-format_error({error, _, File, {ic_pp_error, Lines}}) ->
- display(File, "preprocessor error: ~s", [Lines]);
-format_error({error, _, File, {illegal_float, Line}}) ->
- display(File, Line, "illegal floating point number", []);
-format_error({error, _, File, {bad_type_combination, E, V1, V2}}) ->
- display(File, ic_forms:get_line(E), "incompatible types, ~p and ~p", [V1, V2]);
-format_error({error, _, File, {bad_oneway_type, X, _TK}}) ->
- display(File, ic_forms:get_line(X), "oneway operations must be declared void", []);
-format_error({error, _, File, {inout_spec_for_c, X, Arg}}) ->
- display(File, ic_forms:get_line(X), "inout parameter ~s specified in native c mode",
- [Arg]);
-format_error({error, _, File, {sequence_not_defined, X, Arg}}) ->
- display(File, ic_forms:get_line(X), "sequence ~s not defined", [Arg]);
-format_error({error, _, File, {illegal_typecode_for_c, Arg}}) ->
- display(File, not_specified, "illegal typecode ~s used in native c mode",
- [Arg]);
-format_error({error, _, File, {name_not_found, N}}) ->
- display(File, not_specified, "name ~s not found", [N]);
-format_error({error, _, File, {illegal_typecode_for_c, Arg, N}}) ->
- display(File, not_specified, "illegal typecode ~p used for ~p in native c mode", [Arg, N]);
-format_error({error, _, File, {oneway_outparams, X}}) ->
- display(File, ic_forms:get_line(X),
- "oneway operations may not have out or inout parameters", []);
-format_error({error, _, File, {oneway_raises, X}}) ->
- display(File, ic_forms:get_line(X), "oneway operations may not raise exceptions",
- []);
-format_error({error, _, File, {bad_tk_match, T, TK, V}}) ->
- display(File, ic_forms:get_line(T),
- "value ~p does not match declared type ~s", [V, pp(TK)]);
-format_error({error, _, File, {bad_scope_enum_case, ScopedId}}) ->
- display(File, ic_forms:get_line(ScopedId),
- "scoped enum identifiers not allowed as case (~s)",
- [pp(ScopedId)]);
-format_error({error, _, File, {bad_type, Expr, Op, _TypeList, V}}) ->
- display(File, ic_forms:get_line(Expr),
- "parameter value ~p to ~s is of illegal type", [V, pp(Op)]);
-format_error({error, _, File, {bad_case_type, TK, X, Val}}) ->
- display(File, ic_forms:get_line(X),
- "case value ~s does not match discriminator type ~s",
- [case_pp(X, Val), pp(TK)]);
-format_error({error, _, File, {tk_not_found, X}}) ->
- display(File, ic_forms:get_line(X), "undeclared identifier ~s", [pp(X)]);
-%%% New format_errors
-format_error({error, _, File, {bad_fixed, Format, Args, Line}}) ->
- display(File, Line, Format, Args);
-format_error({error, _, File, {illegal_switch_t, Arg, _N}}) ->
- display(File, ic_forms:get_line(Arg), "illegal switch", []);
-format_error({error, _, File, {inherit_resolve, Arg, N}}) ->
- display(File, ic_forms:get_line(Arg), "cannot resolve ~s", [N]);
-format_error({error, _, File, {bad_escape_character, Line, Char}}) ->
- display(File, Line, "bad escape character \"~c\"", [Char]);
-format_error({error, _, File, {pragma_code_opt_bad_option_list, Line}}) ->
- display(File, Line, "bad option list on pragma \"CODEOPT\"", []);
-format_error({error, _, File, {bad_string, Line}}) ->
- display(File, Line, "bad string", []);
-format_error({error, _, File, {create_dir, Path, Reason}}) ->
- display(File, not_specified, "couldn't create directory ~p due to ~p", [Path, Reason]);
-format_error({error, _, File, {open_file, Path, Reason}}) ->
- display(File, not_specified, "couldn't open ~p due to ~p", [Path, Reason]);
-format_error({error, _, File, {plain_error_string, ErrString}}) ->
- display(File, not_specified, "~s", [ErrString]);
-format_error({error, _, File, {plain_error_string, T, ErrString}}) ->
- display(File, ic_forms:get_line(T), "~s", [ErrString]);
-format_error({error, _, File, {ErrString, Line}}) ->
- display(File, Line, ErrString, []).
-
-
-%% Warnings
-print_warn(G, Warn) ->
- case {ic_options:get_opt(G, silent), ic_options:get_opt(G, silent2)} of
- {true, _} -> ok;
- {_, true} -> ok;
- _ -> format_warn(Warn)
- end.
-
-format_warn({warn, _, File, {ic_pp_warning, Lines}}) ->
- display(File, "preprocessor warning: ~s", [Lines]);
-format_warn({warn, _, _File, {cfg_open, _Reason, File}}) ->
- display(File, "warning: could not open file: ~p", [File]);
-format_warn({warn, _, _File, {cfg_read, File}}) ->
- display(File, "warning: syntax error in configuration file", []);
-format_warn({warn, _, File, {multi_modules, Id}}) ->
- display(File, ic_forms:get_line(Id), "warning: multiple modules in file", []);
-format_warn({warn, _, File, {illegal_opt, Opt}}) ->
- display(File, "warning: unrecognised option: ~p", [Opt]);
-format_warn({warn, _, File, {nested_mod, Id}}) ->
- display(File, ic_forms:get_line(Id), "warning: nested module: ~s", [ic_forms:get_id(Id)]);
-format_warn({warn, _, File, {inherit_name_shadow, {Orig, Item},
- {Base, NewItem}}}) ->
- display(File, ic_forms:get_line(Item),
- "warning: ~s shadows ~s", [pp([ic_forms:get_id2(Item) | Orig]),
- pp([ic_forms:get_id2(NewItem) | Base])]);
-format_warn({warn, _, File, {internal_307, X, Y}}) ->
- %% If global Scope variable is not [] at top level constant
- display(File, ic_forms:get_line(X), "warning: internal 307: ~p ~p", [X, Y]);
-format_warn({warn, _, File, {WarnString, Line}}) ->
- display(File, Line, WarnString, []).
-
-%% Display an error or warning
-display(File, not_specified, F, A) ->
- io:format("~p : ~s~n", [File, io_lib:format(F, A)]);
-display(File, Line, F, A) ->
- io:format("~p on line ~p: ~s~n", [File, Line, io_lib:format(F, A)]).
-display(File, F, A) ->
- io:format("~p: ~s~n", [File, io_lib:format(F, A)]).
-
-
-
-%%format_warn2(G, WarnStr) ->
-%% case {ic_options:get_opt(G, silent), ic_options:get_opt(G, silent2),
-%% ic_options:get_opt(G, nowarn)} of
-%% {false, false, false} ->
-%% io:format("~p: warning: ~s~n", [ic_genobj:idlfile(G), WarnStr]);
-%% _ -> ok
-%% end.
-
-%%format_warn2(G, Line, WarnStr) ->
-%% case {ic_options:get_opt(G, silent), ic_options:get_opt(G, silent2),
-%% ic_options:get_opt(G, nowarn)} of
-%% {false, false, false} ->
-%% io:format("~p on line ~p: warning: ~s~n",
-%% [ic_genobj:idlfile(G), Line, WarnStr]);
-%% _ -> ok
-%% end.
-
-
-
-
-%% pretty print various stuff
-
-pp({tk_string, _}) -> "string";
-pp({tk_wstring, _}) -> "wstring";
-pp(tk_long) -> "long";
-pp(tk_short) -> "short";
-pp(tk_ushort) -> "unsigned short";
-pp(tk_ulong) -> "unsigned long";
-pp(tk_float) -> "float";
-pp(tk_double) -> "double";
-pp(tk_boolean) -> "boolean";
-pp(tk_char) -> "char";
-pp(tk_wchar) -> "wchar";
-pp(tk_octet) -> "octet";
-pp(tk_null) -> "null";
-pp(tk_void) -> "void";
-pp(tk_any) -> "any";
-pp({tk_fixed, _, _}) -> "fixed";
-pp({tk_objref, _, _}) -> "object reference";
-pp(rshift) -> ">>";
-pp(lshift) -> "<<";
-pp(X) when element(1, X) == tk_enum -> "enum";
-pp(X) when is_record(X, scoped_id) -> ic_util:to_colon(X);
-pp(X) when element(1, X) == '<identifier>' -> ic_forms:get_id(X);
-pp(X) when is_list(X) andalso is_list(hd(X)) -> ic_util:to_colon(X);
-pp({_, Num, Beef}) when is_integer(Num) -> Beef;
-pp({Beef, Num}) when is_integer(Num) -> ic_util:to_list(Beef);
-pp(X) -> ic_util:to_list(X).
-
-%% special treatment of case label names
-case_pp(X, _Val) when is_record(X, scoped_id) -> pp(X);
-case_pp(_X, Val) -> pp(Val).
-
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
diff --git a/lib/ic/src/ic_fetch.erl b/lib/ic/src/ic_fetch.erl
deleted file mode 100644
index 59f21711ec..0000000000
--- a/lib/ic/src/ic_fetch.erl
+++ /dev/null
@@ -1,389 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ic_fetch).
-
--include("icforms.hrl").
-
--export([member2type/3]).
-
--export([fetchTk/3, isArray/3, isBasicType/1, isBasicType/2,
- isBasicType/3, isBasicTypeOrEterm/3, isEterm/3, isString/3,
- isStruct/3, isUnion/3, name2type/2, searchIncludedTk/2,
- searchInsideTks/2, searchTk/2, searchTk/3]).
-
-name2type(G, Name) ->
- S = ic_genobj:tktab(G),
- ScopedName = lists:reverse(string:tokens(Name,"_")),
- InfoList = ets:lookup( S, ScopedName ),
- filter( InfoList ).
-
-
-
-%% This is en overloaded function,
-%% differs in input on unions
-member2type(_G, X, I) when is_record(X, union)->
- Name = ic_forms:get_id2(I),
- case lists:keysearch(Name,2,element(6,X#union.tk)) of
- false ->
- error;
- {value,Rec} ->
- fetchType(element(3,Rec))
- end;
-member2type( G, SName, MName ) ->
-
- S = ic_genobj:tktab( G ),
- SNList = lists:reverse(string:tokens(SName,"_")),
- ScopedName = [MName | SNList],
- InfoList = ets:lookup( S, ScopedName ),
-
- case filter( InfoList ) of
- error ->
- %% Try a little harder, seeking inside tktab
- case lookup_member_type_in_tktab(S, ScopedName, MName) of
- error ->
- %% Check if this is the "return to return1" case
- case MName of
- "return1" ->
- %% Do it all over again !
- ScopedName2 = ["return" | SNList],
- InfoList2 = ets:lookup( S, ScopedName2 ),
- case filter( InfoList2 ) of
- error ->
- %% Last resort: seek in pragma table
- lookup_type_in_pragmatab(G, SName);
-
- Other ->
- Other
- end;
- _ ->
- %% Last resort: seek in pragma table
- lookup_type_in_pragmatab(G, SName)
- end;
- Other ->
- Other
- end;
- Other ->
- Other
- end.
-
-
-lookup_member_type_in_tktab(S, ScopedName, MName) ->
- case ets:match_object(S, {'_',member,{MName,'_'},nil}) of
- [] ->
- error;
- [{_FullScopedName,member,{MName,TKInfo},nil}]->
- fetchType( TKInfo );
- List ->
- lookup_member_type_in_tktab(List,ScopedName)
- end.
-
-lookup_member_type_in_tktab([],_ScopedName) ->
- error;
-lookup_member_type_in_tktab([{FullScopedName,_,{_,TKInfo},_}|Rest],ScopedName) ->
- case lists:reverse(string:tokens(ic_util:to_undersc(FullScopedName),"_")) of
- ScopedName ->
- fetchType(TKInfo);
- _ ->
- lookup_member_type_in_tktab(Rest,ScopedName)
- end.
-
-
-lookup_type_in_pragmatab(G, SName) ->
- S = ic_genobj:pragmatab(G),
-
- %% Look locally first
- case ets:match(S,{file_data_local,'_','_','$2','_','_',SName,'_','_'}) of
- [] ->
- %% No match, seek included
- case ets:match(S,{file_data_included,'_','_','$2','_','_',SName,'_','_'}) of
-
- [] ->
- error;
- [[Type]] ->
- io:format("1 Found(~p) : ~p~n",[SName,Type]),
- Type
- end;
-
- [[Type]] ->
- io:format("2 Found(~p) : ~p~n",[SName,Type]),
- Type
- end.
-
-
-
-
-filter( [] ) ->
- error;
-filter( [I | Is ] ) ->
- case I of
- { _, member, { _, TKINFO }, _ } ->
- fetchType( TKINFO );
-
- { _, struct, _, _ } ->
- struct;
-
- { _, typedef, TKINFO, _ } ->
- fetchType( TKINFO );
-
- { _, module, _, _ } ->
- module;
-
- { _, interface, _, _ } ->
- interface;
-
- { _, op, _, _ } ->
- op;
-
- { _,enum, _, _ } ->
- enum;
-
- { _, spellcheck } ->
- filter( Is );
-
- _ ->
- error
- end.
-
-
-fetchType( { tk_sequence, _, _ } ) ->
- sequence;
-fetchType( { tk_array, _, _ } ) ->
- array;
-fetchType( { tk_struct, _, _, _} ) ->
- struct;
-fetchType( { tk_string, _} ) ->
- string;
-fetchType( tk_short ) ->
- short;
-fetchType( tk_long ) ->
- long;
-fetchType( tk_ushort ) ->
- ushort;
-fetchType( tk_ulong ) ->
- ulong;
-fetchType( tk_float ) ->
- float;
-fetchType( tk_double ) ->
- double;
-fetchType( tk_boolean ) ->
- boolean;
-fetchType( tk_char ) ->
- char;
-fetchType( tk_octet ) ->
- octet;
-fetchType( { tk_enum, _, _, _ } ) ->
- enum;
-fetchType( { tk_union, _, _, _, _, _ } ) ->
- union;
-fetchType( tk_any ) ->
- any;
-fetchType( _ ) ->
- error.
-
-isBasicTypeOrEterm(G, N, S) ->
- case isBasicType(G, N, S) of
- true ->
- true;
- false ->
- isEterm(G, N, S)
- end.
-
-
-isEterm(G, N, S) when element(1, S) == scoped_id ->
- {FullScopedName, _, _TK, _} = ic_symtab:get_full_scoped_name(G, N, S),
- case ic_code:get_basetype(G, ic_util:to_undersc(FullScopedName)) of
- "erlang_term" ->
- true;
- "ETERM*" ->
- true;
- _X ->
- false
- end;
-isEterm(_G, _Ni, _X) ->
- false.
-
-isBasicType(G, N, S) when element(1, S) == scoped_id ->
- {_, _, TK, _} = ic_symtab:get_full_scoped_name(G, N, S),
- isBasicType(fetchType(TK));
-isBasicType(_G, _N, {string, _} ) ->
- false;
-isBasicType(_G, _N, {Type, _} ) ->
- isBasicType(Type).
-
-
-isBasicType(G, Name) ->
- isBasicType(name2type(G, Name )).
-
-
-isBasicType(Type) ->
- lists:member(Type,
- [tk_short,short,
- tk_long,long,
- tk_ushort,ushort,
- tk_ulong,ulong,
- tk_float,float,
- tk_double,double,
- tk_boolean,boolean,
- tk_char,char,
- tk_octet,octet]).
-
-
-
-isString(G, N, T) when element(1, T) == scoped_id ->
- case ic_symtab:get_full_scoped_name(G, N, T) of
- {_FullScopedName, _, {'tk_string',_}, _} ->
- true;
- _ ->
- false
- end;
-isString(_G, _N, T) when is_record(T, string) ->
- true;
-isString(_G, _N, _Other) ->
- false.
-
-
-isArray(G, N, T) when element(1, T) == scoped_id ->
- case ic_symtab:get_full_scoped_name(G, N, T) of
- {_FullScopedName, _, {'tk_array', _, _}, _} ->
- true;
- _ ->
- false
- end;
-isArray(_G, _N, T) when is_record(T, array) ->
- true;
-isArray(_G, _N, _Other) ->
- false.
-
-
-
-isStruct(G, N, T) when element(1, T) == scoped_id ->
- case ic_symtab:get_full_scoped_name(G, N, T) of
- {_FullScopedName, _, {'tk_struct', _, _, _}, _} ->
- true;
- _ ->
- false
- end;
-isStruct(_G, _N, T) when is_record(T, struct) ->
- true;
-isStruct(_G, _N, _Other) ->
- false.
-
-
-
-isUnion(G, N, T) when element(1, T) == scoped_id ->
- case ic_symtab:get_full_scoped_name(G, N, T) of
- {_FullScopedName, _, {'tk_union', _, _, _,_,_}, _} ->
- true;
- _Other ->
- false
- end;
-isUnion(_G, _N, T) when is_record(T, union) ->
- true;
-isUnion(_G, _N, _Other) ->
- false.
-
-
-
-%%------------------------------------------------------------
-%%
-%% Always fetchs TK of a record.
-%%
-%%------------------------------------------------------------
-fetchTk(G,N,X) ->
- case ic_forms:get_tk(X) of
- undefined ->
- searchTk(G,ictk:get_IR_ID(G, N, X));
- TK ->
- TK
- end.
-
-
-%%------------------------------------------------------------
-%%
-%% seek type code when not accessible by get_tk/1
-%%
-%%------------------------------------------------------------
-searchTk(G,IR_ID) ->
- S = ic_genobj:tktab(G),
- case catch searchTk(S,IR_ID,typedef) of
- {value,TK} ->
- TK;
- _ -> %% false / exit
- case catch searchTk(S,IR_ID,struct) of
- {value,TK} ->
- TK;
- _ -> %% false / exit
- case catch searchTk(S,IR_ID,union) of
- {value,TK} ->
- TK;
- _ ->
- undefined
- end
- end
- end.
-
-
-searchTk(S,IR_ID,Type) ->
- L = lists:flatten(ets:match(S,{'_',Type,'$1','_'})),
- case lists:keysearch(IR_ID,2,L) of
- {value,TK} ->
- {value,TK};
- false ->
- searchInsideTks(L,IR_ID)
- end.
-
-
-searchInsideTks([],_IR_ID) ->
- false;
-searchInsideTks([{tk_array,TK,_}|Xs],IR_ID) ->
- case searchIncludedTk(TK,IR_ID) of
- {value,TK} ->
- {value,TK};
- false ->
- searchInsideTks(Xs,IR_ID)
- end.
-
-
-searchIncludedTk({tk_array,TK,_},IR_ID) ->
- searchIncludedTk(TK,IR_ID);
-searchIncludedTk({tk_sequence,TK,_},IR_ID) ->
- searchIncludedTk(TK,IR_ID);
-searchIncludedTk(TK,_IR_ID) when is_atom(TK) ->
- false;
-searchIncludedTk(TK,IR_ID) ->
- case element(2,TK) == IR_ID of
- true ->
- {value,TK};
- false ->
- false
- end.
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/src/ic_file.erl b/lib/ic/src/ic_file.erl
deleted file mode 100644
index 688a777400..0000000000
--- a/lib/ic/src/ic_file.erl
+++ /dev/null
@@ -1,448 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ic_file).
-
--include_lib("ic/src/ic.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([filename_push/4, filename_pop/2, open/2, close/1, remove_ext/1, join/2,
- add_dot_erl/1, add_dot_hrl/1, add_dot_c/1, add_dot_h/1, add_dot_java/1,
- add_dot_idl/1, javaInterfaceFilePush/3, javaInterfaceFilePop/1,
- createDirectory/2, createJavaDirectory/2, open_java_file/3]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% Func: filename_push
-%%
-%% Pushes a file name, can also push ignore in which case means that
-%% no files should ever be opened at this scope. Note that empty in
-%% the file descriptor entries means that the file just isn't open
-%% yet.
-%%-----------------------------------------------------------------
-filename_push(G, _N, ignore, _) ->
- G#genobj{stubfile=[ignore | G#genobj.stubfile],
- stubfiled=[ignore | G#genobj.stubfiled],
- skelfile=[ignore | G#genobj.skelfile],
- skelfiled=[ignore | G#genobj.skelfiled],
- includefile=[ignore | G#genobj.includefile],
- includefiled=[ignore | G#genobj.includefiled]};
-
-filename_push(G, N, X, Lang) ->
- Fullname = [ic_forms:get_id2(X) | N],
- EName0 = ic_util:to_undersc(Fullname),
-
- DoGen = ic_genobj:do_gen(G),
-
- ImplName = find_impl_name(G, Fullname),
-
- {StubName, EName} =
- case Lang of
- erlang ->
- {join(ic_options:get_opt(G, stubdir), add_dot_erl(EName0)),
- EName0};
- erlang_template ->
- {join(ic_options:get_opt(G, stubdir), add_dot_erl(ImplName)),
- ImplName};
- c ->
- {join(ic_options:get_opt(G, stubdir), add_dot_c(EName0)),
- EName0};
- c_server ->
- {join(ic_options:get_opt(G, stubdir), add_dot_c(EName0++"__s")),
- EName0};
- erlang_template_no_gen ->
- {undefined, EName0};
- erlang_no_stub ->
- {undefined, EName0};
- c_no_stub ->
- {undefined, EName0};
- c_server_no_stub ->
- {undefined, EName0}
- end,
- Stub = if DoGen==true ->
- case StubName of
- undefined ->
- ignore;
- _ ->
- ic_codegen:emit_stub_head(G, open(empty, StubName), EName, Lang)
- end;
- true -> ignore end,
-
- HrlName = case Lang of
- erlang_template ->
- ignore;
- erlang_template_no_gen ->
- ignore;
- erlang ->
- ?ifopt2(G, gen_hrl,
- join(ic_options:get_opt(G, stubdir), add_dot_hrl(EName)),
- ignore);
- c ->
- ?ifopt2(G, gen_hrl,
- join(ic_options:get_opt(G, stubdir), add_dot_h(EName)),
- ignore);
- c_server ->
- ?ifopt2(G, gen_hrl,
- join(ic_options:get_opt(G, stubdir),
- add_dot_h(EName++"__s")),
- ignore);
- erlang_no_stub ->
- ?ifopt2(G, gen_hrl,
- join(ic_options:get_opt(G, stubdir), add_dot_hrl(EName)),
- ignore);
- c_no_stub ->
- ?ifopt2(G, gen_hrl,
- join(ic_options:get_opt(G, stubdir), add_dot_h(EName)),
- ignore);
- c_server_no_stub ->
- ?ifopt2(G, gen_hrl,
- join(ic_options:get_opt(G, stubdir),
- add_dot_h(EName++"__s")),
- ignore)
- end,
- Hrl = if DoGen==true ->
- case Lang of
- erlang_template ->
- ignore;
- erlang_template_no_gen ->
- ignore;
- erlang_no_stub ->
- ic_codegen:emit_hrl_head(G, open(empty, HrlName),
- EName, erlang);
- c_no_stub ->
- ic_codegen:emit_hrl_head(G, open(empty, HrlName),
- EName, c);
- c_server_no_stub ->
- ic_codegen:emit_hrl_head(G, open(empty, HrlName),
- EName, c_server);
- _ ->
- ic_codegen:emit_hrl_head(G, open(empty, HrlName),
- EName, Lang)
- end;
- true -> ignore end,
-
- G#genobj{impl=ImplName,
- stubfile=[StubName | G#genobj.stubfile],
- stubfiled=[Stub | G#genobj.stubfiled],
- includefile=[HrlName | G#genobj.includefile],
- includefiled=[Hrl | G#genobj.includefiled]}.
-
-%%-----------------------------------------------------------------
-%% Func: join/2
-%%
-%% Special version of filename join.
-%%-----------------------------------------------------------------
-join([], File) ->
- File;
-join(Path, File) ->
- filename:join(Path, File).
-
-
-%%-----------------------------------------------------------------
-%% Func: filename_pop/2
-%%-----------------------------------------------------------------
-filename_pop(G, Lang) ->
-%% io:format("Popped file names: ~p~n", [hd(G#genobj.stubfile)]),
-%% case is_skelfile_open(G) of
-%% true -> emit_skel_footer(G);
-%% false -> ok end,
-%% close(hd(G#genobj.skelfiled)),
- close(hd(G#genobj.stubfiled)),
- ic_codegen:emit_hrl_foot(G, Lang),
- close(hd(G#genobj.includefiled)),
- G#genobj{stubfile=tl(G#genobj.stubfile),
- stubfiled=tl(G#genobj.stubfiled),
-%% skelfile=tl(G#genobj.skelfile),
-%% skelfiled=tl(G#genobj.skelfiled),
- includefile=tl(G#genobj.includefile),
- includefiled=tl(G#genobj.includefiled)}.
-
-
-
-%%-----------------------------------------------------------------
-%% Func: javaInterfaceFilePush/3
-%%-----------------------------------------------------------------
-javaInterfaceFilePush(G, N, X) ->
- Name = ic_forms:get_java_id(X),
- {InterfaceFd, InterfaceFileName} = open_java_file(G, N, Name),
-
- StubClassName = "_" ++ Name ++ "Stub",
- {StubFd, StubFileName} = open_java_file(G, N, StubClassName),
-
- SkelClassName = "_" ++ Name ++ "ImplBase",
- {SkelFd, SkelFileName} = open_java_file(G, N, SkelClassName),
-
- HelperClassName = Name ++ "Helper",
- {HelperFd, HelperFileName} = open_java_file(G, N, HelperClassName),
-
- HolderClassName = Name ++ "Holder",
- {HolderFd, HolderFileName} = open_java_file(G, N, HolderClassName),
-
- G#genobj{
- interfacefile=[InterfaceFileName | G#genobj.interfacefile],
- interfacefiled=[InterfaceFd | G#genobj.interfacefiled],
- stubfile=[StubFileName | G#genobj.stubfile],
- stubfiled=[StubFd | G#genobj.stubfiled],
- skelfile=[SkelFileName | G#genobj.skelfile],
- skelfiled=[SkelFd | G#genobj.skelfiled],
- helperfile=[HelperFileName | G#genobj.helperfile],
- helperfiled=[HelperFd | G#genobj.helperfiled],
- holderfile=[HolderFileName | G#genobj.holderfile],
- holderfiled=[HolderFd | G#genobj.holderfiled]}.
-
-
-
-
-
-%%-----------------------------------------------------------------
-%% Func: javaInterfaceFilePop/1
-%%-----------------------------------------------------------------
-javaInterfaceFilePop(G) ->
- close(hd(G#genobj.interfacefiled)),
- close(hd(G#genobj.stubfiled)),
- close(hd(G#genobj.skelfiled)),
- close(hd(G#genobj.helperfiled)),
- close(hd(G#genobj.holderfiled)),
- G#genobj{
- interfacefile=tl(G#genobj.interfacefile),
- interfacefiled=tl(G#genobj.interfacefiled),
- stubfile=tl(G#genobj.stubfile),
- stubfiled=tl(G#genobj.stubfiled),
- skelfile=tl(G#genobj.skelfile),
- skelfiled=tl(G#genobj.skelfiled),
- helperfile=tl(G#genobj.helperfile),
- helperfiled=tl(G#genobj.helperfiled),
- holderfile=tl(G#genobj.holderfile),
- holderfiled=tl(G#genobj.holderfiled)}.
-
-%%-----------------------------------------------------------------
-%% Func: createDirectory/2
-%%-----------------------------------------------------------------
-createDirectory(_G, []) ->
- ok;
-createDirectory(G, Scope) ->
- Path = ic_file:join(ic_options:get_opt(G, stubdir), ic_pragma:slashify(Scope)),
- case file:make_dir(Path) of
- ok ->
- ok;
- {error, eexist} ->
- ok;
- {error, Reason} ->
- ic_error:fatal_error(G, {create_dir, Path, Reason})
- end.
-
-
-%%-----------------------------------------------------------------
-%% Func: createJavaDirectory/2
-%%-----------------------------------------------------------------
-createJavaDirectory(_G, []) ->
- ok;
-createJavaDirectory(G, Scope) ->
- JavaScope = ic_util:adjustScopeToJava(G,Scope),
- Path = ic_file:join(ic_options:get_opt(G, stubdir), ic_pragma:slashify(JavaScope)),
- case file:make_dir(Path) of
- ok ->
- ok;
- {error, eexist} ->
- ok;
- {error, Reason} ->
- ic_error:fatal_error(G, {create_dir, Path, Reason})
- end.
-
-
-
-
-%%-----------------------------------------------------------------
-%% Func: createJavaFileName/3
-%%-----------------------------------------------------------------
-createJavaFileName(G, Scope, FName) ->
- JavaScope = ic_util:adjustScopeToJava(G,Scope),
- join(ic_options:get_opt(G, stubdir),
- ic_pragma:slashify([FName++".java"|JavaScope])).
-
-%%-----------------------------------------------------------------
-%% Func: close/2 (used to be file_close)
-%%-----------------------------------------------------------------
-close(empty) -> ok;
-close(ignore) -> ok;
-close(Fd) ->
- file:close(Fd).
-
-%%-----------------------------------------------------------------
-%% Func: remove_ext/1
-%%-----------------------------------------------------------------
-remove_ext(File) ->
- filename:rootname(filename:basename(File)).
-
-%%-----------------------------------------------------------------
-%% Func: open/2 (used to be file_open)
-%%-----------------------------------------------------------------
-open(_, ignore) -> ignore;
-open(empty, Name) ->
- case file:open(Name, [raw, binary, write]) of
- {ok, Fd} ->
- Fd;
- {error, Reason} ->
- exit({error, Reason})
-%% ic_error:fatal_error(G, {open_file, Name, Reason})
- end.
-
-%%-----------------------------------------------------------------
-%% Func: open_java_file/3
-%%-----------------------------------------------------------------
-open_java_file(G, N, Name) ->
- createJavaDirectory(G, N),
- FName = createJavaFileName(G, N, Name),
- case file:open(FName, [raw, binary, write]) of
- {ok, Fd} ->
- ic_codegen:emit_stub_head(G, Fd, Name, java),
- emit_package(G, N, Fd),
- {Fd, FName};
- {error, Reason} ->
- ic_error:fatal_error(G, {open_file, FName, Reason})
- end.
-
-%%-----------------------------------------------------------------
-%% Func: emit_package/3
-%%-----------------------------------------------------------------
-emit_package(_G, [], _Fd) ->
- ok;
-emit_package(G, N, Fd) ->
- ic_codegen:emit(Fd, "package ~s;\n", [ic_util:to_dot(G,N)]),
- ic_codegen:nl(Fd).
-
-%%-----------------------------------------------------------------
-%% Func: add_dot_erl/1
-%%-----------------------------------------------------------------
-add_dot_erl(F) ->
- File = ic_util:to_list(F),
- F2 = lists:reverse(File),
- case F2 of
- [$l, $r, $e, $. | _Rest] ->
- File;
- _ ->
- File ++ ".erl"
- end.
-
-%%-----------------------------------------------------------------
-%% Func: add_dot_hrl/1
-%%-----------------------------------------------------------------
-add_dot_hrl(F) ->
- File = ic_util:to_list(F),
- F2 = lists:reverse(File),
- case F2 of
- [$l, $r, $h, $. | _Rest] ->
- File;
- _ ->
- File ++ ".hrl"
- end.
-
-%%-----------------------------------------------------------------
-%% Func: add_dot_c/1
-%%-----------------------------------------------------------------
-add_dot_c(F) ->
- File = ic_util:to_list(F),
- F2 = lists:reverse(File),
- case F2 of
- [$c, $. | _Rest] ->
- File;
- _ ->
- File ++ ".c"
- end.
-
-%%-----------------------------------------------------------------
-%% Func: add_dot_h/1
-%%-----------------------------------------------------------------
-add_dot_h(F) ->
- File = ic_util:to_list(F),
- F2 = lists:reverse(File),
- case F2 of
- [$h, $. | _Rest] ->
- File;
- _ ->
- File ++ ".h"
- end.
-
-%%-----------------------------------------------------------------
-%% Func: add_dot_java/1
-%%-----------------------------------------------------------------
-add_dot_java(F) ->
- File = ic_util:to_list(F),
- F2 = lists:reverse(File),
- case F2 of
- [$a, $v, $a, $j, $. | _Rest] ->
- File;
- _ ->
- File ++ ".java"
- end.
-
-%%-----------------------------------------------------------------
-%% Func: add_dot_idl/1
-%%-----------------------------------------------------------------
-add_dot_idl(F) ->
- File = ic_util:to_list(F),
- F2 = lists:reverse(File),
- case F2 of
- [$l, $d, $i, $. | _Rest] ->
- File;
- _ ->
- File ++ ".idl"
- end.
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-
-%%--------------------------------------------------------------------
-%%
-%% File handling stuff
-%%
-%%
-%% Shall open a file for writing. Also sets up the generator with
-%% usefull bits of information
-%%
-%%--------------------------------------------------------------------
-find_impl_name(G, Name) ->
- N1 = ic_util:to_colon(Name),
- N2 = ic_util:to_undersc(Name),
- case {ic_options:get_opt(G, {impl, N1}),
- ic_options:get_opt(G, {impl, N2})} of
- {false, false} ->
- case {ic_options:get_opt(G, {impl, "::"++N1}),
- ic_options:get_opt(G, {impl, N2})} of
- {false, false} -> N2 ++ "_impl";
- {X, _Y} when X /= false -> ic_util:to_list(X);
- {_X, Y} when Y /= false -> ic_util:to_list(Y)
- end;
- {X, _Y} when X /= false -> ic_util:to_list(X);
- {_X, Y} when Y /= false -> ic_util:to_list(Y)
- end.
diff --git a/lib/ic/src/ic_forms.erl b/lib/ic/src/ic_forms.erl
deleted file mode 100644
index ed4b3e9a22..0000000000
--- a/lib/ic/src/ic_forms.erl
+++ /dev/null
@@ -1,442 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ic_forms).
-
--include_lib("ic/src/ic.hrl").
--include_lib("ic/src/icforms.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([get_id/1, get_id2/1, get_java_id/1, get_line/1]).
--export([get_type_code/3, search_tk/2, clean_up_scope/1]).
--export([get_body/1, get_dimension/1, get_idlist/1, get_type/1, get_tk/1, is_oneway/1]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-
-%%--------------------------------------------------------------------
-%%
-%% Generation go-get utilities
-%%
-%% Feeble attempt at virtual funtions.
-%%
-%%--------------------------------------------------------------------
-
-get_dimension(X) when is_record(X, array) ->
- [element(3, L) || L <- X#array.size].
-
-%% Should find the name hidden in constructs
-get_id( [{'<identifier>', _LineNo, Id}] ) -> Id;
-get_id( {'<identifier>', _LineNo, Id} ) -> Id;
-get_id(Id) when is_list(Id) andalso is_integer(hd(Id)) -> Id;
-get_id(X) when is_record(X, scoped_id) -> X#scoped_id.id;
-get_id(X) when is_record(X, array) -> get_id(X#array.id);
-get_id( {'<string_literal>', _LineNo, Id} ) -> Id;
-get_id( {'<wstring_literal>', _LineNo, Id} ) -> Id.
-
-get_line([{'<identifier>', LineNo, _Id}]) -> LineNo;
-get_line({'<identifier>', LineNo, _Id}) -> LineNo;
-get_line(X) when is_record(X, scoped_id) -> X#scoped_id.line;
-get_line(X) when is_record(X, module) -> get_line(X#module.id);
-get_line(X) when is_record(X, interface) -> get_line(X#interface.id);
-get_line(X) when is_record(X, forward) -> get_line(X#forward.id);
-get_line(X) when is_record(X, constr_forward) -> get_line(X#constr_forward.id);
-get_line(X) when is_record(X, const) -> get_line(X#const.id);
-get_line(X) when is_record(X, typedef) -> get_line(X#typedef.id);
-get_line(X) when is_record(X, struct) -> get_line(X#struct.id);
-get_line(X) when is_record(X, member) -> get_line(X#member.id);
-get_line(X) when is_record(X, union) -> get_line(X#union.id);
-get_line(X) when is_record(X, case_dcl) -> get_line(X#case_dcl.id);
-get_line(X) when is_record(X, enum) -> get_line(X#enum.id);
-get_line(X) when is_record(X, enumerator) -> get_line(X#enumerator.id);
-get_line(X) when is_record(X, array) -> get_line(X#array.id);
-get_line(X) when is_record(X, attr) -> get_line(X#attr.id);
-get_line(X) when is_record(X, except) -> get_line(X#except.id);
-get_line(X) when is_record(X, op) -> get_line(X#op.id);
-get_line(X) when is_record(X, param) -> get_line(X#param.id);
-get_line(X) when is_record(X, id_of) -> get_line(X#id_of.id);
-
-get_line({'or', T1, _T2}) -> get_line(T1);
-get_line({'xor', T1, _T2}) -> get_line(T1);
-get_line({'and', T1, _T2}) -> get_line(T1);
-get_line({'rshift', T1, _T2}) ->get_line(T1);
-get_line({'lshift', T1, _T2}) ->get_line(T1);
-get_line({'+', T1, _T2}) -> get_line(T1);
-get_line({'-', T1, _T2}) -> get_line(T1);
-get_line({'*', T1, _T2}) -> get_line(T1);
-get_line({'/', T1, _T2}) -> get_line(T1);
-get_line({'%', T1, _T2}) -> get_line(T1);
-get_line({{'-', _Line}, T}) -> get_line(T);
-get_line({{'+', _Line}, T}) -> get_line(T);
-get_line({{'~', _Line}, T}) -> get_line(T);
-get_line({_, X, _}) when is_integer(X) -> X;
-get_line({_A, N}) when is_integer(N) -> N;
-get_line(_) -> -1.
-
-
-%%--------------------------------------------------------------------
-%%
-%% High level get functions.
-%%
-%% These are highly polymorphic functions that will get the id,
-%% body and type of a record (those records output from the
-%% parser).
-%%
-%% NOTE: The typedef node (the alias) is special, because the type
-%% field is a type definition and therefore considered a body,
-%% and the type of a typedef is its name.
-%%
-
-get_id2(X) when is_record(X, module) -> get_id(X#module.id);
-get_id2(X) when is_record(X, interface) -> get_id(X#interface.id);
-get_id2(X) when is_record(X, forward) -> get_id(X#forward.id);
-get_id2(X) when is_record(X, constr_forward) -> get_id(X#constr_forward.id);
-get_id2(X) when is_record(X, const) -> get_id(X#const.id);
-get_id2(X) when is_record(X, typedef) -> get_id(hd(X#typedef.id));
-get_id2(X) when is_record(X, struct) -> get_id(X#struct.id);
-get_id2(X) when is_record(X, member) -> get_id(hd(X#member.id));
-get_id2(X) when is_record(X, union) -> get_id(X#union.id);
-get_id2(X) when is_record(X, case_dcl) -> get_id(X#case_dcl.id);
-get_id2(X) when is_record(X, enum) -> get_id(X#enum.id);
-get_id2(X) when is_record(X, enumerator) -> get_id(X#enumerator.id);
-get_id2(X) when is_record(X, array) -> get_id(X#array.id);
-get_id2(X) when is_record(X, attr) -> get_id(X#attr.id);
-get_id2(X) when is_record(X, except) -> get_id(X#except.id);
-get_id2(X) when is_record(X, op) -> get_id(X#op.id);
-get_id2(X) when is_record(X, param) -> get_id(X#param.id);
-get_id2(X) when is_record(X, type_dcl) -> get_id2(X#type_dcl.type);
-get_id2(X) when is_record(X, scoped_id) -> ic_symtab:scoped_id_strip(X);
-get_id2(X) when is_record(X, preproc) -> get_id(X#preproc.id);
-get_id2(X) when is_record(X, id_of) -> get_id2(X#id_of.id);
-get_id2(X) -> get_id(X).
-
-get_body(X) when is_record(X, module) -> X#module.body;
-get_body(X) when is_record(X, interface) -> X#interface.body;
-get_body(X) when is_record(X, struct) -> X#struct.body;
-get_body(X) when is_record(X, union) -> X#union.body;
-get_body(X) when is_record(X, enum) -> X#enum.body;
-get_body(X) when is_record(X, typedef) -> X#typedef.type; % See Note
-get_body(X) when is_record(X, except) -> X#except.body.
-
-get_type(X) when is_record(X, const) -> X#const.type;
-get_type(X) when is_record(X, type_dcl) -> X#type_dcl.type;
-get_type(X) when is_record(X, typedef) -> X#typedef.id; % See Note
-get_type(X) when is_record(X, member) -> X#member.type;
-get_type(X) when is_record(X, union) -> X#union.type;
-get_type(X) when is_record(X, case_dcl) -> X#case_dcl.type;
-get_type(X) when is_record(X, sequence) -> X#sequence.type;
-get_type(X) when is_record(X, attr) -> X#attr.type;
-get_type(X) when is_record(X, op) -> X#op.type;
-get_type(X) when is_record(X, param) -> X#param.type.
-%%get_type(X) when record(X, id_of) -> get_type(X#id_of.type).
-
-%% Temporary place
-get_tk(X) when is_record(X, interface) -> X#interface.tk;
-get_tk(X) when is_record(X, forward) -> X#forward.tk;
-get_tk(X) when is_record(X, constr_forward) -> X#constr_forward.tk;
-get_tk(X) when is_record(X, const) -> X#const.tk;
-get_tk(X) when is_record(X, type_dcl) -> X#type_dcl.tk;
-get_tk(X) when is_record(X, typedef) -> X#typedef.tk;
-get_tk(X) when is_record(X, struct) -> X#struct.tk;
-get_tk(X) when is_record(X, union) -> X#union.tk;
-get_tk(X) when is_record(X, enum) -> X#enum.tk;
-get_tk(X) when is_record(X, attr) -> X#attr.tk;
-get_tk(X) when is_record(X, except) -> X#except.tk;
-get_tk(X) when is_record(X, op) -> X#op.tk;
-get_tk(X) when is_record(X, id_of) -> X#id_of.tk;
-get_tk(X) when is_record(X, param) -> X#param.tk.
-
-
-%% Get idlist returns the list of identifiers found in typedefs, case
-%% dcls etc.
-get_idlist(X) when is_record(X, typedef) -> X#typedef.id;
-get_idlist(X) when is_record(X, member) -> X#member.id;
-get_idlist(X) when is_record(X, case_dcl) -> X#case_dcl.label;
-get_idlist(X) when is_record(X, attr) -> X#attr.id.
-
-
-is_oneway(X) when is_record(X, op) ->
- case X#op.oneway of
- {oneway, _} -> true;
- _ -> false
- end;
-is_oneway(_X) -> false.
-
-
-
-
-
-%%------------------------------------------------------------
-%%
-%% Analyze the record and seek the correct type code.
-%%
-%% NOT equal to get_tk, this will always succed !
-%%
-%%------------------------------------------------------------
-get_type_code(G, N, X) ->
- case get_type_code2(G, N, X) of
- undefined ->
- %% Remove "Package" suffix from scope
- N2 = clean_up_scope(N),
- search_tk(G,ictk:get_IR_ID(G, N2, X));
- TC ->
- TC
- end.
-
-clean_up_scope(N) ->
- clean_up_scope(N,[]).
-
-clean_up_scope([],N) ->
- lists:reverse(N);
-clean_up_scope([N|Ns],Found) ->
- case lists:suffix("Package",N) of
- true ->
- Len = length(N),
- case Len > 7 of
- true ->
- N2 = string:substr(N,1,Len-7),
- clean_up_scope(Ns,[N2|Found]);
- false ->
- clean_up_scope(Ns,[N|Found])
- end;
- false ->
- clean_up_scope(Ns,[N|Found])
- end.
-
-
-get_type_code2(_, _, X) when is_record(X, interface) -> X#interface.tk;
-get_type_code2(_, _, X) when is_record(X, forward) -> X#forward.tk;
-get_type_code2(_, _, X) when is_record(X, constr_forward) -> X#constr_forward.tk;
-get_type_code2(_, _, X) when is_record(X, const) -> X#const.tk;
-get_type_code2(_, _, X) when is_record(X, type_dcl) -> X#type_dcl.tk;
-get_type_code2(_, _, X) when is_record(X, typedef) ->
- Id = X#typedef.id,
- ET = X#typedef.tk,
- if is_list(Id) ->
- Head = hd(Id),
- if is_tuple(Head) ->
- case element(1,Head) of
- array ->
- get_array_tc(ET, element(3,Head));
- _ ->
- ET
- end;
- true ->
- ET
- end;
- true ->
- ET
- end;
-
-get_type_code2(_, _, X) when is_record(X, struct) -> X#struct.tk;
-get_type_code2(_, _, X) when is_record(X, union) -> X#union.tk;
-get_type_code2(_, _, X) when is_record(X, enum) -> X#enum.tk;
-get_type_code2(_, _, X) when is_record(X, attr) -> X#attr.tk;
-get_type_code2(_, _, X) when is_record(X, except) -> X#except.tk;
-get_type_code2(_, _, X) when is_record(X, op) -> X#op.tk;
-get_type_code2(_, _, X) when is_record(X, id_of) -> X#id_of.tk;
-get_type_code2(_, _, X) when is_record(X, param) -> X#param.tk;
-
-get_type_code2(G, N, X) when is_record(X, member) ->
- ET = get_type_code(G, N, element(2,X)),
- Id = element(3,X),
-
- if is_list(Id) ->
- Head = hd(Id),
- if is_tuple(Head) ->
- case element(1,Head) of
- array ->
- get_array_tc(ET, element(3,Head));
- _ ->
- ET
- end;
- true ->
- ET
- end;
- true ->
- ET
- end;
-
-get_type_code2(G, N, X) when is_record(X, scoped_id) ->
- element(3,ic_symtab:get_full_scoped_name(G, N, X));
-
-get_type_code2(G, N, X) when is_record(X, sequence) ->
- if is_tuple(X#sequence.length) ->
- {tk_sequence,
- get_type_code(G, N, X#sequence.type),
- list_to_integer(element(3,X#sequence.length))};
- true ->
- {tk_sequence,
- get_type_code(G, N, X#sequence.type),
- X#sequence.length}
- end;
-
-get_type_code2(_G, _N, {unsigned,{short,_}}) -> tk_ushort;
-
-get_type_code2(_G, _N, {unsigned,{long,_}}) -> tk_ulong;
-
-get_type_code2(_G, _N, {unsigned,{'long long',_}}) -> tk_ulonglong;
-
-get_type_code2(_G, _N, X) when is_record(X, fixed) ->
- {tk_fixed, X#fixed.digits, X#fixed.scale};
-
-get_type_code2(G, N, {X,_}) ->
- get_type_code2(G, N, X);
-
-get_type_code2(_, _, short) -> tk_short;
-get_type_code2(_, _, long) -> tk_long;
-get_type_code2(_, _, 'long long') -> tk_longlong;
-get_type_code2(_, _, float) -> tk_float;
-get_type_code2(_, _, double) -> tk_double;
-get_type_code2(_, _, boolean) -> tk_boolean;
-get_type_code2(_, _, char) -> tk_char;
-get_type_code2(_, _, wchar) -> tk_wchar;
-get_type_code2(_, _, octet) -> tk_octet;
-get_type_code2(_, _, string) -> tk_string;
-get_type_code2(_, _, wstring) -> tk_wstring;
-get_type_code2(_, _, any) -> tk_any.
-
-
-get_array_tc(ET, []) ->
- ET;
-get_array_tc(ET, [L|Ls]) ->
- {tk_array,
- get_array_tc(ET,Ls),
- list_to_integer(element(3,L))}.
-
-
-
-
-%%------------------------------------------------------------
-%%
-%% seek type code when not accessible by ic_forms:get_tk/1 ( should be
-%% a part of "do_gen" related functions later )
-%%
-%%------------------------------------------------------------
-search_tk(G, IR_ID) ->
- S = ic_genobj:tktab(G),
- case catch search_tk(S,IR_ID,typedef) of
- {value,TK} ->
- TK;
- _ -> %% false / exit
- case catch search_tk(S,IR_ID,struct) of
- {value,TK} ->
- TK;
- _ -> %% false / exit
- case catch search_tk(S,IR_ID,union) of
- {value,TK} ->
- TK;
- _ ->
- undefined
- end
- end
- end.
-
-
-search_tk(S, IR_ID, Type) ->
- L = lists:flatten(ets:match(S,{'_',Type,'$1','_'})),
- case lists:keysearch(IR_ID,2,L) of
- {value,TK} ->
- {value,TK};
- false ->
- search_inside_tks(L,IR_ID)
- end.
-
-
-search_inside_tks([],_IR_ID) ->
- false;
-search_inside_tks([{tk_array,TK,_}|Xs],IR_ID) ->
- case search_included_tk(TK,IR_ID) of
- {value,TK} ->
- {value,TK};
- false ->
- search_inside_tks(Xs,IR_ID)
- end.
-
-
-search_included_tk({tk_array,TK,_}, IR_ID) ->
- search_included_tk(TK,IR_ID);
-search_included_tk({tk_sequence,TK,_}, IR_ID) ->
- search_included_tk(TK,IR_ID);
-search_included_tk(TK, _IR_ID) when is_atom(TK) ->
- false;
-search_included_tk(TK, IR_ID) ->
- case element(2,TK) == IR_ID of
- true ->
- {value,TK};
- false ->
- false
- end.
-
-
-
-
-%% This is similar to get_id2 but in everything else
-%% than a module it will generate an id prefixed
-get_java_id(Id) when is_list(Id) ->
- case java_keyword_coalition(Id) of
- true ->
- "_" ++ Id;
- false ->
- Id
- end;
-get_java_id(Id_atom) when is_atom(Id_atom) ->
- Id = atom_to_list(Id_atom),
- case java_keyword_coalition(Id) of
- true ->
- "_" ++ Id;
- false ->
- Id
- end;
-get_java_id(X) ->
- Id = get_id2(X),
- case java_keyword_coalition(Id) of
- true ->
- "_" ++ Id;
- false ->
- Id
- end.
-
-java_keyword_coalition(Id) ->
- lists:member(list_to_atom(Id),
- [abstract, default, 'if', private, throw, boolean,
- do, implements, protected, throws, break,
- double, import, public, transient, byte,
- else, instanceof, return, 'try', 'case', extends,
- int, short, void, 'catch', final, interface, static,
- volatile, char, finally, long, super, while, class,
- float, native, switch, const, for, new, synchronized,
- continue, goto, package, this, true, false]).
-
-
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
diff --git a/lib/ic/src/ic_genobj.erl b/lib/ic/src/ic_genobj.erl
deleted file mode 100644
index eb2c24c000..0000000000
--- a/lib/ic/src/ic_genobj.erl
+++ /dev/null
@@ -1,245 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ic_genobj).
-
-
--include_lib("ic/src/ic.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([new/1, free_table_space/1, process_space/0]).
--export([skelfiled/1, stubfiled/1, hrlfiled/1, includefiled/1]).
--export([interfacefiled/1, helperfiled/1, holderfiled/1]).
--export([is_skelfile_open/1, is_stubfile_open/1, is_hrlfile_open/1]).
--export([include_file/1, include_file_stack/1]).
--export([push_file/2, pop_file/2, sys_file/2]).
-
--export([skelscope/1, stubscope/1, impl/1, do_gen/1]).
--export([symtab/1, auxtab/1, tktab/1, pragmatab/1, optiontab/1, typedeftab/1]).
--export([idlfile/1, module/1, set_idlfile/2, set_module/2]).
-
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-
-%%--------------------------------------------------------------------
-%%
-%% Initialisation stuff
-%%
-%%
-%%
-%%--------------------------------------------------------------------
-
-
-new(Opts) ->
- OptDB = ets:new(options, [set, public]),
- Warns = ets:new(warnings, [set, public]),
- Aux = ets:new(aux, [set, public]),
- Tk = ets:new(tktab, [set, public]),
- PragmaTab = ets:new(pragmatab, [bag, public]),
- TypeDefTab = ets:new(c_typedeftab, [set, public]),
- G = #genobj{options=OptDB,
- warnings=Warns,
- symtab=ic_symtab:new(),
- auxtab=Aux,
- tktab=Tk,
- pragmatab=PragmaTab,
- c_typedeftab=TypeDefTab},
- ic_error:init_errors(G),
- ic_options:add_opt(G, default_opts, true),
- ic_options:read_cfg(G, Opts), % Read any config files
- ic_options:add_opt(G, Opts, true),
- ic_symtab:symtab_add_faked_included_types(G), % Add CORBA::<Types> that as if they
- % were defined in an included file
- case ic_options:get_opt(G, be) of
- false ->
- DefBE = ic_options:defaultBe(),
- case ic_options:get_opt(G, multiple_be) of
- false ->
- ic_options:add_opt(G, be, DefBE),
- G;
- List ->
- case lists:member(DefBE, List) of
- true ->
- %% Delete the default be from the list to avoid
- %% generating it twice.
- NewList = lists:delete(DefBE, List),
- ic_options:add_opt(G, multiple_be, NewList),
- ic_options:add_opt(G, be, DefBE),
- G;
- false ->
- G
- end
- end;
- _ ->
- G
- end.
-
-
-%%--------------------------------------------------------------------
-%%
-%% Table removal
-%%
-%%
-%%
-%%--------------------------------------------------------------------
-
-
-free_table_space(G) ->
- %% Free ets tables
- ets:delete(G#genobj.options),
- ets:delete(G#genobj.symtab),
- ets:delete(G#genobj.warnings),
- ets:delete(G#genobj.auxtab),
- ets:delete(G#genobj.tktab),
- ets:delete(G#genobj.pragmatab),
- ets:delete(G#genobj.c_typedeftab),
- %% Close file descriptors
- close_fd(G#genobj.skelfiled),
- close_fd(G#genobj.stubfiled),
- close_fd(G#genobj.interfacefiled),
- close_fd(G#genobj.helperfiled),
- close_fd(G#genobj.holderfiled),
- close_fd(G#genobj.includefiled).
-
-close_fd([]) ->
- ok;
-close_fd([Fd|Fds]) ->
- file_close(Fd),
- close_fd(Fds).
-
-file_close(empty) -> ok;
-file_close(ignore) -> ok;
-file_close(Fd) ->
- file:close(Fd).
-
-
-%%--------------------------------------------------------------------
-%%
-%% Process memory usage
-%%
-%%
-%%
-%%--------------------------------------------------------------------
-
-process_space() ->
- Pheap=4*element(2,element(2,lists:keysearch(heap_size,1,process_info(self())))),
- Pstack=4*element(2,element(2,lists:keysearch(stack_size,1,process_info(self())))),
- io:format("Process current heap = ~p bytes\n",[Pheap]),
- io:format("Symbol current stack = ~p bytes\n",[Pstack]),
- io:format("-----------------------------------------------\n"),
- io:format("Totally used ~p bytes\n\n",[Pheap+Pstack]).
-
-
-
-
-
-
-skelfiled(G) -> hd(G#genobj.skelfiled).
-stubfiled(G) -> hd(G#genobj.stubfiled).
-includefiled(G) -> hd(G#genobj.includefiled).
-hrlfiled(G) -> hd(G#genobj.includefiled).
-interfacefiled(G) -> hd(G#genobj.interfacefiled).
-helperfiled(G) -> hd(G#genobj.helperfiled).
-holderfiled(G) -> hd(G#genobj.holderfiled).
-
-include_file(G) -> hd(G#genobj.includefile).
-include_file_stack(G) -> G#genobj.includefile.
-
-is_skelfile_open(G) ->
- if hd(G#genobj.skelfiled) /= empty, hd(G#genobj.skelfiled) /= ignore
- -> true;
- true -> false
- end.
-is_stubfile_open(G) ->
- if hd(G#genobj.stubfiled) /= empty, hd(G#genobj.stubfiled) /= ignore
- -> true;
- true -> false
- end.
-
-is_hrlfile_open(G) ->
- if hd(G#genobj.includefiled) /= empty, hd(G#genobj.includefiled) /= ignore
- -> true;
- true -> false
- end.
-
-%%--------------------------------------------------------------------
-%%
-%% Handling of pre processor file commands
-%%
-%%--------------------------------------------------------------------
-
-push_file(G, Id) ->
- New = G#genobj.filestack+1,
- set_idlfile(G, Id),
- G#genobj{filestack=New, do_gen=true_or_not(New)}.
-pop_file(G, Id) ->
- New = G#genobj.filestack-1,
- set_idlfile(G, Id),
- G#genobj{filestack=New, do_gen=true_or_not(New)}.
-sys_file(G, _Id) -> G#genobj{sysfile=true}.
-
-
-do_gen(G) -> G#genobj.do_gen.
-
-%%--------------------------------------------------------------------
-%%
-%% Storage routines
-%%i
-%% The generator object G is used to store many usefull bits of
-%% information so that the information doesn't need to get passed
-%% around everywhere.
-%%
-%%--------------------------------------------------------------------
-
-
-skelscope(G) -> G#genobj.skelscope.
-stubscope(G) -> G#genobj.stubscope.
-symtab(G) -> G#genobj.symtab.
-auxtab(G) -> G#genobj.auxtab.
-tktab(G) -> G#genobj.tktab.
-impl(G) -> G#genobj.impl.
-pragmatab(G) -> G#genobj.pragmatab.
-optiontab(G) -> G#genobj.options.
-typedeftab(G) -> G#genobj.c_typedeftab.
-
-idlfile(G) -> ?lookup(G#genobj.options, idlfile).
-module(G) -> ?lookup(G#genobj.options, module).
-
-set_idlfile(G, X) -> ?insert(G#genobj.options, idlfile, X).
-set_module(G, X) -> ?insert(G#genobj.options, module, ic_forms:get_id(X)).
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-true_or_not(X) when X < 2 ->
- true;
-true_or_not(_) ->
- false.
diff --git a/lib/ic/src/ic_java_type.erl b/lib/ic/src/ic_java_type.erl
deleted file mode 100644
index 931aa92a8e..0000000000
--- a/lib/ic/src/ic_java_type.erl
+++ /dev/null
@@ -1,1214 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ic_java_type).
-
-
--include("icforms.hrl").
--include("ic.hrl").
--include("ic_debug.hrl").
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([getType/3, getHolderType/3,
- getParamType/4, inlinedTypes/2,
- marshalFun/4, unMarshalFun/4, getFullType/4,
- getFullType/3, getMarshalType/4, getUnmarshalType/4,
- getdim/1]).
--export([isBasicType/3, isBasicType/1]).
--export([isIntegerType/3, isIntegerType/1]).
--export([isTermType/3]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: getType/3
-%%-----------------------------------------------------------------
-getType(G, N, T) when is_record(T, scoped_id) ->
- {FullScopedName, _, TK, _} = ic_symtab:get_full_scoped_name(G, N, T),
- BT = ic_code:get_basetype(G, ic_util:to_dot(G,FullScopedName)),
- case BT of
- "erlang.pid" ->
- ?ICPACKAGE ++ "Pid";
- "erlang.port" ->
- ?ICPACKAGE ++ "Port";
- "erlang.ref" ->
- ?ICPACKAGE ++ "Ref";
- "erlang.term" ->
- ?ICPACKAGE ++ "Term";
- {enum, Type} ->
- getType(G, N, Type);
- Type ->
- case TK of
- {tk_array,_,_} ->
- tk2type(G,N,T,TK);
- {tk_sequence,_,_} ->
- tk2type(G,N,T,TK);
- tk_any ->
- ?ICPACKAGE ++ "Any";
- _ ->
- case isBasicType(G,N,TK) of
- true ->
- tk2type(G,N,T,TK);
- false ->
- Type %% Other types
- end
- end
- end;
-
-getType(_G, _N, S) when is_list(S) ->
- S;
-
-getType(_G, _N, T) when is_record(T, string) ->
- "java.lang.String";
-
-getType(_G, _N, T) when is_record(T, wstring) -> %% WSTRING
- "java.lang.String";
-
-getType(G, N, T) when is_record(T, struct) ->
- ic_util:to_dot(G,[ic_forms:get_id2(T)|N]);
-
-getType(G, N, T) when is_record(T, union) ->
- ic_util:to_dot(G,[ic_forms:get_id2(T)|N]);
-
-getType(G, N, T) when is_record(T, sequence) ->
- getType(G, N, ic_forms:get_type(T)) ++ "[]";
-
-getType(G, N, T) when is_record(T, enum) ->
- ic_util:to_dot(G,[ic_forms:get_id2(T)|N]);
-
-%% NOTE i am using the new isJavaElementaryType
-%% to avoid members declared as keywords (except
-%% all java elementary types) to be used as a
-%% class
-getType(G, N, T) when is_record(T, member) ->
- Type = tk2type(G,N,T,ic_forms:get_type_code(G, N, T)),
- case isJavaElementaryType(list_to_atom(Type)) of
- true ->
- Type;
- false ->
- Prefix = list_to_atom(lists:flatten(string:tokens(Type,"[]"))),
- case isJavaElementaryType(Prefix) of %% Checks if Type is an array
- %% of elementary java types
- true ->
- Type;
- false ->
- ic_forms:get_java_id(getType(G,N,ic_forms:get_type(T))) ++
- if is_record(hd(T#member.id),array) ->
- arrayEmptyDim(hd(T#member.id));
- true ->
- ""
- end
- end
- end;
-
-getType(_G, _N, {boolean, _}) ->
- "boolean";
-
-getType(_G, _N, {octet, _}) ->
- "byte";
-
-getType(_G, _N, {void, _}) ->
- "void";
-
-getType(_G, _N, {unsigned, U}) ->
- case U of
- {short,_} ->
- "short";
- {long,_} ->
- "int";
- {'long long',_} ->
- "long"
- end;
-
-getType(_G, _N, {char, _}) ->
- "char";
-
-getType(_G, _N, {wchar, _}) -> %% WCHAR
- "char";
-
-getType(_G, _N, {short, _}) ->
- "short";
-
-getType(_G, _N, {long, _}) ->
- "int";
-
-getType(_G, _N, {'long long', _}) ->
- "long";
-
-getType(_G, _N, {float, _}) ->
- "float";
-
-getType(_G, _N, {double, _}) ->
- "double";
-
-getType(_G, _N, {any, _}) ->
- ?ICPACKAGE ++ "Any".
-
-
-
-
-
-
-%%-----------------------------------------------------------------
-%% Func: getHolderType/3
-%%-----------------------------------------------------------------
-getHolderType(G, N, T) when element(1, T) == scoped_id ->
- {FullScopedName, _, TK, _} = ic_symtab:get_full_scoped_name(G, N, T),
- BT = ic_code:get_basetype(G, ic_util:to_dot(G,FullScopedName)),
- case BT of
- "erlang.pid" ->
- ?ICPACKAGE ++ "PidHolder";
- "erlang.port" ->
- ?ICPACKAGE ++ "PortHolder";
- "erlang.ref" ->
- ?ICPACKAGE ++ "RefHolder";
- "erlang.term" ->
- ?ICPACKAGE ++ "TermHolder";
- {enum, Type} ->
- getHolderType(G, N, Type);
-
- Type ->
- case TK of
- {'tk_struct', _, _, _} ->
- Type ++ "Holder";
-
- {'tk_union', _, _, _, _, _} ->
- Type ++ "Holder";
-
- {'tk_array', _ , _} ->
- Type ++ "Holder";
-
- {'tk_sequence', _ , _} ->
- Type ++ "Holder";
-
- {'tk_string', _} ->
- ?ICPACKAGE ++ "StringHolder";
-
- {'tk_wstring', _} -> %% WSTRING
- ?ICPACKAGE ++ "StringHolder";
-
- {'tk_enum', _, _, _} ->
- Type ++ "Holder";
-
- 'tk_boolean' ->
- ?ICPACKAGE ++ "BooleanHolder";
-
- 'tk_octet' ->
- ?ICPACKAGE ++ "ByteHolder";
-
- 'tk_ushort' ->
- ?ICPACKAGE ++ "ShortHolder";
-
- 'tk_ulong' ->
- ?ICPACKAGE ++ "IntHolder";
-
- 'tk_ulonglong' -> %% ULLONG
- ?ICPACKAGE ++ "LongHolder";
-
- 'tk_short' ->
- ?ICPACKAGE ++ "ShortHolder";
-
- 'tk_long' ->
- ?ICPACKAGE ++ "IntHolder";
-
- 'tk_longlong' ->
- ?ICPACKAGE ++ "LongHolder"; %% LLONG
-
- 'tk_float' ->
- ?ICPACKAGE ++ "FloatHolder";
-
- 'tk_double' ->
- ?ICPACKAGE ++ "DoubleHolder";
-
- 'tk_char' ->
- ?ICPACKAGE ++ "CharHolder";
-
- 'tk_wchar' -> %% WCHAR
- ?ICPACKAGE ++ "CharHolder";
-
- 'tk_any' ->
- ?ICPACKAGE ++ "AnyHolder";
-
- _ ->
- case isBasicType(G,N,TK) of
- true ->
- %% Faked the type !
- getHolderType(G, N, {list_to_atom(tk2type(G,N,T,TK)), -1});
- false ->
- %%io:format("TK = ~p, Type = ~p\n",[TK,Type]),
- ic_util:to_dot(G,FullScopedName) ++ "Holder"
- end
- end
- end;
-
-getHolderType(G, N, S) when is_list(S) ->
- ic_util:to_dot(G,[S|N]) ++ "Holder";
-
-getHolderType(_G, _N, T) when is_record(T, string) ->
- ?ICPACKAGE ++"StringHolder";
-
-getHolderType(_G, _N, T) when is_record(T, wstring) -> %% WSTRING
- ?ICPACKAGE ++"StringHolder";
-
-getHolderType(G, N, T) when is_record(T, struct) ->
- ic_util:to_dot(G,[ic_forms:get_id2(T)|N]) ++ "Holder";
-
-getHolderType(G, N, T) when is_record(T, union) ->
- ic_util:to_dot(G,[ic_forms:get_id2(T)|N]) ++ "Holder";
-
-getHolderType(G, N, T) when is_record(T, array) ->
- ic_util:to_dot(G,[ic_forms:get_id2(T)|N]) ++ "Holder";
-
-getHolderType(G, N, T) when is_record(T, sequence) ->
- getType(G, N, ic_forms:get_type(T)) ++ "Holder[]";
-
-getHolderType(G, N, T) when is_record(T, enum) ->
- ic_util:to_dot(G,[ic_forms:get_id2(T)|N]) ++ "Holder";
-
-getHolderType(_G, _N, {boolean, _}) ->
- ?ICPACKAGE ++"BooleanHolder";
-
-getHolderType(_G, _N, {octet, _}) ->
- ?ICPACKAGE ++"ByteHolder";
-
-getHolderType(_G, _N, {void, _}) ->
- "void";
-
-getHolderType(_G, _N, {unsigned, U}) ->
- case U of
- {short,_} ->
- ?ICPACKAGE ++"ShortHolder";
- {long,_} ->
- ?ICPACKAGE ++"IntHolder";
- {'long long',_} ->
- ?ICPACKAGE ++"LongHolder"
- end;
-
-getHolderType(_G, _N, {char, _}) ->
- ?ICPACKAGE ++"CharHolder";
-
-getHolderType(_G, _N, {wchar, _}) -> %% WCHAR
- ?ICPACKAGE ++"CharHolder";
-
-getHolderType(_G, _N, {short, _}) ->
- ?ICPACKAGE ++"ShortHolder";
-
-getHolderType(_G, _N, {long, _}) ->
- ?ICPACKAGE ++"IntHolder";
-
-getHolderType(_G, _N, {'long long', _}) ->
- ?ICPACKAGE ++"LongHolder";
-
-getHolderType(_G, _N, {float, _}) ->
- ?ICPACKAGE ++"FloatHolder";
-
-getHolderType(_G, _N, {double, _}) ->
- ?ICPACKAGE ++"DoubleHolder";
-
-getHolderType(_G, _N, {any,_}) ->
- ?ICPACKAGE ++ "AnyHolder".
-
-
-%%-----------------------------------------------------------------
-%% Func: getParamType/4
-%%-----------------------------------------------------------------
-getParamType(G, N, S, in) ->
- getType(G, N, S);
-getParamType(G, N, S, ret) ->
- getType(G, N, S);
-getParamType(G, N, S, out) ->
- getHolderType(G, N, S);
-getParamType(G, N, S, inout) ->
- getHolderType(G, N, S).
-
-
-%%-----------------------------------------------------------------
-%% Func: getUnmarshalType/4
-%%-----------------------------------------------------------------
-getUnmarshalType(G, N, X, T) when element(1, T) == scoped_id ->
- {FullScopedName, _, TK, _} = ic_symtab:get_full_scoped_name(G, N, T),
- BT = ic_code:get_basetype(G, ic_util:to_dot(G,FullScopedName)),
- case BT of
- "erlang.pid" ->
- ?ICPACKAGE ++ "PidHelper";
- "erlang.port" ->
- ?ICPACKAGE ++ "PortHelper";
- "erlang.ref" ->
- ?ICPACKAGE ++ "RefHelper";
- "erlang.term" ->
- ?ICPACKAGE ++ "TermHelper";
- {enum, Type} ->
- getUnmarshalType(G, N, X, Type);
- Type ->
- case TK of
- {'tk_struct', _, _, _} ->
- Type ++ "Helper";
-
- {'tk_union', _, _, _, _, _} ->
- Type ++ "Helper";
-
- {'tk_sequence', _ , _} ->
- Type ++ "Helper";
-
- {'tk_array', _ , _} ->
- Type ++ "Helper";
-
- {'tk_enum', _, _, _} ->
- Type ++ "Helper";
-
- {'tk_string',_} ->
- ?ERLANGPACKAGE ++ "OtpErlangString";
-
- {'tk_wstring',_} -> %% WSTRING
- ?ERLANGPACKAGE ++ "OtpErlangString";
-
- 'tk_char' ->
- ?ERLANGPACKAGE ++ "OtpErlangLong";
-
- 'tk_wchar' -> %% WCHAR
- ?ERLANGPACKAGE ++ "OtpErlangLong";
-
- 'tk_octet' ->
- ?ERLANGPACKAGE ++ "OtpErlangLong";
-
- 'tk_ushort' ->
- ?ERLANGPACKAGE ++ "OtpErlangLong";
-
- 'tk_ulong' ->
- ?ERLANGPACKAGE ++ "OtpErlangLong";
-
- 'tk_ulonglong' -> %% ULLONG
- ?ERLANGPACKAGE ++ "OtpErlangLong";
-
- 'tk_short' ->
- ?ERLANGPACKAGE ++ "OtpErlangLong";
-
- 'tk_long' ->
- ?ERLANGPACKAGE ++ "OtpErlangLong";
-
- 'tk_longlong' -> %% LLONG
- ?ERLANGPACKAGE ++ "OtpErlangLong";
-
- 'tk_float' ->
- ?ERLANGPACKAGE ++ "OtpErlangDouble";
-
- 'tk_double' ->
- ?ERLANGPACKAGE ++ "OtpErlangDouble";
-
- 'tk_boolean' ->
- ?ERLANGPACKAGE ++ "OtpErlangAtom";
-
- 'tk_void' ->
- ?ERLANGPACKAGE ++ "OtpErlangAtom";
-
- 'tk_any' ->
- ?ICPACKAGE ++ "AnyHelper";
-
- _ ->
- case isBasicType(G,N,TK) of
- true ->
- %% Faked the type !
- getUnmarshalType(G, N, X, {list_to_atom(tk2type(G,N,T,TK)), -1});
- false ->
- ic_util:to_dot(G,FullScopedName) ++ "Helper"
- end
- end
- end;
-
-getUnmarshalType(_G, _N, _X, S) when is_list(S) ->
- S ++ "Helper";
-
-getUnmarshalType(_G, _N, _X, T) when is_record(T, string) ->
- ?ERLANGPACKAGE ++ "OtpErlangString";
-
-getUnmarshalType(_G, _N, _X, T) when is_record(T, wstring) -> %% WSTRING
- ?ERLANGPACKAGE ++ "OtpErlangString";
-
-getUnmarshalType(G, N, _X, T) when is_record(T, struct) ->
- ic_util:to_dot(G,[ic_forms:get_id2(T)|N]) ++ "Helper";
-
-getUnmarshalType(G, N, _X, T) when is_record(T, union) ->
- ic_util:to_dot(G,[ic_forms:get_id2(T)|N]) ++ "Helper";
-
-getUnmarshalType(G, N, X, T) when is_record(T, sequence) andalso
- is_record(X, member) ->
- ic_util:to_dot(G,[ic_forms:get_id2(X)|N]) ++ "Helper";
-
-getUnmarshalType(G, N, X, T) when is_record(T, sequence) andalso
- is_record(X, case_dcl) ->
- ic_util:to_dot(G,[ic_forms:get_id2(X)|N]) ++ "Helper";
-
-getUnmarshalType(G, N, X, T) when is_record(T, sequence) ->
- getUnmarshalType(G, N, X, ic_forms:get_type(T)) ++ "Helper";
-
-getUnmarshalType(G, N, X, T) when is_record(T, array) andalso
- is_record(X, case_dcl) ->
- ic_util:to_dot(G,[ic_forms:get_id2(T)|N]) ++ "Helper";
-
-getUnmarshalType(G, N, _X, T) when is_record(T, enum) ->
- ic_util:to_dot(G,[ic_forms:get_id2(T)|N]) ++
- "Helper";
-
-getUnmarshalType(_G, _N, _X, {boolean, _}) ->
- ?ERLANGPACKAGE ++ "OtpErlangAtom";
-
-getUnmarshalType(_G, _N, _X, {octet, _}) ->
- ?ERLANGPACKAGE ++ "OtpErlangLong";
-
-getUnmarshalType(_G, _N, _X, {void, _}) ->
- ?ERLANGPACKAGE ++ "OtpErlangAtom";
-
-getUnmarshalType(_G, _N, _X, {unsigned, U}) ->
- case U of
- {short,_} ->
- ?ERLANGPACKAGE ++ "OtpErlangLong";
- {long,_} ->
- ?ERLANGPACKAGE ++ "OtpErlangLong";
- {'long long',_} ->
- ?ERLANGPACKAGE ++ "OtpErlangLong"
- end;
-
-getUnmarshalType(_G, _N, _X, {char, _}) ->
- ?ERLANGPACKAGE ++ "OtpErlangLong";
-
-getUnmarshalType(_G, _N, _X, {wchar, _}) -> %% WCHAR
- ?ERLANGPACKAGE ++ "OtpErlangLong";
-
-getUnmarshalType(_G, _N, _X, {short, _}) ->
- ?ERLANGPACKAGE ++ "OtpErlangLong";
-
-getUnmarshalType(_G, _N, _X, {long, _}) ->
- ?ERLANGPACKAGE ++ "OtpErlangLong";
-
-getUnmarshalType(_G, _N, _X, {'long long', _}) ->
- ?ERLANGPACKAGE ++ "OtpErlangLong";
-
-getUnmarshalType(_G, _N, _X, {float, _}) ->
- ?ERLANGPACKAGE ++ "OtpErlangDouble";
-
-getUnmarshalType(_G, _N, _X, {double, _}) ->
- ?ERLANGPACKAGE ++ "OtpErlangDouble";
-
-getUnmarshalType(_G, _N, _X, {any, _}) ->
- ?ICPACKAGE ++ "AnyHelper".
-
-%%-----------------------------------------------------------------
-%% Func: getMarshalType/4
-%%-----------------------------------------------------------------
-getMarshalType(G, N, X, T) when element(1, T) == scoped_id ->
- {FullScopedName, _, TK, _} = ic_symtab:get_full_scoped_name(G, N, T),
- BT = ic_code:get_basetype(G, ic_util:to_dot(G,FullScopedName)),
- case BT of
- "erlang.pid" ->
- ?ICPACKAGE ++ "PidHelper";
- "erlang.port" ->
- ?ICPACKAGE ++ "PortHelper";
- "erlang.ref" ->
- ?ICPACKAGE ++ "RefHelper";
- "erlang.term" ->
- ?ICPACKAGE ++ "TermHelper";
- {enum, Type} ->
- getMarshalType(G, N, X, Type);
- Type ->
- case TK of
- {'tk_struct', _, _, _} ->
- Type ++ "Helper";
-
- {'tk_union', _, _, _, _, _} ->
- Type ++ "Helper";
-
- {'tk_array', _ , _} ->
- Type ++ "Helper";
-
- {'tk_sequence', _ , _} ->
- Type ++ "Helper";
-
- {'tk_enum', _, _, _} ->
- Type ++ "Helper";
-
- {'tk_string',_} ->
- "string";
-
- {'tk_wstring',_} -> %% WSTRING
- "string";
-
- 'tk_char' ->
- "char";
-
- 'tk_wchar' -> %% WCHAR
- "char";
-
- 'tk_octet' ->
- "byte";
-
- 'tk_ushort' ->
- "ushort";
-
- 'tk_ulong' ->
- "uint";
-
- 'tk_ulonglong' -> %% ULLONG
- "ulong";
-
- 'tk_short' ->
- "short";
-
- 'tk_long' ->
- "int";
-
- 'tk_longlong' -> %% LLONG
- "long";
-
- 'tk_float' ->
- "float";
-
- 'tk_double' ->
- "double";
-
- 'tk_boolean' ->
- "boolean";
-
- 'tk_void' ->
- "atom";
-
- 'tk_any' ->
- ?ICPACKAGE ++ "AnyHelper";
-
- _ ->
- case isBasicType(G,N,TK) of
- true ->
- %% Faked the type !
- getMarshalType(G, N, X, {list_to_atom(tk2type(G,N,T,TK)), -1});
- false ->
- ic_util:to_dot(G,FullScopedName) ++ "Helper"
- end
- end
- end;
-
-getMarshalType(_G, _N, _X, S) when is_list(S) ->
- S ++ "Helper";
-
-getMarshalType(_G, _N, _X, T) when is_record(T, string) ->
- "string";
-
-getMarshalType(_G, _N, _X, T) when is_record(T, wstring) -> %% WSTRING
- "string";
-
-getMarshalType(G, N, _X, T) when is_record(T, struct) ->
- ic_util:to_dot(G,[ic_forms:get_id2(T)|N]) ++
- "Helper";
-
-getMarshalType(G, N, _X, T) when is_record(T, union) ->
- ic_util:to_dot(G,[ic_forms:get_id2(T)|N]) ++
- "Helper";
-
-getMarshalType(G, N, X, T) when is_record(T, array) andalso
- is_record(X, case_dcl) ->
- ic_util:to_dot(G,[ic_forms:get_id2(T)|N]) ++
- "Helper";
-
-getMarshalType(G, N, X, T) when is_record(T, sequence) andalso
- is_record(X, member) ->
- ic_util:to_dot(G,[ic_forms:get_id2(X)|N]) ++
- "Helper";
-
-getMarshalType(G, N, _X, T) when is_record(T, sequence) ->
- getType(G, N, ic_forms:get_type(T)) ++
- "Helper";
-
-getMarshalType(G, N, _X, T) when is_record(T, enum) ->
- ic_util:to_dot(G,[ic_forms:get_id2(T)|N]) ++
- "Helper";
-
-getMarshalType(_G, _N, _X, {boolean, _}) ->
- "boolean";
-
-getMarshalType(_G, _N, _X, {octet, _}) ->
- "byte";
-
-getMarshalType(_G, _N, _X, {void, _}) ->
- ""; % <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
-
-getMarshalType(_G, _N, _X, {unsigned, U}) ->
- case U of
- {short,_} ->
- "ushort";
- {long,_} ->
- "uint";
- {'long long',_} ->
- "ulong"
- end;
-
-getMarshalType(_G, _N, _X, {short, _}) ->
- "short";
-getMarshalType(_G, _N, _X, {long, _}) ->
- "int";
-getMarshalType(_G, _N, _X, {'long long', _}) ->
- "long";
-getMarshalType(_G, _N, _X, {float, _}) ->
- "float";
-getMarshalType(_G, _N, _X, {double, _}) ->
- "double";
-getMarshalType(_G, _N, _X, {char, _}) ->
- "char";
-getMarshalType(_G, _N, _X, {wchar, _}) -> %% WCHAR
- "char";
-getMarshalType(_G, _N, _X, {any, _}) ->
- ?ICPACKAGE ++ "AnyHelper".
-
-
-
-
-%%-----------------------------------------------------------------
-%% Func: unMarshalFun/4
-%%-----------------------------------------------------------------
-unMarshalFun(G, N, X, T) when element(1, T) == scoped_id ->
- {FullScopedName, _, TK, _} = ic_symtab:get_full_scoped_name(G, N, T),
- BT = ic_code:get_basetype(G, ic_util:to_dot(G,FullScopedName)),
- case BT of
- "erlang.pid" ->
- ".read_pid()";
- "erlang.port" ->
- ".read_port()";
- "erlang.ref" ->
- ".read_ref()";
- "erlang.term" ->
- ".read_term()";
- {enum, Type} ->
- unMarshalFun(G, N, X, Type);
- _Type ->
- case isBasicType(G,N,TK) of
- true ->
- case TK of
- {'tk_string',_} ->
- ".read_string()";
-
- {'tk_wstring',_} -> %% WSTRING
- ".read_string()";
-
- 'tk_boolean' ->
- ".read_boolean()";
-
- 'tk_octet' ->
- ".read_byte()";
-
- 'tk_ushort' ->
- ".read_ushort()";
-
- 'tk_ulong' ->
- ".read_uint()";
-
- 'tk_ulonglong' -> %% ULLONG
- ".read_ulong()";
-
- 'tk_short' ->
- ".read_short()";
-
- 'tk_long' ->
- ".read_int()";
-
- 'tk_longlong' -> %% LLONG
- ".read_long()";
-
- 'tk_float' ->
- ".read_float()";
-
- 'tk_double' ->
- ".read_double()";
-
- 'tk_char' ->
- ".read_char()";
-
- 'tk_wchar' -> %% WCHAR
- ".read_char()";
-
- _ ->
- %% Faked the type !
- unMarshalFun(G, N, X, {list_to_atom(tk2type(G,N,X,TK)), -1})
- end;
- false ->
- ".unmarshal()"
- end
- end;
-
-unMarshalFun(_G, _N, _X, S) when is_list(S) ->
- ".unmarshal()";
-
-unMarshalFun(_G, _N, _X, T) when is_record(T, string) ->
- ".read_string()";
-
-unMarshalFun(_G, _N, _X, T) when is_record(T, wstring) -> %% WSTRING
- ".read_string()";
-
-unMarshalFun(_G, _N, _X, T) when is_record(T, struct) ->
- ".unmarshal((" ++ ?ERLANGPACKAGE ++ "OtpErlangTuple)";
-
-unMarshalFun(_G, _N, _X, T) when is_record(T, union) ->
- ".unmarshal((" ++ ?ERLANGPACKAGE ++ "OtpErlangTuple)";
-
-unMarshalFun(_G, _N, _X, T) when is_record(T, sequence) ->
- ".unmarshal((" ++ ?ERLANGPACKAGE ++ "OtpErlanglist)";
-
-unMarshalFun(_G, _N, _X, T) when is_record(T, enum) ->
- ".unmarshal((" ++ ?ERLANGPACKAGE ++ "OtpErlangAtom)";
-
-unMarshalFun(_G, _N, _X, {boolean, _}) ->
- ".read_boolean()";
-
-unMarshalFun(_G, _N, _X, {octet, _}) ->
- ".read_byte()";
-
-unMarshalFun(_G, _N, _X, {void, _}) ->
- "";
-
-unMarshalFun(_G, _N, _X, {unsigned, U}) ->
- case U of
- {short,_} ->
- ".read_ushort()";
- {long,_} ->
- ".read_uint()";
- {'long long',_} ->
- ".read_ulong()"
- end;
-
-unMarshalFun(_G, _N, _X, {short, _}) ->
- ".read_short()";
-unMarshalFun(_G, _N, _X, {long, _}) ->
- ".read_int()";
-unMarshalFun(_G, _N, _X, {'long long', _}) ->
- ".read_long()";
-unMarshalFun(_G, _N, _X, {float, _}) ->
- ".read_float()";
-unMarshalFun(_G, _N, _X, {double, _}) ->
- ".read_double()";
-unMarshalFun(_G, _N, _X, {char, _}) ->
- ".read_char()";
-unMarshalFun(_G, _N, _X, {wchar, _}) -> %% WCHAR
- ".read_char()".
-
-
-
-
-
-%%-----------------------------------------------------------------
-%% Func: getFullType/4 - /3
-%%
-%% Note : Similar to the getType/3 with the major difference
-%% thet on arrays and sequences it will also declare
-%% their sizes. Used for "new" declarations
-%%
-%%-----------------------------------------------------------------
-
-
-getFullType(G, N, X, T) when is_record(X, typedef) andalso is_record(T, array) ->
- FullDim =
- tk2FullType(G,N,X,ic_forms:get_tk(X)) ++
- getFullDim(G,N,T#array.size),
- fixArrayDims(FullDim);
-
-getFullType(G, N, X, T) when is_record(X, member) andalso is_record(T, array) ->
- FullDim =
- getFullType(G, N, ic_forms:get_type(X)) ++
- getFullDim(G,N,T#array.size),
- fixArrayDims(FullDim);
-
-getFullType(G, N, X, T) when is_record(X, case_dcl) andalso is_record(T, array) ->
- FullDim =
- getFullType(G, N, ic_forms:get_type(X)) ++
- getFullDim(G,N,T#array.size),
- fixArrayDims(FullDim);
-
-getFullType(G, N, _X, T) ->
- getFullType(G, N, T).
-
-
-
-getFullType(G, N, T) when is_record(T, scoped_id) ->
- {FullScopedName, _, TK, _} = ic_symtab:get_full_scoped_name(G, N, T),
- case TK of
- {tk_array,_,_} ->
- tk2FullType(G,N,T,TK);
- {tk_sequence,_,_} ->
- tk2FullType(G,N,T,TK);
- _ ->
- case isBasicType(G,N,TK) of
- true ->
- tk2FullType(G,N,T,TK);
- false ->
- %% Other types
- ic_code:get_basetype(G, ic_util:to_dot(G,FullScopedName))
- end
- end;
-
-getFullType(G, N, T) when is_record(T, sequence) ->
- fixSeqDims(getType(G,N,T),"_length");
-
-getFullType(G, N, T) ->
- getType(G, N, T).
-
-
-
-%% In order to make a legal declaration
-%% of an assignable array, the dimensions
-%% of empty array sequences are swifted to
-%% the end of the type
-fixArrayDims(Cs) ->
- fixArrayDims(Cs,[],[]).
-
-fixArrayDims([],Fulls,Emptys) ->
- lists:reverse(Fulls) ++ Emptys;
-fixArrayDims([91,93|Rest],Fulls,Emptys) ->
- fixArrayDims(Rest,Fulls,[91,93|Emptys]);
-fixArrayDims([C|Rest],Fulls,Emptys) ->
- fixArrayDims(Rest,[C|Fulls],Emptys).
-
-
-%% In order to make a legal declaration
-%% of an assignable array, the dimensions
-%% of empty array of sequences are swifted
-%% to the end of the type
-fixSeqDims(Cs,Length) ->
- fixSeqDims(Cs,Length,[]).
-
-fixSeqDims([],_Length,Found) ->
- lists:reverse(Found);
-fixSeqDims([91,93|Rest],Length,Found) when is_list(Length) ->
- lists:reverse([93|lists:reverse(Length)] ++
- [91|Found]) ++ Rest;
-fixSeqDims([C|Rest],Length,Found) ->
- fixSeqDims(Rest,Length,[C|Found]).
-
-
-
-%%-----------------------------------------------------------------
-%% Func: inlinedTypes/2
-%%-----------------------------------------------------------------
-inlinedTypes(PkgName, Type) when is_record(Type, struct) ->
- "_" ++ PkgName ++ ".";
-inlinedTypes(PkgName, Type) when is_record(Type, union) ->
- "_" ++ PkgName ++ ".";
-inlinedTypes(PkgName, Type) when is_record(Type, enum) ->
- "_" ++ PkgName ++ ".";
-inlinedTypes(_, _) ->
- "".
-
-%%-----------------------------------------------------------------
-%% Func: marshalFun/4
-%%-----------------------------------------------------------------
-marshalFun(G, N, X, Type) ->
- case isBasicType(G, N, Type) of
- true ->
- ".write_" ++ getMarshalType(G, N, X, Type);
- _ ->
- getMarshalType(G, N, X, Type) ++ ".marshal"
- end.
-
-
-%%-----------------------------------------------------------------
-%% Func: isBasicType/3
-%%-----------------------------------------------------------------
-isBasicType(G, N, S) when element(1, S) == scoped_id ->
- {_, _, TK, _} = ic_symtab:get_full_scoped_name(G, N, S),
- isBasicType(ictype:fetchType(TK));
-
-isBasicType(G, N, X) when is_record(X, member) ->
- if is_record(hd(element(3,X)), array) ->
- false;
- true ->
- isBasicType(G, N, element(2,X))
- end;
-
-isBasicType(_G, _N, {unsigned, {long, _}} ) ->
- true;
-
-isBasicType(_G, _N, {unsigned, {short, _}} ) ->
- true;
-
-isBasicType(_G, _N, {unsigned, {'long long', _}} ) ->
- true;
-
-isBasicType(_G, _N, {'long long', _} ) ->
- true;
-
-isBasicType(_G, _N, {Type, _} ) ->
- isBasicType(Type);
-
-isBasicType(_G, _N, Type) ->
- isBasicType(Type).
-
-
-%%-----------------------------------------------------------------
-%% Func: isBasicType/1
-%%-----------------------------------------------------------------
-
-isBasicType( Type ) ->
- lists:member(Type,
- [tk_short,short,
- tk_long,long,
- tk_longlong,longlong, %% LLONG
- tk_ushort,ushort,
- tk_ulong,ulong,
- tk_ulonglong,ulonglong, %% ULLONG
- tk_float,float,
- tk_double,double,
- tk_boolean,boolean,
- tk_char,char,
- tk_wchar,wchar, %% WCHAR
- tk_octet,octet,
- tk_wstring,wstring, %% WSTRING
- tk_string,string]).
-
-%% returns true if the Type is a java elementary type
-isJavaElementaryType( Type ) ->
- lists:member(Type,
- [byte, char, wchar, boolean,
- int, short, long, 'long long', float, double]).
-
-%%-----------------------------------------------------------------
-%% Func: isIntegerType/3
-%%-----------------------------------------------------------------
-isIntegerType(G, N, S) when element(1, S) == scoped_id ->
- {_, _, TK, _} = ic_symtab:get_full_scoped_name(G, N, S),
- isIntegerType(ictype:fetchType(TK));
-isIntegerType(_G, _N, {unsigned, {long, _}} ) ->
- true;
-isIntegerType(_G, _N, {unsigned, {short, _}} ) ->
- true;
-isIntegerType(_G, _N, {unsigned, {'long long', _}} ) ->
- true;
-isIntegerType(_G, _N, {'long long', _} ) ->
- true;
-isIntegerType(_G, _N, {Type, _} ) ->
- isIntegerType(Type);
-isIntegerType(_G, _N, Type) ->
- isIntegerType(Type).
-
-%%-----------------------------------------------------------------
-%% Func: isIntegerType/1
-%%-----------------------------------------------------------------
-
-isIntegerType( Type ) ->
- lists:member(Type,
- [tk_short,short,
- tk_long,long,
- tk_longlong,longlong, %% LLONG
- tk_ushort,ushort,
- tk_ulong,ulong,
- tk_ulonglong,ulonglong, %% ULLONG
- tk_char,char,
- tk_wchar,wchar, %% WCHAR
- tk_octet,octet]).
-
-
-
-%%-----------------------------------------------------------------
-%% Func: isTerm/3
-%%-----------------------------------------------------------------
-isTermType(G, N, T) ->
- case getType(G,N,T) of
- "com.ericsson.otp.ic.Term" ->
- true;
- _ ->
- false
- end.
-
-
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-
-
-%% Changes the typecode to the
-%% corresponding "basic" type
-tk2type(_G,_N,_X,{'tk_struct', _IFRId, "port", _ElementList}) ->
- ?ICPACKAGE ++ "Port";
-tk2type(_G,_N,_X,{'tk_struct', _IFRId, "pid", _ElementList}) ->
- ?ICPACKAGE ++ "Pid";
-tk2type(_G,_N,_X,{'tk_struct', _IFRId, "ref", _ElementList}) ->
- ?ICPACKAGE ++ "Ref";
-tk2type(_G,_N,_X,{'tk_struct', _IFRId, "term", _ElementList}) ->
- ?ICPACKAGE ++ "Term";
-tk2type(_G,_N,_X,{'tk_string', _}) ->
- "java.lang.String";
-tk2type(_G,_N,_X,{'tk_wstring', _}) -> %% WSTRING
- "java.lang.String";
-tk2type(G,N,X,{'tk_array', ElemTC, Dim}) ->
- tkarr2decl(G,N,X,{'tk_array', ElemTC, Dim});
-tk2type(G,N,X,{'tk_sequence', ElemTC, MaxLsextractength}) ->
- tkseq2decl(G,N,X,{'tk_sequence', ElemTC, MaxLsextractength});
-tk2type(G,N,_X,{'tk_struct', IFRId, Name, _ElementList}) ->
- ScopedId=
- lists:reverse(string:tokens(lists:nth(2,string:tokens(IFRId,":")),"/")),
-
- case ic_forms:clean_up_scope([Name|N]) of
- ScopedId ->
- %% Right path, use N instead
- ic_util:to_dot(G,[Name|N]);
- _ ->
- %% Ugly work arround
- ic_util:to_dot(G,ScopedId)
- end;
-tk2type(G,N,_X,{'tk_union', IFRId, Name, _, _, _ElementList}) ->
- ScopedId=
- lists:reverse(string:tokens(lists:nth(2,string:tokens(IFRId,":")),"/")),
-
- case ic_forms:clean_up_scope([Name|N]) of
- ScopedId ->
- %% Right path, use N instead
- ic_util:to_dot(G,[Name|N]);
- _ ->
- %% Ugly work arround
- ic_util:to_dot(G,ScopedId)
- end;
-tk2type(_G,_N,_X,{'tk_enum', _Id, Name, _ElementList}) ->
- Name;
-tk2type(_G,_N,_X,tk_void) ->
- "void";
-tk2type(_G,_N,_X,tk_long) ->
- "int";
-tk2type(_G,_N,_X,tk_longlong) -> %% LLONG
- "long";
-tk2type(_G,_N,_X,tk_short) ->
- "short";
-tk2type(_G,_N,_X,tk_ulong) ->
- "int";
-tk2type(_G,_N,_X,tk_ulonglong) -> %% ULLONG
- "long";
-tk2type(_G,_N,_X,tk_ushort) ->
- "short";
-tk2type(_G,_N,_X,tk_float) ->
- "float";
-tk2type(_G,_N,_X,tk_double) ->
- "double";
-tk2type(_G,_N,_X,tk_boolean) ->
- "boolean";
-tk2type(_G,_N,_X,tk_char) ->
- "char";
-tk2type(_G,_N,_X,tk_wchar) -> %% WCHAR
- "char";
-tk2type(_G,_N,_X,tk_octet) ->
- "byte";
-tk2type(_G,_N,_X,tk_string) ->
- "java.lang.String";
-tk2type(_G,_N,_X,tk_wstring) -> %% WSTRING
- "java.lang.String";
-tk2type(_G,_N,_X,tk_any) ->
- ?ICPACKAGE ++ "Any";
-tk2type(_G,_N,_X,tk_term) -> %% Term
- ?ICPACKAGE ++ "Term".
-
-%% Changes the sequence typecode to the
-%% corresponding "basic" structure
-tkseq2decl(G,N,X,TKSeq) ->
- tkseq2decl2(G,N,X,TKSeq,[],[]).
-
-tkseq2decl2(G,N,X,{tk_sequence,E,D},[],Ds) ->
- tkseq2decl2(G,N,X,E,[],[D|Ds]);
-tkseq2decl2(G,N,X,TkEl,[],Ds) ->
- ElName = tk2type(G,N,X,TkEl),
- ElName ++ getdim(Ds).
-
-%% Changes the array typecode to the
-%% corresponding "basic" structure
-tkarr2decl(G,N,X,TKArr) ->
- tkarr2decl2(G,N,X,TKArr,[],[]).
-
-tkarr2decl2(G,N,X,{tk_array,E,D},[],Ds) ->
- tkarr2decl2(G,N,X,E,[],[D|Ds]);
-tkarr2decl2(G,N,X,TkEl,[],Ds) ->
- ElName = tk2type(G,N,X,TkEl),
- ElName ++ getdim(Ds).
-
-getdim([]) ->
- "";
-getdim([_D|Ds]) ->
- getdim(Ds) ++ "[]".
-
-
-
-%% Changes the typecode to the corresponding "basic" type
-%% used for variable declarations where arrays and sequences
-%% are declared with there full dimensions
-tk2FullType(G,N,X,{'tk_array', ElemTC, Dim}) ->
- tkarr2FullDecl(G,N,X,{'tk_array', ElemTC, Dim});
-tk2FullType(G,N,X,{'tk_sequence', ElemTC, MaxLsextractength}) ->
- tkseq2FullDecl(G,N,X,{'tk_sequence', ElemTC, MaxLsextractength});
-tk2FullType(G,N,X,TK) ->
- tk2type(G,N,X,TK).
-
-
-%% Changes the sequence typecode to the
-%% corresponding "basic" structure here
-%% arrays and sequences are declared with
-%% their full dimensions
-tkseq2FullDecl(G,N,X,TKSeq) ->
- tkseq2FullDecl2(G,N,X,TKSeq,[],[]).
-
-tkseq2FullDecl2(G,N,X,{tk_sequence,E,D},[],Ds) ->
- tkseq2FullDecl2(G,N,X,E,[],[D|Ds]);
-tkseq2FullDecl2(G,N,X,TkEl,[],Ds) ->
- ElName = tk2FullType(G,N,X,TkEl),
- ElName ++ getdim(Ds).
-
-%% Changes the array typecode to the
-%% corresponding "basic" structure
-tkarr2FullDecl(G,N,X,TKArr) ->
- tkarr2FullDecl2(G,N,X,TKArr,[],[]).
-
-tkarr2FullDecl2(G,N,X,{tk_array,E,D},[],Ds) ->
- tkarr2FullDecl2(G,N,X,E,[],[D|Ds]);
-tkarr2FullDecl2(G,N,X,TkEl,[],Ds) ->
- ElName = tk2FullType(G,N,X,TkEl),
- ElName ++ getFullDim(G,N,Ds).
-
-getFullDim(_G,_N,[]) ->
- "";
-getFullDim(G,N,[D|Ds]) when is_record(D,scoped_id) ->
- {FSN, _, _, _} = ic_symtab:get_full_scoped_name(G, N, D),
- "[" ++ ic_util:to_dot(G,FSN) ++ "]" ++ getFullDim(G,N,Ds);
-getFullDim(G,N,[D|Ds]) when is_integer(D) ->
- "[" ++ integer_to_list(D) ++ "]" ++ getFullDim(G,N,Ds);
-getFullDim(G,N,[D|Ds]) when is_tuple(D) ->
- "[" ++ ic_util:eval_java(G,N,D) ++ "]" ++ getFullDim(G,N,Ds).
-
-
-
-%% Constructs an array empty dimension string
-%% used for array variable declaration
-arrayEmptyDim(X) ->
- arrayEmptyDim2(X#array.size).
-
-arrayEmptyDim2([_D]) ->
- "[]";
-arrayEmptyDim2([_D |Ds]) ->
- "[]" ++ arrayEmptyDim2(Ds).
-
-
-
diff --git a/lib/ic/src/ic_jbe.erl b/lib/ic/src/ic_jbe.erl
deleted file mode 100644
index 56518a681b..0000000000
--- a/lib/ic/src/ic_jbe.erl
+++ /dev/null
@@ -1,1488 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-
--module(ic_jbe).
-
-
--export([do_gen/3, gen/3, emit_type_function/4]).
-
-
-
--include("icforms.hrl").
--include("ic.hrl").
--include("ic_debug.hrl").
--include_lib("stdlib/include/erl_compile.hrl").
-
-
-
-%%------------------------------------------------------------
-%%
-%% Entry point
-%%
-%%------------------------------------------------------------
-
-do_gen(G, _File, Form) ->
- gen(G, [], Form).
-
-
-%%------------------------------------------------------------
-%%
-%% Generate the client side C stubs.
-%%
-%% Each module is generated to a separate file.
-%%
-%% Each function needs to generate a function head and
-%% a body. IDL parameters must be converted into C parameters.
-%%
-%%------------------------------------------------------------
-
-gen(G, N, [X|Xs]) when is_record(X, preproc) ->
- NewG = handle_preproc(G, N, X#preproc.cat, X),
- gen(NewG, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, module) ->
- gen_module(G, N, X),
- gen(G, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, interface) ->
- gen_interface(G, N, X),
- gen(G, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, const) ->
- ic_constant_java:gen(G, N, X),
- gen(G, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, op) ->
- gen(G, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, attr) ->
- gen(G, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, except) ->
- gen_exception(G, N, X),
- gen(G, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, enum) ->
- ic_enum_java:gen(G, N, X),
- gen(G, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, struct) ->
- ic_struct_java:gen(G, N, X),
- gen(G, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, union) ->
- ic_union_java:gen(G, N, X),
- gen(G, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, typedef) ->
- gen_typedef(G, N, X),
- gen(G, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, member) ->
- %%?PRINTDEBUG2("gen member: ~p\n",[ic_forms:get_type(X)]),
- gen_member(G, N, X),
- gen(G, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, case_dcl) ->
- %%?PRINTDEBUG2("gen case decl: ~p\n",[ic_forms:get_type(X)]),
- gen(G, N, [ic_forms:get_type(X)]),
- gen(G, N, Xs);
-
-gen(G, N, [_|Xs]) ->
- gen(G, N, Xs);
-
-gen(_G, _N, []) ->
- ok.
-
-
-%%%--------------------------------------------
-%%%
-%%% Just generates the directory to host
-%%% the module files
-%%%
-%%%--------------------------------------------
-
-gen_module(G, N, X) ->
- case ic_genobj:do_gen(G) of
-
- true -> %% Generate & register
- N1 = [ic_forms:get_id2(X) | N],
- %% Create directory
- ic_file:createJavaDirectory(G, N1),
- gen(G, N1, ic_forms:get_body(X));
-
- false -> %% Register only
- N1 = [ic_forms:get_id2(X) | N],
- reg(G, N1, ic_forms:get_body(X))
- end.
-
-reg(G, N, [X|_Xs]) when is_record(X, module) ->
- reg(G, [ic_forms:get_id2(X) | N], ic_forms:get_body(X));
-
-reg(G, N, [X|_Xs]) when is_record(X, interface) ->
- reg(G, [ic_forms:get_id2(X) | N], ic_forms:get_body(X));
-
-reg(G, N, [X|Xs]) when is_record(X, typedef) ->
- Name = ic_util:to_dot(G,[ic_forms:get_java_id(X) | N]),
- case X#typedef.type of
- {scoped_id,_,_,_} ->
- {FullScopedName, _, _, _} =
- ic_symtab:get_full_scoped_name(G, N, X#typedef.type),
- Type = ic_code:get_basetype(G, ic_util:to_dot(G,FullScopedName)),
- ic_code:insert_typedef(G, Name, Type);
- _ ->
- ok
- end,
- reg(G, N, Xs);
-
-reg(G, N, [_|Xs]) ->
- reg(G, N, Xs);
-
-reg(_G, _N, []) ->
- ok.
-
-
-
-
-%%%----------------------------------------------
-%%%
-%%% Generates the interface code
-%%%
-%%%----------------------------------------------
-
-gen_interface(G, N, X) ->
- case ic_genobj:do_gen(G) of
- true ->
- G1 = ic_file:javaInterfaceFilePush(G, N, X),
-
- %% Generate Interface file
- InterfaceFd = ic_genobj:interfacefiled(G1),
- emit_interface(G1, N, X, InterfaceFd),
-
- %% Generate Helper file
- HelperFd = ic_genobj:helperfiled(G1),
- emit_helper(G1, N, X, HelperFd),
-
- %% Generate Holder file
- HolderFd = ic_genobj:holderfiled(G1),
- emit_holder(G1, N, X, HolderFd),
-
- %% Generate Stub file
- StubFd = ic_genobj:stubfiled(G1),
- emit_stub(G1,N,X,StubFd), %<--------------------------------------------------- 1
-
- %% Generate Skeleton file
- SkelFd = ic_genobj:skelfiled(G1),
- emit_skel(G1, N, X, SkelFd),
-
- ic_file:javaInterfaceFilePop(G1);
- false ->
- ok
- end.
-
-
-
-
-%%%--------------------------------------------
-%%%
-%%% Typedef redirection
-%%%
-%%%--------------------------------------------
-
-gen_typedef(G, N, X) ->
- Name = ic_util:to_dot(G,[ic_forms:get_java_id(X) | N]),
- case X#typedef.type of
- {scoped_id,_,_,_} ->
- {FullScopedName, _, _, _} =
- ic_symtab:get_full_scoped_name(G, N, X#typedef.type),
- Type = ic_code:get_basetype(G, ic_util:to_dot(G,FullScopedName)),
- ic_code:insert_typedef(G, Name, Type);
- _ ->
- ok
- end,
- gen_typedef_1(G, N, X, ic_forms:get_body(X)).
-
-gen_typedef_1(G, N, X, Type) when is_record(Type, sequence) ->
- ic_sequence_java:gen(G, N, Type, ic_forms:get_java_id(X));
-gen_typedef_1(G, N, X, Type) when is_record(Type, array) ->
- ic_array_java:gen(G, N, X, Type);
-gen_typedef_1(G, N, X, _Type) ->
- gen_typedef_2(G, N, X, X#typedef.id),
- ok.
-
-gen_typedef_2(G, N, X, Type) when is_record(Type, array) ->
- gen_typedef_1(G, N, X, Type);
-gen_typedef_2(G, N, X, Type) when is_list(Type) ->
- case Type of
- [] ->
- ok;
- _ ->
- gen_typedef_2(G, N, X, hd(Type)),
- gen_typedef_2(G, N, X, tl(Type))
- end;
-%gen_typedef_2(G, N, X, Type) -> %% Generating Helpers for typedef
-% %% Stoped due to compatibility problems
-% %% with erl_genserv backend
-% case ic_java_type:isBasicType(G,N,X#typedef.type) of
-% true ->
-% ok;
-% false ->
-% case ic_forms:get_type_code(G,N,X#typedef.type) of
-% {'tk_struct', _, _, _} ->
-% ic_struct_java:gen(G, N, X);
-% {'tk_sequence',_,_} ->
-% ic_sequence_java:gen(G, N, X, ic_forms:get_java_id(X)),
-% ok;
-% _ ->
-% ok
-% end
-% end;
-gen_typedef_2(_G, _N, _X, _Type) ->
- ok.
-
-
-
-%%%--------------------------------------------
-%%%
-%%% Member redirection
-%%%
-%%%--------------------------------------------
-
-gen_member(G, N, X) ->
- gen_member_1(G, N, X, [X#member.type]),
- gen_member_2(G, N, X, X#member.id).
-
-
-gen_member_1(_G, _N, _X, []) ->
- ok;
-
-gen_member_1(G, N, X, [T|Ts]) when is_record(T, sequence) ->
- ic_sequence_java:gen(G, N, T, ic_forms:get_java_id(X)),
- gen_member_1(G, N, X, Ts);
-
-gen_member_1(G, N, X, [T|Ts]) ->
- gen(G,N,[T]),
- gen_member_1(G,N,X,Ts).
-
-
-gen_member_2(_G, _N, _X, []) ->
- ok;
-
-gen_member_2(G, N, X, [T|Ts]) when is_record(T, array) -> %% BUG !
- ic_array_java:gen(G, N, X, T),
- gen_member_2(G, N, X, Ts);
-
-gen_member_2(G, N, X, [_T|Ts]) ->
- gen_member_2(G, N, X, Ts).
-
-
-
-gen_exception(_G, N, X) ->
- io:format("Warning : Exceptions not supported for java mapping, ~p ignored\n",
- [ic_util:to_colon([ic_forms:get_java_id(X)|N])]),
- ok.
-
-
-
-%%%-----------------------------------------------------
-%%%
-%%% Interface file generation
-%%%
-%%%-----------------------------------------------------
-
-emit_interface(G, N, X, Fd) ->
- Interface = ic_forms:get_java_id(X), %% Java Interface Name
- IFCName = ic_forms:get_id2(X), %% Internal Interface Name
-
- ic_codegen:emit(Fd, "public interface ~s {\n\n",[Interface]),
- Body = ic_forms:get_body(X),
-
- %% Generate type declarations inside interface
- gen(G, [IFCName |N], Body),
-
- lists:foreach(fun({_Name, Body1}) ->
- emit_interface_prototypes(G, [IFCName|N], Body1, Fd) end,
- [{x, Body} | X#interface.inherit_body]),
-
- ic_codegen:emit(Fd, "}\n\n").
-
-
-emit_interface_prototypes(G, N, [X |Xs], Fd) when is_record(X, op) ->
-
- {_, ArgNames, TypeList} = extract_info(G, N, X),
- {R, ParameterTypes, _} = TypeList,
-
- OpName = ic_forms:get_java_id(X),
- RT = ic_java_type:getParamType(G,N,R,ret),
- PL = ic_util:mk_list(gen_par_list(G, N, X, ParameterTypes,ArgNames)),
-
- ic_codegen:emit(Fd, "/*\n"),
- ic_codegen:emit(Fd, " * Operation ~p interface functions \n", [ic_util:to_colon([OpName|N])]),
- ic_codegen:emit(Fd, " */\n\n"),
-
- ic_codegen:emit(Fd, "~s ~s(~s)\n",[RT, OpName, PL]),
- ic_codegen:emit(Fd, " throws java.lang.Exception;\n\n\n"),
-
- emit_interface_prototypes(G, N, Xs, Fd);
-emit_interface_prototypes(G, N, [X |Xs], Fd) when is_record(X, attr) ->
- ic_attribute_java:emit_attribute_prototype(G, N, X, Fd),
- emit_interface_prototypes(G, N, Xs, Fd);
-emit_interface_prototypes(G, N, [_X|Xs], Fd) ->
- emit_interface_prototypes(G, N, Xs, Fd);
-emit_interface_prototypes(_G, _N, [], _Fd) -> ok.
-
-
-
-
-%%%-----------------------------------------------------
-%%%
-%%% Holder file generation
-%%%
-%%%-----------------------------------------------------
-
-emit_holder(_G, N, X, Fd) ->
- InterfaceName = ic_forms:get_java_id(X),
- FullInterfaceName = ic_util:to_dot([InterfaceName|N]),
-
- ic_codegen:emit(Fd, "public final class ~sHolder {\n\n",[InterfaceName]),
-
- ic_codegen:emit(Fd, " // Instance variable\n"),
- ic_codegen:emit(Fd, " public ~s value;\n\n",[FullInterfaceName]),
-
- ic_codegen:emit(Fd, " // Constructors\n"),
- ic_codegen:emit(Fd, " public ~sHolder() {\n",[InterfaceName]),
- ic_codegen:emit(Fd, " this(null);\n"),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public ~sHolder(~s _arg) {\n",[InterfaceName, FullInterfaceName]),
- ic_codegen:emit(Fd, " value = _arg;\n"),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public void _marshal() {\n"),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public void _unmarshal() {\n"),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, "}\n\n").
-
-
-
-
-%%%-----------------------------------------------------
-%%%
-%%% Helper file generation
-%%%
-%%%-----------------------------------------------------
-emit_helper(G, N, X, Fd) ->
- InterfaceName = ic_forms:get_java_id(X),
- FullInterfaceName = ic_util:to_dot([InterfaceName|N]),
-
- ic_codegen:emit(Fd, "public final class ~sHelper {\n\n",[InterfaceName]),
-
- ic_codegen:emit(Fd, " // Constructor\n"),
- ic_codegen:emit(Fd, " public ~sHelper() {\n",[InterfaceName]),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public static void _marshal() {\n"),
- ic_codegen:emit(Fd, " // Writing the object to the message\n"),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public static ~s _unmarshal() {\n",[FullInterfaceName]),
- ic_codegen:emit(Fd, " // Reading the object from the message\n"),
- ic_codegen:emit(Fd, " return null;\n"),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public static java.lang.String id() {\n"),
- ic_codegen:emit(Fd, " return ~p;\n",[ictk:get_IR_ID(G, N, X)]),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, "}\n\n").
-
-
-
-
-%%%-----------------------------------------------------
-%%%
-%%% Stub file generation
-%%%
-%%%-----------------------------------------------------
-
-emit_stub(G, N, X, Fd) ->
- InterfaceName = ic_forms:get_java_id(X), %% Java Interface Name
- IFCName = ic_forms:get_id2(X), %% Internal Interface Name
-
- FullInterfaceName = ic_util:to_dot([InterfaceName|N]),
- Body = ic_forms:get_body(X),
-
- ic_codegen:emit(Fd, "public class _~sStub implements ~s {\n\n",
- [InterfaceName,FullInterfaceName]),
-
- ic_codegen:emit(Fd, " // Client data\n"),
- ic_codegen:emit(Fd, " public ~sEnvironment _env;\n\n",[?ICPACKAGE]),
-
- ic_codegen:emit(Fd, " // Constructors\n"),
- ic_codegen:emit(Fd, " public _~sStub(~sOtpSelf _self,\n",[InterfaceName,?ERLANGPACKAGE]),
- ic_codegen:emit(Fd, " ~sOtpPeer _peer,\n",[?ERLANGPACKAGE]),
- ic_codegen:emit(Fd, " java.lang.Object _server) throws java.lang.Exception {\n\n"),
-
- ic_codegen:emit(Fd, " _env =\n"),
- ic_codegen:emit(Fd, " new ~sEnvironment(_self, _peer, _server);\n",[?ICPACKAGE]),
- ic_codegen:emit(Fd, " _env.connect();\n"),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public _~sStub(java.lang.String _selfN,\n",[InterfaceName]),
- ic_codegen:emit(Fd, " java.lang.String _peerN,\n"),
- ic_codegen:emit(Fd, " java.lang.String _cookie,\n"),
- ic_codegen:emit(Fd, " java.lang.Object _server) throws java.lang.Exception {\n\n"),
- ic_codegen:emit(Fd, " _env =\n"),
- ic_codegen:emit(Fd, " new ~sEnvironment(_selfN, _peerN, _cookie, _server);\n",[?ICPACKAGE]),
- ic_codegen:emit(Fd, " _env.connect();\n"),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public _~sStub(~sOtpConnection _connection,\n",[InterfaceName, ?ERLANGPACKAGE]),
- ic_codegen:emit(Fd, " java.lang.Object _server) throws java.lang.Exception {\n\n"),
- ic_codegen:emit(Fd, " _env =\n"),
- ic_codegen:emit(Fd, " new ~sEnvironment(_connection, _server);\n",[?ICPACKAGE]),
- ic_codegen:emit(Fd, " _env.connect();\n"),
- ic_codegen:emit(Fd, " }\n\n"),
-
- emit_message_reference_extraction(Fd),
-
- emit_servers_object_access(Fd),
-
- emit_client_connection_close(Fd),
-
- emit_client_connection_reconnect(Fd),
-
- emit_client_destroy(Fd),
-
- lists:foreach(fun({_Name, Body1}) ->
- emit_op_implementation(G, [IFCName|N], Body1, Fd) end,
- [{x, Body} | X#interface.inherit_body]),
-
- ic_codegen:emit(Fd, "}\n\n").
-
-
-emit_op_implementation(G, N, [X |Xs], Fd) when is_record(X, op) ->
-
- WireOpName = ic_forms:get_id2(X),
- OpName = ic_forms:get_java_id(WireOpName),
- {_, ArgNames, TypeList} = extract_info(G, N, X),
- {R, ParamTypes, _} = TypeList,
-
- RT = ic_java_type:getParamType(G,N,R,ret),
- PL = ic_util:mk_list(gen_par_list(G, N, X, ParamTypes, ArgNames)),
- CMCPL = ic_util:mk_list(gen_client_marshal_call_par_list(ArgNames)),
-
- ic_codegen:emit(Fd, " // Operation ~p implementation\n", [ic_util:to_colon([WireOpName|N])]),
- ic_codegen:emit(Fd, " public ~s ~s(~s)\n", [RT, OpName, PL]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
-
- %% Function marshal call
- ic_codegen:emit(Fd, " // Calling the marshal function\n"),
-
- case CMCPL of
- "" ->
- ic_codegen:emit(Fd, " _~s_marshal(_env);\n\n",[OpName]);
- _ ->
- ic_codegen:emit(Fd, " _~s_marshal(_env, ~s);\n\n",[OpName, CMCPL])
- end,
-
- %% Sending call
- ic_codegen:emit(Fd, " // Message send\n"),
- ic_codegen:emit(Fd, " _env.send();\n\n"),
-
- case ic_forms:is_oneway(X) of
- true ->
- ok;
- false ->
- %% Receiving return values
- ic_codegen:emit(Fd, " // Message receive\n"),
- ic_codegen:emit(Fd, " _env.receive();\n\n"),
-
- %% Function unmarshal call
- case RT of
- "void" ->
- case ic_util:mk_list(gen_client_unmarshal_call_par_list(ArgNames)) of
- "" ->
- ic_codegen:emit(Fd, " // Calling the unmarshal function\n"),
- ic_codegen:emit(Fd, " _~s_unmarshal(_env);\n",
- [OpName]);
- UMCPL ->
- ic_codegen:emit(Fd, " // Calling the unmarshal function\n"),
- ic_codegen:emit(Fd, " _~s_unmarshal(_env, ~s);\n",
- [OpName,UMCPL])
- end;
- _ ->
- ic_codegen:emit(Fd, " // Calling the unmarshal function\n"),
- case ic_util:mk_list(gen_client_unmarshal_call_par_list(ArgNames)) of
- "" ->
- ic_codegen:emit(Fd, " return _~s_unmarshal(_env);\n",
- [OpName]);
- UMCPL ->
- ic_codegen:emit(Fd, " return _~s_unmarshal(_env, ~s);\n",
- [OpName,UMCPL])
- end
- end
- end,
- ic_codegen:emit(Fd, " }\n\n"),
-
- %% Marshalling
- emit_op_marshal(G, N, X, Fd),
-
- %% UnMarshalling
- emit_op_unmarshal(G, N, X, Fd),
- ic_codegen:emit(Fd, "\n"),
-
- emit_op_implementation(G, N, Xs, Fd);
-emit_op_implementation(G, N, [X |Xs], Fd) when is_record(X, attr) ->
- ic_attribute_java:emit_attribute_stub_code(G, N, X, Fd),
- emit_op_implementation(G, N, Xs, Fd);
-emit_op_implementation(G, N, [_X|Xs], Fd) ->
- emit_op_implementation(G, N, Xs, Fd);
-emit_op_implementation(_G, _N, [], _Fd) -> ok.
-
-
-
-
-
-%%---------------------------------------
-%%
-%% Marshal operation generation
-%%
-%%---------------------------------------
-
-emit_op_marshal(G, N, X, Fd) ->
- WireOpName = ic_forms:get_id2(X),
- OpName = ic_forms:get_java_id(WireOpName),
- {_, ArgNames, TypeList} = extract_info(G, N, X),
- {_R, ParamTypes, _} = TypeList,
-
- PL = ic_util:mk_list(gen_marshal_par_list(G, N, X, ParamTypes, ArgNames)),
-
- ic_codegen:emit(Fd, " // Marshal operation for ~p\n", [OpName]),
- case PL of
- "" ->
- ic_codegen:emit(Fd, " public static void _~s_marshal(~sEnvironment __env)\n",
- [OpName, ?ICPACKAGE]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n");
- _ ->
- ic_codegen:emit(Fd, " public static void _~s_marshal(~sEnvironment __env, ~s)\n",
- [OpName, ?ICPACKAGE, PL]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n")
- end,
- %% Message encoding
- emit_op_encode(G, N, X, OpName, WireOpName, ParamTypes, ArgNames, Fd),
-
- ic_codegen:emit(Fd, " }\n\n").
-
-
-emit_op_encode(G, N, X, _OpN, WOpN, ParamTypes, ArgNames, Fd) ->
-
- OpCallName = case ic_options:get_opt(G, scoped_op_calls) of
- true ->
- ic_util:to_undersc([WOpN|N]);
- false ->
- WOpN
- end,
-
- SendParamNr = count_client_send(ArgNames),
-
- ic_codegen:emit(Fd, " ~sOtpOutputStream __os = __env.getOs();\n\n",
- [?ERLANGPACKAGE]),
-
- case ic_forms:is_oneway(X) of
- true ->
- %% Initiating call tuple
- ic_codegen:emit(Fd, " // Message header assembly\n"),
- ic_codegen:emit(Fd, " __os.reset();\n"),
- ic_codegen:emit(Fd, " __os.write_tuple_head(2);\n"),
- ic_codegen:emit(Fd, " __os.write_atom(\"$gen_cast\");\n\n");
- false ->
- %% Initiating call tuple
- ic_codegen:emit(Fd, " // Message header assembly\n"),
- ic_codegen:emit(Fd, " __os.reset();\n"),
- ic_codegen:emit(Fd, " __os.write_tuple_head(3);\n"),
- ic_codegen:emit(Fd, " __os.write_atom(\"$gen_call\");\n\n"),
-
- %% Initiating call identity tuple
- ic_codegen:emit(Fd, " // Message identity part creation\n"),
- ic_codegen:emit(Fd, " __os.write_tuple_head(2);\n"),
- ic_codegen:emit(Fd, " __env.write_client_pid();\n"),
- ic_codegen:emit(Fd, " __env.write_client_ref();\n\n")
- end,
-
- %% Operation part initializations
- case SendParamNr > 0 of
- true ->
- ic_codegen:emit(Fd, " // Operation attribute creation\n"),
- ic_codegen:emit(Fd, " __os.write_tuple_head(~p);\n", [SendParamNr+1]),
- ic_codegen:emit(Fd, " __os.write_atom(~p);\n", [OpCallName]),
- emit_op_encode_loop(G, N, X, ParamTypes, ArgNames, 1, Fd);
- false -> %% No in/inout paramaters
- ic_codegen:emit(Fd, " __os.write_atom(~p);\n", [OpCallName])
- end.
-
-
-
-emit_op_encode_loop(_,_,_,_,[],_,_Fd) ->
- ok;
-emit_op_encode_loop(G, N, X, [_Type|Types],[{out, _Arg}|Args], Counter, Fd) ->
- emit_op_encode_loop(G, N, X, Types, Args, Counter, Fd);
-emit_op_encode_loop(G, N, X, [Type|Types], [{inout, Arg}|Args], Counter, Fd) ->
- case ic_java_type:isBasicType(G, N, Type) of
- true ->
- ic_codegen:emit(Fd, " __os~s(~s.value);\n",
- [ic_java_type:marshalFun(G, N, X, Type),Arg]);
- false ->
- ic_codegen:emit(Fd, " ~s(__os, ~s.value);\n",
- [ic_java_type:marshalFun(G, N, X, Type),Arg])
- end,
- emit_op_encode_loop(G, N, X, Types, Args, Counter+1, Fd);
-emit_op_encode_loop(G, N, X, [Type|Types], [{in, Arg}|Args], Counter, Fd) ->
- case ic_java_type:isBasicType(G, N, Type) of
- true ->
- ic_codegen:emit(Fd, " __os~s(~s);\n",
- [ic_java_type:marshalFun(G, N, X, Type),Arg]);
- false ->
- ic_codegen:emit(Fd, " ~s(__os, ~s);\n",
- [ic_java_type:marshalFun(G, N, X, Type),Arg])
- end,
- emit_op_encode_loop(G, N, X, Types, Args, Counter+1, Fd).
-
-
-
-
-
-
-%%-------------------------------------
-%%
-%% UnMarshal operation generation
-%%
-%%-------------------------------------
-
-emit_op_unmarshal(G, N, X, Fd) ->
- case ic_forms:is_oneway(X) of
- true ->
- ok;
- false ->
- OpName = ic_forms:get_java_id(X),
- {_, ArgNames, TypeList} = extract_info(G, N, X),
- {R, ParamTypes, _} = TypeList,
-
- RT = ic_java_type:getParamType(G,N,R,ret),
- PL = ic_util:mk_list(gen_unmarshal_par_list(G, N, X, ParamTypes, ArgNames)),
-
- case PL of
- "" ->
- case RT of
- "void" ->
- ic_codegen:emit(Fd, " // Unmarshal operation for ~p\n", [OpName]),
- ic_codegen:emit(Fd, " public static void _~s_unmarshal(~sEnvironment __env)\n",
- [OpName, ?ICPACKAGE]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
- ic_codegen:emit(Fd, " __env.getIs().read_atom();\n"),
- ic_codegen:emit(Fd, " }\n\n");
- _ ->
- ic_codegen:emit(Fd, " // Unmarshal operation for ~p\n", [OpName]),
- ic_codegen:emit(Fd, " public static ~s _~s_unmarshal(~sEnvironment __env)\n",
- [RT, OpName, ?ICPACKAGE]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
-
- ic_codegen:emit(Fd, " // Get input stream\n"),
- ic_codegen:emit(Fd, " ~sOtpInputStream __is = __env.getIs();\n\n",
- [?ERLANGPACKAGE]),
-
- emit_op_decode(G, N, X, R, RT, ParamTypes, ArgNames, Fd),
- ic_codegen:emit(Fd, " }\n\n")
- end;
- _ ->
- ic_codegen:emit(Fd, " // Unmarshal operation for ~p\n", [OpName]),
- ic_codegen:emit(Fd, " public static ~s _~s_unmarshal(~sEnvironment __env, ~s)\n",
- [RT, OpName, ?ICPACKAGE, PL]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
-
- ic_codegen:emit(Fd, " // Get input stream\n"),
- ic_codegen:emit(Fd, " ~sOtpInputStream __is = __env.getIs();\n\n",
- [?ERLANGPACKAGE]),
-
- emit_op_decode(G, N, X, R, RT, ParamTypes, ArgNames, Fd),
- ic_codegen:emit(Fd, " }\n\n")
- end
- end.
-
-
-emit_op_decode(G, N, X, R, RT, ParamTypes, ArgNames, Fd) ->
- ReceiveNr = count_client_receive(ArgNames),
-
- case RT of
- "void" ->
- case ReceiveNr > 0 of
- true ->
- ic_codegen:emit(Fd, " // Extracting output values\n"),
- ic_codegen:emit(Fd, " __is.read_tuple_head();\n"),
- ic_codegen:emit(Fd, " __is.read_atom();\n"),
- emit_op_decode_loop(G, N, X, ParamTypes, ArgNames, 1, Fd);
- false ->
- ic_codegen:emit(Fd, " __is.read_atom();\n")
- end;
- _ ->
- case ReceiveNr > 0 of
- true ->
- ic_codegen:emit(Fd, " // Extracting return/output values\n"),
- ic_codegen:emit(Fd, " __is.read_tuple_head();\n"),
- case ic_java_type:isBasicType(G,N,R) of
- true ->
- ic_codegen:emit(Fd, " ~s _result = __is~s;\n",
- [RT,ic_java_type:unMarshalFun(G, N, X, R)]);
- false ->
- ic_codegen:emit(Fd, " ~s _result = ~s.unmarshal(__is);\n",
- [RT, ic_java_type:getUnmarshalType(G,N,X,R)])
- end,
- emit_op_decode_loop(G, N, X, ParamTypes, ArgNames, 1, Fd),
-
- ic_codegen:nl(Fd),
- ic_codegen:emit(Fd, " return _result;\n");
- false ->
- ic_codegen:emit(Fd, " // Extracting return value\n"),
- case ic_java_type:isBasicType(G,N,R) of
- true ->
- ic_codegen:emit(Fd, " return __is~s;\n",
- [ic_java_type:unMarshalFun(G, N, X, R)]);
- false ->
- ic_codegen:emit(Fd, " return ~s.unmarshal(__is);\n",
- [ic_java_type:getUnmarshalType(G,N,X,R)])
- end
- end
- end.
-
-emit_op_decode_loop(_,_,_,_,[],_,_Fd) ->
- ok;
-emit_op_decode_loop(G, N, X, [_Type|Types], [{in, _Arg}|Args], Counter, Fd) ->
- emit_op_decode_loop(G, N, X, Types, Args, Counter, Fd);
-emit_op_decode_loop(G, N, X, [Type|Types], [{_, Arg}|Args], Counter, Fd) ->
- case ic_java_type:isBasicType(G,N,Type) of
- true ->
- ic_codegen:emit(Fd, " ~s.value = __is~s;\n",
- [Arg,
- ic_java_type:unMarshalFun(G, N, X, Type)]);
- false ->
- ic_codegen:emit(Fd, " ~s.value = ~s.unmarshal(__is);\n",
- [Arg,
- ic_java_type:getUnmarshalType(G, N, X, Type)])
- end,
- emit_op_decode_loop(G, N, X, Types, Args, Counter+1, Fd).
-
-
-
-emit_message_reference_extraction(Fd) ->
- ic_codegen:emit(Fd, " // Returns call reference\n"),
- ic_codegen:emit(Fd, " public ~sOtpErlangRef __getRef()\n",
- [?ERLANGPACKAGE]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n"),
- ic_codegen:emit(Fd, " return _env.received_ref();\n"),
- ic_codegen:emit(Fd, " }\n\n").
-
-emit_servers_object_access(Fd) ->
- ic_codegen:emit(Fd, " // Returns the server\n"),
- ic_codegen:emit(Fd, " public java.lang.Object __server() {\n"),
- ic_codegen:emit(Fd, " return _env.server();\n"),
- ic_codegen:emit(Fd, " }\n\n").
-
-emit_client_connection_close(Fd) ->
- ic_codegen:emit(Fd, " // Closes connection\n"),
- ic_codegen:emit(Fd, " public void __disconnect() {\n"),
- ic_codegen:emit(Fd, " _env.disconnect();\n"),
- ic_codegen:emit(Fd, " }\n\n").
-
-emit_client_connection_reconnect(Fd) ->
- ic_codegen:emit(Fd, " // Reconnects client\n"),
- ic_codegen:emit(Fd, " public void __reconnect()\n"),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n"),
- ic_codegen:emit(Fd, " _env.reconnect();\n"),
- ic_codegen:emit(Fd, " }\n\n").
-
-emit_client_destroy(Fd) ->
- ic_codegen:emit(Fd, " // Destroy server\n"),
- ic_codegen:emit(Fd, " public void __stop()\n"),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n"),
- ic_codegen:emit(Fd, " _env.client_stop_server();\n"),
- ic_codegen:emit(Fd, " }\n\n").
-
-
-
-%%%----------------------------------------------------
-%%%
-%%% Generates the server code
-%%%
-%%%----------------------------------------------------
-
-emit_skel(G, N, X, Fd) ->
- InterfaceName = ic_forms:get_java_id(X),
- FullInterfaceName = ic_util:to_dot([InterfaceName|N]),
-
- ic_codegen:emit(Fd, "public abstract class _~sImplBase implements ~s {\n\n",
- [InterfaceName,FullInterfaceName]),
-
- ic_codegen:emit(Fd, " // Server data\n"),
- ic_codegen:emit(Fd, " protected ~sEnvironment _env = null;\n\n",[?ICPACKAGE]),
-
- ic_codegen:emit(Fd, " // Constructors\n"),
- ic_codegen:emit(Fd, " public _~sImplBase() {\n",[InterfaceName]),
- ic_codegen:emit(Fd, " }\n\n"),
-
- emit_caller_pid(G, N, X, Fd),
-
- %% Emit operation dictionary
- emit_dictionary(G, N, X, Fd),
-
- %% Emit server switch
- emit_server_switch(G, N, X, Fd),
-
- ic_codegen:emit(Fd, "}\n").
-
-
-emit_server_switch(G, N, X, Fd) ->
-
- IFCName = ic_forms:get_id2(X), %% Internal Interface Name
- Body = ic_forms:get_body(X),
- Counter = 0,
-
- ic_codegen:emit(Fd, " // Operation invokation\n"),
- ic_codegen:emit(Fd, " public ~sOtpOutputStream invoke(~sOtpInputStream _in)\n",
- [?ERLANGPACKAGE,?ERLANGPACKAGE]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
-
- ic_codegen:emit(Fd, " // Create a new environment if needed\n"),
- ic_codegen:emit(Fd, " if (_env == null)\n"),
- ic_codegen:emit(Fd, " _env = new com.ericsson.otp.ic.Environment();\n\n"),
-
- ic_codegen:emit(Fd, " // Unmarshal head\n"),
- ic_codegen:emit(Fd, " _env.uHead(_in);\n\n"),
-
- ic_codegen:emit(Fd, " // Switch over operation\n"),
- ic_codegen:emit(Fd, " return __switch(_env);\n"),
-
- ic_codegen:emit(Fd, " }\n\n"),
-
-
- ic_codegen:emit(Fd, " // Operation switch\n"),
- ic_codegen:emit(Fd, " public ~sOtpOutputStream __switch(~sEnvironment __env)\n", [?ERLANGPACKAGE,?ICPACKAGE]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
-
- ic_codegen:emit(Fd, " // Setup streams and operation label\n"),
- ic_codegen:emit(Fd, " ~sOtpOutputStream __os = __env.getOs();\n",[?ERLANGPACKAGE]),
- ic_codegen:emit(Fd, " __os.reset();\n"),
- ic_codegen:emit(Fd, " int __label = __env.uLabel(__operations);\n\n"),
-
- ic_codegen:emit(Fd, " // Switch over operation\n"),
- ic_codegen:emit(Fd, " switch(__label) {\n\n"),
-
- OpNr = emit_server_op_switch_loop(G,
- [IFCName|N],
- [{x, Body} | X#interface.inherit_body],
- Counter,
- Fd),
-
- ic_codegen:emit(Fd, " case ~p: { // Standard stop operation\n\n",[OpNr]),
- ic_codegen:emit(Fd, " __env.server_stop_server();\n\n"),
- ic_codegen:emit(Fd, " } break;\n\n"),
-
- ic_codegen:emit(Fd, " default: // It will never come down here \n"),
- ic_codegen:emit(Fd, " throw new java.lang.Exception(\"BAD OPERATION\");\n\n", []),
-
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " if(__os.count() > 0)\n"),
- ic_codegen:emit(Fd, " return __os;\n\n"),
-
- ic_codegen:emit(Fd, " return null;\n"),
- ic_codegen:emit(Fd, " }\n\n").
-
-
-
-emit_server_op_switch_loop(_G, _N, [], C, _Fd) ->
- C;
-emit_server_op_switch_loop(G, N, [{_,X}|Xs], C, Fd) ->
- C1 = emit_server_op_switch(G, N, X, C, Fd),
- emit_server_op_switch_loop(G, N, Xs, C1, Fd).
-
-
-emit_server_op_switch(G, N, [X|Xs], C, Fd) when is_record(X, op) ->
-
- OpName = ic_forms:get_java_id(X),
-
- ic_codegen:emit(Fd, " case ~p: { // Operation ~s\n\n",[C,ic_util:to_dot([OpName|N])]),
-
- emit_invoke(G, N, X, Fd),
-
- ic_codegen:emit(Fd, " } break;\n\n"),
-
- emit_server_op_switch(G, N, Xs, C+1, Fd);
-emit_server_op_switch(G, N, [X |Xs], C, Fd) when is_record(X, attr) ->
- C1 = ic_attribute_java:emit_attribute_switch_case(G,N,X,Fd,C),
- emit_server_op_switch(G, N, Xs, C1, Fd);
-emit_server_op_switch(G, N, [_X|Xs], C, Fd) ->
- emit_server_op_switch(G, N, Xs, C, Fd);
-emit_server_op_switch(_G, _N, [], C, _Fd) ->
- C.
-
-
-emit_caller_pid(_G, _N, _X, Fd) ->
- ic_codegen:emit(Fd, " // Extracts caller identity\n"),
- ic_codegen:emit(Fd, " public ~sOtpErlangPid __getCallerPid() {\n", [?ERLANGPACKAGE]),
- ic_codegen:emit(Fd, " return _env.getScaller();\n"),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public ~sOtpErlangPid __getCallerPid(~sEnvironment __env) {\n",
- [?ERLANGPACKAGE, ?ICPACKAGE]),
- ic_codegen:emit(Fd, " return __env.getScaller();\n"),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public boolean __isStopped() {\n"),
- ic_codegen:emit(Fd, " return _env.isStopped();\n"),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public boolean __isStopped(~sEnvironment __env) {\n",
- [?ICPACKAGE]),
- ic_codegen:emit(Fd, " return __env.isStopped();\n"),
- ic_codegen:emit(Fd, " }\n\n").
-
-
-
-%% Creates an operation dictionary
-emit_dictionary(G, N, X, Fd) ->
-
- Counter = 0,
- Body = ic_forms:get_body(X),
-
- ic_codegen:emit(Fd, " // Operation dictionary\n"),
- ic_codegen:emit(Fd, " private static java.util.Dictionary __operations = new java.util.Hashtable();\n"),
- ic_codegen:emit(Fd, " static {\n"),
-
- emit_dictionary_loop(G,
- [ic_forms:get_id2(X)|N],
- [{x, Body} | X#interface.inherit_body],
- Counter,
- Fd),
-
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " // Operation dictionary access\n"),
- ic_codegen:emit(Fd, " public static java.util.Dictionary __operations() {\n"),
- ic_codegen:emit(Fd, " return __operations;\n"),
- ic_codegen:emit(Fd, " }\n\n").
-
-
-
-
-emit_dictionary_loop(_G, _N, [], C, Fd) ->
- ic_codegen:emit(Fd, " __operations.put(~p, new java.lang.Integer(~p));\n",
- ["stop",C]);
-emit_dictionary_loop(G, N, [{_,X}|Xs], C, Fd) ->
- C1 = emit_dictionary(G, N, X, C, Fd),
- emit_dictionary_loop(G, N, Xs, C1, Fd).
-
-
-emit_dictionary(G, N, [X|Xs], C, Fd) when is_record(X, op) ->
-
- OpName = case ic_options:get_opt(G, scoped_op_calls) of
- true ->
- ic_util:to_undersc([ic_forms:get_id2(X)|N]);
- false ->
- ic_forms:get_id2(X)
- end,
-
- ic_codegen:emit(Fd, " __operations.put(~p, new java.lang.Integer(~p));\n",
- [OpName,C]),
- emit_dictionary(G, N, Xs, C+1, Fd);
-
-emit_dictionary(G, N, [X |Xs], C, Fd) when is_record(X, attr) ->
- C1 = ic_attribute_java:emit_atrribute_on_dictionary(G, N, X, Fd, C),
- emit_dictionary(G, N, Xs, C1, Fd);
-
-emit_dictionary(G, N, [_X|Xs], C, Fd) ->
- emit_dictionary(G, N, Xs, C, Fd);
-
-emit_dictionary(_G, _N, [], C, _Fd) ->
- C.
-
-
-
-emit_invoke(G, N, X, Fd) ->
-
- {_, ArgNames, TypeList} = extract_info(G, N, X),
- {R, ParamTypes, _} = TypeList,
- OpName = ic_forms:get_java_id(X),
- RT = ic_java_type:getParamType(G,N,R,ret),
- PL = ic_util:mk_list(gen_cb_arg_list(ArgNames)),
- OutParamNr = count_server_send(ArgNames),
-
- case count_server_receive(ArgNames) of
- 0 ->
- ok;
- _C ->
- ic_codegen:emit(Fd, " // Preparing input\n"),
- ic_codegen:emit(Fd, " ~sOtpInputStream __is = __env.getIs();\n",
- [?ERLANGPACKAGE]),
- emit_server_unmarshal_loop(G, N, X, ParamTypes, ArgNames, 1, Fd)
- end,
-
- ic_codegen:emit(Fd, " // Calling implementation function\n"),
- case RT of
- "void" ->
- ic_codegen:emit(Fd, " this.~s(~s);\n\n",
- [OpName,PL]);
- _ ->
- ic_codegen:emit(Fd, " ~s _result = this.~s(~s);\n\n",
- [RT, OpName, PL])
- end,
-
- case ic_forms:is_oneway(X) of
- true ->
- ok;
- false ->
- ic_codegen:emit(Fd, " // Marshaling output\n"),
- ic_codegen:emit(Fd, " ~sOtpErlangRef __ref = __env.getSref();\n",[?ERLANGPACKAGE]),
-
- case RT of
- "void" ->
- case OutParamNr > 0 of
- true ->
- ic_codegen:emit(Fd, " __os.write_tuple_head(2);\n"),
- ic_codegen:emit(Fd, " __os.write_ref(__ref.node(),__ref.ids(),__ref.creation()); // Call reference\n"),
- ic_codegen:emit(Fd, " __os.write_tuple_head(~p);\n",[OutParamNr+1]),
- ic_codegen:emit(Fd, " __os.write_atom(\"ok\");\n"),
- emit_server_marshal_loop(G, N, X, ParamTypes,ArgNames,1,Fd);
- false ->
- ic_codegen:emit(Fd, " __os.write_tuple_head(2);\n"),
- ic_codegen:emit(Fd, " __os.write_ref(__ref.node(),__ref.ids(),__ref.creation()); // Call reference\n"),
- ic_codegen:emit(Fd, " __os.write_atom(\"ok\");\n\n")
- end;
- _ ->
- case OutParamNr > 0 of
- true ->
- ic_codegen:emit(Fd, " __os.write_tuple_head(2);\n"),
- ic_codegen:emit(Fd, " __os.write_ref(__ref.node(),__ref.ids(),__ref.creation()); // Call reference\n"),
- ic_codegen:emit(Fd, " __os.write_tuple_head(~p);\n",[OutParamNr+1]),
-
- case ic_java_type:isBasicType(G,N,R) of
- true ->
- ic_codegen:emit(Fd, " __os~s(_result); // Return value\n",
- [ic_java_type:marshalFun(G,N,X,R)]);
- false ->
- ic_codegen:emit(Fd, " ~s(__os,_result); // Return value\n",
- [ic_java_type:marshalFun(G,N,X,R)])
- end,
- emit_server_marshal_loop(G, N, X, ParamTypes,ArgNames,1,Fd);
- false ->
- ic_codegen:emit(Fd, " __os.write_tuple_head(2);\n"),
- ic_codegen:emit(Fd, " __os.write_ref(__ref.node(),__ref.ids(),__ref.creation()); // Call reference\n"),
-
- case ic_java_type:isBasicType(G,N,R) of
- true ->
- ic_codegen:emit(Fd, " __os~s(_result); // Return value\n\n",
- [ic_java_type:marshalFun(G,N,X,R)]);
- false ->
- ic_codegen:emit(Fd, " ~s(__os,_result); // Return value\n\n",
- [ic_java_type:marshalFun(G,N,X,R)])
- end
- end
- end,
- ic_codegen:nl(Fd)
- end.
-
-
-emit_server_unmarshal_loop(_,_,_,_,[],_,Fd) ->
- ic_codegen:nl(Fd);
-emit_server_unmarshal_loop(G, N, X, [Type|Types], [{in, Arg}|Args], Counter, Fd) ->
- case ic_java_type:isBasicType(G,N,Type) of
- true ->
- ic_codegen:emit(Fd, " ~s ~s = __is~s; // In value\n",
- [ic_java_type:getType(G,N,Type),
- Arg,
- ic_java_type:unMarshalFun(G,N,X,Type)]);
- false ->
- ic_codegen:emit(Fd, " ~s ~s = ~s.unmarshal(__is); // In value\n",
- [ic_java_type:getType(G,N,Type),
- Arg,
- ic_java_type:getUnmarshalType(G,N,X,Type)])
- end,
- emit_server_unmarshal_loop(G, N, X, Types, Args, Counter+1, Fd);
-emit_server_unmarshal_loop(G, N, X, [Type|Types],[{inout, Arg}|Args], Counter, Fd) ->
- Holder = ic_java_type:getHolderType(G,N,Type),
- case ic_java_type:isBasicType(G,N,Type) of
- true ->
-% OtpEncVar = ic_java_type:getUnmarshalType(G,N,X,Type),
- ic_codegen:emit(Fd, " ~s _~s = __is~s;\n",
- [ic_java_type:getType(G,N,Type),
- Arg,
- ic_java_type:unMarshalFun(G,N,X,Type)]),
- ic_codegen:emit(Fd, " ~s ~s = new ~s(_~s); // InOut value\n",
- [Holder,
- Arg,
- Holder,
- Arg]);
- false ->
- ic_codegen:emit(Fd, " ~s ~s = new ~s(); // InOut value\n",
- [Holder,
- Arg,
- Holder]),
- ic_codegen:emit(Fd, " ~s._unmarshal(__is);\n",
- [Arg])
- end,
- emit_server_unmarshal_loop(G, N, X, Types, Args, Counter+1, Fd);
-emit_server_unmarshal_loop(G, N, X, [Type|Types],[{out, Arg}|Args], Counter, Fd) ->
- Holder = ic_java_type:getHolderType(G,N,Type),
- ic_codegen:emit(Fd, " ~s ~s = new ~s(); // Out value\n", [Holder, Arg, Holder]),
- emit_server_unmarshal_loop(G, N, X, Types, Args, Counter, Fd).
-
-
-emit_server_marshal_loop(_,_,_,_,[],_,_Fd) ->
- ok;
-emit_server_marshal_loop(G, N, X, [_Type|Types],[{in, _Arg}|Args], Counter, Fd) ->
- emit_server_marshal_loop(G, N, X, Types, Args, Counter, Fd);
-emit_server_marshal_loop(G, N, X, [Type|Types],[{_, Arg}|Args], Counter, Fd) ->
-% Holder = ic_java_type:getHolderType(G,N,Type),
- case ic_java_type:isBasicType(G,N,Type) of
- true ->
- ic_codegen:emit(Fd, " __os~s(~s.value); // Out/InOut value\n",
- [ic_java_type:marshalFun(G,N,X,Type),Arg]);
- false ->
- ic_codegen:emit(Fd, " ~s._marshal(__os); // Out/InOut value\n",
- [Arg])
- end,
- emit_server_marshal_loop(G, N, X, Types, Args, Counter+1, Fd).
-
-
-
-
-
-%%%----------------------------------------------------
-%%%
-%%% Utilities
-%%%
-%%%----------------------------------------------------
-
-extract_info(_G, N, X) when is_record(X, op) ->
- Name = ic_util:to_undersc([ic_forms:get_id2(X) | N]),
- Args = X#op.params,
- ArgNames = mk_c_vars(Args),
- TypeList = {ic_forms:get_type(X),
- lists:map(fun(Y) -> ic_forms:get_type(Y) end, Args),
- []
- },
- {Name, ArgNames, TypeList};
-extract_info(_G, N, X) ->
- Name = ic_util:to_undersc([ic_forms:get_id2(X) | N]),
- {Name, [], []}.
-
-%% Input is a list of parameters (in parse form) and output is a list
-%% of parameter attribute and variable names.
-mk_c_vars(Params) ->
- lists:map(fun(P) -> {A, _} = P#param.inout,
- {A, ic_forms:get_id(P#param.id)}
- end,
- Params).
-
-%%
-handle_preproc(G, _N, line_nr, X) ->
- Id = ic_forms:get_java_id(X),
- Flags = X#preproc.aux,
- case Flags of
- [] -> ic_genobj:push_file(G, Id);
- _ ->
- lists:foldr(fun({_, _, "1"}, Gprim) -> ic_genobj:push_file(Gprim, Id);
- ({_, _, "2"}, Gprim) -> ic_genobj:pop_file(Gprim, Id);
- ({_, _, "3"}, Gprim) -> ic_genobj:sys_file(Gprim, Id) end,
- G, Flags)
- end;
-handle_preproc(G, _N, _Other, _X) ->
- G.
-
-
-%%
-gen_par_list(_, _, _, [], []) ->
- [];
-gen_par_list(G, N, X, [Type |Types], [{Attr, Arg}|Args]) ->
- JType = ic_java_type:getParamType(G, N, Type, Attr),
- [JType ++ " " ++ Arg |
- gen_par_list(G, N, X, Types, Args)].
-
-
-gen_marshal_par_list(_, _, _, [], []) ->
- [];
-gen_marshal_par_list(G, N, X, [_Type |Types], [{out, _Arg}|Args]) ->
- gen_marshal_par_list(G, N, X, Types, Args);
-gen_marshal_par_list(G, N, X, [Type |Types], [{Attr, Arg}|Args]) ->
- JType = ic_java_type:getParamType(G, N, Type, Attr),
- [JType ++ " " ++ Arg |
- gen_marshal_par_list(G, N, X, Types, Args)].
-
-
-gen_unmarshal_par_list(_, _, _, [], []) ->
- [];
-gen_unmarshal_par_list(G, N, X, [_Type |Types], [{in, _Arg}|Args]) ->
- gen_unmarshal_par_list(G, N, X, Types, Args);
-gen_unmarshal_par_list(G, N, X, [Type |Types], [{Attr, Arg}|Args]) ->
- JType = ic_java_type:getParamType(G, N, Type, Attr),
- [JType ++ " " ++ Arg |
- gen_unmarshal_par_list(G, N, X, Types, Args)].
-
-
-%%
-gen_client_marshal_call_par_list([]) ->
- [];
-gen_client_marshal_call_par_list([{out, _Arg}|Args]) ->
- gen_client_marshal_call_par_list(Args);
-gen_client_marshal_call_par_list([{_Attr, Arg}|Args]) ->
- [Arg | gen_client_marshal_call_par_list(Args)].
-
-
-gen_client_unmarshal_call_par_list([]) ->
- [];
-gen_client_unmarshal_call_par_list([{in, _Arg}|Args]) ->
- gen_client_unmarshal_call_par_list(Args);
-gen_client_unmarshal_call_par_list([{_Attr, Arg}|Args]) ->
- [Arg | gen_client_unmarshal_call_par_list(Args)].
-
-
-
-count_client_receive(ArgNames) ->
- count_client_receive(ArgNames,0).
-
-count_client_receive([],C) ->
- C;
-count_client_receive([{in, _Arg}|Args],C) ->
- count_client_receive(Args,C);
-count_client_receive([_|Args],C) ->
- count_client_receive(Args,C+1).
-
-
-
-count_client_send(ArgNames) ->
- count_client_send(ArgNames,0).
-
-count_client_send([],C) ->
- C;
-count_client_send([{out, _Arg}|Args],C) ->
- count_client_send(Args,C);
-count_client_send([_|Args],C) ->
- count_client_send(Args,C+1).
-
-
-gen_cb_arg_list([]) ->
- [];
-gen_cb_arg_list([{_Attr, Arg}|Args]) ->
- [Arg | gen_cb_arg_list(Args)].
-
-
-count_server_receive(ArgNames) ->
- count_server_receive(ArgNames,0).
-
-count_server_receive([],C) ->
- C;
-count_server_receive([_|Args],C) ->
- count_server_receive(Args,C+1).
-
-
-count_server_send(ArgNames) ->
- count_server_send(ArgNames,0).
-
-count_server_send([],C) ->
- C;
-count_server_send([{in, _Arg}|Args],C) ->
- count_server_send(Args,C);
-count_server_send([_|Args],C) ->
- count_server_send(Args,C+1).
-
-
-
-
-
-%%%-------------------------------------------------------
-
-
-emit_type_function(G, N, X, Fd) ->
-
- TC = ic_forms:get_type_code(G, N, X),
-
- %%io:format("X = ~p\nTC = ~p\n",[X,TC]),
-
- ic_codegen:emit(Fd, " private static ~sTypeCode _tc;\n",[?ICPACKAGE]),
- ic_codegen:emit(Fd, " synchronized public static ~sTypeCode type() {\n\n",[?ICPACKAGE]),
-
- ic_codegen:emit(Fd, " if (_tc != null)\n"),
- ic_codegen:emit(Fd, " return _tc;\n\n"),
-
- emit_type_function(TC, 0, Fd),
-
- ic_codegen:emit(Fd, "\n _tc = _tc0;\n"),
-
- ic_codegen:emit(Fd, "\n return _tc0;\n"),
- ic_codegen:emit(Fd, " }\n\n").
-
-
-
-emit_type_function({tk_struct, ID, Name, ML}, C, Fd) -> %% struct
- ic_codegen:emit(Fd, " ~sTypeCode _tc~p =\n",[?ICPACKAGE,C]),
- ic_codegen:emit(Fd, " new ~sTypeCode();\n", [?ICPACKAGE]),
- ic_codegen:emit(Fd, " _tc~p.kind(~sTCKind.tk_struct);\n", [C,?ICPACKAGE]),
- ic_codegen:emit(Fd, " _tc~p.id(~p);\n", [C,ID]),
- ic_codegen:emit(Fd, " _tc~p.name(~p);\n", [C,Name]),
- ic_codegen:emit(Fd, " _tc~p.member_count(~p);\n", [C,length(ML)]),
- emit_struct_members(ML, C, C+1, 0, Fd);
-
-emit_type_function({tk_enum, ID, Name, MNames}, C, Fd) -> %% enum
- ic_codegen:emit(Fd, " ~sTypeCode _tc~p =\n",[?ICPACKAGE,C]),
- ic_codegen:emit(Fd, " new ~sTypeCode();\n", [?ICPACKAGE]),
- ic_codegen:emit(Fd, " _tc~p.kind(~sTCKind.tk_enum);\n", [C,?ICPACKAGE]),
- ic_codegen:emit(Fd, " _tc~p.id(~p);\n", [C,ID]),
- ic_codegen:emit(Fd, " _tc~p.name(~p);\n", [C,Name]),
- ic_codegen:emit(Fd, " _tc~p.member_count(~p);\n", [C,length(MNames)]),
- emit_enum_members(MNames, C, 0, Fd),
- C+1;
-
-emit_type_function({tk_array, ET, L}, C, Fd) -> %% array
- ic_codegen:emit(Fd, " ~sTypeCode _tc~p =\n",[?ICPACKAGE,C]),
- ic_codegen:emit(Fd, " new ~sTypeCode();\n", [?ICPACKAGE]),
- ic_codegen:emit(Fd, " _tc~p.kind(~sTCKind.tk_array);\n", [C,?ICPACKAGE]),
- ic_codegen:emit(Fd, " _tc~p.id(id());\n",[C]),
- ic_codegen:emit(Fd, " _tc~p.length(~p);\n", [C,L]),
- C1 = C+1,
- C2 = emit_type_function(ET, C1, Fd),
- ic_codegen:emit(Fd, " _tc~p.content_type(_tc~p);\n", [C,C1]),
- C2;
-
-emit_type_function({tk_sequence, ET, L}, C, Fd) -> %% sequence
- ic_codegen:emit(Fd, " ~sTypeCode _tc~p =\n",[?ICPACKAGE,C]),
- ic_codegen:emit(Fd, " new ~sTypeCode();\n", [?ICPACKAGE]),
- ic_codegen:emit(Fd, " _tc~p.kind(~sTCKind.tk_sequence);\n", [C,?ICPACKAGE]),
- ic_codegen:emit(Fd, " _tc~p.id(id());\n",[C]),
- ic_codegen:emit(Fd, " _tc~p.length(~p);\n", [C,L]),
- C1 = C+1,
- C2 = emit_type_function(ET, C1, Fd),
- ic_codegen:emit(Fd, " _tc~p.content_type(_tc~p);\n", [C,C1]),
- C2;
-
-emit_type_function({tk_string, L}, C, Fd) -> %% string
- ic_codegen:emit(Fd, " ~sTypeCode _tc~p =\n",[?ICPACKAGE,C]),
- ic_codegen:emit(Fd, " new ~sTypeCode();\n", [?ICPACKAGE]),
- ic_codegen:emit(Fd, " _tc~p.kind(~sTCKind.tk_string);\n", [C,?ICPACKAGE]),
- ic_codegen:emit(Fd, " _tc~p.length(~p);\n", [C,L]),
- C+1;
-
-emit_type_function({tk_union, ID, Name, DT, DI, LL}, C, Fd) -> %% union
-
- ic_codegen:emit(Fd, " ~sTypeCode _tc~p =\n",[?ICPACKAGE,C]),
- ic_codegen:emit(Fd, " new ~sTypeCode();\n", [?ICPACKAGE]),
- ic_codegen:emit(Fd, " _tc~p.kind(~sTCKind.tk_union);\n", [C,?ICPACKAGE]),
- ic_codegen:emit(Fd, " _tc~p.id(~p);\n", [C,ID]),
- ic_codegen:emit(Fd, " _tc~p.name(~p);\n", [C,Name]),
-
- C1 = C+1,
- C2 = emit_type_function(DT, C1, Fd),
-
- ic_codegen:emit(Fd, " _tc~p.discriminator_type(_tc~p);\n", [C,C1]),
- ic_codegen:emit(Fd, " _tc~p.default_index(~p);\n", [C,DI]),
- ic_codegen:emit(Fd, " _tc~p.member_count(~p);\n", [C,length(LL)]),
-
- emit_union_labels(LL, C, DT, C2, 0, Fd);
-
-emit_type_function(tk_term, C, Fd) -> %% term, must change it to tk_any
- ic_codegen:emit(Fd, " ~sTypeCode _tc~p =\n",[?ICPACKAGE,C]),
- ic_codegen:emit(Fd, " new ~sTypeCode();\n", [?ICPACKAGE]),
- ic_codegen:emit(Fd, " _tc~p.kind(~sTCKind.tk_any);\n", [C,?ICPACKAGE]),
- C+1;
-
-emit_type_function(TC, C, Fd) -> %% other
- ic_codegen:emit(Fd, " ~sTypeCode _tc~p =\n",[?ICPACKAGE,C]),
- ic_codegen:emit(Fd, " new ~sTypeCode();\n", [?ICPACKAGE]),
- ic_codegen:emit(Fd, " _tc~p.kind(~sTCKind.~p);\n", [C,?ICPACKAGE,TC]),
- C+1.
-
-
-
-emit_struct_members([], _, TCtr, _, _Fd) ->
- TCtr;
-emit_struct_members([{Name,MT}|Rest], BTCtr, TCtr, I, Fd) ->
- ic_codegen:emit(Fd, " _tc~p.member_name(~p,~p);\n", [BTCtr,I,Name]),
- TCtr2 = emit_type_function(MT, TCtr, Fd),
- ic_codegen:emit(Fd, " _tc~p.member_type(~p,_tc~p);\n", [BTCtr,I,TCtr]),
- emit_struct_members(Rest, BTCtr, TCtr2, I+1, Fd).
-
-emit_enum_members([], _, _, _Fd) ->
- ok;
-emit_enum_members([Name|Names], BTCtr, I, Fd) ->
- ic_codegen:emit(Fd, " _tc~p.member_name(~p,~p);\n", [BTCtr,I,Name]),
- emit_enum_members(Names, BTCtr, I+1, Fd).
-
-
-emit_union_labels([], _, _, TCtr, _, _) ->
- TCtr;
-emit_union_labels([{L, LN, LT}|Rest], BTCtr, DT, TCtr, I, Fd) ->
- ic_codegen:emit(Fd, " ~sAny _any~p =\n",[?ICPACKAGE,TCtr]),
- ic_codegen:emit(Fd, " new ~sAny();\n", [?ICPACKAGE]),
- TCtr1 = TCtr+1,
- TCtr2 = emit_type_function(LT, TCtr1,Fd),
- ic_codegen:emit(Fd, " _any~p.type(_tc~p);\n",[TCtr,TCtr1]),
-
- case L of
- default ->
- ic_codegen:emit(Fd, " _any~p.insert_atom(\"default\");\n", [TCtr]);
- _ ->
- case DT of
- tk_boolean ->
- ic_codegen:emit(Fd, " _any~p.insert_boolean(~p);\n",[TCtr,L]);
- tk_char ->
- Default = if is_integer(L) ->
- [L];
- true ->
- L
- end,
- ic_codegen:emit(Fd, " _any~p.insert_char('~s');\n",[TCtr,Default]);
- tk_ushort ->
- ic_codegen:emit(Fd, " _any~p.insert_ushort(~p);\n",[TCtr,L]);
- tk_ulong ->
- ic_codegen:emit(Fd, " _any~p.insert_ulong(~p);\n",[TCtr,L]);
- tk_short ->
- ic_codegen:emit(Fd, " _any~p.insert_short(~p);\n",[TCtr,L]);
- tk_long ->
- ic_codegen:emit(Fd, " _any~p.insert_long(~p);\n",[TCtr,L]);
- _ ->
- ic_codegen:emit(Fd, " _any~p.insert_string(~p);\n", [TCtr,L])
- end
- end,
- ic_codegen:emit(Fd, " _tc~p.member_label(~p,_any~p);\n", [BTCtr,I,TCtr]),
- ic_codegen:emit(Fd, " _tc~p.member_name(~p,~p);\n", [BTCtr,I,LN]),
- TCtr3 = emit_type_function(LT, TCtr2, Fd),
- ic_codegen:emit(Fd, " _tc~p.member_type(~p,_tc~p);\n", [BTCtr,I,TCtr2]),
- emit_union_labels(Rest, BTCtr, DT, TCtr3, I+1, Fd).
-
-
-
-
-
-
-
-
diff --git a/lib/ic/src/ic_noc.erl b/lib/ic/src/ic_noc.erl
deleted file mode 100644
index 0e387b5e70..0000000000
--- a/lib/ic/src/ic_noc.erl
+++ /dev/null
@@ -1,1117 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(ic_noc).
-
-
--export([do_gen/3]).
-%%------------------------------------------------------------
-%%
-%% Internal stuff
-%%
-%%------------------------------------------------------------
-
--export([unfold/1, mk_attr_func_names/2]).
-
-
--import(ic_util, [mk_name/2, mk_var/1, mk_oe_name/2, to_atom/1, to_list/1]).
--import(ic_forms, [get_id/1, get_id2/1, get_body/1, is_oneway/1]).
--import(ic_codegen, [emit/2, emit/3, nl/1]).
--import(ic_options, [get_opt/2]).
-
-
--import(lists, [foreach/2, foldr/3, map/2]).
-
-
--include("icforms.hrl").
--include("ic.hrl").
-
-
-
-
-%%------------------------------------------------------------
-%%
-%% Generate the client side Erlang stubs.
-%%
-%% Each module is generated to a separate file.
-%%
-%% Export declarations for all interface functions must be
-%% generated. Each function then needs to generate a function head and
-%% a body. IDL parameters must be converted into Erlang parameters
-%% (variables, capitalised) and a type signature list must be
-%% generated (for later encode/decode).
-%%
-%%------------------------------------------------------------
-
-
-do_gen(G, File, Form) ->
- G2 = ic_file:filename_push(G, [], mk_oe_name(G,
- ic_file:remove_ext(to_list(File))),
- erlang),
- gen_head(G2, [], Form),
- exportDependency(G2),
- %% Loop through form and adds inheritence data
- ic_pragma:preproc(G2, [], Form),
- gen(G2, [], Form),
- genDependency(G2),
- ic_file:filename_pop(G2, erlang),
- ok.
-
-
-gen(G, N, [X|Xs]) when is_record(X, preproc) ->
- NewG = ic:handle_preproc(G, N, X#preproc.cat, X),
- gen(NewG, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, module) ->
- CD = ic_code:codeDirective(G,X),
- G2 = ic_file:filename_push(G, N, X, CD),
- N2 = [get_id2(X) | N],
- gen_head(G2, N2, X),
- gen(G2, N2, get_body(X)),
- G3 = ic_file:filename_pop(G2, CD),
- gen(G3, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, interface) ->
- G2 = ic_file:filename_push(G, N, X, erlang),
- N2 = [get_id2(X) | N],
- gen_head(G2, N2, X),
- gen(G2, N2, get_body(X)),
- foreach(fun({_Name, Body}) -> gen(G2, N2, Body) end,
- X#interface.inherit_body),
- gen_serv(G2, N, X),
- G3 = ic_file:filename_pop(G2, erlang),
- gen(G3, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, const) ->
-% N2 = [get_id2(X) | N],
- emit_constant_func(G, X#const.id, X#const.val),
- gen(G, N, Xs); %% N2 or N?
-
-gen(G, N, [X|Xs]) when is_record(X, op) ->
- {Name, ArgNames, TypeList, OutArgs} = extract_info(G, N, X),
-
- case getNocType(G,X,N) of
- transparent ->
- emit_transparent_func(G, N, X, Name, ArgNames, TypeList, OutArgs);
- multiple ->
- mark_not_transparent(G,N),
- emit_transparent_func(G, N, X, Name, ArgNames, TypeList, OutArgs);
- _XTuple ->
- mark_not_transparent(G,N),
- emit_stub_func(G, N, X, Name, ArgNames, TypeList, OutArgs)
- end,
-
- gen(G, N, Xs);
-
-
-gen(G, N, [X|Xs]) when is_record(X, attr) ->
- emit_attr(G, N, X, fun emit_stub_func/7),
- gen(G, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, except) ->
- icstruct:except_gen(G, N, X, erlang),
- gen(G, N, Xs);
-
-gen(G, N, [X|Xs]) ->
- case may_contain_structs(X) of
- true -> icstruct:struct_gen(G, N, X, erlang);
- false -> ok
- end,
- gen(G, N, Xs);
-
-gen(_G, _N, []) -> ok.
-
-
-may_contain_structs(X) when is_record(X, typedef) -> true;
-may_contain_structs(X) when is_record(X, struct) -> true;
-may_contain_structs(X) when is_record(X, union) -> true;
-may_contain_structs(_X) -> false.
-
-
-
-%%--------------------------------------------------------------------
-%%
-%% Generate the server side (handle_call and handle_cast)
-%%
-
-gen_serv(G, N, X) ->
- case ic_genobj:is_stubfile_open(G) of
- true ->
- emit_serv_std(G, N, X),
- N2 = [get_id2(X) | N],
- gen_calls(G, N2, get_body(X)),
- lists:foreach(fun({_Name, Body}) ->
- gen_calls(G, N2, Body) end,
- X#interface.inherit_body),
- get_if_gen(G, N2, X),
- gen_end_of_call(G, N, X), % Note N instead of N2
-
- gen_casts(G, N2, get_body(X)),
- lists:foreach(fun({_Name, Body}) ->
- gen_casts(G, N2, Body) end,
- X#interface.inherit_body),
- gen_end_of_cast(G, N, X), % Note N instead of N2
- emit_skel_footer(G, N, X); % Note N instead of N2
- false ->
- ok
- end.
-
-gen_calls(G, N, [X|Xs]) when is_record(X, op) ->
- case is_oneway(X) of
- false ->
- {Name, ArgNames, TypeList, OutArgs} = extract_info(G, N, X),
- emit_skel_func(G, N, X, Name, ArgNames, TypeList, OutArgs),
- gen_calls(G, N, Xs);
- true ->
- gen_calls(G, N, Xs)
- end;
-
-gen_calls(G, N, [X|Xs]) when is_record(X, attr) ->
- emit_attr(G, N, X, fun emit_skel_func/7),
- gen_calls(G, N, Xs);
-
-gen_calls(G, N, [_X|Xs]) -> gen_calls(G, N, Xs);
-gen_calls(_G, _N, []) -> ok.
-
-gen_casts(G, N, [X|Xs]) when is_record(X, op) ->
- case is_oneway(X) of
- true ->
- {Name, ArgNames, TypeList, OutArgs} = extract_info(G, N, X),
- emit_skel_func(G, N, X, Name, ArgNames, TypeList, OutArgs),
- gen_casts(G, N, Xs);
- false ->
- gen_casts(G, N, Xs)
- end;
-
-gen_casts(G, N, [_X|Xs]) -> gen_casts(G, N, Xs);
-gen_casts(_G, _N, []) -> ok.
-
-emit_attr(G, N, X, F) ->
- XX = #id_of{type=X},
- {GetType, SetType} = mk_attr_func_types(N, X),
- lists:foreach(fun(Id) ->
- X2 = XX#id_of{id=Id},
- {Get, Set} = mk_attr_func_names(N, get_id(Id)),
- F(G, N, X2, Get, [], GetType, []),
- case X#attr.readonly of
- {readonly, _} -> ok;
- _ ->
- F(G, N, X2, Set, [mk_name(G, "Value")],
- SetType, [])
- end end, ic_forms:get_idlist(X)).
-
-
-extract_info(G, _N, X) when is_record(X, op) ->
- Name = get_id2(X),
- InArgs = ic:filter_params([in,inout], X#op.params),
- OutArgs = ic:filter_params([out,inout], X#op.params),
- ArgNames = mk_erl_vars(G, InArgs),
- TypeList = {ic_forms:get_tk(X),
- map(fun(Y) -> ic_forms:get_tk(Y) end, InArgs),
- map(fun(Y) -> ic_forms:get_tk(Y) end, OutArgs)
- },
- {Name, ArgNames, TypeList, OutArgs}.
-
-
-
-
-emit_serv_std(G, N, X) ->
- Fd = ic_genobj:stubfiled(G),
- case transparent(G) of
- true ->
- true;
- _XTupleORMultiple ->
- Impl = getImplMod(G,X,[get_id2(X)|N]),
- TypeID = ictk:get_IR_ID(G, N, X),
-
- nl(Fd), nl(Fd), nl(Fd),
- ic_codegen:mcomment(Fd, ["Server implementation."]),
- nl(Fd), nl(Fd),
- ic_codegen:mcomment(Fd, ["Function for fetching the interface type ID."]),
- nl(Fd),
- emit(Fd, "typeID() ->\n"),
- emit(Fd, " \"~s\".\n", [TypeID]),
- nl(Fd), nl(Fd),
- ic_codegen:mcomment(Fd, ["Server creation functions."]),
- nl(Fd),
- emit(Fd, "oe_create() ->\n"),
- emit(Fd, " start([], []).\n", []),
- nl(Fd),
- emit(Fd, "oe_create_link() ->\n"),
- emit(Fd, " start_link([], []).\n", []),
- nl(Fd),
- emit(Fd, "oe_create(Env) ->\n"),
- emit(Fd, " start(Env, []).\n", []),
- nl(Fd),
- emit(Fd, "oe_create_link(Env) ->\n"),
- emit(Fd, " start_link(Env, []).\n", []),
- nl(Fd),
- emit(Fd, "oe_create(Env, RegName) ->\n"),
- emit(Fd, " start(RegName, Env, []).\n", []),
- nl(Fd),
- emit(Fd, "oe_create_link(Env, RegName) ->\n"),
- emit(Fd, " start_link(RegName, Env, []).\n", []),
- nl(Fd),
- ic_codegen:mcomment(Fd, ["Start functions."]),
- nl(Fd),
- emit(Fd, "start(Env, Opt) ->\n"),
- emit(Fd, " gen_server:start(?MODULE, Env, Opt).\n"),
- nl(Fd),
- emit(Fd, "start_link(Env, Opt) ->\n"),
- emit(Fd, " gen_server:start_link(?MODULE, Env, Opt).\n"),
- nl(Fd),
- emit(Fd, "start(RegName, Env, Opt) ->\n"),
- emit(Fd, " gen_server:start(RegName, ?MODULE, Env, Opt).\n"),
- nl(Fd),
- emit(Fd, "start_link(RegName, Env, Opt) ->\n"),
- emit(Fd, " gen_server:start_link(RegName, ?MODULE, Env, Opt).\n"),
- nl(Fd),
- ic_codegen:comment(Fd, "Call to implementation init"),
- emit(Fd, "init(Env) ->\n"),
- emit(Fd, " ~p:~p(Env).\n", [Impl, init]),
- nl(Fd),
- emit(Fd, "terminate(Reason, State) ->\n"),
- emit(Fd, " ~p:~p(Reason, State).\n",
- [Impl, terminate]),
- nl(Fd),
- emit(Fd, "code_change(_OldVsn, State, _Extra) ->\n"),
- emit(Fd, " {ok, State}.\n"),
- nl(Fd), nl(Fd)
- end,
- Fd.
-
-
-
-
-gen_end_of_call(G, _N, _X) ->
- case transparent(G) of
- true ->
- true;
- _XTuple ->
- Fd = ic_genobj:stubfiled(G),
- nl(Fd), nl(Fd),
- ic_codegen:mcomment_light(Fd, ["Standard gen_server call handle"]),
- emit(Fd, "handle_call(stop, _From, State) ->\n"),
- emit(Fd, " {stop, normal, ok, State}"),
- case get_opt(G, serv_last_call) of
- exception ->
- emit(Fd, ";\n"),
- nl(Fd),
- emit(Fd, "handle_call(_Req, _From, State) ->\n"),
- emit(Fd, " {reply, ~p, State}.\n",[getCallErr()]);
- exit ->
- emit(Fd, ".\n"),
- nl(Fd),
- nl(Fd)
- end
- end,
- ok.
-
-
-gen_end_of_cast(G, _N, _X) ->
- case transparent(G) of
- true ->
- true;
- _XTuple ->
- Fd = ic_genobj:stubfiled(G),
- nl(Fd), nl(Fd),
- ic_codegen:mcomment_light(Fd, ["Standard gen_server cast handle"]),
- emit(Fd, "handle_cast(stop, State) ->\n"),
- emit(Fd, " {stop, normal, State}"),
- case get_opt(G, serv_last_call) of
- exception ->
- emit(Fd, ";\n"),
- nl(Fd),
- emit(Fd, "handle_cast(_Req, State) ->\n"),
- emit(Fd, " {reply, ~p, State}.\n",[getCastErr()]);
- exit ->
- emit(Fd, ".\n"),
- nl(Fd), nl(Fd)
- end
- end,
- ok.
-
-
-emit_skel_footer(G, N, X) ->
- case transparent(G) of
- true ->
- true;
- _XTuple ->
- Fd = ic_genobj:stubfiled(G),
- nl(Fd), nl(Fd),
- ic_codegen:mcomment_light(Fd, ["Standard gen_server handles"]),
- case use_impl_handle_info(G, N, X) of
- true ->
- emit(Fd, "handle_info(X, State) ->\n"),
- emit(Fd, " ~p:handle_info(X, State).\n\n",
- [list_to_atom(ic_genobj:impl(G))]);
- false ->
- emit(Fd, "handle_info(_X, State) ->\n"),
- emit(Fd, " {reply, ~p, State}.\n\n",[getInfoErr()])
- end
- end,
- ok.
-
-
-use_impl_handle_info(G, N, X) ->
- FullName = ic_util:to_colon([get_id2(X) | N]),
- case {get_opt(G, {handle_info, true}), get_opt(G, {handle_info, FullName})} of
- {_, force_false} -> false;
- {false, false} -> false;
- _ -> true
- end.
-
-
-use_timeout(G, N, _X) ->
- FullName = ic_util:to_colon(N),
- case {get_opt(G, {timeout, true}), get_opt(G, {timeout, FullName})} of
- {_, force_false} -> false;
- {false, false} -> false;
- _ -> true
- end.
-
-
-get_if_name(G) -> mk_oe_name(G, "get_interface").
-
-
-%% Generates the get_interface function (for Lars)
-get_if_gen(G, N, X) ->
- case transparent(G) of
- true ->
- ok;
- _XTuple ->
- case ic_genobj:is_stubfile_open(G) of
- true ->
- IFC_TKS = tk_interface_data(G,N,X),
- Fd = ic_genobj:stubfiled(G),
- Name = to_atom(get_if_name(G)),
-
- ic_codegen:mcomment_light(Fd,
- [io_lib:format("Standard Operation: ~p",
- [Name])]),
-
- emit(Fd, "handle_call({_~s, ~p, []}, _From, State) ->~n",
- [mk_name(G, "Ref"), Name]),
- emit(Fd, " {reply, ~p, State};~n", [IFC_TKS]),
- nl(Fd),
- ok;
-
- false -> ok
- end
- end.
-
-
-get_if(G,N,[X|Rest]) when is_record(X, op) ->
- R = ic_forms:get_tk(X),
- IN = lists:map(fun(P) -> ic_forms:get_tk(P) end,
- ic:filter_params([in, inout], X#op.params)),
- OUT = lists:map(fun(P) -> ic_forms:get_tk(P) end,
- ic:filter_params([out, inout], X#op.params)),
- case print_tk(G,N,X) of
- true ->
- [{get_id2(X), {R, IN, OUT}} | get_if(G,N,Rest)];
- false ->
- get_if(G,N,Rest)
- end;
-
-get_if(G,N,[X|Rest]) when is_record(X, attr) -> %% Attributes not handled so far <<<<<<<<<<<<<<<<<<<<<<<<
- {GetT, SetT} = mk_attr_func_types([], X),
- AList = lists:map(fun(Id) ->
- {Get, Set} = mk_attr_func_names([], get_id(Id)),
- case X#attr.readonly of
- {readonly, _} ->
- {Get, GetT};
- _ ->
- [{Set, SetT}, {Get, GetT}]
- end end, ic_forms:get_idlist(X)),
- lists:flatten(AList) ++ get_if(G,N,Rest);
-
-get_if(G,N,[_X|Rest]) -> get_if(G,N,Rest);
-get_if(_,_,[]) -> [].
-
-
-
-
-%%------------------------------------------------------------
-%%
-%% Export stuff
-%%
-%% Gathering of all names that should be exported from a stub
-%% file.
-%%
-
-
-gen_head_special(G, N, X) when is_record(X, interface) ->
- Fd = ic_genobj:stubfiled(G),
- NocType = getNocType(G,X,N),
-
- foreach(fun({Name, Body}) ->
- ic_codegen:comment(Fd, "Exports from ~p",
- [ic_util:to_colon(Name)]),
- ic_codegen:export(Fd, exp_top(G, N, Body, NocType, [])),
- nl(Fd)
- end, X#interface.inherit_body),
-
- case transparent(G) of
- true ->
- nl(Fd), nl(Fd);
- _XTuple ->
- ic_codegen:comment(Fd, "Type identification function"),
- ic_codegen:export(Fd, [{typeID, 0}]),
- nl(Fd),
- ic_codegen:comment(Fd, "Used to start server"),
- ic_codegen:export(Fd, [{start, 2},{start_link, 3}]),
- ic_codegen:export(Fd, [{oe_create, 0}, {oe_create_link, 0}, {oe_create, 1},
- {oe_create_link, 1},{oe_create, 2}, {oe_create_link, 2}]),
- nl(Fd),
- ic_codegen:comment(Fd, "gen server export stuff"),
- emit(Fd, "-behaviour(gen_server).\n"),
- ic_codegen:export(Fd, [{init, 1}, {terminate, 2}, {code_change, 3},
- {handle_call, 3}, {handle_cast, 2}, {handle_info, 2}]),
- nl(Fd), nl(Fd),
- ic_codegen:mcomment(Fd, ["Object interface functions."]),
- nl(Fd), nl(Fd), nl(Fd)
- end,
- Fd;
-
-
-gen_head_special(_G, _N, _X) -> ok.
-
-
-
-%% Shall generate all export declarations
-gen_head(G, N, X) ->
- case ic_genobj:is_stubfile_open(G) of
- true ->
- F = ic_genobj:stubfiled(G),
- ic_codegen:comment(F, "Interface functions"),
- ic_codegen:export(F, exp_top(G, N, X, getNocType(G,X,N), [])),
- nl(F),
- gen_head_special(G, N, X);
- false -> ok
- end.
-
-exp_top(_G, _N, X, _NT, Acc) when element(1, X) == preproc ->
- Acc;
-exp_top(G, N, L, NT, Acc) when is_list(L) ->
- exp_list(G, N, L, NT, Acc);
-exp_top(G, N, M, NT, Acc) when is_record(M, module) ->
- exp_list(G, N, get_body(M), NT, Acc);
-exp_top(G, N, I, NT, Acc) when is_record(I, interface) ->
- exp_list(G, N, get_body(I), NT, Acc);
-exp_top(G, N, X, NT, Acc) ->
- exp3(G, N, X, NT, Acc).
-
-exp3(_G, _N, C, _NT, Acc) when is_record(C, const) ->
- [{get_id(C#const.id), 0} | Acc];
-
-exp3(G, N, Op, NocType, Acc) when is_record(Op, op) ->
- FuncName = get_id(Op#op.id),
-
- TA = case use_timeout(G,N,Op) of
- true ->
- 1;
- false ->
- 0
- end,
-
- case NocType of
- transparent ->
- Arity = length(ic:filter_params([in, inout], Op#op.params)) + TA + 1,
- [{FuncName, Arity} | Acc];
- multiple ->
- case getModType(G, Op, N) of
- dt ->
- Arity = length(ic:filter_params([in, inout], Op#op.params)) + TA + 1,
- [{FuncName, Arity} | Acc];
- do ->
- Arity = length(ic:filter_params([in, inout], Op#op.params)) + TA + 1,
- [{FuncName, Arity} | Acc];
- spt ->
- Arity = length(ic:filter_params([in, inout], Op#op.params)) + TA + 1,
- [{FuncName, Arity} | Acc];
- spo ->
- Arity = length(ic:filter_params([in, inout], Op#op.params)) + TA + 1,
- [{FuncName, Arity} | Acc]
- end;
- _ ->
- Arity = length(ic:filter_params([in, inout], Op#op.params)) + TA + 1,
- [{FuncName, Arity} | Acc]
- end;
-exp3(_G, _N, A, _NT, Acc) when is_record(A, attr) ->
- lists:foldr(fun(Id, Acc2) ->
- {Get, Set} = mk_attr_func_names([], get_id(Id)),
- case A#attr.readonly of
- {readonly, _} -> [{Get, 1} | Acc2];
- _ -> [{Get, 1}, {Set, 2} | Acc2]
- end end, Acc, ic_forms:get_idlist(A));
-
-exp3(_G, _N, _X, _NT, Acc) -> Acc.
-
-exp_list(G, N, L, NT, OrigAcc) ->
- lists:foldr(fun(X, Acc) -> exp3(G, N, X, NT, Acc) end, OrigAcc, L).
-
-
-
-
-%%------------------------------------------------------------
-%%
-%% Emit stuff
-%%
-%% Low level generation primitives
-%%
-
-emit_stub_func(G, N, X, Name, ArgNames, TypeList, _OutArgs) ->
- case ic_genobj:is_stubfile_open(G) of
- false -> ok;
- true ->
- Fd = ic_genobj:stubfiled(G),
- StubName = list_to_atom(Name),
- This = mk_name(G, "Ref"),
- XTuple = getNocType(G,X,N),
- CallOrCast =
- case is_oneway(X) of
- true -> ?CAST;
- _ -> ?CALL
- end,
-
- %% Type expand operation on comments
- ic_code:type_expand_op(G,N,X,Fd),
-
- case use_timeout(G,N,X) of
- true ->
- Timeout = mk_name(G,"Timeout"),
- emit(Fd, "~p(~s) ->\n",
- [StubName, mk_list([This, Timeout| ArgNames])]),
- emit(Fd, " ~p:~s(~s, ~s, ?MODULE, ~p, ~p, [~s], ~p).\n\n",
- [getImplMod(G,X,N),
- CallOrCast,
- This,
- Timeout,
- XTuple,
- StubName,
- mk_list(ArgNames),
- tk_operation_data(G, N, X, TypeList)]);
- false ->
- emit(Fd, "~p(~s) ->\n",
- [StubName, mk_list([This | ArgNames])]),
-
- emit(Fd, " ~p:~s(~s, ~p, ?MODULE, ~p, [~s], ~p).\n\n",
- [getImplMod(G,X,N),
- CallOrCast,
- This,
- XTuple,
- StubName,
- mk_list(ArgNames),
- tk_operation_data(G, N, X, TypeList)])
- end
- end.
-
-
-emit_transparent_func(G, N, X, Name, ArgNames, _TypeList, _OutArgs) ->
- case ic_genobj:is_stubfile_open(G) of
- false -> ok;
- true ->
- Fd = ic_genobj:stubfiled(G),
- OpName = list_to_atom(Name),
-
- ArgList = case use_timeout(G,N,X) of
- true ->
- mk_list([mk_name(G,"Ref"),mk_name(G,"Timeout")|ArgNames]);
- false ->
- mk_list([mk_name(G,"Ref")|ArgNames])
- end,
-
- %% Type expand operation on comments
- ic_code:type_expand_op(G,N,X,Fd),
-
- emit(Fd, "~p(~s) ->\n", [OpName,ArgList]),
- emit(Fd, " ~p:~s(~s).\n\n", [getImplMod(G,X,N), OpName, ArgList])
- end.
-
-
-
-
-
-
-emit_skel_func(G, N, X, OpName, ArgNames, _TypeList, _OutArgs) ->
- case getNocType(G,X,N) of
- transparent ->
- true;
- multiple ->
- true;
- XTuple ->
- case ic_genobj:is_stubfile_open(G) of
- false -> ok;
- true ->
- Fd = ic_genobj:stubfiled(G),
- Name = list_to_atom(OpName),
- This = mk_name(G, "Ref"),
- From = mk_name(G, "From"),
- State = mk_name(G, "State"),
-
- %% Type expand handle operation on comments
- ic_code:type_expand_handle_op(G,N,X,Fd),
-
- case is_oneway(X) of
- true ->
- emit(Fd, "handle_cast({~s, ~p, OE_Module, ~p, [~s]}, ~s) ->\n",
- [This, XTuple, Name, mk_list(ArgNames), State]),
- emit(Fd, " ~p:handle_cast({~s, ~p, OE_Module, ~p, [~s]}, ~s);\n\n",
- [getImplMod(G,X,N), This, XTuple, Name, mk_list(ArgNames), State]);
- false ->
- emit(Fd, "handle_call({~s, ~p, OE_Module, ~p, [~s]}, ~s, ~s) ->\n",
- [This, XTuple, Name, mk_list(ArgNames), From, State]),
- emit(Fd, " ~p:handle_call({~s, ~p, OE_Module, ~p, [~s]}, ~s, ~s);\n\n",
- [getImplMod(G,X,N), This, XTuple, Name, mk_list(ArgNames), From, State])
- end
- end
- end.
-
-
-
-emit_constant_func(G, Id, Val) ->
- case ic_genobj:is_stubfile_open(G) of
- false -> ok;
- true ->
- Fd = ic_genobj:stubfiled(G),
- N = list_to_atom(get_id(Id)),
- emit_const_comment(G, Fd, Id, N),
- emit(Fd, "~p() -> ~p.\n\n", [N, Val])
- end.
-
-
-emit_const_comment(_G, F, _X, Name) ->
- ic_codegen:mcomment_light(F,
- [io_lib:format("Constant: ~p", [Name])]).
-
-%%------------------------------------------------------------
-%%
-%% Utilities
-%%
-%% Convenient little go-get functions
-%%
-%%------------------------------------------------------------
-
-%% The automaticly generated get and set operation names for an
-%% attribute.
-mk_attr_func_names(_Scope, Name) ->
- {"_get_" ++ Name, "_set_" ++ Name}.
-
-%% Returns TK of the Get and Set attribute functions.
-mk_attr_func_types(_N, X) ->
- TK = ic_forms:get_tk(X),
- {{TK, [], []}, {tk_void, [TK], []}}.
-
-
-
-%%------------------------------------------------------------
-%%
-%% Generation utilities and common stuff
-%%
-%% Convenient stuff for generation
-%%
-%%------------------------------------------------------------
-
-
-%% Input is a list of parameters (in parse form) and output is a list
-%% of capitalised variable names. mk_var is in icgen
-mk_erl_vars(_G, Params) ->
- map(fun(P) -> mk_var(get_id(P#param.id)) end, Params).
-
-
-%% mk_list produces a nice comma separated string of variable names
-mk_list([]) -> [];
-mk_list([Arg | Args]) ->
- Arg ++ mk_list2(Args).
-mk_list2([Arg | Args]) ->
- ", " ++ Arg ++ mk_list2(Args);
-mk_list2([]) -> [].
-
-
-%%------------------------------------------------------------
-%%
-%% Parser utilities
-%%
-%% Called from the yecc parser. Expands the identifier list of an
-%% attribute so that the attribute generator never has to handle
-%% lists.
-%%
-%%------------------------------------------------------------
-
-
-%% Unfold identifier lists or nested lists. Note that many records
-%% contain an entry named id that is a list before unfold and a single
-%% id afterwards.
-unfold(L) when is_list(L) ->
- lists:flatten(map(fun(X) -> unfold2(X) end, L));
-unfold(X) -> unfold2(X).
-
-unfold2(A) when is_record(A, attr) ->
- map(fun(Id) -> A#attr{id=Id} end, A#attr.id);
-unfold2(M) when is_record(M, member) ->
- map(fun(Id) -> M#member{id=Id} end, M#member.id);
-unfold2(M) when is_record(M, case_dcl) ->
- map(fun(Id) -> M#case_dcl{label=Id} end, M#case_dcl.label);
-unfold2(T) when is_record(T, typedef) ->
- map(fun(Id) -> T#typedef{id=Id} end, T#typedef.id ).
-
-
-
-
-
-
-%% Export code produce for dependency function
-exportDependency(G) ->
- Fd = ic_genobj:stubfiled(G),
- ic_codegen:export(Fd, [{oe_dependency, 0}]),
- nl(Fd).
-
-%% Code produce for dependency function
-genDependency(G) ->
- Fd = ic_genobj:stubfiled(G),
- nl(Fd),nl(Fd),
- ic_codegen:comment(Fd, "Idl file dependency list function"),
- emit(Fd, "oe_dependency() ->\n", []),
- emit(Fd, " ~p.\n\n", [ic_pragma:get_dependencies(G)]).
-
-
-
-
-
-%%%%%%
-
-
-getImplMod(G,X,Scope) -> %% to_atom(ic_genobj:impl(G)) | ChoicedModuleName
-
- %% Get actual pragma appliance scope
- SpecScope = getActualScope(G,X,Scope),
-
- %% The "broker" option is passed
- %% only by pragmas, seek for module.
- case ic_pragma:getBrokerData(G,X,SpecScope) of
- {Module,_Type} ->
- Module;
- _List ->
- element(1,ic_pragma:defaultBrokerData(G))
- end.
-
-
-getNocType(G,X,Scope) when is_record(X, interface) -> %% default | specified
- OpList = getAllOperationScopes(G,Scope),
- getNocType2(G,X,OpList);
-getNocType(G,X,Scope) -> %% transparent | {extraarg1,....,extraargN}
- getNocType3(G,X,Scope).
-
-getNocType2(G,X,List) ->
- getNocType2(G,X,List,[]).
-
-getNocType2(_,_,[],Found) ->
- selectTypeFromList(Found);
-getNocType2(G,X,[OpScope|OpScopes],Found) ->
- getNocType2(G,X,OpScopes,[getNocType3(G,X,OpScope)|Found]).
-
-getNocType3(G,X,Scope) -> %% transparent | {extraarg1,....,extraargN}
-
- %% Get actual pragma appliance scope
- SpecScope = getActualScope(G,X,Scope),
-
- %% The "broker" option is passed
- %% only by pragmas, seek for type.
- case ic_pragma:getBrokerData(G,X,SpecScope) of
- {_Module,Type} ->
- Type;
- List ->
- selectTypeFromList(List) %%transparent/multiple
- end.
-
-
-getModType(G,X,Scope) -> %% default | specified
-
- %% Get actual pragma appliance scope
- SpecScope = getActualScope(G,X,Scope),
-
- %% The "broker" option is passed
- %% only by pragmas, seek for brokerdata.
- case ic_pragma:getBrokerData(G,X,SpecScope) of
- {Module,Type} ->
- case Module == ic_genobj:impl(G) of
- true ->
- case Type of
- transparent ->
- dt; %% default + transparent
- _ ->
- do %% default + opaque
- end;
- false ->
- case Type of
- transparent ->
- spt; %% specified + transparent
- _ ->
- spo %% specified + opaque
- end
- end;
- _List ->
- dt
- end.
-
-
-
-%%%%
-%%
-%% Returns a list of ALL operation full
-%% scoped names local and inherited
-%% from other interfaces
-%%
-
-getAllOperationScopes(G,Scope) ->
- getOperationScopes(G,Scope) ++
- getInhOperationScopes(G,Scope).
-
-
-getOperationScopes(G,Scope) ->
- getOpScopes(G,
- Scope,
- ets:match(ic_genobj:pragmatab(G),{op,'$0',Scope,'_','_'}),
- []).
-
-getOpScopes(_,_,[],OpScopes) ->
- OpScopes;
-getOpScopes(G,Scope,[[Name]|Names],Found) ->
- getOpScopes(G,Scope,Names,[[Name|Scope]|Found]).
-
-
-getInhOperationScopes(G,Scope) ->
- getInhOpScopes1(G,
- Scope,
- ets:match(ic_genobj:pragmatab(G),{inherits,Scope,'$1'}),
- []).
-
-getInhOpScopes1(G,_Scope,[],OpScopes) ->
- getInhOpScopes2(G,OpScopes);
-getInhOpScopes1(G,Scope,[[SC]|SCs],Found) ->
- getInhOpScopes1(G,Scope,SCs,[SC|Found]).
-
-
-getInhOpScopes2(G,Scopes) ->
- getInhOpScopes2(G,Scopes,[]).
-
-getInhOpScopes2(_G,[],Found) ->
- Found;
-getInhOpScopes2(G,[SC|SCs],Found) ->
- getOperationScopes(G,SC) ++ getInhOpScopes2(G,SCs,Found).
-
-%%
-%%
-%%%%
-
-
-
-%%%%
-%%
-%%
-%% Seek the actual operation scope :
-%%
-%% * if the operation is inherited, get the real scope for it
-%%
-%% * if the operation has a specific pragma, apply the real
-%% scope, otherwise return the including scope
-%%
-getActualScope(G, X, Scope) when is_record(X, op) ->
- OpScope = getRealOpScope(G,X,Scope),
- case ets:match(ic_genobj:pragmatab(G),{codeopt_specific,OpScope}) of
- [[]] ->
- OpScope;
- _ ->
- Scope
- end;
-getActualScope(_G, _X, N) ->
- N.
-
-%%
-%% Just seek and return the scope for the operation
-%% where it were originaly defined
-%%
-getRealOpScope(G,X,N) when is_record(X, op) ->
- Ptab = ic_genobj:pragmatab(G),
- Id = get_id2(X),
-
- case ets:match(Ptab,{op,Id,N,'_','_'}) of
- [[]] ->
- [Id|N];
- _ ->
- getRealOpScope(G, Ptab, X, N, Id, ets:match(Ptab,{inherits,N,'$1'}))
- end;
-getRealOpScope(_G,_X,N) ->
- N.
-
-getRealOpScope(_G, _S, _X, N, Id, []) ->
- [Id|N];
-getRealOpScope(G, S, X, N, Id, [[OS]|OSs]) ->
- case ets:match(S,{op,Id,OS,'_','_'}) of
- [[]] ->
- [Id|OS];
- _ ->
- getRealOpScope(G, S, X, N, Id, OSs)
- end.
-
-selectTypeFromList([]) ->
- transparent;
-selectTypeFromList([{_,transparent}|Rest]) ->
- selectTypeFromList(Rest);
-selectTypeFromList([transparent|Rest]) ->
- selectTypeFromList(Rest);
-selectTypeFromList([_|_Rest]) ->
- multiple.
-
-
-
-getCallErr() ->
- {'ERROR' ,"Bad Operation -- handle call"}.
-
-getCastErr() ->
- {'ERROR' ,"Bad Operation -- handle cast"}.
-
-getInfoErr() ->
- {'ERROR' ,"Bad Operation -- handle info"}.
-
-
-
-
-
-
-%%
-%% Type code access utilities
-%%
-
-tk_operation_data(G, N, X, TL) ->
- case print_tk(G,N,X) of
- true ->
- TL;
- false ->
- no_tk
- end.
-
-tk_interface_data(G, N, X) ->
- InfoList =
- foldr(fun({_Name, Body}, Acc) ->
- get_if(G,N,Body)++Acc end,
- get_if(G,N,get_body(X)),
- X#interface.inherit_body),
- case InfoList of
- [] ->
- no_tk; %%%%%%%% Should be changed to [] <<<<<<<<<<<<<<<<<<<<<<<<<<< Warning !
- _ ->
- InfoList
- end.
-
-
-print_tk(G, N, X) when is_record(X, op)-> %% operation
- case getNocType(G,X,N) of
- transparent ->
- false;
- multiple ->
- false;
- _XTuple -> %%check if there are any USETK pragmas
- operation_usetk(G,N,X)
- end;
-print_tk(_G, _N, _X) -> %% error
- false.
-
-
-operation_usetk(G,N,X) ->
- PTab = ic_genobj:pragmatab(G),
- OTab = ic_genobj:optiontab(G),
- OpName = get_id2(X),
-% SID = ic_util:to_colon(N),
- Res = case use_tk(OTab,[N]) of
- {ok,N} ->
- true;
- false ->
- %% Look if there is an operation with that name
- %% which can be found in an included file.
- case ets:match(PTab,{file_data_included,'_','_',op,'$3',OpName,'_','_','_'}) of
- [] ->
- false;
- ScopeList ->
- case use_tk(OTab,ScopeList) of
- %% There is an operation with that name,
- %% look if it is inherited by interface "N"
- {ok,FoundScope} ->
- ic_pragma:is_inherited_by(FoundScope,N,PTab);
- false ->
- false
- end
- end
- end,
- Res.
-
-
-use_tk(_,[]) ->
- false;
-use_tk(OTab,[[Scope]|Scopes]) ->
- SID = ic_util:to_colon(Scope),
- case ets:match(OTab,{{option,{use_tk,SID}},true}) of
- [] ->
- case ets:match(OTab,{{option,{use_tk,"::"++SID}},true}) of
- [] ->
- use_tk(OTab,Scopes);
- _ ->
- {ok,Scope}
- end;
- _ ->
- {ok,Scope}
- end;
-use_tk(OTab,[Scope|Scopes]) ->
- SID = ic_util:to_colon(Scope),
- case ets:match(OTab,{{option,{use_tk,SID}},true}) of
- [] ->
- case ets:match(OTab,{{option,{use_tk,"::"++SID}},true}) of
- [] ->
- use_tk(OTab,Scopes);
- _ ->
- {ok,Scope}
- end;
- _ ->
- {ok,Scope}
- end.
-
-
-
-
-
-mark_not_transparent(G,N) ->
-
- %% Mark that there are multiple
- %% functions in interface
- S = ic_genobj:pragmatab(G),
- ets:insert(S,{no_transparent,N}).
-
-
-transparent(G) ->
-
- S = ic_genobj:pragmatab(G),
- case ets:match_object(S,{no_transparent,'$0'}) of
- [] ->
- true;
- _ ->
- false
- end.
-
diff --git a/lib/ic/src/ic_options.erl b/lib/ic/src/ic_options.erl
deleted file mode 100644
index d7f56c0d46..0000000000
--- a/lib/ic/src/ic_options.erl
+++ /dev/null
@@ -1,364 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ic_options).
-
--include_lib("ic/src/ic.hrl").
--include_lib("kernel/include/file.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([defaultBe/0, float_to_version/1, get_opt/2, add_opt/3,
- read_cfg/2, which_opts/1, allowed_opt/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-
-%%--------------------------------------------------------------------
-%%
-%% Option handling
-%%
-%% Valid options are: (those with * is NotYetImpl)
-%%
-%% pedantic - makes the compiler really nitty-gritty about its input
-%%
-%% Wall - those warning options that we feel an IDL programmer should
-%% care about. Not as picky as pedantic
-%%
-%% warn_multi_mod - warn if several modules are declared in the same
-%% IDL file
-%%
-%% warn_nested_mod - warn if there are nested modules. This is not a
-%% problem but it breakes the rule that modules are put into one file
-%% each.
-%%
-%% warn_name_shadow - warn if identifiers are shadow through inherited
-%% interfaces. Default is true.
-%%
-%% warn_quoted_atom - warn if atoms needs quote, this makes Erlang
-%% code less nice but is certainly no error.
-%%
-%% nowarn - suppress all warning messages. Will still output warnings
-%% if silent2 option is used
-%%
-%% always_outargs - force object server implementation return the
-%% tuple {RetVal, OutArgs, NewState} even if there are no OutArgs. If
-%% this option is not set then such an operation implementation is
-%% assumed to return {RetVal, NewState}
-%%
-%% use_proc_dict - use the process dictionary in the client
-%% stubs. This means that client stubs return RetVal instead of {ok,
-%% RetVal, OutArgs} and that corba:get_outargs() returns OutArgs. The
-%% out arguments are stored with the key '$corba_outargs'.
-%%
-%% module_group - use the top module as file name for both skeletons
-%% and stubs. Default value is false which means that each interface
-%% is put in a separate file.
-%%
-%% skel_module_group - group all interfaces in a module in one
-%% skeleton file as opposed to one skeleton file for each
-%% interface. Defaults to false.
-%%
-%% stub_module_group - group all interface stubs from a module in one
-%% stub file as opposed to one stub file for each interface. Default
-%% is false.
-%%
-%% *help - prints a small summary of the compiler usage
-%%
-%% silent - suppresses all messages from the compiler
-%%
-%% silent2 - suppresses all messages from the compiler and returns all
-%% warnings or errors as lists. Returns {ok, WarnList} or {error,
-%% WarnList, ErrList}
-%%
-%% *noexec - runs the compiler but does not open files or write to
-%% files.
-%%
-%% {serv, <ModName>} - sets the name of the implementation skeleton
-%% file. This defaults to ModName_skel.
-%%
-%% {impl, <ModName>} - sets the name of the interface server
-%% implementation module name. This defaults to InterfaceName_impl
-%%
-%% {outdir, Dir} - use Dir as the directory to put all generated
-%% files.
-%%
-%% {servdir, Dir} - put all generated skel files in the directory Dir.
-%%
-%% {stubdir, Dir} - put all generated stub files in the directory Dir.
-%%
-%% {this, InterfaceOrOpName} - puts the OE_THIS parameter into the
-%% impl. call. This option can be used both on whole interfaces an on
-%% distinct operations. Fullscoped names must be used (as in {this,
-%% "M1::I1::Op"}). The option can be given in 3 ways: {this, Name}
-%% means this will be added to all matching Name or as {{this, Name},
-%% true} or this can explicitly be asked to be left out as in {{this,
-%% Name}, false} which enables OE_THIS to be passed to all ops of an
-%% interface except those set by the false flag.
-%%
-%% cfgfile - sets the name of the config file that is read at
-%% startup. The order of the different ways to set options is: default
-%% setting, configuration file, options given when generator is
-%% called. Default name for this file is .ic_config
-%%
-%% serv_last_call - tells what the last handle_call clause should
-%% do. It can have the values exception, which makes the last clause
-%% return a CORBA exception and exit which does not generate a last clause
-%% (which will make the server crash on an unknown call)
-%%
-%%
-%% -- UNDOCUMENTED --
-%%
-%% debug - prints debug information
-%%
-%% tokens - prints the tokens from the tokenizer and then exit
-%%
-%% form - prints the form from the parser and then exit
-%%
-%% tform - form returned from type check
-%%
-%% time - if true then time is measured during compilation
-%%
-%%
-%%--------------------------------------------------------------------
-allowed_opt(default_opts, _V) -> true;
-allowed_opt(debug, V) -> is_bool(V);
-allowed_opt(tokens, V) -> is_bool(V);
-allowed_opt(form, V) -> is_bool(V);
-allowed_opt(tform, V) -> is_bool(V);
-allowed_opt(time, V) -> is_bool(V);
-allowed_opt(maxerrs, V) -> is_intorinfinity(V);
-allowed_opt(maxwarns, V) -> is_intorinfinity(V);
-allowed_opt(nowarn, V) -> is_bool(V);
-allowed_opt(show_opts, V) -> is_bool(V);
-
-allowed_opt(help, V) -> is_bool(V);
-allowed_opt('Wall', V) -> is_bool(V);
-allowed_opt(warn_multi_mod, V) -> is_bool(V);
-allowed_opt(warn_quoted_atom, V) -> is_bool(V);
-allowed_opt(warn_nested_mod, V) -> is_bool(V);
-allowed_opt(warn_name_shadow, V) -> is_bool(V);
-allowed_opt(module_group, V) -> is_bool(V);
-allowed_opt(skel_module_group, V) -> is_bool(V);
-allowed_opt(stub_module_group, V) -> is_bool(V);
-allowed_opt(always_outargs, V) -> is_bool(V);
-allowed_opt(pedantic, V) -> is_bool(V);
-%%allowed_opt(gen_serv, V) -> is_bool(V);
-%%allowed_opt(gen_stub, V) -> is_bool(V);
-allowed_opt(gen_hrl, V) -> is_bool(V);
-allowed_opt(serv_last_call, exception) -> true;
-allowed_opt(serv_last_call, exit) -> true;
-allowed_opt(silent, V) -> is_bool(V);
-allowed_opt(silent2, V) -> is_bool(V);
-allowed_opt({serv, _}, _V) -> true;
-allowed_opt({impl, _}, _V) -> true;
-allowed_opt(outdir, _V) -> true;
-allowed_opt(servdir, _V) -> true;
-allowed_opt(stubdir, _V) -> true;
-allowed_opt(cfgfile, _V) -> true;
-allowed_opt(use_preproc, V) -> is_bool(V);
-allowed_opt(preproc_cmd, _V) -> true;
-allowed_opt(preproc_flags, _V) -> true;
-allowed_opt(this, _V) -> true;
-allowed_opt({this, _}, V) -> is_bool(V);
-allowed_opt(from, _V) -> true;
-allowed_opt({from, _}, V) -> is_bool(V);
-allowed_opt(handle_info, _V) -> true;
-allowed_opt({handle_info, _}, V) -> is_bool(V);
-allowed_opt(timeout, _V) -> true;
-allowed_opt({timeout, _}, V) -> is_bool(V);
-allowed_opt(c_timeout, {V1, V2}) -> is_int(V1) and is_int(V2);
-allowed_opt(c_timeout, V) -> is_int(V);
-allowed_opt(c_report, V) -> is_bool(V);
-allowed_opt(scoped_op_calls, V) -> is_bool(V);
-% Compatibility option (semantic check limitation)
-allowed_opt(scl, V) -> is_bool(V);
-% Added switches for non corba generation
-allowed_opt(flags, V) -> is_int(V);
-allowed_opt(be, erl_corba) -> true;
-allowed_opt(be, erl_template) -> true;
-allowed_opt(be, erl_genserv) -> true;
-allowed_opt(be, c_genserv) -> true;
-allowed_opt(be, erl_plain) -> true;
-allowed_opt(be, c_server) -> true;
-allowed_opt(be, c_client) -> true;
-allowed_opt(be, java) -> true;
-% Noc backend
-allowed_opt(be, noc) -> true;
-allowed_opt({broker,_},{_,transparent}) -> true;
-allowed_opt({broker,_},{_,Term}) -> is_term(Term);
-allowed_opt({use_tk,_},V) -> is_bool(V);
-%
-% Multiple be
-allowed_opt(multiple_be, _List) -> true;
-%
-allowed_opt(precond, {_M, _F}) -> true;
-allowed_opt({precond, _}, {_M, _F}) -> true;
-allowed_opt(postcond, {_M, _F}) -> true;
-allowed_opt({postcond, _}, {_M, _F}) -> true;
-allowed_opt(no_codechange, V) -> is_bool(V);
-allowed_opt(user_protocol, _V) -> true;
-allowed_opt(light_ifr, V) -> is_bool(V);
-allowed_opt(_, _) -> false.
-
-
--define(DEFAULTCFGFILE, ".ic_config").
-
-which_opts(G) ->
- ets:match(G#genobj.options, {{option, '$1'}, '$2'}).
-
-add_opt(G, KList, Val) when is_list(KList) ->
- lists:foreach(fun({K, V}) -> add_opt(G, K, V);
- (K) -> add_opt(G, K, Val) end,
- KList);
-
-add_opt(G, servdir, V) ->
- do_add_opt(G, servdir, assure_directory(G, ic_util:to_list(V)));
-add_opt(G, stubdir, V) ->
- do_add_opt(G, stubdir, assure_directory(G, ic_util:to_list(V)));
-add_opt(G, K, V) ->
- do_add_opt(G, K, V).
-
-
-assure_directory(_G, Dir) ->
- Dirs = filename:split(Dir),
- check_dirs(Dirs, [], filename:pathtype(Dir)).
-
-check_dirs([X | Xs], SoFar, Type) ->
- New = if SoFar == [], Type /= absolute ->
- X;
- true ->
- filename:join(SoFar, X)
- end,
- assert_dir(New),
- check_dirs(Xs, New, Type);
-check_dirs([], SoFar, _Type) ->
- SoFar.
-
-assert_dir(D) ->
- case file:read_file_info(D) of
- {ok, X} when X#file_info.type == directory -> ok;
- _ -> case file:make_dir(D) of
- ok -> ok;
- _ -> exit({could_not_create, D})
- end
- end.
-
-do_add_opt(G, handle_info, V) ->
- ?insert(G#genobj.options, {option, {handle_info, V}}, true);
-do_add_opt(G, {handle_info, V}, false) ->
- ?insert(G#genobj.options, {option, {handle_info, V}}, force_false);
-do_add_opt(G, timeout, V) ->
- ?insert(G#genobj.options, {option, {timeout, V}}, true);
-do_add_opt(G, {timeout, V}, false) ->
- ?insert(G#genobj.options, {option, {timeout, V}}, force_false);
-do_add_opt(G, this, V) ->
- ?insert(G#genobj.options, {option, {this, V}}, true);
-do_add_opt(G, {this, V}, false) ->
- ?insert(G#genobj.options, {option, {this, V}}, force_false);
-do_add_opt(G, from, V) ->
- ?insert(G#genobj.options, {option, {from, V}}, true);
-do_add_opt(G, {from, V}, false) ->
- ?insert(G#genobj.options, {option, {from, V}}, force_false);
-do_add_opt(G, scoped_op_calls, V) when V /= true, V /= false ->
- ?insert(G#genobj.options, {option, {scoped_op_calls, V}}, false);
-do_add_opt(G, K, V) ->
- case allowed_opt(K, V) of
- true ->
- case expand_opt(K) of
- L when is_list(L) ->
- add_opt(G, L, V);
- _ ->
- %%io:format("Add opt: ~p ~p~n", [K, V]),
- ?insert(G#genobj.options, {option, K}, V)
- end;
- _ ->
- ic_error:warn(G, {illegal_opt, K})
- end.
-
-get_opt(G, K) ->
- case ets:lookup(G#genobj.options, {option, K}) of
- [] -> false;
- [{{_, K}, V}] -> V
- end.
-
-expand_opt(pedantic) -> [warn_multi_mod, warn_quoted_atom, always_outargs];
-expand_opt(module_group) -> [skel_module_group, stub_module_group];
-expand_opt('Wall') -> [warn_multi_mod, warn_nested_mod, warn_name_shadow];
-expand_opt(outdir) -> [servdir, stubdir];
-expand_opt(default_opts) ->
- ['Wall', gen_hrl, {serv_last_call, exception},
- {outdir, []}, use_preproc, {preproc_cmd, "erl"},
- {preproc_flags, ""}, {maxerrs, 10}, {maxwarns, infinity}];
-%% gcc preproc command {preproc_cmd, "gcc -x c++ -E"}
-expand_opt(Opt) -> Opt.
-
-
-%% Use this if user not provide
-%% a backend.
-defaultBe() -> erl_corba.
-
-
-%%
-%% Read any config file
-read_cfg(G, Opts) ->
- Name = case lists:keysearch(cfgfile, 1, Opts) of
- {value, {_, N}} -> ic_util:to_list(N);
- _ -> ?DEFAULTCFGFILE
- end,
- case file:consult(Name) of
- {ok, OptList} ->
- add_opt(G, OptList, true);
- _X when Name == ?DEFAULTCFGFILE -> ok;
-%% {error, X} ->
-%% ic_error:warn(G, {cfg_open, X, Name});
- X -> ic_error:warn(G, {cfg_open, X, Name})
- end.
-
-
-float_to_version({_,_,Str}) -> Str.
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-is_bool(true) -> true;
-is_bool(false) -> true;
-is_bool(_) -> false.
-
-is_int(V) when is_integer(V) -> true;
-is_int(_) -> false.
-
-is_intorinfinity(X) when is_integer(X) -> true;
-is_intorinfinity(infinity) -> true;
-is_intorinfinity(_X) -> false.
-
-
-is_term(Term) when is_tuple(Term) -> true;
-is_term(_NoTerm) -> false.
-
diff --git a/lib/ic/src/ic_plainbe.erl b/lib/ic/src/ic_plainbe.erl
deleted file mode 100644
index 6875c1314e..0000000000
--- a/lib/ic/src/ic_plainbe.erl
+++ /dev/null
@@ -1,356 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(ic_plainbe).
-
-
--export([do_gen/3]).
-%%------------------------------------------------------------
-%%
-%% Internal stuff
-%%
-%%------------------------------------------------------------
-
--import(ic_util, [mk_var/1, mk_oe_name/2, to_atom/1, to_list/1]).
--import(ic_forms, [get_id/1, get_id2/1, get_body/1]).
--import(ic_codegen, [emit/3, nl/1]).
-
--import(lists, [foreach/2, map/2]).
-
--include("icforms.hrl").
--include("ic.hrl").
-
-%%------------------------------------------------------------
-%%
-%% Generate the client side Erlang stubs.
-%%
-%% Each module is generated to a separate file.
-%%
-%% Export declarations for all interface functions must be
-%% generated. Each function then needs to generate a function head and
-%% a body. IDL parameters must be converted into Erlang parameters
-%% (variables, capitalised) and a type signature list must be
-%% generated (for later encode/decode).
-%%
-%%------------------------------------------------------------
-
-
-do_gen(G, File, Form) ->
- G2 = ic_file:filename_push(G, [], mk_oe_name(G,
- ic_file:remove_ext(to_list(File))),
- erlang),
- gen_head(G2, [], Form),
- exportDependency(G2),
- gen(G2, [], Form),
- genDependency(G2),
- ic_file:filename_pop(G2, erlang),
- ok.
-
-
-gen(G, N, [X|Xs]) when is_record(X, preproc) ->
- NewG = ic:handle_preproc(G, N, X#preproc.cat, X),
- gen(NewG, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, module) ->
- CD = ic_code:codeDirective(G,X),
- G2 = ic_file:filename_push(G, N, X, CD),
- N2 = [get_id2(X) | N],
- gen_head(G2, N2, X),
- gen(G2, N2, get_body(X)),
- G3 = ic_file:filename_pop(G2, CD),
- gen(G3, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, interface) ->
- %% Add inheritence data to pragmatab
- ic_pragma:add_inh_data(G,N,X),
- G2 = ic_file:filename_push(G, N, X, erlang),
- N2 = [get_id2(X) | N],
- gen_head(G2, N2, X),
- gen(G2, N2, get_body(X)),
- foreach(fun({_Name, Body}) -> gen(G2, N2, Body) end,
- X#interface.inherit_body),
- G3 = ic_file:filename_pop(G2, erlang),
- gen(G3, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, const) ->
-% N2 = [get_id2(X) | N],
- emit_constant_func(G, X#const.id, X#const.val),
- gen(G, N, Xs); %% N or N2?
-
-gen(G, N, [X|Xs]) when is_record(X, op) ->
- {Name, ArgNames, TypeList, OutArgs} = extract_info(G, N, X),
- emit_func(G, N, X, Name, ArgNames, TypeList, OutArgs),
- gen(G, N, Xs);
-
-
-gen(G, N, [X|Xs]) when is_record(X, attr) ->
- emit_attr(G, N, X, fun emit_func/7),
- gen(G, N, Xs);
-
-gen(G, N, [X|Xs]) when is_record(X, except) ->
- icstruct:except_gen(G, N, X, erlang),
- gen(G, N, Xs);
-
-gen(G, N, [X|Xs]) ->
- case may_contain_structs(X) of
- true -> icstruct:struct_gen(G, N, X, erlang);
- false -> ok
- end,
- gen(G, N, Xs);
-
-gen(_G, _N, []) -> ok.
-
-
-may_contain_structs(X) when is_record(X, typedef) -> true;
-may_contain_structs(X) when is_record(X, struct) -> true;
-may_contain_structs(X) when is_record(X, union) -> true;
-may_contain_structs(_X) -> false.
-
-
-%%------------------------------------------------------------
-%%
-%% Export stuff
-%%
-%% Gathering of all names that should be exported from a stub
-%% file.
-%%
-
-
-gen_head_special(G, N, X) when is_record(X, interface) ->
- Fd = ic_genobj:stubfiled(G),
-
- foreach(fun({Name, Body}) ->
- ic_codegen:comment(Fd, "Exports from ~p",
- [ic_util:to_colon(Name)]),
- ic_codegen:export(Fd, exp_top(G, N, Body, [])),
- nl(Fd)
- end, X#interface.inherit_body),
- Fd;
-gen_head_special(_G, _N, _X) -> ok.
-
-
-
-%% Shall generate all export declarations
-gen_head(G, N, X) ->
- case ic_genobj:is_stubfile_open(G) of
- true ->
- F = ic_genobj:stubfiled(G),
- ic_codegen:comment(F, "Interface functions"),
- ic_codegen:export(F, exp_top(G, N, X, [])),
- nl(F),
- gen_head_special(G, N, X);
- false -> ok
- end.
-
-exp_top(_G, _N, X, Acc) when element(1, X) == preproc ->
- Acc;
-exp_top(G, N, L, Acc) when is_list(L) ->
- exp_list(G, N, L, Acc);
-exp_top(G, N, M, Acc) when is_record(M, module) ->
- exp_list(G, N, get_body(M), Acc);
-exp_top(G, N, I, Acc) when is_record(I, interface) ->
- exp_list(G, N, get_body(I), Acc);
-exp_top(G, N, X, Acc) ->
- exp3(G, N, X, Acc).
-
-exp3(_G, _N, C, Acc) when is_record(C, const) ->
- [{get_id(C#const.id), 0} | Acc];
-
-exp3(_G, _N, Op, Acc) when is_record(Op, op) ->
- FuncName = get_id(Op#op.id),
- Arity = length(ic:filter_params([in, inout], Op#op.params)),
- [{FuncName, Arity} | Acc];
-
-exp3(_G, _N, A, Acc) when is_record(A, attr) ->
- lists:foldr(fun(Id, Acc2) ->
- {Get, Set} = mk_attr_func_names([], get_id(Id)),
- case A#attr.readonly of
- {readonly, _} -> [{Get, 1} | Acc2];
- _ -> [{Get, 1}, {Set, 2} | Acc2]
- end end, Acc, ic_forms:get_idlist(A));
-
-exp3(_G, _N, _X, Acc) -> Acc.
-
-exp_list(G, N, L, OrigAcc) ->
- lists:foldr(fun(X, Acc) -> exp3(G, N, X, Acc) end, OrigAcc, L).
-
-
-
-
-%%------------------------------------------------------------
-%%
-%% Emit stuff
-%%
-%% Low level generation primitives
-%%
-
-
-emit_func(G, _N, X, Name, ArgNames, _TypeList, OutArgs) ->
- case ic_genobj:is_stubfile_open(G) of
- false -> ok;
- true ->
- Fd = ic_genobj:stubfiled(G),
- OpName = list_to_atom(Name),
- ArgList = mk_list(ArgNames),
- emit_op_comment(G, Fd, X, OpName, ArgNames, OutArgs),
- emit(Fd, "~p(~s) ->\n", [OpName,ArgList]),
- emit(Fd, " ~p:~p(~s).\n\n", [to_atom(ic_genobj:impl(G)), OpName, ArgList])
- end.
-
-emit_attr(G, N, X, F) ->
- XX = #id_of{type=X},
- {GetType, SetType} = mk_attr_func_types(N, X),
- lists:foreach(fun(Id) ->
- X2 = XX#id_of{id=Id},
- {Get, Set} = mk_attr_func_names(N, get_id(Id)),
- F(G, N, X2, Get, [], GetType, []),
- case X#attr.readonly of
- {readonly, _} -> ok;
- _ ->
- F(G, N, X2, Set, [ic_util:mk_name(G, "Value")],
- SetType, [])
- end end, ic_forms:get_idlist(X)).
-
-emit_constant_func(G, Id, Val) ->
- case ic_genobj:is_stubfile_open(G) of
- false -> ok;
- true ->
- Fd = ic_genobj:stubfiled(G),
- N = list_to_atom(get_id(Id)),
- emit_const_comment(G, Fd, Id, N),
- emit(Fd, "~p() -> ~p.\n\n", [N, Val])
- end.
-
-
-emit_const_comment(_G, F, _X, Name) ->
- ic_codegen:mcomment_light(F,
- [io_lib:format("Constant: ~p", [Name])]).
-
-
-emit_op_comment(G, F, X, Name, InP, OutP) ->
- ic_codegen:mcomment_light(F,
- [io_lib:format("~s: ~p", [get_title(X), Name]),
- "",
- get_returns(G, X, InP, OutP) |
- get_raises(X)]).
-
-get_title(X) when is_record(X, attr) -> "Attribute Operation";
-get_title(_X) -> "Operation".
-
-get_raises(X) when is_record(X, op) ->
- if X#op.raises == [] -> [];
- true ->
- [" Raises: " ++
- mk_list(lists:map(fun(E) -> ic_util:to_colon(E) end, X#op.raises))]
- end;
-get_raises(_X) -> [].
-
-get_returns(_G, _X, _InP, []) ->
- " Returns: RetVal";
-get_returns(G, _X, _InP, OutP) ->
- " Returns: "++mk_list(["RetVal" | mk_erl_vars(G, OutP)]).
-
-
-
-
-%%------------------------------------------------------------
-%%
-%% Utilities
-%%
-%% Convenient little go-get functions
-%%
-%%------------------------------------------------------------
-
-%% The automaticly generated get and set operation names for an
-%% attribute.
-mk_attr_func_names(_Scope, Name) ->
- {"_get_" ++ Name, "_set_" ++ Name}.
-
-%% Returns TK of the Get and Set attribute functions.
-mk_attr_func_types(_N, X) ->
- TK = ic_forms:get_tk(X),
- {{TK, [], []}, {tk_void, [TK], []}}.
-
-
-
-%%------------------------------------------------------------
-%%
-%% Generation utilities and common stuff
-%%
-%% Convenient stuff for generation
-%%
-%%------------------------------------------------------------
-
-
-%% Input is a list of parameters (in parse form) and output is a list
-%% of capitalised variable names. mk_var is in icgen
-mk_erl_vars(_G, Params) ->
- map(fun(P) -> mk_var(get_id(P#param.id)) end, Params).
-
-
-%% mk_list produces a nice comma separated string of variable names
-mk_list([]) -> [];
-mk_list([Arg | Args]) ->
- Arg ++ mk_list2(Args).
-mk_list2([Arg | Args]) ->
- ", " ++ Arg ++ mk_list2(Args);
-mk_list2([]) -> [].
-
-
-%%------------------------------------------------------------
-%%
-%% Parser utilities
-%%
-%% Called from the yecc parser. Expands the identifier list of an
-%% attribute so that the attribute generator never has to handle
-%% lists.
-%%
-%%------------------------------------------------------------
-
-
-
-
-%% Export code produce for dependency function
-exportDependency(G) ->
- Fd = ic_genobj:stubfiled(G),
- ic_codegen:export(Fd, [{oe_dependency, 0}]),
- nl(Fd).
-
-%% Code produce for dependency function
-genDependency(G) ->
- Fd = ic_genobj:stubfiled(G),
- nl(Fd),nl(Fd),
- ic_codegen:comment(Fd, "Idl file dependency list function"),
- emit(Fd, "oe_dependency() ->\n", []),
- emit(Fd, " ~p.\n\n", [ic_pragma:get_dependencies(G)]).
-
-
-
-
-extract_info(G, _N, X) when is_record(X, op) ->
- Name = get_id2(X),
- InArgs = ic:filter_params([in,inout], X#op.params),
- OutArgs = ic:filter_params([out,inout], X#op.params),
- ArgNames = mk_erl_vars(G, InArgs),
- TypeList = {ic_forms:get_tk(X),
- map(fun(Y) -> ic_forms:get_tk(Y) end, InArgs),
- map(fun(Y) -> ic_forms:get_tk(Y) end, OutArgs)
- },
- {Name, ArgNames, TypeList, OutArgs}.
diff --git a/lib/ic/src/ic_pp.erl b/lib/ic/src/ic_pp.erl
deleted file mode 100644
index 8c2e3a0ffe..0000000000
--- a/lib/ic/src/ic_pp.erl
+++ /dev/null
@@ -1,2245 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(ic_pp).
-
--export([run/2]).
-
--define(is_number(X), X >= $0, X =< $9).
--define(is_upper(X), X >= $A, X =< $Z).
--define(is_lower(X), X >= $a, X =< $z).
--define(is_underline(X), X == $_).
--define(is_tab(X), X == 9).
--define(is_space(X), X == 32).
--define(tab, 9).
--define(space, 32).
-
-
-%%======================================================================================
-%%======================================================================================
-%%======================================================================================
-%% Preprocessor
-%%
-%% This preprocessor is equivalent to the gcc-preprocessor. It takes a file name and
-%% a list of preprocessor flags as an input and returns a processed text file.
-%%
-%% The processing is done in two phases.
-%% In the first phase the input file is tokenised into a list where all comments are
-%% replaced by a space and all "backslash-newline" sequences are removed.
-%%
-%% In the second phase all macros are expanded.
-
-%% %% %% NOTE: #if, #else, and #elif are not yet implemented.
-%% Only '#if 0' is implemented to be possible to keep old code as a comment for
-%% future refence by putting '#if 0' before it and '#endif' after it.
-%%
-%%======================================================================================
-%%======================================================================================
-%%======================================================================================
-
-
-%%======================================================================================
-%% Variables which are used throughout the program:
-%% ------------------------------------------------
-%%
-%% Command A preprocessor command
-%% Current Temporary variable used when tokenising the file
-%% Defs The currently valid macro definitions
-%% Err The current list of errors = [{file, line number, error text}, ...]
-%% File The tokenised file (or what remains of it when expanding the macros)
-%% Flags The preprocessor flags
-%% FN or FileName Tbe name of the current file
-%% IfCou Used for ifdef/ifndef/endif values: check_all | {endif, Endif, IfLine}
-%% Endif = number of matching endif's yet to be found
-%% Ifline = the line number for the the first found ifdef/ifndef
-%% IncDir Directories to be searched for included files
-%% IncFile Stack of included files
-%% IncLine The line numer of an include
-%% L The current line number
-%% Name Name of a macro
-%% Nl Number of encountered newlines
-%% No_of_para Numer of parameters of the currently expanded macro
-%% Out The result of the second step
-%% Parameters The parameters of the currently expanded macro
-%% PrevFile The name of the "parent" file which includes the currently expanded file
-%% Rem Remaining of the file currently being expanded
-%% Removed The tokens removed, used when removing tokens to the end of a line
-%% Result The current result of something
-%% SelfRef List of variables which shoud not be expanded at the rescan to avoid
-%% endless loops due to self referencing
-%% Str Temporary string
-%% Text A variable used for string handling, e.g at error handling
-%% Tokens Temoprary list when tokenising
-%% War The current list of warnings = [{file, line number, warning text}, ...]
-%% X Temporary variable used when the value is not important
-%% Y Temporary variable used when the value is not important
-%%
-%%======================================================================================
-
-%% Multiple Include Optimization
-%%
-%% Algorithm described at:
-%% http://gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html
--record(mio, {valid = true, %% multiple include valid
- cmacro, %% controlling macro of the current conditional directive
- depth = 0, %% conditional directive depth
- included = []}).
-
-
-
-%%======================================================================================
-%%======================================================================================
-%%======================================================================================
-%% The main entry for the preprocessor
-%%
-%%
-%% Output {ok, Out, War} | {error, Err}
-%%======================================================================================
-%%======================================================================================
-%%======================================================================================
-run(FileName, Flags) when is_atom(FileName) ->
- run(atom_to_list(FileName), Flags);
-
-run(FileName, Flags) ->
- IncDir = include_dir(Flags),
-
- case catch file:read_file(FileName) of
- {ok, Bin} ->
- FileList = binary_to_list(Bin),
- run(FileList, FileName, IncDir, Flags);
- {error, _} ->
- Text = "No such file or directory",
- {error, [FileName ++ ": " ++ Text]}
- end.
-
-
-run(FileList, FileName, IncDir, Flags) ->
- %%----------------------------------------------------------
- %% Run the first phase, i.e tokenise the file
- %%----------------------------------------------------------
- File = tokenise(FileList, FileName),
-
- %%----------------------------------------------------------
- %% Run the second phase, i.e expand macros
- %%----------------------------------------------------------
- {Out, Err, War, _Defs, _Mio, IfCou} = expand(File, FileName, IncDir, Flags),
-
- %%----------------------------------------------------------
- %% Check if all #if #ifdef #ifndef have a matching #endif
- %%----------------------------------------------------------
- IfError = case IfCou of
- {endif, Endif, IfLine} when Endif > 0 ->
- [{FileName, IfLine, "unterminated `#if' conditional"}];
- _ ->
- []
- end,
-
- Err2 = Err++IfError,
-
- case Err2 of
- [] ->
- {ok, lists:flatten(lists:reverse(Out)), lists:reverse(War)};
- _ ->
- {error, lists:reverse(Err2)}
- end.
-
-%%======================================================================================
-%% The entry for all included files
-%%
-%%
-%% Output {Out, Err, War, Defs, MultipleIncludeValid}
-%%======================================================================================
-run_include(FileName, FileList, _Out, Defs, Err, War, IncLine, IncFile, IncDir, Mio) ->
-
- %%----------------------------------------------------------
- %% Run the first phase, i.e tokenise the file
- %%----------------------------------------------------------
- [PrevFile | _T] = IncFile,
- {File, FileInfoStart, FileInfoEnd} =
- tokenise(FileList, FileName, IncLine, PrevFile),
-
- %%----------------------------------------------------------
- %% Run the second phase, i.e expand macros
- %%----------------------------------------------------------
- {Out2, Err2, War2, Defs2, Mio2, IfCou2} =
- expand([FileInfoStart|File]++FileInfoEnd, Defs, Err, War,
- [FileName|IncFile], IncDir,
- #mio{included=Mio#mio.included}),
-
- MergeIncluded = sets:to_list(sets:from_list(Mio#mio.included ++ Mio2#mio.included)),
-
- Mio3 =
- case {Mio2#mio.valid, Mio2#mio.cmacro} of
- {V, Macro} when V == false;
- Macro == undefined ->
- update_mio(Mio#mio{included=MergeIncluded});
- {true, _} ->
- update_mio({include, FileName}, Mio#mio{included=MergeIncluded})
- end,
-
- %%----------------------------------------------------------
- %% Check if all #if #ifdef #ifndef have a matching #endif
- %%----------------------------------------------------------
- IfError = case IfCou2 of
- {endif, Endif, IfLine} when Endif > 0 ->
- [{FileName, IfLine, "unterminated `#if' conditional"}];
- _ ->
- []
- end,
-
- {Out2, Defs2, Err2++IfError, War2, Mio3}.
-
-
-
-
-%%===================================================================================
-%%===================================================================================
-%%===================================================================================
-%% Tokenise the file
-%%
-%%
-%% Output: File
-%%
-%% Description:
-%% The input file is tokenised into a list where all comments are replaced
-%% by a space and all "backslash-newline" sequences are removed.
-%%
-%% A file information is added at start and end of an included file to set the
-%% current file name and line number.
-%%
-%%
-%% A token consists of:
-%% --------------------
-%%
-%% {char, Char} special characters like ()[]{},!%& etc
-%% {command,Command} a macro command
-%% {expanded,Str} an expanded variable, used to prevent infinite loops
-%% at self reference
-%% {file_info,FI} start and end information of a file
-%% FI is a string of the following format:
-%% "# Line FileName Int" were Int is
-%% 1 if start of an included file,
-%% 2 when returning to "parent" file
-%% {nl, L} newline
-%% {number,Num) variable, a string starting with a number
-%% {self_ref,Var} to allow reference to a variable again, used when expanding
-%% self refering macros
-%% space a space
-%% space_exp a space, special notation to prevent not wanted concatination
-%% {string, Str} a (tail of a) string constant
-%% {string_part, Str} a head of a string constant defined on several consecutive lines
-%% {sys_head, Str} (tail of) the file name of included system file
-%% {sys_head_part , Str} the file name of included system file
-%% {var,Var} variable, a string starting with minuscular or capital letter or
-%% an underline
-%%
-%% Note, comments are not removed within a character or string constant
-%% or inside an include-definition where the file name is delimited with < >
-%%===================================================================================
-%%===================================================================================
-%%===================================================================================
-
-tokenise(File, FileName) ->
- {Result, _L} = token(File, 2, [], not_set, 0),
- FI_start = lists:reverse(lists:flatten(io_lib:format("# 1 \"~ts\"~n",[FileName]))),
- FileInfoStart = {file_info, FI_start},
- [FileInfoStart | Result].
-
-tokenise(File, FileName, IncLine, PrevFile) ->
- {Result, _L} = token(File, 2, [], not_set, 0),
- FI_start = lists:reverse(lists:flatten(io_lib:format("# 1 \"~ts\" 1~n",[FileName]))),
- FileInfoStart = {file_info, FI_start},
- FI_end = lists:reverse(lists:flatten(io_lib:format("# ~p \"~ts\" 2~n~n",[IncLine-1,PrevFile]))),
- FileInfoEnd = [{file_info, FI_end}],
- {Result, FileInfoStart, FileInfoEnd}.
-% [FileInfoStart | Result] ++ FileInfoEnd.
-
-
-%%===================================================================================
-%% token(InputFile, L, Result, Gen)
-%% Gen information of the first token on the line, default = not_set
-%%
-%% Output: File
-%%===================================================================================
-
-%%==================================================================
-%% Normal line
-%%==================================================================
-%%---------------------------------------
-%% All file tokenised
-%%---------------------------------------
-token([], L, [{nl,NL}|Result], _Gen, _BsNl) when L == NL+1->
- {lists:reverse([{nl,NL}|Result]), L};
-token([], L, Result, _Gen, _BsNl) ->
- {lists:reverse([{nl,L-1}|Result]), L};
-
-%%---------------------------------------
-%% String
-%%---------------------------------------
-token(File, L, Result, string, BsNl) ->
- case token_string(File, []) of
- {Rem, Str, nl} ->
- Result1 = [{nl, L}, {string,Str} | Result],
- token(Rem, L+1, Result1, string, BsNl);
- {Rem, Str} ->
- token(Rem, L, [{string,Str}|Result], not_set, BsNl)
- end;
-
-token([$"|File], L, Result, Gen, BsNl) ->
- case token_string(File, []) of
- {Rem, Str, nl} ->
- Result1 = [{nl, L}, {string_part,Str} | Result],
- token(Rem, L+1, Result1, string, BsNl);
- {Rem, Str} ->
- token(Rem, L, [{string,Str}|Result], Gen, BsNl)
- end;
-
-%%---------------------------------------
-%% Include with < >
-%%---------------------------------------
-token(File, L, Result, include, BsNl) ->
- case token_include(File, []) of
- {Rem, Str, nl} ->
- Result1 = [{nl, L}, {sys_head,Str} | Result],
- token(Rem, L+1, Result1, include, BsNl);
- {Rem, Str} ->
- token(Rem, L, [{sys_head,Str}|Result], not_set, BsNl)
- end;
-
-token([$<|File], L, [space,{command,"include"}|Result], Gen, BsNl) ->
- case token_include(File, []) of
- {Rem, Str, nl} ->
- Result1 = [{nl, L}, {sys_head_part,Str}, space, {command,"include"} |Result],
- token(Rem, L+1,Result1, include, BsNl);
- {Rem, Str} ->
- Result1 = [{sys_head,Str}, space, {command,"include"} |Result],
- token(Rem, L, Result1, Gen, BsNl)
- end;
-token([$<|File], L, [{command,"include"}|Result], Gen, BsNl) ->
- case token_include(File, []) of
- {Rem, Str, nl} ->
- Result1 = [{nl, L}, {sys_head_part,Str}, space, {command,"include"} |Result],
- token(Rem, L+1,Result1, include, BsNl);
- {Rem, Str} ->
- Result1 = [{sys_head,Str}, space, {command,"include"} |Result],
- token(Rem, L, Result1, Gen, BsNl)
- end;
-
-
-
-
-%%---------------------------------------
-%% CR (just remove these)
-%%---------------------------------------
-token([$\r|File], L, Result, Gen, BsNl) ->
-% Bs = lists:duplicate(BsNl+1,{nl,L}),
- token(File, L, Result, Gen, BsNl); %% Bs or BsNl?
-
-%%---------------------------------------
-%% Newline
-%%---------------------------------------
-token([$\n|File], L, Result, _Gen, BsNl) ->
- Bs = lists:duplicate(BsNl+1,{nl,L}),
- token(File, L+1, Bs++Result, not_set, 0);
-
-token([$\\,$\n|File], L, Result, Gen, BsNl) ->
- token(File, L, Result, Gen, BsNl+1);
-
-%%---------------------------------------
-%% Comments
-%%---------------------------------------
-token([$/,$/|File], L, Result, not_set, BsNl) ->
- Rem = skip_to_nl(File),
- token(Rem, L+1,[{nl, L} | Result], not_set, BsNl);
-token([$/,$/|File], L, Result, _Gen, BsNl) ->
- Rem = skip_to_nl(File),
- token(Rem, L+1,[{nl, L} | Result], not_set, BsNl);
-
-token([$/,$*|File], L, Result, not_set, BsNl) ->
- case token_comment(File) of
- {Rem, nl} ->
- token(Rem, L+1, [{nl, L} | Result], not_set, BsNl);
- Rem ->
- token(Rem, L, Result, not_set, BsNl)
- end;
-token([$/,$*|File], L, Result, Gen, BsNl) ->
- case token_comment(File) of
- {Rem, nl} ->
- token(Rem, L+1, [{nl, L}, space | Result], not_set, BsNl);
- Rem ->
- token(Rem, L, [space|Result], Gen, BsNl)
- end;
-
-%%---------------------------------------
-%% Variable
-%%---------------------------------------
-token([X|File], L, Result, Gen, BsNl) when ?is_upper(X) ->
- GenNew = case Gen of not_set -> var; _ -> Gen end,
- {Rem, Var} = tok_var(File, [X]),
- token(Rem, L, [{var,Var}|Result], GenNew, BsNl);
-token([X|File], L, Result, Gen, BsNl) when ?is_lower(X) ->
- GenNew = case Gen of not_set -> var; _ -> Gen end,
- {Rem, Var} = tok_var(File, [X]),
- token(Rem, L, [{var,Var}|Result], GenNew, BsNl);
-token([X|File], L, Result, Gen, BsNl) when ?is_underline(X) ->
- GenNew = case Gen of not_set -> var; _ -> Gen end,
- {Rem, Var} = tok_var(File, [X]),
- token(Rem, L, [{var,Var}|Result], GenNew, BsNl);
-
-%%---------------------------------------
-%% Number
-%%---------------------------------------
-token([X|File], L, Result, Gen, BsNl) when ?is_number(X) ->
- GenNew = case Gen of not_set -> number; _ -> Gen end,
- {Rem, Tokens} = tok_number(File, [X]),
- token(Rem, L, [{number,Tokens}|Result], GenNew, BsNl);
-
-%%---------------------------------------
-%% Space
-%%---------------------------------------
-token([X|File], L, [Y|Result], Gen, BsNl) when ?is_space(X) ->
- case Y of
- space ->
- Rem = remove_leading_spaces(File),
- token(Rem, L, [Y|Result], Gen, BsNl);
- {nl,_,_} ->
- Rem = remove_leading_spaces(File),
- token(Rem, L, Result, Gen, BsNl);
- _ ->
- Rem = remove_leading_spaces(File),
- token(Rem, L, [space, Y |Result], Gen, BsNl)
- end;
-
-token([X|File], L, [Y|Result], Gen, BsNl) when ?is_tab(X) ->
- case Y of
- space ->
- Rem = remove_leading_spaces(File),
- token(Rem, L, [Y|Result], Gen, BsNl);
- {nl,_,_} ->
- Rem = remove_leading_spaces(File),
- token(Rem, L, Result, Gen, BsNl);
- _ ->
- Rem = remove_leading_spaces(File),
- token(Rem, L, [space, Y |Result], Gen, BsNl)
- end;
-
-%%---------------------------------------
-%% Command
-%%---------------------------------------
-token([$#|File], L, Result, not_set, BsNl) ->
- {Rem, Command} = token_pp_com(File),
- case catch list_to_integer(Command) of
- {'EXIT', _} ->
- token(Rem, L, [{command,Command}|Result], not_set, BsNl);
- _Int ->
- Result1 = [{number,Command}, {command,"line"}| Result],
- token(Rem, L, Result1, not_set, BsNl)
- end;
-
-%%---------------------------------------
-%% Char
-%%---------------------------------------
-token([X|File], L, Result, Gen, BsNl) ->
- GenNew = case Gen of not_set -> char; _ -> Gen end,
- token(File, L, [{char,X}|Result], GenNew, BsNl).
-
-
-%%==================================================================
-%% Scan to the end of a token
-%%==================================================================
-%%---------------------------------------
-%% Number
-%%---------------------------------------
-tok_number([], Str) ->
- {[], lists:reverse(Str)};
-tok_number([X|File], Str) when ?is_upper(X) ->
- tok_number(File, [X|Str]);
-tok_number([X|File], Str) when ?is_lower(X) ->
- tok_number(File, [X|Str]);
-tok_number([X|File], Str) when ?is_underline(X) ->
- tok_number(File, [X|Str]);
-tok_number([X|File], Str) when ?is_number(X) ->
- tok_number(File, [X|Str]);
-tok_number(File, Str) ->
- {File, lists:reverse(Str)}.
-
-
-%%---------------------------------------
-%% Variable
-%%---------------------------------------
-tok_var([], Str) ->
- {[], lists:reverse(Str)};
-tok_var([X|File], Str) when ?is_upper(X) ->
- tok_var(File, [X|Str]);
-tok_var([X|File], Str) when ?is_lower(X) ->
- tok_var(File, [X|Str]);
-tok_var([X|File], Str) when ?is_underline(X) ->
- tok_var(File, [X|Str]);
-tok_var([X|File], Str) when ?is_number(X) ->
- tok_var(File, [X|Str]);
-tok_var(File, Str) ->
- {File, lists:reverse(Str)}.
-
-
-%%---------------------------------------
-%% Preprocessor command
-%%---------------------------------------
-token_pp_com([X|File]) when ?is_upper(X) ->
- tok_var(File, [X]);
-token_pp_com([X|File]) when ?is_lower(X) ->
- tok_var(File, [X]);
-token_pp_com([X|File]) when ?is_underline(X) ->
- tok_var(File, [X]);
-token_pp_com([X|File]) when ?is_number(X) ->
- tok_var(File, [X]);
-token_pp_com(File) ->
- Rem = remove_leading_spaces(File),
- {Rem, "null"}.
-
-
-
-%%---------------------------------------
-%% Comment
-%%---------------------------------------
-token_comment([]) ->
- [];
-token_comment([$*,$/|File]) ->
- File;
-token_comment([$\n|File]) ->
- {[$/,$*|File], nl};
-token_comment([$\r,$\n|File]) ->
- {[$/,$*|File], nl};
-token_comment([$\\,$\n|File]) ->
- {[$/,$*|File], nl};
-%token_comment([$\\,$\n|File]) ->
-% token_comment(File);
-token_comment([_|File]) ->
- token_comment(File).
-
-
-%%---------------------------------------
-%% String
-%%---------------------------------------
-token_string([], Str) ->
- {[], lists:reverse(Str)};
-token_string([$"|File], Str) ->
- {File, lists:reverse(Str)};
-token_string([$\n|File], Str) ->
- {File, lists:reverse(Str), nl};
-token_string([$\r,$\n|File], Str) ->
- {File, lists:reverse(Str), nl};
-token_string([$\\,$\n|File], Str) ->
- token_string(File, Str);
-token_string([X|File], Str) ->
- token_string(File, [X|Str]).
-
-
-%%---------------------------------------
-%% Include
-%%---------------------------------------
-token_include([], Str) ->
- {[], lists:reverse(Str)};
-token_include([$>|File], Str) ->
- {File, lists:reverse(Str)};
-token_include([$\n|File], Str) ->
- {File, lists:reverse(Str), nl};
-token_include([$\r,$\n|File], Str) ->
- {File, lists:reverse(Str), nl};
-token_include([$\\,$\n|File], Str) ->
- token_include(File, Str);
-token_include([X|File], Str) ->
- token_include(File, [X|Str]).
-
-
-
-
-%%===================================================================================
-%% detokenise a list of tokens, until next newline
-%%
-%% Output: a string
-%%===================================================================================
-detokenise(Tokens) ->
- detokenise(Tokens, []).
-
-detokenise([], Result) ->
- lists:flatten(Result);
-detokenise([space], Result) ->
- lists:flatten(Result);
-detokenise([space_exp], Result) ->
- lists:flatten(Result);
-detokenise([space|Rem], Result) ->
- detokenise(Rem, Result++[?space]);
-detokenise([space_exp|Rem], Result) ->
- detokenise(Rem, Result++[?space]);
-detokenise([nl|Rem], Result) ->
- detokenise(Rem, Result++[$\n]);
-detokenise([{_, String}|Rem], Result) ->
- detokenise(Rem, Result++[String]).
-
-
-detokenise_pragma(Tokens) ->
- detokenise_pragma(Tokens, []).
-
-detokenise_pragma([], Result) ->
- lists:flatten(Result);
-detokenise_pragma([space], Result) ->
- lists:flatten(Result);
-detokenise_pragma([space|Rem], Result) ->
- detokenise_pragma(Rem, Result++[?space]);
-detokenise_pragma([nl|Rem], Result) ->
- detokenise_pragma(Rem, Result++[$\n]);
-detokenise_pragma([{string, String}|Rem], Result) ->
- detokenise_pragma(Rem, Result++[$"|String]++[$"]);
-detokenise_pragma([{_, String}|Rem], Result) ->
- detokenise_pragma(Rem, Result++[String]).
-
-
-
-
-
-
-
-%%======================================================================================
-%%======================================================================================
-%%======================================================================================
-%% Expand macros.
-%%
-%%
-%% Output: A text file
-%%
-%% Description: Expands all macros. All macro definitions are logged in a list 'Defs'
-%% and all found errors and warnings are logged in a list 'Err' and 'War',
-%% respectively.
-%%
-%% When a macro name is found in a source line it is expanded according
-%% to the current 'Defs'-list. The macro must agree both to the name
-%% and number of parameters, otherwise an error is reported.
-%%======================================================================================
-%%======================================================================================
-%%======================================================================================
-
-
-expand(List, FileName, IncDir, Flags) ->
- %% Get all definitions from preprocessor commnads
- %% and merge them on top of the file collected.
- CLDefs = get_cmd_line_defs(Flags),
- expand(List, [], [], CLDefs, [FileName], IncDir, #mio{}, check_all, [], [], 1, FileName).
-
-expand(List, Defs, Err, War, [FileName|IncFile], IncDir, Mio) ->
- expand(List, [], [], Defs, [FileName|IncFile], IncDir, Mio, check_all, Err, War, 1, FileName).
-
-%%=======================================================
-%% Main loop for the expansion
-%%=======================================================
-expand([], Out, _SelfRef, Defs, _IncFile, _IncDir, Mio, IfCou, Err, War, _L, _FN) ->
-% io:format("~n ===============~n"),
-% io:format(" definitions ~p~n",[lists:reverse(Defs)]),
-% io:format(" found warnings ~p~n",[lists:reverse(War)]),
-% io:format(" found errors ~p~n",[lists:reverse(Err)]),
-% io:format(" ===============~n~n~n"),
- {Out, Err, War, Defs, Mio, IfCou};
-
-expand([{file_info, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
- expand(Rem, Str++Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN);
-
-%%---------------------------------------
-%% Searching for endif,
-%% i.e skip all source lines until matching
-%% end if is encountered
-%%---------------------------------------
-expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN)
- when Command == "ifdef" ->
- {_Removed, Rem2, _Nl} = read_to_nl(Rem),
- IfCou2 = {endif, Endif+1, IfLine},
- expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err, War, L, FN);
-
-
-expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN)
- when Command == "ifndef" ->
- {_Removed, Rem2, _Nl} = read_to_nl(Rem),
- IfCou2 = {endif, Endif+1, IfLine},
- expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err, War, L, FN);
-
-
-expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN)
- when Command == "if" ->
- case pp_command(Command, Rem, Defs, IncDir, Mio, Err, War, L, FN) of
- {{'if', true}, Rem2, Err2, War2, Nl} ->
- IfCou2 = {endif, Endif+1, IfLine},
- expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN);
-%% {{'if', false}, Rem2, Err2, War2, Nl} -> Not implemented yet
- {{'if', error}, Rem2, Err2, War2, Nl} ->
- IfCou2 = {endif, Endif, IfLine},
- expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN)
- end;
-
-expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN)
- when Command == "endif" ->
- {_Removed, Rem2, Nl} = read_to_nl(Rem),
- case Endif of
- 1 ->
- Out2 = lists:duplicate(Nl,$\n) ++ Out,
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, check_all, Err, War, L+Nl, FN);
- _ ->
- IfCou2 = {endif, Endif-1, IfLine},
- expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err, War, L+Nl, FN)
- end;
-
-
-expand([{command,_Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) ->
- {_Removed, Rem2, _Nl} = read_to_nl(Rem),
- IfCou2 = {endif, Endif, IfLine},
- expand(Rem2, Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err, War, L, FN);
-
-%% Solves a bug when spaces in front of hashmark !
-expand([space | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) ->
- expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN);
-
-expand([{nl,_Nl} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) ->
- expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN);
-
-
-expand([_X | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN) ->
- {_Removed, Rem2, Nl} = read_to_nl(Rem),
- Out2 = lists:duplicate(Nl,$\n) ++ Out,
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, {endif, Endif, IfLine}, Err, War, L, FN);
-
-
-
-
-
-%%---------------------------------------
-%% Check all tokens
-%%---------------------------------------
-expand([{nl, _N} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
- expand(Rem, [$\n | Out], SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L+1, FN);
-
-expand([space | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
- expand(Rem, [?space | Out], SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN);
-
-expand([space_exp | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
- expand(Rem, [?space | Out], SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN);
-
-expand([{command,Command} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, check_all, Err, War, L, FN) ->
- case pp_command(Command, Rem, Defs, IncDir, Mio, Err, War, L, FN) of
- {define, Rem2, Defs2, Err2, War2, Nl} ->
- Out2 = lists:duplicate(Nl,$\n) ++ Out,
- expand(Rem2, Out2, SelfRef, Defs2, IncFile, IncDir, update_mio(Mio), check_all, Err2, War2, L+Nl, FN);
-
- {undef, Rem2, Defs2, Err2, War2, Nl} ->
- Out2 = lists:duplicate(Nl,$\n) ++ Out,
- expand(Rem2, Out2, SelfRef, Defs2, IncFile, IncDir, update_mio(Mio), check_all, Err2, War2, L+Nl, FN);
-
- {{include, ok}, FileName, FileCont, Rem2, Nl, Err2, War2} ->
- {Out3, Defs3, Err3, War3, Mio2} =
- run_include(FileName, FileCont, Out, Defs, Err2, War2, L+Nl, IncFile, IncDir, Mio),
- Nls = [],
- Out4 = Out3++Nls++Out,
- expand(Rem2, Out4, SelfRef, Defs3, IncFile, IncDir, Mio2, check_all, Err3, War3, L+Nl, FN);
-
- {{include, error}, Rem2, Nl, Err2, War2} ->
- Out2 = lists:duplicate(Nl,$\n) ++ Out,
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err2, War2, L+Nl, FN);
-
- {{include, skip}, Rem2} ->
- Out2 = [$\n|Out],
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err, War, L+1, FN);
-
- {{ifdef, true}, Rem2, Err2, War2, Nl} ->
- Out2 = lists:duplicate(Nl,$\n) ++ Out,
- IfCou2 = {endif, 1, L},
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN);
- {{ifdef, false}, Rem2, Err2, War2, Nl} ->
- Out2 = lists:duplicate(Nl,$\n) ++ Out,
- Mio2 = update_mio(ifdef, Mio),
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err2, War2, L+Nl, FN);
-
- {{ifndef, true}, Rem2, Err2, War2, Nl} ->
- Out2 = lists:duplicate(Nl,$\n) ++ Out,
- IfCou2 = {endif, 1, L},
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN);
- {{ifndef, false}, Macro, Rem2, Err2, War2, Nl} ->
- Out2 = lists:duplicate(Nl,$\n) ++ Out,
- Mio2 = update_mio({ifndef, Macro}, Mio),
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err2, War2, L+Nl, FN);
-
- {endif, Rem2, Err2, War2, Nl} ->
- Out2 = lists:duplicate(Nl,$\n) ++ Out,
- Mio2 = update_mio(endif, Mio),
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err2, War2, L+Nl, FN);
-
- {{'if', true}, Rem2, Err2, War2, Nl} ->
- Out2 = lists:duplicate(Nl,$\n) ++ Out,
- IfCou2 = {endif, 1, L},
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio, IfCou2, Err2, War2, L+Nl, FN);
-%% {{'if', false}, Removed, Rem2, Nl} -> Not implemented at present
- {{'if', error}, Rem2, Err2, War2, Nl} ->
- Out2 = lists:duplicate(Nl,$\n) ++ Out,
- Mio2 = update_mio('if', Mio),
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err2, War2, L+Nl, FN);
-
- {'else', {_Removed, Rem2, Nl}} ->
- Out2 = lists:duplicate(Nl,$\n) ++ Out,
- Err2 = {FN, L, "`else' command is not implemented at present"},
- Mio2 = update_mio('else', Mio),
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, [Err2|Err], War, L+Nl, FN);
-
- {'elif', {_Removed, Rem2, Nl}} ->
- Out2 = lists:duplicate(Nl,$\n) ++ Out,
- Err2 = {FN, L, "`elif' command is not implemented at present"},
- Mio2 = update_mio('elif', Mio),
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, [Err2|Err], War, L+Nl, FN);
-
- {warning, {WarningText, Rem2, Nl}} ->
- [FileName|_More] = IncFile,
- War2 = {FileName, L, "warning: #warning "++detokenise(WarningText)},
- Out2 = lists:duplicate(Nl,$\n) ++ Out,
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err, [War2|War], L+Nl, FN);
-
- {error, {ErrorText, Rem2, Nl}} ->
- [FileName|_More] = IncFile,
- Err2 = {FileName, L, detokenise(ErrorText)},
- Out2 = lists:duplicate(Nl,$\n) ++ Out,
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, [Err2|Err], War, L+Nl, FN);
-
- {{line, ok}, {_Removed, Rem2, Nl}, L2, FN2, LineText} ->
- Out2 = lists:duplicate(Nl,$\n)++LineText++Out,
- [_X|IF] = IncFile,
- IncFile2 = [FN2|IF],
- expand(Rem2, Out2, SelfRef, Defs, IncFile2, IncDir, update_mio(Mio), check_all, Err, War, L2, FN2);
- {{line, error}, {_Removed, Rem2, Nl}, Err2} ->
- Out2 = lists:duplicate(Nl,$\n) ++ Out,
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, [Err2|Err], War, L+Nl, FN);
-
- hash_mark ->
- expand(Rem, Out, SelfRef, Defs, IncFile, IncDir, Mio, check_all, Err, War, L, FN);
-
- {pragma, Rem2, Nl, Text} ->
- Out2 = lists:duplicate(Nl,$\n)++Text++Out,
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err, War, L+Nl, FN);
-
- {ident, Rem2, Nl, Text} ->
- Out2 = lists:duplicate(Nl,$\n)++Text++Out,
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, update_mio(Mio), check_all, Err, War, L+Nl, FN);
-
- {not_recognised, {Removed, Rem2, Nl}} ->
- Text = lists:reverse([$#|Command]),
- RemovedS = lists:reverse([?space|detokenise(Removed)]),
- Out2 = [$\n|RemovedS]++Text++Out,
- Mio2 = update_mio(Mio),
- case Command of
- [X|_T] when ?is_upper(X) ->
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err, War, L+Nl, FN);
- [X|_T] when ?is_lower(X) ->
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err, War, L+Nl, FN);
- [X|_T] when ?is_underline(X) ->
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, Err, War, L+Nl, FN);
- _ ->
- Err2 = {FN, L, "invalid preprocessing directive name"},
- expand(Rem2, Out2, SelfRef, Defs, IncFile, IncDir, Mio2, check_all, [Err2|Err], War, L+Nl, FN)
- end;
-
- Else ->
-% io:format(" %%%%Else%%%%%% ~p~n",[Else]),
- exit(Else)
- end;
-
-
-expand([{var, "__LINE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
- LL = io_lib:format("~p",[L]),
- expand(Rem, [LL | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-
-expand([{var, "__FILE__"}|Rem], Out, SelfRef, Defs, IncFile, Mio, IncDir, IfCou, Err, War, L, FN) ->
- expand(Rem, [$",FN,$" | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-
-expand([{var, "__DATE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
- {{Y,M,D},{_H,_Mi,_S}} = calendar:universal_time(),
- Date = io_lib:format("\"~s ~p ~p\"",[month(M),D,Y]),
- expand(Rem, [Date | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-
-expand([{var, "__TIME__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
- {{_Y,_M,_D},{H,Mi,S}} = calendar:universal_time(),
- HS = if H < 10 -> "0"++integer_to_list(H);
- true -> integer_to_list(H)
- end,
- MiS = if Mi < 10 -> "0"++integer_to_list(Mi);
- true -> integer_to_list(Mi)
- end,
- SS = if S < 10 -> "0"++integer_to_list(S);
- true -> integer_to_list(S)
- end,
- Time = io_lib:format("\"~s:~s:~s\"",[HS,MiS,SS]),
- expand(Rem, [Time | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-
-expand([{var, "__INCLUDE_LEVEL__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
- IL = io_lib:format("~p",[length(IncFile)-1]),
- expand(Rem, [IL | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-
-expand([{var, "__BASE_FILE__"}|Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
- [BF|_T] = lists:reverse(IncFile),
- expand(Rem, [$",BF,$" | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-
-expand([{var, Var} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
- {Out2, Err2, War2, Rem2, SelfRef2} =
- source_line(Var, Rem, SelfRef, Defs, Err, War, L, FN),
- expand(Rem2, [Out2 | Out], SelfRef2, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err2, War2, L, FN);
-
-expand([{char, Char} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
- expand(Rem, [Char | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-
-expand([{number, Number} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
- expand(Rem, [Number | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-
-expand([{expanded, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
- expand(Rem, [Str | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-
-expand([{self_ref, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
- SelfRef2 = lists:delete(Str,SelfRef),
- expand(Rem, Out, SelfRef2, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-
-expand([{string, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
- expand(Rem, [$", Str, $" | Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L, FN);
-
-expand([{string_part, Str} | Rem], Out, SelfRef, Defs, IncFile, IncDir, Mio, IfCou, Err, War, L, FN) ->
- {Str2, Rem2, Nl} = expand_string_part([$"|Str], Rem),
- expand(Rem2, [Str2| Out], SelfRef, Defs, IncFile, IncDir, update_mio(Mio), IfCou, Err, War, L+Nl, FN).
-
-
-
-
-
-
-
-
-%%========================================================================
-%% Expand a line starting as a partial string
-%%========================================================================
-expand_string_part(Str, File) ->
- expand_string_part(File, Str, 0).
-
-expand_string_part([{string, Str_part} | Rem], Str, Nl) ->
- {Str++Str_part++[$"], Rem, Nl};
-expand_string_part([space | Rem], Str, Nl) ->
- expand_string_part(Rem, Str, Nl);
-expand_string_part([nl| Rem], Str, Nl) ->
- expand_string_part(Rem, Str++[$\n], Nl);
-expand_string_part([{string_part, Str_part} | Rem], Str, Nl) ->
- expand_string_part(Rem, Str++Str_part, Nl).
-
-
-
-
-
-%%========================================================================
-%% Parse and integrate command line macro directives
-%% At this momment, only -D and -U are supported (gcc like)
-%%========================================================================
-
-
-%% Collect all command line macro definitions
-get_cmd_line_defs(Flags) ->
- Adjusted = parse_cmd_line(Flags,[]),
-
- {_Out, _Err, _War, Defs, _IfCou, _Mio} =
- expand(tokenise(Adjusted,""),
- [],
- [],
- [],
- [],
- [],
- #mio{},
- check_all,
- [],
- [],
- 1,
- ""),
- Defs.
-
-%% Parse command line macros
-parse_cmd_line([],Found) ->
- lists:flatten(lists:reverse(Found));
-
-parse_cmd_line([45,68|Rest],Found) ->
- {Collected,RestCmds} = collect_define(Rest,[]),
- parse_cmd_line(RestCmds,[Collected|Found]);
-
-parse_cmd_line([45,85|Rest],Found) ->
- {Collected,RestCmds} = collect_undefine(Rest,[]),
- parse_cmd_line(RestCmds,[Collected|Found]);
-
-parse_cmd_line([_|Rest],Found) ->
- parse_cmd_line(Rest,Found).
-
-
-%% Collect defines and translate them
-%% into a text format
-collect_define([],Found) ->
- { "#define "++lists:reverse(Found)++"\n", [] };
-collect_define([32|Rest],Found) ->
- { "#define "++lists:reverse(Found)++"\n", Rest };
-collect_define([61|Rest],[]) ->
- { "", Rest };
-collect_define([61|Rest],Found) ->
- collect_define(Rest,[32|Found]);
-collect_define([C|Rest],Found) ->
- collect_define(Rest,[C|Found]).
-
-
-%% Collect undefines and translate them
-%% into a text format
-collect_undefine([],Found) ->
- { "#undef "++lists:reverse(Found)++"\n", [] };
-collect_undefine([32|Rest],Found) ->
- { "#undef "++lists:reverse(Found)++"\n", Rest };
-collect_undefine([C|Rest],Found) ->
- collect_undefine(Rest,[C|Found]).
-
-
-
-
-
-
-
-
-
-
-
-
-%%======================================================================================
-%%======================================================================================
-%%======================================================================================
-%% Read a preprocessor command
-%%
-%%
-%% Output: Depending of the command, typically = {Command, Rem, Err, War, Nl}
-%%
-%%======================================================================================
-%%======================================================================================
-%%======================================================================================
-
-pp_command(Command, [space|File], Defs, IncDir, Mio, Err, War, L, FN) ->
- pp_command(Command, File, Defs, IncDir, Mio, Err, War, L, FN);
-
-pp_command(Command, File, Defs, IncDir, Mio, Err, War, L, FN) ->
-
- case Command of
- %%----------------------------------------
- %% #define
- %%----------------------------------------
- "define" ->
- case define(File, Err, War, L, FN) of
- {error, Rem, Err2, War2, Nl} ->
- {define, Rem, Defs, Err2, War2, Nl};
- {warning, Rem, Name, No_of_para, Parameters, Macro, Err2, War2, Nl} ->
- case is_define_ok(Name, No_of_para, Parameters, Macro, Defs) of
- {yes, Defs2} ->
- {define, Rem, Defs2, Err2, War2, Nl};
- {no, Defs2} ->
- Text = lists:flatten(io_lib:format("`~s' redefined",[Name])),
- {define, Rem, Defs2, Err2, [{FN, L, Text}|War2], Nl};
- {error, Text, Defs2} ->
- {define, Rem, Defs2, [{FN, L, Text}|Err2], War2, Nl}
- end;
- {ok, Rem, Name, No_of_para, Parameters, Macro, Err2, War2, Nl} ->
- case is_define_ok(Name, No_of_para, Parameters, Macro, Defs) of
- {yes, Defs2} ->
- {define, Rem, Defs2, Err2, War2, Nl};
- {no, Defs2} ->
- Text = lists:flatten(io_lib:format("`~s' redefined",[Name])),
- {define, Rem, Defs2, Err2, [{FN, L, Text}|War2], Nl};
- {error, Text, Defs2} ->
- {define, Rem, Defs2, [{FN, L, Text}|Err2], War2, Nl}
- end
- end;
-
- %%----------------------------------------
- %% #undef
- %%----------------------------------------
- "undef" ->
- case undef(File, Err, War, L, FN) of
- {error, Rem, Err2, War2, Nl} ->
- {undef, Rem, Defs, Err2, War2, Nl};
- {ok, Rem, Name, Err2, War2, Nl} ->
- Defs2 = lists:keydelete(Name, 1, Defs),
- {undef, Rem, Defs2, Err2, War2, Nl}
- end;
-
- %%----------------------------------------
- %% #include
- %%----------------------------------------
- "include" ->
- case include(File, IncDir, Mio) of
- {error, Rem, Nl, Err2} ->
- {{include, error}, Rem, Nl, [{FN, L, Err2}|Err], War};
- {error, Rem, Nl, Err2, NameNl} ->
- {{include, error}, Rem, Nl, [{FN, L+ NameNl, Err2}|Err], War};
- {ok, FileNamePath, FileCont, Rem, Nl} ->
- {{include, ok}, FileNamePath, FileCont, Rem, Nl, Err, War};
- {skip, Rem} ->
- {{include, skip}, Rem}
- end;
-
- %%----------------------------------------
- %% #ifdef
- %%----------------------------------------
- "ifdef" ->
- case define(File, Err, War, L, FN) of
- {error, Rem, Err2, War2, Nl} ->
- {{ifdef, false}, Rem, Defs, Err2, War2, Nl};
- {warning, Rem, Name, No_of_para, _Parameters, _Macro, Err2, War2, Nl} ->
- case is_defined_before(Name, No_of_para, Defs) of
- yes ->
- {{ifdef, false}, Rem, Err2, War2, Nl};
- no ->
- {{ifdef, true}, Rem, Err2, War2, Nl}
- end;
- {ok, Rem, Name, No_of_para, _Parameters, _Macro, Err2, War2, Nl} ->
- case is_defined_before(Name, No_of_para, Defs) of
- yes ->
- {{ifdef, false}, Rem, Err2, War2, Nl};
- no ->
- {{ifdef, true}, Rem, Err2, War2, Nl}
- end
- end;
-
-
-
- %%----------------------------------------
- %% #ifndef
- %%----------------------------------------
- "ifndef" ->
- case define(File, Err, War, L, FN) of
- {error, Rem, Err2, War2, Nl} ->
- {{ifndef, false}, Rem, Defs, Err2, War2, Nl};
- {warning, Rem, Name, No_of_para, _Parameters, _Macro, Err2, War2, Nl} ->
- case is_defined_before(Name, No_of_para, Defs) of
- yes ->
- {{ifndef, true}, Rem, Err2, War2, Nl};
- no ->
- {{ifndef, false}, Name, Rem, Err2, War2, Nl}
- end;
- {ok, Rem, Name, No_of_para, _Parameters, _Macro, Err2, War2, Nl} ->
- case is_defined_before(Name, No_of_para, Defs) of
- yes ->
- {{ifndef, true}, Rem, Err2, War2, Nl};
- no ->
- {{ifndef, false}, Name, Rem, Err2, War2, Nl}
- end
- end;
-
-
- %%----------------------------------------
- %% #endif
- %%----------------------------------------
- "endif" ->
- {Removed, Rem, Nl} = read_to_nl(File),
- case Removed of
- [] ->
- {endif, Rem, Err, War, 1};
- _ ->
- Text = "ignoring the tail of the line",
- {ok, Rem, Err, [{FN, L, Text}|War], Nl}
- end;
-
-
- %%----------------------------------------
- %% #if
- %%----------------------------------------
- "if" ->
- case if_zero(File, Err, War, L, FN) of
- {error, Rem2, _Removed, Nl} ->
- Err2 = {FN, L, "only '#if 0' is implemented at present"},
- {{'if', error}, Rem2, [Err2 | Err], War, Nl};
- {ok, Rem2, 0, _Removed, Nl} ->
- {{'if', true}, Rem2, Err, War, Nl};
- {ok, Rem2, _Num, _Removed, Nl} ->
- Err2 = {FN, L, "only '#if 0' is implemented at present"},
- {{'if', error}, Rem2, [Err2 | Err], War, Nl}
- end;
-
- %%----------------------------------------
- %% #else
- %%----------------------------------------
- "else" ->
- {'else', read_to_nl(File)};
-
- %%----------------------------------------
- %% #elif
- %%----------------------------------------
- "elif" ->
- {'elif', read_to_nl(File)};
-
- %%----------------------------------------
- %% #pragma
- %%----------------------------------------
- "pragma" ->
- {Removed, Rem, Nl} = read_to_nl(File),
- {pragma, Rem, Nl, lists:reverse("#pragma " ++ detokenise_pragma(Removed))};
-
- %%----------------------------------------
- %% #ident
- %%----------------------------------------
- "ident" ->
- {Removed, Rem, Nl} = read_to_nl(File),
- {ident, Rem, Nl, lists:reverse("#ident " ++ detokenise_pragma(Removed))};
-
- %%----------------------------------------
- %% #warning
- %%----------------------------------------
- "warning" ->
- {warning, read_to_nl(File)};
-
- %%----------------------------------------
- %% #error
- %%----------------------------------------
- "error" ->
- {error, read_to_nl(File)};
-
- %%----------------------------------------
- %% #line
- %%----------------------------------------
- "line" ->
- line(File, L, FN);
-
- %%----------------------------------------
- %% #
- %%----------------------------------------
- "null" ->
- hash_mark;
-
- %%----------------------------------------
- %% not recognised preprocessor commands
- %%----------------------------------------
- _Else ->
- {not_recognised, read_to_nl(File)}
- end.
-
-
-
-
-%%===============================================================
-%%===============================================================
-%%===============================================================
-%% if
-%%
-%% Only #if 0 is implemented at the time to be able to use if
-%% to comment some code parts.
-%%===============================================================
-%%===============================================================
-%%===============================================================
-
-if_zero(File, _Err, _War, _L, _FN) ->
- case if_zero(File) of
- {ok, Remain, Num, Removed, Nl} ->
- case catch list_to_integer(Num) of
- {'EXIT', _} ->
- {Removed2, Rem2, Nl2} = read_to_nl(File),
- {error, Rem2, Removed2, Nl2};
- Int ->
- {ok, Remain, Int, Removed, Nl}
- end;
- E ->
- E
- end.
-
-if_zero([{number,Num}]) ->
- {ok, [], Num, [], 0};
-if_zero([{number,Num}, space]) ->
- {ok, [], Num, [], 0};
-if_zero([{number,Num} | Rem]) ->
- {Removed, Rem2, Nl} = read_to_nl(Rem),
- {ok, Rem2, Num, Removed, Nl};
-%if_zero([{number,Num}, {nl,_X} | Rem]) ->
-% {ok, Rem, Num, [], 1};
-if_zero(Rem) ->
- {Removed, Rem2, Nl} = read_to_nl(Rem),
- {error, Rem2, Removed, Nl}.
-
-
-
-%%===============================================================
-%%===============================================================
-%%===============================================================
-%% Define macro
-%%
-%% Check the syntax of the macro, extract the parameters if any.
-%% If valid macro it is added to the Defs-list.
-%% If a macro is redefined, a warning will be given, the latest
-%% definition is always the valid one.
-%%===============================================================
-%%===============================================================
-%%===============================================================
-
-define(File, Err, War, L, FN) ->
- case define_name(File) of
- {ok, Rem, Name, No_of_para, Parameters, Macro, Nl} ->
- {ok, Rem, Name, No_of_para, Parameters, Macro, Err, War, Nl};
- {{warning,no_space}, Rem, Name, No_of_para, Parameters, Macro, Nl} ->
- Text = lists:flatten(io_lib:format("missing white space after `#define ~s'",[Name])),
- {warning, Rem, Name, No_of_para, Parameters, Macro, Err, [{FN, L, Text}|War], Nl};
- {error, invalid_name, Nl} ->
- Text = "invalid macro name",
- {_Removed, Rem, Nl2} = read_to_nl(File),
- {error, Rem, [{FN, L, Text}|Err], War, Nl+Nl2};
- {error, invalid_name, Name, Nl} ->
- Text = lists:flatten(io_lib:format("invalid macro name `~s'",[Name])),
- {_Removed, Rem, Nl2} = read_to_nl(File),
- {error, Rem, [{FN, L, Text}|Err], War, Nl+Nl2};
- {error, illegal_arg} ->
- {Removed, Rem, Nl} = read_to_nl(File),
- RemovedS = detokenise(Removed),
- Text = lists:flatten(io_lib:format("Invalid argument list ~s",[RemovedS])),
- {error, Rem, [{FN, L, Text}|Err], War, Nl}
- end.
-
-
-
-%%===========================================================
-%% Check if valid macro
-%%===========================================================
-define_name([]) ->
- {warning, no_macro};
-define_name([space]) ->
- {warning, no_macro};
-%% Macro with parameters
-define_name([{var,Name},{char,$(}|Rem]) ->
- case read_para([{char,$(}|Rem]) of
- {ok, Rem2, Para, NoOfPara} ->
- {Removed, Rem3, _Nl} = read_to_nl(Rem2),
- {ok, Rem3, Name, NoOfPara, Para, Removed, 1};
- Error ->
- Error
- end;
-%% Macro without parameters
-define_name([{var,Name}]) ->
- {ok, [], Name, 0, [], [], 0};
-define_name([{var,Name}, space | Rem]) ->
- {Removed, Rem2, Nl} = read_to_nl(Rem),
- {ok, Rem2, Name, 0, [], Removed, Nl};
-define_name([{var,Name}, {nl,_X} | Rem]) ->
- {ok, Rem, Name, 0, [], [], 1};
-define_name([{var,Name} | Rem]) ->
- {Removed, Rem2, Nl} = read_to_nl(Rem),
- {{warning,no_space}, Rem2, Name, 0, [], Removed, Nl};
-%% Invalid macro name
-define_name([{number, Name} | _Rem]) ->
- {error, invalid_name, Name, 0};
-define_name(_Rem) ->
- {error, invalid_name, 0}.
-
-
-
-
-
-
-
-%%===============================================================
-%%===============================================================
-%%===============================================================
-%% Undefine macro
-%%
-%% If it is a valid undef command the macro name will be deleted
-%% from the Defs-list
-%%===============================================================
-%%===============================================================
-%%===============================================================
-
-undef(File, Err, War, L, FN) ->
- case undef(File) of
- {ok, Rem, Name, Nl} ->
- {ok, Rem, Name, Err, War, Nl};
- {warning, Rem, Name, Nl} ->
- Text = "ignoring the tail of the line",
- {ok, Rem, Name, Err, [{FN, L, Text}|War], Nl};
- {error, invalid_name} ->
- Text = "invalid macro name",
- {_Removed, Rem, Nl} = read_to_nl(File),
- {error, Rem, [{FN, L, Text}|Err], War, Nl};
- {error, invalid_name, Name} ->
- Text = lists:flatten(io_lib:format("invalid macro name `~s'",[Name])),
- {_Removed, Rem, Nl} = read_to_nl(File),
- {error, Rem, [{FN, L, Text}|Err], War, Nl}
- end.
-
-%%-------------------------------------------------
-%% Check if valid macro name
-%%-------------------------------------------------
-undef([]) ->
- {error, invalid_name, []};
-%% Valid name
-undef([{var,Name}]) ->
- {ok, [], Name, 0};
-undef([{var,Name}, {nl,_X} | Rem]) ->
- {ok, Rem, Name, 1};
-undef([{var,Name}, space, {nl,_X} | Rem]) ->
- {ok, Rem, Name, 1};
-undef([{var,Name} | Rem]) ->
- {_Removed, Rem2, Nl} = read_to_nl(Rem),
- {warning, Rem2, Name, Nl};
-%% Invalid macro name
-undef([{number, Name} | _Rem]) ->
- {error, invalid_name, Name};
-undef(_Rem) ->
- {error, invalid_name}.
-
-
-
-
-
-
-%%===============================================================
-%%===============================================================
-%%===============================================================
-%% Include macro
-%%
-%% Read the included file
-%%===============================================================
-%%===============================================================
-%%===============================================================
-
-include(File, IncDir, Mio) ->
- case include2(File) of
- {ok, FileName, Rem, Nl, FileType} ->
- Result = read_inc_file(FileName, IncDir, Mio),
- case {Result, Nl, FileType} of
- {{ok, FileNamePath, FileCont}, _, _} ->
- {ok, FileNamePath, FileCont, Rem, Nl};
- {skip, _, _} ->
- {skip, Rem};
- {{error, Text}, _, own_file} ->
- NameNl = count_nl(FileName,0),
- Error = lists:flatten(io_lib:format("~s: ~s",[FileName,Text])),
- {error, Rem, Nl, Error, NameNl};
- {{error, Text}, 1, sys_file} ->
- NameNl = count_nl(FileName,0),
- Error = lists:flatten(io_lib:format("~s: ~s",[FileName,Text])),
- {error, Rem, Nl, Error, NameNl};
- {{error, _Text}, _, sys_file} ->
- {error, Rem, Nl, "`#include' expects \"FILENAME\" or <FILENAME>"}
- end;
- {error, {_Removed, Rem, Nl}} ->
- {error, Rem, Nl, "`#include' expects \#FILENAME\" or <FILENAME>"}
- end.
-
-
-
-count_nl([],Nl) ->
- Nl;
-count_nl([$\n|T],Nl) ->
- count_nl(T,Nl+1);
-count_nl([_H|T],Nl) ->
- count_nl(T,Nl).
-
-%%=================================================
-%% Extract the file name from the token list
-%%=================================================
-include2([space|Rem]) ->
- include2(Rem);
-
-include2([{string, FileName}]) ->
- {ok, FileName, [], 1, own_file};
-include2([{string, FileName}, space]) ->
- {ok, FileName, [], 1, own_file};
-include2([{string, FileName}, {nl, _X} | Rem]) ->
- {ok, FileName, Rem, 1, own_file};
-include2([{string, FileName}, space, {nl, _X} | Rem]) ->
- {ok, FileName, Rem, 1, own_file};
-include2([{string, _FileName}, _No_nl | Rem]) ->
- {error, read_to_nl(Rem)};
-include2([{string_part, File_part}, {nl, _X} | Rem]) ->
- case include_read_string_file_name(File_part++[$\n], Rem, 1) of
- {ok, FileName, Rem2, Nl} ->
- {ok, FileName, Rem2, Nl, own_file};
- error ->
- {error, read_to_nl([{string_part,File_part} | Rem])}
- end;
-include2([{sys_head, FileName}]) ->
- {ok, FileName, [], 1, sys_file};
-include2([{sys_head, FileName}, space]) ->
- {ok, FileName, [], 1, sys_file};
-include2([{sys_head, FileName}, {nl, _X} | Rem]) ->
- {ok, FileName, Rem, 1, sys_file};
-include2([{sys_head, FileName}, space, {nl, _X} | Rem]) ->
- {ok, FileName, Rem, 1, sys_file};
-include2([{sys_head, _FileName}, _No_nl | Rem]) ->
- {error, read_to_nl(Rem)};
-include2([{sys_head_part ,File_part}, {nl, _X} | Rem]) ->
- case include_read_sys_file_name(File_part++[$\n], Rem, 1) of
- {ok, FileName, Rem2, Nl} ->
- {ok, FileName, Rem2, Nl, sys_file};
- error ->
- {error, read_to_nl([{sys_head_part, File_part} | Rem])}
- end;
-include2(Rem) ->
- {error, read_to_nl(Rem)}.
-
-
-
-%%-------------------------------------------------
-%% File name framed by " "
-%%-------------------------------------------------
-include_read_string_file_name(File, [{string, File_part}, {nl,_X} | Rem], Nl) ->
- {ok, File++File_part, Rem, Nl+1};
-include_read_string_file_name(File, [{string_part, File_part}, {nl,_X} | Rem], Nl) ->
- include_read_string_file_name(File++File_part++[$\n], Rem, Nl+1);
-include_read_string_file_name(_File, _X, _Nl) ->
- error.
-
-%%-------------------------------------------------
-%% File name framed by < >
-%%-------------------------------------------------
-include_read_sys_file_name(File, [{sys_head, File_part}, {nl,_X} | Rem], Nl) ->
- {ok, File++File_part, Rem, Nl+1};
-include_read_sys_file_name(File, [{sys_head_part, File_part}, {nl,_X} | Rem], Nl) ->
- include_read_sys_file_name(File++File_part++[$\n], Rem, Nl+1);
-include_read_sys_file_name(_File, _X, _Nl) ->
- error.
-
-
-
-
-
-
-
-%%===============================================================
-%%===============================================================
-%%===============================================================
-%% Line macro
-%%
-%% The line macro may redefine both the current line number and
-%% the current file name: #line ' new_line_nr' 'new_file_name'
-%%===============================================================
-%%===============================================================
-%%===============================================================
-
-line(File, L, FN) ->
- line(File, L, FN, not_defined, not_defined).
-
-
-
-line([], L, FN, _Line, _File) ->
- {{line, error}, {[],[],0}, {FN,L,"invalid format `#line' directive"}};
-
-line([space|Rem], L, FN, Line, File) ->
- line(Rem, L, FN, Line, File);
-
-%%------------------------------
-%% Line number expected
-%%------------------------------
-line([{number,Number}|Rem], L, FN, not_defined, File) ->
- case catch list_to_integer(Number) of
- {'EXIT', _} ->
- {{line, error}, read_to_nl(Rem), {FN,L,"invalid format `#line' directive"}};
- Int ->
- line(Rem, L, FN, Int, File)
- end;
-line(Rem, L, FN, not_defined, _File) ->
- {{line, error}, read_to_nl(Rem), {FN,L,"invalid format `#line' directive"}};
-
-%%------------------------------
-%% File name or newline expected
-%%------------------------------
-line([{nl, _NL}|Rem], _L, FN, Line, not_defined) ->
- {{line, ok}, {[],Rem,1}, Line, FN, io_lib:format("~n~p ~p #",[FN, Line-1])};
-line([{string,NewFN}|Rem], _L, _FN, Line, not_defined) ->
- {{line, ok}, read_to_nl(Rem), Line, NewFN, io_lib:format("~n~p ~p #",[NewFN, Line-1])};
-line(Rem, L, FN, _Line, _File) ->
- {{line, error}, read_to_nl(Rem), {FN,L,"invalid format `#line' directive"}}.
-
-
-
-
-%%======================================================================================
-%%======================================================================================
-%%======================================================================================
-%% Source line
-%%
-%%
-%% Output: {Str, Err, War, Rem, SelfRef}
-%%
-%% Description: The input source line is searched for macros. If a macro is found it
-%% is expanded. The result of an expansion is rescanned for more macros.
-%% To prevent infinite loops if the macro is self referring
-%% an extra token is put into the Rem list. The variable SelfRef
-%% contains all the macros which are inhibited to be expanded.
-%% A special specae token is also inserted to prevent not wanted
-%% concatinations if one of the variables to be concatinated is expanded.
-%%======================================================================================
-%%======================================================================================
-%%======================================================================================
-
-source_line(Str, Rem, SelfRef, Defs, Err, War, L, FN) ->
- {Rem2, Para, No_of_para} = case read_para(Rem) of
- {ok, RemT, ParaT, No_of_paraT} ->
- {RemT, ParaT, No_of_paraT};
- {error, illegal_arg} ->
- {[], [], 0}
- end,
-
-
- %%-------------------------------------------------
- %% Check if a valid macro
- %%-------------------------------------------------
- case lists:keysearch(Str, 1, Defs) of
- %% a macro without parameters
- {value, {Str, 0, _MacroPara, Macro}} ->
- case lists:member(Str, SelfRef) of
- true ->
- {[Str], Err, War, Rem, SelfRef};
- false ->
- ExpandedRes2 = sl_mark_expanded(Macro, Str),
- {[], Err, War, ExpandedRes2 ++ [{self_ref,Str}|Rem], [Str|SelfRef]}
- end;
-
- %% a macro with parameters
- {value, {Str, N, _MacroPara, Macro}} when N == No_of_para ->
- case lists:member(Str, SelfRef) of
- true ->
- {[Str], Err, War, Rem, SelfRef};
- false ->
- ExpandedRes = sl_macro_expand(Macro, Para, Defs),
- ExpandedRes2 = sl_mark_expanded(ExpandedRes, Str),
- {[], Err, War, ExpandedRes2 ++ [{self_ref,Str}|Rem2], [Str|SelfRef]}
- end;
-
- %% a variable, because it doesn't have any parameters
- {value, {Str, _N, _MacroPara, _Macro}} when No_of_para == 0 ->
- {Str, Err, War, Rem, SelfRef};
-
- %% illegal no of parameters
- {value, {Str, N, _MacroPara, _Macro}} when No_of_para < N ->
- Text = io_lib:format(" macro `~s' used with just ~p arg",[Str,No_of_para]),
- Err2 = {FN, L, lists:flatten(Text)},
- {Str, [Err2|Err], War, Rem, SelfRef};
- {value, {Str, _N, _MacroPara, _Macro}} ->
- Text = io_lib:format(" macro `~s' used with too many (~p) args",[Str,No_of_para]),
- Err2 = {FN, L, lists:flatten(Text)},
- {Str, [Err2|Err], War, Rem, SelfRef};
-
- %% no macro
- false ->
- {Str, Err, War, Rem, SelfRef}
- end.
-
-
-
-
-
-%%=================================================
-%% Expand a macro
-%%=================================================
-sl_macro_expand(Macro, Para, Defs) ->
- sl_macro_expand(Macro, Para, Defs, []).
-
-
-%%...................
-%% End
-%%...................
-sl_macro_expand([], _Para, _Defs, Res) ->
- lists:reverse(Res);
-
-%%...................
-%% Concatination
-%%...................
-%% para ## para
-sl_macro_expand([{para, N}, space, {char,$#}, {char,$#}, space, {para,M} | T], Para, Defs, Res) ->
- Exp = sl_para_para({para, N},{para, M}, Para),
- sl_macro_expand(Exp++T, Para, Defs, [space |Res]);
-%% para## para
-sl_macro_expand([{para, N}, {char,$#}, {char,$#}, space, {para,M} | T], Para, Defs, Res) ->
- Exp = sl_para_para({para, N},{para, M}, Para),
- sl_macro_expand(Exp++T, Para, Defs, [space |Res]);
-%% para ##para
-sl_macro_expand([{para, N}, space, {char,$#}, {char,$#}, {para,M} | T], Para, Defs, Res) ->
- Exp = sl_para_para({para, N},{para, M}, Para),
- sl_macro_expand(Exp++T, Para, Defs, [space |Res]);
-%% para##para
-sl_macro_expand([{para, N}, {char,$#}, {char,$#}, {para,M} | T], Para, Defs, Res) ->
- Exp = sl_para_para({para, N},{para, M}, Para),
- sl_macro_expand(Exp++T, Para, Defs, [space |Res]);
-
-%% para ## var
-sl_macro_expand([{para, N}, space, {char,$#}, {char,$#}, space, {var, Var}|T], Para, Defs, Res) ->
- Exp = sl_para_var({para, N}, {var, Var}, Para),
- sl_macro_expand(Exp++T, Para, Defs, [space |Res]);
-%% para## var
-sl_macro_expand([{para, N}, {char,$#}, {char,$#}, space, {var, Var} | T], Para, Defs, Res) ->
- [{var, VarN}] = lists:nth(N,Para),
- sl_macro_expand(T, Para, Defs, [{expanded,Var},{expanded,VarN}, space |Res]);
-%% para ##var
-sl_macro_expand([{para, N}, space, {char,$#}, {char,$#}, {var, Var} | T], Para, Defs, Res) ->
- [{var, VarN}] = lists:nth(N,Para),
- sl_macro_expand(T, Para, Defs, [{expanded,Var},{expanded,VarN}, space |Res]);
-%% para##var
-sl_macro_expand([{para, N}, {char,$#}, {char,$#}, {var, Var} | T], Para, Defs, Res) ->
- [{var, VarN}] = lists:nth(N,Para),
- sl_macro_expand(T, Para, Defs, [{expanded,Var},{expanded,VarN}, space |Res]);
-
-%% var ## para
-sl_macro_expand([{var, Var}, space, {char,$#}, {char,$#}, space, {para,M} | T], Para, Defs, Res) ->
- Exp = sl_var_para({var, Var},{para, M}, Para),
- sl_macro_expand(Exp++T, Para, Defs, [space |Res]);
-%% var## para
-sl_macro_expand([{var, Var}, {char,$#}, {char,$#}, space, {para,M} | T], Para, Defs, Res) ->
- Exp = sl_var_para({var, Var},{para, M}, Para),
- sl_macro_expand(Exp++T, Para, Defs, [space |Res]);
-%% var ##para
-sl_macro_expand([{var, Var}, space, {char,$#}, {char,$#}, {para,M} | T], Para, Defs, Res) ->
- Exp = sl_var_para({var, Var},{para, M}, Para),
- sl_macro_expand(Exp++T, Para, Defs, [space |Res]);
-%% var##para
-sl_macro_expand([{var, Var}, {char,$#}, {char,$#}, {para,M} | T], Para, Defs, Res) ->
- Exp = sl_var_para({var, Var},{para, M}, Para),
- sl_macro_expand(Exp++T, Para, Defs, [space |Res]);
-
-%% expanded ## para
-sl_macro_expand([space, {char,$#}, {char,$#}, space, {para,M} | T], Para, Defs, [{expanded, Var}|Res]) ->
- [{var, VarM}] = lists:nth(M,Para),
- sl_macro_expand(T, Para, Defs, [{expanded,VarM},{expanded,Var} |Res]);
-%% expanded## para
-sl_macro_expand([{char,$#}, {char,$#}, space, {para,M} | T], Para, Defs, [{expanded, Var}|Res]) ->
- [{var, VarM}] = lists:nth(M,Para),
- sl_macro_expand(T, Para, Defs, [{expanded,VarM},{expanded,Var} |Res]);
-%% expanded ##para
-sl_macro_expand([space, {char,$#}, {char,$#}, {para,M} | T], Para, Defs, [{expanded, Var}|Res]) ->
- [{var, VarM}] = lists:nth(M,Para),
- sl_macro_expand(T, Para, Defs, [{expanded,VarM},{expanded,Var} |Res]);
-%% expanded##para
-sl_macro_expand([{char,$#}, {char,$#}, {para,M} | T], Para, Defs, [{expanded, Var}|Res]) ->
- [{var, VarM}] = lists:nth(M,Para),
- sl_macro_expand(T, Para, Defs, [{expanded,VarM},{expanded,Var} |Res]);
-
-%% para ## ?
-sl_macro_expand([{para, N}, space, {char,$#}, {char,$#}, space, X | T], Para, Defs, Res) ->
- Reexp = sl_macro_reexpand(lists:nth(N,Para), Defs, []),
- sl_macro_expand([X, space|T], Para, Defs, lists:flatten([Reexp, space|Res]));
-%% para## ?
-sl_macro_expand([{para, N}, {char,$#}, {char,$#}, space, X | T], Para, Defs, Res) ->
- Reexp = sl_macro_reexpand(lists:nth(N,Para), Defs, []),
- sl_macro_expand([X, space|T], Para, Defs, lists:flatten([Reexp, space|Res]));
-%% para ##?
-sl_macro_expand([{para, N}, space, {char,$#}, {char,$#}, X | T], Para, Defs, Res) ->
- Reexp = sl_macro_reexpand(lists:nth(N,Para), Defs, []),
- sl_macro_expand([X, space|T], Para, Defs, lists:flatten([Reexp, space|Res]));
-%% para##?
-sl_macro_expand([{para, N}, {char,$#}, {char,$#}, X | T], Para, Defs, Res) ->
- Reexp = sl_macro_reexpand(lists:nth(N,Para), Defs, []),
- sl_macro_expand([X, space|T], Para, Defs, lists:flatten([Reexp, space|Res]));
-
-sl_macro_expand([{char,$#}, {char,$#}, space |T], Para, Defs, [space|Res]) ->
- sl_macro_expand(T, Para, Defs, Res);
-sl_macro_expand([{char,$#}, {char,$#} |T], Para, Defs, [space|Res]) ->
- sl_macro_expand(T, Para, Defs, Res);
-sl_macro_expand([{char,$#}, {char,$#}, space |T], Para, Defs, Res) ->
- sl_macro_expand(T, Para, Defs, Res);
-sl_macro_expand([{char,$#}, {char,$#} |T], Para, Defs, Res) ->
- sl_macro_expand(T, Para, Defs, Res);
-
-%%...................
-%% Stringification
-%%...................
-sl_macro_expand([{char,$#}, {para, N}|T], Para, Defs, Res) ->
- Nth = lists:nth(N,Para),
- Tokens = detokenise(Nth),
- sl_macro_expand(T, Para, Defs, [{string,Tokens}|Res]);
-sl_macro_expand([{char,$#}, space, {para, N}|T], Para, Defs, Res) ->
- Nth = lists:nth(N,Para),
- Tokens = detokenise(Nth),
- sl_macro_expand(T, Para, Defs, [{string,Tokens}|Res]);
-
-%%...................
-%% A parameter
-%%...................
-sl_macro_expand([{para, N}|T], Para, Defs, Res) ->
- Reexp = sl_macro_reexpand(lists:nth(N,Para), Defs, []),
- sl_macro_expand(T, Para, Defs, lists:flatten([Reexp|Res]));
-
-%%...................
-%% No parameter
-%%...................
-sl_macro_expand([H|T], Para, Defs, Res) ->
- sl_macro_expand(T, Para, Defs, [H|Res]).
-
-
-
-%%-------------------------------------------------
-%% Expand parameters
-%%-------------------------------------------------
-sl_para_para({para, N}, {para, M}, Para) ->
- case sl_para_1st(lists:nth(N,Para)) of
- {ok, Para1st} ->
- Para1st ++ sl_para_2nd(lists:nth(M,Para));
- {exp, Para1st} ->
- Para1st ++ sl_para_2nd(lists:nth(M,Para)) ++ [space_exp];
- {space, Para1st} ->
- Para1st ++ [space_exp | sl_para_2nd(lists:nth(M,Para))]
- end.
-
-
-sl_var_para(Var, {para, M}, Para) ->
- [Var|sl_para_2nd(lists:nth(M,Para))].
-
-
-sl_para_var({para, N}, Var, Para) ->
- case sl_para_1st(lists:nth(N,Para)) of
- {ok, Para1st} ->
- Para1st ++ [Var];
- {exp, Para1st} ->
- Para1st ++ [Var | space_exp];
- {space, Para1st} ->
- Para1st ++ [space_exp | Var]
- end.
-
-
-sl_para_1st([{var, Var}]) ->
- {ok,[{expanded,Var}]};
-sl_para_1st([{var, Var}, space]) ->
- {ok,[{expanded,Var}]};
-sl_para_1st([{var, Var}, space_exp]) ->
- {exp, [{expanded,Var}]};
-sl_para_1st(L) ->
- {space, L}.
-
-sl_para_2nd([{var, Var}]) ->
- [{expanded,Var}];
-sl_para_2nd([{var, Var}, space_exp]) ->
- [{expanded,Var}];
-sl_para_2nd([space, {var, Var}]) ->
- [{expanded,Var}];
-sl_para_2nd([space_exp, {var, Var}]) ->
- [{expanded,Var}];
-sl_para_2nd(L) ->
- L++[space].
-
-
-
-%%-------------------------------------------------
-%% Check if the expansion is a valid macro,
-%% do not reexpand if concatination
-%%-------------------------------------------------
-sl_macro_reexpand([], _Defs, Result) ->
- Result;
-sl_macro_reexpand([{var,Var}|Rem], Defs, Result) ->
- case lists:keysearch(Var, 1, Defs) of
- {value, {Var, 0, _MacroPara, Macro}} ->
- Rem2 = case Rem of
- [space | RemT] ->
- [space_exp | RemT];
- _ ->
- [space_exp | Rem]
- end,
- sl_macro_reexpand(Macro++Rem2, Defs, Result);
- _ ->
- sl_macro_reexpand(Rem, Defs, [{var,Var}|Result])
- end;
-sl_macro_reexpand([H|Rem], Defs, Result) ->
- sl_macro_reexpand(Rem, Defs, [H|Result]).
-
-
-
-%%-------------------------------------------------
-%% Self referring macros are marked not be reexpanded
-%%-------------------------------------------------
-sl_mark_expanded(QQ, Str) ->
- sl_mark_expanded(QQ, Str, []).
-
-sl_mark_expanded([], _Str, Res) ->
- lists:reverse(Res);
-sl_mark_expanded([H|T], Str, Res) ->
- case H of
- {_,Str} ->
- sl_mark_expanded(T, Str, [{expanded, Str}|Res]);
- _ ->
- sl_mark_expanded(T, Str, [H|Res])
- end.
-
-
-
-
-
-
-
-
-
-%%======================================================================================
-%%======================================================================================
-%%======================================================================================
-%% Misceleaneous functions
-%%======================================================================================
-%%======================================================================================
-%%======================================================================================
-
-
-%%===============================================================
-%% Check the Flags for include directories
-%%===============================================================
-include_dir(Flags) when is_list(Flags)->
- include_dir(Flags,[]);
-include_dir(_Flags) ->
- [].
-
-include_dir(Flags,IncDirs) ->
- case string:str(Flags,"-I") of
- 0 ->
- lists:reverse(IncDirs);
- X ->
- {NewDir, RemainingFlags} =
- gobble_inc_dir(string:sub_string(Flags, X+2),nq,[]),
- include_dir(RemainingFlags, [NewDir|IncDirs])
- end.
-
-% nq = not-quoted, q = quoted.
-% Possible strange scenarios:
-% /usr/test\ ing/
-% "/usr/test ing/"
-% /usr/test\"ing/
-% "/usr/test\"ing/"
-gobble_inc_dir([],nq,Acc) ->
- % Only accept nq here, if we end up here in q mode the user has missed a "
- {lists:reverse(Acc),[]};
-gobble_inc_dir([$\\,$"|R],Q,Acc) ->
- gobble_inc_dir(R,Q,[$"|Acc]);
-gobble_inc_dir([$"|R],nq,Acc) ->
- gobble_inc_dir(R,q,Acc);
-gobble_inc_dir([$"|R],q,Acc) ->
- gobble_inc_dir(R,nq,Acc);
-gobble_inc_dir([$\\,$ |R],nq,Acc) ->
- gobble_inc_dir(R,nq,[$ |Acc]);
-gobble_inc_dir([$ |R],nq,Acc) ->
- {lists:reverse(Acc),R};
-gobble_inc_dir([C|R],Q,Acc) ->
- gobble_inc_dir(R,Q,[C|Acc]).
-
-
-%%===============================================================
-%% Read a included file. Try current dir first then the IncDir list
-%%===============================================================
-
-read_inc_file(FileName, IncDir, Mio) ->
- case find_inc_file(FileName, IncDir) of
- {ok, AbsFile} ->
- %% is included before?
- case lists:member(FileName, Mio#mio.included) of
- false ->
- case catch file:read_file(AbsFile) of
- {ok, Bin} ->
- FileList = binary_to_list(Bin),
- {ok, AbsFile, FileList};
- {error, Text} ->
- {error, Text}
- end;
- true ->
- skip
- end;
- {error, Text} ->
- {error, Text}
- end.
-
-find_inc_file(FileName, IncDir) ->
- case catch file:read_file_info(FileName) of
- {ok, _} ->
- {ok, FileName};
- {error, _} ->
- find_inc_file2(FileName, IncDir)
- end.
-
-find_inc_file2(_FileName, []) ->
- {error, "No such file or directory"};
-find_inc_file2(FileName, [D|Rem]) ->
- Dir = case lists:last(D) of
- $/ ->
- D;
- _ ->
- D++"/"
- end,
- case catch file:read_file_info(Dir++FileName) of
- {ok, _} ->
- {ok, Dir++FileName};
- {error, _} ->
- find_inc_file2(FileName, Rem)
- end.
-
-
-%%===============================================================
-%% Read parameters of a macro or a variable in a source line
-%%===============================================================
-read_para([{char,$(} | Rem]) ->
- read_para(Rem, 1, [], [], 1);
-read_para([space,{char,$(} | Rem]) ->
- read_para(Rem, 1, [], [], 1);
-read_para(_Rem) ->
- {ok, [], [], 0}.
-
-
-%% Abrupt end of the list
-read_para([], _NoOfParen, _Current, _Para, _NoOfPara) ->
- {error, illegal_arg};
-%% All parameters checked
-read_para([{char,$)}|Rem], 1, [], Para, NoOfPara) ->
- {ok, Rem, lists:reverse(Para), NoOfPara};
-read_para([{char,$)}|Rem], 1, Current, Para, NoOfPara) ->
- {ok, Rem, lists:reverse([Current|Para]), NoOfPara};
-
-%% Continue reading
-read_para([{char,$)}|Rem], NoOfParen, Current, Para, NoOfPara) ->
- read_para(Rem, NoOfParen-1, Current++[{char,$)}], Para, NoOfPara);
-read_para([{char,$(}|Rem], NoOfParen, Current, Para, NoOfPara) ->
- read_para(Rem, NoOfParen+1, Current++[{char,$(}], Para, NoOfPara);
-read_para([{char,$,}|Rem], NoOfParen, Current, Para, NoOfPara) when NoOfParen == 1 ->
- read_para(Rem, NoOfParen, [], [Current|Para], NoOfPara+1);
-read_para([space|Rem], NoOfParen, [], Para, NoOfPara) ->
- read_para(Rem, NoOfParen, [], Para, NoOfPara);
-read_para([X|Rem], NoOfParen, Current, Para, NoOfPara) ->
- read_para(Rem, NoOfParen, Current++[X], Para, NoOfPara).
-
-
-
-
-
-
-%%===================================================================================
-%% check if a macro is already defined
-%%===================================================================================
-is_define_ok(Name, No_of_para, Parameters, Macro, Defs) ->
-
- case lists:keysearch(Name, 1, Defs) of
- {value, {Name, No_of_para, _MacroPara, Macro}} ->
- {yes, Defs};
- {value, _} ->
- Defs2 = lists:keydelete(Name, 1, Defs),
- NewMacro = is_define_ok_check_para(Parameters, Macro, []),
- case is_stringify_ok(NewMacro) of
- yes ->
- {no, [{Name, No_of_para, Parameters, NewMacro}|Defs2]};
- no ->
- ErrorText = "`#' operator is not followed by a macro argument name",
- {error, ErrorText, [{Name, No_of_para, Parameters, NewMacro}|Defs2]}
- end;
- false ->
- NewMacro = is_define_ok_check_para(Parameters, Macro, []),
- case is_stringify_ok(NewMacro) of
- yes ->
- {yes, [{Name, No_of_para, Parameters, NewMacro}|Defs]};
- no ->
- ErrorText = "`#' operator is not followed by a macro argument name",
- {error, ErrorText, [{Name, No_of_para, Parameters, NewMacro}|Defs]}
- end
- end.
-
-is_define_ok_check_para(_Para, [], Result) ->
- lists:reverse(Result);
-
-is_define_ok_check_para(Para, [H|T], Result) ->
- case define_arg_para_number(1, Para, H) of
- no_para ->
- is_define_ok_check_para(Para, T, [H|Result]);
- N ->
- is_define_ok_check_para(Para, T, [{para,N}|Result])
- end.
-
-define_arg_para_number(_N, [], _Current) ->
- no_para;
-define_arg_para_number(N, [H|_Para], Current) when H == [Current] ->
- N;
-define_arg_para_number(N, [_H|Para], Current) ->
- define_arg_para_number(N+1, Para, Current).
-
-
-is_stringify_ok([]) ->
- yes;
-is_stringify_ok([{char,$#},{char,$#}|T]) ->
- is_stringify_ok(T);
-is_stringify_ok([{char,$#},space,{para,_X}|T]) ->
- is_stringify_ok(T);
-is_stringify_ok([{char,$#},{para,_X}|T]) ->
- is_stringify_ok(T);
-is_stringify_ok([{char,$#},space,{var,_X}|T]) ->
- is_stringify_ok(T);
-is_stringify_ok([{char,$#},{var,_X}|T]) ->
- is_stringify_ok(T);
-is_stringify_ok([{char,$#},space,{nl,_X}|_T]) ->
- no;
-is_stringify_ok([{char,$#},{nl,_X}|_T]) ->
- no;
-is_stringify_ok([{char,$#}|_T]) ->
- no;
-is_stringify_ok([_H|T]) ->
- is_stringify_ok(T).
-
-%%===================================================================================
-%% check if a macro is already defined
-%%===================================================================================
-is_defined_before(Name, No_of_para, Defs) ->
- case lists:keysearch(Name, 1, Defs) of
- {value, {Name, No_of_para, _MacroPara, _Macro}} ->
- yes;
- {value, _} ->
- no;
- false ->
- no
- end.
-
-
-
-
-%%===================================================================================
-%% read_to_nl(File)
-%%===================================================================================
-read_to_nl([space|Rem]) ->
- read_to_nl(Rem, [], 1);
-read_to_nl(Rem) ->
- read_to_nl(Rem, [], 1).
-
-read_to_nl([], Result, Nl) ->
- {lists:reverse(Result), [], Nl};
-read_to_nl([{nl, _N}|Rem], [{string_part,String} | Result], Nl) ->
- read_to_nl(Rem, [nl, {string_part,String}|Result], Nl+1);
-read_to_nl([{nl, _N}|Rem], [{sys_head_part,String} | Result], Nl) ->
- read_to_nl(Rem, [nl, {sys_head_part,String}|Result], Nl+1);
-read_to_nl([{nl, _N}|Rem], Result, Nl) ->
- {lists:reverse(Result), Rem, Nl};
-read_to_nl([space|Rem], Result, Nl) ->
- read_to_nl(Rem, [space|Result], Nl);
-read_to_nl([{X,String}|Rem], Result, Nl) ->
- read_to_nl(Rem, [{X,String}|Result], Nl).
-
-
-
-
-%%===========================================================
-%% Read characters until next newline
-%%===========================================================
-%read_to_nl2(Str) -> read_to_nl2([],Str).
-
-%read_to_nl2(Line, []) -> {Line,[]};
-%read_to_nl2(Line, [$\n|Str]) -> {Line, Str};
-%read_to_nl2(Line, [X|Str]) -> read_to_nl2([X|Line], Str).
-
-
-
-
-%%===========================================================
-%% Remove leading spaces from a list
-%%===========================================================
-remove_leading_spaces([?space|List]) ->
- remove_leading_spaces(List);
-remove_leading_spaces([?tab|List]) ->
- remove_leading_spaces(List);
-remove_leading_spaces(List) ->
- List.
-
-
-
-
-%%===========================================================
-%% Skip characters until next newline
-%%===========================================================
-skip_to_nl([]) -> [];
-skip_to_nl([$\n | Str]) -> Str;
-skip_to_nl([$\\,$\n | Str]) -> [$/,$/|Str];
-skip_to_nl([_|Str]) -> skip_to_nl(Str).
-
-
-
-
-month(1) -> "Jan";
-month(2) -> "Feb";
-month(3) -> "Mar";
-month(4) -> "Apr";
-month(5) -> "May";
-month(6) -> "Jun";
-month(7) -> "Jul";
-month(8) -> "Aug";
-month(9) -> "Sep";
-month(10) -> "Oct";
-month(11) -> "Nov";
-month(12) -> "Dec".
-
-
-%% Multiple Include Optimization
-%%
-%% Algorithm described at:
-%% http://gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html
-update_mio({include, FileName}, #mio{included=Inc}=Mio) ->
- Mio#mio{valid=false, included=[FileName|Inc]};
-
-%% valid=false & cmacro=undefined indicates it is already decided this file is
-%% not subject to MIO
-update_mio(_, #mio{valid=false, depth=0, cmacro=undefined}=Mio) ->
- Mio;
-
-%% if valid=true, there is no non-whitespace tokens before this ifndef
-update_mio({'ifndef', Macro}, #mio{valid=true, depth=0, cmacro=undefined}=Mio) ->
- Mio#mio{valid=false, cmacro=Macro, depth=1};
-
-%% detect any tokens before top level #ifndef
-update_mio(_, #mio{valid=true, depth=0, cmacro=undefined}=Mio) ->
- Mio#mio{valid=false};
-
-%% If cmacro is alreay set, this is after the top level #endif
-update_mio({'ifndef', _}, #mio{valid=true, depth=0}=Mio) ->
- Mio#mio{valid=false, cmacro=undefined};
-
-%% non-top level conditional, just update depth
-update_mio({'ifndef', _}, #mio{depth=D}=Mio) when D > 0 ->
- Mio#mio{depth=D+1};
-update_mio('ifdef', #mio{depth=D}=Mio) ->
- Mio#mio{depth=D+1};
-update_mio('if', #mio{depth=D}=Mio) ->
- Mio#mio{depth=D+1};
-
-%% top level #else #elif invalidates multiple include optimization
-update_mio('else', #mio{depth=1}=Mio) ->
- Mio#mio{valid=false, cmacro=undefined};
-update_mio('else', Mio) ->
- Mio;
-update_mio('elif', #mio{depth=1}=Mio) ->
- Mio#mio{valid=false, cmacro=undefined};
-update_mio('elif', Mio) ->
- Mio;
-
-%% AT exit to top level, if the controlling macro is not set, this could be the
-%% end of a non-ifndef conditional block, or there were tokens before entering
-%% the #ifndef block. In either way, this invalidates the MIO
-%%
-%% It doesn't matter if `valid` is true at the time of exiting, it is set to
-%% true. This will be used to detect if more tokens are following the top
-%% level #endif.
-update_mio('endif', #mio{depth=1, cmacro=undefined}=Mio) ->
- Mio#mio{valid=false, depth=0};
-update_mio('endif', #mio{depth=1}=Mio) ->
- Mio#mio{valid=true, depth=0};
-update_mio('endif', #mio{depth=D}=Mio) when D > 1 ->
- Mio#mio{valid=true, depth=D-1};
-
-%%if more tokens are following the top level #endif.
-update_mio('endif', #mio{depth=1, cmacro=undefined}=Mio) ->
- Mio#mio{valid=false, depth=0};
-update_mio('endif', #mio{depth=D}=Mio) when D > 0 ->
- Mio#mio{valid=true, depth=D-1};
-update_mio(_, Mio) ->
- Mio#mio{valid=false}.
-
-%% clear `valid`, this doesn't matter since #endif will restore it if
-%% appropriate
-update_mio(Mio) ->
- Mio#mio{valid=false}.
-
-
diff --git a/lib/ic/src/ic_pragma.erl b/lib/ic/src/ic_pragma.erl
deleted file mode 100644
index 13c02cfcba..0000000000
--- a/lib/ic/src/ic_pragma.erl
+++ /dev/null
@@ -1,1957 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(ic_pragma).
-
-
--export([pragma_reg/2,pragma_cover/3]).
--export([pragma_prefix/3,pragma_version/3,pragma_id/3]).
--export([mk_alias/3,get_alias/2,scope2id/2,id2scope/2,mk_scope/1]).
--export([mk_ref/3,get_incl_refs/1,get_local_refs/1]).
--export([get_dependencies/1, add_inh_data/3, preproc/3]).
--export([getBrokerData/3,defaultBrokerData/1,list_to_term/1]).
--export([get_local_c_headers/2,get_included_c_headers/1,is_inherited_by/3]).
--export([no_doubles/1,fetchRandomLocalType/1,fetchLocalOperationNames/2]).
--export([is_local/2]).
-
-%% Debug
--export([print_tab/1,slashify/1,is_short/1]).
-
--import(lists,[suffix/2,delete/2,reverse/1,keysearch/3,member/2,last/1,flatten/1]).
--import(string,[tokens/2]).
--import(ets,[insert/2,lookup/2]).
-
--import(ic_forms, [get_id2/1, get_body/1, get_line/1]).
--import(ic_util, [to_atom/1]).
--import(ic_genobj, [idlfile/1]).
--import(ic_options, [get_opt/2]).
-
--include("icforms.hrl").
--include("ic.hrl").
-
-
-
-
-%% Initialization of the pragma table and
-%% start of pragma registration.
-%% NOTE : this pragma registration is build
-%% as a separate stage under compilation.
-%% If it is to be optimised, it should be
-%% embodied in one of other compiling stages.
-pragma_reg(G,X) ->
- S = ic_genobj:pragmatab(G),
- init_idlfile(G,S),
- init_pragma_status(S),
- registerOptions(G,S),
- pragma_reg_all(G, S, [], X),
- denote_specific_code_opts(G),
- case get_pragma_compilation_status(S) of
- true ->
- %% Remove ugly pragmas from form
- PragmaCleanForm = cleanup(X),
- {ok,PragmaCleanForm};
- false ->
- ErrorNr = get_pragma_error_nr(S),
- %% Just print the number of errors found
- case ErrorNr > 1 of
- true ->
- io:format("There were ~p errors found on file ~p~n",
- [ErrorNr,get_idlfile(S)]),
- error;
- false ->
- io:format("There were ~p error found on file ~p~n",
- [ErrorNr,get_idlfile(S)]),
- error
- end
- end.
-
-
-
-registerOptions(G,S) ->
- OptList = ets:tab2list(ic_genobj:optiontab(G)),
- registerOptions(G,S,OptList).
-
-
-registerOptions(_G,_S,[]) ->
- true;
-registerOptions(G,S,[{{option,{broker,Scope}},{Mod,Type}}|Rest]) ->
- insert(S,
- {codeopt,
- reverse(tokens(Scope,":")),
- {broker,{Mod,Type}},
- -1,
- nil,
- nil}),
- registerOptions(G,S,Rest);
-registerOptions(G,S,[_|Rest]) ->
- registerOptions(G,S,Rest).
-
-
-%% Decide if to apply pragmas
-%% by checking backend switch
-applyPragmasInBe(G) ->
- case get_opt(G, be) of
- erl_plain ->
- false;
- _ ->
- true
- end.
-
-
-%% Decide if the code option directive
-%% is allowed to change backend
-applyCodeOpt(G) ->
- case get_opt(G, be) of
- erl_corba -> %% Does not support codeopt
- false;
- erl_plain -> %% Does not support codeopt
- false;
- c_native -> %% Does not support codeopt
- false;
- _ ->
- true
- end.
-
-
-
-%% This removes all pragma records from the form.
-%% When debugged, it can be enbodied in pragma_reg_all.
-cleanup(undefined,C) -> C;
-cleanup([],C) -> C;
-cleanup([X|Xs],CSF) ->
- cleanup(Xs, CSF++cleanup(X)).
-
-cleanup(X) when is_list(X) -> cleanup(X,[]);
-cleanup(X) when is_record(X, preproc) -> [X];
-cleanup(X) when is_record(X, pragma) -> [];
-cleanup(X) when is_record(X, op) -> % Clean inside operation parameters
- [ X#op{params = cleanup(X#op.params,[])}];
-
-cleanup(X) when is_record(X, module) -> % Clean inside module body
- [ X#module{body = cleanup(X#module.body,[])}];
-
-cleanup(X) when is_record(X, interface) -> % Clean inside interface body
- [ X#interface{body = cleanup(X#interface.body,[])}];
-
-cleanup(X) when is_record(X, except) -> % Clean inside exception body
- [ X#except{body = cleanup(X#except.body,[])}];
-
-cleanup(X) when is_record(X, struct) -> % Clean inside struct body
- [ X#struct{body = cleanup(X#struct.body,[])}];
-
-cleanup(X) when is_record(X, case_dcl) -> % Clean inside union body
- [ X#case_dcl{label = cleanup(X#case_dcl.label,[])}];
-
-cleanup(X) when is_record(X, union) -> % Clean inside union body
- [ X#union{body = cleanup(X#union.body,[])}];
-
-cleanup(X) when is_record(X, enum) -> % Clean inside enum body
- [ X#enum{body = cleanup(X#enum.body,[])}];
-
-cleanup(X) -> [X].
-
-
-
-
-%% pragma_reg_all is top level registration for pragmas
-pragma_reg_all(_G, _S, _N, []) -> ok;
-pragma_reg_all(G, S, N, [X|Xs]) ->
- pragma_reg(G, S, N, X),
- pragma_reg_all(G, S, N, Xs).
-
-
-%% pragma_reg is top level registration for pragmas
-pragma_reg(G, S, N, X) when is_list(X) -> pragma_reg_list(G, S, N, X);
-pragma_reg(_G, S, _N, X) when element(1, X) == preproc ->
- case X#preproc.aux of
- [{_, _, "1"}] ->
- IncludeEntryLNr = get_line(X#preproc.id),
- IncludeFileName = element(3,element(3,X)),
- insert(S,{includes,get_idlfile(S),IncludeFileName,IncludeEntryLNr});
- _Other ->
- ok
- end,
- set_idlfile(S,element(3,element(3,X)));
-pragma_reg(G, S, N, X) when element(1, X) == pragma ->
- case applyPragmasInBe(G) of
-
- %% Pragmas are allowed to be
- %% applied in this this backend.
- true ->
-
- File = get_idlfile(S), % The current file or an included one.
- Type = case idlfile(G) of % Local/Included flag
- File ->
- local;
- _ ->
- included
- end,
-
- %% Register pragmas into pragmatab.
- case X of
- {pragma,{_,LineNr,"prefix"}, _To, _Apply} ->
- insert(S,{prefix,X,LineNr,N,File,Type});
-
- {pragma,{_,_,"ID"},_,_} ->
- pragma_reg_ID(G, S, N, X);
-
- {pragma,{_,_,"version"},_,_} ->
- pragma_reg_version(G, S, N, X );
-
- {pragma,{_,_,"CODEOPT"},_,_} ->
- pragma_reg_codeOpt(G,S,N,X);
-
- {pragma,{_,LineNr,BadPragma}, _To, _Apply} ->
- io:format("Warning : on file ~p :~n",[get_idlfile(S)]),
- io:format(" Unknown pragma directive ~p on line ~p, ignored.~n",
- [BadPragma,LineNr])
- end;
-
- %% Pragmas are not to be applied in
- %% this backend, ignore all pragmas.
- false ->
- true
- end,
- ok;
-
-pragma_reg(G, S, N, X) when is_record(X, module) ->
- mk_ref(G,[get_id2(X) | N],mod_ref),
- mk_file_data(G,X,N,module),
- pragma_reg_all(G, S, [get_id2(X) | N], get_body(X));
-
-pragma_reg(G, S, N, X) when is_record(X, interface) ->
- mk_ref(G,[get_id2(X) | N],ifc_ref),
- mk_file_data(G,X,N,interface),
- pragma_reg_all(G, S, [get_id2(X) | N], get_body(X));
-
-pragma_reg(G, S, N, X) when is_record(X, op) ->
- %% Add operation in table
- insert(S,{op,
- get_id2(X),
- N,
- get_idlfile(S),
- get_filepath(S)}),
- mk_file_data(G,X,N,op),
- pragma_reg_all(G, S, N, X#op.params);
-
-pragma_reg(G, S, N, X) when is_record(X, except) ->
- mk_ref(G,[get_id2(X) | N],except_ref),
- mk_file_data(G,X,N,except),
- pragma_reg_all(G, S, N, X#except.body);
-
-pragma_reg(G, _S, N, X) when is_record(X, const) ->
- mk_ref(G,[get_id2(X) | N],const_ref),
- mk_file_data(G,X,N,const);
-
-pragma_reg(G, _S, N, X) when is_record(X, typedef) ->
- XX = #id_of{type=X},
- lists:foreach(fun(Id) ->
- mk_ref(G,[get_id2(Id) | N],typedef_ref),
- mk_file_data(G,XX#id_of{id=Id},N,typedef)
- end,
- ic_forms:get_idlist(X));
-
-pragma_reg(G, S, N, X) when is_record(X, enum) ->
- mk_ref(G,[get_id2(X) | N],enum_ref),
- mk_file_data(G,X,N,enum),
- pragma_reg_all(G, S, N, X#enum.body);
-
-pragma_reg(G, S, N, X) when is_record(X, union) ->
- mk_ref(G,[get_id2(X) | N],union_ref),
- mk_file_data(G,X,N,union),
- pragma_reg_all(G, S, N, X#union.body);
-
-pragma_reg(G, S, N, X) when is_record(X, struct) ->
- mk_ref(G,[get_id2(X) | N],struct_ref),
- mk_file_data(G,X,N,struct),
- case X#struct.body of
- undefined ->
- ok;
- _ ->
- pragma_reg_all(G, S, N, X#struct.body)
- end;
-
-pragma_reg(G, _S, N, X) when is_record(X, attr) ->
- XX = #id_of{type=X},
- lists:foreach(fun(Id) ->
- mk_ref(G,[get_id2(Id) | N],attr_ref),
- mk_file_data(G,XX#id_of{id=Id},N,attr)
- end,
- ic_forms:get_idlist(X));
-
-pragma_reg(_G, _S, _N, _X) -> ok.
-
-
-
-
-pragma_reg_list(_G, _S, _N, []) -> ok;
-pragma_reg_list(G, S, N, List ) ->
- CurrentFileName = get_idlfile(S),
- pragma_reg_list(G, S, N, CurrentFileName, List).
-
-pragma_reg_list(_G, _S, _N, _CFN, []) -> ok;
-pragma_reg_list(G, S, N, CFN, [X | Xs]) ->
- case X of
- {preproc,_,{_,_,FileName},_} ->
- set_idlfile(S,FileName),
- pragma_reg(G, S, N, X),
- pragma_reg_list(G, S, N, FileName, Xs);
- _ ->
- pragma_reg(G, S, N, X),
- pragma_reg_list(G, S, N, CFN, Xs)
- end.
-
-
-
-
-
-pragma_reg_ID(G, S, N, X) ->
- {pragma,{_,LineNr,"ID"}, _To, Apply} = X,
-
-
- File = get_idlfile(S), % The current file or an included one.
- Type = case idlfile(G) of % Local/Included flag
- File ->
- local;
- _ ->
- included
- end,
-
- %% Check if ID is one of the allowed types :
- %% * OMG IDL
- %% * DCE UUID
- %% * LOCAL
- case tokens(element(3,Apply),":") of
- ["IDL",_,_] ->
- insert(S,{id,X,LineNr,N,File,Type});
- ["DCE",_,VSN] ->
- case is_short(VSN) of
- true ->
- insert(S,{id,X,LineNr,N,File,Type});
- false ->
- set_compilation_failure(S),
- io:format("Error on file ~p :~n",[get_idlfile(S)]),
- io:format(" Bad pragma ID ~p on line ~p,~n",
- [element(3,Apply),LineNr]),
- io:format(" the version part of ID is not a short integer.~n")
- end;
- ["LOCAL"|_] ->
- insert(S,{id,X,LineNr,N,File,Type});
- _ ->
- set_compilation_failure(S),
- io:format("Error on file ~p :~n",[get_idlfile(S)]),
- io:format(" Bad pragma ID ~p on line ~p.~n",
- [element(3,Apply),LineNr])
- end.
-
-
-
-pragma_reg_version(G, S, N, X) ->
- {pragma,{_,LineNr,"version"}, _To, Apply} = X,
-
- File = get_idlfile(S), % The current file or an included one.
- Type = case idlfile(G) of % Local/Included flag
- File ->
- local;
- _ ->
- included
- end,
-
- case tokens(Apply,".") of
- [Major,Minor] ->
- case is_short(Major) and is_short(Minor) of
- true ->
- insert(S,{version,X,LineNr,N,File,Type});
- false ->
- set_compilation_failure(S),
- io:format("Error on file ~p :~n",[get_idlfile(S)]),
- io:format(" Bad pragma version ~p on line ~p,~n",
- [Apply,LineNr]),
- io:format(" the version is not valid.~n")
- end;
- _ ->
- set_compilation_failure(S),
- io:format("Error on file ~p :~n",[get_idlfile(S)]),
- io:format(" Bad pragma version ~p on line ~p,~n",
- [Apply,LineNr]),
- io:format(" the version is not valid.~n")
- end.
-
-
-pragma_reg_codeOpt(G, S, _N, {pragma,{_,LineNr,"CODEOPT"},_,Apply} )->
- case applyCodeOpt(G) of
- true ->
- {_,_,OptionList_str} = Apply,
- case list_to_term(OptionList_str) of
- error ->
- ic_error:error(G,{pragma_code_opt_bad_option_list,LineNr});
- OptionList ->
- case lists:keysearch(be,1,OptionList) of
- false ->
- %% Add the terms of the option list
- %% to the compiler option list
- applyCodeOpts(G,S,LineNr,OptionList);
- {value, {be,Type}} ->
- %% If backend is set from user,
- %% let the same backend be otherwize
- %% set backend by codeOpt directive
- case get_opt(G, be) of
- false ->
- %% Add the terms of the option list
- %% to the compiler option list
- applyCodeOpts(G,S,LineNr,OptionList);
- _ ->
- %% Add all the terms of the option list
- %% to the compiler option list but the
- %% backend option
- applyCodeOpts(G,
- S,
- LineNr,
- lists:delete({be,Type},OptionList))
- end
- end
- end;
- false ->
- true
- end.
-
-
-
-applyCodeOpts(_,_,_,[]) ->
- true;
-applyCodeOpts(G,S,LNr,[{{broker,Scope},{M,T}}|Xs]) ->
- ScopedId = reverse(tokens(Scope,":")),
- case ets:match(S,
- {codeopt,ScopedId,
- '$1','$2','_','_'}) of
- [] ->
- %% Add pragma in table
- insert(S,
- {codeopt,
- ScopedId,
- {broker,{M,T}},
- LNr,
- get_idlfile(S),
- get_filepath(S)}),
- %% Continue
- applyCodeOpts(G,S,LNr,Xs);
- _ ->
- %% Use the code option
- %% from user and continue
- applyCodeOpts(G,S,LNr,Xs)
- end;
-applyCodeOpts(G,S,LNr,[X|Xs]) ->
- case is_allowed_opt(X) of
- true ->
- %% Add that term of the option list
- %% to the compiler option list
- ic_options:add_opt(G, [X], true),
- %% Continue
- applyCodeOpts(G,S,LNr,Xs);
- false ->
- %% Print warning and continue
- io:format("Warning on file ~p :~n",[get_idlfile(S)]),
- io:format(" Bad option in pragma : ~p, ignored !~n",[X]),
- applyCodeOpts(G,S,LNr,Xs)
- end.
-
-
-is_allowed_opt({X,Y}) ->
- ic_options:allowed_opt(X,Y);
-is_allowed_opt(_X) ->
- false.
-
-
-
-%% Returns a tuple { PFX, VSN, ID }, that is the
-%% pragma prefix, version and id coverages of
-%% the scope SCOPE. This is done by use of the
-%% function pragma_cover/4.
-pragma_cover(G,Scope,Object) ->
- pragma_cover(ic_genobj:pragmatab(G),get_id2(Object),Scope,get_line(Object)).
-
-%% Returns a tuple { PFX, VSN, ID }, that is the
-%% pragma prefix, version and id coverages of
-%% the scope SCOPE
-pragma_cover(PragmaTab,Name,Scope,LineNr) ->
- PFX = pragma_prefix_cover(PragmaTab,Name,Scope,LineNr),
- VSN = pragma_version_cover(PragmaTab,Name,Scope,LineNr),
- ID = pragma_id_cover(PragmaTab,Name,Scope,LineNr),
- { PFX, VSN, ID }.
-
-
-
-%% Finds out which pragma PREFIX that affects
-%% the scope Scope
-pragma_prefix(G,Scope,Object) ->
- pragma_prefix_cover(ic_genobj:pragmatab(G),get_id2(Object),Scope,get_line(Object)).
-
-
-%% Finds out which pragma PREFIX that affects
-%% the scope Scope
-pragma_prefix_cover(PragmaTab,Name,Scope,LineNr) ->
- case lookup(PragmaTab,prefix) of
- [] ->
- none;
- PragmaPrefixList ->
- FilteredPragmaPrefixList =
- filter_pragma_prefix_list(PragmaTab,Name,Scope,PragmaPrefixList),
- case most_local(FilteredPragmaPrefixList,Scope) of
- [] ->
- none;
- MostLocalList ->
- case dominant_prefix(MostLocalList,LineNr) of
- none ->
- none;
-
- %% Just filter empty pragma prefix
- {prefix,{pragma,{_,_,_},_,{'<string_literal>',_,[]}},_,_,_,_} ->
- none;
-
- DP ->
- %% Return the scoped id (reversed list of
- %% path elements, but remember to remove
- %% '[]' that represents the top level
- slashify(lists:sublist(Scope, 1,
- length(Scope) - length(element(4,DP))) ++
- [ element(3,element(4,element(2,DP)))])
- end
- end
- end.
-
-
-%% Returns a slashified name, [I1, M1] becomes "M1/I1"
-slashify(List) -> lists:foldl(fun(X, Acc) -> X++"/"++Acc end,
- hd(List), tl(List)).
-
-
-%% Finds out which pragma VERSION that affects
-%% the scope Scope
-pragma_version(G,Scope,Object) ->
- pragma_version_cover(ic_genobj:pragmatab(G),get_id2(Object),Scope,get_line(Object)).
-
-%% Finds out which pragma VERSION that affects
-%% the scope Scope
-pragma_version_cover(PragmaTab,Name,Scope,LineNr) ->
- case lookup(PragmaTab,version) of
- [] ->
- default_version();
- PragmaVersionList ->
- case all_actual_for_version_or_id( PragmaVersionList, Name ) of
- [] ->
- default_version();
- ActualVersionList ->
- case most_local(ActualVersionList,Scope) of
- [] ->
- default_version();
- MostLocalList ->
- case dominant_version(MostLocalList,LineNr) of
- DV ->
- element(4,element(2,DV))
- end
- end
- end
- end.
-
-
-default_version() -> "1.0".
-
-
-
-%% Finds out which pragma ID that affects
-%% the scope Scope
-pragma_id(G,Scope,Object) ->
- pragma_id_cover(ic_genobj:pragmatab(G),get_id2(Object),Scope,get_line(Object)).
-
-%% Finds out which pragma ID that affects
-%% the scope Scope
-pragma_id_cover(PragmaTab,Name,Scope,LineNr) ->
- case lookup(PragmaTab,id) of
- [] ->
- none;
- PragmaIdList ->
- case all_actual_for_version_or_id( PragmaIdList, Name ) of
- [] ->
- none;
- ActualIdList ->
- case most_local(ActualIdList,Scope) of
- [] ->
- none;
- MostLocalList ->
- case dominant_id(MostLocalList,LineNr) of
- PI ->
- element(3,element(4,element(2,PI)))
- end
- end
- end
- end.
-
-
-
-
-%% Finds out which pragma VERSION ( or ID ) that
-%% that affects the scope object with name NAME
-all_actual_for_version_or_id(NList, Name) ->
- all_actual_for_version_or_id( NList, [], Name ).
-
-all_actual_for_version_or_id([], Actual, _) ->
- Actual;
-all_actual_for_version_or_id([First|Rest], Found, Name) ->
- case is_actual_for_version_or_id(First,Name) of
- true ->
- all_actual_for_version_or_id(Rest, [First|Found], Name);
- false ->
- all_actual_for_version_or_id(Rest, Found, Name)
- end.
-
-is_actual_for_version_or_id( Current, Name ) ->
- case element(3,element(3,element(2,Current))) of
- Name ->
- true;
- OtherName ->
- suffix([Name],tokens(OtherName,"::"))
- end.
-
-
-
-
-%% Find the most locally defind pragmas
-%% to the scope SCOPE
-most_local( SList, Scope ) ->
- case SList of
- [] ->
- [];
- [First|Rest] ->
- case suffix( element(4,First), Scope ) of
- true ->
- most_local( Rest, First, Scope, [First] );
- false ->
- most_local( Rest, Scope )
- end
- end.
-
-%% Returns a list of all pragmas found in the
-%% same scope. Should choose the right one by looking
-%% att the position of the pragma in relation to
-%% the current object..... ( For hairy cases ).
-most_local( SList, Current, Scope, AllFound ) ->
- case SList of
- [] ->
- AllFound;
- [First|Rest] ->
- FirstScope = element(4,First),
- case suffix( FirstScope, Scope ) of
- true ->
- CurrentScope = element(4,Current),
- case suffix( CurrentScope, FirstScope ) of
- true ->
- case length( CurrentScope ) == length( FirstScope ) of
- true -> %% SAME SCOPE ! KEEP BOTH
- most_local( Rest, Current, Scope, [First|AllFound] );
- false ->
- most_local( Rest, First, Scope, [First] )
- end;
- false ->
- most_local( Rest, Current, Scope, AllFound )
- end;
- false ->
- most_local( Rest, Current, Scope, AllFound )
- end
- end.
-
-
-
-
-%% Find the most dominant prefix pragmas
-%% located onto the SAME scope. Now
-%% we look att the line number, the position
-%% on the file.
-dominant_prefix(SList,LineNr) ->
- case SList of
- [First|Rest] ->
- dominant_prefix(Rest,First,LineNr)
- end.
-
-
-dominant_prefix([],{prefix,X,PLNr,N,F,T},LineNr) ->
- case LineNr > PLNr of
- true ->
- {prefix,X,PLNr,N,F,T};
- false ->
- none
- end;
-dominant_prefix([{prefix,FX,FPLNr,FN,F1,T1}|Rest],{prefix,CX,CPLNr,CN,F2,T2},LineNr) ->
- case LineNr > FPLNr of % Check if FIRST before the object
- true ->
- case FPLNr > CPLNr of % Check if FIRST after CURRENT
- true ->
- dominant_prefix(Rest,{prefix,FX,FPLNr,FN,F1,T1},LineNr);
- false ->
- dominant_prefix(Rest,{prefix,CX,CPLNr,CN,F2,T2},LineNr)
- end;
- false -> % FIRST does not affect the object
- dominant_prefix(Rest,{prefix,CX,CPLNr,CN,F2,T2},LineNr)
- end.
-
-
-
-
-%% Find the most dominant version pragmas
-%% located onto the SAME scope. Now
-%% we look att the line number, the position
-%% on the file.
-dominant_version(SList,LineNr) ->
- case SList of
- [First|Rest] ->
- dominant_version(Rest,First,LineNr)
- end.
-
-
-dominant_version([],Current,_) -> Current;
-dominant_version([{version,FX,FPLNr,FN,F1,T1}|Rest],{version,CX,CPLNr,CN,F2,T2},LineNr) ->
- case FPLNr > CPLNr of % Check if FIRST after CURRENT
- true ->
- dominant_version(Rest,{prefix,FX,FPLNr,FN,F1,T1},LineNr);
- false ->
- dominant_version(Rest,{prefix,CX,CPLNr,CN,F2,T2},LineNr)
- end.
-
-
-
-
-%% Find the most dominant id pragmas
-%% located onto the SAME scope. Now
-%% we look att the line number, the position
-%% on the file.
-dominant_id(SList,LineNr) ->
- case SList of
- [First|Rest] ->
- dominant_id(Rest,First,LineNr)
- end.
-
-
-dominant_id([],Current,_) -> Current;
-dominant_id([{id,FX,FPLNr,FN,F1,T1}|Rest],{id,CX,CPLNr,CN,F2,T2},LineNr) ->
- case FPLNr > CPLNr of % Check if FIRST after CURRENT
- true ->
- dominant_id(Rest,{id,FX,FPLNr,FN,F1,T1},LineNr);
- false ->
- dominant_id(Rest,{id,CX,CPLNr,CN,F2,T2},LineNr)
- end.
-
-
-
-
-
-%% This registers a module defined inside the file or
-%% an included file. A tuple that describes the module
-%% is added to the table.
-%% Observe that the modules registered are ONLY those
-%% who are in the top level, not definedd inside others !
-mk_ref(G,Name,Type) ->
- case length(Name) > 1 of
- true -> %% The interface is NOT defined att top level
- true;
- false ->
- S = ic_genobj:pragmatab(G),
- File = get_idlfile(S), % The current file or an included one.
- case idlfile(G) of % The current file to be compiled.
- File ->
- insert(S,{Type,Name,File,local});
- _ ->
- insert(S,{Type,Name,File,included})
- end
- end.
-
-
-%% The same as mk_ref/3 but this registers everything with
-%% all vital information available inside files.
-%% Registers ESSENTIAL data for included files
-mk_file_data(G,X,Scope,Type) ->
- S = ic_genobj:pragmatab(G),
- Name = get_id2(X),
- PreprocFile = get_idlfile(S), % The current file or an included one.
- CompFile = idlfile(G), % The current file compiled
- Depth = length(Scope), % The depth of the scope
- ScopedName = ic_util:to_undersc([Name|Scope]),
- Line = ic_forms:get_line(X),
- case PreprocFile of
- CompFile ->
- insert(S,{file_data_local,CompFile,CompFile,Type,Scope,Name,ScopedName,Depth,Line});
- PreprocFile ->
- insert(S,{file_data_included,PreprocFile,CompFile,Type,Scope,Name,ScopedName,Depth,Line})
- end.
-
-
-
-%% Return a list with all the headers from
-%% the local file that represent the module
-%% or interface that is preciding the current
-get_local_c_headers(G,X) ->
- S = ic_genobj:pragmatab(G),
- Local = lookup(S,file_data_local),
- FoundLocal = get_local_c_headers(X,Local,Local),
- no_doubles(FoundLocal).
-
-get_local_c_headers(X,Local,Local) ->
- get_local_c_headers(X,Local,Local,[]).
-
-get_local_c_headers(_X,[],_All,Found) ->
- Found;
-get_local_c_headers(X,[{file_data_local,_PF_idl,_,module,_,_,SN,_,Line}|Hs],All,Found)->
- case ic_forms:get_line(X) > Line of
- true ->
- get_local_c_headers(X,Hs,All,[SN|Found]);
- false ->
- get_local_c_headers(X,Hs,All,Found)
- end;
-get_local_c_headers(X,[{file_data_local,_PF_idl,_,interface,_,_,SN,_,Line}|Hs],All,Found)->
- case ic_forms:get_line(X) > Line of
- true ->
- get_local_c_headers(X,Hs,All,[SN|Found]);
- false ->
- get_local_c_headers(X,Hs,All,Found)
- end;
-get_local_c_headers(X,[_|Hs],All,Found) ->
- get_local_c_headers(X,Hs,All,Found).
-
-
-
-%% Return a list with all the headers from
-%% the included file that represent the module
-%% or interface that have to be included
-get_included_c_headers(G) ->
- S = ic_genobj:pragmatab(G),
- Included = lookup(S,file_data_included),
- FoundIncluded = get_included_c_headers(Included,Included),
- no_doubles(FoundIncluded).
-
-get_included_c_headers(Included,Included) ->
- get_included_c_headers(Included,Included,[]).
-
-get_included_c_headers([],_All,Found) ->
- Found;
-get_included_c_headers([{file_data_included,PF_idl,_CF_idl,T,_S,_N,SN,0,_}|Hs],All,Found) ->
- Len = length(PF_idl),
- FN = string:sub_string(PF_idl,1,Len-4),
- case only_top_level(PF_idl,All) of
- true ->
- %%
- L = string:tokens(FN,"/"),
- FN2 = lists:last(L),
- %%
- get_included_c_headers(Hs,All,["oe_"++FN2|Found]);
- false ->
- case T of
- module ->
- case contains_interface(PF_idl,All) of
- true ->
- %%
- L = string:tokens(FN,"/"),
- FN2 = lists:last(L),
- %%
- get_included_c_headers(Hs,All,["oe_"++FN2|Found]);
- false ->
- get_included_c_headers(Hs,All,[SN|Found])
- end;
- interface ->
- case contains_interface(PF_idl,All) of
- true ->
- %%
- L = string:tokens(FN,"/"),
- FN2 = lists:last(L),
- %%
- get_included_c_headers(Hs,All,["oe_"++FN2|Found]);
- false ->
- get_included_c_headers(Hs,All,[SN|Found])
- end;
- _ ->
- get_included_c_headers(Hs,All,["oe_"++FN|Found])
- end
- end;
-get_included_c_headers([{file_data_included,_PF_idl,_,module,_,_,SN,_,_}|Hs],All,Found)->
- get_included_c_headers(Hs,All,[SN|Found]);
-get_included_c_headers([{file_data_included,_PF_idl,_,interface,_,_,SN,_,_}|Hs],All,Found)->
- get_included_c_headers(Hs,All,[SN|Found]);
-get_included_c_headers([_|Hs],All,Found) ->
- get_included_c_headers(Hs,All,Found).
-
-%% Help functions for the above
-
-only_top_level(_PF_idl,[]) ->
- true;
-only_top_level(PF_idl,[H|Hs]) ->
- case element(2,H) of
- PF_idl ->
- case element(8,H) > 0 of
- true ->
- false;
- false ->
- only_top_level(PF_idl,Hs)
- end;
- _ ->
- only_top_level(PF_idl,Hs)
- end.
-
-contains_interface(_PF_idl,[]) ->
- false;
-contains_interface(PF_idl,[H|Hs]) ->
- case element(2,H) of
- PF_idl ->
- case element(4,H) of
- interface ->
- case element(8,H) > 0 of
- true ->
- true;
- false ->
- contains_interface(PF_idl,Hs)
- end;
- _ ->
- contains_interface(PF_idl,Hs)
- end;
- _ ->
- contains_interface(PF_idl,Hs)
- end.
-
-
-
-%% This returns a list of everything defined in an included file.
-get_incl_refs(G) ->
- S = ic_genobj:pragmatab(G),
-
- RefList =
- ets:match(S,{mod_ref,'$0','_',included}) ++
- ets:match(S,{ifc_ref,'$0','_',included}) ++
- ets:match(S,{const_ref,'$0','_',included}) ++
- ets:match(S,{typedef_ref,'$0','_',included}) ++
- ets:match(S,{except_ref,'$0','_',included}) ++
- ets:match(S,{struct_ref,'$0','_',included}) ++
- ets:match(S,{union_ref,'$0','_',included}) ++
- ets:match(S,{enum_ref,'$0','_',included}) ++
- ets:match(S,{attr_ref,'$0','_',included}),
-
- case RefList of
- [] ->
- none;
- _ ->
- RefList
- end.
-
-
-
-%% This returns a list of everything locally defined.
-get_local_refs(G) ->
- S = ic_genobj:pragmatab(G),
-
- RefList =
- ets:match(S,{mod_ref,'$0','_',local}) ++
- ets:match(S,{ifc_ref,'$0','_',local}) ++
- ets:match(S,{const_ref,'$0','_',local}) ++
- ets:match(S,{typedef_ref,'$0','_',local}) ++
- ets:match(S,{except_ref,'$0','_',local}) ++
- ets:match(S,{struct_ref,'$0','_',local}) ++
- ets:match(S,{union_ref,'$0','_',local}) ++
- ets:match(S,{enum_ref,'$0','_',local}) ++
- ets:match(S,{attr_ref,'$0','_',local}),
-
- case RefList of
- [] ->
- none;
- _ ->
- RefList
- end.
-
-
-
-
-
-%% This is intented to be used for solving the identification
-%% problem introduced by pragmas. It creates aliases between
-%% scoped and "final" identities.
-mk_alias(G,PragmaId,ScopedId) ->
- %io:format("~nMaking alias -> ~p~n",[PragmaId]),
- S = ic_genobj:pragmatab(G),
- insert(S,{alias,ScopedId,PragmaId}).
-
-
-%% This is used to find out if the object described with
-%% the scoped id is created. If this is the case, it should
-%% be registered as an alias and the identity of the object
-%% is returned. Otherwize "none" is returned.
-get_alias(G,ScopedId) ->
- S = ic_genobj:pragmatab(G),
- case ets:match(S,{alias,ScopedId,'$1'}) of
- [] ->
- none;
- [[IfrId]] ->
- %io:format("~nFound alias -> ~p~n",[IfrId]),
- IfrId
- end.
-
-
-
-%% Returns the alias id or constructs an id
-scope2id(G,ScopedId) ->
- case get_alias(G,ScopedId) of
- none ->
- case is_included(G,ScopedId) of
- true -> %% File included
- get_included_IR_ID(G,ScopedId);
- false -> %% File local
- NewIfrId = mk_id(ScopedId), % Create a "standard" id
- mk_alias(G,NewIfrId,ScopedId), % Create an alias
- NewIfrId
- end;
- IfrId ->
- IfrId
- end.
-
-
-
-
-is_included(G,ScopedId) ->
- S = ic_genobj:pragmatab(G),
- Name = ic_util:to_undersc(ScopedId),
- case ets:match(S,{file_data_included,'_','_','_','_','_',Name,'_','_'}) of
- [[]] ->
- true;
- _ ->
- false
- end.
-
-
-
-get_included_IR_ID(G,ScopedId) ->
- S = ic_genobj:pragmatab(G),
- ScopedName = ic_util:to_undersc(ScopedId),
- [[Scope,Name,LNr]] = ets:match(S,{file_data_included,'_','_','_','$3','$4',ScopedName,'_','$7'}),
- {Prefix,Vsn,Id} = pragma_cover(S,Name,Scope,LNr),
- case Id of
- none ->
- case Prefix of
- none ->
- IR_ID =
- lists:flatten(io_lib:format("IDL:~s:~s",[ScopedName, Vsn])),
- ic_pragma:mk_alias(G,IR_ID,ScopedId),
- IR_ID;
- _ ->
- IR_ID =
- lists:flatten(io_lib:format("IDL:~s:~s",[Prefix ++ "/" ++ ScopedName, Vsn])),
- ic_pragma:mk_alias(G,IR_ID,ScopedId),
- IR_ID
- end;
- _ ->
- ic_pragma:mk_alias(G,Id,ScopedId),
- Id
- end.
-
-
-
-
-
-%% Returns the scope for object
-id2scope(G,IfrId) ->
- S = ic_genobj:pragmatab(G),
- case lookup(S,alias) of
- [] ->
- mk_scope(IfrId);
- AliasList ->
- case keysearch(IfrId,3,AliasList) of
- false ->
- mk_scope(IfrId);
- {value,{alias,ScopedId,_}} ->
- ScopedId
- end
- end.
-
-%% Returns a "standard" IDL ID by getting the scope list
-mk_id(ScopedId) ->
- "IDL:" ++ ic_pragma:slashify(ScopedId) ++ ":" ++ default_version().
-
-%% Returns the scope of an object when getting a "standard" IDL ID
-mk_scope(IfrId) ->
- [_,Body,_] = tokens(IfrId,":"),
- reverse(tokens(Body,"/")).
-
-
-
-%% This is used to note the exact compiled file
-%% under pragma creation. There are two options, the
-%% main file or files included by the main file. This
-%% just denotes the CURRENT file, the main file or
-%% the included ones. A very usual field is the file
-%% path that shows the include path of the file
-
-init_idlfile(G,S) ->
- IdlFile = idlfile(G),
- insert(S,{file,IdlFile,[]}).
-
-set_idlfile(S,FileName) ->
- FilePath = get_filepath(S),
- case FilePath of
- [] ->
- ets:delete(S,file),
- insert(S,{file,FileName,[FileName|FilePath]});
- _ ->
- case hd(FilePath) of
- [] ->
- ets:delete(S,file),
- insert(S,{file,FileName,[FileName|FilePath]});
- _ ->
- case tl(FilePath) of
- [] ->
- ets:delete(S,file),
- insert(S,{file,FileName,[FileName|FilePath]});
- _ ->
- case hd(tl(FilePath)) of
- [] ->
- ets:delete(S,file),
- insert(S,{file,FileName,[FileName|FilePath]});
- FileName ->
- ets:delete(S,file),
- insert(S,{dependency,FilePath}), % Add dependency branch
- insert(S,{file,FileName,tl(FilePath)});
- _ ->
- ets:delete(S,file),
- insert(S,{file,FileName,[FileName|FilePath]})
- end
- end
- end
- end.
-
-get_idlfile(S) ->
- [FT] = lookup(S,file),
- element(2,FT).
-
-get_filepath(S) ->
- [FT] = lookup(S,file),
- element(3,FT).
-
-
-%% This returns a list of file names
-%% that direct or indirect the current
-%% compiled file is depended on.
-get_dependencies(G) ->
- S = ic_genobj:pragmatab(G),
- case lookup(S,dependency) of
- [] ->
- [];
- Dependencies ->
- {get_idlfile(S),get_dependencies(Dependencies,[])}
- end.
-
-get_dependencies([],Dependencies) ->
- no_doubles(Dependencies);
-get_dependencies([{dependency,Path}|Tail],Current) ->
- get_dependencies(Tail,[hd(Path)|Current]).
-
-
-no_doubles(List) ->
- no_doubles(List,[]).
-
-no_doubles([],NoDoubles) ->
- NoDoubles;
-no_doubles([X|Xs],Current) ->
- case member(X,Xs) of
- true ->
- no_doubles(Xs,Current);
- false ->
- no_doubles(Xs,[X|Current])
- end.
-
-
-
-
-%% Pragma compilation status initialization
-init_pragma_status(S) ->
- insert(S,{status,true,0}).
-
-%% Pragma compilation status set to failure
-%% and count up the number of errors
-set_compilation_failure(S) ->
- [{status,_,ErrorNr}] = lookup(S,status),
- ets:delete(S,status),
- insert(S,{status,false,ErrorNr+1}).
-
-%% Pragma compilation status set to lookup
-get_pragma_compilation_status(S) ->
- [Status] = lookup(S,status),
- element(2,Status).
-
-%% Pragma error number
-get_pragma_error_nr(S) ->
- [Status] = lookup(S,status),
- element(3,Status).
-
-
-%% Short check
-is_short(N_str) when is_list(N_str) ->
- case is_short_decimal_str(N_str) of
- true ->
- true;
- false ->
- false
- end;
-is_short(N) when is_integer(N)->
- (N < 65535) and (N > -65536);
-is_short(_) -> false.
-
-
-%% Check if the string is a
-%% list of characters representing
-%% a short. Avoid crash !.
-is_short_decimal_str(N_str) ->
- case is_decimal_str(N_str) of
- true ->
- N = list_to_integer(N_str),
- (N < 65535) and (N > -65536);
- false ->
- false
- end.
-
-%% Check if the string is a
-%% list of characters representing
-%% decimals.
-is_decimal_str([]) ->
- true;
-is_decimal_str([First|Rest]) ->
- case is_decimal_char(First) of
- true ->
- is_decimal_str(Rest);
- false ->
- false
- end.
-
-%% True if D is a character
-%% representing a decimal (0-9).
-is_decimal_char(D) ->
- case (48=<D) and (D=<57) of
- true ->
- true;
- false ->
- false
- end.
-
-
-%% Prints out all the table
-print_tab(G) ->
- io:format("~nPragmaTab = ~p~n",[ets:tab2list(ic_genobj:pragmatab(G))]).
-
-
-list_to_term(List) ->
- case catch erl_scan:string(List) of
- {ok, Tokens, _} ->
- case erl_parse:parse_term(Tokens ++ [{dot, 1}]) of
- {ok,Term} ->
- Term;
- _ ->
- error
- end;
- _ ->
- error
- end.
-
-
-
-%% Cleanup all other code options for a specified scope
-%% in the same file, but the most dominant.
-cleanup_codeOptions(G,S,ScopedId) ->
- case ets:match(S,{codeopt,ScopedId,'$1','$2',idlfile(G),'$4'}) of
- [] ->
- %% No codeOpt directive is placed inside the
- %% currently compiled file. Try to find other
- %% directives located in included files.
- true;
- List ->
- %% A codeOpt directive is placed inside the
- %% currently compiled file. This dominates
- %% all other directives.
- CodeOption = best_positioned_codeOpt(List),
- %% Remove code options that do not affect
- %% the code production (redundant)
- remove_redundant_codeOpt(S,[ScopedId|CodeOption])
- end.
-
-
-%% Best positioned is the codeopt located
-%% "highest" on the SAME file, the one with
-%% lowest line number.
-best_positioned_codeOpt([X|Xs]) ->
- best_positioned_codeOpt(Xs,X).
-
-best_positioned_codeOpt([],Found) ->
- Found;
-best_positioned_codeOpt([X|Xs],Current) ->
- case hd(tl(X)) > hd(tl(Current)) of
- true ->
- best_positioned_codeOpt(Xs,Current);
- false ->
- best_positioned_codeOpt(Xs,X)
- end.
-
-
-remove_redundant_codeOpt(S,[ScopedId,CodeOption,LNr,FilePath]) ->
- ets:match_delete(S,{codeopt,ScopedId,'$1','$2','$3','$4'}),
- ets:insert(S,{codeopt,ScopedId,CodeOption,LNr,last(FilePath),FilePath}).
-
-
-
-
-add_inh_data(G,InclScope,X) ->
- S = ic_genobj:pragmatab(G),
- case X#interface.inherit of
- [] ->
- true;
- [InhBody] ->
- Scope = [get_id2(X)|InclScope],
- insert(S,{inherits,Scope,InhBody});
- InhList ->
- add_inh_data(G, S, InclScope, X, InhList)
- end.
-
-add_inh_data(_,_,_,_,[]) ->
- true;
-add_inh_data(G, S, InclScope, X, [InhBody|InhBodies]) ->
- Scope = [get_id2(X)|InclScope],
- insert(S, {inherits,Scope,InhBody}),
- add_inh_data(G, S, InclScope, X, InhBodies).
-
-
-%% Returns a default broker data
-defaultBrokerData(G) ->
- {to_atom(ic_genobj:impl(G)),transparent}.
-
-
-%% Loops through the form and sdds inheritence data
-preproc(G, N, [X|Xs]) when is_record(X, interface) ->
- %% Add inheritence data to pragmatab
- ic_pragma:add_inh_data(G,N,X),
- N2 = [get_id2(X) | N],
- preproc(G, N2, get_body(X)),
- lists:foreach(fun({_Name, Body}) -> preproc(G, N2, Body) end,
- X#interface.inherit_body),
- preproc(G, N, Xs);
-
-preproc(G,N,[X|Xs]) when is_record(X, module) ->
- N2 = [get_id2(X) | N],
- preproc(G, N2, get_body(X)),
- preproc(G,N,Xs);
-
-preproc(G,N,[_X|Xs]) ->
- preproc(G,N,Xs);
-
-preproc(_G, _N, []) ->
- ok.
-
-
-%% Returns a tuple / list of tuples { Mod, Type }
-%% Does not check overridence because it is the
-%% top scope for the module to be produced and
-%% cannot be overriden.
-getBrokerData(G,X,Scope) ->
- S = ic_genobj:pragmatab(G),
- cleanup_codeOptions(G,S,Scope),
-
- %% Check if it is an operation denoted
- case isOperation(S,Scope) of
- %% Yes, check options
- true ->
- %% Look if there is a specific code option on top file
- case hasSpecificCodeoptionOnTopFile(S,ic_genobj:idlfile(G),Scope) of
- true ->
- %% Yes, let it work
- getBrokerData(G,S,X,Scope,[Scope],[]);
- false ->
- %% No, try to see if there is codeoption on top file
- case hasNonSpecificCodeoptionOnTopFile(S,ic_genobj:idlfile(G)) of
- true ->
- %% Yes, override every other specific code option
- [_H|T] = Scope,
- getBrokerData(G,S,X,Scope,[T],[]);
- false ->
- %% No, let inherited specific code options work
- getBrokerData(G,S,X,Scope,[Scope],[])
- end
- end;
- %% No, continue
- false ->
- getBrokerData(G,S,X,Scope,[Scope],[])
- end.
-
-%% Returns a tuple / list of tuples { Mod, Type }
-%% Inside loop, uses overridence.
-getBrokerData(G,X,RS,Scope,CSF) ->
- S = ic_genobj:pragmatab(G),
- cleanup_codeOptions(G,S,Scope),
- OvScope = overridedFrom(S,RS,Scope),
- getBrokerData(G,S,X,RS,[OvScope],[OvScope|CSF]).
-
-
-
-getBrokerData(G,S,X,RS,[[[First]|Rest]],CSF) when is_integer(First) ->
- Scope = [[First]|Rest],
- case ets:match(S,{codeopt,Scope,'$1','_','_','_'}) of
- [] ->
- case ets:match(S,{inherits,Scope,'$1'}) of
- [] -> %% No inheritence, no pragma codeopt
- defaultBrokerData(G); %% Default
- [InhScope] ->
- getBrokerData(G,S,X,RS,InhScope,CSF);
- InhList ->
- getBrokerDataInh(G,S,X,RS,Scope,CSF,InhList)
- end;
- [[{broker,{Module,Type}}]] -> %% A branch only, with pragma codeopt
- {Module,Type};
- List -> %% Multiple branches with pragma codeopt
- flatten(List)
- end;
-
-getBrokerData(G,S,X,RS,[[[First]|Rest]],CSF) ->
- getBrokerDataLoop(G,S,X,RS,[[First]|Rest],CSF);
-
-getBrokerData(G,S,X,RS,[Scope],CSF) ->
- %io:format(" 1"),
- case ets:match(S,{codeopt,Scope,'$1','_','_','_'}) of
- [] ->
- %io:format(" 2"),
- case ets:match(S,{inherits,Scope,'$1'}) of
- [] -> %% No inheritence, no pragma codeopt
- %io:format(" 5"),
- defaultBrokerData(G); %% Default
- [InhScope] ->
- %io:format(" 6"),
- getBrokerData(G,S,X,RS,InhScope,CSF);
- InhList ->
- %io:format(" 7"),
- getBrokerDataInh(G,S,X,RS,Scope,CSF,InhList)
- end;
- [[{broker,{Module,Type}}]] -> %% A branch only, with pragma codeopt
- %io:format(" 3"),
- {Module,Type};
- List -> %% Multiple branches with pragma codeopt
- %io:format(" 4"),
- flatten(List)
- end.
-
-
-%% Special treatment when X is an operation
-getBrokerDataInh(G,S,X,RS,Scope,CSF,InhList) when is_record(X,op)->
- %io:format(" 8"),
- case ets:match(S,{op,get_id2(X),'$1','_','_'}) of
- [] ->
- %io:format(" 10"),
- CleanList = remove_inherited(S,InhList),
- getBrokerDataLoop(G,S,X,RS,CleanList,CSF);
-
- [[Scope]] ->
- %io:format(" 11"),
- CleanList = remove_inherited(S,InhList),
- getBrokerDataLoop(G,S,X,RS,CleanList,CSF);
-
- [[OpScope]] ->
- %io:format(" 12"),
- case member([OpScope],InhList) of
- true ->
- %io:format(" 14"),
- %% No inherited scopes
- getBrokerData(G,X,RS,OpScope,CSF);
- false ->
- %io:format(" 15"),
- %% Inherited scopes
- CleanList = remove_inherited(S,InhList),
- getBrokerDataLoop(G,S,X,RS,CleanList,CSF)
- end;
-
- ListOfOpScopes ->
- %io:format(" 13"),
- case get_inherited(S,Scope,ListOfOpScopes) of
- [[OpScope]] ->
- case member([OpScope],InhList) of
- true ->
- getBrokerData(G,X,RS,OpScope,CSF);
- false ->
- CleanList = remove_inherited(S,InhList),
- getBrokerDataLoop(G,S,X,RS,CleanList,CSF)
- end;
- _ ->
- CleanList = remove_inherited(S,InhList),
- getBrokerDataLoop(G,S,X,RS,CleanList,CSF)
- end
- end;
-%% Just add InhList after removing all inherited
-getBrokerDataInh(G,S,X,RS,_Scope,CSF,InhList) ->
- %io:format(" 9"),
- CleanList = remove_inherited(S,InhList),
- getBrokerDataLoop(G,S,X,RS,CleanList,CSF).
-
-
-
-
-%% Loops over a list of scopes
-getBrokerDataLoop(G,S,X,RS,List,CSF) ->
- getBrokerDataLoop(G,S,X,RS,List,[],CSF).
-
-getBrokerDataLoop(G,_,_X,_RS,[],BrokerDataList,_CSF) ->
- case no_doubles(BrokerDataList) of
- [BrokerData] -> %% No pragma codeopt / Multiple branches with pragma codeopt
- BrokerData;
- List ->
- DefaultBD = defaultBrokerData(G),
- case member(DefaultBD,List) of
- true ->
- %% Remove default, choose codeoption
- NewList = delete(DefaultBD,List),
- case NewList of
- [BData] -> %% A branch only, with pragma codeopt
- BData;
- _Other -> %% Multiple branches with pragma codeopt
- %%io:format("Multiple branches ~p~n",[Other]),
- NewList
- end;
- false -> %% Multiple branches with pragma codeopt
- flatten(List)
- end
- end;
-
-getBrokerDataLoop(G,S,X,RS,[[Scope]|Scopes],_Found,CSF) when is_integer(Scope) ->
- getBrokerData(G,S,X,RS,[[Scope]|Scopes],CSF);
-
-getBrokerDataLoop(G,S,X,RS,[[Scope]|Scopes],Found,CSF) ->
- %% Start from the beginning, check for overridings
- case member(overridedFrom(S,RS,Scope),CSF) of %% Avoid infinite loops
- true ->
- getBrokerDataLoop(G,S,X,RS,Scopes,Found,CSF);
- false ->
- BrokerData = getBrokerData(G,X,RS,Scope,CSF),
- getBrokerDataLoop(G,S,X,RS,Scopes,[BrokerData|Found],[Scope|CSF])
- end.
-
-
-
-
-%%%--------------------------------------
-%%% Finds out the overrider of a scope
-%%%--------------------------------------
-overridedFrom(S,RS,Scope) ->
- overridedFrom(S,RS,Scope,Scope).
-
-overridedFrom(S,RS,Last,Scope) ->
- case ets:match(S,{inherits,'$0',Scope}) of
- [] ->
- %% No inheritence, no pragma codeopt,
- %% choose the last scope.
- Last;
-
- [[RS]] ->
- %% Garbage, unused interface with pragma
- %% code option ! Danger !
- Last;
-
- [[InhScope]] ->
- case ets:match(S,{codeopt,InhScope,'$1','_','_','_'}) of
- [] ->
- %% InhScope has no code options, keep Last.
- overridedFrom(S,RS,Scope,InhScope);
- _ ->
- %% InhScope has code option, Last = InhScope.
- overridedFrom(S,RS,InhScope,InhScope)
- end;
- List ->
- %% Several inherit from Scope, choose the one feeseble,
- %% the one DIRECTLY inherited by Scope and not through
- %% other interface.
- case remove_inheriters(S,RS,List) of
- [] ->
- Scope;
- Removed ->
- Removed
- end
- end.
-
-%%%------------------------------------------------------
-%%% Removes all the scopes that inherit from others
-%%%------------------------------------------------------
-remove_inheriters(S,RS,InheriterList) ->
- DominantList =
- dominantList(S,InheriterList),
- ReducedInhList =
- [X || X <- InheriterList,
- member(X,DominantList)],
-
- case ReducedInhList of
- [] ->
- [];
- [_OneOnly] ->
- ReducedInhList;
- _Other ->
- CleanList =
- ets:match_object(S, {inherits,'_','_'}),
-% CodeOptList =
-% [X || X <- EtsList, element(1,X) == codeopt],
- NoInheriters =remove_inheriters2(S,ReducedInhList,CleanList),
-
- [ [X] || [X] <- NoInheriters,
- inherits(RS,X,CleanList)]
- end.
-
-remove_inheriters2(_,[A],_) ->
- [A];
-remove_inheriters2(_S,[A,B],EtsList) ->
- case remove_inh(A,B,[A,B],EtsList) of
- [[X]] ->
- X;
- List ->
- List
- end;
-remove_inheriters2(S,[A,B|Rest],EtsList) ->
- case remove_inh(A,B,[A,B|Rest],EtsList) of
- [A,B|Rest] ->
- [A,B|Rest];
- NewList ->
- remove_inheriters2(S,NewList,EtsList)
- end.
-
-remove_inh([X],[Y],List,EtsList) ->
- case inherits(X,Y,EtsList) of
- true ->
- delete([X],List);
- false ->
- case inherits(Y,X,EtsList) of
- true ->
- delete([Y],List);
- false ->
- List
- end
- end.
-
-
-
-%%%----------------------------------------------
-%%% Should remove all scope links that inherit
-%%% from others in the list
-%%%----------------------------------------------
-remove_inherited(S,InheriterList) ->
- CleanList =
- ets:match_object(S, {inherits, '_', '_'}),
- remove_inherited(S,InheriterList,CleanList).
-
-
-remove_inherited(_S,[A,B],EtsList) ->
- case remove_inhed(A,B,[A,B],EtsList) of
- [[X]] ->
- [[X]];
- List ->
- List
- end;
-remove_inherited(S,[A,B|Rest],EtsList) ->
- case remove_inhed(A,B,[A,B|Rest],EtsList) of
- [A,B|Rest] ->
- [A,B|Rest];
- NewList ->
- remove_inherited(S,NewList,EtsList)
- end.
-
-
-remove_inhed([X],[Y],List,EtsList) ->
- case inherits(X,Y,EtsList) of
- true ->
- delete([Y],List);
- false ->
- case inherits(Y,X,EtsList) of
- true ->
- delete([X],List);
- false ->
- List
- end
- end.
-
-
-
-
-
-
-
-%%%----------------------------------------------
-%%% Should return all scope links that is
-%% are inherited from scope in the list
-%%%----------------------------------------------
-get_inherited(S,Scope,OpScopeList) ->
- EtsList1 = ets:match(S, {inherits, Scope, '$1'}),
- [X || X <- EtsList1, member(X, OpScopeList)].
-
-
-
-
-
-
-
-%%%---------------------------------------------------
-%%% Returns a the list of scopes that have codeoption
-%%% from a list of scopes
-%%%---------------------------------------------------
-dominantList(S,IL) ->
- dominantList(S,IL,[]).
-
-dominantList(_S,[],Found) ->
- Found;
-dominantList(S,[[X]|Xs],Found) ->
- case ets:match(S,{codeopt,X,'$1','_','_','_'}) of
- [] ->
- dominantList(S,Xs,Found);
- _ ->
- dominantList(S,Xs,[[X]|Found])
- end.
-
-
-
-
-%%%---------------------------------------------------
-%%% Returns true if X direct or indirect inherits Y
-%%%---------------------------------------------------
-inherits(X,Y,EtsList) ->
- case member({inherits,X,Y},EtsList) of
- true ->
- %% Direct inherited
- true;
- false ->
- %% Indirectly inherited
- AllInh = [ B || {inherits,A,B} <- EtsList, A == X ],
- inherits(X,Y,AllInh,EtsList)
- end.
-
-inherits(_X,_Y,[],_EtsList) ->
- false;
-inherits(X,Y,[Z|Zs],EtsList) ->
- case inherits2(X,Y,Z,EtsList) of
- true ->
- true;
- false ->
- inherits(X,Y,Zs,EtsList)
- end.
-
-inherits2(_X,Y,Z,EtsList) ->
- case member({inherits,Z,Y},EtsList) of
- true ->
- true;
- false ->
- inherits(Z,Y,EtsList)
- end.
-
-
-
-%%
-%% is_inherited_by/3
-%%
-%% Returns :
-%%
-%% true if the first parameter is
-%% inherited by the second one
-%%
-%% false otherwise
-%%
-is_inherited_by(Interface1,Interface2,PragmaTab) ->
- InheritsList = ets:match_object(PragmaTab, {inherits, '_', '_'}),
- inherits(Interface2,Interface1,InheritsList).
-
-
-
-
-%% Filters all pragma prefix from list not in same file
-%% the object
-
-filter_pragma_prefix_list(PragmaTab, Name, Scope, List) ->
- IdlFile = scoped_names_idl_file(PragmaTab, Name, Scope),
- filter_pragma_prefix_list2(PragmaTab,IdlFile,List,[]).
-
-
-filter_pragma_prefix_list2(_,_,[],Found) ->
- Found;
-filter_pragma_prefix_list2(PT, IdlFile, [PP|PPs], Found) ->
- case PP of
- {prefix,_,_,_,IdlFile,_} -> %% Same file as the Object, keep
- filter_pragma_prefix_list2(PT, IdlFile, PPs, [PP|Found]);
-
- _Other -> %% NOT in same file as the Object, throw away
- filter_pragma_prefix_list2(PT, IdlFile, PPs, Found)
- end.
-
-scoped_names_idl_file(PragmaTab, Name, Scope) ->
- case ets:match(PragmaTab,{'_','$0','_','$2',Scope,Name,'_','_','_'}) of
- [[IdlFile, _Type]] -> %% Usual case
- IdlFile;
- [[_File,module]|_Files] -> %% Multiple modules, get LOCAL file
- case ets:match(PragmaTab,{file_data_local,'$0','_',module,Scope,Name,'_','_','_'}) of
- [[LocalIdlFile]] ->
- LocalIdlFile;
- _ -> %% Should NEVER occur
- error
- end;
-
- _ ->
- error %% Should NEVER occur
- end.
-
-
-
-
-
-
-%%-------------------------------------------------
-%%
-%% Register specific pragma code options
-%%
-%% If there is an operation with that
-%% scope, denote this as {codeopt_specific,Scope}
-%%
-%%-------------------------------------------------
-denote_specific_code_opts(G) ->
- case ic_options:get_opt(G, be) of
- noc ->
- S = ic_genobj:pragmatab(G),
- COList = ets:match(S,{codeopt,'$0','_','_','_','_'}),
- OPList = ets:match(S,{op,'$0','$1','_','_'}),
- denote_specific_code_opts(S,COList,OPList);
- _ ->
- ok
- end.
-
-denote_specific_code_opts(_,_,[]) ->
- ok;
-denote_specific_code_opts(S,COList,[[OpN,OpS]|OPSs]) ->
- case lists:member([[OpN|OpS]],COList) of
- true ->
- insert(S, {codeopt_specific,[OpN|OpS]});
- false ->
- ok
- end,
- denote_specific_code_opts(S,COList,OPSs).
-
-
-
-%%---------------------------------------------
-%%
-%% Returns true/false if it denotes an operation
-%%
-%%---------------------------------------------
-isOperation(_S,[]) ->
- false;
-isOperation(_S,[_]) ->
- false;
-isOperation(S,[H|T]) ->
- case ets:match(S,{op,H,T,'$2','$3'}) of
- [] ->
- false;
- _ ->
- true
- end.
-
-
-hasSpecificCodeoptionOnTopFile(S,File,Scope) ->
- case ets:match(S,{codeopt,Scope,'_','$2',File,[File]}) of
- [] ->
- false;
- _ ->
- true
- end.
-
-
-hasNonSpecificCodeoptionOnTopFile(S,File) ->
- case ets:match(S,{codeopt,'_','_','$2',File,[File]}) of
- [] ->
- false;
- _ ->
- true
- end.
-
-
-
-%%---------------------------------------------
-%%
-%% Returns {ok,IfrId}/error when searching a random local type
-%%
-%%---------------------------------------------
-
-
-fetchRandomLocalType(G) ->
-
- S = ic_genobj:pragmatab(G),
-
- case ets:match(S,{file_data_local,'_','_','$2','$3','$4','_','_','_'}) of
- [] ->
- false;
-
- List ->
- fetchRandomLocalType(S,List)
- end.
-
-
-fetchRandomLocalType(_,[]) ->
- false;
-fetchRandomLocalType(S,[[module|_]|Tail]) ->
- fetchRandomLocalType(S,Tail);
-fetchRandomLocalType(S,[[_,Scope,Name]|Tail]) ->
- case ets:match(S,{alias,[Name|Scope],'$1'}) of
- [] ->
- fetchRandomLocalType(S,Tail);
- [[IfrId]] ->
- {ok,IfrId}
- end.
-
-
-
-%%---------------------------------------------
-%%
-%% Returns A list of local operation mapping
-%% for a given scope
-%%
-%%---------------------------------------------
-
-
-fetchLocalOperationNames(G,I) ->
- S = ic_genobj:pragmatab(G),
- case ets:match(S,{file_data_local,'_','_',op,I,'$4','_','_','_'}) of
- [] ->
- [];
- List ->
- fetchLocalOperationNames2(List,[])
- end.
-
-fetchLocalOperationNames2([],Found) ->
- lists:reverse(Found);
-fetchLocalOperationNames2([[Name]|Names],Found) ->
- fetchLocalOperationNames2(Names,[Name|Found]).
-
-
-
-%%------------------------------------------------
-%%
-%% Returns a true if this scoped id is a local
-%% one, false otherwise
-%%
-%%------------------------------------------------
-is_local(G,ScopedId) ->
- S = ic_genobj:pragmatab(G),
- Name = ic_util:to_undersc(ScopedId),
- case ets:match(S,{file_data_local,'_','_','_',tl(ScopedId),'_',Name,'_','_'}) of
- [[]] ->
- true;
- _ ->
- false
- end.
diff --git a/lib/ic/src/ic_sequence_java.erl b/lib/ic/src/ic_sequence_java.erl
deleted file mode 100644
index f4873a0691..0000000000
--- a/lib/ic/src/ic_sequence_java.erl
+++ /dev/null
@@ -1,240 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ic_sequence_java).
-
-
--include("icforms.hrl").
--include("ic.hrl").
--include("ic_debug.hrl").
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([gen/4]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% Func: gen/4
-%%-----------------------------------------------------------------
-gen(G, N, X, SequenceName) when is_record(X, sequence) ->
- emit_holder_class(G, N, X, SequenceName),
- emit_helper_class(G, N, X, SequenceName);
-gen(_G, _N, _X, _SequenceName) ->
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-
-
-%%-----------------------------------------------------------------
-%% Func: emit_holder_class/4
-%%-----------------------------------------------------------------
-emit_holder_class(G, N, X, SequenceName) ->
- SName = string:concat(SequenceName, "Holder"),
- {Fd, _}= ic_file:open_java_file(G, N, SName),
-
- SequenceType = ic_java_type:getType(G, N, X),
-
- ic_codegen:emit(Fd, ["final public class ",SequenceName,"Holder {\n"
- " // instance variables\n"
- " public ",SequenceType," value;\n\n"
- " // constructors\n"
- " public ",SequenceName,"Holder() {}\n"
- " public ",SequenceName,"Holder(",SequenceType," initial) {\n"
- " value = initial;\n"
- " }\n\n"
-
- " // methods\n"
-
- " public void _marshal(",?ERLANGPACKAGE,"OtpOutputStream out) throws java.lang.Exception{\n"
- " ",SequenceName,"Helper.marshal(out, value);\n"
- " }\n\n"
-
- " public void _unmarshal(",?ERLANGPACKAGE,"OtpInputStream in) throws java.lang.Exception {\n"
- " value = ",SequenceName,"Helper.unmarshal(in);\n"
- " }\n\n"
- "}\n"]),
- file:close(Fd).
-
-
-
-emit_helper_class(G, N, X, SequenceName) ->
- SName = string:concat(SequenceName, "Helper"),
- {Fd, _}= ic_file:open_java_file(G, N, SName),
-
- SequenceType = ic_java_type:getType(G, N, X),
- ElementType = ic_forms:get_type(X),
-
- ic_codegen:emit(Fd, ["public class ",SequenceName,"Helper {\n"
-
- " // constructors\n"
- " private ",SequenceName,"Helper() {}\n\n"
-
- " // methods\n"
- " public static void marshal(",?ERLANGPACKAGE,"OtpOutputStream _out, ",SequenceType," _value) \n"
- " throws java.lang.Exception {\n\n"]),
-
- emit_sequence_marshal_function(G, N, X, Fd, SequenceName, ElementType),
-
- ic_codegen:emit(Fd, [" }\n\n"
-
- " public static ",SequenceType," unmarshal(",?ERLANGPACKAGE,"OtpInputStream _in) \n"
- " throws java.lang.Exception {\n\n"]),
-
- emit_sequence_unmarshal_function(G, N, X, Fd, SequenceName, ElementType),
-
- ic_codegen:emit(Fd, [" }\n\n"
-
- " public static String id() {\n"
- " return \"",ic_pragma:scope2id(G, [SequenceName | N]),"\";\n"
- " }\n\n"
-
- " public static String name() {\n"
- " return \"",SequenceName,"\";\n"
- " }\n\n"]),
-
- ic_jbe:emit_type_function(G, N, X, Fd),
-
- ic_codegen:emit(Fd, [" public static void insert(",?ICPACKAGE,"Any _any, ",SequenceType," _this)\n"
- " throws java.lang.Exception {\n\n"
-
- " ",?ERLANGPACKAGE,"OtpOutputStream _os = \n"
- " new ",?ERLANGPACKAGE,"OtpOutputStream();\n\n"
-
- " _any.type(type());\n"
- " marshal(_os, _this);\n"
- " _any.insert_Streamable(_os);\n"
- " }\n\n"
-
- " public static ",SequenceType," extract(",?ICPACKAGE,"Any _any)\n"
- " throws java.lang.Exception {\n\n"
-
- " return unmarshal(_any.extract_Streamable());\n"
- " }\n\n"
-
-
- %% In corba mapping there is also a _type function here.
- "}\n\n"]),
- file:close(Fd).
-
-
-%%-----------------------------------------------------------------
-%% Func: emit_sequence_marshal_function/6
-%%-----------------------------------------------------------------
-emit_sequence_marshal_function(G, N, X, Fd, _SequenceName, ElementType) ->
- ic_codegen:emit(Fd, [" int _length = _value.length;\n\n"
-
- " _out.write_list_head(_length);\n\n"
-
- " if (_length > 0) {\n"
- " for(int _tmp = 0; _tmp < _length; _tmp++)\n"]),
-
- case ic_java_type:isBasicType(G, N, ElementType) of
- true ->
- ic_codegen:emit(Fd, [" _out",ic_java_type:marshalFun(G, N, X, ElementType),"(_value[_tmp]);\n\n"]);
- false ->
- ic_codegen:emit(Fd, [" ",ic_java_type:marshalFun(G, N, X, ElementType),"(_out, _value[_tmp]);\n\n"])
- end,
-
- ic_codegen:emit(Fd, [" _out.write_nil();\n"
- " }\n\n"]).
-
-
-
-
-%%-----------------------------------------------------------------
-%% Func: emit_sequence_unmarshal_function/6
-%%-----------------------------------------------------------------
-emit_sequence_unmarshal_function(G, N, X, Fd, _SequenceName, ElementType) ->
-
- SequenceElementType = ic_java_type:getType(G, N, ElementType),
-
- ic_codegen:emit(Fd, [" int _tag,_length;\n"
- " ",SequenceElementType," _sequence[];\n"
- " _tag = _in.peek();\n\n"]),
-
- case ic_java_type:isIntegerType(G, N, ElementType) of
- true ->
- ic_codegen:emit(Fd, [" switch(_tag) {\n"
- " case ",?ERLANGPACKAGE,"OtpExternal.stringTag:\n"
- " byte _compressed[] = (_in.read_string()).getBytes();\n"
- " _length = _compressed.length;\n"
- " _sequence = new ",ic_java_type:getFullType(G,N,X),";\n\n"
-
- " for(int _tmp = 0; _tmp < _length; _tmp++)\n"
- " _sequence[_tmp] = (",ic_java_type:getType(G, N, ElementType),")(_compressed[_tmp] & 0xff);\n\n"
-
- " break;\n"
- " default:\n"
- " _length = _in.read_list_head();\n"
- " _sequence = new ",ic_java_type:getFullType(G,N,X),";\n\n"
-
- " if(_length > 0) {\n"
- " for(int _tmp = 0; _tmp < _length; _tmp++)\n"
- " _sequence[_tmp] = _in",ic_java_type:unMarshalFun(G, N, X, ElementType),";\n\n"
-
- " _in.read_nil();\n"
- " }\n"
- " }\n"]);
- false ->
- ic_codegen:emit(Fd, [" _length = _in.read_list_head();\n"
- " _sequence = new ",ic_java_type:getFullType(G,N,X),";\n\n"
-
- " if(_length > 0) {\n"
- " for(int _tmp = 0; _tmp < _length; _tmp++)\n"]),
- case ic_java_type:isBasicType(G, N, ElementType) of
- true ->
- ic_codegen:emit(Fd, [" _sequence[_tmp] = _in",ic_java_type:unMarshalFun(G, N, X, ElementType),";\n\n"]);
- _ ->
- ic_codegen:emit(Fd, [" _sequence[_tmp] = ",ic_java_type:getUnmarshalType(G, N, X, ElementType),".unmarshal(_in);\n\n"])
- end,
-
- ic_codegen:emit(Fd, [" _in.read_nil();\n"
- " }\n\n"])
- end,
-
- ic_codegen:emit(Fd, " return _sequence;\n").
-
-
-
-
-%%---------------------------------------------------
-%% Utilities
-%%---------------------------------------------------
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/src/ic_struct_java.erl b/lib/ic/src/ic_struct_java.erl
deleted file mode 100644
index 94b98f6c52..0000000000
--- a/lib/ic/src/ic_struct_java.erl
+++ /dev/null
@@ -1,315 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ic_struct_java).
-
--include("icforms.hrl").
--include("ic.hrl").
--include("ic_debug.hrl").
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([gen/3]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-gen(G, N, X) when is_record(X, struct) ->
- StructName = ic_forms:get_java_id(X),
- WireStructName = ic_forms:get_id2(X),
- emit_struct_class(G, N, X, StructName),
- emit_holder_class(G, N, X, StructName),
- emit_helper_class(G, N, X, StructName, WireStructName),
- N2 = [StructName ++ "Package" |N],
- ic_jbe:gen(G, N2, ic_forms:get_body(X));
-gen(_G, _N, _X) ->
- ok.
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% Func: emit_struct_class/4
-%%-----------------------------------------------------------------
-emit_struct_class(G, N, X, StructName) ->
- {Fd, _}= ic_file:open_java_file(G, N, StructName),
-
- MList = struct_member_list(G, N, X),
- ArgList = gen_parameter_list(G, [ StructName ++ "Package" |N], X, MList),
-
- ic_codegen:emit(Fd, ["final public class ",StructName," {\n"
- " // instance variables\n"]),
-
- emit_struct_members_declarations(G, [StructName ++ "Package" |N],
- X, Fd, MList),
-
- ic_codegen:emit(Fd, ["\n // constructors\n"
- " public ",StructName,"() {}\n\n"
-
- " public ",StructName,"(",ArgList,") {\n"]),
-
- emit_struct_members_initialisation(G, N, X, Fd, MList),
-
- ic_codegen:emit(Fd, [" }\n\n"
-
- "}\n\n"]),
- file:close(Fd).
-
-
-%%-----------------------------------------------------------------
-%% Func: emit_holder_class/4
-%%-----------------------------------------------------------------
-emit_holder_class(G, N, _X, StructName) ->
- SName = string:concat(StructName, "Holder"),
- {Fd, _}= ic_file:open_java_file(G, N, SName),
-
- ic_codegen:emit(Fd, ["final public class ",StructName,"Holder {\n"
-
- " // instance variables\n"
- " public ",StructName," value;\n\n"
-
- " // constructors\n"
- " public ",StructName,"Holder() {}\n\n"
-
- " public ",StructName,"Holder(",StructName," initial) {\n"
- " value = initial;\n"
- " }\n\n"
-
- " // methods\n"]),
-
- ic_codegen:emit(Fd, [" public void _marshal(",?ERLANGPACKAGE,"OtpOutputStream out) throws java.lang.Exception {\n"
- " ",StructName,"Helper.marshal(out, value);\n"
- " }\n\n"
-
- " public void _unmarshal(",?ERLANGPACKAGE,"OtpInputStream in) throws java.lang.Exception {\n"
- " value = ",StructName,"Helper.unmarshal(in);\n"
- " }\n"
-
- "}\n\n"]),
- file:close(Fd).
-
-%%-----------------------------------------------------------------
-%% Func: emit_helper_class/5
-%%-----------------------------------------------------------------
-emit_helper_class(G, N, X, StructName, WireStructName) ->
- SName = string:concat(StructName, "Helper"),
- {Fd, _}= ic_file:open_java_file(G, N, SName),
-
- ic_codegen:emit(Fd, ["public class ",StructName,"Helper {\n"
-
- " // constructors\n"
- " private ",StructName,"Helper() {}\n\n"
-
- " // methods\n"]),
-
- MList = struct_member_list(G, N, X),
-
- ic_codegen:emit(Fd, [" public static void marshal(",?ERLANGPACKAGE,"OtpOutputStream _out, ",StructName," _value)\n"
- " throws java.lang.Exception {\n\n"]),
-
- emit_struct_marshal_function(G, N, X, Fd, StructName, WireStructName, MList),
-
- ic_codegen:emit(Fd, [" }\n\n"
-
- " public static ",StructName," unmarshal(",?ERLANGPACKAGE,"OtpInputStream _in)\n"
- " throws java.lang.Exception {\n\n"]),
-
- emit_struct_unmarshal_function(G, N, X, Fd, StructName, WireStructName, MList),
-
- ic_codegen:emit(Fd, [" }\n\n"
-
- " public static String id() {\n"
- " return \"",ictk:get_IR_ID(G, N, X),"\";\n"
- " }\n\n"
-
- " public static String name() {\n"
- " return \"",StructName,"\";\n"
- " }\n\n"]),
-
- ic_jbe:emit_type_function(G, N, X, Fd),
-
- ic_codegen:emit(Fd, [" public static void insert(",?ICPACKAGE,"Any _any, ",StructName," _this)\n"
- " throws java.lang.Exception {\n\n"
-
- " ",?ERLANGPACKAGE,"OtpOutputStream _os = \n"
- " new ",?ERLANGPACKAGE,"OtpOutputStream();\n\n"
-
- " _any.type(type());\n"
- " marshal(_os, _this);\n"
- " _any.insert_Streamable(_os);\n"
- " }\n\n"
-
- " public static ",StructName," extract(",?ICPACKAGE,"Any _any)\n"
- " throws java.lang.Exception {\n\n"
-
- " return unmarshal(_any.extract_Streamable());\n"
- " }\n\n"
-
-
- %% In corba mapping there is also a _type function here.
- "}\n"]),
- file:close(Fd).
-
-
-%%-----------------------------------------------------------------
-%% Func: emit_struct_members_declarations/
-%%-----------------------------------------------------------------
-emit_struct_members_declarations(_, _, _, _, []) ->
- ok;
-emit_struct_members_declarations(G, N, X, Fd, [{Member, _Type, Id} | MList]) ->
- ic_codegen:emit(Fd, [" public ",ic_java_type:getType(G, N, Member)," ",Id,";\n"]),
- emit_struct_members_declarations(G, N, X, Fd, MList).
-
-
-
-%%-----------------------------------------------------------------
-%% Func: emit_struct_members_initialisation/5
-%%-----------------------------------------------------------------
-emit_struct_members_initialisation(_, _, _, _, []) ->
- ok;
-emit_struct_members_initialisation(G, N, X, Fd, [{_Member, _Type, Id} | MList]) ->
- ic_codegen:emit(Fd, [" ",Id," = _",Id,";\n"]),
- emit_struct_members_initialisation(G, N, X, Fd, MList).
-
-
-
-
-%%-----------------------------------------------------------------
-%% Func: emit_struct_marshal_function/7
-%%-----------------------------------------------------------------
-emit_struct_marshal_function(G, N, X, Fd, StructName, WireStructName, MList) ->
-
- ic_codegen:emit(Fd, [" _out.write_tuple_head(",integer_to_list(length(MList) + 1),");\n"
- " _out.write_atom(\"",ic_util:to_undersc([WireStructName|N]),"\");\n\n"]),
-
- emit_struct_marshal_function_loop(G, [StructName ++ "Package" |N],
- X, Fd, MList, 1).
-
-%%-----------------------------------------------------------------
-%% Func: emit_struct_marshal_function_loop/6
-%%-----------------------------------------------------------------
-emit_struct_marshal_function_loop(_, _, _, Fd, [], _) ->
- ic_codegen:nl(Fd);
-emit_struct_marshal_function_loop(G, N, X, Fd, [{Member, Type, Id} |MList], Num) ->
-
- case ic_java_type:isBasicType(G, N, Member) of
- true ->
- ic_codegen:emit(Fd, [" _out",ic_java_type:marshalFun(G, N, Member, Type),"(_value.",Id,");\n"]);
- _ ->
- if (element(1,hd(element(3,Member))) == array) ->
- ic_codegen:emit(Fd,
- [" ",
- ic_util:to_dot(G,[ic_forms:get_id2(Member)|N]),
- "Helper.marshal(_out, _value.",Id,");\n"]);
- true ->
- ic_codegen:emit(Fd, [" ",
- ic_java_type:marshalFun(G, N, Member, Type),
- "(_out, _value.",Id,");\n"])
- end
- end,
-
- emit_struct_marshal_function_loop(G, N, X, Fd, MList, Num+1).
-
-
-
-
-%%-----------------------------------------------------------------
-%% Func: emit_struct_unmarshal_function/7
-%%-----------------------------------------------------------------
-emit_struct_unmarshal_function(G, N, X, Fd, StructName, WireStructName, MList) ->
-
- ic_codegen:emit(Fd, [" _in.read_tuple_head();\n\n"
-
- " if ((_in.read_atom()).compareTo(\"",
- ic_util:to_undersc([WireStructName|N]),
- "\") != 0)\n"
- " throw new java.lang.Exception(\"\");\n\n"
-
- " ",StructName," _value = new ",StructName,"();\n"]),
-
- emit_struct_unmarshal_function_loop(G, [StructName ++ "Package"|N],
- X, Fd, MList, 1),
-
- ic_codegen:emit(Fd, " return _value;\n").
-
-%%-----------------------------------------------------------------
-%% Func: emit_union_unmarshal_function_loop/6
-%%-----------------------------------------------------------------
-emit_struct_unmarshal_function_loop(_, _, _, Fd, [], _) ->
- ic_codegen:nl(Fd);
-emit_struct_unmarshal_function_loop(G, N, X, Fd, [{Member, Type, Id} |MList], Num) ->
-
- case ic_java_type:isBasicType(G, N, Member) of
- true ->
- ic_codegen:emit(Fd, [" _value.",Id," = _in",ic_java_type:unMarshalFun(G, N, Member, Type),";\n"]);
- _ ->
- if (element(1,hd(element(3,Member))) == array) ->
- ic_codegen:emit(Fd,
- [" _value.",Id," = ",ic_util:to_dot(G,[ic_forms:get_id2(Member)|N]),"Helper.unmarshal(_in);\n"]);
- true ->
- ic_codegen:emit(Fd,
- [" _value.",Id," = ",ic_java_type:getUnmarshalType(G, N, Member, Type),".unmarshal(_in);\n"])
- end
- end,
-
- emit_struct_unmarshal_function_loop(G, N, X, Fd, MList, Num +1).
-
-
-
-%%-----------------------------------------------------------------
-%% Func: gen_parameter_list/4
-%%-----------------------------------------------------------------
-gen_parameter_list(G, N, _X, [{Member, _Type, Id}]) ->
- ic_java_type:getType(G,N,Member) ++
- " _" ++
- ic_util:to_list(Id);
-gen_parameter_list(G, N, X, [{Member, _Type, Id} | MList]) ->
- ic_java_type:getType(G,N,Member) ++
- " _" ++
- ic_util:to_list(Id) ++
- ", " ++
- gen_parameter_list(G, N, X, MList).
-
-
-%%-----------------------------------------------------------------
-%% Func: struct_member_list/3
-%%-----------------------------------------------------------------
-struct_member_list(_G, _N, X) ->
- M = lists:map(
- fun(Member) ->
- lists:map(
- fun(Id) ->
- Type = ic_forms:get_type(Member),
- { Member, Type, ic_forms:get_java_id(Id)}
- end,
- ic_forms:get_idlist(Member))
- end,
- ic_forms:get_body(X)),
- lists:flatten(M).
-
-
-
diff --git a/lib/ic/src/ic_symtab.erl b/lib/ic/src/ic_symtab.erl
deleted file mode 100644
index 037d004049..0000000000
--- a/lib/ic/src/ic_symtab.erl
+++ /dev/null
@@ -1,235 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ic_symtab).
-
-
--include_lib("ic/src/ic.hrl").
--include_lib("ic/src/icforms.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([new/0, store/3, retrieve/2, soft_retrieve/2, intf_resolv/3]).
--export([get_full_scoped_name/3, scoped_id_new_global/1, scoped_id_new/1]).
--export([scoped_id_strip/1,symtab_add_faked_included_types/1]).
--export([scoped_id_is_global/1, scoped_id_add/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-
-
-%%--------------------------------------------------------------------
-%%
-%% Symbol table routines
-%%
-%% Symbol tables handles mappings Id -> Value, where Id is an
-%% ordinary Id from the parser (or a string) and value is an
-%% arbitrary term.
-%%
-%%--------------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% Func: new/0 (used to be symtab_new)
-%%-----------------------------------------------------------------
-new() ->
- ets:new(symtab, [set, public]).
-
-%%-----------------------------------------------------------------
-%% Func: store/3 (used to be symtab_store)
-%%-----------------------------------------------------------------
-store(G, N, X) ->
- Name = [ic_forms:get_id2(X) | N],
- %%io:format("Adding id: ~p~n", [N]),
- case soft_retrieve(G, Name) of
- {error, _} ->
- ets:insert(G#genobj.symtab, {Name, X});
- {ok, Y} when is_record(Y, forward) ->
- ets:insert(G#genobj.symtab, {Name, X});
- {ok, Y} when is_record(Y, constr_forward) ->
- ets:insert(G#genobj.symtab, {Name, X});
- {ok, _Y} ->
- ic_error:error(G, {multiply_defined, X})
- end.
-
-
-%%-----------------------------------------------------------------
-%% Func: retrieve/2 (used to be symtab_retrieve)
-%%
-%% Makes a lookup in the symbol table for Id. Will throw
-%% not_found if it fails.
-%%-----------------------------------------------------------------
-retrieve(G, Id) ->
- case ets:lookup(G#genobj.symtab, Id) of
- [{_, Val}] -> Val;
- [] -> ic_error:error(G, {symtab_not_found, Id})
- end.
-
-
-%%-----------------------------------------------------------------
-%% Func: soft_retrieve/2 (used to be symtab_soft_retrieve)
-%%
-%% Same as retrieve but will use tagged return values.
-%%
-%%-----------------------------------------------------------------
-soft_retrieve(G, Id) ->
- case ets:lookup(G#genobj.symtab, Id) of
- [{_, Val}] -> {ok, Val};
- [] -> {error, {symtab_not_found, Id}}
- end.
-
-
-%%-----------------------------------------------------------------
-%% Func: intf_resolv/3 and resolv2/3
-%% (used to be symtab_intf_resolv and symtab_intf_resolv2)
-%%
-%% Tries to resolv the interface identifier reference. The id can
-%% be either a scoped name or an standard identifier. The
-%% function returns a global reference to the id.
-%%
-%% Will throw not_found if the id really cannot be found. Will
-%% throw illegal_forward if any forward references are founf in
-%% the inheritance list.
-%%
-%%-----------------------------------------------------------------
-intf_resolv(G, Scope, Id) ->
- case scoped_id_is_global(Id) of
- true ->
- retrieve(G, Id),
- Id;
- false ->
- intf_resolv2(G, Scope, Id)
- end.
-
-intf_resolv2(G, Scope, Id) ->
- N = scoped_id_add(Scope, Id),
- case soft_retrieve(G, scoped_id_strip(N)) of
- {ok, F} when is_record(F, forward) ->
- ic_error:error(G, {illegal_forward, Id}), [];
- {ok, _Val} ->
- scoped_id_mk_global(N);
- _ ->
- case scoped_id_is_top(Scope) of
- false ->
- intf_resolv2(G, scoped_id_up_one(Scope), Id);
- true ->
- ic_error:error(G, {symtab_not_found, Id}), []
- end
- end.
-
-
-
-%%--------------------------------------------------------------------
-%%
-%% Scoped id routines
-%%
-%% A scoped id is an id written as M::Id in IDL. Scoped ids are
-%% implemented as lists of id in reverse order, so M1::F1 becomes
-%% [F1, M1].
-%%
-%%--------------------------------------------------------------------
-
-get_full_scoped_name(G, N, S) when element(1, S) == scoped_id ->
- ictype:scoped_lookup(G, ic_genobj:tktab(G), N, S).
-
-scoped_id_new_global(Id) ->
- X=scoped_id_new(Id), X#scoped_id{type=global}.
-
-scoped_id_new(Id) ->
- #scoped_id{line=ic_forms:get_line(Id), id=[ic_forms:get_id(Id)]}.
-
-%% Adds one more id to the list of ids
-scoped_id_add(S1, S2) when is_record(S2, scoped_id) ->
- S1#scoped_id{id=S2#scoped_id.id ++ S1#scoped_id.id,
- line=S2#scoped_id.line};
-scoped_id_add(S, Id) ->
- S#scoped_id{id=[ic_forms:get_id(Id) | S#scoped_id.id], line=ic_forms:get_line(Id)}.
-
-
-scoped_id_mk_global(S) -> S#scoped_id{type=global}.
-
-scoped_id_is_global(S) when is_record(S, scoped_id), S#scoped_id.type==global ->
- true;
-scoped_id_is_global(_) -> false.
-
-%% Top level scope (i.e no more cd ..)
-scoped_id_is_top(S) when S#scoped_id.id==[] -> true;
-scoped_id_is_top(_) -> false.
-
-
-scoped_id_up_one(S) -> S#scoped_id{id=tl(S#scoped_id.id)}. % cd .. in scope
-%%scoped_id_get_def(S) -> hd(S#scoped_id.id). % Last added id
-scoped_id_strip(S) -> S#scoped_id.id. % Strips all junk
-
-
-
-
-% Add CORBA::<Types> that as if they
-% were defined in an included file.
-% This is only supported in the case
-% of Corba backend
-symtab_add_faked_included_types(G) ->
- case ic_options:get_opt(G, be) of
- false ->
- %% Add TypeCode as if it were defiend in included file
- ets:insert(G#genobj.symtab, {["CORBA"],
- {interface,{'<identifier>',0,"TypeCode"},
- [],
- [],
- [],
- {tk_objref,
- "IDL:omg.org/CORBA/TypeCode:1.0",
- "TypeCode"}}});
- erl_corba ->
- %% Add TypeCode as if it were defiend in included file
- ets:insert(G#genobj.symtab, {["CORBA"],
- {interface,{'<identifier>',0,"TypeCode"},
- [],
- [],
- [],
- {tk_objref,
- "IDL:omg.org/CORBA/TypeCode:1.0",
- "TypeCode"}}});
- erl_template ->
- %% Add TypeCode as if it were defiend in included file
- ets:insert(G#genobj.symtab, {["CORBA"],
- {interface,{'<identifier>',0,"TypeCode"},
- [],
- [],
- [],
- {tk_objref,
- "IDL:omg.org/CORBA/TypeCode:1.0",
- "TypeCode"}}});
- _ ->
- ok
- end.
-
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
diff --git a/lib/ic/src/ic_union_java.erl b/lib/ic/src/ic_union_java.erl
deleted file mode 100644
index 14d585b0a4..0000000000
--- a/lib/ic/src/ic_union_java.erl
+++ /dev/null
@@ -1,755 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-
--module(ic_union_java).
-
--include("icforms.hrl").
--include("ic.hrl").
--include("ic_debug.hrl").
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([gen/3]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% Func: gen/3
-%%-----------------------------------------------------------------
-gen(G, N, X) when is_record(X, union) ->
-
- %% Create a TK value if not existed
- %% Should be integrated in fetchTk
- %% instead
- NewX = case ic_forms:get_tk(X) of
- undefined ->
- S = ic_genobj:tktab(G),
- Tk = ictype:tk(G, S, N, X),
- #union{ id = X#union.id,
- type = X#union.type,
- body = X#union.body,
- tk = Tk };
- _Tk ->
- X
- end,
-
- UnionName = ic_forms:get_java_id(NewX),
- WiredUnionName = ic_forms:get_id2(NewX),
- N2 = [UnionName ++ "Package"|N],
- %%?PRINTDEBUG2("Recursive call over type ~p",
- %% [[ic_forms:get_type(NewX)]]),
- ic_jbe:gen(G, N, [ic_forms:get_type(NewX)]),
- %%?PRINTDEBUG2("Recursive call over body: ~p",
- %% [ic_forms:get_body(NewX)]),
- ic_jbe:gen(G, N2, ic_forms:get_body(NewX)),
-
- emit_union_class(G, N, NewX, UnionName),
- emit_holder_class(G, N, NewX, UnionName),
- emit_helper_class(G, N, NewX, UnionName, WiredUnionName);
-gen(_G, _N, _X) ->
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% Func: emit_union_class/4
-%%-----------------------------------------------------------------
-emit_union_class(G, N, X, UnionName) ->
- {Fd, _} = ic_file:open_java_file(G, N, UnionName),
-
- DiscrType = ic_java_type:getType(G, [UnionName ++ "Package"|N],
- ic_forms:get_type(X)),
-
- MList = union_member_list(G, N, X, DiscrType),
-
- ic_codegen:emit(Fd, "final public class ~s {\n",[UnionName]),
-
- ic_codegen:emit(Fd, " // instance variables\n", []),
- ic_codegen:emit(Fd, " private boolean _initialized;\n", []),
- ic_codegen:emit(Fd, " private ~s _discriminator;\n", [DiscrType]),
- ic_codegen:emit(Fd, " private java.lang.Object _value;\n", []),
-
- {tk_union,_, _,DiscrTk, _, _} = ic_forms:get_tk(X),
-
- DV = get_default_val(G, [UnionName |N], DiscrType, DiscrTk, MList),
-
- case DV of
- none -> %% all values in case
- ok;
- _ ->
- ic_codegen:emit(Fd, " private ~s _default = ~s;\n",
- [DiscrType, DV])
- end,
-
- ic_codegen:nl(Fd),
- ic_codegen:emit(Fd, " // constructors\n", []),
-
- ic_codegen:emit(Fd, " public ~s() {\n", [UnionName]),
- ic_codegen:emit(Fd, " _initialized = false;\n", []),
- ic_codegen:emit(Fd, " _value = null;\n", []),
- ic_codegen:emit(Fd, " }\n", []),
- ic_codegen:nl(Fd),
-
- ic_codegen:emit(Fd, " // discriminator access\n", []),
-
- ic_codegen:emit(Fd, " public ~s discriminator() "
- "throws java.lang.Exception {\n", [DiscrType]),
- ic_codegen:emit(Fd, " if (!_initialized) {\n", []),
- ic_codegen:emit(Fd, " throw new java.lang.Exception(\"\");\n",[]),
- ic_codegen:emit(Fd, " }\n", []),
- ic_codegen:emit(Fd, " return _discriminator;\n", []),
- ic_codegen:emit(Fd, " }\n", []),
- ic_codegen:nl(Fd),
-
- emit_union_members_functions(G, [UnionName ++ "Package"|N], X,
- Fd, UnionName, DiscrType, MList, MList),
- ic_codegen:nl(Fd),
-
- ic_codegen:emit(Fd, "}\n", []),
- file:close(Fd).
-
-%%-----------------------------------------------------------------
-%% Func: emit_holder_class/4
-%%-----------------------------------------------------------------
-emit_holder_class(G, N, _X, UnionName) ->
- UName = string:concat(UnionName, "Holder"),
- {Fd, _} = ic_file:open_java_file(G, N, UName),
-
- ic_codegen:emit(Fd, "final public class ~sHolder {\n",[UnionName]),
-
- ic_codegen:emit(Fd, " // instance variables\n"),
- ic_codegen:emit(Fd, " public ~s value;\n", [UnionName]),
- ic_codegen:nl(Fd),
-
- ic_codegen:emit(Fd, " // constructors\n"),
- ic_codegen:emit(Fd, " public ~sHolder() {}\n", [UnionName]),
- ic_codegen:emit(Fd, " public ~sHolder(~s initial) {\n",
- [UnionName, UnionName]),
- ic_codegen:emit(Fd, " value = initial;\n"),
- ic_codegen:emit(Fd, " }\n"),
- ic_codegen:nl(Fd),
-
- ic_codegen:emit(Fd, " // methods\n"),
-
- ic_codegen:emit(Fd, " public void _marshal(~sOtpOutputStream out) throws java.lang.Exception {\n",
- [?ERLANGPACKAGE]),
- ic_codegen:emit(Fd, " ~sHelper.marshal(out, value);\n", [UnionName]),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public void _unmarshal(~sOtpInputStream in) throws java.lang.Exception {\n",
- [?ERLANGPACKAGE]),
- ic_codegen:emit(Fd, " value = ~sHelper.unmarshal(in);\n", [UnionName]),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, "}\n"),
- file:close(Fd).
-
-
-%%-----------------------------------------------------------------
-%% Func: emit_helper_class/4
-%%-----------------------------------------------------------------
-emit_helper_class(G, N, X, UnionName, WiredUnionName) ->
- UName = string:concat(UnionName, "Helper"),
- {Fd, _} = ic_file:open_java_file(G, N, UName),
-
- DiscrType = ic_java_type:getType(G, [ UnionName ++ "Package" |N],
- ic_forms:get_type(X)),
-
- ic_codegen:emit(Fd, "public class ~sHelper {\n",[UnionName]),
-
- ic_codegen:emit(Fd, " // constructors\n", []),
- ic_codegen:emit(Fd, " private ~sHelper() {}\n", [UnionName]),
- ic_codegen:nl(Fd),
-
- ic_codegen:emit(Fd, " // methods\n", []),
- MList = union_member_list(G, N, X, DiscrType),
-
- ic_codegen:emit(Fd, " public static void marshal(~sOtpOutputStream _out, ~s _value)\n",
- [?ERLANGPACKAGE, UnionName]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
- emit_union_marshal_function(G, N, X, Fd, UnionName, WiredUnionName, MList),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public static ~s unmarshal(~sOtpInputStream _in)\n",
- [UnionName, ?ERLANGPACKAGE]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
- emit_union_unmarshal_function(G, N, X, Fd, UnionName, WiredUnionName, MList),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public static String id() {\n"),
- ic_codegen:emit(Fd, " return ~p;\n",[ictk:get_IR_ID(G, N, X)]),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public static String name() {\n"),
- ic_codegen:emit(Fd, " return ~p;\n",[UnionName]),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_jbe:emit_type_function(G, N, X, Fd),
-
-
- ic_codegen:emit(Fd, " public static void insert(~sAny _any, ~s _this)\n",
- [?ICPACKAGE,UnionName]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
-
- ic_codegen:emit(Fd, " ~sOtpOutputStream _os = \n",[?ERLANGPACKAGE]),
- ic_codegen:emit(Fd, " new ~sOtpOutputStream();\n\n",[?ERLANGPACKAGE]),
-
- ic_codegen:emit(Fd, " _any.type(type());\n"),
- ic_codegen:emit(Fd, " marshal(_os, _this);\n"),
- ic_codegen:emit(Fd, " _any.insert_Streamable(_os);\n"),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public static ~s extract(~sAny _any)\n",
- [UnionName,?ICPACKAGE]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n\n"),
-
- ic_codegen:emit(Fd, " return unmarshal(_any.extract_Streamable());\n"),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " public static int discriminatorAsInt(~s _discriminator)\n",
- [DiscrType]),
- ic_codegen:emit(Fd, " throws java.lang.Exception {\n"),
- emit_discriminator_as_int(G, N, ic_forms:get_type(X), Fd),
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, "}\n"),
- file:close(Fd).
-
-%%-----------------------------------------------------------------
-%% Func: emit_union_members_functions/7
-%%-----------------------------------------------------------------
-emit_union_members_functions(_, _, _, _, _, _, [], _) ->
- ok;
-emit_union_members_functions(G, N, X, Fd, UnionName, DiscrType,
- [{Label, Case, TypeDef, Id, Ls} | MList], MListTot) ->
-
- CaseId = Case#case_dcl.id, %% Maybe Array
- CaseType = Case#case_dcl.type, %% Maybe Sequence
-
- Type = if element(1,CaseId) == array ->
- ic_java_type:getType(G, N, TypeDef) ++
- ic_java_type:getdim(CaseId#array.size);
- true ->
- ic_java_type:getType(G, N, TypeDef)
- end,
-
- HolderType =
- if element(1,CaseId) == array ->
- ic_java_type:getHolderType(G, N, CaseId);
- true ->
- if element(1,CaseType) == sequence ->
- ic_util:to_dot(G,[Id|N]) ++"Holder";
- true ->
- ic_java_type:getHolderType(G, N, TypeDef)
- end
- end,
-
- %%
- %% Set method
- %%
- ic_codegen:emit(Fd, " // ~s access and set functions\n",[Id]),
- ic_codegen:emit(Fd, " public void ~s(~s value) "
- "throws java.lang.Exception {\n",
- [Id, Type]),
- ic_codegen:emit(Fd, " _initialized = true;\n", []),
- case Label of
- "default" ->
- ic_codegen:emit(Fd, " _discriminator = (~s) _default;\n",
- [DiscrType]);
- _ ->
- case ic_java_type:isBasicType(G, N, ic_forms:get_type(X)) of
- true ->
- ic_codegen:emit(Fd, " _discriminator = (~s) "
- "~s;\n",
- [DiscrType, Label]);
- _ ->
- ic_codegen:emit(Fd, " _discriminator = (~s) "
- "~s.~s;\n",
- [DiscrType, DiscrType, Label])
- end
- end,
- ic_codegen:emit(Fd, " _value = new ~s(value);\n",
- [HolderType]),
- ic_codegen:emit(Fd, " }\n", []),
-
- %%
- %% Check this entry has more than one label and the generate an extra set method.
- %%
- case Ls of
- [] ->
- ok;
- _ ->
- ic_codegen:emit(Fd, " public void ~s(~s discriminator, ~s value) "
- "throws java.lang.Exception {\n",
- [Id, DiscrType, Type]),
- ic_codegen:emit(Fd, " _initialized = true;\n", []),
- ic_codegen:emit(Fd, " _discriminator = (~s) discriminator;\n",
- [DiscrType]),
- ic_codegen:emit(Fd, " _value = new ~s(value);\n",
- [HolderType]),
- ic_codegen:emit(Fd, " }\n", [])
- end,
-
- %%
- %% Get method
- %%
- ic_codegen:emit(Fd, " public ~s ~s() throws java.lang.Exception {\n",
- [Type, Id]),
- ic_codegen:emit(Fd, " if (!_initialized) {\n", []),
- ic_codegen:emit(Fd, " throw new java.lang.Exception(\"\");\n",[]),
- ic_codegen:emit(Fd, " }\n", []),
- ic_codegen:emit(Fd, " switch (~sHelper.discriminatorAsInt"
- "(discriminator())) {\n",
- [UnionName]),
- if
- Label == "default" ->
- ic_codegen:emit(Fd, " default:\n", []),
- ic_codegen:emit(Fd, " break;\n", []),
- emit_default_access_fun_switch_cases(G, N, X, Fd, DiscrType,
- MListTot),
- ic_codegen:emit(Fd, " throw new java.lang.Exception(\"\");\n", []);
- true ->
- ic_codegen:emit(Fd, " case ~s:\n",
- [get_case_as_int(G, N, ic_forms:get_type(X),
- DiscrType, Label)]),
- ic_codegen:emit(Fd, " break;\n", []),
- ic_codegen:emit(Fd, " default:\n", []),
- ic_codegen:emit(Fd, " throw new java.lang.Exception(\"\");\n", [])
- end,
- ic_codegen:emit(Fd, " }\n", []),
-
- ic_codegen:emit(Fd, " return ((~s) _value).value;\n",
- [HolderType]),
- ic_codegen:emit(Fd, " }\n", []),
- ic_codegen:nl(Fd),
- emit_union_members_functions(G, N, X, Fd, UnionName, DiscrType, MList,
- MListTot).
-
-
-%%-----------------------------------------------------------------
-%% Func: emit_default_access_fun_switch_cases/6
-%%-----------------------------------------------------------------
-emit_default_access_fun_switch_cases(_G, _N, _X, _Fd, _DiscrType, []) ->
- ok;
-emit_default_access_fun_switch_cases(G, N, X, Fd, DiscrType,
- [{"default", _, _, _, _} |MList]) ->
- emit_default_access_fun_switch_cases(G, N, X, Fd, DiscrType, MList);
-emit_default_access_fun_switch_cases(G, N, X, Fd, DiscrType,
- [{Label, _Case, _TypeDef, _Id, _} | MList]) ->
- ic_codegen:emit(Fd, " case ~s:\n",
- [get_case_as_int(G, N, ic_forms:get_type(X),
- DiscrType, Label)]),
- emit_default_access_fun_switch_cases(G, N, X, Fd, DiscrType, MList).
-
-
-
-%%-----------------------------------------------------------------
-%% Func: emit_union_unmarshal_function/5
-%%-----------------------------------------------------------------
-emit_union_unmarshal_function(G, N, X, Fd, UnionName, WiredUnionName, MList) ->
- DiscrTypeForm = ic_forms:get_type(X),
- DiscrType = ic_java_type:getType(G, [UnionName ++ "Package"|N],
- DiscrTypeForm),
-
- ic_codegen:emit(Fd, " _in.read_tuple_head();\n\n"),
-
- ic_codegen:emit(Fd, " if ((_in.read_atom()).compareTo(~p) != 0)\n",
- [ic_util:to_undersc([WiredUnionName|N])]),
- ic_codegen:emit(Fd, " throw new java.lang.Exception(\"\");\n\n",[]),
-
- ic_codegen:emit(Fd, " ~s _value = new ~s();\n", [UnionName, UnionName]),
-
- %% Decode discriminator
- case ic_java_type:isBasicType(G, N, DiscrTypeForm) of
- true ->
- ic_codegen:emit(Fd, " ~s _discriminator = _in~s;\n\n",
- [DiscrType,
- ic_java_type:unMarshalFun(G, N, X, DiscrTypeForm)]);
- _ ->
- ic_codegen:emit(Fd, " ~s _discriminator = ~s.unmarshal(_in);\n\n",
- [DiscrType,ic_java_type:getUnmarshalType(G, N, X, DiscrTypeForm)])
- end,
-
- ic_codegen:emit(Fd, " switch (~sHelper.discriminatorAsInt(_discriminator)) {\n",
- [UnionName]),
-
- emit_union_unmarshal_function_loop(G, [UnionName ++ "Package"|N], X,
- Fd, DiscrType, MList),
-
- ic_codegen:emit(Fd, " }\n\n"),
-
- ic_codegen:emit(Fd, " return _value;\n").
-
-%%-----------------------------------------------------------------
-%% Func: emit_union_unmarshal_function_loop/6
-%%-----------------------------------------------------------------
-emit_union_unmarshal_function_loop(_, _, _, _, _, []) ->
- ok;
-emit_union_unmarshal_function_loop(G, N, X, Fd, DiscrType,
- [{Label, Case, Type, Id, Ls} |MList]) ->
- case Label of
- "default" ->
- ic_codegen:emit(Fd, " default:\n");
- _ ->
- ic_codegen:emit(Fd, " case ~s:\n",
- [get_case_as_int(G, N, ic_forms:get_type(X),
- DiscrType, Label)])
- end,
-
- gen_multiple_cases(G, N, X, Fd, DiscrType, Ls),
-
- CaseId = Case#case_dcl.id, %% Maybe Array
- CaseType = Case#case_dcl.type, %% Maybe Sequence
-
- case element(1,CaseId) of
- array ->
- ic_codegen:emit(Fd, " _value.~s(~s.unmarshal(_in));\n",
- [Id,
- ic_java_type:getUnmarshalType(G, N, Case, CaseId)]);
-
- _ ->
- case element(1, CaseType) of
- sequence ->
- ic_codegen:emit(Fd, " _value.~s(~s.unmarshal(_in));\n",
- [Id,
- ic_java_type:getUnmarshalType(G, N, Case, CaseType)]);
- _ ->
- case ic_java_type:isBasicType(G, N, CaseType) of
- true ->
- ic_codegen:emit(Fd, " _value.~s(_in~s);\n",
- [Id,
- ic_java_type:unMarshalFun(G, N, X, Type)]);
- false ->
- ic_codegen:emit(Fd, " _value.~s(~s.unmarshal(_in));\n",
- [Id,
- ic_java_type:getUnmarshalType(G, N, X, Type)])
- end
- end
- end,
-
- ic_codegen:emit(Fd, " break;\n", []),
- emit_union_unmarshal_function_loop(G, N, X, Fd, DiscrType, MList).
-
-
-
-
-
-%%-----------------------------------------------------------------
-%% Func: emit_union_marshal_function/6
-%%-----------------------------------------------------------------
-emit_union_marshal_function(G, N, X, Fd, UnionName, WiredUnionName, MList) ->
-
- DiscrTypeForm = ic_forms:get_type(X),
- DiscrType = ic_java_type:getType(G, [UnionName ++ "Package" |N],
- DiscrTypeForm),
-
- ic_codegen:emit(Fd, " _out.write_tuple_head(3);\n"),
- ic_codegen:emit(Fd, " _out.write_atom(~p);\n",
- [ic_util:to_undersc([WiredUnionName|N])]),
-
- case ic_java_type:isBasicType(G, N, DiscrTypeForm) of
- true ->
- ic_codegen:emit(Fd, " _out~s(_value.discriminator());\n\n",
- [ic_java_type:marshalFun(G, N, X, DiscrTypeForm)]);
- false ->
- ic_codegen:emit(Fd, " ~s(_out, _value.discriminator());\n\n",
- [ic_java_type:marshalFun(G, N, X, DiscrTypeForm)])
- end,
-
- ic_codegen:emit(Fd, " switch(~sHelper.discriminatorAsInt(_value.discriminator())) {\n",
- [UnionName]),
-
- emit_union_marshal_function_loop(G,
- [ UnionName ++ "Package"|N],
- X,
- Fd,
- DiscrType,
- MList),
-
- ic_codegen:emit(Fd, " }\n\n", []).
-
-
-%%-----------------------------------------------------------------
-%% Func: emit_union_marshal_function_loop/
-%%-----------------------------------------------------------------
-emit_union_marshal_function_loop(_, _, _, _, _, []) ->
- ok;
-emit_union_marshal_function_loop(G, N, X, Fd, DiscrType,
- [{Label, Case, Type, Id, Ls} |MList]) ->
- case Label of
- "default" ->
- ic_codegen:emit(Fd, " default:\n",
- []);
- _ ->
- ic_codegen:emit(Fd, " case ~s:\n",
- [get_case_as_int(G, N, ic_forms:get_type(X),
- DiscrType, Label)])
- end,
-
- gen_multiple_cases(G, N, X, Fd, DiscrType, Ls),
-
-
- CaseId = Case#case_dcl.id, %% Maybe Array
- CaseType = Case#case_dcl.type, %% Maybe Sequence
-
- case element(1,CaseId) of
- array ->
- ic_codegen:emit(Fd, " ~s(_out, _value.~s());\n",
- [ic_java_type:marshalFun(G, N, Case, CaseId),
- Id]);
- _ ->
- case element(1, CaseType) of
- sequence ->
- ic_codegen:emit(Fd, " ~s.marshal(_out, _value.~s());\n",
- [ic_util:to_dot(G,[Id|N]) ++ "Helper",
- Id]);
- _ ->
- case ic_java_type:isBasicType(G, N, CaseType) of
- true ->
- ic_codegen:emit(Fd, " _out~s(_value.~s());\n",
- [ic_java_type:marshalFun(G, N, X, Type),
- Id]);
- false ->
- ic_codegen:emit(Fd, " ~s(_out, _value.~s());\n",
- [ic_java_type:marshalFun(G, N, X, Type),
- Id])
- end
- end
- end,
-
- ic_codegen:emit(Fd, " break;\n", []),
- emit_union_marshal_function_loop(G, N, X, Fd, DiscrType, MList).
-
-
-
-gen_multiple_cases(_G, _N, _X, _Fd, _DiscrType, []) ->
- ok;
-gen_multiple_cases(G, N, X, Fd, DiscrType, [Label |Ls]) ->
- ic_codegen:emit(Fd, " case ~s:\n",
- [get_case_as_int(G, N, ic_forms:get_type(X),
- DiscrType, getLabel(DiscrType, Label))]),
- gen_multiple_cases(G, N, X, Fd, DiscrType, Ls).
-
-
-%%-----------------------------------------------------------------
-%% Func: union_member_list/3
-%%-----------------------------------------------------------------
-union_member_list(G, N, X, DiscrType) ->
- M = lists:map(
- fun(Case) ->
- {Label, LabelList} = case check_default(ic_forms:get_idlist(Case)) of
- {{default, C}, List} ->
- {{default, C}, List};
- {L, []} ->
- {L, []};
- {_, [L |Ls]} ->
- {L, Ls}
- end,
-
- CName = ic_forms:get_java_id(Case),
- CId = Case#case_dcl.id,
- CType = Case#case_dcl.type,
-
- if element(1,CId) == array ->
- N2 = [ic_forms:get_id2(X) ++ "Package" |N],
- ic_array_java:gen(G, N2, Case, CId);
- true ->
- if element(1,Case#case_dcl.type) == sequence ->
- N2 = [ic_forms:get_id2(X) ++ "Package" |N],
- ic_sequence_java:gen(G, N2, CType, CName);
- true ->
- ok
- end
- end,
-
- {getLabel(DiscrType, Label),
- Case,
- ic_forms:get_type(Case),
- CName,
- LabelList}
- end,
- ic_forms:get_body(X)),
- lists:flatten(M).
-
-check_default([]) ->
- {false, []};
-check_default([{default, X} |Ls]) ->
- {{default, X}, Ls};
-check_default([L]) ->
- {false, [L]};
-check_default([L |Ls]) ->
- {X, Y} = check_default(Ls),
- {X, [L | Y]}.
-
-getLabel(_, {'<integer_literal>', _, N}) ->
- N;
-getLabel(_, {'<character_literal>', _, N}) ->
- "'" ++ N ++ "'";
-getLabel(_, {'<wcharacter_literal>', _, N}) ->
- "'" ++ N ++ "'";
-getLabel(_, {'TRUE',_}) ->
- "true";
-getLabel(_, {'FALSE',_}) ->
- "true";
-getLabel(_, {default, _}) ->
- "default";
-getLabel(_DiscrType, X) -> %%DiscrType ++ "." ++
- ic_util:to_dot(ic_forms:get_id(X)).
-
-get_default_val(G, N, _, tk_short, MList) ->
- integer_default_val(G, N, 1, lists:map(fun({V, _, _, _, _}) -> V end, MList));
-get_default_val(G, N, _, tk_long, MList) ->
- integer_default_val(G, N, 1, lists:map(fun({V, _, _, _, _}) -> V end, MList));
-get_default_val(G, N, _, tk_ushort, MList) ->
- integer_default_val(G, N, 1, lists:map(fun({V, _, _, _, _}) -> V end, MList));
-get_default_val(G, N, _, tk_ulong, MList) ->
- integer_default_val(G, N, 1, lists:map(fun({V, _, _, _, _}) -> V end, MList));
-get_default_val(G, N, _, tk_char, MList) ->
- char_default_val(G, N, $a, lists:map(fun({V, _, _, _, _}) -> V end, MList));
-get_default_val(G, N, _, tk_boolean, MList) ->
- boolean_default_val(G, N, lists:map(fun({V, _, _, _, _}) -> V end, MList));
-get_default_val(G, N, DiscrType, {tk_enum, _, _, Values}, MList) ->
- enum_default_val(G, N, DiscrType, Values, MList).
-
-integer_default_val(G, N, Num, MList) ->
- Num2 = integer_to_list(Num),
- case lists:member(Num2, MList) of
- true ->
- integer_default_val(G, N, Num + 1, MList);
- false ->
- Num2
- end.
-
-char_default_val(G, N, CharNum, MList) ->
- Str = "'",
- CharNum2 = Str ++ [CharNum | Str],
- case lists:member(CharNum2, MList) of
- true ->
- char_default_val(G, N, CharNum + 1, MList);
- false ->
- CharNum2
- end.
-
-boolean_default_val(G, N, MList) ->
- if
- length(MList) > 2 ->
- ic_error:error(G, {plain_error_string,
- lists:flatten(
- io_lib:format("Default value found while all values have label on ~s",
- [ic_util:to_colon(N)]))}),
- none;
- true ->
- case MList of
- ["true"] ->
- "false";
- ["false"] ->
- "true";
- ["default","true"] ->
- "false";
- ["true","default"] ->
- "false";
- ["default","false"] ->
- "true";
- ["false","default"] ->
- "true";
- _ ->
- none
- end
- end.
-
-
-
-
-enum_default_val(G, N, DiscrType, Values, Mlist) ->
-
- VLen = length(Values),
- MLen = length(Mlist),
-
- case MLen > VLen of
- true ->
- ic_error:error(G, {plain_error_string,
- lists:flatten(
- io_lib:format("Default value found while all values have label on ~s",
- [ic_util:to_colon(N)]))}),
- none;
- false ->
- enum_default_val_loop(G, N, DiscrType, Values, Mlist)
- end.
-
-enum_default_val_loop(_G, _N, _, [], []) ->
- none;
-enum_default_val_loop(_G, _N, DiscrType, [Value| _], []) ->
- DiscrType ++ "." ++ Value;
-enum_default_val_loop(G, N, DiscrType, Values, [Case | MList]) when is_tuple(Case) ->
- NewValues = lists:delete(element(1,Case), Values),
- enum_default_val_loop(G, N, DiscrType, NewValues, MList).
-
-
-
-emit_discriminator_as_int(G, N, T, Fd) ->
- case ictype:isBoolean(G,N,T) of
- true ->
- ic_codegen:emit(Fd, " if(_discriminator)\n", []),
- ic_codegen:emit(Fd, " return 1;\n", []),
- ic_codegen:emit(Fd, " else\n", []),
- ic_codegen:emit(Fd, " return 0;\n", []);
- false ->
- case ictype:isEnum(G, N, T) of
- true ->
- ic_codegen:emit(Fd, " return _discriminator.value();\n",
- []);
- false ->
- ic_codegen:emit(Fd, " return _discriminator;\n", [])
- end
- end.
-
-
-get_case_as_int(G, N, T, DiscrJavaTypeName, Label) ->
- case ictype:isBoolean(G,N,T) of
- true ->
- case Label of
- "true" ->
- "1";
- "false" ->
- "0"
- end;
- false ->
- case ictype:isEnum(G, N, T) of
- true ->
- DiscrJavaTypeName ++ "._" ++ Label;
- false ->
- "(" ++ DiscrJavaTypeName ++ ") " ++ Label
- end
- end.
-
-
-
diff --git a/lib/ic/src/ic_util.erl b/lib/ic/src/ic_util.erl
deleted file mode 100644
index b1263ae63d..0000000000
--- a/lib/ic/src/ic_util.erl
+++ /dev/null
@@ -1,314 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ic_util).
-
-
--include("icforms.hrl").
--include("ic.hrl").
--include("ic_debug.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
-
--export([mk_align/1, mk_list/1, join/2, chain/2, mk_name/2,
- mk_OE_name/2, mk_oe_name/2, mk_var/1]).
-
--export([to_atom/1, to_colon/1, to_list/1, to_undersc/1, to_dot/1,
- to_dot/2]).
--export([to_uppercase/1, adjustScopeToJava/2, eval_java/3, eval_c/3]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-
-%% mk_list produces a nice comma separated string of variable names
-mk_list([]) -> [];
-mk_list([Arg | Args]) ->
- Arg ++ mk_list2(Args).
-mk_list2([Arg | Args]) ->
- ", " ++ Arg ++ mk_list2(Args);
-mk_list2([]) -> [].
-
-%% Produce a list of items separated by S.
-join([E1, E2| Es], S) ->
- [E1, S| join([E2| Es], S)];
-join([E], _) ->
- [E];
-join([], _) ->
- [].
-
-%% Produce a list of items, each terminated by T.
-chain([E| Es], T) ->
- [E, T| chain(Es, T)];
-chain([], _) ->
- [].
-
-
-%% Shall convert a string to a Erlang variable name (Capitalise)
-mk_var( [N | Str] ) when N >= $a, N =< $z ->
- [ N+$A-$a | Str ];
-mk_var( [N | Str] ) when N >= $A, N =< $Z -> [N | Str].
-
-%% Shall produce a "public" name for name. When we introduce new
-%% identifiers in the mapping that must not collide with those from
-%% the IDL spec.
-%%
-%% NOTE: Change name of IFR ID in system exceptions in corba.hrl when
-%% prefix is changed here.
-%%
-mk_name(_Gen, Name) -> lists:flatten(["OE_" | Name]).
-mk_OE_name(_Gen, Name) -> lists:flatten(["OE_" | Name]).
-mk_oe_name(_Gen, Name) -> lists:flatten(["oe_" | Name]).
-
-mk_align(String) ->
- io_lib:format("OE_ALIGN(~s)",[String]).
-
-to_atom(A) when is_atom(A) -> A;
-to_atom(L) when is_list(L) -> list_to_atom(L).
-
-to_list(A) when is_list(A) -> A;
-to_list(L) when is_atom(L) -> atom_to_list(L);
-to_list(X) when is_integer(X) -> integer_to_list(X).
-
-
-
-%% Produce a colon (or under score) separated string repr of the name
-%% X
-%%
-to_colon(X) when element(1, X) == scoped_id ->
- to_colon2(ic_symtab:scoped_id_strip(X));
-to_colon(L) -> to_colon2(L).
-
-to_colon2([X]) -> X;
-to_colon2([X | Xs]) -> to_colon2(Xs) ++ "::" ++ X;
-to_colon2([]) -> "".
-
-
-to_undersc(X) when element(1, X) == scoped_id ->
- to_undersc2(ic_symtab:scoped_id_strip(X));
-to_undersc(L) -> to_undersc2(L).
-
-to_undersc2([X]) -> X;
-to_undersc2([X | Xs]) -> to_undersc2(Xs) ++ "_" ++ X;
-to_undersc2([]) -> "".
-
-
-%% Z is a single name
-to_uppercase(Z) ->
- lists:map(fun(X) when X>=$a, X=<$z -> X-$a+$A;
- (X) -> X end, Z).
-
-
-%%
-to_dot(X) when element(1, X) == scoped_id ->
- to_dotLoop(ic_symtab:scoped_id_strip(X));
-to_dot(L) -> to_dotLoop(L).
-
-to_dotLoop([X]) -> ic_forms:get_java_id(X);
-to_dotLoop([X | Xs]) -> to_dotLoop(Xs) ++ "." ++ ic_forms:get_java_id(X);
-to_dotLoop([]) -> "".
-
-
-
-%%
-to_dot(G,X) when element(1, X) == scoped_id ->
- S = ic_genobj:pragmatab(G),
- ScopedId = ic_symtab:scoped_id_strip(X),
- case isConstScopedId(S, ScopedId) of %% Costants are left as is
- true ->
- to_dotLoop(ScopedId) ++ addDotValue(S, ScopedId);
- false ->
- to_dotLoop(S,ScopedId)
- end;
-to_dot(G,ScopedId) ->
- S = ic_genobj:pragmatab(G),
- case isConstScopedId(S, ScopedId) of %% Costants are left as is
- true ->
- to_dotLoop(ScopedId) ++ addDotValue(S, ScopedId);
- false ->
- to_dotLoop(S,ScopedId)
- end.
-
-addDotValue(S, [_C | Ss]) ->
- case isInterfaceScopedId(S, Ss) of
- true ->
- "";
- false ->
- ".value"
- end.
-
-to_dotLoop(S,[X]) ->
- case isInterfaceScopedId(S, [X]) of
- true ->
- ic_forms:get_java_id(X) ++ "Package";
- false ->
- ic_forms:get_java_id(X)
- end;
-to_dotLoop(S,[X | Xs]) ->
- case isInterfaceScopedId(S, [X | Xs]) of
- true ->
- to_dotLoop(S,Xs) ++ "." ++ ic_forms:get_java_id(X) ++ "Package";
- false ->
- to_dotLoop(S,Xs) ++ "." ++ ic_forms:get_java_id(X)
- end;
-to_dotLoop(_S,[]) -> "".
-
-isInterfaceScopedId(_S,[]) ->
- false;
-isInterfaceScopedId(S,[X|Xs]) ->
- case ets:match(S,{file_data_local,'_','_',interface,Xs,X,'_','_','_'}) of
- [] ->
- case ets:match(S,{file_data_included,'_','_',interface,Xs,X,'_','_','_'}) of
- [] ->
- false;
- _ ->
- true
- end;
- _ ->
- true
- end.
-
-isConstScopedId(_S,[]) ->
- false;
-isConstScopedId(S,[X|Xs]) ->
- case ets:match(S,{file_data_local,'_','_',const,Xs,X,'_','_','_'}) of
- [] ->
- case ets:match(S,{file_data_included,'_','_',const,Xs,X,'_','_','_'}) of
- [] ->
- false;
- _ ->
- true
- end;
- _ ->
- true
- end.
-
-
-
-%%
-adjustScopeToJava(G,X) when element(1, X) == scoped_id ->
- S = ic_genobj:pragmatab(G),
- ScopedId = ic_symtab:scoped_id_strip(X),
- case isConstScopedId(S, ScopedId) of %% Costants are left as is
- true ->
- ic_forms:get_java_id(ScopedId);
- false ->
- adjustScopeToJavaLoop(S,ScopedId)
- end;
-adjustScopeToJava(G,ScopedId) ->
- S = ic_genobj:pragmatab(G),
- case isConstScopedId(S, ScopedId) of %% Costants are left as is
- true ->
- ic_forms:get_java_id(ScopedId);
- false ->
- adjustScopeToJavaLoop(S,ScopedId)
- end.
-
-
-
-adjustScopeToJavaLoop(_S,[]) ->
- [];
-adjustScopeToJavaLoop(S,[X | Xs]) ->
- case isInterfaceScopedId(S, [X | Xs]) of
- true ->
- [ic_forms:get_java_id(X) ++ "Package" | adjustScopeToJavaLoop(S,Xs)];
- false ->
- [ic_forms:get_java_id(X) | adjustScopeToJavaLoop(S,Xs)]
- end.
-
-
-%%
-%% Expression evaluator for java
-%%
-%% Well, this is not an evaluator, it just
-%% prints the hole operation, sorry.
-%%
-eval_java(G,N,Arg) when is_record(Arg, scoped_id) ->
- {FSN, _, _, _} =
- ic_symtab:get_full_scoped_name(G, N, Arg),
- ic_util:to_dot(G,FSN);
-eval_java(_G,_N,Arg) when is_tuple(Arg) andalso element(1,Arg) == '<integer_literal>' ->
- element(3,Arg);
-eval_java(_G,_N,Arg) when is_tuple(Arg) andalso element(1,Arg) == '<character_literal>' ->
- element(3,Arg);
-eval_java(_G,_N,Arg) when is_tuple(Arg) andalso element(1,Arg) == '<wcharacter_literal>' ->
- element(3,Arg);
-eval_java(_G,_N,Arg) when is_tuple(Arg) andalso element(1,Arg) == '<boolean_literal>' ->
- element(3,Arg);
-eval_java(_G,_N,Arg) when is_tuple(Arg) andalso element(1,Arg) == '<floating_pt_literal>' ->
- element(3,Arg);
-eval_java(_G,_N,Arg) when is_tuple(Arg) andalso element(1,Arg) == '<string_literal>' ->
- element(3,Arg);
-eval_java(_G,_N,Arg) when is_tuple(Arg) andalso element(1,Arg) == '<wstring_literal>' ->
- element(3,Arg);
-eval_java(G,N,{Op,Arg1,Arg2}) ->
- "(" ++ eval_java(G,N,Arg1) ++
- ic_forms:get_java_id(Op) ++
- eval_java(G,N,Arg2) ++ ")".
-
-
-
-%%
-%% Expression evaluator for c
-%%
-%% Well, this is not an evaluator, it just
-%% prints the hole operation, sorry.
-%%
-eval_c(G,N,Arg) when is_record(Arg, scoped_id) ->
- {FSN, _, _, _} =
- ic_symtab:get_full_scoped_name(G, N, Arg),
- ic_util:to_undersc(FSN);
-eval_c(_G,_N,Arg) when is_tuple(Arg) andalso element(1,Arg) == '<integer_literal>' ->
- element(3,Arg);
-eval_c(_G,_N,Arg) when is_tuple(Arg) andalso element(1,Arg) == '<character_literal>' ->
- element(3,Arg);
-eval_c(_G,_N,Arg) when is_tuple(Arg) andalso element(1,Arg) == '<wcharacter_literal>' ->
- element(3,Arg);
-eval_c(_G,_N,Arg) when is_tuple(Arg) andalso element(1,Arg) == '<boolean_literal>' ->
- element(3,Arg);
-eval_c(_G,_N,Arg) when is_tuple(Arg) andalso element(1,Arg) == '<floating_pt_literal>' ->
- element(3,Arg);
-eval_c(_G,_N,Arg) when is_tuple(Arg) andalso element(1,Arg) == '<string_literal>' ->
- element(3,Arg);
-eval_c(_G,_N,Arg) when is_tuple(Arg) andalso element(1,Arg) == '<wstring_literal>' ->
- element(3,Arg);
-eval_c(G,N,{Op,Arg1,Arg2}) ->
- "(" ++ eval_c(G,N,Arg1) ++
- atom_to_list(Op) ++
- eval_c(G,N,Arg2) ++ ")".
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-
-
-
-
-
-
diff --git a/lib/ic/src/icenum.erl b/lib/ic/src/icenum.erl
deleted file mode 100644
index cab68d17fa..0000000000
--- a/lib/ic/src/icenum.erl
+++ /dev/null
@@ -1,206 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: icenum.erl
-%%
-%%
-%%-----------------------------------------------------------------
-%%
-%% Code generation for enum's.
-%%-----------------------------------------------------------------
--module(icenum).
-
--import(ic_codegen, [emit/2, emit/3, emit/4, emit_c_enc_rpt/4, emit_c_dec_rpt/4]).
-
--include("icforms.hrl").
--include("ic.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([enum_gen/4]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-enum_gen(G, N, X, c) when is_record(X, enum) ->
- emit_c_enum(G, N, X);
-enum_gen(_G, _N, _X, _L) ->
- ok.
-
-
-emit_c_enum(G, N, X) ->
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- EnumName = [ic_forms:get_id2(X) | N],
-
- case ic_pragma:is_local(G,EnumName) of
- true ->
-
- Fd = ic_genobj:hrlfiled(G),
- EnumNameStr = ic_util:to_undersc(EnumName),
- ic_code:insert_typedef(G, EnumNameStr, {enum, EnumNameStr}),
- {tk_enum,_,_,EList} = ic_forms:get_tk(X),
- emit(Fd, "\n#ifndef __~s__\n",[ic_util:to_uppercase(EnumNameStr)]),
- emit(Fd, "#define __~s__\n",[ic_util:to_uppercase(EnumNameStr)]),
- ic_codegen:mcomment_light(Fd,
- [io_lib:format("Enum definition: ~s",
- [EnumNameStr])],
- c),
- emit(Fd, "typedef CORBA_enum {", []),
- emit_c_enum_values(G, N, Fd, EList),
- emit(Fd, "} ~s ;\n\n", [EnumNameStr]),
- create_c_enum_file(G, N, EnumNameStr, EList),
- emit(Fd, "\n#endif\n\n");
-
- false -> %% Do not generate included types att all.
- ok
- end;
-
- false ->
- ok
- end.
-
-
-emit_c_enum_values(_G, N, Fd, [E]) ->
- emit(Fd, "~s", [ic_util:to_undersc([E| N])]);
-emit_c_enum_values(G, N, Fd, [E |Es]) ->
- emit(Fd, "~s, ", [ic_util:to_undersc([E| N])]),
- emit_c_enum_values(G, N, Fd, Es).
-
-
-open_c_coding_file(G, Name) ->
- SName = string:concat(ic_util:mk_oe_name(G, "code_"), Name),
- FName =
- ic_file:join(ic_options:get_opt(G, stubdir),ic_file:add_dot_c(SName)),
- case file:open(FName, [write]) of
- {ok, Fd} ->
- {Fd, SName};
- Other ->
- exit(Other)
- end.
-
-
-create_c_enum_file(G, N, Name, Elist) ->
-
- {Fd , SName} = open_c_coding_file(G, Name),
- HFd = ic_genobj:hrlfiled(G), %% Write on stubfile header
- HrlFName = filename:basename(ic_genobj:include_file(G)),
- ic_codegen:emit_stub_head(G, Fd, SName, c),
- emit(Fd, "#include \"~s\"\n\n",[HrlFName]),
-
- %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %% Fd = ic_genobj:stubfiled(G), %% Write on stubfile
- %% HFd = ic_genobj:hrlfiled(G), %% Write on stubfile header
- %% HrlFName = filename:basename(ic_genobj:include_file(G)),
- %% emit(Fd, "#include \"~s\"\n\n",[HrlFName]),
- %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- emit(Fd, "char* ~s[~p] = {\n", [ic_util:mk_oe_name(G, Name),
- length(Elist)]),
- emit_c_enum_array_values(Fd, Elist),
- emit(Fd, "};\n\n",[]),
- emit_sizecount(G, N, Fd, HFd, Name, Elist),
- emit_encode(G, N, Fd, HFd, Name, Elist),
- emit_decode(G, N, Fd, HFd, Name, Elist),
- file:close(Fd).
-
-emit_c_enum_array_values(Fd, [E]) ->
- emit(Fd, " ~p\n", [E]);
-emit_c_enum_array_values(Fd, [E |Es]) ->
- emit(Fd, " ~p,\n", [E]),
- emit_c_enum_array_values(Fd, Es).
-
-
-emit_sizecount(G, _N, Fd, HFd, Name, _Elist) ->
-
- emit(HFd, "int ~s~s(CORBA_Environment *oe_env, int*, int*);\n",
- [ic_util:mk_oe_name(G, "sizecalc_"), Name]),
-
- emit(Fd, "int ~s~s(CORBA_Environment *oe_env, int* oe_size_count_index, int* oe_size)\n"
- "{\n",
- [ic_util:mk_oe_name(G, "sizecalc_"), Name]),
- emit(Fd, " int oe_error_code = 0;\n\n",[]),
-
- AlignName = lists:concat(["*oe_size + sizeof(",Name,")"]),
- emit(Fd, " *oe_size = ~s;\n\n",[ic_util:mk_align(AlignName)]),
-
- emit(Fd, " if ((oe_error_code = ei_decode_atom(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- emit_c_enc_rpt(Fd, " ", "ei_decode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " return 0;\n\n",[]),
- emit(Fd, "}\n\n",[]).
-
-
-emit_encode(G, _N, Fd, HFd, Name, _Elist) ->
-
- emit(HFd, "int ~s~s(CORBA_Environment *oe_env, ~s);\n",
- [ic_util:mk_oe_name(G, "encode_"), Name, Name]),
-
- emit(Fd, "int ~s~s(CORBA_Environment *oe_env, ~s oe_rec) {\n",
- [ic_util:mk_oe_name(G, "encode_"), Name, Name]),
- emit(Fd, " int oe_error_code = 0;\n\n",[]),
-
- emit(Fd, " if ((oe_error_code = oe_ei_encode_atom(oe_env, ~s[oe_rec])) < 0) {\n",
- [ic_util:mk_oe_name(G, Name)]),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit(Fd, " return 0;\n\n",[]),
- emit(Fd, "}\n\n",[]).
-
-emit_decode(G, _N, Fd, HFd, Name, Elist) ->
-
- emit(HFd, "int ~s~s(CORBA_Environment *oe_env, char *, int*, ~s *);\n",
- [ic_util:mk_oe_name(G, "decode_"), Name, Name]),
-
- emit(Fd, "int ~s~s(CORBA_Environment *oe_env, char *oe_first, int* oe_outindex, "
- "~s *oe_out) {\n\n",
- [ic_util:mk_oe_name(G, "decode_"), Name, Name]),
- emit(Fd, " int oe_error_code = 0;\n",[]),
- emit(Fd, " int oe_i;\n",[]),
- emit(Fd, " char oe_atom[256];\n\n",[]),
-
- AlignName = lists:concat(["*oe_outindex + sizeof(",Name,")"]),
- emit(Fd, " *oe_outindex = ~s;\n\n",[ic_util:mk_align(AlignName)]),
-
- emit(Fd, " if ((oe_error_code = ei_decode_atom(oe_env->_inbuf, &oe_env->_iin, oe_atom)) < 0) {\n"),
- emit_c_enc_rpt(Fd, " ", "ei_decode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- Len = length(Elist),
- emit(Fd, " for(oe_i = 0; oe_i < ~p && strcmp(oe_atom, ~s[oe_i]); oe_i++);\n",
- [Len, ic_util:mk_oe_name(G, Name)]),
- emit(Fd, " *oe_out = oe_i;\n\n", []),
-
- emit(Fd, " if (oe_i == ~p) {\n",[Len]),
- emit_c_enc_rpt(Fd, " ", "decode atom failure", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit(Fd, " return 0;\n",[]),
- emit(Fd, "}\n\n",[]).
-
-
-
-
-
diff --git a/lib/ic/src/iceval.erl b/lib/ic/src/iceval.erl
deleted file mode 100644
index a93e60124c..0000000000
--- a/lib/ic/src/iceval.erl
+++ /dev/null
@@ -1,556 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(iceval).
-
--include("icforms.hrl").
-
--export([eval_const/5, eval_e/5]).
-
--export([check_tk/3, get_val/1, mk_val/1]).
-
--define(get_max(__X, __Y), if __X > __Y -> __X; true -> __Y end).
--define(get_min(__X, __Y), if __X > __Y -> __Y; true -> __X end).
-
--define(BASE, 100000000000000000000000000000000).
--define(FIXED_MAX, 9999999999999999999999999999999).
-
-%% Called fr: ictype 99, 522, 533
-%% Fixed constants can be declared as:
-%% (1) const fixed pi = 3.14D; or
-%% (2) typedef fixed<3,2> f32;
-%% const f32 pi = 3.14D;
-%% Hence, if fixed is declared as (1) we must handle it especially.
-eval_const(G, S, N, tk_fixed, Expr) ->
- case catch eval_e(G, S, N, tk_fixed, Expr) of
- T when element(1, T) == error -> 0;
- V when is_record(V, fixed) ->
- {ok, {tk_fixed, V#fixed.digits, V#fixed.scale}, V};
- V ->
- ic_error:error(G, {bad_tk_match, Expr, tk_fixed, get_val(V)})
- end;
-eval_const(G, S, N, TK, Expr) ->
- case catch eval_e(G, S, N, TK, Expr) of
- T when element(1, T) == error -> 0;
- V ->
- case check_tk(G, TK, V) of
- true -> ok;
- false ->
- ic_error:error(G, {bad_tk_match, Expr, TK, get_val(V)})
- end,
- get_val(V)
- end.
-
-
-check_op(G, S, N, Tk, Types, Op, E1, E2) ->
- V1 = eval_e(G, S, N, Tk, E1),
- V2 = eval_e(G, S, N, Tk, E2),
- check_types(G, Op, E1, Types, V1),
- check_types(G, Op, E2, Types, V2),
- case check_comb(V1, V2) of
- true ->
- {V1, V2};
- false ->
- Err = {bad_type_combination, E1, get_val(V1), get_val(V2)},
- ic_error:error(G, Err),
- throw({error, Err})
- end.
-
-check_op(G, S, N, Tk, Types, Op, E1) ->
- V1 = eval_e(G, S, N, Tk, E1),
- check_types(G, Op, E1, Types, V1),
- V1.
-
-%% Match the declared type TK against the factual value of an constant
-%%
-check_tk(_G, _Any, default) -> true; % Default case in union
-check_tk(_G, positive_int, V) when is_integer(V) andalso V >= 0 -> true;
-check_tk(_G, tk_long, V) when is_integer(V) -> true;
-check_tk(_G, tk_longlong, V) when is_integer(V) -> true; %% LLON_G
-check_tk(_G, tk_short, V) when is_integer(V) -> true;
-check_tk(_G, tk_ushort, V) when is_integer(V) andalso V >= 0 -> true;
-check_tk(_G, tk_ulong, V) when is_integer(V) andalso V >= 0 -> true;
-check_tk(_G, tk_ulonglong, V) when is_integer(V) andalso V >= 0 -> true; %% ULLON_G
-check_tk(_G, tk_float, V) when is_float(V) -> true;
-check_tk(_G, tk_double, V) when is_float(V) -> true;
-check_tk(_G, tk_boolean, V) -> is_bool(V);
-check_tk(_G, tk_char, {char, _V}) -> true;
-check_tk(_G, tk_wchar, {wchar, _V}) -> true; %% WCHAR
-check_tk(_G, {tk_string, _Len}, {string, _V}) -> true;
-check_tk(_G, {tk_wstring, _Len}, {wstring, _V}) -> true; %% WSTRING
-check_tk(_G, {tk_fixed, Digits, Scale}, {fixed, Digits, Scale, _V}) -> true;
-check_tk(_G, tk_octet, V) when is_integer(V) -> true;
-%%check_tk(_G, tk_null, V) when integer(V) -> true;
-%%check_tk(_G, tk_void, V) when integer(V) -> true;
-%%check_tk(_G, tk_any, V) when integer(V) -> true;
-%%check_tk(_G, {tk_objref, "", "Object"}, V) when integer(V) -> true.
-check_tk(_G, {tk_enum, _, _, Body}, {enum_id, Id}) ->
- until(fun(X) when X == Id -> true;
- (_X) ->
- false
- end, Body);
-check_tk(_G, _TK, _V) ->
- false.
-
-get_val({string, X}) -> X;
-get_val({wstring, X}) -> X; %% WCHAR
-get_val({char, X}) -> X;
-get_val({wchar, X}) -> X; %% WSTRING
-get_val({enum_id, X}) -> X;
-get_val(X) -> X.
-
-check_types(G, Op, Expr, TypeList, V) ->
- case until(fun(int) when is_integer(V) -> true;
- (float) when is_float(V) -> true;
- (bool) when V==true -> true;
- (bool) when V==false -> true;
- (fixed) when is_record(V, fixed) -> true;
- (_) -> false end,
- TypeList) of
- true -> true;
- false ->
- Err = {bad_type, Expr, Op, TypeList, V},
- ic_error:error(G, Err),
- throw({error, Err})
- end.
-
-%%get_op(T) when tuple(T) -> element(1, T).
-
-%% Should be in lists
-until(F, [H|T]) ->
- case F(H) of
- true -> true;
- false -> until(F, T)
- end;
-until(_F, []) -> false.
-
-%% Section of all the boolean operators (because Erlang ops don't like
-%% boolean values.
-e_or(X, Y) when is_integer(X) andalso is_integer(Y) -> X bor Y;
-e_or(true, _) -> true;
-e_or(_, true) -> true;
-e_or(_, _) -> false.
-
-e_and(X, Y) when is_integer(X) andalso is_integer(Y) -> X band Y;
-e_and(true, true) -> true;
-e_and(_, _) -> false.
-
-e_xor(X, Y) when is_integer(X) andalso is_integer(Y) -> X bxor Y;
-e_xor(X, X) -> false;
-e_xor(_, _) -> true.
-
-%% Handling infix operators (+,-,*,/) for fixed type.
-%% Boundries determined as fixed<max(d1-s1,d2-s2) + max(s1,s2) + 1, max(s1,s2)>
-e_fixed_add(#fixed{digits = D1, scale = S1, value = V1},
- #fixed{digits = D2, scale = S2, value = V2}) ->
- Scale = ?get_max(S1, S2),
- Digits = ?get_max((D1-S1), (D2-S2)) + Scale +1,
- %% We must normalize the values before adding. Why?
- %% 4.23 and 5.2 are represented as 423 and 52. To be able to get the
- %% correct result we must add 4230 and 5200 == 9430.
- {PV1, PV2} = normalize(S1, V1, S2, V2),
- check_fixed_overflow(#fixed{digits = Digits,
- scale = Scale,
- value = (PV1 + PV2)}).
-
-%% Boundries determined as fixed<max(d1-s1,d2-s2) + max(s1,s2) + 1, max(s1,s2)>
-e_fixed_sub(#fixed{digits = D1, scale = S1, value = V1},
- #fixed{digits = D2, scale = S2, value = V2}) ->
- Scale = ?get_max(S1, S2),
- Digits = ?get_max((D1-S1), (D2-S2)) + Scale +1,
- {PV1, PV2} = normalize(S1, V1, S2, V2),
- check_fixed_overflow(#fixed{digits = Digits,
- scale = Scale,
- value = (PV1 - PV2)}).
-
-%% Boundries determined as fixed<d1+d2, s1+s2>
-e_fixed_mul(#fixed{digits = D1, scale = S1, value = V1},
- #fixed{digits = D2, scale = S2, value = V2}) ->
- check_fixed_overflow(#fixed{digits = (D1+D2),
- scale = (S1+S2),
- value = V1*V2}).
-
-%% Boundries determined as fixed<(d1-s1+s2) + s inf ,s inf>
-e_fixed_div(#fixed{digits = D1, scale = S1, value = V1},
- #fixed{digits = _D2, scale = S2, value = V2}) ->
- {PV1, PV2} = normalize(S1, V1, S2, V2),
- DigitsMin = (D1-S1+S2),
- R1 = (PV1 div PV2),
- R2 = (R1*?BASE + (PV1 rem PV2) * (?BASE div PV2)),
- {Result2, Sinf} = delete_zeros_value(R2, 0, R1),
- check_fixed_overflow(#fixed{digits = DigitsMin + Sinf, scale = Sinf,
- value = Result2}).
-
-
-%% Checks combination of argument types, basically floats and ints are
-%% interchangeable, and all types are allowed with themselves. No
-%% other combinations are allowed
-%%
-check_comb(X, Y) when is_integer(X) andalso is_integer(Y) -> true;
-check_comb(X, Y) when is_float(X) andalso is_integer(Y) -> true;
-check_comb(X, Y) when is_integer(X) andalso is_float(Y) -> true;
-check_comb(X, Y) when is_float(X) andalso is_float(Y) -> true;
-check_comb({X, _}, {X, _}) -> true; % Strings and chars are tuples
-check_comb({fixed, _, _, _}, {fixed, _, _, _}) -> true;
-check_comb(X, Y) ->
- case {is_bool(X), is_bool(Y)} of
- {true, true} ->
- true;
- _ ->
- false
- end.
-
-is_bool(true) -> true;
-is_bool(false) -> true;
-is_bool(_) -> false.
-
-
-%%%% (15)
-eval_e(G, S, N, Tk, {'or', T1, T2}) ->
- {E1, E2} = check_op(G, S, N, Tk, [int, bool], 'or', T1, T2),
- e_or(E1, E2);
-
-%%%% (16)
-eval_e(G, S, N, Tk, {'xor', T1, T2}) ->
- {E1, E2} = check_op(G, S, N, Tk, [int, bool], 'xor', T1, T2),
- e_xor(E1, E2);
-
-%%%% (17)
-eval_e(G, S, N, Tk, {'and', T1, T2}) ->
- {E1, E2} = check_op(G, S, N, Tk, [int, bool], 'and', T1, T2),
- e_and(E1, E2);
-
-%%%% (18)
-eval_e(G, S, N, Tk, {'rshift', T1, T2}) ->
- {E1, E2} = check_op(G, S, N, Tk, [int], 'rshift', T1, T2),
- E1 bsr E2;
-eval_e(G, S, N, Tk, {'lshift', T1, T2}) ->
- {E1, E2} = check_op(G, S, N, Tk, [int], 'lshift', T1, T2),
- E1 bsl E2;
-
-%%%% (19)
-eval_e(G, S, N, Tk, {'+', T1, T2}) ->
- case check_op(G, S, N, Tk, [int, float, fixed], '+', T1, T2) of
- {F1, F2} when is_record(F1,fixed) andalso is_record(F2,fixed) ->
- e_fixed_add(F1, F2);
- {E1, E2} ->
- E1 + E2
- end;
-eval_e(G, S, N, Tk, {'-', T1, T2}) ->
- case check_op(G, S, N, Tk, [int, float, fixed], '-', T1, T2) of
- {F1, F2} when is_record(F1,fixed) andalso is_record(F2,fixed) ->
- e_fixed_sub(F1, F2);
- {E1, E2} ->
- E1 - E2
- end;
-
-%%%% (20)
-eval_e(G, S, N, Tk, {'*', T1, T2}) ->
- case check_op(G, S, N, Tk, [int, float, fixed], '*', T1, T2) of
- {F1, F2} when is_record(F1,fixed) andalso is_record(F2,fixed) ->
- e_fixed_mul(F1, F2);
- {E1, E2} ->
- E1 * E2
- end;
-eval_e(G, S, N, Tk, {'/', T1, T2}) ->
- case check_op(G, S, N, Tk, [int, float, fixed], '/', T1, T2) of
- {F1, F2} when is_record(F1,fixed) andalso is_record(F2,fixed) ->
- e_fixed_div(F1, F2);
- {E1, E2} ->
- E1 / E2
- end;
-eval_e(G, S, N, Tk, {'%', T1, T2}) ->
- {E1, E2} = check_op(G, S, N, Tk, [int], '%', T1, T2),
- E1 rem E2;
-
-%%%% (21)
-eval_e(G, S, N, Tk, {{'-', _Line}, T}) ->
- case check_op(G, S, N, Tk, [int, float, fixed], '-', T) of
- F when is_record(F,fixed) ->
- F#fixed{value = -(F#fixed.value)};
- Number ->
- -Number
- end;
-eval_e(G, S, N, Tk, {{'+', _Line}, T}) ->
- check_op(G, S, N, Tk, [int, float, fixed], '+', T);
-eval_e(G, S, N, Tk, {{'~', Line}, T}) ->
- ic_error:error(G, {unsupported_op, {'~', Line}}),
- eval_e(G, S, N, Tk, T);
-
-
-%% Ints are repr. by an Erlang integer val, floats and doubles by
-%% Erlang floats, chars and strings must be tuplerized for type
-%% checking. These tuples are removed just before returning from top
-%% function.
-%%
-eval_e(_G, _S, _N, tk_fixed, {'<fixed_pt_literal>', _Line, X}) ->
- create_fixed(X);
-eval_e(G, _S, _N, {tk_fixed, Digits, Scale}, {'<fixed_pt_literal>', Line, X})
- when Digits < 32, Digits >= Scale ->
- case convert_fixed(X, [], Digits, Digits-Scale) of
- {error, Format, Args} ->
- ic_error:error(G, {bad_fixed, Format, Args, Line});
- FixedData ->
- {fixed, Digits, Scale, FixedData}
- end;
-eval_e(_G, _S, _N, _Tk, {'<integer_literal>', _Line, X}) -> list_to_integer(X);
-eval_e(_G, _S, _N, {tk_string,_}, {'<string_literal>', _Line, X}) -> {string, X};
-eval_e(_G, _S, _N, {tk_wstring,_}, {'<wstring_literal>', _Line, X}) -> {wstring, X}; %% WSTRING
-eval_e(_G, _S, _N, tk_char, {'<character_literal>', _Line, X}) -> {char, hd(X)};
-eval_e(_G, _S, _N, tk_wchar, {'<wcharacter_literal>', _Line, X}) -> {wchar, hd(X)}; %% WCHAR
-eval_e(_G, _S, _N, _Tk, {'TRUE', _Line}) -> true;
-eval_e(_G, _S, _N, _Tk, {'FALSE', _Line}) -> false;
-eval_e(_G, _S, _N, _Tk, {'<floating_pt_literal>', _Line, X}) -> to_float(X);
-%% Some possible error conditions
-eval_e(_G, _S, _N, _Tk, {'<character_literal>', _Line, X}) -> {char, hd(X)}; %% ERROR?
-%%
-eval_e(G, S, N, _Tk, X) when element(1, X) == scoped_id ->
- mk_val(ictype:scoped_lookup(G, S, N, X));
-eval_e(_G, _S, _N, _Tk, {default, _}) -> default; % Default case in union
-eval_e(G, _S, _N, Tk, Val) ->
- ic_error:error(G, {plain_error_string, Val,
- io_lib:format("value and declared type ~p differ", [Tk])}).
-
-%% A fixed type can be 123.45 or 123 but we represent it as integers (i.e. 12345 or 123).
-convert_fixed([], Acc, 0, _) ->
- list_to_integer(lists:reverse(Acc));
-convert_fixed([], _Acc, _, _) ->
- {error, "Fixed type do not match the digits field", []};
-convert_fixed([$.|Rest], Acc, Digits, 0) ->
- convert_fixed(Rest, Acc, Digits, -1);
-convert_fixed([$.|_Rest], _Acc, _, _) ->
- {error, "Fixed decimal point placed incorrectly", []};
-convert_fixed([X|Rest], Acc, Digits, Position) ->
- convert_fixed(Rest, [X|Acc], Digits-1, Position-1).
-
-
-create_fixed([$0|Rest]) ->
- %% Leading zeros shall be ignored.
- create_fixed(Rest);
-create_fixed(Fixed) ->
- create_fixed(Fixed, [], 0, 0, false).
-
-create_fixed([], Acc, Total, Frac, true) ->
- {Fixed, N} = remove_trailing_zeros(Acc, 0),
- Digits = Total-N,
- Scale = Frac-N,
- #fixed{digits = Digits, scale = Scale, value = list_to_integer(Fixed)};
-create_fixed([], Acc, Total, _Frac, false) ->
- %% A '.' never found. Hence, must be 2000D
- #fixed{digits = Total, scale = 0, value = list_to_integer(lists:reverse(Acc))};
-create_fixed([$.|Rest], Acc, Total, _, _) ->
- create_fixed(Rest, Acc, Total, 0, true);
-create_fixed([X|Rest], Acc, Total, Frac, FoundDot) ->
- create_fixed(Rest, [X|Acc], Total+1, Frac+1, FoundDot).
-
-remove_trailing_zeros([$0|Rest], N) ->
- remove_trailing_zeros(Rest, N+1);
-remove_trailing_zeros(Fixed, N) ->
- {lists:reverse(Fixed), N}.
-
-%% Make the newly looked up value a value that can be type checked.
-mk_val({_, _, {tk_string, _}, V}) -> {string, V};
-mk_val({_, _, {tk_wstring, _}, V}) -> {wstring, V}; %% WSTRING
-mk_val({_, _, tk_char, V}) -> {char, V};
-mk_val({_, _, tk_wchar, V}) -> {wchar, V}; %% WCHAR
-mk_val({_, _, enum_val, V}) ->
- {enum_id, ic_forms:get_id2(V)};
-mk_val(X) when element(1, X) == error -> X;
-mk_val({_, _, _TK, V}) ->
- V;
-mk_val(V) -> V.
-
-
-
-%% Floating point numbers
-%%
-%% Conversion to Erlang floating points is neccessary because
-%% list_to_float BIF differs from IDL floats. "1e2" ".4e2" is
-%% allowed in IDL and must be translated to "1.0e2" and "0.4e2"
-
-to_float(X) ->
- list_to_float(erlangify(X)).
-
-erlangify([$. | R]) ->
- [$0, $. | R];
-erlangify(R) ->
- look_for_dot(R).
-
-look_for_dot([$. | R]) -> [$. | dot_pending(R)];
-look_for_dot([$e | R]) -> [$., $0, $e | R];
-look_for_dot([$E | R]) -> [$., $0, $E | R];
-look_for_dot([X | R]) -> [X | look_for_dot(R)].
-
-dot_pending([$e | R]) -> [$0, $e | R];
-dot_pending([$E | R]) -> [$0, $E | R];
-dot_pending([]) -> [$0];
-dot_pending(R) -> R.
-
-
-%%------------------------------------------------------------------
-%%--------------- Fixed Datatype Helper Functions ------------------
-%%------------------------------------------------------------------
-%% Pretty?! No, but since we now the upper-limit this is the fastest way
-%% to calculate 10^x
-power(0) -> 1;
-power(1) -> 10;
-power(2) -> 100;
-power(3) -> 1000;
-power(4) -> 10000;
-power(5) -> 100000;
-power(6) -> 1000000;
-power(7) -> 10000000;
-power(8) -> 100000000;
-power(9) -> 1000000000;
-power(10) -> 10000000000;
-power(11) -> 100000000000;
-power(12) -> 1000000000000;
-power(13) -> 10000000000000;
-power(14) -> 100000000000000;
-power(15) -> 1000000000000000;
-power(16) -> 10000000000000000;
-power(17) -> 100000000000000000;
-power(18) -> 1000000000000000000;
-power(19) -> 10000000000000000000;
-power(20) -> 100000000000000000000;
-power(21) -> 1000000000000000000000;
-power(22) -> 10000000000000000000000;
-power(23) -> 100000000000000000000000;
-power(24) -> 1000000000000000000000000;
-power(25) -> 10000000000000000000000000;
-power(26) -> 100000000000000000000000000;
-power(27) -> 1000000000000000000000000000;
-power(28) -> 10000000000000000000000000000;
-power(29) -> 100000000000000000000000000000;
-power(30) -> 1000000000000000000000000000000;
-power(31) -> 10000000000000000000000000000000;
-power(_) -> 10000000000000000000000000000000.
-
-
-
-%% If the result of an operation (+, -, * or /) causes overflow we use this
-%% operation. However, since these calculations are performed during compiletime,
-%% shouldn't the IDL-specification be changed to not cause overflow?! But, since
-%% the OMG standard allows this we must support it.
-check_fixed_overflow(#fixed{digits = Digits, scale = Scale, value = Value}) ->
- case count_digits(abs(Value)) of
- overflow ->
- {N, NewVal} = cut_overflow(0, Value),
-% NewDigits = Digits - N,
- if
- N > Scale ->
- #fixed{digits = 31, scale = 0, value = NewVal};
- true ->
- NewScale = Scale - N,
- {NewVal2, Removed} = delete_zeros(NewVal, NewScale),
- #fixed{digits = 31, scale = NewScale-Removed, value = NewVal2}
- end;
- Count when Count > Digits ->
- Diff = Count-Digits,
- if
- Diff > Scale ->
- #fixed{digits = Digits, scale = 0,
- value = (Value div power(Diff))};
- true ->
- NewScale = Scale-Diff,
- {NewVal, Removed} = delete_zeros((Value div power(Diff)), NewScale),
- #fixed{digits = Digits-Removed,
- scale = NewScale-Removed,
- value = NewVal}
- end;
- Count ->
- {NewVal, Removed} = delete_zeros(Value, Scale),
- #fixed{digits = Count-Removed, scale = Scale-Removed, value = NewVal}
- end.
-
-%% This function see to that the values are of the same baase.
-normalize(S, V1, S, V2) ->
- {V1, V2};
-normalize(S1, V1, S2, V2) when S1 > S2 ->
- {V1, V2*power(S1-S2)};
-normalize(S1, V1, S2, V2) ->
- {V1*power(S2-S1), V2}.
-
-%% If we have access to the integer part of the fixed type we use this
-%% operation to remove all trailing zeros. If we know the scale, length of
-%% fraction part, we can use delete_zeros as well. But, after a division
-%% it's hard to know the scale and we don't need to calcluate the integer part.
-delete_zeros_value(0, N, _) ->
- {0, 32-N};
-delete_zeros_value(X, N, M) when X > M, (X rem 10) == 0 ->
- delete_zeros_value((X div 10), N+1, M);
-delete_zeros_value(X, N, _) ->
- {X, 32-N}.
-
-%% If we know the exact scale of a fixed type we can use this operation to
-%% remove all trailing zeros.
-delete_zeros(0, _) ->
- {0,0};
-delete_zeros(X, Max) ->
- delete_zeros(X, 0, Max).
-delete_zeros(X, Max, Max) ->
- {X, Max};
-delete_zeros(X, N, Max) when (X rem 10) == 0 ->
- delete_zeros((X div 10), N+1, Max);
-delete_zeros(X, N, _) ->
- {X, N}.
-
-cut_overflow(N, X) when X > ?FIXED_MAX ->
- cut_overflow(N+1, (X div 10));
-cut_overflow(N, X) ->
- {N, X}.
-
-%% A fast way to check the size of a fixed data type.
-count_digits(X) when X > ?FIXED_MAX -> overflow;
-count_digits(X) when X >= 1000000000000000000000000000000 -> 31;
-count_digits(X) when X >= 100000000000000000000000000000 -> 30;
-count_digits(X) when X >= 10000000000000000000000000000 -> 29;
-count_digits(X) when X >= 1000000000000000000000000000 -> 28;
-count_digits(X) when X >= 100000000000000000000000000 -> 27;
-count_digits(X) when X >= 10000000000000000000000000 -> 26;
-count_digits(X) when X >= 1000000000000000000000000 -> 25;
-count_digits(X) when X >= 100000000000000000000000 -> 24;
-count_digits(X) when X >= 10000000000000000000000 -> 23;
-count_digits(X) when X >= 1000000000000000000000 -> 22;
-count_digits(X) when X >= 100000000000000000000 -> 21;
-count_digits(X) when X >= 10000000000000000000 -> 20;
-count_digits(X) when X >= 1000000000000000000 -> 19;
-count_digits(X) when X >= 100000000000000000 -> 18;
-count_digits(X) when X >= 10000000000000000 -> 17;
-count_digits(X) when X >= 1000000000000000 -> 16;
-count_digits(X) when X >= 100000000000000 -> 15;
-count_digits(X) when X >= 10000000000000 -> 14;
-count_digits(X) when X >= 1000000000000 -> 13;
-count_digits(X) when X >= 100000000000 -> 12;
-count_digits(X) when X >= 10000000000 -> 11;
-count_digits(X) when X >= 1000000000 -> 10;
-count_digits(X) when X >= 100000000 -> 9;
-count_digits(X) when X >= 10000000 -> 8;
-count_digits(X) when X >= 1000000 -> 7;
-count_digits(X) when X >= 100000 -> 6;
-count_digits(X) when X >= 10000 -> 5;
-count_digits(X) when X >= 1000 -> 4;
-count_digits(X) when X >= 100 -> 3;
-count_digits(X) when X >= 10 -> 2;
-count_digits(_X) -> 1.
-
-%%------------------------------------------------------------------
-%%--------------- END Fixed Datatype Helper Functions --------------
-%%------------------------------------------------------------------
diff --git a/lib/ic/src/icforms.hrl b/lib/ic/src/icforms.hrl
deleted file mode 100644
index f71aee3664..0000000000
--- a/lib/ic/src/icforms.hrl
+++ /dev/null
@@ -1,70 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%
-%% Module documentation:
-%% ---------------------
-%%
-%% Header file for the Erlang IDL compiler. Contains all records
-%% used in the parse tree
-%%
-%%
-%%------------------------------------------------------------
-
-
-
-%%------------------------------------------------------------
-
--record(module, {id, body}).
--record(interface, {id, inherit, body, inherit_body, tk}).
--record(forward, {id, tk}).
--record(constr_forward, {id, tk}).
--record(const, {type, id, val, tk}).
--record(type_dcl, {type, tk}).
--record(typedef, {type, id, tk}).
--record(struct, {id, body, tk}).
--record(member, {type, id}).
--record(union, {id, type, body, tk}).
--record(case_dcl, {label, id, type}).
--record(enum, {id, body, tk}).
--record(enumerator, {id}).
--record(sequence, {type, length=0}).
--record(string, {length=0}).
--record(wstring, {length=0}). %% WSTRING
--record(array, {id, size}).
--record(attr, {readonly, type, id, tk}).
--record(except, {id, body, tk}).
--record(op, {oneway, type, id, params, raises, ctx, tk}).
--record(param, {inout, type, id, tk}).
--record(fixed, {digits, scale, value}).
-
-%% NON-STANDARD
--record(preproc, {cat, id, aux}).
--record(pragma, {type, to, apply}).
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/src/icparse.yrl b/lib/ic/src/icparse.yrl
deleted file mode 100644
index 27e949729c..0000000000
--- a/lib/ic/src/icparse.yrl
+++ /dev/null
@@ -1,872 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%------------------------------------------------------------
-%% Yecc spec for IDL
-%%
-%%
-%%
-%% Implementation Detail:
-%% OorM_ means OneORMany and is used instead of
-%% the "+" BNF notation
-%% ZorM_ means ZeroORMany and is used instead of
-%% the "*" BNF notation
-%%
-%% All the reverse/1 calls are because yecc+lists naturally leads
-%% to reversed lists, which then have to be reversed. Maybe fix
-%% this?
-%%
-%% Implementation history
-%%
-%% The IDL language supported is not the complete IDL. We skipped
-%% the multiple declarator syntax allowed (i.e. typedef long T1,
-%% T2). This also applies to attributes members in structs,
-%% unions and exceptions, and to case labels in unions. The cases
-%% where IDL has been altered is marked with comments containing
-%% NIY.
-%%
-%% Above is chaging. Whenever we change a clause, we put (FIXED) in
-%% its comment.
-%%
-%%------------------------------------------------------------
-
-
-
-
-
-Nonterminals
- '<op_type_spec>'
- '<enumerator>'
- '<switch_body>'
- 'OorM_<case>'
- '<member_list>'
- '<struct_type>'
- '<unsigned_int>'
- '<constr_type_spec>'
- '<shift_expr>'
- '<or_expr>'
- '<inheritance_spec>'
- 'ZorM_<param_dcl>'
- 'Opt_<context_expr>'
- '<attr_dcl>'
- '<array_declarator>'
- '<element_spec>'
- '<signed_int>'
- '<primary_expr>'
- '<interface_dcl>'
- 'ZorM_<string_literal>'
- 'Opt_<raises_expr>'
- '<integer_type>'
- '<signed_long_int>'
- '<literal>'
- '<export>'
- '<forward_dcl>'
- 'OorM_<definition>'
- '<base_type_spec>'
- '<op_dcl>'
- '<const_exp>'
- '<case>'
- '<any_type>'
- '<signed_short_int>'
- '<unary_expr>'
- '<context_expr>'
- 'ZorM_<scoped_name>'
- '<switch_type_spec>'
- '<complex_declarator>'
- '<declarators>'
- 'OorM_<member>'
- '<interface>'
- '<parameter_dcls>'
- '<op_attribute>'
- '<positive_int_const>'
- 'OorM_<fixed_array_size>'
- '<sequence_type>'
- '<case_label>'
- '<octet_type>'
- '<type_dcl>'
- '<module>'
- '<specification>'
- '<declarator>'
- '<boolean_type>'
- '<union_type>'
- '<add_expr>'
- '<interface_body>'
- '<except_dcl>'
- '<fixed_array_size>'
- '<unsigned_short_int>'
- '<boolean_literal>'
- '<and_expr>'
- 'Opt_<inheritance_spec>'
- '<scoped_name>'
- '<param_type_spec>'
- 'ZorM_<member>'
- '<char_type>'
- '<const_dcl>'
- '<param_dcl>'
- 'ZorM_<simple_declarator>'
- 'ZorM_<declarator>'
- '<const_type>'
- '<definition>'
- '<param_attribute>'
- '<simple_declarator>'
- 'Opt_readonly'
- '<simple_type_spec>'
- '<enum_type>'
- '<type_spec>'
- 'OorM_<case_label>'
- '<floating_pt_type>'
- '<template_type_spec>'
- '<mult_expr>'
- '<xor_expr>'
- '<string_type>'
- '<raises_expr>'
- 'Opt_<op_attribute>'
- 'ZorM_<enumerator>'
- '<member>'
- '<unsigned_long_int>'
- '<type_declarator>'
- '<unary_operator>'
- 'ZorM_<export>'
- '<interface_header>'
- 'OE_preproc' % NON standard
- 'OE_pragma' % NON standard
- 'Ugly_pragmas' % NON standard
- 'ZorM_<integer_literal>'
- '<fixed_pt_type>'
- '<fixed_pt_const_type>'
- '<constr_forward_decl>'
- .
-
-
-Terminals
- '#'
- 'in'
- '['
- 'interface'
- '('
- 'case'
- 'union'
- 'struct'
- '<character_literal>'
- '<wcharacter_literal>'
- ')'
- ']'
- 'any'
- 'long'
- 'float'
- 'out'
- '*'
- '^'
- 'enum'
- 'double'
- '+'
- 'context'
- 'oneway'
- 'sequence'
- ','
- 'FALSE'
- '<identifier>'
- '{'
- 'readonly'
- ':'
- '-'
- 'void'
- ';'
- 'char'
- 'wchar' %% WCHAR
- '|'
- 'inout'
- '}'
- 'attribute'
- '<'
- 'octet'
- '/'
- 'TRUE'
- '~'
- '='
- '>'
- 'switch'
- 'unsigned'
- 'typedef'
- '>>'
- 'const'
- '<string_literal>'
- '<wstring_literal>'
- 'raises'
- 'string'
- 'wstring'
- 'fixed'
- 'default'
- 'short'
- '%'
- '<<'
- 'module'
- 'exception'
- 'boolean'
- '<integer_literal>'
- '<fixed_pt_literal>'
- '<floating_pt_literal>'
- '&'
- '::'
- 'Object'
- .
-
-
-Rootsymbol '<specification>'.
-
-
-Expect 9.
-
-
-%%------------------------------------------------------------
-%% Clauses
-%%
-
-%% Handling of pragmas.
-%% Pragma prefix, id and version are not standard.
-
-%% pragma prefix, or codeopt
-OE_pragma -> '#' '<integer_literal>' '<identifier>'
- '<identifier>' '<string_literal>' '#'
- : #pragma{type='$4', to=followed, apply='$5'} .
-
-%% pragma id
-OE_pragma -> '#' '<integer_literal>' '<identifier>'
- '<identifier>' '<identifier>' '<string_literal>' '#'
- : #pragma{type='$4', to='$5', apply='$6'} .
-
-%% pragma version
-OE_pragma -> '#' '<integer_literal>' '<identifier>'
- '<identifier>' '<identifier>' '<floating_pt_literal>' '#'
- : #pragma{type='$4', to='$5', apply=ic_options:float_to_version('$6')} .
-
-
-
-
-
-
-
-%% Ugly pragmas
-Ugly_pragmas -> '$empty' : [].
-Ugly_pragmas -> 'Ugly_pragmas' 'OE_pragma' : ['$2'|'$1'].
-
-
-
-%% (0) Handling of preprocessor stuff.
-
-OE_preproc -> '#' '#' .
-
-OE_preproc -> '#' '<integer_literal>' '<string_literal>'
- 'ZorM_<integer_literal>' '#'
- : case '$4' of
- [] ->
- case '$2' of
- {_,_,"1"} ->
- #preproc{cat=line_nr, id='$3', aux='$4'};
- _ ->
- []
- end;
- _ ->
- #preproc{cat=line_nr, id='$3', aux='$4'}
- end.
-
-%% (0b) Non-standard
-'ZorM_<integer_literal>' -> '$empty' : [] .
-'ZorM_<integer_literal>' -> '<integer_literal>' 'ZorM_<integer_literal>'
- : ['$1' | '$2'] .
-
-%% (1)
-'<specification>' -> 'OorM_<definition>' : reverse('$1') .
-
-
-%% Added clause
-'OorM_<definition>' -> '<definition>' : ['$1'] .
-'OorM_<definition>' -> 'OorM_<definition>' '<definition>'
-: ['$2' | '$1'] .
-
-
-%% (2)
-'<definition>' -> '<type_dcl>' ';' : '$1' .
-'<definition>' -> '<const_dcl>' ';' : '$1' .
-'<definition>' -> '<except_dcl>' ';' : '$1' .
-'<definition>' -> '<interface>' ';' : '$1' .
-'<definition>' -> '<module>' ';' : '$1' .
-'<definition>' -> 'OE_preproc' : '$1' .
-'<definition>' -> 'OE_pragma' : '$1' .
-
-
-%% (3)
-'<module>' -> 'module' '<identifier>' '{' 'OorM_<definition>' '}'
-: #module{ id='$2', body=reverse('$4')}.
-
-
-%% (4)
-'<interface>' -> '<interface_dcl>' : '$1' .
-'<interface>' -> '<forward_dcl>' : '$1' .
-
-
-%% (5)
-'<interface_dcl>' -> '<interface_header>' '{' '<interface_body>' '}'
- : #interface{id=element(1, '$1'), inherit=element(2, '$1'),
- body=lists:reverse('$3')} .
-
-
-%% (6)
-'<forward_dcl>' -> 'interface' '<identifier>'
-: #forward{id='$2'} .
-
-
-%% (7)
-'<interface_header>' -> 'interface' '<identifier>' 'Opt_<inheritance_spec>'
-: {'$2', '$3'} .
-
-
-%% (8)
-'<interface_body>' -> 'ZorM_<export>' : '$1' .
-
-
-%% Added clause
-'ZorM_<export>' -> '$empty' : [] .
-'ZorM_<export>' -> 'ZorM_<export>' '<export>'
- %% Complicated because <export> might be a list (of type defs for instance)
- : if is_list('$2') -> '$2' ++ '$1';
- true -> ['$2' | '$1']
- end .
-
-
-%% (9)
-'<export>' -> '<type_dcl>' ';' : '$1' .
-'<export>' -> '<const_dcl>' ';' : '$1' .
-'<export>' -> '<except_dcl>' ';' : '$1' .
-'<export>' -> '<attr_dcl>' ';' : '$1' .
-'<export>' -> '<op_dcl>' ';' : '$1' .
-'<export>' -> 'OE_preproc' : '$1' .
-'<export>' -> 'OE_pragma' : '$1' .
-
-%% Added clause
-'Opt_<inheritance_spec>' -> '$empty' : [].
-'Opt_<inheritance_spec>' -> '<inheritance_spec>' : '$1'.
-
-%% (10)
-'<inheritance_spec>' -> ':' '<scoped_name>' 'ZorM_<scoped_name>'
- : ['$2' | reverse('$3')] .
-
-
-%% Added clause
-'ZorM_<scoped_name>' -> '$empty' : [] .
-'ZorM_<scoped_name>' -> 'ZorM_<scoped_name>' ',' '<scoped_name>'
- : ['$3' | '$1'] .
-
-
-%% (11)
-'<scoped_name>' -> '<identifier>' : ic_symtab:scoped_id_new('$1') .
-'<scoped_name>' -> '::' '<identifier>' : ic_symtab:scoped_id_new_global('$2') .
-'<scoped_name>' -> '<scoped_name>' '::' '<identifier>'
- : ic_symtab:scoped_id_add('$1', '$3') .
-
-
-%% (12)
-'<const_dcl>' -> 'const' '<const_type>' '<identifier>' '=' '<const_exp>'
- : #const{type='$2', id='$3', val='$5'} .
-
-
-%% (13)
-'<const_type>' -> '<integer_type>' : '$1' .
-'<const_type>' -> '<char_type>' : '$1' .
-'<const_type>' -> '<boolean_type>' : '$1' .
-'<const_type>' -> '<floating_pt_type>' : '$1' .
-'<const_type>' -> '<string_type>' : '$1' .
-'<const_type>' -> '<fixed_pt_const_type>' : '$1' .
-'<const_type>' -> '<scoped_name>' : '$1' .
-'<const_type>' -> '<octet_type>' : '$1' .
-
-
-%% (14)
-'<const_exp>' -> '<or_expr>' : '$1' .
-
-
-%% (15)
-'<or_expr>' -> '<xor_expr>' : '$1' .
-'<or_expr>' -> '<or_expr>' '|' '<xor_expr>' : {'or', '$1', '$3'} .
-
-
-%% (16)
-'<xor_expr>' -> '<and_expr>' : '$1' .
-'<xor_expr>' -> '<xor_expr>' '^' '<and_expr>' : {'xor', '$1', '$3'} .
-
-
-%% (17)
-'<and_expr>' -> '<shift_expr>' : '$1' .
-'<and_expr>' -> '<and_expr>' '&' '<shift_expr>' : {'and', '$1', '$3'} .
-
-
-%% (18)
-'<shift_expr>' -> '<add_expr>' : '$1' .
-'<shift_expr>' -> '<shift_expr>' '>>' '<add_expr>' : {'rshift', '$1', '$3'} .
-'<shift_expr>' -> '<shift_expr>' '<<' '<add_expr>' : {'lshift', '$1', '$3'} .
-
-
-%% (19)
-'<add_expr>' -> '<mult_expr>' : '$1' .
-'<add_expr>' -> '<add_expr>' '+' '<mult_expr>' : {'+', '$1', '$3'} .
-'<add_expr>' -> '<add_expr>' '-' '<mult_expr>' : {'-', '$1', '$3'} .
-
-
-%% (20)
-'<mult_expr>' -> '<unary_expr>' : '$1' .
-'<mult_expr>' -> '<mult_expr>' '*' '<unary_expr>' : {'*', '$1', '$3'} .
-'<mult_expr>' -> '<mult_expr>' '/' '<unary_expr>' : {'/', '$1', '$3'} .
-'<mult_expr>' -> '<mult_expr>' '%' '<unary_expr>' : {'%', '$1', '$3'} .
-
-
-%% (21)
-'<unary_expr>' -> '<unary_operator>' '<primary_expr>' : {'$1', '$2'} .
-'<unary_expr>' -> '<primary_expr>' : '$1' .
-
-
-%% (22)
-'<unary_operator>' -> '-' : '$1' .
-'<unary_operator>' -> '+' : '$1' .
-'<unary_operator>' -> '~' : '$1' .
-
-
-%% (23)
-'<primary_expr>' -> '<scoped_name>' : '$1' .
-'<primary_expr>' -> '<literal>' : '$1' .
-'<primary_expr>' -> '(' '<const_exp>' ')' : '$2' .
-
-
-%% (24)
-'<literal>' -> '<integer_literal>' : '$1' .
-'<literal>' -> '<wstring_literal>' : '$1' .
-'<literal>' -> '<string_literal>' : '$1' .
-'<literal>' -> '<character_literal>' : '$1' .
-'<literal>' -> '<wcharacter_literal>' : '$1' .
-'<literal>' -> '<fixed_pt_literal>' : '$1' .
-'<literal>' -> '<floating_pt_literal>' : '$1' .
-'<literal>' -> '<boolean_literal>' : '$1' .
-
-
-%% (25)
-'<boolean_literal>' -> 'TRUE' : '$1' .
-'<boolean_literal>' -> 'FALSE' : '$1' .
-
-
-%% (26)
-'<positive_int_const>' -> '<const_exp>' : '$1' .
-
-
-%% (27)
-'<type_dcl>' -> 'typedef' '<type_declarator>' : '$2' .
-'<type_dcl>' -> '<struct_type>' : '$1' .
-'<type_dcl>' -> '<union_type>' : '$1' .
-'<type_dcl>' -> '<enum_type>' : '$1' .
-'<type_dcl>' -> '<constr_forward_decl>' : '$1' .
-
-%% (28) NIY multiple declarators (FIXED)
-'<type_declarator>' -> '<type_spec>' '<declarators>'
- : #typedef{type='$1', id='$2'} . %%%ic:unfold(#typedef{type='$1', id='$2'}) .
-%%'<type_declarator>' -> '<type_spec>' '<declarator>'
-%% : #typedef{type='$1', id='$2'} .
-
-%% (29)
-'<type_spec>' -> '<simple_type_spec>' : '$1' .
-'<type_spec>' -> '<constr_type_spec>' : '$1' .
-
-
-%% (30)
-'<simple_type_spec>' -> '<base_type_spec>' : '$1' .
-'<simple_type_spec>' -> '<template_type_spec>' : '$1' .
-'<simple_type_spec>' -> '<scoped_name>' : '$1' .
-
-
-%% (31)
-'<base_type_spec>' -> '<floating_pt_type>' : '$1' .
-'<base_type_spec>' -> '<integer_type>' : '$1' .
-'<base_type_spec>' -> '<char_type>' : '$1' .
-'<base_type_spec>' -> '<boolean_type>' : '$1' .
-'<base_type_spec>' -> '<octet_type>' : '$1' .
-'<base_type_spec>' -> '<any_type>' : '$1' .
-'<base_type_spec>' -> 'Object' : '$1' . %% NON Standard, isn't a base type
-
-
-%% (32)
-'<template_type_spec>' -> '<sequence_type>' : '$1' .
-'<template_type_spec>' -> '<string_type>' : '$1' .
-'<template_type_spec>' -> '<fixed_pt_type>' : '$1' .
-
-
-%% (33)
-'<constr_type_spec>' -> '<struct_type>' : '$1' .
-'<constr_type_spec>' -> '<union_type>' : '$1' .
-'<constr_type_spec>' -> '<enum_type>' : '$1' .
-
-
-%% (34)
-'<declarators>' -> '<declarator>' 'ZorM_<declarator>'
-: ['$1' | reverse('$2')] .
-
-%% Added clause
-'ZorM_<declarator>' -> '$empty' : [] .
-'ZorM_<declarator>' -> 'ZorM_<declarator>' ',' '<declarator>'
-: ['$3' | '$1'] .
-
-
-%% (35)
-'<declarator>' -> '<simple_declarator>' : '$1' .
-'<declarator>' -> '<complex_declarator>' : '$1' .
-
-
-%% (36)
-'<simple_declarator>' -> '<identifier>' : '$1' .
-
-
-%% (37)
-'<complex_declarator>' -> '<array_declarator>' : '$1' .
-
-
-%% (38)
-'<floating_pt_type>' -> 'float' : '$1' .
-'<floating_pt_type>' -> 'double' : '$1' .
-
-
-%% (39)
-'<integer_type>' -> '<signed_int>' : '$1' .
-'<integer_type>' -> '<unsigned_int>' : {'unsigned', '$1'} .
-
-
-%% (40)
-'<signed_int>' -> '<signed_long_int>' : '$1' .
-'<signed_int>' -> '<signed_short_int>' : '$1' .
-
-
-%% (41)
-'<signed_long_int>' -> 'long' : '$1' .
-'<signed_long_int>' -> 'long' 'long': {'long long', element(2,'$2')} .
-
-
-%% (42)
-'<signed_short_int>' -> 'short' : '$1' .
-
-
-%% (43)
-'<unsigned_int>' -> '<unsigned_long_int>' : '$1' .
-'<unsigned_int>' -> '<unsigned_short_int>' : '$1' .
-
-
-%% (44)
-'<unsigned_long_int>' -> 'unsigned' 'long' : '$2' .
-'<unsigned_long_int>' -> 'unsigned' 'long' 'long' : {'long long', element(2,'$2')} . %% ULLONG
-
-
-%% (45)
-'<unsigned_short_int>' -> 'unsigned' 'short' : '$2' .
-
-
-%% (46)
-'<char_type>' -> 'char' : '$1' .
-'<char_type>' -> 'wchar' : '$1' . %% WCHAR
-
-
-%% (47)
-'<boolean_type>' -> 'boolean' : '$1' .
-
-
-%% (48)
-'<octet_type>' -> 'octet' : '$1' .
-
-
-%% (49)
-'<any_type>' -> 'any' : '$1' .
-
-%%
-'<fixed_pt_const_type>' -> 'fixed' : '$1'.
-
-%% (50) NIY: unfolding of struct decls (FIXED)
-%%'<struct_type>' -> 'struct' '<identifier>' '{' '<member_list>' '}'
-%% : #struct{id='$2', body=ic:unfold('$4')} .
-'<struct_type>' -> 'struct' '<identifier>' '{' '<member_list>' '}'
- : #struct{id='$2', body='$4'} .
-
-
-%% (51)
-'<member_list>' -> 'OorM_<member>' : reverse('$1') .
-
-
-%% Added clause
-%%'OorM_<member>' -> '<member>' : ['$1'] .
-%%'OorM_<member>' -> 'OorM_<member>' '<member>'
-%% : ['$2' | '$1'] .
-
-'OorM_<member>' -> '<member>' : '$1' .
-'OorM_<member>' -> 'OorM_<member>' '<member>'
- : '$2' ++ '$1' .
-
-
-
-%% (52) NIY: member multiple declarators (FIXED)
-%%'<member>' -> '<type_spec>' '<declarators>' ';'
-%% : #member{type='$1', id='$2'} .
-
-'<member>' -> 'Ugly_pragmas' '<type_spec>' '<declarators>' 'Ugly_pragmas' ';' 'Ugly_pragmas'
- : '$1' ++ '$4' ++ '$6' ++ [#member{type='$2', id='$3'}] .
-
-
-%% (53) NIY: unfolding of union cases (FIXED)
-%%'<union_type>' -> 'union' '<identifier>' 'switch'
-%% '(' '<switch_type_spec>' ')' '{' '<switch_body>' '}'
-%% : #union{id='$2', type='$5', body=ic:unfold('$8')} .
-'<union_type>' -> 'union' '<identifier>' 'switch'
- '(' '<switch_type_spec>' ')' '{' '<switch_body>' '}'
- : #union{id='$2', type='$5', body='$8'} .
-
-
-%% (54)
-'<switch_type_spec>' -> '<integer_type>' : '$1' .
-'<switch_type_spec>' -> '<char_type>' : '$1' .
-'<switch_type_spec>' -> '<boolean_type>' : '$1' .
-'<switch_type_spec>' -> '<enum_type>' : '$1' .
-'<switch_type_spec>' -> '<scoped_name>' : '$1' .
-
-
-%% (55)
-'<switch_body>' -> 'OorM_<case>' : reverse(lists:flatten('$1')) .
-
-%%'<switch_body>' -> 'OorM_<case>' : '$1' .
-
-
-%% Added clause
-'OorM_<case>' -> '<case>' : ['$1'] .
-'OorM_<case>' -> 'OorM_<case>' '<case>' : ['$2' | '$1'] .
-
-
-%% (56) NIY thing: multiple case labels (FIXED)
-%%'<case>' -> 'OorM_<case_label>' '<element_spec>' ';'
-%% : '$2'#case_dcl{label=reverse('$1')} .
-
-'<case>' ->
- 'Ugly_pragmas' 'OorM_<case_label>'
- 'Ugly_pragmas' '<element_spec>'
- 'Ugly_pragmas' ';' 'Ugly_pragmas'
- : '$1' ++ '$3' ++ '$5' ++ '$7' ++ [ '$4'#case_dcl{label=reverse('$2')} ] .
-
-
-%% Added clause
-%%'OorM_<case_label>' -> '<case_label>' : ['$1'] .
-%%'OorM_<case_label>' -> 'OorM_<case_label>' '<case_label>' : ['$2' | '$1'] .
-
-'OorM_<case_label>' -> 'Ugly_pragmas' '<case_label>' 'Ugly_pragmas'
- : '$1' ++ ['$2'] ++ '$3' .
-'OorM_<case_label>' -> 'OorM_<case_label>' 'Ugly_pragmas' '<case_label>' 'Ugly_pragmas'
- : '$2' ++ ['$3'|'$1'] ++ '$4'.
-
-
-%% (57)
-'<case_label>' -> 'case' '<const_exp>' ':' : '$2' .
-'<case_label>' -> 'default' ':' : '$1' .
-
-
-%% (58)
-'<element_spec>' -> '<type_spec>' '<declarator>'
-: #case_dcl{type='$1', id='$2'} .
-
-
-%% (59)
-%%'<enum_type>' -> 'enum' '<identifier>'
-%%'{' '<enumerator>' 'ZorM_<enumerator>' '}'
-%%: #enum{id='$2', body=['$4' | reverse('$5')]} .
-
-'<enum_type>' -> 'enum' '<identifier>'
-'{' 'Ugly_pragmas' '<enumerator>' 'Ugly_pragmas' 'ZorM_<enumerator>' 'Ugly_pragmas' '}'
-: #enum{id='$2', body='$4'++'$6'++'$8'++['$5' | reverse('$7')]} .
-
-
-
-%% Added clause
-%%'ZorM_<enumerator>' -> '$empty' : [] .
-%%'ZorM_<enumerator>' -> 'ZorM_<enumerator>' ',' '<enumerator>' : ['$3' | '$1'] .
-
-'ZorM_<enumerator>' -> '$empty' : [] .
-'ZorM_<enumerator>' -> 'ZorM_<enumerator>' 'Ugly_pragmas' ',' 'Ugly_pragmas' '<enumerator>'
- : '$2'++'$4'++['$5' | '$1'] .
-
-%% (60)
-'<enumerator>' -> '<identifier>' : #enumerator{id='$1'} .
-
-
-%% (61)
-'<sequence_type>' -> 'sequence' '<' '<simple_type_spec>' ','
- '<positive_int_const>' '>'
- : #sequence{type='$3', length='$5'} .
-'<sequence_type>' -> 'sequence' '<' '<simple_type_spec>' '>'
- : #sequence{type='$3'} .
-
-
-%% (62)
-'<string_type>' -> 'string' '<' '<positive_int_const>' '>'
- : #string{length='$3'} .
-'<string_type>' -> 'string' : #string{} .
-
-'<string_type>' -> 'wstring' '<' '<positive_int_const>' '>' %% WSTRING
- : #wstring{length='$3'} .
-'<string_type>' -> 'wstring' : #wstring{} . %% WSTRING
-
-
-%% (63)
-'<array_declarator>' -> '<identifier>' 'OorM_<fixed_array_size>'
- : #array{id='$1', size=reverse('$2')} .
-
-
-%% Added clause
-'OorM_<fixed_array_size>' -> '<fixed_array_size>' : ['$1'] .
-'OorM_<fixed_array_size>' -> 'OorM_<fixed_array_size>' '<fixed_array_size>'
- : ['$2' | '$1'] .
-
-
-%% (64)
-'<fixed_array_size>' -> '[' '<positive_int_const>' ']' : '$2' .
-
-
-%% (65) NIY: multiple attribute declarators (FIXED)
-'<attr_dcl>' -> 'Opt_readonly' 'attribute' '<param_type_spec>'
- '<simple_declarator>' 'ZorM_<simple_declarator>'
- : #attr{readonly='$1', type='$3', id=['$4' | reverse('$5')]} .
-%% : ic:unfold(#attr{readonly='$1', type='$3', id=['$4' | reverse('$5')]}) .
-%%'<attr_dcl>' -> 'Opt_readonly' 'attribute' '<param_type_spec>'
-%% '<simple_declarator>'
-
-
-%% (66) NIY: unfolding of exception bodies (FIXED)
-%%'<except_dcl>' -> 'exception' '<identifier>' '{' 'ZorM_<member>' '}'
-%% : #except{id='$2', body=ic:unfold('$4')} .
-'<except_dcl>' -> 'exception' '<identifier>' '{' 'ZorM_<member>' '}'
- : #except{id='$2', body=reverse('$4')} .
-
-%% (67)
-'<op_dcl>' -> 'Opt_<op_attribute>' '<op_type_spec>' '<identifier>' '<parameter_dcls>' 'Opt_<raises_expr>' 'Opt_<context_expr>'
- : #op{oneway='$1', type='$2', id='$3', params='$4', raises='$5', ctx='$6'} .
-
-%% Added clause
-'Opt_<op_attribute>' -> '$empty' : nil.
-'Opt_<op_attribute>' -> '<op_attribute>' : '$1'.
-
-%% (68)
-'<op_attribute>' -> 'oneway' : '$1' .
-
-
-%% (69)
-'<op_type_spec>' -> '<param_type_spec>' : '$1' .
-'<op_type_spec>' -> 'void' : '$1' .
-
-
-%% (70) Rewritten
-%'<parameter_dcls>' -> '(' '<param_dcl>' 'ZorM_<param_dcl>' ')'
-% : ['$2' | reverse('$3')] .
-%'<parameter_dcls>' -> '(' ')' : [] .
-
-'<parameter_dcls>' -> '(' 'Ugly_pragmas' '<param_dcl>' 'ZorM_<param_dcl>' ')'
- : '$2' ++ ['$3' | reverse('$4')] .
-'<parameter_dcls>' -> '(' 'Ugly_pragmas' ')' : '$2' .
-
-
-%% Added clause
-%'ZorM_<param_dcl>' -> '$empty' : [] .
-%'ZorM_<param_dcl>' -> 'ZorM_<param_dcl>' ',' '<param_dcl>' : ['$3' | '$1'] .
-
-
-'ZorM_<param_dcl>' -> 'Ugly_pragmas' : '$1' .
-'ZorM_<param_dcl>' -> 'ZorM_<param_dcl>' 'Ugly_pragmas' ',' 'Ugly_pragmas' '<param_dcl>' 'Ugly_pragmas'
- : '$2' ++ '$4' ++ '$6' ++ ['$5' | '$1'] .
-
-
-
-
-%% (71)
-'<param_dcl>' -> '<param_attribute>' '<param_type_spec>' '<simple_declarator>'
- : #param{inout='$1', type='$2', id='$3'} .
-
-
-%% (72)
-'<param_attribute>' -> 'in' : '$1' .
-'<param_attribute>' -> 'out' : '$1' .
-'<param_attribute>' -> 'inout' : '$1' .
-
-
-%% Added clause
-'Opt_<raises_expr>' -> '$empty' : [] .
-'Opt_<raises_expr>' -> '<raises_expr>' : '$1' .
-
-%% (73)
-'<raises_expr>' -> 'raises' '(' '<scoped_name>' 'ZorM_<scoped_name>' ')'
- : ['$3'| reverse('$4')] .
-
-
-%% Added clause
-'Opt_<context_expr>' -> '$empty' : [] .
-'Opt_<context_expr>' -> '<context_expr>' : '$1'.
-
-%% (74)
-'<context_expr>' -> 'context' '(' '<string_literal>' 'ZorM_<string_literal>'')'
- : ['$3' | reverse('$4')] .
-
-
-
-%% (75)
-'<param_type_spec>' -> '<base_type_spec>' : '$1' .
-'<param_type_spec>' -> '<string_type>' : '$1' .
-'<param_type_spec>' -> '<scoped_name>' : '$1' .
-
-
-%% (96)
-'<fixed_pt_type>' -> 'fixed' '<' '<positive_int_const>' ',' '<positive_int_const>' '>'
- : #fixed{digits='$3',scale='$5'} .
-
-%% (99)
-'<constr_forward_decl>' -> 'struct' '<identifier>' : #constr_forward{id='$2', tk=tk_struct} .
-'<constr_forward_decl>' -> 'union' '<identifier>' : #constr_forward{id='$2', tk=tk_union} .
-
-%% Added clause
-'ZorM_<string_literal>' -> '$empty' : [] .
-'ZorM_<string_literal>' -> 'ZorM_<string_literal>' ',' '<string_literal>'
- : ['$3' | '$1'] .
-
-%% Added clause
-'ZorM_<simple_declarator>' -> '$empty' : [] .
-'ZorM_<simple_declarator>' -> 'ZorM_<simple_declarator>' ','
-'<simple_declarator>' : ['$3' | '$1'] .
-
-%% Added clause
-%%'ZorM_<member>' -> '$empty' : [] .
-%%'ZorM_<member>' -> 'ZorM_<member>' '<member>' : ['$2' | '$1'] .
-
-'ZorM_<member>' -> 'Ugly_pragmas' : '$1' .
-'ZorM_<member>' -> 'ZorM_<member>' '<member>' : '$2' ++ '$1' .
-
-
-%% Added clause
-'Opt_readonly' -> '$empty' : nil.
-'Opt_readonly' -> 'readonly' : '$1'.
-
-
-
-Erlang code.
-%%-----------------------------------------------------------
-
-
-
diff --git a/lib/ic/src/icpreproc.erl b/lib/ic/src/icpreproc.erl
deleted file mode 100644
index fc936c4bf3..0000000000
--- a/lib/ic/src/icpreproc.erl
+++ /dev/null
@@ -1,112 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(icpreproc).
-
-
-
--export([preproc/2]).
-
-
--import(lists, [filter/2]).
-
-
-%%----------------------------------------------------------------------
-%%----------------------------------------------------------------------
-
-
-preproc(G, File) ->
- Cmd = ic_options:get_opt(G, preproc_cmd),
- Flags = ic_options:get_opt(G, preproc_flags),
-
-
- case Cmd of
- "erl" ->
- case ic_pp:run(File,Flags) of
- {ok, [$#, $ , $1 | Rest], []} ->
- [$#, $ , $1 | Rest];
- {ok, [$#, $ , $1 | Rest], Warning} ->
- print_warning(G,Warning),
- [$#, $ , $1 | Rest];
- {error,Error} ->
- print_error(G,Error)
- end;
-
- _ ->
- Line = Cmd++" "++Flags++" "++File,
- % FIXME: Check status code of command instead of this test
- case os:cmd(Line) of
- [$#, $ , C | Rest] when is_integer(C), C > $0, C =< $9 ->
- [$#, $ , C | Rest];
- X ->
- ic_error:fatal_error(G, {preproc, filter(X)})
- end
- end.
-
-
-filter(X) ->
- X2 = divide_nl(X, []),
- filter_x_switch(X2).
-
-
-divide_nl([10 | Xs], Out) ->
- [lists:reverse(Out) | divide_nl(Xs, [])];
-divide_nl([X | Xs], Out) -> divide_nl(Xs, [X|Out]);
-divide_nl([], Out) -> lists:reverse(Out).
-
-
-filter_x_switch(L) ->
- filter(fun([$g,$c,$c,$:,$ ,$W,$a,$r,$n,$i,$n,$g,$:,$ ,$`,$-,$x,$ | _]) ->
- false;
- (_) -> true end, L).
-
-
-print_error(_G,[]) ->
- ok;
-print_error(G,[{File,Line,Text}]) ->
- ErrorText = File++":"++integer_to_list(Line)++": "++Text,
- ic_error:fatal_error(G, {ic_pp_error, ErrorText}),
- ok;
-print_error(G,[{File,Line,Text}|T]) ->
- ErrorText = File++":"++integer_to_list(Line)++": "++Text,
- ic_error:error(G, {ic_pp_error, ErrorText}),
- print_error(G,T);
-print_error(G,[H]) ->
- ErrorText = H++"\n",
- ic_error:fatal_error(G, {ic_pp_error, ErrorText}),
- ok;
-print_error(G,[H|T]) ->
- ErrorText = H++"\n",
- ic_error:error(G, {ic_pp_error, ErrorText}),
- print_error(G,T).
-
-
-print_warning(_G,[]) ->
- ok;
-print_warning(G,[{File,Line,Text}|T]) ->
- WarText = File++":"++integer_to_list(Line)++": "++Text,
- ic_error:warn(G, {ic_pp_warning, WarText}),
- print_warning(G,T);
-print_warning(G,[H|T]) ->
- WarText = H++"\n",
- ic_error:warn(G, {ic_pp_warning, WarText}),
- print_warning(G,T).
-
-
diff --git a/lib/ic/src/icscan.erl b/lib/ic/src/icscan.erl
deleted file mode 100644
index 123041495e..0000000000
--- a/lib/ic/src/icscan.erl
+++ /dev/null
@@ -1,453 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(icscan).
-
-
--export([scan/2]).
-
--include("ic.hrl").
-
-
-%%----------------------------------------------------------------------
-%%----------------------------------------------------------------------
-
--import(lists, [reverse/1]).
-
-
-scan(G, File) ->
- PL = call_preproc(G, File),
- call_scan(G, PL).
-
-call_preproc(G, File) ->
- case ic_options:get_opt(G, use_preproc) of
- true ->
- icpreproc:preproc(G, File);
- false ->
- case catch file:read_file(File) of
- {ok, Bin} ->
- binary_to_list(Bin);
- Other ->
- exit(Other)
- end
- end.
-
-call_scan(G, PL) ->
- BE = ic_options:get_opt(G, be),
- RSL = scan(G, BE, PL, 1, []),
- lists:reverse(RSL).
-
-
-%% Guard macros used at top scan functions only
--define(is_number(X), X >= $0 , X =< $9).
--define(is_upper(X), X >= $A , X =< $Z).
--define(is_lower(X), X >= $a, X =< $z).
--define(is_hex_uc(X), X >= $A , X =< $F).
--define(is_hex_lc(X), X >= $a , X =< $f).
--define(is_octal(X), X >=$0, X =< $7).
-
-%% Handle:
-%% const wchar aWChar = L'X';
-scan(G, BE, [$L, $'|Str], Line, Out) ->
- scan_const(G, BE, wchar, Str, [], Line, Out);
-scan(G, BE, [$L, $"|Str], Line, Out) ->
- scan_const(G, BE, wstring, Str, [], Line, Out);
-scan(G, BE, [$_, X|Str], Line, Out) when ?is_upper(X) ->
- scan_name(G, BE, Str, [X], false, Line, Out);
-scan(G, BE, [$_, X|Str], Line, Out) when ?is_lower(X) ->
- scan_name(G, BE, Str, [X], false, Line, Out);
-scan(G, BE, [X|Str], Line, Out) when ?is_upper(X) ->
- scan_name(G, BE, Str, [X], true, Line, Out);
-scan(G, BE, [X|Str], Line, Out) when ?is_lower(X) ->
- scan_name(G, BE, Str, [X], true, Line, Out);
-scan(G, BE, [X|Str], Line, Out) when ?is_number(X) ->
- scan_number(G, BE, Str, [X], Line, Out);
-scan(G, BE, [9| T], Line, Out) -> scan(G, BE, T, Line, Out);
-scan(G, BE, [32| T], Line, Out) -> scan(G, BE, T, Line, Out);
-scan(G, BE, [$\r|Str], Line, Out) ->
- scan(G, BE, Str, Line, Out);
-scan(G, BE, [$\n|Str], Line, Out) ->
- scan(G, BE, Str, Line+1, Out);
-scan(G, BE, [$:, $: | Str], Line, Out) ->
- scan(G, BE, Str, Line, [{'::', Line} | Out]);
-scan(G, BE, [$/, $/ | Str], Line, Out) ->
- Rest = skip_to_nl(Str),
- scan(G, BE, Rest, Line, Out);
-scan(G, BE, [$/, $* | Str], Line, Out) ->
- Rest = skip_comment(Str),
- scan(G, BE, Rest, Line, Out);
-scan(G, BE, [$", $\\|Str], Line, Out) ->
- scan_const(G, BE, string, [$\\|Str], [], Line, Out);
-scan(G, BE, [$"|Str], Line, Out) ->
- scan_const(G, BE, string, Str, [], Line, Out);
-scan(G, BE, [$', $\\|Str], Line, Out) ->
- scan_const(G, BE, char, [$\\|Str], [], Line, Out);
-scan(G, BE, [$'|Str], Line, Out) ->
- scan_const(G, BE, char, Str, [], Line, Out);
-scan(G, BE, [$\\|Str], Line, Out) ->
- scan_const(G, BE, escaped, [$\\|Str], [], Line, Out);
-scan(G, BE, [$. | Str], Line, Out) ->
- scan_frac(G, BE, Str, [$.], Line, Out);
-scan(G, BE, [$# | Str], Line, Out) ->
- scan_preproc(G, BE, Str, Line, Out);
-scan(G, BE, [$<, $< | Str], Line, Out) ->
- scan(G, BE, Str, Line, [{'<<', Line} | Out]);
-scan(G, BE, [$>, $> | Str], Line, Out) ->
- scan(G, BE, Str, Line, [{'>>', Line} | Out]);
-scan(G, BE, [C|Str], Line, Out) ->
- scan(G, BE, Str, Line, [{list_to_atom([C]), Line} | Out]);
-
-scan(_G, _BE, [], _Line, Out) ->
- Out.
-
-
-scan_number(G, BE, [X|Str], [$0], Line, Out) when X == $X ; X ==$x ->
- case Str of
- [D|_TmpStr] when ?is_number(D); ?is_hex_uc(D); ?is_hex_lc(D) ->
- {Num,Rest} = scan_hex_number(Str,0),
- scan(G, BE, Rest, Line, [{'<integer_literal>', Line,
- integer_to_list(Num)} | Out]);
- [D|TmpStr] ->
- scan(G, BE, TmpStr, Line, [{list_to_atom([D]), Line} | Out])
- end;
-scan_number(G, BE, Str, [$0], Line, Out) ->
- %% If an integer literal starts with a 0 it may indicate that
- %% it is represented as an octal number. But, it can also be a fixed
- %% type which must use padding to match a fixed typedef. For example:
- %% typedef fixed<5,2> fixed52;
- %% 123.45d, 123.00d and 023.00d is all valid fixed values.
- %% Naturally, a float can be defined as 0.14 or 00.14.
- case pre_scan_number(Str, [], octal) of
- octal ->
- {Num, Rest} = scan_octal_number(Str,0),
- scan(G, BE, Rest, Line, [{'<integer_literal>', Line,
- integer_to_list(Num)} | Out]);
- {fixed, Fixed, Rest} ->
- scan(G, BE, Rest, Line, [{'<fixed_pt_literal>', Line, Fixed} | Out]);
- float ->
- %% Not very likely that someone defines a constant as 00.14 but ...
- NewStr = remove_leading_zeroes(Str),
- scan(G, BE, NewStr, Line, Out)
- end;
-scan_number(G, BE, [X|Str], Accum, Line, Out) when ?is_number(X) ->
- scan_number(G, BE, Str, [X|Accum], Line, Out);
-scan_number(G, BE, [X|Str], Accum, Line, Out) when X==$. ->
- scan_frac(G, BE, Str, [X|Accum], Line, Out);
-scan_number(G, BE, [X|Str], Accum, Line, Out) when X==$e ; X==$e ->
- scan_exp(G, BE, Str, [X|Accum], Line, Out);
-scan_number(G, BE, [X|Str], Accum, Line, Out) when X==$D ; X==$d ->
- scan(G, BE, Str, Line, [{'<fixed_pt_literal>', Line,
- (lists:reverse(Accum))} | Out]);
-scan_number(G, BE, Str, Accum, Line, Out) ->
- scan(G, BE, Str, Line, [{'<integer_literal>', Line,
- (lists:reverse(Accum))} | Out]).
-
-
-remove_leading_zeroes([$0|Rest]) ->
- remove_leading_zeroes(Rest);
-remove_leading_zeroes(L) ->
- L.
-
-scan_hex_number([X|Rest],Acc) when X >=$a, X =< $f ->
- scan_hex_number(Rest,(Acc bsl 4) + (X - $a + 10));
-scan_hex_number([X|Rest],Acc) when X >=$A, X =< $F ->
- scan_hex_number(Rest,(Acc bsl 4) + (X - $A + 10));
-scan_hex_number([X|Rest],Acc) when X >=$0, X =< $9 ->
- scan_hex_number(Rest,(Acc bsl 4) + (X-$0));
-scan_hex_number(Rest,Acc) ->
- {Acc,Rest}.
-
-pre_scan_number([$d|Rest], Acc, _) ->
- {fixed, [$0|lists:reverse(Acc)], Rest};
-pre_scan_number([$D|Rest], Acc, _) ->
- {fixed, [$0|lists:reverse(Acc)], Rest};
-pre_scan_number([$.|Rest], Acc, _) ->
- %% Actually, we don't know if it's a float since it can be a fixed.
- pre_scan_number(Rest, [$.|Acc], float);
-pre_scan_number([X|_], _Acc, _) when X == $E ; X ==$e ->
- %% Now we now it's a float.
- float;
-pre_scan_number([X|Rest], Acc, Type) when ?is_number(X) ->
- pre_scan_number(Rest, [X|Acc], Type);
-pre_scan_number(_Rest, _Acc, Type) ->
- %% At this point we know it's a octal or float.
- Type.
-
-scan_octal_number([X|Rest],Acc) when ?is_octal(X) ->
- scan_octal_number(Rest,(Acc bsl 3) + (X-$0));
-scan_octal_number(Rest,Acc) ->
- {Acc, Rest}.
-
-%% Floating point number scan.
-%%
-%% Non trivial scan. A float consists of an integral part, a
-%% decimal point, a fraction part, an e or E and a signed integer
-%% exponent. Either the integer part or the fraction part but not
-%% both may be missing, and either the decimal point or the
-%% exponent part but not both may be missing. The exponent part
-%% must consist of an e or E and a possibly signed exponent.
-%%
-%% Analysis shows that "1." ".7" "1e2" ".5e-3" "1.7e2" "1.7e-2"
-%% is allowed and "1" ".e9" is not. The sign is only allowed just
-%% after an e or E. The scanner reads a number as an integer
-%% until it encounters a "." so the integer part only error case
-%% will not be caught in the scanner (but rather in expression
-%% evaluation)
-
-scan_frac(G, _BE, [$e | _Str], [$.], Line, _Out) ->
- ic_error:fatal_error(G, {illegal_float, Line});
-scan_frac(G, _BE, [$E | _Str], [$.], Line, _Out) ->
- ic_error:fatal_error(G, {illegal_float, Line});
-scan_frac(G, BE, Str, Accum, Line, Out) ->
- scan_frac2(G, BE, Str, Accum, Line, Out).
-
-scan_frac2(G, BE, [X|Str], Accum, Line, Out) when ?is_number(X) ->
- scan_frac2(G, BE, Str, [X|Accum], Line, Out);
-scan_frac2(G, BE, [X|Str], Accum, Line, Out) when X==$e ; X==$E ->
- scan_exp(G, BE, Str, [X|Accum], Line, Out);
-%% The following case is for fixed (e.g. 123.45d).
-scan_frac2(G, BE, [X|Str], Accum, Line, Out) when X==$d ; X==$D ->
- scan(G, BE, Str, Line, [{'<fixed_pt_literal>', Line,
- (lists:reverse(Accum))} | Out]);
-scan_frac2(G, BE, Str, Accum, Line, Out) ->
- scan(G, BE, Str, Line, [{'<floating_pt_literal>', Line,
- (lists:reverse(Accum))} | Out]).
-
-scan_exp(G, BE, [X|Str], Accum, Line, Out) when X==$- ->
- scan_exp2(G, BE, Str, [X|Accum], Line, Out);
-scan_exp(G, BE, Str, Accum, Line, Out) ->
- scan_exp2(G, BE, Str, Accum, Line, Out).
-
-scan_exp2(G, BE, [X|Str], Accum, Line, Out) when ?is_number(X) ->
- scan_exp2(G, BE, Str, [X|Accum], Line, Out);
-scan_exp2(G, BE, Str, Accum, Line, Out) ->
- scan(G, BE, Str, Line, [{'<floating_pt_literal>', Line,
- (lists:reverse(Accum))} | Out]).
-
-
-scan_name(G, BE, [X|Str], Accum, TypeCheck, Line, Out) when ?is_upper(X) ->
- scan_name(G, BE, Str, [X|Accum], TypeCheck, Line, Out);
-scan_name(G, BE, [X|Str], Accum, TypeCheck, Line, Out) when ?is_lower(X) ->
- scan_name(G, BE, Str, [X|Accum], TypeCheck, Line, Out);
-scan_name(G, BE, [X|Str], Accum, TypeCheck, Line, Out) when ?is_number(X) ->
- scan_name(G, BE, Str, [X|Accum], TypeCheck, Line, Out);
-scan_name(G, BE, [$_|Str], Accum, TypeCheck, Line, Out) ->
- scan_name(G, BE, Str, [$_|Accum], TypeCheck, Line, Out);
-scan_name(G, BE, S, Accum, false, Line, Out) ->
- %% The CORBA 2.3 specification allows the user to override typechecking:
- %% typedef string _native;
- %% interface i {
- %% void foo(in _native VT);
- %% };
- %% BUT, the IFR-id remains the same ("IDL:native:1.0") etc. The reason for
- %% this is that one don't have to re-write a large chunk of IDL- and
- %% application-code.
- scan(G, BE, S, Line, [{'<identifier>', Line, lists:reverse(Accum)} | Out]);
-scan_name(G, BE, S, Accum, _, Line, Out) ->
- L = lists:reverse(Accum),
- X = case is_reserved(L, BE) of
- undefined ->
- {'<identifier>', Line, L};
- Yes ->
- {Yes, Line}
- end,
- scan(G, BE, S, Line, [X | Out]).
-
-%% Shall scan a constant
-scan_const(G, BE, string, [$" | Rest], Accum, Line, [{'<string_literal>', _, Str}|Out]) ->
- scan(G, BE, Rest, Line,
- [{'<string_literal>', Line, Str ++ lists:reverse(Accum)} | Out]);
-scan_const(G, BE, string, [$" | Rest], Accum, Line, Out) ->
- scan(G, BE, Rest, Line,
- [{'<string_literal>', Line, lists:reverse(Accum)} | Out]);
-scan_const(G, BE, wstring, [$" | Rest], Accum, Line, [{'<wstring_literal>', _,Wstr}|Out]) -> %% WSTRING
- scan(G, BE, Rest, Line,
- [{'<wstring_literal>', Line, Wstr ++ lists:reverse(Accum)} | Out]);
-scan_const(G, BE, wstring, [$" | Rest], Accum, Line, Out) -> %% WSTRING
- scan(G, BE, Rest, Line,
- [{'<wstring_literal>', Line, lists:reverse(Accum)} | Out]);
-scan_const(G, _BE, string, [], _Accum, Line, Out) -> %% Bad string
- ic_error:error(G, {bad_string, Line}),
- Out;
-scan_const(G, _BE, wstring, [], _Accum, Line, Out) -> %% Bad WSTRING
- ic_error:error(G, {bad_string, Line}),
- Out;
-scan_const(G, BE, char, [$' | Rest], Accum, Line, Out) ->
- scan(G, BE, Rest, Line,
- [{'<character_literal>', Line, lists:reverse(Accum)} | Out]);
-scan_const(G, BE, wchar, [$' | Rest], Accum, Line, Out) -> %% WCHAR
- scan(G, BE, Rest, Line,
- [{'<wcharacter_literal>', Line, lists:reverse(Accum)} | Out]);
-scan_const(G, BE, Mode, [$\\, C | Rest], Accum, Line, Out) ->
- case escaped_char(C) of
- error ->
- ic_error:error(G, {bad_escape_character, Line, C}), %% Bad escape character
- scan_const(G, BE, Mode, Rest, [C | Accum], Line, Out);
- octal ->
- {Num,Rest2} = scan_octal_number([C|Rest], 0),
- scan_const(G, BE, Mode, Rest2, [Num|Accum], Line, Out);
- hexadecimal ->
- {Num,Rest2} = scan_hex_number(Rest, 0),
- if
- Num > 255 -> %% 16#FF
- ic_error:error(G, {bad_escape_character, Line, C}),
- scan_const(G, BE, Mode, Rest, [C | Accum], Line, Out);
- true ->
- scan_const(G, BE, Mode, Rest2, [Num|Accum], Line, Out)
- end;
- unicode ->
- {Num,Rest2} = scan_hex_number(Rest, 0),
- if
- Num > 65535 -> %% 16#FFFF
- ic_error:error(G, {bad_escape_character, Line, C}),
- scan_const(G, BE, Mode, Rest, [C | Accum], Line, Out);
- true ->
- scan_const(G, BE, Mode, Rest2, [Num|Accum], Line, Out)
- end;
- EC ->
- scan_const(G, BE, Mode, Rest, [EC | Accum], Line, Out)
- end;
-scan_const(G, BE, Mode, [C | Rest], Accum, Line, Out) ->
- scan_const(G, BE, Mode, Rest, [C | Accum], Line, Out).
-
-
-%%
-%% Preprocessor output handling
-%%
-%% gcc outputs a line with line number, file name (within \") and
-%% one or more integer flags. The scanner scans the line number,
-%% the id and all integers up to nl.
-%%
-%% NOTE: This will have to be enhanced in order to eat #pragma
-%%
-scan_preproc(G, BE, Str, Line, Out) ->
- {List, Rest} = scan_to_nl(strip(Str), []),
- NewLine = get_new_line_nr(strip(List), Line+1, []),
- case scan_number(G, BE, List, [], Line, [{'#', Line} | Out]) of
- L when is_list(L) ->
- scan(G, BE, Rest, NewLine, [{'#', Line} | L])
- end.
-
-get_new_line_nr([C|R], Line, Acc) when C>=$0, C=<$9 ->
- get_new_line_nr(R, Line, [C|Acc]);
-get_new_line_nr(_, Line, []) -> Line; % No line nr found
-get_new_line_nr(_, _, Acc) -> list_to_integer(reverse(Acc)).
-
-scan_to_nl([], Acc) -> {reverse(Acc), []};
-scan_to_nl([$\n|Str], Acc) -> {reverse(Acc), Str};
-scan_to_nl([$\r|R], Acc) -> scan_to_nl(R, Acc);
-scan_to_nl([C|R], Acc) -> scan_to_nl(R, [C|Acc]).
-
-strip([$ |R]) -> strip(R);
-strip(L) -> L.
-
-%% Escaped character. Escaped chars are repr as two characters in the
-%% input list of letters and this is translated into one char.
-escaped_char($n) -> $\n;
-escaped_char($t) -> $\t;
-escaped_char($v) -> $\v;
-escaped_char($b) -> $\b;
-escaped_char($r) -> $ ;
-escaped_char($f) -> $\f;
-escaped_char($a) -> $\a;
-escaped_char($\\) -> $\\;
-escaped_char($?) -> $?;
-escaped_char($') -> $';
-escaped_char($") -> $";
-escaped_char($x) -> hexadecimal;
-escaped_char($u) -> unicode;
-escaped_char(X) when ?is_octal(X) -> octal;
-%% Error
-escaped_char(_Other) -> error.
-
-skip_to_nl([]) -> [];
-skip_to_nl([$\n | Str]) ->[$\n | Str];
-skip_to_nl([_|Str]) ->
- skip_to_nl(Str).
-
-skip_comment([$\\, _ | Str]) ->
- skip_comment(Str);
-skip_comment([$*, $/ | Str]) -> Str;
-skip_comment([_|Str]) ->
- skip_comment(Str).
-
-
-%%----------------------------------------------------------------------
-%% Shall separate keywords from identifiers and numbers
-
-%% Fill in the ets of reserved words
-is_reserved("Object", _) -> 'Object';
-is_reserved("in", _) -> in;
-is_reserved("interface", _) -> interface;
-is_reserved("case", _) -> 'case';
-is_reserved("union", _) -> union;
-is_reserved("struct", _) -> struct;
-is_reserved("any", _) -> any;
-is_reserved("long", _) -> long;
-is_reserved("float", _) -> float;
-is_reserved("out", _) -> out;
-is_reserved("enum", _) -> enum;
-is_reserved("double", _) -> double;
-is_reserved("context", _) -> context;
-is_reserved("oneway", _) -> oneway;
-is_reserved("sequence", _) -> sequence;
-is_reserved("FALSE", _) -> 'FALSE';
-is_reserved("readonly", _) -> readonly;
-is_reserved("char", _) -> char;
-is_reserved("wchar", _) -> wchar;
-is_reserved("void", _) -> void;
-is_reserved("inout", _) -> inout;
-is_reserved("attribute", _) -> attribute;
-is_reserved("octet", _) -> octet;
-is_reserved("TRUE", _) -> 'TRUE';
-is_reserved("switch", _) -> switch;
-is_reserved("unsigned", _) -> unsigned;
-is_reserved("typedef", _) -> typedef;
-is_reserved("const", _) -> const;
-is_reserved("raises", _) -> raises;
-is_reserved("string", _) -> string;
-is_reserved("wstring", _) -> wstring;
-is_reserved("default", _) -> default;
-is_reserved("short", _) -> short;
-is_reserved("module", _) -> module;
-is_reserved("exception", _) -> exception;
-is_reserved("boolean", _) -> boolean;
-%% --- New keywords Introduced in CORBA-2.3.1 ---
-%% For now we cannot add these for all backends right now since it would cause
-%% some problems for at least one customer.
-is_reserved("fixed", BE) -> check_be(BE, fixed);
-%is_reserved("abstract", BE) -> check_be(BE, abstract);
-%is_reserved("custom", BE) -> check_be(BE, custom);
-%is_reserved("factory", BE) -> check_be(BE, factory);
-%is_reserved("local", BE) -> check_be(BE, local);
-%is_reserved("native", BE) -> check_be(BE, native);
-%is_reserved("private", BE) -> check_be(BE, private);
-%is_reserved("public", BE) -> check_be(BE, public);
-%is_reserved("supports", BE) -> check_be(BE, supports);
-%is_reserved("truncatable", BE) -> check_be(BE, truncatable);
-%is_reserved("ValueBase", BE) -> check_be(BE, 'ValueBase');
-%is_reserved("valuetype", BE) -> check_be(BE, valuetype);
-is_reserved(_, _) -> undefined.
-
-check_be(erl_corba, KeyWord) ->
- KeyWord;
-check_be(_, _) ->
- undefined.
-
diff --git a/lib/ic/src/icstruct.erl b/lib/ic/src/icstruct.erl
deleted file mode 100644
index 713ac87287..0000000000
--- a/lib/ic/src/icstruct.erl
+++ /dev/null
@@ -1,1917 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(icstruct).
-
-
--export([struct_gen/4, except_gen/4, create_c_array_coding_file/5]).
-
-%%------------------------------------------------------------
-%%
-%% Internal stuff
-%%
-%%------------------------------------------------------------
--import(ic_codegen, [emit/2, emit/3, emit/4, emit_c_enc_rpt/4, emit_c_dec_rpt/4]).
-
--include("icforms.hrl").
--include("ic.hrl").
-
-
-
-%%------------------------------------------------------------
-
-%%------------------------------------------------------------
-%%
-%% File handling stuff
-%%
-%%------------------------------------------------------------
-
-
-
-%%------------------------------------------------------------
-%%
-%% Generation loop
-%%
-%% The idea is to traverse everything and find every struct that
-%% may be hiding down in nested types. All structs that are found
-%% are generated to a hrl file.
-%%
-%% struct_gen is entry point for structs and types, except_gen is
-%% for exceptions
-%%
-%%------------------------------------------------------------
-
-
-except_gen(G, N, X, L) when is_record(X, except) ->
- N2 = [ic_forms:get_id2(X) | N],
- if
- L == c ->
- io:format("Warning : Exception not defined for c mapping\n", []);
- true ->
- emit_struct(G, N, X, L)
- end,
- struct_gen_list(G, N2, ic_forms:get_body(X), L).
-
-struct_gen(G, N, X, L) when is_record(X, struct) ->
- N2 = [ic_forms:get_id2(X) | N],
- struct_gen_list(G, N2, ic_forms:get_body(X), L),
- emit_struct(G, N, X, L);
-struct_gen(G, N, X, L) when is_record(X, union) ->
- N2 = [ic_forms:get_id2(X) | N],
- if
- L == c ->
- %% Produce the "body" first
- struct_gen_list(G, N2, ic_forms:get_body(X), L),
- icunion:union_gen(G, N, X, c);
- true ->
- struct_gen(G, N, ic_forms:get_type(X), L),
- struct_gen_list(G, N2, ic_forms:get_body(X), L)
- end,
- emit_union(G, N, X, L);
-struct_gen(G, N, X, L) when is_record(X, member) ->
- struct_gen(G, N, ic_forms:get_type(X), L);
-struct_gen(G, N, X, L) when is_record(X, typedef) ->
- struct_gen(G, N, ic_forms:get_body(X), L),
- emit_typedef(G, N, X, L);
-struct_gen(G, N, X, L) when is_record(X, type_dcl) ->
- struct_gen_list(G, N, ic_forms:get_type(X), L);
-struct_gen(G, N, X, L) when is_record(X, case_dcl) ->
- struct_gen(G, N, ic_forms:get_type(X), L);
-struct_gen(G, N, X, L) when is_record(X, sequence) ->
- struct_gen(G, N, ic_forms:get_type(X), L),
- X;
-struct_gen(G, N, X, L) when is_record(X, enum) ->
- icenum:enum_gen(G, N, X, L);
-struct_gen(_G, _N, _X, _L) ->
- ok.
-
-%% List clause for struct_gen
-struct_gen_list(G, N, Xs, L) ->
- lists:foreach(
- fun(X) ->
- R = struct_gen(G, N, X, L),
- if
- L == c ->
- if
- is_record(R,sequence) ->
- emit_sequence_head_def(G,N,X,R,L);
- true ->
- ok
- end;
- true ->
- ok
- end
- end, Xs).
-
-
-%% emit primitive for structs.
-emit_struct(G, N, X, erlang) ->
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- %% Make a straight list of all member ids (this is a
- %% variant of flatten)
- EList = lists:map(
- fun(XX) ->
- lists:map(
- fun(XXX) ->
- ic_util:to_atom(ic_forms:get_id2(XXX))
- end,
- ic_forms:get_idlist(XX))
- end,
- ic_forms:get_body(X)),
- ic_codegen:record(G, X,
- ic_util:to_undersc([ic_forms:get_id2(X) | N]),
- ictk:get_IR_ID(G, N, X), lists:flatten(EList)),
- mkFileRecObj(G,N,X,erlang);
- false ->
- ok
- end;
-emit_struct(G, N, X, c) ->
-
- N1 = [ic_forms:get_id2(X) | N],
- case ic_pragma:is_local(G,N1) of
- true ->
- emit_c_struct(G, N, X,local);
- false ->
- emit_c_struct(G, N, X,included)
- end.
-
-
-emit_c_struct(_G, _N, _X, included) ->
- %% Do not generate included types att all.
- ok;
-emit_c_struct(G, N, X, local) ->
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- Fd = ic_genobj:hrlfiled(G),
-
- N1 = [ic_forms:get_id2(X) | N],
- StructName = ic_util:to_undersc(N1),
-
- %% Make a straight list of all member ids (this is a
- %% variant of flatten)
- M = lists:map(
- fun(XX) ->
- lists:map(
- fun(XXX) ->
- if
- is_record(XXX, array) ->
- Type = ic_forms:get_type(XX),
- Name = element(3,element(2,XXX)),
- {_, _, StructTK, _} =
- ic_symtab:get_full_scoped_name(
- G,
- N,
- ic_symtab:scoped_id_new(
- ic_forms:get_id2(X))),
- ArrayTK =
- get_structelement_tk(StructTK,
- Name),
- Dim = extract_dim(ArrayTK),
- %% emit array file
- emit(Fd, "\n#ifndef __~s__\n",
- [ic_util:to_uppercase(
- StructName ++ "_"
- ++ Name)]),
- emit(Fd, "#define __~s__\n\n",
- [ic_util:to_uppercase(
- StructName ++ "_"
- ++ Name)]),
- create_c_array_coding_file(
- G,
- N,
- {StructName ++ "_" ++ Name, Dim},
- Type,
- no_typedef),
- emit(Fd, "\n#endif\n\n"),
- {{Type, XXX},
- ic_forms:get_id2(XXX)};
- true ->
- %% Ugly work around to fix the ETO
- %% return patch problem
- Name =
- case ic_forms:get_id2(XXX) of
- "return" ->
- "return1";
- Other ->
- Other
- end,
- {ic_forms:get_type(XX), Name}
- end
- end,
- ic_forms:get_idlist(XX))
- end,
- ic_forms:get_body(X)),
- EList = lists:flatten(M),
- %%io:format("Elist = ~p~n",[EList]),
-
- emit(Fd, "\n#ifndef __~s__\n",[ic_util:to_uppercase(StructName)]),
- emit(Fd, "#define __~s__\n",[ic_util:to_uppercase(StructName)]),
- ic_codegen:mcomment_light(Fd,
- [io_lib:format("Struct definition: ~s",
- [StructName])],
- c),
- emit(Fd, "typedef struct {\n"),
- lists:foreach(
- fun({Type, Name}) ->
- emit_struct_member(Fd, G, N1, X, Name, Type)
- end,
- EList),
- emit(Fd, "} ~s;\n\n", [StructName]),
- create_c_struct_coding_file(G, N, X, nil, StructName,
- EList, struct),
- emit(Fd, "\n#endif\n\n");
- false ->
- ok
- end.
-
-%% Extracts array dimention(s)
-
-get_structelement_tk({tk_struct, _, _, EList}, EN) ->
- {value, {EN, ArrayTK}} = lists:keysearch(EN, 1, EList),
- ArrayTK.
-
-extract_dim({tk_array, {tk_array, T, D1}, D}) ->
- [integer_to_list(D) | extract_dim({tk_array, T, D1})];
-extract_dim({tk_array, _, D}) ->
- [integer_to_list(D)].
-
-%% Makes the array name
-mk_array_name(Name,Dim) ->
- Name ++ mk_array_name(Dim).
-
-mk_array_name([]) ->
- "";
-mk_array_name([Dim|Dims]) ->
- "[" ++ Dim ++ "]" ++ mk_array_name(Dims).
-
-
-emit_struct_member(Fd, G, N, X, Name,{Type,Array}) when is_record(Array, array)->
- {_, _, StructTK, _} =
- ic_symtab:get_full_scoped_name(
- G,
- N,
- ic_symtab:scoped_id_new(ic_forms:get_id2(X))),
- ArrayTK = get_structelement_tk(StructTK, Name),
- Dim = extract_dim(ArrayTK),
- emit(Fd, " ~s ~s;\n",
- [ic_cbe:mk_c_type(G, N, Type),mk_array_name(Name,Dim)]);
-emit_struct_member(Fd, _G, N, _X, Name, Union) when is_record(Union, union)->
- emit(Fd, " ~s ~s;\n",
- [ic_util:to_undersc([ic_forms:get_id2(Union) | N]),Name]);
-emit_struct_member(Fd, _G, _N, _X, Name, {string, _}) ->
- emit(Fd, " CORBA_char *~s;\n",
- [Name]);
-emit_struct_member(Fd, _G, N, _X, Name, {sequence, _Type, _Length}) ->
- %% Sequence used as struct
- emit(Fd, " ~s ~s;\n",
- [ic_util:to_undersc([Name | N]), Name]);
-emit_struct_member(Fd, G, N, X, Name, Type)
- when element(1, Type) == scoped_id ->
- CType = ic_cbe:mk_c_type(G, N, Type, evaluate_not),
- emit_struct_member(Fd, G, N, X, Name, CType);
-emit_struct_member(Fd, G, N, _X, Name, {enum, Type}) ->
- emit(Fd, " ~s ~s;\n",
- [ic_cbe:mk_c_type(G, N, Type),
- Name]);
-emit_struct_member(Fd, _G, _N, _X, Name, "ETERM*") ->
- emit(Fd, " ETERM* ~s;\n",
- [Name]);
-emit_struct_member(Fd, _G, _N, _X, Name, Type) when is_list(Type) ->
- emit(Fd, " ~s ~s;\n",
- [Type, Name]);
-emit_struct_member(Fd, G, N, _X, Name, Type) ->
- emit(Fd, " ~s ~s;\n",
- [ic_cbe:mk_c_type(G, N, Type),
- Name]).
-
-
-emit_typedef(G, N, X, erlang) ->
- case X of
- {typedef,_,[{array,_,_}],_} -> %% Array but not a typedef of
- %% an array definition
- case ic_options:get_opt(G, be) of
- noc ->
- mkFileArrObj(G,N,X,erlang);
- _ ->
- %% Search the table to see if the type is local or
- %% inherited.
- PTab = ic_genobj:pragmatab(G),
- Id = ic_forms:get_id2(X),
- case ets:match(PTab,{file_data_local,'_','_',
- typedef,N,Id,
- ic_util:to_undersc([Id | N]),
- '_','_'}) of
- [[]] ->
- %% Local, create erlang file for the array
- mkFileArrObj(G,N,X,erlang);
- _ ->
- %% Inherited, do nothing
- ok
- end
- end;
-
- {typedef,{sequence,_,_},_,{tk_sequence,_,_}} ->
- %% Sequence but not a typedef of
- %% a typedef of a sequence definition
- case ic_options:get_opt(G, be) of
- noc ->
- mkFileRecObj(G,N,X,erlang);
- _ ->
- %% Search the table to see if the type is local or
- %% inherited.
- PTab = ic_genobj:pragmatab(G),
- Id = ic_forms:get_id2(X),
- case ets:match(PTab,{file_data_local,'_','_',typedef,
- N,Id,
- ic_util:to_undersc([Id | N]),
- '_','_'}) of
- [[]] ->
- %% Local, create erlang file for the sequence
- mkFileRecObj(G,N,X,erlang);
- _ ->
- %% Inherited, do nothing
- ok
- end
- end;
- _ ->
- ok
- end;
-emit_typedef(G, N, X, c) ->
- B = ic_forms:get_body(X),
- if
- is_record(B, sequence) ->
- emit_sequence_head_def(G, N, X, B, c);
- true ->
- lists:foreach(fun(D) ->
- emit_typedef(G, N, D, B, c)
- end,
- ic_forms:get_idlist(X))
- end.
-
-emit_typedef(G, N, D, Type, c) when is_record(D, array) ->
- emit_array(G, N, D, Type);
-emit_typedef(G, N, D, Type, c) ->
- Name = ic_util:to_undersc([ic_forms:get_id2(D) | N]),
- CType = ic_cbe:mk_c_type(G, N, Type),
- TDType = mk_base_type(G, N, Type),
- ic_code:insert_typedef(G, Name, TDType),
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- Fd = ic_genobj:hrlfiled(G),
- emit(Fd, "\n#ifndef __~s__\n",[ic_util:to_uppercase(Name)]),
- emit(Fd, "#define __~s__\n",[ic_util:to_uppercase(Name)]),
- ic_codegen:mcomment_light(Fd,
- [io_lib:format("Type definition ~s "
- "for type ~s",
- [Name, CType])],
- c),
- emit(Fd, "typedef ~s ~s;\n",
- [CType, Name]),
- emit(Fd, "\n#endif\n\n"),
- ic_codegen:nl(Fd);
- false ->
- ok
- end.
-
-
-mk_base_type(G, N, S) when element(1, S) == scoped_id ->
- {FullScopedName, _T, _TK, _} = ic_symtab:get_full_scoped_name(G, N, S),
- BT = ic_code:get_basetype(G, ic_util:to_undersc(FullScopedName)),
- case BT of
- "erlang_binary" ->
- "erlang_binary";
- "erlang_pid" ->
- "erlang_pid";
- "erlang_port" ->
- "erlang_port";
- "erlang_ref" ->
- "erlang_ref";
- "erlang_term" ->
- "ETERM*";
- Type ->
- Type
- end;
-mk_base_type(_G, _N, S) ->
- S.
-
-emit_array(G, N, D, Type) ->
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- Fd = ic_genobj:hrlfiled(G),
- Name = ic_util:to_undersc([ic_forms:get_id2(D) | N]),
- {_, _, ArrayTK, _} =
- ic_symtab:get_full_scoped_name(G, N,
- ic_symtab:scoped_id_new(
- ic_forms:get_id(D))),
- Dim = extract_dim(ArrayTK),
- CType = ic_cbe:mk_c_type(G, N, Type),
- emit(Fd, "\n#ifndef __~s__\n",[ic_util:to_uppercase(Name)]),
- emit(Fd, "#define __~s__\n",[ic_util:to_uppercase(Name)]),
- ic_codegen:mcomment_light(Fd,
- [io_lib:format("Array definition ~s "
- "for type ~s",
- [Name, CType])],
- c),
- emit(Fd, "typedef ~s ~s~s;\n",
- [CType, Name, ic_cbe:mk_dim(Dim)]),
- emit(Fd, "typedef ~s ~s_slice~s;\n",
- [CType, Name, ic_cbe:mk_slice_dim(Dim)]),
- ic_codegen:nl(Fd),
- create_c_array_coding_file(G, N, {Name, Dim}, Type, typedef),
- emit(Fd, "\n#endif\n\n");
- false ->
- ok
- end.
-
-open_c_coding_file(G, Name) ->
- SName = string:concat(ic_util:mk_oe_name(G, "code_"), Name),
- FName =
- ic_file:join(ic_options:get_opt(G, stubdir),ic_file:add_dot_c(SName)),
- case file:open(FName, [write]) of
- {ok, Fd} ->
- {Fd, SName};
- Other ->
- exit(Other)
- end.
-
-
-
-create_c_array_coding_file(G, N, {Name, Dim}, Type, TypeDefFlag) ->
-
- {Fd , SName} = open_c_coding_file(G, Name),
- HFd = ic_genobj:hrlfiled(G), %% Write on stubfile header
- HrlFName = filename:basename(ic_genobj:include_file(G)),
- ic_codegen:emit_stub_head(G, Fd, SName, c),
- emit(Fd, "#include \"~s\"\n\n",[HrlFName]),
-
- %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %% Fd = ic_genobj:stubfiled(G), %% Write on stubfile
- %% HFd = ic_genobj:hrlfiled(G), %% Write on stubfile header
- %% HrlFName = filename:basename(ic_genobj:include_file(G)),
- %% emit(Fd, "#include \"~s\"\n\n",[HrlFName]),
- %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- put(op_variable_count, 0),
- put(tmp_declarations, []),
-
- emit(HFd, "int ~s~s(CORBA_Environment *oe_env, int*, int*);\n",
- [ic_util:mk_oe_name(G, "sizecalc_"), Name]),
-
- emit(Fd, "int ~s~s(CORBA_Environment *oe_env, int* oe_size_count_index, "
- "int* oe_size) {\n", [ic_util:mk_oe_name(G, "sizecalc_"), Name]),
-
- emit(Fd, " int oe_malloc_size = 0;\n",[]),
- emit(Fd, " int oe_error_code = 0;\n",[]),
- emit(Fd, " int oe_type = 0;\n",[]),
- emit(Fd, " int oe_array_size = 0;\n",[]),
-
- {ok, RamFd} = ram_file:open([], [binary, write]),
-
- emit_sizecount(array, G, N, nil, RamFd, {Name, Dim}, Type),
-
- ic_cbe:emit_tmp_variables(Fd),
- ic_codegen:nl(Fd),
- %% Move data from ram file to output file.
- {ok, Data} = ram_file:get_file(RamFd),
- emit(Fd, Data),
- ram_file:close(RamFd),
-
- emit(Fd, " return 0;\n\n",[]),
- emit(Fd, "}\n",[]),
-
- put(op_variable_count, 0),
- put(tmp_declarations, []),
-
- RefStr = get_refStr(Dim),
-
- case TypeDefFlag of
- typedef ->
- emit(HFd, "int ~s~s(CORBA_Environment *oe_env, ~s);\n",
- [ic_util:mk_oe_name(G, "encode_"), Name, Name]),
-
- emit(Fd, "int ~s~s(CORBA_Environment *oe_env, ~s oe_rec) {\n",
- [ic_util:mk_oe_name(G, "encode_"), Name, Name]);
- no_typedef ->
-
- emit(HFd, "int ~s~s(CORBA_Environment *oe_env, ~s oe_rec~s);\n",
- [ic_util:mk_oe_name(G, "encode_"),
- Name,
- ic_cbe:mk_c_type(G, N, Type),
- RefStr]),
-
- emit(Fd, "int ~s~s(CORBA_Environment *oe_env, ~s oe_rec~s) {\n",
- [ic_util:mk_oe_name(G, "encode_"),
- Name,
- ic_cbe:mk_c_type(G, N, Type),
- RefStr])
- end,
-
- emit(Fd, " int oe_error_code = 0;\n",[]),
-
- {ok, RamFd1} = ram_file:open([], [binary, write]),
-
- case TypeDefFlag of
- typedef ->
- emit_encode(array, G, N, nil, RamFd1, {Name, Dim}, Type);
- no_typedef ->
- emit_encode(array_no_typedef, G, N, nil, RamFd1, {Name, Dim}, Type)
- end,
-
- ic_cbe:emit_tmp_variables(Fd),
- ic_codegen:nl(Fd),
- %% Move data from ram file to output file.
- {ok, Data1} = ram_file:get_file(RamFd1),
- emit(Fd, Data1),
- ram_file:close(RamFd1),
-
- emit(Fd, " return 0;\n\n",[]),
- emit(Fd, "}\n",[]),
-
- put(op_variable_count, 0),
- put(tmp_declarations, []),
-
- case TypeDefFlag of
- typedef ->
- emit(HFd, "int ~s~s(CORBA_Environment *oe_env, char *, "
- "int*, ~s);\n",
- [ic_util:mk_oe_name(G, "decode_"), Name, Name]),
-
- emit(Fd, "int ~s~s(CORBA_Environment *oe_env, char *oe_first, "
- "int* oe_outindex, ~s oe_out) {\n",
- [ic_util:mk_oe_name(G, "decode_"), Name, Name]);
- no_typedef ->
- emit(HFd, "int ~s~s(CORBA_Environment *oe_env, char *, int*, "
- "~s oe_rec~s);\n",
- [ic_util:mk_oe_name(G, "decode_"),
- Name,
- ic_cbe:mk_c_type(G, N, Type),
- RefStr]),
-
- emit(Fd, "int ~s~s(CORBA_Environment *oe_env, char *oe_first, "
- "int* oe_outindex, ~s oe_out~s) {\n",
- [ic_util:mk_oe_name(G, "decode_"),
- Name,
- ic_cbe:mk_c_type(G, N, Type),
- RefStr])
- end,
-
- emit(Fd, " int oe_error_code = 0;\n",[]),
- emit(Fd, " int oe_array_size = 0;\n",[]),
-
- {ok, RamFd2} = ram_file:open([], [binary, write]),
-
- case TypeDefFlag of
- typedef ->
- emit_decode(array, G, N, nil, RamFd2, {Name, Dim}, Type);
- no_typedef ->
- emit_decode(array_no_typedef, G, N, nil, RamFd2, {Name, Dim}, Type)
- end,
-
-
- ic_cbe:emit_tmp_variables(Fd),
- ic_codegen:nl(Fd),
- %% Move data from ram file to output file.
- {ok, Data2} = ram_file:get_file(RamFd2),
- emit(Fd, Data2),
- ram_file:close(RamFd2),
-
- emit(Fd, " *oe_outindex = ~s;\n\n",[align("*oe_outindex")]),
-
- emit(Fd, " return 0;\n\n",[]),
- emit(Fd, "}\n",[]),
- file:close(Fd).
-
-
-get_refStr([]) ->
- "";
-get_refStr([X|Xs]) ->
- "[" ++ X ++ "]" ++ get_refStr(Xs).
-
-
-emit_sequence_head_def(G, N, X, T, c) ->
- %% T is the sequence
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- Fd = ic_genobj:hrlfiled(G),
- SeqName = ic_util:to_undersc([ic_forms:get_id2(X) | N]),
- emit(Fd, "\n#ifndef __~s__\n",[ic_util:to_uppercase(SeqName)]),
- emit(Fd, "#define __~s__\n",[ic_util:to_uppercase(SeqName)]),
- ic_codegen:mcomment_light(Fd,
- [io_lib:format("Struct definition: ~s",
- [SeqName])],
- c),
- emit(Fd, "typedef struct {\n"),
- emit(Fd, " CORBA_unsigned_long _maximum;\n"),
- emit(Fd, " CORBA_unsigned_long _length;\n"),
- emit_seq_buffer(Fd, G, N, T#sequence.type),
- emit(Fd, "} ~s;\n\n", [SeqName]),
- create_c_struct_coding_file(G, N, X, T, SeqName,
- T#sequence.type, sequence_head),
- emit(Fd, "\n#endif\n\n");
-
- false ->
- ok
- end.
-
-emit_seq_buffer(Fd, G, N, Type) ->
- emit(Fd, " ~s* _buffer;\n",
- [ic_cbe:mk_c_type(G, N, Type)]).
-
-%%------------------------------------------------------------
-%%
-%% Emit decode bodies for functions in C for array, sequences and
-%% structs.
-%%
-%%------------------------------------------------------------
-emit_decode(array, G, N, _T, Fd, {_Name, Dim}, Type) ->
- emit(Fd, " if((char*) oe_out == oe_first)\n",[]),
- AlignName =
- lists:concat(["*oe_outindex + ", dim_multiplication(Dim),
- " * sizeof(", ic_cbe:mk_c_type(G, N, Type),")"]),
- emit(Fd, " *oe_outindex = ~s;\n\n",[align(AlignName)]),
- array_decode_dimension_loop(G, N, Fd, Dim, "", Type, array);
-emit_decode(array_no_typedef, G, N, _T, Fd, {_Name, Dim}, Type) ->
- emit(Fd, " if((char*) oe_out == oe_first)\n",[]),
- AlignName =
- lists:concat(["*oe_outindex + ", dim_multiplication(Dim),
- " * sizeof(", ic_cbe:mk_c_type(G, N, Type),")"]),
- emit(Fd, " *oe_outindex = ~s;\n\n",[align(AlignName)]),
- array_decode_dimension_loop(G, N, Fd, Dim, "", Type, array_no_typedef);
-emit_decode(sequence_head, G, N, T, Fd, SeqName, ElType) ->
- ic_cbe:store_tmp_decl(" int oe_seq_len = 0;\n", []),
- ic_cbe:store_tmp_decl(" int oe_seq_count = 0;\n", []),
- ic_cbe:store_tmp_decl(" int oe_seq_dummy = 0;\n", []),
-
- TmpBuf =
- case ictype:isBasicTypeOrEterm(G, N, ElType) of
- true ->
- Tmp = "oe_seq_tmpbuf",
- ic_cbe:store_tmp_decl(" char* ~s = 0;\n", [Tmp]),
- Tmp;
- false ->
- "NOT USED"
- end,
-
- MaxSize = get_seq_max(T),
- emit(Fd, " if((char*) oe_out == oe_first)\n",[]),
- emit(Fd, " *oe_outindex = ~s;\n\n",
- [align(["*oe_outindex + sizeof(", SeqName, ")"])]),
-
- Ctype = ic_cbe:mk_c_type(G, N, ElType),
- emit(Fd, " if ((oe_error_code = ei_decode_list_header(oe_env->_inbuf, "
- "&oe_env->_iin, &oe_seq_len)) < 0) {\n"),
- case ictype:isBasicTypeOrEterm(G, N, ElType) of
- true ->
- emit(Fd, " int oe_type = 0;\n"),
- emit(Fd, " (int) ei_get_type(oe_env->_inbuf, &oe_env->_iin, "
- "&oe_type, &oe_seq_len);\n\n"),
-
- if
- MaxSize == infinity ->
- ok;
- true ->
- emit(Fd, " if (oe_seq_len > ~w) {\n", [MaxSize]),
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, DATA_CONVERSION, "
- "\"Length of sequence `~s' out of bound\");\n"
- " return -1;\n }\n", [SeqName])
- end,
- emit(Fd, " oe_out->_maximum = oe_seq_len;\n"),
- emit(Fd, " oe_out->_length = oe_seq_len;\n"),
- emit(Fd, " oe_out->_buffer = (void *) (oe_first + "
- "*oe_outindex);\n"),
- emit(Fd, " *oe_outindex = ~s;\n",
- [align(["*oe_outindex + (sizeof(", Ctype, ") * "
- "oe_out->_length)"])]),
- emit(Fd,
- " if ((~s = malloc(oe_seq_len + 1)) == NULL) {\n"
- " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "NO_MEMORY, \"Cannot malloc\");\n"
- " return -1;\n"
- " }\n", [TmpBuf]),
- emit(Fd, " if ((oe_error_code = ei_decode_string("
- "oe_env->_inbuf, &oe_env->_iin, ~s)) < 0) {\n", [TmpBuf]),
- emit(Fd, " CORBA_free(~s);\n\n", [TmpBuf]),
- emit_c_dec_rpt(Fd, " ", "string1", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " for (oe_seq_count = 0; "
- "oe_seq_count < oe_out->_length; oe_seq_count++)\n"),
- case ictype:isBasicType(G, N, ElType) of
- true ->
- emit(Fd, " oe_out->_buffer[oe_seq_count] = (unsigned char) "
- "~s[oe_seq_count];\n\n", [TmpBuf]);
- false -> %% Term
- emit(Fd, " oe_out->_buffer[oe_seq_count] = "
- "erl_mk_int(~s[oe_seq_count]);\n\n",[TmpBuf]) % XXXX What?
- end,
- emit(Fd, " CORBA_free(~s);\n\n", [TmpBuf]);
- false ->
- emit(Fd, " return oe_error_code;\n")
- end,
-
- emit(Fd, " } else {\n"),
-
- if
- MaxSize == infinity ->
- ok;
- true ->
- emit(Fd, " if (oe_seq_len > ~w) {\n", [MaxSize]),
- emit(Fd, " CORBA_exc_set(oe_env, "
- "CORBA_SYSTEM_EXCEPTION, DATA_CONVERSION, "
- "\"Length of sequence `~s' out of bound\");\n"
- " return -1;\n }\n", [SeqName])
- end,
-
- emit(Fd, " oe_out->_maximum = oe_seq_len;\n"),
- emit(Fd, " oe_out->_length = oe_seq_len;\n"),
- emit(Fd, " oe_out->_buffer = (void *) (oe_first + *oe_outindex);\n"),
- emit(Fd, " *oe_outindex = ~s;\n\n",
- [align(["*oe_outindex + (sizeof(", Ctype, ") * oe_out->_length)"])]),
-
- if
- Ctype == "CORBA_char *" ->
- emit(Fd, " for (oe_seq_count = 0; "
- "oe_seq_count < oe_out->_length; oe_seq_count++) {\n"),
- emit(Fd, " oe_out->_buffer[oe_seq_count] = "
- "(void*) (oe_first + *oe_outindex);\n\n"),
- ic_cbe:emit_decoding_stmt(G, N, Fd, ElType,
- "oe_out->_buffer[oe_seq_count]",
- "",
- "oe_env->_inbuf", 0, "", caller_dyn),
- emit(Fd, " *oe_outindex = ~s;",
- [align(["*oe_outindex + strlen(oe_out->_buffer["
- "oe_seq_count]) + 1"])]);
- true ->
- emit(Fd, " for (oe_seq_count = 0; "
- "oe_seq_count < oe_out->_length; oe_seq_count++) {\n"),
- case ictype:isArray(G, N, ElType) of
- %% XXX Silly. There is no real difference between the
- %% C statements produced by the following calls.
- true ->
- ic_cbe:emit_decoding_stmt(G, N, Fd, ElType,
- "oe_out->_buffer[oe_seq_count]",
- "",
- "oe_env->_inbuf",
- 0, "oe_outindex", generator);
- false ->
- ic_cbe:emit_decoding_stmt(G, N, Fd, ElType,
- "oe_out->_buffer + oe_seq_count",
- "",
- "oe_env->_inbuf",
- 0, "oe_outindex", generator)
- end
- end,
- emit(Fd, " }\n"),
- emit(Fd, " if (oe_out->_length != 0) {\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_list_header("
- "oe_env->_inbuf, &oe_env->_iin, &oe_seq_dummy)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_decode_list_header", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " } else\n"),
- emit(Fd, " oe_out->_buffer = NULL;\n"),
- emit(Fd, " }\n");
-
-emit_decode(struct, G, N, _T, Fd, StructName, ElTypes) ->
- Length = length(ElTypes) + 1,
- Tname = ic_cbe:mk_variable_name(op_variable_count),
- Tname1 = ic_cbe:mk_variable_name(op_variable_count),
-
- ic_cbe:store_tmp_decl(" int ~s = 0;\n",[Tname]),
- ic_cbe:store_tmp_decl(" char ~s[256];\n\n",[Tname1]),
-
- emit(Fd, " if((char*) oe_out == oe_first)\n",[]),
- AlignName = lists:concat(["*oe_outindex + sizeof(",StructName,")"]),
- emit(Fd, " *oe_outindex = ~s;\n\n", [align(AlignName)]),
-
- emit(Fd, " if ((oe_error_code = ei_decode_tuple_header(oe_env->_inbuf, "
- "&oe_env->_iin, &~s)) < 0) {\n", [Tname]),
- emit_c_dec_rpt(Fd, " ", "ei_decode_tuple_header", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit(Fd, " if (~s != ~p) {\n",[Tname, Length]),
- emit_c_dec_rpt(Fd, " ", "tuple header size != ~p", [Length]),
- emit(Fd, " return -1;\n }\n"),
-
- emit(Fd, " if ((oe_error_code = ei_decode_atom(oe_env->_inbuf, "
- "&oe_env->_iin, ~s)) < 0) {\n", [Tname1]),
- emit_c_dec_rpt(Fd, " ", "ei_decode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " if (strcmp(~s, ~p) != 0)\n",[Tname1, StructName]),
- emit(Fd, " return -1;\n\n"),
- lists:foreach(
- fun({ET, EN}) ->
- case ic_cbe:is_variable_size(G, N, ET) of
- true ->
- case ET of
-
- {struct, _, _, _} ->
- %% Sequence member = a struct
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- StructName ++ "_" ++
- ic_forms:get_id2(ET),
- "&oe_out->" ++ EN,
- "", "oe_env->_inbuf",
- 0,
- "oe_outindex",
- generator);
-
- {sequence, _, _} ->
- %% Sequence member = a struct XXX ??
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- StructName ++ "_" ++
- EN,
- "&oe_out->" ++ EN,
- "",
- "oe_env->_inbuf",
- 0,
- "oe_outindex",
- generator);
- {_,{array, _, _}} ->
- emit(Fd, " oe_out->~s = (void *) "
- "(oe_first+*oe_outindex);\n\n",[EN]),
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- StructName ++ "_" ++
- EN, "oe_out->" ++ EN ,
- "",
- "oe_env->_inbuf",
- 0,
- "oe_outindex",
- generator);
-
- {union, _, _, _, _} ->
- %% Sequence member = a union
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- StructName ++ "_" ++
- ic_forms:get_id2(ET),
- "&oe_out->" ++ EN,
- "",
- "oe_env->_inbuf",
- 0,
- "oe_outindex",
- generator);
-
- {string,_} ->
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- ET,
- "oe_out->" ++ EN ,
- "",
- "oe_env->_inbuf",
- 0,
- "oe_outindex",
- generator_malloc);
-
- {scoped_id,_,_,_} ->
- case ictype:member2type(G,StructName,EN) of
- array ->
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- ET,
- "oe_out->" ++
- EN,
- "",
- "oe_env->"
- "_inbuf",
- 0,
- "oe_outindex",
- generator);
- struct ->
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- ET,
- "&oe_out->" ++
- EN ,
- "",
- "oe_env->"
- "_inbuf",
- 0,
- "oe_outindex",
- generator);
- sequence ->
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- ET,
- "&oe_out->" ++
- EN,
- "",
- "oe_env->"
- "_inbuf",
- 0,
- "oe_outindex",
- generator);
- union ->
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- ET,
- "&oe_out->" ++
- EN,
- "",
- "oe_env->"
- "_inbuf",
- 0,
- "oe_outindex",
- generator);
- _ ->
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- ET,
- "oe_out->" ++
- EN,
- "",
- "oe_env->"
- "_inbuf",
- 0,
- "oe_outindex",
- generator)
- end;
-
- _ ->
- emit(Fd, " oe_out->~s = (void *) "
- "(oe_first+*oe_outindex);\n\n",[EN]),
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- ET,
- "oe_out->" ++ EN ,
- "",
- "oe_env->_inbuf",
- 0, "oe_outindex",
- generator)
- end;
- false ->
- case ET of
-
- {struct, _, _, _} ->
- %% A struct member
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- StructName ++ "_" ++
- ic_forms:get_id2(ET),
- "&oe_out->" ++ EN ,
- "",
- "oe_env->_inbuf",
- 0,
- "oe_outindex",
- generator);
-
- {_,{array, _, _}} ->
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- StructName ++ "_" ++
- EN,
- "oe_out->" ++ EN ,
- "",
- "oe_env->_inbuf",
- 0,
- "oe_outindex",
- generator);
-
- {union, _, _, _, _} ->
- %% Sequence member = a union
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- StructName ++ "_" ++
- ic_forms:get_id2(ET),
- "&oe_out->" ++ EN ,
- "",
- "oe_env->_inbuf",
- 0,
- "oe_outindex",
- generator);
-
- {_,_} ->
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- ET,
- "&oe_out->" ++ EN ,
- "",
- "oe_env->_inbuf",
- 0,
- "oe_outindex",
- generator);
- {scoped_id,_,_,_} ->
- case ic_symtab:get_full_scoped_name(G, N, ET) of
- {_FullScopedName, _, {tk_array,_,_}, _} ->
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- ET,
- "oe_out->" ++
- EN,
- "",
- "oe_env->"
- "_inbuf",
- 0,
- "oe_outindex",
- generator);
- {_FullScopedName, _, {tk_string,_}, _} ->
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- ET,
- "oe_out->" ++
- EN,
- "",
- "oe_env->"
- "_inbuf",
- 0,
- "oe_outindex",
- generator);
- {_FullScopedName, _, {tk_struct,_,_,_}, _} ->
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- ET,
- "&oe_out->" ++
- EN,
- "",
- "oe_env->"
- "_inbuf",
- 0,
- "oe_outindex",
- generator);
-
- {_FullScopedName, _,
- {tk_union,_,_,_,_,_}, _} ->
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- ET,
- "&oe_out->" ++
- EN,
- "",
- "oe_env->"
- "_inbuf",
- 0,
- "oe_outindex",
- generator);
-
- _ ->
- ic_cbe:emit_decoding_stmt(G, N, Fd,
- ET,
- "&oe_out->" ++
- EN,
- "",
- "oe_env->"
- "_inbuf",
- 0,
- "oe_outindex",
- generator)
- end
- end
- end
- end,
- ElTypes).
-
-
-ref_array_static_dec(array, true) ->
- %% Typedef, Static, Basic Type
- "&(oe_out)";
-ref_array_static_dec(array, false) ->
- %% Typedef, Static, Constr Type
- "&(oe_out)";
-ref_array_static_dec(array_no_typedef, true) ->
- %% No Typedef, Static, Basic Type
- "&oe_out";
-ref_array_static_dec(array_no_typedef, false) ->
- %% No Typedef, Static, Constr Type
- "&oe_out".
-
-
-ref_array_dynamic_dec(G, N, T, array) ->
- case ictype:isString(G, N, T) of
- true -> % Typedef, Dynamic, String
- "oe_out";
- false -> % Typedef, Dynamic, No String
- "&(oe_out)"
- end;
-ref_array_dynamic_dec(G, N, T, array_no_typedef) ->
- case ictype:isString(G, N, T) of
- true -> % No Typedef, Dynamic, String
- "oe_out";
- false -> % No Typedef, Dynamic, No String
- "&oe_out"
- end.
-
-
-
-array_decode_dimension_loop(G, N, Fd, [Dim], Dimstr, Type, TDFlag) ->
- Tname = ic_cbe:mk_variable_name(op_variable_count),
- ic_cbe:store_tmp_decl(" int ~s = 0;\n",[Tname]),
-
- emit(Fd, " if ((oe_error_code = ei_decode_tuple_header(oe_env->_inbuf, "
- "&oe_env->_iin, &oe_array_size)) < 0) {\n",
- []),
- emit_c_dec_rpt(Fd, " ", "ei_decode_tuple_header", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- %% This is disabled due to a bug in erl_interface :
- %% tuples inside tuples hae no correct data about the size
- %% of the tuple........( allways = 0 )
- %%emit(Fd, " if (oe_array_size != ~s)\n",[Dim]),
- %%emit(Fd, " return -1;\n\n"),
-
- emit(Fd, " for (~s = 0; ~s < ~s; ~s++) {\n",
- [Tname, Tname, Dim, Tname]),
-
-
- ArrAccess =
- case ic_cbe:is_variable_size(G, N, Type) of
- true ->
- ref_array_dynamic_dec(G, N, Type, TDFlag) ++
- Dimstr ++ "[" ++ Tname ++ "]";
- false ->
- ref_array_static_dec(TDFlag, ictype:isBasicType(G,N,Type)) ++
- Dimstr ++ "[" ++ Tname ++ "]"
- end,
-
- ic_cbe:emit_decoding_stmt(G, N, Fd, Type,
- ArrAccess,
- "", "oe_env->_inbuf", 0,
- "oe_outindex", generator),
-
- %% emit(Fd, "\n *oe_outindex +=
- %% sizeof(~s);\n",[ic_cbe:mk_c_type(G, N, Type)]),
- emit(Fd, " }\n");
-array_decode_dimension_loop(G, N, Fd, [Dim | Ds], _Dimstr, Type, TDFlag) ->
- Tname = ic_cbe:mk_variable_name(op_variable_count),
- ic_cbe:store_tmp_decl(" int ~s = 0;\n",[Tname]),
-
- emit(Fd, " if ((oe_error_code = ei_decode_tuple_header(oe_env->_inbuf, "
- "&oe_env->_iin, &oe_array_size)) < 0) {\n",
- []),
- emit_c_dec_rpt(Fd, " ", "ei_decode_tuple_header", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- %% This is disabled due to a bug in erl_interface :
- %% tuples inside tuples hae no correct data about the size
- %% of the tuple........( allways = 0 )
- %%emit(Fd, " if (oe_array_size != ~s)\n",[Dim]),
- %%emit(Fd, " return -1;\n\n"),
-
- emit(Fd, " for (~s = 0; ~s < ~s; ~s++) {\n",
- [Tname, Tname, Dim, Tname]),
- array_decode_dimension_loop(G, N, Fd, Ds, "[" ++ Tname ++ "]" , Type,
- TDFlag),
-
- emit(Fd, " }\n").
-
-dim_multiplication([D]) ->
- D;
-dim_multiplication([D |Ds]) ->
- D ++ "*" ++ dim_multiplication(Ds).
-
-emit_encode(array, G, N, _T, Fd, {_Name, Dim}, Type) ->
- array_encode_dimension_loop(G, N, Fd, Dim, {"",""}, Type, array);
-emit_encode(array_no_typedef, G, N, _T, Fd, {_Name, Dim}, Type) ->
- array_encode_dimension_loop(G, N, Fd, Dim, {"",""}, Type,
- array_no_typedef);
-emit_encode(sequence_head, G, N, T, Fd, SeqName, ElType) ->
- Tname = ic_cbe:mk_variable_name(op_variable_count),
- ic_cbe:store_tmp_decl(" int ~s = 0;\n\n",[Tname]),
-
- MaxSize = get_seq_max(T),
- if
- MaxSize == infinity ->
- ok;
- true ->
- emit(Fd, " if (oe_rec->_length > ~w) {\n", [MaxSize]),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "DATA_CONVERSION, \"Length of sequence `~s' "
- "out of bound\");\n"
- " return -1;\n }\n", [SeqName])
- end,
-
- emit(Fd, " if (oe_rec->_length != 0) {\n"),
-
- emit(Fd, " if ((oe_error_code = oe_ei_encode_list_header(oe_env, "
- "oe_rec->_length)) < 0) {\n",
- []),
- emit_c_enc_rpt(Fd, " ", "oi_ei_encode_list_header", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit(Fd, " for (~s = 0; ~s < oe_rec->_length; ~s++) {\n",
- [Tname, Tname, Tname]),
- case ElType of
- {_,_} -> %% ElType = elementary type or pointer type
- ic_cbe:emit_encoding_stmt(G, N, Fd, ElType, "oe_rec->_buffer[" ++
- Tname ++ "]", "oe_env->_outbuf");
-
- {scoped_id,local,_,["term","erlang"]} ->
- ic_cbe:emit_encoding_stmt(G, N, Fd, ElType, "oe_rec->_buffer[" ++
- Tname ++ "]", "oe_env->_outbuf");
-
- {scoped_id,_,_,_} ->
- case ic_symtab:get_full_scoped_name(G, N, ElType) of
- {_, typedef, TDef, _} ->
- case TDef of
- {tk_struct,_,_,_} ->
- ic_cbe:emit_encoding_stmt(G, N, Fd, ElType,
- "&oe_rec->_buffer[" ++
- Tname ++ "]",
- "oe_env->_outbuf");
- {tk_sequence,_,_} ->
- ic_cbe:emit_encoding_stmt(G, N, Fd, ElType,
- "&oe_rec->_buffer[" ++
- Tname ++ "]",
- "oe_env->_outbuf");
- {tk_union,_,_,_,_,_} ->
- ic_cbe:emit_encoding_stmt(G, N, Fd, ElType,
- "&oe_rec->_buffer[" ++
- Tname ++ "]",
- "oe_env->_outbuf");
- _ ->
- ic_cbe:emit_encoding_stmt(G, N, Fd, ElType,
- "oe_rec->_buffer[" ++
- Tname ++ "]",
- "oe_env->_outbuf")
- end;
- {_,enum,_,_} ->
- ic_cbe:emit_encoding_stmt(G, N, Fd, ElType,
- "oe_rec->_buffer[" ++
- Tname ++ "]",
- "oe_env->_outbuf");
- _ ->
- ic_cbe:emit_encoding_stmt(G, N, Fd, ElType,
- "&oe_rec->_buffer[" ++
- Tname ++ "]",
- "oe_env->_outbuf")
- end;
-
- _ -> %% ElType = structure
- ic_cbe:emit_encoding_stmt(G, N, Fd, ElType,
- "&oe_rec->_buffer[" ++ Tname ++ "]",
- "oe_env->_outbuf")
- end,
- emit(Fd, " }\n"),
- emit(Fd, " }\n"),
- emit(Fd, " if ((oe_error_code = oe_ei_encode_empty_list(oe_env)) < 0) {\n"),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_empty_list", []),
- emit(Fd, " return oe_error_code;\n }\n");
-emit_encode(struct, G, N, _T, Fd, StructName, ElTypes) ->
- Length = length(ElTypes) + 1,
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_tuple_header(oe_env, ~p)) < 0) {\n", [Length]),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_tuple_header", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_atom(oe_env, ~p)) < 0) {\n", [StructName]),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- lists:foreach(
- fun({ET, EN}) ->
- case ET of
- {sequence, _, _} ->
- %% Sequence = struct
- ic_cbe:emit_encoding_stmt(G, N, Fd,
- StructName ++ "_" ++ EN,
- "&oe_rec->" ++ EN,
- "oe_env->_outbuf");
- {_,{array, _, _Dims}} ->
- ic_cbe:emit_encoding_stmt(G, N, Fd,
- StructName ++ "_" ++ EN,
- "oe_rec->" ++ EN,
- "oe_env->_outbuf");
-
- {union,_,_,_,_} ->
- ic_cbe:emit_encoding_stmt(G, N, Fd,
- StructName ++ "_" ++
- ic_forms:get_id2(ET),
- "&oe_rec->" ++ EN,
- "oe_env->_outbuf");
-
- {struct,_,_,_} ->
- ic_cbe:emit_encoding_stmt(G, N, Fd,
- StructName ++ "_" ++
- ic_forms:get_id2(ET),
- "&oe_rec->" ++ EN,
- "oe_env->_outbuf");
-
- {scoped_id,_,_,_} ->
- case ictype:member2type(G,StructName,EN) of
- struct ->
- ic_cbe:emit_encoding_stmt(G, N, Fd,
- ET,
- "&oe_rec->" ++ EN,
- "oe_env->_outbuf");
- sequence ->
- ic_cbe:emit_encoding_stmt(G, N, Fd,
- ET,
- "&oe_rec->" ++ EN,
- "oe_env->_outbuf");
- union ->
- ic_cbe:emit_encoding_stmt(G, N, Fd,
- ET,
- "&oe_rec->" ++ EN,
- "oe_env->_outbuf");
- array ->
- ic_cbe:emit_encoding_stmt(G, N, Fd,
- ET,
- "oe_rec->" ++ EN,
- "oe_env->_outbuf");
- _ ->
- ic_cbe:emit_encoding_stmt(G, N, Fd,
- ET,
- "oe_rec->" ++ EN,
- "oe_env->_outbuf")
- end;
- _ ->
- ic_cbe:emit_encoding_stmt(G, N, Fd,
- ET,
- "oe_rec->" ++ EN,
- "oe_env->_outbuf")
- end
- end,
- ElTypes).
-
-ref_array_static_enc(array, true) ->
- %% Typedef, Static, Basic Type
- "oe_rec";
-ref_array_static_enc(array, false) ->
- %% Typedef, Static, Constr Type
- "&(oe_rec)";
-ref_array_static_enc(array_no_typedef, true) ->
- %% No Typedef, Static, Basic Type
- "oe_rec";
-ref_array_static_enc(array_no_typedef, false) ->
- %% No Typedef, Static, Constr Type
- "&oe_rec".
-
-
-ref_array_dynamic_enc(G, N, T, array) ->
- case ictype:isString(G, N, T) of
- true -> % Typedef, Dynamic, String
- "oe_rec";
- false -> % Typedef, Dynamic, No String
- "&(oe_rec)"
- end;
-ref_array_dynamic_enc(G, N, T, array_no_typedef) ->
- case ictype:isString(G, N, T) of
- true -> % No Typedef, Dynamic, String
- "oe_rec";
- false -> % No Typedef, Dynamic, No String
- "&oe_rec"
- end.
-
-
-
-array_encode_dimension_loop(G, N, Fd, [Dim], {Str1,_Str2}, Type, TDFlag) ->
- Tname = ic_cbe:mk_variable_name(op_variable_count),
- ic_cbe:store_tmp_decl(" int ~s = 0;\n",[Tname]),
-
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_tuple_header(oe_env, ~s)) < 0) {\n", [Dim]),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_tuple_header", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit(Fd, " for (~s = 0; ~s < ~s; ~s++) {\n",
- [Tname, Tname, Dim, Tname]),
-
- ArrAccess =
- case ic_cbe:is_variable_size(G, N, Type) of
- true ->
- ref_array_dynamic_enc(G, N, Type, TDFlag) ++
- Str1 ++ "[" ++ Tname ++ "]";
- false ->
- ref_array_static_enc(TDFlag, ictype:isBasicType(G,N,Type)) ++
- Str1 ++ "[" ++ Tname ++ "]"
- end,
-
- ic_cbe:emit_encoding_stmt(G, N, Fd, Type, ArrAccess, "oe_env->_outbuf"),
- emit(Fd, " }\n");
-array_encode_dimension_loop(G, N, Fd, [Dim | Ds],{Str1,Str2}, Type, TDFlag) ->
- Tname = ic_cbe:mk_variable_name(op_variable_count),
- ic_cbe:store_tmp_decl(" int ~s = 0;\n",[Tname]),
-
- emit(Fd, " if ((oe_error_code = "
- "oe_ei_encode_tuple_header(oe_env, ~s)) < 0) {\n", [Dim]),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_tuple_header", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit(Fd, " for (~s = 0; ~s < ~s; ~s++) {\n",
- [Tname, Tname, Dim, Tname]),
- array_encode_dimension_loop(G, N, Fd, Ds,
- {Str1 ++ "[" ++ Tname ++ "]", Str2},
- Type, TDFlag),
- emit(Fd, " }\n").
-
-
-emit_sizecount(array, G, N, _T, Fd, {_Name, Dim}, Type) ->
- emit(Fd, " if(*oe_size == 0)\n",[]),
- AlignName = lists:concat(["*oe_size + ", dim_multiplication(Dim),
- " * sizeof(", ic_cbe:mk_c_type(G, N, Type),")"]),
- emit(Fd, " *oe_size = ~s;\n\n",[align(AlignName)]),
- array_size_dimension_loop(G, N, Fd, Dim, Type),
- emit(Fd, " *oe_size = ~s;\n\n",
- [align("*oe_size + oe_malloc_size")]),
- ic_codegen:nl(Fd);
-
-emit_sizecount(sequence_head, G, N, T, Fd, SeqName, ElType) ->
- ic_cbe:store_tmp_decl(" int oe_seq_len = 0;\n", []),
- ic_cbe:store_tmp_decl(" int oe_seq_count = 0;\n", []),
-
- emit(Fd, " if(*oe_size == 0)\n",[]),
- emit(Fd, " *oe_size = ~s;\n\n",
- [align(["*oe_size + sizeof(", SeqName, ")"])]),
-
- MaxSize = get_seq_max(T),
-
- emit(Fd, " if ((oe_error_code = ei_get_type(oe_env->_inbuf, "
- "oe_size_count_index, &oe_type, &oe_seq_len)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_get_type", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- if
- MaxSize == infinity ->
- ok;
- true ->
- emit(Fd, " if (oe_seq_len > ~w) {\n", [MaxSize]),
- emit(Fd, " CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, "
- "DATA_CONVERSION, \"Length of sequence `~s' "
- "out of bound\");\n"
- " return -1;\n }\n", [SeqName])
- end,
-
- CType = ic_cbe:mk_c_type(G, N, ElType),
-
- emit(Fd, " if ((oe_error_code = ei_decode_list_header(oe_env->_inbuf, "
- "oe_size_count_index, NULL)) < 0) {\n"),
-
- case ictype:isBasicTypeOrEterm(G, N, ElType) of
- true ->
- emit(Fd, " if ((oe_error_code = ei_decode_string(oe_env->"
- "_inbuf, oe_size_count_index, NULL)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_decode_string", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit(Fd, " oe_malloc_size = ~s;\n\n",
- [align(["sizeof(", CType, ") * oe_seq_len"])]);
- false ->
- emit_c_dec_rpt(Fd, " ", "non mea culpa", []),
- emit(Fd, " return oe_error_code;\n\n")
- end,
-
- emit(Fd, " } else {\n"),
-
- emit(Fd, " oe_malloc_size = ~s;\n\n",
- [align(["sizeof(", CType, ") * oe_seq_len"])]),
-
- emit(Fd, " for (oe_seq_count = 0; oe_seq_count < oe_seq_len; "
- "oe_seq_count++) {\n"),
- ic_cbe:emit_malloc_size_stmt(G, N, Fd, ElType,
- "oe_env->_inbuf", 0, generator),
- emit(Fd, " }\n"),
-
- emit(Fd, " if (oe_seq_len != 0) \n"),
- emit(Fd, " if ((oe_error_code = ei_decode_list_header(oe_env->_inbuf,"
- "oe_size_count_index, NULL)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_decode_list_header", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " }\n"),
- emit(Fd, " *oe_size = ~s;\n\n", [align("*oe_size + oe_malloc_size")]);
-
-emit_sizecount(struct, G, N, _T, Fd, StructName, ElTypes) ->
- Length = length(ElTypes) + 1,
- Tname = ic_cbe:mk_variable_name(op_variable_count),
- ic_cbe:store_tmp_decl(" int ~s = 0;\n\n",[Tname]),
-
- emit(Fd, " if(*oe_size == 0)\n",[]),
- AlignName = lists:concat(["*oe_size + sizeof(",StructName,")"]),
- emit(Fd, " *oe_size = ~s;\n\n", [align(AlignName)]),
- ic_codegen:nl(Fd),
-
- emit(Fd, " if ((oe_error_code = "
- "ei_get_type(oe_env->_inbuf, oe_size_count_index, &oe_type, "
- "&~s)) < 0) {\n", [Tname]),
- emit_c_dec_rpt(Fd, " ", "ei_get_type", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit(Fd, " if (~s != ~p) {\n",[Tname, Length]),
- emit_c_dec_rpt(Fd, " ", "~s != ~p", [Tname, Length]),
- emit(Fd, " return -1;\n }\n"),
-
-
- emit(Fd, " if ((oe_error_code = "
- "ei_decode_tuple_header(oe_env->_inbuf, "
- "oe_size_count_index, 0)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_decode_tuple_header", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " if ((oe_error_code = "
- "ei_decode_atom(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n", []),
- emit_c_dec_rpt(Fd, " ", "ei_decode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- lists:foreach(
- fun({ET, EN}) ->
- case ic_cbe:is_variable_size(G, N, ET) of
- true ->
- case ET of
- {sequence, _, _} ->
- ic_cbe:emit_malloc_size_stmt(
- G, N, Fd,
- StructName ++ "_" ++ EN,
- "oe_env->_inbuf",
- 0,
- generator);
- {_,{array, _, _}} ->
- ic_cbe:emit_malloc_size_stmt(
- G, N, Fd,
- StructName ++ "_" ++ EN,
- "oe_env->_inbuf",
- 0,
- generator);
- {union,_,_,_,_} ->
- ic_cbe:emit_malloc_size_stmt(
- G, N, Fd,
- StructName ++ "_" ++ ic_forms:get_id2(ET),
- "oe_env->_inbuf",
- 0,
- generator);
-
- {struct,_,_,_} ->
- ic_cbe:emit_malloc_size_stmt(
- G, N, Fd,
- StructName ++ "_" ++ ic_forms:get_id2(ET),
- "oe_env->_inbuf",
- 0,
- generator);
-
- _ ->
- ic_cbe:emit_malloc_size_stmt(
- G, N, Fd,
- ET,
- "oe_env->_inbuf",
- 0,
- generator)
- end;
- false ->
- case ET of
- {_,{array, _, _}} ->
- ic_cbe:emit_malloc_size_stmt(
- G, N, Fd,
- StructName ++ "_" ++ EN,
- "oe_env->_inbuf",
- 0,
- generator);
-
- {union,_,_,_,_} ->
- ic_cbe:emit_malloc_size_stmt(
- G, N, Fd,
- StructName ++ "_" ++ ic_forms:get_id2(ET),
- "oe_env->_inbuf",
- 0,
- generator);
-
- {struct,_,_,_} ->
- ic_cbe:emit_malloc_size_stmt(
- G, N, Fd,
- StructName ++ "_" ++ ic_forms:get_id2(ET),
- "oe_env->_inbuf",
- 0,
- generator);
- _ ->
- ic_cbe:emit_malloc_size_stmt(
- G, N, Fd,
- ET,
- "oe_env->_inbuf",
- 1,
- generator)
- end
- end
- end,
- ElTypes),
-
- emit(Fd, " *oe_size = ~s;\n\n",
- [align("*oe_size + oe_malloc_size")]).
-
-
-array_size_dimension_loop(G, N, Fd, [Dim], Type) ->
- Tname = ic_cbe:mk_variable_name(op_variable_count),
-
- ic_cbe:store_tmp_decl(" int ~s = 0;\n",[Tname]),
- emit(Fd, " if ((oe_error_code = "
- "ei_get_type(oe_env->_inbuf, oe_size_count_index, "
- "&oe_type, &oe_array_size)) < 0) {\n",
- []),
- emit_c_dec_rpt(Fd, " ", "ei_get_type", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit(Fd, " if (oe_array_size != ~s) {\n",[Dim]),
- emit_c_dec_rpt(Fd, " ", "array size != ~s", [Dim]),
- emit(Fd, " return -1;\n }\n"),
-
- emit(Fd, " if ((oe_error_code = ei_decode_tuple_header(oe_env->_inbuf, "
- "oe_size_count_index, 0)) < 0) {\n", []),
- emit_c_dec_rpt(Fd, " ", "ei_decode_tuple_header", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit(Fd, " for (~s = 0; ~s < ~s; ~s++) {\n",
- [Tname, Tname, Dim, Tname]),
- ic_cbe:emit_malloc_size_stmt(G, N, Fd,
- Type, "oe_env->_inbuf", 0, generator),
- emit(Fd, " }\n");
-array_size_dimension_loop(G, N, Fd, [Dim | Ds], Type) ->
- Tname = ic_cbe:mk_variable_name(op_variable_count),
-
- ic_cbe:store_tmp_decl(" int ~s = 0;\n",[Tname]),
- emit(Fd, " if ((oe_error_code = "
- "ei_get_type(oe_env->_inbuf, oe_size_count_index, "
- "&oe_type, &oe_array_size)) < 0) {\n", []),
- emit_c_dec_rpt(Fd, " ", "ei_get_type", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit(Fd, " if (oe_array_size != ~s) {\n",[Dim]),
- emit_c_dec_rpt(Fd, " ", "array size != ~s", [Dim]),
- emit(Fd, " return -1;\n }\n"),
-
- emit(Fd, " if ((oe_error_code = ei_decode_tuple_header(oe_env->_inbuf, "
- "oe_size_count_index, 0)) < 0) {\n",
- []),
- emit_c_dec_rpt(Fd, " ", "ei_decode_tuple_header", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit(Fd, " for (~s = 0; ~s < ~s; ~s++) {\n",
- [Tname, Tname, Dim, Tname]),
- array_size_dimension_loop(G, N, Fd, Ds, Type),
- emit(Fd, " }\n").
-
-
-create_c_struct_coding_file(G, N, _X, T, StructName, ElTypes, StructType) ->
-
- {Fd , SName} = open_c_coding_file(G, StructName), % stub file
- HFd = ic_genobj:hrlfiled(G), % stub header file
- HrlFName = filename:basename(ic_genobj:include_file(G)),
-
- ic_codegen:emit_stub_head(G, Fd, SName, c),
- HrlFName = filename:basename(ic_genobj:include_file(G)),
- emit(Fd, "#include \"~s\"\n\n",[HrlFName]),
-
- %% Size count
-
- put(op_variable_count, 0),
- put(tmp_declarations, []),
-
- emit(HFd, "int ~s~s(CORBA_Environment *oe_env, int*, int*);\n",
- [ic_util:mk_oe_name(G, "sizecalc_"), StructName]),
-
- emit(Fd, "int ~s~s(CORBA_Environment *oe_env, "
- "int* oe_size_count_index, int* oe_size)\n{\n",
- [ic_util:mk_oe_name(G, "sizecalc_"), StructName]),
-
- emit(Fd, " int oe_malloc_size = 0;\n",[]),
- emit(Fd, " int oe_error_code = 0;\n",[]),
- emit(Fd, " int oe_type = 0;\n",[]),
-
- {ok, RamFd} = ram_file:open([], [binary, write]),
-
- emit_sizecount(StructType, G, N, T, RamFd, StructName, ElTypes),
-
- ic_cbe:emit_tmp_variables(Fd),
- ic_codegen:nl(Fd),
- %% Move data from ram file to output file.
- {ok, Data} = ram_file:get_file(RamFd),
- emit(Fd, Data),
- ram_file:close(RamFd),
-
- emit(Fd, " return 0;\n\n",[]),
- emit(Fd, "}\n\n",[]),
-
- %% Encode
-
- put(op_variable_count, 0),
- put(tmp_declarations, []),
-
-
- emit(HFd, "int ~s~s(CORBA_Environment *oe_env, ~s*);\n",
- [ic_util:mk_oe_name(G, "encode_"), StructName, StructName]),
-
- emit(Fd, "int ~s~s(CORBA_Environment *oe_env, ~s* oe_rec)\n{\n",
- [ic_util:mk_oe_name(G, "encode_"), StructName, StructName]),
-
- emit(Fd, " int oe_error_code = 0;\n",[]),
-
- {ok, RamFd1} = ram_file:open([], [binary, write]),
-
- emit_encode(StructType, G, N, T, RamFd1, StructName, ElTypes),
-
- ic_cbe:emit_tmp_variables(Fd),
- ic_codegen:nl(Fd),
- %% Move data from ram file to output file.
- {ok, Data1} = ram_file:get_file(RamFd1),
- emit(Fd, Data1),
- ram_file:close(RamFd1),
-
- emit(Fd, " return 0;\n\n",[]),
- emit(Fd, "}\n\n",[]),
-
- %% Decode
-
- put(op_variable_count, 0),
- put(tmp_declarations, []),
-
- emit(HFd, "int ~s~s(CORBA_Environment *oe_env, char *, int*, ~s *);\n",
- [ic_util:mk_oe_name(G, "decode_"), StructName, StructName]),
-
- emit(Fd, "int ~s~s(CORBA_Environment *oe_env, char *oe_first, "
- "int* oe_outindex, "
- "~s *oe_out)\n{\n",
- [ic_util:mk_oe_name(G, "decode_"), StructName, StructName]),
-
- emit(Fd, " int oe_error_code = 0;\n",[]),
-
- {ok, RamFd2} = ram_file:open([], [binary, write]),
-
- emit_decode(StructType, G, N, T, RamFd2, StructName, ElTypes),
-
- ic_cbe:emit_tmp_variables(Fd),
- ic_codegen:nl(Fd),
- %% Move data from ram file to output file.
- {ok, Data2} = ram_file:get_file(RamFd2),
- emit(Fd, Data2),
- ram_file:close(RamFd2),
-
- emit(Fd, " *oe_outindex = ~s;\n",[align("*oe_outindex")]),
- emit(Fd, " return 0;\n\n",[]),
- emit(Fd, "}\n\n",[]),
- file:close(Fd).
-
-
-%%------------------------------------------------------------
-%%
-%% emit primitive for unions.
-%%
-%%------------------------------------------------------------
-emit_union(G, N, X, erlang) ->
- case ic_genobj:is_hrlfile_open(G) of
- true ->
- ic_codegen:record(G, X,
- ic_util:to_undersc([ic_forms:get_id2(X) | N]),
- nil,nil),
- mkFileRecObj(G,N,X,erlang);
- false -> ok
- end;
-emit_union(_G, _N, _X, c) -> %% Not supported in c backend
- true.
-
-
-%%------------------------------------------------------------
-%%
-%% emit erlang modules for objects with record definitions
-%% (such as unions or structs), or sequences
-%%
-%% The record files, other than headers are only generated
-%% for CORBA...... If wished an option could allows even
-%% for other backends ( not necessary anyway )
-%%
-%%------------------------------------------------------------
-mkFileRecObj(G,N,X,erlang) ->
- case ic_options:get_opt(G, be) of
- erl_corba ->
- SName =
- ic_util:to_undersc([ic_forms:get_id2(X) | N]),
- FName =
- ic_file:join(ic_options:get_opt(G, stubdir),
- ic_file:add_dot_erl(SName)),
-
- case file:open(FName, [write]) of
- {ok, Fd} ->
- HrlFName = filename:basename(ic_genobj:include_file(G)),
-
- ic_codegen:emit_stub_head(G, Fd, SName, erlang),
- emit(Fd, "-include(~p).\n\n",[HrlFName]),
- emit_exports(G,Fd),
- emit_rec_methods(G,N,X,SName,Fd),
- ic_codegen:nl(Fd),
- ic_codegen:nl(Fd),
- file:close(Fd);
- Other ->
- exit(Other)
- end;
- _ ->
- true
- end.
-
-
-%%------------------------------------------------------------
-%%
-%% emit erlang modules for objects with array definitions..
-%%
-%%------------------------------------------------------------
-mkFileArrObj(G,N,X,erlang) ->
- SName =
- ic_util:to_undersc([ic_forms:get_id2(X) | N]),
- FName =
- ic_file:join(ic_options:get_opt(G, stubdir),
- ic_file:add_dot_erl(SName)),
-
- case file:open(FName, [write]) of
- {ok, Fd} ->
- HrlFName = filename:basename(ic_genobj:include_file(G)),
-
- ic_codegen:emit_stub_head(G, Fd, SName, erlang),
- emit(Fd, "-include(~p).\n\n",[HrlFName]),
- emit_exports(G,Fd),
- emit_arr_methods(G,N,X,SName,Fd),
- ic_codegen:nl(Fd),
- ic_codegen:nl(Fd),
- file:close(Fd);
- Other ->
- exit(Other)
- end.
-
-
-
-
-%%------------------------------------------------------------
-%%
-%% emit exports for erlang modules which represent records.
-%%
-%%------------------------------------------------------------
-emit_exports(G,Fd) ->
- case ic_options:get_opt(G, be) of
- erl_corba ->
- emit(Fd, "-export([tc/0,id/0,name/0]).\n\n\n\n",[]);
- _ ->
- emit(Fd, "-export([id/0,name/0]).\n\n\n\n",[])
- end.
-
-
-%%------------------------------------------------------------
-%%
-%% emit erlang module functions which represent records, yields
-%% record information such as type code, identity and name.
-%%
-%%------------------------------------------------------------
-emit_rec_methods(G,N,X,Name,Fd) ->
-
- IR_ID = ictk:get_IR_ID(G, N, X),
-
- case ic_options:get_opt(G, be) of
-
- erl_corba ->
- TK = ic_forms:get_tk(X),
-
- case TK of
- undefined ->
- STK = ic_forms:search_tk(G,ictk:get_IR_ID(G, N, X)),
- emit(Fd, "%% returns type code\n",[]),
- emit(Fd, "tc() -> ~p.\n\n",[STK]),
- emit(Fd, "%% returns id\n",[]),
- emit(Fd, "id() -> ~p.\n\n",[IR_ID]),
- emit(Fd, "%% returns name\n",[]),
- emit(Fd, "name() -> ~p.\n\n",[Name]);
- _ ->
- emit(Fd, "%% returns type code\n",[]),
- emit(Fd, "tc() -> ~p.\n\n",[TK]),
- emit(Fd, "%% returns id\n",[]),
- emit(Fd, "id() -> ~p.\n\n",[IR_ID]),
- emit(Fd, "%% returns name\n",[]),
- emit(Fd, "name() -> ~p.\n\n",[Name])
- end;
-
- _ ->
- emit(Fd, "%% returns id\n",[]),
- emit(Fd, "id() -> ~p.\n\n",[IR_ID]),
- emit(Fd, "%% returns name\n",[]),
- emit(Fd, "name() -> ~p.\n\n",[Name])
- end.
-
-
-
-%%------------------------------------------------------------
-%%
-%% emit erlang module functions which represent arrays, yields
-%% record information such as type code, identity and name.
-%%
-%%------------------------------------------------------------
-emit_arr_methods(G,N,X,Name,Fd) ->
-
- IR_ID = ictk:get_IR_ID(G, N, X),
-
- case ic_options:get_opt(G, be) of
-
- erl_corba ->
-
- TK = ic_forms:get_type_code(G, N, X),
-
- emit(Fd, "%% returns type code\n",[]),
- emit(Fd, "tc() -> ~p.\n\n",[TK]),
- emit(Fd, "%% returns id\n",[]),
- emit(Fd, "id() -> ~p.\n\n",[IR_ID]),
- emit(Fd, "%% returns name\n",[]),
- emit(Fd, "name() -> ~p.\n\n",[Name]);
-
- _ ->
-
- emit(Fd, "%% returns id\n",[]),
- emit(Fd, "id() -> ~p.\n\n",[IR_ID]),
- emit(Fd, "%% returns name\n",[]),
- emit(Fd, "name() -> ~p.\n\n",[Name])
- end.
-
-get_seq_max(T) when is_record(T, sequence) andalso T#sequence.length == 0 ->
- infinity;
-get_seq_max(T) when is_record(T, sequence) andalso is_tuple(T#sequence.length) ->
- list_to_integer(element(3, T#sequence.length)).
-
-
-align(Cs) ->
- ic_util:mk_align(Cs).
-
diff --git a/lib/ic/src/ictk.erl b/lib/ic/src/ictk.erl
deleted file mode 100644
index 701d662776..0000000000
--- a/lib/ic/src/ictk.erl
+++ /dev/null
@@ -1,874 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(ictk).
-
-
-%% Toplevel generation functions
--export([reg_gen/3, unreg_gen/3]).
-
-
-%% Utilities
--export([get_IR_ID/3, get_IR_VSN/3, register_name/1, unregister_name/1]).
-
--import(ic_forms, [get_id2/1, get_body/1, get_idlist/1]).
--import(ic_util, [mk_name/2, mk_oe_name/2, to_atom/1, to_list/1]).
--import(ic_codegen, [emit/2, emit/3, nl/1]).
-
--include("icforms.hrl").
--include("ic.hrl").
-
-%%--------------------------------------------------------------------
-%%
-%% IFR Registration Generation
-%%
-%%
-%%--------------------------------------------------------------------
-
--define(IFRID(G), mk_name(G, "IFR")).
--define(VARID(G), mk_name(G, "VAR")).
--define(IFRMOD, orber_ifr).
-
-reg_gen(G, N, X) ->
- S = ic_genobj:tktab(G),
- Light = ic_options:get_opt(G, light_ifr),
- init_var(),
- case ic_genobj:is_stubfile_open(G) of
- true when Light == false ->
- Var = ?IFRID(G),
- Fd = ic_genobj:stubfiled(G),
- nl(Fd), nl(Fd), nl(Fd),
- emit(Fd, "~p() ->\n", [to_atom(register_name(G))]),
- emit(Fd, " ~s = ~p:find_repository(),\n",
- [Var, ?IFRMOD]),
- nl(Fd),
-
- %% Write call function that checks if included
- %% modules and interfaces are created.
- emit(Fd, " register_tests(~s),\n",[?IFRID(G)]),
-
- reg2(G, S, N, Var, X),
- nl(Fd),
- emit(Fd, " ok.\n"),
-
- %% Write general register test function.
- register_tests(Fd,G),
-
- %% Write functopn that registers modules only if
- %% they are not registered.
- register_if_unregistered(Fd);
- true when Light == true ->
- Fd = ic_genobj:stubfiled(G),
- nl(Fd), nl(Fd), nl(Fd),
- Regname = to_atom(register_name(G)),
- emit(Fd, "~p() ->\n\t~p([]).\n\n", [Regname, Regname]),
- emit(Fd, "~p(OE_Options) ->\n\t~p:add_items(?MODULE, OE_Options,\n\t[",
- [Regname, ?IFRMOD]),
- reg_light(G, N, X),
- emit(Fd, "ok]),\n\tok.\n");
- false ->
- ok
- end.
-
-reg_light(G, N, X) when is_list(X) ->
- reg_light_list(G, N, X);
-reg_light(G, N, X) when is_record(X, module) ->
- reg_light_list(G, [get_id2(X) | N], get_body(X));
-reg_light(G, N, X) when is_record(X, struct) ->
- emit(ic_genobj:stubfiled(G), "{~p, ~p, struct},\n\t",
- [get_IR_ID(G, N, X), get_module(X, N)]);
-reg_light(G, N, X) when is_record(X, except) ->
- emit(ic_genobj:stubfiled(G), "{~p, ~p, except},\n\t",
- [get_IR_ID(G, N, X), get_module(X, N)]);
-reg_light(G, N, X) when is_record(X, union) ->
- emit(ic_genobj:stubfiled(G), "{~p, ~p, union},\n\t",
- [get_IR_ID(G, N, X), get_module(X, N)]);
-reg_light(G, N, X) when is_record(X, interface) ->
- emit(ic_genobj:stubfiled(G), "{~p, ~p, interface},\n\t",
- [get_IR_ID(G, N, X), get_module(X, N)]),
- reg_light_list(G, [get_id2(X)|N], get_body(X));
-reg_light(_G, _N, _X) ->
- ok.
-
-get_module(X, N) ->
- List = [get_id2(X) | N],
- list_to_atom(lists:foldl(fun(E, Acc) -> E++"_"++Acc end,
- hd(List), tl(List))).
-
-%% This function filters off all "#include <FileName>.idl" code that
-%% come along from preprocessor and scanner. Produces code ONLY for
-%% the actuall file. See ticket OTP-2133
-reg_light_list(_G, _N, []) -> [];
-reg_light_list(G, N, List ) ->
- CurrentFileName = ic_genobj:idlfile(G),
- reg_light_list(G, N, {CurrentFileName,true}, List).
-
-%% The filter function + loop
-reg_light_list(_G, _N, {_CFN, _Status}, []) -> [];
-reg_light_list(G, N, {CFN,Status}, [X | Xs]) ->
- case Status of
- true ->
- case X of
- {preproc,_,{_,_,_FileName},[{_,_,"1"}]} ->
- reg_light_list(G, N, {CFN,false}, Xs);
- _ ->
- reg_light(G, N, X),
- reg_light_list(G, N, {CFN,Status}, Xs)
- end;
- false ->
- case X of
- {preproc,_,{_,_,CFN},[{_,_,"2"}]} ->
- reg_light(G, N, X),
- reg_light_list(G, N, {CFN,true}, Xs);
- _ ->
- reg_light_list(G, N, {CFN,Status}, Xs)
- end
- end.
-
-
-%% reg2 is top level registration
-
-reg2(G, S, N, Var, X) ->
- reg2(G, S, N, "Repository_create_", Var, X).
-
-reg2(G, S, N, C, V, X) when is_list(X) -> reg2_list(G, S, N, C, V, X);
-
-reg2(G, S, N, C, V, X) when is_record(X, module) ->
- NewV = r_emit2(G, S, N, C, V, X, "", []),
- reg2_list(G, S, [get_id2(X) | N], "ModuleDef_create_", NewV, get_body(X));
-
-reg2(G, S, N, C, V, X) when is_record(X, const) ->
- r_emit2(G, S, N, C, V, X, ", ~s, ~p",
- [get_idltype(G, S, N, X), {X#const.tk, X#const.val}]);
-
-reg2(G, S, N, C, V, X) when is_record(X, struct) ->
- do_struct(G, S, N, C, V, X, ic_forms:get_tk(X));
-
-reg2(G, S, N, C, V, X) when is_record(X, except) ->
- do_except(G, S, N, C, V, X, ic_forms:get_tk(X));
-
-reg2(G, S, N, C, V, X) when is_record(X, union) ->
- do_union(G, S, N, C, V, X, ic_forms:get_tk(X));
-
-reg2(G, S, N, C, V, X) when is_record(X, enum) ->
- r_emit2(G, S, N, C, V, X, ", ~p",
- [get_enum_member_list(G, S, N, get_body(X))]);
-
-reg2(G, S, N, C, V, X) when is_record(X, typedef) ->
- do_typedef(G, S, N, C, V, X),
- look_for_types(G, S, N, C, V, get_body(X));
-
-reg2(G, S, N, C, V, X) when is_record(X, attr) ->
- XX = #id_of{type=X},
- lists:foreach(fun(Id) -> r_emit2(G, S, N, C, V, XX#id_of{id=Id}, ", ~s, ~p",
- [get_idltype(G, S, N, X), get_mode(G, N, X)])
- end,
- get_idlist(X));
-
-reg2(G, S, N, C, V, X) when is_record(X, interface) ->
- N2 = [get_id2(X) | N],
- Body = get_body(X),
- BIs = get_base_interfaces(G,X), %% produce code for the interface inheritance
- NewV = r_emit2(G, S, N, C, V, X, ", " ++ BIs,[]),
- reg2_list(G, S, N2, "InterfaceDef_create_", NewV, Body);
-
-
-reg2(G, S, N, C, V, X) when is_record(X, op) ->
- r_emit2(G, S, N, C, V, X, ", ~s, ~p, [~s], [~s], ~p",
- [get_idltype(G, S, N, X), get_mode(G, N, X),
- get_params(G, S, N, X#op.params), get_exceptions(G, S, N, X),
- get_context(G, S, N, X)]);
-
-reg2(_G, _S, _N, _C, _V, X) when is_record(X, preproc) -> ok;
-
-reg2(_G, _S, _N, _C, _V, X) when is_record(X, pragma) -> ok;
-
-reg2(_G, _S, _N, _C, _V, _X) -> ok.
-
-
-%% This function filters off all "#include <FileName>.idl" code that
-%% come along from preprocessor and scanner. Produces code ONLY for
-%% the actuall file. See ticket OTP-2133
-reg2_list(_G, _S, _N, _C, _V, []) -> [];
-reg2_list(G, S, N, C, V, List ) ->
- CurrentFileName = ic_genobj:idlfile(G),
- reg2_list(G, S, N, C, V, {CurrentFileName,true}, List).
-
-%% The filter function + loop
-reg2_list(_G, _S, _N, _C, _V, {_CFN, _Status}, []) -> [];
-reg2_list(G, S, N, C, V, {CFN,Status}, [X | Xs]) ->
- case Status of
- true ->
- case X of
- {preproc,_,{_,_,_FileName},[{_,_,"1"}]} ->
- reg2_list(G, S, N, C, V, {CFN,false}, Xs);
- _ ->
- F = reg2(G, S, N, C, V, X),
- [F | reg2_list(G, S, N, C, V, {CFN,Status}, Xs)]
- end;
- false ->
- case X of
- {preproc,_,{_,_,CFN},[{_,_,"2"}]} ->
- F = reg2(G, S, N, C, V, X),
- [F | reg2_list(G, S, N, C, V, {CFN,true}, Xs)];
- _ ->
- reg2_list(G, S, N, C, V, {CFN,Status}, Xs)
- end
- end.
-
-
-
-
-
-%% General registration tests
-register_tests(Fd,G) ->
- IfrId = ?IFRID(G),
- emit(Fd,"\n\n%% General IFR registration checks.\n", []),
- emit(Fd,"register_tests(~s)->\n",[IfrId]),
- emit(Fd," re_register_test(~s),\n",[IfrId]),
- emit(Fd," include_reg_test(~s).\n\n",[IfrId]),
-
- emit(Fd,"\n%% IFR type Re-registration checks.\n", []),
- case ic_pragma:fetchRandomLocalType(G) of
- {ok,TypeId} ->
- emit(Fd,"re_register_test(~s)->\n",[IfrId]),
- emit(Fd," case orber_ifr:'Repository_lookup_id'(~s,~p) of\n", [IfrId,TypeId]),
- emit(Fd," [] ->\n true;\n",[]),
- emit(Fd," _ ->\n exit({allready_registered,~p})\n end.\n\n", [TypeId]);
- false ->
- emit(Fd,"re_register_test(_)-> true.\n",[])
- end,
-
- emit(Fd,"~s",[check_include_regs(G)]).
-
-
-
-
-%% This function produces code for existance check over
-%% top level included modules and interfaces
-check_include_regs(G) ->
- IfrId = ?IFRID(G),
- case ic_pragma:get_incl_refs(G) of
- none ->
- io_lib:format("\n%% No included idl-files detected.\n", []) ++
- io_lib:format("include_reg_test(_~s) -> true.\n",[IfrId]);
- IMs ->
- io_lib:format("\n%% IFR registration checks for included idl files.\n", []) ++
- io_lib:format("include_reg_test(~s) ->\n",[IfrId]) ++
- check_incl_refs(G,IfrId,IMs)
- end.
-
-
-
-check_incl_refs(_,_,[]) ->
- io_lib:format(" true.\n",[]);
-check_incl_refs(G,IfrId,[[First]|Rest]) ->
- ModId = ic_pragma:scope2id(G,First),
- io_lib:format(" case orber_ifr:'Repository_lookup_id'(~s,~p) of~n", [IfrId,ModId]) ++
- io_lib:format(" [] ->~n exit({unregistered,~p});~n", [ModId]) ++
- io_lib:format(" _ ->~n true~n end,~n",[]) ++
- check_incl_refs(G,IfrId,Rest).
-
-
-
-%% This function will return module ref, it will
-%% also register module if not registered.
-register_if_unregistered(Fd) ->
- emit(Fd, "\n\n%% Fetch top module reference, register if unregistered.\n"),
- emit(Fd, "oe_get_top_module(OE_IFR, ID, Name, Version) ->\n"),
- emit(Fd, " case orber_ifr:'Repository_lookup_id'(OE_IFR, ID) of\n"),
- emit(Fd, " [] ->\n"),
- emit(Fd, " orber_ifr:'Repository_create_module'(OE_IFR, ID, Name, Version);\n"),
- emit(Fd, " Mod ->\n"),
- emit(Fd, " Mod\n",[]),
- emit(Fd, " end.\n\n"),
- emit(Fd, "%% Fetch module reference, register if unregistered.\n"),
- emit(Fd, "oe_get_module(OE_IFR, OE_Parent, ID, Name, Version) ->\n"),
- emit(Fd, " case orber_ifr:'Repository_lookup_id'(OE_IFR, ID) of\n"),
- emit(Fd, " [] ->\n"),
- emit(Fd, " orber_ifr:'ModuleDef_create_module'(OE_Parent, ID, Name, Version);\n"),
- emit(Fd, " Mod ->\n"),
- emit(Fd, " Mod\n",[]),
- emit(Fd, " end.\n").
-
-
-
-do_typedef(G, S, N, C, V, X) ->
- case ic_genobj:is_stubfile_open(G) of
- false -> ok;
- true ->
- Fd = ic_genobj:stubfiled(G),
- Thing = get_thing_name(X),
- IR_VSN = get_IR_VSN(G, N, X),
- TK = ic_forms:get_tk(X),
-
- lists:foreach(
- fun(Id) ->
- r_emit_raw(G, X, Fd, "", C, Thing, V,
- get_IR_ID(G, N, Id), get_id2(Id),
- IR_VSN, ", ~s",
- [get_idltype_tk(G, S, N,
- ictype:maybe_array(G, S, N,
- Id, TK))])
- end, get_idlist(X))
- end.
-
-
-do_union(G, S, N, C, V, X, {tk_union, _IFRID, _Name, DiscrTK, _DefNr, L}) ->
- N2 = [get_id2(X) | N],
- r_emit2(G, S, N, C, V, X, ", ~s, [~s]",
- [get_idltype_tk(G, S, N, DiscrTK),
- get_union_member_def(G, S, N2, L)]),
- look_for_types(G, S, N2, C, V, get_body(X)).
-
-do_struct(G, S, N, C, V, X, {tk_struct, _IFRID, _Name, ElemList}) ->
- N2 = [get_id2(X) | N],
- r_emit2(G, S, N, C, V, X, ", [~s]",
- [get_member_def(G, S, N, ElemList)]),
- look_for_types(G, S, N2, C, V, get_body(X)).
-
-do_except(G, S, N, C, V, X, {tk_except, _IFRID, _Name, ElemList}) ->
- N2 = [get_id2(X) | N],
- r_emit2(G, S, N, C, V, X, ", [~s]",
- [get_member_def(G, S, N, ElemList)]),
- look_for_types(G, S, N2, C, V, get_body(X)).
-
-
-%% new_var finds an unused Erlang variable name by increasing a
-%% counter.
-new_var(_G) ->
- lists:flatten(["_OE_", integer_to_list(put(var_count, get(var_count) + 1))]).
-init_var() ->
- put(var_count, 1).
-
-%% Public interface. The name of the register function.
-register_name(G) ->
- mk_oe_name(G, "register").
-unregister_name(G) ->
- mk_oe_name(G, "unregister").
-
-
-
-look_for_types(G, S, N, C, V, L) when is_list(L) ->
- lists:foreach(fun(X) -> look_for_types(G, S, N, C, V, X) end, L);
-look_for_types(G, S, N, C, V, {_Name, TK}) -> % member
- look_for_types(G, S, N, C, V, TK);
-look_for_types(_G, _S, _N, _C, _V, {tk_union, _IFRID, _Name, _DT, _Def, _L}) ->
- ok;
-look_for_types(G, S, N, C, V, {_Label, _Name, TK}) -> % case_dcl
- look_for_types(G, S, N, C, V, TK);
-look_for_types(_G, _S, _N, _C, _V, {tk_struct, _IFRID, _Name, _L}) ->
- ok;
-look_for_types(_G, _S, _N, _C, _V, _X) ->
- ok.
-
-
-
-
-%% This function produces code for the interface inheritance registration.
-%% It produces a string that represents a list of function calls.
-%% This list becomes a list of object references when the main function
-%% "orber_ifr:ModuleDef_create_interface" is called.
-
-get_base_interfaces(G,X) ->
- case element(3,X) of
- [] ->
- "[]";
- L ->
- "[" ++
- lists:flatten(
- lists:foldl(
- fun(E, Acc) -> [call_fun_str(G,E), ", " | Acc] end,
- call_fun_str(G,hd(L)),
- tl(L)
- )
- ) ++ "]"
- end.
-
-call_fun_str(G,S) ->
- lists:flatten(
- io_lib:format("orber_ifr:lookup_id(~s,\"~s\")",
- [ ?IFRID(G),
- ic_pragma:scope2id(G,S)] )).
-
-
-
-
-
-%%--------------------------------------------------------------------
-%%
-%% r_emit emits an IFR register function call. It returns a new
-%% variable (if further defs should be added to that one)
-%%
-%% G is genobj
-%%
-%% S is symbol table (ets)
-%%
-%% N is list of ids describing scope
-%%
-%% C is create stub (eg. "Repository_create_")
-%%
-%% V is variable name where current def should be added,
-%%
-%% X is the current def item,
-%%
-%% F and A is auxillary format and args that will be io_lib
-%% formatted and inserted as a string (don't forget to start with
-%% ", ")
-%%
-r_emit2(G, _S, N, C, V, X, F, A) ->
- case ic_genobj:is_stubfile_open(G) of
- false -> ok;
- true ->
- {NewV, Str} = get_assign(G, V, X),
- r_emit_raw(G, X, ic_genobj:stubfiled(G), Str,
- C, get_thing_name(X), V,
- get_IR_ID(G, N, X), get_id2(X), get_IR_VSN(G, N, X),
- F, A),
- NewV
- end.
-
-
-%%--------------------------------------------------------------------
-%%
-%% An IFR register line registers an entity (Thing) into the IFR. The
-%% thing is registered INTO something, an type is registered into a
-%% module for instance, and this is reflected in the Var parameter
-%% below. The var parameter is the name of the parent IFR object. The
-%% Thing parameter is the name of the thing we're trying to register,
-%% a typdef is called an alias and an interface is called an
-%% interface. Sometimes we need to store the thing we're registering
-%% into a variable because we're going to add other things to it
-%% later, modules and interfaces are such containers, so we must
-%% remember that variable for later use.
-%%
-%% All parameters shall be strings unless otherwise noted
-%%
-%% Fd - File descriptor
-%% AssignStr - Assign or not, empty except for interfaces and modules
-%% Create - Create has diff. names dep. on into what we register
-%% Thing - WHAT is registered, interface
-%% Var - The name of the variable we register into
-%% IR_ID - The IFR identifier (may be "")
-%% Id - The identifier (name) of the object
-%% IR_VSN - The IFR version as a string
-%% AuxStr - An auxillary string
-%%
-%%r_emit_raw(Fd, AssignStr, Create, Thing, Var, IR_ID, Id, IR_VSN) ->
-%% r_emit_raw(Fd, AssignStr, Create, Thing, Var, IR_ID, Id, IR_VSN, "", []).
-r_emit_raw(_G, X, Fd, AssignStr, "Repository_create_", Thing, Var, IR_ID, Id, IR_VSN, F, A)
- when is_record(X, module) ->
- emit(Fd, "~n ~s~p(~s, \"~s\", \"~s\", \"~s\"~s),~n",
- [AssignStr, to_atom("oe_get_top_"++Thing), Var, IR_ID, Id,
- IR_VSN, io_lib:format(F, A)]);
-r_emit_raw(G, X, Fd, AssignStr, "ModuleDef_create_", Thing, Var, IR_ID, Id, IR_VSN, F, A)
- when is_record(X, module) ->
- emit(Fd, "~n ~s~p(~s, ~s, \"~s\", \"~s\", \"~s\"~s),~n",
- [AssignStr, to_atom("oe_get_"++Thing), ?IFRID(G), Var, IR_ID, Id,
- IR_VSN, io_lib:format(F, A)]);
-r_emit_raw(_G, _X, Fd, AssignStr, Create, Thing, Var, IR_ID, Id, IR_VSN, F, A) ->
- emit(Fd, "~n ~s~p:~p(~s, \"~s\", \"~s\", \"~s\"~s),~n",
- [AssignStr, ?IFRMOD, to_atom(Create++Thing), Var, IR_ID, Id,
- IR_VSN, io_lib:format(F, A)]).
-
-
-
-
-%% Used by r_emit. Returns tuple {Var, Str} where Var is the resulting
-%% output var (if any, otherwise same as input arg) and Str is a
-%% string of the assignment if any ("" or "Var = ")
-get_assign(G, _V, X) when is_record(X, module) ->
- mk_assign(G);
-get_assign(G, _V, X) when is_record(X, interface) ->
- mk_assign(G);
-get_assign(_G, V, _X) -> {V, ""}.
-mk_assign(G) ->
- V = new_var(G),
- {V, io_lib:format("~s = ", [V])}.
-
-%% Returns a list of strings of all enum members (suitable for ~p)
-get_enum_member_list(_G, _S, _N, L) ->
- lists:map(fun(M) -> get_id2(M) end, L).
-
-%% Will output a string of the union members.
-get_union_member_def(_G, _S, _N, []) -> [];
-get_union_member_def(G, S, N, L) ->
- [union_member2str(G, S, N, hd(L)) |
- lists:map(fun(M) -> [", ", union_member2str(G, S, N, M)] end, tl(L))].
-%% lists:foldl(fun(M, Acc) ->
-%% [union_member2str(G, S, N, M),", " | Acc] end,
-%% union_member2str(G, S, N, hd(L)), tl(L)).
-
-union_member2str(G, S, N, {Label, Name, TK}) ->
- io_lib:format("~s{name=~p, label=~p, type=~p, type_def=~s}",
- ["#unionmember", Name, Label, TK,
- get_idltype_tk(G, S, N, TK)]).
-
-
-%% Will output a string of the struct members. Works for exceptions
-%% and structs
-%%
-get_member_def(_G, _S, _N, []) -> [];
-get_member_def(G, S, N, L) ->
- [member2str(G, S, N, hd(L)) |
- lists:map(fun(M) -> [", ", member2str(G, S, N, M)] end, tl(L))].
-
-member2str(G, S, N, {Id, TK}) ->
- io_lib:format("~s{name=~p, type=~p, type_def=~s}",
- ["#structmember", Id, TK, get_idltype_tk(G, S, N, TK)]).
-
-%% Translates between record names and create operation names.
-get_thing_name(X) when is_record(X, op) -> "operation";
-get_thing_name(X) when is_record(X, const) -> "constant";
-get_thing_name(X) when is_record(X, typedef) -> "alias";
-get_thing_name(X) when is_record(X, attr) -> "attribute";
-get_thing_name(X) when is_record(X, except) -> "exception";
-get_thing_name(X) when is_record(X, id_of) -> get_thing_name(X#id_of.type);
-get_thing_name(X) -> to_list(element(1,X)).
-
-
-%% Returns the mode (in, out, oneway etc) of ops and params. Return
-%% value is an atom.
-get_mode(_G, _N, X) when is_record(X, op) ->
- case X#op.oneway of
- {oneway, _} -> 'OP_ONEWAY';
- _ -> 'OP_NORMAL'
- end;
-get_mode(_G, _N, X) when is_record(X, attr) ->
- case X#attr.readonly of
- {readonly, _} -> 'ATTR_READONLY';
- _ -> 'ATTR_NORMAL'
- end;
-get_mode(_G, _N, X) when is_record(X, param) ->
- case X#param.inout of
- {in, _} -> 'PARAM_IN';
- {inout, _} -> 'PARAM_INOUT';
- {out, _} -> 'PARAM_OUT'
- end.
-
-
-%% Returns a string form of idltype creation.
-%%get_idltype_id(G, S, N, X, Id) ->
-%% TK = ictype:tk_lookup(G, S, N, Id),
-%% get_idltype_tk(G, S, N, TK).
-get_idltype(G, S, N, X) ->
- get_idltype_tk(G, S, N, ic_forms:get_tk(X)).
-get_idltype_tk(G, _S, _N, TK) ->
- io_lib:format("~p:~p(~s, ~p)", [orber_ifr, 'Repository_create_idltype',
- ?IFRID(G), TK]).
-
-%% Returns a string form of typecode creation. This shall be found in
-%% the type code symbol table.
-%%get_typecode(G, S, N, X) -> typecode.
-%%get_typecode(G, S, N, X) -> tk(G, S, N, get_type(X)).
-
-
-%% Returns the string form of a list of parameters.
-get_params(_G, _S, _N, []) -> "";
-get_params(G, S, N, L) ->
- lists:foldl(fun(X, Acc) -> param2str(G, S, N, X)++", "++Acc end,
- param2str(G, S, N, hd(L)), tl(L)).
-
-
-%% Converts a parameter to a string.
-param2str(G, S, N, X) ->
- io_lib:format("~s{name=~p, type=~p, type_def=~s, mode=~p}~n",
- ["#parameterdescription", get_id2(X),
- ic_forms:get_tk(X),
- %%tk_lookup(G, S, N, get_type(X)),
- get_idltype(G, S, N, X),
- get_mode(G, N, X)]).
-
-
-
-
-%% Public interface. Returns the IFR ID of an object. This
-%% is updated to comply with CORBA 2.0 pragma directives.
-get_IR_ID(G, N, X) ->
- ScopedId = [get_id2(X) | N],
- case ic_pragma:get_alias(G,ScopedId) of
- none ->
- case ic_pragma:pragma_id(G, N, X) of
- none ->
- case ic_pragma:pragma_prefix(G, N, X) of
- none ->
- IR_ID = lists:flatten(
- io_lib:format("IDL:~s:~s",
- [slashify(ScopedId),
- get_IR_VSN(G, N, X)])),
- ic_pragma:mk_alias(G,IR_ID,ScopedId),
- IR_ID;
- PF ->
- IR_ID = lists:flatten(
- io_lib:format("IDL:~s:~s",
- [ PF ++ "/" ++
- get_id2(X),
- get_IR_VSN(G, N, X)])),
- ic_pragma:mk_alias(G,IR_ID,ScopedId),
- IR_ID
- end;
- PI ->
- ic_pragma:mk_alias(G,PI,ScopedId),
- PI
- end;
- Alias ->
- Alias
- end.
-
-
-%% Public interface. Returns the IFR Version of an object. This
-%% is updated to comply with CORBA 2.0 pragma directives.
-get_IR_VSN(G, N, X) ->
- ic_pragma:pragma_version(G,N,X).
-
-
-
-
-
-%% Returns a slashified name, [I1, M1] becomes "M1/I1"
-%slashify(List) -> lists:foldl(fun(X, Acc) -> get_id2(X)++"/"++Acc end,
-% hd(List), tl(List)).
-
-%% Returns a slashified name, [I1, M1] becomes "M1/I1"
-slashify(List) -> lists:foldl(fun(X, Acc) -> X++"/"++Acc end,
- hd(List), tl(List)).
-
-
-%% Returns the context literals of an op
-get_context(_G, _S, _N, X) ->
- lists:map(fun(C) -> element(3, C) end, X#op.ctx).
-
-
-
-%% Returns the list of the exceptions of an operation
-get_exceptions(G, S, N, X) ->
- case X#op.raises of
- [] ->
- "";
- L ->
- lists:flatten(
- lists:foldl(
- fun(E, Acc) -> [excdef(G, S, N, X, E), ", " | Acc] end,
- excdef(G, S, N, X, hd(L)),
- tl(L)
- )
- )
- end.
-
-
-%% Returns the definition of an exception of an operation
-excdef(G, S, N, X, L) ->
- io_lib:format("orber_ifr:lookup_id(~s,\"~s\")",
- [ ?IFRID(G),
- get_EXC_ID(G, S, N, X, L) ] ).
-
-
-
-
-
-
-%% This function produces code for the exception registration.
-%% It produces a string that represents a list of function calls.
-%% This list becomes a list of object references when the main function
-%% "orber_ifr:InterfaceDef_create_operation" is called.
-
-get_EXC_ID(G, _S, N, X, ScopedId) ->
- case ic_pragma:get_alias(G,ScopedId) of
- none ->
- case ic_pragma:pragma_id(G, N, X) of
- none ->
- case ic_pragma:pragma_prefix(G, N, X) of
- none ->
- EXC_ID = lists:flatten(
- io_lib:format("IDL:~s:~s", [slashify(ScopedId),
- get_IR_VSN(G, N, X)])),
- ic_pragma:mk_alias(G,EXC_ID,ScopedId),
- EXC_ID;
- PF ->
- EXC_ID = lists:flatten(
- io_lib:format("IDL:~s:~s", [ PF ++ "/" ++
- hd(ScopedId),
- get_IR_VSN(G, N, X)])),
- ic_pragma:mk_alias(G,EXC_ID,ScopedId),
- EXC_ID
- end;
- PI ->
- ic_pragma:mk_alias(G,PI,ScopedId),
- PI
- end;
- Alias ->
- Alias
- end.
-
-
-
-
-
-%% unreg_gen/1 uses the information stored in pragma table
-%% to decide which modules are to be unregistered
-unreg_gen(G, N, X) ->
- Light = ic_options:get_opt(G, light_ifr),
- case ic_genobj:is_stubfile_open(G) of
- true when Light == false ->
- Var = ?IFRID(G),
- Fd = ic_genobj:stubfiled(G),
- nl(Fd), nl(Fd), nl(Fd),
- emit(Fd, "~p() ->\n", [to_atom(unregister_name(G))]),
- emit(Fd, " ~s = ~p:find_repository(),\n",
- [Var, ?IFRMOD]),
- nl(Fd),
-
- unreg2(G, N, X),
- emit(Fd, " ok.\n\n"),
- destroy(Fd);
- true ->
- Fd = ic_genobj:stubfiled(G),
- nl(Fd), nl(Fd),
- Unregname = to_atom(unregister_name(G)),
- emit(Fd, "~p() ->\n\t~p([]).\n\n~p(OE_Options) ->\n",
- [Unregname, Unregname, Unregname]),
- emit(Fd, "\t~p:remove(?MODULE, OE_Options),\n\tok.\n\n", [?IFRMOD]);
- false -> ok
- end.
-
-
-destroy(Fd) ->
-emit(Fd,"
-oe_destroy_if_empty(OE_IFR,IFR_ID) ->
- case orber_ifr:'Repository_lookup_id'(OE_IFR, IFR_ID) of
- [] ->
- ok;
- Ref ->
- case orber_ifr:contents(Ref, \'dk_All\', \'true\') of
- [] ->
- orber_ifr:destroy(Ref),
- ok;
- _ ->
- ok
- end
- end.
-
-oe_destroy(OE_IFR,IFR_ID) ->
- case orber_ifr:'Repository_lookup_id'(OE_IFR, IFR_ID) of
- [] ->
- ok;
- Ref ->
- orber_ifr:destroy(Ref),
- ok
- end.
-
-",[]).
-
-
-
-
-
-
-
-
-
-
-%% unreg2 is top level registration
-
-unreg2(G, N, X) ->
- emit(ic_genobj:stubfiled(G),"~s",[lists:flatten(unreg3(G, N, X))]).
-
-unreg3(G, N, X) when is_list(X) ->
- unreg3_list(G, N, X, []);
-
-unreg3(G, N, X) when is_record(X, module) ->
- unreg3_list(G, [get_id2(X) | N], get_body(X), [unreg_collect(G, N, X)]);
-
-unreg3(G, N, X) when is_record(X, const) ->
- unreg_collect(G, N, X);
-
-unreg3(G, N, X) when is_record(X, struct) ->
- unreg_collect(G, N, X);
-
-unreg3(G, N, X) when is_record(X, except) ->
- unreg_collect(G, N, X);
-
-unreg3(G, N, X) when is_record(X, union) ->
- unreg_collect(G, N, X);
-
-unreg3(G, N, X) when is_record(X, enum) ->
- unreg_collect(G, N, X);
-
-unreg3(G, N, X) when is_record(X, typedef) ->
- unreg_collect(G, N, X);
-
-unreg3(G, N, X) when is_record(X, interface) ->
- unreg_collect(G, N, X);
-
-unreg3(_G, _N, X) when is_record(X, op) -> [];
-
-unreg3(_G, _N, X) when is_record(X, attr) -> [];
-
-unreg3(_G, _N, X) when is_record(X, preproc) -> [];
-
-unreg3(_G, _N, X) when is_record(X, pragma) -> [];
-
-unreg3(_G, _N, _X) -> [].
-
-
-unreg3_list(_G, _N, [], Found) ->
- Found;
-unreg3_list(G, N, List, Found) ->
- CurrentFileName = ic_genobj:idlfile(G),
- unreg3_list(G, N, {CurrentFileName,true}, List, Found).
-
-%% The filter function + loop
-unreg3_list(_G, _N, {_CFN, _Status}, [], Found) ->
- Found;
-unreg3_list(G, N, {CFN,Status}, [X | Xs], Found) ->
- case Status of
- true ->
- case X of
- {preproc,_,{_,_,_FileName},[{_,_,"1"}]} ->
- unreg3_list(G, N, {CFN,false}, Xs, Found);
- _ ->
- unreg3_list(G, N, {CFN,Status}, Xs, [unreg3(G, N, X) | Found])
- end;
- false ->
- case X of
- {preproc,_,{_,_,CFN},[{_,_,"2"}]} ->
- unreg3_list(G, N, {CFN,true}, Xs,[unreg3(G, N, X) | Found]);
- _ ->
- unreg3_list(G, N, {CFN,Status}, Xs, Found)
- end
- end.
-
-
-
-unreg_collect(G, N, X) when is_record(X, module) ->
- io_lib:format(" oe_destroy_if_empty(OE_IFR, ~p),\n",
- [get_IR_ID(G, N, X)]);
-unreg_collect(G, N, X) when is_record(X, typedef) ->
- lists:map(fun(Id) ->
- io_lib:format(" oe_destroy(OE_IFR, ~p),\n",
- [get_IR_ID(G, N, Id)])
- end,
- ic_forms:get_idlist(X));
-unreg_collect(G, N, X) ->
- io_lib:format(" oe_destroy(OE_IFR, ~p),\n",
- [get_IR_ID(G, N, X)]).
-
-
-
diff --git a/lib/ic/src/ictype.erl b/lib/ic/src/ictype.erl
deleted file mode 100644
index eb6f2088d7..0000000000
--- a/lib/ic/src/ictype.erl
+++ /dev/null
@@ -1,1417 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(ictype).
-
-
--include("ic.hrl").
--include("icforms.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([type_check/2, scoped_lookup/4, maybe_array/5, to_uppercase/1]).
-
--export([name2type/2, member2type/3, isBasicTypeOrEterm/3, isEterm/3]).
--export([isBasicType/1, isBasicType/2, isBasicType/3, isString/3, isWString/3,
- isArray/3, isStruct/3, isUnion/3, isEnum/3, isSequence/3, isBoolean/3 ]).
--export([fetchTk/3, fetchType/1, tk/4]).
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
-%%-define(DBG(F,A), io:format(F,A)).
--define(DBG(F,A), true).
--define(STDDBG, ?DBG(" dbg: ~p: ~p~n", [element(1,X), ic_forms:get_id2(X)])).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-
-type_check(G, Forms) ->
- S = ic_genobj:tktab(G),
- check_list(G, S, [], Forms).
-
-scoped_lookup(G, S, N, X) ->
- Id = ic_symtab:scoped_id_strip(X),
- case ic_symtab:scoped_id_is_global(X) of
- true ->
- lookup(G, S, [], X, Id);
- false ->
- lookup(G, S, N, X, Id)
- end.
-
-
-%%--------------------------------------------------------------------
-%% maybe_array
-%%
-%% Array declarators are indicated on the declarator and not on
-%% the type, therefore the declarator decides if the array type
-%% kind is added or not.
-%%
-maybe_array(G, S, N, X, TK) when is_record(X, array) ->
- mk_array(G, S, N, X#array.size, TK);
-maybe_array(_G, _S, _N, _, TK) -> TK.
-
-
-
-name2type(G, Name) ->
- S = ic_genobj:tktab(G),
- ScopedName = lists:reverse(string:tokens(Name, "_")),
- InfoList = ets:lookup(S, ScopedName ),
- filter( InfoList ).
-
-
-%% This is en overloaded function,
-%% differs in input on unions
-member2type(_G, X, I) when is_record(X, union)->
- Name = ic_forms:get_id2(I),
- case lists:keysearch(Name,2,element(6,X#union.tk)) of
- false ->
- error;
- {value,Rec} ->
- fetchType(element(3,Rec))
- end;
-member2type( G, SName, MName ) ->
-
- S = ic_genobj:tktab( G ),
- SNList = lists:reverse(string:tokens(SName,"_")),
- ScopedName = [MName | SNList],
- InfoList = ets:lookup( S, ScopedName ),
-
- case filter( InfoList ) of
- error ->
- %% Try a little harder, seeking inside tktab
- case lookup_member_type_in_tktab(S, ScopedName, MName) of
- error ->
- %% Check if this is the "return to return1" case
- case MName of
- "return1" ->
- %% Do it all over again !
- ScopedName2 = ["return" | SNList],
- InfoList2 = ets:lookup( S, ScopedName2 ),
- case filter( InfoList2 ) of
- error ->
- %% Last resort: seek in pragma table
- lookup_type_in_pragmatab(G, SName);
-
- Other ->
- Other
- end;
- _ ->
- %% Last resort: seek in pragma table
- lookup_type_in_pragmatab(G, SName)
- end;
- Other ->
- Other
- end;
- Other ->
- Other
- end.
-
-
-lookup_member_type_in_tktab(S, ScopedName, MName) ->
- case ets:match_object(S, {'_',member,{MName,'_'},nil}) of
- [] ->
- error;
- [{_FullScopedName,member,{MName,TKInfo},nil}]->
- fetchType( TKInfo );
- List ->
- lookup_member_type_in_tktab(List,ScopedName)
- end.
-
-lookup_member_type_in_tktab([], _ScopedName) ->
- error;
-lookup_member_type_in_tktab([{FullScopedName,_,{_,TKInfo},_}|Rest],ScopedName) ->
- case lists:reverse(string:tokens(ic_util:to_undersc(FullScopedName),"_")) of
- ScopedName ->
- fetchType(TKInfo);
- _ ->
- lookup_member_type_in_tktab(Rest,ScopedName)
- end.
-
-
-lookup_type_in_pragmatab(G, SName) ->
- S = ic_genobj:pragmatab(G),
-
- %% Look locally first
- case ets:match(S,{file_data_local,'_','_','$2','_','_',SName,'_','_'}) of
- [] ->
- %% No match, seek included
- case ets:match(S,{file_data_included,'_','_','$2','_','_',SName,'_','_'}) of
-
- [] ->
- error;
- [[Type]] ->
- io:format("1 Found(~p) : ~p~n",[SName,Type]),
- Type
- end;
-
- [[Type]] ->
- io:format("2 Found(~p) : ~p~n",[SName,Type]),
- Type
- end.
-
-
-
-
-isString(G, N, T) when element(1, T) == scoped_id ->
- case ic_symtab:get_full_scoped_name(G, N, T) of
- {_FullScopedName, _, {'tk_string',_}, _} ->
- true;
- _ ->
- false
- end;
-isString(_G, _N, T) when is_record(T, string) ->
- true;
-isString(_G, _N, _Other) ->
- false.
-
-
-isWString(G, N, T) when element(1, T) == scoped_id -> %% WSTRING
- case ic_symtab:get_full_scoped_name(G, N, T) of
- {_FullScopedName, _, {'tk_wstring',_}, _} ->
- true;
- _ ->
- false
- end;
-isWString(_G, _N, T) when is_record(T, wstring) ->
- true;
-isWString(_G, _N, _Other) ->
- false.
-
-
-isArray(G, N, T) when element(1, T) == scoped_id ->
- case ic_symtab:get_full_scoped_name(G, N, T) of
- {_FullScopedName, _, {'tk_array', _, _}, _} ->
- true;
- _ ->
- false
- end;
-isArray(_G, _N, T) when is_record(T, array) ->
- true;
-isArray(_G, _N, _Other) ->
- false.
-
-
-isSequence(G, N, T) when element(1, T) == scoped_id ->
- case ic_symtab:get_full_scoped_name(G, N, T) of
- {_FullScopedName, _, {'tk_sequence', _, _}, _} ->
- true;
- _ ->
- false
- end;
-isSequence(_G, _N, T) when is_record(T, sequence) ->
- true;
-isSequence(_G, _N, _Other) ->
- false.
-
-
-isStruct(G, N, T) when element(1, T) == scoped_id ->
- case ic_symtab:get_full_scoped_name(G, N, T) of
- {_FullScopedName, _, {'tk_struct', _, _, _}, _} ->
- true;
- _ ->
- false
- end;
-isStruct(_G, _N, T) when is_record(T, struct) ->
- true;
-isStruct(_G, _N, _Other) ->
- false.
-
-
-isUnion(G, N, T) when element(1, T) == scoped_id ->
- case ic_symtab:get_full_scoped_name(G, N, T) of
- {_FullScopedName, _, {'tk_union', _, _, _,_,_}, _} ->
- true;
- _Other ->
- false
- end;
-isUnion(_G, _N, T) when is_record(T, union) ->
- true;
-isUnion(_G, _N, _Other) ->
- false.
-
-
-
-isEnum(G, N, T) when element(1, T) == scoped_id ->
- case ic_symtab:get_full_scoped_name(G, N, T) of
- {_FullScopedName, _, {'tk_enum',_,_,_}, _} ->
- true;
- _Other ->
- false
- end;
-isEnum(_G, _N, T) when is_record(T, enum) ->
- true;
-isEnum(_G, _N, _Other) ->
- false.
-
-
-
-isBoolean(G, N, T) when element(1, T) == scoped_id ->
- {_, _, TK, _} =
- ic_symtab:get_full_scoped_name(G, N, T),
- case fetchType(TK) of
- 'boolean' ->
- true;
- _ ->
- false
- end;
-isBoolean(_, _, {'tk_boolean',_}) ->
- true;
-isBoolean(_, _, {'boolean',_}) ->
- true;
-isBoolean(_, _, _) ->
- false.
-
-
-%%% Just used for C
-
-isBasicTypeOrEterm(G, N, S) ->
- case isBasicType(G, N, S) of
- true ->
- true;
- false ->
- isEterm(G, N, S)
- end.
-
-isEterm(G, N, S) when element(1, S) == scoped_id ->
- {FullScopedName, _, _TK, _} = ic_symtab:get_full_scoped_name(G, N, S),
- case ic_code:get_basetype(G, ic_util:to_undersc(FullScopedName)) of
- "erlang_term" ->
- true;
- "ETERM*" ->
- true;
- _X ->
- false
- end;
-isEterm(_G, _Ni, _X) ->
- false.
-
-isBasicType(_G, _N, {scoped_id,_,_,["term","erlang"]}) ->
- false;
-isBasicType(G, N, S) when element(1, S) == scoped_id ->
- {_, _, TK, _} = ic_symtab:get_full_scoped_name(G, N, S),
- isBasicType(fetchType(TK));
-isBasicType(_G, _N, {string, _} ) ->
- false;
-isBasicType(_G, _N, {wstring, _} ) -> %% WSTRING
- false;
-isBasicType(_G, _N, {unsigned, {long, _}} ) ->
- true;
-isBasicType(_G, _N, {unsigned, {short, _}} ) ->
- true;
-isBasicType(_G, _N, {Type, _} ) ->
- isBasicType(Type);
-isBasicType(_G, _N, _X) ->
- false.
-
-
-isBasicType( G, Name ) ->
- isBasicType( name2type( G, Name ) ).
-
-
-isBasicType( Type ) ->
- lists:member(Type,
- [tk_short,short,
- tk_long,long,
- tk_longlong,longlong, %% LLONG
- tk_ushort,ushort,
- tk_ulong,ulong,
- tk_ulonglong,ulonglong, %% ULLONG
- tk_float,float,
- tk_double,double,
- tk_boolean,boolean,
- tk_char,char,
- tk_wchar,wchar, %% WCHAR
- tk_octet,octet,
- tk_any,any]). %% Fix for any
-
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-check(G, _S, N, X) when is_record(X, preproc) ->
- handle_preproc(G, N, X#preproc.cat, X),
- X;
-
-check(G, S, N, X) when is_record(X, op) ->
- ?STDDBG,
- TK = tk_base(G, S, N, ic_forms:get_type(X)),
- tktab_add(G, S, N, X),
- N2 = [ic_forms:get_id2(X) | N],
- Ps = lists:map(fun(P) ->
- tktab_add(G, S, N2, P),
- P#param{tk=tk_base(G, S, N, ic_forms:get_type(P))} end,
- X#op.params),
- %% Check for exception defs.
- Raises = lists:map(fun(E) -> name_lookup(G, S, N, E) end,
- X#op.raises),
- case ic_forms:is_oneway(X) of
- true ->
- if TK /= tk_void ->
- ic_error:error(G, {bad_oneway_type, X, TK});
- true -> ok
- end,
- case ic:filter_params([inout, out], X#op.params) of
- [] -> ok; % No out parameters!
- _ ->
- ic_error:error(G, {oneway_outparams, X})
- end,
- case X#op.raises of
- [] -> ok;
- _ ->
- ic_error:error(G, {oneway_raises, X})
- end;
- false ->
- ok
- end,
- X#op{params=Ps, tk=TK, raises=Raises};
-
-check(G, S, N, X) when is_record(X, interface) ->
- ?STDDBG,
- N2 = [ic_forms:get_id2(X) | N],
- TK = {tk_objref, ictk:get_IR_ID(G, N, X), ic_forms:get_id2(X)},
- Inherit = inherit_resolve(G, S, N, X#interface.inherit, []),
- tktab_add(G, S, N, X, TK, Inherit),
- CheckedBody = check_list(G, S, N2, ic_forms:get_body(X)),
- InhBody = calc_inherit_body(G, N2, CheckedBody, Inherit, []),
- X2 = X#interface{inherit=Inherit, tk=TK, body=CheckedBody,
- inherit_body=InhBody},
- ic_symtab:store(G, N, X2),
- X2;
-
-check(G, S, N, X) when is_record(X, forward) ->
- ?STDDBG,
- tktab_add(G, S, N, X, {tk_objref, ictk:get_IR_ID(G, N, X), ic_forms:get_id2(X)}),
- X;
-
-check(G, S, N, #constr_forward{tk = tk_struct} = X) ->
- ?STDDBG,
- ID = ic_forms:get_id2(X),
- Module = list_to_atom(string:join(lists:reverse([ID|N]), "_")),
- tktab_add(G, S, N, X, {tk_struct, ictk:get_IR_ID(G, N, X), ID, Module}),
- X;
-check(G, S, N, #constr_forward{tk = tk_union} = X) ->
- ?STDDBG,
- ID = ic_forms:get_id2(X),
- Module = list_to_atom(string:join(lists:reverse([ID|N]), "_")),
- tktab_add(G, S, N, X, {tk_union, ictk:get_IR_ID(G, N, X), ID, [], [], Module}),
- X;
-
-check(G, S, N, X) when is_record(X, const) ->
- ?STDDBG,
- case tk_base(G, S, N, ic_forms:get_type(X)) of
- Err when element(1, Err) == error -> X;
- TK ->
- check_const_tk(G, S, N, X, TK),
- case iceval:eval_const(G, S, N, TK, X#const.val) of
- Err when element(1, Err) == error -> X;
- {ok, NewTK, Val} ->
- V = iceval:get_val(Val),
- tktab_add(G, S, N, X, NewTK, V),
- X#const{val=V, tk=NewTK};
- Val ->
- V = iceval:get_val(Val),
- tktab_add(G, S, N, X, TK, V),
- X#const{val=V, tk=TK}
- end
- end;
-
-check(G, S, N, X) when is_record(X, except) ->
- ?STDDBG,
- TK = tk(G, S, N, X),
- X#except{tk=TK};
-
-check(G, S, N, X) when is_record(X, struct) ->
- ?STDDBG,
- TK = tk(G, S, N, X),
- X#struct{tk=TK};
-
-check(G, S, N, X) when is_record(X, enum) ->
- ?STDDBG,
- TK = tk(G, S, N, X),
- X#enum{tk=TK};
-
-check(G, S, N, X) when is_record(X, union) ->
- ?STDDBG,
- TK = tk(G, S, N, X),
- X#union{tk=TK};
-
-check(G, S, N, X) when is_record(X, attr) ->
- ?STDDBG,
- TK = tk_base(G, S, N, ic_forms:get_type(X)),
- XX = #id_of{type=X},
- lists:foreach(fun(Id) -> tktab_add(G, S, N, XX#id_of{id=Id}) end,
- ic_forms:get_idlist(X)),
- X#attr{tk=TK};
-
-check(G, S, N, X) when is_record(X, module) ->
- ?STDDBG,
- tktab_add(G, S, N, X),
- X#module{body=check_list(G, S, [ic_forms:get_id2(X) | N], ic_forms:get_body(X))};
-
-check(G, S, N, X) when is_record(X, typedef) ->
- ?STDDBG,
- TKbase = tk(G, S, N, X),
- X#typedef{tk=TKbase};
-
-check(_G, _S, _N, X) ->
- ?DBG(" dbg: ~p~n", [element(1,X)]),
- X.
-
-handle_preproc(G, _N, line_nr, X) -> ic_genobj:set_idlfile(G, ic_forms:get_id2(X));
-handle_preproc(_G, _N, _C, _X) -> ok.
-
-
-%%--------------------------------------------------------------------
-%%
-%% TK calculation
-%%
-%%--------------------------------------------------------------------
-
-tk(G, S, N, X) when is_record(X, union) ->
- N2 = [ic_forms:get_id2(X) | N],
- DisrcTK = tk(G, S, N, ic_forms:get_type(X)),
- case check_switch_tk(G, S, N, X, DisrcTK) of
- true ->
- do_special_enum(G, S, N2, ic_forms:get_type(X)),
- BodyTK = lists:reverse(
- tk_caselist(G, S, N2, DisrcTK, ic_forms:get_body(X))),
- tktab_add(G, S, N, X,
- {tk_union, ictk:get_IR_ID(G, N, X), ic_forms:get_id2(X),
- DisrcTK, default_count(ic_forms:get_body(X)), BodyTK});
- false ->
- tk_void
- end;
-
-tk(G, S, N, X) when is_record(X, enum) ->
- N2 = [ic_forms:get_id2(X) | N],
- tktab_add(G, S, N, X,
- {tk_enum, ictk:get_IR_ID(G, N, X), ic_forms:get_id2(X),
- enum_body(G, S, N2, ic_forms:get_body(X))});
-
-
-%% Note that the TK returned from this function is the base TK. It
-%% must be modified for each of the identifiers in the idlist (for
-%% array reasons).
-tk(G, S, N, X) when is_record(X, typedef) ->
- case X of
- %% Special case only for term and java backend !
- {typedef,{any,_},[{'<identifier>',_,"term"}],undefined} ->
- case ic_options:get_opt(G, be) of
- java ->
- tktab_add(G, S, N, X, tk_term),
- tk_term;
- _ ->
- TK = tk(G, S, N, ic_forms:get_body(X)),
- lists:foreach(fun(Id) ->
- tktab_add(G, S, N, #id_of{id=Id, type=X},
- maybe_array(G, S, N, Id, TK))
- end,
- X#typedef.id),
- TK
- end;
- _ ->
- TK = tk(G, S, N, ic_forms:get_body(X)),
- lists:foreach(fun(Id) ->
- tktab_add(G, S, N, #id_of{id=Id, type=X},
- maybe_array(G, S, N, Id, TK))
- end,
- X#typedef.id),
- TK
- end;
-
-tk(G, S, N, X) when is_record(X, struct) ->
- N2 = [ic_forms:get_id2(X) | N],
- tktab_add(G, S, N, X, {tk_struct, ictk:get_IR_ID(G, N, X), ic_forms:get_id2(X),
- tk_memberlist(G, S, N2, ic_forms:get_body(X))});
-
-tk(G, S, N, X) when is_record(X, except) ->
- N2 = [ic_forms:get_id2(X) | N],
- tktab_add(G, S, N, X, {tk_except, ictk:get_IR_ID(G, N, X), ic_forms:get_id2(X),
- tk_memberlist(G, S, N2, ic_forms:get_body(X))});
-
-tk(G, S, N, X) -> tk_base(G, S, N, X).
-
-
-tk_base(G, S, N, X) when is_record(X, sequence) ->
- {tk_sequence, tk(G, S, N, X#sequence.type),
- len_eval(G, S, N, X#sequence.length)};
-
-tk_base(G, S, N, X) when is_record(X, string) ->
- {tk_string, len_eval(G, S, N, X#string.length)};
-
-tk_base(G, S, N, X) when is_record(X, wstring) -> %% WSTRING
- {tk_wstring, len_eval(G, S, N, X#wstring.length)};
-
-%% Fixed constants can be declared as:
-%% (1) const fixed pi = 3.14D; or
-%% (2) typedef fixed<3,2> f32;
-%% const f32 pi = 3.14D;
-tk_base(G, S, N, X) when is_record(X, fixed) ->
- %% Case 2
- {tk_fixed, len_eval(G, S, N, X#fixed.digits), len_eval(G, S, N, X#fixed.scale)};
-tk_base(_G, _S, _N, {fixed, _}) ->
- %% Case 1
- tk_fixed;
-
-
-%% Special case, here CORBA::TypeCode is built in
-%% ONLY when erl_corba is the backend of choice
-tk_base(G, S, N, {scoped_id,V1,V2,["TypeCode","CORBA"]}) ->
- case ic_options:get_opt(G, be) of
- false ->
- tk_TypeCode;
- erl_corba ->
- tk_TypeCode;
- erl_template ->
- tk_TypeCode;
- _ ->
- case scoped_lookup(G, S, N, {scoped_id,V1,V2,["TypeCode","CORBA"]}) of
- T when element(1, T) == error -> T;
- T when is_tuple(T) -> element(3, T)
- end
- end;
-
-tk_base(G, S, N, X) when element(1, X) == scoped_id ->
- case scoped_lookup(G, S, N, X) of
- T when element(1, T) == error -> T;
- T when is_tuple(T) -> element(3, T)
- end;
-tk_base(_G, _S, _N, {long, _}) -> tk_long;
-tk_base(_G, _S, _N, {'long long', _}) -> tk_longlong; %% LLONG
-tk_base(_G, _S, _N, {short, _}) -> tk_short;
-tk_base(_G, _S, _N, {'unsigned', {short, _}}) -> tk_ushort;
-tk_base(_G, _S, _N, {'unsigned', {long, _}}) -> tk_ulong;
-tk_base(_G, _S, _N, {'unsigned', {'long long', _}})-> tk_ulonglong; %% ULLONG
-tk_base(_G, _S, _N, {float, _}) -> tk_float;
-tk_base(_G, _S, _N, {double, _}) -> tk_double;
-tk_base(_G, _S, _N, {boolean, _}) -> tk_boolean;
-tk_base(_G, _S, _N, {char, _}) -> tk_char;
-tk_base(_G, _S, _N, {wchar, _}) -> tk_wchar; %% WCHAR
-tk_base(_G, _S, _N, {octet, _}) -> tk_octet;
-tk_base(_G, _S, _N, {null, _}) -> tk_null;
-tk_base(_G, _S, _N, {void, _}) -> tk_void;
-tk_base(_G, _S, _N, {any, _}) -> tk_any;
-tk_base(_G, _S, _N, {'Object', _}) -> {tk_objref, "", "Object"}.
-
-
-%%--------------------------------------------------------------------
-%%
-%% Special handling of idlists. Note that the recursion case is given
-%% as accumulator to foldr. Idlists are those lists of identifiers
-%% that share the same definition, i.e. multiple cases, multiple type
-%% declarations, multiple member names.
-%%
-tk_memberlist(G, S, N, [X | Xs]) ->
- BaseTK = tk(G, S, N, ic_forms:get_type(X)),
-
- XX = #id_of{type=X},
- lists:foldr(fun(Id, Acc) ->
- [tk_member(G, S, N, XX#id_of{id=Id}, BaseTK) | Acc] end,
- tk_memberlist(G, S, N, Xs),
- ic_forms:get_idlist(X));
-tk_memberlist(_G, _S, _N, []) -> [].
-
-%% same as above but for case dcls
-tk_caselist(G, S, N, DiscrTK, Xs) ->
- lists:foldl(fun(Case, Acc) ->
- BaseTK = tk(G, S, N, ic_forms:get_type(Case)),
- %% tktab_add for the uniqueness check of the declarator
- tktab_add(G, S, N, Case),
- lists:foldl(fun(Id, Acc2) ->
- case tk_case(G, S, N, Case, BaseTK,
- DiscrTK, Id) of
- Err when element(1, Err)==error ->
- Acc2;
- TK ->
- unique_add_case_label(G, S, N, Id,
- TK, Acc2)
- end
- end,
- Acc,
- ic_forms:get_idlist(Case))
- end,
- [],
- Xs).
-
-
-%% Handling of the things that can be in an idlist or caselist
-tk_member(G, S, N, X, BaseTK) ->
- tktab_add(G, S, N, X,
- {ic_forms:get_id2(X), maybe_array(G, S, N, X#id_of.id, BaseTK)}).
-
-
-get_case_id_and_check(G, _S, _N, _X, ScopedId) ->
- case ic_symtab:scoped_id_is_global(ScopedId) of
- true -> ic_error:error(G, {bad_scope_enum_case, ScopedId});
- false -> ok
- end,
- case ic_symtab:scoped_id_strip(ScopedId) of
- [Id] -> Id;
- _List ->
- ic_error:error(G, {bad_scope_enum_case, ScopedId}),
- ""
- end.
-
-
-tk_case(G, S, N, X, BaseTK, DiscrTK, Id) ->
- case case_eval(G, S, N, DiscrTK, Id) of
- Err when element(1, Err) == error -> Err;
- Val ->
- case iceval:check_tk(G, DiscrTK, Val) of
- true ->
- {iceval:get_val(Val), ic_forms:get_id2(X),
- maybe_array(G, S, N, X#case_dcl.id, BaseTK)};
- false ->
- ic_error:error(G, {bad_case_type, DiscrTK, X,
- iceval:get_val(Val)})
- end
- end.
-
-tktab_add(G, S, N, X) ->
- tktab_add_id(G, S, N, X, ic_forms:get_id2(X), nil, nil).
-tktab_add(G, S, N, X, TK) ->
- tktab_add_id(G, S, N, X, ic_forms:get_id2(X), TK, nil).
-tktab_add(G, S, N, X, TK, Aux) ->
- tktab_add_id(G, S, N, X, ic_forms:get_id2(X), TK, Aux).
-
-
-tktab_add_id(G, S, N, X, Id, TK, Aux) when is_record(X,enumerator) ->
-
- %% Check if the "scl" flag is set to true
- %% if so, allow old semantics ( errornous )
- %% Warning, this is for compatibility reasons only.
- Name = case ic_options:get_opt(G, scl) of
- true ->
- [Id | N];
- false ->
- [Id | tl(N)]
- end,
-
- UName = mk_uppercase(Name),
- case ets:lookup(S, Name) of
- [_] -> ic_error:error(G, {multiply_defined, X});
- [] ->
- case ets:lookup(S, UName) of
- [] -> ok;
- [_] -> ic_error:error(G, {illegal_spelling, X})
- end
- end,
- ets:insert(S, {Name, element(1, get_beef(X)), TK, Aux}),
- if UName =/= Name -> ets:insert(S, {UName, spellcheck});
- true -> true end,
- TK;
-%%
-%% Fixes the multiple file module definition check
-%% but ONLY for Corba backend
-%%
-tktab_add_id(G, S, N, X, Id, TK, Aux) when is_record(X,module) ->
- case ic_options:get_opt(G, be) of
- erl_template ->
- Name = [Id | N],
- UName = mk_uppercase(Name),
- ets:insert(S, {Name, element(1, get_beef(X)), TK, Aux}),
- if UName =/= Name -> ets:insert(S, {UName, spellcheck});
- true -> true end,
- TK;
- erl_corba ->
- Name = [Id | N],
- UName = mk_uppercase(Name),
- ets:insert(S, {Name, element(1, get_beef(X)), TK, Aux}),
- if UName =/= Name -> ets:insert(S, {UName, spellcheck});
- true -> true end,
- TK;
- false -> %% default == erl_corba
- Name = [Id | N],
- UName = mk_uppercase(Name),
- ets:insert(S, {Name, element(1, get_beef(X)), TK, Aux}),
- if UName =/= Name -> ets:insert(S, {UName, spellcheck});
- true -> true end,
- TK;
- java ->
- Name = [Id | N],
- UName = mk_uppercase(Name),
- ets:insert(S, {Name, element(1, get_beef(X)), TK, Aux}),
- if UName =/= Name -> ets:insert(S, {UName, spellcheck});
- true -> true end,
- TK;
- erl_genserv ->
- Name = [Id | N],
- UName = mk_uppercase(Name),
- ets:insert(S, {Name, element(1, get_beef(X)), TK, Aux}),
- if UName =/= Name -> ets:insert(S, {UName, spellcheck});
- true -> true end,
- TK;
- erl_plain ->
- Name = [Id | N],
- UName = mk_uppercase(Name),
- ets:insert(S, {Name, element(1, get_beef(X)), TK, Aux}),
- if UName =/= Name -> ets:insert(S, {UName, spellcheck});
- true -> true end,
- TK;
- _Be ->
- Name = [Id | N],
- UName = mk_uppercase(Name),
- case ets:lookup(S, Name) of
- [_] -> ic_error:error(G, {multiply_defined, X});
- [] ->
- case ets:lookup(S, UName) of
- [] -> ok;
- [_] -> ic_error:error(G, {illegal_spelling, X})
- end
- end,
- ets:insert(S, {Name, element(1, get_beef(X)), TK, Aux}),
- if UName =/= Name -> ets:insert(S, {UName, spellcheck});
- true -> true end,
- TK
- end;
-tktab_add_id(G, S, N, X, Id, TK, Aux) ->
- Name = [Id | N],
- UName = mk_uppercase(Name),
- case ets:lookup(S, Name) of
- [{_, forward, _, _}] when is_record(X, interface) ->
- ok;
- [{_, constr_forward, _, _}] when is_record(X, union) orelse
- is_record(X, struct) ->
- ok;
- [XX] when is_record(X, forward) andalso element(2, XX)==interface ->
- ok;
- [_] ->
- ic_error:error(G, {multiply_defined, X});
- [] ->
- case ets:lookup(S, UName) of
- [] -> ok;
- [_] -> ic_error:error(G, {illegal_spelling, X})
- end
- end,
- ets:insert(S, {Name, element(1, get_beef(X)), TK, Aux}),
- if UName =/= Name -> ets:insert(S, {UName, spellcheck});
- true -> true end,
- TK.
-
-
-
-
-%%--------------------------------------------------------------------
-%% enum_body
-%%
-%% Special because ids are treated different than usual.
-%%
-enum_body(G, S, N, [Enum | EnumList]) ->
- tktab_add(G, S, N, Enum), %%%, enum_val, Enum),
- %% tktab_add(G, S, N, X, TK, V),
- [ic_forms:get_id2(Enum) | enum_body(G, S, N, EnumList)];
-enum_body(_G, _S, _N, []) -> [].
-
-
-%%--------------------------------------------------------------------
-%% mk_array
-%%
-%% Multi dimensional arrays are written as nested tk_array
-%%
-mk_array(G, S, N, [Sz | Szs], TK) ->
- case iceval:eval_const(G, S, N, positive_int, Sz) of
- Err when element(1, Err) == error -> TK;
- Val ->
- {tk_array, mk_array(G, S, N, Szs, TK), iceval:get_val(Val)}
- end;
-mk_array(_G, _S, _N, [], TK) -> TK.
-
-
-%%--------------------------------------------------------------------
-%% len_eval
-%%
-%% Evaluates the length, which in case it has been left out is a
-%% plain 0 (zero)
-%%
-len_eval(_G, _S, _N, 0) -> 0;
-len_eval(G, S, N, X) -> %%iceval:eval_const(G, S, N, positive_int, X).
- case iceval:eval_const(G, S, N, positive_int, X) of
- Err when element(1, Err) == error -> 0;
- Val -> iceval:get_val(Val)
- end.
-
-
-%%--------------------------------------------------------------------
-%% case_eval
-%%
-%% Evaluates the case label.
-%%
-
-case_eval(G, S, N, DiscrTK, X) when element(1, DiscrTK) == tk_enum,
- element(1, X) == scoped_id ->
- {tk_enum, _, _, Cases} = DiscrTK,
- Id = get_case_id_and_check(G, S, N, X, X),
- %%io:format("Matching: ~p to ~p~n", [Id, Cases]),
- case lists:member(Id, Cases) of
- true ->
- {enum_id, Id};
- false ->
- iceval:mk_val(scoped_lookup(G, S, N, X)) % Will generate error
- end;
-
-case_eval(G, S, N, DiscrTK, X) ->
- iceval:eval_e(G, S, N, DiscrTK, X).
-
-
-%% The enum declarator is in the union scope.
-do_special_enum(G, S, N, X) when is_record(X, enum) ->
- tktab_add(G, S, N, #id_of{id=X#enum.id, type=X});
-do_special_enum(_G, _S, _N, _X) ->
- ok.
-
-
-unique_add_case_label(G, _S, _N, Id, TK, TKList) ->
-%%%io:format("check_case_labels: TK:~p TKLIST:~p ~n", [TK, TKList]),
- if element(1, TK) == error ->
- TKList;
- true ->
- case lists:keysearch(element(1, TK), 1, TKList) of
- {value, _} ->
- ic_error:error(G, {multiple_cases, Id}),
- TKList;
- false ->
- [TK | TKList]
- end
- end.
-
-
-%%--------------------------------------------------------------------
-%% default_count
-%%
-%% Returns the position of the default case.
-%%
-%% Modified for OTP-2007
-%%
-default_count(Xs) ->
- default_count2(Xs, 0).
-
-default_count2([X | Xs], N) -> default_count3(X#case_dcl.label, Xs, N);
-default_count2([], _) -> -1.
-
-default_count3([{default, _} | _Ys], _Xs, N) -> N;
-default_count3([_ | Ys], Xs, N) -> default_count3(Ys, Xs, N+1);
-default_count3([], Xs, N) -> default_count2(Xs, N).
-
-
-
-
-%%
-%% Type checks.
-%%
-%% Check constant type references (only for the scoped id case, others
-%% are caught by the BNF)
-%%
-check_const_tk(_G, _S, _N, _X, tk_long) -> true;
-check_const_tk(_G, _S, _N, _X, tk_longlong) -> true; %% LLONG
-check_const_tk(_G, _S, _N, _X, tk_short) -> true;
-check_const_tk(_G, _S, _N, _X, tk_ushort) -> true;
-check_const_tk(_G, _S, _N, _X, tk_ulong) -> true;
-check_const_tk(_G, _S, _N, _X, tk_ulonglong) -> true; %% ULLONG
-check_const_tk(_G, _S, _N, _X, tk_float) -> true;
-check_const_tk(_G, _S, _N, _X, tk_double) -> true;
-check_const_tk(_G, _S, _N, _X, tk_boolean) -> true;
-check_const_tk(_G, _S, _N, _X, tk_char) -> true;
-check_const_tk(_G, _S, _N, _X, tk_wchar) -> true; %% WCHAR
-check_const_tk(_G, _S, _N, _X, tk_octet) -> true;
-check_const_tk(_G, _S, _N, _X, {tk_string, _Len}) -> true;
-check_const_tk(_G, _S, _N, _X, {tk_wstring, _Len}) -> true; %% WSTRING
-check_const_tk(_G, _S, _N, _X, tk_fixed) -> true;
-check_const_tk(_G, _S, _N, _X, {tk_fixed, _Digits, _Scale}) -> true;
-check_const_tk(G, _S, _N, X, TK) -> ic_error:error(G, {illegal_const_t, X, TK}).
-
-
-check_switch_tk(_G, _S, _N, _X, tk_long) -> true;
-check_switch_tk(_G, _S, _N, _X, tk_longlong) -> true; %% LLONG
-check_switch_tk(_G, _S, _N, _X, tk_short) -> true;
-check_switch_tk(_G, _S, _N, _X, tk_ushort) -> true;
-check_switch_tk(_G, _S, _N, _X, tk_ulong) -> true;
-check_switch_tk(_G, _S, _N, _X, tk_ulonglong) -> true; %% ULLONG
-check_switch_tk(_G, _S, _N, _X, tk_boolean) -> true;
-check_switch_tk(_G, _S, _N, _X, tk_char) -> true;
-check_switch_tk(_G, _S, _N, _X, tk_wchar) -> true; %% WCHAR
-check_switch_tk(_G, _S, _N, _X, TK) when element(1, TK) == tk_enum -> true;
-check_switch_tk(G, _S, _N, X, TK) -> ic_error:error(G, {illegal_switch_t, X, TK}),
- false.
-
-
-
-%% Lookup a name
-name_lookup(G, S, N, X) ->
- case scoped_lookup(G, S, N, X) of
- T when is_tuple(T) -> element(1, T)
- end.
-
-
-lookup(G, S, N, X, Id) ->
- N2 = Id ++ N,
- ?DBG(" Trying ~p ...~n", [N2]),
- case ets:lookup(S, N2) of
- [] ->
- case look_for_interface(G, S, [hd(N2)], tl(N2)) of
-
- %% First attempt: filtering inherited members !
- [{_, member, _, _}] ->
- case look_for_interface(G, S, [hd(N)], tl(N2)) of
- [T] ->
- ?DBG(" -- found ~p~n", [T]),
- T;
- _ ->
- lookup(G, S, tl(N), X, Id)
- end;
- %%
-
- [T] ->
- ?DBG(" -- found ~p~n", [T]),
- T;
-
- _ ->
- if N == [] ->
- ic_error:error(G, {tk_not_found, X});
- true ->
- lookup(G, S, tl(N), X, Id)
- end
-
- end;
-
- %% Second attempt: filtering members !
- [{_, member, _, _}] ->
- case look_for_interface(G, S, [hd(N2)], tl(N2)) of
- [T] ->
- ?DBG(" -- found ~p~n", [T]),
- T;
- _ ->
- if N == [] ->
- ic_error:error(G, {tk_not_found, X});
- true ->
- lookup(G, S, tl(N), X, Id)
- end
- end;
- %%
- [T] ->
- ?DBG(" -- found ~p~n", [T]),
- T
- end.
-
-
-look_for_interface(_G, _S, _Hd, []) ->
- false;
-look_for_interface(G, S, Hd, Tl) ->
- case ets:lookup(S, Tl) of
- [{_, interface, _TK, Inh}] ->
- case look_in_inherit(G, S, Hd, Inh) of
- %% gather_inherit(G, S, Inh, [])) of
- [X] when is_tuple(X) ->
- [X];
- _ ->
- look_for_interface(G, S, Hd ++ [hd(Tl)], tl(Tl))
- end;
- _ ->
- look_for_interface(G, S, Hd ++ [hd(Tl)], tl(Tl))
- end.
-
-look_in_inherit(G, S, Id, [I | Is]) ->
- case ets:lookup(S, Id ++ I) of
- [X] when is_tuple(X) ->
- [X];
- [] ->
- look_in_inherit(G, S, Id, Is)
- end;
-look_in_inherit(_G, _S, _Id, []) ->
- false.
-
-
-%% L is a list of names
-mk_uppercase(L) ->
- lists:map(fun(Z) -> lists:map(fun(X) when X>=$a, X=<$z -> X-$a+$A;
- (X) -> X end, Z) end, L).
-
-
-%%--------------------------------------------------------------------
-%%
-%% Inheritance stuff
-%%
-%%
-%%--------------------------------------------------------------------
-
-%% InhBody is an accumulating parameter
-
-calc_inherit_body(G, N, OrigBody, [X|Xs], InhBody) ->
- case ic_symtab:retrieve(G, X) of
- Intf when is_record(Intf, interface) ->
- Body = filter_body(G, X, ic_forms:get_body(Intf), N, OrigBody, InhBody),
- calc_inherit_body(G, N, OrigBody, Xs, [{X, Body} | InhBody]);
- XXX ->
- io:format("Oops, not found ~p~n", [XXX]),
- calc_inherit_body(G, N, OrigBody, Xs, InhBody)
- end;
-calc_inherit_body(_G, _N, _OrigBody, [], InhBody) -> lists:reverse(InhBody).
-
-
-filter_body(G, XPath, [X | Xs], OrigPath, OrigBody, InhBody) ->
- case complex_body_member(G, XPath, X, OrigPath, OrigBody, InhBody) of
- true ->
- %%io:format("NOT adding ~p~n", [ic_forms:get_id2(X)]),
- filter_body(G, XPath, Xs, OrigPath, OrigBody, InhBody);
- {false, NewX} -> % For those with idlist
- %%io:format("Adding from idlist~n", []),
- [NewX | filter_body(G, XPath, Xs, OrigPath, OrigBody, InhBody)];
- false ->
- %%io:format("Adding: ~p~n", [ic_forms:get_id2(X)]),
- [X | filter_body(G, XPath, Xs, OrigPath, OrigBody, InhBody)]
- end;
-filter_body(_G, _XPath, [], _OrigPath, _OrigBody, _InhBody) -> [].
-
-
-complex_body_member(G, XPath, X, OrigPath, OrigBody, InhBody) ->
- case has_idlist(X) of
- true ->
- idlist_member(G, XPath, X, OrigPath, OrigBody, InhBody);
- false ->
- straight_member(G, XPath, X, OrigPath, OrigBody, InhBody)
- end.
-
-
-idlist_member(G, XPath, X, OrigPath, OrigBody, InhBody) ->
- XX = #id_of{type=X},
- F = fun(Id) ->
- not(straight_member(G, XPath, XX#id_of{id=Id}, OrigPath,
- OrigBody, InhBody))
- end,
- case lists:filter(F, ic_forms:get_idlist(X)) of
- [] ->
- true;
- IdList ->
-%%% io:format("Idlist added: ~p~n",[IdList]),
- {false, replace_idlist(X, IdList)}
- end.
-
-
-straight_member(G, XPath, X, OrigPath, OrigBody, InhBody) ->
- %%io:format("straight member: ~p~n", [ic_forms:get_id2(X)]),
- case body_member(G, XPath, X, OrigPath, OrigBody) of
- true ->
- true;
- false ->
- inh_body_member(G, XPath, X, InhBody)
- end.
-
-
-inh_body_member(G, XPath, X, [{Name, Body} | InhBody]) ->
- case body_member(G, XPath, X, Name, Body) of
- true ->
- true;
- false ->
- inh_body_member(G, XPath, X, InhBody)
- end;
-inh_body_member(_G, _XPath, _X, []) -> false.
-
-
-body_member(G, XPath, X, YPath, [Y|Ys]) ->
- case has_idlist(Y) of
- true ->
- YY = #id_of{type=Y},
- case list_and(fun(Y2) ->
- not(is_equal(G, XPath, X, YPath,
- YY#id_of{id=Y2})) end,
- ic_forms:get_idlist(Y)) of
- true ->
- body_member(G, XPath, X, YPath, Ys);
- false ->
- true
- end;
- false ->
- case is_equal(G, XPath, X, YPath, Y) of
- false ->
- body_member(G, XPath, X, YPath, Ys);
- true ->
- true
- end
- end;
-body_member(_G, _XPath, _X, _YPath, []) -> false.
-
-
-is_equal(G, XPath, X, YPath, Y) ->
- case {ic_forms:get_id2(X), ic_forms:get_id2(Y)} of
- {ID, ID} ->
- collision(G, XPath, X, YPath, Y),
- true;
- _ ->
- false
- end.
-
-
-%% X is the new item, Y is the old one. So it is X that collides with
-%% Y and Y shadows X.
-collision(G, XPath, X, YPath, Y) ->
- I1 = get_beef(X),
- % I2 = get_beef(Y),
- if is_record(I1, op) -> %%, record(I2, op) ->
- ic_error:error(G, {inherit_name_collision,
- {YPath, Y}, {XPath, X}});
- is_record(I1, attr) -> %%, record(I2, attr) ->
- ic_error:error(G, {inherit_name_collision,
- {YPath, Y}, {XPath, X}});
- true ->
- ?ifopt(G, warn_name_shadow,
- ic_error:warn(G, {inherit_name_shadow,
- {YPath, Y}, {XPath, X}}))
- end.
-
-has_idlist(X) when is_record(X, typedef) -> true;
-has_idlist(X) when is_record(X, member) -> true;
-has_idlist(X) when is_record(X, case_dcl) -> true;
-has_idlist(X) when is_record(X, attr) -> true;
-has_idlist(_) -> false.
-
-replace_idlist(X, IdList) when is_record(X, typedef) -> X#typedef{id=IdList};
-replace_idlist(X, IdList) when is_record(X, attr) -> X#attr{id=IdList}.
-
-get_beef(X) when is_record(X, id_of) -> X#id_of.type;
-get_beef(X) -> X.
-
-
-%% And among all elements in list
-list_and(F, [X|Xs]) ->
- case F(X) of
- true -> list_and(F, Xs);
- false -> false
- end;
-list_and(_F, []) -> true.
-
-
-
-
-
-%%--------------------------------------------------------------------
-%%
-%% resolve_inherit shall return a list of resolved inheritances,
-%% that is all names replaced with their global names.
-%%
-
-inherit_resolve(G, S, N, [X|Rest], Out) ->
- case scoped_lookup(G, S, N, X) of
- {Name, _T, _TK, Inh} ->
- case lists:member(Name, Out) of
- true ->
- inherit_resolve(G, S, N, Rest, Out);
- false ->
- case unique_append(Inh, [Name|Out]) of
- error ->
- ic_error:error(G, {inherit_resolve, X, Name}),
- inherit_resolve(G, S, N, Rest, []);
- UA ->
- inherit_resolve(G, S, N, Rest, UA)
- end
- end;
- _ -> inherit_resolve(G, S, N, Rest, Out)
- end;
-inherit_resolve(_G, _S, _N, [], Out) -> lists:reverse(Out).
-
-unique_append([X|Xs], L) ->
- case lists:member(X, L) of
- true -> unique_append(Xs, L);
- false -> unique_append(Xs, [X|L])
- end;
-unique_append([], L) -> L;
-%% Error
-unique_append(_, _L) -> error.
-
-
-
-
-%%--------------------------------------------------------------------
-%%
-%% Utilities
-%%
-
-%% Must preserve order, therefore had to write my own (instead of lists:map)
-check_list(G, S, N, [X|Xs]) ->
- X1 = check(G, S, N, X),
- [X1 | check_list(G, S, N, Xs)];
-check_list(_G, _S, _N, []) -> [].
-
-
-
-filter( [] ) ->
- error;
-filter( [I | Is ] ) ->
- case I of
- { _, member, { _, TKINFO }, _ } ->
- fetchType( TKINFO );
-
- { _, struct, _, _ } ->
- struct;
-
- { _, typedef, TKINFO, _ } ->
- fetchType( TKINFO );
-
- { _, module, _, _ } ->
- module;
-
- { _, interface, _, _ } ->
- interface;
-
- { _, op, _, _ } ->
- op;
-
- { _,enum, _, _ } ->
- enum;
-
- { _, spellcheck } ->
- filter( Is );
-
- _ ->
- error
- end.
-
-
-fetchType( { tk_sequence, _, _ } ) ->
- sequence;
-fetchType( { tk_array, _, _ } ) ->
- array;
-fetchType( { tk_struct, _, _, _} ) ->
- struct;
-fetchType( { tk_string, _} ) ->
- string;
-fetchType( { tk_wstring, _} ) -> %% WSTRING
- wstring;
-fetchType( { tk_fixed, _, _} ) ->
- fixed;
-fetchType( tk_short ) ->
- short;
-fetchType( tk_long ) ->
- long;
-fetchType( tk_longlong ) -> %% LLONG
- longlong;
-fetchType( tk_ushort ) ->
- ushort;
-fetchType( tk_ulong ) ->
- ulong;
-fetchType( tk_ulonglong ) -> %% ULLONG
- ulonglong;
-fetchType( tk_float ) ->
- float;
-fetchType( tk_double ) ->
- double;
-fetchType( tk_boolean ) ->
- boolean;
-fetchType( tk_char ) ->
- char;
-fetchType( tk_wchar ) -> %% WCHAR
- wchar;
-fetchType( tk_octet ) ->
- octet;
-fetchType( { tk_enum, _, _, _ } ) ->
- enum;
-fetchType( { tk_union, _, _, _, _, _ } ) ->
- union;
-fetchType( tk_any ) ->
- any;
-fetchType( _ ) ->
- error.
-
-%% Z is a single name
-to_uppercase(Z) ->
- lists:map(fun(X) when X>=$a, X=<$z -> X-$a+$A;
- (X) -> X end, Z).
-
-
-%%------------------------------------------------------------
-%%
-%% Always fetchs TK of a record.
-%%
-%%------------------------------------------------------------
-fetchTk(G,N,X) ->
- case ic_forms:get_tk(X) of
- undefined ->
- searchTk(G,ictk:get_IR_ID(G, N, X));
- TK ->
- TK
- end.
-
-
-%%------------------------------------------------------------
-%%
-%% seek type code when not accessible by get_tk/1
-%%
-%%------------------------------------------------------------
-searchTk(G,IR_ID) ->
- S = ic_genobj:tktab(G),
- case catch searchTk(S,IR_ID,typedef) of
- {value,TK} ->
- TK;
- _ -> %% false / exit
- case catch searchTk(S,IR_ID,struct) of
- {value,TK} ->
- TK;
- _ -> %% false / exit
- case catch searchTk(S,IR_ID,union) of
- {value,TK} ->
- TK;
- _ ->
- undefined
- end
- end
- end.
-
-
-searchTk(S,IR_ID,Type) ->
- L = lists:flatten(ets:match(S,{'_',Type,'$1','_'})),
- case lists:keysearch(IR_ID,2,L) of
- {value,TK} ->
- {value,TK};
- false ->
- searchInsideTks(L,IR_ID)
- end.
-
-
-searchInsideTks([],_IR_ID) ->
- false;
-searchInsideTks([{tk_array,TK,_}|Xs],IR_ID) ->
- case searchIncludedTk(TK,IR_ID) of
- {value,TK} ->
- {value,TK};
- false ->
- searchInsideTks(Xs,IR_ID)
- end.
-
-
-searchIncludedTk({tk_array,TK,_},IR_ID) ->
- searchIncludedTk(TK,IR_ID);
-searchIncludedTk({tk_sequence,TK,_},IR_ID) ->
- searchIncludedTk(TK,IR_ID);
-searchIncludedTk(TK, _IR_ID) when is_atom(TK) ->
- false;
-searchIncludedTk(TK,IR_ID) ->
- case element(2,TK) == IR_ID of
- true ->
- {value,TK};
- false ->
- false
- end.
-
diff --git a/lib/ic/src/icunion.erl b/lib/ic/src/icunion.erl
deleted file mode 100644
index c39a5177e7..0000000000
--- a/lib/ic/src/icunion.erl
+++ /dev/null
@@ -1,1491 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(icunion).
-
--import(ic_codegen, [emit/2, emit/3, emit/4, emit_c_enc_rpt/4, emit_c_dec_rpt/4]).
--import(ic_cbe, [mk_c_type/3, mk_c_type/4]).
-
--include("icforms.hrl").
--include("ic.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([union_gen/4]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-union_gen(G, N, X, c) when is_record(X, union) ->
- emit_c_union(G, N, X);
-union_gen(_G, _N, _X, _L) ->
- ok.
-
-
-%% Emits the union
-emit_c_union(G, N, X) ->
- %%io:format("Rec = ~p\n",[X]),
- case ic_genobj:is_hrlfile_open(G) of
- true ->
-
- %% Sort Union Default = put it last in case list
- NewX = #union{ id = X#union.id,
- type = X#union.type,
- body = mvDefaultToTail(X#union.body),
- tk = X#union.tk },
-
- UnionScope = [ic_forms:get_id2(NewX) | N],
-
- case ic_pragma:is_local(G,UnionScope) of
-
- true ->
-
- HFd = ic_genobj:hrlfiled(G),
- emit_c_union_values(G, N, NewX, HFd),
- UnionName = ic_util:to_undersc(UnionScope),
-
- emit(HFd, "\n#ifndef __~s__\n",[ictype:to_uppercase(UnionName)]),
- emit(HFd, "#define __~s__\n",[ictype:to_uppercase(UnionName)]),
- ic_codegen:mcomment_light(HFd,
- [io_lib:format("Union definition: ~s",
- [UnionName])],
- c),
- emit(HFd, "typedef struct {\n"),
- emit(HFd, " ~s _d;\n", [get_c_union_discriminator(G, N, NewX)]),
- emit(HFd, " union {\n"),
- emit_c_union_values_decl(G, N, NewX, HFd),
- emit(HFd, " } _u;\n"),
- emit(HFd, "} ~s;\n\n", [UnionName]),
-
- emit(HFd, "int ~s~s(CORBA_Environment *oe_env, int*, int*);\n",
- [ic_util:mk_oe_name(G, "sizecalc_"), UnionName]),
- emit(HFd, "int ~s~s(CORBA_Environment *oe_env, ~s*);\n",
- [ic_util:mk_oe_name(G, "encode_"), UnionName, UnionName]),
- emit(HFd, "int ~s~s(CORBA_Environment *oe_env, char *, int*, ~s*);\n",
- [ic_util:mk_oe_name(G, "decode_"), UnionName, UnionName]),
- emit(HFd, "\n#endif\n\n"),
- create_c_union_file(G, N, NewX, UnionName);
-
- false -> %% Do not generate included types att all.
- ok
- end;
- false ->
- ok
- end.
-
-
-
-%% Loops over union members and creates members typedefs
-emit_c_union_values(G, N, X, Fd) ->
- emit_c_union_values_loop(G, N, X, Fd, X#union.body).
-
-emit_c_union_values_loop(G, N, X, Fd, [CU]) ->
- case CU of
- {case_dcl,_,Id,Type} ->
- case Id of
- {array, _AID, _SZ} -> % Check for arrays
- mk_array_file(G,N,X,Id,Type,Fd);
- _ -> % Elementary types or seq/struct
- ok
- end;
- _ ->
- error
- end;
-emit_c_union_values_loop(G, N, X, Fd, [CU |CUs]) ->
- case CU of
- {case_dcl,_,Id,Type} ->
- case Id of
- {array, _AID, _SZ} -> % Check for arrays
- mk_array_file(G,N,X,Id,Type,Fd);
- _ -> % Elementary types or seq/struct
- emit_c_union_values_loop(G, N, X, Fd, CUs)
- end;
- _ ->
- error
- end.
-
-
-%% Loops over union members and declares members inside union structure
-emit_c_union_values_decl(G, N, X, Fd) ->
- emit_c_union_values_decl_loop(G, N, X, Fd, X#union.body).
-
-emit_c_union_values_decl_loop(G, N, X, Fd, [CU]) ->
- case CU of
- {case_dcl,_,Id,Type} ->
- case Id of
- {array, _AID, _SZ} -> % Check for arrays
- mk_array_decl(G,N,X,Id,Type,Fd);
- _ -> % Elementary types or seq/struct
- mk_union_member_decl(G,N,X,Id,Type,Fd),
- ok
- end;
- _ ->
- error
- end;
-emit_c_union_values_decl_loop(G, N, X, Fd, [CU |CUs]) ->
- case CU of
- {case_dcl,_,Id,Type} ->
- case Id of
- {array, _AID, _SZ} -> % Check for arrays
- mk_array_decl(G,N,X,Id,Type,Fd),
- emit_c_union_values_decl_loop(G, N, X, Fd, CUs);
- _ -> % Elementary types or seq/struct
- mk_union_member_decl(G,N,X,Id,Type,Fd),
- emit_c_union_values_decl_loop(G, N, X, Fd, CUs)
- end;
- _ ->
- error
- end.
-
-
-%% Makes the declaration for the array in union
-mk_array_decl(G,N,X,Id,Type,Fd) ->
- emit(Fd, " ~s ~s;\n",
- [getCaseTypeStr(G,N,X,Id,Type),
- mk_array_name(Id)]).
-
-mk_array_name({array,Id,D}) ->
- ic_forms:get_id2(Id) ++ mk_array_dim(D).
-
-mk_array_dim([]) ->
- "";
-mk_array_dim([{_,_,Dim}|Dims]) ->
- "[" ++ Dim ++ "]" ++ mk_array_dim(Dims).
-
-
-%% Creates the array file
-mk_array_file(G,N,X,{array,AID,SZ},Type,HFd) ->
- ArrayName = ic_util:to_undersc([ic_forms:get_id2(AID),ic_forms:get_id2(X) | N]),
- ArrayDim = extract_array_dim(SZ),
- emit(HFd, "\n#ifndef __~s__\n",[ictype:to_uppercase(ArrayName)]),
- emit(HFd, "#define __~s__\n\n",[ictype:to_uppercase(ArrayName)]),
- icstruct:create_c_array_coding_file(G,
- N,
- {ArrayName,ArrayDim},
- Type,
- no_typedef),
- emit(HFd, "\n#endif\n\n").
-
-extract_array_dim([{_,_,Dim}]) ->
- [Dim];
-extract_array_dim([{_,_,Dim}|Dims]) ->
- [Dim | extract_array_dim(Dims)].
-
-
-%% Makes the declaration for the member in union
-mk_union_member_decl(G,N,X,Id,Type,Fd) ->
- emit(Fd, " ~s ~s;\n",
- [getCaseTypeStr(G,N,X,Id,Type),
- ic_forms:get_id2(Id)]).
-
-
-
-
-%% File utilities
-create_c_union_file(G, N, X, UnionName) ->
-
- {Fd , SName} = open_c_coding_file(G, UnionName),
- _HFd = ic_genobj:hrlfiled(G), %% Write on stubfile header
- HrlFName = filename:basename(ic_genobj:include_file(G)),
- ic_codegen:emit_stub_head(G, Fd, SName, c),
- emit(Fd, "#include \"~s\"\n\n",[HrlFName]),
-
- %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %% Fd = ic_genobj:stubfiled(G), %% Write on stubfile
- %% HFd = ic_genobj:hrlfiled(G), %% Write on stubfile header
- %% HrlFName = filename:basename(ic_genobj:include_file(G)),
- %% emit(Fd, "#include \"~s\"\n\n",[HrlFName]),
- %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- put(op_variable_count, 0),
- put(tmp_declarations, []),
-
- %% Write generated code on file
- emit_union_sizecount(G, N, X, Fd, UnionName),
- emit_union_encode(G, N, X, Fd, UnionName),
- emit_union_decode(G, N, X, Fd, UnionName),
- file:close(Fd).
-
-open_c_coding_file(G, Name) ->
- SName = string:concat(ic_util:mk_oe_name(G, "code_"), Name),
- FName =
- ic_file:join(ic_options:get_opt(G, stubdir),ic_file:add_dot_c(SName)),
- case file:open(FName, [write]) of
- {ok, Fd} ->
- {Fd, SName};
- Other ->
- exit(Other)
- end.
-
-
-
-
-get_c_union_discriminator(G, N, X) ->
- case getDiscrStr(G, N, X#union.type) of
- error ->
- ic_error:fatal_error(G, {illegal_typecode_for_c, X#union.type, N});
- DiscrStr ->
- case ic_code:get_basetype(G, DiscrStr) of
- {short, _} ->
- "CORBA_short";
- {unsigned,{short, _}} ->
- "CORBA_unsigned_short";
- {long, _} ->
- "CORBA_long";
- {unsigned,{long, _}} ->
- "CORBA_unsigned_long";
- {boolean,_} ->
- "CORBA_boolean";
- {char,_} ->
- "CORBA_char";
- {enum, EnumType} ->
- EnumType;
- _ ->
- DiscrStr
- end
- end.
-
-getDiscrStr(G, N, S) when element(1, S) == scoped_id ->
- case ic_symtab:get_full_scoped_name(G, N, S) of
- {FSN, _, tk_short, _} ->
- ic_util:to_undersc(FSN);
- {FSN, _, tk_ushort, _} ->
- ic_util:to_undersc(FSN);
- {FSN, _, tk_long, _} ->
- ic_util:to_undersc(FSN);
- {FSN, _, tk_ulong, _} ->
- ic_util:to_undersc(FSN);
- {FSN, _, tk_boolean, _} ->
- ic_util:to_undersc(FSN);
- {FSN, _, tk_char, _} ->
- ic_util:to_undersc(FSN);
- {FSN, _, {tk_enum,_,_,_}, _} ->
- ic_util:to_undersc(FSN);
- _ ->
- error
- end;
-getDiscrStr(_G, N, X) ->
- case X of
- {short,_} ->
- "CORBA_short";
- {unsigned,{short,_}} ->
- "CORBA_unsigned_short";
- {long, _} ->
- "CORBA_long";
- {unsigned,{long,_}} ->
- "CORBA_unsigned_long";
- {boolean,_} ->
- "CORBA_boolean";
- {char,_} ->
- "CORBA_char";
- {enum,TID,_,_} ->
- ic_util:to_undersc([ic_forms:get_id2(TID) | N]);
- _ ->
- error
- end.
-
-
-
-
-getCaseTypeStr(G, N, X, I, T) when element(1, T) == scoped_id ->
- case catch ic_symtab:get_full_scoped_name(G, N, T) of
- {FSN, _, _, _} ->
- BT = ic_code:get_basetype(G, ic_util:to_undersc(FSN)),
- case isList(BT) of
- true ->
- BT;
- false ->
- case BT of
- {short,_} ->
- "CORBA_short";
- {unsigned,{short,_}} ->
- "CORBA_unsigned_short";
- {long, _} ->
- "CORBA_long";
- {unsigned,{long,_}} ->
- "CORBA_unsigned_long";
- {float,_} ->
- "CORBA_float";
- {double,_} ->
- "CORBA_double";
- {boolean,_} ->
- "CORBA_boolean";
- {char,_} ->
- "CORBA_char";
- {wchar,_} ->
- "CORBA_wchar";
- {octet,_} ->
- "CORBA_octet";
- {string,_} ->
- "CORBA_char*";
- {wstring,_} ->
- "CORBA_wchar*";
- {sequence,_,_} ->
- ic_util:to_undersc([ic_forms:get_id2(I), ic_forms:get_id2(X) | N]);
- {struct,SID,_,_} ->
- ic_util:to_undersc([ic_forms:get_id2(SID), ic_forms:get_id2(X) | N]);
- {enum,EID} ->
- EID;
- {any, _} -> %% Fix for any type
- "CORBA_long";
- _ ->
- %%io:format("BT = ~p~n",[BT]),
- error
- end
- end
- end;
-getCaseTypeStr(_G, N, X, I, T) ->
- case T of
- {short,_} ->
- "CORBA_short";
- {unsigned,{short,_}} ->
- "CORBA_unsigned_short";
- {long, _} ->
- "CORBA_long";
- {unsigned,{long,_}} ->
- "CORBA_unsigned_long";
- {float,_} ->
- "CORBA_float";
- {double,_} ->
- "CORBA_double";
- {boolean,_} ->
- "CORBA_boolean";
- {char,_} ->
- "CORBA_char";
- {wchar,_} ->
- "CORBA_wchar";
- {octet,_} ->
- "CORBA_octet";
- {string,_} ->
- "CORBA_char*";
- {wstring,_} ->
- "CORBA_wchar*";
- {sequence,_,_} ->
- ic_util:to_undersc([ic_forms:get_id2(I), ic_forms:get_id2(X) | N]);
- {struct,SID,_,_} ->
- ic_util:to_undersc([ic_forms:get_id2(SID), ic_forms:get_id2(X) | N]);
- {union,UID,_,_,_} ->
- ic_util:to_undersc([ic_forms:get_id2(UID), ic_forms:get_id2(X) | N]);
- {any, _} -> %% Fix for any type
- "CORBA_long";
- _ ->
- error
- end.
-
-isList(L) when is_list(L) ->
- true;
-isList(_) ->
- false.
-
-%%
-%% Sizecount facilities
-%%
-emit_union_sizecount(G, N, X, Fd, UnionName) ->
- emit(Fd, "int ~s~s(CORBA_Environment *oe_env, int* oe_size_count_index, int* oe_size) {\n\n",
- [ic_util:mk_oe_name(G, "sizecalc_"), UnionName]),
-
- emit(Fd, " int oe_malloc_size = 0;\n"),
- emit(Fd, " int oe_error_code = 0;\n"),
- emit(Fd, " int oe_type = 0;\n"),
- emit(Fd, " int oe_tmp = 0;\n"),
- emit_union_discr_var_decl(G, N, X, Fd),
-
- ic_codegen:nl(Fd),
- emit(Fd, " if(*oe_size == 0)\n",[]),
- AlignName = lists:concat(["*oe_size + sizeof(",UnionName,")"]),
- emit(Fd, " *oe_size = ~s;\n\n", [ic_util:mk_align(AlignName)]),
-
- emit(Fd, " if ((oe_error_code = ei_get_type(oe_env->_inbuf, oe_size_count_index, &oe_type, &oe_tmp)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_get_type", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- %%emit(Fd, " if (oe_tmp != 3)\n"),
- %%emit(Fd, " return -1;\n\n"),
-
- emit(Fd, " if ((oe_error_code = ei_decode_tuple_header(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_decode_tuple_header", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_atom(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n", []),
- emit_c_dec_rpt(Fd, " ", "ei_decode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit_c_union_discr_sizecount(G, N, X, Fd),
- emit(Fd, " /* Calculate union size */\n"),
- emit(Fd, " switch(oe_discr) {\n"),
-
- emit_c_union_loop(G, N, X, Fd, X#union.body, sizecalc),
- emit(Fd, " }\n\n"),
-
- emit(Fd, " *oe_size = ~s;\n",[ic_util:mk_align("*oe_size+oe_malloc_size")]),
- emit(Fd, " return 0;\n"),
- emit(Fd, "}\n\n\n").
-
-
-emit_union_discr_var_decl(G, N, X, Fd) ->
- UD = get_c_union_discriminator(G, N, X),
- case UD of
- "CORBA_short" ->
- emit(Fd, " long oe_discr = 0;\n");
- "CORBA_unsigned_short" ->
- emit(Fd, " unsigned long oe_discr = 0;\n");
- "CORBA_long" ->
- emit(Fd, " long oe_discr = 0;\n");
- "CORBA_unsigned_long" ->
- emit(Fd, " unsigned long oe_discr = 0;\n");
- "CORBA_boolean" ->
- emit(Fd, " int oe_discr = 0;\n"),
- emit(Fd, " char oe_bool[256];\n");
- "CORBA_char" ->
- emit(Fd, " char oe_discr = 0;\n");
- _T ->
- emit(Fd, " int oe_dummy = 0;\n"),
- emit(Fd, " ~s oe_discr = 0;\n",[UD])
- end.
-
-
-emit_c_union_discr_sizecount(G, N, X, Fd) ->
- emit(Fd, " /* Calculate discriminator size */\n"),
- UD = get_c_union_discriminator(G, N, X),
- case UD of
- "CORBA_short" ->
- emit(Fd, " if ((oe_error_code = ei_decode_long(oe_env->_inbuf, oe_size_count_index, &oe_discr)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_decode_long", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "CORBA_unsigned_short" ->
- emit(Fd, " if ((oe_error_code = ei_decode_ulong(oe_env->_inbuf, oe_size_count_index, &oe_discr)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_decode_ulong", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "CORBA_long" ->
- emit(Fd, " if ((oe_error_code = ei_decode_long(oe_env->_inbuf, oe_size_count_index, &oe_discr)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_decode_long", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "CORBA_unsigned_long" ->
- emit(Fd, " if ((oe_error_code = ei_decode_ulong(oe_env->_inbuf, oe_size_count_index, &oe_discr)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_decode_ulong", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "CORBA_boolean" ->
- emit(Fd, " if ((oe_error_code = ei_decode_atom(oe_env->_inbuf, oe_size_count_index, oe_bool)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_decode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " if (strcmp(oe_bool, \"false\") == 0) {\n"),
- emit(Fd, " oe_discr = 0;\n"),
- emit(Fd, " }\n"),
- emit(Fd, " else if (strcmp(oe_bool, \"true\") == 0) {\n"),
- emit(Fd, " oe_discr = 1;\n"),
- emit(Fd, " }\n"),
- emit(Fd, " else {\n"),
- emit_c_dec_rpt(Fd, " ", "not boolean", []),
- emit(Fd, " return -1;\n }\n");
-
- "CORBA_char" ->
- emit(Fd, " if ((oe_error_code = ei_decode_char(oe_env->_inbuf, oe_size_count_index, &oe_discr)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_decode_char", []),
- emit(Fd, " return oe_error_code;\n }\n");
- T ->
- emit(Fd, " oe_tmp = *oe_size_count_index;\n"),
- emit(Fd, " if ((oe_error_code = oe_sizecalc_~s(oe_env, oe_size_count_index, &oe_malloc_size)) < 0) {\n", [T]),
- ?emit_c_dec_rpt(Fd, " ", "oe_size_calc_~s", [T]),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit(Fd, " *oe_size_count_index = oe_tmp;\n"),
- emit(Fd, " oe_tmp = oe_env->_iin;\n"),
- emit(Fd, " oe_env->_iin = *oe_size_count_index;\n"),
- emit(Fd, " if ((oe_error_code = oe_decode_~s(oe_env, NULL, &oe_dummy, &oe_discr)) < 0) {\n", [T]),
- ?emit_c_dec_rpt(Fd, " ", "oe_decode_~s", [T]),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit(Fd, " *oe_size_count_index = oe_env->_iin;\n"),
- emit(Fd, " oe_env->_iin = oe_tmp;\n\n")
- end.
-
-
-
-emit_c_union_loop(G, N, X, Fd, CaseList, Case) ->
- emit_c_union_loop(G, N, X, Fd, CaseList, false, Case).
-
-emit_c_union_loop(G, N, X, Fd, [], GotDefaultCase, Case) ->
- case GotDefaultCase of
- false ->
- emit_c_union_valueless_discriminator(G, N, X, Fd, Case)
- end;
-emit_c_union_loop(G, N, X, Fd, [CU|CUs], GotDefaultCase, Case) ->
- case CU of
- {case_dcl,CaseList,I,T} ->
- GotDefaultCase = emit_c_union_case(G, N, X, Fd, I, T, CaseList, Case),
- emit_c_union_loop(G, N, X, Fd, CUs, GotDefaultCase, Case);
- _ ->
- error
- end.
-
-emit_c_union_valueless_discriminator(_G, _N, _X, Fd, Case) ->
- emit(Fd, " default:\n"),
- case Case of
- sizecalc ->
- emit(Fd, " {\n"),
- emit(Fd, " char oe_undefined[15];\n\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_atom(oe_env->_inbuf, "
- "oe_size_count_index, oe_undefined)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_decode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " }\n");
- encode ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_atom(oe_env, \"undefined\")) < 0) {\n"),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " break;\n");
- decode ->
- emit(Fd, " {\n"),
- emit(Fd, " char oe_undefined[15];\n\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_atom(oe_env->_inbuf, &oe_env->_iin, "
- "oe_undefined)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_decode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " if (strcmp(oe_undefined, \"undefined\") != 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "undefined", []),
- emit(Fd, " return -1;\n }\n"),
- emit(Fd, " }\n")
- end.
-
-
-emit_c_union_case(G, N, X, Fd, I, T, [{default,_}], Case) ->
- emit(Fd, " default:\n"),
- case Case of
- sizecalc ->
- getCaseTypeSizecalc(G, N, X, Fd, I, T);
- encode ->
- getCaseTypeEncode(G, N, X, Fd, I, T);
- decode ->
- getCaseTypeDecode(G, N, X, Fd, I, T)
- end,
- true;
-emit_c_union_case(G, N, X, Fd, I, T, [{Bool,_}], Case) -> %% Boolean discriminator
- case Bool of
- 'TRUE' ->
- emit(Fd, " case 1:\n");
- 'FALSE' ->
- emit(Fd, " case 0:\n")
- end,
- case Case of
- sizecalc ->
- getCaseTypeSizecalc(G, N, X, Fd, I, T);
- encode ->
- getCaseTypeEncode(G, N, X, Fd, I, T);
- decode ->
- getCaseTypeDecode(G, N, X, Fd, I, T)
- end,
- emit(Fd, " break;\n\n"),
- false;
-emit_c_union_case(G, N, X, Fd, I, T, [{Bool,_}|Rest], Case) -> %% Boolean discriminator
- case Bool of
- 'TRUE' ->
- emit(Fd, " case 1:\n");
- 'FALSE' ->
- emit(Fd, " case 0:\n")
- end,
- emit_c_union_case(G, N, X, Fd, I, T, Rest, Case),
- false;
-emit_c_union_case(G, N, X, Fd, I, T, [{_,_,NrStr}], Case) -> %% Integer type discriminator
- case get_c_union_discriminator(G, N, X) of
- "CORBA_char" ->
- emit(Fd, " case \'~s\':\n",[NrStr]);
- _ ->
- emit(Fd, " case ~s:\n",[NrStr])
- end,
- case Case of
- sizecalc ->
- getCaseTypeSizecalc(G, N, X, Fd, I, T);
- encode ->
- getCaseTypeEncode(G, N, X, Fd, I, T);
- decode ->
- getCaseTypeDecode(G, N, X, Fd, I, T)
- end,
- emit(Fd, " break;\n\n"),
- false;
-emit_c_union_case(G, N, X, Fd, I, T, [{_,_,NrStr}|Rest], Case) -> %% Integer type discriminator
- emit(Fd, " case ~s:\n",[NrStr]),
- emit_c_union_case(G, N, X, Fd, I, T, Rest, Case),
- false;
-emit_c_union_case(G, N, X, Fd, I, T, [{scoped_id,_,_,[EID]}], Case) -> %% Enumerant type discriminator
- SID = ic_util:to_undersc([EID|get_c_union_discriminator_scope(G, N, X)]),
- %%io:format("SID = ~p~n",[SID]),
- emit(Fd, " case ~s:\n",[SID]),
- case Case of
- sizecalc ->
- getCaseTypeSizecalc(G, N, X, Fd, I, T);
- encode ->
- getCaseTypeEncode(G, N, X, Fd, I, T);
- decode ->
- getCaseTypeDecode(G, N, X, Fd, I, T)
- end,
- emit(Fd, " break;\n\n"),
- false;
-emit_c_union_case(G, N, X, Fd, I, T, [{scoped_id,_,_,[EID]}|Rest], Case) -> %% Enumerant type discriminator
- SID = ic_util:to_undersc([EID|get_c_union_discriminator_scope(G, N, X)]),
- %%io:format("SID = ~p~n",[SID]),
- emit(Fd, " case ~s:\n",[SID]),
- emit_c_union_case(G, N, X, Fd, I, T, Rest, Case),
- false.
-
-
-%%
-%% Returns the enumerant discriminator scope
-%%
-get_c_union_discriminator_scope(G, N, X) ->
- {FullScopedName, _, _TK, _} = ic_symtab:get_full_scoped_name(G, N, X#union.type),
- BT = case ic_code:get_basetype(G, ic_util:to_undersc(FullScopedName)) of
- {enum,ST} ->
- ST;
- Other ->
- Other
- end,
- tl(lists:reverse(string:tokens(BT,"_"))). %% Ugly work arround
-
-
-
-
-
-getCaseTypeSizecalc(G, N, X, Fd, I, T) when element(1, T) == scoped_id ->
- case ic_fetch:member2type(G,X,I) of
- ushort ->
- emit(Fd, " if ((oe_error_code = ei_decode_ulong(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "ushort:ei_decode_ulong", []),
- emit(Fd, " return oe_error_code;\n }\n");
- ulong ->
- emit(Fd, " if ((oe_error_code = ei_decode_ulong(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "ulong:ei_decode_ulong", []),
- emit(Fd, " return oe_error_code;\n }\n");
- short ->
- emit(Fd, " if ((oe_error_code = ei_decode_long(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "short:ei_decode_long", []),
- emit(Fd, " return oe_error_code;\n }\n");
- long ->
- emit(Fd, " if ((oe_error_code = ei_decode_long(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "long:ei_decode_long", []),
- emit(Fd, " return oe_error_code;\n }\n");
- float ->
- emit(Fd, " if ((oe_error_code = ei_decode_double(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "float:ei_decode_double", []),
- emit(Fd, " return oe_error_code;\n }\n");
- double ->
- emit(Fd, " if ((oe_error_code = ei_decode_double(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "double:ei_decode_double", []),
- emit(Fd, " return oe_error_code;\n }\n");
- boolean ->
- emit(Fd, " if ((oe_error_code = ei_decode_atom(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "boolean:ei_decode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n");
- char ->
- emit(Fd, " if ((oe_error_code = ei_decode_char(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "char:ei_decode_char", []),
- emit(Fd, " return oe_error_code;\n }\n");
- octet ->
- emit(Fd, " if ((oe_error_code = ei_decode_char(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "octet:ei_decode_char", []),
- emit(Fd, " return oe_error_code;\n }\n");
- string ->
- emit(Fd, " if ((oe_error_code = ei_get_type(oe_env->_inbuf, oe_size_count_index, &oe_type, &oe_tmp)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "ei_get_type", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_string(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "ei_decode_string", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " oe_malloc_size = ~s;\n",[ic_util:mk_align("oe_malloc_size+oe_tmp+1")]);
- any -> %% Fix for any type
- emit(Fd, " if ((oe_error_code = ei_decode_long(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "ei_decode_long", []),
- emit(Fd, " return oe_error_code;\n }\n");
-
- _ ->
- case getCaseTypeStr(G, N, X, I, T) of
- "erlang_pid" ->
- emit(Fd, " if ((oe_error_code = ei_decode_pid(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n",
- []),
- ?emit_c_dec_rpt(Fd, " ", "ei_decode_pid", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "erlang_port" ->
- emit(Fd, " if ((oe_error_code = ei_decode_port(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n",
- []),
- ?emit_c_dec_rpt(Fd, " ", "ei_decode_port", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "erlang_ref" ->
- emit(Fd, " if ((oe_error_code = ei_decode_ref(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n",
- []),
- ?emit_c_dec_rpt(Fd, " ", "ei_decode_ref", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "erlang_term" ->
- emit(Fd, " if ((oe_error_code = ei_decode_term(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n",
- []),
- ?emit_c_dec_rpt(Fd, " ", "ei_deoce_term", []),
- emit(Fd, " return oe_error_code;\n }\n");
-
- Other ->
-
- emit(Fd, " if ((oe_error_code = oe_sizecalc_~s(oe_env, oe_size_count_index, &oe_malloc_size)) < 0) {\n",
- [Other]),
- ?emit_c_dec_rpt(Fd, " ", "oe_sizecalc_~s", [Other]),
- emit(Fd, " return oe_error_code;\n }\n")
- end
- end;
-getCaseTypeSizecalc(G, N, X, Fd, I, T) ->
- case I of
- {array,_,_} ->
- ArrayName = ic_util:to_undersc([ic_forms:get_id2(I),ic_forms:get_id2(X) | N]),
- emit(Fd, " if ((oe_error_code = oe_sizecalc_~s(oe_env, oe_size_count_index, &oe_malloc_size)) < 0) {\n",
- [ArrayName]),
- ?emit_c_dec_rpt(Fd, " ", "oe_sizecalc_~s", [ArrayName]),
- emit(Fd, " return oe_error_code;\n }\n");
- _ ->
- case T of
- {short,_} ->
- emit(Fd, " if ((oe_error_code = ei_decode_long(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "short:ei_decode_long", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {unsigned,{short,_}} ->
- emit(Fd, " if ((oe_error_code = ei_decode_ulong(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "ushort:ei_decode_ulong", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {long, _} ->
- emit(Fd, " if ((oe_error_code = ei_decode_long(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "long:ei_decode_long", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {unsigned,{long,_}} ->
- emit(Fd, " if ((oe_error_code = ei_decode_ulong(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "ulong:ei_decode_ulong", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {float,_} ->
- emit(Fd, " if ((oe_error_code = ei_decode_double(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "float:ei_decode_double", []),
- emit(Fd, " return oe_error_code;\n }");
- {double,_} ->
- emit(Fd, " if ((oe_error_code = ei_decode_double(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "double:ei_decode_double", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {boolean,_} ->
- emit(Fd, " if ((oe_error_code = ei_decode_atom(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "boolean:ei_decode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {char,_} ->
- emit(Fd, " if ((oe_error_code = ei_decode_char(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "char:ei_decode_char", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {octet,_} ->
- emit(Fd, " if ((oe_error_code = ei_decode_char(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "octet:ei_decode_char", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {string,_} ->
- emit(Fd, " if ((oe_error_code = ei_get_type(oe_env->_inbuf, oe_size_count_index, &oe_type, &oe_tmp)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "ei_get_type", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_string(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "ei_decode_string", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " oe_malloc_size = ~s;\n",[ic_util:mk_align("oe_malloc_size+oe_tmp+1")]);
- {sequence,_,_} ->
- SeqName = ic_util:to_undersc([ic_forms:get_id2(I), ic_forms:get_id2(X) | N]),
- emit(Fd, " if ((oe_error_code = oe_sizecalc_~s(oe_env, oe_size_count_index, &oe_malloc_size)) < 0) {\n",
- [SeqName]),
- ?emit_c_dec_rpt(Fd, " ", "sequence:oe_sizecalc_~s", [SeqName]),
- emit(Fd, " return oe_error_code;\n }\n");
- {struct,SID,_,_} ->
- StructName = ic_util:to_undersc([ic_forms:get_id2(SID), ic_forms:get_id2(X) | N]),
- emit(Fd, " if ((oe_error_code = oe_sizecalc_~s(oe_env, oe_size_count_index, &oe_malloc_size)) < 0) {\n",
- [StructName]),
- ?emit_c_dec_rpt(Fd, " ", "struct:oe_sizecalc_~s", [StructName]),
- emit(Fd, " return oe_error_code;\n }\n");
- {union,UID,_,_,_} ->
- UnionName = ic_util:to_undersc([ic_forms:get_id2(UID), ic_forms:get_id2(X) | N]),
- emit(Fd, " if ((oe_error_code = oe_sizecalc_~s(oe_env, oe_size_count_index, &oe_malloc_size)) < 0) {\n",
- [UnionName]),
- ?emit_c_dec_rpt(Fd, " ", "union:oe_sizecalce_~s", [UnionName]),
- emit(Fd, " return oe_error_code;\n }\n");
- {any, _} -> %% Fix for any type
- emit(Fd, " if ((oe_error_code = ei_decode_long(oe_env->_inbuf, oe_size_count_index, 0)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "any:ei_decode_long", []),
- emit(Fd, " return oe_error_code;\n }\n");
- _ ->
- ic_error:fatal_error(G, {illegal_typecode_for_c, T, N})
- end
- end.
-
-
-
-
-
-%%
-%% Encode facilities
-%%
-emit_union_encode(G, N, X, Fd, UnionName) ->
- emit(Fd, "int ~s~s(CORBA_Environment *oe_env, ~s* oe_rec) {\n\n",
- [ic_util:mk_oe_name(G, "encode_"), UnionName, UnionName]),
-
- emit(Fd, " int oe_error_code = 0;\n\n"),
-
- emit(Fd, " if ((oe_error_code = oe_ei_encode_tuple_header(oe_env, 3)) < 0) {\n"),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_tuple_header", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit(Fd, " if ((oe_error_code = oe_ei_encode_atom(oe_env, \"~s\")) < 0) {\n",
- [UnionName]),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit_c_union_discr_encode(G, N, X, Fd),
- emit(Fd, " /* Encode union */\n"),
- emit(Fd, " switch(oe_rec->_d) {\n"),
- emit_c_union_loop(G, N, X, Fd, X#union.body, encode),
- emit(Fd, " }\n\n"),
- emit(Fd, " return 0;\n"),
- emit(Fd, "}\n\n\n").
-
-
-emit_c_union_discr_encode(G, N, X, Fd) ->
- emit(Fd, " /* Encode descriminator */\n"),
- UD = get_c_union_discriminator(G, N, X),
- case UD of
- "CORBA_short" ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_long(oe_env, oe_rec->_d)) < 0) {\n"),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_long", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "CORBA_unsigned_short" ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_ulong(oe_env, oe_rec->_d)) < 0) {\n"),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_ulong", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "CORBA_long" ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_long(oe_env, oe_rec->_d)) < 0) {\n"),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_long", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "CORBA_unsigned_long" ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_ulong(oe_env, oe_rec->_d)) < 0) {\n"),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_ulong", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "CORBA_boolean" ->
- emit(Fd, " switch(oe_rec->_d) {\n"),
- emit(Fd, " case 0:\n"),
- emit(Fd, " if ((oe_error_code = oe_ei_encode_atom(oe_env, \"false\")) < 0) {\n"),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " break;\n"),
- emit(Fd, " case 1:\n"),
- emit(Fd, " if ((oe_error_code = oe_ei_encode_atom(oe_env, \"true\")) < 0) {\n"),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " break;\n"),
- emit(Fd, " default:\n"),
- emit_c_enc_rpt(Fd, " ", "boolean failure", []),
- emit(Fd, " return -1;\n"),
- emit(Fd, " }\n\n");
- "CORBA_char" ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_char(oe_env, oe_rec->_d)) < 0) {\n"),
- emit_c_enc_rpt(Fd, " ", "oe_ei_encode_char", []),
- emit(Fd, " return oe_error_code;\n }\n");
- T ->
- emit(Fd, " if ((oe_error_code = oe_encode_~s(oe_env, oe_rec->_d)) < 0) {\n", [T]),
- ?emit_c_enc_rpt(Fd, " ", "oe_encode_~s", [T]),
- emit(Fd, " return oe_error_code;\n }\n")
- end.
-
-
-getCaseTypeEncode(G, N, X, Fd, I, T) when element(1, T) == scoped_id ->
- case ic_fetch:member2type(G,X,I) of
- ushort ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_ulong(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "ushort:oe_ei_encode_ulong", []),
- emit(Fd, " return oe_error_code;\n }\n");
- ulong ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_ulong(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "ulong:oe_ei_encode_ulong", []),
- emit(Fd, " return oe_error_code;\n }\n");
- short ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_long(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "short:oe_ei_encode_long", []),
- emit(Fd, " return oe_error_code;\n }\n");
- long ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_long(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "long:oe_ei_encode_long", []),
- emit(Fd, " return oe_error_code;\n }\n");
- float ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_double(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "float:oe_ei_encode_double", []),
- emit(Fd, " return oe_error_code;\n }\n");
- double ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_double(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "double:oe_ei_encode_double", []),
- emit(Fd, " return oe_error_code;\n }\n");
- boolean ->
- emit(Fd, " switch(oe_rec->_u.~s) {\n",[ic_forms:get_id2(I)]),
- emit(Fd, " case 0:\n"),
- emit(Fd, " if ((oe_error_code = oe_ei_encode_atom(oe_env, \"false\")) < 0) {\n"),
- ?emit_c_enc_rpt(Fd, " ", "boolean:oe_ei_encode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " break;\n"),
- emit(Fd, " case 1:\n"),
- emit(Fd, " if ((oe_error_code = oe_ei_encode_atom(oe_env, \"true\")) < 0) {\n"),
- ?emit_c_enc_rpt(Fd, " ", "boolean:oe_ei_encode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " break;\n"),
- emit(Fd, " default:\n"),
- ?emit_c_enc_rpt(Fd, " ", "boolean failure", []),
- emit(Fd, " return -1;\n"),
- emit(Fd, " }\n");
- char ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_char(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "char:oe_ei_encode_char", []),
- emit(Fd, " return oe_error_code;\n }\n");
- octet ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_char(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "octet:oe_ei_encode_char", []),
- emit(Fd, " return oe_error_code;\n }\n");
- string ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_string(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "oe_ei_encode_string", []),
- emit(Fd, " return oe_error_code;\n }\n");
- struct ->
- case ic_cbe:mk_c_type(G, N, T, evaluate_not) of
- "erlang_pid" ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_pid(oe_env, &oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "oe_ei_encode_pid", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "erlang_port" ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_port(oe_env, &oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "oe_ei_encode_port", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "erlang_ref" ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_ref(oe_env, &oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "oe_ei_encode_ref", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "ETERM*" ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_term(oe_env, &oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "oe_ei_encode_term", []),
- emit(Fd, " return oe_error_code;\n }\n");
- _ ->
- emit(Fd, " if ((oe_error_code = oe_encode_~s(oe_env, &oe_rec->_u.~s)) < 0) {\n",
- [getCaseTypeStr(G, N, X, I, T), ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "oe_encode_~s",
- [getCaseTypeStr(G, N, X, I, T)]),
- emit(Fd, " return oe_error_code;\n }\n")
- end;
- sequence ->
- emit(Fd, " if ((oe_error_code = oe_encode_~s(oe_env, &oe_rec->_u.~s)) < 0) {\n",
- [getCaseTypeStr(G, N, X, I, T),ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "sequence:oe_encode_~s",
- [getCaseTypeStr(G, N, X, I, T)]),
- emit(Fd, " return oe_error_code;\n }\n");
- array ->
- emit(Fd, " if ((oe_error_code = oe_encode_~s(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [getCaseTypeStr(G, N, X, I, T),ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "array:oe_encode_~s",
- [getCaseTypeStr(G, N, X, I, T)]),
- emit(Fd, " return oe_error_code;\n }\n");
- union ->
- emit(Fd, " if ((oe_error_code = oe_encode_~s(oe_env, &oe_rec->_u.~s)) < 0) {\n",
- [getCaseTypeStr(G, N, X, I, T),ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "union:oe_encode_~s",
- [getCaseTypeStr(G, N, X, I, T)]),
- emit(Fd, " return oe_error_code;\n }\n");
- enum ->
- emit(Fd, " if ((oe_error_code = oe_encode_~s(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [getCaseTypeStr(G, N, X, I, T),ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "enum:oe_encode_~s",
- [getCaseTypeStr(G, N, X, I, T)]),
- emit(Fd, " return oe_error_code;\n }\n");
- any -> %% Fix for any type
- emit(Fd, " if ((oe_error_code = oe_ei_encode_long(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "enum:oe_ei_encodelong", []),
- emit(Fd, " return oe_error_code;\n }\n");
- _ ->
- ic_error:fatal_error(G, {illegal_typecode_for_c, T, N})
- end;
-getCaseTypeEncode(G, N, X, Fd, I, T) ->
- case I of
- {array,AID,_} ->
- ArrayName = ic_util:to_undersc([ic_forms:get_id2(AID),ic_forms:get_id2(X) | N]),
- emit(Fd, " if ((oe_error_code = oe_encode_~s(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ArrayName,ic_forms:get_id2(AID)]),
- ?emit_c_enc_rpt(Fd, " ", "array:oe_encode_~s", [ArrayName]),
- emit(Fd, " return oe_error_code;\n }\n");
- _ ->
- case T of
- {short,_} ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_long(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "short:oe_ei_encode_long", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {unsigned,{short,_}} ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_ulong(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "ushort:oe_ei_encode_ulong", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {long, _} ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_long(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "long:oe_ei_encode_long", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {unsigned,{long,_}} ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_ulong(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "ulong:oe_ei_encode_ulong", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {float,_} ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_double(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "float:oe_ei_encode_double", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {double,_} ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_double(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "double:oe_ei_encode_double", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {boolean,_} ->
- emit(Fd, " switch(oe_rec->_u.~s) {\n",[ic_forms:get_id2(I)]),
- emit(Fd, " case 0:\n"),
- emit(Fd, " if ((oe_error_code = oe_ei_encode_atom(oe_env, \"false\")) < 0) {\n"),
- ?emit_c_enc_rpt(Fd, " ", "boolean:oe_ei_encode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " break;\n"),
- emit(Fd, " case 1:\n"),
- emit(Fd, " if ((oe_error_code = oe_ei_encode_atom(oe_env, \"true\")) < 0) {\n"),
- ?emit_c_enc_rpt(Fd, " ", "boolean:oe_ei_encode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " break;\n"),
- emit(Fd, " default:\n"),
- ?emit_c_enc_rpt(Fd, " ", "boolean failure", []),
- emit(Fd, " return -1;\n"),
- emit(Fd, " }\n");
- {char,_} ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_char(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "char:oe_ei_encode_char", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {octet,_} ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_char(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "octet:oe_ei_encode_char", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {string,_} ->
- emit(Fd, " if ((oe_error_code = oe_ei_encode_string(oe_env, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "oe_ei_encode_string", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {sequence,_,_} ->
- SeqName = ic_util:to_undersc([ic_forms:get_id2(I), ic_forms:get_id2(X) | N]),
- emit(Fd, " if ((oe_error_code = oe_encode_~s(oe_env, &oe_rec->_u.~s)) < 0) {\n",
- [SeqName,ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "sequence:oe_encode_~s", [SeqName]),
- emit(Fd, " return oe_error_code;\n }\n");
- {struct,SID,_,_} ->
- StructName = ic_util:to_undersc([ic_forms:get_id2(SID), ic_forms:get_id2(X) | N]),
- emit(Fd, " if ((oe_error_code = oe_encode_~s(oe_env, &oe_rec->_u.~s)) < 0) {\n",
- [StructName,ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "struct:oe_encode_~s", [StructName]),
- emit(Fd, " return oe_error_code;\n }\n");
- {union,UID,_,_,_} ->
- UnionName = ic_util:to_undersc([ic_forms:get_id2(UID), ic_forms:get_id2(X) | N]),
- emit(Fd, " if ((oe_error_code = oe_encode_~s(oe_env, &oe_rec->_u.~s)) < 0) {\n",
- [UnionName,ic_forms:get_id2(I)]),
- ?emit_c_enc_rpt(Fd, " ", "union:oe_encode_~s", [UnionName]),
- emit(Fd, " return oe_error_code;\n }\n");
- _ ->
- ic_error:fatal_error(G, {illegal_typecode_for_c, T, N})
- end
- end.
-
-
-
-
-%%
-%% Decode facilities
-%%
-emit_union_decode(G, N, X, Fd, UnionName) ->
- emit(Fd, "int ~s~s(CORBA_Environment *oe_env, char *oe_first, int* oe_index, ~s* oe_rec) {\n\n",
- [ic_util:mk_oe_name(G, "decode_"), UnionName, UnionName]),
-
- emit(Fd, " int oe_error_code = 0;\n"),
- emit(Fd, " int oe_tmp = 0;\n"),
- emit(Fd, " char oe_union_name[256];\n\n"),
-
- emit(Fd, " if((char*) oe_rec == oe_first)\n",[]),
- AlignName = lists:concat(["*oe_index + sizeof(",UnionName,")"]),
- emit(Fd, " *oe_index = ~s;\n\n", [ic_util:mk_align(AlignName)]),
-
- emit(Fd, " if ((oe_error_code = ei_decode_tuple_header(oe_env->_inbuf, &oe_env->_iin, &oe_tmp)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_decode_tuple_header", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit(Fd, " if ((oe_error_code = ei_decode_atom(oe_env->_inbuf, &oe_env->_iin, oe_union_name)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ei_decode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit_c_union_discr_decode(G, N, X, Fd),
- emit(Fd, " /* Decode union */\n"),
- emit(Fd, " switch(oe_rec->_d) {\n"),
- emit_c_union_loop(G, N, X, Fd, X#union.body, decode),
- emit(Fd, " }\n\n"),
-
- emit(Fd, " *oe_index = ~s;\n", [ic_util:mk_align("*oe_index")]),
- emit(Fd, " return 0;\n"),
- emit(Fd, "}\n\n\n").
-
-
-emit_c_union_discr_decode(G, N, X, Fd) ->
- emit(Fd, " /* Decode descriminator */\n"),
- UD = get_c_union_discriminator(G, N, X),
- case UD of
- "CORBA_short" ->
- emit(Fd, " {\n"),
- emit(Fd, " long oe_long;\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_long(oe_env->_inbuf, &oe_env->_iin, &oe_long)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "short:ei_decode_long", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " oe_rec->_d = (short) oe_long;\n\n"),
- emit(Fd, " if (oe_rec->_d != oe_long)\n return -1;\n"),
- emit(Fd, " }\n\n");
- "CORBA_unsigned_short" ->
- emit(Fd, " {\n"),
- emit(Fd, " unsigned long oe_ulong;\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_ulong(oe_env->_inbuf, &oe_env->_iin, &oe_ulong)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "unshort:ei_decode_ulong", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " oe_rec->_d = (unsigned short) oe_ulong;\n\n"),
- emit(Fd, " if (oe_rec->_d != oe_ulong)\n return -1;\n"),
- emit(Fd, " }\n\n");
- "CORBA_long" ->
- emit(Fd, " if ((oe_error_code = ei_decode_long(oe_env->_inbuf, &oe_env->_iin, &oe_rec->_d)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "long:ei_decode_long", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "CORBA_unsigned_long" ->
- emit(Fd, " if ((oe_error_code = ei_decode_ulong(oe_env->_inbuf, &oe_env->_iin, &oe_rec->_d)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "ulong:ei_decode_ulong", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "CORBA_boolean" ->
- emit(Fd, " {\n"),
- emit(Fd, " char oe_bool[25];\n\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_atom(oe_env->_inbuf, &oe_env->_iin, oe_bool)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "boolean:ei_decode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " if (strcmp(oe_bool, \"false\") == 0) {\n"),
- emit(Fd, " oe_rec->_d = 0;\n"),
- emit(Fd, " }else if (strcmp(oe_bool, \"true\") == 0) {\n"),
- emit(Fd, " oe_rec->_d = 1;\n"),
- emit(Fd, " } else {\n"),
- emit_c_dec_rpt(Fd, " ", "boolean failure", []),
- emit(Fd, " return -1;\n }\n"),
- emit(Fd, " }\n\n");
- "CORBA_char" ->
- emit(Fd, " if ((oe_error_code = ei_decode_char(oe_env->_inbuf, &oe_env->_iin, &oe_rec->_d)) < 0) {\n"),
- emit_c_dec_rpt(Fd, " ", "char:ei_decode_char", []),
- emit(Fd, " return oe_error_code;\n }\n");
- T ->
- emit(Fd, " if ((oe_error_code = oe_decode_~s(oe_env, oe_first, oe_index, &oe_rec->_d)) < 0) {\n",
- [T]),
- ?emit_c_dec_rpt(Fd, " ", "oe_decode_~s", [T]),
- emit(Fd, " return oe_error_code;\n }\n")
- end.
-
-
-
-getCaseTypeDecode(G, N, X, Fd, I, T) when element(1, T) == scoped_id ->
- case ic_fetch:member2type(G,X,I) of
- ushort ->
- emit(Fd, " {\n"),
- emit(Fd, " unsigned long oe_ulong;\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_ulong(oe_env->_inbuf, &oe_env->_iin, &oe_ulong)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "ushort:ei_decode_ulong", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " oe_rec->_u.~s = (unsigned short) oe_ulong;\n\n",[ic_forms:get_id2(I)]),
- emit(Fd, " if (oe_rec->_u.~s != oe_ulong)\n return -1;\n",[ic_forms:get_id2(I)]),
- emit(Fd, " }\n");
- ulong ->
- emit(Fd, " if ((oe_error_code = ei_decode_ulong(oe_env->_inbuf, &oe_env->_iin, &oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "ulong:ei_decode_ulong", []),
- emit(Fd, " return oe_error_code;\n }\n");
- short ->
- emit(Fd, " {\n"),
- emit(Fd, " long oe_long;\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_long(oe_env->_inbuf, &oe_env->_iin, &oe_long)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "short:ei_decode_long", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " oe_rec->_u.~s = (short) oe_long;\n\n",[ic_forms:get_id2(I)]),
- emit(Fd, " if (oe_rec->_u.~s != oe_long)\n return -1;\n",[ic_forms:get_id2(I)]),
- emit(Fd, " }\n");
- long ->
- emit(Fd, " if ((oe_error_code = ei_decode_long(oe_env->_inbuf, &oe_env->_iin, &oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "long:ei_decode_long", []),
- emit(Fd, " return oe_error_code;\n }\n");
- float ->
- emit(Fd, " {\n"),
- emit(Fd, " double oe_double;\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_double(oe_env->_inbuf, &oe_env->_iin, &oe_double)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "float:ei_decode_double", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " oe_rec->_u.~s = (float) oe_double;\n",[ic_forms:get_id2(I)]),
- emit(Fd, " }\n");
- double ->
- emit(Fd, " if ((oe_error_code = ei_decode_double(oe_env->_inbuf, &oe_env->_iin, &oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "double:ei_decode_double", []),
- emit(Fd, " return oe_error_code;\n }\n");
- boolean ->
- emit(Fd, " {\n"),
- emit(Fd, " char oe_bool[25];\n\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_atom(oe_env->_inbuf, &oe_env->_iin, oe_bool)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "boolean:ei_decode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " if (strcmp(oe_bool, \"false\") == 0) {\n"),
- emit(Fd, " oe_rec->_u.~s = 0;\n",[ic_forms:get_id2(I)]),
- emit(Fd, " } else if (strcmp(oe_bool, \"true\") == 0) {\n"),
- emit(Fd, " oe_rec->_u.~s = 1;\n",[ic_forms:get_id2(I)]),
- emit(Fd, " } else {\n"),
- ?emit_c_dec_rpt(Fd, " ", "boolean failure", []),
- emit(Fd, " return -1;\n }\n"),
- emit(Fd, " }\n");
- char ->
- emit(Fd, " if ((oe_error_code = ei_decode_char(oe_env->_inbuf, &oe_env->_iin, &oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "char:ei_decode_char", []),
- emit(Fd, " return oe_error_code;\n }\n");
- octet ->
- emit(Fd, " if ((oe_error_code = ei_decode_char(oe_env->_inbuf, &oe_env->_iin, &oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "octet:ei_decode_char", []),
- emit(Fd, " return oe_error_code;\n }\n");
- string ->
- emit(Fd, " {\n"),
- emit(Fd, " int oe_type = 0;\n"),
- emit(Fd, " int oe_string_ctr = 0;\n\n"),
-
- emit(Fd, " (int) ei_get_type(oe_env->_inbuf, &oe_env->_iin, &oe_type, &oe_string_ctr);\n\n"),
-
- emit(Fd, " oe_rec->_u.~s = (void *) (oe_first + *oe_index);\n\n",[ic_forms:get_id2(I)]),
-
- emit(Fd, " if ((oe_error_code = ei_decode_string(oe_env->_inbuf, &oe_env->_iin, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "ei_decode_string", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit(Fd, " *oe_index = ~s;\n",[ic_util:mk_align("*oe_index+oe_string_ctr+1")]),
- emit(Fd, " }\n");
- struct ->
- case ic_cbe:mk_c_type(G, N, T, evaluate_not) of
- "erlang_pid" ->
- emit(Fd, " if ((oe_error_code = ei_decode_pid(oe_env->_inbuf, &oe_env->_iin, &oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "ei_decode_pid", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "erlang_port" ->
- emit(Fd, " if ((oe_error_code = ei_decode_port(oe_env->_inbuf, &oe_env->_iin, &oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "ei_decode_port", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "erlang_ref" ->
- emit(Fd, " if ((oe_error_code = ei_decode_ref(oe_env->_inbuf, &oe_env->_iin, &oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "ei_decode_ref", []),
- emit(Fd, " return oe_error_code;\n }\n");
- "ETERM*" ->
- emit(Fd, " if ((oe_error_code = ei_decode_term(oe_env->_inbuf, &oe_env->_iin, (void **)&oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "ei_decode_term", []),
- emit(Fd, " return oe_error_code;\n }\n");
-
- _ ->
- emit(Fd, " if ((oe_error_code = oe_decode_~s(oe_env, oe_first, oe_index, &oe_rec->_u.~s)) < 0) {\n",
- [getCaseTypeStr(G, N, X, I, T),ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "oe_decode_~s",
- [getCaseTypeStr(G, N, X, I, T)]),
- emit(Fd, " return oe_error_code;\n }\n")
- end;
- sequence ->
- emit(Fd, " if ((oe_error_code = oe_decode_~s(oe_env, oe_first, oe_index, &oe_rec->_u.~s)) < 0) {\n",
- [getCaseTypeStr(G, N, X, I, T),ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "sequence:oe_decode_~s",
- [getCaseTypeStr(G, N, X, I, T)]),
- emit(Fd, " return oe_error_code;\n }\n");
- array ->
- emit(Fd, " if ((oe_error_code = oe_decode_~s(oe_env, oe_first, oe_index, oe_rec->_u.~s)) < 0) {\n",
- [getCaseTypeStr(G, N, X, I, T),ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "array:oe_decode_~s", [getCaseTypeStr(G, N, X, I, T)]),
- emit(Fd, " return oe_error_code;\n }\n");
- union ->
- emit(Fd, " if ((oe_error_code = oe_decode_~s(oe_env, oe_first, oe_index, &oe_rec->_u.~s)) < 0) {\n",
- [getCaseTypeStr(G, N, X, I, T),ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "union:oe_decode_~s", [getCaseTypeStr(G, N, X, I, T)]),
- emit(Fd, " return oe_error_code;\n }\n");
- enum ->
- emit(Fd, " if ((oe_error_code = oe_decode_~s(oe_env, oe_first, oe_index, &oe_rec->_u.~s)) < 0) {\n",
- [getCaseTypeStr(G, N, X, I, T),ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "enum:oe_decode_~s", [getCaseTypeStr(G, N, X, I, T)]),
- emit(Fd, " return oe_error_code;\n }\n");
- any -> %% Fix for any type
- emit(Fd, " if ((oe_error_code = ei_decode_long(oe_env->_inbuf, &oe_env->_iin, &oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "any:ei_decodelong", []),
- emit(Fd, " return oe_error_code;\n }\n");
- _ ->
- ic_error:fatal_error(G, {illegal_typecode_for_c, T, N})
- end;
-getCaseTypeDecode(G, N, X, Fd, I, T) ->
- case I of
- {array,AID,_} ->
- ArrayName = ic_util:to_undersc([ic_forms:get_id2(AID),ic_forms:get_id2(X) | N]),
- emit(Fd, " if ((oe_error_code = oe_decode_~s(oe_env, oe_first, oe_index, oe_rec->_u.~s)) < 0) {\n",
- [ArrayName,ic_forms:get_id2(AID)]),
- ?emit_c_dec_rpt(Fd, " ", "array:oe_decode_~s", [ArrayName]),
- emit(Fd, " return oe_error_code;\n }\n");
- _ ->
- case T of
- {short,_} ->
- emit(Fd, " {\n"),
- emit(Fd, " long oe_long;\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_long(oe_env->_inbuf, &oe_env->_iin, &oe_long)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "short:ei_decode_long", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " oe_rec->_u.~s = (short) oe_long;\n\n",[ic_forms:get_id2(I)]),
- emit(Fd, " if (oe_rec->_u.~s != oe_long)\n return -1;\n",[ic_forms:get_id2(I)]),
- emit(Fd, " }\n");
- {unsigned,{short,_}} ->
- emit(Fd, " {\n"),
- emit(Fd, " unsigned long oe_ulong;\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_ulong(oe_env->_inbuf, &oe_env->_iin, &oe_ulong)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "ushort:ei_decode_ulong", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " oe_rec->_u.~s = (unsigned short) oe_ulong;\n\n",[ic_forms:get_id2(I)]),
- emit(Fd, " if (oe_rec->_u.~s != oe_ulong)\n return -1;\n",[ic_forms:get_id2(I)]),
- emit(Fd, " }\n");
- {long, _} ->
- emit(Fd, " if ((oe_error_code = ei_decode_long(oe_env->_inbuf, &oe_env->_iin, &oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "long:ei_decode_long", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {unsigned,{long,_}} ->
- emit(Fd, " if ((oe_error_code = ei_decode_ulong(oe_env->_inbuf, &oe_env->_iin, &oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "ulong:ei_decode_ulong", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {float,_} ->
- emit(Fd, " {\n"),
- emit(Fd, " double oe_double;\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_double(oe_env->_inbuf, &oe_env->_iin, &oe_double)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "float:ei_decode_double", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " oe_rec->_u.~s = (float) oe_double;\n",[ic_forms:get_id2(I)]),
- emit(Fd, " }\n");
- {double,_} ->
- emit(Fd, " if ((oe_error_code = ei_decode_double(oe_env->_inbuf, &oe_env->_iin, &oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "dobule:ei_decode_double", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {boolean,_} ->
- emit(Fd, " {\n"),
- emit(Fd, " char oe_bool[25];\n\n"),
- emit(Fd, " if ((oe_error_code = ei_decode_atom(oe_env->_inbuf, &oe_env->_iin, oe_bool)) < 0) {\n"),
- ?emit_c_dec_rpt(Fd, " ", "boolean:ei_decode_atom", []),
- emit(Fd, " return oe_error_code;\n }\n"),
- emit(Fd, " if (strcmp(oe_bool, \"false\") == 0) {\n"),
- emit(Fd, " oe_rec->_u.~s = 0;\n",[ic_forms:get_id2(I)]),
- emit(Fd, " } else if (strcmp(oe_bool, \"true\") == 0) {\n"),
- emit(Fd, " oe_rec->_u.~s = 1;\n",[ic_forms:get_id2(I)]),
- emit(Fd, " } else {\n"),
- ?emit_c_dec_rpt(Fd, " ", "boolean failure", []),
- emit(Fd, " return -1;\n }\n"),
- emit(Fd, " }\n");
- {char,_} ->
- emit(Fd, " if ((oe_error_code = ei_decode_char(oe_env->_inbuf, &oe_env->_iin, &oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "char:ei_decode_char", []),
- emit(Fd, " return oe_error_code;\n }\n");
- {octet,_} ->
- emit(Fd, " if ((oe_error_code = ei_decode_char(oe_env->_inbuf, &oe_env->_iin, &oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- emit(Fd, " return oe_error_code;\n }\n");
- {string,_} ->
- emit(Fd, " {\n"),
- emit(Fd, " int oe_type = 0;\n"),
- emit(Fd, " int oe_string_ctr = 0;\n\n"),
-
- emit(Fd, " (int) ei_get_type(oe_env->_inbuf, &oe_env->_iin, &oe_type, &oe_string_ctr);\n\n"),
-
- emit(Fd, " oe_rec->_u.~s = (void *) (oe_first + *oe_index);\n\n",[ic_forms:get_id2(I)]),
-
- emit(Fd, " if ((oe_error_code = ei_decode_string(oe_env->_inbuf, &oe_env->_iin, oe_rec->_u.~s)) < 0) {\n",
- [ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "ei_decode_string", []),
- emit(Fd, " return oe_error_code;\n }\n"),
-
- emit(Fd, " *oe_index = ~s;\n",[ic_util:mk_align("*oe_index+oe_string_ctr+1")]),
- emit(Fd, " }\n");
- {sequence,_,_} ->
- SeqName = ic_util:to_undersc([ic_forms:get_id2(I), ic_forms:get_id2(X) | N]),
- emit(Fd, " if ((oe_error_code = oe_decode_~s(oe_env, oe_first, oe_index, &oe_rec->_u.~s)) < 0) {\n",
- [SeqName,ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "sequence:oe_decode_~s", [SeqName]),
- emit(Fd, " return oe_error_code;\n }\n");
- {struct,SID,_,_} ->
- StructName = ic_util:to_undersc([ic_forms:get_id2(SID), ic_forms:get_id2(X) | N]),
- emit(Fd, " if ((oe_error_code = oe_decode_~s(oe_env, oe_first, oe_index, &oe_rec->_u.~s)) < 0) {\n",
- [StructName,ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "struct:oe_decode_~s", [StructName]),
- emit(Fd, " return oe_error_code;\n }\n");
- {union,UID,_,_,_} ->
- UnionName = ic_util:to_undersc([ic_forms:get_id2(UID), ic_forms:get_id2(X) | N]),
- emit(Fd, " if ((oe_error_code = oe_decode_~s(oe_env, oe_first, oe_index, &oe_rec->_u.~s)) < 0) {\n",
- [UnionName,ic_forms:get_id2(I)]),
- ?emit_c_dec_rpt(Fd, " ", "union:oe_decode_~s", [UnionName]),
- emit(Fd, " return oe_error_code;\n }");
- _ ->
- ic_error:fatal_error(G, {illegal_typecode_for_c, T, N})
- end
- end.
-
-mvDefaultToTail(CDclL) ->
- mvDefaultToTail(CDclL,[],[]).
-
-
-mvDefaultToTail([], F, FD) ->
- lists:reverse(F) ++ FD;
-mvDefaultToTail([{case_dcl,CaseList,I,T}|Rest], Found, FoundDefault) ->
- case lists:keysearch(default, 1, CaseList) of
- {value,Default} ->
- NewCaseList = lists:delete(Default, CaseList) ++ [Default],
- mvDefaultToTail(Rest, Found, [{case_dcl,NewCaseList,I,T}|FoundDefault]);
- false ->
- mvDefaultToTail(Rest, [{case_dcl,CaseList,I,T}|Found], FoundDefault)
- end.
-
-
diff --git a/lib/ic/src/icyeccpre.hrl b/lib/ic/src/icyeccpre.hrl
deleted file mode 100644
index 3a2fad185f..0000000000
--- a/lib/ic/src/icyeccpre.hrl
+++ /dev/null
@@ -1,125 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-
--export([parse/1, parse_and_scan/1, format_error/1]).
-
--import(lists, [reverse/1]).
-
--ifdef(JAM).
--compile([{parse_transform,jam_yecc_pj},pj]).
--endif.
-
-
--include("icforms.hrl").
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% The parser generator will insert appropriate declarations before this line.%
-
-parse(Tokens) ->
- case catch yeccpars1(Tokens, false, 0, [], []) of
- error ->
- Errorline =
- if Tokens == [] -> 0; true -> element(2, hd(Tokens)) end,
- {error,
- {Errorline, ?MODULE, "syntax error at or after this line."}};
- Other ->
- Other
- end.
-
-parse_and_scan({Mod, Fun, Args}) ->
- case apply(Mod, Fun, Args) of
- {eof, _} ->
- {ok, eof};
- {error, Descriptor, _} ->
- {error, Descriptor};
- {ok, Tokens, _} ->
- yeccpars1(Tokens, {Mod, Fun, Args}, 0, [], [])
- end.
-
-format_error(Message) ->
- case io_lib:deep_char_list(Message) of
- true ->
- Message;
- _ ->
- io_lib:write(Message)
- end.
-
-% To be used in grammar files to throw an error message to the parser toplevel.
-% Doesn't have to be exported!
-return_error(Line, Message) ->
- throw({error, {Line, ?MODULE, Message}}).
-
-
-% Don't change yeccpars1/6 too much, it is called recursively by yeccpars2/8!
-yeccpars1([Token | Tokens], Tokenizer, State, States, Vstack) ->
- yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens,
- Tokenizer);
-yeccpars1([], {M, F, A}, State, States, Vstack) ->
- case catch apply(M, F, A) of
- {eof, Endline} ->
- {error, {Endline, ?MODULE, "end_of_file"}};
- {error, Descriptor, _Endline} ->
- {error, Descriptor};
- {'EXIT', Reason} ->
- {error, {0, ?MODULE, Reason}};
- {ok, Tokens, _Endline} ->
- case catch yeccpars1(Tokens, {M, F, A}, State, States, Vstack) of
- error ->
- Errorline = element(2, hd(Tokens)),
- {error, {Errorline, ?MODULE,
- "syntax error at or after this line."}};
- Other ->
- Other
- end
- end;
-yeccpars1([], false, State, States, Vstack) ->
- yeccpars2(State, '$end', States, Vstack, {'$end', 999999}, [], false).
-
-% For internal use only.
-yeccerror(Token) ->
- {error,
- {element(2, Token), ?MODULE,
- ["syntax error before: ", yecctoken2string(Token)]}}.
-
-yecctoken2string({atom, _, A}) -> io_lib:write(A);
-yecctoken2string({integer,_,N}) -> io_lib:write(N);
-yecctoken2string({float,_,F}) -> io_lib:write(F);
-yecctoken2string({char,_,C}) -> io_lib:write_char(C);
-yecctoken2string({var,_,V}) -> io_lib:format("~s", [V]);
-yecctoken2string({string,_,S}) -> io_lib:write_string(S);
-yecctoken2string({reserved_symbol, _, A}) -> io_lib:format("~w", [A]);
-yecctoken2string({'dot', _}) -> "'.'";
-yecctoken2string({'$end', _}) ->
- [];
-yecctoken2string({Other, _}) when is_atom(Other) ->
- io_lib:format("~w", [Other]);
-yecctoken2string({_, _, Other}) when is_list(Other) andalso is_number(hd(Other)) ->
- Other;
-yecctoken2string({_, _, Other}) ->
- io_lib:format("~p", [Other]);
-yecctoken2string(Other) ->
- io_lib:write(Other).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
diff --git a/lib/ic/test/Makefile b/lib/ic/test/Makefile
deleted file mode 100644
index 55b8915875..0000000000
--- a/lib/ic/test/Makefile
+++ /dev/null
@@ -1,276 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1998-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(IC_VSN)
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/ic_test
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-TEST_SPEC_FILE = ic.spec ic_smoke.spec
-
-
-IDL_FILES =
-
-COMPILER_TEST_FILES = \
- ic_SUITE_data/Corba.idl \
- ic_SUITE_data/Coss.idl \
- ic_SUITE_data/attr.idl \
- ic_SUITE_data/c_err1.idl \
- ic_SUITE_data/c_err2.idl \
- ic_SUITE_data/c_err3.idl \
- ic_SUITE_data/c_norm.idl \
- ic_SUITE_data/enum.idl \
- ic_SUITE_data/forward.idl \
- ic_SUITE_data/include.idl \
- ic_SUITE_data/include2.idl \
- ic_SUITE_data/include3.idl \
- ic_SUITE_data/inherit.idl \
- ic_SUITE_data/inherit_err.idl \
- ic_SUITE_data/inherit_warn.idl \
- ic_SUITE_data/mult_ids.idl \
- ic_SUITE_data/nasty.idl \
- ic_SUITE_data/one.idl \
- ic_SUITE_data/one_out.idl \
- ic_SUITE_data/one_raises.idl \
- ic_SUITE_data/one_followed.idl \
- ic_SUITE_data/one_void.idl \
- ic_SUITE_data/raises_reg.idl \
- ic_SUITE_data/struct.idl \
- ic_SUITE_data/syntax1.idl \
- ic_SUITE_data/syntax2.idl \
- ic_SUITE_data/syntax3.idl \
- ic_SUITE_data/syntax4.idl \
- ic_SUITE_data/syntax5.idl \
- ic_SUITE_data/syntax6.idl \
- ic_SUITE_data/type.idl \
- ic_SUITE_data/typeid.idl \
- ic_SUITE_data/u_case_mult.idl \
- ic_SUITE_data/u_mult.idl \
- ic_SUITE_data/u_norm.idl \
- ic_SUITE_data/u_type.idl \
- ic_SUITE_data/u_default.idl \
- ic_SUITE_data/undef_id.idl
-
-
-COMPILER_TEST_FILES2 = \
- ic_register_SUITE_data/reg_m8.idl \
- ic_register_SUITE_data/reg_m9.idl \
- ic_register_SUITE_data/reg_m10.idl \
- ic_register_SUITE_data/reg_m11.idl \
- ic_register_SUITE_data/reg_m12.idl
-
-
-COMPILER_TEST_FILES3 = \
- ic_pragma_SUITE_data/reg_m0.idl \
- ic_pragma_SUITE_data/reg_m1.idl \
- ic_pragma_SUITE_data/reg_m2.idl \
- ic_pragma_SUITE_data/reg_m3.idl \
- ic_pragma_SUITE_data/reg_m4.idl \
- ic_pragma_SUITE_data/reg_m5.idl \
- ic_pragma_SUITE_data/reg_m6.idl \
- ic_pragma_SUITE_data/reg_m7.idl \
- ic_pragma_SUITE_data/uggly.idl
-
-
-COMPILER_TEST_FILES4 = \
- ic_be_SUITE_data/plain.idl
-
-
-PREPROCESSOR_TEST_FILES = \
- ic_pp_SUITE_data/arg.idl \
- ic_pp_SUITE_data/cascade.idl \
- ic_pp_SUITE_data/comment.idl \
- ic_pp_SUITE_data/concat.idl \
- ic_pp_SUITE_data/define.idl \
- ic_pp_SUITE_data/if.idl \
- ic_pp_SUITE_data/if_zero.idl \
- ic_pp_SUITE_data/improp_nest_constr.idl \
- ic_pp_SUITE_data/inc.idl \
- ic_pp_SUITE_data/line.idl \
- ic_pp_SUITE_data/misc.idl \
- ic_pp_SUITE_data/nopara.idl \
- ic_pp_SUITE_data/predef.idl \
- ic_pp_SUITE_data/predef_time.idl \
- ic_pp_SUITE_data/self_ref.idl \
- ic_pp_SUITE_data/separate.idl \
- ic_pp_SUITE_data/swallow_sc.idl \
- ic_pp_SUITE_data/unintended_grp.idl
-
-C_CLIENT_ERL_SERVER_TEST_FILES = \
- c_client_erl_server_SUITE_data/Makefile.src \
- c_client_erl_server_SUITE_data/c_erl_test.idl \
- c_client_erl_server_SUITE_data/c_client.c \
- c_client_erl_server_SUITE_data/m_i_impl.erl
-
-C_CLIENT_ERL_SERVER_PROTO_TEST_FILES = \
- c_client_erl_server_proto_SUITE_data/Makefile.src \
- c_client_erl_server_proto_SUITE_data/c_erl_test.idl \
- c_client_erl_server_proto_SUITE_data/c_client.c \
- c_client_erl_server_proto_SUITE_data/my.c \
- c_client_erl_server_proto_SUITE_data/m_i_impl.erl
-
-C_CLIENT_ERL_SERVER_PROTO_TMO_TEST_FILES = \
- c_client_erl_server_proto_tmo_SUITE_data/Makefile.src \
- c_client_erl_server_proto_tmo_SUITE_data/c_erl_test.idl \
- c_client_erl_server_proto_tmo_SUITE_data/c_client.c \
- c_client_erl_server_proto_tmo_SUITE_data/my.c \
- c_client_erl_server_proto_tmo_SUITE_data/m_i_impl.erl
-
-ERL_CLIENT_C_SERVER_TEST_FILES = \
- erl_client_c_server_SUITE_data/Makefile.src \
- erl_client_c_server_SUITE_data/erl_c_test.idl \
- erl_client_c_server_SUITE_data/erl_client.erl \
- erl_client_c_server_SUITE_data/c_server.c \
- erl_client_c_server_SUITE_data/callbacks.c
-
-ERL_CLIENT_C_SERVER_PROTO_TEST_FILES = \
- erl_client_c_server_proto_SUITE_data/Makefile.src \
- erl_client_c_server_proto_SUITE_data/erl_c_test.idl \
- erl_client_c_server_proto_SUITE_data/erl_client.erl \
- erl_client_c_server_proto_SUITE_data/c_server.c \
- erl_client_c_server_proto_SUITE_data/callbacks.c
-
-JAVA_CLIENT_ERL_SERVER_TEST_FILES = \
- java_client_erl_server_SUITE_data/Makefile.src \
- java_client_erl_server_SUITE_data/java_erl_test.idl \
- java_client_erl_server_SUITE_data/JavaClient.java \
- java_client_erl_server_SUITE_data/m_i_impl.erl
-
-MODULES = \
- ic_SUITE \
- ic_register_SUITE \
- ic_pragma_SUITE \
- ic_pp_SUITE \
- ic_be_SUITE \
- c_client_erl_server_SUITE \
- c_client_erl_server_proto_SUITE \
- c_client_erl_server_proto_tmo_SUITE \
- erl_client_c_server_SUITE \
- erl_client_c_server_proto_SUITE \
- java_client_erl_server_SUITE
-
-GEN_MODULES =
-
-ERL_FILES = $(MODULES:%=%.erl)
-
-HRL_FILES =
-
-GEN_HRL_FILES =
-
-
-GEN_FILES = \
- $(GEN_HRL_FILES:%=$(IDLOUTDIR)/%) \
- $(GEN_MODULES=:%=$(IDLOUTDIR)/%.erl)
-
-GEN_TARGET_FILES = $(GEN_MODULES:%=$(IDLOUTDIR)/%.$(EMULATOR))
-
-SUITE_TARGET_FILES = $(MODULES:%=%.$(EMULATOR))
-
-TARGET_FILES = \
- $(GEN_TARGET_FILES) \
- $(SUITE_TARGET_FILES)
-
-# ----------------------------------------------------
-# PROGRAMS
-# ----------------------------------------------------
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_LOCAL_FLAGS += -pa $(ERL_TOP)/lib/orber/ebin -pa $(ERL_TOP)/lib/ic/ebin
-
-ERL_COMPILE_FLAGS += \
- $(ERL_LOCAL_FLAGS) \
- -pa $(ERL_TOP)/lib/orber/ebin \
- -I$(ERL_TOP)/lib/orber
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-tests debug opt: $(TARGET_FILES)
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f errs core *~
-
-docs:
-
-# ----------------------------------------------------
-# Special Targets
-# ----------------------------------------------------
-
-
-# ----------------------------------------------------
-# Release Targets
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec:
-
-release_docs_spec:
-
-release_tests_spec: tests
- $(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELSYSDIR)/ic_SUITE_data"
- $(INSTALL_DIR) "$(RELSYSDIR)/ic_register_SUITE_data"
- $(INSTALL_DIR) "$(RELSYSDIR)/ic_pragma_SUITE_data"
- $(INSTALL_DIR) "$(RELSYSDIR)/ic_pp_SUITE_data"
- $(INSTALL_DIR) "$(RELSYSDIR)/ic_be_SUITE_data"
- $(INSTALL_DIR) "$(RELSYSDIR)/c_client_erl_server_SUITE_data"
- $(INSTALL_DIR) "$(RELSYSDIR)/c_client_erl_server_proto_SUITE_data"
- $(INSTALL_DIR) "$(RELSYSDIR)/c_client_erl_server_proto_tmo_SUITE_data"
- $(INSTALL_DIR) "$(RELSYSDIR)/erl_client_c_server_SUITE_data"
- $(INSTALL_DIR) "$(RELSYSDIR)/erl_client_c_server_proto_SUITE_data"
- $(INSTALL_DIR) "$(RELSYSDIR)/java_client_erl_server_SUITE_data"
- $(INSTALL_DATA) $(IDL_FILES) ic.cover $(TEST_SPEC_FILE) $(ERL_FILES) \
- "$(RELSYSDIR)"
- $(INSTALL_DATA) $(COMPILER_TEST_FILES) "$(RELSYSDIR)/ic_SUITE_data"
- $(INSTALL_DATA) $(COMPILER_TEST_FILES2) \
- "$(RELSYSDIR)/ic_register_SUITE_data"
- $(INSTALL_DATA) $(COMPILER_TEST_FILES3) \
- "$(RELSYSDIR)/ic_pragma_SUITE_data"
- $(INSTALL_DATA) $(COMPILER_TEST_FILES4) \
- "$(RELSYSDIR)/ic_be_SUITE_data"
- $(INSTALL_DATA) $(PREPROCESSOR_TEST_FILES) \
- "$(RELSYSDIR)/ic_pp_SUITE_data"
- $(INSTALL_DATA) $(C_CLIENT_ERL_SERVER_TEST_FILES) \
- "$(RELSYSDIR)/c_client_erl_server_SUITE_data"
- $(INSTALL_DATA) $(C_CLIENT_ERL_SERVER_PROTO_TEST_FILES) \
- "$(RELSYSDIR)/c_client_erl_server_proto_SUITE_data"
- $(INSTALL_DATA) $(C_CLIENT_ERL_SERVER_PROTO_TMO_TEST_FILES) \
- "$(RELSYSDIR)/c_client_erl_server_proto_tmo_SUITE_data"
- $(INSTALL_DATA) $(ERL_CLIENT_C_SERVER_TEST_FILES) \
- "$(RELSYSDIR)/erl_client_c_server_SUITE_data"
- $(INSTALL_DATA) $(ERL_CLIENT_C_SERVER_PROTO_TEST_FILES) \
- "$(RELSYSDIR)/erl_client_c_server_proto_SUITE_data"
- $(INSTALL_DATA) $(SUITE_TARGET_FILES) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(JAVA_CLIENT_ERL_SERVER_TEST_FILES) \
- "$(RELSYSDIR)/java_client_erl_server_SUITE_data"
diff --git a/lib/ic/test/c_client_erl_server_SUITE.erl b/lib/ic/test/c_client_erl_server_SUITE.erl
deleted file mode 100644
index b6e100e102..0000000000
--- a/lib/ic/test/c_client_erl_server_SUITE.erl
+++ /dev/null
@@ -1,265 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-%%----------------------------------------------------------------------
-%% Purpose : Test suite for c-client/erl-server
-%%----------------------------------------------------------------------
-
-
--module(c_client_erl_server_SUITE).
--include_lib("common_test/include/ct.hrl").
-
--export([init_per_testcase/2, end_per_testcase/2,
- all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- void_test/1, long_test/1, long_long_test/1,
- unsigned_short_test/1, unsigned_long_test/1,
- unsigned_long_long_test/1, double_test/1, char_test/1,
- wchar_test/1, octet_test/1, bool_test/1, struct_test/1,
- struct2_test/1, seq1_test/1, seq2_test/1, seq3_test/1,
- seq4_test/1, seq5_test/1, array1_test/1, array2_test/1,
- enum_test/1, string1_test/1, string2_test/1, string3_test/1,
- string4_test/1, pid_test/1, port_test/1, ref_test/1, term_test/1,
- typedef_test/1, inline_sequence_test/1, term_sequence_test/1,
- term_struct_test/1, wstring1_test/1]).
-
--define(DEFAULT_TIMEOUT, 20000).
--define(PORT_TIMEOUT, 15000).
--define(ERLANG_SERVER_NAME, idl_erlang_server).
--define(C_CLIENT_NODE_NAME, c_client_idl_test).
-
-%% Add/remove code path and watchdog before/after each test case.
-%%
-init_per_testcase(_Case, Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- code:add_patha(DataDir),
-
- %% Since other test suites use the module m_i, we have
- %% to make sure we are using the right m_i module.
- code:purge(m_i),
- code:load_file(m_i),
-
- WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- code:del_path(DataDir),
- WatchDog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [void_test, long_test, long_long_test,
- unsigned_short_test, unsigned_long_test,
- unsigned_long_long_test, double_test, char_test,
- wchar_test, octet_test, bool_test, struct_test,
- struct2_test, seq1_test, seq2_test, seq3_test,
- seq4_test, seq5_test, array1_test, array2_test,
- enum_test, string1_test, string2_test, string3_test,
- string4_test, pid_test, port_test, ref_test, term_test,
- typedef_test, inline_sequence_test, term_sequence_test,
- term_struct_test, wstring1_test].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-array1_test(Config) ->
- do_test(array1_test, Config).
-
-array2_test(Config) ->
- do_test(array2_test, Config).
-
-bool_test(Config) ->
- do_test(bool_test, Config).
-
-char_test(Config) ->
- do_test(char_test, Config).
-
-double_test(Config) ->
- do_test(double_test, Config).
-
-enum_test(Config) ->
- do_test(enum_test, Config).
-
-inline_sequence_test(Config) ->
- do_test(inline_sequence_test, Config).
-
-long_long_test(Config) ->
- do_test(long_long_test, Config).
-
-long_test(Config) ->
- do_test(long_test, Config).
-
-octet_test(Config) ->
- do_test(octet_test, Config).
-
-pid_test(Config) ->
- do_test(pid_test, Config).
-
-port_test(Config) ->
- do_test(port_test, Config).
-
-ref_test(Config) ->
- do_test(ref_test, Config).
-
-seq1_test(Config) ->
- do_test(seq1_test, Config).
-
-seq2_test(Config) ->
- do_test(seq2_test, Config).
-
-seq3_test(Config) ->
- do_test(seq3_test, Config).
-
-seq4_test(Config) ->
- do_test(seq4_test, Config).
-
-seq5_test(Config) ->
- do_test(seq5_test, Config).
-
-string1_test(Config) ->
- do_test(string1_test, Config).
-
-string2_test(Config) ->
- do_test(string2_test, Config).
-
-string3_test(Config) ->
- do_test(string3_test, Config).
-
-string4_test(Config) ->
- do_test(string4_test, Config).
-
-struct2_test(Config) ->
- do_test(struct2_test, Config).
-
-struct_test(Config) ->
- do_test(struct_test, Config).
-
-term_sequence_test(Config) ->
- do_test(term_sequence_test, Config).
-
-term_struct_test(Config) ->
- do_test(term_struct_test, Config).
-
-term_test(Config) ->
- do_test(term_test, Config).
-
-typedef_test(Config) ->
- do_test(typedef_test, Config).
-
-unsigned_long_long_test(Config) ->
- do_test(unsigned_long_long_test, Config).
-
-unsigned_long_test(Config) ->
- do_test(unsigned_long_test, Config).
-
-unsigned_short_test(Config) ->
- do_test(unsigned_short_test, Config).
-
-void_test(Config) ->
- do_test(void_test, Config).
-
-wchar_test(Config) ->
- do_test(wchar_test, Config).
-
-wstring1_test(Config) ->
- do_test(wstring1_test, Config).
-
-
-%% It is here that all tests really are done.
-%%
-
-do_test(Case, Config) ->
- %% Trap exits
- process_flag(trap_exit, true),
- %% Start the server
- {ok, _Pid} = m_i:oe_create_link([], {local, ?ERLANG_SERVER_NAME}),
- Node = atom_to_list(node()),
- DataDir = proplists:get_value(data_dir, Config),
- %% io:format("~p: data directory: ~p~n", [?MODULE, DataDir]),
- Cookie = atom_to_list(erlang:get_cookie()),
- %% Start C-client node as a port program.
- Cmd = filename:join([DataDir, "c_client"]) ++
- " -this-node-name " ++ atom_to_list(?C_CLIENT_NODE_NAME) ++
- " -peer-node " ++ Node ++
- " -peer-process-name " ++ atom_to_list(?ERLANG_SERVER_NAME) ++
- " -cookie " ++ Cookie ++
- " -test-case " ++ atom_to_list(Case),
- Port = open_port({spawn, Cmd}, [exit_status, eof, stderr_to_stdout]),
- Res = wait_for_completion(Port),
- %% Kill off node if there was timeout
- case Res of
- {error, timeout} ->
- catch rpc:cast(?C_CLIENT_NODE_NAME, erlang, halt, [1]);
- _ ->
- ok
- end,
- process_flag(trap_exit, false),
- catch m_i:stop(?ERLANG_SERVER_NAME),
- ok = Res.
-
-
-%% Wait for eof *and* exit status, but return if exit status indicates
-%% an error, or we have been waiting more than PORT_TIMEOUT seconds.
-%%
-wait_for_completion(Port) ->
- wait_for_completion(Port, 0).
-
-wait_for_completion(Port, N) when N < 2 ->
- receive
- {Port, {data, Bytes}} ->
- %% Relay output
- io:format("~s", [Bytes]),
- wait_for_completion(Port, N);
- {Port, {exit_status, 0}} ->
- wait_for_completion(Port, N + 1);
- {Port, {exit_status, Status}} ->
- {error, Status};
- {Port, eof} ->
- wait_for_completion(Port, N + 1);
- {'EXIT', Port, Reason} ->
- io:format("Port exited with reason: ~w~n", [Reason]),
- wait_for_completion(Port, N);
- {'EXIT', From, Reason} ->
- io:format("Got unexpected exit: ~p~n", [{'EXIT', From, Reason}]),
- wait_for_completion(Port, N)
- after ?PORT_TIMEOUT ->
- {error, timeout}
- end;
-wait_for_completion(_, _) ->
- ok.
-
-
-
diff --git a/lib/ic/test/c_client_erl_server_SUITE_data/Makefile.src b/lib/ic/test/c_client_erl_server_SUITE_data/Makefile.src
deleted file mode 100644
index 60ea8ea598..0000000000
--- a/lib/ic/test/c_client_erl_server_SUITE_data/Makefile.src
+++ /dev/null
@@ -1,155 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2001-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-# Makefile.src for c_client_erl_server test
-# Note: This file *must* work for both Unix and Windows
-#
-# We use both `rm' (Unix) and `del' (Windows) for removing files, but
-# with a `-' in front so that the error in not finding `rm' (`del') on
-# Windows (Unix) is ignored.
-#
-# VxWorks? XXX
-#
-
-.SUFFIXES:
-.SUFFIXES: .c .h .erl .idl @obj@ .@EMULATOR@
-
-
-# Variables from ts:
-#
-
-ERL_INCLUDE = @erl_include@
-
-IC_INCLUDE_PATH = @ic_include_path@
-IC_LIB = @ic_lib@
-
-ERL_INTERFACE_INCLUDE = @erl_interface_include@
-ERL_INTERFACE_LIB = @erl_interface_lib@
-ERL_INTERFACE_EILIB = @erl_interface_eilib@
-ERL_INTERFACE_THREADLIB = @erl_interface_threadlib@
-ERL_INTERFACE_SOCK_LIBS = @erl_interface_sock_libs@
-
-CC = @CC@
-## XXX Should set warning flag with a DEBUG_FLAG
-CFLAGS = @CFLAGS@ @DEFS@ -I@erl_include@ \
- -I@ic_include_path@ -I@erl_interface_include@
-
-LD = @LD@
-LDFLAGS = @CROSSLDFLAGS@
-LIBS = $(IC_LIB) $(ERL_INTERFACE_LIB) $(ERL_INTERFACE_EILIB) \
- $(ERL_INTERFACE_THREADLIB) @LIBS@ $(ERL_INTERFACE_SOCK_LIBS)
-ERLC = erlc
-
-# Generated C header files
-GEN_H_FILES = \
- m.h \
- m_i.h \
- oe_c_erl_test.h
-
-# Generated C files
-GEN_C_FILES = \
- m.c \
- m_i.c \
- oe_c_erl_test.c \
- oe_code_m_a.c \
- oe_code_m_arr1.c \
- oe_code_m_arr2.c \
- oe_code_m_arr3.c \
- oe_code_m_aseq.c \
- oe_code_m_b.c \
- oe_code_m_bseq.c \
- oe_code_m_dd.c \
- oe_code_m_dyn.c \
- oe_code_m_dyn_sl.c \
- oe_code_m_es.c \
- oe_code_m_et.c \
- oe_code_m_etseq.c \
- oe_code_m_fruit.c \
- oe_code_m_lseq.c \
- oe_code_m_s.c \
- oe_code_m_s_sl.c \
- oe_code_m_sarr3.c \
- oe_code_m_simple.c \
- oe_code_m_ssarr3.c \
- oe_code_m_sseq.c \
- oe_code_m_ssstr3.c \
- oe_code_m_sstr3.c \
- oe_code_m_str1.c \
- oe_code_m_str3.c \
- oe_code_m_strRec.c \
- oe_code_m_strRec_str5.c \
- oe_code_m_strRec_str7.c
-
-GEN_HRL_FILES = \
- m.hrl \
- m_i.hrl \
- oe_c_erl_test.hrl
-
-GEN_ERL_FILES = \
- m.erl \
- m_arr2.erl \
- m_arr3.erl \
- m_i.erl \
- m_str3.erl \
- oe_c_erl_test.erl
-
-C_FILES = $(GEN_C_FILES) c_client.c
-
-OBJS = $(C_FILES:.c=@obj@)
-
-PGMS = c_client@exe@
-
-ERL_FILES = $(GEN_ERL_FILES) m_i_impl.erl
-
-EBINS = $(ERL_FILES:.erl=.@EMULATOR@)
-
-
-all: $(PGMS) $(EBINS)
-
-$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.built_erl
-$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.built_c
-$(OBJS): $(GEN_C_FILES) $(GEN_H_FILES)
-$(EBINS): $(GEN_ERL_FILES) $(GEN_HRL_FILES)
-
-clean:
- -rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
- c_erl_test.built_erl c_erl_test.built_c
- -del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
- c_erl_test.built_erl c_erl_test.built_c
-
-$(PGMS): $(OBJS)
- $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
-
-c_erl_test.built_c: c_erl_test.idl
- $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_client}" c_erl_test.idl
- echo done > c_erl_test.built_c
-
-c_erl_test.built_erl: c_erl_test.idl
- $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" c_erl_test.idl
- echo done > c_erl_test.built_erl
-
-.c@obj@:
- $(CC) -c -o $*@obj@ $(CFLAGS) $<
-
-.erl.@EMULATOR@:
- $(ERLC) -I $(IC_INCLUDE_PATH) $<
-
diff --git a/lib/ic/test/c_client_erl_server_SUITE_data/c_client.c b/lib/ic/test/c_client_erl_server_SUITE_data/c_client.c
deleted file mode 100644
index b3a18e03d4..0000000000
--- a/lib/ic/test/c_client_erl_server_SUITE_data/c_client.c
+++ /dev/null
@@ -1,1760 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2001-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/* C-client for test of IC.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifndef __WIN32__
-# include <unistd.h>
-#endif
-
-#include <string.h>
-
-#ifdef __WIN32__
-# include <time.h>
-# include <sys/timeb.h>
-#elif defined VXWORKS
-#include <time.h>
-#include <sys/times.h>
-#else
-#include <sys/time.h>
-#endif
-
-#include <ctype.h>
-
-#ifdef __WIN32__
-# include <winsock2.h>
-# include <windows.h>
-#else
-# include <sys/types.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <arpa/inet.h>
-# include <netdb.h>
-#endif
-
-#include "ei.h"
-#include "erl_interface.h"
-#include "m_i.h"
-
-#define HOSTNAMESZ 255
-#define NODENAMESZ 512
-
-#define INBUFSZ 10
-#define OUTBUFSZ 0
-
-#define MAXTRIES 5
-
-#define CHECK_EXCEPTION(x) \
- if ((x)->_major != CORBA_NO_EXCEPTION) { \
- fprintf(stderr,"\n\nException: %s\n\n", \
- (char *)CORBA_exception_value((x))); \
- CORBA_exception_free((x)); \
- return -1; \
- } \
-
-/* XXX Should free things here too! */
-#define RETURN_IF_OK(x) \
- if ((x)) {\
- fprintf(stdout, "ok\n");\
- return 0;\
- }\
-
-#define cmp_str(x,y) (!strcmp((x),(y)))
-#define cmp_wstr(x,y) (!ic_wstrcmp((x),(y)))
-
-typedef CORBA_Environment IC_Env;
-
-typedef int (*TestFunc)(IC_Env *);
-typedef struct {
- char *name;
- TestFunc func;
-} TestCase;
-
-static char longtext[] =
-"Introduction The IC application is an IDL compiler implemented in Erlang."
-" The IDL compiler generates client stubs and server skeletons."
-" Several back-ends are supported, and they fall into three main groups."
-" For more details on IC compiler options consult the ic(3) manual page."
-" Argument passing cases 1 Caller allocates all necessary storage,"
-" except that which may be encapsulated and managed within the parameter itself."
-" 2 The caller allocates a pointer and passes it by reference to the callee."
-" The callee sets the pointer to point to a valid instance of the parameter's type."
-" The caller is responsible for releasing the returned storage."
-" Following completion of a request, the caller is not allowed to modify any values"
-" in the returned storage. To do so the caller must first copy the returned instance"
-" into a new instance, then modify the new instance. 3 The caller allocates a"
-" pointer to an array slice which has all the same dimensions of the original"
-" array except the first, and passes it by reference to the callee. The callee sets"
-" the pointer to point to a valid instance of the array. The caller is responsible for"
-" releasing the returned storage. Following completion of a request, the caller is not"
-" allowed to modify any values in the returned storage. To do so the caller must first"
-" copy the returned instance into a new instance, then modify the new instance."
-" Generated Files Two files will be generated for each scope. One set of files will be"
-" generated for each module and each interface scope. An extra set is generated for"
-" those definitions at top level scope. One of the files is a header file(.h), and the"
-" other file is a C source code file (.c). In addition to these files a number of C"
-" source files will be generated for type encodings, they are named according to the "
-"following template: oe_code_<type>.c.";
-static char this_node[NODENAMESZ + 1];
-static char *progname;
-
-/* Test function prototypes */
-
-static int void_test(IC_Env *env);
-static int long_test(IC_Env *env);
-static int long_long_test(IC_Env *env);
-static int unsigned_short_test(IC_Env *env);
-static int unsigned_long_test(IC_Env *env);
-static int unsigned_long_long_test(IC_Env *env);
-static int double_test(IC_Env *env);
-static int char_test(IC_Env *env);
-static int wchar_test(IC_Env *env);
-static int octet_test(IC_Env *env);
-static int bool_test(IC_Env *env);
-static int struct_test(IC_Env *env);
-static int struct2_test(IC_Env *env);
-static int seq1_test(IC_Env *env);
-static int seq2_test(IC_Env *env);
-static int seq3_test(IC_Env *env);
-static int seq4_test(IC_Env *env);
-static int seq5_test(IC_Env *env);
-static int array1_test(IC_Env *env);
-static int array2_test(IC_Env *env);
-static int enum_test(IC_Env *env);
-static int string1_test(IC_Env *env);
-static int string2_test(IC_Env *env);
-static int string3_test(IC_Env *env);
-static int string4_test(IC_Env *env);
-static int pid_test(IC_Env *env);
-static int port_test(IC_Env *env);
-static int ref_test(IC_Env *env);
-static int term_test(IC_Env *env);
-static int typedef_test(IC_Env *env);
-static int inline_sequence_test(IC_Env *env);
-static int term_sequence_test(IC_Env *env);
-static int term_struct_test(IC_Env *env);
-static int wstring1_test(IC_Env *env);
-
-static TestCase test_cases[] = {
- {"void_test", void_test},
- {"long_test", long_test},
- {"long_long_test", long_long_test},
- {"unsigned_short_test", unsigned_short_test},
- {"unsigned_long_test", unsigned_long_test},
- {"unsigned_long_long_test", unsigned_long_long_test},
- {"double_test", double_test},
- {"char_test", char_test},
- {"wchar_test", wchar_test},
- {"octet_test", octet_test},
- {"bool_test", bool_test},
- {"struct_test", struct_test},
- {"struct2_test", struct2_test},
- {"seq1_test", seq1_test},
- {"seq2_test", seq2_test},
- {"seq3_test", seq3_test},
- {"seq4_test", seq4_test},
- {"seq5_test", seq5_test},
- {"array1_test", array1_test},
- {"array2_test", array2_test},
- {"enum_test", enum_test},
- {"string1_test", string1_test},
- {"string2_test", string2_test},
- {"string3_test", string3_test},
- {"string4_test", string4_test},
- {"pid_test", pid_test},
- {"port_test", port_test},
- {"ref_test", ref_test},
- {"term_test", term_test},
- {"typedef_test", typedef_test},
- {"inline_sequence_test", inline_sequence_test},
- {"term_sequence_test", term_sequence_test},
- {"term_struct_test", term_struct_test},
- {"wstring1_test", wstring1_test},
- {"", NULL}
-};
-
-/* Other prototypes */
-static int cmp_aseq(m_aseq *a1, m_aseq *a2);
-static int cmp_a(m_a *a1, m_a *a2);
-static int cmp_bseq(m_bseq *b1, m_bseq *b2);
-static int cmp_b(m_b *b1, m_b *b2);
-static int cmp_lseq(m_lseq *b1, m_lseq *b2);
-static int cmp_etseq(m_etseq *b1, m_etseq *b2);
-static int cmp_et(m_et* b1, m_et *b2);
-static int cmp_es(m_es *b1, m_es *b2);
-static int cmp_arr1(m_arr1 b1, m_arr1 b2);
-static int cmp_dd(m_dd b1, m_dd b2);
-static int cmp_strRec(m_strRec *b1, m_strRec *b2);
-static int cmp_sseq(m_sseq *b1, m_sseq *b2);
-static int cmp_pid(erlang_pid *p1, erlang_pid *p2);
-static int cmp_port(erlang_port *p1, erlang_port *p2);
-static int cmp_ref(erlang_ref *p1, erlang_ref *p2);
-static int cmp_s(m_s *b1, m_s *b2);
-static int cmp_ssstr3(m_ssstr3 *b1, m_ssstr3 *b2);
-static int cmp_ssarr3(m_ssarr3 *b1, m_ssarr3 *b2);
-static int cmp_sarr3(m_sarr3 *b1, m_sarr3 *b2);
-static int cmp_arr3(m_arr3 b1, m_arr3 b2);
-
-static void print_aseq(m_aseq *a);
-static void print_a(m_a *a);
-static void print_bseq(m_bseq *b);
-static void print_lseq(m_lseq *b);
-static void print_b(m_b *b);
-static void print_etseq(m_etseq *b);
-static void print_et(m_et* b);
-static void print_es(m_es *b);
-static void print_arr1(long a[500]);
-static void print_dd(long a[2][3]);
-static void print_strRec(m_strRec* sr);
-static void print_sseq(m_sseq *b);
-static void print_pid(erlang_pid *p);
-static void print_port(erlang_port *p);
-static void print_ref(erlang_ref *p);
-static void print_term(ETERM *t);
-static void print_s(m_s *p);
-static void print_ssstr3(m_ssstr3 *b1);
-static void print_ssarr3(m_ssarr3 *b1);
-static void print_sarr3(m_sarr3 *b1);
-static void print_arr3(m_arr3 b1);
-static void print_wstr(CORBA_wchar *ws);
-
-static void free_etseq_buf(m_etseq *b);
-static void free_et(m_et* b);
-
-#ifdef __WIN32__
-typedef struct {
- long tv_sec;
- long tv_usec;
-} MyTimeval;
-#else
-typedef struct timeval MyTimeval;
-#endif
-static void my_gettimeofday(MyTimeval *tv);
-static void showtime(MyTimeval *start, MyTimeval *stop);
-static void usage(void);
-static void done(int r);
-
-
-
-/* main */
-
-#ifdef VXWORKS
-int client(int argc, char **argv)
-#else
-int main(int argc, char **argv)
-#endif
-{
- struct hostent *hp;
- erlang_pid pid;
- MyTimeval start, stop;
- int i, fd, ires, tres;
- IC_Env *env;
- int tries = 0;
- char *this_node_name = NULL;
- char *peer_node = NULL;
- char *peer_process_name = NULL;
- char *cookie = NULL;
- char host[HOSTNAMESZ + 1];
- TestFunc test_func = NULL;
- TestCase *test_case;
- char *test_case_name = NULL;
-
-#ifdef __WIN32__
- WORD wVersionRequested;
- WSADATA wsaData;
-
- wVersionRequested = MAKEWORD(2, 0);
-
- if (WSAStartup(wVersionRequested, &wsaData) != 0) {
- fprintf(stderr, "Could not load winsock2 v2.0 compatible DLL");
- exit(1);
- }
-#endif
-
- progname = argv[0];
- host[HOSTNAMESZ] = '\0';
- if (gethostname(host, HOSTNAMESZ + 1) < 0) {
- fprintf(stderr, "Can't find own hostname\n");
- done(1);
- }
- if ((hp = gethostbyname(host)) == 0) {
- fprintf(stderr, "Can't get ip address for host %s\n", host);
- done(1);
- }
- for (i = 1; i < argc; i++) {
- if (cmp_str(argv[i], "-help")) {
- usage();
- done(0);
- } else if (cmp_str(argv[i], "-this-node-name")) {
- i++;
- this_node_name = argv[i];
- } else if (cmp_str(argv[i], "-peer-node")) {
- i++;
- peer_node = argv[i];
- } else if (cmp_str(argv[i], "-peer-process-name")) {
- i++;
- peer_process_name = argv[i];
- } else if (cmp_str(argv[i], "-cookie")) {
- i++;
- cookie = argv[i];
- } else if (cmp_str(argv[i], "-test-case")) {
- i++;
- test_case_name = argv[i];
- } else {
- fprintf(stderr, "Error : invalid argument \"%s\"\n", argv[i]);
- usage();
- done(1);
- }
- }
-
- if (this_node_name == NULL || peer_node == NULL || test_case_name == NULL
- || peer_process_name == NULL || cookie == NULL) {
- fprintf(stderr, "Error: missing option\n");
- usage();
- done(1);
- }
-
- test_case = test_cases;
- while (test_case->func) {
- if (cmp_str(test_case->name, test_case_name)) {
- test_func = test_case->func;
- break;
- }
- test_case++;
- }
- if (test_func == NULL) {
- fprintf(stderr, "Error: illegal test case: \"%s\"\n", test_case_name);
- done(1);
- }
-
- /* Behead hostname at first dot */
- for (i=0; host[i] != '\0'; i++) {
- if (host[i] == '.') { host[i] = '\0'; break; }
- }
- sprintf(this_node, "%s@%s", this_node_name, host);
- fprintf(stderr, "c_client: this node: \"%s\"\n", this_node);
- fprintf(stderr, "c_client: peer node: \"%s\"\n", peer_node);
- fprintf(stderr, "c_client: test case: \"%s\"\n", test_case_name);
-
- fprintf(stderr, "c_client: starting\n");
-
- /* initialize erl_interface */
- erl_init(NULL, 0);
-
- for (tries = 0; tries < MAXTRIES; tries++) {
-
- /* connect to erlang node */
-
- ires = erl_connect_xinit(host, this_node_name, this_node,
- (struct in_addr *)*hp->h_addr_list,
- cookie, 0);
-
- fprintf(stderr, "c_client: erl_connect_xinit(): %d\n", ires);
-
- fd = erl_connect(peer_node);
- fprintf(stderr, "c_client: erl_connect(): %d\n", fd);
-
- if (fd >= 0)
- break;
- fprintf(stderr, "c_client: cannot connect, retrying\n");
- }
- if (fd < 0) {
- fprintf(stderr, "c_client: cannot connect, exiting\n");
- done(1);
- }
- env = CORBA_Environment_alloc(INBUFSZ, OUTBUFSZ);
- env->_fd = fd;
- strcpy(env->_regname, peer_process_name);
- env->_to_pid = NULL;
- env->_from_pid = &pid;
-
- strcpy(pid.node, this_node);
- pid.num = fd;
- pid.serial = 0;
- pid.creation = 0;
-
- my_gettimeofday(&start);
- tres = test_func(env); /* Call test case */
- my_gettimeofday(&stop);
- showtime(&start, &stop);
- erl_close_connection(fd);
-
- printf("c_client: env->_inbuf before : %d\n", INBUFSZ);
- printf("c_client: env->_outbuf before : %d\n", OUTBUFSZ);
- printf("c_client: env->_inbuf after : %d\n", env->_inbufsz);
- printf("c_client: env->_outbuf after : %d\n", env->_outbufsz);
-
- CORBA_free(env->_inbuf);
- CORBA_free(env->_outbuf);
- CORBA_free(env);
- done(tres);
-}
-
-static void usage()
-{
- fprintf(stderr, "Usage: %s [-help] -this-node-name <name> "
- "-peer-node <nodename> -peer-process-name <name> "
- "-cookie <cookie> -test-case <test case name>\n", progname);
- fprintf(stderr, "Example:\n %s -this-node-name kalle "
- "-peer-node olle@home -peer-process-name idltest "
- "-cookie oa678er -test-case octet_test\n", progname);
-}
-
-static void done(int r)
-{
-#ifdef __WIN32__
- WSACleanup();
-#endif
- exit(r);
-}
-
-
-/* TESTS */
-
-static int void_test(IC_Env *env)
-{
- fprintf(stdout, "\n======== m_i_void test ======\n\n");
- m_i_void_test(NULL,env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(1);
-}
-
-static int long_test(IC_Env *env)
-{
- long l = 4711, lo, lr;
-
- fprintf(stdout, "\n======== m_i_long test ======\n\n");
- lr = m_i_long_test(NULL, l, &lo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(l == lo && l == lr);
- if (l != lo)
- fprintf(stdout, " out parameter error, sent: %ld, got: %ld\n", l, lo);
- if (l != lr)
- fprintf(stdout, " result error, sent: %ld, got: %ld\n", l, lr);
- return -1;
-}
-
-static int long_long_test(IC_Env *env)
-{
- CORBA_long_long ll = 4711, llo, llr;
-
- fprintf(stdout, "\n======== m_i_longlong test ======\n\n");
- llr = m_i_longlong_test(NULL, ll, &llo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(ll == llo && ll == llr);
- if (ll != llo)
- fprintf(stdout, " out parameter error, sent: %ld, got: %ld\n",
- ll, llo);
- if (ll != llr)
- fprintf(stdout, " result error, sent: %ld, got: %ld\n", ll, llr);
- return -1;
-}
-
-static int unsigned_short_test(IC_Env *env)
-{
- unsigned short x, y = 2, z;
-
- fprintf(stdout, "\n======== m_i_ushort test ======\n\n");
- x = m_i_ushort_test(NULL, y, &z, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(y == z && y == x);
- if (y != z)
- fprintf(stdout, " out parameter error, sent: %d, got: %d\n", y, z);
- if (y != x)
- fprintf(stdout, " result error, sent: %d, got: %d\n", y, x);
- return -1;
-}
-
-
-static int unsigned_long_test(IC_Env *env)
-{
- unsigned long ul = 5050, ulo, ulr;
-
- fprintf(stdout, "\n======== m_i_ulong test ======\n\n");
- ulr = m_i_ulong_test(NULL, ul, &ulo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(ul == ulo && ul == ulr);
- if (ul != ulo)
- fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n",
- ul, ulo);
- if (ul != ulr)
- fprintf(stdout, " result error, sent: %lu, got: %lu\n", ul, ulr);
- return -1;
-}
-
-/*
- * Note: CORBA_unsigned_long_long is in fact a plain long.
- */
-static int unsigned_long_long_test(IC_Env *env)
-{
- CORBA_unsigned_long_long ull = 5050, ullo, ullr;
-
- fprintf(stdout, "\n======== m_i_ulonglong test ======\n\n");
- ullr = m_i_ulonglong_test(NULL, ull, &ullo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(ull == ullo && ull == ullr);
- if (ull != ullo)
- fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n",
- ull, ullo);
- if (ull != ullr)
- fprintf(stdout, " result error, sent: %lu, got: %lu\n",
- ull, ullr);
- return -1;
-}
-
-static int double_test(IC_Env *env)
-{
- double d = 12.1212, db, dr;
-
- fprintf(stdout, "\n======== m_i_double test ======\n\n");
- dr = m_i_double_test(NULL, d, &db, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(d == db && d == dr);
- if (d != db)
- fprintf(stdout, " out parameter error, sent: %f, got: %f\n", d, db);
- if (d != dr)
- fprintf(stdout, " result error, sent: %f, got: %f\n", d, dr);
- return -1;
-}
-
-static int char_test(IC_Env *env)
-{
- char c = 'g', co, cr;
-
- /* char test */
- fprintf(stdout, "\n======== m_i_char test ======\n\n");
- cr = m_i_char_test(NULL, c, &co, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(c == co && c == cr);
- if (c !=co)
- fprintf(stdout, " out parameter error, sent: %c, got: %c\n", c, co);
- if (c != cr)
- fprintf(stdout, " result error, sent: %c, got: %c\n", c, cr);
- return -1;
-}
-
-static int wchar_test(IC_Env *env)
-{
- CORBA_wchar wc = 103, wco, wcr;
-
- fprintf(stdout, "\n======== m_i_wchar test ======\n\n");
- wcr = m_i_wchar_test(NULL, wc, &wco, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(wc == wco && wc == wcr);
- if (wc != wco)
- fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n",
- wc, wco);
- if (wc != wcr)
- fprintf(stdout, " result error, sent: %lu, got: %lu\n",
- wc, wcr);
- return -1;
-}
-
-static int octet_test(IC_Env *env)
-{
- char o ='r', oo, or;
-
- fprintf(stdout, "\n======== m_i_octet test ======\n\n");
- or = m_i_octet_test(NULL, o, &oo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(o == oo && o == or);
- if (o != oo)
- fprintf(stdout, " out parameter error, sent: %c, got: %c\n", o, oo);
- if (o != or)
- fprintf(stdout, " result error, sent: %c, got: %c\n", o, or);
- return -1;
-}
-
-static int bool_test(IC_Env *env)
-{
- unsigned char i = 0, io, ir;
-
- fprintf(stdout, "\n======== m_i_bool test ======\n\n");
- ir = m_i_bool_test(NULL, i, &io, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(i == io && i == ir);
- if (i != io)
- fprintf(stdout, " out parameter error, sent: %d, got: %d\n", i, io);
- if (i != ir)
- fprintf(stdout, " result error, sent: %d, got: %d\n", i, ir);
- return -1;
-}
-
-static int struct_test(IC_Env *env)
-{
- m_b b = {4711, 'a'}, bo, br;
-
- fprintf(stdout, "\n======== m_i_struct test ======\n\n");
- br = m_i_struct_test(NULL, &b, &bo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_b(&b, &bo) && cmp_b(&b, &br));
- if (!cmp_b(&b, &bo)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_b(&b);
- fprintf(stdout, " got:\n");
- print_b(&bo);
- fprintf(stdout, "\n");
- }
- if (!cmp_b(&b, &br)) {
- fprintf(stdout, " result error, sent:\n");
- print_b(&b);
- fprintf(stdout, " got:\n");
- print_b(&br);
- fprintf(stdout, "\n");
- }
- return -1;
-}
-
-static int struct2_test(IC_Env *env)
-{
- m_es esi = {m_peach, 5050}, eso, esr;
-
- fprintf(stdout, "\n======== m_i_struct2 test ======\n\n");
- esr = m_i_struct2_test(NULL, &esi, &eso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_es(&esi, &eso) && cmp_es(&esi, &esr));
- if (!cmp_es(&esi, &eso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_es(&esi);
- fprintf(stdout, " got:\n");
- print_es(&eso);
- fprintf(stdout, "\n");
- }
- if (!cmp_es(&esi, &esr)) {
- fprintf(stdout, " result error, sent:\n");
- print_es(&esi);
- fprintf(stdout, " got:\n");
- print_es(&esr);
- fprintf(stdout, "\n");
- }
- return -1;
-}
-
-
-static int seq1_test(IC_Env *env)
-{
- m_bseq bs, *bso, *bsr;
-
- m_b ba[3] = {{4711, 'a'}, {4712, 'b'}, {4713, 'c'}};
- bs._length = 3;
- bs._buffer = ba;
-
- fprintf(stdout, "\n======== m_i_seq1 test ======\n\n");
- bsr = m_i_seq1_test(NULL, &bs, &bso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_bseq(&bs, bso) && cmp_bseq(&bs, bsr));
- if (!cmp_bseq(&bs, bso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_bseq(&bs);
- fprintf(stdout, " got:\n");
- print_bseq(bso);
- fprintf(stdout, "\n");
- }
- if (!cmp_bseq(&bs, bsr)) {
- fprintf(stdout, " result error, sent:\n");
- print_bseq(&bs);
- fprintf(stdout, " got:\n");
- print_bseq(bsr);
- fprintf(stdout, "\n");
- }
- CORBA_free(bso);
- CORBA_free(bsr);
- return -1;
-}
-
-static int seq2_test(IC_Env *env)
-{
- m_b ba[3] = {{4711, 'a'}, {4712, 'b'}, {4713, 'c'}};
- m_a a;
- m_a aa[2];
- m_aseq as, *aso, *asr;
-
- a.l = 9999;
- a.y._length = 3;
- a.y._buffer = ba;
- a.d = 66.89898989;
-
- aa[0] = a;
- aa[1] = a;
- as._length = 2;
- as._buffer = aa;
-
- fprintf(stdout, "\n======== m_i_seq2 test ======\n\n");
- asr = m_i_seq2_test(NULL, &as, &aso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_aseq(&as, aso) && cmp_aseq(&as, asr));
- if (!cmp_aseq(&as, aso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_aseq(&as);
- fprintf(stdout, " got:\n");
- print_aseq(aso);
- fprintf(stdout, "\n");
- }
- if (!cmp_aseq(&as, asr)) {
- fprintf(stdout, " result error, sent:\n");
- print_aseq(&as);
- fprintf(stdout, " got:\n");
- print_aseq(asr);
- fprintf(stdout, "\n");
- }
- CORBA_free(aso);
- CORBA_free(asr);
- return -1;
-}
-
-static int seq3_test(IC_Env *env)
-{
- m_lseq lsi, *lso, *lsr;
- long al[500];
- int i=0;
-
- for (i = 0; i < 500; i++)
- al[i]=i;
- lsi._length = 500;
- lsi._buffer = al;
-
- fprintf(stdout, "\n======== m_i_seq3 test ======\n\n");
- lsr = m_i_seq3_test(NULL, &lsi, &lso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_lseq(&lsi, lso) && cmp_lseq(&lsi, lsr));
- if (!cmp_lseq(&lsi, lso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_lseq(&lsi);
- fprintf(stdout, " got:\n");
- print_lseq(lso);
- fprintf(stdout, "\n");
- }
- if (!cmp_lseq(&lsi, lsr)) {
- fprintf(stdout, " result error, sent:\n");
- print_lseq(&lsi);
- fprintf(stdout, " got:\n");
- print_lseq(lsr);
- fprintf(stdout, "\n");
- }
- CORBA_free(lso);
- CORBA_free(lsr);
- return -1;
-}
-
-static int seq4_test(IC_Env *env)
-{
- char *stra0[3] = {"a", "long", "time"};
- char *stra1[3] = {"ago", "there", "was"};
- char *stra2[3] = {"a", "buggy", "compiler"};
- m_sstr3 str3s[3] = {{3, 3, stra0}, {3, 3, stra1}, {3, 3, stra2}};
- m_ssstr3 str3ssi = {3, 3, str3s};
- m_ssstr3 *str3sso, *str3ssr;
-
- fprintf(stdout, "\n======== m_i_seq4 test ======\n\n");
- str3ssr = m_i_seq4_test(NULL, &str3ssi, &str3sso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_ssstr3(&str3ssi, str3sso) &&
- cmp_ssstr3(&str3ssi, str3ssr));
- if (!cmp_ssstr3(&str3ssi, str3sso)){
- fprintf(stdout, " out parameter error, sent:\n");
- print_ssstr3(&str3ssi);
- fprintf(stdout, " got:\n");
- print_ssstr3(str3sso);
- fprintf(stdout, "\n");
- }
- if (!cmp_ssstr3(&str3ssi, str3ssr)) {
- fprintf(stdout, " result error, sent:\n");
- print_ssstr3(&str3ssi);
- fprintf(stdout, " got:\n");
- print_ssstr3(str3ssr);
- fprintf(stdout, "\n");
- }
- CORBA_free(str3sso);
- CORBA_free(str3ssr);
- return -1;
-}
-
-static int seq5_test(IC_Env *env)
-{
- m_arr3 arr3a[3] = {
- {4711, 18931947, 3},
- {4711, 18931947, 3},
- {4711, 18931947, 3}};
- m_sarr3 arr3sa[3] = {{3, 3, arr3a}, {3, 3, arr3a}, {3, 3, arr3a}};
- m_ssarr3 arr3ssi = {3, 3, arr3sa};
- m_ssarr3 *arr3sso;
- m_ssarr3 *arr3ssr;
-
- fprintf(stdout, "\n======== m_i_seq5 test ======\n\n");
- arr3ssr = m_i_seq5_test(NULL, &arr3ssi, &arr3sso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_ssarr3(&arr3ssi, arr3sso) &&
- cmp_ssarr3(&arr3ssi, arr3ssr));
- if (!cmp_ssarr3(&arr3ssi, arr3sso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_ssarr3(&arr3ssi);
- fprintf(stdout, " got:\n");
- print_ssarr3(arr3sso);
- fprintf(stdout, "\n");
- }
- if (!cmp_ssarr3(&arr3ssi, arr3ssr)) {
- fprintf(stdout, " result error, sent:\n");
- print_ssarr3(&arr3ssi);
- fprintf(stdout, " got:\n");
- print_ssarr3(arr3ssr);
- fprintf(stdout, "\n");
- }
- CORBA_free(arr3sso);
- CORBA_free(arr3ssr);
- return -1;
-}
-
-static int array1_test(IC_Env *env)
-{
- int i;
- long al[500];
- m_arr1 alo;
- m_arr1_slice* alr;
-
- for (i = 0; i < 500; i++)
- al[i]=i;
-
- fprintf(stdout, "\n======== m_i_array1 test ======\n\n");
- alr = m_i_array1_test(NULL, al, alo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_arr1(al, alo) && cmp_arr1(al, alr));
- if (!cmp_arr1(al, alo)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_arr1(al);
- fprintf(stdout, " got:\n");
- print_arr1(alo);
- fprintf(stdout, "\n");
- }
- if (!cmp_arr1(al,alr)) {
- fprintf(stdout, " result error, sent:\n");
- print_arr1(al);
- fprintf(stdout, " got:\n");
- print_arr1(alr);
- fprintf(stdout, "\n");
- }
- free(alr);
- return -1;
-}
-
-static int array2_test(IC_Env *env)
-{
- long dl[2][3] = {{11, 2, 7}, {22, 8 ,13}};
- m_dd dlo;
- m_dd_slice* dlr;
-
- fprintf(stdout, "\n======== m_i_array2 test ======\n\n");
- dlr = m_i_array2_test(NULL, dl, dlo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_dd(dl,dlo) && cmp_dd(dl,dlr));
- if (!cmp_dd(dl,dlo)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_dd(dl);
- fprintf(stdout, " got:\n");
- print_dd(dlo);
- fprintf(stdout, "\n");
- }
- if (!cmp_dd(dl,dlr)) {
- fprintf(stdout, " result error, sent:\n");
- print_dd(dl);
- fprintf(stdout, " got:\n");
- print_dd(dlr);
- fprintf(stdout, "\n");
- }
- free(*dlr);
- return -1;
-}
-
-static int enum_test(IC_Env *env)
-{
- m_fruit ei = m_banana, eo, er;
-
- fprintf(stdout, "\n======== m_i_enum test ======\n\n");
- er = m_i_enum_test(NULL, ei, &eo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(ei == eo && ei == er);
- if (ei != eo)
- fprintf(stdout, " out parameter error, sent: %d, got: %d\n", ei, eo);
- if (ei != er)
- fprintf(stdout, " result error, sent: %d, got: %d\n", ei, er);
- return -1;
-}
-
-static int string1_test(IC_Env *env)
-{
- char* si = longtext;
- char* so;
- char* sr;
-
- fprintf(stdout, "\n======== m_i_string1 test ======\n\n");
- sr = m_i_string1_test(NULL, si, &so, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_str(si, so) && cmp_str(si, sr));
- if (!cmp_str(si, so))
- fprintf(stdout, " out parameter error, sent: %s, got: %s\n", si, so);
- if (!cmp_str(si, sr))
- fprintf(stdout, " result error, sent: %s, got: %s\n", si, sr);
- CORBA_free(so);
- CORBA_free(sr);
- return -1;
-}
-
-static int string2_test(IC_Env *env)
-{
- char* sa[3] = {"hello", "foo", "bar"};
- m_sseq ssi = {3, 3, sa};
- m_sseq *sso, *ssr;
-
- fprintf(stdout, "\n======== m_i_string2 test ======\n\n");
- ssr = m_i_string2_test(NULL, &ssi, &sso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_sseq(&ssi, sso) && cmp_sseq(&ssi, sso));
- if (!cmp_sseq(&ssi, sso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_sseq(&ssi);
- fprintf(stdout, "got:\n");
- print_sseq(sso);
- }
- if (!cmp_sseq(&ssi, ssr)) {
- fprintf(stdout, " result error, sent:\n");
- print_sseq(&ssi);
- fprintf(stdout, "got:\n");
- print_sseq(ssr);
- }
- CORBA_free(sso);
- CORBA_free(ssr);
- return -1;
-}
-
-static int string3_test(IC_Env *env)
-{
- char* si = longtext;
- char* so;
- char* sr;
-
- fprintf(stdout, "\n======== m_i_string3 test ======\n\n");
- sr = m_i_string3_test(NULL, si, &so, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_str(si, so) && cmp_str(si, so));
- if (!cmp_str(si, so))
- fprintf(stdout, " out parameter error, sent: %s, got: %s\n", si, so);
- if (!cmp_str(si, sr))
- fprintf(stdout, " result error, sent: %s, got: %s\n", si, sr);
- CORBA_free(so);
- CORBA_free(sr);
- return -1;
-}
-
-static int string4_test(IC_Env *env)
-{
- char as1[100] = "a string", as2[200] = "help", as3[200] = "hello there";
- m_strRec stri = { 1, /* dd */
- as1, /* str4 */
- {{'a', 'k'}, {'z', 'g'}, {'n', 'q'}}, /* str7 */
- {3, 3, "buf"}, /* str5 */
- as2, /* str6 */
- {'m', 'f', 'o'}, /* str8 */
- as3, /* str9 */
- {3, 3, "stu"} /* str10 */
- };
- m_strRec *stro, *strr;
-
- fprintf(stdout, "\n======== m_i_string4 test ======\n\n");
- strr = m_i_string4_test(NULL, &stri, &stro, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_strRec(&stri,stro) && cmp_strRec(&stri,strr));
- if (!cmp_strRec(&stri,stro)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_strRec(&stri);
- fprintf(stdout, " got:\n");
- print_strRec(stro);
- fprintf(stdout, "\n");
- }
- if (!cmp_strRec(&stri,strr)) {
- fprintf(stdout, " result error, sent:\n");
- print_strRec(&stri);
- fprintf(stdout, " got:\n");
- print_strRec(strr);
- fprintf(stdout, "\n");
- }
- CORBA_free(stro);
- CORBA_free(strr);
- return -1;
-}
-
-
-static int pid_test(IC_Env *env)
-{
- erlang_pid pid = {"", 7, 0, 0}, pido, pidr;
-
- strcpy(pid.node, this_node), /* this currently running node */
- fprintf(stdout, "\n======== m_i_pid test ======\n\n");
- pidr = m_i_pid_test(NULL, &pid, &pido, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_pid(&pid, &pido) && cmp_pid(&pid, &pidr));
- if (!cmp_pid(&pid, &pido)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_pid(&pid);
- fprintf(stdout, "got:\n");
- print_pid(&pido);
- }
- if (!cmp_pid(&pid, &pidr)) {
- fprintf(stdout, " result error, sent:\n");
- print_pid(&pid);
- fprintf(stdout, "got:\n");
- print_pid(&pidr);
- }
- return -1;
-}
-
-static int port_test(IC_Env *env)
-{
- erlang_port porti = {"node", 5, 1}, porto, portr;
-
- fprintf(stdout, "\n======== m_i_port test ======\n\n");
- portr = m_i_port_test(NULL, &porti, &porto, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_port(&porti, &porto) && cmp_port(&porti, &portr));
- if (!cmp_port(&porti, &porto)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_port(&porti);
- fprintf(stdout, "got:\n");
- print_port(&porto);
- }
- if (!cmp_port(&porti, &portr)) {
- fprintf(stdout, " result error, sent:\n");
- print_port(&porti);
- fprintf(stdout, "got:\n");
- print_port(&portr);
- }
- return -1;
-}
-
-static int ref_test(IC_Env *env)
-{
- erlang_ref refi = { "node1", 3, {1, 2, 3}, 1},
- refo, refr;
-
- fprintf(stdout, "\n======== m_i_ref test ======\n\n");
- refr = m_i_ref_test(NULL, &refi, &refo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_ref(&refi, &refo) && cmp_ref(&refi, &refr));
- if (!cmp_ref(&refi, &refo)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_ref(&refi);
- fprintf(stdout, "got:\n");
- print_ref(&refo);
- }
- if (!cmp_ref(&refi, &refr)) {
- fprintf(stdout, " result error, sent:\n");
- print_ref(&refi);
- fprintf(stdout, "got:\n");
- print_ref(&refr);
- }
- return -1;
-}
-
-static int term_test(IC_Env *env)
-{
- ETERM *ti, *to, *tr;
-
- ti = erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]");
-
- fprintf(stdout, "\n======== m_i_term test ======\n\n");
- tr = m_i_term_test(NULL, ti, &to, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(erl_match(ti, to) && erl_match(ti, tr));
- if (!erl_match(ti, to)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_term(ti);
- fprintf(stdout, "got:\n");
- print_term(to);
- }
- if (!erl_match(ti, tr)) {
- fprintf(stdout, " result error, sent:\n");
- print_term(ti);
- fprintf(stdout, "got:\n");
- print_term(tr);
- }
- erl_free_term(ti);
- erl_free_term(to);
- erl_free_term(tr);
- return -1;
-}
-
-static int typedef_test(IC_Env *env)
-{
- m_banan mbi, mbo; /* erlang_port */
- m_apa mai; /* ETERM* */
- m_apa mao = NULL;
- long tl;
-
- strcpy(mbi.node,"node");
- mbi.id = 15;
- mbi.creation = 1;
-
- fprintf(stdout, "\n======== m_i_typedef test ======\n\n");
- mai = erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]");
- tl = m_i_typedef_test(NULL, mai, &mbi, &mao, &mbo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(erl_match(mai, mao) && cmp_port(&mbi, &mbo) && tl == 4711);
- if (!erl_match(mai, mao)) {
- fprintf(stdout, " out parameter error (term), sent:\n");
- print_term(mai);
- fprintf(stdout, "got:\n");
- print_term(mao);
- }
- if (!cmp_port(&mbi, &mbo)) {
- fprintf(stdout, " out parameter error (port), sent:\n");
- print_port(&mbi);
- fprintf(stdout, "got:\n");
- print_port(&mbo);
- }
- if (tl != 4711) {
- fprintf(stdout, " result error, sent: 4711, got %ld\n", tl);
- }
- erl_free_term(mai);
- erl_free_term(mao);
- return -1;
-}
-
-static int inline_sequence_test(IC_Env *env)
-{
- int i;
- long al[500];
- m_s isi = {4711, {500, 10, al}},
- *iso, *isr;
-
- for (i = 0; i < 500; i++)
- al[i]=i;
- fprintf(stdout, "\n======== m_i_inline_sequence test ======\n\n");
- isr = m_i_inline_sequence_test(NULL, &isi, &iso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_s(&isi, iso) && cmp_s(&isi, isr));
- if (!cmp_s(&isi, iso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_s(&isi);
- fprintf(stdout, "got:\n");
- print_s(iso);
- }
- if (!cmp_s(&isi, isr)) {
- fprintf(stdout, " result error, sent:\n");
- print_s(&isi);
- fprintf(stdout, "got:\n");
- print_s(isr);
- }
- CORBA_free(iso);
- CORBA_free(isr);
- return -1;
-}
-
-static int term_sequence_test(IC_Env *env)
-{
- ETERM* et_array[4] = {
- erl_format("[{apa, 1, 23}, \"string\", {1.23, 45}]"),
- erl_format("[{banan, 1, 23}, \"string\", {1.23, 45}]"),
- erl_format("[{apelsin, 1, 23}, \"string\", {1.23, 45}]"),
- erl_format("[{mango, 1, 23}, \"string\", {1.23, 45}]")};
- m_etseq etsi = {4, 4, et_array}, *etso, *etsr;
-
- fprintf(stdout, "\n======== m_i_term_sequence test ======\n\n");
- etsr = m_i_term_sequence_test(NULL, &etsi, &etso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_etseq(&etsi, etso) && cmp_etseq(&etsi, etsr));
- if (!cmp_etseq(&etsi, etso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_etseq(&etsi);
- fprintf(stdout, "got:\n");
- print_etseq(etso);
- }
- if (!cmp_etseq(&etsi, etsr)) {
- fprintf(stdout, " result error, sent:\n");
- print_etseq(&etsi);
- fprintf(stdout, "got:\n");
- print_etseq(etsr);
- }
- free_etseq_buf(&etsi);
- free_etseq_buf(etso);
- free_etseq_buf(etsr);
- CORBA_free(etso);
- CORBA_free(etsr);
- return -1;
-}
-
-static int term_struct_test(IC_Env *env)
-{
- m_et eti = { erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]"),
- 121212 };
- m_et eto, etr;
-
- fprintf(stdout, "\n======== m_i_term_struct test ======\n\n");
- etr = m_i_term_struct_test(NULL, &eti, &eto, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_et(&eti, &eto) && cmp_et(&eti, &etr));
- if (!cmp_et(&eti, &eto)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_et(&eti);
- fprintf(stdout, "got:\n");
- print_et(&eto);
- }
- if (!cmp_et(&eti, &etr)) {
- fprintf(stdout, " result error, sent:\n");
- print_et(&eti);
- fprintf(stdout, "got:\n");
- print_et(&etr);
- }
- free_et(&eti);
- free_et(&eto);
- free_et(&etr);
- return -1;
-}
-
-static int wstring1_test(IC_Env *env)
-{
- CORBA_wchar wsi[] = {100, 101, 102, 103, 104, 0}, *wso, *wsr;
-
- fprintf(stdout, "\n======== m_i_wstring1 test ======\n\n");
- wsr = m_i_wstring1_test(NULL, wsi, &wso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_wstr(wsi, wso) && cmp_wstr(wsi, wsr));
- if (!cmp_wstr(wsi, wso)) {
- fprintf(stdout, " out parameter error, sent: \n");
- print_wstr(wsi);
- fprintf(stdout, "got:\n");
- print_wstr(wso);
- }
- if (!cmp_wstr(wsi, wsr)) {
- fprintf(stdout, " result error, sent: \n");
- print_wstr(wsi);
- fprintf(stdout, "got:\n");
- print_wstr(wsr);
- }
- CORBA_free(wso);
- CORBA_free(wsr);
- return -1;
-}
-
-/* Compare functions */
-static int cmp_aseq(m_aseq *a1, m_aseq *a2)
-{
- int i;
-
- if (a1->_length != a2->_length)
- return 0;
- for (i = 0; i < a1->_length; i++)
- if (cmp_a(&(a1->_buffer[i]), &(a2->_buffer[i])) == 0)
- return 0;
- return 1;
-}
-
-static int cmp_a(m_a *a1, m_a *a2)
-{
- return a1->l == a2->l &&
- a1->d == a2->d &&
- cmp_bseq(&a1->y, &a2->y);
-}
-
-static int cmp_bseq(m_bseq *b1, m_bseq *b2)
-{
- int i;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++)
- if (cmp_b(&(b1->_buffer[i]), &(b2->_buffer[i])) == 0)
- return 0;
- return 1;
-}
-
-static int cmp_b(m_b *b1, m_b *b2)
-{
- return b1->l == b2->l && b1->c == b2->c;
-}
-
-static int cmp_lseq(m_lseq *b1, m_lseq *b2)
-{
- int i;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++)
- if (b1->_buffer[i] != b2->_buffer[i])
- return 0;
- return 1;
-}
-
-static int cmp_etseq(m_etseq *b1, m_etseq *b2)
-{
- int i;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++)
- if (!erl_match(b1->_buffer[i], b2->_buffer[i]))
- return 0;
- return 1;
-}
-
-static int cmp_et(m_et* b1, m_et *b2)
-{
- return erl_match(b1->e, b2->e) && b1->l == b2->l;
-}
-
-static int cmp_es(m_es *b1, m_es *b2)
-{
- return b1->f == b2->f && b1->l == b2->l;
-}
-
-static int cmp_arr1(m_arr1 b1, m_arr1 b2)
-{
- int i;
-
- for (i = 0; i < 500; i++)
- if (b1[i] != b2[i])
- return 0;
- return 1;
-}
-
-static int cmp_dd(m_dd b1, m_dd b2)
-{
-
- int i, j;
-
- for (i = 0; i < 2; i++)
- for (j = 0; j < 3; j++)
- if (b1[i][j] != b2[i][j])
- return 0;
- return 1;
-}
-
-
-
-static int cmp_strRec(m_strRec *b1, m_strRec *b2)
-{
- int i, j;
-
- if (b1->bb != b2->bb)
- return 0;
- if (!cmp_str(b1->str4,b2->str4))
- return 0;
- if (b1->str5._length != b2->str5._length)
- return 0;
- for (j = 0; j < b1->str5._length; j++)
- if (b1->str5._buffer[j] != b2->str5._buffer[j])
- return 0;
- if (!cmp_str(b1->str6,b2->str6))
- return 0;
- for (i = 0; i < 2; i++)
- for (j = 0; j < 3; j++)
- if (b1->str7[i][j] != b2->str7[i][j])
- return 0;
- for (j = 0; j < 3; j++)
- if (b1->str8[j] != b2->str8[j])
- return 0;
- if (!cmp_str(b1->str9,b2->str9))
- return 0;
- if (b1->str10._length != b2->str10._length)
- return 0;
- for (j = 0; j < b1->str10._length; j++)
- if (b1->str10._buffer[j] != b2->str10._buffer[j])
- return 0;
- return 1;
-}
-
-
-static int cmp_sseq(m_sseq *b1, m_sseq *b2)
-{
- int i;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++)
- if (!cmp_str(b1->_buffer[i], b2->_buffer[i]))
- return 0;
- return 1;
-}
-
-
-static int cmp_pid(erlang_pid *p1, erlang_pid *p2)
-{
- return cmp_str(p1->node,p2-> node) &&
- p1->num == p2->num &&
- p1->serial == p2->serial &&
- p1->creation == p2->creation;
-}
-
-static int cmp_port(erlang_port *p1, erlang_port *p2)
-{
- return cmp_str(p1->node,p2-> node) && p1->id == p2->id;
-}
-
-static int cmp_ref(erlang_ref *p1, erlang_ref *p2)
-{
- return cmp_str(p1->node, p2->node) &&
- p1->len == p2->len &&
- (p1->len < 1 || p1->n[0] == p2->n[0]) &&
- (p1->len < 2 || p1->n[1] == p2->n[1]) &&
- (p1->len < 3 || p1->n[2] == p2->n[2]);
-}
-
-static int cmp_s(m_s *b1, m_s *b2)
-{
- int i;
-
- if (b1->l != b2->l)
- return 0;
- if (b1->sl._length != b2->sl._length)
- return 0;
- for (i = 0; i < b1->sl._length; i++)
- if (b1->sl._buffer[i] != b2->sl._buffer[i])
- return 0;
- return 1;
-}
-
-
-static int cmp_ssstr3(m_ssstr3 *b1, m_ssstr3 *b2)
-{
- int i,j;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++) {
- if (b1->_buffer[i]._length != b2->_buffer[i]._length)
- return 0;
- for (j = 0; j < b1->_buffer[i]._length; j++)
- if (!cmp_str(b1->_buffer[i]._buffer[j],
- b2->_buffer[i]._buffer[j]))
- return 0;
- }
- return 1;
-}
-
-
-
-static int cmp_ssarr3(m_ssarr3 *b1, m_ssarr3 *b2)
-{
- int i;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++) {
- if (!cmp_sarr3(&b1->_buffer[i], &b2->_buffer[i]))
- return 0;
- }
- return 1;
-}
-
-static int cmp_sarr3(m_sarr3 *b1, m_sarr3 *b2)
-{
- int i;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++) {
- if (!cmp_arr3(b1->_buffer[i], b2->_buffer[i]))
- return 0;
- }
- return 1;
-}
-
-static int cmp_arr3(m_arr3 b1, m_arr3 b2)
-{
- int i;
-
- for (i = 0; i < sizeof(m_arr3)/sizeof(CORBA_long); i++) {
- if (b1[i] != b2[i])
- return 0;
- }
- return 1;
-}
-
-/* Print functions */
-static void print_aseq(m_aseq *a)
-{
- int i;
- fprintf(stdout, "\nm_aseq size: %ld --------\n", a->_length);
- for (i = 0; i < a->_length; i++)
- print_a(&(a->_buffer[i]));
-}
-
-static void print_a(m_a *a)
-{
- fprintf(stdout, "\nm_a --------\n l: %ld\n d:%f\n", a->l, a->d);
- print_bseq(&a->y);
-}
-
-static void print_bseq(m_bseq *b)
-{
- int i;
-
- fprintf(stdout, "\nm_bseq size: %ld --------\n",b->_length);
- for (i = 0; i < b->_length; i++)
- print_b(&(b->_buffer[i]));
-}
-
-static void print_lseq(m_lseq *b)
-{
- int i;
-
- fprintf(stdout, "\nm_lseq size: %ld --------\n",b->_length);
- for (i = 0; i < b->_length; i++)
- fprintf(stdout, "[%d]: %ld\n", i, b->_buffer[i]);
-}
-
-static void print_b(m_b *b)
-{
- fprintf(stdout, "\nm_b --------\n l: %ld\n c: %c\n", b->l, b->c);
-}
-
-
-static void print_etseq(m_etseq *b)
-{
- int i;
-
- for (i = 0; i < b->_length; i++) {
- fprintf(stdout, "[%d]:\n", i);
- erl_print_term(stdout, b->_buffer[i]);
- }
-}
-
-
-static void print_et(m_et* b)
-{
- fprintf(stdout, "\net struct --------\n");
- erl_print_term(stdout, b->e);
- fprintf(stdout, "long: %ld\n", b->l);
- fprintf(stdout, "\n--------\n");
-}
-
-static void print_es(m_es *b)
-{
- fprintf(stdout, "\nm_es --------\n f: %d\n l: %ld\n", b->f, b->l);
-}
-
-
-static void print_arr1(long a[10])
-{
- int i;
-
- for (i = 0; i < 10; i++)
- fprintf(stdout, "\n[%d]: %ld\n", i, a[i]);
-}
-
-static void print_dd(long a[2][3])
-{
- int i, j;
-
- fprintf(stdout, "\nlong dd[2][3] --------\n");
- for (i = 0; i < 2; i++)
- for (j = 0; j < 3; j++)
- fprintf(stdout, "\n[%d][%d]: %ld\n", i, j, a[i][j]);
-}
-
-
-static void print_strRec(m_strRec* sr)
-{
- int i, j;
-
- fprintf(stdout, "\nboolean bb : %d\n",sr->bb);
- fprintf(stdout, "string str4 : %s\n",sr->str4);
- fprintf(stdout, "str7[2][3] :\n");
- for (i = 0; i < 2; i++)
- for (j = 0; j < 3; j++)
- fprintf(stdout, "str7[%d][%d]: %ld\n", i, j, sr->str7[i][j]);
- fprintf(stdout, "str5._length : %ld\n",sr->str5._length);
- for (j = 0; j < sr->str5._length; j++)
- fprintf(stdout, "str5._buffer[%d]: %c\n", j, sr->str5._buffer[j]);
- fprintf(stdout, "string str6 : %s\n",sr->str6);
- fprintf(stdout, "str8 :\n");
- for (j = 0; j < 3; j++)
- fprintf(stdout, "str8[%d]: %c\n", j, sr->str8[j]);
- fprintf(stdout, "string str9 : %s\n",sr->str9);
- fprintf(stdout, "str10._length : %ld\n",sr->str10._length);
- for (j = 0; j < sr->str10._length; j++)
- fprintf(stdout, "str10._buffer[%d]: %c\n", j, sr->str10._buffer[j]);
-}
-
-static void print_sseq(m_sseq *b)
-{
- int i;
-
- fprintf(stdout, "\nm_sseq size: %ld --------\n",b->_length);
- for (i = 0; i < b->_length; i++)
- fprintf(stdout, "%s\n", b->_buffer[i]);
-
-}
-
-
-static void print_pid(erlang_pid *p)
-{
- fprintf(stdout, "\nerlang_pid --------\n node: %s\n num: %d\n "
- "serial: %d\n creation: %d\n",
- p->node, p->num, p->serial, p->creation);
-}
-
-static void print_port(erlang_port *p)
-{
- fprintf(stdout, "\nerlang_port --------\n node: %s\n id: %d\n "
- "creation: %d\n", p->node, p->id, p->creation);
-}
-
-static void print_ref(erlang_ref *p)
-{
- fprintf(stdout, "\nerlang_ref --------\n node: %s\n len: %d\n "
- "n[0]: %d\n n[1]: %d\n n[2]: %d\n creation: %d\n",
- p->node, p->len, p->n[0], p->n[1], p->n[2], p->creation);
-}
-
-static void print_term(ETERM *t)
-{
- fprintf(stdout, "\nETERM --------\n");
- erl_print_term(stdout, t);
- fprintf(stdout, "\n--------\n");
-}
-
-static void print_s(m_s *p)
-{
- int i;
-
- fprintf(stdout, "\n%ld\n", p->l);
- for (i = 0; i < p->sl._length; i++)
- fprintf(stdout, "\n[%d]: %ld\n", i, p->sl._buffer[i]);
-}
-
-
-static void print_ssstr3(m_ssstr3 *b1)
-{
- int i,j;
-
- fprintf(stdout, "\nSSSTR3 --------\n");
- fprintf(stdout,"b1->_length = %ld\n",b1->_length);
- for (i = 0; i < b1->_length; i++) {
- fprintf(stdout,"\nb1->_buffer[%d]._length %ld\n",
- i, b1->_buffer[i]._length);
- for (j = 0; j < b1->_buffer[i]._length; j++)
- fprintf(stdout,"b1->_buffer[%d]._buffer[%d] = %s\n",
- i, j, b1->_buffer[i]._buffer[j]);
- }
- fprintf(stdout, "\n--------\n");
-}
-
-static void print_wstr(CORBA_wchar *ws)
-{
- int i = 0;
-
- fprintf(stdout, "\nwstr --------\n");
- while (ws[i]) {
- fprintf(stdout, "[%d]: %ld\n", i, ws[i]);
- i++;
- }
- fprintf(stdout, "\n--------\n");
-}
-
-
-static void print_ssarr3(m_ssarr3 *b1)
-{
- int i;
-
- fprintf(stdout, "\nssarr3 --------\n");
- fprintf(stdout,"length: %ld\n",b1->_length);
- fprintf(stdout, "buffer:\n");
- for (i = 0; i < b1->_length; i++)
- print_sarr3(&b1->_buffer[i]);
- fprintf(stdout, "\n--------\n");
-}
-
-static void print_sarr3(m_sarr3 *b1)
-{
- int i;
-
- fprintf(stdout, "\nsarr3 --------\n");
- fprintf(stdout,"length: %ld\n",b1->_length);
- fprintf(stdout, "buffer:\n");
- for (i = 0; i < b1->_length; i++)
- print_arr3(b1->_buffer[i]);
- fprintf(stdout, "\n--------\n");
-}
-
-static void print_arr3(m_arr3 b1)
-{
- int i;
-
- fprintf(stdout, "\narr3 --------\n");
- for (i = 0; i < sizeof(m_arr3)/sizeof(CORBA_long); i++)
- fprintf(stdout, "%ld ", b1[i]);
- fprintf(stdout, "\n--------\n");
-}
-
-static void free_etseq_buf(m_etseq *b)
-{
- int i;
-
- for (i = 0; i < b->_length; i++)
- erl_free_term(b->_buffer[i]);
-}
-
-static void free_et(m_et* b)
-{
- erl_free_term(b->e);
-}
-
-static void showtime(MyTimeval *start, MyTimeval *stop)
-{
- MyTimeval elapsed;
-
- elapsed.tv_sec = stop->tv_sec - start->tv_sec;
- elapsed.tv_usec = stop->tv_usec - start->tv_usec;
- while (elapsed.tv_usec < 0) {
- elapsed.tv_sec -= 1;
- elapsed.tv_usec += 1000000;
- }
- fprintf(stderr,"%ld.%06ld seconds\n",elapsed.tv_sec, elapsed.tv_usec);
-}
-
-static void my_gettimeofday(MyTimeval *tv)
-#ifdef __WIN32__
-#define EPOCH_JULIAN_DIFF 11644473600i64
-{
- SYSTEMTIME t;
- FILETIME ft;
- LONGLONG lft;
-
- GetSystemTime(&t);
- SystemTimeToFileTime(&t, &ft);
- memcpy(&lft, &ft, sizeof(lft));
- tv->tv_usec = (long) ((lft / 10i64) % 1000000i64);
- tv->tv_sec = (long) ((lft / 10000000i64) - EPOCH_JULIAN_DIFF);
-}
-#elif defined VXWORKS
-{
- int rate = sysClkRateGet(); /* Ticks per second */
- unsigned long ctick = tickGet();
- tv->tv_sec = ctick / rate; /* secs since reboot */
- tv->tv_usec = ((ctick - (tv->tv_sec * rate))*1000000)/rate;
-}
-#else
-{
- gettimeofday(tv, NULL);
-}
-#endif
diff --git a/lib/ic/test/c_client_erl_server_SUITE_data/c_erl_test.idl b/lib/ic/test/c_client_erl_server_SUITE_data/c_erl_test.idl
deleted file mode 100644
index 126389b01d..0000000000
--- a/lib/ic/test/c_client_erl_server_SUITE_data/c_erl_test.idl
+++ /dev/null
@@ -1,175 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 2001-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-#include "erlang.idl"
-
-
-const short TestConst = 1;
-
-module m {
-
- const short TestConst = 2;
-
- struct b {
- long l;
- char c;
- };
-
- struct simple {
- long l;
- b b_t;
- };
-
- enum fruit {orange, banana, apple, peach, pear};
-
- typedef sequence<long> lseq;
-
- typedef sequence<b> bseq;
-
- struct a {
- long l;
- bseq y;
- double d;
- };
-
- typedef sequence<a> aseq;
-
- typedef sequence<string> sseq;
- typedef string str;
- typedef long myLong;
-
- typedef long arr1[500], dd[2][3];
-
- typedef erlang::term apa;
- typedef erlang::port banan;
-
- typedef sequence<erlang::term> etseq;
-
- struct s {
- long l;
- sequence<long> sl;
- };
-
- struct es {
- fruit f;
- myLong l;
- };
-
- struct et {
- erlang::term e;
- long l;
- };
-
-
- typedef sequence<char> str1;
- typedef string<12> str2;
- typedef char str3[3];
-
- typedef sequence<string> sstr3; // sequence of string
- typedef sequence<sstr3> ssstr3; // sequence of sequences of strings
-
- typedef long arr3[3]; // array of long
- typedef sequence<arr3> sarr3; // sequence of array
- typedef sequence<sarr3> ssarr3; // sequence of sequnces of arrays of strings
-
- struct strRec{
- boolean bb;
- string str4;
- long str7[3][2];
- sequence<char> str5;
- string<12> str6;
- str3 str8;
- str2 str9;
- str1 str10;
- };
-
-
- struct dyn {
- long l;
- sequence<long> sl;
- };
- typedef dyn arr2[1][2];
-
-
- interface i {
-
- const short TestConst = 3;
-
- //arr2 suck(in arr2 x, out arr2 y );
-
- ///////////////////////////////// attribute long l;
-
- // simple types
- void void_test();
- long long_test(in long a, out long a1);
- long long longlong_test(in long long a, out long long a1);
- unsigned short ushort_test(in unsigned short a, out unsigned short a1);
- unsigned long ulong_test(in unsigned long a, out unsigned long a1);
- unsigned long long ulonglong_test(in unsigned long long a, out unsigned long long a1);
- double double_test(in double a, out double a1);
- char char_test(in char a, out char a1);
- wchar wchar_test(in wchar a, out wchar a1);
- octet octet_test(in octet a, out octet a1);
- boolean bool_test(in boolean a, out boolean a1);
-
- // Seq. and struct tests
- b struct_test(in b a, out b a1);
- es struct2_test(in es a, out es a1);
- //simple struct3_test(in simple x, out simple y);
- bseq seq1_test(in bseq a, out bseq a1);
- aseq seq2_test(in aseq a, out aseq a1);
- lseq seq3_test(in lseq a, out lseq a1);
- ssstr3 seq4_test(in ssstr3 a, out ssstr3 a1);
- ssarr3 seq5_test(in ssarr3 a, out ssarr3 a1);
-
- // Array tests
- arr1 array1_test(in arr1 a, out arr1 a1);
- dd array2_test(in dd a, out dd a1);
-
- // enum test
- fruit enum_test(in fruit a, out fruit a1);
-
- // string tests
- string string1_test(in string a, out string a1);
- wstring wstring1_test(in wstring a, out wstring a1);
- sseq string2_test(in sseq a, out sseq a1);
- str string3_test(in str a, out str a1);
- strRec string4_test(in strRec a, out strRec a1);
-
- // Special erlang types
- erlang::pid pid_test(in erlang::pid a, out erlang::pid a1);
- erlang::port port_test(in erlang::port a, out erlang::port a1);
- erlang::ref ref_test(in erlang::ref a, out erlang::ref a1);
- erlang::term term_test(in erlang::term a, out erlang::term a1);
-
- // typedef test
- long typedef_test(in apa a, in banan b, out apa a1, out banan b1);
-
- // inlined seq. test
- s inline_sequence_test(in s a, out s a1);
-
- // term seq. test
- etseq term_sequence_test(in etseq a, out etseq a1);
- // term struct test
- et term_struct_test(in et a, out et a1);
-
- };
-
-};
diff --git a/lib/ic/test/c_client_erl_server_SUITE_data/erl_server.erl b/lib/ic/test/c_client_erl_server_SUITE_data/erl_server.erl
deleted file mode 100644
index 159d3b9b89..0000000000
--- a/lib/ic/test/c_client_erl_server_SUITE_data/erl_server.erl
+++ /dev/null
@@ -1,29 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(erl_server).
-
--export([run/0, stop/0]).
-
-run() ->
- m_i:oe_create().
-
-stop() ->
- gen_server:cast(cidl_test, stop).
diff --git a/lib/ic/test/c_client_erl_server_SUITE_data/m_i_impl.erl b/lib/ic/test/c_client_erl_server_SUITE_data/m_i_impl.erl
deleted file mode 100644
index c530991058..0000000000
--- a/lib/ic/test/c_client_erl_server_SUITE_data/m_i_impl.erl
+++ /dev/null
@@ -1,162 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(m_i_impl).
--include("m.hrl").
-
--export([init/1, terminate/2, void_test/1, long_test/2, ushort_test/2,
- longlong_test/2, ulong_test/2, ulonglong_test/2,
- double_test/2, char_test/2, wchar_test/2, octet_test/2,
- bool_test/2, struct_test/2, struct2_test/2, seq1_test/2,
- seq2_test/2, seq3_test/2, seq4_test/2, seq5_test/2,
- array1_test/2, array2_test/2, enum_test/2, string1_test/2,
- string2_test/2, string3_test/2, string4_test/2, pid_test/2,
- port_test/2, ref_test/2, term_test/2, typedef_test/3,
- inline_sequence_test/2, '_set_l'/2, '_get_l'/1,
- term_struct_test/2, term_sequence_test/2, wstring1_test/2]).
-
--define(PRINTDEBUG(Case),
- io:format("erl_server: case: ~p~n"
- "erl_server: location: ~p~n", [Case, [?FILE, ?LINE]])).
--define(PRINTDEBUG2(Case, Msg),
- io:format("erl_server: case: ~p~n"
- "erl_server: Msg: ~p~n"
- "erl_server: location: ~p~n", [Case, Msg, [?FILE, ?LINE]])).
-
-init(Env) ->
- {ok, []}.
-
-terminate(F, R) ->
- ok.
-
-'_get_l'(State) ->
- ?PRINTDEBUG("_get_l"),
- {reply, State, State}.
-void_test(State) ->
- ?PRINTDEBUG("void_test"),
- {reply, ok, State}.
-
-'_set_l'(State, V) ->
- ?PRINTDEBUG2("_set_l", V),
- {reply, ok, V}.
-ushort_test(State, V) ->
- ?PRINTDEBUG2("ushort_test", V),
- {reply, {V, V}, State}.
-long_test(State, V) ->
- ?PRINTDEBUG2("long_test", V),
- {reply, {V, V}, State}.
-longlong_test(State, V) ->
- ?PRINTDEBUG2("longlong_test", V),
- {reply, {V, V}, State}.
-ulong_test(State, V) ->
- ?PRINTDEBUG2("ulong_test", V),
- {reply, {V, V}, State}.
-ulonglong_test(State, V) ->
- ?PRINTDEBUG2("ulonglong_test", V),
- {reply, {V, V}, State}.
-double_test(State, V) ->
- ?PRINTDEBUG2("double_test", V),
- {reply, {V, V}, State}.
-char_test(State, V) ->
- ?PRINTDEBUG2("char_test", V),
- {reply, {V, V}, State}.
-wchar_test(State, V) ->
- ?PRINTDEBUG2("wchar_test", V),
- {reply, {V, V}, State}.
-octet_test(State, V) ->
- ?PRINTDEBUG2("octet_test", V),
- {reply, {V, V}, State}.
-bool_test(State, V) ->
- ?PRINTDEBUG2("bool_test", V),
- {reply, {V, V}, State}.
-
-struct_test(State, V) ->
- ?PRINTDEBUG2("struct_test", V),
- {reply, {V, V}, State}.
-struct2_test(State, V) ->
- ?PRINTDEBUG2("struct2_test", V),
- {reply, {V, V}, State}.
-seq1_test(State, V) ->
- ?PRINTDEBUG2("seq1_test", V),
- {reply, {V, V}, State}.
-seq2_test(State, V) ->
- ?PRINTDEBUG2("seq2_test", V),
- {reply, {V, V}, State}.
-seq3_test(State, V) ->
- ?PRINTDEBUG2("seq3_test", V),
- {reply, {V, V}, State}.
-seq4_test(State, V) ->
- ?PRINTDEBUG2("seq4_test", V),
- {reply, {V, V}, State}.
-seq5_test(State, V) ->
- ?PRINTDEBUG2("seq5_test", V),
- {reply, {V, V}, State}.
-array1_test(State, V) ->
- ?PRINTDEBUG2("array1_test", V),
- {reply, {V, V}, State}.
-array2_test(State, V) ->
- ?PRINTDEBUG2("array2_test", V),
- {reply, {V, V}, State}.
-enum_test(State, V) ->
- ?PRINTDEBUG2("enum_test", V),
- {reply, {V, V}, State}.
-string1_test(State, V) ->
- ?PRINTDEBUG2("string1_test", V),
- {reply, {V, V}, State}.
-string2_test(State, V) ->
- ?PRINTDEBUG2("string2_test", V),
- {reply, {V, V}, State}.
-string3_test(State, V) ->
- ?PRINTDEBUG2("string3_test", V),
- {reply, {V, V}, State}.
-string4_test(State, V) ->
- ?PRINTDEBUG2("string4_test", V),
- {reply, {V, V}, State}.
-pid_test(State, V) ->
- ?PRINTDEBUG2("pid_test", V),
- {reply, {V, V}, State}.
-port_test(State, V) ->
- ?PRINTDEBUG2("port_test", binary_to_list(term_to_binary(V))),
- {reply, {V, V}, State}.
-ref_test(State, V) ->
- ?PRINTDEBUG2("ref_test", binary_to_list(term_to_binary(V))),
- {reply, {V, V}, State}.
-term_test(State, V) ->
- ?PRINTDEBUG2("term_test", V),
- {reply, {V, V}, State}.
-typedef_test(State, A, B) ->
- ?PRINTDEBUG2("typedef_test", [A,B]),
- {reply, {4711, A, B}, State}.
-inline_sequence_test(State, V) ->
- ?PRINTDEBUG2("inline_sequence_test", V),
- {reply, {V, V}, State}.
-term_sequence_test(State, V) ->
- ?PRINTDEBUG2("term_sequence_test", V),
- {reply, {V, V}, State}.
-term_struct_test(State, V) ->
- ?PRINTDEBUG2("term_struct_test", V),
- {reply, {V, V}, State}.
-wstring1_test(State, V) ->
- ?PRINTDEBUG2("wstring1_test", V),
- {reply, {V, V}, State}.
-
-
-
-
diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE.erl b/lib/ic/test/c_client_erl_server_proto_SUITE.erl
deleted file mode 100644
index c15617ea3f..0000000000
--- a/lib/ic/test/c_client_erl_server_proto_SUITE.erl
+++ /dev/null
@@ -1,265 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-%%----------------------------------------------------------------------
-%% Purpose : Test suite for c-client/erl-server
-%%----------------------------------------------------------------------
-
--module(c_client_erl_server_proto_SUITE).
--include_lib("common_test/include/ct.hrl").
-
--export([init_per_testcase/2, end_per_testcase/2,
- all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- void_test/1, long_test/1, long_long_test/1,
- unsigned_short_test/1, unsigned_long_test/1,
- unsigned_long_long_test/1, double_test/1, char_test/1,
- wchar_test/1, octet_test/1, bool_test/1, struct_test/1,
- struct2_test/1, seq1_test/1, seq2_test/1, seq3_test/1,
- seq4_test/1, seq5_test/1, array1_test/1, array2_test/1,
- enum_test/1, string1_test/1, string2_test/1, string3_test/1,
- string4_test/1, pid_test/1, port_test/1, ref_test/1, term_test/1,
- typedef_test/1, inline_sequence_test/1, term_sequence_test/1,
- term_struct_test/1, wstring1_test/1]).
-
--define(DEFAULT_TIMEOUT, 20000).
--define(PORT_TIMEOUT, 15000).
--define(ERLANG_SERVER_NAME, idl_erlang_server).
--define(C_CLIENT_NODE_NAME, c_client_idl_test).
-
-%% Add/remove code path and watchdog before/after each test case.
-%%
-init_per_testcase(_Case, Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- code:add_patha(DataDir),
-
- %% Since other test suites use the module m_i, we have
- %% to make sure we are using the right m_i module.
- code:purge(m_i),
- code:load_file(m_i),
-
- WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- code:del_path(DataDir),
- WatchDog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [void_test, long_test, long_long_test,
- unsigned_short_test, unsigned_long_test,
- unsigned_long_long_test, double_test, char_test,
- wchar_test, octet_test, bool_test, struct_test,
- struct2_test, seq1_test, seq2_test, seq3_test,
- seq4_test, seq5_test, array1_test, array2_test,
- enum_test, string1_test, string2_test, string3_test,
- string4_test, pid_test, port_test, ref_test, term_test,
- typedef_test, inline_sequence_test, term_sequence_test,
- term_struct_test, wstring1_test].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-array1_test(Config) ->
- do_test(array1_test, Config).
-
-array2_test(Config) ->
- do_test(array2_test, Config).
-
-bool_test(Config) ->
- do_test(bool_test, Config).
-
-char_test(Config) ->
- do_test(char_test, Config).
-
-double_test(Config) ->
- do_test(double_test, Config).
-
-enum_test(Config) ->
- do_test(enum_test, Config).
-
-inline_sequence_test(Config) ->
- do_test(inline_sequence_test, Config).
-
-long_long_test(Config) ->
- do_test(long_long_test, Config).
-
-long_test(Config) ->
- do_test(long_test, Config).
-
-octet_test(Config) ->
- do_test(octet_test, Config).
-
-pid_test(Config) ->
- do_test(pid_test, Config).
-
-port_test(Config) ->
- do_test(port_test, Config).
-
-ref_test(Config) ->
- do_test(ref_test, Config).
-
-seq1_test(Config) ->
- do_test(seq1_test, Config).
-
-seq2_test(Config) ->
- do_test(seq2_test, Config).
-
-seq3_test(Config) ->
- do_test(seq3_test, Config).
-
-seq4_test(Config) ->
- do_test(seq4_test, Config).
-
-seq5_test(Config) ->
- do_test(seq5_test, Config).
-
-string1_test(Config) ->
- do_test(string1_test, Config).
-
-string2_test(Config) ->
- do_test(string2_test, Config).
-
-string3_test(Config) ->
- do_test(string3_test, Config).
-
-string4_test(Config) ->
- do_test(string4_test, Config).
-
-struct2_test(Config) ->
- do_test(struct2_test, Config).
-
-struct_test(Config) ->
- do_test(struct_test, Config).
-
-term_sequence_test(Config) ->
- do_test(term_sequence_test, Config).
-
-term_struct_test(Config) ->
- do_test(term_struct_test, Config).
-
-term_test(Config) ->
- do_test(term_test, Config).
-
-typedef_test(Config) ->
- do_test(typedef_test, Config).
-
-unsigned_long_long_test(Config) ->
- do_test(unsigned_long_long_test, Config).
-
-unsigned_long_test(Config) ->
- do_test(unsigned_long_test, Config).
-
-unsigned_short_test(Config) ->
- do_test(unsigned_short_test, Config).
-
-void_test(Config) ->
- do_test(void_test, Config).
-
-wchar_test(Config) ->
- do_test(wchar_test, Config).
-
-wstring1_test(Config) ->
- do_test(wstring1_test, Config).
-
-
-%% It is here that all tests really are done.
-%%
-
-do_test(Case, Config) ->
- %% Trap exits
- process_flag(trap_exit, true),
- %% Start the server
- {ok, _Pid} = m_i:oe_create_link([], {local, ?ERLANG_SERVER_NAME}),
- Node = atom_to_list(node()),
- %% [NodeName, HostName] = string:tokens(Node, "@"),
- DataDir = proplists:get_value(data_dir, Config),
- %% io:format("~p: data directory: ~p~n", [?MODULE, DataDir]),
- Cookie = atom_to_list(erlang:get_cookie()),
- %% Start C-client node as a port program.
- Cmd = filename:join([DataDir, "c_client"]) ++
- " -this-node-name " ++ atom_to_list(?C_CLIENT_NODE_NAME) ++
- " -peer-node " ++ Node ++
- " -peer-process-name " ++ atom_to_list(?ERLANG_SERVER_NAME) ++
- " -cookie " ++ Cookie ++
- " -test-case " ++ atom_to_list(Case),
- Port = open_port({spawn, Cmd}, [exit_status, eof, stderr_to_stdout]),
- Res = wait_for_completion(Port),
- %% Kill off node if there was timeout
- case Res of
- {error, timeout} ->
- catch rpc:cast(?C_CLIENT_NODE_NAME, erlang, halt, [1]);
- _ ->
- ok
- end,
- process_flag(trap_exit, false),
- catch m_i:stop(?ERLANG_SERVER_NAME),
- ok = Res.
-
-
-%% Wait for eof *and* exit status, but return if exit status indicates
-%% an error, or we have been waiting more than PORT_TIMEOUT seconds.
-%%
-wait_for_completion(Port) ->
- wait_for_completion(Port, 0).
-
-wait_for_completion(Port, N) when N < 2 ->
- receive
- {Port, {data, Bytes}} ->
- %% Relay output
- io:format("~s", [Bytes]),
- wait_for_completion(Port, N);
- {Port, {exit_status, 0}} ->
- wait_for_completion(Port, N + 1);
- {Port, {exit_status, Status}} ->
- {error, Status};
- {Port, eof} ->
- wait_for_completion(Port, N + 1);
- {'EXIT', Port, Reason} ->
- io:format("Port exited with reason: ~w~n", [Reason]),
- wait_for_completion(Port, N);
- {'EXIT', From, Reason} ->
- io:format("Got unexpected exit: ~p~n", [{'EXIT', From, Reason}]),
- wait_for_completion(Port, N)
- after ?PORT_TIMEOUT ->
- {error, timeout}
- end;
-wait_for_completion(_, _) ->
- ok.
-
-
-
diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/Makefile.src b/lib/ic/test/c_client_erl_server_proto_SUITE_data/Makefile.src
deleted file mode 100644
index fc6d416316..0000000000
--- a/lib/ic/test/c_client_erl_server_proto_SUITE_data/Makefile.src
+++ /dev/null
@@ -1,156 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2003-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-# Makefile.src for c_client_erl_server test
-# Note: This file *must* work for both Unix and Windows
-#
-# We use both `rm' (Unix) and `del' (Windows) for removing files, but
-# with a `-' in front so that the error in not finding `rm' (`del') on
-# Windows (Unix) is ignored.
-#
-# VxWorks? XXX
-#
-
-.SUFFIXES:
-.SUFFIXES: .c .h .erl .idl @obj@ .@EMULATOR@
-
-
-# Variables from ts:
-#
-
-ERL_INCLUDE = @erl_include@
-
-IC_INCLUDE_PATH = @ic_include_path@
-IC_LIB = @ic_lib@
-
-ERL_INTERFACE_INCLUDE = @erl_interface_include@
-ERL_INTERFACE_LIB = @erl_interface_lib@
-ERL_INTERFACE_EILIB = @erl_interface_eilib@
-ERL_INTERFACE_THREADLIB = @erl_interface_threadlib@
-ERL_INTERFACE_SOCK_LIBS = @erl_interface_sock_libs@
-
-CC = @CC@
-## XXX Should set warning flag with a DEBUG_FLAG
-CFLAGS = @CFLAGS@ @DEFS@ -I@erl_include@ \
- -I@ic_include_path@ -I@erl_interface_include@
-
-LD = @LD@
-LDFLAGS = @CROSSLDFLAGS@
-LIBS = $(IC_LIB) $(ERL_INTERFACE_LIB) $(ERL_INTERFACE_EILIB) \
- $(ERL_INTERFACE_THREADLIB) @LIBS@ $(ERL_INTERFACE_SOCK_LIBS)
-ERLC = erlc
-
-# Generated C header files
-GEN_H_FILES = \
- m.h \
- m_i.h \
- oe_c_erl_test.h
-
-# Generated C files
-GEN_C_FILES = \
- m.c \
- m_i.c \
- oe_c_erl_test.c \
- oe_code_m_a.c \
- oe_code_m_arr1.c \
- oe_code_m_arr2.c \
- oe_code_m_arr3.c \
- oe_code_m_aseq.c \
- oe_code_m_b.c \
- oe_code_m_bseq.c \
- oe_code_m_dd.c \
- oe_code_m_dyn.c \
- oe_code_m_dyn_sl.c \
- oe_code_m_es.c \
- oe_code_m_et.c \
- oe_code_m_etseq.c \
- oe_code_m_fruit.c \
- oe_code_m_lseq.c \
- oe_code_m_s.c \
- oe_code_m_s_sl.c \
- oe_code_m_sarr3.c \
- oe_code_m_simple.c \
- oe_code_m_ssarr3.c \
- oe_code_m_sseq.c \
- oe_code_m_ssstr3.c \
- oe_code_m_sstr3.c \
- oe_code_m_str1.c \
- oe_code_m_str3.c \
- oe_code_m_strRec.c \
- oe_code_m_strRec_str5.c \
- oe_code_m_strRec_str7.c
-
-GEN_HRL_FILES = \
- m.hrl \
- m_i.hrl \
- oe_c_erl_test.hrl
-
-GEN_ERL_FILES = \
- m.erl \
- m_arr2.erl \
- m_arr3.erl \
- m_i.erl \
- m_str3.erl \
- oe_c_erl_test.erl
-
-C_FILES = $(GEN_C_FILES) c_client.c my.c
-
-OBJS = $(C_FILES:.c=@obj@)
-
-PGMS = c_client@exe@
-
-ERL_FILES = $(GEN_ERL_FILES) m_i_impl.erl
-
-EBINS = $(ERL_FILES:.erl=.@EMULATOR@)
-
-
-all: $(PGMS) $(EBINS)
-
-$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.built_erl
-$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.built_c
-$(OBJS): $(GEN_C_FILES) $(GEN_H_FILES)
-$(EBINS): $(GEN_ERL_FILES) $(GEN_HRL_FILES)
-
-clean:
- -rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
- c_erl_test.built_erl c_erl_test.built_c
- -del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
- c_erl_test.built_erl c_erl_test.built_c
-
-$(PGMS): $(OBJS)
- $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
-
-c_erl_test.built_c: c_erl_test.idl
- $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_client}" \
- "+{user_protocol,my}" c_erl_test.idl
- echo done > c_erl_test.built_c
-
-c_erl_test.built_erl: c_erl_test.idl
- $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" c_erl_test.idl
- echo done > c_erl_test.built_erl
-
-.c@obj@:
- $(CC) -c -o $*@obj@ $(CFLAGS) $<
-
-.erl.@EMULATOR@:
- $(ERLC) -I $(IC_INCLUDE_PATH) $<
-
diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/c_client.c b/lib/ic/test/c_client_erl_server_proto_SUITE_data/c_client.c
deleted file mode 100644
index 40c7328f03..0000000000
--- a/lib/ic/test/c_client_erl_server_proto_SUITE_data/c_client.c
+++ /dev/null
@@ -1,1764 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2003-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/* C-client for test of IC.
- *
- * TODO:
- *
- * 1. XXX #includes for VxWorks, Windows
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifndef __WIN32__
-# include <unistd.h>
-#endif
-
-#include <string.h>
-
-#ifdef __WIN32__
-# include <time.h>
-# include <sys/timeb.h>
-#elif defined VXWORKS
-#include <time.h>
-#include <sys/times.h>
-#else
-#include <sys/time.h>
-#endif
-
-#include <ctype.h>
-
-#ifdef __WIN32__
-# include <winsock2.h>
-# include <windows.h>
-#else
-# include <sys/types.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <arpa/inet.h>
-# include <netdb.h>
-#endif
-
-#include "ei.h"
-#include "erl_interface.h"
-#include "m_i.h"
-
-#define HOSTNAMESZ 255
-#define NODENAMESZ 512
-
-#define INBUFSZ 10
-#define OUTBUFSZ 0
-
-#define MAXTRIES 5
-
-#define CHECK_EXCEPTION(x) \
- if ((x)->_major != CORBA_NO_EXCEPTION) { \
- fprintf(stderr,"\n\nException: %s\n\n", \
- (char *)CORBA_exception_value((x))); \
- CORBA_exception_free((x)); \
- return -1; \
- } \
-
-/* XXX Should free things here too! */
-#define RETURN_IF_OK(x) \
- if ((x)) {\
- fprintf(stdout, "ok\n");\
- return 0;\
- }\
-
-#define cmp_str(x,y) (!strcmp((x),(y)))
-#define cmp_wstr(x,y) (!ic_wstrcmp((x),(y)))
-
-typedef CORBA_Environment IC_Env;
-
-typedef int (*TestFunc)(IC_Env *);
-typedef struct {
- char *name;
- TestFunc func;
-} TestCase;
-
-static char longtext[] =
-"Introduction The IC application is an IDL compiler implemented in Erlang."
-" The IDL compiler generates client stubs and server skeletons."
-" Several back-ends are supported, and they fall into three main groups."
-" For more details on IC compiler options consult the ic(3) manual page."
-" Argument passing cases 1 Caller allocates all necessary storage,"
-" except that which may be encapsulated and managed within the parameter itself."
-" 2 The caller allocates a pointer and passes it by reference to the callee."
-" The callee sets the pointer to point to a valid instance of the parameter's type."
-" The caller is responsible for releasing the returned storage."
-" Following completion of a request, the caller is not allowed to modify any values"
-" in the returned storage. To do so the caller must first copy the returned instance"
-" into a new instance, then modify the new instance. 3 The caller allocates a"
-" pointer to an array slice which has all the same dimensions of the original"
-" array except the first, and passes it by reference to the callee. The callee sets"
-" the pointer to point to a valid instance of the array. The caller is responsible for"
-" releasing the returned storage. Following completion of a request, the caller is not"
-" allowed to modify any values in the returned storage. To do so the caller must first"
-" copy the returned instance into a new instance, then modify the new instance."
-" Generated Files Two files will be generated for each scope. One set of files will be"
-" generated for each module and each interface scope. An extra set is generated for"
-" those definitions at top level scope. One of the files is a header file(.h), and the"
-" other file is a C source code file (.c). In addition to these files a number of C"
-" source files will be generated for type encodings, they are named according to the "
-"following template: oe_code_<type>.c.";
-static char this_node[NODENAMESZ + 1];
-static char *progname;
-
-/* Test function prototypes */
-
-static int void_test(IC_Env *env);
-static int long_test(IC_Env *env);
-static int long_long_test(IC_Env *env);
-static int unsigned_short_test(IC_Env *env);
-static int unsigned_long_test(IC_Env *env);
-static int unsigned_long_long_test(IC_Env *env);
-static int double_test(IC_Env *env);
-static int char_test(IC_Env *env);
-static int wchar_test(IC_Env *env);
-static int octet_test(IC_Env *env);
-static int bool_test(IC_Env *env);
-static int struct_test(IC_Env *env);
-static int struct2_test(IC_Env *env);
-static int seq1_test(IC_Env *env);
-static int seq2_test(IC_Env *env);
-static int seq3_test(IC_Env *env);
-static int seq4_test(IC_Env *env);
-static int seq5_test(IC_Env *env);
-static int array1_test(IC_Env *env);
-static int array2_test(IC_Env *env);
-static int enum_test(IC_Env *env);
-static int string1_test(IC_Env *env);
-static int string2_test(IC_Env *env);
-static int string3_test(IC_Env *env);
-static int string4_test(IC_Env *env);
-static int pid_test(IC_Env *env);
-static int port_test(IC_Env *env);
-static int ref_test(IC_Env *env);
-static int term_test(IC_Env *env);
-static int typedef_test(IC_Env *env);
-static int inline_sequence_test(IC_Env *env);
-static int term_sequence_test(IC_Env *env);
-static int term_struct_test(IC_Env *env);
-static int wstring1_test(IC_Env *env);
-
-static TestCase test_cases[] = {
- {"void_test", void_test},
- {"long_test", long_test},
- {"long_long_test", long_long_test},
- {"unsigned_short_test", unsigned_short_test},
- {"unsigned_long_test", unsigned_long_test},
- {"unsigned_long_long_test", unsigned_long_long_test},
- {"double_test", double_test},
- {"char_test", char_test},
- {"wchar_test", wchar_test},
- {"octet_test", octet_test},
- {"bool_test", bool_test},
- {"struct_test", struct_test},
- {"struct2_test", struct2_test},
- {"seq1_test", seq1_test},
- {"seq2_test", seq2_test},
- {"seq3_test", seq3_test},
- {"seq4_test", seq4_test},
- {"seq5_test", seq5_test},
- {"array1_test", array1_test},
- {"array2_test", array2_test},
- {"enum_test", enum_test},
- {"string1_test", string1_test},
- {"string2_test", string2_test},
- {"string3_test", string3_test},
- {"string4_test", string4_test},
- {"pid_test", pid_test},
- {"port_test", port_test},
- {"ref_test", ref_test},
- {"term_test", term_test},
- {"typedef_test", typedef_test},
- {"inline_sequence_test", inline_sequence_test},
- {"term_sequence_test", term_sequence_test},
- {"term_struct_test", term_struct_test},
- {"wstring1_test", wstring1_test},
- {"", NULL}
-};
-
-/* Other prototypes */
-static int cmp_aseq(m_aseq *a1, m_aseq *a2);
-static int cmp_a(m_a *a1, m_a *a2);
-static int cmp_bseq(m_bseq *b1, m_bseq *b2);
-static int cmp_b(m_b *b1, m_b *b2);
-static int cmp_lseq(m_lseq *b1, m_lseq *b2);
-static int cmp_etseq(m_etseq *b1, m_etseq *b2);
-static int cmp_et(m_et* b1, m_et *b2);
-static int cmp_es(m_es *b1, m_es *b2);
-static int cmp_arr1(m_arr1 b1, m_arr1 b2);
-static int cmp_dd(m_dd b1, m_dd b2);
-static int cmp_strRec(m_strRec *b1, m_strRec *b2);
-static int cmp_sseq(m_sseq *b1, m_sseq *b2);
-static int cmp_pid(erlang_pid *p1, erlang_pid *p2);
-static int cmp_port(erlang_port *p1, erlang_port *p2);
-static int cmp_ref(erlang_ref *p1, erlang_ref *p2);
-static int cmp_s(m_s *b1, m_s *b2);
-static int cmp_ssstr3(m_ssstr3 *b1, m_ssstr3 *b2);
-static int cmp_ssarr3(m_ssarr3 *b1, m_ssarr3 *b2);
-static int cmp_sarr3(m_sarr3 *b1, m_sarr3 *b2);
-static int cmp_arr3(m_arr3 b1, m_arr3 b2);
-
-static void print_aseq(m_aseq *a);
-static void print_a(m_a *a);
-static void print_bseq(m_bseq *b);
-static void print_lseq(m_lseq *b);
-static void print_b(m_b *b);
-static void print_etseq(m_etseq *b);
-static void print_et(m_et* b);
-static void print_es(m_es *b);
-static void print_arr1(long a[500]);
-static void print_dd(long a[2][3]);
-static void print_strRec(m_strRec* sr);
-static void print_sseq(m_sseq *b);
-static void print_pid(erlang_pid *p);
-static void print_port(erlang_port *p);
-static void print_ref(erlang_ref *p);
-static void print_term(ETERM *t);
-static void print_s(m_s *p);
-static void print_ssstr3(m_ssstr3 *b1);
-static void print_ssarr3(m_ssarr3 *b1);
-static void print_sarr3(m_sarr3 *b1);
-static void print_arr3(m_arr3 b1);
-static void print_wstr(CORBA_wchar *ws);
-
-static void free_etseq_buf(m_etseq *b);
-static void free_et(m_et* b);
-
-#ifdef __WIN32__
-typedef struct {
- long tv_sec;
- long tv_usec;
-} MyTimeval;
-#else
-typedef struct timeval MyTimeval;
-#endif
-static void my_gettimeofday(MyTimeval *tv);
-static void showtime(MyTimeval *start, MyTimeval *stop);
-static void usage(void);
-static void done(int r);
-
-
-
-/* main */
-
-#ifdef VXWORKS
-int client(int argc, char **argv)
-#else
-int main(int argc, char **argv)
-#endif
-{
- struct hostent *hp;
- erlang_pid pid;
- MyTimeval start, stop;
- int i, fd, ires, tres;
- IC_Env *env;
- int tries = 0;
- char *this_node_name = NULL;
- char *peer_node = NULL;
- char *peer_process_name = NULL;
- char *cookie = NULL;
- char host[HOSTNAMESZ + 1];
- TestFunc test_func = NULL;
- TestCase *test_case;
- char *test_case_name = NULL;
-
-#ifdef __WIN32__
- WORD wVersionRequested;
- WSADATA wsaData;
-
- wVersionRequested = MAKEWORD(2, 0);
-
- if (WSAStartup(wVersionRequested, &wsaData) != 0) {
- fprintf(stderr, "Could not load winsock2 v2.0 compatible DLL");
- exit(1);
- }
-#endif
-
- progname = argv[0];
- host[HOSTNAMESZ] = '\0';
- if (gethostname(host, HOSTNAMESZ + 1) < 0) {
- fprintf(stderr, "Can't find own hostname\n");
- done(1);
- }
- if ((hp = gethostbyname(host)) == 0) {
- fprintf(stderr, "Can't get ip address for host %s\n", host);
- done(1);
- }
- for (i = 1; i < argc; i++) {
- if (cmp_str(argv[i], "-help")) {
- usage();
- done(0);
- } else if (cmp_str(argv[i], "-this-node-name")) {
- i++;
- this_node_name = argv[i];
- } else if (cmp_str(argv[i], "-peer-node")) {
- i++;
- peer_node = argv[i];
- } else if (cmp_str(argv[i], "-peer-process-name")) {
- i++;
- peer_process_name = argv[i];
- } else if (cmp_str(argv[i], "-cookie")) {
- i++;
- cookie = argv[i];
- } else if (cmp_str(argv[i], "-test-case")) {
- i++;
- test_case_name = argv[i];
- } else {
- fprintf(stderr, "Error : invalid argument \"%s\"\n", argv[i]);
- usage();
- done(1);
- }
- }
-
- if (this_node_name == NULL || peer_node == NULL || test_case_name == NULL
- || peer_process_name == NULL || cookie == NULL) {
- fprintf(stderr, "Error: missing option\n");
- usage();
- done(1);
- }
-
- test_case = test_cases;
- while (test_case->func) {
- if (cmp_str(test_case->name, test_case_name)) {
- test_func = test_case->func;
- break;
- }
- test_case++;
- }
- if (test_func == NULL) {
- fprintf(stderr, "Error: illegal test case: \"%s\"\n", test_case_name);
- done(1);
- }
-
- /* Behead hostname at first dot */
- for (i=0; host[i] != '\0'; i++) {
- if (host[i] == '.') { host[i] = '\0'; break; }
- }
- sprintf(this_node, "%s@%s", this_node_name, host);
- fprintf(stderr, "c_client: this node: \"%s\"\n", this_node);
- fprintf(stderr, "c_client: peer node: \"%s\"\n", peer_node);
- fprintf(stderr, "c_client: test case: \"%s\"\n", test_case_name);
-
- fprintf(stderr, "c_client: starting\n");
-
- /* initialize erl_interface */
- erl_init(NULL, 0);
-
- for (tries = 0; tries < MAXTRIES; tries++) {
-
- /* connect to erlang node */
-
- ires = erl_connect_xinit(host, this_node_name, this_node,
- (struct in_addr *)*hp->h_addr_list,
- cookie, 0);
-
- fprintf(stderr, "c_client: erl_connect_xinit(): %d\n", ires);
-
- fd = erl_connect(peer_node);
- fprintf(stderr, "c_client: erl_connect(): %d\n", fd);
-
- if (fd >= 0)
- break;
- fprintf(stderr, "c_client: cannot connect, retrying\n");
- }
- if (fd < 0) {
- fprintf(stderr, "c_client: cannot connect, exiting\n");
- done(1);
- }
- env = CORBA_Environment_alloc(INBUFSZ, OUTBUFSZ);
- env->_fd = fd;
- strcpy(env->_regname, peer_process_name);
- env->_to_pid = NULL;
- env->_from_pid = &pid;
-
- strcpy(pid.node, this_node);
- pid.num = fd;
- pid.serial = 0;
- pid.creation = 0;
-
- my_gettimeofday(&start);
- tres = test_func(env); /* Call test case */
- my_gettimeofday(&stop);
- showtime(&start, &stop);
- erl_close_connection(fd);
-
- printf("c_client: env->_inbuf before : %d\n", INBUFSZ);
- printf("c_client: env->_outbuf before : %d\n", OUTBUFSZ);
- printf("c_client: env->_inbuf after : %d\n", env->_inbufsz);
- printf("c_client: env->_outbuf after : %d\n", env->_outbufsz);
-
- CORBA_free(env->_inbuf);
- CORBA_free(env->_outbuf);
- CORBA_free(env);
- done(tres);
-}
-
-static void usage()
-{
- fprintf(stderr, "Usage: %s [-help] -this-node-name <name> "
- "-peer-node <nodename> -peer-process-name <name> "
- "-cookie <cookie> -test-case <test case name>\n", progname);
- fprintf(stderr, "Example:\n %s -this-node-name kalle "
- "-peer-node olle@home -peer-process-name idltest "
- "-cookie oa678er -test-case octet_test\n", progname);
-}
-
-static void done(int r)
-{
-#ifdef __WIN32__
- WSACleanup();
-#endif
- exit(r);
-}
-
-
-/* TESTS */
-
-static int void_test(IC_Env *env)
-{
- fprintf(stdout, "\n======== m_i_void test ======\n\n");
- m_i_void_test(NULL,env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(1);
-}
-
-static int long_test(IC_Env *env)
-{
- long l = 4711, lo, lr;
-
- fprintf(stdout, "\n======== m_i_long test ======\n\n");
- lr = m_i_long_test(NULL, l, &lo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(l == lo && l == lr);
- if (l != lo)
- fprintf(stdout, " out parameter error, sent: %ld, got: %ld\n", l, lo);
- if (l != lr)
- fprintf(stdout, " result error, sent: %ld, got: %ld\n", l, lr);
- return -1;
-}
-
-static int long_long_test(IC_Env *env)
-{
- CORBA_long_long ll = 4711, llo, llr;
-
- fprintf(stdout, "\n======== m_i_longlong test ======\n\n");
- llr = m_i_longlong_test(NULL, ll, &llo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(ll == llo && ll == llr);
- if (ll != llo)
- fprintf(stdout, " out parameter error, sent: %ld, got: %ld\n",
- ll, llo);
- if (ll != llr)
- fprintf(stdout, " result error, sent: %ld, got: %ld\n", ll, llr);
- return -1;
-}
-
-static int unsigned_short_test(IC_Env *env)
-{
- unsigned short x, y = 2, z;
-
- fprintf(stdout, "\n======== m_i_ushort test ======\n\n");
- x = m_i_ushort_test(NULL, y, &z, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(y == z && y == x);
- if (y != z)
- fprintf(stdout, " out parameter error, sent: %d, got: %d\n", y, z);
- if (y != x)
- fprintf(stdout, " result error, sent: %d, got: %d\n", y, x);
- return -1;
-}
-
-
-static int unsigned_long_test(IC_Env *env)
-{
- unsigned long ul = 5050, ulo, ulr;
-
- fprintf(stdout, "\n======== m_i_ulong test ======\n\n");
- ulr = m_i_ulong_test(NULL, ul, &ulo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(ul == ulo && ul == ulr);
- if (ul != ulo)
- fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n",
- ul, ulo);
- if (ul != ulr)
- fprintf(stdout, " result error, sent: %lu, got: %lu\n", ul, ulr);
- return -1;
-}
-
-/*
- * Note: CORBA_unsigned_long_long is in fact a plain long.
- */
-static int unsigned_long_long_test(IC_Env *env)
-{
- CORBA_unsigned_long_long ull = 5050, ullo, ullr;
-
- fprintf(stdout, "\n======== m_i_ulonglong test ======\n\n");
- ullr = m_i_ulonglong_test(NULL, ull, &ullo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(ull == ullo && ull == ullr);
- if (ull != ullo)
- fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n",
- ull, ullo);
- if (ull != ullr)
- fprintf(stdout, " result error, sent: %lu, got: %lu\n",
- ull, ullr);
- return -1;
-}
-
-static int double_test(IC_Env *env)
-{
- double d = 12.1212, db, dr;
-
- fprintf(stdout, "\n======== m_i_double test ======\n\n");
- dr = m_i_double_test(NULL, d, &db, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(d == db && d == dr);
- if (d != db)
- fprintf(stdout, " out parameter error, sent: %f, got: %f\n", d, db);
- if (d != dr)
- fprintf(stdout, " result error, sent: %f, got: %f\n", d, dr);
- return -1;
-}
-
-static int char_test(IC_Env *env)
-{
- char c = 'g', co, cr;
-
- /* char test */
- fprintf(stdout, "\n======== m_i_char test ======\n\n");
- cr = m_i_char_test(NULL, c, &co, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(c == co && c == cr);
- if (c !=co)
- fprintf(stdout, " out parameter error, sent: %c, got: %c\n", c, co);
- if (c != cr)
- fprintf(stdout, " result error, sent: %c, got: %c\n", c, cr);
- return -1;
-}
-
-static int wchar_test(IC_Env *env)
-{
- CORBA_wchar wc = 103, wco, wcr;
-
- fprintf(stdout, "\n======== m_i_wchar test ======\n\n");
- wcr = m_i_wchar_test(NULL, wc, &wco, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(wc == wco && wc == wcr);
- if (wc != wco)
- fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n",
- wc, wco);
- if (wc != wcr)
- fprintf(stdout, " result error, sent: %lu, got: %lu\n",
- wc, wcr);
- return -1;
-}
-
-static int octet_test(IC_Env *env)
-{
- char o ='r', oo, or;
-
- fprintf(stdout, "\n======== m_i_octet test ======\n\n");
- or = m_i_octet_test(NULL, o, &oo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(o == oo && o == or);
- if (o != oo)
- fprintf(stdout, " out parameter error, sent: %c, got: %c\n", o, oo);
- if (o != or)
- fprintf(stdout, " result error, sent: %c, got: %c\n", o, or);
- return -1;
-}
-
-static int bool_test(IC_Env *env)
-{
- unsigned char i = 0, io, ir;
-
- fprintf(stdout, "\n======== m_i_bool test ======\n\n");
- ir = m_i_bool_test(NULL, i, &io, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(i == io && i == ir);
- if (i != io)
- fprintf(stdout, " out parameter error, sent: %d, got: %d\n", i, io);
- if (i != ir)
- fprintf(stdout, " result error, sent: %d, got: %d\n", i, ir);
- return -1;
-}
-
-static int struct_test(IC_Env *env)
-{
- m_b b = {4711, 'a'}, bo, br;
-
- fprintf(stdout, "\n======== m_i_struct test ======\n\n");
- br = m_i_struct_test(NULL, &b, &bo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_b(&b, &bo) && cmp_b(&b, &br));
- if (!cmp_b(&b, &bo)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_b(&b);
- fprintf(stdout, " got:\n");
- print_b(&bo);
- fprintf(stdout, "\n");
- }
- if (!cmp_b(&b, &br)) {
- fprintf(stdout, " result error, sent:\n");
- print_b(&b);
- fprintf(stdout, " got:\n");
- print_b(&br);
- fprintf(stdout, "\n");
- }
- return -1;
-}
-
-static int struct2_test(IC_Env *env)
-{
- m_es esi = {m_peach, 5050}, eso, esr;
-
- fprintf(stdout, "\n======== m_i_struct2 test ======\n\n");
- esr = m_i_struct2_test(NULL, &esi, &eso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_es(&esi, &eso) && cmp_es(&esi, &esr));
- if (!cmp_es(&esi, &eso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_es(&esi);
- fprintf(stdout, " got:\n");
- print_es(&eso);
- fprintf(stdout, "\n");
- }
- if (!cmp_es(&esi, &esr)) {
- fprintf(stdout, " result error, sent:\n");
- print_es(&esi);
- fprintf(stdout, " got:\n");
- print_es(&esr);
- fprintf(stdout, "\n");
- }
- return -1;
-}
-
-
-static int seq1_test(IC_Env *env)
-{
- m_bseq bs, *bso, *bsr;
-
- m_b ba[3] = {{4711, 'a'}, {4712, 'b'}, {4713, 'c'}};
- bs._length = 3;
- bs._buffer = ba;
-
- fprintf(stdout, "\n======== m_i_seq1 test ======\n\n");
- bsr = m_i_seq1_test(NULL, &bs, &bso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_bseq(&bs, bso) && cmp_bseq(&bs, bsr));
- if (!cmp_bseq(&bs, bso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_bseq(&bs);
- fprintf(stdout, " got:\n");
- print_bseq(bso);
- fprintf(stdout, "\n");
- }
- if (!cmp_bseq(&bs, bsr)) {
- fprintf(stdout, " result error, sent:\n");
- print_bseq(&bs);
- fprintf(stdout, " got:\n");
- print_bseq(bsr);
- fprintf(stdout, "\n");
- }
- CORBA_free(bso);
- CORBA_free(bsr);
- return -1;
-}
-
-static int seq2_test(IC_Env *env)
-{
- m_b ba[3] = {{4711, 'a'}, {4712, 'b'}, {4713, 'c'}};
- m_a a;
- m_a aa[2];
- m_aseq as, *aso, *asr;
-
- a.l = 9999;
- a.y._length = 3;
- a.y._buffer = ba;
- a.d = 66.89898989;
-
- aa[0] = a;
- aa[1] = a;
- as._length = 2;
- as._buffer = aa;
-
- fprintf(stdout, "\n======== m_i_seq2 test ======\n\n");
- asr = m_i_seq2_test(NULL, &as, &aso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_aseq(&as, aso) && cmp_aseq(&as, asr));
- if (!cmp_aseq(&as, aso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_aseq(&as);
- fprintf(stdout, " got:\n");
- print_aseq(aso);
- fprintf(stdout, "\n");
- }
- if (!cmp_aseq(&as, asr)) {
- fprintf(stdout, " result error, sent:\n");
- print_aseq(&as);
- fprintf(stdout, " got:\n");
- print_aseq(asr);
- fprintf(stdout, "\n");
- }
- CORBA_free(aso);
- CORBA_free(asr);
- return -1;
-}
-
-static int seq3_test(IC_Env *env)
-{
- m_lseq lsi, *lso, *lsr;
- long al[500];
- int i=0;
-
- for (i = 0; i < 500; i++)
- al[i]=i;
- lsi._length = 500;
- lsi._buffer = al;
-
- fprintf(stdout, "\n======== m_i_seq3 test ======\n\n");
- lsr = m_i_seq3_test(NULL, &lsi, &lso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_lseq(&lsi, lso) && cmp_lseq(&lsi, lsr));
- if (!cmp_lseq(&lsi, lso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_lseq(&lsi);
- fprintf(stdout, " got:\n");
- print_lseq(lso);
- fprintf(stdout, "\n");
- }
- if (!cmp_lseq(&lsi, lsr)) {
- fprintf(stdout, " result error, sent:\n");
- print_lseq(&lsi);
- fprintf(stdout, " got:\n");
- print_lseq(lsr);
- fprintf(stdout, "\n");
- }
- CORBA_free(lso);
- CORBA_free(lsr);
- return -1;
-}
-
-static int seq4_test(IC_Env *env)
-{
- char *stra0[3] = {"a", "long", "time"};
- char *stra1[3] = {"ago", "there", "was"};
- char *stra2[3] = {"a", "buggy", "compiler"};
- m_sstr3 str3s[3] = {{3, 3, stra0}, {3, 3, stra1}, {3, 3, stra2}};
- m_ssstr3 str3ssi = {3, 3, str3s};
- m_ssstr3 *str3sso, *str3ssr;
-
- fprintf(stdout, "\n======== m_i_seq4 test ======\n\n");
- str3ssr = m_i_seq4_test(NULL, &str3ssi, &str3sso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_ssstr3(&str3ssi, str3sso) &&
- cmp_ssstr3(&str3ssi, str3ssr));
- if (!cmp_ssstr3(&str3ssi, str3sso)){
- fprintf(stdout, " out parameter error, sent:\n");
- print_ssstr3(&str3ssi);
- fprintf(stdout, " got:\n");
- print_ssstr3(str3sso);
- fprintf(stdout, "\n");
- }
- if (!cmp_ssstr3(&str3ssi, str3ssr)) {
- fprintf(stdout, " result error, sent:\n");
- print_ssstr3(&str3ssi);
- fprintf(stdout, " got:\n");
- print_ssstr3(str3ssr);
- fprintf(stdout, "\n");
- }
- CORBA_free(str3sso);
- CORBA_free(str3ssr);
- return -1;
-}
-
-static int seq5_test(IC_Env *env)
-{
- m_arr3 arr3a[3] = {
- {4711, 18931947, 3},
- {4711, 18931947, 3},
- {4711, 18931947, 3}};
- m_sarr3 arr3sa[3] = {{3, 3, arr3a}, {3, 3, arr3a}, {3, 3, arr3a}};
- m_ssarr3 arr3ssi = {3, 3, arr3sa};
- m_ssarr3 *arr3sso;
- m_ssarr3 *arr3ssr;
-
- fprintf(stdout, "\n======== m_i_seq5 test ======\n\n");
- arr3ssr = m_i_seq5_test(NULL, &arr3ssi, &arr3sso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_ssarr3(&arr3ssi, arr3sso) &&
- cmp_ssarr3(&arr3ssi, arr3ssr));
- if (!cmp_ssarr3(&arr3ssi, arr3sso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_ssarr3(&arr3ssi);
- fprintf(stdout, " got:\n");
- print_ssarr3(arr3sso);
- fprintf(stdout, "\n");
- }
- if (!cmp_ssarr3(&arr3ssi, arr3ssr)) {
- fprintf(stdout, " result error, sent:\n");
- print_ssarr3(&arr3ssi);
- fprintf(stdout, " got:\n");
- print_ssarr3(arr3ssr);
- fprintf(stdout, "\n");
- }
- CORBA_free(arr3sso);
- CORBA_free(arr3ssr);
- return -1;
-}
-
-static int array1_test(IC_Env *env)
-{
- int i;
- long al[500];
- m_arr1 alo;
- m_arr1_slice* alr;
-
- for (i = 0; i < 500; i++)
- al[i]=i;
-
- fprintf(stdout, "\n======== m_i_array1 test ======\n\n");
- alr = m_i_array1_test(NULL, al, alo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_arr1(al, alo) && cmp_arr1(al, alr));
- if (!cmp_arr1(al, alo)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_arr1(al);
- fprintf(stdout, " got:\n");
- print_arr1(alo);
- fprintf(stdout, "\n");
- }
- if (!cmp_arr1(al,alr)) {
- fprintf(stdout, " result error, sent:\n");
- print_arr1(al);
- fprintf(stdout, " got:\n");
- print_arr1(alr);
- fprintf(stdout, "\n");
- }
- free(alo);
- free(alr);
- return -1;
-}
-
-static int array2_test(IC_Env *env)
-{
- long dl[2][3] = {{11, 2, 7}, {22, 8 ,13}};
- m_dd dlo;
- m_dd_slice* dlr;
-
- fprintf(stdout, "\n======== m_i_array2 test ======\n\n");
- dlr = m_i_array2_test(NULL, dl, dlo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_dd(dl,dlo) && cmp_dd(dl,dlr));
- if (!cmp_dd(dl,dlo)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_dd(dl);
- fprintf(stdout, " got:\n");
- print_dd(dlo);
- fprintf(stdout, "\n");
- }
- if (!cmp_dd(dl,dlr)) {
- fprintf(stdout, " result error, sent:\n");
- print_dd(dl);
- fprintf(stdout, " got:\n");
- print_dd(dlr);
- fprintf(stdout, "\n");
- }
- free(*dlr);
- return -1;
-}
-
-static int enum_test(IC_Env *env)
-{
- m_fruit ei = m_banana, eo, er;
-
- fprintf(stdout, "\n======== m_i_enum test ======\n\n");
- er = m_i_enum_test(NULL, ei, &eo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(ei == eo && ei == er);
- if (ei != eo)
- fprintf(stdout, " out parameter error, sent: %d, got: %d\n", ei, eo);
- if (ei != er)
- fprintf(stdout, " result error, sent: %d, got: %d\n", ei, er);
- return -1;
-}
-
-static int string1_test(IC_Env *env)
-{
- char* si = longtext;
- char* so;
- char* sr;
-
- fprintf(stdout, "\n======== m_i_string1 test ======\n\n");
- sr = m_i_string1_test(NULL, si, &so, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_str(si, so) && cmp_str(si, sr));
- if (!cmp_str(si, so))
- fprintf(stdout, " out parameter error, sent: %s, got: %s\n", si, so);
- if (!cmp_str(si, sr))
- fprintf(stdout, " result error, sent: %s, got: %s\n", si, sr);
- CORBA_free(so);
- CORBA_free(sr);
- return -1;
-}
-
-static int string2_test(IC_Env *env)
-{
- char* sa[3] = {"hello", "foo", "bar"};
- m_sseq ssi = {3, 3, sa};
- m_sseq *sso, *ssr;
-
- fprintf(stdout, "\n======== m_i_string2 test ======\n\n");
- ssr = m_i_string2_test(NULL, &ssi, &sso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_sseq(&ssi, sso) && cmp_sseq(&ssi, sso));
- if (!cmp_sseq(&ssi, sso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_sseq(&ssi);
- fprintf(stdout, "got:\n");
- print_sseq(sso);
- }
- if (!cmp_sseq(&ssi, ssr)) {
- fprintf(stdout, " result error, sent:\n");
- print_sseq(&ssi);
- fprintf(stdout, "got:\n");
- print_sseq(ssr);
- }
- CORBA_free(sso);
- CORBA_free(ssr);
- return -1;
-}
-
-static int string3_test(IC_Env *env)
-{
- char* si = longtext;
- char* so;
- char* sr;
-
- fprintf(stdout, "\n======== m_i_string3 test ======\n\n");
- sr = m_i_string3_test(NULL, si, &so, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_str(si, so) && cmp_str(si, so));
- if (!cmp_str(si, so))
- fprintf(stdout, " out parameter error, sent: %s, got: %s\n", si, so);
- if (!cmp_str(si, sr))
- fprintf(stdout, " result error, sent: %s, got: %s\n", si, sr);
- CORBA_free(so);
- CORBA_free(sr);
- return -1;
-}
-
-static int string4_test(IC_Env *env)
-{
- char as1[100] = "a string", as2[200] = "help", as3[200] = "hello there";
- m_strRec stri = { 1, /* dd */
- as1, /* str4 */
- {{'a', 'k'}, {'z', 'g'}, {'n', 'q'}}, /* str7 */
- {3, 3, "buf"}, /* str5 */
- as2, /* str6 */
- {'m', 'f', 'o'}, /* str8 */
- as3, /* str9 */
- {3, 3, "stu"} /* str10 */
- };
- m_strRec *stro, *strr;
-
- fprintf(stdout, "\n======== m_i_string4 test ======\n\n");
- strr = m_i_string4_test(NULL, &stri, &stro, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_strRec(&stri,stro) && cmp_strRec(&stri,strr));
- if (!cmp_strRec(&stri,stro)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_strRec(&stri);
- fprintf(stdout, " got:\n");
- print_strRec(stro);
- fprintf(stdout, "\n");
- }
- if (!cmp_strRec(&stri,strr)) {
- fprintf(stdout, " result error, sent:\n");
- print_strRec(&stri);
- fprintf(stdout, " got:\n");
- print_strRec(strr);
- fprintf(stdout, "\n");
- }
- CORBA_free(stro);
- CORBA_free(strr);
- return -1;
-}
-
-
-static int pid_test(IC_Env *env)
-{
- erlang_pid pid = {"", 7, 0, 0}, pido, pidr;
-
- strcpy(pid.node, this_node), /* this currently running node */
- fprintf(stdout, "\n======== m_i_pid test ======\n\n");
- pidr = m_i_pid_test(NULL, &pid, &pido, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_pid(&pid, &pido) && cmp_pid(&pid, &pidr));
- if (!cmp_pid(&pid, &pido)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_pid(&pid);
- fprintf(stdout, "got:\n");
- print_pid(&pido);
- }
- if (!cmp_pid(&pid, &pidr)) {
- fprintf(stdout, " result error, sent:\n");
- print_pid(&pid);
- fprintf(stdout, "got:\n");
- print_pid(&pidr);
- }
- return -1;
-}
-
-static int port_test(IC_Env *env)
-{
- erlang_port porti = {"node", 5, 1}, porto, portr;
-
- fprintf(stdout, "\n======== m_i_port test ======\n\n");
- portr = m_i_port_test(NULL, &porti, &porto, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_port(&porti, &porto) && cmp_port(&porti, &portr));
- if (!cmp_port(&porti, &porto)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_port(&porti);
- fprintf(stdout, "got:\n");
- print_port(&porto);
- }
- if (!cmp_port(&porti, &portr)) {
- fprintf(stdout, " result error, sent:\n");
- print_port(&porti);
- fprintf(stdout, "got:\n");
- print_port(&portr);
- }
- return -1;
-}
-
-static int ref_test(IC_Env *env)
-{
- erlang_ref refi = { "node1", 3, {1, 2, 3}, 1},
- refo, refr;
-
- fprintf(stdout, "\n======== m_i_ref test ======\n\n");
- refr = m_i_ref_test(NULL, &refi, &refo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_ref(&refi, &refo) && cmp_ref(&refi, &refr));
- if (!cmp_ref(&refi, &refo)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_ref(&refi);
- fprintf(stdout, "got:\n");
- print_ref(&refo);
- }
- if (!cmp_ref(&refi, &refr)) {
- fprintf(stdout, " result error, sent:\n");
- print_ref(&refi);
- fprintf(stdout, "got:\n");
- print_ref(&refr);
- }
- return -1;
-}
-
-static int term_test(IC_Env *env)
-{
- ETERM *ti, *to, *tr;
-
- ti = erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]");
-
- fprintf(stdout, "\n======== m_i_term test ======\n\n");
- tr = m_i_term_test(NULL, ti, &to, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(erl_match(ti, to) && erl_match(ti, tr));
- if (!erl_match(ti, to)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_term(ti);
- fprintf(stdout, "got:\n");
- print_term(to);
- }
- if (!erl_match(ti, tr)) {
- fprintf(stdout, " result error, sent:\n");
- print_term(ti);
- fprintf(stdout, "got:\n");
- print_term(tr);
- }
- erl_free_term(ti);
- erl_free_term(to);
- erl_free_term(tr);
- return -1;
-}
-
-static int typedef_test(IC_Env *env)
-{
- m_banan mbi, mbo; /* erlang_port */
- m_apa mai; /* ETERM* */
- m_apa mao = NULL;
- long tl;
-
- strcpy(mbi.node,"node");
- mbi.id = 15;
- mbi.creation = 1;
-
- fprintf(stdout, "\n======== m_i_typedef test ======\n\n");
- mai = erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]");
- tl = m_i_typedef_test(NULL, mai, &mbi, &mao, &mbo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(erl_match(mai, mao) && cmp_port(&mbi, &mbo) && tl == 4711);
- if (!erl_match(mai, mao)) {
- fprintf(stdout, " out parameter error (term), sent:\n");
- print_term(mai);
- fprintf(stdout, "got:\n");
- print_term(mao);
- }
- if (!cmp_port(&mbi, &mbo)) {
- fprintf(stdout, " out parameter error (port), sent:\n");
- print_port(&mbi);
- fprintf(stdout, "got:\n");
- print_port(&mbo);
- }
- if (tl != 4711) {
- fprintf(stdout, " result error, sent: 4711, got %ld\n", tl);
- }
- erl_free_term(mai);
- erl_free_term(mao);
- return -1;
-}
-
-static int inline_sequence_test(IC_Env *env)
-{
- int i;
- long al[500];
- m_s isi = {4711, {500, 10, al}},
- *iso, *isr;
-
- for (i = 0; i < 500; i++)
- al[i]=i;
- fprintf(stdout, "\n======== m_i_inline_sequence test ======\n\n");
- isr = m_i_inline_sequence_test(NULL, &isi, &iso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_s(&isi, iso) && cmp_s(&isi, isr));
- if (!cmp_s(&isi, iso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_s(&isi);
- fprintf(stdout, "got:\n");
- print_s(iso);
- }
- if (!cmp_s(&isi, isr)) {
- fprintf(stdout, " result error, sent:\n");
- print_s(&isi);
- fprintf(stdout, "got:\n");
- print_s(isr);
- }
- CORBA_free(iso);
- CORBA_free(isr);
- return -1;
-}
-
-static int term_sequence_test(IC_Env *env)
-{
- ETERM* et_array[4] = {
- erl_format("[{apa, 1, 23}, \"string\", {1.23, 45}]"),
- erl_format("[{banan, 1, 23}, \"string\", {1.23, 45}]"),
- erl_format("[{apelsin, 1, 23}, \"string\", {1.23, 45}]"),
- erl_format("[{mango, 1, 23}, \"string\", {1.23, 45}]")};
- m_etseq etsi = {4, 4, et_array}, *etso, *etsr;
-
- fprintf(stdout, "\n======== m_i_term_sequence test ======\n\n");
- etsr = m_i_term_sequence_test(NULL, &etsi, &etso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_etseq(&etsi, etso) && cmp_etseq(&etsi, etsr));
- if (!cmp_etseq(&etsi, etso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_etseq(&etsi);
- fprintf(stdout, "got:\n");
- print_etseq(etso);
- }
- if (!cmp_etseq(&etsi, etsr)) {
- fprintf(stdout, " result error, sent:\n");
- print_etseq(&etsi);
- fprintf(stdout, "got:\n");
- print_etseq(etsr);
- }
- free_etseq_buf(&etsi);
- free_etseq_buf(etso);
- free_etseq_buf(etsr);
- CORBA_free(etso);
- CORBA_free(etsr);
- return -1;
-}
-
-static int term_struct_test(IC_Env *env)
-{
- m_et eti = { erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]"),
- 121212 };
- m_et eto, etr;
-
- fprintf(stdout, "\n======== m_i_term_struct test ======\n\n");
- etr = m_i_term_struct_test(NULL, &eti, &eto, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_et(&eti, &eto) && cmp_et(&eti, &etr));
- if (!cmp_et(&eti, &eto)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_et(&eti);
- fprintf(stdout, "got:\n");
- print_et(&eto);
- }
- if (!cmp_et(&eti, &etr)) {
- fprintf(stdout, " result error, sent:\n");
- print_et(&eti);
- fprintf(stdout, "got:\n");
- print_et(&etr);
- }
- free_et(&eti);
- free_et(&eto);
- free_et(&etr);
- return -1;
-}
-
-static int wstring1_test(IC_Env *env)
-{
- CORBA_wchar wsi[] = {100, 101, 102, 103, 104, 0}, *wso, *wsr;
-
- fprintf(stdout, "\n======== m_i_wstring1 test ======\n\n");
- wsr = m_i_wstring1_test(NULL, wsi, &wso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_wstr(wsi, wso) && cmp_wstr(wsi, wsr));
- if (!cmp_wstr(wsi, wso)) {
- fprintf(stdout, " out parameter error, sent: \n");
- print_wstr(wsi);
- fprintf(stdout, "got:\n");
- print_wstr(wso);
- }
- if (!cmp_wstr(wsi, wsr)) {
- fprintf(stdout, " result error, sent: \n");
- print_wstr(wsi);
- fprintf(stdout, "got:\n");
- print_wstr(wsr);
- }
- CORBA_free(wso);
- CORBA_free(wsr);
- return -1;
-}
-
-/* Compare functions */
-static int cmp_aseq(m_aseq *a1, m_aseq *a2)
-{
- int i;
-
- if (a1->_length != a2->_length)
- return 0;
- for (i = 0; i < a1->_length; i++)
- if (cmp_a(&(a1->_buffer[i]), &(a2->_buffer[i])) == 0)
- return 0;
- return 1;
-}
-
-static int cmp_a(m_a *a1, m_a *a2)
-{
- return a1->l == a2->l &&
- a1->d == a2->d &&
- cmp_bseq(&a1->y, &a2->y);
-}
-
-static int cmp_bseq(m_bseq *b1, m_bseq *b2)
-{
- int i;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++)
- if (cmp_b(&(b1->_buffer[i]), &(b2->_buffer[i])) == 0)
- return 0;
- return 1;
-}
-
-static int cmp_b(m_b *b1, m_b *b2)
-{
- return b1->l == b2->l && b1->c == b2->c;
-}
-
-static int cmp_lseq(m_lseq *b1, m_lseq *b2)
-{
- int i;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++)
- if (b1->_buffer[i] != b2->_buffer[i])
- return 0;
- return 1;
-}
-
-static int cmp_etseq(m_etseq *b1, m_etseq *b2)
-{
- int i;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++)
- if (!erl_match(b1->_buffer[i], b2->_buffer[i]))
- return 0;
- return 1;
-}
-
-static int cmp_et(m_et* b1, m_et *b2)
-{
- return erl_match(b1->e, b2->e) && b1->l == b2->l;
-}
-
-static int cmp_es(m_es *b1, m_es *b2)
-{
- return b1->f == b2->f && b1->l == b2->l;
-}
-
-static int cmp_arr1(m_arr1 b1, m_arr1 b2)
-{
- int i;
-
- for (i = 0; i < 500; i++)
- if (b1[i] != b2[i])
- return 0;
- return 1;
-}
-
-static int cmp_dd(m_dd b1, m_dd b2)
-{
-
- int i, j;
-
- for (i = 0; i < 2; i++)
- for (j = 0; j < 3; j++)
- if (b1[i][j] != b2[i][j])
- return 0;
- return 1;
-}
-
-
-
-static int cmp_strRec(m_strRec *b1, m_strRec *b2)
-{
- int i, j;
-
- if (b1->bb != b2->bb)
- return 0;
- if (!cmp_str(b1->str4,b2->str4))
- return 0;
- if (b1->str5._length != b2->str5._length)
- return 0;
- for (j = 0; j < b1->str5._length; j++)
- if (b1->str5._buffer[j] != b2->str5._buffer[j])
- return 0;
- if (!cmp_str(b1->str6,b2->str6))
- return 0;
- for (i = 0; i < 2; i++)
- for (j = 0; j < 3; j++)
- if (b1->str7[i][j] != b2->str7[i][j])
- return 0;
- for (j = 0; j < 3; j++)
- if (b1->str8[j] != b2->str8[j])
- return 0;
- if (!cmp_str(b1->str9,b2->str9))
- return 0;
- if (b1->str10._length != b2->str10._length)
- return 0;
- for (j = 0; j < b1->str10._length; j++)
- if (b1->str10._buffer[j] != b2->str10._buffer[j])
- return 0;
- return 1;
-}
-
-
-static int cmp_sseq(m_sseq *b1, m_sseq *b2)
-{
- int i;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++)
- if (!cmp_str(b1->_buffer[i], b2->_buffer[i]))
- return 0;
- return 1;
-}
-
-
-static int cmp_pid(erlang_pid *p1, erlang_pid *p2)
-{
- return cmp_str(p1->node,p2-> node) &&
- p1->num == p2->num &&
- p1->serial == p2->serial &&
- p1->creation == p2->creation;
-}
-
-static int cmp_port(erlang_port *p1, erlang_port *p2)
-{
- return cmp_str(p1->node,p2-> node) && p1->id == p2->id;
-}
-
-static int cmp_ref(erlang_ref *p1, erlang_ref *p2)
-{
- return cmp_str(p1->node, p2->node) &&
- p1->len == p2->len &&
- (p1->len < 1 || p1->n[0] == p2->n[0]) &&
- (p1->len < 2 || p1->n[1] == p2->n[1]) &&
- (p1->len < 3 || p1->n[2] == p2->n[2]);
-}
-
-static int cmp_s(m_s *b1, m_s *b2)
-{
- int i;
-
- if (b1->l != b2->l)
- return 0;
- if (b1->sl._length != b2->sl._length)
- return 0;
- for (i = 0; i < b1->sl._length; i++)
- if (b1->sl._buffer[i] != b2->sl._buffer[i])
- return 0;
- return 1;
-}
-
-
-static int cmp_ssstr3(m_ssstr3 *b1, m_ssstr3 *b2)
-{
- int i,j;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++) {
- if (b1->_buffer[i]._length != b2->_buffer[i]._length)
- return 0;
- for (j = 0; j < b1->_buffer[i]._length; j++)
- if (!cmp_str(b1->_buffer[i]._buffer[j],
- b2->_buffer[i]._buffer[j]))
- return 0;
- }
- return 1;
-}
-
-
-
-static int cmp_ssarr3(m_ssarr3 *b1, m_ssarr3 *b2)
-{
- int i;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++) {
- if (!cmp_sarr3(&b1->_buffer[i], &b2->_buffer[i]))
- return 0;
- }
- return 1;
-}
-
-static int cmp_sarr3(m_sarr3 *b1, m_sarr3 *b2)
-{
- int i;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++) {
- if (!cmp_arr3(b1->_buffer[i], b2->_buffer[i]))
- return 0;
- }
- return 1;
-}
-
-static int cmp_arr3(m_arr3 b1, m_arr3 b2)
-{
- int i;
-
- for (i = 0; i < sizeof(m_arr3)/sizeof(CORBA_long); i++) {
- if (b1[i] != b2[i])
- return 0;
- }
- return 1;
-}
-
-/* Print functions */
-static void print_aseq(m_aseq *a)
-{
- int i;
- fprintf(stdout, "\nm_aseq size: %ld --------\n", a->_length);
- for (i = 0; i < a->_length; i++)
- print_a(&(a->_buffer[i]));
-}
-
-static void print_a(m_a *a)
-{
- fprintf(stdout, "\nm_a --------\n l: %ld\n d:%f\n", a->l, a->d);
- print_bseq(&a->y);
-}
-
-static void print_bseq(m_bseq *b)
-{
- int i;
-
- fprintf(stdout, "\nm_bseq size: %ld --------\n",b->_length);
- for (i = 0; i < b->_length; i++)
- print_b(&(b->_buffer[i]));
-}
-
-static void print_lseq(m_lseq *b)
-{
- int i;
-
- fprintf(stdout, "\nm_lseq size: %ld --------\n",b->_length);
- for (i = 0; i < b->_length; i++)
- fprintf(stdout, "[%d]: %ld\n", i, b->_buffer[i]);
-}
-
-static void print_b(m_b *b)
-{
- fprintf(stdout, "\nm_b --------\n l: %ld\n c: %c\n", b->l, b->c);
-}
-
-
-static void print_etseq(m_etseq *b)
-{
- int i;
-
- for (i = 0; i < b->_length; i++) {
- fprintf(stdout, "[%d]:\n", i);
- erl_print_term(stdout, b->_buffer[i]);
- }
-}
-
-
-static void print_et(m_et* b)
-{
- fprintf(stdout, "\net struct --------\n");
- erl_print_term(stdout, b->e);
- fprintf(stdout, "long: %ld\n", b->l);
- fprintf(stdout, "\n--------\n");
-}
-
-static void print_es(m_es *b)
-{
- fprintf(stdout, "\nm_es --------\n f: %d\n l: %ld\n", b->f, b->l);
-}
-
-
-static void print_arr1(long a[10])
-{
- int i;
-
- for (i = 0; i < 10; i++)
- fprintf(stdout, "\n[%d]: %ld\n", i, a[i]);
-}
-
-static void print_dd(long a[2][3])
-{
- int i, j;
-
- fprintf(stdout, "\nlong dd[2][3] --------\n");
- for (i = 0; i < 2; i++)
- for (j = 0; j < 3; j++)
- fprintf(stdout, "\n[%d][%d]: %ld\n", i, j, a[i][j]);
-}
-
-
-static void print_strRec(m_strRec* sr)
-{
- int i, j;
-
- fprintf(stdout, "\nboolean bb : %d\n",sr->bb);
- fprintf(stdout, "string str4 : %s\n",sr->str4);
- fprintf(stdout, "str7[2][3] :\n");
- for (i = 0; i < 2; i++)
- for (j = 0; j < 3; j++)
- fprintf(stdout, "str7[%d][%d]: %ld\n", i, j, sr->str7[i][j]);
- fprintf(stdout, "str5._length : %ld\n",sr->str5._length);
- for (j = 0; j < sr->str5._length; j++)
- fprintf(stdout, "str5._buffer[%d]: %c\n", j, sr->str5._buffer[j]);
- fprintf(stdout, "string str6 : %s\n",sr->str6);
- fprintf(stdout, "str8 :\n");
- for (j = 0; j < 3; j++)
- fprintf(stdout, "str8[%d]: %c\n", j, sr->str8[j]);
- fprintf(stdout, "string str9 : %s\n",sr->str9);
- fprintf(stdout, "str10._length : %ld\n",sr->str10._length);
- for (j = 0; j < sr->str10._length; j++)
- fprintf(stdout, "str10._buffer[%d]: %c\n", j, sr->str10._buffer[j]);
-}
-
-static void print_sseq(m_sseq *b)
-{
- int i;
-
- fprintf(stdout, "\nm_sseq size: %ld --------\n",b->_length);
- for (i = 0; i < b->_length; i++)
- fprintf(stdout, "%s\n", b->_buffer[i]);
-
-}
-
-
-static void print_pid(erlang_pid *p)
-{
- fprintf(stdout, "\nerlang_pid --------\n node: %s\n num: %d\n "
- "serial: %d\n creation: %d\n",
- p->node, p->num, p->serial, p->creation);
-}
-
-static void print_port(erlang_port *p)
-{
- fprintf(stdout, "\nerlang_port --------\n node: %s\n id: %d\n "
- "creation: %d\n", p->node, p->id, p->creation);
-}
-
-static void print_ref(erlang_ref *p)
-{
- fprintf(stdout, "\nerlang_ref --------\n node: %s\n len: %d\n "
- "n[0]: %d\n n[1]: %d\n n[2]: %d\n creation: %d\n",
- p->node, p->len, p->n[0], p->n[1], p->n[2], p->creation);
-}
-
-static void print_term(ETERM *t)
-{
- fprintf(stdout, "\nETERM --------\n");
- erl_print_term(stdout, t);
- fprintf(stdout, "\n--------\n");
-}
-
-static void print_s(m_s *p)
-{
- int i;
-
- fprintf(stdout, "\n%ld\n", p->l);
- for (i = 0; i < p->sl._length; i++)
- fprintf(stdout, "\n[%d]: %ld\n", i, p->sl._buffer[i]);
-}
-
-
-static void print_ssstr3(m_ssstr3 *b1)
-{
- int i,j;
-
- fprintf(stdout, "\nSSSTR3 --------\n");
- fprintf(stdout,"b1->_length = %ld\n",b1->_length);
- for (i = 0; i < b1->_length; i++) {
- fprintf(stdout,"\nb1->_buffer[%d]._length %ld\n",
- i, b1->_buffer[i]._length);
- for (j = 0; j < b1->_buffer[i]._length; j++)
- fprintf(stdout,"b1->_buffer[%d]._buffer[%d] = %s\n",
- i, j, b1->_buffer[i]._buffer[j]);
- }
- fprintf(stdout, "\n--------\n");
-}
-
-static void print_wstr(CORBA_wchar *ws)
-{
- int i = 0;
-
- fprintf(stdout, "\nwstr --------\n");
- while (ws[i]) {
- fprintf(stdout, "[%d]: %ld\n", i, ws[i]);
- i++;
- }
- fprintf(stdout, "\n--------\n");
-}
-
-
-static void print_ssarr3(m_ssarr3 *b1)
-{
- int i;
-
- fprintf(stdout, "\nssarr3 --------\n");
- fprintf(stdout,"length: %ld\n",b1->_length);
- fprintf(stdout, "buffer:\n");
- for (i = 0; i < b1->_length; i++)
- print_sarr3(&b1->_buffer[i]);
- fprintf(stdout, "\n--------\n");
-}
-
-static void print_sarr3(m_sarr3 *b1)
-{
- int i;
-
- fprintf(stdout, "\nsarr3 --------\n");
- fprintf(stdout,"length: %ld\n",b1->_length);
- fprintf(stdout, "buffer:\n");
- for (i = 0; i < b1->_length; i++)
- print_arr3(b1->_buffer[i]);
- fprintf(stdout, "\n--------\n");
-}
-
-static void print_arr3(m_arr3 b1)
-{
- int i;
-
- fprintf(stdout, "\narr3 --------\n");
- for (i = 0; i < sizeof(m_arr3)/sizeof(CORBA_long); i++)
- fprintf(stdout, "%ld ", b1[i]);
- fprintf(stdout, "\n--------\n");
-}
-
-static void free_etseq_buf(m_etseq *b)
-{
- int i;
-
- for (i = 0; i < b->_length; i++)
- erl_free_term(b->_buffer[i]);
-}
-
-static void free_et(m_et* b)
-{
- erl_free_term(b->e);
-}
-
-static void showtime(MyTimeval *start, MyTimeval *stop)
-{
- MyTimeval elapsed;
-
- elapsed.tv_sec = stop->tv_sec - start->tv_sec;
- elapsed.tv_usec = stop->tv_usec - start->tv_usec;
- while (elapsed.tv_usec < 0) {
- elapsed.tv_sec -= 1;
- elapsed.tv_usec += 1000000;
- }
- fprintf(stderr,"%ld.%06ld seconds\n",elapsed.tv_sec, elapsed.tv_usec);
-}
-
-static void my_gettimeofday(MyTimeval *tv)
-#ifdef __WIN32__
-#define EPOCH_JULIAN_DIFF 11644473600i64
-{
- SYSTEMTIME t;
- FILETIME ft;
- LONGLONG lft;
-
- GetSystemTime(&t);
- SystemTimeToFileTime(&t, &ft);
- memcpy(&lft, &ft, sizeof(lft));
- tv->tv_usec = (long) ((lft / 10i64) % 1000000i64);
- tv->tv_sec = (long) ((lft / 10000000i64) - EPOCH_JULIAN_DIFF);
-}
-#elif defined VXWORKS
-{
- int rate = sysClkRateGet(); /* Ticks per second */
- unsigned long ctick = tickGet();
- tv->tv_sec = ctick / rate; /* secs since reboot */
- tv->tv_usec = ((ctick - (tv->tv_sec * rate))*1000000)/rate;
-}
-#else
-{
- gettimeofday(tv, NULL);
-}
-#endif
diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/c_erl_test.idl b/lib/ic/test/c_client_erl_server_proto_SUITE_data/c_erl_test.idl
deleted file mode 100644
index b6ba1583f3..0000000000
--- a/lib/ic/test/c_client_erl_server_proto_SUITE_data/c_erl_test.idl
+++ /dev/null
@@ -1,174 +0,0 @@
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 2003-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-#include "erlang.idl"
-
-
-const short TestConst = 1;
-
-module m {
-
- const short TestConst = 2;
-
- struct b {
- long l;
- char c;
- };
-
- struct simple {
- long l;
- b b_t;
- };
-
- enum fruit {orange, banana, apple, peach, pear};
-
- typedef sequence<long> lseq;
-
- typedef sequence<b> bseq;
-
- struct a {
- long l;
- bseq y;
- double d;
- };
-
- typedef sequence<a> aseq;
-
- typedef sequence<string> sseq;
- typedef string str;
- typedef long myLong;
-
- typedef long arr1[500], dd[2][3];
-
- typedef erlang::term apa;
- typedef erlang::port banan;
-
- typedef sequence<erlang::term> etseq;
-
- struct s {
- long l;
- sequence<long> sl;
- };
-
- struct es {
- fruit f;
- myLong l;
- };
-
- struct et {
- erlang::term e;
- long l;
- };
-
-
- typedef sequence<char> str1;
- typedef string<12> str2;
- typedef char str3[3];
-
- typedef sequence<string> sstr3; // sequence of string
- typedef sequence<sstr3> ssstr3; // sequence of sequences of strings
-
- typedef long arr3[3]; // array of long
- typedef sequence<arr3> sarr3; // sequence of array
- typedef sequence<sarr3> ssarr3; // sequence of sequnces of arrays of strings
-
- struct strRec{
- boolean bb;
- string str4;
- long str7[3][2];
- sequence<char> str5;
- string<12> str6;
- str3 str8;
- str2 str9;
- str1 str10;
- };
-
-
- struct dyn {
- long l;
- sequence<long> sl;
- };
- typedef dyn arr2[1][2];
-
-
- interface i {
-
- const short TestConst = 3;
-
- //arr2 suck(in arr2 x, out arr2 y );
-
- ///////////////////////////////// attribute long l;
-
- // simple types
- void void_test();
- long long_test(in long a, out long a1);
- long long longlong_test(in long long a, out long long a1);
- unsigned short ushort_test(in unsigned short a, out unsigned short a1);
- unsigned long ulong_test(in unsigned long a, out unsigned long a1);
- unsigned long long ulonglong_test(in unsigned long long a, out unsigned long long a1);
- double double_test(in double a, out double a1);
- char char_test(in char a, out char a1);
- wchar wchar_test(in wchar a, out wchar a1);
- octet octet_test(in octet a, out octet a1);
- boolean bool_test(in boolean a, out boolean a1);
-
- // Seq. and struct tests
- b struct_test(in b a, out b a1);
- es struct2_test(in es a, out es a1);
- //simple struct3_test(in simple x, out simple y);
- bseq seq1_test(in bseq a, out bseq a1);
- aseq seq2_test(in aseq a, out aseq a1);
- lseq seq3_test(in lseq a, out lseq a1);
- ssstr3 seq4_test(in ssstr3 a, out ssstr3 a1);
- ssarr3 seq5_test(in ssarr3 a, out ssarr3 a1);
-
- // Array tests
- arr1 array1_test(in arr1 a, out arr1 a1);
- dd array2_test(in dd a, out dd a1);
-
- // enum test
- fruit enum_test(in fruit a, out fruit a1);
-
- // string tests
- string string1_test(in string a, out string a1);
- wstring wstring1_test(in wstring a, out wstring a1);
- sseq string2_test(in sseq a, out sseq a1);
- str string3_test(in str a, out str a1);
- strRec string4_test(in strRec a, out strRec a1);
-
- // Special erlang types
- erlang::pid pid_test(in erlang::pid a, out erlang::pid a1);
- erlang::port port_test(in erlang::port a, out erlang::port a1);
- erlang::ref ref_test(in erlang::ref a, out erlang::ref a1);
- erlang::term term_test(in erlang::term a, out erlang::term a1);
-
- // typedef test
- long typedef_test(in apa a, in banan b, out apa a1, out banan b1);
-
- // inlined seq. test
- s inline_sequence_test(in s a, out s a1);
-
- // term seq. test
- etseq term_sequence_test(in etseq a, out etseq a1);
- // term struct test
- et term_struct_test(in et a, out et a1);
-
- };
-
-};
diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/erl_server.erl b/lib/ic/test/c_client_erl_server_proto_SUITE_data/erl_server.erl
deleted file mode 100644
index 2fe1dc2f79..0000000000
--- a/lib/ic/test/c_client_erl_server_proto_SUITE_data/erl_server.erl
+++ /dev/null
@@ -1,29 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(erl_server).
-
--export([run/0, stop/0]).
-
-run() ->
- m_i:oe_create().
-
-stop() ->
- gen_server:cast(cidl_test, stop).
diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/m_i_impl.erl b/lib/ic/test/c_client_erl_server_proto_SUITE_data/m_i_impl.erl
deleted file mode 100644
index 92420eaeb4..0000000000
--- a/lib/ic/test/c_client_erl_server_proto_SUITE_data/m_i_impl.erl
+++ /dev/null
@@ -1,162 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(m_i_impl).
--include("m.hrl").
-
--export([init/1, terminate/2, void_test/1, long_test/2, ushort_test/2,
- longlong_test/2, ulong_test/2, ulonglong_test/2,
- double_test/2, char_test/2, wchar_test/2, octet_test/2,
- bool_test/2, struct_test/2, struct2_test/2, seq1_test/2,
- seq2_test/2, seq3_test/2, seq4_test/2, seq5_test/2,
- array1_test/2, array2_test/2, enum_test/2, string1_test/2,
- string2_test/2, string3_test/2, string4_test/2, pid_test/2,
- port_test/2, ref_test/2, term_test/2, typedef_test/3,
- inline_sequence_test/2, '_set_l'/2, '_get_l'/1,
- term_struct_test/2, term_sequence_test/2, wstring1_test/2]).
-
--define(PRINTDEBUG(Case),
- io:format("erl_server: case: ~p~n"
- "erl_server: location: ~p~n", [Case, [?FILE, ?LINE]])).
--define(PRINTDEBUG2(Case, Msg),
- io:format("erl_server: case: ~p~n"
- "erl_server: Msg: ~p~n"
- "erl_server: location: ~p~n", [Case, Msg, [?FILE, ?LINE]])).
-
-init(Env) ->
- {ok, []}.
-
-terminate(F, R) ->
- ok.
-
-'_get_l'(State) ->
- ?PRINTDEBUG("_get_l"),
- {reply, State, State}.
-void_test(State) ->
- ?PRINTDEBUG("void_test"),
- {reply, ok, State}.
-
-'_set_l'(State, V) ->
- ?PRINTDEBUG2("_set_l", V),
- {reply, ok, V}.
-ushort_test(State, V) ->
- ?PRINTDEBUG2("ushort_test", V),
- {reply, {V, V}, State}.
-long_test(State, V) ->
- ?PRINTDEBUG2("long_test", V),
- {reply, {V, V}, State}.
-longlong_test(State, V) ->
- ?PRINTDEBUG2("longlong_test", V),
- {reply, {V, V}, State}.
-ulong_test(State, V) ->
- ?PRINTDEBUG2("ulong_test", V),
- {reply, {V, V}, State}.
-ulonglong_test(State, V) ->
- ?PRINTDEBUG2("ulonglong_test", V),
- {reply, {V, V}, State}.
-double_test(State, V) ->
- ?PRINTDEBUG2("double_test", V),
- {reply, {V, V}, State}.
-char_test(State, V) ->
- ?PRINTDEBUG2("char_test", V),
- {reply, {V, V}, State}.
-wchar_test(State, V) ->
- ?PRINTDEBUG2("wchar_test", V),
- {reply, {V, V}, State}.
-octet_test(State, V) ->
- ?PRINTDEBUG2("octet_test", V),
- {reply, {V, V}, State}.
-bool_test(State, V) ->
- ?PRINTDEBUG2("bool_test", V),
- {reply, {V, V}, State}.
-
-struct_test(State, V) ->
- ?PRINTDEBUG2("struct_test", V),
- {reply, {V, V}, State}.
-struct2_test(State, V) ->
- ?PRINTDEBUG2("struct2_test", V),
- {reply, {V, V}, State}.
-seq1_test(State, V) ->
- ?PRINTDEBUG2("seq1_test", V),
- {reply, {V, V}, State}.
-seq2_test(State, V) ->
- ?PRINTDEBUG2("seq2_test", V),
- {reply, {V, V}, State}.
-seq3_test(State, V) ->
- ?PRINTDEBUG2("seq3_test", V),
- {reply, {V, V}, State}.
-seq4_test(State, V) ->
- ?PRINTDEBUG2("seq4_test", V),
- {reply, {V, V}, State}.
-seq5_test(State, V) ->
- ?PRINTDEBUG2("seq5_test", V),
- {reply, {V, V}, State}.
-array1_test(State, V) ->
- ?PRINTDEBUG2("array1_test", V),
- {reply, {V, V}, State}.
-array2_test(State, V) ->
- ?PRINTDEBUG2("array2_test", V),
- {reply, {V, V}, State}.
-enum_test(State, V) ->
- ?PRINTDEBUG2("enum_test", V),
- {reply, {V, V}, State}.
-string1_test(State, V) ->
- ?PRINTDEBUG2("string1_test", V),
- {reply, {V, V}, State}.
-string2_test(State, V) ->
- ?PRINTDEBUG2("string2_test", V),
- {reply, {V, V}, State}.
-string3_test(State, V) ->
- ?PRINTDEBUG2("string3_test", V),
- {reply, {V, V}, State}.
-string4_test(State, V) ->
- ?PRINTDEBUG2("string4_test", V),
- {reply, {V, V}, State}.
-pid_test(State, V) ->
- ?PRINTDEBUG2("pid_test", V),
- {reply, {V, V}, State}.
-port_test(State, V) ->
- ?PRINTDEBUG2("port_test", binary_to_list(term_to_binary(V))),
- {reply, {V, V}, State}.
-ref_test(State, V) ->
- ?PRINTDEBUG2("ref_test", binary_to_list(term_to_binary(V))),
- {reply, {V, V}, State}.
-term_test(State, V) ->
- ?PRINTDEBUG2("term_test", V),
- {reply, {V, V}, State}.
-typedef_test(State, A, B) ->
- ?PRINTDEBUG2("typedef_test", [A,B]),
- {reply, {4711, A, B}, State}.
-inline_sequence_test(State, V) ->
- ?PRINTDEBUG2("inline_sequence_test", V),
- {reply, {V, V}, State}.
-term_sequence_test(State, V) ->
- ?PRINTDEBUG2("term_sequence_test", V),
- {reply, {V, V}, State}.
-term_struct_test(State, V) ->
- ?PRINTDEBUG2("term_struct_test", V),
- {reply, {V, V}, State}.
-wstring1_test(State, V) ->
- ?PRINTDEBUG2("wstring1_test", V),
- {reply, {V, V}, State}.
-
-
-
-
diff --git a/lib/ic/test/c_client_erl_server_proto_SUITE_data/my.c b/lib/ic/test/c_client_erl_server_proto_SUITE_data/my.c
deleted file mode 100644
index 46920ce05f..0000000000
--- a/lib/ic/test/c_client_erl_server_proto_SUITE_data/my.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2004-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-
-#include "ic.h"
-#include "m_i.h"
-
-int my_prepare_notification_encoding(CORBA_Environment *env)
-{
- return oe_prepare_notification_encoding(env);
-}
-
-int my_send_notification(CORBA_Environment *env)
-{
- return oe_send_notification(env);
-}
-
-int my_prepare_request_encoding(CORBA_Environment *env)
-{
- return oe_prepare_request_encoding(env);
-}
-
-int my_send_request_and_receive_reply(CORBA_Environment *env)
-{
- return oe_send_request_and_receive_reply(env);
-}
-
-int my_prepare_reply_decoding(CORBA_Environment *env)
-{
- return oe_prepare_reply_decoding(env);
-}
-
-
-
diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE.erl b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE.erl
deleted file mode 100644
index 334db7c1da..0000000000
--- a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE.erl
+++ /dev/null
@@ -1,265 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-%%----------------------------------------------------------------------
-%% Purpose : Test suite for c-client/erl-server
-%%----------------------------------------------------------------------
-
--module(c_client_erl_server_proto_tmo_SUITE).
--include_lib("common_test/include/ct.hrl").
-
--export([init_per_testcase/2, end_per_testcase/2,
- all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- void_test/1, long_test/1, long_long_test/1,
- unsigned_short_test/1, unsigned_long_test/1,
- unsigned_long_long_test/1, double_test/1, char_test/1,
- wchar_test/1, octet_test/1, bool_test/1, struct_test/1,
- struct2_test/1, seq1_test/1, seq2_test/1, seq3_test/1,
- seq4_test/1, seq5_test/1, array1_test/1, array2_test/1,
- enum_test/1, string1_test/1, string2_test/1, string3_test/1,
- string4_test/1, pid_test/1, port_test/1, ref_test/1, term_test/1,
- typedef_test/1, inline_sequence_test/1, term_sequence_test/1,
- term_struct_test/1, wstring1_test/1]).
-
--define(DEFAULT_TIMEOUT, 20000).
--define(PORT_TIMEOUT, 15000).
--define(ERLANG_SERVER_NAME, idl_erlang_server).
--define(C_CLIENT_NODE_NAME, c_client_idl_test).
-
-%% Add/remove code path and watchdog before/after each test case.
-%%
-init_per_testcase(_Case, Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- code:add_patha(DataDir),
-
- %% Since other test suites use the module m_i, we have
- %% to make sure we are using the right m_i module.
- code:purge(m_i),
- code:load_file(m_i),
-
- WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- code:del_path(DataDir),
- WatchDog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [void_test, long_test, long_long_test,
- unsigned_short_test, unsigned_long_test,
- unsigned_long_long_test, double_test, char_test,
- wchar_test, octet_test, bool_test, struct_test,
- struct2_test, seq1_test, seq2_test, seq3_test,
- seq4_test, seq5_test, array1_test, array2_test,
- enum_test, string1_test, string2_test, string3_test,
- string4_test, pid_test, port_test, ref_test, term_test,
- typedef_test, inline_sequence_test, term_sequence_test,
- term_struct_test, wstring1_test].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-array1_test(Config) ->
- do_test(array1_test, Config).
-
-array2_test(Config) ->
- do_test(array2_test, Config).
-
-bool_test(Config) ->
- do_test(bool_test, Config).
-
-char_test(Config) ->
- do_test(char_test, Config).
-
-double_test(Config) ->
- do_test(double_test, Config).
-
-enum_test(Config) ->
- do_test(enum_test, Config).
-
-inline_sequence_test(Config) ->
- do_test(inline_sequence_test, Config).
-
-long_long_test(Config) ->
- do_test(long_long_test, Config).
-
-long_test(Config) ->
- do_test(long_test, Config).
-
-octet_test(Config) ->
- do_test(octet_test, Config).
-
-pid_test(Config) ->
- do_test(pid_test, Config).
-
-port_test(Config) ->
- do_test(port_test, Config).
-
-ref_test(Config) ->
- do_test(ref_test, Config).
-
-seq1_test(Config) ->
- do_test(seq1_test, Config).
-
-seq2_test(Config) ->
- do_test(seq2_test, Config).
-
-seq3_test(Config) ->
- do_test(seq3_test, Config).
-
-seq4_test(Config) ->
- do_test(seq4_test, Config).
-
-seq5_test(Config) ->
- do_test(seq5_test, Config).
-
-string1_test(Config) ->
- do_test(string1_test, Config).
-
-string2_test(Config) ->
- do_test(string2_test, Config).
-
-string3_test(Config) ->
- do_test(string3_test, Config).
-
-string4_test(Config) ->
- do_test(string4_test, Config).
-
-struct2_test(Config) ->
- do_test(struct2_test, Config).
-
-struct_test(Config) ->
- do_test(struct_test, Config).
-
-term_sequence_test(Config) ->
- do_test(term_sequence_test, Config).
-
-term_struct_test(Config) ->
- do_test(term_struct_test, Config).
-
-term_test(Config) ->
- do_test(term_test, Config).
-
-typedef_test(Config) ->
- do_test(typedef_test, Config).
-
-unsigned_long_long_test(Config) ->
- do_test(unsigned_long_long_test, Config).
-
-unsigned_long_test(Config) ->
- do_test(unsigned_long_test, Config).
-
-unsigned_short_test(Config) ->
- do_test(unsigned_short_test, Config).
-
-void_test(Config) ->
- do_test(void_test, Config).
-
-wchar_test(Config) ->
- do_test(wchar_test, Config).
-
-wstring1_test(Config) ->
- do_test(wstring1_test, Config).
-
-
-%% It is here that all tests really are done.
-%%
-
-do_test(Case, Config) ->
- %% Trap exits
- process_flag(trap_exit, true),
- %% Start the server
- {ok, _Pid} = m_i:oe_create_link([], {local, ?ERLANG_SERVER_NAME}),
- Node = atom_to_list(node()),
- %% [NodeName, HostName] = string:tokens(Node, "@"),
- DataDir = proplists:get_value(data_dir, Config),
- %% io:format("~p: data directory: ~p~n", [?MODULE, DataDir]),
- Cookie = atom_to_list(erlang:get_cookie()),
- %% Start C-client node as a port program.
- Cmd = filename:join([DataDir, "c_client"]) ++
- " -this-node-name " ++ atom_to_list(?C_CLIENT_NODE_NAME) ++
- " -peer-node " ++ Node ++
- " -peer-process-name " ++ atom_to_list(?ERLANG_SERVER_NAME) ++
- " -cookie " ++ Cookie ++
- " -test-case " ++ atom_to_list(Case),
- Port = open_port({spawn, Cmd}, [exit_status, eof, stderr_to_stdout]),
- Res = wait_for_completion(Port),
- %% Kill off node if there was timeout
- case Res of
- {error, timeout} ->
- catch rpc:cast(?C_CLIENT_NODE_NAME, erlang, halt, [1]);
- _ ->
- ok
- end,
- process_flag(trap_exit, false),
- catch m_i:stop(?ERLANG_SERVER_NAME),
- ok = Res.
-
-
-%% Wait for eof *and* exit status, but return if exit status indicates
-%% an error, or we have been waiting more than PORT_TIMEOUT seconds.
-%%
-wait_for_completion(Port) ->
- wait_for_completion(Port, 0).
-
-wait_for_completion(Port, N) when N < 2 ->
- receive
- {Port, {data, Bytes}} ->
- %% Relay output
- io:format("~s", [Bytes]),
- wait_for_completion(Port, N);
- {Port, {exit_status, 0}} ->
- wait_for_completion(Port, N + 1);
- {Port, {exit_status, Status}} ->
- {error, Status};
- {Port, eof} ->
- wait_for_completion(Port, N + 1);
- {'EXIT', Port, Reason} ->
- io:format("Port exited with reason: ~w~n", [Reason]),
- wait_for_completion(Port, N);
- {'EXIT', From, Reason} ->
- io:format("Got unexpected exit: ~p~n", [{'EXIT', From, Reason}]),
- wait_for_completion(Port, N)
- after ?PORT_TIMEOUT ->
- {error, timeout}
- end;
-wait_for_completion(_, _) ->
- ok.
-
-
-
diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/Makefile.src b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/Makefile.src
deleted file mode 100644
index 6d6bd9baab..0000000000
--- a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/Makefile.src
+++ /dev/null
@@ -1,155 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2004-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-# Makefile.src for c_client_erl_server test
-# Note: This file *must* work for both Unix and Windows
-#
-# We use both `rm' (Unix) and `del' (Windows) for removing files, but
-# with a `-' in front so that the error in not finding `rm' (`del') on
-# Windows (Unix) is ignored.
-#
-# VxWorks? XXX
-#
-
-.SUFFIXES:
-.SUFFIXES: .c .h .erl .idl @obj@ .@EMULATOR@
-
-
-# Variables from ts:
-#
-
-ERL_INCLUDE = @erl_include@
-
-IC_INCLUDE_PATH = @ic_include_path@
-IC_LIB = @ic_lib@
-
-ERL_INTERFACE_INCLUDE = @erl_interface_include@
-ERL_INTERFACE_LIB = @erl_interface_lib@
-ERL_INTERFACE_EILIB = @erl_interface_eilib@
-ERL_INTERFACE_THREADLIB = @erl_interface_threadlib@
-ERL_INTERFACE_SOCK_LIBS = @erl_interface_sock_libs@
-
-CC = @CC@
-## XXX Should set warning flag with a DEBUG_FLAG
-CFLAGS = @CFLAGS@ @DEFS@ -I@erl_include@ \
- -I@ic_include_path@ -I@erl_interface_include@
-
-LD = @LD@
-LDFLAGS = @CROSSLDFLAGS@
-LIBS = $(IC_LIB) $(ERL_INTERFACE_LIB) $(ERL_INTERFACE_EILIB) \
- $(ERL_INTERFACE_THREADLIB) @LIBS@ $(ERL_INTERFACE_SOCK_LIBS)
-ERLC = erlc
-
-# Generated C header files
-GEN_H_FILES = \
- m.h \
- m_i.h \
- oe_c_erl_test.h
-
-# Generated C files
-GEN_C_FILES = \
- m.c \
- m_i.c \
- oe_c_erl_test.c \
- oe_code_m_a.c \
- oe_code_m_arr1.c \
- oe_code_m_arr2.c \
- oe_code_m_arr3.c \
- oe_code_m_aseq.c \
- oe_code_m_b.c \
- oe_code_m_bseq.c \
- oe_code_m_dd.c \
- oe_code_m_dyn.c \
- oe_code_m_dyn_sl.c \
- oe_code_m_es.c \
- oe_code_m_et.c \
- oe_code_m_etseq.c \
- oe_code_m_fruit.c \
- oe_code_m_lseq.c \
- oe_code_m_s.c \
- oe_code_m_s_sl.c \
- oe_code_m_sarr3.c \
- oe_code_m_simple.c \
- oe_code_m_ssarr3.c \
- oe_code_m_sseq.c \
- oe_code_m_ssstr3.c \
- oe_code_m_sstr3.c \
- oe_code_m_str1.c \
- oe_code_m_str3.c \
- oe_code_m_strRec.c \
- oe_code_m_strRec_str5.c \
- oe_code_m_strRec_str7.c
-
-GEN_HRL_FILES = \
- m.hrl \
- m_i.hrl \
- oe_c_erl_test.hrl
-
-GEN_ERL_FILES = \
- m.erl \
- m_arr2.erl \
- m_arr3.erl \
- m_i.erl \
- m_str3.erl \
- oe_c_erl_test.erl
-
-C_FILES = $(GEN_C_FILES) c_client.c my.c
-
-OBJS = $(C_FILES:.c=@obj@)
-
-PGMS = c_client@exe@
-
-ERL_FILES = $(GEN_ERL_FILES) m_i_impl.erl
-
-EBINS = $(ERL_FILES:.erl=.@EMULATOR@)
-
-
-all: $(PGMS) $(EBINS)
-
-$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.built_erl
-$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.built_c
-$(OBJS): $(GEN_C_FILES) $(GEN_H_FILES)
-$(EBINS): $(GEN_ERL_FILES) $(GEN_HRL_FILES)
-
-clean:
- -rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
- c_erl_test.built_erl c_erl_test.built_c
- -del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
- c_erl_test.built_erl c_erl_test.built_c
-
-$(PGMS): $(OBJS)
- $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
-
-c_erl_test.built_c: c_erl_test.idl
- $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_client}" c_erl_test.idl
- echo done > c_erl_test.built_c
-
-c_erl_test.built_erl: c_erl_test.idl
- $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" c_erl_test.idl
- echo done > c_erl_test.built_erl
-
-.c@obj@:
- $(CC) -c -o $*@obj@ $(CFLAGS) $<
-
-.erl.@EMULATOR@:
- $(ERLC) -I $(IC_INCLUDE_PATH) $<
-
diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_client.c b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_client.c
deleted file mode 100644
index 33cfe71322..0000000000
--- a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_client.c
+++ /dev/null
@@ -1,1764 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2004-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/* C-client for test of IC.
- *
- * TODO:
- *
- * 1. XXX #includes for VxWorks, Windows
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifndef __WIN32__
-# include <unistd.h>
-#endif
-
-#include <string.h>
-
-#ifdef __WIN32__
-# include <time.h>
-# include <sys/timeb.h>
-#elif defined VXWORKS
-#include <time.h>
-#include <sys/times.h>
-#else
-#include <sys/time.h>
-#endif
-
-#include <ctype.h>
-
-#ifdef __WIN32__
-# include <winsock2.h>
-# include <windows.h>
-#else
-# include <sys/types.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <arpa/inet.h>
-# include <netdb.h>
-#endif
-
-#include "ei.h"
-#include "erl_interface.h"
-#include "m_i.h"
-
-#define HOSTNAMESZ 255
-#define NODENAMESZ 512
-
-#define INBUFSZ 10
-#define OUTBUFSZ 0
-
-#define MAXTRIES 5
-
-#define CHECK_EXCEPTION(x) \
- if ((x)->_major != CORBA_NO_EXCEPTION) { \
- fprintf(stderr,"\n\nException: %s\n\n", \
- (char *)CORBA_exception_value((x))); \
- CORBA_exception_free((x)); \
- return -1; \
- } \
-
-/* XXX Should free things here too! */
-#define RETURN_IF_OK(x) \
- if ((x)) {\
- fprintf(stdout, "ok\n");\
- return 0;\
- }\
-
-#define cmp_str(x,y) (!strcmp((x),(y)))
-#define cmp_wstr(x,y) (!ic_wstrcmp((x),(y)))
-
-typedef CORBA_Environment IC_Env;
-
-typedef int (*TestFunc)(IC_Env *);
-typedef struct {
- char *name;
- TestFunc func;
-} TestCase;
-
-static char longtext[] =
-"Introduction The IC application is an IDL compiler implemented in Erlang."
-" The IDL compiler generates client stubs and server skeletons."
-" Several back-ends are supported, and they fall into three main groups."
-" For more details on IC compiler options consult the ic(3) manual page."
-" Argument passing cases 1 Caller allocates all necessary storage,"
-" except that which may be encapsulated and managed within the parameter itself."
-" 2 The caller allocates a pointer and passes it by reference to the callee."
-" The callee sets the pointer to point to a valid instance of the parameter's type."
-" The caller is responsible for releasing the returned storage."
-" Following completion of a request, the caller is not allowed to modify any values"
-" in the returned storage. To do so the caller must first copy the returned instance"
-" into a new instance, then modify the new instance. 3 The caller allocates a"
-" pointer to an array slice which has all the same dimensions of the original"
-" array except the first, and passes it by reference to the callee. The callee sets"
-" the pointer to point to a valid instance of the array. The caller is responsible for"
-" releasing the returned storage. Following completion of a request, the caller is not"
-" allowed to modify any values in the returned storage. To do so the caller must first"
-" copy the returned instance into a new instance, then modify the new instance."
-" Generated Files Two files will be generated for each scope. One set of files will be"
-" generated for each module and each interface scope. An extra set is generated for"
-" those definitions at top level scope. One of the files is a header file(.h), and the"
-" other file is a C source code file (.c). In addition to these files a number of C"
-" source files will be generated for type encodings, they are named according to the "
-"following template: oe_code_<type>.c.";
-static char this_node[NODENAMESZ + 1];
-static char *progname;
-
-/* Test function prototypes */
-
-static int void_test(IC_Env *env);
-static int long_test(IC_Env *env);
-static int long_long_test(IC_Env *env);
-static int unsigned_short_test(IC_Env *env);
-static int unsigned_long_test(IC_Env *env);
-static int unsigned_long_long_test(IC_Env *env);
-static int double_test(IC_Env *env);
-static int char_test(IC_Env *env);
-static int wchar_test(IC_Env *env);
-static int octet_test(IC_Env *env);
-static int bool_test(IC_Env *env);
-static int struct_test(IC_Env *env);
-static int struct2_test(IC_Env *env);
-static int seq1_test(IC_Env *env);
-static int seq2_test(IC_Env *env);
-static int seq3_test(IC_Env *env);
-static int seq4_test(IC_Env *env);
-static int seq5_test(IC_Env *env);
-static int array1_test(IC_Env *env);
-static int array2_test(IC_Env *env);
-static int enum_test(IC_Env *env);
-static int string1_test(IC_Env *env);
-static int string2_test(IC_Env *env);
-static int string3_test(IC_Env *env);
-static int string4_test(IC_Env *env);
-static int pid_test(IC_Env *env);
-static int port_test(IC_Env *env);
-static int ref_test(IC_Env *env);
-static int term_test(IC_Env *env);
-static int typedef_test(IC_Env *env);
-static int inline_sequence_test(IC_Env *env);
-static int term_sequence_test(IC_Env *env);
-static int term_struct_test(IC_Env *env);
-static int wstring1_test(IC_Env *env);
-
-static TestCase test_cases[] = {
- {"void_test", void_test},
- {"long_test", long_test},
- {"long_long_test", long_long_test},
- {"unsigned_short_test", unsigned_short_test},
- {"unsigned_long_test", unsigned_long_test},
- {"unsigned_long_long_test", unsigned_long_long_test},
- {"double_test", double_test},
- {"char_test", char_test},
- {"wchar_test", wchar_test},
- {"octet_test", octet_test},
- {"bool_test", bool_test},
- {"struct_test", struct_test},
- {"struct2_test", struct2_test},
- {"seq1_test", seq1_test},
- {"seq2_test", seq2_test},
- {"seq3_test", seq3_test},
- {"seq4_test", seq4_test},
- {"seq5_test", seq5_test},
- {"array1_test", array1_test},
- {"array2_test", array2_test},
- {"enum_test", enum_test},
- {"string1_test", string1_test},
- {"string2_test", string2_test},
- {"string3_test", string3_test},
- {"string4_test", string4_test},
- {"pid_test", pid_test},
- {"port_test", port_test},
- {"ref_test", ref_test},
- {"term_test", term_test},
- {"typedef_test", typedef_test},
- {"inline_sequence_test", inline_sequence_test},
- {"term_sequence_test", term_sequence_test},
- {"term_struct_test", term_struct_test},
- {"wstring1_test", wstring1_test},
- {"", NULL}
-};
-
-/* Other prototypes */
-static int cmp_aseq(m_aseq *a1, m_aseq *a2);
-static int cmp_a(m_a *a1, m_a *a2);
-static int cmp_bseq(m_bseq *b1, m_bseq *b2);
-static int cmp_b(m_b *b1, m_b *b2);
-static int cmp_lseq(m_lseq *b1, m_lseq *b2);
-static int cmp_etseq(m_etseq *b1, m_etseq *b2);
-static int cmp_et(m_et* b1, m_et *b2);
-static int cmp_es(m_es *b1, m_es *b2);
-static int cmp_arr1(m_arr1 b1, m_arr1 b2);
-static int cmp_dd(m_dd b1, m_dd b2);
-static int cmp_strRec(m_strRec *b1, m_strRec *b2);
-static int cmp_sseq(m_sseq *b1, m_sseq *b2);
-static int cmp_pid(erlang_pid *p1, erlang_pid *p2);
-static int cmp_port(erlang_port *p1, erlang_port *p2);
-static int cmp_ref(erlang_ref *p1, erlang_ref *p2);
-static int cmp_s(m_s *b1, m_s *b2);
-static int cmp_ssstr3(m_ssstr3 *b1, m_ssstr3 *b2);
-static int cmp_ssarr3(m_ssarr3 *b1, m_ssarr3 *b2);
-static int cmp_sarr3(m_sarr3 *b1, m_sarr3 *b2);
-static int cmp_arr3(m_arr3 b1, m_arr3 b2);
-
-static void print_aseq(m_aseq *a);
-static void print_a(m_a *a);
-static void print_bseq(m_bseq *b);
-static void print_lseq(m_lseq *b);
-static void print_b(m_b *b);
-static void print_etseq(m_etseq *b);
-static void print_et(m_et* b);
-static void print_es(m_es *b);
-static void print_arr1(long a[500]);
-static void print_dd(long a[2][3]);
-static void print_strRec(m_strRec* sr);
-static void print_sseq(m_sseq *b);
-static void print_pid(erlang_pid *p);
-static void print_port(erlang_port *p);
-static void print_ref(erlang_ref *p);
-static void print_term(ETERM *t);
-static void print_s(m_s *p);
-static void print_ssstr3(m_ssstr3 *b1);
-static void print_ssarr3(m_ssarr3 *b1);
-static void print_sarr3(m_sarr3 *b1);
-static void print_arr3(m_arr3 b1);
-static void print_wstr(CORBA_wchar *ws);
-
-static void free_etseq_buf(m_etseq *b);
-static void free_et(m_et* b);
-
-#ifdef __WIN32__
-typedef struct {
- long tv_sec;
- long tv_usec;
-} MyTimeval;
-#else
-typedef struct timeval MyTimeval;
-#endif
-static void my_gettimeofday(MyTimeval *tv);
-static void showtime(MyTimeval *start, MyTimeval *stop);
-static void usage(void);
-static void done(int r);
-
-
-
-/* main */
-
-#ifdef VXWORKS
-int client(int argc, char **argv)
-#else
-int main(int argc, char **argv)
-#endif
-{
- struct hostent *hp;
- erlang_pid pid;
- MyTimeval start, stop;
- int i, fd, ires, tres;
- IC_Env *env;
- int tries = 0;
- char *this_node_name = NULL;
- char *peer_node = NULL;
- char *peer_process_name = NULL;
- char *cookie = NULL;
- char host[HOSTNAMESZ + 1];
- TestFunc test_func = NULL;
- TestCase *test_case;
- char *test_case_name = NULL;
-
-#ifdef __WIN32__
- WORD wVersionRequested;
- WSADATA wsaData;
-
- wVersionRequested = MAKEWORD(2, 0);
-
- if (WSAStartup(wVersionRequested, &wsaData) != 0) {
- fprintf(stderr, "Could not load winsock2 v2.0 compatible DLL");
- exit(1);
- }
-#endif
-
- progname = argv[0];
- host[HOSTNAMESZ] = '\0';
- if (gethostname(host, HOSTNAMESZ + 1) < 0) {
- fprintf(stderr, "Can't find own hostname\n");
- done(1);
- }
- if ((hp = gethostbyname(host)) == 0) {
- fprintf(stderr, "Can't get ip address for host %s\n", host);
- done(1);
- }
- for (i = 1; i < argc; i++) {
- if (cmp_str(argv[i], "-help")) {
- usage();
- done(0);
- } else if (cmp_str(argv[i], "-this-node-name")) {
- i++;
- this_node_name = argv[i];
- } else if (cmp_str(argv[i], "-peer-node")) {
- i++;
- peer_node = argv[i];
- } else if (cmp_str(argv[i], "-peer-process-name")) {
- i++;
- peer_process_name = argv[i];
- } else if (cmp_str(argv[i], "-cookie")) {
- i++;
- cookie = argv[i];
- } else if (cmp_str(argv[i], "-test-case")) {
- i++;
- test_case_name = argv[i];
- } else {
- fprintf(stderr, "Error : invalid argument \"%s\"\n", argv[i]);
- usage();
- done(1);
- }
- }
-
- if (this_node_name == NULL || peer_node == NULL || test_case_name == NULL
- || peer_process_name == NULL || cookie == NULL) {
- fprintf(stderr, "Error: missing option\n");
- usage();
- done(1);
- }
-
- test_case = test_cases;
- while (test_case->func) {
- if (cmp_str(test_case->name, test_case_name)) {
- test_func = test_case->func;
- break;
- }
- test_case++;
- }
- if (test_func == NULL) {
- fprintf(stderr, "Error: illegal test case: \"%s\"\n", test_case_name);
- done(1);
- }
-
- /* Behead hostname at first dot */
- for (i=0; host[i] != '\0'; i++) {
- if (host[i] == '.') { host[i] = '\0'; break; }
- }
- sprintf(this_node, "%s@%s", this_node_name, host);
- fprintf(stderr, "c_client: this node: \"%s\"\n", this_node);
- fprintf(stderr, "c_client: peer node: \"%s\"\n", peer_node);
- fprintf(stderr, "c_client: test case: \"%s\"\n", test_case_name);
-
- fprintf(stderr, "c_client: starting\n");
-
- /* initialize erl_interface */
- erl_init(NULL, 0);
-
- for (tries = 0; tries < MAXTRIES; tries++) {
-
- /* connect to erlang node */
-
- ires = erl_connect_xinit(host, this_node_name, this_node,
- (struct in_addr *)*hp->h_addr_list,
- cookie, 0);
-
- fprintf(stderr, "c_client: erl_connect_xinit(): %d\n", ires);
-
- fd = erl_connect(peer_node);
- fprintf(stderr, "c_client: erl_connect(): %d\n", fd);
-
- if (fd >= 0)
- break;
- fprintf(stderr, "c_client: cannot connect, retrying\n");
- }
- if (fd < 0) {
- fprintf(stderr, "c_client: cannot connect, exiting\n");
- done(1);
- }
- env = CORBA_Environment_alloc(INBUFSZ, OUTBUFSZ);
- env->_fd = fd;
- strcpy(env->_regname, peer_process_name);
- env->_to_pid = NULL;
- env->_from_pid = &pid;
-
- strcpy(pid.node, this_node);
- pid.num = fd;
- pid.serial = 0;
- pid.creation = 0;
-
- my_gettimeofday(&start);
- tres = test_func(env); /* Call test case */
- my_gettimeofday(&stop);
- showtime(&start, &stop);
- erl_close_connection(fd);
-
- printf("c_client: env->_inbuf before : %d\n", INBUFSZ);
- printf("c_client: env->_outbuf before : %d\n", OUTBUFSZ);
- printf("c_client: env->_inbuf after : %d\n", env->_inbufsz);
- printf("c_client: env->_outbuf after : %d\n", env->_outbufsz);
-
- CORBA_free(env->_inbuf);
- CORBA_free(env->_outbuf);
- CORBA_free(env);
- done(tres);
-}
-
-static void usage()
-{
- fprintf(stderr, "Usage: %s [-help] -this-node-name <name> "
- "-peer-node <nodename> -peer-process-name <name> "
- "-cookie <cookie> -test-case <test case name>\n", progname);
- fprintf(stderr, "Example:\n %s -this-node-name kalle "
- "-peer-node olle@home -peer-process-name idltest "
- "-cookie oa678er -test-case octet_test\n", progname);
-}
-
-static void done(int r)
-{
-#ifdef __WIN32__
- WSACleanup();
-#endif
- exit(r);
-}
-
-
-/* TESTS */
-
-static int void_test(IC_Env *env)
-{
- fprintf(stdout, "\n======== m_i_void test ======\n\n");
- m_i_void_test(NULL,env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(1);
-}
-
-static int long_test(IC_Env *env)
-{
- long l = 4711, lo, lr;
-
- fprintf(stdout, "\n======== m_i_long test ======\n\n");
- lr = m_i_long_test(NULL, l, &lo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(l == lo && l == lr);
- if (l != lo)
- fprintf(stdout, " out parameter error, sent: %ld, got: %ld\n", l, lo);
- if (l != lr)
- fprintf(stdout, " result error, sent: %ld, got: %ld\n", l, lr);
- return -1;
-}
-
-static int long_long_test(IC_Env *env)
-{
- CORBA_long_long ll = 4711, llo, llr;
-
- fprintf(stdout, "\n======== m_i_longlong test ======\n\n");
- llr = m_i_longlong_test(NULL, ll, &llo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(ll == llo && ll == llr);
- if (ll != llo)
- fprintf(stdout, " out parameter error, sent: %ld, got: %ld\n",
- ll, llo);
- if (ll != llr)
- fprintf(stdout, " result error, sent: %ld, got: %ld\n", ll, llr);
- return -1;
-}
-
-static int unsigned_short_test(IC_Env *env)
-{
- unsigned short x, y = 2, z;
-
- fprintf(stdout, "\n======== m_i_ushort test ======\n\n");
- x = m_i_ushort_test(NULL, y, &z, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(y == z && y == x);
- if (y != z)
- fprintf(stdout, " out parameter error, sent: %d, got: %d\n", y, z);
- if (y != x)
- fprintf(stdout, " result error, sent: %d, got: %d\n", y, x);
- return -1;
-}
-
-
-static int unsigned_long_test(IC_Env *env)
-{
- unsigned long ul = 5050, ulo, ulr;
-
- fprintf(stdout, "\n======== m_i_ulong test ======\n\n");
- ulr = m_i_ulong_test(NULL, ul, &ulo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(ul == ulo && ul == ulr);
- if (ul != ulo)
- fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n",
- ul, ulo);
- if (ul != ulr)
- fprintf(stdout, " result error, sent: %lu, got: %lu\n", ul, ulr);
- return -1;
-}
-
-/*
- * Note: CORBA_unsigned_long_long is in fact a plain long.
- */
-static int unsigned_long_long_test(IC_Env *env)
-{
- CORBA_unsigned_long_long ull = 5050, ullo, ullr;
-
- fprintf(stdout, "\n======== m_i_ulonglong test ======\n\n");
- ullr = m_i_ulonglong_test(NULL, ull, &ullo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(ull == ullo && ull == ullr);
- if (ull != ullo)
- fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n",
- ull, ullo);
- if (ull != ullr)
- fprintf(stdout, " result error, sent: %lu, got: %lu\n",
- ull, ullr);
- return -1;
-}
-
-static int double_test(IC_Env *env)
-{
- double d = 12.1212, db, dr;
-
- fprintf(stdout, "\n======== m_i_double test ======\n\n");
- dr = m_i_double_test(NULL, d, &db, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(d == db && d == dr);
- if (d != db)
- fprintf(stdout, " out parameter error, sent: %f, got: %f\n", d, db);
- if (d != dr)
- fprintf(stdout, " result error, sent: %f, got: %f\n", d, dr);
- return -1;
-}
-
-static int char_test(IC_Env *env)
-{
- char c = 'g', co, cr;
-
- /* char test */
- fprintf(stdout, "\n======== m_i_char test ======\n\n");
- cr = m_i_char_test(NULL, c, &co, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(c == co && c == cr);
- if (c !=co)
- fprintf(stdout, " out parameter error, sent: %c, got: %c\n", c, co);
- if (c != cr)
- fprintf(stdout, " result error, sent: %c, got: %c\n", c, cr);
- return -1;
-}
-
-static int wchar_test(IC_Env *env)
-{
- CORBA_wchar wc = 103, wco, wcr;
-
- fprintf(stdout, "\n======== m_i_wchar test ======\n\n");
- wcr = m_i_wchar_test(NULL, wc, &wco, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(wc == wco && wc == wcr);
- if (wc != wco)
- fprintf(stdout, " out parameter error, sent: %lu, got: %lu\n",
- wc, wco);
- if (wc != wcr)
- fprintf(stdout, " result error, sent: %lu, got: %lu\n",
- wc, wcr);
- return -1;
-}
-
-static int octet_test(IC_Env *env)
-{
- char o ='r', oo, or;
-
- fprintf(stdout, "\n======== m_i_octet test ======\n\n");
- or = m_i_octet_test(NULL, o, &oo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(o == oo && o == or);
- if (o != oo)
- fprintf(stdout, " out parameter error, sent: %c, got: %c\n", o, oo);
- if (o != or)
- fprintf(stdout, " result error, sent: %c, got: %c\n", o, or);
- return -1;
-}
-
-static int bool_test(IC_Env *env)
-{
- unsigned char i = 0, io, ir;
-
- fprintf(stdout, "\n======== m_i_bool test ======\n\n");
- ir = m_i_bool_test(NULL, i, &io, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(i == io && i == ir);
- if (i != io)
- fprintf(stdout, " out parameter error, sent: %d, got: %d\n", i, io);
- if (i != ir)
- fprintf(stdout, " result error, sent: %d, got: %d\n", i, ir);
- return -1;
-}
-
-static int struct_test(IC_Env *env)
-{
- m_b b = {4711, 'a'}, bo, br;
-
- fprintf(stdout, "\n======== m_i_struct test ======\n\n");
- br = m_i_struct_test(NULL, &b, &bo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_b(&b, &bo) && cmp_b(&b, &br));
- if (!cmp_b(&b, &bo)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_b(&b);
- fprintf(stdout, " got:\n");
- print_b(&bo);
- fprintf(stdout, "\n");
- }
- if (!cmp_b(&b, &br)) {
- fprintf(stdout, " result error, sent:\n");
- print_b(&b);
- fprintf(stdout, " got:\n");
- print_b(&br);
- fprintf(stdout, "\n");
- }
- return -1;
-}
-
-static int struct2_test(IC_Env *env)
-{
- m_es esi = {m_peach, 5050}, eso, esr;
-
- fprintf(stdout, "\n======== m_i_struct2 test ======\n\n");
- esr = m_i_struct2_test(NULL, &esi, &eso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_es(&esi, &eso) && cmp_es(&esi, &esr));
- if (!cmp_es(&esi, &eso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_es(&esi);
- fprintf(stdout, " got:\n");
- print_es(&eso);
- fprintf(stdout, "\n");
- }
- if (!cmp_es(&esi, &esr)) {
- fprintf(stdout, " result error, sent:\n");
- print_es(&esi);
- fprintf(stdout, " got:\n");
- print_es(&esr);
- fprintf(stdout, "\n");
- }
- return -1;
-}
-
-
-static int seq1_test(IC_Env *env)
-{
- m_bseq bs, *bso, *bsr;
-
- m_b ba[3] = {{4711, 'a'}, {4712, 'b'}, {4713, 'c'}};
- bs._length = 3;
- bs._buffer = ba;
-
- fprintf(stdout, "\n======== m_i_seq1 test ======\n\n");
- bsr = m_i_seq1_test(NULL, &bs, &bso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_bseq(&bs, bso) && cmp_bseq(&bs, bsr));
- if (!cmp_bseq(&bs, bso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_bseq(&bs);
- fprintf(stdout, " got:\n");
- print_bseq(bso);
- fprintf(stdout, "\n");
- }
- if (!cmp_bseq(&bs, bsr)) {
- fprintf(stdout, " result error, sent:\n");
- print_bseq(&bs);
- fprintf(stdout, " got:\n");
- print_bseq(bsr);
- fprintf(stdout, "\n");
- }
- CORBA_free(bso);
- CORBA_free(bsr);
- return -1;
-}
-
-static int seq2_test(IC_Env *env)
-{
- m_b ba[3] = {{4711, 'a'}, {4712, 'b'}, {4713, 'c'}};
- m_a a;
- m_a aa[2];
- m_aseq as, *aso, *asr;
-
- a.l = 9999;
- a.y._length = 3;
- a.y._buffer = ba;
- a.d = 66.89898989;
-
- aa[0] = a;
- aa[1] = a;
- as._length = 2;
- as._buffer = aa;
-
- fprintf(stdout, "\n======== m_i_seq2 test ======\n\n");
- asr = m_i_seq2_test(NULL, &as, &aso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_aseq(&as, aso) && cmp_aseq(&as, asr));
- if (!cmp_aseq(&as, aso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_aseq(&as);
- fprintf(stdout, " got:\n");
- print_aseq(aso);
- fprintf(stdout, "\n");
- }
- if (!cmp_aseq(&as, asr)) {
- fprintf(stdout, " result error, sent:\n");
- print_aseq(&as);
- fprintf(stdout, " got:\n");
- print_aseq(asr);
- fprintf(stdout, "\n");
- }
- CORBA_free(aso);
- CORBA_free(asr);
- return -1;
-}
-
-static int seq3_test(IC_Env *env)
-{
- m_lseq lsi, *lso, *lsr;
- long al[500];
- int i=0;
-
- for (i = 0; i < 500; i++)
- al[i]=i;
- lsi._length = 500;
- lsi._buffer = al;
-
- fprintf(stdout, "\n======== m_i_seq3 test ======\n\n");
- lsr = m_i_seq3_test(NULL, &lsi, &lso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_lseq(&lsi, lso) && cmp_lseq(&lsi, lsr));
- if (!cmp_lseq(&lsi, lso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_lseq(&lsi);
- fprintf(stdout, " got:\n");
- print_lseq(lso);
- fprintf(stdout, "\n");
- }
- if (!cmp_lseq(&lsi, lsr)) {
- fprintf(stdout, " result error, sent:\n");
- print_lseq(&lsi);
- fprintf(stdout, " got:\n");
- print_lseq(lsr);
- fprintf(stdout, "\n");
- }
- CORBA_free(lso);
- CORBA_free(lsr);
- return -1;
-}
-
-static int seq4_test(IC_Env *env)
-{
- char *stra0[3] = {"a", "long", "time"};
- char *stra1[3] = {"ago", "there", "was"};
- char *stra2[3] = {"a", "buggy", "compiler"};
- m_sstr3 str3s[3] = {{3, 3, stra0}, {3, 3, stra1}, {3, 3, stra2}};
- m_ssstr3 str3ssi = {3, 3, str3s};
- m_ssstr3 *str3sso, *str3ssr;
-
- fprintf(stdout, "\n======== m_i_seq4 test ======\n\n");
- str3ssr = m_i_seq4_test(NULL, &str3ssi, &str3sso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_ssstr3(&str3ssi, str3sso) &&
- cmp_ssstr3(&str3ssi, str3ssr));
- if (!cmp_ssstr3(&str3ssi, str3sso)){
- fprintf(stdout, " out parameter error, sent:\n");
- print_ssstr3(&str3ssi);
- fprintf(stdout, " got:\n");
- print_ssstr3(str3sso);
- fprintf(stdout, "\n");
- }
- if (!cmp_ssstr3(&str3ssi, str3ssr)) {
- fprintf(stdout, " result error, sent:\n");
- print_ssstr3(&str3ssi);
- fprintf(stdout, " got:\n");
- print_ssstr3(str3ssr);
- fprintf(stdout, "\n");
- }
- CORBA_free(str3sso);
- CORBA_free(str3ssr);
- return -1;
-}
-
-static int seq5_test(IC_Env *env)
-{
- m_arr3 arr3a[3] = {
- {4711, 18931947, 3},
- {4711, 18931947, 3},
- {4711, 18931947, 3}};
- m_sarr3 arr3sa[3] = {{3, 3, arr3a}, {3, 3, arr3a}, {3, 3, arr3a}};
- m_ssarr3 arr3ssi = {3, 3, arr3sa};
- m_ssarr3 *arr3sso;
- m_ssarr3 *arr3ssr;
-
- fprintf(stdout, "\n======== m_i_seq5 test ======\n\n");
- arr3ssr = m_i_seq5_test(NULL, &arr3ssi, &arr3sso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_ssarr3(&arr3ssi, arr3sso) &&
- cmp_ssarr3(&arr3ssi, arr3ssr));
- if (!cmp_ssarr3(&arr3ssi, arr3sso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_ssarr3(&arr3ssi);
- fprintf(stdout, " got:\n");
- print_ssarr3(arr3sso);
- fprintf(stdout, "\n");
- }
- if (!cmp_ssarr3(&arr3ssi, arr3ssr)) {
- fprintf(stdout, " result error, sent:\n");
- print_ssarr3(&arr3ssi);
- fprintf(stdout, " got:\n");
- print_ssarr3(arr3ssr);
- fprintf(stdout, "\n");
- }
- CORBA_free(arr3sso);
- CORBA_free(arr3ssr);
- return -1;
-}
-
-static int array1_test(IC_Env *env)
-{
- int i;
- long al[500];
- m_arr1 alo;
- m_arr1_slice* alr;
-
- for (i = 0; i < 500; i++)
- al[i]=i;
-
- fprintf(stdout, "\n======== m_i_array1 test ======\n\n");
- alr = m_i_array1_test(NULL, al, alo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_arr1(al, alo) && cmp_arr1(al, alr));
- if (!cmp_arr1(al, alo)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_arr1(al);
- fprintf(stdout, " got:\n");
- print_arr1(alo);
- fprintf(stdout, "\n");
- }
- if (!cmp_arr1(al,alr)) {
- fprintf(stdout, " result error, sent:\n");
- print_arr1(al);
- fprintf(stdout, " got:\n");
- print_arr1(alr);
- fprintf(stdout, "\n");
- }
- free(alo);
- free(alr);
- return -1;
-}
-
-static int array2_test(IC_Env *env)
-{
- long dl[2][3] = {{11, 2, 7}, {22, 8 ,13}};
- m_dd dlo;
- m_dd_slice* dlr;
-
- fprintf(stdout, "\n======== m_i_array2 test ======\n\n");
- dlr = m_i_array2_test(NULL, dl, dlo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_dd(dl,dlo) && cmp_dd(dl,dlr));
- if (!cmp_dd(dl,dlo)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_dd(dl);
- fprintf(stdout, " got:\n");
- print_dd(dlo);
- fprintf(stdout, "\n");
- }
- if (!cmp_dd(dl,dlr)) {
- fprintf(stdout, " result error, sent:\n");
- print_dd(dl);
- fprintf(stdout, " got:\n");
- print_dd(dlr);
- fprintf(stdout, "\n");
- }
- free(*dlr);
- return -1;
-}
-
-static int enum_test(IC_Env *env)
-{
- m_fruit ei = m_banana, eo, er;
-
- fprintf(stdout, "\n======== m_i_enum test ======\n\n");
- er = m_i_enum_test(NULL, ei, &eo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(ei == eo && ei == er);
- if (ei != eo)
- fprintf(stdout, " out parameter error, sent: %d, got: %d\n", ei, eo);
- if (ei != er)
- fprintf(stdout, " result error, sent: %d, got: %d\n", ei, er);
- return -1;
-}
-
-static int string1_test(IC_Env *env)
-{
- char* si = longtext;
- char* so;
- char* sr;
-
- fprintf(stdout, "\n======== m_i_string1 test ======\n\n");
- sr = m_i_string1_test(NULL, si, &so, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_str(si, so) && cmp_str(si, sr));
- if (!cmp_str(si, so))
- fprintf(stdout, " out parameter error, sent: %s, got: %s\n", si, so);
- if (!cmp_str(si, sr))
- fprintf(stdout, " result error, sent: %s, got: %s\n", si, sr);
- CORBA_free(so);
- CORBA_free(sr);
- return -1;
-}
-
-static int string2_test(IC_Env *env)
-{
- char* sa[3] = {"hello", "foo", "bar"};
- m_sseq ssi = {3, 3, sa};
- m_sseq *sso, *ssr;
-
- fprintf(stdout, "\n======== m_i_string2 test ======\n\n");
- ssr = m_i_string2_test(NULL, &ssi, &sso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_sseq(&ssi, sso) && cmp_sseq(&ssi, sso));
- if (!cmp_sseq(&ssi, sso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_sseq(&ssi);
- fprintf(stdout, "got:\n");
- print_sseq(sso);
- }
- if (!cmp_sseq(&ssi, ssr)) {
- fprintf(stdout, " result error, sent:\n");
- print_sseq(&ssi);
- fprintf(stdout, "got:\n");
- print_sseq(ssr);
- }
- CORBA_free(sso);
- CORBA_free(ssr);
- return -1;
-}
-
-static int string3_test(IC_Env *env)
-{
- char* si = longtext;
- char* so;
- char* sr;
-
- fprintf(stdout, "\n======== m_i_string3 test ======\n\n");
- sr = m_i_string3_test(NULL, si, &so, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_str(si, so) && cmp_str(si, so));
- if (!cmp_str(si, so))
- fprintf(stdout, " out parameter error, sent: %s, got: %s\n", si, so);
- if (!cmp_str(si, sr))
- fprintf(stdout, " result error, sent: %s, got: %s\n", si, sr);
- CORBA_free(so);
- CORBA_free(sr);
- return -1;
-}
-
-static int string4_test(IC_Env *env)
-{
- char as1[100] = "a string", as2[200] = "help", as3[200] = "hello there";
- m_strRec stri = { 1, /* dd */
- as1, /* str4 */
- {{'a', 'k'}, {'z', 'g'}, {'n', 'q'}}, /* str7 */
- {3, 3, "buf"}, /* str5 */
- as2, /* str6 */
- {'m', 'f', 'o'}, /* str8 */
- as3, /* str9 */
- {3, 3, "stu"} /* str10 */
- };
- m_strRec *stro, *strr;
-
- fprintf(stdout, "\n======== m_i_string4 test ======\n\n");
- strr = m_i_string4_test(NULL, &stri, &stro, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_strRec(&stri,stro) && cmp_strRec(&stri,strr));
- if (!cmp_strRec(&stri,stro)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_strRec(&stri);
- fprintf(stdout, " got:\n");
- print_strRec(stro);
- fprintf(stdout, "\n");
- }
- if (!cmp_strRec(&stri,strr)) {
- fprintf(stdout, " result error, sent:\n");
- print_strRec(&stri);
- fprintf(stdout, " got:\n");
- print_strRec(strr);
- fprintf(stdout, "\n");
- }
- CORBA_free(stro);
- CORBA_free(strr);
- return -1;
-}
-
-
-static int pid_test(IC_Env *env)
-{
- erlang_pid pid = {"", 7, 0, 0}, pido, pidr;
-
- strcpy(pid.node, this_node), /* this currently running node */
- fprintf(stdout, "\n======== m_i_pid test ======\n\n");
- pidr = m_i_pid_test(NULL, &pid, &pido, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_pid(&pid, &pido) && cmp_pid(&pid, &pidr));
- if (!cmp_pid(&pid, &pido)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_pid(&pid);
- fprintf(stdout, "got:\n");
- print_pid(&pido);
- }
- if (!cmp_pid(&pid, &pidr)) {
- fprintf(stdout, " result error, sent:\n");
- print_pid(&pid);
- fprintf(stdout, "got:\n");
- print_pid(&pidr);
- }
- return -1;
-}
-
-static int port_test(IC_Env *env)
-{
- erlang_port porti = {"node", 5, 1}, porto, portr;
-
- fprintf(stdout, "\n======== m_i_port test ======\n\n");
- portr = m_i_port_test(NULL, &porti, &porto, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_port(&porti, &porto) && cmp_port(&porti, &portr));
- if (!cmp_port(&porti, &porto)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_port(&porti);
- fprintf(stdout, "got:\n");
- print_port(&porto);
- }
- if (!cmp_port(&porti, &portr)) {
- fprintf(stdout, " result error, sent:\n");
- print_port(&porti);
- fprintf(stdout, "got:\n");
- print_port(&portr);
- }
- return -1;
-}
-
-static int ref_test(IC_Env *env)
-{
- erlang_ref refi = { "node1", 3, {1, 2, 3}, 1},
- refo, refr;
-
- fprintf(stdout, "\n======== m_i_ref test ======\n\n");
- refr = m_i_ref_test(NULL, &refi, &refo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_ref(&refi, &refo) && cmp_ref(&refi, &refr));
- if (!cmp_ref(&refi, &refo)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_ref(&refi);
- fprintf(stdout, "got:\n");
- print_ref(&refo);
- }
- if (!cmp_ref(&refi, &refr)) {
- fprintf(stdout, " result error, sent:\n");
- print_ref(&refi);
- fprintf(stdout, "got:\n");
- print_ref(&refr);
- }
- return -1;
-}
-
-static int term_test(IC_Env *env)
-{
- ETERM *ti, *to, *tr;
-
- ti = erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]");
-
- fprintf(stdout, "\n======== m_i_term test ======\n\n");
- tr = m_i_term_test(NULL, ti, &to, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(erl_match(ti, to) && erl_match(ti, tr));
- if (!erl_match(ti, to)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_term(ti);
- fprintf(stdout, "got:\n");
- print_term(to);
- }
- if (!erl_match(ti, tr)) {
- fprintf(stdout, " result error, sent:\n");
- print_term(ti);
- fprintf(stdout, "got:\n");
- print_term(tr);
- }
- erl_free_term(ti);
- erl_free_term(to);
- erl_free_term(tr);
- return -1;
-}
-
-static int typedef_test(IC_Env *env)
-{
- m_banan mbi, mbo; /* erlang_port */
- m_apa mai; /* ETERM* */
- m_apa mao = NULL;
- long tl;
-
- strcpy(mbi.node,"node");
- mbi.id = 15;
- mbi.creation = 1;
-
- fprintf(stdout, "\n======== m_i_typedef test ======\n\n");
- mai = erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]");
- tl = m_i_typedef_test(NULL, mai, &mbi, &mao, &mbo, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(erl_match(mai, mao) && cmp_port(&mbi, &mbo) && tl == 4711);
- if (!erl_match(mai, mao)) {
- fprintf(stdout, " out parameter error (term), sent:\n");
- print_term(mai);
- fprintf(stdout, "got:\n");
- print_term(mao);
- }
- if (!cmp_port(&mbi, &mbo)) {
- fprintf(stdout, " out parameter error (port), sent:\n");
- print_port(&mbi);
- fprintf(stdout, "got:\n");
- print_port(&mbo);
- }
- if (tl != 4711) {
- fprintf(stdout, " result error, sent: 4711, got %ld\n", tl);
- }
- erl_free_term(mai);
- erl_free_term(mao);
- return -1;
-}
-
-static int inline_sequence_test(IC_Env *env)
-{
- int i;
- long al[500];
- m_s isi = {4711, {500, 10, al}},
- *iso, *isr;
-
- for (i = 0; i < 500; i++)
- al[i]=i;
- fprintf(stdout, "\n======== m_i_inline_sequence test ======\n\n");
- isr = m_i_inline_sequence_test(NULL, &isi, &iso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_s(&isi, iso) && cmp_s(&isi, isr));
- if (!cmp_s(&isi, iso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_s(&isi);
- fprintf(stdout, "got:\n");
- print_s(iso);
- }
- if (!cmp_s(&isi, isr)) {
- fprintf(stdout, " result error, sent:\n");
- print_s(&isi);
- fprintf(stdout, "got:\n");
- print_s(isr);
- }
- CORBA_free(iso);
- CORBA_free(isr);
- return -1;
-}
-
-static int term_sequence_test(IC_Env *env)
-{
- ETERM* et_array[4] = {
- erl_format("[{apa, 1, 23}, \"string\", {1.23, 45}]"),
- erl_format("[{banan, 1, 23}, \"string\", {1.23, 45}]"),
- erl_format("[{apelsin, 1, 23}, \"string\", {1.23, 45}]"),
- erl_format("[{mango, 1, 23}, \"string\", {1.23, 45}]")};
- m_etseq etsi = {4, 4, et_array}, *etso, *etsr;
-
- fprintf(stdout, "\n======== m_i_term_sequence test ======\n\n");
- etsr = m_i_term_sequence_test(NULL, &etsi, &etso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_etseq(&etsi, etso) && cmp_etseq(&etsi, etsr));
- if (!cmp_etseq(&etsi, etso)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_etseq(&etsi);
- fprintf(stdout, "got:\n");
- print_etseq(etso);
- }
- if (!cmp_etseq(&etsi, etsr)) {
- fprintf(stdout, " result error, sent:\n");
- print_etseq(&etsi);
- fprintf(stdout, "got:\n");
- print_etseq(etsr);
- }
- free_etseq_buf(&etsi);
- free_etseq_buf(etso);
- free_etseq_buf(etsr);
- CORBA_free(etso);
- CORBA_free(etsr);
- return -1;
-}
-
-static int term_struct_test(IC_Env *env)
-{
- m_et eti = { erl_format("[{hej, 1, 23}, \"string\", {1.23, 45}]"),
- 121212 };
- m_et eto, etr;
-
- fprintf(stdout, "\n======== m_i_term_struct test ======\n\n");
- etr = m_i_term_struct_test(NULL, &eti, &eto, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_et(&eti, &eto) && cmp_et(&eti, &etr));
- if (!cmp_et(&eti, &eto)) {
- fprintf(stdout, " out parameter error, sent:\n");
- print_et(&eti);
- fprintf(stdout, "got:\n");
- print_et(&eto);
- }
- if (!cmp_et(&eti, &etr)) {
- fprintf(stdout, " result error, sent:\n");
- print_et(&eti);
- fprintf(stdout, "got:\n");
- print_et(&etr);
- }
- free_et(&eti);
- free_et(&eto);
- free_et(&etr);
- return -1;
-}
-
-static int wstring1_test(IC_Env *env)
-{
- CORBA_wchar wsi[] = {100, 101, 102, 103, 104, 0}, *wso, *wsr;
-
- fprintf(stdout, "\n======== m_i_wstring1 test ======\n\n");
- wsr = m_i_wstring1_test(NULL, wsi, &wso, env);
- CHECK_EXCEPTION(env);
- RETURN_IF_OK(cmp_wstr(wsi, wso) && cmp_wstr(wsi, wsr));
- if (!cmp_wstr(wsi, wso)) {
- fprintf(stdout, " out parameter error, sent: \n");
- print_wstr(wsi);
- fprintf(stdout, "got:\n");
- print_wstr(wso);
- }
- if (!cmp_wstr(wsi, wsr)) {
- fprintf(stdout, " result error, sent: \n");
- print_wstr(wsi);
- fprintf(stdout, "got:\n");
- print_wstr(wsr);
- }
- CORBA_free(wso);
- CORBA_free(wsr);
- return -1;
-}
-
-/* Compare functions */
-static int cmp_aseq(m_aseq *a1, m_aseq *a2)
-{
- int i;
-
- if (a1->_length != a2->_length)
- return 0;
- for (i = 0; i < a1->_length; i++)
- if (cmp_a(&(a1->_buffer[i]), &(a2->_buffer[i])) == 0)
- return 0;
- return 1;
-}
-
-static int cmp_a(m_a *a1, m_a *a2)
-{
- return a1->l == a2->l &&
- a1->d == a2->d &&
- cmp_bseq(&a1->y, &a2->y);
-}
-
-static int cmp_bseq(m_bseq *b1, m_bseq *b2)
-{
- int i;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++)
- if (cmp_b(&(b1->_buffer[i]), &(b2->_buffer[i])) == 0)
- return 0;
- return 1;
-}
-
-static int cmp_b(m_b *b1, m_b *b2)
-{
- return b1->l == b2->l && b1->c == b2->c;
-}
-
-static int cmp_lseq(m_lseq *b1, m_lseq *b2)
-{
- int i;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++)
- if (b1->_buffer[i] != b2->_buffer[i])
- return 0;
- return 1;
-}
-
-static int cmp_etseq(m_etseq *b1, m_etseq *b2)
-{
- int i;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++)
- if (!erl_match(b1->_buffer[i], b2->_buffer[i]))
- return 0;
- return 1;
-}
-
-static int cmp_et(m_et* b1, m_et *b2)
-{
- return erl_match(b1->e, b2->e) && b1->l == b2->l;
-}
-
-static int cmp_es(m_es *b1, m_es *b2)
-{
- return b1->f == b2->f && b1->l == b2->l;
-}
-
-static int cmp_arr1(m_arr1 b1, m_arr1 b2)
-{
- int i;
-
- for (i = 0; i < 500; i++)
- if (b1[i] != b2[i])
- return 0;
- return 1;
-}
-
-static int cmp_dd(m_dd b1, m_dd b2)
-{
-
- int i, j;
-
- for (i = 0; i < 2; i++)
- for (j = 0; j < 3; j++)
- if (b1[i][j] != b2[i][j])
- return 0;
- return 1;
-}
-
-
-
-static int cmp_strRec(m_strRec *b1, m_strRec *b2)
-{
- int i, j;
-
- if (b1->bb != b2->bb)
- return 0;
- if (!cmp_str(b1->str4,b2->str4))
- return 0;
- if (b1->str5._length != b2->str5._length)
- return 0;
- for (j = 0; j < b1->str5._length; j++)
- if (b1->str5._buffer[j] != b2->str5._buffer[j])
- return 0;
- if (!cmp_str(b1->str6,b2->str6))
- return 0;
- for (i = 0; i < 2; i++)
- for (j = 0; j < 3; j++)
- if (b1->str7[i][j] != b2->str7[i][j])
- return 0;
- for (j = 0; j < 3; j++)
- if (b1->str8[j] != b2->str8[j])
- return 0;
- if (!cmp_str(b1->str9,b2->str9))
- return 0;
- if (b1->str10._length != b2->str10._length)
- return 0;
- for (j = 0; j < b1->str10._length; j++)
- if (b1->str10._buffer[j] != b2->str10._buffer[j])
- return 0;
- return 1;
-}
-
-
-static int cmp_sseq(m_sseq *b1, m_sseq *b2)
-{
- int i;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++)
- if (!cmp_str(b1->_buffer[i], b2->_buffer[i]))
- return 0;
- return 1;
-}
-
-
-static int cmp_pid(erlang_pid *p1, erlang_pid *p2)
-{
- return cmp_str(p1->node,p2-> node) &&
- p1->num == p2->num &&
- p1->serial == p2->serial &&
- p1->creation == p2->creation;
-}
-
-static int cmp_port(erlang_port *p1, erlang_port *p2)
-{
- return cmp_str(p1->node,p2-> node) && p1->id == p2->id;
-}
-
-static int cmp_ref(erlang_ref *p1, erlang_ref *p2)
-{
- return cmp_str(p1->node, p2->node) &&
- p1->len == p2->len &&
- (p1->len < 1 || p1->n[0] == p2->n[0]) &&
- (p1->len < 2 || p1->n[1] == p2->n[1]) &&
- (p1->len < 3 || p1->n[2] == p2->n[2]);
-}
-
-static int cmp_s(m_s *b1, m_s *b2)
-{
- int i;
-
- if (b1->l != b2->l)
- return 0;
- if (b1->sl._length != b2->sl._length)
- return 0;
- for (i = 0; i < b1->sl._length; i++)
- if (b1->sl._buffer[i] != b2->sl._buffer[i])
- return 0;
- return 1;
-}
-
-
-static int cmp_ssstr3(m_ssstr3 *b1, m_ssstr3 *b2)
-{
- int i,j;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++) {
- if (b1->_buffer[i]._length != b2->_buffer[i]._length)
- return 0;
- for (j = 0; j < b1->_buffer[i]._length; j++)
- if (!cmp_str(b1->_buffer[i]._buffer[j],
- b2->_buffer[i]._buffer[j]))
- return 0;
- }
- return 1;
-}
-
-
-
-static int cmp_ssarr3(m_ssarr3 *b1, m_ssarr3 *b2)
-{
- int i;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++) {
- if (!cmp_sarr3(&b1->_buffer[i], &b2->_buffer[i]))
- return 0;
- }
- return 1;
-}
-
-static int cmp_sarr3(m_sarr3 *b1, m_sarr3 *b2)
-{
- int i;
-
- if (b1->_length != b2->_length)
- return 0;
- for (i = 0; i < b1->_length; i++) {
- if (!cmp_arr3(b1->_buffer[i], b2->_buffer[i]))
- return 0;
- }
- return 1;
-}
-
-static int cmp_arr3(m_arr3 b1, m_arr3 b2)
-{
- int i;
-
- for (i = 0; i < sizeof(m_arr3)/sizeof(CORBA_long); i++) {
- if (b1[i] != b2[i])
- return 0;
- }
- return 1;
-}
-
-/* Print functions */
-static void print_aseq(m_aseq *a)
-{
- int i;
- fprintf(stdout, "\nm_aseq size: %ld --------\n", a->_length);
- for (i = 0; i < a->_length; i++)
- print_a(&(a->_buffer[i]));
-}
-
-static void print_a(m_a *a)
-{
- fprintf(stdout, "\nm_a --------\n l: %ld\n d:%f\n", a->l, a->d);
- print_bseq(&a->y);
-}
-
-static void print_bseq(m_bseq *b)
-{
- int i;
-
- fprintf(stdout, "\nm_bseq size: %ld --------\n",b->_length);
- for (i = 0; i < b->_length; i++)
- print_b(&(b->_buffer[i]));
-}
-
-static void print_lseq(m_lseq *b)
-{
- int i;
-
- fprintf(stdout, "\nm_lseq size: %ld --------\n",b->_length);
- for (i = 0; i < b->_length; i++)
- fprintf(stdout, "[%d]: %ld\n", i, b->_buffer[i]);
-}
-
-static void print_b(m_b *b)
-{
- fprintf(stdout, "\nm_b --------\n l: %ld\n c: %c\n", b->l, b->c);
-}
-
-
-static void print_etseq(m_etseq *b)
-{
- int i;
-
- for (i = 0; i < b->_length; i++) {
- fprintf(stdout, "[%d]:\n", i);
- erl_print_term(stdout, b->_buffer[i]);
- }
-}
-
-
-static void print_et(m_et* b)
-{
- fprintf(stdout, "\net struct --------\n");
- erl_print_term(stdout, b->e);
- fprintf(stdout, "long: %ld\n", b->l);
- fprintf(stdout, "\n--------\n");
-}
-
-static void print_es(m_es *b)
-{
- fprintf(stdout, "\nm_es --------\n f: %d\n l: %ld\n", b->f, b->l);
-}
-
-
-static void print_arr1(long a[10])
-{
- int i;
-
- for (i = 0; i < 10; i++)
- fprintf(stdout, "\n[%d]: %ld\n", i, a[i]);
-}
-
-static void print_dd(long a[2][3])
-{
- int i, j;
-
- fprintf(stdout, "\nlong dd[2][3] --------\n");
- for (i = 0; i < 2; i++)
- for (j = 0; j < 3; j++)
- fprintf(stdout, "\n[%d][%d]: %ld\n", i, j, a[i][j]);
-}
-
-
-static void print_strRec(m_strRec* sr)
-{
- int i, j;
-
- fprintf(stdout, "\nboolean bb : %d\n",sr->bb);
- fprintf(stdout, "string str4 : %s\n",sr->str4);
- fprintf(stdout, "str7[2][3] :\n");
- for (i = 0; i < 2; i++)
- for (j = 0; j < 3; j++)
- fprintf(stdout, "str7[%d][%d]: %ld\n", i, j, sr->str7[i][j]);
- fprintf(stdout, "str5._length : %ld\n",sr->str5._length);
- for (j = 0; j < sr->str5._length; j++)
- fprintf(stdout, "str5._buffer[%d]: %c\n", j, sr->str5._buffer[j]);
- fprintf(stdout, "string str6 : %s\n",sr->str6);
- fprintf(stdout, "str8 :\n");
- for (j = 0; j < 3; j++)
- fprintf(stdout, "str8[%d]: %c\n", j, sr->str8[j]);
- fprintf(stdout, "string str9 : %s\n",sr->str9);
- fprintf(stdout, "str10._length : %ld\n",sr->str10._length);
- for (j = 0; j < sr->str10._length; j++)
- fprintf(stdout, "str10._buffer[%d]: %c\n", j, sr->str10._buffer[j]);
-}
-
-static void print_sseq(m_sseq *b)
-{
- int i;
-
- fprintf(stdout, "\nm_sseq size: %ld --------\n",b->_length);
- for (i = 0; i < b->_length; i++)
- fprintf(stdout, "%s\n", b->_buffer[i]);
-
-}
-
-
-static void print_pid(erlang_pid *p)
-{
- fprintf(stdout, "\nerlang_pid --------\n node: %s\n num: %d\n "
- "serial: %d\n creation: %d\n",
- p->node, p->num, p->serial, p->creation);
-}
-
-static void print_port(erlang_port *p)
-{
- fprintf(stdout, "\nerlang_port --------\n node: %s\n id: %d\n "
- "creation: %d\n", p->node, p->id, p->creation);
-}
-
-static void print_ref(erlang_ref *p)
-{
- fprintf(stdout, "\nerlang_ref --------\n node: %s\n len: %d\n "
- "n[0]: %d\n n[1]: %d\n n[2]: %d\n creation: %d\n",
- p->node, p->len, p->n[0], p->n[1], p->n[2], p->creation);
-}
-
-static void print_term(ETERM *t)
-{
- fprintf(stdout, "\nETERM --------\n");
- erl_print_term(stdout, t);
- fprintf(stdout, "\n--------\n");
-}
-
-static void print_s(m_s *p)
-{
- int i;
-
- fprintf(stdout, "\n%ld\n", p->l);
- for (i = 0; i < p->sl._length; i++)
- fprintf(stdout, "\n[%d]: %ld\n", i, p->sl._buffer[i]);
-}
-
-
-static void print_ssstr3(m_ssstr3 *b1)
-{
- int i,j;
-
- fprintf(stdout, "\nSSSTR3 --------\n");
- fprintf(stdout,"b1->_length = %ld\n",b1->_length);
- for (i = 0; i < b1->_length; i++) {
- fprintf(stdout,"\nb1->_buffer[%d]._length %ld\n",
- i, b1->_buffer[i]._length);
- for (j = 0; j < b1->_buffer[i]._length; j++)
- fprintf(stdout,"b1->_buffer[%d]._buffer[%d] = %s\n",
- i, j, b1->_buffer[i]._buffer[j]);
- }
- fprintf(stdout, "\n--------\n");
-}
-
-static void print_wstr(CORBA_wchar *ws)
-{
- int i = 0;
-
- fprintf(stdout, "\nwstr --------\n");
- while (ws[i]) {
- fprintf(stdout, "[%d]: %ld\n", i, ws[i]);
- i++;
- }
- fprintf(stdout, "\n--------\n");
-}
-
-
-static void print_ssarr3(m_ssarr3 *b1)
-{
- int i;
-
- fprintf(stdout, "\nssarr3 --------\n");
- fprintf(stdout,"length: %ld\n",b1->_length);
- fprintf(stdout, "buffer:\n");
- for (i = 0; i < b1->_length; i++)
- print_sarr3(&b1->_buffer[i]);
- fprintf(stdout, "\n--------\n");
-}
-
-static void print_sarr3(m_sarr3 *b1)
-{
- int i;
-
- fprintf(stdout, "\nsarr3 --------\n");
- fprintf(stdout,"length: %ld\n",b1->_length);
- fprintf(stdout, "buffer:\n");
- for (i = 0; i < b1->_length; i++)
- print_arr3(b1->_buffer[i]);
- fprintf(stdout, "\n--------\n");
-}
-
-static void print_arr3(m_arr3 b1)
-{
- int i;
-
- fprintf(stdout, "\narr3 --------\n");
- for (i = 0; i < sizeof(m_arr3)/sizeof(CORBA_long); i++)
- fprintf(stdout, "%ld ", b1[i]);
- fprintf(stdout, "\n--------\n");
-}
-
-static void free_etseq_buf(m_etseq *b)
-{
- int i;
-
- for (i = 0; i < b->_length; i++)
- erl_free_term(b->_buffer[i]);
-}
-
-static void free_et(m_et* b)
-{
- erl_free_term(b->e);
-}
-
-static void showtime(MyTimeval *start, MyTimeval *stop)
-{
- MyTimeval elapsed;
-
- elapsed.tv_sec = stop->tv_sec - start->tv_sec;
- elapsed.tv_usec = stop->tv_usec - start->tv_usec;
- while (elapsed.tv_usec < 0) {
- elapsed.tv_sec -= 1;
- elapsed.tv_usec += 1000000;
- }
- fprintf(stderr,"%ld.%06ld seconds\n",elapsed.tv_sec, elapsed.tv_usec);
-}
-
-static void my_gettimeofday(MyTimeval *tv)
-#ifdef __WIN32__
-#define EPOCH_JULIAN_DIFF 11644473600i64
-{
- SYSTEMTIME t;
- FILETIME ft;
- LONGLONG lft;
-
- GetSystemTime(&t);
- SystemTimeToFileTime(&t, &ft);
- memcpy(&lft, &ft, sizeof(lft));
- tv->tv_usec = (long) ((lft / 10i64) % 1000000i64);
- tv->tv_sec = (long) ((lft / 10000000i64) - EPOCH_JULIAN_DIFF);
-}
-#elif defined VXWORKS
-{
- int rate = sysClkRateGet(); /* Ticks per second */
- unsigned long ctick = tickGet();
- tv->tv_sec = ctick / rate; /* secs since reboot */
- tv->tv_usec = ((ctick - (tv->tv_sec * rate))*1000000)/rate;
-}
-#else
-{
- gettimeofday(tv, NULL);
-}
-#endif
diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_erl_test.idl b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_erl_test.idl
deleted file mode 100644
index ec74d36cea..0000000000
--- a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/c_erl_test.idl
+++ /dev/null
@@ -1,174 +0,0 @@
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 2004-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-#include "erlang.idl"
-
-
-const short TestConst = 1;
-
-module m {
-
- const short TestConst = 2;
-
- struct b {
- long l;
- char c;
- };
-
- struct simple {
- long l;
- b b_t;
- };
-
- enum fruit {orange, banana, apple, peach, pear};
-
- typedef sequence<long> lseq;
-
- typedef sequence<b> bseq;
-
- struct a {
- long l;
- bseq y;
- double d;
- };
-
- typedef sequence<a> aseq;
-
- typedef sequence<string> sseq;
- typedef string str;
- typedef long myLong;
-
- typedef long arr1[500], dd[2][3];
-
- typedef erlang::term apa;
- typedef erlang::port banan;
-
- typedef sequence<erlang::term> etseq;
-
- struct s {
- long l;
- sequence<long> sl;
- };
-
- struct es {
- fruit f;
- myLong l;
- };
-
- struct et {
- erlang::term e;
- long l;
- };
-
-
- typedef sequence<char> str1;
- typedef string<12> str2;
- typedef char str3[3];
-
- typedef sequence<string> sstr3; // sequence of string
- typedef sequence<sstr3> ssstr3; // sequence of sequences of strings
-
- typedef long arr3[3]; // array of long
- typedef sequence<arr3> sarr3; // sequence of array
- typedef sequence<sarr3> ssarr3; // sequence of sequnces of arrays of strings
-
- struct strRec{
- boolean bb;
- string str4;
- long str7[3][2];
- sequence<char> str5;
- string<12> str6;
- str3 str8;
- str2 str9;
- str1 str10;
- };
-
-
- struct dyn {
- long l;
- sequence<long> sl;
- };
- typedef dyn arr2[1][2];
-
-
- interface i {
-
- const short TestConst = 3;
-
- //arr2 suck(in arr2 x, out arr2 y );
-
- ///////////////////////////////// attribute long l;
-
- // simple types
- void void_test();
- long long_test(in long a, out long a1);
- long long longlong_test(in long long a, out long long a1);
- unsigned short ushort_test(in unsigned short a, out unsigned short a1);
- unsigned long ulong_test(in unsigned long a, out unsigned long a1);
- unsigned long long ulonglong_test(in unsigned long long a, out unsigned long long a1);
- double double_test(in double a, out double a1);
- char char_test(in char a, out char a1);
- wchar wchar_test(in wchar a, out wchar a1);
- octet octet_test(in octet a, out octet a1);
- boolean bool_test(in boolean a, out boolean a1);
-
- // Seq. and struct tests
- b struct_test(in b a, out b a1);
- es struct2_test(in es a, out es a1);
- //simple struct3_test(in simple x, out simple y);
- bseq seq1_test(in bseq a, out bseq a1);
- aseq seq2_test(in aseq a, out aseq a1);
- lseq seq3_test(in lseq a, out lseq a1);
- ssstr3 seq4_test(in ssstr3 a, out ssstr3 a1);
- ssarr3 seq5_test(in ssarr3 a, out ssarr3 a1);
-
- // Array tests
- arr1 array1_test(in arr1 a, out arr1 a1);
- dd array2_test(in dd a, out dd a1);
-
- // enum test
- fruit enum_test(in fruit a, out fruit a1);
-
- // string tests
- string string1_test(in string a, out string a1);
- wstring wstring1_test(in wstring a, out wstring a1);
- sseq string2_test(in sseq a, out sseq a1);
- str string3_test(in str a, out str a1);
- strRec string4_test(in strRec a, out strRec a1);
-
- // Special erlang types
- erlang::pid pid_test(in erlang::pid a, out erlang::pid a1);
- erlang::port port_test(in erlang::port a, out erlang::port a1);
- erlang::ref ref_test(in erlang::ref a, out erlang::ref a1);
- erlang::term term_test(in erlang::term a, out erlang::term a1);
-
- // typedef test
- long typedef_test(in apa a, in banan b, out apa a1, out banan b1);
-
- // inlined seq. test
- s inline_sequence_test(in s a, out s a1);
-
- // term seq. test
- etseq term_sequence_test(in etseq a, out etseq a1);
- // term struct test
- et term_struct_test(in et a, out et a1);
-
- };
-
-};
diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/erl_server.erl b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/erl_server.erl
deleted file mode 100644
index f2a6ed83fa..0000000000
--- a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/erl_server.erl
+++ /dev/null
@@ -1,29 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(erl_server).
-
--export([run/0, stop/0]).
-
-run() ->
- m_i:oe_create().
-
-stop() ->
- gen_server:cast(cidl_test, stop).
diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/m_i_impl.erl b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/m_i_impl.erl
deleted file mode 100644
index ab62ee40c0..0000000000
--- a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/m_i_impl.erl
+++ /dev/null
@@ -1,162 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(m_i_impl).
--include("m.hrl").
-
--export([init/1, terminate/2, void_test/1, long_test/2, ushort_test/2,
- longlong_test/2, ulong_test/2, ulonglong_test/2,
- double_test/2, char_test/2, wchar_test/2, octet_test/2,
- bool_test/2, struct_test/2, struct2_test/2, seq1_test/2,
- seq2_test/2, seq3_test/2, seq4_test/2, seq5_test/2,
- array1_test/2, array2_test/2, enum_test/2, string1_test/2,
- string2_test/2, string3_test/2, string4_test/2, pid_test/2,
- port_test/2, ref_test/2, term_test/2, typedef_test/3,
- inline_sequence_test/2, '_set_l'/2, '_get_l'/1,
- term_struct_test/2, term_sequence_test/2, wstring1_test/2]).
-
--define(PRINTDEBUG(Case),
- io:format("erl_server: case: ~p~n"
- "erl_server: location: ~p~n", [Case, [?FILE, ?LINE]])).
--define(PRINTDEBUG2(Case, Msg),
- io:format("erl_server: case: ~p~n"
- "erl_server: Msg: ~p~n"
- "erl_server: location: ~p~n", [Case, Msg, [?FILE, ?LINE]])).
-
-init(Env) ->
- {ok, []}.
-
-terminate(F, R) ->
- ok.
-
-'_get_l'(State) ->
- ?PRINTDEBUG("_get_l"),
- {reply, State, State}.
-void_test(State) ->
- ?PRINTDEBUG("void_test"),
- {reply, ok, State}.
-
-'_set_l'(State, V) ->
- ?PRINTDEBUG2("_set_l", V),
- {reply, ok, V}.
-ushort_test(State, V) ->
- ?PRINTDEBUG2("ushort_test", V),
- {reply, {V, V}, State}.
-long_test(State, V) ->
- ?PRINTDEBUG2("long_test", V),
- {reply, {V, V}, State}.
-longlong_test(State, V) ->
- ?PRINTDEBUG2("longlong_test", V),
- {reply, {V, V}, State}.
-ulong_test(State, V) ->
- ?PRINTDEBUG2("ulong_test", V),
- {reply, {V, V}, State}.
-ulonglong_test(State, V) ->
- ?PRINTDEBUG2("ulonglong_test", V),
- {reply, {V, V}, State}.
-double_test(State, V) ->
- ?PRINTDEBUG2("double_test", V),
- {reply, {V, V}, State}.
-char_test(State, V) ->
- ?PRINTDEBUG2("char_test", V),
- {reply, {V, V}, State}.
-wchar_test(State, V) ->
- ?PRINTDEBUG2("wchar_test", V),
- {reply, {V, V}, State}.
-octet_test(State, V) ->
- ?PRINTDEBUG2("octet_test", V),
- {reply, {V, V}, State}.
-bool_test(State, V) ->
- ?PRINTDEBUG2("bool_test", V),
- {reply, {V, V}, State}.
-
-struct_test(State, V) ->
- ?PRINTDEBUG2("struct_test", V),
- {reply, {V, V}, State}.
-struct2_test(State, V) ->
- ?PRINTDEBUG2("struct2_test", V),
- {reply, {V, V}, State}.
-seq1_test(State, V) ->
- ?PRINTDEBUG2("seq1_test", V),
- {reply, {V, V}, State}.
-seq2_test(State, V) ->
- ?PRINTDEBUG2("seq2_test", V),
- {reply, {V, V}, State}.
-seq3_test(State, V) ->
- ?PRINTDEBUG2("seq3_test", V),
- {reply, {V, V}, State}.
-seq4_test(State, V) ->
- ?PRINTDEBUG2("seq4_test", V),
- {reply, {V, V}, State}.
-seq5_test(State, V) ->
- ?PRINTDEBUG2("seq5_test", V),
- {reply, {V, V}, State}.
-array1_test(State, V) ->
- ?PRINTDEBUG2("array1_test", V),
- {reply, {V, V}, State}.
-array2_test(State, V) ->
- ?PRINTDEBUG2("array2_test", V),
- {reply, {V, V}, State}.
-enum_test(State, V) ->
- ?PRINTDEBUG2("enum_test", V),
- {reply, {V, V}, State}.
-string1_test(State, V) ->
- ?PRINTDEBUG2("string1_test", V),
- {reply, {V, V}, State}.
-string2_test(State, V) ->
- ?PRINTDEBUG2("string2_test", V),
- {reply, {V, V}, State}.
-string3_test(State, V) ->
- ?PRINTDEBUG2("string3_test", V),
- {reply, {V, V}, State}.
-string4_test(State, V) ->
- ?PRINTDEBUG2("string4_test", V),
- {reply, {V, V}, State}.
-pid_test(State, V) ->
- ?PRINTDEBUG2("pid_test", V),
- {reply, {V, V}, State}.
-port_test(State, V) ->
- ?PRINTDEBUG2("port_test", binary_to_list(term_to_binary(V))),
- {reply, {V, V}, State}.
-ref_test(State, V) ->
- ?PRINTDEBUG2("ref_test", binary_to_list(term_to_binary(V))),
- {reply, {V, V}, State}.
-term_test(State, V) ->
- ?PRINTDEBUG2("term_test", V),
- {reply, {V, V}, State}.
-typedef_test(State, A, B) ->
- ?PRINTDEBUG2("typedef_test", [A,B]),
- {reply, {4711, A, B}, State}.
-inline_sequence_test(State, V) ->
- ?PRINTDEBUG2("inline_sequence_test", V),
- {reply, {V, V}, State}.
-term_sequence_test(State, V) ->
- ?PRINTDEBUG2("term_sequence_test", V),
- {reply, {V, V}, State}.
-term_struct_test(State, V) ->
- ?PRINTDEBUG2("term_struct_test", V),
- {reply, {V, V}, State}.
-wstring1_test(State, V) ->
- ?PRINTDEBUG2("wstring1_test", V),
- {reply, {V, V}, State}.
-
-
-
-
diff --git a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/my.c b/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/my.c
deleted file mode 100644
index 6045034052..0000000000
--- a/lib/ic/test/c_client_erl_server_proto_tmo_SUITE_data/my.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2004-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include "ic.h"
-#include "m_i.h"
-
-int my_prepare_notification_encoding(CORBA_Environment *env)
-{
- return oe_prepare_notification_encoding(env);
-}
-
-int my_send_notification_tmo(CORBA_Environment *env, unsigned int send_ms)
-{
- return oe_send_notification_tmo(env, send_ms);
-}
-
-int my_prepare_request_encoding(CORBA_Environment *env)
-{
- return oe_prepare_request_encoding(env);
-}
-
-int my_send_request_and_receive_reply_tmo(CORBA_Environment *env,
- unsigned int send_ms,
- unsigned int recv_ms)
-{
- return oe_send_request_and_receive_reply_tmo(env, send_ms, recv_ms);
-}
-
-int my_prepare_reply_decoding(CORBA_Environment *env)
-{
- return oe_prepare_reply_decoding(env);
-}
-
-
-
diff --git a/lib/ic/test/erl_client_c_server_SUITE.erl b/lib/ic/test/erl_client_c_server_SUITE.erl
deleted file mode 100644
index d592a611f7..0000000000
--- a/lib/ic/test/erl_client_c_server_SUITE.erl
+++ /dev/null
@@ -1,298 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-%%----------------------------------------------------------------------
-%% Purpose : Test suite for erl-client/c-server
-%%----------------------------------------------------------------------
-
-
--module(erl_client_c_server_SUITE).
--include_lib("common_test/include/ct.hrl").
-
--export([init_per_testcase/2, end_per_testcase/2,all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, void_test/1,
- long_test/1, longlong_test/1, ushort_test/1, ulong_test/1,
- ulonglong_test/1, double_test/1, char_test/1, wchar_test/1,
- octet_test/1, bool_test/1, struct_test/1, struct2_test/1,
- seq1_test/1, seq2_test/1, seq3_test/1, seq4_test/1,
- seq5_test/1, array1_test/1, array2_test/1, enum_test/1,
- string1_test/1, string2_test/1, string3_test/1,
- string4_test/1, pid_test/1, port_test/1, ref_test/1,
- term_test/1, typedef_test/1, inline_sequence_test/1,
- term_sequence_test/1, term_struct_test/1, wstring1_test/1]).
-
--define(DEFAULT_TIMEOUT, 20000).
--define(PORT_TIMEOUT, 15000).
--define(CALL_TIMEOUT, 5000).
-
--define(C_SERVER_NODE_NAME, idl_c_server_test).
-
-%% Add/remove code path and watchdog before/after each test case.
-%%
-init_per_testcase(_Case, Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- code:add_patha(DataDir),
-
- %% Since other test suites use the module m_i, we have
- %% to make sure we are using the right m_i module.
- code:purge(m_i),
- code:load_file(m_i),
-
- WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- code:del_path(DataDir),
- WatchDog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
-[void_test, long_test, longlong_test, ushort_test,
- ulong_test, ulonglong_test, double_test, char_test,
- wchar_test, octet_test, bool_test, struct_test,
- struct2_test, seq1_test, seq2_test, seq3_test,
- seq4_test, seq5_test, array1_test, array2_test,
- enum_test, string1_test, string2_test, string3_test,
- string4_test, pid_test, port_test, ref_test, term_test,
- typedef_test, inline_sequence_test, term_sequence_test,
- term_struct_test, wstring1_test].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-array1_test(Config) ->
- do_test(array1_test, Config).
-
-array2_test(Config) ->
- do_test(array2_test, Config).
-
-bool_test(Config) ->
- do_test(bool_test, Config).
-
-char_test(Config) ->
- do_test(char_test, Config).
-
-double_test(Config) ->
- do_test(double_test, Config).
-
-enum_test(Config) ->
- do_test(enum_test, Config).
-
-inline_sequence_test(Config) ->
- do_test(inline_sequence_test, Config).
-
-longlong_test(Config) ->
- do_test(longlong_test, Config).
-
-long_test(Config) ->
- do_test(long_test, Config).
-
-octet_test(Config) ->
- do_test(octet_test, Config).
-
-pid_test(Config) ->
- do_test(pid_test, Config).
-
-port_test(Config) ->
- do_test(port_test, Config).
-
-ref_test(Config) ->
- do_test(ref_test, Config).
-
-seq1_test(Config) ->
- do_test(seq1_test, Config).
-
-seq2_test(Config) ->
- do_test(seq2_test, Config).
-
-seq3_test(Config) ->
- do_test(seq3_test, Config).
-
-seq4_test(Config) ->
- do_test(seq4_test, Config).
-
-seq5_test(Config) ->
- do_test(seq5_test, Config).
-
-string1_test(Config) ->
- do_test(string1_test, Config).
-
-string2_test(Config) ->
- do_test(string2_test, Config).
-
-string3_test(Config) ->
- do_test(string3_test, Config).
-
-string4_test(Config) ->
- do_test(string4_test, Config).
-
-struct2_test(Config) ->
- do_test(struct2_test, Config).
-
-struct_test(Config) ->
- do_test(struct_test, Config).
-
-term_sequence_test(Config) ->
- do_test(term_sequence_test, Config).
-
-term_struct_test(Config) ->
- do_test(term_struct_test, Config).
-
-term_test(Config) ->
- do_test(term_test, Config).
-
-typedef_test(Config) ->
- do_test(typedef_test, Config).
-
-ulonglong_test(Config) ->
- do_test(ulonglong_test, Config).
-
-ulong_test(Config) ->
- do_test(ulong_test, Config).
-
-ushort_test(Config) ->
- do_test(ushort_test, Config).
-
-void_test(Config) ->
- do_test(void_test, Config).
-
-wchar_test(Config) ->
- do_test(wchar_test, Config).
-
-wstring1_test(Config) ->
- do_test(wstring1_test, Config).
-
-
-do_test(Case, Config) ->
- %% Trap exits
- process_flag(trap_exit, true),
- Node = atom_to_list(node()),
- [_NodeName, HostName] = string:tokens(Node, "@"),
- DataDir = proplists:get_value(data_dir, Config),
- %% io:format("~p: data directory: ~p~n", [?MODULE, DataDir]),
- Cookie = atom_to_list(erlang:get_cookie()),
- ServerNodeName = atom_to_list(?C_SERVER_NODE_NAME),
- %% Start C-server node as a port program. We wait for the node
- %% to connect to us.
- Cmd = filename:join([DataDir, "c_server"]) ++
- " -this-node-name " ++ ServerNodeName ++
- " -peer-node " ++ Node ++
- " -cookie " ++ Cookie,
- Port = open_port({spawn, Cmd}, [exit_status, eof, stderr_to_stdout]),
- ServerNode = list_to_atom(ServerNodeName ++ "@" ++ HostName),
- Res = case wait_for_hidden_node(ServerNode) of
- ok ->
- %% Need a port for port_test and typedef_test
- put(port_test_port, Port),
- R = (catch erl_client:Case(ServerNode, ?CALL_TIMEOUT)),
- case wait_for_completion(Port) of
- {error, timeout} ->
- kill_off_node(ServerNode);
- _ ->
- ok
- end,
- R;
- {error, timeout} ->
- case wait_for_completion(Port) of
- {error, timeout} ->
- kill_off_node(ServerNode);
- _ ->
- ok
- end,
- {error, timeout}
- end,
- process_flag(trap_exit, false),
- true = Res.
-
-
-%% Wait for eof *and* exit status, but return if exit status indicates
-%% an error, or we have been waiting more than PORT_TIMEOUT seconds.
-%%
-wait_for_completion(Port) ->
- wait_for_completion(Port, 0).
-
-wait_for_completion(Port, N) when N < 2 ->
- receive
- {Port, {data, Bytes}} ->
- %% Relay output
- io:format("~s", [Bytes]),
- wait_for_completion(Port, N);
- {Port, {exit_status, 0}} ->
- wait_for_completion(Port, N + 1);
- {Port, {exit_status, Status}} ->
- {error, Status};
- {Port, eof} ->
- wait_for_completion(Port, N + 1);
- {'EXIT', Port, Reason} ->
- io:format("Port exited with reason: ~w~n", [Reason]),
- wait_for_completion(Port, N);
- {'EXIT', From, Reason} ->
- io:format("Got unexpected exit: ~p~n", [{'EXIT', From, Reason}]),
- wait_for_completion(Port, N)
- after ?PORT_TIMEOUT ->
- {error, timeout}
- end;
-wait_for_completion(_, _) ->
- ok.
-
-wait_for_hidden_node(Node) ->
- Times = ?DEFAULT_TIMEOUT div 100,
- wait_for_hidden_node(Node, Times, 100).
-
-wait_for_hidden_node(Node, Times, WaitTime) when Times > 0 ->
- io:format("Waiting for hidden node: ~p~n", [Node]),
- case lists:member(Node, erlang:nodes(hidden)) of
- true ->
- ok;
- false ->
- delay(WaitTime),
- wait_for_hidden_node(Node, Times - 1, WaitTime)
- end;
-wait_for_hidden_node(_Node, _, _WaitTime) ->
- {error, timeout}.
-
-kill_off_node(Node) ->
- catch rpc:cast(Node, erlang, halt, [1]).
-
-delay(Time) ->
- receive
- after Time ->
- ok
- end.
-
-
-
-
diff --git a/lib/ic/test/erl_client_c_server_SUITE_data/Makefile.src b/lib/ic/test/erl_client_c_server_SUITE_data/Makefile.src
deleted file mode 100644
index 11eee8b7ac..0000000000
--- a/lib/ic/test/erl_client_c_server_SUITE_data/Makefile.src
+++ /dev/null
@@ -1,160 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2002-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-# Makefile.src for erl_client_c_server test
-# Note: This file *must* work for both Unix and Windows
-#
-# We use both `rm' (Unix) and `del' (Windows) for removing files, but
-# with a `-' in front so that the error in not finding `rm' (`del') on
-# Windows (Unix) is ignored.
-#
-# VxWorks? XXX
-#
-
-.SUFFIXES:
-.SUFFIXES: .c .h .erl .idl @obj@ .@EMULATOR@
-
-
-# Variables from ts:
-#
-
-ERL_INCLUDE = @erl_include@
-
-IC_INCLUDE_PATH = @ic_include_path@
-IC_LIB = @ic_lib@
-
-ERL_INTERFACE_INCLUDE = @erl_interface_include@
-ERL_INTERFACE_LIB = @erl_interface_lib@
-ERL_INTERFACE_EILIB = @erl_interface_eilib@
-ERL_INTERFACE_THREADLIB = @erl_interface_threadlib@
-ERL_INTERFACE_SOCK_LIBS = @erl_interface_sock_libs@
-
-CC = @CC@
-## XXX Should set warning flag with a DEBUG_FLAG
-CFLAGS = @CFLAGS@ @DEFS@ -I$(ERL_INCLUDE) \
- -I$(IC_INCLUDE_PATH) -I$(ERL_INTERFACE_INCLUDE)
-
-LD = @LD@
-LDFLAGS = @CROSSLDFLAGS@
-LIBS = $(IC_LIB) $(ERL_INTERFACE_LIB) $(ERL_INTERFACE_EILIB) \
- $(ERL_INTERFACE_THREADLIB) @LIBS@ $(ERL_INTERFACE_SOCK_LIBS)
-ERLC = erlc
-
-# Generated C header files
-GEN_H_FILES = \
- m__s.h \
- m_i__s.h \
- oe_erl_c_test__s.h
-
-# Generated C files
-GEN_C_FILES = \
- m__s.c \
- m_i__s.c \
- oe_code_m_a.c \
- oe_code_m_arr1.c \
- oe_code_m_arr2.c \
- oe_code_m_arr3.c \
- oe_code_m_aseq.c \
- oe_code_m_b.c \
- oe_code_m_bseq.c \
- oe_code_m_dd.c \
- oe_code_m_dyn.c \
- oe_code_m_dyn_sl.c \
- oe_code_m_es.c \
- oe_code_m_et.c \
- oe_code_m_etseq.c \
- oe_code_m_fruit.c \
- oe_code_m_lseq.c \
- oe_code_m_s.c \
- oe_code_m_s_sl.c \
- oe_code_m_sarr3.c \
- oe_code_m_simple.c \
- oe_code_m_ssarr3.c \
- oe_code_m_sseq.c \
- oe_code_m_ssstr3.c \
- oe_code_m_sstr3.c \
- oe_code_m_str1.c \
- oe_code_m_str3.c \
- oe_code_m_strRec.c \
- oe_code_m_strRec_str5.c \
- oe_code_m_strRec_str7.c \
- oe_erl_c_test__s.c
-
-GEN_HRL_FILES = \
- m.hrl \
- m_i.hrl \
- oe_erl_c_test.hrl
-
-GEN_ERL_FILES = \
- m.erl \
- m_arr2.erl \
- m_arr3.erl \
- m_i.erl \
- m_str3.erl \
- oe_erl_c_test.erl
-
-C_FILES = $(GEN_C_FILES) c_server.c callbacks.c
-
-OBJS = $(C_FILES:.c=@obj@)
-
-PGMS = c_server@exe@
-
-ERL_FILES = $(GEN_ERL_FILES) erl_client.erl
-
-EBINS = $(ERL_FILES:.erl=.@EMULATOR@)
-
-
-all: $(PGMS) $(EBINS)
-
-$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.built_erl
-$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.built_c
-$(OBJS): $(GEN_C_FILES) $(GEN_H_FILES)
-$(EBINS): $(GEN_ERL_FILES) $(GEN_HRL_FILES)
-
-clean:
- -rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
- c_erl_test.built_erl c_erl_test.built_c
- -del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
- c_erl_test.built_erl c_erl_test.built_c
-
-$(PGMS): $(OBJS)
- $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
-
-c_erl_test.built_c: erl_c_test.idl
- $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_server}" \
- "+{scoped_op_calls,true}" erl_c_test.idl
- echo done > c_erl_test.built_c
-
-# If we have scoped operation calls for C, we must have that for
-# Erlang as well, if we use the m_i.erl file for calling the server.
-
-c_erl_test.built_erl: erl_c_test.idl
- $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" \
- "+{scoped_op_calls,true}" "+{timeout,true}" erl_c_test.idl
- echo done > c_erl_test.built_erl
-
-.c@obj@:
- $(CC) -c -o $*@obj@ $(CFLAGS) $<
-
-.erl.@EMULATOR@:
- $(ERLC) -W -I $(IC_INCLUDE_PATH) $<
-
diff --git a/lib/ic/test/erl_client_c_server_SUITE_data/c_server.c b/lib/ic/test/erl_client_c_server_SUITE_data/c_server.c
deleted file mode 100644
index f48480e8dc..0000000000
--- a/lib/ic/test/erl_client_c_server_SUITE_data/c_server.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2002-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/* C-server for test of IC.
- *
- * The C-node implemented here connects to its peer node, waits for
- * one message, evaluates the message, returns an result message, and
- * terminates.
- *
- * TODO:
- *
- * 1. XXX #includes for VxWorks, Windows
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifndef __WIN32__
-# include <unistd.h>
-#endif
-
-#include <string.h>
-
-#ifdef __WIN32__
-# include <time.h>
-# include <sys/timeb.h>
-#elif defined VXWORKS
-# include <time.h>
-# include <sys/times.h>
-#else
-# include <sys/time.h>
-#endif
-
-#include <ctype.h>
-
-#ifdef __WIN32__
-# include <winsock2.h>
-# include <windows.h>
-#else
-# include <sys/types.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <arpa/inet.h>
-# include <netdb.h>
-#endif
-
-#include "ic.h"
-#include "ei.h"
-#include "erl_interface.h"
-#include "eicode.h"
-#include "m_i__s.h"
-#include "m__s.h"
-
-#ifdef __WIN32__
-typedef struct {
- long tv_sec;
- long tv_usec;
-} MyTimeval;
-#else
-typedef struct timeval MyTimeval;
-#endif
-static void my_gettimeofday(MyTimeval *tv);
-static void showtime(MyTimeval *start, MyTimeval *stop);
-static void usage(void);
-static void done(int r);
-
-#define HOSTNAMESZ 255
-#define NODENAMESZ 512
-#define INBUFSZ 10
-#define OUTBUFSZ 0
-#define MAXTRIES 5
-
-static char *progname;
-
-/* main */
-#ifdef VXWORKS
-int c_server(int argc, char **argv)
-#else
-int main(int argc, char **argv)
-#endif
-{
- struct hostent *hp;
- MyTimeval start, stop;
- int i, fd, ires, tries;
- CORBA_Environment *env;
- char *this_node_name = NULL;
- char *peer_node = NULL;
- char *cookie = NULL;
- char host[HOSTNAMESZ + 1];
- char this_node[NODENAMESZ + 1];
- erlang_msg msg;
- int status, loop;
-
-#ifdef __WIN32__
- WORD wVersionRequested;
- WSADATA wsaData;
-
- wVersionRequested = MAKEWORD(2, 0);
-
- if (WSAStartup(wVersionRequested, &wsaData) != 0) {
- fprintf(stderr, "Could not load winsock2 v2.0 compatible DLL");
- exit(1);
- }
-#endif
-
- progname = argv[0];
- host[HOSTNAMESZ] = '\0';
- if (gethostname(host, HOSTNAMESZ + 1) < 0) {
- fprintf(stderr, "Can't find own hostname\n");
- done(1);
- }
- if ((hp = gethostbyname(host)) == 0) {
- fprintf(stderr, "Can't get ip address for host %s\n", host);
- done(1);
- }
- for (i = 1; i < argc; i++) {
- if (strcmp(argv[i], "-help") == 0) {
- usage();
- done(0);
- } else if (strcmp(argv[i], "-this-node-name") == 0) {
- i++;
- this_node_name = argv[i];
- } else if (strcmp(argv[i], "-peer-node") == 0) {
- i++;
- peer_node = argv[i];
- } else if (strcmp(argv[i], "-cookie") == 0) {
- i++;
- cookie = argv[i];
- } else {
- fprintf(stderr, "Error : invalid argument \"%s\"\n", argv[i]);
- usage();
- done(1);
- }
- }
-
- if (this_node_name == NULL || peer_node == NULL || cookie == NULL) {
- fprintf(stderr, "Error: missing option\n");
- usage();
- done(1);
- }
-
- /* Behead hostname at first dot */
- for (i=0; host[i] != '\0'; i++) {
- if (host[i] == '.') { host[i] = '\0'; break; }
- }
- sprintf(this_node, "%s@%s", this_node_name, host);
-
- fprintf(stderr, "c_server: this node: \"%s\"\n", this_node);
- fprintf(stderr, "c_server: peer node: \"%s\"\n", peer_node);
-
- /* initialize erl_interface */
- erl_init(NULL, 0);
-
- for (tries = 0; tries < MAXTRIES; tries++) {
- /* connect to peer node */
- ires = erl_connect_xinit(host, this_node_name, this_node,
- (struct in_addr *)*hp->h_addr_list,
- cookie, 0);
- fprintf(stderr, "c_server: erl_connect_xinit(): %d\n", ires);
-
- fd = erl_connect(peer_node);
- fprintf(stderr, "c_server: erl_connect(): %d\n", fd);
- if (fd >= 0)
- break;
- fprintf(stderr, "c_server: cannot connect, retrying\n");
- }
- if (fd < 0) {
- fprintf(stderr, "c_server: cannot connect, exiting\n");
- done(1);
- }
- env = CORBA_Environment_alloc(INBUFSZ, OUTBUFSZ);
- env->_fd = fd;
-
- status = 1;
- loop = 1;
- my_gettimeofday(&start);
- while (status >= 0 && loop > 0) {
- status = ei_receive_encoded(env->_fd, &env->_inbuf, &env->_inbufsz,
- &msg, &env->_iin);
- switch(status) {
- case ERL_SEND:
- case ERL_REG_SEND:
- /* get result */
- m_i__switch(NULL, env);
- switch(env->_major) {
- case CORBA_NO_EXCEPTION:
- break;
- case CORBA_SYSTEM_EXCEPTION:
- fprintf(stderr, "Request failure, reason : %s\n",
- (char *) CORBA_exception_value(env));
- CORBA_exception_free(env);
- break;
- default: /* Should not happen */
- CORBA_exception_free(env);
- break;
- }
- /* send back result data */
- if (env->_iout > 0)
- ei_send_encoded(env->_fd, &env->_caller, env->_outbuf,
- env->_iout);
- loop = 0;
- break;
- case ERL_TICK:
- break;
- default:
- if (status < 0) {
- fprintf(stderr, "Status negative: %d\n", status);
- loop = 0;
- }
- break;
- }
- }
- my_gettimeofday(&stop);
- showtime(&start, &stop);
-
- erl_close_connection(fd);
-
- CORBA_free(env->_inbuf);
- CORBA_free(env->_outbuf);
- CORBA_free(env);
- if (status < 0)
- done(-status);
- else
- done(0);
-}
-
-static void usage()
-{
- fprintf(stderr, "Usage: %s [-help] -this-node-name <name> "
- "-peer-node <nodename> -cookie <cookie>\n", progname);
- fprintf(stderr, "Example:\n %s -this-node-name kalle "
- "-peer-node olle@home -cookie oa678er\n", progname);
-}
-
-static void done(int r)
-{
-#ifdef __WIN32__
- WSACleanup();
-#endif
- exit(r);
-}
-
-static void showtime(MyTimeval *start, MyTimeval *stop)
-{
- MyTimeval elapsed;
-
- elapsed.tv_sec = stop->tv_sec - start->tv_sec;
- elapsed.tv_usec = stop->tv_usec - start->tv_usec;
- while (elapsed.tv_usec < 0) {
- elapsed.tv_sec -= 1;
- elapsed.tv_usec += 1000000;
- }
- fprintf(stderr,"%ld.%06ld seconds\n",elapsed.tv_sec, elapsed.tv_usec);
-}
-
-
-
-static void my_gettimeofday(MyTimeval *tv)
-#ifdef __WIN32__
-#define EPOCH_JULIAN_DIFF 11644473600i64
-{
- SYSTEMTIME t;
- FILETIME ft;
- LONGLONG lft;
-
- GetSystemTime(&t);
- SystemTimeToFileTime(&t, &ft);
- memcpy(&lft, &ft, sizeof(lft));
- tv->tv_usec = (long) ((lft / 10i64) % 1000000i64);
- tv->tv_sec = (long) ((lft / 10000000i64) - EPOCH_JULIAN_DIFF);
-}
-#elif defined VXWORKS
-{
- int rate = sysClkRateGet(); /* Ticks per second */
- unsigned long ctick = tickGet();
- tv->tv_sec = ctick / rate; /* secs since reboot */
- tv->tv_usec = ((ctick - (tv->tv_sec * rate))*1000000)/rate;
-}
-#else
-{
- gettimeofday(tv, NULL);
-}
-#endif
diff --git a/lib/ic/test/erl_client_c_server_SUITE_data/callbacks.c b/lib/ic/test/erl_client_c_server_SUITE_data/callbacks.c
deleted file mode 100644
index 2611e15f5a..0000000000
--- a/lib/ic/test/erl_client_c_server_SUITE_data/callbacks.c
+++ /dev/null
@@ -1,611 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2002-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#ifndef __WIN32__
-# include <unistd.h>
-#endif
-#include <string.h>
-#include <ctype.h>
-#include <ic.h>
-#include <erl_interface.h>
-#include <ei.h>
-#include "m_i__s.h"
-
-
-
-/* OK */
-
-void my_void_test(CORBA_Object oe_obj,
- CORBA_Environment *oe_env)
-{
- /* printf("void test !\n"); */
-}
-
-m_i_void_test__rs* m_i_void_test__cb(CORBA_Object oe_obj,
- CORBA_Environment *oe_env)
-{
- return (m_i_void_test__rs*) (my_void_test);
-}
-
-
-
-/* OK */
-
-void my_long_test(CORBA_Object oe_obj,
- long* a,
- long* b,
- long* c,
- CORBA_Environment *oe_env)
-{
- /* printf("long test !\n"); */
-}
-
-
-m_i_long_test__rs* m_i_long_test__cb(CORBA_Object oe_obj,
- long* a,
- long* b,
- long* c,
- CORBA_Environment *oe_env)
-{
- *a = *b;
- *c = *b;
- return (m_i_long_test__rs*) (my_long_test);
-}
-
-/* OK */
-
-void my_longlong_test(CORBA_Object oe_obj,
- CORBA_long_long* a,
- CORBA_long_long* b,
- CORBA_long_long* c,
- CORBA_Environment *oe_env)
-{
- /* printf("long test !\n"); */
-}
-
-m_i_longlong_test__rs* m_i_longlong_test__cb(CORBA_Object oe_obj,
- CORBA_long_long* a,
- CORBA_long_long* b,
- CORBA_long_long* c,
- CORBA_Environment *oe_env)
-{
- *a = *b;
- *c = *b;
- return (m_i_longlong_test__rs*) (my_longlong_test);
-}
-
-/* OK */
-void my_ulong_test(CORBA_Object oe_obj,
- unsigned long* a,
- unsigned long* b,
- unsigned long* c,
- CORBA_Environment *oe_env)
-{
- /* printf("ulong test !\n"); */
-}
-
-m_i_ulong_test__rs* m_i_ulong_test__cb(CORBA_Object oe_obj,
- unsigned long* a,
- unsigned long* b,
- unsigned long* c,
- CORBA_Environment *oe_env)
-{
- *a = *b;
- *c = *b;
- return (m_i_ulong_test__rs*) (my_ulong_test);
-}
-
-/* OK */
-void my_ulonglong_test(CORBA_Object oe_obj,
- CORBA_unsigned_long_long* a,
- CORBA_unsigned_long_long* b,
- CORBA_unsigned_long_long* c,
- CORBA_Environment *oe_env)
-{
- /* printf("ulong test !\n"); */
-}
-
-m_i_ulonglong_test__rs* m_i_ulonglong_test__cb(CORBA_Object oe_obj,
- CORBA_unsigned_long_long* a,
- CORBA_unsigned_long_long* b,
- CORBA_unsigned_long_long* c,
- CORBA_Environment *oe_env)
-{
- *a = *b;
- *c = *b;
- return (m_i_ulonglong_test__rs*) (my_ulonglong_test);
-}
-
-m_i_ushort_test__rs* m_i_ushort_test__cb(CORBA_Object oe_obj,
- unsigned short* a,
- unsigned short* b,
- unsigned short* c,
- CORBA_Environment *oe_env)
-{
- *a = *b;
- *c = *b;
- return (m_i_ushort_test__rs*) NULL;
-}
-
-
-/* OK */
-void my_double_test(CORBA_Object oe_obj,
- double* a,
- double* b,
- double* c,
- CORBA_Environment *oe_env)
-{
- /* printf("double test !\n"); */
-}
-
-m_i_double_test__rs* m_i_double_test__cb(CORBA_Object oe_obj,
- double* a,
- double* b,
- double* c,
- CORBA_Environment *oe_env)
-{
- *a = *b;
- *c = *b;
- return (m_i_double_test__rs*) (my_double_test);
-}
-
-/* OK */
-m_i_char_test__rs* m_i_char_test__cb(CORBA_Object oe_obj,
- char* a,
- char* b,
- char* c,
- CORBA_Environment *oe_env)
-{
- m_i_char_test__rs* rs = NULL;
-
- *a = *b;
- *c = *b;
- return rs;
-}
-
-
-/* OK */
-m_i_wchar_test__rs* m_i_wchar_test__cb(CORBA_Object oe_obj,
- CORBA_wchar* a,
- CORBA_wchar* b,
- CORBA_wchar* c,
- CORBA_Environment *oe_env)
-{
- m_i_wchar_test__rs* rs = NULL;
-
- *a = *b;
- *c = *b;
- return rs;
-}
-
-/* OK */
-m_i_octet_test__rs* m_i_octet_test__cb(CORBA_Object oe_obj,
- char* a,
- char* b,
- char* c,
- CORBA_Environment *oe_env)
-{
- m_i_octet_test__rs* rs = NULL;
-
- *a = *b;
- *c = *b;
- return rs;
-}
-
-/* OK */
-m_i_bool_test__rs* m_i_bool_test__cb(CORBA_Object oe_obj,
- CORBA_boolean* a,
- CORBA_boolean* b,
- CORBA_boolean* c,
- CORBA_Environment *oe_env)
-{
- m_i_bool_test__rs* rs = NULL;
-
- *a = *b;
- *c = *b;
- return rs;
-}
-
-/* OK */
-void my_struct_test(CORBA_Object oe_obj,
- m_b* a,
- m_b* b,
- m_b* c,
- CORBA_Environment *oe_env)
-{
- /* printf("struct test !\n"); */
-}
-
-m_i_struct_test__rs* m_i_struct_test__cb(CORBA_Object oe_obj,
- m_b* a,
- m_b* b,
- m_b* c,
- CORBA_Environment *oe_env)
-{
- *a = *b;
- *c = *b;
- return (m_i_struct_test__rs*) (my_struct_test);
-}
-
-/* OK */
-m_i_struct2_test__rs* m_i_struct2_test__cb(CORBA_Object oe_obj,
- m_es* a,
- m_es* b,
- m_es* c,
- CORBA_Environment *oe_env)
-{
- m_i_struct2_test__rs* rs = NULL;
-
- *a = *b;
- *c = *b;
- return rs;
-}
-
-/* OK */
-/* XXX Commented out
-m_i_struct3_test__rs* m_i_struct3_test__cb(CORBA_Object oe_obj,
- m_simple* a,
- m_simple* b,
- m_simple* c,
- CORBA_Environment *oe_env)
-{
- m_i_struct3_test__rs* rs = NULL;
- *a = *b;
- *c = *b;
- return rs;
-}
-*/
-
-/* OK */
-m_i_seq1_test__rs* m_i_seq1_test__cb(CORBA_Object oe_obj,
- m_bseq** a,
- m_bseq* b,
- m_bseq** c,
- CORBA_Environment *oe_env)
-{
- m_i_seq1_test__rs* rs = NULL;
-
- *a = b;
- *c = b;
- return rs;
-}
-
-
-/* OK */
-m_i_seq2_test__rs* m_i_seq2_test__cb(CORBA_Object oe_obj,
- m_aseq** a,
- m_aseq* b,
- m_aseq** c,
- CORBA_Environment *oe_env)
-{
- m_i_seq2_test__rs* rs = NULL;
-
- *a = b;
- *c = b;
- return rs;
-}
-
-/* OK */
-m_i_seq3_test__rs* m_i_seq3_test__cb(CORBA_Object oe_obj,
- m_lseq** a,
- m_lseq* b,
- m_lseq** c,
- CORBA_Environment *oe_env)
-{
- m_i_seq3_test__rs* rs = NULL;
-
- *a = b;
- *c = b;
- return rs;
-}
-
-/* OK */
-m_i_seq4_test__rs* m_i_seq4_test__cb(CORBA_Object oe_obj,
- m_ssstr3** a,
- m_ssstr3* b,
- m_ssstr3** c,
- CORBA_Environment *oe_env)
-{
- m_i_seq4_test__rs* rs = NULL;
-
- *a = b;
- *c = b;
- return rs;
-}
-
-/* OK */
-m_i_seq5_test__rs* m_i_seq5_test__cb(CORBA_Object oe_obj,
- m_ssarr3** a,
- m_ssarr3* b,
- m_ssarr3** c,
- CORBA_Environment *oe_env)
-{
- m_i_seq5_test__rs* rs = NULL;
-
- *a = b;
- *c = b;
- return rs;
-}
-
-/* OK */
-m_i_array1_test__rs* m_i_array1_test__cb(CORBA_Object oe_obj,
- m_arr1 a,
- m_arr1 b,
- m_arr1 c,
- CORBA_Environment *oe_env)
-{
- int i;
- m_i_array1_test__rs* rs = NULL;
-
- for (i = 0; i < 500; i++) {
- a[i] = b[i];
- c[i] = b[i];
- }
- return rs;
-}
-
-/* OK */
-m_i_array2_test__rs* m_i_array2_test__cb(CORBA_Object oe_obj,
- m_dd a,
- m_dd b,
- m_dd c,
- CORBA_Environment *oe_env)
-{
- int i,j;
- m_i_array2_test__rs* rs = NULL;
-
- for (i = 0; i < 2; i++)
- for (j = 0; j < 3; j++) {
- a[i][j] = b[i][j];
- c[i][j] = b[i][j];
- }
- return rs;
-}
-
-
-/* OK */
-m_i_enum_test__rs* m_i_enum_test__cb(CORBA_Object oe_obj,
- m_fruit* a,
- m_fruit* b,
- m_fruit* c,
- CORBA_Environment *oe_env)
-{
- m_i_enum_test__rs* rs = NULL;
-
- *a = *b;
- *c = *b;
- return rs;
-}
-
-/* OK */
-m_i_string1_test__rs* m_i_string1_test__cb(CORBA_Object oe_obj,
- char ** a,
- char * b,
- char ** c,
- CORBA_Environment *oe_env)
-{
- m_i_string1_test__rs* rs = NULL;
-
- /*printf("\nString in ------> %s\n\n",b);*/
- *a = b;
- *c = b;
- return rs;
-}
-
-/* OK */
-m_i_string2_test__rs* m_i_string2_test__cb(CORBA_Object oe_obj,
- m_sseq** a,
- m_sseq* b,
- m_sseq** c,
- CORBA_Environment *oe_env)
-{
- m_i_string2_test__rs* rs = NULL;
-
- *a = b;
- *c = b;
- return rs;
-}
-
-/* OK */
-m_i_string3_test__rs* m_i_string3_test__cb(CORBA_Object oe_obj,
- char ** a,
- char * b,
- char ** c,
- CORBA_Environment *oe_env)
-{
- m_i_string3_test__rs* rs = NULL;
-
- *a = b;
- *c = b;
- return rs;
-}
-
-m_i_string4_test__rs* m_i_string4_test__cb(CORBA_Object oe_obj,
- m_strRec** a,
- m_strRec* b,
- m_strRec** c,
- CORBA_Environment *oe_env)
-{
- *a = b;
- *c = b;
-
- return (m_i_string4_test__rs*) NULL;
-}
-
-/* OK */
-m_i_wstring1_test__rs* m_i_wstring1_test__cb(CORBA_Object oe_obj,
- CORBA_wchar ** a,
- CORBA_wchar * b,
- CORBA_wchar ** c,
- CORBA_Environment *oe_env)
-{
- int tmp;
- m_i_wstring1_test__rs* rs = NULL;
-
- /*printf("\nString in ------> %s\n\n",b);*/
-
- for(tmp = 0; tmp < 5; tmp++)
- fprintf(stderr,"\np[%d] = %ld\n", tmp, b[tmp]);
- *a = b;
- *c = b;
- return rs;
-}
-
-
-/* OK */
-m_i_pid_test__rs* m_i_pid_test__cb(CORBA_Object oe_obj,
- erlang_pid* a,
- erlang_pid* b,
- erlang_pid* c,
- CORBA_Environment *oe_env)
-{
- m_i_pid_test__rs* rs = NULL;
-
- *a = *b;
- *c = *b;
- return rs;
-}
-
-/* OK */
-m_i_port_test__rs* m_i_port_test__cb(CORBA_Object oe_obj,
- erlang_port* a,
- erlang_port* b,
- erlang_port* c,
- CORBA_Environment *oe_env)
-{
- m_i_port_test__rs* rs = NULL;
-
- strcpy((*a).node,(*b).node);
- (*a).id = (*b).id;
- (*a).creation = 0;
-
- strcpy((*c).node,(*b).node);
- (*c).id = (*b).id;
- (*c).creation = 0;
- return rs;
-}
-
-/* OK */
-m_i_ref_test__rs* m_i_ref_test__cb(CORBA_Object oe_obj,
- erlang_ref* a,
- erlang_ref* b,
- erlang_ref* c,
- CORBA_Environment *oe_env)
-{
-
- m_i_ref_test__rs* rs = NULL;
-
- strcpy((*a).node,(*b).node);
- /*(*a).id = (*b).id;*/
- (*a).len = (*b).len;
- (*a).n[0] = (*b).n[0];
- (*a).n[1] = (*b).n[1];
- (*a).n[2] = (*b).n[2];
- (*a).creation = 0;
-
- strcpy((*c).node,(*b).node);
- /*(*c).id = (*b).id;*/
- (*c).len = (*b).len;
- (*c).n[0] = (*b).n[0];
- (*c).n[1] = (*b).n[1];
- (*c).n[2] = (*b).n[2];
- (*c).creation = 0;
- return rs;
-}
-
-/* OK */
-m_i_term_test__rs* m_i_term_test__cb(CORBA_Object oe_obj,
- ETERM** a,
- ETERM** b,
- ETERM** c,
- CORBA_Environment *oe_env)
-{
- m_i_term_test__rs* rs = NULL;
-
- *a = *b;
- *c = *b;
- return rs;
-}
-
-m_i_typedef_test__rs* m_i_typedef_test__cb(CORBA_Object oe_obj,
- long* a,
- ETERM** b,
- erlang_port* c,
- ETERM** d ,
- erlang_port* e,
- CORBA_Environment *oe_env)
-{
- m_i_typedef_test__rs* rs = NULL;
-
- *d = *b;
- strcpy((*e).node,(*c).node);
- (*e).id = (*c).id;
- (*e).creation = 0;
- *a = 4711;
- return rs;
-}
-
-/* OK */
-m_i_inline_sequence_test__rs* m_i_inline_sequence_test__cb(
- CORBA_Object oe_obj,
- m_s** a,
- m_s* b,
- m_s** c,
- CORBA_Environment *oe_env)
-{
- m_i_inline_sequence_test__rs* rs = NULL;
-
- *a = b;
- *c = b;
- return rs;
-}
-
-/* OK */
-m_i_term_sequence_test__rs* m_i_term_sequence_test__cb(
- CORBA_Object oe_obj,
- m_etseq** a,
- m_etseq* b,
- m_etseq** c,
- CORBA_Environment *oe_env)
-{
- m_i_term_sequence_test__rs* rs = NULL;
-
- *a = b;
- *c = b;
- return rs;
-}
-
-
-/* OK */
-m_i_term_struct_test__rs* m_i_term_struct_test__cb(CORBA_Object oe_obj,
- m_et* a,
- m_et* b,
- m_et* c,
- CORBA_Environment *oe_env)
-{
- m_i_term_struct_test__rs* rs = NULL;
-
- *a = *b;
- *c = *b;
- return rs;
-}
-
diff --git a/lib/ic/test/erl_client_c_server_SUITE_data/erl_c_test.idl b/lib/ic/test/erl_client_c_server_SUITE_data/erl_c_test.idl
deleted file mode 100644
index 6ed28f0822..0000000000
--- a/lib/ic/test/erl_client_c_server_SUITE_data/erl_c_test.idl
+++ /dev/null
@@ -1,175 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 2002-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-#include "erlang.idl"
-
-
-const short TestConst = 1;
-
-module m {
-
- const short TestConst = 2;
-
- struct b {
- long l;
- char c;
- };
-
- struct simple {
- long l;
- b b_t;
- };
-
- enum fruit {orange, banana, apple, peach, pear};
-
- typedef sequence<long> lseq;
-
- typedef sequence<b> bseq;
-
- struct a {
- long l;
- bseq y;
- double d;
- };
-
- typedef sequence<a> aseq;
-
- typedef sequence<string> sseq;
- typedef string str;
- typedef long myLong;
-
- typedef long arr1[500], dd[2][3];
-
- typedef erlang::term apa;
- typedef erlang::port banan;
-
- typedef sequence<erlang::term> etseq;
-
- struct s {
- long l;
- sequence<long> sl;
- };
-
- struct es {
- fruit f;
- myLong l;
- };
-
- struct et {
- erlang::term e;
- long l;
- };
-
-
- typedef sequence<char> str1;
- typedef string<12> str2;
- typedef char str3[3];
-
- typedef sequence<string> sstr3; // sequence of string
- typedef sequence<sstr3> ssstr3; // sequence of sequences of strings
-
- typedef long arr3[3]; // array of long
- typedef sequence<arr3> sarr3; // sequence of array
- typedef sequence<sarr3> ssarr3; // sequence of sequnces of arrays of strings
-
- struct strRec{
- boolean bb;
- string str4;
- long str7[3][2];
- sequence<char> str5;
- string<12> str6;
- str3 str8;
- str2 str9;
- str1 str10;
- };
-
-
- struct dyn {
- long l;
- sequence<long> sl;
- };
- typedef dyn arr2[1][2];
-
-
- interface i {
-
- const short TestConst = 3;
-
- //arr2 suck(in arr2 x, out arr2 y );
-
- ///////////////////////////////// attribute long l;
-
- // simple types
- void void_test();
- long long_test(in long a, out long a1);
- long long longlong_test(in long long a, out long long a1);
- unsigned short ushort_test(in unsigned short a, out unsigned short a1);
- unsigned long ulong_test(in unsigned long a, out unsigned long a1);
- unsigned long long ulonglong_test(in unsigned long long a, out unsigned long long a1);
- double double_test(in double a, out double a1);
- char char_test(in char a, out char a1);
- wchar wchar_test(in wchar a, out wchar a1);
- octet octet_test(in octet a, out octet a1);
- boolean bool_test(in boolean a, out boolean a1);
-
- // Seq. and struct tests
- b struct_test(in b a, out b a1);
- es struct2_test(in es a, out es a1);
- //simple struct3_test(in simple x, out simple y);
- bseq seq1_test(in bseq a, out bseq a1);
- aseq seq2_test(in aseq a, out aseq a1);
- lseq seq3_test(in lseq a, out lseq a1);
- ssstr3 seq4_test(in ssstr3 a, out ssstr3 a1);
- ssarr3 seq5_test(in ssarr3 a, out ssarr3 a1);
-
- // Array tests
- arr1 array1_test(in arr1 a, out arr1 a1);
- dd array2_test(in dd a, out dd a1);
-
- // enum test
- fruit enum_test(in fruit a, out fruit a1);
-
- // string tests
- string string1_test(in string a, out string a1);
- wstring wstring1_test(in wstring a, out wstring a1);
- sseq string2_test(in sseq a, out sseq a1);
- str string3_test(in str a, out str a1);
- strRec string4_test(in strRec a, out strRec a1);
-
- // Special erlang types
- erlang::pid pid_test(in erlang::pid a, out erlang::pid a1);
- erlang::port port_test(in erlang::port a, out erlang::port a1);
- erlang::ref ref_test(in erlang::ref a, out erlang::ref a1);
- erlang::term term_test(in erlang::term a, out erlang::term a1);
-
- // typedef test
- long typedef_test(in apa a, in banan b, out apa a1, out banan b1);
-
- // inlined seq. test
- s inline_sequence_test(in s a, out s a1);
-
- // term seq. test
- etseq term_sequence_test(in etseq a, out etseq a1);
- // term struct test
- et term_struct_test(in et a, out et a1);
-
- };
-
-};
diff --git a/lib/ic/test/erl_client_c_server_SUITE_data/erl_client.erl b/lib/ic/test/erl_client_c_server_SUITE_data/erl_client.erl
deleted file mode 100644
index 139e2d7661..0000000000
--- a/lib/ic/test/erl_client_c_server_SUITE_data/erl_client.erl
+++ /dev/null
@@ -1,332 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(erl_client).
-
--export([void_test/2, long_test/2, longlong_test/2, ushort_test/2,
- ulong_test/2, ulonglong_test/2, double_test/2, char_test/2,
- wchar_test/2, octet_test/2, bool_test/2, struct_test/2,
- struct2_test/2, seq1_test/2, seq2_test/2, seq3_test/2,
- seq4_test/2, seq5_test/2, array1_test/2, array2_test/2,
- enum_test/2, string1_test/2, wstring1_test/2, string2_test/2,
- string3_test/2, string4_test/2, pid_test/2, port_test/2,
- ref_test/2, term_test/2, typedef_test/2,
- inline_sequence_test/2, term_sequence_test/2,
- term_struct_test/2
-
-]).
-
--include("m.hrl").
--include("m_i.hrl").
--include("oe_erl_c_test.hrl").
-
-%%b
-void_test(Node, Timeout) ->
- Ret = m_i:void_test({olsson, Node}, Timeout),
- Ret == void. % XXX Not documented
-%%e
-
-%%b
-long_test(Node, Timeout) ->
- In = max_long(),
- {Ret, Out} = m_i:long_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-longlong_test(Node, Timeout) ->
- In = 65537,
- {Ret, Out} = m_i:longlong_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-ushort_test(Node, Timeout) ->
- In = max_ushort(),
- {Ret, Out} = m_i:ushort_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-ulong_test(Node, Timeout) ->
- In = max_ulong(),
- {Ret, Out} = m_i:ulong_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-ulonglong_test(Node, Timeout) ->
- In = 65537,
- {Ret, Out} = m_i:ulonglong_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-double_test(Node, Timeout) ->
- In = 37768.93,
- {Ret, Out} = m_i:double_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-char_test(Node, Timeout) ->
- In = 80,
- {Ret, Out} = m_i:char_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-wchar_test(Node, Timeout) ->
- In = 4097,
- {Ret, Out} = m_i:wchar_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-octet_test(Node, Timeout) ->
- In = 255,
- {Ret, Out} = m_i:octet_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-bool_test(Node, Timeout) ->
- In = false,
- {Ret, Out} = m_i:bool_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-struct_test(Node, Timeout) ->
- In = #m_b{l = max_long(), c = $a},
- {Ret, Out} = m_i:struct_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-struct2_test(Node, Timeout) ->
- In = #m_es{ f = banana, l = max_long()},
- {Ret, Out} = m_i:struct2_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-seq1_test(Node, Timeout) ->
- B1 = #m_b{l = max_long(), c = $a},
- B2 = #m_b{l = min_long(), c = $b},
- In = [B1, B2],
- {Ret, Out} = m_i:seq1_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-seq2_test(Node, Timeout) ->
- B = #m_b{l = max_long(), c = $a},
- A = #m_a{l = min_long(), y = [B, B], d = 4711.31},
- In = [A, A, A],
- {Ret, Out} = m_i:seq2_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-seq3_test(Node, Timeout) ->
- In = [max_long(), min_long(), max_long()],
- {Ret, Out} = m_i:seq3_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-seq4_test(Node, Timeout) ->
- In = [["hello", "all"], ["Erlang", "users", "!"]],
- {Ret, Out} = m_i:seq4_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-seq5_test(Node, Timeout) ->
- Arr3 = mk_array(3, max_long()),
- In = [[Arr3, Arr3], [Arr3, Arr3, Arr3]],
- {Ret, Out} = m_i:seq5_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-array1_test(Node, Timeout) ->
- In = mk_array(500, min_long()),
- {Ret, Out} = m_i:array1_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-array2_test(Node, Timeout) ->
- In = mk_array(2, mk_array(3, min_long())),
- {Ret, Out} = m_i:array2_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-enum_test(Node, Timeout) ->
- In = banana,
- {Ret, Out} = m_i:enum_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-string1_test(Node, Timeout) ->
- In = "Developing Erlang applications is fun!",
- {Ret, Out} = m_i:string1_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-wstring1_test(Node, Timeout) ->
- In = [1047| "eveloping Erlang applications is fun!"],
- {Ret, Out} = m_i:wstring1_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-string2_test(Node, Timeout) ->
- In = ["Developing Erlang applications ", "is fun!"],
- {Ret, Out} = m_i:string2_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-string3_test(Node, Timeout) ->
- In = "Developing Erlang applications is fun!",
- {Ret, Out} = m_i:string3_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-string4_test(Node, Timeout) ->
-
- In = #m_strRec{
- bb = true,
- str4 = "Developing Erlang applications "
- "is fun!",
- str7 = mk_array(3, mk_array(2, max_long())),
- str5 = [$a, $b, $c, $d, $e, $f],
- str6 = "123456789012",
- str8 = {$x, $y, $x},
- str9 = "123456789012",
- str10 = [$a, $b, $c, $d, $e, $f]
- },
- {Ret, Out} = m_i:string4_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-pid_test(Node, Timeout) ->
- In = self(),
- {Ret, Out} = m_i:pid_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-port_test(Node, Timeout) ->
- In = get(port_test_port),
- {Ret, Out} = m_i:port_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-ref_test(Node, Timeout) ->
- In = make_ref(),
- {Ret, Out} = m_i:ref_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-term_test(Node, Timeout) ->
- In = {[a, b], 17, kalle},
- {Ret, Out} = m_i:term_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-typedef_test(Node, Timeout) ->
- In1 = {nisse, [1, 2], olsson},
- In2 = get(port_test_port),
- {Ret, Out1, Out2} = m_i:typedef_test({olsson, Node}, Timeout, In1, In2),
- %% XXX Should check that Ret is an integer.
- (Out1 == In1) and (Out2 == In2).
-%%e
-
-%%b
-inline_sequence_test(Node, Timeout) ->
- In = #m_s{l = min_long(), sl = [max_long(), min_long()]},
- {Ret, Out} = m_i:inline_sequence_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-term_sequence_test(Node, Timeout) ->
- In = lists:duplicate(17, {nisse, [1, 2], {kalle, olsson}}),
- {Ret, Out} = m_i:term_sequence_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-term_struct_test(Node, Timeout) ->
- In = #m_et{e = {nisse, ["abcde"], {kalle, olsson}}, l = 4711},
- {Ret, Out} = m_i:term_struct_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-
-%% Locals
-
-mk_array(Es) ->
- list_to_tuple(Es).
-
-mk_array(N, E) ->
- mk_array(lists:duplicate(N, E)).
-
-%% max_short() ->
-%% power_of_two(15) - 1.
-max_long() ->
- power_of_two(31) - 1.
-max_longlong() ->
- power_of_two(63) - 1.
-max_ushort() ->
- power_of_two(16) - 1.
-max_ulong() ->
- power_of_two(32) - 1.
-max_ulonglong() ->
- power_of_two(64) - 1.
-
-%% min_short() ->
-%% -power_of_two(15).
-min_long() ->
- -power_of_two(31).
-%% min_longlong() ->
-%% -power_of_two(63).
-%% min_ushort() ->
-%% 0.
-%% min_ulong() ->
-%% 0.
-%% min_ulonglong() ->
-%% 0.
-
-power_of_two(N) ->
- round(math:pow(2, N)).
-
diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE.erl b/lib/ic/test/erl_client_c_server_proto_SUITE.erl
deleted file mode 100644
index 99eeed01ad..0000000000
--- a/lib/ic/test/erl_client_c_server_proto_SUITE.erl
+++ /dev/null
@@ -1,298 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-%%----------------------------------------------------------------------
-%% Purpose : Test suite for erl-client/c-server
-%%----------------------------------------------------------------------
-
-
--module(erl_client_c_server_proto_SUITE).
--include_lib("common_test/include/ct.hrl").
-
--export([init_per_testcase/2, end_per_testcase/2,all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, void_test/1,
- long_test/1, longlong_test/1, ushort_test/1, ulong_test/1,
- ulonglong_test/1, double_test/1, char_test/1, wchar_test/1,
- octet_test/1, bool_test/1, struct_test/1, struct2_test/1,
- seq1_test/1, seq2_test/1, seq3_test/1, seq4_test/1,
- seq5_test/1, array1_test/1, array2_test/1, enum_test/1,
- string1_test/1, string2_test/1, string3_test/1,
- string4_test/1, pid_test/1, port_test/1, ref_test/1,
- term_test/1, typedef_test/1, inline_sequence_test/1,
- term_sequence_test/1, term_struct_test/1, wstring1_test/1]).
-
--define(DEFAULT_TIMEOUT, 20000).
--define(PORT_TIMEOUT, 15000).
--define(CALL_TIMEOUT, 5000).
-
--define(C_SERVER_NODE_NAME, idl_c_server_test).
-
-%% Add/remove code path and watchdog before/after each test case.
-%%
-init_per_testcase(_Case, Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- code:add_patha(DataDir),
-
- %% Since other test suites use the module m_i, we have
- %% to make sure we are using the right m_i module.
- code:purge(m_i),
- code:load_file(m_i),
-
- WatchDog = test_server:timetrap(?DEFAULT_TIMEOUT),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- code:del_path(DataDir),
- WatchDog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
-[void_test, long_test, longlong_test, ushort_test,
- ulong_test, ulonglong_test, double_test, char_test,
- wchar_test, octet_test, bool_test, struct_test,
- struct2_test, seq1_test, seq2_test, seq3_test,
- seq4_test, seq5_test, array1_test, array2_test,
- enum_test, string1_test, string2_test, string3_test,
- string4_test, pid_test, port_test, ref_test, term_test,
- typedef_test, inline_sequence_test, term_sequence_test,
- term_struct_test, wstring1_test].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-array1_test(Config) ->
- do_test(array1_test, Config).
-
-array2_test(Config) ->
- do_test(array2_test, Config).
-
-bool_test(Config) ->
- do_test(bool_test, Config).
-
-char_test(Config) ->
- do_test(char_test, Config).
-
-double_test(Config) ->
- do_test(double_test, Config).
-
-enum_test(Config) ->
- do_test(enum_test, Config).
-
-inline_sequence_test(Config) ->
- do_test(inline_sequence_test, Config).
-
-longlong_test(Config) ->
- do_test(longlong_test, Config).
-
-long_test(Config) ->
- do_test(long_test, Config).
-
-octet_test(Config) ->
- do_test(octet_test, Config).
-
-pid_test(Config) ->
- do_test(pid_test, Config).
-
-port_test(Config) ->
- do_test(port_test, Config).
-
-ref_test(Config) ->
- do_test(ref_test, Config).
-
-seq1_test(Config) ->
- do_test(seq1_test, Config).
-
-seq2_test(Config) ->
- do_test(seq2_test, Config).
-
-seq3_test(Config) ->
- do_test(seq3_test, Config).
-
-seq4_test(Config) ->
- do_test(seq4_test, Config).
-
-seq5_test(Config) ->
- do_test(seq5_test, Config).
-
-string1_test(Config) ->
- do_test(string1_test, Config).
-
-string2_test(Config) ->
- do_test(string2_test, Config).
-
-string3_test(Config) ->
- do_test(string3_test, Config).
-
-string4_test(Config) ->
- do_test(string4_test, Config).
-
-struct2_test(Config) ->
- do_test(struct2_test, Config).
-
-struct_test(Config) ->
- do_test(struct_test, Config).
-
-term_sequence_test(Config) ->
- do_test(term_sequence_test, Config).
-
-term_struct_test(Config) ->
- do_test(term_struct_test, Config).
-
-term_test(Config) ->
- do_test(term_test, Config).
-
-typedef_test(Config) ->
- do_test(typedef_test, Config).
-
-ulonglong_test(Config) ->
- do_test(ulonglong_test, Config).
-
-ulong_test(Config) ->
- do_test(ulong_test, Config).
-
-ushort_test(Config) ->
- do_test(ushort_test, Config).
-
-void_test(Config) ->
- do_test(void_test, Config).
-
-wchar_test(Config) ->
- do_test(wchar_test, Config).
-
-wstring1_test(Config) ->
- do_test(wstring1_test, Config).
-
-
-do_test(Case, Config) ->
- %% Trap exits
- process_flag(trap_exit, true),
- Node = atom_to_list(node()),
- [_NodeName, HostName] = string:tokens(Node, "@"),
- DataDir = proplists:get_value(data_dir, Config),
- %% io:format("~p: data directory: ~p~n", [?MODULE, DataDir]),
- Cookie = atom_to_list(erlang:get_cookie()),
- ServerNodeName = atom_to_list(?C_SERVER_NODE_NAME),
- %% Start C-server node as a port program. We wait for the node
- %% to connect to us.
- Cmd = filename:join([DataDir, "c_server"]) ++
- " -this-node-name " ++ ServerNodeName ++
- " -peer-node " ++ Node ++
- " -cookie " ++ Cookie,
- Port = open_port({spawn, Cmd}, [exit_status, eof, stderr_to_stdout]),
- ServerNode = list_to_atom(ServerNodeName ++ "@" ++ HostName),
- Res = case wait_for_hidden_node(ServerNode) of
- ok ->
- %% Need a port for port_test and typedef_test
- put(port_test_port, Port),
- R = (catch erl_client:Case(ServerNode, ?CALL_TIMEOUT)),
- case wait_for_completion(Port) of
- {error, timeout} ->
- kill_off_node(ServerNode);
- _ ->
- ok
- end,
- R;
- {error, timeout} ->
- case wait_for_completion(Port) of
- {error, timeout} ->
- kill_off_node(ServerNode);
- _ ->
- ok
- end,
- {error, timeout}
- end,
- process_flag(trap_exit, false),
- true = Res.
-
-
-%% Wait for eof *and* exit status, but return if exit status indicates
-%% an error, or we have been waiting more than PORT_TIMEOUT seconds.
-%%
-wait_for_completion(Port) ->
- wait_for_completion(Port, 0).
-
-wait_for_completion(Port, N) when N < 2 ->
- receive
- {Port, {data, Bytes}} ->
- %% Relay output
- io:format("~s", [Bytes]),
- wait_for_completion(Port, N);
- {Port, {exit_status, 0}} ->
- wait_for_completion(Port, N + 1);
- {Port, {exit_status, Status}} ->
- {error, Status};
- {Port, eof} ->
- wait_for_completion(Port, N + 1);
- {'EXIT', Port, Reason} ->
- io:format("Port exited with reason: ~w~n", [Reason]),
- wait_for_completion(Port, N);
- {'EXIT', From, Reason} ->
- io:format("Got unexpected exit: ~p~n", [{'EXIT', From, Reason}]),
- wait_for_completion(Port, N)
- after ?PORT_TIMEOUT ->
- {error, timeout}
- end;
-wait_for_completion(_, _) ->
- ok.
-
-wait_for_hidden_node(Node) ->
- Times = ?DEFAULT_TIMEOUT div 100,
- wait_for_hidden_node(Node, Times, 100).
-
-wait_for_hidden_node(Node, Times, WaitTime) when Times > 0 ->
- io:format("Waiting for hidden node: ~p~n", [Node]),
- case lists:member(Node, erlang:nodes(hidden)) of
- true ->
- ok;
- false ->
- delay(WaitTime),
- wait_for_hidden_node(Node, Times - 1, WaitTime)
- end;
-wait_for_hidden_node(_Node, _, _WaitTime) ->
- {error, timeout}.
-
-kill_off_node(Node) ->
- catch rpc:cast(Node, erlang, halt, [1]).
-
-delay(Time) ->
- receive
- after Time ->
- ok
- end.
-
-
-
-
diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/Makefile.src b/lib/ic/test/erl_client_c_server_proto_SUITE_data/Makefile.src
deleted file mode 100644
index 4ef7a74cde..0000000000
--- a/lib/ic/test/erl_client_c_server_proto_SUITE_data/Makefile.src
+++ /dev/null
@@ -1,160 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2004-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-# Makefile.src for erl_client_c_server test
-# Note: This file *must* work for both Unix and Windows
-#
-# We use both `rm' (Unix) and `del' (Windows) for removing files, but
-# with a `-' in front so that the error in not finding `rm' (`del') on
-# Windows (Unix) is ignored.
-#
-# VxWorks? XXX
-#
-
-.SUFFIXES:
-.SUFFIXES: .c .h .erl .idl @obj@ .@EMULATOR@
-
-
-# Variables from ts:
-#
-
-ERL_INCLUDE = @erl_include@
-
-IC_INCLUDE_PATH = @ic_include_path@
-IC_LIB = @ic_lib@
-
-ERL_INTERFACE_INCLUDE = @erl_interface_include@
-ERL_INTERFACE_LIB = @erl_interface_lib@
-ERL_INTERFACE_EILIB = @erl_interface_eilib@
-ERL_INTERFACE_THREADLIB = @erl_interface_threadlib@
-ERL_INTERFACE_SOCK_LIBS = @erl_interface_sock_libs@
-
-CC = @CC@
-## XXX Should set warning flag with a DEBUG_FLAG
-CFLAGS = @CFLAGS@ @DEFS@ -I$(ERL_INCLUDE) \
- -I$(IC_INCLUDE_PATH) -I$(ERL_INTERFACE_INCLUDE)
-
-LD = @LD@
-LDFLAGS = @CROSSLDFLAGS@
-LIBS = $(IC_LIB) $(ERL_INTERFACE_LIB) $(ERL_INTERFACE_EILIB) \
- $(ERL_INTERFACE_THREADLIB) @LIBS@ $(ERL_INTERFACE_SOCK_LIBS)
-ERLC = erlc
-
-# Generated C header files
-GEN_H_FILES = \
- m__s.h \
- m_i__s.h \
- oe_erl_c_test__s.h
-
-# Generated C files
-GEN_C_FILES = \
- m__s.c \
- m_i__s.c \
- oe_code_m_a.c \
- oe_code_m_arr1.c \
- oe_code_m_arr2.c \
- oe_code_m_arr3.c \
- oe_code_m_aseq.c \
- oe_code_m_b.c \
- oe_code_m_bseq.c \
- oe_code_m_dd.c \
- oe_code_m_dyn.c \
- oe_code_m_dyn_sl.c \
- oe_code_m_es.c \
- oe_code_m_et.c \
- oe_code_m_etseq.c \
- oe_code_m_fruit.c \
- oe_code_m_lseq.c \
- oe_code_m_s.c \
- oe_code_m_s_sl.c \
- oe_code_m_sarr3.c \
- oe_code_m_simple.c \
- oe_code_m_ssarr3.c \
- oe_code_m_sseq.c \
- oe_code_m_ssstr3.c \
- oe_code_m_sstr3.c \
- oe_code_m_str1.c \
- oe_code_m_str3.c \
- oe_code_m_strRec.c \
- oe_code_m_strRec_str5.c \
- oe_code_m_strRec_str7.c \
- oe_erl_c_test__s.c
-
-GEN_HRL_FILES = \
- m.hrl \
- m_i.hrl \
- oe_erl_c_test.hrl
-
-GEN_ERL_FILES = \
- m.erl \
- m_arr2.erl \
- m_arr3.erl \
- m_i.erl \
- m_str3.erl \
- oe_erl_c_test.erl
-
-C_FILES = $(GEN_C_FILES) c_server.c callbacks.c
-
-OBJS = $(C_FILES:.c=@obj@)
-
-PGMS = c_server@exe@
-
-ERL_FILES = $(GEN_ERL_FILES) erl_client.erl
-
-EBINS = $(ERL_FILES:.erl=.@EMULATOR@)
-
-
-all: $(PGMS) $(EBINS)
-
-$(GEN_ERL_FILES) $(GEN_HRL_FILES): c_erl_test.built_erl
-$(GEN_C_FILES) $(GEN_H_FILES): c_erl_test.built_c
-$(OBJS): $(GEN_C_FILES) $(GEN_H_FILES)
-$(EBINS): $(GEN_ERL_FILES) $(GEN_HRL_FILES)
-
-clean:
- -rm -f $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
- c_erl_test.built_erl c_erl_test.built_c
- -del /F /Q $(OBJS) $(GEN_C_FILES) $(GEN_H_FILES) $(PGMS) \
- $(EBINS) $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
- c_erl_test.built_erl c_erl_test.built_c
-
-$(PGMS): $(OBJS)
- $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
-
-c_erl_test.built_c: erl_c_test.idl
- $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,c_server}" \
- "+{scoped_op_calls,true}" erl_c_test.idl
- echo done > c_erl_test.built_c
-
-# If we have scoped operation calls for C, we must have that for
-# Erlang as well, if we use the m_i.erl file for calling the server.
-
-c_erl_test.built_erl: erl_c_test.idl
- $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" \
- "+{scoped_op_calls,true}" "+{timeout,true}" erl_c_test.idl
- echo done > c_erl_test.built_erl
-
-.c@obj@:
- $(CC) -c -o $*@obj@ $(CFLAGS) $<
-
-.erl.@EMULATOR@:
- $(ERLC) -W -I $(IC_INCLUDE_PATH) $<
-
diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/c_server.c b/lib/ic/test/erl_client_c_server_proto_SUITE_data/c_server.c
deleted file mode 100644
index e2ba5bd5b6..0000000000
--- a/lib/ic/test/erl_client_c_server_proto_SUITE_data/c_server.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2004-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/* C-server for test of IC.
- *
- * The C-node implemented here connects to its peer node, waits for
- * one message, evaluates the message, returns an result message, and
- * terminates.
- *
- * TODO:
- *
- * 1. XXX #includes for VxWorks, Windows
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifndef __WIN32__
-# include <unistd.h>
-#endif
-
-#include <string.h>
-
-#ifdef __WIN32__
-# include <time.h>
-# include <sys/timeb.h>
-#elif defined VXWORKS
-# include <time.h>
-# include <sys/times.h>
-#else
-# include <sys/time.h>
-#endif
-
-#include <ctype.h>
-
-#ifdef __WIN32__
-# include <winsock2.h>
-# include <windows.h>
-#else
-# include <sys/types.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <arpa/inet.h>
-# include <netdb.h>
-#endif
-
-#include "ic.h"
-#include "ei.h"
-#include "erl_interface.h"
-#include "eicode.h"
-#include "m_i__s.h"
-#include "m__s.h"
-
-#ifdef __WIN32__
-typedef struct {
- long tv_sec;
- long tv_usec;
-} MyTimeval;
-#else
-typedef struct timeval MyTimeval;
-#endif
-static void my_gettimeofday(MyTimeval *tv);
-static void showtime(MyTimeval *start, MyTimeval *stop);
-static void usage(void);
-static void done(int r);
-
-#define HOSTNAMESZ 255
-#define NODENAMESZ 512
-#define INBUFSZ 10
-#define OUTBUFSZ 0
-#define MAXTRIES 5
-
-static char *progname;
-
-/* main */
-#ifdef VXWORKS
-int c_server(int argc, char **argv)
-#else
-int main(int argc, char **argv)
-#endif
-{
- struct hostent *hp;
- MyTimeval start, stop;
- int i, fd, ires, tries;
- CORBA_Environment *env;
- char *this_node_name = NULL;
- char *peer_node = NULL;
- char *cookie = NULL;
- char host[HOSTNAMESZ + 1];
- char this_node[NODENAMESZ + 1];
- erlang_msg msg;
- int status, loop;
-
-#ifdef __WIN32__
- WORD wVersionRequested;
- WSADATA wsaData;
-
- wVersionRequested = MAKEWORD(2, 0);
-
- if (WSAStartup(wVersionRequested, &wsaData) != 0) {
- fprintf(stderr, "Could not load winsock2 v2.0 compatible DLL");
- exit(1);
- }
-#endif
-
- progname = argv[0];
- host[HOSTNAMESZ] = '\0';
- if (gethostname(host, HOSTNAMESZ + 1) < 0) {
- fprintf(stderr, "Can't find own hostname\n");
- done(1);
- }
- if ((hp = gethostbyname(host)) == 0) {
- fprintf(stderr, "Can't get ip address for host %s\n", host);
- done(1);
- }
- for (i = 1; i < argc; i++) {
- if (strcmp(argv[i], "-help") == 0) {
- usage();
- done(0);
- } else if (strcmp(argv[i], "-this-node-name") == 0) {
- i++;
- this_node_name = argv[i];
- } else if (strcmp(argv[i], "-peer-node") == 0) {
- i++;
- peer_node = argv[i];
- } else if (strcmp(argv[i], "-cookie") == 0) {
- i++;
- cookie = argv[i];
- } else {
- fprintf(stderr, "Error : invalid argument \"%s\"\n", argv[i]);
- usage();
- done(1);
- }
- }
-
- if (this_node_name == NULL || peer_node == NULL || cookie == NULL) {
- fprintf(stderr, "Error: missing option\n");
- usage();
- done(1);
- }
-
- /* Behead hostname at first dot */
- for (i=0; host[i] != '\0'; i++) {
- if (host[i] == '.') { host[i] = '\0'; break; }
- }
- sprintf(this_node, "%s@%s", this_node_name, host);
-
- fprintf(stderr, "c_server: this node: \"%s\"\n", this_node);
- fprintf(stderr, "c_server: peer node: \"%s\"\n", peer_node);
-
- /* initialize erl_interface */
- erl_init(NULL, 0);
-
- for (tries = 0; tries < MAXTRIES; tries++) {
- /* connect to peer node */
- ires = erl_connect_xinit(host, this_node_name, this_node,
- (struct in_addr *)*hp->h_addr_list,
- cookie, 0);
- fprintf(stderr, "c_server: erl_connect_xinit(): %d\n", ires);
-
- fd = erl_connect(peer_node);
- fprintf(stderr, "c_server: erl_connect(): %d\n", fd);
- if (fd >= 0)
- break;
- fprintf(stderr, "c_server: cannot connect, retrying\n");
- }
- if (fd < 0) {
- fprintf(stderr, "c_server: cannot connect, exiting\n");
- done(1);
- }
- env = CORBA_Environment_alloc(INBUFSZ, OUTBUFSZ);
- env->_fd = fd;
-
- status = 1;
- loop = 1;
- my_gettimeofday(&start);
- while (status >= 0 && loop > 0) {
- status = ei_receive_encoded(env->_fd, &env->_inbuf, &env->_inbufsz,
- &msg, &env->_iin);
- switch(status) {
- case ERL_SEND:
- case ERL_REG_SEND:
- /* get result */
- m_i__switch(NULL, env);
- switch(env->_major) {
- case CORBA_NO_EXCEPTION:
- break;
- case CORBA_SYSTEM_EXCEPTION:
- fprintf(stderr, "Request failure, reason : %s\n",
- (char *) CORBA_exception_value(env));
- CORBA_exception_free(env);
- break;
- default: /* Should not happen */
- CORBA_exception_free(env);
- break;
- }
- /* send back result data */
- if (env->_iout > 0)
- ei_send_encoded(env->_fd, &env->_caller, env->_outbuf,
- env->_iout);
- loop = 0;
- break;
- case ERL_TICK:
- break;
- default:
- if (status < 0) {
- fprintf(stderr, "Status negative: %d\n", status);
- loop = 0;
- }
- break;
- }
- }
- my_gettimeofday(&stop);
- showtime(&start, &stop);
-
- erl_close_connection(fd);
-
- CORBA_free(env->_inbuf);
- CORBA_free(env->_outbuf);
- CORBA_free(env);
- if (status < 0)
- done(-status);
- else
- done(0);
-}
-
-static void usage()
-{
- fprintf(stderr, "Usage: %s [-help] -this-node-name <name> "
- "-peer-node <nodename> -cookie <cookie>\n", progname);
- fprintf(stderr, "Example:\n %s -this-node-name kalle "
- "-peer-node olle@home -cookie oa678er\n", progname);
-}
-
-static void done(int r)
-{
-#ifdef __WIN32__
- WSACleanup();
-#endif
- exit(r);
-}
-
-static void showtime(MyTimeval *start, MyTimeval *stop)
-{
- MyTimeval elapsed;
-
- elapsed.tv_sec = stop->tv_sec - start->tv_sec;
- elapsed.tv_usec = stop->tv_usec - start->tv_usec;
- while (elapsed.tv_usec < 0) {
- elapsed.tv_sec -= 1;
- elapsed.tv_usec += 1000000;
- }
- fprintf(stderr,"%ld.%06ld seconds\n",elapsed.tv_sec, elapsed.tv_usec);
-}
-
-
-
-static void my_gettimeofday(MyTimeval *tv)
-#ifdef __WIN32__
-#define EPOCH_JULIAN_DIFF 11644473600i64
-{
- SYSTEMTIME t;
- FILETIME ft;
- LONGLONG lft;
-
- GetSystemTime(&t);
- SystemTimeToFileTime(&t, &ft);
- memcpy(&lft, &ft, sizeof(lft));
- tv->tv_usec = (long) ((lft / 10i64) % 1000000i64);
- tv->tv_sec = (long) ((lft / 10000000i64) - EPOCH_JULIAN_DIFF);
-}
-#elif defined VXWORKS
-{
- int rate = sysClkRateGet(); /* Ticks per second */
- unsigned long ctick = tickGet();
- tv->tv_sec = ctick / rate; /* secs since reboot */
- tv->tv_usec = ((ctick - (tv->tv_sec * rate))*1000000)/rate;
-}
-#else
-{
- gettimeofday(tv, NULL);
-}
-#endif
diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/callbacks.c b/lib/ic/test/erl_client_c_server_proto_SUITE_data/callbacks.c
deleted file mode 100644
index bed1dc2dd3..0000000000
--- a/lib/ic/test/erl_client_c_server_proto_SUITE_data/callbacks.c
+++ /dev/null
@@ -1,611 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2004-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#ifndef __WIN32__
-# include <unistd.h>
-#endif
-#include <string.h>
-#include <ctype.h>
-#include <ic.h>
-#include <erl_interface.h>
-#include <ei.h>
-#include "m_i__s.h"
-
-
-
-/* OK */
-
-void my_void_test(CORBA_Object oe_obj,
- CORBA_Environment *oe_env)
-{
- /* printf("void test !\n"); */
-}
-
-m_i_void_test__rs* m_i_void_test__cb(CORBA_Object oe_obj,
- CORBA_Environment *oe_env)
-{
- return (m_i_void_test__rs*) (my_void_test);
-}
-
-
-
-/* OK */
-
-void my_long_test(CORBA_Object oe_obj,
- long* a,
- long* b,
- long* c,
- CORBA_Environment *oe_env)
-{
- /* printf("long test !\n"); */
-}
-
-
-m_i_long_test__rs* m_i_long_test__cb(CORBA_Object oe_obj,
- long* a,
- long* b,
- long* c,
- CORBA_Environment *oe_env)
-{
- *a = *b;
- *c = *b;
- return (m_i_long_test__rs*) (my_long_test);
-}
-
-/* OK */
-
-void my_longlong_test(CORBA_Object oe_obj,
- CORBA_long_long* a,
- CORBA_long_long* b,
- CORBA_long_long* c,
- CORBA_Environment *oe_env)
-{
- /* printf("long test !\n"); */
-}
-
-m_i_longlong_test__rs* m_i_longlong_test__cb(CORBA_Object oe_obj,
- CORBA_long_long* a,
- CORBA_long_long* b,
- CORBA_long_long* c,
- CORBA_Environment *oe_env)
-{
- *a = *b;
- *c = *b;
- return (m_i_longlong_test__rs*) (my_longlong_test);
-}
-
-/* OK */
-void my_ulong_test(CORBA_Object oe_obj,
- unsigned long* a,
- unsigned long* b,
- unsigned long* c,
- CORBA_Environment *oe_env)
-{
- /* printf("ulong test !\n"); */
-}
-
-m_i_ulong_test__rs* m_i_ulong_test__cb(CORBA_Object oe_obj,
- unsigned long* a,
- unsigned long* b,
- unsigned long* c,
- CORBA_Environment *oe_env)
-{
- *a = *b;
- *c = *b;
- return (m_i_ulong_test__rs*) (my_ulong_test);
-}
-
-/* OK */
-void my_ulonglong_test(CORBA_Object oe_obj,
- CORBA_unsigned_long_long* a,
- CORBA_unsigned_long_long* b,
- CORBA_unsigned_long_long* c,
- CORBA_Environment *oe_env)
-{
- /* printf("ulong test !\n"); */
-}
-
-m_i_ulonglong_test__rs* m_i_ulonglong_test__cb(CORBA_Object oe_obj,
- CORBA_unsigned_long_long* a,
- CORBA_unsigned_long_long* b,
- CORBA_unsigned_long_long* c,
- CORBA_Environment *oe_env)
-{
- *a = *b;
- *c = *b;
- return (m_i_ulonglong_test__rs*) (my_ulonglong_test);
-}
-
-m_i_ushort_test__rs* m_i_ushort_test__cb(CORBA_Object oe_obj,
- unsigned short* a,
- unsigned short* b,
- unsigned short* c,
- CORBA_Environment *oe_env)
-{
- *a = *b;
- *c = *b;
- return (m_i_ushort_test__rs*) NULL;
-}
-
-
-/* OK */
-void my_double_test(CORBA_Object oe_obj,
- double* a,
- double* b,
- double* c,
- CORBA_Environment *oe_env)
-{
- /* printf("double test !\n"); */
-}
-
-m_i_double_test__rs* m_i_double_test__cb(CORBA_Object oe_obj,
- double* a,
- double* b,
- double* c,
- CORBA_Environment *oe_env)
-{
- *a = *b;
- *c = *b;
- return (m_i_double_test__rs*) (my_double_test);
-}
-
-/* OK */
-m_i_char_test__rs* m_i_char_test__cb(CORBA_Object oe_obj,
- char* a,
- char* b,
- char* c,
- CORBA_Environment *oe_env)
-{
- m_i_char_test__rs* rs = NULL;
-
- *a = *b;
- *c = *b;
- return rs;
-}
-
-
-/* OK */
-m_i_wchar_test__rs* m_i_wchar_test__cb(CORBA_Object oe_obj,
- CORBA_wchar* a,
- CORBA_wchar* b,
- CORBA_wchar* c,
- CORBA_Environment *oe_env)
-{
- m_i_wchar_test__rs* rs = NULL;
-
- *a = *b;
- *c = *b;
- return rs;
-}
-
-/* OK */
-m_i_octet_test__rs* m_i_octet_test__cb(CORBA_Object oe_obj,
- char* a,
- char* b,
- char* c,
- CORBA_Environment *oe_env)
-{
- m_i_octet_test__rs* rs = NULL;
-
- *a = *b;
- *c = *b;
- return rs;
-}
-
-/* OK */
-m_i_bool_test__rs* m_i_bool_test__cb(CORBA_Object oe_obj,
- CORBA_boolean* a,
- CORBA_boolean* b,
- CORBA_boolean* c,
- CORBA_Environment *oe_env)
-{
- m_i_bool_test__rs* rs = NULL;
-
- *a = *b;
- *c = *b;
- return rs;
-}
-
-/* OK */
-void my_struct_test(CORBA_Object oe_obj,
- m_b* a,
- m_b* b,
- m_b* c,
- CORBA_Environment *oe_env)
-{
- /* printf("struct test !\n"); */
-}
-
-m_i_struct_test__rs* m_i_struct_test__cb(CORBA_Object oe_obj,
- m_b* a,
- m_b* b,
- m_b* c,
- CORBA_Environment *oe_env)
-{
- *a = *b;
- *c = *b;
- return (m_i_struct_test__rs*) (my_struct_test);
-}
-
-/* OK */
-m_i_struct2_test__rs* m_i_struct2_test__cb(CORBA_Object oe_obj,
- m_es* a,
- m_es* b,
- m_es* c,
- CORBA_Environment *oe_env)
-{
- m_i_struct2_test__rs* rs = NULL;
-
- *a = *b;
- *c = *b;
- return rs;
-}
-
-/* OK */
-/* XXX Commented out
-m_i_struct3_test__rs* m_i_struct3_test__cb(CORBA_Object oe_obj,
- m_simple* a,
- m_simple* b,
- m_simple* c,
- CORBA_Environment *oe_env)
-{
- m_i_struct3_test__rs* rs = NULL;
- *a = *b;
- *c = *b;
- return rs;
-}
-*/
-
-/* OK */
-m_i_seq1_test__rs* m_i_seq1_test__cb(CORBA_Object oe_obj,
- m_bseq** a,
- m_bseq* b,
- m_bseq** c,
- CORBA_Environment *oe_env)
-{
- m_i_seq1_test__rs* rs = NULL;
-
- *a = b;
- *c = b;
- return rs;
-}
-
-
-/* OK */
-m_i_seq2_test__rs* m_i_seq2_test__cb(CORBA_Object oe_obj,
- m_aseq** a,
- m_aseq* b,
- m_aseq** c,
- CORBA_Environment *oe_env)
-{
- m_i_seq2_test__rs* rs = NULL;
-
- *a = b;
- *c = b;
- return rs;
-}
-
-/* OK */
-m_i_seq3_test__rs* m_i_seq3_test__cb(CORBA_Object oe_obj,
- m_lseq** a,
- m_lseq* b,
- m_lseq** c,
- CORBA_Environment *oe_env)
-{
- m_i_seq3_test__rs* rs = NULL;
-
- *a = b;
- *c = b;
- return rs;
-}
-
-/* OK */
-m_i_seq4_test__rs* m_i_seq4_test__cb(CORBA_Object oe_obj,
- m_ssstr3** a,
- m_ssstr3* b,
- m_ssstr3** c,
- CORBA_Environment *oe_env)
-{
- m_i_seq4_test__rs* rs = NULL;
-
- *a = b;
- *c = b;
- return rs;
-}
-
-/* OK */
-m_i_seq5_test__rs* m_i_seq5_test__cb(CORBA_Object oe_obj,
- m_ssarr3** a,
- m_ssarr3* b,
- m_ssarr3** c,
- CORBA_Environment *oe_env)
-{
- m_i_seq5_test__rs* rs = NULL;
-
- *a = b;
- *c = b;
- return rs;
-}
-
-/* OK */
-m_i_array1_test__rs* m_i_array1_test__cb(CORBA_Object oe_obj,
- m_arr1 a,
- m_arr1 b,
- m_arr1 c,
- CORBA_Environment *oe_env)
-{
- int i;
- m_i_array1_test__rs* rs = NULL;
-
- for (i = 0; i < 500; i++) {
- a[i] = b[i];
- c[i] = b[i];
- }
- return rs;
-}
-
-/* OK */
-m_i_array2_test__rs* m_i_array2_test__cb(CORBA_Object oe_obj,
- m_dd a,
- m_dd b,
- m_dd c,
- CORBA_Environment *oe_env)
-{
- int i,j;
- m_i_array2_test__rs* rs = NULL;
-
- for (i = 0; i < 2; i++)
- for (j = 0; j < 3; j++) {
- a[i][j] = b[i][j];
- c[i][j] = b[i][j];
- }
- return rs;
-}
-
-
-/* OK */
-m_i_enum_test__rs* m_i_enum_test__cb(CORBA_Object oe_obj,
- m_fruit* a,
- m_fruit* b,
- m_fruit* c,
- CORBA_Environment *oe_env)
-{
- m_i_enum_test__rs* rs = NULL;
-
- *a = *b;
- *c = *b;
- return rs;
-}
-
-/* OK */
-m_i_string1_test__rs* m_i_string1_test__cb(CORBA_Object oe_obj,
- char ** a,
- char * b,
- char ** c,
- CORBA_Environment *oe_env)
-{
- m_i_string1_test__rs* rs = NULL;
-
- /*printf("\nString in ------> %s\n\n",b);*/
- *a = b;
- *c = b;
- return rs;
-}
-
-/* OK */
-m_i_string2_test__rs* m_i_string2_test__cb(CORBA_Object oe_obj,
- m_sseq** a,
- m_sseq* b,
- m_sseq** c,
- CORBA_Environment *oe_env)
-{
- m_i_string2_test__rs* rs = NULL;
-
- *a = b;
- *c = b;
- return rs;
-}
-
-/* OK */
-m_i_string3_test__rs* m_i_string3_test__cb(CORBA_Object oe_obj,
- char ** a,
- char * b,
- char ** c,
- CORBA_Environment *oe_env)
-{
- m_i_string3_test__rs* rs = NULL;
-
- *a = b;
- *c = b;
- return rs;
-}
-
-m_i_string4_test__rs* m_i_string4_test__cb(CORBA_Object oe_obj,
- m_strRec** a,
- m_strRec* b,
- m_strRec** c,
- CORBA_Environment *oe_env)
-{
- *a = b;
- *c = b;
-
- return (m_i_string4_test__rs*) NULL;
-}
-
-/* OK */
-m_i_wstring1_test__rs* m_i_wstring1_test__cb(CORBA_Object oe_obj,
- CORBA_wchar ** a,
- CORBA_wchar * b,
- CORBA_wchar ** c,
- CORBA_Environment *oe_env)
-{
- int tmp;
- m_i_wstring1_test__rs* rs = NULL;
-
- /*printf("\nString in ------> %s\n\n",b);*/
-
- for(tmp = 0; tmp < 5; tmp++)
- fprintf(stderr,"\np[%d] = %ld\n", tmp, b[tmp]);
- *a = b;
- *c = b;
- return rs;
-}
-
-
-/* OK */
-m_i_pid_test__rs* m_i_pid_test__cb(CORBA_Object oe_obj,
- erlang_pid* a,
- erlang_pid* b,
- erlang_pid* c,
- CORBA_Environment *oe_env)
-{
- m_i_pid_test__rs* rs = NULL;
-
- *a = *b;
- *c = *b;
- return rs;
-}
-
-/* OK */
-m_i_port_test__rs* m_i_port_test__cb(CORBA_Object oe_obj,
- erlang_port* a,
- erlang_port* b,
- erlang_port* c,
- CORBA_Environment *oe_env)
-{
- m_i_port_test__rs* rs = NULL;
-
- strcpy((*a).node,(*b).node);
- (*a).id = (*b).id;
- (*a).creation = 0;
-
- strcpy((*c).node,(*b).node);
- (*c).id = (*b).id;
- (*c).creation = 0;
- return rs;
-}
-
-/* OK */
-m_i_ref_test__rs* m_i_ref_test__cb(CORBA_Object oe_obj,
- erlang_ref* a,
- erlang_ref* b,
- erlang_ref* c,
- CORBA_Environment *oe_env)
-{
-
- m_i_ref_test__rs* rs = NULL;
-
- strcpy((*a).node,(*b).node);
- /*(*a).id = (*b).id;*/
- (*a).len = (*b).len;
- (*a).n[0] = (*b).n[0];
- (*a).n[1] = (*b).n[1];
- (*a).n[2] = (*b).n[2];
- (*a).creation = 0;
-
- strcpy((*c).node,(*b).node);
- /*(*c).id = (*b).id;*/
- (*c).len = (*b).len;
- (*c).n[0] = (*b).n[0];
- (*c).n[1] = (*b).n[1];
- (*c).n[2] = (*b).n[2];
- (*c).creation = 0;
- return rs;
-}
-
-/* OK */
-m_i_term_test__rs* m_i_term_test__cb(CORBA_Object oe_obj,
- ETERM** a,
- ETERM** b,
- ETERM** c,
- CORBA_Environment *oe_env)
-{
- m_i_term_test__rs* rs = NULL;
-
- *a = *b;
- *c = *b;
- return rs;
-}
-
-m_i_typedef_test__rs* m_i_typedef_test__cb(CORBA_Object oe_obj,
- long* a,
- ETERM** b,
- erlang_port* c,
- ETERM** d ,
- erlang_port* e,
- CORBA_Environment *oe_env)
-{
- m_i_typedef_test__rs* rs = NULL;
-
- *d = *b;
- strcpy((*e).node,(*c).node);
- (*e).id = (*c).id;
- (*e).creation = 0;
- *a = 4711;
- return rs;
-}
-
-/* OK */
-m_i_inline_sequence_test__rs* m_i_inline_sequence_test__cb(
- CORBA_Object oe_obj,
- m_s** a,
- m_s* b,
- m_s** c,
- CORBA_Environment *oe_env)
-{
- m_i_inline_sequence_test__rs* rs = NULL;
-
- *a = b;
- *c = b;
- return rs;
-}
-
-/* OK */
-m_i_term_sequence_test__rs* m_i_term_sequence_test__cb(
- CORBA_Object oe_obj,
- m_etseq** a,
- m_etseq* b,
- m_etseq** c,
- CORBA_Environment *oe_env)
-{
- m_i_term_sequence_test__rs* rs = NULL;
-
- *a = b;
- *c = b;
- return rs;
-}
-
-
-/* OK */
-m_i_term_struct_test__rs* m_i_term_struct_test__cb(CORBA_Object oe_obj,
- m_et* a,
- m_et* b,
- m_et* c,
- CORBA_Environment *oe_env)
-{
- m_i_term_struct_test__rs* rs = NULL;
-
- *a = *b;
- *c = *b;
- return rs;
-}
-
diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_c_test.idl b/lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_c_test.idl
deleted file mode 100644
index ef9556dd42..0000000000
--- a/lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_c_test.idl
+++ /dev/null
@@ -1,175 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 2004-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-#include "erlang.idl"
-
-
-const short TestConst = 1;
-
-module m {
-
- const short TestConst = 2;
-
- struct b {
- long l;
- char c;
- };
-
- struct simple {
- long l;
- b b_t;
- };
-
- enum fruit {orange, banana, apple, peach, pear};
-
- typedef sequence<long> lseq;
-
- typedef sequence<b> bseq;
-
- struct a {
- long l;
- bseq y;
- double d;
- };
-
- typedef sequence<a> aseq;
-
- typedef sequence<string> sseq;
- typedef string str;
- typedef long myLong;
-
- typedef long arr1[500], dd[2][3];
-
- typedef erlang::term apa;
- typedef erlang::port banan;
-
- typedef sequence<erlang::term> etseq;
-
- struct s {
- long l;
- sequence<long> sl;
- };
-
- struct es {
- fruit f;
- myLong l;
- };
-
- struct et {
- erlang::term e;
- long l;
- };
-
-
- typedef sequence<char> str1;
- typedef string<12> str2;
- typedef char str3[3];
-
- typedef sequence<string> sstr3; // sequence of string
- typedef sequence<sstr3> ssstr3; // sequence of sequences of strings
-
- typedef long arr3[3]; // array of long
- typedef sequence<arr3> sarr3; // sequence of array
- typedef sequence<sarr3> ssarr3; // sequence of sequnces of arrays of strings
-
- struct strRec{
- boolean bb;
- string str4;
- long str7[3][2];
- sequence<char> str5;
- string<12> str6;
- str3 str8;
- str2 str9;
- str1 str10;
- };
-
-
- struct dyn {
- long l;
- sequence<long> sl;
- };
- typedef dyn arr2[1][2];
-
-
- interface i {
-
- const short TestConst = 3;
-
- //arr2 suck(in arr2 x, out arr2 y );
-
- ///////////////////////////////// attribute long l;
-
- // simple types
- void void_test();
- long long_test(in long a, out long a1);
- long long longlong_test(in long long a, out long long a1);
- unsigned short ushort_test(in unsigned short a, out unsigned short a1);
- unsigned long ulong_test(in unsigned long a, out unsigned long a1);
- unsigned long long ulonglong_test(in unsigned long long a, out unsigned long long a1);
- double double_test(in double a, out double a1);
- char char_test(in char a, out char a1);
- wchar wchar_test(in wchar a, out wchar a1);
- octet octet_test(in octet a, out octet a1);
- boolean bool_test(in boolean a, out boolean a1);
-
- // Seq. and struct tests
- b struct_test(in b a, out b a1);
- es struct2_test(in es a, out es a1);
- //simple struct3_test(in simple x, out simple y);
- bseq seq1_test(in bseq a, out bseq a1);
- aseq seq2_test(in aseq a, out aseq a1);
- lseq seq3_test(in lseq a, out lseq a1);
- ssstr3 seq4_test(in ssstr3 a, out ssstr3 a1);
- ssarr3 seq5_test(in ssarr3 a, out ssarr3 a1);
-
- // Array tests
- arr1 array1_test(in arr1 a, out arr1 a1);
- dd array2_test(in dd a, out dd a1);
-
- // enum test
- fruit enum_test(in fruit a, out fruit a1);
-
- // string tests
- string string1_test(in string a, out string a1);
- wstring wstring1_test(in wstring a, out wstring a1);
- sseq string2_test(in sseq a, out sseq a1);
- str string3_test(in str a, out str a1);
- strRec string4_test(in strRec a, out strRec a1);
-
- // Special erlang types
- erlang::pid pid_test(in erlang::pid a, out erlang::pid a1);
- erlang::port port_test(in erlang::port a, out erlang::port a1);
- erlang::ref ref_test(in erlang::ref a, out erlang::ref a1);
- erlang::term term_test(in erlang::term a, out erlang::term a1);
-
- // typedef test
- long typedef_test(in apa a, in banan b, out apa a1, out banan b1);
-
- // inlined seq. test
- s inline_sequence_test(in s a, out s a1);
-
- // term seq. test
- etseq term_sequence_test(in etseq a, out etseq a1);
- // term struct test
- et term_struct_test(in et a, out et a1);
-
- };
-
-};
diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_client.erl b/lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_client.erl
deleted file mode 100644
index 5fe80cdd7a..0000000000
--- a/lib/ic/test/erl_client_c_server_proto_SUITE_data/erl_client.erl
+++ /dev/null
@@ -1,332 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(erl_client).
-
--export([void_test/2, long_test/2, longlong_test/2, ushort_test/2,
- ulong_test/2, ulonglong_test/2, double_test/2, char_test/2,
- wchar_test/2, octet_test/2, bool_test/2, struct_test/2,
- struct2_test/2, seq1_test/2, seq2_test/2, seq3_test/2,
- seq4_test/2, seq5_test/2, array1_test/2, array2_test/2,
- enum_test/2, string1_test/2, wstring1_test/2, string2_test/2,
- string3_test/2, string4_test/2, pid_test/2, port_test/2,
- ref_test/2, term_test/2, typedef_test/2,
- inline_sequence_test/2, term_sequence_test/2,
- term_struct_test/2
-
-]).
-
--include("m.hrl").
--include("m_i.hrl").
--include("oe_erl_c_test.hrl").
-
-%%b
-void_test(Node, Timeout) ->
- Ret = m_i:void_test({olsson, Node}, Timeout),
- Ret == void. % XXX Not documented
-%%e
-
-%%b
-long_test(Node, Timeout) ->
- In = max_long(),
- {Ret, Out} = m_i:long_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-longlong_test(Node, Timeout) ->
- In = 65537,
- {Ret, Out} = m_i:longlong_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-ushort_test(Node, Timeout) ->
- In = max_ushort(),
- {Ret, Out} = m_i:ushort_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-ulong_test(Node, Timeout) ->
- In = max_ulong(),
- {Ret, Out} = m_i:ulong_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-ulonglong_test(Node, Timeout) ->
- In = 65537,
- {Ret, Out} = m_i:ulonglong_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-double_test(Node, Timeout) ->
- In = 37768.93,
- {Ret, Out} = m_i:double_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-char_test(Node, Timeout) ->
- In = 80,
- {Ret, Out} = m_i:char_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-wchar_test(Node, Timeout) ->
- In = 4097,
- {Ret, Out} = m_i:wchar_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-octet_test(Node, Timeout) ->
- In = 255,
- {Ret, Out} = m_i:octet_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-bool_test(Node, Timeout) ->
- In = false,
- {Ret, Out} = m_i:bool_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-struct_test(Node, Timeout) ->
- In = #m_b{l = max_long(), c = $a},
- {Ret, Out} = m_i:struct_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-struct2_test(Node, Timeout) ->
- In = #m_es{ f = banana, l = max_long()},
- {Ret, Out} = m_i:struct2_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-seq1_test(Node, Timeout) ->
- B1 = #m_b{l = max_long(), c = $a},
- B2 = #m_b{l = min_long(), c = $b},
- In = [B1, B2],
- {Ret, Out} = m_i:seq1_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-seq2_test(Node, Timeout) ->
- B = #m_b{l = max_long(), c = $a},
- A = #m_a{l = min_long(), y = [B, B], d = 4711.31},
- In = [A, A, A],
- {Ret, Out} = m_i:seq2_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-seq3_test(Node, Timeout) ->
- In = [max_long(), min_long(), max_long()],
- {Ret, Out} = m_i:seq3_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-seq4_test(Node, Timeout) ->
- In = [["hej", "hopp"], ["ditt", "feta", "nylle"]],
- {Ret, Out} = m_i:seq4_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-seq5_test(Node, Timeout) ->
- Arr3 = mk_array(3, max_long()),
- In = [[Arr3, Arr3], [Arr3, Arr3, Arr3]],
- {Ret, Out} = m_i:seq5_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-array1_test(Node, Timeout) ->
- In = mk_array(500, min_long()),
- {Ret, Out} = m_i:array1_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-array2_test(Node, Timeout) ->
- In = mk_array(2, mk_array(3, min_long())),
- {Ret, Out} = m_i:array2_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-enum_test(Node, Timeout) ->
- In = banana,
- {Ret, Out} = m_i:enum_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-string1_test(Node, Timeout) ->
- In = "Die Paula muss beim Tango immer weinen",
- {Ret, Out} = m_i:string1_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-wstring1_test(Node, Timeout) ->
- In = [1047| "ie Paula muss beim Tango immer weinen"],
- {Ret, Out} = m_i:wstring1_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-string2_test(Node, Timeout) ->
- In = ["Lass doch die Blumen,", "Konrad!"],
- {Ret, Out} = m_i:string2_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-string3_test(Node, Timeout) ->
- In = "Seeman, lass uns freuden!",
- {Ret, Out} = m_i:string3_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-string4_test(Node, Timeout) ->
-
- In = #m_strRec{
- bb = true,
- str4 = "Paula war zu Hause in ihrem Stadtchen als die beste Tanzerin"
- "bekannt",
- str7 = mk_array(3, mk_array(2, max_long())),
- str5 = [$a, $b, $c, $d, $e, $f],
- str6 = "123456789012",
- str8 = {$x, $y, $x},
- str9 = "123456789012",
- str10 = [$a, $b, $c, $d, $e, $f]
- },
- {Ret, Out} = m_i:string4_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-pid_test(Node, Timeout) ->
- In = self(),
- {Ret, Out} = m_i:pid_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-port_test(Node, Timeout) ->
- In = get(port_test_port),
- {Ret, Out} = m_i:port_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-ref_test(Node, Timeout) ->
- In = make_ref(),
- {Ret, Out} = m_i:ref_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-term_test(Node, Timeout) ->
- In = {[a, b], 17, kalle},
- {Ret, Out} = m_i:term_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-typedef_test(Node, Timeout) ->
- In1 = {nisse, [1, 2], olsson},
- In2 = get(port_test_port),
- {Ret, Out1, Out2} = m_i:typedef_test({olsson, Node}, Timeout, In1, In2),
- %% XXX Should check that Ret is an integer.
- (Out1 == In1) and (Out2 == In2).
-%%e
-
-%%b
-inline_sequence_test(Node, Timeout) ->
- In = #m_s{l = min_long(), sl = [max_long(), min_long()]},
- {Ret, Out} = m_i:inline_sequence_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-term_sequence_test(Node, Timeout) ->
- In = lists:duplicate(17, {nisse, [1, 2], {kalle, olsson}}),
- {Ret, Out} = m_i:term_sequence_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-%%b
-term_struct_test(Node, Timeout) ->
- In = #m_et{e = {nisse, ["abcde"], {kalle, olsson}}, l = 4711},
- {Ret, Out} = m_i:term_struct_test({olsson, Node}, Timeout, In),
- (Ret == In) and (Out == In).
-%%e
-
-
-%% Locals
-
-mk_array(Es) ->
- list_to_tuple(Es).
-
-mk_array(N, E) ->
- mk_array(lists:duplicate(N, E)).
-
-%% max_short() ->
-%% power_of_two(15) - 1.
-max_long() ->
- power_of_two(31) - 1.
-max_longlong() ->
- power_of_two(63) - 1.
-max_ushort() ->
- power_of_two(16) - 1.
-max_ulong() ->
- power_of_two(32) - 1.
-max_ulonglong() ->
- power_of_two(64) - 1.
-
-%% min_short() ->
-%% -power_of_two(15).
-min_long() ->
- -power_of_two(31).
-%% min_longlong() ->
-%% -power_of_two(63).
-%% min_ushort() ->
-%% 0.
-%% min_ulong() ->
-%% 0.
-%% min_ulonglong() ->
-%% 0.
-
-power_of_two(N) ->
- round(math:pow(2, N)).
-
diff --git a/lib/ic/test/erl_client_c_server_proto_SUITE_data/my.c b/lib/ic/test/erl_client_c_server_proto_SUITE_data/my.c
deleted file mode 100644
index aff03253d6..0000000000
--- a/lib/ic/test/erl_client_c_server_proto_SUITE_data/my.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2004-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-#include "ic.h"
-#include "m_i.h"
-
-int my_prepare_request_decoding(CORBA_Environment *env)
-{
- return oe_prepare_request_decoding(env);
-}
-
-int my_prepare_reply_encoding(CORBA_Environment *env)
-{
- return oe_prepare_reply_encoding(env);
-}
-
-
-
diff --git a/lib/ic/test/ic.cover b/lib/ic/test/ic.cover
deleted file mode 100644
index 5a679c8b6f..0000000000
--- a/lib/ic/test/ic.cover
+++ /dev/null
@@ -1,2 +0,0 @@
-{incl_app,ic,details}.
-
diff --git a/lib/ic/test/ic.spec b/lib/ic/test/ic.spec
deleted file mode 100644
index 22905dcee4..0000000000
--- a/lib/ic/test/ic.spec
+++ /dev/null
@@ -1 +0,0 @@
-{suites,"../ic_test",all}.
diff --git a/lib/ic/test/ic.spec.vxworks b/lib/ic/test/ic.spec.vxworks
deleted file mode 100644
index b15260ab70..0000000000
--- a/lib/ic/test/ic.spec.vxworks
+++ /dev/null
@@ -1,2 +0,0 @@
-{topcase, {dir, "../ic_test"}}.
-{skip,{ic_pp_SUITE,"Uses gcc"}}.
diff --git a/lib/ic/test/ic_SUITE.erl b/lib/ic/test/ic_SUITE.erl
deleted file mode 100644
index 42c1dbb415..0000000000
--- a/lib/ic/test/ic_SUITE.erl
+++ /dev/null
@@ -1,894 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%%----------------------------------------------------------------------
-%%% Purpose : Test suite for the IDL compiler
-%%%----------------------------------------------------------------------
-
--module(ic_SUITE).
--include_lib("common_test/include/ct.hrl").
-
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
-
--include_lib("orber/src/orber_ifr.hrl").
--include_lib("orber/src/ifr_objects.hrl").
--include_lib("orber/include/ifr_types.hrl").
-
-
-%% The type cases
--export([ type_norm/1]).
-
-%% The syntax case
--export([]).
--export([syntax1/1, syntax2/1, syntax3/1, syntax4/1, syntax5/1, syntax6/1]).
-
-%% The constant cases
--export([]).
--export([const_norm/1, const_bad_tk/1, const_bad_type/1]).
--export([const_bad_comb/1]).
-
-%% The union cases
--export([]).
--export([union_norm/1, union_type/1, union_mult_err/1, union_case_mult/1]).
--export([union_default/1]).
-
-%% The enum cases
--export([]).
--export([enum_norm/1]).
-
-%% The struct cases
--export([]).
--export([struct_norm/1]).
-
-%% The oneway cases
--export([]).
--export([oneway_norm/1, oneway_raises/1, oneway_out/1, oneway_void/1, oneway_followed/1]).
-
-%% The attributes cases
--export([]).
--export([attr_norm/1]).
-
-%% The raises registration case
--export([raises_reg/1]).
-
-
-%% The typeID case
-
-%% general stuff
--export([]).
--export([typeid/1, undef_id/1, dir/1, nasty_names/1, coss/1, mult_ids/1]).
--export([forward/1, include/1, app_test/1]).
-
-%% inheritance stuff
--export([ inherit_norm/1, inherit_warn/1, inherit_err/1]).
-
-%% Standard options to the ic compiler, NOTE unholy use of OutDir
-
--define(OUT(X), filename:join([proplists:get_value(priv_dir, Config), gen, to_list(X)])).
-
-
-%% Top of cases
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [app_test, {group, const}, {group, union},
- {group, enum}, {group, attr}, {group, type},
- {group, struct}, {group, general}, {group, inherit},
- {group, oneway}, {group, syntax}, raises_reg].
-
-groups() ->
- [{const, [],
- [const_norm, const_bad_tk, const_bad_type,
- const_bad_comb]},
- {union, [],
- [union_norm, union_type, union_mult_err,
- union_case_mult, union_default]},
- {enum, [], [enum_norm]}, {struct, [], [struct_norm]},
- {general, [],
- [typeid, undef_id, mult_ids, forward, include,
- nasty_names]},
- {inherit, [],
- [inherit_norm, inherit_warn, inherit_err]},
- {oneway, [],
- [oneway_norm, oneway_out, oneway_raises, oneway_void,
- oneway_followed]},
- {attr, [], [attr_norm]}, {type, [], [type_norm]},
- {syntax, [],
- [syntax1, syntax2, syntax3, syntax4, syntax5, syntax6]}].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-app_test(_Config) ->
- ok=test_server:app_test(ic),
- ok.
-
-%%---------------------------------------------------------------------
-%%
-%% Test of constant expressions.
-%%
-
-%% Checks normal constant types and values
-const_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(const_norm),
- File = filename:join(DataDir, c_norm),
- ok = ic:gen(File, stdopts(OutDir)),
- {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
- ok = compile(OutDir, const_norm_files()),
- ok.
-
-%% Checks when the constant value doesn't match the declared type
-const_bad_tk(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, c_err1),
- error = ic:gen(File, stdopts(OutDir)),
- {error, [], R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(18, bad_tk_match, R),
- ok.
-
-%% Checks operands of ops are of correct type
-const_bad_type(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, c_err2),
- error = ic:gen(File, stdopts(OutDir)),
- {error, [], R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(4, bad_type, R),
- ok.
-
-%% Checks operands of ops are of conflicting types
-const_bad_comb(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, c_err3),
- error = ic:gen(File, stdopts(OutDir)),
- {error, [], R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(3, bad_type_combination, R),
- ok.
-
-
-%% Checks that normal union declarations works.
-union_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(union_norm),
- File = filename:join(DataDir, u_norm),
-
- ok = ic:gen(File, stdopts(OutDir)),
- {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
- ok = compile(OutDir, union_norm_files()),
- ok.
-
-
-%% Checks OTP-2007
-%% Checks that default cases are correct in type code.
-union_default(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(union_default),
- File = filename:join(DataDir, u_default),
-
- ok = ic:gen(File, stdopts(OutDir)),
- {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
- ok = compile(OutDir, union_default_files(), [load]),
- TkList = i1:oe_get_interface(),
- check_label("op0", 0, TkList),
- check_label("op1", 1, TkList),
- check_label("op2", 2, TkList),
- check_label("op3", -1, TkList),
- ok.
-
-check_label(Id, N, List) ->
- case lists:keysearch(Id, 1, List) of
- {value, {_, {{_, _, _, _, D, L}, _, _}}} ->
- if D /= N ->
- test_server:fail({bad_default_num, D, N});
- D /= -1 ->
- case lists:nth(D+1, L) of
- T when element(1, T) == default ->
- ok;
- _Que ->
- test_server:fail({bad_default_list, D, L})
- end;
- true ->
- %% D = N = -1, just check that there is no default label
- case lists:keysearch(default, 1, L) of
- false ->
- ok;
- _ ->
- test_server:fail({bad_default_label, D, L})
- end
- end;
- _ ->
- test_server:fail({'no_such_op!', Id, List})
- end.
-
-%% Checks that errors are detected. Check that mismatch between case
-%% value and declared discriminator type is detected.
-union_type(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, u_type),
- error = ic:gen(File, stdopts(OutDir)),
- {error, [], R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(28, bad_case_type, R),
- ok.
-
-
-%% Check that multiple declared declarators are caught.
-%% Also check that if the discriminator is an enum, then the enum name
-%% must not be used as a declarator in the union switch (declarator
-%% as opposed to label).
-union_mult_err(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, u_mult),
- error = ic:gen(File, stdopts(OutDir)),
- {error, [], R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(8, multiply_defined, R),
- ok.
-
-%% Check that multiply defined case labels are found in the
-%% correct order
-union_case_mult(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, u_case_mult),
- error = ic:gen(File, stdopts(OutDir)),
- {error, [], R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(7, multiple_cases, R),
- ok.
-
-
-%%--------------------------------------------------------------------
-%%
-%% Enum cases
-%%
-%%Checks that normal enum declarations works.
-enum_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(enum_norm),
- File = filename:join(DataDir, enum),
-
- ok = ic:gen(File, stdopts(OutDir)),
- {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
- ok = compile(OutDir, enum_norm_files()),
- ok.
-
-
-%%--------------------------------------------------------------------
-%%
-%% Struct cases
-%%
-%% Checks that normal struct declarations works.
-struct_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(struct_norm),
- File = filename:join(DataDir, struct),
-
- ok = ic:gen(File, stdopts(OutDir)),
- {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
- ok = compile(OutDir, struct_norm_files()),
- Mod = ridiculous_name_to_avoid_clash_svenne,
- TestFile = filename:join(OutDir, Mod),
- ok = gen_struct_file(TestFile, Mod),
- ok = compile(OutDir, [Mod], [load]),
-%% {ok, Mod, []} = compile:file(TestFile,
-%% [{i, OutDir}, {outdir, OutDir},
-%% return, load]),
- ok = Mod:test(),
- ok.
-
-
-%%--------------------------------------------------------------------
-%%
-%% General cases
-%%
-
-%% coss (add sometimes, takes 440 seconds!)
-%% Check that type id's are generated correctly
-typeid(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(typeid),
- File = filename:join(DataDir, typeid),
-
- ok = ic:gen(File, stdopts(OutDir)),
- {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
- ok = compile(OutDir, typeid_files(), [load]),
- "IDL:I1:1.0" = 'I1':'typeID'(),
- "IDL:M1/I1:1.0" = 'M1_I1':'typeID'(),
- "IDL:M2/M1/I1:1.0" = 'M2_M1_I1':'typeID'(),
- "IDL:M3/M2/M1/I1:1.0" = 'M3_M2_M1_I1':'typeID'(),
- ok.
-
-
-%%% This test case is removed because there's no way to test this from
-%%% an automated test suite.
-%% Check that relative directories work, absolute is used in
-%% all other cases in the suite.
-dir(Config) when is_list(Config) ->
- ok;
-dir(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
-
- %% Needs a unique directory (any better way?)
- OutDir = mk_unique("oe_the_dir"),
-
- %% More unique names
- File = filename:join(DataDir, mk_unique("oe_the_file")),
- Const = mk_unique("oe_the_constant"),
- Mod = list_to_atom(File),
- Func = list_to_atom(Const),
-
- %% Generate a unique IDL file with a single constant
- gen_file(File, Const),
-
- ok = ic:gen(File, stdopts(OutDir)),
- ok = compile(OutDir, [load]),
- 19955 = Mod:Func(),
- {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
- ok = compile(OutDir, [load]),
- 19955 = Mod:Func(),
-
- ok = ic:gen(File),
-%%% ok = compile(".", [load]),
- ok.
-
-%% Check that various undefied id's are detected correctly
-undef_id(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, undef_id),
- error = ic:gen(File, stdopts(OutDir)),
- {error, [], R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(16, tk_not_found, R),
- ok.
-
-%% Check that multiply defined ids are caught.
-mult_ids(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, mult_ids),
- error = ic:gen(File, stdopts(OutDir)),
- {error, [], R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(22, multiply_defined, R),
- ok.
-
-
-%% Check that various nasty names can be generated.
-%% Try to provoke name clashes and name conflicts with
-%% Erlang and IDL
-nasty_names(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(nasty_names),
- File = filename:join(DataDir, nasty),
-
- ok = ic:gen(File, stdopts(OutDir)),
- {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
- ok = compile(OutDir, nasty_names_files(), [load]),
- ok.
-
-%% Check that the Coss standard specification works.
-coss(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(coss),
- File = filename:join(DataDir, 'Coss'),
-
- ok = ic:gen(File, stdopts(OutDir)),
- {ok, [_W1]} = ic:gen(File, stdopts(OutDir)++[silent2]),
- ok = compile(OutDir, []),
- ok.
-
-%% Check that forward declaratios work.
-forward(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(forward),
- File = filename:join(DataDir, forward),
-
- ok = ic:gen(File, stdopts(OutDir)),
- {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
- ok = compile(OutDir, forward_files(), [load]),
- ok.
-
-%% Check that various undefied id's are detected correctly
-include(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, include),
- error = ic:gen(File, stdopts(OutDir)++[{preproc_flags,"-I" ++ DataDir}]),
- {error, [], R} =
- ic:gen(File, stdopts(OutDir)++[{preproc_flags,"-I" ++ DataDir},silent2]),
- case lists:map(fun(D) ->
- filename:rootname(filename:basename(element(3, D)))
- end,
- lists:sort(R)) of
- ["include",
- "include2",
- "include2",
- "include3"] ->
- ok;
- RRR ->
- test_server:fail({bad_include_file, RRR})
- end,
- ok.
-
-
-
-
-%%--------------------------------------------------------------------
-%%
-%% Inhertit cases
-%%
-
-%% Checks that normal inheritance works.
-inherit_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(inherit_norm),
- File = filename:join(DataDir, inherit),
-
- ok = ic:gen(File, stdopts(OutDir)),
- {ok, _Ws} = ic:gen(File, stdopts(OutDir)++[silent2]),
- ok = compile(OutDir, inherit_norm_files(), [load]),
-
- %% Now check constant values:
- 9 = m1_I1:c1(),
-
- 9 = m1_I2:c1(),
- 14 = m1_I2:c2(),
- 27 = m1_I2:c3(),
-
- 50 = m1_I3:c1(),
- 14 = m1_I3:c2(),
- 27 = m1_I3:c3(),
- 91 = m1_I3:c4(),
- 100 = m1_I3:c5(),
- ok.
-
-%% Check that various inheritance shadowing is detected
-inherit_warn(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, inherit_warn),
- ok = ic:gen(File, stdopts(OutDir)),
- {ok, R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(7, inherit_name_shadow, R),
- ok.
-
-%% Check that various inheritance errors is detected
-inherit_err(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, inherit_err),
- error = ic:gen(File, stdopts(OutDir)),
- {error, _Ws, R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(21, inherit_name_collision, R),
- ok.
-
-
-%% Checks that normal oneway operations works.
-oneway_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(oneway_norm),
- File = filename:join(DataDir, one),
-
- ok = ic:gen(File, stdopts(OutDir)),
- ok = compile(OutDir, oneway_norm_files(), [load]),
- {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
- ok = compile(OutDir, oneway_norm_files(), [load]),
- ok.
-
-%% Check that non-void oneways are detected.
-oneway_void(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, one_void),
- error = ic:gen(File, stdopts(OutDir)),
- {error, [], R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(2, bad_oneway_type, R),
- ok.
-
-%% Check that oneways cannot raise exceptions.
-oneway_raises(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, one_raises),
- error = ic:gen(File, stdopts(OutDir)),
- {error, [], R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(3, oneway_raises, R),
- ok.
-
-%% Check that illegal out parameters are detected
-oneway_out(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, one_out),
- error = ic:gen(File, stdopts(OutDir)),
- {error, [], R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(2, oneway_outparams, R),
- ok.
-
-%% Checks that normal oneways, followed by other operations.
-oneway_followed(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(oneway_followed),
- File = filename:join(DataDir, one_followed),
-
- ok = ic:gen(File, stdopts(OutDir)),
- ok = compile(OutDir, oneway_followed_files(), [load]),
- {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
- ok = compile(OutDir, oneway_followed_files(), [load]),
- ok.
-
-
-%% Checks that normal attr operations works.
-attr_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(attr_norm),
- File = filename:join(DataDir, attr),
-
- ok = ic:gen(File, stdopts(OutDir)),
- ok = compile(OutDir, attr_norm_files(), [load]),
- {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
- ok = compile(OutDir, attr_norm_files(), [load]),
- ok.
-
-
-%% Checks all types are handled.
-type_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(type_norm),
- File = filename:join(DataDir, type),
-
- ok = ic:gen(File, stdopts(OutDir)),
- ok = compile(OutDir, type_norm_files(), [load]),
- {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
- ok = compile(OutDir, type_norm_files(), [load]),
- ok.
-
-syntax1(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, syntax1),
-
- error = ic:gen(File, stdopts(OutDir)),
- {error, [], R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(1, parse_error, R),
- ok.
-
-syntax2(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, syntax2),
-
- error = ic:gen(File, stdopts(OutDir)),
- {error, [], R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(1, parse_error, R),
- ok.
-
-syntax3(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, syntax3),
-
- error = ic:gen(File, stdopts(OutDir)),
- {error, [], R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(1, parse_error, R),
- ok.
-
-syntax4(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, syntax4),
-
- error = ic:gen(File, stdopts(OutDir)),
- {error, [], R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(1, parse_error, R),
- ok.
-
-syntax5(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, syntax5),
-
- error = ic:gen(File, stdopts(OutDir)),
- {error, [], R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(1, parse_error, R),
- ok.
-
-syntax6(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, syntax6),
-
- error = ic:gen(File, stdopts(OutDir)),
- {error, [], R} =
- ic:gen(File, stdopts(OutDir)++[silent2]),
- check_errors(1, parse_error, R),
- ok.
-
-
-
-%%--------------------------------------------------------------------
-%%
-%% Checks RAISES to be registered under IFR operation registration
-%% ( OTP-2102 )
-%%
-
-%% Check that exceptions are really registered to operations.
-raises_reg(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(raises_reg_check),
- File = filename:join(DataDir, raises_reg),
-
- ok = ic:gen(File, stdopts(OutDir)),
- {ok, []} = ic:gen(File, stdopts(OutDir)++[silent2]),
- ok = compile(OutDir, raises_reg_files(), [load]),
-
- set_up('oe_raises_reg'),
-
- io:format("~n##### Starting the test case #####~n"),
- io:format("Checking for existance of exception : ~s~n",["IDL:Raises_RegModule/Exception_1:1.0"]),
- raises_register_check("IDL:Raises_RegModule/R_R/op:1.0","IDL:Raises_RegModule/Exception_1:1.0"),
-
- io:format("Checking for existance of exception : ~s~n",["IDL:Raises_RegModule/Exception_2:1.0"]),
- raises_register_check("IDL:Raises_RegModule/R_R/op:1.0","IDL:Raises_RegModule/Exception_2:1.0"),
-
- io:format("Checking for existance of exception : ~s~n",["IDL:Raises_RegModule/XXXXXXXX:1.0"]),
- raises_register_check("IDL:Raises_RegModule/R_R/op:1.0","IDL:RaisesModule/XXXXXXXX:1.0"),
-
- set_down('oe_raises_reg'),
-
- ok.
-
-set_up(Register) ->
- io:format("Setting up.....~n"),
- mnesia:stop(),
- mnesia:delete_schema([node()]),
- mnesia:create_schema([node()]),
- mnesia:start(),
- orber:install([node()]),
- orber:start(),
- io:format("Running OE_register()~n"),
- Register:'oe_register'().
-
-set_down(Register) ->
- io:format("Running OE_unregister()~n"),
- Register:'oe_unregister'(),
- io:format("Setting down.....~n"),
- orber:stop(),
- orber:uninstall(),
- mnesia:stop(),
- mnesia:delete_schema([node()]).
-
-
-raises_register_check(OpId,ExcId) ->
- case is_valid_exc(OpId,ExcId) of
- true ->
- ok; % Because right exception where found,
- % the test succeeds for normal cases.
- false ->
- ok; % Because the exception tested, is not
- % registered for that operation.
- FailReason ->
- test_server:fail({FailReason, OpId, ExcId})
- % Because the test descovered errors in a previous
- % stage, or no exceptions where registered att all.
- % ( This testcase assumes that operations to be
- % checked allways raise excption(s) )
- end.
-
-is_valid_exc(OpId,ExcId) ->
- OE_IFR = orber_ifr:find_repository(),
- OpDef = orber_ifr:'Repository_lookup_id'(OE_IFR,OpId),
- ExcDefList = orber_ifr:get_exceptions(OpDef),
- case ExcDefList of
- [] ->
- no_exceptions_registered;
- _ ->
- ExcDef=orber_ifr:lookup_id(OE_IFR,ExcId),
- lists:member(ExcDef,ExcDefList)
- end.
-
-%%--------------------------------------------------------------------
-%%
-%% Utilities
-
-
-stdopts(OutDir) ->
- [{outdir, OutDir},{maxerrs, infinity}].
-
-mk_unique(Prefix) ->
- {A,B,C} = now(),
- Prefix++"_"++integer_to_list(A)++"_"++integer_to_list(B)++"_"++
- integer_to_list(C).
-
-gen_file(File, Const) ->
- {ok, Fd} = file:open(File++".idl", [write]),
- io:format(Fd, "interface ~s {~n", [File]),
- io:format(Fd, " const long ~s = 19955;~n", [Const]),
- io:format(Fd, "};~n", []),
- file:close(Fd).
-
-
-%% Compile all files in Dir. Used for checking that valid Erlang has
-%% been generated.
-%%compile(Dir) ->
-%% compile(Dir, []).
-%%compile(Dir, Opts) ->
-%% {ok, Cwd} = file:get_cwd(),
-%% catch do_compile(Dir, Opts),
-%% file:set_cwd(Cwd).
-
-%%do_compile(Dir, Opts) ->
-%% ok = file:set_cwd(Dir),
-%% up_to_date = ts_make_erl:all(Opts),
-%% ok.
-
-compile(Dir, Files) ->
- compile(Dir, Files, []).
-
-compile(Dir, Files, Opts) ->
- {ok, Cwd} = file:get_cwd(),
- file:set_cwd(Dir),
- io:format("Changing to ~p~n", [Dir]),
- case catch do_compile(Files, Opts) of
- ok ->
- file:set_cwd(Cwd);
- Err ->
- file:set_cwd(Cwd),
- test_server:fail(Err)
- end.
-
-do_compile([], _Opts) -> ok;
-do_compile([F | Fs], Opts) ->
- io:format("Compiling ~p", [F]),
- case compile:file(F, Opts) of
- ok ->
- io:format(" ok~n", []),
- do_load(F, Opts),
- do_compile(Fs, Opts);
- {ok, _} ->
- io:format(" ok~n", []),
- do_load(F, Opts),
- do_compile(Fs, Opts);
- {ok, _, _} ->
- io:format(" ok~n", []),
- do_load(F, Opts),
- do_compile(Fs, Opts);
- Err ->
- io:format(" error: ~p~n", [Err]),
- Err
- end.
-
-do_load(File, Opts) ->
- case lists:member(load, Opts) of
- true ->
- io:format("Loading file ~p", [File]),
- code:purge(File),
- R = code:load_abs(File),
- io:format("Loaded: ~p", [R]);
- false ->
- ok
- end.
-
-
-%% Check that ErrList consists of exactly Num errors of type ErrType
-check_errors(Num, ErrType, ErrList) ->
- Num = length(ErrList),
- lists:foreach(fun(T) ->
- case catch element(1, element(4, T)) of
- ErrType -> ok;
- Else ->
- test_server:fail({bad, ErrType, Else})
- end end, ErrList).
-
-to_list(X) when is_atom(X) -> atom_to_list(X);
-to_list(X) -> X.
-
-
-%% File must be an atom
-gen_struct_file(File, Mod) ->
-
- {ok, Fd} = file:open(to_list(File)++".erl", [write]),
- io:format(Fd, "~n", []),
- io:format(Fd, "-module(~p).~n", [Mod]),
- io:format(Fd, "-export([test/0]).~n", []),
- io:format(Fd, "-include(\"oe_struct.hrl\").~n", []),
- io:format(Fd, "test() ->~n", []),
- io:format(Fd, " A = #'S1'{a=99, b=$a, s=\"123456789\"},~n", []),
- io:format(Fd, " B = #'S2'{a=9, b=#'S2_S3'{a=1, b=9, b1=5, c=$2},~n", []),
- io:format(Fd, " c=[#'S1'{a=1}, #'S1'{a=2}],~n", []),
- io:format(Fd,
-" c2=[#'S1'{a=2}, #'S1'{a=3}, #'S1'{a=2}, #'S1'{a=3}]},~n", []),
- io:format(Fd, " C = #'S2_S3'{a=11, b=999, b1=19},~n", []),
- io:format(Fd, " D = #s4{a=7},~n", []),
- io:format(Fd, " E = {1, #'U1_S5'{a=3}},~n", []),
- io:format(Fd, " F = {2, {$b, #'U1_U2_s6'{a=6, b=false}}},~n", []),
- io:format(Fd, " ok.~n", []),
- file:close(Fd).
-
-
-union_norm_files() -> ['oe_u_norm'].
-union_default_files() -> ['oe_u_default', i1].
-
-typeid_files() -> ['oe_typeid', 'M3_M2_M1_I1', 'M2_M1_I1', 'M1_I1', 'I1'].
-
-struct_norm_files() -> ['oe_struct'].
-oneway_norm_files() -> ['oe_one', 'I1'].
-oneway_followed_files() -> ['oe_one_followed', 'I1'].
-nasty_names_files() -> ['oe_nasty', 'I2', 'I1'].
-
-inherit_norm_files() -> [m1_I3, m1_I2, m1_I1, 'oe_inherit', 'I4', 'I3',
- 'I2', 'I1'].
-
-forward_files() -> [i1, 'oe_forward'].
-enum_norm_files() -> ['oe_enum'].
-const_norm_files() -> ['oe_c_norm'].
-attr_norm_files() -> ['oe_attr', 'I1', 'I2'].
-type_norm_files() -> ['oe_type'].
-
-raises_reg_files() -> ['oe_raises_reg'].
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/test/ic_SUITE_data/Corba.idl b/lib/ic/test/ic_SUITE_data/Corba.idl
deleted file mode 100644
index 6b81132500..0000000000
--- a/lib/ic/test/ic_SUITE_data/Corba.idl
+++ /dev/null
@@ -1,1013 +0,0 @@
-// This file contains OMG IDL from CORBA V2.0, July 1995.
-// Includes IDL for CORBA Core
-// (Interface Repository, ORB Interface, Basic Object Adapter Interface)
-// and CORBA Interoperability (IOP, GIOP, IIOP, and DCE CIOP modules)
-
-// Complete OMG IDL for Interface Repository starts on pg 6-42, CORBA V2.0 July 1995
-// IRObject interface described on pg 6-9 CORBA V2.0, July 1995
-// Contained interface: pg 6-11 CORBA V2, 7-95
-// Container interface: pg 6-12 thru 6-15 CORBA V2, 7-95
-// IDLType interface: pg 6-15 CORBA V2, 7-95
-// Repository interface: pg 6-16 CORBA V2, 7-95
-// ModuleDef interface: pg 6-17 CORBA V2, 7-95
-// ConstantDef interface: pg 6-18 CORBA V2, 7-95
-// TypeDef interface: pg 6-19 CORBA V2, 7-95
-// StructDef interface: pg 6-19 CORBA V2, 7-95
-// UnionDef interface: pg 6-19 CORBA V2, 7-95
-// EnumDef interface: pg 6-20 CORBA V2, 7-95
-// AliasDef interface: pg 6-21 CORBA V2, 7-95
-// PrimitiveDef interface: pg 6-21 CORBA V2, 7-95
-// StringDef interface: pg 6-22 CORBA V2, 7-95
-// SequenceDef interface: pg 6-22 CORBA V2, 7-95
-// ArrayDef interface: pg 6-23 CORBA V2, 7-95
-// ExceptionDef interface: pg 6-24 CORBA V2, 7-95
-// AttributeDef interface: pg 6-25 CORBA V2, 7-95
-// OperationDef interface: pg 6-26 CORBA V2, 7-95
-// InterfaceDef interface: pg 6-28 CORBA V2, 7-95
-// TypeCode interface (PIDL): pg 6-34 CORBA V2, 7-95
-// ORB interface: pg 6-40 CORBA V2, 7-95
-
-#ifndef __CORBA_IDL
-#define __CORBA_IDL
-
-// #pragma prefix "omg.org"
-module CORBA {
-
- interface TypeCode;
- typedef string Identifier;
- typedef string ScopedName;
- typedef string RepositoryId;
-
- /*
- * start of section added by Christian Blum
- */
-
- typedef enum new_type {NO,USER,SYSTEM_EXCEPTION} exception_type;
-
- /**
- * no definition for this type
- */
- interface ImplementationDef
- {
- };
-
- /**
- * no definition for this type
- */
- //interface Principal
- struct Principal
- {
- string str;
- };
-
- /**
- * no definition for this type
- */
- interface Environment
- {
-
- };
-
- typedef unsigned long Flags;
- typedef unsigned long Status;
-
- struct NamedValue // PIDL
- {
- Identifier name; // argument name
- any argument; // argument
- long len; // length/count of argument value
- Flags arg_modes; // argument mode flags
-
- };
-
- typedef sequence<NamedValue> NVList; /* C */
-
- interface Request // PIDL
- {
-
- Status add_arg (
- in Identifier name, // argument name
- in TypeCode arg_type, // argument datatype
- // in void * value, // argument value to be added
- in any value_LOOK_AT_SOURCE, // changed by blum
- in long len, // length/count of argument value
- in Flags arg_flags // argument flags
- );
-
- Status invoke (
- in Flags invoke_flags // invocation flags
- );
-
- Status delete ();
- Status send (
- in Flags invoke_flags // invocation flags
- );
-
- Status get_response (
- in Flags response_flags // response flags
- );
-
- };
-
-
- interface Context // PIDL
- {
-
- Status set_one_value (
- in Identifier prop_name, // property name to add
- in string value // property value to add
- );
-
- Status set_values (
- in NVList values // property values to be changed
- );
-
- Status get_values (
- in Identifier start_scope, // search scope
- in Flags op_flags, // operation flags
- in Identifier prop_name, // name of property(s) to retrieve
- out NVList values // requested property(s)
- );
-
- Status delete_values (
- in Identifier prop_name // name of property(s) to delete
- );
-
- Status create_child (
- in Identifier ctx_name, // name of context object
- out Context child_ctx // newly created context object
- );
-
- Status delete (
- in Flags del_flags // flags controlling deletion
- );
-
- };
-
- /*
- * end of section added by Christian Blum
- */
-
-
- enum DefinitionKind {
- dk_none, dk_all,
- dk_Attribute, dk_Constant, dk_Exception, dk_Interface,
- dk_Module, dk_Operation, dk_Typedef,
- dk_Alias, dk_Struct, dk_Union, dk_Enum,
- dk_Primitive, dk_String, dk_Sequence, dk_Array,
- dk_Repository
- };
-
-
- interface IRObject {
- // read interface
- readonly attribute DefinitionKind def_kind;
-
- // write interface
- void destroy ();
- };
-
-
-
- typedef string VersionSpec;
-
- interface Contained;
- interface Repository;
- interface Container;
-
- interface Contained : IRObject {
- // read/write interface
-
- attribute RepositoryId id;
- attribute Identifier name;
- attribute VersionSpec version;
-
- // read interface
-
- readonly attribute Container defined_in;
- readonly attribute ScopedName absolute_name;
- readonly attribute Repository containing_repository;
-
- struct Description {
- DefinitionKind kind;
- any value;
- };
-
- Description describe ();
-
- // write interface
-
- void move (
- in Container new_container,
- in Identifier new_name,
- in VersionSpec new_version
- );
- };
-
-
- interface ModuleDef;
- interface ConstantDef;
- interface IDLType;
- interface StructDef;
- interface UnionDef;
- interface EnumDef;
- interface AliasDef;
- interface InterfaceDef;
- typedef sequence <InterfaceDef> InterfaceDefSeq;
-
- typedef sequence <Contained> ContainedSeq;
-
- struct StructMember {
- Identifier name;
- TypeCode type;
- IDLType type_def;
- };
- typedef sequence <StructMember> StructMemberSeq;
-
- struct UnionMember {
- Identifier name;
- any label;
- TypeCode type;
- IDLType type_def;
- };
- typedef sequence <UnionMember> UnionMemberSeq;
-
- typedef sequence <Identifier> EnumMemberSeq;
-
- interface Container : IRObject {
- // read interface
-
- Contained lookup ( in ScopedName search_name);
-
- ContainedSeq contents (
- in DefinitionKind limit_type,
- in boolean exclude_inherited
- );
-
- ContainedSeq lookup_name (
- in Identifier search_name,
- in long levels_to_search,
- in DefinitionKind limit_type,
- in boolean exclude_inherited
- );
-
- struct Description {
- Contained contained_object;
- DefinitionKind kind;
- any value;
- };
-
- typedef sequence<Description> DescriptionSeq;
-
- DescriptionSeq describe_contents (
- in DefinitionKind limit_type,
- in boolean exclude_inherited,
- in long max_returned_objs
- );
-
- // write interface
-
- ModuleDef create_module (
- in RepositoryId id,
- in Identifier name,
- in VersionSpec version
- );
-
- ConstantDef create_constant (
- in RepositoryId id,
- in Identifier name,
- in VersionSpec version,
- in IDLType type,
- in any value
- );
-
- StructDef create_struct (
- in RepositoryId id,
- in Identifier name,
- in VersionSpec version,
- in StructMemberSeq members
- );
-
- UnionDef create_union (
- in RepositoryId id,
- in Identifier name,
- in VersionSpec version,
- in IDLType discriminator_type,
- in UnionMemberSeq members
- );
-
- EnumDef create_enum (
- in RepositoryId id,
- in Identifier name,
- in VersionSpec version,
- in EnumMemberSeq members
- );
-
- AliasDef create_alias (
- in RepositoryId id,
- in Identifier name,
- in VersionSpec version,
- in IDLType original_type
- );
-
- InterfaceDef create_interface (
- in RepositoryId id,
- in Identifier name,
- in VersionSpec version,
- in InterfaceDefSeq base_interfaces
- );
- };
-
-
-
- interface IDLType : IRObject {
- readonly attribute TypeCode type;
- };
-
-
-
- interface PrimitiveDef;
- interface StringDef;
- interface SequenceDef;
- interface ArrayDef;
-
- enum PrimitiveKind {
- pk_null, pk_void, pk_short, pk_long, pk_ushort, pk_ulong,
- pk_float, pk_double, pk_boolean, pk_char, pk_octet,
- pk_any, pk_TypeCode, pk_Principal, pk_string, pk_objref
- };
-
- interface Repository : Container {
- // read interface
-
- Contained lookup_id (in RepositoryId search_id);
-
- PrimitiveDef get_primitive (in PrimitiveKind kind);
-
- // write interface
-
- StringDef create_string (in unsigned long bound);
-
- SequenceDef create_sequence (
- in unsigned long bound,
- in IDLType element_type
- );
-
- ArrayDef create_array (
- in unsigned long length,
- in IDLType element_type
- );
- };
-
-
- interface ModuleDef : Container, Contained {
- };
-
- struct ModuleDescription {
- Identifier name;
- RepositoryId id;
- RepositoryId defined_in;
- VersionSpec version;
- };
-
-
- interface ConstantDef : Contained {
- readonly attribute TypeCode type;
- attribute IDLType type_def;
- attribute any value;
- };
-
- struct ConstantDescription {
- Identifier name;
- RepositoryId id;
- RepositoryId defined_in;
- VersionSpec version;
- TypeCode type;
- any value;
- };
-
-
- interface TypedefDef : Contained, IDLType {
- };
-
- struct TypeDescription {
- Identifier name;
- RepositoryId id;
- RepositoryId defined_in;
- VersionSpec version;
- TypeCode type;
- };
-
-
- interface StructDef : TypedefDef {
- attribute StructMemberSeq members;
- };
-
-
- interface UnionDef : TypedefDef {
- readonly attribute TypeCode discriminator_type;
- attribute IDLType discriminator_type_def;
- attribute UnionMemberSeq members;
- };
-
-
- interface EnumDef : TypedefDef {
- attribute EnumMemberSeq members;
- };
-
-
- interface AliasDef : TypedefDef {
- attribute IDLType original_type_def;
- };
-
-
- interface PrimitiveDef: IDLType {
- readonly attribute PrimitiveKind kind;
- };
-
-
- interface StringDef : IDLType {
- attribute unsigned long bound;
- };
-
-
- interface SequenceDef : IDLType {
- attribute unsigned long bound;
- readonly attribute TypeCode element_type;
- attribute IDLType element_type_def;
- };
-
- interface ArrayDef : IDLType {
- attribute unsigned long length;
- readonly attribute TypeCode element_type;
- attribute IDLType element_type_def;
- };
-
-
- interface ExceptionDef : Contained {
- readonly attribute TypeCode type;
- attribute StructMemberSeq members;
- };
- struct ExceptionDescription {
- Identifier name;
- RepositoryId id;
- RepositoryId defined_in;
- VersionSpec version;
- TypeCode type;
- };
-
-
-
- enum AttributeMode {ATTR_NORMAL, ATTR_READONLY};
-
- interface AttributeDef : Contained {
- readonly attribute TypeCode type;
- attribute IDLType type_def;
- attribute AttributeMode mode;
- };
-
- struct AttributeDescription {
- Identifier name;
- RepositoryId id;
- RepositoryId defined_in;
- VersionSpec version;
- TypeCode type;
- AttributeMode mode;
- };
-
-
-
- enum OperationMode {OP_NORMAL, OP_ONEWAY};
-
- enum ParameterMode {PARAM_IN, PARAM_OUT, PARAM_INOUT};
- struct ParameterDescription {
- Identifier name;
- TypeCode type;
- IDLType type_def;
- ParameterMode mode;
- };
- typedef sequence <ParameterDescription> ParDescriptionSeq;
-
- typedef Identifier ContextIdentifier;
- typedef sequence <ContextIdentifier> ContextIdSeq;
-
- typedef sequence <ExceptionDef> ExceptionDefSeq;
- typedef sequence <ExceptionDescription> ExcDescriptionSeq;
-
- interface OperationDef : Contained {
- readonly attribute TypeCode result;
- attribute IDLType result_def;
- attribute ParDescriptionSeq params;
- attribute OperationMode mode;
- attribute ContextIdSeq contexts;
- attribute ExceptionDefSeq exceptions;
- };
-
- struct OperationDescription {
- Identifier name;
- RepositoryId id;
- RepositoryId defined_in;
- VersionSpec version;
- TypeCode result;
- OperationMode mode;
- ContextIdSeq contexts;
- ParDescriptionSeq parameters;
- ExcDescriptionSeq exceptions;
- };
-
-
-
- typedef sequence <RepositoryId> RepositoryIdSeq;
- typedef sequence <OperationDescription> OpDescriptionSeq;
- typedef sequence <AttributeDescription> AttrDescriptionSeq;
-
- interface InterfaceDef : Container, Contained, IDLType {
- // read/write interface
-
- attribute InterfaceDefSeq base_interfaces;
-
- // read interface
-
- boolean is_a (in RepositoryId interface_id);
-
- struct FullInterfaceDescription {
- Identifier name;
- RepositoryId id;
- RepositoryId defined_in;
- VersionSpec version;
- OpDescriptionSeq operations;
- AttrDescriptionSeq attributes;
- RepositoryIdSeq base_interfaces;
- TypeCode type;
- };
-
- FullInterfaceDescription describe_interface();
-
- // write interface
-
- AttributeDef create_attribute (
- in RepositoryId id,
- in Identifier name,
- in VersionSpec version,
- in IDLType type,
- in AttributeMode mode
- );
-
- OperationDef create_operation (
- in RepositoryId id,
- in Identifier name,
- in VersionSpec version,
- in IDLType result,
- in OperationMode mode,
- in ParDescriptionSeq params,
- in ExceptionDefSeq exceptions,
- in ContextIdSeq contexts
- );
- };
-
- struct InterfaceDescription {
- Identifier name;
- RepositoryId id;
- RepositoryId defined_in;
- VersionSpec version;
- RepositoryIdSeq base_interfaces;
- };
-
-
-
- enum TCKind {
- tk_null, tk_void,
- tk_short, tk_long, tk_ushort, tk_ulong,
- tk_float, tk_double, tk_boolean, tk_char,
- tk_octet, tk_any, tk_TypeCode, tk_Principal, tk_objref,
- tk_struct, tk_union, tk_enum, tk_string,
- tk_sequence, tk_array, tk_alias, tk_except
- };
-
- interface TypeCode { // PIDL
- exception Bounds {};
- exception BadKind {};
-
- // for all TypeCode kinds
- boolean equal (in TypeCode tc);
- TCKind kind ();
-
- // for tk_objref, tk_struct, tk_union, tk_enum, tk_alias, and tk_except
- RepositoryId id () raises (BadKind);
-
- // for tk_objref, tk_struct, tk_union, tk_enum, tk_alias, and tk_except
- Identifier name () raises (BadKind);
-
- // for tk_struct, tk_union, tk_enum, and tk_except
- unsigned long member_count () raises (BadKind);
- Identifier member_name (in unsigned long index) raises (BadKind, Bounds);
-
- // for tk_struct, tk_union, and tk_except
- TypeCode member_type (in unsigned long index) raises (BadKind, Bounds);
-
- // for tk_union
- any member_label (in unsigned long index) raises (BadKind, Bounds);
- TypeCode discriminator_type () raises (BadKind);
- long default_index () raises (BadKind);
-
- // for tk_string, tk_sequence, and tk_array
- unsigned long length () raises (BadKind);
-
- // for tk_sequence, tk_array, and tk_alias
- TypeCode content_type () raises (BadKind);
-
- // deprecated interface
- long param_count ();
- any parameter (in long index) raises (Bounds);
- };
-
-
- /*
- * following line added by Christian Blum
- */
- interface BOA;
-
- interface ORB {
- // other operations ...
-
- TypeCode create_struct_tc (
- in RepositoryId id,
- in Identifier name,
- in StructMemberSeq members
- );
-
- TypeCode create_union_tc (
- in RepositoryId id,
- in Identifier name,
- in TypeCode discriminator_type,
- in UnionMemberSeq members
- );
-
- TypeCode create_enum_tc (
- in RepositoryId id,
- in Identifier name,
- in EnumMemberSeq members
- );
-
- TypeCode create_alias_tc (
- in RepositoryId id,
- in Identifier name,
- in TypeCode original_type
- );
-
- TypeCode create_exception_tc (
- in RepositoryId id,
- in Identifier name,
- in StructMemberSeq members
- );
-
- TypeCode create_interface_tc (
- in RepositoryId id,
- in Identifier name
- );
-
- TypeCode create_string_tc (
- in unsigned long bound
- );
-
- TypeCode create_sequence_tc (
- in unsigned long bound,
- in TypeCode element_type
- );
-
- TypeCode create_recursive_sequence_tc (
- in unsigned long bound,
- in unsigned long offset
- );
-
- TypeCode create_array_tc (
- in unsigned long length,
- in TypeCode element_type
- );
-
- /*
- * following line commented out by Christian Blum
- */
- // };
-
- // The ORB interface (PIDL) is described in Chapter 7, CORBA V2.0 July 1995
- // Object interface (object reference operations): pg 7-3 CORBA V2, 7-95
- // ORB initialization: pg 7-7 CORBA V2, 7-95
- // Object Adapter and Basic Object Adapter initialization: pg 7-8 CORBA V2 7-95
- // Getting initial references: pg 7-10 CORBA V2 7-95
- //PIDL
-
- /*
- * following line commented out by Christian Blum
- */
- //interface ORB {
-
-
- string object_to_string (in Object obj);
- Object string_to_object (in string str);
-
- Status create_list (
- in long count,
- out NVList new_list
- );
- Status create_operation_list (
- in OperationDef oper,
- out NVList new_list
- );
- Status get_default_context (out Context ctx);
-
- // Initializing the ORB
- typedef string ORBid;
- typedef sequence <string> arg_list;
- ORB ORB_init (inout arg_list argv, in ORBid orb_identifier);
-
- // Initializing an object adapter and the Basic Object Adapter
- typedef string OAid;
-
- // Template for OA initialization operations
- // <OA> <OA>_init (inout arg_list argv,
- // in OAid oa_identifier);
-
-
-
- BOA BOA_init (inout arg_list argv,
- in OAid boa_identifier);
-
-
-
- // Getting initial object references
- typedef string ObjectId;
- typedef sequence <ObjectId> ObjectIdList;
-
- exception InvalidName {};
-
- ObjectIdList list_initial_services ();
-
- Object resolve_initial_references (in ObjectId identifier)
- raises (InvalidName);
- };
-
- // had to be changed..., Gerald Brose 1996
- interface ORBject {
-
- ImplementationDef get_implementation ();
- InterfaceDef get_interface ();
- boolean is_nil();
- Object duplicate ();
- void release ();
- boolean is_a (in string logical_type_id);
- boolean non_existent();
- boolean is_equivalent (in Object other_object);
- unsigned long hash(in unsigned long maximum);
-
-
- Status create_request (
- in Context ctx,
- in Identifier operation,
- in NVList arg_list,
- inout NamedValue result,
- out Request request,
- in Flags req_flags
- );
- };
-
-
- // Basic Object Adapter interface described in Chapter 8, CORBA V2.0, July 1995
- // interface InterfaceDef; // from Interface Repository // PIDL
- // interface ImplementationDef; // from Implementation Repository
- // interface Object; // an object reference
- // interface Principal; // for the authentication service
- typedef sequence <octet, 1024> ReferenceData;
-
- interface BOA {
- Object create (
- in ReferenceData id,
- in InterfaceDef intf,
- in ImplementationDef impl
- );
- void dispose (in Object obj);
- ReferenceData get_id (in Object obj);
-
- void change_implementation (in Object obj,
- in ImplementationDef impl
- );
-
- Principal get_principal (in Object obj,
- in Environment ev
- );
-
- void set_exception (in exception_type major, // NO, USER,
- //or SYSTEM_EXCEPTION
- in string userid, // exception type id
- in any param_LOOK_AT_SOURCE
- // in void *param // pointer to associated data
- );
-
- void impl_is_ready (in ImplementationDef impl);
- void deactivate_impl (in ImplementationDef impl);
- void obj_is_ready (in Object obj, in ImplementationDef impl);
- void deactivate_obj (in Object obj);
- };
-};
-
-// IOP module described in chap 10 CORBA V2, 7-95
-module IOP{ // IDL
- //
- // Standard Protocol Profile tag values
- //
- typedef unsigned long ProfileId;
- const ProfileId TAG_INTERNET_IOP = 0;
- const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
-
- struct TaggedProfile {
- ProfileId tag;
- sequence <octet> profile_data;
- };
-
- //
- // an Interoperable Object Reference is a sequence of
- // object-specific protocol profiles, plus a type ID.
- //
- struct IOR {
- string type_id;
- sequence <TaggedProfile> profiles;
- };
-
- //
- // Standard way of representing multicomponent profiles.
- // This would be encapsulated in a TaggedProfile.
- //
- typedef unsigned long ComponentId;
- struct TaggedComponent {
- ComponentId tag;
- sequence <octet> component_data;
- };
- typedef sequence <TaggedComponent> MultipleComponentProfile;
-
-
- typedef unsigned long ServiceID;
-
- struct ServiceContext {
- ServiceID context_id;
- sequence <octet> context_data;
- };
- typedef sequence <ServiceContext> ServiceContextList;
-
- const ServiceID TransactionService = 0;
-
-
-
-};
-// GIOP module described in CORBA V2, 7-95 chap 12
-// Complete IDL for GIOP module in CORBA
-// V2.0, 7-95 p 10-29
-// GIOP message header: CORBA V2, 7-95 p 12-16
-// GIOP request header: CORBA V2, 7-95 p 12-17
-// GIOP reply header: CORBA V2, 7-95 p 12-19
-// GIOP cancel request and locate request: CORBA V2, 7-95 pp 12-20 -- 12-21
-// GIOP locate reply: CORBA V2, 7-95 p 12-22
-module GIOP { // IDL
- enum MsgType {
- Request, Reply, CancelRequest,
- LocateRequest, LocateReply,
- CloseConnection, MessageError
- };
-
- struct Version {
- char major;
- char minor;
- };
-
- struct MessageHeader {
- char magic [4];
- Version GIOP_version;
- boolean byte_order;
- octet message_type;
- unsigned long message_size;
- };
-
- struct RequestHeader {
- ::IOP::ServiceContextList service_context;
- unsigned long request_id;
- boolean response_expected;
- sequence <octet> object_key;
- string operation;
-
- /*
- * ::CORBA:: added for correct scope
- */
- ::CORBA::Principal requesting_principal;
- };
-
- enum ReplyStatusType {
- NO_EXCEPTION,
- USER_EXCEPTION,
- SYSTEM_EXCEPTION,
- LOCATION_FORWARD
- };
-
- struct ReplyHeader {
- ::IOP::ServiceContextList service_context;
- unsigned long request_id;
- ReplyStatusType reply_status;
- };
-
- struct CancelRequestHeader {
- unsigned long request_id;
- };
-
- struct LocateRequestHeader {
- unsigned long request_id;
- sequence <octet> object_key;
- };
-
- enum LocateStatusType {
- UNKNOWN_OBJECT,
- OBJECT_HERE,
- OBJECT_FORWARD
- };
-
- struct LocateReplyHeader {
- unsigned long request_id;
- LocateStatusType locate_status;
- };
-};
-// IIOP module described in CORBA V2, 7-95 chap 12
-// Complete IDL for IIOP module: CORBA V2, 7-95 p 12-31
-module IIOP { // IDL
- struct Version {
- char major;
- char minor;
- };
-
- struct ProfileBody {
- Version iiop_version;
- string host;
- unsigned short port;
- sequence <octet> object_key;
- };
-};
-// DCE CIOP module described in CORBA V2, 7-95 chap 13
-// IDL for DCE CIOP module: CORBA V2, 7-95 p 13-2
-module DCE_CIOP {
- struct InvokeRequestHeader {
- boolean byte_order;
- ::IOP::ServiceContextList service_context;
- sequence <octet> object_key;
- string endpoint_id;
- string operation;
- ::CORBA::Principal principal;
- sequence <string> client_context;
-
- // in and inout parameters follow
- };
- enum InvokeResponseStatus {
- INVOKE_NO_EXCEPTION,
- INVOKE_USER_EXCEPTION,
- INVOKE_SYSTEM_EXCEPTION,
- INVOKE_LOCATION_FORWARD,
- INVOKE_TRY_AGAIN
- };
-
- struct InvokeResponseHeader {
- boolean byte_order;
- ::IOP::ServiceContextList service_context;
- InvokeResponseStatus status;
-
- // if status = INVOKE_NO_EXCEPTION,
- // result then inouts and outs follow
-
- // if status = INVOKE_USER_EXCEPTION or
- // INVOKE_SYSTEM_EXCEPTION, an exception follows
-
- // if status = INVOKE_LOCATION_FORWARD, an
- // ::IOP::MultipleComponentsProfile follows
- };
-
- struct LocateRequestHeader {
- boolean byte_order;
- sequence <octet> object_key;
- string endpoint_id;
- string operation;
-
- // no body follows
- };
-
- module IOP {
-
- /*
- * ::IOP:: added to get the right scope
- */
- const ::IOP::ComponentId TAG_OBJECT_KEY = 10;
- const ::IOP::ComponentId TAG_ENDPOINT_ID = 11;
- const ::IOP::ComponentId TAG_LOCATION_POLICY = 12;
- // illegal IDL
- /* const octet LOCATE_NEVER = 0;
- const octet LOCATE_OBJECT = 1;
- const octet LOCATE_OPERATION = 2;
- const octet LOCATE_ALWAYS = 3;
- */
- };
-};
-
-#endif
diff --git a/lib/ic/test/ic_SUITE_data/Coss.idl b/lib/ic/test/ic_SUITE_data/Coss.idl
deleted file mode 100644
index c84d4a8247..0000000000
--- a/lib/ic/test/ic_SUITE_data/Coss.idl
+++ /dev/null
@@ -1,1537 +0,0 @@
-// This file contains OMG IDL and PIDL for the Common Object Services.
-// CosNaming Module, p 3-6 CORBAservices, Naming Service V1.0, 3/94
-
-// A few minor changes for the JacORB distribution:
-//
-// added am enclosing COSS module and changed scoped names accordingly
-//
-// corrected a few syntax errors
-//
-// commented out:
-// #includes
-// forward declaration of Object
-
-#include "Corba.idl"
-
-module COSS {
-
-module CosNaming {
-
- typedef string Istring;
- struct NameComponent {
- Istring id;
- Istring kind;
- };
-
- typedef sequence <NameComponent> Name;
-
- enum BindingType {nobject, ncontext};
-
- struct Binding {
- Name binding_name;
- BindingType binding_type;
- };
-
- typedef sequence <Binding> BindingList;
- interface BindingIterator;
-
- interface NamingContext {
-
- enum NotFoundReason { missing_node, not_context, not_object};
-
- exception NotFound {
- NotFoundReason why;
- Name rest_of_name;
- };
-
- exception CannotProceed {
- NamingContext cxt;
- Name rest_of_name;
- };
-
- exception InvalidName{};
- exception AlreadyBound {};
- exception NotEmpty{};
-
- void bind(in Name n, in Object obj)
- raises(NotFound, CannotProceed, InvalidName, AlreadyBound);
- void rebind(in Name n, in Object obj)
- raises(NotFound, CannotProceed, InvalidName);
- void bind_context(in Name n, in NamingContext nc)
- raises(NotFound, CannotProceed, InvalidName, AlreadyBound);
- void rebind_context(in Name n, in NamingContext nc)
- raises(NotFound, CannotProceed, InvalidName);
- Object resolve (in Name n)
- raises(NotFound, CannotProceed, InvalidName);
- void unbind(in Name n)
- raises(NotFound, CannotProceed, InvalidName);
- NamingContext new_context();
- NamingContext bind_new_context(in Name n)
- raises(NotFound, AlreadyBound, CannotProceed, InvalidName);
- void destroy( )
- raises(NotEmpty);
- void list (in unsigned long how_many,
- out BindingList bl, out BindingIterator bi);
- };
-
- interface BindingIterator {
- boolean next_one(out Binding b);
- boolean next_n(in unsigned long how_many,
- out BindingList bl);
- void destroy();
- };
-};
-
-// Names Library interface in PIDL, CORBAservices p 3- 14, Naming Service V1.0 3/94
-/*
-interface LNameComponent { // PIDL
- exception NotSet{};
- string get_id()
- raises(NotSet);
- void set_id(in string i);
- string get_kind()
- raises(NotSet);
- void set_kind(in string k);
- void destroy();
-};
-
-interface LName { // PIDL
- exception NoComponent{};
- exception OverFlow{};
- exception InvalidName{};
- LName insert_component(in unsigned long i,
- in LNameComponent n)
- raises(NoComponent, OverFlow);
- LNameComponent get_component(in unsigned long i)
- raises(NoComponent);
- LNameComponent delete_component(in unsigned long i)
- raises(NoComponent);
- unsigned long num_components();
- boolean equal(in LName ln);
- boolean less_than(in LName ln);
- Name to_idl_form()
- raises(InvalidName);
- void from_idl_form(in Name n);
- void destroy();
-};
-
-LName create_lname(); // C/C++
-LNameComponent create_lname_component(); // C/C++
-*/
-
-// CosEventComm Module, CORBAservices p 4-8, Event Service V1.0 3/94
-
-module CosEventComm {
-
- exception Disconnected{};
-
- interface PushConsumer {
- void push (in any data) raises(Disconnected);
- void disconnect_push_consumer();
- };
-
- interface PushSupplier {
- void disconnect_push_supplier();
- };
-
- interface PullSupplier {
- any pull () raises(Disconnected);
- any try_pull (out boolean has_event)
- raises(Disconnected);
- void disconnect_pull_supplier();
- };
-
- interface PullConsumer {
- void disconnect_pull_consumer();
- };
-
-};
-
-// CosEventChannelAdmin Module, p 4-15 CORBAservices, Event
-// Service V1.0, 3/94
-
-// #include "CosEventComm.idl"
-
-module CosEventChannelAdmin {
-
- exception AlreadyConnected {};
- exception TypeError {};
-
- interface ProxyPushConsumer: ::COSS::CosEventComm::PushConsumer {
- void connect_push_supplier(
- in ::COSS::CosEventComm::PushSupplier push_supplier)
- raises(AlreadyConnected);
- };
-
- interface ProxyPullSupplier: ::COSS::CosEventComm::PullSupplier {
- void connect_pull_consumer(
- in ::COSS::CosEventComm::PullConsumer pull_consumer)
- raises(AlreadyConnected);
- };
-
- interface ProxyPullConsumer: ::COSS::CosEventComm::PullConsumer {
- void connect_pull_supplier(
- in ::COSS::CosEventComm::PullSupplier pull_supplier)
- raises(AlreadyConnected,TypeError);
- };
-
- interface ProxyPushSupplier: ::COSS::CosEventComm::PushSupplier {
- void connect_push_consumer(
- in ::COSS::CosEventComm::PushConsumer
- push_consumer)
- raises(AlreadyConnected, TypeError);
- };
-
-
- interface ConsumerAdmin {
- ProxyPushSupplier obtain_push_supplier();
- ProxyPullSupplier obtain_pull_supplier();
- };
-
- interface SupplierAdmin {
- ProxyPushConsumer obtain_push_consumer();
- ProxyPullConsumer obtain_pull_consumer();
- };
-
- interface EventChannel {
- ConsumerAdmin for_consumers();
- SupplierAdmin for_suppliers();
- void destroy();
- };
-
-};
-
-
-// CosTyped Event Module, p 4-22 CORBAservices, Event Service
-// V1.0, 3/94
-
-// // #include "CosEventComm.idl"
-
-module CosTypedEventComm {
-
- interface TypedPushConsumer : ::COSS::CosEventComm::PushConsumer {
- Object get_typed_consumer();
- };
-
- interface TypedPullSupplier : ::COSS::CosEventComm::PullSupplier {
- Object get_typed_supplier();
- };
-
-};
-
-// CosTypedEventChannelAdmin Module, p 4- 25 CORBAservices,
-// Event Service V1.0, 3/94
-
-// // #include "CosEventChannel.idl"
-// // #include "CosTypedEventComm.idl"
-module CosTypedEventChannelAdmin {
- exception InterfaceNotSupported {};
- exception NoSuchImplementation {};
- typedef string Key;
-
- interface TypedProxyPushConsumer :
- ::COSS::CosEventChannelAdmin::ProxyPushConsumer,
- ::COSS::CosTypedEventComm::TypedPushConsumer { };
-
- interface TypedProxyPullSupplier :
- ::COSS::CosEventChannelAdmin::ProxyPullSupplier,
- ::COSS::CosTypedEventComm::TypedPullSupplier { };
-
- interface TypedSupplierAdmin :
- ::COSS::CosEventChannelAdmin::SupplierAdmin {
- TypedProxyPushConsumer obtain_typed_push_consumer(
- in Key supported_interface)
- raises(InterfaceNotSupported);
- ::COSS::CosEventChannelAdmin::ProxyPullConsumer obtain_typed_pull_consumer (
- in Key uses_interface)
- raises(NoSuchImplementation);
- };
-
- interface TypedConsumerAdmin :
- ::COSS::CosEventChannelAdmin::ConsumerAdmin {
- TypedProxyPullSupplier obtain_typed_pull_supplier(
- in Key supported_interface)
- raises (InterfaceNotSupported);
- ::COSS::CosEventChannelAdmin::ProxyPushSupplier obtain_typed_push_supplier(
- in Key uses_interface)
- raises(NoSuchImplementation);
- };
-
- interface TypedEventChannel {
- TypedConsumerAdmin for_consumers();
- TypedSupplierAdmin for_suppliers();
- void destroy ();
- };
-};
-
-
-// CosPersistencePID Module, p 5-20 CORBAservices,
-// Persistent Object Service V1.0, 3/94
-
-//#ifndef __COSPERSISTENCE
-//#define __COSPERSISTENCE
-
-module CosPersistencePID {
-
- interface PID {
- attribute string datastore_type;
- string get_PIDString();
- };
-};
-
-
-// CosPersistencePDS Module, p 5-20 CORBAservices,
-// Persistent Object Service V1.0, 3/94
-
-// #include "CosPersistencePID.idl"
-
-module CosPersistencePDS {
-
-// interface Object;
- interface PDS {
- PDS connect (in Object obj,
- in ::COSS::CosPersistencePID::PID p);
- void disconnect (in Object obj,
- in ::COSS::CosPersistencePID::PID p);
- void store (in Object obj,
- in ::COSS::CosPersistencePID::PID p);
- void restore (in Object obj,
- in ::COSS::CosPersistencePID::PID p);
- void delete (in Object obj,
- in ::COSS::CosPersistencePID::PID p);
- };
-};
-
-
-// CosPersistencePO Module, p 5-12 CORBAservices,
-// Persistent Object Service V1.0, 3/94
-
-// // #include "CosPersistencePDS.idl"
-// CosPersistencePDS.idl
-// // #includes CosPersistencePID.idl
-
-module CosPersistencePO {
-
- interface PO {
- attribute ::COSS::CosPersistencePID::PID p;
- ::COSS::CosPersistencePDS::PDS connect (
- in ::COSS::CosPersistencePID::PID p);
- void disconnect (in ::COSS::CosPersistencePID::PID p);
- void store (in ::COSS::CosPersistencePID::PID p);
- void restore (in ::COSS::CosPersistencePID::PID p);
- void delete (in ::COSS::CosPersistencePID::PID p);
- };
-
- interface SD {
- void pre_store();
- void post_restore();
- };
-};
-
-
-// CosPersistencePOM Module, p 5-15 CORBAservices,
-// Persistent Object Service V1.0, 3/94
-
-// #include "CosPersistencePDS.idl"
-
-// CosPersistencePDS.idl // #includes CosPersistencePID.idl
-
-module CosPersistencePOM {
-
-// interface Object;
-
- interface POM {
- ::COSS::CosPersistencePDS::PDS connect (
- in Object obj,
- in ::COSS::CosPersistencePID::PID p);
- void disconnect (
- in Object obj,
- in ::COSS::CosPersistencePID::PID p);
- void store (
- in Object obj,
- in ::COSS::CosPersistencePID::PID p);
- void restore (
- in Object obj,
- in ::COSS::CosPersistencePID::PID p);
- void delete (
- in Object obj,
- in ::COSS::CosPersistencePID::PID p);
- };
- };
-
-// CosPersistencePDS_DA Module, p 5-22 CORBAservices,
-// Persistent Object Service, V1.0, 3/94
-
-// #include "CosPersistencePDS.idl"
-// CosPersistencePDS.idl // #includes CosPersistencePID.idl
-
-module CosPersistencePDS_DA {
-
- typedef string DAObjectID;
-
- interface PID_DA : ::COSS::CosPersistencePID::PID {
- attribute DAObjectID oid;
- };
-
- interface DAObject {
- boolean dado_same(in DAObject d);
- DAObjectID dado_oid();
- PID_DA dado_pid();
- void dado_remove();
- void dado_free();
- };
-
- interface DAObjectFactory {
- DAObject create();
- };
-
- interface DAObjectFactoryFinder {
- DAObjectFactory find_factory(in string key);
- };
-
- interface PDS_DA : ::COSS::CosPersistencePDS::PDS {
- DAObject get_data();
- void set_data(in DAObject new_data);
- DAObject lookup(in DAObjectID id);
- PID_DA get_pid();
- PID_DA get_object_pid(in DAObject dao);
- DAObjectFactoryFinder data_factories();
- };
-
- typedef sequence<string> AttributeNames;
- interface DynamicAttributeAccess {
- AttributeNames attribute_names();
- any attribute_get(in string name);
- void attribute_set(in string name, in any value);
- };
-
- typedef string ClusterID;
- typedef sequence<ClusterID> ClusterIDs;
- interface PDS_ClusteredDA : PDS_DA{
- ClusterID cluster_id();
- string cluster_kind();
- ClusterIDs clusters_of();
- PDS_ClusteredDA create_cluster(in string kind);
- PDS_ClusteredDA open_cluster(in ClusterID cluster);
- PDS_ClusteredDA copy_cluster(
- in PDS_DA source);
- };
-};
-
-// CosPersistenceDDO Module, p 5-32 CORBAservices, Persistent Object Service V1.0, 3/94
-
-// #include "CosPersistencePID.idl"
-module CosPersistenceDDO {
-
- interface DDO {
- attribute string object_type;
- attribute ::COSS::CosPersistencePID::PID p;
- short add_data();
- short add_data_property (in short data_id);
- short get_data_count();
- short get_data_property_count (in short data_id);
- void get_data_property (in short data_id,
- in short property_id,
- out string property_name,
- out any property_value);
- void set_data_property (in short data_id,
- in short property_id,
- in string property_name,
- in any property_value);
- void get_data (in short data_id,
- out string data_name,
- out any data_value);
- void set_data (in short data_id,
- in string data_name,
- in any data_value);
- };
-};
-
-// CosPersistenceDS_CLI module, p 5-34 CORBAservices,
-// Persistent Object Service V1.0, 3/94
-
-// #include "CosPersistenceDDO.idl"
-// CosPersistenceDDO.idl // #includes CosPersistencePID.idl
-
-module CosPersistenceDS_CLI {
- interface UserEnvironment {
- void set_option (in long option,in any value);
- void get_option (in long option,out any value);
- void release();
- };
-
- interface Connection {
- void set_option (in long option,in any value);
- void get_option (in long option,out any value);
- };
-
- interface ConnectionFactory {
- Connection create_object (
- in UserEnvironment user_envir);
- };
-
- interface Cursor {
- void set_position (in long position,in any value);
- ::COSS::CosPersistenceDDO::DDO fetch_object();
- };
-
- interface CursorFactory {
- Cursor create_object (
- in Connection connection);
- };
-
- interface PID_CLI : ::COSS::CosPersistencePID::PID {
- attribute string datastore_id;
- attribute string id;
- };
-
-
-
- interface Datastore_CLI {
- void connect (in Connection connection,
- in string datastore_id,
- in string user_name,
- in string authentication);
- void disconnect (in Connection connection);
- Connection get_connection (
- in string datastore_id,
- in string user_name);
- void add_object (in Connection connection,
- in ::COSS::CosPersistenceDDO::DDO data_obj);
- void delete_object (
- in Connection connection,
- in ::COSS::CosPersistenceDDO::DDO data_obj);
- void update_object (
- in Connection connection,
- in ::COSS::CosPersistenceDDO::DDO data_obj);
- void retrieve_object(
- in Connection connection,
- in ::COSS::CosPersistenceDDO::DDO data_obj);
- Cursor select_object(
- in Connection connection,
- in string key);
- void transact (in UserEnvironment user_envir,
- in short completion_type);
- void assign_PID (in PID_CLI p);
- void assign_PID_relative (
- in PID_CLI source_pid,
- in PID_CLI target_pid);
- boolean is_identical_PID (
- in PID_CLI pid_1,
- in PID_CLI pid_2);
- string get_object_type (in PID_CLI p);
- void register_mapping_schema (in string schema_file);
- Cursor execute (in Connection connection,
- in string command);
- };
-
-};
-
-
-// CosLifeCycle Module, p 6-10 CORBAservices, LifeCycle Service V1.0, 3/94
-
-// #include "Naming.idl"
-
-module CosLifeCycle
-{
- typedef ::COSS::CosNaming::Name Key;
- typedef Object Factory;
- typedef sequence <Factory> Factories;
- typedef struct NVP {
- ::COSS::CosNaming::Istring name;
- any value;
- } NameValuePair;
- typedef sequence <NameValuePair> Criteria;
-
- exception NoFactory {
- Key search_key;
- };
- exception NotCopyable { string reason; };
- exception NotMovable { string reason; };
- exception NotRemovable { string reason; };
- exception InvalidCriteria{
- Criteria invalid_criteria;
- };
- exception CannotMeetCriteria {
- Criteria unmet_criteria;
- };
-
-
- interface FactoryFinder {
- Factories find_factories(in Key factory_key)
- raises(NoFactory);
- };
-
- interface LifeCycleObject {
- LifeCycleObject copy(in FactoryFinder there,
- in Criteria the_criteria)
- raises(NoFactory, NotCopyable, InvalidCriteria,
- CannotMeetCriteria);
- void move(in FactoryFinder there,
- in Criteria the_criteria)
- raises(NoFactory, NotMovable, InvalidCriteria,
- CannotMeetCriteria);
- void remove()
- raises(NotRemovable);
- };
-
- interface GenericFactory {
- boolean supports(in Key k);
- Object create_object(
- in Key k,
- in Criteria the_criteria)
- raises (NoFactory, InvalidCriteria,
- CannotMeetCriteria);
- };
-};
-
-
-
-// LifeCycleService Module, p 6- 55 CORBAservices, Life Cycle
-// Service V1.0, 3/94
-
-// #include "LifeCycle.idl"
-
-module LifeCycleService {
-
- typedef sequence <::COSS::CosLifeCycle::NameValuePair> PolicyList;
- typedef sequence <::COSS::CosLifeCycle::Key> Keys;
- typedef sequence <::COSS::CosLifeCycle::NameValuePair> PropertyList;
- typedef sequence <::COSS::CosNaming::NameComponent> NameComponents;
-
- interface LifeCycleServiceAdmin {
-
- attribute PolicyList policies;
-
- void bind_generic_factory(
- in ::COSS::CosLifeCycle::GenericFactory gf,
- in ::COSS::CosNaming::NameComponent name,
- in Keys key_set,
- in PropertyList other_properties)
- raises (::COSS::CosNaming::NamingContext::AlreadyBound, ::COSS::CosNaming::NamingContext::InvalidName);
-
- void unbind_generic_factory(
- in ::COSS::CosNaming::NameComponent name)
- raises (::COSS::CosNaming::NamingContext::NotFound, ::COSS::CosNaming::NamingContext::InvalidName);
-
- ::COSS::CosLifeCycle::GenericFactory resolve_generic_factory(
- in ::COSS::CosNaming::NameComponent name)
- raises (::COSS::CosNaming::NamingContext::NotFound, ::COSS::CosNaming::NamingContext::InvalidName);
-
- NameComponents list_generic_factories();
-
- boolean match_service (in ::COSS::CosLifeCycle::GenericFactory f);
-
- string get_hint();
-
- void get_link_properties(
- in ::COSS::CosNaming::NameComponent name,
- out Keys key_set,
- out PropertyList other_properties)
- raises (::COSS::CosNaming::NamingContext::NotFound, ::COSS::CosNaming::NamingContext::InvalidName);
- };
-};
-
-// CosTransactions Module, p 10-66
-// CORBAservices, Transaction Service V1.0, 3/94
-
-module CosTransactions {
-// DATATYPES
-enum Status {
- StatusActive,
- StatusMarkedRollback,
- StatusPrepared,
- StatusCommitted,
- StatusRolledBack,
- StatusUnknown,
- StatusNoTransaction
-};
-
-enum Vote {
- VoteCommit,
- VoteRollback,
- VoteReadOnly
-};
-
-// Standard exceptions
-exception TransactionRequired {};
-exception TransactionRolledBack {};
-exception InvalidTransaction {};
-
-// Heuristic exceptions
-exception HeuristicRollback {};
-exception HeuristicCommit {};
-exception HeuristicMixed {};
-exception HeuristicHazard {};
-
-// Exception from Orb operations
-exception WrongTransaction {};
-
-// Other transaction-specific exceptions
-exception SubtransactionsUnavailable {};
-exception NotSubtransaction {};
-exception Inactive {};
-exception NotPrepared {};
-exception NoTransaction {};
-exception InvalidControl {};
-exception Unavailable {};
-
-// Forward references for interfaces defined later in module
-interface Control;
-interface Terminator;
-interface Coordinator;
-interface Resource;
-interface RecoveryCoordinator;
-interface SubtransactionAwareResource;
-interface TransactionFactory;
-interface TransactionalObject;
-interface Current;
-
-// Current transaction pseudo object (PIDL)
- interface Current {
- void begin()
- raises(SubtransactionsUnavailable);
- void commit(in boolean report_heuristics)
- raises(
- NoTransaction,
- HeuristicMixed,
- HeuristicHazard
- );
- void rollback()
- raises(NoTransaction);
- void rollback_only()
- raises(NoTransaction);
-
- Status get_status();
- string get_transaction_name();
- void set_timeout(in unsigned long seconds);
-
- Control get_control();
- Control suspend();
- void resume(in Control which)
- raises(InvalidControl);
- };
-
- interface TransactionFactory {
- Control create(in unsigned long time_out);
- };
-
- interface Control {
- Terminator get_terminator()
- raises(Unavailable);
- Coordinator get_coordinator()
- raises(Unavailable);
- };
-
- interface Terminator {
- void commit(in boolean report_heuristics)
- raises(
- HeuristicMixed,
- HeuristicHazard
- );
- void rollback();
- };
-
-
- interface Coordinator {
-
- Status get_status();
- Status get_parent_status();
- Status get_top_level_status();
-
- boolean is_same_transaction(in Coordinator tc);
- boolean is_related_transaction(in Coordinator tc);
- boolean is_ancestor_transaction(in Coordinator tc);
- boolean is_descendant_transaction(in Coordinator tc);
- boolean is_top_level_transaction();
-
- unsigned long hash_transaction();
- unsigned long hash_top_level_tran();
-
- RecoveryCoordinator register_resource(in Resource r)
- raises(Inactive);
-
- void register_subtran_aware(in SubtransactionAwareResource r)
- raises(Inactive, NotSubtransaction);
-
- void rollback_only()
- raises(Inactive);
-
- string get_transaction_name();
-
- Control create_subtransaction()
- raises(SubtransactionsUnavailable, Inactive);
- };
-
- interface RecoveryCoordinator {
- Status replay_completion(in Resource r)
- raises(NotPrepared);
- };
-
-}; // end module CosTransactions
-
-
-// CosConcurrency Control Module, p 7-8 CORBAservices,
-// Concurrency Control Service V1.0, 3/94
-
-// #include <CosTransactions.idl>
-module CosConcurrencyControl {
-
- enum lock_mode {
- read,
- write,
- upgrade,
- intention_read,
- intention_write
- };
-
- exception LockNotHeld{};
-
- interface LockCoordinator
- {
- void drop_locks();
- };
-
- interface LockSet
- {
- void lock(in lock_mode mode);
- boolean try_lock(in lock_mode mode);
-
- void unlock(in lock_mode mode)
- raises(LockNotHeld);
- void change_mode(in lock_mode held_mode,
- in lock_mode new_mode)
- raises(LockNotHeld);
- LockCoordinator get_coordinator(
- in ::COSS::CosTransactions::Coordinator which);
- };
-
- interface TransactionalLockSet
- {
- void lock(in ::COSS::CosTransactions::Coordinator current,
- in lock_mode mode);
- boolean try_lock(in ::COSS::CosTransactions::Coordinator current,
- in lock_mode mode);
- void unlock(in ::COSS::CosTransactions::Coordinator current,
- in lock_mode mode)
- raises(LockNotHeld);
- void change_mode(in ::COSS::CosTransactions::Coordinator current,
- in lock_mode held_mode,
- in lock_mode new_mode)
- raises(LockNotHeld);
- LockCoordinator get_coordinator(
- in ::COSS::CosTransactions::Coordinator which);
- };
-
- interface LockSetFactory
- {
- LockSet create();
- LockSet create_related(in LockSet which);
- TransactionalLockSet create_transactional();
- TransactionalLockSet create_transactional_related(in
- TransactionalLockSet which);
- };
-};
-
-// CosObjectIdentity Module, p 9-19 CORBAservices, Relationship
-// Service V1.0, 3/94
-
-
-module CosObjectIdentity {
-
- typedef unsigned long ObjectIdentifier;
-
- interface IdentifiableObject {
- readonly attribute ObjectIdentifier constant_random_id;
- boolean is_identical (
- in IdentifiableObject other_object);
- };
-
-};
-
-
-// CosRelationships Module, p 9-21 CORBAservices, Relationship
-// Service V1.0, 3/94
-
-// #include <ObjectIdentity.idl>
-
-module CosRelationships {
-
- interface RoleFactory;
- interface RelationshipFactory;
- interface Relationship;
- interface Role;
- interface RelationshipIterator;
-
- typedef Object RelatedObject;
- typedef sequence<Role> Roles;
- typedef string RoleName;
- typedef sequence<RoleName> RoleNames;
-
- struct NamedRole {RoleName name; Role aRole;};
- typedef sequence<NamedRole> NamedRoles;
-
- struct RelationshipHandle {
- Relationship the_relationship;
- ::COSS::CosObjectIdentity::ObjectIdentifier constant_random_id;
- };
- typedef sequence<RelationshipHandle> RelationshipHandles;
-
- interface RelationshipFactory {
- struct NamedRoleType {
- RoleName name;
- ::CORBA::InterfaceDef named_role_type;
- };
- typedef sequence<NamedRoleType> NamedRoleTypes;
- readonly attribute ::CORBA::InterfaceDef relationship_type;
- readonly attribute unsigned short degree;
- readonly attribute NamedRoleTypes named_role_types;
- exception RoleTypeError {NamedRoles culprits;};
- exception MaxCardinalityExceeded {
- NamedRoles culprits;};
- exception DegreeError {unsigned short required_degree;};
- exception DuplicateRoleName {NamedRoles culprits;};
- exception UnknownRoleName {NamedRoles culprits;};
-
- Relationship create (in NamedRoles named_roles)
- raises (RoleTypeError,
- MaxCardinalityExceeded,
- DegreeError,
- DuplicateRoleName,
- UnknownRoleName);
- };
-
- interface Relationship :
- ::COSS::CosObjectIdentity::IdentifiableObject {
- exception CannotUnlink {
- Roles offending_roles;
- };
- readonly attribute NamedRoles named_roles;
- void destroy () raises(CannotUnlink);
- };
-
- interface Role {
- exception UnknownRoleName {};
- exception UnknownRelationship {};
- exception RelationshipTypeError {};
- exception CannotDestroyRelationship {
- RelationshipHandles offenders;
- };
- exception ParticipatingInRelationship {
- RelationshipHandles the_relationships;
- };
- readonly attribute RelatedObject related_object;
- RelatedObject get_other_related_object (
- in RelationshipHandle rel,
- in RoleName target_name)
- raises (UnknownRoleName,
- UnknownRelationship);
- Role get_other_role (in RelationshipHandle rel,
- in RoleName target_name)
- raises (UnknownRoleName, UnknownRelationship);
- void get_relationships (
- in unsigned long how_many,
- out RelationshipHandles rels,
- out RelationshipIterator iterator);
- void destroy_relationships()
- raises(CannotDestroyRelationship);
- void destroy() raises(ParticipatingInRelationship);
- boolean check_minimum_cardinality ();
- void link (in RelationshipHandle rel,
- in NamedRoles named_roles)
- raises(RelationshipFactory::MaxCardinalityExceeded,
- RelationshipTypeError);
- void unlink (in RelationshipHandle rel)
- raises (UnknownRelationship);
- };
-
- interface RoleFactory {
- exception NilRelatedObject {};
- exception RelatedObjectTypeError {};
- readonly attribute ::CORBA::InterfaceDef role_type;
- readonly attribute unsigned long max_cardinality;
- readonly attribute unsigned long min_cardinality;
-// the following isn't allowed in IDL,
-// readonly attribute sequence <::CORBA::InterfaceDef> related_object_types;
- typedef sequence <::CORBA::InterfaceDef> InterfaceDefSeq;
- readonly attribute InterfaceDefSeq related_object_types;
- Role create_role (in RelatedObject related_object)
- raises (NilRelatedObject, RelatedObjectTypeError);
- };
-
- interface RelationshipIterator {
- boolean next_one (out RelationshipHandle rel);
- boolean next_n (in unsigned long how_many,
- out RelationshipHandles rels);
- void destroy ();
- };
-
-};
-
-// CosCompoundExternalization Module, p 8-20 CORBAservices,
-// Externalization Service V1.0, 3/94
-
-// #include <Graphs.idl>
-// #include <Stream.idl>
-
-// CosGraphs Module, p 9-39 CORBAservices, Relationship Service
-// V1.0, 3/94
-
-// #include <Relationships.idl>
-// #include <ObjectIdentity.idl>
-
-module CosGraphs {
-
- interface TraversalFactory;
- interface Traversal;
- interface TraversalCriteria;
- interface Node;
- interface NodeFactory;
- interface Role;
- interface EdgeIterator;
-
- struct NodeHandle {
- Node the_node;
- ::COSS::CosObjectIdentity::ObjectIdentifier constant_random_id;
- };
- typedef sequence<NodeHandle> NodeHandles;
-
- struct NamedRole {
- Role the_role;
- ::COSS::CosRelationships::RoleName the_name;
- };
- typedef sequence<NamedRole> NamedRoles;
-
- struct EndPoint {
- NodeHandle the_node;
- NamedRole the_role;
- };
- typedef sequence<EndPoint> EndPoints;
-
- struct Edge {
- EndPoint from;
- ::COSS::CosRelationships::RelationshipHandle the_relationship;
- EndPoints relatives;
- };
- typedef sequence<Edge> Edges;
-
- enum PropagationValue {deep, shallow, none, inhibit};
- enum Mode {depthFirst, breadthFirst, bestFirst};
-
- interface TraversalFactory {
- Traversal create_traversal_on (
- in NodeHandle root_node,
- in TraversalCriteria the_criteria,
- in Mode how);
- };
-
- interface Traversal {
- typedef unsigned long TraversalScopedId;
- struct ScopedEndPoint {
- EndPoint point;
- TraversalScopedId id;
- };
- typedef sequence<ScopedEndPoint> ScopedEndPoints;
- struct ScopedRelationship {
- ::COSS::CosRelationships::RelationshipHandle
- scoped_relationship;
- TraversalScopedId id;
- };
- struct ScopedEdge {
- ScopedEndPoint from;
- ScopedRelationship the_relationship;
- ScopedEndPoints relatives;
- };
- typedef sequence<ScopedEdge> ScopedEdges;
- boolean next_one (out ScopedEdge the_edge);
- boolean next_n (in short how_many,
- out ScopedEdges the_edges);
- void destroy ();
- };
-
- interface TraversalCriteria {
- struct WeightedEdge {
- Edge the_edge;
- unsigned long weight;
- sequence<NodeHandle> next_nodes;
- };
- typedef sequence<WeightedEdge> WeightedEdges;
- void visit_node(in NodeHandle a_node,
- in Mode search_mode);
- boolean next_one (out WeightedEdge the_edge);
- boolean next_n (in short how_many,
- out WeightedEdges the_edges);
- void destroy();
- };
-
- interface Node: ::COSS::CosObjectIdentity::IdentifiableObject {
- typedef sequence<Role> Roles;
- exception NoSuchRole {};
- exception DuplicateRoleType {};
-
- readonly attribute ::COSS::CosRelationships::RelatedObject
- related_object;
- readonly attribute Roles roles_of_node;
- Roles roles_of_type (
- in ::CORBA::InterfaceDef role_type);
- void add_role (in Role a_role)
- raises (DuplicateRoleType);
- void remove_role (in ::CORBA::InterfaceDef of_type)
- raises (NoSuchRole);
- };
-
- interface NodeFactory {
- Node create_node (in Object related_object);
- };
-
- interface Role : ::COSS::CosRelationships::Role {
- void get_edges ( in long how_many,
- out Edges the_edges,
- out EdgeIterator the_rest);
- };
-
- interface EdgeIterator {
- boolean next_one (out Edge the_edge);
- boolean next_n ( in unsigned long how_many,
- out Edges the_edges);
- void destroy ();
- };
-
-};
-
-
-
-// CosStream Module, 8-15 CORBAservices,
-// Externalization Service V1.0, 3/94
-
-// #include <LifeCycle.idl>
-// #include <ObjectIdentity.idl>
-// #include <CompoundExternalization.idl>
-module CosStream {
- exception ObjectCreationError{};
- exception StreamDataFormatError{};
- interface StreamIO;
-
- interface Streamable: ::COSS::CosObjectIdentity::IdentifiableObject
- {
- readonly attribute ::COSS::CosLifeCycle::Key external_form_id;
- void externalize_to_stream(
- in StreamIO targetStreamIO);
- void internalize_from_stream(
- in StreamIO sourceStreamIO,
- in ::COSS::CosLifeCycle::FactoryFinder there)
- raises( ::COSS::CosLifeCycle::NoFactory,
- ObjectCreationError,
- StreamDataFormatError );
- };
-
- interface StreamableFactory {
- Streamable create_uninitialized();
- };
-
-
- interface StreamIO {
- void write_string(in string aString);
- void write_char(in char aChar);
- void write_octet(in octet anOctet);
- void write_unsigned_long(
- in unsigned long anUnsignedLong);
- void write_unsigned_short(
- in unsigned short anUnsignedShort);
- void write_long(in long aLong);
- void write_short(in short aShort);
- void write_float(in float aFloat);
- void write_double(in double aDouble);
- void write_boolean(in boolean aBoolean);
- void write_object(in Streamable aStreamable);
- // void write_graph(in ::COSS::CosCompoundExternalization::Node aNode);
- string read_string()
- raises(StreamDataFormatError);
- char read_char()
- raises(StreamDataFormatError );
- octet read_octet()
- raises(StreamDataFormatError );
- unsigned long read_unsigned_long()
- raises(StreamDataFormatError );
- unsigned short read_unsigned_short()
- raises( StreamDataFormatError );
- long read_long()
- raises(StreamDataFormatError );
- short read_short()
- raises(StreamDataFormatError );
- float read_float()
- raises(StreamDataFormatError );
- double read_double()
- raises(StreamDataFormatError );
- boolean read_boolean()
- raises(StreamDataFormatError );
- Streamable read_object(
- in ::COSS::CosLifeCycle::FactoryFinder there,
- in Streamable aStreamable)
- raises(StreamDataFormatError );
-// void read_graph(
-// in ::COSS::CosCompoundExternalization::Node starting_node,
-// in ::COSS::CosLifeCycle::FactoryFinder there)
-// raises(StreamDataFormatError );
- };
-};
-
-module CosCompoundExternalization {
- interface Node;
- interface Role;
- interface Relationship;
- interface PropagationCriteriaFactory;
-
- struct RelationshipHandle {
- Relationship theRelationship;
- ::COSS::CosObjectIdentity::ObjectIdentifier constantRandomId;
- };
-
- interface Node : ::COSS::CosGraphs::Node, ::COSS::CosStream::Streamable{
- void externalize_node (in ::COSS::CosStream::StreamIO sio);
- void internalize_node (in ::COSS::CosStream::StreamIO sio,
- in ::COSS::CosLifeCycle::FactoryFinder there,
- out ::COSS::CosGraphs::Node::Roles rolesOfNode)
- raises (::COSS::CosLifeCycle::NoFactory);
- };
-
- interface Role : ::COSS::CosGraphs::Role {
- void externalize_role (in ::COSS::CosStream::StreamIO sio);
- void internalize_role (in ::COSS::CosStream::StreamIO sio);
- ::COSS::CosGraphs::PropagationValue externalize_propagation (
- in RelationshipHandle rel,
- in ::COSS::CosRelationships::RoleName toRoleName,
- out boolean sameForAll);
- };
-
- interface Relationship :
- ::COSS::CosRelationships::Relationship {
- void externalize_relationship (
- in ::COSS::CosStream::StreamIO sio);
- void internalize_relationship(
- in ::COSS::CosStream::StreamIO sio,
- in ::COSS::CosGraphs::NamedRoles newRoles);
- ::COSS::CosGraphs::PropagationValue externalize_propagation (
- in ::COSS::CosRelationships::RoleName fromRoleName,
- in ::COSS::CosRelationships::RoleName toRoleName,
- out boolean sameForAll);
- };
-
- interface PropagationCriteriaFactory {
- ::COSS::CosGraphs::TraversalCriteria create_for_externalize( );
- };
-
-};
-
-// CosExternalization Module, 8-12 CORBAservices,
-// Externalization Service V1.0, 3/94
-
-
-// #include <LifeCycle.idl>
-// #include <Stream.idl>
-module CosExternalization {
- exception InvalidFileNameError{};
- exception ContextAlreadyRegistered{};
- interface Stream: ::COSS::CosLifeCycle::LifeCycleObject{
- void externalize(
- in ::COSS::CosStream::Streamable theObject);
- ::COSS::CosStream::Streamable internalize(
- in ::COSS::CosLifeCycle::FactoryFinder there)
- raises( ::COSS::CosLifeCycle::NoFactory,
- ::COSS::CosStream::StreamDataFormatError );
- void begin_context()
- raises( ContextAlreadyRegistered);
- void end_context();
- void flush();
- };
- interface StreamFactory {
- Stream create();
- };
- interface FileStreamFactory {
- Stream create(
- in string theFileName)
- raises( InvalidFileNameError );
- };
-};
-
-// CosContainment Module, p 9- 48 CORBAservices, Relationship
-// Service V1.0, 3/94
-
-// #include <Graphs.idl>
-
-module CosContainment {
-
- interface Relationship :
- ::COSS::CosRelationships::Relationship {};
-
- interface ContainsRole : ::COSS::CosGraphs::Role {};
-
- interface ContainedInRole : ::COSS::CosGraphs::Role {};
-
-};
-
-// CosExternalizationContainment Module, p 8-26 CORBAservices,
-// Externalization Service V1.0, 3/94
-
-// #include <Containment.idl>
-// #include <CompoundExternalization.idl>
-
-module CosExternalizationContainment {
-
- interface Relationship :
- ::COSS::CosCompoundExternalization::Relationship,
- ::COSS::CosContainment::Relationship {};
-
- interface ContainsRole :
- ::COSS::CosCompoundExternalization::Role,
- ::COSS::CosContainment::ContainsRole {};
-
- interface ContainedInRole :
- ::COSS::CosCompoundExternalization::Role,
- ::COSS::CosContainment::ContainedInRole {};
-};
-
-// CosReference Module, p 9-50 CORBAservices,
-// Relationship Service V1.0, 3/94
-
-// #include <Graphs.idl>
-
-module CosReference {
-
- interface Relationship :
- ::COSS::CosRelationships::Relationship {};
-
- interface ReferencesRole : ::COSS::CosGraphs::Role {};
-
- interface ReferencedByRole : ::COSS::CosGraphs::Role {};
-
-};
-
-// CosExternalizationReference Module, p 8-28 CORBAservices,
-// Externalization Service V1.0, 3/94
-
-// #include <Reference.idl>
-// #include <CompoundExternalization.idl>
-
-module CosExternalizationReference {
-
- interface Relationship :
- ::COSS::CosCompoundExternalization::Relationship,
- ::COSS::CosReference::Relationship {};
-
- interface ReferencesRole :
- ::COSS::CosCompoundExternalization::Role,
- ::COSS::CosReference::ReferencesRole {};
-
- interface ReferencedByRole :
- ::COSS::CosCompoundExternalization::Role,
- ::COSS::CosReference::ReferencedByRole {};
-};
-
-// PIDL for CosTSInteroperation Module, p 10-59
-// CORBAservices, Transaction Service V1.0, 3/94
-module CosTSInteroperation { // PIDL
- struct otid_t {
- long formatID; /*format identifier. 0 is OSI TP */
- long bequal_length;
- sequence <octet> tid;
- };
- struct TransIdentity {
- ::COSS::CosTransactions::Coordinator coordinator;
- ::COSS::CosTransactions::Terminator terminator;
- otid_t otid;
- };
- struct PropagationContext {
- unsigned long timeout;
- TransIdentity current;
- sequence <TransIdentity> parents;
- any implementation_specific_data;
- };
-};
-
-// PIDL for CosTSPortability Module, p 10-63
-// CORBAservices, Transaction Service V1.0, 3/94
-
-module CosTSPortability { // PIDL
- typedef long ReqId;
-
- interface Sender {
- void sending_request(in ReqId id,
- out ::COSS::CosTSInteroperation::PropagationContext ctx);
- void received_reply(in ReqId id,
- in ::COSS::CosTSInteroperation::PropagationContext ctx,
- in ::CORBA::Environment env);
- };
-
- interface Receiver {
- void received_request(in ReqId id,
- in ::COSS::CosTSInteroperation::PropagationContext ctx);
- void sending_reply(in ReqId id,
- out::COSS::CosTSInteroperation::PropagationContext ctx);
- };
-};
-
-// CosCompoundLifeCycle Module, p 6-30 CORBAservices,
-// Life Cycle Service V1.0, 3/94
-
-// #include <LifeCycle.idl>
-// #include <Relationships.idl>
-// #include <Graphs.idl>
-
-module CosCompoundLifeCycle {
- interface OperationsFactory;
- interface Operations;
- interface Node;
- interface Role;
- interface Relationship;
- interface PropagationCriteriaFactory;
-
- enum Operation {copy, move, remove};
-
- struct RelationshipHandle {
- Relationship the_relationship;
- ::COSS::CosObjectIdentity::ObjectIdentifier constant_random_id;
- };
-
- interface OperationsFactory {
- Operations create_compound_operations();
- };
-
- interface Operations {
- Node copy (
- in Node starting_node,
- in ::COSS::CosLifeCycle::FactoryFinder there,
- in ::COSS::CosLifeCycle::Criteria the_criteria)
- raises (::COSS::CosLifeCycle::NoFactory,
- ::COSS::CosLifeCycle::NotCopyable,
- ::COSS::CosLifeCycle::InvalidCriteria,
- ::COSS::CosLifeCycle::CannotMeetCriteria);
- void move (
- in Node starting_node,
- in ::COSS::CosLifeCycle::FactoryFinder there,
- in ::COSS::CosLifeCycle::Criteria the_criteria)
- raises (::COSS::CosLifeCycle::NoFactory,
- ::COSS::CosLifeCycle::NotMovable,
- ::COSS::CosLifeCycle::InvalidCriteria,
- ::COSS::CosLifeCycle::CannotMeetCriteria);
- void remove (in Node starting_node)
- raises (::COSS::CosLifeCycle::NotRemovable);
- void destroy();
- };
-
- interface Node : ::COSS::CosGraphs::Node {
- exception NotLifeCycleObject {};
- void copy_node ( in ::COSS::CosLifeCycle::FactoryFinder there,
- in ::COSS::CosLifeCycle::Criteria the_criteria,
- out Node new_node,
- out ::COSS::CosGraphs::Node::Roles roles_of_new_node)
- raises (::COSS::CosLifeCycle::NoFactory,
- ::COSS::CosLifeCycle::NotCopyable,
- ::COSS::CosLifeCycle::InvalidCriteria,
- ::COSS::CosLifeCycle::CannotMeetCriteria);
- void move_node (in ::COSS::CosLifeCycle::FactoryFinder there,
- in ::COSS::CosLifeCycle::Criteria the_criteria)
- raises (::COSS::CosLifeCycle::NoFactory,
- ::COSS::CosLifeCycle::NotMovable,
- ::COSS::CosLifeCycle::InvalidCriteria,
- ::COSS::CosLifeCycle::CannotMeetCriteria);
- void remove_node ()
- raises (::COSS::CosLifeCycle::NotRemovable);
- ::COSS::CosLifeCycle::LifeCycleObject get_life_cycle_object()
- raises (NotLifeCycleObject);
- };
-
- interface Role : ::COSS::CosGraphs::Role {
- Role copy_role (in ::COSS::CosLifeCycle::FactoryFinder there,
- in ::COSS::CosLifeCycle::Criteria the_criteria)
- raises (::COSS::CosLifeCycle::NoFactory,
- ::COSS::CosLifeCycle::NotCopyable,
- ::COSS::CosLifeCycle::InvalidCriteria,
- ::COSS::CosLifeCycle::CannotMeetCriteria);
- void move_role (in ::COSS::CosLifeCycle::FactoryFinder there,
- in ::COSS::CosLifeCycle::Criteria the_criteria)
- raises (::COSS::CosLifeCycle::NoFactory,
- ::COSS::CosLifeCycle::NotMovable,
- ::COSS::CosLifeCycle::InvalidCriteria,
- ::COSS::CosLifeCycle::CannotMeetCriteria);
- ::COSS::CosGraphs::PropagationValue life_cycle_propagation (
- in Operation op,
- in RelationshipHandle rel,
- in ::COSS::CosRelationships::RoleName to_role_name,
- out boolean same_for_all);
- };
-
- interface Relationship :
- ::COSS::CosRelationships::Relationship {
- Relationship copy_relationship (
- in ::COSS::CosLifeCycle::FactoryFinder there,
- in ::COSS::CosLifeCycle::Criteria the_criteria,
- in ::COSS::CosGraphs::NamedRoles new_roles)
- raises (::COSS::CosLifeCycle::NoFactory,
- ::COSS::CosLifeCycle::NotCopyable,
- ::COSS::CosLifeCycle::InvalidCriteria,
- ::COSS::CosLifeCycle::CannotMeetCriteria);
- void move_relationship (
- in ::COSS::CosLifeCycle::FactoryFinder there,
- in ::COSS::CosLifeCycle::Criteria the_criteria)
- raises (::COSS::CosLifeCycle::NoFactory,
- ::COSS::CosLifeCycle::NotMovable,
- ::COSS::CosLifeCycle::InvalidCriteria,
- ::COSS::CosLifeCycle::CannotMeetCriteria);
- ::COSS::CosGraphs::PropagationValue life_cycle_propagation (
- in Operation op,
- in ::COSS::CosRelationships::RoleName from_role_name,
- in ::COSS::CosRelationships::RoleName to_role_name,
- out boolean same_for_all);
- };
-
- interface PropagationCriteriaFactory {
- ::COSS::CosGraphs::TraversalCriteria create(in Operation op);
- };
-
-};
-
-// CosLifeCycleContainment Module, p 6-42 CORBAservices,
-// Life Cycle Service V1.0, 3/94
-
-// #include <Containment.idl>
-// #include <CompoundLifeCycle.idl>
-
-module CosLifeCycleContainment {
-
- interface Relationship :
- ::COSS::CosCompoundLifeCycle::Relationship,
- ::COSS::CosContainment::Relationship {};
-
- interface ContainsRole :
- ::COSS::CosCompoundLifeCycle::Role,
- ::COSS::CosContainment::ContainsRole {};
-
- interface ContainedInRole :
- ::COSS::CosCompoundLifeCycle::Role,
- ::COSS::CosContainment::ContainedInRole {};
-};
-
-// CosLifeCycleReference Module, p 6-44 CORBAservices,
-// Life Cycle Service V1.0, 3/94
-
-// #include <Reference.idl>
-// #include <CompoundLifeCycle.idl>
-
-module CosLifeCycleReference {
-
- interface Relationship :
- ::COSS::CosCompoundLifeCycle::Relationship,
- ::COSS::CosReference::Relationship {};
-
- interface ReferencesRole :
- ::COSS::CosCompoundLifeCycle::Role,
- ::COSS::CosReference::ReferencesRole {};
-
- interface ReferencedByRole :
- ::COSS::CosCompoundLifeCycle::Role,
- ::COSS::CosReference::ReferencedByRole {};
-};
-
-
-}; // end module COSS
diff --git a/lib/ic/test/ic_SUITE_data/attr.idl b/lib/ic/test/ic_SUITE_data/attr.idl
deleted file mode 100644
index 0a1edc787c..0000000000
--- a/lib/ic/test/ic_SUITE_data/attr.idl
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-interface I1 {
- attribute long a1, a2;
- attribute char a3;
-};
-
-interface I2 : I1 {
- attribute short a4;
- readonly attribute char a5;
-};
-
diff --git a/lib/ic/test/ic_SUITE_data/c_err1.idl b/lib/ic/test/ic_SUITE_data/c_err1.idl
deleted file mode 100644
index d50c51c807..0000000000
--- a/lib/ic/test/ic_SUITE_data/c_err1.idl
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-//
-// This file forces the bad_tk_match. This triggers when the type of
-// the expression does not match the declared type of the constant
-//
-
-const long c1 = TRUE;
-const unsigned short c1b= TRUE;
-const boolean c2 = +5;
-const long c3 = 'c';
-const float c5 = 3;
-const unsigned long c6 = -2; // Maybe not checked in compiler or suite
-
-const boolean c4 = 1 | 2;
-
-
-// Now define some correct constants for use in reference checking
-
-const long longC = -9;
-const short shortC = -9;
-const unsigned long ulongC = 1;
-const unsigned short ushortC = 0;
-
-const float floatC = 5.1;
-const double doubleC = -2.111;
-
-const boolean boolC = TRUE;
-
-const char charC = 'f';
-const string stringC = "hej";
-const string<9> stringCb = "hejdu";
-
-// Check the reference errors
-
-const long c19 = floatC;
-const short c20 = doubleC;
-const unsigned long c21 = charC;
-const unsigned short c22 = stringC;
-const float c23 = stringCb;
-const double c24 = boolC;
-const boolean c25 = longC;
-const char c26 = shortC;
-const string c27 = ushortC;
-const string<9> c28 = ulongC;
-const long c29 = 3+floatC;
diff --git a/lib/ic/test/ic_SUITE_data/c_err2.idl b/lib/ic/test/ic_SUITE_data/c_err2.idl
deleted file mode 100644
index 84c12421ef..0000000000
--- a/lib/ic/test/ic_SUITE_data/c_err2.idl
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-//
-// Checks bad type of operands
-//
-
-
-const long c1 = 1 + TRUE;
-const boolean c3 = TRUE | FALSE | 19.8;
-const long c4 = 1 << TRUE;
-const long c5 = TRUE >> TRUE;
-
-
diff --git a/lib/ic/test/ic_SUITE_data/c_err3.idl b/lib/ic/test/ic_SUITE_data/c_err3.idl
deleted file mode 100644
index 910f7abcf1..0000000000
--- a/lib/ic/test/ic_SUITE_data/c_err3.idl
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-//
-// Checks ill-formed expressions (type conflict in operands)
-//
-
-
-const long c1 = 5|TRUE;
-const long c2 = 5&TRUE;
-const long c3 = 5^TRUE;
-
diff --git a/lib/ic/test/ic_SUITE_data/c_norm.idl b/lib/ic/test/ic_SUITE_data/c_norm.idl
deleted file mode 100644
index b573ac3f3d..0000000000
--- a/lib/ic/test/ic_SUITE_data/c_norm.idl
+++ /dev/null
@@ -1,164 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-//
-// Check normal values and expressions for constants
-//
-
-// Integer types
-const long co1 = 077;
-const long ch1 = 0xf1;
-const long ch2 = 0XAB;
-const long c1 = 1;
-const short c2 = 3;
-const unsigned long c3 = 1;
-const unsigned short c4 = 3;
-
-// Unary ops
-const long c1hb = -0x1;
-const long c1b = -1;
-const short c2b = -3;
-const long c1c = +1;
-const short c2c = +3;
-// ~ not supported
-
-// Check binary ops
-const long c1d = 9+1-3;
-const long c1hd = 9+1-0xf3;
-const short c2d = 7+3;
-const short c2e = 7*3;
-const long c1e = 1 | 7;
-const long c1f = 7 & 9;
-const long c1g = (1 | 7) & 9;
-const long c1h = 1^7;
-
-//floats
-const float c5 = 1.9;
-const double c6 = 1.9;
-const float c5b = -1.9;
-const double c6b = -1.9;
-
-// Check type operand casting
-const float c5c = 1/(9+2) * 2;
-const double c6c = 1.9-1;
-//const double c6d = 1; // Does not work yet
-
-// Booleans and expressions
-const boolean c7 = TRUE;
-const boolean c7b = FALSE;
-const boolean c7c = TRUE | FALSE;
-const boolean c7d = TRUE & FALSE;
-const boolean c7e = TRUE&TRUE | FALSE&TRUE;
-const boolean c7f = TRUE&TRUE ^ FALSE&TRUE;
-
-// Character and string
-const char c8 = 'c';
-const char c8b = '\n';
-const string c9 = "hej";
-const string<9> c9b = "hejdu";
-
-
-//
-// Check that value references work
-//
-
-const long rc1 = c1g;
-const long rc1h = c1h + 9;
-const short rc2 = c2;
-const unsigned long rc3 = c3;
-const unsigned short rc4 = c4;
-
-
-const float rc5c = c5c;
-const double rc6c = c6c;
-const double rc6d = c6c+1.3;
-
-const boolean rc7 = c7;
-const boolean rc7c = c7c | TRUE;
-
-const char rc8 = c8;
-const char rc8b = c8b;
-const string rc9 = c9;
-const string<9> rc9b = c9b;
-
-
-
-
-//
-// Now check that all typerefs work
-//
-
-typedef long longT;
-typedef short shortT;
-typedef unsigned long ulongT;
-typedef unsigned short ushortT;
-
-typedef float floatT;
-typedef double doubleT;
-
-typedef char charT;
-typedef string stringT;
-
-typedef boolean booleanT;
-
-const longT cc1 = 1;
-const shortT cc2 = 3;
-const ::longT cc1b = -1;
-const ::shortT cc2b = -3;
-
-const floatT cc5 = 1.9;
-const doubleT cc6 = 1.9;
-const floatT cc5b = -1.9;
-const doubleT cc6b = -1.9;
-const floatT cc5c = 1/(9+2) * 2;
-const doubleT cc6c = 1.9-1;
-
-const booleanT cc7 = TRUE;
-const booleanT cc7b = TRUE;
-const booleanT cc7c = TRUE | FALSE;
-const booleanT cc7d = TRUE & FALSE;
-const booleanT cc7e = TRUE&TRUE | FALSE&TRUE;
-
-
-const charT cc8 = 'c';
-const charT cc8b = '\n';
-const stringT cc9 = "hej";
-const stringT cc9b = "hejdu";
-
-
-//
-// Check value casting
-//
-const long longC = -9;
-const short shortC = -9;
-const unsigned long ulongC = 1;
-const unsigned short ushortC = 0;
-
-const float floatC = 5.1;
-const double doubleC = -2.111;
-
-const long c20 = shortC;
-const long c21 = ulongC;
-const long c22 = ushortC;
-const short c23 = ushortC;
-const double c34 = floatC;
-
-
-
diff --git a/lib/ic/test/ic_SUITE_data/enum.idl b/lib/ic/test/ic_SUITE_data/enum.idl
deleted file mode 100644
index 397212baf8..0000000000
--- a/lib/ic/test/ic_SUITE_data/enum.idl
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-
-enum E1 {kalle, sune};
-
-enum E2 { el0, el1, el2, el3, el4, el5, el6, el7, el8, el9, el10, el11, el12, el13,
-el14, el15, el16, el17, el18, el19, el20, el21, el22, el23, el24, el25, el26, el27,
-el28, el29, el30, el31, el32, el33, el34, el35, el36, el37, el38, el39, el40, el41,
-el42, el43, el44, el45, el46, el47, el48, el49, el50, el51, el52, el53, el54, el55,
-el56, el57, el58, el59};
-
-
-
-
-
diff --git a/lib/ic/test/ic_SUITE_data/forward.idl b/lib/ic/test/ic_SUITE_data/forward.idl
deleted file mode 100644
index e9e8edb89e..0000000000
--- a/lib/ic/test/ic_SUITE_data/forward.idl
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-//
-// Check that forward declarations are handled correctly
-//
-
-
-interface i1;
-
-
-interface i1 {
- typedef long T;
-};
-
-
-interface i1;
-
diff --git a/lib/ic/test/ic_SUITE_data/include.idl b/lib/ic/test/ic_SUITE_data/include.idl
deleted file mode 100644
index 292de177c2..0000000000
--- a/lib/ic/test/ic_SUITE_data/include.idl
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-// Check that errors are given with the correct file name reference
-
-#include "include2.idl"
-
-
-typedef T1 T7;
-typedef long T7;
-typedef long T111;
-
-
-
diff --git a/lib/ic/test/ic_SUITE_data/include2.idl b/lib/ic/test/ic_SUITE_data/include2.idl
deleted file mode 100644
index 37caa0bf54..0000000000
--- a/lib/ic/test/ic_SUITE_data/include2.idl
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-// Check that errors are given with the correct file name reference
-
-#include "include3.idl"
-
-
-typedef T7 T1;
-
diff --git a/lib/ic/test/ic_SUITE_data/include3.idl b/lib/ic/test/ic_SUITE_data/include3.idl
deleted file mode 100644
index 18424b3318..0000000000
--- a/lib/ic/test/ic_SUITE_data/include3.idl
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-// Check that errors are given with the correct file name reference
-
-typedef T7 T1;
-
-
-
diff --git a/lib/ic/test/ic_SUITE_data/inherit.idl b/lib/ic/test/ic_SUITE_data/inherit.idl
deleted file mode 100644
index 93fd4b42ba..0000000000
--- a/lib/ic/test/ic_SUITE_data/inherit.idl
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-
-interface I1 {
- typedef long T1;
- typedef struct S1 {long a; boolean b;} T2;
- typedef string StringT, StringT_arr[10];
-
- T1 op1( in StringT a, inout char b, out StringT_arr c );
- T2 op2( in char a, inout char b, out StringT_arr c );
-
- const T1 LongC = 10;
- const StringT StringC = "Hola bambino";
-
-};
-
-
-interface I2 : I1 {
- T1 op3( in long a);
-
- const long c1 = LongC;
- const string c2 = StringC;
-};
-
-interface I3 : I1 {};
-
-interface I4 : I3, I2 {}; // Check that branced inherit works
-
-
-
-// Now use cnstants to check that inheritance works as expected
-
-module m1 {
- interface I1 {
- typedef long T1;
-
- const T1 c1 = 9;
- };
-
- interface I2 : I1 {
- const T1 c2 = c1+5; // c2 = 14
- const long c3 = c2+c1+4; // c3 = 27
- };
-
- interface I3 : I2, I1 {
- const long c1 = 50; // Overrides I1::c1
- const T1 c4 = c1+c2+c3; // c4=91
- const T1 c5 = I1::c1+c1+c2+c3; // 100
- };
-};
-
diff --git a/lib/ic/test/ic_SUITE_data/inherit_err.idl b/lib/ic/test/ic_SUITE_data/inherit_err.idl
deleted file mode 100644
index 3b4989dd8b..0000000000
--- a/lib/ic/test/ic_SUITE_data/inherit_err.idl
+++ /dev/null
@@ -1,72 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-//
-// Ops and attributes must not be redefined (shadowed)
-
-interface I1 {
- long op1( in long a, inout char b, out boolean c );
- long op2( in char a, inout char b, out boolean c );
- attribute long a1, a2;
- readonly attribute char a3;
-};
-
-interface I2 : I1 {
- long op1( in float a, inout char b, out boolean c );
- long op2( in char a, inout char b, out boolean c );
- attribute long a1, a2;
- readonly attribute char a3;
-};
-
-interface I3 : I1 {
- long op3 (in string<19> b);
-};
-
-
-interface I4 : I3 {
- long op1( in float a, inout char b, out boolean c );
- long op2( in char a, inout char b, out boolean c );
- attribute long a1, a2;
- readonly attribute char a3;
-
- long op3 (in string<19> b);
-};
-
-
-interface I11 {
- long op1( in float a, inout char b, out boolean c );
- long op2( in char a, inout char b, out boolean c );
- attribute long a1, a2;
- readonly attribute char a3;
-};
-
-
-
-interface I5 : I1, I11 {};
-
-interface I6 : I1 {
- const long op1=0;
- const long op2=0;
- const long a1=0;
- const long a2=0;
- const long a3=0;
-};
-
-
diff --git a/lib/ic/test/ic_SUITE_data/inherit_warn.idl b/lib/ic/test/ic_SUITE_data/inherit_warn.idl
deleted file mode 100644
index 07f57f1a7d..0000000000
--- a/lib/ic/test/ic_SUITE_data/inherit_warn.idl
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-//
-// Checks that shadow warnings comes out as expected
-//
-
-
-interface I1 {
- typedef long T1;
- typedef struct S1 {long a; boolean b;} T2;
- typedef string StringT, StringT_arr[10];
-
- T1 op1( in StringT a, inout char b, out StringT_arr c );
- T2 op2( in char a, inout char b, out StringT_arr c );
-
- const T1 LongC = 10;
- const StringT StringC = "Hola bambino";
-
-};
-
-
-interface I2 : I1 {
- typedef char T1; // Shadows I1::T1
- const boolean StringC = FALSE; // shadows I1::StringC
-
- T1 op3( in long a);
-
- const long c1 = LongC;
- const boolean c2 = StringC;
-};
-
-interface I3 : I2 {}; // More shadows
-
-interface I4 : I1 {
- T1 op4();
- const T1 c2 = 66;
-};
-
-interface I5 : I4 {
- typedef string T1; // Shadows I1::T1
- const char LongC = 'a'; // Shadows I1::LongC
-};
-
-
-interface I6 : I4, I3 {
-};
-
diff --git a/lib/ic/test/ic_SUITE_data/mult_ids.idl b/lib/ic/test/ic_SUITE_data/mult_ids.idl
deleted file mode 100644
index 577e1031fb..0000000000
--- a/lib/ic/test/ic_SUITE_data/mult_ids.idl
+++ /dev/null
@@ -1,93 +0,0 @@
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-//
-// Check that multiply defined identifiers are detected
-//
-
-typedef long T1;
-typedef long T1;
-typedef long T2;
-exception T2 {};
-
-
-//Exceptions
-exception Exc1 {};
-exception Exc1 {};
-
-
-// Enums
-enum E1 {kalle};
-enum E1 {kalle};
-enum E2 {kalle, sune, kalle};
-
-
-// Structs
-struct S1 {long a;};
-struct S1 {long a;};
-struct S2 {long a; short a;};
-struct S3 {long a,b; short a;};
-struct S4 {long a,a; short a;};
-
-
-// Constants
-const long c1 = 0;
-const long c1 = 0;
-
-
-// Interfaces
-
-interface i1 {};
-interface i1 {};
-
-interface i2 {
- attribute long a1;
- attribute long a1;
-};
-
-interface i3 {
- attribute long a1, a2;
- attribute long a2;
-};
-
-interface i4 {
- attribute long a1, a1;
-};
-
-interface i5 {
- long op1();
- long op1();
-
- long op2(in long a, inout char a);
-};
-
-
-// Unions
-
-union U1 switch (long) {case 1: long a;};
-union U1 switch (long) {case 1: long a;};
-
-union U2 switch (long) {
-case 1: long a;
-default: char a;
-};
-
-
-
-
-
diff --git a/lib/ic/test/ic_SUITE_data/nasty.idl b/lib/ic/test/ic_SUITE_data/nasty.idl
deleted file mode 100644
index e55060f762..0000000000
--- a/lib/ic/test/ic_SUITE_data/nasty.idl
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-//
-// Checks nasty name collisions
-//
-
-typedef string T;
-
-
-#define nasty01 version
-#define nasty02 preproc
-#define nasty03 pragma
-#define nasty04 compile
-#define nasty05 if
-#define nasty06 receive
-#define nasty07 foldr
-#define nasty08 length
-#define nasty09 ID
-
-interface I1 {
- attribute T nasty01;
- attribute T nasty02;
- attribute T nasty03;
- attribute T nasty04;
- attribute T nasty05;
- attribute T nasty06;
- attribute T nasty07;
- attribute T nasty08;
- attribute T nasty09;
-};
-
-interface I2 {
- T nasty01();
- T nasty02();
- T nasty03();
- T nasty04();
- T nasty05();
- T nasty06();
- T nasty07();
- T nasty08();
- T nasty09();
-};
-
diff --git a/lib/ic/test/ic_SUITE_data/one.idl b/lib/ic/test/ic_SUITE_data/one.idl
deleted file mode 100644
index 7fb9808767..0000000000
--- a/lib/ic/test/ic_SUITE_data/one.idl
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-// Test oneway operations
-
-interface I1 {
- long op1(in char a, inout boolean b, out string c);
- oneway void op2(in char a, in boolean b, in string c);
- oneway void op3();
-};
-
-
-
diff --git a/lib/ic/test/ic_SUITE_data/one_followed.idl b/lib/ic/test/ic_SUITE_data/one_followed.idl
deleted file mode 100644
index 17074f7e55..0000000000
--- a/lib/ic/test/ic_SUITE_data/one_followed.idl
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-// Test oneway operations followed by other operations
-
-interface I1 {
- oneway void op1();
- oneway void op2(in char a, in boolean b, in string c);
- long op3(in char a, inout boolean b, out string c);
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/test/ic_SUITE_data/one_out.idl b/lib/ic/test/ic_SUITE_data/one_out.idl
deleted file mode 100644
index 1e75c2d962..0000000000
--- a/lib/ic/test/ic_SUITE_data/one_out.idl
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-// Test oneway operations not using in out params
-
-interface I1 {
- oneway void op1(in char a, inout boolean b, in string c);
- oneway void op2(in char a, out boolean b, in string c);
-};
-
-
-
diff --git a/lib/ic/test/ic_SUITE_data/one_raises.idl b/lib/ic/test/ic_SUITE_data/one_raises.idl
deleted file mode 100644
index 4cd7ae00bb..0000000000
--- a/lib/ic/test/ic_SUITE_data/one_raises.idl
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-// Test oneway operations not using in out params
-
-exception hell {boolean burn; unsigned long for_how_long;};
-exception high_water {long mark;};
-
-interface I1 {
- oneway void op1(in char a) raises (hell);
- oneway void op2(in char a) raises (hell);
- oneway void op3() raises (hell, high_water);
-};
-
-
-
diff --git a/lib/ic/test/ic_SUITE_data/one_void.idl b/lib/ic/test/ic_SUITE_data/one_void.idl
deleted file mode 100644
index 6e8c39197c..0000000000
--- a/lib/ic/test/ic_SUITE_data/one_void.idl
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-// Test oneway operations not using in out params
-
-typedef long T;
-
-interface I1 {
- oneway char op1(in char a);
- oneway T op2(in char a);
-};
-
-
-
diff --git a/lib/ic/test/ic_SUITE_data/raises_reg.idl b/lib/ic/test/ic_SUITE_data/raises_reg.idl
deleted file mode 100644
index 52aba10b8d..0000000000
--- a/lib/ic/test/ic_SUITE_data/raises_reg.idl
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#ifndef _RAISES_REG_IDL
-#define _RAISES_REG_IDL
-
-module Raises_RegModule {
-
- exception Exception_1 {};
-
- exception Exception_2 {};
-
- interface R_R {
-
- void op()
- raises(Raises_RegModule::Exception_1,Raises_RegModule::Exception_2);
-
- };
-
-};
-
-#endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/test/ic_SUITE_data/struct.idl b/lib/ic/test/ic_SUITE_data/struct.idl
deleted file mode 100644
index 011c2404d9..0000000000
--- a/lib/ic/test/ic_SUITE_data/struct.idl
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-
-struct S1 {
- long a;
- char b;
- string<9> s;
-};
-
-struct S2 {
- long a;
- struct S3 {
- long a;
- short b, b1;
- char c;
- } b;
- sequence <S1> c, c2, c3, c4, c5, c6, c7;
-};
-
-
-// Check that structs are detected down in other types
-
-
-typedef struct s4 {long a;} T1;
-union U1 switch (long) {
-case 1:
- struct S5 {unsigned short a;} a;
-case 2:
- union U2 switch (char) {
- case 'a':
- boolean a;
- case 'b':
- struct s6 {long a; boolean b;} c;
- } b;
-};
-
diff --git a/lib/ic/test/ic_SUITE_data/syntax1.idl b/lib/ic/test/ic_SUITE_data/syntax1.idl
deleted file mode 100644
index 2de35a6ddf..0000000000
--- a/lib/ic/test/ic_SUITE_data/syntax1.idl
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-//
-// Check syntax errors
-//
-
-
-typedef long T1 _;
-
-
-
diff --git a/lib/ic/test/ic_SUITE_data/syntax2.idl b/lib/ic/test/ic_SUITE_data/syntax2.idl
deleted file mode 100644
index 39f28392e6..0000000000
--- a/lib/ic/test/ic_SUITE_data/syntax2.idl
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-struct S2 {
- long a_arr[99];
- struct S3 {
- long a;_arr[99]
- boolean b_arr[99];
- } b;
-};
-
-
diff --git a/lib/ic/test/ic_SUITE_data/syntax3.idl b/lib/ic/test/ic_SUITE_data/syntax3.idl
deleted file mode 100644
index 2bb9ac7229..0000000000
--- a/lib/ic/test/ic_SUITE_data/syntax3.idl
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-typdef long T1;
-
diff --git a/lib/ic/test/ic_SUITE_data/syntax4.idl b/lib/ic/test/ic_SUITE_data/syntax4.idl
deleted file mode 100644
index e41ad60ed6..0000000000
--- a/lib/ic/test/ic_SUITE_data/syntax4.idl
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-union U1 switch (long) {
-case 1: long a;
-2: short b;
-};
-
diff --git a/lib/ic/test/ic_SUITE_data/syntax5.idl b/lib/ic/test/ic_SUITE_data/syntax5.idl
deleted file mode 100644
index 6468f0adc0..0000000000
--- a/lib/ic/test/ic_SUITE_data/syntax5.idl
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-union U1 switch (enum E1 {kalle, sune}) {
-case kalle: long a;
-sune: short b;
-};
diff --git a/lib/ic/test/ic_SUITE_data/syntax6.idl b/lib/ic/test/ic_SUITE_data/syntax6.idl
deleted file mode 100644
index 6012cc868c..0000000000
--- a/lib/ic/test/ic_SUITE_data/syntax6.idl
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-constant long c1 = 0;
diff --git a/lib/ic/test/ic_SUITE_data/type.idl b/lib/ic/test/ic_SUITE_data/type.idl
deleted file mode 100644
index 6109661c4f..0000000000
--- a/lib/ic/test/ic_SUITE_data/type.idl
+++ /dev/null
@@ -1,191 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-//
-// Check all types in IDL
-//
-
-typedef long T01;
-typedef unsigned long T02;
-typedef short T03;
-typedef unsigned short T04;
-typedef float T05;
-typedef double T06;
-typedef char T07;
-typedef boolean T08;
-typedef octet T09;
-typedef any T10;
-typedef Object T11;
-typedef T01 T12;
-
-// Template types
-typedef sequence <long> T21;
-typedef sequence <unsigned long> T22;
-typedef sequence <short, 2> T23;
-typedef sequence <unsigned short, 6> T24;
-typedef sequence <float, 12> T25;
-typedef sequence <double> T26;
-typedef sequence <char, 1> T27;
-typedef sequence <boolean> T28;
-typedef sequence <octet, 9> T29;
-typedef sequence <any> T30;
-typedef sequence <Object,2 > T31;
-typedef sequence <T01> T32;
-typedef sequence <sequence <sequence <T32> > > T33;
-
-struct S1 {
- long a;
- boolean b;
-};
-
-struct S2 {
- long a;
- struct S3 {
- long a;
- boolean b;
- } b;
-};
-
-union U1 switch (enum E1 {kalle1, sune1}) {
-case kalle1: long a;
-default: boolean b;
-case sune1: octet c;
-};
-
-union U2 switch (enum E2 {kalle2, sune2}) {
-case kalle2: long a;
-default: struct S4 { long a; short b;} b;
-case sune2: octet c;
-};
-
-// Typedefs of above types
-
-typedef struct S11 {
- long a;
- boolean b;
-} T41;
-
-typedef struct S21 {
- long a;
- struct S3 {
- long a;
- boolean b;
- } b;
-} T42;
-
-typedef union U11 switch (enum E3 {kalle3, sune3}) {
-case kalle3: long a;
-default: boolean b;
-case sune3: octet c;
-} T43;
-
-typedef union U21 switch (enum E4 {kalle4, sune4}) {
-case kalle4: long a;
-default: struct S4 { long a; short b;} b;
-case sune4: octet c;
-} T44;
-
-
-
-
-// Array versions
-
-typedef long T01_arr[99];
-typedef unsigned long T02_arr[99];
-typedef short T03_arr[99];
-typedef unsigned short T04_arr[99];
-typedef float T05_arr[99];
-typedef double T06_arr[99];
-typedef char T07_arr[99];
-typedef boolean T08_arr[99];
-typedef octet T09_arr[99];
-typedef any T10_arr[99];
-typedef Object T11_arr[99];
-typedef T01 T12_arr[99];
-
-typedef sequence <long> T21_arr[99];
-typedef sequence <unsigned long> T22_arr[99];
-typedef sequence <short, 2> T23_arr[99];
-typedef sequence <unsigned short, 6> T24_arr[99];
-typedef sequence <float, 12> T25_arr[99];
-typedef sequence <double> T26_arr[99];
-typedef sequence <char, 1> T27_arr[99];
-typedef sequence <boolean> T28_arr[99];
-typedef sequence <octet, 9> T29_arr[99];
-typedef sequence <any> T30_arr[99];
-typedef sequence <Object,2 > T31_arr[99];
-typedef sequence <T01> T32_arr[99];
-typedef sequence <sequence <sequence <T32> > > T33_arr[99];
-
-struct S12 {
- long a;
- boolean b_arr[99];
-};
-
-struct S22 {
- long a_arr[99];
- struct S3 {
- long a_arr[99];
- boolean b_arr[99];
- } b;
-};
-
-union U12 switch (enum E12 {kalle12, sune12}) {
-case kalle12: long a_arr[99];
-default: boolean b;
-case sune12: octet c;
-};
-
-union U22 switch (enum E22 {kalle22, sune22}) {
-case kalle22: long a;
-default: struct S4 { long a; short b;} b_arr[99];
-case sune22: octet c;
-};
-
-// Typedefs of above types
-
-typedef struct S13 {
- long a_arr[99];
- boolean b;
-} T41_arr[99];
-
-typedef struct S23 {
- long a;
- struct S3 {
- long a;
- boolean b_arr[99];
- char c;
- } b;
-} T42_arr[99];
-
-typedef union U13 switch (enum E13 {kalle13, sune13}) {
-case kalle13: long a;
-default: boolean b_arr[99];
-case sune13: octet c;
-} T43_arr[99];
-
-typedef union U23 switch (enum E23 {kalle23, sune23}) {
-case kalle23: long a_arr[99];
-default: struct S4 { long a; short b;} b_arr[99];
-case sune23: octet c_arr[99];
-} T44_arr[99];
-
-
-
diff --git a/lib/ic/test/ic_SUITE_data/typeid.idl b/lib/ic/test/ic_SUITE_data/typeid.idl
deleted file mode 100644
index 9a5ce28bdf..0000000000
--- a/lib/ic/test/ic_SUITE_data/typeid.idl
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-interface I1 {};
-
-module M1 { interface I1 {};};
-
-module M2 { module M1 { interface I1 {};};};
-
-module M3 { module M2 { module M1 { interface I1 {};};};};
-
-
diff --git a/lib/ic/test/ic_SUITE_data/u_case_mult.idl b/lib/ic/test/ic_SUITE_data/u_case_mult.idl
deleted file mode 100644
index 3d1523b5f5..0000000000
--- a/lib/ic/test/ic_SUITE_data/u_case_mult.idl
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-// Check that case labels are not duplicated
-
-union U1 switch (long) {
-case 1 : long a;
-case 1 : short b;
-};
-
-union U2 switch (char) {
-case 'c' : long a;
-case 'c' : short b;
-};
-
-union U2b switch (char) {
-case 'c' :
-case 'c' : long a;
-case 'e': long b;
-case 'c': long c;
-};
-
-union U3 switch (enum E1 {kalle, kula}) {
-case kula : long a;
-case kula : short b;
-};
-
-union U4 switch (boolean) {
-case TRUE : long a;
-case TRUE : short b;
-};
-
-union U5 switch (boolean) {
-case TRUE : long a;
-default: short p;
-default: short pp;
-};
-
diff --git a/lib/ic/test/ic_SUITE_data/u_default.idl b/lib/ic/test/ic_SUITE_data/u_default.idl
deleted file mode 100644
index 050b876aad..0000000000
--- a/lib/ic/test/ic_SUITE_data/u_default.idl
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-//
-// Checking that default labels are correct in TK
-//
-
-interface i1 {
- union U1 switch (long) {
- default: long a;
- case 1: case 2: long b;
- };
-
- union U2 switch (long) {
- case 0: default: long a;
- case 1: case 2: long b;
- };
-
- union U3 switch (long) {
- case -1: long aa;
- case 0: default: long a;
- case 1: case 2: long b;
- };
-
- union U4 switch (long) {
- case -1: long aa;
- case 0: long a;
- case 1: case 2: long b;
- };
-
- U1 op0();
- U2 op1();
- U3 op2();
- U4 op3();
-};
diff --git a/lib/ic/test/ic_SUITE_data/u_mult.idl b/lib/ic/test/ic_SUITE_data/u_mult.idl
deleted file mode 100644
index 3ab47c40a5..0000000000
--- a/lib/ic/test/ic_SUITE_data/u_mult.idl
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-
-// Check multiply defined declarators
-
-enum E2 {kal, kula, E1}; // legal, but used below
-
-// Now check that declarator a is multiply defined in all unions below
-union U0 switch (long) {
-case 0: long a;
-case 1: short a;
-};
-union U00 switch (char) {
-case 'c' : long a;
-case 'f' : char c;
-case 'b' : short a;
-};
-union U000 switch (boolean) {
-case TRUE: long a;
-case FALSE: short a;
-};
-union U0000 switch (E2) {
-case kal: long a;
-case kula: short a;
-};
-
-
-
-
-// Check that enum name duplication is found.
-
-union U1 switch (enum E1 {kalle, kula, E1}) {
-case E1 : long a; // legal
-case kalle : short E1; // illegal
-};
-
-
-// This is legal, but ended up here anyway
-
-union U2 switch(::E2) {
-case kal : long a;
-case kula : short b;
-default : boolean E1;
-};
diff --git a/lib/ic/test/ic_SUITE_data/u_norm.idl b/lib/ic/test/ic_SUITE_data/u_norm.idl
deleted file mode 100644
index b2f146f45a..0000000000
--- a/lib/ic/test/ic_SUITE_data/u_norm.idl
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-
-union U1 switch (long) {
-case 1: long a;
-case 2: case 3: short b;
-};
-
-
-union U2 switch (unsigned short) {
-case 10: boolean a;
-case 188: char b;
-default: string c;
-};
-
-
-union U3 switch (enum E1 {kalle, kula, boll}) {
-case kalle: long a;
-case kula: U2 b;
-};
-
-enum E2 {Cissi, Anders};
-
-union U4 switch (::E2) {
-case Cissi: U1 a;
-default: case Anders: unsigned long b;
-};
-
-union U5 switch(char) {
-case 'e': long a;
-case 'b': case 'f': char b;
-default: struct S {long a; boolean b;} c;
-};
-
-
-// Now check that references can be used as case values
-
-const long c1 = 9;
-const long c2 = 10;
-
-union U6 switch (long) {
-case c1: boolean a;
-case ::c2: boolean b;
-};
-
-
diff --git a/lib/ic/test/ic_SUITE_data/u_type.idl b/lib/ic/test/ic_SUITE_data/u_type.idl
deleted file mode 100644
index 8a46b9375f..0000000000
--- a/lib/ic/test/ic_SUITE_data/u_type.idl
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-
-//
-// Check that case values match declared discriminator type
-//
-
-
-const long longC = 0;
-const short shortC = 0;
-const char charC = 'c';
-const string stringC = "Yacht";
-
-enum E1 {kalle, kula};
-
-union U1 switch (long) {
-case 'c' : long a;
-case TRUE : long b;
-case stringC : long d;
-case kalle : long f;
-};
-
-union U2 switch (unsigned long) {
-case 'c' : long a;
-case TRUE : long b;
-case stringC : long d;
-case kalle : long f;
-};
-
-union U3 switch (short) {
-case 'c' : long a;
-case TRUE : long b;
-case stringC : long d;
-case kalle : long f;
-};
-
-union U4 switch (unsigned short) {
-case 'c' : long a;
-case TRUE : long b;
-case stringC : long d;
-case kalle : long f;
-};
-
-union U5 switch (char) {
-case TRUE : long b;
-case stringC : long d;
-case shortC : long e;
-case kalle : long f;
-};
-
-
-union U6 switch (E1) {
-case 'c' : long a;
-case TRUE : long b;
-case stringC : long d;
-case shortC : long e;
-};
-
-union U7 switch (enum E2 {ja, nej, kanske}) {
-case 'c' : long a;
-case TRUE : long b;
-case stringC : long d;
-case shortC : long e;
-};
-
diff --git a/lib/ic/test/ic_SUITE_data/undef_id.idl b/lib/ic/test/ic_SUITE_data/undef_id.idl
deleted file mode 100644
index a09598f0a7..0000000000
--- a/lib/ic/test/ic_SUITE_data/undef_id.idl
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-//
-// Check that undefined ids are detected
-//
-
-typedef T7 T1;
-
-const char c1 = ::c0;
-const T01 c2 = 'h';
-const T7 c3 = 9;
-
-interface i1 {
- T17 op();
- long op2( in T7 a);
- attribute T7 a1, a2;
- readonly attribute T17 a3;
-};
-
-union U1 switch (long) {
-case 1: long a;
-case ::g : short b;
-};
-
-union U2 switch (enum E1 {kalle, kula}) {
-case kula1: long a;
-case kalle : short b;
-};
-
-union U3 switch (long) {
-case kula2: long a;
-case ::E3::kalle : short b;
-case ::E4::kalle : short c;
-};
-
-enum E2 {kalle2, kula2};
-
-union U4 switch (E2) {
-case kula1: long a;
-case kula1: long b;
-case c3: short c;
-};
-
-
-
-
diff --git a/lib/ic/test/ic_be_SUITE.erl b/lib/ic/test/ic_be_SUITE.erl
deleted file mode 100644
index d5d3038a6e..0000000000
--- a/lib/ic/test/ic_be_SUITE.erl
+++ /dev/null
@@ -1,75 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%%----------------------------------------------------------------------
-%%% Purpose : Test suite for the backends of the IDL compiler
-%%%----------------------------------------------------------------------
-
--module(ic_be_SUITE).
--include_lib("common_test/include/ct.hrl").
-
-
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,plain/1]).
-
-
--define(OUT(X), filename:join([proplists:get_value(priv_dir, Config), gen, to_list(X)])).
-
-
-%% Top of cases
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [plain].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% Checking code for the plain backend.
-plain(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(slask),
- File = filename:join(DataDir, plain),
- ok = ic:gen(File,stdopts(OutDir)++[{be,erl_plain}]),
- ok.
-
-%%--------------------------------------------------------------------
-%%
-%% Utilities
-stdopts(OutDir) ->
- [{outdir, OutDir}, {maxerrs, infinity}].
-
-to_list(X) when is_atom(X) -> atom_to_list(X);
-to_list(X) -> X.
-
diff --git a/lib/ic/test/ic_be_SUITE_data/plain.idl b/lib/ic/test/ic_be_SUITE_data/plain.idl
deleted file mode 100644
index 1ee20eeb1f..0000000000
--- a/lib/ic/test/ic_be_SUITE_data/plain.idl
+++ /dev/null
@@ -1,34 +0,0 @@
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-module m {
-
- struct s {
- long x;
- long y;
- };
-
- interface i {
-
- void foo( in s a, out short b );
-
- };
-
-};
-
diff --git a/lib/ic/test/ic_pp_SUITE.erl b/lib/ic/test/ic_pp_SUITE.erl
deleted file mode 100644
index be37953126..0000000000
--- a/lib/ic/test/ic_pp_SUITE.erl
+++ /dev/null
@@ -1,569 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% Purpose : Test suite for the IDL preprocessor
-%%----------------------------------------------------------------------
-
--module(ic_pp_SUITE).
--include_lib("common_test/include/ct.hrl").
-
-
-
-%% Standard options to the ic compiler, NOTE unholy use of OutDir
-
--define(OUT(X), filename:join([proplists:get_value(priv_dir, Config), gen, to_list(X)])).
--define(GCC, "g++").
--define(GCC_VER, "2.95.3").
-
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
--export([arg_norm/1]).
--export([cascade_norm/1]).
--export([comment_norm/1]).
--export([concat_norm/1]).
--export([define_norm/1]).
--export([if_norm/1]).
--export([if_zero/1]).
--export([misc_norm/1]).
--export([improp_nest_constr_norm/1]).
--export([inc_norm/1]).
--export([line_norm/1]).
--export([nopara_norm/1]).
--export([predef_norm/1]).
--export([predef_time_norm/1]).
--export([self_ref_norm/1]).
--export([separate_norm/1]).
--export([swallow_sc_norm/1]).
--export([unintended_grp_norm/1]).
--export([cases/0, init_per_suite/1, end_per_suite/1]).
-
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [{arg, [], [arg_norm]}, {cascade, [], [cascade_norm]},
- {comment, [], [comment_norm]},
- {concat, [], [concat_norm]},
- {define, [], [define_norm]}, {inc, [], [inc_norm]},
- {improp_nest_constr, [], [improp_nest_constr_norm]},
- {misc, [], [misc_norm]}, {line, [], [line_norm]},
- {nopara, [], [nopara_norm]},
- {predef, [], [predef_norm]},
- {predef_time, [], [predef_time_norm]},
- {self_ref, [], [self_ref_norm]},
- {separate, [], [separate_norm]},
- {swallow_sc, [], [swallow_sc_norm]},
- {unintended_grp, [], [unintended_grp_norm]},
- {'if', [],[if_norm, if_zero]}].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_suite(Config) ->
- if
- is_list(Config) ->
- case os:type() of
- {win32, _} ->
- {skipped, "Very unplesent to run on windows"};
- _ ->
- check_gcc(Config)
- end;
- true ->
- exit("Config not a list")
- end.
-
-check_gcc(Config) ->
- case os:find_executable(?GCC) of
- false ->
- {skipped,
- lists:flatten(io_lib:format("Can not run without ~s in path",
- [?GCC]))};
- _ ->
- case trim(os:cmd(?GCC++" --version")) of
- ?GCC_VER++[] ->
- Config;
- ?GCC_VER++[D|_] when is_integer(D), D>=$0, D=<$9 ->
- fail_gcc(?GCC_VER++[D]);
- ?GCC_VER++_ ->
- Config;
- Ver ->
- fail_gcc(Ver)
- end
- end.
-
-fail_gcc(Ver) ->
- {skipped, lists:flatten(io_lib:format("Need ~s v~s, not ~s",
- [?GCC, ?GCC_VER, Ver]))}.
-
-trim(S) -> lists:reverse(skip_white(lists:reverse(skip_white(S)))).
-
-skip_white([$\s|T]) -> skip_white(T);
-skip_white([$\n|T]) -> skip_white(T);
-skip_white([$\r|T]) -> skip_white(T);
-skip_white([$\t|T]) -> skip_white(T);
-skip_white(L) -> L.
-
-
-end_per_suite(Config) ->
- Config.
-
-
-cases() ->
- [{group, arg}, {group, cascade}, {group, comment},
- {group, concat}, {group, define}, {group, misc}, {group, 'if'},
- {group, improp_nest_constr}, {group, inc},
- {group, line}, {group, nopara}, {group, predef},
- {group, predef_time}, {group, self_ref},
- {group, separate}, {group, swallow_sc},
- {group, unintended_grp}].
-
-
-
-%%--------------------------------------------------------------------
-%% arg
-%%--------------------------------------------------------------------
-%% Checks arguments for #define.
-arg_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- _OutDir = ?OUT(arg_norm),
- File = filename:join(DataDir, arg),
-
- ok = test_file(File, DataDir),
- ok.
-
-
-%%--------------------------------------------------------------------
-%% cascade
-%%--------------------------------------------------------------------
-%% Check cascade #define.
-cascade_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- _OutDir = ?OUT(cascade_norm),
- File = filename:join(DataDir, cascade),
-
- ok = test_file(File, DataDir),
- ok.
-
-
-%%--------------------------------------------------------------------
-%% comment
-%%--------------------------------------------------------------------
-%% Check comments.
-comment_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- _OutDir = ?OUT(comment_norm),
- File = filename:join(DataDir, comment),
-
- ok = test_file(File, DataDir),
- ok.
-
-
-%%--------------------------------------------------------------------
-%% concat
-%%--------------------------------------------------------------------
-%% Check concatinations, i.e ## .
-concat_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- _OutDir = ?OUT(concat_norm),
- File = filename:join(DataDir, concat),
-
- ok = test_file(File, DataDir),
- ok.
-
-
-%%--------------------------------------------------------------------
-%% define
-%%--------------------------------------------------------------------
-%% Check misceleaneous #define.
-define_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- _OutDir = ?OUT(define_norm),
- File = filename:join(DataDir, define),
-
- ok = test_file(File, DataDir),
- ok.
-
-
-%%--------------------------------------------------------------------
-%% if
-%%--------------------------------------------------------------------
-%% Check #if, #elif, and #endif.
-if_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- _OutDir = ?OUT(if_norm),
- File = filename:join(DataDir, 'if'),
-
- ok = test_file(File, DataDir),
- ok.
-
-%% Check #if 0
-if_zero(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- _OutDir = ?OUT(if_zero),
- File = filename:join(DataDir, if_zero),
-
- ok = test_file(File, DataDir),
- ok.
-
-
-%%--------------------------------------------------------------------
-%% inc
-%%--------------------------------------------------------------------
-%% Check #include.
-inc_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- _OutDir = ?OUT(inc_norm),
- File = filename:join(DataDir, inc),
-
- ok = test_file(File, DataDir),
- ok.
-
-
-
-%%--------------------------------------------------------------------
-%% improp_nest_constr
-%%--------------------------------------------------------------------
-%% Check improperly nested constructs.
-improp_nest_constr_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- _OutDir = ?OUT(improp_nest_constr_norm),
- File = filename:join(DataDir, improp_nest_constr),
-
- ok = test_file(File, DataDir),
- ok.
-
-
-%%--------------------------------------------------------------------
-%% misc
-%%--------------------------------------------------------------------
-%% Misceleaneous checks.
-misc_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- _OutDir = ?OUT(misc_norm),
- File = filename:join(DataDir, misc),
-
- ok = test_file(File, DataDir),
- ok.
-
-
-%%--------------------------------------------------------------------
-%% line
-%%--------------------------------------------------------------------
-%% Checks #line.
-line_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- _OutDir = ?OUT(line_norm),
- File = filename:join(DataDir, line),
-
- ok = test_file(File, DataDir),
- ok.
-
-
-%%--------------------------------------------------------------------
-%% nopara
-%%--------------------------------------------------------------------
-%% Checks #define with no parameters.
-nopara_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- _OutDir = ?OUT(nopara_norm),
- File = filename:join(DataDir, nopara),
-
- ok = test_file(File, DataDir),
- ok.
-
-
-%%--------------------------------------------------------------------
-%% predef
-%%--------------------------------------------------------------------
-%% Checks predefined macros. Note: not __TIME__ and __DATE__.
-predef_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- _OutDir = ?OUT(predef_norm),
- File = filename:join(DataDir, predef),
-
- ok = test_file(File, DataDir),
- ok.
-
-
-%%--------------------------------------------------------------------
-%% predef_time
-%%--------------------------------------------------------------------
-%% Checks the predefined macros __TIME__ and __DATE__.
-predef_time_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- _OutDir = ?OUT(predef_time_norm),
- File = filename:join(DataDir, predef_time),
-
- ok = test_file(File, DataDir),
- ok.
-
-
-%%--------------------------------------------------------------------
-%% self_ref
-%%--------------------------------------------------------------------
-%% Checks self referring macros.
-self_ref_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- _OutDir = ?OUT(self_ref_norm),
- File = filename:join(DataDir, self_ref),
-
- ok = test_file(File, DataDir),
- ok.
-
-
-%%--------------------------------------------------------------------
-%% separate
-%%--------------------------------------------------------------------
-%% Checks separete expansion of macro arguments.
-separate_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- _OutDir = ?OUT(separate_norm),
- File = filename:join(DataDir, separate),
-
- ok = test_file(File, DataDir),
- ok.
-
-
-%%--------------------------------------------------------------------
-%% swallow_sc
-%%--------------------------------------------------------------------
-%% Checks swallowing an undesirable semicolon.
-swallow_sc_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- _OutDir = ?OUT(swallow_sc_norm),
- File = filename:join(DataDir, swallow_sc),
-
- ok = test_file(File, DataDir),
- ok.
-
-
-%%--------------------------------------------------------------------
-%% unintended_grp
-%%--------------------------------------------------------------------
-%% Checks unintended grouping of arithmetic.
-unintended_grp_norm(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- _OutDir = ?OUT(unintended_grp_norm),
- File = filename:join(DataDir, unintended_grp),
-
- ok = test_file(File, DataDir),
- ok.
-
-
-test_file(FileT, DataDir) ->
- case test_file_1(FileT, DataDir) of
- ok -> ok;
- Chars ->
- io:put_chars(Chars),
- {error,{FileT,DataDir}}
- end.
-
-test_file_1(FileT, DataDir) ->
- Tok = string:tokens(FileT, "/"),
- FileName = lists:last(Tok),
- File = FileT++".idl",
-
- test_server:format("File ~p~n",[File]),
- test_server:format("FileName ~p~n",[FileName]),
-
- Flags = "-I"++DataDir,
-
- test_server:format("Flags ~p~n",[Flags]),
-
- Erl = pp_erl(File, Flags),
- Gcc = pp_gcc(File, Flags),
-
- case Erl of
- {error,_ErlError} ->
- test_server:format("Internal_pp Result ~n==================~n~p~n~n",[Erl]);
- {warning, _ErlWar} ->
- test_server:format("Internal_pp Result ~n==================~n~p~n~n",[Erl]);
- _ ->
- test_server:format("Internal_pp Result ~n==================~n~s~n~n",[Erl])
- end,
-
- case Gcc of
- {error,GccError} ->
- Error = string:tokens(GccError, "\n"),
- test_server:format(?GCC" Result ~n==========~n~p~n~n",
- [Error]);
- _ ->
- test_server:format(?GCC" Result ~n==========~n~s~n~n",[Gcc])
- end,
-
-
-
- case {Erl,Gcc} of
- {{warning,W}, {error,X}} ->
- case is_ok(W,X) of
- yes ->
- ok;
- no ->
- io_lib:format("Internal_pp found Warning = ~p ~n"
- ?GCC" found Error = ~p~n",[W,X])
- end;
-
-
- {{warning,W}, _} ->
- io_lib:format(?GCC" did not find warnings while ~n"
- "Internal_pp found the following Warning = ~p~n",[W]);
-
- {{error,E}, {error,X}} ->
- case is_ok(E,X) of
- yes ->
- ok;
- no ->
- io_lib:format("Internal_pp found Error = ~p ~n"
- ?GCC" found Error = ~p~n",[E,X])
- end;
-
- {{error,E}, _} ->
- case FileName of
- "if" ->
- case if_res(E) of
- ok ->
- ok;
- _ ->
- io_lib:format(?GCC" did not find errors while ~n"
- "Internal_pp found the following Error = ~p~n",[E])
- end;
- _ ->
- io_lib:format(?GCC" did not find errors while ~n"
- "Internal_pp found the following Error = ~p~n",[lists:flatten(E)])
- end;
-
- {_, {error,X}} ->
- io_lib:format("Internal_pp did not find errors while ~n"
- ?GCC" found the following Error = ~p~n",[X]);
-
- _ ->
-
- file:write_file("/tmp/Erl.pp",list_to_binary(Erl)),
- file:write_file("/tmp/Gcc.pp",list_to_binary(Gcc)),
-
- Res = os:cmd("diff -b -w /tmp/Erl.pp /tmp/Gcc.pp"),
- test_server:format("///////////{error,E} E ~p FileName~p~n",[Res,FileName]),
- case {Res, FileName} of
- {[], _} ->
- test_server:format("Diff = [] OK!!!!!!~n"),
- ok;
- {_, "predef_time"} ->
- Tokens = string:tokens(Res,"\n"),
- test_server:format("///////////{error,E} Tokens~p~n",[Tokens]),
- case Tokens of
- ["3c3",_,"---",_,"5c5",_,"---",_,"9c9",_,"---",_] ->
- ok;
- _ ->
- io_lib:format("Diff Result = ~p~n",[Res])
- end;
- _ ->
- io_lib:format("Diff Result = ~p~n",[Res])
- end
- end.
-
-
-
-
-
-pp_erl(File, Flags) ->
- case ic_pp:run(File,Flags) of
- {ok, [$#, $ , $1 | Rest], []} ->
- [$#, $ , $1 | Rest];
- {ok, [$#, $ , $1 | _Rest], Warning} ->
- {warning,Warning};
- {error,Error} ->
- {error,Error}
- end.
-
-pp_gcc(File, Flags) ->
- Cmd = ?GCC" -x c++ -E",
- Line = Cmd++" "++Flags++" "++File,
-
- case os:cmd(Line) of
- [$#, $ , $1 | Rest] ->
- [$#, $ , $1 | Rest];
- Res ->
-
- case string:str(Res,"# 1 \"") of
- 0 ->
- {error,Res};
- X ->
- {error, string:sub_string(Res, 1, X-1)}
- end
- end.
-
-
-is_ok([],_Gcc) ->
- yes;
-is_ok([{FileName,Line,Text}|T],Gcc) ->
- Str = FileName++":"++integer_to_list(Line)++": "++Text,
- case string:str(Gcc,Str) of
- 0 ->
- io:format("~n is_ok Internal_pp missed Error = ~s~n",[Str]),
- no;
- _X ->
- is_ok(T,Gcc)
- end;
-is_ok([Str|T],Gcc) ->
- case string:str(Gcc,Str) of
- 0 ->
- io:format("~n is_ok Internal_pp missed Error = ~s~n",[Str]),
- no;
- _X ->
- is_ok(T,Gcc)
- end.
-
-
-to_list(X) when is_atom(X) -> atom_to_list(X);
-to_list(X) -> X.
-
-
-
-if_res(E) ->
- if_res(E,1).
-
-if_res([H|T],Nr) ->
- %% Dir = "/clearcase/otp/libraries/ic/test/ic_pp_SUITE_data/if.idl",
- case {Nr, H} of
- {1, {_Dir, 2, "only '#if 0' is implemented at present"}} ->
- if_res(T,Nr+1);
- {2, {_Dir, 3, "only '#if 0' is implemented at present"}} ->
- if_res(T,Nr+1);
- {3, {_Dir, 5, "`else' command is not implemented at present"}} ->
- if_res(T,Nr+1);
- {4, {_Dir, 9, "`elif' command is not implemented at present"}} ->
- if_res(T,Nr+1);
- {5, {_Dir, 11, "`else' command is not implemented at present"}} ->
- ok;
- _ ->
- error
- end;
-if_res(_, _) ->
- error.
-
-
-
diff --git a/lib/ic/test/ic_pp_SUITE_data/arg.idl b/lib/ic/test/ic_pp_SUITE_data/arg.idl
deleted file mode 100644
index 42d8457f2c..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/arg.idl
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#define xstr (s) str(s)
-#define str(s) #s
-#define foo 4
-
-xstr(foo);
-
-#define x(kalle)stina
-x(kurt)
-x
-
-#define y(kalle) stina
-y(kurt)
-y
-
-#define a(kalle) stina
-a(kurt)
-a
-
-#define b (kalle) stina
-b(kurt)
diff --git a/lib/ic/test/ic_pp_SUITE_data/cascade.idl b/lib/ic/test/ic_pp_SUITE_data/cascade.idl
deleted file mode 100644
index f96f2a0bd7..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/cascade.idl
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#define BUFS 1020
-#define TABS BUFS
-#undef BUFS
-#define BUFS 37
-
-
-main()
-{
- TABS;
-
-}
diff --git a/lib/ic/test/ic_pp_SUITE_data/comment.idl b/lib/ic/test/ic_pp_SUITE_data/comment.idl
deleted file mode 100644
index 9b5e310e6c..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/comment.idl
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#define T 12
-#define F T
-
-//comment
-/*exception except {};*/
-
-// comment
- // comment
-/* another */
- /* another */
-/* still
-another */
- /* still
- another */
-__LINE__
-/* yet \
- another */
-// yet \
- another
-__LINE__
-
-#include "all.c"
-#include <all.c>
-#include /* comment */ "all.c"
-#include /* comment */ <all.c>
-#include "all.c" /* comment */
-#include <all.c> /* comment */
-#include // "all.c"
-#include // <all.c>
-#include "all.c" // comment
-#include <all.c> // comment
-#include "all/*cc*/.c"
-#include <all/*cc*/.c>
-
-main()
-{
- printf(" %d \n",F);
- a();
-
-}
-//comment
-/*exception hell {};*/
-#undef T
-#define T "3/*com\
-ment*/4"
-a()
-{
- printf(" %d \n",F);
- printf(" %d \n",T);
-}
-
-b()
-{}
-
diff --git a/lib/ic/test/ic_pp_SUITE_data/concat.idl b/lib/ic/test/ic_pp_SUITE_data/concat.idl
deleted file mode 100644
index eb1f6aa1ad..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/concat.idl
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#define sune kurt
-#define a(name) a #name name##_command
-#define b(name) b #name name## _command
-#define c(name) c #name name ##_command
-#define d(name) d #name name ## _command
-#define e(name) e #name command ## _command
-#define f(name) f #name command ## %_command
-#define g(name) g #name name ## %_command
-#define h(name) h #name %_command ## name
-#define i(name) i #name name ## _ ## name
-#define j(name) j #name name ## name
-#define k(name) k #name name ## name
-#define l(name) l #name !name ## name
-#define m(name) m #name name ## !name
-#define n(name) n #name !name ## !name
-#define o(name) stina
-#define p(name) name
-#define q1(name) q1 #name j(name) ## j(name)
-#define q2(name) q2 #name j(name)
-#define q3(name) q3 #name !! ## j(name)
-#define q4(name) q4 #name ## j(name)
-
-a(quit)
-b(quit)
-c(quit)
-d(quit)
-e(quit)
-f(quit)
-g(sune)
-h(sune)
-i(sune)
-j(sune)
-l(sune)
-m(sune)
-n(sune)
-k(j(sune))
-k(o(sune))
-k(p(sune))
-q1(sune)
-q2(sune)
-q3(sune)
-q4(sune)
diff --git a/lib/ic/test/ic_pp_SUITE_data/define.idl b/lib/ic/test/ic_pp_SUITE_data/define.idl
deleted file mode 100644
index 76a3b5ec22..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/define.idl
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#define 8
-#define
-#define a
-#define _a
-#define b dfs
-#define 9 fdas
-#define a8
-#define A
-#define (c) fadfas
-#define )c) fadfas
-#define % c) fadfas
-#define d(p) kfdsa
-#define e(p) sinus(p)
-#warning warning line
-#define w%er percent
-#define q() no_para
-#warning warning line
-#undef
-#undef 8
-#undef a
-#undef b
-#undef _a d(kk)
-
diff --git a/lib/ic/test/ic_pp_SUITE_data/if.idl b/lib/ic/test/ic_pp_SUITE_data/if.idl
deleted file mode 100644
index 437ea7c2e1..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/if.idl
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#define kurt 12
-#if !true
-#if X == 1
-ett
-#else
-else
-#endif
-true
-#elif kurt
-trueelif
-#else
-trueelse
-#endif
-end
diff --git a/lib/ic/test/ic_pp_SUITE_data/if_zero.idl b/lib/ic/test/ic_pp_SUITE_data/if_zero.idl
deleted file mode 100644
index a0184f8bff..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/if_zero.idl
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#if 0
-pelle = mallan
-#endif
-pelle = stina
-#if 0
-kalle = stina
-#endif
-kalle = mallan
-#if 0
-kurt = fia
-#endif
-fia = kurt
-
diff --git a/lib/ic/test/ic_pp_SUITE_data/improp_nest_constr.idl b/lib/ic/test/ic_pp_SUITE_data/improp_nest_constr.idl
deleted file mode 100644
index b658811277..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/improp_nest_constr.idl
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#define double(x) (2*(x))
-#define call_with_1(x) x(1)
-
-#define strange(file) fprintf (file, "%s %d",
-
-main()
-{
- call_with_1(double);
- strange(stderr) p, 35)
-
-}
-
diff --git a/lib/ic/test/ic_pp_SUITE_data/inc.idl b/lib/ic/test/ic_pp_SUITE_data/inc.idl
deleted file mode 100644
index e13875b10c..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/inc.idl
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-int x;
-
-#include "head.h"
-#warning line nr
-main()
-{
- printf(test());
-}
-
-
-
-
-
-
-
-
-#define C false
-#define Z on
-#include "inc2.h"
-#undef Z
-"Ca" C
-"Za" Z
-#include "inc2.h"
-"Cb" C
-"Zb" Z
-
-main()
-{
-#define Q(a,b) sinus(a,b kurt ## b)
- if (Q(34,56)=='NULL') printf(" T AAA%sEEEE \n",Q);
- printf(" %d \n",F);
- a();
-}
-//comment
-/*exception
-hell {};*/
-#undef T
-#define T "3/*com\ment*/4"
-#define T 33
-#define F again
-a ()
-{
- printf(" %d \n",F);
- printf(" %d \n",T);
-}
-
-b()
-{}
-
diff --git a/lib/ic/test/ic_pp_SUITE_data/included1.idl b/lib/ic/test/ic_pp_SUITE_data/included1.idl
deleted file mode 100644
index f3cc40f549..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/included1.idl
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 2000-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#ifndef INCLUDED1_IDL
-#define INCLUDED1_IDL
-
-
-#ifndef SOMETHING
-#endif
-
-
-struct s {
-
- long l;
-
-};
-
-
-
-#endif
diff --git a/lib/ic/test/ic_pp_SUITE_data/included2.idl b/lib/ic/test/ic_pp_SUITE_data/included2.idl
deleted file mode 100644
index 6a718ce021..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/included2.idl
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 2000-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#ifndef INCLUDED2_IDL
-#define INCLUDED2_IDL
-
-#include "included1.idl"
-
-
-#ifdef SOMETHING
-#endif
-
-
-module m {
-
- struct t {
-
- s st;
-
- };
-
-
-};
-
-
-#endif
diff --git a/lib/ic/test/ic_pp_SUITE_data/includer.idl b/lib/ic/test/ic_pp_SUITE_data/includer.idl
deleted file mode 100644
index d4fabd024a..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/includer.idl
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 2000-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#ifndef INCLUDER_IDL
-#define INCLUDER_IDL
-
-#include "included1.idl"
-#include "included2.idl"
-
-#ifdef SOMETHING
-#endif
-
-
-
-module n {
-
- interface j {
-
- s op(in m::t inpar);
-
- };
-
-};
-
-
-
-
-#endif
-
-
diff --git a/lib/ic/test/ic_pp_SUITE_data/line.idl b/lib/ic/test/ic_pp_SUITE_data/line.idl
deleted file mode 100644
index 83783dff03..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/line.idl
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#line
-#line 8
-#line 8a
-#line 12 abc.c
-#line 12 "kurt.c"
-#warning fdafdsaf
-
-
-#define T 12
-#define F T
-#define Q(a) sinus(a)
-#undef Q
-#
-#line 12
-#warning test of warning
-#warning second of warning
-#warning third of warning
-#pragma kurt
-#ident kurt
-#kurt fdsafd
-#line 20
-main()
-{
- if (Q(34,56)=='NULL') printf(" T AAA%sEEEE \n",Q);
- printf(" %d \n",F);
-}
-sune
diff --git a/lib/ic/test/ic_pp_SUITE_data/misc.idl b/lib/ic/test/ic_pp_SUITE_data/misc.idl
deleted file mode 100644
index 512ccb16b1..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/misc.idl
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#define str(s) #s
-str(fool);
-str(foo);
-str(kurt);
-#define xstr(s) str(s)
-#define foo 4
-#define kurt sune
-#define sune 17
-
-xstr(fool);
-xstr(foo);
-xstr(kurt);
-
-#define a(b) b #8b
-#define r(b) b #
-#define t(b) b ## a
-a(sinus)
-
-#define ww #www
-ww
-
-#define x 14 + y
-#define y 12 + #x
-x
-
-#define e(a) cosinus(a)
diff --git a/lib/ic/test/ic_pp_SUITE_data/nopara.idl b/lib/ic/test/ic_pp_SUITE_data/nopara.idl
deleted file mode 100644
index 9d5253bf38..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/nopara.idl
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#11a
-#define xstr str(s) + kurt*2;
-#define asdf pragma
-#asdf
-#define asd #pragma asd
-
-#10
-#12 8kurt
-
-#define sss "stringing in the rain"
-#define ddd "string
-ing in the rain" asd
-#line 20
-#include "head.h" qqqq
-#include %!#
-#include <sys.h>
-
diff --git a/lib/ic/test/ic_pp_SUITE_data/predef.idl b/lib/ic/test/ic_pp_SUITE_data/predef.idl
deleted file mode 100644
index 8805501d66..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/predef.idl
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#define b(q,w) kurt q w
-
-
-b(__LINE__, __FILE__)
-__LINE__
-__FILE__
-
-
-
-b(__INCLUDE_LEVEL__, __BASE_FILE__)
-__INCLUDE_LEVEL__
-__BASE_FILE__
-
-Line __LINE__
-#include "predef.h"
diff --git a/lib/ic/test/ic_pp_SUITE_data/predef_time.idl b/lib/ic/test/ic_pp_SUITE_data/predef_time.idl
deleted file mode 100644
index 7ce8d2a313..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/predef_time.idl
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#define b(q,w) kurt q w
-b(__DATE__, __TIME__)
-__DATE__
-__TIME__
-
-#include "predef_time.h"
diff --git a/lib/ic/test/ic_pp_SUITE_data/self_ref.idl b/lib/ic/test/ic_pp_SUITE_data/self_ref.idl
deleted file mode 100644
index 50f8a04e69..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/self_ref.idl
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#define foo (4 + foo)
-
-
-main()
-{
- foo;
-
-}
diff --git a/lib/ic/test/ic_pp_SUITE_data/separate.idl b/lib/ic/test/ic_pp_SUITE_data/separate.idl
deleted file mode 100644
index 6151a41709..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/separate.idl
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#define xstr(s) str(s)
-#define str(s) #s
-#define foo 4
-#define str1(s) #s lose(s)
-#define foo1 4
-
-main()
-{
- str(foo);
- str1(foo1);
- xstr(foo);
-
-#define qxstr(s) qstr(s)
- qxstr(qfoo);
-#define qstr(s) #s
- qstr( 4 ) ;
-#define qfoo 4
- qstr(qfoo);
-}
diff --git a/lib/ic/test/ic_pp_SUITE_data/swallow_sc.idl b/lib/ic/test/ic_pp_SUITE_data/swallow_sc.idl
deleted file mode 100644
index a42fcc6295..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/swallow_sc.idl
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-/* comment \
- ends */
-// comment\
-ends
-Line __LINE__
-#define SKIP_SPACES(p, limit) \
-{register char *lim = (limit); \
- while (p != lim) { \
- if (*p++ != ' ') { \
- p--; break; }}}
-
-
-main()
-{
- if (*p != 0)
- SKIP_SPACES (ppp, lim);
- else
- a = 17;
-}
diff --git a/lib/ic/test/ic_pp_SUITE_data/unintended_grp.idl b/lib/ic/test/ic_pp_SUITE_data/unintended_grp.idl
deleted file mode 100644
index ba744ac938..0000000000
--- a/lib/ic/test/ic_pp_SUITE_data/unintended_grp.idl
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-#define ceil_div( xz, yz) (xz + yz - 1) / yz
-#define ceil_div2(xz, yz) ((xz) + (yz) - 1) / (yz)
-
-#define b kurt
-
-main()
-{
- ceil_div(b & c, sizeof(int));
- ceil_div2(b & c, sizeof(int));
-
-}
diff --git a/lib/ic/test/ic_pragma_SUITE.erl b/lib/ic/test/ic_pragma_SUITE.erl
deleted file mode 100644
index bb95e59109..0000000000
--- a/lib/ic/test/ic_pragma_SUITE.erl
+++ /dev/null
@@ -1,301 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: ic_pragma_SUITE.erl
-%%
-%% Description:
-%% Test suite for the IFR object registration when
-%% pragmas are engaged
-%%
-%%-----------------------------------------------------------------
--module(ic_pragma_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
- init_per_suite/1, end_per_suite/1]).
--export([ifr_pragma_reg/1, pragma_error/1, uggly_pragmas/1]).
-
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
--define(REMAP_EXCEPT(F), case catch F of
- {'EXCEPTION', E} -> exit(E);
- R -> R
- end).
-%% Standard options to the ic compiler, NOTE unholy use of OutDir
-
--define(OUT(X), filename:join([proplists:get_value(priv_dir, Config), gen, to_list(X)])).
-
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-cases() ->
- [ifr_pragma_reg, pragma_error, uggly_pragmas].
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_suite(Config) ->
- io:format("Setting up.....~n"),
- mnesia:stop(),
- mnesia:delete_schema([node()]),
- mnesia:create_schema([node()]),
- mnesia:start(),
- orber:install([node()]),
- orber:start(),
- if
- is_list(Config) ->
- Config;
- true ->
- exit("Config not a list")
- end.
-
-end_per_suite(Config) ->
- io:format("Setting down.....~n"),
- orber:stop(),
- orber:uninstall(),
- mnesia:stop(),
- mnesia:delete_schema([node()]),
- Config.
-
-
-
-
-%%-----------------------------------------------------------------
-%% Test Case: IFR registration with pragmas
-%%-----------------------------------------------------------------
-%% Checks that IFR object is correctly registered under pragma engagement.
-ifr_pragma_reg(Config) when is_list(Config) ->
- ?REMAP_EXCEPT(ifr_pragma_reg_run(Config)).
-
-ifr_pragma_reg_run(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(ifr_pragma_reg),
- File0 = filename:join(DataDir, reg_m0),
- ok = ic:gen(File0, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}]),
- ok = compile(OutDir, ifr_pragma_files()),
- code:add_pathz(OutDir),
-
- %% OE_register for all files
- ok = 'oe_reg_m0':'oe_register'(),
-
- %% Pragma registration test
- OE_IFR = orber_ifr:find_repository(),
- io:format("~n##### Starting the test case #####~n"),
- check_pragma_effect(OE_IFR,"IDL:M1/T1:1.0"),
- check_pragma_effect(OE_IFR,"DCE:d62207a2-011e-11ce-88b4-0800090b5d3e:3"),
- check_pragma_effect(OE_IFR,"IDL:P2/T3:1.0"),
- check_pragma_effect(OE_IFR,"IDL:P1/M2/T4:2.4"),
-
- %% OE_unregister for all files
- ok = 'oe_reg_m0':'oe_unregister'(),
- code:del_path(OutDir),
- ok.
-
-
-ifr_pragma_files() -> ['oe_reg_m0'].
-
-
-check_pragma_effect(OE_IFR,ID) ->
- io:format("Checking for existance of : ~s~n",[ID]),
- case orber_ifr:lookup_id(OE_IFR,ID) of
- [] ->
- test_server:fail(ID ++ " does not exist"),
- false;
- {Def,_} ->
- io:format("Id refers to = {~p,#Bin}~n",[Def]),
- true
- end.
-
-
-
-
-%%-----------------------------------------------------------------
-%% Test Case: Syntactical / Semantical error pragma definitions
-%%-----------------------------------------------------------------
-%% Finds errornous pragma definitions under compilation.
-pragma_error(Config) when is_list(Config) ->
- ?REMAP_EXCEPT(pragma_error_run(Config)).
-
-pragma_error_run(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(pragma_error),
- File1 = filename:join(DataDir, reg_m1),
- File2 = filename:join(DataDir, reg_m2),
- File3 = filename:join(DataDir, reg_m3),
- File4 = filename:join(DataDir, reg_m4),
- File5 = filename:join(DataDir, reg_m5),
- File6 = filename:join(DataDir, reg_m6),
-
- error = ic:gen(File1, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
-
- error = ic:gen(File2, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
-
- error = ic:gen(File3, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
-
- ok = ic:gen(File4, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
-
- error = ic:gen(File5, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
-
- error = ic:gen(File6, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
- ok.
-
-
-
-
-%%-----------------------------------------------------------------
-%% Test Case: IFR registration with realy uggly placed pragmas
-%%-----------------------------------------------------------------
-%% Checks that IFR object is correctly registered under really uggly pragma engagement.
-uggly_pragmas(Config) when is_list(Config) ->
- ?REMAP_EXCEPT(uggly_pragmas_run(Config)).
-
-uggly_pragmas_run(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(ifr_pragma_reg),
- File0 = filename:join(DataDir, uggly),
-
- ok = ic:gen(File0, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}]),
-
- ok = compile(OutDir, uggly_pragma_files()),
- code:add_pathz(OutDir),
-
- %% OE_register for all files
- ok = 'oe_uggly':'oe_register'(),
-
- %% Pragma registration test
- OE_IFR = orber_ifr:find_repository(),
- io:format("~n##### Starting the test case #####~n"),
-
- check_pragma_effect(OE_IFR, "IDL:M:1.0"),
- check_pragma_effect(OE_IFR, "LOCAL:SomeLocalId:10"),
- check_pragma_effect(OE_IFR, "LOCAL:SomeLocalId:11"),
- check_pragma_effect(OE_IFR, "LOCAL:SomeLocalId:17"),
- check_pragma_effect(OE_IFR, "LOCAL:SomeLocalId:34"),
- check_pragma_effect(OE_IFR, "IDL:Exc1:2.2"),
- check_pragma_effect(OE_IFR, "IDL:Exc2:2.2"),
- check_pragma_effect(OE_IFR, "IDL:S:1.0"),
- check_pragma_effect(OE_IFR, "IDL:U:1.0"),
- check_pragma_effect(OE_IFR, "LOCAL:SomeLocalId:23"),
-
- %% OE_unregister for all files
- ok = 'oe_uggly':'oe_unregister'(),
-
- code:del_path(OutDir),
- ok.
-
-
-uggly_pragma_files() -> ['oe_uggly'].
-
-
-
-
-%%----------------------------
-
-
-stdopts(OutDir) ->
- [{outdir, OutDir}, {maxerrs, infinity}].
-
-
-compile(Dir, Files) ->
- compile(Dir, Files, []).
-
-compile(Dir, Files, Opts) ->
- {ok, Cwd} = file:get_cwd(),
- file:set_cwd(Dir),
- io:format("Changing to ~p~n", [Dir]),
- case catch do_compile(Files, Opts) of
- ok ->
- file:set_cwd(Cwd);
- Err ->
- file:set_cwd(Cwd),
- test_server:fail(Err)
- end.
-
-do_compile([], _Opts) -> ok;
-do_compile([F | Fs], Opts) ->
- io:format("Compiling ~p", [F]),
- case compile:file(F, Opts) of
- ok ->
- io:format(" ok~n", []),
- do_load(F, Opts),
- do_compile(Fs, Opts);
- {ok, _} ->
- io:format(" ok~n", []),
- do_load(F, Opts),
- do_compile(Fs, Opts);
- {ok, _, _} ->
- io:format(" ok~n", []),
- do_load(F, Opts),
- do_compile(Fs, Opts);
- Err ->
- io:format(" error: ~p~n", [Err]),
- Err
- end.
-
-do_load(File, Opts) ->
- case lists:member(load, Opts) of
- true ->
- io:format("Loading file ~p", [File]),
- code:purge(File),
- R = code:load_abs(File),
- io:format("Loaded: ~p", [R]);
- false ->
- ok
- end.
-
-
-to_list(X) when is_atom(X) -> atom_to_list(X);
-to_list(X) -> X.
-
-
-
diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m0.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m0.idl
deleted file mode 100644
index a7a90edc92..0000000000
--- a/lib/ic/test/ic_pragma_SUITE_data/reg_m0.idl
+++ /dev/null
@@ -1,78 +0,0 @@
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-// Normal pragmas
-
-module M1 {
-
- typedef long T1;
-
- typedef long T2;
-
-#pragma ID T2 "DCE:d62207a2-011e-11ce-88b4-0800090b5d3e:3"
-
-};
-
-
-#pragma prefix "P1"
-
-module M2 {
-
- module M3 {
-
-#pragma prefix "P2"
-
- interface I1 {
- void Op( in short b,
- out short c);
- };
- typedef long T3;
- };
-
-
- typedef long T4;
-
-#pragma version T4 2.4
-
-};
-
-
-
-/*
-
- Specified types with the following scoped names
- and RepositoryIds
-
- ::M1::T1 IDL:M1/T1:1.0
-
- ::M1::T2 DCE:d62207a2-011e-11ce-88b4-0800090b5d3e:3
-
- ::M2::M3::T3 IDL:P2/T3:1.0
-
- ::M2::T4 IDL:P1/M2/T4:2.4
-
-*/
-
-
-
-
-
-
-
-
diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m1.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m1.idl
deleted file mode 100644
index e222dcddc7..0000000000
--- a/lib/ic/test/ic_pragma_SUITE_data/reg_m1.idl
+++ /dev/null
@@ -1,76 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-// Bad pragma IDs
-
-// Completelly bad id
-module M1 {
-
- typedef long T1;
-
- typedef long T2;
-
-#pragma ID T2 "CompletelyBadId"
-
-};
-
-
-// Bad id, should start with DCE
-module M2 {
-
- typedef long T1;
-
- typedef long T2;
-
-#pragma ID T2 "BAD:d62207a2-011e-11ce-88b4-0800090b5d3e:3"
-
-};
-
-
-// Bad version in ID : not a short number
-module M3 {
-
- typedef long T1;
-
- typedef long T2;
-
-#pragma ID T2 "DCE:d62207a2-011e-11ce-88b4-0800090b5d3e:ABCD"
-
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m2.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m2.idl
deleted file mode 100644
index 351e662ac7..0000000000
--- a/lib/ic/test/ic_pragma_SUITE_data/reg_m2.idl
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-// Bad pragma versions
-
-
-// Bad major version : not a short number
-module M1 {
-
- typedef long T4;
-
-#pragma version T4 2000000000.4
-
-};
-
-// Bad minor version : not a short number
-module M2 {
-
- typedef long T4;
-
-#pragma version T4 2.4000000000000
-
-};
-
-
diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m3.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m3.idl
deleted file mode 100644
index 4f876da8bc..0000000000
--- a/lib/ic/test/ic_pragma_SUITE_data/reg_m3.idl
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-// Bad pragma prefixs
-
-module M2 {
-
- module M3 {
-
-#pragma prefix P2 // Should be "P2"
-
- interface I1 {
- void foo( in short b,
- out short c);
- };
- typedef long T3;
- };
-
-
- typedef long T4;
-};
-
-
diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m4.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m4.idl
deleted file mode 100644
index 9de19b645b..0000000000
--- a/lib/ic/test/ic_pragma_SUITE_data/reg_m4.idl
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-// Unrecognmizable pragmas
-
-module M1 {
-
- typedef long T1;
-
- typedef long T2;
-
-
- // Should be ID directive
-
-#pragma ShouldBeId T2 "DCE:d62207a2-011e-11ce-88b4-0800090b5d3e:3"
-
-};
-
- // Should be prefix directive
-
-#pragma ShouldBePrefix "P1"
-
-module M2 {
-
- module M3 {
-
- // Should be prefix directive
-
-#pragma ShouldBePrefix "P2"
-
- interface I1 {
- void foo( in short b,
- out short c);
- };
- typedef long T3;
- };
-
-
- typedef long T4;
-
-
- // Should be version
-
-#pragma ShouldBeVersion T4 2.4
-
-};
-
-
-
diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m5.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m5.idl
deleted file mode 100644
index 85ff419689..0000000000
--- a/lib/ic/test/ic_pragma_SUITE_data/reg_m5.idl
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-// Version not in valid form : major.ninor
-
-module M1 {
-
- typedef long T4;
-
- #pragma version T4 2
-
-};
diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m6.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m6.idl
deleted file mode 100644
index 4f876da8bc..0000000000
--- a/lib/ic/test/ic_pragma_SUITE_data/reg_m6.idl
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-// Bad pragma prefixs
-
-module M2 {
-
- module M3 {
-
-#pragma prefix P2 // Should be "P2"
-
- interface I1 {
- void foo( in short b,
- out short c);
- };
- typedef long T3;
- };
-
-
- typedef long T4;
-};
-
-
diff --git a/lib/ic/test/ic_pragma_SUITE_data/reg_m7.idl b/lib/ic/test/ic_pragma_SUITE_data/reg_m7.idl
deleted file mode 100644
index 038b670dd9..0000000000
--- a/lib/ic/test/ic_pragma_SUITE_data/reg_m7.idl
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-
-// Very uggly pragmas
-
-
-#pragma prefix "P1" // Normal pragma
-
-module M4 {
-
- module M5 {
-
-#pragma prefix "P2" // Inside a parameter list
-
- interface I1 {
- void Op(
- #pragma prefix "P2" // Inside a parameter list
- in short b,
- #pragma prefix "P2" // Inside a parameter list
- out short c
- #pragma prefix "P2" // Inside a parameter list
- );
- };
- typedef long T3;
- };
-
-};
-
-
-
-/*
-
- Specified types with the following scoped names
- and RepositoryIds
-
- ::M4::M5::T3 IDL:P2/T3:1.0
-
-*/
-
-
-
-
-
-
-
-
diff --git a/lib/ic/test/ic_pragma_SUITE_data/uggly.idl b/lib/ic/test/ic_pragma_SUITE_data/uggly.idl
deleted file mode 100644
index d12909c00e..0000000000
--- a/lib/ic/test/ic_pragma_SUITE_data/uggly.idl
+++ /dev/null
@@ -1,205 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-// Really uggly pragmas
-
-
-struct S {
-
-#pragma ID TDL1 "LOCAL:SomeLocalId:1"
-#pragma ID TDL1 "LOCAL:SomeLocalId:2"
-
-long a
-
-#pragma ID TDL1 "LOCAL:SomeLocalId:3"
-#pragma ID TDL1 "LOCAL:SomeLocalId:4"
-
-;
-
-#pragma ID TDL1 "LOCAL:SomeLocalId:5"
-#pragma ID TDL1 "LOCAL:SomeLocalId:6"
-
-long b
-
-#pragma ID TDL1 "LOCAL:SomeLocalId:7"
-#pragma ID TDL1 "LOCAL:SomeLocalId:8"
-
-;
-
-
-#pragma ID TDL1 "LOCAL:SomeLocalId:9"
-#pragma ID TDL1 "LOCAL:SomeLocalId:10"
-
-};
-
-
-typedef long TDL1;
-
-
-exception Exc1{
-
-#pragma version Exc1 2.2
-#pragma ID TDL2 "LOCAL:SomeLocalId:11"
-
-};
-
-
-typedef long TDL2;
-
-
-exception Exc2 {
-
-#pragma version Exc2 2.2
-#pragma ID TDL3 "LOCAL:SomeLocalId:11"
-
- long a
-
-#pragma ID TDL3 "LOCAL:SomeLocalId:12"
-#pragma ID TDL3 "LOCAL:SomeLocalId:13"
-
- ;
-
-#pragma ID TDL3 "LOCAL:SomeLocalId:14"
-#pragma ID TDL3 "LOCAL:SomeLocalId:15"
-
- long b
-
-#pragma ID TDL3 "LOCAL:SomeLocalId:16"
-
- ;
-
-#pragma ID TDL3 "LOCAL:SomeLocalId:17"
-
-
-};
-
-typedef long TDL3;
-
-enum E {
-#pragma ID E "LOCAL:SomeLocalId:18"
- a
-#pragma ID E "LOCAL:SomeLocalId:19"
- ,
-#pragma ID E "LOCAL:SomeLocalId:20"
- b
-#pragma ID E "LOCAL:SomeLocalId:21"
-,
-#pragma ID E "LOCAL:SomeLocalId:22"
- c
-#pragma ID E "LOCAL:SomeLocalId:23"
-};
-
-
-
-union U switch (long) {
-
-#pragma ID TDL4 "LOCAL:SomeLocalId:24"
-
- case 1:
-
-#pragma ID TDL4 "LOCAL:SomeLocalId:25"
-
- long a
-
-#pragma ID TDL4 "LOCAL:SomeLocalId:26"
-
-;
-
-#pragma ID TDL4 "LOCAL:SomeLocalId:27"
-
- case 2:
-
-#pragma ID TDL4 "LOCAL:SomeLocalId:28"
-
- case 3:
-
-#pragma ID TDL4 "LOCAL:SomeLocalId:29"
-
-long b
-
-#pragma ID TDL4 "LOCAL:SomeLocalId:30"
-
-;
-
-#pragma ID TDL4 "LOCAL:SomeLocalId:31"
-
- default :
-
-#pragma ID TDL4 "LOCAL:SomeLocalId:32"
-
-long c
-
-#pragma ID TDL4 "LOCAL:SomeLocalId:33"
-
-;
-
-#pragma ID TDL4 "LOCAL:SomeLocalId:34"
-
-};
-
-
-typedef long TDL4;
-
-
-
-module M {
-
- interface I {
-
- void fun1(
-
-#pragma version fun1 3.0
-#pragma ID TDL5 "LOCAL:SomeLocalId:35"
-
- in short b
-
-#pragma ID TDL5 "LOCAL:SomeLocalId:36"
-#pragma ID TDL5 "LOCAL:SomeLocalId:37"
-
- ,
-
-#pragma ID TDL5 "LOCAL:SomeLocalId:38"
-#pragma ID TDL5 "LOCAL:SomeLocalId:39"
-
- out short c
-
-#pragma ID TDL5 "LOCAL:SomeLocalId:40"
-#pragma ID TDL5 "LOCAL:SomeLocalId:41"
-
- );
-
-
- typedef long TDL5;
-
-
- void fun2(
-
-#pragma ID TDL6 "LOCAL:SomeLocalId:42"
-#pragma ID TDL6 "LOCAL:SomeLocalId:43"
-
- );
-
- typedef long TDL6;
-
- };
-
-
-
-};
-
diff --git a/lib/ic/test/ic_register_SUITE.erl b/lib/ic/test/ic_register_SUITE.erl
deleted file mode 100644
index 69eb923f85..0000000000
--- a/lib/ic/test/ic_register_SUITE.erl
+++ /dev/null
@@ -1,422 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: ic_register_SUITE.erl
-%%
-%% Description:
-%% Test suite for the IFR object registration
-%%
-%%-----------------------------------------------------------------
--module(ic_register_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
- init_per_suite/1, end_per_suite/1, ifr_reg_unreg/1]).
--export([ifr_inheritence_reg/1,ifr_reg_unreg_with_inheritence/1]).
--export([ifr_reg_unreg_with_inheritence_bad_order/1]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
--define(REMAP_EXCEPT(F), case catch F of
- {'EXCEPTION', E} -> exit(E);
- R -> R
- end).
-%% Standard options to the ic compiler, NOTE unholy use of OutDir
-
--define(OUT(X), filename:join([proplists:get_value(priv_dir, Config), gen, to_list(X)])).
-
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-cases() ->
- [ifr_reg_unreg, ifr_reg_unreg_with_inheritence,
- ifr_reg_unreg_with_inheritence_bad_order,
- ifr_inheritence_reg].
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-
-init_per_suite(Config) ->
- io:format("Setting up.....~n"),
- mnesia:stop(),
- mnesia:delete_schema([node()]),
- mnesia:create_schema([node()]),
- mnesia:start(),
- orber:install([node()]),
- orber:start(),
- if
- is_list(Config) ->
- Config;
- true ->
- exit("Config not a list")
- end.
-
-end_per_suite(Config) ->
- io:format("Setting down.....~n"),
- orber:stop(),
- orber:uninstall(),
- mnesia:stop(),
- mnesia:delete_schema([node()]),
- Config.
-
-
-
-%%-----------------------------------------------------------------
-%% Test Case: IFR type registration
-%%-----------------------------------------------------------------
-%% Checks that the generated register/unregister
-%% code for the IFR is correct.
-ifr_reg_unreg(Config) when is_list(Config) ->
- ?REMAP_EXCEPT(ifr_reg_unregt_run(Config)).
-
-ifr_reg_unregt_run(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(ifr_reg_unreg),
- File0 = filename:join(DataDir, reg_m8),
- File1 = filename:join(DataDir, reg_m9),
- File2 = filename:join(DataDir, reg_m10),
- ok = ic:gen(File0, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
- {ok, []} = ic:gen(File0, stdopts(OutDir)++[silent2, {preproc_flags,
- "-I" ++ DataDir}]),
- ok = ic:gen(File1, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
- {ok, []} = ic:gen(File1, stdopts(OutDir)++[silent2, {preproc_flags,
- "-I" ++ DataDir}]),
- ok = ic:gen(File2, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
- {ok, []} = ic:gen(File2, stdopts(OutDir)++[silent2, {preproc_flags,
- "-I" ++ DataDir}]),
- ok = compile(OutDir, ifr_reg_unreg_files()),
- code:add_pathz(OutDir),
- ok = 'oe_reg_m8':'oe_register'(),
- ok = 'oe_reg_m9':'oe_register'(),
- ok = 'oe_reg_m10':'oe_register'(),
- ok = 'oe_reg_m10':'oe_unregister'(),
- ok = 'oe_reg_m9':'oe_unregister'(),
- ok = 'oe_reg_m8':'oe_unregister'(),
- code:del_path(OutDir),
- ok.
-
-ifr_reg_unreg_files() -> ['oe_reg_m8', 'oe_reg_m9', 'oe_reg_m10'].
-
-
-
-%%-----------------------------------------------------------------
-%% Test Case: IFR registration when object inheritence
-%% is applied and registered.
-%%-----------------------------------------------------------------
-%% Checks that the generated register/unregister
-%% code for the IFR is correct, and works even when
-%% the object inheritence is registered. This fixes
-%% two bugs in ifr that caused crash when trying to
-%% use OE_register/OE_unregister in a sequence of
-%% compiled files that contained interfaces who
-%% inherited others in sequence.
-ifr_reg_unreg_with_inheritence(Config) when is_list(Config) ->
- ?REMAP_EXCEPT(ifr_reg_unreg_with_inheritence_run(Config)).
-
-ifr_reg_unreg_with_inheritence_run(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(ifr_reg_unreg),
- File0 = filename:join(DataDir, reg_m8),
- File1 = filename:join(DataDir, reg_m9),
- File2 = filename:join(DataDir, reg_m10),
- File3 = filename:join(DataDir, reg_m11),
- File4 = filename:join(DataDir, reg_m12),
- ok = ic:gen(File0, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
- {ok, []} = ic:gen(File0, stdopts(OutDir)++[silent2, {preproc_flags,
- "-I" ++ DataDir}]),
- ok = ic:gen(File1, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
- {ok, []} = ic:gen(File1, stdopts(OutDir)++[silent2, {preproc_flags,
- "-I" ++ DataDir}]),
- ok = ic:gen(File2, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
- {ok, []} = ic:gen(File2, stdopts(OutDir)++[silent2, {preproc_flags,
- "-I" ++ DataDir}]),
- ok = ic:gen(File3, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
- {ok, []} = ic:gen(File3, stdopts(OutDir)++[silent2, {preproc_flags,
- "-I" ++ DataDir}]),
- ok = ic:gen(File4, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
- {ok, []} = ic:gen(File4, stdopts(OutDir)++[silent2, {preproc_flags,
- "-I" ++ DataDir}]),
- ok = compile(OutDir, ifr_reg_unreg_with_inheritence_files()),
- code:add_pathz(OutDir),
- ok = 'oe_reg_m8':'oe_register'(),
- ok = 'oe_reg_m9':'oe_register'(),
- ok = 'oe_reg_m10':'oe_register'(),
- ok = 'oe_reg_m11':'oe_register'(),
- ok = 'oe_reg_m12':'oe_register'(),
- ok = 'oe_reg_m8':'oe_unregister'(),
- ok = 'oe_reg_m9':'oe_unregister'(),
- ok = 'oe_reg_m10':'oe_unregister'(),
- ok = 'oe_reg_m11':'oe_unregister'(),
- ok = 'oe_reg_m12':'oe_unregister'(),
- code:del_path(OutDir),
- ok.
-
-ifr_reg_unreg_with_inheritence_files() ->
- ['oe_reg_m8', 'oe_reg_m9', 'oe_reg_m10', 'oe_reg_m11', 'oe_reg_m12'].
-
-
-
-
-
-%%-----------------------------------------------------------------
-%% Test Case: IFR registration when object inheritence
-%% is applied and registered in a bad order.
-%% Modules included and used from an ifr object
-%% are not allready registered when the current
-%% object is getting registered.
-%%-----------------------------------------------------------------
-ifr_reg_unreg_with_inheritence_bad_order(Config) when is_list(Config) ->
- ?REMAP_EXCEPT(ifr_reg_unreg_with_inheritence_bad_order_run(Config)).
-
-ifr_reg_unreg_with_inheritence_bad_order_run(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(ifr_reg_unreg),
- File1 = filename:join(DataDir, reg_m9),
- File2 = filename:join(DataDir, reg_m10),
- File4 = filename:join(DataDir, reg_m12),
- ok = ic:gen(File1, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
- {ok, []} = ic:gen(File1, stdopts(OutDir)++[silent2, {preproc_flags,
- "-I" ++ DataDir}]),
- ok = ic:gen(File2, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
- {ok, []} = ic:gen(File2, stdopts(OutDir)++[silent2, {preproc_flags,
- "-I" ++ DataDir}]),
- ok = ic:gen(File4, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
- {ok, []} = ic:gen(File4, stdopts(OutDir)++[silent2, {preproc_flags,
- "-I" ++ DataDir}]),
- ok = compile(OutDir, ifr_reg_unreg_with_inheritence_files()),
- code:add_pathz(OutDir),
- case catch 'oe_reg_m12':'oe_register'() of
- {'EXIT',Reason1} ->
- io:format("IFR object missing detected : ~p~n",[Reason1]),
- true;
- _ ->
- test_server:fail("Failed to detect object missing : IDL:M1:1.0~n")
- end,
- ok = 'oe_reg_m9':'oe_register'(),
- case catch 'oe_reg_m10':'oe_register'() of
- {'EXIT',Reason2} ->
- io:format("IFR object missing detected : ~p~n",[Reason2]),
- true;
- _ ->
- test_server:fail("Failed to detect object missing : IDL:M0:1.0~n")
- end,
- ok = 'oe_reg_m9':'oe_unregister'(),
- code:del_path(OutDir),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: IFR registration with inheritence is correctly registered
-%%-----------------------------------------------------------------
-ifr_inheritence_reg(Config) when is_list(Config) ->
- ?REMAP_EXCEPT(ifr_inh_reg_run(Config)).
-
-ifr_inh_reg_run(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- OutDir = ?OUT(ifr_reg_unreg),
- File0 = filename:join(DataDir, reg_m8),
- File1 = filename:join(DataDir, reg_m9),
- File2 = filename:join(DataDir, reg_m10),
- File3 = filename:join(DataDir, reg_m11),
- File4 = filename:join(DataDir, reg_m12),
- ok = ic:gen(File0, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
- {ok, []} = ic:gen(File0, stdopts(OutDir)++[silent2, {preproc_flags,
- "-I" ++ DataDir}]),
- ok = ic:gen(File1, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
- {ok, []} = ic:gen(File1, stdopts(OutDir)++[silent2, {preproc_flags,
- "-I" ++ DataDir}]),
- ok = ic:gen(File2, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
- {ok, []} = ic:gen(File2, stdopts(OutDir)++[silent2, {preproc_flags,
- "-I" ++ DataDir}]),
- ok = ic:gen(File3, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
- {ok, []} = ic:gen(File3, stdopts(OutDir)++[silent2, {preproc_flags,
- "-I" ++ DataDir}]),
- ok = ic:gen(File4, stdopts(OutDir)++[{preproc_flags,
- "-I" ++ DataDir}] ),
- {ok, []} = ic:gen(File4, stdopts(OutDir)++[silent2, {preproc_flags,
- "-I" ++ DataDir}]),
- ok = compile(OutDir, ifr_reg_unreg_with_inheritence_files()),
- code:add_pathz(OutDir),
- %% OE_register for all files
- ok = 'oe_reg_m8':'oe_register'(),
- ok = 'oe_reg_m9':'oe_register'(),
- ok = 'oe_reg_m10':'oe_register'(),
- ok = 'oe_reg_m11':'oe_register'(),
- ok = 'oe_reg_m12':'oe_register'(),
-
- %% Inheritence registration test
- OE_IFR = orber_ifr:find_repository(),
- %% Interfaces that not inherit from other interfaces
- [] = get_inh(OE_IFR, "IDL:m0/i0:1.0"),
- [] = get_inh(OE_IFR, "IDL:m1/i1:1.0"),
- [] = get_inh(OE_IFR, "IDL:m3/i3:1.0"),
- %% Interfaces that inherit from other interfaces
- ["IDL:m1/i1:1.0"] = get_inh(OE_IFR, "IDL:m2/i2:1.0"),
- ["IDL:m1/i1:1.0","IDL:m2/i2:1.0"] = get_inh(OE_IFR, "IDL:m4/i4:1.0"),
- ["IDL:m3/i3:1.0"] = get_inh(OE_IFR, "IDL:m4/i5:1.0"),
-
- %% OE_unregister for all files
- ok = 'oe_reg_m8':'oe_unregister'(),
- ok = 'oe_reg_m9':'oe_unregister'(),
- ok = 'oe_reg_m10':'oe_unregister'(),
- ok = 'oe_reg_m11':'oe_unregister'(),
- ok = 'oe_reg_m12':'oe_unregister'(),
- code:del_path(OutDir),
- ok.
-
-
-get_inh(OE_IFR,ID) ->
- OE_CURRENT = orber_ifr:lookup_id(OE_IFR,ID),
- INH_LIST = orber_ifr:get_base_interfaces(OE_CURRENT),
- case INH_LIST of
- [] ->
- io:format("~nInterface ~p inherits from nobody.~n",[ID]),
- [];
- _ ->
- print_inh_list_ids(ID, INH_LIST, [])
- end.
-
-print_inh_list_ids(_ID, [], Acc) ->
- lists:reverse(Acc);
-print_inh_list_ids(ID, [H|T], Acc) ->
- io:format("~n"),
- Parent = orber_ifr:get_id(H),
- io:format("Interface ~p inherits from ~p.~n", [ID, Parent]),
- print_inh_list_ids(ID, T, [Parent|Acc]).
-
-
-
-
-stdopts(OutDir) ->
- [{outdir, OutDir}, {maxerrs, infinity}].
-
-
-compile(Dir, Files) ->
- compile(Dir, Files, []).
-
-compile(Dir, Files, Opts) ->
- {ok, Cwd} = file:get_cwd(),
- file:set_cwd(Dir),
- io:format("Changing to ~p~n", [Dir]),
- case catch do_compile(Files, Opts) of
- ok ->
- file:set_cwd(Cwd);
- Err ->
- file:set_cwd(Cwd),
- test_server:fail(Err)
- end.
-
-do_compile([], _Opts) -> ok;
-do_compile([F | Fs], Opts) ->
- io:format("Compiling ~p", [F]),
- case compile:file(F, Opts) of
- ok ->
- io:format(" ok~n", []),
- do_load(F, Opts),
- do_compile(Fs, Opts);
- {ok, _} ->
- io:format(" ok~n", []),
- do_load(F, Opts),
- do_compile(Fs, Opts);
- {ok, _, _} ->
- io:format(" ok~n", []),
- do_load(F, Opts),
- do_compile(Fs, Opts);
- Err ->
- io:format(" error: ~p~n", [Err]),
- Err
- end.
-
-do_load(File, Opts) ->
- case lists:member(load, Opts) of
- true ->
- io:format("Loading file ~p", [File]),
- code:purge(File),
- R = code:load_abs(File),
- io:format("Loaded: ~p", [R]);
- false ->
- ok
- end.
-
-
-to_list(X) when is_atom(X) -> atom_to_list(X);
-to_list(X) -> X.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/ic/test/ic_register_SUITE_data/reg_m10.idl b/lib/ic/test/ic_register_SUITE_data/reg_m10.idl
deleted file mode 100644
index cc9156ae0c..0000000000
--- a/lib/ic/test/ic_register_SUITE_data/reg_m10.idl
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-//
-// IDL for testing register/unregister in the IFR when using included specs
-//
-#include "reg_m9.idl"
-
-typedef sequence<long> Sequence1;
-
-#include "reg_m8.idl"
-
-module m2 {
-
- interface i2 : m1::i1
- {
- short op3( in long a, inout char b, out long c );
- };
-
-
-};
-
diff --git a/lib/ic/test/ic_register_SUITE_data/reg_m11.idl b/lib/ic/test/ic_register_SUITE_data/reg_m11.idl
deleted file mode 100644
index 6a6c49a48e..0000000000
--- a/lib/ic/test/ic_register_SUITE_data/reg_m11.idl
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-//
-// IDL for testing register/unregister in the IFR when using included specs
-//
-
-module m3 {
-
- interface i3
- {
- short op4( in long a, inout char b, out long c );
- };
-
-
-};
-
diff --git a/lib/ic/test/ic_register_SUITE_data/reg_m12.idl b/lib/ic/test/ic_register_SUITE_data/reg_m12.idl
deleted file mode 100644
index 0c5f8083b5..0000000000
--- a/lib/ic/test/ic_register_SUITE_data/reg_m12.idl
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-//
-// IDL for testing register/unregister in the IFR when using included specs
-// Special case with multiple inheritence.
-//
-#include "reg_m10.idl"
-#include "reg_m11.idl"
-
-module m4 {
-
- interface i4 : m2::i2
- {
- short op5( in long a, inout char b, out long c );
- };
-
- interface i5 : m3::i3
- {
- short op6( in long a, inout char b, out long c );
- };
-
-
-};
-
diff --git a/lib/ic/test/ic_register_SUITE_data/reg_m8.idl b/lib/ic/test/ic_register_SUITE_data/reg_m8.idl
deleted file mode 100644
index 5129b6b636..0000000000
--- a/lib/ic/test/ic_register_SUITE_data/reg_m8.idl
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-//
-// IDL for testing register/unregister in the IFR when using included specs
-//
-module m0 {
-
- interface i0 {
- void op1( in short c );
- float op2( in char a);
-
- };
-
-
-};
-
diff --git a/lib/ic/test/ic_register_SUITE_data/reg_m9.idl b/lib/ic/test/ic_register_SUITE_data/reg_m9.idl
deleted file mode 100644
index c077d289b6..0000000000
--- a/lib/ic/test/ic_register_SUITE_data/reg_m9.idl
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1998-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-//
-// IDL for testing register/unregister in the IFR when using included specs
-//
-module m1 {
-
- interface i1 {
- void op1( in short c );
- float op2( in char a);
-
- };
-
-
-};
-
diff --git a/lib/ic/test/ic_smoke.spec b/lib/ic/test/ic_smoke.spec
deleted file mode 100644
index ec3b5758b1..0000000000
--- a/lib/ic/test/ic_smoke.spec
+++ /dev/null
@@ -1 +0,0 @@
-{suites,"../ic_test",[ic_SUITE]}.
diff --git a/lib/ic/test/java_client_erl_server_SUITE.erl b/lib/ic/test/java_client_erl_server_SUITE.erl
deleted file mode 100644
index 9fe52249ba..0000000000
--- a/lib/ic/test/java_client_erl_server_SUITE.erl
+++ /dev/null
@@ -1,319 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%%----------------------------------------------------------------------
-%%% Purpose : Test suite for the backends of the IDL compiler
-%%%----------------------------------------------------------------------
-
--module(java_client_erl_server_SUITE).
--include_lib("common_test/include/ct.hrl").
-
-
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
- init_per_suite/1,end_per_suite/1,
- init_per_testcase/2,end_per_testcase/2]).
--export([marshal_ll/1,marshal_ull/1,
- marshal_l/1,marshal_ul/1,
- marshal_s/1,marshal_us/1,
- marshal_c/1,marshal_wc/1,
- marshal_str/1,
- marshal_any_3/1,marshal_any_2/1]).
-
-
-%% Top of cases
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-cases() ->
- [marshal_ll, marshal_ull, marshal_l, marshal_ul,
- marshal_s, marshal_us, marshal_c, marshal_wc,
- marshal_str, marshal_any_3, marshal_any_2].
-
-init_per_suite(Config) when is_list(Config) ->
- case case code:priv_dir(jinterface) of
- {error,bad_name} ->
- false;
- P ->
- case filelib:wildcard(filename:join(P, "*.jar")) of
- [_|_] ->
- true;
- [] ->
- false
- end
- end
- of
- true ->
- case find_executable(["java"]) of
- false ->
- {skip,"Found no Java VM"};
- Path ->
- [{java,Path}|Config]
- end;
- false ->
- {skip,"No jinterface application"}
- end.
-
-
-find_executable([]) ->
- false;
-find_executable([E|T]) ->
- case os:find_executable(E) of
- false -> find_executable(T);
- Path -> Path
- end.
-
-end_per_suite(Config) -> Config.
-
-
-
-%% Add/remove code path and watchdog before/after each test case.
-%%
-init_per_testcase(_Case, Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- code:add_patha(DataDir),
-
- %% Since other test suites use the module m_i et,al, we have
- %% to make sure we are using the right modules.
- code:purge(m_i),
- code:purge(m_i_impl),
- code:purge(oe_java_erl_test),
- code:load_file(m_i),
- code:load_file(m_i_impl),
- code:load_file(oe_java_erl_test),
-
- WatchDog = test_server:timetrap(test_server:seconds(20)),
- [{watchdog, WatchDog}| Config].
-
-end_per_testcase(_Case, Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- code:del_path(DataDir),
- WatchDog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(WatchDog).
-
-
-
-%%--------------------------------------------------------------------
-%%
-%% Test cases
-
-%% Testing marshalling of IDL long long
-marshal_ll(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- {ok,Server} = m_i:oe_create_link([], {local,marshal_ll}),
- ok = java(proplists:get_value(java, Config), DataDir, "JavaClient",
- ["JavaClient",node(),erlang:get_cookie(),marshal_ll]),
- ok = m_i:stop(Server),
- ok.
-
-%% Testing marshalling of IDL unsigned long long
-marshal_ull(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- {ok,Server} = m_i:oe_create_link([], {local,marshal_ull}),
- ok = java(proplists:get_value(java, Config), DataDir, "JavaClient",
- ["JavaClient",node(),erlang:get_cookie(),marshal_ull]),
- ok = m_i:stop(Server),
- ok.
-
-%% Testing marshalling of IDL long
-marshal_l(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- {ok,Server} = m_i:oe_create_link([], {local,marshal_l}),
- ok = java(proplists:get_value(java, Config), DataDir, "JavaClient",
- ["JavaClient",node(),erlang:get_cookie(),marshal_l]),
- ok = m_i:stop(Server),
- ok.
-
-%% Testing marshalling of IDL unsigned long
-marshal_ul(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- {ok,Server} = m_i:oe_create_link([], {local,marshal_ul}),
- ok = java(proplists:get_value(java, Config), DataDir, "JavaClient",
- ["JavaClient",node(),erlang:get_cookie(),marshal_ul]),
- ok = m_i:stop(Server),
- ok.
-
-%% Testing marshalling of IDL short
-marshal_s(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- {ok,Server} = m_i:oe_create_link([], {local,marshal_s}),
- ok = java(proplists:get_value(java, Config), DataDir, "JavaClient",
- ["JavaClient",node(),erlang:get_cookie(),marshal_s]),
- ok = m_i:stop(Server),
- ok.
-
-%% Testing marshalling of IDL unsigned short
-marshal_us(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- {ok,Server} = m_i:oe_create_link([], {local,marshal_us}),
- ok = java(proplists:get_value(java, Config), DataDir, "JavaClient",
- ["JavaClient",node(),erlang:get_cookie(),marshal_us]),
- ok = m_i:stop(Server),
- ok.
-
-%% Testing marshalling of IDL char
-marshal_c(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- {ok,Server} = m_i:oe_create_link([], {local,marshal_c}),
- ok = java(proplists:get_value(java, Config), DataDir, "JavaClient",
- ["JavaClient",node(),erlang:get_cookie(),marshal_c]),
- ok = m_i:stop(Server),
- ok.
-
-%% Testing marshalling of IDL char
-marshal_wc(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- {ok,Server} = m_i:oe_create_link([], {local,marshal_wc}),
- ok = java(proplists:get_value(java, Config), DataDir, "JavaClient",
- ["JavaClient",node(),erlang:get_cookie(),marshal_wc]),
- ok = m_i:stop(Server),
- ok.
-
-%% Testing marshalling of IDL string
-marshal_str(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- {ok,Server} = m_i:oe_create_link([], {local,marshal_str}),
- ok = java(proplists:get_value(java, Config), DataDir,
-%%% "-DOtpConnection.trace=4 "
- "JavaClient",
- ["JavaClient",node(),erlang:get_cookie(),marshal_str]),
- ok = m_i:stop(Server),
- ok.
-
-%% Testing marshalling of IDL any
-marshal_any_3(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- {ok,Server} = m_i:oe_create_link([], {local,marshal_any_3}),
- ok = java(proplists:get_value(java, Config), DataDir, "JavaClient",
- ["JavaClient",node(),erlang:get_cookie(),marshal_any_3]),
- ok = m_i:stop(Server),
- ok.
-
-marshal_any_2(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- {ok,Server} = m_i:oe_create_link([], {local,marshal_any_2}),
- ok = java(proplists:get_value(java, Config), DataDir, "JavaClient",
- ["JavaClient",node(),erlang:get_cookie(),marshal_any_2]),
- ok = m_i:stop(Server),
- ok.
-
-%%--------------------------------------------------------------------
-%%
-%% Utilities
-
-
-java(Java, Dir, ClassAndArgs) ->
- cmd(Java++" -classpath \""++classpath(Dir)++"\" "++ClassAndArgs).
-
-java(Java, Dir, Class, Args) ->
- java(Java, Dir, Class++" "++to_string(Args)).
-
-to_string([H|T]) when is_integer(H) ->
- integer_to_list(H)++" "++to_string(T);
-to_string([H|T]) when is_atom(H) ->
- atom_to_list(H)++" "++to_string(T);
-to_string([H|T]) when is_list(H) ->
- lists:flatten(H)++" "++to_string(T);
-to_string([]) -> [].
-
-% javac(Dir, File) ->
-% cmd("javac -d "++Dir++" -classpath "++classpath(Dir)++" "++
-% filename:join(Dir, File)).
-
-classpath(Dir) ->
- PS =
- case os:type() of
- {win32, _} -> ";";
- _ -> ":"
- end,
- Dir++PS++
- filename:join([code:lib_dir(ic),"priv","ic.jar"])++PS++
- filename:join([code:lib_dir(jinterface),"priv","OtpErlang.jar"])++PS++
- os:getenv("CLASSPATH", "").
-
-cmd(Cmd) ->
- PortOpts = [{line,80},eof,exit_status,stderr_to_stdout],
- io:format("<cmd> ~ts~n", [Cmd]),
- case catch open_port({spawn,Cmd}, PortOpts) of
- Port when is_port(Port) ->
- Result = cmd_loop(Port, []),
- io:format("<cmd=~w>~n", [Result]),
- case Result of
- 0 -> ok;
- ExitCode when is_integer(ExitCode) -> {error,ExitCode};
- Error -> Error
- end;
- {'EXIT',Reason} ->
- {error,Reason}
- end.
-
-cmd_loop(Port, Line) ->
- receive
- {Port,eof} ->
- receive
- {Port,{exit_status,ExitStatus}} ->
- ExitStatus
- after 1 ->
- undefined
- end;
- {Port,{exit_status,ExitStatus}} ->
- receive
- {Port,eof} ->
- ok after 1 -> ok end,
- ExitStatus;
- {Port,{data,{Tag,Data}}} ->
- case Tag of
- eol ->
- io:put_chars([Line|cr_to_nl(Data)]),
- io:nl(),
- cmd_loop(Port, []);
- noeol ->
- cmd_loop(Port, [Line|cr_to_nl(Data)])
- end;
- {'EXIT',Port,Reason} ->
- {error,Reason};
- Other ->
- io:format("WARNING: Unexpected at ~s:~p: ~p~n",
- [?MODULE_STRING,?LINE,Other]),
- cmd_loop(Port, Line)
- end.
-
-%% Convert lonely CR to NL, and CRLF to NL
-%%
-cr_to_nl([$\r,$\n|T]) ->
- [$\n|cr_to_nl(T)];
-cr_to_nl([$\r|T]) ->
- [$\n|cr_to_nl(T)];
-cr_to_nl([C|T]) ->
- [C|cr_to_nl(T)];
-cr_to_nl([]) ->
- [].
diff --git a/lib/ic/test/java_client_erl_server_SUITE_data/JavaClient.java b/lib/ic/test/java_client_erl_server_SUITE_data/JavaClient.java
deleted file mode 100644
index 8092d7c627..0000000000
--- a/lib/ic/test/java_client_erl_server_SUITE_data/JavaClient.java
+++ /dev/null
@@ -1,760 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2003-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-public class JavaClient {
-
- public static void main(String[] argv)
- {
- System.out.println("Hello World!");
- if (argv.length < 4) {
- System.out.println("Too few arguments!");
- System.exit(1);
- }
- // for (int j = 0; j < argv.length; j++)
- // System.out.println(argv[j]);
- try {
- if (argv[3].equals("marshal_ll")) {
- System.out.println("marshal_ll");
- marshal_ll(argv[0], argv[1], argv[2], argv[3]);
- }
- else if (argv[3].equals("marshal_ull")) {
- marshal_ull(argv[0], argv[1], argv[2], argv[3]);
- }
- else if (argv[3].equals("marshal_l")) {
- marshal_l(argv[0], argv[1], argv[2], argv[3]);
- }
- else if (argv[3].equals("marshal_ul")) {
- marshal_ul(argv[0], argv[1], argv[2], argv[3]);
- }
- else if (argv[3].equals("marshal_s")) {
- marshal_s(argv[0], argv[1], argv[2], argv[3]);
- }
- else if (argv[3].equals("marshal_us")) {
- marshal_us(argv[0], argv[1], argv[2], argv[3]);
- }
- else if (argv[3].equals("marshal_c")) {
- marshal_c(argv[0], argv[1], argv[2], argv[3]);
- }
- else if (argv[3].equals("marshal_wc")) {
- marshal_wc(argv[0], argv[1], argv[2], argv[3]);
- }
- else if (argv[3].equals("marshal_str")) {
- marshal_str(argv[0], argv[1], argv[2], argv[3]);
- }
- else if (argv[3].equals("marshal_any_3")) {
- marshal_any_3(argv[0], argv[1], argv[2], argv[3]);
- }
- else if (argv[3].equals("marshal_any_2")) {
- marshal_any_2(argv[0], argv[1], argv[2], argv[3]);
- }
- else {
- System.out.println("Unknown test: "+argv[3]);
- System.exit(2);
- }
- } catch (java.lang.Exception e) {
- System.out.println("Exception!: "+e);
- System.exit(3);
- }
- System.exit(0);
- }
-
-
-
- static void marshal_ll(String selfNode, String peerNode,
- String cookie, String serverName)
- throws java.lang.Exception
- {
- m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
- // Just warming up..
- System.out.println("Just warming up.."+i);
- verify_ll(i, 3, 2, 1);
- verify_ll(i, 5, 4, 3);
- verify_ll(i, -128, 0, 1);
- // The small integer border
- verify_ll(i, 255, 0, 1);
- verify_ll(i, 256, 0, 1);
- // The integer border
- verify_ll(i, (1L<<26)-1L, 0L, 1);
- verify_ll(i, 1L<<26, 0L, 1);
- verify_ll(i, -(1L<<26), 0L, 1);
- verify_ll(i, (1L<<27)-1L, 0L, 1);
- verify_ll(i, 1L<<27, 0L, 1);
- verify_ll(i, -(1L<<27), 0L, 1);
- // Bignum byte borders
- verify_ll(i, (1L<<32)-1L, 0L, 1);
- verify_ll(i, 1L<<32, 0L, 1);
- verify_ll(i, -(1L<<32)+1L, 0L, 1);
- verify_ll(i, -(1L<<32), 0L, 1);
- verify_ll(i, (1L<<40)-1L, 0L, 1);
- verify_ll(i, 1L<<40, 0L, 1);
- verify_ll(i, -(1L<<40)+1L, 0L, 1);
- verify_ll(i, -(1L<<40), 0L, 1);
- verify_ll(i, (1L<<48)-1L, 0L, 1);
- verify_ll(i, 1L<<48, 0L, 1);
- verify_ll(i, -(1L<<48)+1L, 0L, 1);
- verify_ll(i, -(1L<<48), 0L, 1);
- // Java long border
- verify_ll(i, java.lang.Long.MAX_VALUE, 0L, 1);
- verify_ll(i, java.lang.Long.MIN_VALUE, 0L, 1);
- verify_ll(i, -1L, 0L, 1);
- // Impossible decodes
- verify_ll_bad(i, java.lang.Long.MAX_VALUE, -1L, 1);
- verify_ll_bad(i, java.lang.Long.MIN_VALUE, 1L, 1);
- verify_ll_bad(i, java.lang.Long.MIN_VALUE, 0L, -1);
- verify_ll_bad(i, java.lang.Long.MAX_VALUE, -1L, 2);
- verify_ll_bad(i, java.lang.Long.MIN_VALUE, 0L, 2);
- }
-
- static void marshal_ull(String selfNode, String peerNode,
- String cookie, String serverName)
- throws java.lang.Exception
- {
- m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
- // Just warming up..
- verify_ull(i, 3, 2, 1);
- verify_ull(i, 5, 4, 3);
- // The small integer border
- verify_ull(i, 255, 0, 1);
- verify_ull(i, 256, 0, 1);
- // The integer border
- verify_ull(i, (1L<<26)-1L, 0L, 1);
- verify_ull(i, 1L<<26, 0L, 1);
- verify_ull(i, (1L<<27)-1L, 0L, 1);
- verify_ull(i, 1L<<27, 0L, 1);
- // Bignum byte borders
- verify_ull(i, (1L<<32)-1L, 0L, 1);
- verify_ull(i, 1L<<32, 0L, 1);
- verify_ull(i, (1L<<40)-1L, 0L, 1);
- verify_ull(i, 1L<<40, 0L, 1);
- verify_ull(i, (1L<<48)-1L, 0L, 1);
- verify_ull(i, 1L<<48, 0L, 1);
- // Java long border
- verify_ull(i, java.lang.Long.MAX_VALUE, 0L, 1);
- verify_ull(i, java.lang.Long.MIN_VALUE, 0L, 1);
- verify_ull(i, -1L, 0L, 1);
- verify_ull(i, java.lang.Long.MAX_VALUE,
- java.lang.Long.MIN_VALUE, 1);
- // Impossible decodes
- verify_ull_bad(i, -1L, -1L, 1);
- verify_ull_bad(i, java.lang.Long.MAX_VALUE, -1L, 2);
- }
-
- static void marshal_l(String selfNode, String peerNode,
- String cookie, String serverName)
- throws java.lang.Exception
- {
- m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
- // Just warming up..
- verify_l(i, 3, 2, 1);
- verify_l(i, 5, 4, 3);
- verify_l(i, -128, 0, 1);
- // The small integer border
- verify_l(i, 255, 0, 1);
- verify_l(i, 256, 0, 1);
- // The integer border
- verify_l(i, (1<<26)-1, 0, 1);
- verify_l(i, 1<<26, 0, 1);
- verify_l(i, -(1<<26), 0, 1);
- verify_l(i, (1<<27)-1, 0, 1);
- verify_l(i, 1<<27, 0, 1);
- verify_l(i, -(1<<27), 0, 1);
- // Java int border
- verify_l(i, java.lang.Integer.MAX_VALUE, 0, 1);
- verify_l(i, java.lang.Integer.MIN_VALUE, 0, 1);
- // Impossible decodes
- verify_l_bad(i, java.lang.Integer.MAX_VALUE, -1, 1);
- verify_l_bad(i, java.lang.Integer.MIN_VALUE, 1, 1);
- verify_l_bad(i, java.lang.Integer.MIN_VALUE, 0, -1);
- }
-
- static void marshal_ul(String selfNode, String peerNode,
- String cookie, String serverName)
- throws java.lang.Exception
- {
- m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
- // Just warming up..
- verify_ul(i, 3, 2, 1);
- verify_ul(i, 5, 4, 3);
- // The small integer border
- verify_ul(i, 255, 0, 1);
- verify_ul(i, 256, 0, 1);
- // The integer border
- verify_ul(i, (1<<26)-1, 0, 1);
- verify_ul(i, 1<<26, 0, 1);
- verify_ul(i, (1<<27)-1, 0, 1);
- verify_ul(i, 1<<27, 0, 1);
- // Java int border
- verify_ul(i, java.lang.Integer.MAX_VALUE, 0, 1);
- verify_ul(i, java.lang.Integer.MIN_VALUE, 0, 1);
- verify_ul(i, -1, 0, 1);
- verify_ul(i, java.lang.Integer.MAX_VALUE,
- java.lang.Integer.MIN_VALUE, 1);
- // Impossible decodes
- verify_ul_bad(i, -1, -1, 1);
- }
-
- static void marshal_s(String selfNode, String peerNode,
- String cookie, String serverName)
- throws java.lang.Exception
- {
- m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
- // Just warming up..
- verify_s(i, 3, 2, 1);
- verify_s(i, 5, 4, 3);
- verify_s(i, -128, 0, 1);
- // The small integer border
- verify_s(i, 255, 0, 1);
- verify_s(i, 256, 0, 1);
- // Java short border
- verify_s(i, java.lang.Short.MAX_VALUE, 0, 1);
- verify_s(i, java.lang.Short.MIN_VALUE, 0, 1);
- // Impossible decodes
- verify_s_bad(i, java.lang.Short.MAX_VALUE, -1, 1);
- verify_s_bad(i, java.lang.Short.MIN_VALUE, 1, 1);
- verify_s_bad(i, java.lang.Short.MIN_VALUE, 0, -1);
- }
-
- static void marshal_us(String selfNode, String peerNode,
- String cookie, String serverName)
- throws java.lang.Exception
- {
- m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
- // Just warming up..
- verify_us(i, 3, 2, 1);
- verify_us(i, 5, 4, 3);
- // The small integer border
- verify_us(i, 255, 0, 1);
- verify_us(i, 256, 0, 1);
- // Java short border
- verify_us(i, java.lang.Short.MAX_VALUE, 0, 1);
- verify_us(i, java.lang.Short.MIN_VALUE, 0, 1);
- verify_us(i, -1, 0, 1);
- verify_us(i, java.lang.Short.MAX_VALUE,
- java.lang.Short.MIN_VALUE, 1);
- // Impossible decodes
- verify_us_bad(i, -1, -1, 1);
- }
-
- static void marshal_c(String selfNode, String peerNode,
- String cookie, String serverName)
- throws java.lang.Exception
- {
- m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
- // Just warming up..
- verify_c(i, '\3', '\2', 1);
- verify_c(i, '\5', '\4', 3);
- // The small integer border
- verify_c(i, '\u00FF', '\0', 1);
- verify_c(i, '\u0100', '\0', 1);
- // Java char border
- verify_c(i, java.lang.Character.MAX_VALUE, '\0', 1);
- verify_c(i, java.lang.Character.MIN_VALUE, '\0', 1);
- verify_c(i, java.lang.Character.MAX_VALUE,
- java.lang.Character.MIN_VALUE, 1);
- // Impossible decodes
- verify_c_bad(i, '\u8000', '\0', 2);
- }
-
- static void marshal_wc(String selfNode, String peerNode,
- String cookie, String serverName)
- throws java.lang.Exception
- {
- m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
- // Just warming up..
- verify_wc(i, '\3', '\2', 1);
- verify_wc(i, '\5', '\4', 3);
- // The small integer border
- verify_wc(i, '\u00FF', '\0', 1);
- verify_wc(i, '\u0100', '\0', 1);
- // Java char border
- verify_wc(i, java.lang.Character.MAX_VALUE, '\0', 1);
- verify_wc(i, java.lang.Character.MIN_VALUE, '\0', 1);
- verify_wc(i, java.lang.Character.MAX_VALUE,
- java.lang.Character.MIN_VALUE, 1);
- // Impossible decodes
- verify_c_bad(i, '\u8000', '\0', 2);
- }
-
- static void marshal_str(String selfNode, String peerNode,
- String cookie, String serverName)
- throws java.lang.Exception
- {
- m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
- // Just warming up..
- verify_str(i, 100, 100);
- verify_str(i, 100, 1);
- // Erlang string border
- verify_str(i, 65535, 1);
- verify_str(i, 2, 65535);
- // Erlang string border out
- verify_str(i, 65536, 1);
- verify_str(i, 65536, 65536);
- }
-
- static void marshal_any_3(String selfNode, String peerNode,
- String cookie, String serverName)
- throws java.lang.Exception
- {
- m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
- com.ericsson.otp.ic.Any x = new com.ericsson.otp.ic.Any();
- com.ericsson.otp.ic.Any y = new com.ericsson.otp.ic.Any();
- com.ericsson.otp.ic.Any z = new com.ericsson.otp.ic.Any();
-
- x.insert_longlong(java.lang.Long.MAX_VALUE);
- y.insert_longlong(1L);
- z.insert_longlong(java.lang.Long.MAX_VALUE-1L);
- System.out.println("verify_any_3 longlong max");
- verify_any_3(i, x, y, 1, z);
-
- x.insert_longlong(java.lang.Long.MIN_VALUE);
- y.insert_longlong(-1L);
- z.insert_longlong(java.lang.Long.MIN_VALUE+1L);
- System.out.println("verify_any_3 longlong min");
- verify_any_3(i, x, y, 1, z);
-
- x.insert_ulonglong(-1L);
- y.insert_longlong(1L);
- z.insert_ulonglong(-2L);
- System.out.println("verify_any_3 ulonglong max");
- verify_any_3(i, x, y, 1, z);
-
- x.insert_ulonglong(0L);
- y.insert_longlong(-1L);
- z.insert_ulonglong(1L);
- System.out.println("verify_any_3 ulonglong min");
- verify_any_3(i, x, y, 1, z);
-
- x.insert_long(java.lang.Integer.MAX_VALUE);
- y.insert_long(1);
- z.insert_long(java.lang.Integer.MAX_VALUE-1);
- System.out.println("verify_any_3 long max");
- verify_any_3(i, x, y, 1, z);
-
- x.insert_long(java.lang.Integer.MIN_VALUE);
- y.insert_long(-1);
- z.insert_long(java.lang.Integer.MIN_VALUE+1);
- System.out.println("verify_any_3 long min");
- verify_any_3(i, x, y, 1, z);
-
- x.insert_ulong(-1);
- y.insert_long(1);
- z.insert_ulong(-2);
- System.out.println("verify_any_3 ulong max");
- verify_any_3(i, x, y, 1, z);
-
- x.insert_ulong(0);
- y.insert_long(-1);
- z.insert_ulong(1);
- System.out.println("verify_any_3 ulong min");
- verify_any_3(i, x, y, 1, z);
-
- x.insert_short(java.lang.Short.MAX_VALUE);
- y.insert_short((short)1);
- z.insert_short((short)(java.lang.Short.MAX_VALUE-1));
- System.out.println("verify_any_3 short max");
- verify_any_3(i, x, y, 1, z);
-
- x.insert_short(java.lang.Short.MIN_VALUE);
- y.insert_short((short)-1);
- z.insert_short((short)(java.lang.Short.MIN_VALUE+1));
- System.out.println("verify_any_3 short min");
- verify_any_3(i, x, y, 1, z);
-
- x.insert_ushort((short)-1);
- y.insert_short((short)1);
- z.insert_ushort((short)-2);
- System.out.println("verify_any_3 ushort max");
- verify_any_3(i, x, y, 1, z);
-
- x.insert_ushort((short)0);
- y.insert_short((short)-1);
- z.insert_ushort((short)1);
- System.out.println("verify_any_3 ushort min");
- verify_any_3(i, x, y, 1, z);
-
- x.insert_char('\377');
- y.insert_char('\1');
- z.insert_char('\376');
- System.out.println("verify_any_3 char max");
- verify_any_3(i, x, y, 1, z);
-
- x.insert_wchar('\uFFFF');
- y.insert_wchar('\u0001');
- z.insert_wchar('\uFFFE');
- System.out.println("verify_any_3 char max");
- verify_any_3(i, x, y, 1, z);
- }
-
- static void marshal_any_2(String selfNode, String peerNode,
- String cookie, String serverName)
- throws java.lang.Exception
- {
- m._iStub i = new m._iStub(selfNode, peerNode, cookie, serverName);
- m.s s = new m.s();
- com.ericsson.otp.ic.Any a = new com.ericsson.otp.ic.Any();
- //
- s.ull_x = -1L;
- s.ll_x = java.lang.Long.MAX_VALUE;
- s.ll_y = 1L;
- s.ull_z = -2L;
- s.ll_z = java.lang.Long.MAX_VALUE-1L;
- //
- s.ul_x = -1;
- s.l_x = java.lang.Integer.MAX_VALUE;
- s.l_y = 1;
- s.ul_z = -2;
- s.l_z = java.lang.Integer.MAX_VALUE-1;
- //
- s.us_x = (short)-1;
- s.s_x = java.lang.Short.MAX_VALUE;
- s.s_y = (short)1;
- s.us_z = (short)-2;
- s.s_z = (short)(java.lang.Short.MAX_VALUE-1);
- //
- s.c_x = '\377';
- s.c_y = '\1';
- s.c_z = '\376';
- s.wc_x = '\uFFFF';
- s.wc_y = '\u0001';
- s.wc_z = '\uFFFE';
- m.sHelper.insert(a, s);
- verify_any_2(i, a, 1);
-
- s.ull_x = 0L;
- s.ll_x = java.lang.Long.MIN_VALUE;
- s.ll_y = -1L;
- s.ull_z = 1L;
- s.ll_z = java.lang.Long.MIN_VALUE+1L;
- //
- s.ul_x = 0;
- s.l_x = java.lang.Integer.MIN_VALUE;
- s.l_y = -1;
- s.ul_z = 1;
- s.l_z = java.lang.Integer.MIN_VALUE+1;
- //
- s.us_x = (short)0;
- s.s_x = java.lang.Short.MIN_VALUE;
- s.s_y = (short)-1;
- s.us_z = (short)1;
- s.s_z = (short)(java.lang.Short.MIN_VALUE+1);
- //
- s.c_x = '\0';
- s.c_y = '\0';
- s.c_z = '\0';
- s.wc_x = '\u0000';
- s.wc_y = '\u0000';
- s.wc_z = '\u0000';
- m.sHelper.insert(a, s);
- verify_any_2(i, a, 1);
- }
-
-
- static void verify_ll(m._iStub i, long x, long y, int b)
- throws java.lang.Exception
- {
- m.s a = new m.s();
- System.out.println("verify_ll "+a);
- a.ll_x = x;
- a.ll_y = y;
- long expected = (x - y)*(short)b;
- long result = i.marshal_ll(a, (short)b);
- if (result == expected) {
- System.out.println("verify_ll("+x+", "+y+", "+b+") => "
- +result);
- } else {
- System.out.println("verify_ll("+x+", "+y+", "+b+") => "
- +result+" != "+expected);
- System.exit(4);
- }
- }
-
- static void verify_ull(m._iStub i, long x, long y, int b)
- throws java.lang.Exception
- {
- m.s a = new m.s();
- a.ull_x = x;
- a.ll_y = y;
- long expected = (x - y)*(short)b;
- long result = i.marshal_ull(a, (short)b);
- if (result == expected) {
- System.out.println("verify_ull("+x+", "+y+", "+b+") => "
- +result);
- } else {
- System.out.println("verify_ull("+x+", "+y+", "+b+") => "
- +result+" != "+expected);
- System.exit(4);
- }
- }
-
- static void verify_l(m._iStub i, int x, int y, int b)
- throws java.lang.Exception
- {
- m.s a = new m.s();
- a.l_x = x;
- a.l_y = y;
- int expected = (x - y)*(short)b;
- int result = i.marshal_l(a, (short)b);
- if (result == expected) {
- System.out.println("verify_l("+x+", "+y+", "+b+") => "
- +result);
- } else {
- System.out.println("verify_l("+x+", "+y+", "+b+") => "
- +result+" != "+expected);
- System.exit(4);
- }
- }
-
- static void verify_ul(m._iStub i, int x, int y, int b)
- throws java.lang.Exception
- {
- m.s a = new m.s();
- a.ul_x = x;
- a.l_y = y;
- int expected = (x - y)*(short)b;
- int result = i.marshal_ul(a, (short)b);
- if (result == expected) {
- System.out.println("verify_ul("+x+", "+y+", "+b+") => "
- +result);
- } else {
- System.out.println("verify_ul("+x+", "+y+", "+b+") => "
- +result+" != "+expected);
- System.exit(4);
- }
- }
-
- static void verify_s(m._iStub i, int x, int y, int b)
- throws java.lang.Exception
- {
- m.s a = new m.s();
- a.s_x = (short)x;
- a.s_y = (short)y;
- short expected = (short)((x - y)*(short)b);
- short result = i.marshal_s(a, (short)b);
- if (result == expected) {
- System.out.println("verify_s("+x+", "+y+", "+b+") => "
- +result);
- } else {
- System.out.println("verify_s("+x+", "+y+", "+b+") => "
- +result+" != "+expected);
- System.exit(4);
- }
- }
-
- static void verify_us(m._iStub i, int x, int y, int b)
- throws java.lang.Exception
- {
- m.s a = new m.s();
- a.us_x = (short)x;
- a.s_y = (short)y;
- short expected = (short)((x - y)*(short)b);
- short result = i.marshal_us(a, (short)b);
- if (result == expected) {
- System.out.println("verify_us("+x+", "+y+", "+b+") => "
- +result);
- } else {
- System.out.println("verify_us("+x+", "+y+", "+b+") => "
- +result+" != "+expected);
- System.exit(4);
- }
- }
-
- static void verify_c(m._iStub i, char x, char y, int b)
- throws java.lang.Exception
- {
- m.s a = new m.s();
- a.c_x = x;
- a.c_y = y;
- char expected = (char)(((int)x - (int)y)*(short)b);
- char result = i.marshal_c(a, (short)b);
- if (result == expected) {
- System.out.println("verify_c("+x+", "+y+", "+b+") => "
- +result);
- } else {
- System.out.println("verify_c("+x+", "+y+", "+b+") => "
- +result+" != "+expected);
- System.exit(4);
- }
- }
-
- static void verify_wc(m._iStub i, char x, char y, int b)
- throws java.lang.Exception
- {
- m.s a = new m.s();
- a.wc_x = x;
- a.wc_y = y;
- char expected = (char)(((int)x - (int)y)*(short)b);
- char result = i.marshal_wc(a, (short)b);
- if (result == expected) {
- System.out.println("verify_wc("+x+", "+y+", "+b+") => "
- +result);
- } else {
- System.out.println("verify_wc("+x+", "+y+", "+b+") => "
- +result+" != "+expected);
- System.exit(4);
- }
- }
-
- static void verify_str(m._iStub i, int a_len, int b_len)
- throws java.lang.Exception
- {
- String a = mk_str(a_len);
- String b = mk_str(b_len);
- String expected = a + b;
- String result = i.strcat(a, b);
- if (result.equals(expected)) {
- System.out.println("verify_str(\""+a+"\", \""+b+"\") => \""
- +result+"\"");
- } else {
- System.out.println("verify_str(\""+a+"\", \""+b+"\") => \""
- +result+"\" != \""+expected.length()+"\"");
- System.exit(4);
- }
- }
-
- static String mk_str(int len)
- throws StringIndexOutOfBoundsException
- {
- StringBuffer s = new StringBuffer();
- // 17 characters is prime relative all bases of two - on purpose
- do s.append("qwertyuiopasdfghj"); while (s.length() < len);
- return s.substring(0, len);
- }
-
- static void verify_any_3(m._iStub i,
- com.ericsson.otp.ic.Any x,
- com.ericsson.otp.ic.Any y,
- int b,
- com.ericsson.otp.ic.Any expected)
- throws java.lang.Exception
- {
- com.ericsson.otp.ic.Any result = i.marshal_any_3(x, y, (short)b);
- if (! expected.equal(result)) {
- System.exit(4);
- }
- }
-
- static void verify_any_2(m._iStub i, com.ericsson.otp.ic.Any a, int b)
- throws java.lang.Exception
- {
- com.ericsson.otp.ic.Any result = i.marshal_any_2(a, (short)b);
- if (! a.equal(result)) {
- System.exit(4);
- }
- }
-
-
-
- static void verify_ll_bad(m._iStub i, long x, long y, int b)
- throws java.lang.Exception
- {
- try {
- verify_ll(i, x, y, b);
- System.out.println("Expected exception missing!");
- System.exit(5);
- } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) {
- System.out.println("Expected exception: "+e);
- }
- }
-
- static void verify_ull_bad(m._iStub i, long x, long y, int b)
- throws java.lang.Exception
- {
- try {
- verify_ull(i, x, y, b);
- System.out.println("Expected exception missing!");
- System.exit(5);
- } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) {
- System.out.println("Expected exception: "+e);
- }
- }
-
- static void verify_l_bad(m._iStub i, int x, int y, int b)
- throws java.lang.Exception
- {
- try {
- verify_l(i, x, y, b);
- System.out.println("Expected exception missing!");
- System.exit(5);
- } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) {
- System.out.println("Expected exception: "+e);
- }
- }
-
- static void verify_ul_bad(m._iStub i, int x, int y, int b)
- throws java.lang.Exception
- {
- try {
- verify_ul(i, x, y, b);
- System.out.println("Expected exception missing!");
- System.exit(5);
- } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) {
- System.out.println("Expected exception: "+e);
- }
- }
-
- static void verify_s_bad(m._iStub i, int x, int y, int b)
- throws java.lang.Exception
- {
- try {
- verify_s(i, x, y, b);
- System.out.println("Expected exception missing!");
- System.exit(5);
- } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) {
- System.out.println("Expected exception: "+e);
- }
- }
-
- static void verify_us_bad(m._iStub i, int x, int y, int b)
- throws java.lang.Exception
- {
- try {
- verify_us(i, x, y, b);
- System.out.println("Expected exception missing!");
- System.exit(5);
- } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) {
- System.out.println("Expected exception: "+e);
- }
- }
-
- static void verify_c_bad(m._iStub i, char x, char y, int b)
- throws java.lang.Exception
- {
- try {
- verify_c(i, x, y, b);
- System.out.println("Expected exception missing!");
- System.exit(5);
- } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) {
- System.out.println("Expected exception: "+e);
- }
- }
-
- static void verify_wc_bad(m._iStub i, char x, char y, int b)
- throws java.lang.Exception
- {
- try {
- verify_wc(i, x, y, b);
- System.out.println("Expected exception missing!");
- System.exit(5);
- } catch (com.ericsson.otp.erlang.OtpErlangDecodeException e) {
- System.out.println("Expected exception: "+e);
- }
- }
-
-}
diff --git a/lib/ic/test/java_client_erl_server_SUITE_data/Makefile.src b/lib/ic/test/java_client_erl_server_SUITE_data/Makefile.src
deleted file mode 100644
index bcc59e87db..0000000000
--- a/lib/ic/test/java_client_erl_server_SUITE_data/Makefile.src
+++ /dev/null
@@ -1,101 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2003-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-# Makefile.src for java_client_erl_server test
-# Note: This file *must* work for both Unix and Windows
-#
-# We use both `rm' (Unix) and `del' (Windows) for removing files, but
-# with a `-' in front so that the error in not finding `rm' (`del') on
-# Windows (Unix) is ignored.
-#
-# VxWorks? XXX
-#
-
-.SUFFIXES:
-.SUFFIXES: .erl .idl .@EMULATOR@ .java
-
-
-JAVAC = @JAVAC@
-ERLC = erlc
-
-# ic variables available from ts:
-#
-# ic_libpath: @ic_libpath@
-# ic_include_path: @ic_include_path@
-
-IC_INCLUDE_PATH = @ic_include_path@
-IC_CLASSPATH = @ic_classpath@
-
-JINTERFACE_CLASSPATH = @jinterface_classpath@
-
-CLASSPATH = .@PS@$(IC_CLASSPATH)@PS@$(JINTERFACE_CLASSPATH)@PS@
-
-GEN_JAVA_FILES = \
- m@DS@_iImplBase.java \
- m@DS@_iStub.java \
-
-GEN_HRL_FILES = \
- m.hrl \
- m_i.hrl \
- oe_java_erl_test.hrl
-
-GEN_ERL_FILES = \
- m_i.erl \
- oe_java_erl_test.erl
-
-JAVA_FILES = $(GEN_JAVA_FILES) JavaClient.java
-CLASS_FILES = $(JAVA_FILES:.java=.class)
-ERL_FILES = $(GEN_ERL_FILES) m_i_impl.erl
-EBINS = $(ERL_FILES:.erl=.@EMULATOR@)
-
-@IFEQ@ (@jinterface@,not_found)
-all:
-@ELSE@
-all: $(CLASS_FILES) $(EBINS)
-@ENDIF@
-
-$(GEN_ERL_FILES) $(GEN_HRL_FILES): java_erl_test.built_erl
-$(GEN_JAVA_FILES): java_erl_test.built_java
-$(CLASS_FILES): $(GEN_JAVA_FILES)
-$(EBINS): $(GEN_ERL_FILES) $(GEN_HRL_FILES)
-
-clean:
- -rm -f $(GEN_JAVA_FILES) $(CLASS_FILES) \
- $(GEN_ERL_FILES) $(GEN_HRL_FILES) $(EBINS) \
- java_erl_test.built_erl java_erl_test.built_java
- -del /F /Q $(GEN_JAVA_FILES) $(CLASS_FILES) \
- $(GEN_ERL_FILES) $(GEN_HRL_FILES) $(EBINS) \
- java_erl_test.built_erl java_erl_test.built_java
-
-java_erl_test.built_java: java_erl_test.idl
- $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,java}" java_erl_test.idl
- echo done > java_erl_test.built_java
-
-$(CLASS_FILES) : $(JAVA_FILES)
- $(JAVAC) -classpath $(CLASSPATH) $(JAVA_FILES)
-
-java_erl_test.built_erl: java_erl_test.idl
- $(ERLC) -I $(IC_INCLUDE_PATH) "+{be,erl_genserv}" java_erl_test.idl
- echo done > java_erl_test.built_erl
-
-.erl.@EMULATOR@:
- $(ERLC) -I $(IC_INCLUDE_PATH) $<
diff --git a/lib/ic/test/java_client_erl_server_SUITE_data/java_erl_test.idl b/lib/ic/test/java_client_erl_server_SUITE_data/java_erl_test.idl
deleted file mode 100644
index 55194cf911..0000000000
--- a/lib/ic/test/java_client_erl_server_SUITE_data/java_erl_test.idl
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 2003-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-module m {
-
- struct s {
- long long ll_x;
- unsigned long long ull_x;
- long long ll_y;
- long long ll_z;
- unsigned long long ull_z;
-
- long l_x;
- unsigned long ul_x;
- long l_y;
- long l_z;
- unsigned long ul_z;
-
- short s_x;
- unsigned short us_x;
- short s_y;
- short s_z;
- unsigned short us_z;
-
- char c_x;
- char c_y;
- char c_z;
-
- wchar wc_x;
- wchar wc_y;
- wchar wc_z;
- };
-
- interface i {
- long long marshal_ll( in s a, in short b );
- unsigned long long marshal_ull( in s a, in short b );
-
- long marshal_l( in s a, in short b );
- unsigned long marshal_ul( in s a, in short b );
-
- short marshal_s( in s a, in short b );
- unsigned short marshal_us( in s a, in short b );
-
- char marshal_c( in s a, in short b );
- wchar marshal_wc( in s a, in short b );
-
- string strcat( in string a, in string b );
-
- any marshal_any_3( in any x, in any y, in short b );
- any marshal_any_2( in any a, in short b );
- };
-
-};
diff --git a/lib/ic/test/java_client_erl_server_SUITE_data/m_i_impl.erl b/lib/ic/test/java_client_erl_server_SUITE_data/m_i_impl.erl
deleted file mode 100644
index 31b4c1dd7a..0000000000
--- a/lib/ic/test/java_client_erl_server_SUITE_data/m_i_impl.erl
+++ /dev/null
@@ -1,170 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%--------------------------------------------------------------------
--module(m_i_impl).
-
--export([marshal_ll/3,marshal_ull/3,
- marshal_l/3,marshal_ul/3,
- marshal_s/3,marshal_us/3,
- marshal_c/3,marshal_wc/3,
- strcat/3,
- marshal_any_3/4,marshal_any_2/3]).
--export([init/1,terminate/2,code_change/3]).
-
--include("m.hrl").
-
--define(TK_M_S, {tk_struct,
- "IDL:m/s:1.0",
- "s",
- [{"ll_x",tk_longlong},
- {"ull_x",tk_ulonglong},
- {"ll_y",tk_longlong},
- {"ll_z",tk_longlong},
- {"ull_z",tk_ulonglong},
- {"l_x",tk_long},
- {"ul_x",tk_ulong},
- {"l_y",tk_long},
- {"l_z",tk_long},
- {"ul_z",tk_ulong},
- {"s_x",tk_short},
- {"us_x",tk_ushort},
- {"s_y",tk_short},
- {"s_z",tk_short},
- {"us_z",tk_ushort},
- {"c_x",tk_char},
- {"c_y",tk_char},
- {"c_z",tk_char},
- {"wc_x",tk_wchar},
- {"wc_y",tk_wchar},
- {"wc_z",tk_wchar}|_]}).
-
-
-
-marshal_ll(State, #m_s{ll_x = X, ll_y = Y}=_A, B) when integer(B) ->
- R = (X - Y)*B,
- io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]),
- {reply, R, State}.
-
-marshal_ull(State, #m_s{ull_x = X, ll_y = Y}=_A, B) when integer(B) ->
- R = (X - Y)*B,
- io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]),
- {reply, R, State}.
-
-
-marshal_l(State, #m_s{l_x = X, l_y = Y}=_A, B) when integer(B) ->
- R = (X - Y)*B,
- io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]),
- {reply, R, State}.
-
-marshal_ul(State, #m_s{ul_x = X, l_y = Y}=_A, B) when integer(B) ->
- R = (X - Y)*B,
- io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]),
- {reply, R, State}.
-
-
-marshal_s(State, #m_s{s_x = X, s_y = Y}=_A, B) when integer(B) ->
- R = (X - Y)*B,
- io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]),
- {reply, R, State}.
-
-marshal_us(State, #m_s{us_x = X, s_y = Y}=_A, B) when integer(B) ->
- R = (X - Y)*B,
- io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]),
- {reply, R, State}.
-
-
-marshal_c(State, #m_s{c_x = X, c_y = Y}=_A, B) when integer(B) ->
- R = (X - Y)*B,
- io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]),
- {reply, R, State}.
-
-marshal_wc(State, #m_s{wc_x = X, wc_y = Y}=_A, B) when integer(B) ->
- R = (X - Y)*B,
- io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]),
- {reply, R, State}.
-
-strcat(State, A, B) when list(A), list(B) ->
- R = A++B,
- io:format("~p", [{?MODULE,?LINE,[length(A),length(B),A,B,R]}]),
- {reply, R, State};
-strcat(State, A, B) ->
- io:format("~p", [{?MODULE,?LINE,[A,B]}]),
- {reply, [], State}.
-
-marshal_any_3(State, {any,TkX,_}=X, {any,_,_}=Y, B) when integer(B) ->
- R = any(mul(sub(any(X), any(Y)), B), TkX),
- io:format("~p", [{?MODULE,?LINE,[X,Y,B,R]}]),
- {reply, R, State}.
-
-marshal_any_2(State,
- {any,TkA,#m_s{ll_x=LL_X, ull_x=ULL_X, ll_y=LL_Y,
- l_x=L_X, ul_x=UL_X, l_y=L_Y,
- s_x=S_X, us_x=US_X, s_y=S_Y,
- c_x=C_X, c_y=C_Y,
- wc_x=WC_X, wc_y=WC_Y} = A},
- B) when integer(B) ->
- {check_type_code,?TK_M_S} = {check_type_code,TkA},
- ULL_Z = (ULL_X - LL_Y) * B,
- LL_Z = (LL_X - LL_Y) * B,
- UL_Z = (UL_X - L_Y) * B,
- L_Z = (L_X - L_Y) * B,
- US_Z = (US_X - S_Y) * B,
- S_Z = (S_X - S_Y) * B,
- C_Z = (C_X - C_Y) * B,
- WC_Z = (WC_X - WC_Y) * B,
- R = A#m_s{ll_z=LL_Z, ull_z=ULL_Z,
- l_z=L_Z, ul_z=UL_Z,
- s_z=S_Z, us_z=US_Z,
- c_z=C_Z, wc_z=WC_Z},
- io:format("~p", [{?MODULE,?LINE,[A,B,R]}]),
- {reply, {any,TkA,R}, State}.
-
-
-
-init(_Env) ->
- {ok, []}.
-
-terminate(_Reason, _State) ->
- ok.
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-
-any({any,tk_longlong,X}) -> X;
-any({any,tk_long,X}) -> X;
-any({any,tk_short,X}) -> X;
-any({any,tk_ulonglong,X}) -> X;
-any({any,tk_ulong,X}) -> X;
-any({any,tk_ushort,X}) -> X;
-any({any,tk_char,X}) -> X;
-any({any,tk_wchar,X}) -> X.
-
-any(X, Tk) when integer(X) -> {any,Tk,X}.
-
-sub(X, Y) when integer(X), integer(Y) ->
- X - Y.
-
-mul(X, Y) when integer(X), integer(Y) ->
- X * Y.
-
-napp(0, L) -> L;
-napp(N, L) when integer(N), N >= 1 -> napp(N-1, L)++L.
diff --git a/lib/ic/vsn.mk b/lib/ic/vsn.mk
deleted file mode 100644
index f0e5e7c266..0000000000
--- a/lib/ic/vsn.mk
+++ /dev/null
@@ -1 +0,0 @@
-IC_VSN = 4.4.2
diff --git a/lib/inets/doc/src/Makefile b/lib/inets/doc/src/Makefile
index cb71fbeb9c..cbc0e384d8 100644
--- a/lib/inets/doc/src/Makefile
+++ b/lib/inets/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2015. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -39,16 +39,14 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
XML_APPLICATION_FILES = ref_man.xml
XML_CHAPTER_FILES = \
+ introduction.xml \
inets_services.xml \
http_client.xml \
http_server.xml \
- ftp_client.xml \
notes.xml
XML_REF3_FILES = \
inets.xml \
- ftp.xml \
- tftp.xml \
http_uri.xml\
httpc.xml\
httpd.xml \
@@ -58,7 +56,7 @@ XML_REF3_FILES = \
mod_alias.xml \
mod_auth.xml \
mod_esi.xml \
- mod_security.xml
+ mod_security.xml
XML_PART_FILES = \
part.xml
@@ -83,7 +81,7 @@ HTML_FILES = \
$(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
INFO_FILE = ../../info
-EXTRA_FILES = summary.html.src \
+EXTRA_FILES = \
$(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html) \
$(XML_REF6_FILES:%.xml=$(HTMLDIR)/%.html) \
$(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html)
@@ -95,10 +93,10 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
+XML_FLAGS +=
+DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -117,27 +115,28 @@ pdf: $(TOP_PDF_FILE)
html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs: clean_html clean_man clean_pdf
+ rm -rf $(XMLDIR)
rm -f errs core *~
-man: $(MAN3_FILES)
+man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-debug opt:
+debug opt:
-clean_pdf:
+clean_pdf:
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
-clean_html:
+clean_html:
rm -rf $(TOP_HTML_FILES) $(HTMLDIR)/*
clean_man:
- rm -f $(MAN3_FILES)
+ rm -f $(MAN3_FILES)
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
diff --git a/lib/inets/doc/src/book.gif b/lib/inets/doc/src/book.gif
deleted file mode 100644
index 94b3868792..0000000000
--- a/lib/inets/doc/src/book.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/doc/src/fascicules.xml b/lib/inets/doc/src/fascicules.xml
deleted file mode 100644
index c075478967..0000000000
--- a/lib/inets/doc/src/fascicules.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
-
diff --git a/lib/inets/doc/src/ftp.xml b/lib/inets/doc/src/ftp.xml
deleted file mode 100644
index 42bece4d38..0000000000
--- a/lib/inets/doc/src/ftp.xml
+++ /dev/null
@@ -1,948 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>ftp</title>
- <prepared>Peter H&ouml;gfeldt</prepared>
- <docno></docno>
- <date>1997-11-05</date>
- <rev>B</rev>
- <file>ftp.xml</file>
- </header>
- <module>ftp</module>
- <modulesummary>A File Transfer Protocol client.</modulesummary>
-
- <description>
-
- <p>This module implements a client for file transfer
- according to a subset of the File Transfer Protocol (FTP), see
- <url href="http://www.ietf.org/rfc/rfc959.txt">RFC 959</url>.</p>
-
- <p>As from <c>Inets</c> 4.4.1, the FTP
- client always tries to use passive FTP mode and only resort
- to active FTP mode if this fails. This default behavior can be
- changed by start option <seealso marker="#mode">mode</seealso>.</p>
-
- <marker id="two_start"></marker>
-
- <p>An FTP client can be started in two ways. One is using the
- <seealso marker="#service_start">Inets service framework</seealso>,
- the other is to start it directly as a standalone process
- using function <seealso marker="#open">open</seealso>.</p>
-
- <p>For a simple example of an FTP session, see
- <seealso marker="ftp_client">Inets User's Guide</seealso>.</p>
-
- <p>In addition to the ordinary functions for receiving and sending
- files (see <c>recv/2</c>, <c>recv/3</c>, <c>send/2</c>, and
- <c>send/3</c>) there are functions for receiving remote files as
- binaries (see <c>recv_bin/2</c>) and for sending binaries to be
- stored as remote files (see <c>send_bin/3</c>).</p>
-
- <p>A set of functions is provvided for sending and receiving
- contiguous parts of a file to be stored in a remote file. For send,
- see <c>send_chunk_start/2</c>, <c>send_chunk/2</c>, and
- <c>send_chunk_end/1</c>. For receive, see
- <c>recv_chunk_start/2</c> and <c>recv_chunk/</c>).</p>
-
- <p>The return values of the following functions depend
- much on the implementation of the FTP server at the remote
- host. In particular, the results from <c>ls</c> and <c>nlist</c>
- varies. Often real errors are not reported as errors by <c>ls</c>,
- even if, for example, a file or directory does not
- exist. <c>nlist</c> is usually more strict, but some
- implementations have the peculiar behaviour of responding with an
- error if the request is a listing of the contents of a directory
- that exists but is empty.</p>
-
- <marker id="service_start"></marker>
- </description>
-
- <section>
- <title>FTP CLIENT SERVICE START/STOP</title>
-
- <p>The FTP client can be started and stopped dynamically in runtime by
- calling the <c>Inets</c> application API
- <c>inets:start(ftpc, ServiceConfig)</c>,
- or <c>inets:start(ftpc, ServiceConfig, How)</c>, and
- <c>inets:stop(ftpc, Pid)</c>.
- For details, see <seealso marker="inets">inets(3)</seealso>.</p>
-
- <p>The available configuration options are as follows:</p>
-
- <taglist>
- <tag>{host, Host}</tag>
- <item>
- <marker id="host"></marker>
- <p>Host = <c>string() | ip_address()</c></p>
- </item>
-
- <tag>{port, Port}</tag>
- <item>
- <marker id="port"></marker>
- <p>Port = <c>integer() > 0</c></p>
- <p>Default is <c>21</c>.</p>
- </item>
-
- <tag>{mode, Mode}</tag>
- <item>
- <marker id="mode"></marker>
- <p>Mode = <c>active | passive</c></p>
- <p>Default is <c>passive</c>.</p>
- </item>
-
- <tag>{verbose, Verbose}</tag>
- <item>
- <marker id="verbose"></marker>
- <p>Verbose = <c>boolean()</c> </p>
- <p>Determines if the FTP communication is to be
- verbose or not.</p>
- <p>Default is <c>false</c>.</p>
- </item>
-
- <tag>{debug, Debug}</tag>
- <item>
- <marker id="debug"></marker>
- <p>Debug = <c>trace | debug | disable</c> </p>
- <p>Debugging using the dbg toolkit. </p>
- <p>Default is <c>disable</c>.</p>
- </item>
-
- <tag>{ipfamily, IpFamily}</tag>
- <item>
- <marker id="ipfamily"></marker>
- <p>IpFamily = <c>inet | inet6 | inet6fb4</c> </p>
- <p>With <c>inet6fb4</c> the client behaves as before, that is,
- tries to use IPv6, and only if that does not work it
- uses IPv4).</p>
- <p>Default is <c>inet</c> (IPv4).</p>
- </item>
-
- <tag>{timeout, Timeout}</tag>
- <item>
- <marker id="timeout"></marker>
- <p>Timeout = <c>non_neg_integer()</c></p>
- <p>Connection time-out.</p>
- <p>Default is <c>60000</c> (milliseconds).</p>
- </item>
-
- <tag>{dtimeout, DTimeout}</tag>
- <item>
- <marker id="dtimeout"></marker>
- <p>DTimeout = <c>non_neg_integer() | infinity</c> </p>
- <p>Data connect time-out.
- The time the client waits for the server to connect to the
- data socket.</p>
- <p>Default is <c>infinity</c>. </p>
- </item>
-
- <tag>{progress, Progress}</tag>
- <item>
- <marker id="progress"></marker>
- <p>Progress = <c>ignore | {CBModule, CBFunction, InitProgress}</c></p>
- <p><c>CBModule = atom()</c>, <c>CBFunction = atom()</c></p>
- <p><c>InitProgress = term()</c></p>
- <p>Default is <c>ignore</c>.</p>
- </item>
-
- </taglist>
-
- <p>Option <c>progress</c> is intended to be used by applications that
- want to create some type of progress report, such as a progress bar in
- a GUI. Default for the progress option is <c>ignore</c>,
- that is, the option is not used. When the progress option is
- specified, the following happens when <c>ftp:send/[3,4]</c> or
- <c>ftp:recv/[3,4]</c> are called:</p>
-
- <list type="bulleted">
- <item>
- <p>Before a file is transferred, the following call is
- made to indicate the start of the file transfer and how large
- the file is. The return value of the callback function
- is to be a new value for the <c>UserProgressTerm</c> that will
- be used as input the next time the callback function is
- called.</p>
- <p><c>
- CBModule:CBFunction(InitProgress, File, {file_size, FileSize})
- </c></p>
- </item>
-
- <item>
- <p>Every time a chunk of bytes is transferred the
- following call is made:</p>
- <p><c>
- CBModule:CBFunction(UserProgressTerm, File, {transfer_size, TransferSize})
- </c></p>
- </item>
-
- <item>
- <p>At the end of the file the following call is
- made to indicate the end of the transfer:</p>
- <p><c>
- CBModule:CBFunction(UserProgressTerm, File, {transfer_size, 0})
- </c></p>
- </item>
- </list>
-
- <p>The callback function is to be defined as follows:</p>
-
- <p><c>
- CBModule:CBFunction(UserProgressTerm, File, Size) -> UserProgressTerm
- </c></p>
-
- <p><c>
- CBModule = CBFunction = atom()
- </c></p>
-
- <p><c>
- UserProgressTerm = term()
- </c></p>
-
- <p><c>
- File = string()
- </c></p>
-
- <p><c>
- Size = {transfer_size, integer()} | {file_size, integer()} | {file_size, unknown}
- </c></p>
-
- <p>For remote files, <c>ftp</c> cannot determine the
- file size in a platform independent way. In this case the size
- becomes <c>unknown</c> and it is left to the application to
- determine the size.</p>
-
- <note>
- <p>The callback is made by a middleman process, hence the
- file transfer is not affected by the code in the progress
- callback function. If the callback crashes, this is
- detected by the FTP connection process, which then prints an
- info-report and goes on as if the progress option was set
- to <c>ignore</c>.</p>
- </note>
-
- <p>The file transfer type is set to the default of the FTP server
- when the session is opened. This is usually ASCCI mode.
- </p>
-
- <p>The current local working directory (compare <c>lpwd/1</c>) is set
- to the value reported by <c>file:get_cwd/1</c>, the wanted
- local directory.
- </p>
-
- <p>The return value <c>Pid</c> is used as a reference to the
- newly created FTP client in all other functions, and they are to
- be called by the process that created the connection. The FTP
- client process monitors the process that created it and
- terminates if that process terminates.</p>
- </section>
-
- <section>
- <title>DATA TYPES</title>
- <p>The following type definitions are used by more than one
- function in the FTP client API:</p>
- <p><c>pid()</c> = identifier of an FTP connection</p>
- <p><c>string()</c> = list of ASCII characters</p>
- <p><c>shortage_reason()</c> = <c>etnospc | epnospc</c></p>
- <p><c>restriction_reason()</c> = <c>epath | efnamena | elogin | enotbinary</c>
- - all restrictions are not always relevant to all functions
- </p>
- <p><c>common_reason()</c> = <c>econn | eclosed | term()</c>
- - some explanation of what went wrong</p>
-
- <marker id="account"></marker>
- </section>
-
- <funcs>
- <func>
- <name>account(Pid, Account) -> ok | {error, Reason}</name>
- <fsummary>Specifies which account to use.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Account = string()</v>
- <v>Reason = eacct | common_reason()</v>
- </type>
- <desc>
- <p>Sets the account for an operation, if needed.</p>
-
- <marker id="append"></marker>
- <marker id="append2"></marker>
- <marker id="append3"></marker>
- </desc>
- </func>
-
- <func>
- <name>append(Pid, LocalFile) -> </name>
- <name>append(Pid, LocalFile, RemoteFile) -> ok | {error, Reason}</name>
- <fsummary>Transfers a file to remote server, and appends it to
- <c>Remotefile</c>.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>LocalFile = RemoteFile = string()</v>
- <v>Reason = epath | elogin | etnospc | epnospc | efnamena | common_reason</v>
- </type>
- <desc>
- <p>Transfers the file <c>LocalFile</c> to the remote server. If
- <c>RemoteFile</c> is specified, the name of the remote file that the
- file is appended to is set to <c>RemoteFile</c>, otherwise
- to <c>LocalFile</c>. If the file does not exists,
- it is created.</p>
-
- <marker id="append_bin"></marker>
- </desc>
- </func>
-
- <func>
- <name>append_bin(Pid, Bin, RemoteFile) -> ok | {error, Reason}</name>
- <fsummary>Transfers a binary into a remote file.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Bin = binary()()</v>
- <v>RemoteFile = string()</v>
- <v>Reason = restriction_reason()| shortage_reason() | common_reason()</v>
- </type>
- <desc>
- <p>Transfers the binary <c>Bin</c> to the remote server and appends
- it to the file <c>RemoteFile</c>. If the file does not exist, it
- is created.</p>
-
- <marker id="append_chunk"></marker>
- </desc>
- </func>
-
- <func>
- <name>append_chunk(Pid, Bin) -> ok | {error, Reason}</name>
- <fsummary>Appends a chunk to the remote file.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Bin = binary()</v>
- <v>Reason = echunk | restriction_reason() | common_reason()</v>
- </type>
- <desc>
- <p>Transfers the chunk <c>Bin</c> to the remote server, which
- appends it to the file specified in the call to
- <c>append_chunk_start/2</c>.</p>
- <p>For some errors, for example, file system full, it is
- necessary to call <c>append_chunk_end</c> to get the
- proper reason.</p>
-
- <marker id="append_chunk_start"></marker>
- </desc>
- </func>
-
- <func>
- <name>append_chunk_start(Pid, File) -> ok | {error, Reason}</name>
- <fsummary>Starts transfer of file chunks for appending to <c>File</c>.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>File = string()</v>
- <v>Reason = restriction_reason() | common_reason()</v>
- </type>
- <desc>
- <p>Starts the transfer of chunks for appending to the file
- <c>File</c> at the remote server. If the file does not exist,
- it is created.</p>
-
- <marker id="append_chunk_end"></marker>
- </desc>
- </func>
-
- <func>
- <name>append_chunk_end(Pid) -> ok | {error, Reason}</name>
- <fsummary>Stops transfer of chunks for appending.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Reason = echunk | restriction_reason() | shortage_reason() </v>
- </type>
- <desc>
- <p>Stops transfer of chunks for appending to the remote server.
- The file at the remote server, specified in the call to
- <c>append_chunk_start/2</c>, is closed by the server.</p>
-
- <marker id="cd"></marker>
- </desc>
- </func>
-
- <func>
- <name>cd(Pid, Dir) -> ok | {error, Reason}</name>
- <fsummary>Changes remote working directory.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Dir = string()</v>
- <v>Reason = restriction_reason() | common_reason() </v>
- </type>
- <desc>
- <p>Changes the working directory at the remote server to
- <c>Dir</c>.</p>
-
- <marker id="close"></marker>
- </desc>
- </func>
-
- <func>
- <name>close(Pid) -> ok</name>
- <fsummary>Ends the FTP session.</fsummary>
- <type>
- <v>Pid = pid()</v>
- </type>
- <desc>
- <p>Ends an FTP session, created using function
- <seealso marker="#open">open</seealso>.</p>
-
- <marker id="delete"></marker>
- </desc>
- </func>
-
- <func>
- <name>delete(Pid, File) -> ok | {error, Reason}</name>
- <fsummary>Deletes a file at the remote server.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>File = string()</v>
- <v>Reason = restriction_reason() | common_reason()</v>
- </type>
- <desc>
- <p>Deletes the file <c>File</c> at the remote server.</p>
-
- <marker id="append"></marker>
- </desc>
- </func>
-
- <func>
- <name>formaterror(Tag) -> string()</name>
- <fsummary>Returns error diagnostics.</fsummary>
- <type>
- <v>Tag = {error, atom()} | atom()</v>
- </type>
- <desc>
- <p>Given an error return value <c>{error, AtomReason}</c>,
- this function returns a readable string describing the error.</p>
-
- <marker id="lcd"></marker>
- </desc>
- </func>
-
- <func>
- <name>lcd(Pid, Dir) -> ok | {error, Reason}</name>
- <fsummary>Changes local working directory.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Dir = string()</v>
- <v>Reason = restriction_reason()</v>
- </type>
- <desc>
- <p>Changes the working directory to <c>Dir</c> for the local client.</p>
-
- <marker id="lpwd"></marker>
- </desc>
- </func>
-
- <func>
- <name>lpwd(Pid) -> {ok, Dir}</name>
- <fsummary>Gets local current working directory.</fsummary>
- <type>
- <v>Pid = pid()</v>
- </type>
- <desc>
- <p>Returns the current working directory at the local client.</p>
-
- <marker id="ls"></marker>
- <marker id="ls1"></marker>
- <marker id="ls2"></marker>
- </desc>
- </func>
-
- <func>
- <name>ls(Pid) -> </name>
- <name>ls(Pid, Pathname) -> {ok, Listing} | {error, Reason}</name>
- <fsummary>List of files.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Pathname = string()</v>
- <v>Listing = string()</v>
- <v>Reason = restriction_reason() | common_reason()</v>
- </type>
- <desc>
- <p>Returns a list of files in long format.</p>
- <p><c>Pathname</c> can be a directory, a group of files, or
- a file. The <c>Pathname</c> string can contain wildcards.</p>
- <p><c>ls/1</c> implies the current remote directory of the user.</p>
- <p>The format of <c>Listing</c> depends on the operating system.
- On UNIX, it is typically produced from the output of the
- <c>ls -l</c> shell command.</p>
-
- <marker id="mkdir"></marker>
- </desc>
- </func>
-
- <func>
- <name>mkdir(Pid, Dir) -> ok | {error, Reason}</name>
- <fsummary>Creates a remote directory.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Dir = string()</v>
- <v>Reason = restriction_reason() | common_reason()</v>
- </type>
- <desc>
- <p>Creates the directory <c>Dir</c> at the remote server.</p>
-
- <marker id="nlist"></marker>
- <marker id="nlist1"></marker>
- <marker id="nlist2"></marker>
- </desc>
- </func>
-
- <func>
- <name>nlist(Pid) -> </name>
- <name>nlist(Pid, Pathname) -> {ok, Listing} | {error, Reason}</name>
- <fsummary>List of files.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Pathname = string()</v>
- <v>Listing = string()</v>
- <v>Reason = restriction_reason() | common_reason()</v>
- </type>
- <desc>
- <p>Returns a list of files in short format.</p>
- <p><c>Pathname</c> can be a directory, a group of files, or
- a file. The <c>Pathname</c> string can contain wildcards.</p>
- <p><c>nlist/1</c> implies the current remote directory of the user.</p>
- <p>The format of <c>Listing</c> is a stream of
- filenames where each filename is separated by &lt;CRLF&gt; or
- &lt;NL&gt;. Contrary to function <c>ls</c>, the purpose of
- <c>nlist</c> is to enable a program to
- process filename information automatically.</p>
-
- <marker id="open"></marker>
- </desc>
- </func>
-
- <func>
- <name>open(Host) -> {ok, Pid} | {error, Reason}</name>
- <name>open(Host, Opts) -> {ok, Pid} | {error, Reason}</name>
- <fsummary>Starts a standalone FTP client.</fsummary>
- <type>
- <v>Host = string() | ip_address()</v>
- <v>Opts = options()</v>
- <v>options() = [option()]</v>
- <v>option() = start_option() | open_option()</v>
- <v>start_option() = {verbose, verbose()} | {debug, debug()}</v>
- <v>verbose() = boolean() (default is false)</v>
- <v>debug() = disable | debug | trace (default is disable)</v>
- <v>open_option() = {ipfamily, ipfamily()} | {port, port()} | {mode, mode()} | {tls, tls_options()} | {timeout, timeout()} | {dtimeout, dtimeout()} | {progress, progress()}</v>
- <v>ipfamily() = inet | inet6 | inet6fb4 (default is inet)</v>
- <v>port() = integer() > 0 (default is 21)</v>
- <v>mode() = active | passive (default is passive)</v>
- <v>tls_options() = [<seealso marker="ssl:ssl#type-ssloption">ssl:ssloption()</seealso>]</v>
- <v>timeout() = integer() > 0 (default is 60000 milliseconds)</v>
- <v>dtimeout() = integer() > 0 | infinity (default is infinity)</v>
- <v>pogress() = ignore | {module(), function(), initial_data()} (default is ignore)</v>
- <v>module() = atom()</v>
- <v>function() = atom()</v>
- <v>initial_data() = term()</v>
- <v>Reason = ehost | term()</v>
- </type>
-
- <desc>
- <p>Starts a standalone FTP client process
- (without the <c>Inets</c> service framework) and
- opens a session with the FTP server at <c>Host</c>. </p>
-
- <p>If option <c>{tls, tls_options()}</c> is present, the FTP session
- is transported over <c>tls</c> (<c>ftps</c>, see
- <url href="http://www.ietf.org/rfc/rfc4217.txt">RFC 4217</url>).
- The list <c>tls_options()</c> can be empty. The function
- <seealso marker="ssl:ssl#connect/3"><c>ssl:connect/3</c></seealso>
- is used for securing both the control connection and the data sessions.
- </p>
-
- <p>A session opened in this way is closed using function
- <seealso marker="#close">close</seealso>.</p>
-
- <marker id="pwd"></marker>
- </desc>
- </func>
-
- <func>
- <name>pwd(Pid) -> {ok, Dir} | {error, Reason}</name>
- <fsummary>Gets the remote current working directory.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Reason = restriction_reason() | common_reason()</v>
- </type>
- <desc>
- <p>Returns the current working directory at the remote server.</p>
-
- <marker id="recv"></marker>
- <marker id="recv2"></marker>
- <marker id="recv3"></marker>
- </desc>
- </func>
-
- <func>
- <name>recv(Pid, RemoteFile) -> </name>
- <name>recv(Pid, RemoteFile, LocalFile) -> ok | {error, Reason}</name>
- <fsummary>Transfers a file from remote server.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>RemoteFile = LocalFile = string()</v>
- <v>Reason = restriction_reason() | common_reason() | file_write_error_reason() </v>
- <v>file_write_error_reason() = see file:write/2</v>
- </type>
- <desc>
- <p>Transfers the file <c>RemoteFile</c> from the remote server
- to the file system of the local client. If
- <c>LocalFile</c> is specified, the local file will be
- <c>LocalFile</c>, otherwise
- <c>RemoteFile</c>.</p>
- <p>If the file write fails (for example, <c>enospc</c>), the command is
- aborted and <c>{error, file_write_error_reason()}</c> is returned.
- However, the file is <em>not</em> removed.</p>
-
- <marker id="recv_bin"></marker>
- </desc>
- </func>
-
- <func>
- <name>recv_bin(Pid, RemoteFile) -> {ok, Bin} | {error, Reason}</name>
- <fsummary>Transfers a file from remote server as a binary.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Bin = binary()</v>
- <v>RemoteFile = string()</v>
- <v>Reason = restriction_reason() | common_reason()</v>
- </type>
- <desc>
- <p>Transfers the file <c>RemoteFile</c> from the remote server and
- receives it as a binary.</p>
-
- <marker id="recv_chunk_start"></marker>
- </desc>
- </func>
-
- <func>
- <name>recv_chunk_start(Pid, RemoteFile) -> ok | {error, Reason}</name>
- <fsummary>Starts chunk-reading of the remote file.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>RemoteFile = string()</v>
- <v>Reason = restriction_reason() | common_reason()</v>
- </type>
- <desc>
- <p>Starts transfer of the file <c>RemoteFile</c> from the
- remote server.</p>
-
- <marker id="recv_chunk"></marker>
- </desc>
- </func>
-
- <func>
- <name>recv_chunk(Pid) -> ok | {ok, Bin} | {error, Reason}</name>
- <fsummary>Receives a chunk of the remote file.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Bin = binary()</v>
- <v>Reason = restriction_reason() | common_reason()</v>
- </type>
- <desc>
- <p>Receives a chunk of the remote file (<c>RemoteFile</c> of
- <c>recv_chunk_start</c>). The return values have the following
- meaning:</p>
- <list type="bulleted">
- <item><c>ok</c> = the transfer is complete.</item>
- <item><c>{ok, Bin}</c> = just another chunk of the file.</item>
- <item><c>{error, Reason}</c> = transfer failed.</item>
- </list>
-
- <marker id="rename"></marker>
- </desc>
- </func>
-
- <func>
- <name>rename(Pid, Old, New) -> ok | {error, Reason}</name>
- <fsummary>Renames a file at the remote server.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>CurrFile = NewFile = string()</v>
- <v>Reason = restriction_reason() | common_reason()</v>
- </type>
- <desc>
- <p>Renames <c>Old</c> to <c>New</c> at the remote server.</p>
-
- <marker id="rmdir"></marker>
- </desc>
- </func>
-
- <func>
- <name>rmdir(Pid, Dir) -> ok | {error, Reason}</name>
- <fsummary>Removes a remote directory.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Dir = string()</v>
- <v>Reason = restriction_reason() | common_reason()</v>
- </type>
- <desc>
- <p>Removes directory <c>Dir</c> at the remote server.</p>
-
- <marker id="send"></marker>
- <marker id="send2"></marker>
- <marker id="send3"></marker>
- </desc>
- </func>
-
- <func>
- <name>send(Pid, LocalFile) -></name>
- <name>send(Pid, LocalFile, RemoteFile) -> ok | {error, Reason}</name>
- <fsummary>Transfers a file to the remote server.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>LocalFile = RemoteFile = string()</v>
- <v>Reason = restriction_reason() | common_reason() | shortage_reason()</v>
- </type>
- <desc>
- <p>Transfers the file <c>LocalFile</c> to the remote server. If
- <c>RemoteFile</c> is specified, the name of the remote file is set
- to <c>RemoteFile</c>, otherwise to <c>LocalFile</c>.</p>
-
- <marker id="send_bin"></marker>
- </desc>
- </func>
-
- <func>
- <name>send_bin(Pid, Bin, RemoteFile) -> ok | {error, Reason}</name>
- <fsummary>Transfers a binary into a remote file.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Bin = binary()()</v>
- <v>RemoteFile = string()</v>
- <v>Reason = restriction_reason() | common_reason() | shortage_reason()</v>
- </type>
- <desc>
- <p>Transfers the binary <c>Bin</c> into the file <c>RemoteFile</c>
- at the remote server.</p>
-
- <marker id="send_chunk"></marker>
- </desc>
- </func>
-
- <func>
- <name>send_chunk(Pid, Bin) -> ok | {error, Reason}</name>
- <fsummary>Writes a chunk to the remote file.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Bin = binary()</v>
- <v>Reason = echunk | restriction_reason() | common_reason()</v>
- </type>
- <desc>
- <p>Transfers the chunk <c>Bin</c> to the remote server, which
- writes it into the file specified in the call to
- <c>send_chunk_start/2</c>.</p>
- <p>For some errors, for example, file system full, it is
- necessary to to call <c>send_chunk_end</c> to get the
- proper reason.</p>
-
- <marker id="send_chunk_start"></marker>
- </desc>
- </func>
-
- <func>
- <name>send_chunk_start(Pid, File) -> ok | {error, Reason}</name>
- <fsummary>Starts transfer of file chunks.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>File = string()</v>
- <v>Reason = restriction_reason() | common_reason()</v>
- </type>
- <desc>
- <p>Starts transfer of chunks into the file <c>File</c> at the
- remote server.</p>
-
- <marker id="send_chunk_end"></marker>
- </desc>
- </func>
-
- <func>
- <name>send_chunk_end(Pid) -> ok | {error, Reason}</name>
- <fsummary>Stops transfer of chunks.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Reason = restriction_reason() | common_reason() | shortage_reason()</v>
- </type>
- <desc>
- <p>Stops transfer of chunks to the remote server. The file at the
- remote server, specified in the call to <c>send_chunk_start/2</c>
- is closed by the server.</p>
-
- <marker id="type"></marker>
- </desc>
- </func>
-
- <func>
- <name>type(Pid, Type) -> ok | {error, Reason}</name>
- <fsummary>Sets transfer type to <c>ascii</c>or <c>binary</c>.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Type = ascii | binary</v>
- <v>Reason = etype | restriction_reason() | common_reason()</v>
- </type>
- <desc>
- <p>Sets the file transfer type to <c>ascii</c> or <c>binary</c>. When
- an FTP session is opened, the default transfer type of the
- server is used, most often <c>ascii</c>, which is default
- according to <url href="http://www.ietf.org/rfc/rfc959.txt">RFC 959</url>.</p>
- <marker id="user3"></marker>
- </desc>
- </func>
-
- <func>
- <name>user(Pid, User, Password) -> ok | {error, Reason}</name>
- <fsummary>User login.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>User = Password = string()</v>
- <v>Reason = euser | common_reason()</v>
- </type>
- <desc>
- <p>Performs login of <c>User</c> with <c>Password</c>.</p>
-
- <marker id="user4"></marker>
- </desc>
- </func>
-
- <func>
- <name>user(Pid, User, Password, Account) -> ok | {error, Reason}</name>
- <fsummary>User login.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>User = Password = string()</v>
- <v>Reason = euser | common_reason() </v>
- </type>
- <desc>
- <p>Performs login of <c>User</c> with <c>Password</c> to the account
- specified by <c>Account</c>.</p>
-
- <marker id="quote"></marker>
- </desc>
- </func>
-
- <func>
- <name>quote(Pid, Command) -> [FTPLine]</name>
- <fsummary>Sends an arbitrary FTP command.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Command = string()</v>
- <v>FTPLine = string(</v>
- </type>
- <desc><note><p>The telnet end of line characters, from the FTP
- protocol definition, CRLF, for example, "\\r\\n" has been removed.</p></note>
- <p>Sends an arbitrary FTP command and returns verbatim a list
- of the lines sent back by the FTP server. This function is
- intended to give application accesses to FTP commands
- that are server-specific or that cannot be provided by
- this FTP client.</p>
- <note>
- <p>FTP commands requiring a data connection cannot be
- successfully issued with this function.</p>
- </note>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>ERRORS</title>
- <p>The possible error reasons and the corresponding diagnostic strings
- returned by <c>formaterror/1</c> are as follows:
- </p>
- <taglist>
- <tag><c>echunk</c></tag>
- <item>
- <p>Synchronization error during chunk sending according to one
- of the following:
- </p><list type="bulleted">
- <item>A call is made to <c>send_chunk/2</c> or <c>send_chunk_end/1</c>
- before a call to <c>send_chunk_start/2</c>.</item>
- <item>A call has been made to another transfer function during chunk
- sending, that is, before a call to <c>send_chunk_end/1</c>.</item>
- </list>
- </item>
- <tag><c>eclosed</c></tag>
- <item>
- <p>The session is closed.</p>
- </item>
- <tag><c>econn</c></tag>
- <item>
- <p>Connection to the remote server is prematurely closed.</p>
- </item>
- <tag><c>ehost</c></tag>
- <item>
- <p>Host is not found, FTP server is not found, or connection is rejected
- by FTP server.</p>
- </item>
- <tag><c>elogin</c></tag>
- <item>
- <p>User is not logged in.</p>
- </item>
- <tag><c>enotbinary</c></tag>
- <item>
- <p>Term is not a binary.</p>
- </item>
- <tag><c>epath</c></tag>
- <item>
- <p>No such file or directory, or directory already exists, or
- permission denied.</p>
- </item>
- <tag><c>etype</c></tag>
- <item>
- <p>No such type.</p>
- </item>
- <tag><c>euser</c></tag>
- <item>
- <p>Invalid username or password.</p>
- </item>
- <tag><c>etnospc</c></tag>
- <item>
- <p>Insufficient storage space in system [452].</p>
- </item>
- <tag><c>epnospc</c></tag>
- <item>
- <p>Exceeded storage allocation (for current directory or
- dataset) [552].</p>
- </item>
- <tag><c>efnamena</c></tag>
- <item>
- <p>Filename not allowed [553].</p>
- </item>
- </taglist>
- </section>
-
- <section>
- <title>SEE ALSO</title>
- <p><seealso marker="kernel:file">file(3)</seealso>
- <seealso marker="stdlib:filename">filename(3)</seealso>
- and J. Postel and J. Reynolds: File Transfer Protocol
- (<url href="http://www.ietf.org/rfc/rfc959.txt">RFC 959</url>).
- </p>
- </section>
-
-</erlref>
-
-
diff --git a/lib/inets/doc/src/ftp_client.xml b/lib/inets/doc/src/ftp_client.xml
deleted file mode 100644
index 990dd68604..0000000000
--- a/lib/inets/doc/src/ftp_client.xml
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>FTP Client</title>
- <prepared>Ingela Anderton Andin</prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date></date>
- <rev></rev>
- <file>ftp_client.xml</file>
- </header>
-
- <section>
- <title>Getting Started</title>
-
- <p>FTP clients are considered to be rather temporary. Thus,
- they are only started and stopped during runtime and cannot
- be started at application startup.
- The FTP client API is designed to allow some functions to
- return intermediate results. This implies that only the process
- that started the FTP client can access it with
- preserved sane semantics.
- If the process that started the FTP session
- dies, the FTP client process terminates.</p>
-
- <p>The client supports IPv6 as long as the underlying mechanisms
- also do so.</p>
-
- <p>The following is a simple example of an FTP session, where
- the user <c>guest</c> with password <c>password</c> logs on to
- the remote host <c>erlang.org</c>:</p>
- <code type="erl"><![CDATA[
- 1> inets:start().
- ok
- 2> {ok, Pid} = inets:start(ftpc, [{host, "erlang.org"}]).
- {ok,<0.22.0>}
- 3> ftp:user(Pid, "guest", "password").
- ok
- 4> ftp:pwd(Pid).
- {ok, "/home/guest"}
- 5> ftp:cd(Pid, "appl/examples").
- ok
- 6> ftp:lpwd(Pid).
- {ok, "/home/fred"}.
- 7> ftp:lcd(Pid, "/home/eproj/examples").
- ok
- 8> ftp:recv(Pid, "appl.erl").
- ok
- 9> inets:stop(ftpc, Pid).
- ok
- ]]></code>
- <p> The file
- <c>appl.erl</c> is transferred from the remote to the local
- host. When the session is opened, the current directory at
- the remote host is <c>/home/guest</c>, and <c>/home/fred</c>
- at the local host. Before transferring the file, the current
- local directory is changed to <c>/home/eproj/examples</c>, and
- the remote directory is set to
- <c>/home/guest/appl/examples</c>.</p>
- </section>
-</chapter>
-
-
diff --git a/lib/inets/doc/src/http_client.xml b/lib/inets/doc/src/http_client.xml
index 212958f17f..c31a47f4f4 100644
--- a/lib/inets/doc/src/http_client.xml
+++ b/lib/inets/doc/src/http_client.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2016</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -97,27 +97,32 @@
7 > {ok, {{NewVersion, 200, NewReasonPhrase}, NewHeaders, NewBody}} =
httpc:request(get, {"http://www.erlang.org", [{"connection", "close"}]},
[], []).</code>
-
+ <p>This sends an HTTP request over a unix domain socket (experimental):</p>
+ <code type="erl">
+ 8 > httpc:set_options([{ipfamily, local},
+ {unix_socket,"/tmp/unix_socket/consul_http.sock"}]).
+ 9 > {ok, {{NewVersion, 200, NewReasonPhrase}, NewHeaders, NewBody}} =
+ httpc:request(put, {"http:///v1/kv/foo", [], [], "hello"}, [], []).</code>
<p>Start an HTTP client profile:</p>
<code><![CDATA[
- 8 > {ok, Pid} = inets:start(httpc, [{profile, foo}]).
+ 10 > {ok, Pid} = inets:start(httpc, [{profile, foo}]).
{ok, <0.45.0>}
]]></code>
<p>The new profile has no proxy settings, so the connection is refused:</p>
<code type="erl">
- 9 > httpc:request("http://www.erlang.org", foo).
+ 11 > httpc:request("http://www.erlang.org", foo).
{error, econnrefused}</code>
<p>Stop the HTTP client profile:</p>
<code type="erl">
- 10 > inets:stop(httpc, foo).
+ 12 > inets:stop(httpc, foo).
ok</code>
<p>Alternative way to stop the HTTP client profile:</p>
<code type="erl">
- 10 > inets:stop(httpc, Pid).
+ 13 > inets:stop(httpc, Pid).
ok</code>
</section>
diff --git a/lib/inets/doc/src/http_uri.xml b/lib/inets/doc/src/http_uri.xml
index 20c042c202..2dec5acbf9 100644
--- a/lib/inets/doc/src/http_uri.xml
+++ b/lib/inets/doc/src/http_uri.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2012</year><year>2017</year>
+ <year>2012</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -45,7 +45,6 @@
this module:</p>
<p><c>boolean() = true | false</c></p>
<p><c>string()</c> = list of ASCII characters</p>
- <p><c>unicode_binary()</c> = binary() with characters encoded in the UTF-8 coding standard</p>
</section>
@@ -54,22 +53,22 @@
<p>Type definitions that are related to URI:</p>
<taglist>
- <tag><c>uri() = string() | unicode:unicode_binary()</c></tag>
+ <tag><c>uri() = string() | binary()</c></tag>
<item><p>Syntax according to the URI definition in RFC 3986,
for example, "http://www.erlang.org/"</p></item>
- <tag><c>user_info() = string() | unicode:unicode_binary()</c></tag>
+ <tag><c>user_info() = string() | binary()</c></tag>
<item><p></p></item>
<tag><c>scheme() = atom()</c></tag>
<item><p>Example: http, https</p></item>
- <tag><c>host() = string() | unicode:unicode_binary()</c></tag>
+ <tag><c>host() = string() | binary()</c></tag>
<item><p></p></item>
- <tag><c>port() = pos_integer()</c></tag>
+ <tag><c>port() = inet:port_number()</c></tag>
<item><p></p></item>
- <tag><c>path() = string() | unicode:unicode_binary()</c></tag>
+ <tag><c>path() = string() | binary()</c></tag>
<item><p>Represents a file path or directory path</p></item>
- <tag><c>query() = string() | unicode:unicode_binary()</c></tag>
+ <tag><c>query() = string() | binary()</c></tag>
<item><p></p></item>
- <tag><c>fragment() = string() | unicode:unicode_binary()</c></tag>
+ <tag><c>fragment() = string() | binary()</c></tag>
<item><p></p></item>
</taglist>
@@ -84,7 +83,7 @@
<fsummary>Decodes a hexadecimal encoded URI.</fsummary>
<type>
- <v>HexEncodedURI = string() | unicode:unicode_binary() - A possibly hexadecimal encoded URI</v>
+ <v>HexEncodedURI = string() | binary() - A possibly hexadecimal encoded URI</v>
<v>URI = uri()</v>
</type>
@@ -99,7 +98,7 @@
<fsummary>Encodes a hexadecimal encoded URI.</fsummary>
<type>
<v>URI = uri()</v>
- <v>HexEncodedURI = string() | unicode:unicode_binary() - Hexadecimal encoded URI</v>
+ <v>HexEncodedURI = string() | binary() - Hexadecimal encoded URI</v>
</type>
<desc>
@@ -119,12 +118,13 @@
<v>Option = {ipv6_host_with_brackets, boolean()} |
{scheme_defaults, scheme_defaults()} |
{fragment, boolean()} |
- {scheme_validation_fun, fun()}]</v>
+ {scheme_validation_fun, fun()}</v>
<v>Result = {Scheme, UserInfo, Host, Port, Path, Query} |
{Scheme, UserInfo, Host, Port, Path, Query, Fragment}</v>
+ <v>Scheme = scheme()</v>
<v>UserInfo = user_info()</v>
<v>Host = host()</v>
- <v>Port = pos_integer()</v>
+ <v>Port = inet:port_number()</v>
<v>Path = path()</v>
<v>Query = query()</v>
<v>Fragment = fragment()</v>
@@ -146,13 +146,20 @@
<p>Scheme validation fun is to be defined as follows:</p>
<code>
-fun(SchemeStr :: string() | unicode:unicode_binary()) ->
+fun(SchemeStr :: string() | binary()) ->
valid | {error, Reason :: term()}.
</code>
<p>It is called before scheme string gets converted into scheme atom and
thus possible atom leak could be prevented</p>
+ <warning>
+ <p>The scheme portion of the URI gets converted into atom,
+ meaning that atom leak may occur. Specifying a scheme
+ validation fun is recommended unless the URI is already
+ sanitized.</p>
+ </warning>
+
<marker id="encode"></marker>
</desc>
</func>
@@ -162,7 +169,7 @@ fun(SchemeStr :: string() | unicode:unicode_binary()) ->
<fsummary>A list of the scheme and their default ports.</fsummary>
<type>
<v>SchemeDefaults = [{scheme(), default_scheme_port_number()}] </v>
- <v>default_scheme_port_number() = pos_integer()</v>
+ <v>default_scheme_port_number() = inet:port_number()</v>
</type>
<desc>
<p>Provides a list of the scheme and their default
diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml
index 66ec6cabd8..a2871f3b95 100644
--- a/lib/inets/doc/src/httpc.xml
+++ b/lib/inets/doc/src/httpc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -210,7 +210,8 @@
ip |
port |
socket_opts |
- verbose</v>
+ verbose |
+ unix_socket</v>
<v>Profile = profile() | pid()</v>
<d>When started <c>stand_alone</c> only the pid can used.</d>
<v>Values = [{option_item(), term()}]</v>
@@ -287,8 +288,7 @@
{autoredirect, boolean()} |
{proxy_auth, {userstring(), passwordstring()}} |
{version, http_version()} |
- {relaxed, boolean()} |
- {url_encode, boolean()}</v>
+ {relaxed, boolean()}</v>
<v>timeout() = integer() >= 0 | infinity</v>
<v>Options = options()</v>
<v>options() = [option()]</v>
@@ -298,8 +298,8 @@
{full_result, boolean()} |
{headers_as_is, boolean() |
{socket_opts, socket_opts()} |
- {receiver, receiver()},
- {ipv6_host_with_brackets, boolean()}}</v>
+ {receiver, receiver()} |
+ {ipv6_host_with_brackets, boolean()}</v>
<v>stream_to() = none | self | {self, once} | filename()</v>
<v>socket_opts() = [socket_opt()]</v>
<v>receiver() = pid() | function()/1 | {Module, Function, Args}</v>
@@ -312,8 +312,7 @@
<v>Body = string() | binary()</v>
<v>Profile = profile() | pid()</v>
<d>When started <c>stand_alone</c> only the pid can be used.</d>
- <v>Reason = {connect_failed, term()} |
- {send_failed, term()} | term()</v>
+ <v>Reason = term()</v>
</type>
<desc>
@@ -379,13 +378,6 @@
from the HTTP-standard are enabled.</p>
<p>Default is <c>false</c>.</p>
</item>
-
- <tag><c><![CDATA[url_encode]]></c></tag>
- <item>
- <p>Applies Percent-encoding, also known as URL encoding on the
- URL.</p>
- <p>Default is <c>false</c>.</p>
- </item>
</taglist>
<p>Option (<c>option()</c>) details:</p>
@@ -408,7 +400,7 @@
<c>{self, once}</c>, the first message has an extra
element, that is, <c>{http, {RequestId, stream_start, Headers, Pid}}</c>.
This is the process id to be used as an argument to
- <c>http:stream_next/1</c> to trigger the next message to be sent to
+ <c>httpc:stream_next/1</c> to trigger the next message to be sent to
the calling process.</p>
<p>Notice that chunked encoding can add
headers so that there are more headers in the <c>stream_end</c>
@@ -449,17 +441,22 @@
<tag><c><![CDATA[socket_opts]]></c></tag>
<item>
- <p>Socket options to be used for this and subsequent
- requests.</p>
+ <p>Socket options to be used for this request.</p>
<p>Overrides any value set by function
<seealso marker="#set_options-1">set_options</seealso>.</p>
<p>The validity of the options is <em>not</em> checked by
the HTTP client they are assumed to be correct and passed
on to ssl application and inet driver, which may reject
- them if they are not correct. Note that the current
- implementation assumes the requests to the same host, port
- combination will use the same socket options.
+ them if they are not correct.
</p>
+ <note>
+ <p>
+ Persistent connections are not supported when setting the
+ <c>socket_opts</c> option. When <c>socket_opts</c> is not
+ set the current implementation assumes the requests to the
+ same host, port combination will use the same socket options.
+ </p>
+ </note>
<p>By default the socket options set by function
<seealso marker="#set_options-1">set_options/[1,2]</seealso>
@@ -541,7 +538,8 @@
<v>| {ip, IpAddress}</v>
<v>| {port, Port}</v>
<v>| {socket_opts, socket_opts()}</v>
- <v>| {verbose, VerboseMode}</v>
+ <v>| {verbose, VerboseMode}</v>
+ <v>| {unix_socket, UnixSocket}</v>
<v>Proxy = {Hostname, Port}</v>
<v>Hostname = string()</v>
<d>Example: "localhost" or "foo.bar.se"</d>
@@ -584,7 +582,7 @@
If option <c>verify</c> is used, function <c>store_cookies/2</c>
has to be called for the cookies to be saved.
Default is <c>disabled</c>.</d>
- <v>IpFamily = inet | inet6 </v>
+ <v>IpFamily = inet | inet6 | local</v>
<d>Default is <c>inet</c>.</d>
<v>IpAddress = ip_address()</v>
<d>If the host has several network interfaces, this option specifies
@@ -609,6 +607,12 @@
It is a debug feature.</d>
<v>Profile = profile() | pid()</v>
<d>When started <c>stand_alone</c> only the pid can be used.</d>
+ <v>UnixSocket = path()</v>
+ <d>
+ Experimental option for sending HTTP requests over a unix domain socket. The value
+ of <c>unix_socket</c> shall be the full path to a unix domain socket file with read/write
+ permissions for the erlang process. Default is <c>undefined</c>.
+ </d>
</type>
<desc>
<p>Sets options to be used for subsequent requests.</p>
@@ -625,8 +629,11 @@
to complete. The HTTP/1.1 specification suggests a
limit of two persistent connections per server, which is the
default value of option <c>max_sessions</c>.</p>
+ <p>
+ The current implementation assumes the requests to the same host, port
+ combination will use the same socket options.
+ </p>
</note>
-
<marker id="get_options"></marker>
</desc>
</func>
diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml
index d74635fc01..2c70c2b050 100644
--- a/lib/inets/doc/src/httpd.xml
+++ b/lib/inets/doc/src/httpd.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -279,7 +279,18 @@
requests defined by <c>max_keep_alive_requests</c>, the server
closes the connection. The server closes it even if there are
queued request. Default is no limit.</p>
- </item>
+ </item>
+
+
+ <tag><marker id="max_client_body_chunk"></marker>{max_client_body_chunk, integer()}</tag>
+ <item>
+ <p>Enforces chunking of a HTTP PUT or POST body data to be deliverd
+ to the mod_esi callback. Note this is not supported for mod_cgi.
+ Default is no limit e.i the whole body is deliverd as one entity, which could
+ be very memory consuming. <seealso marker="mod_esi">mod_esi(3)</seealso>.
+ </p>
+ </item>
+
</taglist>
<marker id="props_admin"></marker>
diff --git a/lib/inets/doc/src/inets.gif b/lib/inets/doc/src/inets.gif
deleted file mode 100644
index 64968ae68a..0000000000
--- a/lib/inets/doc/src/inets.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/doc/src/inets.xml b/lib/inets/doc/src/inets.xml
index 137381cbe9..9b0ffaad5e 100644
--- a/lib/inets/doc/src/inets.xml
+++ b/lib/inets/doc/src/inets.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2007</year><year>2016</year>
+ <year>2007</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -188,10 +188,9 @@
<section>
<title>SEE ALSO</title>
- <p><seealso marker="ftp">ftp(3)</seealso>,
- <seealso marker="httpc">httpc(3)</seealso>,
- <seealso marker="httpd">httpd(3)</seealso>,
- <seealso marker="tftp">tftp(3)</seealso></p>
+ <p><seealso marker="httpc">httpc(3)</seealso>,
+ <seealso marker="httpd">httpd(3)</seealso>
+ </p>
</section>
</erlref>
diff --git a/lib/inets/doc/src/introduction.xml b/lib/inets/doc/src/introduction.xml
index 1af2ef5dae..faf911f188 100644
--- a/lib/inets/doc/src/introduction.xml
+++ b/lib/inets/doc/src/introduction.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -22,12 +22,12 @@
</legalnotice>
<title>Introduction</title>
- <prepared>Ingela Anderton Andin</prepared>
+ <prepared>Péter Dimitrov</prepared>
<responsible></responsible>
<docno></docno>
<approved></approved>
<checked></checked>
- <date>2004-09-28</date>
+ <date>2018-02-28</date>
<rev>A</rev>
<file>introduction.xml</file>
</header>
@@ -37,8 +37,6 @@
<p><c>Inets</c> is a container for Internet clients and servers
including the following:</p>
<list type="bulleted">
- <item>An FTP client</item>
- <item>A TFTP client and server</item>
<item>An <term id="HTTP"></term> client and server</item>
</list>
<p>The HTTP client and server are HTTP 1.1 compliant as
@@ -50,7 +48,7 @@
<title>Prerequisites</title>
<p>It is assumed that the reader is familiar with the Erlang
programming language, concepts of OTP, and has a basic
- understanding of the FTP, TFTP, and HTTP protocols.</p>
+ understanding of and HTTP protocol.</p>
</section>
</chapter>
diff --git a/lib/inets/doc/src/min_head.gif b/lib/inets/doc/src/min_head.gif
deleted file mode 100644
index 67948a6378..0000000000
--- a/lib/inets/doc/src/min_head.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/doc/src/mod_esi.xml b/lib/inets/doc/src/mod_esi.xml
index 46cc796c8a..ede7dc8f7d 100644
--- a/lib/inets/doc/src/mod_esi.xml
+++ b/lib/inets/doc/src/mod_esi.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -121,35 +121,60 @@
<funcs>
<func>
- <name>Module:Function(SessionID, Env, Input)-> _ </name>
+ <name>Module:Function(SessionID, Env, Input)-> {continue, State} | _ </name>
<fsummary>Creates a dynamic web page and returns it chunk by chunk
to the server process by calling <c>mod_esi:deliver/2</c>.</fsummary>
<type>
<v>SessionID = term()</v>
<v>Env = env()</v>
- <v>Input = string()</v>
+ <v>Input = string() | chunked_data()</v>
+ <v>chunked_data() = {first, Data::binary()} |
+ {continue, Data::binary(), State::term()} |
+ {last, Data::binary(), State::term()} </v>
+ <v>State = term()</v>
</type>
<desc>
<p><c>Module</c> must be found in the code path and export
<c>Function</c> with an arity of three. An <c>erlScriptAlias</c> must
also be set up in the configuration file for the web server.</p>
- <p>If the HTTP request is a 'post' request and a body is sent,
- <c>content_length</c> is the length of the posted
- data. If 'get' is used, <c>query_string</c> is the data after
- <em>?</em> in the URL.</p>
- <p><c>ParsedHeader</c> is the HTTP request as a key-value tuple
- list. The keys in <c>ParsedHeader</c> are in lower case.</p>
- <p><c>SessionID</c> is an identifier
- the server uses when <c>deliver/2</c> is called. Do not
- assume anything about the datatype.</p>
- <p>Use this callback function to generate dynamic web
- content dynamically. When a part of the page is generated, send the
- data back to the client through <c>deliver/2</c>. Notice
- that the first chunk of data sent to the client must at
- least contain all HTTP header fields that the response
- will generate. If the first chunk does not contain the
- <em>end of HTTP header</em>, that is, <c>"\r\n\r\n",</c>
- the server assumes that no HTTP header fields will be generated.</p>
+
+ <p><c>mod_esi:deliver/2</c> shall be used to generate the response
+ to the client and <c>SessionID</c> is an identifier that shall by used when
+ calling this function, do not assume anything about
+ the datatype. This function may be called
+ several times to chunk the response data. Notice that the
+ first chunk of data sent to the client must at least contain
+ all HTTP header fields that the response will generate. If the
+ first chunk does not contain the <em>end of HTTP header</em>,
+ that is, <c>"\r\n\r\n",</c> the server assumes that no HTTP
+ header fields will be generated.</p>
+
+ <p><c>Env</c> environment data of the request see description above.</p>
+
+ <p><c>Input</c> is query data of a GET request or the body of
+ a PUT or POST request. The default behavior (legacy reasons)
+ for delivering the body, is that the whole body is gathered and
+ converted to a string. But if the httpd config parameter
+ <seealso
+ marker="httpd#max_client_body_chunk">max_client_body_chunk</seealso>
+ is set, the body will be delivered as binary chunks
+ instead. The maximum size of the chunks is either <seealso
+ marker="httpd#max_client_body_chunk">max_client_body_chunk</seealso>
+ or decide by the client if it uses HTTP chunked encoding
+ to send the body. When using the chunking
+ mechanism this callback must return {continue, State::term()}
+ for all calls where <c>Input</c> is <c>{first,
+ Data::binary()}</c> or <c>{continue, Data::binary(),
+ State::term()}</c>. When <c>Input</c> is <c>{last,
+ Data::binary(), State::term()}</c> the return value will be ignored.</p>
+ <note><p>Note that if the body is
+ small all data may be delivered in only one chunk and then the
+ callback will be called with {last, Data::binary(), undefined}
+ without getting called with <c>{first,
+ Data::binary()}</c>.</p></note><p>The input <c>State</c> is
+ the last returned <c>State</c>, in it the callback can include
+ any data that it needs to keep track of when handling the chunks.
+ </p>
</desc>
</func>
@@ -159,14 +184,13 @@
This function is deprecated and is only kept for backwards compatibility.</fsummary>
<type>
<v>Env = env()</v>
- <v>Input = string()</v>
+ <v>Input = string() </v>
<v>Response = string()</v>
</type>
<desc>
<p>This callback format consumes much memory, as the
whole response must be generated before it is sent to the
- user. This function is deprecated and is only kept for backwards
- compatibility.
+ user. This callback format is deprecated.
For new development, use <c>Module:Function/3</c>.</p>
</desc>
</func>
diff --git a/lib/inets/doc/src/mod_security.xml b/lib/inets/doc/src/mod_security.xml
index ec8d6ec42c..6f3f3c048a 100644
--- a/lib/inets/doc/src/mod_security.xml
+++ b/lib/inets/doc/src/mod_security.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1998</year><year>2016</year>
+ <year>1998</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -135,7 +135,8 @@
<type>
<v>What = atom()</v>
<v>Port = integer()</v>
- <v>Address = {A,B,C,D} | string() &lt;v>Dir = string()</v>
+ <v>Address = {A,B,C,D} | string()</v>
+ <v>Dir = string()</v>
<v>Data = [Info]</v>
<v>Info = {Name, Value}</v>
</type>
diff --git a/lib/inets/doc/src/note.gif b/lib/inets/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/inets/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/doc/src/notes.gif b/lib/inets/doc/src/notes.gif
deleted file mode 100644
index e000cca26a..0000000000
--- a/lib/inets/doc/src/notes.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index 2f4f20347a..fdcb394108 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2002</year><year>2017</year>
+ <year>2002</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,7 +33,396 @@
<file>notes.xml</file>
</header>
- <section><title>Inets 6.4</title>
+ <section><title>Inets 7.0.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Enhance error handling, that is mod_get will return 403
+ if a path is a directory and not a file.</p>
+ <p>
+ Own Id: OTP-15192</p>
+ </item>
+ <item>
+ <p>
+ Do not use chunked-encoding with 1xx, 204 and 304
+ responses when using mod_esi. Old behavior was not
+ compliant with HTTP/1.1 RFC and could cause clients to
+ hang when they received 1xx, 204 or 304 responses that
+ included an empty chunked-encoded body.</p>
+ <p>
+ Own Id: OTP-15241</p>
+ </item>
+ <item>
+ <p>
+ Add robust handling of chunked-encoded HTTP responses
+ with an empty body (1xx, 204, 304). Old behavior could
+ cause the client to hang when connecting to a faulty
+ server implementation.</p>
+ <p>
+ Own Id: OTP-15242</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 7.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Change status code for no mod found to handle request to
+ 501</p>
+ <p>
+ Own Id: OTP-15215</p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+ <section><title>Inets 7.0</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed HTTP content injection bug in httpc (ERL-456).</p>
+ <p>
+ Own Id: OTP-14726</p>
+ </item>
+ <item>
+ <p>
+ Fixed support for URI-references in HTTP 'Location'
+ header (ERL-333).</p>
+ <p>
+ Own Id: OTP-14729</p>
+ </item>
+ <item>
+ <p>
+ Fix broken 'Content-Type' handling in httpc (ERL-536).</p>
+ <p>
+ Own Id: OTP-15006</p>
+ </item>
+ <item>
+ <p>
+ Fix handling of relative paths in the script_alias
+ property of httpd (ERL-574).</p>
+ <p>
+ Own Id: OTP-15021</p>
+ </item>
+ <item>
+ <p>
+ Fix httpd:reload_config/2 with path() as the first
+ argument (ERL-578).</p>
+ <p>
+ Own Id: OTP-15025</p>
+ </item>
+ <item>
+ <p>
+ Improved gracefulness.</p>
+ <p>
+ Own Id: OTP-15042</p>
+ </item>
+ </list>
+ </section>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Split inets and create separate ftp and tftp apps.</p>
+ <p>
+ Own Id: OTP-14113</p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+ <section><title>Inets 6.5.2.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Do not use chunked-encoding with 1xx, 204 and 304
+ responses when using mod_esi. Old behavior was not
+ compliant with HTTP/1.1 RFC and could cause clients to
+ hang when they received 1xx, 204 or 304 responses that
+ included an empty chunked-encoded body.</p>
+ <p>
+ Own Id: OTP-15241</p>
+ </item>
+ <item>
+ <p>
+ Add robust handling of chunked-encoded HTTP responses
+ with an empty body (1xx, 204, 304). Old behavior could
+ cause the client to hang when connecting to a faulty
+ server implementation.</p>
+ <p>
+ Own Id: OTP-15242</p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+ <section><title>Inets 6.5.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Change status code for no mod found to handle request to
+ 501</p>
+ <p>
+ Own Id: OTP-15215</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.5.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Enhance error handling, that is mod_get will return 403
+ if a path is a directory and not a file.</p>
+ <p>
+ Own Id: OTP-15192</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+ <section><title>Inets 6.5.2.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Options added for setting low-level properties on the
+ underlying TCP connections. The options are:
+ <c>sock_ctrl</c>, <c>sock_data_act</c> and
+ <c>sock_data_pass</c>. See the manual for details.</p>
+ <p>
+ Own Id: OTP-15120 Aux Id: ERIERL-192 </p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+<section><title>Inets 6.5.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ inets: httpd - Gracefully handle bad headers</p>
+ <p>
+ The option max_headers operated on the individual header
+ length instead of the total length of all headers. Also
+ headers with empty keys are now discarded.</p>
+ <p>
+ Own Id: OTP-15092</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.5.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix broken options handling in httpc (ERL-441).</p>
+ <p>
+ Own Id: OTP-15007</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ httpc_manager crashes when a long running request is sent
+ on a persistent HTTP connection (keep-alive). Fixed
+ httpc_manager to use proper timeouts on keep-alive
+ connections.</p>
+ <p>
+ Own Id: OTP-14908</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add support for unix domain sockets in the http client.</p>
+ <p>
+ Own Id: OTP-14854</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.4.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ CGI environment variable CONTENT_LENGTH shall be a string</p>
+ <p>
+ Own Id: OTP-14679</p>
+ </item>
+ <item>
+ <p>
+ In relaxed mode disregard Content-Length header if there
+ is also a Transfer-Encoding header.</p>
+ <p>
+ Own Id: OTP-14727</p>
+ </item>
+ <item>
+ <p>
+ Eliminated race condition, that could cause http request
+ to sporadically fail to complete successfully, when
+ keep-alive connections are used.</p>
+ <p>
+ Own Id: OTP-14783</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.4.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Correct the handling of location headers so that the
+ status code is not hard coded. This should have been
+ fixed by commit 2cc5ba70cbbc6b3ace81a2a0324417c3b65265bb
+ but unfortunately was broken during a code refactoring
+ and unnoticed due to a faulty placed test case.</p>
+ <p>
+ Own Id: OTP-14761</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.4.3</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Fix broken handling of POST requests</p>
+ <p>
+ New chunk mechanism of body data in POST requests added
+ in 5d01c70ca399edf28e99dc760506329689fab6ba broke
+ handling of POST body data not using the new mechanism.</p>
+ <p>
+ Own Id: OTP-14656</p>
+ </item>
+ <item>
+ <p>
+ Make sure ints:stop/2 of the service httpd is synchronous</p>
+ <p>
+ Own Id: OTP-14696</p>
+ </item>
+ <item>
+ <p>
+ Honor status code returned by ESI script and modernize
+ "location" header handling.</p>
+ <p>
+ Own Id: OTP-14716</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.4.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Make sure mod_log uses the correct status code</p>
+ <p>
+ Own Id: OTP-14510</p>
+ </item>
+ <item>
+ <p>
+ Correct behaviour of mod_disk_log to proparly handle
+ repair options</p>
+ <p>
+ Own Id: OTP-14530</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.4.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ http_uri aligned to follow RFC 3986 and not convert "+"
+ to space when decoding URIs.</p>
+ <p>
+ Own Id: OTP-14573</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added new option max_client_body_chunk to httpd server to
+ allow chunked delivery of PUT and POST data to mod_esi
+ callback. Note, new mod_esi callback implementation is
+ required.</p>
+ <p>
+ Also correct value provided by server_name environment
+ variable</p>
+ <p>
+ Own Id: OTP-14450</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
@@ -1599,7 +1988,7 @@
<list>
<item>
<p>[ftpc] Add a config option to specify a
- <seealso marker="ftp#dtimeout">data connect timeout</seealso>.
+ <seealso marker="ftp:ftp#dtimeout">data connect timeout</seealso>.
That is how long the ftp client will wait for the server to connect
to the data socket. If this timeout occurs, an error will be
returned to the caller and the ftp client process will be
@@ -2482,10 +2871,10 @@
<item>
<p>It is now also possible to start a standalone FTP client
process using the re-introduced
- <seealso marker="ftp#open">ftp:open</seealso>
+ <seealso marker="ftp:ftp#open">ftp:open</seealso>
function. </p>
<p>This is an alternative to starting the client using the
- <seealso marker="ftp#service_start">inets service framework</seealso>. </p>
+ <seealso marker="ftp:ftp#service_start">inets service framework</seealso>. </p>
<p>The old <c>ftp:open/1</c>, undocumented, function,
caused the client to be hooken into the inets service
supervision framework. This is <em>no</em> longer the
@@ -2498,10 +2887,10 @@
flag), and only used IPv4 if this did not work.
This has now been <em>changed</em>. </p>
<p>A new option,
- <seealso marker="ftp#ipfamily">ipfamily</seealso>,
+ <seealso marker="ftp:ftp#ipfamily">ipfamily</seealso>,
has been introduced, with the default value
<c>inet</c> (IPv4). </p>
- <p>See <seealso marker="ftp#open">ftp:open</seealso>
+ <p>See <seealso marker="ftp:ftp#open">ftp:open</seealso>
for more info.</p>
<p>*** POTENTIAL INCOMPATIBILITY ***</p>
</item>
@@ -2535,9 +2924,9 @@
<item>
<p>[ftpc] - The
- <seealso marker="ftp#ls2">ls/2</seealso> function (LIST command)
+ <seealso marker="ftp:ftp#ls2">ls/2</seealso> function (LIST command)
and the
- <seealso marker="ftp#nlist2">nlist/2</seealso> function
+ <seealso marker="ftp:ftp#nlist2">nlist/2</seealso> function
(NLST command)
with wildcards did
not work properly. </p>
diff --git a/lib/inets/doc/src/part.xml b/lib/inets/doc/src/part.xml
index f777481b5c..b9c8ed674c 100644
--- a/lib/inets/doc/src/part.xml
+++ b/lib/inets/doc/src/part.xml
@@ -4,7 +4,7 @@
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2004</year><year>2016</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -23,9 +23,9 @@
</legalnotice>
<title>Inets User's Guide</title>
- <prepared>Ingela Anderton Andin</prepared>
+ <prepared>Péter Dimitrov</prepared>
<docno></docno>
- <date>2002-09-17</date>
+ <date>2018-02-28</date>
<rev>A</rev>
<file>part.sgml</file>
</header>
@@ -33,8 +33,6 @@
<p>The <c>Inets</c> application provides a set of
Internet-related services as follows:</p>
<list type="bulleted">
- <item>An FTP client</item>
- <item>A TFTP client and server</item>
<item>An <term id="HTTP"></term> client and server</item>
</list>
<p>The HTTP client and server are HTTP 1.1 compliant as
@@ -43,7 +41,6 @@
</description>
<xi:include href="introduction.xml"/>
<xi:include href="inets_services.xml"/>
- <xi:include href="ftp_client.xml"/>
<xi:include href="http_client.xml"/>
<xi:include href="http_server.xml"/>
</part>
diff --git a/lib/inets/doc/src/part_notes.xml b/lib/inets/doc/src/part_notes.xml
deleted file mode 100644
index d10c829f4a..0000000000
--- a/lib/inets/doc/src/part_notes.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2002</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Inets</title>
- <prepared>Micael Karlberg</prepared>
- <docno></docno>
- <date>2002-02-28</date>
- <rev>3.0</rev>
- <file>part_notes.sgml</file>
- </header>
- <description>
- <p>A set of services such as a Web server and a ftp client etc. </p>
- <p>For information about older versions see
- <url href="part_notes_history_frame.html">release notes history</url>.</p>
- </description>
- <xi:include file="notes.xml"/>
-</part>
-
-
diff --git a/lib/inets/doc/src/part_notes_history.xml b/lib/inets/doc/src/part_notes_history.xml
deleted file mode 100644
index 66e3307f69..0000000000
--- a/lib/inets/doc/src/part_notes_history.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Inets</title>
- <prepared>Micael Karlberg</prepared>
- <docno></docno>
- <date>2002-02-28</date>
- <rev>3.0</rev>
- <file>part_notes.sgml</file>
- </header>
- <include file="notes_history"></include>
-</part>
-
-
diff --git a/lib/inets/doc/src/ref_man.gif b/lib/inets/doc/src/ref_man.gif
deleted file mode 100644
index b13c4efd53..0000000000
--- a/lib/inets/doc/src/ref_man.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/doc/src/ref_man.xml b/lib/inets/doc/src/ref_man.xml
index 27021ea09a..58c1a651f9 100644
--- a/lib/inets/doc/src/ref_man.xml
+++ b/lib/inets/doc/src/ref_man.xml
@@ -4,7 +4,7 @@
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>1997</year><year>2015</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -23,20 +23,16 @@
</legalnotice>
<title>Inets Reference Manual</title>
- <prepared>Joakim Greben&ouml;</prepared>
+ <prepared>Péter Dimitrov</prepared>
<docno></docno>
- <date>1997-07-16</date>
+ <date>2018-02-28</date>
<rev>2.1</rev>
<file>ref_man.xml</file>
</header>
<description>
- <p><c>Inets</c> is a container for Internet clients and
- servers. An FTP client, an HTTP client and server, and
- a TFTP client and server are incorporated in <c>Inets</c>.</p>
+ <p><c>Inets</c> is a container for an HTTP client and server.</p>
</description>
<xi:include href="inets.xml"/>
- <xi:include href="ftp.xml"/>
- <xi:include href="tftp.xml"/>
<xi:include href="httpc.xml"/>
<xi:include href="httpd.xml"/>
<xi:include href="httpd_custom_api.xml"/>
diff --git a/lib/inets/doc/src/summary.html.src b/lib/inets/doc/src/summary.html.src
deleted file mode 100644
index 17637a0787..0000000000
--- a/lib/inets/doc/src/summary.html.src
+++ /dev/null
@@ -1 +0,0 @@
-A set of services such as a web server and a ftp client etc \ No newline at end of file
diff --git a/lib/inets/doc/src/tftp.xml b/lib/inets/doc/src/tftp.xml
deleted file mode 100644
index 10398f5088..0000000000
--- a/lib/inets/doc/src/tftp.xml
+++ /dev/null
@@ -1,647 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2006</year><year>2015</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>tftp</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <module>tftp</module>
- <modulesummary>Trivial FTP.</modulesummary>
- <description>
- <p>This is a complete implementation of the following IETF standards:</p>
- <list type="bulleted">
- <item>RFC 1350, The TFTP Protocol (revision 2)</item>
- <item>RFC 2347, TFTP Option Extension</item>
- <item>RFC 2348, TFTP Blocksize Option</item>
- <item>RFC 2349, TFTP Timeout Interval and Transfer Size Options</item>
- </list>
- <p>The only feature that not is implemented is
- the "netascii" transfer mode.</p>
- <p>The <seealso marker="#start/1">start/1</seealso> function starts
- a daemon process listening for UDP packets on a port. When it
- receives a request for read or write, it spawns a temporary server
- process handling the transfer.</p>
- <p>On the client side,
- function <seealso marker="#read_file/3">read_file/3</seealso>
- and <seealso marker="#write_file/3">write_file/3</seealso>
- spawn a temporary client process establishing
- contact with a TFTP daemon and perform the file transfer.</p>
- <p><c>tftp</c> uses a callback module to handle the file
- transfer. Two such callback modules are provided,
- <c>tftp_binary</c> and <c>tftp_file</c>. See
- <seealso marker="#read_file/3">read_file/3</seealso> and
- <seealso marker="#write_file/3">write_file/3</seealso> for details.
- You can also implement your own callback modules, see
- <seealso marker="#tftp_callback">CALLBACK FUNCTIONS</seealso>.
- A callback module provided by
- the user is registered using option <c>callback</c>, see
- <seealso marker="#options">DATA TYPES</seealso>.</p>
- </description>
-
- <section>
- <title>TFTP SERVER SERVICE START/STOP</title>
-
- <p>A TFTP server can be configured to start statically when starting
- the <c>Inets</c> application. Alternatively, it can be started dynamically
- (when <c>Inets</c> is already started) by calling the <c>Inets</c> application
- API <c>inets:start(tftpd, ServiceConfig)</c> or
- <c>inets:start(tftpd, ServiceConfig, How)</c>,
- see <seealso marker="inets">inets(3)</seealso> for details.
- The <c>ServiceConfig</c> for TFTP is described in
- the <seealso marker="#options">DATA TYPES</seealso>
- section.</p>
-
- <p>The TFTP server can be stopped using <c>inets:stop(tftpd, Pid)</c>,
- see <seealso marker="inets">inets(3)</seealso> for details.</p>
-
- <p>The TPFT client is of such a temporary nature that it is not
- handled as a service in the <c>Inets</c> service framework.</p>
-
- </section>
-
- <section>
- <marker id="options"></marker>
- <title>DATA TYPES</title>
- <p><c>ServiceConfig = Options</c></p>
- <p><c>Options = [option()]</c></p>
- <p>Most of the options are common for both the client and the server
- side, but some of them differs a little.
- The available <c>option()</c>s are as follows:</p>
- <taglist>
- <tag><c>{debug, Level}</c></tag>
- <item>
- <p><c>Level = none | error | warning | brief | normal | verbose | all</c></p>
- <p>Controls the level of debug printouts.
- Default is <c>none</c>.</p>
- </item>
- <tag><c>{host, Host}</c></tag>
- <item>
- <p><c>Host = hostname()</c>, see
- <seealso marker="kernel:inet">inet(3)</seealso>.</p>
- <p>The name or IP address of the host where the TFTP daemon
- resides. This option is only used by the client.</p>
- </item>
- <tag><c>{port, Port}</c></tag>
- <item>
- <p><c>Port = int()</c></p>
- <p>The TFTP port where the daemon listens. Defaults is
- the standardized number 69. On the server side, it can
- sometimes make sense to set it to 0, meaning that
- the daemon just picks a free port (which one is
- returned by function <c>info/1</c>).</p>
- <p>If a socket is connected already, option
- <c>{udp, [{fd, integer()}]}</c> can be used to pass the
- open file descriptor to <c>gen_udp</c>. This can be automated
- by using a command-line argument stating the
- prebound file descriptor number. For example, if the
- port is 69 and file descriptor 22 is opened by
- <c>setuid_socket_wrap</c>, the command-line argument
- "-tftpd_69 22" triggers the prebound file
- descriptor 22 to be used instead of opening port 69.
- The UDP option <c>{udp, [{fd, 22}]}</c> is automatically added.
- See <c>init:get_argument/</c> about command-line arguments and
- <c>gen_udp:open/2</c> about UDP options.</p>
- </item>
- <tag><c>{port_policy, Policy}</c></tag>
- <item>
- <p><c>Policy = random | Port | {range, MinPort, MaxPort}</c></p>
- <p><c>Port = MinPort = MaxPort = int()</c></p>
- <p>Policy for the selection of the temporary port that is used
- by the server/client during the file transfer. Default is
- <c>random</c>, which is the standardized policy. With this
- policy a randomized free port is used. A single port or a range
- of ports can be useful if the protocol passes through a
- firewall.</p>
- </item>
- <tag><c>{udp, Options}</c></tag>
- <item>
- <p><c>Options = [Opt]</c>, see
- <seealso marker="kernel:gen_udp#open/1">gen_udp:open/2</seealso>.</p>
- </item>
- <tag><c>{use_tsize, Bool}</c></tag>
- <item>
- <p><c>Bool = bool()</c></p>
- <p>Flag for automated use of option <c>tsize</c>. With
- this set to <c>true</c>, the <c>write_file/3</c> client
- determines the filesize and sends it to the server as
- the standardized <c>tsize</c> option. A <c>read_file/3</c>
- client acquires only a filesize from the server by sending
- a zero <c>tsize</c>.</p>
- </item>
- <tag><c>{max_tsize, MaxTsize}</c></tag>
- <item>
- <p><c>MaxTsize = int() | infinity</c></p>
- <p>Threshold for the maximal filesize in bytes. The transfer
- is aborted if the limit is exceeded.
- Default is <c>infinity</c>.</p>
- </item>
- <tag><c>{max_conn, MaxConn}</c></tag>
- <item>
- <p><c>MaxConn = int() | infinity</c></p>
- <p>Threshold for the maximal number of active connections.
- The daemon rejects the setup of new connections if
- the limit is exceeded. Default is <c>infinity</c>.</p>
- </item>
- <tag><c>{TftpKey, TftpVal}</c></tag>
- <item>
- <p><c>TftpKey = string()</c> <br></br>
-<c>TftpVal = string()</c></p>
- <p>Name and value of a TFTP option.</p>
- </item>
- <tag><c>{reject, Feature}</c></tag>
- <item>
- <p><c>Feature = Mode | TftpKey</c> <br></br>
-<c>&nbsp;Mode = read | write</c> <br></br>
-<c>&nbsp;TftpKey = string()</c></p>
- <p>Controls which features to reject. This is
- mostly useful for the server as it can restrict the use
- of certain TFTP options or read/write access.</p>
- </item>
- <tag><c>{callback, {RegExp, Module, State}}</c></tag>
- <item>
- <p><c>RegExp = string()</c> <br></br>
-<c>Module = atom()</c> <br></br>
-<c>State = term()</c></p>
- <p>Registration of a callback module. When a file is to be
- transferred, its local filename is matched to the regular
- expressions of the registered callbacks. The first matching
- callback is used during the transfer. See
- <seealso marker="#read_file/3">read_file/3</seealso> and
- <seealso marker="#write_file/3">write_file/3</seealso>.
- </p>
- <p>The callback module must implement the <c>tftp</c> behavior, see
- <seealso marker="#tftp_callback">CALLBACK FUNCTIONS</seealso>.</p>
- </item>
-
- <tag><c>{logger, Module}</c></tag>
- <item>
- <p><c>Module = module()()</c></p>
-
- <p>Callback module for customized logging of errors, warnings, and
- info messages. The callback module must implement the
- <c>tftp_logger</c> behavior, see
- <seealso marker="#tftp_logger">LOGGER FUNCTIONS</seealso>.
- The default module is <c>tftp_logger</c>.</p>
- </item>
-
- <tag><c>{max_retries, MaxRetries}</c></tag>
- <item>
- <p><c>MaxRetries = int()</c></p>
-
- <p>Threshold for the maximal number of retries. By default
- the server/client tries to resend a message up to
- five times when the time-out expires.</p>
- </item>
- </taglist>
- </section>
-
- <funcs>
- <func>
- <name>change_config(daemons, Options) -> [{Pid, Result}]</name>
- <fsummary>Changes configuration for all daemons.
- </fsummary>
- <type>
- <v>Options = [option()]</v>
- <v>Pid = pid()</v>
- <v>Result = ok | {error, Reason}</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Changes configuration for all TFTP daemon processes. </p>
- </desc>
- </func>
-
- <func>
- <name>change_config(servers, Options) -> [{Pid, Result}]</name>
- <fsummary>Changes configuration for all servers.
- </fsummary>
- <type>
- <v>Options = [option()]</v>
- <v>Pid = pid()</v>
- <v>Result = ok | {error, Reason}</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Changes configuration for all TFTP server processes.</p>
- </desc>
- </func>
-
- <func>
- <name>change_config(Pid, Options) -> Result</name>
- <fsummary>Changes configuration for a TFTP daemon, server,
- or client process.</fsummary>
- <type>
- <v>Pid = pid()</v>
- <v>Options = [option()]</v>
- <v>Result = ok | {error, Reason}</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Changes configuration for a TFTP daemon, server, or client process.</p>
- </desc>
- </func>
-
- <func>
- <name>info(daemons) -> [{Pid, Options}]</name>
- <fsummary>Returns information about all daemons.</fsummary>
- <type>
- <v>Pid = [pid()()]</v>
- <v>Options = [option()]</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Returns information about all TFTP daemon processes.</p>
- </desc>
- </func>
-
- <func>
- <name>info(servers) -> [{Pid, Options}]</name>
- <fsummary>Returns information about all servers.</fsummary>
- <type>
- <v>Pid = [pid()()]</v>
- <v>Options = [option()]</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Returns information about all TFTP server processes. </p>
- </desc>
- </func>
-
- <func>
- <name>info(Pid) -> {ok, Options} | {error, Reason}</name>
- <fsummary>Returns information about a daemon, server, or client process.</fsummary>
- <type>
- <v>Options = [option()]</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Returns information about a TFTP daemon, server, or client process.</p>
- </desc>
- </func>
-
- <func>
- <name>read_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason}</name>
- <fsummary>Reads a (virtual) file from a TFTP server.</fsummary>
- <type>
- <v>RemoteFilename = string()</v>
- <v>LocalFilename = binary | string()</v>
- <v>Options = [option()]</v>
- <v>LastCallbackState = term()</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Reads a (virtual) file <c>RemoteFilename</c> from a TFTP
- server.</p>
- <p>If <c>LocalFilename</c> is the atom <c>binary</c>,
- <c>tftp_binary</c> is used as callback module. It concatenates
- all transferred blocks and returns them as one single binary
- in <c>LastCallbackState</c>.</p>
- <p>If <c>LocalFilename</c> is a string and there are no
- registered callback modules, <c>tftp_file</c> is used as
- callback module. It writes each transferred block to the file
- named <c>LocalFilename</c> and returns the number of
- transferred bytes in <c>LastCallbackState</c>.</p>
- <p>If <c>LocalFilename</c> is a string and there are registered
- callback modules, <c>LocalFilename</c> is tested against
- the regexps of these and the callback module corresponding to
- the first match is used, or an error tuple is returned if no
- matching regexp is found.</p>
- </desc>
- </func>
-
- <func>
- <name>start(Options) -> {ok, Pid} | {error, Reason}</name>
- <fsummary>Starts a daemon process.</fsummary>
- <type>
- <v>Options = [option()]</v>
- <v>Pid = pid()</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Starts a daemon process listening for UDP packets on a
- port. When it receives a request for read or write, it spawns
- a temporary server process handling the actual transfer
- of the (virtual) file.</p>
- </desc>
- </func>
-
- <func>
- <name>write_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason}</name>
- <fsummary>Writes a (virtual) file to a TFTP server.</fsummary>
- <type>
- <v>RemoteFilename = string()</v>
- <v>LocalFilename = binary() | string()</v>
- <v>Options = [option()]</v>
- <v>LastCallbackState = term()</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Writes a (virtual) file <c>RemoteFilename</c> to a TFTP
- server.</p>
- <p>If <c>LocalFilename</c> is a binary, <c>tftp_binary</c> is
- used as callback module. The binary is transferred block by
- block and the number of transferred bytes is returned in
- <c>LastCallbackState</c>.</p>
- <p>If <c>LocalFilename</c> is a string and there are no
- registered callback modules, <c>tftp_file</c> is used as
- callback module. It reads the file named <c>LocalFilename</c>
- block by block and returns the number of transferred bytes
- in <c>LastCallbackState</c>.</p>
- <p>If <c>LocalFilename</c> is a string and there are registered
- callback modules, <c>LocalFilename</c> is tested against
- the regexps of these and the callback module corresponding to
- the first match is used, or an error tuple is returned if no
- matching regexp is found.</p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <marker id="tftp_callback"></marker>
- <title>CALLBACK FUNCTIONS</title>
- <p>A <c>tftp</c> callback module is to be implemented as a
- <c>tftp</c> behavior and export the functions listed
- in the following.</p>
- <p>On the server side, the callback interaction starts with a call to
- <c>open/5</c> with the registered initial callback state.
- <c>open/5</c> is expected to open the (virtual) file. Then either
- function <c>read/1</c> or <c>write/2</c> is invoked
- repeatedly, once per transferred block. At each function call,
- the state returned from the previous call is obtained. When
- the last block is encountered, function <c>read/1</c> or
- <c>write/2</c> is expected to close the (virtual) file
- and return its last state. Function <c>abort/3</c> is only
- used in error situations. Function <c>prepare/5</c> is not used on
- the server side.</p>
- <p>On the client side, the callback interaction is the same, but it
- starts and ends a bit differently. It starts with a call to
- <c>prepare/5</c> with the same arguments as <c>open/5</c> takes.
- <c>prepare/5</c> is expected to validate the TFTP options
- suggested by the user and to return the subset of them that it
- accepts. Then the options are sent to the server, which performs
- the same TFTP option negotiation procedure. The options that are
- accepted by the server are forwarded to function <c>open/5</c>
- on the client side. On the client side, function <c>open/5</c>
- must accept all option as-is or reject the transfer. Then
- the callback interaction follows the same pattern as described
- for the server side. When the last block is encountered in
- <c>read/1</c> or <c>write/2</c>, the returned state is forwarded to
- the user and returned from <c>read_file</c>/3 or
- <c>write_file/3</c>.</p>
-
- <p> If a callback (performing the file access
- in the TFTP server) takes too long time (more than
- the double TFTP time-out), the server aborts the
- connection and sends an error reply to the client.
- This implies that the server releases resources
- attached to the connection faster than before. The
- server simply assumes that the client has given
- up.</p>
-
- <p>If the TFTP server receives yet another request from
- the same client (same host and port) while it
- already has an active connection to the client, it
- ignores the new request if the request is
- equal to the first one (same filename and options).
- This implies that the (new) client will be served
- by the already ongoing connection on the server
- side. By not setting up yet another connection, in
- parallel with the ongoing one, the server
- consumes less resources.</p>
-
- <marker id="prepare"></marker>
- </section>
-
- <funcs>
- <func>
- <name>Module:abort(Code, Text, State) -> ok</name>
- <fsummary>Aborts the file transfer.</fsummary>
- <type>
- <v>Code = undef | enoent | eacces | enospc</v>
- <v>&nbsp;&nbsp;| badop | eexist | baduser | badopt</v>
- <v>&nbsp;&nbsp;| int()</v>
- <v>Text = string()</v>
- <v>State = term()</v>
- </type>
- <desc>
- <p>Invoked when the file transfer is aborted.</p>
- <p>The callback function is expected to clean
- up its used resources after the aborted file
- transfer, such as closing open file
- descriptors and so on. The function is not
- invoked if any of the other callback
- functions returns an error, as it is
- expected that they already have cleaned up
- the necessary resources. However, it is
- invoked if the functions fail (crash).</p>
- </desc>
- </func>
-
- <func>
- <name>Module:open(Peer, Access, Filename, Mode, SuggestedOptions, State) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}}</name>
- <fsummary>Opens a file for read or write access.</fsummary>
- <type>
- <v>Peer = {PeerType, PeerHost, PeerPort}</v>
- <v>PeerType = inet | inet6</v>
- <v>PeerHost = ip_address()</v>
- <v>PeerPort = integer()</v>
- <v>Access = read | write</v>
- <v>Filename = string()</v>
- <v>Mode = string()</v>
- <v>SuggestedOptions = AcceptedOptions = [{Key, Value}]</v>
- <v>&nbsp;Key = Value = string()</v>
- <v>State = InitialState | term()</v>
- <v>&nbsp;InitialState = [] | [{root_dir, string()}]</v>
- <v>NewState = term()</v>
- <v>Code = undef | enoent | eacces | enospc</v>
- <v>&nbsp;&nbsp;| badop | eexist | baduser | badopt</v>
- <v>&nbsp;&nbsp;| int()</v>
- <v>Text = string()</v>
- </type>
- <desc>
- <p>Opens a file for read or write access.</p>
- <p>On the client side, where the <c>open/5</c> call has been
- preceded by a call to <c>prepare/5</c>, all options must be
- accepted or rejected.</p>
- <p>On the server side, where there is no preceding
- <c>prepare/5</c> call, no new options can be added, but
- those present in <c>SuggestedOptions</c> can be
- omitted or replaced with new values in <c>AcceptedOptions</c>.</p>
-
- <marker id="read"></marker>
- </desc>
- </func>
-
- <func>
- <name>Module:prepare(Peer, Access, Filename, Mode, SuggestedOptions, InitialState) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}}</name>
- <fsummary>Prepares to open a file on the client side.</fsummary>
- <type>
- <v>Peer = {PeerType, PeerHost, PeerPort}</v>
- <v>PeerType = inet | inet6</v>
- <v>PeerHost = ip_address()</v>
- <v>PeerPort = integer()</v>
- <v>Access = read | write</v>
- <v>Filename = string()</v>
- <v>Mode = string()</v>
- <v>SuggestedOptions = AcceptedOptions = [{Key, Value}]</v>
- <v>&nbsp;Key = Value = string()</v>
- <v>InitialState = [] | [{root_dir, string()}]</v>
- <v>NewState = term()</v>
- <v>Code = undef | enoent | eacces | enospc</v>
- <v>&nbsp;&nbsp;| badop | eexist | baduser | badopt</v>
- <v>&nbsp;&nbsp;| int()</v>
- <v>Text = string()</v>
- </type>
- <desc>
- <p>Prepares to open a file on the client side.</p>
- <p>No new options can be added, but those present in
- <c>SuggestedOptions</c> can be omitted or replaced with new
- values in <c>AcceptedOptions</c>.</p>
- <p>This is followed by a call to <c>open/4</c> before any
- read/write access is performed. <c>AcceptedOptions</c> is
- sent to the server, which replies with the options that it
- accepts. These are then forwarded to <c>open/4</c> as
- <c>SuggestedOptions</c>.</p>
-
- <marker id="open"></marker>
- </desc>
- </func>
-
- <func>
- <name>Module:read(State) -> {more, Bin, NewState} | {last, Bin, FileSize} | {error, {Code, Text}}</name>
- <fsummary>Reads a chunk from the file.</fsummary>
- <type>
- <v>State = NewState = term()</v>
- <v>Bin = binary()</v>
- <v>FileSize = int()</v>
- <v>Code = undef | enoent | eacces | enospc</v>
- <v>&nbsp;&nbsp;| badop | eexist | baduser | badopt</v>
- <v>&nbsp;&nbsp;| int()</v>
- <v>Text = string()</v>
- </type>
- <desc>
- <p>Reads a chunk from the file.</p>
- <p>The callback function is expected to close
- the file when the last file chunk is
- encountered. When an error is encountered,
- the callback function is expected to clean
- up after the aborted file transfer, such as
- closing open file descriptors, and so on. In both
- cases there will be no more calls to any of
- the callback functions.</p>
-
- <marker id="write"></marker>
- </desc>
- </func>
-
- <func>
- <name>Module:write(Bin, State) -> {more, NewState} | {last, FileSize} | {error, {Code, Text}}</name>
- <fsummary>Writes a chunk to the file.</fsummary>
- <type>
- <v>Bin = binary()</v>
- <v>State = NewState = term()</v>
- <v>FileSize = int()</v>
- <v>Code = undef | enoent | eacces | enospc</v>
- <v>&nbsp;&nbsp;| badop | eexist | baduser | badopt</v>
- <v>&nbsp;&nbsp;| int()</v>
- <v>Text = string()</v>
- </type>
- <desc>
- <p>Writes a chunk to the file.</p>
- <p>The callback function is expected to close
- the file when the last file chunk is
- encountered. When an error is encountered,
- the callback function is expected to clean
- up after the aborted file transfer, such as
- closing open file descriptors, and so on. In both
- cases there will be no more calls to any of
- the callback functions.</p>
-
- <marker id="abort"></marker>
- </desc>
- </func>
- </funcs>
-
- <section>
- <marker id="tftp_logger"></marker>
- <title>LOGGER FUNCTIONS</title>
-
- <p>A <c>tftp_logger</c> callback module is to be implemented as a
- <c>tftp_logger</c> behavior and export the following functions:</p>
-
- <marker id="error_msg"></marker>
- </section>
-
- <funcs>
- <func>
- <name>Logger:error_msg(Format, Data) -> ok | exit(Reason)</name>
- <fsummary>Logs an error message.</fsummary>
- <type>
- <v>Format = string()</v>
- <v>Data = [term()]</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Logs an error message.
- See <c>error_logger:error_msg/2</c> for details.</p>
-
- <marker id="warning_msg"></marker>
- </desc>
- </func>
-
- <func>
- <name>Logger:info_msg(Format, Data) -> ok | exit(Reason)</name>
- <fsummary>Logs an info message.</fsummary>
- <type>
- <v>Format = string()</v>
- <v>Data = [term()]</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Logs an info message.
- See <c>error_logger:info_msg/2</c> for details.</p>
- </desc>
- </func>
-
- <func>
- <name>Logger:warning_msg(Format, Data) -> ok | exit(Reason)</name>
- <fsummary>Logs a warning message.</fsummary>
- <type>
- <v>Format = string()</v>
- <v>Data = [term()]</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Logs a warning message.
- See <c>error_logger:warning_msg/2</c> for details.</p>
-
- <marker id="info_msg"></marker>
- </desc>
- </func>
- </funcs>
-</erlref>
-
-
diff --git a/lib/inets/doc/src/user_guide.gif b/lib/inets/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/inets/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/doc/src/warning.gif b/lib/inets/doc/src/warning.gif
deleted file mode 100644
index 96af52360e..0000000000
--- a/lib/inets/doc/src/warning.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/src/ftp/Makefile b/lib/inets/src/ftp/Makefile
deleted file mode 100644
index 6b99694ea7..0000000000
--- a/lib/inets/src/ftp/Makefile
+++ /dev/null
@@ -1,104 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2005-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-
-include $(ERL_TOP)/make/target.mk
-EBIN = ../../ebin
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-
-VSN = $(INETS_VSN)
-
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
-
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-MODULES = \
- ftp \
- ftp_progress \
- ftp_response \
- ftp_sup
-
-HRL_FILES = ftp_internal.hrl
-
-ERL_FILES = $(MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-
-include ../inets_app/inets.mk
-
-ifeq ($(FTP_DEBUG),true)
- INETS_FLAGS += -Dftp_debug
-endif
-
-ERL_COMPILE_FLAGS += \
- $(INETS_FLAGS) \
- $(INETS_ERL_COMPILE_FLAGS) \
- -I../../include \
- -I../inets_app
-
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt: $(TARGET_FILES)
-
-clean:
- rm -f $(TARGET_FILES)
- rm -f core
-
-docs:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/src"
- $(INSTALL_DIR) "$(RELSYSDIR)/src/ftp"
- $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) "$(RELSYSDIR)/src/ftp"
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
-
-release_docs_spec:
-
-info:
- @echo "APPLICATION = $(APPLICATION)"
- @echo "INETS_DEBUG = $(INETS_DEBUG)"
- @echo "INETS_FLAGS = $(INETS_FLAGS)"
- @echo "ERL_COMPILE_FLAGS = $(ERL_COMPILE_FLAGS)"
diff --git a/lib/inets/src/ftp/ftp.erl b/lib/inets/src/ftp/ftp.erl
deleted file mode 100644
index e0430654eb..0000000000
--- a/lib/inets/src/ftp/ftp.erl
+++ /dev/null
@@ -1,2596 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%% Description: This module implements an ftp client, RFC 959.
-%% It also supports ipv6 RFC 2428 and starttls RFC 4217.
-
--module(ftp).
-
--behaviour(gen_server).
--behaviour(inets_service).
-
-
-%% API - Client interface
--export([cd/2, close/1, delete/2, formaterror/1,
- lcd/2, lpwd/1, ls/1, ls/2,
- mkdir/2, nlist/1, nlist/2,
- open/1, open/2,
- pwd/1, quote/2,
- recv/2, recv/3, recv_bin/2,
- recv_chunk_start/2, recv_chunk/1,
- rename/3, rmdir/2,
- send/2, send/3, send_bin/3,
- send_chunk_start/2, send_chunk/2, send_chunk_end/1,
- type/2, user/3, user/4, account/2,
- append/3, append/2, append_bin/3,
- append_chunk/2, append_chunk_end/1, append_chunk_start/2,
- info/1, latest_ctrl_response/1]).
-
-%% gen_server callbacks
--export([init/1, handle_call/3, handle_cast/2,
- handle_info/2, terminate/2, code_change/3]).
-
-%% supervisor callbacks
--export([start_link/1, start_link/2]).
-
-%% Behavior callbacks
--export([start_standalone/1, start_service/1,
- stop_service/1, services/0, service_info/1]).
-
--include("ftp_internal.hrl").
-
-%% Constants used in internal state definition
--define(CONNECTION_TIMEOUT, 60*1000).
--define(DATA_ACCEPT_TIMEOUT, infinity).
--define(DEFAULT_MODE, passive).
--define(PROGRESS_DEFAULT, ignore).
--define(FTP_EXT_DEFAULT, false).
-
-%% Internal Constants
--define(FTP_PORT, 21).
--define(FILE_BUFSIZE, 4096).
-
-%% Internal state
--record(state, {
- csock = undefined, % socket() - Control connection socket
- dsock = undefined, % socket() - Data connection socket
- tls_options = undefined, % list()
- verbose = false, % boolean()
- ldir = undefined, % string() - Current local directory
- type = ftp_server_default, % atom() - binary | ascii
- chunk = false, % boolean() - Receiving data chunks
- mode = ?DEFAULT_MODE, % passive | active
- timeout = ?CONNECTION_TIMEOUT, % integer()
- %% Data received so far on the data connection
- data = <<>>, % binary()
- %% Data received so far on the control connection
- %% {BinStream, AccLines}. If a binary sequence
- %% ends with ?CR then keep it in the binary to
- %% be able to detect if the next received byte is ?LF
- %% and hence the end of the response is reached!
- ctrl_data = {<<>>, [], start}, % {binary(), [bytes()], LineStatus}
- %% pid() - Client pid (note not the same as "From")
- latest_ctrl_response = "",
- owner = undefined,
- client = undefined, % "From" to be used in gen_server:reply/2
- %% Function that activated a connection and maybe some
- %% data needed further on.
- caller = undefined, % term()
- ipfamily, % inet | inet6 | inet6fb4
- progress = ignore, % ignore | pid()
- dtimeout = ?DATA_ACCEPT_TIMEOUT, % non_neg_integer() | infinity
- tls_upgrading_data_connection = false,
- ftp_extension = ?FTP_EXT_DEFAULT
- }).
-
--record(recv_chunk_closing, {
- dconn_closed = false,
- pos_compl_received = false,
- client_called_us = false
- }).
-
-
--type shortage_reason() :: 'etnospc' | 'epnospc'.
--type restriction_reason() :: 'epath' | 'efnamena' | 'elogin' | 'enotbinary'.
--type common_reason() :: 'econn' | 'eclosed' | term().
--type file_write_error_reason() :: term(). % See file:write for more info
-
--define(DBG(F,A), 'n/a').
-%%-define(DBG(F,A), io:format(F,A)).
-%%-define(DBG(F,A), ct:pal("~p:~p " ++ if is_list(F) -> F; is_atom(F) -> atom_to_list(F) end, [?MODULE,?LINE|A])).
-
-%%%=========================================================================
-%%% API - CLIENT FUNCTIONS
-%%%=========================================================================
-
-%%--------------------------------------------------------------------------
-%% open(HostOrOtpList, <Port>, <Flags>) -> {ok, Pid} | {error, ehost}
-%% HostOrOtpList = string() | [{option_list, Options}]
-%% Port = integer(),
-%% Flags = [Flag],
-%% Flag = verbose | debug | trace
-%%
-%% Description: Start an ftp client and connect to a host.
-%%--------------------------------------------------------------------------
-
--spec open(Host :: string() | inet:ip_address()) ->
- {'ok', Pid :: pid()} | {'error', Reason :: 'ehost' | term()}.
-
-%% <BACKWARD-COMPATIBILLITY>
-open({option_list, Options}) when is_list(Options) ->
- try
- {ok, StartOptions} = start_options(Options),
- {ok, OpenOptions} = open_options(Options),
- case ftp_sup:start_child([[[{client, self()} | StartOptions], []]]) of
- {ok, Pid} ->
- call(Pid, {open, ip_comm, OpenOptions}, plain);
- Error1 ->
- Error1
- end
- catch
- throw:Error2 ->
- Error2
- end;
-%% </BACKWARD-COMPATIBILLITY>
-
-open(Host) ->
- open(Host, []).
-
--spec open(Host :: string() | inet:ip_address(), Opts :: list()) ->
- {'ok', Pid :: pid()} | {'error', Reason :: 'ehost' | term()}.
-
-%% <BACKWARD-COMPATIBILLITY>
-open(Host, Port) when is_integer(Port) ->
- open(Host, [{port, Port}]);
-%% </BACKWARD-COMPATIBILLITY>
-
-open(Host, Opts) when is_list(Opts) ->
- ?fcrt("open", [{host, Host}, {opts, Opts}]),
- try
- {ok, StartOptions} = start_options(Opts),
- ?fcrt("open", [{start_options, StartOptions}]),
- {ok, OpenOptions} = open_options([{host, Host}|Opts]),
- ?fcrt("open", [{open_options, OpenOptions}]),
- case start_link(StartOptions, []) of
- {ok, Pid} ->
- do_open(Pid, OpenOptions, tls_options(Opts));
- Error1 ->
- ?fcrt("open - error", [{error1, Error1}]),
- Error1
- end
- catch
- throw:Error2 ->
- ?fcrt("open - error", [{error2, Error2}]),
- Error2
- end.
-
-do_open(Pid, OpenOptions, TLSOpts) ->
- case call(Pid, {open, ip_comm, OpenOptions}, plain) of
- {ok, Pid} ->
- maybe_tls_upgrade(Pid, TLSOpts);
- Error ->
- Error
- end.
-%%--------------------------------------------------------------------------
-%% user(Pid, User, Pass, <Acc>) -> ok | {error, euser} | {error, econn}
-%% | {error, eacct}
-%% Pid = pid(),
-%% User = Pass = Acc = string()
-%%
-%% Description: Login with or without a supplied account name.
-%%--------------------------------------------------------------------------
--spec user(Pid :: pid(),
- User :: string(),
- Pass :: string()) ->
- 'ok' | {'error', Reason :: 'euser' | common_reason()}.
-
-user(Pid, User, Pass) ->
- case {is_name_sane(User), is_name_sane(Pass)} of
- {true, true} ->
- call(Pid, {user, User, Pass}, atom);
- _ ->
- {error, euser}
- end.
-
--spec user(Pid :: pid(),
- User :: string(),
- Pass :: string(),
- Acc :: string()) ->
- 'ok' | {'error', Reason :: 'euser' | common_reason()}.
-
-user(Pid, User, Pass, Acc) ->
- case {is_name_sane(User), is_name_sane(Pass), is_name_sane(Acc)} of
- {true, true, true} ->
- call(Pid, {user, User, Pass, Acc}, atom);
- _ ->
- {error, euser}
- end.
-
-
-%%--------------------------------------------------------------------------
-%% account(Pid, Acc) -> ok | {error, eacct}
-%% Pid = pid()
-%% Acc= string()
-%%
-%% Description: Set a user Account.
-%%--------------------------------------------------------------------------
-
--spec account(Pid :: pid(), Acc :: string()) ->
- 'ok' | {'error', Reason :: 'eacct' | common_reason()}.
-
-account(Pid, Acc) ->
- case is_name_sane(Acc) of
- true ->
- call(Pid, {account, Acc}, atom);
- _ ->
- {error, eacct}
- end.
-
-
-%%--------------------------------------------------------------------------
-%% pwd(Pid) -> {ok, Dir} | {error, elogin} | {error, econn}
-%% Pid = pid()
-%% Dir = string()
-%%
-%% Description: Get the current working directory at remote server.
-%%--------------------------------------------------------------------------
-
--spec pwd(Pid :: pid()) ->
- {'ok', Dir :: string()} |
- {'error', Reason :: restriction_reason() | common_reason()}.
-
-pwd(Pid) ->
- call(Pid, pwd, ctrl).
-
-
-%%--------------------------------------------------------------------------
-%% lpwd(Pid) -> {ok, Dir}
-%% Pid = pid()
-%% Dir = string()
-%%
-%% Description: Get the current working directory at local server.
-%%--------------------------------------------------------------------------
-
--spec lpwd(Pid :: pid()) ->
- {'ok', Dir :: string()}.
-
-lpwd(Pid) ->
- call(Pid, lpwd, string).
-
-
-%%--------------------------------------------------------------------------
-%% cd(Pid, Dir) -> ok | {error, epath} | {error, elogin} | {error, econn}
-%% Pid = pid()
-%% Dir = string()
-%%
-%% Description: Change current working directory at remote server.
-%%--------------------------------------------------------------------------
-
--spec cd(Pid :: pid(), Dir :: string()) ->
- 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
-
-cd(Pid, Dir) ->
- case is_name_sane(Dir) of
- true ->
- call(Pid, {cd, Dir}, atom);
- _ ->
- {error, efnamena}
- end.
-
-
-%%--------------------------------------------------------------------------
-%% lcd(Pid, Dir) -> ok | {error, epath}
-%% Pid = pid()
-%% Dir = string()
-%%
-%% Description: Change current working directory for the local client.
-%%--------------------------------------------------------------------------
-
--spec lcd(Pid :: pid(), Dir :: string()) ->
- 'ok' | {'error', Reason :: restriction_reason()}.
-
-lcd(Pid, Dir) ->
- call(Pid, {lcd, Dir}, string).
-
-
-%%--------------------------------------------------------------------------
-%% ls(Pid) -> Result
-%% ls(Pid, <Dir>) -> Result
-%%
-%% Pid = pid()
-%% Dir = string()
-%% Result = {ok, Listing} | {error, Reason}
-%% Listing = string()
-%% Reason = epath | elogin | econn
-%%
-%% Description: Returns a list of files in long format.
-%%--------------------------------------------------------------------------
-
--spec ls(Pid :: pid()) ->
- {'ok', Listing :: string()} |
- {'error', Reason :: restriction_reason() | common_reason()}.
-
-ls(Pid) ->
- ls(Pid, "").
-
--spec ls(Pid :: pid(), Dir :: string()) ->
- {'ok', Listing :: string()} |
- {'error', Reason :: restriction_reason() | common_reason()}.
-
-ls(Pid, Dir) ->
- case is_name_sane(Dir) of
- true ->
- call(Pid, {dir, long, Dir}, string);
- _ ->
- {error, efnamena}
- end.
-
-
-%%--------------------------------------------------------------------------
-%% nlist(Pid) -> Result
-%% nlist(Pid, Pathname) -> Result
-%%
-%% Pid = pid()
-%% Pathname = string()
-%% Result = {ok, Listing} | {error, Reason}
-%% Listing = string()
-%% Reason = epath | elogin | econn
-%%
-%% Description: Returns a list of files in short format
-%%--------------------------------------------------------------------------
-
--spec nlist(Pid :: pid()) ->
- {'ok', Listing :: string()} |
- {'error', Reason :: restriction_reason() | common_reason()}.
-
-nlist(Pid) ->
- nlist(Pid, "").
-
--spec nlist(Pid :: pid(), Pathname :: string()) ->
- {'ok', Listing :: string()} |
- {'error', Reason :: restriction_reason() | common_reason()}.
-
-nlist(Pid, Dir) ->
- case is_name_sane(Dir) of
- true ->
- call(Pid, {dir, short, Dir}, string);
- _ ->
- {error, efnamena}
- end.
-
-
-%%--------------------------------------------------------------------------
-%% rename(Pid, Old, New) -> ok | {error, epath} | {error, elogin}
-%% | {error, econn}
-%% Pid = pid()
-%% CurrFile = NewFile = string()
-%%
-%% Description: Rename a file at remote server.
-%%--------------------------------------------------------------------------
-
--spec rename(Pid :: pid(), Old :: string(), New :: string()) ->
- 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
-
-rename(Pid, Old, New) ->
- case {is_name_sane(Old), is_name_sane(New)} of
- {true, true} ->
- call(Pid, {rename, Old, New}, string);
- _ ->
- {error, efnamena}
- end.
-
-
-%%--------------------------------------------------------------------------
-%% delete(Pid, File) -> ok | {error, epath} | {error, elogin} |
-%% {error, econn}
-%% Pid = pid()
-%% File = string()
-%%
-%% Description: Remove file at remote server.
-%%--------------------------------------------------------------------------
-
--spec delete(Pid :: pid(), File :: string()) ->
- 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
-
-delete(Pid, File) ->
- case is_name_sane(File) of
- true ->
- call(Pid, {delete, File}, string);
- _ ->
- {error, efnamena}
- end.
-
-
-%%--------------------------------------------------------------------------
-%% mkdir(Pid, Dir) -> ok | {error, epath} | {error, elogin} | {error, econn}
-%% Pid = pid(),
-%% Dir = string()
-%%
-%% Description: Make directory at remote server.
-%%--------------------------------------------------------------------------
-
--spec mkdir(Pid :: pid(), Dir :: string()) ->
- 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
-
-mkdir(Pid, Dir) ->
- case is_name_sane(Dir) of
- true ->
- call(Pid, {mkdir, Dir}, atom);
- _ ->
- {error, efnamena}
- end.
-
-
-%%--------------------------------------------------------------------------
-%% rmdir(Pid, Dir) -> ok | {error, epath} | {error, elogin} | {error, econn}
-%% Pid = pid(),
-%% Dir = string()
-%%
-%% Description: Remove directory at remote server.
-%%--------------------------------------------------------------------------
-
--spec rmdir(Pid :: pid(), Dir :: string()) ->
- 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
-
-rmdir(Pid, Dir) ->
- case is_name_sane(Dir) of
- true ->
- call(Pid, {rmdir, Dir}, atom);
- _ ->
- {error, efnamena}
- end.
-
-
-%%--------------------------------------------------------------------------
-%% type(Pid, Type) -> ok | {error, etype} | {error, elogin} | {error, econn}
-%% Pid = pid()
-%% Type = ascii | binary
-%%
-%% Description: Set transfer type.
-%%--------------------------------------------------------------------------
-
--spec type(Pid :: pid(), Type :: ascii | binary) ->
- 'ok' |
- {'error', Reason :: 'etype' | restriction_reason() | common_reason()}.
-
-type(Pid, Type) ->
- call(Pid, {type, Type}, atom).
-
-
-%%--------------------------------------------------------------------------
-%% recv(Pid, RemoteFileName [, LocalFileName]) -> ok | {error, epath} |
-%% {error, elogin} | {error, econn}
-%% Pid = pid()
-%% RemoteFileName = LocalFileName = string()
-%%
-%% Description: Transfer file from remote server.
-%%--------------------------------------------------------------------------
-
--spec recv(Pid :: pid(), RemoteFileName :: string()) ->
- 'ok' | {'error', Reason :: restriction_reason() |
- common_reason() |
- file_write_error_reason()}.
-
-recv(Pid, RemotFileName) ->
- recv(Pid, RemotFileName, RemotFileName).
-
--spec recv(Pid :: pid(),
- RemoteFileName :: string(),
- LocalFileName :: string()) ->
- 'ok' | {'error', Reason :: term()}.
-
-recv(Pid, RemotFileName, LocalFileName) ->
- case is_name_sane(RemotFileName) of
- true ->
- call(Pid, {recv, RemotFileName, LocalFileName}, atom);
- _ ->
- {error, efnamena}
- end.
-
-
-%%--------------------------------------------------------------------------
-%% recv_bin(Pid, RemoteFile) -> {ok, Bin} | {error, epath} | {error, elogin}
-%% | {error, econn}
-%% Pid = pid()
-%% RemoteFile = string()
-%% Bin = binary()
-%%
-%% Description: Transfer file from remote server into binary.
-%%--------------------------------------------------------------------------
-
--spec recv_bin(Pid :: pid(),
- RemoteFile :: string()) ->
- {'ok', Bin :: binary()} |
- {'error', Reason :: restriction_reason() | common_reason()}.
-
-recv_bin(Pid, RemoteFile) ->
- case is_name_sane(RemoteFile) of
- true ->
- call(Pid, {recv_bin, RemoteFile}, bin);
- _ ->
- {error, efnamena}
- end.
-
-
-%%--------------------------------------------------------------------------
-%% recv_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} | {error, epath}
-%% | {error, econn}
-%% Pid = pid()
-%% RemoteFile = string()
-%%
-%% Description: Start receive of chunks of remote file.
-%%--------------------------------------------------------------------------
-
--spec recv_chunk_start(Pid :: pid(),
- RemoteFile :: string()) ->
- 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
-
-recv_chunk_start(Pid, RemoteFile) ->
- case is_name_sane(RemoteFile) of
- true ->
- call(Pid, {recv_chunk_start, RemoteFile}, atom);
- _ ->
- {error, efnamena}
- end.
-
-
-%%--------------------------------------------------------------------------
-%% recv_chunk(Pid, RemoteFile) -> ok | {ok, Bin} | {error, Reason}
-%% Pid = pid()
-%% RemoteFile = string()
-%%
-%% Description: Transfer file from remote server into binary in chunks
-%%--------------------------------------------------------------------------
-
--spec recv_chunk(Pid :: pid()) ->
- 'ok' |
- {'ok', Bin :: binary()} |
- {'error', Reason :: restriction_reason() | common_reason()}.
-
-recv_chunk(Pid) ->
- call(Pid, recv_chunk, atom).
-
-
-%%--------------------------------------------------------------------------
-%% send(Pid, LocalFileName [, RemotFileName]) -> ok | {error, epath}
-%% | {error, elogin}
-%% | {error, econn}
-%% Pid = pid()
-%% LocalFileName = RemotFileName = string()
-%%
-%% Description: Transfer file to remote server.
-%%--------------------------------------------------------------------------
-
--spec send(Pid :: pid(), LocalFileName :: string()) ->
- 'ok' |
- {'error', Reason :: restriction_reason() |
- common_reason() |
- shortage_reason()}.
-
-send(Pid, LocalFileName) ->
- send(Pid, LocalFileName, LocalFileName).
-
--spec send(Pid :: pid(),
- LocalFileName :: string(),
- RemoteFileName :: string()) ->
- 'ok' |
- {'error', Reason :: restriction_reason() |
- common_reason() |
- shortage_reason()}.
-
-send(Pid, LocalFileName, RemotFileName) ->
- case is_name_sane(RemotFileName) of
- true ->
- call(Pid, {send, LocalFileName, RemotFileName}, atom);
- _ ->
- {error, efnamena}
- end.
-
-
-%%--------------------------------------------------------------------------
-%% send_bin(Pid, Bin, RemoteFile) -> ok | {error, epath} | {error, elogin}
-%% | {error, enotbinary} | {error, econn}
-%% Pid = pid()
-%% Bin = binary()
-%% RemoteFile = string()
-%%
-%% Description: Transfer a binary to a remote file.
-%%--------------------------------------------------------------------------
-
--spec send_bin(Pid :: pid(), Bin :: binary(), RemoteFile :: string()) ->
- 'ok' |
- {'error', Reason :: restriction_reason() |
- common_reason() |
- shortage_reason()}.
-
-send_bin(Pid, Bin, RemoteFile) when is_binary(Bin) ->
- case is_name_sane(RemoteFile) of
- true ->
- call(Pid, {send_bin, Bin, RemoteFile}, atom);
- _ ->
- {error, efnamena}
- end;
-send_bin(_Pid, _Bin, _RemoteFile) ->
- {error, enotbinary}.
-
-
-%%--------------------------------------------------------------------------
-%% send_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} | {error, epath}
-%% | {error, econn}
-%% Pid = pid()
-%% RemoteFile = string()
-%%
-%% Description: Start transfer of chunks to remote file.
-%%--------------------------------------------------------------------------
-
--spec send_chunk_start(Pid :: pid(), RemoteFile :: string()) ->
- 'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
-
-send_chunk_start(Pid, RemoteFile) ->
- case is_name_sane(RemoteFile) of
- true ->
- call(Pid, {send_chunk_start, RemoteFile}, atom);
- _ ->
- {error, efnamena}
- end.
-
-
-%%--------------------------------------------------------------------------
-%% append_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} |
-%% {error, epath} | {error, econn}
-%% Pid = pid()
-%% RemoteFile = string()
-%%
-%% Description: Start append chunks of data to remote file.
-%%--------------------------------------------------------------------------
-
--spec append_chunk_start(Pid :: pid(), RemoteFile :: string()) ->
- 'ok' | {'error', Reason :: term()}.
-
-append_chunk_start(Pid, RemoteFile) ->
- case is_name_sane(RemoteFile) of
- true ->
- call(Pid, {append_chunk_start, RemoteFile}, atom);
- _ ->
- {error, efnamena}
- end.
-
-
-%%--------------------------------------------------------------------------
-%% send_chunk(Pid, Bin) -> ok | {error, elogin} | {error, enotbinary}
-%% | {error, echunk} | {error, econn}
-%% Pid = pid()
-%% Bin = binary().
-%%
-%% Purpose: Send chunk to remote file.
-%%--------------------------------------------------------------------------
-
--spec send_chunk(Pid :: pid(), Bin :: binary()) ->
- 'ok' |
- {'error', Reason :: 'echunk' |
- restriction_reason() |
- common_reason()}.
-
-send_chunk(Pid, Bin) when is_binary(Bin) ->
- call(Pid, {transfer_chunk, Bin}, atom);
-send_chunk(_Pid, _Bin) ->
- {error, enotbinary}.
-
-
-%%--------------------------------------------------------------------------
-%% append_chunk(Pid, Bin) -> ok | {error, elogin} | {error, enotbinary}
-%% | {error, echunk} | {error, econn}
-%% Pid = pid()
-%% Bin = binary()
-%%
-%% Description: Append chunk to remote file.
-%%--------------------------------------------------------------------------
-
--spec append_chunk(Pid :: pid(), Bin :: binary()) ->
- 'ok' |
- {'error', Reason :: 'echunk' |
- restriction_reason() |
- common_reason()}.
-
-append_chunk(Pid, Bin) when is_binary(Bin) ->
- call(Pid, {transfer_chunk, Bin}, atom);
-append_chunk(_Pid, _Bin) ->
- {error, enotbinary}.
-
-
-%%--------------------------------------------------------------------------
-%% send_chunk_end(Pid) -> ok | {error, elogin} | {error, echunk}
-%% | {error, econn}
-%% Pid = pid()
-%%
-%% Description: End sending of chunks to remote file.
-%%--------------------------------------------------------------------------
-
--spec send_chunk_end(Pid :: pid()) ->
- 'ok' |
- {'error', Reason :: restriction_reason() |
- common_reason() |
- shortage_reason()}.
-
-send_chunk_end(Pid) ->
- call(Pid, chunk_end, atom).
-
-
-%%--------------------------------------------------------------------------
-%% append_chunk_end(Pid) -> ok | {error, elogin} | {error, echunk}
-%% | {error, econn}
-%% Pid = pid()
-%%
-%% Description: End appending of chunks to remote file.
-%%--------------------------------------------------------------------------
-
--spec append_chunk_end(Pid :: pid()) ->
- 'ok' |
- {'error', Reason :: restriction_reason() |
- common_reason() |
- shortage_reason()}.
-
-append_chunk_end(Pid) ->
- call(Pid, chunk_end, atom).
-
-
-%%--------------------------------------------------------------------------
-%% append(Pid, LocalFileName [, RemotFileName]) -> ok | {error, epath}
-%% | {error, elogin}
-%% | {error, econn}
-%% Pid = pid()
-%% LocalFileName = RemotFileName = string()
-%%
-%% Description: Append the local file to the remote file
-%%--------------------------------------------------------------------------
-
--spec append(Pid :: pid(), LocalFileName :: string()) ->
- 'ok' |
- {'error', Reason :: 'epath' |
- 'elogin' |
- 'etnospc' |
- 'epnospc' |
- 'efnamena' | common_reason()}.
-
-append(Pid, LocalFileName) ->
- append(Pid, LocalFileName, LocalFileName).
-
--spec append(Pid :: pid(),
- LocalFileName :: string(),
- RemoteFileName :: string()) ->
- 'ok' | {'error', Reason :: term()}.
-
-append(Pid, LocalFileName, RemotFileName) ->
- case is_name_sane(RemotFileName) of
- true ->
- call(Pid, {append, LocalFileName, RemotFileName}, atom);
- _ ->
- {error, efnamena}
- end.
-
-
-%%--------------------------------------------------------------------------
-%% append_bin(Pid, Bin, RemoteFile) -> ok | {error, epath} | {error, elogin}
-%% | {error, enotbinary} | {error, econn}
-%% Pid = pid()
-%% Bin = binary()
-%% RemoteFile = string()
-%%
-%% Purpose: Append a binary to a remote file.
-%%--------------------------------------------------------------------------
-
--spec append_bin(Pid :: pid(),
- Bin :: binary(),
- RemoteFile :: string()) ->
- 'ok' |
- {'error', Reason :: restriction_reason() |
- common_reason() |
- shortage_reason()}.
-
-append_bin(Pid, Bin, RemoteFile) when is_binary(Bin) ->
- case is_name_sane(RemoteFile) of
- true ->
- call(Pid, {append_bin, Bin, RemoteFile}, atom);
- _ ->
- {error, efnamena}
- end;
-append_bin(_Pid, _Bin, _RemoteFile) ->
- {error, enotbinary}.
-
-
-%%--------------------------------------------------------------------------
-%% quote(Pid, Cmd) -> list()
-%% Pid = pid()
-%% Cmd = string()
-%%
-%% Description: Send arbitrary ftp command.
-%%--------------------------------------------------------------------------
-
--spec quote(Pid :: pid(), Cmd :: string()) -> list().
-
-quote(Pid, Cmd) when is_list(Cmd) ->
- call(Pid, {quote, Cmd}, atom).
-
-
-%%--------------------------------------------------------------------------
-%% close(Pid) -> ok
-%% Pid = pid()
-%%
-%% Description: End the ftp session.
-%%--------------------------------------------------------------------------
-
--spec close(Pid :: pid()) -> 'ok'.
-
-close(Pid) ->
- cast(Pid, close),
- ok.
-
-
-%%--------------------------------------------------------------------------
-%% formaterror(Tag) -> string()
-%% Tag = atom() | {error, atom()}
-%%
-%% Description: Return diagnostics.
-%%--------------------------------------------------------------------------
-
--spec formaterror(Tag :: term()) -> string().
-
-formaterror(Tag) ->
- ftp_response:error_string(Tag).
-
-
-info(Pid) ->
- call(Pid, info, list).
-
-
-%%--------------------------------------------------------------------------
-%% latest_ctrl_response(Pid) -> string()
-%% Pid = pid()
-%%
-%% Description: The latest received response from the server
-%%--------------------------------------------------------------------------
-
--spec latest_ctrl_response(Pid :: pid()) -> string().
-
-latest_ctrl_response(Pid) ->
- call(Pid, latest_ctrl_response, string).
-
-%%%========================================================================
-%%% Behavior callbacks
-%%%========================================================================
-start_standalone(Options) ->
- try
- {ok, StartOptions} = start_options(Options),
- {ok, OpenOptions} = open_options(Options),
- case start_link(StartOptions, []) of
- {ok, Pid} ->
- call(Pid, {open, ip_comm, OpenOptions}, plain);
- Error1 ->
- Error1
- end
- catch
- throw:Error2 ->
- Error2
- end.
-
-start_service(Options) ->
- try
- {ok, StartOptions} = start_options(Options),
- {ok, OpenOptions} = open_options(Options),
- case ftp_sup:start_child([[[{client, self()} | StartOptions], []]]) of
- {ok, Pid} ->
- call(Pid, {open, ip_comm, OpenOptions}, plain);
- Error1 ->
- Error1
- end
- catch
- throw:Error2 ->
- Error2
- end.
-
-stop_service(Pid) ->
- close(Pid).
-
-services() ->
- [{ftpc, Pid} || {_, Pid, _, _} <-
- supervisor:which_children(ftp_sup)].
-service_info(Pid) ->
- {ok, Info} = call(Pid, info, list),
- {ok, [proplists:lookup(mode, Info),
- proplists:lookup(local_port, Info),
- proplists:lookup(peer, Info),
- proplists:lookup(peer_port, Info)]}.
-
-
-%% This function extracts the start options from the
-%% Valid options:
-%% debug,
-%% verbose
-%% ipfamily
-%% priority
-%% flags (for backward compatibillity)
-start_options(Options) ->
- ?fcrt("start_options", [{options, Options}]),
- case lists:keysearch(flags, 1, Options) of
- {value, {flags, Flags}} ->
- Verbose = lists:member(verbose, Flags),
- IsTrace = lists:member(trace, Flags),
- IsDebug = lists:member(debug, Flags),
- DebugLevel =
- if
- (IsTrace =:= true) ->
- trace;
- IsDebug =:= true ->
- debug;
- true ->
- disable
- end,
- {ok, [{verbose, Verbose},
- {debug, DebugLevel},
- {priority, low}]};
- false ->
- ValidateVerbose =
- fun(true) -> true;
- (false) -> true;
- (_) -> false
- end,
- ValidateDebug =
- fun(trace) -> true;
- (debug) -> true;
- (disable) -> true;
- (_) -> false
- end,
- ValidatePriority =
- fun(low) -> true;
- (normal) -> true;
- (high) -> true;
- (_) -> false
- end,
- ValidOptions =
- [{verbose, ValidateVerbose, false, false},
- {debug, ValidateDebug, false, disable},
- {priority, ValidatePriority, false, low}],
- validate_options(Options, ValidOptions, [])
- end.
-
-
-%% This function extracts and validates the open options from the
-%% Valid options:
-%% mode
-%% host
-%% port
-%% timeout
-%% dtimeout
-%% progress
-%% ftp_extension
-
-open_options(Options) ->
- ?fcrt("open_options", [{options, Options}]),
- ValidateMode =
- fun(active) -> true;
- (passive) -> true;
- (_) -> false
- end,
- ValidateHost =
- fun(Host) when is_list(Host) ->
- true;
- (Host) when is_tuple(Host) andalso
- ((size(Host) =:= 4) orelse (size(Host) =:= 8)) ->
- true;
- (_) ->
- false
- end,
- ValidatePort =
- fun(Port) when is_integer(Port) andalso (Port > 0) -> true;
- (_) -> false
- end,
- ValidateIpFamily =
- fun(inet) -> true;
- (inet6) -> true;
- (inet6fb4) -> true;
- (_) -> false
- end,
- ValidateTimeout =
- fun(Timeout) when is_integer(Timeout) andalso (Timeout >= 0) -> true;
- (_) -> false
- end,
- ValidateDTimeout =
- fun(DTimeout) when is_integer(DTimeout) andalso (DTimeout >= 0) -> true;
- (infinity) -> true;
- (_) -> false
- end,
- ValidateProgress =
- fun(ignore) ->
- true;
- ({Mod, Func, _InitProgress}) when is_atom(Mod) andalso
- is_atom(Func) ->
- true;
- (_) ->
- false
- end,
- ValidateFtpExtension =
- fun(true) -> true;
- (false) -> true;
- (_) -> false
- end,
- ValidOptions =
- [{mode, ValidateMode, false, ?DEFAULT_MODE},
- {host, ValidateHost, true, ehost},
- {port, ValidatePort, false, ?FTP_PORT},
- {ipfamily, ValidateIpFamily, false, inet},
- {timeout, ValidateTimeout, false, ?CONNECTION_TIMEOUT},
- {dtimeout, ValidateDTimeout, false, ?DATA_ACCEPT_TIMEOUT},
- {progress, ValidateProgress, false, ?PROGRESS_DEFAULT},
- {ftp_extension, ValidateFtpExtension, false, ?FTP_EXT_DEFAULT}],
- validate_options(Options, ValidOptions, []).
-
-tls_options(Options) ->
- %% Options will be validated by ssl application
- proplists:get_value(tls, Options, undefined).
-
-validate_options([], [], Acc) ->
- ?fcrt("validate_options -> done", [{acc, Acc}]),
- {ok, lists:reverse(Acc)};
-validate_options([], ValidOptions, Acc) ->
- ?fcrt("validate_options -> done",
- [{valid_options, ValidOptions}, {acc, Acc}]),
- %% Check if any mandatory options are missing!
- case [{Key, Reason} || {Key, _, true, Reason} <- ValidOptions] of
- [] ->
- Defaults =
- [{Key, Default} || {Key, _, _, Default} <- ValidOptions],
- {ok, lists:reverse(Defaults ++ Acc)};
- [{_, Reason}|_Missing] ->
- throw({error, Reason})
- end;
-validate_options([{Key, Value}|Options], ValidOptions, Acc) ->
- ?fcrt("validate_options -> check",
- [{key, Key}, {value, Value}, {acc, Acc}]),
- case lists:keysearch(Key, 1, ValidOptions) of
- {value, {Key, Validate, _, Default}} ->
- case (catch Validate(Value)) of
- true ->
- ?fcrt("validate_options -> check - accept", []),
- NewValidOptions = lists:keydelete(Key, 1, ValidOptions),
- validate_options(Options, NewValidOptions,
- [{Key, Value} | Acc]);
- _ ->
- ?fcrt("validate_options -> check - reject",
- [{default, Default}]),
- NewValidOptions = lists:keydelete(Key, 1, ValidOptions),
- validate_options(Options, NewValidOptions,
- [{Key, Default} | Acc])
- end;
- false ->
- validate_options(Options, ValidOptions, Acc)
- end;
-validate_options([_|Options], ValidOptions, Acc) ->
- validate_options(Options, ValidOptions, Acc).
-
-
-
-%%%========================================================================
-%%% gen_server callback functions
-%%%========================================================================
-
-%%-------------------------------------------------------------------------
-%% init(Args) -> {ok, State} | {ok, State, Timeout} | {stop, Reason}
-%% Description: Initiates the erlang process that manages a ftp connection.
-%%-------------------------------------------------------------------------
-init(Options) ->
- process_flag(trap_exit, true),
-
- %% Keep track of the client
- {value, {client, Client}} = lists:keysearch(client, 1, Options),
- erlang:monitor(process, Client),
-
- %% Make sure inet is started
- _ = inet_db:start(),
-
- %% Where are we
- {ok, Dir} = file:get_cwd(),
-
- %% Maybe activate dbg
- case key_search(debug, Options, disable) of
- trace ->
- dbg:tracer(),
- dbg:p(all, [call]),
- {ok, _} = dbg:tpl(ftp, [{'_', [], [{return_trace}]}]),
- {ok, _} = dbg:tpl(ftp_response, [{'_', [], [{return_trace}]}]),
- {ok, _} = dbg:tpl(ftp_progress, [{'_', [], [{return_trace}]}]),
- ok;
- debug ->
- dbg:tracer(),
- dbg:p(all, [call]),
- {ok, _} = dbg:tp(ftp, [{'_', [], [{return_trace}]}]),
- {ok, _} = dbg:tp(ftp_response, [{'_', [], [{return_trace}]}]),
- {ok, _} = dbg:tp(ftp_progress, [{'_', [], [{return_trace}]}]),
- ok;
- _ ->
- %% Keep silent
- ok
- end,
-
- %% Verbose?
- Verbose = key_search(verbose, Options, false),
-
- %% IpFamily?
- IpFamily = key_search(ipfamily, Options, inet),
-
- State = #state{owner = Client,
- verbose = Verbose,
- ipfamily = IpFamily,
- ldir = Dir},
-
- %% Set process prio
- Priority = key_search(priority, Options, low),
- process_flag(priority, Priority),
-
- %% And we are done
- {ok, State}.
-
-
-%%--------------------------------------------------------------------------
-%% handle_call(Request, From, State) -> {reply, Reply, State} |
-%% {reply, Reply, State, Timeout} |
-%% {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, Reply, State} |
-%% Description: Handle incoming requests.
-%%-------------------------------------------------------------------------
-
-%% Anyone can ask this question
-handle_call({_, info}, _, #state{verbose = Verbose,
- mode = Mode,
- timeout = Timeout,
- ipfamily = IpFamily,
- csock = Socket,
- progress = Progress} = State) ->
- {ok, {_, LocalPort}} = sockname(Socket),
- {ok, {Address, Port}} = peername(Socket),
- Options = [{verbose, Verbose},
- {ipfamily, IpFamily},
- {mode, Mode},
- {peer, Address},
- {peer_port, Port},
- {local_port, LocalPort},
- {timeout, Timeout},
- {progress, Progress}],
- {reply, {ok, Options}, State};
-
-handle_call({_,latest_ctrl_response}, _, #state{latest_ctrl_response=Resp} = State) ->
- {reply, {ok,Resp}, State};
-
-%% But everything else must come from the owner
-handle_call({Pid, _}, _, #state{owner = Owner} = State) when Owner =/= Pid ->
- {reply, {error, not_connection_owner}, State};
-
-handle_call({_, {open, ip_comm, Opts}}, From, State) ->
- ?fcrd("handle_call(open)", [{opts, Opts}]),
- case key_search(host, Opts, undefined) of
- undefined ->
- {stop, normal, {error, ehost}, State};
- Host ->
- Mode = key_search(mode, Opts, ?DEFAULT_MODE),
- Port = key_search(port, Opts, ?FTP_PORT),
- Timeout = key_search(timeout, Opts, ?CONNECTION_TIMEOUT),
- DTimeout = key_search(dtimeout, Opts, ?DATA_ACCEPT_TIMEOUT),
- Progress = key_search(progress, Opts, ignore),
- IpFamily = key_search(ipfamily, Opts, inet),
- FtpExt = key_search(ftp_extension, Opts, ?FTP_EXT_DEFAULT),
-
- State2 = State#state{client = From,
- mode = Mode,
- progress = progress(Progress),
- ipfamily = IpFamily,
- dtimeout = DTimeout,
- ftp_extension = FtpExt},
-
- ?fcrd("handle_call(open) -> setup ctrl connection with",
- [{host, Host}, {port, Port}, {timeout, Timeout}]),
- case setup_ctrl_connection(Host, Port, Timeout, State2) of
- {ok, State3, WaitTimeout} ->
- ?fcrd("handle_call(open) -> ctrl connection setup done",
- [{waittimeout, WaitTimeout}]),
- {noreply, State3, WaitTimeout};
- {error, Reason} ->
- ?fcrd("handle_call(open) -> ctrl connection setup failed",
- [{reason, Reason}]),
- gen_server:reply(From, {error, ehost}),
- {stop, normal, State2#state{client = undefined}}
- end
- end;
-
-handle_call({_, {open, ip_comm, Host, Opts}}, From, State) ->
- Mode = key_search(mode, Opts, ?DEFAULT_MODE),
- Port = key_search(port, Opts, ?FTP_PORT),
- Timeout = key_search(timeout, Opts, ?CONNECTION_TIMEOUT),
- DTimeout = key_search(dtimeout, Opts, ?DATA_ACCEPT_TIMEOUT),
- Progress = key_search(progress, Opts, ignore),
- FtpExt = key_search(ftp_extension, Opts, ?FTP_EXT_DEFAULT),
-
- State2 = State#state{client = From,
- mode = Mode,
- progress = progress(Progress),
- dtimeout = DTimeout,
- ftp_extension = FtpExt},
-
- case setup_ctrl_connection(Host, Port, Timeout, State2) of
- {ok, State3, WaitTimeout} ->
- {noreply, State3, WaitTimeout};
- {error, _Reason} ->
- gen_server:reply(From, {error, ehost}),
- {stop, normal, State2#state{client = undefined}}
- end;
-
-handle_call({_, {open, tls_upgrade, TLSOptions}}, From, State) ->
- send_ctrl_message(State, mk_cmd("AUTH TLS", [])),
- activate_ctrl_connection(State),
- {noreply, State#state{client = From, caller = open, tls_options = TLSOptions}};
-
-handle_call({_, {user, User, Password}}, From,
- #state{csock = CSock} = State) when (CSock =/= undefined) ->
- handle_user(User, Password, "", State#state{client = From});
-
-handle_call({_, {user, User, Password, Acc}}, From,
- #state{csock = CSock} = State) when (CSock =/= undefined) ->
- handle_user(User, Password, Acc, State#state{client = From});
-
-handle_call({_, {account, Acc}}, From, State)->
- handle_user_account(Acc, State#state{client = From});
-
-handle_call({_, pwd}, From, #state{chunk = false} = State) ->
- send_ctrl_message(State, mk_cmd("PWD", [])),
- activate_ctrl_connection(State),
- {noreply, State#state{client = From, caller = pwd}};
-
-handle_call({_, lpwd}, From, #state{ldir = LDir} = State) ->
- {reply, {ok, LDir}, State#state{client = From}};
-
-handle_call({_, {cd, Dir}}, From, #state{chunk = false} = State) ->
- send_ctrl_message(State, mk_cmd("CWD ~s", [Dir])),
- activate_ctrl_connection(State),
- {noreply, State#state{client = From, caller = cd}};
-
-handle_call({_,{lcd, Dir}}, _From, #state{ldir = LDir0} = State) ->
- LDir = filename:absname(Dir, LDir0),
- case file:read_file_info(LDir) of %% FIX better check that LDir is a dir.
- {ok, _ } ->
- {reply, ok, State#state{ldir = LDir}};
- _ ->
- {reply, {error, epath}, State}
- end;
-
-handle_call({_, {dir, Len, Dir}}, {_Pid, _} = From,
- #state{chunk = false} = State) ->
- setup_data_connection(State#state{caller = {dir, Dir, Len},
- client = From});
-handle_call({_, {rename, CurrFile, NewFile}}, From,
- #state{chunk = false} = State) ->
- send_ctrl_message(State, mk_cmd("RNFR ~s", [CurrFile])),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = {rename, NewFile}, client = From}};
-
-handle_call({_, {delete, File}}, {_Pid, _} = From,
- #state{chunk = false} = State) ->
- send_ctrl_message(State, mk_cmd("DELE ~s", [File])),
- activate_ctrl_connection(State),
- {noreply, State#state{client = From}};
-
-handle_call({_, {mkdir, Dir}}, From, #state{chunk = false} = State) ->
- send_ctrl_message(State, mk_cmd("MKD ~s", [Dir])),
- activate_ctrl_connection(State),
- {noreply, State#state{client = From}};
-
-handle_call({_,{rmdir, Dir}}, From, #state{chunk = false} = State) ->
- send_ctrl_message(State, mk_cmd("RMD ~s", [Dir])),
- activate_ctrl_connection(State),
- {noreply, State#state{client = From}};
-
-handle_call({_,{type, Type}}, From, #state{chunk = false} = State) ->
- case Type of
- ascii ->
- send_ctrl_message(State, mk_cmd("TYPE A", [])),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = type, type = ascii,
- client = From}};
- binary ->
- send_ctrl_message(State, mk_cmd("TYPE I", [])),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = type, type = binary,
- client = From}};
- _ ->
- {reply, {error, etype}, State}
- end;
-
-handle_call({_,{recv, RemoteFile, LocalFile}}, From,
- #state{chunk = false, ldir = LocalDir} = State) ->
- progress_report({remote_file, RemoteFile}, State),
- NewLocalFile = filename:absname(LocalFile, LocalDir),
-
- case file_open(NewLocalFile, write) of
- {ok, Fd} ->
- setup_data_connection(State#state{client = From,
- caller =
- {recv_file,
- RemoteFile, Fd}});
- {error, _What} ->
- {reply, {error, epath}, State}
- end;
-
-handle_call({_, {recv_bin, RemoteFile}}, From, #state{chunk = false} =
- State) ->
- setup_data_connection(State#state{caller = {recv_bin, RemoteFile},
- client = From});
-
-handle_call({_,{recv_chunk_start, RemoteFile}}, From, #state{chunk = false}
- = State) ->
- setup_data_connection(State#state{caller = {start_chunk_transfer,
- "RETR", RemoteFile},
- client = From});
-
-handle_call({_, recv_chunk}, _, #state{chunk = false} = State) ->
- {reply, {error, "ftp:recv_chunk_start/2 not called"}, State};
-
-handle_call({_, recv_chunk}, _From, #state{chunk = true,
- caller = #recv_chunk_closing{dconn_closed = true,
- pos_compl_received = true
- }
- } = State0) ->
- %% The ftp:recv_chunk call was the last event we waited for, finnish and clean up
- ?DBG("recv_chunk_closing ftp:recv_chunk, last event",[]),
- activate_ctrl_connection(State0),
- {reply, ok, State0#state{caller = undefined,
- chunk = false,
- client = undefined}};
-
-handle_call({_, recv_chunk}, From, #state{chunk = true,
- caller = #recv_chunk_closing{} = R
- } = State) ->
- %% Waiting for more, don't care what
- ?DBG("recv_chunk_closing ftp:recv_chunk, get more",[]),
- {noreply, State#state{client = From, caller = R#recv_chunk_closing{client_called_us=true}}};
-
-handle_call({_, recv_chunk}, From, #state{chunk = true} = State0) ->
- State = activate_data_connection(State0),
- {noreply, State#state{client = From, caller = recv_chunk}};
-
-handle_call({_, {send, LocalFile, RemoteFile}}, From,
- #state{chunk = false, ldir = LocalDir} = State) ->
- progress_report({local_file, filename:absname(LocalFile, LocalDir)},
- State),
- setup_data_connection(State#state{caller = {transfer_file,
- {"STOR",
- LocalFile, RemoteFile}},
- client = From});
-handle_call({_, {append, LocalFile, RemoteFile}}, From,
- #state{chunk = false} = State) ->
- setup_data_connection(State#state{caller = {transfer_file,
- {"APPE",
- LocalFile, RemoteFile}},
- client = From});
-handle_call({_, {send_bin, Bin, RemoteFile}}, From,
- #state{chunk = false} = State) ->
- setup_data_connection(State#state{caller = {transfer_data,
- {"STOR", Bin, RemoteFile}},
- client = From});
-handle_call({_,{append_bin, Bin, RemoteFile}}, From,
- #state{chunk = false} = State) ->
- setup_data_connection(State#state{caller = {transfer_data,
- {"APPE", Bin, RemoteFile}},
- client = From});
-handle_call({_, {send_chunk_start, RemoteFile}}, From, #state{chunk = false}
- = State) ->
- setup_data_connection(State#state{caller = {start_chunk_transfer,
- "STOR", RemoteFile},
- client = From});
-handle_call({_, {append_chunk_start, RemoteFile}}, From, #state{chunk = false}
- = State) ->
- setup_data_connection(State#state{caller = {start_chunk_transfer,
- "APPE", RemoteFile},
- client = From});
-handle_call({_, {transfer_chunk, Bin}}, _, #state{chunk = true} = State) ->
- send_data_message(State, Bin),
- {reply, ok, State};
-
-handle_call({_, {transfer_chunk, _}}, _, #state{chunk = false} = State) ->
- {reply, {error, echunk}, State};
-
-handle_call({_, chunk_end}, From, #state{chunk = true} = State) ->
- close_data_connection(State),
- activate_ctrl_connection(State),
- {noreply, State#state{client = From, dsock = undefined,
- caller = end_chunk_transfer, chunk = false}};
-
-handle_call({_, chunk_end}, _, #state{chunk = false} = State) ->
- {reply, {error, echunk}, State};
-
-handle_call({_, {quote, Cmd}}, From, #state{chunk = false} = State) ->
- send_ctrl_message(State, mk_cmd(Cmd, [])),
- activate_ctrl_connection(State),
- {noreply, State#state{client = From, caller = quote}};
-
-handle_call({_, _Req}, _From, #state{csock = CSock} = State)
- when (CSock =:= undefined) ->
- {reply, {error, not_connected}, State};
-
-handle_call(_, _, #state{chunk = true} = State) ->
- {reply, {error, echunk}, State};
-
-%% Catch all - This can only happen if the application programmer writes
-%% really bad code that violates the API.
-handle_call(Request, _Timeout, State) ->
- {stop, {'API_violation_connection_closed', Request},
- {error, {connection_terminated, 'API_violation'}}, State}.
-
-%%--------------------------------------------------------------------------
-%% handle_cast(Request, State) -> {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State}
-%% Description: Handles cast messages.
-%%-------------------------------------------------------------------------
-handle_cast({Pid, close}, #state{owner = Pid} = State) ->
- send_ctrl_message(State, mk_cmd("QUIT", [])),
- close_ctrl_connection(State),
- close_data_connection(State),
- {stop, normal, State#state{csock = undefined, dsock = undefined}};
-
-handle_cast({Pid, close}, State) ->
- Report = io_lib:format("A none owner process ~p tried to close an "
- "ftp connection: ~n", [Pid]),
- error_logger:info_report(Report),
- {noreply, State};
-
-%% Catch all - This can oly happen if the application programmer writes
-%% really bad code that violates the API.
-handle_cast(Msg, State) ->
- {stop, {'API_violation_connection_closed', Msg}, State}.
-
-%%--------------------------------------------------------------------------
-%% handle_info(Msg, State) -> {noreply, State} | {noreply, State, Timeout} |
-%% {stop, Reason, State}
-%% Description: Handles tcp messages from the ftp-server.
-%% Note: The order of the function clauses is significant.
-%%--------------------------------------------------------------------------
-
-handle_info(timeout, #state{caller = open} = State) ->
- {stop, timeout, State};
-
-handle_info(timeout, State) ->
- {noreply, State};
-
-%%% Data socket messages %%%
-handle_info({Trpt, Socket, Data},
- #state{dsock = {Trpt,Socket},
- caller = {recv_file, Fd}} = State0) when Trpt==tcp;Trpt==ssl ->
- ?DBG('L~p --data ~p ----> ~s~p~n',[?LINE,Socket,Data,State0]),
- ok = file_write(binary_to_list(Data), Fd),
- progress_report({binary, Data}, State0),
- State = activate_data_connection(State0),
- {noreply, State};
-
-handle_info({Trpt, Socket, Data}, #state{dsock = {Trpt,Socket}, client = From,
- caller = recv_chunk}
- = State) when Trpt==tcp;Trpt==ssl ->
- ?DBG('L~p --data ~p ----> ~s~p~n',[?LINE,Socket,Data,State]),
- gen_server:reply(From, {ok, Data}),
- {noreply, State#state{client = undefined, data = <<>>}};
-
-handle_info({Trpt, Socket, Data}, #state{dsock = {Trpt,Socket}} = State0) when Trpt==tcp;Trpt==ssl ->
- ?DBG('L~p --data ~p ----> ~s~p~n',[?LINE,Socket,Data,State0]),
- State = activate_data_connection(State0),
- {noreply, State#state{data = <<(State#state.data)/binary,
- Data/binary>>}};
-
-handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket},
- caller = {recv_file, Fd}} = State)
- when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
- file_close(Fd),
- progress_report({transfer_size, 0}, State),
- activate_ctrl_connection(State),
- ?DBG("Data channel close",[]),
- {noreply, State#state{dsock = undefined, data = <<>>}};
-
-handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket},
- client = Client,
- caller = recv_chunk} = State)
- when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
- ?DBG("Data channel close recv_chunk",[]),
- activate_ctrl_connection(State),
- {noreply, State#state{dsock = undefined,
- caller = #recv_chunk_closing{dconn_closed = true,
- client_called_us = Client =/= undefined}
- }};
-
-handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket}, caller = recv_bin,
- data = Data} = State)
- when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
- ?DBG("Data channel close",[]),
- activate_ctrl_connection(State),
- {noreply, State#state{dsock = undefined, data = <<>>,
- caller = {recv_bin, Data}}};
-
-handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket}, data = Data,
- caller = {handle_dir_result, Dir}}
- = State) when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
- ?DBG("Data channel close",[]),
- activate_ctrl_connection(State),
- {noreply, State#state{dsock = undefined,
- caller = {handle_dir_result, Dir, Data},
-% data = <<?CR,?LF>>}};
- data = <<>>}};
-
-handle_info({Err, Socket, Reason}, #state{dsock = {Trpt,Socket},
- client = From} = State)
- when {Err,Trpt}=={tcp_error,tcp} ; {Err,Trpt}=={ssl_error,ssl} ->
- gen_server:reply(From, {error, Reason}),
- close_data_connection(State),
- {noreply, State#state{dsock = undefined, client = undefined,
- data = <<>>, caller = undefined, chunk = false}};
-
-%%% Ctrl socket messages %%%
-handle_info({Transport, Socket, Data}, #state{csock = {Transport, Socket},
- verbose = Verbose,
- caller = Caller,
- client = From,
- ctrl_data = {CtrlData, AccLines,
- LineStatus}}
- = State) ->
- ?DBG('--ctrl ~p ----> ~s~p~n',[Socket,<<CtrlData/binary, Data/binary>>,State]),
- case ftp_response:parse_lines(<<CtrlData/binary, Data/binary>>,
- AccLines, LineStatus) of
- {ok, Lines, NextMsgData} ->
- verbose(Lines, Verbose, 'receive'),
- CtrlResult = ftp_response:interpret(Lines),
- case Caller of
- quote ->
- gen_server:reply(From, string:tokens(Lines, [?CR, ?LF])),
- {noreply, State#state{client = undefined,
- caller = undefined,
- latest_ctrl_response = Lines,
- ctrl_data = {NextMsgData, [],
- start}}};
- _ ->
- ?DBG(' ...handle_ctrl_result(~p,...) ctrl_data=~p~n',[CtrlResult,{NextMsgData, [], start}]),
- handle_ctrl_result(CtrlResult,
- State#state{latest_ctrl_response = Lines,
- ctrl_data =
- {NextMsgData, [], start}})
- end;
- {continue, NewCtrlData} ->
- ?DBG(' ...Continue... ctrl_data=~p~n',[NewCtrlData]),
- activate_ctrl_connection(State),
- {noreply, State#state{ctrl_data = NewCtrlData}}
- end;
-
-%% If the server closes the control channel it is
-%% the expected behavior that connection process terminates.
-handle_info({Cls, Socket}, #state{csock = {Trpt, Socket}})
- when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
- exit(normal); %% User will get error message from terminate/2
-
-handle_info({Err, Socket, Reason}, _) when Err==tcp_error ; Err==ssl_error ->
- Report =
- io_lib:format("~p on socket: ~p for reason: ~p~n",
- [Err, Socket, Reason]),
- error_logger:error_report(Report),
- %% If tcp does not work the only option is to terminate,
- %% this is the expected behavior under these circumstances.
- exit(normal); %% User will get error message from terminate/2
-
-%% Monitor messages - if the process owning the ftp connection goes
-%% down there is no point in continuing.
-handle_info({'DOWN', _Ref, _Type, _Process, normal}, State) ->
- {stop, normal, State#state{client = undefined}};
-
-handle_info({'DOWN', _Ref, _Type, _Process, shutdown}, State) ->
- {stop, normal, State#state{client = undefined}};
-
-handle_info({'DOWN', _Ref, _Type, _Process, timeout}, State) ->
- {stop, normal, State#state{client = undefined}};
-
-handle_info({'DOWN', _Ref, _Type, Process, Reason}, State) ->
- {stop, {stopped, {'EXIT', Process, Reason}},
- State#state{client = undefined}};
-
-handle_info({'EXIT', Pid, Reason}, #state{progress = Pid} = State) ->
- Report = io_lib:format("Progress reporting stopped for reason ~p~n",
- [Reason]),
- error_logger:info_report(Report),
- {noreply, State#state{progress = ignore}};
-
-%% Catch all - throws away unknown messages (This could happen by "accident"
-%% so we do not want to crash, but we make a log entry as it is an
-%% unwanted behaviour.)
-handle_info(Info, State) ->
- Report = io_lib:format("ftp : ~p : Unexpected message: ~p~nState: ~p~n",
- [self(), Info, State]),
- error_logger:info_report(Report),
- {noreply, State}.
-
-%%--------------------------------------------------------------------------
-%% terminate/2 and code_change/3
-%%--------------------------------------------------------------------------
-terminate(normal, State) ->
- %% If terminate reason =/= normal the progress reporting process will
- %% be killed by the exit signal.
- progress_report(stop, State),
- do_terminate({error, econn}, State);
-terminate(Reason, State) ->
- Report = io_lib:format("Ftp connection closed due to: ~p~n", [Reason]),
- error_logger:error_report(Report),
- do_terminate({error, eclosed}, State).
-
-do_terminate(ErrorMsg, State) ->
- close_data_connection(State),
- close_ctrl_connection(State),
- case State#state.client of
- undefined ->
- ok;
- From ->
- gen_server:reply(From, ErrorMsg)
- end,
- ok.
-
-code_change(_Vsn, State1, upgrade_from_pre_5_12) ->
- {state, CSock, DSock, Verbose, LDir, Type, Chunk, Mode, Timeout,
- Data, CtrlData, Owner, Client, Caller, IPv6Disable, Progress} = State1,
- IpFamily =
- if
- (IPv6Disable =:= true) ->
- inet;
- true ->
- inet6fb4
- end,
- State2 = #state{csock = CSock,
- dsock = DSock,
- verbose = Verbose,
- ldir = LDir,
- type = Type,
- chunk = Chunk,
- mode = Mode,
- timeout = Timeout,
- data = Data,
- ctrl_data = CtrlData,
- owner = Owner,
- client = Client,
- caller = Caller,
- ipfamily = IpFamily,
- progress = Progress},
- {ok, State2};
-
-code_change(_Vsn, State1, downgrade_to_pre_5_12) ->
- #state{csock = CSock,
- dsock = DSock,
- verbose = Verbose,
- ldir = LDir,
- type = Type,
- chunk = Chunk,
- mode = Mode,
- timeout = Timeout,
- data = Data,
- ctrl_data = CtrlData,
- owner = Owner,
- client = Client,
- caller = Caller,
- ipfamily = IpFamily,
- progress = Progress} = State1,
- IPv6Disable =
- if
- (IpFamily =:= inet) ->
- true;
- true ->
- false
- end,
- State2 =
- {state, CSock, DSock, Verbose, LDir, Type, Chunk, Mode, Timeout,
- Data, CtrlData, Owner, Client, Caller, IPv6Disable, Progress},
- {ok, State2};
-
-code_change(_Vsn, State, _Extra) ->
- {ok, State}.
-
-
-%%%=========================================================================
-%% Start/stop
-%%%=========================================================================
-%%--------------------------------------------------------------------------
-%% start_link([Opts, GenServerOptions]) -> {ok, Pid} | {error, Reason}
-%%
-%% Description: Callback function for the ftp supervisor. It is called
-%% : when start_service/1 calls ftp_sup:start_child/1 to start an
-%% : instance of the ftp process. Also called by start_standalone/1
-%%--------------------------------------------------------------------------
-start_link([Opts, GenServerOptions]) ->
- start_link(Opts, GenServerOptions).
-
-start_link(Opts, GenServerOptions) ->
- case lists:keysearch(client, 1, Opts) of
- {value, _} ->
- %% Via the supervisor
- gen_server:start_link(?MODULE, Opts, GenServerOptions);
- false ->
- Opts2 = [{client, self()} | Opts],
- gen_server:start_link(?MODULE, Opts2, GenServerOptions)
- end.
-
-
-%%% Stop functionality is handled by close/1
-
-%%%========================================================================
-%%% Internal functions
-%%%========================================================================
-
-%%--------------------------------------------------------------------------
-%%% Help functions to handle_call and/or handle_ctrl_result
-%%--------------------------------------------------------------------------
-%% User handling
-handle_user(User, Password, Acc, State) ->
- send_ctrl_message(State, mk_cmd("USER ~s", [User])),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = {handle_user, Password, Acc}}}.
-
-handle_user_passwd(Password, Acc, State) ->
- send_ctrl_message(State, mk_cmd("PASS ~s", [Password])),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = {handle_user_passwd, Acc}}}.
-
-handle_user_account(Acc, State) ->
- send_ctrl_message(State, mk_cmd("ACCT ~s", [Acc])),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = handle_user_account}}.
-
-
-%%--------------------------------------------------------------------------
-%% handle_ctrl_result
-%%--------------------------------------------------------------------------
-handle_ctrl_result({tls_upgrade, _}, #state{csock = {tcp, Socket},
- tls_options = TLSOptions,
- timeout = Timeout,
- caller = open, client = From}
- = State0) ->
- ?DBG('<--ctrl ssl:connect(~p, ~p)~n~p~n',[Socket,TLSOptions,State0]),
- case ssl:connect(Socket, TLSOptions, Timeout) of
- {ok, TLSSocket} ->
- State = State0#state{csock = {ssl,TLSSocket}},
- send_ctrl_message(State, mk_cmd("PBSZ 0", [])),
- activate_ctrl_connection(State),
- {noreply, State#state{tls_upgrading_data_connection = {true, pbsz}} };
- {error, _} = Error ->
- gen_server:reply(From, {Error, self()}),
- {stop, normal, State0#state{client = undefined,
- caller = undefined,
- tls_upgrading_data_connection = false}}
- end;
-
-handle_ctrl_result({pos_compl, _}, #state{tls_upgrading_data_connection = {true, pbsz}} = State) ->
- send_ctrl_message(State, mk_cmd("PROT P", [])),
- activate_ctrl_connection(State),
- {noreply, State#state{tls_upgrading_data_connection = {true, prot}}};
-
-handle_ctrl_result({pos_compl, _}, #state{tls_upgrading_data_connection = {true, prot},
- client = From} = State) ->
- gen_server:reply(From, {ok, self()}),
- {noreply, State#state{client = undefined,
- caller = undefined,
- tls_upgrading_data_connection = false}};
-
-handle_ctrl_result({pos_compl, _}, #state{caller = open, client = From}
- = State) ->
- gen_server:reply(From, {ok, self()}),
- {noreply, State#state{client = undefined,
- caller = undefined }};
-handle_ctrl_result({_, Lines}, #state{caller = open} = State) ->
- ctrl_result_response(econn, State, {error, Lines});
-
-%%--------------------------------------------------------------------------
-%% Data connection setup active mode
-handle_ctrl_result({pos_compl, _Lines},
- #state{mode = active,
- caller = {setup_data_connection,
- {LSock, Caller}}} = State) ->
- handle_caller(State#state{caller = Caller, dsock = {lsock, LSock}});
-
-handle_ctrl_result({Status, _Lines},
- #state{mode = active,
- caller = {setup_data_connection, {LSock, _}}}
- = State) ->
- close_connection({tcp,LSock}),
- ctrl_result_response(Status, State, {error, Status});
-
-%% Data connection setup passive mode
-handle_ctrl_result({pos_compl, Lines},
- #state{mode = passive,
- ipfamily = inet6,
- client = From,
- caller = {setup_data_connection, Caller},
- csock = CSock,
- timeout = Timeout}
- = State) ->
- [_, PortStr | _] = lists:reverse(string:tokens(Lines, "|")),
- {ok, {IP, _}} = peername(CSock),
- case connect(IP, list_to_integer(PortStr), Timeout, State) of
- {ok, _, Socket} ->
- handle_caller(State#state{caller = Caller, dsock = {tcp, Socket}});
- {error, _Reason} = Error ->
- gen_server:reply(From, Error),
- {noreply, State#state{client = undefined, caller = undefined}}
- end;
-
-handle_ctrl_result({pos_compl, Lines},
- #state{mode = passive,
- ipfamily = inet,
- client = From,
- caller = {setup_data_connection, Caller},
- timeout = Timeout,
- ftp_extension = false} = State) ->
-
- {_, [?LEFT_PAREN | Rest]} =
- lists:splitwith(fun(?LEFT_PAREN) -> false; (_) -> true end, Lines),
- {NewPortAddr, _} =
- lists:splitwith(fun(?RIGHT_PAREN) -> false; (_) -> true end, Rest),
- [A1, A2, A3, A4, P1, P2] =
- lists:map(fun(X) -> list_to_integer(X) end,
- string:tokens(NewPortAddr, [$,])),
- IP = {A1, A2, A3, A4},
- Port = (P1 * 256) + P2,
-
- ?DBG('<--data tcp connect to ~p:~p, Caller=~p~n',[IP,Port,Caller]),
- case connect(IP, Port, Timeout, State) of
- {ok, _, Socket} ->
- handle_caller(State#state{caller = Caller, dsock = {tcp,Socket}});
- {error, _Reason} = Error ->
- gen_server:reply(From, Error),
- {noreply,State#state{client = undefined, caller = undefined}}
- end;
-
-handle_ctrl_result({pos_compl, Lines},
- #state{mode = passive,
- ipfamily = inet,
- client = From,
- caller = {setup_data_connection, Caller},
- csock = CSock,
- timeout = Timeout,
- ftp_extension = true} = State) ->
-
- [_, PortStr | _] = lists:reverse(string:tokens(Lines, "|")),
- {ok, {IP, _}} = peername(CSock),
-
- ?DBG('<--data tcp connect to ~p:~p, Caller=~p~n',[IP,PortStr,Caller]),
- case connect(IP, list_to_integer(PortStr), Timeout, State) of
- {ok, _, Socket} ->
- handle_caller(State#state{caller = Caller, dsock = {tcp, Socket}});
- {error, _Reason} = Error ->
- gen_server:reply(From, Error),
- {noreply, State#state{client = undefined, caller = undefined}}
- end;
-
-
-%% FTP server does not support passive mode: try to fallback on active mode
-handle_ctrl_result(_,
- #state{mode = passive,
- caller = {setup_data_connection, Caller}} = State) ->
- setup_data_connection(State#state{mode = active, caller = Caller});
-
-
-%%--------------------------------------------------------------------------
-%% User handling
-handle_ctrl_result({pos_interm, _},
- #state{caller = {handle_user, PassWord, Acc}} = State) ->
- handle_user_passwd(PassWord, Acc, State);
-handle_ctrl_result({Status, _},
- #state{caller = {handle_user, _, _}} = State) ->
- ctrl_result_response(Status, State, {error, euser});
-
-%% Accounts
-handle_ctrl_result({pos_interm_acct, _},
- #state{caller = {handle_user_passwd, Acc}} = State)
- when Acc =/= "" ->
- handle_user_account(Acc, State);
-handle_ctrl_result({Status, _},
- #state{caller = {handle_user_passwd, _}} = State) ->
- ctrl_result_response(Status, State, {error, euser});
-
-%%--------------------------------------------------------------------------
-%% Print current working directory
-handle_ctrl_result({pos_compl, Lines},
- #state{caller = pwd, client = From} = State) ->
- Dir = pwd_result(Lines),
- gen_server:reply(From, {ok, Dir}),
- {noreply, State#state{client = undefined, caller = undefined}};
-
-%%--------------------------------------------------------------------------
-%% Directory listing
-handle_ctrl_result({pos_prel, _}, #state{caller = {dir, Dir}} = State0) ->
- case accept_data_connection(State0) of
- {ok, State1} ->
- State = activate_data_connection(State1),
- {noreply, State#state{caller = {handle_dir_result, Dir}}};
- {error, _Reason} = ERROR ->
- case State0#state.client of
- undefined ->
- {stop, ERROR, State0};
- From ->
- gen_server:reply(From, ERROR),
- {stop, normal, State0#state{client = undefined}}
- end
- end;
-
-handle_ctrl_result({pos_compl, _}, #state{caller = {handle_dir_result, Dir,
- Data}, client = From}
- = State) ->
- case Dir of
- "" -> % Current directory
- gen_server:reply(From, {ok, Data}),
- {noreply, State#state{client = undefined,
- caller = undefined}};
- _ ->
- %% <WTF>
- %% Dir cannot be assumed to be a dir. It is a string that
- %% could be a dir, but could also be a file or even a string
- %% containing wildcards (*).
- %%
- %% %% If there is only one line it might be a directory with one
- %% %% file but it might be an error message that the directory
- %% %% was not found. So in this case we have to endure a little
- %% %% overhead to be able to give a good return value. Alas not
- %% %% all ftp implementations behave the same and returning
- %% %% an error string is allowed by the FTP RFC.
- %% case lists:dropwhile(fun(?CR) -> false;(_) -> true end,
- %% binary_to_list(Data)) of
- %% L when (L =:= [?CR, ?LF]) orelse (L =:= []) ->
- %% send_ctrl_message(State, mk_cmd("PWD", [])),
- %% activate_ctrl_connection(State),
- %% {noreply,
- %% State#state{caller = {handle_dir_data, Dir, Data}}};
- %% _ ->
- %% gen_server:reply(From, {ok, Data}),
- %% {noreply, State#state{client = undefined,
- %% caller = undefined}}
- %% end
- %% </WTF>
- gen_server:reply(From, {ok, Data}),
- {noreply, State#state{client = undefined,
- caller = undefined}}
- end;
-
-handle_ctrl_result({pos_compl, Lines},
- #state{caller = {handle_dir_data, Dir, DirData}} =
- State) ->
- OldDir = pwd_result(Lines),
- send_ctrl_message(State, mk_cmd("CWD ~s", [Dir])),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = {handle_dir_data_second_phase, OldDir,
- DirData}}};
-handle_ctrl_result({Status, _},
- #state{caller = {handle_dir_data, _, _}} = State) ->
- ctrl_result_response(Status, State, {error, epath});
-
-handle_ctrl_result(S={_Status, _},
- #state{caller = {handle_dir_result, _, _}} = State) ->
- %% OTP-5731, macosx
- ctrl_result_response(S, State, {error, epath});
-
-handle_ctrl_result({pos_compl, _},
- #state{caller = {handle_dir_data_second_phase, OldDir,
- DirData}} = State) ->
- send_ctrl_message(State, mk_cmd("CWD ~s", [OldDir])),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = {handle_dir_data_third_phase, DirData}}};
-handle_ctrl_result({Status, _},
- #state{caller = {handle_dir_data_second_phase, _, _}}
- = State) ->
- ctrl_result_response(Status, State, {error, epath});
-handle_ctrl_result(_, #state{caller = {handle_dir_data_third_phase, DirData},
- client = From} = State) ->
- gen_server:reply(From, {ok, DirData}),
- {noreply, State#state{client = undefined, caller = undefined}};
-
-handle_ctrl_result({Status, _}, #state{caller = cd} = State) ->
- ctrl_result_response(Status, State, {error, Status});
-
-handle_ctrl_result(Status={epath, _}, #state{caller = {dir,_}} = State) ->
- ctrl_result_response(Status, State, {error, epath});
-
-%%--------------------------------------------------------------------------
-%% File renaming
-handle_ctrl_result({pos_interm, _}, #state{caller = {rename, NewFile}}
- = State) ->
- send_ctrl_message(State, mk_cmd("RNTO ~s", [NewFile])),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = rename_second_phase}};
-
-handle_ctrl_result({Status, _},
- #state{caller = {rename, _}} = State) ->
- ctrl_result_response(Status, State, {error, Status});
-
-handle_ctrl_result({Status, _},
- #state{caller = rename_second_phase} = State) ->
- ctrl_result_response(Status, State, {error, Status});
-
-%%--------------------------------------------------------------------------
-%% File handling - recv_bin
-handle_ctrl_result({pos_prel, _}, #state{caller = recv_bin} = State0) ->
- case accept_data_connection(State0) of
- {ok, State1} ->
- State = activate_data_connection(State1),
- {noreply, State};
- {error, _Reason} = ERROR ->
- case State0#state.client of
- undefined ->
- {stop, ERROR, State0};
- From ->
- gen_server:reply(From, ERROR),
- {stop, normal, State0#state{client = undefined}}
- end
- end;
-
-handle_ctrl_result({pos_compl, _}, #state{caller = {recv_bin, Data},
- client = From} = State) ->
- gen_server:reply(From, {ok, Data}),
- close_data_connection(State),
- {noreply, State#state{client = undefined, caller = undefined}};
-
-handle_ctrl_result({Status, _}, #state{caller = recv_bin} = State) ->
- close_data_connection(State),
- ctrl_result_response(Status, State#state{dsock = undefined},
- {error, epath});
-
-handle_ctrl_result({Status, _}, #state{caller = {recv_bin, _}} = State) ->
- close_data_connection(State),
- ctrl_result_response(Status, State#state{dsock = undefined},
- {error, epath});
-%%--------------------------------------------------------------------------
-%% File handling - start_chunk_transfer
-handle_ctrl_result({pos_prel, _}, #state{client = From,
- caller = start_chunk_transfer}
- = State0) ->
- case accept_data_connection(State0) of
- {ok, State1} ->
- State = start_chunk(State1),
- {noreply, State};
- {error, _Reason} = ERROR ->
- case State0#state.client of
- undefined ->
- {stop, ERROR, State0};
- From ->
- gen_server:reply(From, ERROR),
- {stop, normal, State0#state{client = undefined}}
- end
- end;
-
-%%--------------------------------------------------------------------------
-%% File handling - chunk_transfer complete
-
-handle_ctrl_result({pos_compl, _}, #state{client = From,
- caller = #recv_chunk_closing{dconn_closed = true,
- client_called_us = true,
- pos_compl_received = false
- }}
- = State0) when From =/= undefined ->
- %% The pos_compl was the last event we waited for, finnish and clean up
- ?DBG("recv_chunk_closing pos_compl, last event",[]),
- gen_server:reply(From, ok),
- activate_ctrl_connection(State0),
- {noreply, State0#state{caller = undefined,
- chunk = false,
- client = undefined}};
-
-handle_ctrl_result({pos_compl, _}, #state{caller = #recv_chunk_closing{}=R}
- = State0) ->
- %% Waiting for more, don't care what
- ?DBG("recv_chunk_closing pos_compl, wait more",[]),
- {noreply, State0#state{caller = R#recv_chunk_closing{pos_compl_received=true}}};
-
-
-%%--------------------------------------------------------------------------
-%% File handling - recv_file
-handle_ctrl_result({pos_prel, _}, #state{caller = {recv_file, _}} = State0) ->
- case accept_data_connection(State0) of
- {ok, State1} ->
- State = activate_data_connection(State1),
- {noreply, State};
- {error, _Reason} = ERROR ->
- case State0#state.client of
- undefined ->
- {stop, ERROR, State0};
- From ->
- gen_server:reply(From, ERROR),
- {stop, normal, State0#state{client = undefined}}
- end
- end;
-
-handle_ctrl_result({Status, _}, #state{caller = {recv_file, Fd}} = State) ->
- file_close(Fd),
- close_data_connection(State),
- ctrl_result_response(Status, State#state{dsock = undefined},
- {error, epath});
-%%--------------------------------------------------------------------------
-%% File handling - transfer_*
-handle_ctrl_result({pos_prel, _}, #state{caller = {transfer_file, Fd}}
- = State0) ->
- case accept_data_connection(State0) of
- {ok, State1} ->
- send_file(State1, Fd);
- {error, _Reason} = ERROR ->
- case State0#state.client of
- undefined ->
- {stop, ERROR, State0};
- From ->
- gen_server:reply(From, ERROR),
- {stop, normal, State0#state{client = undefined}}
- end
- end;
-
-handle_ctrl_result({pos_prel, _}, #state{caller = {transfer_data, Bin}}
- = State0) ->
- case accept_data_connection(State0) of
- {ok, State} ->
- send_bin(State, Bin);
- {error, _Reason} = ERROR ->
- case State0#state.client of
- undefined ->
- {stop, ERROR, State0};
- From ->
- gen_server:reply(From, ERROR),
- {stop, normal, State0#state{client = undefined}}
- end
- end;
-
-%%--------------------------------------------------------------------------
-%% Default
-handle_ctrl_result({Status, _Lines}, #state{client = From} = State)
- when From =/= undefined ->
- ctrl_result_response(Status, State, {error, Status}).
-
-%%--------------------------------------------------------------------------
-%% Help functions to handle_ctrl_result
-%%--------------------------------------------------------------------------
-ctrl_result_response(pos_compl, #state{client = From} = State, _) ->
- gen_server:reply(From, ok),
- {noreply, State#state{client = undefined, caller = undefined}};
-
-ctrl_result_response(enofile, #state{client = From} = State, _) ->
- gen_server:reply(From, {error, enofile}),
- {noreply, State#state{client = undefined, caller = undefined}};
-
-ctrl_result_response(Status, #state{client = From} = State, _)
- when (Status =:= etnospc) orelse
- (Status =:= epnospc) orelse
- (Status =:= efnamena) orelse
- (Status =:= econn) ->
- gen_server:reply(From, {error, Status}),
-%% {stop, normal, {error, Status}, State#state{client = undefined}};
- {stop, normal, State#state{client = undefined}};
-
-ctrl_result_response(_, #state{client = From} = State, ErrorMsg) ->
- gen_server:reply(From, ErrorMsg),
- {noreply, State#state{client = undefined, caller = undefined}}.
-
-%%--------------------------------------------------------------------------
-handle_caller(#state{caller = {dir, Dir, Len}} = State) ->
- Cmd = case Len of
- short -> "NLST";
- long -> "LIST"
- end,
- case Dir of
- "" ->
- send_ctrl_message(State, mk_cmd(Cmd, ""));
- _ ->
- send_ctrl_message(State, mk_cmd(Cmd ++ " ~s", [Dir]))
- end,
- activate_ctrl_connection(State),
- {noreply, State#state{caller = {dir, Dir}}};
-
-handle_caller(#state{caller = {recv_bin, RemoteFile}} = State) ->
- send_ctrl_message(State, mk_cmd("RETR ~s", [RemoteFile])),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = recv_bin}};
-
-handle_caller(#state{caller = {start_chunk_transfer, Cmd, RemoteFile}} =
- State) ->
- send_ctrl_message(State, mk_cmd("~s ~s", [Cmd, RemoteFile])),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = start_chunk_transfer}};
-
-handle_caller(#state{caller = {recv_file, RemoteFile, Fd}} = State) ->
- send_ctrl_message(State, mk_cmd("RETR ~s", [RemoteFile])),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = {recv_file, Fd}}};
-
-handle_caller(#state{caller = {transfer_file, {Cmd, LocalFile, RemoteFile}},
- ldir = LocalDir, client = From} = State) ->
- case file_open(filename:absname(LocalFile, LocalDir), read) of
- {ok, Fd} ->
- send_ctrl_message(State, mk_cmd("~s ~s", [Cmd, RemoteFile])),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = {transfer_file, Fd}}};
- {error, _} ->
- gen_server:reply(From, {error, epath}),
- {noreply, State#state{client = undefined, caller = undefined,
- dsock = undefined}}
- end;
-
-handle_caller(#state{caller = {transfer_data, {Cmd, Bin, RemoteFile}}} =
- State) ->
- send_ctrl_message(State, mk_cmd("~s ~s", [Cmd, RemoteFile])),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = {transfer_data, Bin}}}.
-
-%% ----------- FTP SERVER COMMUNICATION -------------------------
-
-%% Connect to FTP server at Host (default is TCP port 21)
-%% in order to establish a control connection.
-setup_ctrl_connection(Host, Port, Timeout, State) ->
- MsTime = erlang:monotonic_time(),
- case connect(Host, Port, Timeout, State) of
- {ok, IpFam, CSock} ->
- NewState = State#state{csock = {tcp, CSock}, ipfamily = IpFam},
- activate_ctrl_connection(NewState),
- case Timeout - inets_lib:millisec_passed(MsTime) of
- Timeout2 when (Timeout2 >= 0) ->
- {ok, NewState#state{caller = open}, Timeout2};
- _ ->
- %% Oups: Simulate timeout
- {ok, NewState#state{caller = open}, 0}
- end;
- Error ->
- Error
- end.
-
-setup_data_connection(#state{mode = active,
- caller = Caller,
- csock = CSock,
- ftp_extension = FtpExt} = State) ->
- case (catch sockname(CSock)) of
- {ok, {{_, _, _, _, _, _, _, _} = IP, _}} ->
- {ok, LSock} =
- gen_tcp:listen(0, [{ip, IP}, {active, false},
- inet6, binary, {packet, 0}]),
- {ok, {_, Port}} = sockname({tcp,LSock}),
- IpAddress = inet_parse:ntoa(IP),
- Cmd = mk_cmd("EPRT |2|~s|~p|", [IpAddress, Port]),
- send_ctrl_message(State, Cmd),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = {setup_data_connection,
- {LSock, Caller}}}};
- {ok, {{_,_,_,_} = IP, _}} ->
- {ok, LSock} = gen_tcp:listen(0, [{ip, IP}, {active, false},
- binary, {packet, 0}]),
- {ok, Port} = inet:port(LSock),
- case FtpExt of
- false ->
- {IP1, IP2, IP3, IP4} = IP,
- {Port1, Port2} = {Port div 256, Port rem 256},
- send_ctrl_message(State,
- mk_cmd("PORT ~w,~w,~w,~w,~w,~w",
- [IP1, IP2, IP3, IP4, Port1, Port2]));
- true ->
- IpAddress = inet_parse:ntoa(IP),
- Cmd = mk_cmd("EPRT |1|~s|~p|", [IpAddress, Port]),
- send_ctrl_message(State, Cmd)
- end,
- activate_ctrl_connection(State),
- {noreply, State#state{caller = {setup_data_connection,
- {LSock, Caller}}}}
- end;
-
-setup_data_connection(#state{mode = passive, ipfamily = inet6,
- caller = Caller} = State) ->
- send_ctrl_message(State, mk_cmd("EPSV", [])),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = {setup_data_connection, Caller}}};
-
-setup_data_connection(#state{mode = passive, ipfamily = inet,
- caller = Caller,
- ftp_extension = false} = State) ->
- send_ctrl_message(State, mk_cmd("PASV", [])),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = {setup_data_connection, Caller}}};
-
-setup_data_connection(#state{mode = passive, ipfamily = inet,
- caller = Caller,
- ftp_extension = true} = State) ->
- send_ctrl_message(State, mk_cmd("EPSV", [])),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = {setup_data_connection, Caller}}}.
-
-connect(Host, Port, Timeout, #state{ipfamily = inet = IpFam}) ->
- connect2(Host, Port, IpFam, Timeout);
-
-connect(Host, Port, Timeout, #state{ipfamily = inet6 = IpFam}) ->
- connect2(Host, Port, IpFam, Timeout);
-
-connect(Host, Port, Timeout, #state{ipfamily = inet6fb4}) ->
- case inet:getaddr(Host, inet6) of
- {ok, {0, 0, 0, 0, 0, 16#ffff, _, _} = IPv6} ->
- case inet:getaddr(Host, inet) of
- {ok, IPv4} ->
- IpFam = inet,
- connect2(IPv4, Port, IpFam, Timeout);
-
- _ ->
- IpFam = inet6,
- connect2(IPv6, Port, IpFam, Timeout)
- end;
-
- {ok, IPv6} ->
- IpFam = inet6,
- connect2(IPv6, Port, IpFam, Timeout);
-
- _ ->
- case inet:getaddr(Host, inet) of
- {ok, IPv4} ->
- IpFam = inet,
- connect2(IPv4, Port, IpFam, Timeout);
- Error ->
- Error
- end
- end.
-
-connect2(Host, Port, IpFam, Timeout) ->
- Opts = [IpFam, binary, {packet, 0}, {active, false}],
- case gen_tcp:connect(Host, Port, Opts, Timeout) of
- {ok, Sock} ->
- {ok, IpFam, Sock};
- Error ->
- Error
- end.
-
-
-accept_data_connection(#state{mode = active,
- dtimeout = DTimeout,
- tls_options = TLSOptions,
- dsock = {lsock, LSock}} = State0) ->
- case gen_tcp:accept(LSock, DTimeout) of
- {ok, Socket} when is_list(TLSOptions) ->
- gen_tcp:close(LSock),
- ?DBG('<--data ssl:connect(~p, ~p)~n~p~n',[Socket,TLSOptions,State0]),
- case ssl:connect(Socket, TLSOptions, DTimeout) of
- {ok, TLSSocket} ->
- {ok, State0#state{dsock={ssl,TLSSocket}}};
- {error, Reason} ->
- {error, {ssl_connect_failed, Reason}}
- end;
- {ok, Socket} ->
- gen_tcp:close(LSock),
- {ok, State0#state{dsock={tcp,Socket}}};
- {error, Reason} ->
- {error, {data_connect_failed, Reason}}
- end;
-
-accept_data_connection(#state{mode = passive,
- dtimeout = DTimeout,
- dsock = {tcp,Socket},
- tls_options = TLSOptions} = State) when is_list(TLSOptions) ->
- ?DBG('<--data ssl:connect(~p, ~p)~n~p~n',[Socket,TLSOptions,State]),
- case ssl:connect(Socket, TLSOptions, DTimeout) of
- {ok, TLSSocket} ->
- {ok, State#state{dsock={ssl,TLSSocket}}};
- {error, Reason} ->
- {error, {ssl_connect_failed, Reason}}
- end;
-accept_data_connection(#state{mode = passive} = State) ->
- {ok,State}.
-
-
-send_ctrl_message(_S=#state{csock = Socket, verbose = Verbose}, Message) ->
- verbose(lists:flatten(Message),Verbose,send),
- ?DBG('<--ctrl ~p ---- ~s~p~n',[Socket,Message,_S]),
- _ = send_message(Socket, Message).
-
-send_data_message(_S=#state{dsock = Socket}, Message) ->
- ?DBG('<==data ~p ==== ~s~n~p~n',[Socket,Message,_S]),
- case send_message(Socket, Message) of
- ok ->
- ok;
- {error, Reason} ->
- Report = io_lib:format("send/2 for socket ~p failed with "
- "reason ~p~n", [Socket, Reason]),
- error_logger:error_report(Report),
- %% If tcp/ssl does not work the only option is to terminate,
- %% this is the expected behavior under these circumstances.
- exit(normal) %% User will get error message from terminate/2
- end.
-
-send_message({tcp, Socket}, Message) ->
- gen_tcp:send(Socket, Message);
-send_message({ssl, Socket}, Message) ->
- ssl:send(Socket, Message).
-
-activate_ctrl_connection(#state{csock = CSock, ctrl_data = {<<>>, _, _}}) ->
- activate_connection(CSock);
-activate_ctrl_connection(#state{csock = CSock}) ->
- activate_connection(CSock),
- %% We have already received at least part of the next control message,
- %% that has been saved in ctrl_data, process this first.
- self() ! {socket_type(CSock), unwrap_socket(CSock), <<>>},
- ok.
-
-activate_data_connection(#state{dsock = DSock} = State) ->
- activate_connection(DSock),
- State.
-
-activate_connection(Socket) ->
- ignore_return_value(
- case socket_type(Socket) of
- tcp -> inet:setopts(unwrap_socket(Socket), [{active, once}]);
- ssl -> ssl:setopts(unwrap_socket(Socket), [{active, once}])
- end).
-
-
-ignore_return_value(_) -> ok.
-
-unwrap_socket({tcp,Socket}) -> Socket;
-unwrap_socket({ssl,Socket}) -> Socket.
-
-socket_type({tcp,_Socket}) -> tcp;
-socket_type({ssl,_Socket}) -> ssl.
-
-close_ctrl_connection(#state{csock = undefined}) -> ok;
-close_ctrl_connection(#state{csock = Socket}) -> close_connection(Socket).
-
-close_data_connection(#state{dsock = undefined}) -> ok;
-close_data_connection(#state{dsock = Socket}) -> close_connection(Socket).
-
-close_connection({lsock,Socket}) -> ignore_return_value( gen_tcp:close(Socket) );
-close_connection({tcp, Socket}) -> ignore_return_value( gen_tcp:close(Socket) );
-close_connection({ssl, Socket}) -> ignore_return_value( ssl:close(Socket) ).
-
-%% ------------ FILE HANDLING ----------------------------------------
-send_file(#state{tls_upgrading_data_connection = {true, CTRL, _}} = State, Fd) ->
- {noreply, State#state{tls_upgrading_data_connection = {true, CTRL, ?MODULE, send_file, Fd}}};
-send_file(State, Fd) ->
- case file_read(Fd) of
- {ok, N, Bin} when N > 0 ->
- send_data_message(State, Bin),
- progress_report({binary, Bin}, State),
- send_file(State, Fd);
- {ok, _, _} ->
- file_close(Fd),
- close_data_connection(State),
- progress_report({transfer_size, 0}, State),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = transfer_file_second_phase,
- dsock = undefined}};
- {error, Reason} ->
- gen_server:reply(State#state.client, {error, Reason}),
- {stop, normal, State#state{client = undefined}}
- end.
-
-file_open(File, Option) ->
- file:open(File, [raw, binary, Option]).
-
-file_close(Fd) ->
- ignore_return_value( file:close(Fd) ).
-
-file_read(Fd) ->
- case file:read(Fd, ?FILE_BUFSIZE) of
- {ok, Bytes} ->
- {ok, size(Bytes), Bytes};
- eof ->
- {ok, 0, []};
- Other ->
- Other
- end.
-
-file_write(Bytes, Fd) ->
- file:write(Fd, Bytes).
-
-%% -------------- MISC ----------------------------------------------
-
-call(GenServer, Msg, Format) ->
- call(GenServer, Msg, Format, infinity).
-call(GenServer, Msg, Format, Timeout) ->
- Req = {self(), Msg},
- case (catch gen_server:call(GenServer, Req, Timeout)) of
- {ok, Bin} when is_binary(Bin) andalso (Format =:= string) ->
- {ok, binary_to_list(Bin)};
- {'EXIT', _} ->
- {error, eclosed};
- Result ->
- Result
- end.
-
-cast(GenServer, Msg) ->
- gen_server:cast(GenServer, {self(), Msg}).
-
-send_bin(#state{tls_upgrading_data_connection = {true, CTRL, _}} = State, Bin) ->
- State#state{tls_upgrading_data_connection = {true, CTRL, ?MODULE, send_bin, Bin}};
-send_bin(State, Bin) ->
- send_data_message(State, Bin),
- close_data_connection(State),
- activate_ctrl_connection(State),
- {noreply, State#state{caller = transfer_data_second_phase,
- dsock = undefined}}.
-
-mk_cmd(Fmt, Args) ->
- [io_lib:format(Fmt, Args)| [?CR, ?LF]]. % Deep list ok.
-
-is_name_sane([]) ->
- true;
-is_name_sane([?CR| _]) ->
- false;
-is_name_sane([?LF| _]) ->
- false;
-is_name_sane([_| Rest]) ->
- is_name_sane(Rest).
-
-pwd_result(Lines) ->
- {_, [?DOUBLE_QUOTE | Rest]} =
- lists:splitwith(fun(?DOUBLE_QUOTE) -> false; (_) -> true end, Lines),
- {Dir, _} =
- lists:splitwith(fun(?DOUBLE_QUOTE) -> false; (_) -> true end, Rest),
- Dir.
-
-
-key_search(Key, List, Default) ->
- case lists:keysearch(Key, 1, List) of
- {value, {_,Val}} ->
- Val;
- false ->
- Default
- end.
-
-verbose(Lines, true, Direction) ->
- DirStr =
- case Direction of
- send ->
- "Sending: ";
- _ ->
- "Receiving: "
- end,
- Str = string:strip(string:strip(Lines, right, ?LF), right, ?CR),
- erlang:display(DirStr++Str);
-verbose(_, false,_) ->
- ok.
-
-progress(Options) ->
- ftp_progress:start_link(Options).
-
-progress_report(_, #state{progress = ignore}) ->
- ok;
-progress_report(stop, #state{progress = ProgressPid}) ->
- ftp_progress:stop(ProgressPid);
-progress_report({binary, Data}, #state{progress = ProgressPid}) ->
- ftp_progress:report(ProgressPid, {transfer_size, size(Data)});
-progress_report(Report, #state{progress = ProgressPid}) ->
- ftp_progress:report(ProgressPid, Report).
-
-
-peername({tcp, Socket}) -> inet:peername(Socket);
-peername({ssl, Socket}) -> ssl:peername(Socket).
-
-sockname({tcp, Socket}) -> inet:sockname(Socket);
-sockname({ssl, Socket}) -> ssl:sockname(Socket).
-
-maybe_tls_upgrade(Pid, undefined) ->
- {ok, Pid};
-maybe_tls_upgrade(Pid, TLSOptions) ->
- catch ssl:start(),
- call(Pid, {open, tls_upgrade, TLSOptions}, plain).
-
-start_chunk(#state{tls_upgrading_data_connection = {true, CTRL, _}} = State) ->
- State#state{tls_upgrading_data_connection = {true, CTRL, ?MODULE, start_chunk, undefined}};
-start_chunk(#state{client = From} = State) ->
- gen_server:reply(From, ok),
- State#state{chunk = true,
- client = undefined,
- caller = undefined}.
diff --git a/lib/inets/src/ftp/ftp_internal.hrl b/lib/inets/src/ftp/ftp_internal.hrl
deleted file mode 100644
index f29bb4a099..0000000000
--- a/lib/inets/src/ftp/ftp_internal.hrl
+++ /dev/null
@@ -1,33 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--ifndef(ftp_internal_hrl).
--define(ftp_internal_hrl, true).
-
--include_lib("inets/src/inets_app/inets_internal.hrl").
-
--define(SERVICE, ftpc).
--define(fcri(Label, Content), ?report_important(Label, ?SERVICE, Content)).
--define(fcrv(Label, Content), ?report_verbose(Label, ?SERVICE, Content)).
--define(fcrd(Label, Content), ?report_debug(Label, ?SERVICE, Content)).
--define(fcrt(Label, Content), ?report_trace(Label, ?SERVICE, Content)).
-
--endif. % -ifdef(ftp_internal_hrl).
diff --git a/lib/inets/src/ftp/ftp_progress.erl b/lib/inets/src/ftp/ftp_progress.erl
deleted file mode 100644
index a6263e5cd7..0000000000
--- a/lib/inets/src/ftp/ftp_progress.erl
+++ /dev/null
@@ -1,136 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%% Description: This module impements a temporary process that
-%% performes progress reporting during file transfer calling a user
-%% defined callback function. Its life span is as long as the ftp connection
-%% processes that spawned it lives. The purpose of this process is to
-%% shild the ftp connection process from errors and time consuming operations
-%% in the user defined callback function.
-
--module(ftp_progress).
-
-%% Internal API
--export([start_link/1, report/2, stop/1]).
-
-%% Spawn export
--export([init/1]).
-
--include_lib("kernel/include/file.hrl").
-
--record(progress, {
- file :: string() | 'undefined',
- cb_module :: module(),
- cb_function :: atom(),
- init_progress_term :: term(),
- current_progress_term :: term()
- }).
-
-%%%=========================================================================
-%%% Internal application API
-%%%=========================================================================
-%%--------------------------------------------------------------------------
-%% start_link(Options) -> ignore | pid()
-%% Options = ignore | {CBModule, CBFunction, InitProgressTerm}
-%%
-%% Description: Starts the progress report process unless progress reporting
-%% should not be performed.
-%%--------------------------------------------------------------------------
--type options() :: 'ignore' | {module(), atom(), term()}.
--spec start_link(options()) -> 'ignore' | pid().
-start_link(ignore) ->
- ignore;
-start_link(Options) ->
- spawn_link(?MODULE, init, [Options]).
-
-%%--------------------------------------------------------------------------
-%% report_progress(Pid, Report) -> ok
-%% Pid = pid()
-%% Report = {local_file, File} | {remote_file, File} |
-%% {transfer_size, Size}
-%% Size = integer()
-%%
-%% Description: Reports progress to the reporting process that calls the
-%% user defined callback function.
-%%--------------------------------------------------------------------------
--type report() :: {'local_file', string()} | {'remote_file', string()}
- | {'transfer_size', non_neg_integer()}.
--spec report(pid(), report()) -> 'ok'.
-report(Pid, Report) ->
- Pid ! {progress_report, Report},
- ok.
-
-%%--------------------------------------------------------------------------
-%% stop(Pid) -> ok
-%% Pid = pid()
-%%
-%% Description:
-%%--------------------------------------------------------------------------
--spec stop(pid()) -> 'ok'.
-stop(Pid) ->
- Pid ! stop,
- ok.
-
-%%%=========================================================================
-%%% Internal functions
-%%%=========================================================================
-init(Options) ->
- loop(progress(Options)).
-
-loop(Progress) ->
- receive
- {progress_report, Report} ->
- NewProgress = report_progress(Report, Progress),
- loop(NewProgress);
- stop ->
- ok
- end.
-
-progress({CBModule, CBFunction, InitProgressTerm}) when is_atom(CBModule),
- is_atom(CBFunction) ->
- #progress{cb_module = CBModule,
- cb_function = CBFunction,
- init_progress_term = InitProgressTerm,
- current_progress_term = InitProgressTerm}.
-
-report_progress({local_file, File}, Progress) ->
- {ok, FileInfo} = file:read_file_info(File),
- report_progress({file_size, FileInfo#file_info.size},
- Progress#progress{file = File});
-
-report_progress({remote_file, File}, Progress) ->
- report_progress({file_size, unknown}, Progress#progress{file = File});
-
-report_progress(Size, #progress{file = File,
- cb_module = CBModule,
- cb_function = CBFunction,
- current_progress_term = Term,
- init_progress_term = InitTerm} = Progress) ->
-
- NewProgressTerm = CBModule:CBFunction(Term, File, Size),
-
- case Size of
- {transfer_size, 0} ->
- %% Transfer is compleat reset initial values
- Progress#progress{current_progress_term = InitTerm,
- file = undefined};
- _ ->
- Progress#progress{current_progress_term = NewProgressTerm}
- end.
diff --git a/lib/inets/src/ftp/ftp_response.erl b/lib/inets/src/ftp/ftp_response.erl
deleted file mode 100644
index d54d97dc91..0000000000
--- a/lib/inets/src/ftp/ftp_response.erl
+++ /dev/null
@@ -1,203 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%% Description: This module impements handling of ftp server responses.
-
--module(ftp_response).
-
-%% Internal API
--export([parse_lines/3, interpret/1, error_string/1]).
-
--include("ftp_internal.hrl").
-
-%% First group of reply code digits
--define(POS_PREL, 1).
--define(POS_COMPL, 2).
--define(POS_INTERM, 3).
--define(TRANS_NEG_COMPL, 4).
--define(PERM_NEG_COMPL, 5).
-%% Second group of reply code digits
--define(SYNTAX,0).
--define(INFORMATION,1).
--define(CONNECTION,2).
--define(AUTH_ACC,3).
--define(UNSPEC,4).
--define(FILE_SYSTEM,5).
-
-%%%=========================================================================
-%%% INTERNAL API
-%%%=========================================================================
-
-%%--------------------------------------------------------------------------
-%% parse_lines(Data, AccLines, StatusCode) -> {ok, Lines} |
-%% {continue, {Data,
-%% AccLines, StatusCode}}
-%%
-%% Data = binary() - data recived on the control connection from the
-%% ftp-server.
-%% AccLines = [string()]
-%% StatusCode = start | {byte(), byte(), byte()} | finish -
-%% Indicates where in the parsing process we are.
-%% start - (looking for the status code of the message)
-%% {byte(), byte(), byte()} - status code found, now
-%% looking for the last line indication.
-%% finish - now on the last line.
-%% Description: Parses a ftp control response message.
-%% "A reply is defined to contain the 3-digit code, followed by Space
-%% <SP>, followed by one line of text (where some maximum line length
-%% has been specified), and terminated by the Telnet end-of-line
-%% code (CRLF), or a so called multilined reply for example:
-%%
-%% 123-First line
-%% Second line
-%% 234 A line beginning with numbers
-%% 123 The last line
-%%
-%% The user-process then simply needs to search for the second
-%% occurrence of the same reply code, followed by <SP> (Space), at
-%% the beginning of a line, and ignore all intermediary lines. If
-%% an intermediary line begins with a 3-digit number, the Server
-%% will pad the front to avoid confusion.
-%%--------------------------------------------------------------------------
-
-%% Make sure we received the first 4 bytes so we know how to parse
-%% the FTP server response e.i. is the response composed of one
-%% or multiple lines.
-parse_lines(Bin, Lines, start) when size(Bin) < 4 ->
- {continue, {Bin, Lines, start}};
-%% Multiple lines exist
-parse_lines(<<C1, C2, C3, $-, Rest/binary>>, Lines, start) ->
- parse_lines(Rest, [$-, C3, C2, C1 | Lines], {C1, C2, C3});
-%% Only one line exists
-parse_lines(<<C1, C2, C3, ?WHITE_SPACE, Bin/binary>>, Lines, start) ->
- parse_lines(Bin, [?WHITE_SPACE, C3, C2, C1 | Lines], finish);
-
-%% Last line found
-parse_lines(<<?CR, ?LF, C1, C2, C3, ?WHITE_SPACE, Rest/binary>>, Lines, {C1, C2, C3}) ->
- parse_lines(Rest, [?WHITE_SPACE, C3, C2, C1, ?LF, ?CR | Lines], finish);
-%% Potential end found wait for more data
-parse_lines(<<?CR, ?LF, C1, C2, C3>> = Bin, Lines, {C1, C2, C3}) ->
- {continue, {Bin, Lines, {C1, C2, C3}}};
-%% Intermidate line begining with status code
-parse_lines(<<?CR, ?LF, C1, C2, C3, Rest/binary>>, Lines, {C1, C2, C3}) ->
- parse_lines(Rest, [C3, C2, C1, ?LF, ?CR | Lines], {C1, C2, C3});
-
-%% Potential last line wait for more data
-parse_lines(<<?CR, ?LF, C1, C2>> = Data, Lines, {C1, C2, _} = StatusCode) ->
- {continue, {Data, Lines, StatusCode}};
-parse_lines(<<?CR, ?LF, C1>> = Data, Lines, {C1, _, _} = StatusCode) ->
- {continue, {Data, Lines, StatusCode}};
-parse_lines(<<?CR, ?LF>> = Data, Lines, {_,_,_} = StatusCode) ->
- {continue, {Data, Lines, StatusCode}};
-parse_lines(<<?LF>> = Data, Lines, {_,_,_} = StatusCode) ->
- {continue, {Data, Lines, StatusCode}};
-parse_lines(<<>> = Data, Lines, {_,_,_} = StatusCode) ->
- {continue, {Data, Lines, StatusCode}};
-%% Part of the multiple lines
-parse_lines(<<Octet, Rest/binary>>, Lines, {_,_, _} = StatusCode) ->
- parse_lines(Rest, [Octet | Lines], StatusCode);
-
-%% End of FTP server response found
-parse_lines(<<?CR, ?LF>>, Lines, finish) ->
- {ok, lists:reverse([?LF, ?CR | Lines]), <<>>};
-parse_lines(<<?CR, ?LF, Rest/binary>>, Lines, finish) ->
- {ok, lists:reverse([?LF, ?CR | Lines]), Rest};
-
-%% Potential end found wait for more data
-parse_lines(<<?CR>> = Data, Lines, finish) ->
- {continue, {Data, Lines, finish}};
-parse_lines(<<>> = Data, Lines, finish) ->
- {continue, {Data, Lines, finish}};
-%% Part of last line
-parse_lines(<<Octet, Rest/binary>>, Lines, finish) ->
- parse_lines(Rest, [Octet | Lines], finish).
-
-%%--------------------------------------------------------------------------
-%% interpret(Lines) -> {Status, Text}
-%% Lines = [byte(), byte(), byte() | Text] - ftp server response as
-%% returned by parse_lines/3
-%% Stauts = atom() (see interpret_status/3)
-%% Text = [string()]
-%%
-%% Description: Create nicer data to match on.
-%%--------------------------------------------------------------------------
-interpret([Didgit1, Didgit2, Didgit3 | Data]) ->
- Code1 = Didgit1 - $0,
- Code2 = Didgit2 - $0,
- Code3 = Didgit3 - $0,
- {interpret_status(Code1, Code2, Code3), Data}.
-
-%%--------------------------------------------------------------------------
-%% error_string(Error) -> string()
-%% Error = {error, term()} | term()
-%%
-%% Description: Translates error codes into strings intended for
-%% human interpretation.
-%%--------------------------------------------------------------------------
-error_string({error, Reason}) ->
- error_string(Reason);
-
-error_string(echunk) -> "Synchronisation error during chunk sending.";
-error_string(eclosed) -> "Session has been closed.";
-error_string(econn) -> "Connection to remote server prematurely closed.";
-error_string(eexists) ->"File or directory already exists.";
-error_string(ehost) -> "Host not found, FTP server not found, "
- "or connection rejected.";
-error_string(elogin) -> "User not logged in.";
-error_string(enotbinary) -> "Term is not a binary.";
-error_string(epath) -> "No such file or directory, already exists, "
- "or permission denied.";
-error_string(etype) -> "No such type.";
-error_string(euser) -> "User name or password not valid.";
-error_string(etnospc) -> "Insufficient storage space in system.";
-error_string(enofile) -> "No files found or file unavailable";
-error_string(epnospc) -> "Exceeded storage allocation "
- "(for current directory or dataset).";
-error_string(efnamena) -> "File name not allowed.";
-error_string(Reason) ->
- lists:flatten(io_lib:format("Unknown error: ~w", [Reason])).
-
-%%%========================================================================
-%%% Internal functions
-%%%========================================================================
-
-%% Positive Preleminary Reply
-interpret_status(?POS_PREL,_,_) -> pos_prel;
-%%FIXME ??? 3??? interpret_status(?POS_COMPL, ?AUTH_ACC, 3) -> tls_upgrade;
-interpret_status(?POS_COMPL, ?AUTH_ACC, 4) -> tls_upgrade;
-%% Positive Completion Reply
-interpret_status(?POS_COMPL,_,_) -> pos_compl;
-%% Positive Intermediate Reply nedd account
-interpret_status(?POS_INTERM,?AUTH_ACC,2) -> pos_interm_acct;
-%% Positive Intermediate Reply
-interpret_status(?POS_INTERM,_,_) -> pos_interm;
-%% No files found or file not available
-interpret_status(?TRANS_NEG_COMPL,?FILE_SYSTEM,0) -> enofile;
-%% No storage area no action taken
-interpret_status(?TRANS_NEG_COMPL,?FILE_SYSTEM,2) -> etnospc;
-%% Temporary Error, no action taken
-interpret_status(?TRANS_NEG_COMPL,_,_) -> trans_neg_compl;
-%% Permanent disk space error, the user shall not try again
-interpret_status(?PERM_NEG_COMPL,?FILE_SYSTEM,0) -> epath;
-interpret_status(?PERM_NEG_COMPL,?FILE_SYSTEM,2) -> epnospc;
-interpret_status(?PERM_NEG_COMPL,?FILE_SYSTEM,3) -> efnamena;
-interpret_status(?PERM_NEG_COMPL,?AUTH_ACC,0) -> elogin;
-interpret_status(?PERM_NEG_COMPL,_,_) -> perm_neg_compl.
-
diff --git a/lib/inets/src/ftp/ftp_sup.erl b/lib/inets/src/ftp/ftp_sup.erl
deleted file mode 100644
index 21dcfb6ab2..0000000000
--- a/lib/inets/src/ftp/ftp_sup.erl
+++ /dev/null
@@ -1,60 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% Purpose: The top supervisor for the ftp hangs under inets_sup.
-%%----------------------------------------------------------------------
--module(ftp_sup).
-
--behaviour(supervisor).
-
-%% API
--export([start_link/0]).
--export([start_child/1]).
-
-%% Supervisor callback
--export([init/1]).
-
-%%%=========================================================================
-%%% API
-%%%=========================================================================
-start_link() ->
- supervisor:start_link({local, ?MODULE}, ?MODULE, []).
-
-start_child(Args) ->
- supervisor:start_child(?MODULE, Args).
-
-%%%=========================================================================
-%%% Supervisor callback
-%%%=========================================================================
-init(_) ->
- RestartStrategy = simple_one_for_one,
- MaxR = 0,
- MaxT = 3600,
-
- Name = undefined, % As simple_one_for_one is used.
- StartFunc = {ftp, start_link, []},
- Restart = temporary, % E.g. should not be restarted
- Shutdown = 4000,
- Modules = [ftp],
- Type = worker,
-
- ChildSpec = {Name, StartFunc, Restart, Shutdown, Type, Modules},
- {ok, {{RestartStrategy, MaxR, MaxT}, [ChildSpec]}}.
diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl
index bf2da82603..24a205ced9 100644
--- a/lib/inets/src/http_client/httpc.erl
+++ b/lib/inets/src/http_client/httpc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -171,14 +171,15 @@ request(Method,
HTTPOptions, Options, Profile)
when (Method =:= options) orelse
(Method =:= get) orelse
+ (Method =:= put) orelse
(Method =:= head) orelse
(Method =:= delete) orelse
(Method =:= trace) andalso
(is_atom(Profile) orelse is_pid(Profile)) ->
- case uri_parse(Url, Options) of
- {error, Reason} ->
+ case uri_string:parse(uri_string:normalize(Url)) of
+ {error, Reason, _} ->
{error, Reason};
- {ok, ParsedUrl} ->
+ ParsedUrl ->
case header_parse(Headers) of
{error, Reason} ->
{error, Reason};
@@ -189,10 +190,10 @@ request(Method,
end.
do_request(Method, {Url, Headers, ContentType, Body}, HTTPOptions, Options, Profile) ->
- case uri_parse(Url, Options) of
- {error, Reason} ->
+ case uri_string:parse(uri_string:normalize(Url)) of
+ {error, Reason, _} ->
{error, Reason};
- {ok, ParsedUrl} ->
+ ParsedUrl ->
handle_request(Method, Url,
ParsedUrl, Headers, ContentType, Body,
HTTPOptions, Options, Profile)
@@ -312,23 +313,28 @@ store_cookies(SetCookieHeaders, Url) ->
store_cookies(SetCookieHeaders, Url, Profile)
when is_atom(Profile) orelse is_pid(Profile) ->
- try
- begin
+ case uri_string:parse(uri_string:normalize(Url)) of
+ {error, Bad, _} ->
+ {error, {parse_failed, Bad}};
+ URI ->
+ Scheme = scheme_to_atom(maps:get(scheme, URI, '')),
+ Host = maps:get(host, URI, ""),
+ Port = maps:get(port, URI, default_port(Scheme)),
+ Path = uri_string:recompose(#{path => maps:get(path, URI, "")}),
%% Since the Address part is not actually used
%% by the manager when storing cookies, we dont
%% care about ipv6-host-with-brackets.
- {ok, {_, _, Host, Port, Path, _}} = uri_parse(Url),
Address = {Host, Port},
ProfileName = profile_name(Profile),
Cookies = httpc_cookie:cookies(SetCookieHeaders, Path, Host),
httpc_manager:store_cookies(Cookies, Address, ProfileName),
ok
- end
- catch
- error:{badmatch, Bad} ->
- {error, {parse_failed, Bad}}
end.
+default_port(http) ->
+ 80;
+default_port(https) ->
+ 443.
%%--------------------------------------------------------------------------
%% cookie_header(Url) -> Header | {error, Reason}
@@ -495,7 +501,7 @@ service_info(Pid) ->
%%% Internal functions
%%%========================================================================
handle_request(Method, Url,
- {Scheme, UserInfo, Host, Port, Path, Query},
+ URI,
Headers0, ContentType, Body0,
HTTPOptions0, Options0, Profile) ->
@@ -520,37 +526,42 @@ handle_request(Method, Url,
throw({error, {bad_body, Body0}})
end,
- HTTPOptions = http_options(HTTPOptions0),
- Options = request_options(Options0),
- Sync = proplists:get_value(sync, Options),
- Stream = proplists:get_value(stream, Options),
- Host2 = http_request:normalize_host(Scheme, Host, Port),
- HeadersRecord = header_record(NewHeaders, Host2, HTTPOptions),
- Receiver = proplists:get_value(receiver, Options),
- SocketOpts = proplists:get_value(socket_opts, Options),
- BracketedHost = proplists:get_value(ipv6_host_with_brackets,
- Options),
- MaybeEscPath = maybe_encode_uri(HTTPOptions, Path),
- MaybeEscQuery = maybe_encode_uri(HTTPOptions, Query),
- AbsUri = maybe_encode_uri(HTTPOptions, Url),
+ HTTPOptions = http_options(HTTPOptions0),
+ Options = request_options(Options0),
+ Sync = proplists:get_value(sync, Options),
+ Stream = proplists:get_value(stream, Options),
+ Receiver = proplists:get_value(receiver, Options),
+ SocketOpts = proplists:get_value(socket_opts, Options),
+ UnixSocket = proplists:get_value(unix_socket, Options),
+ BracketedHost = proplists:get_value(ipv6_host_with_brackets,
+ Options),
+
+ Scheme = scheme_to_atom(maps:get(scheme, URI, '')),
+ Userinfo = maps:get(userinfo, URI, ""),
+ Host = http_util:maybe_add_brackets(maps:get(host, URI, ""), BracketedHost),
+ Port = maps:get(port, URI, default_port(Scheme)),
+ Host2 = http_request:normalize_host(Scheme, Host, Port),
+ Path = uri_string:recompose(#{path => maps:get(path, URI, "")}),
+ Query = add_question_mark(maps:get(query, URI, "")),
+ HeadersRecord = header_record(NewHeaders, Host2, HTTPOptions),
Request = #request{from = Receiver,
- scheme = Scheme,
- address = {host_address(Host, BracketedHost), Port},
- path = MaybeEscPath,
- pquery = MaybeEscQuery,
+ scheme = Scheme,
+ address = {Host, Port},
+ path = Path,
+ pquery = Query,
method = Method,
headers = HeadersRecord,
content = {ContentType, Body},
settings = HTTPOptions,
- abs_uri = AbsUri,
- userinfo = UserInfo,
+ abs_uri = Url,
+ userinfo = Userinfo,
stream = Stream,
headers_as_is = headers_as_is(Headers0, Options),
socket_opts = SocketOpts,
started = Started,
+ unix_socket = UnixSocket,
ipv6_host_with_brackets = BracketedHost},
-
case httpc_manager:request(Request, profile_name(Profile)) of
{ok, RequestId} ->
handle_answer(RequestId, Sync, Options);
@@ -565,14 +576,31 @@ handle_request(Method, Url,
Error
end.
+
+add_question_mark(<<>>) ->
+ <<>>;
+add_question_mark([]) ->
+ [];
+add_question_mark(Comp) when is_binary(Comp) ->
+ <<$?, Comp/binary>>;
+add_question_mark(Comp) when is_list(Comp) ->
+ [$?|Comp].
+
+
+scheme_to_atom("http") ->
+ http;
+scheme_to_atom("https") ->
+ https;
+scheme_to_atom('') ->
+ '';
+scheme_to_atom(Scheme) ->
+ throw({error, {bad_scheme, Scheme}}).
+
+
ensure_chunked_encoding(Hdrs) ->
Key = "transfer-encoding",
lists:keystore(Key, 1, Hdrs, {Key, "chunked"}).
-maybe_encode_uri(#http_options{url_encode = true}, URI) ->
- http_uri:encode(URI);
-maybe_encode_uri(_, URI) ->
- URI.
mk_chunkify_fun(ProcessBody) ->
fun(eof_body) ->
@@ -798,7 +826,7 @@ request_options_defaults() ->
error
end,
- VerifyBrackets = VerifyBoolean,
+ VerifyBrackets = VerifyBoolean,
[
{sync, true, VerifySync},
@@ -869,11 +897,36 @@ request_options_sanity_check(Opts) ->
end,
ok.
-validate_options(Options) ->
- (catch validate_options(Options, [])).
-
-validate_options([], ValidateOptions) ->
- {ok, lists:reverse(ValidateOptions)};
+validate_ipfamily_unix_socket(Options0) ->
+ IpFamily = proplists:get_value(ipfamily, Options0, inet),
+ UnixSocket = proplists:get_value(unix_socket, Options0, undefined),
+ Options1 = proplists:delete(ipfamily, Options0),
+ Options2 = proplists:delete(ipfamily, Options1),
+ validate_ipfamily_unix_socket(IpFamily, UnixSocket, Options2,
+ [{ipfamily, IpFamily}, {unix_socket, UnixSocket}]).
+%%
+validate_ipfamily_unix_socket(local, undefined, _Options, _Acc) ->
+ bad_option(unix_socket, undefined);
+validate_ipfamily_unix_socket(IpFamily, UnixSocket, _Options, _Acc)
+ when IpFamily =/= local, UnixSocket =/= undefined ->
+ bad_option(ipfamily, IpFamily);
+validate_ipfamily_unix_socket(IpFamily, UnixSocket, Options, Acc) ->
+ validate_ipfamily(IpFamily),
+ validate_unix_socket(UnixSocket),
+ {Options, Acc}.
+
+
+validate_options(Options0) ->
+ try
+ {Options, Acc} = validate_ipfamily_unix_socket(Options0),
+ validate_options(Options, Acc)
+ catch
+ error:Reason ->
+ {error, Reason}
+ end.
+%%
+validate_options([], ValidOptions) ->
+ {ok, lists:reverse(ValidOptions)};
validate_options([{proxy, Proxy} = Opt| Tail], Acc) ->
validate_proxy(Proxy),
@@ -933,6 +986,10 @@ validate_options([{verbose, Value} = Opt| Tail], Acc) ->
validate_verbose(Value),
validate_options(Tail, [Opt | Acc]);
+validate_options([{unix_socket, Value} = Opt| Tail], Acc) ->
+ validate_unix_socket(Value),
+ validate_options(Tail, [Opt | Acc]);
+
validate_options([{_, _} = Opt| _], _Acc) ->
{error, {not_an_option, Opt}}.
@@ -1001,7 +1058,8 @@ validate_ipv6(BadValue) ->
bad_option(ipv6, BadValue).
validate_ipfamily(Value)
- when (Value =:= inet) orelse (Value =:= inet6) orelse (Value =:= inet6fb4) ->
+ when (Value =:= inet) orelse (Value =:= inet6) orelse
+ (Value =:= inet6fb4) orelse (Value =:= local) ->
Value;
validate_ipfamily(BadValue) ->
bad_option(ipfamily, BadValue).
@@ -1031,6 +1089,15 @@ validate_verbose(Value)
validate_verbose(BadValue) ->
bad_option(verbose, BadValue).
+validate_unix_socket(Value)
+ when (Value =:= undefined) ->
+ Value;
+validate_unix_socket(Value)
+ when is_list(Value) andalso length(Value) > 0 ->
+ Value;
+validate_unix_socket(BadValue) ->
+ bad_option(unix_socket, BadValue).
+
bad_option(Option, BadValue) ->
throw({error, {bad_option, Option, BadValue}}).
@@ -1190,17 +1257,6 @@ validate_headers(RequestHeaders, _, _) ->
%% These functions is just simple wrappers to parse specifically HTTP URIs
%%--------------------------------------------------------------------------
-scheme_defaults() ->
- [{http, 80}, {https, 443}].
-
-uri_parse(URI) ->
- http_uri:parse(URI, [{scheme_defaults, scheme_defaults()}]).
-
-uri_parse(URI, Opts) ->
- http_uri:parse(URI, [{scheme_defaults, scheme_defaults()} | Opts]).
-
-
-%%--------------------------------------------------------------------------
header_parse([]) ->
ok;
header_parse([{Field, Value}|T]) when is_list(Field), is_list(Value) ->
@@ -1221,10 +1277,6 @@ child_name(Pid, [{Name, Pid} | _]) ->
child_name(Pid, [_ | Children]) ->
child_name(Pid, Children).
-host_address(Host, false) ->
- Host;
-host_address(Host, true) ->
- string:strip(string:strip(Host, right, $]), left, $[).
check_body_gen({Fun, _}) when is_function(Fun) ->
ok;
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index bd1d2e833a..1bf5d25c98 100644
--- a/lib/inets/src/http_client/httpc_handler.erl
+++ b/lib/inets/src/http_client/httpc_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -48,19 +48,17 @@
queue_timer :: reference() | 'undefined'
}).
--type session_failed() :: {'connect_failed',term()} | {'send_failed',term()}.
-
-record(state,
{
request :: request() | 'undefined',
- session :: session() | session_failed() | 'undefined',
+ session :: session() | 'undefined',
status_line, % {Version, StatusCode, ReasonPharse}
headers :: http_response_h() | 'undefined',
body :: binary() | 'undefined',
mfa, % {Module, Function, Args}
pipeline = queue:new() :: queue:queue(),
keep_alive = queue:new() :: queue:queue(),
- status, % undefined | new | pipeline | keep_alive | close | {ssl_tunnel, Request}
+ status :: undefined | new | pipeline | keep_alive | close | {ssl_tunnel, request()},
canceled = [], % [RequestId]
max_header_size = nolimit :: nolimit | integer(),
max_body_size = nolimit :: nolimit | integer(),
@@ -109,7 +107,7 @@ start_link(Parent, Request, Options, ProfileName) ->
%% to be called by the httpc manager process.
%%--------------------------------------------------------------------
send(Request, Pid) ->
- call(Request, Pid, 5000).
+ call(Request, Pid).
%%--------------------------------------------------------------------
@@ -255,8 +253,8 @@ handle_call(Request, From, State) ->
Result ->
Result
catch
- _:Reason ->
- {stop, {shutdown, Reason} , State}
+ Class:Reason:ST ->
+ {stop, {shutdown, {{Class, Reason}, ST}}, State}
end.
@@ -271,8 +269,8 @@ handle_cast(Msg, State) ->
Result ->
Result
catch
- _:Reason ->
- {stop, {shutdown, Reason} , State}
+ Class:Reason:ST ->
+ {stop, {shutdown, {{Class, Reason}, ST}}, State}
end.
%%--------------------------------------------------------------------
@@ -286,8 +284,8 @@ handle_info(Info, State) ->
Result ->
Result
catch
- _:Reason ->
- {stop, {shutdown, Reason} , State}
+ Class:Reason:ST ->
+ {stop, {shutdown, {{Class, Reason}, ST}}, State}
end.
%%--------------------------------------------------------------------
@@ -295,23 +293,6 @@ handle_info(Info, State) ->
%% Description: Shutdown the httpc_handler
%%--------------------------------------------------------------------
-%% Init error there is no socket to be closed.
-terminate(normal,
- #state{request = Request,
- session = {send_failed, _} = Reason} = State) ->
- maybe_send_answer(Request,
- httpc_response:error(Request, Reason),
- State),
- ok;
-
-terminate(normal,
- #state{request = Request,
- session = {connect_failed, _} = Reason} = State) ->
- maybe_send_answer(Request,
- httpc_response:error(Request, Reason),
- State),
- ok;
-
terminate(normal, #state{session = undefined}) ->
ok;
@@ -588,11 +569,11 @@ do_handle_info({Proto, _Socket, Data},
activate_once(Session),
{noreply, State#state{mfa = NewMFA}}
catch
- _:Reason ->
+ Class:Reason:ST ->
ClientReason = {could_not_parse_as_http, Data},
ClientErrMsg = httpc_response:error(Request, ClientReason),
NewState = answer_request(Request, ClientErrMsg, State),
- {stop, {shutdown, Reason}, NewState}
+ {stop, {shutdown, {{Class, Reason}, ST}}, NewState}
end;
do_handle_info({Proto, Socket, Data},
@@ -711,13 +692,17 @@ do_handle_info({'EXIT', _, _}, State = #state{request = undefined}) ->
%% can retry requests in the pipeline.
do_handle_info({'EXIT', _, _}, State) ->
{noreply, State#state{status = close}}.
-
call(Msg, Pid) ->
- call(Msg, Pid, infinity).
-
-call(Msg, Pid, Timeout) ->
- gen_server:call(Pid, Msg, Timeout).
+ try gen_server:call(Pid, Msg, infinity)
+ catch
+ exit:{noproc, _} ->
+ {error, closed};
+ exit:{normal, _} ->
+ {error, closed};
+ exit:{{shutdown, _},_} ->
+ {error, closed}
+ end.
cast(Msg, Pid) ->
gen_server:cast(Pid, Msg).
@@ -736,7 +721,7 @@ maybe_send_answer(Request, Answer, State) ->
answer_request(Request, Answer, State).
deliver_answer(#request{from = From} = Request)
- when is_pid(From) ->
+ when From =/= answer_sent ->
Response = httpc_response:error(Request, socket_closed_remotely),
httpc_response:send(From, Response);
deliver_answer(_Request) ->
@@ -750,6 +735,7 @@ connect(SocketType, ToAddress,
#options{ipfamily = IpFamily,
ip = FromAddress,
port = FromPort,
+ unix_socket = UnixSocket,
socket_opts = Opts0}, Timeout) ->
Opts1 =
case FromPort of
@@ -785,6 +771,16 @@ connect(SocketType, ToAddress,
OK ->
OK
end;
+ local ->
+ Opts3 = [IpFamily | Opts2],
+ SocketAddr = {local, UnixSocket},
+ case http_transport:connect(SocketType, {SocketAddr, 0}, Opts3, Timeout) of
+ {error, Reason} ->
+ {error, {failed_connect, [{to_address, SocketAddr},
+ {IpFamily, Opts3, Reason}]}};
+ Else ->
+ Else
+ end;
_ ->
Opts3 = [IpFamily | Opts2],
case http_transport:connect(SocketType, ToAddress, Opts3, Timeout) of
@@ -796,9 +792,23 @@ connect(SocketType, ToAddress,
end
end.
-connect_and_send_first_request(Address, Request, #state{options = Options} = State) ->
+handle_unix_socket_options(#request{unix_socket = UnixSocket}, Options)
+ when UnixSocket =:= undefined ->
+ Options;
+
+handle_unix_socket_options(#request{unix_socket = UnixSocket},
+ Options = #options{ipfamily = IpFamily}) ->
+ case IpFamily of
+ local ->
+ Options#options{unix_socket = UnixSocket};
+ Else ->
+ error({badarg, [{ipfamily, Else}, {unix_socket, UnixSocket}]})
+ end.
+
+connect_and_send_first_request(Address, Request, #state{options = Options0} = State) ->
SocketType = socket_type(Request),
ConnTimeout = (Request#request.settings)#http_options.connect_timeout,
+ Options = handle_unix_socket_options(Request, Options0),
case connect(SocketType, Address, Options, ConnTimeout) of
{ok, Socket} ->
ClientClose =
@@ -829,7 +839,7 @@ connect_and_send_first_request(Address, Request, #state{options = Options} = Sta
self() ! {init_error, error_sending,
httpc_response:error(Request, Reason)},
{ok, State#state{request = Request,
- session = #session{socket = Socket}}}
+ session = Session}}
end;
{error, Reason} ->
self() ! {init_error, error_connecting,
@@ -837,9 +847,10 @@ connect_and_send_first_request(Address, Request, #state{options = Options} = Sta
{ok, State#state{request = Request}}
end.
-connect_and_send_upgrade_request(Address, Request, #state{options = Options} = State) ->
+connect_and_send_upgrade_request(Address, Request, #state{options = Options0} = State) ->
ConnTimeout = (Request#request.settings)#http_options.connect_timeout,
SocketType = ip_comm,
+ Options = handle_unix_socket_options(Request, Options0),
case connect(SocketType, Address, Options, ConnTimeout) of
{ok, Socket} ->
SessionType = httpc_manager:session_type(Options),
@@ -950,13 +961,23 @@ handle_http_body(_, #state{status = {ssl_tunnel, Request},
NewState = answer_request(Request, ClientErrMsg, State),
{stop, normal, NewState};
-handle_http_body(<<>>, #state{status_line = {_,304, _}} = State) ->
+%% All 1xx (informational), 204 (no content), and 304 (not modified)
+%% responses MUST NOT include a message-body, and thus are always
+%% terminated by the first empty line after the header fields.
+%% This implies that chunked encoding MUST NOT be used for these
+%% status codes.
+handle_http_body(<<>>, #state{headers = Headers,
+ status_line = {_,StatusCode, _}} = State)
+ when Headers#http_response_h.'transfer-encoding' =/= "chunked" andalso
+ (StatusCode =:= 204 orelse %% No Content
+ StatusCode =:= 304 orelse %% Not Modified
+ 100 =< StatusCode andalso StatusCode =< 199) -> %% Informational
handle_response(State#state{body = <<>>});
-handle_http_body(<<>>, #state{status_line = {_,204, _}} = State) ->
- handle_response(State#state{body = <<>>});
-handle_http_body(<<>>, #state{request = #request{method = head}} = State) ->
+handle_http_body(<<>>, #state{headers = Headers,
+ request = #request{method = head}} = State)
+ when Headers#http_response_h.'transfer-encoding' =/= "chunked" ->
handle_response(State#state{body = <<>>});
handle_http_body(Body, #state{headers = Headers,
@@ -1028,15 +1049,15 @@ handle_response(#state{status = new} = State) ->
?hcrd("handle response - status = new", []),
handle_response(try_to_enable_pipeline_or_keep_alive(State));
-handle_response(#state{request = Request,
- status = Status,
- session = Session,
- status_line = StatusLine,
- headers = Headers,
- body = Body,
- options = Options,
- profile_name = ProfileName} = State)
- when Status =/= new ->
+handle_response(#state{status = Status0} = State0) when Status0 =/= new ->
+ State = handle_server_closing(State0),
+ #state{request = Request,
+ session = Session,
+ status_line = StatusLine,
+ headers = Headers,
+ body = Body,
+ options = Options,
+ profile_name = ProfileName} = State,
handle_cookies(Headers, Request, Options, ProfileName),
case httpc_response:result({StatusLine, Headers, Body}, Request) of
%% 100-continue
@@ -1300,6 +1321,14 @@ try_to_enable_pipeline_or_keep_alive(
State#state{status = close}
end.
+handle_server_closing(State = #state{status = close}) -> State;
+handle_server_closing(State = #state{headers = undefined}) -> State;
+handle_server_closing(State = #state{headers = Headers}) ->
+ case httpc_response:is_server_closing(Headers) of
+ true -> State#state{status = close};
+ false -> State
+ end.
+
answer_request(#request{id = RequestId, from = From} = Request, Msg,
#state{session = Session,
timers = Timers,
@@ -1681,9 +1710,8 @@ update_session(ProfileName, #session{id = SessionId} = Session, Pos, Value) ->
insert_session(Session2, ProfileName);
error:badarg ->
{stop, normal};
- T:E ->
+ T:E:Stacktrace ->
%% Unexpected this must be an error!
- Stacktrace = erlang:get_stacktrace(),
error_logger:error_msg("Failed updating session: "
"~n ProfileName: ~p"
"~n SessionId: ~p"
diff --git a/lib/inets/src/http_client/httpc_internal.hrl b/lib/inets/src/http_client/httpc_internal.hrl
index 5f8c70f28d..a14d8aa71b 100644
--- a/lib/inets/src/http_client/httpc_internal.hrl
+++ b/lib/inets/src/http_client/httpc_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -83,10 +83,11 @@
max_sessions = ?HTTP_MAX_TCP_SESSIONS,
cookies = disabled, % enabled | disabled | verify
verbose = false, % boolean(),
- ipfamily = inet, % inet | inet6 | inet6fb4
+ ipfamily = inet, % inet | inet6 | inet6fb4 | local
ip = default, % specify local interface
port = default, % specify local port
- socket_opts = [] % other socket options
+ socket_opts = [], % other socket options
+ unix_socket = undefined % Local unix socket
}
).
-type options() :: #options{}.
@@ -115,6 +116,7 @@
% request
timer :: undefined | reference(),
socket_opts, % undefined | [socket_option()]
+ unix_socket, % undefined | string()
ipv6_host_with_brackets % boolean()
}
).
diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl
index a63864493f..0333442bf2 100644
--- a/lib/inets/src/http_client/httpc_manager.erl
+++ b/lib/inets/src/http_client/httpc_manager.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -553,7 +553,8 @@ handle_cast({set_options, Options}, State = #state{options = OldOptions}) ->
ip = get_ip(Options, OldOptions),
port = get_port(Options, OldOptions),
verbose = get_verbose(Options, OldOptions),
- socket_opts = get_socket_opts(Options, OldOptions)
+ socket_opts = get_socket_opts(Options, OldOptions),
+ unix_socket = get_unix_socket_opts(Options, OldOptions)
},
case {OldOptions#options.verbose, NewOptions#options.verbose} of
{Same, Same} ->
@@ -749,8 +750,26 @@ handle_request(#request{settings =
start_handler(NewRequest#request{headers = NewHeaders}, State),
{reply, {ok, NewRequest#request.id}, State};
-handle_request(Request, State = #state{options = Options}) ->
+%% Simple socket options handling (ERL-441).
+%%
+%% TODO: Refactor httpc to enable sending socket options in requests
+%% using persistent connections. This workaround opens a new
+%% connection for each request with non-empty socket_opts.
+handle_request(Request0 = #request{socket_opts = SocketOpts},
+ State0 = #state{options = Options0})
+ when is_list(SocketOpts) andalso length(SocketOpts) > 0 ->
+ Request = handle_cookies(generate_request_id(Request0), State0),
+ Options = convert_options(SocketOpts, Options0),
+ State = State0#state{options = Options},
+ Headers =
+ (Request#request.headers)#http_request_h{connection
+ = "close"},
+ %% Reset socket_opts to avoid setopts failure.
+ start_handler(Request#request{headers = Headers, socket_opts = []}, State),
+ %% Do not change the state
+ {reply, {ok, Request#request.id}, State0};
+handle_request(Request, State = #state{options = Options}) ->
NewRequest = handle_cookies(generate_request_id(Request), State),
SessionType = session_type(Options),
case select_session(Request#request.method,
@@ -774,6 +793,18 @@ handle_request(Request, State = #state{options = Options}) ->
{reply, {ok, NewRequest#request.id}, State}.
+%% Convert Request options to State options
+convert_options([], Options) ->
+ Options;
+convert_options([{ipfamily, Value}|T], Options) ->
+ convert_options(T, Options#options{ipfamily = Value});
+convert_options([{ip, Value}|T], Options) ->
+ convert_options(T, Options#options{ip = Value});
+convert_options([{port, Value}|T], Options) ->
+ convert_options(T, Options#options{port = Value});
+convert_options([Option|T], Options = #options{socket_opts = SocketOpts}) ->
+ convert_options(T, Options#options{socket_opts = SocketOpts ++ [Option]}).
+
start_handler(#request{id = Id,
from = From} = Request,
#state{profile_name = ProfileName,
@@ -849,11 +880,11 @@ pipeline_or_keep_alive(#request{id = Id,
from = From} = Request,
HandlerPid,
#state{handler_db = HandlerDb} = State) ->
- case (catch httpc_handler:send(Request, HandlerPid)) of
+ case httpc_handler:send(Request, HandlerPid) of
ok ->
HandlerInfo = {Id, HandlerPid, From},
ets:insert(HandlerDb, HandlerInfo);
- _ -> % timeout pipelining failed
+ {error, closed} -> % timeout pipelining failed
start_handler(Request, State)
end.
@@ -963,7 +994,10 @@ get_option(ip, #options{ip = IP}) ->
get_option(port, #options{port = Port}) ->
Port;
get_option(socket_opts, #options{socket_opts = SocketOpts}) ->
- SocketOpts.
+ SocketOpts;
+get_option(unix_socket, #options{unix_socket = UnixSocket}) ->
+ UnixSocket.
+
get_proxy(Opts, #options{proxy = Default}) ->
proplists:get_value(proxy, Opts, Default).
@@ -1016,6 +1050,8 @@ get_verbose(Opts, #options{verbose = Default}) ->
get_socket_opts(Opts, #options{socket_opts = Default}) ->
proplists:get_value(socket_opts, Opts, Default).
+get_unix_socket_opts(Opts, #options{unix_socket = Default}) ->
+ proplists:get_value(unix_socket, Opts, Default).
handle_verbose(debug) ->
dbg:p(self(), [call]),
diff --git a/lib/inets/src/http_client/httpc_request.erl b/lib/inets/src/http_client/httpc_request.erl
index 89872a3831..0f20d93bc1 100644
--- a/lib/inets/src/http_client/httpc_request.erl
+++ b/lib/inets/src/http_client/httpc_request.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -190,35 +190,11 @@ is_client_closing(Headers) ->
%%%========================================================================
post_data(Method, Headers, {ContentType, Body}, HeadersAsIs)
when (Method =:= post)
- orelse (Method =:= put)
- orelse (Method =:= patch)
- orelse (Method =:= delete) ->
-
- NewBody = case Headers#http_request_h.expect of
- "100-continue" ->
- "";
- _ ->
- Body
- end,
-
- NewHeaders = case HeadersAsIs of
- [] ->
- Headers#http_request_h{
- 'content-type' = ContentType,
- 'content-length' = case body_length(Body) of
- undefined ->
- % on upload streaming the caller must give a
- % value to the Content-Length header
- % (or use chunked Transfer-Encoding)
- Headers#http_request_h.'content-length';
- Len when is_list(Len) ->
- Len
- end
- };
- _ ->
- HeadersAsIs
- end,
-
+ orelse (Method =:= put)
+ orelse (Method =:= patch)
+ orelse (Method =:= delete) ->
+ NewBody = update_body(Headers, Body),
+ NewHeaders = update_headers(Headers, ContentType, Body, HeadersAsIs),
{NewHeaders, NewBody};
post_data(_, Headers, _, []) ->
@@ -226,14 +202,56 @@ post_data(_, Headers, _, []) ->
post_data(_, _, _, HeadersAsIs = [_|_]) ->
{HeadersAsIs, ""}.
+update_body(Headers, Body) ->
+ case Headers#http_request_h.expect of
+ "100-continue" ->
+ "";
+ _ ->
+ Body
+ end.
+
+update_headers(Headers, ContentType, Body, []) ->
+ case Body of
+ [] ->
+ Headers1 = Headers#http_request_h{'content-length' = "0"},
+ handle_content_type(Headers1, ContentType);
+ <<>> ->
+ Headers1 = Headers#http_request_h{'content-length' = "0"},
+ handle_content_type(Headers1, ContentType);
+ {Fun, _Acc} when is_function(Fun, 1) ->
+ %% A client MUST NOT generate a 100-continue expectation in a request
+ %% that does not include a message body. This implies that either the
+ %% Content-Length or the Transfer-Encoding header MUST be present.
+ %% DO NOT send content-type when Body is empty.
+ Headers1 = Headers#http_request_h{'content-type' = ContentType},
+ handle_transfer_encoding(Headers1);
+ _ ->
+ Headers#http_request_h{
+ 'content-length' = body_length(Body),
+ 'content-type' = ContentType}
+ end;
+update_headers(_, _, _, HeadersAsIs) ->
+ HeadersAsIs.
+
+handle_transfer_encoding(Headers = #http_request_h{'transfer-encoding' = undefined}) ->
+ Headers;
+handle_transfer_encoding(Headers) ->
+ %% RFC7230 3.3.2
+ %% A sender MUST NOT send a 'Content-Length' header field in any message
+ %% that contains a 'Transfer-Encoding' header field.
+ Headers#http_request_h{'content-length' = undefined}.
+
body_length(Body) when is_binary(Body) ->
integer_to_list(size(Body));
body_length(Body) when is_list(Body) ->
- integer_to_list(length(Body));
+ integer_to_list(length(Body)).
-body_length({DataFun, _Acc}) when is_function(DataFun, 1) ->
- undefined.
+%% Set 'Content-Type' when it is explicitly set.
+handle_content_type(Headers, "") ->
+ Headers;
+handle_content_type(Headers, ContentType) ->
+ Headers#http_request_h{'content-type' = ContentType}.
method(Method) ->
http_util:to_upper(atom_to_list(Method)).
diff --git a/lib/inets/src/http_client/httpc_response.erl b/lib/inets/src/http_client/httpc_response.erl
index b3b11b74ab..78d6b4ed24 100644
--- a/lib/inets/src/http_client/httpc_response.erl
+++ b/lib/inets/src/http_client/httpc_response.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -83,7 +83,6 @@ whole_body(Body, Length) ->
%% result(Response, Request) ->
%% Response - {StatusLine, Headers, Body}
%% Request - #request{}
-%% Session - #tcp_session{}
%%
%% Description: Checks the status code ...
%%-------------------------------------------------------------------------
@@ -190,7 +189,7 @@ parse_status_code(<<?CR, ?LF, Rest/binary>>, StatusCodeStr,
MaxHeaderSize, Result, true) ->
parse_headers(Rest, [], [], MaxHeaderSize,
[" ", list_to_integer(lists:reverse(
- string:strip(StatusCodeStr)))
+ string:trim(StatusCodeStr)))
| Result], true);
parse_status_code(<<?SP, Rest/binary>>, StatusCodeStr,
@@ -269,7 +268,7 @@ parse_headers(<<?LF,?LF,Body/binary>>, Header, Headers,
MaxHeaderSize, Result, Relaxed);
parse_headers(<<?CR,?LF,?CR,?LF,Body/binary>>, Header, Headers,
- MaxHeaderSize, Result, _) ->
+ MaxHeaderSize, Result, Relaxed) ->
HTTPHeaders = [lists:reverse(Header) | Headers],
Length = lists:foldl(fun(H, Acc) -> length(H) + Acc end,
0, HTTPHeaders),
@@ -277,8 +276,42 @@ parse_headers(<<?CR,?LF,?CR,?LF,Body/binary>>, Header, Headers,
true ->
ResponseHeaderRcord =
http_response:headers(HTTPHeaders, #http_response_h{}),
- {ok, list_to_tuple(
- lists:reverse([Body, ResponseHeaderRcord | Result]))};
+
+ %% RFC7230, Section 3.3.3
+ %% If a message is received with both a Transfer-Encoding and a
+ %% Content-Length header field, the Transfer-Encoding overrides the
+ %% Content-Length. Such a message might indicate an attempt to
+ %% perform request smuggling (Section 9.5) or response splitting
+ %% (Section 9.4) and ought to be handled as an error. A sender MUST
+ %% remove the received Content-Length field prior to forwarding such
+ %% a message downstream.
+ case ResponseHeaderRcord#http_response_h.'transfer-encoding' of
+ undefined ->
+ {ok, list_to_tuple(
+ lists:reverse([Body, ResponseHeaderRcord | Result]))};
+ Value ->
+ TransferEncoding = string:lowercase(Value),
+ ContentLength = ResponseHeaderRcord#http_response_h.'content-length',
+ if
+ %% Respond without error but remove Content-Length field in relaxed mode
+ (Relaxed =:= true)
+ andalso (TransferEncoding =:= "chunked")
+ andalso (ContentLength =/= "-1") ->
+ ResponseHeaderRcordFixed =
+ ResponseHeaderRcord#http_response_h{'content-length' = "-1"},
+ {ok, list_to_tuple(
+ lists:reverse([Body, ResponseHeaderRcordFixed | Result]))};
+ %% Respond with error in default (not relaxed) mode
+ (Relaxed =:= false)
+ andalso (TransferEncoding =:= "chunked")
+ andalso (ContentLength =/= "-1") ->
+ throw({error, {headers_conflict, {'content-length',
+ 'transfer-encoding'}}});
+ true ->
+ {ok, list_to_tuple(
+ lists:reverse([Body, ResponseHeaderRcord | Result]))}
+ end
+ end;
false ->
throw({error, {header_too_long, MaxHeaderSize,
MaxHeaderSize-Length}})
@@ -343,58 +376,172 @@ status_server_error_50x(Response, Request) ->
{stop, {Request#request.id, Msg}}.
-redirect(Response = {StatusLine, Headers, Body}, Request) ->
+redirect(Response = {_, Headers, _}, Request) ->
{_, Data} = format_response(Response),
case Headers#http_response_h.location of
- undefined ->
- transparent(Response, Request);
- RedirUrl ->
- UrlParseOpts = [{ipv6_host_with_brackets,
- Request#request.ipv6_host_with_brackets}],
- case uri_parse(RedirUrl, UrlParseOpts) of
- {error, no_scheme} when
- (Request#request.settings)#http_options.relaxed ->
- NewLocation = fix_relative_uri(Request, RedirUrl),
- redirect({StatusLine, Headers#http_response_h{
- location = NewLocation},
- Body}, Request);
- {error, Reason} ->
- {ok, error(Request, Reason), Data};
- %% Automatic redirection
- {ok, {Scheme, _, Host, Port, Path, Query}} ->
- HostPort = http_request:normalize_host(Scheme, Host, Port),
- NewHeaders =
- (Request#request.headers)#http_request_h{host = HostPort},
- NewRequest =
- Request#request{redircount =
- Request#request.redircount+1,
- scheme = Scheme,
- headers = NewHeaders,
- address = {Host,Port},
- path = Path,
- pquery = Query,
- abs_uri =
- atom_to_list(Scheme) ++ "://" ++
- Host ++ ":" ++
- integer_to_list(Port) ++
- Path ++ Query},
- {redirect, NewRequest, Data}
- end
+ undefined ->
+ transparent(Response, Request);
+ RedirUrl ->
+ Brackets = Request#request.ipv6_host_with_brackets,
+ case uri_string:parse(RedirUrl) of
+ {error, Reason, _} ->
+ {ok, error(Request, Reason), Data};
+ %% Automatic redirection
+ URI ->
+ {Host, Port0} = Request#request.address,
+ Port = maybe_to_integer(Port0),
+ Path = Request#request.path,
+ Scheme = atom_to_list(Request#request.scheme),
+ Query = Request#request.pquery,
+ URIMap = resolve_uri(Scheme, Host, Port, Path, Query, URI),
+ TScheme = list_to_atom(maps:get(scheme, URIMap)),
+ THost = http_util:maybe_add_brackets(maps:get(host, URIMap), Brackets),
+ TPort = maps:get(port, URIMap),
+ TPath = maps:get(path, URIMap),
+ TQuery = maps:get(query, URIMap, ""),
+ NewURI = uri_string:normalize(
+ uri_string:recompose(URIMap)),
+ HostPort = http_request:normalize_host(TScheme, THost, TPort),
+ NewHeaders =
+ (Request#request.headers)#http_request_h{host = HostPort},
+ NewRequest =
+ Request#request{redircount =
+ Request#request.redircount+1,
+ scheme = TScheme,
+ headers = NewHeaders,
+ address = {THost,TPort},
+ path = TPath,
+ pquery = TQuery,
+ abs_uri = NewURI},
+ {redirect, NewRequest, Data}
+ end
+ end.
+
+
+%% RFC3986 - 5.2.2. Transform References
+resolve_uri(Scheme, Host, Port, Path, Query, URI) ->
+ resolve_uri(Scheme, Host, Port, Path, Query, URI, #{}).
+%%
+resolve_uri(Scheme, Host, Port, Path, Query, URI, Map0) ->
+ case maps:get(scheme, URI, undefined) of
+ undefined ->
+ Port0 = get_port(Scheme, URI),
+ Map = Map0#{scheme => Scheme,
+ port => Port0},
+ resolve_authority(Host, Port, Path, Query, URI, Map);
+ URIScheme ->
+ Port0 = get_port(URIScheme, URI),
+ maybe_add_query(
+ Map0#{scheme => URIScheme,
+ host => maps:get(host, URI),
+ port => Port0,
+ path => maps:get(path, URI)},
+ URI)
+ end.
+
+
+get_port(Scheme, URI) ->
+ case maps:get(port, URI, undefined) of
+ undefined ->
+ get_default_port(Scheme);
+ Port ->
+ Port
+ end.
+
+
+get_default_port("http") ->
+ 80;
+get_default_port("https") ->
+ 443.
+
+
+resolve_authority(Host, Port, Path, Query, RelURI, Map) ->
+ case maps:is_key(host, RelURI) of
+ true ->
+ maybe_add_query(
+ Map#{host => maps:get(host, RelURI),
+ path => maps:get(path, RelURI)},
+ RelURI);
+ false ->
+ Map1 = Map#{host => Host,
+ port => Port},
+ resolve_path(Path, Query, RelURI, Map1)
+ end.
+
+
+maybe_add_query(Map, RelURI) ->
+ case maps:is_key(query, RelURI) of
+ true ->
+ Map#{query => maps:get(query, RelURI)};
+ false ->
+ Map
+ end.
+
+
+resolve_path(Path, Query, RelURI, Map) ->
+ case maps:is_key(path, RelURI) of
+ true ->
+ Path1 = calculate_path(Path, maps:get(path, RelURI)),
+ maybe_add_query(
+ Map#{path => Path1},
+ RelURI);
+ false ->
+ Map1 = Map#{path => Path},
+ resolve_query(Query, RelURI, Map1)
+ end.
+
+
+calculate_path(BaseP, RelP) ->
+ case starts_with_slash(RelP) of
+ true ->
+ RelP;
+ false ->
+ merge_paths(BaseP, RelP)
+ end.
+
+
+starts_with_slash([$/|_]) ->
+ true;
+starts_with_slash(<<$/,_/binary>>) ->
+ true;
+starts_with_slash(_) ->
+ false.
+
+
+%% RFC3986 - 5.2.3. Merge Paths
+merge_paths("", RelP) ->
+ [$/|RelP];
+merge_paths(BaseP, RelP) when is_list(BaseP) ->
+ do_merge_paths(lists:reverse(BaseP), RelP);
+merge_paths(BaseP, RelP) when is_binary(BaseP) ->
+ B = binary_to_list(BaseP),
+ R = binary_to_list(RelP),
+ Res = merge_paths(B, R),
+ list_to_binary(Res).
+
+
+do_merge_paths([$/|_] = L, RelP) ->
+ lists:reverse(L) ++ RelP;
+do_merge_paths([_|T], RelP) ->
+ do_merge_paths(T, RelP).
+
+
+resolve_query(Query, RelURI, Map) ->
+ case maps:is_key(query, RelURI) of
+ true ->
+ Map#{query => maps:get(query, RelURI)};
+ false ->
+ Map#{query => Query}
end.
-maybe_to_list(Port) when is_integer(Port) ->
- integer_to_list(Port);
-maybe_to_list(Port) when is_list(Port) ->
+
+maybe_to_integer(Port) when is_list(Port) ->
+ {Port1, _} = string:to_integer(Port),
+ Port1;
+maybe_to_integer(Port) when is_integer(Port) ->
Port.
-%%% Guessing that we received a relative URI, fix it to become an absoluteURI
-fix_relative_uri(Request, RedirUrl) ->
- {Server, Port0} = Request#request.address,
- Port = maybe_to_list(Port0),
- Path = Request#request.path,
- atom_to_list(Request#request.scheme) ++ "://" ++ Server ++ ":" ++ Port
- ++ Path ++ RedirUrl.
-
+
error(#request{id = Id}, Reason) ->
{Id, {error, Reason}}.
@@ -444,18 +591,3 @@ format_response({StatusLine, Headers, Body}) ->
{Body, <<>>}
end,
{{StatusLine, http_response:header_list(Headers), NewBody}, Data}.
-
-%%--------------------------------------------------------------------------
-%% These functions is just simple wrappers to parse specifically HTTP URIs
-%%--------------------------------------------------------------------------
-
-scheme_defaults() ->
- [{http, 80}, {https, 443}].
-
-uri_parse(URI, Opts) ->
- http_uri:parse(URI, [{scheme_defaults, scheme_defaults()} | Opts]).
-
-
-%%--------------------------------------------------------------------------
-
-
diff --git a/lib/inets/src/http_lib/http_request.erl b/lib/inets/src/http_lib/http_request.erl
index f68b233e10..2b1a0bd40f 100644
--- a/lib/inets/src/http_lib/http_request.erl
+++ b/lib/inets/src/http_lib/http_request.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,10 +27,12 @@
key_value(KeyValueStr) ->
case lists:splitwith(fun($:) -> false; (_) -> true end, KeyValueStr) of
- {Key, [$: | Value]} ->
+ {Key, [$: | Value]} when Key =/= [] ->
{http_util:to_lower(string:strip(Key)), string:strip(Value)};
{_, []} ->
- undefined
+ undefined;
+ _ ->
+ undefined
end.
%%-------------------------------------------------------------------------
%% headers(HeaderList, #http_request_h{}) -> #http_request_h{}
diff --git a/lib/inets/src/http_lib/http_uri.erl b/lib/inets/src/http_lib/http_uri.erl
index c4be5abd7c..6805b0293d 100644
--- a/lib/inets/src/http_lib/http_uri.erl
+++ b/lib/inets/src/http_lib/http_uri.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -61,19 +61,35 @@
scheme_defaults/0,
encode/1, decode/1]).
--export_type([scheme/0, default_scheme_port_number/0]).
+-export_type([uri/0,
+ user_info/0,
+ scheme/0, default_scheme_port_number/0,
+ host/0,
+ path/0,
+ query/0,
+ fragment/0]).
+-type uri() :: string() | binary().
+-type user_info() :: string() | binary().
+-type scheme() :: atom().
+-type host() :: string() | binary().
+-type path() :: string() | binary().
+-type query() :: string() | binary().
+-type fragment() :: string() | binary().
+-type port_number() :: inet:port_number().
+-type default_scheme_port_number() :: port_number().
+-type hex_uri() :: string() | binary(). %% Hexadecimal encoded URI.
+-type maybe_hex_uri() :: string() | binary(). %% A possibly hexadecimal encoded URI.
+
+-type scheme_defaults() :: [{scheme(), default_scheme_port_number()}].
+-type scheme_validation_fun() :: fun((SchemeStr :: string() | binary()) ->
+ valid | {error, Reason :: term()}).
%%%=========================================================================
%%% API
%%%=========================================================================
--type scheme() :: atom().
--type default_scheme_port_number() :: pos_integer().
-
--spec scheme_defaults() ->
- [{scheme(), default_scheme_port_number()}].
-
+-spec scheme_defaults() -> scheme_defaults().
scheme_defaults() ->
[{http, 80},
{https, 443},
@@ -82,9 +98,20 @@ scheme_defaults() ->
{sftp, 22},
{tftp, 69}].
+-type parse_result() ::
+ {scheme(), user_info(), host(), port_number(), path(), query()} |
+ {scheme(), user_info(), host(), port_number(), path(), query(),
+ fragment()}.
+
+-spec parse(uri()) -> {ok, parse_result()} | {error, term()}.
parse(AbsURI) ->
parse(AbsURI, []).
+-spec parse(uri(), [Option]) -> {ok, parse_result()} | {error, term()} when
+ Option :: {ipv6_host_with_brackets, boolean()} |
+ {scheme_defaults, scheme_defaults()} |
+ {fragment, boolean()} |
+ {scheme_validation_fun, scheme_validation_fun() | none}.
parse(AbsURI, Opts) ->
case parse_scheme(AbsURI, Opts) of
{error, Reason} ->
@@ -105,6 +132,7 @@ reserved() ->
$#, $[, $], $<, $>, $\", ${, $}, $|, %"
$\\, $', $^, $%, $ ]).
+-spec encode(uri()) -> hex_uri().
encode(URI) when is_list(URI) ->
Reserved = reserved(),
lists:append([uri_encode(Char, Reserved) || Char <- URI]);
@@ -112,13 +140,12 @@ encode(URI) when is_binary(URI) ->
Reserved = reserved(),
<< <<(uri_encode_binary(Char, Reserved))/binary>> || <<Char>> <= URI >>.
+-spec decode(maybe_hex_uri()) -> uri().
decode(String) when is_list(String) ->
do_decode(String);
decode(String) when is_binary(String) ->
do_decode_binary(String).
-do_decode([$+|Rest]) ->
- [$ |do_decode(Rest)];
do_decode([$%,Hex1,Hex2|Rest]) ->
[hex2dec(Hex1)*16+hex2dec(Hex2)|do_decode(Rest)];
do_decode([First|Rest]) ->
@@ -126,8 +153,6 @@ do_decode([First|Rest]) ->
do_decode([]) ->
[].
-do_decode_binary(<<$+, Rest/bits>>) ->
- <<$ , (do_decode_binary(Rest))/binary>>;
do_decode_binary(<<$%, Hex:2/binary, Rest/bits>>) ->
<<(binary_to_integer(Hex, 16)), (do_decode_binary(Rest))/binary>>;
do_decode_binary(<<First:1/binary, Rest/bits>>) ->
@@ -172,7 +197,7 @@ extract_scheme(Str, Opts) ->
{value, {scheme_validation_fun, Fun}} when is_function(Fun) ->
case Fun(Str) of
valid ->
- {ok, list_to_atom(http_util:to_lower(Str))};
+ {ok, to_atom(http_util:to_lower(Str))};
{error, Error} ->
{error, Error}
end;
diff --git a/lib/inets/src/http_lib/http_util.erl b/lib/inets/src/http_lib/http_util.erl
index 487d04f7aa..5577b00cc8 100644
--- a/lib/inets/src/http_lib/http_util.erl
+++ b/lib/inets/src/http_lib/http_util.erl
@@ -27,7 +27,8 @@
convert_month/1,
is_hostname/1,
timestamp/0, timeout/2,
- html_encode/1
+ html_encode/1,
+ maybe_add_brackets/2
]).
@@ -194,6 +195,24 @@ html_encode(Chars) ->
lists:append([char_to_html_entity(Char, Reserved) || Char <- Chars]).
+maybe_add_brackets(Addr, false) ->
+ Addr;
+maybe_add_brackets(Addr, true) when is_list(Addr) ->
+ case is_ipv6_address(Addr) of
+ true ->
+ [$[|Addr] ++ "]";
+ false ->
+ Addr
+ end;
+maybe_add_brackets(Addr, true) when is_binary(Addr) ->
+ case is_ipv6_address(Addr) of
+ true ->
+ <<$[,Addr/binary,$]>>;
+ false ->
+ Addr
+ end.
+
+
%%%========================================================================
%%% Internal functions
%%%========================================================================
@@ -205,3 +224,14 @@ char_to_html_entity(Char, Reserved) ->
false ->
[Char]
end.
+
+is_ipv6_address(Addr) when is_binary(Addr) ->
+ B = binary_to_list(Addr),
+ is_ipv6_address(B);
+is_ipv6_address(Addr) when is_list(Addr) ->
+ case inet:parse_ipv6strict_address(Addr) of
+ {ok, _ } ->
+ true;
+ {error, _} ->
+ false
+ end.
diff --git a/lib/inets/src/http_server/httpd.erl b/lib/inets/src/http_server/httpd.erl
index 0b632d24e3..f4b53ce129 100644
--- a/lib/inets/src/http_server/httpd.erl
+++ b/lib/inets/src/http_server/httpd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,7 +36,13 @@
]).
%% API
--export([parse_query/1, reload_config/2, info/1, info/2, info/3]).
+-export([
+ parse_query/1,
+ reload_config/2,
+ info/1,
+ info/2,
+ info/3
+ ]).
%%%========================================================================
%%% API
@@ -49,13 +55,24 @@ parse_query(String) ->
reload_config(Config = [Value| _], Mode) when is_tuple(Value) ->
do_reload_config(Config, Mode);
reload_config(ConfigFile, Mode) ->
- case httpd_conf:load(ConfigFile) of
- {ok, ConfigList} ->
- do_reload_config(ConfigList, Mode);
- Error ->
- Error
+ try file:consult(ConfigFile) of
+ {ok, [PropList]} ->
+ %% Erlang terms format
+ do_reload_config(PropList, Mode);
+ {error, _ } ->
+ %% Apache format
+ case httpd_conf:load(ConfigFile) of
+ {ok, ConfigList} ->
+ do_reload_config(ConfigList, Mode);
+ Error ->
+ Error
+ end
+ catch
+ exit:_ ->
+ throw({error, {could_not_consult_proplist_file, ConfigFile}})
end.
+
info(Pid) when is_pid(Pid) ->
info(Pid, []).
@@ -99,7 +116,14 @@ start_service(Conf) ->
stop_service({Address, Port}) ->
stop_service({Address, Port, ?DEFAULT_PROFILE});
stop_service({Address, Port, Profile}) ->
- httpd_sup:stop_child(Address, Port, Profile);
+ Name = httpd_util:make_name("httpd_instance_sup", Address, Port, Profile),
+ Pid = whereis(Name),
+ MonitorRef = erlang:monitor(process, Pid),
+ Result = httpd_sup:stop_child(Address, Port, Profile),
+ receive
+ {'DOWN', MonitorRef, _, _, _} ->
+ Result
+ end;
stop_service(Pid) when is_pid(Pid) ->
case service_info(Pid) of
{ok, Info} ->
diff --git a/lib/inets/src/http_server/httpd_esi.erl b/lib/inets/src/http_server/httpd_esi.erl
index 9406b47802..3b66b86348 100644
--- a/lib/inets/src/http_server/httpd_esi.erl
+++ b/lib/inets/src/http_server/httpd_esi.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -66,7 +66,7 @@ handle_headers("") ->
{ok, [], 200};
handle_headers(Headers) ->
NewHeaders = string:tokens(Headers, ?CRLF),
- handle_headers(NewHeaders, [], 200).
+ handle_headers(NewHeaders, [], 200, true).
%%%========================================================================
%%% Internal functions
@@ -80,21 +80,17 @@ parse_headers([?CR, ?LF, ?CR, ?LF | Rest], Acc) ->
parse_headers([Char | Rest], Acc) ->
parse_headers(Rest, [Char | Acc]).
-handle_headers([], NewHeaders, StatusCode) ->
+handle_headers([], NewHeaders, StatusCode, _) ->
{ok, NewHeaders, StatusCode};
-handle_headers([Header | Headers], NewHeaders, StatusCode) ->
+handle_headers([Header | Headers], NewHeaders, StatusCode, NoESIStatus) ->
{FieldName, FieldValue} = httpd_response:split_header(Header, []),
case FieldName of
- "location" ->
- case http_request:is_absolut_uri(FieldValue) of
- true ->
- handle_headers(Headers,
- [{FieldName, FieldValue} | NewHeaders],
- 302);
- false ->
- {proceed, FieldValue}
- end;
+ "location" when NoESIStatus == true ->
+ handle_headers(Headers,
+ [{FieldName, FieldValue} | NewHeaders],
+ 302, NoESIStatus);
+
"status" ->
NewStatusCode =
case httpd_util:split(FieldValue," ",2) of
@@ -103,8 +99,9 @@ handle_headers([Header | Headers], NewHeaders, StatusCode) ->
_ ->
200
end,
- handle_headers(Headers, NewHeaders, NewStatusCode);
+ handle_headers(Headers, NewHeaders, NewStatusCode, false);
_ ->
handle_headers(Headers,
- [{FieldName, FieldValue}| NewHeaders], StatusCode)
- end.
+ [{FieldName, FieldValue}| NewHeaders], StatusCode,
+ NoESIStatus)
+ end.
diff --git a/lib/inets/src/http_server/httpd_example.erl b/lib/inets/src/http_server/httpd_example.erl
index c893b10dca..37e4f97bc0 100644
--- a/lib/inets/src/http_server/httpd_example.erl
+++ b/lib/inets/src/http_server/httpd_example.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,9 +20,9 @@
%%
-module(httpd_example).
-export([print/1]).
--export([get/2, put/2, post/2, yahoo/2, test1/2, get_bin/2, peer/2]).
+-export([get/2, put/2, post/2, yahoo/2, test1/2, get_bin/2, peer/2,new_status_and_location/2]).
--export([newformat/3]).
+-export([newformat/3, post_chunked/3, post_204/3]).
%% These are used by the inets test-suite
-export([delay/1, chunk_timeout/3]).
@@ -90,6 +90,9 @@ post(Env,Input) ->
yahoo(_Env,_Input) ->
"Location: http://www.yahoo.com\r\n\r\n".
+new_status_and_location(_Env,_Input) ->
+ "status:201 Created\r\n Location: http://www.yahoo.com\r\n\r\n".
+
default(Env,Input) ->
[header(),
top("Default Example"),
@@ -131,15 +134,37 @@ footer() ->
"</BODY>
</HTML>\n".
-
-newformat(SessionID, _Env, _Input)->
+post_chunked(_SessionID, _Env, {first, _Body} = _Bodychunk) ->
+ {continue, {state, 1}};
+post_chunked(_SessionID, _Env, {continue, _Body, {state, N}} = _Bodychunk) ->
+ {continue, {state, N+1}};
+post_chunked(SessionID, _Env, {last, _Body, {state, N}} = _Bodychunk) ->
+ mod_esi:deliver(SessionID, "Content-Type:text/html\r\n\r\n"),
+ mod_esi:deliver(SessionID, top("Received chunked body")),
+ mod_esi:deliver(SessionID, "Received" ++ integer_to_list(N) ++ "chunks"),
+ mod_esi:deliver(SessionID, footer());
+post_chunked(SessionID, _Env, {last, _Body, undefined} = _Bodychunk) ->
+ mod_esi:deliver(SessionID, "Content-Type:text/html\r\n\r\n"),
+ mod_esi:deliver(SessionID, top("Received chunked body")),
+ mod_esi:deliver(SessionID, "Received 1 chunk"),
+ mod_esi:deliver(SessionID, footer());
+post_chunked(_, _, _Body) ->
+ exit(body_not_chunked).
+
+post_204(SessionID, _Env, _Input) ->
+ mod_esi:deliver(SessionID,
+ ["Status: 204 No Content" ++ "\r\n\r\n"]),
+ mod_esi:deliver(SessionID, []).
+
+
+newformat(SessionID,_,_) ->
mod_esi:deliver(SessionID, "Content-Type:text/html\r\n\r\n"),
mod_esi:deliver(SessionID, top("new esi format test")),
mod_esi:deliver(SessionID, "This new format is nice<BR>"),
mod_esi:deliver(SessionID, "This new format is nice<BR>"),
mod_esi:deliver(SessionID, "This new format is nice<BR>"),
mod_esi:deliver(SessionID, footer()).
-
+
%% ------------------------------------------------------
delay(Time) when is_integer(Time) ->
diff --git a/lib/inets/src/http_server/httpd_file.erl b/lib/inets/src/http_server/httpd_file.erl
index 4d419172d0..bf7554bd08 100644
--- a/lib/inets/src/http_server/httpd_file.erl
+++ b/lib/inets/src/http_server/httpd_file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,6 +33,9 @@ handle_error(enoent, Op, ModData, Path) ->
handle_error(enotdir, Op, ModData, Path) ->
handle_error(404, Op, ModData, Path,
": A component of the file name is not a directory");
+handle_error(eisdir, Op, ModData, Path) ->
+ handle_error(403, Op, ModData, Path,
+ ":Ilegal operation expected a file not a directory");
handle_error(emfile, Op, _ModData, Path) ->
handle_error(500, Op, none, Path, ": Too many open files");
handle_error({enfile,_}, Op, _ModData, Path) ->
diff --git a/lib/inets/src/http_server/httpd_request.erl b/lib/inets/src/http_server/httpd_request.erl
index 749f58c197..9d7538a13d 100644
--- a/lib/inets/src/http_server/httpd_request.erl
+++ b/lib/inets/src/http_server/httpd_request.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,7 +36,7 @@
%% little at a time on a socket.
-export([
parse_method/1, parse_uri/1, parse_version/1, parse_headers/1,
- whole_body/1
+ whole_body/1, body_chunk_first/3, body_chunk/3, add_chunk/1
]).
@@ -76,13 +76,12 @@ body_data(Headers, Body) ->
ContentLength = list_to_integer(Headers#http_request_h.'content-length'),
case size(Body) - ContentLength of
0 ->
- {binary_to_list(Body), <<>>};
+ {Body, <<>>};
_ ->
<<BodyThisReq:ContentLength/binary, Next/binary>> = Body,
- {binary_to_list(BodyThisReq), Next}
+ {BodyThisReq, Next}
end.
-
%%-------------------------------------------------------------------------
%% validate(Method, Uri, Version) -> ok | {error, {bad_request, Reason} |
%% {error, {not_supported, {Method, Uri, Version}}
@@ -260,17 +259,17 @@ parse_headers(<<?LF, Octet, Rest/binary>>, Header, Headers, Current, Max,
%% If ?CR is is missing RFC2616 section-19.3
parse_headers(<<?CR,?LF, Octet, Rest/binary>>, Header, Headers, Current, Max,
Options, Result);
-parse_headers(<<?CR,?LF, Octet, Rest/binary>>, Header, Headers, _, Max,
+parse_headers(<<?CR,?LF, Octet, Rest/binary>>, Header, Headers, Current, Max,
Options, Result) ->
case http_request:key_value(lists:reverse(Header)) of
undefined -> %% Skip headers with missing :
parse_headers(Rest, [Octet], Headers,
- 0, Max, Options, Result);
+ Current, Max, Options, Result);
NewHeader ->
case check_header(NewHeader, Options) of
ok ->
parse_headers(Rest, [Octet], [NewHeader | Headers],
- 0, Max, Options, Result);
+ Current, Max, Options, Result);
{error, Reason} ->
HttpVersion = lists:nth(3, lists:reverse(Result)),
{error, Reason, HttpVersion}
@@ -292,10 +291,46 @@ parse_headers(<<Octet, Rest/binary>>, Header, Headers, Current,
parse_headers(Rest, [Octet | Header], Headers, Current + 1, Max,
Options, Result).
+body_chunk_first(Body, 0 = Length, _) ->
+ whole_body(Body, Length);
+body_chunk_first(Body, Length, MaxChunk) ->
+ case body_chunk(Body, Length, MaxChunk) of
+ {ok, {last, NewBody}} ->
+ {ok, NewBody};
+ Other ->
+ Other
+ end.
+%% Used to chunk non chunk decoded post/put data
+add_chunk([<<>>, Body, Length, MaxChunk]) ->
+ body_chunk(Body, Length, MaxChunk);
+add_chunk([More, Body, Length, MaxChunk]) ->
+ body_chunk(<<Body/binary, More/binary>>, Length, MaxChunk).
+
+body_chunk(Body, Length, nolimit) ->
+ whole_body(Body, Length);
+body_chunk(<<>> = Body, Length, MaxChunk) ->
+ {ok, {continue, ?MODULE, add_chunk, [Body, Length, MaxChunk]}};
+
+body_chunk(Body, Length, MaxChunk) when Length > MaxChunk ->
+ case size(Body) >= MaxChunk of
+ true ->
+ <<Chunk:MaxChunk/binary, Rest/binary>> = Body,
+ {ok, {{continue, Chunk}, ?MODULE, add_chunk, [Rest, Length - MaxChunk, MaxChunk]}};
+ false ->
+ {ok, {continue, ?MODULE, add_chunk, [Body, Length, MaxChunk]}}
+ end;
+body_chunk(Body, Length, MaxChunk) ->
+ case size(Body) of
+ Length ->
+ {ok, {last, Body}};
+ _ ->
+ {ok, {continue, ?MODULE, add_chunk, [Body, Length, MaxChunk]}}
+ end.
+
whole_body(Body, Length) ->
case size(Body) of
N when N < Length, Length > 0 ->
- {?MODULE, whole_body, [Body, Length]};
+ {?MODULE, add_chunk, [Body, Length, nolimit]};
N when N >= Length, Length >= 0 ->
%% When a client uses pipelining trailing data
%% may be part of the next request!
@@ -443,6 +478,3 @@ check_header({"content-length", Value}, Maxsizes) ->
end;
check_header(_, _) ->
ok.
-
-
-
diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl
index 538d52b98d..d918f10424 100644
--- a/lib/inets/src/http_server/httpd_request_handler.erl
+++ b/lib/inets/src/http_server/httpd_request_handler.erl
@@ -49,7 +49,8 @@
headers, %% #http_request_h{}
body, %% binary()
data, %% The total data received in bits, checked after 10s
- byte_limit %% Bit limit per second before kick out
+ byte_limit, %% Bit limit per second before kick out
+ chunk
}).
%%====================================================================
@@ -124,7 +125,8 @@ continue_init(Manager, ConfigDB, SocketType, Socket, TimeOut) ->
NrOfRequest = max_keep_alive_request(ConfigDB),
MaxContentLen = max_content_length(ConfigDB),
Customize = customize(ConfigDB),
-
+ MaxChunk = max_client_body_chunk(ConfigDB),
+
{_, Status} = httpd_manager:new_connection(Manager),
MFA = {httpd_request, parse, [[{max_uri, MaxURISize}, {max_header, MaxHeaderSize},
@@ -139,7 +141,8 @@ continue_init(Manager, ConfigDB, SocketType, Socket, TimeOut) ->
status = Status,
timeout = TimeOut,
max_keep_alive_request = NrOfRequest,
- mfa = MFA},
+ mfa = MFA,
+ chunk = chunk_start(MaxChunk)},
http_transport:setopts(SocketType, Socket,
[binary, {packet, 0}, {active, once}]),
@@ -194,6 +197,7 @@ handle_cast(Msg, #state{mod = ModData} = State) ->
%%--------------------------------------------------------------------
handle_info({Proto, Socket, Data},
#state{mfa = {Module, Function, Args},
+ chunk = {ChunkState, _},
mod = #mod{socket_type = SockType,
socket = Socket} = ModData} = State)
when (((Proto =:= tcp) orelse
@@ -207,7 +211,8 @@ handle_info({Proto, Socket, Data},
_ ->
State#state.data + byte_size(Data)
end,
- case PROCESSED of
+
+ case PROCESSED of
{ok, Result} ->
NewState = case NewDataSize of
undefined ->
@@ -215,7 +220,7 @@ handle_info({Proto, Socket, Data},
_ ->
set_new_data_size(cancel_request_timeout(State), NewDataSize)
end,
- handle_http_msg(Result, NewState);
+ handle_msg(Result, NewState);
{error, {size_error, MaxSize, ErrCode, ErrStr}, Version} ->
NewModData = ModData#mod{http_version = Version},
httpd_response:send_status(NewModData, ErrCode, ErrStr),
@@ -224,7 +229,10 @@ handle_info({Proto, Socket, Data},
error_log(Reason, NewModData),
{stop, normal, State#state{response_sent = true,
mod = NewModData}};
-
+
+ {http_chunk = Module, Function, Args} when ChunkState =/= undefined ->
+ NewState = handle_chunk(Module, Function, Args, State),
+ {noreply, NewState};
NewMFA ->
http_transport:setopts(SockType, Socket, [{active, once}]),
case NewDataSize of
@@ -349,6 +357,34 @@ await_socket_ownership_transfer(AcceptTimeout) ->
exit(accept_socket_timeout)
end.
+
+%%% Internal chunking of client body
+handle_msg({{continue, Chunk}, Module, Function, Args}, #state{chunk = {_, CbState}} = State) ->
+ handle_internal_chunk(State#state{chunk = {continue, CbState},
+ body = Chunk}, Module, Function, Args);
+handle_msg({continue, Module, Function, Args}, #state{mod = ModData} = State) ->
+ http_transport:setopts(ModData#mod.socket_type,
+ ModData#mod.socket,
+ [{active, once}]),
+ {noreply, State#state{mfa = {Module, Function, Args}}};
+handle_msg({last, Body}, #state{headers = Headers, chunk = {_, CbState}} = State) ->
+ NewHeaders = Headers#http_request_h{'content-length' = integer_to_list(size(Body))},
+ handle_response(State#state{chunk = {last, CbState},
+ headers = NewHeaders,
+ body = Body});
+%%% Last data chunked by client
+handle_msg({ChunkedHeaders, Body}, #state{headers = Headers , chunk = {ChunkState, CbState}} = State) when ChunkState =/= undefined ->
+ NewHeaders = http_chunk:handle_headers(Headers, ChunkedHeaders),
+ handle_response(State#state{chunk = {last, CbState},
+ headers = NewHeaders,
+ body = Body});
+handle_msg({ChunkedHeaders, Body}, #state{headers = Headers , chunk = {undefined, _}} = State) ->
+ NewHeaders = http_chunk:handle_headers(Headers, ChunkedHeaders),
+ handle_response(State#state{headers = NewHeaders,
+ body = Body});
+handle_msg(Result, State) ->
+ handle_http_msg(Result, State).
+
handle_http_msg({_, _, Version, {_, _}, _},
#state{status = busy, mod = ModData} = State) ->
handle_manager_busy(State#state{mod =
@@ -405,10 +441,6 @@ handle_http_msg({Method, Uri, Version, {RecordHeaders, Headers}, Body},
error_log(Reason, ModData),
{stop, normal, State#state{response_sent = true}}
end;
-handle_http_msg({ChunkedHeaders, Body},
- State = #state{headers = Headers}) ->
- NewHeaders = http_chunk:handle_headers(Headers, ChunkedHeaders),
- handle_response(State#state{headers = NewHeaders, body = Body});
handle_http_msg(Body, State) ->
handle_response(State#state{body = Body}).
@@ -443,22 +475,25 @@ handle_body(#state{mod = #mod{config_db = ConfigDB}} = State) ->
end.
-handle_body(#state{headers = Headers, body = Body, mod = ModData} = State,
+handle_body(#state{headers = Headers, body = Body,
+ chunk = {ChunkState, CbState}, mod = #mod{config_db = ConfigDB} = ModData} = State,
MaxHeaderSize, MaxBodySize) ->
+ MaxChunk = max_client_body_chunk(ConfigDB),
case Headers#http_request_h.'transfer-encoding' of
"chunked" ->
try http_chunk:decode(Body, MaxBodySize, MaxHeaderSize) of
- {Module, Function, Args} ->
+ {Module, Function, Args} ->
http_transport:setopts(ModData#mod.socket_type,
ModData#mod.socket,
[{active, once}]),
{noreply, State#state{mfa =
- {Module, Function, Args}}};
- {ok, {ChunkedHeaders, NewBody}} ->
- NewHeaders =
- http_chunk:handle_headers(Headers, ChunkedHeaders),
- handle_response(State#state{headers = NewHeaders,
- body = NewBody})
+ {Module, Function, Args},
+ chunk = chunk_start(MaxChunk)}};
+ {ok, {ChunkedHeaders, NewBody}} ->
+ NewHeaders = http_chunk:handle_headers(Headers, ChunkedHeaders),
+ handle_response(State#state{headers = NewHeaders,
+ body = NewBody,
+ chunk = chunk_finish(ChunkState, CbState, MaxChunk)})
catch
throw:Error ->
httpd_response:send_status(ModData, 400,
@@ -476,21 +511,36 @@ handle_body(#state{headers = Headers, body = Body, mod = ModData} = State,
error_log(Reason, ModData),
{stop, normal, State#state{response_sent = true}};
_ ->
- Length = list_to_integer(Headers#http_request_h.'content-length'),
+ Length = list_to_integer(Headers#http_request_h.'content-length'),
+ MaxChunk = max_client_body_chunk(ConfigDB),
case ((Length =< MaxBodySize) or (MaxBodySize == nolimit)) of
true ->
- case httpd_request:whole_body(Body, Length) of
- {Module, Function, Args} ->
- http_transport:setopts(ModData#mod.socket_type,
+ case httpd_request:body_chunk_first(Body, Length, MaxChunk) of
+ %% This is the case that the we need more data to complete
+ %% the body but chunking to the mod_esi user is not enabled.
+ {Module, add_chunk = Function, Args} ->
+ http_transport:setopts(ModData#mod.socket_type,
+ ModData#mod.socket,
+ [{active, once}]),
+ {noreply, State#state{mfa =
+ {Module, Function, Args}}};
+ %% Chunking to mod_esi user is enabled
+ {ok, {continue, Module, Function, Args}} ->
+ http_transport:setopts(ModData#mod.socket_type,
ModData#mod.socket,
[{active, once}]),
{noreply, State#state{mfa =
{Module, Function, Args}}};
-
- {ok, NewBody} ->
- handle_response(
- State#state{headers = Headers,
- body = NewBody})
+ {ok, {{continue, Chunk}, Module, Function, Args}} ->
+ handle_internal_chunk(State#state{chunk = chunk_start(MaxChunk),
+ body = Chunk}, Module, Function, Args);
+ %% Whole body delivered, if chunking mechanism is enabled the whole
+ %% body fits in one chunk.
+ {ok, NewBody} ->
+ handle_response(State#state{chunk = chunk_finish(ChunkState,
+ CbState, MaxChunk),
+ headers = Headers,
+ body = NewBody})
end;
false ->
httpd_response:send_status(ModData, 413, "Body too long"),
@@ -550,15 +600,61 @@ expect(Headers, _, ConfigDB) ->
end
end.
+handle_chunk(http_chunk = Module, decode_data = Function,
+ [ChunkSize, TotalChunk, {MaxBodySize, BodySoFar, _AccLength, MaxHeaderSize}],
+ #state{chunk = {_, CbState},
+ mod = #mod{socket_type = SockType,
+ socket = Socket} = ModData} = State) ->
+ {continue, NewCbState} = httpd_response:handle_continuation(ModData#mod{entity_body =
+ {continue, BodySoFar, CbState}}),
+ http_transport:setopts(SockType, Socket, [{active, once}]),
+ State#state{chunk = {continue, NewCbState}, mfa = {Module, Function, [ChunkSize, TotalChunk, {MaxBodySize, <<>>, 0, MaxHeaderSize}]}};
+
+handle_chunk(http_chunk = Module, decode_size = Function,
+ [Data, HexList, _AccSize, {MaxBodySize, BodySoFar, _AccLength, MaxHeaderSize}],
+ #state{chunk = {_, CbState},
+ mod = #mod{socket_type = SockType,
+ socket = Socket} = ModData} = State) ->
+ {continue, NewCbState} = httpd_response:handle_continuation(ModData#mod{entity_body = {continue, BodySoFar, CbState}}),
+ http_transport:setopts(SockType, Socket, [{active, once}]),
+ State#state{chunk = {continue, NewCbState}, mfa = {Module, Function, [Data, HexList, 0, {MaxBodySize, <<>>, 0, MaxHeaderSize}]}};
+handle_chunk(Module, Function, Args, #state{mod = #mod{socket_type = SockType,
+ socket = Socket}} = State) ->
+ http_transport:setopts(SockType, Socket, [{active, once}]),
+ State#state{mfa = {Module, Function, Args}}.
+
+handle_internal_chunk(#state{chunk = {ChunkState, CbState}, body = Chunk,
+ mod = #mod{socket_type = SockType,
+ socket = Socket} = ModData} = State, Module, Function, Args)->
+ Bodychunk = body_chunk(ChunkState, CbState, Chunk),
+ {continue, NewCbState} = httpd_response:handle_continuation(ModData#mod{entity_body = Bodychunk}),
+ case Args of
+ [<<>> | _] ->
+ http_transport:setopts(SockType, Socket, [{active, once}]),
+ {noreply, State#state{chunk = {continue, NewCbState}, mfa = {Module, Function, Args}}};
+ _ ->
+ handle_info({dummy, Socket, <<>>}, State#state{chunk = {continue, NewCbState},
+ mfa = {Module, Function, Args}})
+ end.
+
+handle_response(#state{body = Body,
+ headers = Headers,
+ mod = ModData,
+ chunk = {last, CbState},
+ max_keep_alive_request = Max} = State) when Max > 0 ->
+ {NewBody, Data} = httpd_request:body_data(Headers, Body),
+ ok = httpd_response:generate_and_send_response(
+ ModData#mod{entity_body = {last, NewBody, CbState}}),
+ handle_next_request(State#state{response_sent = true}, Data);
handle_response(#state{body = Body,
mod = ModData,
headers = Headers,
max_keep_alive_request = Max} = State) when Max > 0 ->
{NewBody, Data} = httpd_request:body_data(Headers, Body),
+ %% Backwards compatible, may cause memory explosion
ok = httpd_response:generate_and_send_response(
- ModData#mod{entity_body = NewBody}),
+ ModData#mod{entity_body = binary_to_list(NewBody)}),
handle_next_request(State#state{response_sent = true}, Data);
-
handle_response(#state{body = Body,
headers = Headers,
mod = ModData} = State) ->
@@ -578,6 +674,7 @@ handle_next_request(#state{mod = #mod{connection = true} = ModData,
MaxURISize = max_uri_size(ModData#mod.config_db),
MaxContentLen = max_content_length(ModData#mod.config_db),
Customize = customize(ModData#mod.config_db),
+ MaxChunk = max_client_body_chunk(ModData#mod.config_db),
MFA = {httpd_request, parse, [[{max_uri, MaxURISize}, {max_header, MaxHeaderSize},
{max_version, ?HTTP_MAX_VERSION_STRING},
@@ -590,6 +687,7 @@ handle_next_request(#state{mod = #mod{connection = true} = ModData,
max_keep_alive_request = decrease(Max),
headers = undefined,
body = undefined,
+ chunk = chunk_start(MaxChunk),
response_sent = false},
NewState = activate_request_timeout(TmpState),
@@ -647,6 +745,9 @@ error_log(ReasonString, #mod{config_db = ConfigDB}) ->
max_header_size(ConfigDB) ->
httpd_util:lookup(ConfigDB, max_header_size, ?HTTP_MAX_HEADER_SIZE).
+max_client_body_chunk(ConfigDB) ->
+ httpd_util:lookup(ConfigDB, max_client_body_chunk, nolimit).
+
max_uri_size(ConfigDB) ->
httpd_util:lookup(ConfigDB, max_uri_size, ?HTTP_MAX_URI_SIZE).
@@ -661,3 +762,17 @@ max_content_length(ConfigDB) ->
customize(ConfigDB) ->
httpd_util:lookup(ConfigDB, customize, httpd_custom).
+
+chunk_start(nolimit) ->
+ {undefined, undefined};
+chunk_start(_) ->
+ {first, undefined}.
+chunk_finish(_, _, nolimit) ->
+ {undefined, undefined};
+chunk_finish(_, CbState, _) ->
+ {last, CbState}.
+
+body_chunk(first, _, Chunk) ->
+ {first, Chunk};
+body_chunk(ChunkState, CbState, Chunk) ->
+ {ChunkState, Chunk, CbState}.
diff --git a/lib/inets/src/http_server/httpd_response.erl b/lib/inets/src/http_server/httpd_response.erl
index effa273e92..bb946664f9 100644
--- a/lib/inets/src/http_server/httpd_response.erl
+++ b/lib/inets/src/http_server/httpd_response.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
-module(httpd_response).
-export([generate_and_send_response/1, send_status/3, send_header/3,
send_body/3, send_chunk/3, send_final_chunk/2, send_final_chunk/3,
- split_header/2, is_disable_chunked_send/1, cache_headers/2]).
+ split_header/2, is_disable_chunked_send/1, cache_headers/2, handle_continuation/1]).
-export([map_status_code/2]).
-include_lib("inets/src/inets_app/inets_internal.hrl").
@@ -31,6 +31,9 @@
-define(VMODULE,"RESPONSE").
+handle_continuation(Mod) ->
+ generate_and_send_response(Mod).
+
%% If peername does not exist the client already discarded the
%% request so we do not need to send a reply.
generate_and_send_response(#mod{init_data =
@@ -39,6 +42,8 @@ generate_and_send_response(#mod{init_data =
generate_and_send_response(#mod{config_db = ConfigDB} = ModData) ->
Modules = httpd_util:lookup(ConfigDB, modules, ?DEFAULT_MODS),
case traverse_modules(ModData, Modules) of
+ {continue, _} = Continue ->
+ Continue;
done ->
ok;
{proceed, Data} ->
@@ -56,8 +61,12 @@ generate_and_send_response(#mod{config_db = ConfigDB} = ModData) ->
{StatusCode, Response} -> %% Old way
send_response_old(ModData, StatusCode, Response),
ok;
- undefined ->
- send_status(ModData, 500, none),
+ undefined ->
+ %% Happens when no mod_*
+ %% handles the request
+ send_status(ModData, 501, {ModData#mod.method,
+ ModData#mod.request_uri,
+ ModData#mod.http_version}),
ok
end
end
@@ -69,26 +78,24 @@ generate_and_send_response(#mod{config_db = ConfigDB} = ModData) ->
traverse_modules(ModData,[]) ->
{proceed,ModData#mod.data};
traverse_modules(ModData,[Module|Rest]) ->
- ?hdrd("traverse modules", [{callback_module, Module}]),
try apply(Module, do, [ModData]) of
+ {continue, _} = Continue ->
+ Continue;
done ->
- ?hdrt("traverse modules - done", []),
- done;
+ done;
{break, NewData} ->
- ?hdrt("traverse modules - break", [{new_data, NewData}]),
- {proceed, NewData};
+ {proceed, NewData};
{proceed, NewData} ->
- ?hdrt("traverse modules - proceed", [{new_data, NewData}]),
- traverse_modules(ModData#mod{data = NewData}, Rest)
+ traverse_modules(ModData#mod{data = NewData}, Rest)
catch
- T:E ->
+ T:E:Stacktrace ->
String =
lists:flatten(
io_lib:format("module traverse failed: ~p:do => "
"~n Error Type: ~p"
"~n Error: ~p"
"~n Stack trace: ~p",
- [Module, T, E, ?STACK()])),
+ [Module, T, E, Stacktrace])),
httpd_util:error_log(ModData#mod.config_db, String),
send_status(ModData, 500, none),
done
@@ -104,15 +111,10 @@ send_status(#mod{socket_type = SocketType,
socket = Socket,
config_db = ConfigDB} = ModData, StatusCode, PhraseArgs) ->
- ?hdrd("send status", [{status_code, StatusCode},
- {phrase_args, PhraseArgs}]),
-
ReasonPhrase = httpd_util:reason_phrase(StatusCode),
Message = httpd_util:message(StatusCode, PhraseArgs, ConfigDB),
Body = get_body(ReasonPhrase, Message),
- ?hdrt("send status - header", [{reason_phrase, ReasonPhrase},
- {message, Message}]),
send_header(ModData, StatusCode,
[{content_type, "text/html"},
{content_length, integer_to_list(length(Body))}]),
diff --git a/lib/inets/src/http_server/httpd_script_env.erl b/lib/inets/src/http_server/httpd_script_env.erl
index e15613273e..055edca211 100644
--- a/lib/inets/src/http_server/httpd_script_env.erl
+++ b/lib/inets/src/http_server/httpd_script_env.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -74,9 +74,13 @@ which_peercert(#mod{socket_type = {Type, _}, socket = Socket}) when Type == essl
which_peercert(_) -> %% Not an ssl connection
undefined.
+
which_resolve(#mod{init_data = #init_data{resolve = Resolve}}) ->
Resolve.
+which_name(#mod{config_db = ConfigDB}) ->
+ httpd_util:lookup(ConfigDB, server_name).
+
which_method(#mod{method = Method}) ->
Method.
@@ -85,7 +89,8 @@ which_request_uri(#mod{request_uri = RUri}) ->
create_basic_elements(esi, ModData) ->
[{server_software, which_server(ModData)},
- {server_name, which_resolve(ModData)},
+ {server_name, which_name(ModData)},
+ {host_name, which_resolve(ModData)},
{gateway_interface, ?GATEWAY_INTERFACE},
{server_protocol, ?SERVER_PROTOCOL},
{server_port, which_port(ModData)},
@@ -96,7 +101,8 @@ create_basic_elements(esi, ModData) ->
create_basic_elements(cgi, ModData) ->
[{"SERVER_SOFTWARE", which_server(ModData)},
- {"SERVER_NAME", which_resolve(ModData)},
+ {"SERVER_NAME", which_name(ModData)},
+ {"HOST_NAME", which_resolve(ModData)},
{"GATEWAY_INTERFACE", ?GATEWAY_INTERFACE},
{"SERVER_PROTOCOL", ?SERVER_PROTOCOL},
{"SERVER_PORT", integer_to_list(which_port(ModData))},
@@ -160,9 +166,9 @@ create_script_elements(cgi, path_info, PathInfo, ModData) ->
[{"PATH_INFO", PathInfo},
{"PATH_TRANSLATED", PathTranslated}];
create_script_elements(esi, entity_body, Body, _) ->
- [{content_length, httpd_util:flatlength(Body)}];
+ [{content_length, integer_to_list(httpd_util:flatlength(Body))}];
create_script_elements(cgi, entity_body, Body, _) ->
- [{"CONTENT_LENGTH", httpd_util:flatlength(Body)}];
+ [{"CONTENT_LENGTH", integer_to_list(httpd_util:flatlength(Body))}];
create_script_elements(_, _, _, _) ->
[].
diff --git a/lib/inets/src/http_server/mod_alias.erl b/lib/inets/src/http_server/mod_alias.erl
index 0333076546..68a3de0229 100644
--- a/lib/inets/src/http_server/mod_alias.erl
+++ b/lib/inets/src/http_server/mod_alias.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -163,28 +163,24 @@ longest_match([], _RequestURI, _LongestNo, LongestAlias) ->
real_script_name(_ConfigDB, _RequestURI, []) ->
not_a_script;
-
-real_script_name(ConfigDB, RequestURI, [{MP,Replacement} | Rest])
- when element(1, MP) =:= re_pattern ->
- case re:run(RequestURI, MP, [{capture, none}]) of
- match ->
- ActualName =
- re:replace(RequestURI, MP, Replacement, [{return,list}]),
- httpd_util:split_script_path(default_index(ConfigDB, ActualName));
- nomatch ->
- real_script_name(ConfigDB, RequestURI, Rest)
- end;
-
real_script_name(ConfigDB, RequestURI, [{FakeName,RealName} | Rest]) ->
case re:run(RequestURI, "^" ++ FakeName, [{capture, none}]) of
match ->
- ActualName =
+ ActualName0 =
re:replace(RequestURI, "^" ++ FakeName, RealName, [{return,list}]),
+ ActualName = abs_script_path(ConfigDB, ActualName0),
httpd_util:split_script_path(default_index(ConfigDB, ActualName));
nomatch ->
real_script_name(ConfigDB, RequestURI, Rest)
end.
+%% ERL-574: relative path in script_alias property results in malformed url
+abs_script_path(ConfigDB, [$.|_] = RelPath) ->
+ Root = httpd_util:lookup(ConfigDB, server_root),
+ Root ++ "/" ++ RelPath;
+abs_script_path(_, RelPath) ->
+ RelPath.
+
%% default_index
default_index(ConfigDB, Path) ->
diff --git a/lib/inets/src/http_server/mod_disk_log.erl b/lib/inets/src/http_server/mod_disk_log.erl
index 3be5f2dd74..190cf91416 100644
--- a/lib/inets/src/http_server/mod_disk_log.erl
+++ b/lib/inets/src/http_server/mod_disk_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -363,17 +363,21 @@ create_disk_log(Filename, MaxBytes, MaxFiles, ConfigList) ->
%%----------------------------------------------------------------------
open(Filename, MaxBytes, MaxFiles, internal) ->
- Opts = [{format, internal}, {repair, truncate}],
- open1(Filename, MaxBytes, MaxFiles, Opts);
+ Opt0 = {format, internal},
+ Opts1 = [Opt0, {repair, true}],
+ Opts2 = [Opt0, {repair, truncate}],
+ open1(Filename, MaxBytes, MaxFiles, Opts1, Opts2);
open(Filename, MaxBytes, MaxFiles, _) ->
Opts = [{format, external}],
- open1(Filename, MaxBytes, MaxFiles, Opts).
+ open1(Filename, MaxBytes, MaxFiles, Opts, Opts).
-open1(Filename, MaxBytes, MaxFiles, Opts0) ->
- Opts1 = [{name, Filename}, {file, Filename}, {type, wrap}] ++ Opts0,
- case open2(Opts1, {MaxBytes, MaxFiles}) of
+open1(Filename, MaxBytes, MaxFiles, Opts1, Opts2) ->
+ Opts0 = [{name, Filename}, {file, Filename}, {type, wrap}],
+ case open2(Opts0 ++ Opts1, Opts0 ++ Opts2, {MaxBytes, MaxFiles}) of
{ok, LogDB} ->
{ok, LogDB};
+ {repaired, LogDB, {recovered, _}, {badbytes, _}} ->
+ {ok, LogDB};
{error, Reason} ->
{error,
?NICE("Can't create " ++ Filename ++
@@ -382,11 +386,16 @@ open1(Filename, MaxBytes, MaxFiles, Opts0) ->
{error, ?NICE("Can't create "++Filename)}
end.
-open2(Opts, Size) ->
- case disk_log:open(Opts) of
+open2(Opts1, Opts2, Size) ->
+ case disk_log:open(Opts1) of
{error, {badarg, size}} ->
%% File did not exist, add the size option and try again
- disk_log:open([{size, Size} | Opts]);
+ disk_log:open([{size, Size} | Opts1]);
+ {error, {Reason, _}} when
+ Reason == not_a_log_file;
+ Reason == invalid_index_file ->
+ %% File was corrupt, add the truncate option and try again
+ disk_log:open([{size, Size} | Opts2]);
Else ->
Else
end.
diff --git a/lib/inets/src/http_server/mod_esi.erl b/lib/inets/src/http_server/mod_esi.erl
index b21af1418c..443b7ee564 100644
--- a/lib/inets/src/http_server/mod_esi.erl
+++ b/lib/inets/src/http_server/mod_esi.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,7 +31,6 @@
-include("httpd.hrl").
-include("httpd_internal.hrl").
--include("inets_internal.hrl").
-define(VMODULE,"ESI").
-define(DEFAULT_ERL_TIMEOUT,15000).
@@ -69,7 +68,6 @@ deliver(_SessionID, _Data) ->
%% Description: See httpd(3) ESWAPI CALLBACK FUNCTIONS
%%-------------------------------------------------------------------------
do(ModData) ->
- ?hdrt("do", []),
case proplists:get_value(status, ModData#mod.data) of
{_StatusCode, _PhraseArgs, _Reason} ->
{proceed, ModData#mod.data};
@@ -190,7 +188,6 @@ store({erl_script_nocache, Value}, _) ->
%%% Internal functions
%%%========================================================================
generate_response(ModData) ->
- ?hdrt("generate response", []),
case scheme(ModData#mod.request_uri, ModData#mod.config_db) of
{eval, ESIBody, Modules} ->
eval(ModData, ESIBody, Modules);
@@ -242,7 +239,6 @@ alias_match_str(Alias, eval_script_alias) ->
erl(#mod{method = Method} = ModData, ESIBody, Modules)
when (Method =:= "GET") orelse (Method =:= "HEAD") orelse (Method =:= "DELETE") ->
- ?hdrt("erl", [{method, Method}]),
case httpd_util:split(ESIBody,":|%3A|/",2) of
{ok, [ModuleName, FuncAndInput]} ->
case httpd_util:split(FuncAndInput,"[\?/]",2) of
@@ -273,14 +269,12 @@ erl(#mod{method = "PUT", entity_body = Body} = ModData,
generate_webpage(ModData, ESIBody, Modules,
list_to_atom(ModuleName),
FunctionName, {Input,Body},
- [{entity_body, Body} |
- script_elements(FuncAndInput, Input)]);
+ script_elements(FuncAndInput, Input));
{ok, [FunctionName]} ->
generate_webpage(ModData, ESIBody, Modules,
list_to_atom(ModuleName),
FunctionName, {undefined,Body},
- [{entity_body, Body} |
- script_elements(FuncAndInput, "")]);
+ script_elements(FuncAndInput, ""));
{ok, BadRequest} ->
{proceed,[{status,{400,none, BadRequest}} |
ModData#mod.data]}
@@ -290,12 +284,11 @@ erl(#mod{method = "PUT", entity_body = Body} = ModData,
end;
erl(#mod{method = "POST", entity_body = Body} = ModData, ESIBody, Modules) ->
- ?hdrt("erl", [{method, post}]),
case httpd_util:split(ESIBody,":|%3A|/",2) of
{ok,[ModuleName, Function]} ->
generate_webpage(ModData, ESIBody, Modules,
list_to_atom(ModuleName),
- Function, Body, [{entity_body, Body}]);
+ Function, Body, []);
{ok, BadRequest} ->
{proceed,[{status, {400, none, BadRequest}} | ModData#mod.data]}
end;
@@ -304,7 +297,6 @@ erl(#mod{request_uri = ReqUri,
method = "PATCH",
http_version = Version,
data = Data}, _ESIBody, _Modules) ->
- ?hdrt("erl", [{method, patch}]),
{proceed, [{status,{501,{"PATCH", ReqUri, Version},
?NICE("Erl mechanism doesn't support method PATCH")}}|
Data]}.
@@ -315,7 +307,6 @@ generate_webpage(ModData, ESIBody, [all], Module, FunctionName,
FunctionName, Input, ScriptElements);
generate_webpage(ModData, ESIBody, Modules, Module, FunctionName,
Input, ScriptElements) ->
- ?hdrt("generate webpage", []),
Function = list_to_atom(FunctionName),
case lists:member(Module, Modules) of
true ->
@@ -337,7 +328,6 @@ generate_webpage(ModData, ESIBody, Modules, Module, FunctionName,
%% Old API that waits for the dymnamic webpage to be totally generated
%% before anythig is sent back to the client.
erl_scheme_webpage_whole(Mod, Func, Env, Input, ModData) ->
- ?hdrt("erl_scheme_webpage_whole", [{module, Mod}, {function, Func}]),
case (catch Mod:Func(Env, Input)) of
{'EXIT',{undef, _}} ->
{proceed, [{status, {404, ModData#mod.request_uri, "Not found"}}
@@ -349,33 +339,27 @@ erl_scheme_webpage_whole(Mod, Func, Env, Input, ModData) ->
{Headers, Body} =
httpd_esi:parse_headers(lists:flatten(Response)),
Length = httpd_util:flatlength(Body),
- case httpd_esi:handle_headers(Headers) of
- {proceed, AbsPath} ->
- {proceed, [{real_name, httpd_util:split_path(AbsPath)}
- | ModData#mod.data]};
- {ok, NewHeaders, StatusCode} ->
- send_headers(ModData, StatusCode,
- [{"content-length",
- integer_to_list(Length)}| NewHeaders]),
- case ModData#mod.method of
- "HEAD" ->
- {proceed, [{response, {already_sent, 200, 0}} |
- ModData#mod.data]};
- _ ->
- httpd_response:send_body(ModData,
- StatusCode, Body),
- {proceed, [{response, {already_sent, 200,
- Length}} |
- ModData#mod.data]}
- end
- end
+ {ok, NewHeaders, StatusCode} = httpd_esi:handle_headers(Headers),
+ send_headers(ModData, StatusCode,
+ [{"content-length",
+ integer_to_list(Length)}| NewHeaders]),
+ case ModData#mod.method of
+ "HEAD" ->
+ {proceed, [{response, {already_sent, 200, 0}} |
+ ModData#mod.data]};
+ _ ->
+ httpd_response:send_body(ModData,
+ StatusCode, Body),
+ {proceed, [{response, {already_sent, 200,
+ Length}} |
+ ModData#mod.data]}
+ end
end.
%% New API that allows the dynamic wepage to be sent back to the client
%% in small chunks at the time during generation.
erl_scheme_webpage_chunk(Mod, Func, Env, Input, ModData) ->
process_flag(trap_exit, true),
- ?hdrt("erl_scheme_webpage_chunk", [{module, Mod}, {function, Func}]),
Self = self(),
%% Spawn worker that generates the webpage.
%% It would be nicer to use erlang:function_exported/3 but if the
@@ -386,7 +370,9 @@ erl_scheme_webpage_chunk(Mod, Func, Env, Input, ModData) ->
{'EXIT', {undef,_}} ->
%% Will force fallback on the old API
exit(erl_scheme_webpage_chunk_undefined);
- _ ->
+ {continue, _} = Continue ->
+ exit(Continue);
+ _ ->
ok
end
end),
@@ -400,38 +386,39 @@ deliver_webpage_chunk(#mod{config_db = Db} = ModData, Pid) ->
deliver_webpage_chunk(ModData, Pid, Timeout).
deliver_webpage_chunk(#mod{config_db = Db} = ModData, Pid, Timeout) ->
- ?hdrt("deliver_webpage_chunk", [{timeout, Timeout}]),
case receive_headers(Timeout) of
{error, Reason} ->
%% Happens when webpage generator callback/3 is undefined
- ?hdrv("deliver_webpage_chunk - failed receiving headers",
- [{reason, Reason}]),
{error, Reason};
+ {continue, _} = Continue ->
+ Continue;
{Headers, Body} ->
- case httpd_esi:handle_headers(Headers) of
- {proceed, AbsPath} ->
- {proceed, [{real_name, httpd_util:split_path(AbsPath)}
- | ModData#mod.data]};
- {ok, NewHeaders, StatusCode} ->
- IsDisableChunkedSend =
- httpd_response:is_disable_chunked_send(Db),
- case (ModData#mod.http_version =/= "HTTP/1.1") or
- (IsDisableChunkedSend) of
- true ->
- send_headers(ModData, StatusCode,
- [{"connection", "close"} |
- NewHeaders]);
- false ->
- send_headers(ModData, StatusCode,
- [{"transfer-encoding",
- "chunked"} | NewHeaders])
- end,
- handle_body(Pid, ModData, Body, Timeout, length(Body),
- IsDisableChunkedSend)
- end;
- timeout ->
- ?hdrv("deliver_webpage_chunk - timeout", []),
- send_headers(ModData, 504, [{"connection", "close"}]),
+ {ok, NewHeaders, StatusCode} = httpd_esi:handle_headers(Headers),
+ %% All 1xx (informational), 204 (no content), and 304 (not modified)
+ %% responses MUST NOT include a message-body, and thus are always
+ %% terminated by the first empty line after the header fields.
+ %% This implies that chunked encoding MUST NOT be used for these
+ %% status codes.
+ IsDisableChunkedSend =
+ httpd_response:is_disable_chunked_send(Db) orelse
+ StatusCode =:= 204 orelse %% No Content
+ StatusCode =:= 304 orelse %% Not Modified
+ (100 =< StatusCode andalso StatusCode =< 199), %% Informational
+ case (ModData#mod.http_version =/= "HTTP/1.1") or
+ (IsDisableChunkedSend) of
+ true ->
+ send_headers(ModData, StatusCode,
+ [{"connection", "close"} |
+ NewHeaders]);
+ false ->
+ send_headers(ModData, StatusCode,
+ [{"transfer-encoding",
+ "chunked"} | NewHeaders])
+ end,
+ handle_body(Pid, ModData, Body, Timeout, length(Body),
+ IsDisableChunkedSend);
+ timeout ->
+ send_headers(ModData, 504, [{"connection", "close"}]),
httpd_socket:close(ModData#mod.socket_type, ModData#mod.socket),
{proceed,[{response, {already_sent, 200, 0}} | ModData#mod.data]}
end.
@@ -439,16 +426,14 @@ deliver_webpage_chunk(#mod{config_db = Db} = ModData, Pid, Timeout) ->
receive_headers(Timeout) ->
receive
{esi_data, Chunk} ->
- ?hdrt("receive_headers - received esi data (esi)", []),
httpd_esi:parse_headers(lists:flatten(Chunk));
{ok, Chunk} ->
- ?hdrt("receive_headers - received esi data (ok)", []),
httpd_esi:parse_headers(lists:flatten(Chunk));
{'EXIT', Pid, erl_scheme_webpage_chunk_undefined} when is_pid(Pid) ->
- ?hdrd("receive_headers - exit:chunk-undef", []),
{error, erl_scheme_webpage_chunk_undefined};
- {'EXIT', Pid, Reason} when is_pid(Pid) ->
- ?hdrv("receive_headers - exit", [{reason, Reason}]),
+ {'EXIT', Pid, {continue, _} = Continue} when is_pid(Pid) ->
+ Continue;
+ {'EXIT', Pid, Reason} when is_pid(Pid) ->
exit({mod_esi_linked_process_died, Pid, Reason})
after Timeout ->
timeout
@@ -463,7 +448,6 @@ handle_body(_, #mod{method = "HEAD"} = ModData, _, _, Size, _) ->
{proceed, [{response, {already_sent, 200, Size}} | ModData#mod.data]};
handle_body(Pid, ModData, Body, Timeout, Size, IsDisableChunkedSend) ->
- ?hdrt("handle_body - send chunk", [{timeout, Timeout}, {size, Size}]),
httpd_response:send_chunk(ModData, Body, IsDisableChunkedSend),
receive
{esi_data, Data} when is_binary(Data) ->
@@ -543,7 +527,6 @@ eval(#mod{request_uri = ReqUri,
method = "PUT",
http_version = Version,
data = Data}, _ESIBody, _Modules) ->
- ?hdrt("eval", [{method, put}]),
{proceed,[{status,{501,{"PUT", ReqUri, Version},
?NICE("Eval mechanism doesn't support method PUT")}}|
Data]};
@@ -552,7 +535,6 @@ eval(#mod{request_uri = ReqUri,
method = "DELETE",
http_version = Version,
data = Data}, _ESIBody, _Modules) ->
- ?hdrt("eval", [{method, delete}]),
{proceed,[{status,{501,{"DELETE", ReqUri, Version},
?NICE("Eval mechanism doesn't support method DELETE")}}|
Data]};
@@ -561,14 +543,12 @@ eval(#mod{request_uri = ReqUri,
method = "POST",
http_version = Version,
data = Data}, _ESIBody, _Modules) ->
- ?hdrt("eval", [{method, post}]),
{proceed,[{status,{501,{"POST", ReqUri, Version},
?NICE("Eval mechanism doesn't support method POST")}}|
Data]};
eval(#mod{method = Method} = ModData, ESIBody, Modules)
when (Method =:= "GET") orelse (Method =:= "HEAD") ->
- ?hdrt("eval", [{method, Method}]),
case is_authorized(ESIBody, Modules) of
true ->
case generate_webpage(ESIBody) of
@@ -578,15 +558,10 @@ eval(#mod{method = Method} = ModData, ESIBody, Modules)
{ok, Response} ->
{Headers, _} =
httpd_esi:parse_headers(lists:flatten(Response)),
- case httpd_esi:handle_headers(Headers) of
- {ok, _, StatusCode} ->
- {proceed,[{response, {StatusCode, Response}} |
- ModData#mod.data]};
- {proceed, AbsPath} ->
- {proceed, [{real_name, AbsPath} |
- ModData#mod.data]}
- end
- end;
+ {ok, _, StatusCode} =httpd_esi:handle_headers(Headers),
+ {proceed,[{response, {StatusCode, Response}} |
+ ModData#mod.data]}
+ end;
false ->
{proceed,[{status,
{403, ModData#mod.request_uri,
@@ -595,7 +570,7 @@ eval(#mod{method = Method} = ModData, ESIBody, Modules)
end.
generate_webpage(ESIBody) ->
- (catch lib:eval_str(string:concat(ESIBody,". "))).
+ (catch erl_eval:eval_str(string:concat(ESIBody,". "))).
is_authorized(_ESIBody, [all]) ->
true;
diff --git a/lib/inets/src/http_server/mod_log.erl b/lib/inets/src/http_server/mod_log.erl
index ad7e9713d9..0323918578 100644
--- a/lib/inets/src/http_server/mod_log.erl
+++ b/lib/inets/src/http_server/mod_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -105,8 +105,8 @@ do(Info) ->
Code = proplists:get_value(code,Head,unknown),
transfer_log(Info, "-", AuthUser, Date, Code, Size),
{proceed, Info#mod.data};
- {_StatusCode, Response} ->
- transfer_log(Info,"-",AuthUser,Date,200,
+ {StatusCode, Response} ->
+ transfer_log(Info, "-", AuthUser, Date, StatusCode,
httpd_util:flatlength(Response)),
{proceed,Info#mod.data};
undefined ->
diff --git a/lib/inets/src/inets_app/Makefile b/lib/inets/src/inets_app/Makefile
index eb0098dbee..ec1ae70305 100644
--- a/lib/inets/src/inets_app/Makefile
+++ b/lib/inets/src/inets_app/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2016. All Rights Reserved.
+# Copyright Ericsson AB 2005-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -48,7 +48,9 @@ MODULES = \
inets_app \
inets_sup \
inets_trace \
- inets_lib
+ inets_lib \
+ inets_ftp_wrapper \
+ inets_tftp_wrapper
INTERNAL_HRL_FILES = inets_internal.hrl
EXTERNAL_HRL_FILES = ../../include/httpd.hrl \
diff --git a/lib/inets/src/inets_app/inets.app.src b/lib/inets/src/inets_app/inets.app.src
index eb4be932ac..e5780b2a4c 100644
--- a/lib/inets/src/inets_app/inets.app.src
+++ b/lib/inets/src/inets_app/inets.app.src
@@ -1,7 +1,7 @@
%% This is an -*- erlang -*- file.
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,10 +30,7 @@
inets_lib,
%% FTP
- ftp,
- ftp_progress,
- ftp_response,
- ftp_sup,
+ inets_ftp_wrapper,
%% HTTP client:
httpc,
@@ -101,17 +98,11 @@
mod_trace,
%% TFTP
- tftp,
- tftp_binary,
- tftp_engine,
- tftp_file,
- tftp_lib,
- tftp_logger,
- tftp_sup
+ inets_tftp_wrapper
]},
{registered,[inets_sup, httpc_manager]},
%% If the "new" ssl is used then 'crypto' must be started before inets.
{applications,[kernel,stdlib]},
{mod,{inets_app,[]}},
- {runtime_dependencies, ["stdlib-2.0","ssl-5.3.4","runtime_tools-1.8.14",
+ {runtime_dependencies, ["stdlib-3.5","ssl-5.3.4","runtime_tools-1.8.14",
"mnesia-4.12","kernel-3.0","erts-6.0"]}]}.
diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src
index f9ad8709d9..b197590bfd 100644
--- a/lib/inets/src/inets_app/inets.appup.src
+++ b/lib/inets/src/inets_app/inets.appup.src
@@ -1,7 +1,7 @@
%% -*- erlang -*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,14 +18,12 @@
%% %CopyrightEnd%
{"%VSN%",
[
- {<<"6.2.4">>, [{load_module, httpd_request_handler,
- soft_purge, soft_purge, []}]},
+ {<<"7\\..*">>,[{restart_application, inets}]},
{<<"6\\..*">>,[{restart_application, inets}]},
{<<"5\\..*">>,[{restart_application, inets}]}
],
[
- {<<"6.2.4">>, [{load_module, httpd_request_handler,
- soft_purge, soft_purge, []}]},
+ {<<"7\\..*">>,[{restart_application, inets}]},
{<<"6\\..*">>,[{restart_application, inets}]},
{<<"5\\..*">>,[{restart_application, inets}]}
]
diff --git a/lib/inets/src/inets_app/inets.erl b/lib/inets/src/inets_app/inets.erl
index 2d380012d7..ab2bc5b784 100644
--- a/lib/inets/src/inets_app/inets.erl
+++ b/lib/inets/src/inets_app/inets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -465,13 +465,19 @@ call_service(Service, Call, Args) ->
exit:{noproc, _} ->
{error, inets_not_started}
end.
-
+
+%% Obsolete! Kept for backward compatiblity!
+%% TFTP application has been moved out from inets
service_module(tftpd) ->
- tftp;
+ inets_tftp_wrapper;
service_module(tftpc) ->
- tftp;
+ inets_tftp_wrapper;
+service_module(tftp) ->
+ inets_tftp_wrapper;
+%% Obsolete! Kept for backward compatiblity!
+%% FTP application has been moved out from inets
service_module(ftpc) ->
- ftp;
+ inets_ftp_wrapper;
service_module(Service) ->
Service.
diff --git a/lib/inets/src/inets_app/inets_ftp_wrapper.erl b/lib/inets/src/inets_app/inets_ftp_wrapper.erl
new file mode 100644
index 0000000000..e350a490f7
--- /dev/null
+++ b/lib/inets/src/inets_app/inets_ftp_wrapper.erl
@@ -0,0 +1,48 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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(inets_ftp_wrapper).
+
+
+-export([start_standalone/1,
+ start_service/1,
+ stop_service/1,
+ services/0,
+ service_info/1]).
+
+
+start_standalone(Options) ->
+ ftp:start_standalone(Options).
+
+
+start_service(Options) ->
+ application:ensure_started(ftp),
+ ftp:start_service(Options).
+
+
+stop_service(Pid) ->
+ ftp:stop_service(Pid).
+
+
+services() ->
+ [].
+
+
+service_info(_) ->
+ [].
diff --git a/lib/inets/src/inets_app/inets_internal.hrl b/lib/inets/src/inets_app/inets_internal.hrl
index 079b415b56..38b7e68638 100644
--- a/lib/inets/src/inets_app/inets_internal.hrl
+++ b/lib/inets/src/inets_app/inets_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,8 +22,6 @@
-ifndef(inets_internal_hrl).
-define(inets_internal_hrl, true).
--define(STACK(), erlang:get_stacktrace()).
-
%% Various trace macros
-define(report(Severity, Label, Service, Content),
diff --git a/lib/inets/src/inets_app/inets_sup.erl b/lib/inets/src/inets_app/inets_sup.erl
index d8ae7eff26..0d3c7475fc 100644
--- a/lib/inets/src/inets_app/inets_sup.erl
+++ b/lib/inets/src/inets_app/inets_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -61,19 +61,7 @@ children() ->
Services = get_services(),
HttpdServices = [Service || Service <- Services, is_httpd(Service)],
HttpcServices = [Service || Service <- Services, is_httpc(Service)],
- TftpdServices = [Service || Service <- Services, is_tftpd(Service)],
- [ftp_child_spec(), httpc_child_spec(HttpcServices),
- httpd_child_spec(HttpdServices), tftpd_child_spec(TftpdServices)].
-
-ftp_child_spec() ->
- Name = ftp_sup,
- StartFunc = {ftp_sup, start_link, []},
- Restart = permanent,
- Shutdown = infinity,
- Modules = [ftp_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
-
+ [httpc_child_spec(HttpcServices), httpd_child_spec(HttpdServices)].
httpc_child_spec(HttpcServices0) ->
HttpcServices = default_profile(HttpcServices0, []),
@@ -94,15 +82,6 @@ httpd_child_spec(HttpdServices) ->
Type = supervisor,
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
-tftpd_child_spec(TftpServices) ->
- Name = tftp_sup,
- StartFunc = {tftp_sup, start_link, [TftpServices]},
- Restart = permanent,
- Shutdown = infinity,
- Modules = [tftp_sup],
- Type = supervisor,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
-
is_httpd({httpd, _}) ->
true;
is_httpd({httpd, _, _}) ->
@@ -115,11 +94,6 @@ is_httpc({httpc, _}) ->
is_httpc(_) ->
false.
-is_tftpd({tftpd, _}) ->
- true;
-is_tftpd(_) ->
- false.
-
default_profile([], Acc) ->
[{httpc, {default, only_session_cookies}} | Acc];
default_profile([{httpc, {default, _}} | _] = Profiles, Acc) ->
diff --git a/lib/inets/src/inets_app/inets_tftp_wrapper.erl b/lib/inets/src/inets_app/inets_tftp_wrapper.erl
new file mode 100644
index 0000000000..1e5deb234b
--- /dev/null
+++ b/lib/inets/src/inets_app/inets_tftp_wrapper.erl
@@ -0,0 +1,48 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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(inets_tftp_wrapper).
+
+
+-export([start_standalone/1,
+ start_service/1,
+ stop_service/1,
+ services/0,
+ service_info/1]).
+
+
+start_standalone(Options) ->
+ tftp:start_standalone(Options).
+
+
+start_service(Options) ->
+ application:ensure_started(tftp),
+ tftp:start_service(Options).
+
+
+stop_service(Pid) ->
+ tftp:stop_service(Pid).
+
+
+services() ->
+ [].
+
+
+service_info(_) ->
+ [].
diff --git a/lib/inets/src/subdirs.mk b/lib/inets/src/subdirs.mk
index 9f2a0079f2..e9f4de959c 100644
--- a/lib/inets/src/subdirs.mk
+++ b/lib/inets/src/subdirs.mk
@@ -1,3 +1,3 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
-SUB_DIRECTORIES = inets_app http_lib http_client http_server ftp tftp
+SUB_DIRECTORIES = inets_app http_lib http_client http_server
diff --git a/lib/inets/src/tftp/Makefile b/lib/inets/src/tftp/Makefile
deleted file mode 100644
index 4eaa959cce..0000000000
--- a/lib/inets/src/tftp/Makefile
+++ /dev/null
@@ -1,109 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2005-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-
-include $(ERL_TOP)/make/target.mk
-EBIN = ../../ebin
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-
-VSN = $(INETS_VSN)
-
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
-
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-BEHAVIOUR_MODULES= \
- tftp
-
-MODULES = \
- tftp_binary \
- tftp_engine \
- tftp_file \
- tftp_lib \
- tftp_logger \
- tftp_sup
-
-HRL_FILES = tftp.hrl
-
-ERL_FILES= \
- $(MODULES:%=%.erl) \
- $(BEHAVIOUR_MODULES:%=%.erl)
-
-TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-BEHAVIOUR_TARGET_FILES= $(BEHAVIOUR_MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-
-include ../inets_app/inets.mk
-
-ERL_COMPILE_FLAGS += \
- $(INETS_FLAGS) \
- $(INETS_ERL_COMPILE_FLAGS) \
- -I../../include \
- -I../inets_app
-
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-$(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES)
-
-debug opt: $(TARGET_FILES)
-
-clean:
- rm -f $(TARGET_FILES) $(BEHAVIOUR_TARGET_FILES)
- rm -f core
-
-docs:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/src"
- $(INSTALL_DIR) "$(RELSYSDIR)/src/tftp"
- $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) "$(RELSYSDIR)/src/tftp"
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) $(BEHAVIOUR_TARGET_FILES) "$(RELSYSDIR)/ebin"
-
-release_docs_spec:
-
-info:
- @echo "APPLICATION = $(APPLICATION)"
- @echo "INETS_DEBUG = $(INETS_DEBUG)"
- @echo "INETS_FLAGS = $(INETS_FLAGS)"
- @echo "ERL_COMPILE_FLAGS = $(ERL_COMPILE_FLAGS)"
diff --git a/lib/inets/src/tftp/tftp.erl b/lib/inets/src/tftp/tftp.erl
deleted file mode 100644
index c8804ea55f..0000000000
--- a/lib/inets/src/tftp/tftp.erl
+++ /dev/null
@@ -1,398 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-%%%-------------------------------------------------------------------
-%%% File : tftp.erl
-%%% Author : Hakan Mattsson <[email protected]>
-%%% Description : Trivial FTP
-%%% Created : 18 May 2004 by Hakan Mattsson <[email protected]>
-%%%-------------------------------------------------------------------
-%%%
-%%% This is a complete implementation of the following IETF standards:
-%%%
-%%% RFC 1350, The TFTP Protocol (revision 2).
-%%% RFC 2347, TFTP Option Extension.
-%%% RFC 2348, TFTP Blocksize Option.
-%%% RFC 2349, TFTP Timeout Interval and Transfer Size Options.
-%%%
-%%% The only feature that not is implemented in this release is
-%%% the "netascii" transfer mode.
-%%%
-%%% The start/1 function starts a daemon process which, listens for
-%%% UDP packets on a port. When it receives a request for read or
-%%% write it spawns a temporary server process which handles the
-%%% actual transfer of the file. On the client side the read_file/3
-%%% and write_file/3 functions spawns a temporary client process which
-%%% establishes contact with a TFTP daemon and performs the actual
-%%% transfer of the file.
-%%%
-%%% Most of the options are common for both the client and the server
-%%% side, but some of them differs a little. Here are the available
-%%% options:
-%%%
-%%% {debug, Level}
-%%%
-%%% Level = none | error | warning brief | normal | verbose | all
-%%%
-%%% Controls the level of debug printouts. The default is none.
-%%%
-%%% {host, Host}
-%%%
-%%% The name or IP address of the host where the TFTP daemon
-%%% resides. This option is only used by the client. See
-%%% 'inet' about valid host names.
-%%%
-%%% {port, Port}
-%%%
-%%% Port = integer()
-%%%
-%%% The TFTP port where the daemon listens. It defaults to the
-%%% standardized number 69. On the server side it may sometimes
-%%% make sense to set it to 0, which means that the daemon just
-%%% will pick a free port (which is returned by the start/1
-%%% function).
-%%%
-%%% If a socket has somehow already has been connected, the
-%%% {udp, [{fd, integer()}]} option can be used to pass the
-%%% open file descriptor to gen_udp. This can be automated
-%%% a bit by using a command line argument stating the
-%%% prebound file descriptor number. For example, if the
-%%% Port is 69 and the file descriptor 22 has been opened by
-%%% setuid_socket_wrap. Then the command line argument
-%%% "-tftpd_69 22" will trigger the prebound file
-%%% descriptor 22 to be used instead of opening port 69.
-%%% The UDP option {udp, [{fd, 22}]} autmatically be added.
-%%% See init:get_argument/ about command line arguments and
-%%% gen_udp:open/2 about UDP options.
-%%%
-%%% {port_policy, Policy}
-%%%
-%%% Policy = random | Port | {range, MinPort, MaxPort}
-%%% Port = MinPort = MaxPort = integer()
-%%%
-%%% Policy for the selection of the temporary port which is used
-%%% by the server/client during the file transfer. It defaults to
-%%% 'random' which is the standardized policy. With this policy a
-%%% randomized free port used. A single port or a range of ports
-%%% can be useful if the protocol should pass thru a firewall.
-%%%
-%%% {prebound_fd, InitArgFlag}
-%%%
-%%% InitArgFlag = atom()
-%%%
-%%% If a socket has somehow already has been connected, the
-%%% {udp, [{fd, integer()}]} option can be used to pass the
-%%% open file descriptor to gen_udp.
-%%%
-%%% The prebound_fd option makes it possible to pass give the
-%%% file descriptor as a command line argument. The typical
-%%% usage is when used in conjunction with setuid_socket_wrap
-%%% to be able to open privileged sockets. For example if the
-%%% file descriptor 22 has been opened by setuid_socket_wrap
-%%% and you have choosen my_tftp_fd as init argument, the
-%%% command line should like this "erl -my_tftp_fd 22" and
-%%% FileDesc should be set to my_tftpd_fd. This would
-%%% automatically imply {fd, 22} to be set as UDP option.
-%%%
-%%% {udp, UdpOptions}
-%%%
-%%% Options to gen_udp:open/2.
-%%%
-%%% {use_tsize, Bool}
-%%%
-%%% Bool = boolean()
-%%%
-%%% Flag for automated usage of the "tsize" option. With this set
-%%% to true, the write_file/3 client will determine the filesize
-%%% and send it to the server as the standardized "tsize" option.
-%%% A read_file/3 client will just acquire filesize from the
-%%% server by sending a zero "tsize".
-%%%
-%%% {max_tsize, MaxTsize}
-%%%
-%%% MaxTsize = integer() | infinity
-%%%
-%%% Threshold for the maximal filesize in bytes. The transfer will
-%%% be aborted if the limit is exceeded. It defaults to
-%%% 'infinity'.
-%%%
-%%% {max_conn, MaxConn}
-%%%
-%%% MaxConn = integer() | infinity
-%%%
-%%% Threshold for the maximal number of active connections. The
-%%% daemon will reject the setup of new connections if the limit
-%%% is exceeded. It defaults to 'infinity'.
-%%%
-%%% {TftpKey, TftpVal}
-%%%
-%%% TftpKey = string()
-%%% TftpVal = string()
-%%%
-%%% The name and value of a TFTP option.
-%%%
-%%% {reject, Feature}
-%%%
-%%% Feature = Mode | TftpKey
-%%% Mode = read | write
-%%% TftpKey = string()
-%%%
-%%% Control which features that should be rejected.
-%%% This is mostly useful for the server as it may restrict
-%%% usage of certain TFTP options or read/write access.
-%%%
-%%% {callback, {RegExp, Module, State}}
-%%%
-%%% RegExp = string()
-%%% Module = atom()
-%%% State = term()
-%%%
-%%% Registration of a callback module. When a file is to be
-%%% transferred, its local filename will be matched to the
-%%% regular expressions of the registered callbacks. The first
-%%% matching callback will be used the during the transfer.The
-%%% callback module must implement the 'tftp' behaviour.
-%%%
-%%% On the server side the callback interaction starts with a
-%%% call to open/5 with the registered initial callback
-%%% state. open/5 is expected to open the (virtual) file. Then
-%%% either the read/1 or write/2 functions are invoked
-%%% repeatedly, once per transfererred block. At each function
-%%% call the state returned from the previous call is
-%%% obtained. When the last block has been encountered the read/1
-%%% or write/2 functions is expected to close the (virtual)
-%%% file.and return its last state. The abort/3 function is only
-%%% used in error situations. prepare/5 is not used on the server
-%%% side.
-%%%
-%%% On the client side the callback interaction is the same, but
-%%% it starts and ends a bit differently. It starts with a call
-%%% to prepare/5 with the same arguments as open/5
-%%% takes. prepare/5 is expected to validate the TFTP options,
-%%% suggested by the user and return the subset of them that it
-%%% accepts. Then the options is sent to the server which will
-%%% perform the same TFTP option negotiation procedure. The
-%%% options that are accepted by the server is forwarded to the
-%%% open/5 function on the client side. On the client side the
-%%% open/5 function must accept all option as is or reject the
-%%% transfer. Then the callback interaction follows the same
-%%% pattern as described above for the server side. When the last
-%%% block is encountered in read/1 or write/2 the returned stated
-%%% is forwarded to the user and returned from read_file/3 or
-%%% write_file/3.
-%%%-------------------------------------------------------------------
-
--module(tftp).
-
-%%-------------------------------------------------------------------
-%% Interface
-%%-------------------------------------------------------------------
-
-%% Public functions
--export([
- read_file/3,
- write_file/3,
- start/1,
- info/1,
- change_config/2,
- start/0
- ]).
-
-%% Application local functions
--export([
- start_standalone/1,
- start_service/1,
- stop_service/1,
- services/0,
- service_info/1
- ]).
-
-
--type peer() :: {PeerType :: inet | inet6,
- PeerHost :: inet:ip_address(),
- PeerPort :: port()}.
-
--type access() :: read | write.
-
--type options() :: [{Key :: string(), Value :: string()}].
-
--type error_code() :: undef | enoent | eacces | enospc |
- badop | eexist | baduser | badopt |
- integer().
-
--callback prepare(Peer :: peer(),
- Access :: access(),
- Filename :: file:name(),
- Mode :: string(),
- SuggestedOptions :: options(),
- InitialState :: [] | [{root_dir, string()}]) ->
- {ok, AcceptedOptions :: options(), NewState :: term()} |
- {error, {Code :: error_code(), string()}}.
-
--callback open(Peer :: peer(),
- Access :: access(),
- Filename :: file:name(),
- Mode :: string(),
- SuggestedOptions :: options(),
- State :: [] | [{root_dir, string()}] | term()) ->
- {ok, AcceptedOptions :: options(), NewState :: term()} |
- {error, {Code :: error_code(), string()}}.
-
--callback read(State :: term()) -> {more, binary(), NewState :: term()} |
- {last, binary(), integer()} |
- {error, {Code :: error_code(), string()}}.
-
--callback write(binary(), State :: term()) ->
- {more, NewState :: term()} |
- {last, FileSize :: integer()} |
- {error, {Code :: error_code(), string()}}.
-
--callback abort(Code :: error_code(), string(), State :: term()) -> 'ok'.
-
--include("tftp.hrl").
-
-
-%%-------------------------------------------------------------------
-%% read_file(RemoteFilename, LocalFilename, Options) ->
-%% {ok, LastCallbackState} | {error, Reason}
-%%
-%% RemoteFilename = string()
-%% LocalFilename = binary | string()
-%% Options = [option()]
-%% LastCallbackState = term()
-%% Reason = term()
-%%
-%% Reads a (virtual) file from a TFTP server
-%%
-%% If LocalFilename is the atom 'binary', tftp_binary will be used as
-%% callback module. It will concatenate all transferred blocks and
-%% return them as one single binary in the CallbackState.
-%%
-%% When LocalFilename is a string, it will be matched to the
-%% registered callback modules and hopefully one of them will be
-%% selected. By default, tftp_file will be used as callback module. It
-%% will write each transferred block to the file named
-%% LocalFilename. The number of transferred bytes will be returned as
-%% LastCallbackState.
-%%-------------------------------------------------------------------
-
-read_file(RemoteFilename, LocalFilename, Options) ->
- tftp_engine:client_start(read, RemoteFilename, LocalFilename, Options).
-
-%%-------------------------------------------------------------------
-%% write(RemoteFilename, LocalFilename, Options) ->
-%% {ok, LastCallbackState} | {error, Reason}
-%%
-%% RemoteFilename = string()
-%% LocalFilename = binary() | string()
-%% Options = [option()]
-%% LastCallbackState = term()
-%% Reason = term()
-%%
-%% Writes a (virtual) file to a TFTP server
-%%
-%% If LocalFilename is a binary, tftp_binary will be used as callback
-%% module. The binary will be transferred block by block and the number
-%% of transferred bytes will be returned as LastCallbackState.
-%%
-%% When LocalFilename is a string, it will be matched to the
-%% registered callback modules and hopefully one of them will be
-%% selected. By default, tftp_file will be used as callback module. It
-%% will read the file named LocalFilename block by block. The number
-%% of transferred bytes will be returned as LastCallbackState.
-%%-------------------------------------------------------------------
-
-write_file(RemoteFilename, LocalFilename, Options) ->
- tftp_engine:client_start(write, RemoteFilename, LocalFilename, Options).
-
-%%-------------------------------------------------------------------
-%% start(Options) -> {ok, Pid} | {error, Reason}
-%%
-%% Options = [option()]
-%% Pid = pid()
-%% Reason = term()
-%%
-%% Starts a daemon process which listens for udp packets on a
-%% port. When it receives a request for read or write it spawns
-%% a temporary server process which handles the actual transfer
-%% of the (virtual) file.
-%%-------------------------------------------------------------------
-
-start(Options) ->
- tftp_engine:daemon_start(Options).
-
-%%-------------------------------------------------------------------
-%% info(Pid) -> {ok, Options} | {error, Reason}
-%%
-%% Options = [option()]
-%% Reason = term()
-%%
-%% Returns info about a tftp daemon, server or client process
-%%-------------------------------------------------------------------
-
-info(Pid) ->
- tftp_engine:info(Pid).
-
-%%-------------------------------------------------------------------
-%% change_config(Pid, Options) -> ok | {error, Reason}
-%%
-%% Options = [option()]
-%% Reason = term()
-%%
-%% Changes config for a tftp daemon, server or client process
-%% Must be used with care.
-%%-------------------------------------------------------------------
-
-change_config(Pid, Options) ->
- tftp_engine:change_config(Pid, Options).
-
-%%-------------------------------------------------------------------
-%% start() -> ok | {error, Reason}
-%%
-%% Reason = term()
-%%
-%% Start the application
-%%-------------------------------------------------------------------
-
-start() ->
- application:start(inets).
-
-%%-------------------------------------------------------------------
-%% Inets service behavior
-%%-------------------------------------------------------------------
-
-start_standalone(Options) ->
- start(Options).
-
-start_service(Options) ->
- tftp_sup:start_child(Options).
-
-stop_service(Pid) ->
- tftp_sup:stop_child(Pid).
-
-services() ->
- tftp_sup:which_children().
-
-service_info(Pid) ->
- info(Pid).
-
-
-
diff --git a/lib/inets/src/tftp/tftp.hrl b/lib/inets/src/tftp/tftp.hrl
deleted file mode 100644
index 25543e0b9e..0000000000
--- a/lib/inets/src/tftp/tftp.hrl
+++ /dev/null
@@ -1,69 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-%%%-------------------------------------------------------------------
-%%% Defines
-%%%-------------------------------------------------------------------
-
--define(TFTP_DEFAULT_PORT, 69).% Default server port
-
--define(TFTP_OPCODE_RRQ, 1). % Read request
--define(TFTP_OPCODE_WRQ, 2). % Write request
--define(TFTP_OPCODE_DATA, 3). % Data
--define(TFTP_OPCODE_ACK, 4). % Acknowledgement
--define(TFTP_OPCODE_ERROR, 5). % Error
--define(TFTP_OPCODE_OACK, 6). % Option acknowledgment
-
--define(TFTP_ERROR_UNDEF, 0). % Not defined, see error message (if any)
--define(TFTP_ERROR_ENOENT, 1). % File not found.
--define(TFTP_ERROR_EACCES, 2). % Access violation.
--define(TFTP_ERROR_ENOSPC, 3). % Disk full or allocation exceeded.
--define(TFTP_ERROR_BADOP, 4). % Illegal TFTP operation.
--define(TFTP_ERROR_BADBLK, 5). % Unknown transfer ID.
--define(TFTP_ERROR_EEXIST, 6). % File already exists.
--define(TFTP_ERROR_BADUSER, 7). % No such user.
--define(TFTP_ERROR_BADOPT, 8). % Unrequested or illegal option.
-
--record(tftp_msg_req, {access, filename, mode, options, local_filename}).
--record(tftp_msg_data, {block_no, data}).
--record(tftp_msg_ack, {block_no}).
--record(tftp_msg_error, {code, text, details}).
--record(tftp_msg_oack, {options}).
-
--record(config, {parent_pid = self(),
- udp_socket,
- udp_options = [binary, {reuseaddr, true}, {active, once}],
- udp_host = "localhost",
- udp_port = ?TFTP_DEFAULT_PORT,
- port_policy = random,
- use_tsize = false,
- max_tsize = infinity, % Filesize
- max_conn = infinity,
- rejected = [],
- polite_ack = false,
- debug_level = none,
- timeout,
- user_options = [],
- callbacks = [],
- logger = tftp_logger,
- max_retries = 5}).
-
--record(callback, {regexp, internal, module, state, block_no, count}).
diff --git a/lib/inets/src/tftp/tftp_binary.erl b/lib/inets/src/tftp/tftp_binary.erl
deleted file mode 100644
index 09adcfc41f..0000000000
--- a/lib/inets/src/tftp/tftp_binary.erl
+++ /dev/null
@@ -1,239 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-%%%-------------------------------------------------------------------
-%%% File : tft_binary.erl
-%%% Author : Hakan Mattsson <[email protected]>
-%%% Description :
-%%%
-%%% Created : 24 May 2004 by Hakan Mattsson <[email protected]>
-%%%-------------------------------------------------------------------
-
--module(tftp_binary).
-
-%%%-------------------------------------------------------------------
-%%% Interface
-%%%-------------------------------------------------------------------
-
--behaviour(tftp).
-
--export([prepare/6, open/6, read/1, write/2, abort/3]).
-
--record(read_state, {options, blksize, bin, is_native_ascii, is_network_ascii, count}).
--record(write_state, {options, blksize, list, is_native_ascii, is_network_ascii}).
-
-%%-------------------------------------------------------------------
-%% Prepare
-%%-------------------------------------------------------------------
-
-prepare(_Peer, Access, Filename, Mode, SuggestedOptions, Initial) when is_list(Initial) ->
- %% Client side
- IsNativeAscii = is_native_ascii(Initial),
- case catch handle_options(Access, Filename, Mode, SuggestedOptions, IsNativeAscii) of
- {ok, IsNetworkAscii, AcceptedOptions} when Access =:= read, is_binary(Filename) ->
- State = #read_state{options = AcceptedOptions,
- blksize = lookup_blksize(AcceptedOptions),
- bin = Filename,
- is_network_ascii = IsNetworkAscii,
- count = size(Filename),
- is_native_ascii = IsNativeAscii},
- {ok, AcceptedOptions, State};
- {ok, IsNetworkAscii, AcceptedOptions} when Access =:= write, Filename =:= binary ->
- State = #write_state{options = AcceptedOptions,
- blksize = lookup_blksize(AcceptedOptions),
- list = [],
- is_network_ascii = IsNetworkAscii,
- is_native_ascii = IsNativeAscii},
- {ok, AcceptedOptions, State};
- {ok, _, _} ->
- {error, {undef, "Illegal callback usage. Mode and filename is incompatible."}};
- {error, {Code, Text}} ->
- {error, {Code, Text}}
- end;
-prepare(_Peer, _Access, _Bin, _Mode, _SuggestedOptions, _Initial) ->
- {error, {undef, "Illegal callback options."}}.
-
-%%-------------------------------------------------------------------
-%% Open
-%%-------------------------------------------------------------------
-
-open(Peer, Access, Filename, Mode, SuggestedOptions, Initial) when is_list(Initial) ->
- %% Server side
- case prepare(Peer, Access, Filename, Mode, SuggestedOptions, Initial) of
- {ok, AcceptedOptions, State} ->
- open(Peer, Access, Filename, Mode, AcceptedOptions, State);
- {error, {Code, Text}} ->
- {error, {Code, Text}}
- end;
-open(_Peer, Access, Filename, Mode, NegotiatedOptions, State) when is_record(State, read_state) ->
- %% Both sides
- case catch handle_options(Access, Filename, Mode, NegotiatedOptions, State#read_state.is_native_ascii) of
- {ok, IsNetworkAscii, Options}
- when Options =:= NegotiatedOptions,
- IsNetworkAscii =:= State#read_state.is_network_ascii ->
- {ok, NegotiatedOptions, State};
- {error, {Code, Text}} ->
- {error, {Code, Text}}
- end;
-open(_Peer, Access, Filename, Mode, NegotiatedOptions, State) when is_record(State, write_state) ->
- %% Both sides
- case catch handle_options(Access, Filename, Mode, NegotiatedOptions, State#write_state.is_native_ascii) of
- {ok, IsNetworkAscii, Options}
- when Options =:= NegotiatedOptions,
- IsNetworkAscii =:= State#write_state.is_network_ascii ->
- {ok, NegotiatedOptions, State};
- {error, {Code, Text}} ->
- {error, {Code, Text}}
- end;
-open(Peer, Access, Filename, Mode, NegotiatedOptions, State) ->
- %% Handle upgrade from old releases. Please, remove this clause in next release.
- State2 = upgrade_state(State),
- open(Peer, Access, Filename, Mode, NegotiatedOptions, State2).
-
-%%-------------------------------------------------------------------
-%% Read
-%%-------------------------------------------------------------------
-
-read(#read_state{bin = Bin} = State) when is_binary(Bin) ->
- BlkSize = State#read_state.blksize,
- if
- size(Bin) >= BlkSize ->
- <<Block:BlkSize/binary, Bin2/binary>> = Bin,
- State2 = State#read_state{bin = Bin2},
- {more, Block, State2};
- size(Bin) < BlkSize ->
- {last, Bin, State#read_state.count}
- end;
-read(State) ->
- %% Handle upgrade from old releases. Please, remove this clause in next release.
- State2 = upgrade_state(State),
- read(State2).
-
-%%-------------------------------------------------------------------
-%% Write
-%%-------------------------------------------------------------------
-
-write(Bin, #write_state{list = List} = State) when is_binary(Bin), is_list(List) ->
- Size = size(Bin),
- BlkSize = State#write_state.blksize,
- if
- Size =:= BlkSize ->
- {more, State#write_state{list = [Bin | List]}};
- Size < BlkSize ->
- Bin2 = list_to_binary(lists:reverse([Bin | List])),
- {last, Bin2}
- end;
-write(Bin, State) ->
- %% Handle upgrade from old releases. Please, remove this clause in next release.
- State2 = upgrade_state(State),
- write(Bin, State2).
-
-%%-------------------------------------------------------------------
-%% Abort
-%%-------------------------------------------------------------------
-
-abort(_Code, _Text, #read_state{bin = Bin} = State)
- when is_record(State, read_state), is_binary(Bin) ->
- ok;
-abort(_Code, _Text, #write_state{list = List} = State)
- when is_record(State, write_state), is_list(List) ->
- ok;
-abort(Code, Text, State) ->
- %% Handle upgrade from old releases. Please, remove this clause in next release.
- State2 = upgrade_state(State),
- abort(Code, Text, State2).
-
-%%-------------------------------------------------------------------
-%% Process options
-%%-------------------------------------------------------------------
-
-handle_options(Access, Bin, Mode, Options, IsNativeAscii) ->
- IsNetworkAscii = handle_mode(Mode, IsNativeAscii),
- Options2 = do_handle_options(Access, Bin, Options),
- {ok, IsNetworkAscii, Options2}.
-
-handle_mode(Mode, IsNativeAscii) ->
- case Mode of
- "netascii" when IsNativeAscii =:= true -> true;
- "octet" -> false;
- _ -> throw({error, {badop, "Illegal mode " ++ Mode}})
- end.
-
-do_handle_options(Access, Bin, [{Key, Val} | T]) ->
- case Key of
- "tsize" ->
- case Access of
- read when Val =:= "0", is_binary(Bin) ->
- Tsize = integer_to_list(size(Bin)),
- [{Key, Tsize} | do_handle_options(Access, Bin, T)];
- _ ->
- handle_integer(Access, Bin, Key, Val, T, 0, infinity)
- end;
- "blksize" ->
- handle_integer(Access, Bin, Key, Val, T, 8, 65464);
- "timeout" ->
- handle_integer(Access, Bin, Key, Val, T, 1, 255);
- _ ->
- do_handle_options(Access, Bin, T)
- end;
-do_handle_options(_Access, _Bin, []) ->
- [].
-
-
-handle_integer(Access, Bin, Key, Val, Options, Min, Max) ->
- case catch list_to_integer(Val) of
- {'EXIT', _} ->
- do_handle_options(Access, Bin, Options);
- Int when Int >= Min, Int =< Max ->
- [{Key, Val} | do_handle_options(Access, Bin, Options)];
- Int when Int >= Min, Max =:= infinity ->
- [{Key, Val} | do_handle_options(Access, Bin, Options)];
- _Int ->
- throw({error, {badopt, "Illegal " ++ Key ++ " value " ++ Val}})
- end.
-
-lookup_blksize(Options) ->
- case lists:keysearch("blksize", 1, Options) of
- {value, {_, Val}} ->
- list_to_integer(Val);
- false ->
- 512
- end.
-
-is_native_ascii([]) ->
- is_native_ascii();
-is_native_ascii([{native_ascii, Bool}]) ->
- case Bool of
- true -> true;
- false -> false
- end.
-
-is_native_ascii() ->
- case os:type() of
- {win32, _} -> true;
- _ -> false
- end.
-
-%% Handle upgrade from old releases. Please, remove this function in next release.
-upgrade_state({read_state, Options, Blksize, Bin, IsNetworkAscii, Count}) ->
- {read_state, Options, Blksize, Bin, false, IsNetworkAscii, Count};
-upgrade_state({write_state, Options, Blksize, List, IsNetworkAscii}) ->
- {write_state, Options, Blksize, List, false, IsNetworkAscii}.
diff --git a/lib/inets/src/tftp/tftp_engine.erl b/lib/inets/src/tftp/tftp_engine.erl
deleted file mode 100644
index fb2c9749e5..0000000000
--- a/lib/inets/src/tftp/tftp_engine.erl
+++ /dev/null
@@ -1,1422 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%-------------------------------------------------------------------
-%% Protocol engine for trivial FTP
-%%-------------------------------------------------------------------
-
--module(tftp_engine).
-
-%%%-------------------------------------------------------------------
-%%% Interface
-%%%-------------------------------------------------------------------
-
-%% application internal functions
--export([
- daemon_start/1,
- daemon_loop/1,
- daemon_loop/3, %% Handle upgrade from old releases. Please, remove this function in next release.
- client_start/4,
- common_loop/6,
- info/1,
- change_config/2
- ]).
-
-%% module internal
--export([
- daemon_init/1,
- server_init/2,
- client_init/2,
- wait_for_msg/3,
- callback/4
- ]).
-
-%% sys callback functions
--export([
- system_continue/3,
- system_terminate/4,
- system_code_change/4
- ]).
-
--include("tftp.hrl").
-
--type prep_status() :: 'error' | 'last' | 'more' | 'terminate'.
-
--record(daemon_state, {config, n_servers, server_tab, file_tab}).
--record(server_info, {pid, req, peer}).
--record(file_info, {peer_req, pid}).
--record(sys_misc, {module, function, arguments}).
--record(error, {where, code, text, filename}).
--record(prepared, {status :: prep_status() | 'undefined',
- result, block_no, next_data, prev_data}).
--record(transfer_res, {status, decoded_msg, prepared}).
--define(ERROR(Where, Code, Text, Filename),
- #error{where = Where, code = Code, text = Text, filename = Filename}).
-
-%%%-------------------------------------------------------------------
-%%% Info
-%%%-------------------------------------------------------------------
-
-info(daemons) ->
- Daemons = supervisor:which_children(tftp_sup),
- [{Pid, info(Pid)} || {_, Pid, _, _} <- Daemons];
-info(servers) ->
- [{Pid, info(Pid)} || {_, {ok, DeamonInfo}} <- info(daemons),
- {server, Pid} <- DeamonInfo];
-info(ToPid) when is_pid(ToPid) ->
- call(info, ToPid, timer:seconds(10)).
-
-change_config(daemons, Options) ->
- Daemons = supervisor:which_children(tftp_sup),
- [{Pid, change_config(Pid, Options)} || {_, Pid, _, _} <- Daemons];
-change_config(servers, Options) ->
- [{Pid, change_config(Pid, Options)} || {_, {ok, DeamonInfo}} <- info(daemons),
- {server, Pid} <- DeamonInfo];
-change_config(ToPid, Options) when is_pid(ToPid) ->
- BadKeys = [host, port, udp],
- BadOptions = [{Key, Val} || {Key, Val} <- Options,
- BadKey <- BadKeys,
- Key =:= BadKey],
- case BadOptions of
- [] ->
- call({change_config, Options}, ToPid, timer:seconds(10));
- [{Key, Val} | _] ->
- {error, {badarg, {Key, Val}}}
- end.
-
-call(Req, ToPid, Timeout) when is_pid(ToPid) ->
- Type = process,
- Ref = erlang:monitor(Type, ToPid),
- ToPid ! {Req, Ref, self()},
- receive
- {Reply, Ref, FromPid} when FromPid =:= ToPid ->
- erlang:demonitor(Ref, [flush]),
- Reply;
- {'DOWN', Ref, Type, FromPid, _Reason} when FromPid =:= ToPid ->
- {error, timeout}
- after Timeout ->
- {error, timeout}
- end.
-
-reply(Reply, Ref, ToPid) ->
- ToPid ! {Reply, Ref, self()}.
-
-%%%-------------------------------------------------------------------
-%%% Daemon
-%%%-------------------------------------------------------------------
-
-%% Returns {ok, Port}
-daemon_start(Options) when is_list(Options) ->
- Config = tftp_lib:parse_config(Options),
- proc_lib:start_link(?MODULE, daemon_init, [Config], infinity).
-
-daemon_init(Config) when is_record(Config, config),
- is_pid(Config#config.parent_pid) ->
- process_flag(trap_exit, true),
- {Port, UdpOptions} = prepare_daemon_udp(Config),
- case catch gen_udp:open(Port, UdpOptions) of
- {ok, Socket} ->
- {ok, ActualPort} = inet:port(Socket),
- proc_lib:init_ack({ok, self()}),
- Config2 = Config#config{udp_socket = Socket,
- udp_port = ActualPort},
- print_debug_info(Config2, daemon, open, #tftp_msg_req{filename = ""}),
- ServerTab = ets:new(tftp_daemon_servers, [{keypos, 2}]),
- FileTab = ets:new(tftp_daemon_files, [{keypos, 2}]),
- State = #daemon_state{config = Config2,
- n_servers = 0,
- server_tab = ServerTab,
- file_tab = FileTab},
- daemon_loop(State);
- {error, Reason} ->
- Text = lists:flatten(io_lib:format("UDP open ~p -> ~p", [UdpOptions, Reason])),
- print_debug_info(Config, daemon, open, ?ERROR(open, undef, Text, "")),
- exit({gen_udp_open, UdpOptions, Reason});
- Reason ->
- Text = lists:flatten(io_lib:format("UDP open ~p -> ~p", [UdpOptions, Reason])),
- print_debug_info(Config, daemon, open, ?ERROR(open, undef, Text, "")),
- exit({gen_udp_open, UdpOptions, Reason})
- end.
-
-prepare_daemon_udp(#config{udp_port = Port, udp_options = UdpOptions} = Config) ->
- case lists:keymember(fd, 1, UdpOptions) of
- true ->
- %% Use explicit fd
- {Port, UdpOptions};
- false ->
- %% Use fd from setuid_socket_wrap, such as -tftpd_69
- InitArg = list_to_atom("tftpd_" ++ integer_to_list(Port)),
- case init:get_argument(InitArg) of
- {ok, [[FdStr]] = Badarg} when is_list(FdStr) ->
- case catch list_to_integer(FdStr) of
- Fd when is_integer(Fd) ->
- {0, [{fd, Fd} | lists:keydelete(ip, 1, UdpOptions)]};
- {'EXIT', _} ->
- Text = lists:flatten(io_lib:format("Illegal prebound fd ~p: ~p", [InitArg, Badarg])),
- print_debug_info(Config, daemon, open, ?ERROR(open, undef, Text, "")),
- exit({badarg, {prebound_fd, InitArg, Badarg}})
- end;
- {ok, Badarg} ->
- Text = lists:flatten(io_lib:format("Illegal prebound fd ~p: ~p", [InitArg, Badarg])),
- print_debug_info(Config, daemon, open, ?ERROR(open, undef, Text, "")),
- exit({badarg, {prebound_fd, InitArg, Badarg}});
- error ->
- {Port, UdpOptions}
- end
- end.
-
-daemon_loop(DaemonConfig, N, Servers) when is_list(Servers) ->
- %% Handle upgrade from old releases. Please, remove this function in next release.
- ServerTab = ets:new(tftp_daemon_servers, [{keypos, 2}]),
- FileTab = ets:new(tftp_daemon_files, [{keypos, 2}]),
- State = #daemon_state{config = DaemonConfig,
- n_servers = N,
- server_tab = ServerTab,
- file_tab = FileTab},
- Req = #tftp_msg_req{filename = dummy},
- [ets:insert(ServerTab, #server_info{pid = Pid, req = Req, peer = dummy}) || Pid <- Servers],
- daemon_loop(State).
-
-daemon_loop(#daemon_state{config = DaemonConfig,
- n_servers = N,
- server_tab = ServerTab,
- file_tab = FileTab} = State) when is_record(DaemonConfig, config) ->
- %% info_msg(DaemonConfig, "=====> TFTP: Daemon #~p\n", [N]), %% XXX
- receive
- {info, Ref, FromPid} when is_pid(FromPid) ->
- Fun = fun(#server_info{pid = Pid}, Acc) -> [{server, Pid} | Acc] end,
- ServerInfo = ets:foldl(Fun, [], ServerTab),
- Info = internal_info(DaemonConfig, daemon) ++ [{n_conn, N}] ++ ServerInfo,
- reply({ok, Info}, Ref, FromPid),
- ?MODULE:daemon_loop(State);
- {{change_config, Options}, Ref, FromPid} when is_pid(FromPid) ->
- case catch tftp_lib:parse_config(Options, DaemonConfig) of
- {'EXIT', Reason} ->
- reply({error, Reason}, Ref, FromPid),
- ?MODULE:daemon_loop(State);
- DaemonConfig2 when is_record(DaemonConfig2, config) ->
- reply(ok, Ref, FromPid),
- ?MODULE:daemon_loop(State#daemon_state{config = DaemonConfig2})
- end;
- {udp, Socket, RemoteHost, RemotePort, Bin} when is_binary(Bin) ->
- inet:setopts(Socket, [{active, once}]),
- ServerConfig = DaemonConfig#config{parent_pid = self(),
- udp_host = RemoteHost,
- udp_port = RemotePort},
- Msg = (catch tftp_lib:decode_msg(Bin)),
- print_debug_info(ServerConfig, daemon, recv, Msg),
- case Msg of
- Req when is_record(Req, tftp_msg_req),
- N =< DaemonConfig#config.max_conn ->
- Peer = peer_info(ServerConfig),
- PeerReq = {Peer, Req},
- PeerInfo = lists:flatten(io_lib:format("~p", [Peer])),
- case ets:lookup(FileTab, PeerReq) of
- [] ->
- Args = [ServerConfig, Req],
- Pid = proc_lib:spawn_link(?MODULE, server_init, Args),
- ets:insert(ServerTab, #server_info{pid = Pid, req = Req, peer = Peer}),
- ets:insert(FileTab, #file_info{peer_req = PeerReq, pid = Pid}),
- ?MODULE:daemon_loop(State#daemon_state{n_servers = N + 1});
- [#file_info{pid = Pid}] ->
- %% Yet another request of the file from same peer
- warning_msg(DaemonConfig, "~p Reuse connection for ~s\n\t~p\n",
- [Pid, PeerInfo, Req#tftp_msg_req.filename]),
- ?MODULE:daemon_loop(State)
- end;
- Req when is_record(Req, tftp_msg_req) ->
- Reply = #tftp_msg_error{code = enospc, text = "Too many connections"},
- Peer = peer_info(ServerConfig),
- PeerInfo = lists:flatten(io_lib:format("~p", [Peer])),
- warning_msg(DaemonConfig,
- "Daemon has too many connections (~p)."
- "\n\tRejecting request from ~s\n",
- [N, PeerInfo]),
- send_msg(ServerConfig, daemon, Reply),
- ?MODULE:daemon_loop(State);
- {'EXIT', Reply} when is_record(Reply, tftp_msg_error) ->
- send_msg(ServerConfig, daemon, Reply),
- ?MODULE:daemon_loop(State);
- Req ->
- Reply = #tftp_msg_error{code = badop,
- text = "Illegal TFTP operation"},
- warning_msg(DaemonConfig, "Daemon received: ~p.\n\tfrom ~p:~p",
- [Req, RemoteHost, RemotePort]),
- send_msg(ServerConfig, daemon, Reply),
- ?MODULE:daemon_loop(State)
- end;
- {system, From, Msg} ->
- Misc = #sys_misc{module = ?MODULE, function = daemon_loop, arguments = [State]},
- sys:handle_system_msg(Msg, From, DaemonConfig#config.parent_pid, ?MODULE, [], Misc);
- {'EXIT', Pid, Reason} when DaemonConfig#config.parent_pid =:= Pid ->
- close_port(DaemonConfig, daemon, #tftp_msg_req{filename = ""}),
- exit(Reason);
- {'EXIT', Pid, _Reason} = Info ->
- case ets:lookup(ServerTab, Pid) of
- [] ->
- warning_msg(DaemonConfig, "Daemon received: ~p", [Info]),
- ?MODULE:daemon_loop(State);
- [#server_info{req = Req, peer = Peer}] ->
- PeerReq = {Peer, Req},
- ets:delete(FileTab, PeerReq),
- ets:delete(ServerTab, Pid),
- ?MODULE:daemon_loop(State#daemon_state{n_servers = N - 1})
- end;
- Info ->
- warning_msg(DaemonConfig, "Daemon received: ~p", [Info]),
- ?MODULE:daemon_loop(State)
- end;
-daemon_loop(#daemon_state{config = Config} = State) ->
- %% Handle upgrade from old releases. Please, remove this clause in next release.
- Config2 = upgrade_config(Config),
- daemon_loop(State#daemon_state{config = Config2}).
-
-upgrade_config({config, ParentPid, UdpSocket, UdpOptions, UdpHost, UdpPort, PortPolicy,
- UseTsize, MaxTsize, MaxConn, Rejected, PoliteAck, DebugLevel,
- Timeout, UserOptions, Callbacks}) ->
- Callbacks2 = tftp_lib:add_default_callbacks(Callbacks),
- Logger = tftp_logger,
- MaxRetries = 5,
- {config, ParentPid, UdpSocket, UdpOptions, UdpHost, UdpPort, PortPolicy,
- UseTsize, MaxTsize, MaxConn, Rejected, PoliteAck, DebugLevel,
- Timeout, UserOptions, Callbacks2, Logger, MaxRetries}.
-
-%%%-------------------------------------------------------------------
-%%% Server
-%%%-------------------------------------------------------------------
-
-server_init(Config, Req) when is_record(Config, config),
- is_pid(Config#config.parent_pid),
- is_record(Req, tftp_msg_req) ->
- process_flag(trap_exit, true),
- %% Config =
- %% case os:getenv("TFTPDEBUG") of
- %% false ->
- %% Config0;
- %% DebugLevel ->
- %% Config0#config{debug_level = list_to_atom(DebugLevel)}
- %% end,
- SuggestedOptions = Req#tftp_msg_req.options,
- UdpOptions = Config#config.udp_options,
- UdpOptions2 = lists:keydelete(fd, 1, UdpOptions),
- Config1 = Config#config{udp_options = UdpOptions2},
- Config2 = tftp_lib:parse_config(SuggestedOptions, Config1),
- SuggestedOptions2 = Config2#config.user_options,
- Req2 = Req#tftp_msg_req{options = SuggestedOptions2},
- case open_free_port(Config2, server, Req2) of
- {ok, Config3} ->
- Filename = Req#tftp_msg_req.filename,
- case match_callback(Filename, Config3#config.callbacks) of
- {ok, Callback} ->
- print_debug_info(Config3, server, match, Callback),
- case pre_verify_options(Config3, Req2) of
- ok ->
- case callback({open, server_open}, Config3, Callback, Req2) of
- {Callback2, {ok, AcceptedOptions}} ->
- {LocalAccess, _} = local_file_access(Req2),
- OptText = "Internal error. Not allowed to add new options.",
- case post_verify_options(Config3, Req2, AcceptedOptions, OptText) of
- {ok, Config4, Req3} when AcceptedOptions =/= [] ->
- Reply = #tftp_msg_oack{options = AcceptedOptions},
- BlockNo =
- case LocalAccess of
- read -> 0;
- write -> 1
- end,
- {Config5, Callback3, TransferRes} =
- transfer(Config4, Callback2, Req3, Reply, LocalAccess, BlockNo, #prepared{}),
- common_loop(Config5, Callback3, Req3, TransferRes, LocalAccess, BlockNo);
- {ok, Config4, Req3} when LocalAccess =:= write ->
- BlockNo = 0,
- common_ack(Config4, Callback2, Req3, LocalAccess, BlockNo, #prepared{});
- {ok, Config4, Req3} when LocalAccess =:= read ->
- BlockNo = 0,
- common_read(Config4, Callback2, Req3, LocalAccess, BlockNo, BlockNo, #prepared{});
- {error, {Code, Text}} ->
- {undefined, Error} =
- callback({abort, {Code, Text}}, Config3, Callback2, Req2),
- send_msg(Config3, Req, Error),
- terminate(Config3, Req2, ?ERROR(post_verify_options, Code, Text, Req2#tftp_msg_req.filename))
- end;
- {undefined, #tftp_msg_error{code = Code, text = Text} = Error} ->
- send_msg(Config3, Req, Error),
- terminate(Config3, Req, ?ERROR(server_open, Code, Text, Req2#tftp_msg_req.filename))
- end;
- {error, {Code, Text}} ->
- {undefined, Error} =
- callback({abort, {Code, Text}}, Config2, Callback, Req2),
- send_msg(Config2, Req, Error),
- terminate(Config2, Req2, ?ERROR(pre_verify_options, Code, Text, Req2#tftp_msg_req.filename))
- end;
- {error, #tftp_msg_error{code = Code, text = Text} = Error} ->
- send_msg(Config3, Req, Error),
- terminate(Config3, Req, ?ERROR(match_callback, Code, Text, Req2#tftp_msg_req.filename))
- end;
- #error{} = Error ->
- terminate(Config2, Req, Error)
- end;
-server_init(Config, Req) when is_record(Req, tftp_msg_req) ->
- Config2 = upgrade_config(Config),
- server_init(Config2, Req).
-
-%%%-------------------------------------------------------------------
-%%% Client
-%%%-------------------------------------------------------------------
-
-%% LocalFilename = filename() | 'binary' | binary()
-%% Returns {ok, LastCallbackState} | {error, Reason}
-client_start(Access, RemoteFilename, LocalFilename, Options) ->
- Config = tftp_lib:parse_config(Options),
- Config2 = Config#config{parent_pid = self(),
- udp_socket = undefined},
- Req = #tftp_msg_req{access = Access,
- filename = RemoteFilename,
- mode = lookup_mode(Config2#config.user_options),
- options = Config2#config.user_options,
- local_filename = LocalFilename},
- Args = [Config2, Req],
- case proc_lib:start_link(?MODULE, client_init, Args, infinity) of
- {ok, LastCallbackState} ->
- {ok, LastCallbackState};
- {error, Error} ->
- {error, Error}
- end.
-
-client_init(Config, Req) when is_record(Config, config),
- is_pid(Config#config.parent_pid),
- is_record(Req, tftp_msg_req) ->
- process_flag(trap_exit, true),
- %% Config =
- %% case os:getenv("TFTPDEBUG") of
- %% false ->
- %% Config0;
- %% "none" ->
- %% Config0;
- %% DebugLevel ->
- %% info_msg(Config, "TFTPDEBUG: ~s\n", [DebugLevel]),
- %% Config0#config{debug_level = list_to_atom(DebugLevel)}
- %% end,
- case open_free_port(Config, client, Req) of
- {ok, Config2} ->
- Req2 =
- case Config2#config.use_tsize of
- true ->
- SuggestedOptions = Req#tftp_msg_req.options,
- SuggestedOptions2 = tftp_lib:replace_val("tsize", "0", SuggestedOptions),
- Req#tftp_msg_req{options = SuggestedOptions2};
- false ->
- Req
- end,
- LocalFilename = Req2#tftp_msg_req.local_filename,
- case match_callback(LocalFilename, Config2#config.callbacks) of
- {ok, Callback} ->
- print_debug_info(Config2, client, match, Callback),
- client_prepare(Config2, Callback, Req2);
- {error, #tftp_msg_error{code = Code, text = Text}} ->
- terminate(Config, Req, ?ERROR(match, Code, Text, Req#tftp_msg_req.filename))
- end;
- #error{} = Error ->
- terminate(Config, Req, Error)
- end.
-
-client_prepare(Config, Callback, Req) when is_record(Req, tftp_msg_req) ->
- case pre_verify_options(Config, Req) of
- ok ->
- case callback({open, client_prepare}, Config, Callback, Req) of
- {Callback2, {ok, AcceptedOptions}} ->
- OptText = "Internal error. Not allowed to add new options.",
- case post_verify_options(Config, Req, AcceptedOptions, OptText) of
- {ok, Config2, Req2} ->
- {LocalAccess, _} = local_file_access(Req2),
- BlockNo = 0,
- {Config3, Callback3, TransferRes} =
- transfer(Config2, Callback2, Req2, Req2, LocalAccess, BlockNo, #prepared{}),
- client_open(Config3, Callback3, Req2, BlockNo, TransferRes);
- {error, {Code, Text}} ->
- callback({abort, {Code, Text}}, Config, Callback2, Req),
- terminate(Config, Req, ?ERROR(post_verify_options, Code, Text, Req#tftp_msg_req.filename))
- end;
- {undefined, #tftp_msg_error{code = Code, text = Text}} ->
- terminate(Config, Req, ?ERROR(client_prepare, Code, Text, Req#tftp_msg_req.filename))
- end;
- {error, {Code, Text}} ->
- callback({abort, {Code, Text}}, Config, Callback, Req),
- terminate(Config, Req, ?ERROR(pre_verify_options, Code, Text, Req#tftp_msg_req.filename))
- end.
-
-client_open(Config, Callback, Req, BlockNo, #transfer_res{status = Status, decoded_msg = DecodedMsg, prepared = Prepared}) ->
- {LocalAccess, _} = local_file_access(Req),
- case Status of
- ok when is_record(Prepared, prepared) ->
- case DecodedMsg of
- Msg when is_record(Msg, tftp_msg_oack) ->
- ServerOptions = Msg#tftp_msg_oack.options,
- OptText = "Protocol violation. Server is not allowed new options",
- case post_verify_options(Config, Req, ServerOptions, OptText) of
- {ok, Config2, Req2} ->
- {Config3, Callback2, Req3} =
- do_client_open(Config2, Callback, Req2),
- case LocalAccess of
- read ->
- common_read(Config3, Callback2, Req3, LocalAccess, BlockNo, BlockNo, Prepared);
- write ->
- common_ack(Config3, Callback2, Req3, LocalAccess, BlockNo, Prepared)
- end;
- {error, {Code, Text}} ->
- {undefined, Error} =
- callback({abort, {Code, Text}}, Config, Callback, Req),
- send_msg(Config, Req, Error),
- terminate(Config, Req, ?ERROR(verify_server_options, Code, Text, Req#tftp_msg_req.filename))
- end;
- #tftp_msg_ack{block_no = ActualBlockNo} when LocalAccess =:= read ->
- Req2 = Req#tftp_msg_req{options = []},
- {Config2, Callback2, Req2} = do_client_open(Config, Callback, Req2),
- ExpectedBlockNo = 0,
- common_read(Config2, Callback2, Req2, LocalAccess, ExpectedBlockNo, ActualBlockNo, Prepared);
- #tftp_msg_data{block_no = ActualBlockNo, data = Data} when LocalAccess =:= write ->
- Req2 = Req#tftp_msg_req{options = []},
- {Config2, Callback2, Req2} = do_client_open(Config, Callback, Req2),
- ExpectedBlockNo = 1,
- common_write(Config2, Callback2, Req2, LocalAccess, ExpectedBlockNo, ActualBlockNo, Data, Prepared);
- %% #tftp_msg_error{code = Code, text = Text} when Req#tftp_msg_req.options =/= [] ->
- %% %% Retry without options
- %% callback({abort, {Code, Text}}, Config, Callback, Req),
- %% Req2 = Req#tftp_msg_req{options = []},
- %% client_prepare(Config, Callback, Req2);
- #tftp_msg_error{code = Code, text = Text} ->
- callback({abort, {Code, Text}}, Config, Callback, Req),
- terminate(Config, Req, ?ERROR(client_open, Code, Text, Req#tftp_msg_req.filename));
- {'EXIT', #tftp_msg_error{code = Code, text = Text}} ->
- callback({abort, {Code, Text}}, Config, Callback, Req),
- terminate(Config, Req, ?ERROR(client_open, Code, Text, Req#tftp_msg_req.filename));
- Msg when is_tuple(Msg) ->
- Code = badop,
- Text = "Illegal TFTP operation",
- {undefined, Error} =
- callback({abort, {Code, Text}}, Config, Callback, Req),
- send_msg(Config, Req, Error),
- Text2 = lists:flatten([Text, ". ", io_lib:format("~p", [element(1, Msg)])]),
- terminate(Config, Req, ?ERROR(client_open, Code, Text2, Req#tftp_msg_req.filename))
- end;
- error when is_record(Prepared, tftp_msg_error) ->
- #tftp_msg_error{code = Code, text = Text} = Prepared,
- callback({abort, {Code, Text}}, Config, Callback, Req),
- terminate(Config, Req, ?ERROR(client_open, Code, Text, Req#tftp_msg_req.filename))
- end.
-
-do_client_open(Config, Callback, Req) ->
- case callback({open, client_open}, Config, Callback, Req) of
- {Callback2, {ok, FinalOptions}} ->
- OptText = "Internal error. Not allowed to change options.",
- case post_verify_options(Config, Req, FinalOptions, OptText) of
- {ok, Config2, Req2} ->
- {Config2, Callback2, Req2};
- {error, {Code, Text}} ->
- {undefined, Error} =
- callback({abort, {Code, Text}}, Config, Callback2, Req),
- send_msg(Config, Req, Error),
- terminate(Config, Req, ?ERROR(post_verify_options, Code, Text, Req#tftp_msg_req.filename))
- end;
- {undefined, #tftp_msg_error{code = Code, text = Text} = Error} ->
- send_msg(Config, Req, Error),
- terminate(Config, Req, ?ERROR(client_open, Code, Text, Req#tftp_msg_req.filename))
- end.
-
-%%%-------------------------------------------------------------------
-%%% Common loop for both client and server
-%%%-------------------------------------------------------------------
-
-common_loop(Config, Callback, Req, #transfer_res{status = Status, decoded_msg = DecodedMsg, prepared = Prepared}, LocalAccess, ExpectedBlockNo)
- when is_record(Config, config)->
- %% Config =
- %% case os:getenv("TFTPMAX") of
- %% false ->
- %% Config0;
- %% MaxBlockNoStr when Config0#config.debug_level =/= none ->
- %% case list_to_integer(MaxBlockNoStr) of
- %% MaxBlockNo when ExpectedBlockNo > MaxBlockNo ->
- %% info_msg(Config, "TFTPMAX: ~p\n", [MaxBlockNo]),
- %% info_msg(Config, "TFTPDEBUG: none\n", []),
- %% Config0#config{debug_level = none};
- %% _ ->
- %% Config0
- %% end;
- %% _MaxBlockNoStr ->
- %% Config0
- %% end,
- case Status of
- ok when is_record(Prepared, prepared) ->
- case DecodedMsg of
- #tftp_msg_ack{block_no = ActualBlockNo} when LocalAccess =:= read ->
- common_read(Config, Callback, Req, LocalAccess, ExpectedBlockNo, ActualBlockNo, Prepared);
- #tftp_msg_data{block_no = ActualBlockNo, data = Data} when LocalAccess =:= write ->
- common_write(Config, Callback, Req, LocalAccess, ExpectedBlockNo, ActualBlockNo, Data, Prepared);
- #tftp_msg_error{code = Code, text = Text} ->
- callback({abort, {Code, Text}}, Config, Callback, Req),
- terminate(Config, Req, ?ERROR(common_loop, Code, Text, Req#tftp_msg_req.filename));
- {'EXIT', #tftp_msg_error{code = Code, text = Text} = Error} ->
- callback({abort, {Code, Text}}, Config, Callback, Req),
- send_msg(Config, Req, Error),
- terminate(Config, Req, ?ERROR(common_loop, Code, Text, Req#tftp_msg_req.filename));
- Msg when is_tuple(Msg) ->
- Code = badop,
- Text = "Illegal TFTP operation",
- {undefined, Error} =
- callback({abort, {Code, Text}}, Config, Callback, Req),
- send_msg(Config, Req, Error),
- Text2 = lists:flatten([Text, ". ", io_lib:format("~p", [element(1, Msg)])]),
- terminate(Config, Req, ?ERROR(common_loop, Code, Text2, Req#tftp_msg_req.filename))
- end;
- error when is_record(Prepared, tftp_msg_error) ->
- #tftp_msg_error{code = Code, text = Text} = Prepared,
- send_msg(Config, Req, Prepared),
- terminate(Config, Req, ?ERROR(transfer, Code, Text, Req#tftp_msg_req.filename))
- end;
-common_loop(Config, Callback, Req, TransferRes, LocalAccess, ExpectedBlockNo) ->
- %% Handle upgrade from old releases. Please, remove this clause in next release.
- Config2 = upgrade_config(Config),
- common_loop(Config2, Callback, Req, TransferRes, LocalAccess, ExpectedBlockNo).
-
--spec common_read(#config{}, #callback{}, _, 'read', _, _, #prepared{}) -> no_return().
-
-common_read(Config, _, Req, _, _, _, #prepared{status = terminate, result = Result}) ->
- terminate(Config, Req, {ok, Result});
-common_read(Config, Callback, Req, LocalAccess, ExpectedBlockNo, ActualBlockNo, Prepared)
- when ActualBlockNo =:= ExpectedBlockNo, is_record(Prepared, prepared) ->
- case early_read(Config, Callback, Req, LocalAccess, ActualBlockNo, Prepared) of
- {Callback2, #prepared{status = more, next_data = Data} = Prepared2} when is_binary(Data) ->
- Prepared3 = Prepared2#prepared{prev_data = Data, next_data = undefined},
- do_common_read(Config, Callback2, Req, LocalAccess, ActualBlockNo, Data, Prepared3);
- {undefined, #prepared{status = last, next_data = Data} = Prepared2} when is_binary(Data) ->
- Prepared3 = Prepared2#prepared{status = terminate},
- do_common_read(Config, undefined, Req, LocalAccess, ActualBlockNo, Data, Prepared3);
- {undefined, #prepared{status = error, result = Error}} ->
- #tftp_msg_error{code = Code, text = Text} = Error,
- send_msg(Config, Req, Error),
- terminate(Config, Req, ?ERROR(read, Code, Text, Req#tftp_msg_req.filename))
- end;
-common_read(Config, Callback, Req, LocalAccess, ExpectedBlockNo, ActualBlockNo, Prepared)
- when ActualBlockNo =:= (ExpectedBlockNo - 1), is_record(Prepared, prepared) ->
- case Prepared of
- #prepared{status = more, prev_data = Data} when is_binary(Data) ->
- do_common_read(Config, Callback, Req, LocalAccess, ActualBlockNo, Data, Prepared);
- #prepared{status = last, prev_data = Data} when is_binary(Data) ->
- do_common_read(Config, Callback, Req, LocalAccess, ActualBlockNo, Data, Prepared);
- #prepared{status = error, result = Error} ->
- #tftp_msg_error{code = Code, text = Text} = Error,
- send_msg(Config, Req, Error),
- terminate(Config, Req, ?ERROR(read, Code, Text, Req#tftp_msg_req.filename))
- end;
-common_read(Config, Callback, Req, LocalAccess, ExpectedBlockNo, ActualBlockNo, Prepared)
- when ActualBlockNo =< ExpectedBlockNo, is_record(Prepared, prepared) ->
- %% error_logger:error_msg("TFTP READ ~s: Expected block ~p but got block ~p - IGNORED\n",
- %% [Req#tftp_msg_req.filename, ExpectedBlockNo, ActualBlockNo]),
- case Prepared of
- #prepared{status = more, prev_data = Data} when is_binary(Data) ->
- Reply = #tftp_msg_data{block_no = ExpectedBlockNo, data = Data},
- {Config2, Callback2, TransferRes} =
- wait_for_msg_and_handle_timeout(Config, Callback, Req, Reply, LocalAccess, ExpectedBlockNo, Prepared),
- ?MODULE:common_loop(Config2, Callback2, Req, TransferRes, LocalAccess, ExpectedBlockNo);
- #prepared{status = last, prev_data = Data} when is_binary(Data) ->
- Reply = #tftp_msg_data{block_no = ExpectedBlockNo, data = Data},
- {Config2, Callback2, TransferRes} =
- wait_for_msg_and_handle_timeout(Config, Callback, Req, Reply, LocalAccess, ExpectedBlockNo, Prepared),
- ?MODULE:common_loop(Config2, Callback2, Req, TransferRes, LocalAccess, ExpectedBlockNo);
- #prepared{status = error, result = Error} ->
- #tftp_msg_error{code = Code, text = Text} = Error,
- send_msg(Config, Req, Error),
- terminate(Config, Req, ?ERROR(read, Code, Text, Req#tftp_msg_req.filename))
- end;
-common_read(Config, Callback, Req, _LocalAccess, ExpectedBlockNo, ActualBlockNo, Prepared)
- when is_record(Prepared, prepared) ->
- Code = badblk,
- Text = "Unknown transfer ID = " ++
- integer_to_list(ActualBlockNo) ++ " (" ++ integer_to_list(ExpectedBlockNo) ++ ")",
- {undefined, Error} =
- callback({abort, {Code, Text}}, Config, Callback, Req),
- send_msg(Config, Req, Error),
- terminate(Config, Req, ?ERROR(read, Code, Text, Req#tftp_msg_req.filename)).
-
--spec do_common_read(#config{}, #callback{} | undefined, _, 'read', integer(), binary(), #prepared{}) -> no_return().
-
-do_common_read(Config, Callback, Req, LocalAccess, BlockNo, Data, Prepared)
- when is_binary(Data), is_record(Prepared, prepared) ->
- NextBlockNo = (BlockNo + 1) rem 65536,
- Reply = #tftp_msg_data{block_no = NextBlockNo, data = Data},
- {Config2, Callback2, TransferRes} =
- transfer(Config, Callback, Req, Reply, LocalAccess, NextBlockNo, Prepared),
- ?MODULE:common_loop(Config2, Callback2, Req, TransferRes, LocalAccess, NextBlockNo).
-
--spec common_write(#config{}, #callback{}, _, 'write', integer(), integer(), _, #prepared{}) -> no_return().
-
-common_write(Config, _, Req, _, _, _, _, #prepared{status = terminate, result = Result}) ->
- terminate(Config, Req, {ok, Result});
-common_write(Config, Callback, Req, LocalAccess, ExpectedBlockNo, ActualBlockNo, Data, Prepared)
- when ActualBlockNo =:= ExpectedBlockNo, is_binary(Data), is_record(Prepared, prepared) ->
- case callback({write, Data}, Config, Callback, Req) of
- {Callback2, #prepared{status = more} = Prepared2} ->
- common_ack(Config, Callback2, Req, LocalAccess, ActualBlockNo, Prepared2);
- {undefined, #prepared{status = last, result = Result} = Prepared2} ->
- Config2 = pre_terminate(Config, Req, {ok, Result}),
- Prepared3 = Prepared2#prepared{status = terminate},
- common_ack(Config2, undefined, Req, LocalAccess, ActualBlockNo, Prepared3);
- {undefined, #prepared{status = error, result = Error}} ->
- #tftp_msg_error{code = Code, text = Text} = Error,
- send_msg(Config, Req, Error),
- terminate(Config, Req, ?ERROR(write, Code, Text, Req#tftp_msg_req.filename))
- end;
-common_write(Config, Callback, Req, LocalAccess, ExpectedBlockNo, ActualBlockNo, Data, Prepared)
- when ActualBlockNo =:= (ExpectedBlockNo - 1), is_binary(Data), is_record(Prepared, prepared) ->
- common_ack(Config, Callback, Req, LocalAccess, ExpectedBlockNo - 1, Prepared);
-common_write(Config, Callback, Req, LocalAccess, ExpectedBlockNo, ActualBlockNo, Data, Prepared)
- when ActualBlockNo =< ExpectedBlockNo, is_binary(Data), is_record(Prepared, prepared) ->
- %% error_logger:error_msg("TFTP WRITE ~s: Expected block ~p but got block ~p - IGNORED\n",
- %% [Req#tftp_msg_req.filename, ExpectedBlockNo, ActualBlockNo]),
- Reply = #tftp_msg_ack{block_no = ExpectedBlockNo},
- {Config2, Callback2, TransferRes} =
- wait_for_msg_and_handle_timeout(Config, Callback, Req, Reply, LocalAccess, ExpectedBlockNo, Prepared),
- ?MODULE:common_loop(Config2, Callback2, Req, TransferRes, LocalAccess, ExpectedBlockNo);
-common_write(Config, Callback, Req, _, ExpectedBlockNo, ActualBlockNo, Data, Prepared)
- when is_binary(Data), is_record(Prepared, prepared) ->
- Code = badblk,
- Text = "Unknown transfer ID = " ++
- integer_to_list(ActualBlockNo) ++ " (" ++ integer_to_list(ExpectedBlockNo) ++ ")",
- {undefined, Error} =
- callback({abort, {Code, Text}}, Config, Callback, Req),
- send_msg(Config, Req, Error),
- terminate(Config, Req, ?ERROR(write, Code, Text, Req#tftp_msg_req.filename)).
-
-common_ack(Config, Callback, Req, LocalAccess, BlockNo, Prepared)
- when is_record(Prepared, prepared) ->
- Reply = #tftp_msg_ack{block_no = BlockNo},
- NextBlockNo = (BlockNo + 1) rem 65536,
- {Config2, Callback2, TransferRes} =
- transfer(Config, Callback, Req, Reply, LocalAccess, NextBlockNo, Prepared),
- ?MODULE:common_loop(Config2, Callback2, Req, TransferRes, LocalAccess, NextBlockNo).
-
-pre_terminate(Config, Req, Result) ->
- if
- Req#tftp_msg_req.local_filename =/= undefined,
- Config#config.parent_pid =/= undefined ->
- proc_lib:init_ack(Result),
- unlink(Config#config.parent_pid),
- Config#config{parent_pid = undefined, polite_ack = true};
- true ->
- Config#config{polite_ack = true}
- end.
-
--spec terminate(#config{}, #tftp_msg_req{}, {'ok', _} | #error{}) -> no_return().
-
-terminate(Config, Req, Result) ->
- Result2 =
- case Result of
- {ok, _} ->
- Result;
- #error{where = Where, code = Code, text = Text} = Error ->
- print_debug_info(Config, Req, Where, Error#error{filename = Req#tftp_msg_req.filename}),
- {error, {Where, Code, Text}}
- end,
- if
- Config#config.parent_pid =:= undefined ->
- close_port(Config, client, Req),
- exit(normal);
- Req#tftp_msg_req.local_filename =/= undefined ->
- %% Client
- close_port(Config, client, Req),
- proc_lib:init_ack(Result2),
- unlink(Config#config.parent_pid),
- exit(normal);
- true ->
- %% Server
- close_port(Config, server, Req),
- exit(shutdown)
- end.
-
-close_port(Config, Who, Req) when is_record(Req, tftp_msg_req) ->
- case Config#config.udp_socket of
- undefined ->
- ignore;
- Socket ->
- print_debug_info(Config, Who, close, Req),
- gen_udp:close(Socket)
- end.
-
-open_free_port(Config, Who, Req) when is_record(Config, config), is_record(Req, tftp_msg_req) ->
- UdpOptions = Config#config.udp_options,
- case Config#config.port_policy of
- random ->
- %% BUGBUG: Should be a random port
- case catch gen_udp:open(0, UdpOptions) of
- {ok, Socket} ->
- Config2 = Config#config{udp_socket = Socket},
- print_debug_info(Config2, Who, open, Req),
- {ok, Config2};
- {error, Reason} ->
- Text = lists:flatten(io_lib:format("UDP open ~p -> ~p", [[0 | UdpOptions], Reason])),
- ?ERROR(open, undef, Text, Req#tftp_msg_req.filename);
- {'EXIT', _} = Reason ->
- Text = lists:flatten(io_lib:format("UDP open ~p -> ~p", [[0 | UdpOptions], Reason])),
- ?ERROR(open, undef, Text, Req#tftp_msg_req.filename)
- end;
- {range, Port, Max} when Port =< Max ->
- case catch gen_udp:open(Port, UdpOptions) of
- {ok, Socket} ->
- Config2 = Config#config{udp_socket = Socket},
- print_debug_info(Config2, Who, open, Req),
- {ok, Config2};
- {error, eaddrinuse} ->
- PortPolicy = {range, Port + 1, Max},
- Config2 = Config#config{port_policy = PortPolicy},
- open_free_port(Config2, Who, Req);
- {error, Reason} ->
- Text = lists:flatten(io_lib:format("UDP open ~p -> ~p", [[Port | UdpOptions], Reason])),
- ?ERROR(open, undef, Text, Req#tftp_msg_req.filename);
- {'EXIT', _} = Reason->
- Text = lists:flatten(io_lib:format("UDP open ~p -> ~p", [[Port | UdpOptions], Reason])),
- ?ERROR(open, undef, Text, Req#tftp_msg_req.filename)
- end;
- {range, Port, _Max} ->
- Reason = "Port range exhausted",
- Text = lists:flatten(io_lib:format("UDP open ~p -> ~p", [[Port | UdpOptions], Reason])),
- ?ERROR(Who, undef, Text, Req#tftp_msg_req.filename)
- end.
-
-%%-------------------------------------------------------------------
-%% Transfer
-%%-------------------------------------------------------------------
-
-%% Returns {Config, Callback, #transfer_res{}}
-transfer(Config, Callback, Req, Msg, LocalAccess, NextBlockNo, Prepared)
- when is_record(Prepared, prepared) ->
- IoList = tftp_lib:encode_msg(Msg),
- Retries = Config#config.max_retries + 1,
- do_transfer(Config, Callback, Req, Msg, IoList, LocalAccess, NextBlockNo, Prepared, Retries).
-
-do_transfer(Config, Callback, Req, Msg, IoList, LocalAccess, NextBlockNo, Prepared, Retries)
- when is_record(Prepared, prepared), is_integer(Retries), Retries >= 0 ->
- case do_send_msg(Config, Req, Msg, IoList) of
- ok ->
- {Callback2, Prepared2} =
- early_read(Config, Callback, Req, LocalAccess, NextBlockNo, Prepared),
- do_wait_for_msg_and_handle_timeout(Config, Callback2, Req, Msg, IoList, LocalAccess, NextBlockNo, Prepared2, Retries);
- {error, _Reason} when Retries > 0 ->
- Retries2 = 0, % Just retry once when send fails
- do_transfer(Config, Callback, Req, Msg, IoList, LocalAccess, NextBlockNo, Prepared, Retries2);
- {error, Reason} ->
- Code = undef,
- Text = lists:flatten(io_lib:format("Transfer failed - giving up -> ~p", [Reason])),
- Error = #tftp_msg_error{code = Code, text = Text},
- {Config, Callback, #transfer_res{status = error, prepared = Error}}
- end.
-
-wait_for_msg_and_handle_timeout(Config, Callback, Req, Msg, LocalAccess, NextBlockNo, Prepared) ->
- IoList = tftp_lib:encode_msg(Msg),
- Retries = Config#config.max_retries + 1,
- do_wait_for_msg_and_handle_timeout(Config, Callback, Req, Msg, IoList, LocalAccess, NextBlockNo, Prepared, Retries).
-
-do_wait_for_msg_and_handle_timeout(Config, Callback, Req, Msg, IoList, LocalAccess, NextBlockNo, Prepared, Retries) ->
- Code = undef,
- Text = "Transfer timed out.",
- case wait_for_msg(Config, Callback, Req) of
- timeout when Config#config.polite_ack =:= true ->
- do_send_msg(Config, Req, Msg, IoList),
- case Prepared of
- #prepared{status = terminate, result = Result} ->
- terminate(Config, Req, {ok, Result});
- #prepared{} ->
- terminate(Config, Req, ?ERROR(transfer, Code, Text, Req#tftp_msg_req.filename))
- end;
- timeout when Retries > 0 ->
- Retries2 = Retries - 1,
- do_transfer(Config, Callback, Req, Msg, IoList, LocalAccess, NextBlockNo, Prepared, Retries2);
- timeout ->
- Error = #tftp_msg_error{code = Code, text = Text},
- {Config, Callback, #transfer_res{status = error, prepared = Error}};
- {Config2, DecodedMsg} ->
- {Config2, Callback, #transfer_res{status = ok, decoded_msg = DecodedMsg, prepared = Prepared}}
- end.
-
-send_msg(Config, Req, Msg) ->
- case catch tftp_lib:encode_msg(Msg) of
- {'EXIT', Reason} ->
- Code = undef,
- Text = "Internal error. Encode failed",
- Msg2 = #tftp_msg_error{code = Code, text = Text, details = Reason},
- send_msg(Config, Req, Msg2);
- IoList ->
- do_send_msg(Config, Req, Msg, IoList)
- end.
-
-do_send_msg(#config{udp_socket = Socket, udp_host = RemoteHost, udp_port = RemotePort} = Config, Req, Msg, IoList) ->
- %% {ok, LocalPort} = inet:port(Socket),
- %% if
- %% LocalPort =/= ?TFTP_DEFAULT_PORT ->
- %% ok;
- %% true ->
- %% print_debug_info(Config#config{debug_level = all}, Req, send, Msg),
- %% error(Config,
- %% "Daemon replies from the default port (~p)\n\t to ~p:~p\n\t¨~p\n",
- %% [LocalPort, RemoteHost, RemotePort, Msg])
- %% end,
-
- print_debug_info(Config, Req, send, Msg),
-
- %% case os:getenv("TFTPDUMP") of
- %% false ->
- %% ignore;
- %% DumpPath ->
- %% trace_udp_send(Req, Msg, IoList, DumpPath)
- %% end,
- Res = gen_udp:send(Socket, RemoteHost, RemotePort, IoList),
- case Res of
- ok ->
- ok;
- {error, einval = Reason} ->
- error_msg(Config,
- "Stacktrace; ~p\n gen_udp:send(~p, ~p, ~p, ~p) -> ~p\n",
- [erlang:get_stacktrace(), Socket, RemoteHost, RemotePort, IoList, {error, Reason}]);
- {error, Reason} ->
- {error, Reason}
- end.
-
-%% trace_udp_send(#tftp_msg_req{filename = [$/ | RelFile]} = Req, Msg, IoList, DumpPath) ->
-%% trace_udp_send(Req#tftp_msg_req{filename = RelFile}, Msg, IoList, DumpPath);
-%% trace_udp_send(#tftp_msg_req{filename = RelFile},
-%% #tftp_msg_data{block_no = BlockNo, data = Data},
-%% _IoList,
-%% DumpPath) ->
-%% File = filename:join([DumpPath, RelFile, "block" ++ string:right(integer_to_list(BlockNo), 5, $0) ++ ".dump"]),
-%% if
-%% (BlockNo rem 1000) =:= 1 ->
-%% info_msg(Config, "TFTPDUMP: Data ~s\n", [File]);
-%% true ->
-%% ignore
-%% end,
-%% ok = filelib:ensure_dir(File),
-%% ok = file:write_file(File, Data);
-%% trace_udp_send(#tftp_msg_req{filename = RelFile}, Msg, _IoList, _DumpPath) ->
-%% info_msg(Config, "TFTPDUMP: No data ~s -> ~p\n", [RelFile, element(1, Msg)]).
-
-wait_for_msg(Config, Callback, Req) ->
- receive
- {udp, Socket, RemoteHost, RemotePort, Bin}
- when is_binary(Bin), Callback#callback.block_no =:= undefined ->
- %% Client prepare
- inet:setopts(Socket, [{active, once}]),
- Config2 = Config#config{udp_host = RemoteHost,
- udp_port = RemotePort},
- DecodedMsg = (catch tftp_lib:decode_msg(Bin)),
- print_debug_info(Config2, Req, recv, DecodedMsg),
- {Config2, DecodedMsg};
- {udp, Socket, Host, Port, Bin} when is_binary(Bin),
- Config#config.udp_host =:= Host,
- Config#config.udp_port =:= Port ->
- inet:setopts(Socket, [{active, once}]),
- DecodedMsg = (catch tftp_lib:decode_msg(Bin)),
- print_debug_info(Config, Req, recv, DecodedMsg),
- {Config, DecodedMsg};
- {info, Ref, FromPid} when is_pid(FromPid) ->
- Type =
- case Req#tftp_msg_req.local_filename =/= undefined of
- true -> client;
- false -> server
- end,
- Info = internal_info(Config, Type),
- reply({ok, Info}, Ref, FromPid),
- wait_for_msg(Config, Callback, Req);
- {{change_config, Options}, Ref, FromPid} when is_pid(FromPid) ->
- case catch tftp_lib:parse_config(Options, Config) of
- {'EXIT', Reason} ->
- reply({error, Reason}, Ref, FromPid),
- wait_for_msg(Config, Callback, Req);
- Config2 when is_record(Config2, config) ->
- reply(ok, Ref, FromPid),
- wait_for_msg(Config2, Callback, Req)
- end;
- {system, From, Msg} ->
- Misc = #sys_misc{module = ?MODULE, function = wait_for_msg, arguments = [Config, Callback, Req]},
- sys:handle_system_msg(Msg, From, Config#config.parent_pid, ?MODULE, [], Misc);
- {'EXIT', Pid, _Reason} when Config#config.parent_pid =:= Pid ->
- Code = undef,
- Text = "Parent exited.",
- terminate(Config, Req, ?ERROR(wait_for_msg, Code, Text, Req#tftp_msg_req.filename));
- Msg when Req#tftp_msg_req.local_filename =/= undefined ->
- warning_msg(Config, "Client received : ~p", [Msg]),
- wait_for_msg(Config, Callback, Req);
- Msg when Req#tftp_msg_req.local_filename =:= undefined ->
- warning_msg(Config, "Server received : ~p", [Msg]),
- wait_for_msg(Config, Callback, Req)
- after Config#config.timeout * 1000 ->
- print_debug_info(Config, Req, recv, timeout),
- timeout
- end.
-
-early_read(Config, Callback, Req, LocalAccess, _NextBlockNo,
- #prepared{status = Status, next_data = NextData, prev_data = PrevData} = Prepared) ->
- if
- Status =/= terminate,
- LocalAccess =:= read,
- Callback#callback.block_no =/= undefined,
- NextData =:= undefined ->
- case callback(read, Config, Callback, Req) of
- {undefined, Error} when is_record(Error, tftp_msg_error) ->
- {undefined, Error};
- {Callback2, Prepared2} when is_record(Prepared2, prepared)->
- {Callback2, Prepared2#prepared{prev_data = PrevData}}
- end;
- true ->
- {Callback, Prepared}
- end.
-
-%%-------------------------------------------------------------------
-%% Callback
-%%-------------------------------------------------------------------
-
-callback(Access, Config, Callback, Req) ->
- {Callback2, Result} =
- do_callback(Access, Config, Callback, Req),
- print_debug_info(Config, Req, call, {Callback2, Result}),
- {Callback2, Result}.
-
-do_callback(read = Fun, Config, Callback, Req)
- when is_record(Config, config),
- is_record(Callback, callback),
- is_record(Req, tftp_msg_req) ->
- Args = [Callback#callback.state],
- NextBlockNo = Callback#callback.block_no + 1,
- case catch safe_apply(Callback#callback.module, Fun, Args) of
- {more, Bin, NewState} when is_binary(Bin) ->
- Count = Callback#callback.count + size(Bin),
- Callback2 = Callback#callback{state = NewState,
- block_no = NextBlockNo,
- count = Count},
- Prepared = #prepared{status = more,
- result = undefined,
- block_no = NextBlockNo,
- next_data = Bin},
- verify_count(Config, Callback2, Req, Prepared);
- {last, Bin, Result} when is_binary(Bin) ->
- Prepared = #prepared{status = last,
- result = Result,
- block_no = NextBlockNo,
- next_data = Bin},
- {undefined, Prepared};
- {error, {Code, Text}} ->
- Error = #tftp_msg_error{code = Code, text = Text},
- Prepared = #prepared{status = error,
- result = Error},
- {undefined, Prepared};
- Illegal ->
- Code = undef,
- Text = "Internal error. File handler error.",
- callback({abort, {Code, Text, Illegal}}, Config, Callback, Req)
- end;
-do_callback({write = Fun, Bin}, Config, Callback, Req)
- when is_record(Config, config),
- is_record(Callback, callback),
- is_record(Req, tftp_msg_req),
- is_binary(Bin) ->
- Args = [Bin, Callback#callback.state],
- NextBlockNo = Callback#callback.block_no + 1,
- case catch safe_apply(Callback#callback.module, Fun, Args) of
- {more, NewState} ->
- Count = Callback#callback.count + size(Bin),
- Callback2 = Callback#callback{state = NewState,
- block_no = NextBlockNo,
- count = Count},
- Prepared = #prepared{status = more,
- block_no = NextBlockNo},
- verify_count(Config, Callback2, Req, Prepared);
- {last, Result} ->
- Prepared = #prepared{status = last,
- result = Result,
- block_no = NextBlockNo},
- {undefined, Prepared};
- {error, {Code, Text}} ->
- Error = #tftp_msg_error{code = Code, text = Text},
- Prepared = #prepared{status = error,
- result = Error},
- {undefined, Prepared};
- Illegal ->
- Code = undef,
- Text = "Internal error. File handler error.",
- callback({abort, {Code, Text, Illegal}}, Config, Callback, Req)
- end;
-do_callback({open, Type}, Config, Callback, Req)
- when is_record(Config, config),
- is_record(Callback, callback),
- is_record(Req, tftp_msg_req) ->
- {Access, Filename} = local_file_access(Req),
- {Fun, BlockNo} =
- case Type of
- client_prepare -> {prepare, undefined};
- client_open -> {open, 0};
- server_open -> {open, 0}
- end,
- Mod = Callback#callback.module,
- Args = [Access,
- Filename,
- Req#tftp_msg_req.mode,
- Req#tftp_msg_req.options,
- Callback#callback.state],
- PeerInfo = peer_info(Config),
- fast_ensure_loaded(Mod),
- Args2 =
- case erlang:function_exported(Mod, Fun, length(Args)) of
- true -> Args;
- false -> [PeerInfo | Args]
- end,
- case catch safe_apply(Mod, Fun, Args2) of
- {ok, AcceptedOptions, NewState} ->
- Callback2 = Callback#callback{state = NewState,
- block_no = BlockNo,
- count = 0},
- {Callback2, {ok, AcceptedOptions}};
- {error, {Code, Text}} ->
- {undefined, #tftp_msg_error{code = Code, text = Text}};
- Illegal ->
- Code = undef,
- Text = "Internal error. File handler error.",
- callback({abort, {Code, Text, Illegal}}, Config, Callback, Req)
- end;
-do_callback({abort, {Code, Text}}, Config, Callback, Req) ->
- Error = #tftp_msg_error{code = Code, text = Text},
- do_callback({abort, Error}, Config, Callback, Req);
-do_callback({abort, {Code, Text, Details}}, Config, Callback, Req) ->
- Error = #tftp_msg_error{code = Code, text = Text, details = Details},
- do_callback({abort, Error}, Config, Callback, Req);
-do_callback({abort = Fun, #tftp_msg_error{code = Code, text = Text} = Error}, Config, Callback, Req)
- when is_record(Config, config),
- is_record(Callback, callback),
- is_record(Req, tftp_msg_req) ->
- Args = [Code, Text, Callback#callback.state],
- catch safe_apply(Callback#callback.module, Fun, Args),
- {undefined, Error};
-do_callback({abort, Error}, _Config, undefined, _Req) when is_record(Error, tftp_msg_error) ->
- {undefined, Error}.
-
-peer_info(#config{udp_host = Host, udp_port = Port}) ->
- if
- is_tuple(Host), size(Host) =:= 4 ->
- {inet, tftp_lib:host_to_string(Host), Port};
- is_tuple(Host), size(Host) =:= 8 ->
- {inet6, tftp_lib:host_to_string(Host), Port};
- true ->
- {undefined, Host, Port}
- end.
-
-match_callback(Filename, Callbacks) ->
- if
- Filename =:= binary ->
- lookup_callback_mod(tftp_binary, Callbacks);
- is_binary(Filename) ->
- lookup_callback_mod(tftp_binary, Callbacks);
- true ->
- do_match_callback(Filename, Callbacks)
- end.
-
-do_match_callback(Filename, [C | Tail]) when is_record(C, callback) ->
- case catch re:run(Filename, C#callback.internal, [{capture, none}]) of
- match ->
- {ok, C};
- nomatch ->
- do_match_callback(Filename, Tail);
- Details ->
- Code = baduser,
- Text = "Internal error. File handler not found",
- {error, #tftp_msg_error{code = Code, text = Text, details = Details}}
- end;
-do_match_callback(Filename, []) ->
- Code = baduser,
- Text = "Internal error. File handler not found",
- {error, #tftp_msg_error{code = Code, text = Text, details = Filename}}.
-
-lookup_callback_mod(Mod, Callbacks) ->
- {value, C} = lists:keysearch(Mod, #callback.module, Callbacks),
- {ok, C}.
-
-verify_count(Config, Callback, Req, Result) ->
- case Config#config.max_tsize of
- infinity ->
- {Callback, Result};
- Max when Callback#callback.count =< Max ->
- {Callback, Result};
- _Max ->
- Code = enospc,
- Text = "Too large file.",
- callback({abort, {Code, Text}}, Config, Callback, Req)
- end.
-
-%%-------------------------------------------------------------------
-%% Miscellaneous
-%%-------------------------------------------------------------------
-
-internal_info(Config, Type) when is_record(Config, config) ->
- {ok, ActualPort} = inet:port(Config#config.udp_socket),
- [
- {type, Type},
- {host, tftp_lib:host_to_string(Config#config.udp_host)},
- {port, Config#config.udp_port},
- {local_port, ActualPort},
- {port_policy, Config#config.port_policy},
- {udp, Config#config.udp_options},
- {use_tsize, Config#config.use_tsize},
- {max_tsize, Config#config.max_tsize},
- {max_conn, Config#config.max_conn},
- {rejected, Config#config.rejected},
- {timeout, Config#config.timeout},
- {polite_ack, Config#config.polite_ack},
- {debug, Config#config.debug_level},
- {parent_pid, Config#config.parent_pid}
- ] ++ Config#config.user_options ++ Config#config.callbacks.
-
-local_file_access(#tftp_msg_req{access = Access,
- local_filename = Local,
- filename = Filename}) ->
- case Local =:= undefined of
- true ->
- %% Server side
- {Access, Filename};
- false ->
- %% Client side
- case Access of
- read -> {write, Local};
- write -> {read, Local}
- end
- end.
-
-pre_verify_options(Config, Req) ->
- Options = Req#tftp_msg_req.options,
- case catch verify_reject(Config, Req, Options) of
- ok ->
- case verify_integer("tsize", 0, Config#config.max_tsize, Options) of
- true ->
- case verify_integer("blksize", 0, 65464, Options) of
- true ->
- ok;
- false ->
- {error, {badopt, "Too large blksize"}}
- end;
- false ->
- {error, {badopt, "Too large tsize"}}
- end;
- {error, Reason} ->
- {error, Reason}
- end.
-
-post_verify_options(Config, Req, NewOptions, Text) ->
- OldOptions = Req#tftp_msg_req.options,
- BadOptions =
- [Key || {Key, _Val} <- NewOptions,
- not lists:keymember(Key, 1, OldOptions)],
- case BadOptions =:= [] of
- true ->
- Config2 = Config#config{timeout = lookup_timeout(NewOptions)},
- Req2 = Req#tftp_msg_req{options = NewOptions},
- {ok, Config2, Req2};
- false ->
- {error, {badopt, Text}}
- end.
-
-verify_reject(Config, Req, Options) ->
- Access = Req#tftp_msg_req.access,
- Rejected = Config#config.rejected,
- case lists:member(Access, Rejected) of
- true ->
- {error, {eacces, atom_to_list(Access) ++ " mode not allowed"}};
- false ->
- [throw({error, {badopt, Key ++ " not allowed"}}) ||
- {Key, _} <- Options, lists:member(Key, Rejected)],
- ok
- end.
-
-lookup_timeout(Options) ->
- case lists:keysearch("timeout", 1, Options) of
- {value, {_, Val}} ->
- list_to_integer(Val);
- false ->
- 3
- end.
-
-lookup_mode(Options) ->
- case lists:keysearch("mode", 1, Options) of
- {value, {_, Val}} ->
- Val;
- false ->
- "octet"
- end.
-
-verify_integer(Key, Min, Max, Options) ->
- case lists:keysearch(Key, 1, Options) of
- {value, {_, Val}} when is_list(Val) ->
- case catch list_to_integer(Val) of
- {'EXIT', _} ->
- false;
- Int when Int >= Min, is_integer(Min),
- Max =:= infinity ->
- true;
- Int when Int >= Min, is_integer(Min),
- Int =< Max, is_integer(Max) ->
- true;
- _ ->
- false
- end;
- false ->
- true
- end.
-
-error_msg(#config{logger = Logger, debug_level = _Level}, F, A) ->
- safe_apply(Logger, error_msg, [F, A]).
-
-warning_msg(#config{logger = Logger, debug_level = Level}, F, A) ->
- case Level of
- none -> ok;
- error -> ok;
- _ -> safe_apply(Logger, warning_msg, [F, A])
- end.
-
-info_msg(#config{logger = Logger}, F, A) ->
- safe_apply(Logger, info_msg, [F, A]).
-
-safe_apply(Mod, Fun, Args) ->
- fast_ensure_loaded(Mod),
- apply(Mod, Fun, Args).
-
-fast_ensure_loaded(Mod) ->
- case erlang:function_exported(Mod, module_info, 0) of
- true ->
- ok;
- false ->
- Res = code:load_file(Mod),
- %% io:format("tftp: code:load_file(~p) -> ~p\n", [Mod, Res]), %% XXX
- Res
- end.
-
-print_debug_info(#config{debug_level = Level} = Config, Who, Where, Data) ->
- if
- Level =:= none ->
- ok;
- is_record(Data, error) ->
- do_print_debug_info(Config, Who, Where, Data);
- Level =:= warning ->
- ok;
- Level =:= error ->
- ok;
- Level =:= all ->
- do_print_debug_info(Config, Who, Where, Data);
- Where =:= open ->
- do_print_debug_info(Config, Who, Where, Data);
- Where =:= close ->
- do_print_debug_info(Config, Who, Where, Data);
- Level =:= brief ->
- ok;
- Where =/= recv, Where =/= send ->
- ok;
- is_record(Data, tftp_msg_data), Level =:= normal ->
- ok;
- is_record(Data, tftp_msg_ack), Level =:= normal ->
- ok;
- true ->
- do_print_debug_info(Config, Who, Where, Data)
- end.
-
-do_print_debug_info(Config, Who, Where, #tftp_msg_data{data = Bin} = Msg) when is_binary(Bin) ->
- Msg2 = Msg#tftp_msg_data{data = {bytes, size(Bin)}},
- do_print_debug_info(Config, Who, Where, Msg2);
-do_print_debug_info(Config, Who, Where, #tftp_msg_req{local_filename = Filename} = Msg) when is_binary(Filename) ->
- Msg2 = Msg#tftp_msg_req{local_filename = binary},
- do_print_debug_info(Config, Who, Where, Msg2);
-do_print_debug_info(Config, Who, Where, Data) ->
- Local =
- case catch inet:port(Config#config.udp_socket) of
- {'EXIT', _Reason} ->
- 0;
- {ok, Port} ->
- Port
- end,
- %% Remote = Config#config.udp_port,
- PeerInfo = lists:flatten(io_lib:format("~p", [peer_info(Config)])),
- Side =
- if
- is_record(Who, tftp_msg_req),
- Who#tftp_msg_req.local_filename =/= undefined ->
- client;
- is_record(Who, tftp_msg_req),
- Who#tftp_msg_req.local_filename =:= undefined ->
- server;
- is_atom(Who) ->
- Who
- end,
- case {Where, Data} of
- {_, #error{where = Where, code = Code, text = Text, filename = Filename}} ->
- do_format(Config, Side, Local, "error ~s ->\n\t~p ~p\n\t~p ~p: ~s\n",
- [PeerInfo, self(), Filename, Where, Code, Text]);
- {open, #tftp_msg_req{filename = Filename}} ->
- do_format(Config, Side, Local, "open ~s ->\n\t~p ~p\n",
- [PeerInfo, self(), Filename]);
- {close, #tftp_msg_req{filename = Filename}} ->
- do_format(Config, Side, Local, "close ~s ->\n\t~p ~p\n",
- [PeerInfo, self(), Filename]);
- {recv, _} ->
- do_format(Config, Side, Local, "recv ~s <-\n\t~p\n",
- [PeerInfo, Data]);
- {send, _} ->
- do_format(Config, Side, Local, "send ~s ->\n\t~p\n",
- [PeerInfo, Data]);
- {match, _} when is_record(Data, callback) ->
- Mod = Data#callback.module,
- State = Data#callback.state,
- do_format(Config, Side, Local, "match ~s ~p =>\n\t~p\n",
- [PeerInfo, Mod, State]);
- {call, _} ->
- case Data of
- {Callback, _Result} when is_record(Callback, callback) ->
- Mod = Callback#callback.module,
- State = Callback#callback.state,
- do_format(Config, Side, Local, "call ~s ~p =>\n\t~p\n",
- [PeerInfo, Mod, State]);
- {undefined, Result} ->
- do_format(Config, Side, Local, "call ~s result =>\n\t~p\n",
- [PeerInfo, Result])
- end
- end.
-
-do_format(Config, Side, Local, Format, Args) ->
- info_msg(Config, "~p(~p): " ++ Format, [Side, Local | Args]).
-
-%%-------------------------------------------------------------------
-%% System upgrade
-%%-------------------------------------------------------------------
-
-system_continue(_Parent, _Debug, #sys_misc{module = Mod, function = Fun, arguments = Args}) ->
- apply(Mod, Fun, Args);
-system_continue(Parent, Debug, {Fun, Args}) ->
- %% Handle upgrade from old releases. Please, remove this clause in next release.
- system_continue(Parent, Debug, #sys_misc{module = ?MODULE, function = Fun, arguments = Args}).
-
--spec system_terminate(_, _, _, #sys_misc{} | {_, _}) -> no_return().
-
-system_terminate(Reason, _Parent, _Debug, #sys_misc{}) ->
- exit(Reason);
-system_terminate(Reason, Parent, Debug, {Fun, Args}) ->
- %% Handle upgrade from old releases. Please, remove this clause in next release.
- system_terminate(Reason, Parent, Debug, #sys_misc{module = ?MODULE, function = Fun, arguments = Args}).
-
-system_code_change({Fun, Args}, _Module, _OldVsn, _Extra) ->
- {ok, {Fun, Args}}.
diff --git a/lib/inets/src/tftp/tftp_file.erl b/lib/inets/src/tftp/tftp_file.erl
deleted file mode 100644
index 7664324808..0000000000
--- a/lib/inets/src/tftp/tftp_file.erl
+++ /dev/null
@@ -1,390 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-%%%-------------------------------------------------------------------
-%%% File : tft_file.erl
-%%% Author : Hakan Mattsson <[email protected]>
-%%% Description :
-%%%
-%%% Created : 24 May 2004 by Hakan Mattsson <[email protected]>
-%%%-------------------------------------------------------------------
-
--module(tftp_file).
-
-%%%-------------------------------------------------------------------
-%%% Interface
-%%%-------------------------------------------------------------------
-
--behaviour(tftp).
-
--export([prepare/6, open/6, read/1, write/2, abort/3]).
-
-%%%-------------------------------------------------------------------
-%%% Defines
-%%%-------------------------------------------------------------------
-
--include_lib("kernel/include/file.hrl").
-
--record(initial,
- {filename,
- is_native_ascii}).
-
--record(state,
- {access,
- filename,
- is_native_ascii,
- is_network_ascii,
- root_dir,
- options,
- blksize,
- fd,
- count,
- buffer}).
-
-%%-------------------------------------------------------------------
-%% prepare(Peer, Access, Filename, Mode, SuggestedOptions, InitialState) ->
-%% {ok, AcceptedOptions, NewState} | {error, Code, Text}
-%%
-%% Peer = {PeerType, PeerHost, PeerPort}
-%% PeerType = inet | inet6
-%% PeerHost = ip_address()
-%% PeerPort = integer()
-%% Acess = read | write
-%% Filename = string()
-%% Mode = string()
-%% SuggestedOptions = [{Key, Value}]
-%% AcceptedOptions = [{Key, Value}]
-%% Key = string()
-%% Value = string()
-%% InitialState = [] | [{root_dir, string()}]
-%% NewState = term()
-%% Code = undef | enoent | eacces | enospc |
-%% badop | eexist | baduser | badopt |
-%% integer()
-%% Text = string()
-%%
-%% Prepares open of a file on the client side.
-%%
-%% Will be followed by a call to open/4 before any read/write access
-%% is performed. The AcceptedOptions will be sent to the server which
-%% will reply with those options that it accepts. The options that are
-%% accepted by the server will be forwarded to open/4 as SuggestedOptions.
-%%
-%% No new options may be added, but the ones that are present as
-%% SuggestedOptions may be omitted or replaced with new values
-%% in the AcceptedOptions.
-%%-------------------------------------------------------------------
-
-prepare(_Peer, Access, Filename, Mode, SuggestedOptions, Initial) when is_list(Initial) ->
- %% Client side
- case catch handle_options(Access, Filename, Mode, SuggestedOptions, Initial) of
- {ok, Filename2, IsNativeAscii, IsNetworkAscii, AcceptedOptions} ->
- State = #state{access = Access,
- filename = Filename2,
- is_native_ascii = IsNativeAscii,
- is_network_ascii = IsNetworkAscii,
- options = AcceptedOptions,
- blksize = lookup_blksize(AcceptedOptions),
- count = 0,
- buffer = []},
- {ok, AcceptedOptions, State};
- {error, {Code, Text}} ->
- {error, {Code, Text}}
- end.
-
-%% ---------------------------------------------------------
-%% open(Peer, Access, Filename, Mode, SuggestedOptions, State) ->
-%% {ok, AcceptedOptions, NewState} | {error, Code, Text}
-%%
-%% Peer = {PeerType, PeerHost, PeerPort}
-%% PeerType = inet | inet6
-%% PeerHost = ip_address()
-%% PeerPort = integer()
-%% Acess = read | write
-%% Filename = string()
-%% Mode = string()
-%% SuggestedOptions = [{Key, Value}]
-%% AcceptedOptions = [{Key, Value}]
-%% Key = string()
-%% Value = string()
-%% State = InitialState | #state{}
-%% InitialState = [] | [{root_dir, string()}]
-%% NewState = term()
-%% Code = undef | enoent | eacces | enospc |
-%% badop | eexist | baduser | badopt |
-%% integer()
-%% Text = string()
-%%
-%% Opens a file for read or write access.
-%%
-%% On the client side where the open/4 call has been preceeded by a
-%% call to prepare/4, all options must be accepted or rejected.
-%% On the server side, where there are no preceeding prepare/4 call,
-%% noo new options may be added, but the ones that are present as
-%% SuggestedOptions may be omitted or replaced with new values
-%% in the AcceptedOptions.
-%%-------------------------------------------------------------------
-
-open(Peer, Access, Filename, Mode, SuggestedOptions, Initial) when is_list(Initial) ->
- %% Server side
- case prepare(Peer, Access, Filename, Mode, SuggestedOptions, Initial) of
- {ok, AcceptedOptions, State} ->
- open(Peer, Access, Filename, Mode, AcceptedOptions, State);
- {error, {Code, Text}} ->
- {error, {Code, Text}}
- end;
-open(_Peer, Access, Filename, Mode, NegotiatedOptions, State) when is_record(State, state) ->
- %% Both sides
- case catch handle_options(Access, Filename, Mode, NegotiatedOptions, State) of
- {ok, _Filename2, _IsNativeAscii, _IsNetworkAscii, Options}
- when Options =:= NegotiatedOptions ->
- do_open(State);
- {error, {Code, Text}} ->
- {error, {Code, Text}}
- end;
-open(Peer, Access, Filename, Mode, NegotiatedOptions, State) ->
- %% Handle upgrade from old releases. Please, remove this clause in next release.
- State2 = upgrade_state(State),
- open(Peer, Access, Filename, Mode, NegotiatedOptions, State2).
-
-do_open(State) when is_record(State, state) ->
- case file:open(State#state.filename, file_options(State)) of
- {ok, Fd} ->
- {ok, State#state.options, State#state{fd = Fd}};
- {error, Reason} when is_atom(Reason) ->
- {error, file_error(Reason)}
- end.
-
-file_options(State) ->
- case State#state.access of
- read -> [read, read_ahead, raw, binary];
- write -> [write, delayed_write, raw, binary]
- end.
-
-file_error(Reason) when is_atom(Reason) ->
- Details = file:format_error(Reason),
- case Reason of
- eexist -> {Reason, Details};
- enoent -> {Reason, Details};
- eacces -> {Reason, Details};
- eperm -> {eacces, Details};
- enospc -> {Reason, Details};
- _ -> {undef, Details ++ " (" ++ atom_to_list(Reason) ++ ")"}
- end.
-
-%%-------------------------------------------------------------------
-%% read(State) ->
-%% {more, Bin, NewState} | {last, Bin, FileSize} | {error, {Code, Text}}
-%%
-%% State = term()
-%% NewState = term()
-%% Bin = binary()
-%% FileSize = integer()
-%% Code = undef | enoent | eacces | enospc |
-%% badop | eexist | baduser | badopt |
-%% integer()
-%% Text = string()
-%%
-%% Reads a chunk from the file
-%%
-%% The file is automatically closed when the last chunk is read.
-%%-------------------------------------------------------------------
-
-read(#state{access = read} = State) ->
- BlkSize = State#state.blksize,
- case file:read(State#state.fd, BlkSize) of
- {ok, Bin} when is_binary(Bin), size(Bin) =:= BlkSize ->
- Count = State#state.count + size(Bin),
- {more, Bin, State#state{count = Count}};
- {ok, Bin} when is_binary(Bin), size(Bin) < BlkSize ->
- file:close(State#state.fd),
- Count = State#state.count + size(Bin),
- {last, Bin, Count};
- eof ->
- {last, <<>>, State#state.count};
- {error, Reason} ->
- file:close(State#state.fd),
- {error, file_error(Reason)}
- end;
-read(State) ->
- %% Handle upgrade from old releases. Please, remove this clause in next release.
- State2 = upgrade_state(State),
- read(State2).
-
-%%-------------------------------------------------------------------
-%% write(Bin, State) ->
-%% {more, NewState} | {last, FileSize} | {error, {Code, Text}}
-%%
-%% State = term()
-%% NewState = term()
-%% Bin = binary()
-%% FileSize = integer()
-%% Code = undef | enoent | eacces | enospc |
-%% badop | eexist | baduser | badopt |
-%% integer()
-%% Text = string()
-%%
-%% Writes a chunk to the file
-%%
-%% The file is automatically closed when the last chunk is written
-%%-------------------------------------------------------------------
-
-write(Bin, #state{access = write} = State) when is_binary(Bin) ->
- Size = size(Bin),
- BlkSize = State#state.blksize,
- case file:write(State#state.fd, Bin) of
- ok when Size =:= BlkSize->
- Count = State#state.count + Size,
- {more, State#state{count = Count}};
- ok when Size < BlkSize->
- file:close(State#state.fd),
- Count = State#state.count + Size,
- {last, Count};
- {error, Reason} ->
- file:close(State#state.fd),
- file:delete(State#state.filename),
- {error, file_error(Reason)}
- end;
-write(Bin, State) ->
- %% Handle upgrade from old releases. Please, remove this clause in next release.
- State2 = upgrade_state(State),
- write(Bin, State2).
-
-%%-------------------------------------------------------------------
-%% abort(Code, Text, State) -> ok
-%%
-%% State = term()
-%% Code = undef | enoent | eacces | enospc |
-%% badop | eexist | baduser | badopt |
-%% badblk | integer()
-%% Text = string()
-%%
-%% Aborts the file transfer
-%%-------------------------------------------------------------------
-
-abort(_Code, _Text, #state{fd = Fd, access = Access} = State) ->
- file:close(Fd),
- case Access of
- write ->
- ok = file:delete(State#state.filename);
- read ->
- ok
- end.
-
-%%-------------------------------------------------------------------
-%% Process options
-%%-------------------------------------------------------------------
-
-handle_options(Access, Filename, Mode, Options, Initial) ->
- I = #initial{filename = Filename, is_native_ascii = is_native_ascii()},
- {Filename2, IsNativeAscii} = handle_initial(Initial, I),
- IsNetworkAscii = handle_mode(Mode, IsNativeAscii),
- Options2 = do_handle_options(Access, Filename2, Options),
- {ok, Filename2, IsNativeAscii, IsNetworkAscii, Options2}.
-
-handle_mode(Mode, IsNativeAscii) ->
- case Mode of
- "netascii" when IsNativeAscii =:= true -> true;
- "octet" -> false;
- _ -> throw({error, {badop, "Illegal mode " ++ Mode}})
- end.
-
-handle_initial([{root_dir, Dir} | Initial], I) ->
- case catch filename_join(Dir, I#initial.filename) of
- {'EXIT', _} ->
- throw({error, {badop, "Internal error. root_dir is not a string"}});
- Filename2 ->
- handle_initial(Initial, I#initial{filename = Filename2})
- end;
-handle_initial([{native_ascii, Bool} | Initial], I) ->
- case Bool of
- true -> handle_initial(Initial, I#initial{is_native_ascii = true});
- false -> handle_initial(Initial, I#initial{is_native_ascii = false})
- end;
-handle_initial([], I) when is_record(I, initial) ->
- {I#initial.filename, I#initial.is_native_ascii};
-handle_initial(State, _) when is_record(State, state) ->
- {State#state.filename, State#state.is_native_ascii}.
-
-filename_join(Dir, Filename) ->
- case filename:pathtype(Filename) of
- absolute ->
- [_ | RelFilename] = filename:split(Filename),
- filename:join([Dir, RelFilename]);
- _ ->
- filename:join([Dir, Filename])
- end.
-
-do_handle_options(Access, Filename, [{Key, Val} | T]) ->
- case Key of
- "tsize" ->
- case Access of
- read when Val =:= "0" ->
- case file:read_file_info(Filename) of
- {ok, FI} ->
- Tsize = integer_to_list(FI#file_info.size),
- [{Key, Tsize} | do_handle_options(Access, Filename, T)];
- {error, _} ->
- do_handle_options(Access, Filename, T)
- end;
- _ ->
- handle_integer(Access, Filename, Key, Val, T, 0, infinity)
- end;
- "blksize" ->
- handle_integer(Access, Filename, Key, Val, T, 8, 65464);
- "timeout" ->
- handle_integer(Access, Filename, Key, Val, T, 1, 255);
- _ ->
- do_handle_options(Access, Filename, T)
- end;
-do_handle_options(_Access, _Filename, []) ->
- [].
-
-
-handle_integer(Access, Filename, Key, Val, Options, Min, Max) ->
- case catch list_to_integer(Val) of
- {'EXIT', _} ->
- do_handle_options(Access, Filename, Options);
- Int when Int >= Min, Int =< Max ->
- [{Key, Val} | do_handle_options(Access, Filename, Options)];
- Int when Int >= Min, Max =:= infinity ->
- [{Key, Val} | do_handle_options(Access, Filename, Options)];
- _Int ->
- throw({error, {badopt, "Illegal " ++ Key ++ " value " ++ Val}})
- end.
-
-lookup_blksize(Options) ->
- case lists:keysearch("blksize", 1, Options) of
- {value, {_, Val}} ->
- list_to_integer(Val);
- false ->
- 512
- end.
-
-is_native_ascii() ->
- case os:type() of
- {win32, _} -> true;
- _ -> false
- end.
-
-%% Handle upgrade from old releases. Please, remove this function in next release.
-upgrade_state({state, Access, Filename, RootDir, Options, BlkSize, Fd, Count, Buffer}) ->
- {state, Access, Filename, false, false, RootDir, Options, BlkSize, Fd, Count, Buffer}.
diff --git a/lib/inets/src/tftp/tftp_lib.erl b/lib/inets/src/tftp/tftp_lib.erl
deleted file mode 100644
index 454754f0a3..0000000000
--- a/lib/inets/src/tftp/tftp_lib.erl
+++ /dev/null
@@ -1,474 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-%%%-------------------------------------------------------------------
-%%% File : tftp_lib.erl
-%%% Author : Hakan Mattsson <[email protected]>
-%%% Description : Option parsing, decode, encode etc.
-%%%
-%%% Created : 18 May 2004 by Hakan Mattsson <[email protected]>
-%%%-------------------------------------------------------------------
-
--module(tftp_lib).
-
-%%-------------------------------------------------------------------
-%% Interface
-%%-------------------------------------------------------------------
-
-%% application internal functions
--export([
- parse_config/1,
- parse_config/2,
- decode_msg/1,
- encode_msg/1,
- replace_val/3,
- to_lower/1,
- host_to_string/1,
- add_default_callbacks/1
- ]).
-
-%%-------------------------------------------------------------------
-%% Defines
-%%-------------------------------------------------------------------
-
--include("tftp.hrl").
-
--define(LOWER(Char),
- if
- Char >= $A, Char =< $Z ->
- Char - ($A - $a);
- true ->
- Char
- end).
-
-%%-------------------------------------------------------------------
-%% Config
-%%-------------------------------------------------------------------
-
-parse_config(Options) ->
- parse_config(Options, #config{}).
-
-parse_config(Options, Config) ->
- do_parse_config(Options, Config).
-
-do_parse_config([{Key, Val} | Tail], Config) when is_record(Config, config) ->
- case Key of
- debug ->
- if
- Val =:= 0; Val =:= none ->
- do_parse_config(Tail, Config#config{debug_level = none});
- Val =:= 1; Val =:= error ->
- do_parse_config(Tail, Config#config{debug_level = error});
- Val =:= 2; Val =:= warning ->
- do_parse_config(Tail, Config#config{debug_level = warning});
- Val =:= 3; Val =:= brief ->
- do_parse_config(Tail, Config#config{debug_level = brief});
- Val =:= 4; Val =:= normal ->
- do_parse_config(Tail, Config#config{debug_level = normal});
- Val =:= 5; Val =:= verbose ->
- do_parse_config(Tail, Config#config{debug_level = verbose});
- Val =:= 6; Val =:= all ->
- do_parse_config(Tail, Config#config{debug_level = all});
- true ->
- exit({badarg, {Key, Val}})
- end;
- host ->
- if
- is_list(Val) ->
- do_parse_config(Tail, Config#config{udp_host = Val});
- is_tuple(Val), size(Val) =:= 4 ->
- do_parse_config(Tail, Config#config{udp_host = Val});
- is_tuple(Val), size(Val) =:= 8 ->
- do_parse_config(Tail, Config#config{udp_host = Val});
- true ->
- exit({badarg, {Key, Val}})
- end;
- port ->
- if
- is_integer(Val), Val >= 0 ->
- Config2 = Config#config{udp_port = Val, udp_options = Config#config.udp_options},
- do_parse_config(Tail, Config2);
- true ->
- exit({badarg, {Key, Val}})
- end;
- port_policy ->
- case Val of
- random ->
- do_parse_config(Tail, Config#config{port_policy = Val});
- 0 ->
- do_parse_config(Tail, Config#config{port_policy = random});
- MinMax when is_integer(MinMax), MinMax > 0 ->
- do_parse_config(Tail, Config#config{port_policy = {range, MinMax, MinMax}});
- {range, Min, Max} when Max >= Min,
- is_integer(Min), Min > 0,
- is_integer(Max), Max > 0 ->
- do_parse_config(Tail, Config#config{port_policy = Val});
- true ->
- exit({badarg, {Key, Val}})
- end;
- udp when is_list(Val) ->
- Fun =
- fun({K, V}, List) when K /= active ->
- replace_val(K, V, List);
- (V, List) when V /= list, V /= binary ->
- List ++ [V];
- (V, _List) ->
- exit({badarg, {udp, [V]}})
- end,
- UdpOptions = lists:foldl(Fun, Config#config.udp_options, Val),
- do_parse_config(Tail, Config#config{udp_options = UdpOptions});
- use_tsize ->
- case Val of
- true ->
- do_parse_config(Tail, Config#config{use_tsize = Val});
- false ->
- do_parse_config(Tail, Config#config{use_tsize = Val});
- _ ->
- exit({badarg, {Key, Val}})
- end;
- max_tsize ->
- if
- Val =:= infinity ->
- do_parse_config(Tail, Config#config{max_tsize = Val});
- is_integer(Val), Val >= 0 ->
- do_parse_config(Tail, Config#config{max_tsize = Val});
- true ->
- exit({badarg, {Key, Val}})
- end;
- max_conn ->
- if
- Val =:= infinity ->
- do_parse_config(Tail, Config#config{max_conn = Val});
- is_integer(Val), Val > 0 ->
- do_parse_config(Tail, Config#config{max_conn = Val});
- true ->
- exit({badarg, {Key, Val}})
- end;
- _ when is_list(Key), is_list(Val) ->
- Key2 = to_lower(Key),
- Val2 = to_lower(Val),
- TftpOptions = replace_val(Key2, Val2, Config#config.user_options),
- do_parse_config(Tail, Config#config{user_options = TftpOptions});
- reject ->
- case Val of
- read ->
- Rejected = [Val | Config#config.rejected],
- do_parse_config(Tail, Config#config{rejected = Rejected});
- write ->
- Rejected = [Val | Config#config.rejected],
- do_parse_config(Tail, Config#config{rejected = Rejected});
- _ when is_list(Val) ->
- Rejected = [Val | Config#config.rejected],
- do_parse_config(Tail, Config#config{rejected = Rejected});
- _ ->
- exit({badarg, {Key, Val}})
- end;
- callback ->
- case Val of
- {RegExp, Mod, State} when is_list(RegExp), is_atom(Mod) ->
- case re:compile(RegExp) of
- {ok, Internal} ->
- Callback = #callback{regexp = RegExp,
- internal = Internal,
- module = Mod,
- state = State},
- Callbacks = Config#config.callbacks ++ [Callback],
- do_parse_config(Tail, Config#config{callbacks = Callbacks});
- {error, Reason} ->
- exit({badarg, {Key, Val}, Reason})
- end;
- _ ->
- exit({badarg, {Key, Val}})
- end;
- logger ->
- if
- is_atom(Val) ->
- do_parse_config(Tail, Config#config{logger = Val});
- true ->
- exit({badarg, {Key, Val}})
- end;
- max_retries ->
- if
- is_integer(Val), Val > 0 ->
- do_parse_config(Tail, Config#config{max_retries = Val});
- true ->
- exit({badarg, {Key, Val}})
- end;
- _ ->
- exit({badarg, {Key, Val}})
- end;
-do_parse_config([], #config{udp_host = Host,
- udp_options = UdpOptions,
- user_options = UserOptions,
- callbacks = Callbacks} = Config) ->
- IsInet6 = lists:member(inet6, UdpOptions),
- IsInet = lists:member(inet, UdpOptions),
- Host2 =
- if
- (IsInet and not IsInet6); (not IsInet and not IsInet6) ->
- case inet:getaddr(Host, inet) of
- {ok, Addr} ->
- Addr;
- {error, Reason} ->
- exit({badarg, {host, Reason}})
- end;
- (IsInet6 and not IsInet) ->
- case inet:getaddr(Host, inet6) of
- {ok, Addr} ->
- Addr;
- {error, Reason} ->
- exit({badarg, {host, Reason}})
- end;
- true ->
- %% Conflicting options
- exit({badarg, {udp, [inet]}})
- end,
- UdpOptions2 = lists:reverse(UdpOptions),
- TftpOptions = lists:reverse(UserOptions),
- Callbacks2 = add_default_callbacks(Callbacks),
- Config#config{udp_host = Host2,
- udp_options = UdpOptions2,
- user_options = TftpOptions,
- callbacks = Callbacks2};
-do_parse_config(Options, Config) when is_record(Config, config) ->
- exit({badarg, Options}).
-
-add_default_callbacks(Callbacks) ->
- RegExp = "",
- {ok, Internal} = re:compile(RegExp),
- File = #callback{regexp = RegExp,
- internal = Internal,
- module = tftp_file,
- state = []},
- Bin = #callback{regexp = RegExp,
- internal = Internal,
- module = tftp_binary,
- state = []},
- Callbacks ++ [File, Bin].
-
-host_to_string(Host) ->
- case Host of
- String when is_list(String) ->
- String;
- {A1, A2, A3, A4} -> % inet
- lists:concat([A1, ".", A2, ".", A3, ".",A4]);
- {A1, A2, A3, A4, A5, A6, A7, A8} -> % inet6
- lists:concat([
- int16_to_hex(A1), "::",
- int16_to_hex(A2), "::",
- int16_to_hex(A3), "::",
- int16_to_hex(A4), "::",
- int16_to_hex(A5), "::",
- int16_to_hex(A6), "::",
- int16_to_hex(A7), "::",
- int16_to_hex(A8)
- ])
- end.
-
-int16_to_hex(0) ->
- [$0];
-int16_to_hex(I) ->
- N1 = ((I bsr 8) band 16#ff),
- N2 = (I band 16#ff),
- [code_character(N1 div 16), code_character(N1 rem 16),
- code_character(N2 div 16), code_character(N2 rem 16)].
-
-code_character(N) when N < 10 ->
- $0 + N;
-code_character(N) ->
- $A + (N - 10).
-
-%%-------------------------------------------------------------------
-%% Decode
-%%-------------------------------------------------------------------
-
-decode_msg(Bin) when is_binary(Bin) ->
- case Bin of
- <<?TFTP_OPCODE_RRQ:16/integer, Tail/binary>> ->
- case decode_strings(Tail, [keep_case, lower_case]) of
- [Filename, Mode | Strings] ->
- Options = decode_options(Strings),
- #tftp_msg_req{access = read,
- filename = Filename,
- mode = to_lower(Mode),
- options = Options};
- [_Filename | _Strings] ->
- exit(#tftp_msg_error{code = undef,
- text = "Missing mode"});
- _ ->
- exit(#tftp_msg_error{code = undef,
- text = "Missing filename"})
- end;
- <<?TFTP_OPCODE_WRQ:16/integer, Tail/binary>> ->
- case decode_strings(Tail, [keep_case, lower_case]) of
- [Filename, Mode | Strings] ->
- Options = decode_options(Strings),
- #tftp_msg_req{access = write,
- filename = Filename,
- mode = to_lower(Mode),
- options = Options};
- [_Filename | _Strings] ->
- exit(#tftp_msg_error{code = undef,
- text = "Missing mode"});
- _ ->
- exit(#tftp_msg_error{code = undef,
- text = "Missing filename"})
- end;
- <<?TFTP_OPCODE_DATA:16/integer, SeqNo:16/integer, Data/binary>> ->
- #tftp_msg_data{block_no = SeqNo, data = Data};
- <<?TFTP_OPCODE_ACK:16/integer, SeqNo:16/integer>> ->
- #tftp_msg_ack{block_no = SeqNo};
- <<?TFTP_OPCODE_ERROR:16/integer, ErrorCode:16/integer, Tail/binary>> ->
- case decode_strings(Tail, [keep_case]) of
- [ErrorText] ->
- ErrorCode2 = decode_error_code(ErrorCode),
- #tftp_msg_error{code = ErrorCode2,
- text = ErrorText};
- _ ->
- exit(#tftp_msg_error{code = undef,
- text = "Trailing garbage"})
- end;
- <<?TFTP_OPCODE_OACK:16/integer, Tail/binary>> ->
- Strings = decode_strings(Tail, [lower_case]),
- Options = decode_options(Strings),
- #tftp_msg_oack{options = Options};
- _ ->
- exit(#tftp_msg_error{code = undef,
- text = "Invalid syntax"})
- end.
-
-decode_strings(Bin, Cases) when is_binary(Bin), is_list(Cases) ->
- do_decode_strings(Bin, Cases, []).
-
-do_decode_strings(<<>>, _Cases, Strings) ->
- lists:reverse(Strings);
-do_decode_strings(Bin, [Case | Cases], Strings) ->
- {String, Tail} = decode_string(Bin, Case, []),
- if
- Cases =:= [] ->
- do_decode_strings(Tail, [Case], [String | Strings]);
- true ->
- do_decode_strings(Tail, Cases, [String | Strings])
- end.
-
-decode_string(<<Char:8/integer, Tail/binary>>, Case, String) ->
- if
- Char =:= 0 ->
- {lists:reverse(String), Tail};
- Case =:= keep_case ->
- decode_string(Tail, Case, [Char | String]);
- Case =:= lower_case ->
- Char2 = ?LOWER(Char),
- decode_string(Tail, Case, [Char2 | String])
- end;
-decode_string(<<>>, _Case, _String) ->
- exit(#tftp_msg_error{code = undef, text = "Trailing null missing"}).
-
-decode_options([Key, Value | Strings]) ->
- [{to_lower(Key), Value} | decode_options(Strings)];
-decode_options([]) ->
- [].
-
-decode_error_code(Int) ->
- case Int of
- ?TFTP_ERROR_UNDEF -> undef;
- ?TFTP_ERROR_ENOENT -> enoent;
- ?TFTP_ERROR_EACCES -> eacces;
- ?TFTP_ERROR_ENOSPC -> enospc;
- ?TFTP_ERROR_BADOP -> badop;
- ?TFTP_ERROR_BADBLK -> badblk;
- ?TFTP_ERROR_EEXIST -> eexist;
- ?TFTP_ERROR_BADUSER -> baduser;
- ?TFTP_ERROR_BADOPT -> badopt;
- Int when is_integer(Int), Int >= 0, Int =< 65535 -> Int;
- _ -> exit(#tftp_msg_error{code = undef, text = "Error code outside range."})
- end.
-
-%%-------------------------------------------------------------------
-%% Encode
-%%-------------------------------------------------------------------
-
-encode_msg(#tftp_msg_req{access = Access,
- filename = Filename,
- mode = Mode,
- options = Options}) ->
- OpCode = case Access of
- read -> ?TFTP_OPCODE_RRQ;
- write -> ?TFTP_OPCODE_WRQ
- end,
- [
- <<OpCode:16/integer>>,
- Filename,
- 0,
- Mode,
- 0,
- [[Key, 0, Val, 0] || {Key, Val} <- Options]
- ];
-encode_msg(#tftp_msg_data{block_no = BlockNo, data = Data}) when BlockNo =< 65535 ->
- [
- <<?TFTP_OPCODE_DATA:16/integer, BlockNo:16/integer>>,
- Data
- ];
-encode_msg(#tftp_msg_ack{block_no = BlockNo}) when BlockNo =< 65535 ->
- <<?TFTP_OPCODE_ACK:16/integer, BlockNo:16/integer>>;
-encode_msg(#tftp_msg_error{code = Code, text = Text}) ->
- IntCode = encode_error_code(Code),
- [
- <<?TFTP_OPCODE_ERROR:16/integer, IntCode:16/integer>>,
- Text,
- 0
- ];
-encode_msg(#tftp_msg_oack{options = Options}) ->
- [
- <<?TFTP_OPCODE_OACK:16/integer>>,
- [[Key, 0, Val, 0] || {Key, Val} <- Options]
- ].
-
-encode_error_code(Code) ->
- case Code of
- undef -> ?TFTP_ERROR_UNDEF;
- enoent -> ?TFTP_ERROR_ENOENT;
- eacces -> ?TFTP_ERROR_EACCES;
- enospc -> ?TFTP_ERROR_ENOSPC;
- badop -> ?TFTP_ERROR_BADOP;
- badblk -> ?TFTP_ERROR_BADBLK;
- eexist -> ?TFTP_ERROR_EEXIST;
- baduser -> ?TFTP_ERROR_BADUSER;
- badopt -> ?TFTP_ERROR_BADOPT;
- Int when is_integer(Int), Int >= 0, Int =< 65535 -> Int
- end.
-
-%%-------------------------------------------------------------------
-%% Miscellaneous
-%%-------------------------------------------------------------------
-
-replace_val(Key, Val, List) ->
- case lists:keysearch(Key, 1, List) of
- false ->
- List ++ [{Key, Val}];
- {value, {_, OldVal}} when OldVal =:= Val ->
- List;
- {value, {_, _}} ->
- lists:keyreplace(Key, 1, List, {Key, Val})
- end.
-
-to_lower(Chars) ->
- [?LOWER(Char) || Char <- Chars].
diff --git a/lib/inets/src/tftp/tftp_logger.erl b/lib/inets/src/tftp/tftp_logger.erl
deleted file mode 100644
index a869958484..0000000000
--- a/lib/inets/src/tftp/tftp_logger.erl
+++ /dev/null
@@ -1,99 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(tftp_logger).
-
-%%-------------------------------------------------------------------
-%% Interface
-%%-------------------------------------------------------------------
-
-%% public functions
--export([
- error_msg/2,
- warning_msg/2,
- info_msg/2
- ]).
-
--export([behaviour_info/1]).
-
-behaviour_info(callbacks) ->
- [{error_msg, 2}, {warning_msg, 2}, {info_msg, 2}];
-behaviour_info(_) ->
- undefined.
-
-%%-------------------------------------------------------------------
-%% error_msg(Format, Data) -> ok | exit(Reason)
-%%
-%% Format = string()
-%% Data = [term()]
-%% Reason = term()
-%%
-%% Log an error message
-%%-------------------------------------------------------------------
-
-error_msg(Format, Data) ->
- {Format2, Data2} = add_timestamp(Format, Data),
- error_logger:error_msg(Format2, Data2).
-
-%%-------------------------------------------------------------------
-%% warning_msg(Format, Data) -> ok | exit(Reason)
-%%
-%% Format = string()
-%% Data = [term()]
-%% Reason = term()
-%%
-%% Log a warning message
-%%-------------------------------------------------------------------
-
-warning_msg(Format, Data) ->
- {Format2, Data2} = add_timestamp(Format, Data),
- error_logger:warning_msg(Format2, Data2).
-
-%%-------------------------------------------------------------------
-%% info_msg(Format, Data) -> ok | exit(Reason)
-%%
-%% Format = string()
-%% Data = [term()]
-%% Reason = term()
-%%
-%% Log an info message
-%%-------------------------------------------------------------------
-
-info_msg(Format, Data) ->
- {Format2, Data2} = add_timestamp(Format, Data),
- io:format(Format2, Data2).
-
-%%-------------------------------------------------------------------
-%% Add timestamp to log message
-%%-------------------------------------------------------------------
-
-add_timestamp(Format, Data) ->
- Time = erlang:timestamp(),
- {{_Y, _Mo, _D}, {H, Mi, S}} = calendar:now_to_universal_time(Time),
- %% {"~p-~s-~sT~s:~s:~sZ,~6.6.0w tftp: " ++ Format ++ "\n",
- %% [Y, t(Mo), t(D), t(H), t(Mi), t(S), MicroSecs | Data]}.
- {"~s:~s:~s tftp: " ++ Format, [t(H), t(Mi), t(S) | Data]}.
-
-%% Convert 9 to "09".
-t(Int) ->
- case integer_to_list(Int) of
- [Single] -> [$0, Single];
- Multi -> Multi
- end.
diff --git a/lib/inets/src/tftp/tftp_sup.erl b/lib/inets/src/tftp/tftp_sup.erl
deleted file mode 100644
index 40b67c499c..0000000000
--- a/lib/inets/src/tftp/tftp_sup.erl
+++ /dev/null
@@ -1,111 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% Purpose: The top supervisor for tftp hangs under inets_sup.
-%%----------------------------------------------------------------------
-
--module(tftp_sup).
-
--behaviour(supervisor).
-
-%% API
--export([start_link/1,
- start_child/1,
- stop_child/1,
- which_children/0]).
-
-%% Supervisor callback
--export([init/1]).
-
-%%%=========================================================================
-%%% API
-%%%=========================================================================
-
-start_link(TftpServices) ->
- supervisor:start_link({local, ?MODULE}, ?MODULE, [TftpServices]).
-
-start_child(Options) ->
- KillAfter = default_kill_after(),
- ChildSpec = worker_spec(KillAfter, Options),
- supervisor:start_child(?MODULE, ChildSpec).
-
-stop_child(Pid) when is_pid(Pid) ->
- Children = supervisor:which_children(?MODULE),
- case [Id || {Id, P, _Type, _Modules} <- Children, P =:= Pid] of
- [] ->
- {error, not_found};
- [Id] ->
- case supervisor:terminate_child(?MODULE, Id) of
- ok ->
- supervisor:delete_child(?MODULE, Id);
- {error, not_found} ->
- supervisor:delete_child(?MODULE, Id);
- {error, Reason} ->
- {error, Reason}
- end
- end.
-
-which_children() ->
- Children = supervisor:which_children(?MODULE),
- [{tftpd, Pid} || {_Id, Pid, _Type, _Modules} <- Children, Pid =/= undefined].
-
-%%%=========================================================================
-%%% Supervisor callback
-%%%=========================================================================
-
-init([Services]) when is_list(Services) ->
- RestartStrategy = one_for_one,
- MaxR = 10,
- MaxT = 3600,
- KillAfter = default_kill_after(),
- Children = [worker_spec(KillAfter, Options) || {tftpd, Options} <- Services],
- {ok, {{RestartStrategy, MaxR, MaxT}, Children}}.
-
-%%%=========================================================================
-%%% Internal functions
-%%%=========================================================================
-
-worker_spec(KillAfter, Options) ->
- Modules = [proc_lib, tftp, tftp_engine],
- KA = supervisor_timeout(KillAfter),
- Name = unique_name(Options),
- {Name, {tftp, start, [Options]}, permanent, KA, worker, Modules}.
-
-unique_name(Options) ->
- case lists:keysearch(port, 1, Options) of
- {value, {_, Port}} when is_integer(Port), Port > 0 ->
- {tftpd, Port};
- _ ->
- {tftpd, erlang:unique_integer([positive])}
- end.
-
-default_kill_after() ->
- timer:seconds(3).
-
-%% supervisor_spec(Name) ->
-%% {Name, {Name, start, []}, permanent, infinity, supervisor,
-%% [Name, supervisor]}.
-
--ifdef(debug_shutdown).
-supervisor_timeout(_KillAfter) -> timer:hours(24).
--else.
-supervisor_timeout(KillAfter) -> KillAfter.
--endif.
diff --git a/lib/inets/test/Makefile b/lib/inets/test/Makefile
index ffc512050a..6ab9771a8f 100644
--- a/lib/inets/test/Makefile
+++ b/lib/inets/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -44,8 +44,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
INCLUDES = -I. \
-I$(ERL_TOP)/lib/inets/src/inets_app \
-I$(ERL_TOP)/lib/inets/src/http_lib \
- -I$(ERL_TOP)/lib/inets/src/http_client \
- -I$(ERL_TOP)/lib/inets/src/ftp
+ -I$(ERL_TOP)/lib/inets/src/http_client
CP = cp
@@ -68,34 +67,6 @@ INETS_FLAGS = -Dinets_data_dir='"$(INETS_DATA_DIR)"' \
###
### test suite debug flags
###
-ifeq ($(FTP_DEBUG_CLIENT),)
- FTP_DEBUG_CLIENT = y
-endif
-
-ifeq ($(FTP_DEBUG_CLIENT),)
- FTP_FLAGS += -Dftp_debug_client
-endif
-
-ifeq ($(FTP_TRACE_CLIENT),)
- FTP_DEBUG_CLIENT = y
-endif
-
-ifeq ($(FTP_TRACE_CLIENT),y)
- FTP_FLAGS += -Dftp_trace_client
-endif
-
-ifneq ($(FTP_DEBUG),)
- FTP_DEBUG = s
-endif
-
-ifeq ($(FTP_DEBUG),l)
- FTP_FLAGS += -Dftp_log
-endif
-
-ifeq ($(FTP_DEBUG),d)
- FTP_FLAGS += -Dftp_debug -Dftp_log
-endif
-
ifeq ($(INETS_DEBUG),)
INETS_DEBUG = d
endif
@@ -150,17 +121,16 @@ INETS_ROOT = ../../inets
MODULES = \
inets_test_lib \
erl_make_certs \
- ftp_SUITE \
- ftp_format_SUITE \
+ make_certs \
http_format_SUITE \
httpc_SUITE \
httpc_cookie_SUITE \
httpc_proxy_SUITE \
httpd_SUITE \
- old_httpd_SUITE \
+ httpd_bench_SUITE \
+ http_test_lib \
httpd_basic_SUITE \
httpd_mod \
- httpd_block \
httpd_load \
httpd_time_test \
httpd_1_1 \
@@ -168,8 +138,6 @@ MODULES = \
httpd_test_lib \
inets_sup_SUITE \
inets_SUITE \
- tftp_test_lib \
- tftp_SUITE \
uri_SUITE \
inets_socketwrap_SUITE
@@ -178,10 +146,8 @@ EBIN = .
HRL_FILES = inets_test_lib.hrl \
inets_internal.hrl \
- ftp_internal.hrl \
httpc_internal.hrl \
- http_internal.hrl \
- tftp_test_lib.hrl
+ http_internal.hrl
ERL_FILES = $(MODULES:%=%.erl)
@@ -189,23 +155,22 @@ SOURCE = $(ERL_FILES) $(HRL_FILES)
TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-INETS_SPECS = inets.spec
+INETS_SPECS = inets.spec inets_bench.spec
COVER_FILE = inets.cover
INETS_FILES = inets.config $(INETS_SPECS)
# SUB_SUITES = \
# inets_sup_suite \
# inets_httpd_suite \
-# inets_httpc_suite \
-# inets_ftp_suite \
-# inets_tftp_suite
+# inets_httpc_suite
+
INETS_DATADIRS = inets_SUITE_data inets_socketwrap_SUITE_data
-HTTPD_DATADIRS = httpd_test_data httpd_SUITE_data httpd_basic_SUITE_data old_httpd_SUITE_data
+HTTPD_DATADIRS = httpd_test_data httpd_SUITE_data httpd_basic_SUITE_data old_httpd_SUITE_data httpd_bench_SUITE_data
+
HTTPC_DATADIRS = httpc_SUITE_data httpc_proxy_SUITE_data
-FTP_DATADIRS = ftp_SUITE_data
-DATADIRS = $(INETS_DATADIRS) $(HTTPD_DATADIRS) $(HTTPC_DATADIRS) $(FTP_DATADIRS)
+DATADIRS = $(INETS_DATADIRS) $(HTTPD_DATADIRS) $(HTTPC_DATADIRS)
EMAKEFILE = Emakefile
MAKE_EMAKE = $(wildcard $(ERL_TOP)/make/make_emakefile)
@@ -235,7 +200,6 @@ RELTESTSYSBINDIR = $(RELTESTSYSALLDATADIR)/bin
# ----------------------------------------------------
ERL_COMPILE_FLAGS += \
$(INCLUDES) \
- $(FTP_FLAGS) \
$(INETS_FLAGS)
# ----------------------------------------------------
@@ -331,11 +295,3 @@ info:
@echo "INETS_PRIV_DIR = $(INETS_PRIV_DIR)"
@echo "INETS_ROOT = $(INETS_ROOT)"
@echo "INETS_FLAGS = $(INETS_FLAGS)"
- @echo "FTP_FLAGS = $(FTP_FLAGS)"
-
-tftp:
- erlc $(ERL_COMPILE_FLAGS) tftp_test_lib.erl tftp_SUITE.erl && erl -pa ../../inets/ebin -s tftp_SUITE t -s erlang halt
-
-tftp_work:
- echo "tftp_test_lib:t([{tftp_SUITE, all}])."
- erlc $(ERL_COMPILE_FLAGS) tftp_test_lib.erl tftp_SUITE.erl && erl -pa ../../inets/ebin
diff --git a/lib/inets/test/ftp_SUITE.erl b/lib/inets/test/ftp_SUITE.erl
deleted file mode 100644
index 3dfec01ba2..0000000000
--- a/lib/inets/test/ftp_SUITE.erl
+++ /dev/null
@@ -1,1180 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-%%
-%% ct:run("../inets_test", ftp_SUITE).
-%%
-
--module(ftp_SUITE).
-
--include_lib("kernel/include/file.hrl").
--include_lib("common_test/include/ct.hrl").
--include("inets_test_lib.hrl").
-
-%% Note: This directive should only be used in test suites.
--compile(export_all).
-
--define(FTP_USER, "anonymous").
--define(FTP_PASS(Cmnt), (fun({ok,__H}) -> "ftp_SUITE_"++Cmnt++"@" ++ __H;
- (_) -> "ftp_SUITE_"++Cmnt++"@localhost"
- end)(inet:gethostname())
- ).
-
--define(BAD_HOST, "badhostname").
--define(BAD_USER, "baduser").
--define(BAD_DIR, "baddirectory").
-
--record(progress, {
- current = 0,
- total
- }).
-
-%%--------------------------------------------------------------------
-%% Common Test interface functions -----------------------------------
-%%--------------------------------------------------------------------
-suite() ->
- [{timetrap,{seconds,20}}].
-
-all() ->
- [
- {group, ftp_passive},
- {group, ftp_active},
- {group, ftps_passive},
- {group, ftps_active},
- error_ehost,
- clean_shutdown
- ].
-
-groups() ->
- [
- {ftp_passive, [], ftp_tests()},
- {ftp_active, [], ftp_tests()},
- {ftps_passive, [], ftp_tests()},
- {ftps_active, [], ftp_tests()}
- ].
-
-ftp_tests()->
- [
- user,
- bad_user,
- pwd,
- cd,
- lcd,
- ls,
- nlist,
- rename,
- delete,
- mkdir,
- rmdir,
- send,
- send_3,
- send_bin,
- send_chunk,
- append,
- append_bin,
- append_chunk,
- recv,
- recv_3,
- recv_bin,
- recv_bin_twice,
- recv_chunk,
- recv_chunk_twice,
- recv_chunk_three_times,
- type,
- quote,
- error_elogin,
- progress_report_send,
- progress_report_recv,
- not_owner,
- unexpected_call,
- unexpected_cast,
- unexpected_bang
- ].
-
-%%--------------------------------------------------------------------
-
-%%% Config
-%%% key meaning
-%%% ................................................................
-%%% ftpservers list of servers to check if they are available
-%%% The element is:
-%%% {Name, % string(). The os command name
-%%% Path, % string(). The os PATH syntax, e.g "/bin:/usr/bin"
-%%% StartCommand, % fun()->{ok,start_result()} | {error,string()}.
-%%% % The command to start the daemon with.
-%%% ChkUp, % fun(start_result()) -> string(). Os command to check
-%%% % if the server is running. [] if not running.
-%%% % The string in string() is suitable for logging.
-%%% StopCommand, % fun(start_result()) -> void(). The command to stop the daemon with.
-%%% AugmentFun, % fun(config()) -> config() Adds two funs for transforming names of files
-%%% % and directories to the form they are returned from this server
-%%% ServerHost, % string(). Mostly "localhost"
-%%% ServerPort % pos_integer()
-%%% }
-%%%
-
--define(default_ftp_servers,
- [{"vsftpd",
- "/sbin:/usr/sbin:/usr/local/sbin",
- fun(__CONF__, AbsName) ->
- DataDir = proplists:get_value(data_dir,__CONF__),
- ConfFile = filename:join(DataDir, "vsftpd.conf"),
- PrivDir = proplists:get_value(priv_dir,__CONF__),
- AnonRoot = PrivDir,
- Cmd = [AbsName ++" "++filename:join(DataDir,"vsftpd.conf"),
- " -oftpd_banner=erlang_otp_testing",
- " -oanon_root=\"",AnonRoot,"\"",
- " -orsa_cert_file=\"",filename:join(DataDir,"server-cert.pem"),"\"",
- " -orsa_private_key_file=\"",filename:join(DataDir,"server-key.pem"),"\""
- ],
- Result = os:cmd(Cmd),
- ct:log("Config file:~n~s~n~nServer start command:~n ~s~nResult:~n ~p",
- [case file:read_file(ConfFile) of
- {ok,X} -> X;
- _ -> ""
- end,
- Cmd, Result
- ]),
- case Result of
- [] -> {ok,'dont care'};
- [Msg] -> {error,Msg}
- end
- end,
- fun(_StartResult) -> os:cmd("ps ax | grep erlang_otp_testing | grep -v grep")
- end,
- fun(_StartResult) -> os:cmd("kill `ps ax | grep erlang_otp_testing | awk '/vsftpd/{print $1}'`")
- end,
- fun(__CONF__) ->
- AnonRoot = proplists:get_value(priv_dir,__CONF__),
- [{id2ftp, fun(Id) -> filename:join(AnonRoot,Id) end},
- {id2ftp_result,fun(Id) -> filename:join(AnonRoot,Id) end} | __CONF__]
- end,
- "localhost",
- 9999
- }
- ]
- ).
-
-
-init_per_suite(Config) ->
- case find_executable(Config) of
- false ->
- {skip, "No ftp server found"};
- {ok,Data} ->
- TstDir = filename:join(proplists:get_value(priv_dir,Config), "test"),
- file:make_dir(TstDir),
- make_cert_files(dsa, rsa, "server-", proplists:get_value(data_dir,Config)),
- start_ftpd([{test_dir,TstDir},
- {ftpd_data,Data}
- | Config])
- end.
-
-end_per_suite(Config) ->
- ps_ftpd(Config),
- stop_ftpd(Config),
- ps_ftpd(Config),
- ok.
-
-%%--------------------------------------------------------------------
-init_per_group(Group, Config) when Group == ftps_active,
- Group == ftps_passive ->
- catch crypto:stop(),
- try crypto:start() of
- ok ->
- Config
- catch
- _:_ ->
- {skip, "Crypto did not start"}
- end;
-
-init_per_group(_Group, Config) ->
- Config.
-
-end_per_group(_Group, Config) ->
- Config.
-
-%%--------------------------------------------------------------------
-init_per_testcase(Case, Config0) ->
- Group = proplists:get_value(name, proplists:get_value(tc_group_properties,Config0)),
- TLS = [{tls,[{reuse_sessions,true}]}],
- ACTIVE = [{mode,active}],
- PASSIVE = [{mode,passive}],
- CaseOpts = case Case of
- progress_report_send -> [{progress, {?MODULE,progress,#progress{}}}];
- progress_report_recv -> [{progress, {?MODULE,progress,#progress{}}}];
- _ -> []
- end,
- ExtraOpts = [verbose | CaseOpts],
- Config =
- case Group of
- ftp_active -> ftp__open(Config0, ACTIVE ++ ExtraOpts);
- ftps_active -> ftp__open(Config0, TLS++ ACTIVE ++ ExtraOpts);
- ftp_passive -> ftp__open(Config0, PASSIVE ++ ExtraOpts);
- ftps_passive -> ftp__open(Config0, TLS++PASSIVE ++ ExtraOpts);
- undefined -> Config0
- end,
- case Case of
- user -> Config;
- bad_user -> Config;
- error_elogin -> Config;
- error_ehost -> Config;
- clean_shutdown -> Config;
- _ ->
- Pid = proplists:get_value(ftp,Config),
- ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS(atom_to_list(Group)++"-"++atom_to_list(Case)) ),
- ok = ftp:cd(Pid, proplists:get_value(priv_dir,Config)),
- Config
- end.
-
-
-end_per_testcase(user, _Config) -> ok;
-end_per_testcase(bad_user, _Config) -> ok;
-end_per_testcase(error_elogin, _Config) -> ok;
-end_per_testcase(error_ehost, _Config) -> ok;
-end_per_testcase(clean_shutdown, _Config) -> ok;
-end_per_testcase(_Case, Config) ->
- case proplists:get_value(tc_status,Config) of
- ok -> ok;
- _ ->
- try ftp:latest_ctrl_response(proplists:get_value(ftp,Config))
- of
- {ok,S} -> ct:log("***~n*** Latest ctrl channel response:~n*** ~p~n***",[S])
- catch
- _:_ -> ok
- end
- end,
- ftp__close(Config).
-
-%%--------------------------------------------------------------------
-%% Test Cases --------------------------------------------------------
-%%--------------------------------------------------------------------
-user() -> [
- {doc, "Open an ftp connection to a host, and logon as anonymous ftp,"
- " then logoff"}].
-user(Config) ->
- Pid = proplists:get_value(ftp, Config),
- ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS("")),% logon
- ok = ftp:close(Pid), % logoff
- {error,eclosed} = ftp:pwd(Pid), % check logoff result
- ok.
-
-%%-------------------------------------------------------------------------
-bad_user() ->
- [{doc, "Open an ftp connection to a host, and logon with bad user."}].
-bad_user(Config) ->
- Pid = proplists:get_value(ftp, Config),
- {error, euser} = ftp:user(Pid, ?BAD_USER, ?FTP_PASS("")),
- ok.
-
-%%-------------------------------------------------------------------------
-pwd() ->
- [{doc, "Test ftp:pwd/1 & ftp:lpwd/1"}].
-pwd(Config0) ->
- Config = set_state([reset], Config0),
- Pid = proplists:get_value(ftp, Config),
- {ok, PWD} = ftp:pwd(Pid),
- {ok, PathLpwd} = ftp:lpwd(Pid),
- PWD = id2ftp_result("", Config),
- PathLpwd = id2ftp_result("", Config).
-
-%%-------------------------------------------------------------------------
-cd() ->
- ["Open an ftp connection, log on as anonymous ftp, and cd to a"
- "directory and to a non-existent directory."].
-cd(Config0) ->
- Dir = "test",
- Config = set_state([reset,{mkdir,Dir}], Config0),
- Pid = proplists:get_value(ftp, Config),
- ok = ftp:cd(Pid, id2ftp(Dir,Config)),
- {ok, PWD} = ftp:pwd(Pid),
- ExpectedPWD = id2ftp_result(Dir, Config),
- PWD = ExpectedPWD,
- {error, epath} = ftp:cd(Pid, ?BAD_DIR),
- ok.
-
-%%-------------------------------------------------------------------------
-lcd() ->
- [{doc, "Test api function ftp:lcd/2"}].
-lcd(Config0) ->
- Dir = "test",
- Config = set_state([reset,{mkdir,Dir}], Config0),
- Pid = proplists:get_value(ftp, Config),
- ok = ftp:lcd(Pid, id2ftp(Dir,Config)),
- {ok, PWD} = ftp:lpwd(Pid),
- ExpectedPWD = id2ftp_result(Dir, Config),
- PWD = ExpectedPWD,
- {error, epath} = ftp:lcd(Pid, ?BAD_DIR).
-
-%%-------------------------------------------------------------------------
-ls() ->
- [{doc, "Open an ftp connection; ls the current directory, and the "
- "\"test\" directory. We assume that ls never fails, since "
- "it's output is meant to be read by humans. "}].
-ls(Config0) ->
- Config = set_state([reset,{mkdir,"test"}], Config0),
- Pid = proplists:get_value(ftp, Config),
- {ok, _R1} = ftp:ls(Pid),
- {ok, _R2} = ftp:ls(Pid, id2ftp("test",Config)),
- %% neither nlist nor ls operates on a directory
- %% they operate on a pathname, which *can* be a
- %% directory, but can also be a filename or a group
- %% of files (including wildcards).
- case proplists:get_value(wildcard_support, Config) of
- true ->
- {ok, _R3} = ftp:ls(Pid, id2ftp("te*",Config));
- _ ->
- ok
- end.
-
-%%-------------------------------------------------------------------------
-nlist() ->
- [{doc,"Open an ftp connection; nlist the current directory, and the "
- "\"test\" directory. Nlist does not behave consistenly over "
- "operating systems. On some it is an error to have an empty "
- "directory."}].
-nlist(Config0) ->
- Config = set_state([reset,{mkdir,"test"}], Config0),
- Pid = proplists:get_value(ftp, Config),
- {ok, _R1} = ftp:nlist(Pid),
- {ok, _R2} = ftp:nlist(Pid, id2ftp("test",Config)),
- %% neither nlist nor ls operates on a directory
- %% they operate on a pathname, which *can* be a
- %% directory, but can also be a filename or a group
- %% of files (including wildcards).
- case proplists:get_value(wildcard_support, Config) of
- true ->
- {ok, _R3} = ftp:nlist(Pid, id2ftp("te*",Config));
- _ ->
- ok
- end.
-
-%%-------------------------------------------------------------------------
-rename() ->
- [{doc, "Rename a file."}].
-rename(Config0) ->
- Contents = <<"ftp_SUITE test ...">>,
- OldFile = "old.txt",
- NewFile = "new.txt",
- Config = set_state([reset,{mkfile,OldFile,Contents}], Config0),
- Pid = proplists:get_value(ftp, Config),
-
- ok = ftp:rename(Pid,
- id2ftp(OldFile,Config),
- id2ftp(NewFile,Config)),
-
- true = (chk_file(NewFile,Contents,Config)
- and chk_no_file([OldFile],Config)),
- {error,epath} = ftp:rename(Pid,
- id2ftp("non_existing_file",Config),
- id2ftp(NewFile,Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-send() ->
- [{doc, "Transfer a file with ftp using send/2."}].
-send(Config0) ->
- Contents = <<"ftp_SUITE test ...">>,
- SrcDir = "data",
- File = "file.txt",
- Config = set_state([reset,{mkfile,[SrcDir,File],Contents}], Config0),
- Pid = proplists:get_value(ftp, Config),
-
- chk_no_file([File],Config),
- chk_file([SrcDir,File],Contents,Config),
-
- ok = ftp:lcd(Pid, id2ftp(SrcDir,Config)),
- ok = ftp:cd(Pid, id2ftp("",Config)),
- ok = ftp:send(Pid, File),
- chk_file(File, Contents, Config),
-
- {error,epath} = ftp:send(Pid, "non_existing_file"),
- ok.
-
-%%-------------------------------------------------------------------------
-send_3() ->
- [{doc, "Transfer a file with ftp using send/3."}].
-send_3(Config0) ->
- Contents = <<"ftp_SUITE test ...">>,
- Dir = "incoming",
- File = "file.txt",
- RemoteFile = "remfile.txt",
- Config = set_state([reset,{mkfile,File,Contents},{mkdir,Dir}], Config0),
- Pid = proplists:get_value(ftp, Config),
-
- ok = ftp:cd(Pid, id2ftp(Dir,Config)),
- ok = ftp:lcd(Pid, id2ftp("",Config)),
- ok = ftp:send(Pid, File, RemoteFile),
- chk_file([Dir,RemoteFile], Contents, Config),
-
- {error,epath} = ftp:send(Pid, "non_existing_file", RemoteFile),
- ok.
-
-%%-------------------------------------------------------------------------
-send_bin() ->
- [{doc, "Send a binary."}].
-send_bin(Config0) ->
- BinContents = <<"ftp_SUITE test ...">>,
- File = "file.txt",
- Config = set_state([reset], Config0),
- Pid = proplists:get_value(ftp, Config),
- {error, enotbinary} = ftp:send_bin(Pid, "some string", id2ftp(File,Config)),
- ok = ftp:send_bin(Pid, BinContents, id2ftp(File,Config)),
- chk_file(File, BinContents, Config),
- {error, efnamena} = ftp:send_bin(Pid, BinContents, "/nothere"),
- ok.
-
-%%-------------------------------------------------------------------------
-send_chunk() ->
- [{doc, "Send a binary using chunks."}].
-send_chunk(Config0) ->
- Contents1 = <<"1: ftp_SUITE test ...">>,
- Contents2 = <<"2: ftp_SUITE test ...">>,
- File = "file.txt",
- Config = set_state([reset,{mkdir,"incoming"}], Config0),
- Pid = proplists:get_value(ftp, Config),
-
- ok = ftp:send_chunk_start(Pid, id2ftp(File,Config)),
- {error, echunk} = ftp:send_chunk_start(Pid, id2ftp(File,Config)),
- {error, echunk} = ftp:cd(Pid, "incoming"),
- {error, enotbinary} = ftp:send_chunk(Pid, "some string"),
- ok = ftp:send_chunk(Pid, Contents1),
- ok = ftp:send_chunk(Pid, Contents2),
- ok = ftp:send_chunk_end(Pid),
- chk_file(File, <<Contents1/binary,Contents2/binary>>, Config),
-
- {error, echunk} = ftp:send_chunk(Pid, Contents1),
- {error, echunk} = ftp:send_chunk_end(Pid),
- {error, efnamena} = ftp:send_chunk_start(Pid, "/"),
- ok.
-
-%%-------------------------------------------------------------------------
-delete() ->
- [{doc, "Delete a file."}].
-delete(Config0) ->
- Contents = <<"ftp_SUITE test ...">>,
- File = "file.txt",
- Config = set_state([reset,{mkfile,File,Contents}], Config0),
- Pid = proplists:get_value(ftp, Config),
- ok = ftp:delete(Pid, id2ftp(File,Config)),
- chk_no_file([File], Config),
- {error,epath} = ftp:delete(Pid, id2ftp(File,Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-mkdir() ->
- [{doc, "Make a remote directory."}].
-mkdir(Config0) ->
- NewDir = "new_dir",
- Config = set_state([reset], Config0),
- Pid = proplists:get_value(ftp, Config),
- ok = ftp:mkdir(Pid, id2ftp(NewDir,Config)),
- chk_dir([NewDir], Config),
- {error,epath} = ftp:mkdir(Pid, id2ftp(NewDir,Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-rmdir() ->
- [{doc, "Remove a directory."}].
-rmdir(Config0) ->
- Dir = "dir",
- Config = set_state([reset,{mkdir,Dir}], Config0),
- Pid = proplists:get_value(ftp, Config),
- ok = ftp:rmdir(Pid, id2ftp(Dir,Config)),
- chk_no_dir([Dir], Config),
- {error,epath} = ftp:rmdir(Pid, id2ftp(Dir,Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-append() ->
- [{doc, "Append a local file twice to a remote file"}].
-append(Config0) ->
- SrcFile = "f_src.txt",
- DstFile = "f_dst.txt",
- Contents = <<"ftp_SUITE test ...">>,
- Config = set_state([reset,{mkfile,SrcFile,Contents}], Config0),
- Pid = proplists:get_value(ftp, Config),
- ok = ftp:append(Pid, id2ftp(SrcFile,Config), id2ftp(DstFile,Config)),
- ok = ftp:append(Pid, id2ftp(SrcFile,Config), id2ftp(DstFile,Config)),
- chk_file(DstFile, <<Contents/binary,Contents/binary>>, Config),
- {error,epath} = ftp:append(Pid, id2ftp("non_existing_file",Config), id2ftp(DstFile,Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-append_bin() ->
- [{doc, "Append a local file twice to a remote file using append_bin"}].
-append_bin(Config0) ->
- DstFile = "f_dst.txt",
- Contents = <<"ftp_SUITE test ...">>,
- Config = set_state([reset], Config0),
- Pid = proplists:get_value(ftp, Config),
- ok = ftp:append_bin(Pid, Contents, id2ftp(DstFile,Config)),
- ok = ftp:append_bin(Pid, Contents, id2ftp(DstFile,Config)),
- chk_file(DstFile, <<Contents/binary,Contents/binary>>, Config).
-
-%%-------------------------------------------------------------------------
-append_chunk() ->
- [{doc, "Append chunks."}].
-append_chunk(Config0) ->
- File = "f_dst.txt",
- Contents = [<<"ER">>,<<"LE">>,<<"RL">>],
- Config = set_state([reset], Config0),
- Pid = proplists:get_value(ftp, Config),
- ok = ftp:append_chunk_start(Pid, id2ftp(File,Config)),
- {error, enotbinary} = ftp:append_chunk(Pid, binary_to_list(lists:nth(1,Contents))),
- ok = ftp:append_chunk(Pid,lists:nth(1,Contents)),
- ok = ftp:append_chunk(Pid,lists:nth(2,Contents)),
- ok = ftp:append_chunk(Pid,lists:nth(3,Contents)),
- ok = ftp:append_chunk_end(Pid),
- chk_file(File, <<"ERLERL">>, Config).
-
-%%-------------------------------------------------------------------------
-recv() ->
- [{doc, "Receive a file using recv/2"}].
-recv(Config0) ->
- File1 = "f_dst1.txt",
- File2 = "f_dst2.txt",
- SrcDir = "a_dir",
- Contents1 = <<"1 ftp_SUITE test ...">>,
- Contents2 = <<"2 ftp_SUITE test ...">>,
- Config = set_state([reset, {mkfile,[SrcDir,File1],Contents1}, {mkfile,[SrcDir,File2],Contents2}], Config0),
- Pid = proplists:get_value(ftp, Config),
- ok = ftp:cd(Pid, id2ftp(SrcDir,Config)),
- ok = ftp:lcd(Pid, id2ftp("",Config)),
- ok = ftp:recv(Pid, File1),
- chk_file(File1, Contents1, Config),
- ok = ftp:recv(Pid, File2),
- chk_file(File2, Contents2, Config),
- {error,epath} = ftp:recv(Pid, "non_existing_file"),
- ok.
-
-%%-------------------------------------------------------------------------
-recv_3() ->
- [{doc,"Receive a file using recv/3"}].
-recv_3(Config0) ->
- DstFile = "f_src.txt",
- SrcFile = "f_dst.txt",
- Contents = <<"ftp_SUITE test ...">>,
- Config = set_state([reset, {mkfile,SrcFile,Contents}], Config0),
- Pid = proplists:get_value(ftp, Config),
- ok = ftp:cd(Pid, id2ftp("",Config)),
- ok = ftp:recv(Pid, SrcFile, id2abs(DstFile,Config)),
- chk_file(DstFile, Contents, Config).
-
-%%-------------------------------------------------------------------------
-recv_bin() ->
- [{doc, "Receive a file as a binary."}].
-recv_bin(Config0) ->
- File = "f_dst.txt",
- Contents = <<"ftp_SUITE test ...">>,
- Config = set_state([reset, {mkfile,File,Contents}], Config0),
- Pid = proplists:get_value(ftp, Config),
- {ok,Received} = ftp:recv_bin(Pid, id2ftp(File,Config)),
- find_diff(Received, Contents),
- {error,epath} = ftp:recv_bin(Pid, id2ftp("non_existing_file",Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-recv_bin_twice() ->
- [{doc, "Receive two files as a binaries."}].
-recv_bin_twice(Config0) ->
- File1 = "f_dst1.txt",
- File2 = "f_dst2.txt",
- Contents1 = <<"1 ftp_SUITE test ...">>,
- Contents2 = <<"2 ftp_SUITE test ...">>,
- Config = set_state([reset, {mkfile,File1,Contents1}, {mkfile,File2,Contents2}], Config0),
- ct:log("First transfer",[]),
- Pid = proplists:get_value(ftp, Config),
- {ok,Received1} = ftp:recv_bin(Pid, id2ftp(File1,Config)),
- find_diff(Received1, Contents1),
- ct:log("Second transfer",[]),
- {ok,Received2} = ftp:recv_bin(Pid, id2ftp(File2,Config)),
- find_diff(Received2, Contents2),
- ct:log("Transfers ready!",[]),
- {error,epath} = ftp:recv_bin(Pid, id2ftp("non_existing_file",Config)),
- ok.
-%%-------------------------------------------------------------------------
-recv_chunk() ->
- [{doc, "Receive a file using chunk-wise."}].
-recv_chunk(Config0) ->
- File = "big_file.txt",
- Contents = list_to_binary( lists:duplicate(1000, lists:seq(0,255)) ),
- Config = set_state([reset, {mkfile,File,Contents}], Config0),
- Pid = proplists:get_value(ftp, Config),
- {{error, "ftp:recv_chunk_start/2 not called"},_} = recv_chunk(Pid, <<>>),
- ok = ftp:recv_chunk_start(Pid, id2ftp(File,Config)),
- {ok, ReceivedContents, _Ncunks} = recv_chunk(Pid, <<>>),
- find_diff(ReceivedContents, Contents).
-
-recv_chunk_twice() ->
- [{doc, "Receive two files using chunk-wise."}].
-recv_chunk_twice(Config0) ->
- File1 = "big_file1.txt",
- File2 = "big_file2.txt",
- Contents1 = list_to_binary( lists:duplicate(1000, lists:seq(0,255)) ),
- Contents2 = crypto:strong_rand_bytes(1200),
- Config = set_state([reset, {mkfile,File1,Contents1}, {mkfile,File2,Contents2}], Config0),
- Pid = proplists:get_value(ftp, Config),
- {{error, "ftp:recv_chunk_start/2 not called"},_} = recv_chunk(Pid, <<>>),
- ok = ftp:recv_chunk_start(Pid, id2ftp(File1,Config)),
- {ok, ReceivedContents1, _Ncunks1} = recv_chunk(Pid, <<>>),
- ok = ftp:recv_chunk_start(Pid, id2ftp(File2,Config)),
- {ok, ReceivedContents2, _Ncunks2} = recv_chunk(Pid, <<>>),
- find_diff(ReceivedContents1, Contents1),
- find_diff(ReceivedContents2, Contents2).
-
-recv_chunk_three_times() ->
- [{doc, "Receive two files using chunk-wise."},
- {timetrap,{seconds,120}}].
-recv_chunk_three_times(Config0) ->
- File1 = "big_file1.txt",
- File2 = "big_file2.txt",
- File3 = "big_file3.txt",
- Contents1 = list_to_binary( lists:duplicate(1000, lists:seq(0,255)) ),
- Contents2 = crypto:strong_rand_bytes(1200),
- Contents3 = list_to_binary( lists:duplicate(1000, lists:seq(255,0,-1)) ),
-
- Config = set_state([reset, {mkfile,File1,Contents1}, {mkfile,File2,Contents2}, {mkfile,File3,Contents3}], Config0),
- Pid = proplists:get_value(ftp, Config),
- {{error, "ftp:recv_chunk_start/2 not called"},_} = recv_chunk(Pid, <<>>),
-
- ok = ftp:recv_chunk_start(Pid, id2ftp(File1,Config)),
- {ok, ReceivedContents1, Nchunks1} = recv_chunk(Pid, <<>>),
-
- ok = ftp:recv_chunk_start(Pid, id2ftp(File2,Config)),
- {ok, ReceivedContents2, _Nchunks2} = recv_chunk(Pid, <<>>),
-
- ok = ftp:recv_chunk_start(Pid, id2ftp(File3,Config)),
- {ok, ReceivedContents3, _Nchunks3} = recv_chunk(Pid, <<>>, 10000, 0, Nchunks1),
-
- find_diff(ReceivedContents1, Contents1),
- find_diff(ReceivedContents2, Contents2),
- find_diff(ReceivedContents3, Contents3).
-
-
-
-recv_chunk(Pid, Acc) ->
- recv_chunk(Pid, Acc, 0, 0, undefined).
-
-
-
-%% ExpectNchunks :: integer() | undefined
-recv_chunk(Pid, Acc, DelayMilliSec, N, ExpectNchunks) when N+1 < ExpectNchunks ->
- %% for all I in integer(), I < undefined
- recv_chunk1(Pid, Acc, DelayMilliSec, N, ExpectNchunks);
-
-recv_chunk(Pid, Acc, DelayMilliSec, N, ExpectNchunks) ->
- %% N >= ExpectNchunks-1
- timer:sleep(DelayMilliSec),
- recv_chunk1(Pid, Acc, DelayMilliSec, N, ExpectNchunks).
-
-
-recv_chunk1(Pid, Acc, DelayMilliSec, N, ExpectNchunks) ->
- ct:log("Call ftp:recv_chunk",[]),
- case ftp:recv_chunk(Pid) of
- ok -> {ok, Acc, N};
- {ok, Bin} -> recv_chunk(Pid, <<Acc/binary, Bin/binary>>, DelayMilliSec, N+1, ExpectNchunks);
- Error -> {Error, N}
- end.
-
-%%-------------------------------------------------------------------------
-type() ->
- [{doc,"Test that we can change btween ASCCI and binary transfer mode"}].
-type(Config) ->
- Pid = proplists:get_value(ftp, Config),
- ok = ftp:type(Pid, ascii),
- ok = ftp:type(Pid, binary),
- ok = ftp:type(Pid, ascii),
- {error, etype} = ftp:type(Pid, foobar).
-
-%%-------------------------------------------------------------------------
-quote(Config) ->
- Pid = proplists:get_value(ftp, Config),
- ["257 \""++_Rest] = ftp:quote(Pid, "pwd"), %% 257
- [_| _] = ftp:quote(Pid, "help"),
- %% This negativ test causes some ftp servers to hang. This test
- %% is not important for the client, so we skip it for now.
- %%["425 Can't build data connection: Connection refused."]
- %% = ftp:quote(Pid, "list"),
- ok.
-
-%%-------------------------------------------------------------------------
-progress_report_send() ->
- [{doc, "Test the option progress for ftp:send/[2,3]"}].
-progress_report_send(Config) when is_list(Config) ->
- ReportPid =
- spawn_link(?MODULE, progress_report_receiver_init, [self(), 1]),
- send(Config),
- receive
- {ReportPid, ok} ->
- ok
- end.
-
-%%-------------------------------------------------------------------------
-progress_report_recv() ->
- [{doc, "Test the option progress for ftp:recv/[2,3]"}].
-progress_report_recv(Config) when is_list(Config) ->
- ReportPid =
- spawn_link(?MODULE, progress_report_receiver_init, [self(), 3]),
- recv(Config),
- receive
- {ReportPid, ok} ->
- ok
- end.
-
-%%-------------------------------------------------------------------------
-
-not_owner() ->
- [{doc, "Test what happens if a process that not owns the connection tries "
- "to use it"}].
-not_owner(Config) when is_list(Config) ->
- Pid = proplists:get_value(ftp, Config),
-
- Parent = self(),
- OtherPid = spawn_link(
- fun() ->
- {error, not_connection_owner} = ftp:pwd(Pid),
- ftp:close(Pid),
- Parent ! {self(), ok}
- end),
- receive
- {OtherPid, ok} ->
- {ok, _} = ftp:pwd(Pid)
- end.
-
-
-%%-------------------------------------------------------------------------
-
-
-unexpected_call()->
- [{doc, "Test that behaviour of the ftp process if the api is abused"}].
-unexpected_call(Config) when is_list(Config) ->
- Flag = process_flag(trap_exit, true),
- Pid = proplists:get_value(ftp, Config),
-
- %% Serious programming fault, connetion will be shut down
- case (catch gen_server:call(Pid, {self(), foobar, 10}, infinity)) of
- {error, {connection_terminated, 'API_violation'}} ->
- ok;
- Unexpected1 ->
- exit({unexpected_result, Unexpected1})
- end,
- ct:sleep(500),
- undefined = process_info(Pid, status),
- process_flag(trap_exit, Flag).
-%%-------------------------------------------------------------------------
-
-unexpected_cast()->
- [{doc, "Test that behaviour of the ftp process if the api is abused"}].
-unexpected_cast(Config) when is_list(Config) ->
- Flag = process_flag(trap_exit, true),
- Pid = proplists:get_value(ftp, Config),
- %% Serious programming fault, connetion will be shut down
- gen_server:cast(Pid, {self(), foobar, 10}),
- ct:sleep(500),
- undefined = process_info(Pid, status),
- process_flag(trap_exit, Flag).
-%%-------------------------------------------------------------------------
-
-unexpected_bang()->
- [{doc, "Test that connection ignores unexpected bang"}].
-unexpected_bang(Config) when is_list(Config) ->
- Flag = process_flag(trap_exit, true),
- Pid = proplists:get_value(ftp, Config),
- %% Could be an innocent misstake the connection lives.
- Pid ! foobar,
- ct:sleep(500),
- {status, _} = process_info(Pid, status),
- process_flag(trap_exit, Flag).
-
-%%-------------------------------------------------------------------------
-
-clean_shutdown() ->
- [{doc, "Test that owning process that exits with reason "
- "'shutdown' does not cause an error message. OTP 6035"}].
-
-clean_shutdown(Config) ->
- Parent = self(),
- HelperPid = spawn(
- fun() ->
- ftp__open(Config, [verbose]),
- Parent ! ok,
- receive
- nothing -> ok
- end
- end),
- receive
- ok ->
- PrivDir = proplists:get_value(priv_dir, Config),
- LogFile = filename:join([PrivDir,"ticket_6035.log"]),
- error_logger:logfile({open, LogFile}),
- exit(HelperPid, shutdown),
- timer:sleep(2000),
- error_logger:logfile(close),
- case is_error_report_6035(LogFile) of
- true -> ok;
- false -> {fail, "Bad logfile"}
- end
- end.
-
-%%%----------------------------------------------------------------
-%%% Error codes not tested elsewhere
-
-error_elogin(Config0) ->
- Dir = "test",
- OldFile = "old.txt",
- NewFile = "new.txt",
- SrcDir = "data",
- File = "file.txt",
- Config = set_state([reset,
- {mkdir,Dir},
- {mkfile,OldFile,<<"Contents..">>},
- {mkfile,[SrcDir,File],<<"Contents..">>}], Config0),
-
- Pid = proplists:get_value(ftp, Config),
- ok = ftp:lcd(Pid, id2ftp(SrcDir,Config)),
- {error,elogin} = ftp:send(Pid, File),
- ok = ftp:lcd(Pid, id2ftp("",Config)),
- {error,elogin} = ftp:pwd(Pid),
- {error,elogin} = ftp:cd(Pid, id2ftp(Dir,Config)),
- {error,elogin} = ftp:rename(Pid,
- id2ftp(OldFile,Config),
- id2ftp(NewFile,Config)),
- ok.
-
-error_ehost(_Config) ->
- {error, ehost} = ftp:open("nohost.nodomain"),
- ok.
-
-%%--------------------------------------------------------------------
-%% Internal functions -----------------------------------------------
-%%--------------------------------------------------------------------
-
-make_cert_files(Alg1, Alg2, Prefix, Dir) ->
- CaInfo = {CaCert,_} = erl_make_certs:make_cert([{key,Alg1}]),
- {Cert,CertKey} = erl_make_certs:make_cert([{key,Alg2},{issuer,CaInfo}]),
- CaCertFile = filename:join(Dir, Prefix++"cacerts.pem"),
- CertFile = filename:join(Dir, Prefix++"cert.pem"),
- KeyFile = filename:join(Dir, Prefix++"key.pem"),
- der_to_pem(CaCertFile, [{'Certificate', CaCert, not_encrypted}]),
- der_to_pem(CertFile, [{'Certificate', Cert, not_encrypted}]),
- der_to_pem(KeyFile, [CertKey]),
- ok.
-
-der_to_pem(File, Entries) ->
- PemBin = public_key:pem_encode(Entries),
- file:write_file(File, PemBin).
-
-%%--------------------------------------------------------------------
-chk_file(Path=[C|_], ExpectedContents, Config) when 0<C,C=<255 ->
- chk_file([Path], ExpectedContents, Config);
-
-chk_file(PathList, ExpectedContents, Config) ->
- Path = filename:join(PathList),
- AbsPath = id2abs(Path,Config),
- case file:read_file(AbsPath) of
- {ok,ExpectedContents} ->
- true;
- {ok,ReadContents} ->
- {error,{diff,Pos,RC,LC}} = find_diff(ReadContents, ExpectedContents, 1),
- ct:log("Bad contents of ~p.~nGot:~n~p~nExpected:~n~p~nDiff at pos ~p ~nRead: ~p~nExp : ~p",
- [AbsPath,ReadContents,ExpectedContents,Pos,RC,LC]),
- ct:fail("Bad contents of ~p", [Path]);
- {error,Error} ->
- try begin
- {ok,CWD} = file:get_cwd(),
- ct:log("file:get_cwd()=~p~nfiles:~n~p",[CWD,file:list_dir(CWD)])
- end
- of _ -> ok
- catch _:_ ->ok
- end,
- ct:fail("Error reading ~p: ~p",[Path,Error])
- end.
-
-
-chk_no_file(Path=[C|_], Config) when 0<C,C=<255 ->
- chk_no_file([Path], Config);
-
-chk_no_file(PathList, Config) ->
- Path = filename:join(PathList),
- AbsPath = id2abs(Path,Config),
- case file:read_file(AbsPath) of
- {error,enoent} ->
- true;
- {ok,Contents} ->
- ct:log("File ~p exists although it shouldn't. Contents:~n~p",
- [AbsPath,Contents]),
- ct:fail("File exists: ~p", [Path]);
- {error,Error} ->
- ct:fail("Unexpected error reading ~p: ~p",[Path,Error])
- end.
-
-
-chk_dir(Path=[C|_], Config) when 0<C,C=<255 ->
- chk_dir([Path], Config);
-
-chk_dir(PathList, Config) ->
- Path = filename:join(PathList),
- AbsPath = id2abs(Path,Config),
- case file:read_file_info(AbsPath) of
- {ok, #file_info{type=directory}} ->
- true;
- {ok, #file_info{type=Type}} ->
- ct:fail("Expected dir ~p is a ~p",[Path,Type]);
- {error,Error} ->
- ct:fail("Expected dir ~p: ~p",[Path,Error])
- end.
-
-chk_no_dir(PathList, Config) ->
- Path = filename:join(PathList),
- AbsPath = id2abs(Path,Config),
- case file:read_file_info(AbsPath) of
- {error,enoent} ->
- true;
- {ok, #file_info{type=directory}} ->
- ct:fail("Dir ~p erroneously exists",[Path]);
- {ok, #file_info{type=Type}} ->
- ct:fail("~p ~p erroneously exists",[Type,Path]);
- {error,Error} ->
- ct:fail("Unexpected error for ~p: ~p",[Path,Error])
- end.
-
-%%--------------------------------------------------------------------
-find_executable(Config) ->
- search_executable(proplists:get_value(ftpservers, Config, ?default_ftp_servers)).
-
-
-search_executable([{Name,Paths,_StartCmd,_ChkUp,_StopCommand,_ConfigUpd,_Host,_Port}|Srvrs]) ->
- case os_find(Name,Paths) of
- false ->
- ct:log("~p not found",[Name]),
- search_executable(Srvrs);
- AbsName ->
- ct:comment("Found ~p",[AbsName]),
- {ok, {AbsName,_StartCmd,_ChkUp,_StopCommand,_ConfigUpd,_Host,_Port}}
- end;
-search_executable([]) ->
- false.
-
-
-os_find(Name, Paths) ->
- case os:find_executable(Name, Paths) of
- false -> os:find_executable(Name);
- AbsName -> AbsName
- end.
-
-%%%----------------------------------------------------------------
-start_ftpd(Config0) ->
- {AbsName,StartCmd,_ChkUp,_StopCommand,ConfigRewrite,Host,Port} =
- proplists:get_value(ftpd_data, Config0),
- case StartCmd(Config0, AbsName) of
- {ok,StartResult} ->
- Config = [{ftpd_host,Host},
- {ftpd_port,Port},
- {ftpd_start_result,StartResult} | ConfigRewrite(Config0)],
- try
- ftp__close(ftp__open(Config,[verbose]))
- of
- Config1 when is_list(Config1) ->
- ct:log("Usuable ftp server ~p started on ~p:~p",[AbsName,Host,Port]),
- Config
- catch
- Class:Exception ->
- ct:log("Ftp server ~p started on ~p:~p but is unusable:~n~p:~p",
- [AbsName,Host,Port,Class,Exception]),
- {skip, [AbsName," started but unusuable"]}
- end;
- {error,Msg} ->
- {skip, [AbsName," not started: ",Msg]}
- end.
-
-stop_ftpd(Config) ->
- {_Name,_StartCmd,_ChkUp,StopCommand,_ConfigUpd,_Host,_Port} = proplists:get_value(ftpd_data, Config),
- StopCommand(proplists:get_value(ftpd_start_result,Config)).
-
-ps_ftpd(Config) ->
- {_Name,_StartCmd,ChkUp,_StopCommand,_ConfigUpd,_Host,_Port} = proplists:get_value(ftpd_data, Config),
- ct:log( ChkUp(proplists:get_value(ftpd_start_result,Config)) ).
-
-
-ftpd_running(Config) ->
- {_Name,_StartCmd,ChkUp,_StopCommand,_ConfigUpd,_Host,_Port} = proplists:get_value(ftpd_data, Config),
- ChkUp(proplists:get_value(ftpd_start_result,Config)).
-
-ftp__open(Config, Options) ->
- Host = proplists:get_value(ftpd_host,Config),
- Port = proplists:get_value(ftpd_port,Config),
- ct:log("Host=~p, Port=~p",[Host,Port]),
- {ok,Pid} = ftp:open(Host, [{port,Port} | Options]),
- [{ftp,Pid}|Config].
-
-ftp__close(Config) ->
- ok = ftp:close(proplists:get_value(ftp,Config)),
- Config.
-
-split(Cs) -> string:tokens(Cs, "\r\n").
-
-find_diff(Bin1, Bin2) ->
- case find_diff(Bin1, Bin2, 1) of
- {error, {diff,Pos,RC,LC}} ->
- ct:log("Contents differ at position ~p.~nOp1: ~p~nOp2: ~p",[Pos,RC,LC]),
- ct:fail("Contents differ at pos ~p",[Pos]);
- Other ->
- Other
- end.
-
-find_diff(A, A, _) -> true;
-find_diff(<<H,T1/binary>>, <<H,T2/binary>>, Pos) -> find_diff(T1, T2, Pos+1);
-find_diff(RC, LC, Pos) -> {error, {diff, Pos, RC, LC}}.
-
-set_state(Ops, Config) when is_list(Ops) -> lists:foldl(fun set_state/2, Config, Ops);
-
-set_state(reset, Config) ->
- rm('*', id2abs("",Config)),
- PrivDir = proplists:get_value(priv_dir,Config),
- file:set_cwd(PrivDir),
- ftp:lcd(proplists:get_value(ftp,Config),PrivDir),
- set_state({mkdir,""},Config);
-set_state({mkdir,Id}, Config) ->
- Abs = id2abs(Id, Config),
- mk_path(Abs),
- file:make_dir(Abs),
- Config;
-set_state({mkfile,Id,Contents}, Config) ->
- Abs = id2abs(Id, Config),
- mk_path(Abs),
- ok = file:write_file(Abs, Contents),
- Config.
-
-mk_path(Abs) -> lists:foldl(fun mk_path/2, [], filename:split(filename:dirname(Abs))).
-
-mk_path(F, Pfx) ->
- case file:read_file_info(AbsName=filename:join(Pfx,F)) of
- {ok,#file_info{type=directory}} ->
- AbsName;
- {error,eexist} ->
- AbsName;
- {error,enoent} ->
- ok = file:make_dir(AbsName),
- AbsName
- end.
-
-rm('*', Pfx) ->
- {ok,Fs} = file:list_dir(Pfx),
- lists:foreach(fun(F) -> rm(F, Pfx) end, Fs);
-rm(F, Pfx) ->
- case file:read_file_info(AbsName=filename:join(Pfx,F)) of
- {ok,#file_info{type=directory}} ->
- {ok,Fs} = file:list_dir(AbsName),
- lists:foreach(fun(F1) -> rm(F1,AbsName) end, Fs),
- ok = file:del_dir(AbsName);
-
- {ok,#file_info{type=regular}} ->
- ok = file:delete(AbsName);
-
- {error,enoent} ->
- ok
- end.
-
-id2abs(Id, Conf) -> filename:join(proplists:get_value(priv_dir,Conf),ids(Id)).
-id2ftp(Id, Conf) -> (proplists:get_value(id2ftp,Conf))(ids(Id)).
-id2ftp_result(Id, Conf) -> (proplists:get_value(id2ftp_result,Conf))(ids(Id)).
-
-ids([[_|_]|_]=Ids) -> filename:join(Ids);
-ids(Id) -> Id.
-
-
-is_expected_absName(Id, File, Conf) -> File = (proplists:get_value(id2abs,Conf))(Id).
-is_expected_ftpInName(Id, File, Conf) -> File = (proplists:get_value(id2ftp,Conf))(Id).
-is_expected_ftpOutName(Id, File, Conf) -> File = (proplists:get_value(id2ftp_result,Conf))(Id).
-
-
-%%%----------------------------------------------------------------
-%%% Help functions for the option '{progress,Progress}'
-%%%
-
-%%%----------------
-%%% Callback:
-
-progress(#progress{} = P, _File, {file_size, Total} = M) ->
- ct:pal("Progress: ~p",[M]),
- progress_report_receiver ! start,
- P#progress{total = Total};
-
-progress(#progress{current = Current} = P, _File, {transfer_size, 0} = M) ->
- ct:pal("Progress: ~p",[M]),
- progress_report_receiver ! finish,
- case P#progress.total of
- unknown -> P;
- Current -> P;
- Total -> ct:fail({error, {progress, {total,Total}, {current,Current}}}),
- P
- end;
-
-progress(#progress{current = Current} = P, _File, {transfer_size, Size} = M) ->
- ct:pal("Progress: ~p",[M]),
- progress_report_receiver ! update,
- P#progress{current = Current + Size};
-
-progress(P, _File, M) ->
- ct:pal("Progress **** Strange: ~p",[M]),
- P.
-
-
-%%%----------------
-%%% Help process that counts the files transferred:
-
-progress_report_receiver_init(Parent, N) ->
- register(progress_report_receiver, self()),
- progress_report_receiver_expect_N_files(Parent, N).
-
-progress_report_receiver_expect_N_files(_Parent, 0) ->
- ct:pal("progress_report got all files!", []);
-progress_report_receiver_expect_N_files(Parent, N) ->
- ct:pal("progress_report expects ~p more files",[N]),
- receive
- start -> ok
- end,
- progress_report_receiver_loop(Parent, N-1).
-
-
-progress_report_receiver_loop(Parent, N) ->
- ct:pal("progress_report expect update | finish. N = ~p",[N]),
- receive
- update ->
- ct:pal("progress_report got update",[]),
- progress_report_receiver_loop(Parent, N);
- finish ->
- ct:pal("progress_report got finish, send ~p to ~p",[{self(),ok}, Parent]),
- Parent ! {self(), ok},
- progress_report_receiver_expect_N_files(Parent, N)
- end.
-
-%%%----------------------------------------------------------------
-%%% Help functions for bug OTP-6035
-
-is_error_report_6035(LogFile) ->
- case file:read_file(LogFile) of
- {ok, Bin} ->
- nomatch =/= binary:match(Bin, <<"=ERROR REPORT====">>);
- _ ->
- false
- end.
-
diff --git a/lib/inets/test/ftp_SUITE_data/vsftpd.conf b/lib/inets/test/ftp_SUITE_data/vsftpd.conf
deleted file mode 100644
index a5584f5916..0000000000
--- a/lib/inets/test/ftp_SUITE_data/vsftpd.conf
+++ /dev/null
@@ -1,26 +0,0 @@
-
-###
-### Some parameters are given in the vsftpd start command.
-###
-### Typical command-line paramters are such that has a file path
-### component like cert files.
-###
-
-
-listen=YES
-listen_port=9999
-run_as_launching_user=YES
-ssl_enable=YES
-allow_anon_ssl=YES
-
-background=YES
-
-write_enable=YES
-anonymous_enable=YES
-anon_upload_enable=YES
-anon_mkdir_write_enable=YES
-anon_other_write_enable=YES
-anon_world_readable_only=NO
-
-### Shouldn't be necessary....
-require_ssl_reuse=NO
diff --git a/lib/inets/test/ftp_format_SUITE.erl b/lib/inets/test/ftp_format_SUITE.erl
deleted file mode 100644
index 95d594a44b..0000000000
--- a/lib/inets/test/ftp_format_SUITE.erl
+++ /dev/null
@@ -1,328 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(ftp_format_SUITE).
--author('[email protected]').
-
--include_lib("common_test/include/ct.hrl").
--include("ftp_internal.hrl").
-
-%% Note: This directive should only be used in test suites.
--compile(export_all).
-
-suite() ->
- [{ct_hooks,[ts_install_cth]},
- {timetrap,{seconds,5}}
- ].
-
-all() ->
- [{group, ftp_response}, format_error].
-
-groups() ->
- [{ftp_response, [],
- [ftp_150, ftp_200, ftp_220, ftp_226, ftp_257, ftp_331,
- ftp_425, ftp_other_status_codes, ftp_multiple_lines_status_in_msg,
- ftp_multiple_lines, ftp_multipel_ctrl_messages]}].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(_, Config) ->
- Config.
-end_per_testcase(_, _) ->
- ok.
-
-%%-------------------------------------------------------------------------
-%% Test cases starts here.
-%%-------------------------------------------------------------------------
-
-ftp_150() ->
- [{doc, "Especially check that respons can be devided in a random place."}].
-ftp_150(Config) when is_list(Config) ->
- FtpResponse = ["150 ASCII data conn", "ection for /bin/ls ",
- "(134.138.177", ".89,50434) (0 bytes).\r\n"],
-
- "150 ASCII data connection for /bin/ls "
- "(134.138.177.89,50434) (0 bytes).\r\n" = Msg =
- parse(ftp_response, parse_lines, [[], start], FtpResponse),
- {pos_prel, _} = ftp_response:interpret(Msg).
-
-ftp_200() ->
- [{doc, "Especially check that respons can be devided after the first status "
- "code character and in the end delimiter."}].
-ftp_200(Config) when is_list(Config) ->
- FtpResponse = ["2", "00 PORT command successful.", [?CR], [?LF]],
-
- "200 PORT command successful.\r\n" = Msg =
- parse(ftp_response, parse_lines, [[], start], FtpResponse),
- {pos_compl, _} = ftp_response:interpret(Msg),
- ok.
-
-ftp_220() ->
- [{doc, "Especially check that respons can be devided after the "
- "first with space "}].
-ftp_220(Config) when is_list(Config) ->
- FtpResponse = ["220 ","fingon FTP server (SunOS 5.8) ready.\r\n"],
-
- "220 fingon FTP server (SunOS 5.8) ready.\r\n" = Msg =
- parse(ftp_response, parse_lines, [[], start], FtpResponse),
- {pos_compl, _} = ftp_response:interpret(Msg),
- ok.
-
-ftp_226() ->
- [{doc, "Especially check that respons can be devided after second status code"
- " character and in the end delimiter."}].
-ftp_226(Config) when is_list(Config) ->
- FtpResponse = ["22" "6 Transfer complete.\r", [?LF]],
-
- "226 Transfer complete.\r\n" = Msg =
- parse(ftp_response, parse_lines, [[], start], FtpResponse),
- {pos_compl, _} = ftp_response:interpret(Msg),
- ok.
-
-ftp_257() ->
- [{doc, "Especially check that quoted chars do not cause a problem."}].
-ftp_257(Config) when is_list(Config) ->
- FtpResponse = ["257 \"/\" is current directory.\r\n"],
-
- "257 \"/\" is current directory.\r\n" = Msg =
- parse(ftp_response, parse_lines, [[], start], FtpResponse),
- {pos_compl, _} = ftp_response:interpret(Msg),
- ok.
-
-ftp_331() ->
- [{doc, "Especially check that respons can be devided after the third status "
- " status code character."}].
-ftp_331(Config) when is_list(Config) ->
- %% Brake before white space after code
- FtpResponse =
- ["331"," Guest login ok, send ient as password.\r\n"],
-
- "331 Guest login ok, send ient as password.\r\n" = Msg =
- parse(ftp_response, parse_lines, [[], start], FtpResponse),
- {pos_interm, _} = ftp_response:interpret(Msg),
- ok.
-
-ftp_425() ->
- [{doc, "Especially check a message that was received in only one part."}].
-ftp_425(Config) when is_list(Config) ->
- FtpResponse =
- ["425 Can't build data connection: Connection refused.\r\n"],
-
- "425 Can't build data connection: Connection refused.\r\n"
- = Msg = parse(ftp_response, parse_lines, [[], start], FtpResponse),
- {trans_neg_compl, _} = ftp_response:interpret(Msg),
- ok.
-
-ftp_multiple_lines_status_in_msg() ->
- [{doc, "check that multiple lines gets parsed correct, even if we have "
- " the status code within the msg being sent"}].
-ftp_multiple_lines_status_in_msg(Config) when is_list(Config) ->
- ML = "230-User usr-230 is logged in\r\n" ++
- "230 OK. Current directory is /\r\n",
- {ok, ML, <<>>} = ftp_response:parse_lines(list_to_binary(ML), [], start),
- ok.
-
-ftp_multiple_lines() ->
- [{doc, "Especially check multiple lines devided in significant places"}].
-ftp_multiple_lines(Config) when is_list(Config) ->
- FtpResponse = ["21", "4","-The",
- " following commands are recognized:\r\n"
- " USER EPRT STRU MAIL* ALLO CWD",
- " STAT* XRMD \r\n"
- " PASS LPRT MODE MSND* "
- " REST* XCWD HELP PWD ", [?CRLF],
- " ACCT* EPSV RETR MSOM* RNFR LIST "
- " NOOP XPWD \r\n",
- " REIN* LPSV STOR MSAM* RNTO NLST "
- " MKD CDUP \r\n"
- " QUIT PASV APPE MRSQ* ABOR SITE* "
- " XMKD XCUP \r\n"
- " PORT TYPE MLFL* MRCP* DELE SYST "
- " RMD STOU \r\n"
- "214 (*'s => unimplemented)", [?CR], [?LF]],
-
-
- FtpResponse1 = ["214-", "The",
- " following commands are recognized:\r\n"
- " USER EPRT STRU MAIL* ALLO CWD",
- " STAT* XRMD \r\n"
- " PASS LPRT MODE MSND* "
- " REST* XCWD HELP PWD ", [?CRLF],
- " ACCT* EPSV RETR MSOM* RNFR LIST "
- " NOOP XPWD \r\n",
- " REIN* LPSV STOR MSAM* RNTO NLST "
- " MKD CDUP \r\n"
- " QUIT PASV APPE MRSQ* ABOR SITE* "
- " XMKD XCUP \r\n"
- " PORT TYPE MLFL* MRCP* DELE SYST "
- " RMD STOU \r\n"
- "2", "14 (*'s => unimplemented)", [?CR], [?LF]],
-
- FtpResponse2 = ["214-", "The",
- " following commands are recognized:\r\n"
- " USER EPRT STRU MAIL* ALLO CWD",
- " STAT* XRMD \r\n"
- " PASS LPRT MODE MSND* "
- " REST* XCWD HELP PWD ", [?CRLF],
- " ACCT* EPSV RETR MSOM* RNFR LIST "
- " NOOP XPWD \r\n",
- " REIN* LPSV STOR MSAM* RNTO NLST "
- " MKD CDUP \r\n"
- " QUIT PASV APPE MRSQ* ABOR SITE* "
- " XMKD XCUP \r\n"
- " PORT TYPE MLFL* MRCP* DELE SYST "
- " RMD STOU \r\n"
- "21", "4"," (*'s => unimplemented)", [?CR], [?LF]],
-
- MultiLineResultStr =
- "214-The following commands are recognized:\r\n"
- " USER EPRT STRU MAIL* ALLO CWD STAT* "
- "XRMD \r\n"
- " PASS LPRT MODE MSND* REST* XCWD HELP "
- "PWD \r\n"
- " ACCT* EPSV RETR MSOM* RNFR LIST NOOP "
- "XPWD \r\n"
- " REIN* LPSV STOR MSAM* RNTO NLST MKD "
- "CDUP \r\n"
- " QUIT PASV APPE MRSQ* ABOR SITE* XMKD "
- "XCUP \r\n"
- " PORT TYPE MLFL* MRCP* DELE SYST RMD "
- "STOU \r\n"
- "214 (*'s => unimplemented)\r\n",
-
- MultiLineResultStr =
- parse(ftp_response, parse_lines, [[], start], FtpResponse),
- {pos_compl, _} = ftp_response:interpret(MultiLineResultStr),
-
- MultiLineResultStr = parse(ftp_response, parse_lines, [[], start],
- FtpResponse1),
-
- MultiLineResultStr = parse(ftp_response, parse_lines, [[], start],
- FtpResponse2),
- ok.
-
-ftp_other_status_codes() ->
- [{doc, "Check that other valid status codes, than the ones above, are handled"
- "by ftp_response:interpret/1. Note there are som ftp status codes"
- "that will not be received with the current ftp instruction support,"
- "they are not included here."}].
-ftp_other_status_codes(Config) when is_list(Config) ->
-
- %% 1XX
- {pos_prel, _ } = ftp_response:interpret("120 Foobar\r\n"),
-
- %% 2XX
- {pos_compl, _ } = ftp_response:interpret("202 Foobar\r\n"),
- {pos_compl, _ } = ftp_response:interpret("221 Foobar\r\n"),
- {pos_compl, _ } = ftp_response:interpret("227 Foobar\r\n"),
- {pos_compl, _ } = ftp_response:interpret("230 Foobar\r\n"),
- {pos_compl, _ } = ftp_response:interpret("250 Foobar\r\n"),
-
- %% 3XX
- {pos_interm_acct, _ } = ftp_response:interpret("332 Foobar\r\n"),
- {pos_interm, _ } = ftp_response:interpret("350 Foobar\r\n"),
-
- %% 4XX
- {trans_neg_compl, _ } = ftp_response:interpret("421 Foobar\r\n"),
- {trans_neg_compl, _ } = ftp_response:interpret("426 Foobar\r\n"),
- {enofile, _ } = ftp_response:interpret("450 Foobar\r\n"),
- {trans_neg_compl, _ } = ftp_response:interpret("451 Foobar\r\n"),
- {etnospc, _ } = ftp_response:interpret("452 Foobar\r\n"),
-
- %% 5XX
- {perm_neg_compl, _ } = ftp_response:interpret("500 Foobar\r\n"),
- {perm_neg_compl, _ } = ftp_response:interpret("501 Foobar\r\n"),
- {perm_neg_compl, _ } = ftp_response:interpret("503 Foobar\r\n"),
- {perm_neg_compl, _ } = ftp_response:interpret("504 Foobar\r\n"),
- {elogin, _ } = ftp_response:interpret("530 Foobar\r\n"),
- {perm_neg_compl, _ } = ftp_response:interpret("532 Foobar\r\n"),
- {epath, _ } = ftp_response:interpret("550 Foobar\r\n"),
- {epnospc, _ } = ftp_response:interpret("552 Foobar\r\n"),
- {efnamena, _ } = ftp_response:interpret("553 Foobar\r\n"),
- ok.
-
-ftp_multipel_ctrl_messages() ->
- [{doc, "The ftp server may send more than one control message as a reply,"
- "check that they are handled one at the time."}].
-ftp_multipel_ctrl_messages(Config) when is_list(Config) ->
- FtpResponse = ["200 PORT command successful.\r\n200 Foobar\r\n"],
-
- {"200 PORT command successful.\r\n" = Msg, NextMsg} =
- parse(ftp_response, parse_lines, [[], start], FtpResponse),
- {pos_compl, _} = ftp_response:interpret(Msg),
- NewMsg = parse(ftp_response, parse_lines, [[], start], NextMsg),
- {pos_compl, _} = ftp_response:interpret(NewMsg),
- ok.
-
-
-%%-------------------------------------------------------------------------
-format_error(Config) when is_list(Config) ->
- "Synchronisation error during chunk sending." =
- ftp:formaterror(echunk),
- "Session has been closed." = ftp:formaterror(eclosed),
- "Connection to remote server prematurely closed." =
- ftp:formaterror(econn),
- "File or directory already exists." = ftp:formaterror(eexists),
- "Host not found, FTP server not found, or connection rejected." =
- ftp:formaterror(ehost),
- "User not logged in." = ftp:formaterror(elogin),
- "Term is not a binary." = ftp:formaterror(enotbinary),
- "No such file or directory, already exists, or permission denied."
- = ftp:formaterror(epath),
- "No such type." = ftp:formaterror(etype),
- "User name or password not valid." = ftp:formaterror(euser),
- "Insufficient storage space in system." = ftp:formaterror(etnospc),
- "Exceeded storage allocation (for current directory or dataset)."
- = ftp:formaterror(epnospc),
- "File name not allowed." = ftp:formaterror(efnamena),
- "Unknown error: foobar" = ftp:formaterror({error, foobar}).
-
-%%--------------------------------------------------------------------
-%%% Internal functions
-%%--------------------------------------------------------------------
-parse(Module, Function, Args, Bin) when is_binary(Bin) ->
- parse(Module, Function, Args, [binary_to_list(Bin)]);
-
-parse(Module, Function, [AccLines, StatusCode], [Data | Rest]) ->
- case Module:Function(list_to_binary(Data), AccLines, StatusCode) of
- {ok, Result, <<>>} ->
- Result;
- {ok, Result, Next} ->
- {Result, Next};
- {continue, {NewData, NewAccLines, NewStatusCode}} ->
- case Rest of
- [] ->
- ct:fail({wrong_input, Data, Rest});
- [_ | _] ->
- parse(Module, Function, [NewAccLines, NewStatusCode],
- [binary_to_list(NewData) ++ hd(Rest) | tl(Rest)])
- end
- end.
diff --git a/lib/inets/test/ftp_internal.hrl b/lib/inets/test/ftp_internal.hrl
deleted file mode 120000
index af57081f14..0000000000
--- a/lib/inets/test/ftp_internal.hrl
+++ /dev/null
@@ -1 +0,0 @@
-../src/ftp/ftp_internal.hrl \ No newline at end of file
diff --git a/lib/inets/test/ftp_property_test_SUITE.erl b/lib/inets/test/ftp_property_test_SUITE.erl
deleted file mode 100644
index b314882296..0000000000
--- a/lib/inets/test/ftp_property_test_SUITE.erl
+++ /dev/null
@@ -1,53 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-%%% Run like this:
-%%% ct:run_test([{suite,"ftp_property_test_SUITE"}, {logdir,"/ldisk/OTP/LOG"}]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%% %%%
-%%% WARNING %%%
-%%% %%%
-%%% This is experimental code which may be changed or removed %%%
-%%% anytime without any warning. %%%
-%%% %%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
--module(ftp_property_test_SUITE).
-
--compile(export_all).
-
--include_lib("common_test/include/ct.hrl").
-
-all() -> [prop_ftp_case].
-
-
-init_per_suite(Config) ->
- inets:start(),
- ct_property_test:init_per_suite(Config).
-
-
-%%%---- test case
-prop_ftp_case(Config) ->
- ct_property_test:quickcheck(
- ftp_simple_client_server:prop_ftp(Config),
- Config
- ).
diff --git a/lib/inets/test/http_format_SUITE.erl b/lib/inets/test/http_format_SUITE.erl
index 4e10a97f58..d6b0e5f9f5 100644
--- a/lib/inets/test/http_format_SUITE.erl
+++ b/lib/inets/test/http_format_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -535,8 +535,11 @@ esi_parse_headers(Config) when is_list(Config) ->
{"location","http://foo.bar.se"}], 302} =
httpd_esi:handle_headers(Headers2),
- {proceed,"/foo/bar.html"} =
- httpd_esi:handle_headers("location:/foo/bar.html\r\n").
+ {ok,[{"location","/foo/bar.html"}], 302} =
+ httpd_esi:handle_headers("location:/foo/bar.html\r\n"),
+
+ {ok,[{"location","http://foo/bar.html"}],201} =
+ httpd_esi:handle_headers("status:201 Created\r\nlocation:http://foo/bar.html\r\n").
%%--------------------------------------------------------------------
cgi_parse_headers() ->
diff --git a/lib/inets/test/http_test_lib.erl b/lib/inets/test/http_test_lib.erl
new file mode 100644
index 0000000000..4e119cce04
--- /dev/null
+++ b/lib/inets/test/http_test_lib.erl
@@ -0,0 +1,199 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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(http_test_lib).
+
+-include_lib("common_test/include/ct.hrl").
+-include("inets_test_lib.hrl").
+-include("http_internal.hrl").
+-include("httpc_internal.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+dummy_server(SocketType, Inet, Extra) ->
+ dummy_server(self(), SocketType, Inet, Extra).
+
+dummy_server(Caller, SocketType, Inet, Extra) ->
+ Args = [Caller, SocketType, Inet, Extra],
+ Pid = spawn(?MODULE, dummy_server_init, Args),
+ receive
+ {port, Port} ->
+ {Pid, Port}
+ end.
+
+dummy_server_init(Caller, ip_comm, Inet, Extra) ->
+ ContentCb = proplists:get_value(content_cb, Extra),
+ BaseOpts = [binary, {packet, 0}, {reuseaddr,true}, {active, false}, {nodelay, true}],
+ Conf = proplists:get_value(conf, Extra),
+ {ok, ListenSocket} = gen_tcp:listen(0, [Inet | BaseOpts]),
+ {ok, Port} = inet:port(ListenSocket),
+ Caller ! {port, Port},
+ dummy_ipcomm_server_loop({httpd_request, parse, [[{max_uri, ?HTTP_MAX_URI_SIZE},
+ {max_header, ?HTTP_MAX_HEADER_SIZE},
+ {max_version,?HTTP_MAX_VERSION_STRING},
+ {max_method, ?HTTP_MAX_METHOD_STRING},
+ {max_content_length, ?HTTP_MAX_CONTENT_LENGTH},
+ {customize, httpd_custom}
+ ]]},
+ [], ContentCb, Conf, ListenSocket);
+
+dummy_server_init(Caller, unix_socket, Inet, Extra) ->
+ ContentCb = proplists:get_value(content_cb, Extra),
+ UnixSocket = proplists:get_value(unix_socket, Extra),
+ SocketAddr = {local, UnixSocket},
+ BaseOpts = [binary, {packet, 0}, {reuseaddr,true}, {active, false}, {nodelay, true},
+ {ifaddr, SocketAddr}],
+ Conf = proplists:get_value(conf, Extra),
+ {ok, ListenSocket} = gen_tcp:listen(0, [Inet | BaseOpts]),
+ {ok, Port} = inet:port(ListenSocket),
+ Caller ! {port, Port},
+ dummy_ipcomm_server_loop({httpd_request, parse, [[{max_uri, ?HTTP_MAX_URI_SIZE},
+ {max_header, ?HTTP_MAX_HEADER_SIZE},
+ {max_version,?HTTP_MAX_VERSION_STRING},
+ {max_method, ?HTTP_MAX_METHOD_STRING},
+ {max_content_length, ?HTTP_MAX_CONTENT_LENGTH},
+ {customize, httpd_custom}
+ ]]},
+ [], ContentCb, Conf, ListenSocket);
+
+dummy_server_init(Caller, ssl, Inet, Extra) ->
+ ContentCb = proplists:get_value(content_cb, Extra),
+ SSLOptions = proplists:get_value(ssl, Extra),
+ Conf = proplists:get_value(conf, Extra),
+ BaseOpts = [binary, {reuseaddr,true}, {active, false}, {nodelay, true} |
+ SSLOptions],
+ dummy_ssl_server_init(Caller, BaseOpts, Inet, ContentCb, Conf).
+
+dummy_ssl_server_init(Caller, BaseOpts, Inet, ContentCb, Conf) ->
+ {ok, ListenSocket} = ssl:listen(0, [Inet | BaseOpts]),
+ {ok, {_, Port}} = ssl:sockname(ListenSocket),
+ Caller ! {port, Port},
+ dummy_ssl_server_loop({httpd_request, parse, [[{max_uri, ?HTTP_MAX_URI_SIZE},
+ {max_method, ?HTTP_MAX_METHOD_STRING},
+ {max_version,?HTTP_MAX_VERSION_STRING},
+ {max_method, ?HTTP_MAX_METHOD_STRING},
+ {max_content_length, ?HTTP_MAX_CONTENT_LENGTH},
+ {customize, httpd_custom}
+ ]]},
+ [], ContentCb, Conf, ListenSocket).
+
+dummy_ipcomm_server_loop(MFA, Handlers, ContentCb, Conf, ListenSocket) ->
+ receive
+ stop ->
+ lists:foreach(fun(Handler) -> Handler ! stop end, Handlers);
+ {stop, From} ->
+ Stopper = fun(Handler) -> Handler ! stop end,
+ lists:foreach(Stopper, Handlers),
+ From ! {stopped, self()}
+ after 0 ->
+ {ok, Socket} = gen_tcp:accept(ListenSocket),
+ HandlerPid = dummy_request_handler(MFA, Socket, ContentCb, Conf),
+ gen_tcp:controlling_process(Socket, HandlerPid),
+ HandlerPid ! ipcomm_controller,
+ dummy_ipcomm_server_loop(MFA, [HandlerPid | Handlers],
+ ContentCb, Conf, ListenSocket)
+ end.
+
+dummy_ssl_server_loop(MFA, Handlers, ContentCb, Conf, ListenSocket) ->
+ receive
+ stop ->
+ lists:foreach(fun(Handler) -> Handler ! stop end, Handlers);
+ {stop, From} ->
+ Stopper = fun(Handler) -> Handler ! stop end,
+ lists:foreach(Stopper, Handlers),
+ From ! {stopped, self()}
+ after 0 ->
+ {ok, Socket} = ssl:transport_accept(ListenSocket),
+ HandlerPid = dummy_request_handler(MFA, Socket, ContentCb, Conf),
+ ssl:controlling_process(Socket, HandlerPid),
+ HandlerPid ! ssl_controller,
+ dummy_ssl_server_loop(MFA, [HandlerPid | Handlers],
+ ContentCb, Conf, ListenSocket)
+ end.
+
+dummy_request_handler(MFA, Socket, ContentCb, Conf) ->
+ spawn(?MODULE, dummy_request_handler_init, [MFA, Socket, ContentCb, Conf]).
+
+dummy_request_handler_init(MFA, Socket, ContentCb, Conf) ->
+ SockType =
+ receive
+ ipcomm_controller ->
+ inet:setopts(Socket, [{active, true}]),
+ ip_comm;
+ ssl_controller ->
+ ok = ssl:ssl_accept(Socket, infinity),
+ ssl:setopts(Socket, [{active, true}]),
+ ssl
+ end,
+ dummy_request_handler_loop(MFA, SockType, Socket, ContentCb, Conf).
+
+dummy_request_handler_loop({Module, Function, Args}, SockType, Socket, ContentCb, Conf) ->
+ receive
+ {Proto, _, Data} when (Proto =:= tcp) orelse (Proto =:= ssl) ->
+ case handle_request(Module, Function, [Data | Args], Socket, ContentCb, Conf) of
+ stop when Proto =:= tcp ->
+ gen_tcp:close(Socket);
+ stop when Proto =:= ssl ->
+ ssl:close(Socket);
+ NewMFA ->
+ dummy_request_handler_loop(NewMFA, SockType, Socket, ContentCb, Conf)
+ end;
+ stop when SockType =:= ip_comm ->
+ gen_tcp:close(Socket);
+ stop when SockType =:= ssl ->
+ ssl:close(Socket)
+ end.
+
+handle_request(Module, Function, Args, Socket, ContentCb, Conf) ->
+ case Module:Function(Args) of
+ {ok, Result} ->
+ case ContentCb:handle_http_msg(Result, Socket, Conf) of
+ stop ->
+ stop;
+ <<>> ->
+ {httpd_request, parse, [[{max_uri,?HTTP_MAX_URI_SIZE},
+ {max_header, ?HTTP_MAX_HEADER_SIZE},
+ {max_version,?HTTP_MAX_VERSION_STRING},
+ {max_method, ?HTTP_MAX_METHOD_STRING},
+ {max_content_length, ?HTTP_MAX_CONTENT_LENGTH},
+ {customize, httpd_custom}
+ ]]};
+ Data ->
+ handle_request(httpd_request, parse,
+ [Data, [{max_uri, ?HTTP_MAX_URI_SIZE},
+ {max_header, ?HTTP_MAX_HEADER_SIZE},
+ {max_version,?HTTP_MAX_VERSION_STRING},
+ {max_method, ?HTTP_MAX_METHOD_STRING},
+ {max_content_length, ?HTTP_MAX_CONTENT_LENGTH},
+ {customize, httpd_custom}
+ ]], Socket, ContentCb, Conf)
+ end;
+ NewMFA ->
+ NewMFA
+ end.
+
+%% Perform a synchronous stop
+dummy_server_stop(Pid) ->
+ Pid ! {stop, self()},
+ receive
+ {stopped, Pid} ->
+ ok
+ end.
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index e6dcd2285f..8357e02014 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -37,36 +37,53 @@
-define(TLS_URL_START, "https://").
-define(NOT_IN_USE_PORT, 8997).
+%% Using hardcoded file path to keep it below 107 charaters
+%% (maximum length supported by erlang)
+-define(UNIX_SOCKET, "/tmp/inets_httpc_SUITE.sock").
+
-record(sslsocket, {fd = nil, pid = nil}).
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
suite() ->
- [{ct_hooks,[ts_install_cth]}
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{seconds, 30}}
].
all() ->
[
{group, http},
+ {group, http_ipv6},
{group, sim_http},
+ {group, http_internal},
+ {group, http_unix_socket},
{group, https},
{group, sim_https},
- {group, misc}
+ {group, misc},
+ {group, sim_mixed} % HTTP and HTTPS sim servers
].
groups() ->
[
{http, [], real_requests()},
- {sim_http, [], only_simulated()},
+ {http_ipv6, [], [request_options]},
+ %% process_leak_on_keepalive is depending on stream_fun_server_close
+ %% and it shall be the last test case in the suite otherwise cookie
+ %% will fail.
+ {sim_http, [], only_simulated() ++ server_closing_connection() ++ [process_leak_on_keepalive]},
+ {http_internal, [], real_requests_esi()},
+ {http_unix_socket, [], simulated_unix_socket()},
{https, [], real_requests()},
{sim_https, [], only_simulated()},
- {misc, [], misc()}
+ {misc, [], misc()},
+ {sim_mixed, [], sim_mixed()}
].
real_requests()->
[
head,
get,
+ get_query_string,
post,
delete,
post_stream,
@@ -92,6 +109,12 @@ real_requests()->
invalid_body
].
+real_requests_esi() ->
+ [slow_connection].
+
+simulated_unix_socket() ->
+ [unix_domain_socket].
+
only_simulated() ->
[
cookie,
@@ -114,10 +137,10 @@ only_simulated() ->
invalid_chunk_size,
headers_dummy,
headers_with_obs_fold,
+ headers_conflict_chunked_with_length,
empty_response_header,
remote_socket_close,
remote_socket_close_async,
- process_leak_on_keepalive,
transfer_encoding,
transfer_encoding_identity,
redirect_loop,
@@ -126,23 +149,41 @@ only_simulated() ->
redirect_found,
redirect_see_other,
redirect_temporary_redirect,
+ redirect_relative_uri,
port_in_host_header,
redirect_port_in_host_header,
relaxed,
- multipart_chunks
+ multipart_chunks,
+ get_space,
+ delete_no_body,
+ post_with_content_type,
+ stream_fun_server_close
+ ].
+
+server_closing_connection() ->
+ [
+ server_closing_connection_on_first_response,
+ server_closing_connection_on_second_response
].
misc() ->
[
server_does_not_exist,
timeout_memory_leak,
- wait_for_whole_response
+ wait_for_whole_response,
+ post_204_chunked,
+ chunkify_fun
+ ].
+
+sim_mixed() ->
+ [
+ redirect_http_to_https,
+ redirect_relative_different_port
].
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- ct:timetrap({seconds, 30}),
PrivDir = proplists:get_value(priv_dir, Config),
DataDir = proplists:get_value(data_dir, Config),
inets_test_lib:start_apps([inets]),
@@ -165,30 +206,88 @@ init_per_group(misc = Group, Config) ->
Config;
-init_per_group(Group, Config0) when Group =:= sim_https; Group =:= https->
+init_per_group(Group, Config0) when Group =:= sim_https; Group =:= https;
+ Group =:= sim_mixed ->
catch crypto:stop(),
try crypto:start() of
ok ->
- ct:timetrap({seconds, 30}),
start_apps(Group),
do_init_per_group(Group, Config0)
catch
_:_ ->
{skip, "Crypto did not start"}
end;
-
+init_per_group(http_unix_socket = Group, Config0) ->
+ case os:type() of
+ {win32,_} ->
+ {skip, "Unix Domain Sockets are not supported on Windows"};
+ _ ->
+ file:delete(?UNIX_SOCKET),
+ start_apps(Group),
+ Config = proplists:delete(port, Config0),
+ Port = server_start(Group, server_config(Group, Config)),
+ [{port, Port} | Config]
+ end;
+init_per_group(http_ipv6 = Group, Config0) ->
+ case is_ipv6_supported() of
+ true ->
+ start_apps(Group),
+ Config = proplists:delete(port, Config0),
+ Port = server_start(Group, server_config(Group, Config)),
+ [{port, Port} | Config];
+ false ->
+ {skip, "Host does not support IPv6"}
+ end;
init_per_group(Group, Config0) ->
start_apps(Group),
Config = proplists:delete(port, Config0),
Port = server_start(Group, server_config(Group, Config)),
[{port, Port} | Config].
+end_per_group(http_unix_socket,_Config) ->
+ file:delete(?UNIX_SOCKET),
+ ok;
end_per_group(_, _Config) ->
ok.
+
+do_init_per_group(Group=sim_mixed, Config0) ->
+ % The mixed group uses two server ports (http and https), so we use
+ % different config names here.
+ Config1 = init_ssl(Config0),
+ Config2 = proplists:delete(http_port, proplists:delete(https_port, Config1)),
+ {HttpPort, HttpsPort} = server_start(Group, server_config(sim_https, Config2)),
+ [{http_port, HttpPort} | [{https_port, HttpsPort} | Config2]];
do_init_per_group(Group, Config0) ->
- Config = proplists:delete(port, Config0),
+ Config1 =
+ case Group of
+ https ->
+ init_ssl(Config0);
+ sim_https ->
+ init_ssl(Config0);
+ _ ->
+ Config0
+ end,
+ Config = proplists:delete(port, Config1),
Port = server_start(Group, server_config(Group, Config)),
[{port, Port} | Config].
+
+init_ssl(Config) ->
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "client"]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "server"]),
+ GenCertData =
+ public_key:pkix_test_data(#{server_chain =>
+ #{root => [{key, inets_test_lib:hardcode_rsa_key(1)}],
+ intermediates => [[{key, inets_test_lib:hardcode_rsa_key(2)}]],
+ peer => [{key, inets_test_lib:hardcode_rsa_key(3)}
+ ]},
+ client_chain =>
+ #{root => [{key, inets_test_lib:hardcode_rsa_key(4)}],
+ intermediates => [[{key, inets_test_lib:hardcode_rsa_key(5)}]],
+ peer => [{key, inets_test_lib:hardcode_rsa_key(6)}]}}),
+
+ Conf = inets_test_lib:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+ [{ssl_conf, Conf} | Config].
+
%%--------------------------------------------------------------------
init_per_testcase(pipeline, Config) ->
inets:start(httpc, [{profile, pipeline}]),
@@ -199,7 +298,7 @@ init_per_testcase(pipeline, Config) ->
init_per_testcase(persistent_connection, Config) ->
inets:start(httpc, [{profile, persistent}]),
httpc:set_options([{keep_alive_timeout, 50000},
- {max_keep_alive_length, 3}], persistent_connection),
+ {max_keep_alive_length, 3}], persistent),
Config;
init_per_testcase(wait_for_whole_response, Config) ->
@@ -218,10 +317,38 @@ end_per_testcase(pipeline, _Config) ->
inets:stop(httpc, pipeline);
end_per_testcase(persistent_connection, _Config) ->
inets:stop(httpc, persistent);
+end_per_testcase(Case, Config)
+ when Case == server_closing_connection_on_first_response;
+ Case == server_closing_connection_on_second_response ->
+ %% Test case uses at most one session. Ensure no leftover
+ %% sessions left behind.
+ {_, Status} = proplists:lookup(tc_status, Config),
+ ShallCleanup = case Status of
+ ok -> true;
+ {failed, _} -> true;
+ {skipped, _} -> false
+ end,
+ if ShallCleanup =:= true ->
+ httpc:request(url(group_name(Config), "/just_close.html", Config)),
+ ok;
+ true ->
+ ct:pal("Not cleaning up because test case status was ~p", [Status]),
+ ok
+ end;
end_per_testcase(_Case, _Config) ->
ok.
+is_ipv6_supported() ->
+ case gen_udp:open(0, [inet6]) of
+ {ok, Socket} ->
+ gen_udp:close(Socket),
+ true;
+ _ ->
+ false
+ end.
+
+
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
@@ -243,6 +370,25 @@ get(Config) when is_list(Config) ->
{ok, {{_,200,_}, [_ | _], BinBody}} = httpc:request(get, Request, [], [{body_format, binary}]),
true = is_binary(BinBody).
+
+
+get_query_string() ->
+ [{doc, "Test http get request with query string against local server"}].
+get_query_string(Config) when is_list(Config) ->
+ Request = {url(group_name(Config), "/dummy.html?foo=bar", Config), []},
+ {ok, {{_,200,_}, [_ | _], Body = [_ | _]}} = httpc:request(get, Request, [], []),
+
+ inets_test_lib:check_body(Body).
+
+%%--------------------------------------------------------------------
+get_space() ->
+ [{"Test http get request with '%20' in the path of the URL."}].
+get_space(Config) when is_list(Config) ->
+ Request = {url(group_name(Config), "/space%20.html", Config), []},
+ {ok, {{_,200,_}, [_ | _], Body = [_ | _]}} = httpc:request(get, Request, [], []),
+
+ inets_test_lib:check_body(Body).
+
%%--------------------------------------------------------------------
post() ->
[{"Test http post request against local server. We do in this case "
@@ -576,7 +722,26 @@ redirect_temporary_redirect(Config) when is_list(Config) ->
{ok, {{_,200,_}, [_ | _], [_|_]}}
= httpc:request(post, {URL307, [],"text/plain", "foobar"},
[], []).
+%%-------------------------------------------------------------------------
+redirect_relative_uri() ->
+ [{doc, "The server SHOULD generate a Location header field in the response "
+ "containing a preferred URI reference for the new permanent URI. The user "
+ "agent MAY use the Location field value for automatic redirection. The server's "
+ "response payload usually contains a short hypertext note with a "
+ "hyperlink to the new URI(s)."}].
+redirect_relative_uri(Config) when is_list(Config) ->
+
+ URL301 = url(group_name(Config), "/301_rel_uri.html", Config),
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL301, []}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], []}}
+ = httpc:request(head, {URL301, []}, [], []),
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(post, {URL301, [],"text/plain", "foobar"},
+ [], []).
%%-------------------------------------------------------------------------
redirect_loop() ->
[{"doc, Test redirect loop detection"}].
@@ -588,6 +753,48 @@ redirect_loop(Config) when is_list(Config) ->
= httpc:request(get, {URL, []}, [], []).
%%-------------------------------------------------------------------------
+redirect_http_to_https() ->
+ [{doc, "Test that a 30X redirect from one scheme to another is handled "
+ "correctly."}].
+redirect_http_to_https(Config) when is_list(Config) ->
+ URL301 = mixed_url(http, "/301_custom_url.html", Config),
+ TargetUrl = mixed_url(https, "/dummy.html", Config),
+ Headers = [{"x-test-301-url", TargetUrl}],
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL301, Headers}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], []}}
+ = httpc:request(head, {URL301, Headers}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(post, {URL301, Headers, "text/plain", "foobar"},
+ [], []).
+%%-------------------------------------------------------------------------
+redirect_relative_different_port() ->
+ [{doc, "Test that a 30X redirect with a relative target, but different "
+ "port, is handled correctly."}].
+redirect_relative_different_port(Config) when is_list(Config) ->
+ URL301 = mixed_url(http, "/301_custom_url.html", Config),
+
+ % We need an extra server of the same protocol here, so spawn a new
+ % HTTP-protocol one
+ Port = server_start(sim_http, []),
+ {ok, Host} = inet:gethostname(),
+ % Prefix the URI with '/' instead of a scheme
+ TargetUrl = "//" ++ Host ++ ":" ++ integer_to_list(Port) ++ "/dummy.html",
+ Headers = [{"x-test-301-url", TargetUrl}],
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL301, Headers}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], []}}
+ = httpc:request(head, {URL301, Headers}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(post, {URL301, Headers, "text/plain", "foobar"},
+ [], []).
+%%-------------------------------------------------------------------------
cookie() ->
[{doc, "Test cookies."}].
cookie(Config) when is_list(Config) ->
@@ -746,7 +953,7 @@ empty_body() ->
empty_body(Config) when is_list(Config) ->
URL = url(group_name(Config), "/empty.html", Config),
{ok, {{_,200,_}, [_ | _], []}} =
- httpc:request(get, {URL, []}, [{timeout, 500}], []).
+ httpc:request(get, {URL, []}, [], []).
%%-------------------------------------------------------------------------
@@ -978,7 +1185,6 @@ headers_dummy(Config) when is_list(Config) ->
{"If-Range", "Sat, 29 Oct 1994 19:43:31 GMT"},
{"If-Match", "*"},
{"Content-Type", "text/plain"},
- {"Content-Encoding", "chunked"},
{"Content-Length", "6"},
{"Content-Language", "en"},
{"Content-Location", "http://www.foobar.se"},
@@ -1004,6 +1210,18 @@ headers_with_obs_fold(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
+headers_conflict_chunked_with_length(doc) ->
+ ["Test the code for handling headers with both Transfer-Encoding"
+ "and Content-Length which must receive error in default (not relaxed) mode"
+ "and must receive successful response in relaxed mode"];
+headers_conflict_chunked_with_length(Config) when is_list(Config) ->
+ Request = {url(group_name(Config), "/headers_conflict_chunked_with_length.html", Config), []},
+ {error, {could_not_parse_as_http, _}} = httpc:request(get, Request, [{relaxed, false}], []),
+ {ok,{{_,200,_},_,_}} = httpc:request(get, Request, [{relaxed, true}], []),
+ ok.
+
+%%-------------------------------------------------------------------------
+
invalid_headers(Config) ->
Request = {url(group_name(Config), "/dummy.html", Config), [{"cookie", undefined}]},
{error, _} = httpc:request(get, Request, [], []).
@@ -1043,8 +1261,6 @@ remote_socket_close_async(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
process_leak_on_keepalive(Config) ->
- {ok, ClosedSocket} = gen_tcp:listen(6666, [{active, false}]),
- ok = gen_tcp:close(ClosedSocket),
Request = {url(group_name(Config), "/dummy.html", Config), []},
HttpcHandlers0 = supervisor:which_children(httpc_handler_sup),
{ok, {{_, 200, _}, _, Body}} = httpc:request(get, Request, [], []),
@@ -1056,11 +1272,10 @@ process_leak_on_keepalive(Config) ->
ordsets:to_list(
ordsets:subtract(ordsets:from_list(HttpcHandlers1),
ordsets:from_list(HttpcHandlers0))),
- sys:replace_state(
- Pid, fun (State) ->
- Session = element(3, State),
- setelement(3, State, Session#session{socket=ClosedSocket})
- end),
+ State = sys:get_state(Pid),
+ #session{socket=Socket} = element(3, State),
+ gen_tcp:close(Socket),
+
{ok, {{_, 200, _}, _, Body}} = httpc:request(get, Request, [], []),
%% bad handler with the closed socket should get replaced by
%% the new one, so children count should stay the same
@@ -1179,6 +1394,234 @@ wait_for_whole_response(Config) when is_list(Config) ->
ReqSeqNumServer ! shutdown.
%%--------------------------------------------------------------------
+post_204_chunked() ->
+ [{doc,"Test that chunked encoded 204 responses do not freeze the http client"}].
+post_204_chunked(_Config) ->
+ Msg = "HTTP/1.1 204 No Content\r\n" ++
+ "Date: Thu, 23 Aug 2018 13:36:29 GMT\r\n" ++
+ "Content-Type: text/html\r\n" ++
+ "Server: inets/6.5.2.3\r\n" ++
+ "Cache-Control: no-cache\r\n" ++
+ "Pragma: no-cache\r\n" ++
+ "Expires: Fri, 24 Aug 2018 07:49:35 GMT\r\n" ++
+ "Transfer-Encoding: chunked\r\n" ++
+ "\r\n",
+ Chunk = "0\r\n\r\n",
+
+ {ok, ListenSocket} = gen_tcp:listen(0, [{active,once}, binary]),
+ {ok,{_,Port}} = inet:sockname(ListenSocket),
+ spawn(fun () -> custom_server(Msg, Chunk, ListenSocket,
+ fun post_204_receive/0) end),
+
+ {ok,Host} = inet:gethostname(),
+ End = "/cgi-bin/erl/httpd_example:post_204",
+ URL = ?URL_START ++ Host ++ ":" ++ integer_to_list(Port) ++ End,
+ {ok, _} = httpc:request(post, {URL, [], "text/html", []}, [], []),
+ timer:sleep(500),
+ %% Second request times out in the faulty case.
+ {ok, _} = httpc:request(post, {URL, [], "text/html", []}, [], []).
+
+post_204_receive() ->
+ receive
+ {tcp, _, Msg} ->
+ ct:log("Message received: ~p", [Msg])
+ after
+ 1000 ->
+ ct:fail("Timeout: did not recive packet")
+ end.
+
+%% Custom server is used to test special cases when using chunked encoding
+custom_server(Msg, Chunk, ListenSocket, ReceiveFun) ->
+ {ok, Accept} = gen_tcp:accept(ListenSocket),
+ ReceiveFun(),
+ send_response(Msg, Chunk, Accept),
+ custom_server_loop(Msg, Chunk, Accept, ReceiveFun).
+
+custom_server_loop(Msg, Chunk, Accept, ReceiveFun) ->
+ ReceiveFun(),
+ send_response(Msg, Chunk, Accept),
+ custom_server_loop(Msg, Chunk, Accept, ReceiveFun).
+
+send_response(Msg, Chunk, Socket) ->
+ inet:setopts(Socket, [{active, once}]),
+ gen_tcp:send(Socket, Msg),
+ timer:sleep(250),
+ gen_tcp:send(Socket, Chunk).
+
+%%--------------------------------------------------------------------
+chunkify_fun() ->
+ [{doc,"Test that a chunked encoded request does not include the 'Content-Length header'"}].
+chunkify_fun(_Config) ->
+ Msg = "HTTP/1.1 204 No Content\r\n" ++
+ "Date: Thu, 23 Aug 2018 13:36:29 GMT\r\n" ++
+ "Content-Type: text/html\r\n" ++
+ "Server: inets/6.5.2.3\r\n" ++
+ "Cache-Control: no-cache\r\n" ++
+ "Pragma: no-cache\r\n" ++
+ "Expires: Fri, 24 Aug 2018 07:49:35 GMT\r\n" ++
+ "Transfer-Encoding: chunked\r\n" ++
+ "\r\n",
+ Chunk = "0\r\n\r\n",
+
+ {ok, ListenSocket} = gen_tcp:listen(0, [{active,once}, binary]),
+ {ok,{_,Port}} = inet:sockname(ListenSocket),
+ spawn(fun () -> custom_server(Msg, Chunk, ListenSocket,
+ fun chunkify_receive/0) end),
+
+ {ok,Host} = inet:gethostname(),
+ End = "/cgi-bin/erl/httpd_example",
+ URL = ?URL_START ++ Host ++ ":" ++ integer_to_list(Port) ++ End,
+ Fun = fun(_) -> {ok,<<1>>,eof_body} end,
+ Acc = start,
+
+ {ok, {{_,204,_}, _, _}} =
+ httpc:request(put, {URL, [], "text/html", {chunkify, Fun, Acc}}, [], []).
+
+chunkify_receive() ->
+ Error = "HTTP/1.1 500 Internal Server Error\r\n" ++
+ "Content-Length: 0\r\n\r\n",
+ receive
+ {tcp, Port, Msg} ->
+ case binary:match(Msg, <<"content-length">>) of
+ nomatch ->
+ ct:log("Message received: ~s", [binary_to_list(Msg)]);
+ {_, _} ->
+ ct:log("Message received (negative): ~s", [binary_to_list(Msg)]),
+ %% Signal a testcase failure when the received HTTP request
+ %% contains a 'Content-Length' header.
+ gen_tcp:send(Port, Error),
+ ct:fail("Content-Length present in received headers.")
+ end
+ after
+ 1000 ->
+ ct:fail("Timeout: did not recive packet")
+ end.
+%%--------------------------------------------------------------------
+stream_fun_server_close() ->
+ [{doc, "Test that an error msg is received when using a receiver fun as stream target"}].
+stream_fun_server_close(Config) when is_list(Config) ->
+ Request = {url(group_name(Config), "/delay_close.html", Config), []},
+ Self = self(),
+ Fun = fun(X) -> Self ! X end,
+ {ok, RequestId} = httpc:request(get, Request, [], [{sync, false}, {receiver, Fun}]),
+ receive
+ {RequestId, {error, Reason}} ->
+ ct:pal("Close ~p", [Reason]),
+ ok
+ after 13000 ->
+ ct:fail(did_not_receive_close)
+ end.
+
+%%--------------------------------------------------------------------
+server_closing_connection_on_first_response() ->
+ [{doc, "Client receives \"Connection: close\" on first response."
+ "A client that receives a \"close\" connection option MUST cease sending"
+ "requests on that connection and close the connection after reading"
+ "the response message containing the \"close\""}].
+server_closing_connection_on_first_response(Config) when is_list(Config) ->
+ ReqSrvSendOctFun =
+ fun(V, U, S) ->
+ {ok, {{V, S, _}, Headers0, []}} =
+ httpc:request(get, {U, []}, [{version, V}], []),
+ {_, SendOctStr} =
+ proplists:lookup("x-socket-stat-send-oct", Headers0),
+ list_to_integer(SendOctStr)
+ end,
+ V = "HTTP/1.1",
+ Url0 = url(group_name(Config), "/http_1_1_send_oct.html", Config),
+ Url1 = url(group_name(Config), "/http_1_1_send_oct_and_connection_close.html", Config),
+ %% Test case assumes at most one reusable past session.
+ _ = ReqSrvSendOctFun(V, Url1, 204),
+ 0 = ReqSrvSendOctFun(V, Url0, 204),
+ ok.
+
+%%--------------------------------------------------------------------
+server_closing_connection_on_second_response() ->
+ [{doc, "Client receives \"Connection: close\" on second response."
+ "A client that receives a \"close\" connection option MUST cease sending"
+ "requests on that connection and close the connection after reading"
+ "the response message containing the \"close\""}].
+server_closing_connection_on_second_response(Config) when is_list(Config) ->
+ ReqSrvSendOctFun =
+ fun(V, U, S) ->
+ {ok, {{V, S, _}, Headers0, []}} =
+ httpc:request(get, {U, []}, [{version, V}], []),
+ {_, SendOctStr} =
+ proplists:lookup("x-socket-stat-send-oct", Headers0),
+ list_to_integer(SendOctStr)
+ end,
+ V = "HTTP/1.1",
+ Url0 = url(group_name(Config), "/http_1_1_send_oct.html", Config),
+ Url1 = url(group_name(Config), "/http_1_1_send_oct_and_connection_close.html", Config),
+ %% Test case assumes no reusable past sessions.
+ SendOct0 = 0 = ReqSrvSendOctFun(V, Url0, 204),
+ case ReqSrvSendOctFun(V, Url1, 204) of SendOct1 when SendOct1 > SendOct0 -> ok end,
+ 0 = ReqSrvSendOctFun(V, Url0, 204),
+ ok.
+
+%%--------------------------------------------------------------------
+slow_connection() ->
+ [{doc, "Test that a request on a slow keep-alive connection won't crash the httpc_manager"}].
+slow_connection(Config) when is_list(Config) ->
+ BodyFun = fun(0) -> eof;
+ (LenLeft) -> timer:sleep(1000),
+ {ok, lists:duplicate(10, "1"), LenLeft - 10}
+ end,
+ Request = {url(group_name(Config), "/httpc_SUITE:esi_post", Config),
+ [{"content-length", "100"}],
+ "text/plain",
+ {BodyFun, 100}},
+ {ok, _} = httpc:request(post, Request, [], []),
+ %% Second request causes a crash if gen_server timeout is not set to infinity
+ %% in httpc_handler.
+ {ok, _} = httpc:request(post, Request, [], []).
+
+%%-------------------------------------------------------------------------
+unix_domain_socket() ->
+ [{"doc, Test HTTP requests over unix domain sockets"}].
+unix_domain_socket(Config) when is_list(Config) ->
+
+ URL = "http:///v1/kv/foo",
+
+ {ok,[{unix_socket,?UNIX_SOCKET}]} =
+ httpc:get_options([unix_socket]),
+ {ok, {{_,200,_}, [_ | _], _}}
+ = httpc:request(put, {URL, [], [], ""}, [], []),
+ {ok, {{_,200,_}, [_ | _], _}}
+ = httpc:request(get, {URL, []}, [], []).
+
+%%-------------------------------------------------------------------------
+delete_no_body(doc) ->
+ ["Test that a DELETE request without Body does not send a Content-Type header - Solves ERL-536"];
+delete_no_body(Config) when is_list(Config) ->
+ URL = url(group_name(Config), "/delete_no_body.html", Config),
+ %% Simulated server replies 500 if 'Content-Type' header is present
+ {ok, {{_,200,_}, _, _}} =
+ httpc:request(delete, {URL, []}, [], []),
+ {ok, {{_,500,_}, _, _}} =
+ httpc:request(delete, {URL, [], "text/plain", "TEST"}, [], []).
+
+%%--------------------------------------------------------------------
+post_with_content_type(doc) ->
+ ["Test that a POST request with explicit 'Content-Type' does not drop the 'Content-Type' header - Solves ERL-736"];
+post_with_content_type(Config) when is_list(Config) ->
+ URL = url(group_name(Config), "/delete_no_body.html", Config),
+ %% Simulated server replies 500 if 'Content-Type' header is present
+ {ok, {{_,500,_}, _, _}} =
+ httpc:request(post, {URL, [], "application/x-www-form-urlencoded", ""}, [], []).
+
+%%--------------------------------------------------------------------
+request_options() ->
+ [{doc, "Test http get request with socket options against local server (IPv6)"}].
+request_options(Config) when is_list(Config) ->
+ Request = {url(group_name(Config), "/dummy.html", Config), []},
+ {ok, {{_,200,_}, [_ | _], _ = [_ | _]}} = httpc:request(get, Request, [],
+ [{socket_opts,[{ipfamily, inet6}]}]),
+ {error,{failed_connect,_ }} = httpc:request(get, Request, [], []).
+
+
+
+%%--------------------------------------------------------------------
%% Internal Functions ------------------------------------------------
%%--------------------------------------------------------------------
stream(ReceiverPid, Receiver, Config) ->
@@ -1265,12 +1708,17 @@ url(http, End, Config) ->
Port = proplists:get_value(port, Config),
{ok,Host} = inet:gethostname(),
?URL_START ++ Host ++ ":" ++ integer_to_list(Port) ++ End;
+url(http_ipv6, End, Config) ->
+ Port = proplists:get_value(port, Config),
+ ?URL_START ++ "[::1]" ++ ":" ++ integer_to_list(Port) ++ End;
url(https, End, Config) ->
Port = proplists:get_value(port, Config),
{ok,Host} = inet:gethostname(),
?TLS_URL_START ++ Host ++ ":" ++ integer_to_list(Port) ++ End;
url(sim_http, End, Config) ->
url(http, End, Config);
+url(http_internal, End, Config) ->
+ url(http, End, Config);
url(sim_https, End, Config) ->
url(https, End, Config).
url(http, UserInfo, End, Config) ->
@@ -1284,25 +1732,56 @@ url(sim_http, UserInfo, End, Config) ->
url(sim_https, UserInfo, End, Config) ->
url(https, UserInfo, End, Config).
+% Only for use in the `mixed` test group, where both http and https
+% URLs are possible.
+mixed_url(http, End, Config) ->
+ mixed_url(http_port, End, Config);
+mixed_url(https, End, Config) ->
+ mixed_url(https_port, End, Config);
+mixed_url(PortType, End, Config) ->
+ Port = proplists:get_value(PortType, Config),
+ {ok, Host} = inet:gethostname(),
+ Start = case PortType of
+ http_port -> ?URL_START;
+ https_port -> ?TLS_URL_START
+ end,
+ Start ++ Host ++ ":" ++ integer_to_list(Port) ++ End.
+
group_name(Config) ->
GroupProp = proplists:get_value(tc_group_properties, Config),
proplists:get_value(name, GroupProp).
server_start(sim_http, _) ->
Inet = inet_version(),
- ok = httpc:set_options([{ipfamily, Inet}]),
- {_Pid, Port} = dummy_server(Inet),
+ ok = httpc:set_options([{ipfamily, Inet},{unix_socket, undefined}]),
+ {_Pid, Port} = http_test_lib:dummy_server(ip_comm, Inet, [{content_cb, ?MODULE}]),
Port;
server_start(sim_https, SslConfig) ->
Inet = inet_version(),
- ok = httpc:set_options([{ipfamily, Inet}]),
- {_Pid, Port} = dummy_server(ssl, Inet, SslConfig),
+ ok = httpc:set_options([{ipfamily, Inet},{unix_socket, undefined}]),
+ {_Pid, Port} = http_test_lib:dummy_server(ssl, Inet, [{ssl, SslConfig}, {content_cb, ?MODULE}]),
Port;
+server_start(http_unix_socket, Config) ->
+ Inet = local,
+ Socket = proplists:get_value(unix_socket, Config),
+ ok = httpc:set_options([{ipfamily, Inet},{unix_socket, Socket}]),
+ {_Pid, Port} = http_test_lib:dummy_server(unix_socket, Inet, [{content_cb, ?MODULE},
+ {unix_socket, Socket}]),
+ Port;
+server_start(http_ipv6, HttpdConfig) ->
+ {ok, Pid} = inets:start(httpd, HttpdConfig),
+ Serv = inets:services_info(),
+ {value, {_, _, Info}} = lists:keysearch(Pid, 2, Serv),
+ proplists:get_value(port, Info);
+server_start(sim_mixed, Config) ->
+ % For the mixed http/https case, we start two servers and return both ports.
+ {server_start(sim_http, []), server_start(sim_https, Config)};
server_start(_, HttpdConfig) ->
{ok, Pid} = inets:start(httpd, HttpdConfig),
Serv = inets:services_info(),
+ ok = httpc:set_options([{ipfamily, inet_version()},{unix_socket, undefined}]),
{value, {_, _, Info}} = lists:keysearch(Pid, 2, Serv),
proplists:get_value(port, Info).
@@ -1317,26 +1796,54 @@ server_config(http, Config) ->
{mime_type, "text/plain"},
{script_alias, {"/cgi-bin/", filename:join(ServerRoot, "cgi-bin") ++ "/"}}
];
-
+server_config(http_ipv6, Config) ->
+ ServerRoot = proplists:get_value(server_root, Config),
+ [{port, 0},
+ {server_name,"httpc_test"},
+ {server_root, ServerRoot},
+ {document_root, proplists:get_value(doc_root, Config)},
+ {bind_address, {0,0,0,0,0,0,0,1}},
+ {ipfamily, inet6},
+ {mime_type, "text/plain"},
+ {script_alias, {"/cgi-bin/", filename:join(ServerRoot, "cgi-bin") ++ "/"}}
+ ];
+server_config(http_internal, Config) ->
+ ServerRoot = proplists:get_value(server_root, Config),
+ [{port, 0},
+ {server_name,"httpc_test"},
+ {server_root, ServerRoot},
+ {document_root, proplists:get_value(doc_root, Config)},
+ {bind_address, any},
+ {ipfamily, inet_version()},
+ {mime_type, "text/plain"},
+ {erl_script_alias, {"", [httpc_SUITE]}}
+ ];
server_config(https, Config) ->
[{socket_type, {essl, ssl_config(Config)}} | server_config(http, Config)];
server_config(sim_https, Config) ->
ssl_config(Config);
+server_config(http_unix_socket, _Config) ->
+ Socket = ?UNIX_SOCKET,
+ [{unix_socket, Socket}];
+
server_config(_, _) ->
[].
+esi_post(Sid, _Env, _Input) ->
+ mod_esi:deliver(Sid, ["OK"]).
+
start_apps(https) ->
inets_test_lib:start_apps([crypto, public_key, ssl]);
start_apps(sim_https) ->
inets_test_lib:start_apps([crypto, public_key, ssl]);
+start_apps(sim_mixed) ->
+ inets_test_lib:start_apps([crypto, public_key, ssl]);
start_apps(_) ->
ok.
ssl_config(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- [{certfile, filename:join(DataDir, "ssl_server_cert.pem")},
- {verify, verify_none}
- ].
+ SSLConf = proplists:get_value(ssl_conf, Config),
+ proplists:get_value(server_config, SSLConf).
setup_server_dirs(ServerRoot, DocRoot, DataDir) ->
CgiDir = filename:join(ServerRoot, "cgi-bin"),
@@ -1401,13 +1908,7 @@ receive_replys([ID|IDs]) ->
ct:pal({recived_canceld_id, Other})
end.
-%% Perform a synchronous stop
-dummy_server_stop(Pid) ->
- Pid ! {stop, self()},
- receive
- {stopped, Pid} ->
- ok
- end.
+
inet_version() ->
inet. %% Just run inet for now
@@ -1535,7 +2036,7 @@ dummy_request_handler_loop({Module, Function, Args}, SockType, Socket) ->
handle_request(Module, Function, Args, Socket) ->
case Module:Function(Args) of
{ok, Result} ->
- case handle_http_msg(Result, Socket) of
+ case handle_http_msg(Result, Socket, []) of
stop ->
stop;
<<>> ->
@@ -1560,8 +2061,7 @@ handle_request(Module, Function, Args, Socket) ->
NewMFA
end.
-handle_http_msg({Method, RelUri, _, {_, Headers}, Body}, Socket) ->
-
+handle_http_msg({Method, RelUri, _, {_, Headers}, Body}, Socket, _) ->
ct:print("Request: ~p ~p", [Method, RelUri]),
NextRequest =
@@ -1661,6 +2161,13 @@ auth_header([{"authorization", Value} | _]) ->
auth_header([_ | Tail]) ->
auth_header(Tail).
+content_type_header([]) ->
+ not_found;
+content_type_header([{"content-type", Value}|_]) ->
+ {ok, string:strip(Value)};
+content_type_header([_|T]) ->
+ content_type_header(T).
+
handle_auth("Basic " ++ UserInfo, Challange, DefaultResponse) ->
case string:tokens(base64:decode_to_string(UserInfo), ":") of
["alladin", "sesame"] = Auth ->
@@ -1685,6 +2192,15 @@ content_length(["content-length:" ++ Value | _]) ->
content_length([_Head | Tail]) ->
content_length(Tail).
+handle_uri("GET","/dummy.html?foo=bar",_,_,_,_) ->
+ "HTTP/1.0 200 OK\r\n\r\nTEST";
+
+handle_uri("GET","/space%20.html",_,_,_,_) ->
+ Body = "<HTML><BODY>foobar</BODY></HTML>",
+ "HTTP/1.1 200 OK\r\n" ++
+ "Content-Length:" ++ integer_to_list(length(Body)) ++ "\r\n\r\n" ++
+ Body;
+
handle_uri(_,"/just_close.html",_,_,_,_) ->
close;
handle_uri(_,"/no_content.html",_,_,_,_) ->
@@ -1750,6 +2266,37 @@ handle_uri(_,"/301.html",Port,_,Socket,_) ->
"Content-Length:" ++ integer_to_list(length(Body))
++ "\r\n\r\n" ++ Body;
+
+handle_uri("HEAD","/301_rel_uri.html",_,_,_,_) ->
+ NewUri = "/dummy.html",
+ "HTTP/1.1 301 Moved Permanently\r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:0\r\n\r\n";
+
+handle_uri(_,"/301_rel_uri.html",_,_,_,_) ->
+ NewUri = "/dummy.html",
+ Body = "<HTML><BODY><a href=" ++ NewUri ++
+ ">New place</a></BODY></HTML>",
+ "HTTP/1.1 301 Moved Permanently\r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:" ++ integer_to_list(length(Body))
+ ++ "\r\n\r\n" ++ Body;
+
+handle_uri("HEAD","/301_custom_url.html",_,Headers,_,_) ->
+ NewUri = proplists:get_value("x-test-301-url", Headers),
+ "HTTP/1.1 301 Moved Permanently\r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:0\r\n\r\n";
+
+handle_uri(_,"/301_custom_url.html",_,Headers,_,_) ->
+ NewUri = proplists:get_value("x-test-301-url", Headers),
+ Body = "<HTML><BODY><a href=" ++ NewUri ++
+ ">New place</a></BODY></HTML>",
+ "HTTP/1.1 301 Moved Permanently\r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:" ++ integer_to_list(length(Body))
+ ++ "\r\n\r\n" ++ Body;
+
handle_uri("HEAD","/302.html",Port,_,Socket,_) ->
NewUri = url_start(Socket) ++
integer_to_list(Port) ++ "/dummy.html",
@@ -1853,7 +2400,6 @@ handle_uri(_,"/dummy_headers.html",_,_,Socket,_) ->
%% user to evaluate. This is not a valid response
%% it only tests that the header handling code works.
Head = "HTTP/1.1 200 ok\r\n" ++
- "Content-Length:32\r\n" ++
"Pragma:1#no-cache\r\n" ++
"Via:1.0 fred, 1.1 nowhere.com (Apache/1.1)\r\n" ++
"Warning:1#pseudonym foobar\r\n" ++
@@ -1883,6 +2429,15 @@ handle_uri(_,"/obs_folded_headers.html",_,_,_,_) ->
" b\r\n\r\n"
"Hello";
+handle_uri(_,"/headers_conflict_chunked_with_length.html",_,_,Socket,_) ->
+ Head = "HTTP/1.1 200 ok\r\n"
+ "Content-Length:32\r\n"
+ "Transfer-Encoding:Chunked\r\n\r\n",
+ send(Socket, Head),
+ send(Socket, http_chunk:encode("<HTML><BODY>fo")),
+ send(Socket, http_chunk:encode("obar</BODY></HTML>")),
+ http_chunk:encode_last();
+
handle_uri(_,"/capital_transfer_encoding.html",_,_,Socket,_) ->
Head = "HTTP/1.1 200 ok\r\n" ++
"Transfer-Encoding:Chunked\r\n\r\n",
@@ -2030,12 +2585,58 @@ handle_uri(_,"/multipart_chunks.html",_,_,Socket,_) ->
send(Socket, Head),
send_multipart_chunks(Socket),
http_chunk:encode_last();
+handle_uri(_,"/delay_close.html",_,_,Socket,_) ->
+ ct:sleep(10000),
+ close(Socket);
handle_uri("HEAD",_,_,_,_,_) ->
"HTTP/1.1 200 ok\r\n" ++
"Content-Length:0\r\n\r\n";
+handle_uri("PUT","/v1/kv/foo",_,_,_,_) ->
+ "HTTP/1.1 200 OK\r\n" ++
+ "Date: Tue, 20 Feb 2018 14:39:08 GMT\r\n" ++
+ "Content-Length: 5\r\n\r\n" ++
+ "Content-Type: application/json\r\n\r\n" ++
+ "true\n";
+handle_uri("GET","/v1/kv/foo",_,_,_,_) ->
+ "HTTP/1.1 200 OK\r\n" ++
+ "Date: Tue, 20 Feb 2018 14:39:08 GMT\r\n" ++
+ "Content-Length: 24\r\n" ++
+ "Content-Type: application/json\r\n\r\n" ++
+ "[{\"Value\": \"aGVsbG8=\"}]\n";
+handle_uri(_,"/http_1_1_send_oct.html",_,_,Socket,_) ->
+ "HTTP/1.1 204 No Content\r\n" ++
+ "X-Socket-Stat-Send-Oct: " ++ integer_to_list(get_stat(Socket, send_oct)) ++ "\r\n" ++
+ "\r\n";
+handle_uri(_,"/http_1_1_send_oct_and_connection_close.html",_,_,Socket,_) ->
+ "HTTP/1.1 204 No Content\r\n" ++
+ "X-Socket-Stat-Send-Oct: " ++ integer_to_list(get_stat(Socket, send_oct)) ++ "\r\n" ++
+ "Connection: close\r\n" ++
+ "\r\n";
+handle_uri(_,"/delete_no_body.html", _,Headers,_, DefaultResponse) ->
+ Error = "HTTP/1.1 500 Internal Server Error\r\n" ++
+ "Content-Length:0\r\n\r\n",
+ case content_type_header(Headers) of
+ {ok, _} ->
+ Error;
+ not_found ->
+ DefaultResponse
+ end;
handle_uri(_,_,_,_,_,DefaultResponse) ->
DefaultResponse.
+get_stat(S, Opt) ->
+ case getstat(S, [Opt]) of
+ {ok, [{Opt, V}]} when is_integer(V) ->
+ V;
+ {error, _} = E ->
+ E
+ end.
+
+getstat(#sslsocket{} = S, Opts) ->
+ ssl:getstat(S, Opts);
+getstat(S, Opts) ->
+ inet:getstat(S, Opts).
+
url_start(#sslsocket{}) ->
{ok,Host} = inet:gethostname(),
?TLS_URL_START ++ Host ++ ":";
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index 055b847319..5b6740fba3 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -73,6 +73,11 @@ all() ->
{group, http_reload},
{group, https_reload},
{group, http_mime_types},
+ {group, http_logging},
+ {group, http_post},
+ {group, http_rel_path_script_alias},
+ {group, http_not_sup},
+ {group, https_not_sup},
mime_types_format
].
@@ -96,8 +101,12 @@ groups() ->
{https_htaccess, [], [{group, htaccess}]},
{http_security, [], [{group, security}]},
{https_security, [], [{group, security}]},
+ {http_logging, [], [{group, logging}]},
{http_reload, [], [{group, reload}]},
{https_reload, [], [{group, reload}]},
+ {http_post, [], [{group, post}]},
+ {http_not_sup, [], [{group, not_sup}]},
+ {https_not_sup, [], [{group, not_sup}]},
{http_mime_types, [], [alias_1_1, alias_1_0, alias_0_9]},
{limit, [], [max_clients_1_1, max_clients_1_0, max_clients_0_9]},
{custom, [], [customize, add_default]},
@@ -108,8 +117,10 @@ groups() ->
non_disturbing_0_9,
disturbing_1_1,
disturbing_1_0,
- disturbing_0_9
+ disturbing_0_9,
+ reload_config_file
]},
+ {post, [], [chunked_post, chunked_chunked_encoded_post, post_204]},
{basic_auth, [], [basic_auth_1_1, basic_auth_1_0, basic_auth_0_9]},
{auth_api, [], [auth_api_1_1, auth_api_1_0, auth_api_0_9
]},
@@ -119,12 +130,16 @@ groups() ->
]},
{htaccess, [], [htaccess_1_1, htaccess_1_0, htaccess_0_9]},
{security, [], [security_1_1, security_1_0]}, %% Skip 0.9 as causes timing issus in test code
+ {logging, [], [disk_log_internal, disk_log_exists,
+ disk_log_bad_size, disk_log_bad_file]},
{http_1_1, [],
[host, chunked, expect, cgi, cgi_chunked_encoding_test,
trace, range, if_modified_since, mod_esi_chunk_timeout,
- esi_put] ++ http_head() ++ http_get() ++ load()},
+ esi_put, esi_post] ++ http_head() ++ http_get() ++ load()},
{http_1_0, [], [host, cgi, trace] ++ http_head() ++ http_get() ++ load()},
- {http_0_9, [], http_head() ++ http_get() ++ load()}
+ {http_0_9, [], http_head() ++ http_get() ++ load()},
+ {http_rel_path_script_alias, [], [cgi]},
+ {not_sup, [], [put_not_sup]}
].
basic_groups ()->
@@ -148,6 +163,7 @@ http_get() ->
ipv6
].
+
load() ->
[light, medium
%%,heavy
@@ -160,6 +176,7 @@ init_per_suite(Config) ->
ServerRoot = filename:join(PrivDir, "server_root"),
inets_test_lib:del_dirs(ServerRoot),
DocRoot = filename:join(ServerRoot, "htdocs"),
+ setup_tmp_dir(PrivDir),
setup_server_dirs(ServerRoot, DocRoot, DataDir),
{ok, Hostname0} = inet:gethostname(),
Inet =
@@ -195,7 +212,8 @@ init_per_group(Group, Config0) when Group == https_basic;
Group == https_auth_api_dets;
Group == https_auth_api_mnesia;
Group == https_security;
- Group == https_reload
+ Group == https_reload;
+ Group == https_not_sup
->
catch crypto:stop(),
try crypto:start() of
@@ -214,6 +232,8 @@ init_per_group(Group, Config0) when Group == http_basic;
Group == http_auth_api_mnesia;
Group == http_security;
Group == http_reload;
+ Group == http_not_sup;
+ Group == http_post;
Group == http_mime_types
->
ok = start_apps(Group),
@@ -254,6 +274,16 @@ init_per_group(auth_api_dets, Config) ->
init_per_group(auth_api_mnesia, Config) ->
start_mnesia(proplists:get_value(node, Config)),
[{auth_prefix, "mnesia_"} | Config];
+init_per_group(http_logging, Config) ->
+ Config1 = [{http_version, "HTTP/1.1"} | Config],
+ ServerRoot = proplists:get_value(server_root, Config1),
+ Path = ServerRoot ++ "/httpd_log_transfer",
+ [{transfer_log, Path} | Config1];
+init_per_group(http_rel_path_script_alias = Group, Config) ->
+ ok = start_apps(Group),
+ init_httpd(Group, [{type, ip_comm},{http_version, "HTTP/1.1"}| Config]);
+init_per_group(not_sup, Config) ->
+ [{http_version, "HTTP/1.1"} | Config];
init_per_group(_, Config) ->
Config.
@@ -266,6 +296,7 @@ end_per_group(Group, _Config) when Group == http_basic;
Group == http_htaccess;
Group == http_security;
Group == http_reload;
+ Group == http_post;
Group == http_mime_types
->
inets:stop();
@@ -290,7 +321,7 @@ end_per_group(_, _) ->
%%--------------------------------------------------------------------
init_per_testcase(Case, Config) when Case == host; Case == trace ->
- ct:timetrap({seconds, 20}),
+ ct:timetrap({seconds, 40}),
Prop = proplists:get_value(tc_group_properties, Config),
Name = proplists:get_value(name, Prop),
Cb = case Name of
@@ -310,10 +341,60 @@ init_per_testcase(range, Config) ->
create_range_data(DocRoot),
dbg(range, Config, init);
+init_per_testcase(disk_log_internal, Config0) ->
+ ok = start_apps(http_logging),
+ Config1 = init_httpd(http_logging, [{type, ip_comm} | Config0]),
+ ct:timetrap({seconds, 20}),
+ dbg(disk_log_internal, Config1, init);
+
+init_per_testcase(disk_log_exists, Config0) ->
+ ServerRoot = proplists:get_value(server_root, Config0),
+ Filename = ServerRoot ++ "/httpd_log_transfer",
+ {ok, Log} = disk_log:open([{name, Filename}, {file, Filename},
+ {repair, truncate}, {format, internal},
+ {type, wrap}, {size, {1048576, 5}}]),
+ ok = disk_log:log(Log, {bogus, node(), self()}),
+ ok = disk_log:close(Log),
+ ok = start_apps(http_logging),
+ Config1 = init_httpd(http_logging, [{type, ip_comm} | Config0]),
+ ct:timetrap({seconds, 20}),
+ dbg(disk_log_internal, Config1, init);
+
+init_per_testcase(disk_log_bad_size, Config0) ->
+ ServerRoot = proplists:get_value(server_root, Config0),
+ Filename = ServerRoot ++ "/httpd_log_transfer",
+ {ok, Log} = disk_log:open([{name, Filename}, {file, Filename},
+ {repair, truncate}, {format, internal},
+ {type, wrap}, {size, {1048576, 5}}]),
+ ok = disk_log:log(Log, {bogus, node(), self()}),
+ ok = disk_log:close(Log),
+ ok = file:delete(Filename ++ ".siz"),
+ ok = start_apps(http_logging),
+ Config1 = init_httpd(http_logging, [{type, ip_comm} | Config0]),
+ ct:timetrap({seconds, 20}),
+ dbg(disk_log_internal, Config1, init);
+
+init_per_testcase(disk_log_bad_file, Config0) ->
+ ServerRoot = proplists:get_value(server_root, Config0),
+ Filename = ServerRoot ++ "/httpd_log_transfer",
+ ok = file:write_file(Filename ++ ".1", <<>>),
+ ok = start_apps(http_logging),
+ Config1 = init_httpd(http_logging, [{type, ip_comm} | Config0]),
+ ct:timetrap({seconds, 20}),
+ dbg(disk_log_internal, Config1, init);
+
init_per_testcase(Case, Config) ->
ct:timetrap({seconds, 20}),
dbg(Case, Config, init).
+end_per_testcase(Case, Config) when
+ Case == disk_log_internal;
+ Case == disk_log_exists;
+ Case == disk_log_bad_size;
+ Case == disk_log_bad_file ->
+ inets:stop(),
+ dbg(Case, Config, 'end');
+
end_per_testcase(Case, Config) ->
dbg(Case, Config, 'end').
@@ -376,8 +457,19 @@ get(Config) when is_list(Config) ->
{header, "Content-Type", "text/html"},
{header, "Date"},
{header, "Server"},
+ {version, Version}]),
+
+ ok = httpd_test_lib:verify_request(proplists:get_value(type, Config), Host,
+ proplists:get_value(port, Config),
+ transport_opts(Type, Config),
+ proplists:get_value(node, Config),
+ http_request("GET /open/ ", Version, Host),
+ [{statuscode, 403},
+ {header, "Content-Type", "text/html"},
+ {header, "Date"},
+ {header, "Server"},
{version, Version}]).
-
+
basic_auth_1_1(Config) when is_list(Config) ->
basic_auth([{http_version, "HTTP/1.1"} | Config]).
@@ -618,6 +710,87 @@ ipv6(Config) when is_list(Config) ->
end.
%%-------------------------------------------------------------------------
+chunked_post() ->
+ [{doc,"Test option max_client_body_chunk"}].
+chunked_post(Config) when is_list(Config) ->
+ ok = http_status("POST /cgi-bin/erl/httpd_example:post_chunked ",
+ {"Content-Length:833 \r\n",
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"},
+ [{http_version, "HTTP/1.1"} |Config],
+ [{statuscode, 200}]),
+ ok = http_status("POST /cgi-bin/erl/httpd_example:post_chunked ",
+ {"Content-Length:2 \r\n",
+ "ZZ"
+ },
+ [{http_version, "HTTP/1.1"} |Config],
+ [{statuscode, 200}]).
+
+chunked_chunked_encoded_post() ->
+ [{doc,"Test option max_client_body_chunk with chunked client encoding"}].
+chunked_chunked_encoded_post(Config) when is_list(Config) ->
+ Chunk = http_chunk:encode("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"),
+ LastChunk = http_chunk:encode_last(),
+ Chunks = lists:duplicate(10000, Chunk),
+ ok = http_status("POST /cgi-bin/erl/httpd_example:post_chunked ",
+ {"Transfer-Encoding:chunked \r\n",
+ [Chunks | LastChunk]},
+ [{http_version, "HTTP/1.1"} | Config],
+ [{statuscode, 200}]).
+
+%%-------------------------------------------------------------------------
+post_204() ->
+ [{doc,"Test that 204 responses are not chunk encoded"}].
+post_204(Config) ->
+ Host = proplists:get_value(host, Config),
+ Port = proplists:get_value(port, Config),
+ SockType = proplists:get_value(type, Config),
+ TranspOpts = transport_opts(SockType, Config),
+ Request = "POST /cgi-bin/erl/httpd_example:post_204 ",
+
+ try inets_test_lib:connect_bin(SockType, Host, Port, TranspOpts) of
+ {ok, Socket} ->
+ RequestStr = http_request(Request, "HTTP/1.1", Host),
+ ok = inets_test_lib:send(SockType, Socket, RequestStr),
+ receive
+ {tcp, Socket, Data} ->
+ case binary:match(Data, <<"chunked">>,[]) of
+ nomatch ->
+ ok;
+ {_, _} ->
+ ct:fail("Chunked encoding detected.")
+ end
+ after 2000 ->
+ ct:fail(connection_timed_out)
+ end;
+ ConnectError ->
+ ct:fail({connect_error, ConnectError,
+ [SockType, Host, Port, TranspOpts]})
+ catch
+ T:E ->
+ ct:fail({connect_failure,
+ [{type, T},
+ {error, E},
+ {stacktrace, erlang:get_stacktrace()},
+ {args, [SockType, Host, Port, TranspOpts]}]})
+ end.
+
+%%-------------------------------------------------------------------------
htaccess_1_1(Config) when is_list(Config) ->
htaccess([{http_version, "HTTP/1.1"} | Config]).
@@ -781,6 +954,33 @@ max_clients_0_9() ->
max_clients_0_9(Config) when is_list(Config) ->
do_max_clients([{http_version, "HTTP/0.9"} | Config]).
+
+
+%%-------------------------------------------------------------------------
+put_not_sup() ->
+ [{doc, "Test unhandled request"}].
+
+put_not_sup(Config) when is_list(Config) ->
+ ok = http_status("PUT /index.html ",
+ {"Content-Length:100 \r\n",
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"},
+ Config, [{statuscode, 501}]).
%%-------------------------------------------------------------------------
esi() ->
[{doc, "Test mod_esi"}].
@@ -813,8 +1013,11 @@ esi(Config) when is_list(Config) ->
{no_header, "cache-control"}]),
ok = http_status("GET /cgi-bin/erl/httpd_example:peer ",
Config, [{statuscode, 200},
- {header, "peer-cert-exist", peer(Config)}]).
-
+ {header, "peer-cert-exist", peer(Config)}]),
+ ok = http_status("GET /cgi-bin/erl/httpd_example:new_status_and_location ",
+ Config, [{statuscode, 201},
+ {header, "location"}]).
+
%%-------------------------------------------------------------------------
esi_put() ->
[{doc, "Test mod_esi PUT"}].
@@ -822,7 +1025,20 @@ esi_put() ->
esi_put(Config) when is_list(Config) ->
ok = http_status("PUT /cgi-bin/erl/httpd_example/put/123342234123 ",
Config, [{statuscode, 200}]).
-
+%%-------------------------------------------------------------------------
+esi_post() ->
+ [{doc, "Test mod_esi POST"}].
+
+esi_post(Config) when is_list(Config) ->
+ Chunk = "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ",
+ Data = lists:duplicate(10000, Chunk),
+ Length = lists:flatlength(Data),
+ ok = http_status("POST /cgi-bin/erl/httpd_example/post ",
+ {"Content-Length:" ++ integer_to_list(Length) ++ "\r\n",
+ Data},
+ [{http_version, "HTTP/1.1"} |Config],
+ [{statuscode, 200}]).
+
%%-------------------------------------------------------------------------
mod_esi_chunk_timeout(Config) when is_list(Config) ->
ok = httpd_1_1:mod_esi_chunk_timeout(proplists:get_value(type, Config),
@@ -1257,6 +1473,63 @@ security(Config) ->
true = unblock_user(Node, "two", Port, OpenDir).
%%-------------------------------------------------------------------------
+
+disk_log_internal() ->
+ ["Test mod_disk_log"].
+
+disk_log_internal(Config) ->
+ Version = proplists:get_value(http_version, Config),
+ Request = "GET /" ++ integer_to_list(rand:uniform(1000000)) ++ " ",
+ ok = http_status(Request, Config, [{statuscode, 404}]),
+ Log = proplists:get_value(transfer_log, Config),
+ Match = list_to_binary(Request ++ Version),
+ disk_log_internal1(Log, Match, disk_log:chunk(Log, start)).
+disk_log_internal1(_, _, eof) ->
+ ct:fail(eof);
+disk_log_internal1(Log, Match, {Cont, [H | T]}) ->
+ case binary:match(H, Match) of
+ nomatch ->
+ disk_log_internal1(Log, Match, {Cont, T});
+ _ ->
+ ok
+ end;
+disk_log_internal1(Log, Match, {Cont, []}) ->
+ disk_log_internal1(Log, Match, disk_log:chunk(Log, Cont)).
+
+disk_log_exists() ->
+ ["Test mod_disk_log with existing logs"].
+
+disk_log_exists(Config) ->
+ Log = proplists:get_value(transfer_log, Config),
+ Self = self(),
+ Node = node(),
+ Log = proplists:get_value(transfer_log, Config),
+ {_, [{bogus, Node, Self} | _]} = disk_log:chunk(Log, start).
+
+disk_log_bad_size() ->
+ ["Test mod_disk_log with existing log, missing .siz"].
+
+disk_log_bad_size(Config) ->
+ Log = proplists:get_value(transfer_log, Config),
+ Self = self(),
+ Node = node(),
+ Log = proplists:get_value(transfer_log, Config),
+ {_, [{bogus, Node, Self} | _]} = disk_log:chunk(Log, start).
+
+disk_log_bad_file() ->
+ ["Test mod_disk_log with bad file"].
+
+disk_log_bad_file(Config) ->
+ Log = proplists:get_value(transfer_log, Config),
+ Version = proplists:get_value(http_version, Config),
+ Request = "GET /" ++ integer_to_list(rand:uniform(1000000)) ++ " ",
+ ok = http_status(Request, Config, [{statuscode, 404}]),
+ Log = proplists:get_value(transfer_log, Config),
+ Match = list_to_binary(Request ++ Version),
+ {_, [H | _]} = disk_log:chunk(Log, start),
+ {_, _} = binary:match(H, Match).
+
+%%-------------------------------------------------------------------------
non_disturbing_reconfiger_dies(Config) when is_list(Config) ->
do_reconfiger_dies([{http_version, "HTTP/1.1"} | Config], non_disturbing).
disturbing_reconfiger_dies(Config) when is_list(Config) ->
@@ -1353,6 +1626,45 @@ non_disturbing(Config) when is_list(Config)->
end,
inets_test_lib:close(Type, Socket),
[{server_name, "httpd_non_disturbing_" ++ Version}] = httpd:info(Server, [server_name]).
+%%-------------------------------------------------------------------------
+reload_config_file(Config) when is_list(Config) ->
+ ServerRoot = proplists:get_value(server_root, Config),
+ HttpdConf = filename:join(get_tmp_dir(Config), "inets_httpd_server.conf"),
+ ServerConfig =
+ "[\n" ++
+ "{bind_address, \"localhost\"}," ++
+ "{port,0}," ++
+ "{server_name,\"httpd_test\"}," ++
+ "{server_root,\"" ++ ServerRoot ++ "\"}," ++
+ "{document_root,\"" ++ proplists:get_value(doc_root, Config) ++ "\"}" ++
+ "].",
+ ok = file:write_file(HttpdConf, ServerConfig),
+ {ok, Server} = inets:start(httpd, [{proplist_file, HttpdConf}]),
+ Port = proplists:get_value(port, httpd:info(Server)),
+ NewConfig =
+ "[\n" ++
+ "{bind_address, \"localhost\"}," ++
+ "{port," ++ integer_to_list(Port) ++ "}," ++
+ "{server_name,\"httpd_test_new\"}," ++
+ "{server_root,\"" ++ ServerRoot ++ "\"}," ++
+ "{document_root,\"" ++ proplists:get_value(doc_root, Config) ++ "\"}" ++
+ "].",
+ NewConfigApache =
+ "BindAddress localhost\n" ++
+ "Port " ++ integer_to_list(Port) ++ "\n" ++
+ "ServerName httpd_test_new_apache\n" ++
+ "ServerRoot " ++ ServerRoot ++ "\n" ++
+ "DocumentRoot " ++ proplists:get_value(doc_root, Config) ++ "\n",
+
+ %% Test Erlang term format
+ ok = file:write_file(HttpdConf, NewConfig),
+ ok = httpd:reload_config(HttpdConf, non_disturbing),
+ "httpd_test_new" = proplists:get_value(server_name, httpd:info(Server)),
+
+ %% Test Apache format
+ ok = file:write_file(HttpdConf, NewConfigApache),
+ ok = httpd:reload_config(HttpdConf, non_disturbing),
+ "httpd_test_new_apache" = proplists:get_value(server_name, httpd:info(Server)).
%%-------------------------------------------------------------------------
mime_types_format(Config) when is_list(Config) ->
@@ -1464,6 +1776,7 @@ mime_types_format(Config) when is_list(Config) ->
{"cpt","application/mac-compactpro"},
{"hqx","application/mac-binhex40"}]} = httpd_conf:load_mime_types(MimeTypes).
+
%%--------------------------------------------------------------------
%% Internal functions -----------------------------------
%%--------------------------------------------------------------------
@@ -1545,7 +1858,15 @@ setup_server_dirs(ServerRoot, DocRoot, DataDir) ->
{ok, FileInfo1} = file:read_file_info(EnvCGI),
ok = file:write_file_info(EnvCGI,
FileInfo1#file_info{mode = 8#00755}).
-
+
+setup_tmp_dir(PrivDir) ->
+ TmpDir = filename:join(PrivDir, "tmp"),
+ ok = file:make_dir(TmpDir).
+
+get_tmp_dir(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ filename:join(PrivDir, "tmp").
+
start_apps(Group) when Group == https_basic;
Group == https_limit;
Group == https_custom;
@@ -1555,7 +1876,8 @@ start_apps(Group) when Group == https_basic;
Group == https_auth_api_mnesia;
Group == https_htaccess;
Group == https_security;
- Group == https_reload
+ Group == https_reload;
+ Group == https_not_sup
->
inets_test_lib:start_apps([inets, asn1, crypto, public_key, ssl]);
start_apps(Group) when Group == http_basic;
@@ -1567,7 +1889,12 @@ start_apps(Group) when Group == http_basic;
Group == http_auth_api_mnesia;
Group == http_htaccess;
Group == http_security;
+ Group == http_logging;
Group == http_reload;
+ Group == http_post;
+ Group == http_mime_types;
+ Group == http_rel_path_script_alias;
+ Group == http_not_sup;
Group == http_mime_types->
inets_test_lib:start_apps([inets]).
@@ -1578,32 +1905,23 @@ server_start(_, HttpdConfig) ->
{Pid, proplists:get_value(port, Info)}.
init_ssl(Group, Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- CaKey = {_Trusted,_} =
- erl_make_certs:make_cert([{key, dsa},
- {subject,
- [{name, "Public Key"},
- {?'id-at-name',
- {printableString, "public_key"}},
- {?'id-at-pseudonym',
- {printableString, "pubkey"}},
- {city, "Stockholm"},
- {country, "SE"},
- {org, "erlang"},
- {org_unit, "testing dep"}
- ]}
- ]),
- ok = erl_make_certs:write_pem(PrivDir, "public_key_cacert", CaKey),
-
- CertK1 = {_Cert1, _} = erl_make_certs:make_cert([{issuer, CaKey}]),
- CertK2 = {_Cert2,_} = erl_make_certs:make_cert([{issuer, CertK1},
- {digest, md5},
- {extensions, false}]),
- ok = erl_make_certs:write_pem(PrivDir, "public_key_cert", CertK2),
-
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "client"]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "server"]),
+ GenCertData =
+ public_key:pkix_test_data(#{server_chain =>
+ #{root => [{key, inets_test_lib:hardcode_rsa_key(1)}],
+ intermediates => [[{key, inets_test_lib:hardcode_rsa_key(2)}]],
+ peer => [{key, inets_test_lib:hardcode_rsa_key(3)}
+ ]},
+ client_chain =>
+ #{root => [{key, inets_test_lib:hardcode_rsa_key(4)}],
+ intermediates => [[{key, inets_test_lib:hardcode_rsa_key(5)}]],
+ peer => [{key, inets_test_lib:hardcode_rsa_key(6)}]}}),
+
+ Conf = inets_test_lib:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
case start_apps(Group) of
ok ->
- init_httpd(Group, [{type, ssl} | Config]);
+ init_httpd(Group, [{type, ssl}, {ssl_conf, Conf} | Config]);
_ ->
{skip, "Could not start https apps"}
end.
@@ -1612,8 +1930,14 @@ server_config(http_basic, Config) ->
basic_conf() ++ server_config(http, Config);
server_config(https_basic, Config) ->
basic_conf() ++ server_config(https, Config);
+server_config(http_not_sup, Config) ->
+ not_sup_conf() ++ server_config(http, Config);
+server_config(https_not_sup, Config) ->
+ not_sup_conf() ++ server_config(https, Config);
server_config(http_reload, Config) ->
[{keep_alive_timeout, 2}] ++ server_config(http, Config);
+server_config(http_post, Config) ->
+ [{max_client_body_chunk, 10}] ++ server_config(http, Config);
server_config(https_reload, Config) ->
[{keep_alive_timeout, 2}] ++ server_config(https, Config);
server_config(http_limit, Config) ->
@@ -1662,6 +1986,8 @@ server_config(http_security, Config) ->
server_config(https_security, Config) ->
ServerRoot = proplists:get_value(server_root, Config),
tl(auth_conf(ServerRoot)) ++ security_conf(ServerRoot) ++ server_config(https, Config);
+server_config(http_logging, Config) ->
+ log_conf() ++ server_config(http, Config);
server_config(http_mime_types, Config0) ->
Config1 = basic_conf() ++ server_config(http, Config0),
ServerRoot = proplists:get_value(server_root, Config0),
@@ -1689,18 +2015,33 @@ server_config(http, Config) ->
{erl_script_alias, {"/cgi-bin/erl", [httpd_example, io]}},
{eval_script_alias, {"/eval", [httpd_example, io]}}
];
-
+server_config(http_rel_path_script_alias, Config) ->
+ ServerRoot = proplists:get_value(server_root, Config),
+ [{port, 0},
+ {socket_type, {ip_comm, [{nodelay, true}]}},
+ {server_name,"httpd_test"},
+ {server_root, ServerRoot},
+ {document_root, proplists:get_value(doc_root, Config)},
+ {bind_address, any},
+ {ipfamily, proplists:get_value(ipfamily, Config)},
+ {max_header_size, 256},
+ {max_header_action, close},
+ {directory_index, ["index.html", "welcome.html"]},
+ {mime_types, [{"html","text/html"},{"htm","text/html"}, {"shtml","text/html"},
+ {"gif", "image/gif"}]},
+ {alias, {"/icons/", filename:join(ServerRoot,"icons") ++ "/"}},
+ {alias, {"/pics/", filename:join(ServerRoot,"icons") ++ "/"}},
+ {script_alias, {"/cgi-bin/", "./cgi-bin/"}},
+ {script_alias, {"/htbin/", "./cgi-bin/"}},
+ {erl_script_alias, {"/cgi-bin/erl", [httpd_example, io]}},
+ {eval_script_alias, {"/eval", [httpd_example, io]}}
+ ];
server_config(https, Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
+ SSLConf = proplists:get_value(ssl_conf, Config),
+ ServerConf = proplists:get_value(server_config, SSLConf),
[{socket_type, {essl,
- [{nodelay, true},
- {cacertfile,
- filename:join(PrivDir, "public_key_cacert.pem")},
- {certfile,
- filename:join(PrivDir, "public_key_cert.pem")},
- {keyfile,
- filename:join(PrivDir, "public_key_cert_key.pem")}
- ]}}] ++ proplists:delete(socket_type, server_config(http, Config)).
+ [{nodelay, true} | ServerConf]}}]
+ ++ proplists:delete(socket_type, server_config(http, Config)).
init_httpd(Group, Config0) ->
Config1 = proplists:delete(port, Config0),
@@ -1741,7 +2082,10 @@ head_status(_) ->
basic_conf() ->
[{modules, [mod_alias, mod_range, mod_responsecontrol,
- mod_trace, mod_esi, mod_cgi, mod_dir, mod_get, mod_head]}].
+ mod_trace, mod_esi, mod_cgi, mod_get, mod_head]}].
+
+not_sup_conf() ->
+ [{modules, [mod_get]}].
auth_access_conf() ->
[{modules, [mod_alias, mod_htaccess, mod_dir, mod_get, mod_head]},
@@ -1863,6 +2207,16 @@ mod_security_conf(SecFile, Dir) ->
{path, Dir} %% This is should not be needed, but is atm, awful design!
].
+log_conf() ->
+ [{modules, [mod_alias, mod_dir, mod_get, mod_head, mod_disk_log]},
+ {transfer_disk_log, "httpd_log_transfer"},
+ {security_disk_log, "httpd_log_security"},
+ {error_disk_log, "httpd_log_error"},
+ {transfer_disk_log_size, {1048576, 5}},
+ {error_disk_log_size, {1048576, 5}},
+ {error_disk_log_size, {1048576, 5}},
+ {security_disk_log_size, {1048576, 5}},
+ {disk_log_format, internal}].
http_status(Request, Config, Expected) ->
Version = proplists:get_value(http_version, Config),
@@ -1945,9 +2299,9 @@ cleanup_mnesia() ->
ok.
transport_opts(ssl, Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- [proplists:get_value(ipfamily, Config),
- {cacertfile, filename:join(PrivDir, "public_key_cacert.pem")}];
+ SSLConf = proplists:get_value(ssl_conf, Config),
+ ClientConf = proplists:get_value(client_config, SSLConf),
+ [proplists:get_value(ipfamily, Config) | ClientConf];
transport_opts(_, Config) ->
[proplists:get_value(ipfamily, Config)].
diff --git a/lib/inets/test/httpd_basic_SUITE.erl b/lib/inets/test/httpd_basic_SUITE.erl
index 931cd076cc..94d22ea76c 100644
--- a/lib/inets/test/httpd_basic_SUITE.erl
+++ b/lib/inets/test/httpd_basic_SUITE.erl
@@ -303,7 +303,10 @@ escaped_url_in_error_body(Config) when is_list(Config) ->
%% Ask for a non-existing page(1)
Path = "/<b>this_is_bold<b>",
HTMLEncodedPath = http_util:html_encode(Path),
- URL2 = URL1 ++ Path,
+ URL2 = uri_string:recompose(#{scheme => "http",
+ host => "localhost",
+ port => Port,
+ path => Path}),
{ok, {404, Body3}} = httpc:request(get, {URL2, []},
[{url_encode, true},
{version, "HTTP/1.0"}],
diff --git a/lib/inets/test/httpd_bench_SUITE.erl b/lib/inets/test/httpd_bench_SUITE.erl
new file mode 100644
index 0000000000..4b549dcb5b
--- /dev/null
+++ b/lib/inets/test/httpd_bench_SUITE.erl
@@ -0,0 +1,846 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012-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(httpd_bench_SUITE).
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+-include_lib("public_key/include/public_key.hrl").
+-include_lib("kernel/include/file.hrl").
+
+-define(remote_host, "NETMARKS_REMOTE_HOST").
+-define(LF, [10]).
+-define(CR, [13]).
+-define(CRLF, ?CR ++ ?LF).
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+suite() ->
+ [{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]}].
+
+all() ->
+ [
+ {group, http_dummy},
+ {group, http_inets},
+ {group, http_nginx},
+ {group, https_inets},
+ {group, https_dummy},
+ {group, https_nginx},
+ {group, http_dummy_keep_alive},
+ {group, http_inets_keep_alive},
+ {group, http_nginx_keep_alive},
+ {group, https_inets_keep_alive},
+ {group, https_dummy_keep_alive},
+ {group, https_nginx_keep_alive}
+ ].
+
+groups() ->
+ [
+ {http_dummy, [], client_tests()},
+ {http_inets, [], client_tests()},
+ {http_nginx, [], client_tests()},
+ {https_dummy, [], client_tests()},
+ {https_inets, [], client_tests()},
+ {https_nginx, [], client_tests()},
+ {http_dummy_keep_alive, [], client_tests()},
+ {http_inets_keep_alive, [], client_tests()},
+ {http_nginx_keep_alive, [], client_tests()},
+ {https_dummy_keep_alive, [], client_tests()},
+ {https_inets_keep_alive, [], client_tests()},
+ {https_nginx_keep_alive, [], client_tests()}
+ ].
+
+
+client_tests() ->
+ [wget_small,
+ erl_dummy_small,
+ httpc_small,
+ wget_big,
+ erl_dummy_big,
+ httpc_big
+ ].
+
+init_per_suite(Config) ->
+ try
+ {Node, Host} = setup(Config, node()),
+ init_ssl(Config),
+ [{iter, 10}, {server_node, Node}, {server_host, Host} | Config]
+ catch _:_ ->
+ {skipped, "Benchmark machines only"}
+ end.
+
+end_per_suite(_Config) ->
+ [application:stop(App) || App <- [asn1, crypto, public_key, ssl, inets]].
+
+init_per_group(Group, Config) when Group == http_dummy_keep_alive;
+ Group == https_dummy_keep_alive;
+ Group == http_inets_keep_alive;
+ Group == https_inets_keep_alive;
+ Group == http_nginx_keep_alive;
+ Group == https_nginx_keep_alive ->
+ Version = http_version(Group),
+ start_web_server(Group,
+ [{keep_alive, true},
+ {reuse_sessions, false},
+ {http_version, Version},
+ {http_opts,[{version, Version}]},
+ {http_headers, [{"connection", "keep-alive"}]},
+ {httpc_opts, [{keep_alive_timeout, 1500},
+ {max_keep_alive_length, ?config(iter, Config)}]}
+ | Config]);
+init_per_group(Group, Config) when Group == http_dummy;
+ Group == https_dummy;
+ Group == http_inets;
+ Group == https_inets;
+ Group == http_nginx;
+ Group == https_nginx ->
+ Version = http_version(Group),
+ start_web_server(Group,
+ [{keep_alive, false},
+ {reuse_sessions, false},
+ {http_version, Version},
+ {http_headers, [{"connection", "close"}]},
+ {http_opts,[{version, Version}]},
+ {httpc_opts, [{keep_alive_timeout, 0}, {max_keep_alive_length, 0}]}
+ | Config]);
+
+
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(Group, Config) ->
+ stop_web_server(Group, Config).
+
+init_per_testcase(TestCase, Config) when TestCase == httpc_small;
+ TestCase == httpc_big
+ ->
+ Opts = ?config(httpc_opts, Config),
+ inets:start(httpc, [{profile, TestCase}, {socket_opts, [{nodelay, true}]}]),
+ httpc:set_options(Opts, TestCase),
+ [{profile, TestCase} | proplists:delete(profile, Config)];
+
+init_per_testcase(_, Config) ->
+ Config.
+end_per_testcase(TestCase, _Config) when TestCase == httpc_small;
+ TestCase == httpc_big ->
+ ok = inets:stop(httpc, TestCase);
+end_per_testcase(_TestCase, Config) ->
+ Config.
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+erl_dummy_small(Config) when is_list(Config) ->
+ {ok, Result} = run_test(httpd_lib_client, "1k_file", Config),
+ notify(Result, Config, "erl_1k_file").
+
+erl_dummy_big(Config) when is_list(Config) ->
+ {ok, Result} = run_test(httpd_lib_client, "1M_file", Config),
+ notify(Result, Config, "erl_1M_file").
+
+wget_small(Config) when is_list(Config) ->
+ {ok, Result} = run_test(wget_client, "1k_file", Config),
+ notify(Result, Config, "wget_1k_file").
+
+wget_big(Config) when is_list(Config) ->
+ {ok, Result} = run_test(wget_client, "1M_file", Config),
+ notify(Result, Config, "wget_1M_file").
+
+httpc_small(Config) when is_list(Config) ->
+ {ok, Result} = run_test(httpc_client, "1k_file", Config),
+ notify(Result, Config, "httpc_1k_file").
+
+httpc_big(Config) when is_list(Config) ->
+ {ok, Result} = run_test(httpc_client, "1M_file", Config),
+ notify(Result, Config, "httpc_1M_file").
+
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Report benchmark results ------------------------------------------------
+%%--------------------------------------------------------------------
+
+notify({TestPerSec, _MBps}, Config, Suffix) ->
+ Name = lists:concat([?config(protocol,Config), " ",
+ server_name(Config, [dummy_pid, httpd_pid, nginx_port]),
+ "", Suffix]),
+ ct:comment("~p tps", [TestPerSec]),
+ ct_event:notify(#event{name = benchmark_data,
+ data=[{value, TestPerSec},
+ {suite, ?MODULE},
+ {name, Name}]}),
+ ok.
+%%--------------------------------------------------------------------
+%% Setup erlang nodes ------------------------------------------------
+%%--------------------------------------------------------------------
+
+server_name(Config, [Server | Rest]) ->
+ case proplists:get_value(Server, Config) of
+ undefined ->
+ server_name(Config, Rest);
+ _ ->
+ server_name(Server)
+ end.
+
+server_name(httpd_pid) ->
+ "inets";
+server_name(nginx_port) ->
+ "nginx";
+server_name(dummy_pid) ->
+ "erlang".
+
+setup(_Config, nonode@nohost) ->
+ exit(dist_not_enabled);
+setup(_Config, _LocalNode) ->
+ Host = case os:getenv(?remote_host) of
+ false ->
+ {ok, This} = inet:gethostname(),
+ This;
+ RemHost ->
+ RemHost
+ end,
+ Node = list_to_atom("inets_perf_server@" ++ Host),
+ SlaveArgs = case init:get_argument(pa) of
+ {ok, PaPaths} ->
+ lists:append([" -pa " ++ P || [P] <- PaPaths]);
+ _ -> []
+ end,
+ Prog =
+ case os:find_executable("erl") of
+ false -> "erl";
+ P -> P
+ end,
+ case net_adm:ping(Node) of
+ pong -> ok;
+ pang ->
+ {ok, Node} = slave:start(Host, inets_perf_server, SlaveArgs, no_link, Prog)
+ end,
+ Path = code:get_path(),
+ true = rpc:call(Node, code, set_path, [Path]),
+ [ensure_started(Node, App) || App <- [asn1, crypto, public_key, ssl, inets]],
+ [ensure_started(node(), App) || App <- [asn1, crypto, public_key, ssl, inets]],
+ (Node =:= node()) andalso restrict_schedulers(client),
+ {Node, Host}.
+
+ensure_started(Node, App) ->
+ ok = rpc:call(Node, application, ensure_started, [App]).
+
+
+restrict_schedulers(Type) ->
+ %% We expect this to run on 8 core machine
+ Extra0 = 1,
+ Extra = if (Type =:= server) -> -Extra0; true -> Extra0 end,
+ Scheds = erlang:system_info(schedulers),
+ erlang:system_flag(schedulers_online, (Scheds div 2) + Extra).
+
+%%--------------------------------------------------------------------
+%% Setup TLS input files ------------------------------------------------
+%%--------------------------------------------------------------------
+
+init_ssl(Config) ->
+ DDir = ?config(data_dir, Config),
+ PDir = ?config(priv_dir, Config),
+ {ok, _} = make_certs:all(DDir,
+ PDir).
+cert_opts(Config) ->
+ ClientCaCertFile = filename:join([?config(priv_dir, Config),
+ "client", "cacerts.pem"]),
+ ClientCertFile = filename:join([?config(priv_dir, Config),
+ "client", "cert.pem"]),
+ ServerCaCertFile = filename:join([?config(priv_dir, Config),
+ "server", "cacerts.pem"]),
+ ServerCertFile = filename:join([?config(priv_dir, Config),
+ "server", "cert.pem"]),
+ ServerKeyFile = filename:join([?config(priv_dir, Config),
+ "server", "key.pem"]),
+ ClientKeyFile = filename:join([?config(priv_dir, Config),
+ "client", "key.pem"]),
+ [{server_verification_opts, [{reuseaddr, true},
+ {cacertfile, ServerCaCertFile},
+ {ciphers, ["ECDHE-RSA-AES256-GCM-SHA384"]},
+ {certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
+ {client_verification_opts, [
+ %%{verify, verify_peer},
+ {cacertfile, ClientCaCertFile},
+ {certfile, ClientCertFile},
+ {keyfile, ClientKeyFile}]}].
+
+%%--------------------------------------------------------------------
+%% Run clients ------------------------------------------------
+%%--------------------------------------------------------------------
+
+run_test(Client, File, Config) ->
+ Parent = self(),
+ Pid = spawn(fun() ->
+ receive
+ go ->
+ Parent ! {self(),
+ do_runs(Client, [{file, File} | Config])}
+ end
+ end),
+ Pid ! go,
+ receive
+ {Pid,{{tps, Tps}, {mbps, MBps}}} ->
+ ct:pal("Tps: ~p Bps~p", [Tps, MBps]),
+ {ok, {Tps, MBps}}
+ end.
+
+do_runs(Client, Config) ->
+ N = ?config(iter, Config),
+ DataDir = ?config(data_dir, Config),
+ File = ?config(file, Config),
+ Name = filename:join(DataDir, File),
+ Args = ?MODULE:Client(Config),
+ ?MODULE:Client({init, Args}),
+ Run =
+ fun() ->
+ ok = ?MODULE:Client(Args, N)
+ end,
+ {ok, Info} = file:read_file_info(Name, []),
+ Length = Info#file_info.size,
+ {TimeInMicro, _} = timer:tc(Run),
+ ReqPerSecond = (1000000 * N) div TimeInMicro,
+ BytesPerSecond = (1000000 * N * Length) div TimeInMicro,
+ {{tps, ReqPerSecond}, {mbps, BytesPerSecond}}.
+
+
+httpc_client({init, [_, Profile, URL, Headers, HTTPOpts]}) ->
+ %% Make sure pipelining feature will kick in when appropriate.
+ {ok, {{_ ,200, "OK"}, _,_}} = httpc:request(get,{URL, Headers}, HTTPOpts,
+ [{body_format, binary},
+ {socket_opts, [{nodelay, true}]}], Profile),
+ ct:sleep(1000);
+httpc_client(Config) ->
+ File = ?config(file, Config),
+ Protocol = ?config(protocol, Config),
+ Profile = ?config(profile, Config),
+ URL = (?config(urlfun,Config))(File),
+ Headers = ?config(http_headers, Config),
+ HTTPOpts = ?config(http_opts, Config),
+ [Protocol, Profile, URL, Headers, HTTPOpts].
+httpc_client(_,0) ->
+ ok;
+httpc_client([Protocol, Profile, URL, Headers, HTTPOpts], N) ->
+ {ok, {{_ ,200,"OK"}, _,_}} = httpc:request(get,{URL, Headers}, HTTPOpts, [{body_format, binary},
+ {socket_opts, [{nodelay, true}]}], Profile),
+ httpc_client([Protocol, Profile, URL, Headers, HTTPOpts], N-1).
+
+httpd_lib_client({init, [_, Type, Version, Request, Host, Port, Opts]}) ->
+ ok = httpd_test_lib:verify_request(Type, Host,
+ Port,
+ Opts, node(),
+ Request,
+ [{statuscode, 200},
+ {version, Version}], infinity),
+ ct:sleep(1000);
+httpd_lib_client(Config) ->
+ File = ?config(file, Config),
+ KeepAlive = ?config(keep_alive, Config),
+ Host = ?config(server_host, Config),
+ Port = ?config(port, Config),
+ ReuseSession = ?config(reuse_sessions, Config),
+ {Type, Opts} =
+ case ?config(protocol, Config) of
+ "http" ->
+ {ip_comm, [{active, true}, {mode, binary},{nodelay, true}]};
+ "https" ->
+ SSLOpts = proplists:get_value(client_verification_opts, cert_opts(Config)),
+ {ssl, [{active, true}, {mode, binary}, {nodelay, true},
+ {reuse_sessions, ReuseSession} | SSLOpts]}
+
+ end,
+ Version = ?config(http_version, Config),
+ Request = case KeepAlive of
+ true ->
+ http_request("GET /" ++ File ++ " ", Version, Host, {"connection:keep-alive\r\n", ""});
+ false ->
+ http_request("GET /" ++ File ++ " ", Version, Host)
+ end,
+
+ Args = [KeepAlive, Type, Version, Request, Host, Port, Opts],
+ httpd_lib_client(Args, 1),
+ Args.
+
+httpd_lib_client(_, 0) ->
+ ok;
+httpd_lib_client([true, Type, Version, Request, Host, Port, Opts], N) ->
+ ok = httpd_test_lib:verify_request_N(Type, Host,
+ Port,
+ Opts, node(),
+ Request,
+ [{statuscode, 200},
+ {version, Version}], infinity, N);
+httpd_lib_client([false, Type, Version, Request, Host, Port, Opts] = List, N) ->
+ ok = httpd_test_lib:verify_request(Type, Host,
+ Port,
+ Opts, node(),
+ Request,
+ [{statuscode, 200},
+ {version, Version}], infinity),
+ httpd_lib_client(List, N-1).
+
+wget_client({init,_}) ->
+ ok;
+wget_client(Config) ->
+ File = ?config(file, Config),
+ URL = (?config(urlfun,Config))(File),
+ KeepAlive = ?config(keep_alive, Config),
+ PrivDir = ?config(priv_dir, Config),
+ Protocol = ?config(protocol, Config),
+ Iter = ?config(iter, Config),
+ FileName = filename:join(PrivDir, "wget_req"),
+ ProtocolOpts = case Protocol of
+ "http" ->
+ [];
+ "https" ->
+ proplists:get_value(client_verification_opts, cert_opts(Config))
+ end,
+ wget_req_file(FileName,URL,Iter),
+ [KeepAlive, FileName, URL, Protocol, ProtocolOpts, Iter].
+wget_client([KeepAlive, WgetFile, _URL, Protocol, ProtocolOpts, _], _) ->
+ process_flag(trap_exit, true),
+ Cmd = wget_N(KeepAlive, WgetFile, Protocol, ProtocolOpts),
+ %%ct:pal("Wget cmd: ~p", [Cmd]),
+ Port = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ wait_for_wget(Port).
+
+
+%%--------------------------------------------------------------------
+%% Start/stop servers ------------------------------------------------
+%%--------------------------------------------------------------------
+start_web_server(Group, Config) when Group == http_dummy;
+ Group == http_dummy_keep_alive ->
+ start_dummy("http", Config);
+
+start_web_server(Group, Config) when Group == https_dummy;
+ Group == https_dummy_keep_alive ->
+ start_dummy("https", Config);
+
+start_web_server(Group, Config) when Group == http_inets;
+ Group == http_inets_keep_alive ->
+ start_inets("http", [], Config);
+
+start_web_server(Group, Config) when Group == https_inets;
+ Group == https_inets_keep_alive ->
+ Opts = proplists:get_value(server_verification_opts, cert_opts(Config)),
+ ReuseSessions = ?config(reuse_sessions, Config),
+ SSLConfHttpd = [{socket_type, {essl,
+ [{nodelay, true}, {reuse_sessions, ReuseSessions} | Opts]}}],
+ start_inets("https", SSLConfHttpd, Config);
+
+start_web_server(Group, Config) when Group == http_nginx;
+ Group == http_nginx_keep_alive ->
+ case os:find_executable("nginx") of
+ false ->
+ {skip, "nginx not found"};
+ _ ->
+ start_nginx("http", Config)
+ end;
+
+start_web_server(Group, Config) when Group == https_nginx;
+ Group == https_nginx_keep_alive ->
+ case os:find_executable("nginx") of
+ false ->
+ {skip, "nginx not found"};
+ _ ->
+ start_nginx("https", cert_opts(Config) ++ Config)
+ end.
+
+start_inets(Protocol, ConfHttpd, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ DataDir = ?config(data_dir, Config),
+ Node = ?config(server_node, Config),
+ Host = ?config(server_host, Config),
+ HTTPVersion = ?config(http_version, Config),
+ Conf = [httpd, [{port,0},
+ {http_version, HTTPVersion},
+ {ipfamily, inet},
+ {server_name, "inets_test"},
+ {server_root, PrivDir},
+ {document_root, DataDir},
+ {keep_alive, ?config(keep_alive, Config)},
+ {keep_alive_timeout, 360}
+ | ConfHttpd]],
+ {ok, Pid} = rpc:call(Node, inets, start, Conf),
+ Port = proplists:get_value(port, rpc:call(Node, httpd, info, [Pid])),
+ F = fun(File) ->
+ lists:concat([Protocol,"://",Host,":",Port,"/",File])
+ end,
+ [{httpd_pid,Pid},{urlfun,F},{protocol,Protocol},{port,Port} | Config].
+
+start_dummy("http"= Protocol, Config) ->
+ HTTPVersion = ?config(http_version, Config),
+ Node = ?config(server_node, Config),
+ %%DataDir= ?config(data_dir, Config),
+ Host = ?config(server_host, Config),
+ Conf = [
+ %%{big, filename:join(DataDir, "1M_file")},
+ %%{small, filename:join(DataDir, "1k_file")},
+ {big, {gen, crypto:rand_bytes(1000000)}},
+ {small, {gen, crypto:rand_bytes(1000)}},
+ {http_version, HTTPVersion},
+ {keep_alive, ?config(keep_alive, Config)}
+ ],
+ {Pid, Port} = rpc:call(Node, http_test_lib, dummy_server, [ip_comm, inet, [{content_cb, ?MODULE}, {conf, Conf}]]),
+ F = fun(File) ->
+ lists:concat([Protocol,"://",Host,":",Port,"/",File])
+ end,
+ [{dummy_pid,Pid},{urlfun,F},{protocol, Protocol},{port,Port} | Config];
+
+start_dummy("https" = Protocol, Config) ->
+ HTTPVersion = ?config(http_version, Config),
+ Node = ?config(server_node, Config),
+ %% DataDir= ?config(data_dir, Config),
+ Host = ?config(server_host, Config),
+ SSLOpts = proplists:get_value(server_verification_opts, cert_opts(Config)),
+ Opts = [{active, true}, {nodelay, true}, {reuseaddr, true} | SSLOpts],
+ Conf = [%%{big, filename:join(DataDir, "1M_file")},
+ %%{small, filename:join(DataDir, "1k_file")},
+ {big, {gen, crypto:rand_bytes(1000000)}},
+ {small, {gen, crypto:rand_bytes(1000)}},
+ {http_version, HTTPVersion},
+ {keep_alive, ?config(keep_alive, Config)}
+ ],
+ {Pid, Port} = rpc:call(Node, http_test_lib, dummy_server,
+ [ssl, inet, [{ssl, Opts}, {content_cb, ?MODULE}, {conf, Conf}]]),
+ F = fun(File) ->
+ lists:concat([Protocol,"://",Host,":",Port,"/",File])
+ end,
+ [{dummy_pid,Pid},{urlfun,F},{protocol,Protocol},{port,Port} | Config].
+
+start_nginx(Protocol, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ DataDir = ?config(data_dir, Config),
+ Host = ?config(server_host, Config),
+ Port = inet_port(node()),
+
+ ConfFile = filename:join(PrivDir, "nginx.conf"),
+ nginx_conf(ConfFile, [{port, Port}, {protocol, Protocol} | Config]),
+ Cmd = "nginx -c " ++ ConfFile,
+ NginxPort = open_port({spawn, Cmd}, [{cd, DataDir}, stderr_to_stdout]),
+
+ F = fun(File) ->
+ lists:concat([Protocol,"://",Host,":",Port,"/",File])
+ end,
+
+ wait_for_nginx_up(Host, Port),
+
+ [{port, Port},{nginx_port, NginxPort},{urlfun,F},{protocol, Protocol} | Config ].
+
+stop_nginx(Config)->
+ PrivDir = ?config(priv_dir, Config),
+ {ok, Bin} = file:read_file(filename:join(PrivDir, "nginx.pid")),
+ Pid = string:strip(binary_to_list(Bin), right, $\n),
+ Cmd = "kill " ++ Pid,
+ os:cmd(Cmd).
+
+stop_web_server(Group, Config) when Group == http_inets;
+ Group == http_inets_keep_alive;
+ Group == https_inets;
+ Group == https_inets_keep_alive ->
+ ServerNode = ?config(server_node, Config),
+ rpc:call(ServerNode, inets, stop, [httpd, ?config(httpd_pid, Config)]);
+stop_web_server(Group, Config) when Group == http_dummy;
+ Group == http_dummy_keep_alive;
+ Group == https_dummy;
+ Group == https_dummy_keep_alive ->
+ stop_dummy_server(Config);
+stop_web_server(Group, Config) when Group == http_nginx;
+ Group == http_nginx_keep_alive;
+ Group == https_nginx;
+ Group == https_nginx_keep_alive ->
+ stop_nginx(Config).
+
+stop_dummy_server(Config) ->
+ case ?config(dummy_pid, Config) of
+ Pid when is_pid(Pid) ->
+ exit(Pid, kill);
+ _ ->
+ ok
+ end.
+
+%%--------------------------------------------------------------------
+%% Misc ------------------------------------------------
+%%--------------------------------------------------------------------
+http_request(Request, "HTTP/1.1" = Version, Host, {Headers, Body}) ->
+ Request ++ Version ++ "\r\nhost:" ++ Host ++ "\r\n" ++ Headers ++ "\r\n" ++ Body;
+http_request(Request, Version, _, {Headers, Body}) ->
+ Request ++ Version ++ "\r\n" ++ Headers ++ "\r\n" ++ Body.
+
+http_request(Request, "HTTP/1.1" = Version, Host) ->
+ Request ++ Version ++ "\r\nhost:" ++ Host ++ "\r\n\r\n";
+http_request(Request, Version, _) ->
+ Request ++ Version ++ "\r\n\r\n".
+
+http_version(_) ->
+ "HTTP/1.1".
+
+inet_port(Node) ->
+ {Port, Socket} = do_inet_port(Node),
+ rpc:call(Node, gen_tcp, close, [Socket]),
+ Port.
+
+do_inet_port(Node) ->
+ {ok, Socket} = rpc:call(Node, gen_tcp, listen, [0, [{reuseaddr, true}]]),
+ {ok, Port} = rpc:call(Node, inet, port, [Socket]),
+ {Port, Socket}.
+
+%%--------------------------------------------------------------------
+%% Dummy server callbacks ------------------------------------------------
+%%--------------------------------------------------------------------
+
+handle_request(CB, S, "/1M_file" ++ _, Opts) ->
+ Name = proplists:get_value(big, Opts),
+ KeepAlive = proplists:get_value(keep_alive, Opts),
+ do_handle_request(CB, S, Name, Opts, KeepAlive);
+handle_request(CB, S, "/1k_file" ++ _, Opts) ->
+ Name = proplists:get_value(small, Opts),
+ KeepAlive = proplists:get_value(keep_alive, Opts),
+ do_handle_request(CB, S, Name, Opts, KeepAlive).
+
+do_handle_request(CB, S, Name, Opts, KeepAlive) when is_list(Name) ->
+ Version = proplists:get_value(http_version, Opts),
+ {ok, Fdesc} = file:open(Name, [read, binary]),
+ {ok, Info} = file:read_file_info(Name, []),
+ Length = Info#file_info.size,
+ Response = response_status_line_and_headers(Version, "Content-Length:"
+ ++ integer_to_list(Length) ++ ?CRLF, keep_alive(KeepAlive)),
+ CB:send(S, Response),
+ send_file(CB, S, Fdesc);
+do_handle_request(CB, S, {gen, Data}, Opts, KeepAlive) ->
+ Version = proplists:get_value(http_version, Opts),
+ Length = size(Data),
+ Response = response_status_line_and_headers(Version, "Content-Length:"
+ ++ integer_to_list(Length) ++ ?CRLF, keep_alive(KeepAlive)),
+ CB:send(S, Response),
+ send_file(CB, S, {gen, Data}).
+
+send_file(CB, S, {gen, Data}) ->
+ CB:send(S, Data);
+ %% ChunkSize = 64*1024,
+ %% case size(Data) of
+ %% N when N > ChunkSize ->
+ %% <<Chunk:N/binary, Rest/binary>> = Data,
+ %% %%{Chunk, Rest} = lists:split(N, Data),
+ %% CB:send(S, Chunk),
+ %% send_file(CB, S, {gen, Rest});
+ %% _ ->
+ %% CB:send(S, Data)
+ %% end;
+
+send_file(CB, S, FileDesc) ->
+ case file:read(FileDesc, 64*1024) of
+ {ok, Chunk} ->
+ CB:send(S, Chunk),
+ send_file(CB, S, FileDesc);
+ eof ->
+ file:close(FileDesc),
+ ok
+ end.
+
+response_status_line_and_headers(Version, Headers, ConnectionHeader) ->
+ StatusLine = [Version, " ", "200 OK", ?CRLF],
+ [StatusLine, Headers, ConnectionHeader, ?CRLF].
+
+keep_alive(true)->
+ "Connection:keep-alive\r\n";
+keep_alive(false) ->
+ "Connection:close\r\n".
+
+handle_http_msg({_Method, RelUri, _, {_, _Headers}, _Body}, Socket, Conf) ->
+ handle_request(connect_cb(Socket), Socket, RelUri, Conf),
+ case proplists:get_value(keep_alive, Conf) of
+ true ->
+ <<>>;
+ false ->
+ stop
+ end.
+
+connect_cb({sslsocket, _, _}) ->
+ ssl;
+connect_cb(_) ->
+ gen_tcp.
+
+%%--------------------------------------------------------------------
+%% Setup wget ------------------------------------------------
+%%--------------------------------------------------------------------
+wget_req_file(FileName, Url, Iter) ->
+ {ok, File} = file:open(FileName, [write]),
+ write_urls(File, Url, Iter).
+
+write_urls(File, Url, 1) ->
+ file:write(File, Url),
+ file:close(File);
+write_urls(File, Url, N) ->
+ file:write(File, Url),
+ file:write(File, "\n"),
+ write_urls(File, Url, N-1).
+
+wait_for_wget(Port) ->
+ receive
+ {Port, {data, _Data}} when is_port(Port) ->
+ wait_for_wget(Port);
+ {Port, closed} ->
+ ok;
+ {'EXIT', Port, _Reason} ->
+ ok
+ end.
+
+wget_N(KeepAlive, WegetFile, "http", _ProtocolOpts) ->
+ "wget -i " ++ WegetFile ++ " " ++ wget_keep_alive(KeepAlive) ++
+ " --no-cache --timeout=120" ;
+wget_N(KeepAlive, WegetFile, "https", ProtocolOpts) ->
+
+ "wget -i " ++ WegetFile ++ " " ++ wget_keep_alive(KeepAlive)
+ ++ wget_cert(ProtocolOpts) ++ wget_key(ProtocolOpts)
+ ++ wget_cacert(ProtocolOpts) ++
+ " --no-cache --timeout=120".
+
+wget(KeepAlive, URL, "http", _ProtocolOpts) ->
+ "wget " ++ URL ++ " " ++ wget_keep_alive(KeepAlive) ++
+ " --no-cache --timeout=120" ;
+wget(KeepAlive, URL, "https", ProtocolOpts) ->
+
+ "wget " ++ URL ++ " " ++ wget_keep_alive(KeepAlive)
+ ++ wget_cert(ProtocolOpts) ++ wget_key(ProtocolOpts)
+ ++ wget_cacert(ProtocolOpts) ++
+ " --no-cache --timeout=120".
+
+wget_keep_alive(true)->
+ "";
+wget_keep_alive(false) ->
+ "--no-http-keep-alive ".
+
+wget_cacert(ProtocolOpts) ->
+ "--ca-certificate=" ++ proplists:get_value(cacertfile, ProtocolOpts) ++ " ".
+
+wget_cert(ProtocolOpts) ->
+ "--certificate=" ++ proplists:get_value(certfile, ProtocolOpts) ++ " ".
+
+wget_key(ProtocolOpts) ->
+ "--private-key=" ++ proplists:get_value(keyfile, ProtocolOpts) ++ " ".
+
+%%--------------------------------------------------------------------
+%% Setup nginx ------------------------------------------------
+%%--------------------------------------------------------------------
+nginx_conf(ConfFile, Config)->
+ Protocol = ?config(protocol, Config),
+ file:write_file(ConfFile,
+ [format_nginx_conf(nginx_global(Config)),
+ format_nginx_conf(nginx_events(Config)),
+ format_nginx_conf(nginx_http(Protocol, Config))]).
+
+format_nginx_conf(Directives) ->
+ lists:map(fun({Key, Value}) ->
+ io_lib:format("~s ~s;\n", [Key, Value]);
+ (Str) ->
+ Str
+ end, Directives).
+
+
+nginx_global(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ [{"pid", filename:join(PrivDir, "nginx.pid")},
+ {"error_log", filename:join(PrivDir, "nginx.pid")},
+ {"worker_processes", "1"}].
+
+nginx_events(_Config) ->
+ ["events {\n",
+ {"worker_connections", "1024"},
+ "\n}"
+ ].
+
+nginx_http("http", Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ DataDir = ?config(data_dir, Config),
+ Port = ?config(port, Config),
+ ["http {\n" |
+ nginx_defaults(PrivDir) ++
+ [" server {",
+ {root, DataDir},
+ {listen, integer_to_list(Port)},
+ " location / {\n try_files $uri $uri/ /index.html;\n}"
+ "}\n", "}\n"
+ ]
+ ];
+
+nginx_http("https", Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ DataDir = ?config(data_dir, Config),
+ Port = ?config(port, Config),
+ SSLOpts = ?config(server_verification_opts, Config),
+ Ciphers = proplists:get_value(ciphers, SSLOpts),
+ ReuseSession = ?config(reuse_sessions, Config),
+ ["http {" |
+ nginx_defaults(PrivDir) ++
+ [" server {",
+ {"root", DataDir},
+ {"listen", integer_to_list(Port) ++ " ssl"},
+ {"ssl_certificate", ?config(certfile, SSLOpts)},
+ {"ssl_certificate_key", ?config(keyfile, SSLOpts)},
+ {"ssl_protocols", "TLSv1 TLSv1.1 TLSv1.2"},
+ {"ssl_ciphers", Ciphers},
+ {"ssl_session_cache", nginx_reuse_session(ReuseSession)},
+ " location / {\n try_files $uri $uri/ /index.html;\n}"
+ "}\n", "}\n"
+ ]
+ ].
+
+nginx_defaults(PrivDir) ->
+ [
+ %% Set temp and cache file options that will otherwise default to
+ %% restricted locations accessible only to root.
+ {"client_body_temp_path", filename:join(PrivDir, "client_body")},
+ {"fastcgi_temp_path", filename:join(PrivDir, "fastcgi_temp")},
+ {"proxy_temp_path", filename:join(PrivDir, "proxy_temp")},
+ {"scgi_temp_path", filename:join(PrivDir, "scgi_temp")},
+ {"uwsgi_temp_path", filename:join(PrivDir, "uwsgi_temp_path")},
+ {"access_log", filename:join(PrivDir, "access.log")},
+ {"error_log", filename:join(PrivDir, "error.log")},
+ %% Standard options
+ {"sendfile", "on"},
+ {"tcp_nopush", "on"},
+ {"tcp_nodelay", "on"},
+ {"keepalive_timeout", "360"},
+ {"types_hash_max_size", "2048"},
+ {"include", "/etc/nginx/mime.types"},
+ {"default_type", "application/octet-stream"}
+ ].
+
+nginx_reuse_session(true) ->
+ "on";
+nginx_reuse_session(false) ->
+ "off".
+
+wait_for_nginx_up(Host, Port) ->
+ case gen_tcp:connect(Host, Port, []) of
+ {ok, Socket} ->
+ gen_tcp:close(Socket);
+ _ ->
+ ct:sleep(100),
+ wait_for_nginx_up(Host, Port)
+ end.
+
diff --git a/lib/inets/test/httpd_bench_SUITE_data/1M_file b/lib/inets/test/httpd_bench_SUITE_data/1M_file
new file mode 100644
index 0000000000..557989144e
--- /dev/null
+++ b/lib/inets/test/httpd_bench_SUITE_data/1M_file
Binary files differ
diff --git a/lib/inets/test/httpd_bench_SUITE_data/1k_file b/lib/inets/test/httpd_bench_SUITE_data/1k_file
new file mode 100644
index 0000000000..cade172d80
--- /dev/null
+++ b/lib/inets/test/httpd_bench_SUITE_data/1k_file
Binary files differ
diff --git a/lib/inets/test/httpd_block.erl b/lib/inets/test/httpd_block.erl
deleted file mode 100644
index 45547e6d4e..0000000000
--- a/lib/inets/test/httpd_block.erl
+++ /dev/null
@@ -1,372 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(httpd_block).
-
--include_lib("common_test/include/ct.hrl").
-
-%% General testcases bodies called from httpd_SUITE
--export([block_disturbing_idle/4, block_non_disturbing_idle/4,
- block_503/4, block_disturbing_active/4,
- block_non_disturbing_active/4,
- block_disturbing_active_timeout_not_released/4,
- block_disturbing_active_timeout_released/4,
- block_non_disturbing_active_timeout_not_released/4,
- block_non_disturbing_active_timeout_released/4,
- disturbing_blocker_dies/4,
- non_disturbing_blocker_dies/4, restart_no_block/4,
- restart_disturbing_block/4, restart_non_disturbing_block/4
- ]).
-
-%% Help functions
--export([httpd_block/3, httpd_block/4, httpd_unblock/2, httpd_restart/2]).
--export([do_block_server/4, do_block_nd_server/5, do_long_poll/6]).
-
--define(report(Label, Content),
- inets:report_event(20, Label, test_case,
- [{module, ?MODULE}, {line, ?LINE} | Content])).
-
-
-%%-------------------------------------------------------------------------
-%% Test cases starts here.
-%%-------------------------------------------------------------------------
-block_disturbing_idle(_Type, Port, Host, Node) ->
- io:format("block_disturbing_idle -> entry~n", []),
- validate_admin_state(Node, Host, Port, unblocked),
- block_server(Node, Host, Port),
- validate_admin_state(Node, Host, Port, blocked),
- unblock_server(Node, Host, Port),
- validate_admin_state(Node, Host, Port, unblocked),
- io:format("block_disturbing_idle -> done~n", []),
- ok.
-
-%%--------------------------------------------------------------------
-block_non_disturbing_idle(_Type, Port, Host, Node) ->
- unblocked = get_admin_state(Node, Host, Port),
- block_nd_server(Node, Host, Port),
- blocked = get_admin_state(Node, Host, Port),
- unblock_server(Node, Host, Port),
- unblocked = get_admin_state(Node, Host, Port),
- ok.
-
-%%--------------------------------------------------------------------
-block_503(Type, Port, Host, Node) ->
- Req = "GET / HTTP/1.0\r\ndummy-host.ericsson.se:\r\n\r\n",
- unblocked = get_admin_state(Node, Host, Port),
- ok = httpd_test_lib:verify_request(Type, Host, Port, Node, Req,
- [{statuscode, 200},
- {version, "HTTP/1.0"}]),
- ok = block_server(Node, Host, Port),
- blocked = get_admin_state(Node, Host, Port),
- ok = httpd_test_lib:verify_request(Type, Host, Port, Node, Req,
- [{statuscode, 503},
- {version, "HTTP/1.0"}]),
- ok = unblock_server(Node, Host, Port),
- unblocked = get_admin_state(Node, Host, Port),
- ok = httpd_test_lib:verify_request(Type, Host, Port, Node, Req,
- [{statuscode, 200},
- {version, "HTTP/1.0"}]).
-
-%%--------------------------------------------------------------------
-block_disturbing_active(Type, Port, Host, Node) ->
- process_flag(trap_exit, true),
- Pid = long_poll(Type, Host, Port, Node, 200, 60000),
- ct:sleep(15000),
- block_server(Node, Host, Port),
- await_suite_failed_process_exit(Pid, "poller", 60000,
- connection_closed),
- blocked = get_admin_state(Node, Host, Port),
- process_flag(trap_exit, false),
- ok.
-
-%%--------------------------------------------------------------------
-block_non_disturbing_active(Type, Port, Host, Node) ->
- process_flag(trap_exit, true),
- Poller = long_poll(Type, Host, Port, Node, 200, 60000),
- ct:sleep(15000),
- ok = block_nd_server(Node, Host, Port),
- await_normal_process_exit(Poller, "poller", 60000),
- blocked = get_admin_state(Node, Host, Port),
- process_flag(trap_exit, false),
- ok.
-
-%%--------------------------------------------------------------------
-block_disturbing_active_timeout_not_released(Type, Port, Host, Node) ->
- process_flag(trap_exit, true),
- Poller = long_poll(Type, Host, Port, Node, 200, 60000),
- ct:sleep(15000),
- ok = httpd_block(undefined, Port, disturbing, 50000),
- await_normal_process_exit(Poller, "poller", 30000),
- blocked = get_admin_state(Node, Host, Port),
- process_flag(trap_exit, false),
- ok.
-
-%%--------------------------------------------------------------------
-block_disturbing_active_timeout_released(Type, Port, Host, Node) ->
- process_flag(trap_exit, true),
- Poller = long_poll(Type, Host, Port, Node, 200, 40000),
- ct:sleep(5000),
- ok = httpd_block(undefined, Port, disturbing, 10000),
- await_suite_failed_process_exit(Poller, "poller", 40000,
- connection_closed),
- blocked = get_admin_state(Node, Host, Port),
- process_flag(trap_exit, false),
- ok.
-%%--------------------------------------------------------------------
-block_non_disturbing_active_timeout_not_released(Type, Port, Host, Node) ->
- process_flag(trap_exit, true),
- Poller = long_poll(Type, Host, Port, Node, 200, 60000),
- ct:sleep(5000),
- ok = block_nd_server(Node, Host, Port, 40000),
- await_normal_process_exit(Poller, "poller", 60000),
- blocked = get_admin_state(Node, Host, Port),
- process_flag(trap_exit, false),
- ok.
-
-%%--------------------------------------------------------------------
-block_non_disturbing_active_timeout_released(Type, Port, Host, Node) ->
- process_flag(trap_exit, true),
- Poller = long_poll(Type, Host, Port, Node, 200, 45000),
- ct:sleep(5000),
- Blocker = blocker_nd(Node, Host, Port ,10000, {error,timeout}),
- await_normal_process_exit(Blocker, "blocker", 15000),
- await_normal_process_exit(Poller, "poller", 50000),
- unblocked = get_admin_state(Node, Host, Port),
- process_flag(trap_exit, false),
- ok.
-%%--------------------------------------------------------------------
-disturbing_blocker_dies(Type, Port, Host, Node) ->
- process_flag(trap_exit, true),
- Poller = long_poll(Type, Host, Port, Node, 200, 60000),
- ct:sleep(5000),
- Blocker = blocker(Node, Host, Port, 10000),
- ct:sleep(5000),
- exit(Blocker,simulate_blocker_crash),
- await_normal_process_exit(Poller, "poller", 60000),
- unblocked = get_admin_state(Node, Host, Port),
- process_flag(trap_exit, false),
- ok.
-
-%%--------------------------------------------------------------------
-non_disturbing_blocker_dies(Type, Port, Host, Node) ->
- process_flag(trap_exit, true),
- Poller = long_poll(Type, Host, Port, Node, 200, 60000),
- ct:sleep(5000),
- Blocker = blocker_nd(Node, Host, Port, 10000, ok),
- ct:sleep(5000),
- exit(Blocker, simulate_blocker_crash),
- await_normal_process_exit(Poller, "poller", 60000),
- unblocked = get_admin_state(Node, Host, Port),
- process_flag(trap_exit, false),
- ok.
-%%--------------------------------------------------------------------
-restart_no_block(_, Port, Host, Node) ->
- {error,_Reason} = restart_server(Node, Host, Port).
-
-%%--------------------------------------------------------------------
-restart_disturbing_block(_, Port, Host, Node) ->
- ?report("restart_disturbing_block - get_admin_state (unblocked)", []),
- unblocked = get_admin_state(Node, Host, Port),
- ?report("restart_disturbing_block - block_server", []),
- ok = block_server(Node, Host, Port),
- ?report("restart_disturbing_block - restart_server", []),
- ok = restart_server(Node, Host, Port),
- ?report("restart_disturbing_block - unblock_server", []),
- ok = unblock_server(Node, Host, Port),
- ?report("restart_disturbing_block - get_admin_state (unblocked)", []),
- unblocked = get_admin_state(Node, Host, Port).
-
-%%--------------------------------------------------------------------
-restart_non_disturbing_block(_, Port, Host, Node) ->
- ?report("restart_non_disturbing_block - get_admin_state (unblocked)", []),
- unblocked = get_admin_state(Node, Host, Port),
- ?report("restart_non_disturbing_block - block_nd_server", []),
- ok = block_nd_server(Node, Host, Port),
- ?report("restart_non_disturbing_block - restart_server", []),
- ok = restart_server(Node, Host, Port),
- ?report("restart_non_disturbing_block - unblock_server", []),
- ok = unblock_server(Node, Host, Port),
- ?report("restart_non_disturbing_block - get_admin_state (unblocked)", []),
- unblocked = get_admin_state(Node, Host, Port).
-
-%%--------------------------------------------------------------------
-%% Internal functions
-%%--------------------------------------------------------------------
-blocker(Node, Host, Port, Timeout) ->
- spawn_link(?MODULE, do_block_server,[Node, Host, Port,Timeout]).
-
-do_block_server(Node, Host, Port, Timeout) ->
- ok = block_server(Node, Host, Port, Timeout),
- exit(normal).
-
-blocker_nd(Node, Host, Port, Timeout, Reply) ->
- spawn_link(?MODULE, do_block_nd_server,
- [Node, Host, Port, Timeout, Reply]).
-
-do_block_nd_server(Node, Host, Port, Timeout, Reply) ->
- Reply = block_nd_server(Node, Host, Port, Timeout),
- exit(normal).
-
-restart_server(Node, _Host, Port) ->
- Addr = undefined,
- rpc:call(Node, ?MODULE, httpd_restart, [Addr, Port]).
-
-
-block_server(Node, _Host, Port) ->
- io:format("block_server -> entry~n", []),
- Addr = undefined,
- rpc:call(Node, ?MODULE, httpd_block, [Addr, Port, disturbing]).
-
-
-block_server(Node, _Host, Port, Timeout) ->
- Addr = undefined,
- rpc:call(Node, ?MODULE, httpd_block, [Addr, Port, disturbing, Timeout]).
-
-
-block_nd_server(Node, _Host, Port) ->
- Addr = undefined,
- rpc:call(Node, ?MODULE, httpd_block, [Addr, Port, non_disturbing]).
-
-block_nd_server(Node, _Host, Port, Timeout) ->
- Addr = undefined,
- rpc:call(Node, ?MODULE, httpd_block, [Addr, Port, non_disturbing, Timeout]).
-
-unblock_server(Node, _Host, Port) ->
- io:format("~p:~p:block_server -> entry~n", [node(),self()]),
- Addr = undefined,
- rpc:call(Node, ?MODULE, httpd_unblock, [Addr, Port]).
-
-
-httpd_block(Addr, Port, Mode) ->
- io:format("~p:~p:httpd_block -> entry~n", [node(),self()]),
- Name = make_name(Addr, Port),
- case whereis(Name) of
- Pid when is_pid(Pid) ->
- httpd_manager:block(Pid, Mode);
- _ ->
- {error, not_started}
- end.
-
-httpd_block(Addr, Port, Mode, Timeout) ->
- Name = make_name(Addr, Port),
- case whereis(Name) of
- Pid when is_pid(Pid) ->
- httpd_manager:block(Pid, Mode, Timeout);
- _ ->
- {error, not_started}
- end.
-
-httpd_unblock(Addr, Port) ->
- io:format("~p:~p:httpd_unblock -> entry~n", [node(),self()]),
- Name = make_name(Addr, Port),
- case whereis(Name) of
- Pid when is_pid(Pid) ->
- httpd_manager:unblock(Pid);
- _ ->
- {error, not_started}
- end.
-
-httpd_restart(Addr, Port) ->
- Name = make_name(Addr, Port),
- case whereis(Name) of
- Pid when is_pid(Pid) ->
- httpd_manager:reload(Pid, undefined);
- _ ->
- {error, not_started}
- end.
-
-make_name(Addr, Port) ->
- httpd_util:make_name("httpd", Addr, Port, default).
-
-get_admin_state(_, _Host, Port) ->
- Name = make_name(undefined, Port),
- {status, _, _, StatusInfo} = sys:get_status(whereis(Name)),
- [_, _,_, _, Prop] = StatusInfo,
- State = state(Prop),
- element(6, State).
-
-validate_admin_state(Node, Host, Port, Expect) ->
- io:format("try validating server admin state: ~p~n", [Expect]),
- case get_admin_state(Node, Host, Port) of
- Expect ->
- ok;
- Unexpected ->
- io:format("failed validating server admin state: ~p~n",
- [Unexpected]),
- exit({unexpected_admin_state, Unexpected, Expect})
- end.
-
-
-await_normal_process_exit(Pid, Name, Timeout) ->
- receive
- {'EXIT', Pid, normal} ->
- ok;
- {'EXIT', Pid, Reason} ->
- Err =
- lists:flatten(
- io_lib:format("expected normal exit, "
- "unexpected exit of ~s process: ~p",
- [Name, Reason])),
- ct:fail(Err)
- after Timeout ->
- ct:fail("timeout while waiting for " ++ Name)
- end.
-
-
-await_suite_failed_process_exit(Pid, Name, Timeout, Why) ->
- receive
- {'EXIT', Pid, {test_failed, Why}} ->
- ok;
- {'EXIT', Pid, Reason} ->
- Err =
- lists:flatten(
- io_lib:format("expected connection_closed, "
- "unexpected exit of ~s process: ~p",
- [Name, Reason])),
- ct:fail(Err)
- after Timeout ->
- ct:fail("timeout while waiting for " ++ Name)
- end.
-
-long_poll(Type, Host, Port, Node, StatusCode, Timeout) ->
- spawn_link(?MODULE, do_long_poll, [Type, Host, Port, Node,
- StatusCode, Timeout]).
-
-do_long_poll(Type, Host, Port, Node, StatusCode, Timeout) ->
- Mod = "httpd_example",
- Func = "delay",
- Req = lists:flatten(io_lib:format("GET /eval?" ++ Mod ++ ":" ++ Func ++
- "(~p) HTTP/1.0\r\n\r\n",[30000])),
- case httpd_test_lib:verify_request(Type, Host, Port, Node, Req,
- [{statuscode, StatusCode},
- {version, "HTTP/1.0"}], Timeout) of
- ok ->
- exit(normal);
- Reason ->
- exit({test_failed, Reason})
- end.
-
-
-state([{data,[{"State", State}]} | _]) ->
- State;
-state([{data,[{"StateData", State}]} | _]) ->
- State;
-state([_ | Rest]) ->
- state(Rest).
diff --git a/lib/inets/test/httpd_mod.erl b/lib/inets/test/httpd_mod.erl
index d9118aa1a4..6e3635001a 100644
--- a/lib/inets/test/httpd_mod.erl
+++ b/lib/inets/test/httpd_mod.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -779,9 +779,14 @@ esi(Type, Port, Host, Node) ->
[{statuscode, 200},
{no_header, "cache-control"},
{version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/httpd_example:new_status_and_location"
+ " HTTP/1.1\r\n\r\n",
+ [{statuscode, 201},
+ {header, "Location"},
+ {version, "HTTP/1.1"}]),
ok.
-
%%--------------------------------------------------------------------
get(Type, Port, Host, Node) ->
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
diff --git a/lib/inets/test/httpd_test_lib.erl b/lib/inets/test/httpd_test_lib.erl
index 1cecd2642c..b6525037b2 100644
--- a/lib/inets/test/httpd_test_lib.erl
+++ b/lib/inets/test/httpd_test_lib.erl
@@ -23,7 +23,8 @@
-include("inets_test_lib.hrl").
%% Poll functions
--export([verify_request/6, verify_request/7, verify_request/8, is_expect/1]).
+-export([verify_request/6, verify_request/7, verify_request/8, is_expect/1,
+ verify_request_N/9]).
-record(state, {request, % string()
socket, % socket()
@@ -109,9 +110,9 @@ verify_request(SocketType, Host, Port, TranspOpts, Node, RequestStr, Options, Ti
{error, Reason};
NewState ->
ValidateResult =
- validate(RequestStr, NewState, Options, Node, Port),
+ validate(RequestStr, NewState, Options, Node, Port),
inets_test_lib:close(SocketType, Socket),
- ValidateResult
+ ValidateResult
end;
ConnectError ->
@@ -126,6 +127,46 @@ verify_request(SocketType, Host, Port, TranspOpts, Node, RequestStr, Options, Ti
{args, [SocketType, Host, Port, TranspOpts]}]})
end.
+verify_request_N(SocketType, Host, Port, TranspOpts, Node, RequestStr, Options, TimeOut, N) ->
+ State = #state{},
+ try inets_test_lib:connect_bin(SocketType, Host, Port, TranspOpts) of
+ {ok, Socket} ->
+ request_N(SocketType, Socket, RequestStr, Options, TimeOut, Node, Port, State, N);
+ ConnectError ->
+ ct:fail({connect_error, ConnectError,
+ [SocketType, Host, Port, TranspOpts]})
+ catch
+ T:E ->
+ ct:fail({connect_failure,
+ [{type, T},
+ {error, E},
+ {stacktrace, erlang:get_stacktrace()},
+ {args, [SocketType, Host, Port, TranspOpts]}]})
+ end.
+
+request_N(SocketType, Socket, RequestStr, Options, TimeOut, Node, Port, State, 0) ->
+ ok = inets_test_lib:send(SocketType, Socket, RequestStr),
+ case request(State#state{request = RequestStr,
+ socket = Socket}, TimeOut) of
+ {error, Reason} ->
+ {error, Reason};
+ NewState ->
+ ValidateResult =
+ validate(RequestStr, NewState, Options, Node, Port),
+ inets_test_lib:close(SocketType, Socket),
+ ValidateResult
+ end;
+request_N(SocketType, Socket, RequestStr, Options, TimeOut, Node, Port, State, N) ->
+ ok = inets_test_lib:send(SocketType, Socket, RequestStr),
+ case request(State#state{request = RequestStr,
+ socket = Socket}, TimeOut) of
+ {error, Reason} ->
+ {error, Reason};
+ _NewState ->
+ request_N(SocketType, Socket, RequestStr, Options, TimeOut, Node, Port,
+ #state{}, N-1)
+ end.
+
request(#state{mfa = {Module, Function, Args},
request = RequestStr, socket = Socket} = State, TimeOut) ->
@@ -160,13 +201,35 @@ request(#state{mfa = {Module, Function, Args},
{ssl_closed, Socket} ->
exit({test_failed, connection_closed});
{ssl_error, Socket, Reason} ->
- ct:fail({ssl_error, Reason})
+ ct:fail({ssl_error, Reason});
+ {Socket, {data, Data}} when is_port(Socket) ->
+ case Module:Function([list_to_binary(Data) | Args]) of
+ {ok, Parsed} ->
+ port_handle_http_msg(Parsed, State);
+ {_, whole_body, _} when HeadRequest =:= "HEAD" ->
+ State#state{body = <<>>};
+ NewMFA ->
+ request(State#state{mfa = NewMFA}, TimeOut)
+ end;
+ {Socket, closed} when Function =:= whole_body ->
+ State#state{body = hd(Args)};
+ {Socket, closed} ->
+ exit({test_failed, connection_closed})
after TimeOut ->
ct:pal("~p ~w[~w]request -> timeout"
- "~n", [self(), ?MODULE, ?LINE]),
+ "~p~n", [self(), ?MODULE, ?LINE, Args]),
ct:fail(connection_timed_out)
end.
+
+port_handle_http_msg({Version, StatusCode, ReasonPharse, Headers, Body}, State) ->
+ State#state{status_line = {Version,
+ StatusCode,
+ ReasonPharse},
+ headers = Headers,
+ body = Body}.
+
+
handle_http_msg({Version, StatusCode, ReasonPharse, Headers, Body},
State = #state{request = RequestStr}) ->
case is_expect(RequestStr) of
diff --git a/lib/inets/test/inets.spec b/lib/inets/test/inets.spec
index ed102f8219..6cb3d6526c 100644
--- a/lib/inets/test/inets.spec
+++ b/lib/inets/test/inets.spec
@@ -1 +1,3 @@
-{suites,"../inets_test",all}.
+{suites,"../inets_test", all}.
+{skip_suites, "../inets_test", [httpd_bench_SUITE],
+ "Benchmarks run separately"}.
diff --git a/lib/inets/test/inets_SUITE.erl b/lib/inets/test/inets_SUITE.erl
index 38b8229389..e7964ff7f1 100644
--- a/lib/inets/test/inets_SUITE.erl
+++ b/lib/inets/test/inets_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -41,9 +41,7 @@ groups() ->
[{services_test, [],
[start_inets,
start_httpc,
- start_httpd,
- start_ftpc,
- start_tftpd
+ start_httpd
]},
{app_test, [], [app, appup]}].
@@ -213,7 +211,6 @@ start_httpd(Config) when is_list(Config) ->
true = lists:member(Pid0, Pids0),
[_|_] = inets:services_info(),
inets:stop(httpd, Pid0),
- ct:sleep(500),
Pids1 = [ServicePid || {_, ServicePid} <- inets:services()],
false = lists:member(Pid0, Pids1),
{ok, Pid0b} =
@@ -222,7 +219,6 @@ start_httpd(Config) when is_list(Config) ->
true = lists:member(Pid0b, Pids0b),
[_|_] = inets:services_info(),
inets:stop(httpd, Pid0b),
- ct:sleep(500),
Pids1 = [ServicePid || {_, ServicePid} <- inets:services()],
false = lists:member(Pid0b, Pids1),
{ok, Pid1} =
@@ -300,79 +296,6 @@ start_httpd(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
-start_ftpc(doc) ->
- [{doc, "Start/stop of ftpc service"}];
-start_ftpc(Config0) when is_list(Config0) ->
- process_flag(trap_exit, true),
- ok = inets:start(),
- case ftp_SUITE:init_per_suite(Config0) of
- {skip, _} = Skip ->
- Skip;
- Config ->
- FtpdHost = proplists:get_value(ftpd_host,Config),
- {ok, Pid0} = inets:start(ftpc, [{host, FtpdHost}]),
- Pids0 = [ServicePid || {_, ServicePid} <-
- inets:services()],
- true = lists:member(Pid0, Pids0),
- [_|_] = inets:services_info(),
- inets:stop(ftpc, Pid0),
- ct:sleep(100),
- Pids1 = [ServicePid || {_, ServicePid} <-
- inets:services()],
- false = lists:member(Pid0, Pids1),
- {ok, Pid1} =
- inets:start(ftpc, [{host, FtpdHost}], stand_alone),
- Pids2 = [ServicePid || {_, ServicePid} <-
- inets:services()],
- false = lists:member(Pid1, Pids2),
- ok = inets:stop(stand_alone, Pid1),
- receive
- {'EXIT', Pid1, shutdown} ->
- ok
- after 100 ->
- ct:fail(stand_alone_not_shutdown)
- end,
- ok = inets:stop(),
- catch ftp_SUITE:end_per_SUITE(Config)
- end.
-
-%%-------------------------------------------------------------------------
-
-start_tftpd() ->
- [{doc, "Start/stop of tfpd service"}].
-start_tftpd(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- ok = inets:start(),
- {ok, Pid0} = inets:start(tftpd, [{host, "localhost"}, {port, 0}]),
- Pids0 = [ServicePid || {_, ServicePid} <- inets:services()],
- true = lists:member(Pid0, Pids0),
- [_|_] = inets:services_info(),
- inets:stop(tftpd, Pid0),
- ct:sleep(100),
- Pids1 = [ServicePid || {_, ServicePid} <- inets:services()],
- false = lists:member(Pid0, Pids1),
- {ok, Pid1} =
- inets:start(tftpd, [{host, "localhost"}, {port, 0}], stand_alone),
- Pids2 = [ServicePid || {_, ServicePid} <- inets:services()],
- false = lists:member(Pid1, Pids2),
- ok = inets:stop(stand_alone, Pid1),
- receive
- {'EXIT', Pid1, shutdown} ->
- ok
- after 100 ->
- ct:fail(stand_alone_not_shutdown)
- end,
- ok = inets:stop(),
- application:load(inets),
- application:set_env(inets, services, [{tftpd,[{host, "localhost"},
- {port, 0}]}]),
- ok = inets:start(),
- (?NUM_DEFAULT_SERVICES + 1) = length(inets:services()),
- application:unset_env(inets, services),
- ok = inets:stop().
-
-%%-------------------------------------------------------------------------
-
httpd_reload() ->
[{doc, "Reload httpd configuration without restarting service"}].
httpd_reload(Config) when is_list(Config) ->
diff --git a/lib/inets/test/inets_bench.spec b/lib/inets/test/inets_bench.spec
new file mode 100644
index 0000000000..19136e691b
--- /dev/null
+++ b/lib/inets/test/inets_bench.spec
@@ -0,0 +1 @@
+{suites,"../inets_test",[httpd_bench_SUITE]}.
diff --git a/lib/inets/test/inets_socketwrap_SUITE.erl b/lib/inets/test/inets_socketwrap_SUITE.erl
index 7ea7e08ed1..b88cff4e90 100644
--- a/lib/inets/test/inets_socketwrap_SUITE.erl
+++ b/lib/inets/test/inets_socketwrap_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@ suite() ->
[{ct_hooks,[ts_install_cth]}].
all() ->
- [start_httpd_fd, start_tftpd_fd].
+ [start_httpd_fd].
init_per_suite(Config) ->
case os:type() of
@@ -90,37 +90,7 @@ start_httpd_fd(Config) when is_list(Config) ->
ct:fail(open_port_failed)
end
end.
-%%-------------------------------------------------------------------------
-start_tftpd_fd() ->
- [{doc, "Start/stop of tfpd service with socket wrapper"}].
-start_tftpd_fd(Config) when is_list(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- case setup_node_info(node()) of
- {skip, _} = Skip ->
- Skip;
- {Node, NodeArg} ->
- InetPort = inets_test_lib:inet_port(node()),
- ct:pal("Node: ~p~n", [Node]),
- Wrapper = filename:join(DataDir, "setuid_socket_wrap"),
- Cmd = Wrapper ++
- " -s -tftpd_69,0:" ++ integer_to_list(InetPort)
- ++ " -p " ++ os:find_executable("erl") ++
- " -- " ++ NodeArg,
- ct:pal("cmd: ~p~n", [Cmd]),
- case open_port({spawn, Cmd}, [stderr_to_stdout]) of
- Port when is_port(Port) ->
- wait_node_up(Node, 10),
- ct:pal("~p", [rpc:call(Node, init, get_argument, [tftpd_69])]),
- ok = rpc:call(Node, inets, start, []),
- {ok, Pid} = rpc:call(Node, inets, start,
- [tftpd,[{host, "localhost"}]]),
- {ok, Info} = rpc:call(Node, tftp, info, [Pid]),
- {value,{port, InetPort}} = lists:keysearch(port, 1, Info),
- rpc:call(Node, erlang, halt, []);
- _ ->
- ct:fail(open_port_failed)
- end
- end.
+
%%-------------------------------------------------------------------------
%% Internal functions
%%-------------------------------------------------------------------------
diff --git a/lib/inets/test/inets_sup_SUITE.erl b/lib/inets/test/inets_sup_SUITE.erl
index 1e664337e6..b90d55dadf 100644
--- a/lib/inets/test/inets_sup_SUITE.erl
+++ b/lib/inets/test/inets_sup_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,8 +32,7 @@ suite() ->
].
all() ->
- [default_tree, ftpc_worker, tftpd_worker,
- httpd_config, httpd_subtree, httpd_subtree_profile,
+ [default_tree, httpd_config, httpd_subtree, httpd_subtree_profile,
httpc_subtree].
groups() ->
@@ -147,15 +146,11 @@ default_tree() ->
"in the default case."}].
default_tree(Config) when is_list(Config) ->
TopSupChildren = supervisor:which_children(inets_sup),
- 4 = length(TopSupChildren),
+ 2 = length(TopSupChildren),
{value, {httpd_sup, _, supervisor,[httpd_sup]}} =
lists:keysearch(httpd_sup, 1, TopSupChildren),
{value, {httpc_sup, _,supervisor,[httpc_sup]}} =
lists:keysearch(httpc_sup, 1, TopSupChildren),
- {value, {ftp_sup,_,supervisor,[ftp_sup]}} =
- lists:keysearch(ftp_sup, 1, TopSupChildren),
- {value, {tftp_sup,_,supervisor,[tftp_sup]}} =
- lists:keysearch(tftp_sup, 1, TopSupChildren),
HttpcSupChildren = supervisor:which_children(httpc_sup),
{value, {httpc_profile_sup,_, supervisor, [httpc_profile_sup]}} =
@@ -163,8 +158,6 @@ default_tree(Config) when is_list(Config) ->
{value, {httpc_handler_sup,_, supervisor, [httpc_handler_sup]}} =
lists:keysearch(httpc_handler_sup, 1, HttpcSupChildren),
- [] = supervisor:which_children(ftp_sup),
-
[] = supervisor:which_children(httpd_sup),
%% Default profile
@@ -172,48 +165,7 @@ default_tree(Config) when is_list(Config) ->
= supervisor:which_children(httpc_profile_sup),
[] = supervisor:which_children(httpc_handler_sup),
-
- [] = supervisor:which_children(tftp_sup),
-
- ok.
-ftpc_worker() ->
- [{doc, "Makes sure the ftp worker processes are added and removed "
- "appropriatly to/from the supervison tree."}].
-ftpc_worker(Config0) when is_list(Config0) ->
- [] = supervisor:which_children(ftp_sup),
- case ftp_SUITE:init_per_suite(Config0) of
- {skip, _} = Skip ->
- Skip;
- Config ->
- FtpdHost = proplists:get_value(ftpd_host,Config),
- {ok, Pid} = inets:start(ftpc, [{host, FtpdHost}]),
- case supervisor:which_children(ftp_sup) of
- [{_,_, worker, [ftp]}] ->
- inets:stop(ftpc, Pid),
- ct:sleep(5000),
- [] = supervisor:which_children(ftp_sup),
- catch ftp_SUITE:end_per_SUITE(Config),
- ok;
- Children ->
- catch ftp_SUITE:end_per_SUITE(Config),
- exit({unexpected_children, Children})
- end
- end.
-
-tftpd_worker() ->
- [{doc, "Makes sure the tftp sub tree is correct."}].
-tftpd_worker(Config) when is_list(Config) ->
- [] = supervisor:which_children(tftp_sup),
- {ok, Pid0} = inets:start(tftpd, [{host, inets_test_lib:hostname()},
- {port, 0}]),
- {ok, _Pid1} = inets:start(tftpd, [{host, inets_test_lib:hostname()},
- {port, 0}], stand_alone),
-
- [{_,Pid0, worker, _}] = supervisor:which_children(tftp_sup),
- inets:stop(tftpd, Pid0),
- ct:sleep(5000),
- [] = supervisor:which_children(tftp_sup),
ok.
httpd_config() ->
diff --git a/lib/inets/test/inets_test_lib.erl b/lib/inets/test/inets_test_lib.erl
index f1185f7574..1cc4e11e45 100644
--- a/lib/inets/test/inets_test_lib.erl
+++ b/lib/inets/test/inets_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
-include("inets_test_lib.hrl").
-include_lib("inets/src/http_lib/http_internal.hrl").
+-include_lib("public_key/include/public_key.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
@@ -463,8 +464,9 @@ connect_bin(essl, Host, Port, Opts0) ->
connect(ssl, Host, Port, Opts);
connect_bin(ip_comm, Host, Port, Opts0) ->
Opts = [binary, {packet, 0} | Opts0],
- connect(ip_comm, Host, Port, Opts).
-
+ connect(ip_comm, Host, Port, Opts);
+connect_bin(Type, Host, Port, Opts) ->
+ connect(Type, Host, Port, Opts).
connect_byte(SockType, Host, Port) ->
connect_byte(SockType, Host, Port, []).
@@ -477,27 +479,40 @@ connect_byte(essl, Host, Port, Opts0) ->
connect(ssl, Host, Port, Opts);
connect_byte(ip_comm, Host, Port, Opts0) ->
Opts = [{packet,0} | Opts0],
- connect(ip_comm, Host, Port, Opts).
+ connect(ip_comm, Host, Port, Opts);
+connect_byte(Type, Host, Port, Opts) ->
+ connect(Type, Host, Port, Opts).
connect(ip_comm, Host, Port, Opts) ->
gen_tcp:connect(Host, Port, Opts);
connect(ssl, Host, Port, Opts) ->
- ssl:connect(Host, Port, Opts).
+ ssl:connect(Host, Port, Opts);
+connect(openssl_port, Host, Port, Opts) ->
+ CaCertFile = proplists:get_value(cacertfile, Opts),
+ Cmd = "openssl s_client -quiet -port " ++ integer_to_list(Port) ++ " -host " ++ Host
+ ++ " -CAfile " ++ CaCertFile,
+ ct:log("openssl cmd: ~p~n", [Cmd]),
+ OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ read_junk(OpensslPort),
+ {ok, OpensslPort}.
send(ssl, Socket, Data) ->
ssl:send(Socket, Data);
send(essl, Socket, Data) ->
ssl:send(Socket, Data);
send(ip_comm,Socket,Data) ->
- gen_tcp:send(Socket,Data).
-
-
+ gen_tcp:send(Socket,Data);
+send(openssl_port, Port, Data) ->
+ true = port_command(Port, Data),
+ ok.
close(ssl,Socket) ->
catch ssl:close(Socket);
close(essl,Socket) ->
catch ssl:close(Socket);
close(ip_comm,Socket) ->
- catch gen_tcp:close(Socket).
+ catch gen_tcp:close(Socket);
+close(openssl_port, Port) ->
+ exit(Port, normal).
hours(N) -> trunc(N * 1000 * 60 * 60).
@@ -572,3 +587,166 @@ do_inet_port(Node) ->
{ok, Socket} = rpc:call(Node, gen_tcp, listen, [0, [{reuseaddr, true}]]),
{ok, Port} = rpc:call(Node, inet, port, [Socket]),
{Port, Socket}.
+
+read_junk(OpensslPort) ->
+ receive
+ {OpensslPort, _} ->
+ read_junk(OpensslPort)
+ after 500 ->
+ ok
+ end.
+hardcode_rsa_key(1) ->
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus = 23995666614853919027835084074500048897452890537492185072956789802729257783422306095699263934587064480357348855732149402060270996295002843755712064937715826848741191927820899197493902093529581182351132392364214171173881547273475904587683433713767834856230531387991145055273426806331200574039205571401702219159773947658558490957010003143162250693492642996408861265758000254664396313741422909188635443907373976005987612936763564996605457102336549804831742940035613780926178523017685712710473543251580072875247250504243621640157403744718833162626193206685233710319205099867303242759099560438381385658382486042995679707669,
+ publicExponent = 17,
+ privateExponent = 11292078406990079542510627799764728892919007311761028269626724613049062486316379339152594792746853873109340637991599718616598115903530750002688030558925094987642913848386305504703012749896273497577003478759630198199473669305165131570674557041773098755873191241407597673069847908861741446606684974777271632545629600685952292605647052193819136445675100211504432575554351515262198132231537860917084269870590492135731720141577986787033006338680118008484613510063003323516659048210893001173583018220214626635609151105287049126443102976056146630518124476470236027123782297108342869049542023328584384300970694412006494684657,
+ prime1 = 169371138592582642967021557955633494538845517070305333860805485424261447791289944610138334410987654265476540480228705481960508520379619587635662291973699651583489223555422528867090299996446070521801757353675026048850480903160224210802452555900007597342687137394192939372218903554801584969667104937092080815197,
+ prime2 = 141675062317286527042995673340952251894209529891636708844197799307963834958115010129693036021381525952081167155681637592199810112261679449166276939178032066869788822014115556349519329537177920752776047051833616197615329017439297361972726138285974555338480581117881706656603857310337984049152655480389797687577,
+ exponent1 = 119556097830058336212015217380447172615655659108450823901745048534772786676204666783627059584226579481512852103690850928442711896738555003036938088452023283470698275450886490965004917644550167427154181661417665446247398284583687678213495921811770068712485038160606780733330990744565824684470897602653233516609,
+ exponent2 = 41669135975672507953822256864985956439473391144599032012999352737636422046504414744027363535700448809435637398729893409470532385959317485048904982111185902020526124121798693043976273393287623750816484427009887116945685005129205106462566511260580751570141347387612266663707016855981760014456663376585234613993,
+ coefficient = 76837684977089699359024365285678488693966186052769523357232308621548155587515525857011429902602352279058920284048929101483304120686557782043616693940283344235057989514310975192908256494992960578961614059245280827077951132083993754797053182279229469590276271658395444955906108899267024101096069475145863928441,
+ otherPrimeInfos = asn1_NOVALUE};
+
+hardcode_rsa_key(2) ->
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus = 21343679768589700771839799834197557895311746244621307033143551583788179817796325695589283169969489517156931770973490560582341832744966317712674900833543896521418422508485833901274928542544381247956820115082240721897193055368570146764204557110415281995205343662628196075590438954399631753508888358737971039058298703003743872818150364935790613286541190842600031570570099801682794056444451081563070538409720109449780410837763602317050353477918147758267825417201591905091231778937606362076129350476690460157227101296599527319242747999737801698427160817755293383890373574621116766934110792127739174475029121017282777887777,
+ publicExponent = 17,
+ privateExponent = 18832658619343853622211588088997845201745658451136447382185486691577805721584993260814073385267196632785528033211903435807948675951440868570007265441362261636545666919252206383477878125774454042314841278013741813438699754736973658909592256273895837054592950290554290654932740253882028017801960316533503857992358685308186680144968293076156011747178275038098868263178095174694099811498968993700538293188879611375604635940554394589807673542938082281934965292051746326331046224291377703201248790910007232374006151098976879987912446997911775904329728563222485791845480864283470332826504617837402078265424772379987120023773,
+ prime1 = 146807662748886761089048448970170315054939768171908279335181627815919052012991509112344782731265837727551849787333310044397991034789843793140419387740928103541736452627413492093463231242466386868459637115999163097726153692593711599245170083315894262154838974616739452594203727376460632750934355508361223110419,
+ prime2 = 145385325050081892763917667176962991350872697916072592966410309213561884732628046256782356731057378829876640317801978404203665761131810712267778698468684631707642938779964806354584156202882543264893826268426566901882487709510744074274965029453915224310656287149777603803201831202222853023280023478269485417083,
+ exponent1 = 51814469205489445090252393754177758254684624060673510353593515699736136004585238510239335081623236845018299924941168250963996835808180162284853901555621683602965806809675350150634081614988136541809283687999704622726877773856604093851236499993845033701707873394143336209718962603456693912094478414715725803677,
+ exponent2 = 51312467664734785681382706062457526359131540440966797517556579722433606376221663384746714140373192528191755406283051201483646739222992016094510128871300458249756331334105225772206172777487956446433115153562317730076172132768497908567634716277852432109643395464627389577600646306666889302334125933506877206029,
+ coefficient = 30504662229874176232343608562807118278893368758027179776313787938167236952567905398252901545019583024374163153775359371298239336609182249464886717948407152570850677549297935773605431024166978281486607154204888016179709037883348099374995148481968169438302456074511782717758301581202874062062542434218011141540,
+ otherPrimeInfos = asn1_NOVALUE};
+hardcode_rsa_key(3) ->
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus = 25089040456112869869472694987833070928503703615633809313972554887193090845137746668197820419383804666271752525807484521370419854590682661809972833718476098189250708650325307850184923546875260207894844301992963978994451844985784504212035958130279304082438876764367292331581532569155681984449177635856426023931875082020262146075451989132180409962870105455517050416234175675478291534563995772675388370042873175344937421148321291640477650173765084699931690748536036544188863178325887393475703801759010864779559318631816411493486934507417755306337476945299570726975433250753415110141783026008347194577506976486290259135429,
+ publicExponent = 17,
+ privateExponent = 8854955455098659953931539407470495621824836570223697404931489960185796768872145882893348383311931058684147950284994536954265831032005645344696294253579799360912014817761873358888796545955974191021709753644575521998041827642041589721895044045980930852625485916835514940558187965584358347452650930302268008446431977397918214293502821599497633970075862760001650736520566952260001423171553461362588848929781360590057040212831994258783694027013289053834376791974167294527043946669963760259975273650548116897900664646809242902841107022557239712438496384819445301703021164043324282687280801738470244471443835900160721870265,
+ prime1 = 171641816401041100605063917111691927706183918906535463031548413586331728772311589438043965564336865070070922328258143588739626712299625805650832695450270566547004154065267940032684307994238248203186986569945677705100224518137694769557564475390859269797990555863306972197736879644001860925483629009305104925823,
+ prime2 =146170909759497809922264016492088453282310383272504533061020897155289106805616042710009332510822455269704884883705830985184223718261139908416790475825625309815234508695722132706422885088219618698987115562577878897003573425367881351537506046253616435685549396767356003663417208105346307649599145759863108910523,
+ exponent1 = 60579464612132153154728441333538327425711971378777222246428851853999433684345266860486105493295364142377972586444050678378691780811632637288529186629507258781295583787741625893888579292084087601124818789392592131211843947578009918667375697196773859928702549128225990187436545756706539150170692591519448797349,
+ exponent2 = 137572620950115585809189662580789132500998007785886619351549079675566218169991569609420548245479957900898715184664311515467504676010484619686391036071176762179044243478326713135456833024206699951987873470661533079532774988581535389682358631768109586527575902839864474036157372334443583670210960715165278974609,
+ coefficient = 15068630434698373319269196003209754243798959461311186548759287649485250508074064775263867418602372588394608558985183294561315208336731894947137343239541687540387209051236354318837334154993136528453613256169847839789803932725339395739618592522865156272771578671216082079933457043120923342632744996962853951612,
+ otherPrimeInfos = asn1_NOVALUE};
+hardcode_rsa_key(4) ->
+ #'RSAPrivateKey'{
+ version ='two-prime',
+ modulus = 28617237755030755643854803617273584643843067580642149032833640135949799721163782522787597288521902619948688786051081993247908700824196122780349730169173433743054172191054872553484065655968335396052034378669869864779940355219732200954630251223541048434478476115391643898092650304645086338265930608997389611376417609043761464100338332976874588396803891301015812818307951159858145399281035705713082131199940309445719678087542976246147777388465712394062188801177717719764254900022006288880246925156931391594131839991579403409541227225173269459173129377291869028712271737734702830877034334838181789916127814298794576266389,
+ publicExponent = 17,
+ privateExponent = 26933870828264240605980991639786903194205240075898493207372837775011576208154148256741268036255908348187001210401018346586267012540419880263858569570986761169933338532757527109161473558558433313931326474042230460969355628442100895016122589386862163232450330461545076609969553227901257730132640573174013751883368376011370428995523268034111482031427024082719896108094847702954695363285832195666458915142143884210891427766607838346722974883433132513540317964796373298134261669479023445911856492129270184781873446960437310543998533283339488055776892320162032014809906169940882070478200435536171854883284366514852906334641,
+ prime1 = 177342190816702392178883147766999616783253285436834252111702533617098994535049411784501174309695427674025956656849179054202187436663487378682303508229883753383891163725167367039879190685255046547908384208614573353917213168937832054054779266431207529839577747601879940934691505396807977946728204814969824442867,
+ prime2 = 161367340863680900415977542864139121629424927689088951345472941851682581254789586032968359551717004797621579428672968948552429138154521719743297455351687337112710712475376510559020211584326773715482918387500187602625572442687231345855402020688502483137168684570635690059254866684191216155909970061793538842967,
+ exponent1 = 62591361464718491357252875682470452982324688977706206627659717747211409835899792394529826226951327414362102349476180842659595565881230839534930649963488383547255704844176717778780890830090016428673547367746320007264898765507470136725216211681602657590439205035957626212244060728285168687080542875871702744541,
+ exponent2 = 28476589564178982426348978152495139111074987239250991413906989738532220221433456358759122273832412611344984605059935696803369847909621479954699550944415412431654831613301737157474154985469430655673456186029444871051571607533040825739188591886206320553618003159523945304574388238386685203984112363845918619347,
+ coefficient = 34340318160575773065401929915821192439103777558577109939078671096408836197675640654693301707202885840826672396546056002756167635035389371579540325327619480512374920136684787633921441576901246290213545161954865184290700344352088099063404416346968182170720521708773285279884132629954461545103181082503707725012,
+ otherPrimeInfos = asn1_NOVALUE};
+
+hardcode_rsa_key(5) ->
+ #'RSAPrivateKey'{
+ version= 'two-prime',
+ modulus = 26363170152814518327068346871197765236382539835597898797762992537312221863402655353436079974302838986536256364057947538018476963115004626096654613827403121905035011992899481598437933532388248462251770039307078647864188314916665766359828262009578648593031111569685489178543405615478739906285223620987558499488359880003693226535420421293716164794046859453204135383236667988765227190694994861629971618548127529849059769249520775574008363789050621665120207265361610436965088511042779948238320901918522125988916609088415989475825860046571847719492980547438560049874493788767083330042728150253120940100665370844282489982633,
+ publicExponent = 17,
+ privateExponent = 10855423004100095781734025182257903332628104638187370093196526338893267826106975733767797636477639582691399679317978398007608161282648963686857782164224814902073240232370374775827384395689278778574258251479385325591136364965685903795223402003944149420659869469870495544106108194608892902588033255700759382142132115013969680562678811046675523365751498355532768935784747314021422035957153013494814430893022253205880275287307995039363642554998244274484818208792520243113824379110193356010059999642946040953102866271737127640405568982049887176990990501963784502429481034227543991366980671390566584211881030995602076468001,
+ prime1 =163564135568104310461344551909369650951960301778977149705601170951529791054750122905880591964737953456660497440730575925978769763154927541340839715938951226089095007207042122512586007411328664679011914120351043948122025612160733403945093961374276707993674792189646478659304624413958625254578122842556295400709,
+ prime2 = 161179405627326572739107057023381254841260287988433675196680483761672455172873134522398837271764104320975746111042211695289319249471386600030523328069395763313848583139553961129874895374324504709512019736703349829576024049432816885712623938437949550266365056310544300920756181033500610331519029869549723159637,
+ exponent1 = 115457036871603042678596154288966812436677860079277988027483179495197499568058910286503947269226790675289762899339230065396778656344654735064122152427494983121714122734382674714766593466820233891067233496718383963380253373289929461608301619793607087995535147427985749641862087821617853120878674947686796753441,
+ exponent2 = 142217122612346975946270932667689342506994371754500301644129838613240401623123353990351915239791856753802128921507833848784693455415929352968108818884760967629866396887841730408713142977345151214275311532385308673155315337734838428569962298621720191411498579097539089047726042088382891468987379296661520434973,
+ coefficient = 40624877259097915043489529504071755460170951428490878553842519165800720914888257733191322215286203357356050737713125202129282154441426952501134581314792133018830748896123382106683994268028624341502298766844710276939303555637478596035491641473828661569958212421472263269629366559343208764012473880251174832392,
+ otherPrimeInfos = asn1_NOVALUE};
+hardcode_rsa_key(6) ->
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus = 22748888494866396715768692484866595111939200209856056370972713870125588774286266397044592487895293134537316190976192161177144143633669641697309689280475257429554879273045671863645233402796222694405634510241820106743648116753479926387434021380537483429927516962909367257212902212159798399531316965145618774905828756510318897899298783143203190245236381440043169622358239226123652592179006905016804587837199618842875361941208299410035232803124113612082221121192550063791073372276763648926636149384299189072950588522522800393261949880796214514243704858378436010975184294077063518776479282353562934591448646412389762167039,
+ publicExponent = 17,
+ privateExponent = 6690849557313646092873144848490175032923294179369428344403739373566349639495960705013115437616262686628622409110644753287395336362844012263914614494257428655751435080307550548130951000822418439531068973600535325512837681398082331290421770994275730420566916753796872722709677121223470117509210872101652580854566448661533030419787125312956120661097410038933324613372774190658239039998357548275441758790939430824924502690997433186652165055694361752689819209062683281242276039100201318203707142383491769671330743466041394101421674581185260900666085723130684175548215193875544802254923825103844262661010117443222587769713,
+ prime1 = 164748737139489923768181260808494855987398781964531448608652166632780898215212977127034263859971474195908846263894581556691971503119888726148555271179103885786024920582830105413607436718060544856016793981261118694063993837665813285582095833772675610567592660039821387740255651489996976698808018635344299728063,
+ prime2 = 138082323967104548254375818343885141517788525705334488282154811252858957969378263753268344088034079842223206527922445018725900110643394926788280539200323021781309918753249061620424428562366627334409266756720941754364262467100514166396917565961434203543659974860389803369482625510495464845206228470088664021953,
+ exponent1 = 19382204369351755737433089506881747763223386113474288071606137250915399790025056132592266336467232258342217207517009594904937823896457497193947678962247515974826461245038835931012639613889475865413740468383661022831058098548919210068481862796785365949128548239978986792971253116470232552800943368864035262125,
+ exponent2 = 48734937870742781736838524121371226418043009072470995864289933383361985165662916618800592031070851709019955245149098241903258862580021738866451955011878713569874088971734962924855680669070574353320917678842685325069739694270769705787147376221682660074232932303666989424523279591939575827719845342384234360689,
+ coefficient = 81173034184183681160439870161505779100040258708276674532866007896310418779840630960490793104541748007902477778658270784073595697910785917474138815202903114440800310078464142273778315781957021015333260021813037604142367434117205299831740956310682461174553260184078272196958146289378701001596552915990080834227,
+ otherPrimeInfos = asn1_NOVALUE}.
+
+gen_pem_config_files(#{server_config := ServerConf,
+ client_config := ClientConf}, ClientBase, ServerBase) ->
+
+ ServerCaCertFile = ServerBase ++ "_server_cacerts.pem",
+ ServerCertFile = ServerBase ++ "_server_cert.pem",
+ ServerKeyFile = ServerBase ++ "_server_key.pem",
+
+ ClientCaCertFile = ClientBase ++ "_client_cacerts.pem",
+ ClientCertFile = ClientBase ++ "_client_cert.pem",
+ ClientKeyFile = ClientBase ++ "_client_key.pem",
+
+ do_gen_pem_config_files(ServerConf,
+ ServerCertFile,
+ ServerKeyFile,
+ ServerCaCertFile),
+ do_gen_pem_config_files(ClientConf,
+ ClientCertFile,
+ ClientKeyFile,
+ ClientCaCertFile),
+ [{server_config, [{certfile, ServerCertFile},
+ {keyfile, ServerKeyFile}, {cacertfile, ServerCaCertFile}]},
+ {client_config, [{certfile, ClientCertFile},
+ {keyfile, ClientKeyFile}, {cacertfile, ClientCaCertFile}]}].
+extensions(Exts) ->
+ [extension(Ext) || Ext <- Exts].
+
+
+do_gen_pem_config_files(Config, CertFile, KeyFile, CAFile) ->
+ CAs = proplists:get_value(cacerts, Config),
+ Cert = proplists:get_value(cert, Config),
+ Key = proplists:get_value(key, Config),
+ der_to_pem(CertFile, [cert_entry(Cert)]),
+ der_to_pem(KeyFile, [key_entry(Key)]),
+ der_to_pem(CAFile, ca_entries(CAs)).
+
+cert_entry(Cert) ->
+ {'Certificate', Cert, not_encrypted}.
+
+key_entry({'RSAPrivateKey', DERKey}) ->
+ {'RSAPrivateKey', DERKey, not_encrypted};
+key_entry({'DSAPrivateKey', DERKey}) ->
+ {'DSAPrivateKey', DERKey, not_encrypted};
+key_entry({'ECPrivateKey', DERKey}) ->
+ {'ECPrivateKey', DERKey, not_encrypted}.
+
+ca_entries(CAs) ->
+ [{'Certificate', CACert, not_encrypted} || CACert <- CAs].
+
+extension({_, undefined}) ->
+ [];
+extension({basic_constraints, Data}) ->
+ case Data of
+ default ->
+ #'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue = #'BasicConstraints'{cA=true},
+ critical=true};
+ false ->
+ [];
+ Len when is_integer(Len) ->
+ #'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue = #'BasicConstraints'{cA=true, pathLenConstraint = Len},
+ critical = true};
+ _ ->
+ #'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue = Data}
+ end;
+extension({key_usage, Value}) ->
+ #'Extension'{extnID = ?'id-ce-keyUsage',
+ extnValue = Value,
+ critical = false};
+extension({subject_alt, Hostname}) ->
+ #'Extension'{extnID = ?'id-ce-subjectAltName',
+ extnValue = [{dNSName, Hostname}],
+ critical = false};
+extension({Id, Data, Critical}) ->
+ #'Extension'{extnID = Id, extnValue = Data, critical = Critical}.
+
+der_to_pem(File, Entries) ->
+ PemBin = public_key:pem_encode(Entries),
+ file:write_file(File, PemBin).
diff --git a/lib/inets/test/make_certs.erl b/lib/inets/test/make_certs.erl
new file mode 100644
index 0000000000..7215a59823
--- /dev/null
+++ b/lib/inets/test/make_certs.erl
@@ -0,0 +1,530 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2007-2015. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(make_certs).
+-compile([export_all]).
+
+%-export([all/1, all/2, rootCA/2, intermediateCA/3, endusers/3, enduser/3, revoke/3, gencrl/2, verify/3]).
+
+-record(config, {commonName,
+ organizationalUnitName = "Erlang OTP",
+ organizationName = "Ericsson AB",
+ localityName = "Stockholm",
+ countryName = "SE",
+ emailAddress = "[email protected]",
+ default_bits = 2048,
+ v2_crls = true,
+ ecc_certs = false,
+ issuing_distribution_point = false,
+ crl_port = 8000,
+ openssl_cmd = "openssl"}).
+
+
+default_config() ->
+ #config{}.
+
+make_config(Args) ->
+ make_config(Args, #config{}).
+
+make_config([], C) ->
+ C;
+make_config([{organizationalUnitName, Name}|T], C) when is_list(Name) ->
+ make_config(T, C#config{organizationalUnitName = Name});
+make_config([{organizationName, Name}|T], C) when is_list(Name) ->
+ make_config(T, C#config{organizationName = Name});
+make_config([{localityName, Name}|T], C) when is_list(Name) ->
+ make_config(T, C#config{localityName = Name});
+make_config([{countryName, Name}|T], C) when is_list(Name) ->
+ make_config(T, C#config{countryName = Name});
+make_config([{emailAddress, Name}|T], C) when is_list(Name) ->
+ make_config(T, C#config{emailAddress = Name});
+make_config([{default_bits, Bits}|T], C) when is_integer(Bits) ->
+ make_config(T, C#config{default_bits = Bits});
+make_config([{v2_crls, Bool}|T], C) when is_boolean(Bool) ->
+ make_config(T, C#config{v2_crls = Bool});
+make_config([{crl_port, Port}|T], C) when is_integer(Port) ->
+ make_config(T, C#config{crl_port = Port});
+make_config([{ecc_certs, Bool}|T], C) when is_boolean(Bool) ->
+ make_config(T, C#config{ecc_certs = Bool});
+make_config([{issuing_distribution_point, Bool}|T], C) when is_boolean(Bool) ->
+ make_config(T, C#config{issuing_distribution_point = Bool});
+make_config([{openssl_cmd, Cmd}|T], C) when is_list(Cmd) ->
+ make_config(T, C#config{openssl_cmd = Cmd}).
+
+
+all([DataDir, PrivDir]) ->
+ all(DataDir, PrivDir).
+
+all(DataDir, PrivDir) ->
+ all(DataDir, PrivDir, #config{}).
+
+all(DataDir, PrivDir, C) when is_list(C) ->
+ all(DataDir, PrivDir, make_config(C));
+all(DataDir, PrivDir, C = #config{}) ->
+ ok = filelib:ensure_dir(filename:join(PrivDir, "erlangCA")),
+ create_rnd(DataDir, PrivDir), % For all requests
+ rootCA(PrivDir, "erlangCA", C),
+ intermediateCA(PrivDir, "otpCA", "erlangCA", C),
+ endusers(PrivDir, "otpCA", ["client", "server", "revoked", "a.server", "b.server"], C),
+ endusers(PrivDir, "erlangCA", ["localhost"], C),
+ %% Create keycert files
+ SDir = filename:join([PrivDir, "server"]),
+ SC = filename:join([SDir, "cert.pem"]),
+ SK = filename:join([SDir, "key.pem"]),
+ SKC = filename:join([SDir, "keycert.pem"]),
+ append_files([SK, SC], SKC),
+ CDir = filename:join([PrivDir, "client"]),
+ CC = filename:join([CDir, "cert.pem"]),
+ CK = filename:join([CDir, "key.pem"]),
+ CKC = filename:join([CDir, "keycert.pem"]),
+ append_files([CK, CC], CKC),
+ RDir = filename:join([PrivDir, "revoked"]),
+ RC = filename:join([RDir, "cert.pem"]),
+ RK = filename:join([RDir, "key.pem"]),
+ RKC = filename:join([RDir, "keycert.pem"]),
+ revoke(PrivDir, "otpCA", "revoked", C),
+ append_files([RK, RC], RKC),
+ remove_rnd(PrivDir),
+ {ok, C}.
+
+append_files(FileNames, ResultFileName) ->
+ {ok, ResultFile} = file:open(ResultFileName, [write]),
+ do_append_files(FileNames, ResultFile).
+
+do_append_files([], RF) ->
+ ok = file:close(RF);
+do_append_files([F|Fs], RF) ->
+ {ok, Data} = file:read_file(F),
+ ok = file:write(RF, Data),
+ do_append_files(Fs, RF).
+
+rootCA(Root, Name, C) ->
+ create_ca_dir(Root, Name, ca_cnf(C#config{commonName = Name})),
+ create_self_signed_cert(Root, Name, req_cnf(C#config{commonName = Name}), C),
+ file:copy(filename:join([Root, Name, "cert.pem"]), filename:join([Root, Name, "cacerts.pem"])),
+ gencrl(Root, Name, C).
+
+intermediateCA(Root, CA, ParentCA, C) ->
+ create_ca_dir(Root, CA, ca_cnf(C#config{commonName = CA})),
+ CARoot = filename:join([Root, CA]),
+ CnfFile = filename:join([CARoot, "req.cnf"]),
+ file:write_file(CnfFile, req_cnf(C#config{commonName = CA})),
+ KeyFile = filename:join([CARoot, "private", "key.pem"]),
+ ReqFile = filename:join([CARoot, "req.pem"]),
+ create_req(Root, CnfFile, KeyFile, ReqFile, C),
+ CertFile = filename:join([CARoot, "cert.pem"]),
+ sign_req(Root, ParentCA, "ca_cert", ReqFile, CertFile, C),
+ CACertsFile = filename:join(CARoot, "cacerts.pem"),
+ file:copy(filename:join([Root, ParentCA, "cacerts.pem"]), CACertsFile),
+ %% append this CA's cert to the cacerts file
+ {ok, Bin} = file:read_file(CertFile),
+ {ok, FD} = file:open(CACertsFile, [append]),
+ file:write(FD, ["\n", Bin]),
+ file:close(FD),
+ gencrl(Root, CA, C).
+
+endusers(Root, CA, Users, C) ->
+ [enduser(Root, CA, User, C) || User <- Users].
+
+enduser(Root, CA, User, C) ->
+ UsrRoot = filename:join([Root, User]),
+ file:make_dir(UsrRoot),
+ CnfFile = filename:join([UsrRoot, "req.cnf"]),
+ file:write_file(CnfFile, req_cnf(C#config{commonName = User})),
+ KeyFile = filename:join([UsrRoot, "key.pem"]),
+ ReqFile = filename:join([UsrRoot, "req.pem"]),
+ create_req(Root, CnfFile, KeyFile, ReqFile, C),
+ %create_req(Root, CnfFile, KeyFile, ReqFile),
+ CertFileAllUsage = filename:join([UsrRoot, "cert.pem"]),
+ sign_req(Root, CA, "user_cert", ReqFile, CertFileAllUsage, C),
+ CertFileDigitalSigOnly = filename:join([UsrRoot, "digital_signature_only_cert.pem"]),
+ sign_req(Root, CA, "user_cert_digital_signature_only", ReqFile, CertFileDigitalSigOnly, C),
+ CACertsFile = filename:join(UsrRoot, "cacerts.pem"),
+ file:copy(filename:join([Root, CA, "cacerts.pem"]), CACertsFile),
+ ok.
+
+revoke(Root, CA, User, C) ->
+ UsrCert = filename:join([Root, User, "cert.pem"]),
+ CACnfFile = filename:join([Root, CA, "ca.cnf"]),
+ Cmd = [C#config.openssl_cmd, " ca"
+ " -revoke ", UsrCert,
+ [" -crl_reason keyCompromise" || C#config.v2_crls ],
+ " -config ", CACnfFile],
+ Env = [{"ROOTDIR", filename:absname(Root)}],
+ cmd(Cmd, Env),
+ gencrl(Root, CA, C).
+
+gencrl(Root, CA, C) ->
+ CACnfFile = filename:join([Root, CA, "ca.cnf"]),
+ CACRLFile = filename:join([Root, CA, "crl.pem"]),
+ Cmd = [C#config.openssl_cmd, " ca"
+ " -gencrl ",
+ " -crlhours 24",
+ " -out ", CACRLFile,
+ " -config ", CACnfFile],
+ Env = [{"ROOTDIR", filename:absname(Root)}],
+ cmd(Cmd, Env).
+
+verify(Root, CA, User, C) ->
+ CAFile = filename:join([Root, User, "cacerts.pem"]),
+ CACRLFile = filename:join([Root, CA, "crl.pem"]),
+ CertFile = filename:join([Root, User, "cert.pem"]),
+ Cmd = [C#config.openssl_cmd, " verify"
+ " -CAfile ", CAFile,
+ " -CRLfile ", CACRLFile, %% this is undocumented, but seems to work
+ " -crl_check ",
+ CertFile],
+ Env = [{"ROOTDIR", filename:absname(Root)}],
+ try cmd(Cmd, Env) catch
+ exit:{eval_cmd, _, _} ->
+ invalid
+ end.
+
+create_self_signed_cert(Root, CAName, Cnf, C = #config{ecc_certs = true}) ->
+ CARoot = filename:join([Root, CAName]),
+ CnfFile = filename:join([CARoot, "req.cnf"]),
+ file:write_file(CnfFile, Cnf),
+ KeyFile = filename:join([CARoot, "private", "key.pem"]),
+ CertFile = filename:join([CARoot, "cert.pem"]),
+ Cmd = [C#config.openssl_cmd, " ecparam"
+ " -out ", KeyFile,
+ " -name secp521r1 ",
+ %" -name sect283k1 ",
+ " -genkey "],
+ Env = [{"ROOTDIR", filename:absname(Root)}],
+ cmd(Cmd, Env),
+
+ Cmd2 = [C#config.openssl_cmd, " req"
+ " -new"
+ " -x509"
+ " -config ", CnfFile,
+ " -key ", KeyFile,
+ " -outform PEM ",
+ " -out ", CertFile],
+ cmd(Cmd2, Env);
+create_self_signed_cert(Root, CAName, Cnf, C) ->
+ CARoot = filename:join([Root, CAName]),
+ CnfFile = filename:join([CARoot, "req.cnf"]),
+ file:write_file(CnfFile, Cnf),
+ KeyFile = filename:join([CARoot, "private", "key.pem"]),
+ CertFile = filename:join([CARoot, "cert.pem"]),
+ Cmd = [C#config.openssl_cmd, " req"
+ " -new"
+ " -x509"
+ " -config ", CnfFile,
+ " -keyout ", KeyFile,
+ " -outform PEM",
+ " -out ", CertFile],
+ Env = [{"ROOTDIR", filename:absname(Root)}],
+ cmd(Cmd, Env).
+
+
+create_ca_dir(Root, CAName, Cnf) ->
+ CARoot = filename:join([Root, CAName]),
+ ok = filelib:ensure_dir(CARoot),
+ file:make_dir(CARoot),
+ create_dirs(CARoot, ["certs", "crl", "newcerts", "private"]),
+ create_rnd(Root, filename:join([CAName, "private"])),
+ create_files(CARoot, [{"serial", "01\n"},
+ {"crlnumber", "01"},
+ {"index.txt", ""},
+ {"ca.cnf", Cnf}]).
+
+create_req(Root, CnfFile, KeyFile, ReqFile, C = #config{ecc_certs = true}) ->
+ Cmd = [C#config.openssl_cmd, " ecparam"
+ " -out ", KeyFile,
+ " -name secp521r1 ",
+ %" -name sect283k1 ",
+ " -genkey "],
+ Env = [{"ROOTDIR", filename:absname(Root)}],
+ cmd(Cmd, Env),
+ Cmd2 = [C#config.openssl_cmd, " req"
+ " -new ",
+ " -key ", KeyFile,
+ " -outform PEM ",
+ " -out ", ReqFile,
+ " -config ", CnfFile],
+ cmd(Cmd2, Env);
+ %fix_key_file(KeyFile).
+create_req(Root, CnfFile, KeyFile, ReqFile, C) ->
+ Cmd = [C#config.openssl_cmd, " req"
+ " -new"
+ " -config ", CnfFile,
+ " -outform PEM ",
+ " -keyout ", KeyFile,
+ " -out ", ReqFile],
+ Env = [{"ROOTDIR", filename:absname(Root)}],
+ cmd(Cmd, Env).
+ %fix_key_file(KeyFile).
+
+
+sign_req(Root, CA, CertType, ReqFile, CertFile, C) ->
+ CACnfFile = filename:join([Root, CA, "ca.cnf"]),
+ Cmd = [C#config.openssl_cmd, " ca"
+ " -batch"
+ " -notext"
+ " -config ", CACnfFile,
+ " -extensions ", CertType,
+ " -in ", ReqFile,
+ " -out ", CertFile],
+ Env = [{"ROOTDIR", filename:absname(Root)}],
+ cmd(Cmd, Env).
+
+%%
+%% Misc
+%%
+
+create_dirs(Root, Dirs) ->
+ lists:foreach(fun(Dir) ->
+ file:make_dir(filename:join([Root, Dir])) end,
+ Dirs).
+
+create_files(Root, NameContents) ->
+ lists:foreach(
+ fun({Name, Contents}) ->
+ file:write_file(filename:join([Root, Name]), Contents) end,
+ NameContents).
+
+create_rnd(FromDir, ToDir) ->
+ From = filename:join([FromDir, "RAND"]),
+ To = filename:join([ToDir, "RAND"]),
+ file:copy(From, To).
+
+remove_rnd(Dir) ->
+ File = filename:join([Dir, "RAND"]),
+ file:delete(File).
+
+cmd(Cmd, Env) ->
+ FCmd = lists:flatten(Cmd),
+ Port = open_port({spawn, FCmd}, [stream, eof, exit_status, stderr_to_stdout,
+ {env, Env}]),
+ eval_cmd(Port, FCmd).
+
+eval_cmd(Port, Cmd) ->
+ receive
+ {Port, {data, _}} ->
+ eval_cmd(Port, Cmd);
+ {Port, eof} ->
+ ok
+ end,
+ receive
+ {Port, {exit_status, 0}} ->
+ ok;
+ {Port, {exit_status, Status}} ->
+ exit({eval_cmd, Cmd, Status})
+ after 0 ->
+ ok
+ end.
+
+%%
+%% Contents of configuration files
+%%
+
+req_cnf(C) ->
+ ["# Purpose: Configuration for requests (end users and CAs)."
+ "\n"
+ "ROOTDIR = $ENV::ROOTDIR\n"
+ "\n"
+
+ "[req]\n"
+ "input_password = secret\n"
+ "output_password = secret\n"
+ "default_bits = ", integer_to_list(C#config.default_bits), "\n"
+ "RANDFILE = $ROOTDIR/RAND\n"
+ "encrypt_key = no\n"
+ "default_md = md5\n"
+ "#string_mask = pkix\n"
+ "x509_extensions = ca_ext\n"
+ "prompt = no\n"
+ "distinguished_name= name\n"
+ "\n"
+
+ "[name]\n"
+ "commonName = ", C#config.commonName, "\n"
+ "organizationalUnitName = ", C#config.organizationalUnitName, "\n"
+ "organizationName = ", C#config.organizationName, "\n"
+ "localityName = ", C#config.localityName, "\n"
+ "countryName = ", C#config.countryName, "\n"
+ "emailAddress = ", C#config.emailAddress, "\n"
+ "\n"
+
+ "[ca_ext]\n"
+ "basicConstraints = critical, CA:true\n"
+ "keyUsage = cRLSign, keyCertSign\n"
+ "subjectKeyIdentifier = hash\n"
+ "subjectAltName = email:copy\n"].
+
+ca_cnf(C = #config{issuing_distribution_point = true}) ->
+ ["# Purpose: Configuration for CAs.\n"
+ "\n"
+ "ROOTDIR = $ENV::ROOTDIR\n"
+ "default_ca = ca\n"
+ "\n"
+
+ "[ca]\n"
+ "dir = $ROOTDIR/", C#config.commonName, "\n"
+ "certs = $dir/certs\n"
+ "crl_dir = $dir/crl\n"
+ "database = $dir/index.txt\n"
+ "new_certs_dir = $dir/newcerts\n"
+ "certificate = $dir/cert.pem\n"
+ "serial = $dir/serial\n"
+ "crl = $dir/crl.pem\n",
+ ["crlnumber = $dir/crlnumber\n" || C#config.v2_crls],
+ "private_key = $dir/private/key.pem\n"
+ "RANDFILE = $dir/private/RAND\n"
+ "\n"
+ "x509_extensions = user_cert\n",
+ ["crl_extensions = crl_ext\n" || C#config.v2_crls],
+ "unique_subject = no\n"
+ "default_days = 3600\n"
+ "default_md = md5\n"
+ "preserve = no\n"
+ "policy = policy_match\n"
+ "\n"
+
+ "[policy_match]\n"
+ "commonName = supplied\n"
+ "organizationalUnitName = optional\n"
+ "organizationName = match\n"
+ "countryName = match\n"
+ "localityName = match\n"
+ "emailAddress = supplied\n"
+ "\n"
+
+ "[crl_ext]\n"
+ "authorityKeyIdentifier=keyid:always,issuer:always\n",
+ ["issuingDistributionPoint=critical, @idpsec\n" || C#config.issuing_distribution_point],
+
+ "[idpsec]\n"
+ "fullname=URI:http://localhost:8000/",C#config.commonName,"/crl.pem\n"
+
+ "[user_cert]\n"
+ "basicConstraints = CA:false\n"
+ "keyUsage = nonRepudiation, digitalSignature, keyEncipherment\n"
+ "subjectKeyIdentifier = hash\n"
+ "authorityKeyIdentifier = keyid,issuer:always\n"
+ "subjectAltName = email:copy\n"
+ "issuerAltName = issuer:copy\n"
+ "crlDistributionPoints=@crl_section\n"
+
+ "[crl_section]\n"
+ %% intentionally invalid
+ "URI.1=http://localhost/",C#config.commonName,"/crl.pem\n"
+ "URI.2=http://localhost:",integer_to_list(C#config.crl_port),"/",C#config.commonName,"/crl.pem\n"
+ "\n"
+
+ "[user_cert_digital_signature_only]\n"
+ "basicConstraints = CA:false\n"
+ "keyUsage = digitalSignature\n"
+ "subjectKeyIdentifier = hash\n"
+ "authorityKeyIdentifier = keyid,issuer:always\n"
+ "subjectAltName = email:copy\n"
+ "issuerAltName = issuer:copy\n"
+ "\n"
+
+ "[ca_cert]\n"
+ "basicConstraints = critical,CA:true\n"
+ "keyUsage = cRLSign, keyCertSign\n"
+ "subjectKeyIdentifier = hash\n"
+ "authorityKeyIdentifier = keyid:always,issuer:always\n"
+ "subjectAltName = email:copy\n"
+ "issuerAltName = issuer:copy\n"
+ "crlDistributionPoints=@crl_section\n"
+ ];
+
+ca_cnf(C = #config{issuing_distribution_point = false}) ->
+ ["# Purpose: Configuration for CAs.\n"
+ "\n"
+ "ROOTDIR = $ENV::ROOTDIR\n"
+ "default_ca = ca\n"
+ "\n"
+
+ "[ca]\n"
+ "dir = $ROOTDIR/", C#config.commonName, "\n"
+ "certs = $dir/certs\n"
+ "crl_dir = $dir/crl\n"
+ "database = $dir/index.txt\n"
+ "new_certs_dir = $dir/newcerts\n"
+ "certificate = $dir/cert.pem\n"
+ "serial = $dir/serial\n"
+ "crl = $dir/crl.pem\n",
+ ["crlnumber = $dir/crlnumber\n" || C#config.v2_crls],
+ "private_key = $dir/private/key.pem\n"
+ "RANDFILE = $dir/private/RAND\n"
+ "\n"
+ "x509_extensions = user_cert\n",
+ ["crl_extensions = crl_ext\n" || C#config.v2_crls],
+ "unique_subject = no\n"
+ "default_days = 3600\n"
+ "default_md = md5\n"
+ "preserve = no\n"
+ "policy = policy_match\n"
+ "\n"
+
+ "[policy_match]\n"
+ "commonName = supplied\n"
+ "organizationalUnitName = optional\n"
+ "organizationName = match\n"
+ "countryName = match\n"
+ "localityName = match\n"
+ "emailAddress = supplied\n"
+ "\n"
+
+ "[crl_ext]\n"
+ "authorityKeyIdentifier=keyid:always,issuer:always\n",
+ %["issuingDistributionPoint=critical, @idpsec\n" || C#config.issuing_distribution_point],
+
+ %"[idpsec]\n"
+ %"fullname=URI:http://localhost:8000/",C#config.commonName,"/crl.pem\n"
+
+ "[user_cert]\n"
+ "basicConstraints = CA:false\n"
+ "keyUsage = nonRepudiation, digitalSignature, keyEncipherment\n"
+ "subjectKeyIdentifier = hash\n"
+ "authorityKeyIdentifier = keyid,issuer:always\n"
+ "subjectAltName = email:copy\n"
+ "issuerAltName = issuer:copy\n"
+ %"crlDistributionPoints=@crl_section\n"
+
+ %%"[crl_section]\n"
+ %% intentionally invalid
+ %%"URI.1=http://localhost/",C#config.commonName,"/crl.pem\n"
+ %%"URI.2=http://localhost:",integer_to_list(C#config.crl_port),"/",C#config.commonName,"/crl.pem\n"
+ %%"\n"
+
+ "[user_cert_digital_signature_only]\n"
+ "basicConstraints = CA:false\n"
+ "keyUsage = digitalSignature\n"
+ "subjectKeyIdentifier = hash\n"
+ "authorityKeyIdentifier = keyid,issuer:always\n"
+ "subjectAltName = email:copy\n"
+ "issuerAltName = issuer:copy\n"
+ "\n"
+
+ "[ca_cert]\n"
+ "basicConstraints = critical,CA:true\n"
+ "keyUsage = cRLSign, keyCertSign\n"
+ "subjectKeyIdentifier = hash\n"
+ "authorityKeyIdentifier = keyid:always,issuer:always\n"
+ "subjectAltName = email:copy\n"
+ "issuerAltName = issuer:copy\n"
+ %"crlDistributionPoints=@crl_section\n"
+ ].
diff --git a/lib/inets/test/old_httpd_SUITE.erl b/lib/inets/test/old_httpd_SUITE.erl
deleted file mode 100644
index 172db53844..0000000000
--- a/lib/inets/test/old_httpd_SUITE.erl
+++ /dev/null
@@ -1,2347 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(old_httpd_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include("inets_test_lib.hrl").
-
--include_lib("kernel/include/file.hrl").
-
-%% Test server specific exports
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
--export([init_per_testcase/2, end_per_testcase/2,
- init_per_suite/1, end_per_suite/1]).
-
-%% Core Server tests
--export([
- ip_mod_alias/1,
- ip_mod_actions/1,
- ip_mod_security/1,
- ip_mod_auth/1,
- ip_mod_auth_api/1,
- ip_mod_auth_mnesia_api/1,
- ip_mod_htaccess/1,
- ip_mod_cgi/1,
- ip_mod_esi/1,
- ip_mod_get/1,
- ip_mod_head/1,
- ip_mod_all/1,
- ip_load_light/1,
- ip_load_medium/1,
- ip_load_heavy/1,
- ip_dos_hostname/1,
- ip_time_test/1,
- ip_block_disturbing_idle/1,
- ip_block_non_disturbing_idle/1,
- ip_block_503/1,
- ip_block_disturbing_active/1,
- ip_block_non_disturbing_active/1,
- ip_block_disturbing_active_timeout_not_released/1,
- ip_block_disturbing_active_timeout_released/1,
- ip_block_non_disturbing_active_timeout_not_released/1,
- ip_block_non_disturbing_active_timeout_released/1,
- ip_block_disturbing_blocker_dies/1,
- ip_block_non_disturbing_blocker_dies/1,
- ip_restart_no_block/1,
- ip_restart_disturbing_block/1,
- ip_restart_non_disturbing_block/1
- ]).
-
--export([
- essl_mod_alias/1,
- essl_mod_actions/1,
- essl_mod_security/1,
- essl_mod_auth/1,
- essl_mod_auth_api/1,
- essl_mod_auth_mnesia_api/1,
- essl_mod_htaccess/1,
- essl_mod_cgi/1,
- essl_mod_esi/1,
- essl_mod_get/1,
- essl_mod_head/1,
- essl_mod_all/1,
- essl_load_light/1,
- essl_load_medium/1,
- essl_load_heavy/1,
- essl_dos_hostname/1,
- essl_time_test/1,
- essl_restart_no_block/1,
- essl_restart_disturbing_block/1,
- essl_restart_non_disturbing_block/1,
- essl_block_disturbing_idle/1,
- essl_block_non_disturbing_idle/1,
- essl_block_503/1,
- essl_block_disturbing_active/1,
- essl_block_non_disturbing_active/1,
- essl_block_disturbing_active_timeout_not_released/1,
- essl_block_disturbing_active_timeout_released/1,
- essl_block_non_disturbing_active_timeout_not_released/1,
- essl_block_non_disturbing_active_timeout_released/1,
- essl_block_disturbing_blocker_dies/1,
- essl_block_non_disturbing_blocker_dies/1
- ]).
-
-%%% HTTP 1.1 tests
--export([ip_host/1, ip_chunked/1, ip_expect/1, ip_range/1,
- ip_if_test/1, ip_http_trace/1, ip_http1_1_head/1,
- ip_mod_cgi_chunked_encoding_test/1]).
-
-%%% HTTP 1.0 tests
--export([ip_head_1_0/1, ip_get_1_0/1, ip_post_1_0/1]).
-
-%%% HTTP 0.9 tests
--export([ip_get_0_9/1]).
-
-%%% Ticket tests
--export([ticket_5775/1,ticket_5865/1,ticket_5913/1,ticket_6003/1,
- ticket_7304/1]).
-
-%%% IPv6 tests
--export([ipv6_hostname_ipcomm/0, ipv6_hostname_ipcomm/1,
- ipv6_address_ipcomm/0, ipv6_address_ipcomm/1,
- ipv6_hostname_essl/0, ipv6_hostname_essl/1,
- ipv6_address_essl/0, ipv6_address_essl/1]).
-
-%% Help functions
--export([cleanup_mnesia/0, setup_mnesia/0, setup_mnesia/1]).
-
--define(IP_PORT, 8898).
--define(SSL_PORT, 8899).
--define(MAX_HEADER_SIZE, 256).
--define(IPV6_LOCAL_HOST, "0:0:0:0:0:0:0:1").
-
-%% Minutes before failed auths timeout.
--define(FAIL_EXPIRE_TIME,1).
-
-%% Seconds before successful auths timeout.
--define(AUTH_TIMEOUT,5).
-
--record(httpd_user, {user_name, password, user_data}).
--record(httpd_group, {group_name, userlist}).
-
-
-%%--------------------------------------------------------------------
-%% all(Arg) -> [Doc] | [Case] | {skip, Comment}
-%% Arg - doc | suite
-%% Doc - string()
-%% Case - atom()
-%% Name of a test case function.
-%% Comment - string()
-%% Description: Returns documentation/test cases in this test suite
-%% or a skip tuple if the platform is not supported.
-%%--------------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [
- {group, ip},
- {group, ssl},
- %%{group, http_1_1_ip},
- %%{group, http_1_0_ip},
- %%{group, http_0_9_ip},
- %%{group, ipv6},
- {group, tickets}
- ].
-
-groups() ->
- [
- {ip, [],
- [
- %%ip_mod_alias,
- ip_mod_actions,
- %%ip_mod_security,
- %% ip_mod_auth,
- %% ip_mod_auth_api,
- ip_mod_auth_mnesia_api,
- %%ip_mod_htaccess,
- %%ip_mod_cgi,
- %%ip_mod_esi,
- %%ip_mod_get,
- %%ip_mod_head,
- %%ip_mod_all,
- %% ip_load_light,
- %% ip_load_medium,
- %% ip_load_heavy,
- %%ip_dos_hostname,
- ip_time_test,
- %% Only used through load_config
- %% but we still need these tests
- %% should be cleaned up and moved to new test suite
- %%ip_restart_no_block,
- %%ip_restart_disturbing_block,
- %%ip_restart_non_disturbing_block,
- %% Tested in inets_SUITE
- %%ip_block_disturbing_idle,
- %%ip_block_non_disturbing_idle,
- ip_block_503
- %% Tested in new httpd_SUITE
- %%ip_block_disturbing_active,
- %%ip_block_non_disturbing_active,
- %%ip_block_disturbing_blocker_dies,
- %%ip_block_non_disturbing_blocker_dies
- %% No longer relevant
- %%ip_block_disturbing_active_timeout_not_released,
- %%ip_block_disturbing_active_timeout_released,
- %%ip_block_non_disturbing_active_timeout_not_released,
- %%ip_block_non_disturbing_active_timeout_released,
- ]},
- {ssl, [], [{group, essl}]},
- {essl, [],
- [
- %%essl_mod_alias,
- essl_mod_actions,
- %% essl_mod_security,
- %% essl_mod_auth,
- %% essl_mod_auth_api,
- essl_mod_auth_mnesia_api,
- %%essl_mod_htaccess,
- %%essl_mod_cgi,
- %%essl_mod_esi,
- %%essl_mod_get,
- %%essl_mod_head,
- %% essl_mod_all,
- %% essl_load_light,
- %% essl_load_medium,
- %% essl_load_heavy,
- %%essl_dos_hostname,
- essl_time_test
- %% Replaced by load_config
- %% essl_restart_no_block,
- %% essl_restart_disturbing_block,
- %% essl_restart_non_disturbing_block,
- %% essl_block_disturbing_idle,
- %% essl_block_non_disturbing_idle, essl_block_503,
- %% essl_block_disturbing_active,
- %% essl_block_non_disturbing_active,
- %% essl_block_disturbing_active_timeout_not_released,
- %% essl_block_disturbing_active_timeout_released,
- %% essl_block_non_disturbing_active_timeout_not_released,
- %% essl_block_non_disturbing_active_timeout_released,
- %% essl_block_disturbing_blocker_dies,
- %% essl_block_non_disturbing_blocker_dies
- ]},
- %% {http_1_1_ip, [],
- %% [
- %% %%ip_host, ip_chunked, ip_expect,
- %% %%ip_range,
- %% %%ip_if_test
- %% %%ip_http_trace, ip_http1_1_head,
- %% %%ip_mod_cgi_chunked_encoding_test
- %% ]},
- %%{http_1_0_ip, [],
- %%[ip_head_1_0, ip_get_1_0, ip_post_1_0]},
- %%{http_0_9_ip, [], [ip_get_0_9]},
- %% {ipv6, [], [ipv6_hostname_ipcomm, ipv6_address_ipcomm,
- %% ipv6_hostname_essl, ipv6_address_essl]},
- {tickets, [],
- [%%ticket_5775, ticket_5865,
- ticket_5913%%, ticket_6003,
- %%ticket_7304
- ]}].
-
-init_per_group(ipv6 = _GroupName, Config) ->
- case inets_test_lib:has_ipv6_support() of
- {ok, _} ->
- Config;
- _ ->
- {skip, "Host does not support IPv6"}
- end;
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- io:format(user, "init_per_suite -> entry with"
- "~n Config: ~p"
- "~n", [Config]),
-
- PrivDir = proplists:get_value(priv_dir, Config),
- SuiteTopDir = filename:join(PrivDir, ?MODULE),
- case file:make_dir(SuiteTopDir) of
- ok ->
- ok;
- {error, eexist} ->
- ok;
- Error ->
- throw({error, {failed_creating_suite_top_dir, Error}})
- end,
-
- [{has_ipv6_support, inets_test_lib:has_ipv6_support()},
- {suite_top_dir, SuiteTopDir},
- {node, node()},
- {host, inets_test_lib:hostname()},
- {address, getaddr()} | Config].
-
-
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
-
-end_per_suite(_Config) ->
- %% SuiteTopDir = proplists:get_value(suite_top_dir, Config),
- %% inets_test_lib:del_dirs(SuiteTopDir),
- ok.
-
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(Case, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initiation before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_testcase(Case, Config) ->
- NewConfig = init_per_testcase2(Case, Config),
- init_per_testcase3(Case, NewConfig).
-
-
-init_per_testcase2(Case, Config) ->
-
- %% tsp("init_per_testcase2 -> entry with"
- %% "~n Config: ~p", [Config]),
-
- IpNormal = integer_to_list(?IP_PORT) ++ ".conf",
- IpHtaccess = integer_to_list(?IP_PORT) ++ "htaccess.conf",
- SslNormal = integer_to_list(?SSL_PORT) ++ ".conf",
- SslHtaccess = integer_to_list(?SSL_PORT) ++ "htaccess.conf",
-
- DataDir = proplists:get_value(data_dir, Config),
- SuiteTopDir = proplists:get_value(suite_top_dir, Config),
-
- %% tsp("init_per_testcase2 -> "
- %% "~n SuiteDir: ~p"
- %% "~n DataDir: ~p", [SuiteTopDir, DataDir]),
-
- TcTopDir = filename:join(SuiteTopDir, Case),
- ?line ok = file:make_dir(TcTopDir),
-
- %% tsp("init_per_testcase2 -> "
- %% "~n TcTopDir: ~p", [TcTopDir]),
-
- DataSrc = filename:join([DataDir, "server_root"]),
- ServerRoot = filename:join([TcTopDir, "server_root"]),
-
- %% tsp("init_per_testcase2 -> "
- %% "~n DataSrc: ~p"
- %% "~n ServerRoot: ~p", [DataSrc, ServerRoot]),
-
- ok = file:make_dir(ServerRoot),
- ok = file:make_dir(filename:join([TcTopDir, "logs"])),
-
- NewConfig = [{tc_top_dir, TcTopDir}, {server_root, ServerRoot} | Config],
-
- %% tsp("init_per_testcase2 -> copy DataSrc to ServerRoot"),
-
- inets_test_lib:copy_dirs(DataSrc, ServerRoot),
-
- %% tsp("init_per_testcase2 -> fix cgi"),
- EnvCGI = filename:join([ServerRoot, "cgi-bin", "printenv.sh"]),
- {ok, FileInfo} = file:read_file_info(EnvCGI),
- ok = file:write_file_info(EnvCGI,
- FileInfo#file_info{mode = 8#00755}),
-
- EchoCGI = case test_server:os_type() of
- {win32, _} ->
- "cgi_echo.exe";
- _ ->
- "cgi_echo"
- end,
- CGIDir = filename:join([ServerRoot, "cgi-bin"]),
- inets_test_lib:copy_file(EchoCGI, DataDir, CGIDir),
- NewEchoCGI = filename:join([CGIDir, EchoCGI]),
- {ok, FileInfo1} = file:read_file_info(NewEchoCGI),
- ok = file:write_file_info(NewEchoCGI,
- FileInfo1#file_info{mode = 8#00755}),
-
- %% To be used by IP test cases
- %% tsp("init_per_testcase2 -> ip testcase setups"),
- create_config([{port, ?IP_PORT}, {sock_type, ip_comm} | NewConfig],
- normal_access, IpNormal),
- create_config([{port, ?IP_PORT}, {sock_type, ip_comm} | NewConfig],
- mod_htaccess, IpHtaccess),
-
- %% To be used by SSL test cases
- %% tsp("init_per_testcase2 -> ssl testcase setups"),
- SocketType =
- case atom_to_list(Case) of
- [X, $s, $s, $l | _] ->
- case X of
- $p -> ssl;
- $e -> essl
- end;
- _ ->
- ssl
- end,
-
- create_config([{port, ?SSL_PORT}, {sock_type, SocketType} | NewConfig],
- normal_access, SslNormal),
- create_config([{port, ?SSL_PORT}, {sock_type, SocketType} | NewConfig],
- mod_htaccess, SslHtaccess),
-
- %% To be used by IPv6 test cases. Case-clause is so that
- %% you can do ts:run(inets, httpd_SUITE, <test case>)
- %% for all cases except the ipv6 cases as they depend
- %% on 'test_host_ipv6_only' that will only be present
- %% when you run the whole test suite due to shortcomings
- %% of the test server.
-
- tsp("init_per_testcase2 -> maybe generate IPv6 config file(s)"),
- NewConfig2 =
- case atom_to_list(Case) of
- "ipv6_" ++ _ ->
- case (catch inets_test_lib:has_ipv6_support(NewConfig)) of
- {ok, IPv6Address0} ->
- {ok, Hostname} = inet:gethostname(),
- IPv6Address = http_transport:ipv6_name(IPv6Address0),
- create_ipv6_config([{port, ?IP_PORT},
- {sock_type, ip_comm},
- {ipv6_host, IPv6Address} |
- NewConfig],
- "ipv6_hostname_ipcomm.conf",
- Hostname),
- create_ipv6_config([{port, ?IP_PORT},
- {sock_type, ip_comm},
- {ipv6_host, IPv6Address} |
- NewConfig],
- "ipv6_address_ipcomm.conf",
- IPv6Address),
- create_ipv6_config([{port, ?SSL_PORT},
- {sock_type, essl},
- {ipv6_host, IPv6Address} |
- NewConfig],
- "ipv6_hostname_essl.conf",
- Hostname),
- create_ipv6_config([{port, ?SSL_PORT},
- {sock_type, essl},
- {ipv6_host, IPv6Address} |
- NewConfig],
- "ipv6_address_essl.conf",
- IPv6Address),
- [{ipv6_host, IPv6Address} | NewConfig];
- _ ->
- NewConfig
- end;
-
- _ ->
- NewConfig
- end,
-
- %% tsp("init_per_testcase2 -> done when"
- %% "~n NewConfig2: ~p", [NewConfig2]),
-
- NewConfig2.
-
-
-init_per_testcase3(Case, Config) ->
- tsp("init_per_testcase3(~w) -> entry with"
- "~n Config: ~p", [Case, Config]),
-
-
-%% %% Create a new fresh node to be used by the server in this test-case
-
-%% NodeName = list_to_atom(atom_to_list(Case) ++ "_httpd"),
-%% Node = inets_test_lib:start_node(NodeName),
-
- %% Clean up (we do not want this clean up in end_per_testcase
- %% if init_per_testcase crashes for some testcase it will
- %% have contaminated the environment and there will be no clean up.)
- %% This init can take a few different paths so that one crashes
- %% does not mean that all invocations will.
-
- application:unset_env(inets, services),
- application:stop(inets),
- application:stop(ssl),
- cleanup_mnesia(),
-
- %% Start initialization
- tsp("init_per_testcase3(~w) -> start init", [Case]),
-
- Dog = test_server:timetrap(inets_test_lib:minutes(10)),
- NewConfig = lists:keydelete(watchdog, 1, Config),
- TcTopDir = proplists:get_value(tc_top_dir, Config),
-
- CaseRest =
- case atom_to_list(Case) of
- "ip_mod_htaccess" ->
- inets_test_lib:start_http_server(
- filename:join(TcTopDir,
- integer_to_list(?IP_PORT) ++
- "htaccess.conf")),
- "mod_htaccess";
- "ip_" ++ Rest ->
- inets_test_lib:start_http_server(
- filename:join(TcTopDir,
- integer_to_list(?IP_PORT) ++ ".conf")),
- Rest;
- "ticket_5913" ->
- HttpdOptions =
- [{file,
- filename:join(TcTopDir,
- integer_to_list(?IP_PORT) ++ ".conf")},
- {accept_timeout,30000},
- {debug,[{exported_functions,
- [httpd_manager,httpd_request_handler]}]}],
- inets_test_lib:start_http_server(HttpdOptions);
- "ticket_"++Rest ->
- %% OTP-5913 use the new syntax of inets.config
- inets_test_lib:start_http_server([{file,
- filename:join(TcTopDir,
- integer_to_list(?IP_PORT) ++ ".conf")}]),
- Rest;
-
- [X, $s, $s, $l, $_, $m, $o, $d, $_, $h, $t, $a, $c, $c, $e, $s, $s] ->
- ?ENSURE_STARTED([crypto, public_key, ssl]),
- SslTag =
- case X of
- $p -> ssl; % Plain
- $e -> essl % Erlang based ssl
- end,
- case inets_test_lib:start_http_server_ssl(
- filename:join(TcTopDir,
- integer_to_list(?SSL_PORT) ++
- "htaccess.conf"), SslTag) of
- ok ->
- "mod_htaccess";
- Other ->
- error_logger:info_msg("Other: ~p~n", [Other]),
- {skip, "SSL does not seem to be supported"}
- end;
- [X, $s, $s, $l, $_ | Rest] ->
- ?ENSURE_STARTED([crypto, public_key, ssl]),
- SslTag =
- case X of
- $p -> ssl;
- $e -> essl
- end,
- case inets_test_lib:start_http_server_ssl(
- filename:join(TcTopDir,
- integer_to_list(?SSL_PORT) ++
- ".conf"), SslTag) of
- ok ->
- Rest;
- Other ->
- error_logger:info_msg("Other: ~p~n", [Other]),
- {skip, "SSL does not seem to be supported"}
- end;
- "ipv6_" ++ _ = TestCaseStr ->
- case inets_test_lib:has_ipv6_support() of
- {ok, _} ->
- inets_test_lib:start_http_server(
- filename:join(TcTopDir,
- TestCaseStr ++ ".conf"));
-
- _ ->
- {skip, "Host does not support IPv6"}
- end
- end,
-
- InitRes =
- case CaseRest of
- {skip, _} = Skip ->
- Skip;
- "mod_auth_" ++ _ ->
- start_mnesia(proplists:get_value(node, Config)),
- [{watchdog, Dog} | NewConfig];
- "mod_htaccess" ->
- ServerRoot = proplists:get_value(server_root, Config),
- Path = filename:join([ServerRoot, "htdocs"]),
- catch remove_htaccess(Path),
- create_htaccess_data(Path, proplists:get_value(address, Config)),
- [{watchdog, Dog} | NewConfig];
- "range" ->
- ServerRoot = proplists:get_value(server_root, Config),
- Path = filename:join([ServerRoot, "htdocs"]),
- create_range_data(Path),
- [{watchdog, Dog} | NewConfig];
- _ ->
- [{watchdog, Dog} | NewConfig]
- end,
-
- tsp("init_per_testcase3(~w) -> done when"
- "~n InitRes: ~p", [Case, InitRes]),
-
- InitRes.
-
-
-%%--------------------------------------------------------------------
-%% Function: end_per_testcase(Case, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
-%%--------------------------------------------------------------------
-end_per_testcase(Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- end_per_testcase2(Case, lists:keydelete(watchdog, 1, Config)),
- ok.
-
-end_per_testcase2(Case, Config) ->
- tsp("end_per_testcase2(~w) -> entry with"
- "~n Config: ~p", [Case, Config]),
- application:unset_env(inets, services),
- application:stop(inets),
- application:stop(ssl),
- application:stop(crypto), % used by the new ssl (essl test cases)
- cleanup_mnesia(),
- tsp("end_per_testcase2(~w) -> done", [Case]),
- ok.
-
-
-%%-------------------------------------------------------------------------
-%% Test cases starts here.
-%%-------------------------------------------------------------------------
-
-%%-------------------------------------------------------------------------
-ip_mod_alias(doc) ->
- ["Module test: mod_alias"];
-ip_mod_alias(suite) ->
- [];
-ip_mod_alias(Config) when is_list(Config) ->
- httpd_mod:alias(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config), proplists:get_value(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_mod_actions(doc) ->
- ["Module test: mod_actions"];
-ip_mod_actions(suite) ->
- [];
-ip_mod_actions(Config) when is_list(Config) ->
- httpd_mod:actions(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config), proplists:get_value(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_mod_security(doc) ->
- ["Module test: mod_security"];
-ip_mod_security(suite) ->
- [];
-ip_mod_security(Config) when is_list(Config) ->
- ServerRoot = proplists:get_value(server_root, Config),
- httpd_mod:security(ServerRoot, ip_comm, ?IP_PORT,
- proplists:get_value(host, Config), proplists:get_value(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_mod_auth(doc) ->
- ["Module test: mod_auth"];
-ip_mod_auth(suite) ->
- [];
-ip_mod_auth(Config) when is_list(Config) ->
- httpd_mod:auth(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config), proplists:get_value(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_mod_auth_api(doc) ->
- ["Module test: mod_auth_api"];
-ip_mod_auth_api(suite) ->
- [];
-ip_mod_auth_api(Config) when is_list(Config) ->
- ServerRoot = proplists:get_value(server_root, Config),
- Host = proplists:get_value(host, Config),
- Node = proplists:get_value(node, Config),
- httpd_mod:auth_api(ServerRoot, "", ip_comm, ?IP_PORT, Host, Node),
- httpd_mod:auth_api(ServerRoot, "dets_", ip_comm, ?IP_PORT, Host, Node),
- httpd_mod:auth_api(ServerRoot, "mnesia_", ip_comm, ?IP_PORT, Host, Node),
- ok.
-%%-------------------------------------------------------------------------
-ip_mod_auth_mnesia_api(doc) ->
- ["Module test: mod_auth_mnesia_api"];
-ip_mod_auth_mnesia_api(suite) ->
- [];
-ip_mod_auth_mnesia_api(Config) when is_list(Config) ->
- httpd_mod:auth_mnesia_api(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config), proplists:get_value(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_mod_htaccess(doc) ->
- ["Module test: mod_htaccess"];
-ip_mod_htaccess(suite) ->
- [];
-ip_mod_htaccess(Config) when is_list(Config) ->
- httpd_mod:htaccess(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config), proplists:get_value(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_mod_cgi(doc) ->
- ["Module test: mod_cgi"];
-ip_mod_cgi(suite) ->
- [];
-ip_mod_cgi(Config) when is_list(Config) ->
- httpd_mod:cgi(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config), proplists:get_value(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_mod_esi(doc) ->
- ["Module test: mod_esi"];
-ip_mod_esi(suite) ->
- [];
-ip_mod_esi(Config) when is_list(Config) ->
- httpd_mod:esi(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config), proplists:get_value(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_mod_get(doc) ->
- ["Module test: mod_get"];
-ip_mod_get(suite) ->
- [];
-ip_mod_get(Config) when is_list(Config) ->
- httpd_mod:get(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config), proplists:get_value(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_mod_head(doc) ->
- ["Module test: mod_head"];
-ip_mod_head(suite) ->
- [];
-ip_mod_head(Config) when is_list(Config) ->
- httpd_mod:head(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config), proplists:get_value(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_mod_all(doc) ->
- ["All modules test"];
-ip_mod_all(suite) ->
- [];
-ip_mod_all(Config) when is_list(Config) ->
- httpd_mod:all(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config), proplists:get_value(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_load_light(doc) ->
- ["Test light load"];
-ip_load_light(suite) ->
- [];
-ip_load_light(Config) when is_list(Config) ->
- httpd_load:load_test(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
- proplists:get_value(node, Config),
- get_nof_clients(ip_comm, light)),
- ok.
-%%-------------------------------------------------------------------------
-ip_load_medium(doc) ->
- ["Test medium load"];
-ip_load_medium(suite) ->
- [];
-ip_load_medium(Config) when is_list(Config) ->
- httpd_load:load_test(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
- proplists:get_value(node, Config),
- get_nof_clients(ip_comm, medium)),
- ok.
-%%-------------------------------------------------------------------------
-ip_load_heavy(doc) ->
- ["Test heavy load"];
-ip_load_heavy(suite) ->
- [];
-ip_load_heavy(Config) when is_list(Config) ->
- httpd_load:load_test(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
- proplists:get_value(node, Config),
- get_nof_clients(ip_comm, heavy)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-ip_dos_hostname(doc) ->
- ["Denial Of Service (DOS) attack test case"];
-ip_dos_hostname(suite) ->
- [];
-ip_dos_hostname(Config) when is_list(Config) ->
- dos_hostname(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
- proplists:get_value(node, Config), ?MAX_HEADER_SIZE),
- ok.
-
-
-%%-------------------------------------------------------------------------
-ip_time_test(doc) ->
- [""];
-ip_time_test(suite) ->
- [];
-ip_time_test(Config) when is_list(Config) ->
- httpd_time_test:t(ip_comm, proplists:get_value(host, Config), ?IP_PORT),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_block_503(doc) ->
- ["Check that you will receive status code 503 when the server"
- " is blocked and 200 when its not blocked."];
-ip_block_503(suite) ->
- [];
-ip_block_503(Config) when is_list(Config) ->
- httpd_block:block_503(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_block_disturbing_idle(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "distribing does not really make a difference in this case."];
-ip_block_disturbing_idle(suite) ->
- [];
-ip_block_disturbing_idle(Config) when is_list(Config) ->
- httpd_block:block_disturbing_idle(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_block_non_disturbing_idle(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "non distribing does not really make a difference in this case."];
-ip_block_non_disturbing_idle(suite) ->
- [];
-ip_block_non_disturbing_idle(Config) when is_list(Config) ->
- httpd_block:block_non_disturbing_idle(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_block_disturbing_active(doc) ->
- ["Check that you can block/unblock an active server. The strategy "
- "distribing means ongoing requests should be terminated."];
-ip_block_disturbing_active(suite) ->
- [];
-ip_block_disturbing_active(Config) when is_list(Config) ->
- httpd_block:block_disturbing_active(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_block_non_disturbing_active(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "non distribing means the ongoing requests should be compleated."];
-ip_block_non_disturbing_active(suite) ->
- [];
-ip_block_non_disturbing_active(Config) when is_list(Config) ->
- httpd_block:block_non_disturbing_idle(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_block_disturbing_active_timeout_not_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "distribing means ongoing requests should be compleated"
- "if the timeout does not occur."];
-ip_block_disturbing_active_timeout_not_released(suite) ->
- [];
-ip_block_disturbing_active_timeout_not_released(Config)
- when is_list(Config) ->
- httpd_block:block_disturbing_active_timeout_not_released(ip_comm,
- ?IP_PORT,
- proplists:get_value(host,
- Config),
- proplists:get_value(node,
- Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_block_disturbing_active_timeout_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "distribing means ongoing requests should be terminated when"
- "the timeout occurs."];
-ip_block_disturbing_active_timeout_released(suite) ->
- [];
-ip_block_disturbing_active_timeout_released(Config)
- when is_list(Config) ->
- httpd_block:block_disturbing_active_timeout_released(ip_comm,
- ?IP_PORT,
- proplists:get_value(host,
- Config),
- proplists:get_value(node,
- Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_block_non_disturbing_active_timeout_not_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "non non distribing means ongoing requests should be completed."];
-ip_block_non_disturbing_active_timeout_not_released(suite) ->
- [];
-ip_block_non_disturbing_active_timeout_not_released(Config)
- when is_list(Config) ->
- httpd_block:
- block_non_disturbing_active_timeout_not_released(ip_comm,
- ?IP_PORT,
- proplists:get_value(host,
- Config),
- proplists:get_value(node,
- Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_block_non_disturbing_active_timeout_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "non non distribing means ongoing requests should be completed. "
- "When the timeout occurs the block operation sohould be canceled." ];
-ip_block_non_disturbing_active_timeout_released(suite) ->
- [];
-ip_block_non_disturbing_active_timeout_released(Config)
- when is_list(Config) ->
- httpd_block:
- block_non_disturbing_active_timeout_released(ip_comm,
- ?IP_PORT,
- proplists:get_value(host,
- Config),
- proplists:get_value(node,
- Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_block_disturbing_blocker_dies(doc) ->
- [];
-ip_block_disturbing_blocker_dies(suite) ->
- [];
-ip_block_disturbing_blocker_dies(Config) when is_list(Config) ->
- httpd_block:disturbing_blocker_dies(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_block_non_disturbing_blocker_dies(doc) ->
- [];
-ip_block_non_disturbing_blocker_dies(suite) ->
- [];
-ip_block_non_disturbing_blocker_dies(Config) when is_list(Config) ->
- httpd_block:non_disturbing_blocker_dies(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_restart_no_block(doc) ->
- [""];
-ip_restart_no_block(suite) ->
- [];
-ip_restart_no_block(Config) when is_list(Config) ->
- httpd_block:restart_no_block(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_restart_disturbing_block(doc) ->
- [""];
-ip_restart_disturbing_block(suite) ->
- [];
-ip_restart_disturbing_block(Config) when is_list(Config) ->
- httpd_block:restart_disturbing_block(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_restart_non_disturbing_block(doc) ->
- [""];
-ip_restart_non_disturbing_block(suite) ->
- [];
-ip_restart_non_disturbing_block(Config) when is_list(Config) ->
- httpd_block:restart_non_disturbing_block(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-
-essl_mod_alias(doc) ->
- ["Module test: mod_alias - using new of configure new SSL"];
-essl_mod_alias(suite) ->
- [];
-essl_mod_alias(Config) when is_list(Config) ->
- ssl_mod_alias(essl, Config).
-
-
-ssl_mod_alias(Tag, Config) ->
- httpd_mod:alias(Tag, ?SSL_PORT,
- proplists:get_value(host, Config), proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_mod_actions(doc) ->
- ["Module test: mod_actions - using new of configure new SSL"];
-essl_mod_actions(suite) ->
- [];
-essl_mod_actions(Config) when is_list(Config) ->
- ssl_mod_actions(essl, Config).
-
-
-ssl_mod_actions(Tag, Config) ->
- httpd_mod:actions(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_mod_security(doc) ->
- ["Module test: mod_security - using new of configure new SSL"];
-essl_mod_security(suite) ->
- [];
-essl_mod_security(Config) when is_list(Config) ->
- ssl_mod_security(essl, Config).
-
-ssl_mod_security(Tag, Config) ->
- ServerRoot = proplists:get_value(server_root, Config),
- httpd_mod:security(ServerRoot,
- Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_mod_auth(doc) ->
- ["Module test: mod_auth - using new of configure new SSL"];
-essl_mod_auth(suite) ->
- [];
-essl_mod_auth(Config) when is_list(Config) ->
- ssl_mod_auth(essl, Config).
-
-ssl_mod_auth(Tag, Config) ->
- httpd_mod:auth(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-
-essl_mod_auth_api(doc) ->
- ["Module test: mod_auth - using new of configure new SSL"];
-essl_mod_auth_api(suite) ->
- [];
-essl_mod_auth_api(Config) when is_list(Config) ->
- ssl_mod_auth_api(essl, Config).
-
-ssl_mod_auth_api(Tag, Config) ->
- ServerRoot = proplists:get_value(server_root, Config),
- Host = proplists:get_value(host, Config),
- Node = proplists:get_value(node, Config),
- httpd_mod:auth_api(ServerRoot, "", Tag, ?SSL_PORT, Host, Node),
- httpd_mod:auth_api(ServerRoot, "dets_", Tag, ?SSL_PORT, Host, Node),
- httpd_mod:auth_api(ServerRoot, "mnesia_", Tag, ?SSL_PORT, Host, Node),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-
-essl_mod_auth_mnesia_api(doc) ->
- ["Module test: mod_auth_mnesia_api - using new of configure new SSL"];
-essl_mod_auth_mnesia_api(suite) ->
- [];
-essl_mod_auth_mnesia_api(Config) when is_list(Config) ->
- ssl_mod_auth_mnesia_api(essl, Config).
-
-ssl_mod_auth_mnesia_api(Tag, Config) ->
- httpd_mod:auth_mnesia_api(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_mod_htaccess(doc) ->
- ["Module test: mod_htaccess - using new of configure new SSL"];
-essl_mod_htaccess(suite) ->
- [];
-essl_mod_htaccess(Config) when is_list(Config) ->
- ssl_mod_htaccess(essl, Config).
-
-ssl_mod_htaccess(Tag, Config) ->
- httpd_mod:htaccess(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_mod_cgi(doc) ->
- ["Module test: mod_cgi - using new of configure new SSL"];
-essl_mod_cgi(suite) ->
- [];
-essl_mod_cgi(Config) when is_list(Config) ->
- ssl_mod_cgi(essl, Config).
-
-ssl_mod_cgi(Tag, Config) ->
- httpd_mod:cgi(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_mod_esi(doc) ->
- ["Module test: mod_esi - using new of configure new SSL"];
-essl_mod_esi(suite) ->
- [];
-essl_mod_esi(Config) when is_list(Config) ->
- ssl_mod_esi(essl, Config).
-
-ssl_mod_esi(Tag, Config) ->
- httpd_mod:esi(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_mod_get(doc) ->
- ["Module test: mod_get - using new of configure new SSL"];
-essl_mod_get(suite) ->
- [];
-essl_mod_get(Config) when is_list(Config) ->
- ssl_mod_get(essl, Config).
-
-ssl_mod_get(Tag, Config) ->
- httpd_mod:get(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_mod_head(doc) ->
- ["Module test: mod_head - using new of configure new SSL"];
-essl_mod_head(suite) ->
- [];
-essl_mod_head(Config) when is_list(Config) ->
- ssl_mod_head(essl, Config).
-
-ssl_mod_head(Tag, Config) ->
- httpd_mod:head(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_mod_all(doc) ->
- ["All modules test - using new of configure new SSL"];
-essl_mod_all(suite) ->
- [];
-essl_mod_all(Config) when is_list(Config) ->
- ssl_mod_all(essl, Config).
-
-ssl_mod_all(Tag, Config) ->
- httpd_mod:all(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_load_light(doc) ->
- ["Test light load - using new of configure new SSL"];
-essl_load_light(suite) ->
- [];
-essl_load_light(Config) when is_list(Config) ->
- ssl_load_light(essl, Config).
-
-ssl_load_light(Tag, Config) ->
- httpd_load:load_test(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config),
- get_nof_clients(ssl, light)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_load_medium(doc) ->
- ["Test medium load - using new of configure new SSL"];
-essl_load_medium(suite) ->
- [];
-essl_load_medium(Config) when is_list(Config) ->
- ssl_load_medium(essl, Config).
-
-ssl_load_medium(Tag, Config) ->
- httpd_load:load_test(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config),
- get_nof_clients(ssl, medium)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_load_heavy(doc) ->
- ["Test heavy load - using new of configure new SSL"];
-essl_load_heavy(suite) ->
- [];
-essl_load_heavy(Config) when is_list(Config) ->
- ssl_load_heavy(essl, Config).
-
-ssl_load_heavy(Tag, Config) ->
- httpd_load:load_test(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config),
- get_nof_clients(ssl, heavy)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-
-essl_dos_hostname(doc) ->
- ["Denial Of Service (DOS) attack test case - using new of configure new SSL"];
-essl_dos_hostname(suite) ->
- [];
-essl_dos_hostname(Config) when is_list(Config) ->
- ssl_dos_hostname(essl, Config).
-
-ssl_dos_hostname(Tag, Config) ->
- dos_hostname(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config),
- ?MAX_HEADER_SIZE),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-
-essl_time_test(doc) ->
- ["using new of configure new SSL"];
-essl_time_test(suite) ->
- [];
-essl_time_test(Config) when is_list(Config) ->
- ssl_time_test(essl, Config).
-
-ssl_time_test(Tag, Config) when is_list(Config) ->
- httpd_time_test:t(Tag,
- proplists:get_value(host, Config),
- ?SSL_PORT),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-
-essl_block_503(doc) ->
- ["Check that you will receive status code 503 when the server"
- " is blocked and 200 when its not blocked - using new of configure new SSL."];
-essl_block_503(suite) ->
- [];
-essl_block_503(Config) when is_list(Config) ->
- ssl_block_503(essl, Config).
-
-ssl_block_503(Tag, Config) ->
- httpd_block:block_503(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_block_disturbing_idle(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "distribing does not really make a difference in this case."
- "Using new of configure new SSL"];
-essl_block_disturbing_idle(suite) ->
- [];
-essl_block_disturbing_idle(Config) when is_list(Config) ->
- ssl_block_disturbing_idle(essl, Config).
-
-ssl_block_disturbing_idle(Tag, Config) ->
- httpd_block:block_disturbing_idle(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_block_non_disturbing_idle(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "non distribing does not really make a difference in this case."
- "Using new of configure new SSL"];
-essl_block_non_disturbing_idle(suite) ->
- [];
-essl_block_non_disturbing_idle(Config) when is_list(Config) ->
- ssl_block_non_disturbing_idle(essl, Config).
-
-ssl_block_non_disturbing_idle(Tag, Config) ->
- httpd_block:block_non_disturbing_idle(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_block_disturbing_active(doc) ->
- ["Check that you can block/unblock an active server. The strategy "
- "distribing means ongoing requests should be terminated."
- "Using new of configure new SSL"];
-essl_block_disturbing_active(suite) ->
- [];
-essl_block_disturbing_active(Config) when is_list(Config) ->
- ssl_block_disturbing_active(essl, Config).
-
-ssl_block_disturbing_active(Tag, Config) ->
- httpd_block:block_disturbing_active(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_block_non_disturbing_active(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "non distribing means the ongoing requests should be compleated."
- "Using new of configure new SSL"];
-essl_block_non_disturbing_active(suite) ->
- [];
-essl_block_non_disturbing_active(Config) when is_list(Config) ->
- ssl_block_non_disturbing_active(essl, Config).
-
-ssl_block_non_disturbing_active(Tag, Config) ->
- httpd_block:block_non_disturbing_idle(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_block_disturbing_active_timeout_not_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "distribing means ongoing requests should be compleated"
- "if the timeout does not occur."
- "Using new of configure new SSL"];
-essl_block_disturbing_active_timeout_not_released(suite) ->
- [];
-essl_block_disturbing_active_timeout_not_released(Config)
- when is_list(Config) ->
- ssl_block_disturbing_active_timeout_not_released(essl, Config).
-
-ssl_block_disturbing_active_timeout_not_released(Tag, Config) ->
- Port = ?SSL_PORT,
- Host = proplists:get_value(host, Config),
- Node = proplists:get_value(node, Config),
- httpd_block:block_disturbing_active_timeout_not_released(Tag,
- Port, Host, Node),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_block_disturbing_active_timeout_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "distribing means ongoing requests should be terminated when"
- "the timeout occurs."
- "Using new of configure new SSL"];
-essl_block_disturbing_active_timeout_released(suite) ->
- [];
-essl_block_disturbing_active_timeout_released(Config)
- when is_list(Config) ->
- ssl_block_disturbing_active_timeout_released(essl, Config).
-
-ssl_block_disturbing_active_timeout_released(Tag, Config) ->
- Port = ?SSL_PORT,
- Host = proplists:get_value(host, Config),
- Node = proplists:get_value(node, Config),
- httpd_block:block_disturbing_active_timeout_released(Tag,
- Port,
- Host,
- Node),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_block_non_disturbing_active_timeout_not_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "non non distribing means ongoing requests should be completed."
- "Using new of configure new SSL"];
-essl_block_non_disturbing_active_timeout_not_released(suite) ->
- [];
-essl_block_non_disturbing_active_timeout_not_released(Config)
- when is_list(Config) ->
- ssl_block_non_disturbing_active_timeout_not_released(essl, Config).
-
-ssl_block_non_disturbing_active_timeout_not_released(Tag, Config) ->
- Port = ?SSL_PORT,
- Host = proplists:get_value(host, Config),
- Node = proplists:get_value(node, Config),
- httpd_block:block_non_disturbing_active_timeout_not_released(Tag,
- Port,
- Host,
- Node),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-
-essl_block_non_disturbing_active_timeout_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "non distribing means ongoing requests should be completed. "
- "When the timeout occurs the block operation sohould be canceled."
- "Using new of configure new SSL"];
-essl_block_non_disturbing_active_timeout_released(suite) ->
- [];
-essl_block_non_disturbing_active_timeout_released(Config)
- when is_list(Config) ->
- ssl_block_non_disturbing_active_timeout_released(essl, Config).
-
-ssl_block_non_disturbing_active_timeout_released(Tag, Config)
- when is_list(Config) ->
- Port = ?SSL_PORT,
- Host = proplists:get_value(host, Config),
- Node = proplists:get_value(node, Config),
- httpd_block:block_non_disturbing_active_timeout_released(Tag,
- Port,
- Host,
- Node),
-
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-
-essl_block_disturbing_blocker_dies(doc) ->
- ["using new of configure new SSL"];
-essl_block_disturbing_blocker_dies(suite) ->
- [];
-essl_block_disturbing_blocker_dies(Config) when is_list(Config) ->
- ssl_block_disturbing_blocker_dies(essl, Config).
-
-ssl_block_disturbing_blocker_dies(Tag, Config) ->
- httpd_block:disturbing_blocker_dies(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-essl_block_non_disturbing_blocker_dies(doc) ->
- ["using new of configure new SSL"];
-essl_block_non_disturbing_blocker_dies(suite) ->
- [];
-essl_block_non_disturbing_blocker_dies(Config) when is_list(Config) ->
- ssl_block_non_disturbing_blocker_dies(essl, Config).
-
-ssl_block_non_disturbing_blocker_dies(Tag, Config) ->
- httpd_block:non_disturbing_blocker_dies(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-
-essl_restart_no_block(doc) ->
- ["using new of configure new SSL"];
-essl_restart_no_block(suite) ->
- [];
-essl_restart_no_block(Config) when is_list(Config) ->
- ssl_restart_no_block(essl, Config).
-
-ssl_restart_no_block(Tag, Config) ->
- httpd_block:restart_no_block(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-
-essl_restart_disturbing_block(doc) ->
- ["using new of configure new SSL"];
-essl_restart_disturbing_block(suite) ->
- [];
-essl_restart_disturbing_block(Config) when is_list(Config) ->
- ssl_restart_disturbing_block(essl, Config).
-
-ssl_restart_disturbing_block(Tag, Config) ->
- httpd_block:restart_disturbing_block(Tag, ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-
-essl_restart_non_disturbing_block(doc) ->
- ["using new of configure new SSL"];
-essl_restart_non_disturbing_block(suite) ->
- [];
-essl_restart_non_disturbing_block(Config) when is_list(Config) ->
- ssl_restart_non_disturbing_block(essl, Config).
-
-ssl_restart_non_disturbing_block(Tag, Config) ->
- httpd_block:restart_non_disturbing_block(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-ip_host(doc) ->
- ["Control that the server accepts/rejects requests with/ without host"];
-ip_host(suite)->
- [];
-ip_host(Config) when is_list(Config) ->
- httpd_1_1:host(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_chunked(doc) ->
- ["Control that the server accepts chunked requests"];
-ip_chunked(suite) ->
- [];
-ip_chunked(Config) when is_list(Config) ->
- httpd_1_1:chunked(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_expect(doc) ->
- ["Control that the server handles request with the expect header "
- "field appropiate"];
-ip_expect(suite)->
- [];
-ip_expect(Config) when is_list(Config) ->
- httpd_1_1:expect(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_range(doc) ->
- ["Control that the server can handle range requests to plain files"];
-ip_range(suite)->
- [];
-ip_range(Config) when is_list(Config) ->
- httpd_1_1:range(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_if_test(doc) ->
- ["Test that the if - request header fields is handled correclty"];
-ip_if_test(suite) ->
- [];
-ip_if_test(Config) when is_list(Config) ->
- ServerRoot = proplists:get_value(server_root, Config),
- DocRoot = filename:join([ServerRoot, "htdocs"]),
- httpd_1_1:if_test(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
- proplists:get_value(node, Config), DocRoot),
- ok.
-%%-------------------------------------------------------------------------
-ip_http_trace(doc) ->
- ["Test the trace module "];
-ip_http_trace(suite) ->
- [];
-ip_http_trace(Config) when is_list(Config) ->
- httpd_1_1:http_trace(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_http1_1_head(doc) ->
- ["Test the trace module "];
-ip_http1_1_head(suite)->
- [];
-ip_http1_1_head(Config) when is_list(Config) ->
- httpd_1_1:head(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_get_0_9(doc) ->
- ["Test simple HTTP/0.9 GET"];
-ip_get_0_9(suite)->
- [];
-ip_get_0_9(Config) when is_list(Config) ->
- Host = proplists:get_value(host, Config),
- Node = proplists:get_value(node, Config),
- ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
- "GET / \r\n\r\n",
- [{statuscode, 200},
- {version, "HTTP/0.9"} ]),
- %% Without space after uri
- ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
- "GET /\r\n\r\n",
- [{statuscode, 200},
- {version, "HTTP/0.9"} ]),
- ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
- "GET / HTTP/0.9\r\n\r\n",
- [{statuscode, 200},
- {version, "HTTP/0.9"}]),
-
- ok.
-%%-------------------------------------------------------------------------
-ip_head_1_0(doc) ->
- ["Test HTTP/1.0 HEAD"];
-ip_head_1_0(suite)->
- [];
-ip_head_1_0(Config) when is_list(Config) ->
- Host = proplists:get_value(host, Config),
- Node = proplists:get_value(node, Config),
- ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
- "HEAD / HTTP/1.0\r\n\r\n", [{statuscode, 200},
- {version, "HTTP/1.0"}]),
-
- ok.
-%%-------------------------------------------------------------------------
-ip_get_1_0(doc) ->
- ["Test HTTP/1.0 GET"];
-ip_get_1_0(suite)->
- [];
-ip_get_1_0(Config) when is_list(Config) ->
- Host = proplists:get_value(host, Config),
- Node = proplists:get_value(node, Config),
- ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
- "GET / HTTP/1.0\r\n\r\n", [{statuscode, 200},
- {version, "HTTP/1.0"}]),
-
- ok.
-%%-------------------------------------------------------------------------
-ip_post_1_0(doc) ->
- ["Test HTTP/1.0 POST"];
-ip_post_1_0(suite)->
- [];
-ip_post_1_0(Config) when is_list(Config) ->
- Host = proplists:get_value(host, Config),
- Node = proplists:get_value(node, Config),
- %% Test the post message formatin 1.0! Real post are testes elsewhere
- ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
- "POST / HTTP/1.0\r\n\r\n "
- "Content-Length:6 \r\n\r\nfoobar",
- [{statuscode, 500}, {version, "HTTP/1.0"}]),
-
- ok.
-%%-------------------------------------------------------------------------
-ip_mod_cgi_chunked_encoding_test(doc) ->
- ["Test the trace module "];
-ip_mod_cgi_chunked_encoding_test(suite)->
- [];
-ip_mod_cgi_chunked_encoding_test(Config) when is_list(Config) ->
- Host = proplists:get_value(host, Config),
- Script =
- case test_server:os_type() of
- {win32, _} ->
- "/cgi-bin/printenv.bat";
- _ ->
- "/cgi-bin/printenv.sh"
- end,
- Requests =
- ["GET " ++ Script ++ " HTTP/1.1\r\nHost:"++ Host ++"\r\n\r\n",
- "GET /cgi-bin/erl/httpd_example/newformat HTTP/1.1\r\nHost:"
- ++ Host ++"\r\n\r\n"],
- httpd_1_1:mod_cgi_chunked_encoding_test(ip_comm, ?IP_PORT,
- Host,
- proplists:get_value(node, Config),
- Requests),
- ok.
-
-%-------------------------------------------------------------------------
-
-ipv6_hostname_ipcomm() ->
- [{require, ipv6_hosts}].
-ipv6_hostname_ipcomm(X) ->
- SocketType = ip_comm,
- Port = ?IP_PORT,
- ipv6_hostname(SocketType, Port, X).
-
-ipv6_hostname_essl() ->
- [{require, ipv6_hosts}].
-ipv6_hostname_essl(X) ->
- SocketType = essl,
- Port = ?SSL_PORT,
- ipv6_hostname(SocketType, Port, X).
-
-ipv6_hostname(_SocketType, _Port, doc) ->
- ["Test standard ipv6 address"];
-ipv6_hostname(_SocketType, _Port, suite)->
- [];
-ipv6_hostname(SocketType, Port, Config) when is_list(Config) ->
- tsp("ipv6_hostname -> entry with"
- "~n SocketType: ~p"
- "~n Port: ~p"
- "~n Config: ~p", [SocketType, Port, Config]),
- Host = proplists:get_value(host, Config),
- URI = "GET HTTP://" ++
- Host ++ ":" ++ integer_to_list(Port) ++ "/ HTTP/1.1\r\n\r\n",
- tsp("ipv6_hostname -> Host: ~p", [Host]),
- httpd_test_lib:verify_request(SocketType, Host, Port, [inet6],
- node(),
- URI,
- [{statuscode, 200}, {version, "HTTP/1.1"}]),
- ok.
-
-%%-------------------------------------------------------------------------
-
-ipv6_address_ipcomm() ->
- [{require, ipv6_hosts}].
-ipv6_address_ipcomm(X) ->
- SocketType = ip_comm,
- Port = ?IP_PORT,
- ipv6_address(SocketType, Port, X).
-
-ipv6_address_essl() ->
- [{require, ipv6_hosts}].
-ipv6_address_essl(X) ->
- SocketType = essl,
- Port = ?SSL_PORT,
- ipv6_address(SocketType, Port, X).
-
-ipv6_address(_SocketType, _Port, doc) ->
- ["Test standard ipv6 address"];
-ipv6_address(_SocketType, _Port, suite)->
- [];
-ipv6_address(SocketType, Port, Config) when is_list(Config) ->
- tsp("ipv6_address -> entry with"
- "~n SocketType: ~p"
- "~n Port: ~p"
- "~n Config: ~p", [SocketType, Port, Config]),
- Host = proplists:get_value(host, Config),
- tsp("ipv6_address -> Host: ~p", [Host]),
- URI = "GET HTTP://" ++
- Host ++ ":" ++ integer_to_list(Port) ++ "/ HTTP/1.1\r\n\r\n",
- httpd_test_lib:verify_request(SocketType, Host, Port, [inet6],
- node(),
- URI,
- [{statuscode, 200}, {version, "HTTP/1.1"}]),
- ok.
-
-
-%%--------------------------------------------------------------------
-ticket_5775(doc) ->
- ["Tests that content-length is correct"];
-ticket_5775(suite) ->
- [];
-ticket_5775(Config) ->
- ok=httpd_test_lib:verify_request(ip_comm, proplists:get_value(host, Config),
- ?IP_PORT, proplists:get_value(node, Config),
- "GET /cgi-bin/erl/httpd_example:get_bin "
- "HTTP/1.0\r\n\r\n",
- [{statuscode, 200},
- {version, "HTTP/1.0"}]),
- ok.
-ticket_5865(doc) ->
- ["Tests that a header without last-modified is handled"];
-ticket_5865(suite) ->
- [];
-ticket_5865(Config) ->
- ct:skip(as_of_r15_behaviour_of_calendar_has_changed),
- Host = proplists:get_value(host,Config),
- ServerRoot = proplists:get_value(server_root, Config),
- DocRoot = filename:join([ServerRoot, "htdocs"]),
- File = filename:join([DocRoot,"last_modified.html"]),
-
- Bad_mtime = case test_server:os_type() of
- {win32, _} ->
- {{1600,12,31},{23,59,59}};
- {unix, _} ->
- {{1969,12,31},{23,59,59}}
- end,
-
- {ok,FI}=file:read_file_info(File),
-
- case file:write_file_info(File,FI#file_info{mtime=Bad_mtime}) of
- ok ->
- ok = httpd_test_lib:verify_request(ip_comm, Host,
- ?IP_PORT, proplists:get_value(node, Config),
- "GET /last_modified.html"
- " HTTP/1.1\r\nHost:"
- ++Host++"\r\n\r\n",
- [{statuscode, 200},
- {no_header,
- "last-modified"}]),
- ok;
- {error, Reason} ->
- Fault =
- io_lib:format("Attempt to change the file info to set the"
- " preconditions of the test case failed ~p~n",
- [Reason]),
- {skip, Fault}
- end.
-
-ticket_5913(doc) ->
- ["Tests that a header without last-modified is handled"];
-ticket_5913(suite) -> [];
-ticket_5913(Config) ->
- ok = httpd_test_lib:verify_request(ip_comm, proplists:get_value(host, Config),
- ?IP_PORT, proplists:get_value(node, Config),
- "GET /cgi-bin/erl/httpd_example:get_bin "
- "HTTP/1.0\r\n\r\n",
- [{statuscode, 200},
- {version, "HTTP/1.0"}]),
- ok.
-
-ticket_6003(doc) ->
- ["Tests that a URI with a bad hexadecimal code is handled"];
-ticket_6003(suite) -> [];
-ticket_6003(Config) ->
- ok = httpd_test_lib:verify_request(ip_comm, proplists:get_value(host, Config),
- ?IP_PORT, proplists:get_value(node, Config),
- "GET http://www.erlang.org/%skalle "
- "HTTP/1.0\r\n\r\n",
- [{statuscode, 400},
- {version, "HTTP/1.0"}]),
- ok.
-
-ticket_7304(doc) ->
- ["Tests missing CR in delimiter"];
-ticket_7304(suite) ->
- [];
-ticket_7304(Config) ->
- ok = httpd_test_lib:verify_request(ip_comm, proplists:get_value(host, Config),
- ?IP_PORT, proplists:get_value(node, Config),
- "GET / HTTP/1.0\r\n\n",
- [{statuscode, 200},
- {version, "HTTP/1.0"}]),
- ok.
-
-%%--------------------------------------------------------------------
-%% Internal functions
-%%--------------------------------------------------------------------
-dos_hostname(Type, Port, Host, Node, Max) ->
- H1 = {"", 200},
- H2 = {"dummy-host.ericsson.se", 200},
- TooLongHeader = lists:append(lists:duplicate(Max + 1, "a")),
- H3 = {TooLongHeader, 403},
- Hosts = [H1,H2,H3],
- dos_hostname_poll(Type, Host, Port, Node, Hosts).
-
-%% make_ipv6(T) when is_tuple(T) andalso (size(T) =:= 8) ->
-%% make_ipv6(tuple_to_list(T));
-
-%% make_ipv6([_, _, _, _, _, _, _, _] = IPV6) ->
-%% lists:flatten(io_lib:format("~s:~s:~s:~s:~s:~s:~s:~s", IPV6)).
-
-
-%%--------------------------------------------------------------------
-%% Other help functions
-create_config(Config, Access, FileName) ->
- ServerRoot = proplists:get_value(server_root, Config),
- TcTopDir = proplists:get_value(tc_top_dir, Config),
- Port = proplists:get_value(port, Config),
- Type = proplists:get_value(sock_type, Config),
- Host = proplists:get_value(host, Config),
- Mods = io_lib:format("~p", [httpd_mod]),
- Funcs = io_lib:format("~p", [ssl_password_cb]),
- MaxHdrSz = io_lib:format("~p", [256]),
- MaxHdrAct = io_lib:format("~p", [close]),
-
- io:format(user,
- "create_config -> "
- "~n ServerRoot: ~p"
- "~n TcTopDir: ~p"
- "~n Type: ~p"
- "~n Port: ~p"
- "~n Host: ~p"
- "~n", [ServerRoot, TcTopDir, Type, Port, Host]),
-
- SSL =
- if
- (Type =:= ssl) orelse
- (Type =:= essl) ->
- [cline(["SSLCertificateFile ",
- filename:join(ServerRoot, "ssl/ssl_server.pem")]),
- cline(["SSLCertificateKeyFile ",
- filename:join(ServerRoot, "ssl/ssl_server.pem")]),
- cline(["SSLCACertificateFile ",
- filename:join(ServerRoot, "ssl/ssl_server.pem")]),
- cline(["SSLPasswordCallbackModule ", Mods]),
- cline(["SSLPasswordCallbackFunction ", Funcs]),
- cline(["SSLVerifyClient 0"]),
- cline(["SSLVerifyDepth 1"])];
- true ->
- []
- end,
- ModOrder =
- case Access of
- mod_htaccess ->
- "Modules mod_alias mod_htaccess mod_auth "
- "mod_security "
- "mod_responsecontrol mod_trace mod_esi "
- "mod_actions mod_cgi mod_dir "
- "mod_range mod_get "
- "mod_head mod_log mod_disk_log";
- _ ->
- "Modules mod_alias mod_auth mod_security "
- "mod_responsecontrol mod_trace mod_esi "
- "mod_actions mod_cgi mod_dir "
- "mod_range mod_get "
- "mod_head mod_log mod_disk_log"
- end,
-
- %% The test suite currently does not handle an explicit BindAddress.
- %% They assume any has been used, that is Addr is always set to undefined!
-
- %% {ok, Hostname} = inet:gethostname(),
- %% {ok, Addr} = inet:getaddr(Hostname, inet6),
- %% AddrStr = make_ipv6(Addr),
- %% BindAddress = lists:flatten(io_lib:format("~s|inet6", [AddrStr])),
-
- BindAddress = "*|inet",
- %% BindAddress = "*",
-
- HttpConfig = [
- cline(["Port ", integer_to_list(Port)]),
- cline(["ServerName ", Host]),
- cline(["SocketType ", atom_to_list(Type)]),
- cline([ModOrder]),
- %% cline(["LogFormat ", "erlang"]),
- cline(["ServerAdmin [email protected]"]),
- cline(["BindAddress ", BindAddress]),
- cline(["ServerRoot ", ServerRoot]),
- cline(["ErrorLog ", TcTopDir,
- "/logs/error_log_", integer_to_list(Port)]),
- cline(["TransferLog ", TcTopDir,
- "/logs/access_log_", integer_to_list(Port)]),
- cline(["SecurityLog ", TcTopDir,
- "/logs/security_log_", integer_to_list(Port)]),
- cline(["ErrorDiskLog ", TcTopDir,
- "/logs/error_disk_log_", integer_to_list(Port)]),
- cline(["ErrorDiskLogSize ", "190000 ", "11"]),
- cline(["TransferDiskLog ", TcTopDir,
- "/logs/access_disk_log_", integer_to_list(Port)]),
- cline(["TransferDiskLogSize ", "200000 ", "10"]),
- cline(["SecurityDiskLog ", TcTopDir,
- "/logs/security_disk_log_", integer_to_list(Port)]),
- cline(["SecurityDiskLogSize ", "210000 ", "9"]),
- cline(["MaxClients 10"]),
- cline(["MaxHeaderSize ", MaxHdrSz]),
- cline(["MaxHeaderAction ", MaxHdrAct]),
- cline(["DocumentRoot ",
- filename:join(ServerRoot, "htdocs")]),
- cline(["DirectoryIndex ", "index.html ", "welcome.html"]),
- cline(["DefaultType ", "text/plain"]),
- SSL,
- mod_alias_config(ServerRoot),
-
- config_directory(filename:join([ServerRoot,"htdocs",
- "open"]),
- "Open Area",
- filename:join(ServerRoot, "auth/passwd"),
- filename:join(ServerRoot, "auth/group"),
- plain,
- "user one Aladdin",
- filename:join(ServerRoot, "security_data")),
- config_directory(filename:join([ServerRoot,"htdocs",
- "secret"]),
- "Secret Area",
- filename:join(ServerRoot, "auth/passwd"),
- filename:join(ServerRoot, "auth/group"),
- plain,
- "group group1 group2",
- filename:join(ServerRoot, "security_data")),
- config_directory(filename:join([ServerRoot,"htdocs",
- "secret",
- "top_secret"]),
- "Top Secret Area",
- filename:join(ServerRoot, "auth/passwd"),
- filename:join(ServerRoot, "auth/group"),
- plain,
- "group group3",
- filename:join(ServerRoot, "security_data")),
-
- config_directory(filename:join([ServerRoot,"htdocs",
- "dets_open"]),
- "Dets Open Area",
- filename:join(ServerRoot, "passwd"),
- filename:join(ServerRoot, "group"),
- dets,
- "user one Aladdin",
- filename:join(ServerRoot, "security_data")),
- config_directory(filename:join([ServerRoot,"htdocs",
- "dets_secret"]),
- "Dets Secret Area",
- filename:join(ServerRoot, "passwd"),
- filename:join(ServerRoot, "group"),
- dets,
- "group group1 group2",
- filename:join(ServerRoot, "security_data")),
- config_directory(filename:join([ServerRoot,"htdocs",
- "dets_secret",
- "top_secret"]),
- "Dets Top Secret Area",
- filename:join(ServerRoot, "passwd"),
- filename:join(ServerRoot, "group"),
- dets,
- "group group3",
- filename:join(ServerRoot, "security_data")),
-
- config_directory(filename:join([ServerRoot,"htdocs",
- "mnesia_open"]),
- "Mnesia Open Area",
- false,
- false,
- mnesia,
- "user one Aladdin",
- filename:join(ServerRoot, "security_data")),
- config_directory(filename:join([ServerRoot,"htdocs",
- "mnesia_secret"]),
- "Mnesia Secret Area",
- false,
- false,
- mnesia,
- "group group1 group2",
- filename:join(ServerRoot, "security_data")),
- config_directory(filename:join(
- [ServerRoot, "htdocs", "mnesia_secret",
- "top_secret"]),
- "Mnesia Top Secret Area",
- false,
- false,
- mnesia,
- "group group3",
- filename:join(ServerRoot, "security_data"))
- ],
- ConfigFile = filename:join([TcTopDir, FileName]),
- {ok, Fd} = file:open(ConfigFile, [write]),
- ok = file:write(Fd, lists:flatten(HttpConfig)),
- ok = file:close(Fd).
-
-config_directory(Dir, AuthName, AuthUserFile, AuthGroupFile, AuthDBType,
- Require, SF) ->
- file:delete(SF),
- [
- cline(["<Directory ", Dir, ">"]),
- cline(["SecurityDataFile ", SF]),
- cline(["SecurityMaxRetries 3"]),
- cline(["SecurityFailExpireTime ", integer_to_list(?FAIL_EXPIRE_TIME)]),
- cline(["SecurityBlockTime 1"]),
- cline(["SecurityAuthTimeout ", integer_to_list(?AUTH_TIMEOUT)]),
- cline(["SecurityCallbackModule ", "httpd_mod"]),
- cline_if_set("AuthUserFile", AuthUserFile),
- cline_if_set("AuthGroupFile", AuthGroupFile),
- cline_if_set("AuthName", AuthName),
- cline_if_set("AuthDBType", AuthDBType),
- cline(["require ", Require]),
- cline(["</Directory>\r\n"])
- ].
-
-mod_alias_config(Root) ->
- [
- cline(["Alias /icons/ ", filename:join(Root,"icons"), "/"]),
- cline(["Alias /pics/ ", filename:join(Root, "icons"), "/"]),
- cline(["ScriptAlias /cgi-bin/ ", filename:join(Root, "cgi-bin"), "/"]),
- cline(["ScriptAlias /htbin/ ", filename:join(Root, "cgi-bin"), "/"]),
- cline(["ErlScriptAlias /cgi-bin/erl httpd_example io"]),
- cline(["EvalScriptAlias /eval httpd_example io"])
- ].
-
-cline(List) ->
- lists:flatten([List, "\r\n"]).
-
-cline_if_set(_, false) ->
- [];
-cline_if_set(Name, Var) when is_list(Var) ->
- cline([Name, " ", Var]);
-cline_if_set(Name, Var) when is_atom(Var) ->
- cline([Name, " ", atom_to_list(Var)]).
-
-getaddr() ->
- {ok,HostName} = inet:gethostname(),
- {ok,{A1,A2,A3,A4}} = inet:getaddr(HostName,inet),
- lists:flatten(io_lib:format("~p.~p.~p.~p",[A1,A2,A3,A4])).
-
-start_mnesia(Node) ->
- case rpc:call(Node, ?MODULE, cleanup_mnesia, []) of
- ok ->
- ok;
- Other ->
- tsf({failed_to_cleanup_mnesia, Other})
- end,
- case rpc:call(Node, ?MODULE, setup_mnesia, []) of
- {atomic, ok} ->
- ok;
- Other2 ->
- tsf({failed_to_setup_mnesia, Other2})
- end,
- ok.
-
-setup_mnesia() ->
- setup_mnesia([node()]).
-
-setup_mnesia(Nodes) ->
- ok = mnesia:create_schema(Nodes),
- ok = mnesia:start(),
- {atomic, ok} = mnesia:create_table(httpd_user,
- [{attributes,
- record_info(fields, httpd_user)},
- {disc_copies,Nodes}, {type, set}]),
- {atomic, ok} = mnesia:create_table(httpd_group,
- [{attributes,
- record_info(fields,
- httpd_group)},
- {disc_copies,Nodes}, {type,bag}]).
-
-cleanup_mnesia() ->
- mnesia:start(),
- mnesia:delete_table(httpd_user),
- mnesia:delete_table(httpd_group),
- stopped = mnesia:stop(),
- mnesia:delete_schema([node()]),
- ok.
-
-create_htaccess_data(Path, IpAddress)->
- create_htaccess_dirs(Path),
-
- create_html_file(filename:join([Path,"ht/open/dummy.html"])),
- create_html_file(filename:join([Path,"ht/blocknet/dummy.html"])),
- create_html_file(filename:join([Path,"ht/secret/dummy.html"])),
- create_html_file(filename:join([Path,"ht/secret/top_secret/dummy.html"])),
-
- create_htaccess_file(filename:join([Path,"ht/open/.htaccess"]),
- Path, "user one Aladdin"),
- create_htaccess_file(filename:join([Path,"ht/secret/.htaccess"]),
- Path, "group group1 group2"),
- create_htaccess_file(filename:join([Path,
- "ht/secret/top_secret/.htaccess"]),
- Path, "user four"),
- create_htaccess_file(filename:join([Path,"ht/blocknet/.htaccess"]),
- Path, nouser, IpAddress),
-
- create_user_group_file(filename:join([Path,"ht","users.file"]),
- "one:OnePassword\ntwo:TwoPassword\nthree:"
- "ThreePassword\nfour:FourPassword\nAladdin:"
- "AladdinPassword"),
- create_user_group_file(filename:join([Path,"ht","groups.file"]),
- "group1: two one\ngroup2: two three").
-
-create_html_file(PathAndFileName)->
- file:write_file(PathAndFileName,list_to_binary(
- "<html><head><title>test</title></head>
- <body>testar</body></html>")).
-
-create_htaccess_file(PathAndFileName, BaseDir, RequireData)->
- file:write_file(PathAndFileName,
- list_to_binary(
- "AuthUserFile "++ BaseDir ++
- "/ht/users.file\nAuthGroupFile "++ BaseDir
- ++ "/ht/groups.file\nAuthName Test\nAuthType"
- " Basic\n<Limit>\nrequire " ++ RequireData ++
- "\n</Limit>")).
-
-create_htaccess_file(PathAndFileName, BaseDir, nouser, IpAddress)->
- file:write_file(PathAndFileName,list_to_binary(
- "AuthUserFile "++ BaseDir ++
- "/ht/users.file\nAuthGroupFile " ++
- BaseDir ++ "/ht/groups.file\nAuthName"
- " Test\nAuthType"
- " Basic\n<Limit GET>\n\tallow from " ++
- format_ip(IpAddress,
- string:rchr(IpAddress,$.)) ++
- "\n</Limit>")).
-
-create_user_group_file(PathAndFileName, Data)->
- file:write_file(PathAndFileName, list_to_binary(Data)).
-
-create_htaccess_dirs(Path)->
- ok = file:make_dir(filename:join([Path,"ht"])),
- ok = file:make_dir(filename:join([Path,"ht/open"])),
- ok = file:make_dir(filename:join([Path,"ht/blocknet"])),
- ok = file:make_dir(filename:join([Path,"ht/secret"])),
- ok = file:make_dir(filename:join([Path,"ht/secret/top_secret"])).
-
-remove_htaccess_dirs(Path)->
- file:del_dir(filename:join([Path,"ht/secret/top_secret"])),
- file:del_dir(filename:join([Path,"ht/secret"])),
- file:del_dir(filename:join([Path,"ht/blocknet"])),
- file:del_dir(filename:join([Path,"ht/open"])),
- file:del_dir(filename:join([Path,"ht"])).
-
-format_ip(IpAddress,Pos)when Pos > 0->
- case lists:nth(Pos,IpAddress) of
- $.->
- case lists:nth(Pos-2,IpAddress) of
- $.->
- format_ip(IpAddress,Pos-3);
- _->
- lists:sublist(IpAddress,Pos-2) ++ "."
- end;
- _ ->
- format_ip(IpAddress,Pos-1)
- end;
-
-format_ip(IpAddress, _Pos)->
- "1" ++ IpAddress.
-
-remove_htaccess(Path)->
- file:delete(filename:join([Path,"ht/open/dummy.html"])),
- file:delete(filename:join([Path,"ht/secret/dummy.html"])),
- file:delete(filename:join([Path,"ht/secret/top_secret/dummy.html"])),
- file:delete(filename:join([Path,"ht/blocknet/dummy.html"])),
- file:delete(filename:join([Path,"ht/blocknet/.htaccess"])),
- file:delete(filename:join([Path,"ht/open/.htaccess"])),
- file:delete(filename:join([Path,"ht/secret/.htaccess"])),
- file:delete(filename:join([Path,"ht/secret/top_secret/.htaccess"])),
- file:delete(filename:join([Path,"ht","users.file"])),
- file:delete(filename:join([Path,"ht","groups.file"])),
- remove_htaccess_dirs(Path).
-
-
-dos_hostname_poll(Type, Host, Port, Node, Hosts) ->
- [dos_hostname_poll1(Type, Host, Port, Node, Host1, Code)
- || {Host1,Code} <- Hosts].
-
-dos_hostname_poll1(Type, Host, Port, Node, Host1, Code) ->
- ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
- dos_hostname_request(Host1),
- [{statuscode, Code},
- {version, "HTTP/1.0"}]).
-
-dos_hostname_request(Host) ->
- "GET / HTTP/1.0\r\n" ++ Host ++ "\r\n\r\n".
-
-get_nof_clients(Mode, Load) ->
- get_nof_clients(test_server:os_type(), Mode, Load).
-
-get_nof_clients(_, ip_comm, light) -> 5;
-get_nof_clients(_, ssl, light) -> 2;
-get_nof_clients(_, ip_comm, medium) -> 10;
-get_nof_clients(_, ssl, medium) -> 4;
-get_nof_clients(_, ip_comm, heavy) -> 20;
-get_nof_clients(_, ssl, heavy) -> 6.
-
-%% Make a file 100 bytes long containing 012...9*10
-create_range_data(Path) ->
- PathAndFileName=filename:join([Path,"range.txt"]),
- file:write_file(PathAndFileName,list_to_binary(["12345678901234567890",
- "12345678901234567890",
- "12345678901234567890",
- "12345678901234567890",
- "12345678901234567890"])).
-
-create_ipv6_config(Config, FileName, Ipv6Address) ->
- ServerRoot = proplists:get_value(server_root, Config),
- TcTopDir = proplists:get_value(tc_top_dir, Config),
- Port = proplists:get_value(port, Config),
- SockType = proplists:get_value(sock_type, Config),
- Mods = io_lib:format("~p", [httpd_mod]),
- Funcs = io_lib:format("~p", [ssl_password_cb]),
- Host = proplists:get_value(ipv6_host, Config),
-
- MaxHdrSz = io_lib:format("~p", [256]),
- MaxHdrAct = io_lib:format("~p", [close]),
-
- Mod_order = "Modules mod_alias mod_auth mod_esi mod_actions mod_cgi"
- " mod_dir mod_get mod_head"
- " mod_log mod_disk_log mod_trace",
-
- SSL =
- if
- (SockType =:= ssl) orelse
- (SockType =:= essl) ->
- [cline(["SSLCertificateFile ",
- filename:join(ServerRoot, "ssl/ssl_server.pem")]),
- cline(["SSLCertificateKeyFile ",
- filename:join(ServerRoot, "ssl/ssl_server.pem")]),
- cline(["SSLCACertificateFile ",
- filename:join(ServerRoot, "ssl/ssl_server.pem")]),
- cline(["SSLPasswordCallbackModule ", Mods]),
- cline(["SSLPasswordCallbackFunction ", Funcs]),
- cline(["SSLVerifyClient 0"]),
- cline(["SSLVerifyDepth 1"])];
- true ->
- []
- end,
-
- BindAddress = "[" ++ Ipv6Address ++"]|inet6",
-
- HttpConfig =
- [cline(["BindAddress ", BindAddress]),
- cline(["Port ", integer_to_list(Port)]),
- cline(["ServerName ", Host]),
- cline(["SocketType ", atom_to_list(SockType)]),
- cline([Mod_order]),
- cline(["ServerRoot ", ServerRoot]),
- cline(["DocumentRoot ", filename:join(ServerRoot, "htdocs")]),
- cline(["MaxHeaderSize ",MaxHdrSz]),
- cline(["MaxHeaderAction ",MaxHdrAct]),
- cline(["DirectoryIndex ", "index.html "]),
- cline(["DefaultType ", "text/plain"]),
- SSL],
- ConfigFile = filename:join([TcTopDir,FileName]),
- {ok, Fd} = file:open(ConfigFile, [write]),
- ok = file:write(Fd, lists:flatten(HttpConfig)),
- ok = file:close(Fd).
-
-
-tsp(F) ->
- inets_test_lib:tsp("[~w]" ++ F, [?MODULE]).
-tsp(F, A) ->
- inets_test_lib:tsp("[~w]" ++ F, [?MODULE|A]).
-
-tsf(Reason) ->
- inets_test_lib:tsf(Reason).
-
diff --git a/lib/inets/test/old_httpd_SUITE_data/Makefile.src b/lib/inets/test/old_httpd_SUITE_data/Makefile.src
deleted file mode 100644
index b0fdb43d8d..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/Makefile.src
+++ /dev/null
@@ -1,14 +0,0 @@
-CC = @CC@
-LD = @LD@
-CFLAGS = @CFLAGS@ -I@erl_include@ @DEFS@
-CROSSLDFLAGS = @CROSSLDFLAGS@
-
-PROGS = cgi_echo@exe@
-
-all: $(PROGS)
-
-cgi_echo@exe@: cgi_echo@obj@
- $(LD) $(CROSSLDFLAGS) -o cgi_echo cgi_echo@obj@ @LIBS@
-
-cgi_echo@obj@: cgi_echo.c
- $(CC) -c -o cgi_echo@obj@ $(CFLAGS) cgi_echo.c
diff --git a/lib/inets/test/old_httpd_SUITE_data/cgi_echo.c b/lib/inets/test/old_httpd_SUITE_data/cgi_echo.c
deleted file mode 100644
index 580f860e96..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/cgi_echo.c
+++ /dev/null
@@ -1,97 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-
-#if defined __WIN32__
-#include <windows.h>
-#include <fcntl.h>
-#endif
-
-static int read_exact(char *buffer, int len);
-static int write_exact(char *buffer, int len);
-
-int main(void)
-{
- char msg[100];
- int msg_len;
-#ifdef __WIN32__
- _setmode(_fileno( stdin), _O_BINARY);
- _setmode(_fileno( stdout), _O_BINARY);
-#endif
- msg_len = read_exact(msg, 100);
-
- write_exact("Content-type: text/plain\r\n\r\n", 28);
- write_exact(msg, msg_len);
- exit(EXIT_SUCCESS);
-}
-
-
-/* read from stdin */
-#ifdef __WIN32__
-static int read_exact(char *buffer, int len)
-{
- HANDLE standard_input = GetStdHandle(STD_INPUT_HANDLE);
-
- unsigned read_result;
- unsigned sofar = 0;
-
- if (!len) { /* Happens for "empty packages */
- return 0;
- }
- for (;;) {
- if (!ReadFile(standard_input, buffer + sofar,
- len - sofar, &read_result, NULL)) {
- return -1; /* EOF */
- }
- if (!read_result) {
- return -2; /* Interrupted while reading? */
- }
- sofar += read_result;
- if (sofar == len) {
- return len;
- }
- }
-}
-#else
-static int read_exact(char *buffer, int len) {
- int i, got = 0;
-
- do {
- if ((i = read(0, buffer + got, len - got)) <= 0)
- return(i);
- got += i;
- } while (got < len);
- return len;
-
-}
-#endif
-
-/* write to stdout */
-#ifdef __WIN32__
- static int write_exact(char *buffer, int len)
- {
- HANDLE standard_output = GetStdHandle(STD_OUTPUT_HANDLE);
- unsigned written;
-
- if (!WriteFile(standard_output, buffer, len, &written, NULL)) {
- return -1; /* Broken Pipe */
- }
- if (written < ((unsigned) len)) {
- /* This should not happen, standard output is not blocking? */
- return -2;
- }
-
- return (int) written;
-}
-
-#else
- static int write_exact(char *buffer, int len) {
- int i, wrote = 0;
-
- do {
- if ((i = write(1, buffer + wrote, len - wrote)) <= 0)
- return i;
- wrote += i;
- } while (wrote < len);
- return len;
- }
-#endif
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/Makefile b/lib/inets/test/old_httpd_SUITE_data/server_root/Makefile
deleted file mode 100644
index ed4d63a3bb..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/Makefile
+++ /dev/null
@@ -1,210 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(INETS_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/inets-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-MODULE=
-
-AUTH_FILES = auth/group \
- auth/passwd
-CGI_FILES = cgi-bin/printenv.sh
-CONF_FILES = conf/8080.conf \
- conf/8888.conf \
- conf/httpd.conf \
- conf/ssl.conf \
- conf/mime.types
-OPEN_FILES = htdocs/open/dummy.html
-MNESIA_OPEN_FILES = htdocs/mnesia_open/dummy.html
-MISC_FILES = htdocs/misc/friedrich.html \
- htdocs/misc/oech.html
-SECRET_FILES = htdocs/secret/dummy.html
-MNESIA_SECRET_FILES = htdocs/mnesia_secret/dummy.html
-HTDOCS_FILES = htdocs/index.html \
- htdocs/config.shtml \
- htdocs/echo.shtml \
- htdocs/exec.shtml \
- htdocs/flastmod.shtml \
- htdocs/fsize.shtml \
- htdocs/include.shtml
-ICON_FILES = icons/README \
- icons/a.gif \
- icons/alert.black.gif \
- icons/alert.red.gif \
- icons/apache_pb.gif \
- icons/back.gif \
- icons/ball.gray.gif \
- icons/ball.red.gif \
- icons/binary.gif \
- icons/binhex.gif \
- icons/blank.gif \
- icons/bomb.gif \
- icons/box1.gif \
- icons/box2.gif \
- icons/broken.gif \
- icons/burst.gif \
- icons/button1.gif \
- icons/button10.gif \
- icons/button2.gif \
- icons/button3.gif \
- icons/button4.gif \
- icons/button5.gif \
- icons/button6.gif \
- icons/button7.gif \
- icons/button8.gif \
- icons/button9.gif \
- icons/buttonl.gif \
- icons/buttonr.gif \
- icons/c.gif \
- icons/comp.blue.gif \
- icons/comp.gray.gif \
- icons/compressed.gif \
- icons/continued.gif \
- icons/dir.gif \
- icons/down.gif \
- icons/dvi.gif \
- icons/f.gif \
- icons/folder.gif \
- icons/folder.open.gif \
- icons/folder.sec.gif \
- icons/forward.gif \
- icons/generic.gif \
- icons/generic.red.gif \
- icons/generic.sec.gif \
- icons/hand.right.gif \
- icons/hand.up.gif \
- icons/htdig.gif \
- icons/icon.sheet.gif \
- icons/image1.gif \
- icons/image2.gif \
- icons/image3.gif \
- icons/index.gif \
- icons/layout.gif \
- icons/left.gif \
- icons/link.gif \
- icons/movie.gif \
- icons/p.gif \
- icons/patch.gif \
- icons/pdf.gif \
- icons/pie0.gif \
- icons/pie1.gif \
- icons/pie2.gif \
- icons/pie3.gif \
- icons/pie4.gif \
- icons/pie5.gif \
- icons/pie6.gif \
- icons/pie7.gif \
- icons/pie8.gif \
- icons/portal.gif \
- icons/poweredby.gif \
- icons/ps.gif \
- icons/quill.gif \
- icons/right.gif \
- icons/screw1.gif \
- icons/screw2.gif \
- icons/script.gif \
- icons/sound1.gif \
- icons/sound2.gif \
- icons/sphere1.gif \
- icons/sphere2.gif \
- icons/star.gif \
- icons/star_blank.gif \
- icons/tar.gif \
- icons/tex.gif \
- icons/text.gif \
- icons/transfer.gif \
- icons/unknown.gif \
- icons/up.gif \
- icons/uu.gif \
- icons/uuencoded.gif \
- icons/world1.gif \
- icons/world2.gif
-
-SSL_FILES = ssl/ssl_client.pem \
- ssl/ssl_server.pem
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_COMPILE_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt:
-
-clean:
-
-docs:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/auth
- $(INSTALL_DATA) $(AUTH_FILES) $(RELSYSDIR)/examples/server_root/auth
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/cgi-bin
- $(INSTALL_SCRIPT) $(CGI_FILES) $(RELSYSDIR)/examples/server_root/cgi-bin
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/conf
- $(INSTALL_DATA) $(CONF_FILES) $(RELSYSDIR)/examples/server_root/conf
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/htdocs/open
- $(INSTALL_DATA) $(OPEN_FILES) \
- $(RELSYSDIR)/examples/server_root/htdocs/open
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/htdocs/mnesia_open
- $(INSTALL_DATA) $(MNESIA_OPEN_FILES) \
- $(RELSYSDIR)/examples/server_root/htdocs/mnesia_open
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/htdocs/misc
- $(INSTALL_DATA) $(MISC_FILES) \
- $(RELSYSDIR)/examples/server_root/htdocs/misc
- $(INSTALL_DIR) \
- $(RELSYSDIR)/examples/server_root/htdocs/secret/top_secret
- $(INSTALL_DIR) \
- $(RELSYSDIR)/examples/server_root/htdocs/mnesia_secret/top_secret
- $(INSTALL_DATA) $(SECRET_FILES) \
- $(RELSYSDIR)/examples/server_root/htdocs/secret
- $(INSTALL_DATA) $(MNESIA_SECRET_FILES) \
- $(RELSYSDIR)/examples/server_root/htdocs/mnesia_secret
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/htdocs
- $(INSTALL_DATA) $(HTDOCS_FILES) $(RELSYSDIR)/examples/server_root/htdocs
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/icons
- $(INSTALL_DATA) $(ICON_FILES) $(RELSYSDIR)/examples/server_root/icons
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/ssl
- $(INSTALL_DATA) $(SSL_FILES) $(RELSYSDIR)/examples/server_root/ssl
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/logs
-
-release_docs_spec:
-
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/auth/group b/lib/inets/test/old_httpd_SUITE_data/server_root/auth/group
deleted file mode 100644
index b3da0ccbd3..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/auth/group
+++ /dev/null
@@ -1,3 +0,0 @@
-group1: one two
-group2: two three
-group3: three Aladdin
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/auth/passwd b/lib/inets/test/old_httpd_SUITE_data/server_root/auth/passwd
deleted file mode 100644
index 8c980ff547..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/auth/passwd
+++ /dev/null
@@ -1,4 +0,0 @@
-one:onePassword
-two:twoPassword
-three:threePassword
-Aladdin:AladdinPassword
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.bat b/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.bat
deleted file mode 100644
index 25a49a1536..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.bat
+++ /dev/null
@@ -1,9 +0,0 @@
-@echo off
-echo tomrad > c:\cygwin\tmp\hej
-echo Content-type: text/html
-echo.
-echo ^<HTML^> ^<HEAD^> ^<TITLE^>OS Environment^</TITLE^> ^</HEAD^> ^<BODY^>^<PRE^>
-set
-echo ^</PRE^>^</BODY^>^</HTML^>
-
-
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.sh b/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.sh
deleted file mode 100755
index de81de9bde..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-echo "Content-type: text/html"
-echo ""
-echo "<HTML> <HEAD> <TITLE>OS Environment</TITLE> </HEAD> <BODY><PRE>"
-env
-echo "</PRE></BODY></HTML>" \ No newline at end of file
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf
deleted file mode 100644
index 7b1b4a15b2..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf
+++ /dev/null
@@ -1,79 +0,0 @@
-Port 8080
-#ServerName your.server.net
-SocketType ip_comm
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log
-ServerAdmin [email protected]
-ServerRoot /var/tmp/server_root
-ErrorLog logs/error_log_8080
-TransferLog logs/access_log_8080
-SecurityLog logs/security_log_8080
-ErrorDiskLog logs/error_disk_log_8080
-ErrorDiskLogSize 200000 10
-TransferDiskLog logs/access_disk_log_8080
-TransferDiskLogSize 200000 10
-SecurityDiskLog logs/security_disk_log
-SecurityDiskLogSize 200000 10
-MaxClients 50
-#KeepAlive 5
-#KeepAliveTimeout 10
-DocumentRoot /var/tmp/server_root/htdocs
-DirectoryIndex index.html welcome.html
-DefaultType text/plain
-Alias /icons/ /var/tmp/server_root/icons/
-Alias /pics/ /var/tmp/server_root/icons/
-ScriptAlias /cgi-bin/ /var/tmp/server_root/cgi-bin/
-ScriptAlias /htbin/ /var/tmp/server_root/cgi-bin/
-ErlScriptAlias /cgi-bin/erl httpd_example io
-EvalScriptAlias /eval httpd_example io
-#Script HEAD /cgi-bin/printenv.sh
-#Action image/gif /cgi-bin/printenv.sh
-
-<Directory /var/tmp/server_root/htdocs/open>
-AuthDBType plain
-AuthName Open Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require user one Aladdin
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/secret>
-AuthDBType plain
-AuthName Secret Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require group group1 group2
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/secret/top_secret>
-AuthDBType plain
-AuthName Top Secret Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require group group3
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_open>
-AuthDBType mnesia
-AuthName Open Area
-require user one Aladdin
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_secret>
-AuthDBType mnesia
-AuthName Secret Area
-require group group1 group2
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_secret/top_secret>
-AuthDBType mnesia
-AuthName Top Secret Area
-require group group3
-allow from 130.100.34 130.100.35
-deny from 100.234.22.12 194.100.34.1 130.100.34.25
-SecurityDataFile logs/security_data
-SecurityMaxRetries 3
-SecurityBlockTime 10
-SecurityFailExpireTime 1
-SecurityAuthTimeout 1
-SecurityCallbackModule security_callback
-</Directory>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf
deleted file mode 100644
index 042779fcd0..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf
+++ /dev/null
@@ -1,63 +0,0 @@
-Port 8888
-#ServerName your.server.net
-SocketType ip_comm
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log
-ServerAdmin [email protected]
-ServerRoot /var/tmp/server_root
-ErrorLog logs/error_log_8888
-TransferLog logs/access_log_8888
-ErrorDiskLog logs/error_disk_log_8888
-ErrorDiskLogSize 200000 10
-TransferDiskLog logs/access_disk_log_8888
-TransferDiskLogSize 200000 10
-MaxClients 150
-DocumentRoot /var/tmp/server_root/htdocs
-DirectoryIndex index.html welcome.html
-DefaultType text/plain
-Alias /icons/ /var/tmp/server_root/icons/
-Alias /pics/ /var/tmp/server_root/icons/
-ScriptAlias /cgi-bin/ /var/tmp/server_root/cgi-bin/
-ScriptAlias /htbin/ /var/tmp/server_root/cgi-bin/
-ErlScriptAlias /cgi-bin/erl httpd_example io
-EvalScriptAlias /eval httpd_example io
-#Script HEAD /cgi-bin/printenv.sh
-#Action image/gif /cgi-bin/printenv.sh
-
-<Directory /var/tmp/server_root/htdocs/open>
-AuthName Open Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require user one Aladdin
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/secret>
-AuthName Secret Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require group group1 group2
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/secret/top_secret>
-AuthName Top Secret Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require group group3
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_open>
-AuthName Open Area
-AuthMnesiaDB On
-require user one Aladdin
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_secret>
-AuthName Secret Area
-AuthMnesiaDB On
-require group group1 group2
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_secret/top_secret>
-AuthName Top Secret Area
-AuthMnesiaDB On
-require group group3
-</Directory>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf
deleted file mode 100644
index 3add93cd73..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf
+++ /dev/null
@@ -1,269 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2017. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-
-# Port: The port the standalone listens to. For ports < 1023, you will
-# need httpd to be run as root initially.
-
-Port 8888
-
-# BindAddress: This directive is used to tell the server which IP address
-# to listen to. It can either contain "*", an IP address, or a fully
-# qualified Internet domain name.
-#
-# It is also possible to specify the ip-family with the directive.
-# There ar three possible value: inet, inet6 and inet6fb4
-# inet: Use IpFamily inet when retreiving the address and
-# fail if that does not work.
-# inet6: Use IpFamily inet6 when retreiving the address and
-# fail if that does not work.
-# inet6fb4: First IpFamily inet6 is tried and if that does not work,
-# inet is used as fallback.
-# Default value for ip-family is inet6fb4
-#
-# The syntax is: <address>[|<ip-family>]
-#
-#BindAddress *
-#BindAddress *|inet
-
-
-# ServerName allows you to set a host name which is sent back to clients for
-# your server if it's different than the one the program would get (i.e. use
-# "www" instead of the host's real name).
-#
-# Note: You cannot just invent host names and hope they work. The name you
-# define here must be a valid DNS name for your host. If you don't understand
-# this, ask your network administrator.
-
-#ServerName your.server.net
-
-# SocketType is either ip_comm, sockets or ssl.
-
-SocketType ip_comm
-
-# Modules: Server run-time plug-in modules written using the Erlang
-# Web Server API (EWSAPI). The server API make it easy to add functionality
-# to the server. Read more about EWSAPI in the Reference Manual.
-# WARNING! Do not tamper with this directive unless you are familiar with
-# EWSAPI.
-
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_responsecontrol mod_trace mod_range mod_head mod_dir mod_get mod_log mod_disk_log
-
-# ServerAdmin: Your address, where problems with the server should be
-# e-mailed.
-
-ServerAdmin [email protected]
-
-# ServerRoot: The directory the server's config, error, and log files
-# are kept in
-
-ServerRoot /var/tmp/server_root
-
-# ErrorLog: The location of the error log file. If this does not start
-# with /, ServerRoot is prepended to it.
-
-ErrorLog logs/error_log
-
-# TransferLog: The location of the transfer log file. If this does not
-# start with /, ServerRoot is prepended to it.
-
-TransferLog logs/access_log
-
-# SecurityLog: The location of the security log file (mod_security required)
-#
-SecurityLog logs/security_log
-
-# ErrorDiskLog: The location of the error log file. If this does not
-# start with /, ServerRoot is prepended to it. This log file is managed
-# with the disk_log module [See disk_log(3)]. The ErrorDiskLogSize directive
-# takes two argument, i.e. MaxBytes and MaxFiles. The wrap log writes at most
-# MaxBytes bytes on each file, and it uses MaxFiles files before it wraps, and
-# truncates the first file.
-
-ErrorDiskLog logs/error_disk_log
-ErrorDiskLogSize 200000 10
-
-# TransferDiskLog: The location of the transfer log file. If this does not
-# start with /, ServerRoot is prepended to it. This log file is managed
-# with the disk_log module [See disk_log(3)]. The TransferDiskLogSize directive
-# takes two argument, i.e. MaxBytes and MaxFiles. The wrap log writes at most
-# MaxBytes bytes on each file, and it uses MaxFiles files before it wraps, and
-# truncates the first file.
-
-TransferDiskLog logs/access_disk_log
-TransferDiskLogSize 200000 10
-
-# SecurityDiskLog: The location of the security log file. If this does not
-# start with /, ServerRoot is prepended to it. This log file is managed
-# with the disk_log module [See disk_log(3)]. The SecurityDiskLogSize directive
-# takes two argument, i.e. MaxBytes and MaxFiles. The wrap log writes at most
-# MaxBytes bytes on each file, and it uses MaxFiles files before it wraps, and
-# truncates the first file.
-
-SecurityDiskLog logs/security_disk_log
-SecurityDiskLogSize 200000 10
-
-# Limit on total number of servers running, i.e., limit on the number
-# of clients who can simultaneously connect --- if this limit is ever
-# reached, clients will be LOCKED OUT, so it should NOT BE SET TOO LOW.
-# It is intended mainly as a brake to keep a runaway server from taking
-# the server with it as it spirals down...
-
-MaxClients 50
-
-# KeepAlive set the flag for persistent connections. For persistent connections
-# set KeepAlive to on. To use One request per connection set the flag to off
-# Note: The value has changed since previous version of INETS.
-KeepAlive on
-
-# KeepAliveTimeout sets the number of seconds before a persistent connection
-# times out and closes.
-KeepAliveTimeout 10
-
-# MaxKeepAliveRequests sets the number of seconds before a persistent connection
-# times out and closes.
-MaxKeepAliveRequests 10
-
-
-
-# DocumentRoot: The directory out of which you will serve your
-# documents. By default, all requests are taken from this directory, but
-# symbolic links and aliases may be used to point to other locations.
-
-DocumentRoot /var/tmp/server_root/htdocs
-
-# DirectoryIndex: Name of the file or files to use as a pre-written HTML
-# directory index. Separate multiple entries with spaces.
-
-DirectoryIndex index.html welcome.html
-
-# DefaultType is the default MIME type for documents which the server
-# cannot find the type of from filename extensions.
-
-DefaultType text/plain
-
-# Aliases: Add here as many aliases as you need (with no limit). The format is
-# Alias fakename realname
-
-Alias /icons/ /var/tmp/server_root/icons/
-Alias /pics/ /var/tmp/server_root/icons/
-
-# ScriptAlias: This controls which directories contain server scripts.
-# Format: ScriptAlias fakename realname
-
-ScriptAlias /cgi-bin/ /var/tmp/server_root/cgi-bin/
-ScriptAlias /htbin/ /var/tmp/server_root/cgi-bin/
-
-# This directive adds an action, which will activate cgi-script when a
-# file is requested using the method of method, which can be one of
-# GET, POST and HEAD. It sends the URL and file path of the requested
-# document using the standard CGI PATH_INFO and PATH_TRANSLATED
-# environment variables.
-
-#Script HEAD /cgi-bin/printenv.sh
-
-# This directive adds an action, which will activate cgi-script when a
-# file of content type mime-type is requested. It sends the URL and
-# file path of the requested document using the standard CGI PATH_INFO
-# and PATH_TRANSLATED environment variables.
-
-#Action image/gif /cgi-bin/printenv.sh
-
-# ErlScriptAlias: This specifies how "Erl" server scripts are called.
-# Format: ErlScriptAlias fakename realname allowed_modules
-
-ErlScriptAlias /down/erl httpd_example io
-
-# EvalScriptAlias: This specifies how "Eval" server scripts are called.
-# Format: EvalScriptAlias fakename realname allowed_modules
-
-EvalScriptAlias /eval httpd_example io
-
-# Point SSLCertificateFile at a PEM encoded certificate.
-
-SSLCertificateFile /var/tmp/server_root/ssl/ssl_server.pem
-
-# If the key is not combined with the certificate, use this directive to
-# point at the key file.
-
-SSLCertificateKeyFile /var/tmp/server_root/ssl/ssl_server.pem
-
-# Set SSLVerifyClient to:
-# 0 if no certicate is required
-# 1 if the client may present a valid certificate
-# 2 if the client must present a valid certificate
-# 3 if the client may present a valid certificate but it is not required to
-# have a valid CA
-
-SSLVerifyClient 0
-
-# Each directory to which INETS has access, can be configured with respect
-# to which services and features are allowed and/or disabled in that
-# directory (and its subdirectories).
-
-<Directory /var/tmp/server_root/htdocs/open>
-AuthDBType plain
-AuthName Open Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require user one Aladdin
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/secret>
-AuthDBType plain
-AuthName Secret Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require group group1 group2
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/secret/top_secret>
-AuthDBType plain
-AuthName Top Secret Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require group group3
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_open>
-AuthDBType mnesia
-AuthName Open Area
-require user one Aladdin
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_secret>
-AuthDBType mnesia
-AuthName Secret Area
-require group group1 group2
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_secret/top_secret>
-AuthDBType mnesia
-AuthName Top Secret Area
-require group group3
-allow from 130.100.34 130.100.35
-deny from 100.234.22.12 194.100.34.1 130.100.34.25
-SecurityDataFile logs/security_data
-SecurityMaxRetries 3
-SecurityBlockTime 10
-SecurityFailExpireTime 1
-SecurityAuthTimeout 1
-SecurityCallbackModule security_callback
-</Directory>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/mime.types b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/mime.types
deleted file mode 100644
index d2f81e4e5e..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/mime.types
+++ /dev/null
@@ -1,465 +0,0 @@
-# This is a comment. I love comments.
-
-# MIME type Extension
-application/EDI-Consent
-application/EDI-X12
-application/EDIFACT
-application/activemessage
-application/andrew-inset ez
-application/applefile
-application/atomicmail
-application/batch-SMTP
-application/beep+xml
-application/cals-1840
-application/commonground
-application/cybercash
-application/dca-rft
-application/dec-dx
-application/dvcs
-application/eshop
-application/http
-application/hyperstudio
-application/iges
-application/index
-application/index.cmd
-application/index.obj
-application/index.response
-application/index.vnd
-application/iotp
-application/ipp
-application/isup
-application/font-tdpfr
-application/mac-binhex40 hqx
-application/mac-compactpro cpt
-application/macwriteii
-application/marc
-application/mathematica
-application/mathematica-old
-application/msword doc
-application/news-message-id
-application/news-transmission
-application/ocsp-request
-application/ocsp-response
-application/octet-stream bin dms lha lzh exe class so dll
-application/oda oda
-application/parityfec
-application/pdf pdf
-application/pgp-encrypted
-application/pgp-keys
-application/pgp-signature
-application/pkcs10
-application/pkcs7-mime
-application/pkcs7-signature
-application/pkix-cert
-application/pkix-crl
-application/pkixcmp
-application/postscript ai eps ps
-application/prs.alvestrand.titrax-sheet
-application/prs.cww
-application/prs.nprend
-application/qsig
-application/remote-printing
-application/riscos
-application/rtf
-application/sdp
-application/set-payment
-application/set-payment-initiation
-application/set-registration
-application/set-registration-initiation
-application/sgml
-application/sgml-open-catalog
-application/sieve
-application/slate
-application/smil smi smil
-application/timestamp-query
-application/timestamp-reply
-application/vemmi
-application/vnd.3M.Post-it-Notes
-application/vnd.FloGraphIt
-application/vnd.accpac.simply.aso
-application/vnd.accpac.simply.imp
-application/vnd.acucobol
-application/vnd.aether.imp
-application/vnd.anser-web-certificate-issue-initiation
-application/vnd.anser-web-funds-transfer-initiation
-application/vnd.audiograph
-application/vnd.businessobjects
-application/vnd.bmi
-application/vnd.canon-cpdl
-application/vnd.canon-lips
-application/vnd.claymore
-application/vnd.commerce-battelle
-application/vnd.commonspace
-application/vnd.comsocaller
-application/vnd.contact.cmsg
-application/vnd.cosmocaller
-application/vnd.cups-postscript
-application/vnd.cups-raster
-application/vnd.cups-raw
-application/vnd.ctc-posml
-application/vnd.cybank
-application/vnd.dna
-application/vnd.dpgraph
-application/vnd.dxr
-application/vnd.ecdis-update
-application/vnd.ecowin.chart
-application/vnd.ecowin.filerequest
-application/vnd.ecowin.fileupdate
-application/vnd.ecowin.series
-application/vnd.ecowin.seriesrequest
-application/vnd.ecowin.seriesupdate
-application/vnd.enliven
-application/vnd.epson.esf
-application/vnd.epson.msf
-application/vnd.epson.quickanime
-application/vnd.epson.salt
-application/vnd.epson.ssf
-application/vnd.ericsson.quickcall
-application/vnd.eudora.data
-application/vnd.fdf
-application/vnd.ffsns
-application/vnd.framemaker
-application/vnd.fsc.weblaunch
-application/vnd.fujitsu.oasys
-application/vnd.fujitsu.oasys2
-application/vnd.fujitsu.oasys3
-application/vnd.fujitsu.oasysgp
-application/vnd.fujitsu.oasysprs
-application/vnd.fujixerox.ddd
-application/vnd.fujixerox.docuworks
-application/vnd.fujixerox.docuworks.binder
-application/vnd.fut-misnet
-application/vnd.grafeq
-application/vnd.groove-account
-application/vnd.groove-identity-message
-application/vnd.groove-injector
-application/vnd.groove-tool-message
-application/vnd.groove-tool-template
-application/vnd.groove-vcard
-application/vnd.hhe.lesson-player
-application/vnd.hp-HPGL
-application/vnd.hp-PCL
-application/vnd.hp-PCLXL
-application/vnd.hp-hpid
-application/vnd.hp-hps
-application/vnd.httphone
-application/vnd.hzn-3d-crossword
-application/vnd.ibm.afplinedata
-application/vnd.ibm.MiniPay
-application/vnd.ibm.modcap
-application/vnd.informix-visionary
-application/vnd.intercon.formnet
-application/vnd.intertrust.digibox
-application/vnd.intertrust.nncp
-application/vnd.intu.qbo
-application/vnd.intu.qfx
-application/vnd.irepository.package+xml
-application/vnd.is-xpr
-application/vnd.japannet-directory-service
-application/vnd.japannet-jpnstore-wakeup
-application/vnd.japannet-payment-wakeup
-application/vnd.japannet-registration
-application/vnd.japannet-registration-wakeup
-application/vnd.japannet-setstore-wakeup
-application/vnd.japannet-verification
-application/vnd.japannet-verification-wakeup
-application/vnd.koan
-application/vnd.lotus-1-2-3
-application/vnd.lotus-approach
-application/vnd.lotus-freelance
-application/vnd.lotus-notes
-application/vnd.lotus-organizer
-application/vnd.lotus-screencam
-application/vnd.lotus-wordpro
-application/vnd.mcd
-application/vnd.mediastation.cdkey
-application/vnd.meridian-slingshot
-application/vnd.mif mif
-application/vnd.minisoft-hp3000-save
-application/vnd.mitsubishi.misty-guard.trustweb
-application/vnd.mobius.daf
-application/vnd.mobius.dis
-application/vnd.mobius.msl
-application/vnd.mobius.plc
-application/vnd.mobius.txf
-application/vnd.motorola.flexsuite
-application/vnd.motorola.flexsuite.adsi
-application/vnd.motorola.flexsuite.fis
-application/vnd.motorola.flexsuite.gotap
-application/vnd.motorola.flexsuite.kmr
-application/vnd.motorola.flexsuite.ttc
-application/vnd.motorola.flexsuite.wem
-application/vnd.mozilla.xul+xml
-application/vnd.ms-artgalry
-application/vnd.ms-asf
-application/vnd.ms-excel xls
-application/vnd.ms-lrm
-application/vnd.ms-powerpoint ppt
-application/vnd.ms-project
-application/vnd.ms-tnef
-application/vnd.ms-works
-application/vnd.mseq
-application/vnd.msign
-application/vnd.music-niff
-application/vnd.musician
-application/vnd.netfpx
-application/vnd.noblenet-directory
-application/vnd.noblenet-sealer
-application/vnd.noblenet-web
-application/vnd.novadigm.EDM
-application/vnd.novadigm.EDX
-application/vnd.novadigm.EXT
-application/vnd.osa.netdeploy
-application/vnd.palm
-application/vnd.pg.format
-application/vnd.pg.osasli
-application/vnd.powerbuilder6
-application/vnd.powerbuilder6-s
-application/vnd.powerbuilder7
-application/vnd.powerbuilder7-s
-application/vnd.powerbuilder75
-application/vnd.powerbuilder75-s
-application/vnd.previewsystems.box
-application/vnd.publishare-delta-tree
-application/vnd.pvi.ptid1
-application/vnd.pwg-xhtml-print+xml
-application/vnd.rapid
-application/vnd.s3sms
-application/vnd.seemail
-application/vnd.shana.informed.formdata
-application/vnd.shana.informed.formtemplate
-application/vnd.shana.informed.interchange
-application/vnd.shana.informed.package
-application/vnd.sss-cod
-application/vnd.sss-dtf
-application/vnd.sss-ntf
-application/vnd.street-stream
-application/vnd.svd
-application/vnd.swiftview-ics
-application/vnd.triscape.mxs
-application/vnd.trueapp
-application/vnd.truedoc
-application/vnd.tve-trigger
-application/vnd.ufdl
-application/vnd.uplanet.alert
-application/vnd.uplanet.alert-wbxml
-application/vnd.uplanet.bearer-choice-wbxml
-application/vnd.uplanet.bearer-choice
-application/vnd.uplanet.cacheop
-application/vnd.uplanet.cacheop-wbxml
-application/vnd.uplanet.channel
-application/vnd.uplanet.channel-wbxml
-application/vnd.uplanet.list
-application/vnd.uplanet.list-wbxml
-application/vnd.uplanet.listcmd
-application/vnd.uplanet.listcmd-wbxml
-application/vnd.uplanet.signal
-application/vnd.vcx
-application/vnd.vectorworks
-application/vnd.vidsoft.vidconference
-application/vnd.visio
-application/vnd.vividence.scriptfile
-application/vnd.wap.sic
-application/vnd.wap.slc
-application/vnd.wap.wbxml wbxml
-application/vnd.wap.wmlc wmlc
-application/vnd.wap.wmlscriptc wmlsc
-application/vnd.webturbo
-application/vnd.wrq-hp3000-labelled
-application/vnd.wt.stf
-application/vnd.xara
-application/vnd.xfdl
-application/vnd.yellowriver-custom-menu
-application/whoispp-query
-application/whoispp-response
-application/wita
-application/wordperfect5.1
-application/x-bcpio bcpio
-application/x-cdlink vcd
-application/x-chess-pgn pgn
-application/x-compress
-application/x-cpio cpio
-application/x-csh csh
-application/x-director dcr dir dxr
-application/x-dvi dvi
-application/x-futuresplash spl
-application/x-gtar gtar
-application/x-gzip
-application/x-hdf hdf
-application/x-javascript js
-application/x-koan skp skd skt skm
-application/x-latex latex
-application/x-netcdf nc cdf
-application/x-sh sh
-application/x-shar shar
-application/x-shockwave-flash swf
-application/x-stuffit sit
-application/x-sv4cpio sv4cpio
-application/x-sv4crc sv4crc
-application/x-tar tar
-application/x-tcl tcl
-application/x-tex tex
-application/x-texinfo texinfo texi
-application/x-troff t tr roff
-application/x-troff-man man
-application/x-troff-me me
-application/x-troff-ms ms
-application/x-ustar ustar
-application/x-wais-source src
-application/x400-bp
-application/xml
-application/xml-dtd
-application/xml-external-parsed-entity
-application/zip zip
-audio/32kadpcm
-audio/basic au snd
-audio/g.722.1
-audio/l16
-audio/midi mid midi kar
-audio/mp4a-latm
-audio/mpa-robust
-audio/mpeg mpga mp2 mp3
-audio/parityfec
-audio/prs.sid
-audio/telephone-event
-audio/tone
-audio/vnd.cisco.nse
-audio/vnd.cns.anp1
-audio/vnd.cns.inf1
-audio/vnd.digital-winds
-audio/vnd.everad.plj
-audio/vnd.lucent.voice
-audio/vnd.nortel.vbk
-audio/vnd.nuera.ecelp4800
-audio/vnd.nuera.ecelp7470
-audio/vnd.nuera.ecelp9600
-audio/vnd.octel.sbc
-audio/vnd.qcelp
-audio/vnd.rhetorex.32kadpcm
-audio/vnd.vmx.cvsd
-audio/x-aiff aif aiff aifc
-audio/x-mpegurl m3u
-audio/x-pn-realaudio ram rm
-audio/x-pn-realaudio-plugin rpm
-audio/x-realaudio ra
-audio/x-wav wav
-chemical/x-pdb pdb
-chemical/x-xyz xyz
-image/bmp bmp
-image/cgm
-image/g3fax
-image/gif gif
-image/ief ief
-image/jpeg jpeg jpg jpe
-image/naplps
-image/png png
-image/prs.btif
-image/prs.pti
-image/tiff tiff tif
-image/vnd.cns.inf2
-image/vnd.dwg
-image/vnd.dxf
-image/vnd.fastbidsheet
-image/vnd.fpx
-image/vnd.fst
-image/vnd.fujixerox.edmics-mmr
-image/vnd.fujixerox.edmics-rlc
-image/vnd.mix
-image/vnd.net-fpx
-image/vnd.svf
-image/vnd.wap.wbmp wbmp
-image/vnd.xiff
-image/x-cmu-raster ras
-image/x-portable-anymap pnm
-image/x-portable-bitmap pbm
-image/x-portable-graymap pgm
-image/x-portable-pixmap ppm
-image/x-rgb rgb
-image/x-xbitmap xbm
-image/x-xpixmap xpm
-image/x-xwindowdump xwd
-message/delivery-status
-message/disposition-notification
-message/external-body
-message/http
-message/news
-message/partial
-message/rfc822
-message/s-http
-model/iges igs iges
-model/mesh msh mesh silo
-model/vnd.dwf
-model/vnd.flatland.3dml
-model/vnd.gdl
-model/vnd.gs-gdl
-model/vnd.gtw
-model/vnd.mts
-model/vnd.vtu
-model/vrml wrl vrml
-multipart/alternative
-multipart/appledouble
-multipart/byteranges
-multipart/digest
-multipart/encrypted
-multipart/form-data
-multipart/header-set
-multipart/mixed
-multipart/parallel
-multipart/related
-multipart/report
-multipart/signed
-multipart/voice-message
-text/calendar
-text/css css
-text/directory
-text/enriched
-text/html html htm
-text/parityfec
-text/plain asc txt
-text/prs.lines.tag
-text/rfc822-headers
-text/richtext rtx
-text/rtf rtf
-text/sgml sgml sgm
-text/tab-separated-values tsv
-text/t140
-text/uri-list
-text/vnd.DMClientScript
-text/vnd.IPTC.NITF
-text/vnd.IPTC.NewsML
-text/vnd.abc
-text/vnd.curl
-text/vnd.flatland.3dml
-text/vnd.fly
-text/vnd.fmi.flexstor
-text/vnd.in3d.3dml
-text/vnd.in3d.spot
-text/vnd.latex-z
-text/vnd.motorola.reflex
-text/vnd.ms-mediapackage
-text/vnd.wap.si
-text/vnd.wap.sl
-text/vnd.wap.wml wml
-text/vnd.wap.wmlscript wmls
-text/x-setext etx
-text/x-server-parsed-html shtml
-text/xml xml xsl
-text/xml-external-parsed-entity
-video/mp4v-es
-video/mpeg mpeg mpg mpe
-video/parityfec
-video/pointer
-video/quicktime qt mov
-video/vnd.fvt
-video/vnd.motorola.video
-video/vnd.motorola.videop
-video/vnd.mpegurl mxu
-video/vnd.mts
-video/vnd.nokia.interleaved-multimedia
-video/vnd.vivo
-video/x-msvideo avi
-video/x-sgi-movie movie
-x-conference/x-cooltalk ice
-
-
-
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf
deleted file mode 100644
index de49ceafd0..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf
+++ /dev/null
@@ -1,66 +0,0 @@
-Port 8088
-#ServerName your.server.net
-SocketType ssl
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log
-ServerAdmin [email protected]
-ServerRoot /var/tmp/server_root
-ErrorLog logs/error_log_8088
-TransferLog logs/access_log_8088
-ErrorDiskLog logs/error_disk_log_8088
-ErrorDiskLogSize 200000 10
-TransferDiskLog logs/access_disk_log_8088
-TransferDiskLogSize 200000 10
-MaxClients 150
-DocumentRoot /var/tmp/server_root/htdocs
-DirectoryIndex index.html welcome.html
-DefaultType text/plain
-Alias /icons/ /var/tmp/server_root/icons/
-Alias /pics/ /var/tmp/server_root/icons/
-ScriptAlias /cgi-bin/ /var/tmp/server_root/cgi-bin/
-ScriptAlias /htbin/ /var/tmp/server_root/cgi-bin/
-ErlScriptAlias /cgi-bin/erl httpd_example io
-EvalScriptAlias /eval httpd_example io
-SSLCertificateFile /var/tmp/server_root/ssl/ssl_server.pem
-SSLCertificateKeyFile /var/tmp/server_root/ssl/ssl_server.pem
-SSLVerifyClient 0
-#Script HEAD /cgi-bin/printenv.sh
-#Action image/gif /cgi-bin/printenv.sh
-
-<Directory /var/tmp/server_root/htdocs/open>
-AuthName Open Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require user one Aladdin
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/secret>
-AuthName Secret Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require group group1 group2
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/secret/top_secret>
-AuthName Top Secret Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require group group3
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_open>
-AuthName Open Area
-AuthMnesiaDB On
-require user one Aladdin
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_secret>
-AuthName Secret Area
-AuthMnesiaDB On
-require group group1 group2
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_secret/top_secret>
-AuthName Top Secret Area
-AuthMnesiaDB On
-require group group3
-</Directory>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/config.shtml b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/config.shtml
deleted file mode 100644
index 107e3ff610..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/config.shtml
+++ /dev/null
@@ -1,70 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>/ssi.html (17-Apr-1997)</TITLE>
-</HEAD>
-<BODY>
-<H1>/ssi.html</H1>
-
-<!-- ************* CONFIG ************* -->
-
-<!--#config timefmt="%a %b %e %T %Z %Y" sizefmt="abbrev"-->
-<!--#config errmsg="[an especially ugly error occurred while processing this directive]"-->
-
-<!-- ************* INCLUDE ************* -->
-
-<P>Include /misc/friedrich.html:
-<!--#include virtual="/misc/friedrich.html"-->
-<P>Include /misc/not_defined.html: <!--#include virtual="/misc/not_defined.html"-->
-<P>Include misc/friedrich.html:
-<!--#include file="misc/friedrich.html"-->
-<P>Include not_defined.html: <!--#include file="not_defined.html"-->
-
-<P><HR>
-
-<!-- ************* ECHO ************* -->
-
-<P>DOCUMENT_NAME: <!--#echo var="DOCUMENT_NAME"-->
-<P>DOCUMENT_URI: <!--#echo var="DOCUMENT_URI"-->
-<P>QUERY_STRING_UNESCAPED: <!--#echo var="QUERY_STRING_UNESCAPED"-->
-<P>DATE_LOCAL: <!--#echo var="DATE_LOCAL"-->
-<P>DATE_GMT: <!--#echo var="DATE_GMT"-->
-<P>LAST_MODIFIED: <!--#echo var="LAST_MODIFIED"-->
-<P>NOT_DEFINED: <!--#echo var="NOT_DEFINED"-->
-
-<P><HR>
-
-<!-- ************* FSIZE ************* -->
-
-<P>Size of index.html: <!--#fsize file="index.html"-->
-<P>Size of not_defined.html: <!--#fsize file="not_defined.html"-->
-<!--#config sizefmt="bytes"-->
-<P>Size of /misc/friedrich.html: <!--#fsize virtual="/misc/friedrich.html"-->
-<P>Size of /misc/not_defined.html: <!--#fsize virtual="/misc/not_defined.html"-->
-
-<P><HR>
-
-<!-- ************* FLASTMOD ************* -->
-
-<P>Last modification of index.html: <!--#flastmod file="index.html"-->
-<P>Last modification of not_defined.html: <!--#flastmod file="not_defined.html"-->
-<P>Last modification of /misc/friedrich.html: <!--#flastmod virtual="/misc/friedrich.html"-->
-<P>Last modification of /misc/not_defined.html: <!--#flastmod virtual="/misc/not_defined.html"-->
-
-<!--#exec cmd="ls"-->
-<!--#exec cmd="printenv"-->
-<!--#exec cmd="sunemaja"-->
-
-<!--#exec cgi="/cgi-bin/printenv.sh"-->
-
-</BODY>
-</HTML>
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_open/dummy.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_open/dummy.html
deleted file mode 100644
index a6e8a35a04..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_open/dummy.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>/open/dummy.html (17-Apr-1997)</TITLE>
-<!-- Created by: Joakim Greben�, 17-Apr-1997 -->
-<!-- Changed by: Joakim Greben�, 17-Apr-1997 -->
-</HEAD>
-<BODY>
-<H1>/open/dummy.html</H1>
-</BODY>
-</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/dummy.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/dummy.html
deleted file mode 100644
index 016b04e540..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/dummy.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>/secret/dummy.html (17-Apr-1997)</TITLE>
-<!-- Created by: Joakim Greben�, 17-Apr-1997 -->
-<!-- Changed by: Joakim Greben�, 17-Apr-1997 -->
-</HEAD>
-<BODY>
-<H1>/secret/dummy.html</H1>
-</BODY>
-</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/top_secret/index.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/top_secret/index.html
deleted file mode 100644
index 34db3d5d1a..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/top_secret/index.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>/secret/top_secret/index.html (04-Feb-1998)</TITLE>
-<!-- Created by: Mattias Nilsson, 04-Feb-1998 -->
-</HEAD>
-<BODY>
-<H1>/secret/top_secret/index.html</H1>
-</BODY>
-</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/echo.shtml b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/echo.shtml
deleted file mode 100644
index 141db5be59..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/echo.shtml
+++ /dev/null
@@ -1,35 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>/echo.shtml</TITLE>
-</HEAD>
-<BODY>
-<H1>/echo.shtml</H1>
-
-<P>DOCUMENT_NAME: <!--#echo var="DOCUMENT_NAME"-->
-
-<P>DOCUMENT_URI: <!--#echo var="DOCUMENT_URI"-->
-
-<P>QUERY_STRING_UNESCAPED: <!--#echo var="QUERY_STRING_UNESCAPED"-->
-
-<P>DATE_LOCAL: <!--#echo var="DATE_LOCAL"-->
-
-<P>DATE_GMT: <!--#echo var="DATE_GMT"-->
-
-<P>LAST_MODIFIED: <!--#echo var="LAST_MODIFIED"-->
-
-<P>NOT_DEFINED: <!--#echo var="NOT_DEFINED"-->
-
-<P>[<A HREF="ssi.html">Back</A>]
-
-</BODY>
-</HTML>
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/exec.shtml b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/exec.shtml
deleted file mode 100644
index 97333da898..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/exec.shtml
+++ /dev/null
@@ -1,30 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>/exec.shtml</TITLE>
-</HEAD>
-<BODY>
-<H1>/exec.shtml</H1>
-<PRE>
-<!--#exec cmd="ls"-->
-<HR>
-<!--#exec cmd="printenv"-->
-<HR>
-<!--#exec cmd="sunemaja"-->
-<HR>
-<!--#exec cgi="/cgi-bin/printenv.sh"-->
-</PRE>
-
-<P>[<A HREF="ssi.html">Back</A>]
-
-</BODY>
-</HTML>
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/flastmod.shtml b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/flastmod.shtml
deleted file mode 100644
index d54c36fe50..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/flastmod.shtml
+++ /dev/null
@@ -1,29 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>/flastmod.shtml</TITLE>
-</HEAD>
-<BODY>
-<H1>/flastmod.shtml</H1>
-
-<P>Last modification of index.html: <!--#flastmod file="index.html"-->
-
-<P>Last modification of not_defined.html: <!--#flastmod file="not_defined.html"-->
-
-<P>Last modification of /misc/friedrich.html: <!--#flastmod virtual="/misc/friedrich.html"-->
-
-<P>Last modification of /misc/not_defined.html: <!--#flastmod virtual="/misc/not_defined.html"-->
-
-<P>[<A HREF="ssi.html">Back</A>]
-
-</BODY>
-</HTML>
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/fsize.shtml b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/fsize.shtml
deleted file mode 100644
index 570ee9cf6d..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/fsize.shtml
+++ /dev/null
@@ -1,29 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>/fsize.shtml</TITLE>
-</HEAD>
-<BODY>
-<H1>/fsize.shtml</H1>
-
-<P>Size of index.html: <!--#fsize file="index.html"-->
-
-<P>Size of not_defined.html: <!--#fsize file="not_defined.html"-->
-
-<P>Size of /misc/friedrich.html: <!--#fsize virtual="/misc/friedrich.html"-->
-
-<P>Size of /misc/not_defined.html: <!--#fsize virtual="/misc/not_defined.html"-->
-
-<P>[<A HREF="ssi.html">Back</A>]
-
-</BODY>
-</HTML>
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/include.shtml b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/include.shtml
deleted file mode 100644
index 529aad0437..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/include.shtml
+++ /dev/null
@@ -1,33 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>/include.shtml</TITLE>
-</HEAD>
-<BODY>
-<H1>/include.shtml</H1>
-
-<P>Include /misc/friedrich.html:
-<!--#include virtual="/misc/friedrich.html"-->
-
-<P>Include /misc/not_defined.html:
-<!--#include virtual="/misc/not_defined.html"-->
-
-<P>Include misc/friedrich.html:
-<!--#include file="misc/friedrich.html"-->
-
-<P>Include not_defined.html:
-<!--#include file="not_defined.html"-->
-
-<P>[<A HREF="ssi.html">Back</A>]
-
-</BODY>
-</HTML>
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/index.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/index.html
deleted file mode 100644
index cfdc9f9ab7..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/index.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>/index.html</TITLE>
-</HEAD>
-<BODY>
-<H1>/index.html</H1>
-
-<STRONG>Server-Side Include (SSI) commands:</STRONG><BR>
-<A HREF="config.shtml">config</A><BR>
-<A HREF="echo.shtml">echo</A><BR>
-<A HREF="exec.shtml">exec</A><BR>
-<A HREF="flastmod.shtml">flastmod</A><BR>
-<A HREF="fsize.shtml">fsize</A><BR>
-<A HREF="include.shtml">include</A><BR>
-
-<BR>
-<BR>
-
-<STRONG>ESI callback:</STRING><BR>
-<A HREF="cgi-bin/erl/httpd_example/get">cgi-bin/erl/httpd_example/get</A><BR>
-<A HREF="cgi-bin/erl/httpd_example/yahoo">cgi-bin/erl/httpd_example/yahoo</A><BR>
-<A HREF="cgi-bin/erl/httpd_example/test1">cgi-bin/erl/httpd_example/test1</A><BR>
-
-</BODY>
-</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/last_modified.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/last_modified.html
deleted file mode 100644
index 65c1790813..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/last_modified.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>/last_modified.html</TITLE>
-</HEAD>
-<BODY>
-<H1>/last_modified.html</H1>
-
-<P>This document is only used for test of illegal last-modified date.</P>
-
-
-</BODY>
-</HTML>
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/friedrich.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/friedrich.html
deleted file mode 100644
index d7953d5df4..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/friedrich.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<P><CITE>
-Talking much about oneself can also be a means to conceal oneself.<BR>
--- Friedrich Nietzsche
-</CITE>
-
-<P>Nested Include:
-<!--#include file="misc/oech.html"-->
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/oech.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/oech.html
deleted file mode 100644
index 506064bf04..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/oech.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<P><CITE>
-What excuses stand in your way? How can you eliminate them?<BR>
--- Roger von Oech
-</CITE>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/welcome.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/welcome.html
deleted file mode 100644
index 8c17451f91..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/welcome.html
+++ /dev/null
@@ -1 +0,0 @@
-<HTML></HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_open/dummy.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_open/dummy.html
deleted file mode 100644
index a6e8a35a04..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_open/dummy.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>/open/dummy.html (17-Apr-1997)</TITLE>
-<!-- Created by: Joakim Greben�, 17-Apr-1997 -->
-<!-- Changed by: Joakim Greben�, 17-Apr-1997 -->
-</HEAD>
-<BODY>
-<H1>/open/dummy.html</H1>
-</BODY>
-</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/dummy.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/dummy.html
deleted file mode 100644
index 016b04e540..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/dummy.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>/secret/dummy.html (17-Apr-1997)</TITLE>
-<!-- Created by: Joakim Greben�, 17-Apr-1997 -->
-<!-- Changed by: Joakim Greben�, 17-Apr-1997 -->
-</HEAD>
-<BODY>
-<H1>/secret/dummy.html</H1>
-</BODY>
-</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/top_secret/index.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/top_secret/index.html
deleted file mode 100644
index 2d17e8b596..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/top_secret/index.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>/mnesia_secret/top_secret/index.html (04-Feb-1998)</TITLE>
-<!-- Created by: Mattias Nilsson, 04-Feb-1998 -->
-</HEAD>
-<BODY>
-<H1>/mnesia_secret/top_secret/index.html</H1>
-</BODY>
-</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/open/dummy.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/open/dummy.html
deleted file mode 100644
index a6e8a35a04..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/open/dummy.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>/open/dummy.html (17-Apr-1997)</TITLE>
-<!-- Created by: Joakim Greben�, 17-Apr-1997 -->
-<!-- Changed by: Joakim Greben�, 17-Apr-1997 -->
-</HEAD>
-<BODY>
-<H1>/open/dummy.html</H1>
-</BODY>
-</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/dummy.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/dummy.html
deleted file mode 100644
index 016b04e540..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/dummy.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>/secret/dummy.html (17-Apr-1997)</TITLE>
-<!-- Created by: Joakim Greben�, 17-Apr-1997 -->
-<!-- Changed by: Joakim Greben�, 17-Apr-1997 -->
-</HEAD>
-<BODY>
-<H1>/secret/dummy.html</H1>
-</BODY>
-</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/top_secret/index.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/top_secret/index.html
deleted file mode 100644
index 34db3d5d1a..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/top_secret/index.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>/secret/top_secret/index.html (04-Feb-1998)</TITLE>
-<!-- Created by: Mattias Nilsson, 04-Feb-1998 -->
-</HEAD>
-<BODY>
-<H1>/secret/top_secret/index.html</H1>
-</BODY>
-</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/README b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/README
deleted file mode 100644
index a1fc5a5a9c..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/README
+++ /dev/null
@@ -1,161 +0,0 @@
-Public Domain Icons
-
- These icons were originally made for Mosaic for X and have been
- included in the NCSA httpd and Apache server distributions in the
- past. They are in the public domain and may be freely included in any
- application. The originals were done by Kevin Hughes ([email protected]).
-
- Many thanks to Andy Polyakov for tuning the icon colors and adding a
- few new images. If you'd like to contribute additions or ideas to
- this set, please let me know.
-
- The distribution site for these icons is at:
-
- http://www.eit.com/goodies/www.icons/
-
- Kevin Hughes
- September 11, 1995
-
-
-Suggested Uses
-
-The following are a few suggestions, to serve as a starting point for ideas.
-Please feel free to tweak and rename the icons as you like.
-
- a.gif
- This might be used to represent PostScript or text layout
- languages.
-
- alert.black.gif, alert.red.gif
- These can be used to highlight any important items, such as a
- README file in a directory.
-
- back.gif, forward.gif
- These can be used as links to go to previous and next areas.
-
- ball.gray.gif, ball.red.gif
- These might be used as bullets.
-
- binary.gif
- This can be used to represent binary files.
-
- binhex.gif
- This can represent BinHex-encoded data.
-
- blank.gif
- This can be used as a placeholder or a spacing element.
-
- bomb.gif
- This can be used to repreesnt core files.
-
- box1.gif, box2.gif
- These icons can be used to represent generic 3D applications and
- related files.
-
- broken.gif
- This can represent corrupted data.
-
- burst.gif
- This can call attention to new and important items.
-
- c.gif
- This might represent C source code.
-
- comp.blue.gif, comp.red.gif
- These little computer icons can stand for telnet or FTP
- sessions.
-
- compressed.gif
- This may represent compressed data.
-
- continued.gif
- This can be a link to a continued listing of a directory.
-
- down.gif, up.gif, left.gif, right.gif
- These can be used to scroll up, down, left and right in a
- listing or may be used to denote items in an outline.
-
- dvi.gif
- This can represent DVI files.
-
- f.gif
- This might represent FORTRAN or Forth source code.
-
- folder.gif, folder.open.gif, folder.sec.gif
- The folder can represent directories. There is also a version
- that can represent secure directories or directories that cannot
- be viewed.
-
- generic.gif, generic.sec.gif, generic.red.gif
- These can represent generic files, secure files, and important
- files, respectively.
-
- hand.right.gif, hand.up.gif
- These can point out important items (pun intended).
-
- image1.gif, image2.gif, image3.gif
- These can represent image formats of various types.
-
- index.gif
- This might represent a WAIS index or search facility.
-
- layout.gif
- This might represent files and formats that contain graphics as
- well as text layout, such as HTML and PDF files.
-
- link.gif
- This might represent files that are symbolic links.
-
- movie.gif
- This can represent various movie formats.
-
- p.gif
- This may stand for Perl or Python source code.
-
- pie0.gif ... pie8.gif
- These icons can be used in applications where a list of
- documents is returned from a search. The little pie chart images
- can denote how relevant the documents may be to your search
- query.
-
- patch.gif
- This may stand for patches and diff files.
-
- portal.gif
- This might be a link to an online service or a 3D world.
-
- ps.gif, quill.gif
- These may represent PostScript files.
-
- screw1.gif, screw2.gif
- These may represent CAD or engineering data and formats.
-
- script.gif
- This can represent any of various interpreted languages, such as
- Perl, python, TCL, and shell scripts, as well as server
- configuration files.
-
- sound1.gif, sound2.gif
- These can represent sound files.
-
- sphere1.gif, sphere2.gif
- These can represent 3D worlds or rendering applications and
- formats.
-
- tex.gif
- This can represent TeX files.
-
- text.gif
- This can represent generic (plain) text files.
-
- transfer.gif
- This can represent FTP transfers or uploads/downloads.
-
- unknown.gif
- This may represent a file of an unknown type.
-
- uuencoded.gif
- This can stand for uuencoded data.
-
- world1.gif, world2.gif
- These can represent 3D worlds or other 3D formats.
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/a.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/a.gif
deleted file mode 100644
index bb23d971f4..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/a.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.black.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.black.gif
deleted file mode 100644
index eaecd2172a..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.black.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.red.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.red.gif
deleted file mode 100644
index a423894043..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.red.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/apache_pb.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/apache_pb.gif
deleted file mode 100644
index 3a1c139fc4..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/apache_pb.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/back.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/back.gif
deleted file mode 100644
index a694ae1ec3..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/back.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.gray.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.gray.gif
deleted file mode 100644
index eb84268c4c..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.gray.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.red.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.red.gif
deleted file mode 100644
index a8425cb574..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.red.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binary.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binary.gif
deleted file mode 100644
index 9a15cbae04..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binary.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binhex.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binhex.gif
deleted file mode 100644
index 62d0363108..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binhex.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/blank.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/blank.gif
deleted file mode 100644
index 0ccf01e198..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/blank.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/bomb.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/bomb.gif
deleted file mode 100644
index 270fdb1c06..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/bomb.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box1.gif
deleted file mode 100644
index 65dcd002ea..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box1.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box2.gif
deleted file mode 100644
index c43bc4faec..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box2.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/broken.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/broken.gif
deleted file mode 100644
index 9f8cbe9f76..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/broken.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/burst.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/burst.gif
deleted file mode 100644
index fbdcf575f7..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/burst.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button1.gif
deleted file mode 100644
index eb97cb7333..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button1.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button10.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button10.gif
deleted file mode 100644
index fe0c97998c..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button10.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button2.gif
deleted file mode 100644
index 7698455bf9..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button2.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button3.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button3.gif
deleted file mode 100644
index a8b8319232..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button3.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button4.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button4.gif
deleted file mode 100644
index 0fd15a0d7f..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button4.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button5.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button5.gif
deleted file mode 100644
index 64241e5c5d..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button5.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button6.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button6.gif
deleted file mode 100644
index 867cfd1212..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button6.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button7.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button7.gif
deleted file mode 100644
index b3f5fb248f..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button7.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button8.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button8.gif
deleted file mode 100644
index 7a308be8f6..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button8.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button9.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button9.gif
deleted file mode 100644
index 9acba576c0..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button9.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonl.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonl.gif
deleted file mode 100644
index 3883088e7a..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonl.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonr.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonr.gif
deleted file mode 100644
index c4dc3887db..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonr.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/c.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/c.gif
deleted file mode 100644
index 7555b6c164..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/c.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.blue.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.blue.gif
deleted file mode 100644
index f8d76a8c23..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.blue.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.gray.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.gray.gif
deleted file mode 100644
index 7664cd0364..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.gray.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/compressed.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/compressed.gif
deleted file mode 100644
index 39e732739f..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/compressed.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/continued.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/continued.gif
deleted file mode 100644
index b0ffb7e0cc..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/continued.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dir.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dir.gif
deleted file mode 100644
index 48264601ae..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dir.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/down.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/down.gif
deleted file mode 100644
index a354c871cd..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/down.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dvi.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dvi.gif
deleted file mode 100644
index 791be33105..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dvi.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/f.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/f.gif
deleted file mode 100644
index fbe353c282..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/f.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.gif
deleted file mode 100644
index 48264601ae..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.open.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.open.gif
deleted file mode 100644
index 30979cb528..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.open.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.sec.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.sec.gif
deleted file mode 100644
index 75332d9e59..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.sec.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/forward.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/forward.gif
deleted file mode 100644
index b2959b4c85..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/forward.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.gif
deleted file mode 100644
index de60b2940f..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.red.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.red.gif
deleted file mode 100644
index 94743981d9..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.red.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.sec.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.sec.gif
deleted file mode 100644
index 88d5240c3c..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.sec.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.right.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.right.gif
deleted file mode 100644
index 5cdbc7206d..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.right.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.up.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.up.gif
deleted file mode 100644
index 85a5d68317..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.up.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/htdig.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/htdig.gif
deleted file mode 100644
index 35443fb63a..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/htdig.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/icon.sheet.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/icon.sheet.gif
deleted file mode 100644
index ad1686e448..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/icon.sheet.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image1.gif
deleted file mode 100644
index 01e442bfa9..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image1.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image2.gif
deleted file mode 100644
index 751faeea36..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image2.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image3.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image3.gif
deleted file mode 100644
index 4f30484ff6..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image3.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/index.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/index.gif
deleted file mode 100644
index 162478fb3a..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/index.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/layout.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/layout.gif
deleted file mode 100644
index c96338a152..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/layout.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/left.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/left.gif
deleted file mode 100644
index 279e6710d4..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/left.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/link.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/link.gif
deleted file mode 100644
index c5b6889a76..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/link.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/movie.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/movie.gif
deleted file mode 100644
index 0035183774..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/movie.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/p.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/p.gif
deleted file mode 100644
index 7b917b4e91..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/p.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/patch.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/patch.gif
deleted file mode 100644
index 39bc90e795..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/patch.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pdf.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pdf.gif
deleted file mode 100644
index c88fd777c4..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pdf.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie0.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie0.gif
deleted file mode 100644
index 6f7a0ae7a7..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie0.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie1.gif
deleted file mode 100644
index 03aa6be71e..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie1.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie2.gif
deleted file mode 100644
index b04c5e0908..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie2.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie3.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie3.gif
deleted file mode 100644
index 4db9d023ed..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie3.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie4.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie4.gif
deleted file mode 100644
index 93471fdd88..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie4.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie5.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie5.gif
deleted file mode 100644
index 57aee93f07..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie5.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie6.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie6.gif
deleted file mode 100644
index 0dc327b569..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie6.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie7.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie7.gif
deleted file mode 100644
index 8661337f06..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie7.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie8.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie8.gif
deleted file mode 100644
index 59ddb34ce0..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie8.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/portal.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/portal.gif
deleted file mode 100644
index 0e6e506e00..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/portal.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/poweredby.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/poweredby.gif
deleted file mode 100644
index d324ab80ea..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/poweredby.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ps.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ps.gif
deleted file mode 100644
index 0f565bc1db..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ps.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/quill.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/quill.gif
deleted file mode 100644
index 818a5cdc7e..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/quill.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/right.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/right.gif
deleted file mode 100644
index b256e5f75f..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/right.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw1.gif
deleted file mode 100644
index af6ba2b097..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw1.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw2.gif
deleted file mode 100644
index 06dccb3e44..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw2.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/script.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/script.gif
deleted file mode 100644
index d8a853bc58..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/script.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound1.gif
deleted file mode 100644
index 8efb49f55d..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound1.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound2.gif
deleted file mode 100644
index 48e6a7fb2f..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound2.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere1.gif
deleted file mode 100644
index 7067070da2..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere1.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere2.gif
deleted file mode 100644
index a9e462a377..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere2.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star.gif
deleted file mode 100644
index 4cfe0a5e0f..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star_blank.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star_blank.gif
deleted file mode 100644
index a0c83cb85b..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star_blank.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tar.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tar.gif
deleted file mode 100644
index 617e779efa..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tar.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tex.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tex.gif
deleted file mode 100644
index 45e43233b8..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tex.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/text.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/text.gif
deleted file mode 100644
index 4c623909fb..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/text.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/transfer.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/transfer.gif
deleted file mode 100644
index 33697dbb66..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/transfer.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/unknown.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/unknown.gif
deleted file mode 100644
index 32b1ea23fb..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/unknown.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/up.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/up.gif
deleted file mode 100644
index 6d6d6d1ebf..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/up.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uu.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uu.gif
deleted file mode 100644
index 4387d529f6..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uu.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uuencoded.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uuencoded.gif
deleted file mode 100644
index 4387d529f6..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uuencoded.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world1.gif
deleted file mode 100644
index 05b4ec2058..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world1.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world2.gif
deleted file mode 100644
index e3203f7a88..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world2.gif
+++ /dev/null
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/logs/Dummy_File_Needed_By_WinZip b/lib/inets/test/old_httpd_SUITE_data/server_root/logs/Dummy_File_Needed_By_WinZip
deleted file mode 100644
index 8d1c8b69c3..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/logs/Dummy_File_Needed_By_WinZip
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_client.pem b/lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_client.pem
deleted file mode 100644
index 427447958d..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_client.pem
+++ /dev/null
@@ -1,31 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIICXQIBAAKBgQCTFBPkOO98fDY3j6MIxIGKp+rampfIay50Lx4+EnCnRSSVwC+n
-0VVmP7V5SGFJpuXJzN0hvqPUWOOjiMTNlNRaGy0pqu2oMXWAPLOxHWL1wT53h2Zr
-3FUNU/N0Rvnkttse1KZJ9uYCLKUiuXXsv2rR62nH3OhRIiBHSAcSv0NRWwIDAQAB
-AoGACdIVYe/LTeydUihtInC8lZ2QuPgJmoBNocRjqJFipEihoL4scHAx25n1bBvB
-I0HZphffzBkGp28oBAtl2LRPWXqu527unc/RWRfLMqSK1xNSq1DxD1a30zkrZPna
-QiV65vEJuNSJTtlDy/Zqc/BVZXCpxWlzYQedZgkmf0Qse8ECQQCmaz02Yur8zC9f
-eSQKU5OSzGw3bSIumEzziCfHdTheK6MEoccf5TCAyLXhZwA7QlKja4tFXfeyVxws
-/LlnUJN9AkEA4j+xnOeYUyGKXL5i+BAbnqpI4MzPiq+IoCYkaRlD/wAws24r5HNI
-ZQmEHWqD/NNzOf/A2XuyLtMiTGJPW/DftwJBAKKpJP6Ytuh6xz8BUCnLwO12Y7vV
-LtjuQiCzD3aUa5EYA9HOMqxJPxxRkf0LyR0i2VUkE8+sZiPpov+R0cJa7p0CQQCj
-40GUiArGRSiF7/+e84QeVfl+pb29F1QftiFv5DZmFEwy3Z572KpbTh5edJbxYHY6
-UDHxGHJFCvnwXNJhpkVXAkBJqfEfiMJ3Q/E5Gpf3sQizacouW92iiN8ojlF1oB80
-t34RysJH7SgI3gdMhTribCo2UUaV0StjR6yodPN+TB2J
------END RSA PRIVATE KEY-----
------BEGIN CERTIFICATE-----
-MIIChzCCAfCgAwIBAgIGAIsapa8BMA0GCSqGSIb3DQEBBQUAMHoxDjAMBgNVBAMT
-BW90cENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0ZXJAZXJsYW5nLm9yZzESMBAGA1UE
-BxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEPMA0GA1UEChMGZXJsYW5nMRQwEgYD
-VQQLEwt0ZXN0aW5nIGRlcDAiGA8yMDEwMDkwMTAwMDAwMFoYDzIwMjUwODI4MDAw
-MDAwWjB7MQ8wDQYDVQQDEwZjbGllbnQxIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBl
-cmxhbmcub3JnMRIwEAYDVQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYD
-VQQKEwZlcmxhbmcxFDASBgNVBAsTC3Rlc3RpbmcgZGVwMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQCTFBPkOO98fDY3j6MIxIGKp+rampfIay50Lx4+EnCnRSSV
-wC+n0VVmP7V5SGFJpuXJzN0hvqPUWOOjiMTNlNRaGy0pqu2oMXWAPLOxHWL1wT53
-h2Zr3FUNU/N0Rvnkttse1KZJ9uYCLKUiuXXsv2rR62nH3OhRIiBHSAcSv0NRWwID
-AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAG8t6f1A
-PF7xayGxtUpG2r6W5ETylC3ZIKPS2kfJk9aYi7AZNTp7/xTU6SgqvFBN8aBPzxCD
-4jHrSNC8DSb4X1x9uimarb6qdZDHEdij+DRAd2eygJHZxEf7+8B4Fx34thQeU9hZ
-S1Izke5AlsyFMkvB7h0anE4k9BfuU70vl6v5
------END CERTIFICATE-----
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_server.pem b/lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_server.pem
deleted file mode 100644
index 4aac86db49..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_server.pem
+++ /dev/null
@@ -1,31 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIICXQIBAAKBgQCf4Htxr99lLs5W8QQw7jdakqyAkIjOW4aqH8sr4va4SvZ9Adq6
-7k8jMHefCVZo+F8x4cwsBgB4aWzFIGBnvFTi6YsH27XW7f9O9IPCej8fdhRZ4UAt
-NHa253buOWpDGla2JmIdkmfFvXFJycMIKbG5tYilVXoWKBMKmCwWaXz0nQIDAQAB
-AoGAQIlma0r6W6bcRj4+Wd4fXCFvHuq5Psu1fYEeC5Yvz8761xVjjSfbrDHJZ9pm
-FjOEgedK+s5lbDXqYVyjbdyZSugStBRocSmbG8SQHcAsxR2ZIkNzX2hYzB+lslWo
-T3YJojDyB134O7XJznCu+ZFXP86jyJ1JT6k6a+OIHcwnJ+ECQQDYn57dY4Px3mEd
-VBLStN3YkRF5oFyT+xk7IaKeLLB6n4gCnoVbBoHut7PFbPYPzoNzEwPk3MQKDIHb
-Kig3S5CpAkEAvPA1VmoJWAlN6kUi+F2L8HXEArzE8x7vwdsslrwMKUe4dFS+ZC/7
-5iDOaxcZ7TYkCgwzBt341++DCgP6j3fY1QJBALB6AcOcwi52m6l4B8mu3ZkEPjdX
-BHTuONTqhv/TqoaLlxODL2NDvvDKqeMp7KBd/srt79swW2lQXS4+fvrlTdkCQQCm
-zxj4O1QWkthkfje6ubSkTwUIOatUzrp1F9GNH2dJRtX2dx9FCwxGCC7WY6XzRXqa
-GF0wsedSllbGD+82nWQlAkAicMGqCqRq4hKR/cVmFatOqKVWCVkx6OFF2FhuiI5Z
-h5eIOPGCt8dVRs1P9DNSld/D98Sfm65m85z8BtXovvYV
------END RSA PRIVATE KEY-----
------BEGIN CERTIFICATE-----
-MIIChzCCAfCgAwIBAgIGANUxXM9BMA0GCSqGSIb3DQEBBQUAMHoxDjAMBgNVBAMT
-BW90cENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0ZXJAZXJsYW5nLm9yZzESMBAGA1UE
-BxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEPMA0GA1UEChMGZXJsYW5nMRQwEgYD
-VQQLEwt0ZXN0aW5nIGRlcDAiGA8yMDEwMDkwMTAwMDAwMFoYDzIwMjUwODI4MDAw
-MDAwWjB7MQ8wDQYDVQQDEwZzZXJ2ZXIxIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBl
-cmxhbmcub3JnMRIwEAYDVQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYD
-VQQKEwZlcmxhbmcxFDASBgNVBAsTC3Rlc3RpbmcgZGVwMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQCf4Htxr99lLs5W8QQw7jdakqyAkIjOW4aqH8sr4va4SvZ9
-Adq67k8jMHefCVZo+F8x4cwsBgB4aWzFIGBnvFTi6YsH27XW7f9O9IPCej8fdhRZ
-4UAtNHa253buOWpDGla2JmIdkmfFvXFJycMIKbG5tYilVXoWKBMKmCwWaXz0nQID
-AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAGF5Pfwk
-QDdwJup/mVITPxbBls4Yl7anDooUQsq8066lA1g54H/PRfXscGkyCFGh1ifXvf1L
-psMRoBAdDHL/wSJplk3rRavkC94eBgnTFZmfKL6844g1j53yameiYL8IEVExYMBg
-/XGyc0qwq57WT8B/K4aElrvlBlQ0wF3wN54M
------END CERTIFICATE-----
diff --git a/lib/inets/test/tftp_SUITE.erl b/lib/inets/test/tftp_SUITE.erl
deleted file mode 100644
index 09049e36af..0000000000
--- a/lib/inets/test/tftp_SUITE.erl
+++ /dev/null
@@ -1,949 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(tftp_SUITE).
-
--compile(export_all).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Includes and defines
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
--include("tftp_test_lib.hrl").
-
--define(START_DAEMON(PortX, OptionsX),
- fun(Port, Options) ->
- {ok, Pid} = ?VERIFY({ok, _Pid}, tftp:start([{port, Port} | Options])),
- if
- Port == 0 ->
- {ok, ActualOptions} = ?IGNORE(tftp:info(Pid)),
- {value, {port, ActualPort}} =
- lists:keysearch(port, 1, ActualOptions),
- {ActualPort, Pid};
- true ->
- {Port, Pid}
- end
- end(PortX, OptionsX)).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% API
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-t() ->
- tftp_test_lib:t([{?MODULE, all}]).
-
-t(Cases) ->
- tftp_test_lib:t(Cases, default_config()).
-
-t(Cases, Config) ->
- tftp_test_lib:t(Cases, Config).
-
-default_config() ->
- [].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Test server callbacks
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-init_per_testcase(Case, Config) ->
- tftp_test_lib:init_per_testcase(Case, Config).
-
-end_per_testcase(Case, Config) when is_list(Config) ->
- tftp_test_lib:end_per_testcase(Case, Config).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Top test case
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [simple, extra, reuse_connection, resend_client,
- resend_server, large_file].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Simple
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-simple(doc) ->
- ["Start the daemon and perform simple a read and write."];
-simple(suite) ->
- [];
-simple(Config) when is_list(Config) ->
- ?VERIFY(ok, application:start(inets)),
-
- {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, brief}])),
-
- %% Read fail
- RemoteFilename = "tftp_temporary_remote_test_file.txt",
- LocalFilename = "tftp_temporary_local_test_file.txt",
- Blob = list_to_binary(lists:duplicate(2000, $1)),
- %% Blob = <<"Some file contents\n">>,
- Size = size(Blob),
- ?IGNORE(file:delete(RemoteFilename)),
- ?VERIFY({error, {client_open, enoent, _}},
- tftp:read_file(RemoteFilename, binary, [{port, Port}])),
-
- %% Write and read
- ?VERIFY({ok, Size}, tftp:write_file(RemoteFilename, Blob, [{port, Port}])),
- ?VERIFY({ok, Blob}, tftp:read_file(RemoteFilename, binary, [{port, Port}])),
- ?IGNORE(file:delete(LocalFilename)),
- ?VERIFY({ok, Size}, tftp:read_file(RemoteFilename, LocalFilename, [{port, Port}])),
-
- %% Cleanup
- unlink(DaemonPid),
- exit(DaemonPid, kill),
- ?VERIFY(ok, file:delete(LocalFilename)),
- ?VERIFY(ok, file:delete(RemoteFilename)),
- ?VERIFY(ok, application:stop(inets)),
- ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Extra
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-extra(doc) ->
- ["Verify new stuff for IS 1.2."];
-extra(suite) ->
- [];
-extra(Config) when is_list(Config) ->
- ?VERIFY({'EXIT', {badarg,{fake_key, fake_flag}}},
- tftp:start([{port, 0}, {fake_key, fake_flag}])),
-
- {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, brief}])),
-
- RemoteFilename = "tftp_extra_temporary_remote_test_file.txt",
- LocalFilename = "tftp_extra_temporary_local_test_file.txt",
- Blob = <<"Some file contents\n">>,
- Size = size(Blob),
- Host = "127.0.0.1",
- Peer = {inet, Host, Port},
- Generic =
- [
- {state, []},
- {prepare, fun extra_prepare/6},
- {open, fun extra_open/6},
- {read, fun extra_read/1},
- {write, fun extra_write/2},
- {abort, fun extra_abort/3 }
- ],
- Options = [{host, Host},
- {port, Port},
- %%{ debug,all},
- {callback, {".*", tftp_test_lib, Generic}}],
- ?VERIFY(ok, file:write_file(LocalFilename, Blob)),
- ?VERIFY({ok, [{count, Size}, Peer]},
- tftp:write_file(RemoteFilename, LocalFilename, Options)),
- ?VERIFY(ok, file:delete(LocalFilename)),
-
- ?VERIFY({ok,[{bin, Blob}, Peer]},
- tftp:read_file(RemoteFilename, LocalFilename, Options)),
-
- %% Cleanup
- unlink(DaemonPid),
- exit(DaemonPid, kill),
- ?VERIFY(ok, file:delete(LocalFilename)),
- ?VERIFY(ok, file:delete(RemoteFilename)),
- ok.
-
--record(extra_state, {file, blksize, count, acc, peer}).
-
-%%-------------------------------------------------------------------
-%% Prepare
-%%-------------------------------------------------------------------
-
-extra_prepare(Peer, Access, LocalFilename, Mode, SuggestedOptions, []) ->
- %% Client side
- BlkSize = list_to_integer(tftp_test_lib:lookup_option("blksize", "512", SuggestedOptions)),
- State = #extra_state{blksize = BlkSize, peer = Peer},
- extra_open(Peer, Access, LocalFilename, Mode, SuggestedOptions, State),
- {ok, SuggestedOptions, State};
-extra_prepare(_Peer, _Access, _Bin, _Mode, _SuggestedOptions, _Initial) ->
- {error, {undef, "Illegal callback options."}}.
-
-%%-------------------------------------------------------------------
-%% Open
-%%-------------------------------------------------------------------
-
-extra_open(Peer, Access, LocalFilename, Mode, SuggestedOptions, []) ->
- %% Server side
- case extra_prepare(Peer, Access, LocalFilename, Mode, SuggestedOptions, []) of
- {ok, AcceptedOptions, []} ->
- BlkSize = list_to_integer(tftp_test_lib:lookup_option("blksize", "512", AcceptedOptions)),
- State = #extra_state{blksize = BlkSize, peer = Peer},
- extra_open(Peer, Access, LocalFilename, Mode, AcceptedOptions, State);
- {error, {Code, Text}} ->
- {error, {Code, Text}}
- end;
-extra_open(_Peer, Access, LocalFilename, _Mode, NegotiatedOptions, #extra_state{} = State) ->
- {File, Acc} =
- case Access of
- read ->
- if
- is_binary(LocalFilename) ->
- {undefined, LocalFilename};
- is_list(LocalFilename) ->
- {ok, Bin} = file:read_file(LocalFilename),
- {LocalFilename, Bin}
- end;
- write ->
- {LocalFilename, []}
- end,
- %% Both sides
- State2 = State#extra_state{file = File, acc = Acc, count = 0},
- {ok, NegotiatedOptions, State2}.
-
-%%-------------------------------------------------------------------
-%% Read
-%%-------------------------------------------------------------------
-
-extra_read(#extra_state{acc = Bin} = State) when is_binary(Bin) ->
- BlkSize = State#extra_state.blksize,
- Count = State#extra_state.count + size(Bin),
- if
- size(Bin) >= BlkSize ->
- <<Block:BlkSize/binary, Bin2/binary>> = Bin,
- State2 = State#extra_state{acc = Bin2, count = Count},
- {more, Block, State2};
- size(Bin) < BlkSize ->
- Res = [{count, Count}, State#extra_state.peer],
- {last, Bin, Res}
- end.
-
-%%-------------------------------------------------------------------
-%% Write
-%%-------------------------------------------------------------------
-
-extra_write(Bin, #extra_state{acc = List} = State) when is_binary(Bin), is_list(List) ->
- Size = size(Bin),
- BlkSize = State#extra_state.blksize,
- if
- Size == BlkSize ->
- {more, State#extra_state{acc = [Bin | List]}};
- Size < BlkSize ->
- Bin2 = list_to_binary(lists:reverse([Bin | List])),
- Res = [{bin, Bin2}, State#extra_state.peer],
- file:write_file(State#extra_state.file, Bin2),
- {last, Res}
- end.
-
-%%-------------------------------------------------------------------
-%% Abort
-%%-------------------------------------------------------------------
-
-extra_abort(_Code, _Text, #extra_state{}) ->
- ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Re-send client
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-resend_client(doc) ->
- ["Verify that the server behaves correctly when the client re-sends packets."];
-resend_client(suite) ->
- [];
-resend_client(Config) when is_list(Config) ->
- Host = {127, 0, 0, 1},
- {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, all}])),
-
- ?VERIFY(ok, resend_read_client(Host, Port, 10)),
- ?VERIFY(ok, resend_read_client(Host, Port, 512)),
- ?VERIFY(ok, resend_read_client(Host, Port, 1025)),
-
- ?VERIFY(ok, resend_write_client(Host, Port, 10)),
- ?VERIFY(ok, resend_write_client(Host, Port, 512)),
- ?VERIFY(ok, resend_write_client(Host, Port, 1025)),
-
- %% Cleanup
- unlink(DaemonPid),
- exit(DaemonPid, kill),
- ok.
-
-resend_read_client(Host, Port, BlkSize) ->
- RemoteFilename = "tftp_resend_read_client.tmp",
- Block1 = lists:duplicate(BlkSize, $1),
- Block2 = lists:duplicate(BlkSize, $2),
- Block3 = lists:duplicate(BlkSize, $3),
- Block4 = lists:duplicate(BlkSize, $4),
- Block5 = lists:duplicate(BlkSize, $5),
- Blocks = [Block1, Block2, Block3, Block4, Block5],
- Blob = list_to_binary(Blocks),
- ?VERIFY(ok, file:write_file(RemoteFilename, Blob)),
-
- Timeout = timer:seconds(3),
- ?VERIFY(timeout, recv(0)),
-
- %% Open socket
- {ok, Socket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
-
- ReadList = [0, 1, RemoteFilename, 0, "octet", 0],
- Data1Bin = list_to_binary([0, 3, 0, 1 | Block1]),
- NewPort =
- if
- BlkSize =:= 512 ->
- %% Send READ
- ReadBin = list_to_binary(ReadList),
- ?VERIFY(ok, gen_udp:send(Socket, Host, Port, ReadBin)),
-
- %% Sleep a while in order to provoke the server to re-send the packet
- timer:sleep(Timeout + timer:seconds(1)),
-
- %% Recv DATA #1 (the packet that the server think that we have lost)
- {udp, _, _, NewPort0, _} = ?VERIFY({udp, Socket, Host, _, Data1Bin}, recv(Timeout)),
- NewPort0;
- true ->
- %% Send READ
- BlkSizeList = integer_to_list(BlkSize),
- Options = ["blksize", 0, BlkSizeList, 0],
- ReadBin = list_to_binary([ReadList | Options]),
- ?VERIFY(ok, gen_udp:send(Socket, Host, Port, ReadBin)),
-
- %% Recv OACK
- OptionAckBin = list_to_binary([0, 6 | Options]),
- {udp, _, _, NewPort0, _} = ?VERIFY({udp, Socket, Host, _, OptionAckBin}, recv(Timeout)),
-
- %% Send ACK #0
- Ack0Bin = <<0, 4, 0, 0>>,
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort0, Ack0Bin)),
-
- %% Send ACK #0 AGAIN (pretend that we timed out)
- timer:sleep(timer:seconds(1)),
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort0, Ack0Bin)),
-
- %% Recv DATA #1 (the packet that the server think that we have lost)
- ?VERIFY({udp, Socket, Host, NewPort0, Data1Bin}, recv(Timeout)),
- NewPort0
- end,
-
- %% Recv DATA #1 AGAIN (the re-sent package)
- ?VERIFY({udp, Socket, Host, NewPort, Data1Bin}, recv(Timeout)),
-
- %% Send ACK #1
- Ack1Bin = <<0, 4, 0, 1>>,
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack1Bin)),
-
- %% Recv DATA #2
- Data2Bin = list_to_binary([0, 3, 0, 2 | Block2]),
- ?VERIFY({udp, Socket, Host, NewPort, Data2Bin}, recv(Timeout)),
-
- %% Send ACK #2
- Ack2Bin = <<0, 4, 0, 2>>,
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack2Bin)),
-
- %% Recv DATA #3
- Data3Bin = list_to_binary([0, 3, 0, 3 | Block3]),
- ?VERIFY({udp, Socket, Host, NewPort, Data3Bin}, recv(Timeout)),
-
- %% Send ACK #3
- Ack3Bin = <<0, 4, 0, 3>>,
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack3Bin)),
-
- %% Send ACK #3 AGAIN (pretend that we timed out)
- timer:sleep(timer:seconds(1)),
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack3Bin)),
-
- %% Recv DATA #4 (the packet that the server think that we have lost)
- Data4Bin = list_to_binary([0, 3, 0, 4 | Block4]),
- ?VERIFY({udp, Socket, Host, NewPort, Data4Bin}, recv(Timeout)),
-
- %% Recv DATA #4 AGAIN (the re-sent package)
- ?VERIFY({udp, Socket, Host, NewPort, Data4Bin}, recv(Timeout)),
-
- %% Send ACK #2 which is out of range
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack2Bin)),
-
- %% Send ACK #4
- Ack4Bin = <<0, 4, 0, 4>>,
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack4Bin)),
-
- %% Recv DATA #5
- Data5Bin = list_to_binary([0, 3, 0, 5 | Block5]),
- ?VERIFY({udp, Socket, Host, NewPort, Data5Bin}, recv(Timeout)),
-
- %% Send ACK #5
- Ack5Bin = <<0, 4, 0, 5>>,
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack5Bin)),
-
- %% Close socket
- ?VERIFY(ok, gen_udp:close(Socket)),
-
- ?VERIFY(timeout, recv(Timeout)),
- ?VERIFY(ok, file:delete(RemoteFilename)),
- ok.
-
-resend_write_client(Host, Port, BlkSize) ->
- RemoteFilename = "tftp_resend_write_client.tmp",
- Block1 = lists:duplicate(BlkSize, $1),
- Block2 = lists:duplicate(BlkSize, $2),
- Block3 = lists:duplicate(BlkSize, $3),
- Block4 = lists:duplicate(BlkSize, $4),
- Block5 = lists:duplicate(BlkSize, $5),
- Blocks = [Block1, Block2, Block3, Block4, Block5],
- Blob = list_to_binary(Blocks),
- ?IGNORE(file:delete(RemoteFilename)),
- ?VERIFY({error, enoent}, file:read_file(RemoteFilename)),
-
- Timeout = timer:seconds(3),
- ?VERIFY(timeout, recv(0)),
-
- %% Open socket
- {ok, Socket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
-
- WriteList = [0, 2, RemoteFilename, 0, "octet", 0],
- NewPort =
- if
- BlkSize =:= 512 ->
- %% Send WRITE
- WriteBin = list_to_binary(WriteList),
- ?VERIFY(ok, gen_udp:send(Socket, Host, Port, WriteBin)),
-
- %% Sleep a while in order to provoke the server to re-send the packet
- timer:sleep(Timeout + timer:seconds(1)),
-
- %% Recv ACK #0 (the packet that the server think that we have lost)
- Ack0Bin = <<0, 4, 0, 0>>,
- ?VERIFY({udp, Socket, Host, _, Ack0Bin}, recv(Timeout)),
-
- %% Recv ACK #0 AGAIN (the re-sent package)
- {udp, _, _, NewPort0, _} = ?VERIFY({udp, Socket, Host, _, Ack0Bin}, recv(Timeout)),
- NewPort0;
- true ->
- %% Send WRITE
- BlkSizeList = integer_to_list(BlkSize),
- WriteBin = list_to_binary([WriteList, "blksize", 0, BlkSizeList, 0]),
- ?VERIFY(ok, gen_udp:send(Socket, Host, Port, WriteBin)),
-
- %% Sleep a while in order to provoke the server to re-send the packet
- timer:sleep(timer:seconds(1)),
-
- %% Recv OACK (the packet that the server think that we have lost)
- OptionAckBin = list_to_binary([0, 6, "blksize",0, BlkSizeList, 0]),
- ?VERIFY({udp, Socket, Host, _, OptionAckBin}, recv(Timeout)),
-
- %% Recv OACK AGAIN (the re-sent package)
- {udp, _, _, NewPort0, _} = ?VERIFY({udp, Socket, Host, _, OptionAckBin}, recv(Timeout)),
- NewPort0
- end,
-
- %% Send DATA #1
- Data1Bin = list_to_binary([0, 3, 0, 1 | Block1]),
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data1Bin)),
-
- %% Recv ACK #1
- Ack1Bin = <<0, 4, 0, 1>>,
- ?VERIFY({udp, Socket, Host, NewPort, Ack1Bin}, recv(Timeout)),
-
- %% Send DATA #2
- Data2Bin = list_to_binary([0, 3, 0, 2 | Block2]),
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data2Bin)),
-
- %% Recv ACK #2
- Ack2Bin = <<0, 4, 0, 2>>,
- ?VERIFY({udp, Socket, Host, NewPort, Ack2Bin}, recv(Timeout)),
-
- %% Send DATA #3
- Data3Bin = list_to_binary([0, 3, 0, 3 | Block3]),
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data3Bin)),
-
- %% Recv ACK #3
- Ack3Bin = <<0, 4, 0, 3>>,
- ?VERIFY({udp, Socket, Host, NewPort, Ack3Bin}, recv(Timeout)),
-
- %% Send DATA #3 AGAIN (pretend that we timed out)
- timer:sleep(timer:seconds(1)),
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data3Bin)),
-
- %% Recv ACK #3 AGAIN (the packet that the server think that we have lost)
- ?VERIFY({udp, Socket, Host, NewPort, Ack3Bin}, recv(Timeout)),
-
- %% Send DATA #2 which is out of range
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data2Bin)),
-
- %% Send DATA #4
- Data4Bin = list_to_binary([0, 3, 0, 4 | Block4]),
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data4Bin)),
-
- %% Recv ACK #4
- Ack4Bin = <<0, 4, 0, 4>>,
- ?VERIFY({udp, Socket, Host, NewPort, Ack4Bin}, recv(Timeout)),
-
- %% Send DATA #5
- Data5Bin = list_to_binary([0, 3, 0, 5 | Block5]),
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data5Bin)),
-
- %% Recv ACK #5
- Ack5Bin = <<0, 4, 0, 5>>,
- ?VERIFY({udp, Socket, Host, NewPort, Ack5Bin}, recv(Timeout)),
-
- %% Close socket
- ?VERIFY(ok, gen_udp:close(Socket)),
-
- ?VERIFY(timeout, recv(Timeout)),
- ?VERIFY({ok, Blob}, file:read_file(RemoteFilename)),
- ?VERIFY(ok, file:delete(RemoteFilename)),
- ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Re-send server
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-resend_server(doc) ->
- ["Verify that the server behaves correctly when the server re-sends packets."];
-resend_server(suite) ->
- [];
-resend_server(Config) when is_list(Config) ->
- Host = {127, 0, 0, 1},
-
- ?VERIFY(ok, resend_read_server(Host, 10)),
- ?VERIFY(ok, resend_read_server(Host, 512)),
- ?VERIFY(ok, resend_read_server(Host, 1025)),
-
- ?VERIFY(ok, resend_write_server(Host, 10)),
- ?VERIFY(ok, resend_write_server(Host, 512)),
- ?VERIFY(ok, resend_write_server(Host, 1025)),
- ok.
-
-resend_read_server(Host, BlkSize) ->
- RemoteFilename = "tftp_resend_read_server.tmp",
- Block1 = lists:duplicate(BlkSize, $1),
- Block2 = lists:duplicate(BlkSize, $2),
- Block3 = lists:duplicate(BlkSize, $3),
- Block4 = lists:duplicate(BlkSize, $4),
- Block5 = lists:duplicate(BlkSize, $5),
- Block6 = [],
- Blocks = [Block1, Block2, Block3, Block4, Block5, Block6],
- Blob = list_to_binary(Blocks),
-
- Timeout = timer:seconds(3),
- ?VERIFY(timeout, recv(0)),
-
- %% Open daemon socket
- {ok, DaemonSocket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
- {ok, DaemonPort} = ?IGNORE(inet:port(DaemonSocket)),
-
- %% Open server socket
- {ok, ServerSocket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
- ?IGNORE(inet:port(ServerSocket)),
-
- %% Prepare client process
- ReplyTo = self(),
- ClientFun =
- fun(Extra) ->
- Options = [{port, DaemonPort}, {debug, brief}] ++ Extra,
- Res = ?VERIFY({ok, Blob}, tftp:read_file(RemoteFilename, binary, Options)),
- ReplyTo ! {self(), {tftp_client_reply, Res}},
- exit(normal)
- end,
-
- ReadList = [0, 1, RemoteFilename, 0, "octet", 0],
- Data1Bin = list_to_binary([0, 3, 0, 1 | Block1]),
- Ack1Bin = <<0, 4, 0, 1>>,
- {ClientPort, ClientPid} =
- if
- BlkSize =:= 512 ->
- %% Start client process
- ClientPid0 = spawn_link(fun() -> ClientFun([]) end),
-
- %% Recv READ
- ReadBin = list_to_binary(ReadList),
- {udp, _, _, ClientPort0, _} = ?VERIFY({udp, DaemonSocket, Host, _, ReadBin}, recv(Timeout)),
-
- %% Send DATA #1
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort0, Data1Bin)),
-
- %% Sleep a while in order to provoke the client to re-send the packet
- timer:sleep(Timeout + timer:seconds(1)),
-
- %% Recv ACK #1 (the packet that the server think that we have lost)
- ?VERIFY({udp, ServerSocket, Host, ClientPort0, Ack1Bin}, recv(Timeout)),
-
- %% Recv ACK #1 AGAIN (the re-sent package)
- ?VERIFY({udp, ServerSocket, Host, _, Ack1Bin}, recv(Timeout)),
- {ClientPort0, ClientPid0};
- true ->
- %% Start client process
- BlkSizeList = integer_to_list(BlkSize),
- ClientPid0 = spawn_link(fun() -> ClientFun([{"blksize", BlkSizeList}]) end),
-
- %% Recv READ
- Options = ["blksize", 0, BlkSizeList, 0],
- ReadBin = list_to_binary([ReadList | Options]),
- {udp, _, _, ClientPort0, _} = ?VERIFY({udp, DaemonSocket, Host, _, ReadBin}, recv(Timeout)),
-
- %% Send OACK
- BlkSizeList = integer_to_list(BlkSize),
- OptionAckBin = list_to_binary([0, 6, "blksize",0, BlkSizeList, 0]),
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort0, OptionAckBin)),
-
- %% Sleep a while in order to provoke the client to re-send the packet
- timer:sleep(Timeout + timer:seconds(1)),
-
- %% Recv ACK #0 (the packet that the server think that we have lost)
- Ack0Bin = <<0, 4, 0, 0>>,
- ?VERIFY({udp, ServerSocket, Host, ClientPort0, Ack0Bin}, recv(Timeout)),
-
- %% Recv ACK #0 AGAIN (the re-sent package)
- ?VERIFY({udp, ServerSocket, Host, ClientPort0, Ack0Bin}, recv(Timeout)),
-
- %% Send DATA #1
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort0, Data1Bin)),
-
- %% Recv ACK #1
- ?VERIFY({udp, ServerSocket, Host, _, Ack1Bin}, recv(Timeout)),
- {ClientPort0, ClientPid0}
- end,
-
- %% Send DATA #2
- Data2Bin = list_to_binary([0, 3, 0, 2 | Block2]),
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data2Bin)),
-
- %% Recv ACK #2
- Ack2Bin = <<0, 4, 0, 2>>,
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Ack2Bin}, recv(Timeout)),
-
- %% Send DATA #3
- Data3Bin = list_to_binary([0, 3, 0, 3 | Block3]),
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data3Bin)),
-
- %% Recv ACK #3
- Ack3Bin = <<0, 4, 0, 3>>,
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Ack3Bin}, recv(Timeout)),
-
- %% Send DATA #3 AGAIN (pretend that we timed out)
- timer:sleep(timer:seconds(1)),
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data3Bin)),
-
- %% Recv ACK #3 AGAIN (the packet that the server think that we have lost)
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Ack3Bin}, recv(Timeout)),
-
- %% Send DATA #4
- Data4Bin = list_to_binary([0, 3, 0, 4 | Block4]),
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data4Bin)),
-
- %% Recv ACK #4
- Ack4Bin = <<0, 4, 0, 4>>,
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Ack4Bin}, recv(Timeout)),
-
- %% Send DATA #3 which is out of range
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data3Bin)),
-
- %% Send DATA #5
- Data5Bin = list_to_binary([0, 3, 0, 5 | Block5]),
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data5Bin)),
-
- %% Recv ACK #5
- Ack5Bin = <<0, 4, 0, 5>>,
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Ack5Bin}, recv(Timeout)),
-
- %% Send DATA #6
- Data6Bin = list_to_binary([0, 3, 0, 6 | Block6]),
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data6Bin)),
-
- %% Close daemon and server sockets
- ?VERIFY(ok, gen_udp:close(ServerSocket)),
- ?VERIFY(ok, gen_udp:close(DaemonSocket)),
-
- ?VERIFY({ClientPid, {tftp_client_reply, {ok, Blob}}}, recv(Timeout)),
-
- ?VERIFY(timeout, recv(Timeout)),
- ok.
-
-resend_write_server(Host, BlkSize) ->
- RemoteFilename = "tftp_resend_write_server.tmp",
- Block1 = lists:duplicate(BlkSize, $1),
- Block2 = lists:duplicate(BlkSize, $2),
- Block3 = lists:duplicate(BlkSize, $3),
- Block4 = lists:duplicate(BlkSize, $4),
- Block5 = lists:duplicate(BlkSize, $5),
- Block6 = [],
- Blocks = [Block1, Block2, Block3, Block4, Block5, Block6],
- Blob = list_to_binary(Blocks),
- Size = size(Blob),
-
- Timeout = timer:seconds(3),
- ?VERIFY(timeout, recv(0)),
-
- %% Open daemon socket
- {ok, DaemonSocket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
- {ok, DaemonPort} = ?IGNORE(inet:port(DaemonSocket)),
-
- %% Open server socket
- {ok, ServerSocket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
- ?IGNORE(inet:port(ServerSocket)),
-
- %% Prepare client process
- ReplyTo = self(),
- ClientFun =
- fun(Extra) ->
- Options = [{port, DaemonPort}, {debug, brief}] ++ Extra,
- Res = ?VERIFY({ok, Size}, tftp:write_file(RemoteFilename, Blob, Options)),
- ReplyTo ! {self(), {tftp_client_reply, Res}},
- exit(normal)
- end,
-
- WriteList = [0, 2, RemoteFilename, 0, "octet", 0],
- Data1Bin = list_to_binary([0, 3, 0, 1 | Block1]),
- {ClientPort, ClientPid} =
- if
- BlkSize =:= 512 ->
- %% Start client process
- ClientPid0 = spawn_link(fun() -> ClientFun([]) end),
-
- %% Recv WRITE
- WriteBin = list_to_binary(WriteList),
- io:format("WriteBin ~p\n", [WriteBin]),
- {udp, _, _, ClientPort0, _} = ?VERIFY({udp, DaemonSocket, Host, _, WriteBin}, recv(Timeout)),
-
- %% Send ACK #1
- Ack0Bin = <<0, 4, 0, 0>>,
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort0, Ack0Bin)),
-
- %% Sleep a while in order to provoke the client to re-send the packet
- timer:sleep(Timeout + timer:seconds(1)),
-
- %% Recv DATA #1 (the packet that the server think that we have lost)
- ?VERIFY({udp, ServerSocket, Host, ClientPort0, Data1Bin}, recv(Timeout)),
-
- %% Recv DATA #1 AGAIN (the re-sent package)
- ?VERIFY({udp, ServerSocket, Host, _, Data1Bin}, recv(Timeout)),
- {ClientPort0, ClientPid0};
- true ->
- %% Start client process
- BlkSizeList = integer_to_list(BlkSize),
- ClientPid0 = spawn_link(fun() -> ClientFun([{"blksize", BlkSizeList}]) end),
-
- %% Recv WRITE
- Options = ["blksize", 0, BlkSizeList, 0],
- WriteBin = list_to_binary([WriteList | Options]),
- {udp, _, _, ClientPort0, _} = ?VERIFY({udp, DaemonSocket, Host, _, WriteBin}, recv(Timeout)),
-
- %% Send OACK
- BlkSizeList = integer_to_list(BlkSize),
- OptionAckBin = list_to_binary([0, 6, "blksize",0, BlkSizeList, 0]),
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort0, OptionAckBin)),
-
- %% Sleep a while in order to provoke the client to re-send the packet
- timer:sleep(Timeout + timer:seconds(1)),
-
- %% Recv DATA #1 (the packet that the server think that we have lost)
- ?VERIFY({udp, ServerSocket, Host, ClientPort0, Data1Bin}, recv(Timeout)),
-
- %% Recv DATA #1 AGAIN (the re-sent package)
- ?VERIFY({udp, ServerSocket, Host, ClientPort0, Data1Bin}, recv(Timeout)),
- {ClientPort0, ClientPid0}
- end,
-
- %% Send ACK #1
- Ack1Bin = <<0, 4, 0, 1>>,
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack1Bin)),
-
- %% Recv DATA #2
- Data2Bin = list_to_binary([0, 3, 0, 2 | Block2]),
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Data2Bin}, recv(Timeout)),
-
- %% Send ACK #2
- Ack2Bin = <<0, 4, 0, 2>>,
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack2Bin)),
-
- %% Recv DATA #3
- Data3Bin = list_to_binary([0, 3, 0, 3 | Block3]),
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Data3Bin}, recv(Timeout)),
-
- %% Send ACK #3
- Ack3Bin = <<0, 4, 0, 3>>,
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack3Bin)),
-
- %% Send ACK #3 AGAIN (pretend that we timed out)
- timer:sleep(timer:seconds(1)),
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack3Bin)),
-
- %% Recv DATA #4 (the packet that the server think that we have lost)
- Data4Bin = list_to_binary([0, 3, 0, 4 | Block4]),
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Data4Bin}, recv(Timeout)),
-
- %% Recv DATA #4 AGAIN (the re-sent package)
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Data4Bin}, recv(Timeout)),
-
- %% Send ACK #4
- Ack4Bin = <<0, 4, 0, 4>>,
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack4Bin)),
-
- %% Recv DATA #5
- Data5Bin = list_to_binary([0, 3, 0, 5 | Block5]),
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Data5Bin}, recv(Timeout)),
-
- %% Send ACK #3 which is out of range
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack3Bin)),
-
- %% Send ACK #5
- Ack5Bin = <<0, 4, 0, 5>>,
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack5Bin)),
-
- %% Recv DATA #6
- Data6Bin = list_to_binary([0, 3, 0, 6 | Block6]),
- ?VERIFY({udp, ServerSocket, Host, ClientPort, Data6Bin}, recv(Timeout)),
-
- %% Send ACK #6
- Ack6Bin = <<0, 4, 0, 6>>,
- ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack6Bin)),
-
- %% Close daemon and server sockets
- ?VERIFY(ok, gen_udp:close(ServerSocket)),
- ?VERIFY(ok, gen_udp:close(DaemonSocket)),
-
- ?VERIFY({ClientPid, {tftp_client_reply, {ok, Size}}}, recv(Timeout)),
-
- ?VERIFY(timeout, recv(Timeout)),
- ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-reuse_connection(doc) ->
- ["Verify that the server can reuse an ongiong connection when same client resends request."];
-reuse_connection(suite) ->
- [];
-reuse_connection(Config) when is_list(Config) ->
- Host = {127, 0, 0, 1},
- {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, all}])),
-
- RemoteFilename = "reuse_connection.tmp",
- BlkSize = 512,
- Block1 = lists:duplicate(BlkSize, $1),
- Block2 = lists:duplicate(BlkSize div 2, $2),
- Blocks = [Block1, Block2],
- Blob = list_to_binary(Blocks),
- ?VERIFY(ok, file:write_file(RemoteFilename, Blob)),
-
- Seconds = 3,
- Timeout = timer:seconds(Seconds),
- ?VERIFY(timeout, recv(0)),
-
- %% Open socket
- {ok, Socket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
-
- ReadList = [0, 1, RemoteFilename, 0, "octet", 0],
- Data1Bin = list_to_binary([0, 3, 0, 1 | Block1]),
-
- %% Send READ
- TimeoutList = integer_to_list(Seconds),
- Options = ["timeout", 0, TimeoutList, 0],
- ReadBin = list_to_binary([ReadList | Options]),
- ?VERIFY(ok, gen_udp:send(Socket, Host, Port, ReadBin)),
-
- %% Send yet another READ for same file
- ?VERIFY(ok, gen_udp:send(Socket, Host, Port, ReadBin)),
-
- %% Recv OACK
- OptionAckBin = list_to_binary([0, 6 | Options]),
- {udp, _, _, NewPort, _} = ?VERIFY({udp, Socket, Host, _, OptionAckBin}, recv(Timeout)),
-
- %% Send ACK #0
- Ack0Bin = <<0, 4, 0, 0>>,
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack0Bin)),
-
- %% Recv DATA #1
- ?VERIFY({udp, Socket, Host, NewPort, Data1Bin}, recv(Timeout)),
-
- %% Send ACK #1
- Ack1Bin = <<0, 4, 0, 1>>,
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack1Bin)),
-
- %% Recv DATA #2
- Data2Bin = list_to_binary([0, 3, 0, 2 | Block2]),
- ?VERIFY({udp, Socket, Host, NewPort, Data2Bin}, recv(Timeout)),
-
- %% Send ACK #2
- Ack2Bin = <<0, 4, 0, 2>>,
- ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack2Bin)),
-
- %% Close socket
- ?VERIFY(ok, gen_udp:close(Socket)),
-
- ?VERIFY(timeout, recv(Timeout)),
- ?VERIFY(ok, file:delete(RemoteFilename)),
-
- %% Cleanup
- unlink(DaemonPid),
- exit(DaemonPid, kill),
- ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Large file: transfer > 65535 blocks
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-large_file(doc) ->
- ["Start the daemon and test transfer of files greater than 32M."];
-large_file(suite) ->
- [];
-large_file(Config) when is_list(Config) ->
- ?VERIFY(ok, application:start(inets)),
-
- {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, brief}])),
-
- %% Read fail
- RemoteFilename = "tftp_temporary_large_file_remote_test_file.txt",
- LocalFilename = "tftp_temporary_large_file_local_test_file.txt",
-
- {ok, FH} = file:open(LocalFilename, [write,exclusive]),
- {ok, Size} = file:position(FH, {eof, 2*512*65535}),
- ok = file:truncate(FH),
- ?IGNORE(file:close(FH)),
-
- %% Write and read
- ?VERIFY({ok, Size}, tftp:write_file(RemoteFilename, LocalFilename, [{port, Port}])),
- ?IGNORE(file:delete(LocalFilename)),
- ?VERIFY({ok, Size}, tftp:read_file(RemoteFilename, LocalFilename, [{port, Port}])),
-
- %% Cleanup
- unlink(DaemonPid),
- exit(DaemonPid, kill),
- ?VERIFY(ok, file:delete(LocalFilename)),
- ?VERIFY(ok, file:delete(RemoteFilename)),
- ?VERIFY(ok, application:stop(inets)),
- ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Goodies
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-recv(Timeout) ->
- receive
- Msg ->
- Msg
- after Timeout ->
- timeout
- end.
diff --git a/lib/inets/test/tftp_test_lib.erl b/lib/inets/test/tftp_test_lib.erl
deleted file mode 100644
index f07795324f..0000000000
--- a/lib/inets/test/tftp_test_lib.erl
+++ /dev/null
@@ -1,308 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(tftp_test_lib).
-
--compile(export_all).
-
--include("tftp_test_lib.hrl").
-
-%%
-%% -----
-%%
-
-init_per_testcase(_Case, Config) when is_list(Config) ->
- io:format("\n ", []),
- ?IGNORE(application:stop(inets)),
- Config.
-
-end_per_testcase(_Case, Config) when is_list(Config) ->
- ?IGNORE(application:stop(inets)),
- Config.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Infrastructure for test suite
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-error(Actual, Mod, Line) ->
- (catch global:send(tftp_global_logger, {failed, Mod, Line})),
- log("<ERROR> Bad result: ~p\n", [Actual], Mod, Line),
- Label = lists:concat([Mod, "(", Line, ") unexpected result"]),
- et:report_event(60, Mod, Mod, Label,
- [{line, Mod, Line}, {error, Actual}]),
- case global:whereis_name(tftp_test_case_sup) of
- undefined ->
- ignore;
- Pid ->
- Fail = #'REASON'{mod = Mod, line = Line, desc = Actual},
- Pid ! {fail, self(), Fail}
- end,
- Actual.
-
-log(Format, Args, Mod, Line) ->
- case global:whereis_name(tftp_global_logger) of
- undefined ->
- io:format(user, "~p(~p): " ++ Format,
- [Mod, Line] ++ Args);
- Pid ->
- io:format(Pid, "~p(~p): " ++ Format,
- [Mod, Line] ++ Args)
- end.
-
-default_config() ->
- [].
-
-t() ->
- t([{?MODULE, all}]).
-
-t(Cases) ->
- t(Cases, default_config()).
-
-t(Cases, Config) ->
- process_flag(trap_exit, true),
- Res = lists:flatten(do_test(Cases, Config)),
- io:format("Res: ~p\n", [Res]),
- display_result(Res),
- Res.
-
-do_test({Mod, Fun}, Config) when is_atom(Mod), is_atom(Fun) ->
- case catch apply(Mod, Fun, [suite]) of
- [] ->
- io:format("Eval: ~p:", [{Mod, Fun}]),
- Res = eval(Mod, Fun, Config),
- {R, _, _} = Res,
- io:format(" ~p\n", [R]),
- Res;
-
- Cases when is_list(Cases) ->
- io:format("Expand: ~p ...\n", [{Mod, Fun}]),
- Map = fun(Case) when is_atom(Case)-> {Mod, Case};
- (Case) -> Case
- end,
- do_test(lists:map(Map, Cases), Config);
-
- {req, _, {conf, Init, Cases, Finish}} ->
- case (catch apply(Mod, Init, [Config])) of
- Conf when is_list(Conf) ->
- io:format("Expand: ~p ...\n", [{Mod, Fun}]),
- Map = fun(Case) when is_atom(Case)-> {Mod, Case};
- (Case) -> Case
- end,
- Res = do_test(lists:map(Map, Cases), Conf),
- (catch apply(Mod, Finish, [Conf])),
- Res;
-
- {'EXIT', {skipped, Reason}} ->
- io:format(" => skipping: ~p\n", [Reason]),
- [{skipped, {Mod, Fun}, Reason}];
-
- Error ->
- io:format(" => failed: ~p\n", [Error]),
- [{failed, {Mod, Fun}, Error}]
- end;
-
- {'EXIT', {undef, _}} ->
- io:format("Undefined: ~p\n", [{Mod, Fun}]),
- [{nyi, {Mod, Fun}, ok}];
-
- Error ->
- io:format("Ignoring: ~p: ~p\n", [{Mod, Fun}, Error]),
- [{failed, {Mod, Fun}, Error}]
- end;
-do_test(Mod, Config) when is_atom(Mod) ->
- Res = do_test({Mod, all}, Config),
- Res;
-do_test(Cases, Config) when is_list(Cases) ->
- [do_test(Case, Config) || Case <- Cases];
-do_test(Bad, _Config) ->
- [{badarg, Bad, ok}].
-
-eval(Mod, Fun, Config) ->
- TestCase = {?MODULE, Mod, Fun},
- Label = lists:concat(["TEST CASE: ", Fun]),
- et:report_event(40, ?MODULE, Mod, Label ++ " started",
- [TestCase, Config]),
- global:register_name(tftp_test_case_sup, self()),
- Flag = process_flag(trap_exit, true),
- Config2 = Mod:init_per_testcase(Fun, Config),
- Pid = spawn_link(?MODULE, do_eval, [self(), Mod, Fun, Config2]),
- R = wait_for_evaluator(Pid, Mod, Fun, Config2, []),
- Mod:end_per_testcase(Fun, Config2),
- global:unregister_name(tftp_test_case_sup),
- process_flag(trap_exit, Flag),
- R.
-
-wait_for_evaluator(Pid, Mod, Fun, Config, Errors) ->
- TestCase = {?MODULE, Mod, Fun},
- Label = lists:concat(["TEST CASE: ", Fun]),
- receive
- {done, Pid, ok} when Errors == [] ->
- et:report_event(40, Mod, ?MODULE, Label ++ " ok",
- [TestCase, Config]),
- {ok, {Mod, Fun}, Errors};
- {done, Pid, {ok, _}} when Errors == [] ->
- et:report_event(40, Mod, ?MODULE, Label ++ " ok",
- [TestCase, Config]),
- {ok, {Mod, Fun}, Errors};
- {done, Pid, Fail} ->
- et:report_event(20, Mod, ?MODULE, Label ++ " failed",
- [TestCase, Config, {return, Fail}, Errors]),
- {failed, {Mod,Fun}, Fail};
- {'EXIT', Pid, {skipped, Reason}} ->
- et:report_event(20, Mod, ?MODULE, Label ++ " skipped",
- [TestCase, Config, {skipped, Reason}]),
- {skipped, {Mod, Fun}, Errors};
- {'EXIT', Pid, Reason} ->
- et:report_event(20, Mod, ?MODULE, Label ++ " crashed",
- [TestCase, Config, {'EXIT', Reason}]),
- {crashed, {Mod, Fun}, [{'EXIT', Reason} | Errors]};
- {fail, Pid, Reason} ->
- wait_for_evaluator(Pid, Mod, Fun, Config, Errors ++ [Reason])
- end.
-
-do_eval(ReplyTo, Mod, Fun, Config) ->
- case (catch apply(Mod, Fun, [Config])) of
- {'EXIT', {skipped, Reason}} ->
- ReplyTo ! {'EXIT', self(), {skipped, Reason}};
- Other ->
- ReplyTo ! {done, self(), Other}
- end,
- unlink(ReplyTo),
- exit(shutdown).
-
-display_result([]) ->
- io:format("OK\n", []);
-display_result(Res) when is_list(Res) ->
- Ok = [MF || {ok, MF, _} <- Res],
- Nyi = [MF || {nyi, MF, _} <- Res],
- Skipped = [{MF, Reason} || {skipped, MF, Reason} <- Res],
- Failed = [{MF, Reason} || {failed, MF, Reason} <- Res],
- Crashed = [{MF, Reason} || {crashed, MF, Reason} <- Res],
- display_summary(Ok, Nyi, Skipped, Failed, Crashed),
- display_skipped(Skipped),
- display_failed(Failed),
- display_crashed(Crashed).
-
-display_summary(Ok, Nyi, Skipped, Failed, Crashed) ->
- io:format("\nTest case summary:\n", []),
- display_summary(Ok, "successful"),
- display_summary(Nyi, "not yet implemented"),
- display_summary(Skipped, "skipped"),
- display_summary(Failed, "failed"),
- display_summary(Crashed, "crashed"),
- io:format("\n", []).
-
-display_summary(Res, Info) ->
- io:format(" ~w test cases ~s\n", [length(Res), Info]).
-
-display_skipped([]) ->
- ok;
-display_skipped(Skipped) ->
- io:format("Skipped test cases:\n", []),
- F = fun({MF, Reason}) -> io:format(" ~p => ~p\n", [MF, Reason]) end,
- lists:foreach(F, Skipped),
- io:format("\n", []).
-
-
-display_failed([]) ->
- ok;
-display_failed(Failed) ->
- io:format("Failed test cases:\n", []),
- F = fun({MF, Reason}) -> io:format(" ~p => ~p\n", [MF, Reason]) end,
- lists:foreach(F, Failed),
- io:format("\n", []).
-
-display_crashed([]) ->
- ok;
-display_crashed(Crashed) ->
- io:format("Crashed test cases:\n", []),
- F = fun({MF, Reason}) -> io:format(" ~p => ~p\n", [MF, Reason]) end,
- lists:foreach(F, Crashed),
- io:format("\n", []).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% generic callback
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
--record(generic_state, {state, prepare, open, read, write, abort}).
-
-prepare(Peer, Access, LocalFilename, Mode, SuggestedOptions, Initial) when is_list(Initial) ->
- State = lookup_option(state, mandatory, Initial),
- Prepare = lookup_option(prepare, mandatory, Initial),
- Open = lookup_option(open, mandatory, Initial),
- Read = lookup_option(read, mandatory, Initial),
- Write = lookup_option(write, mandatory, Initial),
- Abort = lookup_option(abort, mandatory, Initial),
- case Prepare(Peer, Access, LocalFilename, Mode, SuggestedOptions, State) of
- {ok, AcceptedOptions, NewState} ->
- {ok,
- AcceptedOptions,
- #generic_state{state = NewState,
- prepare = Prepare,
- open = Open,
- read = Read,
- write = Write,
- abort = Abort}};
- Other ->
- Other
- end.
-
-open(Peer, Access, LocalFilename, Mode, SuggestedOptions, Initial) when is_list(Initial) ->
- case prepare(Peer, Access, LocalFilename, Mode, SuggestedOptions, Initial) of
- {ok, SuggestedOptions2, GenericState} ->
- open(Peer, Access, LocalFilename, Mode, SuggestedOptions2, GenericState);
- Other ->
- Other
- end;
-open(Peer, Access, LocalFilename, Mode, SuggestedOptions, #generic_state{state = State, open = Open} = GenericState) ->
- case Open(Peer, Access, LocalFilename, Mode, SuggestedOptions, State) of
- {ok, SuggestedOptions2, NewState} ->
- {ok, SuggestedOptions2, GenericState#generic_state{state = NewState}};
- Other ->
- Other
- end.
-
-read(#generic_state{state = State, read = Read} = GenericState) ->
- case Read(State) of
- {more, DataBlock, NewState} ->
- {more, DataBlock, GenericState#generic_state{state = NewState}};
- Other ->
- Other
- end.
-
-write(DataBlock, #generic_state{state = State, write = Write} = GenericState) ->
- case Write(DataBlock, State) of
- {more, NewState} ->
- {more, GenericState#generic_state{state = NewState}};
- Other ->
- Other
- end.
-
-abort(Code, Text, #generic_state{state = State, abort = Abort}) ->
- Abort(Code, Text, State).
-
-lookup_option(Key, Default, Options) ->
- case lists:keysearch(Key, 1, Options) of
- {value, {_, Val}} ->
- Val;
- false ->
- Default
- end.
-
diff --git a/lib/inets/test/tftp_test_lib.hrl b/lib/inets/test/tftp_test_lib.hrl
deleted file mode 100644
index e7a5a37d2c..0000000000
--- a/lib/inets/test/tftp_test_lib.hrl
+++ /dev/null
@@ -1,44 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--record('REASON', {mod, line, desc}).
-
--define(LOG(Format, Args),
- tftp_test_lib:log(Format, Args, ?MODULE, ?LINE)).
-
--define(ERROR(Reason),
- tftp_test_lib:error(Reason, ?MODULE, ?LINE)).
-
--define(VERIFY(Expected, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- Expected -> ?LOG("Ok, ~p\n", [AcTuAlReS]);
- _ -> ?ERROR(AcTuAlReS)
- end,
- AcTuAlReS
- end()).
-
--define(IGNORE(Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- ?LOG("Ok, ~p\n", [AcTuAlReS]),
- AcTuAlReS
- end()).
diff --git a/lib/inets/test/uri_SUITE.erl b/lib/inets/test/uri_SUITE.erl
index 3e7799141c..db6a8bdfc3 100644
--- a/lib/inets/test/uri_SUITE.erl
+++ b/lib/inets/test/uri_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -52,6 +52,7 @@ all() ->
escaped,
hexed_query,
scheme_validation,
+ scheme_validation_bin,
encode_decode
].
@@ -273,12 +274,32 @@ scheme_validation(Config) when is_list(Config) ->
http_uri:parse("https://localhost#fragment",
[{scheme_validation_fun, none}]).
+scheme_validation_bin(Config) when is_list(Config) ->
+ {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<>>}} =
+ http_uri:parse(<<"http://localhost#fragment">>),
+
+ ValidationFun =
+ fun(<<"http">>) -> valid;
+ (_) -> {error, bad_scheme}
+ end,
+
+ {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<>>}} =
+ http_uri:parse(<<"http://localhost#fragment">>,
+ [{scheme_validation_fun, ValidationFun}]),
+ {error, bad_scheme} =
+ http_uri:parse(<<"https://localhost#fragment">>,
+ [{scheme_validation_fun, ValidationFun}]),
+ %% non-fun scheme_validation_fun works as no option passed
+ {ok, {https,<<>>,<<"localhost">>,443,<<"/">>,<<>>}} =
+ http_uri:parse(<<"https://localhost#fragment">>,
+ [{scheme_validation_fun, none}]).
+
encode_decode(Config) when is_list(Config) ->
?assertEqual("foo%20bar", http_uri:encode("foo bar")),
?assertEqual(<<"foo%20bar">>, http_uri:encode(<<"foo bar">>)),
- ?assertEqual("foo bar", http_uri:decode("foo+bar")),
- ?assertEqual(<<"foo bar">>, http_uri:decode(<<"foo+bar">>)),
+ ?assertEqual("foo+bar", http_uri:decode("foo+bar")),
+ ?assertEqual(<<"foo+bar">>, http_uri:decode(<<"foo+bar">>)),
?assertEqual("foo bar", http_uri:decode("foo%20bar")),
?assertEqual(<<"foo bar">>, http_uri:decode(<<"foo%20bar">>)),
?assertEqual("foo\r\n", http_uri:decode("foo%0D%0A")),
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk
index 96796f11c0..26adb854e1 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2017. All Rights Reserved.
+# Copyright Ericsson AB 2001-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = inets
-INETS_VSN = 6.4
+INETS_VSN = 7.0.2
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"
diff --git a/lib/jinterface/doc/src/Makefile b/lib/jinterface/doc/src/Makefile
index 508c8e01b5..d80bb38ec1 100644
--- a/lib/jinterface/doc/src/Makefile
+++ b/lib/jinterface/doc/src/Makefile
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
+# Copyright Ericsson AB 2000-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -43,25 +43,17 @@ XML_APP_FILES = ref_man.xml
XML_REF3_FILES = jinterface.xml
XML_PART_FILES = \
- part.xml \
- part_notes.xml \
- part_notes_history.xml
-
+ part.xml
XML_CHAPTER_FILES = \
notes.xml \
- notes_history.xml \
jinterface_users_guide.xml
BOOK_FILES = book.xml
-XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \
- $(XML_PART_FILES) $(XML_CHAPTER_FILES)
-
-GIF_FILES = \
- notes.gif \
- ref_man.gif \
- user_guide.gif
+XML_FILES = $(BOOK_FILES) $(XML_APP_FILES) $(XML_REF3_FILES) \
+ $(XML_PART_FILES) $(XML_CHAPTER_FILES)
+GIF_FILES =
#------------------------------------------------------
@@ -92,7 +84,7 @@ JAVA_DOC_FILES = \
serialized-form.html \
package-list \
stylesheet.css \
- help-doc.html
+ help-doc.html
INFO_FILE = ../../info
JAVA_EXTRA_FILES = $(JAVA_DOC_FILES:%=$(HTMLDIR)/java/%)
@@ -110,17 +102,16 @@ JAVA_GEN_FILES = \
HTML_FILES = \
$(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
-TOP_HTML_FILES = $(INDEX_TARGET)
+TOP_HTML_FILES = $(INDEX_TARGET)
INDEX_FILE = index.html
-INDEX_SRC = $(INDEX_FILE).src
INDEX_TARGET = $(DOCDIR)/$(INDEX_FILE)
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
+XML_FLAGS +=
+DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -138,6 +129,7 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
@@ -146,18 +138,15 @@ jdoc:$(JAVA_SRC_FILES)
(cd ../../java_src;$(JAVADOC) -sourcepath . -d $(JAVADOC_DEST) \
-windowtitle $(JAVADOC_TITLE) $(JAVADOC_PKGS))
-man:
+man:
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-#$(INDEX_TARGET): $(INDEX_SRC) ../../vsn.mk
-# sed -e 's;%VSN%;$(VSN);' $< > $@
-
-debug opt:
+debug opt:
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
diff --git a/lib/jinterface/doc/src/fascicules.xml b/lib/jinterface/doc/src/fascicules.xml
deleted file mode 100644
index 4f04be0515..0000000000
--- a/lib/jinterface/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="yes">
- User Guide
- </fascicule>
- <fascicule file="" href="java/index.html" entry="no">
- Java API
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/jinterface/doc/src/index.html.src b/lib/jinterface/doc/src/index.html.src
deleted file mode 100644
index 9276c5f89a..0000000000
--- a/lib/jinterface/doc/src/index.html.src
+++ /dev/null
@@ -1,99 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<!-- This file is obsolete -->
-<HTML>
-<!--
- %CopyrightBegin%
-
- Copyright Ericsson AB 2000-2016. All Rights Reserved.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- %CopyrightEnd%
--->
-<HEAD>
-<TITLE>Jinterface %VSN%</TITLE>
-</HEAD>
-
-<BODY BGCOLOR="#FFFFFF">
-
-<CENTER>
-<A HREF="http://www.erlang.se/"><IMG ALT="Erlang/OTP" BORDER=0 SRC="html/min_head.gif"></A><BR>
-
-<FONT SIZE="-1">
-[<A HREF="../../../doc/index.html">Up</A> |
-<A HREF="http://www.erlang.se/">Erlang/OTP</A>]
-</FONT><BR>
-
-<P><FONT SIZE="+3">Jinterface </FONT><BR>
-Version %VSN%
-</CENTER>
-
-<P><TABLE>
-<TR>
-<TD>
-</TD>
-
-<TD>
-<STRONG>Jinterface</STRONG> contains functions,
-which help you integrate programs written in Java and Erlang.
-</TD>
-</TR>
-</TABLE>
-
-<P><CENTER>
-<TABLE CELLPADDING=15>
-<TR>
-
-
-<TD ALIGN=CENTER>
-<A HREF="html/part_frame.html">
-<IMG ALT="User Guide" BORDER=0 SRC="html/user_guide.gif"></A><BR>
-<FONT SIZE="-1">
-<A HREF="html/part_frame.html">User Guide</A>
-</FONT>
-</TD>
-
-
-<TD ALIGN=CENTER>
-<A HREF="html/index.html"><IMG ALT="Java API" BORDER=0 SRC="html/ref_man.gif"></A><BR>
-<FONT SIZE="-1">
-<A HREF="html/index.html">Java API</A>
-</FONT>
-</TD>
-
-
-
-<TD ALIGN=CENTER>
-<A HREF="html/part_notes_frame.html"><IMG ALT="Release Notes" BORDER=0 SRC="html/notes.gif"></A><BR>
-<FONT SIZE="-1">
-<A HREF="html/part_notes_frame.html">Release Notes</A>
-</FONT>
-</TD>
-
-</TR>
-</TABLE>
-</CENTER>
-
-<P><CENTER>
-<HR>
-<FONT SIZE="-1">
-Copyright &copy; 1991-2001
-<A HREF="http://www.erlang.se/">Ericsson Utvecklings AB</A>
-</FONT>
-</CENTER>
-</BODY>
-</HTML>
-
-
-
-
diff --git a/lib/jinterface/doc/src/notes.gif b/lib/jinterface/doc/src/notes.gif
deleted file mode 100644
index e000cca26a..0000000000
--- a/lib/jinterface/doc/src/notes.gif
+++ /dev/null
Binary files differ
diff --git a/lib/jinterface/doc/src/notes.xml b/lib/jinterface/doc/src/notes.xml
index b44a04d7cd..75a2364384 100644
--- a/lib/jinterface/doc/src/notes.xml
+++ b/lib/jinterface/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2017</year>
+ <year>2000</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,51 @@
</header>
<p>This document describes the changes made to the Jinterface application.</p>
+<section><title>Jinterface 1.9.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Jinterface 1.9</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add module package name for Java 9</p>
+ <p>
+ Own Id: OTP-14844</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Jinterface 1.8.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Jinterface 1.8</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/jinterface/doc/src/part_notes.xml b/lib/jinterface/doc/src/part_notes.xml
deleted file mode 100644
index de6dd7d162..0000000000
--- a/lib/jinterface/doc/src/part_notes.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Jinterface Release Notes</title>
- <prepared>Gordon Beaton</prepared>
- <docno></docno>
- <date>1999-10-25</date>
- <rev>A</rev>
- </header>
- <description>
- <p>The <em>Jinterface</em> application is a Java-Erlang
- communication tool package.</p>
- <p>For information about older versions, see
- <url href="part_notes_history_frame.html">Release Notes History</url>.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/jinterface/doc/src/part_notes_history.xml b/lib/jinterface/doc/src/part_notes_history.xml
deleted file mode 100644
index 94bb996db5..0000000000
--- a/lib/jinterface/doc/src/part_notes_history.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2006</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Jinterface Release Notes History</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p>The <em>Jinterface</em> application is a Java-Erlang
- communication tool package.</p>
- </description>
- <include file="notes_history"></include>
-</part>
-
diff --git a/lib/jinterface/doc/src/ref_man.gif b/lib/jinterface/doc/src/ref_man.gif
deleted file mode 100644
index b13c4efd53..0000000000
--- a/lib/jinterface/doc/src/ref_man.gif
+++ /dev/null
Binary files differ
diff --git a/lib/jinterface/doc/src/summary.html.src b/lib/jinterface/doc/src/summary.html.src
deleted file mode 100644
index beb3305d58..0000000000
--- a/lib/jinterface/doc/src/summary.html.src
+++ /dev/null
@@ -1 +0,0 @@
-Low level interface to Java. \ No newline at end of file
diff --git a/lib/jinterface/doc/src/user_guide.gif b/lib/jinterface/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/jinterface/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile b/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile
index e55cfa62ea..ee616f3d7e 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
+# Copyright Ericsson AB 2000-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -130,7 +130,6 @@ release_spec: opt
release_docs_spec:
-
-
+xmllint:
# ----------------------------------------------------
diff --git a/lib/jinterface/java_src/pom.xml.src b/lib/jinterface/java_src/pom.xml.src
index 98232db78c..584bd81076 100644
--- a/lib/jinterface/java_src/pom.xml.src
+++ b/lib/jinterface/java_src/pom.xml.src
@@ -76,6 +76,17 @@
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifestEntries>
+ <Automatic-Module-Name>com.ericsson.otp.erlang</Automatic-Module-Name>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version>
<executions>
diff --git a/lib/jinterface/test/jinterface_SUITE.erl b/lib/jinterface/test/jinterface_SUITE.erl
index 73851f47e0..468981a557 100644
--- a/lib/jinterface/test/jinterface_SUITE.erl
+++ b/lib/jinterface/test/jinterface_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -176,11 +176,29 @@ init_per_suite(Config) when is_list(Config) ->
{error,bad_name} -> false;
P -> filelib:is_dir(P) end of
true ->
- jitu:init_all(Config);
+ case hostname_resolves() of
+ true ->
+ jitu:init_all(Config);
+ Skip ->
+ Skip
+ end;
false ->
{skip,"No jinterface application"}
end.
+%% Check if inet:gethostname() can be resolved by
+%% the native resolver. If it can, we know that
+%% jinterface name resolution works. If it cannot
+%% jinterface tests will fail.
+hostname_resolves() ->
+ {ok, HN} = inet:gethostname(),
+ case inet_gethost_native:gethostbyname(HN) of
+ {ok, _} ->
+ true;
+ _ ->
+ {skip, "Cannot resolve short hostname, add " ++ HN ++ " to /etc/hosts"}
+ end.
+
end_per_suite(Config) when is_list(Config) ->
jitu:finish_all(Config).
diff --git a/lib/jinterface/test/nc_SUITE.erl b/lib/jinterface/test/nc_SUITE.erl
index 81944f71d4..4f225a396e 100644
--- a/lib/jinterface/test/nc_SUITE.erl
+++ b/lib/jinterface/test/nc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -651,11 +651,10 @@ do_echo(DataList, Config, OutTrans, InTrans, ExtraArgs)
echo_loop([D|Ds], Echoer, OutTrans, InTrans, TermAcc) ->
OutMsg = OutTrans(D),
Echoer ! OutMsg,
- io:format("echo_server ~p: ~p ! ~P~n", [self(),Echoer,OutMsg,10]),
+ %%io:format("echo_server ~p: ~p ! ~P~n", [self(),Echoer,OutMsg,10]),
receive
Reply ->
- io:format("echo_server ~p: receive ~P~n",
- [self(),Reply,10]),
+ %%io:format("echo_server ~p: receive ~P~n", [self(),Reply,10]),
InTrans(Echoer, D, Reply)
end,
Term = case OutMsg of
@@ -670,11 +669,10 @@ echo_loop(Cont, Echoer, OutTrans, InTrans, TermAcc)
when is_function(Cont, 0) ->
check_terms(Echoer, TermAcc),
OutMsg = Echoer ! {self(),undefined,hash_clear},
- io:format("echo_server ~p: ~p ! ~P~n", [self(),Echoer,OutMsg,10]),
+ %%io:format("echo_server ~p: ~p ! ~P~n", [self(),Echoer,OutMsg,10]),
receive
{Echoer,hash_cleared,hash_clear}=Reply ->
- io:format("echo_server ~p: receive ~P~n",
- [self(),Reply,10]),
+ %%io:format("echo_server ~p: receive ~P~n", [self(),Reply,10]),
ok;
Other ->
io:format("echo_server_terms unexpected ~p: receive ~P~n",
@@ -686,11 +684,10 @@ echo_loop(Cont, Echoer, OutTrans, InTrans, TermAcc)
check_terms(Echoer, [Term | Rest]) ->
OutMsg = {self(),Term,hash_lookup},
Echoer ! OutMsg,
- io:format("check_terms ~p: ~p ! ~P~n", [self(),Echoer,OutMsg,10]),
+ %%io:format("check_terms ~p: ~p ! ~P~n", [self(),Echoer,OutMsg,10]),
receive
{Echoer,true,hash_lookup} = ReplyMsg ->
- io:format("check_terms ~p: receive ~P~n",
- [self(),ReplyMsg,10]),
+ %%io:format("check_terms ~p: receive ~P~n", [self(),ReplyMsg,10]),
check_terms(Echoer, Rest);
Other ->
io:format("check_terms unexpected ~p: receive ~P~n",
diff --git a/lib/jinterface/vsn.mk b/lib/jinterface/vsn.mk
index 373e2dab22..a8dc815145 100644
--- a/lib/jinterface/vsn.mk
+++ b/lib/jinterface/vsn.mk
@@ -1 +1 @@
-JINTERFACE_VSN = 1.8
+JINTERFACE_VSN = 1.9.1
diff --git a/lib/kernel/doc/src/.gitignore b/lib/kernel/doc/src/.gitignore
new file mode 100644
index 0000000000..c2813ac866
--- /dev/null
+++ b/lib/kernel/doc/src/.gitignore
@@ -0,0 +1 @@
+*.eps \ No newline at end of file
diff --git a/lib/kernel/doc/src/Makefile b/lib/kernel/doc/src/Makefile
index 8976a3b800..f8867ccf25 100644
--- a/lib/kernel/doc/src/Makefile
+++ b/lib/kernel/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -42,6 +42,7 @@ XML_REF3_FILES = application.xml \
disk_log.xml \
erl_boot_server.xml \
erl_ddll.xml \
+ erl_epmd.xml \
erl_prim_loader_stub.xml \
erlang_stub.xml \
error_handler.xml \
@@ -56,6 +57,11 @@ XML_REF3_FILES = application.xml \
inet.xml \
inet_res.xml \
init_stub.xml \
+ logger.xml \
+ logger_std_h.xml \
+ logger_disk_log_h.xml \
+ logger_filters.xml \
+ logger_formatter.xml \
net_adm.xml \
net_kernel.xml \
os.xml \
@@ -70,11 +76,18 @@ XML_REF4_FILES = app.xml config.xml
XML_REF6_FILES = kernel_app.xml
-XML_PART_FILES = part_notes.xml part_notes_history.xml
-XML_CHAPTER_FILES = notes.xml notes_history.xml
+XML_PART_FILES = part.xml
+XML_CHAPTER_FILES = \
+ notes.xml \
+ introduction_chapter.xml \
+ logger_chapter.xml
BOOK_FILES = book.xml
+# The .png file is generated from a .dia file with target 'update_png'
+IMAGE_FILES = \
+ logger_arch.png
+
XML_FILES = \
$(BOOK_FILES) $(XML_CHAPTER_FILES) \
$(XML_PART_FILES) $(XML_REF3_FILES) $(XML_REF4_FILES)\
@@ -100,9 +113,20 @@ SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
TOP_SPECS_FILE = specs.xml
# ----------------------------------------------------
-# FLAGS
+# FIGURES
+# ----------------------------------------------------
+# In order to update the figures you have to have both dia
+# and imagemagick installed.
+# The generated .png file must be committed.
+
+update_png:
+ dia --export=logger_arch.eps logger_arch.dia
+ convert logger_arch.eps -resize 65% logger_arch.png
+
+# ----------------------------------------------------
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
+XML_FLAGS +=
SPECS_ESRC = ../../src
@@ -111,7 +135,7 @@ SPECS_FLAGS = -I../../include
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-$(HTMLDIR)/%.gif: %.gif
+$(HTMLDIR)/%: %
$(INSTALL_DATA) $< $@
docs: man pdf html
@@ -120,38 +144,40 @@ $(TOP_PDF_FILE): $(XML_FILES)
pdf: $(TOP_PDF_FILE)
-html: gifs $(HTML_REF_MAN_FILE)
+html: images $(HTML_REF_MAN_FILE)
man: $(MAN3_FILES) $(MAN4_FILES) $(MAN6_FILES)
-gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-debug opt:
+images: $(IMAGE_FILES:%=$(HTMLDIR)/%)
+
+debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN4DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(SPECDIR)/*
- rm -f errs core *~
+ rm -f errs core *~ *.eps
$(SPECDIR)/specs_erl_prim_loader_stub.xml:
- escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ $(gen_verbose)escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
-o$(dir $@) -module erl_prim_loader_stub
$(SPECDIR)/specs_erlang_stub.xml:
- escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ $(gen_verbose)escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
-o$(dir $@) -module erlang_stub
$(SPECDIR)/specs_init_stub.xml:
- escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ $(gen_verbose)escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
-o$(dir $@) -module init_stub
$(SPECDIR)/specs_zlib_stub.xml:
- escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ $(gen_verbose)escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
-o$(dir $@) -module zlib_stub
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
@@ -169,4 +195,3 @@ release_docs_spec: docs
$(INSTALL_DATA) $(MAN6_FILES) "$(RELEASE_PATH)/man/man6"
release_spec:
-
diff --git a/lib/kernel/doc/src/application.xml b/lib/kernel/doc/src/application.xml
index 886286b76d..38c7b5acf1 100644
--- a/lib/kernel/doc/src/application.xml
+++ b/lib/kernel/doc/src/application.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -318,8 +318,13 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
<c>{error,{not_started,App}}</c> is returned, where <c>App</c>
is the name of the missing application.</p>
<p>The application controller then creates an <em>application master</em>
- for the application. The application master is
- the group leader of all the processes in the application.
+ for the application. The application master becomes the
+ group leader of all the processes in the application. I/O is
+ forwarded to the previous group leader, though, this is just
+ a way to identify processes that belong to the application.
+ Used for example to find itself from any process, or,
+ reciprocally, to kill them all when it terminates.</p>
+ <p>
The application master starts the application by calling
the application callback function <c>Module:start/2</c> as
defined by the application specification key <c>mod</c>.</p>
@@ -608,4 +613,3 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
<seealso marker="app">app(4)</seealso></p>
</section>
</erlref>
-
diff --git a/lib/kernel/doc/src/book.xml b/lib/kernel/doc/src/book.xml
index 81a87d126d..4b3573b9fe 100644
--- a/lib/kernel/doc/src/book.xml
+++ b/lib/kernel/doc/src/book.xml
@@ -4,7 +4,7 @@
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<header titlestyle="normal">
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,6 +34,9 @@
<preamble>
<contents level="2"></contents>
</preamble>
+ <parts lift="yes">
+ <xi:include href="part.xml"/>
+ </parts>
<applications>
<xi:include href="ref_man.xml"/>
</applications>
diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml
index c94f612c01..aff3e8133c 100644
--- a/lib/kernel/doc/src/code.xml
+++ b/lib/kernel/doc/src/code.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,26 +34,28 @@
<p>This module contains the interface to the Erlang
<em>code server</em>, which deals with the loading of compiled
code into a running Erlang runtime system.</p>
- <p>The runtime system can be started in <em>embedded</em> or
- <em>interactive</em> mode. Which one is decided by command-line
+ <p>The runtime system can be started in <em>interactive</em> or
+ <em>embedded</em> mode. Which one is decided by the command-line
flag <c>-mode</c>:</p>
<pre>
% <input>erl -mode interactive</input></pre>
<p>The modes are as follows:</p>
<list type="bulleted">
<item>
- <p>In embedded mode, all code is loaded during system startup
- according to the boot script. (Code can also be loaded later
- by explicitly ordering the code server to do so).</p>
- </item>
- <item>
<p>In interactive mode, which is default, only some code is loaded
- during system startup, basically the modules needed by the runtime
+ during system startup, basically the modules needed by the runtime
system. Other code is dynamically loaded when first
referenced. When a call to a function in a certain module is
made, and the module is not loaded, the code server searches
for and tries to load the module.</p>
</item>
+ <item>
+ <p>In embedded mode, modules are not auto loaded. Trying to use
+ a module that has not been loaded results in an error. This mode is
+ recommended when the boot script loads all modules, as it is
+ typically done in OTP releases. (Code can still be loaded later
+ by explicitly ordering the code server to do so).</p>
+ </item>
</list>
<p>To prevent accidentally reloading of modules affecting the Erlang
runtime system, directories <c>kernel</c>, <c>stdlib</c>,
diff --git a/lib/kernel/doc/src/config.xml b/lib/kernel/doc/src/config.xml
index fdb2d29f63..714af93f4d 100644
--- a/lib/kernel/doc/src/config.xml
+++ b/lib/kernel/doc/src/config.xml
@@ -4,7 +4,7 @@
<fileref>
<header>
<copyright>
- <year>1997</year><year>2017</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -37,10 +37,10 @@
data in the system configuration file <c>Name.config</c>.</p>
<p>Configuration parameter values in the configuration file
override the values in the application resource files (see
- <seealso marker="app"><c>app(4)</c></seealso>.
+ <seealso marker="app"><c>app(4)</c></seealso>).
The values in the configuration file can be
overridden by command-line flags (see
- <seealso marker="erts:erl"><c>erts:erl(1)</c></seealso>.</p>
+ <seealso marker="erts:erl"><c>erts:erl(1)</c></seealso>).</p>
<p>The value of a configuration parameter is retrieved by calling
<c>application:get_env/1,2</c>.</p>
</description>
@@ -86,8 +86,13 @@
<tag><c>File = string()</c></tag>
<item>Name of another <c>.config</c> file.
Extension <c>.config</c> can be omitted. It is
- recommended to use absolute paths. A relative path is
- relative the current working directory of the emulator.</item>
+ recommended to use absolute paths. If a relative path is used,
+ <c>File</c> is searched, first, relative from <c>sys.config</c> directory, then relative
+ to the current working directory of the emulator, for backward compatibility.
+ This allow to use a <c>sys.config</c> pointing out other <c>.config</c> files in a release
+ or in a node started manually using <c>-config ...</c> with same result whatever
+ the current working directory.
+ </item>
</taglist>
<p>When traversing the contents of <c>sys.config</c> and a filename
is encountered, its contents are read and merged with the result
diff --git a/lib/kernel/doc/src/disk_log.xml b/lib/kernel/doc/src/disk_log.xml
index 1be28adfb8..884cb32c0c 100644
--- a/lib/kernel/doc/src/disk_log.xml
+++ b/lib/kernel/doc/src/disk_log.xml
@@ -972,7 +972,7 @@
<item>
<p>Specifies if messages will be sent to
<c>error_logger</c> on recoverable errors with
- the log files. Defaults to <c>true</c>.</p>
+ the log files. Defaults to <c>false</c>.</p>
</item>
</taglist>
<p><c>open/1</c> returns <c>{ok, <anno>Log</anno>}</c> if the
diff --git a/lib/kernel/doc/src/erl_epmd.xml b/lib/kernel/doc/src/erl_epmd.xml
new file mode 100644
index 0000000000..8b076cd2d7
--- /dev/null
+++ b/lib/kernel/doc/src/erl_epmd.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2018</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>erl_epmd</title>
+ <prepared>Timmo Verlaan</prepared>
+ <docno>1</docno>
+ <date>2018-02-19</date>
+ <rev>A</rev>
+ </header>
+ <module>erl_epmd</module>
+ <modulesummary>
+ Erlang interface towards epmd
+ </modulesummary>
+ <description>
+ <p>This module communicates with the EPMD daemon, see <seealso
+ marker="erts:epmd">epmd</seealso>. To implement your own epmd module please
+ see <seealso marker="erts:alt_disco">ERTS User's Guide: How to Implement an
+ Alternative Service Discovery for Erlang Distribution</seealso></p>
+ </description>
+
+ <funcs>
+ <func>
+ <name name="start_link" arity="0"/>
+ <fsummary>Callback for erl_distribution supervisor.</fsummary>
+ <desc>
+ <p>This function is invoked as this module is added as a child of the
+ <c>erl_distribution</c> supervisor.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="register_node" arity="2"/>
+ <name name="register_node" arity="3"/>
+ <fsummary>Registers the node with <c>epmd</c>.</fsummary>
+ <desc>
+ <p>Registers the node with <c>epmd</c> and tells epmd what port will be
+ used for the current node. It returns a creation number. This number is
+ incremented on each register to help with identifying if a node is
+ reconnecting to epmd.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="port_please" arity="2"/>
+ <name name="port_please" arity="3"/>
+ <fsummary>Returns the port number for a given node.</fsummary>
+ <desc>
+ <p>Requests the distribution port for the given node of an EPMD
+ instance. Together with the port it returns a distribution protocol
+ version which has been 5 since Erlang/OTP R6.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="address_please" arity="3"/>
+ <fsummary>Returns address and port.</fsummary>
+ <desc>
+ <p>Called by the distribution module. Resolves the <c>Host</c> to an IP
+ address.</p>
+ <p>Another epmd module may return port and distribution protocol version
+ as well.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="names" arity="1"/>
+ <fsummary>Names of Erlang nodes at a host.</fsummary>
+ <desc>
+ <p>Called by <seealso marker="net_adm"><c>net_adm:names/0</c></seealso>.
+ <c>Host</c> defaults to the localhost. Returns the names and associated
+ port numbers of the Erlang nodes that <c>epmd</c> registered at the
+ specified host. Returns <c>{error, address}</c> if <c>epmd</c> is not
+ operational.</p>
+ <p><em>Example:</em></p>
+ <pre>
+(arne@dunn)1> <input>erl_epmd:names(localhost).</input>
+{ok,[{"arne",40262}]}</pre>
+ </desc>
+ </func>
+ </funcs>
+
+</erlref>
+
diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml
index 91bf57cb91..c3d68fd79f 100644
--- a/lib/kernel/doc/src/error_logger.xml
+++ b/lib/kernel/doc/src/error_logger.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,36 +31,37 @@
<module>error_logger</module>
<modulesummary>Erlang error logger.</modulesummary>
<description>
+
+ <note>
+ <p>In Erlang/OTP 21.0, a new API for logging was added. The
+ old <c>error_logger</c> module can still be used by legacy
+ code, but log events are redirected to the new Logger API. New
+ code should use the Logger API directly.</p>
+ <p><c>error_logger</c> is no longer started by default, but is
+ automatically started when an event handler is added
+ with <c>error_logger:add_report_handler/1,2</c>. The <c>error_logger</c>
+ module is then also added as a handler to the new logger.</p>
+ <p>See <seealso marker="logger"><c>logger(3)</c></seealso> and
+ the <seealso marker="logger_chapter">Logging</seealso> chapter
+ in the User's Guide for more information.</p>
+ </note>
+
<p>The Erlang <em>error logger</em> is an event manager (see
<seealso marker="doc/design_principles:des_princ">OTP Design Principles</seealso> and
<seealso marker="stdlib:gen_event"><c>gen_event(3)</c></seealso>),
- registered as <c>error_logger</c>. Errors, warnings, and info events
- are sent to the error logger from the Erlang runtime system and
- the different Erlang/OTP applications. The events are, by default,
- logged to the terminal. Notice that an event from a process <c>P</c> is
- logged at the node of the group leader of <c>P</c>. This means
- that log output is directed to the node from which a process was
- created, which not necessarily is the same node as where it is
- executing.</p>
- <p>Initially, <c>error_logger</c> has only a primitive event
- handler, which buffers and prints the raw event messages. During
- system startup, the Kernel application replaces this with a
- <em>standard event handler</em>, by default one that writes
- nicely formatted output to the terminal. Kernel can also be
- configured so that events are logged to a file instead, or not logged at all,
- see <seealso marker="kernel_app"><c>kernel(6)</c></seealso>.</p>
- <p>Also the SASL application, if started, adds its own event
- handler, which by default writes supervisor, crash, and progress
- reports to the terminal. See
- <seealso marker="sasl:sasl_app"><c>sasl(6)</c></seealso>.</p>
- <p>It is recommended that user-defined applications report
- errors through the error logger to get uniform reports.
- User-defined event handlers can be added to handle application-specific
- events, see
- <seealso marker="#add_report_handler/1"><c>add_report_handler/1,2</c></seealso>.
- Also, a useful event handler is provided in STDLIB for multi-file
- logging of events, see
- <seealso marker="stdlib:log_mf_h"><c>log_mf_h(3)</c></seealso>.</p>
+ registered as <c>error_logger</c>.</p>
+ <p>Error logger is no longer started by default, but is
+ automatically started when an event handler is added
+ with <seealso marker="#add_report_handler/1">
+ <c>add_report_handler/1,2</c></seealso>. The <c>error_logger</c>
+ module is then also added as a handler to the new logger,
+ causing log events to be forwarded from logger to error logger,
+ and consequently to all installed error logger event
+ handlers.</p>
+ <p>User-defined event handlers can be added to handle application-specific
+ events.</p>
+ <p>Existing event handlers provided by STDLIB and SASL are still
+ available, but are no longer used by OTP.</p>
<p>Warning events were introduced in Erlang/OTP R9C and are enabled
by default as from Erlang/OTP 18.0. To retain backwards compatibility
with existing user-defined event handlers, the warning events can be
@@ -89,6 +90,9 @@
The function returns <c>ok</c> if successful.</p>
<p>The event handler must be able to handle the events in this module, see
section <seealso marker="#events">Events</seealso>.</p>
+ <p>The first time this function is called,
+ <c>error_logger</c> is added as a Logger handler, and
+ the <c>error_logger</c> process is started.</p>
</desc>
</func>
<func>
@@ -98,37 +102,40 @@
<p>Deletes an event handler from the error logger by calling
<c>gen_event:delete_handler(error_logger, <anno>Handler</anno>, [])</c>,
see <seealso marker="stdlib:gen_event"><c>gen_event(3)</c></seealso>.</p>
+ <p>If no more event handlers exist after the deletion,
+ <c>error_logger</c> is removed as a Logger handler, and
+ the <c>error_logger</c> process is stopped.</p>
</desc>
</func>
<func>
<name name="error_msg" arity="1"/>
<name name="error_msg" arity="2"/>
<name name="format" arity="2"/>
- <fsummary>Send a standard error event to the error logger.</fsummary>
+ <fsummary>Log a standard error event.</fsummary>
<desc>
- <p>Sends a standard error event to the error logger.
- The <c><anno>Format</anno></c> and <c><anno>Data</anno></c> arguments
- are the same as the arguments of
+ <p>Log a standard error event. The <c><anno>Format</anno></c>
+ and <c><anno>Data</anno></c> arguments are the same as the
+ arguments of
<seealso marker="stdlib:io#format/2"><c>io:format/2</c></seealso>
- in STDLIB.
- The event is handled by the standard event handler.</p>
+ in STDLIB.</p>
+ <p>Error logger forwards the event to Logger, including
+ metadata that allows backwards compatibility with legacy
+ error logger event handlers.</p>
+ <p>The event is handled by the default Logger handler.</p>
+ <p>These functions are kept for backwards compatibility and
+ must not be used by new code. Use the <seealso marker="logger#macros">
+ <c>?LOG_ERROR</c></seealso> macro or
+ <seealso marker="logger#error-1"><c>logger:error/1,2,3</c></seealso>
+ instead.</p>
<p><em>Example:</em></p>
<pre>
-1> <input>error_logger:error_msg("An error occurred in ~p~n", [a_module]).</input>
-
-=ERROR REPORT==== 11-Aug-2005::14:03:19 ===
+1> <input>error_logger:error_msg("An error occurred in ~p", [a_module]).</input>
+=ERROR REPORT==== 22-May-2018::11:18:43.376917 ===
An error occurred in a_module
ok</pre>
<warning>
- <p>If called with bad arguments, this function can crash
- the standard event handler, meaning no further events are
- logged. When in doubt, use
- <seealso marker="#error_report/1"><c>error_report/1</c></seealso>
- instead.</p>
- </warning>
- <warning>
<p>If the Unicode translation modifier (<c>t</c>) is used in
- the format string, all error handlers must ensure that the
+ the format string, all event handlers must ensure that the
formatted output is correctly encoded for the I/O
device.</p>
</warning>
@@ -136,36 +143,51 @@ ok</pre>
</func>
<func>
<name name="error_report" arity="1"/>
- <fsummary>Send a standard error report event to the error logger.</fsummary>
+ <fsummary>Log a standard error event.</fsummary>
<desc>
- <p>Sends a standard error report event to the error logger.
- The event is handled by the standard event handler.</p>
+ <p>Log a standard error event. Error logger forwards the event
+ to Logger, including metadata that allows backwards
+ compatibility with legacy error logger event handlers.</p>
+ <p>The event is handled by the default Logger handler.</p>
+ <p>This functions is kept for backwards compatibility and
+ must not be used by new code. Use the <seealso marker="logger#macros">
+ <c>?LOG_ERROR</c></seealso> macro or
+ <seealso marker="logger#error-1"><c>logger:error/1,2,3</c></seealso>
+ instead.</p>
<p><em>Example:</em></p>
<pre>
2> <input>error_logger:error_report([{tag1,data1},a_term,{tag2,data}]).</input>
-
-=ERROR REPORT==== 11-Aug-2005::13:45:41 ===
+=ERROR REPORT==== 22-May-2018::11:24:23.699306 ===
tag1: data1
a_term
tag2: data
ok
3> <input>error_logger:error_report("Serious error in my module").</input>
-
-=ERROR REPORT==== 11-Aug-2005::13:45:49 ===
+=ERROR REPORT==== 22-May-2018::11:24:45.972445 ===
Serious error in my module
ok</pre>
</desc>
</func>
<func>
<name name="error_report" arity="2"/>
- <fsummary>Send a user-defined error report event to the error logger.</fsummary>
+ <fsummary>Log a user-defined error event.</fsummary>
<desc>
- <p>Sends a user-defined error report event to the error logger.
- An event handler to handle the event is supposed to have been
- added. The event is ignored by the standard event handler.</p>
+ <p>Log a user-defined error event. Error logger forwards the
+ event to Logger, including metadata that allows backwards
+ compatibility with legacy error logger event handlers.</p>
+ <p>Error logger also adds a <c>domain</c> field with
+ value <c>[<anno>Type</anno>]</c> to this event's metadata,
+ causing the filters of the default Logger handler to discard
+ the event. A different Logger handler, or an error logger
+ event handler, must be added to handle this event.</p>
<p>It is recommended that <c><anno>Report</anno></c> follows the same
structure as for
<seealso marker="#error_report/1"><c>error_report/1</c></seealso>.</p>
+ <p>This functions is kept for backwards compatibility and
+ must not be used by new code. Use the <seealso marker="logger#macros">
+ <c>?LOG_ERROR</c></seealso> macro or
+ <seealso marker="logger#error-1"><c>logger:error/1,2,3</c></seealso>
+ instead.</p>
</desc>
</func>
<func>
@@ -174,38 +196,48 @@ ok</pre>
<c>error_logger_format_depth</c>.</fsummary>
<desc>
<p>Returns <c>max(10, Depth)</c>, where <c>Depth</c> is the
- value of
- <seealso marker="kernel:kernel_app#error_logger_format_depth">
- error_logger_format_depth</seealso>
+ value of <c>error_logger_format_depth</c>
in the Kernel application, if Depth is an integer. Otherwise,
<c>unlimited</c> is returned.</p>
+ <note>
+ <p>The <c>error_logger_format_depth</c> variable
+ is <seealso marker="kernel_app#deprecated-configuration-parameters">
+ deprecated</seealso> since
+ the <seealso marker="logger">Logger API</seealso> was
+ introduced in Erlang/OTP 21.0. The variable, and this
+ function, are kept for backwards compatibility since they
+ still might be used by legacy report handlers.</p>
+ </note>
</desc>
</func>
<func>
<name name="info_msg" arity="1"/>
<name name="info_msg" arity="2"/>
- <fsummary>Send a standard information event to the error logger.</fsummary>
+ <fsummary>Log a standard information event.</fsummary>
<desc>
- <p>Sends a standard information event to the error logger.
- The <c><anno>Format</anno></c> and <c><anno>Data</anno></c> arguments
- are the same as the arguments of
+ <p>Log a standard information event. The <c><anno>Format</anno></c>
+ and <c><anno>Data</anno></c> arguments are the same as the
+ arguments of
<seealso marker="stdlib:io#format/2"><c>io:format/2</c></seealso>
- in STDLIB. The event is handled by the standard event handler.</p>
+ in STDLIB.</p>
+ <p>Error logger forwards the event to Logger, including
+ metadata that allows backwards compatibility with legacy
+ error logger event handlers.</p>
+ <p>The event is handled by the default Logger handler.</p>
+ <p>These functions are kept for backwards compatibility and
+ must not be used by new code. Use the <seealso marker="logger#macros">
+ <c>?LOG_INFO</c></seealso> macro or
+ <seealso marker="logger#info-1"><c>logger:info/1,2,3</c></seealso>
+ instead.</p>
<p><em>Example:</em></p>
<pre>
-1> <input>error_logger:info_msg("Something happened in ~p~n", [a_module]).</input>
-
-=INFO REPORT==== 11-Aug-2005::14:06:15 ===
+1> <input>error_logger:info_msg("Something happened in ~p", [a_module]).</input>
+=INFO REPORT==== 22-May-2018::12:03:32.612462 ===
Something happened in a_module
ok</pre>
<warning>
- <p>If called with bad arguments, this function can crash
- the standard event handler, meaning no further events are
- logged. When in doubt, use <c>info_report/1</c> instead.</p>
- </warning>
- <warning>
<p>If the Unicode translation modifier (<c>t</c>) is used in
- the format string, all error handlers must ensure that the
+ the format string, all event handlers must ensure that the
formatted output is correctly encoded for the I/O
device.</p>
</warning>
@@ -213,37 +245,52 @@ ok</pre>
</func>
<func>
<name name="info_report" arity="1"/>
- <fsummary>Send a standard information report event to the error logger.</fsummary>
+ <fsummary>Log a standard information event.</fsummary>
<desc>
- <p>Sends a standard information report event to the error
- logger. The event is handled by the standard event handler.</p>
+ <p>Log a standard information event. Error logger forwards the
+ event to Logger, including metadata that allows backwards
+ compatibility with legacy error logger event handlers.</p>
+ <p>The event is handled by the default Logger handler.</p>
+ <p>This functions is kept for backwards compatibility and
+ must not be used by new code. Use the <seealso marker="logger#macros">
+ <c>?LOG_INFO</c></seealso> macro or
+ <seealso marker="logger#info-1"><c>logger:info/1,2,3</c></seealso>
+ instead.</p>
<p><em>Example:</em></p>
<pre>
2> <input>error_logger:info_report([{tag1,data1},a_term,{tag2,data}]).</input>
-
-=INFO REPORT==== 11-Aug-2005::13:55:09 ===
+=INFO REPORT==== 22-May-2018::12:06:35.994440 ===
tag1: data1
a_term
tag2: data
ok
3> <input>error_logger:info_report("Something strange happened").</input>
-
-=INFO REPORT==== 11-Aug-2005::13:55:36 ===
+=INFO REPORT==== 22-May-2018::12:06:49.066872 ===
Something strange happened
ok</pre>
</desc>
</func>
<func>
<name name="info_report" arity="2"/>
- <fsummary>Send a user-defined information report event to the error logger.</fsummary>
+ <fsummary>Log a user-defined information event.</fsummary>
<desc>
- <p>Sends a user-defined information report event to the error
- logger. An event handler to handle the event is supposed to
- have been added. The event is ignored by the standard event
- handler.</p>
+ <p>Log a user-defined information event. Error logger forwards
+ the event to Logger, including metadata that allows
+ backwards compatibility with legacy error logger event
+ handlers.</p>
+ <p>Error logger also adds a <c>domain</c> field with
+ value <c>[<anno>Type</anno>]</c> to this event's metadata,
+ causing the filters of the default Logger handler to discard
+ the event. A different Logger handler, or an error logger
+ event handler, must be added to handle this event.</p>
<p>It is recommended that <c><anno>Report</anno></c> follows the same
structure as for
<seealso marker="#info_report/1"><c>info_report/1</c></seealso>.</p>
+ <p>This functions is kept for backwards compatibility and
+ must not be used by new code. Use the <seealso marker="logger#macros">
+ <c>?LOG_INFO</c></seealso> macro or
+ <seealso marker="logger#info-1"><c>logger:info/1,2,3</c></seealso>
+ instead.</p>
</desc>
</func>
<func>
@@ -258,14 +305,22 @@ ok</pre>
<type name="open_error"/>
<desc>
<p>Enables or disables printout of standard events to a file.</p>
- <p>This is done by adding or deleting the standard event handler
- for output to file. Thus, calling this function overrides
- the value of the Kernel <c>error_logger</c> configuration
- parameter.</p>
- <p>Enabling file logging can be used together with calling
- <c>tty(false)</c>, to have a silent system where
- all standard events are logged to a file only.
- Only one log file can be active at a time.</p>
+ <p>This is done by adding or deleting
+ the <c>error_logger_file_h</c> event handler, and thus
+ indirectly adding <c>error_logger</c> as a Logger
+ handler.</p>
+ <p>Notice that this function does not manipulate the Logger
+ configuration directly, meaning that if the default Logger
+ handler is already logging to a file, this function can
+ potentially cause logging to a second file.</p>
+ <p>This function is useful as a shortcut during development
+ and testing, but must not be used in a production
+ system. See
+ section <seealso marker="logger_chapter">Logging</seealso>
+ in the Kernel User's Guide, and
+ the <seealso marker="logger"><c>logger(3)</c></seealso>
+ manual page for information about how to configure Logger
+ for live systems.</p>
<p><c>Request</c> is one of the following:</p>
<taglist>
<tag><c>{open, <anno>Filename</anno>}</c></tag>
@@ -297,9 +352,14 @@ ok</pre>
<p>Enables (<c><anno>Flag</anno> == true</c>) or disables
(<c><anno>Flag</anno> == false</c>) printout of standard events
to the terminal.</p>
- <p>This is done by adding or deleting the standard event handler
- for output to the terminal. Thus, calling this function overrides
- the value of the Kernel <c>error_logger</c> configuration parameter.</p>
+ <p>This is done by manipulating the Logger configuration. The
+ function is useful as a shortcut during development and
+ testing, but must not be used in a production system. See
+ section <seealso marker="logger_chapter">Logging</seealso>
+ in the Kernel User's Guide, and
+ the <seealso marker="logger"><c>logger(3)</c></seealso>
+ manual page for information about how to configure Logger
+ for live systems.</p>
</desc>
</func>
<func>
@@ -342,24 +402,27 @@ ok</pre>
<func>
<name name="warning_msg" arity="1"/>
<name name="warning_msg" arity="2"/>
- <fsummary>Send a standard warning event to the error logger.</fsummary>
+ <fsummary>Log a standard warning event.</fsummary>
<desc>
- <p>Sends a standard warning event to the error logger.
- The <c><anno>Format</anno></c> and <c><anno>Data</anno></c> arguments
- are the same as the arguments of
+ <p>Log a standard warning event. The <c><anno>Format</anno></c>
+ and <c><anno>Data</anno></c> arguments are the same as the
+ arguments of
<seealso marker="stdlib:io#format/2"><c>io:format/2</c></seealso>
- in STDLIB.
- The event is handled by the standard event handler. It is tagged
- as an error, warning, or info, see
+ in STDLIB.</p>
+ <p>Error logger forwards the event to Logger, including
+ metadata that allows backwards compatibility with legacy
+ error logger event handlers.</p>
+ <p>The event is handled by the default Logger handler. The log
+ level can be changed to error or info, see
<seealso marker="#warning_map/0"><c>warning_map/0</c></seealso>.</p>
- <warning>
- <p>If called with bad arguments, this function can crash
- the standard event handler, meaning no further events are
- logged. When in doubt, use <c>warning_report/1</c> instead.</p>
- </warning>
+ <p>These functions are kept for backwards compatibility and
+ must not be used by new code. Use the <seealso marker="logger#macros">
+ <c>?LOG_WARNING</c></seealso> macro or
+ <seealso marker="logger#warning-1"><c>logger:warning/1,2,3</c></seealso>
+ instead.</p>
<warning>
<p>If the Unicode translation modifier (<c>t</c>) is used in
- the format string, all error handlers must ensure that the
+ the format string, all event handlers must ensure that the
formatted output is correctly encoded for the I/O
device.</p>
</warning>
@@ -367,24 +430,43 @@ ok</pre>
</func>
<func>
<name name="warning_report" arity="1"/>
- <fsummary>Send a standard warning report event to the error logger.</fsummary>
+ <fsummary>Log a standard warning event.</fsummary>
<desc>
- <p>Sends a standard warning report event to the error logger.
- The event is handled by the standard event handler. It is
- tagged as an error, warning, or info, see
+ <p>Log a standard warning event. Error logger forwards the event
+ to Logger, including metadata that allows backwards
+ compatibility with legacy error logger event handlers.</p>
+ <p>The event is handled by the default Logger handler. The log
+ level can be changed to error or info, see
<seealso marker="#warning_map/0"><c>warning_map/0</c></seealso>.</p>
+ <p>This functions is kept for backwards compatibility and
+ must not be used by new code. Use the <seealso marker="logger#macros">
+ <c>?LOG_WARNING</c></seealso> macro or
+ <seealso marker="logger#warning-1"><c>logger:warning/1,2,3</c></seealso>
+ instead.</p>
</desc>
</func>
<func>
<name name="warning_report" arity="2"/>
- <fsummary>Send a user-defined warning report event to the error logger.</fsummary>
+ <fsummary>Log a user-defined warning event.</fsummary>
<desc>
- <p>Sends a user-defined warning report event to the error
- logger. An event handler to handle the event is supposed to
- have been added. The event is ignored by the standard event
- handler. It is tagged as an error, warning, or info,
- depending on the value of
+ <p>Log a user-defined warning event. Error logger forwards the
+ event to Logger, including metadata that allows backwards
+ compatibility with legacy error logger event handlers.</p>
+ <p>Error logger also adds a <c>domain</c> field with
+ value <c>[<anno>Type</anno>]</c> to this event's metadata,
+ causing the filters of the default Logger handler to discard
+ the event. A different Logger handler, or an error logger
+ event handler, must be added to handle this event.</p>
+ <p>The log level can be changed to error or info, see
<seealso marker="#warning_map/0"><c>warning_map/0</c></seealso>.</p>
+ <p>It is recommended that <c><anno>Report</anno></c> follows the same
+ structure as for
+ <seealso marker="#warning_report/1"><c>warning_report/1</c></seealso>.</p>
+ <p>This functions is kept for backwards compatibility and
+ must not be used by new code. Use the <seealso marker="logger#macros">
+ <c>?LOG_WARNING</c></seealso> macro or
+ <seealso marker="logger#warning-1"><c>logger:warning/1,2,3</c></seealso>
+ instead.</p>
</desc>
</func>
</funcs>
@@ -448,8 +530,9 @@ ok</pre>
<section>
<title>See Also</title>
<p><seealso marker="stdlib:gen_event"><c>gen_event(3)</c></seealso>,
- <seealso marker="stdlib:log_mf_h"><c>log_mf_h(3)</c></seealso>
- <seealso marker="kernel_app"><c>kernel(6)</c></seealso>
+ <seealso marker="kernel:logger"><c>logger(3)</c></seealso>,
+ <seealso marker="stdlib:log_mf_h"><c>log_mf_h(3)</c></seealso>,
+ <seealso marker="kernel_app"><c>kernel(6)</c></seealso>,
<seealso marker="sasl:sasl_app"><c>sasl(6)</c></seealso></p>
</section>
</erlref>
diff --git a/lib/kernel/doc/src/fascicules.xml b/lib/kernel/doc/src/fascicules.xml
deleted file mode 100644
index fadd37eefb..0000000000
--- a/lib/kernel/doc/src/fascicules.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml
index b674b3ca93..9acaf6b41e 100644
--- a/lib/kernel/doc/src/file.xml
+++ b/lib/kernel/doc/src/file.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,15 +33,18 @@
<description>
<p>This module provides an interface to the file system.</p>
- <p>On operating systems with thread support,
- file operations can be performed in threads of their own, allowing
- other Erlang processes to continue executing in parallel with
- the file operations. See command-line flag
- <c>+A</c> in <seealso marker="erts:erl"><c>erl(1)</c></seealso>.</p>
+ <warning>
+ <p>File operations are only guaranteed to appear atomic when going
+ through the same file server. A NIF or other OS process may observe
+ intermediate steps on certain operations on some operating systems,
+ eg. renaming an existing file on Windows, or
+ <seealso marker="#write_file_info/2"><c>write_file_info/2</c>
+ </seealso> on any OS at the time of writing.</p>
+ </warning>
<p>Regarding filename encoding, the Erlang VM can operate in
two modes. The current mode can be queried using function
- <seealso marker="#native_name_encoding"><c>native_name_encoding/0</c></seealso>.
+ <seealso marker="#native_name_encoding/0"><c>native_name_encoding/0</c></seealso>.
It returns <c>latin1</c> or <c>utf8</c>.</p>
<p>In <c>latin1</c> mode, the Erlang VM does not change the
@@ -59,7 +62,7 @@
terminal supports UTF-8, otherwise <c>latin1</c>. The default can
be overridden using <c>+fnl</c> (to force <c>latin1</c> mode)
or <c>+fnu</c> (to force <c>utf8</c> mode) when starting
- <seealso marker="erts:erl"><c>erts:erl</c></seealso>.</p>
+ <seealso marker="erts:erl"><c>erl</c></seealso>.</p>
<p>On operating systems with transparent naming, files can be
inconsistently named, for example, some files are encoded in UTF-8 while
@@ -81,6 +84,16 @@
<p>See also section <seealso marker="stdlib:unicode_usage#notes-about-raw-filenames">Notes About Raw Filenames</seealso> in the STDLIB User's Guide.</p>
+ <note><p>
+ File operations used to accept filenames containing
+ null characters (integer value zero). This caused
+ the name to be truncated and in some cases arguments
+ to primitive operations to be mixed up. Filenames
+ containing null characters inside the filename
+ are now <em>rejected</em> and will cause primitive
+ file operations fail.
+ </p></note>
+
</description>
<datatypes>
@@ -96,9 +109,21 @@
</datatype>
<datatype>
<name name="filename"/>
+ <desc>
+ <p>
+ See also the documentation of the
+ <seealso marker="#type-name_all"><c>name_all()</c></seealso> type.
+ </p>
+ </desc>
</datatype>
<datatype>
<name name="filename_all"/>
+ <desc>
+ <p>
+ See also the documentation of the
+ <seealso marker="#type-name_all"><c>name_all()</c></seealso> type.
+ </p>
+ </desc>
</datatype>
<datatype>
<name name="io_device"/>
@@ -112,21 +137,23 @@
<name name="name"/>
<desc>
<p>If VM is in Unicode filename mode, <c>string()</c> and <c>char()</c>
- are allowed to be &gt; 255.
+ are allowed to be &gt; 255. See also the documentation of the
+ <seealso marker="#type-name_all"><c>name_all()</c></seealso> type.
</p>
</desc>
</datatype>
<datatype>
<name name="name_all"/>
<desc>
- <p>If VM is in Unicode filename mode, <c>string()</c> and <c>char()</c>
+ <p>If VM is in Unicode filename mode, characters
are allowed to be &gt; 255.
<c><anno>RawFilename</anno></c> is a filename not subject to
Unicode translation,
meaning that it can contain characters not conforming to
the Unicode encoding expected from the file system
(that is, non-UTF-8 characters although the VM is started
- in Unicode filename mode).
+ in Unicode filename mode). Null characters (integer value zero)
+ are <em>not</em> allowed in filenames (not even at the end).
</p>
</desc>
</datatype>
@@ -954,8 +981,7 @@ f.txt: {person, "kalle", 25}.
</item>
<tag><c>eisdir</c></tag>
<item>
- <p>The named file is not a regular file. It can be a
- directory, a FIFO, or a device.</p>
+ <p>The named file is a directory.</p>
</item>
<tag><c>enotdir</c></tag>
<item>
@@ -1407,8 +1433,12 @@ f.txt: {person, "kalle", 25}.
which is 1970-01-01 00:00 UTC.</p></item>
</taglist>
<p>Default is <c>{time, local}</c>.</p>
- <p>If the option <c>raw</c> is set, the file server is not called
- and only information about local files is returned.</p>
+ <p>If the option <c>raw</c> is set, the file server is not called and
+ only information about local files is returned. Note that this will
+ break this module's atomicity guarantees as it can race with a
+ concurrent call to
+ <seealso marker="#write_file_info/2"><c>write_file_info/1,2</c>
+ </seealso></p>
<note>
<p>As file times are stored in POSIX time on most OS, it is faster to
query file information with option <c>posix</c>.</p>
@@ -1656,8 +1686,12 @@ f.txt: {person, "kalle", 25}.
except that if <c><anno>Name</anno></c> is a symbolic link, information
about the link is returned in the <c>file_info</c> record and
the <c>type</c> field of the record is set to <c>symlink</c>.</p>
- <p>If the option <c>raw</c> is set, the file server is not called
- and only information about local files is returned.</p>
+ <p>If the option <c>raw</c> is set, the file server is not called and
+ only information about local files is returned. Note that this will
+ break this module's atomicity guarantees as it can race with a
+ concurrent call to
+ <seealso marker="#write_file_info/2"><c>write_file_info/1,2</c>
+ </seealso></p>
<p>If <c><anno>Name</anno></c> is not a symbolic link, this function returns
the same result as <c>read_file_info/1</c>.
On platforms that do not support symbolic links, this function
@@ -1795,24 +1829,16 @@ f.txt: {person, "kalle", 25}.
<p>The file used must be opened using the <c>raw</c> flag, and the process
calling <c>sendfile</c> must be the controlling process of the socket.
See <seealso marker="gen_tcp#controlling_process-2"><c>gen_tcp:controlling_process/2</c></seealso>.</p>
- <p>If the OS used does not support <c>sendfile</c>, an Erlang fallback
- using
- <seealso marker="#read/2"><c>read/2</c></seealso> and
- <seealso marker="gen_tcp#send/2"><c>gen_tcp:send/2</c></seealso> is used.</p>
+ <p>If the OS used does not support non-blocking <c>sendfile</c>, an
+ Erlang fallback using <seealso marker="#read/2"><c>read/2</c></seealso>
+ and <seealso marker="gen_tcp#send/2"><c>gen_tcp:send/2</c></seealso> is
+ used.</p>
<p>The option list can contain the following options:</p>
<taglist>
<tag><c>chunk_size</c></tag>
<item><p>The chunk size used by the Erlang fallback to send
data. If using the fallback, set this to a value
that comfortably fits in the systems memory. Default is 20 MB.</p></item>
- <tag><c>use_threads</c></tag>
- <item><p>Instructs the emulator to use the <c>async</c> thread pool for the
- <c>sendfile</c> system call. This can be useful if the OS you are running
- on does not properly support non-blocking <c>sendfile</c> calls. Notice that
- using <c>async</c> threads potentially makes your system vulnerable to slow
- client attacks. If set to <c>true</c> and no <c>async</c> threads are available,
- the <c>sendfile</c> call returns <c>{error,einval}</c>.
- Introduced in Erlang/OTP 17.0. Default is <c>false</c>.</p></item>
</taglist>
</desc>
</func>
@@ -1825,7 +1851,7 @@ f.txt: {person, "kalle", 25}.
<p>The functions in the module <c>file</c> usually treat binaries
as raw filenames, that is, they are passed "as is" even when the
encoding of the binary does not agree with
- <seealso marker="#native_name_encoding"><c>native_name_encoding()</c></seealso>.
+ <seealso marker="#native_name_encoding/0"><c>native_name_encoding()</c></seealso>.
However, this function expects binaries to be encoded according to the
value returned by <c>native_name_encoding()</c>.</p>
<p>Typical error reasons are:</p>
@@ -2117,144 +2143,77 @@ f.txt: {person, "kalle", 25}.
<section>
<title>Performance</title>
- <p>Some operating system file operations, for example, a
- <c>sync/1</c> or <c>close/1</c> on a huge file, can block their
- calling thread for seconds. If this affects the emulator main
- thread, the response time is no longer in the order of
- milliseconds, depending on the definition of "soft" in soft
- real-time system.</p>
- <p>If the device driver thread pool is active, file operations are
- done through those threads instead, so the emulator can go on
- executing Erlang processes. Unfortunately, the time for serving a
- file operation increases because of the extra scheduling required
- from the operating system.</p>
- <p>If the device driver thread pool is disabled or of size 0, large
- file reads and writes are segmented into many smaller, which
- enable the emulator to serve other processes during the file
- operation. This has the same effect as when using the thread
- pool, but with larger overhead. Other file operations, for
- example, <c>sync/1</c> or <c>close/1</c> on a huge file, still are
- a problem.</p>
- <p>For increased performance, raw files are recommended. Raw files
- use the file system of the host machine of the node.</p>
+ <p>For increased performance, raw files are recommended.</p>
+ <p>A normal file is really a process so it can be used as an I/O
+ device (see <seealso marker="stdlib:io"><c>io</c></seealso>).
+ Therefore, when data is written to a normal file, the sending of the
+ data to the file process, copies all data that are not binaries. Opening
+ the file in binary mode and writing binaries is therefore recommended.
+ If the file is opened on another node, or if the file server runs as
+ slave to the file server of another node, also binaries are copied.</p>
<note>
- <p>
- For normal files (non-raw), the file server is used to find the files,
- and if the node is running its file server as slave to the file server
- of another node, and the other node runs on some other host machine,
- they can have different file systems.
- However, this is seldom a problem.</p>
+ <p>Raw files use the file system of the host machine of the node.
+ For normal files (non-raw), the file server is used to find the files,
+ and if the node is running its file server as slave to the file server
+ of another node, and the other node runs on some other host machine,
+ they can have different file systems.
+ However, this is seldom a problem.</p>
</note>
- <p>A normal file is really a process so it can be used as an I/O
- device (see
- <seealso marker="stdlib:io"><c>io</c></seealso>).
- Therefore, when data is written to a
- normal file, the sending of the data to the file process, copies
- all data that are not binaries. Opening the file in binary mode
- and writing binaries is therefore recommended. If the file is
- opened on another node, or if the file server runs as slave to
- the file server of another node, also binaries are copied.</p>
- <p>Caching data to reduce the number of file operations, or rather
- the number of calls to the file driver, generally increases
- performance. The following function writes 4 MBytes in 23
- seconds when tested:</p>
+ <p><seealso marker="#open/2"><c>open/2</c></seealso> can be given the
+ options <c>delayed_write</c> and <c>read_ahead</c> to turn on caching,
+ which will reduce the number of operating system calls and greatly
+ improve performance for small reads and writes. However, the overhead
+ won't disappear completely and it's best to keep the number of file
+ operations to a minimum. As a contrived example, the following function
+ writes 4MB in 2.5 seconds when tested:</p>
+
<code type="none"><![CDATA[
-create_file_slow(Name, N) when integer(N), N >= 0 ->
- {ok, FD} = file:open(Name, [raw, write, delayed_write, binary]),
- ok = create_file_slow(FD, 0, N),
- ok = ?FILE_MODULE:close(FD),
- ok.
-
-create_file_slow(FD, M, M) ->
+create_file_slow(Name) ->
+ {ok, Fd} = file:open(Name, [raw, write, delayed_write, binary]),
+ create_file_slow_1(Fd, 4 bsl 20),
+ file:close(Fd).
+
+create_file_slow_1(_Fd, 0) ->
ok;
-create_file_slow(FD, M, N) ->
- ok = file:write(FD, <<M:32/unsigned>>),
- create_file_slow(FD, M+1, N).]]></code>
+create_file_slow_1(Fd, M) ->
+ ok = file:write(Fd, <<0>>),
+ create_file_slow_1(Fd, M - 1).]]></code>
+
+ <p>The following functionally equivalent code writes 128 bytes per call
+ to <seealso marker="#write/2"><c>write/2</c></seealso> and so does the
+ same work in 0.08 seconds, which is roughly 30 times faster:</p>
- <p>The following, functionally equivalent, function collects 1024
- entries into a list of 128 32-byte binaries before each call to
- <seealso marker="#write/2"><c>write/2</c></seealso> and so
- does the same work in 0.52 seconds,
- which is 44 times faster:</p>
<code type="none"><![CDATA[
-create_file(Name, N) when integer(N), N >= 0 ->
- {ok, FD} = file:open(Name, [raw, write, delayed_write, binary]),
- ok = create_file(FD, 0, N),
- ok = ?FILE_MODULE:close(FD),
+create_file(Name) ->
+ {ok, Fd} = file:open(Name, [raw, write, delayed_write, binary]),
+ create_file_1(Fd, 4 bsl 20),
+ file:close(Fd),
ok.
-
-create_file(FD, M, M) ->
+
+create_file_1(_Fd, 0) ->
ok;
-create_file(FD, M, N) when M + 1024 =&lt; N ->
- create_file(FD, M, M + 1024, []),
- create_file(FD, M + 1024, N);
-create_file(FD, M, N) ->
- create_file(FD, M, N, []).
-
-create_file(FD, M, M, R) ->
- ok = file:write(FD, R);
-create_file(FD, M, N0, R) when M + 8 =&lt; N0 ->
- N1 = N0-1, N2 = N0-2, N3 = N0-3, N4 = N0-4,
- N5 = N0-5, N6 = N0-6, N7 = N0-7, N8 = N0-8,
- create_file(FD, M, N8,
- [<<N8:32/unsigned, N7:32/unsigned,
- N6:32/unsigned, N5:32/unsigned,
- N4:32/unsigned, N3:32/unsigned,
- N2:32/unsigned, N1:32/unsigned>> | R]);
-create_file(FD, M, N0, R) ->
- N1 = N0-1,
- create_file(FD, M, N1, [<<N1:32/unsigned>> | R]).]]></code>
+create_file_1(Fd, M) when M >= 128 ->
+ ok = file:write(Fd, <<0:(128)/unit:8>>),
+ create_file_1(Fd, M - 128);
+create_file_1(Fd, M) ->
+ ok = file:write(Fd, <<0:(M)/unit:8>>),
+ create_file_1(Fd, M - 1).]]></code>
- <note>
- <p>Trust only your own benchmarks. If the list length in
- <c>create_file/2</c> above is increased, it runs slightly
- faster, but consumes more memory and causes more memory
- fragmentation. How much this affects your application is
- something that this simple benchmark cannot predict.</p>
- <p>If the size of each binary is increased to 64 bytes, it
- also runs slightly faster, but the code is then twice as clumsy.
- In the current implementation, binaries larger than 64 bytes are
- stored in memory common to all processes and not copied when
- sent between processes, while these smaller binaries are stored
- on the process heap and copied when sent like any other term.</p>
- <p>So, with a binary size of 68 bytes, <c>create_file/2</c> runs
- 30 percent slower than with 64 bytes, and causes much more
- memory fragmentation. Notice that if the binaries were to be sent
- between processes (for example, a non-raw file), the results
- would probably be completely different.</p>
- </note>
- <p>A raw file is really a port. When writing data to a port, it is
- efficient to write a list of binaries. It is not needed to
- flatten a deep list before writing. On Unix hosts, scatter output,
- which writes a set of buffers in one operation, is used when
- possible. In this way <c>write(FD, [Bin1, Bin2 | Bin3])</c>
- writes the contents of the binaries without copying the data
- at all, except for perhaps deep down in the operating system
- kernel.</p>
- <p>For raw files, <c>pwrite/2</c> and <c>pread/2</c> are
- efficiently implemented. The file driver is called only once for
- the whole operation, and the list iteration is done in the file
- driver.</p>
- <p>The options <c>delayed_write</c> and <c>read_ahead</c> to
- <seealso marker="#open/2"><c>open/2</c></seealso>
- make the file driver cache data to reduce
- the number of operating system calls. The function
- <c>create_file/2</c> in the recent example takes 60 seconds
- without option <c>delayed_write</c>, which is 2.6
- times slower.</p>
- <p>As a bad example, <c>create_file_slow/2</c>
- without options <c>raw</c>, <c>binary</c>, and <c>delayed_write</c>,
- meaning it calls <c>open(Name, [write])</c>, needs
- 1 min 20 seconds for the job, which is 3.5 times slower than
- the first example, and 150 times slower than the optimized
- <c>create_file/2</c>.</p>
- <warning>
- <p>If an error occurs when accessing an open file with module
- <seealso marker="stdlib:io"><c>io</c></seealso>,
- the process handling the file exits. The dead
- file process can hang if a process tries to access it later.
- This will be fixed in a future release.</p>
- </warning>
+ <p>When writing data it's generally more efficient to write a list of
+ binaries rather than a list of integers. It is not needed to
+ flatten a deep list before writing. On Unix hosts, scatter output,
+ which writes a set of buffers in one operation, is used when
+ possible. In this way <c>write(FD, [Bin1, Bin2 | Bin3])</c>
+ writes the contents of the binaries without copying the data
+ at all, except for perhaps deep down in the operating system
+ kernel.</p>
+ <warning>
+ <p>If an error occurs when accessing an open file with module
+ <seealso marker="stdlib:io"><c>io</c></seealso>, the process
+ handling the file exits. The dead file process can hang if a process
+ tries to access it later. This will be fixed in a future release.
+ </p>
+ </warning>
</section>
<section>
diff --git a/lib/kernel/doc/src/gen_sctp.xml b/lib/kernel/doc/src/gen_sctp.xml
index 737800c6b1..1e08b25f66 100644
--- a/lib/kernel/doc/src/gen_sctp.xml
+++ b/lib/kernel/doc/src/gen_sctp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2007</year><year>2016</year>
+ <year>2007</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -331,6 +331,37 @@ connect(Socket, Ip, Port>,
with <anno>SockType</anno> <c>seqpacket</c>, and with reasonably large
<seealso marker="inet#option-sndbuf">kernel</seealso> and driver
<seealso marker="inet#option-buffer">buffers</seealso>.</p>
+ <p>
+ If the socket is in
+ <seealso marker="#option-active">passive</seealso>
+ mode data can be received through the
+ <seealso marker="#recv/1"><c>recv/1,2</c></seealso>
+ calls.
+ </p>
+ <p>
+ If the socket is in
+ <seealso marker="#option-active">active</seealso>
+ mode data received data is delivered to the controlling process
+ as messages:
+ </p>
+ <code type="none">
+{sctp, <anno>Socket</anno>, FromIP, FromPort, {AncData, Data}}
+ </code>
+ <p>
+ See
+ <seealso marker="#recv/1"><c>recv/1,2</c></seealso>
+ for a description of the message fields.
+ </p>
+ <note>
+ <p>
+ This message format unfortunately differs slightly from the
+ <seealso marker="gen_udp#open/1"><c>gen_udp</c></seealso>
+ message format with ancillary data,
+ and from the
+ <seealso marker="#recv/1"><c>recv/1,2</c></seealso>
+ return tuple format.
+ </p>
+ </note>
</desc>
</func>
@@ -380,6 +411,19 @@ connect(Socket, Ip, Port>,
socket option
<seealso marker="#option-sctp_get_peer_addr_info"><c>sctp_get_peer_addr_info</c></seealso>,
but this does still not produce the stream number).</p>
+ <p>
+ <c><anno>AncData</anno></c> may also contain
+ <seealso marker="inet#type-ancillary_data">
+ ancillary data
+ </seealso>
+ from the socket
+ <seealso marker="#type-option">options</seealso>
+ <seealso marker="inet#option-recvtos"><c>recvtos</c></seealso>,
+ <seealso marker="inet#option-recvtclass"><c>recvtclass</c></seealso>
+ or
+ <seealso marker="inet#option-recvttl"><c>recvttl</c></seealso>,
+ if that is supported by the platform for the socket.
+ </p>
<p>The <c><anno>Data</anno></c> received can be a <c>binary()</c>
or a <c>list()</c> of bytes (integers in the range 0 through 255)
depending on the socket mode, or an SCTP event.</p>
@@ -544,12 +588,25 @@ connect(Socket, Ip, Port>,
<seealso marker="#recv/1"><c>recv</c></seealso> call
to retrieve the available data from the socket.</p>
</item>
+ <item>
+ <p>
+ If <c>true|once|N</c> (active modes)
+ received data or events are sent to the owning process.
+ See <seealso marker="#open/0"><c>open/0..2</c></seealso>
+ for the message format.
+ </p>
+ </item>
<item>
- <p>If <c>true</c> (full active mode), the pending data or events are
- sent to the owning process.</p>
- <p>Notice that this can cause the message queue to overflow,
- as there is no way to throttle the sender in this case
- (no flow control).</p>
+ <p>
+ If <c>true</c> (full active mode) there is no flow control.
+ </p>
+ <note>
+ <p>
+ Note that this can cause the message queue to overflow
+ causing for example the virtual machine
+ to run out of memory and crash.
+ </p>
+ </note>
</item>
<item>
<p>If <c>once</c>, only one message is automatically placed
diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml
index 070782e1f3..24d63693fd 100644
--- a/lib/kernel/doc/src/gen_tcp.xml
+++ b/lib/kernel/doc/src/gen_tcp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2017</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -51,6 +51,7 @@ server() ->
{ok, Sock} = gen_tcp:accept(LSock),
{ok, Bin} = do_recv(Sock, []),
ok = gen_tcp:close(Sock),
+ ok = gen_tcp:close(LSock),
Bin.
do_recv(Sock, Bs) ->
@@ -69,6 +70,32 @@ do_recv(Sock, Bs) ->
<name name="option"/>
</datatype>
<datatype>
+ <name name="pktoptions_value"/>
+ <desc>
+ <p>
+ If the platform implements the IPv4 option
+ <c>IP_PKTOPTIONS</c>, or the IPv6 option
+ <c>IPV6_PKTOPTIONS</c> or <c>IPV6_2292PKTOPTIONS</c> for the socket
+ this value is returned from
+ <seealso marker="inet#getopts/2"><c>inet:getopts/2</c></seealso>
+ when called with the option name
+ <seealso marker="#type-option_name"><c>pktoptions</c></seealso>.
+ </p>
+ <note>
+ <p>
+ This option appears to be VERY Linux specific,
+ and its existence in future Linux kernel versions
+ is also worrying since the option is part of RFC 2292
+ which is since long (2003) obsoleted by RFC 3542
+ that <em>explicitly</em> removes this possibility to get
+ packet information from a stream socket.
+ For comparision: it has existed in FreeBSD but is now removed,
+ at least since FreeBSD 10.
+ </p>
+ </note>
+ </desc>
+ </datatype>
+ <datatype>
<name name="option_name"/>
</datatype>
<datatype>
@@ -309,9 +336,9 @@ do_recv(Sock, Bs) ->
<seealso marker="inet#setopts/2"><c>inet:setopts/2</c></seealso>.
</p></item>
</taglist>
- <p>The returned socket <c><anno>ListenSocket</anno></c> can only be
- used in calls to
- <seealso marker="#accept/1"><c>accept/1,2</c></seealso>.</p>
+ <p>The returned socket <c><anno>ListenSocket</anno></c> should be used
+ in calls to <seealso marker="#accept/1"><c>accept/1,2</c></seealso> to
+ accept incoming connection requests.</p>
<note>
<p>The default values for options specified to <c>listen</c> can
be affected by the Kernel configuration parameter
diff --git a/lib/kernel/doc/src/gen_udp.xml b/lib/kernel/doc/src/gen_udp.xml
index f79566ef71..840ca3c188 100644
--- a/lib/kernel/doc/src/gen_udp.xml
+++ b/lib/kernel/doc/src/gen_udp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -147,7 +147,21 @@
at the opened port, if the socket is in an active mode, the packets
are delivered as messages to the controlling process:</p>
<code type="none">
-{udp, Socket, IP, InPortNo, Packet}</code>
+{udp, Socket, IP, InPortNo, Packet} % Without ancillary data
+{udp, Socket, IP, InPortNo, AncData, Packet} % With ancillary data
+ </code>
+ <p>
+ The message contains an <c>AncData</c> field
+ if any of the socket
+ <seealso marker="#type-option">options</seealso>
+ <seealso marker="inet#option-recvtos"><c>recvtos</c></seealso>,
+ <seealso marker="inet#option-recvtclass"><c>recvtclass</c></seealso>
+ or
+ <seealso marker="inet#option-recvttl"><c>recvttl</c></seealso>
+ are active, otherwise it does not.
+ </p>
+ <p>
+ </p>
<p>If the socket is not in an active mode, data can be
retrieved through the
<seealso marker="#recv/2"><c>recv/2,3</c></seealso> calls.
@@ -179,9 +193,22 @@
<name name="recv" arity="3"/>
<fsummary>Receive a packet from a passive socket.</fsummary>
<desc>
- <p>Receives a packet from a socket in passive mode. Optional parameter
+ <p>
+ Receives a packet from a socket in passive mode. Optional parameter
<c><anno>Timeout</anno></c> specifies a time-out in milliseconds.
- Defaults to <c>infinity</c>.</p>
+ Defaults to <c>infinity</c>.
+ </p>
+ <p>
+ If any of the socket
+ <seealso marker="#type-option">options</seealso>
+ <seealso marker="inet#option-recvtos"><c>recvtos</c></seealso>,
+ <seealso marker="inet#option-recvtclass"><c>recvtclass</c></seealso>
+ or
+ <seealso marker="inet#option-recvttl"><c>recvttl</c></seealso>
+ are active, the <c><anno>RecvData</anno></c> tuple contains an
+ <c><anno>AncData</anno></c> field,
+ otherwise it does not.
+ </p>
</desc>
</func>
diff --git a/lib/kernel/doc/src/heart.xml b/lib/kernel/doc/src/heart.xml
index 5b5b71e521..ad1a2ffeb9 100644
--- a/lib/kernel/doc/src/heart.xml
+++ b/lib/kernel/doc/src/heart.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -59,8 +59,9 @@
<pre>
% <input>erl -heart -env HEART_BEAT_TIMEOUT 30 ...</input></pre>
<p>The value (in seconds) must be in the range 10 &lt; X &lt;= 65535.</p>
- <p>Notice that if the system clock is adjusted with
- more than <c>HEART_BEAT_TIMEOUT</c> seconds, <c>heart</c>
+ <p>When running on OSs lacking support for monotonic time,
+ <c>heart</c> is susceptible to system clock adjustments of more than
+ <c>HEART_BEAT_TIMEOUT</c> seconds. When this happens, <c>heart</c>
times out and tries to reboot the system. This can occur, for
example, if the system clock is adjusted automatically by use of the
Network Time Protocol (NTP).</p>
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index b71e8a1e5d..ed775d67eb 100644
--- a/lib/kernel/doc/src/inet.xml
+++ b/lib/kernel/doc/src/inet.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2017</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -177,6 +177,27 @@ fe80::204:acff:fe17:bf38
</desc>
</datatype>
<datatype>
+ <name name="ancillary_data"/>
+ <desc>
+ <p>
+ Ancillary data received with the data packet
+ or read with the socket option
+ <seealso marker="gen_tcp#type-pktoptions_value">
+ <c>pktoptions</c>
+ </seealso>
+ from a TCP socket.
+ </p>
+ <p>
+ The value(s) correspond to the currently active socket
+ <seealso marker="#type-socket_setopt">options</seealso>
+ <seealso marker="inet#option-recvtos"><c>recvtos</c></seealso>,
+ <seealso marker="inet#option-recvtclass"><c>recvtclass</c></seealso>
+ and
+ <seealso marker="inet#option-recvttl"><c>recvttl</c></seealso>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
<name name="posix"/>
<desc>
<p>An atom that is named from the POSIX error codes used in Unix,
@@ -197,6 +218,9 @@ fe80::204:acff:fe17:bf38
<datatype>
<name name="address_family"/>
</datatype>
+ <datatype>
+ <name name="socket_protocol"/>
+ </datatype>
</datatypes>
<funcs>
@@ -222,11 +246,18 @@ fe80::204:acff:fe17:bf38
<name name="get_rc" arity="0"/>
<fsummary>Return a list of IP configuration parameters.</fsummary>
<desc>
- <p>Returns the state of the <c>Inet</c> configuration database in
+ <p>
+ Returns the state of the <c>Inet</c> configuration database in
form of a list of recorded configuration parameters. For more
information, see <seealso marker="erts:inet_cfg">ERTS User's Guide:
Inet Configuration</seealso>.
- Only parameters with other than default values are returned.</p>
+ </p>
+ <p>
+ Only actual parameters with other than default values
+ are returned, for example not directives that specify
+ other sources for configuration parameters nor
+ directives that clear parameters.
+ </p>
</desc>
</func>
@@ -267,9 +298,7 @@ fe80::204:acff:fe17:bf38
<p>Returns a <c>hostent</c> record for the host with the specified
hostname.</p>
<p>If resolver option <c>inet6</c> is <c>true</c>,
- an IPv6 address is looked up. If that fails,
- the IPv4 address is looked up and returned on
- IPv6-mapped IPv4 format.</p>
+ an IPv6 address is looked up.</p>
</desc>
</func>
@@ -336,7 +365,11 @@ fe80::204:acff:fe17:bf38
<desc>
<p>Gets one or more options for a socket. For a list of available
options, see
- <seealso marker="#setopts/2"><c>setopts/2</c></seealso>.</p>
+ <seealso marker="#setopts/2"><c>setopts/2</c></seealso>.
+ See also the description for the type
+ <seealso marker="gen_tcp#type-pktoptions_value">
+ <c>gen_tcp:pktoptions_value()</c>
+ </seealso>.</p>
<p>The number of elements in the returned
<c><anno>OptionValues</anno></c>
list does not necessarily correspond to the number of options
@@ -352,7 +385,7 @@ fe80::204:acff:fe17:bf38
socket options not (explicitly) supported by the emulator. The
use of raw socket options makes the code non-portable, but
allows the Erlang programmer to take advantage of unusual features
- present on the current platform.</p>
+ present on a particular platform.</p>
<p><c>RawOptReq</c> consists of tag <c>raw</c> followed
by the protocol level, the option number, and either a binary
or the size, in bytes, of the
@@ -454,6 +487,61 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
+ <name name="i" arity="0" />
+ <name name="i" arity="1" />
+ <name name="i" arity="2" />
+ <fsummary>Displays information and statistics about sockets on the terminal</fsummary>
+ <desc>
+ <p>
+ Lists all TCP, UDP and SCTP sockets, including those that the Erlang runtime system uses as well as
+ those created by the application.
+ </p>
+ <p>
+ The following options are available:
+ </p>
+
+ <taglist>
+ <tag><c>port</c></tag>
+ <item>
+ <p>The internal index of the port.</p>
+ </item>
+ <tag><c>module</c></tag>
+ <item>
+ <p>The callback module of the socket.</p>
+ </item>
+ <tag><c>recv</c></tag>
+ <item>
+ <p>Number of bytes received by the socket.</p>
+ </item>
+ <tag><c>sent</c></tag>
+ <item>
+ <p>Number of bytes sent from the socket.</p>
+ </item>
+ <tag><c>owner</c></tag>
+ <item>
+ <p>The socket owner process.</p>
+ </item>
+ <tag><c>local_address</c></tag>
+ <item>
+ <p>The local address of the socket.</p>
+ </item>
+ <tag><c>foreign_address</c></tag>
+ <item>
+ <p>The address and port of the other end of the connection.</p>
+ </item>
+ <tag><c>state</c></tag>
+ <item>
+ <p>The connection state.</p>
+ </item>
+ <tag><c>type</c></tag>
+ <item>
+ <p>STREAM or DGRAM or SEQPACKET.</p>
+ </item>
+ </taglist>
+ </desc>
+ </func>
+
+ <func>
<name name="ntoa" arity="1" />
<fsummary>Convert IPv6/IPV4 address to ASCII.</fsummary>
<desc>
@@ -517,6 +605,19 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
+ <name name="ipv4_mapped_ipv6_address" arity="1" />
+ <fsummary>Convert to and from IPv4-mapped IPv6 address.</fsummary>
+ <desc>
+ <p>
+ Convert an IPv4 address to an IPv4-mapped IPv6 address
+ or the reverse. When converting from an IPv6 address
+ all but the 2 low words are ignored so this function also
+ works on some other types of addresses than IPv4-mapped.
+ </p>
+ </desc>
+ </func>
+
+ <func>
<name name="parse_strict_address" arity="1" />
<fsummary>Parse an IPv4 or IPv6 address strict.</fsummary>
<desc>
@@ -658,22 +759,23 @@ get_tcpi_sacked(Sock) ->
</item>
<tag><c>{buffer, Size}</c></tag>
<item>
- <p>The size of the user-level software buffer used by
- the driver.
- Not to be confused with options <c>sndbuf</c>
+ <p>The size of the user-level buffer used by
+ the driver. Not to be confused with options <c>sndbuf</c>
and <c>recbuf</c>, which correspond to the
- Kernel socket buffers. It is recommended
- to have <c>val(buffer) &gt;= max(val(sndbuf),val(recbuf))</c> to
+ Kernel socket buffers. For TCP it is recommended
+ to have <c>val(buffer) &gt;= val(recbuf)</c> to
avoid performance issues because of unnecessary copying.
+ For UDP the same recommendation applies, but the max should
+ not be larger than the MTU of the network path.
<c>val(buffer)</c> is automatically set to the above
- maximum when values <c>sndbuf</c> or <c>recbuf</c> are set.
- However, as the sizes set for <c>sndbuf</c> and <c>recbuf</c>
+ maximum when <c>recbuf</c> is set.
+ However, as the size set for <c>recbuf</c>
usually become larger, you are encouraged to use
<seealso marker="#getopts/2"><c>getopts/2</c></seealso>
to analyze the behavior of your operating system.</p>
<p>Note that this is also the maximum amount of data that can be
- received from a single recv call. If you are using higher than
- normal MTU consider setting buffer higher.</p>
+ received from a single recv call. If you are using higher than
+ normal MTU consider setting buffer higher.</p>
</item>
<tag><c>{delay_send, Boolean}</c></tag>
<item>
@@ -1038,6 +1140,100 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp</code>
the socket. You are encouraged to use
<seealso marker="#getopts/2"><c>getopts/2</c></seealso>
to retrieve the size set by your operating system.</p>
+ <marker id="option-recvtclass"></marker>
+ </item>
+ <tag><c>{recvtclass, Boolean}</c></tag>
+ <item>
+ <p>
+ If set to <c>true</c> activates returning the received
+ <c>TCLASS</c> value on platforms that implements
+ the protocol <c>IPPROTO_IPV6</c>
+ option <c>IPV6_RECVTCLASS</c> or <c>IPV6_2292RECVTCLASS</c>
+ for the socket.
+ The value is returned as a <c>{tclass,TCLASS}</c> tuple
+ regardless of if the platform returns an <c>IPV6_TCLASS</c>
+ or an <c>IPV6_RECVTCLASS</c> CMSG value.
+ </p>
+ <p>
+ For packet oriented sockets that supports receiving
+ ancillary data with the payload data
+ (<c>gen_udp</c> and <c>gen_sctp</c>),
+ the <c>TCLASS</c> value is returned
+ in an extended return tuple contained in an
+ <seealso marker="inet#type-ancillary_data">
+ ancillary data
+ </seealso>
+ list.
+ For stream oriented sockets (<c>gen_tcp</c>)
+ the only way to get the <c>TCLASS</c>
+ value is if the platform supports the
+ <seealso marker="gen_tcp#type-pktoptions_value">
+ <c>pktoptions</c>
+ </seealso>
+ option.
+ </p>
+ <marker id="option-recvtos"></marker>
+ </item>
+ <tag><c>{recvtos, Boolean}</c></tag>
+ <item>
+ <p>
+ If set to <c>true</c> activates returning the received
+ <c>TOS</c> value on platforms that implements
+ the protocol <c>IPPROTO_IP</c> option <c>IP_RECVTOS</c>
+ for the socket.
+ The value is returned as a <c>{tos,TOS}</c> tuple
+ regardless of if the platform returns an <c>IP_TOS</c>
+ or an <c>IP_RECVTOS</c> CMSG value.
+ </p>
+ <p>
+ For packet oriented sockets that supports receiving
+ ancillary data with the payload data
+ (<c>gen_udp</c> and <c>gen_sctp</c>),
+ the <c>TOS</c> value is returned
+ in an extended return tuple contained in an
+ <seealso marker="inet#type-ancillary_data">
+ ancillary data
+ </seealso>
+ list.
+ For stream oriented sockets (<c>gen_tcp</c>)
+ the only way to get the <c>TOS</c>
+ value is if the platform supports the
+ <seealso marker="gen_tcp#type-pktoptions_value">
+ <c>pktoptions</c>
+ </seealso>
+ option.
+ </p>
+ <marker id="option-recvttl"></marker>
+ </item>
+ <tag><c>{recvttl, Boolean}</c></tag>
+ <item>
+ <p>
+ If set to <c>true</c> activates returning the received
+ <c>TTL</c> value on platforms that implements
+ the protocol <c>IPPROTO_IP</c> option <c>IP_RECVTTL</c>
+ for the socket.
+ The value is returned as a <c>{ttl,TTL}</c> tuple
+ regardless of if the platform returns an <c>IP_TTL</c>
+ or an <c>IP_RECVTTL</c> CMSG value.
+ </p>
+ <p>
+ For packet oriented sockets that supports receiving
+ ancillary data with the payload data
+ (<c>gen_udp</c> and <c>gen_sctp</c>),
+ the <c>TTL</c> value is returned
+ in an extended return tuple contained in an
+ <seealso marker="inet#type-ancillary_data">
+ ancillary data
+ </seealso>
+ list.
+ For stream oriented sockets (<c>gen_tcp</c>)
+ the only way to get the <c>TTL</c>
+ value is if the platform supports the
+ <seealso marker="gen_tcp#type-pktoptions_value">
+ <c>pktoptions</c>
+ </seealso>
+ option.
+ </p>
</item>
<tag><c>{reuseaddr, Boolean}</c></tag>
<item>
@@ -1073,7 +1269,7 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp</code>
<seealso marker="gen_tcp#recv/2"><c>gen_tcp:recv/2</c></seealso>
gets <c>{error, closed}</c>. In active
mode, the controlling process receives a
- <c>{tcp_close, Socket}</c> message, indicating that the
+ <c>{tcp_closed, Socket}</c> message, indicating that the
peer has closed the connection.</p>
<p>Setting this option to <c>true</c> allows you to
distinguish between a connection that was closed normally,
@@ -1207,7 +1403,7 @@ inet:setopts(Sock,[{raw,6,8,<<30:32/native>>}]),]]></code>
For one-to-many style sockets, the special value <c>0</c>
is defined to mean that the returned addresses must be
without any particular association.
- How different SCTP implementations interprets this varies somewhat.
+ How different SCTP implementations interpret this varies somewhat.
</p>
</desc>
</func>
diff --git a/lib/kernel/doc/src/inet_res.xml b/lib/kernel/doc/src/inet_res.xml
index 4ada4203c0..351d86a93a 100644
--- a/lib/kernel/doc/src/inet_res.xml
+++ b/lib/kernel/doc/src/inet_res.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2009</year><year>2015</year>
+ <year>2009</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -130,7 +130,7 @@ dns_header() = DnsHeader
inet_dns:header(DnsHeader) ->
[ {id, integer()}
| {qr, boolean()}
- | {opcode, 'query' | iquery | status | integer()}
+ | {opcode, query | iquery | status | integer()}
| {aa, boolean()}
| {tc, boolean()}
| {rd, boolean()}
@@ -230,9 +230,7 @@ inet_dns:record_type(_) -> undefined.</pre>
<seealso marker="#getbyname/2"><c>getbyname/2,3</c></seealso>.
</p>
<p>If resolver option <c>inet6</c> is <c>true</c>,
- an IPv6 address is looked up. If that fails,
- the IPv4 address is looked up and returned on
- IPv6-mapped IPv4 format.</p>
+ an IPv6 address is looked up.</p>
</desc>
</func>
diff --git a/lib/kernel/doc/src/introduction_chapter.xml b/lib/kernel/doc/src/introduction_chapter.xml
new file mode 100644
index 0000000000..d02b1a2ee5
--- /dev/null
+++ b/lib/kernel/doc/src/introduction_chapter.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2017</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>Introduction</title>
+ <prepared></prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev></rev>
+ <file>introduction.xml</file>
+ </header>
+
+ <section>
+ <title>Scope</title>
+ <p>The Kernel application has all the code necessary to run
+ the Erlang runtime system: file servers, code servers,
+ and so on.</p>
+ <p>The Kernel application is the first application started. It is
+ mandatory in the sense that the minimal system based on
+ Erlang/OTP consists of Kernel and STDLIB. Kernel
+ contains the following functional areas:</p>
+ <list type="bulleted">
+ <item>Start, stop, supervision, configuration, and distribution of applications</item>
+ <item>Code loading</item>
+ <item>Logging</item>
+ <item>Global name service</item>
+ <item>Supervision of Erlang/OTP</item>
+ <item>Communication with sockets</item>
+ <item>Operating system interface</item>
+ </list>
+ </section>
+
+ <section>
+ <title>Prerequisites</title>
+ <p>It is assumed that the reader is familiar with the Erlang programming
+ language.</p>
+ </section>
+</chapter>
+
+
diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml
index e5ac031539..15dbdb47dc 100644
--- a/lib/kernel/doc/src/kernel_app.xml
+++ b/lib/kernel/doc/src/kernel_app.xml
@@ -4,7 +4,7 @@
<appref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -42,7 +42,6 @@
<item>Start, stop, supervision, configuration, and distribution of applications</item>
<item>Code loading</item>
<item>Logging</item>
- <item>Error logging</item>
<item>Global name service</item>
<item>Supervision of Erlang/OTP</item>
<item>Communication with sockets</item>
@@ -51,10 +50,13 @@
</description>
<section>
- <title>Error Logger Event Handlers</title>
- <p>Two standard error logger event handlers are defined in
- the Kernel application. These are described in
- <seealso marker="error_logger"><c>error_logger(3)</c></seealso>.</p>
+ <title>Logger Handlers</title>
+ <p>Two standard logger handlers are defined in
+ the Kernel application. These are described in the
+ <seealso marker="logger_chapter">Kernel User's Guide</seealso>,
+ and in the <seealso marker="logger_std_h"><c>logger_std_h(3)</c></seealso>
+ and <seealso marker="logger_disk_log_h"><c>logger_disk_log_h(3)</c>
+ </seealso> manual pages.</p>
</section>
<section>
@@ -113,26 +115,12 @@
</section>
<section>
+ <marker id="configuration"/>
<title>Configuration</title>
<p>The following configuration parameters are defined for the Kernel
application. For more information about configuration parameters,
see file <seealso marker="app"><c>app(4)</c></seealso>.</p>
<taglist>
- <tag><c>browser_cmd = string() | {M,F,A}</c></tag>
- <item>
- <p>When pressing the <em>Help</em> button in a tool such as Debugger,
- the help text (an HTML file <c>File</c>) is by default
- displayed in a Netscape browser, which is required to be
- operational. This parameter can be used to change the command for
- how to display the help text if another browser than Netscape
- is preferred, or if another platform than Unix or Windows is
- used.</p>
- <p>If set to a string <c>Command</c>, the command
- <c>"Command File"</c> is evaluated using
- <seealso marker="os#cmd/1"><c>os:cmd/1</c></seealso>.</p>
- <p>If set to a module-function-args tuple, <c>{M,F,A}</c>,
- the call <c>apply(M,F,[File|A])</c> is evaluated.</p>
- </item>
<tag><c>distributed = [Distrib]</c></tag>
<item>
<p>Specifies which applications that are distributed and on which
@@ -176,65 +164,74 @@
<p>Permissions are described in
<seealso marker="application#permit/2"><c>application:permit/2</c></seealso>.</p>
</item>
- <tag><c>error_logger = Value</c></tag>
- <item>
- <p><c>Value</c> is one of:</p>
- <taglist>
- <tag><c>tty</c></tag>
- <item><p>Installs the standard event handler, which prints error
- reports to <c>stdio</c>. This is the default option.</p></item>
- <tag><c>{file, FileName}</c></tag>
- <item><p>Installs the standard event handler, which prints error
- reports to file <c>FileName</c>, where <c>FileName</c>
- is a string. The file is opened with encoding UTF-8.</p></item>
- <tag><c>false</c></tag>
- <item>
- <p>No standard event handler is installed, but
- the initial, primitive event handler is kept, printing
- raw event messages to <c>tty</c>.</p>
- </item>
- <tag><c>silent</c></tag>
- <item>
- <p>Error logging is turned off.</p>
- </item>
- </taglist>
+ <tag><marker id="logger"/><c>logger = [Config]</c></tag>
+ <item>
+ <p>Specifies the configuration
+ for <seealso marker="logger">Logger</seealso>, except the
+ primary log level, which is specified
+ with <seealso marker="#logger_level"><c>logger_level</c></seealso>,
+ and the compatibility
+ with <seealso marker="sasl:error_logging">SASL Error
+ Logging</seealso>, which is specified
+ with <seealso marker="#logger_sasl_compatible">
+ <c>logger_sasl_compatible</c></seealso>.</p>
+ <p>The <c>logger </c> parameter is described in
+ section <seealso marker="logger_chapter#logger_parameter">
+ Logging</seealso> in the Kernel User's Guide.</p>
+ </item>
+ <tag><marker id="logger_level"/><c>logger_level = Level</c></tag>
+ <item>
+ <p>Specifies the primary log level for Logger. Log events with
+ the same, or a more severe level, pass through the primary
+ log level check. See
+ section <seealso marker="logger_chapter">Logging</seealso>
+ in the Kernel User's Guide for more information about Logger
+ and log levels.</p>
+ <p><c>Level = emergency | alert | critical | error | warning |
+ notice | info | debug | all | none</c></p>
+ <p>To change the primary log level at runtime, use
+ <seealso marker="logger#set_primary_config/2">
+ <c>logger:set_primary_config(level, Level)</c></seealso>.</p>
+ <p>Defaults to <c>notice</c>.</p>
+ </item>
+ <tag><marker id="logger_sasl_compatible"/>
+ <c>logger_sasl_compatible = true | false</c></tag>
+ <item>
+ <p>Specifies if Logger behaves backwards compatible with the
+ SASL error logging functionality from releases prior to
+ Erlang/OTP 21.0.</p>
+ <p>If this parameter is set to <c>true</c>, the default Logger
+ handler does not log any progress-, crash-, or supervisor
+ reports. If the SASL application is then started, it adds a
+ Logger handler named <c>sasl</c>, which logs these events
+ according to values of the SASL configuration
+ parameter <c>sasl_error_logger</c>
+ and <c>sasl_errlog_type</c>.</p>
+ <p>See section
+ <seealso marker="sasl:sasl_app#deprecated_error_logger_config">
+ Deprecated Error Logger Event Handlers and
+ Configuration</seealso> in the sasl(6) manual page for
+ information about the SASL configuration parameters.</p>
+ <p>See section <seealso marker="sasl:error_logging">SASL Error
+ Logging</seealso> in the SASL User's Guide, and
+ section <seealso marker="logger_chapter#compatibility">Backwards
+ Compatibility with error_logger</seealso> in the Kernel
+ User's Guide for information about the SASL error logging
+ functionality, and how Logger can be backwards compatible
+ with this.</p>
+ <p>Defaults to <c>false</c>.</p>
+ <note>
+ <p>If this parameter is set to <c>true</c>,
+ <c>sasl_errlog_type</c> indicates that progress reports
+ shall be logged, and the configured primary log level
+ is <c>notice</c> or more severe, then SASL automatically
+ sets the primary log level to <c>info</c>. That is, this
+ setting can potentially overwrite the value of the Kernel
+ configuration parameter <c>logger_level</c>. This is to
+ allow progress reports, which have log level <c>info</c>,
+ to be forwarded to the handlers.</p>
+ </note>
</item>
- <tag><c>error_logger_format_depth = Depth</c></tag>
- <item>
- <marker id="error_logger_format_depth"></marker>
- <p>Can be used to limit the size of the
- formatted output from the error logger event handlers.</p>
-
- <note><p>This configuration parameter was introduced in OTP 18.1
- and is experimental. Based on user feedback, it
- can be changed or improved in future releases, for example,
- to gain better control over how to limit the size of the
- formatted output. We have no plans to remove this
- new feature entirely, unless it turns out to be
- useless.</p></note>
-
- <p><c>Depth</c> is a positive integer representing the maximum
- depth to which terms are printed by the error logger event
- handlers included in OTP. This
- configuration parameter is used by the two event handlers
- defined by the Kernel application and the two event
- handlers in the SASL application.
- (If you have implemented your own error handlers, this configuration
- parameter has no effect on them.)</p>
-
- <p><c>Depth</c> is used as follows: Format strings
- passed to the event handlers are rewritten.
- The format controls <c>~p</c> and <c>~w</c> are replaced with
- <c>~P</c> and <c>~W</c>, respectively, and <c>Depth</c> is
- used as the depth parameter. For details, see
- <seealso marker="stdlib:io#format/2"><c>io:format/2</c></seealso>
- in STDLIB.</p>
-
- <note><p>A reasonable starting value for <c>Depth</c> is
- <c>30</c>. We recommend to test crashing various processes in your
- application, examine the logs from the crashes, and then
- increase or decrease the value.</p></note>
- </item>
<tag><c>global_groups = [GroupTuple]</c></tag>
<item>
<marker id="global_groups"></marker>
@@ -286,9 +283,8 @@
</item>
<tag><c>inet_parse_error_log = silent</c></tag>
<item>
- <p>If set, no
- <c>error_logger</c> messages are generated when erroneous
- lines are found and skipped in the various Inet configuration
+ <p>If set, no log events are issued when erroneous lines are
+ found and skipped in the various Inet configuration
files.</p>
</item>
<tag><c>inetrc = Filename</c></tag>
@@ -314,24 +310,31 @@
<tag><c>net_ticktime = TickTime</c></tag>
<item>
<marker id="net_ticktime"></marker>
- <p>Specifies the <c>net_kernel</c> tick time. <c>TickTime</c>
- is specified in seconds. Once every <c>TickTime/4</c> second, all
- connected nodes are ticked (if anything else is written
- to a node). If nothing is received from another node
- within the last four tick times, that node is considered
- to be down. This ensures that nodes that are not responding,
- for reasons such as hardware errors, are considered to be
- down.</p>
- <p>The time <c>T</c>, in which a node that is not responding is
- detected, is calculated as <c><![CDATA[MinT < T < MaxT]]></c>, where:</p>
+ <p>Specifies the <c>net_kernel</c> tick time in seconds. This is the
+ approximate time a connected node may be unresponsive until it is
+ considered down and thereby disconnected.</p>
+ <p>Once every <c>TickTime/4</c> seconds, each connected node is ticked
+ if nothing has been sent to it during that last <c>TickTime/4</c>
+ interval. A tick is a small package sent on the connection. A connected
+ node is considered to be down if no ticks or payload packages have been
+ received during the last four <c>TickTime/4</c> intervals. This ensures
+ that nodes that are not responding, for reasons such as hardware errors,
+ are considered to be down.</p>
+ <p>As the availability is only checked every <c>TickTime/4</c> seconds,
+ the actual time <c>T</c> a node have been unresponsive when
+ detected may vary between <c>MinT</c> and <c>MaxT</c>,
+ where:</p>
<code type="none">
MinT = TickTime - TickTime / 4
MaxT = TickTime + TickTime / 4</code>
- <p><c>TickTime</c> defaults to <c>60</c> (seconds). Thus,
- <c><![CDATA[45 < T < 75]]></c> seconds.</p>
- <p>Notice that <em>all</em> communicating nodes are to have the <em>same</em>
- <c>TickTime</c> value specified.</p>
- <p>Normally, a terminating node is detected immediately.</p>
+ <p><c>TickTime</c> defaults to <c>60</c> seconds. Thus,
+ <c><![CDATA[45 < T < 75]]></c> seconds.</p>
+ <p>Notice that <em>all</em> communicating nodes are to have the
+ <em>same</em> <c>TickTime</c> value specified, as it determines both the
+ frequency of outgoing ticks and the expected frequency of incominging
+ ticks.</p>
+ <p>Normally, a terminating node is detected immediately by the transport
+ protocol (like TCP/IP).</p>
</item>
<tag><c>shutdown_timeout = integer() | infinity</c></tag>
<item>
@@ -469,8 +472,12 @@ MaxT = TickTime + TickTime / 4</code>
<item><c>ObjSuffix = string()</c></item>
<item><c>SrcSuffix = string()</c></item>
</list>
- <p>Specifies a list of rules for use by <c>filelib:find_file/2</c> and
- <c>filelib:find_source/2</c>. If this is set to some other value
+ <p>Specifies a list of rules for use by
+ <seealso marker="stdlib:filelib#find_file/2">
+ <c>filelib:find_file/2</c></seealso>
+ <seealso marker="stdlib:filelib#find_source/2">
+ <c>filelib:find_source/2</c></seealso>
+ If this is set to some other value
than the empty list, it replaces the default rules. Rules can be
simple pairs of directory suffixes, such as <c>{"ebin",
"src"}</c>, which are used by <c>filelib:find_file/2</c>, or
@@ -478,8 +485,49 @@ MaxT = TickTime + TickTime / 4</code>
file name extensions, for example <c>[{".beam", ".erl", [{"ebin",
"src"}]}</c>, which are used by <c>filelib:find_source/2</c>. Both
kinds of rules can be mixed in the list.</p>
+ <p>The interpretation of <c>ObjDirSuffix</c> and <c>SrcDirSuffix</c>
+ is as follows: if the end of the directory name where an
+ object is located matches <c>ObjDirSuffix</c>, then the
+ name created by replacing <c>ObjDirSuffix</c> with
+ <c>SrcDirSuffix</c> is expanded by calling
+ <seealso marker="stdlib:filelib#wildcard/1">
+ <c>filelib:wildcard/1</c></seealso>, and the first regular
+ file found among the matches is the source file.
+ </p>
+
+ </item>
+ </taglist>
+ </section>
+
+ <section>
+ <title>Deprecated Configuration Parameters</title>
+ <p>In Erlang/OTP 21.0, a new API for logging was added. The
+ old <c>error_logger</c> event manager, and event handlers
+ running on this manager, still work, but they are no longer used
+ by default.</p>
+ <p>The following application configuration parameters can still be
+ set, but they are only used if the corresponding configuration
+ parameters for Logger are not set.</p>
+ <taglist>
+ <tag><c>error_logger</c></tag>
+ <item>Replaced by setting the type of the default
+ <seealso marker="logger_std_h#type"><c>logger_std_h</c></seealso>
+ to the same value. Example:
+ <code type="none">
+erl -kernel logger '[{handler,default,logger_std_h,#{config=>#{type=>{file,"/tmp/erlang.log"}}}}]'
+ </code>
+ </item>
+ <tag><c>error_logger_format_depth</c></tag>
+ <item>Replaced by setting the <seealso marker="logger_formatter#depth"><c>depth</c></seealso>
+ parameter of the default handlers formatter. Example:
+ <code type="none">
+erl -kernel logger '[{handler,default,logger_std_h,#{formatter=>{logger_formatter,#{legacy_header=>true,template=>[{logger_formatter,header},"\n",msg,"\n"],depth=>10}}}]'
+ </code>
</item>
</taglist>
+ <p>See <seealso marker="logger_chapter#compatibility">Backwards
+ compatibility with error_logger</seealso> for more
+ information.</p>
</section>
<section>
@@ -490,12 +538,12 @@ MaxT = TickTime + TickTime / 4</code>
<seealso marker="disk_log"><c>disk_log(3)</c></seealso>,
<seealso marker="erl_boot_server"><c>erl_boot_server(3)</c></seealso>,
<seealso marker="erl_ddll"><c>erl_ddll(3)</c></seealso>,
- <seealso marker="error_logger"><c>error_logger(3)</c></seealso>,
<seealso marker="file"><c>file(3)</c></seealso>,
<seealso marker="global"><c>global(3)</c></seealso>,
<seealso marker="global_group"><c>global_group(3)</c></seealso>,
<seealso marker="heart"><c>heart(3)</c></seealso>,
<seealso marker="inet"><c>inet(3)</c></seealso>,
+ <seealso marker="logger"><c>logger(3)</c></seealso>,
<seealso marker="net_kernel"><c>net_kernel(3)</c></seealso>,
<seealso marker="os"><c>os(3)</c></seealso>,
<seealso marker="pg2"><c>pg2(3)</c></seealso>,
diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml
new file mode 100644
index 0000000000..464c65ba76
--- /dev/null
+++ b/lib/kernel/doc/src/logger.xml
@@ -0,0 +1,1190 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2017</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>logger</title>
+ <prepared></prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev>A</rev>
+ <file>logger.xml</file>
+ </header>
+ <module>logger</module>
+ <modulesummary>API module for Logger, the standard logging facility
+ in Erlang/OTP.</modulesummary>
+
+ <description>
+ <p>This module implements the main API for logging in
+ Erlang/OTP. To create a log event, use the
+ <seealso marker="#logging_API">API functions</seealso> or the
+ log
+ <seealso marker="#macros">macros</seealso>, for example:</p>
+ <code>
+?LOG_ERROR("error happened because: ~p", [Reason]). % With macro
+logger:error("error happened because: ~p", [Reason]). % Without macro
+ </code>
+ <p>To configure the Logger backend,
+ use <seealso marker="kernel_app#logger">Kernel configuration
+ parameters</seealso>
+ or <seealso marker="#configuration_API">configuration
+ functions</seealso> in the Logger API.</p>
+
+ <p>By default, the Kernel application installs one log handler at
+ system start. This handler is named <c>default</c>. It receives
+ and processes standard log events produced by the Erlang runtime
+ system, standard behaviours and different Erlang/OTP
+ applications. The log events are by default printed to the
+ terminal.</p>
+ <p>If you want your systems logs to be printed to a file instead,
+ you must configure the default handler to do so. The simplest
+ way is to include the following in
+ your <seealso marker="config"><c>sys.config</c></seealso>:</p>
+ <code>
+[{kernel,
+ [{logger,
+ [{handler, default, logger_std_h,
+ #{config => #{type => {file, "path/to/file.log"}}}}]}]}].
+ </code>
+ <p>
+ For more information about:
+ </p>
+ <list type="bulleted">
+ <item>the Logger facility in general, see
+ the <seealso marker="logger_chapter">User's
+ Guide</seealso>.</item>
+ <item>how to configure Logger, see
+ the <seealso marker="logger_chapter#configuration">Configuration</seealso>
+ section in the User's Guide.</item>
+ <item>the built-in handlers,
+ see <seealso marker="logger_std_h">logger_std_h</seealso> and
+ <seealso marker="logger_disk_log_h">logger_disk_log_h</seealso>.</item>
+ <item>the built-in formatter,
+ see <seealso marker="logger_formatter">logger_formatter</seealso>.</item>
+ <item>built-in filters,
+ see <seealso marker="logger_filters">logger_filters</seealso>.</item>
+ </list>
+
+ <note>
+ <p>Since Logger is new in Erlang/OTP 21.0, we do reserve the right
+ to introduce changes to the Logger API and functionality in
+ patches following this release. These changes might or might not
+ be backwards compatible with the initial version.</p>
+ </note>
+
+ </description>
+
+ <datatypes>
+ <datatype>
+ <name name="filter"/>
+ <desc>
+ <p>A filter which can be installed as a handler filter, or as
+ a primary filter in Logger.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="filter_arg"/>
+ <desc>
+ <p>The second argument to the filter fun.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="filter_id"/>
+ <desc>
+ <p>A unique identifier for a filter.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="filter_return"/>
+ <desc>
+ <p>The return value from the filter fun.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="formatter_config"/>
+ <desc>
+ <p>Configuration data for the
+ formatter. See <seealso marker="logger_formatter">
+ <c>logger_formatter(3)</c></seealso>
+ for an example of a formatter implementation.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="handler_config"/>
+ <desc>
+ <p>Handler configuration data for Logger. The following
+ default values apply:</p>
+ <list>
+ <item><c>level => all</c></item>
+ <item><c>filter_default => log</c></item>
+ <item><c>filters => []</c></item>
+ <item><c>formatter => {logger_formatter, DefaultFormatterConfig</c>}</item>
+ </list>
+ <p>In addition to these, the following fields are
+ automatically inserted by Logger, values taken from the
+ two first parameters
+ to <seealso marker="#add_handler-3"><c>add_handler/3</c></seealso>:</p>
+ <list>
+ <item><c>id => HandlerId</c></item>
+ <item><c>module => Module</c></item>
+ </list>
+ <p>These are read-only and cannot be changed in runtime.</p>
+ <p>Handler specific configuration data is inserted by the
+ handler callback itself, in a sub structure associated with
+ the field named <c>config</c>. See
+ the <seealso marker="logger_std_h"><c>logger_std_h(3)</c></seealso>
+ and <seealso marker="logger_disk_log_h"><c>logger_disk_log_h</c></seealso>
+ manual pages for information about the specifc configuration
+ for these handlers.</p>
+ <p>See the <seealso marker="logger_formatter#type-config">
+ <c>logger_formatter(3)</c></seealso> manual page for
+ information about the default configuration for this
+ formatter.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="handler_id"/>
+ <desc>
+ <p>A unique identifier for a handler instance.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="level"/>
+ <desc>
+ <p>The severity level for the message to be logged.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="log_event"/>
+ <desc>
+ <p></p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="metadata"/>
+ <desc>
+ <p>Metadata for the log event.</p>
+ <p>Logger adds the following metadata to each log event:</p>
+ <list>
+ <item><c>pid => self()</c></item>
+ <item><c>gl => group_leader()</c></item>
+ <item><c>time => erlang:system_time(microsecond)</c></item>
+ </list>
+ <p>When a log macro is used, Logger also inserts location
+ information:</p>
+ <list>
+ <item><c>mfa => {?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY}</c></item>
+ <item><c>file => ?FILE</c></item>
+ <item><c>line => ?LINE</c></item>
+ </list>
+ <p>You can add custom metadata, either by specifying a map as
+ the last parameter to any of the log macros or the API
+ functions, or by setting process metadata
+ with <seealso marker="#set_process_metadata-1">
+ <c>set_process_metadata/1</c></seealso>
+ or <seealso marker="#update_process_metadata-1">
+ <c>update_process_metadata/1</c></seealso>.</p>
+ <p>Logger merges all the metadata maps before forwarding the
+ log event to the handlers. If the same keys occur, values
+ from the log call overwrite process metadata, which in turn
+ overwrite values set by Logger.</p>
+ <p>The following custom metadata keys have special meaning:</p>
+ <taglist>
+ <tag><c>domain</c></tag>
+ <item>
+ <p>The value associated with this key is used by filters
+ for grouping log events originating from, for example,
+ specific functional
+ areas. See <seealso marker="logger_filters#domain-2">
+ <c>logger_filters:domain/2</c></seealso>
+ for a description of how this field can be used.</p>
+ </item>
+ <tag><c>report_cb</c></tag>
+ <item>
+ <p>If the log message is specified as
+ a <seealso marker="#type-report"><c>report()</c></seealso>,
+ the <c>report_cb</c> key can be associated with a fun
+ (report callback) that converts the report to a format
+ string and arguments, or directly to a string. See the
+ type definition
+ of <seealso marker="#type-report_cb"><c>report_cb()</c></seealso>,
+ and
+ section <seealso marker="logger_chapter#log_message">Log
+ Message</seealso> in the User's Guide for more
+ information about report callbacks.</p>
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="msg_fun"/>
+ <desc>
+ <p></p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="primary_config"/>
+ <desc>
+ <p>Primary configuration data for Logger. The following
+ default values apply:</p>
+ <list>
+ <item><c>level => info</c></item>
+ <item><c>filter_default => log</c></item>
+ <item><c>filters => []</c></item>
+ </list>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="report"/>
+ <desc>
+ <p></p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="report_cb"/>
+ <desc>
+ <p>A fun which converts a <seealso marker="#type-report"><c>report()</c>
+ </seealso> to a format string and arguments, or directly to a string.
+ See section <seealso marker="logger_chapter#log_message">Log
+ Message</seealso> in the User's Guide for more
+ information.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="report_cb_config"/>
+ <desc>
+ <p></p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="timestamp"/>
+ <desc>
+ <p>A timestamp produced
+ with <seealso marker="erts:erlang#system_time-1">
+ <c>erlang:system_time(microsecond)</c></seealso>.</p>
+ </desc>
+ </datatype>
+ </datatypes>
+
+ <section>
+ <title>Macros</title>
+ <p>The following macros are defined:</p>
+
+ <list>
+ <item><c>?LOG_EMERGENCY(StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG_EMERGENCY(FunOrFormat,Args[,Metadata])</c></item>
+ <item><c>?LOG_ALERT(StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG_ALERT(FunOrFormat,Args[,Metadata])</c></item>
+ <item><c>?LOG_CRITICAL(StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG_CRITICAL(FunOrFormat,Args[,Metadata])</c></item>
+ <item><c>?LOG_ERROR(StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG_ERROR(FunOrFormat,Args[,Metadata])</c></item>
+ <item><c>?LOG_WARNING(StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG_WARNING(FunOrFormat,Args[,Metadata])</c></item>
+ <item><c>?LOG_NOTICE(StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG_NOTICE(FunOrFormat,Args[,Metadata])</c></item>
+ <item><c>?LOG_INFO(StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG_INFO(FunOrFormat,Args[,Metadata])</c></item>
+ <item><c>?LOG_DEBUG(StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG_DEBUG(FunOrFormat,Args[,Metadata])</c></item>
+ <item><c>?LOG(Level,StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG(Level,FunOrFormat,Args[,Metadata])</c></item>
+ </list>
+
+ <p>All macros expand to a call to Logger, where <c>Level</c> is
+ taken from the macro name, or from the first argument in the
+ case of the <c>?LOG</c> macro. Location data is added to the
+ metadata as described under
+ the <seealso marker="#type-metadata"><c>metadata()</c></seealso>
+ type definition.</p>
+
+ <p>The call is wrapped in a case statement and will be evaluated
+ only if <c>Level</c> is equal to or below the configured log
+ level.</p>
+ </section>
+
+ <section>
+ <marker id="logging_API"/>
+ <title>Logging API functions</title>
+ </section>
+ <funcs>
+ <func>
+ <name>emergency(StringOrReport[,Metadata])</name>
+ <name>emergency(Format,Args[,Metadata])</name>
+ <name>emergency(Fun,FunArgs[,Metadata])</name>
+ <fsummary>Logs the given message as level <c>emergency</c>.</fsummary>
+ <desc>
+ <p>Equivalent to
+ <seealso marker="#log-2"><c>log(emergency,...)</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>alert(StringOrReport[,Metadata])</name>
+ <name>alert(Format,Args[,Metadata])</name>
+ <name>alert(Fun,FunArgs[,Metadata])</name>
+ <fsummary>Logs the given message as level <c>alert</c>.</fsummary>
+ <desc>
+ <p>Equivalent to
+ <seealso marker="#log-2"><c>log(alert,...)</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>critical(StringOrReport[,Metadata])</name>
+ <name>critical(Format,Args[,Metadata])</name>
+ <name>critical(Fun,FunArgs[,Metadata])</name>
+ <fsummary>Logs the given message as level <c>critical</c>.</fsummary>
+ <desc>
+ <p>Equivalent to
+ <seealso marker="#log-2"><c>log(critical,...)</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>error(StringOrReport[,Metadata])</name>
+ <name>error(Format,Args[,Metadata])</name>
+ <name>error(Fun,FunArgs[,Metadata])</name>
+ <fsummary>Logs the given message as level <c>error</c>.</fsummary>
+ <desc>
+ <p>Equivalent to
+ <seealso marker="#log-2"><c>log(error,...)</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>warning(StringOrReport[,Metadata])</name>
+ <name>warning(Format,Args[,Metadata])</name>
+ <name>warning(Fun,FunArgs[,Metadata])</name>
+ <fsummary>Logs the given message as level <c>warning</c>.</fsummary>
+ <desc>
+ <p>Equivalent to
+ <seealso marker="#log-2"><c>log(warning,...)</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>notice(StringOrReport[,Metadata])</name>
+ <name>notice(Format,Args[,Metadata])</name>
+ <name>notice(Fun,FunArgs[,Metadata])</name>
+ <fsummary>Logs the given message as level <c>notice</c>.</fsummary>
+ <desc>
+ <p>Equivalent to
+ <seealso marker="#log-2"><c>log(notice,...)</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>info(StringOrReport[,Metadata])</name>
+ <name>info(Format,Args[,Metadata])</name>
+ <name>info(Fun,FunArgs[,Metadata])</name>
+ <fsummary>Logs the given message as level <c>info</c>.</fsummary>
+ <desc>
+ <p>Equivalent to
+ <seealso marker="#log-2"><c>log(info,...)</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>debug(StringOrReport[,Metadata])</name>
+ <name>debug(Format,Args[,Metadata])</name>
+ <name>debug(Fun,FunArgs[,Metadata])</name>
+ <fsummary>Logs the given message as level <c>debug</c>.</fsummary>
+ <desc>
+ <p>Equivalent to
+ <seealso marker="#log-2"><c>log(debug,...)</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="log" arity="2"/>
+ <name name="log" arity="3" clause_i="1"/>
+ <name name="log" arity="3" clause_i="2"/>
+ <name name="log" arity="3" clause_i="3"/>
+ <name name="log" arity="4" clause_i="1"/>
+ <name name="log" arity="4" clause_i="2"/>
+ <fsummary>Logs the given message.</fsummary>
+ <type variable="Level"/>
+ <type variable="StringOrReport" name_i="1"/>
+ <type variable="Format" name_i="3"/>
+ <type variable="Args" name_i="3"/>
+ <type variable="Fun" name_i="4"/>
+ <type variable="FunArgs" name_i="4"/>
+ <type variable="Metadata"/>
+ <desc>
+ <p>Log the given message.</p>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <marker id="configuration_API"/>
+ <title>Configuration API functions</title>
+ </section>
+ <funcs>
+ <func>
+ <name name="add_handler" arity="3"/>
+ <fsummary>Add a handler with the given configuration.</fsummary>
+ <desc>
+ <p>Add a handler with the given configuration.</p>
+ <p><c><anno>HandlerId</anno></c> is a unique identifier which
+ must be used in all subsequent calls referring to this
+ handler.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="add_handler_filter" arity="3"/>
+ <fsummary>Add a filter to the specified handler.</fsummary>
+ <desc>
+ <p>Add a filter to the specified handler.</p>
+ <p>The filter fun is called with the log event as the first
+ parameter, and the specified <c>filter_args()</c> as the
+ second parameter.</p>
+ <p>The return value of the fun specifies if a log event is to
+ be discarded or forwarded to the handler callback:</p>
+ <taglist>
+ <tag><c>log_event()</c></tag>
+ <item>
+ <p>The filter <em>passed</em>. The next handler filter, if
+ any, is applied. If no more filters exist for this
+ handler, the log event is forwarded to the handler
+ callback.</p>
+ </item>
+ <tag><c>stop</c></tag>
+ <item>
+ <p>The filter <em>did not pass</em>, and the log event is
+ immediately discarded.</p>
+ </item>
+ <tag><c>ignore</c></tag>
+ <item>
+ <p>The filter has no knowledge of the log event. The next
+ handler filter, if any, is applied. If no more filters
+ exist for this handler, the value of
+ the <c>filter_default</c> configuration parameter for
+ the handler specifies if the log event shall be
+ discarded or forwarded to the handler callback.</p>
+ </item>
+ </taglist>
+ <p>See
+ section <seealso marker="logger_chapter#filters">Filters</seealso>
+ in the User's Guide for more information about filters.</p>
+ <p>Some built-in filters exist. These are defined in
+ <seealso marker="logger_filters"><c>logger_filters</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="add_handlers" arity="1" clause_i="1"/>
+ <fsummary>Set up log handlers from the application's
+ configuration parameters.</fsummary>
+ <desc>
+ <p>Reads the application configuration parameter <c>logger</c> and
+ calls <c>add_handlers/1</c> with its contents.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="add_handlers" arity="1" clause_i="2"/>
+ <fsummary>Setup logger handlers.</fsummary>
+ <type name="config_handler"/>
+ <desc>
+ <p>This function should be used by custom Logger handlers to make
+ configuration consistent no matter which handler the system uses.
+ Normal usage is to add a call to <c>logger:add_handlers/1</c>
+ just after the processes that the handler needs are started,
+ and pass the application's <c>logger</c> configuration as the argument.
+ For example:</p>
+ <code>
+-behaviour(application).
+start(_, []) ->
+ case supervisor:start_link({local, my_sup}, my_sup, []) of
+ {ok, Pid} ->
+ ok = logger:add_handlers(my_app),
+ {ok, Pid, []};
+ Error -> Error
+ end.</code>
+ <p>This reads the <c>logger</c> configuration parameter from
+ the <c>my_app</c> application and starts the configured
+ handlers. The contents of the configuration use the same
+ rules as the
+ <seealso marker="logger_chapter#handler-configuration">logger handler configuration</seealso>.
+ </p>
+ <p>If the handler is meant to replace the default handler, the Kernel's
+ default handler have to be disabled before the new handler is added.
+ A <c>sys.config</c> file that disables the Kernel handler and adds
+ a custom handler could look like this:</p>
+ <code>
+[{kernel,
+ [{logger,
+ %% Disable the default Kernel handler
+ [{handler, default, undefined}]}]},
+ {my_app,
+ [{logger,
+ %% Enable this handler as the default
+ [{handler, default, my_handler, #{}}]}]}].
+ </code>
+ </desc>
+ </func>
+
+ <func>
+ <name name="add_primary_filter" arity="2"/>
+ <fsummary>Add a primary filter to Logger.</fsummary>
+ <desc>
+ <p>Add a primary filter to Logger.</p>
+ <p>The filter fun is called with the log event as the first
+ parameter, and the specified <c>filter_args()</c> as the
+ second parameter.</p>
+ <p>The return value of the fun specifies if a log event is to
+ be discarded or forwarded to the handlers:</p>
+ <taglist>
+ <tag><c>log_event()</c></tag>
+ <item>
+ <p>The filter <em>passed</em>. The next primary filter, if
+ any, is applied. If no more primary filters exist, the
+ log event is forwarded to the handler part of Logger,
+ where handler filters are applied.</p>
+ </item>
+ <tag><c>stop</c></tag>
+ <item>
+ <p>The filter <em>did not pass</em>, and the log event is
+ immediately discarded.</p>
+ </item>
+ <tag><c>ignore</c></tag>
+ <item>
+ <p>The filter has no knowledge of the log event. The next
+ primary filter, if any, is applied. If no more primary
+ filters exist, the value of the
+ primary <c>filter_default</c> configuration parameter
+ specifies if the log event shall be discarded or
+ forwarded to the handler part.</p>
+ </item>
+ </taglist>
+ <p>See section <seealso marker="logger_chapter#filters">
+ Filters</seealso> in the User's Guide for more information
+ about filters.</p>
+ <p>Some built-in filters exist. These are defined
+ in <seealso marker="logger_filters"><c>logger_filters</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="get_config" arity="0"/>
+ <fsummary>Look up the current Logger configuration</fsummary>
+ <desc>
+ <p>Look up all current Logger configuration, including primary
+ and handler configuration, and module level settings.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="get_handler_config" arity="0"/>
+ <fsummary>Look up the current configuration for all handlers.</fsummary>
+ <desc>
+ <p>Look up the current configuration for all handlers.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="get_handler_config" arity="1"/>
+ <fsummary>Look up the current configuration for the given
+ handler.</fsummary>
+ <desc>
+ <p>Look up the current configuration for the given handler.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="get_handler_ids" arity="0"/>
+ <fsummary>Look up the identities for all installed handlers.</fsummary>
+ <desc>
+ <p>Look up the identities for all installed handlers.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="get_primary_config" arity="0"/>
+ <fsummary>Look up the current primary configuration for Logger.</fsummary>
+ <desc>
+ <p>Look up the current primary configuration for Logger.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="get_module_level" arity="0"/>
+ <fsummary>Look up all current module levels.</fsummary>
+ <desc>
+ <p>Look up all current module levels. Returns a list
+ containing one <c>{Module,Level}</c> element for each module
+ for which the module level was previously set
+ with <seealso marker="#set_module_level-2">
+ <c>set_module_level/2</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="get_module_level" arity="1"/>
+ <fsummary>Look up the current level for the given modules.</fsummary>
+ <desc>
+ <p>Look up the current level for the given modules. Returns a
+ list containing one <c>{Module,Level}</c> element for each
+ of the given modules for which the module level was
+ previously set with <seealso marker="#set_module_level-2">
+ <c>set_module_level/2</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="get_process_metadata" arity="0"/>
+ <fsummary>Retrieve data set with set_process_metadata/1.</fsummary>
+ <desc>
+ <p>Retrieve data set
+ with <seealso marker="#set_process_metadata-1">
+ <c>set_process_metadata/1</c></seealso> or
+ <seealso marker="#update_process_metadata-1">
+ <c>update_process_metadata/1</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="remove_handler" arity="1"/>
+ <fsummary>Remove the handler with the specified identity.</fsummary>
+ <desc>
+ <p>Remove the handler identified by <c><anno>HandlerId</anno></c>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="remove_handler_filter" arity="2"/>
+ <fsummary>Remove a filter from the specified handler.</fsummary>
+ <desc>
+ <p>Remove the filter identified
+ by <c><anno>FilterId</anno></c> from the handler identified
+ by <c><anno>HandlerId</anno></c>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="remove_primary_filter" arity="1"/>
+ <fsummary>Remove a primary filter from Logger.</fsummary>
+ <desc>
+ <p>Remove the primary filter identified
+ by <c><anno>FilterId</anno></c> from Logger.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="set_application_level" arity="2"/>
+ <fsummary>Set the log level for all modules in the specified application.</fsummary>
+ <desc>
+ <p>Set the log level for all the modules of the specified application.</p>
+ <p>This function is a convenience function that calls
+ <seealso marker="#set_module_level/2">logger:set_module_level/2</seealso>
+ for each module associated with an application.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="set_handler_config" arity="2"/>
+ <fsummary>Set configuration data for the specified handler.</fsummary>
+ <desc>
+ <p>Set configuration data for the specified handler. This
+ overwrites the current handler configuration.</p>
+ <p>To modify the existing configuration,
+ use <seealso marker="#update_handler_config-2">
+ <c>update_handler_config/2</c></seealso>, or, if a more
+ complex merge is needed, read the current configuration
+ with <seealso marker="#get_handler_config-1"><c>get_handler_config/1</c>
+ </seealso>, then do the merge before writing the new
+ configuration back with this function.</p>
+ <p>If a key is removed compared to the current configuration,
+ and the key is known by Logger, the default value is used. If
+ it is a custom key, then it is up to the handler
+ implementation if the value is removed or a default value is
+ inserted.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="set_handler_config" arity="3" clause_i="1"/>
+ <name name="set_handler_config" arity="3" clause_i="2"/>
+ <name name="set_handler_config" arity="3" clause_i="3"/>
+ <name name="set_handler_config" arity="3" clause_i="4"/>
+ <name name="set_handler_config" arity="3" clause_i="5"/>
+ <fsummary>Add or update configuration data for the specified
+ handler.</fsummary>
+ <type variable="HandlerId"/>
+ <type variable="Level" name_i="1"/>
+ <type variable="FilterDefault" name_i="2"/>
+ <type variable="Filters" name_i="3"/>
+ <type variable="Formatter" name_i="4"/>
+ <type variable="Config" name_i="5"/>
+ <type variable="Return"/>
+ <desc>
+ <p>Add or update configuration data for the specified
+ handler. If the given <c><anno>Key</anno></c> already
+ exists, its associated value will be changed
+ to the given value. If it does not exist, it will
+ be added.</p>
+ <p>See the definition of
+ the <seealso marker="#type-handler_config">
+ <c>handler_config()</c></seealso> type for more
+ information about the different parameters.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="set_primary_config" arity="1"/>
+ <fsummary>Set primary configuration data for Logger.</fsummary>
+ <desc>
+ <p>Set primary configuration data for Logger. This
+ overwrites the current configuration.</p>
+ <p>To modify the existing configuration,
+ use <seealso marker="#update_primary_config-1">
+ <c>update_primary_config/1</c></seealso>, or, if a more
+ complex merge is needed, read the current configuration
+ with <seealso marker="#get_primary_config-0"><c>get_primary_config/0</c>
+ </seealso>, then do the merge before writing the new
+ configuration back with this function.</p>
+ <p>If a key is removed compared to the current configuration,
+ the default value is used.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="set_primary_config" arity="2" clause_i="1"/>
+ <name name="set_primary_config" arity="2" clause_i="2"/>
+ <name name="set_primary_config" arity="2" clause_i="3"/>
+ <fsummary>Add or update primary configuration data for Logger.</fsummary>
+ <type variable="Level" name_i="1"/>
+ <type variable="FilterDefault" name_i="2"/>
+ <type variable="Filters" name_i="3"/>
+ <desc>
+ <p>Add or update primary configuration data for Logger. If the
+ given <c><anno>Key</anno></c> already exists, its associated
+ value will be changed to the given value. If it does not
+ exist, it will be added.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="set_module_level" arity="2"/>
+ <fsummary>Set the log level for the specified modules.</fsummary>
+ <desc>
+ <p>Set the log level for the specified modules.</p>
+ <p>The log level for a module overrides the primary log level
+ of Logger for log events originating from the module in
+ question. Notice, however, that it does not override the
+ level configuration for any handler.</p>
+ <p>For example: Assume that the primary log level for Logger
+ is <c>info</c>, and there is one handler, <c>h1</c>, with
+ level <c>info</c> and one handler, <c>h2</c>, with
+ level <c>debug</c>.</p>
+ <p>With this configuration, no debug messages will be logged,
+ since they are all stopped by the primary log level.</p>
+ <p>If the level for <c>mymodule</c> is now set
+ to <c>debug</c>, then debug events from this module will be
+ logged by the handler <c>h2</c>, but not by
+ handler <c>h1</c>.</p>
+ <p>Debug events from other modules are still not logged.</p>
+ <p>To change the primary log level for Logger, use
+ <seealso marker="#set_primary_config/2">
+ <c>set_primary_config(level, Level)</c></seealso>.</p>
+ <p>To change the log level for a handler, use
+ <seealso marker="#set_handler_config/3">
+ <c>set_handler_config(HandlerId, level, Level)</c>
+ </seealso>.</p>
+ <note>
+ <p>The originating module for a log event is only detected
+ if the key <c>mfa</c> exists in the metadata, and is
+ associated with <c>{Module, Function, Arity}</c>. When log
+ macros are used, this association is automatically added
+ to all log events. If an API function is called directly,
+ without using a macro, the logging client must explicitly
+ add this information if module levels shall have any
+ effect.</p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
+ <name name="set_process_metadata" arity="1"/>
+ <fsummary>Set metadata to use when logging from current process.</fsummary>
+ <desc>
+ <p>Set metadata which Logger shall automatically insert in
+ all log events produced on the current process.</p>
+ <p>Location data produced by the log macros, and/or metadata
+ given as argument to the log call (API function or macro),
+ are merged with the process metadata. If the same keys
+ occur, values from the metadata argument to the log call
+ overwrite values from the process metadata, which in turn
+ overwrite values from the location data.</p>
+ <p>Subsequent calls to this function overwrites previous data
+ set. To update existing data instead of overwriting it,
+ see <seealso marker="#update_process_metadata-1">
+ <c>update_process_metadata/1</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="unset_application_level" arity="1"/>
+ <fsummary>Unset the log level for all modules in the specified application.</fsummary>
+ <desc>
+ <p>Unset the log level for all the modules of the specified application.</p>
+ <p>This function is a convinience function that calls
+ <seealso marker="#unset_module_level/1">logger:unset_module_level/2</seealso>
+ for each module associated with an application.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="unset_module_level" arity="0"/>
+ <fsummary>Remove module specific log settings for all modules.</fsummary>
+ <desc>
+ <p>Remove module specific log settings. After this, the
+ primary log level is used for all modules.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="unset_module_level" arity="1"/>
+ <fsummary>Remove module specific log settings for the given
+ modules.</fsummary>
+ <desc>
+ <p>Remove module specific log settings. After this, the
+ primary log level is used for the specified modules.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="unset_process_metadata" arity="0"/>
+ <fsummary>Delete data set with set_process_metadata/1.</fsummary>
+ <desc>
+ <p>Delete data set
+ with <seealso marker="#set_process_metadata-1">
+ <c>set_process_metadata/1</c></seealso> or
+ <seealso marker="#update_process_metadata-1">
+ <c>update_process_metadata/1</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="update_formatter_config" arity="2"/>
+ <fsummary>Update the formatter configuration for the specified handler.</fsummary>
+ <desc>
+ <p>Update the formatter configuration for the specified handler.</p>
+ <p>The new configuration is merged with the existing formatter
+ configuration.</p>
+ <p>To overwrite the existing configuration without any merge,
+ use</p>
+ <pre>
+<seealso marker="#set_handler_config-3">set_handler_config(HandlerId, formatter,
+ {FormatterModule, FormatterConfig})</seealso>.</pre>
+ </desc>
+ </func>
+
+ <func>
+ <name name="update_formatter_config" arity="3"/>
+ <fsummary>Update the formatter configuration for the specified handler.</fsummary>
+ <desc>
+ <p>Update the formatter configuration for the specified handler.</p>
+ <p>This is equivalent to</p>
+ <pre>
+<seealso marker="#update_formatter_config-2">update_formatter_config(<anno>HandlerId</anno>, #{<anno>Key</anno> => <anno>Value</anno>})</seealso></pre>
+ </desc>
+ </func>
+
+ <func>
+ <name name="update_handler_config" arity="2"/>
+ <fsummary>Update configuration data for the specified handler.</fsummary>
+ <desc>
+ <p>Update configuration data for the specified handler. This function
+ behaves as if it was implemented as follows:</p>
+ <code type="erl">
+{ok, {_, Old}} = logger:get_handler_config(HandlerId),
+logger:set_handler_config(HandlerId, maps:merge(Old, Config)).
+ </code>
+ <p>To overwrite the existing configuration without any merge,
+ use <seealso marker="#set_handler_config-2"><c>set_handler_config/2</c>
+ </seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="update_primary_config" arity="1"/>
+ <fsummary>Update primary configuration data for Logger.</fsummary>
+ <desc>
+ <p>Update primary configuration data for Logger. This function
+ behaves as if it was implemented as follows:</p>
+ <code type="erl">
+Old = logger:get_primary_config(),
+logger:set_primary_config(maps:merge(Old, Config)).
+ </code>
+ <p>To overwrite the existing configuration without any merge,
+ use <seealso marker="#set_primary_config-1"><c>set_primary_config/1</c>
+ </seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="update_process_metadata" arity="1"/>
+ <fsummary>Set or update metadata to use when logging from
+ current process.</fsummary>
+ <desc>
+ <p>Set or update metadata to use when logging from current
+ process</p>
+ <p>If process metadata exists for the current process, this
+ function behaves as if it was implemented as follows:</p>
+ <code type="erl">
+logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).
+ </code>
+ <p>If no process metadata exists, the function behaves as
+ <seealso marker="#set_process_metadata-1">
+ <c>set_process_metadata/1</c>
+ </seealso>.</p>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <marker id="misc_API"/>
+ <title>Miscellaneous API functions</title>
+ </section>
+ <funcs>
+ <func>
+ <name name="compare_levels" arity="2"/>
+ <fsummary>Compare the severity of two log levels.</fsummary>
+ <desc>
+ <p>Compare the severity of two log levels. Returns <c>gt</c>
+ if <c>Level1</c> is more severe than
+ <c>Level2</c>, <c>lt</c> if <c>Level1</c> is less severe,
+ and <c>eq</c> if the levels are equal.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="format_report" arity="1"/>
+ <fsummary>Convert a log message on report form to {Format, Args}.</fsummary>
+ <desc>
+ <p>Convert a log message on report form to <c>{Format,
+ Args}</c>. This is the default report callback used
+ by <seealso marker="logger_formatter">
+ <c>logger_formatter</c></seealso> when no custom report
+ callback is found. See
+ section <seealso marker="logger_chapter#log_message">Log
+ Message</seealso> in the Kernel User's Guide for
+ information about report callbacks and valid forms of log
+ messages.</p>
+ <p>The function produces lines of <c>Key: Value</c> from
+ key-value lists. Strings are printed with <c>~ts</c> and
+ other terms with <c>~tp</c>.</p>
+ <p>If <c><anno>Report</anno></c> is a map, it is converted to
+ a key-value list before formatting as such.</p>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <marker id="handler_callback_functions"/>
+ <title>Handler Callback Functions</title>
+ <p>The following functions are to be exported from a handler
+ callback module.</p>
+ </section>
+
+ <funcs>
+ <func>
+ <name>HModule:adding_handler(Config1) -> {ok, Config2} | {error,
+ Reason}</name>
+ <fsummary>An instance of this handler is about to be added.</fsummary>
+ <type>
+ <v>Config1 = Config2 =
+ <seealso marker="#type-handler_config">handler_config()</seealso></v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>This callback function is optional.</p>
+ <p>The function is called on a temporary process when an new
+ handler is about to be added. The purpose is to verify the
+ configuration and initiate all resources needed by the
+ handler.</p>
+ <p>The handler identity is associated with the <c>id</c> key
+ in <c>Config1</c>.</p>
+ <p>If everything succeeds, the callback function can add
+ possible default values or internal state values to the
+ configuration, and return the adjusted map
+ in <c>{ok,Config2}</c>.</p>
+ <p>If the configuration is faulty, or if the initiation fails,
+ the callback function must return <c>{error,Reason}</c>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>HModule:changing_config(Config1, Config2) -> {ok, Config3} | {error, Reason}</name>
+ <fsummary>The configuration for this handler is about to change.</fsummary>
+ <type>
+ <v>Config1 = Config2 = Config3 =
+ <seealso marker="#type-handler_config">handler_config()</seealso></v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>This callback function is optional.</p>
+ <p>The function is called on a temporary process when the
+ configuration for a handler is about to change. The purpose
+ is to verify and act on the new configuration.</p>
+ <p><c>Config1</c> is the existing configuration
+ and <c>Config2</c> is the new configuration.</p>
+ <p>The handler identity is associated with the <c>id</c> key
+ in <c>Config1</c>.</p>
+ <p>If everything succeeds, the callback function must return a
+ possibly adjusted configuration in <c>{ok,Config3}</c>.</p>
+ <p>If the configuration is faulty, the callback function must
+ return <c>{error,Reason}</c>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>HModule:log(LogEvent, Config) -> void()</name>
+ <fsummary>Log the given log event.</fsummary>
+ <type>
+ <v>LogEvent =
+ <seealso marker="#type-log_event">log_event()</seealso></v>
+ <v>Config =
+ <seealso marker="#type-handler_config">handler_config()</seealso></v>
+ </type>
+ <desc>
+ <p>This callback function is mandatory.</p>
+ <p>The function is called when all primary filters and all
+ handler filters for the handler in question have passed for
+ the given log event. It is called on the client process, that
+ is, the process that issued the log event.</p>
+ <p>The handler identity is associated with the <c>id</c> key
+ in <c>Config</c>.</p>
+ <p>The handler must log the event.</p>
+ <p>The return value from this function is ignored by
+ Logger.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>HModule:removing_handler(Config) -> ok</name>
+ <fsummary>The given handler is about to be removed.</fsummary>
+ <type>
+ <v>Config =
+ <seealso marker="#type-handler_config">handler_config()</seealso></v>
+ </type>
+ <desc>
+ <p>This callback function is optional.</p>
+ <p>The function is called on a temporary process when a
+ handler is about to be removed. The purpose is to release
+ all resources used by the handler.</p>
+ <p>The handler identity is associated with the <c>id</c> key
+ in <c>Config</c>.</p>
+ <p>The return value is ignored by Logger.</p>
+ </desc>
+ </func>
+
+ </funcs>
+
+ <section>
+ <marker id="formatter_callback_functions"/>
+ <title>Formatter Callback Functions</title>
+ <p>The following functions are to be exported from a formatter
+ callback module.</p>
+ </section>
+
+ <funcs>
+ <func>
+ <name>FModule:check_config(FConfig) -> ok | {error, Reason}</name>
+ <fsummary>Validate the given formatter configuration.</fsummary>
+ <type>
+ <v>FConfig =
+ <seealso marker="#type-formatter_config">formatter_config()</seealso></v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>This callback function is optional.</p>
+ <p>The function is called by a Logger when formatter
+ configuration is set or modified. The formatter must
+ validate the given configuration and return <c>ok</c> if it
+ is correct, and <c>{error,Reason}</c> if it is faulty.</p>
+ <p>The following Logger API functions can trigger this callback:</p>
+ <list>
+ <item><seealso marker="logger#add_handler-3">
+ <c>logger:add_handler/3</c></seealso></item>
+ <item><seealso marker="logger#set_handler_config-2">
+ <c>logger:set_handler_config/2,3</c></seealso></item>
+ <item><seealso marker="logger#update_handler_config-2">
+ <c>logger:updata_handler_config/2</c></seealso></item>
+ <item><seealso marker="logger#update_formatter_config-2">
+ <c>logger:update_formatter_config/2</c></seealso></item>
+ </list>
+ <p>See <seealso marker="logger_formatter">
+ <c>logger_formatter(3)</c></seealso>
+ for an example implementation. <c>logger_formatter</c> is the
+ default formatter used by Logger.</p>
+ </desc>
+ </func>
+ <func>
+ <name>FModule:format(LogEvent, FConfig) -> FormattedLogEntry</name>
+ <fsummary>Format the given log event.</fsummary>
+ <type>
+ <v>LogEvent =
+ <seealso marker="#type-log_event">log_event()</seealso></v>
+ <v>FConfig =
+ <seealso marker="#type-formatter_config">formatter_config()</seealso></v>
+ <v>FormattedLogEntry =
+ <seealso marker="unicode#type-chardata">unicode:chardata()</seealso></v>
+ </type>
+ <desc>
+ <p>This callback function is mandatory.</p>
+ <p>The function can be called by a log handler to convert a
+ log event term to a printable string. The returned value
+ can, for example, be printed as a log entry to the console
+ or a file using <seealso marker="stdlib:io#put_chars-1">
+ <c>io:put_chars/1,2</c></seealso>.</p>
+ <p>See <seealso marker="logger_formatter">
+ <c>logger_formatter(3)</c></seealso>
+ for an example implementation. <c>logger_formatter</c> is the
+ default formatter used by Logger.</p>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <title>See Also</title>
+ <p>
+ <seealso marker="config"><c>config(4)</c></seealso>,
+ <seealso marker="erts:erlang"><c>erlang(3)</c></seealso>,
+ <seealso marker="stdlib:io"><c>io(3)</c></seealso>,
+ <seealso marker="logger_disk_log_h"><c>logger_disk_log_h(3)</c></seealso>,
+ <seealso marker="logger_filters"><c>logger_filters(3)</c></seealso>,
+ <seealso marker="logger_formatter"><c>logger_formatter(3)</c></seealso>,
+ <seealso marker="logger_std_h"><c>logger_std_h(3)</c></seealso>,
+ <seealso marker="stdlib:unicode"><c>unicode(3)</c></seealso>
+ </p>
+ </section>
+</erlref>
+
+
diff --git a/lib/kernel/doc/src/logger_arch.dia b/lib/kernel/doc/src/logger_arch.dia
new file mode 100644
index 0000000000..97be31856e
--- /dev/null
+++ b/lib/kernel/doc/src/logger_arch.dia
Binary files differ
diff --git a/lib/kernel/doc/src/logger_arch.png b/lib/kernel/doc/src/logger_arch.png
new file mode 100644
index 0000000000..70933a5a41
--- /dev/null
+++ b/lib/kernel/doc/src/logger_arch.png
Binary files differ
diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml
new file mode 100644
index 0000000000..4a81cfa34a
--- /dev/null
+++ b/lib/kernel/doc/src/logger_chapter.xml
@@ -0,0 +1,1333 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2017</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>Logging</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>logger_chapter.xml</file>
+ </header>
+
+ <p>Erlang/OTP 21.0 provides a standard API for logging
+ through <c>Logger</c>, which is part of the Kernel
+ application. Logger consists of the API for issuing log events,
+ and a customizable backend where log handlers, filters and
+ formatters can be plugged in.</p>
+ <p>By default, the Kernel application installs one log handler at
+ system start. This handler is named <c>default</c>. It receives
+ and processes standard log events produced by the Erlang runtime
+ system, standard behaviours and different Erlang/OTP
+ applications. The log events are by default written to the
+ terminal.</p>
+ <p>You can also configure the system so that the default handler
+ prints log events to a single file, or to a set of wrap logs
+ via <seealso marker="disk_log"><c>disk_log</c></seealso>.</p>
+ <p>By configuration, you can also modify or disable the default
+ handler, replace it by a custom handler, and install additional
+ handlers.</p>
+
+ <note>
+ <p>Since Logger is new in Erlang/OTP 21.0, we do reserve the right
+ to introduce changes to the Logger API and functionality in
+ patches following this release. These changes might or might not
+ be backwards compatible with the initial version.</p>
+ </note>
+
+ <section>
+ <title>Overview</title>
+ <p>A <em>log event</em> consists of a <em>log level</em>, the
+ <em>message</em> to be logged, and <em>metadata</em>.</p>
+ <p>The Logger backend forwards log events from the API, first
+ through a set of <em>primary filters</em>, then through a set of
+ secondary filters attached to each log handler. The secondary
+ filters are in the following named <em>handler filters</em>.</p>
+ <p>Each filter set consists of a <em>log level check</em>,
+ followed by zero or more <em>filter functions</em>.</p>
+ <p>The following figure shows a conceptual overview of Logger. The
+ figure shows two log handlers, but any number of handlers can be
+ installed.</p>
+
+ <!-- The image is edited with dia in logger_arch.dia file,
+ and .png file generated with make target 'png'. -->
+ <image file="logger_arch.png">
+ <icaption>Conceptual Overview</icaption>
+ </image>
+
+ <p>Log levels are expressed as atoms. Internally in Logger, the
+ atoms are mapped to integer values, and a log event passes the
+ log level check if the integer value of its log level is less
+ than or equal to the currently configured log level. That is,
+ the check passes if the event is equally or more severe than the
+ configured level. See section <seealso marker="#log_level">Log
+ Level</seealso> for a listing and description of all log
+ levels.</p>
+ <p>The primary log level can be overridden by a log level
+ configured per module. This is to, for instance, allow more
+ verbose logging from a specific part of the system.</p>
+ <p>Filter functions can be used for more sophisticated filtering
+ than the log level check provides. A filter function can stop or
+ pass a log event, based on any of the event's contents. It can
+ also modify all parts of the log event. See see
+ section <seealso marker="#filters">Filters</seealso> for more
+ details.</p>
+ <p>If a log event passes through all primary filters and all
+ handler filters for a specific handler, Logger forwards the
+ event to the <em>handler callback</em>. The handler formats and
+ prints the event to its destination. See
+ section <seealso marker="#handlers">Handlers</seealso> for more
+ details.</p>
+ <p>Everything up to and including the call to the handler
+ callbacks is executed on the client process, that is, the
+ process where the log event was issued. It is up to the handler
+ implementation if other processes are involved or not.</p>
+ <p>The handlers are called in sequence, and the order is not
+ defined.</p>
+ </section>
+ <section>
+ <marker id="logger_api"/>
+ <title>Logger API</title>
+ <p>The API for logging consists of a set
+ of <seealso marker="logger#macros">macros</seealso>, and a set
+ of functions on the form <c>logger:Level/1,2,3</c>, which are
+ all shortcuts
+ for <seealso marker="logger#log-2">
+ <c>logger:log(Level,Arg1[,Arg2[,Arg3]])</c></seealso>.</p>
+ <p>The difference between using the macros and the exported
+ functions is that macros add location (originator) information
+ to the metadata, and performs lazy evaluation by wrapping the
+ logger call in a case statement, so it is only evaluated if the
+ log level of the event passes the primary log level check.</p>
+ <section>
+ <marker id="log_level"/>
+ <title>Log Level</title>
+ <p>The log level indicates the severity of a event. In
+ accordance with the Syslog protocol,
+ <url href="https://www.ietf.org/rfc/rfc5424.txt">RFC
+ 5424</url>, eight log levels can be specified. The following
+ table lists all possible log levels by name (atom), integer
+ value, and description:</p>
+
+ <table align="left">
+ <row>
+ <cell><strong>Level</strong></cell>
+ <cell align="center"><strong>Integer</strong></cell>
+ <cell><strong>Description</strong></cell>
+ </row>
+ <row>
+ <cell>emergency</cell>
+ <cell align="center">0</cell>
+ <cell>system is unusable</cell>
+ </row>
+ <row>
+ <cell>alert</cell>
+ <cell align="center">1</cell>
+ <cell>action must be taken immediately</cell>
+ </row>
+ <row>
+ <cell>critical</cell>
+ <cell align="center">2</cell>
+ <cell>critical conditions</cell>
+ </row>
+ <row>
+ <cell>error</cell>
+ <cell align="center">3</cell>
+ <cell>error conditions</cell>
+ </row>
+ <row>
+ <cell>warning</cell>
+ <cell align="center">4</cell>
+ <cell>warning conditions</cell>
+ </row>
+ <row>
+ <cell>notice</cell>
+ <cell align="center">5</cell>
+ <cell>normal but significant conditions</cell>
+ </row>
+ <row>
+ <cell>info</cell>
+ <cell align="center">6</cell>
+ <cell>informational messages</cell>
+ </row>
+ <row>
+ <cell>debug</cell>
+ <cell align="center">7</cell>
+ <cell>debug-level messages</cell>
+ </row>
+ <tcaption>Log Levels</tcaption>
+ </table>
+ <p>Notice that the integer value is only used internally in
+ Logger. In the API, you must always use the atom. To compare
+ the severity of two log levels,
+ use <seealso marker="logger#compare_levels-2">
+ <c>logger:compare_levels/2</c></seealso>.</p>
+ </section>
+ <section>
+ <marker id="log_message"/>
+ <title>Log Message</title>
+ <p>The log message contains the information to be logged. The
+ message can consist of a format string and arguments (given as
+ two separate parameters in the Logger API), a string or a
+ report. The latter, which is either a map or a key-value list,
+ can be accompanied by a <em>report callback</em> specified in
+ the log event's <seealso marker="#metadata">metadata</seealso>.
+ The report callback is a convenience function that
+ the <seealso marker="#formatters">formatter</seealso> can use
+ to convert the report to a format string and arguments, or
+ directly to a string. The
+ formatter can also use its own conversion function, if no
+ callback is provided, or if a customized formatting is
+ desired.</p>
+ <p>The report callback must be a fun with one or two
+ arguments. If it takes one argument, this is the report
+ itself, and the fun returns a format string and arguments:</p>
+ <pre>fun((<seealso marker="logger#type-report"><c>logger:report()</c></seealso>) -> {<seealso marker="stdlib:io#type-format"><c>io:format()</c></seealso>,[term()]})</pre>
+ <p>If it takes two arguments, the first is the report, and the
+ second is a map containing extra data that allows direct
+ coversion to a string:</p>
+ <pre>fun((<seealso marker="logger#type-report"><c>logger:report()</c></seealso>,<seealso marker="logger#type-report_cb_config"><c>logger:report_cb_config()</c></seealso>) -> <seealso marker="stdlib:unicode#type-chardata"><c>unicode:chardata()</c></seealso>)
+ </pre>
+ <p>The fun must obey the <c>depth</c> and <c>chars_limit</c>
+ parameters provided in the second argument, as the formatter can
+ not do anything useful of these parameters with the returned
+ string. The extra data also contains a field named
+ <c>single_line</c>, indicating if the printed log message may
+ contain line breaks or not. This variant is used when the
+ formatting of the report depends on the size or single line
+ parameters.</p>
+ <p>Example, format string and arguments:</p>
+ <code>logger:error("The file does not exist: ~ts",[Filename])</code>
+ <p>Example, string:</p>
+ <code>logger:notice("Something strange happened!")</code>
+ <p>Example, report, and metadata with report callback:</p>
+ <code>
+logger:debug(#{got => connection_request, id => Id, state => State},
+ #{report_cb => fun(R) -> {"~p",[R]} end})</code>
+ <p>The log message can also be provided through a fun for lazy
+ evaluation. The fun is only evaluated if the primary log level
+ check passes, and is therefore recommended if it is expensive
+ to generate the message. The lazy fun must return a string, a
+ report, or a tuple with format string and arguments.</p>
+ </section>
+ <section>
+ <title>Metadata</title>
+ <p>Metadata contains additional data associated with a log
+ message. Logger inserts some metadata fields by default, and
+ the client can add custom metadata in two different ways:</p>
+ <taglist>
+ <tag>Set process metadata</tag>
+ <item>
+ <p>Process metadata is set and updated
+ with <seealso marker="logger#set_process_metadata-1">
+ <c>logger:set_process_metadata/1</c></seealso>
+ and <seealso marker="logger#update_process_metadata-1">
+ <c>logger:update_process_metadata/1</c></seealso>,
+ respectively. This metadata applies to the process on
+ which these calls are made, and Logger adds the metadata
+ to all log events issued on that process.</p>
+ </item>
+ <tag>Add metadata to a specific log event</tag>
+ <item>
+ <p>Metadata associated with one specific log event is given
+ as the last parameter to the log macro or Logger API
+ function when the event is issued. For example:</p>
+ <code>?LOG_ERROR("Connection closed",#{context => server})</code>
+ </item>
+ </taglist>
+ <p>See the description of
+ the <seealso marker="logger#type-metadata">
+ <c>logger:metadata()</c></seealso> type for information
+ about which default keys Logger inserts, and how the different
+ metadata maps are merged.</p>
+ </section>
+ </section>
+ <section>
+ <marker id="filter"/>
+ <title>Filters</title>
+ <p>Filters can be primary, or attached to a specific
+ handler. Logger calls the primary filters first, and if they all
+ pass, it calls the handler filters for each handler. Logger
+ calls the handler callback only if all filters attached to the
+ handler in question also pass.</p>
+ <p>A filter is defined as:</p>
+ <pre>{FilterFun, Extra}</pre>
+ <p>where <c>FilterFun</c> is a function of arity 2,
+ and <c>Extra</c> is any term. When applying the filter, Logger
+ calls the function with the log event as the first argument,
+ and the value of <c>Extra</c> as the second
+ argument. See <seealso marker="logger#type-filter">
+ <c>logger:filter()</c></seealso> for type definitions.</p>
+ <p>The filter function can return <c>stop</c>, <c>ignore</c> or
+ the (possibly modified) log event.</p>
+ <p>If <c>stop</c> is returned, the log event is immediately
+ discarded. If the filter is primary, no handler filters or
+ callbacks are called. If it is a handler filter, the
+ corresponding handler callback is not called, but the log event
+ is forwarded to filters attached to the next handler, if
+ any.</p>
+ <p>If the log event is returned, the next filter function is
+ called with the returned value as the first argument. That is,
+ if a filter function modifies the log event, the next filter
+ function receives the modified event. The value returned from
+ the last filter function is the value that the handler callback
+ receives.</p>
+ <p>If the filter function returns <c>ignore</c>, it means that it
+ did not recognize the log event, and thus leaves to other
+ filters to decide the event's destiny.</p>
+ <p>The configuration option <c>filter_default</c> specifies the
+ behaviour if all filter functions return <c>ignore</c>, or if no
+ filters exist. <c>filter_default</c> is by default set
+ to <c>log</c>, meaning that if all existing filters ignore a log
+ event, Logger forwards the event to the handler
+ callback. If <c>filter_default</c> is set to <c>stop</c>, Logger
+ discards such events.</p>
+ <p>Primary filters are added
+ with <seealso marker="logger#add_primary_filter-2">
+ <c>logger:add_primary_filter/2</c></seealso>
+ and removed
+ with <seealso marker="logger#remove_primary_filter-1">
+ <c>logger:remove_primary_filter/1</c></seealso>. They can also
+ be added at system start via the Kernel configuration
+ parameter <seealso marker="#logger_parameter"><c>logger</c></seealso>.</p>
+ <p>Handler filters are added
+ with <seealso marker="logger#add_handler_filter-3">
+ <c>logger:add_handler_filter/3</c></seealso>
+ and removed
+ with <seealso marker="logger#remove_handler_filter-2">
+ <c>logger:remove_handler_filter/2</c></seealso>. They can also
+ be specified directly in the configuration when adding a handler
+ with <seealso marker="logger#add_handler/3">
+ <c>logger:add_handler/3</c></seealso>
+ or via the Kernel configuration
+ parameter <seealso marker="#logger_parameter"><c>logger</c></seealso>.</p>
+
+ <p>To see which filters are currently installed in the system,
+ use <seealso marker="logger#get_config-0">
+ <c>logger:get_config/0</c></seealso>,
+ or <seealso marker="logger#get_primary_config-0">
+ <c>logger:get_primary_config/0</c></seealso>
+ and <seealso marker="logger#get_handler_config-1">
+ <c>logger:get_handler_config/1</c></seealso>. Filters are
+ listed in the order they are applied, that is, the first
+ filter in the list is applied first, and so on.</p>
+
+ <p>For convenience, the following built-in filters exist:</p>
+
+ <taglist>
+ <tag><seealso marker="logger_filters#domain-2">
+ <c>logger_filters:domain/2</c></seealso></tag>
+ <item>
+ <p>Provides a way of filtering log events based on a
+ <c>domain</c> field in <c>Metadata</c>.</p>
+ </item>
+ <tag><seealso marker="logger_filters#level-2">
+ <c>logger_filters:level/2</c></seealso></tag>
+ <item>
+ <p>Provides a way of filtering log events based on the log
+ level.</p>
+ </item>
+ <tag><seealso marker="logger_filters#progress-2">
+ <c>logger_filters:progress/2</c></seealso></tag>
+ <item>
+ <p>Stops or allows progress reports from <c>supervisor</c>
+ and <c>application_controller</c>.</p>
+ </item>
+ <tag><seealso marker="logger_filters#remote_gl-2">
+ <c>logger_filters:remote_gl/2</c></seealso></tag>
+ <item>
+ <p>Stops or allows log events originating from a process
+ that has its group leader on a remote node.</p>
+ </item>
+ </taglist>
+ </section>
+
+ <section>
+ <marker id="handlers"/>
+ <title>Handlers</title>
+ <p>A handler is defined as a module exporting at least the
+ following callback function:</p>
+
+ <pre><seealso marker="logger#HModule:log-2">log(LogEvent, Config) -> void()</seealso></pre>
+
+ <p>This function is called when a log event has passed through all
+ primary filters, and all handler filters attached to the handler
+ in question. The function call is executed on the client
+ process, and it is up to the handler implementation if other
+ processes are involved or not.</p>
+
+ <p>Logger allows adding multiple instances of a handler
+ callback. That is, if a callback module implementation allows
+ it, you can add multiple handler instances using the same
+ callback module. The different instances are identified by
+ unique handler identities.</p>
+
+ <p>In addition to the mandatory callback function <c>log/2</c>, a
+ handler module can export the optional callback
+ functions <c>adding_handler/1</c>, <c>changing_config/2</c>
+ and <c>removing_handler/1</c>. See
+ section <seealso marker="logger#handler_callback_functions">Handler
+ Callback Functions</seealso> in the logger(3) manual page for
+ more information about these function.</p>
+
+ <p>The following built-in handlers exist:</p>
+
+ <taglist>
+ <tag><c>logger_std_h</c></tag>
+ <item>
+ <p>This is the default handler used by OTP. Multiple instances
+ can be started, and each instance will write log events to a
+ given destination, terminal or file.</p>
+ </item>
+
+ <tag><c>logger_disk_log_h</c></tag>
+ <item>
+ <p>This handler behaves much like <c>logger_std_h</c>, except it uses
+ <seealso marker="disk_log"><c>disk_log</c></seealso> as its
+ destination.</p>
+ </item>
+
+ <tag><marker id="ErrorLoggerManager"/><c>error_logger</c></tag>
+ <item>
+ <p>This handler is provided for backwards compatibility
+ only. It is not started by default, but will be
+ automatically started the first time an <c>error_logger</c>
+ event handler is added
+ with <seealso marker="error_logger#add_report_handler-1">
+ <c>error_logger:add_report_handler/1,2</c></seealso>.</p>
+
+ <p>The old <c>error_logger</c> event handlers in STDLIB and
+ SASL still exist, but they are not added by Erlang/OTP 21.0
+ or later.</p>
+ </item>
+ </taglist>
+ </section>
+
+ <section>
+ <marker id="formatters"/>
+ <title>Formatters</title>
+ <p>A formatter can be used by the handler implementation to do the
+ final formatting of a log event, before printing to the
+ handler's destination. The handler callback receives the
+ formatter information as part of the handler configuration,
+ which is passed as the second argument
+ to <seealso marker="logger#HModule:log-2">
+ <c>HModule:log/2</c></seealso>.</p>
+ <p>The formatter information consist of a formatter
+ module, <c>FModule</c> and its
+ configuration, <c>FConfig</c>. <c>FModule</c> must export the
+ following function, which can be called by the handler:</p>
+ <pre><seealso marker="logger#FModule:format-2">format(LogEvent,FConfig)
+ -> FormattedLogEntry</seealso></pre>
+ <p>The formatter information for a handler is set as a part of its
+ configuration when the handler is added. It can also be changed
+ during runtime
+ with <seealso marker="logger#set_handler_config-3">
+ <c>logger:set_handler_config(HandlerId,formatter,{FModule,FConfig})</c>
+ </seealso>, which overwrites the current formatter information,
+ or with <seealso marker="logger#update_formatter_config-2">
+ <c>logger:update_formatter_config/2,3</c></seealso>, which
+ only modifies the formatter configuration.</p>
+ <p>If the formatter module exports the optional callback
+ function <seealso marker="logger#FModule:check_config-1">
+ <c>check_config(FConfig)</c></seealso>, Logger calls this
+ function when the formatter information is set or modified, to
+ verify the validity of the formatter configuration.</p>
+ <p>If no formatter information is specified for a handler, Logger
+ uses <c>logger_formatter</c> as default. See
+ the <seealso marker="logger_formatter"><c>logger_formatter(3)</c></seealso>
+ manual page for more information about this module.</p>
+ </section>
+
+ <section>
+ <title>Configuration</title>
+
+ <p>At system start, Logger is configured through Kernel
+ configuration parameters. The parameters that apply to Logger
+ are described in
+ section <seealso marker="#kernel_config_params">Kernel
+ Configuration Parameters</seealso>. Examples are found in
+ section <seealso marker="#config_examples">Configuration
+ Examples</seealso>.</p>
+ <p>During runtime, Logger configuration is changed via API
+ functions. See
+ section <seealso marker="logger#configuration_API">Configuration
+ API Functions</seealso> in the <c>logger(3)</c> manual page.</p>
+
+ <section>
+ <title>Primary Logger Configuration</title>
+ <p>Logger API functions that apply to the primary Logger
+ configuration are:</p>
+ <list>
+ <item><seealso marker="logger#get_primary_config-0">
+ <c>get_primary_config/0</c></seealso></item>
+ <item><seealso marker="logger#set_primary_config-1">
+ <c>set_primary_config/1,2</c></seealso></item>
+ <item><seealso marker="logger#update_primary_config-1">
+ <c>update_primary_config/1</c></seealso></item>
+ <item><seealso marker="logger#add_primary_filter-2">
+ <c>add_primary_filter/2</c></seealso></item>
+ <item><seealso marker="logger#remove_primary_filter-1">
+ <c>remove_primary_filter/1</c></seealso></item>
+ </list>
+ <p>The primary Logger configuration is a map with the following
+ keys:</p>
+ <taglist>
+ <tag><marker id="primary_level"/>
+ <c>level = </c><seealso marker="logger#type-level">
+ <c>logger:level()</c></seealso><c> | all | none</c></tag>
+ <item>
+ <p>Specifies the primary log level, that is, log event that
+ are equally or more severe than this level, are forwarded
+ to the primary filters. Less severe log events are
+ immediately discarded.</p>
+ <p>See section <seealso marker="#log_level">Log
+ Level</seealso> for a listing and description of
+ possible log levels.</p>
+ <p>The initial value of this option is set by the Kernel
+ configuration parameter <seealso marker="#logger_level">
+ <c>logger_level</c></seealso>. It is changed during
+ runtime with <seealso marker="logger#set_primary_config-2">
+ <c>logger:set_primary_config(level,Level)</c></seealso>.</p>
+ <p>Defaults to <c>notice</c>.</p>
+ </item>
+ <tag><c>filters = [{FilterId,Filter}]</c></tag>
+ <item>
+ <p>Specifies the primary filters.</p>
+ <list>
+ <item><c>FilterId = </c><seealso marker="logger#type-filter_id">
+ <c>logger:filter_id()</c></seealso></item>
+ <item><c>Filter = </c><seealso marker="logger#type-filter">
+ <c>logger:filter()</c></seealso></item>
+ </list>
+ <p>The initial value of this option is set by the Kernel
+ configuration
+ parameter <seealso marker="#logger_parameter"><c>logger</c></seealso>.
+ During runtime, primary filters are added and removed with
+ <seealso marker="logger#add_primary_filter-2">
+ <c>logger:add_primary_filter/2</c></seealso> and
+ <seealso marker="logger#remove_primary_filter-1">
+ <c>logger:remove_primary_filter/1</c></seealso>,
+ respectively.</p>
+ <p>See section <seealso marker="#filters">Filters</seealso>
+ for more detailed information.</p>
+ <p>Defaults to <c>[]</c>.</p>
+ </item>
+ <tag><c>filter_default = log | stop</c></tag>
+ <item>
+ <p>Specifies what happens to a log event if all filters
+ return <c>ignore</c>, or if no filters exist.</p>
+ <p>See section <seealso marker="#filters">Filters</seealso>
+ for more information about how this option is used.</p>
+ <p>Defaults to <c>log</c>.</p>
+ </item>
+ </taglist>
+ </section>
+
+ <section>
+ <marker id="handler_configuration"/>
+ <title>Handler Configuration</title>
+ <p>Logger API functions that apply to handler configuration
+ are:</p>
+ <list>
+ <item><seealso marker="logger#get_handler_config-0">
+ <c>get_handler_config/0,1</c></seealso></item>
+ <item><seealso marker="logger#set_handler_config-2">
+ <c>set_handler_config/2,3</c></seealso></item>
+ <item><seealso marker="logger#update_handler_config-2">
+ <c>update_handler_config/2</c></seealso></item>
+ <item><seealso marker="logger#add_handler_filter-3">
+ <c>add_handler_filter/3</c></seealso></item>
+ <item><seealso marker="logger#remove_handler_filter-2">
+ <c>remove_handler_filter/2</c></seealso></item>
+ <item><seealso marker="logger#update_formatter_config-2">
+ <c>update_formatter_config/2,3</c></seealso></item>
+ </list>
+ <p>The configuration for a handler is a map with the following keys:</p>
+ <taglist>
+ <tag><c>id = </c><seealso marker="logger#type-handler_id">
+ <c>logger:handler_id()</c></seealso></tag>
+ <item>
+ <p>Automatically inserted by Logger. The value is the same
+ as the <c>HandlerId</c> specified when adding the handler,
+ and it cannot be changed.</p>
+ </item>
+ <tag><c>module = module()</c></tag>
+ <item>
+ <p>Automatically inserted by Logger. The value is the same
+ as the <c>Module</c> specified when adding the handler,
+ and it cannot be changed.</p>
+ </item>
+ <tag><c>level = </c><seealso marker="logger#type-level">
+ <c>logger:level()</c></seealso><c> | all | none</c></tag>
+ <item>
+ <p>Specifies the log level for the handler, that is, log
+ events that are equally or more severe than this level,
+ are forwarded to the handler filters for this
+ handler.</p>
+ <p>See section <seealso marker="#log_level">Log
+ Level</seealso> for a listing and description of
+ possible log levels.</p>
+ <p>The log level is specified when adding the handler, or
+ changed during runtime with, for
+ instance, <seealso marker="logger#set_handler_config/3">
+ <c>logger:set_handler_config(HandlerId,level,Level)</c></seealso>.
+ </p>
+ <p>Defaults to <c>all</c>.</p>
+ </item>
+ <tag><c>filters = [{FilterId,Filter}]</c></tag>
+ <item>
+ <p>Specifies the handler filters.</p>
+ <list>
+ <item><c>FilterId = </c><seealso marker="logger#type-filter_id">
+ <c>logger:filter_id()</c></seealso></item>
+ <item><c>Filter = </c><seealso marker="logger#type-filter">
+ <c>logger:filter()</c></seealso></item>
+ </list>
+ <p>Handler filters are specified when adding the handler,
+ or added or removed during runtime with
+ <seealso marker="logger#add_handler_filter-3">
+ <c>logger:add_handler_filter/3</c></seealso> and
+ <seealso marker="logger#remove_handler_filter-2">
+ <c>logger:remove_handler_filter/2</c></seealso>,
+ respectively.</p>
+ <p>See <seealso marker="#filters">Filters</seealso> for more
+ detailed information.</p>
+ <p>Defaults to <c>[]</c>.</p>
+ </item>
+ <tag><c>filter_default = log | stop</c></tag>
+ <item>
+ <p>Specifies what happens to a log event if all filters
+ return <c>ignore</c>, or if no filters exist.</p>
+ <p>See section <seealso marker="#filters">Filters</seealso>
+ for more information about how this option is used.</p>
+ <p>Defaults to <c>log</c>.</p>
+ </item>
+ <tag><c>formatter = {FormatterModule,FormatterConfig}</c></tag>
+ <item>
+ <p>Specifies a formatter that the handler can use for
+ converting the log event term to a printable string.</p>
+ <list>
+ <item><c>FormatterModule = module()</c></item>
+ <item><c>FormatterConfig = </c>
+ <seealso marker="logger#type-formatter_config">
+ <c>logger:formatter_config()</c></seealso></item>
+ </list>
+ <p>The formatter information is specified when adding the
+ handler. The formatter configuration can be changed during
+ runtime
+ with <seealso marker="logger#update_formatter_config-2">
+ <c>logger:update_formatter_config/2,3</c></seealso>,
+ or the complete formatter information can be overwritten
+ with, for
+ instance, <seealso marker="logger#set_handler_config-3">
+ <c>logger:set_handler_config/3</c></seealso>.</p>
+ <p>See
+ section <seealso marker="#formatters">Formatters</seealso>
+ for more detailed information.</p>
+ <p>Defaults
+ to <c>{logger_formatter,DefaultFormatterConfig}</c>. See
+ the <seealso marker="logger_formatter">
+ <c>logger_formatter(3)</c></seealso> manual page for
+ information about this formatter and its default
+ configuration.</p>
+ </item>
+ <tag><c>config = term()</c></tag>
+ <item>
+ <p>Handler specific configuration, that is, configuration
+ data related to a specific handler implementation.</p>
+ <p>The configuration for the built-in handlers is described
+ in
+ the <seealso marker="logger_std_h"><c>logger_std_h(3)</c></seealso>
+ and
+ <seealso marker="logger_disk_log_h"><c>logger_disk_log_h(3)</c>
+ </seealso> manual pages.</p>
+ </item>
+ </taglist>
+
+ <p>Notice that <c>level</c> and <c>filters</c> are obeyed by
+ Logger itself before forwarding the log events to each
+ handler, while <c>formatter</c> and all handler specific
+ options are left to the handler implementation.</p>
+ </section>
+
+ <section>
+ <marker id="kernel_config_params"/>
+ <title>Kernel Configuration Parameters</title>
+
+ <p>The following Kernel configuration parameters apply to
+ Logger:</p>
+ <taglist>
+ <tag><marker id="logger_parameter"/><c>logger = [Config]</c></tag>
+ <item>
+ <p>Specifies the configuration
+ for <seealso marker="logger">Logger</seealso>, except the
+ primary log level, which is specified
+ with <seealso marker="#logger_level"><c>logger_level</c></seealso>,
+ and the compatibility
+ with <seealso marker="sasl:error_logging">SASL Error
+ Logging</seealso>, which is specified
+ with <seealso marker="#logger_sasl_compatible">
+ <c>logger_sasl_compatible</c></seealso>.</p>
+ <p>With this parameter, you can modify or disable the default
+ handler, add custom handlers and primary logger filters, and
+ set log levels per module.</p>
+ <p><c>Config</c> is any (zero or more) of the following:</p>
+ <taglist>
+ <tag><c>{handler, default, undefined}</c></tag>
+ <item>
+ <p>Disables the default handler. This allows another
+ application to add its own default handler.</p>
+ <p>Only one entry of this type is allowed.</p>
+ </item>
+ <tag><c>{handler, HandlerId, Module, HandlerConfig}</c></tag>
+ <item>
+ <p>If <c>HandlerId</c> is <c>default</c>, then this entry
+ modifies the default handler, equivalent to calling</p>
+ <pre><seealso marker="logger#set_handler_config-2">
+ logger:set_handler_config(default, Module, HandlerConfig)
+ </seealso></pre>
+ <p>For all other values of <c>HandlerId</c>, this entry
+ adds a new handler, equivalent to calling</p>
+ <pre><seealso marker="logger:add_handler/3">
+ logger:add_handler(HandlerId, Module, HandlerConfig)
+ </seealso></pre>
+ <p>Multiple entries of this type are allowed.</p></item>
+ <tag><c>{filters, FilterDefault, [Filter]}</c></tag>
+ <item>
+ <p>Adds the specified primary filters.</p>
+ <list>
+ <item><c>FilterDefault = log | stop</c></item>
+ <item><c>Filter = {FilterId, {FilterFun, FilterConfig}}</c></item>
+ </list>
+ <p>Equivalent to calling</p>
+ <pre><seealso marker="logger#add_primary_filter/2">
+ logger:add_primary_filter(FilterId, {FilterFun, FilterConfig})
+ </seealso></pre>
+ <p>for each <c>Filter</c>.</p>
+ <p><c>FilterDefault</c> specifies the behaviour if all
+ primary filters return <c>ignore</c>, see
+ section <seealso marker="#filters">Filters</seealso>.</p>
+ <p>Only one entry of this type is allowed.</p>
+ </item>
+ <tag><c>{module_level, Level, [Module]}</c></tag>
+ <item>
+ <p>Sets module log level for the given modules. Equivalent
+ to calling</p>
+ <pre><seealso marker="logger#set_module_level/2">
+ logger:set_module_level(Module, Level)</seealso></pre>
+ <p>for each <c>Module</c>.</p>
+ <p>Multiple entries of this type are allowed.</p>
+ </item>
+ </taglist>
+ <p>See
+ section <seealso marker="#config_examples">Configuration
+ Examples</seealso> for examples using the <c>logger</c>
+ parameter for system configuration.</p>
+ </item>
+ <tag><marker id="logger_level"/>
+ <c>logger_level = Level</c></tag>
+ <item>
+ <p>Specifies the primary log level. See
+ the <seealso marker="kernel_app#logger_level"><c>kernel(6)</c></seealso>
+ manual page for more information about this parameter.</p>
+ </item>
+ <tag><marker id="logger_sasl_compatible"/>
+ <c>logger_sasl_compatible = true | false</c></tag>
+ <item>
+ <p>Specifies Logger's compatibility
+ with <seealso marker="sasl:error_logging">SASL Error
+ Logging</seealso>. See
+ the <seealso marker="kernel_app#logger_sasl_compatible">
+ <c>kernel(6)</c></seealso> manual page for more
+ information about this parameter.</p>
+ </item>
+ </taglist>
+ </section>
+
+ <section>
+ <marker id="config_examples"/>
+ <title>Configuration Examples</title>
+ <p>The value of the Kernel configuration parameter <c>logger</c>
+ is a list of tuples. It is possible to write the term on the
+ command line when starting an erlang node, but as the term
+ grows, a better approach is to use the system configuration
+ file. See
+ the <seealso marker="config"><c>config(4)</c></seealso> manual
+ page for more information about this file.</p>
+ <p>Each of the following examples shows a simple system
+ configuration file that configures Logger according to the
+ description.</p>
+ <p>Modify the default handler to print to a file instead of
+ <c>standard_io</c>:</p>
+ <code>
+[{kernel,
+ [{logger,
+ [{handler, default, logger_std_h, % {handler, HandlerId, Module,
+ #{config => #{type => {file,"log/erlang.log"}}}} % Config}
+ ]}]}].
+ </code>
+ <p>Modify the default handler to print each log event as a
+ single line:</p>
+ <code>
+[{kernel,
+ [{logger,
+ [{handler, default, logger_std_h,
+ #{formatter => {logger_formatter, #{single_line => true}}}}
+ ]}]}].
+ </code>
+ <p>Modify the default handler to print the pid of the logging
+ process for each log event:</p>
+ <code>
+[{kernel,
+ [{logger,
+ [{handler, default, logger_std_h,
+ #{formatter => {logger_formatter,
+ #{template => [time," ",pid," ",msg,"\n"]}}}}
+ ]}]}].
+ </code>
+ <p>Modify the default handler to only print errors and more
+ severe log events to "log/erlang.log", and add another handler
+ to print all log events to "log/debug.log".</p>
+ <code>
+[{kernel,
+ [{logger,
+ [{handler, default, logger_std_h,
+ #{level => error,
+ config => #{type => {file, "log/erlang.log"}}}},
+ {handler, info, logger_std_h,
+ #{level => debug,
+ config => #{type => {file, "log/debug.log"}}}}
+ ]}]}].
+ </code>
+ </section>
+
+ </section>
+
+ <section>
+ <marker id="compatibility"/>
+ <title>Backwards Compatibility with error_logger</title>
+ <p>Logger provides backwards compatibility with
+ <c>error_logger</c> in the following ways:</p>
+
+ <taglist>
+ <tag>API for Logging</tag>
+ <item>
+ <p>The <c>error_logger</c> API still exists, but should only
+ be used by legacy code. It will be removed in a later
+ release.</p>
+ <p>Calls
+ to <seealso marker="error_logger#error_report-1">
+ <c>error_logger:error_report/1,2</c></seealso>,
+ <seealso marker="error_logger#error_msg-1">
+ <c>error_logger:error_msg/1,2</c></seealso>, and
+ corresponding functions for warning and info messages, are
+ all forwarded to Logger as calls
+ to <seealso marker="logger#log-3">
+ <c>logger:log(Level,Report,Metadata)</c></seealso>.</p>
+ <p><c>Level = error | warning | info</c> and is taken
+ from the function name. <c>Report</c> contains the actual
+ log message, and <c>Metadata</c> contains additional
+ information which can be used for creating backwards
+ compatible events for legacy <c>error_logger</c> event
+ handlers, see
+ section <seealso marker="#legacy_event_handlers">Legacy
+ Event Handlers</seealso>.</p>
+ </item>
+ <tag>Output Format</tag>
+ <item>
+ <p>To get log events on the same format as produced
+ by <c>error_logger_tty_h</c> and <c>error_logger_file_h</c>,
+ use the default formatter, <c>logger_formatter</c>, with
+ configuration parameter <c>legacy_header</c> set
+ to <c>true</c>. This is the default configuration of
+ the <c>default</c> handler started by Kernel.</p>
+ </item>
+ <tag>Default Format of Log Events from OTP</tag>
+ <item>
+ <p>By default, all log events originating from within OTP,
+ except the former so called "SASL reports", look the same as
+ before.</p>
+ </item>
+ <tag><marker id="sasl_reports"/>SASL Reports</tag>
+ <item>
+ <p>By SASL reports we mean supervisor reports, crash reports
+ and progress reports.</p>
+ <p>Prior to Erlang/OTP 21.0, these reports were only logged
+ when the SASL application was running, and they were printed
+ trough SASL's own event handlers <c>sasl_report_tty_h</c>
+ and <c>sasl_report_file_h</c>.</p>
+ <p>The destination of these log events was configured by
+ <seealso marker="sasl:sasl_app#deprecated_error_logger_config">SASL
+ configuration parameters</seealso>.</p>
+ <p>Due to the specific event handlers, the output format
+ slightly differed from other log events.</p>
+ <p>As of Erlang/OTP 21.0, the concept of SASL reports is
+ removed, meaning that the default behaviour is as
+ follows:</p>
+ <list>
+ <item>Supervisor reports, crash reports, and progress reports
+ are no longer connected to the SASL application.</item>
+ <item>Supervisor reports and crash reports are issued
+ as <c>error</c> level log events, and are logged through
+ the default handler started by Kernel.</item>
+ <item>Progress reports are issued as <c>info</c> level log
+ events, and since the default primary log level
+ is <c>notice</c>, these are not logged by default. To
+ enable printing of progress reports, set
+ the <seealso marker="#primary_level">primary log
+ level</seealso> to <c>info</c>.</item>
+ <item>The output format is the same for all log
+ events.</item>
+ </list>
+ <p>If the old behaviour is preferred, the Kernel configuration
+ parameter <seealso marker="kernel_app#logger_sasl_compatible">
+ <c>logger_sasl_compatible</c></seealso> can be set
+ to <c>true</c>. The
+ <seealso marker="sasl:sasl_app#deprecated_error_logger_config">SASL
+ configuration parameters</seealso> can then be used as
+ before, and the SASL reports will only be printed if the
+ SASL application is running, through a second log handler
+ named <c>sasl</c>.</p>
+ <p>All SASL reports have a metadata field <c>domain</c> which
+ is set to <c>[otp,sasl]</c>. This field can be
+ used by filters to stop or allow the log events.</p>
+ <p>See section <seealso marker="sasl:error_logging">SASL User's
+ Guide</seealso> for more information about the old SASL
+ error logging functionality.</p>
+ </item>
+ <tag><marker id="legacy_event_handlers"/>Legacy Event Handlers</tag>
+ <item>
+ <p>To use event handlers written for <c>error_logger</c>, just
+ add your event handler with</p>
+ <code>
+error_logger:add_report_handler/1,2.
+ </code>
+ <p>This automatically starts the error logger event manager,
+ and adds <c>error_logger</c> as a handler to Logger, with
+ the following configuration:</p>
+<code>
+#{level => info,
+ filter_default => log,
+ filters => []}.
+</code>
+ <note>
+ <p>This handler ignores events that do not originate from
+ the <c>error_logger</c> API, or from within OTP. This
+ means that if your code uses the Logger API for logging,
+ then your log events will be discarded by this
+ handler.</p>
+ <p>The handler is not overload protected.</p>
+ </note>
+ </item>
+ </taglist>
+ </section>
+
+
+ <section>
+ <title>Error Handling</title>
+ <p>Logger does, to a certain extent, check its input data before
+ forwarding a log event to filters and handlers. It does,
+ however, not evaluate report callbacks, or check the validity of
+ format strings and arguments. This means that all filters and
+ handlers must be careful when formatting the data of a log
+ event, making sure that it does not crash due to bad input data
+ or faulty callbacks.</p>
+ <p>If a filter or handler still crashes, Logger will remove the
+ filter or handler in question from the configuration, and print
+ a short error message to the terminal. A debug event containing
+ the crash reason and other details is also issued.</p>
+ <p>See section <seealso marker="#log_message">Log
+ Message</seealso> for more information about report callbacks
+ and valid forms of log messages.</p>
+ </section>
+
+ <section>
+ <title>Example: Add a handler to log info events to file</title>
+ <p>When starting an Erlang node, the default behaviour is that all
+ log events on level <c>notice</c> or more severe, are logged to
+ the terminal via the default handler. To also log info events,
+ you can either change the primary log level to <c>info</c>:</p>
+ <pre>
+1> <input>logger:set_primary_config(level, info).</input>
+ok</pre>
+ <p>or set the level for one or a few modules only:</p>
+ <pre>
+2> <input>logger:set_module_level(mymodule, info).</input>
+ok</pre>
+ <p>This allows info events to pass through to the default handler,
+ and be printed to the terminal as well. If there are many info
+ events, it can be useful to print these to a file instead.</p>
+ <p>First, set the log level of the default handler
+ to <c>notice</c>, preventing it from printing info events to the
+ terminal:</p>
+ <pre>
+3> <input>logger:set_handler_config(default, level, notice).</input>
+ok</pre>
+ <p>Then, add a new handler which prints to file. You can use the
+ handler
+ module <seealso marker="logger_std_h"><c>logger_std_h</c></seealso>,
+ and specify type <c>{file,File}</c>.:</p>
+ <pre>
+4> <input>Config = #{config => #{type => {file,"./info.log"}}, level => info}.</input>
+#{config => #{type => {file,"./info.log"}},level => info}
+5> <input>logger:add_handler(myhandler, logger_std_h, Config).</input>
+ok</pre>
+ <p>Since <c>filter_default</c> defaults to <c>log</c>, this
+ handler now receives all log events. If you want info events
+ only in the file, you must add a filter to stop all non-info
+ events. The built-in
+ filter <seealso marker="logger_filters#level-2">
+ <c>logger_filters:level/2</c></seealso>
+ can do this:</p>
+ <pre>
+6> <input>logger:add_handler_filter(myhandler, stop_non_info,
+ {fun logger_filters:level/2, {stop, neq, info}}).</input>
+ok</pre>
+ <p>See section <seealso marker="#filters">Filters</seealso> for
+ more information about the filters and the <c>filter_default</c>
+ configuration parameter.</p>
+
+ </section>
+
+ <section>
+ <title>Example: Implement a handler</title>
+ <p>Section <seealso marker="logger#handler_callback_functions">Handler
+ Callback Functions</seealso> in the logger(3) manual page
+ describes the callback functions that can be implemented for a
+ Logger handler.</p>
+ <p>A handler callback module must export:</p>
+ <list>
+ <item><c>log(Log, Config)</c></item>
+ </list>
+ <p>It can optionally also export some, or all, of the following:</p>
+ <list>
+ <item><c>adding_handler(Config)</c></item>
+ <item><c>removing_handler(Config)</c></item>
+ <item><c>changing_config(OldConfig, NewConfig)</c></item>
+ </list>
+ <p>When a handler is added, by for example a call
+ to <seealso marker="logger#add_handler-3">
+ <c>logger:add_handler(Id, HModule, Config)</c></seealso>,
+ Logger first calls <c>HModule:adding_handler(Config)</c>. If
+ this function returns <c>{ok,Config1}</c>, Logger
+ writes <c>Config1</c> to the configuration database, and
+ the <c>logger:add_handler/3</c> call returns. After this, the
+ handler is installed and must be ready to receive log events as
+ calls to <c>HModule:log/2</c>.</p>
+ <p>A handler can be removed by calling
+ <seealso marker="logger#remove_handler-1">
+ <c>logger:remove_handler(Id)</c></seealso>. Logger calls
+ <c>HModule:removing_handler(Config)</c>, and removes the
+ handler's configuration from the configuration database.</p>
+ <p>When <seealso marker="logger#set_handler_config-2">
+ <c>logger:set_handler_config/2,3</c></seealso>
+ or <seealso marker="logger#update_handler_config/2">
+ <c>logger:update_handler_config/2</c></seealso> is called,
+ Logger
+ calls <c>HModule:changing_config(OldConfig, NewConfig)</c>. If
+ this function returns <c>{ok,NewConfig1}</c>, Logger
+ writes <c>NewConfig1</c> to the configuration database.</p>
+
+ <p>A simple handler that prints to the terminal can be implemented
+ as follows:</p>
+ <code>
+-module(myhandler1).
+-export([log/2]).
+
+log(LogEvent, #{formatter := {FModule, FConfig}}) ->
+ io:put_chars(FModule:format(LogEvent, FConfig)).
+ </code>
+
+ <p>Notice that the above handler does not have any overload
+ protection, and all log events are printed directly from the
+ client process.</p>
+ <p>For information and examples of overload protection, please
+ refer to
+ section <seealso marker="#overload_protection">Protecting the
+ Handler from Overload</seealso>, and the implementation
+ of <seealso marker="logger_std_h"><c>logger_std_h</c></seealso>
+ and <seealso marker="logger_disk_log_h"><c>logger_disk_log_h</c>
+ </seealso>.</p>
+ <p>The following is a simpler example of a handler which logs to a
+ file through one single process:</p>
+ <code>
+-module(myhandler2).
+-export([adding_handler/1, removing_handler/1, log/2]).
+-export([init/1, handle_call/3, handle_cast/2, terminate/2]).
+
+adding_handler(Config) ->
+ MyConfig = maps:get(config,Config,#{file => "myhandler2.log"}),
+ {ok, Pid} = gen_server:start(?MODULE, MyConfig, []),
+ {ok, Config#{config => MyConfig#{pid => Pid}}}.
+
+removing_handler(#{config := #{pid := Pid}}) ->
+ gen_server:stop(Pid).
+
+log(LogEvent,#{config := #{pid := Pid}} = Config) ->
+ gen_server:cast(Pid, {log, LogEvent, Config}).
+
+init(#{file := File}) ->
+ {ok, Fd} = file:open(File, [append, {encoding, utf8}]),
+ {ok, #{file => File, fd => Fd}}.
+
+handle_call(_, _, State) ->
+ {reply, {error, bad_request}, State}.
+
+handle_cast({log, LogEvent, Config}, #{fd := Fd} = State) ->
+ do_log(Fd, LogEvent, Config),
+ {noreply, State}.
+
+terminate(_Reason, #{fd := Fd}) ->
+ _ = file:close(Fd),
+ ok.
+
+do_log(Fd, LogEvent, #{formatter := {FModule, FConfig}}) ->
+ String = FModule:format(LogEvent, FConfig),
+ io:put_chars(Fd, String).
+ </code>
+ </section>
+
+ <section>
+ <marker id="overload_protection"/>
+ <title>Protecting the Handler from Overload</title>
+ <p>The default handlers, <seealso marker="logger_std_h">
+ <c>logger_std_h</c></seealso> and <seealso marker="logger_disk_log_h">
+ <c>logger_disk_log_h</c></seealso>, feature an overload protection
+ mechanism, which makes it possible for the handlers to survive,
+ and stay responsive, during periods of high load (when huge
+ numbers of incoming log requests must be handled).
+ The mechanism works as follows:</p>
+
+ <section>
+ <title>Message Queue Length</title>
+ <p>The handler process keeps track of the length of its message
+ queue and takes some form of action when the current length exceeds a
+ configurable threshold. The purpose is to keep the handler in, or to
+ as quickly as possible get the handler into, a state where it can
+ keep up with the pace of incoming log events. The memory use of the
+ handler must never grow larger and larger, since that will eventually
+ cause the handler to crash. These three thresholds, with associated
+ actions, exist:</p>
+
+ <taglist>
+ <tag><c>sync_mode_qlen</c></tag>
+ <item>
+ <p>As long as the length of the message queue is lower than this
+ value, all log events are handled asynchronously. This means that
+ the client process sending the log event, by calling a log function
+ in the <seealso marker="logger_chapter#logger_api">Logger API</seealso>,
+ does not wait for a response from the handler but continues
+ executing immediately after the event is sent. It is not affected
+ by the time it takes the handler to print the event to the log
+ device. If the message queue grows larger than this value,
+ the handler starts handling log events synchronously instead,
+ meaning that the client process sending the event must wait for a
+ response. When the handler reduces the message queue to a
+ level below the <c>sync_mode_qlen</c> threshold, asynchronous
+ operation is resumed. The switch from asynchronous to synchronous
+ mode can slow down the logging tempo of one, or a few, busy senders,
+ but cannot protect the handler sufficiently in a situation of many
+ busy concurrent senders.</p>
+ <p>Defaults to <c>10</c> messages.</p>
+ </item>
+ <tag><c>drop_mode_qlen</c></tag>
+ <item>
+ <p>When the message queue grows larger than this threshold, the
+ handler switches to a mode in which it drops all new events that
+ senders want to log. Dropping an event in this mode means that the
+ call to the log function never results in a message being sent to
+ the handler, but the function returns without taking any action.
+ The handler keeps logging the events that are already in its message
+ queue, and when the length of the message queue is reduced to a level
+ below the threshold, synchronous or asynchronous mode is resumed.
+ Notice that when the handler activates or deactivates drop mode,
+ information about it is printed in the log.</p>
+ <p>Defaults to <c>200</c> messages.</p>
+ </item>
+ <tag><c>flush_qlen</c></tag>
+ <item>
+ <p>If the length of the message queue grows larger than this threshold,
+ a flush (delete) operation takes place. To flush events, the handler
+ discards the messages in the message queue by receiving them in a
+ loop without logging. Client processes waiting for a response from a
+ synchronous log request receive a reply from the handler indicating
+ that the request is dropped. The handler process increases its
+ priority during the flush loop to make sure that no new events
+ are received during the operation. Notice that after the flush operation
+ is performed, the handler prints information in the log about how many
+ events have been deleted.</p>
+ <p>Defaults to <c>1000</c> messages.</p>
+ </item>
+ </taglist>
+
+ <p>For the overload protection algorithm to work properly, it is
+ required that:</p>
+
+ <p><c>sync_mode_qlen =&lt; drop_mode_qlen =&lt; flush_qlen</c></p>
+
+ <p>and that:</p>
+
+ <p><c>drop_mode_qlen &gt; 1</c></p>
+
+ <p>To disable certain modes, do the following:</p>
+ <list>
+ <item>If <c>sync_mode_qlen</c> is set to <c>0</c>, all log events are handled
+ synchronously. That is, asynchronous logging is disabled.</item>
+ <item>If <c>sync_mode_qlen</c> is set to the same value as
+ <c>drop_mode_qlen</c>, synchronous mode is disabled. That is, the handler
+ always runs in asynchronous mode, unless dropping or flushing is invoked.</item>
+ <item>If <c>drop_mode_qlen</c> is set to the same value as <c>flush_qlen</c>,
+ drop mode is disabled and can never occur.</item>
+ </list>
+
+ <p>During high load scenarios, the length of the handler message queue
+ rarely grows in a linear and predictable way. Instead, whenever the
+ handler process is scheduled in, it can have an almost arbitrary number
+ of messages waiting in the message queue. It is for this reason that the overload
+ protection mechanism is focused on acting quickly, and quite drastically,
+ such as immediately dropping or flushing messages, when a large queue length
+ is detected.</p>
+
+ <p>The values of the previously listed thresholds can be specified by the user.
+ This way, a handler can be configured to, for example, not drop or flush
+ messages unless the message queue length of the handler process grows extremely
+ large. Notice that large amounts of memory can be required for the node under such
+ circumstances. Another example of user configuration is when, for performance
+ reasons, the client processes must never be blocked by synchronous log requests.
+ It is possible, perhaps, that dropping or flushing events is still acceptable, since
+ it does not affect the performance of the client processes sending the log events.</p>
+
+ <p>A configuration example:</p>
+ <code type="none">
+logger:add_handler(my_standard_h, logger_std_h,
+ #{config => #{type => {file,"./system_info.log"},
+ sync_mode_qlen => 100,
+ drop_mode_qlen => 1000,
+ flush_qlen => 2000}}).
+ </code>
+ </section>
+
+ <section>
+ <title>Controlling Bursts of Log Requests</title>
+ <p>Large bursts of log events - many events received by the handler
+ under a short period of time - can potentially cause problems, such as:</p>
+ <list>
+ <item>Log files grow very large, very quickly.</item>
+ <item>Circular logs wrap too quickly so that important data is overwritten.</item>
+ <item>Write buffers grow large, which slows down file sync operations.</item>
+ </list>
+
+ <p>For this reason, both built-in handlers offer the possibility to specify the
+ maximum number of events to be handled within a certain time frame.
+ With this burst control feature enabled, the handler can avoid choking the log with
+ massive amounts of printouts. The configuration parameters are:</p>
+ <taglist>
+ <tag><c>burst_limit_enable</c></tag>
+ <item>
+ <p>Value <c>true</c> enables burst control and <c>false</c> disables it.</p>
+ <p>Defaults to <c>true</c>.</p>
+ </item>
+ <tag><c>burst_limit_max_count</c></tag>
+ <item>
+ <p>This is the maximum number of events to handle within a
+ <c>burst_limit_window_time</c> time frame. After the limit is
+ reached, successive events are dropped until the end of the time frame.</p>
+ <p>Defaults to <c>500</c> events.</p>
+ </item>
+ <tag><c>burst_limit_window_time</c></tag>
+ <item>
+ <p>See the previous description of <c>burst_limit_max_count</c>.</p>
+ <p>Defaults to <c>1000</c> milliseconds.</p>
+ </item>
+ </taglist>
+
+ <p>A configuration example:</p>
+ <code type="none">
+logger:add_handler(my_disk_log_h, logger_disk_log_h,
+ #{config => #{file => "./my_disk_log",
+ burst_limit_enable => true,
+ burst_limit_max_count => 20,
+ burst_limit_window_time => 500}}).
+ </code>
+ </section>
+
+ <section>
+ <title>Terminating an Overloaded Handler</title>
+ <p>It is possible that a handler, even if it can successfully manage peaks
+ of high load without crashing, can build up a large message queue, or use a
+ large amount of memory. The overload protection mechanism includes an
+ automatic termination and restart feature for the purpose of guaranteeing
+ that a handler does not grow out of bounds. The feature is configured
+ with the following parameters:</p>
+ <taglist>
+ <tag><c>overload_kill_enable</c></tag>
+ <item>
+ <p>Value <c>true</c> enables the feature and <c>false</c> disables it.</p>
+ <p>Defaults to <c>false</c>.</p>
+ </item>
+ <tag><c>overload_kill_qlen</c></tag>
+ <item>
+ <p>This is the maximum allowed queue length. If the message queue grows
+ larger than this, the handler process is terminated.</p>
+ <p>Defaults to <c>20000</c> messages.</p>
+ </item>
+ <tag><c>overload_kill_mem_size</c></tag>
+ <item>
+ <p>This is the maximum memory size that the handler process is allowed to use.
+ If the handler grows larger than this, the process is terminated.</p>
+ <p>Defaults to <c>3000000</c> bytes.</p>
+ </item>
+ <tag><c>overload_kill_restart_after</c></tag>
+ <item>
+ <p>If the handler is terminated, it restarts automatically after a
+ delay specified in milliseconds. The value <c>infinity</c> prevents
+ restarts.</p>
+ <p>Defaults to <c>5000</c> milliseconds.</p>
+ </item>
+ </taglist>
+ <p>If the handler process is terminated because of overload, it prints
+ information about it in the log. It also prints information about when a
+ restart has taken place, and the handler is back in action.</p>
+ <note>
+ <p>The sizes of the log events affect the memory needs of the handler.
+ For information about how to limit the size of log events, see the
+ <seealso marker="logger_formatter"><c>logger_formatter(3)</c></seealso>
+ manual page.</p>
+ </note>
+ </section>
+ </section>
+
+ <section>
+ <title>See Also</title>
+ <p>
+ <seealso marker="disk_log"><c>disk_log(3)</c></seealso>,
+ <seealso marker="error_logger"><c>error_logger(3)</c></seealso>,
+ <seealso marker="logger"><c>logger(3)</c></seealso>,
+ <seealso marker="logger_disk_log_h"><c>logger_disk_log_h(3)</c></seealso>,
+ <seealso marker="logger_filters"><c>logger_filters(3)</c></seealso>,
+ <seealso marker="logger_formatter"><c>logger_formatter(3)</c></seealso>,
+ <seealso marker="logger_std_h"><c>logger_std_h(3)</c></seealso>,
+ <seealso marker="sasl:sasl_app"><c>sasl(6)</c></seealso></p>
+ </section>
+</chapter>
diff --git a/lib/kernel/doc/src/logger_disk_log_h.xml b/lib/kernel/doc/src/logger_disk_log_h.xml
new file mode 100644
index 0000000000..dfe2ab3275
--- /dev/null
+++ b/lib/kernel/doc/src/logger_disk_log_h.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2017</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>logger_disk_log_h</title>
+ <prepared></prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev>A</rev>
+ <file>logger_disk_log_h.xml</file>
+ </header>
+ <module>logger_disk_log_h</module>
+ <modulesummary>A disk_log based handler for Logger</modulesummary>
+
+ <description>
+ <p>This is a handler for Logger that offers circular
+ (wrapped) logs by using <seealso marker="disk_log"><c>disk_log</c></seealso>.
+ Multiple instances of this handler can be added to Logger, and each instance
+ prints to its own disk log file, created with the name and settings specified
+ in the handler configuration.</p>
+ <p>The default standard handler,
+ <seealso marker="logger_std_h"><c>logger_std_h</c></seealso>, can be
+ replaced by a disk_log handler at startup of the Kernel application.
+ See an example of this below.</p>
+ <p>The handler has an overload protection mechanism that keeps the handler
+ process and the Kernel application alive during high loads of log
+ events. How overload protection works, and how to configure it, is
+ described in the
+ <seealso marker="logger_chapter#overload_protection"><c>User's Guide</c>
+ </seealso>.</p>
+ <p>To add a new instance of the disk_log handler, use
+ <seealso marker="logger#add_handler-3"><c>logger:add_handler/3</c>
+ </seealso>. The handler configuration argument is a map which can contain
+ general configuration parameters, as documented in the
+ <seealso marker="logger_chapter#handler_configuration"><c>User's Guide</c>
+ </seealso>, and handler specific parameters. The specific data
+ is stored in a sub map with the key <c>config</c>, and can contain the
+ following parameters:</p>
+ <taglist>
+ <tag><c>file</c></tag>
+ <item>
+ <p>This is the full name of the disk log file. The option
+ corresponds to the <c>name</c> property in the
+ <seealso marker="disk_log#open-1"><c>dlog_option()</c></seealso>
+ datatype.</p>
+ </item>
+ <tag><c>type</c></tag>
+ <item>
+ <p>This is the disk log type, <c>wrap</c> or <c>halt</c>. The option
+ corresponds to the <c>type</c> property in the
+ <seealso marker="disk_log#open-1"><c>dlog_option()</c></seealso>
+ datatype.</p>
+ <p>Defaults to <c>wrap</c>.</p>
+ </item>
+ <tag><c>max_no_files</c></tag>
+ <item>
+ <p>This is the maximum number of files that disk_log uses
+ for its circular logging. The option
+ corresponds to the <c>MaxNoFiles</c> element in the <c>size</c> property in the
+ <seealso marker="disk_log#open-1"><c>dlog_option()</c></seealso>
+ datatype.</p>
+ <p>Defaults to <c>10</c>.</p>
+ <p>The setting has no effect on a halt log.</p>
+ </item>
+ <tag><c>max_no_bytes</c></tag>
+ <item>
+ <p>This is the maximum number of bytes that is written to
+ a log file before disk_log proceeds with the next file in order, or
+ generates an error in case of a full halt log. The option
+ corresponds to the <c>MaxNoBytes</c> element in the <c>size</c> property in the
+ <seealso marker="disk_log#open-1"><c>dlog_option()</c></seealso>
+ datatype.</p>
+ <p>Defaults to <c>1048576</c> bytes for a wrap log, and
+ <c>infinity</c> for a halt log.</p>
+ </item>
+ <tag><c>filesync_repeat_interval</c></tag>
+ <item>
+ <p>This value, in milliseconds, specifies how often the handler does
+ a disk_log sync operation to write buffered data to disk. The handler attempts
+ the operation repeatedly, but only performs a new sync if something has
+ actually been logged.</p>
+ <p>Defaults to <c>5000</c> milliseconds.</p>
+ <p>If <c>no_repeat</c> is set as value, the repeated sync operation
+ is disabled. The user can also call the
+ <seealso marker="logger_disk_log_h#filesync-1"><c>filesync/1</c>
+ </seealso> function to perform a disk_log sync.</p>
+ </item>
+ </taglist>
+ <p>Other configuration parameters exist, to be used for customizing
+ the overload protection behaviour. The same parameters are used both in the
+ standard handler and the disk_log handler, and are documented in the
+ <seealso marker="logger_chapter#overload_protection"><c>User's Guide</c>
+ </seealso>.</p>
+ <p>Notice that when changing the configuration of the handler in runtime, the
+ disk_log options (<c>file</c>, <c>type</c>, <c>max_no_files</c>,
+ <c>max_no_bytes</c>) must not be modified.</p>
+ <p>Example of adding a disk_log handler:</p>
+ <code type="none">
+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},
+ filesync_repeat_interval => 1000}}).
+ </code>
+ <p>To use the disk_log handler instead of the default standard
+ handler when starting an Erlang node, change the Kernel default logger to
+ use <c>logger_disk_log_h</c>. Example:</p>
+ <code type="none">
+erl -kernel logger '[{handler,default,logger_disk_log_h,
+ #{config => #{file => "./system_disk_log"}}}]'
+ </code>
+ </description>
+
+ <funcs>
+
+ <func>
+ <name name="filesync" arity="1" clause_i="1"/>
+ <fsummary>Writes buffered data to disk.</fsummary>
+ <desc>
+ <p>Write buffered data to disk.</p>
+ </desc>
+ </func>
+
+ </funcs>
+
+ <section>
+ <title>See Also</title>
+ <p><seealso marker="logger"><c>logger(3)</c></seealso>,
+ <seealso marker="logger_std_h"><c>logger_std_h(3)</c></seealso>,
+ <seealso marker="disk_log"><c>disk_log(3)</c></seealso></p>
+ </section>
+</erlref>
+
+
diff --git a/lib/kernel/doc/src/logger_filters.xml b/lib/kernel/doc/src/logger_filters.xml
new file mode 100644
index 0000000000..90f1fcc270
--- /dev/null
+++ b/lib/kernel/doc/src/logger_filters.xml
@@ -0,0 +1,254 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>logger_filters</title>
+ <prepared></prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev>A</rev>
+ <file>logger_filters.xml</file>
+ </header>
+ <module>logger_filters</module>
+ <modulesummary>Filters to use with Logger.</modulesummary>
+
+ <description>
+ <p>All functions exported from this module can be used as primary
+ or handler
+ filters. See <seealso marker="logger#add_primary_filter-2">
+ <c>logger:add_primary_filter/2</c></seealso>
+ and <seealso marker="logger#add_handler_filter-3">
+ <c>logger:add_handler_filter/3</c></seealso> for more information
+ about how filters are added.</p>
+ <p>Filters are removed with <seealso marker="logger#remove_primary_filter-1">
+ <c>logger:remove_primary_filter/1</c></seealso>
+ and <seealso marker="logger#remove_handler_filter-2">
+ <c>logger:remove_handler_filter/2</c></seealso>.</p>
+ </description>
+
+ <funcs>
+ <func>
+ <name name="domain" arity="2"/>
+ <fsummary>Filter log events based on the domain field in
+ metadata.</fsummary>
+ <desc>
+ <p>This filter provides a way of filtering log events based on a
+ <c>domain</c> field in <c>Metadata</c>. This field is
+ optional, and the purpose of using it is to group log events
+ from, for example, a specific functional area. This allows
+ filtering or other specialized treatment in a Logger
+ handler.</p>
+
+ <p>A domain field must be a list of atoms, creating smaller
+ and more specialized domains as the list grows longer. The
+ greatest domain is <c>[]</c>, which comprises all possible
+ domains.</p>
+
+ <p>For example, consider the following domains:</p>
+ <pre>
+D1 = [otp]
+D2 = [otp, sasl]</pre>
+
+ <p><c>D1</c> is the greatest of the two, and is said to be a
+ super-domain of <c>D2</c>. <c>D2</c> is a
+ sub-domain <c>D1</c>. Both <c>D1</c> and <c>D2</c> are
+ sub-domains of <c>[]</c>.</p>
+
+ <p>The above domains are used for logs originating from
+ Erlang/OTP. D1 specifies that the log event comes from
+ Erlang/OTP in general, and D2 indicates that the log event
+ is a so
+ called <seealso marker="logger_chapter#sasl_reports">SASL
+ report</seealso>.</p>
+
+ <p>The <c><anno>Extra</anno></c> parameter to
+ the <c>domain/2</c> function is specified when adding the
+ filter via <seealso marker="logger#add_primary_filter-2">
+ <c>logger:add_primary_filter/2</c></seealso>
+ or <seealso marker="logger#add_handler_filter-3">
+ <c>logger:add_handler_filter/3</c></seealso>.</p>
+
+ <p>The filter compares the value of the <c>domain</c> field in
+ the log event's metadata (<c>Domain</c>) against
+ <c><anno>MatchDomain</anno></c>. The filter matches if the
+ value of <c>Compare</c> is:</p>
+
+ <taglist>
+ <tag><c>sub</c></tag>
+ <item>
+ <p>and <c>Domain</c> is equal to or a sub-domain
+ of <c>MatchDomain</c>, that is, if <c>MatchDomain</c> is
+ a prefix of <c>Domain</c>.</p>
+ </item>
+ <tag><c>super</c></tag>
+ <item>
+ <p>and <c>Domain</c> is equal to or a super-domain
+ of <c>MatchDomain</c>, that is, if <c>Domain</c> is a
+ prefix of <c>MatchDomain</c>.</p>
+ </item>
+ <tag><c>equal</c></tag>
+ <item>
+ <p>and <c>Domain</c> is equal to <c>MatchDomain</c>.</p>
+ </item>
+ <tag><c>not_equal</c></tag>
+ <item>
+ <p>and <c>Domain</c> differs from <c>MatchDomain</c>, or
+ if there is no domain field in metadata.</p>
+ </item>
+ <tag><c>undefined</c></tag>
+ <item>
+ <p>and there is no domain field in metadata. In this
+ case <c><anno>MatchDomain</anno></c> must be set
+ to <c>[]</c>.</p>
+ </item>
+ </taglist>
+
+ <p>If the filter matches and <c><anno>Action</anno></c> is
+ <c>log</c>, the log event is allowed. If the filter matches
+ and <c><anno>Action</anno></c> is <c>stop</c>, the log event
+ is stopped.</p>
+
+ <p>If the filter does not match, it returns <c>ignore</c>,
+ meaning that other filters, or the value of the
+ configuration parameter <c>filter_default</c>, decide if the
+ event is allowed or not.</p>
+
+ <p>Log events that do not contain any domain field, match only
+ when <c><anno>Compare</anno></c> is equal
+ to <c>undefined</c> or <c>not_equal</c>.</p>
+
+ <p>Example: stop all events with domain <c>[otp,
+ sasl | _]</c></p>
+
+ <code>
+logger:set_handler_config(h1, filter_default, log). % this is the default
+Filter = {fun logger_filters:domain/2, {stop, sub, [otp, sasl]}}.
+logger:add_handler_filter(h1, no_sasl, Filter).
+ok</code>
+ </desc>
+ </func>
+
+ <func>
+ <name name="level" arity="2"/>
+ <fsummary>Filter log events based on the log level.</fsummary>
+ <desc>
+ <p>This filter provides a way of filtering log events based
+ on the log level. It matches log events by comparing the
+ log level with a specified <c>MatchLevel</c></p>
+
+ <p>The <c><anno>Extra</anno></c> parameter is specified when
+ adding the filter
+ via <seealso marker="logger#add_primary_filter-2">
+ <c>logger:add_primary_filter/2</c></seealso>
+ or <seealso marker="logger#add_handler_filter-3">
+ <c>logger:add_handler_filter/3</c></seealso>.</p>
+
+ <p>The filter compares the value of the event's log level
+ (<c>Level</c>) to <c><anno>MatchLevel</anno></c> by
+ calling <seealso marker="logger#compare_levels-2">
+ <c>logger:compare_levels(Level, MatchLevel)</c></seealso>.
+ The filter matches if the value
+ of <c><anno>Operator</anno></c> is:</p>
+
+ <taglist>
+ <tag><c>neq</c></tag>
+ <item><p>and the compare function returns <c>lt</c>
+ or <c>gt</c>.</p></item>
+ <tag><c>eq</c></tag>
+ <item><p>and the compare function returns <c>eq</c>.</p></item>
+ <tag><c>lt</c></tag>
+ <item><p>and the compare function returns <c>lt</c>.</p></item>
+ <tag><c>gt</c></tag>
+ <item><p>and the compare function returns <c>gt</c>.</p></item>
+ <tag><c>lteq</c></tag>
+ <item><p>and the compare function returns <c>lt</c>
+ or <c>eq</c>.</p></item>
+ <tag><c>gteq</c></tag>
+ <item><p>and the compare function returns <c>gt</c>
+ or <c>eq</c>.</p></item>
+ </taglist>
+
+ <p>If the filter matches and <c><anno>Action</anno></c> is
+ <c>log</c>, the log event is allowed. If the filter
+ matches and <c><anno>Action</anno></c> is <c>stop</c>, the
+ log event is stopped.</p>
+
+ <p>If the filter does not match, it returns <c>ignore</c>,
+ meaning that other filters, or the value of the
+ configuration parameter <c>filter_default</c>, will decide
+ if the event is allowed or not.</p>
+
+ <p>Example: only allow debug level log events</p>
+
+ <code>
+logger:set_handler_config(h1, filter_default, stop).
+Filter = {fun logger_filters:level/2, {log, eq, debug}}.
+logger:add_handler_filter(h1, debug_only, Filter).
+ok</code>
+ </desc>
+ </func>
+
+ <func>
+ <name name="progress" arity="2"/>
+ <fsummary>Filter progress reports from supervisor and application_controller.</fsummary>
+ <desc>
+ <p>This filter matches all progress reports
+ from <c>supervisor</c> and <c>application_controller</c>.</p>
+
+ <p>If <c><anno>Extra</anno></c> is <c>log</c>, the progress
+ reports are allowed. If <c><anno>Extra</anno></c>
+ is <c>stop</c>, the progress reports are stopped.</p>
+
+ <p>The filter returns <c>ignore</c> for all other log events.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="remote_gl" arity="2"/>
+ <fsummary>Filter events with group leader on remote node.</fsummary>
+ <desc>
+ <p>This filter matches all events originating from a process
+ that has its group leader on a remote node.</p>
+
+ <p>If <c><anno>Extra</anno></c> is <c>log</c>, the matching
+ events are allowed. If <c><anno>Extra</anno></c>
+ is <c>stop</c>, the matching events are stopped.</p>
+
+ <p>The filter returns <c>ignore</c> for all other log events.</p>
+ </desc>
+ </func>
+
+ </funcs>
+
+ <section>
+ <title>See Also</title>
+ <p>
+ <seealso marker="logger"><c>logger(3)</c></seealso>
+ </p>
+ </section>
+</erlref>
+
+
diff --git a/lib/kernel/doc/src/logger_formatter.xml b/lib/kernel/doc/src/logger_formatter.xml
new file mode 100644
index 0000000000..24772fd6c4
--- /dev/null
+++ b/lib/kernel/doc/src/logger_formatter.xml
@@ -0,0 +1,354 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2017</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>logger_formatter</title>
+ <prepared></prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev>A</rev>
+ <file>logger_formatter.xml</file>
+ </header>
+ <module>logger_formatter</module>
+ <modulesummary>Default formatter for Logger.</modulesummary>
+
+ <description>
+ <p>Each Logger handler has a configured formatter specified as a
+ module and a configuration term. The purpose of the formatter is
+ to translate the log events to a final printable string
+ (<seealso marker="stdlib:unicode#type-chardata"><c>unicode:chardata()</c>
+ </seealso>) which can be written to the output device of the
+ handler. See
+ sections <seealso marker="logger_chapter#handlers">Handlers</seealso>
+ and <seealso marker="logger_chapter#formatters">Formatters</seealso>
+ in the Kernel User's Guide for more information.</p>
+ <p><c>logger_formatter</c> is the default formatter used by
+ Logger.</p>
+ </description>
+
+
+ <datatypes>
+ <datatype>
+ <name name="config"/>
+ <desc>
+ <p>The configuration term for <c>logger_formatter</c> is a
+ <seealso marker="stdlib:maps">map</seealso>, and the
+ following keys can be set as configuration parameters:</p>
+ <taglist>
+ <tag><marker id="chars_limit"/>
+ <c>chars_limit = integer() > 0 | unlimited</c></tag>
+ <item>
+ <p>A positive integer representing the value of the option
+ with the same name to be used when calling
+ <seealso marker="stdlib:io_lib#format-3">
+ <c>io_lib:format/3</c></seealso>.
+ This value limits the total number of characters printed
+ for each log event. Notice that this is a soft limit. For a
+ hard truncation limit, see option <c>max_size</c>.</p>
+ <p>Defaults to <c>unlimited</c>.</p>
+ </item>
+ <tag><marker id="depth"/><c>depth = integer() > 0 | unlimited</c></tag>
+ <item>
+ <p>A positive integer representing the maximum depth to
+ which terms shall be printed by this formatter. Format
+ strings passed to this formatter are rewritten. The
+ format controls ~p and ~w are replaced with ~P and ~W,
+ respectively, and the value is used as the depth
+ parameter. For details, see
+ <seealso marker="stdlib:io#format-2"><c>io:format/2,3</c></seealso>
+ in STDLIB.</p>
+ <p>Defaults to <c>unlimited</c>.</p>
+ </item>
+ <tag><c>legacy_header = boolean()</c></tag>
+ <item>
+ <p>If set to <c>true</c> a header field is added to
+ logger_formatter's part of <c>Metadata</c>. The value of
+ this field is a string similar to the header created by
+ the
+ old <seealso marker="error_logger"><c>error_logger</c></seealso>
+ event handlers. It can be included in the log event by
+ adding the list <c>[logger_formatter,header]</c> to the
+ template. See the description of
+ the <seealso marker="#type-template"><c>template()</c></seealso>
+ type for more information.</p>
+ <p>Defaults to <c>false</c>.</p>
+ </item>
+ <tag><marker id="max_size"/>
+ <c>max_size = integer() > 0 | unlimited</c></tag>
+ <item>
+ <p>A positive integer representing the absolute maximum size a
+ string returned from this formatter can have. If the
+ formatted string is longer, after possibly being limited
+ by <c>chars_limit</c> or <c>depth</c>, it is truncated.</p>
+ <p>Defaults to <c>unlimited</c>.</p>
+ </item>
+ <tag><c>report_cb = </c><seealso marker="logger#type-report_cb">
+ <c>logger:report_cb()</c></seealso></tag>
+ <item>
+ <p>A report callback is used by the formatter to transform
+ log messages on report form to a format string and
+ arguments. The report callback can be specified in the
+ metadata for the log event. If no report callback exists
+ in metadata, <c>logger_formatter</c> will
+ use <seealso marker="logger#format_report-1">
+ <c>logger:format_report/1</c></seealso> as default
+ callback.</p>
+ <p>If this configuration parameter is set, it replaces
+ both the default report callback, and any report
+ callback found in metadata. That is, all reports are
+ converted by this configured function.</p>
+ </item>
+ <tag><c>single_line = boolean()</c></tag>
+ <item>
+ <p>If set to <c>true</c>, each log event is printed as a
+ single line. To achieve this, <c>logger_formatter</c>
+ sets the field width to <c>0</c> for all <c>~p</c>
+ and <c>~P</c> control sequences in the format a string
+ (see <seealso marker="stdlib:io#format-2">
+ <c>io:format/2</c></seealso>), and replaces all
+ newlines in the message with <c>", "</c>. White spaces
+ following directly after newlines are removed. Notice
+ that newlines added by the <c>template</c> parameter are
+ not replaced.</p>
+ <p>Defaults to <c>true</c>.</p>
+ </item>
+ <tag><marker id="template"/>
+ <c>template = </c><seealso marker="#type-template"><c>template()</c>
+ </seealso></tag>
+ <item>
+ <p>The template describes how the formatted string is
+ composed by combining different data values from the log
+ event. See the description of
+ the <seealso marker="#type-template"><c>template()</c></seealso>
+ type for more information about this.</p>
+ </item>
+ <tag><c>time_designator = byte()</c></tag>
+ <item>
+ <p>Timestamps are formatted according to RFC3339, and the
+ time designator is the character used as date and time
+ separator.</p>
+ <p>Defaults to <c>$T</c>.</p>
+ <p>The value of this parameter is used as
+ the <c>time_designator</c> option
+ to <seealso marker="stdlib:calendar#system_time_to_rfc3339-2">
+ <c>calendar:system_time_to_rcf3339/2</c></seealso>.</p>
+ </item>
+ <tag><c>time_offset = integer() | [byte()]</c></tag>
+ <item>
+ <p>The time offset, either a string or an integer, to be
+ used when formatting the timestamp.</p>
+ <p>An empty string is interpreted as local time. The
+ values <c>"Z"</c>, <c>"z"</c> or <c>0</c> are
+ interpreted as Universal Coordinated Time (UTC).</p>
+ <p>Strings, other than <c>"Z"</c>, <c>"z"</c>,
+ or <c>""</c>, must be on the form <c>±[hh]:[mm]</c>, for
+ example <c>"-02:00"</c> or <c>"+00:00"</c>.</p>
+ <p>Integers must be in microseconds, meaning that the
+ offset <c>7200000000</c> is equivalent
+ to <c>"+02:00"</c>.</p>
+ <p>Defaults to an empty string, meaning that timestamps
+ are displayed in local time. However, for backwards
+ compatibility, if the SASL configuration
+ parameter <seealso marker="sasl:sasl_app#utc_log">
+ <c>utc_log</c></seealso><c>=true</c>, the default is
+ changed to <c>"Z"</c>, meaning that timestamps are displayed
+ in UTC.</p>
+ <p>The value of this parameter is used as
+ the <c>offset</c> option
+ to <seealso marker="stdlib:calendar#system_time_to_rfc3339-2">
+ <c>calendar:system_time_to_rcf3339/2</c></seealso>.</p>
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="metakey"/>
+ <desc>
+ <p></p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="template"/>
+ <desc>
+ <p>The template is a list of atoms, atom lists, tuples and strings. The
+ atoms <c>level</c> or <c>msg</c>, are treated as
+ placeholders for the severity level and the log message,
+ respectively. Other atoms or atom lists are interpreted as
+ placeholders for metadata, where atoms are expected to match
+ top level keys, and atom lists represent paths to sub keys when
+ the metadata is a nested map. For example the
+ list <c>[key1,key2]</c> is replaced by the value of
+ the <c>key2</c> field in the nested map below. The
+ atom <c>key1</c> on its own is replaced by the complete
+ value of the <c>key1</c> field. The values are converted to
+ strings.</p>
+
+ <code>
+#{key1 => #{key2 => my_value,
+ ...}
+ ...}</code>
+
+ <p>Tuples in the template express if-exist tests for metadata
+ keys. For example, the following tuple says that
+ if <c>key1</c> exists in the metadata map,
+ print <c>"key1=Value"</c>, where <c>Value</c> is the value
+ that <c>key1</c> is associated with in the metadata map. If
+ <c>key1</c> does not exist, print nothing.</p>
+ <code>
+{key1, ["key1=",key1], []}</code>
+
+ <p>Strings in the template are printed literally.</p>
+ <p>The default value for the <c>template</c> configuration
+ parameter depends on the value of the <c>single_line</c>
+ and <c>legacy_header</c> configuration parameters as
+ follows.</p>
+
+ <p>The log event used in the examples is:</p>
+ <code>
+?LOG_ERROR("name: ~p~nexit_reason: ~p", [my_name, "It crashed"])</code>
+
+ <taglist>
+ <tag><c>legacy_header = true, single_line = false</c></tag>
+ <item>
+ <p>Default
+ template: <c>[[logger_formatter,header],"\n",msg,"\n"]</c></p>
+
+ <p>Example log entry:</p>
+ <code type="none">
+=ERROR REPORT==== 17-May-2018::18:30:19.453447 ===
+name: my_name
+exit_reason: "It crashed"</code>
+
+ <p>Notice that all eight levels can occur in the heading,
+ not only <c>ERROR</c>, <c>WARNING</c> or <c>INFO</c> as
+ <seealso marker="error_logger"><c>error_logger</c></seealso>
+ produces. And microseconds are added at the end of the
+ timestamp.</p>
+ </item>
+
+ <tag><c>legacy_header = true, single_line = true</c></tag>
+ <item>
+ <p>Default
+ template: <c>[[logger_formatter,header],"\n",msg,"\n"]</c></p>
+
+ <p>Notice that the template is here the same as
+ for <c>single_line=false</c>, but the resulting log entry
+ differs in that there is only one line after the
+ heading:</p>
+ <code type="none">
+=ERROR REPORT==== 17-May-2018::18:31:06.952665 ===
+name: my_name, exit_reason: "It crashed"</code>
+ </item>
+
+ <tag><c>legacy_header = false, single_line = true</c></tag>
+ <item>
+ <p>Default template: <c>[time," ",level,": ",msg,"\n"]</c></p>
+
+ <p>Example log entry:</p>
+ <code type="none">
+2018-05-17T18:31:31.152864+02:00 error: name: my_name, exit_reason: "It crashed"</code>
+ </item>
+
+ <tag><c>legacy_header = false, single_line = false</c></tag>
+ <item>
+ <p>Default template: <c>[time," ",level,":\n",msg,"\n"]</c></p>
+
+ <p>Example log entry:</p>
+ <code type="none">
+2018-05-17T18:32:20.105422+02:00 error:
+name: my_name
+exit_reason: "It crashed"</code>
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+ </datatypes>
+
+ <funcs>
+ <func>
+ <name name="check_config" arity="1"/>
+ <fsummary>Validates the given formatter configuration.</fsummary>
+ <desc>
+ <p>The function is called by Logger when the formatter
+ configuration for a handler is set or modified. It
+ returns <c>ok</c> if the configuration is valid,
+ and <c>{error,term()}</c> if it is faulty.</p>
+ <p>The following Logger API functions can trigger this callback:</p>
+ <list>
+ <item><seealso marker="logger#add_handler-3">
+ <c>logger:add_handler/3</c></seealso></item>
+ <item><seealso marker="logger#set_handler_config-2">
+ <c>logger:set_handler_config/2,3</c></seealso></item>
+ <item><seealso marker="logger#update_handler_config-2">
+ <c>logger:updata_handler_config/2</c></seealso></item>
+ <item><seealso marker="logger#update_formatter_config-2">
+ <c>logger:update_formatter_config/2</c></seealso></item>
+ </list>
+ </desc>
+ </func>
+ <func>
+ <name name="format" arity="2"/>
+ <fsummary>Formats the given message.</fsummary>
+ <desc>
+ <p>This the formatter callback function to be called from
+ handlers. The log event is processed as follows:</p>
+ <list>
+ <item>If the message is on report form, it is converted to
+ <c>{Format,Args}</c> by calling the report callback. See
+ section <seealso marker="logger_chapter#log_message">Log
+ Message</seealso> in the Kernel User's Guide for more
+ information about report callbacks and valid forms of log
+ messages.</item>
+ <item>The message size is limited according to the values of
+ configuration parameters <seealso marker="#chars_limit">
+ <c>chars_limit</c></seealso>
+ and <seealso marker="#depth"><c>depth</c></seealso>.</item>
+ <item>The full log entry is composed according to
+ the <seealso marker="#template"><c>template</c></seealso>.</item>
+ <item>If the final string is too long, it is truncated
+ according to the value of configuration
+ parameter <seealso marker="#max_size"><c>max_size</c></seealso>.</item>
+ </list>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <title>See Also</title>
+ <p>
+ <seealso marker="stdlib:calendar"><c>calendar(3)</c></seealso>,
+ <seealso marker="error_logger"><c>error_logger(3)</c></seealso>,
+ <seealso marker="stdlib:io"><c>io(3)</c></seealso>,
+ <seealso marker="stdlib:io_lib"><c>io_lib(3)</c></seealso>,
+ <seealso marker="logger"><c>logger(3)</c></seealso>,
+ <seealso marker="stdlib:maps"><c>maps(3)</c></seealso>,
+ <seealso marker="sasl:sasl_app"><c>sasl(6)</c></seealso>,
+ <seealso marker="stdlib:unicode"><c>unicode(3)</c></seealso>
+ </p>
+ </section>
+</erlref>
+
+
diff --git a/lib/kernel/doc/src/logger_std_h.xml b/lib/kernel/doc/src/logger_std_h.xml
new file mode 100644
index 0000000000..fcd8189bae
--- /dev/null
+++ b/lib/kernel/doc/src/logger_std_h.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2017</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>logger_std_h</title>
+ <prepared></prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev>A</rev>
+ <file>logger_std_h.xml</file>
+ </header>
+ <module>logger_std_h</module>
+ <modulesummary>Standard handler for Logger.</modulesummary>
+
+ <description>
+ <p>This is the standard handler for Logger.
+ Multiple instances of this handler can be added to
+ Logger, and each instance prints logs to <c>standard_io</c>,
+ <c>standard_error</c>, or to file.</p>
+ <p>The handler has an overload protection mechanism that keeps the handler
+ process and the Kernel application alive during high loads of log
+ events. How overload protection works, and how to configure it, is
+ described in the
+ <seealso marker="logger_chapter#overload_protection"><c>User's Guide</c>
+ </seealso>.</p>
+ <p>To add a new instance of the standard handler, use
+ <seealso marker="logger#add_handler-3"><c>logger:add_handler/3</c>
+ </seealso>. The handler configuration argument is a map which can contain
+ general configuration parameters, as documented in the
+ <seealso marker="logger_chapter#handler_configuration"><c>User's Guide</c>
+ </seealso>, and handler specific parameters. The specific data
+ is stored in a sub map with the key <c>config</c>, and can contain the
+ following parameters:</p>
+ <taglist>
+ <tag><marker id="type"/><c>type</c></tag>
+ <item>
+ <p>This has the value <c>standard_io</c>, <c>standard_error</c>,
+ <c>{file,LogFileName}</c>, or <c>{file,LogFileName,LogFileOpts}</c>.</p>
+ <p>If <c>LogFileOpts</c> is specified, it replaces the default
+ list of options used when opening the log file. The default
+ list is <c>[raw,append,delayed_write]</c>. One reason to do
+ so can be to change <c>append</c> to, for
+ example, <c>write</c>, ensuring that the old log is
+ truncated when a node is restarted. See the reference manual
+ for <seealso marker="file#open-2"><c>file:open/2</c></seealso>
+ for more information about file options.</p>
+ <p>Log files are always UTF-8 encoded. The encoding can not be
+ changed by setting the option <c>{encoding,Encoding}</c>
+ in <c>LogFileOpts</c>.</p>
+ <p>Notice that the standard handler does not have support for
+ circular logging. Use the disk_log handler,
+ <seealso marker="logger_disk_log_h"><c>logger_disk_log_h</c></seealso>,
+ for this.</p>
+ <p> Defaults to <c>standard_io</c>.</p>
+ </item>
+ <tag><c>filesync_repeat_interval</c></tag>
+ <item>
+ <p>This value, in milliseconds, specifies how often the handler does
+ a file sync operation to write buffered data to disk. The handler attempts
+ the operation repeatedly, but only performs a new sync if something has
+ actually been logged.</p>
+ <p>If <c>no_repeat</c> is set as value, the repeated file sync operation
+ is disabled, and it is the operating system settings that determine
+ how quickly or slowly data is written to disk. The user can also call
+ the <seealso marker="logger_std_h#filesync-1"><c>filesync/1</c></seealso>
+ function to perform a file sync.</p>
+ <p>Defaults to <c>5000</c> milliseconds.</p>
+ </item>
+ </taglist>
+ <p>Other configuration parameters exist, to be used for customizing
+ the overload protection behaviour. The same parameters are used both in the
+ standard handler and the disk_log handler, and are documented in the
+ <seealso marker="logger_chapter#overload_protection"><c>User's Guide</c>
+ </seealso>.</p>
+ <p>Notice that if changing the configuration of the handler in runtime,
+ the <c>type</c> parameter must not be modified.</p>
+ <p>Example of adding a standard handler:</p>
+ <code type="none">
+logger:add_handler(my_standard_h, logger_std_h,
+ #{config => #{type => {file,"./system_info.log"},
+ filesync_repeat_interval => 1000}}).
+ </code>
+ <p>To set the default handler, that starts initially with
+ the Kernel application, to log to file instead of <c>standard_io</c>,
+ change the Kernel default logger configuration. Example:</p>
+ <code type="none">
+erl -kernel logger '[{handler,default,logger_std_h,
+ #{config => #{type => {file,"./log.log"}}}}]'
+ </code>
+ <p>An example of how to replace the standard handler with a disk_log handler
+ at startup is found in the
+ <seealso marker="logger_disk_log_h"><c>logger_disk_log_h</c></seealso>
+ manual.</p>
+ </description>
+
+ <funcs>
+
+ <func>
+ <name name="filesync" arity="1" clause_i="1"/>
+ <fsummary>Writes buffered data to disk.</fsummary>
+ <desc>
+ <p>Write buffered data to disk.</p>
+ </desc>
+ </func>
+
+ </funcs>
+
+ <section>
+ <title>See Also</title>
+ <p><seealso marker="logger"><c>logger(3)</c></seealso>,
+ <seealso marker="logger_disk_log_h">
+ <c>logger_disk_log_h(3)</c></seealso></p>
+ </section>
+</erlref>
+
+
diff --git a/lib/kernel/doc/src/net_kernel.xml b/lib/kernel/doc/src/net_kernel.xml
index 0b94fc0fa6..bfbe7a6470 100644
--- a/lib/kernel/doc/src/net_kernel.xml
+++ b/lib/kernel/doc/src/net_kernel.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -56,7 +56,7 @@ $ <input>erl -sname foobar</input></pre>
<p>Normally, connections are established automatically when
another node is referenced. This functionality can be disabled
by setting Kernel configuration parameter
- <c>dist_auto_connect</c> to <c>false</c>, see
+ <c>dist_auto_connect</c> to <c>never</c>, see
<seealso marker="kernel_app"><c>kernel(6)</c></seealso>. In this case,
connections must be established explicitly by calling
<seealso marker="#connect_node/1"><c>connect_node/1</c></seealso>.</p>
@@ -102,8 +102,10 @@ $ <input>erl -sname foobar</input></pre>
<fsummary>Establish a connection to a node.</fsummary>
<desc>
<p>Establishes a connection to <c><anno>Node</anno></c>. Returns
- <c>true</c> if successful, <c>false</c> if not, and <c>ignored</c>
- if the local node is not alive.</p>
+ <c>true</c> if a connection was established or was already
+ established or if <c><anno>Node</anno></c> is the local node
+ itself. Returns <c>false</c> if the connection attempt failed, and
+ <c>ignored</c> if the local node is not alive.</p>
</desc>
</func>
@@ -230,7 +232,12 @@ $ <input>erl -sname foobar</input></pre>
<item>
<p>The tuple <c>{nodedown_reason, Reason}</c> is included in
<c>InfoList</c> in <c>nodedown</c> messages.</p>
- <p><c>Reason</c> can be any of the following:</p>
+ <p>
+ <c>Reason</c> can, depending on which
+ distribution module or process that is used be any term,
+ but for the standard TCP distribution module it is
+ any of the following:
+ </p>
<taglist>
<tag><c>connection_setup_failed</c></tag>
<item><p>The connection setup failed (after <c>nodeup</c>
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index e1cf45109d..8188ede6a2 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,569 @@
</header>
<p>This document describes the changes made to the Kernel application.</p>
+<section><title>Kernel 6.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The values <c>all</c> and <c>none</c> are documented as
+ valid value for the Kernel configuration parameter
+ <c>logger_level</c>, but would cause a crash during node
+ start. This is now corrected.</p>
+ <p>
+ Own Id: OTP-15143</p>
+ </item>
+ <item>
+ <p>
+ Fix some potential buggy behavior in how ticks are sent
+ on inter node distribution connections. Tick is now sent
+ to c-node even if there are unsent buffered data, as
+ c-nodes need ticks in order to send reply ticks. The
+ amount of sent data was also calculated wrongly when
+ ticks were suppressed due to unsent buffered data.</p>
+ <p>
+ Own Id: OTP-15162 Aux Id: ERIERL-191 </p>
+ </item>
+ <item>
+ <p>
+ Non semantic change in dist_util.erl to silence dialyzer
+ warning.</p>
+ <p>
+ Own Id: OTP-15170</p>
+ </item>
+ <item>
+ <p>
+ Fixed <c>net_kernel:connect_node(node())</c> to return
+ <c>true</c> (and do nothing) as it always has before
+ OTP-21.0. Also documented this successful "self connect"
+ as the expected behavior.</p>
+ <p>
+ Own Id: OTP-15182 Aux Id: ERL-643 </p>
+ </item>
+ <item>
+ <p>
+ The single_line option on logger_formatter would in some
+ cases add an unwanted comma after the association arrows
+ in a map. This is now corrected.</p>
+ <p>
+ Own Id: OTP-15228</p>
+ </item>
+ <item>
+ <p>
+ Improved robustness of distribution connection setup. In
+ OTP-21.0 a truly asynchronous connection setup was
+ introduced. This is further improvement on that work to
+ make the emulator more robust and also be able to recover
+ in cases when involved Erlang processes misbehave.</p>
+ <p>
+ Own Id: OTP-15297 Aux Id: OTP-15279, OTP-15280 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A new macro, <c>?LOG(Level,...)</c>, is added. This is
+ equivalent to the existing <c>?LOG_&lt;LEVEL&gt;(...)</c>
+ macros.</p>
+ <p>
+ A new variant of Logger report callback is added, which
+ takes an extra argument containing options for size
+ limiting and line breaks. Module <c>proc_lib</c> in
+ <c>STDLIB</c> uses this for crash reports.</p>
+ <p>
+ Logger configuration is now checked a bit more for
+ errors.</p>
+ <p>
+ Own Id: OTP-15132</p>
+ </item>
+ <item>
+ <p>
+ The socket options <c>recvtos</c>, <c>recvttl</c>,
+ <c>recvtclass</c> and <c>pktoptions</c> have been
+ implemented in the socket modules. See the documentation
+ for the <c>gen_tcp</c>, <c>gen_udp</c> and <c>inet</c>
+ modules. Note that support for these in the runtime
+ system is platform dependent. Especially for
+ <c>pktoptions</c> which is very Linux specific and
+ obsoleted by the RFCs that defined it.</p>
+ <p>
+ Own Id: OTP-15145 Aux Id: ERIERL-187 </p>
+ </item>
+ <item>
+ <p>
+ Add <c>logger:set_application_level/2</c> for setting the
+ logger level of all modules in one application.</p>
+ <p>
+ Own Id: OTP-15146</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 6.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed bug in <c>net_kernel</c> that could cause an
+ emulator crash if certain connection attempts failed. Bug
+ exists since kernel-6.0 (OTP-21.0).</p>
+ <p>
+ Own Id: OTP-15280 Aux Id: ERIERL-226, OTP-15279 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 6.0</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Clarify the documentation of <c>rpc:multicall/5</c>.
+ </p>
+ <p>
+ Own Id: OTP-10551</p>
+ </item>
+ <item>
+ <p>
+ The DNS resolver when getting econnrefused from a server
+ retained an invalid socket so look up towards the next
+ server(s) also failed.</p>
+ <p>
+ Own Id: OTP-13133 Aux Id: PR-1557 </p>
+ </item>
+ <item>
+ <p>
+ No resolver backend returns V4Mapped IPv6 addresses any
+ more. This was inconsistent before, some did, some did
+ not. To facilitate working with such addresses a new
+ function <c>inet:ipv4_mapped_ipv6_address/1</c> has been
+ added.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-13761 Aux Id: ERL-503 </p>
+ </item>
+ <item>
+ <p>
+ The type specifications for <c>file:posix/0</c> and
+ <c>inet:posix/0</c> have been updated according to which
+ errors file and socket operations should be able to
+ return.</p>
+ <p>
+ Own Id: OTP-14019 Aux Id: ERL-550 </p>
+ </item>
+ <item>
+ <p>
+ Fix name resolving in IPv6 only environments when doing
+ the initial distributed connection.</p>
+ <p>
+ Own Id: OTP-14501</p>
+ </item>
+ <item>
+ <p> File operations used to accept <seealso
+ marker="kernel:file#type-name_all">filenames</seealso>
+ containing null characters (integer value zero). This
+ caused the name to be truncated and in some cases
+ arguments to primitive operations to be mixed up.
+ Filenames containing null characters inside the filename
+ are now <em>rejected</em> and will cause primitive file
+ operations to fail. </p> <p> Also environment variable
+ operations used to accept <seealso
+ marker="kernel:os#type-env_var_name">names</seealso> and
+ <seealso
+ marker="kernel:os#type-env_var_value">values</seealso> of
+ environment variables containing null characters (integer
+ value zero). This caused operations to silently produce
+ erroneous results. Environment variable names and values
+ containing null characters inside the name or value are
+ now <em>rejected</em> and will cause environment variable
+ operations to fail. </p> <p>Primitive environment
+ variable operations also used to accept the <c>$=</c>
+ character in environment variable names causing various
+ problems. <c>$=</c> characters in environment variable
+ names are now also <em>rejected</em>. </p> <p>Also
+ <seealso
+ marker="kernel:os#cmd/1"><c>os:cmd/1</c></seealso> now
+ reject null characters inside its <seealso
+ marker="kernel:os#type-os_command">command</seealso>.
+ </p> <p><seealso
+ marker="erts:erlang#open_port/2"><c>erlang:open_port/2</c></seealso>
+ will also reject null characters inside the port name
+ from now on.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-14543 Aux Id: ERL-370 </p>
+ </item>
+ <item>
+ <p><c>os:putenv</c> and <c>os:getenv</c> no longer access
+ the process environment directly and instead work on a
+ thread-safe emulation. The only observable difference is
+ that it's <em>not</em> kept in sync with libc
+ <c>getenv(3)</c> / <c>putenv(3)</c>, so those who relied
+ on that behavior in drivers or NIFs will need to add
+ manual synchronization.</p> <p>On Windows this means that
+ you can no longer resolve DLL dependencies by modifying
+ the <c>PATH</c> just before loading the driver/NIF. To
+ make this less of a problem, the emulator now adds the
+ target DLL's folder to the DLL search path.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-14666</p>
+ </item>
+ <item>
+ <p>
+ Fixed connection tick toward primitive hidden nodes
+ (erl_interface) that could cause faulty tick timeout in
+ rare cases when payload data is sent to hidden node but
+ not received.</p>
+ <p>
+ Own Id: OTP-14681</p>
+ </item>
+ <item>
+ <p>
+ Make group react immediately on an EXIT-signal from shell
+ in e.g ssh.</p>
+ <p>
+ Own Id: OTP-14991 Aux Id: PR1705 </p>
+ </item>
+ <item>
+ <p>
+ Calls to <c>gen_tcp:send/2</c> on closed sockets now
+ returns <c>{error, closed}</c> instead of
+ <c>{error,enotconn}</c>.</p>
+ <p>
+ Own Id: OTP-15001</p>
+ </item>
+ <item>
+ <p>
+ The <c>included_applications</c> key are no longer
+ duplicated as application environment variable. Earlier,
+ the included applications could be read both with
+ <c>application:get[_all]_env(...)</c> and
+ <c>application:get[_all]_key(...)</c> functions. Now, it
+ can only be read with
+ <c>application:get[_all]_key(...)</c>.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15071</p>
+ </item>
+ <item>
+ <p>Owner and group changes through
+ <c>file:write_file_info</c>, <c>file:change_owner</c>,
+ and <c>file:change_group</c> will no longer report
+ success on permission errors.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15118</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>A new logging API is added to Erlang/OTP, see the
+ <seealso
+ marker="kernel:logger"><c>logger(3)</c></seealso> manual
+ page, and section <seealso
+ marker="kernel:logger_chapter">Logging</seealso> in the
+ Kernel User's Guide.</p>
+ <p>Calls to <c>error_logger</c> are automatically
+ redirected to the new API, and legacy error logger event
+ handlers can still be used. It is, however, recommended
+ to use the Logger API directly when writing new code.</p>
+ <p>Notice the following potential incompatibilities:</p>
+ <list> <item><p>Kernel configuration parameters
+ <c>error_logger</c> still works, but is overruled if the
+ default handler's output destination is configured with
+ Kernel configuration parameter <c>logger</c>.</p> <p>In
+ general, parameters for configuring error logger are
+ overwritten by new parameters for configuring
+ Logger.</p></item> <item><p>The concept of SASL error
+ logging is deprecated, meaning that by default the SASL
+ application does not affect which log events are
+ logged.</p> <p>By default, supervisor reports and crash
+ reports are logged by the default Logger handler started
+ by Kernel, and end up at the same destination (terminal
+ or file) as other standard log event from Erlang/OTP.</p>
+ <p>Progress reports are not logged by default, but can be
+ enabled by setting the primary log level to info, for
+ example with the Kernel configuration parameter
+ <c>logger_level</c>.</p> <p>To obtain backwards
+ compatibility with the SASL error logging functionality
+ from earlier releases, set Kernel configuration parameter
+ <c>logger_sasl_compatible</c> to <c>true</c>. This
+ prevents the default Logger handler from logging any
+ supervisor-, crash-, or progress reports. Instead, SASL
+ adds a separate Logger handler during application start,
+ which takes care of these log events. The SASL
+ configuration parameters <c>sasl_error_logger</c> and
+ <c>sasl_errlog_type</c> specify the destination (terminal
+ or file) and severity level to log for these
+ events.</p></item></list>
+ <p>
+ Since Logger is new in Erlang/OTP 21.0, we do reserve the
+ right to introduce changes to the Logger API and
+ functionality in patches following this release. These
+ changes might or might not be backwards compatible with
+ the initial version.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-13295</p>
+ </item>
+ <item>
+ <p>
+ The function <c>inet:i/0</c> has been documented.</p>
+ <p>
+ Own Id: OTP-13713 Aux Id: PR-1645 </p>
+ </item>
+ <item>
+ <p>
+ Typespecs for <c>netns</c> and <c>bind_to_device</c>
+ options have been added to <c>gen_tcp</c>, <c>gen_udp</c>
+ and <c>gen_sctp</c> functions.</p>
+ <p>
+ Own Id: OTP-14359 Aux Id: PR-1816 </p>
+ </item>
+ <item>
+ <p>
+ New functionality for implementation of alternative
+ carriers for the Erlang distribution has been introduced.
+ This mainly consists of support for usage of distribution
+ controller processes (previously only ports could be used
+ as distribution controllers). For more information see
+ <seealso marker="erts:alt_dist#distribution_module">ERTS
+ User's Guide ➜ How to implement an Alternative Carrier
+ for the Erlang Distribution ➜ Distribution
+ Module</seealso>.</p>
+ <p>
+ Own Id: OTP-14459</p>
+ </item>
+ <item>
+ <p><c>seq_trace</c> labels may now be any erlang
+ term.</p>
+ <p>
+ Own Id: OTP-14899</p>
+ </item>
+ <item>
+ <p>
+ The SSL distribution protocol <c>-proto inet_tls</c> has
+ stopped setting the SSL option
+ <c>server_name_indication</c>. New verify funs for client
+ and server in <c>inet_tls_dist</c> has been added, not
+ documented yet, that checks node name if present in peer
+ certificate. Usage is still also yet to be documented.</p>
+ <p>
+ Own Id: OTP-14969 Aux Id: OTP-14465, ERL-598 </p>
+ </item>
+ <item>
+ <p>
+ Changed timeout of <c>gen_server</c> calls to <c>auth</c>
+ server from default 5 seconds to <c>infinity</c>.</p>
+ <p>
+ Own Id: OTP-15009 Aux Id: ERL-601 </p>
+ </item>
+ <item>
+ <p>The callback module passed as <c>-epmd_module</c> to
+ erl has been expanded to be able to do name and port
+ resolving.</p> <p>Documentation has also been added in
+ the <seealso
+ marker="kernel:erl_epmd"><c>erl_epmd</c></seealso>
+ reference manual and ERTS User's Guide <seealso
+ marker="erts:alt_disco">How to Implement an Alternative
+ Service Discovery for Erlang Distribution</seealso>.</p>
+ <p>
+ Own Id: OTP-15086 Aux Id: PR-1694 </p>
+ </item>
+ <item>
+ <p>
+ Included config file specified with relative path in
+ sys.config are now first searched for relative to the
+ directory of sys.config itself. If not found, it is also
+ searched for relative to the current working directory.
+ The latter is for backwards compatibility.</p>
+ <p>
+ Own Id: OTP-15137 Aux Id: PR-1838 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 5.4.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Non semantic change in dist_util.erl to silence dialyzer
+ warning.</p>
+ <p>
+ Own Id: OTP-15170</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 5.4.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix some potential buggy behavior in how ticks are sent
+ on inter node distribution connections. Tick is now sent
+ to c-node even if there are unsent buffered data, as
+ c-nodes need ticks in order to send reply ticks. The
+ amount of sent data was calculated wrongly when ticks
+ where suppressed due to unsent buffered data.</p>
+ <p>
+ Own Id: OTP-15162 Aux Id: ERIERL-191 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 5.4.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Correct a few contracts. </p>
+ <p>
+ Own Id: OTP-14889</p>
+ </item>
+ <item>
+ <p>
+ Reject loading modules with names containing directory
+ separators ('/' or '\' on Windows).</p>
+ <p>
+ Own Id: OTP-14933 Aux Id: ERL-564, PR-1716 </p>
+ </item>
+ <item>
+ <p>
+ Fix bug in handling of os:cmd/2 option max_size on
+ windows.</p>
+ <p>
+ Own Id: OTP-14940</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 5.4.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Add <c>os:cmd/2</c> that takes an options map as the
+ second argument.</p>
+ <p>
+ Add <c>max_size</c> as an option to <c>os:cmd/2</c> that
+ control the maximum size of the result that
+ <c>os:cmd/2</c> will return.</p>
+ <p>
+ Own Id: OTP-14823</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 5.4.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Refactored an internal API.</p>
+ <p>
+ Own Id: OTP-14784</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 5.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Processes which did output after switching jobs (Ctrl+G)
+ could be left forever stuck in the io request.</p>
+ <p>
+ Own Id: OTP-14571 Aux Id: ERL-472 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Lock counting can now be fully toggled at runtime in
+ the lock counting emulator (<c>-emu_type lcnt</c>).
+ Everything is enabled by default to match the old
+ behavior, but specific categories can be toggled at will
+ with minimal runtime overhead when disabled. Refer to the
+ documentation on <c>lcnt:rt_mask/1</c> for details.</p>
+ <p>
+ Own Id: OTP-13170</p>
+ </item>
+ <item>
+ <p><c>lcnt:collect</c> and <c>lcnt:clear</c> will no
+ longer block all other threads in the runtime system.</p>
+ <p>
+ Own Id: OTP-14412</p>
+ </item>
+ <item>
+ <p>
+ General Unicode improvements.</p>
+ <p>
+ Own Id: OTP-14462</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 5.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The documentation for the 'quiet' option in
+ disk_log:open/1 had an incorrect default value.</p>
+ <p>
+ Own Id: OTP-14498</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Kernel 5.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/kernel/doc/src/os.xml b/lib/kernel/doc/src/os.xml
index 0e9add4161..c95e615c6b 100644
--- a/lib/kernel/doc/src/os.xml
+++ b/lib/kernel/doc/src/os.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2017</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -36,19 +36,116 @@
only run on a specific platform. On the other hand, with careful
use, these functions can be of help in enabling a program to run on
most platforms.</p>
+
+ <note>
+ <p>
+ File operations used to accept filenames containing
+ null characters (integer value zero). This caused
+ the name to be truncated and in some cases arguments
+ to primitive operations to be mixed up. Filenames
+ containing null characters inside the filename
+ are now <em>rejected</em> and will cause primitive
+ file operations to fail.
+ </p>
+ <p>
+ Also environment variable operations used to accept
+ names and values of environment variables containing
+ null characters (integer value zero). This caused
+ operations to silently produce erroneous results.
+ Environment variable names and values containing
+ null characters inside the name or value are now
+ <em>rejected</em> and will cause environment variable
+ operations to fail.
+ </p>
+ </note>
</description>
+ <datatypes>
+ <datatype>
+ <name name="env_var_name"/>
+ <desc>
+ <p>A string containing valid characters on the specific
+ OS for environment variable names using
+ <seealso marker="file#native_name_encoding/0"><c>file:native_name_encoding()</c></seealso>
+ encoding. Note that specifically null characters (integer
+ value zero) and <c>$=</c> characters are not allowed.
+ However, note that not all invalid characters necessarily
+ will cause the primitiv operations to fail, but may instead
+ produce invalid results.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="env_var_value"/>
+ <desc>
+ <p>A string containing valid characters on the specific
+ OS for environment variable values using
+ <seealso marker="file#native_name_encoding/0"><c>file:native_name_encoding()</c></seealso>
+ encoding. Note that specifically null characters (integer
+ value zero) are not allowed. However, note that not all
+ invalid characters necessarily will cause the primitiv
+ operations to fail, but may instead produce invalid results.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="env_var_name_value"/>
+ <desc>
+ <p>
+ Assuming that environment variables has been correctly
+ set, a strings containing valid characters on the specific
+ OS for environment variable names and values using
+ <seealso marker="file#native_name_encoding/0"><c>file:native_name_encoding()</c></seealso>
+ encoding. The first <c>$=</c> characters appearing in
+ the string separates environment variable name (on the
+ left) from environment variable value (on the right).
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="os_command"/>
+ <desc>
+ <p>All characters needs to be valid characters on the
+ specific OS using
+ <seealso marker="file#native_name_encoding/0"><c>file:native_name_encoding()</c></seealso>
+ encoding. Note that specifically null characters (integer
+ value zero) are not allowed. However, note that not all
+ invalid characters not necessarily will cause
+ <seealso marker="#cmd/1"><c>os:cmd/1</c></seealso>
+ to fail, but may instead produce invalid results.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="os_command_opts"/>
+ <desc>
+ <p>Options for <seealso marker="#cmd/2"><c>os:cmd/2</c></seealso></p>
+ <taglist>
+ <tag><c>max_size</c></tag>
+ <item>
+ <p>The maximum size of the data returned by the <c>os:cmd</c> call.
+ See the <seealso marker="#cmd/2"><c>os:cmd/2</c></seealso>
+ documentation for more details.</p>
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+ </datatypes>
+
<funcs>
<func>
<name name="cmd" arity="1"/>
+ <name name="cmd" arity="2"/>
<fsummary>Execute a command in a shell of the target OS.</fsummary>
<desc>
<p>Executes <c><anno>Command</anno></c> in a command shell of the
- target OS,
- captures the standard output of the command, and returns this
- result as a string. This function is a replacement of
- the previous function <c>unix:cmd/1</c>; they are equivalent on a
- Unix platform.</p>
+ target OS, captures the standard output of the command,
+ and returns this result as a string.</p>
+ <warning><p>Previous implementation used to allow all characters
+ as long as they were integer values greater than or equal to zero.
+ This sometimes lead to unwanted results since null characters
+ (integer value zero) often are interpreted as string termination. The
+ current implementation rejects these.</p></warning>
<p><em>Examples:</em></p>
<code type="none">
LsOut = os:cmd("ls"), % on unix platform
@@ -57,6 +154,21 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
called from another program (for example, <c>os:cmd/1</c>)
can differ, compared with the standard output of the command
when called directly from an OS command shell.</p>
+ <p><c>os:cmd/2</c> was added in kernel-5.5 (OTP-20.2.1). It makes it
+ possible to pass an options map as the second argument in order to
+ control the behaviour of <c>os:cmd</c>. The possible options are:
+ </p>
+ <taglist>
+ <tag><c>max_size</c></tag>
+ <item>
+ <p>The maximum size of the data returned by the <c>os:cmd</c> call.
+ This option is a safety feature that should be used when the command
+ executed can return a very large, possibly infinite, result.</p>
+ <code type="none">
+> os:cmd("cat /dev/zero", #{ max_size => 20 }).
+[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]</code>
+ </item>
+ </taglist>
</desc>
</func>
@@ -152,6 +264,15 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
<p>On Unix platforms, the environment is set using UTF-8 encoding
if Unicode filename translation is in effect. On Windows, the
environment is set using wide character interfaces.</p>
+ <note>
+ <p>
+ <c><anno>VarName</anno></c> is not allowed to contain
+ an <c>$=</c> character. Previous implementations used
+ to just let the <c>$=</c> character through which
+ silently caused erroneous results. Current implementation
+ will instead throw a <c>badarg</c> exception.
+ </p>
+ </note>
</desc>
</func>
diff --git a/lib/kernel/doc/src/part.xml b/lib/kernel/doc/src/part.xml
new file mode 100644
index 0000000000..fa7e92835f
--- /dev/null
+++ b/lib/kernel/doc/src/part.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE part SYSTEM "part.dtd">
+
+<part xmlns:xi="http://www.w3.org/2001/XInclude">
+ <header>
+ <copyright>
+ <year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>Kernel User's Guide</title>
+ <prepared>OTP Team</prepared>
+ <docno></docno>
+ <date>2018-06-06</date>
+ <file>part.xml</file>
+ </header>
+ <description>
+ <p></p>
+ </description>
+ <xi:include href="introduction_chapter.xml"/>
+ <xi:include href="logger_chapter.xml"/>
+</part>
+
diff --git a/lib/kernel/doc/src/part_notes.xml b/lib/kernel/doc/src/part_notes.xml
deleted file mode 100644
index 5e849039ee..0000000000
--- a/lib/kernel/doc/src/part_notes.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Kernel Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p>The <em>Kernel</em> application has all the code necessary to run
- the Erlang runtime system itself; File servers and code servers
- etc.</p>
- <p>For information about older versions, see
- <url href="part_notes_history_frame.html">Release Notes History</url>.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/kernel/doc/src/part_notes_history.xml b/lib/kernel/doc/src/part_notes_history.xml
deleted file mode 100644
index 0cf7b793da..0000000000
--- a/lib/kernel/doc/src/part_notes_history.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2006</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Kernel Release Notes History</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p>The <em>Kernel</em> application has all the code necessary to run
- the Erlang runtime system itself; File servers and code servers
- etc.</p>
- </description>
- <include file="notes_history"></include>
-</part>
-
diff --git a/lib/kernel/doc/src/ref_man.xml b/lib/kernel/doc/src/ref_man.xml
index 5cd77e0f6f..d3b947527f 100644
--- a/lib/kernel/doc/src/ref_man.xml
+++ b/lib/kernel/doc/src/ref_man.xml
@@ -4,7 +4,7 @@
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,12 +32,15 @@
</description>
<xi:include href="kernel_app.xml"/>
+ <xi:include href="app.xml"/>
<xi:include href="application.xml"/>
<xi:include href="auth.xml"/>
<xi:include href="code.xml"/>
+ <xi:include href="config.xml"/>
<xi:include href="disk_log.xml"/>
<xi:include href="erl_boot_server.xml"/>
<xi:include href="erl_ddll.xml"/>
+ <xi:include href="erl_epmd.xml"/>
<xi:include href="erl_prim_loader_stub.xml"/>
<xi:include href="erlang_stub.xml"/>
<xi:include href="error_handler.xml"/>
@@ -52,6 +55,11 @@
<xi:include href="inet.xml"/>
<xi:include href="inet_res.xml"/>
<xi:include href="init_stub.xml"/>
+ <xi:include href="logger.xml"/>
+ <xi:include href="logger_filters.xml"/>
+ <xi:include href="logger_formatter.xml"/>
+ <xi:include href="logger_std_h.xml"/>
+ <xi:include href="logger_disk_log_h.xml"/>
<xi:include href="net_adm.xml"/>
<xi:include href="net_kernel.xml"/>
<xi:include href="os.xml"/>
@@ -61,6 +69,4 @@
<xi:include href="user.xml"/>
<xi:include href="wrap_log_reader.xml"/>
<xi:include href="zlib_stub.xml"/>
- <xi:include href="app.xml"/>
- <xi:include href="config.xml"/>
</application>
diff --git a/lib/kernel/doc/src/rpc.xml b/lib/kernel/doc/src/rpc.xml
index adec2d9520..fab616e630 100644
--- a/lib/kernel/doc/src/rpc.xml
+++ b/lib/kernel/doc/src/rpc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -217,7 +217,7 @@
<list type="bulleted">
<item>A list of the nodes that do not exist</item>
<item>A list of the nodes where the server does not exist</item>
- <item>A list of the nodes where the server terminatd before sending
+ <item>A list of the nodes where the server terminated before sending
any reply.</item>
</list>
</desc>
@@ -268,8 +268,9 @@
on the specified nodes and collects the answers. It returns
<c>{<anno>ResL</anno>, <anno>BadNodes</anno>}</c>, where
<c><anno>BadNodes</anno></c> is a list
- of the nodes that terminated or timed out during computation,
- and <c><anno>ResL</anno></c> is a list of the return values.
+ of the nodes that do not exist,
+ and <c><anno>ResL</anno></c> is a list of the return values,
+ or <c>{badrpc, <anno>Reason</anno>}</c> for failing calls.
<c><anno>Timeout</anno></c> is a time (integer) in milliseconds, or
<c>infinity</c>.</p>
<p>The following example is useful when new object code is to
@@ -347,7 +348,7 @@
<func>
<name name="pmap" arity="3"/>
- <fsummary>Parallell evaluation of mapping a function over a
+ <fsummary>Parallel evaluation of mapping a function over a
list.</fsummary>
<desc>
<p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>,
diff --git a/lib/kernel/doc/src/seq_trace.xml b/lib/kernel/doc/src/seq_trace.xml
index 197851021f..1a4a74419a 100644
--- a/lib/kernel/doc/src/seq_trace.xml
+++ b/lib/kernel/doc/src/seq_trace.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1998</year><year>2017</year>
+ <year>1998</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -80,13 +80,18 @@ seq_trace:set_token(OldToken), % activate the trace token again
<p>Sets the individual <c><anno>Component</anno></c> of the trace token to
<c><anno>Val</anno></c>. Returns the previous value of the component.</p>
<taglist>
- <tag><c>set_token(label, <anno>Integer</anno>)</c></tag>
+ <tag><c>set_token(label, <anno>Label</anno>)</c></tag>
<item>
- <p>The <c>label</c> component is an integer which
+ <p>The <c>label</c> component is a term which
identifies all events belonging to the same sequential
trace. If several sequential traces can be active
simultaneously, <c>label</c> is used to identify
the separate traces. Default is 0.</p>
+ <warning>
+ <p>Labels were restricted to small signed integers (28 bits)
+ prior to OTP 21. The trace token will be silenty dropped if it
+ crosses over to a node that does not support the label.</p>
+ </warning>
</item>
<tag><c>set_token(serial, SerialValue)</c></tag>
<item>
diff --git a/lib/kernel/doc/src/specs.xml b/lib/kernel/doc/src/specs.xml
index 29d52f23bb..b8c25ca53b 100644
--- a/lib/kernel/doc/src/specs.xml
+++ b/lib/kernel/doc/src/specs.xml
@@ -6,6 +6,7 @@
<xi:include href="../specs/specs_disk_log.xml"/>
<xi:include href="../specs/specs_erl_boot_server.xml"/>
<xi:include href="../specs/specs_erl_ddll.xml"/>
+ <xi:include href="../specs/specs_erl_epmd.xml"/>
<xi:include href="../specs/specs_erl_prim_loader_stub.xml"/>
<xi:include href="../specs/specs_erlang_stub.xml"/>
<xi:include href="../specs/specs_error_handler.xml"/>
@@ -20,6 +21,11 @@
<xi:include href="../specs/specs_inet.xml"/>
<xi:include href="../specs/specs_inet_res.xml"/>
<xi:include href="../specs/specs_init_stub.xml"/>
+ <xi:include href="../specs/specs_logger.xml"/>
+ <xi:include href="../specs/specs_logger_filters.xml"/>
+ <xi:include href="../specs/specs_logger_formatter.xml"/>
+ <xi:include href="../specs/specs_logger_std_h.xml"/>
+ <xi:include href="../specs/specs_logger_disk_log_h.xml"/>
<xi:include href="../specs/specs_net_adm.xml"/>
<xi:include href="../specs/specs_net_kernel.xml"/>
<xi:include href="../specs/specs_os.xml"/>
diff --git a/lib/kernel/doc/src/user_guide.gif b/lib/kernel/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/kernel/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/kernel/examples/Makefile b/lib/kernel/examples/Makefile
index 26ec58f571..f86e662838 100644
--- a/lib/kernel/examples/Makefile
+++ b/lib/kernel/examples/Makefile
@@ -45,7 +45,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/kernel-$(KERNEL_VSN)/examples
# Pack and install the complete directory structure from
# here (CWD) and down, for all examples.
-EXAMPLES = uds_dist
+EXAMPLES = uds_dist gen_tcp_dist
release_spec:
$(INSTALL_DIR) "$(RELSYSDIR)"
diff --git a/lib/kernel/examples/gen_tcp_dist/Makefile b/lib/kernel/examples/gen_tcp_dist/Makefile
new file mode 100644
index 0000000000..65513a1729
--- /dev/null
+++ b/lib/kernel/examples/gen_tcp_dist/Makefile
@@ -0,0 +1,20 @@
+RM=rm -f
+CP=cp
+EBIN=ebin
+ERLC=erlc
+# Works if building in open source source tree
+KERNEL_INCLUDE=$(ERL_TOP)/lib/kernel/include
+ERLCFLAGS+= -W -I$(KERNEL_INCLUDE)
+
+MODULES=gen_tcp_dist
+
+TARGET_FILES=$(MODULES:%=$(EBIN)/%.beam)
+
+opt: $(TARGET_FILES)
+
+$(EBIN)/%.beam: src/%.erl
+ $(ERLC) $(ERLCFLAGS) -o$(EBIN) $<
+
+clean:
+ $(RM) $(TARGET_FILES)
+
diff --git a/lib/cosEvent/example/.gitignore b/lib/kernel/examples/gen_tcp_dist/ebin/.gitignore
index e69de29bb2..e69de29bb2 100644
--- a/lib/cosEvent/example/.gitignore
+++ b/lib/kernel/examples/gen_tcp_dist/ebin/.gitignore
diff --git a/lib/kernel/examples/gen_tcp_dist/src/gen_tcp_dist.erl b/lib/kernel/examples/gen_tcp_dist/src/gen_tcp_dist.erl
new file mode 100644
index 0000000000..98554ed805
--- /dev/null
+++ b/lib/kernel/examples/gen_tcp_dist/src/gen_tcp_dist.erl
@@ -0,0 +1,781 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(gen_tcp_dist).
+
+%%
+%% This is an example of how to plug in an arbitrary distribution
+%% carrier for Erlang using distribution processes.
+%%
+%% This example uses gen_tcp for transportation of data, but
+%% you can use whatever underlying protocol you want as long
+%% as your implementation reliably delivers data chunks to the
+%% receiving VM in the order they were sent from the sending
+%% VM.
+%%
+%% This code is a rewrite of the lib/kernel/src/inet_tcp_dist.erl
+%% distribution impementation for TCP used by default. That
+%% implementation use distribution ports instead of distribution
+%% processes and is more efficient compared to this implementation.
+%% This since this implementation more or less gets the
+%% distribution processes in between the VM and the ports without
+%% any gain specific gain.
+%%
+
+-export([listen/1, accept/1, accept_connection/5,
+ setup/5, close/1, select/1, is_node_name/1]).
+
+%% Optional
+-export([setopts/2, getopts/2]).
+
+%% internal exports
+
+-export([dist_cntrlr_setup/1, dist_cntrlr_input_setup/3,
+ dist_cntrlr_tick_handler/1]).
+
+-export([accept_loop/2,do_accept/6,do_setup/6]).
+
+-import(error_logger,[error_msg/2]).
+
+-include("net_address.hrl").
+
+-include("dist.hrl").
+-include("dist_util.hrl").
+
+%% ------------------------------------------------------------
+%% Select this protocol based on node name
+%% select(Node) => Bool
+%% ------------------------------------------------------------
+
+select(Node) ->
+ case split_node(atom_to_list(Node), $@, []) of
+ [_, Host] ->
+ case inet:getaddr(Host, inet) of
+ {ok,_} -> true;
+ _ -> false
+ end;
+ _ -> false
+ end.
+
+%% ------------------------------------------------------------
+%% Create the listen socket, i.e. the port that this erlang
+%% node is accessible through.
+%% ------------------------------------------------------------
+
+listen(Name) ->
+ case do_listen([binary, {active, false}, {packet,2}, {reuseaddr, true}]) of
+ {ok, Socket} ->
+ TcpAddress = get_tcp_address(Socket),
+ {_,Port} = TcpAddress#net_address.address,
+ ErlEpmd = net_kernel:epmd_module(),
+ case ErlEpmd:register_node(Name, Port) of
+ {ok, Creation} ->
+ {ok, {Socket, TcpAddress, Creation}};
+ Error ->
+ Error
+ end;
+ Error ->
+ Error
+ end.
+
+do_listen(Options) ->
+ {First,Last} = case application:get_env(kernel,inet_dist_listen_min) of
+ {ok,N} when is_integer(N) ->
+ case application:get_env(kernel,
+ inet_dist_listen_max) of
+ {ok,M} when is_integer(M) ->
+ {N,M};
+ _ ->
+ {N,N}
+ end;
+ _ ->
+ {0,0}
+ end,
+ do_listen(First, Last, listen_options([{backlog,128}|Options])).
+
+do_listen(First,Last,_) when First > Last ->
+ {error,eaddrinuse};
+do_listen(First,Last,Options) ->
+ case gen_tcp:listen(First, Options) of
+ {error, eaddrinuse} ->
+ do_listen(First+1,Last,Options);
+ Other ->
+ Other
+ end.
+
+listen_options(Opts0) ->
+ Opts1 =
+ case application:get_env(kernel, inet_dist_use_interface) of
+ {ok, Ip} ->
+ [{ip, Ip} | Opts0];
+ _ ->
+ Opts0
+ end,
+ case application:get_env(kernel, inet_dist_listen_options) of
+ {ok,ListenOpts} ->
+ ListenOpts ++ Opts1;
+ _ ->
+ Opts1
+ end.
+
+
+%% ------------------------------------------------------------
+%% Accepts new connection attempts from other Erlang nodes.
+%% ------------------------------------------------------------
+
+accept(Listen) ->
+ spawn_opt(?MODULE, accept_loop, [self(), Listen], [link, {priority, max}]).
+
+accept_loop(Kernel, Listen) ->
+ ?trace("~p~n",[{?MODULE, accept_loop, self()}]),
+ case gen_tcp:accept(Listen) of
+ {ok, Socket} ->
+ DistCtrl = spawn_dist_cntrlr(Socket),
+ ?trace("~p~n",[{?MODULE, accept_loop, accepted, Socket, DistCtrl, self()}]),
+ flush_controller(DistCtrl, Socket),
+ gen_tcp:controlling_process(Socket, DistCtrl),
+ flush_controller(DistCtrl, Socket),
+ Kernel ! {accept,self(),DistCtrl,inet,tcp},
+ receive
+ {Kernel, controller, Pid} ->
+ call_ctrlr(DistCtrl, {supervisor, Pid}),
+ Pid ! {self(), controller};
+ {Kernel, unsupported_protocol} ->
+ exit(unsupported_protocol)
+ end,
+ accept_loop(Kernel, Listen);
+ Error ->
+ exit(Error)
+ end.
+
+flush_controller(Pid, Socket) ->
+ receive
+ {tcp, Socket, Data} ->
+ Pid ! {tcp, Socket, Data},
+ flush_controller(Pid, Socket);
+ {tcp_closed, Socket} ->
+ Pid ! {tcp_closed, Socket},
+ flush_controller(Pid, Socket)
+ after 0 ->
+ ok
+ end.
+
+%% ------------------------------------------------------------
+%% Accepts a new connection attempt from another Erlang node.
+%% Performs the handshake with the other side.
+%% ------------------------------------------------------------
+
+accept_connection(AcceptPid, DistCtrl, MyNode, Allowed, SetupTime) ->
+ spawn_opt(?MODULE, do_accept,
+ [self(), AcceptPid, DistCtrl, MyNode, Allowed, SetupTime],
+ [link, {priority, max}]).
+
+do_accept(Kernel, AcceptPid, DistCtrl, MyNode, Allowed, SetupTime) ->
+ ?trace("~p~n",[{?MODULE, do_accept, self(), MyNode}]),
+ receive
+ {AcceptPid, controller} ->
+ Timer = dist_util:start_timer(SetupTime),
+ case check_ip(DistCtrl) of
+ true ->
+ HSData0 = hs_data_common(DistCtrl),
+ HSData = HSData0#hs_data{kernel_pid = Kernel,
+ this_node = MyNode,
+ socket = DistCtrl,
+ timer = Timer,
+ this_flags = 0,
+ allowed = Allowed},
+ dist_util:handshake_other_started(HSData);
+ {false,IP} ->
+ error_msg("** Connection attempt from "
+ "disallowed IP ~w ** ~n", [IP]),
+ ?shutdown(no_node)
+ end
+ end.
+
+%% we may not always want the nodelay behaviour
+%% for performance reasons
+
+nodelay() ->
+ case application:get_env(kernel, dist_nodelay) of
+ undefined ->
+ {nodelay, true};
+ {ok, true} ->
+ {nodelay, true};
+ {ok, false} ->
+ {nodelay, false};
+ _ ->
+ {nodelay, true}
+ end.
+
+%% ------------------------------------------------------------
+%% Setup a new connection to another Erlang node.
+%% Performs the handshake with the other side.
+%% ------------------------------------------------------------
+
+setup(Node, Type, MyNode, LongOrShortNames,SetupTime) ->
+ spawn_opt(?MODULE, do_setup,
+ [self(), Node, Type, MyNode, LongOrShortNames, SetupTime],
+ [link, {priority, max}]).
+
+do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
+ ?trace("~p~n",[{?MODULE, do_setup, self(), Node}]),
+ [Name, Address] = splitnode(Node, LongOrShortNames),
+ case inet:getaddr(Address, inet) of
+ {ok, Ip} ->
+ Timer = dist_util:start_timer(SetupTime),
+ ErlEpmd = net_kernel:epmd_module(),
+ case ErlEpmd:port_please(Name, Ip) of
+ {port, TcpPort, Version} ->
+ ?trace("port_please(~p) -> version ~p~n",
+ [Node,Version]),
+ dist_util:reset_timer(Timer),
+ case
+ gen_tcp:connect(
+ Ip, TcpPort,
+ connect_options([binary, {active, false}, {packet, 2}]))
+ of
+ {ok, Socket} ->
+ DistCtrl = spawn_dist_cntrlr(Socket),
+ call_ctrlr(DistCtrl, {supervisor, self()}),
+ flush_controller(DistCtrl, Socket),
+ gen_tcp:controlling_process(Socket, DistCtrl),
+ flush_controller(DistCtrl, Socket),
+ HSData0 = hs_data_common(DistCtrl),
+ HSData = HSData0#hs_data{kernel_pid = Kernel,
+ other_node = Node,
+ this_node = MyNode,
+ socket = DistCtrl,
+ timer = Timer,
+ this_flags = 0,
+ other_version = Version,
+ request_type = Type},
+ dist_util:handshake_we_started(HSData);
+ _ ->
+ %% Other Node may have closed since
+ %% port_please !
+ ?trace("other node (~p) "
+ "closed since port_please.~n",
+ [Node]),
+ ?shutdown(Node)
+ end;
+ _ ->
+ ?trace("port_please (~p) "
+ "failed.~n", [Node]),
+ ?shutdown(Node)
+ end;
+ _Other ->
+ ?trace("inet_getaddr(~p) "
+ "failed (~p).~n", [Node,_Other]),
+ ?shutdown(Node)
+ end.
+
+connect_options(Opts) ->
+ case application:get_env(kernel, inet_dist_connect_options) of
+ {ok,ConnectOpts} ->
+ ConnectOpts ++ Opts;
+ _ ->
+ Opts
+ end.
+
+%%
+%% Close a socket.
+%%
+close(Listen) ->
+ gen_tcp:close(Listen).
+
+
+%% If Node is illegal terminate the connection setup!!
+splitnode(Node, LongOrShortNames) ->
+ case split_node(atom_to_list(Node), $@, []) of
+ [Name|Tail] when Tail =/= [] ->
+ Host = lists:append(Tail),
+ case split_node(Host, $., []) of
+ [_] when LongOrShortNames =:= longnames ->
+ case inet:parse_address(Host) of
+ {ok, _} ->
+ [Name, Host];
+ _ ->
+ error_msg("** System running to use "
+ "fully qualified "
+ "hostnames **~n"
+ "** Hostname ~ts is illegal **~n",
+ [Host]),
+ ?shutdown(Node)
+ end;
+ L when length(L) > 1, LongOrShortNames =:= shortnames ->
+ error_msg("** System NOT running to use fully qualified "
+ "hostnames **~n"
+ "** Hostname ~ts is illegal **~n",
+ [Host]),
+ ?shutdown(Node);
+ _ ->
+ [Name, Host]
+ end;
+ [_] ->
+ error_msg("** Nodename ~p illegal, no '@' character **~n",
+ [Node]),
+ ?shutdown(Node);
+ _ ->
+ error_msg("** Nodename ~p illegal **~n", [Node]),
+ ?shutdown(Node)
+ end.
+
+split_node([Chr|T], Chr, Ack) -> [lists:reverse(Ack)|split_node(T, Chr, [])];
+split_node([H|T], Chr, Ack) -> split_node(T, Chr, [H|Ack]);
+split_node([], _, Ack) -> [lists:reverse(Ack)].
+
+%% ------------------------------------------------------------
+%% Fetch local information about a Socket.
+%% ------------------------------------------------------------
+get_tcp_address(Socket) ->
+ {ok, Address} = inet:sockname(Socket),
+ {ok, Host} = inet:gethostname(),
+ #net_address {
+ address = Address,
+ host = Host,
+ protocol = tcp,
+ family = inet
+ }.
+
+%% ------------------------------------------------------------
+%% Do only accept new connection attempts from nodes at our
+%% own LAN, if the check_ip environment parameter is true.
+%% ------------------------------------------------------------
+check_ip(DistCtrl) ->
+ case application:get_env(check_ip) of
+ {ok, true} ->
+ case get_ifs(DistCtrl) of
+ {ok, IFs, IP} ->
+ check_ip(IFs, IP);
+ _ ->
+ ?shutdown(no_node)
+ end;
+ _ ->
+ true
+ end.
+
+get_ifs(DistCtrl) ->
+ Socket = call_ctrlr(DistCtrl, socket),
+ case inet:peername(Socket) of
+ {ok, {IP, _}} ->
+ case inet:getif(Socket) of
+ {ok, IFs} -> {ok, IFs, IP};
+ Error -> Error
+ end;
+ Error ->
+ Error
+ end.
+
+check_ip([{OwnIP, _, Netmask}|IFs], PeerIP) ->
+ case {inet_tcp:mask(Netmask, PeerIP), inet_tcp:mask(Netmask, OwnIP)} of
+ {M, M} -> true;
+ _ -> check_ip(IFs, PeerIP)
+ end;
+check_ip([], PeerIP) ->
+ {false, PeerIP}.
+
+is_node_name(Node) when is_atom(Node) ->
+ case split_node(atom_to_list(Node), $@, []) of
+ [_, _Host] -> true;
+ _ -> false
+ end;
+is_node_name(_Node) ->
+ false.
+
+hs_data_common(DistCtrl) ->
+ TickHandler = call_ctrlr(DistCtrl, tick_handler),
+ Socket = call_ctrlr(DistCtrl, socket),
+ #hs_data{f_send = send_fun(),
+ f_recv = recv_fun(),
+ f_setopts_pre_nodeup = setopts_pre_nodeup_fun(),
+ f_setopts_post_nodeup = setopts_post_nodeup_fun(),
+ f_getll = getll_fun(),
+ f_handshake_complete = handshake_complete_fun(),
+ f_address = address_fun(),
+ mf_setopts = setopts_fun(DistCtrl, Socket),
+ mf_getopts = getopts_fun(DistCtrl, Socket),
+ mf_getstat = getstat_fun(DistCtrl, Socket),
+ mf_tick = tick_fun(DistCtrl, TickHandler)}.
+
+%%% ------------------------------------------------------------
+%%% Distribution controller processes
+%%% ------------------------------------------------------------
+
+%%
+%% There will be five parties working together when the
+%% connection is up:
+%% - The gen_tcp socket. Providing a tcp/ip connection
+%% to the other node.
+%% - The output handler. It will dispatch all outgoing
+%% traffic from the VM to the gen_tcp socket. This
+%% process is registered as distribution controller
+%% for this channel with the VM.
+%% - The input handler. It will dispatch all incoming
+%% traffic from the gen_tcp socket to the VM. This
+%% process is also the socket owner and receives
+%% incoming traffic using active-N.
+%% - The tick handler. Dispatches asynchronous tick
+%% requests to the socket. It executes on max priority
+%% since it is important to get ticks through to the
+%% other end.
+%% - The channel supervisor (provided by dist_util). It
+%% monitors traffic. Issue tick requests to the tick
+%% handler when no outgoing traffic is seen and bring
+%% the connection down if no incoming traffic is seen.
+%% This process also executes on max priority.
+%%
+%% These parties are linked togheter so should one
+%% of them fail, all of them are terminated and the
+%% connection is taken down.
+%%
+
+%% In order to avoid issues with lingering signal binaries
+%% we enable off-heap message queue data as well as fullsweep
+%% after 0. The fullsweeps will be cheap since we have more
+%% or less no live data.
+-define(DIST_CNTRL_COMMON_SPAWN_OPTS,
+ [{message_queue_data, off_heap},
+ {fullsweep_after, 0}]).
+
+tick_fun(DistCtrl, TickHandler) ->
+ fun (Ctrl) when Ctrl == DistCtrl ->
+ TickHandler ! tick
+ end.
+
+getstat_fun(DistCtrl, Socket) ->
+ fun (Ctrl) when Ctrl == DistCtrl ->
+ case inet:getstat(Socket, [recv_cnt, send_cnt, send_pend]) of
+ {ok, Stat} ->
+ split_stat(Stat,0,0,0);
+ Error ->
+ Error
+ end
+ end.
+
+split_stat([{recv_cnt, R}|Stat], _, W, P) ->
+ split_stat(Stat, R, W, P);
+split_stat([{send_cnt, W}|Stat], R, _, P) ->
+ split_stat(Stat, R, W, P);
+split_stat([{send_pend, P}|Stat], R, W, _) ->
+ split_stat(Stat, R, W, P);
+split_stat([], R, W, P) ->
+ {ok, R, W, P}.
+
+setopts_fun(DistCtrl, Socket) ->
+ fun (Ctrl, Opts) when Ctrl == DistCtrl ->
+ setopts(Socket, Opts)
+ end.
+
+getopts_fun(DistCtrl, Socket) ->
+ fun (Ctrl, Opts) when Ctrl == DistCtrl ->
+ getopts(Socket, Opts)
+ end.
+
+setopts(S, Opts) ->
+ case [Opt || {K,_}=Opt <- Opts,
+ K =:= active orelse K =:= deliver orelse K =:= packet] of
+ [] -> inet:setopts(S,Opts);
+ Opts1 -> {error, {badopts,Opts1}}
+ end.
+
+getopts(S, Opts) ->
+ inet:getopts(S, Opts).
+
+send_fun() ->
+ fun (Ctrlr, Packet) ->
+ call_ctrlr(Ctrlr, {send, Packet})
+ end.
+
+recv_fun() ->
+ fun (Ctrlr, Length, Timeout) ->
+ case call_ctrlr(Ctrlr, {recv, Length, Timeout}) of
+ {ok, Bin} when is_binary(Bin) ->
+ {ok, binary_to_list(Bin)};
+ Other ->
+ Other
+ end
+ end.
+
+getll_fun() ->
+ fun (Ctrlr) ->
+ call_ctrlr(Ctrlr, getll)
+ end.
+
+address_fun() ->
+ fun (Ctrlr, Node) ->
+ case call_ctrlr(Ctrlr, {address, Node}) of
+ {error, no_node} -> %% No '@' or more than one '@' in node name.
+ ?shutdown(no_node);
+ Res ->
+ Res
+ end
+ end.
+
+setopts_pre_nodeup_fun() ->
+ fun (Ctrlr) ->
+ call_ctrlr(Ctrlr, pre_nodeup)
+ end.
+
+setopts_post_nodeup_fun() ->
+ fun (Ctrlr) ->
+ call_ctrlr(Ctrlr, post_nodeup)
+ end.
+
+handshake_complete_fun() ->
+ fun (Ctrlr, Node, DHandle) ->
+ call_ctrlr(Ctrlr, {handshake_complete, Node, DHandle})
+ end.
+
+call_ctrlr(Ctrlr, Msg) ->
+ Ref = erlang:monitor(process, Ctrlr),
+ Ctrlr ! {Ref, self(), Msg},
+ receive
+ {Ref, Res} ->
+ erlang:demonitor(Ref, [flush]),
+ Res;
+ {'DOWN', Ref, process, Ctrlr, Reason} ->
+ exit({dist_controller_exit, Reason})
+ end.
+
+%%
+%% The tick handler process writes a tick to the
+%% socket when it receives a 'tick' message from
+%% the connection supervisor.
+%%
+%% We are not allowed to block the connection
+%% superviser when writing a tick and we also want
+%% the tick to go through even during a heavily
+%% loaded system. gen_tcp does not have a
+%% non-blocking send operation exposed in its API
+%% and we don't want to run the distribution
+%% controller under high priority. Therefore this
+%% sparate process with max prio that dispatches
+%% ticks.
+%%
+dist_cntrlr_tick_handler(Socket) ->
+ receive
+ tick ->
+ %% May block due to busy port...
+ sock_send(Socket, "");
+ _ ->
+ ok
+ end,
+ dist_cntrlr_tick_handler(Socket).
+
+spawn_dist_cntrlr(Socket) ->
+ spawn_opt(?MODULE, dist_cntrlr_setup, [Socket],
+ [{priority, max}] ++ ?DIST_CNTRL_COMMON_SPAWN_OPTS).
+
+dist_cntrlr_setup(Socket) ->
+ TickHandler = spawn_opt(?MODULE, dist_cntrlr_tick_handler,
+ [Socket],
+ [link, {priority, max}]
+ ++ ?DIST_CNTRL_COMMON_SPAWN_OPTS),
+ dist_cntrlr_setup_loop(Socket, TickHandler, undefined).
+
+%%
+%% During the handshake phase we loop in dist_cntrlr_setup().
+%% When the connection is up we spawn an input handler and
+%% continue as output handler.
+%%
+dist_cntrlr_setup_loop(Socket, TickHandler, Sup) ->
+ receive
+ {tcp_closed, Socket} ->
+ exit(connection_closed);
+
+ {Ref, From, {supervisor, Pid}} ->
+ Res = link(Pid),
+ From ! {Ref, Res},
+ dist_cntrlr_setup_loop(Socket, TickHandler, Pid);
+
+ {Ref, From, tick_handler} ->
+ From ! {Ref, TickHandler},
+ dist_cntrlr_setup_loop(Socket, TickHandler, Sup);
+
+ {Ref, From, socket} ->
+ From ! {Ref, Socket},
+ dist_cntrlr_setup_loop(Socket, TickHandler, Sup);
+
+ {Ref, From, {send, Packet}} ->
+ Res = gen_tcp:send(Socket, Packet),
+ From ! {Ref, Res},
+ dist_cntrlr_setup_loop(Socket, TickHandler, Sup);
+
+ {Ref, From, {recv, Length, Timeout}} ->
+ Res = gen_tcp:recv(Socket, Length, Timeout),
+ From ! {Ref, Res},
+ dist_cntrlr_setup_loop(Socket, TickHandler, Sup);
+
+ {Ref, From, getll} ->
+ From ! {Ref, {ok, self()}},
+ dist_cntrlr_setup_loop(Socket, TickHandler, Sup);
+
+ {Ref, From, {address, Node}} ->
+ Res = case inet:peername(Socket) of
+ {ok, Address} ->
+ case split_node(atom_to_list(Node), $@, []) of
+ [_,Host] ->
+ #net_address{address=Address,host=Host,
+ protocol=tcp, family=inet};
+ _ ->
+ {error, no_node}
+ end
+ end,
+ From ! {Ref, Res},
+ dist_cntrlr_setup_loop(Socket, TickHandler, Sup);
+
+ {Ref, From, pre_nodeup} ->
+ Res = inet:setopts(Socket,
+ [{active, false},
+ {packet, 4},
+ nodelay()]),
+ From ! {Ref, Res},
+ dist_cntrlr_setup_loop(Socket, TickHandler, Sup);
+
+ {Ref, From, post_nodeup} ->
+ Res = inet:setopts(Socket,
+ [{active, false},
+ {packet, 4},
+ nodelay()]),
+ From ! {Ref, Res},
+ dist_cntrlr_setup_loop(Socket, TickHandler, Sup);
+
+ {Ref, From, {handshake_complete, _Node, DHandle}} ->
+ From ! {Ref, ok},
+ %% Handshake complete! Begin dispatching traffic...
+
+ %% We use separate process for dispatching input. This
+ %% is not necessary, but it enables parallel execution
+ %% of independent work loads at the same time as it
+ %% simplifies the the implementation...
+ InputHandler = spawn_opt(?MODULE, dist_cntrlr_input_setup,
+ [DHandle, Socket, Sup],
+ [link] ++ ?DIST_CNTRL_COMMON_SPAWN_OPTS),
+
+ flush_controller(InputHandler, Socket),
+ gen_tcp:controlling_process(Socket, InputHandler),
+ flush_controller(InputHandler, Socket),
+
+ ok = erlang:dist_ctrl_input_handler(DHandle, InputHandler),
+
+ InputHandler ! DHandle,
+
+ %% From now on we execute on normal priority
+ process_flag(priority, normal),
+ erlang:dist_ctrl_get_data_notification(DHandle),
+ dist_cntrlr_output_loop(DHandle, Socket)
+ end.
+
+%% We use active 10 for good throughput while still
+%% maintaining back-pressure if the input controller
+%% isn't able to handle all incoming messages...
+-define(ACTIVE_INPUT, 10).
+
+dist_cntrlr_input_setup(DHandle, Socket, Sup) ->
+ link(Sup),
+ %% Ensure we don't try to put data before registerd
+ %% as input handler...
+ receive
+ DHandle ->
+ dist_cntrlr_input_loop(DHandle, Socket, 0)
+ end.
+
+dist_cntrlr_input_loop(DHandle, Socket, N) when N =< ?ACTIVE_INPUT/2 ->
+ inet:setopts(Socket, [{active, ?ACTIVE_INPUT - N}]),
+ dist_cntrlr_input_loop(DHandle, Socket, ?ACTIVE_INPUT);
+dist_cntrlr_input_loop(DHandle, Socket, N) ->
+ receive
+ {tcp_closed, Socket} ->
+ %% Connection to remote node terminated...
+ exit(connection_closed);
+
+ {tcp, Socket, Data} ->
+ %% Incoming data from remote node...
+ try erlang:dist_ctrl_put_data(DHandle, Data)
+ catch _ : _ -> death_row()
+ end,
+ dist_cntrlr_input_loop(DHandle, Socket, N-1);
+
+ _ ->
+ %% Ignore...
+ dist_cntrlr_input_loop(DHandle, Socket, N)
+ end.
+
+dist_cntrlr_send_data(DHandle, Socket) ->
+ case erlang:dist_ctrl_get_data(DHandle) of
+ none ->
+ erlang:dist_ctrl_get_data_notification(DHandle);
+ Data ->
+ sock_send(Socket, Data),
+ dist_cntrlr_send_data(DHandle, Socket)
+ end.
+
+
+dist_cntrlr_output_loop(DHandle, Socket) ->
+ receive
+ dist_data ->
+ %% Outgoing data from this node...
+ try dist_cntrlr_send_data(DHandle, Socket)
+ catch _ : _ -> death_row()
+ end,
+ dist_cntrlr_output_loop(DHandle, Socket);
+
+ {send, From, Ref, Data} ->
+ %% This is for testing only!
+ %%
+ %% Needed by some OTP distribution
+ %% test suites...
+ sock_send(Socket, Data),
+ From ! {Ref, ok},
+ dist_cntrlr_output_loop(DHandle, Socket);
+
+ _ ->
+ %% Drop garbage message...
+ dist_cntrlr_output_loop(DHandle, Socket)
+
+ end.
+
+sock_send(Socket, Data) ->
+ try gen_tcp:send(Socket, Data) of
+ ok -> ok;
+ {error, Reason} -> death_row({send_error, Reason})
+ catch
+ Type : Reason -> death_row({send_error, {Type, Reason}})
+ end.
+
+death_row() ->
+ death_row(connection_closed).
+
+death_row(normal) ->
+ %% We do not want to exit with normal
+ %% exit reason since it wont bring down
+ %% linked processes...
+ death_row();
+death_row(Reason) ->
+ %% When the connection is on its way down operations
+ %% begin to fail. We catch the failures and call
+ %% this function waiting for termination. We should
+ %% be terminated by one of our links to the other
+ %% involved parties that began bringing the
+ %% connection down. By waiting for termination we
+ %% avoid altering the exit reason for the connection
+ %% teardown. We however limit the wait to 5 seconds
+ %% and bring down the connection ourselves if not
+ %% terminated...
+ receive after 5000 -> exit(Reason) end.
diff --git a/lib/kernel/include/dist.hrl b/lib/kernel/include/dist.hrl
index d6bccdf474..003852f1b0 100644
--- a/lib/kernel/include/dist.hrl
+++ b/lib/kernel/include/dist.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -40,3 +40,8 @@
-define(DFLAG_UTF8_ATOMS, 16#10000).
-define(DFLAG_MAP_TAG, 16#20000).
-define(DFLAG_BIG_CREATION, 16#40000).
+-define(DFLAG_SEND_SENDER, 16#80000).
+-define(DFLAG_BIG_SEQTRACE_LABELS, 16#100000).
+
+%% Also update dflag2str() in ../src/dist_util.erl
+%% when adding flags...
diff --git a/lib/kernel/include/dist_util.hrl b/lib/kernel/include/dist_util.hrl
index e3d2fe0eb6..56f775f060 100644
--- a/lib/kernel/include/dist_util.hrl
+++ b/lib/kernel/include/dist_util.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,9 +29,9 @@
-endif.
-ifdef(dist_trace).
--define(trace(Fmt,Args), io:format("~p ~p:~s",[erlang:timestamp(),node(),lists:flatten(io_lib:format(Fmt, Args))])).
+-define(trace(Fmt,Args), io:format("~p ~p:~s",[erlang:convert_time_unit(erlang:monotonic_time()-erlang:system_info(start_time), native, microsecond),node(),lists:flatten(io_lib:format(Fmt, Args))])).
% Use the one below for config-file (early boot) connection tracing
-%-define(trace(Fmt,Args), erlang:display([erlang:now(),node(),lists:flatten(io_lib:format(Fmt, Args))])).
+%-define(trace(Fmt,Args), erlang:display([erlang:convert_time_unit(erlang:monotonic_time()-erlang:system_info(start_time), native, microsecond),node(),lists:flatten(io_lib:format(Fmt, Args))])).
-define(trace_factor,8).
-else.
-define(trace(Fmt,Args), ok).
@@ -78,7 +78,13 @@
%% New in kernel-5.1 (OTP 19.1):
mf_setopts, %% netkernel:setopts on active connection
- mf_getopts %% netkernel:getopts on active connection
+ mf_getopts, %% netkernel:getopts on active connection
+
+ %% New in kernel-6.0 (OTP 21.0)
+ f_handshake_complete, %% Notify handshake complete
+ add_flags, %% dflags to add
+ reject_flags, %% dflags not to use (not all can be rejected)
+ require_flags %% dflags that are required
}).
diff --git a/lib/kernel/include/logger.hrl b/lib/kernel/include/logger.hrl
new file mode 100644
index 0000000000..b09977e0f2
--- /dev/null
+++ b/lib/kernel/include/logger.hrl
@@ -0,0 +1,53 @@
+-ifndef(LOGGER_HRL).
+-define(LOGGER_HRL,true).
+-define(LOG_EMERGENCY(A),?DO_LOG(emergency,[A])).
+-define(LOG_EMERGENCY(A,B),?DO_LOG(emergency,[A,B])).
+-define(LOG_EMERGENCY(A,B,C),?DO_LOG(emergency,[A,B,C])).
+
+-define(LOG_ALERT(A),?DO_LOG(alert,[A])).
+-define(LOG_ALERT(A,B),?DO_LOG(alert,[A,B])).
+-define(LOG_ALERT(A,B,C),?DO_LOG(alert,[A,B,C])).
+
+-define(LOG_CRITICAL(A),?DO_LOG(critical,[A])).
+-define(LOG_CRITICAL(A,B),?DO_LOG(critical,[A,B])).
+-define(LOG_CRITICAL(A,B,C),?DO_LOG(critical,[A,B,C])).
+
+-define(LOG_ERROR(A),?DO_LOG(error,[A])).
+-define(LOG_ERROR(A,B),?DO_LOG(error,[A,B])).
+-define(LOG_ERROR(A,B,C),?DO_LOG(error,[A,B,C])).
+
+-define(LOG_WARNING(A),?DO_LOG(warning,[A])).
+-define(LOG_WARNING(A,B),?DO_LOG(warning,[A,B])).
+-define(LOG_WARNING(A,B,C),?DO_LOG(warning,[A,B,C])).
+
+-define(LOG_NOTICE(A),?DO_LOG(notice,[A])).
+-define(LOG_NOTICE(A,B),?DO_LOG(notice,[A,B])).
+-define(LOG_NOTICE(A,B,C),?DO_LOG(notice,[A,B,C])).
+
+-define(LOG_INFO(A),?DO_LOG(info,[A])).
+-define(LOG_INFO(A,B),?DO_LOG(info,[A,B])).
+-define(LOG_INFO(A,B,C),?DO_LOG(info,[A,B,C])).
+
+-define(LOG_DEBUG(A),?DO_LOG(debug,[A])).
+-define(LOG_DEBUG(A,B),?DO_LOG(debug,[A,B])).
+-define(LOG_DEBUG(A,B,C),?DO_LOG(debug,[A,B,C])).
+
+-define(LOG(L,A),?DO_LOG(L,[A])).
+-define(LOG(L,A,B),?DO_LOG(L,[A,B])).
+-define(LOG(L,A,B,C),?DO_LOG(L,[A,B,C])).
+
+-define(LOCATION,#{mfa=>{?MODULE,?FUNCTION_NAME,?FUNCTION_ARITY},
+ line=>?LINE,
+ file=>?FILE}).
+
+%%%-----------------------------------------------------------------
+%%% Internal, i.e. not intended for direct use in code - use above
+%%% macros instead!
+-define(DO_LOG(Level,Args),
+ case logger:allow(Level,?MODULE) of
+ true ->
+ apply(logger,macro_log,[?LOCATION,Level|Args]);
+ false ->
+ ok
+ end).
+-endif.
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile
index 5946620f0f..57f17defc8 100644
--- a/lib/kernel/src/Makefile
+++ b/lib/kernel/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2017. All Rights Reserved.
+# Copyright Ericsson AB 1996-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -106,8 +106,21 @@ MODULES = \
inet_sctp \
kernel \
kernel_config \
+ kernel_refc \
local_udp \
local_tcp \
+ logger \
+ logger_backend \
+ logger_config \
+ logger_handler_watcher \
+ logger_std_h \
+ logger_disk_log_h \
+ logger_h_common \
+ logger_filters \
+ logger_formatter \
+ logger_server \
+ logger_simple_h \
+ logger_sup \
net \
net_adm \
net_kernel \
@@ -120,17 +133,25 @@ MODULES = \
user \
user_drv \
user_sup \
+ raw_file_io \
+ raw_file_io_compressed \
+ raw_file_io_inflate \
+ raw_file_io_deflate \
+ raw_file_io_delayed \
+ raw_file_io_list \
+ raw_file_io_raw \
wrap_log_reader
HRL_FILES= ../include/file.hrl ../include/inet.hrl ../include/inet_sctp.hrl \
../include/dist.hrl ../include/dist_util.hrl \
- ../include/net_address.hrl
+ ../include/net_address.hrl ../include/logger.hrl
INTERNAL_HRL_FILES= application_master.hrl disk_log.hrl \
- erl_epmd.hrl hipe_ext_format.hrl \
+ erl_epmd.hrl file_int.hrl hipe_ext_format.hrl \
inet_dns.hrl inet_res.hrl \
inet_boot.hrl inet_config.hrl inet_int.hrl \
- inet_dns_record_adts.hrl
+ inet_dns_record_adts.hrl \
+ logger_internal.hrl logger_h_common.hrl
ERL_FILES= $(MODULES:%=%.erl)
@@ -215,7 +236,7 @@ release_docs_spec:
# Include dependencies -- list below added by Kostis Sagonas
-$(EBIN)/application_controller.beam: application_master.hrl
+$(EBIN)/application_controller.beam: application_master.hrl ../include/logger.hrl
$(EBIN)/application_master.beam: application_master.hrl
$(EBIN)/auth.beam: ../include/file.hrl
$(EBIN)/code.beam: ../include/file.hrl
@@ -226,7 +247,9 @@ $(EBIN)/disk_log_server.beam: disk_log.hrl
$(EBIN)/dist_util.beam: ../include/dist_util.hrl ../include/dist.hrl
$(EBIN)/erl_boot_server.beam: inet_boot.hrl
$(EBIN)/erl_epmd.beam: inet_int.hrl erl_epmd.hrl
-$(EBIN)/file.beam: ../include/file.hrl
+$(EBIN)/error_logger.beam: logger_internal.hrl ../include/logger.hrl
+$(EBIN)/file.beam: ../include/file.hrl file_int.hrl
+$(EBIN)/file_io_server.beam: ../include/file.hrl file_int.hrl
$(EBIN)/gen_tcp.beam: inet_int.hrl
$(EBIN)/gen_udp.beam: inet_int.hrl
$(EBIN)/gen_sctp.beam: ../include/inet_sctp.hrl
@@ -250,7 +273,24 @@ $(EBIN)/inet_udp.beam: inet_int.hrl
$(EBIN)/inet_sctp.beam: inet_int.hrl ../include/inet_sctp.hrl
$(EBIN)/local_udp.beam: inet_int.hrl
$(EBIN)/local_tcp.beam: inet_int.hrl
+$(EBIN)/logger.beam: logger_internal.hrl ../include/logger.hrl
+$(EBIN)/logger_backend.beam: logger_internal.hrl ../include/logger.hrl
+$(EBIN)/logger_config.beam: logger_internal.hrl ../include/logger.hrl
+$(EBIN)/logger_disk_log_h.beam: logger_h_common.hrl logger_internal.hrl ../include/logger.hrl ../include/file.hrl
+$(EBIN)/logger_filters.beam: logger_internal.hrl ../include/logger.hrl
+$(EBIN)/logger_formatter.beam: logger_internal.hrl ../include/logger.hrl
+$(EBIN)/logger_server.beam: logger_internal.hrl ../include/logger.hrl
+$(EBIN)/logger_simple_h.beam: logger_internal.hrl ../include/logger.hrl
+$(EBIN)/logger_std_h.beam: logger_h_common.hrl logger_internal.hrl ../include/logger.hrl ../include/file.hrl
+$(EBIN)/logger_h_common.beam: logger_h_common.hrl logger_internal.hrl ../include/logger.hrl
$(EBIN)/net_kernel.beam: ../include/net_address.hrl
$(EBIN)/os.beam: ../include/file.hrl
$(EBIN)/ram_file.beam: ../include/file.hrl
$(EBIN)/wrap_log_reader.beam: disk_log.hrl ../include/file.hrl
+$(EBIN)/raw_file_io.beam: ../include/file.hrl file_int.hrl
+$(EBIN)/raw_file_io_compressed.beam: ../include/file.hrl file_int.hrl
+$(EBIN)/raw_file_io_inflate.beam: ../include/file.hrl file_int.hrl
+$(EBIN)/raw_file_io_deflate.beam: ../include/file.hrl file_int.hrl
+$(EBIN)/raw_file_io_delayed.beam: ../include/file.hrl file_int.hrl
+$(EBIN)/raw_file_io_list.beam: ../include/file.hrl file_int.hrl
+$(EBIN)/raw_file_io_raw.beam: ../include/file.hrl file_int.hrl
diff --git a/lib/kernel/src/application_controller.erl b/lib/kernel/src/application_controller.erl
index 3b642f5873..a074d2e74b 100644
--- a/lib/kernel/src/application_controller.erl
+++ b/lib/kernel/src/application_controller.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -44,6 +44,7 @@
keyfind/3, keydelete/3, keyreplace/4]).
-include("application_master.hrl").
+-include("logger.hrl").
-define(AC, ?MODULE). % Name of process
@@ -1271,9 +1272,7 @@ load(S, {ApplData, ApplEnv, IncApps, Descr, Id, Vsn, Apps}) ->
NewEnv = merge_app_env(ApplEnv, ConfEnv),
CmdLineEnv = get_cmd_env(Name),
NewEnv2 = merge_app_env(NewEnv, CmdLineEnv),
- NewEnv3 = keyreplaceadd(included_applications, 1, NewEnv2,
- {included_applications, IncApps}),
- add_env(Name, NewEnv3),
+ add_env(Name, NewEnv2),
Appl = #appl{name = Name, descr = Descr, id = Id, vsn = Vsn,
appl_data = ApplData, inc_apps = IncApps, apps = Apps},
ets:insert(ac_tab, {{loaded, Name}, Appl}),
@@ -1291,7 +1290,7 @@ load(S, {ApplData, ApplEnv, IncApps, Descr, Id, Vsn, Apps}) ->
{ok, NewS}.
unload(AppName, S) ->
- {ok, IncApps} = get_env(AppName, included_applications),
+ {ok, IncApps} = get_key(AppName, included_applications),
del_env(AppName),
ets:delete(ac_tab, {loaded, AppName}),
foldl(fun(App, S1) ->
@@ -1546,9 +1545,8 @@ do_change_apps(Applications, Config, OldAppls) ->
%% Report errors, but do not terminate
%% (backwards compatible behaviour)
lists:foreach(fun({error, {SysFName, Line, Str}}) ->
- Str2 = lists:flatten(io_lib:format("~tp: ~w: ~ts~n",
- [SysFName, Line, Str])),
- error_logger:format(Str2, [])
+ ?LOG_ERROR("~tp: ~w: ~ts~n",[SysFName, Line, Str],
+ #{error_logger=>#{tag=>error}})
end,
Errors),
@@ -1583,13 +1581,9 @@ do_change_appl({ok, {ApplData, Env, IncApps, Descr, Id, Vsn, Apps}},
CmdLineEnv = get_cmd_env(AppName),
NewEnv2 = merge_app_env(NewEnv1, CmdLineEnv),
- %% included_apps is made into an env parameter as well
- NewEnv3 = keyreplaceadd(included_applications, 1, NewEnv2,
- {included_applications, IncApps}),
-
%% Update ets table with new application env
del_env(AppName),
- add_env(AppName, NewEnv3),
+ add_env(AppName, NewEnv2),
OldAppl#appl{appl_data=ApplData,
descr=Descr,
@@ -1631,8 +1625,9 @@ make_term(Str) ->
end.
handle_make_term_error(Mod, Reason, Str) ->
- error_logger:format("application_controller: ~ts: ~ts~n",
- [Mod:format_error(Reason), Str]),
+ ?LOG_ERROR("application_controller: ~ts: ~ts~n",
+ [Mod:format_error(Reason), Str],
+ #{error_logger=>#{tag=>error}}),
throw({error, {bad_environment_value, Str}}).
get_env_i(Name, #state{conf_data = ConfData}) when is_list(ConfData) ->
@@ -1819,8 +1814,9 @@ check_conf() ->
%% Therefore read and merge contents.
if
BFName =:= "sys" ->
+ DName = filename:dirname(FName),
{ok, SysEnv, Errors} =
- check_conf_sys(NewEnv),
+ check_conf_sys(NewEnv, [], [], DName),
%% Report first error, if any, and
%% terminate
@@ -1842,20 +1838,31 @@ check_conf() ->
end.
check_conf_sys(Env) ->
- check_conf_sys(Env, [], []).
+ check_conf_sys(Env, [], [], []).
-check_conf_sys([File|T], SysEnv, Errors) when is_list(File) ->
+check_conf_sys([File|T], SysEnv, Errors, DName) when is_list(File),is_list(DName) ->
BFName = filename:basename(File, ".config"),
FName = filename:join(filename:dirname(File), BFName ++ ".config"),
- case load_file(FName) of
+ LName = case filename:pathtype(FName) of
+ relative when (DName =/= []) ->
+ % Check if relative to sys.config dir otherwise use legacy mode,
+ % i.e relative to cwd.
+ RName = filename:join(DName, FName),
+ case erl_prim_loader:read_file_info(RName) of
+ {ok, _} -> RName ;
+ error -> FName
+ end;
+ _ -> FName
+ end,
+ case load_file(LName) of
{ok, NewEnv} ->
- check_conf_sys(T, merge_env(SysEnv, NewEnv), Errors);
+ check_conf_sys(T, merge_env(SysEnv, NewEnv), Errors, DName);
{error, {Line, _Mod, Str}} ->
- check_conf_sys(T, SysEnv, [{error, {FName, Line, Str}}|Errors])
+ check_conf_sys(T, SysEnv, [{error, {LName, Line, Str}}|Errors], DName)
end;
-check_conf_sys([Tuple|T], SysEnv, Errors) ->
- check_conf_sys(T, merge_env(SysEnv, [Tuple]), Errors);
-check_conf_sys([], SysEnv, Errors) ->
+check_conf_sys([Tuple|T], SysEnv, Errors, DName) ->
+ check_conf_sys(T, merge_env(SysEnv, [Tuple]), Errors, DName);
+check_conf_sys([], SysEnv, Errors, _) ->
{ok, SysEnv, lists:reverse(Errors)}.
load_file(File) ->
@@ -1913,19 +1920,25 @@ config_error() ->
"configuration file must contain ONE list ended by <dot>"}}.
%%-----------------------------------------------------------------
-%% Info messages sent to error_logger
+%% Info messages sent to logger
%%-----------------------------------------------------------------
info_started(Name, Node) ->
- Rep = [{application, Name},
- {started_at, Node}],
- error_logger:info_report(progress, Rep).
+ ?LOG_INFO(#{label=>{application_controller,progress},
+ report=>[{application, Name},
+ {started_at, Node}]},
+ #{domain=>[otp,sasl],
+ report_cb=>fun logger:format_otp_report/1,
+ logger_formatter=>#{title=>"PROGRESS REPORT"},
+ error_logger=>#{tag=>info_report,type=>progress}}).
info_exited(Name, Reason, Type) ->
- Rep = [{application, Name},
- {exited, Reason},
- {type, Type}],
- error_logger:info_report(Rep).
-
+ ?LOG_NOTICE(#{label=>{application_controller,exit},
+ report=>[{application, Name},
+ {exited, Reason},
+ {type, Type}]},
+ #{domain=>[otp],
+ report_cb=>fun logger:format_otp_report/1,
+ error_logger=>#{tag=>info_report,type=>std_info}}).
%%-----------------------------------------------------------------
%% Reply to all processes waiting this application to be started.
@@ -2012,5 +2025,5 @@ to_string(Term) ->
true ->
Term;
false ->
- lists:flatten(io_lib:format("~134217728p", [Term]))
+ lists:flatten(io_lib:format("~0p", [Term]))
end.
diff --git a/lib/kernel/src/application_master.erl b/lib/kernel/src/application_master.erl
index 5da2b0b06c..8697143dfb 100644
--- a/lib/kernel/src/application_master.erl
+++ b/lib/kernel/src/application_master.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -118,6 +118,10 @@ init(Parent, Starter, ApplData, Type) ->
link(Parent),
process_flag(trap_exit, true),
OldGleader = group_leader(),
+ %% We become the group leader, but forward all I/O to OldGleader.
+ %% This is just a way to identify processes that belong to the
+ %% application. Used for example to find ourselves from any
+ %% process, or, reciprocally, to kill them all when we terminate.
group_leader(self(), self()),
%% Insert ourselves as master for the process. This ensures that
%% the processes in the application can use get_env/1 at startup.
diff --git a/lib/kernel/src/auth.erl b/lib/kernel/src/auth.erl
index 40feee6bf0..4d18daf9e4 100644
--- a/lib/kernel/src/auth.erl
+++ b/lib/kernel/src/auth.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -107,7 +107,7 @@ get_cookie() ->
get_cookie(_Node) when node() =:= nonode@nohost ->
nocookie;
get_cookie(Node) ->
- gen_server:call(auth, {get_cookie, Node}).
+ gen_server:call(auth, {get_cookie, Node}, infinity).
-spec set_cookie(Cookie :: cookie()) -> 'true'.
@@ -119,12 +119,12 @@ set_cookie(Cookie) ->
set_cookie(_Node, _Cookie) when node() =:= nonode@nohost ->
erlang:error(distribution_not_started);
set_cookie(Node, Cookie) ->
- gen_server:call(auth, {set_cookie, Node, Cookie}).
+ gen_server:call(auth, {set_cookie, Node, Cookie}, infinity).
-spec sync_cookie() -> any().
sync_cookie() ->
- gen_server:call(auth, sync_cookie).
+ gen_server:call(auth, sync_cookie, infinity).
-spec print(Node :: node(), Format :: string(), Args :: [_]) -> 'ok'.
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index 9969021a6c..7faef93609 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -149,8 +149,11 @@ load_file(Mod) when is_atom(Mod) ->
-spec ensure_loaded(Module) -> {module, Module} | {error, What} when
Module :: module(),
What :: embedded | badfile | nofile | on_load_failure.
-ensure_loaded(Mod) when is_atom(Mod) ->
- call({ensure_loaded,Mod}).
+ensure_loaded(Mod) when is_atom(Mod) ->
+ case erlang:module_loaded(Mod) of
+ true -> {module, Mod};
+ false -> call({ensure_loaded,Mod})
+ end.
%% XXX File as an atom is allowed only for backwards compatibility.
-spec load_abs(Filename) -> load_ret() when
@@ -627,7 +630,7 @@ do_par_recv(N, Good, Bad) ->
call(Req) ->
code_server:call(Req).
--spec start_link() -> {'ok', pid()} | {'error', 'crash'}.
+-spec start_link() -> {'ok', pid()}.
start_link() ->
do_start().
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index 418b0c50e1..1b4a67ecb7 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -340,8 +340,7 @@ handle_call(all_loaded, _From, S) ->
{reply,all_loaded(Db),S};
handle_call({get_object_code,Mod}, _From, St) when is_atom(Mod) ->
- Path = St#state.path,
- case mod_to_bin(Path, Mod) of
+ case get_object_code(St, Mod) of
{_,Bin,FName} -> {reply,{Mod,Bin,FName},St};
Error -> {reply,Error,St}
end;
@@ -1182,19 +1181,28 @@ load_file(Mod, From, St0) ->
end,
handle_pending_on_load(Action, Mod, From, St0).
-load_file_1(Mod, From, #state{path=Path}=St) ->
- case mod_to_bin(Path, Mod) of
+load_file_1(Mod, From, St) ->
+ case get_object_code(St, Mod) of
error ->
{reply,{error,nofile},St};
{Mod,Binary,File} ->
try_load_module_1(File, Mod, Binary, From, St)
end.
-mod_to_bin([Dir|Tail], Mod) ->
- File = filename:append(Dir, atom_to_list(Mod) ++ objfile_extension()),
+get_object_code(#state{path=Path}, Mod) when is_atom(Mod) ->
+ ModStr = atom_to_list(Mod),
+ case erl_prim_loader:is_basename(ModStr) of
+ true ->
+ mod_to_bin(Path, Mod, ModStr ++ objfile_extension());
+ false ->
+ error
+ end.
+
+mod_to_bin([Dir|Tail], Mod, ModFile) ->
+ File = filename:append(Dir, ModFile),
case erl_prim_loader:get_file(File) of
error ->
- mod_to_bin(Tail, Mod);
+ mod_to_bin(Tail, Mod, ModFile);
{ok,Bin,_} ->
case filename:pathtype(File) of
absolute ->
@@ -1203,10 +1211,9 @@ mod_to_bin([Dir|Tail], Mod) ->
{Mod,Bin,absname(File)}
end
end;
-mod_to_bin([], Mod) ->
+mod_to_bin([], Mod, ModFile) ->
%% At last, try also erl_prim_loader's own method
- File = to_list(Mod) ++ objfile_extension(),
- case erl_prim_loader:get_file(File) of
+ case erl_prim_loader:get_file(ModFile) of
error ->
error; % No more alternatives !
{ok,Bin,FName} ->
@@ -1427,14 +1434,20 @@ all_loaded(Db) ->
-spec error_msg(io:format(), [term()]) -> 'ok'.
error_msg(Format, Args) ->
- Msg = {notify,{error, group_leader(), {self(), Format, Args}}},
- error_logger ! Msg,
+ logger ! {log,error,Format,Args,
+ #{pid=>self(),
+ gl=>group_leader(),
+ time=>erlang:system_time(microsecond),
+ error_logger=>#{tag=>error}}},
ok.
-spec info_msg(io:format(), [term()]) -> 'ok'.
info_msg(Format, Args) ->
- Msg = {notify,{info_msg, group_leader(), {self(), Format, Args}}},
- error_logger ! Msg,
+ logger ! {log,info,Format,Args,
+ #{pid=>self(),
+ gl=>group_leader(),
+ time=>erlang:system_time(microsecond),
+ error_logger=>#{tag=>info_msg}}},
ok.
objfile_extension() ->
diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl
index 70cbf1c87c..99ea8dc384 100644
--- a/lib/kernel/src/disk_log.erl
+++ b/lib/kernel/src/disk_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -266,7 +266,7 @@ inc_wrap_file(Log) ->
Size :: dlog_size(),
Reason :: no_such_log | nonode | {read_only_mode, Log}
| {blocked_log, Log}
- | {new_size_too_small, CurrentSize :: pos_integer()}
+ | {new_size_too_small, Log, CurrentSize :: pos_integer()}
| {badarg, size}
| {file_error, file:filename(), file_error()}.
change_size(Log, NewSize) ->
diff --git a/lib/kernel/src/disk_log_1.erl b/lib/kernel/src/disk_log_1.erl
index 93856aa7b3..41ef33c613 100644
--- a/lib/kernel/src/disk_log_1.erl
+++ b/lib/kernel/src/disk_log_1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -630,7 +630,7 @@ is_head(Bin) when is_binary(Bin) ->
%% Writes MaxB bytes on each file.
%% Creates a file called Name.idx in the Dir. This
%% file contains the last written FileName as one byte, and
-%% follwing that, the sizes of each file (size 0 number of items).
+%% following that, the sizes of each file (size 0 number of items).
%% On startup, this file is read, and the next available
%% filename is used as first log file.
%% Reports can be browsed with Report Browser Tool (rb), or
diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl
index b3507e5d13..ecc022b28d 100644
--- a/lib/kernel/src/dist_util.erl
+++ b/lib/kernel/src/dist_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,8 +27,10 @@
%%-compile(export_all).
-export([handshake_we_started/1, handshake_other_started/1,
+ strict_order_flags/0,
start_timer/1, setup_timer/2,
reset_timer/1, cancel_timer/1,
+ is_node_name/1, split_node/1, is_allowed/2,
shutdown/3, shutdown/4]).
-import(error_logger,[error_msg/2]).
@@ -74,22 +76,52 @@
ticked = 0
}).
-remove_flag(Flag, Flags) ->
- case Flags band Flag of
- 0 ->
- Flags;
- _ ->
- Flags - Flag
- end.
+dflag2str(?DFLAG_PUBLISHED) ->
+ "PUBLISHED";
+dflag2str(?DFLAG_ATOM_CACHE) ->
+ "ATOM_CACHE";
+dflag2str(?DFLAG_EXTENDED_REFERENCES) ->
+ "EXTENDED_REFERENCES";
+dflag2str(?DFLAG_DIST_MONITOR) ->
+ "DIST_MONITOR";
+dflag2str(?DFLAG_FUN_TAGS) ->
+ "FUN_TAGS";
+dflag2str(?DFLAG_DIST_MONITOR_NAME) ->
+ "DIST_MONITOR_NAME";
+dflag2str(?DFLAG_HIDDEN_ATOM_CACHE) ->
+ "HIDDEN_ATOM_CACHE";
+dflag2str(?DFLAG_NEW_FUN_TAGS) ->
+ "NEW_FUN_TAGS";
+dflag2str(?DFLAG_EXTENDED_PIDS_PORTS) ->
+ "EXTENDED_PIDS_PORTS";
+dflag2str(?DFLAG_EXPORT_PTR_TAG) ->
+ "EXPORT_PTR_TAG";
+dflag2str(?DFLAG_BIT_BINARIES) ->
+ "BIT_BINARIES";
+dflag2str(?DFLAG_NEW_FLOATS) ->
+ "NEW_FLOATS";
+dflag2str(?DFLAG_UNICODE_IO) ->
+ "UNICODE_IO";
+dflag2str(?DFLAG_DIST_HDR_ATOM_CACHE) ->
+ "DIST_HDR_ATOM_CACHE";
+dflag2str(?DFLAG_SMALL_ATOM_TAGS) ->
+ "SMALL_ATOM_TAGS";
+dflag2str(?DFLAG_UTF8_ATOMS) ->
+ "UTF8_ATOMS";
+dflag2str(?DFLAG_MAP_TAG) ->
+ "MAP_TAG";
+dflag2str(?DFLAG_BIG_CREATION) ->
+ "BIG_CREATION";
+dflag2str(?DFLAG_SEND_SENDER) ->
+ "SEND_SENDER";
+dflag2str(?DFLAG_BIG_SEQTRACE_LABELS) ->
+ "BIG_SEQTRACE_LABELS";
+dflag2str(_) ->
+ "UNKNOWN".
+
adjust_flags(ThisFlags, OtherFlags) ->
- case (?DFLAG_PUBLISHED band ThisFlags) band OtherFlags of
- 0 ->
- {remove_flag(?DFLAG_PUBLISHED, ThisFlags),
- remove_flag(?DFLAG_PUBLISHED, OtherFlags)};
- _ ->
- {ThisFlags, OtherFlags}
- end.
+ ThisFlags band OtherFlags.
publish_flag(hidden, _) ->
0;
@@ -101,38 +133,56 @@ publish_flag(_, OtherNode) ->
0
end.
-make_this_flags(RequestType, OtherNode) ->
- publish_flag(RequestType, OtherNode) bor
- %% The parenthesis below makes the compiler generate better code.
- (?DFLAG_EXPORT_PTR_TAG bor
- ?DFLAG_EXTENDED_PIDS_PORTS bor
- ?DFLAG_EXTENDED_REFERENCES bor
- ?DFLAG_DIST_MONITOR bor
- ?DFLAG_FUN_TAGS bor
- ?DFLAG_DIST_MONITOR_NAME bor
- ?DFLAG_HIDDEN_ATOM_CACHE bor
- ?DFLAG_NEW_FUN_TAGS bor
- ?DFLAG_BIT_BINARIES bor
- ?DFLAG_NEW_FLOATS bor
- ?DFLAG_UNICODE_IO bor
- ?DFLAG_DIST_HDR_ATOM_CACHE bor
- ?DFLAG_SMALL_ATOM_TAGS bor
- ?DFLAG_UTF8_ATOMS bor
- ?DFLAG_MAP_TAG bor
- ?DFLAG_BIG_CREATION).
-
-handshake_other_started(#hs_data{request_type=ReqType}=HSData0) ->
+
+%% Sync with dist.c
+-record(erts_dflags, {
+ default, % flags erts prefers
+ mandatory, % flags erts needs
+ addable, % flags local dist implementation is allowed to add
+ rejectable, % flags local dist implementation is allowed to reject
+ strict_order % flags for features needing strict order delivery
+}).
+
+-spec strict_order_flags() -> integer().
+strict_order_flags() ->
+ EDF = erts_internal:get_dflags(),
+ EDF#erts_dflags.strict_order.
+
+make_this_flags(RequestType, AddFlags, RejectFlags, OtherNode,
+ #erts_dflags{}=EDF) ->
+ case RejectFlags band (bnot EDF#erts_dflags.rejectable) of
+ 0 -> ok;
+ Rerror -> exit({"Rejecting non rejectable flags", Rerror})
+ end,
+ case AddFlags band (bnot EDF#erts_dflags.addable) of
+ 0 -> ok;
+ Aerror -> exit({"Adding non addable flags", Aerror})
+ end,
+ Flgs0 = EDF#erts_dflags.default,
+ Flgs1 = Flgs0 bor publish_flag(RequestType, OtherNode),
+ Flgs2 = Flgs1 bor AddFlags,
+ Flgs2 band (bnot RejectFlags).
+
+handshake_other_started(#hs_data{request_type=ReqType,
+ add_flags=AddFlgs0,
+ reject_flags=RejFlgs0,
+ require_flags=ReqFlgs0}=HSData0) ->
+ AddFlgs = convert_flags(AddFlgs0),
+ RejFlgs = convert_flags(RejFlgs0),
+ ReqFlgs = convert_flags(ReqFlgs0),
{PreOtherFlags,Node,Version} = recv_name(HSData0),
- PreThisFlags = make_this_flags(ReqType, Node),
- {ThisFlags, OtherFlags} = adjust_flags(PreThisFlags,
- PreOtherFlags),
- HSData = HSData0#hs_data{this_flags=ThisFlags,
- other_flags=OtherFlags,
+ EDF = erts_internal:get_dflags(),
+ PreThisFlags = make_this_flags(ReqType, AddFlgs, RejFlgs, Node, EDF),
+ ChosenFlags = adjust_flags(PreThisFlags, PreOtherFlags),
+ HSData = HSData0#hs_data{this_flags=ChosenFlags,
+ other_flags=ChosenFlags,
other_version=Version,
other_node=Node,
- other_started=true},
- check_dflags(HSData),
- is_allowed(HSData),
+ other_started=true,
+ add_flags=AddFlgs,
+ reject_flags=RejFlgs,
+ require_flags=ReqFlgs},
+ check_dflags(HSData, EDF),
?debug({"MD5 connection from ~p (V~p)~n",
[Node, HSData#hs_data.other_version]}),
mark_pending(HSData),
@@ -150,38 +200,16 @@ handshake_other_started(OldHsData) when element(1,OldHsData) =:= hs_data ->
%%
-%% check if connecting node is allowed to connect
-%% with allow-node-scheme
-%%
-is_allowed(#hs_data{other_node = Node,
- allowed = Allowed} = HSData) ->
- case lists:member(Node, Allowed) of
- false when Allowed =/= [] ->
- send_status(HSData, not_allowed),
- error_msg("** Connection attempt from "
- "disallowed node ~w ** ~n", [Node]),
- ?shutdown2(Node, {is_allowed, not_allowed});
- _ -> true
- end.
-
-%%
-%% Check that both nodes can handle the same types of extended
-%% node containers. If they can not, abort the connection.
+%% Check mandatory flags...
%%
check_dflags(#hs_data{other_node = Node,
other_flags = OtherFlags,
- other_started = OtherStarted} = HSData) ->
-
- Mandatory = [{?DFLAG_EXTENDED_REFERENCES, "EXTENDED_REFERENCES"},
- {?DFLAG_EXTENDED_PIDS_PORTS, "EXTENDED_PIDS_PORTS"},
- {?DFLAG_UTF8_ATOMS, "UTF8_ATOMS"}],
- Missing = lists:filtermap(fun({Bit, Str}) ->
- case Bit band OtherFlags of
- Bit -> false;
- 0 -> {true, Str}
- end
- end,
- Mandatory),
+ other_started = OtherStarted,
+ require_flags = RequiredFlags} = HSData,
+ #erts_dflags{}=EDF) ->
+
+ Mandatory = (EDF#erts_dflags.mandatory bor RequiredFlags),
+ Missing = check_mandatory(Mandatory, OtherFlags, []),
case Missing of
[] ->
ok;
@@ -201,6 +229,21 @@ check_dflags(#hs_data{other_node = Node,
?shutdown2(Node, {check_dflags_failed, Missing})
end.
+check_mandatory(0, _OtherFlags, Missing) ->
+ Missing;
+check_mandatory(Mandatory, OtherFlags, Missing) ->
+ Left = Mandatory band (Mandatory - 1), % clear lowest set bit
+ DFlag = Mandatory bxor Left, % only lowest set bit
+ NewMissing = case DFlag band OtherFlags of
+ 0 ->
+ %% Mandatory and missing...
+ [dflag2str(DFlag) | Missing];
+ _ ->
+ %% Mandatory and present...
+ Missing
+ end,
+ check_mandatory(Left, OtherFlags, NewMissing).
+
%% No nodedown will be sent if we fail before this process has
%% succeeded to mark the node as pending.
@@ -314,17 +357,27 @@ flush_down() ->
end.
handshake_we_started(#hs_data{request_type=ReqType,
- other_node=Node}=PreHSData) ->
- PreThisFlags = make_this_flags(ReqType, Node),
- HSData = PreHSData#hs_data{this_flags=PreThisFlags},
+ other_node=Node,
+ add_flags=AddFlgs0,
+ reject_flags=RejFlgs0,
+ require_flags=ReqFlgs0}=PreHSData) ->
+ AddFlgs = convert_flags(AddFlgs0),
+ RejFlgs = convert_flags(RejFlgs0),
+ ReqFlgs = convert_flags(ReqFlgs0),
+ EDF = erts_internal:get_dflags(),
+ PreThisFlags = make_this_flags(ReqType, AddFlgs, RejFlgs, Node, EDF),
+ HSData = PreHSData#hs_data{this_flags = PreThisFlags,
+ add_flags = AddFlgs,
+ reject_flags = RejFlgs,
+ require_flags = ReqFlgs},
send_name(HSData),
recv_status(HSData),
{PreOtherFlags,ChallengeA} = recv_challenge(HSData),
- {ThisFlags,OtherFlags} = adjust_flags(PreThisFlags, PreOtherFlags),
- NewHSData = HSData#hs_data{this_flags = ThisFlags,
- other_flags = OtherFlags,
+ ChosenFlags = adjust_flags(PreThisFlags, PreOtherFlags),
+ NewHSData = HSData#hs_data{this_flags = ChosenFlags,
+ other_flags = ChosenFlags,
other_started = false},
- check_dflags(NewHSData),
+ check_dflags(NewHSData, EDF),
MyChallenge = gen_challenge(),
{MyCookie,HisCookie} = get_cookies(Node),
send_challenge_reply(NewHSData,MyChallenge,
@@ -336,15 +389,16 @@ handshake_we_started(#hs_data{request_type=ReqType,
handshake_we_started(OldHsData) when element(1,OldHsData) =:= hs_data ->
handshake_we_started(convert_old_hsdata(OldHsData)).
-convert_old_hsdata({hs_data, KP, ON, TN, S, T, TF, A, OV, OF, OS, FS, FR,
- FS_PRE, FS_POST, FG, FA, MFT, MFG, RT}) ->
- #hs_data{
- kernel_pid = KP, other_node = ON, this_node = TN, socket = S, timer = T,
- this_flags = TF, allowed = A, other_version = OV, other_flags = OF,
- other_started = OS, f_send = FS, f_recv = FR, f_setopts_pre_nodeup = FS_PRE,
- f_setopts_post_nodeup = FS_POST, f_getll = FG, f_address = FA,
- mf_tick = MFT, mf_getstat = MFG, request_type = RT}.
+convert_old_hsdata(OldHsData) ->
+ OHSDL = tuple_to_list(OldHsData),
+ NoMissing = tuple_size(#hs_data{}) - tuple_size(OldHsData),
+ true = NoMissing > 0,
+ list_to_tuple(OHSDL ++ lists:duplicate(NoMissing, undefined)).
+convert_flags(Flags) when is_integer(Flags) ->
+ Flags;
+convert_flags(_Undefined) ->
+ 0.
%% --------------------------------------------------------------
%% The connection has been established.
@@ -359,15 +413,20 @@ connection(#hs_data{other_node = Node,
PType = publish_type(HSData#hs_data.other_flags),
case FPreNodeup(Socket) of
ok ->
- do_setnode(HSData), % Succeeds or exits the process.
+ DHandle = do_setnode(HSData), % Succeeds or exits the process.
Address = FAddress(Socket,Node),
mark_nodeup(HSData,Address),
case FPostNodeup(Socket) of
ok ->
+ case HSData#hs_data.f_handshake_complete of
+ undefined -> ok;
+ HsComplete -> HsComplete(Socket, Node, DHandle)
+ end,
con_loop({HSData#hs_data.kernel_pid,
Node,
Socket,
PType,
+ DHandle,
HSData#hs_data.mf_tick,
HSData#hs_data.mf_getstat,
HSData#hs_data.mf_setopts,
@@ -425,18 +484,16 @@ do_setnode(#hs_data{other_node = Node, socket = Socket,
[Node, Port, {publish_type(Flags),
'(', Flags, ')',
Version}]),
- case (catch
- erlang:setnode(Node, Port,
- {Flags, Version, '', ''})) of
- {'EXIT', {system_limit, _}} ->
+ try
+ erlang:setnode(Node, Port, {Flags, Version, '', ''})
+ catch
+ error:system_limit ->
error_msg("** Distribution system limit reached, "
"no table space left for node ~w ** ~n",
[Node]),
?shutdown(Node);
- {'EXIT', Other} ->
- exit(Other);
- _Else ->
- ok
+ error:Other:Stacktrace ->
+ exit({Other, Stacktrace})
end;
_ ->
error_msg("** Distribution connection error, "
@@ -468,7 +525,13 @@ mark_nodeup(#hs_data{kernel_pid = Kernel,
?shutdown(Node)
end.
-con_loop({Kernel, Node, Socket, Type, MFTick, MFGetstat, MFSetOpts, MFGetOpts}=ConData,
+getstat(DHandle, _Socket, undefined) ->
+ erlang:dist_get_stat(DHandle);
+getstat(_DHandle, Socket, MFGetstat) ->
+ MFGetstat(Socket).
+
+con_loop({Kernel, Node, Socket, Type, DHandle, MFTick, MFGetstat,
+ MFSetOpts, MFGetOpts}=ConData,
Tick) ->
receive
{tcp_closed, Socket} ->
@@ -476,15 +539,15 @@ con_loop({Kernel, Node, Socket, Type, MFTick, MFGetstat, MFSetOpts, MFGetOpts}=C
{Kernel, disconnect} ->
?shutdown2(Node, disconnected);
{Kernel, aux_tick} ->
- case MFGetstat(Socket) of
+ case getstat(DHandle, Socket, MFGetstat) of
{ok, _, _, PendWrite} ->
- send_tick(Socket, PendWrite, MFTick);
+ send_aux_tick(Type, Socket, PendWrite, MFTick);
_ ->
ignore_it
end,
con_loop(ConData, Tick);
{Kernel, tick} ->
- case send_tick(Socket, Tick, Type,
+ case send_tick(DHandle, Socket, Tick, Type,
MFTick, MFGetstat) of
{ok, NewTick} ->
con_loop(ConData, NewTick);
@@ -497,7 +560,7 @@ con_loop({Kernel, Node, Socket, Type, MFTick, MFGetstat, MFSetOpts, MFGetOpts}=C
?shutdown2(Node, send_net_tick_failed)
end;
{From, get_status} ->
- case MFGetstat(Socket) of
+ case getstat(DHandle, Socket, MFGetstat) of
{ok, Read, Write, _} ->
From ! {self(), get_status, {ok, Read, Write}},
con_loop(ConData, Tick);
@@ -564,33 +627,130 @@ send_challenge_ack(#hs_data{socket = Socket, f_send = FSend},
%% tcp_drv.c which used it to detect simultaneous connection
%% attempts).
%%
-recv_name(#hs_data{socket = Socket, f_recv = Recv}) ->
+recv_name(#hs_data{socket = Socket, f_recv = Recv} = HSData) ->
case Recv(Socket, 0, infinity) of
- {ok,Data} ->
- get_name(Data);
+ {ok,
+ [$n,VersionA, VersionB, Flag1, Flag2, Flag3, Flag4
+ | OtherNode] = Data} ->
+ case is_node_name(OtherNode) of
+ true ->
+ Flags = ?u32(Flag1, Flag2, Flag3, Flag4),
+ Version = ?u16(VersionA,VersionB),
+ is_allowed(HSData, Flags, OtherNode, Version);
+ false ->
+ ?shutdown(Data)
+ end;
_ ->
?shutdown(no_node)
end.
-get_name([$n,VersionA, VersionB, Flag1, Flag2, Flag3, Flag4 | OtherNode] = Data) ->
- case is_valid_name(OtherNode) of
+is_node_name(OtherNodeName) ->
+ case string:split(OtherNodeName, "@", all) of
+ [Name,Host] ->
+ (not string:is_empty(Name))
+ andalso (not string:is_empty(Host));
+ _ ->
+ false
+ end.
+
+split_node(Node) ->
+ Split = string:split(listify(Node), "@", all),
+ case Split of
+ [Name,Host] ->
+ case string:is_empty(Name) of
+ true ->
+ Split;
+ false ->
+ case string:is_empty(Host) of
+ true ->
+ {name,Name};
+ false ->
+ {node,Name,Host}
+ end
+ end;
+ [Host] ->
+ case string:is_empty(Host) of
+ true ->
+ Split;
+ false ->
+ {host,Host}
+ end
+ end.
+
+%% Check if connecting node is allowed to connect
+%% with allow-node-scheme. An empty allowed list
+%% allows all nodes.
+%%
+is_allowed(#hs_data{allowed = []}, Flags, Node, Version) ->
+ {Flags,list_to_atom(Node),Version};
+is_allowed(#hs_data{allowed = Allowed} = HSData, Flags, Node, Version) ->
+ case is_allowed(Node, Allowed) of
true ->
- {?u32(Flag1, Flag2, Flag3, Flag4), list_to_atom(OtherNode),
- ?u16(VersionA,VersionB)};
+ {Flags,list_to_atom(Node),Version};
false ->
- ?shutdown(Data)
- end;
-get_name(Data) ->
- ?shutdown(Data).
-
-is_valid_name(OtherNodeName) ->
- case string:lexemes(OtherNodeName,"@") of
- [_OtherNodeName,_OtherNodeHost] ->
- true;
- _else ->
- false
+ send_status(HSData#hs_data{other_node = Node}, not_allowed),
+ error_msg("** Connection attempt from "
+ "disallowed node ~s ** ~n", [Node]),
+ ?shutdown2(Node, {is_allowed, not_allowed})
+ end.
+
+%% The allowed list can contain node names, host names
+%% or names before '@', in atom or list form:
+%% [[email protected], "host.example.org", "node@"].
+%% An empty allowed list allows no nodes.
+%%
+%% Allow a node that matches any entry in the allowed list.
+%% Also allow allowed entries as node to match, not from
+%% this module; here the node has to be a valid name.
+%%
+is_allowed(_Node, []) ->
+ false;
+is_allowed(Node, [Node|_Allowed]) ->
+ %% Just an optimization
+ true;
+is_allowed(Node, [AllowedNode|Allowed]) ->
+ case split_node(AllowedNode) of
+ {node,AllowedName,AllowedHost} ->
+ %% Allowed node name
+ case split_node(Node) of
+ {node,AllowedName,AllowedHost} ->
+ true;
+ _ ->
+ is_allowed(Node, Allowed)
+ end;
+ {host,AllowedHost} ->
+ %% Allowed host name
+ case split_node(Node) of
+ {node,_,AllowedHost} ->
+ %% Matching Host part
+ true;
+ {host,AllowedHost} ->
+ %% Host matches Host
+ true;
+ _ ->
+ is_allowed(Node, Allowed)
+ end;
+ {name,AllowedName} ->
+ %% Allowed name before '@'
+ case split_node(Node) of
+ {node,AllowedName,_} ->
+ %% Matching Name part
+ true;
+ {name,AllowedName} ->
+ %% Name matches Name
+ true;
+ _ ->
+ is_allowed(Node, Allowed)
+ end;
+ _ ->
+ is_allowed(Node, Allowed)
end.
+listify(Atom) when is_atom(Atom) ->
+ atom_to_list(Atom);
+listify(Node) when is_list(Node) ->
+ Node.
+
publish_type(Flags) ->
case Flags band ?DFLAG_PUBLISHED of
0 ->
@@ -731,51 +891,57 @@ send_status(#hs_data{socket = Socket, other_node = Node,
%% The detection time interval is thus, by default, 45s < DT < 75s
-%% A HIDDEN node is always (if not a pending write) ticked if
-%% we haven't read anything as a hidden node only ticks when it receives
-%% a TICK !!
+%% A HIDDEN node is always ticked if we haven't read anything
+%% as a (primitive) hidden node only ticks when it receives a TICK !!
-send_tick(Socket, Tick, Type, MFTick, MFGetstat) ->
+send_tick(DHandle, Socket, Tick, Type, MFTick, MFGetstat) ->
#tick{tick = T0,
read = Read,
write = Write,
- ticked = Ticked} = Tick,
+ ticked = Ticked0} = Tick,
T = T0 + 1,
T1 = T rem 4,
- case MFGetstat(Socket) of
- {ok, Read, _, _} when Ticked =:= T ->
+ case getstat(DHandle, Socket, MFGetstat) of
+ {ok, Read, _, _} when Ticked0 =:= T ->
{error, not_responding};
- {ok, Read, W, Pend} when Type =:= hidden ->
- send_tick(Socket, Pend, MFTick),
- {ok, Tick#tick{write = W + 1,
- tick = T1}};
- {ok, Read, Write, Pend} ->
- send_tick(Socket, Pend, MFTick),
- {ok, Tick#tick{write = Write + 1,
- tick = T1}};
- {ok, R, Write, Pend} ->
- send_tick(Socket, Pend, MFTick),
- {ok, Tick#tick{write = Write + 1,
- read = R,
- tick = T1,
- ticked = T}};
- {ok, Read, W, _} ->
- {ok, Tick#tick{write = W,
- tick = T1}};
- {ok, R, W, _} ->
- {ok, Tick#tick{write = W,
- read = R,
- tick = T1,
- ticked = T}};
+
+ {ok, R, W1, Pend} ->
+ RDiff = R - Read,
+ W2 = case need_to_tick(Type, RDiff, W1-Write, Pend) of
+ true ->
+ MFTick(Socket),
+ W1 + 1;
+ false ->
+ W1
+ end,
+
+ Ticked1 = case RDiff of
+ 0 -> Ticked0;
+ _ -> T
+ end,
+
+ {ok, Tick#tick{write = W2,
+ tick = T1,
+ read = R,
+ ticked = Ticked1}};
+
Error ->
Error
end.
-send_tick(Socket, 0, MFTick) ->
- MFTick(Socket);
-send_tick(_, _Pend, _) ->
- %% Dont send tick if pending write.
- ok.
+need_to_tick(_, _, 0, 0) -> % nothing written and empty send queue
+ true;
+need_to_tick(_, _, 0, false) -> % nothing written and empty send queue
+ true;
+need_to_tick(hidden, 0, _, _) -> % nothing read from hidden
+ true;
+need_to_tick(_, _, _, _) ->
+ false.
+
+send_aux_tick(normal, _, Pend, _) when Pend /= false, Pend /= 0 ->
+ ok; %% Dont send tick if pending write.
+send_aux_tick(_Type, Socket, _Pend, MFTick) ->
+ MFTick(Socket).
%% ------------------------------------------------------------
%% Connection setup timeout timer.
diff --git a/lib/kernel/src/erl_boot_server.erl b/lib/kernel/src/erl_boot_server.erl
index ac81cc9689..4ac945ce01 100644
--- a/lib/kernel/src/erl_boot_server.erl
+++ b/lib/kernel/src/erl_boot_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -58,13 +58,11 @@
-define(single_addr_mask, {255, 255, 255, 255}).
--type ip4_address() :: {0..255,0..255,0..255,0..255}.
-
--spec start(Slaves) -> {'ok', Pid} | {'error', What} when
+-spec start(Slaves) -> {'ok', Pid} | {'error', Reason} when
Slaves :: [Host],
- Host :: atom(),
+ Host :: inet:ip_address() | inet:hostname(),
Pid :: pid(),
- What :: any().
+ Reason :: {'badarg', Slaves}.
start(Slaves) ->
case check_arg(Slaves) of
@@ -74,11 +72,11 @@ start(Slaves) ->
{error, {badarg, Slaves}}
end.
--spec start_link(Slaves) -> {'ok', Pid} | {'error', What} when
+-spec start_link(Slaves) -> {'ok', Pid} | {'error', Reason} when
Slaves :: [Host],
- Host :: atom(),
+ Host :: inet:ip_address() | inet:hostname(),
Pid :: pid(),
- What :: any().
+ Reason :: {'badarg', Slaves}.
start_link(Slaves) ->
case check_arg(Slaves) of
@@ -104,10 +102,10 @@ check_arg([], Result) ->
check_arg(_, _Result) ->
error.
--spec add_slave(Slave) -> 'ok' | {'error', What} when
+-spec add_slave(Slave) -> 'ok' | {'error', Reason} when
Slave :: Host,
- Host :: atom(),
- What :: any().
+ Host :: inet:ip_address() | inet:hostname(),
+ Reason :: {'badarg', Slave}.
add_slave(Slave) ->
case inet:getaddr(Slave, inet) of
@@ -117,10 +115,10 @@ add_slave(Slave) ->
{error, {badarg, Slave}}
end.
--spec delete_slave(Slave) -> 'ok' | {'error', What} when
+-spec delete_slave(Slave) -> 'ok' | {'error', Reason} when
Slave :: Host,
- Host :: atom(),
- What :: any().
+ Host :: inet:ip_address() | inet:hostname(),
+ Reason :: {'badarg', Slave}.
delete_slave(Slave) ->
case inet:getaddr(Slave, inet) of
@@ -130,7 +128,7 @@ delete_slave(Slave) ->
{error, {badarg, Slave}}
end.
--spec add_subnet(Mask :: ip4_address(), Addr :: ip4_address()) ->
+-spec add_subnet(Netmask :: inet:ip_address(), Addr :: inet:ip_address()) ->
'ok' | {'error', any()}.
add_subnet(Mask, Addr) when is_tuple(Mask), is_tuple(Addr) ->
@@ -141,14 +139,15 @@ add_subnet(Mask, Addr) when is_tuple(Mask), is_tuple(Addr) ->
{error, empty_subnet}
end.
--spec delete_subnet(Mask :: ip4_address(), Addr :: ip4_address()) -> 'ok'.
+-spec delete_subnet(Netmask :: inet:ip_address(),
+ Addr :: inet:ip_address()) -> 'ok'.
delete_subnet(Mask, Addr) when is_tuple(Mask), is_tuple(Addr) ->
gen_server:call(boot_server, {delete, {Mask, Addr}}).
-spec which_slaves() -> Slaves when
- Slaves :: [Host],
- Host :: atom().
+ Slaves :: [Slave],
+ Slave :: {Netmask :: inet:ip_address(), Address :: inet:ip_address()}.
which_slaves() ->
gen_server:call(boot_server, which).
@@ -253,9 +252,9 @@ handle_info({udp, U, IP, Port, Data}, S0) ->
"~w is not a valid address ** ~n", [IP]),
{noreply,S0};
{true,_,_} ->
- case catch string:substr(Data, 1, length(?EBOOT_REQUEST)) of
+ case catch string:slice(Data, 0, length(?EBOOT_REQUEST)) of
?EBOOT_REQUEST ->
- Vsn = string:substr(Data, length(?EBOOT_REQUEST)+1, length(Data)),
+ Vsn = string:slice(Data, length(?EBOOT_REQUEST), length(Data)),
error_logger:error_msg("** Illegal boot server connection attempt: "
"client version is ~s ** ~n", [Vsn]);
_ ->
diff --git a/lib/kernel/src/erl_epmd.erl b/lib/kernel/src/erl_epmd.erl
index 7bc9e2ede3..b7e8868911 100644
--- a/lib/kernel/src/erl_epmd.erl
+++ b/lib/kernel/src/erl_epmd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,10 +29,20 @@
-define(port_please_failure2(Term), noop).
-endif.
+-ifndef(erlang_daemon_port).
+-define(erlang_daemon_port, 4369).
+-endif.
+-ifndef(epmd_dist_high).
+-define(epmd_dist_high, 4370).
+-endif.
+-ifndef(epmd_dist_low).
+-define(epmd_dist_low, 4370).
+-endif.
+
%% External exports
-export([start/0, start_link/0, stop/0, port_please/2,
port_please/3, names/0, names/1,
- register_node/2, register_node/3, open/0, open/1, open/2]).
+ register_node/2, register_node/3, address_please/3, open/0, open/1, open/2]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
@@ -53,7 +63,7 @@
start() ->
gen_server:start({local, erl_epmd}, ?MODULE, [], []).
-
+-spec start_link() -> {ok, pid()} | ignore | {error,term()}.
start_link() ->
gen_server:start_link({local, erl_epmd}, ?MODULE, [], []).
@@ -66,9 +76,22 @@ stop() ->
%% return {port, P, Version} | noport
%%
+-spec port_please(Name, Host) -> {ok, Port, Version} | noport when
+ Name :: string(),
+ Host :: inet:ip_address(),
+ Port :: non_neg_integer(),
+ Version :: non_neg_integer().
+
port_please(Node, Host) ->
port_please(Node, Host, infinity).
+-spec port_please(Name, Host, Timeout) -> {ok, Port, Version} | noport when
+ Name :: string(),
+ Host :: inet:ip_address(),
+ Timeout :: non_neg_integer() | infinity,
+ Port :: non_neg_integer(),
+ Version :: non_neg_integer().
+
port_please(Node,HostName, Timeout) when is_atom(HostName) ->
port_please1(Node,atom_to_list(HostName), Timeout);
port_please(Node,HostName, Timeout) when is_list(HostName) ->
@@ -79,17 +102,34 @@ port_please(Node, EpmdAddr, Timeout) ->
port_please1(Node,HostName, Timeout) ->
- case inet:gethostbyname(HostName, inet, Timeout) of
+ Family = case inet_db:res_option(inet6) of
+ true ->
+ inet6;
+ false ->
+ inet
+ end,
+ case inet:gethostbyname(HostName, Family, Timeout) of
{ok,{hostent, _Name, _ , _Af, _Size, [EpmdAddr | _]}} ->
get_port(Node, EpmdAddr, Timeout);
Else ->
Else
end.
+-spec names() -> {ok, [{Name, Port}]} | {error, Reason} when
+ Name :: string(),
+ Port :: non_neg_integer(),
+ Reason :: address | file:posix().
+
names() ->
{ok, H} = inet:gethostname(),
names(H).
+-spec names(Host) -> {ok, [{Name, Port}]} | {error, Reason} when
+ Host :: atom() | string() | inet:ip_address(),
+ Name :: string(),
+ Port :: non_neg_integer(),
+ Reason :: address | file:posix().
+
names(HostName) when is_atom(HostName); is_list(HostName) ->
case inet:gethostbyname(HostName) of
{ok,{hostent, _Name, _ , _Af, _Size, [EpmdAddr | _]}} ->
@@ -100,9 +140,22 @@ names(HostName) when is_atom(HostName); is_list(HostName) ->
names(EpmdAddr) ->
get_names(EpmdAddr).
+-spec register_node(Name, Port) -> Result when
+ Name :: string(),
+ Port :: non_neg_integer(),
+ Creation :: non_neg_integer(),
+ Result :: {ok, Creation} | {error, already_registered} | term().
register_node(Name, PortNo) ->
- register_node(Name, PortNo, inet).
+ register_node(Name, PortNo, inet).
+
+-spec register_node(Name, Port, Driver) -> Result when
+ Name :: string(),
+ Port :: non_neg_integer(),
+ Driver :: inet_tcp | inet6_tcp | inet | inet6,
+ Creation :: non_neg_integer(),
+ Result :: {ok, Creation} | {error, already_registered} | term().
+
register_node(Name, PortNo, inet_tcp) ->
register_node(Name, PortNo, inet);
register_node(Name, PortNo, inet6_tcp) ->
@@ -110,6 +163,17 @@ register_node(Name, PortNo, inet6_tcp) ->
register_node(Name, PortNo, Family) ->
gen_server:call(erl_epmd, {register, Name, PortNo, Family}, infinity).
+-spec address_please(Name, Host, AddressFamily) -> Success | {error, term()} when
+ Name :: string(),
+ Host :: string() | inet:ip_address(),
+ AddressFamily :: inet | inet6,
+ Port :: non_neg_integer(),
+ Version :: non_neg_integer(),
+ Success :: {ok, inet:ip_address()} | {ok, inet:ip_address(), Port, Version}.
+
+address_please(_Name, Host, AddressFamily) ->
+ inet:getaddr(Host, AddressFamily).
+
%%%----------------------------------------------------------------------
%%% Callback functions from gen_server
%%%----------------------------------------------------------------------
diff --git a/lib/kernel/src/erl_reply.erl b/lib/kernel/src/erl_reply.erl
index e1e046cbb4..e1c4ffe839 100644
--- a/lib/kernel/src/erl_reply.erl
+++ b/lib/kernel/src/erl_reply.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@ reply(_) ->
%% convert ip number to tuple
ip_string_to_tuple(Ip) ->
- [Ip1,Ip2,Ip3,Ip4] = string:tokens(Ip,"."),
+ [Ip1,Ip2,Ip3,Ip4] = string:lexemes(Ip,"."),
{list_to_integer(Ip1),
list_to_integer(Ip2),
list_to_integer(Ip3),
diff --git a/lib/kernel/src/erl_signal_handler.erl b/lib/kernel/src/erl_signal_handler.erl
index 22f235d4e4..5be905d8ae 100644
--- a/lib/kernel/src/erl_signal_handler.erl
+++ b/lib/kernel/src/erl_signal_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,12 +19,21 @@
-module(erl_signal_handler).
-behaviour(gen_event).
--export([init/1, format_status/2,
+-export([start/0, init/1, format_status/2,
handle_event/2, handle_call/2, handle_info/2,
terminate/2, code_change/3]).
-record(state,{}).
+start() ->
+ %% add signal handler
+ case whereis(erl_signal_server) of
+ %% in case of minimal mode
+ undefined -> ok;
+ _ ->
+ gen_event:add_handler(erl_signal_server, erl_signal_handler, [])
+ end.
+
init(_Args) ->
{ok, #state{}}.
diff --git a/lib/kernel/src/error_handler.erl b/lib/kernel/src/error_handler.erl
index 59ca8e690d..a89ef83261 100644
--- a/lib/kernel/src/error_handler.erl
+++ b/lib/kernel/src/error_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -106,8 +106,8 @@ crash(M, F, A) ->
crash(Tuple) ->
try erlang:error(undef)
catch
- error:undef ->
- Stk = [Tuple|tl(erlang:get_stacktrace())],
+ error:undef:Stacktrace ->
+ Stk = [Tuple|tl(Stacktrace)],
erlang:raise(error, undef, Stk)
end.
diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl
index 9bf8547745..e324be5290 100644
--- a/lib/kernel/src/error_logger.erl
+++ b/lib/kernel/src/error_logger.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,22 +19,23 @@
%%
-module(error_logger).
--export([start/0,start_link/0,format/2,error_msg/1,error_msg/2,error_report/1,
+-include("logger_internal.hrl").
+
+-export([start/0,start_link/0,stop/0,
+ format/2,error_msg/1,error_msg/2,error_report/1,
error_report/2,info_report/1,info_report/2,warning_report/1,
warning_report/2,error_info/1,
info_msg/1,info_msg/2,warning_msg/1,warning_msg/2,
- logfile/1,tty/1,swap_handler/1,
+ logfile/1,tty/1,
add_report_handler/1,add_report_handler/2,
- delete_report_handler/1]).
+ delete_report_handler/1,
+ which_report_handlers/0]).
--export([init/1,
- handle_event/2, handle_call/2, handle_info/2,
- terminate/2]).
+%% logger callbacks
+-export([adding_handler/1, removing_handler/1, log/2]).
-export([get_format_depth/0, limit_term/1]).
--define(buffer_size, 10).
-
%%-----------------------------------------------------------------
%% Types used in this file
%%-----------------------------------------------------------------
@@ -43,8 +44,6 @@
| 'info' | 'info_msg' | 'info_report'
| 'warning_msg' | 'warning_report'.
--type state() :: {non_neg_integer(), non_neg_integer(), [term()]}.
-
%%% BIF
-export([warning_map/0]).
@@ -59,26 +58,164 @@ warning_map() ->
%%-----------------------------------------------------------------
--spec start() -> {'ok', pid()} | {'error', any()}.
+%%%-----------------------------------------------------------------
+%%% Start the event manager process under logger_sup, which is part of
+%%% the kernel application's supervision tree.
+-spec start() -> 'ok' | {'error', any()}.
start() ->
- case gen_event:start({local, error_logger}) of
- {ok, Pid} ->
- simple_logger(?buffer_size),
- {ok, Pid};
- Error -> Error
+ case whereis(?MODULE) of
+ undefined ->
+ ErrorLogger =
+ #{id => ?MODULE,
+ start => {?MODULE, start_link, []},
+ restart => transient,
+ shutdown => 2000,
+ type => worker,
+ modules => dynamic},
+ case supervisor:start_child(logger_sup, ErrorLogger) of
+ {ok,Pid} ->
+ ok = logger_handler_watcher:register_handler(?MODULE,Pid);
+ Error ->
+ Error
+ end;
+ _ ->
+ ok
end.
+%%%-----------------------------------------------------------------
+%%% Start callback specified in child specification to supervisor, see start/0
-spec start_link() -> {'ok', pid()} | {'error', any()}.
start_link() ->
- case gen_event:start_link({local, error_logger}) of
- {ok, Pid} ->
- simple_logger(?buffer_size),
- {ok, Pid};
- Error -> Error
+ gen_event:start_link({local, ?MODULE},
+ [{spawn_opt,[{message_queue_data, off_heap}]}]).
+
+%%%-----------------------------------------------------------------
+%%% Stop the event manager
+-spec stop() -> ok.
+stop() ->
+ case whereis(?MODULE) of
+ undefined ->
+ ok;
+ _Pid ->
+ _ = gen_event:stop(?MODULE,{shutdown,stopped},infinity),
+ _ = supervisor:delete_child(logger_sup,?MODULE),
+ ok
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Callbacks for logger
+-spec adding_handler(logger:handler_config()) ->
+ {ok,logger:handler_config()} | {error,term()}.
+adding_handler(#{id:=?MODULE}=Config) ->
+ case start() of
+ ok ->
+ {ok,Config};
+ Error ->
+ Error
end.
+-spec removing_handler(logger:handler_config()) -> ok.
+removing_handler(#{id:=?MODULE}) ->
+ stop(),
+ ok.
+
+-spec log(logger:log_event(),logger:handler_config()) -> ok.
+log(#{level:=Level,msg:=Msg,meta:=Meta},_Config) ->
+ do_log(Level,Msg,Meta).
+
+do_log(Level,{report,Msg},#{?MODULE:=#{tag:=Tag,type:=Type}}=Meta) ->
+ %% From error_logger:*_report/1,2, or logger call which added
+ %% error_logger data to obtain backwards compatibility with
+ %% error_logger:*_report/1,2
+ Report =
+ case Msg of
+ #{label:=_,report:=R} -> R;
+ _ -> Msg
+ end,
+ notify(Level,Tag,Type,Report,Meta);
+do_log(Level,{report,Msg},#{?MODULE:=#{tag:=Tag}}=Meta) ->
+ {Format,Args} =
+ case Msg of
+ #{label:=_,format:=F,args:=A} ->
+ %% From error_logger:*_msg/1,2.
+ %% In order to be backwards compatible with handling
+ %% of faulty parameters to error_logger:*_msg/1,2,
+ %% don't use report_cb here.
+ {F,A};
+ _ ->
+ %% From logger call which added error_logger data to
+ %% obtain backwards compatibility with error_logger:*_msg/1,2
+ case maps:get(report_cb,Meta,fun logger:format_report/1) of
+ RCBFun when is_function(RCBFun,1) ->
+ try RCBFun(Msg) of
+ {F,A} when is_list(F), is_list(A) ->
+ {F,A};
+ Other ->
+ {"REPORT_CB ERROR: ~tp; Returned: ~tp",[Msg,Other]}
+ catch C:R ->
+ {"REPORT_CB CRASH: ~tp; Reason: ~tp",[Msg,{C,R}]}
+ end;
+ RCBFun when is_function(RCBFun,2) ->
+ try RCBFun(Msg,#{depth=>get_format_depth(),
+ chars_limit=>unlimited,
+ single_line=>false}) of
+ Chardata when ?IS_STRING(Chardata) ->
+ {"~ts",[Chardata]};
+ Other ->
+ {"REPORT_CB ERROR: ~tp; Returned: ~tp",[Msg,Other]}
+ catch C:R ->
+ {"REPORT_CB CRASH: ~tp; Reason: ~tp",[Msg,{C,R}]}
+ end
+ end
+ end,
+ notify(Level,Tag,Format,Args,Meta);
+do_log(Level,{Format,Args},#{?MODULE:=#{tag:=Tag}}=Meta)
+ when is_list(Format), is_list(Args) ->
+ %% From logger call which added error_logger data to obtain
+ %% backwards compatibility with error_logger:*_msg/1,2
+ notify(Level,Tag,Format,Args,Meta);
+do_log(_Level,_Msg,_Meta) ->
+ %% Ignore the rest - i.e. to get backwards compatibility with
+ %% error_logger, you must use the error_logger API for logging.
+ %% Some modules within OTP go around this by adding an
+ %% error_logger field to its metadata. This is done only to allow
+ %% complete backwards compatibility for log events originating
+ %% from within OTP, while still using the new logger interface.
+ ok.
+
+-spec notify(logger:level(), msg_tag(), any(), any(), map()) -> 'ok'.
+notify(Level,Tag0,FormatOrType0,ArgsOrReport,#{pid:=Pid0,gl:=GL,?MODULE:=My}) ->
+ {Tag,FormatOrType} = maybe_map_warnings(Level,Tag0,FormatOrType0),
+ Pid = case maps:get(emulator,My,false) of
+ true -> emulator;
+ _ -> Pid0
+ end,
+ gen_event:notify(?MODULE,{Tag,GL,{Pid,FormatOrType,ArgsOrReport}}).
+
+%% For backwards compatibility with really old even handlers, check
+%% the warning map and update tag and type.
+maybe_map_warnings(warning,Tag,FormatOrType) ->
+ case error_logger:warning_map() of
+ warning ->
+ {Tag,FormatOrType};
+ Level ->
+ {fix_warning_tag(Level,Tag),fix_warning_type(Level,FormatOrType)}
+ end;
+maybe_map_warnings(_,Tag,FormatOrType) ->
+ {Tag,FormatOrType}.
+
+fix_warning_tag(error,warning_msg) -> error;
+fix_warning_tag(error,warning_report) -> error_report;
+fix_warning_tag(info,warning_msg) -> info_msg;
+fix_warning_tag(info,warning_report) -> info_report;
+fix_warning_tag(_,Tag) -> Tag.
+
+fix_warning_type(error,std_warning) -> std_error;
+fix_warning_type(info,std_warning) -> std_info;
+fix_warning_type(_,Type) -> Type.
+
%%-----------------------------------------------------------------
%% These two simple old functions generate events tagged 'error'
%% Used for simple messages; error or information.
@@ -95,14 +232,18 @@ error_msg(Format) ->
Data :: list().
error_msg(Format, Args) ->
- notify({error, group_leader(), {self(), Format, Args}}).
+ logger:log(error,
+ #{label=>{?MODULE,error_msg},
+ format=>Format,
+ args=>Args},
+ meta(error)).
-spec format(Format, Data) -> 'ok' when
Format :: string(),
Data :: list().
format(Format, Args) ->
- notify({error, group_leader(), {self(), Format, Args}}).
+ error_msg(Format, Args).
%%-----------------------------------------------------------------
%% This functions should be used for error reports. Events
@@ -124,7 +265,10 @@ error_report(Report) ->
Report :: report().
error_report(Type, Report) ->
- notify({error_report, group_leader(), {self(), Type, Report}}).
+ logger:log(error,
+ #{label=>{?MODULE,error_report},
+ report=>Report},
+ meta(error_report,Type)).
%%-----------------------------------------------------------------
%% This function should be used for warning reports.
@@ -146,25 +290,10 @@ warning_report(Report) ->
Report :: report().
warning_report(Type, Report) ->
- {Tag, NType} = case error_logger:warning_map() of
- info ->
- if
- Type =:= std_warning ->
- {info_report, std_info};
- true ->
- {info_report, Type}
- end;
- warning ->
- {warning_report, Type};
- error ->
- if
- Type =:= std_warning ->
- {error_report, std_error};
- true ->
- {error_report, Type}
- end
- end,
- notify({Tag, group_leader(), {self(), NType, Report}}).
+ logger:log(warning,
+ #{label=>{?MODULE,warning_report},
+ report=>Report},
+ meta(warning_report,Type)).
%%-----------------------------------------------------------------
%% This function provides similar functions as error_msg for
@@ -183,15 +312,11 @@ warning_msg(Format) ->
Data :: list().
warning_msg(Format, Args) ->
- Tag = case error_logger:warning_map() of
- warning ->
- warning_msg;
- info ->
- info_msg;
- error ->
- error
- end,
- notify({Tag, group_leader(), {self(), Format, Args}}).
+ logger:log(warning,
+ #{label=>{?MODULE,warning_msg},
+ format=>Format,
+ args=>Args},
+ meta(warning_msg)).
%%-----------------------------------------------------------------
%% This function should be used for information reports. Events
@@ -210,7 +335,10 @@ info_report(Report) ->
Report :: report().
info_report(Type, Report) ->
- notify({info_report, group_leader(), {self(), Type, Report}}).
+ logger:log(notice,
+ #{label=>{?MODULE,info_report},
+ report=>Report},
+ meta(info_report,Type)).
%%-----------------------------------------------------------------
%% This function provides similar functions as error_msg for
@@ -228,7 +356,11 @@ info_msg(Format) ->
Data :: list().
info_msg(Format, Args) ->
- notify({info_msg, group_leader(), {self(), Format, Args}}).
+ logger:log(notice,
+ #{label=>{?MODULE,info_msg},
+ format=>Format,
+ args=>Args},
+ meta(info_msg)).
%%-----------------------------------------------------------------
%% Used by the init process. Events are tagged 'info'.
@@ -236,38 +368,75 @@ info_msg(Format, Args) ->
-spec error_info(Error :: any()) -> 'ok'.
+%% unused?
error_info(Error) ->
- notify({info, group_leader(), {self(), Error, []}}).
-
--spec notify({msg_tag(), pid(), {pid(), any(), any()}}) -> 'ok'.
-
-notify(Msg) ->
- gen_event:notify(error_logger, Msg).
-
--type swap_handler_type() :: 'false' | 'silent' | 'tty' | {'logfile', string()}.
--spec swap_handler(Type :: swap_handler_type()) -> any().
-
-swap_handler(tty) ->
- R = gen_event:swap_handler(error_logger, {error_logger, swap},
- {error_logger_tty_h, []}),
- ok = simple_logger(),
- R;
-swap_handler({logfile, File}) ->
- R = gen_event:swap_handler(error_logger, {error_logger, swap},
- {error_logger_file_h, File}),
- ok = simple_logger(),
- R;
-swap_handler(silent) ->
- _ = gen_event:delete_handler(error_logger, error_logger, delete),
- ok = simple_logger();
-swap_handler(false) ->
- ok. % keep primitive event handler as-is
+ {Format,Args} =
+ case string_p(Error) of
+ true -> {Error,[]};
+ false -> {"~p",[Error]}
+ end,
+ MyMeta = #{tag=>info,type=>Error},
+ logger:log(notice, Format, Args, #{?MODULE=>MyMeta,domain=>[Error]}).
+
+%%-----------------------------------------------------------------
+%% Create metadata
+meta(Tag) ->
+ meta(Tag,undefined).
+meta(Tag,Type) ->
+ meta(Tag,Type,#{report_cb=>fun report_to_format/1}).
+meta(Tag,undefined,Meta0) ->
+ Meta0#{?MODULE=>#{tag=>Tag}};
+meta(Tag,Type,Meta0) ->
+ maybe_add_domain(Tag,Type,Meta0#{?MODULE=>#{tag=>Tag,type=>Type}}).
+
+%% This is to prevent events of non standard type from being printed
+%% with the standard logger. Similar to how error_logger_tty_h
+%% discards events of non standard type.
+maybe_add_domain(error_report,std_error,Meta) -> Meta;
+maybe_add_domain(info_report,std_info,Meta) -> Meta;
+maybe_add_domain(warning_report,std_warning,Meta) -> Meta;
+maybe_add_domain(_,Type,Meta) -> Meta#{domain=>[Type]}.
+
+%% -----------------------------------------------------------------
+%% Report formatting - i.e. Term => {Format,Args}
+%% This was earlier done in the event handler (error_logger_tty_h, etc)
+%% -----------------------------------------------------------------
+report_to_format(#{label:={?MODULE,_},
+ report:=Report}) when is_map(Report) ->
+ %% logger:format_otp_report does maps:to_list, and for backwards
+ %% compatibility reasons we don't want that.
+ {"~tp\n",[Report]};
+report_to_format(#{label:={?MODULE,_},
+ format:=Format,
+ args:=Args}) ->
+ %% This is not efficient, but needed for backwards compatibility
+ %% in giving faulty arguments to the *_msg functions.
+ try io_lib:scan_format(Format,Args) of
+ _ -> {Format,Args}
+ catch _:_ ->
+ {"ERROR: ~tp - ~tp",[Format,Args]}
+ end;
+report_to_format(Term) ->
+ logger:format_otp_report(Term).
+
+string_p(List) when is_list(List) ->
+ string_p1(lists:flatten(List));
+string_p(_) ->
+ false.
+string_p1([]) ->
+ false;
+string_p1(FlatList) ->
+ io_lib:printable_list(FlatList).
+
+%% -----------------------------------------------------------------
+%% Stuff directly related to the event manager
+%% -----------------------------------------------------------------
-spec add_report_handler(Handler) -> any() when
Handler :: module().
add_report_handler(Module) when is_atom(Module) ->
- gen_event:add_handler(error_logger, Module, []).
+ add_report_handler(Module, []).
-spec add_report_handler(Handler, Args) -> Result when
Handler :: module(),
@@ -275,24 +444,37 @@ add_report_handler(Module) when is_atom(Module) ->
Result :: gen_event:add_handler_ret().
add_report_handler(Module, Args) when is_atom(Module) ->
- gen_event:add_handler(error_logger, Module, Args).
+ _ = logger:add_handler(?MODULE,?MODULE,#{level=>info,filter_default=>log}),
+ gen_event:add_handler(?MODULE, Module, Args).
-spec delete_report_handler(Handler) -> Result when
Handler :: module(),
Result :: gen_event:del_handler_ret().
delete_report_handler(Module) when is_atom(Module) ->
- gen_event:delete_handler(error_logger, Module, []).
-
-%% Start the lowest level error_logger handler with Buffer.
-
-simple_logger(Buffer_size) when is_integer(Buffer_size) ->
- gen_event:add_handler(error_logger, error_logger, Buffer_size).
-
-%% Start the lowest level error_logger handler without Buffer.
+ case whereis(?MODULE) of
+ Pid when is_pid(Pid) ->
+ Return = gen_event:delete_handler(?MODULE, Module, []),
+ case gen_event:which_handlers(?MODULE) of
+ [] ->
+ %% Don't want a lot of logs here if it's not needed
+ _ = logger:remove_handler(?MODULE),
+ ok;
+ _ ->
+ ok
+ end,
+ Return;
+ _ ->
+ ok
+ end.
-simple_logger() ->
- gen_event:add_handler(error_logger, error_logger, []).
+which_report_handlers() ->
+ case whereis(?MODULE) of
+ Pid when is_pid(Pid) ->
+ gen_event:which_handlers(?MODULE);
+ undefined ->
+ []
+ end.
%% Log all errors to File for all eternity
@@ -308,26 +490,35 @@ simple_logger() ->
FilenameReason :: no_log_file.
logfile({open, File}) ->
- case lists:member(error_logger_file_h,
- gen_event:which_handlers(error_logger)) of
+ case lists:member(error_logger_file_h,which_report_handlers()) of
true ->
{error, allready_have_logfile};
_ ->
- gen_event:add_handler(error_logger, error_logger_file_h, File)
+ add_report_handler(error_logger_file_h, File)
end;
logfile(close) ->
- case gen_event:delete_handler(error_logger, error_logger_file_h, normal) of
- {error,Reason} ->
- {error,Reason};
- _ ->
- ok
+ case whereis(?MODULE) of
+ Pid when is_pid(Pid) ->
+ case gen_event:delete_handler(?MODULE, error_logger_file_h, normal) of
+ {error,Reason} ->
+ {error,Reason};
+ _ ->
+ ok
+ end;
+ _ ->
+ {error,module_not_found}
end;
logfile(filename) ->
- case gen_event:call(error_logger, error_logger_file_h, filename) of
- {error,_} ->
- {error, no_log_file};
- Val ->
- Val
+ case whereis(?MODULE) of
+ Pid when is_pid(Pid) ->
+ case gen_event:call(?MODULE, error_logger_file_h, filename) of
+ {error,_} ->
+ {error, no_log_file};
+ Val ->
+ Val
+ end;
+ _ ->
+ {error, no_log_file}
end.
%% Possibly turn off all tty printouts, maybe we only want the errors
@@ -337,190 +528,38 @@ logfile(filename) ->
Flag :: boolean().
tty(true) ->
- Hs = gen_event:which_handlers(error_logger),
- case lists:member(error_logger_tty_h, Hs) of
- false ->
- gen_event:add_handler(error_logger, error_logger_tty_h, []);
- true ->
- ignore
- end,
+ _ = case lists:member(error_logger_tty_h, which_report_handlers()) of
+ false ->
+ case logger:get_handler_config(default) of
+ {ok,#{module:=logger_std_h,config:=#{type:=standard_io}}} ->
+ logger:remove_handler_filter(default,
+ error_logger_tty_false);
+ _ ->
+ logger:add_handler(error_logger_tty_true,logger_std_h,
+ #{filter_default=>stop,
+ filters=>?DEFAULT_HANDLER_FILTERS(
+ [otp]),
+ formatter=>{?DEFAULT_FORMATTER,
+ ?DEFAULT_FORMAT_CONFIG},
+ config=>#{type=>standard_io}})
+ end;
+ true ->
+ ok
+ end,
ok;
tty(false) ->
- gen_event:delete_handler(error_logger, error_logger_tty_h, []),
+ delete_report_handler(error_logger_tty_h),
+ _ = logger:remove_handler(error_logger_tty_true),
+ _ = case logger:get_handler_config(default) of
+ {ok,#{module:=logger_std_h,config:=#{type:=standard_io}}} ->
+ logger:add_handler_filter(default,error_logger_tty_false,
+ {fun(_,_) -> stop end, ok});
+ _ ->
+ ok
+ end,
ok.
-
-%%% ---------------------------------------------------
-%%% This is the default error_logger handler.
-%%% ---------------------------------------------------
-
--spec init(term()) -> {'ok', state() | []}.
-
-init(Max) when is_integer(Max) ->
- {ok, {Max, 0, []}};
-%% This one is called if someone took over from us, and now wants to
-%% go back.
-init({go_back, _PostState}) ->
- {ok, {?buffer_size, 0, []}};
-init(_) ->
- %% The error logger process may receive a huge amount of
- %% messages. Make sure that they are stored off heap to
- %% avoid exessive GCs.
- process_flag(message_queue_data, off_heap),
- {ok, []}.
-
--spec handle_event(term(), state()) -> {'ok', state()}.
-
-handle_event({Type, GL, Msg}, State) when node(GL) =/= node() ->
- gen_event:notify({error_logger, node(GL)},{Type, GL, Msg}),
- %% handle_event2({Type, GL, Msg}, State); %% Shall we do something
- {ok, State}; %% at this node too ???
-handle_event({info_report, _, {_, Type, _}}, State) when Type =/= std_info ->
- {ok, State}; %% Ignore other info reports here
-handle_event(Event, State) ->
- handle_event2(Event, State).
-
--spec handle_info(term(), state()) -> {'ok', state()}.
-
-handle_info({emulator, GL, Chars}, State) when node(GL) =/= node() ->
- {error_logger, node(GL)} ! {emulator, GL, add_node(Chars,self())},
- {ok, State};
-handle_info({emulator, GL, Chars}, State) ->
- handle_event2({emulator, GL, Chars}, State);
-handle_info(_, State) ->
- {ok, State}.
-
--spec handle_call(term(), state()) -> {'ok', {'error', 'bad_query'}, state()}.
-
-handle_call(_Query, State) -> {ok, {error, bad_query}, State}.
-
--spec terminate(term(), state()) -> {'error_logger', [term()]}.
-
-terminate(swap, {_, 0, Buff}) ->
- {error_logger, Buff};
-terminate(swap, {_, Lost, Buff}) ->
- Myevent = {info, group_leader(), {self(), {lost_messages, Lost}, []}},
- {error_logger, [tag_event(Myevent)|Buff]};
-terminate(_, _) ->
- {error_logger, []}.
-
-handle_event2(Event, {1, Lost, Buff}) ->
- display(tag_event(Event)),
- {ok, {1, Lost+1, Buff}};
-handle_event2(Event, {N, Lost, Buff}) ->
- Tagged = tag_event(Event),
- display(Tagged),
- {ok, {N-1, Lost, [Tagged|Buff]}};
-handle_event2(_, State) ->
- {ok, State}.
-
-tag_event(Event) ->
- {erlang:localtime(), Event}.
-
-display({Tag,{error,_,{_,Format,Args}}}) ->
- display2(Tag,Format,Args);
-display({Tag,{error_report,_,{_,Type,Report}}}) ->
- display2(Tag,Type,Report);
-display({Tag,{info_report,_,{_,Type,Report}}}) ->
- display2(Tag,Type,Report);
-display({Tag,{info,_,{_,Error,_}}}) ->
- display2(Tag,Error,[]);
-display({Tag,{info_msg,_,{_,Format,Args}}}) ->
- display2(Tag,Format,Args);
-display({Tag,{warning_report,_,{_,Type,Report}}}) ->
- display2(Tag,Type,Report);
-display({Tag,{warning_msg,_,{_,Format,Args}}}) ->
- display2(Tag,Format,Args);
-display({Tag,{emulator,_,Chars}}) ->
- display2(Tag,Chars,[]).
-
-add_node(X, Pid) when is_atom(X) ->
- add_node(atom_to_list(X), Pid);
-add_node(X, Pid) ->
- lists:concat([X,"** at node ",node(Pid)," **~n"]).
-
-%% Can't do io_lib:format
-
-display2({{_Y,_Mo,_D},{_H,_Mi,_S}} = Date, F, A) ->
- display_date(Date),
- display3(string_p(F), F, A).
-
-display_date({{Y,Mo,D},{H,Mi,S}}) ->
- erlang:display_string(
- integer_to_list(Y) ++ "-" ++
- two_digits(Mo) ++ "-" ++
- two_digits(D) ++ " " ++
- two_digits(H) ++ ":" ++
- two_digits(Mi) ++ ":" ++
- two_digits(S) ++ " ").
-
-two_digits(N) when 0 =< N, N =< 9 ->
- [$0, $0 + N];
-two_digits(N) ->
- integer_to_list(N).
-
-display3(true, F, A) ->
- %% Format string with arguments
- erlang:display_string(F ++ "\n"),
- [begin
- erlang:display_string("\t"),
- erlang:display(Arg)
- end || Arg <- A],
- ok;
-display3(false, Atom, A) when is_atom(Atom) ->
- %% The widest atom seems to be 'supervisor_report' at 17.
- ColumnWidth = 20,
- AtomString = atom_to_list(Atom),
- AtomLength = length(AtomString),
- Padding = lists:duplicate(ColumnWidth - AtomLength, $\s),
- erlang:display_string(AtomString ++ Padding),
- display4(A);
-display3(_, F, A) ->
- erlang:display({F, A}).
-
-display4([A, []]) ->
- %% Not sure why crash reports look like this.
- display4(A);
-display4(A = [_|_]) ->
- case lists:all(fun({Key,_Value}) -> is_atom(Key); (_) -> false end, A) of
- true ->
- erlang:display_string("\n"),
- lists:foreach(
- fun({Key, Value}) ->
- erlang:display_string(
- " " ++
- atom_to_list(Key) ++
- ": "),
- erlang:display(Value)
- end, A);
- false ->
- erlang:display(A)
- end;
-display4(A) ->
- erlang:display(A).
-
-string_p([]) ->
- false;
-string_p(Term) ->
- string_p1(Term).
-
-string_p1([H|T]) when is_integer(H), H >= $\s, H < 255 ->
- string_p1(T);
-string_p1([$\n|T]) -> string_p1(T);
-string_p1([$\r|T]) -> string_p1(T);
-string_p1([$\t|T]) -> string_p1(T);
-string_p1([$\v|T]) -> string_p1(T);
-string_p1([$\b|T]) -> string_p1(T);
-string_p1([$\f|T]) -> string_p1(T);
-string_p1([$\e|T]) -> string_p1(T);
-string_p1([H|T]) when is_list(H) ->
- case string_p1(H) of
- true -> string_p1(T);
- _ -> false
- end;
-string_p1([]) -> true;
-string_p1(_) -> false.
-
+%%%-----------------------------------------------------------------
-spec limit_term(term()) -> term().
limit_term(Term) ->
@@ -535,6 +574,8 @@ get_format_depth() ->
case application:get_env(kernel, error_logger_format_depth) of
{ok, Depth} when is_integer(Depth) ->
max(10, Depth);
+ {ok, unlimited} ->
+ unlimited;
undefined ->
unlimited
end.
diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl
index ad92aafc2f..1270de4144 100644
--- a/lib/kernel/src/erts_debug.erl
+++ b/lib/kernel/src/erts_debug.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
%% Low-level debugging support. EXPERIMENTAL!
--export([size/1,df/1,df/2,df/3,ic/1]).
+-export([size/1,df/1,df/2,df/3,dis_to_file/2,ic/1]).
%% This module contains the following *experimental* BIFs:
%% disassemble/1
@@ -32,11 +32,11 @@
%%% BIFs
-export([breakpoint/2, disassemble/1, display/1, dist_ext_to_term/2,
- dump_monitors/1, dump_links/1, flat_size/1,
- get_internal_state/1, instructions/0, lock_counters/1,
+ flat_size/1, get_internal_state/1, instructions/0,
map_info/1, same/2, set_internal_state/2,
- size_shared/1, copy_shared/1, dirty_cpu/2, dirty_io/2,
- dirty/3]).
+ size_shared/1, copy_shared/1, dirty_cpu/2, dirty_io/2, dirty/3,
+ lcnt_control/1, lcnt_control/2, lcnt_collect/0, lcnt_clear/0,
+ lc_graph/0, lc_graph_to_dot/2, lc_graph_merge/2]).
-spec breakpoint(MFA, Flag) -> non_neg_integer() when
MFA :: {Module :: module(),
@@ -70,18 +70,6 @@ display(_) ->
dist_ext_to_term(_, _) ->
erlang:nif_error(undef).
--spec dump_monitors(Id) -> true when
- Id :: pid() | atom().
-
-dump_monitors(_) ->
- erlang:nif_error(undef).
-
--spec dump_links(Id) -> true when
- Id :: pid() | port() | atom().
-
-dump_links(_) ->
- erlang:nif_error(undef).
-
-spec flat_size(Term) -> non_neg_integer() when
Term :: term().
@@ -142,12 +130,31 @@ ic(F) when is_function(F) ->
io:format("Total: ~w~n",[lists:sum([C||{_I,C}<-Is])]),
R.
--spec lock_counters(info) -> term();
- (clear) -> ok;
- ({copy_save, boolean()}) -> boolean();
- ({process_locks, boolean()}) -> boolean().
+-spec lcnt_control
+ (copy_save, boolean()) -> ok;
+ (mask, list(atom())) -> ok.
-lock_counters(_) ->
+lcnt_control(_Option, _Value) ->
+ erlang:nif_error(undef).
+
+-spec lcnt_control
+ (copy_save) -> boolean();
+ (mask) -> list(atom()).
+
+lcnt_control(_Option) ->
+ erlang:nif_error(undef).
+
+-type lcnt_lock_info() :: {atom(), term(), atom(), term()}.
+
+-spec lcnt_collect() ->
+ list({duration, {non_neg_integer(), non_neg_integer()}} |
+ {locks, list(lcnt_lock_info())}).
+
+lcnt_collect() ->
+ erlang:nif_error(undef).
+
+-spec lcnt_clear() -> ok.
+lcnt_clear() ->
erlang:nif_error(undef).
-spec same(Term1, Term2) -> boolean() when
@@ -359,16 +366,21 @@ df(Mod, Func, Arity) when is_atom(Mod), is_atom(Func) ->
catch _:_ -> {undef,Mod}
end.
-dff(File, Fs) when is_pid(File), is_list(Fs) ->
- lists:foreach(fun(Mfa) ->
- disassemble_function(File, Mfa),
- io:nl(File)
- end, Fs);
-dff(Name, Fs) when is_list(Name) ->
- case file:open(Name, [write]) of
+-spec dis_to_file(module(), file:filename()) -> df_ret().
+
+dis_to_file(Mod, Name) when is_atom(Mod) ->
+ try Mod:module_info(functions) of
+ Fs0 when is_list(Fs0) ->
+ Fs = [{Mod,Func,Arity} || {Func,Arity} <- Fs0],
+ dff(Name, Fs)
+ catch _:_ -> {undef,Mod}
+ end.
+
+dff(Name, Fs) ->
+ case file:open(Name, [write,raw,delayed_write]) of
{ok,F} ->
try
- dff(F, Fs)
+ dff_1(F, Fs)
after
_ = file:close(F)
end;
@@ -376,12 +388,18 @@ dff(Name, Fs) when is_list(Name) ->
{error,{badopen,Reason}}
end.
+dff_1(File, Fs) ->
+ lists:foreach(fun(Mfa) ->
+ disassemble_function(File, Mfa),
+ file:write(File, "\n")
+ end, Fs).
+
disassemble_function(File, {_,_,_}=MFA) ->
cont_dis(File, erts_debug:disassemble(MFA), MFA).
cont_dis(_, false, _) -> ok;
cont_dis(File, {Addr,Str,MFA}, MFA) ->
- io:put_chars(File, binary_to_list(Str)),
+ ok = file:write(File, Str),
cont_dis(File, erts_debug:disassemble(Addr), MFA);
cont_dis(_, {_,_,_}, _) -> ok.
@@ -390,3 +408,90 @@ cont_dis(_, {_,_,_}, _) -> ok.
map_info(_) ->
erlang:nif_error(undef).
+
+%% Create file "lc_graph.<pid>" with all actual lock dependencies
+%% recorded so far by the VM.
+%% Needs debug VM or --enable-lock-checking config, returns 'notsup' otherwise.
+lc_graph() ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ erts_debug:get_internal_state(lc_graph).
+
+%% Convert "lc_graph.<pid>" file to https://www.graphviz.org dot format.
+lc_graph_to_dot(OutFile, InFile) ->
+ {ok, [LL0]} = file:consult(InFile),
+
+ [{"NO LOCK",0} | LL] = LL0,
+ Map = maps:from_list([{Id, Name} || {Name, Id, _, _} <- LL]),
+
+ case file:open(OutFile, [exclusive]) of
+ {ok, Out} ->
+ ok = file:write(Out, "digraph G {\n"),
+
+ [dot_print_lock(Out, Lck, Map) || Lck <- LL],
+
+ ok = file:write(Out, "}\n"),
+ ok = file:close(Out);
+
+ {error,eexist} ->
+ {"File already exists", OutFile}
+ end.
+
+dot_print_lock(Out, {_Name, Id, Lst, _}, Map) ->
+ [dot_print_edge(Out, From, Id, Map) || From <- Lst],
+ ok.
+
+dot_print_edge(_, 0, _, _) ->
+ ignore; % "NO LOCK"
+dot_print_edge(Out, From, To, Map) ->
+ io:format(Out, "~p -> ~p;\n", [maps:get(From,Map), maps:get(To,Map)]).
+
+
+%% Merge several "lc_graph" files into one file.
+lc_graph_merge(OutFile, InFiles) ->
+ LLs = lists:map(fun(InFile) ->
+ {ok, [LL]} = file:consult(InFile),
+ LL
+ end,
+ InFiles),
+
+ Res = lists:foldl(fun(A, B) -> lcg_merge(A, B) end,
+ hd(LLs),
+ tl(LLs)),
+ case file:open(OutFile, [exclusive]) of
+ {ok, Out} ->
+ try
+ lcg_print(Out, Res)
+ after
+ file:close(Out)
+ end,
+ ok;
+ {error, eexist} ->
+ {"File already exists", OutFile}
+ end.
+
+lcg_merge(A, B) ->
+ lists:zipwith(fun(LA, LB) -> lcg_merge_locks(LA, LB) end,
+ A, B).
+
+lcg_merge_locks(L, L) ->
+ L;
+lcg_merge_locks({Name, Id, DA, IA}, {Name, Id, DB, IB}) ->
+ Direct = lists:umerge(DA, DB),
+ Indirect = lists:umerge(IA, IB),
+ {Name, Id, Direct, Indirect -- Direct}.
+
+
+lcg_print(Out, LL) ->
+ io:format(Out, "[", []),
+ lcg_print_locks(Out, LL),
+ io:format(Out, "].\n", []),
+ ok.
+
+lcg_print_locks(Out, [{_,_}=NoLock | Rest]) ->
+ io:format(Out, "~p,\n", [NoLock]),
+ lcg_print_locks(Out, Rest);
+lcg_print_locks(Out, [LastLock]) ->
+ io:format(Out, "~w", [LastLock]);
+lcg_print_locks(Out, [Lock | Rest]) ->
+ io:format(Out, "~w,\n", [Lock]),
+ lcg_print_locks(Out, Rest).
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index 933f2d5f65..1d4e37196c 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -69,10 +69,10 @@
%% Types that can be used from other modules -- alphabetically ordered.
-export_type([date_time/0, fd/0, file_info/0, filename/0, filename_all/0,
- io_device/0, name/0, name_all/0, posix/0]).
+ io_device/0, mode/0, name/0, name_all/0, posix/0]).
%%% Includes and defines
--include("file.hrl").
+-include("file_int.hrl").
-define(FILE_IO_SERVER_TABLE, file_io_servers).
@@ -101,14 +101,25 @@
-type deep_list() :: [char() | atom() | deep_list()].
-type name() :: string() | atom() | deep_list().
-type name_all() :: string() | atom() | deep_list() | (RawFilename :: binary()).
--type posix() :: 'eacces' | 'eagain' | 'ebadf' | 'ebusy' | 'edquot'
- | 'eexist' | 'efault' | 'efbig' | 'eintr' | 'einval'
- | 'eio' | 'eisdir' | 'eloop' | 'emfile' | 'emlink'
- | 'enametoolong'
- | 'enfile' | 'enodev' | 'enoent' | 'enomem' | 'enospc'
- | 'enotblk' | 'enotdir' | 'enotsup' | 'enxio' | 'eperm'
- | 'epipe' | 'erofs' | 'espipe' | 'esrch' | 'estale'
- | 'exdev'.
+-type posix() ::
+ 'eacces' | 'eagain' |
+ 'ebadf' | 'ebadmsg' | 'ebusy' |
+ 'edeadlk' | 'edeadlock' | 'edquot' |
+ 'eexist' |
+ 'efault' | 'efbig' | 'eftype' |
+ 'eintr' | 'einval' | 'eio' | 'eisdir' |
+ 'eloop' |
+ 'emfile' | 'emlink' | 'emultihop' |
+ 'enametoolong' | 'enfile' |
+ 'enobufs' | 'enodev' | 'enolck' | 'enolink' | 'enoent' |
+ 'enomem' | 'enospc' | 'enosr' | 'enostr' | 'enosys' |
+ 'enotblk' | 'enotdir' | 'enotsup' | 'enxio' |
+ 'eopnotsupp' | 'eoverflow' |
+ 'eperm' | 'epipe' |
+ 'erange' | 'erofs' |
+ 'espipe' | 'esrch' | 'estale' |
+ 'etxtbsy' |
+ 'exdev'.
-type date_time() :: calendar:datetime().
-type posix_file_advise() :: 'normal' | 'sequential' | 'random'
| 'no_reuse' | 'will_need' | 'dont_need'.
@@ -454,41 +465,23 @@ raw_write_file_info(Name, #file_info{} = Info) ->
Reason :: posix() | badarg | system_limit.
open(Item, ModeList) when is_list(ModeList) ->
- case lists:member(raw, ModeList) of
- %% Raw file, use ?PRIM_FILE to handle this file
- true ->
+ case {lists:member(raw, ModeList), lists:member(ram, ModeList)} of
+ {false, false} ->
+ %% File server file
Args = [file_name(Item) | ModeList],
case check_args(Args) of
ok ->
[FileName | _] = Args,
- %% We rely on the returned Handle (in {ok, Handle})
- %% being a pid() or a #file_descriptor{}
- ?PRIM_FILE:open(FileName, ModeList);
+ call(open, [FileName, ModeList]);
Error ->
Error
- end;
- false ->
- case lists:member(ram, ModeList) of
- %% RAM file, use ?RAM_FILE to handle this file
- true ->
- case check_args(ModeList) of
- ok ->
- ?RAM_FILE:open(Item, ModeList);
- Error ->
- Error
- end;
- %% File server file
- false ->
- Args = [file_name(Item) | ModeList],
- case check_args(Args) of
- ok ->
- [FileName | _] = Args,
- call(open, [FileName, ModeList]);
- Error ->
- Error
- end
- end
+ end;
+ {true, _Either} ->
+ raw_file_io:open(file_name(Item), ModeList);
+ {false, true} ->
+ ram_file:open(Item, ModeList)
end;
+
%% Old obsolete mode specification in atom or 2-tuple format
open(Item, Mode) ->
open(Item, mode_list(Mode)).
@@ -1254,15 +1247,18 @@ sendfile(File, _Sock, _Offet, _Bytes, _Opts) when is_pid(File) ->
sendfile(File, Sock, Offset, Bytes, []) ->
sendfile(File, Sock, Offset, Bytes, ?MAX_CHUNK_SIZE, [], [], []);
sendfile(File, Sock, Offset, Bytes, Opts) ->
- ChunkSize0 = proplists:get_value(chunk_size, Opts, ?MAX_CHUNK_SIZE),
- ChunkSize = if ChunkSize0 > ?MAX_CHUNK_SIZE ->
- ?MAX_CHUNK_SIZE;
- true -> ChunkSize0
- end,
- %% Support for headers, trailers and options has been removed because the
- %% Darwin and BSD API for using it does not play nice with
- %% non-blocking sockets. See unix_efile.c for more info.
- sendfile(File, Sock, Offset, Bytes, ChunkSize, [], [], Opts).
+ try proplists:get_value(chunk_size, Opts, ?MAX_CHUNK_SIZE) of
+ ChunkSize0 when is_integer(ChunkSize0) ->
+ ChunkSize = erlang:min(ChunkSize0, ?MAX_CHUNK_SIZE),
+ %% Support for headers, trailers and options has been removed
+ %% because the Darwin and BSD API for using it does not play nice
+ %% with non-blocking sockets. See unix_efile.c for more info.
+ sendfile(File, Sock, Offset, Bytes, ChunkSize, [], [], Opts);
+ _Other ->
+ {error, badarg}
+ catch
+ error:_ -> {error, badarg}
+ end.
%% sendfile/2
-spec sendfile(Filename, Socket) ->
@@ -1397,8 +1393,8 @@ eval_stream2({ok,Form,EndLine}, Fd, H, Last, E, Bs0) ->
try erl_eval:exprs(Form, Bs0) of
{value,V,Bs} ->
eval_stream(Fd, H, EndLine, {V}, E, Bs)
- catch Class:Reason ->
- Error = {EndLine,?MODULE,{Class,Reason,erlang:get_stacktrace()}},
+ catch Class:Reason:StackTrace ->
+ Error = {EndLine,?MODULE,{Class,Reason,StackTrace}},
eval_stream(Fd, H, EndLine, Last, [Error|E], Bs0)
end;
eval_stream2({error,What,EndLine}, Fd, H, Last, E, Bs) ->
diff --git a/lib/kernel/src/file_int.hrl b/lib/kernel/src/file_int.hrl
new file mode 100644
index 0000000000..bafc330c04
--- /dev/null
+++ b/lib/kernel/src/file_int.hrl
@@ -0,0 +1,33 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Internal definitions for the 'file' module and friends.
+%%
+
+-ifndef(FILE_INTERNAL_HRL_).
+-define(FILE_INTERNAL_HRL_, 1).
+
+-include("file.hrl").
+
+-define(CALL_FD(Fd, Method, Args),
+ apply(Fd#file_descriptor.module, Method, [Fd | Args])).
+
+-endif.
diff --git a/lib/kernel/src/file_io_server.erl b/lib/kernel/src/file_io_server.erl
index deb7b315b1..34d5497a4a 100644
--- a/lib/kernel/src/file_io_server.erl
+++ b/lib/kernel/src/file_io_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,7 +28,8 @@
-record(state, {handle,owner,mref,buf,read_mode,unic}).
--define(PRIM_FILE, prim_file).
+-include("file_int.hrl").
+
-define(READ_SIZE_LIST, 128).
-define(READ_SIZE_BINARY, (8*1024)).
@@ -67,8 +68,9 @@ do_start(Spawn, Owner, FileName, ModeList) ->
erlang:dt_restore_tag(Utag),
%% process_flag(trap_exit, true),
case parse_options(ModeList) of
- {ReadMode, UnicodeMode, Opts} ->
- case ?PRIM_FILE:open(FileName, Opts) of
+ {ReadMode, UnicodeMode, Opts0} ->
+ Opts = maybe_add_read_ahead(ReadMode, Opts0),
+ case raw_file_io:open(FileName, [raw | Opts]) of
{error, Reason} = Error ->
Self ! {Ref, Error},
exit(Reason);
@@ -157,6 +159,24 @@ valid_enc({utf32,little}) ->
valid_enc(_Other) ->
{error,badarg}.
+%% Add a small read_ahead buffer if the file is opened for reading
+%% only in list mode and no read_ahead is already given.
+maybe_add_read_ahead(binary, Opts) ->
+ Opts;
+maybe_add_read_ahead(list, Opts) ->
+ P = fun(read_ahead) -> true;
+ ({read_ahead,_}) -> true;
+ (append) -> true;
+ (exclusive) -> true;
+ (write) -> true;
+ (_) -> false
+ end,
+ case lists:any(P, Opts) of
+ false ->
+ [{read_ahead, 4096}|Opts];
+ true ->
+ Opts
+ end.
server_loop(#state{mref = Mref} = State) ->
receive
@@ -205,7 +225,7 @@ io_reply(From, ReplyAs, Reply) ->
file_request({advise,Offset,Length,Advise},
#state{handle=Handle}=State) ->
- case ?PRIM_FILE:advise(Handle, Offset, Length, Advise) of
+ case ?CALL_FD(Handle, advise, [Offset, Length, Advise]) of
{error,Reason}=Reply ->
{stop,Reason,Reply,State};
Reply ->
@@ -213,7 +233,7 @@ file_request({advise,Offset,Length,Advise},
end;
file_request({allocate, Offset, Length},
#state{handle = Handle} = State) ->
- Reply = ?PRIM_FILE:allocate(Handle, Offset, Length),
+ Reply = ?CALL_FD(Handle, allocate, [Offset, Length]),
{reply, Reply, State};
file_request({pread,At,Sz}, State)
when At =:= cur;
@@ -256,7 +276,7 @@ file_request({pwrite,At,Data},
end;
file_request(datasync,
#state{handle=Handle}=State) ->
- case ?PRIM_FILE:datasync(Handle) of
+ case ?CALL_FD(Handle, datasync, []) of
{error,Reason}=Reply ->
{stop,Reason,Reply,State};
Reply ->
@@ -264,7 +284,7 @@ file_request(datasync,
end;
file_request(sync,
#state{handle=Handle}=State) ->
- case ?PRIM_FILE:sync(Handle) of
+ case ?CALL_FD(Handle, sync, []) of
{error,Reason}=Reply ->
{stop,Reason,Reply,State};
Reply ->
@@ -272,7 +292,7 @@ file_request(sync,
end;
file_request(close,
#state{handle=Handle}=State) ->
- case ?PRIM_FILE:close(Handle) of
+ case ?CALL_FD(Handle, close, []) of
{error,Reason}=Reply ->
{stop,Reason,Reply,State#state{buf= <<>>}};
Reply ->
@@ -288,7 +308,7 @@ file_request({position,At},
end;
file_request(truncate,
#state{handle=Handle}=State) ->
- case ?PRIM_FILE:truncate(Handle) of
+ case ?CALL_FD(Handle, truncate, []) of
{error,Reason}=Reply ->
{stop,Reason,Reply,State#state{buf= <<>>}};
Reply ->
@@ -398,7 +418,7 @@ io_request_loop([Request|Tail],
%%
put_chars(Chars, latin1, #state{handle=Handle, unic=latin1}=State) ->
NewState = State#state{buf = <<>>},
- case ?PRIM_FILE:write(Handle, Chars) of
+ case ?CALL_FD(Handle, write, [Chars]) of
{error,Reason}=Reply ->
{stop,Reason,Reply,NewState};
Reply ->
@@ -408,7 +428,7 @@ put_chars(Chars, InEncoding, #state{handle=Handle, unic=OutEncoding}=State) ->
NewState = State#state{buf = <<>>},
case unicode:characters_to_binary(Chars,InEncoding,OutEncoding) of
Bin when is_binary(Bin) ->
- case ?PRIM_FILE:write(Handle, Bin) of
+ case ?CALL_FD(Handle, write, [Bin]) of
{error,Reason}=Reply ->
{stop,Reason,Reply,NewState};
Reply ->
@@ -422,7 +442,7 @@ put_chars(Chars, InEncoding, #state{handle=Handle, unic=OutEncoding}=State) ->
get_line(S, {<<>>, Cont}, OutEnc,
#state{handle=Handle, read_mode=Mode, unic=InEnc}=State) ->
- case ?PRIM_FILE:read(Handle, read_size(Mode)) of
+ case ?CALL_FD(Handle, read, [read_size(Mode)]) of
{ok,Bin} ->
get_line(S, convert_enc([Cont, Bin], InEnc, OutEnc), OutEnc, State);
eof ->
@@ -472,7 +492,7 @@ get_chars(N, OutEnc,#state{handle=Handle,buf=Buf,read_mode=ReadMode,unic=latin1}
BufSize = byte_size(Buf),
NeedSize = N-BufSize,
Size = erlang:max(NeedSize, ?READ_SIZE_BINARY),
- case ?PRIM_FILE:read(Handle, Size) of
+ case ?CALL_FD(Handle, read, [Size]) of
{ok, B} ->
if BufSize+byte_size(B) < N ->
std_reply(cat(Buf, B, ReadMode,latin1,OutEnc), State);
@@ -504,7 +524,7 @@ get_chars(N, OutEnc,#state{handle=Handle,buf=Buf,read_mode=ReadMode,unic=InEncod
%% Need more, Try to read 4*needed in bytes...
NeedSize = (N - BufCount) * 4,
Size = erlang:max(NeedSize, ?READ_SIZE_BINARY),
- case ?PRIM_FILE:read(Handle, Size) of
+ case ?CALL_FD(Handle, read, [Size]) of
{ok, B} ->
NewBuf = list_to_binary([Buf,B]),
{NewCount,NewSplit} = count_and_find(NewBuf,N,InEncoding),
@@ -544,7 +564,7 @@ get_chars(Mod, Func, XtraArg, OutEnc, #state{buf=Buf}=State) ->
get_chars_empty(Mod, Func, XtraArg, S, latin1,
#state{handle=Handle,read_mode=ReadMode, unic=latin1}=State) ->
- case ?PRIM_FILE:read(Handle, read_size(ReadMode)) of
+ case ?CALL_FD(Handle, read, [read_size(ReadMode)]) of
{ok,Bin} ->
get_chars_apply(Mod, Func, XtraArg, S, latin1, State, Bin);
eof ->
@@ -554,7 +574,7 @@ get_chars_empty(Mod, Func, XtraArg, S, latin1,
end;
get_chars_empty(Mod, Func, XtraArg, S, OutEnc,
#state{handle=Handle,read_mode=ReadMode}=State) ->
- case ?PRIM_FILE:read(Handle, read_size(ReadMode)) of
+ case ?CALL_FD(Handle, read, [read_size(ReadMode)]) of
{ok,Bin} ->
get_chars_apply(Mod, Func, XtraArg, S, OutEnc, State, Bin);
eof ->
@@ -564,7 +584,7 @@ get_chars_empty(Mod, Func, XtraArg, S, OutEnc,
end.
get_chars_notempty(Mod, Func, XtraArg, S, OutEnc,
#state{handle=Handle,read_mode=ReadMode,buf = B}=State) ->
- case ?PRIM_FILE:read(Handle, read_size(ReadMode)) of
+ case ?CALL_FD(Handle, read, [read_size(ReadMode)]) of
{ok,Bin} ->
get_chars_apply(Mod, Func, XtraArg, S, OutEnc, State, list_to_binary([B,Bin]));
eof ->
@@ -918,13 +938,10 @@ cbv({utf32,little},_) ->
%% Compensates ?PRIM_FILE:position/2 for the number of bytes
%% we have buffered
position(Handle, At, Buf) ->
- ?PRIM_FILE:position(
- Handle,
- case At of
- cur ->
- {cur, -byte_size(Buf)};
- {cur, Offs} ->
- {cur, Offs-byte_size(Buf)};
- _ ->
- At
- end).
+ SeekTo =
+ case At of
+ {cur, Offs} -> {cur, Offs-byte_size(Buf)};
+ cur -> {cur, -byte_size(Buf)};
+ _ -> At
+ end,
+ ?CALL_FD(Handle, position, [SeekTo]).
diff --git a/lib/kernel/src/file_server.erl b/lib/kernel/src/file_server.erl
index 6504174cbc..29eaa23375 100644
--- a/lib/kernel/src/file_server.erl
+++ b/lib/kernel/src/file_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -63,7 +63,7 @@ stop() ->
%%% Callback functions from gen_server
%%%----------------------------------------------------------------------
--type state() :: port(). % Internal type
+-type state() :: term(). % Internal type
%%----------------------------------------------------------------------
%% Func: init/1
@@ -73,18 +73,12 @@ stop() ->
%% {stop, Reason}
%%----------------------------------------------------------------------
--spec init([]) -> {'ok', state()} | {'stop', term()}.
+-spec init([]) -> {'ok', state()}.
init([]) ->
process_flag(trap_exit, true),
- case ?PRIM_FILE:start() of
- {ok, Handle} ->
- ?FILE_IO_SERVER_TABLE =
- ets:new(?FILE_IO_SERVER_TABLE, [named_table]),
- {ok, Handle};
- {error, Reason} ->
- {stop, Reason}
- end.
+ ?FILE_IO_SERVER_TABLE = ets:new(?FILE_IO_SERVER_TABLE, [named_table]),
+ {ok, undefined}.
%%----------------------------------------------------------------------
%% Func: handle_call/3
@@ -101,7 +95,7 @@ init([]) ->
{'reply', 'eof' | 'ok' | {'error', term()} | {'ok', term()}, state()} |
{'stop', 'normal', 'stopped', state()}.
-handle_call({open, Name, ModeList}, {Pid, _Tag} = _From, Handle)
+handle_call({open, Name, ModeList}, {Pid, _Tag} = _From, State)
when is_list(ModeList) ->
Child = ?FILE_IO_SERVER:start_link(Pid, Name, ModeList),
case Child of
@@ -110,78 +104,78 @@ handle_call({open, Name, ModeList}, {Pid, _Tag} = _From, Handle)
_ ->
ok
end,
- {reply, Child, Handle};
+ {reply, Child, State};
-handle_call({open, _Name, _Mode}, _From, Handle) ->
- {reply, {error, einval}, Handle};
+handle_call({open, _Name, _Mode}, _From, State) ->
+ {reply, {error, einval}, State};
-handle_call({read_file, Name}, _From, Handle) ->
- {reply, ?PRIM_FILE:read_file(Name), Handle};
+handle_call({read_file, Name}, _From, State) ->
+ {reply, ?PRIM_FILE:read_file(Name), State};
-handle_call({write_file, Name, Bin}, _From, Handle) ->
- {reply, ?PRIM_FILE:write_file(Name, Bin), Handle};
+handle_call({write_file, Name, Bin}, _From, State) ->
+ {reply, ?PRIM_FILE:write_file(Name, Bin), State};
-handle_call({set_cwd, Name}, _From, Handle) ->
- {reply, ?PRIM_FILE:set_cwd(Handle, Name), Handle};
+handle_call({set_cwd, Name}, _From, State) ->
+ {reply, ?PRIM_FILE:set_cwd(Name), State};
-handle_call({delete, Name}, _From, Handle) ->
- {reply, ?PRIM_FILE:delete(Handle, Name), Handle};
+handle_call({delete, Name}, _From, State) ->
+ {reply, ?PRIM_FILE:delete(Name), State};
-handle_call({rename, Fr, To}, _From, Handle) ->
- {reply, ?PRIM_FILE:rename(Handle, Fr, To), Handle};
+handle_call({rename, Fr, To}, _From, State) ->
+ {reply, ?PRIM_FILE:rename(Fr, To), State};
-handle_call({make_dir, Name}, _From, Handle) ->
- {reply, ?PRIM_FILE:make_dir(Handle, Name), Handle};
+handle_call({make_dir, Name}, _From, State) ->
+ {reply, ?PRIM_FILE:make_dir(Name), State};
-handle_call({del_dir, Name}, _From, Handle) ->
- {reply, ?PRIM_FILE:del_dir(Handle, Name), Handle};
+handle_call({del_dir, Name}, _From, State) ->
+ {reply, ?PRIM_FILE:del_dir(Name), State};
-handle_call({list_dir, Name}, _From, Handle) ->
- {reply, ?PRIM_FILE:list_dir(Handle, Name), Handle};
-handle_call({list_dir_all, Name}, _From, Handle) ->
- {reply, ?PRIM_FILE:list_dir_all(Handle, Name), Handle};
+handle_call({list_dir, Name}, _From, State) ->
+ {reply, ?PRIM_FILE:list_dir(Name), State};
+handle_call({list_dir_all, Name}, _From, State) ->
+ {reply, ?PRIM_FILE:list_dir_all(Name), State};
-handle_call(get_cwd, _From, Handle) ->
- {reply, ?PRIM_FILE:get_cwd(Handle), Handle};
-handle_call({get_cwd}, _From, Handle) ->
- {reply, ?PRIM_FILE:get_cwd(Handle), Handle};
-handle_call({get_cwd, Name}, _From, Handle) ->
- {reply, ?PRIM_FILE:get_cwd(Handle, Name), Handle};
+handle_call(get_cwd, _From, State) ->
+ {reply, ?PRIM_FILE:get_cwd(), State};
+handle_call({get_cwd}, _From, State) ->
+ {reply, ?PRIM_FILE:get_cwd(), State};
+handle_call({get_cwd, Name}, _From, State) ->
+ {reply, ?PRIM_FILE:get_cwd(Name), State};
-handle_call({read_file_info, Name}, _From, Handle) ->
- {reply, ?PRIM_FILE:read_file_info(Handle, Name), Handle};
+handle_call({read_file_info, Name}, _From, State) ->
+ {reply, ?PRIM_FILE:read_file_info(Name), State};
-handle_call({read_file_info, Name, Opts}, _From, Handle) ->
- {reply, ?PRIM_FILE:read_file_info(Handle, Name, Opts), Handle};
+handle_call({read_file_info, Name, Opts}, _From, State) ->
+ {reply, ?PRIM_FILE:read_file_info(Name, Opts), State};
-handle_call({altname, Name}, _From, Handle) ->
- {reply, ?PRIM_FILE:altname(Handle, Name), Handle};
+handle_call({altname, Name}, _From, State) ->
+ {reply, ?PRIM_FILE:altname(Name), State};
-handle_call({write_file_info, Name, Info}, _From, Handle) ->
- {reply, ?PRIM_FILE:write_file_info(Handle, Name, Info), Handle};
+handle_call({write_file_info, Name, Info}, _From, State) ->
+ {reply, ?PRIM_FILE:write_file_info(Name, Info), State};
-handle_call({write_file_info, Name, Info, Opts}, _From, Handle) ->
- {reply, ?PRIM_FILE:write_file_info(Handle, Name, Info, Opts), Handle};
+handle_call({write_file_info, Name, Info, Opts}, _From, State) ->
+ {reply, ?PRIM_FILE:write_file_info(Name, Info, Opts), State};
-handle_call({read_link_info, Name}, _From, Handle) ->
- {reply, ?PRIM_FILE:read_link_info(Handle, Name), Handle};
+handle_call({read_link_info, Name}, _From, State) ->
+ {reply, ?PRIM_FILE:read_link_info(Name), State};
-handle_call({read_link_info, Name, Opts}, _From, Handle) ->
- {reply, ?PRIM_FILE:read_link_info(Handle, Name, Opts), Handle};
+handle_call({read_link_info, Name, Opts}, _From, State) ->
+ {reply, ?PRIM_FILE:read_link_info(Name, Opts), State};
-handle_call({read_link, Name}, _From, Handle) ->
- {reply, ?PRIM_FILE:read_link(Handle, Name), Handle};
-handle_call({read_link_all, Name}, _From, Handle) ->
- {reply, ?PRIM_FILE:read_link_all(Handle, Name), Handle};
+handle_call({read_link, Name}, _From, State) ->
+ {reply, ?PRIM_FILE:read_link(Name), State};
+handle_call({read_link_all, Name}, _From, State) ->
+ {reply, ?PRIM_FILE:read_link_all(Name), State};
-handle_call({make_link, Old, New}, _From, Handle) ->
- {reply, ?PRIM_FILE:make_link(Handle, Old, New), Handle};
+handle_call({make_link, Old, New}, _From, State) ->
+ {reply, ?PRIM_FILE:make_link(Old, New), State};
-handle_call({make_symlink, Old, New}, _From, Handle) ->
- {reply, ?PRIM_FILE:make_symlink(Handle, Old, New), Handle};
+handle_call({make_symlink, Old, New}, _From, State) ->
+ {reply, ?PRIM_FILE:make_symlink(Old, New), State};
handle_call({copy, SourceName, SourceOpts, DestName, DestOpts, Length},
- _From, Handle) ->
+ _From, State) ->
Reply =
case ?PRIM_FILE:open(SourceName, [read, binary | SourceOpts]) of
{ok, Source} ->
@@ -201,14 +195,14 @@ handle_call({copy, SourceName, SourceOpts, DestName, DestOpts, Length},
{error, _} = Error ->
Error
end,
- {reply, Reply, Handle};
+ {reply, Reply, State};
-handle_call(stop, _From, Handle) ->
- {stop, normal, stopped, Handle};
+handle_call(stop, _From, State) ->
+ {stop, normal, stopped, State};
-handle_call(Request, From, Handle) ->
- error_logger:error_msg("handle_call(~p, ~p, _)", [Request, From]),
- {noreply, Handle}.
+handle_call(Request, From, State) ->
+ error_logger:error_msg("handle_call(~tp, ~tp, _)", [Request, From]),
+ {noreply, State}.
%%----------------------------------------------------------------------
%% Func: handle_cast/2
@@ -220,7 +214,7 @@ handle_call(Request, From, Handle) ->
-spec handle_cast(term(), state()) -> {'noreply', state()}.
handle_cast(Msg, State) ->
- error_logger:error_msg("handle_cast(~p, _)", [Msg]),
+ error_logger:error_msg("handle_cast(~tp, _)", [Msg]),
{noreply, State}.
%%----------------------------------------------------------------------
@@ -231,19 +225,14 @@ handle_cast(Msg, State) ->
%%----------------------------------------------------------------------
-spec handle_info(term(), state()) ->
- {'noreply', state()} | {'stop', 'normal', state()}.
+ {'noreply', state()}.
-handle_info({'EXIT', Pid, _Reason}, Handle) when is_pid(Pid) ->
+handle_info({'EXIT', Pid, _Reason}, State) when is_pid(Pid) ->
ets:delete(?FILE_IO_SERVER_TABLE, Pid),
- {noreply, Handle};
-
-handle_info({'EXIT', Handle, _Reason}, Handle) ->
- error_logger:error_msg("Port controlling ~w terminated in ~w",
- [?FILE_SERVER, ?MODULE]),
- {stop, normal, Handle};
+ {noreply, State};
handle_info(Info, State) ->
- error_logger:error_msg("handle_Info(~p, _)", [Info]),
+ error_logger:error_msg("handle_Info(~tp, _)", [Info]),
{noreply, State}.
%%----------------------------------------------------------------------
@@ -254,8 +243,8 @@ handle_info(Info, State) ->
-spec terminate(term(), state()) -> 'ok'.
-terminate(_Reason, Handle) ->
- ?PRIM_FILE:stop(Handle).
+terminate(_Reason, _State) ->
+ ok.
%%----------------------------------------------------------------------
%% Func: code_change/3
diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl
index a6aa0edd15..d893d44079 100644
--- a/lib/kernel/src/gen_sctp.erl
+++ b/lib/kernel/src/gen_sctp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -66,7 +66,12 @@
{sctp_set_peer_primary_addr, #sctp_setpeerprim{}} |
{sctp_status, #sctp_status{}} |
{sndbuf, non_neg_integer()} |
- {tos, non_neg_integer()}.
+ {tos, non_neg_integer()} |
+ {tclass, non_neg_integer()} |
+ {ttl, non_neg_integer()} |
+ {recvtos, boolean()} |
+ {recvtclass, boolean()} |
+ {recvttl, boolean()}.
-type option_name() ::
active |
buffer |
@@ -97,7 +102,12 @@
sctp_set_peer_primary_addr |
sctp_status |
sndbuf |
- tos.
+ tos |
+ tclass |
+ ttl |
+ recvtos |
+ recvtclass |
+ recvttl.
-type sctp_socket() :: port().
-export_type([assoc_id/0, option/0, option_name/0, sctp_socket/0]).
@@ -118,6 +128,8 @@ open() ->
| inet:address_family()
| {port,Port}
| {type,SockType}
+ | {netns, file:filename_all()}
+ | {bind_to_device, binary()}
| option(),
IP :: inet:ip_address() | any | loopback,
Port :: inet:port_number(),
@@ -363,7 +375,7 @@ send(S, AssocChange, Stream, Data) ->
Socket :: sctp_socket(),
FromIP :: inet:ip_address(),
FromPort :: inet:port_number(),
- AncData :: [#sctp_sndrcvinfo{}],
+ AncData :: [#sctp_sndrcvinfo{} | inet:ancillary_data()],
Data :: binary() | string() | #sctp_sndrcvinfo{}
| #sctp_assoc_change{} | #sctp_paddr_change{}
| #sctp_adaptation_event{},
@@ -380,7 +392,7 @@ recv(S) ->
Timeout :: timeout(),
FromIP :: inet:ip_address(),
FromPort :: inet:port_number(),
- AncData :: [#sctp_sndrcvinfo{}],
+ AncData :: [#sctp_sndrcvinfo{} | inet:ancillary_data()],
Data :: binary() | string() | #sctp_sndrcvinfo{}
| #sctp_assoc_change{} | #sctp_paddr_change{}
| #sctp_adaptation_event{},
diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl
index ac61dbc792..7f7833ec23 100644
--- a/lib/kernel/src/gen_tcp.erl
+++ b/lib/kernel/src/gen_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -62,7 +62,14 @@
{show_econnreset, boolean()} |
{sndbuf, non_neg_integer()} |
{tos, non_neg_integer()} |
+ {tclass, non_neg_integer()} |
+ {ttl, non_neg_integer()} |
+ {recvtos, boolean()} |
+ {recvtclass, boolean()} |
+ {recvttl, boolean()} |
{ipv6_v6only, boolean()}.
+-type pktoptions_value() ::
+ {pktoptions, inet:ancillary_data()}.
-type option_name() ::
active |
buffer |
@@ -81,6 +88,7 @@
nodelay |
packet |
packet_size |
+ pktoptions |
priority |
{raw,
Protocol :: non_neg_integer(),
@@ -94,6 +102,12 @@
show_econnreset |
sndbuf |
tos |
+ tclass |
+ ttl |
+ recvtos |
+ recvtclass |
+ recvttl |
+ pktoptions |
ipv6_v6only.
-type connect_option() ::
{ip, inet:socket_address()} |
@@ -102,6 +116,8 @@
inet:address_family() |
{port, inet:port_number()} |
{tcp_module, module()} |
+ {netns, file:filename_all()} |
+ {bind_to_device, binary()} |
option().
-type listen_option() ::
{ip, inet:socket_address()} |
@@ -111,11 +127,13 @@
{port, inet:port_number()} |
{backlog, B :: non_neg_integer()} |
{tcp_module, module()} |
+ {netns, file:filename_all()} |
+ {bind_to_device, binary()} |
option().
-type socket() :: port().
-export_type([option/0, option_name/0, connect_option/0, listen_option/0,
- socket/0]).
+ socket/0, pktoptions_value/0]).
%%
%% Connect a socket
diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl
index 3121544719..d6e8652e77 100644
--- a/lib/kernel/src/gen_udp.erl
+++ b/lib/kernel/src/gen_udp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -51,6 +51,11 @@
{reuseaddr, boolean()} |
{sndbuf, non_neg_integer()} |
{tos, non_neg_integer()} |
+ {tclass, non_neg_integer()} |
+ {ttl, non_neg_integer()} |
+ {recvtos, boolean()} |
+ {recvtclass, boolean()} |
+ {recvttl, boolean()} |
{ipv6_v6only, boolean()}.
-type option_name() ::
active |
@@ -76,6 +81,12 @@
reuseaddr |
sndbuf |
tos |
+ tclass |
+ ttl |
+ recvtos |
+ recvtclass |
+ recvttl |
+ pktoptions |
ipv6_v6only.
-type socket() :: port().
@@ -97,6 +108,8 @@ open(Port) ->
| {ifaddr, inet:socket_address()}
| inet:address_family()
| {port, inet:port_number()}
+ | {netns, file:filename_all()}
+ | {bind_to_device, binary()}
| option(),
Socket :: socket(),
Reason :: inet:posix().
@@ -145,11 +158,13 @@ send(S, Packet) when is_port(S) ->
end.
-spec recv(Socket, Length) ->
- {ok, {Address, Port, Packet}} | {error, Reason} when
+ {ok, RecvData} | {error, Reason} when
Socket :: socket(),
Length :: non_neg_integer(),
+ RecvData :: {Address, Port, Packet} | {Address, Port, AncData, Packet},
Address :: inet:ip_address() | inet:returned_non_ip_address(),
Port :: inet:port_number(),
+ AncData :: inet:ancillary_data(),
Packet :: string() | binary(),
Reason :: not_owner | inet:posix().
@@ -162,12 +177,14 @@ recv(S,Len) when is_port(S), is_integer(Len) ->
end.
-spec recv(Socket, Length, Timeout) ->
- {ok, {Address, Port, Packet}} | {error, Reason} when
+ {ok, RecvData} | {error, Reason} when
Socket :: socket(),
Length :: non_neg_integer(),
Timeout :: timeout(),
+ RecvData :: {Address, Port, Packet} | {Address, Port, AncData, Packet},
Address :: inet:ip_address() | inet:returned_non_ip_address(),
Port :: inet:port_number(),
+ AncData :: inet:ancillary_data(),
Packet :: string() | binary(),
Reason :: not_owner | inet:posix().
diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl
index a9e92b28b8..a38522eb5c 100644
--- a/lib/kernel/src/global.erl
+++ b/lib/kernel/src/global.erl
@@ -262,7 +262,7 @@ check_dupname(Name, Pid) ->
{ok, allow} ->
true;
_ ->
- S = "global: ~w registered under several names: ~w\n",
+ S = "global: ~w registered under several names: ~tw\n",
Names = [Name | [Name1 || {_Pid, Name1} <- PidNames]],
error_logger:error_msg(S, [Pid, Names]),
false
@@ -659,7 +659,7 @@ handle_call(stop, _From, S) ->
handle_call(Request, From, S) ->
error_logger:warning_msg("The global_name_server "
"received an unexpected message:\n"
- "handle_call(~p, ~p, _)\n",
+ "handle_call(~tp, ~tp, _)\n",
[Request, From]),
{noreply, S}.
@@ -828,7 +828,7 @@ handle_cast({async_del_lock, _ResourceId, _Pid}, S) ->
handle_cast(Request, S) ->
error_logger:warning_msg("The global_name_server "
"received an unexpected message:\n"
- "handle_cast(~p, _)\n", [Request]),
+ "handle_cast(~tp, _)\n", [Request]),
{noreply, S}.
%%========================================================================
@@ -955,7 +955,7 @@ handle_info({'DOWN', MonitorRef, process, _Pid, _Info}, S0) ->
handle_info(Message, S) ->
error_logger:warning_msg("The global_name_server "
"received an unexpected message:\n"
- "handle_info(~p, _)\n", [Message]),
+ "handle_info(~tp, _)\n", [Message]),
{noreply, S}.
@@ -1949,13 +1949,13 @@ exchange_names([{Name, Pid, Method} | Tail], Node, Ops, Res) ->
exchange_names(Tail, Node, [Op | Ops], [Op | Res]);
{badrpc, Badrpc} ->
error_logger:info_msg("global: badrpc ~w received when "
- "conflicting name ~w was found\n",
+ "conflicting name ~tw was found\n",
[Badrpc, Name]),
Op = {insert, {Name, Pid, Method}},
exchange_names(Tail, Node, [Op | Ops], Res);
Else ->
error_logger:info_msg("global: Resolve method ~w for "
- "conflicting name ~w returned ~w\n",
+ "conflicting name ~tw returned ~tw\n",
[Method, Name, Else]),
Op = {delete, Name},
exchange_names(Tail, Node, [Op | Ops], [Op | Res])
@@ -1984,7 +1984,7 @@ minmax(P1,P2) ->
Pid2 :: pid().
random_exit_name(Name, Pid, Pid2) ->
{Min, Max} = minmax(Pid, Pid2),
- error_logger:info_msg("global: Name conflict terminating ~w\n",
+ error_logger:info_msg("global: Name conflict terminating ~tw\n",
[{Name, Max}]),
exit(Max, kill),
Min.
@@ -2200,7 +2200,7 @@ unexpected_message({'EXIT', _Pid, _Reason}, _What) ->
ok;
unexpected_message(Message, What) ->
error_logger:warning_msg("The global_name_server ~w process "
- "received an unexpected message:\n~p\n",
+ "received an unexpected message:\n~tp\n",
[What, Message]).
%%% Utilities
diff --git a/lib/kernel/src/group.erl b/lib/kernel/src/group.erl
index bf785959ff..5625ae6eb7 100644
--- a/lib/kernel/src/group.erl
+++ b/lib/kernel/src/group.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -114,7 +114,7 @@ server_loop(Drv, Shell, Buf0) ->
{io_request,From,ReplyAs,Req} when is_pid(From) ->
%% This io_request may cause a transition to a couple of
%% selective receive loops elsewhere in this module.
- Buf = io_request(Req, From, ReplyAs, Drv, Buf0),
+ Buf = io_request(Req, From, ReplyAs, Drv, Shell, Buf0),
server_loop(Drv, Shell, Buf);
{reply,{{From,ReplyAs},Reply}} ->
io_reply(From, ReplyAs, Reply),
@@ -135,7 +135,7 @@ server_loop(Drv, Shell, Buf0) ->
exit(R);
%% We want to throw away any term that we don't handle (standard
%% practice in receive loops), but not any {Drv,_} tuples which are
- %% handled in io_request/5.
+ %% handled in io_request/6.
NotDrvTuple when (not is_tuple(NotDrvTuple)) orelse
(tuple_size(NotDrvTuple) =/= 2) orelse
(element(1, NotDrvTuple) =/= Drv) ->
@@ -177,8 +177,8 @@ set_unicode_state(Drv,Bool) ->
end.
-io_request(Req, From, ReplyAs, Drv, Buf0) ->
- case io_request(Req, Drv, {From,ReplyAs}, Buf0) of
+io_request(Req, From, ReplyAs, Drv, Shell, Buf0) ->
+ case io_request(Req, Drv, Shell, {From,ReplyAs}, Buf0) of
{ok,Reply,Buf} ->
io_reply(From, ReplyAs, Reply),
Buf;
@@ -208,7 +208,7 @@ io_request(Req, From, ReplyAs, Drv, Buf0) ->
%%
%% These put requests have to be synchronous to the driver as otherwise
%% there is no guarantee that the data has actually been printed.
-io_request({put_chars,unicode,Chars}, Drv, From, Buf) ->
+io_request({put_chars,unicode,Chars}, Drv, _Shell, From, Buf) ->
case catch unicode:characters_to_binary(Chars,utf8) of
Binary when is_binary(Binary) ->
send_drv(Drv, {put_chars_sync, unicode, Binary, {From,ok}}),
@@ -216,7 +216,7 @@ io_request({put_chars,unicode,Chars}, Drv, From, Buf) ->
_ ->
{error,{error,{put_chars, unicode,Chars}},Buf}
end;
-io_request({put_chars,unicode,M,F,As}, Drv, From, Buf) ->
+io_request({put_chars,unicode,M,F,As}, Drv, _Shell, From, Buf) ->
case catch apply(M, F, As) of
Binary when is_binary(Binary) ->
send_drv(Drv, {put_chars_sync, unicode, Binary, {From,ok}}),
@@ -230,12 +230,12 @@ io_request({put_chars,unicode,M,F,As}, Drv, From, Buf) ->
{error,{error,F},Buf}
end
end;
-io_request({put_chars,latin1,Binary}, Drv, From, Buf) when is_binary(Binary) ->
+io_request({put_chars,latin1,Binary}, Drv, _Shell, From, Buf) when is_binary(Binary) ->
send_drv(Drv, {put_chars_sync, unicode,
unicode:characters_to_binary(Binary,latin1),
{From,ok}}),
{noreply,Buf};
-io_request({put_chars,latin1,Chars}, Drv, From, Buf) ->
+io_request({put_chars,latin1,Chars}, Drv, _Shell, From, Buf) ->
case catch unicode:characters_to_binary(Chars,latin1) of
Binary when is_binary(Binary) ->
send_drv(Drv, {put_chars_sync, unicode, Binary, {From,ok}}),
@@ -243,7 +243,7 @@ io_request({put_chars,latin1,Chars}, Drv, From, Buf) ->
_ ->
{error,{error,{put_chars,latin1,Chars}},Buf}
end;
-io_request({put_chars,latin1,M,F,As}, Drv, From, Buf) ->
+io_request({put_chars,latin1,M,F,As}, Drv, _Shell, From, Buf) ->
case catch apply(M, F, As) of
Binary when is_binary(Binary) ->
send_drv(Drv, {put_chars_sync, unicode,
@@ -260,30 +260,30 @@ io_request({put_chars,latin1,M,F,As}, Drv, From, Buf) ->
end
end;
-io_request({get_chars,Encoding,Prompt,N}, Drv, _From, Buf) ->
- get_chars(Prompt, io_lib, collect_chars, N, Drv, Buf, Encoding);
-io_request({get_line,Encoding,Prompt}, Drv, _From, Buf) ->
- get_chars(Prompt, io_lib, collect_line, [], Drv, Buf, Encoding);
-io_request({get_until,Encoding, Prompt,M,F,As}, Drv, _From, Buf) ->
- get_chars(Prompt, io_lib, get_until, {M,F,As}, Drv, Buf, Encoding);
-io_request({get_password,_Encoding},Drv,_From,Buf) ->
- get_password_chars(Drv, Buf);
-io_request({setopts,Opts}, Drv, _From, Buf) when is_list(Opts) ->
+io_request({get_chars,Encoding,Prompt,N}, Drv, Shell, _From, Buf) ->
+ get_chars_n(Prompt, io_lib, collect_chars, N, Drv, Shell, Buf, Encoding);
+io_request({get_line,Encoding,Prompt}, Drv, Shell, _From, Buf) ->
+ get_chars_line(Prompt, io_lib, collect_line, [], Drv, Shell, Buf, Encoding);
+io_request({get_until,Encoding, Prompt,M,F,As}, Drv, Shell, _From, Buf) ->
+ get_chars_line(Prompt, io_lib, get_until, {M,F,As}, Drv, Shell, Buf, Encoding);
+io_request({get_password,_Encoding},Drv,Shell,_From,Buf) ->
+ get_password_chars(Drv, Shell, Buf);
+io_request({setopts,Opts}, Drv, _Shell, _From, Buf) when is_list(Opts) ->
setopts(Opts, Drv, Buf);
-io_request(getopts, Drv, _From, Buf) ->
+io_request(getopts, Drv, _Shell, _From, Buf) ->
getopts(Drv, Buf);
-io_request({requests,Reqs}, Drv, From, Buf) ->
- io_requests(Reqs, {ok,ok,Buf}, From, Drv);
+io_request({requests,Reqs}, Drv, Shell, From, Buf) ->
+ io_requests(Reqs, {ok,ok,Buf}, From, Drv, Shell);
%% New in R12
-io_request({get_geometry,columns},Drv,_From,Buf) ->
+io_request({get_geometry,columns},Drv,_Shell,_From,Buf) ->
case get_tty_geometry(Drv) of
{W,_H} ->
{ok,W,Buf};
_ ->
{error,{error,enotsup},Buf}
end;
-io_request({get_geometry,rows},Drv,_From,Buf) ->
+io_request({get_geometry,rows},Drv,_Shell,_From,Buf) ->
case get_tty_geometry(Drv) of
{_W,H} ->
{ok,H,Buf};
@@ -292,40 +292,40 @@ io_request({get_geometry,rows},Drv,_From,Buf) ->
end;
%% BC with pre-R13
-io_request({put_chars,Chars}, Drv, From, Buf) ->
- io_request({put_chars,latin1,Chars}, Drv, From, Buf);
-io_request({put_chars,M,F,As}, Drv, From, Buf) ->
- io_request({put_chars,latin1,M,F,As}, Drv, From, Buf);
-io_request({get_chars,Prompt,N}, Drv, From, Buf) ->
- io_request({get_chars,latin1,Prompt,N}, Drv, From, Buf);
-io_request({get_line,Prompt}, Drv, From, Buf) ->
- io_request({get_line,latin1,Prompt}, Drv, From, Buf);
-io_request({get_until, Prompt,M,F,As}, Drv, From, Buf) ->
- io_request({get_until,latin1, Prompt,M,F,As}, Drv, From, Buf);
-io_request(get_password,Drv,From,Buf) ->
- io_request({get_password,latin1},Drv,From,Buf);
-
-
-
-io_request(_, _Drv, _From, Buf) ->
+io_request({put_chars,Chars}, Drv, Shell, From, Buf) ->
+ io_request({put_chars,latin1,Chars}, Drv, Shell, From, Buf);
+io_request({put_chars,M,F,As}, Drv, Shell, From, Buf) ->
+ io_request({put_chars,latin1,M,F,As}, Drv, Shell, From, Buf);
+io_request({get_chars,Prompt,N}, Drv, Shell, From, Buf) ->
+ io_request({get_chars,latin1,Prompt,N}, Drv, Shell, From, Buf);
+io_request({get_line,Prompt}, Drv, Shell, From, Buf) ->
+ io_request({get_line,latin1,Prompt}, Drv, Shell, From, Buf);
+io_request({get_until, Prompt,M,F,As}, Drv, Shell, From, Buf) ->
+ io_request({get_until,latin1, Prompt,M,F,As}, Drv, Shell, From, Buf);
+io_request(get_password,Drv,Shell,From,Buf) ->
+ io_request({get_password,latin1},Drv,Shell,From,Buf);
+
+
+
+io_request(_, _Drv, _Shell, _From, Buf) ->
{error,{error,request},Buf}.
-%% Status = io_requests(RequestList, PrevStat, From, Drv)
+%% Status = io_requests(RequestList, PrevStat, From, Drv, Shell)
%% Process a list of output requests as long as
%% the previous status is 'ok' or noreply.
%%
%% We use undefined as the From for all but the last request
%% in order to discards acknowledgements from those requests.
%%
-io_requests([R|Rs], {noreply,Buf}, From, Drv) ->
+io_requests([R|Rs], {noreply,Buf}, From, Drv, Shell) ->
ReqFrom = if Rs =:= [] -> From; true -> undefined end,
- io_requests(Rs, io_request(R, Drv, ReqFrom, Buf), From, Drv);
-io_requests([R|Rs], {ok,ok,Buf}, From, Drv) ->
+ io_requests(Rs, io_request(R, Drv, Shell, ReqFrom, Buf), From, Drv, Shell);
+io_requests([R|Rs], {ok,ok,Buf}, From, Drv, Shell) ->
ReqFrom = if Rs =:= [] -> From; true -> undefined end,
- io_requests(Rs, io_request(R, Drv, ReqFrom, Buf), From, Drv);
-io_requests([_|_], Error, _From, _Drv) ->
+ io_requests(Rs, io_request(R, Drv, Shell, ReqFrom, Buf), From, Drv, Shell);
+io_requests([_|_], Error, _From, _Drv, _Shell) ->
Error;
-io_requests([], Stat, _From, _) ->
+io_requests([], Stat, _From, _, _Shell) ->
Stat.
%% io_reply(From, ReplyAs, Reply)
@@ -333,7 +333,7 @@ io_requests([], Stat, _From, _) ->
%% The ACK contains the return value.
io_reply(undefined, _ReplyAs, _Reply) ->
- %% Ignore these replies as they are generated from io_requests/4.
+ %% Ignore these replies as they are generated from io_requests/5.
ok;
io_reply(From, ReplyAs, Reply) ->
From ! {io_reply,ReplyAs,Reply},
@@ -434,7 +434,7 @@ getopts(Drv,Buf) ->
{ok,[Exp,Echo,Bin,Uni],Buf}.
-%% get_chars(Prompt, Module, Function, XtraArgument, Drv, Buffer)
+%% get_chars_*(Prompt, Module, Function, XtraArgument, Drv, Buffer)
%% Gets characters from the input Drv until as the applied function
%% returns {stop,Result,Rest}. Does not block output until input has been
%% received.
@@ -442,8 +442,8 @@ getopts(Drv,Buf) ->
%% {Result,NewSaveBuffer}
%% {error,What,NewSaveBuffer}
-get_password_chars(Drv,Buf) ->
- case get_password_line(Buf, Drv) of
+get_password_chars(Drv,Shell,Buf) ->
+ case get_password_line(Buf, Drv, Shell) of
{done, Line, Buf1} ->
{ok, Line, Buf1};
interrupted ->
@@ -452,36 +452,62 @@ get_password_chars(Drv,Buf) ->
{exit, terminated}
end.
-get_chars(Prompt, M, F, Xa, Drv, Buf, Encoding) ->
+get_chars_n(Prompt, M, F, Xa, Drv, Shell, Buf, Encoding) ->
Pbs = prompt_bytes(Prompt, Encoding),
- get_chars_loop(Pbs, M, F, Xa, Drv, Buf, start, Encoding).
+ case get(echo) of
+ true ->
+ get_chars_loop(Pbs, M, F, Xa, Drv, Shell, Buf, start, Encoding);
+ false ->
+ get_chars_n_loop(Pbs, M, F, Xa, Drv, Shell, Buf, start, Encoding)
+ end.
+
+get_chars_line(Prompt, M, F, Xa, Drv, Shell, Buf, Encoding) ->
+ Pbs = prompt_bytes(Prompt, Encoding),
+ get_chars_loop(Pbs, M, F, Xa, Drv, Shell, Buf, start, Encoding).
-get_chars_loop(Pbs, M, F, Xa, Drv, Buf0, State, Encoding) ->
- Result = case get(echo) of
+get_chars_loop(Pbs, M, F, Xa, Drv, Shell, Buf0, State, Encoding) ->
+ Result = case get(echo) of
true ->
- get_line(Buf0, Pbs, Drv, Encoding);
+ get_line(Buf0, Pbs, Drv, Shell, Encoding);
false ->
% get_line_echo_off only deals with lists
% and does not need encoding...
- get_line_echo_off(Buf0, Pbs, Drv)
+ get_line_echo_off(Buf0, Pbs, Drv, Shell)
end,
case Result of
- {done,Line,Buf1} ->
- get_chars_apply(Pbs, M, F, Xa, Drv, Buf1, State, Line, Encoding);
+ {done,Line,Buf} ->
+ get_chars_apply(Pbs, M, F, Xa, Drv, Shell, Buf, State, Line, Encoding);
interrupted ->
{error,{error,interrupted},[]};
terminated ->
{exit,terminated}
end.
-get_chars_apply(Pbs, M, F, Xa, Drv, Buf, State0, Line, Encoding) ->
+get_chars_apply(Pbs, M, F, Xa, Drv, Shell, Buf, State0, Line, Encoding) ->
case catch M:F(State0, cast(Line,get(read_mode), Encoding), Encoding, Xa) of
- {stop,Result,Rest} ->
- {ok,Result,append(Rest, Buf, Encoding)};
- {'EXIT',_} ->
- {error,{error,err_func(M, F, Xa)},[]};
- State1 ->
- get_chars_loop(Pbs, M, F, Xa, Drv, Buf, State1, Encoding)
+ {stop,Result,Rest} ->
+ {ok,Result,append(Rest, Buf, Encoding)};
+ {'EXIT',_} ->
+ {error,{error,err_func(M, F, Xa)},[]};
+ State1 ->
+ get_chars_loop(Pbs, M, F, Xa, Drv, Shell, Buf, State1, Encoding)
+ end.
+
+get_chars_n_loop(Pbs, M, F, Xa, Drv, Shell, Buf0, State, Encoding) ->
+ try M:F(State, cast(Buf0, get(read_mode), Encoding), Encoding, Xa) of
+ {stop,Result,Rest} ->
+ {ok, Result, Rest};
+ State1 ->
+ case get_chars_echo_off(Pbs, Drv, Shell) of
+ interrupted ->
+ {error,{error,interrupted},[]};
+ terminated ->
+ {exit,terminated};
+ Buf ->
+ get_chars_n_loop(Pbs, M, F, Xa, Drv, Shell, Buf, State1, Encoding)
+ end
+ catch _:_ ->
+ {error,{error,err_func(M, F, Xa)},[]}
end.
%% Convert error code to make it look as before
@@ -497,24 +523,24 @@ err_func(_, F, _) ->
%% {done,LineChars,RestChars}
%% interrupted
-get_line(Chars, Pbs, Drv, Encoding) ->
+get_line(Chars, Pbs, Drv, Shell, Encoding) ->
{more_chars,Cont,Rs} = edlin:start(Pbs),
send_drv_reqs(Drv, Rs),
- get_line1(edlin:edit_line(Chars, Cont), Drv, new_stack(get(line_buffer)),
+ get_line1(edlin:edit_line(Chars, Cont), Drv, Shell, new_stack(get(line_buffer)),
Encoding).
-get_line1({done,Line,Rest,Rs}, Drv, Ls, _Encoding) ->
+get_line1({done,Line,Rest,Rs}, Drv, _Shell, Ls, _Encoding) ->
send_drv_reqs(Drv, Rs),
save_line_buffer(Line, get_lines(Ls)),
{done,Line,Rest};
-get_line1({undefined,{_A,Mode,Char},Cs,Cont,Rs}, Drv, Ls0, Encoding)
+get_line1({undefined,{_A,Mode,Char},Cs,Cont,Rs}, Drv, Shell, Ls0, Encoding)
when ((Mode =:= none) and (Char =:= $\^P))
or ((Mode =:= meta_left_sq_bracket) and (Char =:= $A)) ->
send_drv_reqs(Drv, Rs),
case up_stack(save_line(Ls0, edlin:current_line(Cont))) of
{none,_Ls} ->
send_drv(Drv, beep),
- get_line1(edlin:edit_line(Cs, Cont), Drv, Ls0, Encoding);
+ get_line1(edlin:edit_line(Cs, Cont), Drv, Shell, Ls0, Encoding);
{Lcs,Ls} ->
send_drv_reqs(Drv, edlin:erase_line(Cont)),
{more_chars,Ncont,Nrs} = edlin:start(edlin:prompt(Cont)),
@@ -522,16 +548,17 @@ get_line1({undefined,{_A,Mode,Char},Cs,Cont,Rs}, Drv, Ls0, Encoding)
get_line1(edlin:edit_line1(lists:sublist(Lcs, 1, length(Lcs)-1),
Ncont),
Drv,
+ Shell,
Ls, Encoding)
end;
-get_line1({undefined,{_A,Mode,Char},Cs,Cont,Rs}, Drv, Ls0, Encoding)
+get_line1({undefined,{_A,Mode,Char},Cs,Cont,Rs}, Drv, Shell, Ls0, Encoding)
when ((Mode =:= none) and (Char =:= $\^N))
or ((Mode =:= meta_left_sq_bracket) and (Char =:= $B)) ->
send_drv_reqs(Drv, Rs),
case down_stack(save_line(Ls0, edlin:current_line(Cont))) of
{none,_Ls} ->
send_drv(Drv, beep),
- get_line1(edlin:edit_line(Cs, Cont), Drv, Ls0, Encoding);
+ get_line1(edlin:edit_line(Cs, Cont), Drv, Shell, Ls0, Encoding);
{Lcs,Ls} ->
send_drv_reqs(Drv, edlin:erase_line(Cont)),
{more_chars,Ncont,Nrs} = edlin:start(edlin:prompt(Cont)),
@@ -539,6 +566,7 @@ get_line1({undefined,{_A,Mode,Char},Cs,Cont,Rs}, Drv, Ls0, Encoding)
get_line1(edlin:edit_line1(lists:sublist(Lcs, 1, length(Lcs)-1),
Ncont),
Drv,
+ Shell,
Ls, Encoding)
end;
%% ^R = backward search, ^S = forward search.
@@ -551,7 +579,7 @@ get_line1({undefined,{_A,Mode,Char},Cs,Cont,Rs}, Drv, Ls0, Encoding)
%% new modes: search, search_quit, search_found. These are added to
%% the regular ones (none, meta_left_sq_bracket) and handle special
%% cases of history search.
-get_line1({undefined,{_A,Mode,Char},Cs,Cont,Rs}, Drv, Ls, Encoding)
+get_line1({undefined,{_A,Mode,Char},Cs,Cont,Rs}, Drv, Shell, Ls, Encoding)
when ((Mode =:= none) and (Char =:= $\^R)) ->
send_drv_reqs(Drv, Rs),
%% drop current line, move to search mode. We store the current
@@ -561,8 +589,8 @@ get_line1({undefined,{_A,Mode,Char},Cs,Cont,Rs}, Drv, Ls, Encoding)
Pbs = prompt_bytes("(search)`': ", Encoding),
{more_chars,Ncont,Nrs} = edlin:start(Pbs, search),
send_drv_reqs(Drv, Nrs),
- get_line1(edlin:edit_line1(Cs, Ncont), Drv, Ls, Encoding);
-get_line1({expand, Before, Cs0, Cont,Rs}, Drv, Ls0, Encoding) ->
+ get_line1(edlin:edit_line1(Cs, Ncont), Drv, Shell, Ls, Encoding);
+get_line1({expand, Before, Cs0, Cont,Rs}, Drv, Shell, Ls0, Encoding) ->
send_drv_reqs(Drv, Rs),
ExpandFun = get(expand_fun),
{Found, Add, Matches} = ExpandFun(Before),
@@ -577,37 +605,37 @@ get_line1({expand, Before, Cs0, Cont,Rs}, Drv, Ls0, Encoding) ->
send_drv(Drv, {put_chars, unicode, unicode:characters_to_binary(MatchStr,unicode)}),
[$\^L | Cs1]
end,
- get_line1(edlin:edit_line(Cs, Cont), Drv, Ls0, Encoding);
-get_line1({undefined,_Char,Cs,Cont,Rs}, Drv, Ls, Encoding) ->
+ get_line1(edlin:edit_line(Cs, Cont), Drv, Shell, Ls0, Encoding);
+get_line1({undefined,_Char,Cs,Cont,Rs}, Drv, Shell, Ls, Encoding) ->
send_drv_reqs(Drv, Rs),
send_drv(Drv, beep),
- get_line1(edlin:edit_line(Cs, Cont), Drv, Ls, Encoding);
+ get_line1(edlin:edit_line(Cs, Cont), Drv, Shell, Ls, Encoding);
%% The search item was found and accepted (new line entered on the exact
%% result found)
-get_line1({_What,Cont={line,_Prompt,_Chars,search_found},Rs}, Drv, Ls0, Encoding) ->
+get_line1({_What,Cont={line,_Prompt,_Chars,search_found},Rs}, Drv, Shell, Ls0, Encoding) ->
Line = edlin:current_line(Cont),
%% this may create duplicate entries.
Ls = save_line(new_stack(get_lines(Ls0)), Line),
- get_line1({done, Line, "", Rs}, Drv, Ls, Encoding);
+ get_line1({done, Line, "", Rs}, Drv, Shell, Ls, Encoding);
%% The search mode has been exited, but the user wants to remain in line
%% editing mode wherever that was, but editing the search result.
-get_line1({What,Cont={line,_Prompt,_Chars,search_quit},Rs}, Drv, Ls, Encoding) ->
+get_line1({What,Cont={line,_Prompt,_Chars,search_quit},Rs}, Drv, Shell, Ls, Encoding) ->
Line = edlin:current_chars(Cont),
%% Load back the old prompt with the correct line number.
case get(search_quit_prompt) of
undefined -> % should not happen. Fallback.
LsFallback = save_line(new_stack(get_lines(Ls)), Line),
- get_line1({done, "\n", Line, Rs}, Drv, LsFallback, Encoding);
+ get_line1({done, "\n", Line, Rs}, Drv, Shell, LsFallback, Encoding);
Prompt -> % redraw the line and keep going with the same stack position
NCont = {line,Prompt,{lists:reverse(Line),[]},none},
send_drv_reqs(Drv, Rs),
send_drv_reqs(Drv, edlin:erase_line(Cont)),
send_drv_reqs(Drv, edlin:redraw_line(NCont)),
- get_line1({What, NCont ,[]}, Drv, pad_stack(Ls), Encoding)
+ get_line1({What, NCont ,[]}, Drv, Shell, pad_stack(Ls), Encoding)
end;
%% Search mode is entered.
get_line1({What,{line,Prompt,{RevCmd0,_Aft},search},Rs},
- Drv, Ls0, Encoding) ->
+ Drv, Shell, Ls0, Encoding) ->
send_drv_reqs(Drv, Rs),
%% Figure out search direction. ^S and ^R are returned through edlin
%% whenever we received a search while being already in search mode.
@@ -629,61 +657,90 @@ get_line1({What,{line,Prompt,{RevCmd0,_Aft},search},Rs},
{Ls2, {RevCmd, "': "++Line}}
end,
Cont = {line,Prompt,NewStack,search},
- more_data(What, Cont, Drv, Ls, Encoding);
-get_line1({What,Cont0,Rs}, Drv, Ls, Encoding) ->
+ more_data(What, Cont, Drv, Shell, Ls, Encoding);
+get_line1({What,Cont0,Rs}, Drv, Shell, Ls, Encoding) ->
send_drv_reqs(Drv, Rs),
- more_data(What, Cont0, Drv, Ls, Encoding).
+ more_data(What, Cont0, Drv, Shell, Ls, Encoding).
-more_data(What, Cont0, Drv, Ls, Encoding) ->
+more_data(What, Cont0, Drv, Shell, Ls, Encoding) ->
receive
{Drv,{data,Cs}} ->
- get_line1(edlin:edit_line(Cs, Cont0), Drv, Ls, Encoding);
+ get_line1(edlin:edit_line(Cs, Cont0), Drv, Shell, Ls, Encoding);
{Drv,eof} ->
- get_line1(edlin:edit_line(eof, Cont0), Drv, Ls, Encoding);
+ get_line1(edlin:edit_line(eof, Cont0), Drv, Shell, Ls, Encoding);
{io_request,From,ReplyAs,Req} when is_pid(From) ->
{more_chars,Cont,_More} = edlin:edit_line([], Cont0),
send_drv_reqs(Drv, edlin:erase_line(Cont)),
- io_request(Req, From, ReplyAs, Drv, []), %WRONG!!!
+ io_request(Req, From, ReplyAs, Drv, Shell, []), %WRONG!!!
send_drv_reqs(Drv, edlin:redraw_line(Cont)),
- get_line1({more_chars,Cont,[]}, Drv, Ls, Encoding);
+ get_line1({more_chars,Cont,[]}, Drv, Shell, Ls, Encoding);
{reply,{{From,ReplyAs},Reply}} ->
%% We take care of replies from puts here as well
io_reply(From, ReplyAs, Reply),
- more_data(What, Cont0, Drv, Ls, Encoding);
+ more_data(What, Cont0, Drv, Shell, Ls, Encoding);
{'EXIT',Drv,interrupt} ->
interrupted;
{'EXIT',Drv,_} ->
- terminated
+ terminated;
+ {'EXIT',Shell,R} ->
+ exit(R)
after
get_line_timeout(What)->
- get_line1(edlin:edit_line([], Cont0), Drv, Ls, Encoding)
+ get_line1(edlin:edit_line([], Cont0), Drv, Shell, Ls, Encoding)
end.
-get_line_echo_off(Chars, Pbs, Drv) ->
+get_line_echo_off(Chars, Pbs, Drv, Shell) ->
send_drv_reqs(Drv, [{put_chars, unicode,Pbs}]),
- get_line_echo_off1(edit_line(Chars,[]), Drv).
+ get_line_echo_off1(edit_line(Chars,[]), Drv, Shell).
-get_line_echo_off1({Chars,[]}, Drv) ->
+get_line_echo_off1({Chars,[]}, Drv, Shell) ->
receive
{Drv,{data,Cs}} ->
- get_line_echo_off1(edit_line(Cs, Chars), Drv);
+ get_line_echo_off1(edit_line(Cs, Chars), Drv, Shell);
{Drv,eof} ->
- get_line_echo_off1(edit_line(eof, Chars), Drv);
+ get_line_echo_off1(edit_line(eof, Chars), Drv, Shell);
{io_request,From,ReplyAs,Req} when is_pid(From) ->
- io_request(Req, From, ReplyAs, Drv, []),
- get_line_echo_off1({Chars,[]}, Drv);
+ io_request(Req, From, ReplyAs, Drv, Shell, []),
+ get_line_echo_off1({Chars,[]}, Drv, Shell);
{reply,{{From,ReplyAs},Reply}} when From =/= undefined ->
%% We take care of replies from puts here as well
io_reply(From, ReplyAs, Reply),
- get_line_echo_off1({Chars,[]},Drv);
+ get_line_echo_off1({Chars,[]},Drv, Shell);
{'EXIT',Drv,interrupt} ->
interrupted;
{'EXIT',Drv,_} ->
- terminated
+ terminated;
+ {'EXIT',Shell,R} ->
+ exit(R)
end;
-get_line_echo_off1({Chars,Rest}, _Drv) ->
+get_line_echo_off1({Chars,Rest}, _Drv, _Shell) ->
{done,lists:reverse(Chars),case Rest of done -> []; _ -> Rest end}.
+get_chars_echo_off(Pbs, Drv, Shell) ->
+ send_drv_reqs(Drv, [{put_chars, unicode,Pbs}]),
+ get_chars_echo_off1(Drv, Shell).
+
+get_chars_echo_off1(Drv, Shell) ->
+ receive
+ {Drv, {data, Cs}} ->
+ Cs;
+ {Drv, eof} ->
+ eof;
+ {io_request,From,ReplyAs,Req} when is_pid(From) ->
+ io_request(Req, From, ReplyAs, Drv, Shell, []),
+ get_chars_echo_off1(Drv, Shell);
+ {reply,{{From,ReplyAs},Reply}} when From =/= undefined ->
+ %% We take care of replies from puts here as well
+ io_reply(From, ReplyAs, Reply),
+ get_chars_echo_off1(Drv, Shell);
+ {'EXIT',Drv,interrupt} ->
+ interrupted;
+ {'EXIT',Drv,_} ->
+ terminated;
+ {'EXIT',Shell,R} ->
+ exit(R)
+ end.
+
%% We support line editing for the ICANON mode except the following
%% line editing characters, which already has another meaning in
%% echo-on mode (See Advanced Programming in the Unix Environment, 2nd ed,
@@ -793,9 +850,9 @@ search_up_stack(Stack, Substr) ->
case up_stack(Stack) of
{none,NewStack} -> {none,NewStack};
{L, NewStack} ->
- case string:str(L, Substr) of
- 0 -> search_up_stack(NewStack, Substr);
- _ -> {string:strip(L,right,$\n), NewStack}
+ case string:find(L, Substr) of
+ nomatch -> search_up_stack(NewStack, Substr);
+ _ -> {string:trim(L, trailing, "$\n"), NewStack}
end
end.
@@ -803,39 +860,41 @@ search_down_stack(Stack, Substr) ->
case down_stack(Stack) of
{none,NewStack} -> {none,NewStack};
{L, NewStack} ->
- case string:str(L, Substr) of
- 0 -> search_down_stack(NewStack, Substr);
- _ -> {string:strip(L,right,$\n), NewStack}
+ case string:find(L, Substr) of
+ nomatch -> search_down_stack(NewStack, Substr);
+ _ -> {string:trim(L, trailing, "$\n"), NewStack}
end
end.
%% This is get_line without line editing (except for backspace) and
%% without echo.
-get_password_line(Chars, Drv) ->
- get_password1(edit_password(Chars,[]),Drv).
+get_password_line(Chars, Drv, Shell) ->
+ get_password1(edit_password(Chars,[]),Drv,Shell).
-get_password1({Chars,[]}, Drv) ->
+get_password1({Chars,[]}, Drv, Shell) ->
receive
{Drv,{data,Cs}} ->
- get_password1(edit_password(Cs,Chars),Drv);
+ get_password1(edit_password(Cs,Chars),Drv,Shell);
{io_request,From,ReplyAs,Req} when is_pid(From) ->
%send_drv_reqs(Drv, [{delete_chars, -length(Pbs)}]),
- io_request(Req, From, ReplyAs, Drv, []), %WRONG!!!
+ io_request(Req, From, ReplyAs, Drv, Shell, []), %WRONG!!!
%% I guess the reason the above line is wrong is that Buf is
%% set to []. But do we expect anything but plain output?
- get_password1({Chars, []}, Drv);
+ get_password1({Chars, []}, Drv, Shell);
{reply,{{From,ReplyAs},Reply}} ->
%% We take care of replies from puts here as well
io_reply(From, ReplyAs, Reply),
- get_password1({Chars, []},Drv);
+ get_password1({Chars, []},Drv, Shell);
{'EXIT',Drv,interrupt} ->
interrupted;
{'EXIT',Drv,_} ->
- terminated
+ terminated;
+ {'EXIT',Shell,R} ->
+ exit(R)
end;
-get_password1({Chars,Rest},Drv) ->
+get_password1({Chars,Rest},Drv,_Shell) ->
send_drv_reqs(Drv,[{put_chars, unicode, "\n"}]),
{done,lists:reverse(Chars),case Rest of done -> []; _ -> Rest end}.
diff --git a/lib/kernel/src/group_history.erl b/lib/kernel/src/group_history.erl
index 91f3663cc5..9745848992 100644
--- a/lib/kernel/src/group_history.erl
+++ b/lib/kernel/src/group_history.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -260,7 +260,7 @@ resize_log(Name, _OldSize, NewSize) ->
ok ->
show('$#erlang-history-resize-result',
"ok~n", []);
- {error, {new_size_too_small, _}} ->
+ {error, {new_size_too_small, _, _}} ->
show('$#erlang-history-resize-result',
"failed (new size is too small)~n", []),
disable_history();
diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl
index f4c7c277ed..5704cc79c2 100644
--- a/lib/kernel/src/hipe_unified_loader.erl
+++ b/lib/kernel/src/hipe_unified_loader.erl
@@ -236,9 +236,10 @@ load_common(Mod, Bin, Beam, Architecture) ->
lists:foreach(fun({FE, DestAddress}) ->
hipe_bifs:set_native_address_in_fe(FE, DestAddress)
end, erase(closures_to_patch)),
- ok = hipe_bifs:commit_patch_load(LoaderState),
set_beam_call_traps(FunDefs),
- ok;
+ export_funs(FunDefs),
+ ok = hipe_bifs:commit_patch_load(LoaderState),
+ ok;
BeamBinary when is_binary(BeamBinary) ->
%% Find all closures in the code.
[] = erase(closures_to_patch), %Clean up, assertion.
@@ -274,6 +275,7 @@ needs_trampolines(Architecture) ->
arm -> true;
powerpc -> true;
ppc64 -> true;
+ amd64 -> true;
_ -> false
end.
@@ -451,7 +453,7 @@ make_beam_stub(Mod, LoaderState, MD5, Beam, FunDefs, ClosuresToPatch) ->
%%========================================================================
%% Patching
%% @spec patch(refs(), BaseAddress::integer(), ConstAndZone::term(),
-%% FunDefs::term(), TrampolineMap::term()) -> 'ok'.
+%% FunDefs::term(), TrampolineMap::term()) -> 'ok'
%% @type refs()=[{RefType::integer(), Reflist::reflist()} | refs()]
%%
%% @type reflist()= [{Data::term(), Offsets::offests()}|reflist()]
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index 6aef5476f1..5dd68dc285 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,7 +34,8 @@
ip/1, stats/0, options/0,
pushf/3, popf/1, close/1, gethostname/0, gethostname/1,
parse_ipv4_address/1, parse_ipv6_address/1, parse_ipv4strict_address/1,
- parse_ipv6strict_address/1, parse_address/1, parse_strict_address/1, ntoa/1]).
+ parse_ipv6strict_address/1, parse_address/1, parse_strict_address/1,
+ ntoa/1, ipv4_mapped_ipv6_address/1]).
-export([connect_options/2, listen_options/2, udp_options/2, sctp_options/2]).
-export([udp_module/1, tcp_module/1, tcp_module/2, sctp_module/1]).
@@ -72,10 +73,10 @@
%% timer interface
-export([start_timer/1, timeout/1, timeout/2, stop_timer/1]).
--export_type([address_family/0, hostent/0, hostname/0, ip4_address/0,
+-export_type([address_family/0, socket_protocol/0, hostent/0, hostname/0, ip4_address/0,
ip6_address/0, ip_address/0, port_number/0,
local_address/0, socket_address/0, returned_non_ip_address/0,
- socket_setopt/0, socket_getopt/0,
+ socket_setopt/0, socket_getopt/0, ancillary_data/0,
posix/0, socket/0, stat_option/0]).
%% imports
-import(lists, [append/1, duplicate/2, filter/2, foldl/3]).
@@ -104,7 +105,20 @@
{local, binary()} |
{unspec, <<>>} |
{undefined, any()}.
--type posix() :: exbadport | exbadseq | file:posix().
+-type posix() ::
+ 'eaddrinuse' | 'eaddrnotavail' | 'eafnosupport' | 'ealready' |
+ 'econnaborted' | 'econnrefused' | 'econnreset' |
+ 'edestaddrreq' |
+ 'ehostdown' | 'ehostunreach' |
+ 'einprogress' | 'eisconn' |
+ 'emsgsize' |
+ 'enetdown' | 'enetunreach' |
+ 'enopkg' | 'enoprotoopt' | 'enotconn' | 'enotty' | 'enotsock' |
+ 'eproto' | 'eprotonosupport' | 'eprototype' |
+ 'esocktnosupport' |
+ 'etimedout' |
+ 'ewouldblock' |
+ 'exbadport' | 'exbadseq' | file:posix().
-type socket() :: port().
-type socket_setopt() ::
@@ -149,9 +163,13 @@
'recv_cnt' | 'recv_max' | 'recv_avg' | 'recv_oct' | 'recv_dvi' |
'send_cnt' | 'send_max' | 'send_avg' | 'send_oct' | 'send_pend'.
+-type ancillary_data() ::
+ [ {'tos', byte()} | {'tclass', byte()} | {'ttl', byte()} ].
+
%%% ---------------------------------
--spec get_rc() -> [{Par :: any(), Val :: any()}].
+-spec get_rc() -> [{Par :: atom(), Val :: any()} |
+ {Par :: atom(), Val1 :: any(), Val2 :: any()}].
get_rc() ->
inet_db:get_rc().
@@ -287,7 +305,7 @@ setopts(Socket, Opts) ->
{'ok', OptionValues} | {'error', posix()} when
Socket :: socket(),
Options :: [socket_getopt()],
- OptionValues :: [socket_setopt()].
+ OptionValues :: [socket_setopt() | gen_tcp:pktoptions_value()].
getopts(Socket, Opts) ->
case prim_inet:getopts(Socket, Opts) of
@@ -674,6 +692,14 @@ parse_address(Addr) ->
parse_strict_address(Addr) ->
inet_parse:strict_address(Addr).
+-spec ipv4_mapped_ipv6_address(ip_address()) -> ip_address().
+ipv4_mapped_ipv6_address({D1,D2,D3,D4})
+ when (D1 bor D2 bor D3 bor D4) < 256 ->
+ {0,0,0,0,0,16#ffff,(D1 bsl 8) bor D2,(D3 bsl 8) bor D4};
+ipv4_mapped_ipv6_address({D1,D2,D3,D4,D5,D6,D7,D8})
+ when (D1 bor D2 bor D3 bor D4 bor D5 bor D6 bor D7 bor D8) < 65536 ->
+ {D7 bsr 8,D7 band 255,D8 bsr 8,D8 band 255}.
+
%% Return a list of available options
options() ->
[
@@ -699,6 +725,7 @@ stats() ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
connect_options() ->
[tos, tclass, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay,
+ recvtos, recvtclass, ttl, recvttl,
header, active, packet, packet_size, buffer, mode, deliver, line_delimiter,
exit_on_close, high_watermark, low_watermark, high_msgq_watermark,
low_msgq_watermark, send_timeout, send_timeout_close, delay_send, raw,
@@ -767,6 +794,7 @@ con_add(Name, Val, #connect_opts{} = R, Opts, AllOpts) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
listen_options() ->
[tos, tclass, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay,
+ recvtos, recvtclass, ttl, recvttl,
header, active, packet, buffer, mode, deliver, backlog, ipv6_v6only,
exit_on_close, high_watermark, low_watermark, high_msgq_watermark,
low_msgq_watermark, send_timeout, send_timeout_close, delay_send,
@@ -847,7 +875,7 @@ tcp_module_1(Opts, Address) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
udp_options() ->
[tos, tclass, priority, reuseaddr, sndbuf, recbuf, header, active, buffer, mode,
- deliver, ipv6_v6only,
+ recvtos, recvtclass, ttl, recvttl, deliver, ipv6_v6only,
broadcast, dontroute, multicast_if, multicast_ttl, multicast_loop,
add_membership, drop_membership, read_packets,raw,
high_msgq_watermark, low_msgq_watermark, bind_to_device].
@@ -917,8 +945,10 @@ udp_module(Opts) ->
% (*) passing of open FDs ("fdopen") is not supported.
sctp_options() ->
[ % The following are generic inet options supported for SCTP sockets:
- mode, active, buffer, tos, tclass, priority, dontroute, reuseaddr, linger, sndbuf,
- recbuf, ipv6_v6only, high_msgq_watermark, low_msgq_watermark,
+ mode, active, buffer, tos, tclass, ttl,
+ priority, dontroute, reuseaddr, linger,
+ recvtos, recvtclass, recvttl,
+ sndbuf, recbuf, ipv6_v6only, high_msgq_watermark, low_msgq_watermark,
bind_to_device,
% Other options are SCTP-specific (though they may be similar to their
@@ -1243,9 +1273,7 @@ gethostbyname_string(Name, Type)
inet ->
inet_parse:ipv4_address(Name);
inet6 ->
- %% XXX should we really translate IPv4 addresses here
- %% even if we do not know if this host can do IPv6?
- inet_parse:ipv6_address(Name)
+ inet_parse:ipv6strict_address(Name)
end of
{ok,IP} ->
{ok,make_hostent(Name, [IP], [], Type)};
@@ -1451,11 +1479,14 @@ fdopen(Fd, Addr, Port, Opts, Protocol, Family, Type, Module) ->
%% socket stat
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec i() -> ok.
i() -> i(tcp), i(udp), i(sctp).
+-spec i(socket_protocol()) -> ok.
i(Proto) -> i(Proto, [port, module, recv, sent, owner,
local_address, foreign_address, state, type]).
+-spec i(socket_protocol(), [atom()]) -> ok.
i(tcp, Fs) ->
ii(tcp_sockets(), Fs, tcp);
i(udp, Fs) ->
diff --git a/lib/kernel/src/inet6_tcp.erl b/lib/kernel/src/inet6_tcp.erl
index a0d5d3df70..347b8b9a1b 100644
--- a/lib/kernel/src/inet6_tcp.erl
+++ b/lib/kernel/src/inet6_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -167,7 +167,7 @@ listen(Port, Opts) ->
%% Accept
%%
accept(L) ->
- case prim_inet:accept(L) of
+ case prim_inet:accept(L, accept_family_opts()) of
{ok, S} ->
inet_db:register_socket(S, ?MODULE),
{ok,S};
@@ -175,13 +175,15 @@ accept(L) ->
end.
accept(L, Timeout) ->
- case prim_inet:accept(L, Timeout) of
+ case prim_inet:accept(L, Timeout, accept_family_opts()) of
{ok, S} ->
inet_db:register_socket(S, ?MODULE),
{ok,S};
Error -> Error
end.
+accept_family_opts() -> [tclass, recvtclass].
+
%%
%% Create a port/socket from a file descriptor
%%
diff --git a/lib/kernel/src/inet_config.erl b/lib/kernel/src/inet_config.erl
index 4bbc520449..9f76360b8b 100644
--- a/lib/kernel/src/inet_config.erl
+++ b/lib/kernel/src/inet_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -369,7 +369,7 @@ win32_load1(Reg,Type,HFileKey) ->
end.
win32_split_line(Line,nt) -> inet_parse:split_line(Line);
-win32_split_line(Line,windows) -> string:tokens(Line, ",").
+win32_split_line(Line,windows) -> string:lexemes(Line, ",").
win32_get_strings(Reg, Names) ->
win32_get_strings(Reg, Names, []).
diff --git a/lib/kernel/src/inet_dns.erl b/lib/kernel/src/inet_dns.erl
index d5f982cc51..f1f58bc872 100644
--- a/lib/kernel/src/inet_dns.erl
+++ b/lib/kernel/src/inet_dns.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,7 @@
-export([decode/1, encode/1]).
--import(lists, [reverse/1, reverse/2, nthtail/2]).
+-import(lists, [reverse/1]).
-include("inet_int.hrl").
-include("inet_dns.hrl").
@@ -473,7 +473,7 @@ decode_data(<<Order:16,Preference:16,Data0/binary>>, _, ?S_NAPTR, Buffer) ->
{Data2,Services} = decode_string(Data1),
{Data,Regexp} = decode_characters(Data2, utf8),
Replacement = decode_domain(Data, Buffer),
- {Order,Preference,string:to_lower(Flags),string:to_lower(Services),
+ {Order,Preference,string:lowercase(Flags),string:lowercase(Services),
Regexp,Replacement};
%% ?S_OPT falls through to default
decode_data(Data, _, ?S_TXT, _) ->
diff --git a/lib/kernel/src/inet_hosts.erl b/lib/kernel/src/inet_hosts.erl
index 0bdf00ac30..fc653bf0d3 100644
--- a/lib/kernel/src/inet_hosts.erl
+++ b/lib/kernel/src/inet_hosts.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -72,9 +72,6 @@ gethostbyname(Name, Type, Byname, Byaddr) ->
gethostbyaddr({A,B,C,D}=IP) when ?ip(A,B,C,D) ->
gethostbyaddr(IP, inet);
-%% ipv4 only ipv6 address
-gethostbyaddr({0,0,0,0,0,16#ffff=F,G,H}) when ?ip6(0,0,0,0,0,F,G,H) ->
- gethostbyaddr({G bsr 8, G band 255, H bsr 8, H band 255});
gethostbyaddr({A,B,C,D,E,F,G,H}=IP) when ?ip6(A,B,C,D,E,F,G,H) ->
gethostbyaddr(IP, inet6);
gethostbyaddr(Addr) when is_list(Addr) ->
diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl
index bc5b67f7bf..c8e09d18ad 100644
--- a/lib/kernel/src/inet_int.hrl
+++ b/lib/kernel/src/inet_int.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -100,6 +100,8 @@
-define(TCP_REQ_RECV, 42).
-define(TCP_REQ_UNRECV, 43).
-define(TCP_REQ_SHUTDOWN, 44).
+-define(TCP_REQ_SENDFILE, 45).
+
%% UDP and SCTP requests
-define(PACKET_REQ_RECV, 60).
%%-define(SCTP_REQ_LISTEN, 61). MERGED
@@ -155,6 +157,11 @@
-define(INET_LOPT_LINE_DELIM, 40).
-define(INET_OPT_TCLASS, 41).
-define(INET_OPT_BIND_TO_DEVICE, 42).
+-define(INET_OPT_RECVTOS, 43).
+-define(INET_OPT_RECVTCLASS, 44).
+-define(INET_OPT_PKTOPTIONS, 45).
+-define(INET_OPT_TTL, 46).
+-define(INET_OPT_RECVTTL, 47).
% Specific SCTP options: separate range:
-define(SCTP_OPT_RTOINFO, 100).
-define(SCTP_OPT_ASSOCINFO, 101).
@@ -319,6 +326,12 @@
[((X) bsr 24) band 16#ff, ((X) bsr 16) band 16#ff,
((X) bsr 8) band 16#ff, (X) band 16#ff]).
+-define(int64(X),
+ [((X) bsr 56) band 16#ff, ((X) bsr 48) band 16#ff,
+ ((X) bsr 40) band 16#ff, ((X) bsr 32) band 16#ff,
+ ((X) bsr 24) band 16#ff, ((X) bsr 16) band 16#ff,
+ ((X) bsr 8) band 16#ff, (X) band 16#ff]).
+
-define(intAID(X), % For SCTP AssocID
?int32(X)).
diff --git a/lib/kernel/src/inet_parse.erl b/lib/kernel/src/inet_parse.erl
index 29804dc50b..e9685c6554 100644
--- a/lib/kernel/src/inet_parse.erl
+++ b/lib/kernel/src/inet_parse.erl
@@ -95,7 +95,7 @@ hosts(Fname,File) ->
%% interface with a %if suffix. These kind of
%% addresses maybe need to be gracefully handled
%% throughout inet* and inet_drv.
- case string:tokens(Address, "%") of
+ case string:lexemes(Address, "%") of
[Addr,_] ->
{ok,_} = address(Addr),
skip;
@@ -407,7 +407,7 @@ is_dom1([C | Cs]) when C >= $a, C =< $z -> is_dom_ldh(Cs);
is_dom1([C | Cs]) when C >= $A, C =< $Z -> is_dom_ldh(Cs);
is_dom1([C | Cs]) when C >= $0, C =< $9 ->
case is_dom_ldh(Cs) of
- true -> is_dom2(string:tokens([C | Cs],"."));
+ true -> is_dom2(string:lexemes([C | Cs],"."));
false -> false
end;
is_dom1(_) -> false.
diff --git a/lib/kernel/src/inet_res.erl b/lib/kernel/src/inet_res.erl
index 90e49ddfdf..6454802b04 100644
--- a/lib/kernel/src/inet_res.erl
+++ b/lib/kernel/src/inet_res.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -349,9 +349,6 @@ gethostbyaddr_tm({A,B,C,D} = IP, Timer) when ?ip(A,B,C,D) ->
{ok, HEnt} -> {ok, HEnt};
_ -> res_gethostbyaddr(dn_in_addr_arpa(A,B,C,D), IP, Timer)
end;
-%% ipv4 only ipv6 address
-gethostbyaddr_tm({0,0,0,0,0,16#ffff,G,H},Timer) when is_integer(G+H) ->
- gethostbyaddr_tm({G div 256, G rem 256, H div 256, H rem 256},Timer);
gethostbyaddr_tm({A,B,C,D,E,F,G,H} = IP, Timer) when ?ip6(A,B,C,D,E,F,G,H) ->
inet_db:res_update_conf(),
case inet_db:gethostbyaddr(IP) of
@@ -431,28 +428,7 @@ gethostbyname(Name,Family,Timeout) ->
gethostbyname_tm(Name,inet,Timer) ->
getbyname_tm(Name,?S_A,Timer);
gethostbyname_tm(Name,inet6,Timer) ->
- case getbyname_tm(Name,?S_AAAA,Timer) of
- {ok,HEnt} -> {ok,HEnt};
- {error,nxdomain} ->
- case getbyname_tm(Name, ?S_A,Timer) of
- {ok, HEnt} ->
- %% rewrite to a ipv4 only ipv6 address
- {ok,
- HEnt#hostent {
- h_addrtype = inet6,
- h_length = 16,
- h_addr_list =
- lists:map(
- fun({A,B,C,D}) ->
- {0,0,0,0,0,16#ffff,A*256+B,C*256+D}
- end, HEnt#hostent.h_addr_list)
- }};
- Error ->
- Error
- end;
- Error ->
- Error
- end;
+ getbyname_tm(Name,?S_AAAA,Timer);
gethostbyname_tm(_Name, _Family, _Timer) ->
{error, einval}.
@@ -859,15 +835,17 @@ query_ns(S0, Id, Buffer, IP, Port, Timer, Retry, I,
{ok,S} ->
Timeout =
inet:timeout( (Tm * (1 bsl I)) div Retry, Timer),
- {S,
case query_udp(
S, Id, Buffer, IP, Port, Timeout, Verbose) of
{ok,#dns_rec{header=H}} when H#dns_header.tc ->
TcpTimeout = inet:timeout(Tm*5, Timer),
- query_tcp(
- TcpTimeout, Id, Buffer, IP, Port, Verbose);
- Reply -> Reply
- end};
+ {S, query_tcp(
+ TcpTimeout, Id, Buffer, IP, Port, Verbose)};
+ {error, econnrefused} = Err ->
+ ok = udp_close(S),
+ {#sock{}, Err};
+ Reply -> {S, Reply}
+ end;
Error ->
{S0,Error}
end
diff --git a/lib/kernel/src/inet_tcp.erl b/lib/kernel/src/inet_tcp.erl
index dac6b3119d..f1e3116856 100644
--- a/lib/kernel/src/inet_tcp.erl
+++ b/lib/kernel/src/inet_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -164,7 +164,7 @@ listen(Port, Opts) ->
%% Accept
%%
accept(L) ->
- case prim_inet:accept(L) of
+ case prim_inet:accept(L, accept_family_opts()) of
{ok, S} ->
inet_db:register_socket(S, ?MODULE),
{ok,S};
@@ -172,13 +172,15 @@ accept(L) ->
end.
accept(L, Timeout) ->
- case prim_inet:accept(L, Timeout) of
+ case prim_inet:accept(L, Timeout, accept_family_opts()) of
{ok, S} ->
inet_db:register_socket(S, ?MODULE),
{ok,S};
Error -> Error
end.
+accept_family_opts() -> [tos, ttl, recvtos, recvttl].
+
%%
%% Create a port/socket from a file descriptor
%%
diff --git a/lib/kernel/src/inet_tcp_dist.erl b/lib/kernel/src/inet_tcp_dist.erl
index e3fdb1bb22..d1701afdaa 100644
--- a/lib/kernel/src/inet_tcp_dist.erl
+++ b/lib/kernel/src/inet_tcp_dist.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -283,73 +283,22 @@ do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
?trace("~p~n",[{inet_tcp_dist,self(),setup,Node}]),
[Name, Address] = splitnode(Driver, Node, LongOrShortNames),
AddressFamily = Driver:family(),
- case inet:getaddr(Address, AddressFamily) of
+ ErlEpmd = net_kernel:epmd_module(),
+ {ARMod, ARFun} = get_address_resolver(ErlEpmd),
+ Timer = dist_util:start_timer(SetupTime),
+ case ARMod:ARFun(Name, Address, AddressFamily) of
+ {ok, Ip, TcpPort, Version} ->
+ ?trace("address_please(~p) -> version ~p~n",
+ [Node,Version]),
+ do_setup_connect(Driver, Kernel, Node, Address, AddressFamily,
+ Ip, TcpPort, Version, Type, MyNode, Timer);
{ok, Ip} ->
- Timer = dist_util:start_timer(SetupTime),
- ErlEpmd = net_kernel:epmd_module(),
case ErlEpmd:port_please(Name, Ip) of
{port, TcpPort, Version} ->
?trace("port_please(~p) -> version ~p~n",
[Node,Version]),
- dist_util:reset_timer(Timer),
- case
- Driver:connect(
- Ip, TcpPort,
- connect_options([{active, false}, {packet, 2}]))
- of
- {ok, Socket} ->
- HSData = #hs_data{
- kernel_pid = Kernel,
- other_node = Node,
- this_node = MyNode,
- socket = Socket,
- timer = Timer,
- this_flags = 0,
- other_version = Version,
- f_send = fun Driver:send/2,
- f_recv = fun Driver:recv/3,
- f_setopts_pre_nodeup =
- fun(S) ->
- inet:setopts
- (S,
- [{active, false},
- {packet, 4},
- nodelay()])
- end,
- f_setopts_post_nodeup =
- fun(S) ->
- inet:setopts
- (S,
- [{active, true},
- {deliver, port},
- {packet, 4},
- nodelay()])
- end,
-
- f_getll = fun inet:getll/1,
- f_address =
- fun(_,_) ->
- #net_address{
- address = {Ip,TcpPort},
- host = Address,
- protocol = tcp,
- family = AddressFamily}
- end,
- mf_tick = fun(S) -> ?MODULE:tick(Driver, S) end,
- mf_getstat = fun ?MODULE:getstat/1,
- request_type = Type,
- mf_setopts = fun ?MODULE:setopts/2,
- mf_getopts = fun ?MODULE:getopts/2
- },
- dist_util:handshake_we_started(HSData);
- _ ->
- %% Other Node may have closed since
- %% port_please !
- ?trace("other node (~p) "
- "closed since port_please.~n",
- [Node]),
- ?shutdown(Node)
- end;
+ do_setup_connect(Driver, Kernel, Node, Address, AddressFamily,
+ Ip, TcpPort, Version, Type, MyNode, Timer);
_ ->
?trace("port_please (~p) "
"failed.~n", [Node]),
@@ -361,6 +310,71 @@ do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
?shutdown(Node)
end.
+%%
+%% Actual setup of connection
+%%
+do_setup_connect(Driver, Kernel, Node, Address, AddressFamily,
+ Ip, TcpPort, Version, Type, MyNode, Timer) ->
+ dist_util:reset_timer(Timer),
+ case
+ Driver:connect(
+ Ip, TcpPort,
+ connect_options([{active, false}, {packet, 2}]))
+ of
+ {ok, Socket} ->
+ HSData = #hs_data{
+ kernel_pid = Kernel,
+ other_node = Node,
+ this_node = MyNode,
+ socket = Socket,
+ timer = Timer,
+ this_flags = 0,
+ other_version = Version,
+ f_send = fun Driver:send/2,
+ f_recv = fun Driver:recv/3,
+ f_setopts_pre_nodeup =
+ fun(S) ->
+ inet:setopts
+ (S,
+ [{active, false},
+ {packet, 4},
+ nodelay()])
+ end,
+ f_setopts_post_nodeup =
+ fun(S) ->
+ inet:setopts
+ (S,
+ [{active, true},
+ {deliver, port},
+ {packet, 4},
+ nodelay()])
+ end,
+
+ f_getll = fun inet:getll/1,
+ f_address =
+ fun(_,_) ->
+ #net_address{
+ address = {Ip,TcpPort},
+ host = Address,
+ protocol = tcp,
+ family = AddressFamily}
+ end,
+ mf_tick = fun(S) -> ?MODULE:tick(Driver, S) end,
+ mf_getstat = fun ?MODULE:getstat/1,
+ request_type = Type,
+ mf_setopts = fun ?MODULE:setopts/2,
+ mf_getopts = fun ?MODULE:getopts/2
+ },
+ dist_util:handshake_we_started(HSData);
+ _ ->
+ %% Other Node may have closed since
+ %% discovery !
+ ?trace("other node (~p) "
+ "closed since discovery (port_please).~n",
+ [Node]),
+ ?shutdown(Node)
+ end.
+
connect_options(Opts) ->
case application:get_env(kernel, inet_dist_connect_options) of
{ok,ConnectOpts} ->
@@ -430,6 +444,16 @@ get_tcp_address(Driver, Socket) ->
}.
%% ------------------------------------------------------------
+%% Determine if EPMD module supports address resolving. Default
+%% is to use inet:getaddr/2.
+%% ------------------------------------------------------------
+get_address_resolver(EpmdModule) ->
+ case erlang:function_exported(EpmdModule, address_please, 3) of
+ true -> {EpmdModule, address_please};
+ _ -> {inet, getaddr}
+ end.
+
+%% ------------------------------------------------------------
%% Do only accept new connection attempts from nodes at our
%% own LAN, if the check_ip environment parameter is true.
%% ------------------------------------------------------------
diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src
index e150938487..fe073621c8 100644
--- a/lib/kernel/src/kernel.app.src
+++ b/lib/kernel/src/kernel.app.src
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -57,8 +57,21 @@
inet_tcp_dist,
kernel,
kernel_config,
+ kernel_refc,
local_tcp,
local_udp,
+ logger,
+ logger_backend,
+ logger_config,
+ logger_disk_log_h,
+ logger_filters,
+ logger_formatter,
+ logger_h_common,
+ logger_handler_watcher,
+ logger_server,
+ logger_simple_h,
+ logger_std_h,
+ logger_sup,
net,
net_adm,
net_kernel,
@@ -88,6 +101,13 @@
inet_udp,
inet_sctp,
pg2,
+ raw_file_io,
+ raw_file_io_compressed,
+ raw_file_io_deflate,
+ raw_file_io_delayed,
+ raw_file_io_inflate,
+ raw_file_io_list,
+ raw_file_io_raw,
seq_trace,
standard_error,
wrap_log_reader]},
@@ -107,7 +127,11 @@
heart,
init,
kernel_config,
+ kernel_refc,
kernel_sup,
+ logger,
+ logger_handler_watcher,
+ logger_sup,
net_kernel,
net_sup,
rex,
@@ -118,8 +142,10 @@
inet_db,
pg2]},
{applications, []},
- {env, [{error_logger, tty}]},
+ {env, [{logger_level, notice},
+ {logger_sasl_compatible, false}
+ ]},
{mod, {kernel, []}},
- {runtime_dependencies, ["erts-9.0", "stdlib-3.0", "sasl-3.0"]}
+ {runtime_dependencies, ["erts-10.1", "stdlib-3.5", "sasl-3.0"]}
]
}.
diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src
index 77085b2064..0c0435e051 100644
--- a/lib/kernel/src/kernel.appup.src
+++ b/lib/kernel/src/kernel.appup.src
@@ -18,7 +18,13 @@
%% %CopyrightEnd%
{"%VSN%",
%% Up from - max one major revision back
- [{<<"5\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-19.*
+ [{<<"5\\.3(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.0
+ {<<"5\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.1+
+ {<<"6\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-21.0
+ {<<"6\\.1(\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-21.1
%% Down to - max one major revision back
- [{<<"5\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-19.*
+ [{<<"5\\.3(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.0
+ {<<"5\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.1+
+ {<<"6\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-21.0
+ {<<"6\\.1(\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-21.1
}.
diff --git a/lib/kernel/src/kernel.erl b/lib/kernel/src/kernel.erl
index cba57088ec..c68d04e279 100644
--- a/lib/kernel/src/kernel.erl
+++ b/lib/kernel/src/kernel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,24 +30,13 @@
%%% Callback functions for the kernel application.
%%%-----------------------------------------------------------------
start(_, []) ->
+ %% Setup the logger and configure the kernel logger environment
+ ok = logger:internal_init_logger(),
case supervisor:start_link({local, kernel_sup}, kernel, []) of
{ok, Pid} ->
- %% add signal handler
- case whereis(erl_signal_server) of
- %% in case of minimal mode
- undefined -> ok;
- _ ->
- ok = gen_event:add_handler(erl_signal_server, erl_signal_handler, [])
- end,
- %% add error handler
- Type = get_error_logger_type(),
- case error_logger:swap_handler(Type) of
- ok -> {ok, Pid, []};
- Error ->
- %% Not necessary since the node will crash anyway:
- exit(Pid, shutdown),
- Error
- end;
+ ok = erl_signal_handler:start(),
+ ok = logger:add_handlers(kernel),
+ {ok, Pid, []};
Error -> Error
end.
@@ -62,16 +51,6 @@ config_change(Changed, New, Removed) ->
do_global_groups_change(Changed, New, Removed),
ok.
-get_error_logger_type() ->
- case application:get_env(kernel, error_logger) of
- {ok, tty} -> tty;
- {ok, {file, File}} when is_list(File) -> {logfile, File};
- {ok, false} -> false;
- {ok, silent} -> silent;
- undefined -> tty; % default value
- {ok, Bad} -> exit({bad_config, {kernel, {error_logger, Bad}}})
- end.
-
%%%-----------------------------------------------------------------
%%% The process structure in kernel is as shown in the figure.
%%%
@@ -111,6 +90,13 @@ init([]) ->
type => worker,
modules => [kernel_config]},
+ RefC = #{id => kernel_refc,
+ start => {kernel_refc, start_link, []},
+ restart => permanent,
+ shutdown => 2000,
+ type => worker,
+ modules => [kernel_refc]},
+
Code = #{id => code_server,
start => {code, start_link, []},
restart => permanent,
@@ -146,9 +132,18 @@ init([]) ->
type => supervisor,
modules => [?MODULE]},
+
+ LoggerSup = #{id => logger_sup,
+ start => {logger_sup, start_link, []},
+ restart => permanent,
+ shutdown => infinity,
+ type => supervisor,
+ modules => [logger_sup]},
+
case init:get_argument(mode) of
{ok, [["minimal"]]} ->
- {ok, {SupFlags, [Code, File, StdError, User, Config, SafeSup]}};
+ {ok, {SupFlags,
+ [Code, File, StdError, User, LoggerSup, Config, RefC, SafeSup]}};
_ ->
Rpc = #{id => rex,
start => {rpc, start_link, []},
@@ -199,7 +194,7 @@ init([]) ->
{ok, {SupFlags,
[Code, Rpc, Global, InetDb | DistAC] ++
[NetSup, GlGroup, File, SigSrv,
- StdError, User, Config, SafeSup] ++ Timer}}
+ StdError, User, Config, RefC, SafeSup, LoggerSup] ++ Timer}}
end;
init(safe) ->
SupFlags = #{strategy => one_for_one,
diff --git a/lib/kernel/src/kernel_config.erl b/lib/kernel/src/kernel_config.erl
index 535083ef27..691a266c2d 100644
--- a/lib/kernel/src/kernel_config.erl
+++ b/lib/kernel/src/kernel_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,11 +30,8 @@
%%%-----------------------------------------------------------------
%%% This module implements a process that configures the kernel
%%% application.
-%%% Its purpose is that in the init phase add an error_logger
-%%% and when it dies (when the kernel application dies) deleting the
-%%% previously installed error_logger.
-%%% Also, this process waits for other nodes at startup, if
-%%% specified.
+%%% Its purpose is that in the init phase waits for other nodes at startup,
+%%% if specified.
%%%-----------------------------------------------------------------
start_link() -> gen_server:start_link(kernel_config, [], []).
diff --git a/lib/kernel/src/kernel_refc.erl b/lib/kernel/src/kernel_refc.erl
new file mode 100644
index 0000000000..8e04ff99d8
--- /dev/null
+++ b/lib/kernel/src/kernel_refc.erl
@@ -0,0 +1,139 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(kernel_refc).
+
+-behaviour(gen_server).
+
+%% External exports
+-export([start_link/0, scheduler_wall_time/1]).
+%% Internal exports
+-export([init/1, handle_info/2, terminate/2]).
+-export([handle_call/3, handle_cast/2, code_change/3]).
+
+%%%-----------------------------------------------------------------
+%%% This module implements a process that handles reference counters for
+%%% various erts or other kernel resources which needs reference counting.
+%%%
+%%% Should not be documented nor used directly by user applications.
+%%%-----------------------------------------------------------------
+start_link() ->
+ gen_server:start_link({local,kernel_refc}, kernel_refc, [], []).
+
+-spec scheduler_wall_time(boolean()) -> boolean().
+scheduler_wall_time(Bool) ->
+ gen_server:call(kernel_refc, {scheduler_wall_time, self(), Bool}, infinity).
+
+%%-----------------------------------------------------------------
+%% Callback functions from gen_server
+%%-----------------------------------------------------------------
+
+-spec init([]) -> {'ok', map()}.
+
+init([]) ->
+ resource(scheduler_wall_time, false),
+ {ok, #{scheduler_wall_time=>#{}}}.
+
+-spec handle_call(term(), term(), State) -> {'reply', term(), State}.
+handle_call({What, Who, false}, _From, State) ->
+ {Reply, Cnt} = do_stop(What, maps:get(What, State), Who),
+ {reply, Reply, State#{What:=Cnt}};
+handle_call({What, Who, true}, _From, State) ->
+ {Reply, Cnt} = do_start(What, maps:get(What, State), Who),
+ {reply, Reply, State#{What:=Cnt}};
+handle_call(_, _From, State) ->
+ {reply, badarg, State}.
+
+-spec handle_cast(term(), State) -> {'noreply', State}.
+handle_cast(_, State) ->
+ {noreply, State}.
+
+-spec handle_info(term(), State) -> {'noreply', State}.
+handle_info({'DOWN', _Ref, process, Pid, _}, State) ->
+ Cleanup = fun(Resource, Cnts) ->
+ cleanup(Resource, Cnts, Pid)
+ end,
+ {noreply, maps:map(Cleanup, State)};
+handle_info(_, State) ->
+ {noreply, State}.
+
+-spec terminate(term(), term()) -> 'ok'.
+terminate(_Reason, _State) ->
+ ok.
+
+-spec code_change(term(), State, term()) -> {'ok', State}.
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%-----------------------------------------------------------------
+%% Internal functions
+%%-----------------------------------------------------------------
+
+do_start(Resource, Cnt, Pid) ->
+ case maps:get(Pid, Cnt, undefined) of
+ undefined ->
+ Ref = erlang:monitor(process, Pid),
+ case any(Cnt) of
+ true ->
+ {true, Cnt#{Pid=>{1, Ref}}};
+ false ->
+ resource(Resource, true),
+ {false, Cnt#{Pid=>{1, Ref}}}
+ end;
+ {N, Ref} ->
+ {true, Cnt#{Pid=>{N+1, Ref}}}
+ end.
+
+do_stop(Resource, Cnt0, Pid) ->
+ case maps:get(Pid, Cnt0, undefined) of
+ undefined ->
+ {any(Cnt0), Cnt0};
+ {1, Ref} ->
+ erlang:demonitor(Ref, [flush]),
+ Cnt = maps:remove(Pid, Cnt0),
+ case any(Cnt) of
+ true ->
+ {true, Cnt};
+ false ->
+ resource(Resource, false),
+ {true, Cnt}
+ end;
+ {N, Ref} ->
+ {true, Cnt0#{Pid=>{N-1, Ref}}}
+ end.
+
+cleanup(Resource, Cnt0, Pid) ->
+ case maps:is_key(Pid, Cnt0) of
+ true ->
+ Cnt = maps:remove(Pid, Cnt0),
+ case any(Cnt) of
+ true ->
+ Cnt;
+ false ->
+ resource(Resource, false),
+ Cnt
+ end;
+ false ->
+ Cnt0
+ end.
+
+any(Cnt) -> maps:size(Cnt) > 0.
+
+resource(scheduler_wall_time, Enable) ->
+ _ = erts_internal:scheduler_wall_time(Enable).
diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl
new file mode 100644
index 0000000000..752dd8d493
--- /dev/null
+++ b/lib/kernel/src/logger.erl
@@ -0,0 +1,917 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger).
+
+%% Log interface
+-export([emergency/1,emergency/2,emergency/3,
+ alert/1,alert/2,alert/3,
+ critical/1,critical/2,critical/3,
+ error/1,error/2,error/3,
+ warning/1,warning/2,warning/3,
+ notice/1,notice/2,notice/3,
+ info/1,info/2,info/3,
+ debug/1,debug/2,debug/3]).
+-export([log/2,log/3,log/4]).
+
+%% Called by macro
+-export([allow/2,macro_log/3,macro_log/4,macro_log/5,add_default_metadata/1]).
+
+%% Configuration
+-export([add_handler/3, remove_handler/1,
+ add_primary_filter/2, add_handler_filter/3,
+ remove_primary_filter/1, remove_handler_filter/2,
+ set_module_level/2,
+ unset_module_level/1, unset_module_level/0,
+ set_application_level/2, unset_application_level/1,
+ get_module_level/0, get_module_level/1,
+ set_primary_config/1, set_primary_config/2,
+ set_handler_config/2, set_handler_config/3,
+ update_primary_config/1, update_handler_config/2,
+ update_formatter_config/2, update_formatter_config/3,
+ get_primary_config/0, get_handler_config/1,
+ get_handler_config/0, get_handler_ids/0, get_config/0,
+ add_handlers/1]).
+
+%% Private configuration
+-export([internal_init_logger/0]).
+
+%% Misc
+-export([compare_levels/2]).
+-export([set_process_metadata/1, update_process_metadata/1,
+ unset_process_metadata/0, get_process_metadata/0]).
+
+%% Basic report formatting
+-export([format_report/1, format_otp_report/1]).
+
+-export([internal_log/2,filter_stacktrace/2]).
+
+-include("logger_internal.hrl").
+-include("logger.hrl").
+
+%%%-----------------------------------------------------------------
+%%% Types
+-type log_event() :: #{level:=level(),
+ msg:={io:format(),[term()]} |
+ {report,report()} |
+ {string,unicode:chardata()},
+ meta:=metadata()}.
+-type level() :: emergency | alert | critical | error |
+ warning | notice | info | debug.
+-type report() :: map() | [{atom(),term()}].
+-type report_cb() :: fun((report()) -> {io:format(),[term()]}) |
+ fun((report(),report_cb_config()) -> unicode:chardata()).
+-type report_cb_config() :: #{depth := pos_integer() | unlimited,
+ chars_limit := pos_integer() | unlimited,
+ single_line := boolean()}.
+-type msg_fun() :: fun((term()) -> {io:format(),[term()]} |
+ report() |
+ unicode:chardata()).
+-type metadata() :: #{pid => pid(),
+ gl => pid(),
+ time => timestamp(),
+ mfa => {module(),atom(),non_neg_integer()},
+ file => file:filename(),
+ line => non_neg_integer(),
+ domain => [atom()],
+ report_cb => report_cb(),
+ atom() => term()}.
+-type location() :: #{mfa := {module(),atom(),non_neg_integer()},
+ file := file:filename(),
+ line := non_neg_integer()}.
+-type handler_id() :: atom().
+-type filter_id() :: atom().
+-type filter() :: {fun((log_event(),filter_arg()) ->
+ filter_return()),filter_arg()}.
+-type filter_arg() :: term().
+-type filter_return() :: stop | ignore | log_event().
+-type primary_config() :: #{level => level() | all | none,
+ filter_default => log | stop,
+ filters => [{filter_id(),filter()}]}.
+-type handler_config() :: #{id => handler_id(),
+ config => term(),
+ level => level() | all | none,
+ module => module(),
+ filter_default => log | stop,
+ filters => [{filter_id(),filter()}],
+ formatter => {module(),formatter_config()}}.
+-type timestamp() :: integer().
+-type formatter_config() :: #{atom() => term()}.
+
+-type config_handler() :: {handler, handler_id(), module(), handler_config()}.
+
+-type config_logger() :: [{handler,default,undefined} |
+ config_handler() |
+ {filters,log | stop,[{filter_id(),filter()}]} |
+ {module_level,level(),[module()]}].
+
+-export_type([log_event/0,
+ level/0,
+ report/0,
+ report_cb/0,
+ report_cb_config/0,
+ msg_fun/0,
+ metadata/0,
+ primary_config/0,
+ handler_config/0,
+ handler_id/0,
+ filter_id/0,
+ filter/0,
+ filter_arg/0,
+ filter_return/0,
+ config_handler/0,
+ formatter_config/0]).
+
+%%%-----------------------------------------------------------------
+%%% API
+emergency(X) ->
+ log(emergency,X).
+emergency(X,Y) ->
+ log(emergency,X,Y).
+emergency(X,Y,Z) ->
+ log(emergency,X,Y,Z).
+
+alert(X) ->
+ log(alert,X).
+alert(X,Y) ->
+ log(alert,X,Y).
+alert(X,Y,Z) ->
+ log(alert,X,Y,Z).
+
+critical(X) ->
+ log(critical,X).
+critical(X,Y) ->
+ log(critical,X,Y).
+critical(X,Y,Z) ->
+ log(critical,X,Y,Z).
+
+error(X) ->
+ log(error,X).
+error(X,Y) ->
+ log(error,X,Y).
+error(X,Y,Z) ->
+ log(error,X,Y,Z).
+
+warning(X) ->
+ log(warning,X).
+warning(X,Y) ->
+ log(warning,X,Y).
+warning(X,Y,Z) ->
+ log(warning,X,Y,Z).
+
+notice(X) ->
+ log(notice,X).
+notice(X,Y) ->
+ log(notice,X,Y).
+notice(X,Y,Z) ->
+ log(notice,X,Y,Z).
+
+info(X) ->
+ log(info,X).
+info(X,Y) ->
+ log(info,X,Y).
+info(X,Y,Z) ->
+ log(info,X,Y,Z).
+
+debug(X) ->
+ log(debug,X).
+debug(X,Y) ->
+ log(debug,X,Y).
+debug(X,Y,Z) ->
+ log(debug,X,Y,Z).
+
+-spec log(Level,StringOrReport) -> ok when
+ Level :: level(),
+ StringOrReport :: unicode:chardata() | report().
+log(Level, StringOrReport) ->
+ do_log(Level,StringOrReport,#{}).
+
+-spec log(Level,StringOrReport,Metadata) -> ok when
+ Level :: level(),
+ StringOrReport :: unicode:chardata() | report(),
+ Metadata :: metadata();
+ (Level,Format,Args) -> ok when
+ Level :: level(),
+ Format :: io:format(),
+ Args ::[term()];
+ (Level,Fun,FunArgs) -> ok when
+ Level :: level(),
+ Fun :: msg_fun(),
+ FunArgs :: term().
+log(Level, StringOrReport, Metadata)
+ when is_map(Metadata), not is_function(StringOrReport) ->
+ do_log(Level,StringOrReport,Metadata);
+log(Level, FunOrFormat, Args) ->
+ do_log(Level,{FunOrFormat,Args},#{}).
+
+-spec log(Level,Format, Args, Metadata) -> ok when
+ Level :: level(),
+ Format :: io:format(),
+ Args :: [term()],
+ Metadata :: metadata();
+ (Level,Fun,FunArgs,Metadata) -> ok when
+ Level :: level(),
+ Fun :: msg_fun(),
+ FunArgs :: term(),
+ Metadata :: metadata().
+log(Level, FunOrFormat, Args, Metadata) ->
+ do_log(Level,{FunOrFormat,Args},Metadata).
+
+-spec allow(Level,Module) -> boolean() when
+ Level :: level(),
+ Module :: module().
+allow(Level,Module) when ?IS_LEVEL(Level), is_atom(Module) ->
+ logger_config:allow(?LOGGER_TABLE,Level,Module).
+
+
+-spec macro_log(Location,Level,StringOrReport) -> ok when
+ Location :: location(),
+ Level :: level(),
+ StringOrReport :: unicode:chardata() | report().
+macro_log(Location,Level,StringOrReport) ->
+ log_allowed(Location,Level,StringOrReport,#{}).
+
+-spec macro_log(Location,Level,StringOrReport,Meta) -> ok when
+ Location :: location(),
+ Level :: level(),
+ StringOrReport :: unicode:chardata() | report(),
+ Meta :: metadata();
+ (Location,Level,Format,Args) -> ok when
+ Location :: location(),
+ Level :: level(),
+ Format :: io:format(),
+ Args ::[term()];
+ (Location,Level,Fun,FunArgs) -> ok when
+ Location :: location(),
+ Level :: level(),
+ Fun :: msg_fun(),
+ FunArgs :: term().
+macro_log(Location,Level,StringOrReport,Meta)
+ when is_map(Meta), not is_function(StringOrReport) ->
+ log_allowed(Location,Level,StringOrReport,Meta);
+macro_log(Location,Level,FunOrFormat,Args) ->
+ log_allowed(Location,Level,{FunOrFormat,Args},#{}).
+
+-spec macro_log(Location,Level,Format,Args,Meta) -> ok when
+ Location :: location(),
+ Level :: level(),
+ Format :: io:format(),
+ Args ::[term()],
+ Meta :: metadata();
+ (Location,Level,Fun,FunArgs,Meta) -> ok when
+ Location :: location(),
+ Level :: level(),
+ Fun :: msg_fun(),
+ FunArgs :: term(),
+ Meta :: metadata().
+macro_log(Location,Level,FunOrFormat,Args,Meta) ->
+ log_allowed(Location,Level,{FunOrFormat,Args},Meta).
+
+-spec format_otp_report(Report) -> FormatArgs when
+ Report :: report(),
+ FormatArgs :: {io:format(),[term()]}.
+format_otp_report(#{label:=_,report:=Report}) ->
+ format_report(Report);
+format_otp_report(Report) ->
+ format_report(Report).
+
+-spec format_report(Report) -> FormatArgs when
+ Report :: report(),
+ FormatArgs :: {io:format(),[term()]}.
+format_report(Report) when is_map(Report) ->
+ format_report(maps:to_list(Report));
+format_report(Report) when is_list(Report) ->
+ case lists:flatten(Report) of
+ [] ->
+ {"~tp",[[]]};
+ FlatList ->
+ case string_p1(FlatList) of
+ true ->
+ {"~ts",[FlatList]};
+ false ->
+ format_term_list(Report,[],[])
+ end
+ end;
+format_report(Report) ->
+ {"~tp",[Report]}.
+
+format_term_list([{Tag,Data}|T],Format,Args) ->
+ PorS = case string_p(Data) of
+ true -> "s";
+ false -> "p"
+ end,
+ format_term_list(T,[" ~tp: ~t"++PorS|Format],[Data,Tag|Args]);
+format_term_list([Data|T],Format,Args) ->
+ format_term_list(T,[" ~tp"|Format],[Data|Args]);
+format_term_list([],Format,Args) ->
+ {lists:flatten(lists:join($\n,lists:reverse(Format))),lists:reverse(Args)}.
+
+string_p(List) when is_list(List) ->
+ string_p1(lists:flatten(List));
+string_p(_) ->
+ false.
+
+string_p1([]) ->
+ false;
+string_p1(FlatList) ->
+ io_lib:printable_unicode_list(FlatList).
+
+internal_log(Level,Term) when is_atom(Level) ->
+ erlang:display_string("Logger - "++ atom_to_list(Level) ++ ": "),
+ erlang:display(Term).
+
+%%%-----------------------------------------------------------------
+%%% Configuration
+-spec add_primary_filter(FilterId,Filter) -> ok | {error,term()} when
+ FilterId :: filter_id(),
+ Filter :: filter().
+add_primary_filter(FilterId,Filter) ->
+ logger_server:add_filter(primary,{FilterId,Filter}).
+
+-spec add_handler_filter(HandlerId,FilterId,Filter) -> ok | {error,term()} when
+ HandlerId :: handler_id(),
+ FilterId :: filter_id(),
+ Filter :: filter().
+add_handler_filter(HandlerId,FilterId,Filter) ->
+ logger_server:add_filter(HandlerId,{FilterId,Filter}).
+
+
+-spec remove_primary_filter(FilterId) -> ok | {error,term()} when
+ FilterId :: filter_id().
+remove_primary_filter(FilterId) ->
+ logger_server:remove_filter(primary,FilterId).
+
+-spec remove_handler_filter(HandlerId,FilterId) -> ok | {error,term()} when
+ HandlerId :: handler_id(),
+ FilterId :: filter_id().
+remove_handler_filter(HandlerId,FilterId) ->
+ logger_server:remove_filter(HandlerId,FilterId).
+
+-spec add_handler(HandlerId,Module,Config) -> ok | {error,term()} when
+ HandlerId :: handler_id(),
+ Module :: module(),
+ Config :: handler_config().
+add_handler(HandlerId,Module,Config) ->
+ logger_server:add_handler(HandlerId,Module,Config).
+
+-spec remove_handler(HandlerId) -> ok | {error,term()} when
+ HandlerId :: handler_id().
+remove_handler(HandlerId) ->
+ logger_server:remove_handler(HandlerId).
+
+-spec set_primary_config(level,Level) -> ok | {error,term()} when
+ Level :: level() | all | none;
+ (filter_default,FilterDefault) -> ok | {error,term()} when
+ FilterDefault :: log | stop;
+ (filters,Filters) -> ok | {error,term()} when
+ Filters :: [{filter_id(),filter()}].
+set_primary_config(Key,Value) ->
+ logger_server:set_config(primary,Key,Value).
+
+-spec set_primary_config(Config) -> ok | {error,term()} when
+ Config :: primary_config().
+set_primary_config(Config) ->
+ logger_server:set_config(primary,Config).
+
+-spec set_handler_config(HandlerId,level,Level) -> Return when
+ HandlerId :: handler_id(),
+ Level :: level() | all | none,
+ Return :: ok | {error,term()};
+ (HandlerId,filter_default,FilterDefault) -> Return when
+ HandlerId :: handler_id(),
+ FilterDefault :: log | stop,
+ Return :: ok | {error,term()};
+ (HandlerId,filters,Filters) -> Return when
+ HandlerId :: handler_id(),
+ Filters :: [{filter_id(),filter()}],
+ Return :: ok | {error,term()};
+ (HandlerId,formatter,Formatter) -> Return when
+ HandlerId :: handler_id(),
+ Formatter :: {module(), formatter_config()},
+ Return :: ok | {error,term()};
+ (HandlerId,config,Config) -> Return when
+ HandlerId :: handler_id(),
+ Config :: term(),
+ Return :: ok | {error,term()}.
+set_handler_config(HandlerId,Key,Value) ->
+ logger_server:set_config(HandlerId,Key,Value).
+
+-spec set_handler_config(HandlerId,Config) -> ok | {error,term()} when
+ HandlerId :: handler_id(),
+ Config :: handler_config().
+set_handler_config(HandlerId,Config) ->
+ logger_server:set_config(HandlerId,Config).
+
+-spec update_primary_config(Config) -> ok | {error,term()} when
+ Config :: primary_config().
+update_primary_config(Config) ->
+ logger_server:update_config(primary,Config).
+
+-spec update_handler_config(HandlerId,Config) -> ok | {error,term()} when
+ HandlerId :: handler_id(),
+ Config :: handler_config().
+update_handler_config(HandlerId,Config) ->
+ logger_server:update_config(HandlerId,Config).
+
+-spec get_primary_config() -> Config when
+ Config :: primary_config().
+get_primary_config() ->
+ {ok,Config} = logger_config:get(?LOGGER_TABLE,primary),
+ maps:remove(handlers,Config).
+
+-spec get_handler_config(HandlerId) -> {ok,Config} | {error,term()} when
+ HandlerId :: handler_id(),
+ Config :: handler_config().
+get_handler_config(HandlerId) ->
+ logger_config:get(?LOGGER_TABLE,HandlerId).
+
+-spec get_handler_config() -> [Config] when
+ Config :: handler_config().
+get_handler_config() ->
+ [begin
+ {ok,Config} = get_handler_config(HandlerId),
+ Config
+ end || HandlerId <- get_handler_ids()].
+
+-spec get_handler_ids() -> [HandlerId] when
+ HandlerId :: handler_id().
+get_handler_ids() ->
+ {ok,#{handlers:=HandlerIds}} = logger_config:get(?LOGGER_TABLE,primary),
+ HandlerIds.
+
+-spec update_formatter_config(HandlerId,FormatterConfig) ->
+ ok | {error,term()} when
+ HandlerId :: handler_id(),
+ FormatterConfig :: formatter_config().
+update_formatter_config(HandlerId,FormatterConfig) ->
+ logger_server:update_formatter_config(HandlerId,FormatterConfig).
+
+-spec update_formatter_config(HandlerId,Key,Value) ->
+ ok | {error,term()} when
+ HandlerId :: handler_id(),
+ Key :: atom(),
+ Value :: term().
+update_formatter_config(HandlerId,Key,Value) ->
+ logger_server:update_formatter_config(HandlerId,#{Key=>Value}).
+
+-spec set_module_level(Modules,Level) -> ok | {error,term()} when
+ Modules :: [module()] | module(),
+ Level :: level() | all | none.
+set_module_level(Module,Level) when is_atom(Module) ->
+ set_module_level([Module],Level);
+set_module_level(Modules,Level) ->
+ logger_server:set_module_level(Modules,Level).
+
+-spec unset_module_level(Modules) -> ok when
+ Modules :: [module()] | module().
+unset_module_level(Module) when is_atom(Module) ->
+ unset_module_level([Module]);
+unset_module_level(Modules) ->
+ logger_server:unset_module_level(Modules).
+
+-spec unset_module_level() -> ok.
+unset_module_level() ->
+ logger_server:unset_module_level().
+
+-spec set_application_level(Application,Level) -> ok | {error, not_loaded} when
+ Application :: atom(),
+ Level :: level() | all | none.
+set_application_level(App,Level) ->
+ case application:get_key(App, modules) of
+ {ok, Modules} ->
+ set_module_level(Modules, Level);
+ undefined ->
+ {error, {not_loaded, App}}
+ end.
+
+-spec unset_application_level(Application) -> ok | {error, not_loaded} when
+ Application :: atom().
+unset_application_level(App) ->
+ case application:get_key(App, modules) of
+ {ok, Modules} ->
+ unset_module_level(Modules);
+ undefined ->
+ {error, {not_loaded, App}}
+ end.
+
+-spec get_module_level(Modules) -> [{Module,Level}] when
+ Modules :: [Module] | Module,
+ Module :: module(),
+ Level :: level() | all | none.
+get_module_level(Module) when is_atom(Module) ->
+ get_module_level([Module]);
+get_module_level(Modules) when is_list(Modules) ->
+ [{M,L} || {M,L} <- get_module_level(),
+ lists:member(M,Modules)].
+
+-spec get_module_level() -> [{Module,Level}] when
+ Module :: module(),
+ Level :: level() | all | none.
+get_module_level() ->
+ logger_config:get_module_level(?LOGGER_TABLE).
+
+%%%-----------------------------------------------------------------
+%%% Misc
+-spec compare_levels(Level1,Level2) -> eq | gt | lt when
+ Level1 :: level(),
+ Level2 :: level().
+compare_levels(Level,Level) when ?IS_LEVEL(Level) ->
+ eq;
+compare_levels(Level1,Level2) when ?IS_LEVEL(Level1), ?IS_LEVEL(Level2) ->
+ Int1 = logger_config:level_to_int(Level1),
+ Int2 = logger_config:level_to_int(Level2),
+ if Int1 < Int2 -> gt;
+ true -> lt
+ end;
+compare_levels(Level1,Level2) ->
+ erlang:error(badarg,[Level1,Level2]).
+
+-spec set_process_metadata(Meta) -> ok when
+ Meta :: metadata().
+set_process_metadata(Meta) when is_map(Meta) ->
+ _ = put(?LOGGER_META_KEY,Meta),
+ ok;
+set_process_metadata(Meta) ->
+ erlang:error(badarg,[Meta]).
+
+-spec update_process_metadata(Meta) -> ok when
+ Meta :: metadata().
+update_process_metadata(Meta) when is_map(Meta) ->
+ case get_process_metadata() of
+ undefined ->
+ set_process_metadata(Meta);
+ Meta0 when is_map(Meta0) ->
+ set_process_metadata(maps:merge(Meta0,Meta)),
+ ok
+ end;
+update_process_metadata(Meta) ->
+ erlang:error(badarg,[Meta]).
+
+-spec get_process_metadata() -> Meta | undefined when
+ Meta :: metadata().
+get_process_metadata() ->
+ get(?LOGGER_META_KEY).
+
+-spec unset_process_metadata() -> ok.
+unset_process_metadata() ->
+ _ = erase(?LOGGER_META_KEY),
+ ok.
+
+-spec get_config() -> #{primary=>primary_config(),
+ handlers=>[handler_config()],
+ module_levels=>[{module(),level() | all | none}]}.
+get_config() ->
+ #{primary=>get_primary_config(),
+ handlers=>get_handler_config(),
+ module_levels=>lists:keysort(1,get_module_level())}.
+
+-spec internal_init_logger() -> ok | {error,term()}.
+%% This function is responsible for config of the logger
+%% This is done before add_handlers because we want the
+%% logger settings to take effect before the kernel supervisor
+%% tree is started.
+internal_init_logger() ->
+ try
+ Env = get_logger_env(kernel),
+ check_logger_config(kernel,Env),
+ ok = logger:set_primary_config(level, get_logger_level()),
+ ok = logger:set_primary_config(filter_default,
+ get_primary_filter_default(Env)),
+
+ [case logger:add_primary_filter(Id, Filter) of
+ ok -> ok;
+ {error, Reason} -> throw(Reason)
+ end || {Id, Filter} <- get_primary_filters(Env)],
+
+ [case logger:set_module_level(Modules, Level) of
+ ok -> ok;
+ {error, Reason} -> throw(Reason)
+ end || {module_level, Level, Modules} <- Env],
+
+ case logger:set_handler_config(simple,filters,
+ get_default_handler_filters()) of
+ ok -> ok;
+ {error,{not_found,simple}} -> ok
+ end,
+
+ init_kernel_handlers(Env)
+ catch throw:Reason ->
+ ?LOG_ERROR("Invalid logger config: ~p", [Reason]),
+ {error, {bad_config, {kernel, Reason}}}
+ end.
+
+-spec init_kernel_handlers(config_logger()) -> ok | {error,term()}.
+%% Setup the kernel environment variables to be correct
+%% The actual handlers are started by a call to add_handlers.
+init_kernel_handlers(Env) ->
+ try
+ case get_logger_type(Env) of
+ {ok,silent} ->
+ ok = logger:remove_handler(simple);
+ {ok,false} ->
+ ok;
+ {ok,Type} ->
+ init_default_config(Type,Env)
+ end
+ catch throw:Reason ->
+ ?LOG_ERROR("Invalid default handler config: ~p", [Reason]),
+ {error, {bad_config, {kernel, Reason}}}
+ end.
+
+-spec add_handlers(Application) -> ok | {error,term()} when
+ Application :: atom();
+ (HandlerConfig) -> ok | {error,term()} when
+ HandlerConfig :: [config_handler()].
+%% This function is responsible for resolving the handler config
+%% and then starting the correct handlers. This is done after the
+%% kernel supervisor tree has been started as it needs the logger_sup.
+add_handlers(App) when is_atom(App) ->
+ add_handlers(App,get_logger_env(App));
+add_handlers(HandlerConfig) ->
+ add_handlers(application:get_application(),HandlerConfig).
+
+add_handlers(App,HandlerConfig) ->
+ try
+ check_logger_config(App,HandlerConfig),
+ DefaultAdded =
+ lists:foldl(
+ fun({handler, default = Id, Module, Config}, _)
+ when not is_map_key(filters, Config) ->
+ %% The default handler should have a couple of extra filters
+ %% set on it by default.
+ DefConfig = #{ filter_default => stop,
+ filters => get_default_handler_filters()},
+ setup_handler(Id, Module, maps:merge(DefConfig,Config)),
+ true;
+ ({handler, Id, Module, Config}, Default) ->
+ setup_handler(Id, Module, Config),
+ Default orelse Id == default;
+ (_,Default) -> Default
+ end, false, HandlerConfig),
+ %% If a default handler was added we try to remove the simple_logger
+ %% If the simple logger exists it will replay its log events
+ %% to the handler(s) added in the fold above.
+ [case logger:remove_handler(simple) of
+ ok -> ok;
+ {error,{not_found,simple}} -> ok
+ end || DefaultAdded],
+ ok
+ catch throw:Reason0 ->
+ Reason =
+ case App of
+ undefined -> Reason0;
+ _ -> {App,Reason0}
+ end,
+ ?LOG_ERROR("Invalid logger handler config: ~p", [Reason]),
+ {error, {bad_config, {handler, Reason}}}
+ end.
+
+setup_handler(Id, Module, Config) ->
+ case logger:add_handler(Id, Module, Config) of
+ ok -> ok;
+ {error, Reason} -> throw(Reason)
+ end.
+
+check_logger_config(_,[]) ->
+ ok;
+check_logger_config(App,[{handler,_,_,_}|Env]) ->
+ check_logger_config(App,Env);
+check_logger_config(kernel,[{handler,default,undefined}|Env]) ->
+ check_logger_config(kernel,Env);
+check_logger_config(kernel,[{filters,_,_}|Env]) ->
+ check_logger_config(kernel,Env);
+check_logger_config(kernel,[{module_level,_,_}|Env]) ->
+ check_logger_config(kernel,Env);
+check_logger_config(_,Bad) ->
+ throw(Bad).
+
+-spec get_logger_type(config_logger()) ->
+ {ok, standard_io | false | silent |
+ {file, file:name_all()} |
+ {file, file:name_all(), [file:mode()]}}.
+get_logger_type(Env) ->
+ case application:get_env(kernel, error_logger) of
+ {ok, tty} ->
+ {ok, standard_io};
+ {ok, {file, File}} when is_list(File) ->
+ {ok, {file, File}};
+ {ok, false} ->
+ {ok, false};
+ {ok, silent} ->
+ {ok, silent};
+ undefined ->
+ case lists:member({handler,default,undefined}, Env) of
+ true ->
+ {ok, false};
+ false ->
+ {ok, standard_io} % default value
+ end;
+ {ok, Bad} ->
+ throw({error_logger, Bad})
+ end.
+
+get_logger_level() ->
+ case application:get_env(kernel,logger_level,info) of
+ Level when ?IS_LEVEL(Level); Level=:=all; Level=:=none ->
+ Level;
+ Level ->
+ throw({logger_level, Level})
+ end.
+
+get_primary_filter_default(Env) ->
+ case lists:keyfind(filters,1,Env) of
+ {filters,Default,_} ->
+ Default;
+ false ->
+ log
+ end.
+
+get_primary_filters(Env) ->
+ case [F || F={filters,_,_} <- Env] of
+ [{filters,_,Filters}] ->
+ case lists:all(fun({_,_}) -> true; (_) -> false end,Filters) of
+ true -> Filters;
+ false -> throw({invalid_filters,Filters})
+ end;
+ [] -> [];
+ _ -> throw({multiple_filters,Env})
+ end.
+
+%% This function looks at the kernel logger environment
+%% and updates it so that the correct logger is configured
+init_default_config(Type,Env) when Type==standard_io;
+ Type==standard_error;
+ element(1,Type)==file ->
+ DefaultFormatter = #{formatter=>{?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}},
+ DefaultConfig = DefaultFormatter#{config=>#{type=>Type}},
+ NewLoggerEnv =
+ case lists:keyfind(default, 2, Env) of
+ {handler, default, logger_std_h, Config} ->
+ %% Only want to add the logger_std_h config
+ %% if not configured by user AND the default
+ %% handler is still the logger_std_h.
+ lists:keyreplace(default, 2, Env,
+ {handler, default, logger_std_h,
+ maps:merge(DefaultConfig,Config)});
+ {handler, default, Module,Config} ->
+ %% Add default formatter. The point of this
+ %% is to get the expected formatter config
+ %% for the default handler, since this
+ %% differs from the default values that
+ %% logger_formatter itself adds.
+ lists:keyreplace(default, 2, Env,
+ {handler, default, Module,
+ maps:merge(DefaultFormatter,Config)});
+ _ ->
+ %% Nothing has been configured, use default
+ [{handler, default, logger_std_h, DefaultConfig} | Env]
+ end,
+ application:set_env(kernel, logger, NewLoggerEnv, [{timeout,infinity}]).
+
+get_default_handler_filters() ->
+ case application:get_env(kernel, logger_sasl_compatible, false) of
+ true ->
+ ?DEFAULT_HANDLER_FILTERS([otp]);
+ false ->
+ ?DEFAULT_HANDLER_FILTERS([otp,sasl])
+ end.
+
+get_logger_env(App) ->
+ application:get_env(App, logger, []).
+
+%%%-----------------------------------------------------------------
+%%% Internal
+do_log(Level,Msg,#{mfa:={Module,_,_}}=Meta) ->
+ case logger_config:allow(?LOGGER_TABLE,Level,Module) of
+ true ->
+ log_allowed(#{},Level,Msg,Meta);
+ false ->
+ ok
+ end;
+do_log(Level,Msg,Meta) ->
+ case logger_config:allow(?LOGGER_TABLE,Level) of
+ true ->
+ log_allowed(#{},Level,Msg,Meta);
+ false ->
+ ok
+ end.
+
+-spec log_allowed(Location,Level,Msg,Meta) -> ok when
+ Location :: location() | #{},
+ Level :: level(),
+ Msg :: {msg_fun(),term()} |
+ {io:format(),[term()]} |
+ report() |
+ unicode:chardata(),
+ Meta :: metadata().
+log_allowed(Location,Level,{Fun,FunArgs},Meta) when is_function(Fun,1) ->
+ try Fun(FunArgs) of
+ Msg={Format,Args} when is_list(Format), is_list(Args) ->
+ log_allowed(Location,Level,Msg,Meta);
+ Report when ?IS_REPORT(Report) ->
+ log_allowed(Location,Level,Report,Meta);
+ String when ?IS_STRING(String) ->
+ log_allowed(Location,Level,String,Meta);
+ Other ->
+ log_allowed(Location,Level,
+ {"LAZY_FUN ERROR: ~tp; Returned: ~tp",
+ [{Fun,FunArgs},Other]},
+ Meta)
+ catch C:R ->
+ log_allowed(Location,Level,
+ {"LAZY_FUN CRASH: ~tp; Reason: ~tp",
+ [{Fun,FunArgs},{C,R}]},
+ Meta)
+ end;
+log_allowed(Location,Level,Msg,Meta0) when is_map(Meta0) ->
+ %% Metadata priorities are:
+ %% Location (added in API macros) - will be overwritten by process
+ %% metadata (set by set_process_metadata/1), which in turn will be
+ %% overwritten by the metadata given as argument in the log call
+ %% (function or macro).
+ Meta = add_default_metadata(
+ maps:merge(Location,maps:merge(proc_meta(),Meta0))),
+ case node(maps:get(gl,Meta)) of
+ Node when Node=/=node() ->
+ log_remote(Node,Level,Msg,Meta),
+ do_log_allowed(Level,Msg,Meta);
+ _ ->
+ do_log_allowed(Level,Msg,Meta)
+ end.
+
+do_log_allowed(Level,{Format,Args}=Msg,Meta)
+ when ?IS_LEVEL(Level),
+ is_list(Format),
+ is_list(Args),
+ is_map(Meta) ->
+ logger_backend:log_allowed(#{level=>Level,msg=>Msg,meta=>Meta},tid());
+do_log_allowed(Level,Report,Meta)
+ when ?IS_LEVEL(Level),
+ ?IS_REPORT(Report),
+ is_map(Meta) ->
+ logger_backend:log_allowed(#{level=>Level,msg=>{report,Report},meta=>Meta},
+ tid());
+do_log_allowed(Level,String,Meta)
+ when ?IS_LEVEL(Level),
+ ?IS_STRING(String),
+ is_map(Meta) ->
+ logger_backend:log_allowed(#{level=>Level,msg=>{string,String},meta=>Meta},
+ tid()).
+tid() ->
+ ets:whereis(?LOGGER_TABLE).
+
+log_remote(Node,Level,{Format,Args},Meta) ->
+ log_remote(Node,{log,Level,Format,Args,Meta});
+log_remote(Node,Level,Msg,Meta) ->
+ log_remote(Node,{log,Level,Msg,Meta}).
+
+log_remote(Node,Request) ->
+ {logger,Node} ! Request,
+ ok.
+
+add_default_metadata(Meta) ->
+ add_default_metadata([pid,gl,time],Meta).
+
+add_default_metadata([Key|Keys],Meta) ->
+ case maps:is_key(Key,Meta) of
+ true ->
+ add_default_metadata(Keys,Meta);
+ false ->
+ add_default_metadata(Keys,Meta#{Key=>default(Key)})
+ end;
+add_default_metadata([],Meta) ->
+ Meta.
+
+proc_meta() ->
+ case get_process_metadata() of
+ ProcMeta when is_map(ProcMeta) -> ProcMeta;
+ _ -> #{}
+ end.
+
+default(pid) -> self();
+default(gl) -> group_leader();
+default(time) -> erlang:system_time(microsecond).
+
+%% Remove everything upto and including this module from the stacktrace
+filter_stacktrace(Module,[{Module,_,_,_}|_]) ->
+ [];
+filter_stacktrace(Module,[H|T]) ->
+ [H|filter_stacktrace(Module,T)];
+filter_stacktrace(_,[]) ->
+ [].
diff --git a/lib/kernel/src/logger_backend.erl b/lib/kernel/src/logger_backend.erl
new file mode 100644
index 0000000000..432c671afd
--- /dev/null
+++ b/lib/kernel/src/logger_backend.erl
@@ -0,0 +1,133 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_backend).
+
+-export([log_allowed/2]).
+
+-include("logger_internal.hrl").
+
+-define(OWN_KEYS,[level,filters,filter_default,handlers]).
+
+%%%-----------------------------------------------------------------
+%%% The default logger backend
+log_allowed(Log, Tid) ->
+ {ok,Config} = logger_config:get(Tid,primary),
+ Filters = maps:get(filters,Config,[]),
+ case apply_filters(primary,Log,Filters,Config) of
+ stop ->
+ ok;
+ Log1 ->
+ Handlers = maps:get(handlers,Config,[]),
+ call_handlers(Log1,Handlers,Tid)
+ end,
+ ok.
+
+call_handlers(#{level:=Level}=Log,[Id|Handlers],Tid) ->
+ case logger_config:get(Tid,Id,Level) of
+ {ok,#{module:=Module}=Config} ->
+ Filters = maps:get(filters,Config,[]),
+ case apply_filters(Id,Log,Filters,Config) of
+ stop ->
+ ok;
+ Log1 ->
+ Config1 = maps:without(?OWN_KEYS,Config),
+ try Module:log(Log1,Config1)
+ catch C:R:S ->
+ case logger:remove_handler(Id) of
+ ok ->
+ logger:internal_log(
+ error,{removed_failing_handler,Id}),
+ ?LOG_INTERNAL(
+ debug,
+ [{logger,removed_failing_handler},
+ {handler,{Id,Module}},
+ {log_event,Log1},
+ {config,Config1},
+ {reason,{C,R,filter_stacktrace(S)}}]);
+ {error,{not_found,_}} ->
+ %% Probably already removed by other client
+ %% Don't report again
+ ok;
+ {error,Reason} ->
+ ?LOG_INTERNAL(
+ debug,
+ [{logger,remove_handler_failed},
+ {reason,Reason}])
+ end
+ end
+ end;
+ _ ->
+ ok
+ end,
+ call_handlers(Log,Handlers,Tid);
+call_handlers(_Log,[],_Tid) ->
+ ok.
+
+apply_filters(Owner,Log,Filters,Config) ->
+ case do_apply_filters(Owner,Log,Filters,ignore) of
+ stop ->
+ stop;
+ ignore ->
+ case maps:get(filter_default,Config) of
+ log ->
+ Log;
+ stop ->
+ stop
+ end;
+ Log1 ->
+ Log1
+ end.
+
+do_apply_filters(Owner,Log,[{_Id,{FilterFun,FilterArgs}}=Filter|Filters],State) ->
+ try FilterFun(Log,FilterArgs) of
+ stop ->
+ stop;
+ ignore ->
+ do_apply_filters(Owner,Log,Filters,State);
+ Log1=#{level:=Level,msg:=Msg,meta:=Meta}
+ when is_atom(Level), ?IS_MSG(Msg), is_map(Meta) ->
+ do_apply_filters(Owner,Log1,Filters,log);
+ Bad ->
+ handle_filter_failed(Filter,Owner,Log,{bad_return_value,Bad})
+ catch C:R:S ->
+ handle_filter_failed(Filter,Owner,Log,{C,R,filter_stacktrace(S)})
+ end;
+do_apply_filters(_Owner,_Log,[],ignore) ->
+ ignore;
+do_apply_filters(_Owner,Log,[],log) ->
+ Log.
+
+handle_filter_failed({Id,_}=Filter,Owner,Log,Reason) ->
+ case logger_server:remove_filter(Owner,Id) of
+ ok ->
+ logger:internal_log(error,{removed_failing_filter,Id}),
+ ?LOG_INTERNAL(debug,
+ [{logger,removed_failing_filter},
+ {filter,Filter},
+ {owner,Owner},
+ {log_event,Log},
+ {reason,Reason}]);
+ _ ->
+ ok
+ end,
+ ignore.
+
+filter_stacktrace(Stacktrace) ->
+ logger:filter_stacktrace(?MODULE,Stacktrace).
diff --git a/lib/kernel/src/logger_config.erl b/lib/kernel/src/logger_config.erl
new file mode 100644
index 0000000000..6bfe658552
--- /dev/null
+++ b/lib/kernel/src/logger_config.erl
@@ -0,0 +1,150 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_config).
+
+-export([new/1,delete/2,
+ exist/2,
+ allow/2,allow/3,
+ get/2, get/3,
+ create/3, set/3,
+ set_module_level/3,unset_module_level/2,
+ get_module_level/1,cache_module_level/2,
+ level_to_int/1]).
+
+-include("logger_internal.hrl").
+
+new(Name) ->
+ _ = ets:new(Name,[set,protected,named_table,{write_concurrency,true}]),
+ ets:whereis(Name).
+
+delete(Tid,Id) ->
+ ets:delete(Tid,table_key(Id)).
+
+allow(Tid,Level,Module) ->
+ LevelInt = level_to_int(Level),
+ case ets:lookup(Tid,Module) of
+ [{Module,{ModLevel,cached}}] when is_integer(ModLevel),
+ LevelInt =< ModLevel ->
+ true;
+ [{Module,ModLevel}] when is_integer(ModLevel),
+ LevelInt =< ModLevel ->
+ true;
+ [] ->
+ logger_server:cache_module_level(Module),
+ allow(Tid,Level);
+ _ ->
+ false
+ end.
+
+allow(Tid,Level) ->
+ GlobalLevelInt = ets:lookup_element(Tid,?PRIMARY_KEY,2),
+ level_to_int(Level) =< GlobalLevelInt.
+
+exist(Tid,What) ->
+ ets:member(Tid,table_key(What)).
+
+get(Tid,What) ->
+ case ets:lookup(Tid,table_key(What)) of
+ [{_,_,Config}] ->
+ {ok,Config};
+ [] ->
+ {error,{not_found,What}}
+ end.
+
+get(Tid,What,Level) ->
+ MS = [{{table_key(What),'$1','$2'},
+ [{'>=','$1',level_to_int(Level)}],
+ ['$2']}],
+ case ets:select(Tid,MS) of
+ [] -> error;
+ [Data] -> {ok,Data}
+ end.
+
+create(Tid,What,Config) ->
+ LevelInt = level_to_int(maps:get(level,Config)),
+ ets:insert(Tid,{table_key(What),LevelInt,Config}).
+
+set(Tid,What,Config) ->
+ LevelInt = level_to_int(maps:get(level,Config)),
+ %% Should do this only if the level has actually changed. Possibly
+ %% overwrite instead of delete?
+ case What of
+ primary ->
+ _ = ets:select_delete(Tid,[{{'_',{'$1',cached}},
+ [{'=/=','$1',LevelInt}],
+ [true]}]),
+ ok;
+ _ ->
+ ok
+ end,
+ ets:update_element(Tid,table_key(What),[{2,LevelInt},{3,Config}]),
+ ok.
+
+set_module_level(Tid,Modules,Level) ->
+ LevelInt = level_to_int(Level),
+ [ets:insert(Tid,{Module,LevelInt}) || Module <- Modules],
+ ok.
+
+%% should possibly overwrite instead of delete?
+unset_module_level(Tid,all) ->
+ MS = [{{'$1','$2'},[{is_atom,'$1'},{is_integer,'$2'}],[true]}],
+ _ = ets:select_delete(Tid,MS),
+ ok;
+unset_module_level(Tid,Modules) ->
+ [ets:delete(Tid,Module) || Module <- Modules],
+ ok.
+
+get_module_level(Tid) ->
+ MS = [{{'$1','$2'},[{is_atom,'$1'},{is_integer,'$2'}],[{{'$1','$2'}}]}],
+ Modules = ets:select(Tid,MS),
+ lists:sort([{M,int_to_level(L)} || {M,L} <- Modules]).
+
+cache_module_level(Tid,Module) ->
+ GlobalLevelInt = ets:lookup_element(Tid,?PRIMARY_KEY,2),
+ ets:insert_new(Tid,{Module,{GlobalLevelInt,cached}}),
+ ok.
+
+level_to_int(none) -> ?LOG_NONE;
+level_to_int(emergency) -> ?EMERGENCY;
+level_to_int(alert) -> ?ALERT;
+level_to_int(critical) -> ?CRITICAL;
+level_to_int(error) -> ?ERROR;
+level_to_int(warning) -> ?WARNING;
+level_to_int(notice) -> ?NOTICE;
+level_to_int(info) -> ?INFO;
+level_to_int(debug) -> ?DEBUG;
+level_to_int(all) -> ?LOG_ALL.
+
+int_to_level(?LOG_NONE) -> none;
+int_to_level(?EMERGENCY) -> emergency;
+int_to_level(?ALERT) -> alert;
+int_to_level(?CRITICAL) -> critical;
+int_to_level(?ERROR) -> error;
+int_to_level(?WARNING) -> warning;
+int_to_level(?NOTICE) -> notice;
+int_to_level(?INFO) -> info;
+int_to_level(?DEBUG) -> debug;
+int_to_level(?LOG_ALL) -> all.
+
+%%%-----------------------------------------------------------------
+%%% Internal
+
+table_key(primary) -> ?PRIMARY_KEY;
+table_key(HandlerId) -> {?HANDLER_KEY,HandlerId}.
diff --git a/lib/kernel/src/logger_disk_log_h.erl b/lib/kernel/src/logger_disk_log_h.erl
new file mode 100644
index 0000000000..a8f141f135
--- /dev/null
+++ b/lib/kernel/src/logger_disk_log_h.erl
@@ -0,0 +1,723 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_disk_log_h).
+
+-behaviour(gen_server).
+
+-include("logger.hrl").
+-include("logger_internal.hrl").
+-include("logger_h_common.hrl").
+
+%%% API
+-export([start_link/3, info/1, filesync/1, reset/1]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+%% logger callbacks
+-export([log/2, adding_handler/1, removing_handler/1, changing_config/2]).
+
+%% handler internal
+-export([log_handler_info/4]).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+%%%-----------------------------------------------------------------
+%%% Start a disk_log handler process and link to caller.
+%%% This function is called by the kernel supervisor when this
+%%% handler process gets added (as a result of calling add/3).
+-spec start_link(Name, Config, HandlerState) -> {ok,Pid} | {error,Reason} when
+ Name :: atom(),
+ Config :: logger:handler_config(),
+ HandlerState :: map(),
+ Pid :: pid(),
+ Reason :: term().
+
+start_link(Name, Config, HandlerState) ->
+ proc_lib:start_link(?MODULE,init,[[Name,Config,HandlerState]]).
+
+%%%-----------------------------------------------------------------
+%%%
+-spec filesync(Name) -> ok | {error,Reason} when
+ Name :: atom(),
+ Reason :: handler_busy | {badarg,term()}.
+
+filesync(Name) when is_atom(Name) ->
+ try
+ gen_server:call(?name_to_reg_name(?MODULE,Name),
+ disk_log_sync, ?DEFAULT_CALL_TIMEOUT)
+ catch
+ _:{timeout,_} -> {error,handler_busy}
+ end;
+filesync(Name) ->
+ {error,{badarg,{filesync,[Name]}}}.
+
+%%%-----------------------------------------------------------------
+%%%
+-spec info(Name) -> Info | {error,Reason} when
+ Name :: atom(),
+ Info :: term(),
+ Reason :: handler_busy | {badarg,term()}.
+
+info(Name) when is_atom(Name) ->
+ try
+ gen_server:call(?name_to_reg_name(?MODULE,Name),
+ info, ?DEFAULT_CALL_TIMEOUT)
+ catch
+ _:{timeout,_} -> {error,handler_busy}
+ end;
+info(Name) ->
+ {error,{badarg,{info,[Name]}}}.
+
+%%%-----------------------------------------------------------------
+%%%
+-spec reset(Name) -> ok | {error,Reason} when
+ Name :: atom(),
+ Reason :: handler_busy | {badarg,term()}.
+
+reset(Name) when is_atom(Name) ->
+ try
+ gen_server:call(?name_to_reg_name(?MODULE,Name),
+ reset, ?DEFAULT_CALL_TIMEOUT)
+ catch
+ _:{timeout,_} -> {error,handler_busy}
+ end;
+reset(Name) ->
+ {error,{badarg,{reset,[Name]}}}.
+
+
+%%%===================================================================
+%%% logger callbacks
+%%%===================================================================
+
+%%%-----------------------------------------------------------------
+%%% Handler being added
+adding_handler(#{id:=Name}=Config) ->
+ case check_config(adding, Config) of
+ {ok, Config1} ->
+ %% create initial handler state by merging defaults with config
+ HConfig = maps:get(config, Config1, #{}),
+ HState = maps:merge(get_init_state(), HConfig),
+ case logger_h_common:overload_levels_ok(HState) of
+ true ->
+ start(Name, Config1, HState);
+ false ->
+ #{sync_mode_qlen := SMQL,
+ drop_mode_qlen := DMQL,
+ flush_qlen := FQL} = HState,
+ {error,{invalid_levels,{SMQL,DMQL,FQL}}}
+ end;
+ Error ->
+ Error
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Updating handler config
+changing_config(OldConfig = #{id:=Name, config:=OldHConfig},
+ NewConfig = #{id:=Name, config:=NewHConfig}) ->
+ #{type:=Type, file:=File, max_no_files:=MaxFs,
+ max_no_bytes:=MaxBytes} = OldHConfig,
+ case NewHConfig of
+ #{type:=Type, file:=File, max_no_files:=MaxFs,
+ max_no_bytes:=MaxBytes} ->
+ changing_config1(OldConfig, NewConfig);
+ _ ->
+ {error,{illegal_config_change,OldConfig,NewConfig}}
+ end;
+changing_config(OldConfig, NewConfig) ->
+ {error,{illegal_config_change,OldConfig,NewConfig}}.
+
+changing_config1(OldConfig=#{config:=OldHConfig}, NewConfig) ->
+ case check_config(changing, NewConfig) of
+ {ok,NewConfig1 = #{config:=NewHConfig}} ->
+ #{handler_pid:=HPid,
+ mode_tab:=ModeTab} = OldHConfig,
+ NewHConfig1 = NewHConfig#{handler_pid=>HPid,
+ mode_tab=>ModeTab},
+ NewConfig2 = NewConfig1#{config=>NewHConfig1},
+ try gen_server:call(HPid, {change_config,OldConfig,NewConfig2},
+ ?DEFAULT_CALL_TIMEOUT) of
+ ok -> {ok,NewConfig2};
+ HError -> HError
+ catch
+ _:{timeout,_} -> {error,handler_busy}
+ end;
+ Error ->
+ Error
+ end.
+
+check_config(adding, #{id:=Name}=Config) ->
+ %% merge handler specific config data
+ HConfig = merge_default_logopts(Name, maps:get(config, Config, #{})),
+ case check_h_config(maps:to_list(HConfig)) of
+ ok ->
+ {ok,Config#{config=>HConfig}};
+ Error ->
+ Error
+ end;
+check_config(changing, Config) ->
+ HConfig = maps:get(config, Config, #{}),
+ case check_h_config(maps:to_list(HConfig)) of
+ ok -> {ok,Config};
+ Error -> Error
+ end.
+
+merge_default_logopts(Name, HConfig) ->
+ Type = maps:get(type, HConfig, wrap),
+ {DefaultNoFiles,DefaultNoBytes} =
+ case Type of
+ halt -> {undefined,infinity};
+ _wrap -> {10,1048576}
+ end,
+ {ok,Dir} = file:get_cwd(),
+ Defaults = #{file => filename:join(Dir,Name),
+ max_no_files => DefaultNoFiles,
+ max_no_bytes => DefaultNoBytes,
+ type => Type},
+ maps:merge(Defaults, HConfig).
+
+check_h_config([{file,File}|Config]) when is_list(File) ->
+ check_h_config(Config);
+check_h_config([{max_no_files,undefined}|Config]) ->
+ check_h_config(Config);
+check_h_config([{max_no_files,N}|Config]) when is_integer(N), N>0 ->
+ check_h_config(Config);
+check_h_config([{max_no_bytes,infinity}|Config]) ->
+ check_h_config(Config);
+check_h_config([{max_no_bytes,N}|Config]) when is_integer(N), N>0 ->
+ check_h_config(Config);
+check_h_config([{type,Type}|Config]) when Type==wrap; Type==halt ->
+ check_h_config(Config);
+check_h_config([Other | Config]) ->
+ case logger_h_common:check_common_config(Other) of
+ valid ->
+ check_h_config(Config);
+ invalid ->
+ {error,{invalid_config,?MODULE,Other}}
+ end;
+check_h_config([]) ->
+ ok.
+
+%%%-----------------------------------------------------------------
+%%% Handler being removed
+removing_handler(#{id:=Name}) ->
+ stop(Name).
+
+%%%-----------------------------------------------------------------
+%%% Log a string or report
+-spec log(LogEvent, Config) -> ok when
+ LogEvent :: logger:log_event(),
+ Config :: logger:handler_config().
+
+log(LogEvent, Config = #{id := Name,
+ config := #{handler_pid := HPid,
+ mode_tab := ModeTab}}) ->
+ %% if the handler has crashed, we must drop this event
+ %% and hope the handler restarts so we can try again
+ true = is_process_alive(HPid),
+ Bin = logger_h_common:log_to_binary(LogEvent, Config),
+ logger_h_common:call_cast_or_drop(Name, HPid, ModeTab, Bin).
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+init([Name,
+ Config = #{config := HConfig = #{file:=File,
+ type:=Type,
+ max_no_bytes:=MNB,
+ max_no_files:=MNF}},
+ State = #{dl_sync_int := DLSyncInt}]) ->
+
+ RegName = ?name_to_reg_name(?MODULE,Name),
+ register(RegName, self()),
+ process_flag(trap_exit, true),
+ process_flag(message_queue_data, off_heap),
+
+ ?init_test_hooks(),
+ ?start_observation(Name),
+
+ LogOpts = #{file=>File, type=>Type, max_no_bytes=>MNB, max_no_files=>MNF},
+ case open_disk_log(Name, File, Type, MNB, MNF) of
+ ok ->
+ try ets:new(Name, [public]) of
+ ModeTab ->
+ ?set_mode(ModeTab, async),
+ T0 = ?timestamp(),
+ State1 =
+ ?merge_with_stats(State#{
+ id => Name,
+ mode_tab => ModeTab,
+ mode => async,
+ dl_sync => DLSyncInt,
+ log_opts => LogOpts,
+ last_qlen => 0,
+ last_log_ts => T0,
+ burst_win_ts => T0,
+ burst_msg_count => 0,
+ last_op => sync,
+ prev_log_result => ok,
+ prev_sync_result => ok,
+ prev_disk_log_info => undefined}),
+ Config1 =
+ Config#{config => HConfig#{handler_pid => self(),
+ mode_tab => ModeTab}},
+ proc_lib:init_ack({ok,self(),Config1}),
+ gen_server:cast(self(), repeated_disk_log_sync),
+ case logger_h_common:unset_restart_flag(Name, ?MODULE) of
+ true ->
+ %% inform about restart
+ gen_server:cast(self(), {log_handler_info,
+ "Handler ~p restarted",
+ [Name]});
+ false ->
+ %% initial start
+ ok
+ end,
+ gen_server:enter_loop(?MODULE, [], State1)
+ catch
+ _:Error ->
+ unregister(RegName),
+ logger_h_common:error_notify({open_disk_log,Name,Error}),
+ proc_lib:init_ack(Error)
+ end;
+ Error ->
+ unregister(RegName),
+ logger_h_common:error_notify({open_disk_log,Name,Error}),
+ proc_lib:init_ack(Error)
+ end.
+
+%% This is the synchronous log event.
+handle_call({log, Bin}, _From, State) ->
+ {Result,State1} = do_log(Bin, call, State),
+ %% Result == ok | dropped
+ {reply, Result, State1};
+
+handle_call(disk_log_sync, _From, State = #{id := Name}) ->
+ State1 = #{prev_sync_result := Result} = disk_log_sync(Name, State),
+ {reply, Result, State1};
+
+handle_call({change_config,_OldConfig,NewConfig}, _From,
+ State = #{filesync_repeat_interval := FSyncInt0}) ->
+ HConfig = maps:get(config, NewConfig, #{}),
+ State1 = #{sync_mode_qlen := SMQL,
+ drop_mode_qlen := DMQL,
+ flush_qlen := FQL} = maps:merge(State, HConfig),
+ case logger_h_common:overload_levels_ok(State1) of
+ true ->
+ _ =
+ case maps:get(filesync_repeat_interval, HConfig, undefined) of
+ undefined ->
+ ok;
+ no_repeat ->
+ _ = logger_h_common:cancel_timer(maps:get(rep_sync_tref,
+ State,
+ undefined));
+ FSyncInt0 ->
+ ok;
+ _FSyncInt1 ->
+ _ = logger_h_common:cancel_timer(maps:get(rep_sync_tref,
+ State,
+ undefined)),
+ _ = gen_server:cast(self(), repeated_disk_log_sync)
+ end,
+ {reply, ok, State1};
+ false ->
+ {reply, {error,{invalid_levels,{SMQL,DMQL,FQL}}}, State}
+ end;
+
+handle_call(info, _From, State) ->
+ {reply, State, State};
+
+handle_call(reset, _From, State) ->
+ State1 = ?merge_with_stats(State),
+ {reply, ok, State1#{last_qlen => 0,
+ last_log_ts => ?timestamp(),
+ prev_log_result => ok,
+ prev_sync_result => ok,
+ prev_disk_log_info => undefined}};
+
+handle_call(stop, _From, State) ->
+ {stop, {shutdown,stopped}, ok, State}.
+
+
+%% This is the asynchronous log event.
+handle_cast({log, Bin}, State) ->
+ {_,State1} = do_log(Bin, cast, State),
+ {noreply, State1};
+
+handle_cast({log_handler_info, Format, Args}, State = #{id:=Name}) ->
+ log_handler_info(Name, Format, Args, State),
+ {noreply, State};
+
+%% If FILESYNC_REPEAT_INTERVAL is set to a millisec value, this
+%% clause gets called repeatedly by the handler. In order to
+%% guarantee that a filesync *always* happens after the last log
+%% event, the repeat operation must be active!
+handle_cast(repeated_disk_log_sync,
+ State = #{id := Name,
+ filesync_repeat_interval := FSyncInt,
+ last_op := LastOp}) ->
+ State1 =
+ if is_integer(FSyncInt) ->
+ %% only do filesync if something has been
+ %% written since last time we checked
+ NewState = if LastOp == sync ->
+ State;
+ true ->
+ disk_log_sync(Name, State)
+ end,
+ {ok,TRef} =
+ timer:apply_after(FSyncInt, gen_server,cast,
+ [self(),repeated_disk_log_sync]),
+ NewState#{rep_sync_tref => TRef, last_op => sync};
+ true ->
+ State
+ end,
+ {noreply,State1}.
+
+%% The disk log owner must handle status messages from disk_log.
+handle_info({disk_log, _Node, _Log, {wrap,_NoLostItems}}, State) ->
+ {noreply, State};
+handle_info({disk_log, _Node, Log, Info = {truncated,_NoLostItems}},
+ State = #{id := Name, prev_disk_log_info := PrevInfo}) ->
+ error_notify_new(Info, PrevInfo, {disk_log,Name,Log,Info}),
+ {noreply, State#{prev_disk_log_info => Info}};
+handle_info({disk_log, _Node, Log, Info = {blocked_log,_Items}},
+ State = #{id := Name, prev_disk_log_info := PrevInfo}) ->
+ error_notify_new(Info, PrevInfo, {disk_log,Name,Log,Info}),
+ {noreply, State#{prev_disk_log_info => Info}};
+handle_info({disk_log, _Node, Log, full},
+ State = #{id := Name, prev_disk_log_info := PrevInfo}) ->
+ error_notify_new(full, PrevInfo, {disk_log,Name,Log,full}),
+ {noreply, State#{prev_disk_log_info => full}};
+handle_info({disk_log, _Node, Log, Info = {error_status,_Status}},
+ State = #{id := Name, prev_disk_log_info := PrevInfo}) ->
+ error_notify_new(Info, PrevInfo, {disk_log,Name,Log,Info}),
+ {noreply, State#{prev_disk_log_info => Info}};
+
+handle_info({'EXIT',_Pid,_Why}, State = #{id := _Name}) ->
+ {noreply, State};
+
+handle_info(_, State) ->
+ {noreply, State}.
+
+terminate(Reason, State = #{id := Name}) ->
+ _ = logger_h_common:cancel_timer(maps:get(rep_sync_tref, State,
+ undefined)),
+ _ = close_disk_log(Name, normal),
+ ok = logger_h_common:stop_or_restart(Name, Reason, State),
+ unregister(?name_to_reg_name(?MODULE, Name)),
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%%-----------------------------------------------------------------
+%%% Internal functions
+
+%%%-----------------------------------------------------------------
+%%%
+get_init_state() ->
+ #{sync_mode_qlen => ?SYNC_MODE_QLEN,
+ drop_mode_qlen => ?DROP_MODE_QLEN,
+ flush_qlen => ?FLUSH_QLEN,
+ burst_limit_enable => ?BURST_LIMIT_ENABLE,
+ burst_limit_max_count => ?BURST_LIMIT_MAX_COUNT,
+ burst_limit_window_time => ?BURST_LIMIT_WINDOW_TIME,
+ overload_kill_enable => ?OVERLOAD_KILL_ENABLE,
+ overload_kill_qlen => ?OVERLOAD_KILL_QLEN,
+ overload_kill_mem_size => ?OVERLOAD_KILL_MEM_SIZE,
+ overload_kill_restart_after => ?OVERLOAD_KILL_RESTART_AFTER,
+ dl_sync_int => ?CONTROLLER_SYNC_INTERVAL,
+ filesync_ok_qlen => ?FILESYNC_OK_QLEN,
+ filesync_repeat_interval => ?FILESYNC_REPEAT_INTERVAL}.
+
+%%%-----------------------------------------------------------------
+%%% Add a disk_log handler to the logger.
+%%% This starts a dedicated handler process which should always
+%%% exist if the handler is registered with logger (and should not
+%%% exist if the handler is not registered).
+%%%
+%%% Config is the logger:handler_config() map. Handler specific parameters
+%%% should be provided with a sub map associated with a key named
+%%% 'config', e.g:
+%%%
+%%% Config = #{config => #{sync_mode_qlen => 50}
+%%%
+%%% The 'config' sub map will also contain parameters for configuring
+%%% the disk_log:
+%%%
+%%% Config = #{config => #{file => file:filename(),
+%%% max_no_bytes => integer(),
+%%% max_no_files => integer(),
+%%% type => wrap | halt}}.
+%%%
+%%% If type == halt, then max_no_files is ignored.
+%%%
+%%% The disk_log handler process is linked to logger_sup, which is
+%%% part of the kernel application's supervision tree.
+start(Name, Config, HandlerState) ->
+ LoggerDLH =
+ #{id => Name,
+ start => {?MODULE, start_link, [Name,Config,HandlerState]},
+ restart => temporary,
+ shutdown => 2000,
+ type => worker,
+ modules => [?MODULE]},
+ case supervisor:start_child(logger_sup, LoggerDLH) of
+ {ok,Pid,Config1} ->
+ ok = logger_handler_watcher:register_handler(Name,Pid),
+ {ok,Config1};
+ Error ->
+ Error
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Stop and remove the handler.
+stop(Name) ->
+ case whereis(?name_to_reg_name(?MODULE,Name)) of
+ undefined ->
+ ok;
+ Pid ->
+ %% We don't want to do supervisor:terminate_child here
+ %% since we need to distinguish this explicit stop from a
+ %% system termination in order to avoid circular attempts
+ %% at removing the handler (implying deadlocks and
+ %% timeouts).
+ %% And we don't need to do supervisor:delete_child, since
+ %% the restart type is temporary, which means that the
+ %% child specification is automatically removed from the
+ %% supervisor when the process dies.
+ _ = gen_server:call(Pid, stop),
+ ok
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Logging and overload control.
+-define(update_dl_sync(C, Interval),
+ if C == 0 -> Interval;
+ true -> C-1 end).
+
+%% check for overload between every event (and set Mode to async,
+%% sync or drop accordingly), but never flush the whole mailbox
+%% before LogWindowSize events have been handled
+do_log(Bin, CallOrCast, State = #{id:=Name, mode := Mode0}) ->
+ T1 = ?timestamp(),
+
+ %% check if the handler is getting overloaded, or if it's
+ %% recovering from overload (the check must be done for each
+ %% event to react quickly to large bursts of events and
+ %% to ensure that the handler can never end up in drop mode
+ %% with an empty mailbox, which would stop operation)
+ {Mode1,QLen,Mem,State1} = logger_h_common:check_load(State),
+
+ if (Mode1 == drop) andalso (Mode0 =/= drop) ->
+ log_handler_info(Name, "Handler ~p switched to drop mode",
+ [Name], State);
+ (Mode0 == drop) andalso ((Mode1 == async) orelse (Mode1 == sync)) ->
+ log_handler_info(Name, "Handler ~p switched to ~w mode",
+ [Name,Mode1], State);
+ true ->
+ ok
+ end,
+
+ %% kill the handler if it can't keep up with the load
+ logger_h_common:kill_if_choked(Name, QLen, Mem, ?MODULE, State),
+
+ if Mode1 == flush ->
+ flush(Name, QLen, T1, State1);
+ true ->
+ write(Name, Mode1, T1, Bin, CallOrCast, State1)
+ end.
+
+%% this function is called by do_log/3 after an overload check
+%% has been performed, where QLen > FlushQLen
+flush(Name, _QLen0, T1, State=#{last_log_ts := _T0, mode_tab := ModeTab}) ->
+ %% flush messages in the mailbox (a limited number in
+ %% order to not cause long delays)
+ NewFlushed = logger_h_common:flush_log_events(?FLUSH_MAX_N),
+
+ %% write info in log about flushed messages
+ log_handler_info(Name, "Handler ~p flushed ~w log events",
+ [Name,NewFlushed], State),
+
+ %% because of the receive loop when flushing messages, the
+ %% handler will be scheduled out often and the mailbox could
+ %% grow very large, so we'd better check the queue again here
+ {_,_QLen1} = process_info(self(), message_queue_len),
+ ?observe(Name,{max_qlen,_QLen1}),
+
+ %% Add 1 for the current log event
+ ?observe(Name,{flushed,NewFlushed+1}),
+
+ State1 = ?update_max_time(?diff_time(T1,_T0),State),
+ {dropped,?update_other(flushed,FLUSHED,NewFlushed,
+ State1#{mode => ?set_mode(ModeTab,async),
+ last_qlen => 0,
+ last_log_ts => T1})}.
+
+%% this function is called to write to disk_log
+write(Name, Mode, T1, Bin, _CallOrCast,
+ State = #{mode_tab := ModeTab,
+ dl_sync := DLSync,
+ dl_sync_int := DLSyncInt,
+ last_qlen := LastQLen,
+ last_log_ts := T0}) ->
+ %% check if we need to limit the number of writes
+ %% during a burst of log events
+ {DoWrite,BurstWinT,BurstMsgCount} = logger_h_common:limit_burst(State),
+
+ %% only send a synhrounous event to the disk_log process
+ %% every DLSyncInt time, to give the handler time between
+ %% writes so it can keep up with incoming messages
+ {Status,LastQLen1,State1} =
+ if DoWrite, DLSync == 0 ->
+ ?observe(Name,{_CallOrCast,1}),
+ NewState = disk_log_write(Name, Bin, State),
+ {ok, element(2,process_info(self(),message_queue_len)),
+ NewState};
+ DoWrite ->
+ ?observe(Name,{_CallOrCast,1}),
+ NewState = disk_log_write(Name, Bin, State),
+ {ok, LastQLen, NewState};
+ not DoWrite ->
+ ?observe(Name,{flushed,1}),
+ {dropped, LastQLen, State}
+ end,
+
+ %% Check if the time since the previous log event is long enough -
+ %% and the queue length small enough - to assume the mailbox has
+ %% been emptied, and if so, do filesync operation and reset mode to
+ %% async. Note that this is the best we can do to detect an idle
+ %% handler without setting a timer after each log call/cast. If the
+ %% time between two consecutive log events is fast and no new
+ %% event comes in after the last one, idle state won't be detected!
+ Time = ?diff_time(T1,T0),
+ {Mode1,BurstMsgCount1,State2} =
+ if (LastQLen1 < ?FILESYNC_OK_QLEN) andalso
+ (Time > ?IDLE_DETECT_TIME_USEC) ->
+ {?change_mode(ModeTab,Mode,async), 0, disk_log_sync(Name,State1)};
+ true ->
+ {Mode, BurstMsgCount,State1}
+ end,
+
+ State3 =
+ ?update_calls_or_casts(_CallOrCast,1,State2),
+ State4 =
+ ?update_max_time(Time,
+ State3#{mode => Mode1,
+ last_qlen := LastQLen1,
+ last_log_ts => T1,
+ burst_win_ts => BurstWinT,
+ burst_msg_count => BurstMsgCount1,
+ dl_sync => ?update_dl_sync(DLSync,DLSyncInt)}),
+ {Status,State4}.
+
+
+log_handler_info(Name, Format, Args, State) ->
+ Config =
+ case logger:get_handler_config(Name) of
+ {ok,Conf} -> Conf;
+ _ -> #{formatter=>{?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}}
+ end,
+ Meta = #{time=>erlang:system_time(microsecond)},
+ Bin = logger_h_common:log_to_binary(#{level => notice,
+ msg => {Format,Args},
+ meta => Meta}, Config),
+ _ = disk_log_write(Name, Bin, State),
+ ok.
+
+
+open_disk_log(Name, File, Type, MaxNoBytes, MaxNoFiles) ->
+ case filelib:ensure_dir(File) of
+ ok ->
+ Size =
+ if Type == halt -> MaxNoBytes;
+ Type == wrap -> {MaxNoBytes,MaxNoFiles}
+ end,
+ Opts = [{name, Name},
+ {file, File},
+ {size, Size},
+ {type, Type},
+ {linkto, self()},
+ {repair, false},
+ {format, external},
+ {notify, true},
+ {quiet, true},
+ {mode, read_write}],
+ case disk_log:open(Opts) of
+ {ok,Name} ->
+ ok;
+ Error = {error,_Reason} ->
+ Error
+ end;
+ Error ->
+ Error
+ end.
+
+close_disk_log(Name, _) ->
+ _ = ?disk_log_sync(Name),
+ _ = disk_log:lclose(Name),
+ ok.
+
+disk_log_write(Name, Bin, State) ->
+ case ?disk_log_blog(Name, Bin) of
+ ok ->
+ State#{prev_log_result => ok, last_op => write};
+ LogError ->
+ _ = case maps:get(prev_log_result, State) of
+ LogError ->
+ %% don't report same error twice
+ ok;
+ _ ->
+ LogOpts = maps:get(log_opts, State),
+ logger_h_common:error_notify({Name,log,
+ LogOpts,
+ LogError})
+ end,
+ State#{prev_log_result => LogError}
+ end.
+
+disk_log_sync(Name, State) ->
+ case ?disk_log_sync(Name) of
+ ok ->
+ State#{prev_sync_result => ok, last_op => sync};
+ SyncError ->
+ _ = case maps:get(prev_sync_result, State) of
+ SyncError ->
+ %% don't report same error twice
+ ok;
+ _ ->
+ LogOpts = maps:get(log_opts, State),
+ logger_h_common:error_notify({Name,filesync,
+ LogOpts,
+ SyncError})
+ end,
+ State#{prev_sync_result => SyncError}
+ end.
+
+error_notify_new(Info,Info, _Term) ->
+ ok;
+error_notify_new(_Info0,_Info1, Term) ->
+ logger_h_common:error_notify(Term).
diff --git a/lib/kernel/src/logger_filters.erl b/lib/kernel/src/logger_filters.erl
new file mode 100644
index 0000000000..0664c598e1
--- /dev/null
+++ b/lib/kernel/src/logger_filters.erl
@@ -0,0 +1,127 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_filters).
+
+-export([domain/2,
+ level/2,
+ progress/2,
+ remote_gl/2]).
+
+-include("logger_internal.hrl").
+-define(IS_ACTION(A), (A==log orelse A==stop)).
+
+-spec domain(LogEvent,Extra) -> logger:filter_return() when
+ LogEvent :: logger:log_event(),
+ Extra :: {Action,Compare,MatchDomain},
+ Action :: log | stop,
+ Compare :: super | sub | equal | not_equal | undefined,
+ MatchDomain :: list(atom()).
+domain(#{meta:=Meta}=LogEvent,{Action,Compare,MatchDomain})
+ when ?IS_ACTION(Action) andalso
+ (Compare==super orelse
+ Compare==sub orelse
+ Compare==equal orelse
+ Compare==not_equal orelse
+ Compare==undefined) andalso
+ is_list(MatchDomain) ->
+ filter_domain(Compare,Meta,MatchDomain,on_match(Action,LogEvent));
+domain(LogEvent,Extra) ->
+ erlang:error(badarg,[LogEvent,Extra]).
+
+-spec level(LogEvent,Extra) -> logger:filter_return() when
+ LogEvent :: logger:log_event(),
+ Extra :: {Action,Operator,MatchLevel},
+ Action :: log | stop,
+ Operator :: neq | eq | lt | gt | lteq | gteq,
+ MatchLevel :: logger:level().
+level(#{level:=L1}=LogEvent,{Action,Op,L2})
+ when ?IS_ACTION(Action) andalso
+ (Op==neq orelse
+ Op==eq orelse
+ Op==lt orelse
+ Op==gt orelse
+ Op==lteq orelse
+ Op==gteq) andalso
+ ?IS_LEVEL(L2) ->
+ filter_level(Op,L1,L2,on_match(Action,LogEvent));
+level(LogEvent,Extra) ->
+ erlang:error(badarg,[LogEvent,Extra]).
+
+-spec progress(LogEvent,Extra) -> logger:filter_return() when
+ LogEvent :: logger:log_event(),
+ Extra :: log | stop.
+progress(LogEvent,Action) when ?IS_ACTION(Action) ->
+ filter_progress(LogEvent,on_match(Action,LogEvent));
+progress(LogEvent,Action) ->
+ erlang:error(badarg,[LogEvent,Action]).
+
+-spec remote_gl(LogEvent,Extra) -> logger:filter_return() when
+ LogEvent :: logger:log_event(),
+ Extra :: log | stop.
+remote_gl(LogEvent,Action) when ?IS_ACTION(Action) ->
+ filter_remote_gl(LogEvent,on_match(Action,LogEvent));
+remote_gl(LogEvent,Action) ->
+ erlang:error(badarg,[LogEvent,Action]).
+
+%%%-----------------------------------------------------------------
+%%% Internal
+filter_domain(super,#{domain:=Domain},MatchDomain,OnMatch) ->
+ is_prefix(Domain,MatchDomain,OnMatch);
+filter_domain(sub,#{domain:=Domain},MatchDomain,OnMatch) ->
+ is_prefix(MatchDomain,Domain,OnMatch);
+filter_domain(equal,#{domain:=Domain},Domain,OnMatch) ->
+ OnMatch;
+filter_domain(not_equal,#{domain:=Domain},MatchDomain,OnMatch)
+ when Domain=/=MatchDomain ->
+ OnMatch;
+filter_domain(Compare,Meta,_,OnMatch) ->
+ case maps:is_key(domain,Meta) of
+ false when Compare==undefined; Compare==not_equal -> OnMatch;
+ _ -> ignore
+ end.
+
+is_prefix(D1,D2,OnMatch) when is_list(D1), is_list(D2) ->
+ case lists:prefix(D1,D2) of
+ true -> OnMatch;
+ false -> ignore
+ end;
+is_prefix(_,_,_) ->
+ ignore.
+
+filter_level(Op,L1,L2,OnMatch) ->
+ case logger:compare_levels(L1,L2) of
+ eq when Op==eq; Op==lteq; Op==gteq -> OnMatch;
+ lt when Op==lt; Op==lteq; Op==neq -> OnMatch;
+ gt when Op==gt; Op==gteq; Op==neq -> OnMatch;
+ _ -> ignore
+ end.
+
+filter_progress(#{msg:={report,#{label:={_,progress}}}},OnMatch) ->
+ OnMatch;
+filter_progress(_,_) ->
+ ignore.
+
+filter_remote_gl(#{meta:=#{gl:=GL}},OnMatch) when node(GL)=/=node() ->
+ OnMatch;
+filter_remote_gl(_,_) ->
+ ignore.
+
+on_match(log,LogEvent) -> LogEvent;
+on_match(stop,_) -> stop.
diff --git a/lib/kernel/src/logger_formatter.erl b/lib/kernel/src/logger_formatter.erl
new file mode 100644
index 0000000000..ded89bac9f
--- /dev/null
+++ b/lib/kernel/src/logger_formatter.erl
@@ -0,0 +1,514 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_formatter).
+
+-export([format/2]).
+-export([check_config/1]).
+
+-include("logger_internal.hrl").
+
+%%%-----------------------------------------------------------------
+%%% Types
+-type config() :: #{chars_limit => pos_integer() | unlimited,
+ depth => pos_integer() | unlimited,
+ legacy_header => boolean(),
+ max_size => pos_integer() | unlimited,
+ report_cb => logger:report_cb(),
+ single_line => boolean(),
+ template => template(),
+ time_designator => byte(),
+ time_offset => integer() | [byte()]}.
+-type template() :: [metakey() | {metakey(),template(),template()} | string()].
+-type metakey() :: atom() | [atom()].
+
+%%%-----------------------------------------------------------------
+%%% API
+-spec format(LogEvent,Config) -> unicode:chardata() when
+ LogEvent :: logger:log_event(),
+ Config :: config().
+format(#{level:=Level,msg:=Msg0,meta:=Meta},Config0)
+ when is_map(Config0) ->
+ Config = add_default_config(Config0),
+ Meta1 = maybe_add_legacy_header(Level,Meta,Config),
+ Template = maps:get(template,Config),
+ {BT,AT0} = lists:splitwith(fun(msg) -> false; (_) -> true end, Template),
+ {DoMsg,AT} =
+ case AT0 of
+ [msg|Rest] -> {true,Rest};
+ _ ->{false,AT0}
+ end,
+ B = do_format(Level,Meta1,BT,Config),
+ A = do_format(Level,Meta1,AT,Config),
+ MsgStr =
+ if DoMsg ->
+ Config1 =
+ case maps:get(chars_limit,Config) of
+ unlimited ->
+ Config;
+ Size0 ->
+ Size =
+ case Size0 - string:length([B,A]) of
+ S when S>=0 -> S;
+ _ -> 0
+ end,
+ Config#{chars_limit=>Size}
+ end,
+ MsgStr0 = format_msg(Msg0,Meta1,Config1),
+ case maps:get(single_line,Config) of
+ true ->
+ %% Trim leading and trailing whitespaces, and replace
+ %% newlines with ", "
+ re:replace(string:trim(MsgStr0),",?\r?\n\s*",", ",
+ [{return,list},global,unicode]);
+ _false ->
+ MsgStr0
+ end;
+ true ->
+ ""
+ end,
+ truncate([B,MsgStr,A],maps:get(max_size,Config)).
+
+do_format(Level,Data,[level|Format],Config) ->
+ [to_string(level,Level,Config)|do_format(Level,Data,Format,Config)];
+do_format(Level,Data,[{Key,IfExist,Else}|Format],Config) ->
+ String =
+ case value(Key,Data) of
+ {ok,Value} -> do_format(Level,Data#{Key=>Value},IfExist,Config);
+ error -> do_format(Level,Data,Else,Config)
+ end,
+ [String|do_format(Level,Data,Format,Config)];
+do_format(Level,Data,[Key|Format],Config)
+ when is_atom(Key) orelse
+ (is_list(Key) andalso is_atom(hd(Key))) ->
+ String =
+ case value(Key,Data) of
+ {ok,Value} -> to_string(Key,Value,Config);
+ error -> ""
+ end,
+ [String|do_format(Level,Data,Format,Config)];
+do_format(Level,Data,[Str|Format],Config) ->
+ [Str|do_format(Level,Data,Format,Config)];
+do_format(_Level,_Data,[],_Config) ->
+ [].
+
+value(Key,Meta) when is_map_key(Key,Meta) ->
+ {ok,maps:get(Key,Meta)};
+value([Key|Keys],Meta) when is_map_key(Key,Meta) ->
+ value(Keys,maps:get(Key,Meta));
+value([],Value) ->
+ {ok,Value};
+value(_,_) ->
+ error.
+
+to_string(time,Time,Config) ->
+ format_time(Time,Config);
+to_string(mfa,MFA,Config) ->
+ format_mfa(MFA,Config);
+to_string(_,Value,Config) ->
+ to_string(Value,Config).
+
+to_string(X,_) when is_atom(X) ->
+ atom_to_list(X);
+to_string(X,_) when is_integer(X) ->
+ integer_to_list(X);
+to_string(X,_) when is_pid(X) ->
+ pid_to_list(X);
+to_string(X,_) when is_reference(X) ->
+ ref_to_list(X);
+to_string(X,Config) when is_list(X) ->
+ case printable_list(lists:flatten(X)) of
+ true -> X;
+ _ -> io_lib:format(p(Config),[X])
+ end;
+to_string(X,Config) ->
+ io_lib:format(p(Config),[X]).
+
+printable_list([]) ->
+ false;
+printable_list(X) ->
+ io_lib:printable_list(X).
+
+format_msg({string,Chardata},Meta,Config) ->
+ format_msg({"~ts",[Chardata]},Meta,Config);
+format_msg({report,_}=Msg,Meta,#{report_cb:=Fun}=Config)
+ when is_function(Fun,1); is_function(Fun,2) ->
+ format_msg(Msg,Meta#{report_cb=>Fun},maps:remove(report_cb,Config));
+format_msg({report,Report},#{report_cb:=Fun}=Meta,Config) when is_function(Fun,1) ->
+ try Fun(Report) of
+ {Format,Args} when is_list(Format), is_list(Args) ->
+ format_msg({Format,Args},maps:remove(report_cb,Meta),Config);
+ Other ->
+ P = p(Config),
+ format_msg({"REPORT_CB/1 ERROR: "++P++"; Returned: "++P,
+ [Report,Other]},Meta,Config)
+ catch C:R:S ->
+ P = p(Config),
+ format_msg({"REPORT_CB/1 CRASH: "++P++"; Reason: "++P,
+ [Report,{C,R,logger:filter_stacktrace(?MODULE,S)}]},
+ Meta,Config)
+ end;
+format_msg({report,Report},#{report_cb:=Fun}=Meta,Config) when is_function(Fun,2) ->
+ try Fun(Report,maps:with([depth,chars_limit,single_line],Config)) of
+ Chardata when ?IS_STRING(Chardata) ->
+ try chardata_to_list(Chardata) % already size limited by report_cb
+ catch _:_ ->
+ P = p(Config),
+ format_msg({"REPORT_CB/2 ERROR: "++P++"; Returned: "++P,
+ [Report,Chardata]},Meta,Config)
+ end;
+ Other ->
+ P = p(Config),
+ format_msg({"REPORT_CB/2 ERROR: "++P++"; Returned: "++P,
+ [Report,Other]},Meta,Config)
+ catch C:R:S ->
+ P = p(Config),
+ format_msg({"REPORT_CB/2 CRASH: "++P++"; Reason: "++P,
+ [Report,{C,R,logger:filter_stacktrace(?MODULE,S)}]},
+ Meta,Config)
+ end;
+format_msg({report,Report},Meta,Config) ->
+ format_msg({report,Report},
+ Meta#{report_cb=>fun logger:format_report/1},
+ Config);
+format_msg(Msg,_Meta,#{depth:=Depth,chars_limit:=CharsLimit,
+ single_line:=Single}) ->
+ Opts = chars_limit_to_opts(CharsLimit),
+ format_msg(Msg, Depth, Opts, Single).
+
+chars_limit_to_opts(unlimited) -> [];
+chars_limit_to_opts(CharsLimit) -> [{chars_limit,CharsLimit}].
+
+format_msg({Format0,Args},Depth,Opts,Single) ->
+ try
+ Format1 = io_lib:scan_format(Format0, Args),
+ Format = reformat(Format1, Depth, Single),
+ io_lib:build_text(Format,Opts)
+ catch C:R:S ->
+ P = p(Single),
+ FormatError = "FORMAT ERROR: "++P++" - "++P,
+ case Format0 of
+ FormatError ->
+ %% already been here - avoid failing cyclically
+ erlang:raise(C,R,S);
+ _ ->
+ format_msg({FormatError,[Format0,Args]},Depth,Opts,Single)
+ end
+ end.
+
+reformat(Format,unlimited,false) ->
+ Format;
+reformat([#{control_char:=C}=M|T], Depth, true) when C =:= $p ->
+ [limit_depth(M#{width => 0}, Depth)|reformat(T, Depth, true)];
+reformat([#{control_char:=C}=M|T], Depth, true) when C =:= $P ->
+ [M#{width => 0}|reformat(T, Depth, true)];
+reformat([#{control_char:=C}=M|T], Depth, Single) when C =:= $p; C =:= $w ->
+ [limit_depth(M, Depth)|reformat(T, Depth, Single)];
+reformat([H|T], Depth, Single) ->
+ [H|reformat(T, Depth, Single)];
+reformat([], _, _) ->
+ [].
+
+limit_depth(M0, unlimited) ->
+ M0;
+limit_depth(#{control_char:=C0, args:=Args}=M0, Depth) ->
+ C = C0 - ($a - $A), %To uppercase.
+ M0#{control_char:=C,args:=Args++[Depth]}.
+
+chardata_to_list(Chardata) ->
+ case unicode:characters_to_list(Chardata,unicode) of
+ List when is_list(List) ->
+ List;
+ Error ->
+ throw(Error)
+ end.
+
+truncate(String,unlimited) ->
+ String;
+truncate(String,Size) ->
+ Length = string:length(String),
+ if Length>Size ->
+ case lists:reverse(lists:flatten(String)) of
+ [$\n|_] ->
+ string:slice(String,0,Size-4)++"...\n";
+ _ ->
+ string:slice(String,0,Size-3)++"..."
+ end;
+ true ->
+ String
+ end.
+
+%% SysTime is the system time in microseconds
+format_time(SysTime,#{time_offset:=Offset,time_designator:=Des})
+ when is_integer(SysTime) ->
+ calendar:system_time_to_rfc3339(SysTime,[{unit,microsecond},
+ {offset,Offset},
+ {time_designator,Des}]).
+
+%% SysTime is the system time in microseconds
+timestamp_to_datetimemicro(SysTime,Config) when is_integer(SysTime) ->
+ Micro = SysTime rem 1000000,
+ Sec = SysTime div 1000000,
+ UniversalTime = erlang:posixtime_to_universaltime(Sec),
+ {{Date,Time},UtcStr} =
+ case offset_to_utc(maps:get(time_offset,Config)) of
+ true -> {UniversalTime,"UTC "};
+ _ -> {erlang:universaltime_to_localtime(UniversalTime),""}
+ end,
+ {Date,Time,Micro,UtcStr}.
+
+format_mfa({M,F,A},_) when is_atom(M), is_atom(F), is_integer(A) ->
+ atom_to_list(M)++":"++atom_to_list(F)++"/"++integer_to_list(A);
+format_mfa({M,F,A},Config) when is_atom(M), is_atom(F), is_list(A) ->
+ format_mfa({M,F,length(A)},Config);
+format_mfa(MFA,Config) ->
+ to_string(MFA,Config).
+
+maybe_add_legacy_header(Level,
+ #{time:=Timestamp}=Meta,
+ #{legacy_header:=true}=Config) ->
+ #{title:=Title}=MyMeta = add_legacy_title(Level,Meta,Config),
+ {{Y,Mo,D},{H,Mi,S},Micro,UtcStr} =
+ timestamp_to_datetimemicro(Timestamp,Config),
+ Header =
+ io_lib:format("=~ts==== ~w-~s-~4w::~2..0w:~2..0w:~2..0w.~6..0w ~s===",
+ [Title,D,month(Mo),Y,H,Mi,S,Micro,UtcStr]),
+ Meta#{?MODULE=>MyMeta#{header=>Header}};
+maybe_add_legacy_header(_,Meta,_) ->
+ Meta.
+
+add_legacy_title(_Level,#{?MODULE:=#{title:=_}=MyMeta},_) ->
+ MyMeta;
+add_legacy_title(Level,Meta,Config) ->
+ case maps:get(?MODULE,Meta,#{}) of
+ #{title:=_}=MyMeta ->
+ MyMeta;
+ MyMeta ->
+ TitleLevel =
+ case (Level=:=notice andalso maps:find(error_logger,Meta)) of
+ {ok,_} ->
+ maps:get(error_logger_notice_header,Config);
+ _ ->
+ Level
+ end,
+ Title = string:uppercase(atom_to_list(TitleLevel)) ++ " REPORT",
+ MyMeta#{title=>Title}
+ end.
+
+month(1) -> "Jan";
+month(2) -> "Feb";
+month(3) -> "Mar";
+month(4) -> "Apr";
+month(5) -> "May";
+month(6) -> "Jun";
+month(7) -> "Jul";
+month(8) -> "Aug";
+month(9) -> "Sep";
+month(10) -> "Oct";
+month(11) -> "Nov";
+month(12) -> "Dec".
+
+%% Ensure that all valid configuration parameters exist in the final
+%% configuration map
+add_default_config(Config0) ->
+ Default =
+ #{chars_limit=>unlimited,
+ error_logger_notice_header=>info,
+ legacy_header=>false,
+ single_line=>true,
+ time_designator=>$T},
+ MaxSize = get_max_size(maps:get(max_size,Config0,undefined)),
+ Depth = get_depth(maps:get(depth,Config0,undefined)),
+ Offset = get_offset(maps:get(time_offset,Config0,undefined)),
+ add_default_template(maps:merge(Default,Config0#{max_size=>MaxSize,
+ depth=>Depth,
+ time_offset=>Offset})).
+
+add_default_template(#{template:=_}=Config) ->
+ Config;
+add_default_template(Config) ->
+ Config#{template=>default_template(Config)}.
+
+default_template(#{legacy_header:=true}) ->
+ ?DEFAULT_FORMAT_TEMPLATE_HEADER;
+default_template(#{single_line:=true}) ->
+ ?DEFAULT_FORMAT_TEMPLATE_SINGLE;
+default_template(_) ->
+ ?DEFAULT_FORMAT_TEMPLATE.
+
+get_max_size(undefined) ->
+ unlimited;
+get_max_size(S) ->
+ max(10,S).
+
+get_depth(undefined) ->
+ error_logger:get_format_depth();
+get_depth(S) ->
+ max(5,S).
+
+get_offset(undefined) ->
+ utc_to_offset(get_utc_config());
+get_offset(Offset) ->
+ Offset.
+
+utc_to_offset(true) ->
+ "Z";
+utc_to_offset(false) ->
+ "".
+
+get_utc_config() ->
+ %% SASL utc_log overrides stdlib config - in order to have uniform
+ %% timestamps in log messages
+ case application:get_env(sasl, utc_log) of
+ {ok, Val} when is_boolean(Val) -> Val;
+ _ ->
+ case application:get_env(stdlib, utc_log) of
+ {ok, Val} when is_boolean(Val) -> Val;
+ _ -> false
+ end
+ end.
+
+offset_to_utc(Z) when Z=:=0; Z=:="z"; Z=:="Z" ->
+ true;
+offset_to_utc([$+|Tz]) ->
+ case io_lib:fread("~d:~d", Tz) of
+ {ok, [0, 0], []} ->
+ true;
+ _ ->
+ false
+ end;
+offset_to_utc(_) ->
+ false.
+
+-spec check_config(Config) -> ok | {error,term()} when
+ Config :: config().
+check_config(Config) when is_map(Config) ->
+ do_check_config(maps:to_list(Config));
+check_config(Config) ->
+ {error,{invalid_formatter_config,?MODULE,Config}}.
+
+do_check_config([{Type,L}|Config]) when Type == chars_limit;
+ Type == depth;
+ Type == max_size ->
+ case check_limit(L) of
+ ok -> do_check_config(Config);
+ error -> {error,{invalid_formatter_config,?MODULE,{Type,L}}}
+ end;
+do_check_config([{single_line,SL}|Config]) when is_boolean(SL) ->
+ do_check_config(Config);
+do_check_config([{legacy_header,LH}|Config]) when is_boolean(LH) ->
+ do_check_config(Config);
+do_check_config([{error_logger_notice_header,ELNH}|Config]) when ELNH == info;
+ ELNH == notice ->
+ do_check_config(Config);
+do_check_config([{report_cb,RCB}|Config]) when is_function(RCB,1);
+ is_function(RCB,2) ->
+ do_check_config(Config);
+do_check_config([{template,T}|Config]) ->
+ case check_template(T) of
+ ok -> do_check_config(Config);
+ error -> {error,{invalid_formatter_template,?MODULE,T}}
+ end;
+do_check_config([{time_offset,Offset}|Config]) ->
+ case check_offset(Offset) of
+ ok ->
+ do_check_config(Config);
+ error ->
+ {error,{invalid_formatter_config,?MODULE,{time_offset,Offset}}}
+ end;
+do_check_config([{time_designator,Char}|Config]) when Char>=0, Char=<255 ->
+ case io_lib:printable_latin1_list([Char]) of
+ true ->
+ do_check_config(Config);
+ false ->
+ {error,{invalid_formatter_config,?MODULE,{time_designator,Char}}}
+ end;
+do_check_config([C|_]) ->
+ {error,{invalid_formatter_config,?MODULE,C}};
+do_check_config([]) ->
+ ok.
+
+check_limit(L) when is_integer(L), L>0 ->
+ ok;
+check_limit(unlimited) ->
+ ok;
+check_limit(_) ->
+ error.
+
+check_template([Key|T]) when is_atom(Key) ->
+ check_template(T);
+check_template([Key|T]) when is_list(Key), is_atom(hd(Key)) ->
+ case lists:all(fun(X) when is_atom(X) -> true;
+ (_) -> false
+ end,
+ Key) of
+ true ->
+ check_template(T);
+ false ->
+ error
+ end;
+check_template([{Key,IfExist,Else}|T])
+ when is_atom(Key) orelse
+ (is_list(Key) andalso is_atom(hd(Key))) ->
+ case check_template(IfExist) of
+ ok ->
+ case check_template(Else) of
+ ok ->
+ check_template(T);
+ error ->
+ error
+ end;
+ error ->
+ error
+ end;
+check_template([Str|T]) when is_list(Str) ->
+ case io_lib:printable_unicode_list(Str) of
+ true -> check_template(T);
+ false -> error
+ end;
+check_template([]) ->
+ ok;
+check_template(_) ->
+ error.
+
+check_offset(I) when is_integer(I) ->
+ ok;
+check_offset(Tz) when Tz=:=""; Tz=:="Z"; Tz=:="z" ->
+ ok;
+check_offset([Sign|Tz]) when Sign=:=$+; Sign=:=$- ->
+ check_timezone(Tz);
+check_offset(_) ->
+ error.
+
+check_timezone(Tz) ->
+ try io_lib:fread("~d:~d", Tz) of
+ {ok, [_, _], []} ->
+ ok;
+ _ ->
+ error
+ catch _:_ ->
+ error
+ end.
+
+p(#{single_line:=Single}) ->
+ p(Single);
+p(true) ->
+ "~0tp";
+p(false) ->
+ "~tp".
diff --git a/lib/kernel/src/logger_h_common.erl b/lib/kernel/src/logger_h_common.erl
new file mode 100644
index 0000000000..38ac7d8ffc
--- /dev/null
+++ b/lib/kernel/src/logger_h_common.erl
@@ -0,0 +1,336 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_h_common).
+
+-include("logger_h_common.hrl").
+-include("logger_internal.hrl").
+
+-export([log_to_binary/2,
+ check_common_config/1,
+ call_cast_or_drop/4,
+ check_load/1,
+ limit_burst/1,
+ kill_if_choked/5,
+ flush_log_events/0,
+ flush_log_events/1,
+ handler_exit/2,
+ set_restart_flag/2,
+ unset_restart_flag/2,
+ cancel_timer/1,
+ stop_or_restart/3,
+ overload_levels_ok/1,
+ error_notify/1,
+ info_notify/1]).
+
+%%%-----------------------------------------------------------------
+%%% Convert log data on any form to binary
+-spec log_to_binary(LogEvent,Config) -> LogString when
+ LogEvent :: logger:log_event(),
+ Config :: logger:handler_config(),
+ LogString :: binary().
+log_to_binary(#{msg:={report,_},meta:=#{report_cb:=_}}=Log,Config) ->
+ do_log_to_binary(Log,Config);
+log_to_binary(#{msg:={report,_},meta:=Meta}=Log,Config) ->
+ DefaultReportCb = fun logger:format_otp_report/1,
+ do_log_to_binary(Log#{meta=>Meta#{report_cb=>DefaultReportCb}},Config);
+log_to_binary(Log,Config) ->
+ do_log_to_binary(Log,Config).
+
+do_log_to_binary(Log,Config) ->
+ {Formatter,FormatterConfig} =
+ maps:get(formatter,Config,{?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}),
+ String = try_format(Log,Formatter,FormatterConfig),
+ try string_to_binary(String)
+ catch C2:R2:S2 ->
+ ?LOG_INTERNAL(debug,[{formatter_error,Formatter},
+ {config,FormatterConfig},
+ {log_event,Log},
+ {bad_return_value,String},
+ {catched,{C2,R2,S2}}]),
+ <<"FORMATTER ERROR: bad return value">>
+ end.
+
+try_format(Log,Formatter,FormatterConfig) ->
+ try Formatter:format(Log,FormatterConfig)
+ catch
+ C:R:S ->
+ ?LOG_INTERNAL(debug,[{formatter_crashed,Formatter},
+ {config,FormatterConfig},
+ {log_event,Log},
+ {reason,
+ {C,R,logger:filter_stacktrace(?MODULE,S)}}]),
+ case {?DEFAULT_FORMATTER,#{}} of
+ {Formatter,FormatterConfig} ->
+ "DEFAULT FORMATTER CRASHED";
+ {DefaultFormatter,DefaultConfig} ->
+ try_format(Log#{msg=>{"FORMATTER CRASH: ~tp",
+ [maps:get(msg,Log)]}},
+ DefaultFormatter,DefaultConfig)
+ end
+ end.
+
+string_to_binary(String) ->
+ case unicode:characters_to_binary(String) of
+ Binary when is_binary(Binary) ->
+ Binary;
+ Error ->
+ throw(Error)
+ end.
+
+
+%%%-----------------------------------------------------------------
+%%% Check that the configuration term is valid
+check_common_config({mode_tab,_Tid}) ->
+ valid;
+check_common_config({handler_pid,Pid}) when is_pid(Pid) ->
+ valid;
+
+check_common_config({sync_mode_qlen,N}) when is_integer(N) ->
+ valid;
+check_common_config({drop_mode_qlen,N}) when is_integer(N) ->
+ valid;
+check_common_config({flush_qlen,N}) when is_integer(N) ->
+ valid;
+
+check_common_config({burst_limit_enable,Bool}) when Bool == true;
+ Bool == false ->
+ valid;
+check_common_config({burst_limit_max_count,N}) when is_integer(N) ->
+ valid;
+check_common_config({burst_limit_window_time,N}) when is_integer(N) ->
+ valid;
+
+check_common_config({overload_kill_enable,Bool}) when Bool == true;
+ Bool == false ->
+ valid;
+check_common_config({overload_kill_qlen,N}) when is_integer(N) ->
+ valid;
+check_common_config({overload_kill_mem_size,N}) when is_integer(N) ->
+ valid;
+check_common_config({overload_kill_restart_after,NorA}) when is_integer(NorA);
+ NorA == infinity ->
+ valid;
+
+check_common_config({filesync_repeat_interval,NorA}) when is_integer(NorA);
+ NorA == no_repeat ->
+ valid;
+check_common_config(_) ->
+ invalid.
+
+
+%%%-----------------------------------------------------------------
+%%% Overload Protection
+call_cast_or_drop(_Name, HandlerPid, ModeTab, Bin) ->
+ %% If the handler process is getting overloaded, the log event
+ %% will be synchronous instead of asynchronous (slows down the
+ %% logging tempo of a process doing lots of logging. If the
+ %% handler is choked, drop mode is set and no event will be sent.
+ try ?get_mode(ModeTab) of
+ async ->
+ gen_server:cast(HandlerPid, {log,Bin});
+ sync ->
+ try gen_server:call(HandlerPid, {log,Bin}, ?DEFAULT_CALL_TIMEOUT) of
+ %% if return value from call == dropped, the
+ %% message has been flushed by handler and should
+ %% therefore not be counted as dropped in stats
+ ok -> ok;
+ dropped -> ok
+ catch
+ _:{timeout,_} ->
+ ?observe(_Name,{dropped,1})
+ end;
+ drop ->
+ ?observe(_Name,{dropped,1})
+ catch
+ %% if the ETS table doesn't exist (maybe because of a
+ %% handler restart), we can only drop the event
+ _:_ -> ?observe(_Name,{dropped,1})
+ end,
+ ok.
+
+handler_exit(_Name, Reason) ->
+ exit(Reason).
+
+set_restart_flag(Name, Module) ->
+ Flag = list_to_atom(lists:concat([Module,"_",Name,"_restarting"])),
+ spawn(fun() ->
+ register(Flag, self()),
+ timer:sleep(infinity)
+ end),
+ ok.
+
+unset_restart_flag(Name, Module) ->
+ Flag = list_to_atom(lists:concat([Module,"_",Name,"_restarting"])),
+ case whereis(Flag) of
+ undefined ->
+ false;
+ Pid ->
+ exit(Pid, kill),
+ true
+ end.
+
+check_load(State = #{id:=_Name, mode_tab := ModeTab, mode := Mode,
+ sync_mode_qlen := SyncModeQLen,
+ drop_mode_qlen := DropModeQLen,
+ flush_qlen := FlushQLen}) ->
+ {_,Mem} = process_info(self(), memory),
+ ?observe(_Name,{max_mem,Mem}),
+ {_,QLen} = process_info(self(), message_queue_len),
+ ?observe(_Name,{max_qlen,QLen}),
+ %% When the handler process gets scheduled in, it's impossible
+ %% to predict the QLen. We could jump "up" arbitrarily from say
+ %% async to sync, async to drop, sync to flush, etc. However, when
+ %% the handler process manages the log events (without flushing),
+ %% one after the other, we will move "down" from drop to sync and
+ %% from sync to async. This way we don't risk getting stuck in
+ %% drop or sync mode with an empty mailbox.
+ {Mode1,_NewDrops,_NewFlushes} =
+ if
+ QLen >= FlushQLen ->
+ {flush, 0,1};
+ QLen >= DropModeQLen ->
+ %% Note that drop mode will force log events to
+ %% be dropped on the client side (never sent get to
+ %% the handler).
+ IncDrops = if Mode == drop -> 0; true -> 1 end,
+ {?change_mode(ModeTab, Mode, drop), IncDrops,0};
+ QLen >= SyncModeQLen ->
+ {?change_mode(ModeTab, Mode, sync), 0,0};
+ true ->
+ {?change_mode(ModeTab, Mode, async), 0,0}
+ end,
+ State1 = ?update_other(drops,DROPS,_NewDrops,State),
+ {Mode1, QLen, Mem,
+ ?update_other(flushes,FLUSHES,_NewFlushes,
+ State1#{last_qlen => QLen})}.
+
+limit_burst(#{burst_limit_enable := false}) ->
+ {true,0,0};
+limit_burst(#{burst_win_ts := BurstWinT0,
+ burst_msg_count := BurstMsgCount,
+ burst_limit_window_time := BurstLimitWinTime,
+ burst_limit_max_count := BurstLimitMaxCnt}) ->
+ if (BurstMsgCount >= BurstLimitMaxCnt) ->
+ %% the limit for allowed messages has been reached
+ BurstWinT1 = ?timestamp(),
+ case ?diff_time(BurstWinT1,BurstWinT0) of
+ BurstCheckTime when BurstCheckTime < (BurstLimitWinTime*1000) ->
+ %% we're still within the burst time frame
+ {false,BurstWinT0,BurstMsgCount};
+ _BurstCheckTime ->
+ %% burst time frame passed, reset counters
+ {true,BurstWinT1,0}
+ end;
+ true ->
+ %% the limit for allowed messages not yet reached
+ {true,BurstWinT0,BurstMsgCount+1}
+ end.
+
+kill_if_choked(Name, QLen, Mem, HandlerMod,
+ State = #{overload_kill_enable := KillIfOL,
+ overload_kill_qlen := OLKillQLen,
+ overload_kill_mem_size := OLKillMem}) ->
+ if KillIfOL andalso
+ ((QLen > OLKillQLen) orelse (Mem > OLKillMem)) ->
+ HandlerMod:log_handler_info(Name,
+ "Handler ~p overloaded and stopping",
+ [Name], State),
+ set_restart_flag(Name, HandlerMod),
+ handler_exit(Name, {shutdown,{overloaded,Name,QLen,Mem}});
+ true ->
+ ok
+ end.
+
+flush_log_events() ->
+ flush_log_events(-1).
+
+flush_log_events(Limit) ->
+ process_flag(priority, high),
+ Flushed = flush_log_events(0, Limit),
+ process_flag(priority, normal),
+ Flushed.
+
+flush_log_events(Limit, Limit) ->
+ Limit;
+flush_log_events(N, Limit) ->
+ %% flush log events but leave other events, such as
+ %% filesync, info and change_config, so that these
+ %% have a chance to be processed even under heavy load
+ receive
+ {'$gen_cast',{log,_}} ->
+ flush_log_events(N+1, Limit);
+ {'$gen_call',{Pid,MRef},{log,_}} ->
+ Pid ! {MRef, dropped},
+ flush_log_events(N+1, Limit)
+ after
+ 0 -> N
+ end.
+
+cancel_timer(TRef) when is_atom(TRef) -> ok;
+cancel_timer(TRef) -> timer:cancel(TRef).
+
+
+stop_or_restart(Name, {shutdown,Reason={overloaded,_Name,_QLen,_Mem}},
+ #{overload_kill_restart_after := RestartAfter}) ->
+ %% If we're terminating because of an overload situation (see
+ %% logger_h_common:kill_if_choked/4), we need to remove the handler
+ %% and set a restart timer. A separate process must perform this
+ %% in order to avoid deadlock.
+ HandlerPid = self(),
+ ConfigResult = logger:get_handler_config(Name),
+ RemoveAndRestart =
+ fun() ->
+ MRef = erlang:monitor(process, HandlerPid),
+ receive
+ {'DOWN',MRef,_,_,_} ->
+ ok
+ after 30000 ->
+ error_notify(Reason),
+ exit(HandlerPid, kill)
+ end,
+ case ConfigResult of
+ {ok,#{module:=HMod}=HConfig} when is_integer(RestartAfter) ->
+ _ = logger:remove_handler(Name),
+ _ = timer:apply_after(RestartAfter, logger, add_handler,
+ [Name,HMod,HConfig]);
+ {ok,_} ->
+ _ = logger:remove_handler(Name);
+ {error,CfgReason} when is_integer(RestartAfter) ->
+ error_notify({Name,restart_impossible,CfgReason});
+ {error,_} ->
+ ok
+ end
+ end,
+ spawn(RemoveAndRestart),
+ ok;
+stop_or_restart(_Name, _Reason, _State) ->
+ ok.
+
+overload_levels_ok(HandlerConfig) ->
+ SMQL = maps:get(sync_mode_qlen, HandlerConfig, ?SYNC_MODE_QLEN),
+ DMQL = maps:get(drop_mode_qlen, HandlerConfig, ?DROP_MODE_QLEN),
+ FQL = maps:get(flush_qlen, HandlerConfig, ?FLUSH_QLEN),
+ (DMQL > 1) andalso (SMQL =< DMQL) andalso (DMQL =< FQL).
+
+error_notify(Term) ->
+ ?internal_log(error, Term).
+
+info_notify(Term) ->
+ ?internal_log(info, Term).
diff --git a/lib/kernel/src/logger_h_common.hrl b/lib/kernel/src/logger_h_common.hrl
new file mode 100644
index 0000000000..e0a7b6e3ca
--- /dev/null
+++ b/lib/kernel/src/logger_h_common.hrl
@@ -0,0 +1,263 @@
+
+%%%-----------------------------------------------------------------
+%%% Overload protection configuration
+
+%%! *** NOTE ***
+%%! It's important that:
+%%! SYNC_MODE_QLEN =< DROP_MODE_QLEN =< FLUSH_QLEN
+%%! and that DROP_MODE_QLEN >= 2.
+%%! Otherwise the handler could end up in drop mode with no new
+%%! log requests to process. This would cause all future requests
+%%! to be dropped (no switch to async mode would ever take place).
+
+%% This specifies the message_queue_len value where the log
+%% requests switch from asynchronous casts to synchronous calls.
+-define(SYNC_MODE_QLEN, 10).
+%% Above this message_queue_len, log requests will be dropped,
+%% i.e. no log requests get sent to the handler process.
+-define(DROP_MODE_QLEN, 200).
+%% Above this message_queue_len, the handler process will flush
+%% its mailbox and only leave this number of messages in it.
+-define(FLUSH_QLEN, 1000).
+
+%% Never flush more than this number of messages in one go,
+%% or the handler will be unresponsive for seconds (keep this
+%% number as large as possible or the mailbox could grow large).
+-define(FLUSH_MAX_N, 5000).
+
+%% BURST_LIMIT_MAX_COUNT is the max number of log requests allowed
+%% to be written within a BURST_LIMIT_WINDOW_TIME time frame.
+-define(BURST_LIMIT_ENABLE, true).
+-define(BURST_LIMIT_MAX_COUNT, 500).
+-define(BURST_LIMIT_WINDOW_TIME, 1000).
+
+%% This enables/disables the feature to automatically get the
+%% handler terminated if it gets too loaded (and can't keep up).
+-define(OVERLOAD_KILL_ENABLE, false).
+%% If the message_queue_len goes above this size even after
+%% flushing has been performed, the handler is terminated.
+-define(OVERLOAD_KILL_QLEN, 20000).
+%% If the memory usage exceeds this level
+-define(OVERLOAD_KILL_MEM_SIZE, 3000000).
+
+%% This is the default time that the handler will wait before
+%% restarting and accepting new requests. The value 'infinity'
+%% disables restarts.
+-define(OVERLOAD_KILL_RESTART_AFTER, 5000).
+%%-define(OVERLOAD_KILL_RESTART_AFTER, infinity).
+
+%% The handler sends asynchronous write requests to the process
+%% controlling the i/o device, but every once in this interval
+%% will the write request be synchronous, so that the i/o device
+%% process doesn't get overloaded. This gives the handler time
+%% to keep up with its mailbox in overload situations, even if
+%% the i/o is slow.
+-define(CONTROLLER_SYNC_INTERVAL, 20).
+%% The handler will not perform a file sync operation if the
+%% mailbox size is greater than this number. This is to ensure
+%% the handler process doesn't get overloaded while waiting for
+%% an expensive file sync operation to finish.
+-define(FILESYNC_OK_QLEN, 2).
+%% Do a file/disk_log sync operation every integer() millisec
+%% (if necessary) or set to 'no_repeat' to only do file sync when
+%% the handler is idle. Note that file sync is not guaranteed to
+%% happen automatically if this operation is disabled.
+-define(FILESYNC_REPEAT_INTERVAL, 5000).
+%%-define(FILESYNC_REPEAT_INTERVAL, no_repeat).
+
+%% This is the time after last message received that we think/hope
+%% that the handler has an empty mailbox (no new log request has
+%% come in).
+-define(IDLE_DETECT_TIME_MSEC, 100).
+-define(IDLE_DETECT_TIME_USEC, 100000).
+
+%% Default disk log option values
+-define(DISK_LOG_TYPE, wrap).
+-define(DISK_LOG_MAX_NO_FILES, 10).
+-define(DISK_LOG_MAX_NO_BYTES, 1048576).
+
+%%%-----------------------------------------------------------------
+%%% Utility macros
+
+-define(name_to_reg_name(MODULE,Name),
+ list_to_atom(lists:concat([MODULE,"_",Name]))).
+
+%%%-----------------------------------------------------------------
+%%% Overload protection macros
+
+-define(timestamp(), erlang:monotonic_time(microsecond)).
+
+-define(get_mode(Tid),
+ case ets:lookup(Tid, mode) of
+ [{mode,M}] -> M;
+ _ -> async
+ end).
+
+-define(set_mode(Tid, M),
+ begin ets:insert(Tid, {mode,M}), M end).
+
+-define(change_mode(Tid, M0, M1),
+ if M0 == M1 ->
+ M0;
+ true ->
+ ets:insert(Tid, {mode,M1}),
+ M1
+ end).
+
+-define(min(X1, X2),
+ if X2 == undefined -> X1;
+ X2 < X1 -> X2;
+ true -> X1
+ end).
+
+-define(max(X1, X2),
+ if
+ X2 == undefined -> X1;
+ X2 > X1 -> X2;
+ true -> X1
+ end).
+
+-define(diff_time(OS_T1, OS_T0), OS_T1-OS_T0).
+
+%%%-----------------------------------------------------------------
+%%% The test hook macros make it possible to observe and manipulate
+%%% internal handler functionality. When enabled, these macros will
+%%% slow down execution and therefore should not be include in code
+%%% to be officially released.
+
+%%-define(TEST_HOOKS, true).
+-ifdef(TEST_HOOKS).
+ -define(TEST_HOOKS_TAB, logger_h_test_hooks).
+
+ -define(init_test_hooks(),
+ _ = case ets:whereis(?TEST_HOOKS_TAB) of
+ undefined -> ets:new(?TEST_HOOKS_TAB, [named_table,public]);
+ _ -> ok
+ end,
+ ets:insert(?TEST_HOOKS_TAB, {internal_log,{logger,internal_log}}),
+ ets:insert(?TEST_HOOKS_TAB, {file_write,ok}),
+ ets:insert(?TEST_HOOKS_TAB, {file_datasync,ok}),
+ ets:insert(?TEST_HOOKS_TAB, {disk_log_blog,ok}),
+ ets:insert(?TEST_HOOKS_TAB, {disk_log_sync,ok})).
+
+ -define(set_internal_log(MOD_FUNC),
+ ets:insert(?TEST_HOOKS_TAB, {internal_log,MOD_FUNC})).
+
+ -define(set_result(OPERATION, RESULT),
+ ets:insert(?TEST_HOOKS_TAB, {OPERATION,RESULT})).
+
+ -define(set_defaults(),
+ ets:insert(?TEST_HOOKS_TAB, {internal_log,{logger,internal_log}}),
+ ets:insert(?TEST_HOOKS_TAB, {file_write,ok}),
+ ets:insert(?TEST_HOOKS_TAB, {file_datasync,ok}),
+ ets:insert(?TEST_HOOKS_TAB, {disk_log_blog,ok}),
+ ets:insert(?TEST_HOOKS_TAB, {disk_log_sync,ok})).
+
+ -define(internal_log(TYPE, TERM),
+ try ets:lookup(?TEST_HOOKS_TAB, internal_log) of
+ [{_,{LMOD,LFUNC}}] -> apply(LMOD, LFUNC, [TYPE,TERM]);
+ _ -> logger:internal_log(TYPE, TERM)
+ catch _:_ -> logger:internal_log(TYPE, TERM) end).
+
+ -define(file_write(DEVICE, DATA),
+ try ets:lookup(?TEST_HOOKS_TAB, file_write) of
+ [{_,ok}] -> file:write(DEVICE, DATA);
+ [{_,ERROR}] -> ERROR
+ catch _:_ -> file:write(DEVICE, DATA) end).
+
+ -define(file_datasync(DEVICE),
+ try ets:lookup(?TEST_HOOKS_TAB, file_datasync) of
+ [{_,ok}] -> file:datasync(DEVICE);
+ [{_,ERROR}] -> ERROR
+ catch _:_ -> file:datasync(DEVICE) end).
+
+ -define(disk_log_blog(LOG, DATA),
+ try ets:lookup(?TEST_HOOKS_TAB, disk_log_blog) of
+ [{_,ok}] -> disk_log:blog(LOG, DATA);
+ [{_,ERROR}] -> ERROR
+ catch _:_ -> disk_log:blog(LOG, DATA) end).
+
+ -define(disk_log_sync(LOG),
+ try ets:lookup(?TEST_HOOKS_TAB, disk_log_sync) of
+ [{_,ok}] -> disk_log:sync(LOG);
+ [{_,ERROR}] -> ERROR
+ catch _:_ -> disk_log:sync(LOG) end).
+
+ -define(DEFAULT_CALL_TIMEOUT, 5000).
+
+-else. % DEFAULTS!
+ -define(TEST_HOOKS_TAB, undefined).
+ -define(init_test_hooks(), ok).
+ -define(set_internal_log(_MOD_FUNC), ok).
+ -define(set_result(_OPERATION, _RESULT), ok).
+ -define(set_defaults(), ok).
+ -define(internal_log(TYPE, TERM), logger:internal_log(TYPE, TERM)).
+ -define(file_write(DEVICE, DATA), file:write(DEVICE, DATA)).
+ -define(file_datasync(DEVICE), file:datasync(DEVICE)).
+ -define(disk_log_blog(LOG, DATA), disk_log:blog(LOG, DATA)).
+ -define(disk_log_sync(LOG), disk_log:sync(LOG)).
+ -define(DEFAULT_CALL_TIMEOUT, 10000).
+-endif.
+
+%%%-----------------------------------------------------------------
+%%% These macros enable statistics counters in the state of the
+%%% handler which is useful for analysing the overload protection
+%%% behaviour. These counters should not be included in code to be
+%%% officially released (as some counters will grow very large
+%%% over time).
+
+%%-define(SAVE_STATS, true).
+-ifdef(SAVE_STATS).
+ -define(merge_with_stats(STATE),
+ STATE#{flushes => 0, flushed => 0, drops => 0,
+ casts => 0, calls => 0,
+ max_qlen => 0, max_time => 0}).
+
+ -define(update_max_qlen(QLEN, STATE),
+ begin #{max_qlen := QLEN0} = STATE,
+ STATE#{max_qlen => ?max(QLEN0,QLEN)} end).
+
+ -define(update_calls_or_casts(CALL_OR_CAST, INC, STATE),
+ case CALL_OR_CAST of
+ cast ->
+ #{casts := CASTS0} = STATE,
+ STATE#{casts => CASTS0+INC};
+ call ->
+ #{calls := CALLS0} = STATE,
+ STATE#{calls => CALLS0+INC}
+ end).
+
+ -define(update_max_time(TIME, STATE),
+ begin #{max_time := TIME0} = STATE,
+ STATE#{max_time => ?max(TIME0,TIME)} end).
+
+ -define(update_other(OTHER, VAR, INCVAL, STATE),
+ begin #{OTHER := VAR} = STATE,
+ STATE#{OTHER => VAR+INCVAL} end).
+
+-else. % DEFAULT!
+ -define(merge_with_stats(STATE), STATE).
+ -define(update_max_qlen(_QLEN, STATE), STATE).
+ -define(update_calls_or_casts(_CALL_OR_CAST, _INC, STATE), STATE).
+ -define(update_max_time(_TIME, STATE), STATE).
+ -define(update_other(_OTHER, _VAR, _INCVAL, STATE), STATE).
+-endif.
+
+%%%-----------------------------------------------------------------
+%%% These macros enable callbacks that make it possible to analyse
+%%% the overload protection behaviour from outside the handler
+%%% process (including dropped requests on the client side).
+%%% An external callback module (?OBSERVER_MOD) is required which
+%%% is not part of the kernel application. For this reason, these
+%%% callbacks should not be included in code to be officially released.
+
+%%-define(OBSERVER_MOD, logger_test).
+-ifdef(OBSERVER_MOD).
+ -define(start_observation(NAME), ?OBSERVER:start_observation(NAME)).
+ -define(observe(NAME,EVENT), ?OBSERVER:observe(NAME,EVENT)).
+
+-else. % DEFAULT!
+ -define(start_observation(_NAME), ok).
+ -define(observe(_NAME,_EVENT), ok).
+-endif.
+%%! <---
diff --git a/lib/kernel/src/logger_handler_watcher.erl b/lib/kernel/src/logger_handler_watcher.erl
new file mode 100644
index 0000000000..b75c74c643
--- /dev/null
+++ b/lib/kernel/src/logger_handler_watcher.erl
@@ -0,0 +1,113 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_handler_watcher).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0]).
+-export([register_handler/2]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]).
+
+-define(SERVER, ?MODULE).
+
+-record(state, {handlers}).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+-spec start_link() -> {ok, Pid :: pid()} |
+ {error, Error :: {already_started, pid()}} |
+ {error, Error :: term()} |
+ ignore.
+start_link() ->
+ gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+
+-spec register_handler(Id::logger:handler_id(),Pid::pid()) -> ok.
+register_handler(Id,Pid) ->
+ gen_server:call(?SERVER,{register,Id,Pid}).
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+-spec init(Args :: term()) -> {ok, State :: term()} |
+ {ok, State :: term(), Timeout :: timeout()} |
+ {ok, State :: term(), hibernate} |
+ {stop, Reason :: term()} |
+ ignore.
+init([]) ->
+ process_flag(trap_exit, true),
+ {ok, #state{handlers=[]}}.
+
+-spec handle_call(Request :: term(), From :: {pid(), term()}, State :: term()) ->
+ {reply, Reply :: term(), NewState :: term()} |
+ {reply, Reply :: term(), NewState :: term(), Timeout :: timeout()} |
+ {reply, Reply :: term(), NewState :: term(), hibernate} |
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), Timeout :: timeout()} |
+ {noreply, NewState :: term(), hibernate} |
+ {stop, Reason :: term(), Reply :: term(), NewState :: term()} |
+ {stop, Reason :: term(), NewState :: term()}.
+handle_call({register,Id,Pid}, _From, #state{handlers=Hs}=State) ->
+ Ref = erlang:monitor(process,Pid),
+ Hs1 = lists:keystore(Id,1,Hs,{Id,Ref}),
+ {reply, ok, State#state{handlers=Hs1}}.
+
+-spec handle_cast(Request :: term(), State :: term()) ->
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), Timeout :: timeout()} |
+ {noreply, NewState :: term(), hibernate} |
+ {stop, Reason :: term(), NewState :: term()}.
+handle_cast(_Request, State) ->
+ {noreply, State}.
+
+-spec handle_info(Info :: timeout() | term(), State :: term()) ->
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), Timeout :: timeout()} |
+ {noreply, NewState :: term(), hibernate} |
+ {stop, Reason :: normal | term(), NewState :: term()}.
+handle_info({'DOWN',Ref,process,_,shutdown}, #state{handlers=Hs}=State) ->
+ case lists:keytake(Ref,2,Hs) of
+ {value,{Id,Ref},Hs1} ->
+ %% Probably terminated by supervisor. Remove the handler to avoid
+ %% error printouts due to failing handler.
+ _ = case logger:get_handler_config(Id) of
+ {ok,_} ->
+ logger:remove_handler(Id);
+ _ ->
+ ok
+ end,
+ {noreply,State#state{handlers=Hs1}};
+ false ->
+ {noreply, State}
+ end;
+handle_info({'DOWN',Ref,process,_,_OtherReason}, #state{handlers=Hs}=State) ->
+ {noreply,State#state{handlers=lists:keydelete(Ref,2,Hs)}};
+handle_info(_Other,State) ->
+ {noreply,State}.
+
+-spec terminate(Reason :: normal | shutdown | {shutdown, term()} | term(),
+ State :: term()) -> any().
+terminate(_Reason, _State) ->
+ ok.
diff --git a/lib/kernel/src/logger_internal.hrl b/lib/kernel/src/logger_internal.hrl
new file mode 100644
index 0000000000..d96a4ac78b
--- /dev/null
+++ b/lib/kernel/src/logger_internal.hrl
@@ -0,0 +1,101 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-include_lib("kernel/include/logger.hrl").
+-define(LOGGER_TABLE,logger).
+-define(PRIMARY_KEY,'$primary_config$').
+-define(HANDLER_KEY,'$handler_config$').
+-define(LOGGER_META_KEY,'$logger_metadata$').
+-define(STANDARD_HANDLER, default).
+-define(DEFAULT_HANDLER_FILTERS,?DEFAULT_HANDLER_FILTERS([otp])).
+-define(DEFAULT_HANDLER_FILTERS(Domain),
+ [{remote_gl,{fun logger_filters:remote_gl/2,stop}},
+ {domain,{fun logger_filters:domain/2,{log,super,Domain}}},
+ {no_domain,{fun logger_filters:domain/2,{log,undefined,[]}}}]).
+-define(DEFAULT_FORMATTER,logger_formatter).
+-define(DEFAULT_FORMAT_CONFIG,#{legacy_header=>true,
+ single_line=>false}).
+-define(DEFAULT_FORMAT_TEMPLATE_HEADER,
+ [[logger_formatter,header],"\n",msg,"\n"]).
+-define(DEFAULT_FORMAT_TEMPLATE_SINGLE,
+ [time," ",level,": ",msg,"\n"]).
+-define(DEFAULT_FORMAT_TEMPLATE,
+ [time," ",level,":\n",msg,"\n"]).
+
+-define(DEFAULT_LOGGER_CALL_TIMEOUT, infinity).
+
+-define(LOG_INTERNAL(Level,Report),
+ case logger:allow(Level,?MODULE) of
+ true ->
+ %% Spawn this to avoid deadlocks
+ _ = spawn(logger,macro_log,[?LOCATION,Level,Report,
+ logger:add_default_metadata(#{})]),
+ ok;
+ false ->
+ ok
+ end).
+
+%%%-----------------------------------------------------------------
+%%% Levels
+%%% Using same as syslog
+-define(LEVELS,[none,
+ emergency,
+ alert,
+ critical,
+ error,
+ warning,
+ notice,
+ info,
+ debug,
+ all]).
+-define(LOG_NONE,-1).
+-define(EMERGENCY,0).
+-define(ALERT,1).
+-define(CRITICAL,2).
+-define(ERROR,3).
+-define(WARNING,4).
+-define(NOTICE,5).
+-define(INFO,6).
+-define(DEBUG,7).
+-define(LOG_ALL,10).
+
+-define(IS_LEVEL(L),
+ (L=:=emergency orelse
+ L=:=alert orelse
+ L=:=critical orelse
+ L=:=error orelse
+ L=:=warning orelse
+ L=:=notice orelse
+ L=:=info orelse
+ L=:=debug)).
+
+-define(IS_MSG(Msg),
+ ((is_tuple(Msg) andalso tuple_size(Msg)==2)
+ andalso
+ (is_list(element(1,Msg)) andalso is_list(element(2,Msg)))
+ orelse
+ (element(1,Msg)==report andalso ?IS_REPORT(element(2,Msg)))
+ orelse
+ (element(1,Msg)==string andalso ?IS_STRING(element(2,Msg))))).
+
+-define(IS_REPORT(Report),
+ (is_map(Report) orelse (is_list(Report) andalso is_tuple(hd(Report))))).
+
+-define(IS_STRING(String),
+ (is_list(String) orelse is_binary(String))).
diff --git a/lib/kernel/src/logger_server.erl b/lib/kernel/src/logger_server.erl
new file mode 100644
index 0000000000..a1d40f1123
--- /dev/null
+++ b/lib/kernel/src/logger_server.erl
@@ -0,0 +1,527 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_server).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0,
+ add_handler/3, remove_handler/1,
+ add_filter/2, remove_filter/2,
+ set_module_level/2, unset_module_level/0,
+ unset_module_level/1, cache_module_level/1,
+ set_config/2, set_config/3, update_config/2,
+ update_formatter_config/2]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2]).
+
+-include("logger_internal.hrl").
+
+-define(SERVER, logger).
+-define(LOGGER_SERVER_TAG, '$logger_cb_process').
+
+-record(state, {tid, async_req, async_req_queue}).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+start_link() ->
+ gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+
+add_handler(Id,Module,Config0) ->
+ try {check_id(Id),check_mod(Module)} of
+ {ok,ok} ->
+ case sanity_check(Id,Config0) of
+ ok ->
+ Default = default_config(Id,Module),
+ Config = maps:merge(Default,Config0),
+ call({add_handler,Id,Module,Config});
+ Error ->
+ Error
+ end
+ catch throw:Error ->
+ {error,Error}
+ end.
+
+remove_handler(HandlerId) ->
+ call({remove_handler,HandlerId}).
+
+add_filter(Owner,Filter) ->
+ case sanity_check(Owner,filters,[Filter]) of
+ ok -> call({add_filter,Owner,Filter});
+ Error -> Error
+ end.
+
+remove_filter(Owner,FilterId) ->
+ call({remove_filter,Owner,FilterId}).
+
+set_module_level(Modules,Level) when is_list(Modules) ->
+ case lists:all(fun(M) -> is_atom(M) end,Modules) of
+ true ->
+ case sanity_check(primary,level,Level) of
+ ok -> call({set_module_level,Modules,Level});
+ Error -> Error
+ end;
+ false ->
+ {error,{not_a_list_of_modules,Modules}}
+ end;
+set_module_level(Modules,_) ->
+ {error,{not_a_list_of_modules,Modules}}.
+
+unset_module_level() ->
+ call({unset_module_level,all}).
+
+unset_module_level(Modules) when is_list(Modules) ->
+ case lists:all(fun(M) -> is_atom(M) end,Modules) of
+ true ->
+ call({unset_module_level,Modules});
+ false ->
+ {error,{not_a_list_of_modules,Modules}}
+ end;
+unset_module_level(Modules) ->
+ {error,{not_a_list_of_modules,Modules}}.
+
+cache_module_level(Module) ->
+ gen_server:cast(?SERVER,{cache_module_level,Module}).
+
+set_config(Owner,Key,Value) ->
+ update_config(Owner,#{Key=>Value}).
+
+set_config(Owner,Config) ->
+ case sanity_check(Owner,Config) of
+ ok ->
+ call({set_config,Owner,Config});
+ Error ->
+ Error
+ end.
+
+update_config(Owner, Config) ->
+ case sanity_check(Owner,Config) of
+ ok ->
+ call({update_config,Owner,Config});
+ Error ->
+ Error
+ end.
+
+update_formatter_config(HandlerId, FormatterConfig)
+ when is_map(FormatterConfig) ->
+ call({update_formatter_config,HandlerId,FormatterConfig});
+update_formatter_config(_HandlerId, FormatterConfig) ->
+ {error,{invalid_formatter_config,FormatterConfig}}.
+
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+init([]) ->
+ process_flag(trap_exit, true),
+ put(?LOGGER_SERVER_TAG,true),
+ Tid = logger_config:new(?LOGGER_TABLE),
+ PrimaryConfig = maps:merge(default_config(primary),
+ #{handlers=>[simple]}),
+ logger_config:create(Tid,primary,PrimaryConfig),
+ SimpleConfig0 = maps:merge(default_config(simple,logger_simple_h),
+ #{filter_default=>stop,
+ filters=>?DEFAULT_HANDLER_FILTERS}),
+ %% If this fails, then the node should crash
+ {ok,SimpleConfig} = logger_simple_h:adding_handler(SimpleConfig0),
+ logger_config:create(Tid,simple,SimpleConfig),
+ {ok, #state{tid=Tid, async_req_queue = queue:new()}}.
+
+handle_call({add_handler,Id,Module,HConfig}, From, #state{tid=Tid}=State) ->
+ case logger_config:exist(Tid,Id) of
+ true ->
+ {reply,{error,{already_exist,Id}},State};
+ false ->
+ call_h_async(
+ fun() ->
+ %% inform the handler
+ call_h(Module,adding_handler,[HConfig],{ok,HConfig})
+ end,
+ fun({ok,HConfig1}) ->
+ %% We know that the call_h would have loaded the module
+ %% if it existed, so it is safe here to call function_exported
+ %% to find out if this is a valid handler
+ case erlang:function_exported(Module, log, 2) of
+ true ->
+ logger_config:create(Tid,Id,HConfig1),
+ {ok,Config} = logger_config:get(Tid,primary),
+ Handlers = maps:get(handlers,Config,[]),
+ logger_config:set(Tid,primary,
+ Config#{handlers=>[Id|Handlers]});
+ false ->
+ {error,{invalid_handler,
+ {function_not_exported,
+ {Module,log,2}}}}
+ end;
+ ({error,HReason}) ->
+ {error,{handler_not_added,HReason}}
+ end,From,State)
+ end;
+handle_call({remove_handler,HandlerId}, From, #state{tid=Tid}=State) ->
+ case logger_config:get(Tid,HandlerId) of
+ {ok,#{module:=Module}=HConfig} ->
+ {ok,Config} = logger_config:get(Tid,primary),
+ Handlers0 = maps:get(handlers,Config,[]),
+ Handlers = lists:delete(HandlerId,Handlers0),
+ call_h_async(
+ fun() ->
+ %% inform the handler
+ call_h(Module,removing_handler,[HConfig],ok)
+ end,
+ fun(_Res) ->
+ logger_config:set(Tid,primary,Config#{handlers=>Handlers}),
+ logger_config:delete(Tid,HandlerId),
+ ok
+ end,From,State);
+ _ ->
+ {reply,{error,{not_found,HandlerId}},State}
+ end;
+handle_call({add_filter,Id,Filter}, _From,#state{tid=Tid}=State) ->
+ Reply = do_add_filter(Tid,Id,Filter),
+ {reply,Reply,State};
+handle_call({remove_filter,Id,FilterId}, _From, #state{tid=Tid}=State) ->
+ Reply = do_remove_filter(Tid,Id,FilterId),
+ {reply,Reply,State};
+handle_call({update_config,primary,NewConfig}, _From, #state{tid=Tid}=State) ->
+ {ok,OldConfig} = logger_config:get(Tid,primary),
+ Config = maps:merge(OldConfig,NewConfig),
+ {reply,logger_config:set(Tid,primary,Config),State};
+handle_call({update_config,HandlerId,NewConfig}, From, #state{tid=Tid}=State) ->
+ case logger_config:get(Tid,HandlerId) of
+ {ok,#{module:=Module}=OldConfig} ->
+ Config = maps:merge(OldConfig,NewConfig),
+ call_h_async(
+ fun() ->
+ call_h(Module,changing_config,[OldConfig,Config],
+ {ok,Config})
+ end,
+ fun({ok,Config1}) ->
+ logger_config:set(Tid,HandlerId,Config1);
+ (Error) ->
+ Error
+ end,From,State);
+ Error ->
+ {reply,Error,State}
+ end;
+handle_call({set_config,primary,Config0}, _From, #state{tid=Tid}=State) ->
+ Config = maps:merge(default_config(primary),Config0),
+ {ok,#{handlers:=Handlers}} = logger_config:get(Tid,primary),
+ Reply = logger_config:set(Tid,primary,Config#{handlers=>Handlers}),
+ {reply,Reply,State};
+handle_call({set_config,HandlerId,Config0}, From, #state{tid=Tid}=State) ->
+ case logger_config:get(Tid,HandlerId) of
+ {ok,#{module:=Module}=OldConfig} ->
+ Config = maps:merge(default_config(HandlerId,Module),Config0),
+ call_h_async(
+ fun() ->
+ call_h(Module,changing_config,[OldConfig,Config],
+ {ok,Config})
+ end,
+ fun({ok,Config1}) ->
+ logger_config:set(Tid,HandlerId,Config1);
+ (Error) ->
+ Error
+ end,From,State);
+ _ ->
+ {reply,{error,{not_found,HandlerId}},State}
+ end;
+handle_call({update_formatter_config,HandlerId,NewFConfig},_From,
+ #state{tid=Tid}=State) ->
+ Reply =
+ case logger_config:get(Tid,HandlerId) of
+ {ok,#{formatter:={FMod,OldFConfig}}=Config} ->
+ try
+ FConfig = maps:merge(OldFConfig,NewFConfig),
+ check_formatter({FMod,FConfig}),
+ logger_config:set(Tid,HandlerId,
+ Config#{formatter=>{FMod,FConfig}})
+ catch throw:Reason -> {error,Reason}
+ end;
+ _ ->
+ {error,{not_found,HandlerId}}
+ end,
+ {reply,Reply,State};
+handle_call({set_module_level,Modules,Level}, _From, #state{tid=Tid}=State) ->
+ Reply = logger_config:set_module_level(Tid,Modules,Level),
+ {reply,Reply,State};
+handle_call({unset_module_level,Modules}, _From, #state{tid=Tid}=State) ->
+ Reply = logger_config:unset_module_level(Tid,Modules),
+ {reply,Reply,State}.
+
+handle_cast({async_req_reply,_Ref,_Reply} = Reply,State) ->
+ call_h_reply(Reply,State);
+handle_cast({cache_module_level,Module}, #state{tid=Tid}=State) ->
+ logger_config:cache_module_level(Tid,Module),
+ {noreply, State}.
+
+%% Interface for those who can't call the API - e.g. the emulator, or
+%% places related to code loading.
+%%
+%% This can also be log events from remote nodes which are sent from
+%% logger.erl when the group leader of the client process is on a
+%% same node as the client process itself.
+handle_info({log,Level,Format,Args,Meta}, State) ->
+ logger:log(Level,Format,Args,Meta),
+ {noreply, State};
+handle_info({log,Level,Report,Meta}, State) ->
+ logger:log(Level,Report,Meta),
+ {noreply, State};
+handle_info({Ref,_Reply},State) when is_reference(Ref) ->
+ %% Assuming this is a timed-out gen_server reply - ignoring
+ {noreply, State};
+handle_info({'DOWN',_Ref,_Proc,_Pid,_Reason} = Down,State) ->
+ call_h_reply(Down,State);
+handle_info(Unexpected,State) when element(1,Unexpected) == 'EXIT' ->
+ %% The simple handler will send an 'EXIT' message when it is replaced
+ %% We may as well ignore all 'EXIT' messages that we get
+ ?LOG_INTERNAL(debug,
+ [{logger,got_unexpected_message},
+ {process,?SERVER},
+ {message,Unexpected}]),
+ {noreply,State};
+handle_info(Unexpected,State) ->
+ ?LOG_INTERNAL(info,
+ [{logger,got_unexpected_message},
+ {process,?SERVER},
+ {message,Unexpected}]),
+ {noreply,State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+call(Request) ->
+ Action = element(1,Request),
+ case get(?LOGGER_SERVER_TAG) of
+ true when
+ Action == add_handler; Action == remove_handler;
+ Action == add_filter; Action == remove_filter;
+ Action == update_config; Action == set_config ->
+ {error,{attempting_syncronous_call_to_self,Request}};
+ _ ->
+ gen_server:call(?SERVER,Request,?DEFAULT_LOGGER_CALL_TIMEOUT)
+ end.
+
+do_add_filter(Tid,Id,{FId,_} = Filter) ->
+ case logger_config:get(Tid,Id) of
+ {ok,Config} ->
+ Filters = maps:get(filters,Config,[]),
+ case lists:keymember(FId,1,Filters) of
+ true ->
+ {error,{already_exist,FId}};
+ false ->
+ logger_config:set(Tid,Id,Config#{filters=>[Filter|Filters]})
+ end;
+ Error ->
+ Error
+ end.
+
+do_remove_filter(Tid,Id,FilterId) ->
+ case logger_config:get(Tid,Id) of
+ {ok,Config} ->
+ Filters0 = maps:get(filters,Config,[]),
+ case lists:keytake(FilterId,1,Filters0) of
+ {value,_,Filters} ->
+ logger_config:set(Tid,Id,Config#{filters=>Filters});
+ false ->
+ {error,{not_found,FilterId}}
+ end;
+ Error ->
+ Error
+ end.
+
+default_config(primary) ->
+ #{level=>notice,
+ filters=>[],
+ filter_default=>log};
+default_config(Id) ->
+ #{id=>Id,
+ level=>all,
+ filters=>[],
+ filter_default=>log,
+ formatter=>{?DEFAULT_FORMATTER,#{}}}.
+default_config(Id,Module) ->
+ (default_config(Id))#{module=>Module}.
+
+sanity_check(Owner,Key,Value) ->
+ sanity_check_1(Owner,[{Key,Value}]).
+
+sanity_check(HandlerId,Config) when is_map(Config) ->
+ sanity_check_1(HandlerId,maps:to_list(Config));
+sanity_check(_,Config) ->
+ {error,{invalid_config,Config}}.
+
+sanity_check_1(Owner,Config) when is_list(Config) ->
+ try
+ Type = get_type(Owner),
+ check_config(Type,Config)
+ catch throw:Error -> {error,Error}
+ end.
+
+get_type(primary) ->
+ primary;
+get_type(Id) ->
+ check_id(Id),
+ handler.
+
+check_config(Owner,[{level,Level}|Config]) ->
+ check_level(Level),
+ check_config(Owner,Config);
+check_config(Owner,[{filters,Filters}|Config]) ->
+ check_filters(Filters),
+ check_config(Owner,Config);
+check_config(Owner,[{filter_default,FD}|Config]) ->
+ check_filter_default(FD),
+ check_config(Owner,Config);
+check_config(handler,[{formatter,Formatter}|Config]) ->
+ check_formatter(Formatter),
+ check_config(handler,Config);
+check_config(primary,[C|_]) ->
+ throw({invalid_primary_config,C});
+check_config(handler,[{_,_}|Config]) ->
+ %% Arbitrary config elements are allowed for handlers
+ check_config(handler,Config);
+check_config(_,[]) ->
+ ok.
+
+check_id(Id) when is_atom(Id) ->
+ ok;
+check_id(Id) ->
+ throw({invalid_id,Id}).
+
+check_mod(Mod) when is_atom(Mod) ->
+ ok;
+check_mod(Mod) ->
+ throw({invalid_module,Mod}).
+
+check_level(Level) ->
+ case lists:member(Level,?LEVELS) of
+ true ->
+ ok;
+ false ->
+ throw({invalid_level,Level})
+ end.
+
+check_filters([{Id,{Fun,_Args}}|Filters]) when is_atom(Id), is_function(Fun,2) ->
+ check_filters(Filters);
+check_filters([Filter|_]) ->
+ throw({invalid_filter,Filter});
+check_filters([]) ->
+ ok;
+check_filters(Filters) ->
+ throw({invalid_filters,Filters}).
+
+check_filter_default(FD) when FD==stop; FD==log ->
+ ok;
+check_filter_default(FD) ->
+ throw({invalid_filter_default,FD}).
+
+check_formatter({Mod,Config}) ->
+ check_mod(Mod),
+ try Mod:check_config(Config) of
+ ok -> ok;
+ {error,Error} -> throw(Error)
+ catch
+ C:R:S ->
+ case {C,R,S} of
+ {error,undef,[{Mod,check_config,[Config],_}|_]} ->
+ ok;
+ _ ->
+ throw({callback_crashed,
+ {C,R,logger:filter_stacktrace(?MODULE,S)}})
+ end
+ end;
+check_formatter(Formatter) ->
+ throw({invalid_formatter,Formatter}).
+
+call_h(Module, Function, Args, DefRet) ->
+ %% Not calling code:ensure_loaded + erlang:function_exported here,
+ %% since in some rare terminal cases, the code_server might not
+ %% exist and we'll get a deadlock in removing the handler.
+ try apply(Module, Function, Args)
+ catch
+ C:R:S ->
+ case {C,R,S} of
+ {error,undef,[{Module,Function,Args,_}|_]} ->
+ DefRet;
+ _ ->
+ ST = logger:filter_stacktrace(?MODULE,S),
+ ?LOG_INTERNAL(error,
+ [{logger,callback_crashed},
+ {process,?SERVER},
+ {reason,{C,R,ST}}]),
+ {error,{callback_crashed,{C,R,ST}}}
+ end
+ end.
+
+%% There are all sort of API functions that can cause deadlocks if called
+%% from the handler callbacks. So we spawn a process that does the request
+%% for the logger_server. There are still APIs that will cause problems,
+%% namely logger:add_handler
+call_h_async(AsyncFun,PostFun,From,#state{ async_req = undefined } = State) ->
+ Parent = self(),
+ {Pid, Ref} = spawn_monitor(
+ fun() ->
+ put(?LOGGER_SERVER_TAG,true),
+ receive Ref -> Ref end,
+ gen_server:cast(Parent, {async_req_reply, Ref, AsyncFun()})
+ end),
+ Pid ! Ref,
+ {noreply,State#state{ async_req = {Ref,PostFun,From} }};
+call_h_async(AsyncFun,PostFun,From,#state{ async_req_queue = Q } = State) ->
+ {noreply,State#state{ async_req_queue = queue:in({AsyncFun,PostFun,From},Q) }}.
+
+call_h_reply({async_req_reply,Ref,Reply},
+ #state{ async_req = {Ref,PostFun,From}, async_req_queue = Q} = State) ->
+ erlang:demonitor(Ref,[flush]),
+ _ = gen_server:reply(From, PostFun(Reply)),
+ {Value,NewQ} = queue:out(Q),
+ NewState = State#state{ async_req = undefined,
+ async_req_queue = NewQ },
+ case Value of
+ {value,{AsyncFun,NPostFun,NFrom}} ->
+ call_h_async(AsyncFun,NPostFun,NFrom,NewState);
+ empty ->
+ {noreply,NewState}
+ end;
+call_h_reply({'DOWN',Ref,_Proc,Pid,Reason}, #state{ async_req = {Ref,_PostFun,_From}} = State) ->
+ %% This clause should only be triggered if someone explicitly sends an exit signal
+ %% to the spawned process. It is only here to make sure that the logger_server does
+ %% not deadlock if that happens.
+ ?LOG_INTERNAL(error,
+ [{logger,process_exited},
+ {process,Pid},
+ {reason,Reason}]),
+ call_h_reply(
+ {async_req_reply,Ref,{error,{logger_process_exited,Pid,Reason}}},
+ State);
+call_h_reply(Unexpected,State) ->
+ ?LOG_INTERNAL(info,
+ [{logger,got_unexpected_message},
+ {process,?SERVER},
+ {message,Unexpected}]),
+ {noreply,State}.
diff --git a/lib/kernel/src/logger_simple_h.erl b/lib/kernel/src/logger_simple_h.erl
new file mode 100644
index 0000000000..8b51dd8569
--- /dev/null
+++ b/lib/kernel/src/logger_simple_h.erl
@@ -0,0 +1,212 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_simple_h).
+
+-export([adding_handler/1, removing_handler/1, log/2]).
+
+%% This module implements a simple handler for logger. It is the
+%% default used during system start.
+
+%%%-----------------------------------------------------------------
+%%% Logger callback
+
+adding_handler(#{id:=simple}=Config) ->
+ Me = self(),
+ case whereis(?MODULE) of
+ undefined ->
+ {Pid,Ref} = spawn_opt(fun() -> init(Me) end,
+ [link,monitor,{message_queue_data,off_heap}]),
+ receive
+ {'DOWN',Ref,process,Pid,Reason} ->
+ {error,Reason};
+ {Pid,started} ->
+ erlang:demonitor(Ref),
+ {ok,Config}
+ end;
+ _ ->
+ {error,{handler_process_name_already_exists,?MODULE}}
+ end.
+
+removing_handler(#{id:=simple}) ->
+ case whereis(?MODULE) of
+ undefined ->
+ ok;
+ Pid ->
+ Ref = erlang:monitor(process,Pid),
+ unlink(Pid),
+ Pid ! stop,
+ receive {'DOWN',Ref,process,Pid,_} ->
+ ok
+ end
+ end.
+
+log(#{meta:=#{error_logger:=#{tag:=info_report,type:=Type}}},_Config)
+ when Type=/=std_info ->
+ %% Skip info reports that are not 'std_info' (ref simple logger in
+ %% error_logger)
+ ok;
+log(#{msg:=_,meta:=#{time:=_}}=Log,_Config) ->
+ _ = case whereis(?MODULE) of
+ undefined ->
+ %% Is the node on the way down? Real emergency?
+ %% Log directly from client just to get it out
+ do_log(
+ #{level=>error,
+ msg=>{report,{error,simple_handler_process_dead}},
+ meta=>#{time=>erlang:system_time(microsecond)}}),
+ do_log(Log);
+ _ ->
+ ?MODULE ! {log,Log}
+ end,
+ ok;
+log(_,_) ->
+ %% Unexpected log.
+ %% We don't want to crash the simple logger, so ignore this.
+ ok.
+
+%%%-----------------------------------------------------------------
+%%% Process
+init(Starter) ->
+ register(?MODULE,self()),
+ Starter ! {self(),started},
+ loop(#{buffer_size=>10,dropped=>0,buffer=>[]}).
+
+loop(Buffer) ->
+ receive
+ stop ->
+ %% We replay the logger messages of there is
+ %% a default handler when the simple handler
+ %% is removed.
+ case logger:get_handler_config(default) of
+ {ok, _} ->
+ replay_buffer(Buffer);
+ _ ->
+ ok
+ end;
+ {log,#{msg:=_,meta:=#{time:=_}}=Log} ->
+ do_log(Log),
+ loop(update_buffer(Buffer,Log));
+ _ ->
+ %% Unexpected message - flush it!
+ loop(Buffer)
+ end.
+
+update_buffer(#{buffer_size:=0,dropped:=D}=Buffer,_Log) ->
+ Buffer#{dropped=>D+1};
+update_buffer(#{buffer_size:=S,buffer:=B}=Buffer,Log) ->
+ Buffer#{buffer_size=>S-1,buffer=>[Log|B]}.
+
+replay_buffer(#{ dropped := D, buffer := Buffer }) ->
+ lists:foreach(
+ fun F(#{msg := {Tag, Msg}} = L) when Tag =:= string; Tag =:= report ->
+ F(L#{ msg := Msg });
+ F(#{ level := Level, msg := Msg, meta := MD}) ->
+ logger:log(Level, Msg, MD)
+ end, lists:reverse(Buffer, drop_msg(D))).
+
+drop_msg(0) ->
+ [];
+drop_msg(N) ->
+ [#{level=>info,
+ msg=>{"Simple handler buffer full, dropped ~w messages",[N]},
+ meta=>#{time=>erlang:system_time(microsecond)}}].
+
+%%%-----------------------------------------------------------------
+%%% Internal
+
+%% Can't do io_lib:format
+
+do_log(#{msg:={report,Report},
+ meta:=#{time:=T,error_logger:=#{type:=Type}}}) ->
+ display_date(T),
+ display_report(Type,Report);
+do_log(#{msg:=Msg,meta:=#{time:=T}}) ->
+ display_date(T),
+ display(Msg).
+
+display_date(Timestamp) when is_integer(Timestamp) ->
+ Micro = Timestamp rem 1000000,
+ Sec = Timestamp div 1000000,
+ {{Y,Mo,D},{H,Mi,S}} = erlang:universaltime_to_localtime(
+ erlang:posixtime_to_universaltime(Sec)),
+ erlang:display_string(
+ integer_to_list(Y) ++ "-" ++
+ pad(Mo,2) ++ "-" ++
+ pad(D,2) ++ " " ++
+ pad(H,2) ++ ":" ++
+ pad(Mi,2) ++ ":" ++
+ pad(S,2) ++ "." ++
+ pad(Micro,6) ++ " ").
+
+pad(Int,Size) when is_integer(Int) ->
+ pad(integer_to_list(Int),Size);
+pad(Str,Size) when length(Str)==Size ->
+ Str;
+pad(Str,Size) ->
+ pad([$0|Str],Size).
+
+display({string,Chardata}) ->
+ try unicode:characters_to_list(Chardata) of
+ String -> erlang:display_string(String), erlang:display_string("\n")
+ catch _:_ -> erlang:display(Chardata)
+ end;
+display({report,Report}) when is_map(Report) ->
+ display_report(maps:to_list(Report));
+display({report,Report}) ->
+ display_report(Report);
+display({F, A}) when is_list(F), is_list(A) ->
+ erlang:display_string(F ++ "\n"),
+ [begin
+ erlang:display_string("\t"),
+ erlang:display(Arg)
+ end || Arg <- A],
+ ok.
+
+display_report(Atom, A) when is_atom(Atom) ->
+ %% The widest atom seems to be 'supervisor_report' at 17.
+ ColumnWidth = 20,
+ AtomString = atom_to_list(Atom),
+ AtomLength = length(AtomString),
+ Padding = lists:duplicate(ColumnWidth - AtomLength, $\s),
+ erlang:display_string(AtomString ++ Padding),
+ display_report(A);
+display_report(F, A) ->
+ erlang:display({F, A}).
+
+display_report([A, []]) ->
+ %% Special case for crash reports when process has no links
+ display_report(A);
+display_report(A = [_|_]) ->
+ case lists:all(fun({Key,_Value}) -> is_atom(Key); (_) -> false end, A) of
+ true ->
+ erlang:display_string("\n"),
+ lists:foreach(
+ fun({Key, Value}) ->
+ erlang:display_string(
+ " " ++
+ atom_to_list(Key) ++
+ ": "),
+ erlang:display(Value)
+ end, A);
+ false ->
+ erlang:display(A)
+ end;
+display_report(A) ->
+ erlang:display(A).
diff --git a/lib/kernel/src/logger_std_h.erl b/lib/kernel/src/logger_std_h.erl
new file mode 100644
index 0000000000..66fa6b6ab6
--- /dev/null
+++ b/lib/kernel/src/logger_std_h.erl
@@ -0,0 +1,828 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_std_h).
+
+-behaviour(gen_server).
+
+-include("logger.hrl").
+-include("logger_internal.hrl").
+-include("logger_h_common.hrl").
+
+-include_lib("kernel/include/file.hrl").
+
+%% API
+-export([start_link/3, info/1, filesync/1, reset/1]).
+
+%% gen_server and proc_lib callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+%% logger callbacks
+-export([log/2, adding_handler/1, removing_handler/1, changing_config/2]).
+
+%% handler internal
+-export([log_handler_info/4]).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+%%%-----------------------------------------------------------------
+%%% Start a standard handler process and link to caller.
+%%% This function is called by the kernel supervisor when this
+%%% handler process gets added
+-spec start_link(Name, Config, HandlerState) -> {ok,Pid} | {error,Reason} when
+ Name :: atom(),
+ Config :: logger:handler_config(),
+ HandlerState :: map(),
+ Pid :: pid(),
+ Reason :: term().
+
+start_link(Name, Config, HandlerState) ->
+ proc_lib:start_link(?MODULE,init,[[Name,Config,HandlerState]]).
+
+%%%-----------------------------------------------------------------
+%%%
+-spec filesync(Name) -> ok | {error,Reason} when
+ Name :: atom(),
+ Reason :: handler_busy | {badarg,term()}.
+
+filesync(Name) when is_atom(Name) ->
+ try
+ gen_server:call(?name_to_reg_name(?MODULE,Name),
+ filesync, ?DEFAULT_CALL_TIMEOUT)
+ catch
+ _:{timeout,_} -> {error,handler_busy}
+ end;
+filesync(Name) ->
+ {error,{badarg,{filesync,[Name]}}}.
+
+%%%-----------------------------------------------------------------
+%%%
+-spec info(Name) -> Info | {error,Reason} when
+ Name :: atom(),
+ Info :: term(),
+ Reason :: handler_busy | {badarg,term()}.
+
+info(Name) when is_atom(Name) ->
+ try
+ gen_server:call(?name_to_reg_name(?MODULE,Name),
+ info, ?DEFAULT_CALL_TIMEOUT)
+ catch
+ _:{timeout,_} -> {error,handler_busy}
+ end;
+info(Name) ->
+ {error,{badarg,{info,[Name]}}}.
+
+%%%-----------------------------------------------------------------
+%%%
+-spec reset(Name) -> ok | {error,Reason} when
+ Name :: atom(),
+ Reason :: handler_busy | {badarg,term()}.
+
+reset(Name) when is_atom(Name) ->
+ try
+ gen_server:call(?name_to_reg_name(?MODULE,Name),
+ reset, ?DEFAULT_CALL_TIMEOUT)
+ catch
+ _:{timeout,_} -> {error,handler_busy}
+ end;
+reset(Name) ->
+ {error,{badarg,{reset,[Name]}}}.
+
+
+%%%===================================================================
+%%% logger callbacks
+%%%===================================================================
+
+%%%-----------------------------------------------------------------
+%%% Handler being added
+adding_handler(#{id:=Name}=Config) ->
+ case check_config(adding, Config) of
+ {ok, Config1} ->
+ %% create initial handler state by merging defaults with config
+ HConfig = maps:get(config, Config1, #{}),
+ HState = maps:merge(get_init_state(), HConfig),
+ case logger_h_common:overload_levels_ok(HState) of
+ true ->
+ start(Name, Config1, HState);
+ false ->
+ #{sync_mode_qlen := SMQL,
+ drop_mode_qlen := DMQL,
+ flush_qlen := FQL} = HState,
+ {error,{invalid_levels,{SMQL,DMQL,FQL}}}
+ end;
+ Error ->
+ Error
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Updating handler config
+changing_config(OldConfig=#{id:=Name, config:=OldHConfig},
+ NewConfig=#{id:=Name}) ->
+ #{type:=Type, handler_pid:=HPid, mode_tab:=ModeTab} = OldHConfig,
+ NewHConfig = maps:get(config, NewConfig, #{}),
+ case maps:get(type, NewHConfig, Type) of
+ Type ->
+ NewHConfig1 = NewHConfig#{type=>Type,
+ handler_pid=>HPid,
+ mode_tab=>ModeTab},
+ changing_config1(HPid, OldConfig,
+ NewConfig#{config=>NewHConfig1});
+ _ ->
+ {error,{illegal_config_change,OldConfig,NewConfig}}
+ end;
+changing_config(OldConfig, NewConfig) ->
+ {error,{illegal_config_change,OldConfig,NewConfig}}.
+
+changing_config1(HPid, OldConfig, NewConfig) ->
+ case check_config(changing, NewConfig) of
+ Result = {ok,NewConfig1} ->
+ try gen_server:call(HPid, {change_config,OldConfig,NewConfig1},
+ ?DEFAULT_CALL_TIMEOUT) of
+ ok -> Result;
+ HError -> HError
+ catch
+ _:{timeout,_} -> {error,handler_busy}
+ end;
+ Error ->
+ Error
+ end.
+
+check_config(adding, Config) ->
+ %% Merge in defaults on handler level
+ HConfig0 = maps:get(config, Config, #{}),
+ HConfig = maps:merge(#{type => standard_io},
+ HConfig0),
+ case check_h_config(maps:to_list(HConfig)) of
+ ok ->
+ {ok,Config#{config=>HConfig}};
+ Error ->
+ Error
+ end;
+check_config(changing, Config) ->
+ HConfig = maps:get(config, Config, #{}),
+ case check_h_config(maps:to_list(HConfig)) of
+ ok -> {ok,Config};
+ Error -> Error
+ end.
+
+check_h_config([{type,Type} | Config]) when Type == standard_io;
+ Type == standard_error ->
+ check_h_config(Config);
+check_h_config([{type,{file,File}} | Config]) when is_list(File) ->
+ check_h_config(Config);
+check_h_config([{type,{file,File,Modes}} | Config]) when is_list(File),
+ is_list(Modes) ->
+ check_h_config(Config);
+check_h_config([Other | Config]) ->
+ case logger_h_common:check_common_config(Other) of
+ valid ->
+ check_h_config(Config);
+ invalid ->
+ {error,{invalid_config,?MODULE,Other}}
+ end;
+check_h_config([]) ->
+ ok.
+
+
+%%%-----------------------------------------------------------------
+%%% Handler being removed
+removing_handler(#{id:=Name}) ->
+ stop(Name).
+
+%%%-----------------------------------------------------------------
+%%% Log a string or report
+-spec log(LogEvent, Config) -> ok when
+ LogEvent :: logger:log_event(),
+ Config :: logger:handler_config().
+
+log(LogEvent, Config = #{id := Name,
+ config := #{handler_pid := HPid,
+ mode_tab := ModeTab}}) ->
+ %% if the handler has crashed, we must drop this event
+ %% and hope the handler restarts so we can try again
+ true = is_process_alive(HPid),
+ Bin = logger_h_common:log_to_binary(LogEvent, Config),
+ logger_h_common:call_cast_or_drop(Name, HPid, ModeTab, Bin).
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+init([Name, Config = #{config := HConfig},
+ State0 = #{type := Type, file_ctrl_sync_int := FileCtrlSyncInt}]) ->
+ RegName = ?name_to_reg_name(?MODULE,Name),
+ register(RegName, self()),
+ process_flag(trap_exit, true),
+ process_flag(message_queue_data, off_heap),
+
+ ?init_test_hooks(),
+ ?start_observation(Name),
+
+ case do_init(Name, Type) of
+ {ok,InitState} ->
+ try ets:new(Name, [public]) of
+ ModeTab ->
+ ?set_mode(ModeTab, async),
+ State = maps:merge(State0, InitState),
+ T0 = ?timestamp(),
+ State1 =
+ ?merge_with_stats(State#{
+ mode_tab => ModeTab,
+ mode => async,
+ file_ctrl_sync => FileCtrlSyncInt,
+ last_qlen => 0,
+ last_log_ts => T0,
+ last_op => sync,
+ burst_win_ts => T0,
+ burst_msg_count => 0}),
+ Config1 =
+ Config#{config => HConfig#{handler_pid => self(),
+ mode_tab => ModeTab}},
+ proc_lib:init_ack({ok,self(),Config1}),
+ gen_server:cast(self(), repeated_filesync),
+ gen_server:enter_loop(?MODULE, [], State1)
+ catch
+ _:Error ->
+ unregister(RegName),
+ logger_h_common:error_notify({init_handler,Name,Error}),
+ proc_lib:init_ack(Error)
+ end;
+ Error ->
+ unregister(RegName),
+ logger_h_common:error_notify({init_handler,Name,Error}),
+ proc_lib:init_ack(Error)
+ end.
+
+do_init(Name, Type) ->
+ case open_log_file(Name, Type) of
+ {ok,FileCtrlPid} ->
+ case logger_h_common:unset_restart_flag(Name, ?MODULE) of
+ true ->
+ %% inform about restart
+ gen_server:cast(self(), {log_handler_info,
+ "Handler ~p restarted",
+ [Name]});
+ false ->
+ %% initial start
+ ok
+ end,
+ {ok,#{id=>Name,type=>Type,file_ctrl_pid=>FileCtrlPid}};
+ Error ->
+ Error
+ end.
+
+%% This is the synchronous log event.
+handle_call({log, Bin}, _From, State) ->
+ {Result,State1} = do_log(Bin, call, State),
+ %% Result == ok | dropped
+ {reply,Result, State1};
+
+handle_call(filesync, _From, State = #{type := Type,
+ file_ctrl_pid := FileCtrlPid}) ->
+ if is_atom(Type) ->
+ {reply, ok, State};
+ true ->
+ {reply, file_ctrl_filesync_sync(FileCtrlPid), State#{last_op=>sync}}
+ end;
+
+handle_call({change_config,_OldConfig,NewConfig}, _From,
+ State = #{filesync_repeat_interval := FSyncInt0}) ->
+ HConfig = maps:get(config, NewConfig, #{}),
+ State1 = maps:merge(State, HConfig),
+ case logger_h_common:overload_levels_ok(State1) of
+ true ->
+ _ =
+ case maps:get(filesync_repeat_interval, HConfig, undefined) of
+ undefined ->
+ ok;
+ no_repeat ->
+ _ = logger_h_common:cancel_timer(maps:get(rep_sync_tref,
+ State,
+ undefined));
+ FSyncInt0 ->
+ ok;
+ _FSyncInt1 ->
+ _ = logger_h_common:cancel_timer(maps:get(rep_sync_tref,
+ State,
+ undefined)),
+ gen_server:cast(self(), repeated_filesync)
+ end,
+ {reply, ok, State1};
+ false ->
+ #{sync_mode_qlen := SMQL,
+ drop_mode_qlen := DMQL,
+ flush_qlen := FQL} = State1,
+ {reply, {error,{invalid_levels,{SMQL,DMQL,FQL}}}, State}
+ end;
+
+handle_call(info, _From, State) ->
+ {reply, State, State};
+
+handle_call(reset, _From, State) ->
+ State1 = ?merge_with_stats(State),
+ {reply, ok, State1#{last_qlen => 0,
+ last_log_ts => ?timestamp()}};
+
+handle_call(stop, _From, State) ->
+ {stop, {shutdown,stopped}, ok, State}.
+
+%% This is the asynchronous log event.
+handle_cast({log, Bin}, State) ->
+ {_,State1} = do_log(Bin, cast, State),
+ {noreply, State1};
+
+handle_cast({log_handler_info, Format, Args}, State = #{id:=Name}) ->
+ log_handler_info(Name, Format, Args, State),
+ {noreply, State};
+
+%% If FILESYNC_REPEAT_INTERVAL is set to a millisec value, this
+%% clause gets called repeatedly by the handler. In order to
+%% guarantee that a filesync *always* happens after the last log
+%% event, the repeat operation must be active!
+handle_cast(repeated_filesync,
+ State = #{type := Type,
+ file_ctrl_pid := FileCtrlPid,
+ filesync_repeat_interval := FSyncInt,
+ last_op := LastOp}) ->
+ State1 =
+ if not is_atom(Type), is_integer(FSyncInt) ->
+ %% only do filesync if something has been
+ %% written since last time we checked
+ if LastOp == sync ->
+ ok;
+ true ->
+ file_ctrl_filesync_async(FileCtrlPid)
+ end,
+ {ok,TRef} =
+ timer:apply_after(FSyncInt, gen_server,cast,
+ [self(),repeated_filesync]),
+ State#{rep_sync_tref => TRef, last_op => sync};
+ true ->
+ State
+ end,
+ {noreply,State1}.
+
+handle_info({'EXIT',Pid,Why}, State = #{id := Name, type := FileInfo}) ->
+ case maps:get(file_ctrl_pid, State, undefined) of
+ Pid ->
+ %% file error, terminate handler
+ logger_h_common:handler_exit(Name,
+ {error,{write_failed,FileInfo,Why}});
+ _Other ->
+ %% ignore EXIT
+ ok
+ end,
+ {noreply, State};
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(Reason, State = #{id:=Name, file_ctrl_pid:=FWPid,
+ type:=_FileInfo}) ->
+ _ = logger_h_common:cancel_timer(maps:get(rep_sync_tref, State,
+ undefined)),
+ case is_process_alive(FWPid) of
+ true ->
+ unlink(FWPid),
+ _ = file_ctrl_stop(FWPid),
+ MRef = erlang:monitor(process, FWPid),
+ receive
+ {'DOWN',MRef,_,_,_} ->
+ ok
+ after
+ ?DEFAULT_CALL_TIMEOUT ->
+ exit(FWPid, kill)
+ end;
+ false ->
+ ok
+ end,
+ ok = logger_h_common:stop_or_restart(Name, Reason, State),
+ unregister(?name_to_reg_name(?MODULE, Name)),
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+
+%%%-----------------------------------------------------------------
+%%%
+get_init_state() ->
+ #{sync_mode_qlen => ?SYNC_MODE_QLEN,
+ drop_mode_qlen => ?DROP_MODE_QLEN,
+ flush_qlen => ?FLUSH_QLEN,
+ burst_limit_enable => ?BURST_LIMIT_ENABLE,
+ burst_limit_max_count => ?BURST_LIMIT_MAX_COUNT,
+ burst_limit_window_time => ?BURST_LIMIT_WINDOW_TIME,
+ overload_kill_enable => ?OVERLOAD_KILL_ENABLE,
+ overload_kill_qlen => ?OVERLOAD_KILL_QLEN,
+ overload_kill_mem_size => ?OVERLOAD_KILL_MEM_SIZE,
+ overload_kill_restart_after => ?OVERLOAD_KILL_RESTART_AFTER,
+ file_ctrl_sync_int => ?CONTROLLER_SYNC_INTERVAL,
+ filesync_ok_qlen => ?FILESYNC_OK_QLEN,
+ filesync_repeat_interval => ?FILESYNC_REPEAT_INTERVAL}.
+
+%%%-----------------------------------------------------------------
+%%% Add a standard handler to the logger.
+%%% This starts a dedicated handler process which should always
+%%% exist if the handler is registered with logger (and should not
+%%% exist if the handler is not registered).
+%%%
+%%% Handler specific config should be provided with a sub map associated
+%%% with a key named 'config', e.g:
+%%%
+%%% Config = #{config => #{sync_mode_qlen => 50}
+%%%
+%%% The standard handler process is linked to logger_sup, which is
+%%% part of the kernel application's supervision tree.
+start(Name, Config, HandlerState) ->
+ LoggerStdH =
+ #{id => Name,
+ start => {?MODULE, start_link, [Name,Config,HandlerState]},
+ restart => temporary,
+ shutdown => 2000,
+ type => worker,
+ modules => [?MODULE]},
+ case supervisor:start_child(logger_sup, LoggerStdH) of
+ {ok,Pid,Config1} ->
+ ok = logger_handler_watcher:register_handler(Name,Pid),
+ {ok,Config1};
+ Error ->
+ Error
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Stop and remove the handler.
+stop(Name) ->
+ case whereis(?name_to_reg_name(?MODULE,Name)) of
+ undefined ->
+ ok;
+ Pid ->
+ %% We don't want to do supervisor:terminate_child here
+ %% since we need to distinguish this explicit stop from a
+ %% system termination in order to avoid circular attempts
+ %% at removing the handler (implying deadlocks and
+ %% timeouts).
+ %% And we don't need to do supervisor:delete_child, since
+ %% the restart type is temporary, which means that the
+ %% child specification is automatically removed from the
+ %% supervisor when the process dies.
+ _ = gen_server:call(Pid, stop),
+ ok
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Logging and overload control.
+-define(update_file_ctrl_sync(C, Interval),
+ if C == 0 -> Interval;
+ true -> C-1 end).
+
+%% check for overload between every event (and set Mode to async,
+%% sync or drop accordingly), but never flush the whole mailbox
+%% before LogWindowSize events have been handled
+do_log(Bin, CallOrCast, State = #{id:=Name, mode:=Mode0}) ->
+ T1 = ?timestamp(),
+
+ %% check if the handler is getting overloaded, or if it's
+ %% recovering from overload (the check must be done for each
+ %% event to react quickly to large bursts of events and
+ %% to ensure that the handler can never end up in drop mode
+ %% with an empty mailbox, which would stop operation)
+ {Mode1,QLen,Mem,State1} = logger_h_common:check_load(State),
+
+ if (Mode1 == drop) andalso (Mode0 =/= drop) ->
+ log_handler_info(Name, "Handler ~p switched to drop mode",
+ [Name], State);
+ (Mode0 == drop) andalso ((Mode1 == async) orelse (Mode1 == sync)) ->
+ log_handler_info(Name, "Handler ~p switched to ~w mode",
+ [Name,Mode1], State);
+ true ->
+ ok
+ end,
+
+ %% kill the handler if it can't keep up with the load
+ logger_h_common:kill_if_choked(Name, QLen, Mem, ?MODULE, State),
+
+ if Mode1 == flush ->
+ flush(Name, QLen, T1, State1);
+ true ->
+ write(Name, Mode1, T1, Bin, CallOrCast, State1)
+ end.
+
+%% this clause is called by do_log/3 after an overload check
+%% has been performed, where QLen > FlushQLen
+flush(Name, _QLen0, T1, State=#{last_log_ts := _T0, mode_tab := ModeTab}) ->
+ %% flush messages in the mailbox (a limited number in
+ %% order to not cause long delays)
+ NewFlushed = logger_h_common:flush_log_events(?FLUSH_MAX_N),
+
+ %% write info in log about flushed messages
+ log_handler_info(Name, "Handler ~p flushed ~w log events",
+ [Name,NewFlushed], State),
+
+ %% because of the receive loop when flushing messages, the
+ %% handler will be scheduled out often and the mailbox could
+ %% grow very large, so we'd better check the queue again here
+ {_,_QLen1} = process_info(self(), message_queue_len),
+ ?observe(Name,{max_qlen,_QLen1}),
+
+ %% Add 1 for the current log event
+ ?observe(Name,{flushed,NewFlushed+1}),
+
+ State1 = ?update_max_time(?diff_time(T1,_T0),State),
+ {dropped,?update_other(flushed,FLUSHED,NewFlushed,
+ State1#{mode => ?set_mode(ModeTab,async),
+ last_qlen => 0,
+ last_log_ts => T1})}.
+
+%% this clause is called to write to file
+write(_Name, Mode, T1, Bin, _CallOrCast,
+ State = #{mode_tab := ModeTab,
+ file_ctrl_pid := FileCtrlPid,
+ file_ctrl_sync := FileCtrlSync,
+ last_qlen := LastQLen,
+ last_log_ts := T0,
+ file_ctrl_sync_int := FileCtrlSyncInt}) ->
+ %% check if we need to limit the number of writes
+ %% during a burst of log events
+ {DoWrite,BurstWinT,BurstMsgCount} = logger_h_common:limit_burst(State),
+
+ %% only send a synhrounous event to the file controller process
+ %% every FileCtrlSyncInt time, to give the handler time between
+ %% file writes so it can keep up with incoming messages
+ {Result,LastQLen1} =
+ if DoWrite, FileCtrlSync == 0 ->
+ ?observe(_Name,{_CallOrCast,1}),
+ file_write_sync(FileCtrlPid, Bin, false),
+ {ok,element(2, process_info(self(), message_queue_len))};
+ DoWrite ->
+ ?observe(_Name,{_CallOrCast,1}),
+ file_write_async(FileCtrlPid, Bin),
+ {ok,LastQLen};
+ not DoWrite ->
+ ?observe(_Name,{flushed,1}),
+ {dropped,LastQLen}
+ end,
+
+ %% Check if the time since the previous log event is long enough -
+ %% and the queue length small enough - to assume the mailbox has
+ %% been emptied, and if so, do filesync operation and reset mode to
+ %% async. Note that this is the best we can do to detect an idle
+ %% handler without setting a timer after each log call/cast. If the
+ %% time between two consecutive log events is fast and no new
+ %% event comes in after the last one, idle state won't be detected!
+ Time = ?diff_time(T1,T0),
+ {Mode1,BurstMsgCount1} =
+ if (LastQLen1 < ?FILESYNC_OK_QLEN) andalso
+ (Time > ?IDLE_DETECT_TIME_USEC) ->
+ %% do filesync if necessary
+ case maps:get(type, State) of
+ Std when is_atom(Std) ->
+ ok;
+ _File ->
+ file_ctrl_filesync_async(FileCtrlPid)
+ end,
+ {?change_mode(ModeTab, Mode, async),0};
+ true ->
+ {Mode,BurstMsgCount}
+ end,
+ State1 =
+ ?update_calls_or_casts(_CallOrCast,1,State),
+ State2 =
+ ?update_max_time(Time,
+ State1#{mode => Mode1,
+ last_qlen := LastQLen1,
+ last_log_ts => T1,
+ last_op => write,
+ burst_win_ts => BurstWinT,
+ burst_msg_count => BurstMsgCount1,
+ file_ctrl_sync =>
+ ?update_file_ctrl_sync(FileCtrlSync,
+ FileCtrlSyncInt)}),
+ {Result,State2}.
+
+open_log_file(HandlerName, FileInfo) ->
+ case file_ctrl_start(HandlerName, FileInfo) of
+ OK = {ok,_FileCtrlPid} -> OK;
+ Error -> Error
+ end.
+
+do_open_log_file({file,File}) ->
+ do_open_log_file({file,File,[raw,append,delayed_write]});
+
+do_open_log_file({file,File,[]}) ->
+ do_open_log_file({file,File,[raw,append,delayed_write]});
+
+do_open_log_file({file,File,Modes}) ->
+ try
+ case filelib:ensure_dir(File) of
+ ok ->
+ file:open(File, Modes);
+ Error ->
+ Error
+ end
+ catch
+ _:Reason -> {error,Reason}
+ end.
+
+close_log_file(Std) when Std == standard_io; Std == standard_error ->
+ ok;
+close_log_file(Fd) ->
+ _ = file:datasync(Fd),
+ _ = file:close(Fd).
+
+
+log_handler_info(Name, Format, Args, #{file_ctrl_pid := FileCtrlPid}) ->
+ Config =
+ case logger:get_handler_config(Name) of
+ {ok,Conf} -> Conf;
+ _ -> #{formatter=>{?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}}
+ end,
+ Meta = #{time=>erlang:system_time(microsecond)},
+ Bin = logger_h_common:log_to_binary(#{level => notice,
+ msg => {Format,Args},
+ meta => Meta}, Config),
+ _ = file_write_async(FileCtrlPid, Bin),
+ ok.
+
+%%%-----------------------------------------------------------------
+%%% File control process
+
+file_ctrl_start(HandlerName, FileInfo) ->
+ Starter = self(),
+ FileCtrlPid =
+ spawn_link(fun() ->
+ file_ctrl_init(HandlerName, FileInfo, Starter)
+ end),
+ receive
+ {FileCtrlPid,ok} ->
+ {ok,FileCtrlPid};
+ {FileCtrlPid,Error} ->
+ Error
+ after
+ ?DEFAULT_CALL_TIMEOUT ->
+ {error,file_ctrl_process_not_started}
+ end.
+
+file_ctrl_stop(Pid) ->
+ Pid ! stop.
+
+file_write_async(Pid, Bin) ->
+ Pid ! {log,Bin},
+ ok.
+
+file_write_sync(Pid, Bin, FileSync) ->
+ case file_ctrl_call(Pid, {log,self(),Bin,FileSync}) of
+ {error,Reason} ->
+ {error,{write_failed,Bin,Reason}};
+ Result ->
+ Result
+ end.
+
+file_ctrl_filesync_async(Pid) ->
+ Pid ! filesync,
+ ok.
+
+file_ctrl_filesync_sync(Pid) ->
+ file_ctrl_call(Pid, {filesync,self()}).
+
+file_ctrl_call(Pid, Msg) ->
+ MRef = monitor(process, Pid),
+ Pid ! {Msg,MRef},
+ receive
+ {MRef,Result} ->
+ demonitor(MRef, [flush]),
+ Result;
+ {'DOWN',MRef,_Type,_Object,Reason} ->
+ {error,Reason}
+ after
+ ?DEFAULT_CALL_TIMEOUT ->
+ {error,{no_response,Pid}}
+ end.
+
+file_ctrl_init(HandlerName, FileInfo, Starter) when is_tuple(FileInfo) ->
+ process_flag(message_queue_data, off_heap),
+ FileName = element(2, FileInfo),
+ case do_open_log_file(FileInfo) of
+ {ok,Fd} ->
+ Starter ! {self(),ok},
+ file_ctrl_loop(Fd, file, FileName, false, ok, ok, HandlerName);
+ {error,Reason} ->
+ Starter ! {self(),{error,{open_failed,FileName,Reason}}}
+ end;
+file_ctrl_init(HandlerName, StdDev, Starter) ->
+ Starter ! {self(),ok},
+ file_ctrl_loop(StdDev, standard_io, StdDev, false, ok, ok, HandlerName).
+
+file_ctrl_loop(Fd, Type, DevName, Synced,
+ PrevWriteResult, PrevSyncResult, HandlerName) ->
+ receive
+ %% asynchronous event
+ {log,Bin} ->
+ Result = if Type == file ->
+ write_to_dev(Fd, Bin, DevName,
+ PrevWriteResult, HandlerName);
+ true ->
+ io:put_chars(Fd, Bin)
+ end,
+ file_ctrl_loop(Fd, Type, DevName, false,
+ Result, PrevSyncResult, HandlerName);
+
+ %% synchronous event
+ {{log,From,Bin,FileSync},MRef} ->
+ if Type == file ->
+ %% check that file hasn't been deleted
+ CheckFile =
+ fun() -> {ok,_} = file:read_file_info(DevName) end,
+ spawn_link(CheckFile),
+ WResult = write_to_dev(Fd, Bin, DevName,
+ PrevWriteResult, HandlerName),
+ {Synced1,SResult} =
+ if not FileSync ->
+ {false,PrevSyncResult};
+ true ->
+ case sync_dev(Fd, DevName,
+ PrevSyncResult, HandlerName) of
+ ok -> {true,ok};
+ Error -> {false,Error}
+ end
+ end,
+ From ! {MRef,ok},
+ file_ctrl_loop(Fd, Type, DevName, Synced1,
+ WResult, SResult, HandlerName);
+ true ->
+ _ = io:put_chars(Fd, Bin),
+ From ! {MRef,ok},
+ file_ctrl_loop(Fd, Type, DevName, false,
+ ok, PrevSyncResult, HandlerName)
+ end;
+
+ filesync when not Synced ->
+ Result = sync_dev(Fd, DevName, PrevSyncResult, HandlerName),
+ file_ctrl_loop(Fd, Type, DevName, true,
+ PrevWriteResult, Result, HandlerName);
+
+ filesync ->
+ file_ctrl_loop(Fd, Type, DevName, true,
+ PrevWriteResult, PrevSyncResult, HandlerName);
+
+ {{filesync,From},MRef} ->
+ Result = if not Synced ->
+ sync_dev(Fd, DevName, PrevSyncResult, HandlerName);
+ true ->
+ ok
+ end,
+ From ! {MRef,ok},
+ file_ctrl_loop(Fd, Type, DevName, true,
+ PrevWriteResult, Result, HandlerName);
+
+ stop ->
+ _ = close_log_file(Fd),
+ stopped
+ end.
+
+write_to_dev(Fd, Bin, FileName, PrevWriteResult, HandlerName) ->
+ case ?file_write(Fd, Bin) of
+ ok ->
+ ok;
+ PrevWriteResult ->
+ %% don't report same error twice
+ PrevWriteResult;
+ Error ->
+ logger_h_common:error_notify({HandlerName,write,FileName,Error}),
+ Error
+ end.
+
+sync_dev(Fd, DevName, PrevSyncResult, HandlerName) ->
+ case ?file_datasync(Fd) of
+ ok ->
+ ok;
+ PrevSyncResult ->
+ %% don't report same error twice
+ PrevSyncResult;
+ Error ->
+ logger_h_common:error_notify({HandlerName,filesync,DevName,Error}),
+ Error
+ end.
+
diff --git a/lib/kernel/src/logger_sup.erl b/lib/kernel/src/logger_sup.erl
new file mode 100644
index 0000000000..3d6f482e20
--- /dev/null
+++ b/lib/kernel/src/logger_sup.erl
@@ -0,0 +1,57 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/0]).
+
+%% Supervisor callbacks
+-export([init/1]).
+
+-define(SERVER, ?MODULE).
+
+%%%===================================================================
+%%% API functions
+%%%===================================================================
+
+start_link() ->
+ supervisor:start_link({local, ?SERVER}, ?MODULE, []).
+
+%%%===================================================================
+%%% Supervisor callbacks
+%%%===================================================================
+
+init([]) ->
+
+ SupFlags = #{strategy => one_for_one,
+ intensity => 1,
+ period => 5},
+
+ Watcher = #{id => logger_handler_watcher,
+ start => {logger_handler_watcher, start_link, []},
+ shutdown => brutal_kill},
+
+ {ok, {SupFlags, [Watcher]}}.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl
index ddda396713..3cf11fd7b1 100644
--- a/lib/kernel/src/net_kernel.erl
+++ b/lib/kernel/src/net_kernel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -53,7 +53,7 @@
%% Documented API functions.
--export([allow/1,
+-export([allow/1, allowed/0,
connect_node/1,
monitor_nodes/1,
monitor_nodes/2,
@@ -70,8 +70,8 @@
protocol_childspecs/0,
epmd_module/0]).
--export([connect/1, disconnect/1, hidden_connect/1, passive_cnct/1]).
--export([hidden_connect_node/1]). %% explicit connect
+-export([disconnect/1, passive_cnct/1]).
+-export([hidden_connect_node/1]).
-export([set_net_ticktime/1, set_net_ticktime/2, get_net_ticktime/0]).
-export([node_info/1, node_info/2, nodes_info/0,
@@ -122,6 +122,7 @@
-record(connection, {
node, %% remote node name
+ conn_id, %% Connection identity
state, %% pending | up | up_pending
owner, %% owner pid
pending_owner, %% possible new owner
@@ -170,6 +171,8 @@ kernel_apply(M,F,A) -> request({apply,M,F,A}).
Nodes :: [node()].
allow(Nodes) -> request({allow, Nodes}).
+allowed() -> request(allowed).
+
longnames() -> request(longnames).
-spec stop() -> ok | {error, Reason} when
@@ -221,8 +224,7 @@ get_net_ticktime() ->
Error :: error | {error, term()}.
monitor_nodes(Flag) ->
case catch process_flag(monitor_nodes, Flag) of
- true -> ok;
- false -> ok;
+ N when is_integer(N) -> ok;
_ -> mk_monitor_nodes_error(Flag, [])
end.
@@ -235,8 +237,7 @@ monitor_nodes(Flag) ->
Error :: error | {error, term()}.
monitor_nodes(Flag, Opts) ->
case catch process_flag({monitor_nodes, Opts}, Flag) of
- true -> ok;
- false -> ok;
+ N when is_integer(N) -> ok;
_ -> mk_monitor_nodes_error(Flag, Opts)
end.
@@ -247,14 +248,15 @@ ticktime_res(A) when is_atom(A) -> A.
%% Called though BIF's
-connect(Node) -> do_connect(Node, normal, false).
%%% Long timeout if blocked (== barred), only affects nodes with
%%% {dist_auto_connect, once} set.
-passive_cnct(Node) -> do_connect(Node, normal, true).
-disconnect(Node) -> request({disconnect, Node}).
+passive_cnct(Node) ->
+ case request({passive_cnct, Node}) of
+ ignored -> false;
+ Other -> Other
+ end.
-%% connect but not seen
-hidden_connect(Node) -> do_connect(Node, hidden, false).
+disconnect(Node) -> request({disconnect, Node}).
%% Should this node publish itself on Node?
publish_on_node(Node) when is_atom(Node) ->
@@ -272,67 +274,24 @@ connect_node(Node) when is_atom(Node) ->
hidden_connect_node(Node) when is_atom(Node) ->
request({connect, hidden, Node}).
-do_connect(Node, Type, WaitForBarred) -> %% Type = normal | hidden
- case catch ets:lookup(sys_dist, Node) of
- {'EXIT', _} ->
- ?connect_failure(Node,{table_missing, sys_dist}),
- false;
- [#barred_connection{}] ->
- case WaitForBarred of
- false ->
- false;
- true ->
- Pid = spawn(?MODULE,passive_connect_monitor,[self(),Node]),
- receive
- {Pid, true} ->
- %%io:format("Net Kernel: barred connection (~p) "
- %% "connected from other end.~n",[Node]),
- true;
- {Pid, false} ->
- ?connect_failure(Node,{barred_connection,
- ets:lookup(sys_dist, Node)}),
- %%io:format("Net Kernel: barred connection (~p) "
- %% "- failure.~n",[Node]),
- false
- end
- end;
- Else ->
- case application:get_env(kernel, dist_auto_connect) of
- {ok, never} ->
- ?connect_failure(Node,{dist_auto_connect,never}),
- false;
- % This might happen due to connection close
- % not beeing propagated to user space yet.
- % Save the day by just not connecting...
- {ok, once} when Else =/= [],
- (hd(Else))#connection.state =:= up ->
- ?connect_failure(Node,{barred_connection,
- ets:lookup(sys_dist, Node)}),
- false;
- _ ->
- request({connect, Type, Node})
- end
- end.
-passive_connect_monitor(Parent, Node) ->
+passive_connect_monitor(From, Node) ->
ok = monitor_nodes(true,[{node_type,all}]),
- case lists:member(Node,nodes([connected])) of
- true ->
- ok = monitor_nodes(false,[{node_type,all}]),
- Parent ! {self(),true};
- _ ->
- Ref = make_ref(),
- Tref = erlang:send_after(connecttime(),self(),Ref),
- receive
- Ref ->
- ok = monitor_nodes(false,[{node_type,all}]),
- Parent ! {self(), false};
- {nodeup,Node,_} ->
- ok = monitor_nodes(false,[{node_type,all}]),
- _ = erlang:cancel_timer(Tref),
- Parent ! {self(),true}
- end
- end.
+ Reply = case lists:member(Node,nodes([connected])) of
+ true ->
+ true;
+ _ ->
+ receive
+ {nodeup,Node,_} ->
+ true
+ after connecttime() ->
+ false
+ end
+ end,
+ ok = monitor_nodes(false,[{node_type,all}]),
+ {Pid, Tag} = From,
+ erlang:send(Pid, {Tag, Reply}).
+
%% If the net_kernel isn't running we ignore all requests to the
%% kernel, thus basically accepting them :-)
@@ -393,41 +352,140 @@ init({Name, LongOrShortNames, TickT, CleanHalt}) ->
{stop, Error}
end.
+do_auto_connect_1(Node, ConnId, From, State) ->
+ case ets:lookup(sys_dist, Node) of
+ [#barred_connection{}] ->
+ case ConnId of
+ passive_cnct ->
+ spawn(?MODULE,passive_connect_monitor,[From,Node]),
+ {noreply, State};
+ _ ->
+ erts_internal:abort_connection(Node, ConnId),
+ {reply, false, State}
+ end;
+
+ ConnLookup ->
+ do_auto_connect_2(Node, ConnId, From, State, ConnLookup)
+ end.
+
+do_auto_connect_2(Node, passive_cnct, From, State, ConnLookup) ->
+ try erts_internal:new_connection(Node) of
+ ConnId ->
+ do_auto_connect_2(Node, ConnId, From, State, ConnLookup)
+ catch
+ _:_ ->
+ error_logger:error_msg("~n** Cannot get connection id for node ~w~n",
+ [Node]),
+ {reply, false, State}
+ end;
+do_auto_connect_2(Node, ConnId, From, State, ConnLookup) ->
+ case ConnLookup of
+ [#connection{conn_id=ConnId, state = up}] ->
+ {reply, true, State};
+ [#connection{conn_id=ConnId, waiting=Waiting}=Conn] ->
+ case From of
+ noreply -> ok;
+ _ -> ets:insert(sys_dist, Conn#connection{waiting = [From|Waiting]})
+ end,
+ {noreply, State};
+
+ _ ->
+ case application:get_env(kernel, dist_auto_connect) of
+ {ok, never} ->
+ ?connect_failure(Node,{dist_auto_connect,never}),
+ erts_internal:abort_connection(Node, ConnId),
+ {reply, false, State};
+
+ %% This might happen due to connection close
+ %% not beeing propagated to user space yet.
+ %% Save the day by just not connecting...
+ {ok, once} when ConnLookup =/= [],
+ (hd(ConnLookup))#connection.state =:= up ->
+ ?connect_failure(Node,{barred_connection,
+ ets:lookup(sys_dist, Node)}),
+ erts_internal:abort_connection(Node, ConnId),
+ {reply, false, State};
+ _ ->
+ case setup(Node, ConnId, normal, From, State) of
+ {ok, SetupPid} ->
+ Owners = [{SetupPid, Node} | State#state.conn_owners],
+ {noreply,State#state{conn_owners=Owners}};
+ _Error ->
+ ?connect_failure(Node, {setup_call, failed, _Error}),
+ erts_internal:abort_connection(Node, ConnId),
+ {reply, false, State}
+ end
+ end
+ end.
+
+
+do_explicit_connect([#connection{conn_id = ConnId, state = up}], _, _, ConnId, _From, State) ->
+ {reply, true, State};
+do_explicit_connect([#connection{conn_id = ConnId}=Conn], _, _, ConnId, From, State)
+ when Conn#connection.state =:= pending;
+ Conn#connection.state =:= up_pending ->
+ Waiting = Conn#connection.waiting,
+ ets:insert(sys_dist, Conn#connection{waiting = [From|Waiting]}),
+ {noreply, State};
+do_explicit_connect([#barred_connection{}], Type, Node, ConnId, From , State) ->
+ %% Barred connection only affects auto_connect, ignore it.
+ do_explicit_connect([], Type, Node, ConnId, From , State);
+do_explicit_connect(_ConnLookup, Type, Node, ConnId, From , State) ->
+ case setup(Node,ConnId,Type,From,State) of
+ {ok, SetupPid} ->
+ Owners = [{SetupPid, Node} | State#state.conn_owners],
+ {noreply,State#state{conn_owners=Owners}};
+ _Error ->
+ ?connect_failure(Node, {setup_call, failed, _Error}),
+ {reply, false, State}
+ end.
+
%% ------------------------------------------------------------
%% handle_call.
%% ------------------------------------------------------------
%%
-%% Set up a connection to Node.
-%% The response is delayed until the connection is up and
-%% running.
+%% Passive auto-connect to Node.
+%% The response is delayed until the connection is up and running.
+%%
+handle_call({passive_cnct, Node}, From, State) when Node =:= node() ->
+ async_reply({reply, true, State}, From);
+handle_call({passive_cnct, Node}, From, State) ->
+ verbose({passive_cnct, Node}, 1, State),
+ R = do_auto_connect_1(Node, passive_cnct, From, State),
+ return_call(R, From);
+
+%%
+%% Explicit connect
+%% The response is delayed until the connection is up and running.
%%
handle_call({connect, _, Node}, From, State) when Node =:= node() ->
async_reply({reply, true, State}, From);
handle_call({connect, Type, Node}, From, State) ->
verbose({connect, Type, Node}, 1, State),
- case ets:lookup(sys_dist, Node) of
- [Conn] when Conn#connection.state =:= up ->
- async_reply({reply, true, State}, From);
- [Conn] when Conn#connection.state =:= pending ->
- Waiting = Conn#connection.waiting,
- ets:insert(sys_dist, Conn#connection{waiting = [From|Waiting]}),
- {noreply, State};
- [Conn] when Conn#connection.state =:= up_pending ->
- Waiting = Conn#connection.waiting,
- ets:insert(sys_dist, Conn#connection{waiting = [From|Waiting]}),
- {noreply, State};
- _ ->
- case setup(Node,Type,From,State) of
- {ok, SetupPid} ->
- Owners = [{SetupPid, Node} | State#state.conn_owners],
- {noreply,State#state{conn_owners=Owners}};
- _ ->
- ?connect_failure(Node, {setup_call, failed}),
- async_reply({reply, false, State}, From)
- end
- end;
+ ConnLookup = ets:lookup(sys_dist, Node),
+ R = try erts_internal:new_connection(Node) of
+ ConnId ->
+ R1 = do_explicit_connect(ConnLookup, Type, Node, ConnId, From, State),
+ case R1 of
+ {reply, true, _S} -> %% already connected
+ ok;
+ {noreply, _S} -> %% connection pending
+ ok;
+ {reply, false, _S} -> %% connection refused
+ erts_internal:abort_connection(Node, ConnId)
+ end,
+ R1
+
+ catch
+ _:_ ->
+ error_logger:error_msg("~n** Cannot get connection id for node ~w~n",
+ [Node]),
+ {reply, false, State}
+ end,
+ return_call(R, From);
+
%%
%% Close the connection to Node.
@@ -470,6 +528,9 @@ handle_call({allow, Nodes}, From, State) ->
async_reply({reply,error,State}, From)
end;
+handle_call(allowed, From, #state{allowed = Allowed} = State) ->
+ async_reply({reply,{ok,Allowed},State}, From);
+
%%
%% authentication, used by auth. Simply works as this:
%% if the message comes through, the other node IS authorized.
@@ -634,6 +695,25 @@ terminate(_Reason, State) ->
%% ------------------------------------------------------------
%%
+%% Asynchronous auto connect request
+%%
+handle_info({auto_connect,Node, DHandle}, State) ->
+ verbose({auto_connect, Node, DHandle}, 1, State),
+ ConnId = DHandle,
+ NewState =
+ case do_auto_connect_1(Node, ConnId, noreply, State) of
+ {noreply, S} -> %% Pending connection
+ S;
+
+ {reply, true, S} -> %% Already connected
+ S;
+
+ {reply, false, S} -> %% Connection refused
+ S
+ end,
+ {noreply, NewState};
+
+%%
%% accept a new connection.
%%
handle_info({accept,AcceptPid,Socket,Family,Proto}, State) ->
@@ -713,14 +793,23 @@ handle_info({AcceptPid, {accept_pending,MyNode,Node,Address,Type}}, State) ->
AcceptPid ! {self(), {accept_pending, already_pending}},
{noreply, State};
_ ->
- ets:insert(sys_dist, #connection{node = Node,
- state = pending,
- owner = AcceptPid,
- address = Address,
- type = Type}),
- AcceptPid ! {self(),{accept_pending,ok}},
- Owners = [{AcceptPid,Node} | State#state.conn_owners],
- {noreply, State#state{conn_owners = Owners}}
+ try erts_internal:new_connection(Node) of
+ ConnId ->
+ ets:insert(sys_dist, #connection{node = Node,
+ conn_id = ConnId,
+ state = pending,
+ owner = AcceptPid,
+ address = Address,
+ type = Type}),
+ AcceptPid ! {self(),{accept_pending,ok}},
+ Owners = [{AcceptPid,Node} | State#state.conn_owners],
+ {noreply, State#state{conn_owners = Owners}}
+ catch
+ _:_ ->
+ error_logger:error_msg("~n** Cannot get connection id for node ~w~n",
+ [Node]),
+ AcceptPid ! {self(),{accept_pending,nok_pending}}
+ end
end;
handle_info({SetupPid, {is_pending, Node}}, State) ->
@@ -778,7 +867,7 @@ handle_info(transition_period_end,
{noreply,State#state{tick = #tick{ticker = Tckr, time = T}}};
handle_info(X, State) ->
- error_msg("Net kernel got ~w~n",[X]),
+ error_msg("Net kernel got ~tw~n",[X]),
{noreply,State}.
%% -----------------------------------------------------------
@@ -906,6 +995,7 @@ pending_nodedown(Conn, Node, Type, State) ->
% Don't bar connections that have never been alive
%mark_sys_dist_nodedown(Node),
% - instead just delete the node:
+ erts_internal:abort_connection(Node, Conn#connection.conn_id),
ets:delete(sys_dist, Node),
reply_waiting(Node,Conn#connection.waiting, false),
case Type of
@@ -920,7 +1010,9 @@ up_pending_nodedown(Conn, Node, _Reason, _Type, State) ->
AcceptPid = Conn#connection.pending_owner,
Owners = State#state.conn_owners,
Pend = lists:keydelete(AcceptPid, 1, State#state.pend_owners),
+ erts_internal:abort_connection(Node, Conn#connection.conn_id),
Conn1 = Conn#connection { owner = AcceptPid,
+ conn_id = erts_internal:new_connection(Node),
pending_owner = undefined,
state = pending },
ets:insert(sys_dist, Conn1),
@@ -928,15 +1020,16 @@ up_pending_nodedown(Conn, Node, _Reason, _Type, State) ->
State#state{conn_owners = [{AcceptPid,Node}|Owners], pend_owners = Pend}.
-up_nodedown(_Conn, Node, _Reason, Type, State) ->
- mark_sys_dist_nodedown(Node),
+up_nodedown(Conn, Node, _Reason, Type, State) ->
+ mark_sys_dist_nodedown(Conn, Node),
case Type of
normal -> ?nodedown(Node, State);
_ -> ok
end,
State.
-mark_sys_dist_nodedown(Node) ->
+mark_sys_dist_nodedown(Conn, Node) ->
+ erts_internal:abort_connection(Node, Conn#connection.conn_id),
case application:get_env(kernel, dist_auto_connect) of
{ok, once} ->
ets:insert(sys_dist, #barred_connection{node = Node});
@@ -1179,15 +1272,8 @@ spawn_func(_,{From,Tag},M,F,A,Gleader) ->
%% Set up connection to a new node.
%% -----------------------------------------------------------
-setup(Node,Type,From,State) ->
- Allowed = State#state.allowed,
- case lists:member(Node, Allowed) of
- false when Allowed =/= [] ->
- error_msg("** Connection attempt with "
- "disallowed node ~w ** ~n", [Node]),
- {error, bad_node};
- _ ->
- case select_mod(Node, State#state.listen) of
+setup(Node, ConnId, Type, From, State) ->
+ case setup_check(Node, State) of
{ok, L} ->
Mod = L#listen.module,
LAddr = L#listen.address,
@@ -1200,18 +1286,38 @@ setup(Node,Type,From,State) ->
Addr = LAddr#net_address {
address = undefined,
host = undefined },
+ Waiting = case From of
+ noreply -> [];
+ _ -> [From]
+ end,
ets:insert(sys_dist, #connection{node = Node,
+ conn_id = ConnId,
state = pending,
owner = Pid,
- waiting = [From],
+ waiting = Waiting,
address = Addr,
type = normal}),
{ok, Pid};
Error ->
Error
- end
end.
+setup_check(Node, State) ->
+ Allowed = State#state.allowed,
+ case lists:member(Node, Allowed) of
+ false when Allowed =/= [] ->
+ error_msg("** Connection attempt with "
+ "disallowed node ~w ** ~n", [Node]),
+ {error, bad_node};
+ _ ->
+ case select_mod(Node, State#state.listen) of
+ {ok, _L}=OK -> OK;
+ Error -> Error
+ end
+ end.
+
+
+
%%
%% Find a module that is willing to handle connection setup to Node
%%
@@ -1652,6 +1758,11 @@ verbose(_, _, _) ->
getnode(P) when is_pid(P) -> node(P);
getnode(P) -> P.
+return_call({noreply, _State}=R, _From) ->
+ R;
+return_call(R, From) ->
+ async_reply(R, From).
+
async_reply({reply, Msg, State}, From) ->
async_gen_server_reply(From, Msg),
{noreply, State}.
@@ -1659,16 +1770,16 @@ async_reply({reply, Msg, State}, From) ->
async_gen_server_reply(From, Msg) ->
{Pid, Tag} = From,
M = {Tag, Msg},
- case catch erlang:send(Pid, M, [nosuspend, noconnect]) of
+ try erlang:send(Pid, M, [nosuspend, noconnect]) of
ok ->
ok;
nosuspend ->
_ = spawn(fun() -> catch erlang:send(Pid, M, [noconnect]) end),
ok;
noconnect ->
- ok; % The gen module takes care of this case.
- {'EXIT', _} ->
- ok
+ ok % The gen module takes care of this case.
+ catch
+ _:_ -> ok
end.
call_owner(Owner, Msg) ->
diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl
index 0250783632..29a26674ba 100644
--- a/lib/kernel/src/os.erl
+++ b/lib/kernel/src/os.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,40 +21,40 @@
%% Provides a common operating system interface.
--export([type/0, version/0, cmd/1, find_executable/1, find_executable/2]).
+-export([type/0, version/0, cmd/1, cmd/2, find_executable/1, find_executable/2]).
-include("file.hrl").
+-export_type([env_var_name/0, env_var_value/0, env_var_name_value/0]).
+
+-export([getenv/0, getenv/1, getenv/2, putenv/2, unsetenv/1]).
+
%%% BIFs
--export([getenv/0, getenv/1, getenv/2, getpid/0,
- perf_counter/0, perf_counter/1,
- putenv/2, set_signal/2, system_time/0, system_time/1,
- timestamp/0, unsetenv/1]).
+-export([get_env_var/1, getpid/0, list_env_vars/0, perf_counter/0,
+ perf_counter/1, set_env_var/2, set_signal/2, system_time/0,
+ system_time/1, timestamp/0, unset_env_var/1]).
--spec getenv() -> [string()].
+-type os_command() :: atom() | io_lib:chars().
+-type os_command_opts() :: #{ max_size => non_neg_integer() | infinity }.
-getenv() -> erlang:nif_error(undef).
+-export_type([os_command/0, os_command_opts/0]).
--spec getenv(VarName) -> Value | false when
- VarName :: string(),
- Value :: string().
+-type env_var_name() :: nonempty_string().
-getenv(_) ->
- erlang:nif_error(undef).
+-type env_var_value() :: string().
--spec getenv(VarName, DefaultValue) -> Value when
- VarName :: string(),
- DefaultValue :: string(),
- Value :: string().
+-type env_var_name_value() :: nonempty_string().
-getenv(VarName, DefaultValue) ->
- case os:getenv(VarName) of
- false ->
- DefaultValue;
- Value ->
- Value
- end.
+-spec list_env_vars() -> [{env_var_name(), env_var_value()}].
+list_env_vars() ->
+ erlang:nif_error(undef).
+
+-spec get_env_var(VarName) -> Value | false when
+ VarName :: env_var_name(),
+ Value :: env_var_value().
+get_env_var(_VarName) ->
+ erlang:nif_error(undef).
-spec getpid() -> Value when
Value :: string().
@@ -74,11 +74,10 @@ perf_counter() ->
perf_counter(Unit) ->
erlang:convert_time_unit(os:perf_counter(), perf_counter, Unit).
--spec putenv(VarName, Value) -> true when
- VarName :: string(),
- Value :: string().
-
-putenv(_, _) ->
+-spec set_env_var(VarName, Value) -> true when
+ VarName :: env_var_name(),
+ Value :: env_var_value().
+set_env_var(_, _) ->
erlang:nif_error(undef).
-spec system_time() -> integer().
@@ -98,10 +97,9 @@ system_time(_Unit) ->
timestamp() ->
erlang:nif_error(undef).
--spec unsetenv(VarName) -> true when
- VarName :: string().
-
-unsetenv(_) ->
+-spec unset_env_var(VarName) -> true when
+ VarName :: env_var_name().
+unset_env_var(_) ->
erlang:nif_error(undef).
-spec set_signal(Signal, Option) -> 'ok' when
@@ -115,6 +113,39 @@ set_signal(_Signal, _Option) ->
%%% End of BIFs
+-spec getenv() -> [env_var_name_value()].
+getenv() ->
+ [lists:flatten([Key, $=, Value]) || {Key, Value} <- os:list_env_vars() ].
+
+-spec getenv(VarName) -> Value | false when
+ VarName :: env_var_name(),
+ Value :: env_var_value().
+getenv(VarName) ->
+ os:get_env_var(VarName).
+
+-spec getenv(VarName, DefaultValue) -> Value when
+ VarName :: env_var_name(),
+ DefaultValue :: env_var_value(),
+ Value :: env_var_value().
+getenv(VarName, DefaultValue) ->
+ case os:getenv(VarName) of
+ false ->
+ DefaultValue;
+ Value ->
+ Value
+ end.
+
+-spec putenv(VarName, Value) -> true when
+ VarName :: env_var_name(),
+ Value :: env_var_value().
+putenv(VarName, Value) ->
+ os:set_env_var(VarName, Value).
+
+-spec unsetenv(VarName) -> true when
+ VarName :: env_var_name().
+unsetenv(VarName) ->
+ os:unset_env_var(VarName).
+
-spec type() -> {Osfamily, Osname} when
Osfamily :: unix | win32,
Osname :: atom().
@@ -178,7 +209,7 @@ verify_executable(Name0, [Ext|Rest], OrigExtensions) ->
end;
verify_executable(Name, [], OrigExtensions) when OrigExtensions =/= [""] -> %% Windows
%% Will only happen on windows, hence case insensitivity
- case can_be_full_name(string:to_lower(Name),OrigExtensions) of
+ case can_be_full_name(string:lowercase(Name),OrigExtensions) of
true ->
verify_executable(Name,[""],[""]);
_ ->
@@ -232,15 +263,20 @@ extensions() ->
%% Executes the given command in the default shell for the operating system.
-spec cmd(Command) -> string() when
- Command :: atom() | io_lib:chars().
+ Command :: os_command().
cmd(Cmd) ->
- validate(Cmd),
- {SpawnCmd, SpawnOpts, SpawnInput, Eot} = mk_cmd(os:type(), Cmd),
+ cmd(Cmd, #{ }).
+
+-spec cmd(Command, Options) -> string() when
+ Command :: os_command(),
+ Options :: os_command_opts().
+cmd(Cmd, Opts) ->
+ {SpawnCmd, SpawnOpts, SpawnInput, Eot} = mk_cmd(os:type(), validate(Cmd)),
Port = open_port({spawn, SpawnCmd}, [binary, stderr_to_stdout,
stream, in, hide | SpawnOpts]),
MonRef = erlang:monitor(port, Port),
true = port_command(Port, SpawnInput),
- Bytes = get_data(Port, MonRef, Eot, []),
+ Bytes = get_data(Port, MonRef, Eot, [], 0, maps:get(max_size, Opts, infinity)),
demonitor(MonRef, [flush]),
String = unicode:characters_to_list(Bytes),
if %% Convert to unicode list if possible otherwise return bytes
@@ -255,8 +291,6 @@ mk_cmd({win32,Wtype}, Cmd) ->
{Cspec,_} -> lists:concat([Cspec," /c",Cmd])
end,
{Command, [], [], <<>>};
-mk_cmd(OsType,Cmd) when is_atom(Cmd) ->
- mk_cmd(OsType, atom_to_list(Cmd));
mk_cmd(_,Cmd) ->
%% Have to send command in like this in order to make sh commands like
%% cd and ulimit available
@@ -279,24 +313,41 @@ mk_cmd(_,Cmd) ->
<<$\^D>>}.
validate(Atom) when is_atom(Atom) ->
- ok;
+ validate(atom_to_list(Atom));
validate(List) when is_list(List) ->
- validate1(List).
+ case validate1(List) of
+ false ->
+ List;
+ true ->
+ %% Had zeros at end; remove them...
+ string:trim(List, trailing, [0])
+ end.
-validate1([C|Rest]) when is_integer(C) ->
+validate1([0|Rest]) ->
+ validate2(Rest);
+validate1([C|Rest]) when is_integer(C), C > 0 ->
validate1(Rest);
validate1([List|Rest]) when is_list(List) ->
- validate1(List),
- validate1(Rest);
+ validate1(List) or validate1(Rest);
validate1([]) ->
- ok.
+ false.
+
+%% Ensure that the rest is zero only...
+validate2([]) ->
+ true;
+validate2([0|Rest]) ->
+ validate2(Rest);
+validate2([List|Rest]) when is_list(List) ->
+ validate2(List),
+ validate2(Rest).
-get_data(Port, MonRef, Eot, Sofar) ->
+get_data(Port, MonRef, Eot, Sofar, Size, Max) ->
receive
{Port, {data, Bytes}} ->
- case eot(Bytes, Eot) of
+ case eot(Bytes, Eot, Size, Max) of
more ->
- get_data(Port, MonRef, Eot, [Sofar,Bytes]);
+ get_data(Port, MonRef, Eot, [Sofar, Bytes],
+ Size + byte_size(Bytes), Max);
Last ->
catch port_close(Port),
flush_until_down(Port, MonRef),
@@ -307,13 +358,16 @@ get_data(Port, MonRef, Eot, Sofar) ->
iolist_to_binary(Sofar)
end.
-eot(_Bs, <<>>) ->
+eot(Bs, <<>>, Size, Max) when Size + byte_size(Bs) < Max ->
more;
-eot(Bs, Eot) ->
+eot(Bs, <<>>, Size, Max) ->
+ binary:part(Bs, {0, Max - Size});
+eot(Bs, Eot, Size, Max) ->
case binary:match(Bs, Eot) of
- nomatch -> more;
- {Pos, _} ->
- binary:part(Bs,{0, Pos})
+ {Pos, _} when Size + Pos < Max ->
+ binary:part(Bs,{0, Pos});
+ _ ->
+ eot(Bs, <<>>, Size, Max)
end.
%% When port_close returns we know that all the
diff --git a/lib/kernel/src/pg2.erl b/lib/kernel/src/pg2.erl
index edf4aedde2..c4732f37ee 100644
--- a/lib/kernel/src/pg2.erl
+++ b/lib/kernel/src/pg2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -199,7 +199,7 @@ handle_call({delete, Name}, _From, S) ->
{reply, ok, S};
handle_call(Request, From, S) ->
error_logger:warning_msg("The pg2 server received an unexpected message:\n"
- "handle_call(~p, ~p, _)\n",
+ "handle_call(~tp, ~tp, _)\n",
[Request, From]),
{noreply, S}.
diff --git a/lib/kernel/src/raw_file_io.erl b/lib/kernel/src/raw_file_io.erl
new file mode 100644
index 0000000000..e3c07c8f78
--- /dev/null
+++ b/lib/kernel/src/raw_file_io.erl
@@ -0,0 +1,75 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(raw_file_io).
+
+-export([open/2]).
+
+open(Filename, Modes) ->
+ %% Layers are applied in this order, and the listed modules will call this
+ %% function again as necessary. eg. a raw compressed delayed file in list
+ %% mode will walk through [_list -> _compressed -> _delayed -> _raw].
+ ModuleOrder = [{raw_file_io_list, fun match_list/1},
+ {raw_file_io_compressed, fun match_compressed/1},
+ {raw_file_io_delayed, fun match_delayed/1},
+ {raw_file_io_raw, fun match_raw/1}],
+ open_1(ModuleOrder, Filename, add_implicit_modes(Modes)).
+open_1([], _Filename, _Modes) ->
+ error(badarg);
+open_1([{Module, Match} | Rest], Filename, Modes) ->
+ case lists:any(Match, Modes) of
+ true ->
+ {Options, ChildModes} =
+ lists:partition(fun(Mode) -> Match(Mode) end, Modes),
+ Module:open_layer(Filename, ChildModes, Options);
+ false ->
+ open_1(Rest, Filename, Modes)
+ end.
+
+%% 'read' and 'list' mode are enabled unless disabled by another option, so
+%% we'll explicitly add them to avoid duplicating this logic in child layers.
+add_implicit_modes(Modes0) ->
+ Modes1 = add_unless_matched(Modes0, fun match_writable/1, read),
+ add_unless_matched(Modes1, fun match_binary/1, list).
+add_unless_matched(Modes, Match, Default) ->
+ case lists:any(Match, Modes) of
+ false -> [Default | Modes];
+ true -> Modes
+ end.
+
+match_list(list) -> true;
+match_list(_Other) -> false.
+
+match_compressed(compressed) -> true;
+match_compressed(_Other) -> false.
+
+match_delayed({delayed_write, _Size, _Timeout}) -> true;
+match_delayed(delayed_write) -> true;
+match_delayed(_Other) -> false.
+
+match_raw(raw) -> true;
+match_raw(_Other) -> false.
+
+match_writable(write) -> true;
+match_writable(append) -> true;
+match_writable(exclusive) -> true;
+match_writable(_Other) -> false.
+
+match_binary(binary) -> true;
+match_binary(_Other) -> false.
diff --git a/lib/kernel/src/raw_file_io_compressed.erl b/lib/kernel/src/raw_file_io_compressed.erl
new file mode 100644
index 0000000000..d5ab042d25
--- /dev/null
+++ b/lib/kernel/src/raw_file_io_compressed.erl
@@ -0,0 +1,134 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(raw_file_io_compressed).
+
+-export([close/1, sync/1, datasync/1, truncate/1, advise/4, allocate/3,
+ position/2, write/2, pwrite/2, pwrite/3,
+ read_line/1, read/2, pread/2, pread/3]).
+
+%% OTP internal.
+-export([ipread_s32bu_p32bu/3, sendfile/8]).
+
+-export([open_layer/3]).
+
+-include("file_int.hrl").
+
+open_layer(Filename, Modes, Options) ->
+ IsAppend = lists:member(append, Modes),
+ IsDeflate = lists:member(write, Modes),
+ IsInflate = lists:member(read, Modes),
+ if
+ IsDeflate, IsInflate; IsAppend ->
+ {error, einval};
+ IsDeflate, not IsInflate ->
+ start_server_module(raw_file_io_deflate, Filename, Modes, Options);
+ IsInflate ->
+ start_server_module(raw_file_io_inflate, Filename, Modes, Options)
+ end.
+
+start_server_module(Module, Filename, Modes, Options) ->
+ Secret = make_ref(),
+ case gen_statem:start(Module, {self(), Secret, Options}, []) of
+ {ok, Pid} -> open_next_layer(Pid, Secret, Filename, Modes);
+ Other -> Other
+ end.
+
+open_next_layer(Pid, Secret, Filename, Modes) ->
+ case gen_statem:call(Pid, {'$open', Secret, Filename, Modes}, infinity) of
+ ok ->
+ PublicFd = #file_descriptor{
+ module = raw_file_io_compressed, data = {self(), Pid} },
+ {ok, PublicFd};
+ Other -> Other
+ end.
+
+close(Fd) ->
+ wrap_call(Fd, [close]).
+
+sync(Fd) ->
+ wrap_call(Fd, [sync]).
+datasync(Fd) ->
+ wrap_call(Fd, [datasync]).
+
+truncate(Fd) ->
+ wrap_call(Fd, [truncate]).
+
+advise(Fd, Offset, Length, Advise) ->
+ wrap_call(Fd, [advise, Offset, Length, Advise]).
+allocate(Fd, Offset, Length) ->
+ wrap_call(Fd, [allocate, Offset, Length]).
+
+position(Fd, Mark) ->
+ wrap_call(Fd, [position, Mark]).
+
+write(Fd, IOData) ->
+ try
+ CompactedData = erlang:iolist_to_iovec(IOData),
+ wrap_call(Fd, [write, CompactedData])
+ catch
+ error:badarg -> {error, badarg}
+ end.
+
+pwrite(Fd, Offset, IOData) ->
+ try
+ CompactedData = erlang:iolist_to_iovec(IOData),
+ wrap_call(Fd, [pwrite, Offset, CompactedData])
+ catch
+ error:badarg -> {error, badarg}
+ end.
+pwrite(Fd, LocBytes) ->
+ try
+ CompactedLocBytes =
+ [ {Offset, erlang:iolist_to_iovec(IOData)} ||
+ {Offset, IOData} <- LocBytes ],
+ wrap_call(Fd, [pwrite, CompactedLocBytes])
+ catch
+ error:badarg -> {error, badarg}
+ end.
+
+read_line(Fd) ->
+ wrap_call(Fd, [read_line]).
+read(Fd, Size) ->
+ wrap_call(Fd, [read, Size]).
+pread(Fd, Offset, Size) ->
+ wrap_call(Fd, [pread, Offset, Size]).
+pread(Fd, LocNums) ->
+ wrap_call(Fd, [pread, LocNums]).
+
+ipread_s32bu_p32bu(Fd, Offset, MaxSize) ->
+ wrap_call(Fd, [ipread_s32bu_p32bu, Offset, MaxSize]).
+
+sendfile(_,_,_,_,_,_,_,_) ->
+ {error, enotsup}.
+
+wrap_call(Fd, Command) ->
+ {_Owner, Pid} = get_fd_data(Fd),
+ try gen_statem:call(Pid, Command, infinity) of
+ Result -> Result
+ catch
+ exit:{noproc, _StackTrace} -> {error, einval}
+ end.
+
+get_fd_data(#file_descriptor{ data = Data }) ->
+ {Owner, _ServerPid} = Data,
+ case self() of
+ Owner -> Data;
+ _ -> error(not_on_controlling_process)
+ end.
diff --git a/lib/kernel/src/raw_file_io_deflate.erl b/lib/kernel/src/raw_file_io_deflate.erl
new file mode 100644
index 0000000000..acfc546743
--- /dev/null
+++ b/lib/kernel/src/raw_file_io_deflate.erl
@@ -0,0 +1,159 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(raw_file_io_deflate).
+
+-behavior(gen_statem).
+
+-export([init/1, callback_mode/0, terminate/3]).
+-export([opening/3, opened/3]).
+
+-include("file_int.hrl").
+
+-define(GZIP_WBITS, 16 + 15).
+
+callback_mode() -> state_functions.
+
+init({Owner, Secret, [compressed]}) ->
+ Monitor = monitor(process, Owner),
+ Z = zlib:open(),
+ ok = zlib:deflateInit(Z, default, deflated, ?GZIP_WBITS, 8, default),
+ Data =
+ #{ owner => Owner,
+ monitor => Monitor,
+ secret => Secret,
+ position => 0,
+ zlib => Z },
+ {ok, opening, Data}.
+
+opening({call, From}, {'$open', Secret, Filename, Modes}, #{ secret := Secret } = Data) ->
+ case raw_file_io:open(Filename, Modes) of
+ {ok, PrivateFd} ->
+ NewData = Data#{ handle => PrivateFd },
+ {next_state, opened, NewData, [{reply, From, ok}]};
+ Other ->
+ {stop_and_reply, normal, [{reply, From, Other}]}
+ end;
+opening(_Event, _Contents, _Data) ->
+ {keep_state_and_data, [postpone]}.
+
+%%
+
+opened(info, {'DOWN', Monitor, process, _Owner, Reason}, #{ monitor := Monitor } = Data) ->
+ if
+ Reason =/= kill -> flush_deflate_state(Data);
+ Reason =:= kill -> ignored
+ end,
+ {stop, shutdown};
+
+opened(info, _Message, _Data) ->
+ keep_state_and_data;
+
+opened({call, {Owner, _Tag} = From}, [close], #{ owner := Owner } = Data) ->
+ #{ handle := PrivateFd } = Data,
+ Response =
+ case flush_deflate_state(Data) of
+ ok -> ?CALL_FD(PrivateFd, close, []);
+ Other -> Other
+ end,
+ {stop_and_reply, normal, [{reply, From, Response}]};
+
+opened({call, {Owner, _Tag} = From}, [position, Mark], #{ owner := Owner } = Data) ->
+ case position(Data, Mark) of
+ {ok, NewData, Result} ->
+ Response = {ok, Result},
+ {keep_state, NewData, [{reply, From, Response}]};
+ Other ->
+ {keep_state_and_data, [{reply, From, Other}]}
+ end;
+
+opened({call, {Owner, _Tag} = From}, [write, IOVec], #{ owner := Owner } = Data) ->
+ case write(Data, IOVec) of
+ {ok, NewData} -> {keep_state, NewData, [{reply, From, ok}]};
+ Other -> {keep_state_and_data, [{reply, From, Other}]}
+ end;
+
+opened({call, {Owner, _Tag} = From}, [read, _Size], #{ owner := Owner }) ->
+ Response = {error, ebadf},
+ {keep_state_and_data, [{reply, From, Response}]};
+
+opened({call, {Owner, _Tag} = From}, [read_line], #{ owner := Owner }) ->
+ Response = {error, ebadf},
+ {keep_state_and_data, [{reply, From, Response}]};
+
+opened({call, {Owner, _Tag} = From}, _Command, #{ owner := Owner }) ->
+ Response = {error, enotsup},
+ {keep_state_and_data, [{reply, From, Response}]};
+
+opened({call, _From}, _Command, _Data) ->
+ %% The client functions filter this out, so we'll crash if the user does
+ %% anything stupid on purpose.
+ {shutdown, protocol_violation};
+
+opened(_Event, _Request, _Data) ->
+ keep_state_and_data.
+
+write(Data, IOVec) ->
+ #{ handle := PrivateFd, position := Position, zlib := Z } = Data,
+ UncompressedSize = iolist_size(IOVec),
+ case ?CALL_FD(PrivateFd, write, [zlib:deflate(Z, IOVec)]) of
+ ok -> {ok, Data#{ position := (Position + UncompressedSize) }};
+ Other -> Other
+ end.
+
+%%
+%% We support "seeking" forward as long as it isn't relative to EOF.
+%%
+%% Seeking is a bit of a misnomer as it's really just compressing zeroes until
+%% we reach the desired point, but it has always behaved like this.
+%%
+
+position(Data, Mark) when is_atom(Mark) ->
+ position(Data, {Mark, 0});
+position(Data, Offset) when is_integer(Offset) ->
+ position(Data, {bof, Offset});
+position(Data, {bof, Offset}) when is_integer(Offset) ->
+ position_1(Data, Offset);
+position(Data, {cur, Offset}) when is_integer(Offset) ->
+ #{ position := Position } = Data,
+ position_1(Data, Position + Offset);
+position(_Data, {eof, Offset}) when is_integer(Offset) ->
+ {error, einval};
+position(_Data, _Any) ->
+ {error, badarg}.
+
+position_1(#{ position := Desired } = Data, Desired) ->
+ {ok, Data, Desired};
+position_1(#{ position := Current } = Data, Desired) when Current < Desired ->
+ BytesToWrite = min(Desired - Current, 4 bsl 20),
+ case write(Data, <<0:(BytesToWrite)/unit:8>>) of
+ {ok, NewData} -> position_1(NewData, Desired);
+ Other -> Other
+ end;
+position_1(#{ position := Current }, Desired) when Current > Desired ->
+ {error, einval}.
+
+flush_deflate_state(#{ handle := PrivateFd, zlib := Z }) ->
+ case ?CALL_FD(PrivateFd, write, [zlib:deflate(Z, [], finish)]) of
+ ok -> ok;
+ Other -> Other
+ end.
+
+terminate(_Reason, _State, _Data) ->
+ ok.
diff --git a/lib/kernel/src/raw_file_io_delayed.erl b/lib/kernel/src/raw_file_io_delayed.erl
new file mode 100644
index 0000000000..d2ad7550a1
--- /dev/null
+++ b/lib/kernel/src/raw_file_io_delayed.erl
@@ -0,0 +1,320 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(raw_file_io_delayed).
+
+-behavior(gen_statem).
+
+-export([close/1, sync/1, datasync/1, truncate/1, advise/4, allocate/3,
+ position/2, write/2, pwrite/2, pwrite/3,
+ read_line/1, read/2, pread/2, pread/3]).
+
+%% OTP internal.
+-export([ipread_s32bu_p32bu/3, sendfile/8]).
+
+-export([open_layer/3]).
+
+-export([init/1, callback_mode/0, terminate/3]).
+-export([opening/3, opened/3]).
+
+-include("file_int.hrl").
+
+open_layer(Filename, Modes, Options) ->
+ Secret = make_ref(),
+ case gen_statem:start(?MODULE, {self(), Secret, Options}, []) of
+ {ok, Pid} ->
+ gen_statem:call(Pid, {'$open', Secret, Filename, Modes}, infinity);
+ Other ->
+ Other
+ end.
+
+callback_mode() -> state_functions.
+
+init({Owner, Secret, Options}) ->
+ Monitor = monitor(process, Owner),
+ Defaults =
+ #{ owner => Owner,
+ monitor => Monitor,
+ secret => Secret,
+ timer => none,
+ pid => self(),
+ buffer => prim_buffer:new(),
+ delay_size => 64 bsl 10,
+ delay_time => 2000 },
+ Data = fill_delay_values(Defaults, Options),
+ {ok, opening, Data}.
+
+fill_delay_values(Data, []) ->
+ Data;
+fill_delay_values(Data, [{delayed_write, Size, Time} | Options]) ->
+ fill_delay_values(Data#{ delay_size => Size, delay_time => Time }, Options);
+fill_delay_values(Data, [_ | Options]) ->
+ fill_delay_values(Data, Options).
+
+opening({call, From}, {'$open', Secret, Filename, Modes}, #{ secret := Secret } = Data) ->
+ case raw_file_io:open(Filename, Modes) of
+ {ok, PrivateFd} ->
+ PublicData = maps:with([owner, buffer, delay_size, pid], Data),
+ PublicFd = #file_descriptor{ module = ?MODULE, data = PublicData },
+
+ NewData = Data#{ handle => PrivateFd },
+ Response = {ok, PublicFd},
+ {next_state, opened, NewData, [{reply, From, Response}]};
+ Other ->
+ {stop_and_reply, normal, [{reply, From, Other}]}
+ end;
+opening(_Event, _Contents, _Data) ->
+ {keep_state_and_data, [postpone]}.
+
+%%
+
+opened(info, {'$timed_out', Secret}, #{ secret := Secret } = Data) ->
+ %% If the user writes something at this exact moment, the flush will fail
+ %% and the timer won't reset on the next write since the buffer won't be
+ %% empty (Unless we collided on a flush). We therefore reset the timeout to
+ %% ensure that data won't sit idle for extended periods of time.
+ case try_flush_write_buffer(Data) of
+ busy -> gen_statem:cast(self(), '$reset_timeout');
+ ok -> ok
+ end,
+ {keep_state, Data#{ timer => none }, []};
+
+opened(info, {'DOWN', Monitor, process, _Owner, Reason}, #{ monitor := Monitor } = Data) ->
+ if
+ Reason =/= kill -> try_flush_write_buffer(Data);
+ Reason =:= kill -> ignored
+ end,
+ {stop, shutdown};
+
+opened(info, _Message, _Data) ->
+ keep_state_and_data;
+
+opened({call, {Owner, _Tag} = From}, [close], #{ owner := Owner } = Data) ->
+ case flush_write_buffer(Data) of
+ ok ->
+ #{ handle := PrivateFd } = Data,
+ Response = ?CALL_FD(PrivateFd, close, []),
+ {stop_and_reply, normal, [{reply, From, Response}]};
+ Other ->
+ {stop_and_reply, normal, [{reply, From, Other}]}
+ end;
+
+opened({call, {Owner, _Tag} = From}, '$wait', #{ owner := Owner }) ->
+ %% Used in write/2 to synchronize writes on lock conflicts.
+ {keep_state_and_data, [{reply, From, ok}]};
+
+opened({call, {Owner, _Tag} = From}, '$synchronous_flush', #{ owner := Owner } = Data) ->
+ cancel_flush_timeout(Data),
+ Response = flush_write_buffer(Data),
+ {keep_state_and_data, [{reply, From, Response}]};
+
+opened({call, {Owner, _Tag} = From}, Command, #{ owner := Owner } = Data) ->
+ Response =
+ case flush_write_buffer(Data) of
+ ok -> dispatch_command(Data, Command);
+ Other -> Other
+ end,
+ {keep_state_and_data, [{reply, From, Response}]};
+
+opened({call, _From}, _Command, _Data) ->
+ %% The client functions filter this out, so we'll crash if the user does
+ %% anything stupid on purpose.
+ {shutdown, protocol_violation};
+
+opened(cast, '$reset_timeout', #{ delay_time := Timeout, secret := Secret } = Data) ->
+ cancel_flush_timeout(Data),
+ Timer = erlang:send_after(Timeout, self(), {'$timed_out', Secret}),
+ {keep_state, Data#{ timer => Timer }, []};
+
+opened(cast, _Message, _Data) ->
+ {keep_state_and_data, []}.
+
+dispatch_command(Data, [Function | Args]) ->
+ #{ handle := Handle } = Data,
+ Module = Handle#file_descriptor.module,
+ apply(Module, Function, [Handle | Args]).
+
+cancel_flush_timeout(#{ timer := none }) ->
+ ok;
+cancel_flush_timeout(#{ timer := Timer }) ->
+ _ = erlang:cancel_timer(Timer, [{async, true}]),
+ ok.
+
+try_flush_write_buffer(#{ buffer := Buffer, handle := PrivateFd }) ->
+ case prim_buffer:try_lock(Buffer) of
+ acquired ->
+ flush_write_buffer_1(Buffer, PrivateFd),
+ prim_buffer:unlock(Buffer),
+ ok;
+ busy ->
+ busy
+ end.
+
+%% This is only safe to use when there is no chance of conflict with the owner
+%% process, or in other words, "during synchronous calls outside of the locked
+%% section of write/2"
+flush_write_buffer(#{ buffer := Buffer, handle := PrivateFd }) ->
+ acquired = prim_buffer:try_lock(Buffer),
+ Result = flush_write_buffer_1(Buffer, PrivateFd),
+ prim_buffer:unlock(Buffer),
+ Result.
+
+flush_write_buffer_1(Buffer, PrivateFd) ->
+ case prim_buffer:size(Buffer) of
+ Size when Size > 0 ->
+ ?CALL_FD(PrivateFd, write, [prim_buffer:read_iovec(Buffer, Size)]);
+ 0 ->
+ ok
+ end.
+
+terminate(_Reason, _State, _Data) ->
+ ok.
+
+%% Client functions
+
+write(Fd, IOData) ->
+ try
+ enqueue_write(Fd, erlang:iolist_to_iovec(IOData))
+ catch
+ error:badarg -> {error, badarg}
+ end.
+enqueue_write(_Fd, []) ->
+ ok;
+enqueue_write(Fd, IOVec) ->
+ %% get_fd_data will reject everyone except the process that opened the Fd,
+ %% so we can't race with anyone except the wrapper process.
+ #{ delay_size := DelaySize,
+ buffer := Buffer,
+ pid := Pid } = get_fd_data(Fd),
+ case prim_buffer:try_lock(Buffer) of
+ acquired ->
+ %% (The wrapper process will exit without flushing if we're killed
+ %% while holding the lock).
+ enqueue_write_locked(Pid, Buffer, DelaySize, IOVec);
+ busy ->
+ %% This can only happen while we're processing a timeout in the
+ %% wrapper process, so we perform a bogus call to get a completion
+ %% notification before trying again.
+ gen_statem:call(Pid, '$wait'),
+ enqueue_write(Fd, IOVec)
+ end.
+enqueue_write_locked(Pid, Buffer, DelaySize, IOVec) ->
+ %% The synchronous operations (write, forced flush) are safe since we're
+ %% running on the only process that can fill the buffer; a timeout being
+ %% processed just before $synchronous_flush will cause the flush to nop,
+ %% and a timeout sneaking in just before a synchronous write won't do
+ %% anything since the buffer is guaranteed to be empty at that point.
+ BufSize = prim_buffer:size(Buffer),
+ case is_iovec_smaller_than(IOVec, DelaySize - BufSize) of
+ true when BufSize > 0 ->
+ prim_buffer:write(Buffer, IOVec),
+ prim_buffer:unlock(Buffer);
+ true ->
+ prim_buffer:write(Buffer, IOVec),
+ prim_buffer:unlock(Buffer),
+ gen_statem:cast(Pid, '$reset_timeout');
+ false when BufSize > 0 ->
+ prim_buffer:write(Buffer, IOVec),
+ prim_buffer:unlock(Buffer),
+ gen_statem:call(Pid, '$synchronous_flush');
+ false ->
+ prim_buffer:unlock(Buffer),
+ gen_statem:call(Pid, [write, IOVec])
+ end.
+
+%% iolist_size/1 will always look through the entire list to get a precise
+%% amount, which is pretty inefficient since we only need to know whether we've
+%% hit the buffer threshold or not.
+%%
+%% We only handle the binary case since write/2 forcibly translates input to
+%% erlang:iovec().
+is_iovec_smaller_than(IOVec, Max) ->
+ is_iovec_smaller_than_1(IOVec, Max, 0).
+is_iovec_smaller_than_1(_IOVec, Max, Acc) when Acc >= Max ->
+ false;
+is_iovec_smaller_than_1([], _Max, _Acc) ->
+ true;
+is_iovec_smaller_than_1([Binary | Rest], Max, Acc) when is_binary(Binary) ->
+ is_iovec_smaller_than_1(Rest, Max, Acc + byte_size(Binary)).
+
+close(Fd) ->
+ wrap_call(Fd, [close]).
+
+sync(Fd) ->
+ wrap_call(Fd, [sync]).
+datasync(Fd) ->
+ wrap_call(Fd, [datasync]).
+
+truncate(Fd) ->
+ wrap_call(Fd, [truncate]).
+
+advise(Fd, Offset, Length, Advise) ->
+ wrap_call(Fd, [advise, Offset, Length, Advise]).
+allocate(Fd, Offset, Length) ->
+ wrap_call(Fd, [allocate, Offset, Length]).
+
+position(Fd, Mark) ->
+ wrap_call(Fd, [position, Mark]).
+
+pwrite(Fd, Offset, IOData) ->
+ try
+ CompactedData = erlang:iolist_to_iovec(IOData),
+ wrap_call(Fd, [pwrite, Offset, CompactedData])
+ catch
+ error:badarg -> {error, badarg}
+ end.
+pwrite(Fd, LocBytes) ->
+ try
+ CompactedLocBytes =
+ [ {Offset, erlang:iolist_to_iovec(IOData)} ||
+ {Offset, IOData} <- LocBytes ],
+ wrap_call(Fd, [pwrite, CompactedLocBytes])
+ catch
+ error:badarg -> {error, badarg}
+ end.
+
+read_line(Fd) ->
+ wrap_call(Fd, [read_line]).
+read(Fd, Size) ->
+ wrap_call(Fd, [read, Size]).
+pread(Fd, Offset, Size) ->
+ wrap_call(Fd, [pread, Offset, Size]).
+pread(Fd, LocNums) ->
+ wrap_call(Fd, [pread, LocNums]).
+
+ipread_s32bu_p32bu(Fd, Offset, MaxSize) ->
+ wrap_call(Fd, [ipread_s32bu_p32bu, Offset, MaxSize]).
+
+sendfile(_,_,_,_,_,_,_,_) ->
+ {error, enotsup}.
+
+wrap_call(Fd, Command) ->
+ #{ pid := Pid } = get_fd_data(Fd),
+ try gen_statem:call(Pid, Command, infinity) of
+ Result -> Result
+ catch
+ exit:{noproc, _StackTrace} -> {error, einval}
+ end.
+
+get_fd_data(#file_descriptor{ data = Data }) ->
+ #{ owner := Owner } = Data,
+ case self() of
+ Owner -> Data;
+ _ -> error(not_on_controlling_process)
+ end.
diff --git a/lib/kernel/src/raw_file_io_inflate.erl b/lib/kernel/src/raw_file_io_inflate.erl
new file mode 100644
index 0000000000..7e9780310c
--- /dev/null
+++ b/lib/kernel/src/raw_file_io_inflate.erl
@@ -0,0 +1,261 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(raw_file_io_inflate).
+
+-behavior(gen_statem).
+
+-export([init/1, callback_mode/0, terminate/3]).
+-export([opening/3, opened_gzip/3, opened_passthrough/3]).
+
+-include("file_int.hrl").
+
+-define(INFLATE_CHUNK_SIZE, (1 bsl 10)).
+-define(GZIP_WBITS, (16 + 15)).
+
+callback_mode() -> state_functions.
+
+init({Owner, Secret, [compressed]}) ->
+ Monitor = monitor(process, Owner),
+ %% We're using the undocumented inflateInit/3 to open the stream in
+ %% 'reset mode', which resets the inflate state at the end of every stream,
+ %% allowing us to read concatenated gzip files.
+ Z = zlib:open(),
+ ok = zlib:inflateInit(Z, ?GZIP_WBITS, reset),
+ Data =
+ #{ owner => Owner,
+ monitor => Monitor,
+ secret => Secret,
+ position => 0,
+ buffer => prim_buffer:new(),
+ zlib => Z },
+ {ok, opening, Data}.
+
+%% The old driver fell back to plain reads if the file didn't start with the
+%% magic gzip bytes.
+choose_decompression_state(PrivateFd) ->
+ State =
+ case ?CALL_FD(PrivateFd, read, [2]) of
+ {ok, <<16#1F, 16#8B>>} -> opened_gzip;
+ _Other -> opened_passthrough
+ end,
+ {ok, 0} = ?CALL_FD(PrivateFd, position, [0]),
+ State.
+
+opening({call, From}, {'$open', Secret, Filename, Modes}, #{ secret := Secret } = Data) ->
+ case raw_file_io:open(Filename, Modes) of
+ {ok, PrivateFd} ->
+ NextState = choose_decompression_state(PrivateFd),
+ NewData = Data#{ handle => PrivateFd },
+ {next_state, NextState, NewData, [{reply, From, ok}]};
+ Other ->
+ {stop_and_reply, normal, [{reply, From, Other}]}
+ end;
+opening(_Event, _Contents, _Data) ->
+ {keep_state_and_data, [postpone]}.
+
+internal_close(From, Data) ->
+ #{ handle := PrivateFd } = Data,
+ Response = ?CALL_FD(PrivateFd, close, []),
+ {stop_and_reply, normal, [{reply, From, Response}]}.
+
+opened_passthrough(info, {'DOWN', Monitor, process, _Owner, _Reason}, #{ monitor := Monitor }) ->
+ {stop, shutdown};
+
+opened_passthrough(info, _Message, _Data) ->
+ keep_state_and_data;
+
+opened_passthrough({call, {Owner, _Tag} = From}, [close], #{ owner := Owner } = Data) ->
+ internal_close(From, Data);
+
+opened_passthrough({call, {Owner, _Tag} = From}, [Method | Args], #{ owner := Owner } = Data) ->
+ #{ handle := PrivateFd } = Data,
+ Response = ?CALL_FD(PrivateFd, Method, Args),
+ {keep_state_and_data, [{reply, From, Response}]};
+
+opened_passthrough({call, _From}, _Command, _Data) ->
+ %% The client functions filter this out, so we'll crash if the user does
+ %% anything stupid on purpose.
+ {shutdown, protocol_violation};
+
+opened_passthrough(_Event, _Request, _Data) ->
+ keep_state_and_data.
+
+%%
+
+opened_gzip(info, {'DOWN', Monitor, process, _Owner, _Reason}, #{ monitor := Monitor }) ->
+ {stop, shutdown};
+
+opened_gzip(info, _Message, _Data) ->
+ keep_state_and_data;
+
+opened_gzip({call, {Owner, _Tag} = From}, [close], #{ owner := Owner } = Data) ->
+ internal_close(From, Data);
+
+opened_gzip({call, {Owner, _Tag} = From}, [position, Mark], #{ owner := Owner } = Data) ->
+ case position(Data, Mark) of
+ {ok, NewData, Result} ->
+ Response = {ok, Result},
+ {keep_state, NewData, [{reply, From, Response}]};
+ Other ->
+ {keep_state_and_data, [{reply, From, Other}]}
+ end;
+
+opened_gzip({call, {Owner, _Tag} = From}, [read, Size], #{ owner := Owner } = Data) ->
+ case read(Data, Size) of
+ {ok, NewData, Result} ->
+ Response = {ok, Result},
+ {keep_state, NewData, [{reply, From, Response}]};
+ Other ->
+ {keep_state_and_data, [{reply, From, Other}]}
+ end;
+
+opened_gzip({call, {Owner, _Tag} = From}, [read_line], #{ owner := Owner } = Data) ->
+ case read_line(Data) of
+ {ok, NewData, Result} ->
+ Response = {ok, Result},
+ {keep_state, NewData, [{reply, From, Response}]};
+ Other ->
+ {keep_state_and_data, [{reply, From, Other}]}
+ end;
+
+opened_gzip({call, {Owner, _Tag} = From}, [write, _IOData], #{ owner := Owner }) ->
+ Response = {error, ebadf},
+ {keep_state_and_data, [{reply, From, Response}]};
+
+opened_gzip({call, {Owner, _Tag} = From}, _Request, #{ owner := Owner }) ->
+ Response = {error, enotsup},
+ {keep_state_and_data, [{reply, From, Response}]};
+
+opened_gzip({call, _From}, _Request, _Data) ->
+ %% The client functions filter this out, so we'll crash if the user does
+ %% anything stupid on purpose.
+ {shutdown, protocol_violation};
+
+opened_gzip(_Event, _Request, _Data) ->
+ keep_state_and_data.
+
+%%
+
+read(#{ buffer := Buffer } = Data, Size) ->
+ try read_1(Data, Buffer, prim_buffer:size(Buffer), Size) of
+ Result -> Result
+ catch
+ error:badarg -> {error, badarg};
+ error:_ -> {error, eio}
+ end.
+read_1(Data, Buffer, BufferSize, ReadSize) when BufferSize >= ReadSize ->
+ #{ position := Position } = Data,
+ Decompressed = prim_buffer:read(Buffer, ReadSize),
+ {ok, Data#{ position => (Position + ReadSize) }, Decompressed};
+read_1(Data, Buffer, BufferSize, ReadSize) when BufferSize < ReadSize ->
+ #{ handle := PrivateFd } = Data,
+ case ?CALL_FD(PrivateFd, read, [?INFLATE_CHUNK_SIZE]) of
+ {ok, Compressed} ->
+ #{ zlib := Z } = Data,
+ Uncompressed = erlang:iolist_to_iovec(zlib:inflate(Z, Compressed)),
+ prim_buffer:write(Buffer, Uncompressed),
+ read_1(Data, Buffer, prim_buffer:size(Buffer), ReadSize);
+ eof when BufferSize > 0 ->
+ read_1(Data, Buffer, BufferSize, BufferSize);
+ Other ->
+ Other
+ end.
+
+read_line(#{ buffer := Buffer } = Data) ->
+ try read_line_1(Data, Buffer, prim_buffer:find_byte_index(Buffer, $\n)) of
+ {ok, NewData, Decompressed} -> {ok, NewData, Decompressed};
+ Other -> Other
+ catch
+ error:badarg -> {error, badarg};
+ error:_ -> {error, eio}
+ end.
+
+read_line_1(Data, Buffer, not_found) ->
+ #{ handle := PrivateFd, zlib := Z } = Data,
+ case ?CALL_FD(PrivateFd, read, [?INFLATE_CHUNK_SIZE]) of
+ {ok, Compressed} ->
+ Uncompressed = erlang:iolist_to_iovec(zlib:inflate(Z, Compressed)),
+ prim_buffer:write(Buffer, Uncompressed),
+ read_line_1(Data, Buffer, prim_buffer:find_byte_index(Buffer, $\n));
+ eof ->
+ case prim_buffer:size(Buffer) of
+ Size when Size > 0 -> {ok, prim_buffer:read(Buffer, Size)};
+ Size when Size =:= 0 -> eof
+ end;
+ Error ->
+ Error
+ end;
+read_line_1(Data, Buffer, {ok, LFIndex}) ->
+ %% Translate CRLF into just LF, completely ignoring which encoding is used,
+ %% but treat the file position as including CR.
+ #{ position := Position } = Data,
+ NewData = Data#{ position => (Position + LFIndex + 1) },
+ CRIndex = (LFIndex - 1),
+ TranslatedLine =
+ case prim_buffer:read(Buffer, LFIndex + 1) of
+ <<Line:CRIndex/binary, "\r\n">> -> <<Line/binary, "\n">>;
+ Line -> Line
+ end,
+ {ok, NewData, TranslatedLine}.
+
+%%
+%% We support seeking in both directions as long as it isn't relative to EOF.
+%%
+%% Seeking backwards is extremely inefficient since we have to seek to the very
+%% beginning and then decompress up to the desired point.
+%%
+
+position(Data, Mark) when is_atom(Mark) ->
+ position(Data, {Mark, 0});
+position(Data, Offset) when is_integer(Offset) ->
+ position(Data, {bof, Offset});
+position(Data, {bof, Offset}) when is_integer(Offset) ->
+ position_1(Data, Offset);
+position(Data, {cur, Offset}) when is_integer(Offset) ->
+ #{ position := Position } = Data,
+ position_1(Data, Position + Offset);
+position(_Data, {eof, Offset}) when is_integer(Offset) ->
+ {error, einval};
+position(_Data, _Other) ->
+ {error, badarg}.
+
+position_1(_Data, Desired) when Desired < 0 ->
+ {error, einval};
+position_1(#{ position := Desired } = Data, Desired) ->
+ {ok, Data, Desired};
+position_1(#{ position := Current } = Data, Desired) when Current < Desired ->
+ case read(Data, min(Desired - Current, ?INFLATE_CHUNK_SIZE)) of
+ {ok, NewData, _Data} -> position_1(NewData, Desired);
+ eof -> {ok, Data, Current};
+ Other -> Other
+ end;
+position_1(#{ position := Current } = Data, Desired) when Current > Desired ->
+ #{ handle := PrivateFd, buffer := Buffer, zlib := Z } = Data,
+ case ?CALL_FD(PrivateFd, position, [bof]) of
+ {ok, 0} ->
+ ok = zlib:inflateReset(Z),
+ prim_buffer:wipe(Buffer),
+ position_1(Data#{ position => 0 }, Desired);
+ Other ->
+ Other
+ end.
+
+terminate(_Reason, _State, _Data) ->
+ ok.
diff --git a/lib/kernel/src/raw_file_io_list.erl b/lib/kernel/src/raw_file_io_list.erl
new file mode 100644
index 0000000000..2e16e63f0e
--- /dev/null
+++ b/lib/kernel/src/raw_file_io_list.erl
@@ -0,0 +1,128 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(raw_file_io_list).
+
+-export([close/1, sync/1, datasync/1, truncate/1, advise/4, allocate/3,
+ position/2, write/2, pwrite/2, pwrite/3,
+ read_line/1, read/2, pread/2, pread/3]).
+
+%% OTP internal.
+-export([ipread_s32bu_p32bu/3, sendfile/8]).
+
+-export([open_layer/3]).
+
+-include("file_int.hrl").
+
+open_layer(Filename, Modes, [list]) ->
+ case raw_file_io:open(Filename, [binary | Modes]) of
+ {ok, PrivateFd} -> {ok, make_public_fd(PrivateFd, Modes)};
+ Other -> Other
+ end.
+
+%% We can skip wrapping the file if it's write-only since only read operations
+%% are affected by list mode. Since raw_file_io fills in all implicit options
+%% for us, all we need to do is check whether 'read' is among them.
+make_public_fd(PrivateFd, Modes) ->
+ case lists:member(read, Modes) of
+ true -> #file_descriptor{ module = ?MODULE, data = PrivateFd };
+ false -> PrivateFd
+ end.
+
+close(Fd) ->
+ PrivateFd = Fd#file_descriptor.data,
+ ?CALL_FD(PrivateFd, close, []).
+
+sync(Fd) ->
+ PrivateFd = Fd#file_descriptor.data,
+ ?CALL_FD(PrivateFd, sync, []).
+datasync(Fd) ->
+ PrivateFd = Fd#file_descriptor.data,
+ ?CALL_FD(PrivateFd, datasync, []).
+
+truncate(Fd) ->
+ PrivateFd = Fd#file_descriptor.data,
+ ?CALL_FD(PrivateFd, truncate, []).
+
+advise(Fd, Offset, Length, Advise) ->
+ PrivateFd = Fd#file_descriptor.data,
+ ?CALL_FD(PrivateFd, advise, [Offset, Length, Advise]).
+allocate(Fd, Offset, Length) ->
+ PrivateFd = Fd#file_descriptor.data,
+ ?CALL_FD(PrivateFd, allocate, [Offset, Length]).
+
+position(Fd, Mark) ->
+ PrivateFd = Fd#file_descriptor.data,
+ ?CALL_FD(PrivateFd, position, [Mark]).
+
+write(Fd, IOData) ->
+ PrivateFd = Fd#file_descriptor.data,
+ ?CALL_FD(PrivateFd, write, [IOData]).
+
+pwrite(Fd, Offset, IOData) ->
+ PrivateFd = Fd#file_descriptor.data,
+ ?CALL_FD(PrivateFd, pwrite, [Offset, IOData]).
+pwrite(Fd, LocBytes) ->
+ PrivateFd = Fd#file_descriptor.data,
+ ?CALL_FD(PrivateFd, pwrite, [LocBytes]).
+
+read_line(Fd) ->
+ PrivateFd = Fd#file_descriptor.data,
+ case ?CALL_FD(PrivateFd, read_line, []) of
+ {ok, Binary} -> {ok, binary_to_list(Binary)};
+ Other -> Other
+ end.
+read(Fd, Size) ->
+ PrivateFd = Fd#file_descriptor.data,
+ case ?CALL_FD(PrivateFd, read, [Size]) of
+ {ok, Binary} -> {ok, binary_to_list(Binary)};
+ Other -> Other
+ end.
+pread(Fd, Offset, Size) ->
+ PrivateFd = Fd#file_descriptor.data,
+ case ?CALL_FD(PrivateFd, pread, [Offset, Size]) of
+ {ok, Binary} -> {ok, binary_to_list(Binary)};
+ Other -> Other
+ end.
+pread(Fd, LocNums) ->
+ PrivateFd = Fd#file_descriptor.data,
+ case ?CALL_FD(PrivateFd, pread, [LocNums]) of
+ {ok, LocResults} ->
+ TranslatedResults =
+ [ case Result of
+ Result when is_binary(Result) -> binary_to_list(Result);
+ eof -> eof
+ end || Result <- LocResults ],
+ {ok, TranslatedResults};
+ Other -> Other
+ end.
+
+ipread_s32bu_p32bu(Fd, Offset, MaxSize) ->
+ PrivateFd = Fd#file_descriptor.data,
+ case ?CALL_FD(PrivateFd, ipread_s32bu_p32bu, [Offset, MaxSize]) of
+ {ok, {Size, Pointer, Binary}} when is_binary(Binary) ->
+ {ok, {Size, Pointer, binary_to_list(Binary)}};
+ Other ->
+ Other
+ end.
+
+sendfile(Fd, Dest, Offset, Bytes, ChunkSize, Headers, Trailers, Flags) ->
+ Args = [Dest, Offset, Bytes, ChunkSize, Headers, Trailers, Flags],
+ PrivateFd = Fd#file_descriptor.data,
+ ?CALL_FD(PrivateFd, sendfile, Args).
diff --git a/lib/kernel/src/raw_file_io_raw.erl b/lib/kernel/src/raw_file_io_raw.erl
new file mode 100644
index 0000000000..9a9fe78eb1
--- /dev/null
+++ b/lib/kernel/src/raw_file_io_raw.erl
@@ -0,0 +1,25 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(raw_file_io_raw).
+
+-export([open_layer/3]).
+
+open_layer(Filename, Modes, [raw]) ->
+ prim_file:open(Filename, [raw | Modes]).
diff --git a/lib/kernel/src/rpc.erl b/lib/kernel/src/rpc.erl
index 0e0b7dffa3..d197de942f 100644
--- a/lib/kernel/src/rpc.erl
+++ b/lib/kernel/src/rpc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -418,10 +418,7 @@ abcast(Name, Mess) ->
abcast([Node|Tail], Name, Mess) ->
Dest = {Name,Node},
- case catch erlang:send(Dest, Mess, [noconnect]) of
- noconnect -> spawn(erlang, send, [Dest,Mess]), ok;
- _ -> ok
- end,
+ try erlang:send(Dest, Mess) catch error:_ -> ok end,
abcast(Tail, Name, Mess);
abcast([], _,_) -> abcast.
@@ -498,7 +495,7 @@ start_monitor(Node, Name) ->
Module :: module(),
Function :: atom(),
Args :: [term()],
- ResL :: [term()],
+ ResL :: [Res :: term() | {'badrpc', Reason :: term()}],
BadNodes :: [node()].
multicall(M, F, A) ->
@@ -509,14 +506,14 @@ multicall(M, F, A) ->
Module :: module(),
Function :: atom(),
Args :: [term()],
- ResL :: [term()],
+ ResL :: [Res :: term() | {'badrpc', Reason :: term()}],
BadNodes :: [node()];
(Module, Function, Args, Timeout) -> {ResL, BadNodes} when
Module :: module(),
Function :: atom(),
Args :: [term()],
Timeout :: timeout(),
- ResL :: [term()],
+ ResL :: [Res :: term() | {'badrpc', Reason :: term()}],
BadNodes :: [node()].
multicall(Nodes, M, F, A) when is_list(Nodes) ->
@@ -531,7 +528,7 @@ multicall(M, F, A, Timeout) ->
Function :: atom(),
Args :: [term()],
Timeout :: timeout(),
- ResL :: [term()],
+ ResL :: [Res :: term() | {'badrpc', Reason :: term()}],
BadNodes :: [node()].
multicall(Nodes, M, F, A, infinity)
diff --git a/lib/kernel/src/seq_trace.erl b/lib/kernel/src/seq_trace.erl
index cc0c10909b..14fe21e9de 100644
--- a/lib/kernel/src/seq_trace.erl
+++ b/lib/kernel/src/seq_trace.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@
-type flag() :: 'send' | 'receive' | 'print' | 'timestamp' | 'monotonic_timestamp' | 'strict_monotonic_timestamp'.
-type component() :: 'label' | 'serial' | flag().
--type value() :: (Integer :: non_neg_integer())
+-type value() :: (Label :: term())
| {Previous :: non_neg_integer(),
Current :: non_neg_integer()}
| (Bool :: boolean()).
@@ -59,10 +59,6 @@ set_token({Flags,Label,Serial,_From,Lastcnt}) ->
F = decode_flags(Flags),
set_token2([{label,Label},{serial,{Lastcnt, Serial}} | F]).
-%% We limit the label type to always be a small integer because erl_interface
-%% expects that, the BIF can however "unofficially" handle atoms as well, and
-%% atoms can be used if only Erlang nodes are involved
-
-spec set_token(Component, Val) -> {Component, OldVal} when
Component :: component(),
Val :: value(),
diff --git a/lib/kernel/src/user.erl b/lib/kernel/src/user.erl
index a5cc7b0ec1..872e63ab53 100644
--- a/lib/kernel/src/user.erl
+++ b/lib/kernel/src/user.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -398,7 +398,7 @@ get_line(Prompt, Port, Q, Acc, Enc) ->
get_line_bytes(Prompt, Port, Q, Acc, Bytes, Enc);
{Port, eof} ->
put(eof, true),
- {ok, eof, []};
+ {ok, eof, queue:new()};
{io_request,From,ReplyAs,{get_geometry,_}=Req} when is_pid(From) ->
do_io_request(Req, From, ReplyAs, Port,
queue:new()),
@@ -615,7 +615,7 @@ get_chars(Prompt, M, F, Xa, Port, Q, State, Enc) ->
get_chars_bytes(State, M, F, Xa, Port, Q, Bytes, Enc);
{Port, eof} ->
put(eof, true),
- {ok, eof, []};
+ {ok, eof, queue:new()};
%%{io_request,From,ReplyAs,Request} when is_pid(From) ->
%% get_chars_req(Prompt, M, F, Xa, Port, queue:new(), State,
%% Request, From, ReplyAs);
diff --git a/lib/kernel/src/user_drv.erl b/lib/kernel/src/user_drv.erl
index b794d4f45e..9f914aa222 100644
--- a/lib/kernel/src/user_drv.erl
+++ b/lib/kernel/src/user_drv.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -175,6 +175,18 @@ server_loop(Iport, Oport, Curr, User, Gr, {Resp, IOQ} = IOQueue) ->
{Iport,eof} ->
Curr ! {self(),eof},
server_loop(Iport, Oport, Curr, User, Gr, IOQueue);
+
+ %% We always handle geometry and unicode requests
+ {Requester,tty_geometry} ->
+ Requester ! {self(),tty_geometry,get_tty_geometry(Iport)},
+ server_loop(Iport, Oport, Curr, User, Gr, IOQueue);
+ {Requester,get_unicode_state} ->
+ Requester ! {self(),get_unicode_state,get_unicode_state(Iport)},
+ server_loop(Iport, Oport, Curr, User, Gr, IOQueue);
+ {Requester,set_unicode_state, Bool} ->
+ Requester ! {self(),set_unicode_state,set_unicode_state(Iport,Bool)},
+ server_loop(Iport, Oport, Curr, User, Gr, IOQueue);
+
Req when element(1,Req) =:= User orelse element(1,Req) =:= Curr,
tuple_size(Req) =:= 2 orelse tuple_size(Req) =:= 3 ->
%% We match {User|Curr,_}|{User|Curr,_,_}
@@ -224,21 +236,16 @@ server_loop(Iport, Oport, Curr, User, Gr, {Resp, IOQ} = IOQueue) ->
_ -> % not current, just remove it
server_loop(Iport, Oport, Curr, User, gr_del_pid(Gr, Pid), IOQueue)
end;
+ {Requester, {put_chars_sync, _, _, Reply}} ->
+ %% We need to ack the Req otherwise originating process will hang forever
+ %% Do discard the output to non visible shells (as was done previously)
+ Requester ! {reply, Reply},
+ server_loop(Iport, Oport, Curr, User, Gr, IOQueue);
_X ->
- %% Ignore unknown messages.
- server_loop(Iport, Oport, Curr, User, Gr, IOQueue)
+ %% Ignore unknown messages.
+ server_loop(Iport, Oport, Curr, User, Gr, IOQueue)
end.
-%% We always handle geometry and unicode requests
-handle_req({Curr,tty_geometry},Iport,_Oport,IOQueue) ->
- Curr ! {self(),tty_geometry,get_tty_geometry(Iport)},
- IOQueue;
-handle_req({Curr,get_unicode_state},Iport,_Oport,IOQueue) ->
- Curr ! {self(),get_unicode_state,get_unicode_state(Iport)},
- IOQueue;
-handle_req({Curr,set_unicode_state, Bool},Iport,_Oport,IOQueue) ->
- Curr ! {self(),set_unicode_state,set_unicode_state(Iport,Bool)},
- IOQueue;
handle_req(next,Iport,Oport,{false,IOQ}=IOQueue) ->
case queue:out(IOQ) of
{empty,_} ->
diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile
index b9942e899f..4a86265a4a 100644
--- a/lib/kernel/test/Makefile
+++ b/lib/kernel/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -70,6 +70,15 @@ MODULES= \
interactive_shell_SUITE \
init_SUITE \
kernel_config_SUITE \
+ logger_SUITE \
+ logger_disk_log_h_SUITE \
+ logger_env_var_SUITE \
+ logger_filters_SUITE \
+ logger_formatter_SUITE \
+ logger_legacy_SUITE \
+ logger_simple_h_SUITE \
+ logger_std_h_SUITE \
+ logger_test_lib \
os_SUITE \
pg2_SUITE \
seq_trace_SUITE \
@@ -80,7 +89,8 @@ MODULES= \
loose_node \
sendfile_SUITE \
standard_error_SUITE \
- multi_load_SUITE
+ multi_load_SUITE \
+ zzz_SUITE
APP_FILES = \
appinc.app \
@@ -101,7 +111,7 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
INSTALL_PROGS= $(TARGET_FILES)
EMAKEFILE=Emakefile
-COVERFILE=kernel.cover
+COVERFILE=kernel.cover logger.cover
# ----------------------------------------------------
# Release directory specification
@@ -148,8 +158,9 @@ release_tests_spec: make_emakefile
$(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) $(ERL_FILES) "$(RELSYSDIR)"
$(INSTALL_DATA) $(APP_FILES) "$(RELSYSDIR)"
- $(INSTALL_DATA) kernel.spec kernel_smoke.spec $(EMAKEFILE)\
- $(COVERFILE) "$(RELSYSDIR)"
+ $(INSTALL_DATA) \
+ kernel.spec kernel_smoke.spec kernel_bench.spec logger.spec \
+ $(EMAKEFILE) $(COVERFILE) "$(RELSYSDIR)"
chmod -R u+w "$(RELSYSDIR)"
@tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
diff --git a/lib/kernel/test/application_SUITE.erl b/lib/kernel/test/application_SUITE.erl
index 866043cfb4..5c35b82207 100644
--- a/lib/kernel/test/application_SUITE.erl
+++ b/lib/kernel/test/application_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -37,7 +37,8 @@
-export([config_change/1, persistent_env/1,
distr_changed_tc1/1, distr_changed_tc2/1,
ensure_started/1, ensure_all_started/1,
- shutdown_func/1, do_shutdown/1, shutdown_timeout/1, shutdown_deadlock/1]).
+ shutdown_func/1, do_shutdown/1, shutdown_timeout/1, shutdown_deadlock/1,
+ config_relative_paths/1]).
-define(TESTCASE, testcase_name).
-define(testcase, proplists:get_value(?TESTCASE, Config)).
@@ -55,7 +56,7 @@ all() ->
script_start, nodedown_start, permit_false_start_local,
permit_false_start_dist, get_key, get_env, ensure_all_started,
{group, distr_changed}, config_change, shutdown_func, shutdown_timeout,
- shutdown_deadlock,
+ shutdown_deadlock, config_relative_paths,
persistent_env].
groups() ->
@@ -1568,7 +1569,8 @@ loop5606(Pid) ->
%% Tests get_env/* functions.
get_env(Conf) when is_list(Conf) ->
- {ok, _} = application:get_env(kernel, error_logger),
+ ok = application:set_env(kernel, new_var, new_val),
+ {ok, new_val} = application:get_env(kernel, new_var),
undefined = application:get_env(undefined_app, a),
undefined = application:get_env(kernel, error_logger_xyz),
default = application:get_env(kernel, error_logger_xyz, default),
@@ -1602,8 +1604,7 @@ get_key(Conf) when is_list(Conf) ->
{ok, [{init, [kalle]}, {takeover, []}, {go, [sune]}]} =
rpc:call(Cp1, application, get_key, [appinc, start_phases]),
{ok, Env} = rpc:call(Cp1, application, get_key, [appinc ,env]),
- [{included_applications,[appinc1,appinc2]},
- {own2,val2},{own_env1,value1}] = lists:sort(Env),
+ [{own2,val2},{own_env1,value1}] = lists:sort(Env),
{ok, []} = rpc:call(Cp1, application, get_key, [appinc, modules]),
{ok, {application_starter, [ch_sup, {appinc, 41, 43}] }} =
rpc:call(Cp1, application, get_key, [appinc, mod]),
@@ -1624,8 +1625,7 @@ get_key(Conf) when is_list(Conf) ->
{mod, {application_starter, [ch_sup, {appinc, 41, 43}] }},
{start_phases, [{init, [kalle]}, {takeover, []}, {go, [sune]}]}]} =
rpc:call(Cp1, application, get_all_key, [appinc]),
- [{included_applications,[appinc1,appinc2]},
- {own2,val2},{own_env1,value1}] = lists:sort(Env),
+ [{own2,val2},{own_env1,value1}] = lists:sort(Env),
{ok, "Test of new app file, including appnew"} =
gen_server:call({global, {ch,41}}, {get_pid_key, description}),
@@ -1642,8 +1642,7 @@ get_key(Conf) when is_list(Conf) ->
{ok, [{init, [kalle]}, {takeover, []}, {go, [sune]}]} =
gen_server:call({global, {ch,41}}, {get_pid_key, start_phases}),
{ok, Env} = gen_server:call({global, {ch,41}}, {get_pid_key, env}),
- [{included_applications,[appinc1,appinc2]},
- {own2,val2},{own_env1,value1}] = lists:sort(Env),
+ [{own2,val2},{own_env1,value1}] = lists:sort(Env),
{ok, []} =
gen_server:call({global, {ch,41}}, {get_pid_key, modules}),
{ok, {application_starter, [ch_sup, {appinc, 41, 43}] }} =
@@ -1670,8 +1669,7 @@ get_key(Conf) when is_list(Conf) ->
{mod, {application_starter, [ch_sup, {appinc, 41, 43}] }},
{start_phases, [{init, [kalle]}, {takeover, []}, {go, [sune]}]}]} =
gen_server:call({global, {ch,41}}, get_pid_all_key),
- [{included_applications,[appinc1,appinc2]},
- {own2,val2},{own_env1,value1}] = lists:sort(Env),
+ [{own2,val2},{own_env1,value1}] = lists:sort(Env),
stop_node_nice(Cp1),
ok.
@@ -2078,6 +2076,42 @@ shutdown_deadlock(Config) when is_list(Config) ->
%%-----------------------------------------------------------------
+%% Relative paths in sys.config
+%%-----------------------------------------------------------------
+config_relative_paths(Config) ->
+ Dir = ?config(priv_dir,Config),
+ SubDir = filename:join(Dir,"subdir"),
+ Sys = filename:join(SubDir,"sys.config"),
+ ok = filelib:ensure_dir(Sys),
+ ok = file:write_file(Sys,"[\"../up.config\",\"current\"].\n"),
+
+ Up = filename:join(Dir,"up.config"),
+ ok = file:write_file(Up,"[{app1,[{key1,value}]}].\n"),
+
+ {ok,Cwd} = file:get_cwd(),
+ Current1 = filename:join(Cwd,"current.config"),
+ ok = file:write_file(Current1,"[{app1,[{key2,value1}]}].\n"),
+
+ N1 = list_to_atom(lists:concat([?FUNCTION_NAME,"_1"])),
+ {ok,Node1} = start_node(N1,filename:rootname(Sys)),
+ ok = rpc:call(Node1, application, load, [app1()]),
+ {ok, value} = rpc:call(Node1, application, get_env,[app1,key1]),
+ {ok, value1} = rpc:call(Node1, application, get_env,[app1,key2]),
+
+ Current2 = filename:join(SubDir,"current.config"),
+ ok = file:write_file(Current2,"[{app1,[{key2,value2}]}].\n"),
+
+ N2 = list_to_atom(lists:concat([?FUNCTION_NAME,"_2"])),
+ {ok, Node2} = start_node(N2,filename:rootname(Sys)),
+ ok = rpc:call(Node2, application, load, [app1()]),
+ {ok, value} = rpc:call(Node2, application, get_env,[app1,key1]),
+ {ok, value2} = rpc:call(Node2, application, get_env,[app1,key2]),
+
+ stop_node_nice([Node1,Node2]),
+
+ ok.
+
+%%-----------------------------------------------------------------
%% Utility functions
%%-----------------------------------------------------------------
app0() ->
diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl
index 6f8e949aac..1314316c13 100644
--- a/lib/kernel/test/code_SUITE.erl
+++ b/lib/kernel/test/code_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@
purge_stacktrace/1, mult_lib_roots/1, bad_erl_libs/1,
code_archive/1, code_archive2/1, on_load/1, on_load_binary/1,
on_load_embedded/1, on_load_errors/1, on_load_update/1,
+ on_load_trace_on_load/1,
on_load_purge/1, on_load_self_call/1, on_load_pending/1,
on_load_deleted/1,
big_boot_embedded/1,
@@ -66,14 +67,16 @@ all() ->
ext_mod_dep, clash, where_is_file,
purge_stacktrace, mult_lib_roots,
bad_erl_libs, code_archive, code_archive2, on_load,
- on_load_binary, on_load_embedded, on_load_errors, on_load_update,
+ on_load_binary, on_load_embedded, on_load_errors,
+ {group, sequence},
on_load_purge, on_load_self_call, on_load_pending,
on_load_deleted,
module_status,
big_boot_embedded, native_early_modules, get_mode, normalized_paths].
-groups() ->
- [].
+%% These need to run in order
+groups() -> [{sequence, [sequence], [on_load_update,
+ on_load_trace_on_load]}].
init_per_group(_GroupName, Config) ->
Config.
@@ -928,37 +931,34 @@ purge_stacktrace(Config) when is_list(Config) ->
code:purge(code_b_test),
try code_b_test:call(fun(b) -> ok end, a)
catch
- error:function_clause ->
+ error:function_clause:Stacktrace ->
code:load_file(code_b_test),
- case erlang:get_stacktrace() of
+ case Stacktrace of
[{?MODULE,_,[a],_},
{code_b_test,call,2,_},
{?MODULE,purge_stacktrace,1,_}|_] ->
- false = code:purge(code_b_test),
- [] = erlang:get_stacktrace()
+ false = code:purge(code_b_test)
end
end,
try code_b_test:call(nofun, 2)
catch
- error:function_clause ->
+ error:function_clause:Stacktrace2 ->
code:load_file(code_b_test),
- case erlang:get_stacktrace() of
+ case Stacktrace2 of
[{code_b_test,call,[nofun,2],_},
{?MODULE,purge_stacktrace,1,_}|_] ->
- false = code:purge(code_b_test),
- [] = erlang:get_stacktrace()
+ false = code:purge(code_b_test)
end
end,
Args = [erlang,error,[badarg]],
try code_b_test:call(erlang, error, [badarg,Args])
catch
- error:badarg ->
+ error:badarg:Stacktrace3 ->
code:load_file(code_b_test),
- case erlang:get_stacktrace() of
+ case Stacktrace3 of
[{code_b_test,call,Args,_},
{?MODULE,purge_stacktrace,1,_}|_] ->
- false = code:purge(code_b_test),
- [] = erlang:get_stacktrace()
+ false = code:purge(code_b_test)
end
end,
ok.
@@ -1493,7 +1493,7 @@ do_on_load_error(ReturnValue) ->
{undef,[{on_load_error,main,[],_}|_]} = Exit
end.
-on_load_update(_Config) ->
+on_load_update(Config) ->
{Mod,Code1} = on_load_update_code(1),
{module,Mod} = code:load_binary(Mod, "", Code1),
42 = Mod:a(),
@@ -1503,7 +1503,7 @@ on_load_update(_Config) ->
{Mod,Code2} = on_load_update_code(2),
{error,on_load_failure} = code:load_binary(Mod, "", Code2),
42 = Mod:a(),
- 100 = Mod:b(99),
+ 78 = Mod:b(77),
{'EXIT',{undef,_}} = (catch Mod:never()),
4 = erlang:trace_pattern({Mod,'_','_'}, false),
@@ -1514,6 +1514,9 @@ on_load_update(_Config) ->
{'EXIT',{undef,_}} = (catch Mod:b(10)),
{'EXIT',{undef,_}} = (catch Mod:never()),
+ code:purge(Mod),
+ code:delete(Mod),
+ code:purge(Mod),
ok.
on_load_update_code(Version) ->
@@ -1545,6 +1548,31 @@ on_load_update_code_1(3, Mod) ->
"f() -> ok.\n",
"c() -> 100.\n"]).
+%% Test -on_load while trace feature 'on_load' is enabled (OTP-14612)
+on_load_trace_on_load(Config) ->
+ Papa = self(),
+ Tracer = spawn_link(fun F() -> receive M -> Papa ! M end, F() end),
+ {tracer,[]} = erlang:trace_info(self(),tracer),
+ erlang:trace(self(), true, [call, {tracer, Tracer}]),
+ erlang:trace_pattern(on_load, true, []),
+ on_load_update(Config),
+ erlang:trace_pattern(on_load, false, []),
+ erlang:trace(self(), false, [call]),
+
+ Ms = flush(),
+ [{trace, Papa, call, {on_load_update_code, a, []}},
+ {trace, Papa, call, {on_load_update_code, b, [99]}},
+ {trace, Papa, call, {on_load_update_code, c, []}}] = Ms,
+
+ exit(Tracer, normal),
+ ok.
+
+flush() ->
+ receive M -> [M | flush()]
+ after 100 -> []
+ end.
+
+
on_load_purge(_Config) ->
Mod = ?FUNCTION_NAME,
register(Mod, self()),
diff --git a/lib/kernel/test/code_SUITE_data/upgrade_client.erl b/lib/kernel/test/code_SUITE_data/upgrade_client.erl
index faa18e1410..1c3c2def53 100644
--- a/lib/kernel/test/code_SUITE_data/upgrade_client.erl
+++ b/lib/kernel/test/code_SUITE_data/upgrade_client.erl
@@ -341,6 +341,7 @@ check_tracing_loop(N, MsgList) ->
stop_tracing(Tracer) ->
+ erlang:trace_pattern({error_handler,undefined_function,3}, false, [global]),
erlang:trace(self(), false, [call]),
Tracer ! die_please,
receive
diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl
index fe2fc778f2..9704c3b28c 100644
--- a/lib/kernel/test/disk_log_SUITE.erl
+++ b/lib/kernel/test/disk_log_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -89,8 +89,6 @@
dist_terminate/1, dist_accessible/1, dist_deadlock/1,
dist_open2/1, other_groups/1,
- evil/1,
-
otp_6278/1, otp_10131/1]).
-export([head_fun/1, hf/0, lserv/1,
@@ -123,7 +121,7 @@
[halt_int, wrap_int, halt_ext, wrap_ext, read_mode, head,
notif, new_idx_vsn, reopen, block, unblock, open, close,
error, chunk, truncate, many_users, info, change_size,
- change_attribute, distribution, evil, otp_6278, otp_10131]).
+ change_attribute, distribution, otp_6278, otp_10131]).
%% These test cases should be skipped if the VxWorks card is
%% configured without NFS cache.
@@ -149,7 +147,7 @@ all() ->
{group, open}, {group, close}, {group, error}, chunk,
truncate, many_users, {group, info},
{group, change_size}, change_attribute,
- {group, distribution}, evil, otp_6278, otp_10131].
+ {group, distribution}, otp_6278, otp_10131].
groups() ->
[{halt_int, [], [halt_int_inf, {group, halt_int_sz}]},
@@ -1752,7 +1750,7 @@ block_queue(Conf) when is_list(Conf) ->
true = [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g},{8,h}] == Terms,
del(File, 2),
Q = qlen(),
- true = (P0 == pps()),
+ check_pps(P0),
ok.
%% OTP-4880. Blocked processes did not get disk_log_stopped message.
@@ -1784,7 +1782,7 @@ block_queue2(Conf) when is_list(Conf) ->
{ok,<<>>} = file:read_file(File ++ ".1"),
del(File, No),
Q = qlen(),
- true = (P0 == pps()),
+ check_pps(P0),
ok.
@@ -2121,7 +2119,7 @@ close_block(Conf) when is_list(Conf) ->
0 = sync_do(Pid2, users),
sync_do(Pid2, terminate),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Users terminate (no link...).
Pid3 = spawn_link(?MODULE, lserv, [n]),
@@ -2139,7 +2137,7 @@ close_block(Conf) when is_list(Conf) ->
disk_log:close(n),
disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking owner terminates.
Pid5 = spawn_link(?MODULE, lserv, [n]),
@@ -2156,7 +2154,7 @@ close_block(Conf) when is_list(Conf) ->
1 = users(n),
ok = disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking user terminates.
Pid6 = spawn_link(?MODULE, lserv, [n]),
@@ -2176,7 +2174,7 @@ close_block(Conf) when is_list(Conf) ->
1 = users(n),
ok = disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking owner terminates.
Pid7 = spawn_link(?MODULE, lserv, [n]),
@@ -2194,7 +2192,7 @@ close_block(Conf) when is_list(Conf) ->
1 = users(n),
ok = disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Two owners, the blocking one terminates.
Pid8 = spawn_link(?MODULE, lserv, [n]),
@@ -2209,7 +2207,7 @@ close_block(Conf) when is_list(Conf) ->
0 = sync_do(Pid9, users),
sync_do(Pid9, terminate),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking user closes.
Pid10 = spawn_link(?MODULE, lserv, [n]),
@@ -2227,7 +2225,7 @@ close_block(Conf) when is_list(Conf) ->
ok = disk_log:close(n),
sync_do(Pid10, terminate),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking user unblocks and closes.
Pid11 = spawn_link(?MODULE, lserv, [n]),
@@ -2246,7 +2244,7 @@ close_block(Conf) when is_list(Conf) ->
ok = disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
sync_do(Pid11, terminate),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking owner closes.
Pid12 = spawn_link(?MODULE, lserv, [n]),
@@ -2265,7 +2263,7 @@ close_block(Conf) when is_list(Conf) ->
ok = disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
sync_do(Pid12, terminate),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking owner unblocks and closes.
Pid13 = spawn_link(?MODULE, lserv, [n]),
@@ -2285,7 +2283,7 @@ close_block(Conf) when is_list(Conf) ->
ok = disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
sync_do(Pid13, terminate),
- true = (P0 == pps()),
+ check_pps(P0),
del(File, No), % cleanup
ok.
@@ -2489,7 +2487,7 @@ error_repair(Conf) when is_list(Conf) ->
P0 = pps(),
{error, {file_error, _, _}} =
disk_log:open([{name, n}, {file, File}, {type, wrap}, {size,{40,4}}]),
- true = (P0 == pps()),
+ check_pps(P0),
del(File, No),
ok = file:del_dir(Dir),
@@ -2508,7 +2506,7 @@ error_repair(Conf) when is_list(Conf) ->
disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, internal}, {size, {40,No}}]),
ok = disk_log:close(n),
- true = (P1 == pps()),
+ check_pps(P1),
del(File, No),
receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok
after 1000 -> ct:fail(failed) end,
@@ -2526,7 +2524,7 @@ error_repair(Conf) when is_list(Conf) ->
disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, internal}, {size, {4000,No}}]),
ok = disk_log:close(n),
- true = (P2 == pps()),
+ check_pps(P2),
del(File, No),
receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok
after 1000 -> ct:fail(failed) end,
@@ -2635,7 +2633,7 @@ error_log(Conf) when is_list(Conf) ->
{ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, external},{size, {100, No}}]),
{error, {file_error, _, _}} = disk_log:truncate(n),
- true = (P0 == pps()),
+ check_pps(P0),
del(File, No),
%% OTP-4880.
@@ -2643,7 +2641,7 @@ error_log(Conf) when is_list(Conf) ->
{ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
{format, external},{size, 100000}]),
{error, {file_error, _, eisdir}} = disk_log:reopen(n, LDir),
- true = (P0 == pps()),
+ check_pps(P0),
file:delete(File),
B = mk_bytes(60),
@@ -3005,7 +3003,7 @@ error_index(Conf) when is_list(Conf) ->
{error, {invalid_index_file, _}} = disk_log:open(Args),
del(File, No),
- true = (P0 == pps()),
+ check_pps(P0),
true = (Q == qlen()),
ok.
@@ -4438,7 +4436,7 @@ dist_open2(Conf) when is_list(Conf) ->
timer:sleep(500),
file:delete(File),
- true = (P0 == pps()),
+ check_pps(P0),
%% This time the first process has a naughty head_func. This test
%% does not add very much. Perhaps it should be removed. However,
@@ -4484,7 +4482,7 @@ dist_open2(Conf) when is_list(Conf) ->
timer:sleep(100),
{error, no_such_log} = disk_log:close(Log),
file:delete(File),
- true = (P0 == pps()),
+ check_pps(P0),
No = 2,
Log2 = n2,
@@ -4513,7 +4511,7 @@ dist_open2(Conf) when is_list(Conf) ->
file:delete(File2),
del(File, No),
- true = (P0 == pps()),
+ check_pps(P0),
R.
@@ -4558,7 +4556,7 @@ dist_open2_1(Conf, Delay) ->
{error, no_such_log} = disk_log:info(Log),
file:delete(File),
- true = (P0 == pps()),
+ check_pps(P0),
ok.
@@ -4615,7 +4613,7 @@ dist_open2_2(Conf, Delay) ->
{[{Node1,{repaired,_,_,_}}],[]}} -> ok
end,
- true = (P0 == pps()),
+ check_pps(P0),
stop_node(Node1),
file:delete(File),
ok.
@@ -4676,119 +4674,6 @@ other_groups(Conf) when is_list(Conf) ->
ok.
--define(MAX, ?MAX_FWRITE_CACHE). % as in disk_log_1.erl
-%% Evil cases such as closed file descriptor port.
-evil(Conf) when is_list(Conf) ->
- Dir = ?privdir(Conf),
- File = filename:join(Dir, "n.LOG"),
- Log = n,
-
- %% Not a very thorough test.
-
- ok = setup_evil_filled_cache_wrap(Log, Dir),
- {error, {file_error,_,einval}} = disk_log:log(Log, apa),
- ok = disk_log:close(Log),
-
- ok = setup_evil_filled_cache_halt(Log, Dir),
- {error, {file_error,_,einval}} = disk_log:truncate(Log, apa),
- ok = stop_evil(Log),
-
- %% White box test.
- file:delete(File),
- Ports0 = erlang:ports(),
- {ok, Log} = disk_log:open([{name,Log},{file,File},{type,halt},
- {size,?MAX+50},{format,external}]),
- [Fd] = erlang:ports() -- Ports0,
- {B,_} = x_mk_bytes(30),
- ok = disk_log:blog(Log, <<0:(?MAX-1)/unit:8>>),
- exit(Fd, kill),
- {error, {file_error,_,einval}} = disk_log:blog_terms(Log, [B,B]),
- ok= disk_log:close(Log),
- file:delete(File),
-
- ok = setup_evil_wrap(Log, Dir),
- {error, {file_error,_,einval}} = disk_log:close(Log),
-
- ok = setup_evil_wrap(Log, Dir),
- {error, {file_error,_,einval}} = disk_log:log(Log, apa),
- ok = stop_evil(Log),
-
- ok = setup_evil_halt(Log, Dir),
- {error, {file_error,_,einval}} = disk_log:log(Log, apa),
- ok = stop_evil(Log),
-
- ok = setup_evil_wrap(Log, Dir),
- {error, {file_error,_,einval}} = disk_log:reopen(Log, apa),
- {error, {file_error,_,einval}} = disk_log:reopen(Log, apa),
- ok = stop_evil(Log),
-
- ok = setup_evil_wrap(Log, Dir),
- {error, {file_error,_,einval}} = disk_log:reopen(Log, apa),
- ok = stop_evil(Log),
-
- ok = setup_evil_wrap(Log, Dir),
- {error, {file_error,_,einval}} = disk_log:inc_wrap_file(Log),
- ok = stop_evil(Log),
-
- ok = setup_evil_wrap(Log, Dir),
- {error, {file_error,_,einval}} = disk_log:chunk(Log, start),
- ok = stop_evil(Log),
-
- ok = setup_evil_wrap(Log, Dir),
- {error, {file_error,_,einval}} = disk_log:truncate(Log),
- ok = stop_evil(Log),
-
- ok = setup_evil_wrap(Log, Dir),
- {error, {file_error,_,einval}} = disk_log:chunk_step(Log, start, 1),
- ok = stop_evil(Log),
-
- io:format("messages: ~p~n", [erlang:process_info(self(), messages)]),
- del(File, 2),
- file:delete(File),
- ok.
-
-setup_evil_wrap(Log, Dir) ->
- setup_evil(Log, [{type,wrap},{size,{100,2}}], Dir).
-
-setup_evil_halt(Log, Dir) ->
- setup_evil(Log, [{type,halt},{size,10000}], Dir).
-
-setup_evil(Log, Args, Dir) ->
- File = filename:join(Dir, lists:concat([Log, ".LOG"])),
- file:delete(File),
- del(File, 2),
- ok = disk_log:start(),
- Ports0 = erlang:ports(),
- {ok, Log} = disk_log:open([{name,Log},{file,File} | Args]),
- [Fd] = erlang:ports() -- Ports0,
- exit(Fd, kill),
- ok = disk_log:log_terms(n, [<<0:10/unit:8>>]),
- timer:sleep(2500), % TIMEOUT in disk_log_1.erl is 2000
- ok.
-
-stop_evil(Log) ->
- {error, _} = disk_log:close(Log),
- ok.
-
-setup_evil_filled_cache_wrap(Log, Dir) ->
- setup_evil_filled_cache(Log, [{type,wrap},{size,{?MAX,2}}], Dir).
-
-setup_evil_filled_cache_halt(Log, Dir) ->
- setup_evil_filled_cache(Log, [{type,halt},{size,infinity}], Dir).
-
-%% The cache is filled, and the file descriptor port gone.
-setup_evil_filled_cache(Log, Args, Dir) ->
- File = filename:join(Dir, lists:concat([Log, ".LOG"])),
- file:delete(File),
- del(File, 2),
- ok = disk_log:start(),
- Ports0 = erlang:ports(),
- {ok, Log} = disk_log:open([{name,Log},{file,File} | Args]),
- [Fd] = erlang:ports() -- Ports0,
- ok = disk_log:log_terms(n, [<<0:?MAX/unit:8>>]),
- exit(Fd, kill),
- ok.
-
%% OTP-6278. open/1 creates no status or crash report.
otp_6278(Conf) when is_list(Conf) ->
Dir = ?privdir(Conf),
@@ -4906,10 +4791,59 @@ log(Name, N) ->
format_error(E) ->
lists:flatten(disk_log:format_error(E)).
+check_pps({Ports0,Procs0} = P0) ->
+ case pps() of
+ P0 ->
+ ok;
+ _ ->
+ timer:sleep(500),
+ case pps() of
+ P0 ->
+ ok;
+ {Ports1,Procs1} = P1 ->
+ case {Ports1 -- Ports0, Procs1 -- Procs0} of
+ {[], []} -> ok;
+ {PortsDiff,ProcsDiff} ->
+ io:format("failure, got ~p~n, expected ~p\n", [P1, P0]),
+ show("Old port", Ports0 -- Ports1),
+ show("New port", PortsDiff),
+ show("Old proc", Procs0 -- Procs1),
+ show("New proc", ProcsDiff),
+ ct:fail(failed)
+ end
+ end
+ end.
+
+show(_S, []) ->
+ ok;
+show(S, [{Pid, Name, InitCall}|Pids]) when is_pid(Pid) ->
+ io:format("~s: ~w (~w), ~w: ~p~n",
+ [S, Pid, proc_reg_name(Name), InitCall,
+ erlang:process_info(Pid)]),
+ show(S, Pids);
+show(S, [{Port, _}|Ports]) when is_port(Port)->
+ io:format("~s: ~w: ~p~n", [S, Port, erlang:port_info(Port)]),
+ show(S, Ports).
+
pps() ->
timer:sleep(100),
- {erlang:ports(), lists:filter(fun(P) -> erlang:is_process_alive(P) end,
- processes())}.
+ {port_list(), process_list()}.
+
+port_list() ->
+ [{P,safe_second_element(erlang:port_info(P, name))} ||
+ P <- erlang:ports()].
+
+process_list() ->
+ [{P,process_info(P, registered_name),
+ safe_second_element(process_info(P, initial_call))} ||
+ P <- processes(), erlang:is_process_alive(P)].
+
+proc_reg_name({registered_name, Name}) -> Name;
+proc_reg_name([]) -> no_reg_name.
+
+safe_second_element({_,Info}) -> Info;
+safe_second_element(Other) -> Other.
+
qlen() ->
{_, {_, N}} = lists:keysearch(message_queue_len, 1, process_info(self())),
diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl
index bbfaa9d147..5a8bbd56c4 100644
--- a/lib/kernel/test/erl_distribution_SUITE.erl
+++ b/lib/kernel/test/erl_distribution_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
init_per_group/2,end_per_group/2]).
-export([tick/1, tick_change/1,
+ connect_node/1,
nodenames/1, hostnames/1,
illegal_nodenames/1, hidden_node/1,
setopts/1,
@@ -70,6 +71,7 @@ suite() ->
all() ->
[tick, tick_change, nodenames, hostnames, illegal_nodenames,
+ connect_node,
hidden_node, setopts,
table_waste, net_setuptime, inet_dist_options_options,
{group, monitor_nodes}].
@@ -87,6 +89,7 @@ init_per_suite(Config) ->
Config.
end_per_suite(_Config) ->
+ [slave:stop(N) || N <- nodes()],
ok.
init_per_group(_GroupName, Config) ->
@@ -95,13 +98,23 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
+init_per_testcase(TC, Config) when TC == hostnames;
+ TC == nodenames ->
+ file:make_dir("hostnames_nodedir"),
+ file:write_file("hostnames_nodedir/ignore_core_files",""),
+ Config;
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
Config.
end_per_testcase(_Func, _Config) ->
ok.
+connect_node(Config) when is_list(Config) ->
+ Connected = nodes(connected),
+ true = net_kernel:connect_node(node()),
+ Connected = nodes(connected),
+ ok.
+
tick(Config) when is_list(Config) ->
PaDir = filename:dirname(code:which(erl_distribution_SUITE)),
@@ -240,7 +253,7 @@ illegal(Name) ->
test_node(Name) ->
test_node(Name, false).
test_node(Name, Illigal) ->
- ProgName = atom_to_list(lib:progname()),
+ ProgName = ct:get_progname(),
Command = ProgName ++ " -noinput " ++ long_or_short() ++ Name ++
" -eval \"net_adm:ping('" ++ atom_to_list(node()) ++ "')\"" ++
case Illigal of
@@ -251,7 +264,7 @@ test_node(Name, Illigal) ->
end,
net_kernel:monitor_nodes(true),
BinCommand = unicode:characters_to_binary(Command, utf8),
- Prt = open_port({spawn, BinCommand}, [stream]),
+ Prt = open_port({spawn, BinCommand}, [stream,{cd,"hostnames_nodedir"}]),
Node = list_to_atom(Name),
receive
{nodeup, Node} ->
@@ -459,9 +472,9 @@ run_remote_test([FuncStr, TestNodeStr | Args]) ->
1
end
catch
- C:E ->
+ C:E:S ->
io:format("Node ~p got EXCEPTION ~p:~p\nat ~p\n",
- [node(), C, E, erlang:get_stacktrace()]),
+ [node(), C, E, S]),
2
end,
io:format("Node ~p doing halt(~p).\n",[node(), Status]),
@@ -1140,17 +1153,16 @@ monitor_nodes_otp_6481_test(Config, TestType) when is_list(Config) ->
TestMonNodeState = monitor_node_state(),
%% io:format("~p~n", [TestMonNodeState]),
TestMonNodeState =
- MonNodeState
+ case TestType of
+ nodedown -> [];
+ nodeup -> [{self(), []}]
+ end
+ ++ lists:map(fun (_) -> {MN, []} end, Seq)
++ case TestType of
nodedown -> [{self(), []}];
nodeup -> []
end
- ++ lists:map(fun (_) -> {MN, []} end, Seq)
- ++ case TestType of
- nodedown -> [];
- nodeup -> [{self(), []}]
- end,
-
+ ++ MonNodeState,
{ok, Node} = start_node(Name, "", this),
receive {nodeup, Node} -> ok end,
diff --git a/lib/kernel/test/erl_distribution_wb_SUITE.erl b/lib/kernel/test/erl_distribution_wb_SUITE.erl
index 03aaee56b7..8256444bdc 100644
--- a/lib/kernel/test/erl_distribution_wb_SUITE.erl
+++ b/lib/kernel/test/erl_distribution_wb_SUITE.erl
@@ -61,10 +61,13 @@
%% From R9 and forward extended references is compulsory
%% From R10 and forward extended pids and ports are compulsory
%% From R20 and forward UTF8 atoms are compulsory
+%% From R21 and forward NEW_FUN_TAGS is compulsory (no more tuple fallback {fun, ...})
-define(COMPULSORY_DFLAGS, (?DFLAG_EXTENDED_REFERENCES bor
?DFLAG_EXTENDED_PIDS_PORTS bor
- ?DFLAG_UTF8_ATOMS)).
+ ?DFLAG_UTF8_ATOMS bor
+ ?DFLAG_NEW_FUN_TAGS)).
+-define(PASS_THROUGH, $p).
-define(shutdown(X), exit(X)).
-define(int16(X), [((X) bsr 8) band 16#ff, (X) band 16#ff]).
@@ -674,15 +677,16 @@ build_rex_message(Cookie,OurName) ->
%% Receive a distribution message
recv_message(Socket) ->
case gen_tcp:recv(Socket, 0) of
+ {ok,[]} ->
+ recv_message(Socket); %% a tick, ignore
{ok,Data} ->
B0 = list_to_binary(Data),
- {_,B1} = erlang:split_binary(B0,1),
- Header = binary_to_term(B1),
- Siz = byte_size(term_to_binary(Header)),
- {_,B2} = erlang:split_binary(B1,Siz),
+ <<?PASS_THROUGH, B1/binary>> = B0,
+ {Header,Siz} = binary_to_term(B1,[used]),
+ <<_:Siz/binary,B2/binary>> = B1,
Message = case (catch binary_to_term(B2)) of
{'EXIT', _} ->
- could_not_digest_message;
+ {could_not_digest_message,B2};
Other ->
Other
end,
diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl
index b6417210b9..16a127aa3e 100644
--- a/lib/kernel/test/erl_prim_loader_SUITE.erl
+++ b/lib/kernel/test/erl_prim_loader_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
primary_archive/1, virtual_dir_in_archive/1,
get_modules/1]).
+-define(PRIM_FILE, prim_file).
%%-----------------------------------------------------------------
%% Test suite for erl_prim_loader. (Most code is run during system start/stop.)
@@ -461,7 +462,7 @@ primary_archive(Config) when is_list(Config) ->
%% Set primary archive
ExpectedEbins = [Archive, DictDir ++ "/ebin", DummyDir ++ "/ebin"],
io:format("ExpectedEbins: ~p\n", [ExpectedEbins]),
- {ok, FileInfo} = prim_file:read_file_info(Archive),
+ {ok, FileInfo} = ?PRIM_FILE:read_file_info(Archive),
{ok, Ebins} = rpc:call(Node, erl_prim_loader, set_primary_archive,
[Archive, ArchiveBin, FileInfo,
fun escript:parse_file/1]),
diff --git a/lib/kernel/test/error_logger_SUITE.erl b/lib/kernel/test/error_logger_SUITE.erl
index 2d26a7246c..eab72e58a7 100644
--- a/lib/kernel/test/error_logger_SUITE.erl
+++ b/lib/kernel/test/error_logger_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,8 @@
init_per_group/2,end_per_group/2,
off_heap/1,
error_report/1, info_report/1, error/1, info/1,
- emulator/1, tty/1, logfile/1, add/1, delete/1]).
+ emulator/1, via_logger_process/1, other_node/1,
+ tty/1, logfile/1, add/1, delete/1, format_depth/1]).
-export([generate_error/2]).
@@ -46,16 +47,20 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- [off_heap, error_report, info_report, error, info, emulator, tty,
- logfile, add, delete].
+ [off_heap, error_report, info_report, error, info, emulator,
+ via_logger_process, other_node, tty, logfile, add, delete,
+ format_depth].
groups() ->
[].
init_per_suite(Config) ->
+ logger:add_handler(error_logger,error_logger,
+ #{level=>info,filter_default=>log}),
Config.
end_per_suite(_Config) ->
+ logger:remove_handler(error_logger),
ok.
init_per_group(_GroupName, Config) ->
@@ -226,6 +231,40 @@ generate_error(Error, Stack) ->
erlang:raise(error, Error, Stack).
%%-----------------------------------------------------------------
+
+via_logger_process(Config) ->
+ case os:type() of
+ {win32,_} ->
+ {skip,"Skip on windows - cant change file mode"};
+ _ ->
+ error_logger:add_report_handler(?MODULE, self()),
+ Dir = filename:join(?config(priv_dir,Config),"dummydir"),
+ Msg = "File operation error: eacces. Target: " ++
+ Dir ++ ". Function: list_dir. ",
+ ok = file:make_dir(Dir),
+ ok = file:change_mode(Dir,8#0222),
+ error = erl_prim_loader:list_dir(Dir),
+ ok = file:change_mode(Dir,8#0664),
+ _ = file:del_dir(Dir),
+ reported(error_report, std_error, Msg),
+ my_yes = error_logger:delete_report_handler(?MODULE),
+ ok
+ end.
+
+%%-----------------------------------------------------------------
+
+other_node(_Config) ->
+ error_logger:add_report_handler(?MODULE, self()),
+ {ok,Node} = test_server:start_node(?FUNCTION_NAME,slave,[]),
+ ok = rpc:call(Node,logger,add_handler,[error_logger,error_logger,
+ #{level=>info,filter_default=>log}]),
+ rpc:call(Node,error_logger,error_report,[hi_from_remote]),
+ reported(error_report,std_error,hi_from_remote),
+ test_server:stop_node(Node),
+ ok.
+
+
+%%-----------------------------------------------------------------
%% We don't enables or disables tty error logging here. We do not
%% want to interact with the test run.
%%-----------------------------------------------------------------
@@ -271,6 +310,21 @@ delete(Config) when is_list(Config) ->
ok.
%%-----------------------------------------------------------------
+
+format_depth(_Config) ->
+ ok = application:set_env(kernel,error_logger_format_depth,30),
+ 30 = error_logger:get_format_depth(),
+ ok = application:set_env(kernel,error_logger_format_depth,3),
+ 10 = error_logger:get_format_depth(),
+ ok = application:set_env(kernel,error_logger_format_depth,11),
+ 11 = error_logger:get_format_depth(),
+ ok = application:set_env(kernel,error_logger_format_depth,unlimited),
+ unlimited = error_logger:get_format_depth(),
+ ok = application:unset_env(kernel,error_logger_format_depth),
+ unlimited = error_logger:get_format_depth(),
+ ok.
+
+%%-----------------------------------------------------------------
%% Check that the report has been received.
%%-----------------------------------------------------------------
reported(Tag, Type, Report) ->
@@ -279,7 +333,7 @@ reported(Tag, Type, Report) ->
test_server:messages_get(),
ok
after 1000 ->
- ct:fail(no_report_received)
+ ct:fail({no_report_received,test_server:messages_get()})
end.
%%-----------------------------------------------------------------
diff --git a/lib/kernel/test/error_logger_warn_SUITE.erl b/lib/kernel/test/error_logger_warn_SUITE.erl
index a8087e11f9..8f1eb2ba0a 100644
--- a/lib/kernel/test/error_logger_warn_SUITE.erl
+++ b/lib/kernel/test/error_logger_warn_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -480,9 +480,12 @@ rb_utc() ->
UtcLog=case application:get_env(sasl,utc_log) of
{ok,true} ->
true;
- _AllOthers ->
+ {ok,false} ->
application:set_env(sasl,utc_log,true),
- false
+ false;
+ undefined ->
+ application:set_env(sasl,utc_log,true),
+ undefined
end,
application:start(sasl),
rb:start([{report_dir, rd()}]),
@@ -494,7 +497,12 @@ rb_utc() ->
Sum=one_rb_findstr([],"UTC"),
rb:stop(),
application:stop(sasl),
- application:set_env(sasl,utc_log,UtcLog),
+ case UtcLog of
+ undefined ->
+ application:unset_env(sasl,utc_log);
+ _ ->
+ application:set_env(sasl,utc_log,UtcLog)
+ end,
stop_node(Node),
ok.
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 119e1f24bb..e784c06865 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -39,6 +39,8 @@
-define(FILE_FIN_PER_TESTCASE(Config), Config).
-endif.
+-define(PRIM_FILE, prim_file).
+
-module(?FILE_SUITE).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -54,7 +56,8 @@
open1/1,
old_modes/1, new_modes/1, path_open/1, open_errors/1]).
-export([ file_info_basic_file/1, file_info_basic_directory/1,
- file_info_bad/1, file_info_times/1, file_write_file_info/1]).
+ file_info_bad/1, file_info_times/1, file_write_file_info/1,
+ file_wfi_helpers/1]).
-export([rename/1, access/1, truncate/1, datasync/1, sync/1,
read_write/1, pread_write/1, append/1, exclusive/1]).
-export([ e_delete/1, e_rename/1, e_make_dir/1, e_del_dir/1]).
@@ -97,6 +100,12 @@
-export([unicode_mode/1]).
+-export([volume_relative_paths/1]).
+
+-export([tiny_writes/1, tiny_writes_delayed/1,
+ large_writes/1, large_writes_delayed/1,
+ tiny_reads/1, tiny_reads_ahead/1]).
+
%% Debug exports
-export([create_file_slow/2, create_file/2, create_bin/2]).
-export([verify_file/2, verify_bin/3]).
@@ -107,6 +116,8 @@
-export([disc_free/1, memsize/0]).
-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
-include_lib("kernel/include/file.hrl").
-define(THROW_ERROR(RES), throw({fail, ?LINE, RES})).
@@ -118,13 +129,13 @@ suite() ->
all() ->
[unicode, altname, read_write_file, {group, dirs},
- {group, files}, delete, rename, names, {group, errors},
- {group, compression}, {group, links}, copy,
+ {group, files}, delete, rename, names, volume_relative_paths,
+ {group, errors}, {group, compression}, {group, links}, copy,
delayed_write, read_ahead, segment_read, segment_write,
ipread, pid2name, interleaved_read_write, otp_5814, otp_10852,
large_file, large_write, read_line_1, read_line_2, read_line_3,
read_line_4, standard_io, old_io_protocol,
- unicode_mode
+ unicode_mode, {group, bench}
].
groups() ->
@@ -142,7 +153,8 @@ groups() ->
{pos, [], [pos1, pos2, pos3]},
{file_info, [],
[file_info_basic_file, file_info_basic_directory,
- file_info_bad, file_info_times, file_write_file_info]},
+ file_info_bad, file_info_times, file_write_file_info,
+ file_wfi_helpers]},
{consult, [], [consult1, path_consult]},
{eval, [], [eval1, path_eval]},
{script, [], [script1, path_script]},
@@ -154,11 +166,19 @@ groups() ->
write_compressed, compress_errors, catenated_gzips,
compress_async_crash]},
{links, [],
- [make_link, read_link_info_for_non_link, symlinks]}].
+ [make_link, read_link_info_for_non_link, symlinks]},
+ {bench, [],
+ [tiny_writes, tiny_writes_delayed,
+ large_writes, large_writes_delayed,
+ tiny_reads, tiny_reads_ahead]}].
init_per_group(_GroupName, Config) ->
Config.
+end_per_group(bench, Config) ->
+ ScratchDir = proplists:get_value(priv_dir, Config),
+ file:delete(filename:join(ScratchDir, "benchmark_scratch_file")),
+ Config;
end_per_group(_GroupName, Config) ->
Config.
@@ -381,11 +401,11 @@ read_write_0(Str, {Func, ReadFun}, Options) ->
io:format("~p:~p: ~p ERROR: ~ts vs~n ~w~n - ~p~n",
[?MODULE, Line, Func, Str, ReadBytes, Options]),
exit({error, ?LINE});
- error:What ->
+ error:What:Stacktrace ->
io:format("~p:??: ~p ERROR: ~p from~n ~w~n ~p~n",
[?MODULE, Func, What, Str, Options]),
- io:format("\t~p~n", [erlang:get_stacktrace()]),
+ io:format("\t~p~n", [Stacktrace]),
exit({error, ?LINE})
end.
@@ -473,7 +493,7 @@ um_check_unicode(_Utf8Bin, {ok, _ListOrBin}, _, _UTF8_) ->
um_filename(Bin, Dir, Options) when is_binary(Bin) ->
um_filename(binary_to_list(Bin), Dir, Options);
um_filename(Str = [_|_], Dir, Options) ->
- Name = hd(string:tokens(Str, ":")),
+ Name = hd(string:lexemes(Str, ":")),
Enc = atom_to_list(proplists:get_value(encoding, Options, latin1)),
File = case lists:member(binary, Options) of
true ->
@@ -638,6 +658,10 @@ cur_dir_0(Config) when is_list(Config) ->
{ok,NewDirFiles} = ?FILE_MODULE:list_dir("."),
true = lists:member(UncommonName,NewDirFiles),
+ %% Ensure that we get the same result with a trailing slash; the
+ %% APIs used on Windows will choke on them if passed directly.
+ {ok,NewDirFiles} = ?FILE_MODULE:list_dir("./"),
+
%% Delete the directory and return to the old current directory
%% and check that the created file isn't there (too!)
expect({error, einval}, {error, eacces},
@@ -690,10 +714,15 @@ win_cur_dir_1(_Config) ->
%% Get the drive letter from the current directory,
%% and try to get current directory for that drive.
- [Drive,$:|_] = BaseDir,
- {ok,BaseDir} = ?FILE_MODULE:get_cwd([Drive,$:]),
+ [CurDrive,$:|_] = BaseDir,
+ {ok,BaseDir} = ?FILE_MODULE:get_cwd([CurDrive,$:]),
io:format("BaseDir = ~s\n", [BaseDir]),
+ %% We should error out on non-existent drives. Any reasonable system will
+ %% have at least one.
+ CurDirs = [?FILE_MODULE:get_cwd([Drive,$:]) || Drive <- lists:seq($A, $Z)],
+ lists:member({error,eaccess}, CurDirs),
+
%% Unfortunately, there is no way to move away from the
%% current drive as we can't use the "subst" command from
%% a SSH connection. We can't test any more.
@@ -831,7 +860,7 @@ no_untranslatable_names() ->
end.
start_node(Name, Args) ->
- [_,Host] = string:tokens(atom_to_list(node()), "@"),
+ [_,Host] = string:lexemes(atom_to_list(node()), "@"),
ct:log("Trying to start ~w@~s~n", [Name,Host]),
case test_server:start_node(Name, peer, [{args,Args}]) of
{error,Reason} ->
@@ -1019,6 +1048,23 @@ close(Config) when is_list(Config) ->
Val = ?FILE_MODULE:close(Fd1),
io:format("Second close gave: ~p",[Val]),
+ %% All operations on a closed raw file should EINVAL, even if they're not
+ %% supported on the current platform.
+ {ok,Fd2} = ?FILE_MODULE:open(Name, [read, write, raw]),
+ ok = ?FILE_MODULE:close(Fd2),
+
+ {error, einval} = ?FILE_MODULE:advise(Fd2, 5, 5, normal),
+ {error, einval} = ?FILE_MODULE:allocate(Fd2, 5, 5),
+ {error, einval} = ?FILE_MODULE:close(Fd2),
+ {error, einval} = ?FILE_MODULE:datasync(Fd2),
+ {error, einval} = ?FILE_MODULE:position(Fd2, 5),
+ {error, einval} = ?FILE_MODULE:pread(Fd2, 5, 1),
+ {error, einval} = ?FILE_MODULE:pwrite(Fd2, 5, "einval please"),
+ {error, einval} = ?FILE_MODULE:read(Fd2, 1),
+ {error, einval} = ?FILE_MODULE:sync(Fd2),
+ {error, einval} = ?FILE_MODULE:truncate(Fd2),
+ {error, einval} = ?FILE_MODULE:write(Fd2, "einval please"),
+
[] = flush(),
ok.
@@ -1132,8 +1178,8 @@ pread_write_test(File, Data) ->
end,
I = Size + 17,
ok = ?FILE_MODULE:pwrite(File, 0, Data),
- Res = ?FILE_MODULE:pread(File, 0, I),
- {ok, Data} = Res,
+ {ok, Data} = ?FILE_MODULE:pread(File, 0, I),
+ {ok, [Data]} = ?FILE_MODULE:pread(File, [{0, I}]),
eof = ?FILE_MODULE:pread(File, I, 1),
ok = ?FILE_MODULE:pwrite(File, [{0, Data}, {I, Data}]),
{ok, [Data, eof, Data]} =
@@ -1321,6 +1367,10 @@ file_info_basic_file(Config) when is_list(Config) ->
io:put_chars(Fd1, "foo bar"),
ok = ?FILE_MODULE:close(Fd1),
+ %% Don't crash the file server when passing incorrect arguments.
+ {error,badarg} = ?FILE_MODULE:read_file_info(Name, [{time, gurka}]),
+ {error,badarg} = ?FILE_MODULE:read_file_info([#{} | gaffel]),
+
%% Test that the file has the expected attributes.
%% The times are tricky, so we will save them to a separate test case.
{ok,FileInfo} = ?FILE_MODULE:read_file_info(Name),
@@ -1564,6 +1614,39 @@ file_write_file_info(Config) when is_list(Config) ->
[] = flush(),
ok.
+file_wfi_helpers(Config) when is_list(Config) ->
+ RootDir = get_good_directory(Config),
+ io:format("RootDir = ~p", [RootDir]),
+
+ Name = filename:join(RootDir,
+ atom_to_list(?MODULE) ++ "_wfi_helpers"),
+
+ ok = ?FILE_MODULE:write_file(Name, "hello again"),
+ NewTime = {{1997, 02, 15}, {13, 18, 20}},
+ ok = ?FILE_MODULE:change_time(Name, NewTime, NewTime),
+
+ {ok, #file_info{atime=NewActAtime, mtime=NewTime}} =
+ ?FILE_MODULE:read_file_info(Name),
+
+ NewFilteredAtime = filter_atime(NewTime, Config),
+ NewFilteredAtime = filter_atime(NewActAtime, Config),
+
+ %% Make the file unwritable
+ ok = ?FILE_MODULE:change_mode(Name, 8#400),
+ {error, eacces} = ?FILE_MODULE:write_file(Name, "hello again"),
+
+ %% ... and writable again
+ ok = ?FILE_MODULE:change_mode(Name, 8#600),
+ ok = ?FILE_MODULE:write_file(Name, "hello again"),
+
+ %% We have no idea which users will work, so all we can do is to check
+ %% that it returns enoent instead of crashing.
+ {error, enoent} = ?FILE_MODULE:change_group("bogus file name", 0),
+ {error, enoent} = ?FILE_MODULE:change_owner("bogus file name", 0),
+
+ [] = flush(),
+ ok.
+
%% Returns a directory on a file system that has correct file times.
get_good_directory(Config) ->
@@ -2044,13 +2127,22 @@ names(Config) when is_list(Config) ->
ok = ?FILE_MODULE:close(Fd2),
{ok,Fd3} = ?FILE_MODULE:open(Name3,read),
ok = ?FILE_MODULE:close(Fd3),
+
+ %% Now try the same on raw files.
+ {ok,Fd4} = ?FILE_MODULE:open(Name2, [read, raw]),
+ ok = ?FILE_MODULE:close(Fd4),
+ {ok,Fd4f} = ?FILE_MODULE:open(lists:flatten(Name2), [read, raw]),
+ ok = ?FILE_MODULE:close(Fd4f),
+ {ok,Fd5} = ?FILE_MODULE:open(Name3, [read, raw]),
+ ok = ?FILE_MODULE:close(Fd5),
+
case length(Name1) > 255 of
true ->
io:format("Path too long for an atom:\n\n~p\n", [Name1]);
false ->
Name4 = list_to_atom(Name1),
- {ok,Fd4} = ?FILE_MODULE:open(Name4,read),
- ok = ?FILE_MODULE:close(Fd4)
+ {ok,Fd6} = ?FILE_MODULE:open(Name4,read),
+ ok = ?FILE_MODULE:close(Fd6)
end,
%% Try some path names
@@ -2074,6 +2166,22 @@ names(Config) when is_list(Config) ->
[] = flush(),
ok.
+volume_relative_paths(Config) when is_list(Config) ->
+ case os:type() of
+ {win32, _} ->
+ {ok, [Drive, $: | _]} = file:get_cwd(),
+ %% Relative to current device root.
+ {ok, RootInfo} = file:read_file_info([Drive, $:, $/]),
+ {ok, RootInfo} = file:read_file_info("/"),
+ %% Relative to current device directory.
+ {ok, DirContents} = file:list_dir([Drive, $:]),
+ {ok, DirContents} = file:list_dir("."),
+ [] = flush(),
+ ok;
+ _ ->
+ {skip, "This test is Windows-specific."}
+ end.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2108,7 +2216,7 @@ e_delete(Config) when is_list(Config) ->
Base, #file_info {mode=0}),
{error, eacces} = ?FILE_MODULE:delete(Afile),
?FILE_MODULE:write_file_info(
- Base, #file_info {mode=8#600})
+ Base, #file_info {mode=8#700})
end,
[] = flush(),
@@ -2239,7 +2347,7 @@ e_make_dir(Config) when is_list(Config) ->
?FILE_MODULE:write_file_info(Base, #file_info {mode=0}),
{error, eacces} = ?FILE_MODULE:make_dir(filename:join(Base, "xxxx")),
?FILE_MODULE:write_file_info(
- Base, #file_info {mode=8#600})
+ Base, #file_info {mode=8#700})
end,
ok.
@@ -2285,7 +2393,7 @@ e_del_dir(Config) when is_list(Config) ->
ok = ?FILE_MODULE:make_dir(ADirectory),
?FILE_MODULE:write_file_info( Base, #file_info {mode=0}),
{error, eacces} = ?FILE_MODULE:del_dir(ADirectory),
- ?FILE_MODULE:write_file_info( Base, #file_info {mode=8#600})
+ ?FILE_MODULE:write_file_info( Base, #file_info {mode=8#700})
end,
[] = flush(),
ok.
@@ -2641,8 +2749,8 @@ altname(Config) when is_list(Config) ->
{skipped, "Altname not supported on this platform"};
{ok, "LONGAL~1"} ->
{ok, "A_FILE~1"} = ?FILE_MODULE:altname(Name),
- {ok, "C:/"} = ?FILE_MODULE:altname("C:/"),
- {ok, "C:\\"} = ?FILE_MODULE:altname("C:\\"),
+ {ok, "c:/"} = ?FILE_MODULE:altname("C:/"),
+ {ok, "c:/"} = ?FILE_MODULE:altname("C:\\"),
{error,enoent} = ?FILE_MODULE:altname(NonexName),
{ok, "short"} = ?FILE_MODULE:altname(ShortName),
ok
@@ -2923,20 +3031,22 @@ delayed_write(Config) when is_list(Config) ->
%%
%% Test caching and normal close of non-raw file
{ok, Fd1} =
- ?FILE_MODULE:open(File, [write, {delayed_write, Size+1, 2000}]),
+ ?FILE_MODULE:open(File, [write, {delayed_write, Size+1, 400}]),
ok = ?FILE_MODULE:write(Fd1, Data1),
- timer:sleep(1000), % Just in case the file system is slow
+ %% Wait for a reasonable amount of time to check whether the write was
+ %% practically instantaneous or actually delayed.
+ timer:sleep(100),
{ok, Fd2} = ?FILE_MODULE:open(File, [read]),
eof = ?FILE_MODULE:read(Fd2, 1),
ok = ?FILE_MODULE:write(Fd1, Data1), % Data flush on size
- timer:sleep(1000), % Just in case the file system is slow
+ timer:sleep(100),
{ok, Data1Data1} = ?FILE_MODULE:pread(Fd2, bof, 2*Size+1),
ok = ?FILE_MODULE:write(Fd1, Data1),
- timer:sleep(3000), % Wait until data flush on timeout
+ timer:sleep(500), % Wait until data flush on timeout
{ok, Data1Data1Data1} = ?FILE_MODULE:pread(Fd2, bof, 3*Size+1),
ok = ?FILE_MODULE:write(Fd1, Data1),
ok = ?FILE_MODULE:close(Fd1), % Data flush on close
- timer:sleep(1000), % Just in case the file system is slow
+ timer:sleep(100),
{ok, Data1Data1Data1Data1} = ?FILE_MODULE:pread(Fd2, bof, 4*Size+1),
ok = ?FILE_MODULE:close(Fd2),
%%
@@ -2970,7 +3080,7 @@ delayed_write(Config) when is_list(Config) ->
{'DOWN', Mref1, _, _, _} = Down1a ->
ct:fail(Down1a)
end,
- timer:sleep(1000), % Just in case the file system is slow
+ timer:sleep(100), % Just in case the file system is slow
{ok, Fd3} = ?FILE_MODULE:open(File, [read]),
eof = ?FILE_MODULE:read(Fd3, 1),
Child1 ! {Parent, continue, normal},
@@ -2980,7 +3090,7 @@ delayed_write(Config) when is_list(Config) ->
{'DOWN', Mref1, _, _, _} = Down1b ->
ct:fail(Down1b)
end,
- timer:sleep(1000), % Just in case the file system is slow
+ timer:sleep(100), % Just in case the file system is slow
{ok, Data1} = ?FILE_MODULE:pread(Fd3, bof, Size+1),
ok = ?FILE_MODULE:close(Fd3),
%%
@@ -2993,7 +3103,7 @@ delayed_write(Config) when is_list(Config) ->
{'DOWN', Mref2, _, _, _} = Down2a ->
ct:fail(Down2a)
end,
- timer:sleep(1000), % Just in case the file system is slow
+ timer:sleep(100), % Just in case the file system is slow
{ok, Fd4} = ?FILE_MODULE:open(File, [read]),
eof = ?FILE_MODULE:read(Fd4, 1),
Child2 ! {Parent, continue, kill},
@@ -3003,7 +3113,7 @@ delayed_write(Config) when is_list(Config) ->
{'DOWN', Mref2, _, _, _} = Down2b ->
ct:fail(Down2b)
end,
- timer:sleep(1000), % Just in case the file system is slow
+ timer:sleep(100), % Just in case the file system is slow
eof = ?FILE_MODULE:pread(Fd4, bof, 1),
ok = ?FILE_MODULE:close(Fd4),
%%
@@ -3095,6 +3205,16 @@ read_ahead(Config) when is_list(Config) ->
Data1Data2Data3 = Data1++Data2++Data3,
{ok, Data1Data2Data3} = ?FILE_MODULE:read(Fd5, 3*Size+1),
ok = ?FILE_MODULE:close(Fd5),
+
+ %% Ensure that a read that draws from both the buffer and the file won't
+ %% return anything wonky.
+ SplitData = << <<(I rem 256)>> || I <- lists:seq(1, 1024) >>,
+ file:write_file(File, SplitData),
+ {ok, Fd6} = ?FILE_MODULE:open(File, [raw, read, binary, {read_ahead, 256}]),
+ {ok, <<1>>} = file:read(Fd6, 1),
+ <<1, Shifted:512/binary, _Rest/binary>> = SplitData,
+ {ok, Shifted} = file:read(Fd6, 512),
+
%%
[] = flush(),
ok.
@@ -3699,6 +3819,83 @@ do_large_write(Name) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Benchmarks
+%%
+%% Note that we only measure the time it takes to run the isolated file
+%% operations and that the actual test runtime can differ significantly,
+%% especially on the write side as the files need to be truncated before
+%% writing.
+
+large_writes(Config) when is_list(Config) ->
+ Modes = [raw, binary],
+ OpCount = 4096,
+ Data = <<0:(64 bsl 10)/unit:8>>,
+ run_write_benchmark(Config, Modes, OpCount, Data).
+
+large_writes_delayed(Config) when is_list(Config) ->
+ %% Each write is exactly as large as the delay buffer, causing the writes
+ %% to pass through each time, giving us a decent idea of how much overhead
+ %% delayed_write adds.
+ Modes = [raw, binary, {delayed_write, 64 bsl 10, 2000}],
+ OpCount = 4096,
+ Data = <<0:(64 bsl 10)/unit:8>>,
+ run_write_benchmark(Config, Modes, OpCount, Data).
+
+tiny_writes(Config) when is_list(Config) ->
+ Modes = [raw, binary],
+ OpCount = 512 bsl 10,
+ Data = <<0>>,
+ run_write_benchmark(Config, Modes, OpCount, Data).
+
+tiny_writes_delayed(Config) when is_list(Config) ->
+ Modes = [raw, binary, {delayed_write, 512 bsl 10, 2000}],
+ OpCount = 512 bsl 10,
+ Data = <<0>>,
+ run_write_benchmark(Config, Modes, OpCount, Data).
+
+%% The read benchmarks assume that "benchmark_scratch_file" has been filled by
+%% the write benchmarks.
+
+tiny_reads(Config) when is_list(Config) ->
+ Modes = [raw, binary],
+ OpCount = 512 bsl 10,
+ run_read_benchmark(Config, Modes, OpCount, 1).
+
+tiny_reads_ahead(Config) when is_list(Config) ->
+ Modes = [raw, binary, {read_ahead, 512 bsl 10}],
+ OpCount = 512 bsl 10,
+ run_read_benchmark(Config, Modes, OpCount, 1).
+
+run_write_benchmark(Config, Modes, OpCount, Data) ->
+ run_benchmark(Config, [write | Modes], OpCount, fun file:write/2, Data).
+
+run_read_benchmark(Config, Modes, OpCount, OpSize) ->
+ run_benchmark(Config, [read | Modes], OpCount, fun file:read/2, OpSize).
+
+run_benchmark(Config, Modes, OpCount, Fun, Arg) ->
+ ScratchDir = proplists:get_value(priv_dir, Config),
+ Path = filename:join(ScratchDir, "benchmark_scratch_file"),
+ {ok, Fd} = file:open(Path, Modes),
+ submit_throughput_results(Fun, [Fd, Arg], OpCount).
+
+submit_throughput_results(Fun, Args, Times) ->
+ MSecs = measure_repeated_file_op(Fun, Args, Times, millisecond),
+ IOPS = trunc(Times * (1000 / MSecs)),
+ ct_event:notify(#event{ name = benchmark_data, data = [{value,IOPS}] }),
+ {comment, io_lib:format("~p IOPS, ~p ms", [IOPS, trunc(MSecs)])}.
+
+measure_repeated_file_op(Fun, Args, Times, Unit) ->
+ Start = os:perf_counter(Unit),
+ repeated_apply(Fun, Args, Times),
+ os:perf_counter(Unit) - Start.
+
+repeated_apply(_F, _Args, Times) when Times =< 0 ->
+ ok;
+repeated_apply(F, Args, Times) ->
+ erlang:apply(F, Args),
+ repeated_apply(F, Args, Times - 1).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
response_analysis(Module, Function, Arguments) ->
@@ -3934,7 +4131,7 @@ read_line_create_files(TestData) ->
read_line_remove_files(TestData) ->
[ file:delete(File) || {_Function,File,_,_} <- TestData ].
-%% read_line with prim_file.
+%% read_line with ?PRIM_FILE.
read_line_1(Config) when is_list(Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
All = read_line_testdata(PrivDir),
@@ -4103,9 +4300,9 @@ read_line_create7(Filename) ->
file:close(F).
read_line_all(Filename) ->
- {ok,F} = prim_file:open(Filename,[read,binary]),
+ {ok,F} = ?PRIM_FILE:open(Filename,[read,binary]),
X=read_rl_lines(F),
- prim_file:close(F),
+ ?PRIM_FILE:close(F),
Bin = list_to_binary([B || {ok,B} <- X]),
Bin = re:replace(list_to_binary([element(2,file:read_file(Filename))]),
"\r\n","\n",[global,{return,binary}]),
@@ -4138,7 +4335,7 @@ read_line_all4(Filename) ->
{length(X),Bin}.
read_rl_lines(F) ->
- case prim_file:read_line(F) of
+ case ?PRIM_FILE:read_line(F) of
eof ->
[];
{error,X} ->
@@ -4158,9 +4355,9 @@ read_rl_lines2(F) ->
end.
read_line_all_alternating(Filename) ->
- {ok,F} = prim_file:open(Filename,[read,binary]),
+ {ok,F} = ?PRIM_FILE:open(Filename,[read,binary]),
X=read_rl_lines(F,true),
- prim_file:close(F),
+ ?PRIM_FILE:close(F),
Bin = list_to_binary([B || {ok,B} <- X]),
Bin = re:replace(list_to_binary([element(2,file:read_file(Filename))]),
"\r\n","\n",[global,{return,binary}]),
@@ -4194,8 +4391,8 @@ read_line_all_alternating4(Filename) ->
read_rl_lines(F,Alternate) ->
case begin
case Alternate of
- true -> prim_file:read(F,1);
- false -> prim_file:read_line(F)
+ true -> ?PRIM_FILE:read(F,1);
+ false -> ?PRIM_FILE:read_line(F)
end
end of
eof ->
diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl
index 899102c908..3afc647081 100644
--- a/lib/kernel/test/file_name_SUITE.erl
+++ b/lib/kernel/test/file_name_SUITE.erl
@@ -77,6 +77,7 @@
init_per_testcase/2, end_per_testcase/2]).
-export([normal/1,icky/1,very_icky/1,normalize/1,home_dir/1]).
+-define(PRIM_FILE, prim_file).
init_per_testcase(_Func, Config) ->
Config.
@@ -131,7 +132,7 @@ home_dir(Config) when is_list(Config) ->
os:putenv("HOME",NewHome),
{"HOME",Save};
_ ->
- rm_rf(prim_file,NewHome),
+ rm_rf(?PRIM_FILE,NewHome),
throw(unsupported_os)
end,
try
@@ -145,7 +146,7 @@ home_dir(Config) when is_list(Config) ->
_ ->
os:putenv(SaveOldName,SaveOldValue)
end,
- rm_rf(prim_file,NewHome)
+ rm_rf(?PRIM_FILE,NewHome)
end
catch
throw:need_unicode_mode ->
@@ -190,7 +191,7 @@ normal(Config) when is_list(Config) ->
try
Priv = proplists:get_value(priv_dir, Config),
file:set_cwd(Priv),
- ok = check_normal(prim_file),
+ ok = check_normal(?PRIM_FILE),
ok = check_normal(file),
%% If all is good, delete dir again (avoid hanging dir on windows)
rm_rf(file,"normal_dir"),
@@ -210,7 +211,7 @@ icky(Config) when is_list(Config) ->
try
Priv = proplists:get_value(priv_dir, Config),
file:set_cwd(Priv),
- ok = check_icky(prim_file),
+ ok = check_icky(?PRIM_FILE),
ok = check_icky(file),
%% If all is good, delete dir again (avoid hanging dir on windows)
rm_rf(file,"icky_dir"),
@@ -229,7 +230,7 @@ very_icky(Config) when is_list(Config) ->
try
Priv = proplists:get_value(priv_dir, Config),
file:set_cwd(Priv),
- case check_very_icky(prim_file) of
+ case check_very_icky(?PRIM_FILE) of
need_unicode_mode ->
{skipped,"VM needs to be started in Unicode filename mode"};
ok ->
@@ -292,17 +293,14 @@ check_normal(Mod) ->
ok
end,
[ begin
- {ok, FD} = Mod:open(Name,[read]),
- {ok, Content} = Mod:read(FD,1024),
- ok = file:close(FD)
- end || {regular,Name,Content} <- NormalDir ],
- [ begin
{ok, FD} = Mod:open(Name,[read,binary]),
BC = list_to_binary(Content),
{ok, BC} = Mod:read(FD,1024),
ok = file:close(FD)
end || {regular,Name,Content} <- NormalDir ],
+ {error, badarg} = Mod:rename("fil1\0tmp_fil2","tmp_fil1"),
Mod:rename("fil1","tmp_fil1"),
+ {error, badarg} = Mod:read_file("tmp_fil1\0.txt"),
{ok, <<"fil1">>} = Mod:read_file("tmp_fil1"),
{error,enoent} = Mod:read_file("fil1"),
Mod:rename("tmp_fil1","fil1"),
@@ -410,11 +408,6 @@ check_icky(Mod) ->
ok
end,
[ begin
- {ok, FD} = Mod:open(Name,[read]),
- {ok, Content} = Mod:read(FD,1024),
- ok = file:close(FD)
- end || {regular,Name,Content} <- IckyDir ],
- [ begin
{ok, FD} = Mod:open(Name,[read,binary]),
BC = list_to_binary([Content]),
{ok, BC} = Mod:read(FD,1024),
@@ -519,11 +512,6 @@ check_very_icky(Mod) ->
ok
end,
[ begin
- {ok, FD} = Mod:open(Name,[read]),
- {ok, Content} = Mod:read(FD,1024),
- ok = file:close(FD)
- end || {regular,Name,Content} <- VeryIckyDir ],
- [ begin
{ok, FD} = Mod:open(Name,[read,binary]),
BC = list_to_binary([Content]),
{ok, BC} = Mod:read(FD,1024),
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index 620ab235a0..a0ae792ba9 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1038,8 +1038,7 @@ do_from_other_process(Fun) ->
Result ->
Parent ! {Ref,Result}
catch
- Class:Reason ->
- Stacktrace = erlang:get_stacktrace(),
+ Class:Reason:Stacktrace ->
Parent ! {Ref,Class,Reason,Stacktrace}
end
end),
@@ -1617,8 +1616,7 @@ s_start(Socket, Timeout, Parent) ->
try
s_loop(Socket, Timeout, Parent, Handler, gb_trees:empty())
catch
- Class:Reason ->
- Stacktrace = erlang:get_stacktrace(),
+ Class:Reason:Stacktrace ->
io:format(?MODULE_STRING":socket exception ~w:~w at~n"
"~p.~n", [Class,Reason,Stacktrace]),
erlang:raise(Class, Reason, Stacktrace)
diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl
index 12d22519ce..1be016444f 100644
--- a/lib/kernel/test/gen_tcp_api_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_api_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -605,9 +605,9 @@ ok({ok,V}) -> V;
ok(NotOk) ->
try throw(not_ok)
catch
- Thrown ->
+ throw:Thrown:Stacktrace ->
erlang:raise(
- error, {Thrown, NotOk}, tl(erlang:get_stacktrace()))
+ error, {Thrown, NotOk}, tl(Stacktrace))
end.
get_localaddr() ->
diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl
index 929f66d400..358ca872f7 100644
--- a/lib/kernel/test/gen_tcp_misc_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -41,6 +41,7 @@
busy_send/1, busy_disconnect_passive/1, busy_disconnect_active/1,
fill_sendq/1, partial_recv_and_close/1,
partial_recv_and_close_2/1,partial_recv_and_close_3/1,so_priority/1,
+ recvtos/1, recvttl/1, recvtosttl/1, recvtclass/1,
%% Accept tests
primitive_accept/1,multi_accept_close_listen/1,accept_timeout/1,
accept_timeouts_in_order/1,accept_timeouts_in_order2/1,
@@ -50,9 +51,8 @@
killing_acceptor/1,killing_multi_acceptors/1,killing_multi_acceptors2/1,
several_accepts_in_one_go/1, accept_system_limit/1,
active_once_closed/1, send_timeout/1, send_timeout_active/1,
- otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1,
- wrapping_oct/0, wrapping_oct/1,
- otp_9389/1]).
+ otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1,
+ wrapping_oct/0, wrapping_oct/1, otp_9389/1, otp_13939/1]).
%% Internal exports.
-export([sender/3, not_owner/1, passive_sockets_server/2, priority_server/1,
@@ -84,7 +84,8 @@ all() ->
busy_disconnect_passive, busy_disconnect_active,
fill_sendq, partial_recv_and_close,
partial_recv_and_close_2, partial_recv_and_close_3,
- so_priority, primitive_accept,
+ so_priority, recvtos, recvttl, recvtosttl,
+ recvtclass, primitive_accept,
multi_accept_close_listen, accept_timeout,
accept_timeouts_in_order, accept_timeouts_in_order2,
accept_timeouts_in_order3, accept_timeouts_in_order4,
@@ -1573,52 +1574,56 @@ fill_sendq(Config) when is_list(Config) ->
Master = self(),
Server =
spawn_link(fun () ->
- {ok,L} = gen_tcp:listen
- (0, [{active,false},binary,
- {reuseaddr,true},{packet,0}]),
+ {ok,L} = gen_tcp:listen(0, [{active,false},binary,
+ {reuseaddr,true},{packet,0}]),
{ok,Port} = inet:port(L),
Master ! {self(),client,
fill_sendq_client(Port, Master)},
fill_sendq_srv(L, Master)
end),
io:format("~p Server~n", [Server]),
- receive {Server,client,Client} ->
- io:format("~p Client~n", [Client]),
- receive {Server,reader,Reader} ->
- io:format("~p Reader~n", [Reader]),
- fill_sendq_loop(Server, Client, Reader)
+ receive
+ {Server,client,Client} ->
+ io:format("~p Client~n", [Client]),
+ receive
+ {Server,reader,Reader} ->
+ io:format("~p Reader~n", [Reader]),
+ fill_sendq_loop(Server, Client, Reader)
end
end.
fill_sendq_loop(Server, Client, Reader) ->
%% Master
%%
- receive {Server,send} ->
+ receive
+ {Server,send} ->
fill_sendq_loop(Server, Client, Reader)
after 2000 ->
%% Send queue full, sender blocked -> close client.
io:format("Send timeout, closing Client...~n", []),
Client ! {self(),close},
- receive {Server,[{error,closed}]} ->
- io:format("Got server closed.~n"),
- receive {Reader,[{error,closed}]} ->
- io:format
- ("Got reader closed.~n"),
- ok
- after 3000 ->
- ct:fail({timeout,{closed,reader}})
- end;
- {Reader,[{error,closed}]} ->
- io:format("Got reader closed.~n"),
- receive {Server,[{error,closed}]} ->
- io:format("Got server closed~n"),
- ok
- after 3000 ->
- ct:fail({timeout,{closed,server}})
- end
- after 3000 ->
- ct:fail({timeout,{closed,[server,reader]}})
- end
+ receive
+ {Server,[{error,closed}]} ->
+ io:format("Got server closed.~n"),
+ receive
+ {Reader,[{error,closed}]} ->
+ io:format("Got reader closed.~n"),
+ ok
+ after 3000 ->
+ ct:fail({timeout,{closed,reader}})
+ end;
+ {Reader,[{error,closed}]} ->
+ io:format("Got reader closed.~n"),
+ receive
+ {Server,[{error,closed}]} ->
+ io:format("Got server closed~n"),
+ ok
+ after 3000 ->
+ ct:fail({timeout,{closed,server}})
+ end
+ after 3000 ->
+ ct:fail({timeout,{closed,[server,reader]}})
+ end
end.
fill_sendq_srv(L, Master) ->
@@ -1911,6 +1916,232 @@ so_priority(Config) when is_list(Config) ->
end
end.
+
+
+%% IP_RECVTOS and IP_RECVTCLASS for IP_PKTOPTIONS
+%% does not seem to be implemented in Linux until kernel 3.1
+%%
+%% It seems pktoptions does not return valid values
+%% for IPv4 connect sockets. On the accept socket
+%% we get valid values, but on the connect socket we get
+%% the default values for TOS and TTL.
+%%
+%% Therefore the argument CheckConnect that enables
+%% checking the returned values for the connect socket.
+%% It is only used for recvtclass that is an IPv6 option
+%% and there we get valid values from both socket ends.
+
+recvtos(_Config) ->
+ test_pktoptions(
+ inet, [{recvtos,tos,96}],
+ fun recvtos_ok/2,
+ false).
+
+recvtosttl(_Config) ->
+ test_pktoptions(
+ inet, [{recvtos,tos,96},{recvttl,ttl,33}],
+ fun (OSType, OSVer) ->
+ recvtos_ok(OSType, OSVer) andalso recvttl_ok(OSType, OSVer)
+ end,
+ false).
+
+recvttl(_Config) ->
+ test_pktoptions(
+ inet, [{recvttl,ttl,33}],
+ fun recvttl_ok/2,
+ false).
+
+recvtclass(_Config) ->
+ {ok,IFs} = inet:getifaddrs(),
+ case
+ [Name ||
+ {Name,Opts} <- IFs,
+ lists:member({addr,{0,0,0,0,0,0,0,1}}, Opts)]
+ of
+ [_] ->
+ test_pktoptions(
+ inet6, [{recvtclass,tclass,224}],
+ fun recvtclass_ok/2,
+ true);
+ [] ->
+ {skip,{ipv6_not_supported,IFs}}
+ end.
+
+%% These version numbers are the highest noted in daily tests
+%% where the test fails for a plausible reason, so
+%% skip on that platform.
+%%
+%% On newer versions it might be fixed, but we'll see about that
+%% when machines with newer versions gets installed...
+%% If the test still fails for a plausible reason these
+%% version numbers simply should be increased.
+%% Or maybe we should change to only test on known good
+%% platforms - change {unix,_} to false?
+
+%% pktoptions is not supported for IPv4
+recvtos_ok({unix,openbsd}, OSVer) -> not semver_lt(OSVer, {6,4,0});
+recvtos_ok({unix,darwin}, OSVer) -> not semver_lt(OSVer, {17,6,0});
+recvtos_ok({unix,freebsd}, OSVer) -> not semver_lt(OSVer, {11,2,0});
+%% Using the option returns einval, so it is not implemented.
+recvtos_ok({unix,sunos}, OSVer) -> not semver_lt(OSVer, {5,12,0});
+%% Does not return any value - not implemented for pktoptions
+recvtos_ok({unix,linux}, OSVer) -> not semver_lt(OSVer, {3,1,0});
+%%
+recvtos_ok({unix,_}, _) -> true;
+recvtos_ok(_, _) -> false.
+
+%% pktoptions is not supported for IPv4
+recvttl_ok({unix,openbsd}, OSVer) -> not semver_lt(OSVer, {6,4,0});
+recvttl_ok({unix,darwin}, OSVer) -> not semver_lt(OSVer, {17,6,0});
+recvttl_ok({unix,freebsd}, OSVer) -> not semver_lt(OSVer, {11,2,0});
+%% Using the option returns einval, so it is not implemented.
+recvttl_ok({unix,sunos}, OSVer) -> not semver_lt(OSVer, {5,12,0});
+%%
+recvttl_ok({unix,linux}, _) -> true;
+recvttl_ok({unix,_}, _) -> true;
+recvttl_ok(_, _) -> false.
+
+%% pktoptions is not supported for IPv6
+recvtclass_ok({unix,openbsd}, OSVer) -> not semver_lt(OSVer, {6,4,0});
+recvtclass_ok({unix,darwin}, OSVer) -> not semver_lt(OSVer, {17,6,0});
+recvtclass_ok({unix,sunos}, OSVer) -> not semver_lt(OSVer, {5,12,0});
+%% Using the option returns einval, so it is not implemented.
+recvtclass_ok({unix,freebsd}, OSVer) -> not semver_lt(OSVer, {11,2,0});
+%% Does not return any value - not implemented for pktoptions
+recvtclass_ok({unix,linux}, OSVer) -> not semver_lt(OSVer, {3,1,0});
+%%
+recvtclass_ok({unix,_}, _) -> true;
+recvtclass_ok(_, _) -> false.
+
+semver_lt({X1,Y1,Z1}, {X2,Y2,Z2}) ->
+ if
+ X1 > X2 -> false;
+ X1 < X2 -> true;
+ Y1 > Y2 -> false;
+ Y1 < Y2 -> true;
+ Z1 > Z2 -> false;
+ Z1 < Z2 -> true;
+ true -> false
+ end;
+semver_lt(_, {_,_,_}) -> false.
+
+test_pktoptions(Family, Spec, OSFilter, CheckConnect) ->
+ OSType = os:type(),
+ OSVer = os:version(),
+ case OSFilter(OSType, OSVer) of
+ true ->
+ io:format("Os: ~p, ~p~n", [OSType,OSVer]),
+ test_pktoptions(Family, Spec, CheckConnect, OSType, OSVer);
+ false ->
+ {skip,{not_supported_for_os_version,{OSType,OSVer}}}
+ end.
+%%
+test_pktoptions(Family, Spec, CheckConnect, OSType, OSVer) ->
+ Timeout = 5000,
+ RecvOpts = [RecvOpt || {RecvOpt,_,_} <- Spec],
+ TrueRecvOpts = [{RecvOpt,true} || {RecvOpt,_,_} <- Spec],
+ FalseRecvOpts = [{RecvOpt,false} || {RecvOpt,_,_} <- Spec],
+ Opts = [Opt || {_,Opt,_} <- Spec],
+ OptsVals = [{Opt,Val} || {_,Opt,Val} <- Spec],
+ Address =
+ case Family of
+ inet ->
+ {127,0,0,1};
+ inet6 ->
+ {0,0,0,0,0,0,0,1}
+ end,
+ %%
+ %% Set RecvOpts on listen socket
+ {ok,L} =
+ gen_tcp:listen(
+ 0,
+ [Family,binary,{active,false},{send_timeout,Timeout}
+ |TrueRecvOpts]),
+ {ok,P} = inet:port(L),
+ {ok,TrueRecvOpts} = inet:getopts(L, RecvOpts),
+ {ok,OptsValsDefault} = inet:getopts(L, Opts),
+ %%
+ %% Set RecvOpts and Option values on connect socket
+ {ok,S2} =
+ gen_tcp:connect(
+ Address, P,
+ [Family,binary,{active,false},{send_timeout,Timeout}
+ |TrueRecvOpts ++ OptsVals],
+ Timeout),
+ {ok,TrueRecvOpts} = inet:getopts(S2, RecvOpts),
+ {ok,OptsVals} = inet:getopts(S2, Opts),
+ %%
+ %% Accept socket inherits the options from listen socket
+ {ok,S1} = gen_tcp:accept(L, Timeout),
+ {ok,TrueRecvOpts} = inet:getopts(S1, RecvOpts),
+ {ok,OptsValsDefault} = inet:getopts(S1, Opts),
+%%% %%
+%%% %% Handshake
+%%% ok = gen_tcp:send(S1, <<"hello">>),
+%%% {ok,<<"hello">>} = gen_tcp:recv(S2, 5, Timeout),
+%%% ok = gen_tcp:send(S2, <<"hi">>),
+%%% {ok,<<"hi">>} = gen_tcp:recv(S1, 2, Timeout),
+ %%
+ %% Verify returned remote options
+ {ok,[{pktoptions,OptsVals1}]} = inet:getopts(S1, [pktoptions]),
+ {ok,[{pktoptions,OptsVals2}]} = inet:getopts(S2, [pktoptions]),
+ (Result1 = sets_eq(OptsVals1, OptsVals))
+ orelse io:format(
+ "Accept differs: ~p neq ~p~n", [OptsVals1,OptsVals]),
+ (Result2 = sets_eq(OptsVals2, OptsValsDefault))
+ orelse io:format(
+ "Connect differs: ~p neq ~p~n",
+ [OptsVals2,OptsValsDefault]),
+ %%
+ ok = gen_tcp:close(S2),
+ ok = gen_tcp:close(S1),
+ %%
+ %%
+ %% Clear RecvOpts on listen socket and set Option values
+ ok = inet:setopts(L, FalseRecvOpts ++ OptsVals),
+ {ok,FalseRecvOpts} = inet:getopts(L, RecvOpts),
+ {ok,OptsVals} = inet:getopts(L, Opts),
+ %%
+ %% Set RecvOpts on connecting socket
+ %%
+ {ok,S4} =
+ gen_tcp:connect(
+ Address, P,
+ [Family,binary,{active,false},{send_timeout,Timeout}
+ |TrueRecvOpts],
+ Timeout),
+ {ok,TrueRecvOpts} = inet:getopts(S4, RecvOpts),
+ {ok,OptsValsDefault} = inet:getopts(S4, Opts),
+ %%
+ %% Accept socket inherits the options from listen socket
+ {ok,S3} = gen_tcp:accept(L, Timeout),
+ {ok,FalseRecvOpts} = inet:getopts(S3, RecvOpts),
+ {ok,OptsVals} = inet:getopts(S3, Opts),
+ %%
+ %% Verify returned remote options
+ {ok,[{pktoptions,[]}]} = inet:getopts(S3, [pktoptions]),
+ {ok,[{pktoptions,OptsVals4}]} = inet:getopts(S4, [pktoptions]),
+ (Result3 = sets_eq(OptsVals4, OptsVals))
+ orelse io:format(
+ "Accept2 differs: ~p neq ~p~n", [OptsVals4,OptsVals]),
+ %%
+ ok = gen_tcp:close(S4),
+ ok = gen_tcp:close(S3),
+ ok = gen_tcp:close(L),
+ (Result1 and ((not CheckConnect) or (Result2 and Result3)))
+ orelse
+ exit({failed,
+ [{OptsVals1,OptsVals4,OptsVals},
+ {OptsVals2,OptsValsDefault}],
+ {OSType,OSVer}}),
+%% exit({{OSType,OSVer},success}), % In search for the truth
+ ok.
+
+sets_eq(L1, L2) ->
+ lists:sort(L1) == lists:sort(L2).
+
+
+
%% Accept test utilities (suites are below)
millis() ->
@@ -2202,7 +2433,7 @@ wait_until_accepting(Proc,0) ->
exit({timeout_waiting_for_accepting,Proc});
wait_until_accepting(Proc,N) ->
case process_info(Proc,current_function) of
- {current_function,{prim_inet,accept0,2}} ->
+ {current_function,{prim_inet,accept0,3}} ->
case process_info(Proc,status) of
{status,waiting} ->
ok;
@@ -3014,3 +3245,42 @@ ok({ok,V}) -> V.
get_hostname(Name) ->
"@"++Host = lists:dropwhile(fun(C) -> C =/= $@ end, atom_to_list(Name)),
Host.
+
+otp_13939(doc) ->
+ ["Check that writing to a remotely closed socket doesn't block forever "
+ "when exit_on_close is false."];
+otp_13939(suite) ->
+ [];
+otp_13939(Config) when is_list(Config) ->
+ {Pid, Ref} = spawn_opt(
+ fun() ->
+ {ok, Listener} = gen_tcp:listen(0, [{exit_on_close, false}]),
+ {ok, Port} = inet:port(Listener),
+
+ spawn_link(
+ fun() ->
+ {ok, Client} = gen_tcp:connect("localhost", Port,
+ [{active, false}]),
+ ok = gen_tcp:close(Client)
+ end),
+
+ {ok, Accepted} = gen_tcp:accept(Listener),
+
+ ok = gen_tcp:send(Accepted, <<0:(10*1024*1024*8)>>),
+
+ %% The bug surfaces when there's a delay between the send
+ %% operations; inet:getstat is a red herring.
+ timer:sleep(100),
+
+ {error, Code} = gen_tcp:send(Accepted, <<0:(10*1024*1024*8)>>),
+ ct:pal("gen_tcp:send returned ~p~n", [Code])
+ end, [link, monitor]),
+
+ receive
+ {'DOWN', Ref, process, Pid, normal} ->
+ ok
+ after 1000 ->
+ demonitor(Ref, [flush]),
+ exit(Pid, normal),
+ ct:fail("Server process blocked on send.")
+ end.
diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl
index aa616d43d6..af9985de45 100644
--- a/lib/kernel/test/gen_udp_SUITE.erl
+++ b/lib/kernel/test/gen_udp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,8 +34,9 @@
-export([init_per_testcase/2, end_per_testcase/2]).
-export([send_to_closed/1, active_n/1,
- buffer_size/1, binary_passive_recv/1, bad_address/1,
+ buffer_size/1, binary_passive_recv/1, max_buffer_size/1, bad_address/1,
read_packets/1, open_fd/1, connect/1, implicit_inet6/1,
+ recvtos/1, recvtosttl/1, recvttl/1, recvtclass/1,
local_basic/1, local_unbound/1,
local_fdopen/1, local_fdopen_unbound/1, local_abstract/1]).
@@ -44,9 +45,10 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- [send_to_closed, buffer_size, binary_passive_recv,
+ [send_to_closed, buffer_size, binary_passive_recv, max_buffer_size,
bad_address, read_packets, open_fd, connect,
implicit_inet6, active_n,
+ recvtos, recvtosttl, recvttl, recvtclass,
{group, local}].
groups() ->
@@ -237,6 +239,14 @@ buffer_size_server_recv(Socket, IP, Port, Cnt) ->
end.
+%%-------------------------------------------------------------
+%% OTP-15206: Keep buffer small for udp
+%%-------------------------------------------------------------
+max_buffer_size(Config) when is_list(Config) ->
+ {ok, Socket} = gen_udp:open(0, [binary]),
+ ok = inet:setopts(Socket,[{recbuf, 1 bsl 20}]),
+ {ok, [{buffer, 65536}]} = inet:getopts(Socket,[buffer]),
+ gen_udp:close(Socket).
%%-------------------------------------------------------------
%% OTP-3823 gen_udp:recv does not return address in binary mode
@@ -288,58 +298,56 @@ bad_address(Config) when is_list(Config) ->
%%
%% Starts a slave node that on command sends a bunch of messages
%% to our UDP port. The receiving process just receives and
-%% ignores the incoming messages, but counts them.
-%% A tracing process traces the receiving process for
-%% 'receive' and scheduling events. From the trace,
-%% message contents is verified; and, how many messages
-%% are received per in/out scheduling, which should be
-%% the same as the read_packets parameter.
-%%
-%% What happens on the SMP emulator remains to be seen...
-%%
+%% ignores the incoming messages.
+%% A tracing process traces the receiving port for
+%% 'send' and scheduling events. From the trace,
+%% how many messages are received per in/out scheduling,
+%% which should never be more than the read_packet parameter.
%% OTP-6249 UDP option for number of packet reads.
read_packets(Config) when is_list(Config) ->
- case erlang:system_info(smp_support) of
- false ->
- read_packets_1();
- true ->
- %% We would need some new sort of tracing to test this
- %% option reliably in an SMP emulator.
- {skip,"SMP emulator"}
- end.
-
-read_packets_1() ->
N1 = 5,
- N2 = 7,
+ N2 = 1,
+ Msgs = 30000,
{ok,R} = gen_udp:open(0, [{read_packets,N1}]),
{ok,RP} = inet:port(R),
{ok,Node} = start_node(gen_udp_SUITE_read_packets),
Die = make_ref(),
- Loop = erlang:spawn_link(fun () -> infinite_loop(Die) end),
%%
- Msgs1 = [erlang:integer_to_list(M) || M <- lists:seq(1, N1*3)],
- [V1|_] = read_packets_test(R, RP, Msgs1, Node),
+ {V1, Trace1} = read_packets_test(R, RP, Msgs, Node),
{ok,[{read_packets,N1}]} = inet:getopts(R, [read_packets]),
%%
ok = inet:setopts(R, [{read_packets,N2}]),
- Msgs2 = [erlang:integer_to_list(M) || M <- lists:seq(1, N2*3)],
- [V2|_] = read_packets_test(R, RP, Msgs2, Node),
+ {V2, Trace2} = read_packets_test(R, RP, Msgs, Node),
{ok,[{read_packets,N2}]} = inet:getopts(R, [read_packets]),
%%
stop_node(Node),
- Mref = erlang:monitor(process, Loop),
- Loop ! Die,
- receive
- {'DOWN',Mref,_,_, normal} ->
- case {V1,V2} of
- {N1,N2} ->
- ok;
- _ when V1 =/= N1, V2 =/= N2 ->
- ok
- end
+ ct:log("N1=~p, V1=~p vs N2=~p, V2=~p",[N1,V1,N2,V2]),
+
+ dump_terms(Config, "trace1.terms", Trace2),
+ dump_terms(Config, "trace2.terms", Trace2),
+
+ %% Because of the inherit racy-ness of the feature it is
+ %% hard to test that it behaves correctly.
+ %% Right now (OTP 21) a port task takes 5% of the
+ %% allotted port task reductions to execute, so
+ %% the max number of executions a port is allowed to
+ %% do before being re-scheduled is N * 20
+
+ if
+ V1 > (N1 * 20) ->
+ ct:fail("Got ~p msgs, max was ~p", [V1, N1]);
+ V2 > (N2 * 20) ->
+ ct:fail("Got ~p msgs, max was ~p", [V2, N2]);
+ true ->
+ ok
end.
+dump_terms(Config, Name, Terms) ->
+ FName = filename:join(proplists:get_value(priv_dir, Config),Name),
+ file:write_file(FName, term_to_binary(Terms)),
+ ct:log("Logged terms to ~s",[FName]).
+
infinite_loop(Die) ->
receive
Die ->
@@ -350,7 +358,6 @@ infinite_loop(Die) ->
end.
read_packets_test(R, RP, Msgs, Node) ->
- Len = length(Msgs),
Receiver = self(),
Tracer =
spawn_link(
@@ -375,24 +382,24 @@ read_packets_test(R, RP, Msgs, Node) ->
[link,{priority,high}]),
receive
{Sender,{port,SP}} ->
- erlang:trace(self(), true,
- [running,'receive',{tracer,Tracer}]),
+ erlang:trace(R, true,
+ [running_ports,'send',{tracer,Tracer}]),
erlang:yield(),
Sender ! {Receiver,go},
- read_packets_recv(Len),
- erlang:trace(self(), false, [all]),
+ read_packets_recv(Msgs),
+ erlang:trace(R, false, [all]),
Tracer ! {Receiver,get_trace},
receive
{Tracer,{trace,Trace}} ->
- read_packets_verify(R, SP, Msgs, Trace)
+ {read_packets_verify(R, SP, Trace), Trace}
end
end.
-read_packets_send(S, RP, [Msg|Msgs]) ->
- ok = gen_udp:send(S, localhost, RP, Msg),
- read_packets_send(S, RP, Msgs);
-read_packets_send(_S, _RP, []) ->
- ok.
+read_packets_send(_S, _RP, 0) ->
+ ok;
+read_packets_send(S, RP, Msgs) ->
+ ok = gen_udp:send(S, localhost, RP, "UDP FLOOOOOOD"),
+ read_packets_send(S, RP, Msgs - 1).
read_packets_recv(0) ->
ok;
@@ -404,23 +411,24 @@ read_packets_recv(N) ->
timeout
end.
-read_packets_verify(R, SP, Msg, Trace) ->
- lists:reverse(
- lists:sort(read_packets_verify(R, SP, Msg, Trace, 0))).
-
-read_packets_verify(R, SP, Msgs, [{trace,Self,OutIn,_}|Trace], M)
- when Self =:= self(), OutIn =:= out;
- Self =:= self(), OutIn =:= in ->
- push(M, read_packets_verify(R, SP, Msgs, Trace, 0));
-read_packets_verify(R, SP, [Msg|Msgs],
- [{trace,Self,'receive',{udp,R,{127,0,0,1},SP,Msg}}
- |Trace], M)
+read_packets_verify(R, SP, Trace) ->
+ [Max | _] = Pkts = lists:reverse(lists:sort(read_packets_verify(R, SP, Trace, 0))),
+ ct:pal("~p",[lists:sublist(Pkts,10)]),
+ Max.
+
+read_packets_verify(R, SP, [{trace,R,OutIn,_}|Trace], M)
+ when OutIn =:= out; OutIn =:= in ->
+ push(M, read_packets_verify(R, SP, Trace, 0));
+read_packets_verify(R, SP, [{trace, R,'receive',timeout}|Trace], M) ->
+ push(M, read_packets_verify(R, SP, Trace, 0));
+read_packets_verify(R, SP,
+ [{trace,R,'send',{udp,R,{127,0,0,1},SP,_Msg}, Self} | Trace], M)
when Self =:= self() ->
- read_packets_verify(R, SP, Msgs, Trace, M+1);
-read_packets_verify(_R, _SP, [], [], M) ->
+ read_packets_verify(R, SP, Trace, M+1);
+read_packets_verify(_R, _SP, [], M) ->
push(M, []);
-read_packets_verify(_R, _SP, Msgs, Trace, M) ->
- ct:fail({read_packets_verify,mismatch,Msgs,Trace,M}).
+read_packets_verify(_R, _SP, Trace, M) ->
+ ct:fail({read_packets_verify,mismatch,Trace,M}).
push(0, Vs) ->
Vs;
@@ -566,6 +574,168 @@ active_n(Config) when is_list(Config) ->
ok.
+
+recvtos(_Config) ->
+ test_recv_opts(
+ inet, [{recvtos,tos,96}],
+ fun recvtos_ok/2).
+
+recvtosttl(_Config) ->
+ test_recv_opts(
+ inet, [{recvtos,tos,96},{recvttl,ttl,33}],
+ fun (OSType, OSVer) ->
+ recvtos_ok(OSType, OSVer) andalso recvttl_ok(OSType, OSVer)
+ end).
+
+recvttl(_Config) ->
+ test_recv_opts(
+ inet, [{recvttl,ttl,33}],
+ fun recvttl_ok/2).
+
+recvtclass(_Config) ->
+ {ok,IFs} = inet:getifaddrs(),
+ case
+ [Name ||
+ {Name,Opts} <- IFs,
+ lists:member({addr,{0,0,0,0,0,0,0,1}}, Opts)]
+ of
+ [_] ->
+ test_recv_opts(
+ inet6, [{recvtclass,tclass,224}],
+ fun recvtclass_ok/2);
+ [] ->
+ {skip,ipv6_not_supported,IFs}
+ end.
+
+%% These version numbers are just above the highest noted in daily tests
+%% where the test fails for a plausible reason, that is the lowest
+%% where we can expect that the test mighe succeed, so
+%% skip on platforms lower than this.
+%%
+%% On newer versions it might be fixed, but we'll see about that
+%% when machines with newer versions gets installed...
+%% If the test still fails for a plausible reason these
+%% version numbers simply should be increased.
+%% Or maybe we should change to only test on known good platforms?
+
+%% Using the option returns einval, so it is not implemented.
+recvtos_ok({unix,darwin}, OSVer) -> not semver_lt(OSVer, {17,6,0});
+%% Using the option returns einval, so it is not implemented.
+recvtos_ok({unix,openbsd}, OSVer) -> not semver_lt(OSVer, {6,4,0});
+%% Using the option returns einval, so it is not implemented.
+recvtos_ok({unix,sunos}, OSVer) -> not semver_lt(OSVer, {5,12,0});
+%%
+recvtos_ok({unix,_}, _) -> true;
+recvtos_ok(_, _) -> false.
+
+recvttl_ok({unix,_}, _) -> true;
+recvttl_ok(_, _) -> false.
+
+%% Using the option returns einval, so it is not implemented.
+recvtclass_ok({unix,darwin}, OSVer) -> not semver_lt(OSVer, {9,9,0});
+recvtclass_ok({unix,linux}, OSVer) -> not semver_lt(OSVer, {2,6,11});
+%%
+recvtclass_ok({unix,_}, _) -> true;
+recvtclass_ok(_, _) -> false.
+
+semver_lt({X1,Y1,Z1}, {X2,Y2,Z2}) ->
+ if
+ X1 > X2 -> false;
+ X1 < X2 -> true;
+ Y1 > Y2 -> false;
+ Y1 < Y2 -> true;
+ Z1 > Z2 -> false;
+ Z1 < Z2 -> true;
+ true -> false
+ end;
+semver_lt(_, {_,_,_}) -> false.
+
+test_recv_opts(Family, Spec, OSFilter) ->
+ OSType = os:type(),
+ OSVer = os:version(),
+ case OSFilter(OSType, OSVer) of
+ true ->
+ io:format("Os: ~p, ~p~n", [OSType,OSVer]),
+ test_recv_opts(Family, Spec, OSType, OSVer);
+ false ->
+ {skip,{not_supported_for_os_version,{OSType,OSVer}}}
+ end.
+%%
+test_recv_opts(Family, Spec, _OSType, _OSVer) ->
+ Timeout = 5000,
+ RecvOpts = [RecvOpt || {RecvOpt,_,_} <- Spec],
+ TrueRecvOpts = [{RecvOpt,true} || {RecvOpt,_,_} <- Spec],
+ FalseRecvOpts = [{RecvOpt,false} || {RecvOpt,_,_} <- Spec],
+ Opts = [Opt || {_,Opt,_} <- Spec],
+ OptsVals = [{Opt,Val} || {_,Opt,Val} <- Spec],
+ TrueRecvOpts_OptsVals = TrueRecvOpts ++ OptsVals,
+ Addr =
+ case Family of
+ inet ->
+ {127,0,0,1};
+ inet6 ->
+ {0,0,0,0,0,0,0,1}
+ end,
+ %%
+ {ok,S1} =
+ gen_udp:open(0, [Family,binary,{active,false}|TrueRecvOpts]),
+ {ok,P1} = inet:port(S1),
+ {ok,TrueRecvOpts} = inet:getopts(S1, RecvOpts),
+ ok = inet:setopts(S1, FalseRecvOpts),
+ {ok,FalseRecvOpts} = inet:getopts(S1, RecvOpts),
+ ok = inet:setopts(S1, TrueRecvOpts_OptsVals),
+ {ok,TrueRecvOpts_OptsVals} = inet:getopts(S1, RecvOpts ++ Opts),
+ %%
+ {ok,S2} =
+ gen_udp:open(0, [Family,binary,{active,true}|FalseRecvOpts]),
+ {ok,P2} = inet:port(S2),
+ {ok,FalseRecvOpts_OptsVals2} = inet:getopts(S2, RecvOpts ++ Opts),
+ OptsVals2 = FalseRecvOpts_OptsVals2 -- FalseRecvOpts,
+ %%
+ ok = gen_udp:send(S2, Addr, P1, <<"abcde">>),
+ ok = gen_udp:send(S1, Addr, P2, <<"fghij">>),
+ {ok,{_,P2,OptsVals3,<<"abcde">>}} = gen_udp:recv(S1, 0, Timeout),
+ verify_sets_eq(OptsVals3, OptsVals2),
+ receive
+ {udp,S2,_,P1,<<"fghij">>} ->
+ ok;
+ Other1 ->
+ exit({unexpected,Other1})
+ after Timeout ->
+ exit(timeout)
+ end,
+ %%
+ ok = inet:setopts(S1, FalseRecvOpts),
+ {ok,FalseRecvOpts} = inet:getopts(S1, RecvOpts),
+ ok = inet:setopts(S2, TrueRecvOpts),
+ {ok,TrueRecvOpts} = inet:getopts(S2, RecvOpts),
+ %%
+ ok = gen_udp:send(S2, Addr, P1, <<"klmno">>),
+ ok = gen_udp:send(S1, Addr, P2, <<"pqrst">>),
+ {ok,{_,P2,<<"klmno">>}} = gen_udp:recv(S1, 0, Timeout),
+ receive
+ {udp,S2,_,P1,OptsVals4,<<"pqrst">>} ->
+ verify_sets_eq(OptsVals4, OptsVals);
+ Other2 ->
+ exit({unexpected,Other2})
+ after Timeout ->
+ exit(timeout)
+ end,
+ ok = gen_udp:close(S1),
+ ok = gen_udp:close(S2),
+%% exit({{OSType,OSVer},success}), % In search for the truth
+ ok.
+
+verify_sets_eq(L1, L2) ->
+ L = lists:sort(L1),
+ case lists:sort(L2) of
+ L ->
+ ok;
+ _ ->
+ exit({sets_neq,L1,L2})
+ end.
+
+
local_basic(_Config) ->
SFile = local_filename(server),
SAddr = {local,bin_filename(SFile)},
@@ -757,9 +927,9 @@ ok({ok,V}) -> V;
ok(NotOk) ->
try throw(not_ok)
catch
- Thrown ->
+ throw:Thrown:Stacktrace ->
erlang:raise(
- error, {Thrown, NotOk}, tl(erlang:get_stacktrace()))
+ error, {Thrown, NotOk}, tl(Stacktrace))
end.
diff --git a/lib/kernel/test/global_SUITE.erl b/lib/kernel/test/global_SUITE.erl
index 0a7f73c344..8eab36e308 100644
--- a/lib/kernel/test/global_SUITE.erl
+++ b/lib/kernel/test/global_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1383,7 +1383,7 @@ ring(Config) when is_list(Config) ->
rpc_cast(Cp8, ?MODULE, single_node, [Time, Cp7, Config]),
%% sleep to make the partitioned net ready
- ct:sleep(Time - msec()),
+ sleep(Time - msec()),
pong = net_adm:ping(Cp0),
pong = net_adm:ping(Cp1),
@@ -1466,7 +1466,7 @@ simple_ring(Config) when is_list(Config) ->
rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]),
%% sleep to make the partitioned net ready
- ct:sleep(Time - msec()),
+ sleep(Time - msec()),
pong = net_adm:ping(Cp0),
pong = net_adm:ping(Cp1),
@@ -1542,7 +1542,7 @@ line(Config) when is_list(Config) ->
rpc_cast(Cp8, ?MODULE, single_node, [Time, Cp7, Config]),
%% Sleep to make the partitioned net ready
- ct:sleep(Time - msec()),
+ sleep(Time - msec()),
pong = net_adm:ping(Cp0),
pong = net_adm:ping(Cp1),
@@ -1626,7 +1626,7 @@ simple_line(Config) when is_list(Config) ->
rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]),
%% sleep to make the partitioned net ready
- ct:sleep(Time - msec()),
+ sleep(Time - msec()),
pong = net_adm:ping(Cp0),
pong = net_adm:ping(Cp1),
@@ -3470,8 +3470,8 @@ start_procs(Parent, N1, N2, N3, Config) ->
Pid6 = rpc:call(N3, ?MODULE, start_proc3, [test4]),
assert_pid(Pid6),
yes = global:register_name(test1, Pid3),
- yes = global:register_name(test2, Pid4, {global, notify_all_name}),
- yes = global:register_name(test3, Pid5, {global, random_notify_name}),
+ yes = global:register_name(test2, Pid4, fun global:notify_all_name/3),
+ yes = global:register_name(test3, Pid5, fun global:random_notify_name/3),
Resolve = fun(Name, Pid1, Pid2) ->
Parent ! {resolve_called, Name, node()},
{Min, Max} = minmax(Pid1, Pid2),
@@ -3546,7 +3546,7 @@ start_proc_basic(Name) ->
end.
init_proc_basic(Parent, Name) ->
- X = global:register_name(Name, self(), {?MODULE, fix_basic_name}),
+ X = global:register_name(Name, self(), fun ?MODULE:fix_basic_name/3),
Parent ! {self(),X},
loop().
@@ -3555,7 +3555,7 @@ single_node(Time, Node, Config) ->
lists:foreach(fun(N) -> _ = erlang:disconnect_node(N) end, nodes()),
?UNTIL(get_known(node()) =:= [node()]),
spawn(?MODULE, init_2, []),
- ct:sleep(Time - msec()),
+ sleep(Time - msec()),
net_adm:ping(Node).
init_2() ->
@@ -3791,15 +3791,6 @@ stop() ->
test_server:stop_node(Node)
end, nodes()).
-dbg_logs(Name) -> dbg_logs(Name, ?NODES).
-
-dbg_logs(Name, Nodes) ->
- lists:foreach(fun(N) ->
- F = lists:concat([Name, ".log.", N, ".txt"]),
- ok = sys:log_to_file({global_name_server, N}, F)
- end, Nodes).
-
-
%% Tests that locally loaded nodes do not loose contact with other nodes.
global_lost_nodes(Config) when is_list(Config) ->
Timeout = 60,
@@ -4018,13 +4009,6 @@ collect_nodes(N, Max) ->
[Node | collect_nodes(N+1, Max)]
end.
-only_element(_E, []) ->
- true;
-only_element(E, [E|R]) ->
- only_element(E, R);
-only_element(_E, _) ->
- false.
-
exit_p(Pid) ->
Ref = erlang:monitor(process, Pid),
Pid ! die,
@@ -4047,6 +4031,11 @@ wait_for_exit_fast(Pid) ->
ok
end.
+sleep(Time) when Time > 0 ->
+ ct:sleep(Time);
+sleep(_Time) ->
+ ok.
+
check_everywhere(Nodes, Name, Config) ->
?UNTIL(begin
case rpc:multicall(Nodes, global, whereis_name, [Name]) of
@@ -4171,10 +4160,10 @@ rpc_cast(Node, Module, Function, Args, File) ->
%% The emulator now ensures that the node has been removed from
%% nodes().
-rpc_disconnect_node(Node, DisconnectedNode, _Config) ->
- True = rpc:call(Node, erlang, disconnect_node, [DisconnectedNode]),
- False = lists:member(DisconnectedNode, rpc:call(Node, erlang, nodes, [])),
- {true, false} = {True, False}.
+rpc_disconnect_node(Node, DisconnectedNode, Config) ->
+ true = rpc:call(Node, erlang, disconnect_node, [DisconnectedNode]),
+ ?UNTIL
+ (not lists:member(DisconnectedNode, rpc:call(Node, erlang, nodes, []))).
%%%
%%% Utility
diff --git a/lib/kernel/test/heart_SUITE.erl b/lib/kernel/test/heart_SUITE.erl
index 45032faf6d..f5ca6d0e1d 100644
--- a/lib/kernel/test/heart_SUITE.erl
+++ b/lib/kernel/test/heart_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -168,7 +168,7 @@ reboot(Config) when is_list(Config) ->
{ok, Node} = start_check(slave, ?UNIQ_NODE_NAME),
ok = rpc:call(Node, heart, set_cmd,
- [atom_to_list(lib:progname()) ++
+ [ct:get_progname() ++
" -noshell -heart " ++ name(Node) ++ "&"]),
rpc:call(Node, init, reboot, []),
receive
@@ -203,7 +203,7 @@ node_start_immediately_after_crash_test(Config) when is_list(Config) ->
[{"ERL_CRASH_DUMP_SECONDS", "0"}]),
ok = rpc:call(Node, heart, set_cmd,
- [atom_to_list(lib:progname()) ++
+ [ct:get_progname() ++
" -noshell -heart " ++ name(Node) ++ "&"]),
Mod = exhaust_atoms,
@@ -254,7 +254,7 @@ node_start_soon_after_crash_test(Config) when is_list(Config) ->
[{"ERL_CRASH_DUMP_SECONDS", "10"}]),
ok = rpc:call(Node, heart, set_cmd,
- [atom_to_list(lib:progname()) ++
+ [ct:get_progname() ++
" -noshell -heart " ++ name(Node) ++ "&"]),
Mod = exhaust_atoms,
@@ -309,7 +309,7 @@ set_cmd(Config) when is_list(Config) ->
clear_cmd(Config) when is_list(Config) ->
{ok, Node} = start_check(slave, ?UNIQ_NODE_NAME),
ok = rpc:call(Node, heart, set_cmd,
- [atom_to_list(lib:progname()) ++
+ [ct:get_progname() ++
" -noshell -heart " ++ name(Node) ++ "&"]),
rpc:call(Node, init, reboot, []),
receive
@@ -346,9 +346,16 @@ clear_cmd(Config) when is_list(Config) ->
get_cmd(Config) when is_list(Config) ->
{ok, Node} = start_check(slave, ?UNIQ_NODE_NAME),
- Cmd = "test",
- ok = rpc:call(Node, heart, set_cmd, [Cmd]),
- {ok, Cmd} = rpc:call(Node, heart, get_cmd, []),
+
+ ShortCmd = "test",
+ ok = rpc:call(Node, heart, set_cmd, [ShortCmd]),
+ {ok, ShortCmd} = rpc:call(Node, heart, get_cmd, []),
+
+ %% This would hang prior to OTP-15024 being fixed.
+ LongCmd = [$a || _ <- lists:seq(1, 160)],
+ ok = rpc:call(Node, heart, set_cmd, [LongCmd]),
+ {ok, LongCmd} = rpc:call(Node, heart, get_cmd, []),
+
stop_node(Node),
ok.
diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl
index 3b502be8b8..2e5f8c7d2c 100644
--- a/lib/kernel/test/inet_SUITE.erl
+++ b/lib/kernel/test/inet_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -40,7 +40,8 @@
lookup_bad_search_option/1,
getif/1,
getif_ifr_name_overflow/1,getservbyname_overflow/1, getifaddrs/1,
- parse_strict_address/1, simple_netns/1, simple_netns_open/1,
+ parse_strict_address/1, ipv4_mapped_ipv6_address/1,
+ simple_netns/1, simple_netns_open/1,
simple_bind_to_device/1, simple_bind_to_device_open/1]).
-export([get_hosts/1, get_ipv6_hosts/1, parse_hosts/1, parse_address/1,
@@ -667,6 +668,26 @@ parse_strict_address(Config) when is_list(Config) ->
{ok, {3089,3106,23603,50240,0,0,119,136}} =
inet:parse_strict_address("c11:0c22:5c33:c440::077:0088").
+ipv4_mapped_ipv6_address(Config) when is_list(Config) ->
+ {D1,D2,D3,D4} = IPv4Address =
+ {rand:uniform(256) - 1,
+ rand:uniform(256) - 1,
+ rand:uniform(256) - 1,
+ rand:uniform(256) - 1},
+ E7 = (D1 bsl 8) bor D2,
+ E8 = (D3 bsl 8) bor D4,
+ io:format("IPv4Address: ~p.~n", [IPv4Address]),
+ {0,0,0,0,0,65535,E7,E8} = inet:ipv4_mapped_ipv6_address(IPv4Address),
+ IPv6Address =
+ {rand:uniform(65536) - 1,
+ rand:uniform(65536) - 1,
+ rand:uniform(65536) - 1,
+ rand:uniform(65536) - 1,
+ rand:uniform(65536) - 1,
+ rand:uniform(65536) - 1, E7, E8},
+ IPv4Address = inet:ipv4_mapped_ipv6_address(IPv6Address),
+ ok.
+
t_gethostnative(Config) when is_list(Config) ->
%% this will result in 26 bytes sent which causes problem in Windows
%% if the port-program has not assured stdin to be read in BINARY mode
@@ -1083,11 +1104,9 @@ ifaddrs([{If,Opts}|IOs]) ->
#ifopts{flags=F} = Ifopts = check_ifopts(Opts, #ifopts{name=If}),
case F of
{flags,Flags} ->
- case lists:member(up, Flags) of
- true ->
- Ifopts#ifopts.addrs;
- false ->
- []
+ case lists:member(running, Flags) of
+ true -> Ifopts#ifopts.addrs;
+ false -> []
end ++ ifaddrs(IOs);
undefined ->
ifaddrs(IOs)
diff --git a/lib/kernel/test/inet_res_SUITE.erl b/lib/kernel/test/inet_res_SUITE.erl
index 6691ad9c06..df6e48abae 100644
--- a/lib/kernel/test/inet_res_SUITE.erl
+++ b/lib/kernel/test/inet_res_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -217,10 +217,10 @@ proxy_start(TC, {NS,P}) ->
spawn_link(
fun () ->
try proxy_start(TC, NS, P, Parent, Tag)
- catch C:X ->
+ catch C:X:Stacktrace ->
io:format(
"~w: ~w:~p ~p~n",
- [self(),C,X,erlang:get_stacktrace()])
+ [self(),C,X,Stacktrace])
end
end),
receive {started,Tag,Port} ->
diff --git a/lib/kernel/test/init_SUITE.erl b/lib/kernel/test/init_SUITE.erl
index 2b59eb2bfe..6a006cdc01 100644
--- a/lib/kernel/test/init_SUITE.erl
+++ b/lib/kernel/test/init_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -299,7 +299,7 @@ many_restarts() ->
many_restarts(Config) when is_list(Config) ->
{ok, Node} = loose_node:start(init_test, "", ?DEFAULT_TIMEOUT_SEC),
- loop_restart(50,Node,rpc:call(Node,erlang,whereis,[error_logger])),
+ loop_restart(50,Node,rpc:call(Node,erlang,whereis,[logger])),
loose_node:stop(Node),
ok.
@@ -316,13 +316,13 @@ loop_restart(N,Node,EHPid) ->
ct:fail(not_stopping)
end,
ok = wait_for(30, Node, EHPid),
- loop_restart(N-1,Node,rpc:call(Node,erlang,whereis,[error_logger])).
+ loop_restart(N-1,Node,rpc:call(Node,erlang,whereis,[logger])).
wait_for(0,Node,_) ->
loose_node:stop(Node),
error;
wait_for(N,Node,EHPid) ->
- case rpc:call(Node, erlang, whereis, [error_logger]) of
+ case rpc:call(Node, erlang, whereis, [logger]) of
Pid when is_pid(Pid), Pid =/= EHPid ->
%% erlang:display(ok),
ok;
@@ -365,7 +365,9 @@ restart(Config) when is_list(Config) ->
%% Ok, the node is up, now the real test test begins.
erlang:monitor_node(Node, true),
SysProcs0 = rpc:call(Node, ?MODULE, find_system_processes, []),
- [InitPid, PurgerPid, LitCollectorPid, DirtyCodePid] = SysProcs0,
+ io:format("SysProcs0=~p~n", [SysProcs0]),
+ [InitPid, PurgerPid, LitCollectorPid,
+ DirtySigNPid, DirtySigHPid, DirtySigMPid] = SysProcs0,
InitPid = rpc:call(Node, erlang, whereis, [init]),
PurgerPid = rpc:call(Node, erlang, whereis, [erts_code_purger]),
Procs = rpc:call(Node, erlang, processes, []),
@@ -381,7 +383,9 @@ restart(Config) when is_list(Config) ->
ok = wait_restart(30, Node),
SysProcs1 = rpc:call(Node, ?MODULE, find_system_processes, []),
- [InitPid1, PurgerPid1, LitCollectorPid1, DirtyCodePid1] = SysProcs1,
+ io:format("SysProcs1=~p~n", [SysProcs1]),
+ [InitPid1, PurgerPid1, LitCollectorPid1,
+ DirtySigNPid1, DirtySigHPid1, DirtySigMPid1] = SysProcs1,
%% Still the same init process!
InitPid1 = rpc:call(Node, erlang, whereis, [init]),
@@ -394,20 +398,18 @@ restart(Config) when is_list(Config) ->
PurgerP = pid_to_list(PurgerPid1),
%% and same literal area collector process!
- case LitCollectorPid of
- undefined -> undefined = LitCollectorPid1;
- _ ->
- LitCollectorP = pid_to_list(LitCollectorPid),
- LitCollectorP = pid_to_list(LitCollectorPid1)
- end,
-
- %% and same dirty process code checker process!
- case DirtyCodePid of
- undefined -> undefined = DirtyCodePid1;
- _ ->
- DirtyCodeP = pid_to_list(DirtyCodePid),
- DirtyCodeP = pid_to_list(DirtyCodePid1)
- end,
+ LitCollectorP = pid_to_list(LitCollectorPid),
+ LitCollectorP = pid_to_list(LitCollectorPid1),
+
+ %% and same normal dirty signal handler process!
+ DirtySigNP = pid_to_list(DirtySigNPid),
+ DirtySigNP = pid_to_list(DirtySigNPid1),
+ %% and same high dirty signal handler process!
+ DirtySigHP = pid_to_list(DirtySigHPid),
+ DirtySigHP = pid_to_list(DirtySigHPid1),
+ %% and same max dirty signal handler process!
+ DirtySigMP = pid_to_list(DirtySigMPid),
+ DirtySigMP = pid_to_list(DirtySigMPid1),
NewProcs0 = rpc:call(Node, erlang, processes, []),
NewProcs = NewProcs0 -- SysProcs1,
@@ -433,7 +435,9 @@ restart(Config) when is_list(Config) ->
-record(sys_procs, {init,
code_purger,
literal_collector,
- dirty_proc_checker}).
+ dirty_sig_handler_normal,
+ dirty_sig_handler_high,
+ dirty_sig_handler_max}).
find_system_processes() ->
find_system_procs(processes(), #sys_procs{}).
@@ -442,21 +446,32 @@ find_system_procs([], SysProcs) ->
[SysProcs#sys_procs.init,
SysProcs#sys_procs.code_purger,
SysProcs#sys_procs.literal_collector,
- SysProcs#sys_procs.dirty_proc_checker];
+ SysProcs#sys_procs.dirty_sig_handler_normal,
+ SysProcs#sys_procs.dirty_sig_handler_high,
+ SysProcs#sys_procs.dirty_sig_handler_max];
find_system_procs([P|Ps], SysProcs) ->
- case process_info(P, initial_call) of
- {initial_call,{otp_ring0,start,2}} ->
+ case process_info(P, [initial_call, priority]) of
+ [{initial_call,{otp_ring0,start,2}},_] ->
undefined = SysProcs#sys_procs.init,
find_system_procs(Ps, SysProcs#sys_procs{init = P});
- {initial_call,{erts_code_purger,start,0}} ->
+ [{initial_call,{erts_code_purger,start,0}},_] ->
undefined = SysProcs#sys_procs.code_purger,
find_system_procs(Ps, SysProcs#sys_procs{code_purger = P});
- {initial_call,{erts_literal_area_collector,start,0}} ->
+ [{initial_call,{erts_literal_area_collector,start,0}},_] ->
undefined = SysProcs#sys_procs.literal_collector,
find_system_procs(Ps, SysProcs#sys_procs{literal_collector = P});
- {initial_call,{erts_dirty_process_code_checker,start,0}} ->
- undefined = SysProcs#sys_procs.dirty_proc_checker,
- find_system_procs(Ps, SysProcs#sys_procs{dirty_proc_checker = P});
+ [{initial_call,{erts_dirty_process_signal_handler,start,0}},
+ {priority,normal}] ->
+ undefined = SysProcs#sys_procs.dirty_sig_handler_normal,
+ find_system_procs(Ps, SysProcs#sys_procs{dirty_sig_handler_normal = P});
+ [{initial_call,{erts_dirty_process_signal_handler,start,0}},
+ {priority,high}] ->
+ undefined = SysProcs#sys_procs.dirty_sig_handler_high,
+ find_system_procs(Ps, SysProcs#sys_procs{dirty_sig_handler_high = P});
+ [{initial_call,{erts_dirty_process_signal_handler,start,0}},
+ {priority,max}] ->
+ undefined = SysProcs#sys_procs.dirty_sig_handler_max,
+ find_system_procs(Ps, SysProcs#sys_procs{dirty_sig_handler_max = P});
_ ->
find_system_procs(Ps, SysProcs)
end.
diff --git a/lib/kernel/test/kernel_SUITE.erl b/lib/kernel/test/kernel_SUITE.erl
index da56359294..3e5ed855b5 100644
--- a/lib/kernel/test/kernel_SUITE.erl
+++ b/lib/kernel/test/kernel_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,14 +30,14 @@
-export([init_per_testcase/2, end_per_testcase/2]).
%% Test cases must be exported.
--export([app_test/1, appup_test/1]).
+-export([app_test/1, appup_test/1, refc/1]).
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap,{minutes,2}}].
all() ->
- [app_test, appup_test].
+ [app_test, appup_test, refc].
groups() ->
[].
@@ -163,3 +163,68 @@ check_appup([Vsn|Vsns],Instrs,Expected) ->
end;
check_appup([],_,_) ->
ok.
+
+%%% Check that refc module handles the counters as expected
+refc(_Config) ->
+ Enable = fun(Enable) -> erlang:system_flag(scheduler_wall_time, Enable) end,
+ IsOn = fun() -> undefined /= erlang:statistics(scheduler_wall_time) end,
+ Tester = self(),
+ Loop = fun Loop() ->
+ receive
+ die -> normal;
+ {apply, Bool} ->
+ Res = Enable(Bool),
+ Tester ! {self(), Res},
+ Loop()
+ end
+ end,
+
+ %% Counter should be 0
+ false = Enable(false),
+
+ false = Enable(true),
+ true = Enable(true),
+ true = Enable(false),
+ true = Enable(false),
+
+ %% Counter should be 0
+ false = IsOn(),
+
+ P1 = spawn_link(Loop),
+ P1 ! {apply, true},
+ receive {P1, R1} -> false = R1 end,
+
+ %% P1 has turned it on counter should be one
+ true = IsOn(),
+ true = Enable(true),
+ true = Enable(false),
+ true = IsOn(),
+
+ P1 ! {apply, false},
+ receive {P1, R2} -> true = R2 end,
+ false = IsOn(),
+
+ P1 ! {apply, true},
+ receive {P1, R3} -> false = R3 end,
+ true = IsOn(),
+ true = Enable(false),
+
+
+ P1 ! die,
+ timer:sleep(100),
+ false = IsOn(),
+ false = Enable(false),
+
+ P2 = spawn_link(Loop),
+ P2 ! {apply, true},
+ receive {P2, R4} -> false = R4 end,
+ true = IsOn(),
+ P2 ! {apply, true},
+ receive {P2, R5} -> true = R5 end,
+ true = IsOn(),
+
+ P2 ! die,
+ timer:sleep(100),
+ false = IsOn(),
+
+ ok.
diff --git a/lib/kernel/test/kernel_bench.spec b/lib/kernel/test/kernel_bench.spec
new file mode 100644
index 0000000000..4de133f21b
--- /dev/null
+++ b/lib/kernel/test/kernel_bench.spec
@@ -0,0 +1,2 @@
+{groups,"../kernel_test",zlib_SUITE,[bench]}.
+{groups,"../kernel_test",file_SUITE,[bench]}.
diff --git a/lib/kernel/test/kernel_config_SUITE.erl b/lib/kernel/test/kernel_config_SUITE.erl
index 9a4578917d..9207025a2c 100644
--- a/lib/kernel/test/kernel_config_SUITE.erl
+++ b/lib/kernel/test/kernel_config_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -76,7 +76,7 @@ sync(Conf) when is_list(Conf) ->
%% Reset wall_clock
{T1,_} = erlang:statistics(wall_clock),
io:format("~p~n", [{t1, T1}]),
- Command = lists:concat([lib:progname(),
+ Command = lists:append([ct:get_progname(),
" -detached -sname cp1 ",
"-config ", Config,
" -env ERL_CRASH_DUMP erl_crash_dump.cp1"]),
diff --git a/lib/kernel/test/logger.cover b/lib/kernel/test/logger.cover
new file mode 100644
index 0000000000..960bc0abff
--- /dev/null
+++ b/lib/kernel/test/logger.cover
@@ -0,0 +1,14 @@
+%% -*- erlang -*-
+{incl_mods,[error_logger,
+ logger,
+ logger_backend,
+ logger_config,
+ logger_disk_log_h,
+ logger_h_common,
+ logger_filters,
+ logger_formatter,
+ logger_server,
+ logger_simple_h,
+ logger_std_h,
+ logger_sup]}.
+
diff --git a/lib/kernel/test/logger.spec b/lib/kernel/test/logger.spec
new file mode 100644
index 0000000000..1ab90b3e93
--- /dev/null
+++ b/lib/kernel/test/logger.spec
@@ -0,0 +1,11 @@
+%% -*-erlang-*-
+{suites,"../kernel_test", [error_logger_SUITE,
+ error_logger_warn_SUITE,
+ logger_SUITE,
+ logger_disk_log_h_SUITE,
+ logger_env_var_SUITE,
+ logger_filters_SUITE,
+ logger_formatter_SUITE,
+ logger_legacy_SUITE,
+ logger_simple_h_SUITE,
+ logger_std_h_SUITE]}.
diff --git a/lib/kernel/test/logger_SUITE.erl b/lib/kernel/test/logger_SUITE.erl
new file mode 100644
index 0000000000..b7ccba8e70
--- /dev/null
+++ b/lib/kernel/test/logger_SUITE.erl
@@ -0,0 +1,1318 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("kernel/include/logger.hrl").
+-include_lib("kernel/src/logger_internal.hrl").
+
+-define(str,"Log from "++atom_to_list(?FUNCTION_NAME)++
+ ":"++integer_to_list(?LINE)).
+-define(map_rep,#{function=>?FUNCTION_NAME, line=>?LINE}).
+-define(keyval_rep,[{function,?FUNCTION_NAME}, {line,?LINE}]).
+
+-define(MY_LOC(N),#{mfa=>{?MODULE,?FUNCTION_NAME,?FUNCTION_ARITY},
+ file=>?FILE, line=>?LINE-N}).
+
+-define(TRY(X), my_try(fun() -> X end)).
+
+
+suite() ->
+ [{timetrap,{seconds,30}},
+ {ct_hooks,[logger_test_lib]}].
+
+init_per_suite(Config) ->
+ case logger:get_handler_config(?STANDARD_HANDLER) of
+ {ok,StdH} ->
+ ok = logger:remove_handler(?STANDARD_HANDLER),
+ [{default_handler,StdH}|Config];
+ _ ->
+ Config
+ end.
+
+end_per_suite(Config) ->
+ case ?config(default_handler,Config) of
+ #{module:=HMod} = HConfig ->
+ ok = logger:add_handler(?STANDARD_HANDLER,HMod,HConfig);
+ _ ->
+ ok
+ end.
+
+init_per_group(_Group, Config) ->
+ Config.
+
+end_per_group(_Group, _Config) ->
+ ok.
+
+init_per_testcase(_TestCase, Config) ->
+ PC = logger:get_primary_config(),
+ [{logger_config,PC}|Config].
+
+end_per_testcase(Case, Config) ->
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
+ ok.
+
+groups() ->
+ [].
+
+all() ->
+ [start_stop,
+ add_remove_handler,
+ multiple_handlers,
+ add_remove_filter,
+ change_config,
+ set_formatter,
+ log_no_levels,
+ log_all_levels_api,
+ macros,
+ set_level,
+ set_module_level,
+ set_application_level,
+ cache_module_level,
+ format_report,
+ filter_failed,
+ handler_failed,
+ config_sanity_check,
+ log_failed,
+ emulator,
+ via_logger_process,
+ other_node,
+ compare_levels,
+ process_metadata,
+ app_config,
+ kernel_config].
+
+start_stop(_Config) ->
+ S = whereis(logger),
+ true = is_pid(S),
+ ok.
+
+add_remove_handler(_Config) ->
+ register(callback_receiver,self()),
+ Hs0 = logger:get_handler_config(),
+ {error,{not_found,h1}} = logger:get_handler_config(h1),
+ ok = logger:add_handler(h1,?MODULE,#{}),
+ [add] = test_server:messages_get(),
+ Hs = logger:get_handler_config(),
+ Hs0 = lists:filter(fun(#{id:=h1}) -> false; (_) -> true end, Hs),
+ {ok,#{module:=?MODULE,level:=all,filters:=[],filter_default:=log}} = %defaults
+ logger:get_handler_config(h1),
+ ok = logger:set_handler_config(h1,filter_default,stop),
+ [changing_config] = test_server:messages_get(),
+ ?LOG_NOTICE("hello",[]),
+ ok = check_no_log(),
+ ok = logger:set_handler_config(h1,filter_default,log),
+ [changing_config] = test_server:messages_get(),
+ {ok,#{filter_default:=log}} = logger:get_handler_config(h1),
+ ?LOG_NOTICE("hello",[]),
+ ok = check_logged(notice,"hello",[],?MY_LOC(1)),
+ ok = logger:remove_handler(h1),
+ [remove] = test_server:messages_get(),
+ Hs0 = logger:get_handler_config(),
+ {error,{not_found,h1}} = logger:get_handler_config(h1),
+ {error,{not_found,h1}} = logger:remove_handler(h1),
+ logger:notice("hello",[]),
+ ok = check_no_log(),
+ ok.
+
+add_remove_handler(cleanup,_Config) ->
+ logger:remove_handler(h1),
+ ok.
+
+multiple_handlers(_Config) ->
+ ok = logger:add_handler(h1,?MODULE,#{level=>notice,filter_default=>log}),
+ ok = logger:add_handler(h2,?MODULE,#{level=>error,filter_default=>log}),
+ ?LOG_ERROR("hello",[]),
+ ok = check_logged(error,"hello",[],?MY_LOC(1)),
+ ok = check_logged(error,"hello",[],?MY_LOC(2)),
+ ?LOG_NOTICE("hello",[]),
+ ok = check_logged(notice,"hello",[],?MY_LOC(1)),
+ ok = check_no_log(),
+ ok.
+
+multiple_handlers(cleanup,_Config) ->
+ logger:remove_handler(h1),
+ logger:remove_handler(h2),
+ ok.
+
+add_remove_filter(_Config) ->
+ ok = logger:add_handler(h1,?MODULE,#{level=>notice,filter_default=>log}),
+ LF = {fun(Log,_) -> Log#{level=>error} end, []},
+ ok = logger:add_primary_filter(lf,LF),
+ {error,{already_exist,lf}} = logger:add_primary_filter(lf,LF),
+ {error,{already_exist,lf}} = logger:add_primary_filter(lf,{fun(Log,_) ->
+ Log
+ end, []}),
+ ?LOG_NOTICE("hello",[]),
+ ok = check_logged(error,"hello",[],?MY_LOC(1)),
+ ok = check_no_log(),
+
+ ok = logger:add_handler(h2,?MODULE,#{level=>notice,filter_default=>log}),
+ HF = {fun(#{level:=error}=Log,_) ->
+ Log#{level=>mylevel};
+ (_,_) ->
+ ignore
+ end,
+ []},
+ ok = logger:add_handler_filter(h1,hf,HF),
+ {error,{already_exist,hf}} = logger:add_handler_filter(h1,hf,HF),
+ {error,{already_exist,hf}} = logger:add_handler_filter(h1,hf,{fun(Log,_) ->
+ Log
+ end, []}),
+ ?LOG_NOTICE("hello",[]),
+ ok = check_logged(mylevel,"hello",[],?MY_LOC(1)),
+ ok = check_logged(error,"hello",[],?MY_LOC(2)),
+
+ ok = logger:remove_primary_filter(lf),
+ {error,{not_found,lf}} = logger:remove_primary_filter(lf),
+
+ ?LOG_NOTICE("hello",[]),
+ ok = check_logged(notice,"hello",[],?MY_LOC(1)),
+ ok = check_logged(notice,"hello",[],?MY_LOC(2)),
+
+ ?LOG_ERROR("hello",[]),
+ ok = check_logged(mylevel,"hello",[],?MY_LOC(1)),
+ ok = check_logged(error,"hello",[],?MY_LOC(2)),
+
+ ok = logger:remove_handler_filter(h1,hf),
+ {error,{not_found,hf}} = logger:remove_handler_filter(h1,hf),
+ ?LOG_NOTICE("hello",[]),
+ ok = check_logged(notice,"hello",[],?MY_LOC(1)),
+ ok = check_logged(notice,"hello",[],?MY_LOC(2)),
+
+ ?LOG_ERROR("hello",[]),
+ ok = check_logged(error,"hello",[],?MY_LOC(1)),
+ ok = check_logged(error,"hello",[],?MY_LOC(2)),
+ ok.
+
+add_remove_filter(cleanup,_Config) ->
+ logger:remove_primary_filter(lf),
+ logger:remove_handler(h1),
+ logger:remove_handler(h2),
+ ok.
+
+change_config(_Config) ->
+ %% Overwrite handler config - check that defaults are added
+ {error,{not_found,h1}} = logger:set_handler_config(h1,#{}),
+ ok = logger:add_handler(h1,?MODULE,#{level=>notice,custom=>custom}),
+ {ok,#{module:=?MODULE,level:=notice,filter_default:=log,custom:=custom}} =
+ logger:get_handler_config(h1),
+ register(callback_receiver,self()),
+ ok = logger:set_handler_config(h1,#{filter_default=>stop}),
+ [changing_config] = test_server:messages_get(),
+ {ok,#{module:=?MODULE,level:=all,filter_default:=stop}=C2} =
+ logger:get_handler_config(h1),
+ false = maps:is_key(custom,C2),
+ {error,fail} = logger:set_handler_config(h1,#{conf_call=>fun() -> {error,fail} end}),
+ {error,{attempting_syncronous_call_to_self,_}} =
+ logger:set_handler_config(
+ h1,#{conf_call=>fun() -> logger:set_handler_config(?MODULE,#{}) end}),
+ ok =
+ logger:set_handler_config(
+ h1,#{conf_call=>fun() -> logger:set_module_level(?MODULE,debug) end}),
+ {ok,C2} = logger:get_handler_config(h1),
+
+ %% Change handler config: Single key
+ {error,fail} = logger:set_handler_config(h1,conf_call,fun() -> {error,fail} end),
+ ok = logger:set_handler_config(h1,custom,custom),
+ [changing_config] = test_server:messages_get(),
+ {ok,#{custom:=custom}=C3} = logger:get_handler_config(h1),
+ C2 = maps:remove(custom,C3),
+
+ %% Change handler config: Map
+ ok = logger:update_handler_config(h1,#{custom=>new_custom}),
+ [changing_config] = test_server:messages_get(),
+ {ok,C4} = logger:get_handler_config(h1),
+ C4 = C3#{custom:=new_custom},
+
+ %% Change primary config: Single key
+ PConfig0 = logger:get_primary_config(),
+ ok = logger:set_primary_config(level,warning),
+ PConfig1 = logger:get_primary_config(),
+ PConfig1 = PConfig0#{level:=warning},
+
+ %% Change primary config: Map
+ ok = logger:update_primary_config(#{level=>error}),
+ PConfig2 = logger:get_primary_config(),
+ PConfig2 = PConfig1#{level:=error},
+
+ %% Overwrite primary config - check that defaults are added
+ ok = logger:set_primary_config(#{filter_default=>stop}),
+ #{level:=notice,filters:=[],filter_default:=stop}=PC1 =
+ logger:get_primary_config(),
+ 3 = maps:size(PC1),
+ %% Check that internal 'handlers' field has not been changed
+ MS = [{{{?HANDLER_KEY,'$1'},'_','_'},[],['$1']}],
+ HIds1 = lists:sort(ets:select(?LOGGER_TABLE,MS)), % dirty, internal data
+ HIds2 = lists:sort(logger:get_handler_ids()),
+ HIds1 = HIds2,
+
+ %% Cleanup
+ ok = logger:set_primary_config(PConfig0),
+ [] = test_server:messages_get(),
+
+ ok.
+
+change_config(cleanup,Config) ->
+ logger:remove_handler(h1),
+ PC = ?config(logger_config,Config),
+ logger:set_primary_config(PC),
+ ok.
+
+set_formatter(_Config) ->
+ {error,{not_found,h1}}=logger:set_handler_config(h1,formatter,{?MODULE,[]}),
+ ok = logger:add_handler(h1,?MODULE,#{level=>notice,filter_default=>log}),
+ ok = logger:set_handler_config(h1,formatter,{?MODULE,[]}),
+ logger:notice("hello",[]),
+ receive
+ {_Log,#{formatter:={?MODULE,[]}}} ->
+ ok
+ after 500 ->
+ ct:fail({timeout,no_log,process_info(self(),messages)})
+ end,
+ ok.
+
+set_formatter(cleanup,_Config) ->
+ logger:remove_handler(h1),
+ ok.
+
+log_no_levels(_Config) ->
+ ok = logger:add_handler(h1,?MODULE,#{level=>all,filter_default=>log}),
+ logger:notice(M1=?map_rep),
+ ok = check_logged(notice,M1,#{}),
+
+ Levels = [emergency,alert,critical,error,warning,notice,info,debug],
+ ok = logger:set_primary_config(level,none),
+ [logger:Level(#{Level=>rep}) || Level <- Levels],
+ ok = check_no_log(),
+
+ ok = logger:set_primary_config(level,all),
+ M2 = ?map_rep,
+ ?LOG_NOTICE(M2),
+ ok = check_logged(notice,M2,#{}),
+
+ ok = logger:set_module_level(?MODULE,none),
+ ?LOG_EMERGENCY(?map_rep),
+ ?LOG_ALERT(?map_rep),
+ ?LOG_CRITICAL(?map_rep),
+ ?LOG_ERROR(?map_rep),
+ ?LOG_WARNING(?map_rep),
+ ?LOG_NOTICE(?map_rep),
+ ?LOG_INFO(?map_rep),
+ ?LOG_DEBUG(?map_rep),
+ ok = check_no_log(),
+
+ ok = logger:unset_module_level(?MODULE),
+ logger:notice(M3=?map_rep),
+ ok = check_logged(notice,M3,#{}),
+
+ ok = logger:set_handler_config(h1,level,none),
+ [logger:Level(#{Level=>rep}) || Level <- Levels],
+ ok = check_no_log(),
+
+ ok.
+log_no_levels(cleanup,_Config) ->
+ logger:remove_handler(h1),
+ logger:set_primary_config(level,notice),
+ logger:unset_module_level(?MODULE),
+ ok.
+
+log_all_levels_api(_Config) ->
+ ok = logger:set_primary_config(level,all),
+ ok = logger:add_handler(h1,?MODULE,#{level=>all,filter_default=>log}),
+ test_api(emergency),
+ test_api(alert),
+ test_api(critical),
+ test_api(error),
+ test_api(warning),
+ test_api(notice),
+ test_api(info),
+ test_api(debug),
+ test_log_function(emergency),
+ ok.
+
+log_all_levels_api(cleanup,_Config) ->
+ logger:remove_handler(h1),
+ logger:set_primary_config(level,notice),
+ ok.
+
+macros(_Config) ->
+ ok = logger:add_handler(h1,?MODULE,#{level=>all,filter_default=>log}),
+ test_macros(emergency),
+ test_log_macro(alert),
+ ok.
+
+macros(cleanup,_Config) ->
+ logger:remove_handler(h1),
+ logger:unset_module_level(?MODULE),
+ ok.
+
+set_level(_Config) ->
+ ok = logger:add_handler(h1,?MODULE,#{level=>all,filter_default=>log}),
+ logger:debug(?map_rep),
+ ok = check_no_log(),
+ logger:notice(M1=?map_rep),
+ ok = check_logged(notice,M1,#{}),
+ ok = logger:set_primary_config(level,debug),
+ logger:debug(M2=?map_rep),
+ ok = check_logged(debug,M2,#{}),
+ ok.
+
+set_level(cleanup,_Config) ->
+ logger:remove_handler(h1),
+ logger:set_primary_config(level,notice),
+ ok.
+
+set_module_level(_Config) ->
+ [] = logger:get_module_level([?MODULE,other]),
+ [] = logger:get_module_level(?MODULE),
+ [] = logger:get_module_level(),
+
+ ok = logger:add_handler(h1,?MODULE,#{level=>notice,filter_default=>log}),
+ {error,{invalid_level,bad}} = logger:set_module_level(?MODULE,bad),
+ {error,{not_a_list_of_modules,{bad}}} =
+ logger:set_module_level({bad},warning),
+ {error,{not_a_list_of_modules,[{bad}]}} =
+ logger:set_module_level([{bad}],warning),
+ ok = logger:set_module_level(?MODULE,warning),
+ [{?MODULE,warning}] = logger:get_module_level([?MODULE,other]),
+ [{?MODULE,warning}] = logger:get_module_level(?MODULE),
+ [{?MODULE,warning}] = logger:get_module_level(),
+ logger:notice(?map_rep,?MY_LOC(0)),
+ ok = check_no_log(),
+ logger:warning(M1=?map_rep,?MY_LOC(0)),
+ ok = check_logged(warning,M1,?MY_LOC(1)),
+ ok = logger:set_module_level(?MODULE,notice),
+ [{?MODULE,notice}] = logger:get_module_level([?MODULE,other]),
+ [{?MODULE,notice}] = logger:get_module_level(?MODULE),
+ [{?MODULE,notice}] = logger:get_module_level(),
+ logger:notice(M2=?map_rep,?MY_LOC(0)),
+ ok = check_logged(notice,M2,?MY_LOC(1)),
+
+ {error,{not_a_list_of_modules,{bad}}} = logger:unset_module_level({bad}),
+ {error,{not_a_list_of_modules,[{bad}]}} = logger:unset_module_level([{bad}]),
+ ok = logger:unset_module_level(?MODULE),
+ [] = logger:get_module_level([?MODULE,other]),
+ [] = logger:get_module_level(?MODULE),
+ [] = logger:get_module_level(),
+
+ ok = logger:set_module_level([m1,m2,m3],notice),
+ [{m1,notice},{m2,notice},{m3,notice}] = logger:get_module_level(),
+ ok = logger:unset_module_level(m2),
+ [{m1,notice},{m3,notice}] = logger:get_module_level(),
+ ok = logger:unset_module_level(),
+ [] = logger:get_module_level(),
+
+ ok.
+
+set_module_level(cleanup,_Config) ->
+ logger:remove_handler(h1),
+ logger:unset_module_level(?MODULE),
+ ok.
+
+set_application_level(_Config) ->
+
+ {error,{not_loaded,mnesia}} = logger:set_application_level(mnesia, warning),
+ {error,{not_loaded,mnesia}} = logger:unset_application_level(mnesia),
+
+ case application:load(mnesia) of
+ ok ->
+ {ok, Modules} = application:get_key(mnesia, modules),
+ [] = logger:get_module_level(Modules),
+
+ {error,{invalid_level,warn}} =
+ logger:set_application_level(mnesia, warn),
+
+ ok = logger:set_application_level(mnesia, debug),
+ DebugModules = lists:sort([{M,debug} || M <- Modules]),
+ DebugModules = lists:sort(logger:get_module_level(Modules)),
+
+ ok = logger:set_application_level(mnesia, warning),
+
+ WarnModules = lists:sort([{M,warning} || M <- Modules]),
+ WarnModules = lists:sort(logger:get_module_level(Modules)),
+
+ ok = logger:unset_application_level(mnesia),
+ [] = logger:get_module_level(Modules);
+ {error,{"no such file or directory","mnesia.app"}} ->
+ {skip, "Cannot load mnesia, does not exist"}
+ end.
+
+set_application_level(cleanup,_Config) ->
+ _ = logger:unset_application_level(mnesia),
+ _ = application:unload(mnesia),
+ ok.
+
+cache_module_level(_Config) ->
+ ok = logger:unset_module_level(?MODULE),
+ [] = ets:lookup(?LOGGER_TABLE,?MODULE), %dirty - add API in logger_config?
+ ?LOG_NOTICE(?map_rep),
+ %% Caching is done asynchronously, so wait a bit for the update
+ timer:sleep(100),
+ [_] = ets:lookup(?LOGGER_TABLE,?MODULE), %dirty - add API in logger_config?
+ ok = logger:unset_module_level(?MODULE),
+ [] = ets:lookup(?LOGGER_TABLE,?MODULE), %dirty - add API in logger_config?
+ ok.
+
+cache_module_level(cleanup,_Config) ->
+ logger:unset_module_level(?MODULE),
+ ok.
+
+format_report(_Config) ->
+ {"~ts",["string"]} = logger:format_report("string"),
+ {"~tp",[term]} = logger:format_report(term),
+ {"~tp",[[]]} = logger:format_report([]),
+ {" ~tp: ~tp",[key,value]} = logger:format_report([{key,value}]),
+ KeyVals = [{key1,value1},{key2,"value2"},{key3,[]}],
+ KeyValRes =
+ {" ~tp: ~tp\n ~tp: ~ts\n ~tp: ~tp",
+ [key1,value1,key2,"value2",key3,[]]} =
+ logger:format_report(KeyVals),
+ KeyValRes = logger:format_report(maps:from_list(KeyVals)),
+ KeyValRes = logger:format_otp_report(#{label=>{?MODULE,test},report=>KeyVals}),
+ {" ~tp: ~tp\n ~tp: ~tp",
+ [label,{?MODULE,test},report,KeyVals]} =
+ logger:format_report(#{label=>{?MODULE,test},report=>KeyVals}),
+
+ {" ~tp: ~tp\n ~tp",[key1,value1,term]} =
+ logger:format_report([{key1,value1},term]),
+
+ {" ~tp: ~tp\n ~tp",[key1,value1,[]]} =
+ logger:format_report([{key1,value1},[]]),
+
+ {"~tp",[[]]} = logger:format_report([[],[],[]]),
+
+ ok.
+
+filter_failed(_Config) ->
+ ok = logger:add_handler(h1,?MODULE,#{level=>notice,filter_default=>log}),
+
+ %% Logger filters
+ {error,{invalid_filter,_}} =
+ logger:add_primary_filter(lf,{fun(_) -> ok end,args}),
+ ok = logger:add_primary_filter(lf,
+ {fun(_,_) ->
+ erlang:error({badmatch,b})
+ end,
+ args}),
+ #{filters:=[_]} = logger:get_primary_config(),
+ ok = logger:notice(M1=?map_rep),
+ ok = check_logged(notice,M1,#{}),
+ {error,{not_found,lf}} = logger:remove_primary_filter(lf),
+
+ ok = logger:add_primary_filter(lf,{fun(_,_) -> faulty_return end,args}),
+ #{filters:=[_]} = logger:get_primary_config(),
+ ok = logger:notice(M2=?map_rep),
+ ok = check_logged(notice,M2,#{}),
+ {error,{not_found,lf}} = logger:remove_primary_filter(lf),
+
+ %% Handler filters
+ {error,{not_found,h0}} =
+ logger:add_handler_filter(h0,hf,{fun(_,_) -> ignore end,args}),
+ {error,{not_found,h0}} = logger:remove_handler_filter(h0,hf),
+ {error,{invalid_filter,_}} =
+ logger:add_handler_filter(h1,hf,{fun(_) -> ok end,args}),
+ ok = logger:add_handler_filter(h1,hf,
+ {fun(_,_) ->
+ erlang:error({badmatch,b})
+ end,
+ args}),
+ {ok,#{filters:=[_]}} = logger:get_handler_config(h1),
+ ok = logger:notice(M3=?map_rep),
+ ok = check_logged(notice,M3,#{}),
+ {error,{not_found,hf}} = logger:remove_handler_filter(h1,hf),
+
+ ok = logger:add_handler_filter(h1,hf,{fun(_,_) -> faulty_return end,args}),
+ {ok,#{filters:=[_]}} = logger:get_handler_config(h1),
+ ok = logger:notice(M4=?map_rep),
+ ok = check_logged(notice,M4,#{}),
+ {error,{not_found,hf}} = logger:remove_handler_filter(h1,hf),
+
+ ok.
+
+filter_failed(cleanup,_Config) ->
+ logger:remove_handler(h1),
+ ok.
+
+handler_failed(_Config) ->
+ register(callback_receiver,self()),
+ {error,{invalid_id,1}} = logger:add_handler(1,?MODULE,#{}),
+ {error,{invalid_module,"nomodule"}} = logger:add_handler(h1,"nomodule",#{}),
+ {error,{invalid_config,bad}} = logger:add_handler(h1,?MODULE,bad),
+ {error,{invalid_filters,false}} =
+ logger:add_handler(h1,?MODULE,#{filters=>false}),
+ {error,{invalid_filter_default,true}} =
+ logger:add_handler(h1,?MODULE,#{filter_default=>true}),
+ {error,{invalid_formatter,[]}} =
+ logger:add_handler(h1,?MODULE,#{formatter=>[]}),
+ {error,{invalid_handler,_}} = logger:add_handler(h1,nomodule,#{filter_default=>log}),
+ logger:notice(?map_rep),
+ check_no_log(),
+ H1 = logger:get_handler_config(),
+ false = lists:search(fun(#{id:=h1}) -> true; (_) -> false end,H1),
+ {error,{not_found,h1}} = logger:remove_handler(h1),
+
+ ok = logger:add_handler(h2,?MODULE,
+ #{filter_default => log,
+ log_call => fun() ->
+ erlang:error({badmatch,b})
+ end}),
+ {error,{already_exist,h2}} = logger:add_handler(h2,othermodule,#{}),
+ [add] = test_server:messages_get(),
+
+ logger:notice(?map_rep),
+ [remove] = test_server:messages_get(),
+ H2 = logger:get_handler_config(),
+ false = lists:search(fun(#{id:=h2}) -> true; (_) -> false end,H2),
+ {error,{not_found,h2}} = logger:remove_handler(h2),
+
+ CallAddHandler = fun() -> logger:add_handler(h2,?MODULE,#{}) end,
+ CrashHandler = fun() -> erlang:error({badmatch,b}) end,
+ KillHandler = fun() -> exit(self(), die) end,
+
+ {error,{handler_not_added,{attempting_syncronous_call_to_self,_}}} =
+ logger:add_handler(h1,?MODULE,#{add_call=>CallAddHandler}),
+ {error,{handler_not_added,{callback_crashed,_}}} =
+ logger:add_handler(h1,?MODULE,#{add_call=>CrashHandler}),
+ {error,{handler_not_added,{logger_process_exited,_,die}}} =
+ logger:add_handler(h1,?MODULE,#{add_call=>KillHandler}),
+
+ check_no_log(),
+ ok = logger:add_handler(h1,?MODULE,#{}),
+ {error,{attempting_syncronous_call_to_self,_}} =
+ logger:set_handler_config(h1,#{conf_call=>CallAddHandler}),
+ {error,{callback_crashed,_}} =
+ logger:set_handler_config(h1,#{conf_call=>CrashHandler}),
+ {error,{logger_process_exited,_,die}} =
+ logger:set_handler_config(h1,#{conf_call=>KillHandler}),
+
+ {error,{attempting_syncronous_call_to_self,_}} =
+ logger:set_handler_config(h1,conf_call,CallAddHandler),
+ {error,{callback_crashed,_}} =
+ logger:set_handler_config(h1,conf_call,CrashHandler),
+ {error,{logger_process_exited,_,die}} =
+ logger:set_handler_config(h1,conf_call,KillHandler),
+
+ ok = logger:remove_handler(h1),
+ [add,remove] = test_server:messages_get(),
+
+ check_no_log(),
+ ok = logger:add_handler(h1,?MODULE,#{rem_call=>CallAddHandler}),
+ ok = logger:remove_handler(h1),
+ ok = logger:add_handler(h1,?MODULE,#{rem_call=>CrashHandler}),
+ ok = logger:remove_handler(h1),
+ ok = logger:add_handler(h1,?MODULE,#{rem_call=>KillHandler}),
+ ok = logger:remove_handler(h1),
+ [add,add,add] = test_server:messages_get(),
+
+ ok.
+
+handler_failed(cleanup,_Config) ->
+ logger:remove_handler(h1),
+ logger:remove_handler(h2),
+ ok.
+
+config_sanity_check(_Config) ->
+ %% Primary config
+ {error,{invalid_config,bad}} = logger:set_primary_config(bad),
+ {error,{invalid_filter_default,bad}} =
+ logger:set_primary_config(filter_default,bad),
+ {error,{invalid_level,bad}} = logger:set_primary_config(level,bad),
+ {error,{invalid_filters,bad}} = logger:set_primary_config(filters,bad),
+ {error,{invalid_filter,bad}} = logger:set_primary_config(filters,[bad]),
+ {error,{invalid_filter,{_,_}}} =
+ logger:set_primary_config(filters,[{id,bad}]),
+ {error,{invalid_filter,{_,{_,_}}}} =
+ logger:set_primary_config(filters,[{id,{bad,args}}]),
+ {error,{invalid_filter,{_,{_,_}}}} =
+ logger:set_primary_config(filters,[{id,{fun() -> ok end,args}}]),
+ {error,{invalid_primary_config,{bad,bad}}} =
+ logger:set_primary_config(bad,bad),
+
+ %% Handler config
+ {error,{not_found,h1}} = logger:set_handler_config(h1,a,b),
+ ok = logger:add_handler(h1,?MODULE,#{}),
+ {error,{invalid_filter_default,bad}} =
+ logger:set_handler_config(h1,filter_default,bad),
+ {error,{invalid_level,bad}} = logger:set_handler_config(h1,level,bad),
+ {error,{invalid_filters,bad}} = logger:set_handler_config(h1,filters,bad),
+ {error,{invalid_filter,bad}} = logger:set_handler_config(h1,filters,[bad]),
+ {error,{invalid_filter,{_,_}}} =
+ logger:set_handler_config(h1,filters,[{id,bad}]),
+ {error,{invalid_filter,{_,{_,_}}}} =
+ logger:set_handler_config(h1,filters,[{id,{bad,args}}]),
+ {error,{invalid_filter,{_,{_,_}}}} =
+ logger:set_handler_config(h1,filters,[{id,{fun() -> ok end,args}}]),
+ {error,{invalid_formatter,bad}} =
+ logger:set_handler_config(h1,formatter,bad),
+ {error,{invalid_module,{bad}}} =
+ logger:set_handler_config(h1,formatter,{{bad},cfg}),
+ {error,{invalid_formatter_config,logger_formatter,bad}} =
+ logger:set_handler_config(h1,formatter,{logger_formatter,bad}),
+ {error,{invalid_formatter_config,logger_formatter,{bad,bad}}} =
+ logger:set_handler_config(h1,formatter,{logger_formatter,#{bad=>bad}}),
+ {error,{invalid_formatter_template,logger_formatter,bad}} =
+ logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{template=>bad}}),
+ {error,{invalid_formatter_template,logger_formatter,[1]}} =
+ logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{template=>[1]}}),
+ ok = logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{template=>[]}}),
+ {error,{invalid_formatter_config,logger_formatter,{single_line,bad}}} =
+ logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{single_line=>bad}}),
+ ok = logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{single_line=>true}}),
+ {error,{invalid_formatter_config,logger_formatter,{legacy_header,bad}}} =
+ logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{legacy_header=>bad}}),
+ ok = logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{legacy_header=>true}}),
+ {error,{invalid_formatter_config,logger_formatter,{report_cb,bad}}} =
+ logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{report_cb=>bad}}),
+ ok = logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{report_cb=>fun(R) ->
+ {"~p",[R]}
+ end}}),
+ {error,{invalid_formatter_config,logger_formatter,{chars_limit,bad}}} =
+ logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{chars_limit=>bad}}),
+ ok = logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{chars_limit=>unlimited}}),
+ ok = logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{chars_limit=>4}}),
+ {error,{invalid_formatter_config,logger_formatter,{depth,bad}}} =
+ logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{depth=>bad}}),
+ ok = logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{depth=>unlimited}}),
+ ok = logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{depth=>4}}),
+ {error,{invalid_formatter_config,logger_formatter,{max_size,bad}}} =
+ logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{max_size=>bad}}),
+ ok = logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{max_size=>unlimited}}),
+ ok = logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{max_size=>4}}),
+ ok = logger:set_handler_config(h1,formatter,{module,config}),
+ {error,{callback_crashed,{error,{badmatch,3},[{?MODULE,check_config,1,_}]}}} =
+ logger:set_handler_config(h1,formatter,{?MODULE,crash}),
+ ok = logger:set_handler_config(h1,custom,custom),
+
+ %% Old utc parameter is no longer allowed (replaced by time_offset)
+ {error,{invalid_formatter_config,logger_formatter,{utc,true}}} =
+ logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{utc=>true}}),
+ {error,{invalid_formatter_config,logger_formatter,{time_offset,bad}}} =
+ logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{time_offset=>bad}}),
+ ok = logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{time_offset=>0}}),
+ ok = logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{time_offset=>""}}),
+ ok = logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{time_offset=>"Z"}}),
+ ok = logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{time_offset=>"z"}}),
+ ok = logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{time_offset=>"-0:0"}}),
+ ok = logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{time_offset=>"+10:13"}}),
+
+ {error,{invalid_formatter_config,logger_formatter,{time_offset,"+0"}}} =
+ logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{time_offset=>"+0"}}),
+
+ {error,{invalid_formatter_config,logger_formatter,{time_designator,bad}}} =
+ logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{time_designator=>bad}}),
+ {error,{invalid_formatter_config,logger_formatter,{time_designator,"s"}}} =
+ logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{time_designator=>"s"}}),
+ {error,{invalid_formatter_config,logger_formatter,{time_designator,0}}} =
+ logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{time_designator=>0}}),
+ ok = logger:set_handler_config(h1,formatter,{logger_formatter,
+ #{time_designator=>$\s}}),
+ ok.
+
+config_sanity_check(cleanup,_Config) ->
+ logger:remove_handler(h1),
+ ok.
+
+log_failed(_Config) ->
+ ok = logger:add_handler(h1,?MODULE,#{level=>notice,filter_default=>log}),
+ {error,function_clause} = ?TRY(logger:log(bad,?map_rep)),
+ {error,function_clause} = ?TRY(logger:log(notice,?map_rep,bad)),
+ {error,function_clause} = ?TRY(logger:log(notice,fun() -> ?map_rep end,bad)),
+ {error,function_clause} = ?TRY(logger:log(notice,fun() -> ?map_rep end,bad,#{})),
+ {error,function_clause} = ?TRY(logger:log(notice,bad,bad,bad)),
+ {error,function_clause} = ?TRY(logger:log(notice,bad,bad,#{})),
+ check_no_log(),
+ ok = logger:log(notice,M1=?str,#{}),
+ check_logged(notice,M1,#{}),
+ ok = logger:log(notice,M2=?map_rep,#{}),
+ check_logged(notice,M2,#{}),
+ ok = logger:log(notice,M3=?keyval_rep,#{}),
+ check_logged(notice,M3,#{}),
+
+ %% Should we check report input more thoroughly?
+ ok = logger:log(notice,M4=?keyval_rep++[other,stuff,in,list],#{}),
+ check_logged(notice,M4,#{}),
+
+ %% This might break a handler since it is assumed to be a format
+ %% string and args, so it depends how the handler protects itself
+ %% against something like io_lib:format("ok","ok")
+ ok = logger:log(notice,"ok","ok",#{}),
+ check_logged(notice,"ok","ok",#{}),
+
+ ok.
+
+log_failed(cleanup,_Config) ->
+ logger:remove_handler(h1),
+ ok.
+
+emulator(_Config) ->
+ ok = logger:add_handler(h1,?MODULE,#{level=>notice,filter_default=>log,
+ tc_proc=>self()}),
+ Msg = "Error in process ~p on node ~p with exit value:~n~p~n",
+ Error = {badmatch,4},
+ Stack = [{module, function, 2, []}],
+ Pid = spawn(?MODULE, generate_error, [Error, Stack]),
+ check_logged(error, Msg, [Pid, node(), {Error, Stack}],
+ #{gl=>group_leader(),
+ error_logger=>#{tag=>error,emulator=>true}}),
+ ok.
+
+emulator(cleanup, _Config) ->
+ logger:remove_handler(h1),
+ ok.
+
+generate_error(Error, Stack) ->
+ erlang:raise(error, Error, Stack).
+
+via_logger_process(Config) ->
+ ok = logger:add_handler(h1,?MODULE,#{level=>notice,filter_default=>log,
+ tc_proc=>self()}),
+
+ %% Explicitly send a message to the logger process
+ %% This is used by code_server, erl_prim_loader, init, prim_file, ...
+ Msg = ?str,
+ logger ! {log,error,Msg,[],#{}},
+ check_logged(error, Msg, [], #{}),
+
+ case os:type() of
+ {win32,_} ->
+ %% Skip this part on windows - cant change file mode"
+ ok;
+ _ ->
+ %% This should trigger the same thing from erl_prim_loader
+ Dir = filename:join(?config(priv_dir,Config),"dummydir"),
+ ok = file:make_dir(Dir),
+ ok = file:change_mode(Dir,8#0222),
+ error = erl_prim_loader:list_dir(Dir),
+ check_logged(error,
+ #{report=>"File operation error: eacces. Target: " ++
+ Dir ++". Function: list_dir. "},
+ #{pid=>self(),
+ gl=>group_leader(),
+ error_logger=>#{tag=>error_report,
+ type=>std_error}}),
+ ok
+ end.
+
+via_logger_process(cleanup, Config) ->
+ Dir = filename:join(?config(priv_dir,Config),"dummydir"),
+ _ = file:change_mode(Dir,8#0664),
+ _ = file:del_dir(Dir),
+ logger:remove_handler(h1),
+ ok.
+
+other_node(_Config) ->
+ ok = logger:add_handler(h1,?MODULE,#{level=>notice,filter_default=>log,
+ tc_proc=>self()}),
+ {ok,Node} = test_server:start_node(?FUNCTION_NAME,slave,[]),
+ rpc:call(Node,logger,error,[Msg=?str,#{}]),
+ check_logged(error,Msg,#{}),
+ ok.
+
+other_node(cleanup,_Config) ->
+ Nodes = nodes(),
+ [test_server:stop_node(Node) || Node <- Nodes],
+ logger:remove_handler(h1),
+ ok.
+
+compare_levels(_Config) ->
+ Levels = [emergency,alert,critical,error,warning,notice,info,debug],
+ ok = compare(Levels),
+ {error,badarg} = ?TRY(logger:compare_levels(bad,bad)),
+ {error,badarg} = ?TRY(logger:compare_levels({bad},notice)),
+ {error,badarg} = ?TRY(logger:compare_levels(notice,"bad")),
+ ok.
+
+compare([L|Rest]) ->
+ eq = logger:compare_levels(L,L),
+ [gt = logger:compare_levels(L,L1) || L1 <- Rest],
+ [lt = logger:compare_levels(L1,L) || L1 <- Rest],
+ compare(Rest);
+compare([]) ->
+ ok.
+
+process_metadata(_Config) ->
+ undefined = logger:get_process_metadata(),
+ {error,badarg} = ?TRY(logger:set_process_metadata(bad)),
+ ok = logger:add_handler(h1,?MODULE,#{level=>notice,filter_default=>log}),
+ Time = erlang:system_time(microsecond),
+ ProcMeta = #{time=>Time,line=>0,custom=>proc},
+ ok = logger:set_process_metadata(ProcMeta),
+ S1 = ?str,
+ ?LOG_NOTICE(S1,#{custom=>macro}),
+ check_logged(notice,S1,#{time=>Time,line=>0,custom=>macro}),
+
+ Time2 = erlang:system_time(microsecond),
+ S2 = ?str,
+ ?LOG_NOTICE(S2,#{time=>Time2,line=>1,custom=>macro}),
+ check_logged(notice,S2,#{time=>Time2,line=>1,custom=>macro}),
+
+ logger:notice(S3=?str,#{custom=>func}),
+ check_logged(notice,S3,#{time=>Time,line=>0,custom=>func}),
+
+ ProcMeta = logger:get_process_metadata(),
+ ok = logger:update_process_metadata(#{custom=>changed,custom2=>added}),
+ Expected = ProcMeta#{custom:=changed,custom2=>added},
+ Expected = logger:get_process_metadata(),
+ ok = logger:unset_process_metadata(),
+ undefined = logger:get_process_metadata(),
+
+ ok = logger:update_process_metadata(#{custom=>added_again}),
+ {error,badarg} = ?TRY(logger:update_process_metadata(bad)),
+ #{custom:=added_again} = logger:get_process_metadata(),
+
+ ok.
+
+process_metadata(cleanup,_Config) ->
+ logger:remove_handler(h1),
+ ok.
+
+app_config(Config) ->
+ %% Start a node with default configuration
+ {ok,_,Node} = logger_test_lib:setup(Config,[]),
+
+ App1Name = app1,
+ App1 = {application, App1Name,
+ [{description, "Test of app with logger config"},
+ {applications, [kernel]}]},
+ ok = rpc:call(Node,application,load,[App1]),
+ ok = rpc:call(Node,application,set_env,
+ [App1Name,logger,[{handler,default,logger_std_h,#{}}]]),
+
+ %% Try to add an own default handler
+ {error,{bad_config,{handler,{app1,{already_exist,default}}}}} =
+ rpc:call(Node,logger,add_handlers,[App1Name]),
+
+ %% Add a different handler
+ ok = rpc:call(Node,application,set_env,[App1Name,logger,
+ [{handler,myh,logger_std_h,#{}}]]),
+ ok = rpc:call(Node,logger,add_handlers,[App1Name]),
+
+ {ok,#{filters:=DF}} = rpc:call(Node,logger,get_handler_config,[default]),
+ {ok,#{filters:=[]}} = rpc:call(Node,logger,get_handler_config,[myh]),
+
+ true = test_server:stop_node(Node),
+
+ %% Start a node with no default handler, then add an own default handler
+ {ok,#{handlers:=[#{id:=simple}]},Node} =
+ logger_test_lib:setup(Config,[{logger,[{handler,default,undefined}]}]),
+
+ ok = rpc:call(Node,application,load,[App1]),
+ ok = rpc:call(Node,application,set_env,
+ [App1Name,logger,[{handler,default,logger_std_h,#{}}]]),
+ ok = rpc:call(Node,logger,add_handlers,[App1Name]),
+
+ #{handlers:=[#{id:=default,filters:=DF}]} =
+ rpc:call(Node,logger,get_config,[]),
+
+ true = test_server:stop_node(Node),
+
+ %% Start a silent node, then add an own default handler
+ {ok,#{handlers:=[]},Node} =
+ logger_test_lib:setup(Config,[{error_logger,silent}]),
+
+ {error,{bad_config,{handler,[{some,bad,config}]}}} =
+ rpc:call(Node,logger,add_handlers,[[{some,bad,config}]]),
+ ok = rpc:call(Node,logger,add_handlers,
+ [[{handler,default,logger_std_h,#{}}]]),
+
+ #{handlers:=[#{id:=default,filters:=DF}]} =
+ rpc:call(Node,logger,get_config,[]),
+
+ ok.
+
+%% This test case is maintly to see code coverage. Note that
+%% logger_env_var_SUITE tests a lot of the same, and checks the
+%% functionality more thoroughly, but since it all happens at node
+%% start, it is not possible to see code coverage in that test.
+kernel_config(Config) ->
+ %% Start a node with simple handler only, then simulate kernel
+ %% start by calling internally exported
+ %% internal_init_logger(). This is to test all variants of kernel
+ %% config, including bad config, and see the code coverage.
+ {ok,#{handlers:=[#{id:=simple,filters:=DF}]}=LC,Node} =
+ logger_test_lib:setup(Config,[{error_logger,false}]),
+
+ %% Same once more, to get coverage
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ LC = rpc:call(Node,logger,get_config,[]),
+
+ %% This shall mean the same as above, but using 'logger' parameter
+ %% instead of 'error_logger'
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,[{handler,default,undefined}]]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ LC = rpc:call(Node,logger,get_config,[]),
+
+ %% Silent
+ ok = rpc:call(Node,application,unset_env,[kernel,logger]),
+ ok = rpc:call(Node,application,set_env,[kernel,error_logger,silent]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% Default
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ ok = rpc:call(Node,application,unset_env,[kernel,logger]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[#{id:=default,filters:=DF,config:=#{type:=standard_io}}],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% error_logger=tty (same as default)
+ ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again
+ ok = rpc:call(Node,application,set_env,[kernel,error_logger,tty]),
+ ok = rpc:call(Node,application,unset_env,[kernel,logger]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[#{id:=default,filters:=DF,config:=#{type:=standard_io}}],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% error_logger={file,File}
+ ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again
+ F = filename:join(?config(priv_dir,Config),
+ atom_to_list(?FUNCTION_NAME)++".log"),
+ ok = rpc:call(Node,application,set_env,[kernel,error_logger,{file,F}]),
+ ok = rpc:call(Node,application,unset_env,[kernel,logger]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[#{id:=default,filters:=DF,config:=#{type:={file,F}}}],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% Same, but using 'logger' parameter instead of 'error_logger'
+ ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ ok = rpc:call(Node,application,set_env,[kernel,logger,
+ [{handler,default,logger_std_h,
+ #{config=>#{type=>{file,F}}}}]]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[#{id:=default,filters:=DF,config:=#{type:={file,F}}}],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% Same, but with type={file,File,Modes}
+ ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ M = [raw,write,delayed_write],
+ ok = rpc:call(Node,application,set_env,[kernel,logger,
+ [{handler,default,logger_std_h,
+ #{config=>#{type=>{file,F,M}}}}]]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[#{id:=default,filters:=DF,config:=#{type:={file,F,M}}}],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% Same, but with disk_log handler
+ ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ M = [raw,write,delayed_write],
+ ok = rpc:call(Node,application,set_env,[kernel,logger,
+ [{handler,default,logger_disk_log_h,
+ #{config=>#{file=>F}}}]]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[#{id:=default,filters:=DF,config:=#{file:=F}}],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% Set primary filters and module level. No default handler.
+ ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,[{handler,default,undefined},
+ {filters,stop,[{f1,{fun(_,_) -> log end,ok}}]},
+ {module_level,debug,[?MODULE]}]]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=stop,filters:=[_]},
+ handlers:=[],
+ module_levels:=[{?MODULE,debug}]} = rpc:call(Node,logger,get_config,[]),
+
+ %% Bad config
+ ok = rpc:call(Node,application,unset_env,[kernel,logger]),
+
+ ok = rpc:call(Node,application,set_env,[kernel,error_logger,bad]),
+ {error,{bad_config,{kernel,{error_logger,bad}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ ok = rpc:call(Node,application,set_env,[kernel,logger_level,bad]),
+ {error,{bad_config,{kernel,{logger_level,bad}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok = rpc:call(Node,application,unset_env,[kernel,logger_level]),
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,[{filters,stop,[bad]}]]),
+ {error,{bad_config,{kernel,{invalid_filters,[bad]}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,[{filters,stop,[bad]}]]),
+ {error,{bad_config,{kernel,{invalid_filters,[bad]}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,[{filters,stop,[{f1,bad}]}]]),
+ {error,{bad_config,{kernel,{invalid_filter,{f1,bad}}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,MF=[{filters,stop,[]},{filters,log,[]}]]),
+ {error,{bad_config,{kernel,{multiple_filters,MF}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,[{module_level,bad,[?MODULE]}]]),
+ {error,{bad_config,{kernel,{invalid_level,bad}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok.
+
+%%%-----------------------------------------------------------------
+%%% Internal
+check_logged(Level,Format,Args,Meta) ->
+ do_check_logged(Level,{Format,Args},Meta).
+
+check_logged(Level,Msg,Meta) when ?IS_REPORT(Msg) ->
+ do_check_logged(Level,{report,Msg},Meta);
+check_logged(Level,Msg,Meta) when ?IS_STRING(Msg) ->
+ do_check_logged(Level,{string,Msg},Meta).
+
+do_check_logged(Level,Msg0,Meta0) ->
+ receive
+ {#{level:=Level,msg:=Msg,meta:=Meta},_} ->
+ check_msg(Msg0,Msg),
+ check_maps(Meta0,Meta,meta)
+ after 500 ->
+ ct:fail({timeout,no_log,process_info(self(),messages)})
+ end.
+
+check_no_log() ->
+ receive
+ X -> ct:fail({got_unexpected_log,X})
+ after 500 ->
+ ok
+ end.
+
+check_msg(Msg,Msg) ->
+ ok;
+check_msg({report,Expected},{report,Got}) when is_map(Expected), is_map(Got) ->
+ check_maps(Expected,Got,msg);
+check_msg(Expected,Got) ->
+ ct:fail({unexpected,msg,Expected,Got}).
+
+check_maps(Expected,Got,What) ->
+ case maps:merge(Got,Expected) of
+ Got ->
+ ok;
+ _ ->
+ ct:fail({unexpected,What,Expected,Got})
+ end.
+
+%% Handler
+adding_handler(#{add_call:=Fun}) ->
+ Fun();
+adding_handler(Config) ->
+ maybe_send(add),
+ {ok,Config}.
+
+removing_handler(#{rem_call:=Fun}) ->
+ Fun();
+removing_handler(_Config) ->
+ maybe_send(remove),
+ ok.
+changing_config(_Old,#{conf_call:=Fun}) ->
+ Fun();
+changing_config(_Old,Config) ->
+ maybe_send(changing_config),
+ {ok,Config}.
+
+maybe_send(Msg) ->
+ case whereis(callback_receiver) of
+ undefined -> ok;
+ Pid -> Pid ! Msg
+ end.
+
+log(_Log,#{log_call:=Fun}) ->
+ Fun();
+log(Log,Config) ->
+ TcProc = maps:get(tc_proc,Config,self()),
+ TcProc ! {Log,Config},
+ ok.
+
+test_api(Level) ->
+ logger:Level(#{Level=>rep}),
+ ok = check_logged(Level,#{Level=>rep},#{}),
+ logger:Level(#{Level=>rep},#{my=>meta}),
+ ok = check_logged(Level,#{Level=>rep},#{my=>meta}),
+ logger:Level("~w: ~w",[Level,fa]),
+ ok = check_logged(Level,"~w: ~w",[Level,fa],#{}),
+ logger:Level("~w: ~w ~w",[Level,fa,meta],#{my=>meta}),
+ ok = check_logged(Level,"~w: ~w ~w",[Level,fa,meta],#{my=>meta}),
+ logger:Level(fun(x) -> {"~w: ~w ~w",[Level,fun_to_fa,meta]} end,x,
+ #{my=>meta}),
+ ok = check_logged(Level,"~w: ~w ~w",[Level,fun_to_fa,meta],#{my=>meta}),
+ logger:Level(fun(x) -> #{Level=>fun_to_r,meta=>true} end,x,
+ #{my=>meta}),
+ ok = check_logged(Level,#{Level=>fun_to_r,meta=>true},#{my=>meta}),
+ logger:Level(fun(x) -> <<"fun_to_s">> end,x,#{}),
+ ok = check_logged(Level,<<"fun_to_s">>,#{}),
+ logger:Level(F1=fun(x) -> {fun_to_bad} end,x,#{}),
+ ok = check_logged(Level,"LAZY_FUN ERROR: ~tp; Returned: ~tp",
+ [{F1,x},{fun_to_bad}],#{}),
+ logger:Level(F2=fun(x) -> erlang:error(fun_that_crashes) end,x,#{}),
+ ok = check_logged(Level,"LAZY_FUN CRASH: ~tp; Reason: ~tp",
+ [{F2,x},{error,fun_that_crashes}],#{}),
+ ok.
+
+test_log_function(Level) ->
+ logger:log(Level,#{Level=>rep}),
+ ok = check_logged(Level,#{Level=>rep},#{}),
+ logger:log(Level,#{Level=>rep},#{my=>meta}),
+ ok = check_logged(Level,#{Level=>rep},#{my=>meta}),
+ logger:log(Level,"~w: ~w",[Level,fa]),
+ ok = check_logged(Level,"~w: ~w",[Level,fa],#{}),
+ logger:log(Level,"~w: ~w ~w",[Level,fa,meta],#{my=>meta}),
+ ok = check_logged(Level,"~w: ~w ~w",[Level,fa,meta],#{my=>meta}),
+ logger:log(Level,fun(x) -> {"~w: ~w ~w",[Level,fun_to_fa,meta]} end,
+ x, #{my=>meta}),
+ ok = check_logged(Level,"~w: ~w ~w",[Level,fun_to_fa,meta],#{my=>meta}),
+ logger:log(Level,fun(x) -> #{Level=>fun_to_r,meta=>true} end,
+ x, #{my=>meta}),
+ ok = check_logged(Level,#{Level=>fun_to_r,meta=>true},#{my=>meta}),
+ logger:log(Level,fun(x) -> <<"fun_to_s">> end,x,#{}),
+ ok = check_logged(Level,<<"fun_to_s">>,#{}),
+ logger:log(Level,F1=fun(x) -> {fun_to_bad} end,x,#{}),
+ ok = check_logged(Level,"LAZY_FUN ERROR: ~tp; Returned: ~tp",
+ [{F1,x},{fun_to_bad}],#{}),
+ logger:log(Level,F2=fun(x) -> erlang:error(fun_that_crashes) end,x,#{}),
+ ok = check_logged(Level,"LAZY_FUN CRASH: ~tp; Reason: ~tp",
+ [{F2,x},{error,fun_that_crashes}],#{}),
+ ok.
+
+test_macros(emergency=Level) ->
+ ?LOG_EMERGENCY(#{Level=>rep}),
+ ok = check_logged(Level,#{Level=>rep},?MY_LOC(1)),
+ ?LOG_EMERGENCY(#{Level=>rep},#{my=>meta}),
+ ok = check_logged(Level,#{Level=>rep},(?MY_LOC(1))#{my=>meta}),
+ ?LOG_EMERGENCY("~w: ~w",[Level,fa]),
+ ok = check_logged(Level,"~w: ~w",[Level,fa],?MY_LOC(1)),
+ ?LOG_EMERGENCY("~w: ~w ~w",[Level,fa,meta],#{my=>meta}),
+ ok = check_logged(Level,"~w: ~w ~w",[Level,fa,meta],(?MY_LOC(1))#{my=>meta}),
+ ?LOG_EMERGENCY(fun(x) -> {"~w: ~w ~w",[Level,fun_to_fa,meta]} end,
+ x, #{my=>meta}),
+ ok = check_logged(Level,"~w: ~w ~w",[Level,fun_to_fa,meta],
+ (?MY_LOC(3))#{my=>meta}),
+ ?LOG_EMERGENCY(fun(x) -> #{Level=>fun_to_r,meta=>true} end, x, #{my=>meta}),
+ ok = check_logged(Level,#{Level=>fun_to_r,meta=>true},
+ (?MY_LOC(2))#{my=>meta}),
+ ?LOG_EMERGENCY(fun(x) -> <<"fun_to_s">> end,x,#{}),
+ ok = check_logged(Level,<<"fun_to_s">>,?MY_LOC(1)),
+ F1=fun(x) -> {fun_to_bad} end,
+ ?LOG_EMERGENCY(F1,x,#{}),
+ ok = check_logged(Level,"LAZY_FUN ERROR: ~tp; Returned: ~tp",
+ [{F1,x},{fun_to_bad}],#{}),
+ F2=fun(x) -> erlang:error(fun_that_crashes) end,
+ ?LOG_EMERGENCY(F2,x,#{}),
+ ok = check_logged(Level,"LAZY_FUN CRASH: ~tp; Reason: ~tp",
+ [{F2,x},{error,fun_that_crashes}],#{}),
+ ok.
+
+test_log_macro(Level) ->
+ ?LOG(Level,#{Level=>rep}),
+ ok = check_logged(Level,#{Level=>rep},?MY_LOC(1)),
+ ?LOG(Level,#{Level=>rep},#{my=>meta}),
+ ok = check_logged(Level,#{Level=>rep},(?MY_LOC(1))#{my=>meta}),
+ ?LOG(Level,"~w: ~w",[Level,fa]),
+ ok = check_logged(Level,"~w: ~w",[Level,fa],?MY_LOC(1)),
+ ?LOG(Level,"~w: ~w ~w",[Level,fa,meta],#{my=>meta}),
+ ok = check_logged(Level,"~w: ~w ~w",[Level,fa,meta],(?MY_LOC(1))#{my=>meta}),
+ ?LOG(Level,fun(x) -> {"~w: ~w ~w",[Level,fun_to_fa,meta]} end,
+ x, #{my=>meta}),
+ ok = check_logged(Level,"~w: ~w ~w",[Level,fun_to_fa,meta],
+ (?MY_LOC(3))#{my=>meta}),
+ ?LOG(Level,fun(x) -> #{Level=>fun_to_r,meta=>true} end, x, #{my=>meta}),
+ ok = check_logged(Level,#{Level=>fun_to_r,meta=>true},
+ (?MY_LOC(2))#{my=>meta}),
+ ?LOG(Level,fun(x) -> <<"fun_to_s">> end,x,#{}),
+ ok = check_logged(Level,<<"fun_to_s">>,?MY_LOC(1)),
+ F1=fun(x) -> {fun_to_bad} end,
+ ?LOG(Level,F1,x,#{}),
+ ok = check_logged(Level,"LAZY_FUN ERROR: ~tp; Returned: ~tp",
+ [{F1,x},{fun_to_bad}],#{}),
+ F2=fun(x) -> erlang:error(fun_that_crashes) end,
+ ?LOG(Level,F2,x,#{}),
+ ok = check_logged(Level,"LAZY_FUN CRASH: ~tp; Reason: ~tp",
+ [{F2,x},{error,fun_that_crashes}],#{}),
+ ok.
+
+%%%-----------------------------------------------------------------
+%%% Called by macro ?TRY(X)
+my_try(Fun) ->
+ try Fun() catch C:R -> {C,R} end.
+
+check_config(crash) ->
+ erlang:error({badmatch,3});
+check_config(_) ->
+ ok.
diff --git a/lib/kernel/test/logger_disk_log_h_SUITE.erl b/lib/kernel/test/logger_disk_log_h_SUITE.erl
new file mode 100644
index 0000000000..a815db14e9
--- /dev/null
+++ b/lib/kernel/test/logger_disk_log_h_SUITE.erl
@@ -0,0 +1,1572 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_disk_log_h_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("kernel/include/logger.hrl").
+-include_lib("kernel/src/logger_internal.hrl").
+-include_lib("kernel/src/logger_h_common.hrl").
+-include_lib("stdlib/include/ms_transform.hrl").
+-include_lib("kernel/include/file.hrl").
+
+-define(check_no_log, [] = test_server:messages_get()).
+
+-define(check(Expected),
+ receive {log,Expected} ->
+ [] = test_server:messages_get()
+ after 1000 ->
+ ct:fail({report_not_received,
+ {line,?LINE},
+ {got,test_server:messages_get()}})
+ end).
+
+-define(msg,"Log from "++atom_to_list(?FUNCTION_NAME)++
+ ":"++integer_to_list(?LINE)).
+-define(bin(Msg), list_to_binary(Msg++"\n")).
+-define(log_no(File,N), lists:concat([File,".",N])).
+-define(domain,#{domain=>[?MODULE]}).
+
+suite() ->
+ [{timetrap,{seconds,30}},
+ {ct_hooks,[logger_test_lib]}].
+
+init_per_suite(Config) ->
+ timer:start(), % to avoid progress report
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_Group, Config) ->
+ Config.
+
+end_per_group(_Group, _Config) ->
+ ok.
+
+init_per_testcase(TestHooksCase, Config) when
+ TestHooksCase == write_failure;
+ TestHooksCase == sync_failure ->
+ case (fun() -> ?TEST_HOOKS_TAB == undefined end)() of
+ true ->
+ {skip,"Define the TEST_HOOKS macro to run this test"};
+ false ->
+ ct:print("********** ~w **********", [TestHooksCase]),
+ Config
+ end;
+init_per_testcase(TestCase, Config) ->
+ ct:print("********** ~w **********", [TestCase]),
+ Config.
+
+end_per_testcase(Case, Config) ->
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
+ ok.
+
+groups() ->
+ [].
+
+all() ->
+ [start_stop_handler,
+ create_log,
+ open_existing_log,
+ disk_log_opts,
+ default_formatter,
+ logging,
+ errors,
+ formatter_fail,
+ config_fail,
+ bad_input,
+ info_and_reset,
+ reconfig,
+ sync,
+ disk_log_full,
+ disk_log_wrap,
+ disk_log_events,
+ write_failure,
+ sync_failure,
+ op_switch_to_sync,
+ op_switch_to_drop,
+ op_switch_to_flush,
+ limit_burst_disabled,
+ limit_burst_enabled_one,
+ limit_burst_enabled_period,
+ kill_disabled,
+ qlen_kill_new,
+ %% qlen_kill_std,
+ mem_kill_new,
+ %% mem_kill_std,
+ restart_after,
+ handler_requests_under_load
+ ].
+
+start_stop_handler(_Config) ->
+ ok = logger:add_handler(?MODULE, logger_disk_log_h, #{}),
+ {error,{already_exist,?MODULE}} =
+ logger:add_handler(?MODULE, logger_disk_log_h, #{}),
+ true = is_pid(whereis(h_proc_name())),
+ ok = logger:remove_handler(?MODULE),
+ timer:sleep(500),
+ undefined = whereis(h_proc_name()).
+start_stop_handler(cleanup, _Config) ->
+ logger:remove_handler(?MODULE).
+
+create_log(Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ %% test new handler
+ Name1 = list_to_atom(lists:concat([?FUNCTION_NAME,"_A"])),
+ LogFile1 = filename:join(PrivDir, Name1),
+ ok = start_and_add(Name1, #{filter_default=>stop,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter=>{?MODULE,self()}},
+ #{file=>LogFile1}),
+ logger:notice("hello", ?domain),
+ logger_disk_log_h:filesync(Name1),
+ ct:pal("Checking contents of ~p", [?log_no(LogFile1,1)]),
+ try_read_file(?log_no(LogFile1,1), {ok,<<"hello\n">>}, 5000),
+
+ %% test second handler
+ Name2 = list_to_atom(lists:concat([?FUNCTION_NAME,"_B"])),
+ DLName = lists:concat([?FUNCTION_NAME,"_B_log"]),
+ LogFile2 = filename:join(PrivDir, DLName),
+ ok = start_and_add(Name2, #{filter_default=>stop,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter=>{?MODULE,self()}},
+ #{file=>LogFile2}),
+ logger:notice("dummy", ?domain),
+ logger_disk_log_h:filesync(Name2),
+ ct:pal("Checking contents of ~p", [?log_no(LogFile2,1)]),
+ try_read_file(?log_no(LogFile2,1), {ok,<<"dummy\n">>}, 5000),
+
+ remove_and_stop(Name1),
+ remove_and_stop(Name2),
+ try_read_file(?log_no(LogFile1,1), {ok,<<"hello\ndummy\n">>}, 1),
+ try_read_file(?log_no(LogFile2,1), {ok,<<"dummy\n">>}, 5000),
+ ok.
+
+open_existing_log(Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ %% test new handler
+ HName = ?FUNCTION_NAME,
+ DLName = lists:concat([?FUNCTION_NAME,"_log"]),
+ LogFile1 = filename:join(PrivDir, DLName),
+ ok = start_and_add(HName, #{filter_default=>stop,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter=>{?MODULE,self()}},
+ #{file=>LogFile1}),
+ logger:notice("one", ?domain),
+ logger_disk_log_h:filesync(HName),
+ ct:pal("Checking contents of ~p", [?log_no(LogFile1,1)]),
+ try_read_file(?log_no(LogFile1,1), {ok,<<"one\n">>}, 5000),
+ logger:notice("two", ?domain),
+ ok = remove_and_stop(HName),
+ try_read_file(?log_no(LogFile1,1), {ok,<<"one\ntwo\n">>}, 5000),
+
+ logger:notice("two and a half", ?domain),
+
+ ok = start_and_add(HName, #{filter_default=>stop,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter=>{?MODULE,self()}},
+ #{file=>LogFile1}),
+ logger:notice("three", ?domain),
+ logger_disk_log_h:filesync(HName),
+ try_read_file(?log_no(LogFile1,1), {ok,<<"one\ntwo\nthree\n">>}, 5000),
+ remove_and_stop(HName),
+ try_read_file(?log_no(LogFile1,1), {ok,<<"one\ntwo\nthree\n">>}, 5000).
+
+disk_log_opts(Config) ->
+ Get = fun(Key, PL) -> proplists:get_value(Key, PL) end,
+ PrivDir = ?config(priv_dir,Config),
+ WName = list_to_atom(lists:concat([?FUNCTION_NAME,"_W"])),
+ WFile = lists:concat([?FUNCTION_NAME,"_W_log"]),
+ Size = length("12345"),
+ ConfigW = #{filter_default=>stop,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter => {?MODULE,no_nl}},
+ WFileFull = filename:join(PrivDir, WFile),
+ DLOptsW = #{file => WFileFull,
+ type => wrap,
+ max_no_bytes => Size,
+ max_no_files => 2},
+ ok = start_and_add(WName, ConfigW, DLOptsW),
+ WInfo1 = disk_log:info(WName),
+ ct:log("Fullname = ~s", [WFileFull]),
+ {WFileFull,wrap,{Size,2},1} = {Get(file,WInfo1),Get(type,WInfo1),
+ Get(size,WInfo1),Get(current_file,WInfo1)},
+ logger:notice("123", ?domain),
+ logger_disk_log_h:filesync(WName),
+ timer:sleep(500),
+ 1 = Get(current_file, disk_log:info(WName)),
+
+ logger:notice("45", ?domain),
+ logger_disk_log_h:filesync(WName),
+ timer:sleep(500),
+ 1 = Get(current_file, disk_log:info(WName)),
+
+ logger:notice("6", ?domain),
+ logger_disk_log_h:filesync(WName),
+ timer:sleep(500),
+ 2 = Get(current_file, disk_log:info(WName)),
+
+ logger:notice("7890", ?domain),
+ logger_disk_log_h:filesync(WName),
+ timer:sleep(500),
+ 2 = Get(current_file, disk_log:info(WName)),
+
+ HName1 = list_to_atom(lists:concat([?FUNCTION_NAME,"_H1"])),
+ HFile1 = lists:concat([?FUNCTION_NAME,"_H1_log"]),
+ ConfigH = #{filter_default=>stop,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter => {?MODULE,no_nl}},
+ HFile1Full = filename:join(PrivDir, HFile1),
+ DLOptsH1 = #{file => HFile1Full,
+ type => halt},
+ ok = start_and_add(HName1, ConfigH, DLOptsH1),
+ HInfo1 = disk_log:info(HName1),
+ ct:log("Fullname = ~s", [HFile1Full]),
+ {HFile1Full,halt,infinity} = {Get(file,HInfo1),Get(type,HInfo1),
+ Get(size,HInfo1)},
+ logger:notice("12345", ?domain),
+ logger_disk_log_h:filesync(HName1),
+ timer:sleep(500),
+ 1 = Get(no_written_items, disk_log:info(HName1)),
+
+ HName2 = list_to_atom(lists:concat([?FUNCTION_NAME,"_H2"])),
+ HFile2 = lists:concat([?FUNCTION_NAME,"_H2_log"]),
+ HFile2Full = filename:join(PrivDir, HFile2),
+ DLOptsH2 = DLOptsH1#{file => HFile2Full,
+ max_no_bytes => 1000},
+ ok = start_and_add(HName2, ConfigH, DLOptsH2),
+ HInfo3 = disk_log:info(HName2),
+ ct:log("Fullname = ~s", [HFile2Full]),
+ {HFile2Full,halt,1000} = {Get(file,HInfo3),Get(type,HInfo3),
+ Get(size,HInfo3)},
+
+ remove_and_stop(WName),
+ remove_and_stop(HName1),
+ remove_and_stop(HName2),
+ ok.
+
+default_formatter(Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ LogFile = filename:join(PrivDir,atom_to_list(?FUNCTION_NAME)),
+ HandlerConfig = #{config => #{file=>LogFile},
+ filter_default=>log},
+ ct:pal("Log: ~p", [LogFile]),
+ ok = logger:add_handler(?MODULE, logger_disk_log_h, HandlerConfig),
+ ok = logger:set_handler_config(?MODULE,formatter,
+ {?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}),
+ LogName = lists:concat([LogFile, ".1"]),
+ logger:notice("dummy"),
+ wait_until_written(LogName),
+ {ok,Bin} = file:read_file(LogName),
+ match = re:run(Bin, "=NOTICE REPORT====.*\ndummy", [{capture,none}]),
+ ok.
+default_formatter(cleanup, _Config) ->
+ logger:remove_handler(?MODULE).
+
+logging(Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ %% test new handler
+ Name = list_to_atom(lists:concat([?FUNCTION_NAME,"_1"])),
+ LogFile = filename:join(PrivDir, Name),
+ ok = start_and_add(Name, #{filter_default=>log,
+ formatter=>{?MODULE,self()}},
+ #{file => LogFile}),
+ MsgFormatter = fun(Term) -> {io_lib:format("Term:~p",[Term]),[]} end,
+ logger:notice([{x,y}], #{report_cb => MsgFormatter}),
+ logger:notice([{x,y}], #{}),
+ ct:pal("Checking contents of ~p", [?log_no(LogFile,1)]),
+ try_read_file(?log_no(LogFile,1), {ok,<<"Term:[{x,y}]\n x: y\n">>}, 5000).
+
+logging(cleanup, _Config) ->
+ Name = list_to_atom(lists:concat([?FUNCTION_NAME,"_1"])),
+ remove_and_stop(Name).
+
+errors(Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ Name1 = list_to_atom(lists:concat([?FUNCTION_NAME,"_1"])),
+ LogFile1 = filename:join(PrivDir,Name1),
+ HandlerConfig = #{config=>#{file=>LogFile1},
+ filter_default=>log,
+ formatter=>{?MODULE,self()}},
+ ok = logger:add_handler(Name1, logger_disk_log_h, HandlerConfig),
+ {error,{already_exist,Name1}} =
+ logger:add_handler(Name1, logger_disk_log_h, #{}),
+
+ %%! TODO:
+ %%! Check how bad log_opts are handled!
+
+ {error,{illegal_config_change,_,_}} =
+ logger:set_handler_config(Name1,
+ config,
+ #{file=>LogFile1,
+ type=>halt}),
+ {error,{illegal_config_change,_,_}} =
+ logger:set_handler_config(Name1,id,new),
+
+ ok = logger:remove_handler(Name1),
+ {error,{not_found,Name1}} = logger:remove_handler(Name1),
+ ok.
+
+errors(cleanup, _Config) ->
+ Name1 = list_to_atom(lists:concat([?FUNCTION_NAME,"_1"])),
+ _ = logger:remove_handler(Name1).
+
+formatter_fail(Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ Name = ?FUNCTION_NAME,
+ LogFile = filename:join(PrivDir,Name),
+ ct:pal("Log = ~p", [LogFile]),
+ HandlerConfig = #{config => #{file=>LogFile},
+ filter_default=>stop,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE])},
+ %% no formatter!
+ logger:add_handler(Name, logger_disk_log_h, HandlerConfig),
+ Pid = whereis(h_proc_name(Name)),
+ true = is_pid(Pid),
+ H = logger:get_handler_ids(),
+ true = lists:member(Name,H),
+
+ %% Formatter is added automatically
+ {ok,#{formatter:={logger_formatter,_}}} = logger:get_handler_config(Name),
+ logger:notice(M1=?msg,?domain),
+ Got1 = try_match_file(?log_no(LogFile,1),"[0-9\\+\\-T:\\.]* notice: "++M1,5000),
+
+ ok = logger:set_handler_config(Name,formatter,{nonexistingmodule,#{}}),
+ logger:notice(M2=?msg,?domain),
+ Got2 = try_match_file(?log_no(LogFile,1),
+ escape(Got1)++"[0-9\\+\\-T:\\.]* notice: FORMATTER CRASH: .*"++M2,
+ 5000),
+
+ ok = logger:set_handler_config(Name,formatter,{?MODULE,crash}),
+ logger:notice(M3=?msg,?domain),
+ Got3 = try_match_file(?log_no(LogFile,1),
+ escape(Got2)++"[0-9\\+\\-T:\\.]* notice: FORMATTER CRASH: .*"++M3,
+ 5000),
+
+ ok = logger:set_handler_config(Name,formatter,{?MODULE,bad_return}),
+ logger:notice(?msg,?domain),
+ try_match_file(?log_no(LogFile,1),
+ escape(Got3)++"FORMATTER ERROR: bad return value",
+ 5000),
+
+ %% Check that handler is still alive and was never dead
+ Pid = whereis(h_proc_name(Name)),
+ H = logger:get_handler_ids(),
+ ok.
+
+formatter_fail(cleanup,_Config) ->
+ _ = logger:remove_handler(?FUNCTION_NAME),
+ ok.
+
+config_fail(_Config) ->
+ {error,{handler_not_added,{invalid_config,logger_disk_log_h,{bad,bad}}}} =
+ logger:add_handler(?MODULE,logger_disk_log_h,
+ #{config => #{bad => bad},
+ filter_default=>log,
+ formatter=>{?MODULE,self()}}),
+
+ {error,{handler_not_added,{invalid_levels,{_,1,_}}}} =
+ logger:add_handler(?MODULE,logger_disk_log_h,
+ #{config => #{drop_mode_qlen=>1}}),
+ {error,{handler_not_added,{invalid_levels,{43,42,_}}}} =
+ logger:add_handler(?MODULE,logger_disk_log_h,
+ #{config => #{sync_mode_qlen=>43,
+ drop_mode_qlen=>42}}),
+ {error,{handler_not_added,{invalid_levels,{_,43,42}}}} =
+ logger:add_handler(?MODULE,logger_disk_log_h,
+ #{config => #{drop_mode_qlen=>43,
+ flush_qlen=>42}}),
+
+ ok = logger:add_handler(?MODULE,logger_disk_log_h,
+ #{filter_default=>log,
+ formatter=>{?MODULE,self()}}),
+ %% can't change the disk log options for a log already in use
+ {error,{illegal_config_change,_,_}} =
+ logger:set_handler_config(?MODULE,config,
+ #{max_no_files=>2}),
+ %% can't change name of an existing handler
+ {error,{illegal_config_change,_,_}} =
+ logger:set_handler_config(?MODULE,id,bad),
+ %% incorrect values of OP params
+ {ok,#{config := HConfig}} = logger:get_handler_config(?MODULE),
+ {error,{invalid_levels,_}} =
+ logger:set_handler_config(?MODULE,config,
+ HConfig#{sync_mode_qlen=>100,
+ flush_qlen=>99}),
+ %% invalid name of config parameter
+ {error,{invalid_config,logger_disk_log_h,{filesync_rep_int,2000}}} =
+ logger:set_handler_config(?MODULE, config,
+ HConfig#{filesync_rep_int => 2000}),
+ ok.
+config_fail(cleanup,_Config) ->
+ logger:remove_handler(?MODULE).
+
+bad_input(_Config) ->
+ {error,{badarg,{filesync,["BadType"]}}} =
+ logger_disk_log_h:filesync("BadType"),
+ {error,{badarg,{info,["BadType"]}}} = logger_disk_log_h:info("BadType"),
+ {error,{badarg,{reset,["BadType"]}}} = logger_disk_log_h:reset("BadType").
+
+info_and_reset(_Config) ->
+ ok = logger:add_handler(?MODULE,logger_disk_log_h,
+ #{filter_default=>log,
+ formatter=>{?MODULE,self()}}),
+ #{id := ?MODULE} = logger_disk_log_h:info(?MODULE),
+ ok = logger_disk_log_h:reset(?MODULE).
+info_and_reset(cleanup,_Config) ->
+ logger:remove_handler(?MODULE).
+
+reconfig(Config) ->
+ Dir = ?config(priv_dir,Config),
+ ok = logger:add_handler(?MODULE,
+ logger_disk_log_h,
+ #{filter_default=>log,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter=>{?MODULE,self()}}),
+ #{id := ?MODULE,
+ sync_mode_qlen := ?SYNC_MODE_QLEN,
+ drop_mode_qlen := ?DROP_MODE_QLEN,
+ flush_qlen := ?FLUSH_QLEN,
+ burst_limit_enable := ?BURST_LIMIT_ENABLE,
+ burst_limit_max_count := ?BURST_LIMIT_MAX_COUNT,
+ burst_limit_window_time := ?BURST_LIMIT_WINDOW_TIME,
+ overload_kill_enable := ?OVERLOAD_KILL_ENABLE,
+ overload_kill_qlen := ?OVERLOAD_KILL_QLEN,
+ overload_kill_mem_size := ?OVERLOAD_KILL_MEM_SIZE,
+ overload_kill_restart_after := ?OVERLOAD_KILL_RESTART_AFTER,
+ filesync_repeat_interval := ?FILESYNC_REPEAT_INTERVAL,
+ log_opts := #{type := ?DISK_LOG_TYPE,
+ max_no_files := ?DISK_LOG_MAX_NO_FILES,
+ max_no_bytes := ?DISK_LOG_MAX_NO_BYTES,
+ file := _DiskLogFile}} =
+ logger_disk_log_h:info(?MODULE),
+
+ {ok,#{config := HConfig0}} = logger:get_handler_config(?MODULE),
+ HConfig1 = HConfig0#{sync_mode_qlen => 1,
+ drop_mode_qlen => 2,
+ flush_qlen => 3,
+ burst_limit_enable => false,
+ burst_limit_max_count => 10,
+ burst_limit_window_time => 10,
+ overload_kill_enable => true,
+ overload_kill_qlen => 100000,
+ overload_kill_mem_size => 10000000,
+ overload_kill_restart_after => infinity,
+ filesync_repeat_interval => no_repeat},
+ ok = logger:set_handler_config(?MODULE, config, HConfig1),
+ #{id := ?MODULE,
+ sync_mode_qlen := 1,
+ drop_mode_qlen := 2,
+ flush_qlen := 3,
+ burst_limit_enable := false,
+ burst_limit_max_count := 10,
+ burst_limit_window_time := 10,
+ overload_kill_enable := true,
+ overload_kill_qlen := 100000,
+ overload_kill_mem_size := 10000000,
+ overload_kill_restart_after := infinity,
+ filesync_repeat_interval := no_repeat} =
+ logger_disk_log_h:info(?MODULE),
+
+ ok = logger:remove_handler(?MODULE),
+
+ File = filename:join(Dir, "logfile"),
+ ok = logger:add_handler(?MODULE,
+ logger_disk_log_h,
+ #{filter_default=>log,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter=>{?MODULE,self()},
+ config=>
+ #{type => halt,
+ max_no_files => 1,
+ max_no_bytes => 1024,
+ file => File}}),
+ #{log_opts := #{type := halt,
+ max_no_files := 1,
+ max_no_bytes := 1024,
+ file := File}} =
+ logger_disk_log_h:info(?MODULE),
+ ok.
+
+reconfig(cleanup, _Config) ->
+ logger:remove_handler(?MODULE).
+
+sync(Config) ->
+ Dir = ?config(priv_dir,Config),
+ File = filename:join(Dir, ?FUNCTION_NAME),
+ Log = lists:concat([File,".1"]),
+ ok = logger:add_handler(?MODULE,
+ logger_disk_log_h,
+ #{config => #{file => File},
+ filter_default=>log,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter=>{?MODULE,nl}}),
+
+ start_tracer([{disk_log,blog,2},
+ {logger_disk_log_h,disk_log_sync,2}],
+ [{disk_log,blog,<<"first\n">>},
+ {logger_disk_log_h,disk_log_sync}]),
+
+ logger:notice("first", ?domain),
+ %% wait for automatic disk_log_sync
+ check_tracer(?FILESYNC_REPEAT_INTERVAL*2),
+
+ %% check that if there's no repeated disk_log_sync active,
+ %% a disk_log_sync is still performed when handler goes idle
+ {ok,#{config := HConfig}} = logger:get_handler_config(?MODULE),
+ HConfig1 = HConfig#{filesync_repeat_interval => no_repeat},
+ ok = logger:set_handler_config(?MODULE, config, HConfig1),
+
+ no_repeat = maps:get(filesync_repeat_interval,
+ logger_disk_log_h:info(?MODULE)),
+ %% The following timer is to make sure the time from last log
+ %% ("first") to next ("second") is long enough, so the a flush is
+ %% triggered by the idle timeout between "fourth" and "fifth".
+ timer:sleep(?IDLE_DETECT_TIME_MSEC*2),
+
+ start_tracer([{disk_log,blog,2},
+ {logger_disk_log_h,disk_log_sync,2}],
+ [{disk_log,blog,<<"second\n">>},
+ {logger_disk_log_h,disk_log_sync},
+ {disk_log,blog,<<"third\n">>},
+ {logger_disk_log_h,disk_log_sync}]),
+
+ logger:notice("second", ?domain),
+ timer:sleep(?IDLE_DETECT_TIME_MSEC*2),
+ logger:notice("third", ?domain),
+ %% wait for automatic disk_log_sync
+ check_tracer(?IDLE_DETECT_TIME_MSEC*2),
+
+ try_read_file(Log, {ok,<<"first\nsecond\nthird\n">>}, 1000),
+
+ %% switch repeated disk_log_sync on and verify that the looping works
+ SyncInt = 1000,
+ WaitT = 4500,
+ OneSync = {logger_disk_log_h,handle_cast,repeated_disk_log_sync},
+ %% receive 1 initial repeated_disk_log_sync, then 1 per sec
+ start_tracer([{logger_disk_log_h,handle_cast,2}],
+ [OneSync || _ <- lists:seq(1, 1 + trunc(WaitT/SyncInt))]),
+
+ HConfig2 = HConfig#{filesync_repeat_interval => SyncInt},
+ ok = logger:set_handler_config(?MODULE, config, HConfig2),
+
+ SyncInt = maps:get(filesync_repeat_interval,
+ logger_disk_log_h:info(?MODULE)),
+ timer:sleep(WaitT),
+ HConfig3 = HConfig#{filesync_repeat_interval => no_repeat},
+ ok = logger:set_handler_config(?MODULE, config, HConfig3),
+ check_tracer(100),
+ ok.
+sync(cleanup,_Config) ->
+ dbg:stop_clear(),
+ logger:remove_handler(?MODULE).
+
+disk_log_wrap(Config) ->
+ Get = fun(Key, PL) -> proplists:get_value(Key, PL) end,
+ Dir = ?config(priv_dir,Config),
+ File = filename:join(Dir, ?FUNCTION_NAME),
+ ct:pal("Log = ~p", [File]),
+ MaxFiles = 3,
+ MaxBytes = 5,
+ ok = logger:add_handler(?MODULE,
+ logger_disk_log_h,
+ #{filter_default=>log,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter=>{?MODULE,self()},
+ config=>
+ #{type => wrap,
+ max_no_files => MaxFiles,
+ max_no_bytes => MaxBytes,
+ file => File}}),
+ Info = disk_log:info(?MODULE),
+ {File,wrap,{MaxBytes,MaxFiles},1} =
+ {Get(file,Info),Get(type,Info),Get(size,Info),Get(current_file,Info)},
+ Tester = self(),
+ TraceFun = fun({trace,_,call,{Mod,Func,Details}}, Pid) ->
+ Pid ! {trace,Mod,Func,Details},
+ Pid
+ end,
+ {ok,_} = dbg:tracer(process, {TraceFun, Tester}),
+ {ok,_} = dbg:p(whereis(h_proc_name()), [c]),
+ {ok,_} = dbg:tp(logger_disk_log_h, handle_info, 2, []),
+
+ Text = [34 + rand:uniform(126-34) || _ <- lists:seq(1,MaxBytes)],
+ ct:pal("String = ~p (~w)", [Text, erts_debug:size(Text)]),
+ %% fill first file
+ lists:foreach(fun(N) ->
+ Log = lists:concat([File,".",N]),
+ logger:notice(Text, ?domain),
+ wait_until_written(Log),
+ ct:pal("N = ~w",
+ [N = Get(current_file,
+ disk_log:info(?MODULE))])
+ end, lists:seq(1,MaxFiles)),
+
+ %% wait for trace messages
+ timer:sleep(1000),
+ dbg:stop_clear(),
+ Received = lists:flatmap(fun({trace,_M,handle_info,
+ [{disk_log,_Node,_Name,What},_]}) ->
+ [{trace,What}];
+ ({log,_}) ->
+ []
+ end, test_server:messages_get()),
+ ct:pal("Trace =~n~p", [Received]),
+ Received = [{trace,{wrap,0}} || _ <- lists:seq(1,MaxFiles-1)],
+ ok.
+
+disk_log_wrap(cleanup,_Config) ->
+ dbg:stop_clear(),
+ logger:remove_handler(?MODULE).
+
+disk_log_full(Config) ->
+ Dir = ?config(priv_dir,Config),
+ File = filename:join(Dir, ?FUNCTION_NAME),
+ ct:pal("Log = ~p", [File]),
+ MaxBytes = 50,
+ ok = logger:add_handler(?MODULE,
+ logger_disk_log_h,
+ #{filter_default=>log,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter=>{?MODULE,self()},
+ config=>
+ #{type => halt,
+ max_no_files => 1,
+ max_no_bytes => MaxBytes,
+ file => File}}),
+
+ Tester = self(),
+ TraceFun = fun({trace,_,call,{Mod,Func,Details}}, Pid) ->
+ Pid ! {trace,Mod,Func,Details},
+ Pid
+ end,
+ {ok,_} = dbg:tracer(process, {TraceFun, Tester}),
+ {ok,_} = dbg:p(whereis(h_proc_name()), [c]),
+ {ok,_} = dbg:tp(logger_disk_log_h, handle_info, 2, []),
+
+ NoOfChars = 5,
+ Text = [34 + rand:uniform(126-34) || _ <- lists:seq(1,NoOfChars)],
+ [logger:notice(Text, ?domain) || _ <- lists:seq(1,trunc(MaxBytes/NoOfChars)+1)],
+
+ %% wait for trace messages
+ timer:sleep(2000),
+ dbg:stop_clear(),
+ Received = lists:flatmap(fun({trace,_M,handle_info,
+ [{disk_log,_Node,_Name,What},_]}) ->
+ [{trace,What}];
+ ({log,_}) ->
+ []
+ end, test_server:messages_get()),
+ ct:pal("Trace =~n~p", [Received]),
+ [{trace,full},
+ {trace,{error_status,{error,{full,_}}}}] = Received,
+ ok.
+disk_log_full(cleanup, _Config) ->
+ dbg:stop_clear(),
+ logger:remove_handler(?MODULE).
+
+disk_log_events(Config) ->
+ Node = node(),
+ Log = ?MODULE,
+ ok = logger:add_handler(?MODULE,
+ logger_disk_log_h,
+ #{filter_default=>log,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter=>{?MODULE,self()}}),
+
+ %% Events copied from disk_log API
+ Events =
+ [{disk_log, Node, Log, {wrap, 0}},
+ {disk_log, Node, Log, {truncated, 0}},
+ {disk_log, Node, Log, {read_only, 42}},
+ {disk_log, Node, Log, {blocked_log, 42}},
+ {disk_log, Node, Log, {format_external, 42}},
+ {disk_log, Node, Log, full},
+ {disk_log, Node, Log, {error_status, ok}}],
+
+ Tester = self(),
+ TraceFun = fun({trace,_,call,{Mod,Func,Details}}, Pid) ->
+ Pid ! {trace,Mod,Func,Details},
+ Pid
+ end,
+ {ok,_} = dbg:tracer(process, {TraceFun, Tester}),
+ {ok,_} = dbg:p(whereis(h_proc_name()), [c]),
+ {ok,_} = dbg:tp(logger_disk_log_h, handle_info, 2, []),
+
+ [whereis(h_proc_name()) ! E || E <- Events],
+ %% wait for trace messages
+ timer:sleep(2000),
+ dbg:stop_clear(),
+ Received = lists:map(fun({trace,_M,handle_info,
+ [Got,_]}) -> Got
+ end, test_server:messages_get()),
+ ct:pal("Trace =~n~p", [Received]),
+ NoOfEvents = length(Events),
+ NoOfEvents = length(Received),
+ lists:foreach(fun(Event) ->
+ true = lists:member(Event, Received)
+ end, Received),
+ ok.
+disk_log_events(cleanup, _Config) ->
+ dbg:stop_clear(),
+ logger:remove_handler(?MODULE).
+
+write_failure(Config) ->
+ Dir = ?config(priv_dir, Config),
+ File = filename:join(Dir, ?FUNCTION_NAME),
+ Log = lists:concat([File,".1"]),
+ ct:pal("Log = ~p", [Log]),
+
+ Node = start_h_on_new_node(Config, File),
+ false = (undefined == rpc:call(Node, ets, whereis, [?TEST_HOOKS_TAB])),
+ rpc:call(Node, ets, insert, [?TEST_HOOKS_TAB,{tester,self()}]),
+ rpc:call(Node, ?MODULE, set_internal_log, [?MODULE,internal_log]),
+ rpc:call(Node, ?MODULE, set_result, [disk_log_blog,ok]),
+ HState = rpc:call(Node, logger_disk_log_h, info, [?STANDARD_HANDLER]),
+ ct:pal("LogOpts = ~p", [LogOpts = maps:get(log_opts, HState)]),
+
+ ok = log_on_remote_node(Node, "Logged1"),
+ rpc:call(Node, logger_disk_log_h, filesync, [?STANDARD_HANDLER]),
+ ?check_no_log,
+
+ SyncRepInt = case (fun() -> is_atom(?FILESYNC_REPEAT_INTERVAL) end)() of
+ true -> 5500;
+ false -> ?FILESYNC_REPEAT_INTERVAL + 500
+ end,
+
+ try_read_file(Log, {ok,<<"Logged1\n">>}, SyncRepInt),
+
+ rpc:call(Node, ?MODULE, set_result, [disk_log_blog,{error,no_such_log}]),
+ ok = log_on_remote_node(Node, "Cause simple error printout"),
+
+ ?check({error,{?STANDARD_HANDLER,log,LogOpts,{error,no_such_log}}}),
+
+ ok = log_on_remote_node(Node, "No second error printout"),
+ ?check_no_log,
+
+ rpc:call(Node, ?MODULE, set_result, [disk_log_blog,
+ {error,{full,?STANDARD_HANDLER}}]),
+ ok = log_on_remote_node(Node, "Cause simple error printout"),
+ ?check({error,{?STANDARD_HANDLER,log,LogOpts,
+ {error,{full,?STANDARD_HANDLER}}}}),
+
+ rpc:call(Node, ?MODULE, set_result, [disk_log_blog,ok]),
+ ok = log_on_remote_node(Node, "Logged2"),
+ rpc:call(Node, logger_disk_log_h, filesync, [?STANDARD_HANDLER]),
+ ?check_no_log,
+ try_read_file(Log, {ok,<<"Logged1\nLogged2\n">>}, SyncRepInt),
+ ok.
+write_failure(cleanup, _Config) ->
+ Nodes = nodes(),
+ [test_server:stop_node(Node) || Node <- Nodes].
+
+
+sync_failure(Config) ->
+ Dir = ?config(priv_dir, Config),
+ FileName = lists:concat([?MODULE,"_",?FUNCTION_NAME]),
+ File = filename:join(Dir, FileName),
+
+
+ Node = start_h_on_new_node(Config, File),
+ false = (undefined == rpc:call(Node, ets, whereis, [?TEST_HOOKS_TAB])),
+ rpc:call(Node, ets, insert, [?TEST_HOOKS_TAB,{tester,self()}]),
+ rpc:call(Node, ?MODULE, set_internal_log, [?MODULE,internal_log]),
+ rpc:call(Node, ?MODULE, set_result, [disk_log_sync,ok]),
+ HState = rpc:call(Node, logger_disk_log_h, info, [?STANDARD_HANDLER]),
+ LogOpts = maps:get(log_opts, HState),
+
+ SyncInt = 500,
+ ok = rpc:call(Node, logger, set_handler_config,
+ [?STANDARD_HANDLER, config,
+ #{filesync_repeat_interval => SyncInt}]),
+ Info = rpc:call(Node, logger_disk_log_h, info, [?STANDARD_HANDLER]),
+ SyncInt = maps:get(filesync_repeat_interval, Info),
+
+ ok = log_on_remote_node(Node, "Logged1"),
+ ?check_no_log,
+
+ rpc:call(Node, ?MODULE, set_result, [disk_log_sync,{error,no_such_log}]),
+ ok = log_on_remote_node(Node, "Cause simple error printout"),
+
+ ?check({error,{?STANDARD_HANDLER,filesync,LogOpts,{error,no_such_log}}}),
+
+ ok = log_on_remote_node(Node, "No second error printout"),
+ ?check_no_log,
+
+ rpc:call(Node, ?MODULE, set_result,
+ [disk_log_sync,{error,{blocked_log,?STANDARD_HANDLER}}]),
+ ok = log_on_remote_node(Node, "Cause simple error printout"),
+ ?check({error,{?STANDARD_HANDLER,filesync,LogOpts,
+ {error,{blocked_log,?STANDARD_HANDLER}}}}),
+
+ rpc:call(Node, ?MODULE, set_result, [disk_log_sync,ok]),
+ ok = log_on_remote_node(Node, "Logged2"),
+ ?check_no_log,
+ ok.
+sync_failure(cleanup, _Config) ->
+ Nodes = nodes(),
+ [test_server:stop_node(Node) || Node <- Nodes].
+
+start_h_on_new_node(Config, File) ->
+ {ok,_,Node} =
+ logger_test_lib:setup(
+ Config,
+ [{logger,[{handler,default,logger_disk_log_h,
+ #{ config => #{ file => File }}}]}]),
+ ok = rpc:call(Node,logger,set_handler_config,[?STANDARD_HANDLER,formatter,
+ {?MODULE,nl}]),
+ Node.
+
+log_on_remote_node(Node,Msg) ->
+ _ = spawn_link(Node,
+ fun() -> erlang:group_leader(whereis(user),self()),
+ logger:notice(Msg)
+ end),
+ ok.
+
+%% functions for test hook macros to be called by rpc
+set_internal_log(_Mod, _Func) ->
+ ?set_internal_log({_Mod,_Func}).
+set_result(_Op, _Result) ->
+ ?set_result(_Op, _Result).
+set_defaults() ->
+ ?set_defaults().
+
+%% internal log function that sends the term to the test case process
+internal_log(Type, Term) ->
+ [{tester,Tester}] = ets:lookup(?TEST_HOOKS_TAB, tester),
+ Tester ! {log,{Type,Term}},
+ logger:internal_log(Type, Term),
+ ok.
+
+
+%%%-----------------------------------------------------------------
+%%% Overload protection tests
+
+op_switch_to_sync(Config) ->
+ {Log,HConfig,DLHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ NumOfReqs = 500,
+ NewHConfig =
+ HConfig#{config => DLHConfig#{sync_mode_qlen => 2,
+ drop_mode_qlen => NumOfReqs+1,
+ flush_qlen => 2*NumOfReqs,
+ burst_limit_enable => false}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
+ Lines = count_lines(Log),
+ NumOfReqs = Lines,
+ ok = file_delete(Log),
+ ok.
+op_switch_to_sync(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+op_switch_to_drop() ->
+ [{timetrap,{seconds,180}}].
+op_switch_to_drop(Config) ->
+ Test =
+ fun() ->
+ {Log,HConfig,DLHConfig} =
+ start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ NumOfReqs = 300,
+ Procs = 2,
+ Bursts = 10,
+ NewHConfig =
+ HConfig#{config =>
+ DLHConfig#{sync_mode_qlen => 1,
+ drop_mode_qlen => 2,
+ flush_qlen => Procs*NumOfReqs*Bursts,
+ burst_limit_enable => false}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ %% It sometimes happens that the handler either gets
+ %% the requests in a slow enough pace so that dropping
+ %% never occurs. Therefore, lets generate a number of
+ %% bursts to increase the chance of message buildup.
+ [send_burst({n,NumOfReqs}, {spawn,Procs,0}, {chars,79}, notice) ||
+ _ <- lists:seq(1, Bursts)],
+ Logged = count_lines(Log),
+ ok = stop_handler(?MODULE),
+ ct:pal("Number of messages dropped = ~w (~w)",
+ [Procs*NumOfReqs*Bursts-Logged,Procs*NumOfReqs*Bursts]),
+ true = (Logged < (Procs*NumOfReqs*Bursts)),
+ true = (Logged > 0),
+ _ = file_delete(Log),
+ ok
+ end,
+ %% As it's tricky to get the timing right in only one go, we perform the
+ %% test repeatedly, hoping that will generate a successful result.
+ case repeat_until_ok(Test, 10) of
+ {ok,{Failures,_Result}} ->
+ ct:log("Failed ~w times before success!", [Failures]);
+ {fails,Reason} ->
+ ct:fail(Reason)
+ end.
+op_switch_to_drop(cleanup, _Config) ->
+ _ = stop_handler(?MODULE).
+
+op_switch_to_flush() ->
+ [{timetrap,{minutes,3}}].
+op_switch_to_flush(Config) ->
+ Test =
+ fun() ->
+ {Log,HConfig,DLHConfig} =
+ start_handler(?MODULE, ?FUNCTION_NAME, Config),
+
+ %% NOTE: it's important that both async and sync
+ %% requests have been queued when the flush happens
+ %% (verify with coverage of flush_log_requests/2)
+
+ NewHConfig =
+ HConfig#{config =>
+ DLHConfig#{sync_mode_qlen => 2,
+ %% disable drop mode
+ drop_mode_qlen => 300,
+ flush_qlen => 300,
+ burst_limit_enable => false}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ NumOfReqs = 1500,
+ Procs = 10,
+ Bursts = 10,
+ %% It sometimes happens that the handler either gets
+ %% the requests in a slow enough pace so that flushing
+ %% never occurs, or it gets all messages at once,
+ %% causing all messages to get flushed (no dropping of
+ %% sync messages gets tested). Therefore, lets
+ %% generate a number of bursts to increase the chance
+ %% of message buildup in some random fashion.
+ [send_burst({n,NumOfReqs}, {spawn,Procs,0}, {chars,79}, notice) ||
+ _ <- lists:seq(1,Bursts)],
+ Logged = count_lines(Log),
+ ok= stop_handler(?MODULE),
+ ct:pal("Number of messages flushed/dropped = ~w (~w)",
+ [NumOfReqs*Procs*Bursts-Logged,NumOfReqs*Procs*Bursts]),
+ true = (Logged < (NumOfReqs*Procs*Bursts)),
+ true = (Logged > 0),
+ _ = file_delete(Log),
+ ok
+ end,
+ %% As it's tricky to get the timing right in only one go, we perform the
+ %% test repeatedly, hoping that will generate a successful result.
+ case repeat_until_ok(Test, 10) of
+ {ok,{Failures,_Result}} ->
+ ct:log("Failed ~w times before success!", [Failures]);
+ {fails,Reason} ->
+ ct:fail(Reason)
+ end.
+op_switch_to_flush(cleanup, _Config) ->
+ _ = stop_handler(?MODULE).
+
+
+limit_burst_disabled(Config) ->
+ {Log,HConfig,DLHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ NewHConfig =
+ HConfig#{config => DLHConfig#{burst_limit_enable => false,
+ burst_limit_max_count => 10,
+ burst_limit_window_time => 2000,
+ drop_mode_qlen => 200,
+ flush_qlen => 300}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ NumOfReqs = 100,
+ send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
+ Logged = count_lines(Log),
+ ct:pal("Number of messages logged = ~w", [Logged]),
+ NumOfReqs = Logged,
+ ok = file_delete(Log),
+ ok.
+limit_burst_disabled(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+limit_burst_enabled_one(Config) ->
+ {Log,HConfig,DLHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ ReqLimit = 10,
+ NewHConfig =
+ HConfig#{config => DLHConfig#{burst_limit_enable => true,
+ burst_limit_max_count => ReqLimit,
+ burst_limit_window_time => 2000,
+ drop_mode_qlen => 200,
+ flush_qlen => 300}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ NumOfReqs = 100,
+ send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
+ Logged = count_lines(Log),
+ ct:pal("Number of messages logged = ~w", [Logged]),
+ ReqLimit = Logged,
+ ok = file_delete(Log),
+ ok.
+limit_burst_enabled_one(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+limit_burst_enabled_period(Config) ->
+ {Log,HConfig,DLHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ ReqLimit = 10,
+ BurstTWin = 1000,
+ NewHConfig =
+ HConfig#{config => DLHConfig#{burst_limit_enable => true,
+ burst_limit_max_count => ReqLimit,
+ burst_limit_window_time => BurstTWin,
+ drop_mode_qlen => 20000,
+ flush_qlen => 20001}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+
+ Windows = 3,
+ Sent = send_burst({t,BurstTWin*Windows}, seq, {chars,79}, notice),
+ Logged = count_lines(Log),
+ ct:pal("Number of messages sent = ~w~nNumber of messages logged = ~w",
+ [Sent,Logged]),
+ true = (Logged > (ReqLimit*Windows)) andalso
+ (Logged < (ReqLimit*(Windows+2))),
+ ok = file_delete(Log),
+ ok.
+limit_burst_enabled_period(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+kill_disabled(Config) ->
+ {Log,HConfig,DLHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ NewHConfig =
+ HConfig#{config=>DLHConfig#{overload_kill_enable=>false,
+ overload_kill_qlen=>10,
+ overload_kill_mem_size=>100}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ NumOfReqs = 100,
+ send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
+ Logged = count_lines(Log),
+ ct:pal("Number of messages logged = ~w", [Logged]),
+ ok = file_delete(Log),
+ true = is_pid(whereis(h_proc_name())),
+ ok.
+kill_disabled(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+qlen_kill_new(Config) ->
+ {Log,HConfig,DLHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ Pid0 = whereis(h_proc_name()),
+ {_,Mem0} = process_info(Pid0, memory),
+ RestartAfter = ?OVERLOAD_KILL_RESTART_AFTER,
+ NewHConfig =
+ HConfig#{config =>
+ DLHConfig#{overload_kill_enable=>true,
+ overload_kill_qlen=>10,
+ overload_kill_mem_size=>Mem0+50000,
+ overload_kill_restart_after=>RestartAfter}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ MRef = erlang:monitor(process, Pid0),
+ NumOfReqs = 100,
+ Procs = 4,
+ send_burst({n,NumOfReqs}, {spawn,Procs,0}, {chars,79}, notice),
+ %% send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
+ receive
+ {'DOWN', MRef, _, _, Info} ->
+ case Info of
+ {shutdown,{overloaded,?MODULE,QLen,Mem}} ->
+ ct:pal("Terminated with qlen = ~w, mem = ~w", [QLen,Mem]);
+ killed ->
+ ct:pal("Slow shutdown, handler process was killed!", [])
+ end,
+ file_delete(Log),
+ {ok,_} = wait_for_process_up(RestartAfter * 3),
+ ok
+ after
+ 5000 ->
+ Info = logger_disk_log_h:info(?MODULE),
+ ct:pal("Handler state = ~p", [Info]),
+ ct:fail("Handler not dead! It should not have survived this!")
+ end.
+qlen_kill_new(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+mem_kill_new(Config) ->
+ {Log,HConfig,DLHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ Pid0 = whereis(h_proc_name()),
+ {_,Mem0} = process_info(Pid0, memory),
+ RestartAfter = ?OVERLOAD_KILL_RESTART_AFTER,
+ NewHConfig =
+ HConfig#{config =>
+ DLHConfig#{overload_kill_enable=>true,
+ overload_kill_qlen=>50000,
+ overload_kill_mem_size=>Mem0+500,
+ overload_kill_restart_after=>RestartAfter}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ MRef = erlang:monitor(process, Pid0),
+ NumOfReqs = 100,
+ Procs = 4,
+ send_burst({n,NumOfReqs}, {spawn,Procs,0}, {chars,79}, notice),
+ %% send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
+ receive
+ {'DOWN', MRef, _, _, Info} ->
+ case Info of
+ {shutdown,{overloaded,?MODULE,QLen,Mem}} ->
+ ct:pal("Terminated with qlen = ~w, mem = ~w", [QLen,Mem]);
+ killed ->
+ ct:pal("Slow shutdown, handler process was killed!", [])
+ end,
+ file_delete(Log),
+ {ok,_} = wait_for_process_up(RestartAfter * 3),
+ ok
+ after
+ 5000 ->
+ Info = logger_disk_log_h:info(?MODULE),
+ ct:pal("Handler state = ~p", [Info]),
+ ct:fail("Handler not dead! It should not have survived this!")
+ end.
+mem_kill_new(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+restart_after() ->
+ [{timetrap,{minutes,2}}].
+restart_after(Config) ->
+ {Log,HConfig,DLHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ NewHConfig1 =
+ HConfig#{config=>DLHConfig#{overload_kill_enable=>true,
+ overload_kill_qlen=>10,
+ overload_kill_restart_after=>infinity}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig1),
+ MRef1 = erlang:monitor(process, whereis(h_proc_name())),
+ %% kill handler
+ send_burst({n,100}, {spawn,4,0}, {chars,79}, notice),
+ receive
+ {'DOWN', MRef1, _, _, _Reason1} ->
+ file_delete(Log),
+ error = wait_for_process_up(?OVERLOAD_KILL_RESTART_AFTER * 3),
+ ok
+ after
+ 5000 ->
+ Info1 = logger_std_h:info(?MODULE),
+ ct:pal("Handler state = ~p", [Info1]),
+ ct:fail("Handler not dead! It should not have survived this!")
+ end,
+
+ {Log,_,_} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ RestartAfter = ?OVERLOAD_KILL_RESTART_AFTER,
+ NewHConfig2 =
+ HConfig#{config=>DLHConfig#{overload_kill_enable=>true,
+ overload_kill_qlen=>10,
+ overload_kill_restart_after=>RestartAfter}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig2),
+ Pid0 = whereis(h_proc_name()),
+ MRef2 = erlang:monitor(process, Pid0),
+ %% kill handler
+ send_burst({n,100}, {spawn,4,0}, {chars,79}, notice),
+ receive
+ {'DOWN', MRef2, _, _, _Reason2} ->
+ file_delete(Log),
+ {ok,Pid1} = wait_for_process_up(RestartAfter * 3),
+ false = (Pid1 == Pid0),
+ ok
+ after
+ 5000 ->
+ Info2 = logger_std_h:info(?MODULE),
+ ct:pal("Handler state = ~p", [Info2]),
+ ct:fail("Handler not dead! It should not have survived this!")
+ end,
+ ok.
+restart_after(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+%% send handler requests (sync, info, reset, change_config)
+%% during high load to verify that sync, dropping and flushing is
+%% handled correctly.
+handler_requests_under_load() ->
+ [{timetrap,{minutes,5}}].
+handler_requests_under_load(Config) ->
+ {Log,HConfig,DLHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ NewHConfig =
+ HConfig#{config => DLHConfig#{sync_mode_qlen => 2,
+ drop_mode_qlen => 1000,
+ flush_qlen => 2000,
+ burst_limit_enable => false}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ Pid = spawn_link(fun() -> send_requests(?MODULE, 1, [{filesync,[]},
+ {info,[]},
+ {reset,[]},
+ {change_config,[]}])
+ end),
+ Procs = 100,
+ Sent = Procs * send_burst({n,5000}, {spawn,Procs,10}, {chars,79}, notice),
+ Pid ! {self(),finish},
+ ReqResult = receive {Pid,Result} -> Result end,
+ Logged = count_lines(Log),
+ ct:pal("Number of messages sent = ~w~nNumber of messages logged = ~w",
+ [Sent,Logged]),
+ FindError = fun(Res) ->
+ [E || E <- Res,
+ is_tuple(E) andalso (element(1,E) == error)]
+ end,
+ Errors = [{Req,FindError(Res)} || {Req,Res} <- ReqResult],
+ NoOfReqs = lists:foldl(fun({_,Res}, N) -> N + length(Res) end, 0, ReqResult),
+ ct:pal("~w requests made. Errors: ~n~p", [NoOfReqs,Errors]),
+ ok = file_delete(Log).
+handler_requests_under_load(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+send_requests(HName, TO, Reqs = [{Req,Res}|Rs]) ->
+ receive
+ {From,finish} ->
+ From ! {self(),Reqs}
+ after
+ TO ->
+ Result =
+ case Req of
+ change_config ->
+ logger:set_handler_config(HName, logger_disk_log_h,
+ #{overload_kill_enable =>
+ false});
+ Func ->
+ logger_disk_log_h:Func(HName)
+ end,
+ send_requests(HName, TO, Rs ++ [{Req,[Result|Res]}])
+ end.
+
+%%%-----------------------------------------------------------------
+%%%
+start_handler(Name, FuncName, Config) ->
+ Dir = ?config(priv_dir,Config),
+ File = filename:join(Dir, FuncName),
+ ct:pal("Logging to ~tp", [File]),
+ FullFile = lists:concat([File,".1"]),
+ _ = file_delete(FullFile),
+ ok = logger:add_handler(Name,
+ logger_disk_log_h,
+ #{config=>#{file => File,
+ max_no_files => 1,
+ max_no_bytes => 100000000},
+ filter_default=>log,
+ filters=>?DEFAULT_HANDLER_FILTERS([Name]),
+ formatter=>{?MODULE,op}}),
+ {ok,HConfig = #{config := DLHConfig}} = logger:get_handler_config(Name),
+ {FullFile,HConfig,DLHConfig}.
+
+stop_handler(Name) ->
+ ct:pal("Stopping handler ~p!", [Name]),
+ logger:remove_handler(Name).
+
+send_burst(NorT, Type, {chars,Sz}, Class) ->
+ Text = [34 + rand:uniform(126-34) || _ <- lists:seq(1,Sz)],
+ case NorT of
+ {n,N} ->
+ %% process_flag(priority, high),
+ send_n_burst(N, Type, Text, Class),
+ %% process_flag(priority, normal),
+ N;
+ {t,T} ->
+ ct:pal("Sending messages sequentially for ~w ms", [T]),
+ T0 = erlang:monotonic_time(millisecond),
+ send_t_burst(T0, T, Text, Class, 0)
+ end.
+
+send_n_burst(0, _, _Text, _Class) ->
+ ok;
+send_n_burst(N, seq, Text, Class) ->
+ ok = logger:Class(Text, ?domain),
+ send_n_burst(N-1, seq, Text, Class);
+send_n_burst(N, {spawn,Ps,TO}, Text, Class) ->
+ ct:pal("~w processes each sending ~w messages", [Ps,N]),
+ MRefs = [begin if TO == 0 -> ok; true -> timer:sleep(TO) end,
+ monitor(process,spawn_link(per_proc_fun(N,Text,Class,X)))
+ end || X <- lists:seq(1,Ps)],
+ lists:foreach(fun(MRef) ->
+ receive
+ {'DOWN', MRef, _, _, _} ->
+ ok
+ end
+ end, MRefs),
+ ct:pal("Message burst sent", []),
+ ok.
+
+send_t_burst(T0, T, Text, Class, N) ->
+ T1 = erlang:monotonic_time(millisecond),
+ if (T1-T0) > T ->
+ N;
+ true ->
+ ok = logger:Class(Text, ?domain),
+ send_t_burst(T0, T, Text, Class, N+1)
+ end.
+
+per_proc_fun(N,Text,Class,X) when X rem 2 == 0 ->
+ fun() ->
+ process_flag(priority,high),
+ send_n_burst(N, seq, Text, Class)
+ end;
+per_proc_fun(N,Text,Class,_) ->
+ fun() ->
+ send_n_burst(N, seq, Text, Class)
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Formatter callback
+%%% Using this to send the formatted string back to the test case
+%%% process - so it can check for logged events.
+format(_,bad_return) ->
+ bad_return;
+format(_,crash) ->
+ erlang:error(formatter_crashed);
+format(#{msg:={report,R},meta:=#{report_cb:=Fun}}=Log,Config) ->
+ format(Log#{msg=>Fun(R)},Config);
+format(#{msg:={string,String0}},no_nl) ->
+ String = unicode:characters_to_list(String0),
+ String;
+format(#{msg:={string,String0}},nl) ->
+ String = unicode:characters_to_list(String0),
+ String++"\n";
+format(#{msg:={string,String0}},op) ->
+ String = unicode:characters_to_list(String0),
+ String++"\n";
+format(#{msg:={report,#{label:={supervisor,progress}}}},op) ->
+ "";
+format(#{msg:={report,#{label:={gen_server,terminate}}}},op) ->
+ "";
+format(#{msg:={report,#{label:={proc_lib,crash}}}},op) ->
+ "";
+format(#{msg:={F,A}},OpOrPid) when is_list(F), is_list(A) ->
+ String = lists:flatten(io_lib:format(F,A)),
+ if is_pid(OpOrPid) -> OpOrPid ! {log,String};
+ true -> ok
+ end,
+ String++"\n";
+format(#{msg:={string,String0}},Pid) ->
+ String = unicode:characters_to_list(String0),
+ Pid ! {log,String},
+ String++"\n";
+format(Msg,Tag) ->
+ Error = {unexpected_format,Msg,Tag},
+ erlang:display(Error),
+ exit(Error).
+
+remove(Handler, LogName) ->
+ logger_disk_log_h:remove(Handler, LogName),
+ HState = #{log_names := Logs} = logger_disk_log_h:info(),
+ false = maps:is_key(LogName, HState),
+ false = lists:member(LogName, Logs),
+ false = logger_config:exist(?LOGGER_TABLE, LogName),
+ {error,no_such_log} = disk_log:info(LogName),
+ ok.
+
+start_and_add(Name, Config, LogOpts) ->
+ HConfig = maps:get(config, Config, #{}),
+ HConfig1 = maps:merge(HConfig, LogOpts),
+ Config1 = Config#{config=>HConfig1},
+ ct:pal("Adding handler ~w with: ~p", [Name,Config1]),
+ ok = logger:add_handler(Name, logger_disk_log_h, Config1),
+ Pid = whereis(h_proc_name(Name)),
+ true = is_pid(Pid),
+ Name = proplists:get_value(name, disk_log:info(Name)),
+ ok.
+
+remove_and_stop(Handler) ->
+ ok = logger:remove_handler(Handler),
+ timer:sleep(500),
+ undefined = whereis(h_proc_name(Handler)),
+ ok.
+
+try_read_file(FileName, Expected, Time) ->
+ try_read_file(FileName, Expected, Time, undefined).
+
+try_read_file(FileName, Expected, Time, _) when Time > 0 ->
+ case file:read_file(FileName) of
+ Expected ->
+ ok;
+ Error = {error,_Reason} ->
+ erlang:error(Error);
+ SomethingElse ->
+ ct:pal("try_read_file read unexpected: ~p~n", [SomethingElse]),
+ timer:sleep(500),
+ try_read_file(FileName, Expected, Time-500, SomethingElse)
+ end;
+
+try_read_file(_, _, _, Incorrect) ->
+ ct:pal("try_read_file got incorrect pattern: ~p~n", [Incorrect]),
+ erlang:error({error,not_matching_pattern,Incorrect}).
+
+try_match_file(FileName, Pattern, Time) ->
+ try_match_file(FileName, Pattern, Time, <<>>).
+
+try_match_file(FileName, Pattern, Time, _) when Time > 0 ->
+ case file:read_file(FileName) of
+ {ok, Bin} ->
+ case re:run(Bin,Pattern,[{capture,none}]) of
+ match ->
+ unicode:characters_to_list(Bin);
+ _ ->
+ timer:sleep(100),
+ try_match_file(FileName, Pattern, Time-100, Bin)
+ end;
+ Error ->
+ erlang:error(Error)
+ end;
+try_match_file(_,Pattern,_,Incorrect) ->
+ ct:pal("try_match_file did not match pattern: ~p~nGot: ~p~n",
+ [Pattern,Incorrect]),
+ erlang:error({error,not_matching_pattern,Pattern,Incorrect}).
+
+count_lines(File) ->
+ wait_until_written(File),
+ count_lines1(File).
+
+wait_until_written(File) ->
+ wait_until_written(File, -1).
+
+wait_until_written(File, Sz) ->
+ timer:sleep(2000),
+ case file:read_file_info(File) of
+ {ok,#file_info{size = Sz}} ->
+ timer:sleep(1000),
+ case file:read_file_info(File) of
+ {ok,#file_info{size = Sz}} ->
+ ok;
+ {ok,#file_info{size = Sz1}} ->
+ wait_until_written(File, Sz1)
+ end;
+ {ok,#file_info{size = Sz1}} ->
+ wait_until_written(File, Sz1)
+ end.
+
+count_lines1(File) ->
+ {_,Dev} = file:open(File, [read]),
+ Lines = count_lines2(Dev, 0),
+ file:close(Dev),
+ Lines.
+
+count_lines2(Dev, LC) ->
+ case file:read_line(Dev) of
+ {ok,"Handler logger_disk_log_h_SUITE " ++_} ->
+ %% Not counting handler info
+ count_lines2(Dev,LC);
+ {ok,_} ->
+ count_lines2(Dev,LC+1);
+ eof -> LC
+ end.
+
+repeat_until_ok(Fun, N) ->
+ repeat_until_ok(Fun, 0, N, undefined).
+
+repeat_until_ok(_Fun, Stop, Stop, Reason) ->
+ {fails,Reason};
+
+repeat_until_ok(Fun, C, Stop, FirstReason) ->
+ if C > 0 -> timer:sleep(5000);
+ true -> ok
+ end,
+ try Fun() of
+ Result ->
+ {ok,{C,Result}}
+ catch
+ _:Reason:Stack ->
+ ct:pal("Test fails: ~p (~p)~n", [Reason,hd(Stack)]),
+ if FirstReason == undefined ->
+ repeat_until_ok(Fun, C+1, Stop, {Reason,Stack});
+ true ->
+ repeat_until_ok(Fun, C+1, Stop, FirstReason)
+ end
+ end.
+
+start_tracer(Trace,Expected) ->
+ Pid = self(),
+ dbg:tracer(process,{fun tracer/2,{Pid,Expected}}),
+ dbg:p(h_proc_name(),[c]),
+ tpl(Trace),
+ ok.
+
+tpl([{M,F,A}|Trace]) ->
+ {ok,Match} = dbg:tpl(M,F,A,c),
+ case lists:keyfind(matched,1,Match) of
+ {_,_,1} ->
+ ok;
+ _ ->
+ dbg:stop_clear(),
+ throw({skip,"Can't trace "++atom_to_list(M)++":"++
+ atom_to_list(F)++"/"++integer_to_list(A)})
+ end,
+ tpl(Trace);
+tpl([]) ->
+ ok.
+
+tracer({trace,_,call,{logger_disk_log_h,handle_cast,[Op|_]},Caller},
+ {Pid,[{Mod,Func,Op}|Expected]}) ->
+ maybe_tracer_done(Pid,Expected,{Mod,Func,Op},Caller);
+tracer({trace,_,call,{Mod=disk_log,Func=blog,[_,Data]},Caller}, {Pid,[{Mod,Func,Data}|Expected]}) ->
+ maybe_tracer_done(Pid,Expected,{Mod,Func,Data},Caller);
+tracer({trace,_,call,{Mod,Func,_},Caller}, {Pid,[{Mod,Func}|Expected]}) ->
+ maybe_tracer_done(Pid,Expected,{Mod,Func},Caller);
+tracer({trace,_,call,Call,Caller}, {Pid,Expected}) ->
+ ct:log("Tracer got unexpected: ~p~nCaller: ~p~nExpected: ~p~n",[Call,Caller,Expected]),
+ Pid ! {tracer_got_unexpected,Call,Expected},
+ {Pid,Expected}.
+
+maybe_tracer_done(Pid,[],Got,Caller) ->
+ ct:log("Tracer got: ~p~nCaller: ~p~n",[Got,Caller]),
+ Pid ! tracer_done;
+maybe_tracer_done(Pid,Expected,Got,Caller) ->
+ ct:log("Tracer got: ~p~nCaller: ~p~n",[Got,Caller]),
+ {Pid,Expected}.
+
+check_tracer(T) ->
+ receive
+ tracer_done ->
+ dbg:stop_clear(),
+ ok;
+ {tracer_got_unexpected,Got,Expected} ->
+ dbg:stop_clear(),
+ ct:fail({tracer_got_unexpected,Got,Expected})
+ after T ->
+ dbg:stop_clear(),
+ ct:fail({timeout,tracer})
+ end.
+
+escape([$+|Rest]) ->
+ [$\\,$+|escape(Rest)];
+escape([H|T]) ->
+ [H|escape(T)];
+escape([]) ->
+ [].
+
+h_proc_name() ->
+ h_proc_name(?MODULE).
+h_proc_name(Name) ->
+ list_to_atom(lists:concat([logger_disk_log_h,"_",Name])).
+
+wait_for_process_up(T) ->
+ wait_for_process_up(?MODULE, h_proc_name(), T).
+
+wait_for_process_up(Name, RegName, T) ->
+ N = (T div 500) + 1,
+ wait_for_process_up1(Name, RegName, N).
+
+wait_for_process_up1(_Name, _RegName, 0) ->
+ error;
+wait_for_process_up1(Name, RegName, N) ->
+ timer:sleep(500),
+ case whereis(RegName) of
+ Pid when is_pid(Pid) ->
+ case logger:get_handler_config(Name) of
+ {ok,_} ->
+ %% ct:pal("Process ~p up (~p tries left)",[Name,N]),
+ {ok,Pid};
+ _ ->
+ wait_for_process_up1(Name, RegName, N-1)
+ end;
+ undefined ->
+ %% ct:pal("Waiting for process ~p (~p tries left)",[Name,N]),
+ wait_for_process_up1(Name, RegName, N-1)
+ end.
+
+file_delete(Log) ->
+ file:delete(Log).
diff --git a/lib/kernel/test/logger_env_var_SUITE.erl b/lib/kernel/test/logger_env_var_SUITE.erl
new file mode 100644
index 0000000000..e8d1a313dc
--- /dev/null
+++ b/lib/kernel/test/logger_env_var_SUITE.erl
@@ -0,0 +1,683 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_env_var_SUITE).
+
+-compile(export_all).
+
+-include_lib("kernel/include/logger.hrl").
+-include_lib("kernel/src/logger_internal.hrl").
+
+-import(logger_test_lib,[setup/2,log/3,sync_and_read/3]).
+
+suite() ->
+ [{timetrap,{seconds,60}},
+ {ct_hooks,[logger_test_lib]}].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+groups() ->
+ [{error_logger,[],[error_logger_tty,
+ error_logger_tty_sasl_compatible,
+ error_logger_false,
+ error_logger_false_progress,
+ error_logger_false_sasl_compatible,
+ error_logger_silent,
+ error_logger_silent_sasl_compatible,
+ error_logger_file]},
+ {logger,[],[logger_file,
+ logger_file_sasl_compatible,
+ logger_file_log_progress,
+ logger_file_no_filter,
+ logger_file_no_filter_level,
+ logger_file_formatter,
+ logger_filters,
+ logger_filters_stop,
+ logger_module_level,
+ logger_disk_log,
+ logger_disk_log_formatter,
+ logger_undefined,
+ logger_many_handlers_default_first,
+ logger_many_handlers_default_last,
+ logger_many_handlers_default_last_broken_filter
+ ]},
+ {bad,[],[bad_error_logger,
+ bad_level,
+ bad_sasl_compatibility]}].
+
+all() ->
+ [default,
+ default_sasl_compatible,
+ sasl_compatible_false,
+ sasl_compatible_false_no_progress,
+ sasl_compatible,
+ all_logger_level,
+ {group,bad},
+ {group,error_logger},
+ {group,logger}
+ ].
+
+default(Config) ->
+ {ok,#{primary:=P,handlers:=Hs,module_levels:=ML},_Node} = setup(Config,[]),
+ notice = maps:get(level,P),
+ #{module:=logger_std_h} = StdC = find(?STANDARD_HANDLER,Hs),
+ all = maps:get(level,StdC),
+ StdFilters = maps:get(filters,StdC),
+ {domain,{_,{log,super,[otp,sasl]}}} = lists:keyfind(domain,1,StdFilters),
+ false = exists(simple,Hs),
+ false = exists(sasl,Hs),
+ [] = ML,
+ ok.
+
+default_sasl_compatible(Config) ->
+ {ok,#{primary:=P,handlers:=Hs,module_levels:=ML},_Node} =
+ setup(Config,[{logger_sasl_compatible,true}]),
+ info = maps:get(level,P),
+ #{module:=logger_std_h} = StdC = find(?STANDARD_HANDLER,Hs),
+ all = maps:get(level,StdC),
+ StdFilters = maps:get(filters,StdC),
+ {domain,{_,{log,super,[otp]}}} = lists:keyfind(domain,1,StdFilters),
+ false = exists(simple,Hs),
+ true = exists(sasl,Hs),
+ [] = ML,
+ ok.
+
+error_logger_tty(Config) ->
+ {ok,#{primary:=P,handlers:=Hs,module_levels:=ML},_Node} =
+ setup(Config,[{error_logger,tty}]),
+ notice = maps:get(level,P),
+ #{module:=logger_std_h} = StdC = find(?STANDARD_HANDLER,Hs),
+ all = maps:get(level,StdC),
+ StdFilters = maps:get(filters,StdC),
+ {domain,{_,{log,super,[otp,sasl]}}} = lists:keyfind(domain,1,StdFilters),
+ false = exists(simple,Hs),
+ false = exists(sasl,Hs),
+ [] = ML,
+ ok.
+
+error_logger_tty_sasl_compatible(Config) ->
+ {ok,#{primary:=P,handlers:=Hs,module_levels:=ML},_Node} =
+ setup(Config,
+ [{error_logger,tty},
+ {logger_sasl_compatible,true}]),
+ info = maps:get(level,P),
+ #{module:=logger_std_h} = StdC = find(?STANDARD_HANDLER,Hs),
+ all = maps:get(level,StdC),
+ StdFilters = maps:get(filters,StdC),
+ {domain,{_,{log,super,[otp]}}} = lists:keyfind(domain,1,StdFilters),
+ false = exists(simple,Hs),
+ true = exists(sasl,Hs),
+ [] = ML,
+ ok.
+
+error_logger_false(Config) ->
+ {ok,#{handlers:=Hs,primary:=P,module_levels:=ML},_Node} =
+ setup(Config,
+ [{error_logger,false},
+ {logger_level,notice}]),
+ false = exists(?STANDARD_HANDLER,Hs),
+ #{module:=logger_simple_h} = SimpleC = find(simple,Hs),
+ all = maps:get(level,SimpleC),
+ notice = maps:get(level,P),
+ SimpleFilters = maps:get(filters,SimpleC),
+ {domain,{_,{log,super,[otp,sasl]}}} = lists:keyfind(domain,1,SimpleFilters),
+ false = exists(sasl,Hs),
+ [] = ML,
+ ok.
+
+error_logger_false_progress(Config) ->
+ {ok,#{handlers:=Hs,primary:=P,module_levels:=ML},_Node} =
+ setup(Config,
+ [{error_logger,false},
+ {logger_level,notice}]),
+ false = exists(?STANDARD_HANDLER,Hs),
+ #{module:=logger_simple_h} = SimpleC = find(simple,Hs),
+ all = maps:get(level,SimpleC),
+ notice = maps:get(level,P),
+ SimpleFilters = maps:get(filters,SimpleC),
+ {domain,{_,{log,super,[otp,sasl]}}} = lists:keyfind(domain,1,SimpleFilters),
+ false = exists(sasl,Hs),
+ [] = ML,
+ ok.
+
+error_logger_false_sasl_compatible(Config) ->
+ {ok,#{handlers:=Hs,primary:=P,module_levels:=ML},_Node} =
+ setup(Config,
+ [{error_logger,false},
+ {logger_level,notice},
+ {logger_sasl_compatible,true}]),
+ false = exists(?STANDARD_HANDLER,Hs),
+ #{module:=logger_simple_h} = SimpleC = find(simple,Hs),
+ all = maps:get(level,SimpleC),
+ info = maps:get(level,P),
+ SimpleFilters = maps:get(filters,SimpleC),
+ {domain,{_,{log,super,[otp]}}} = lists:keyfind(domain,1,SimpleFilters),
+ true = exists(sasl,Hs),
+ [] = ML,
+ ok.
+
+error_logger_silent(Config) ->
+ {ok,#{handlers:=Hs},_Node} = setup(Config,
+ [{error_logger,silent}]),
+ false = exists(?STANDARD_HANDLER,Hs),
+ false = exists(simple,Hs),
+ false = exists(sasl,Hs),
+ ok.
+
+error_logger_silent_sasl_compatible(Config) ->
+ {ok,#{handlers:=Hs},_Node} = setup(Config,
+ [{error_logger,silent},
+ {logger_sasl_compatible,true}]),
+ false = exists(?STANDARD_HANDLER,Hs),
+ false = exists(simple,Hs),
+ true = exists(sasl,Hs),
+ ok.
+
+
+error_logger_file(Config) ->
+ Log = file(Config,?FUNCTION_NAME),
+ {ok,_,Node} = setup(Config,
+ [{error_logger,{file,Log}}]),
+ check_default_log(Node,Log,
+ file,% dest
+ 0),% progress in std logger
+ ok.
+
+
+logger_file(Config) ->
+ Log = file(Config,?FUNCTION_NAME),
+ {ok,#{primary:=P,handlers:=Hs,module_levels:=ML},Node}
+ = setup(Config,
+ [{logger,
+ [{handler,?STANDARD_HANDLER,logger_std_h,
+ #{config=>#{type=>{file,Log}}}}]}]),
+ check_default_log(Node,Log,
+ file,% dest
+ 0),% progress in std logger
+
+ notice = maps:get(level,P),
+ #{module:=logger_std_h} = StdC = find(?STANDARD_HANDLER,Hs),
+ all = maps:get(level,StdC),
+ StdFilters = maps:get(filters,StdC),
+ {domain,{_,{log,super,[otp,sasl]}}} = lists:keyfind(domain,1,StdFilters),
+ false = exists(simple,Hs),
+ false = exists(sasl,Hs),
+ [] = ML,
+ ok.
+
+logger_file_sasl_compatible(Config) ->
+ Log = file(Config,?FUNCTION_NAME),
+ {ok,#{primary:=P,handlers:=Hs,module_levels:=ML},Node}
+ = setup(Config,
+ [{logger_sasl_compatible,true},
+ {logger,
+ [{handler,?STANDARD_HANDLER,logger_std_h,
+ #{config=>#{type=>{file,Log}}}}]}]),
+ check_default_log(Node,Log,
+ file,% dest
+ 0),% progress in std logger
+
+ info = maps:get(level,P),
+ #{module:=logger_std_h} = StdC = find(?STANDARD_HANDLER,Hs),
+ all = maps:get(level,StdC),
+ StdFilters = maps:get(filters,StdC),
+ {domain,{_,{log,super,[otp]}}} = lists:keyfind(domain,1,StdFilters),
+ false = exists(simple,Hs),
+ true = exists(sasl,Hs),
+ [] = ML,
+ ok.
+
+logger_file_log_progress(Config) ->
+ Log = file(Config,?FUNCTION_NAME),
+ {ok,#{primary:=P,handlers:=Hs,module_levels:=ML},Node}
+ = setup(Config,
+ [{logger_level,info},
+ {logger,
+ [{handler,?STANDARD_HANDLER,logger_std_h,
+ #{config=>#{type=>{file,Log}}}}]}]),
+ check_default_log(Node,Log,
+ file,% dest
+ 6,% progress in std logger
+ info),
+
+ info = maps:get(level,P),
+ #{module:=logger_std_h} = StdC = find(?STANDARD_HANDLER,Hs),
+ all = maps:get(level,StdC),
+ StdFilters = maps:get(filters,StdC),
+ {domain,{_,{log,super,[otp,sasl]}}} = lists:keyfind(domain,1,StdFilters),
+ false = exists(simple,Hs),
+ false = exists(sasl,Hs),
+ [] = ML,
+ ok.
+
+logger_file_no_filter(Config) ->
+ Log = file(Config,?FUNCTION_NAME),
+ {ok,#{handlers:=Hs},Node}
+ = setup(Config,
+ [{logger,
+ [{handler,?STANDARD_HANDLER,logger_std_h,
+ #{filter_default=>log,filters=>[],
+ config=>#{type=>{file,Log}}}}]}]),
+ check_default_log(Node,Log,
+ file,% dest
+ 6),% progress in std logger
+
+ #{module:=logger_std_h} = StdC = find(?STANDARD_HANDLER,Hs),
+ all = maps:get(level,StdC),
+ [] = maps:get(filters,StdC),
+ false = exists(simple,Hs),
+ false = exists(sasl,Hs),
+
+ ok.
+
+logger_file_no_filter_level(Config) ->
+ Log = file(Config,?FUNCTION_NAME),
+ {ok,#{handlers:=Hs},Node}
+ = setup(Config,
+ [{logger,
+ [{handler,?STANDARD_HANDLER,logger_std_h,
+ #{filters=>[],level=>error,
+ config=>#{type=>{file,Log}}}}]}]),
+ check_default_log(Node,Log,
+ file,% dest
+ 0,% progress in std logger
+ error),% level
+
+ #{module:=logger_std_h} = StdC = find(?STANDARD_HANDLER,Hs),
+ error = maps:get(level,StdC),
+ [] = maps:get(filters,StdC),
+ false = exists(simple,Hs),
+ false = exists(sasl,Hs),
+
+ ok.
+
+logger_file_formatter(Config) ->
+ Log = file(Config,?FUNCTION_NAME),
+ {ok,#{handlers:=Hs},Node}
+ = setup(Config,
+ [{logger,
+ [{handler,?STANDARD_HANDLER,logger_std_h,
+ #{filters=>[],
+ formatter=>{logger_formatter,#{}},
+ config=>#{type=>{file,Log}}}}]}]),
+ check_single_log(Node,Log,
+ file,% dest
+ 6),% progress in std logger
+
+ #{module:=logger_std_h} = StdC = find(?STANDARD_HANDLER,Hs),
+ all = maps:get(level,StdC),
+ [] = maps:get(filters,StdC),
+ false = exists(simple,Hs),
+ false = exists(sasl,Hs),
+
+ ok.
+
+logger_filters(Config) ->
+ Log = file(Config,?FUNCTION_NAME),
+ {ok,#{handlers:=Hs,primary:=P},Node}
+ = setup(Config,
+ [{logger_level,info},
+ {logger,
+ [{handler,?STANDARD_HANDLER,logger_std_h,
+ #{config=>#{type=>{file,Log}}}},
+ {filters,log,[{stop_progress,{fun logger_filters:progress/2,stop}}]}
+ ]}]),
+ check_default_log(Node,Log,
+ file,% dest
+ 0,% progress in std logger
+ info),
+
+ #{module:=logger_std_h} = StdC = find(?STANDARD_HANDLER,Hs),
+ all = maps:get(level,StdC),
+ StdFilters = maps:get(filters,StdC),
+ {domain,{_,{log,super,[otp,sasl]}}} = lists:keyfind(domain,1,StdFilters),
+ false = exists(simple,Hs),
+ false = exists(sasl,Hs),
+ LoggerFilters = maps:get(filters,P),
+ true = lists:keymember(stop_progress,1,LoggerFilters),
+
+ ok.
+
+logger_filters_stop(Config) ->
+ Log = file(Config,?FUNCTION_NAME),
+ {ok,#{handlers:=Hs,primary:=P},Node}
+ = setup(Config,
+ [{logger_level,info},
+ {logger,
+ [{handler,?STANDARD_HANDLER,logger_std_h,
+ #{filters=>[],
+ config=>#{type=>{file,Log}}}},
+ {filters,stop,[{log_error,{fun logger_filters:level/2,{log,gt,info}}}]}
+ ]}]),
+ check_default_log(Node,Log,
+ file,% dest
+ 0,% progress in std logger
+ info),
+
+ #{module:=logger_std_h} = StdC = find(?STANDARD_HANDLER,Hs),
+ all = maps:get(level,StdC),
+ [] = maps:get(filters,StdC),
+ false = exists(simple,Hs),
+ false = exists(sasl,Hs),
+ LoggerFilters = maps:get(filters,P),
+ true = lists:keymember(log_error,1,LoggerFilters),
+
+ ok.
+
+logger_module_level(Config) ->
+ Log = file(Config,?FUNCTION_NAME),
+ {ok,#{handlers:=Hs,module_levels:=ModuleLevels},Node}
+ = setup(Config,
+ [{logger_level,info},
+ {logger,
+ [{handler,?STANDARD_HANDLER,logger_std_h,
+ #{config=>#{type=>{file,Log}}}},
+ {module_level,error,[supervisor]}
+ ]}]),
+ check_default_log(Node,Log,
+ file,% dest
+ 3,% progress in std logger
+ info),
+
+ #{module:=logger_std_h} = StdC = find(?STANDARD_HANDLER,Hs),
+ all = maps:get(level,StdC),
+ StdFilters = maps:get(filters,StdC),
+ {domain,{_,{log,super,[otp,sasl]}}} = lists:keyfind(domain,1,StdFilters),
+ false = exists(simple,Hs),
+ false = exists(sasl,Hs),
+ [{supervisor,error}] = ModuleLevels,
+ ok.
+
+logger_disk_log(Config) ->
+ Log = file(Config,?FUNCTION_NAME),
+ {ok,#{handlers:=Hs},Node}
+ = setup(Config,
+ [{logger,
+ [{handler,?STANDARD_HANDLER,logger_disk_log_h,
+ #{config=>#{file=>Log}}}]}]),
+ check_default_log(Node,Log,
+ disk_log,% dest
+ 0),% progress in std logger
+
+ #{module:=logger_disk_log_h} = StdC = find(?STANDARD_HANDLER,Hs),
+ all = maps:get(level,StdC),
+ StdFilters = maps:get(filters,StdC),
+ {domain,{_,{log,super,[otp,sasl]}}} = lists:keyfind(domain,1,StdFilters),
+ false = exists(simple,Hs),
+ false = exists(sasl,Hs),
+
+ ok.
+
+logger_disk_log_formatter(Config) ->
+ Log = file(Config,?FUNCTION_NAME),
+ {ok,#{handlers:=Hs},Node}
+ = setup(Config,
+ [{logger,
+ [{handler,?STANDARD_HANDLER,logger_disk_log_h,
+ #{filters=>[],
+ formatter=>{logger_formatter,#{}},
+ config=>#{file=>Log}}}]}]),
+ check_single_log(Node,Log,
+ disk_log,% dest
+ 6),% progress in std logger
+
+ #{module:=logger_disk_log_h} = StdC = find(?STANDARD_HANDLER,Hs),
+ all = maps:get(level,StdC),
+ [] = maps:get(filters,StdC),
+ false = exists(simple,Hs),
+ false = exists(sasl,Hs),
+
+ ok.
+
+logger_undefined(Config) ->
+ {ok,#{handlers:=Hs,primary:=P},_Node} =
+ setup(Config,[{logger,[{handler,?STANDARD_HANDLER,undefined}]}]),
+ false = exists(?STANDARD_HANDLER,Hs),
+ #{module:=logger_simple_h} = SimpleC = find(simple,Hs),
+ all = maps:get(level,SimpleC),
+ notice = maps:get(level,P),
+ SimpleFilters = maps:get(filters,SimpleC),
+ {domain,{_,{log,super,[otp,sasl]}}} = lists:keyfind(domain,1,SimpleFilters),
+ false = exists(sasl,Hs),
+ ok.
+
+
+%% Test that we can add multiple handlers with the default first
+logger_many_handlers_default_first(Config) ->
+ LogErr = file(Config,logger_many_handlers_default_first_error),
+ LogInfo = file(Config,logger_many_handlers_default_first_info),
+
+ logger_many_handlers(
+ Config,[{logger,
+ [{handler,?STANDARD_HANDLER,logger_std_h,
+ #{level=>error,
+ filters=>[],
+ formatter=>{logger_formatter,#{}},
+ config=>#{type=>{file,LogErr}}}
+ },
+ {handler,info,logger_std_h,
+ #{level=>info,
+ filters=>[{level,{fun logger_filters:level/2,{stop,gteq,error}}}],
+ config=>#{type=>{file,LogInfo}}}
+ }
+ ]},
+ {logger_level,info}], LogErr, LogInfo, 6).
+
+%% Test that we can add multiple handlers with the default last
+logger_many_handlers_default_last(Config) ->
+ LogErr = file(Config,logger_many_handlers_default_last_error),
+ LogInfo = file(Config,logger_many_handlers_default_last_info),
+ logger_many_handlers(
+ Config,[{logger,
+ [{handler,info,logger_std_h,
+ #{level=>info,
+ filters=>[{level,{fun logger_filters:level/2,{stop,gteq,error}}}],
+ config=>#{type=>{file,LogInfo}}}
+ },
+ {handler,?STANDARD_HANDLER,logger_std_h,
+ #{level=>error,
+ filters=>[],
+ formatter=>{logger_formatter,#{}},
+ config=>#{type=>{file,LogErr}}}
+ }
+ ]},
+ {logger_level,info}], LogErr, LogInfo, 7).
+
+%% Check that we can handle that an added logger has a broken filter
+%% This used to cause a deadlock.
+logger_many_handlers_default_last_broken_filter(Config) ->
+ LogErr = file(Config,logger_many_handlers_default_first_broken_filter_error),
+ LogInfo = file(Config,logger_many_handlers_default_first_broken_filter_info),
+
+ logger_many_handlers(
+ Config,[{logger,
+ [{handler,info,logger_std_h,
+ #{level=>info,
+ filters=>[{broken,{fun logger_filters:level/2,broken_state}},
+ {level,{fun logger_filters:level/2,{stop,gteq,error}}}],
+ config=>#{type=>{file,LogInfo}}}
+ },
+ {handler,?STANDARD_HANDLER,logger_std_h,
+ #{level=>error,
+ filters=>[],
+ formatter=>{logger_formatter,#{}},
+ config=>#{type=>{file,LogErr}}}
+ }
+ ]},
+ {logger_level,info}], LogErr, LogInfo, 7).
+
+logger_many_handlers(Config, Env, LogErr, LogInfo, NumProgress) ->
+ {ok,_,Node} = setup(Config,Env),
+ check_single_log(Node,LogErr,
+ file,% dest
+ 0,% progress in std logger
+ error), % level
+ ok = rpc:call(Node,logger_std_h,filesync,[info]),
+ {ok, Bin} = file:read_file(LogInfo),
+ ct:log("Log content:~n~s",[Bin]),
+ match(Bin,<<"info:">>,NumProgress,info,info),
+ match(Bin,<<"notice:">>,1,notice,info),
+ match(Bin,<<"alert:">>,0,alert,info),
+
+ ok.
+
+sasl_compatible_false(Config) ->
+ Log = file(Config,?FUNCTION_NAME),
+ {ok,_,Node} = setup(Config,
+ [{error_logger,{file,Log}},
+ {logger_sasl_compatible,false},
+ {logger_level,info}]), % to get progress
+ check_default_log(Node,Log,
+ file,% dest
+ 6,% progress in std logger
+ info),
+ ok.
+
+sasl_compatible_false_no_progress(Config) ->
+ Log = file(Config,?FUNCTION_NAME),
+ {ok,_,Node} = setup(Config,
+ [{error_logger,{file,Log}},
+ {logger_sasl_compatible,false}]),
+ check_default_log(Node,Log,
+ file,% dest
+ 0),% progress in std logger
+ ok.
+
+sasl_compatible(Config) ->
+ Log = file(Config,?FUNCTION_NAME),
+ {ok,_,Node} = setup(Config,
+ [{error_logger,{file,Log}},
+ {sasl_compatible,true}]),
+ check_default_log(Node,Log,
+ file,% dest
+ 0),% progress in std logger
+ ok.
+
+all_logger_level(Config) ->
+ [all_logger_level(Config,Level) || Level <- [none,
+ emergency,
+ alert,
+ critical,
+ error,
+ warning,
+ notice,
+ info,
+ debug,
+ all]],
+ ok.
+
+all_logger_level(Config,Level) ->
+ {ok,#{primary:=#{level:=Level}},Node} = setup(Config,[{logger_level,Level}]),
+ true = test_server:stop_node(Node),
+ ok.
+
+bad_error_logger(Config) ->
+ error = setup(Config,[{error_logger,baddest}]).
+
+bad_level(Config) ->
+ error = setup(Config,[{logger_level,badlevel}]).
+
+bad_sasl_compatibility(Config) ->
+ error = setup(Config,[{logger_sasl_compatible,badcomp}]).
+
+%%%-----------------------------------------------------------------
+%%% Internal
+file(Config,Func) ->
+ filename:join(proplists:get_value(priv_dir,Config),
+ lists:concat([Func,".log"])).
+
+check_default_log(Node,Log,Dest,NumProgress) ->
+ check_default_log(Node,Log,Dest,NumProgress,notice).
+check_default_log(Node,Log,Dest,NumProgress,Level) ->
+
+ {ok,Bin1,Bin2} = check_log(Node,Log,Dest),
+
+ match(Bin1,<<"PROGRESS REPORT">>,NumProgress,info,Level),
+ match(Bin1,<<"ALERT REPORT">>,1,alert,Level),
+ match(Bin1,<<"INFO REPORT">>,0,notice,Level),
+ match(Bin1,<<"DEBUG REPORT">>,0,debug,Level),
+
+ match(Bin2,<<"INFO REPORT">>,1,notice,Level),
+ match(Bin2,<<"DEBUG REPORT">>,0,debug,Level),
+ ok.
+
+check_single_log(Node,Log,Dest,NumProgress) ->
+ check_single_log(Node,Log,Dest,NumProgress,notice).
+check_single_log(Node,Log,Dest,NumProgress,Level) ->
+
+ {ok,Bin1,Bin2} = check_log(Node,Log,Dest),
+
+ match(Bin1,<<"info:">>,NumProgress,info,Level),
+ match(Bin1,<<"alert:">>,1,alert,Level),
+ match(Bin1,<<"debug:">>,0,debug,Level),
+
+ match(Bin2,<<"info:">>,NumProgress+1,info,Level),
+ match(Bin2,<<"debug:">>,0,debug,Level),
+
+ ok.
+
+check_log(Node,Log,Dest) ->
+
+ ok = log(Node,alert,["dummy1"]),
+ ok = log(Node,debug,["dummy1"]),
+
+ %% Check that there are progress reports (supervisor and
+ %% application_controller) and an error report (the call above) in
+ %% the log. There should not be any info reports yet.
+ {ok,Bin1} = sync_and_read(Node,Dest,Log),
+ ct:log("Log content:~n~s",[Bin1]),
+
+ %% Then stop sasl and see that the info report from
+ %% application_controller is there
+ ok = rpc:call(Node,application,stop,[sasl]),
+ {ok,Bin2} = sync_and_read(Node,Dest,Log),
+ ct:log("Log content:~n~s",[Bin2]),
+ {ok,Bin1,Bin2}.
+
+match(Bin,Pattern,0,_,_) ->
+ nomatch = re:run(Bin,Pattern,[{capture,none}]);
+match(Bin,Pattern,N,LogLevel,ConfLevel) ->
+ case logger:compare_levels(LogLevel,ConfLevel) of
+ lt -> match(Bin,Pattern,0,LogLevel,ConfLevel);
+ _ ->
+ {match,M} = re:run(Bin,Pattern,[{capture,all},global]),
+ N = length(M)
+ end.
+
+find(Id,Handlers) ->
+ case lists:search(fun(#{id:=Id0}) when Id0=:=Id-> true;
+ (_) -> false end,
+ Handlers) of
+ {value,Config} ->
+ Config;
+ false ->
+ false
+ end.
+
+exists(Id,Handlers) ->
+ case find(Id,Handlers) of
+ false ->
+ false;
+ _ ->
+ true
+ end.
diff --git a/lib/kernel/test/logger_filters_SUITE.erl b/lib/kernel/test/logger_filters_SUITE.erl
new file mode 100644
index 0000000000..11cce8fd20
--- /dev/null
+++ b/lib/kernel/test/logger_filters_SUITE.erl
@@ -0,0 +1,227 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_filters_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("kernel/include/logger.hrl").
+
+-define(ndlog,
+ #{level=>info,msg=>{"Line: ~p",[?LINE]},meta=>#{}}).
+-define(dlog(Domain),
+ #{level=>info,msg=>{"Line: ~p",[?LINE]},meta=>#{domain=>Domain}}).
+-define(llog(Level),
+ #{level=>Level,msg=>{"Line: ~p",[?LINE]},meta=>#{}}).
+-define(plog,
+ #{level=>info,
+ msg=>{report,#{label=>{?MODULE,progress}}},
+ meta=>#{line=>?LINE}}).
+-define(rlog(Node),
+ #{level=>info,
+ msg=>{"Line: ~p",[?LINE]},
+ meta=>#{gl=>rpc:call(Node,erlang,whereis,[user])}}).
+
+-define(TRY(X), my_try(fun() -> X end)).
+
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_Group, Config) ->
+ Config.
+
+end_per_group(_Group, _Config) ->
+ ok.
+
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+end_per_testcase(Case, Config) ->
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
+ ok.
+
+groups() ->
+ [].
+
+all() ->
+ [domain,
+ level,
+ progress,
+ remote_gl].
+
+domain(_Config) ->
+ L1 = logger_filters:domain(L1=?dlog([]),{log,super,[]}),
+ stop = logger_filters:domain(?dlog([]),{stop,super,[]}),
+ L2 = logger_filters:domain(L2=?dlog([]),{log,sub,[]}),
+ stop = logger_filters:domain(?dlog([]),{stop,sub,[]}),
+ L3 = logger_filters:domain(L3=?dlog([]),{log,equal,[]}),
+ stop = logger_filters:domain(?dlog([]),{stop,equal,[]}),
+ ignore = logger_filters:domain(?dlog([]),{log,not_equal,[]}),
+ ignore = logger_filters:domain(?dlog([]),{stop,not_equal,[]}),
+ ignore = logger_filters:domain(?dlog([]),{log,undefined,[]}),
+ ignore = logger_filters:domain(?dlog([]),{stop,undefined,[]}),
+
+ L4 = logger_filters:domain(L4=?dlog([a]),{log,super,[a,b]}),
+ stop = logger_filters:domain(?dlog([a]),{stop,super,[a,b]}),
+ ignore = logger_filters:domain(?dlog([a]),{log,sub,[a,b]}),
+ ignore = logger_filters:domain(?dlog([a]),{stop,sub,[a,b]}),
+ ignore = logger_filters:domain(?dlog([a]),{log,equal,[a,b]}),
+ ignore = logger_filters:domain(?dlog([a]),{stop,equal,[a,b]}),
+ L5 = logger_filters:domain(L5=?dlog([a]),{log,not_equal,[a,b]}),
+ stop = logger_filters:domain(?dlog([a]),{stop,not_equal,[a,b]}),
+ ignore = logger_filters:domain(?dlog([a]),{log,undefined,[a,b]}),
+ ignore = logger_filters:domain(?dlog([a]),{stop,undefined,[a,b]}),
+
+ ignore = logger_filters:domain(?dlog([a,b]),{log,super,[a]}),
+ ignore = logger_filters:domain(?dlog([a,b]),{stop,super,[a]}),
+ L6 = logger_filters:domain(L6=?dlog([a,b]),{log,sub,[a]}),
+ stop = logger_filters:domain(?dlog([a,b]),{stop,sub,[a]}),
+ ignore = logger_filters:domain(?dlog([a,b]),{log,equal,[a]}),
+ ignore = logger_filters:domain(?dlog([a,b]),{stop,equal,[a]}),
+ L7 = logger_filters:domain(L7=?dlog([a,b]),{log,not_equal,[a]}),
+ stop = logger_filters:domain(?dlog([a,b]),{stop,not_equal,[a]}),
+ ignore = logger_filters:domain(?dlog([a,b]),{log,undefined,[a]}),
+ ignore = logger_filters:domain(?dlog([a,b]),{stop,undefined,[a]}),
+
+ ignore = logger_filters:domain(?ndlog,{log,super,[a]}),
+ ignore = logger_filters:domain(?ndlog,{stop,super,[a]}),
+ ignore = logger_filters:domain(?ndlog,{log,sub,[a]}),
+ ignore = logger_filters:domain(?ndlog,{stop,sub,[a]}),
+ ignore = logger_filters:domain(?ndlog,{log,equal,[a]}),
+ ignore = logger_filters:domain(?ndlog,{stop,equal,[a]}),
+ L8 = logger_filters:domain(L8=?ndlog,{log,not_equal,[a]}),
+ stop = logger_filters:domain(?ndlog,{stop,not_equal,[a]}),
+ L9 = logger_filters:domain(L9=?ndlog,{log,undefined,[a]}),
+ stop = logger_filters:domain(?ndlog,{stop,undefined,[a]}),
+
+ L10 = logger_filters:domain(L10=?dlog([a,b,c,d]),{log,super,[a,b,c,d]}),
+ stop = logger_filters:domain(?dlog([a,b,c,d]),{stop,super,[a,b,c,d]}),
+ L11 = logger_filters:domain(L11=?dlog([a,b,c,d]),{log,sub,[a,b,c,d]}),
+ stop = logger_filters:domain(?dlog([a,b,c,d]),{stop,sub,[a,b,c,d]}),
+ L12 = logger_filters:domain(L12=?dlog([a,b,c,d]),{log,equal,[a,b,c,d]}),
+ stop = logger_filters:domain(?dlog([a,b,c,d]),{stop,equal,[a,b,c,d]}),
+ ignore = logger_filters:domain(?dlog([a,b,c,d]),{log,not_equal,[a,b,c,d]}),
+ ignore = logger_filters:domain(?dlog([a,b,c,d]),{stop,not_equal,[a,b,c,d]}),
+ ignore = logger_filters:domain(?dlog([a,b,c,d]),{log,undefined,[a,b,c,d]}),
+ ignore = logger_filters:domain(?dlog([a,b,c,d]),{stop,undefined,[a,b,c,d]}),
+
+ %% A domain field in meta which is not a list is allowed by the
+ %% filter, but since MatchDomain is always a list of atoms, only
+ %% Action=not_equal can ever match.
+ ignore = logger_filters:domain(?dlog(dummy),{log,super,[a,b,c,d]}),
+ ignore = logger_filters:domain(?dlog(dummy),{stop,super,[a,b,c,d]}),
+ ignore = logger_filters:domain(?dlog(dummy),{log,sub,[a,b,c,d]}),
+ ignore = logger_filters:domain(?dlog(dummy),{stop,sub,[a,b,c,d]}),
+ ignore = logger_filters:domain(?dlog(dummy),{log,equal,[a,b,c,d]}),
+ ignore = logger_filters:domain(?dlog(dummy),{stop,equal,[a,b,c,d]}),
+ L13 = logger_filters:domain(L13=?dlog(dummy),{log,not_equal,[a,b,c,d]}),
+ stop = logger_filters:domain(?dlog(dummy),{stop,not_equal,[a,b,c,d]}),
+ ignore = logger_filters:domain(?dlog(dummy),{log,undefined,[a,b,c,d]}),
+ ignore = logger_filters:domain(?dlog(dummy),{stop,undefined,[a,b,c,d]}),
+
+ {error,badarg} = ?TRY(logger_filters:domain(?ndlog,bad)),
+ {error,badarg} = ?TRY(logger_filters:domain(?ndlog,{bad,super,[]})),
+ {error,badarg} = ?TRY(logger_filters:domain(?ndlog,{log,bad,[]})),
+ {error,badarg} = ?TRY(logger_filters:domain(?ndlog,{log,super,bad})),
+
+ ok.
+
+level(_Config) ->
+ ignore = logger_filters:level(?llog(info),{log,lt,info}),
+ ignore = logger_filters:level(?llog(info),{stop,lt,info}),
+ ignore = logger_filters:level(?llog(info),{log,gt,info}),
+ ignore = logger_filters:level(?llog(info),{stop,gt,info}),
+ L1 = logger_filters:level(L1=?llog(info),{log,lteq,info}),
+ stop = logger_filters:level(?llog(info),{stop,lteq,info}),
+ L2 = logger_filters:level(L2=?llog(info),{log,gteq,info}),
+ stop = logger_filters:level(?llog(info),{stop,gteq,info}),
+ L3 = logger_filters:level(L3=?llog(info),{log,eq,info}),
+ stop = logger_filters:level(?llog(info),{stop,eq,info}),
+ ignore = logger_filters:level(?llog(info),{log,neq,info}),
+ ignore = logger_filters:level(?llog(info),{stop,neq,info}),
+
+ ignore = logger_filters:level(?llog(error),{log,lt,info}),
+ ignore = logger_filters:level(?llog(error),{stop,lt,info}),
+ L4 = logger_filters:level(L4=?llog(error),{log,gt,info}),
+ stop = logger_filters:level(?llog(error),{stop,gt,info}),
+ ignore = logger_filters:level(?llog(error),{log,lteq,info}),
+ ignore = logger_filters:level(?llog(error),{stop,lteq,info}),
+ L5 = logger_filters:level(L5=?llog(error),{log,gteq,info}),
+ stop = logger_filters:level(?llog(error),{stop,gteq,info}),
+ ignore = logger_filters:level(?llog(error),{log,eq,info}),
+ ignore = logger_filters:level(?llog(error),{stop,eq,info}),
+ L6 = logger_filters:level(L6=?llog(error),{log,neq,info}),
+ stop = logger_filters:level(?llog(error),{stop,neq,info}),
+
+ L7 = logger_filters:level(L7=?llog(info),{log,lt,error}),
+ stop = logger_filters:level(?llog(info),{stop,lt,error}),
+ ignore = logger_filters:level(?llog(info),{log,gt,error}),
+ ignore = logger_filters:level(?llog(info),{stop,gt,error}),
+ L8 = logger_filters:level(L8=?llog(info),{log,lteq,error}),
+ stop = logger_filters:level(?llog(info),{stop,lteq,error}),
+ ignore = logger_filters:level(?llog(info),{log,gteq,error}),
+ ignore = logger_filters:level(?llog(info),{stop,gteq,error}),
+ ignore = logger_filters:level(?llog(info),{log,eq,error}),
+ ignore = logger_filters:level(?llog(info),{stop,eq,error}),
+ L9 = logger_filters:level(L9=?llog(info),{log,neq,error}),
+ stop = logger_filters:level(?llog(info),{stop,neq,error}),
+
+ {error,badarg} = ?TRY(logger_filters:level(?llog(info),bad)),
+ {error,badarg} = ?TRY(logger_filters:level(?llog(info),{bad,eq,info})),
+ {error,badarg} = ?TRY(logger_filters:level(?llog(info),{log,bad,info})),
+ {error,badarg} = ?TRY(logger_filters:level(?llog(info),{log,eq,bad})),
+
+ ok.
+
+progress(_Config) ->
+ L1 = logger_filters:progress(L1=?plog,log),
+ stop = logger_filters:progress(?plog,stop),
+ ignore = logger_filters:progress(?ndlog,log),
+ ignore = logger_filters:progress(?ndlog,stop),
+
+ {error,badarg} = ?TRY(logger_filters:progress(?plog,bad)),
+
+ ok.
+
+remote_gl(_Config) ->
+ {ok,Node} = test_server:start_node(?FUNCTION_NAME,slave,[]),
+ L1 = logger_filters:remote_gl(L1=?rlog(Node),log),
+ stop = logger_filters:remote_gl(?rlog(Node),stop),
+ ignore = logger_filters:remote_gl(?ndlog,log),
+ ignore = logger_filters:remote_gl(?ndlog,stop),
+
+ {error,badarg} = ?TRY(logger_filters:remote_gl(?rlog(Node),bad)),
+ ok.
+
+remote_gl(cleanup,_Config) ->
+ [test_server:stop_node(N) || N<-nodes()].
+
+%%%-----------------------------------------------------------------
+%%% Called by macro ?TRY(X)
+my_try(Fun) ->
+ try Fun() catch C:R -> {C,R} end.
diff --git a/lib/kernel/test/logger_formatter_SUITE.erl b/lib/kernel/test/logger_formatter_SUITE.erl
new file mode 100644
index 0000000000..8c13f0f908
--- /dev/null
+++ b/lib/kernel/test/logger_formatter_SUITE.erl
@@ -0,0 +1,886 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_formatter_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("kernel/include/logger.hrl").
+
+-define(TRY(X), my_try(fun() -> X end)).
+
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_Group, Config) ->
+ Config.
+
+end_per_group(_Group, _Config) ->
+ ok.
+
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+end_per_testcase(Case, Config) ->
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
+ ok.
+
+groups() ->
+ [].
+
+all() ->
+ [default,
+ legacy_header,
+ error_logger_notice_header,
+ single_line,
+ template,
+ format_msg,
+ report_cb,
+ max_size,
+ depth,
+ chars_limit,
+ format_mfa,
+ format_time,
+ level_or_msg_in_meta,
+ faulty_log,
+ faulty_config,
+ faulty_msg,
+ check_config,
+ update_config].
+
+default(_Config) ->
+ String1 = format(info,{"~p",[term]},#{},#{}),
+ ct:log(String1),
+ [_DateTime,"info:","term\n"] = string:lexemes(String1," "),
+
+ Time = timestamp(),
+ ExpectedTimestamp = default_time_format(Time),
+ String2 = format(info,{"~p",[term]},#{time=>Time},#{}),
+ ct:log(String2),
+ " info: term\n" = string:prefix(String2,ExpectedTimestamp),
+ ok.
+
+legacy_header(_Config) ->
+ Time = timestamp(),
+ String1 = format(info,{"~p",[term]},#{time=>Time},#{legacy_header=>true,
+ single_line=>false}),
+ ct:log(String1),
+ "=INFO REPORT==== "++Rest = String1,
+ [Timestamp,"\nterm\n"] = string:lexemes(Rest," ="),
+ [D,M,Y,H,Min,S,Micro] = string:lexemes(Timestamp,"-:."),
+ integer(D,31),
+ integer(Y,2018,infinity),
+ integer(H,23),
+ integer(Min,59),
+ integer(S,59),
+ integer(Micro,999999),
+ true = lists:member(M,["Jan","Feb","Mar","Apr","May","Jun",
+ "Jul","Aug","Sep","Oct","Nov","Dec"]),
+
+ String2 = format(info,{"~p",[term]},#{time=>Time},#{legacy_header=>false,
+ single_line=>false}),
+ ct:log(String2),
+ ExpectedTimestamp = default_time_format(Time),
+ " info:\nterm\n" = string:prefix(String2,ExpectedTimestamp),
+
+ String3 = format(info,{"~p",[term]},#{time=>Time},#{legacy_header=>bad,
+ single_line=>false}),
+ ct:log(String3),
+ String3 = String2,
+
+ String4 = format(info,{"~p",[term]},#{time=>Time},
+ #{legacy_header=>true,
+ single_line=>true}), % <---ignored
+ ct:log(String4),
+ String4 = String1,
+
+ String5 = format(info,{"~p",[term]},#{}, % <--- no time
+ #{legacy_header=>true,
+ single_line=>false}),
+ ct:log(String5),
+ "=INFO REPORT==== "++_ = String5,
+ ok.
+
+error_logger_notice_header(_Config) ->
+ Meta1 = #{error_logger=>#{tag => info_report,type => std_info}},
+ String1 = format(notice,{"~p",[term]},Meta1,
+ #{legacy_header=>true,
+ error_logger_notice_header=>notice}),
+ ct:log(String1),
+ "=NOTICE REPORT==== "++_ = String1,
+
+ String2 = format(notice,{"~p",[term]},Meta1,
+ #{legacy_header=>true,
+ error_logger_notice_header=>info}),
+ ct:log(String2),
+ "=INFO REPORT==== "++_ = String2,
+
+ String3 = format(notice,{"~p",[term]},#{},
+ #{legacy_header=>true,
+ error_logger_notice_header=>notice}),
+ ct:log(String3),
+ "=NOTICE REPORT==== "++_ = String3,
+
+ String4 = format(notice,{"~p",[term]},#{},
+ #{legacy_header=>true,
+ error_logger_notice_header=>info}),
+ ct:log(String4),
+ "=NOTICE REPORT==== "++_ = String4,
+
+ ok.
+
+single_line(_Config) ->
+ Time = timestamp(),
+ ExpectedTimestamp = default_time_format(Time),
+ String1 = format(info,{"~p",[term]},#{time=>Time},#{single_line=>true}),
+ ct:log(String1),
+ " info: term\n" = string:prefix(String1,ExpectedTimestamp),
+
+ String2 = format(info,{"~p",[term]},#{time=>Time},#{single_line=>false}),
+ ct:log(String2),
+ " info:\nterm\n" = string:prefix(String2,ExpectedTimestamp),
+
+ String2 = format(info,{"~p",[term]},#{time=>Time},#{single_line=>bad}),
+
+
+ %% Test that no extra commas/spaces are added when removing
+ %% newlines, especially not after "=>" in a map association (as
+ %% was the case in OTP-21.0, when the only single_line adjustment
+ %% was done by regexp replacement of "\n" by ", ").
+ Prefix =
+ "Some characters to fill the line ------------------------------------- ",
+ String3 = format(info,{"~s~p~n~s~p~n",[Prefix,
+ lists:seq(1,10),
+ Prefix,
+ #{a=>map,with=>a,few=>accociations}]},
+ #{time=>Time},
+ #{single_line=>true}),
+ ct:log(String3),
+ match = re:run(String3,"\\[1,2,3,4,5,6,7,8,9,10\\]",[{capture,none}]),
+ match = re:run(String3,
+ "#{a => map,few => accociations,with => a}",
+ [{capture,none}]),
+
+ %% This part is added to make sure that the previous test made
+ %% sense, i.e. that there would actually be newlines inside the
+ %% list and map.
+ String4 = format(info,{"~s~p~n~s~p~n",[Prefix,
+ lists:seq(1,10),
+ Prefix,
+ #{a=>map,with=>a,few=>accociations}]},
+ #{time=>Time},
+ #{single_line=>false}),
+ ct:log(String4),
+ match = re:run(String4,"\\[1,2,3,\n",[global,{capture,none}]),
+ {match,Match4} = re:run(String4,"=>\n",[global,{capture,all}]),
+ 3 = length(Match4),
+
+ %% Test that big metadata fields do not get line breaks
+ String5 = format(info,"",
+ #{mymeta=>lists:seq(1,100)},
+ #{single_line=>true,template=>[mymeta,"\n"]}),
+ ct:log(String5),
+ [_] = string:lexemes(String5,"\n"),
+
+ %% Ensure that the previous test made sense, i.e. that the
+ %% metadata field does produce multiple lines if
+ %% single_line==false.
+ String6 = format(info,"",
+ #{mymeta=>lists:seq(1,100)},
+ #{single_line=>false,template=>[mymeta,"\n"]}),
+ ct:log(String6),
+ [_,_|_] = string:lexemes(String6,"\n"),
+
+ ok.
+
+template(_Config) ->
+ Time = timestamp(),
+
+ Template1 = [msg],
+ String1 = format(info,{"~p",[term]},#{time=>Time},#{template=>Template1}),
+ ct:log(String1),
+ "term" = String1,
+
+ Template2 = [msg,unknown],
+ String2 = format(info,{"~p",[term]},#{time=>Time},#{template=>Template2}),
+ ct:log(String2),
+ "term" = String2,
+
+ Template3 = ["string"],
+ String3 = format(info,{"~p",[term]},#{time=>Time},#{template=>Template3}),
+ ct:log(String3),
+ "string" = String3,
+
+ Template4 = ["string\nnewline"],
+ String4 = format(info,{"~p",[term]},#{time=>Time},#{template=>Template4,
+ single_line=>true}),
+ ct:log(String4),
+ "string\nnewline" = String4,
+
+ Template5 = [],
+ String5 = format(info,{"~p",[term]},#{time=>Time},#{template=>Template5}),
+ ct:log(String5),
+ "" = String5,
+
+ Ref6 = erlang:make_ref(),
+ Meta6 = #{atom=>some_atom,
+ integer=>632,
+ list=>[list,"string",4321,#{},{tuple}],
+ mfa=>{mod,func,0},
+ pid=>self(),
+ ref=>Ref6,
+ string=>"some string",
+ time=>Time,
+ tuple=>{1,atom,"list"},
+ nested=>#{subkey=>subvalue}},
+ Template6 = lists:join(";",lists:sort(maps:keys(maps:remove(nested,Meta6))) ++
+ [[nested,subkey]]),
+ String6 = format(info,{"~p",[term]},Meta6,#{template=>Template6,
+ single_line=>true}),
+ ct:log(String6),
+ SelfStr = pid_to_list(self()),
+ RefStr6 = ref_to_list(Ref6),
+ ListStr = "[list,\"string\",4321,#{},{tuple}]",
+ ExpectedTime6 = default_time_format(Time),
+ ["some_atom",
+ "632",
+ ListStr,
+ "mod:func/0",
+ SelfStr,
+ RefStr6,
+ "some string",
+ ExpectedTime6,
+ "{1,atom,\"list\"}",
+ "subvalue"] = string:lexemes(String6,";"),
+
+ Meta7 = #{time=>Time,
+ nested=>#{key1=>#{subkey1=>value1},
+ key2=>value2}},
+ Template7 = lists:join(";",[nested,
+ [nested,key1],
+ [nested,key1,subkey1],
+ [nested,key2],
+ [nested,key2,subkey2],
+ [nested,key3],
+ [nested,key3,subkey3]]),
+ String7 = format(info,{"~p",[term]},Meta7,#{template=>Template7,
+ single_line=>true}),
+ ct:log(String7),
+ [MultipleKeysStr7,
+ "#{subkey1 => value1}",
+ "value1",
+ "value2",
+ "",
+ "",
+ ""] = string:split(String7,";",all),
+ %% Order of keys is not fixed
+ case MultipleKeysStr7 of
+ "#{key2 => value2,key1 => #{subkey1 => value1}}" -> ok;
+ "#{key1 => #{subkey1 => value1},key2 => value2}" -> ok;
+ _ -> ct:fail({full_nested_map_unexpected,MultipleKeysStr7})
+ end,
+
+ Meta8 = #{time=>Time,
+ nested=>#{key1=>#{subkey1=>value1},
+ key2=>value2}},
+ Template8 =
+ lists:join(
+ ";",
+ [{nested,["exist:",nested],["noexist"]},
+ {[nested,key1],["exist:",[nested,key1]],["noexist"]},
+ {[nested,key1,subkey1],["exist:",[nested,key1,subkey1]],["noexist"]},
+ {[nested,key2],["exist:",[nested,key2]],["noexist"]},
+ {[nested,key2,subkey2],["exist:",[nested,key2,subkey2]],["noexist"]},
+ {[nested,key3],["exist:",[nested,key3]],["noexist"]},
+ {[nested,key3,subkey3],["exist:",[nested,key3,subkey3]],["noexist"]}]),
+ String8 = format(info,{"~p",[term]},Meta8,#{template=>Template8,
+ single_line=>true}),
+ ct:log(String8),
+ [MultipleKeysStr8,
+ "exist:#{subkey1 => value1}",
+ "exist:value1",
+ "exist:value2",
+ "noexist",
+ "noexist",
+ "noexist"] = string:split(String8,";",all),
+ %% Order of keys is not fixed
+ case MultipleKeysStr8 of
+ "exist:#{key2 => value2,key1 => #{subkey1 => value1}}" -> ok;
+ "exist:#{key1 => #{subkey1 => value1},key2 => value2}" -> ok;
+ _ -> ct:fail({full_nested_map_unexpected,MultipleKeysStr8})
+ end,
+
+ ok.
+
+format_msg(_Config) ->
+ Template = [msg],
+
+ String1 = format(info,{"~p",[term]},#{},#{template=>Template}),
+ ct:log(String1),
+ "term" = String1,
+
+ String2 = format(info,{"list",[term]},#{},#{template=>Template}),
+ ct:log(String2),
+ "FORMAT ERROR: \"list\" - [term]" = String2,
+
+ String3 = format(info,{report,term},#{},#{template=>Template}),
+ ct:log(String3),
+ "term" = String3,
+
+ String4 = format(info,{report,term},
+ #{report_cb=>fun(_)-> {"formatted",[]} end},
+ #{template=>Template}),
+ ct:log(String4),
+ "formatted" = String4,
+
+ String5 = format(info,{report,term},
+ #{report_cb=>fun(_)-> faulty_return end},
+ #{template=>Template}),
+ ct:log(String5),
+ "REPORT_CB/1 ERROR: term; Returned: faulty_return" = String5,
+
+ String6 = format(info,{report,term},
+ #{report_cb=>fun(_)-> erlang:error(fun_crashed) end},
+ #{template=>Template}),
+ ct:log(String6),
+ "REPORT_CB/1 CRASH: term; Reason: {error,fun_crashed,"++_ = String6,
+
+ String7 = format(info,{report,term},
+ #{report_cb=>fun(_,_)-> ['not',a,string] end},
+ #{template=>Template}),
+ ct:log(String7),
+ "REPORT_CB/2 ERROR: term; Returned: ['not',a,string]" = String7,
+
+ String8 = format(info,{report,term},
+ #{report_cb=>fun(_,_)-> faulty_return end},
+ #{template=>Template}),
+ ct:log(String8),
+ "REPORT_CB/2 ERROR: term; Returned: faulty_return" = String8,
+
+ String9 = format(info,{report,term},
+ #{report_cb=>fun(_,_)-> erlang:error(fun_crashed) end},
+ #{template=>Template}),
+ ct:log(String9),
+ "REPORT_CB/2 CRASH: term; Reason: {error,fun_crashed,"++_ = String9,
+
+ %% strings are not formatted
+ String10 = format(info,{string,"string"},
+ #{report_cb=>fun(_)-> {"formatted",[]} end},
+ #{template=>Template}),
+ ct:log(String10),
+ "string" = String10,
+
+ String11 = format(info,{string,['not',printable,list]},
+ #{report_cb=>fun(_)-> {"formatted",[]} end},
+ #{template=>Template}),
+ ct:log("~ts",[String11]), % avoiding ct_log crash
+ "FORMAT ERROR: \"~ts\" - [['not',printable,list]]" = String11,
+
+ String12 = format(info,{string,"string"},#{},#{template=>Template}),
+ ct:log(String12),
+ "string" = String12,
+
+ ok.
+
+report_cb(_Config) ->
+ Template = [msg],
+ MetaFun = fun(_) -> {"meta_rcb",[]} end,
+ ConfigFun = fun(_) -> {"config_rcb",[]} end,
+ "term" = format(info,{report,term},#{},#{template=>Template}),
+ "meta_rcb" =
+ format(info,{report,term},#{report_cb=>MetaFun},#{template=>Template}),
+ "config_rcb" =
+ format(info,{report,term},#{},#{template=>Template,
+ report_cb=>ConfigFun}),
+ "config_rcb" =
+ format(info,{report,term},#{report_cb=>MetaFun},#{template=>Template,
+ report_cb=>ConfigFun}),
+ ok.
+
+max_size(_Config) ->
+ Cfg = #{template=>[msg],
+ single_line=>false},
+ "12345678901234567890" =
+ format(info,{"12345678901234567890",[]},#{},Cfg),
+ %% application:set_env(kernel,logger_max_size,11),
+ %% "12345678901234567890" = % min value is 50, so this is not limited
+ %% format(info,{"12345678901234567890",[]},#{},Cfg),
+ %% "12345678901234567890123456789012345678901234567..." = % 50
+ %% format(info,
+ %% {"123456789012345678901234567890123456789012345678901234567890",
+ %% []},
+ %% #{},
+ %% Cfg),
+ %% application:set_env(kernel,logger_max_size,53),
+ %% "12345678901234567890123456789012345678901234567890..." = %53
+ %% format(info,
+ %% {"123456789012345678901234567890123456789012345678901234567890",
+ %% []},
+ %% #{},
+ %% Cfg),
+ "123456789012..." =
+ format(info,{"12345678901234567890",[]},#{},Cfg#{max_size=>15}),
+ "12345678901234567890" =
+ format(info,{"12345678901234567890",[]},#{},Cfg#{max_size=>unlimited}),
+ %% Check that one newline at the end of the line is kept (if it exists)
+ "12345678901...\n" =
+ format(info,{"12345678901234567890\n",[]},#{},Cfg#{max_size=>15}),
+ "12345678901...\n" =
+ format(info,{"12345678901234567890",[]},#{},Cfg#{template=>[msg,"\n"],
+ max_size=>15}),
+ ok.
+max_size(cleanup,_Config) ->
+ application:unset_env(kernel,logger_max_size),
+ ok.
+
+depth(_Config) ->
+ Template = [msg],
+ "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0]" =
+ format(info,
+ {"~p",[[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0]]},
+ #{},
+ #{template=>Template}),
+ application:set_env(kernel,error_logger_format_depth,11),
+ "[1,2,3,4,5,6,7,8,9,0|...]" =
+ format(info,
+ {"~p",[[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0]]},
+ #{},
+ #{template=>Template}),
+ "[1,2,3,4,5,6,7,8,9,0,1,2|...]" =
+ format(info,
+ {"~p",[[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0]]},
+ #{},
+ #{template=>Template,
+ depth=>13}),
+ "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0]" =
+ format(info,
+ {"~p",[[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0]]},
+ #{},
+ #{template=>Template,
+ depth=>unlimited}),
+ ok.
+depth(cleanup,_Config) ->
+ application:unset_env(kernel,error_logger_format_depth),
+ ok.
+
+chars_limit(_Config) ->
+ FA = {"LoL: ~p~nL: ~p~nMap: ~p~n",
+ [lists:duplicate(10,lists:seq(1,100)),
+ lists:seq(1,100),
+ maps:from_list(lists:zip(lists:seq(1,100),
+ lists:duplicate(100,value)))]},
+ Meta = #{time=>timestamp()},
+ Template = [time," - ", msg, "\n"],
+ FC = #{template=>Template,
+ depth=>unlimited,
+ max_size=>unlimited,
+ chars_limit=>unlimited,
+ single_line=>true},
+ CL1 = 80,
+ String1 = format(info,FA,Meta,FC#{chars_limit=>CL1}),
+ L1 = string:length(String1),
+ ct:log("String1: ~p~nLength1: ~p~n",[lists:flatten(String1),L1]),
+ true = L1 > CL1,
+ true = L1 < CL1 + 15,
+
+ String2 = format(info,FA,Meta,FC#{chars_limit=>CL1,depth=>10}),
+ L2 = string:length(String2),
+ ct:log("String2: ~p~nLength2: ~p~n",[lists:flatten(String2),L2]),
+ String2 = String1,
+
+ CL3 = 200,
+ String3 = format(info,FA,Meta,FC#{chars_limit=>CL3}),
+ L3 = string:length(String3),
+ ct:log("String3: ~p~nLength3: ~p~n",[lists:flatten(String3),L3]),
+ true = L3 > CL3,
+ true = L3 < CL3 + 15,
+
+ String4 = format(info,FA,Meta,FC#{chars_limit=>CL3,depth=>10}),
+ L4 = string:length(String4),
+ ct:log("String4: ~p~nLength4: ~p~n",[lists:flatten(String4),L4]),
+ true = L4 > CL3,
+ true = L4 < CL3 + 15,
+
+ %% Test that max_size truncates the string which is limited by
+ %% depth and chars_limit
+ MS5 = 150,
+ String5 = format(info,FA,Meta,FC#{chars_limit=>CL3,depth=>10,max_size=>MS5}),
+ L5 = string:length(String5),
+ ct:log("String5: ~p~nLength5: ~p~n",[String5,L5]),
+ L5 = MS5,
+ true = lists:prefix(lists:sublist(String5,L5-4),String4),
+
+ %% Test that chars_limit limits string also
+ Str = "123456789012345678901234567890123456789012345678901234567890123456789",
+ CL6 = 80,
+ String6 = format(info,{string,Str},Meta,FC#{chars_limit=>CL6}),
+ L6 = string:length(String6),
+ ct:log("String6: ~p~nLength6: ~p~n",[String6,L6]),
+ L6 = CL6,
+
+ ok.
+
+format_mfa(_Config) ->
+ Template = [mfa],
+
+ Meta1 = #{mfa=>{mod,func,0}},
+ String1 = format(info,{"~p",[term]},Meta1,#{template=>Template}),
+ ct:log(String1),
+ "mod:func/0" = String1,
+
+ Meta2 = #{mfa=>{mod,func,[]}},
+ String2 = format(info,{"~p",[term]},Meta2,#{template=>Template}),
+ ct:log(String2),
+ "mod:func/0" = String2,
+
+ Meta3 = #{mfa=>"mod:func/0"},
+ String3 = format(info,{"~p",[term]},Meta3,#{template=>Template}),
+ ct:log(String3),
+ "mod:func/0" = String3,
+
+ Meta4 = #{mfa=>othermfa},
+ String4 = format(info,{"~p",[term]},Meta4,#{template=>Template}),
+ ct:log(String4),
+ "othermfa" = String4,
+
+ ok.
+
+format_time(_Config) ->
+ Time = timestamp(),
+ Meta = #{time=>Time},
+ FC = #{template=>[time]},
+ Msg = {string,""},
+ ExpectedLocal = default_time_format(Time,false),
+ ExpectedUtc = default_time_format(Time,true),
+
+ %% default - local time
+ ExpectedLocal = format(info,Msg,Meta,FC),
+
+ %% time_offset config parameter to formatter
+ ExpectedLocal = format(info,Msg,Meta,FC#{time_offset=>""}),
+ ExpectedUtc = format(info,Msg,Meta,FC#{time_offset=>"Z"}),
+
+ %% stdlib utc_log works when time_offset parameter is not set
+ application:set_env(stdlib,utc_log,true),
+ ExpectedUtc = format(info,Msg,Meta,FC),
+
+ %% sasl utc_log overwrites stdlib utc_log
+ application:set_env(sasl,utc_log,false),
+ ExpectedLocal = format(info,Msg,Meta,FC),
+
+ %% sasl utc_log overwrites stdlib utc_log
+ application:set_env(sasl,utc_log,true),
+ application:set_env(stdlib,utc_log,false),
+ ExpectedUtc = format(info,Msg,Meta,FC),
+
+ %% time_offset config parameter to formatter
+ %% overwrites sasl and stdlib utc_log
+ application:set_env(sasl,utc_log,false),
+ ExpectedUtc = format(info,Msg,Meta,FC#{time_offset=>"Z"}),
+
+ %% time_offset config parameter to formatter
+ %% overwrites sasl and stdlib utc_log
+ application:set_env(sasl,utc_log,true),
+ application:set_env(stdlib,utc_log,true),
+ ExpectedLocal = format(info,Msg,Meta,FC#{time_offset=>""}),
+
+ %% time_designator config parameter to formatter
+ ExpectedLocalS = default_time_format(Time,false,$\s),
+ ExpectedUtcS = default_time_format(Time,true,$\s),
+
+ ExpectedLocalS = format(info,Msg,Meta,FC#{time_offset=>"",
+ time_designator=>$\s}),
+ ExpectedUtcS = format(info,Msg,Meta,FC#{time_offset=>"Z",
+ time_designator=>$\s}),
+
+ ok.
+
+format_time(cleanup,_Config) ->
+ application:unset_env(sasl,utc_log),
+ application:unset_env(stdlib,utc_log),
+ ok.
+
+level_or_msg_in_meta(_Config) ->
+ %% The template contains atoms to pick out values from meta,
+ %% or level/msg to add these from the log event. What if you have
+ %% a key named 'level' or 'msg' in meta and want to display
+ %% its value?
+ %% For now we simply ignore Meta on this and display the
+ %% actual level and msg from the log event.
+
+ Meta = #{level=>mylevel,
+ msg=>"metamsg"},
+ Template = [level,";",msg],
+ String = format(info,{"~p",[term]},Meta,#{template=>Template}),
+ ct:log(String),
+ "info;term" = String, % so mylevel and "metamsg" are ignored
+
+ ok.
+
+faulty_log(_Config) ->
+ %% Unexpected log (should be type logger:log_event()) - print error
+ {error,
+ function_clause,
+ {logger_formatter,format,[_,_],_}} =
+ ?TRY(logger_formatter:format(unexp_log,#{})),
+ ok.
+
+faulty_config(_Config) ->
+ {error,
+ function_clause,
+ {logger_formatter,format,[_,_],_}} =
+ ?TRY(logger_formatter:format(#{level=>info,
+ msg=>{"~p",[term]},
+ meta=>#{time=>timestamp()}},
+ unexp_config)),
+ ok.
+
+faulty_msg(_Config) ->
+ {error,
+ function_clause,
+ {logger_formatter,_,_,_}} =
+ ?TRY(logger_formatter:format(#{level=>info,
+ msg=>term,
+ meta=>#{time=>timestamp()}},
+ #{})),
+ ok.
+
+-define(cfgerr(X), {error,{invalid_formatter_config,logger_formatter,X}}).
+check_config(_Config) ->
+ ok = logger_formatter:check_config(#{}),
+ ?cfgerr(bad) = logger_formatter:check_config(bad),
+
+ C1 = #{chars_limit => 1,
+ depth => 1,
+ legacy_header => true,
+ error_logger_notice_header => info,
+ max_size => 1,
+ report_cb => fun(R) -> {"~p",[R]} end,
+ single_line => false,
+ template => [],
+ time_designator => $T,
+ time_offset => 0},
+ ok = logger_formatter:check_config(C1),
+
+ ok = logger_formatter:check_config(#{chars_limit => unlimited}),
+ ?cfgerr({chars_limit,bad}) =
+ logger_formatter:check_config(#{chars_limit => bad}),
+
+ ok = logger_formatter:check_config(#{depth => unlimited}),
+ ?cfgerr({depth,bad}) =
+ logger_formatter:check_config(#{depth => bad}),
+
+ ok = logger_formatter:check_config(#{legacy_header => false}),
+ ?cfgerr({legacy_header,bad}) =
+ logger_formatter:check_config(#{legacy_header => bad}),
+
+ ok = logger_formatter:check_config(#{error_logger_notice_header => notice}),
+ ?cfgerr({error_logger_notice_header,bad}) =
+ logger_formatter:check_config(#{error_logger_notice_header => bad}),
+
+ ok = logger_formatter:check_config(#{max_size => unlimited}),
+ ?cfgerr({max_size,bad}) =
+ logger_formatter:check_config(#{max_size => bad}),
+
+ ok =
+ logger_formatter:check_config(#{report_cb => fun(_,_) -> "" end}),
+ ?cfgerr({report_cb,F}) =
+ logger_formatter:check_config(#{report_cb => F=fun(_,_,_) -> {"",[]} end}),
+ ?cfgerr({report_cb,bad}) =
+ logger_formatter:check_config(#{report_cb => bad}),
+
+ ok = logger_formatter:check_config(#{single_line => true}),
+ ?cfgerr({single_line,bad}) =
+ logger_formatter:check_config(#{single_line => bad}),
+
+ Ts = [[key],
+ [[key1,key2]],
+ [{key,[key],[]}],
+ [{[key1,key2],[[key1,key2]],["noexist"]}],
+ ["string"]],
+ [begin
+ ct:log("check template: ~p",[T]),
+ ok = logger_formatter:check_config(#{template => T})
+ end
+ || T <- Ts],
+
+ ETs = [bad,
+ [{key,bad}],
+ [{key,[key],bad}],
+ [{key,[key],"bad"}],
+ "bad",
+ [[key,$a,$b,$c]],
+ [[$a,$b,$c,key]]],
+ [begin
+ ct:log("check template: ~p",[T]),
+ {error,{invalid_formatter_template,logger_formatter,T}} =
+ logger_formatter:check_config(#{template => T})
+ end
+ || T <- ETs],
+
+ ?cfgerr({time_designator,bad}) =
+ logger_formatter:check_config(#{time_designator => bad}),
+ ?cfgerr({time_designator,"b"}) =
+ logger_formatter:check_config(#{time_designator => "b"}),
+
+ ok = logger_formatter:check_config(#{time_offset => -1}),
+ ok = logger_formatter:check_config(#{time_offset => "+02:00"}),
+ ok = logger_formatter:check_config(#{time_offset => "-23:59"}),
+ ok = logger_formatter:check_config(#{time_offset => "+24:00"}),
+ ok = logger_formatter:check_config(#{time_offset => "-25:00"}),
+ ?cfgerr({time_offset,bad}) =
+ logger_formatter:check_config(#{time_offset => bad}),
+ ?cfgerr({time_offset,"02:00"}) =
+ logger_formatter:check_config(#{time_offset => "02:00"}),
+ ?cfgerr({time_offset,"+02"}) =
+ logger_formatter:check_config(#{time_offset => "+02"}),
+
+ ok.
+
+%% Test that formatter config can be changed, and that the default
+%% template is updated accordingly
+update_config(_Config) ->
+ {error,{not_found,?MODULE}} = logger:update_formatter_config(?MODULE,#{}),
+
+ logger:add_handler_filter(default,silence,{fun(_,_) -> stop end,ok}),
+ ok = logger:add_handler(?MODULE,?MODULE,#{}),
+ D = lists:seq(1,1000),
+ logger:notice("~p~n",[D]),
+ {Lines1,C1} = check_log(),
+ [ct:log(L) || L <- Lines1],
+ ct:log("~p",[C1]),
+ [Line1] = Lines1,
+ [_Time,"notice: "++D1] = string:split(Line1," "),
+ true = length(D1)>3000,
+ true = #{}==C1,
+
+ ok = logger:update_formatter_config(?MODULE,single_line,false),
+ logger:notice("~p~n",[D]),
+ {Lines2,C2} = check_log(),
+ [ct:log(L) || L <- Lines2],
+ ct:log("~p",[C2]),
+ true = length(Lines2)>50,
+ true = #{single_line=>false}==C2,
+
+ ok = logger:update_formatter_config(?MODULE,#{legacy_header=>true}),
+ logger:notice("~p~n",[D]),
+ {Lines3,C3} = check_log(),
+ [ct:log(L) || L <- Lines3],
+ ct:log("~p",[C3]),
+ ["=NOTICE REPORT==== "++_|D3] = Lines3,
+ true = length(D3)>50,
+ true = #{legacy_header=>true,single_line=>false}==C3,
+
+ ok = logger:update_formatter_config(?MODULE,single_line,true),
+ logger:notice("~p~n",[D]),
+ {Lines4,C4} = check_log(),
+ [ct:log(L) || L <- Lines4],
+ ct:log("~p",[C4]),
+ ["=NOTICE REPORT==== "++_,D4] = Lines4,
+ true = length(D4)>3000,
+ true = #{legacy_header=>true,single_line=>true}==C4,
+
+ %% Finally, check that error_logger_notice_header works, default=info
+ error_logger:info_msg("~p",[D]),
+ {Lines5,C5} = check_log(),
+ [ct:log(L) || L <- Lines5],
+ ct:log("~p",[C5]),
+ ["=INFO REPORT==== "++_,_D5] = Lines5,
+
+ ok=logger:update_formatter_config(?MODULE,error_logger_notice_header,notice),
+ error_logger:info_msg("~p",[D]),
+ {Lines6,C6} = check_log(),
+ [ct:log(L) || L <- Lines6],
+ ct:log("~p",[C6]),
+ ["=NOTICE REPORT==== "++_,_D6] = Lines6,
+
+ {error,{invalid_formatter_config,bad}} =
+ logger:update_formatter_config(?MODULE,bad),
+ {error,{invalid_formatter_config,logger_formatter,{depth,bad}}} =
+ logger:update_formatter_config(?MODULE,depth,bad),
+
+ ok.
+
+update_config(cleanup,_Config) ->
+ _ = logger:remove_handler(?MODULE),
+ _ = logger:remove_handler_filter(default,silence),
+ ok.
+
+%%%-----------------------------------------------------------------
+%%% Internal
+format(Level,Msg,Meta,Config) ->
+ format(#{level=>Level,msg=>Msg,meta=>add_time(Meta)},Config).
+
+format(Log,Config) ->
+ lists:flatten(logger_formatter:format(Log,Config)).
+
+default_time_format(Timestamp) ->
+ default_time_format(Timestamp,false).
+
+default_time_format(Timestamp,Utc) ->
+ default_time_format(Timestamp,Utc,$T).
+
+default_time_format(Timestamp,Utc,Sep) ->
+ Offset = if Utc -> "Z";
+ true -> ""
+ end,
+ calendar:system_time_to_rfc3339(Timestamp,[{unit,microsecond},
+ {time_designator,Sep},
+ {offset,Offset}]).
+
+integer(Str) ->
+ is_integer(list_to_integer(Str)).
+integer(Str,Max) ->
+ integer(Str,0,Max).
+integer(Str,Min,Max) ->
+ Int = list_to_integer(Str),
+ Int >= Min andalso Int =<Max.
+
+%%%-----------------------------------------------------------------
+%%% Called by macro ?TRY(X)
+my_try(Fun) ->
+ try Fun() catch C:R:S -> {C,R,hd(S)} end.
+
+timestamp() ->
+ erlang:system_time(microsecond).
+
+%% necessary?
+add_time(#{time:=_}=Meta) ->
+ Meta;
+add_time(Meta) ->
+ Meta#{time=>timestamp()}.
+
+%%%-----------------------------------------------------------------
+%%% handler callback
+log(Log,#{formatter:={M,C}}) ->
+ put(log,{M:format(Log,C),C}),
+ ok.
+
+check_log() ->
+ {S,C} = erase(log),
+ {string:lexemes(S,"\n"),C}.
diff --git a/lib/kernel/test/logger_legacy_SUITE.erl b/lib/kernel/test/logger_legacy_SUITE.erl
new file mode 100644
index 0000000000..c3cab07d81
--- /dev/null
+++ b/lib/kernel/test/logger_legacy_SUITE.erl
@@ -0,0 +1,288 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_legacy_SUITE).
+
+-compile(export_all).
+-compile({nowarn_deprecated_function,[{gen_fsm,start,3},
+ {gen_fsm,send_all_state_event,2}]}).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("kernel/include/logger.hrl").
+-include_lib("kernel/src/logger_internal.hrl").
+
+%%%-----------------------------------------------------------------
+%%% This test suite test that log events from within OTP can be
+%%% delivered to legacy error_logger event handlers on the same format
+%%% as before 'logger' was introduced.
+%%%
+%%% Before changing the expected format of any of the log events in
+%%% this suite, please make sure that the backwards incompatibility it
+%%% introduces is ok.
+%%% -----------------------------------------------------------------
+
+-define(check(Expected),
+ receive Expected ->
+ [] = test_server:messages_get()
+ after 1000 ->
+ ct:fail({report_not_received,
+ {line,?LINE},
+ {got,test_server:messages_get()}})
+ end).
+-define(check_no_flush(Expected),
+ receive Expected ->
+ ok
+ after 1000 ->
+ ct:fail({report_not_received,
+ {line,?LINE},
+ {got,test_server:messages_get()}})
+ end).
+
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+init_per_suite(Config) ->
+ logger:add_handler(error_logger,error_logger,
+ #{level=>info,filter_default=>stop}),
+ Config.
+
+end_per_suite(_Config) ->
+ logger:remove_handler(error_logger),
+ ok.
+
+init_per_group(std, Config) ->
+ ok = logger:set_handler_config(
+ error_logger,filters,
+ [{domain,{fun logger_filters:domain/2,{log,super,[otp]}}}]),
+ Config;
+init_per_group(sasl, Config) ->
+ %% Since default level is notice, and progress reports are info,
+ %% we need to raise the global logger level to info in order to
+ %% receive these.
+ ok = logger:set_primary_config(level,info),
+ ok = logger:set_handler_config(
+ error_logger,filters,
+ [{domain,{fun logger_filters:domain/2,{log,super,[otp,sasl]}}}]),
+
+ %% cth_log_redirect checks if sasl is started before displaying
+ %% any sasl reports - so just to see the real sasl reports in tc
+ %% log:
+ {ok,Apps} = application:ensure_all_started(sasl),
+ [{stop_apps,Apps}|Config];
+init_per_group(_Group, Config) ->
+ Config.
+
+end_per_group(sasl, Config) ->
+ Apps = ?config(stop_apps,Config),
+ [application:stop(App) || App <- Apps],
+ ok = logger:set_primary_config(level,notice),
+ ok;
+end_per_group(_Group, _Config) ->
+ ok.
+
+init_per_testcase(_TestCase, Config) ->
+ error_logger:add_report_handler(?MODULE,{event_handler,self()}),
+ Config.
+
+end_per_testcase(Case, Config) ->
+ %% Using gen_event directly here, instead of
+ %% error_logger:delete_report_handler. This is to avoid
+ %% automatically stopping the error_logger process due to removing
+ %% the last handler.
+ gen_event:delete_handler(error_logger,?MODULE,[]),
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
+ ok.
+
+groups() ->
+ [{std,[],[gen_server,
+ gen_event,
+ gen_fsm,
+ gen_statem]},
+ {sasl,[],[sasl_reports,
+ supervisor_handle_info]}].
+
+all() ->
+ [{group,std},
+ {group,sasl}].
+
+gen_server(_Config) ->
+ {ok,Pid} = gen_server:start(?MODULE,gen_server,[]),
+ Msg = fun() -> erlang:error({badmatch,b}) end,
+ Pid ! Msg,
+ ?check({warning_msg,"** Undefined handle_info in ~p"++_,[?MODULE,Msg]}),
+ ok = gen_server:cast(Pid,Msg),
+ ?check({error,"** Generic server ~tp terminating"++_,
+ [Pid,{'$gen_cast',Msg},gen_server,{{badmatch,b},_}]}).
+
+gen_event(_Config) ->
+ {ok,Pid} = gen_event:start(),
+ ok = gen_event:add_handler(Pid,?MODULE,gen_event),
+ Msg = fun() -> erlang:error({badmatch,b}) end,
+ Pid ! Msg,
+ ?check({warning_msg,"** Undefined handle_info in ~tp"++_,[?MODULE,Msg]}),
+ gen_event:notify(Pid,Msg),
+ ?check({error,"** gen_event handler ~p crashed."++_,
+ [?MODULE,Pid,Msg,gen_event,{{badmatch,b},_}]}).
+
+gen_fsm(_Config) ->
+ {ok,Pid} = gen_fsm:start(?MODULE,gen_fsm,[]),
+ Msg = fun() -> erlang:error({badmatch,b}) end,
+ Pid ! Msg,
+ ?check({warning_msg,"** Undefined handle_info in ~p"++_,[?MODULE,Msg]}),
+ gen_fsm:send_all_state_event(Pid,Msg),
+ ?check({error,"** State machine ~tp terminating"++_,
+ [Pid,Msg,mystate,gen_fsm,{{badmatch,b},_}]}).
+
+gen_statem(_Config) ->
+ {ok,Pid} = gen_statem:start(?MODULE,gen_statem,[]),
+ Msg = fun() -> erlang:error({badmatch,b}) end,
+ Pid ! Msg,
+ ?check({error,"** State machine ~tp terminating"++_,
+ [Pid,{info,Msg},{mystate,gen_statem},error,{badmatch,b}|_]}).
+
+sasl_reports(Config) ->
+ App = {application,?MODULE,[{description, ""},
+ {vsn, "1.0"},
+ {modules, [?MODULE]},
+ {registered, []},
+ {applications, []},
+ {mod, {?MODULE, []}}]},
+ AppStr = io_lib:format("~p.",[App]),
+ Dir = ?config(priv_dir,Config),
+ AppFile = filename:join(Dir,?MODULE_STRING++".app"),
+ ok = file:write_file(AppFile,AppStr),
+ true = code:add_patha(Dir),
+ ok = application:start(?MODULE),
+ SupName = sup_name(),
+ Pid = whereis(SupName),
+ [{ch,ChPid,_,_}] = supervisor:which_children(Pid),
+ Node = node(),
+ ?check_no_flush({info_report,progress,[{application,?MODULE},
+ {started_at,Node}]}),
+ ?check({info_report,progress,[{supervisor,{local,SupName}},
+ {started,[{pid,ChPid}|_]}]}),
+ ok = gen_server:cast(ChPid, fun() ->
+ spawn_link(fun() -> receive x->ok end end)
+ end),
+ Msg = fun() -> erlang:error({badmatch,b}) end,
+ ok = gen_server:cast(ChPid,Msg),
+ ?check_no_flush({error,"** Generic server ~tp terminating"++_,
+ [ChPid,{'$gen_cast',Msg},gen_server,{{badmatch,b},_}]}),
+ ?check_no_flush({error_report,crash_report,
+ [[{initial_call,_},
+ {pid,ChPid},
+ {registered_name,[]},
+ {error_info,{error,{badmatch,b},_}},
+ {ancestors,_},
+ {message_queue_len,_},
+ {messages,_},
+ {links,[Pid,Neighbour]},
+ {dictionary,_},
+ {trap_exit,_},
+ {status,_},
+ {heap_size,_},
+ {stack_size,_},
+ {reductions,_}],
+ [{neighbour,[{pid,Neighbour},
+ {registered_name,_},
+ {initial_call,_},
+ {current_function,_},
+ {ancestors,_},
+ {message_queue_len,_},
+ {links,[ChPid]},
+ {trap_exit,_},
+ {status,_},
+ {heap_size,_},
+ {stack_size,_},
+ {reductions,_},
+ {current_stacktrace,_}]}]]}),
+ ?check_no_flush({error_report,supervisor_report,
+ [{supervisor,{local,SupName}},
+ {errorContext,child_terminated},
+ {reason,{{badmatch,b},_}},
+ {offender,[{pid,ChPid}|_]}]}),
+ ?check({info_report,progress,[{supervisor,{local,SupName}},
+ {started,_}]}),
+
+ ok = application:stop(?MODULE),
+ ?check({info_report,std_info,[{application,?MODULE},
+ {exited,stopped},
+ {type,temporary}]}).
+
+sasl_reports(cleanup,_Config) ->
+ application:stop(?MODULE).
+
+supervisor_handle_info(_Config) ->
+ {ok,Pid} = supervisor:start_link({local,sup_name()},?MODULE,supervisor),
+ ?check({info_report,progress,[{supervisor,_},{started,_}]}),
+ Pid ! msg,
+ ?check({error,"Supervisor received unexpected message: ~tp~n",[msg]}).
+
+supervisor_handle_info(cleanup,_Config) ->
+ Pid = whereis(sup_name()),
+ unlink(Pid),
+ exit(Pid,shutdown).
+
+%%%-----------------------------------------------------------------
+%%% Callbacks for error_logger event handler, gen_server, gen_statem,
+%%% gen_fsm, gen_event, supervisor and application.
+start(_,_) ->
+ supervisor:start_link({local,sup_name()},?MODULE,supervisor).
+
+init(supervisor) ->
+ {ok,{#{},[#{id=>ch,start=>{gen_server,start_link,[?MODULE,gen_server,[]]}}]}};
+init(StateMachine) when StateMachine==gen_statem; StateMachine==gen_fsm ->
+ {ok,mystate,StateMachine};
+init(State) ->
+ {ok,State}.
+
+%% error_logger event handler
+handle_event({Tag,_Gl,{_Pid,Type,Report}},{_,Pid}=State) ->
+ Pid ! {Tag,Type,Report},
+ {ok,State};
+%% other gen_event
+handle_event(Fun,State) when is_function(Fun) ->
+ Fun(),
+ {next_state,State}.
+
+%% gen_fsm
+handle_event(Fun,State,Data) when is_function(Fun) ->
+ Fun(),
+ {next_state,State,Data}.
+
+%% gen_statem
+handle_event(info,Fun,State,Data) when is_function(Fun) ->
+ Fun(),
+ {next_state,State,Data}.
+
+%% gen_server
+handle_cast(Fun,State) when is_function(Fun) ->
+ Fun(),
+ {noreply,State}.
+
+%% gen_statem
+callback_mode() ->
+ handle_event_function.
+
+%%%-----------------------------------------------------------------
+%%% Internal
+sup_name() ->
+ list_to_atom(?MODULE_STRING++"_sup").
diff --git a/lib/kernel/test/logger_simple_h_SUITE.erl b/lib/kernel/test/logger_simple_h_SUITE.erl
new file mode 100644
index 0000000000..e0ad792bdb
--- /dev/null
+++ b/lib/kernel/test/logger_simple_h_SUITE.erl
@@ -0,0 +1,209 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_simple_h_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("kernel/include/logger.hrl").
+-include_lib("kernel/src/logger_internal.hrl").
+
+-import(logger_test_lib, [setup/2, log/3, sync_and_read/3]).
+
+-define(check_no_log,[] = test_server:messages_get()).
+-define(check(Expected),
+ receive {log,Expected} ->
+ [] = test_server:messages_get()
+ after 1000 ->
+ ct:fail({report_not_received,
+ {line,?LINE},
+ {expected,Expected},
+ {got,test_server:messages_get()}})
+ end).
+
+-define(str,"Log from "++atom_to_list(?FUNCTION_NAME)++
+ ":"++integer_to_list(?LINE)).
+-define(map_rep,#{function=>?FUNCTION_NAME, line=>?LINE}).
+-define(keyval_rep,[{function,?FUNCTION_NAME}, {line,?LINE}]).
+
+suite() ->
+ [{timetrap,{seconds,30}},
+ {ct_hooks, [logger_test_lib]}].
+
+init_per_suite(Config) ->
+ Hs0 = logger:get_handler_config(),
+ Hs = lists:keydelete(cth_log_redirect,1,Hs0),
+ [ok = logger:remove_handler(Id) || {Id,_,_} <- Hs],
+ Env = [{App,Key,application:get_env(App,Key)} ||
+ {App,Key} <- [{kernel,logger_level}]],
+ [{env,Env},{logger,Hs}|Config].
+
+end_per_suite(Config) ->
+ [application:set_env(App,Key,Val) || {App,Key,Val} <- ?config(env,Config)],
+ Hs = ?config(logger,Config),
+ [ok = logger:add_handler(Id,Mod,C) || {Id,Mod,C} <- Hs],
+ ok.
+
+init_per_group(_Group, Config) ->
+ Config.
+
+end_per_group(_Group, _Config) ->
+ ok.
+
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+end_per_testcase(Case, Config) ->
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
+ ok.
+
+groups() ->
+ [].
+
+all() ->
+ [start_stop,
+ replace_default,
+ replace_file,
+ replace_disk_log
+ ].
+
+start_stop(_Config) ->
+ undefined = whereis(logger_simple_h),
+ register(logger_simple_h,self()),
+ {error,_} = logger:add_handler(simple,
+ logger_simple_h,
+ #{filter_default=>log}),
+ unregister(logger_simple_h),
+ ok = logger:add_handler(simple,logger_simple_h,#{filter_default=>log}),
+ Pid = whereis(logger_simple_h),
+ true = is_pid(Pid),
+ ok = logger:remove_handler(simple),
+ false = is_pid(whereis(logger_simple_h)),
+ ok.
+start_stop(cleanup,_Config) ->
+ logger:remove_handler(simple).
+
+%% This testcase just tests that it does not crash, the default handler prints
+%% to stdout which we cannot read from in a detached slave.
+replace_default(Config) ->
+
+ {ok, _, Node} = logger_test_lib:setup(Config, [{logger, [{handler, default, undefined}]}]),
+ log(Node, emergency, [?str]),
+ log(Node, alert, [?str,[]]),
+ log(Node, error, [?map_rep]),
+ log(Node, info, [?keyval_rep]),
+ log(Node, info, [?keyval_rep++[not_key_val]]),
+ rpc:call(Node, error_logger, error_report, [some_type,?map_rep]),
+ rpc:call(Node, error_logger, warning_report, ["some_type",?map_rep]),
+ log(Node, critical, [?str,[?keyval_rep]]),
+ log(Node, notice, [["fake",string,"line:",?LINE]]),
+
+ ok = rpc:call(Node, logger, add_handlers, [kernel]),
+
+ ok.
+
+replace_file(Config) ->
+
+ {ok, _, Node} = logger_test_lib:setup(Config, [{logger, [{handler, default, undefined}]}]),
+ log(Node, emergency, [M1=?str]),
+ log(Node, alert, [M2=?str,[]]),
+ log(Node, error, [?map_rep]),
+ log(Node, warning, [?keyval_rep]),
+ log(Node, warning, [?keyval_rep++[not_key_val]]),
+ log(Node, critical, [?str,[?keyval_rep]]),
+ log(Node, notice, [["fake",string,"line:",?LINE]]),
+
+ File = filename:join(proplists:get_value(priv_dir,Config),
+ atom_to_list(?FUNCTION_NAME)++".log"),
+
+ ok = rpc:call(Node, logger, add_handlers,
+ [[{handler, default, logger_std_h,
+ #{ config => #{ type => {file, File} },
+ formatter => {?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}}}]]),
+
+ {ok,Bin} = sync_and_read(Node, file, File),
+ Lines = [unicode:characters_to_list(L) ||
+ L <- binary:split(Bin,<<"\n">>,[global,trim])],
+ ["=EMERGENCY REPORT===="++_,
+ M1,
+ "=ALERT REPORT===="++_,
+ M2,
+ "=ERROR REPORT===="++_,
+ _,
+ _,
+ "=WARNING REPORT===="++_,
+ _,
+ _,
+ "=WARNING REPORT===="++_,
+ _,
+ _,
+ _,
+ "=CRITICAL REPORT===="++_,
+ _,
+ _,
+ "=NOTICE REPORT===="++_,
+ _
+ ] = Lines,
+ ok.
+
+replace_disk_log(Config) ->
+
+ {ok, _, Node} = logger_test_lib:setup(Config, [{logger, [{handler, default, undefined}]}]),
+ log(Node, emergency, [M1=?str]),
+ log(Node, alert, [M2=?str,[]]),
+ log(Node, error, [?map_rep]),
+ log(Node, warning, [?keyval_rep]),
+ log(Node, warning, [?keyval_rep++[not_key_val]]),
+ log(Node, critical, [?str,[?keyval_rep]]),
+ log(Node, notice, [["fake",string,"line:",?LINE]]),
+
+ File = filename:join(proplists:get_value(priv_dir,Config),
+ atom_to_list(?FUNCTION_NAME)++".log"),
+
+ ok = rpc:call(Node, logger, add_handlers,
+ [[{handler, default, logger_disk_log_h,
+ #{ config => #{ file => File },
+ formatter => {?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}}}]]),
+ {ok,Bin} = sync_and_read(Node, disk_log, File),
+ Lines = [unicode:characters_to_list(L) ||
+ L <- binary:split(Bin,<<"\n">>,[global,trim])],
+ ["=EMERGENCY REPORT===="++_,
+ M1,
+ "=ALERT REPORT===="++_,
+ M2,
+ "=ERROR REPORT===="++_,
+ _,
+ _,
+ "=WARNING REPORT===="++_,
+ _,
+ _,
+ "=WARNING REPORT===="++_,
+ _,
+ _,
+ _,
+ "=CRITICAL REPORT===="++_,
+ _,
+ _,
+ "=NOTICE REPORT===="++_,
+ _
+ ] = Lines,
+ ok.
diff --git a/lib/kernel/test/logger_std_h_SUITE.erl b/lib/kernel/test/logger_std_h_SUITE.erl
new file mode 100644
index 0000000000..3426567bbf
--- /dev/null
+++ b/lib/kernel/test/logger_std_h_SUITE.erl
@@ -0,0 +1,1607 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_std_h_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("kernel/include/logger.hrl").
+-include_lib("kernel/src/logger_internal.hrl").
+-include_lib("kernel/src/logger_h_common.hrl").
+-include_lib("stdlib/include/ms_transform.hrl").
+-include_lib("kernel/include/file.hrl").
+
+-define(check_no_log, [] = test_server:messages_get()).
+-define(check(Expected),
+ receive
+ {log,Expected} ->
+ [] = test_server:messages_get()
+ after 5000 ->
+ ct:fail({report_not_received,
+ {line,?LINE},
+ {expected,Expected},
+ {got,test_server:messages_get()}})
+ end).
+
+-define(msg,"Log from "++atom_to_list(?FUNCTION_NAME)++
+ ":"++integer_to_list(?LINE)).
+-define(bin(Msg), list_to_binary(Msg++"\n")).
+-define(domain,#{domain=>[?MODULE]}).
+
+suite() ->
+ [{timetrap,{seconds,30}},
+ {ct_hooks,[logger_test_lib]}].
+
+init_per_suite(Config) ->
+ timer:start(), % to avoid progress report
+ {ok,#{formatter:=OrigFormatter}} =
+ logger:get_handler_config(?STANDARD_HANDLER),
+ [{formatter,OrigFormatter}|Config].
+
+end_per_suite(Config) ->
+ {OrigMod,OrigConf} = proplists:get_value(formatter,Config),
+ logger:set_handler_config(?STANDARD_HANDLER,formatter,{OrigMod,OrigConf}),
+ ok.
+
+init_per_group(_Group, Config) ->
+ Config.
+
+end_per_group(_Group, _Config) ->
+ ok.
+
+init_per_testcase(TestHooksCase, Config) when
+ TestHooksCase == write_failure;
+ TestHooksCase == sync_failure ->
+ case (fun() -> ?TEST_HOOKS_TAB == undefined end)() of
+ true ->
+ {skip,"Define the TEST_HOOKS macro to run this test"};
+ false ->
+ ct:print("********** ~w **********", [TestHooksCase]),
+ Config
+ end;
+init_per_testcase(OPCase, Config) when
+ OPCase == qlen_kill_new;
+ OPCase == restart_after ->
+ case re:run(erlang:system_info(system_version),
+ "dirty-schedulers-TEST",
+ [{capture,none}]) of
+ match ->
+ {skip,"Overload protection test skipped on dirty-schedulers-TEST"};
+ nomatch ->
+ ct:print("********** ~w **********", [OPCase]),
+ Config
+ end;
+init_per_testcase(TestCase, Config) ->
+ ct:print("********** ~w **********", [TestCase]),
+ Config.
+
+end_per_testcase(Case, Config) ->
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
+ ok.
+
+groups() ->
+ [].
+
+all() ->
+ [add_remove_instance_tty,
+ add_remove_instance_standard_io,
+ add_remove_instance_standard_error,
+ add_remove_instance_file1,
+ add_remove_instance_file2,
+ default_formatter,
+ errors,
+ formatter_fail,
+ config_fail,
+ crash_std_h_to_file,
+ crash_std_h_to_disk_log,
+ bad_input,
+ info_and_reset,
+ reconfig,
+ file_opts,
+ sync,
+ write_failure,
+ sync_failure,
+ op_switch_to_sync_file,
+ op_switch_to_sync_tty,
+ op_switch_to_drop_file,
+ op_switch_to_drop_tty,
+ op_switch_to_flush_file,
+ op_switch_to_flush_tty,
+ limit_burst_disabled,
+ limit_burst_enabled_one,
+ limit_burst_enabled_period,
+ kill_disabled,
+ qlen_kill_new,
+ qlen_kill_std,
+ mem_kill_new,
+ mem_kill_std,
+ restart_after,
+ handler_requests_under_load
+ ].
+
+add_remove_instance_tty(_Config) ->
+ {error,{handler_not_added,{invalid_config,logger_std_h,{type,tty}}}} =
+ logger:add_handler(?MODULE,logger_std_h,
+ #{config => #{type => tty},
+ filter_default=>log,
+ formatter=>{?MODULE,self()}}),
+ ok.
+
+add_remove_instance_standard_io(_Config) ->
+ add_remove_instance_nofile(standard_io).
+add_remove_instance_standard_io(cleanup,_Config) ->
+ logger_std_h_remove().
+
+add_remove_instance_standard_error(_Config) ->
+ add_remove_instance_nofile(standard_error).
+add_remove_instance_standard_error(cleanup,_Config) ->
+ logger_std_h_remove().
+
+add_remove_instance_file1(Config) ->
+ Dir = ?config(priv_dir,Config),
+ Log = filename:join(Dir,"stdlog1.txt"),
+ Type = {file,Log},
+ add_remove_instance_file(Log, Type).
+add_remove_instance_file1(cleanup,_Config) ->
+ logger_std_h_remove().
+
+add_remove_instance_file2(Config) ->
+ Dir = ?config(priv_dir,Config),
+ Log = filename:join(Dir,"stdlog2.txt"),
+ Type = {file,Log,[raw,append]},
+ add_remove_instance_file(Log, Type).
+add_remove_instance_file2(cleanup,_Config) ->
+ logger_std_h_remove().
+
+add_remove_instance_file(Log, Type) ->
+ ok = logger:add_handler(?MODULE,
+ logger_std_h,
+ #{config => #{type => Type},
+ filter_default=>stop,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter=>{?MODULE,self()}}),
+ Pid = whereis(h_proc_name()),
+ true = is_pid(Pid),
+ logger:notice(M1=?msg,?domain),
+ ?check(M1),
+ B1 = ?bin(M1),
+ try_read_file(Log, {ok,B1}, filesync_rep_int()),
+ ok = logger:remove_handler(?MODULE),
+ timer:sleep(500),
+ undefined = whereis(h_proc_name()),
+ logger:notice(?msg,?domain),
+ ?check_no_log,
+ try_read_file(Log, {ok,B1}, filesync_rep_int()),
+ ok.
+
+default_formatter(_Config) ->
+ ok = logger:set_handler_config(?STANDARD_HANDLER,formatter,
+ {?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}),
+ ct:capture_start(),
+ logger:notice(M1=?msg),
+ timer:sleep(100),
+ ct:capture_stop(),
+ [Msg] = ct:capture_get(),
+ match = re:run(Msg,"=NOTICE REPORT====.*\n"++M1,[{capture,none}]),
+ ok.
+
+errors(Config) ->
+ Dir = ?config(priv_dir,Config),
+ Log = filename:join(Dir,?FUNCTION_NAME),
+
+ ok = logger:add_handler(?MODULE,logger_std_h,#{}),
+ {error,{already_exist,?MODULE}} =
+ logger:add_handler(?MODULE,logger_std_h,#{}),
+
+ {error,{not_found,no_such_name}} = logger:remove_handler(no_such_name),
+
+ ok = logger:remove_handler(?MODULE),
+ {error,{not_found,?MODULE}} = logger:remove_handler(?MODULE),
+
+ {error,
+ {handler_not_added,
+ {invalid_config,logger_std_h,{type,faulty_type}}}} =
+ logger:add_handler(?MODULE,logger_std_h,
+ #{config => #{type => faulty_type}}),
+
+ case os:type() of
+ {win32,_} ->
+ %% No use in testing file access on windows
+ ok;
+ _ ->
+ NoDir = lists:concat(["/",?MODULE,"_dir"]),
+ {error,
+ {handler_not_added,{{open_failed,NoDir,eacces},_}}} =
+ logger:add_handler(myh2,logger_std_h,
+ #{config=>#{type=>{file,NoDir}}})
+ end,
+
+ {error,
+ {handler_not_added,{{open_failed,Log,_},_}}} =
+ logger:add_handler(myh3,logger_std_h,
+ #{config=>#{type=>{file,Log,[bad_file_opt]}}}),
+
+ ok = logger:notice(?msg).
+
+errors(cleanup,_Config) ->
+ logger:remove_handler(?MODULE).
+
+formatter_fail(Config) ->
+ Dir = ?config(priv_dir,Config),
+ Log = filename:join(Dir,?FUNCTION_NAME),
+
+ %% no formatter
+ ok = logger:add_handler(?MODULE,
+ logger_std_h,
+ #{config => #{type => {file,Log}},
+ filter_default=>stop,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE])}),
+ Pid = whereis(h_proc_name()),
+ true = is_pid(Pid),
+ H = logger:get_handler_ids(),
+ true = lists:member(?MODULE,H),
+
+ %% Formatter is added automatically
+ {ok,#{formatter:={logger_formatter,_}}} = logger:get_handler_config(?MODULE),
+ logger:notice(M1=?msg,?domain),
+ Got1 = try_match_file(Log,"[0-9\\+\\-T:\\.]* notice: "++M1,5000),
+
+ ok = logger:set_handler_config(?MODULE,formatter,{nonexistingmodule,#{}}),
+ logger:notice(M2=?msg,?domain),
+ Got2 = try_match_file(Log,
+ escape(Got1)++"[0-9\\+\\-T:\\.]* notice: FORMATTER CRASH: .*"++M2,
+ 5000),
+
+ ok = logger:set_handler_config(?MODULE,formatter,{?MODULE,crash}),
+ logger:notice(M3=?msg,?domain),
+ Got3 = try_match_file(Log,
+ escape(Got2)++"[0-9\\+\\-T:\\.]* notice: FORMATTER CRASH: .*"++M3,
+ 5000),
+
+ ok = logger:set_handler_config(?MODULE,formatter,{?MODULE,bad_return}),
+ logger:notice(?msg,?domain),
+ try_match_file(Log,
+ escape(Got3)++"FORMATTER ERROR: bad return value",
+ 5000),
+
+ %% Check that handler is still alive and was never dead
+ Pid = whereis(h_proc_name()),
+ H = logger:get_handler_ids(),
+
+ ok.
+
+formatter_fail(cleanup,_Config) ->
+ logger:remove_handler(?MODULE).
+
+config_fail(_Config) ->
+ {error,{handler_not_added,{invalid_config,logger_std_h,{bad,bad}}}} =
+ logger:add_handler(?MODULE,logger_std_h,
+ #{config => #{bad => bad},
+ filter_default=>log,
+ formatter=>{?MODULE,self()}}),
+ {error,{handler_not_added,{invalid_config,logger_std_h,
+ {restart_type,bad}}}} =
+ logger:add_handler(?MODULE,logger_std_h,
+ #{config => #{restart_type => bad},
+ filter_default=>log,
+ formatter=>{?MODULE,self()}}),
+ {error,{handler_not_added,{invalid_levels,{_,1,_}}}} =
+ logger:add_handler(?MODULE,logger_std_h,
+ #{config => #{drop_mode_qlen=>1}}),
+ {error,{handler_not_added,{invalid_levels,{43,42,_}}}} =
+ logger:add_handler(?MODULE,logger_std_h,
+ #{config => #{sync_mode_qlen=>43,
+ drop_mode_qlen=>42}}),
+ {error,{handler_not_added,{invalid_levels,{_,43,42}}}} =
+ logger:add_handler(?MODULE,logger_std_h,
+ #{config => #{drop_mode_qlen=>43,
+ flush_qlen=>42}}),
+
+ ok = logger:add_handler(?MODULE,logger_std_h,
+ #{filter_default=>log,
+ formatter=>{?MODULE,self()}}),
+ {error,{illegal_config_change,_,_}} =
+ logger:set_handler_config(?MODULE,config,
+ #{type=>{file,"file"}}),
+ {error,{illegal_config_change,_,_}} =
+ logger:set_handler_config(?MODULE,id,bad),
+ {error,{invalid_levels,_}} =
+ logger:set_handler_config(?MODULE,config,
+ #{sync_mode_qlen=>100,
+ flush_qlen=>99}),
+ {error,{invalid_config,logger_std_h,{filesync_rep_int,2000}}} =
+ logger:set_handler_config(?MODULE, config,
+ #{filesync_rep_int => 2000}),
+ ok.
+
+config_fail(cleanup,_Config) ->
+ logger:remove_handler(?MODULE).
+
+crash_std_h_to_file(Config) ->
+ Dir = ?config(priv_dir,Config),
+ Log = filename:join(Dir,lists:concat([?MODULE,"_",?FUNCTION_NAME,".log"])),
+ crash_std_h(Config,?FUNCTION_NAME,
+ [{handler,default,logger_std_h,
+ #{ config => #{ type => {file, Log} }}}],
+ file, Log).
+crash_std_h_to_file(cleanup,_Config) ->
+ crash_std_h(cleanup).
+
+crash_std_h_to_disk_log(Config) ->
+ Dir = ?config(priv_dir,Config),
+ Log = filename:join(Dir,lists:concat([?MODULE,"_",?FUNCTION_NAME,".log"])),
+ crash_std_h(Config,?FUNCTION_NAME,
+ [{handler,default,logger_disk_log_h,
+ #{ config => #{ file => Log }}}],
+ disk_log,Log).
+crash_std_h_to_disk_log(cleanup,_Config) ->
+ crash_std_h(cleanup).
+
+crash_std_h(Config,Func,Var,Type,Log) ->
+ Dir = ?config(priv_dir,Config),
+ SysConfig = filename:join(Dir,lists:concat([?MODULE,"_",Func,".config"])),
+ ok = file:write_file(SysConfig, io_lib:format("[{kernel,[{logger,~p}]}].",[Var])),
+ Pa = filename:dirname(code:which(?MODULE)),
+ Name = lists:concat([?MODULE,"_",Func]),
+ Args = lists:concat([" -config ",filename:rootname(SysConfig)," -pa ",Pa]),
+ ct:pal("Starting ~p with ~tp", [Name,Args]),
+ %% Start a node which prints kernel logs to the destination specified by Type
+ {ok,Node} = test_server:start_node(Name, peer, [{args, Args}]),
+ HProcName =
+ case Type of
+ file -> ?name_to_reg_name(logger_std_h,?STANDARD_HANDLER);
+ disk_log -> ?name_to_reg_name(logger_disk_log_h,?STANDARD_HANDLER)
+ end,
+ Pid = rpc:call(Node,erlang,whereis,[HProcName]),
+ ok = rpc:call(Node,logger,set_handler_config,[?STANDARD_HANDLER,formatter,
+ {?MODULE,self()}]),
+ ok = log_on_remote_node(Node,"dummy1"),
+ ?check("dummy1"),
+ {ok,Bin1} = sync_and_read(Node,Type,Log),
+ <<"dummy1\n">> = binary:part(Bin1,{byte_size(Bin1),-7}),
+
+ %% Kill the logger_std_h process
+ exit(Pid, kill),
+
+ %% Wait a bit, then check that it is gone
+ timer:sleep(2000),
+ undefined = rpc:call(Node,erlang,whereis,[HProcName]),
+
+ %% Check that file is not empty
+ {ok,Bin2} = sync_and_read(Node,Type,Log),
+ <<"dummy1\n">> = binary:part(Bin2,{byte_size(Bin2),-7}),
+ ok.
+
+%% Can not use rpc:call here, since the code would execute on a
+%% process with group_leader on this (the calling) node, and thus
+%% logger would send the log event to the logger process here instead
+%% of logging it itself.
+log_on_remote_node(Node,Msg) ->
+ _ = spawn_link(Node,
+ fun() -> erlang:group_leader(whereis(user),self()),
+ logger:notice(Msg)
+ end),
+ ok.
+
+
+crash_std_h(cleanup) ->
+ Nodes = nodes(),
+ [test_server:stop_node(Node) || Node <- Nodes].
+
+sync_and_read(Node,disk_log,Log) ->
+ rpc:call(Node,logger_disk_log_h,filesync,[?STANDARD_HANDLER]),
+ case file:read_file(Log ++ ".1") of
+ {ok,<<>>} ->
+ timer:sleep(5000),
+ file:read_file(Log ++ ".1");
+ Ok ->
+ Ok
+ end;
+sync_and_read(Node,file,Log) ->
+ rpc:call(Node,logger_std_h,filesync,[?STANDARD_HANDLER]),
+ case file:read_file(Log) of
+ {ok,<<>>} ->
+ timer:sleep(5000),
+ file:read_file(Log);
+ Ok ->
+ Ok
+ end.
+
+bad_input(_Config) ->
+ {error,{badarg,{filesync,["BadType"]}}} = logger_std_h:filesync("BadType"),
+ {error,{badarg,{info,["BadType"]}}} = logger_std_h:info("BadType"),
+ {error,{badarg,{reset,["BadType"]}}} = logger_std_h:reset("BadType").
+
+
+info_and_reset(_Config) ->
+ #{id := ?STANDARD_HANDLER} = logger_std_h:info(?STANDARD_HANDLER),
+ ok = logger_std_h:reset(?STANDARD_HANDLER).
+
+reconfig(Config) ->
+ Dir = ?config(priv_dir,Config),
+ ok = logger:add_handler(?MODULE,
+ logger_std_h,
+ #{config => #{type => standard_io},
+ filter_default=>log,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter=>{?MODULE,self()}}),
+ #{id := ?MODULE,
+ type := standard_io,
+ file_ctrl_pid := FileCtrlPid,
+ sync_mode_qlen := ?SYNC_MODE_QLEN,
+ drop_mode_qlen := ?DROP_MODE_QLEN,
+ flush_qlen := ?FLUSH_QLEN,
+ burst_limit_enable := ?BURST_LIMIT_ENABLE,
+ burst_limit_max_count := ?BURST_LIMIT_MAX_COUNT,
+ burst_limit_window_time := ?BURST_LIMIT_WINDOW_TIME,
+ overload_kill_enable := ?OVERLOAD_KILL_ENABLE,
+ overload_kill_qlen := ?OVERLOAD_KILL_QLEN,
+ overload_kill_mem_size := ?OVERLOAD_KILL_MEM_SIZE,
+ overload_kill_restart_after := ?OVERLOAD_KILL_RESTART_AFTER,
+ filesync_repeat_interval := ?FILESYNC_REPEAT_INTERVAL} =
+ logger_std_h:info(?MODULE),
+
+ ok = logger:set_handler_config(?MODULE, config,
+ #{sync_mode_qlen => 1,
+ drop_mode_qlen => 2,
+ flush_qlen => 3,
+ burst_limit_enable => false,
+ burst_limit_max_count => 10,
+ burst_limit_window_time => 10,
+ overload_kill_enable => true,
+ overload_kill_qlen => 100000,
+ overload_kill_mem_size => 10000000,
+ overload_kill_restart_after => infinity,
+ filesync_repeat_interval => no_repeat}),
+ #{id := ?MODULE,
+ type := standard_io,
+ file_ctrl_pid := FileCtrlPid,
+ sync_mode_qlen := 1,
+ drop_mode_qlen := 2,
+ flush_qlen := 3,
+ burst_limit_enable := false,
+ burst_limit_max_count := 10,
+ burst_limit_window_time := 10,
+ overload_kill_enable := true,
+ overload_kill_qlen := 100000,
+ overload_kill_mem_size := 10000000,
+ overload_kill_restart_after := infinity,
+ filesync_repeat_interval := no_repeat} = logger_std_h:info(?MODULE),
+ ok.
+
+reconfig(cleanup, _Config) ->
+ logger:remove_handler(?MODULE).
+
+
+file_opts(Config) ->
+ Dir = ?config(priv_dir,Config),
+ Log = filename:join(Dir, lists:concat([?FUNCTION_NAME,".log"])),
+ BadFileOpts = [raw],
+ BadType = {file,Log,BadFileOpts},
+ {error,{handler_not_added,{{open_failed,Log,enoent},_}}} =
+ logger:add_handler(?MODULE, logger_std_h,
+ #{config => #{type => BadType}}),
+
+ OkFileOpts = [raw,append],
+ OkType = {file,Log,OkFileOpts},
+ ok = logger:add_handler(?MODULE,
+ logger_std_h,
+ #{config => #{type => OkType},
+ filter_default=>log,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter=>{?MODULE,self()}}),
+
+ #{type := OkType} = logger_std_h:info(?MODULE),
+ logger:notice(M1=?msg,?domain),
+ ?check(M1),
+ B1 = ?bin(M1),
+ try_read_file(Log, {ok,B1}, filesync_rep_int()),
+ ok.
+file_opts(cleanup, _Config) ->
+ logger:remove_handler(?MODULE).
+
+
+sync(Config) ->
+ Dir = ?config(priv_dir,Config),
+ Log = filename:join(Dir, lists:concat([?FUNCTION_NAME,".log"])),
+ Type = {file,Log},
+ ok = logger:add_handler(?MODULE,
+ logger_std_h,
+ #{config => #{type => Type},
+ filter_default=>log,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter=>{?MODULE,nl}}),
+
+ %% check repeated filesync happens
+ start_tracer([{logger_std_h, write_to_dev, 5},
+ {logger_std_h, sync_dev, 4},
+ {file, datasync, 1}],
+ [{logger_std_h, write_to_dev, <<"first\n">>},
+ {logger_std_h, sync_dev},
+ {file,datasync}]),
+
+ logger:notice("first", ?domain),
+ %% wait for automatic filesync
+ check_tracer(filesync_rep_int()*2),
+
+ %% check that explicit filesync is only done once
+ start_tracer([{logger_std_h, write_to_dev, 5},
+ {logger_std_h, sync_dev, 4},
+ {file, datasync, 1}],
+ [{logger_std_h, write_to_dev, <<"second\n">>},
+ {logger_std_h, sync_dev},
+ {file,datasync},
+ {no_more,500}
+ ]),
+ logger:notice("second", ?domain),
+ %% do explicit sync
+ logger_std_h:filesync(?MODULE),
+ %% a second sync should be ignored
+ logger_std_h:filesync(?MODULE),
+ check_tracer(100),
+
+ %% check that if there's no repeated filesync active,
+ %% a filesync is still performed when handler goes idle
+ logger:set_handler_config(?MODULE, config,
+ #{filesync_repeat_interval => no_repeat}),
+ no_repeat = maps:get(filesync_repeat_interval, logger_std_h:info(?MODULE)),
+ %% The following timer is to make sure the time from last log
+ %% ("second") to next ("third") is long enough, so the a flush is
+ %% triggered by the idle timeout between "thrid" and "fourth".
+ timer:sleep(?IDLE_DETECT_TIME_MSEC*2),
+ start_tracer([{logger_std_h, write_to_dev, 5},
+ {logger_std_h, sync_dev, 4},
+ {file, datasync, 1}],
+ [{logger_std_h, write_to_dev, <<"third\n">>},
+ {logger_std_h, sync_dev},
+ {file,datasync},
+ {logger_std_h, write_to_dev, <<"fourth\n">>},
+ {logger_std_h, sync_dev},
+ {file,datasync}]),
+ logger:notice("third", ?domain),
+ %% wait for automatic filesync
+ timer:sleep(?IDLE_DETECT_TIME_MSEC*2),
+ logger:notice("fourth", ?domain),
+ %% wait for automatic filesync
+ check_tracer(?IDLE_DETECT_TIME_MSEC*2),
+
+ %% switch repeated filesync on and verify that the looping works
+ SyncInt = 1000,
+ WaitT = 4500,
+ OneSync = {logger_std_h,handle_cast,repeated_filesync},
+ %% receive 1 initial repeated_filesync, then 1 per sec
+ start_tracer([{logger_std_h,handle_cast,2}],
+ [OneSync || _ <- lists:seq(1, 1 + trunc(WaitT/SyncInt))]),
+
+ logger:set_handler_config(?MODULE, config,
+ #{filesync_repeat_interval => SyncInt}),
+ SyncInt = maps:get(filesync_repeat_interval, logger_std_h:info(?MODULE)),
+ timer:sleep(WaitT),
+ logger:set_handler_config(?MODULE, config,
+ #{filesync_repeat_interval => no_repeat}),
+ check_tracer(100),
+ ok.
+sync(cleanup, _Config) ->
+ dbg:stop_clear(),
+ logger:remove_handler(?MODULE).
+
+write_failure(Config) ->
+ Dir = ?config(priv_dir, Config),
+ File = lists:concat([?MODULE,"_",?FUNCTION_NAME,".log"]),
+ Log = filename:join(Dir, File),
+ Node = start_std_h_on_new_node(Config, Log),
+ false = (undefined == rpc:call(Node, ets, whereis, [?TEST_HOOKS_TAB])),
+ rpc:call(Node, ets, insert, [?TEST_HOOKS_TAB,{tester,self()}]),
+ rpc:call(Node, ?MODULE, set_internal_log, [?MODULE,internal_log]),
+ rpc:call(Node, ?MODULE, set_result, [file_write,ok]),
+
+ ok = log_on_remote_node(Node, "Logged1"),
+ rpc:call(Node, logger_std_h, filesync, [?STANDARD_HANDLER]),
+ ?check_no_log,
+ try_read_file(Log, {ok,<<"Logged1\n">>}, filesync_rep_int()),
+
+ rpc:call(Node, ?MODULE, set_result, [file_write,{error,terminated}]),
+ ok = log_on_remote_node(Node, "Cause simple error printout"),
+
+ ?check({error,{?STANDARD_HANDLER,write,Log,{error,terminated}}}),
+
+ ok = log_on_remote_node(Node, "No second error printout"),
+ ?check_no_log,
+
+ rpc:call(Node, ?MODULE, set_result, [file_write,{error,eacces}]),
+ ok = log_on_remote_node(Node, "Cause simple error printout"),
+ ?check({error,{?STANDARD_HANDLER,write,Log,{error,eacces}}}),
+
+ rpc:call(Node, ?MODULE, set_result, [file_write,ok]),
+ ok = log_on_remote_node(Node, "Logged2"),
+ rpc:call(Node, logger_std_h, filesync, [?STANDARD_HANDLER]),
+ ?check_no_log,
+ try_read_file(Log, {ok,<<"Logged1\nLogged2\n">>}, filesync_rep_int()),
+ ok.
+write_failure(cleanup, _Config) ->
+ Nodes = nodes(),
+ [test_server:stop_node(Node) || Node <- Nodes].
+
+sync_failure(Config) ->
+ Dir = ?config(priv_dir, Config),
+ File = lists:concat([?MODULE,"_",?FUNCTION_NAME,".log"]),
+ Log = filename:join(Dir, File),
+ Node = start_std_h_on_new_node(Config, Log),
+ false = (undefined == rpc:call(Node, ets, whereis, [?TEST_HOOKS_TAB])),
+ rpc:call(Node, ets, insert, [?TEST_HOOKS_TAB,{tester,self()}]),
+ rpc:call(Node, ?MODULE, set_internal_log, [?MODULE,internal_log]),
+ rpc:call(Node, ?MODULE, set_result, [file_datasync,ok]),
+
+ SyncInt = 500,
+ ok = rpc:call(Node, logger, set_handler_config,
+ [?STANDARD_HANDLER, config,
+ #{filesync_repeat_interval => SyncInt}]),
+ Info = rpc:call(Node, logger_std_h, info, [?STANDARD_HANDLER]),
+ SyncInt = maps:get(filesync_repeat_interval, Info),
+
+ ok = log_on_remote_node(Node, "Logged1"),
+ ?check_no_log,
+
+ rpc:call(Node, ?MODULE, set_result, [file_datasync,{error,terminated}]),
+ ok = log_on_remote_node(Node, "Cause simple error printout"),
+
+ ?check({error,{?STANDARD_HANDLER,filesync,Log,{error,terminated}}}),
+
+ ok = log_on_remote_node(Node, "No second error printout"),
+ ?check_no_log,
+
+ rpc:call(Node, ?MODULE, set_result, [file_datasync,{error,eacces}]),
+ ok = log_on_remote_node(Node, "Cause simple error printout"),
+ ?check({error,{?STANDARD_HANDLER,filesync,Log,{error,eacces}}}),
+
+ rpc:call(Node, ?MODULE, set_result, [file_datasync,ok]),
+ ok = log_on_remote_node(Node, "Logged2"),
+ ?check_no_log,
+ ok.
+sync_failure(cleanup, _Config) ->
+ Nodes = nodes(),
+ [test_server:stop_node(Node) || Node <- Nodes].
+
+start_std_h_on_new_node(Config, Log) ->
+ {ok,_,Node} =
+ logger_test_lib:setup(
+ Config,
+ [{logger,[{handler,default,logger_std_h,
+ #{ config => #{ type => {file,Log}}}}]}]),
+ ok = rpc:call(Node,logger,set_handler_config,[?STANDARD_HANDLER,formatter,
+ {?MODULE,nl}]),
+ Node.
+
+%% functions for test hook macros to be called by rpc
+set_internal_log(_Mod, _Func) ->
+ ?set_internal_log({_Mod,_Func}).
+set_result(_Op, _Result) ->
+ ?set_result(_Op, _Result).
+set_defaults() ->
+ ?set_defaults().
+
+%% internal log function that sends the term to the test case process
+internal_log(Type, Term) ->
+ [{tester,Tester}] = ets:lookup(?TEST_HOOKS_TAB, tester),
+ Tester ! {log,{Type,Term}},
+ logger:internal_log(Type, Term),
+ ok.
+
+
+%%%-----------------------------------------------------------------
+%%% Overload protection tests
+
+op_switch_to_sync_file(Config) ->
+ {Log,HConfig,StdHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ NumOfReqs = 500,
+ NewHConfig =
+ HConfig#{config => StdHConfig#{sync_mode_qlen => 2,
+ drop_mode_qlen => NumOfReqs+1,
+ flush_qlen => 2*NumOfReqs,
+ burst_limit_enable => false}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ %% TRecvPid = start_op_trace(),
+ send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
+ Lines = count_lines(Log),
+ %% true = analyse_trace(TRecvPid,
+ %% fun(Events) -> find_mode(async,Events) end),
+ %% true = analyse_trace(TRecvPid,
+ %% fun(Events) -> find_mode(sync,Events) end),
+ %% true = analyse_trace(TRecvPid,
+ %% fun(Events) -> find_switch(async,sync,Events) end),
+ %% false = analyse_trace(TRecvPid,
+ %% fun(Events) -> find_mode(drop,Events) end),
+ %% false = analyse_trace(TRecvPid,
+ %% fun(Events) -> find_mode(flush,Events) end),
+ %% stop_op_trace(TRecvPid),
+ NumOfReqs = Lines,
+ ok = file_delete(Log),
+ ok.
+op_switch_to_sync_file(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+op_switch_to_sync_tty(Config) ->
+ {HConfig,StdHConfig} = start_handler(?MODULE, standard_io, Config),
+ NumOfReqs = 500,
+ NewHConfig =
+ HConfig#{config => StdHConfig#{sync_mode_qlen => 3,
+ drop_mode_qlen => NumOfReqs+1,
+ flush_qlen => 2*NumOfReqs,
+ burst_limit_enable => false}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
+ ok.
+op_switch_to_sync_tty(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+op_switch_to_drop_file() ->
+ [{timetrap,{seconds,180}}].
+op_switch_to_drop_file(Config) ->
+ Test =
+ fun() ->
+ {Log,HConfig,StdHConfig} =
+ start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ NumOfReqs = 300,
+ Procs = 2,
+ Bursts = 10,
+ NewHConfig =
+ HConfig#{config =>
+ StdHConfig#{sync_mode_qlen => 1,
+ drop_mode_qlen => 2,
+ flush_qlen =>
+ Procs*NumOfReqs*Bursts,
+ burst_limit_enable => false}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ %% It sometimes happens that the handler gets the
+ %% requests in a slow enough pace so that dropping
+ %% never occurs. Therefore, lets generate a number of
+ %% bursts to increase the chance of message buildup.
+ [send_burst({n,NumOfReqs}, {spawn,Procs,0}, {chars,79}, notice) ||
+ _ <- lists:seq(1, Bursts)],
+ Logged = count_lines(Log),
+ ok = stop_handler(?MODULE),
+ ct:pal("Number of messages dropped = ~w (~w)",
+ [Procs*NumOfReqs*Bursts-Logged,Procs*NumOfReqs*Bursts]),
+ true = (Logged < (Procs*NumOfReqs*Bursts)),
+ true = (Logged > 0),
+ _ = file_delete(Log),
+ ok
+ end,
+ %% As it's tricky to get the timing right in only one go, we perform the
+ %% test repeatedly, hoping that will generate a successful result.
+ case repeat_until_ok(Test, 10) of
+ {ok,{Failures,_Result}} ->
+ ct:log("Failed ~w times before success!", [Failures]);
+ {fails,Reason} ->
+ ct:fail(Reason)
+ end.
+op_switch_to_drop_file(cleanup, _Config) ->
+ _ = stop_handler(?MODULE).
+
+op_switch_to_drop_tty(Config) ->
+ {HConfig,StdHConfig} = start_handler(?MODULE, standard_io, Config),
+ NumOfReqs = 300,
+ Procs = 2,
+ NewHConfig =
+ HConfig#{config => StdHConfig#{sync_mode_qlen => 1,
+ drop_mode_qlen => 2,
+ flush_qlen =>
+ Procs*NumOfReqs+1,
+ burst_limit_enable => false}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ send_burst({n,NumOfReqs}, {spawn,Procs,0}, {chars,79}, notice),
+ ok.
+op_switch_to_drop_tty(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+op_switch_to_flush_file() ->
+ [{timetrap,{minutes,5}}].
+op_switch_to_flush_file(Config) ->
+ Test =
+ fun() ->
+ {Log,HConfig,StdHConfig} =
+ start_handler(?MODULE, ?FUNCTION_NAME, Config),
+
+ %% NOTE: it's important that both async and sync
+ %% requests have been queued when the flush happens
+ %% (verify with coverage of flush_log_requests/2)
+
+ NewHConfig =
+ HConfig#{config =>
+ StdHConfig#{sync_mode_qlen => 2,
+ %% disable drop mode
+ drop_mode_qlen => 300,
+ flush_qlen => 300,
+ burst_limit_enable => false}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ NumOfReqs = 1500,
+ Procs = 10,
+ Bursts = 10,
+ %% It sometimes happens that the handler either gets
+ %% the requests in a slow enough pace so that flushing
+ %% never occurs, or it gets all messages at once,
+ %% causing all messages to get flushed (no dropping of
+ %% sync messages gets tested). Therefore, lets
+ %% generate a number of bursts to increase the chance
+ %% of message buildup in some random fashion.
+ [send_burst({n,NumOfReqs}, {spawn,Procs,0}, {chars,79}, notice) ||
+ _ <- lists:seq(1,Bursts)],
+ Logged = count_lines(Log),
+ ok = stop_handler(?MODULE),
+ ct:pal("Number of messages flushed/dropped = ~w (~w)",
+ [NumOfReqs*Procs*Bursts-Logged,NumOfReqs*Procs*Bursts]),
+ true = (Logged < (NumOfReqs*Procs*Bursts)),
+ true = (Logged > 0),
+ _ = file_delete(Log),
+ ok
+ end,
+ %% As it's tricky to get the timing right in only one go, we perform the
+ %% test repeatedly, hoping that will generate a successful result.
+ case repeat_until_ok(Test, 10) of
+ {ok,{Failures,_Result}} ->
+ ct:log("Failed ~w times before success!", [Failures]);
+ {fails,Reason} ->
+ ct:fail(Reason)
+ end.
+op_switch_to_flush_file(cleanup, _Config) ->
+ _ = stop_handler(?MODULE).
+
+op_switch_to_flush_tty() ->
+ [{timetrap,{minutes,5}}].
+op_switch_to_flush_tty(Config) ->
+ {HConfig,StdHConfig} = start_handler(?MODULE, standard_io, Config),
+
+ %% it's important that both async and sync requests have been queued
+ %% when the flush happens (verify with coverage of flush_log_requests/2)
+
+ NewHConfig =
+ HConfig#{config => StdHConfig#{sync_mode_qlen => 2,
+ %% disable drop mode
+ drop_mode_qlen => 100,
+ flush_qlen => 100,
+ burst_limit_enable => false}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ NumOfReqs = 1000,
+ Procs = 100,
+ send_burst({n,NumOfReqs}, {spawn,Procs,0}, {chars,79}, notice),
+ ok.
+op_switch_to_flush_tty(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+limit_burst_disabled(Config) ->
+ {Log,HConfig,StdHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ NewHConfig =
+ HConfig#{config => StdHConfig#{burst_limit_enable => false,
+ burst_limit_max_count => 10,
+ burst_limit_window_time => 2000,
+ drop_mode_qlen => 200,
+ flush_qlen => 300}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ NumOfReqs = 100,
+ send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
+ Logged = count_lines(Log),
+ ct:pal("Number of messages logged = ~w", [Logged]),
+ NumOfReqs = Logged,
+ ok = file_delete(Log),
+ ok.
+limit_burst_disabled(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+limit_burst_enabled_one(Config) ->
+ {Log,HConfig,StdHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ ReqLimit = 10,
+ NewHConfig =
+ HConfig#{config => StdHConfig#{burst_limit_enable => true,
+ burst_limit_max_count => ReqLimit,
+ burst_limit_window_time => 2000,
+ drop_mode_qlen => 200,
+ flush_qlen => 300}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ NumOfReqs = 100,
+ send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
+ Logged = count_lines(Log),
+ ct:pal("Number of messages logged = ~w", [Logged]),
+ ReqLimit = Logged,
+ ok = file_delete(Log),
+ ok.
+limit_burst_enabled_one(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+limit_burst_enabled_period(Config) ->
+ {Log,HConfig,StdHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ ReqLimit = 10,
+ BurstTWin = 1000,
+ NewHConfig =
+ HConfig#{config => StdHConfig#{burst_limit_enable => true,
+ burst_limit_max_count => ReqLimit,
+ burst_limit_window_time => BurstTWin,
+ drop_mode_qlen => 20000,
+ flush_qlen => 20001}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+
+ Windows = 3,
+ Sent = send_burst({t,BurstTWin*Windows}, seq, {chars,79}, notice),
+ Logged = count_lines(Log),
+ ct:pal("Number of messages sent = ~w~nNumber of messages logged = ~w",
+ [Sent,Logged]),
+ true = (Logged > (ReqLimit*Windows)) andalso
+ (Logged < (ReqLimit*(Windows+2))),
+ ok = file_delete(Log),
+ ok.
+limit_burst_enabled_period(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+kill_disabled(Config) ->
+ {Log,HConfig,StdHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ NewHConfig =
+ HConfig#{config=>StdHConfig#{overload_kill_enable=>false,
+ overload_kill_qlen=>10,
+ overload_kill_mem_size=>100}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ NumOfReqs = 100,
+ send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
+ Logged = count_lines(Log),
+ ct:pal("Number of messages logged = ~w", [Logged]),
+ ok = file_delete(Log),
+ true = is_pid(whereis(h_proc_name())),
+ ok.
+kill_disabled(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+qlen_kill_new(Config) ->
+ {Log,HConfig,StdHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ Pid0 = whereis(h_proc_name()),
+ {_,Mem0} = process_info(Pid0, memory),
+ RestartAfter = ?OVERLOAD_KILL_RESTART_AFTER,
+ NewHConfig =
+ HConfig#{config=>StdHConfig#{overload_kill_enable=>true,
+ overload_kill_qlen=>10,
+ overload_kill_mem_size=>Mem0+50000,
+ overload_kill_restart_after=>RestartAfter}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ MRef = erlang:monitor(process, Pid0),
+ NumOfReqs = 100,
+ Procs = 4,
+ send_burst({n,NumOfReqs}, {spawn,Procs,0}, {chars,79}, notice),
+ %% send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
+ receive
+ {'DOWN', MRef, _, _, Info} ->
+ case Info of
+ {shutdown,{overloaded,?MODULE,QLen,Mem}} ->
+ ct:pal("Terminated with qlen = ~w, mem = ~w", [QLen,Mem]);
+ killed ->
+ ct:pal("Slow shutdown, handler process was killed!", [])
+ end,
+ file_delete(Log),
+ {ok,_} = wait_for_process_up(RestartAfter * 3),
+ ok
+ after
+ 5000 ->
+ Info = logger_std_h:info(?MODULE),
+ ct:pal("Handler state = ~p", [Info]),
+ ct:fail("Handler not dead! It should not have survived this!")
+ end.
+qlen_kill_new(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+%% choke the standard handler on remote node to verify the termination
+%% works as expected
+qlen_kill_std(_Config) ->
+ %%! HERE
+ %% Dir = ?config(priv_dir, Config),
+ %% File = lists:concat([?MODULE,"_",?FUNCTION_NAME,".log"]),
+ %% Log = filename:join(Dir, File),
+ %% Node = start_std_h_on_new_node(Config, ?FUNCTION_NAME, Log),
+ %% ok = rpc:call(Node, logger, set_handler_config,
+ %% [?STANDARD_HANDLER, config,
+ %% #{overload_kill_enable=>true,
+ %% overload_kill_qlen=>10,
+ %% overload_kill_mem_size=>100000}]),
+ {skip,"Not done yet"}.
+
+mem_kill_new(Config) ->
+ {Log,HConfig,StdHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ Pid0 = whereis(h_proc_name()),
+ {_,Mem0} = process_info(Pid0, memory),
+ RestartAfter = ?OVERLOAD_KILL_RESTART_AFTER,
+ NewHConfig =
+ HConfig#{config=>StdHConfig#{overload_kill_enable=>true,
+ overload_kill_qlen=>50000,
+ overload_kill_mem_size=>Mem0+500,
+ overload_kill_restart_after=>RestartAfter}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ MRef = erlang:monitor(process, Pid0),
+ NumOfReqs = 100,
+ Procs = 4,
+ send_burst({n,NumOfReqs}, {spawn,Procs,0}, {chars,79}, notice),
+ %% send_burst({n,NumOfReqs}, seq, {chars,79}, notice),
+ receive
+ {'DOWN', MRef, _, _, Info} ->
+ case Info of
+ {shutdown,{overloaded,?MODULE,QLen,Mem}} ->
+ ct:pal("Terminated with qlen = ~w, mem = ~w", [QLen,Mem]);
+ killed ->
+ ct:pal("Slow shutdown, handler process was killed!", [])
+ end,
+ file_delete(Log),
+ {ok,_} = wait_for_process_up(RestartAfter * 3),
+ ok
+ after
+ 5000 ->
+ Info = logger_std_h:info(?MODULE),
+ ct:pal("Handler state = ~p", [Info]),
+ ct:fail("Handler not dead! It should not have survived this!")
+ end.
+mem_kill_new(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+%% choke the standard handler on remote node to verify the termination
+%% works as expected
+mem_kill_std(_Config) ->
+ {skip,"Not done yet"}.
+
+restart_after() ->
+ [{timetrap,{minutes,2}}].
+restart_after(Config) ->
+ {Log,HConfig,StdHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ NewHConfig1 =
+ HConfig#{config=>StdHConfig#{overload_kill_enable=>true,
+ overload_kill_qlen=>10,
+ overload_kill_restart_after=>infinity}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig1),
+ MRef1 = erlang:monitor(process, whereis(h_proc_name())),
+ %% kill handler
+ send_burst({n,100}, {spawn,4,0}, {chars,79}, notice),
+ receive
+ {'DOWN', MRef1, _, _, _Reason1} ->
+ file_delete(Log),
+ error = wait_for_process_up(?OVERLOAD_KILL_RESTART_AFTER * 3),
+ ok
+ after
+ 5000 ->
+ Info1 = logger_std_h:info(?MODULE),
+ ct:pal("Handler state = ~p", [Info1]),
+ ct:fail("Handler not dead! It should not have survived this!")
+ end,
+
+ {Log,_,_} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ RestartAfter = ?OVERLOAD_KILL_RESTART_AFTER,
+ NewHConfig2 =
+ HConfig#{config=>StdHConfig#{overload_kill_enable=>true,
+ overload_kill_qlen=>10,
+ overload_kill_restart_after=>RestartAfter}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig2),
+ Pid0 = whereis(h_proc_name()),
+ MRef2 = erlang:monitor(process, Pid0),
+ %% kill handler
+ send_burst({n,100}, {spawn,4,0}, {chars,79}, notice),
+ receive
+ {'DOWN', MRef2, _, _, _Reason2} ->
+ file_delete(Log),
+ {ok,Pid1} = wait_for_process_up(RestartAfter * 3),
+ false = (Pid1 == Pid0),
+ ok
+ after
+ 5000 ->
+ Info2 = logger_std_h:info(?MODULE),
+ ct:pal("Handler state = ~p", [Info2]),
+ ct:fail("Handler not dead! It should not have survived this!")
+ end,
+ ok.
+restart_after(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+%% send handler requests (sync, info, reset, change_config)
+%% during high load to verify that sync, dropping and flushing is
+%% handled correctly.
+handler_requests_under_load() ->
+ [{timetrap,{minutes,3}}].
+handler_requests_under_load(Config) ->
+ {Log,HConfig,StdHConfig} =
+ start_handler(?MODULE, ?FUNCTION_NAME, Config),
+ NewHConfig =
+ HConfig#{config => StdHConfig#{sync_mode_qlen => 2,
+ drop_mode_qlen => 1000,
+ flush_qlen => 2000,
+ burst_limit_enable => false}},
+ ok = logger:set_handler_config(?MODULE, NewHConfig),
+ Pid = spawn_link(fun() -> send_requests(?MODULE, 1, [{filesync,[]},
+ {info,[]},
+ {reset,[]},
+ {change_config,[]}])
+ end),
+ Sent = send_burst({t,10000}, seq, {chars,79}, notice),
+ Pid ! {self(),finish},
+ ReqResult = receive {Pid,Result} -> Result end,
+ Logged = count_lines(Log),
+ ct:pal("Number of messages sent = ~w~nNumber of messages logged = ~w",
+ [Sent,Logged]),
+ FindError = fun(Res) ->
+ [E || E <- Res,
+ is_tuple(E) andalso (element(1,E) == error)]
+ end,
+ Errors = [{Req,FindError(Res)} || {Req,Res} <- ReqResult],
+ NoOfReqs = lists:foldl(fun({_,Res}, N) -> N + length(Res) end, 0, ReqResult),
+ ct:pal("~w requests made. Errors: ~n~p", [NoOfReqs,Errors]),
+ ok = file_delete(Log).
+handler_requests_under_load(cleanup, _Config) ->
+ ok = stop_handler(?MODULE).
+
+send_requests(HName, TO, Reqs = [{Req,Res}|Rs]) ->
+ receive
+ {From,finish} ->
+ From ! {self(),Reqs}
+ after
+ TO ->
+ Result =
+ case Req of
+ change_config ->
+ logger:set_handler_config(HName, config,
+ #{overload_kill_enable =>
+ false});
+ Func ->
+ logger_std_h:Func(HName)
+ end,
+ send_requests(HName, TO, Rs ++ [{Req,[Result|Res]}])
+ end.
+
+
+%%%-----------------------------------------------------------------
+%%%
+start_handler(Name, TTY, Config) when TTY == standard_io;
+ TTY == standard_error->
+ ok = logger:add_handler(Name,
+ logger_std_h,
+ #{config => #{type => TTY},
+ filter_default=>log,
+ filters=>?DEFAULT_HANDLER_FILTERS([Name]),
+ formatter=>{?MODULE,op}}),
+ {ok,HConfig = #{config := StdHConfig}} = logger:get_handler_config(Name),
+ {HConfig,StdHConfig};
+
+start_handler(Name, FuncName, Config) ->
+ Dir = ?config(priv_dir,Config),
+ Log = filename:join(Dir, lists:concat([FuncName,".log"])),
+ ct:pal("Logging to ~tp", [Log]),
+ Type = {file,Log},
+ _ = file_delete(Log),
+ ok = logger:add_handler(Name,
+ logger_std_h,
+ #{config => #{type => Type},
+ filter_default=>log,
+ filters=>?DEFAULT_HANDLER_FILTERS([Name]),
+ formatter=>{?MODULE,op}}),
+ {ok,HConfig = #{config := StdHConfig}} = logger:get_handler_config(Name),
+ {Log,HConfig,StdHConfig}.
+
+stop_handler(Name) ->
+ R = logger:remove_handler(Name),
+ ct:pal("Handler ~p stopped! Result: ~p", [Name,R]),
+ R.
+
+count_lines(File) ->
+ wait_until_written(File, -1),
+ count_lines1(File).
+
+wait_until_written(File, Sz) ->
+ timer:sleep(2000),
+ case file:read_file_info(File) of
+ {ok,#file_info{size = Sz}} ->
+ timer:sleep(1000),
+ case file:read_file_info(File) of
+ {ok,#file_info{size = Sz}} ->
+ ok;
+ {ok,#file_info{size = Sz1}} ->
+ wait_until_written(File, Sz1)
+ end;
+ {ok,#file_info{size = Sz1}} ->
+ wait_until_written(File, Sz1)
+ end.
+
+count_lines1(File) ->
+ {_,Dev} = file:open(File, [read]),
+ Lines = count_lines2(Dev, 0),
+ file:close(Dev),
+ Lines.
+
+count_lines2(Dev, LC) ->
+ case file:read_line(Dev) of
+ {ok,"Handler logger_std_h_SUITE " ++_} ->
+ %% Not counting handler info
+ count_lines2(Dev,LC);
+ {ok,_} ->
+ count_lines2(Dev,LC+1);
+ eof -> LC
+ end.
+
+send_burst(NorT, Type, {chars,Sz}, Class) ->
+ Text = [34 + rand:uniform(126-34) || _ <- lists:seq(1,Sz)],
+ case NorT of
+ {n,N} ->
+ %% process_flag(priority, high),
+ send_n_burst(N, Type, Text, Class),
+ %% process_flag(priority, normal),
+ N;
+ {t,T} ->
+ ct:pal("Sending messages sequentially for ~w ms", [T]),
+ T0 = erlang:monotonic_time(millisecond),
+ send_t_burst(T0, T, Text, Class, 0)
+ end.
+
+send_n_burst(0, _, _Text, _Class) ->
+ ok;
+send_n_burst(N, seq, Text, Class) ->
+ ok = logger:Class(Text, ?domain),
+ send_n_burst(N-1, seq, Text, Class);
+send_n_burst(N, {spawn,Ps,TO}, Text, Class) ->
+ ct:pal("~w processes each sending ~w messages", [Ps,N]),
+ MRefs = [begin if TO == 0 -> ok; true -> timer:sleep(TO) end,
+ monitor(process,spawn_link(per_proc_fun(N,Text,Class,X)))
+ end || X <- lists:seq(1,Ps)],
+ lists:foreach(fun(MRef) ->
+ receive
+ {'DOWN', MRef, _, _, _} ->
+ ok
+ end
+ end, MRefs),
+ ct:pal("Message burst sent", []),
+ ok.
+
+send_t_burst(T0, T, Text, Class, N) ->
+ T1 = erlang:monotonic_time(millisecond),
+ if (T1-T0) > T ->
+ N;
+ true ->
+ ok = logger:Class(Text, ?domain),
+ send_t_burst(T0, T, Text, Class, N+1)
+ end.
+
+per_proc_fun(N,Text,Class,X) when X rem 2 == 0 ->
+ fun() ->
+ process_flag(priority,high),
+ send_n_burst(N, seq, Text, Class)
+ end;
+per_proc_fun(N,Text,Class,_) ->
+ fun() ->
+ send_n_burst(N, seq, Text, Class)
+ end.
+
+%%%-----------------------------------------------------------------
+%%% Formatter callback
+%%% Using this to send the formatted string back to the test case
+%%% process - so it can check for logged events.
+format(_,bad_return) ->
+ bad_return;
+format(_,crash) ->
+ erlang:error(formatter_crashed);
+format(#{msg:={string,String0}},no_nl) ->
+ String = unicode:characters_to_list(String0),
+ String;
+format(#{msg:={string,String0}},nl) ->
+ String = unicode:characters_to_list(String0),
+ String++"\n";
+format(#{msg:={string,String0}},op) ->
+ String = unicode:characters_to_list(String0),
+ String++"\n";
+format(#{msg:={report,#{label:={supervisor,progress}}}},op) ->
+ "";
+format(#{msg:={report,#{label:={gen_server,terminate}}}},op) ->
+ "";
+format(#{msg:={report,#{label:={proc_lib,crash}}}},op) ->
+ "";
+format(#{msg:={F,A}},OpOrPid) when is_list(F), is_list(A) ->
+ String = lists:flatten(io_lib:format(F,A)),
+ if is_pid(OpOrPid) -> OpOrPid ! {log,String};
+ true -> ok
+ end,
+ String++"\n";
+format(#{msg:={string,String0}},Pid) ->
+ String = unicode:characters_to_list(String0),
+ Pid ! {log,String},
+ String++"\n".
+
+add_remove_instance_nofile(Type) ->
+ ok = logger:add_handler(?MODULE,logger_std_h,
+ #{config => #{type => Type},
+ filter_default=>stop,
+ filters=>?DEFAULT_HANDLER_FILTERS([?MODULE]),
+ formatter=>{?MODULE,self()}}),
+ Pid = whereis(h_proc_name()),
+ true = is_pid(Pid),
+ group_leader(group_leader(),Pid), % to get printouts in test log
+ logger:notice(M1=?msg,?domain),
+ ?check(M1),
+ %% check that sync doesn't do damage even if not relevant
+ ok = logger_std_h:filesync(?MODULE),
+ ok = logger:remove_handler(?MODULE),
+ timer:sleep(500),
+ undefined = whereis(h_proc_name()),
+ logger:notice(?msg,?domain),
+ ?check_no_log,
+ ok.
+
+logger_std_h_remove() ->
+ logger:remove_handler(?MODULE).
+logger_std_h_remove(Id) ->
+ logger:remove_handler(Id).
+
+try_read_file(FileName, Expected, Time) when Time > 0 ->
+ case file:read_file(FileName) of
+ Expected ->
+ ok;
+ Error = {error,_Reason} ->
+ ct:pal("Can't read ~tp: ~tp", [FileName,Error]),
+ erlang:error(Error);
+ Got ->
+ ct:pal("try_read_file got ~tp", [Got]),
+ timer:sleep(500),
+ try_read_file(FileName, Expected, Time-500)
+ end;
+try_read_file(FileName, Expected, _) ->
+ ct:pal("Missing pattern ~tp in ~tp", [Expected,FileName]),
+ erlang:error({error,missing_expected_pattern}).
+
+try_match_file(FileName, Pattern, Time) ->
+ try_match_file(FileName, Pattern, Time, <<>>).
+
+try_match_file(FileName, Pattern, Time, _) when Time > 0 ->
+ case file:read_file(FileName) of
+ {ok, Bin} ->
+ case re:run(Bin,Pattern,[{capture,none}]) of
+ match ->
+ unicode:characters_to_list(Bin);
+ _ ->
+ timer:sleep(100),
+ try_match_file(FileName, Pattern, Time-100, Bin)
+ end;
+ Error ->
+ erlang:error(Error)
+ end;
+try_match_file(_,Pattern,_,Incorrect) ->
+ ct:pal("try_match_file did not match pattern: ~p~nGot: ~p~n",
+ [Pattern,Incorrect]),
+ erlang:error({error,not_matching_pattern,Pattern,Incorrect}).
+
+repeat_until_ok(Fun, N) ->
+ repeat_until_ok(Fun, 0, N, undefined).
+
+repeat_until_ok(_Fun, Stop, Stop, Reason) ->
+ {fails,Reason};
+
+repeat_until_ok(Fun, C, Stop, FirstReason) ->
+ if C > 0 -> timer:sleep(5000);
+ true -> ok
+ end,
+ try Fun() of
+ Result ->
+ {ok,{C,Result}}
+ catch
+ _:Reason:Stack ->
+ ct:pal("Test fails: ~p (~p)~n", [Reason,hd(Stack)]),
+ if FirstReason == undefined ->
+ repeat_until_ok(Fun, C+1, Stop, {Reason,Stack});
+ true ->
+ repeat_until_ok(Fun, C+1, Stop, FirstReason)
+ end
+ end.
+
+
+%%%-----------------------------------------------------------------
+%%%
+start_op_trace() ->
+ TraceFun = fun({trace,_,call,{_Mod,Func,Details}}, Pid) ->
+ Pid ! {trace_call,Func,Details},
+ Pid;
+ ({trace,_,return_from,{_Mod,Func,_},RetVal}, Pid) ->
+ Pid ! {trace_return,Func,RetVal},
+ Pid
+ end,
+ TRecvPid = spawn_link(fun() -> trace_receiver(5000) end),
+ {ok,_} = dbg:tracer(process, {TraceFun, TRecvPid}),
+
+ {ok,_} = dbg:p(whereis(h_proc_name()), [c]),
+ {ok,_} = dbg:p(self(), [c]),
+
+ MS1 = dbg:fun2ms(fun([_]) -> return_trace() end),
+ {ok,_} = dbg:tp(logger_h_common, check_load, 1, MS1),
+
+ {ok,_} = dbg:tpl(logger_h_common, flush_log_requests, 2, []),
+
+ MS2 = dbg:fun2ms(fun([_,mode]) -> return_trace() end),
+ {ok,_} = dbg:tpl(ets, lookup, 2, MS2),
+
+ ct:pal("Tracing started!", []),
+ TRecvPid.
+
+stop_op_trace(TRecvPid) ->
+ dbg:stop_clear(),
+ unlink(TRecvPid),
+ exit(TRecvPid, kill),
+ ok.
+
+find_mode(flush, Events) ->
+ lists:any(fun({trace_call,flush_log_requests,[_,_]}) -> true;
+ (_) -> false
+ end, Events);
+find_mode(Mode, Events) ->
+ lists:keymember([{mode,Mode}], 3, Events).
+
+%% find_switch(_From, To, Events) ->
+%% try lists:foldl(fun({trace_return,check_load,{To,_,_,_}},
+%% {trace_call,check_load,[#{mode := From}]}) ->
+%% throw(match);
+%% (Event, _) ->
+%% Event
+%% end, undefined, Events) of
+%% _ -> false
+%% catch
+%% throw:match -> true
+%% end.
+
+analyse_trace(TRecvPid, TestFun) ->
+ TRecvPid ! {test,self(),TestFun},
+ receive
+ {result,TRecvPid,Result} ->
+ Result
+ after
+ 60000 ->
+ fails
+ end.
+
+trace_receiver(IdleT) ->
+ Msgs = receive_until_idle(IdleT, 5, []),
+ ct:pal("~w trace events generated", [length(Msgs)]),
+ analyse(Msgs).
+
+receive_until_idle(IdleT, WaitN, Msgs) ->
+ receive
+ Msg = {trace_call,_,_} ->
+ receive_until_idle(IdleT, 5, [Msg | Msgs]);
+ Msg = {trace_return,_,_} ->
+ receive_until_idle(IdleT, 5, [Msg | Msgs])
+ after
+ IdleT ->
+ if WaitN == 0 ->
+ Msgs;
+ true ->
+ receive_until_idle(IdleT, WaitN-1, Msgs)
+ end
+ end.
+
+analyse(Msgs) ->
+ receive
+ {test,From,TestFun} ->
+ From ! {result,self(),TestFun(Msgs)},
+ analyse(Msgs)
+ end.
+
+start_tracer(Trace,Expected) ->
+ Pid = self(),
+ FileCtrlPid = maps:get(file_ctrl_pid, logger_std_h:info(?MODULE)),
+ dbg:tracer(process,{fun tracer/2,{Pid,Expected}}),
+ dbg:p(whereis(h_proc_name()),[c]),
+ dbg:p(FileCtrlPid,[c]),
+ tpl(Trace),
+ ok.
+
+tpl([{M,F,A}|Trace]) ->
+ {ok,Match} = dbg:tpl(M,F,A,[]),
+ case lists:keyfind(matched,1,Match) of
+ {_,_,1} ->
+ ok;
+ _ ->
+ dbg:stop_clear(),
+ throw({skip,"Can't trace "++atom_to_list(M)++":"++
+ atom_to_list(F)++"/"++integer_to_list(A)})
+ end,
+ tpl(Trace);
+tpl([]) ->
+ ok.
+
+tracer({trace,_,call,{logger_std_h,handle_cast,[Op|_]}},
+ {Pid,[{Mod,Func,Op}|Expected]}) ->
+ maybe_tracer_done(Pid,Expected,{Mod,Func,Op});
+tracer({trace,_,call,{Mod=logger_std_h,Func=write_to_dev,[_,Data,_,_,_]}},
+ {Pid,[{Mod,Func,Data}|Expected]}) ->
+ maybe_tracer_done(Pid,Expected,{Mod,Func,Data});
+tracer({trace,_,call,{Mod,Func,_}}, {Pid,[{Mod,Func}|Expected]}) ->
+ maybe_tracer_done(Pid,Expected,{Mod,Func});
+tracer({trace,_,call,Call}, {Pid,Expected}) ->
+ ct:log("Tracer got unexpected: ~p~nExpected: ~p~n",[Call,Expected]),
+ Pid ! {tracer_got_unexpected,Call,Expected},
+ {Pid,Expected}.
+
+maybe_tracer_done(Pid,[]=Expected,Got) ->
+ ct:log("Tracer got: ~p~n",[Got]),
+ Pid ! {tracer_done,0},
+ {Pid,Expected};
+maybe_tracer_done(Pid,[{no_more,T}]=Expected,Got) ->
+ ct:log("Tracer got: ~p~n",[Got]),
+ Pid ! {tracer_done,T},
+ {Pid,Expected};
+maybe_tracer_done(Pid,Expected,Got) ->
+ ct:log("Tracer got: ~p~n",[Got]),
+ {Pid,Expected}.
+
+check_tracer(T) ->
+ check_tracer(T,fun() -> ct:fail({timeout,tracer}) end).
+check_tracer(T,TimeoutFun) ->
+ receive
+ {tracer_done,Delay} ->
+ %% Possibly wait Delay ms to check that no unexpected
+ %% traces are received
+ check_tracer(Delay,fun() -> ok end);
+ {tracer_got_unexpected,Got,Expected} ->
+ dbg:stop_clear(),
+ ct:fail({tracer_got_unexpected,Got,Expected})
+ after T ->
+ dbg:stop_clear(),
+ TimeoutFun()
+ end.
+
+escape([$+|Rest]) ->
+ [$\\,$+|escape(Rest)];
+escape([H|T]) ->
+ [H|escape(T)];
+escape([]) ->
+ [].
+
+h_proc_name() ->
+ h_proc_name(?MODULE).
+h_proc_name(Name) ->
+ ?name_to_reg_name(logger_std_h,Name).
+
+wait_for_process_up(T) ->
+ wait_for_process_up(?MODULE, h_proc_name(), T).
+
+wait_for_process_up(Name, RegName, T) ->
+ N = (T div 500) + 1,
+ wait_for_process_up1(Name, RegName, N).
+
+wait_for_process_up1(_Name, _RegName, 0) ->
+ error;
+wait_for_process_up1(Name, RegName, N) ->
+ timer:sleep(500),
+ case whereis(RegName) of
+ Pid when is_pid(Pid) ->
+ case logger:get_handler_config(Name) of
+ {ok,_} ->
+ %% ct:pal("Process ~p up (~p tries left)",[Name,N]),
+ {ok,Pid};
+ _ ->
+ wait_for_process_up1(Name, RegName, N-1)
+ end;
+ undefined ->
+ %% ct:pal("Waiting for process ~p (~p tries left)",[Name,N]),
+ wait_for_process_up1(Name, RegName, N-1)
+ end.
+
+filesync_rep_int() ->
+ case (fun() -> is_atom(?FILESYNC_REPEAT_INTERVAL) end)() of
+ true -> 5500;
+ false -> ?FILESYNC_REPEAT_INTERVAL + 500
+ end.
+
+
+file_delete(Log) ->
+ file:delete(Log).
+
diff --git a/lib/kernel/test/logger_test_lib.erl b/lib/kernel/test/logger_test_lib.erl
new file mode 100644
index 0000000000..81eb9ce5eb
--- /dev/null
+++ b/lib/kernel/test/logger_test_lib.erl
@@ -0,0 +1,82 @@
+%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(logger_test_lib).
+
+-include_lib("kernel/src/logger_internal.hrl").
+
+-export([setup/2, log/3, sync_and_read/3]).
+
+-export([init/2,
+ pre_init_per_suite/3, pre_init_per_testcase/4,
+ post_end_per_testcase/5, post_end_per_suite/3]).
+
+setup(Config,Vars) ->
+ FuncStr = lists:concat([proplists:get_value(suite, Config), "_",
+ proplists:get_value(tc, Config)]),
+ ConfigFileName = filename:join(proplists:get_value(priv_dir, Config), FuncStr),
+ file:write_file(ConfigFileName ++ ".config", io_lib:format("[{kernel, ~p}].",[Vars])),
+ case test_server:start_node(proplists:get_value(tc, Config), slave,
+ [{args, ["-pa ",filename:dirname(code:which(?MODULE)),
+ " -boot start_sasl -kernel start_timer true "
+ "-config ",ConfigFileName]}]) of
+ {ok, Node} ->
+ L = rpc:call(Node, logger, get_config, []),
+ ct:log("~p",[L]),
+ {ok, L, Node};
+ {error, Reason} ->
+ ct:log("Failed to start node: ~p",[Reason]),
+ error
+ end.
+
+log(Node, F, A) ->
+ log(Node, logger, F, A).
+log(Node, M, F, A) ->
+ MD = #{ gl => rpc:call(Node, erlang, whereis, [logger]) },
+ rpc:call(Node, M, F, A ++ [MD]).
+
+sync_and_read(Node,disk_log,Log) ->
+ rpc:call(Node,logger_disk_log_h,filesync,[?STANDARD_HANDLER]),
+ file:read_file(Log ++ ".1");
+sync_and_read(Node, file,Log) ->
+ ok = rpc:call(Node,logger_std_h,filesync,[?STANDARD_HANDLER]),
+ file:read_file(Log).
+
+
+init(_, _) ->
+ {ok, []}.
+
+pre_init_per_suite(_Suite, Config, State) ->
+ {[{nodes, nodes()} | Config], State}.
+
+pre_init_per_testcase(Suite, TC, Config, State) ->
+ cleanup(Config),
+ {[{suite, Suite}, {tc, TC} | Config], State}.
+
+post_end_per_testcase(_, _TC, Config, Res, State) ->
+ cleanup(Config),
+ {Res, State}.
+
+post_end_per_suite(_, Config, State) ->
+ cleanup(Config),
+ {Config, State}.
+
+cleanup(Config) ->
+ [test_server:stop_node(N) || N <- nodes(),
+ not lists:member(N, proplists:get_value(nodes, Config))].
diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl
index 53a9e168ef..710b9b115c 100644
--- a/lib/kernel/test/os_SUITE.erl
+++ b/lib/kernel/test/os_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,10 +22,12 @@
-export([all/0, suite/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]).
--export([space_in_cwd/1, quoting/1, cmd_unicode/1, space_in_name/1, bad_command/1,
+-export([space_in_cwd/1, quoting/1, cmd_unicode/1,
+ null_in_command/1, space_in_name/1, bad_command/1,
find_executable/1, unix_comment_in_command/1, deep_list_command/1,
large_output_command/1, background_command/0, background_command/1,
- message_leak/1, close_stdin/0, close_stdin/1, perf_counter_api/1]).
+ message_leak/1, close_stdin/0, close_stdin/1, max_size_command/1,
+ perf_counter_api/1]).
-include_lib("common_test/include/ct.hrl").
@@ -34,10 +36,11 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- [space_in_cwd, quoting, cmd_unicode, space_in_name, bad_command,
+ [space_in_cwd, quoting, cmd_unicode, null_in_command,
+ space_in_name, bad_command,
find_executable, unix_comment_in_command, deep_list_command,
large_output_command, background_command, message_leak,
- close_stdin, perf_counter_api].
+ close_stdin, max_size_command, perf_counter_api].
groups() ->
[].
@@ -125,6 +128,14 @@ cmd_unicode(Config) when is_list(Config) ->
[] = receive_all(),
ok.
+null_in_command(Config) ->
+ {Ok, Error} = case os:type() of
+ {win32,_} -> {"dir", "di\0r"};
+ _ -> {"ls", "l\0s"}
+ end,
+ true = is_list(try os:cmd(Ok) catch Class0:_ -> Class0 end),
+ error = try os:cmd(Error) catch Class1:_ -> Class1 end,
+ ok.
%% Test that program with a space in its name can be executed.
space_in_name(Config) when is_list(Config) ->
@@ -216,8 +227,8 @@ find_executable(Config) when is_list(Config) ->
DataDir = proplists:get_value(data_dir, Config),
%% Smoke test.
- case lib:progname() of
- erl ->
+ case ct:get_progname() of
+ "erl" ->
ErlPath = os:find_executable("erl"),
true = is_list(ErlPath),
true = filelib:is_regular(ErlPath);
@@ -312,6 +323,19 @@ close_stdin(Config) ->
"-1" = os:cmd(Fds).
+max_size_command(_Config) ->
+
+ Res20 = os:cmd("cat /dev/zero", #{ max_size => 20 }),
+ 20 = length(Res20),
+
+ Res0 = os:cmd("cat /dev/zero", #{ max_size => 0 }),
+ 0 = length(Res0),
+
+ Res32768 = os:cmd("cat /dev/zero", #{ max_size => 32768 }),
+ 32768 = length(Res32768),
+
+ ResHello = string:trim(os:cmd("echo hello", #{ max_size => 20 })),
+ 5 = length(ResHello).
%% Test that the os:perf_counter api works as expected
perf_counter_api(_Config) ->
@@ -364,7 +388,7 @@ comp(Expected, Got) ->
ct:fail(failed)
end.
-%% Like lib:nonl/1, but strips \r as well as \n.
+%% strips \n and \r\n from end of string
strip_nl([$\r, $\n]) -> [];
strip_nl([$\n]) -> [];
diff --git a/lib/kernel/test/pdict_SUITE.erl b/lib/kernel/test/pdict_SUITE.erl
index d105952df9..3685e51c10 100644
--- a/lib/kernel/test/pdict_SUITE.erl
+++ b/lib/kernel/test/pdict_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
init_per_group/2,end_per_group/2,
mixed/1,
literals/1,
+ destructive/1,
simple/1, complicated/1, heavy/1, simple_all_keys/1, info/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
-export([other_process/2]).
@@ -52,6 +53,7 @@ suite() ->
all() ->
[simple, complicated, heavy, simple_all_keys, info,
literals,
+ destructive,
mixed].
groups() ->
@@ -367,6 +369,36 @@ match_keys(All) ->
ok.
+%% Test destructive put optimization of immed values
+%% does not affect get/0 or process_info.
+destructive(_Config) ->
+ Keys = lists:seq(1,100),
+ [put(Key, 17) || Key <- Keys],
+ Get1 = get(),
+ {dictionary,PI1} = process_info(self(), dictionary),
+
+ [begin
+ {Key, 17} = lists:keyfind(Key, 1, Get1),
+ {Key, 17} = lists:keyfind(Key, 1, PI1)
+ end
+ || Key <- Keys],
+
+ [17 = put(Key, 42) || Key <- Keys], % Mutate
+
+ Get2 = get(),
+ {dictionary,PI2} = process_info(self(), dictionary),
+
+ [begin
+ {Key, 17} = lists:keyfind(Key, 1, Get1),
+ {Key, 17} = lists:keyfind(Key, 1, PI1),
+ {Key, 42} = lists:keyfind(Key, 1, Get2),
+ {Key, 42} = lists:keyfind(Key, 1, PI2)
+
+ end
+ || Key <- Keys],
+
+ ok.
+
%% Do random mixed put/erase to test grow/shrink
%% Written for a temporary bug in gc during shrink
mixed(_Config) ->
diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl
index 2f4330c217..a02b5f87d1 100644
--- a/lib/kernel/test/prim_file_SUITE.erl
+++ b/lib/kernel/test/prim_file_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,38 +21,23 @@
-export([all/0, suite/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,
read_write_file/1, free_memory/0]).
--export([cur_dir_0a/1, cur_dir_0b/1,
- cur_dir_1a/1, cur_dir_1b/1,
- make_del_dir_a/1, make_del_dir_b/1,
- pos1/1, pos2/1]).
--export([close/1,
- delete_a/1, delete_b/1]).
--export([ open1/1, modes/1]).
--export([
- file_info_basic_file_a/1, file_info_basic_file_b/1,
- file_info_basic_directory_a/1, file_info_basic_directory_b/1,
- file_info_bad_a/1, file_info_bad_b/1,
- file_info_times_a/1, file_info_times_b/1,
- file_write_file_info_a/1, file_write_file_info_b/1,
- file_read_file_info_opts/1, file_write_file_info_opts/1,
- file_write_read_file_info_opts/1
- ]).
--export([rename_a/1, rename_b/1,
- access/1, truncate/1, datasync/1, sync/1,
+-export([cur_dir_0/1, cur_dir_1/1,
+ make_del_dir/1, pos1/1, pos2/1]).
+-export([close/1, delete/1]).
+-export([open1/1, modes/1]).
+-export([file_info_basic_file/1, file_info_basic_directory/1, file_info_bad/1,
+ file_info_times/1, file_write_file_info/1,
+ file_read_file_info_opts/1, file_write_file_info_opts/1,
+ file_write_read_file_info_opts/1]).
+-export([rename/1, access/1, truncate/1, datasync/1, sync/1,
read_write/1, pread_write/1, append/1, exclusive/1]).
--export([ e_delete/1, e_rename/1, e_make_dir/1, e_del_dir/1]).
+-export([e_delete/1, e_rename/1, e_make_dir/1, e_del_dir/1]).
--export([ read_not_really_compressed/1,
- read_compressed/1, write_compressed/1,
- compress_errors/1]).
-
--export([
- make_link_a/1, make_link_b/1,
- read_link_info_for_non_link/1,
- symlinks_a/1, symlinks_b/1,
- list_dir_limit/1,
- list_dir_error/1,
- list_dir/1]).
+-export([make_link/1, read_link_info_for_non_link/1,
+ symlinks/1,
+ list_dir_limit/1,
+ list_dir_error/1,
+ list_dir/1]).
-export([advise/1]).
-export([large_write/1]).
@@ -67,29 +52,16 @@
-define(PRIM_FILE, prim_file).
-%% Calls ?PRIM_FILE:F with arguments A and an optional handle H
-%% as first argument, unless the handle is [], i.e no handle.
-%% This is a macro to give the compiler and thereby
-%% the cross reference tool the possibility to interprete
-%% the call, since M, F, A (or [H | A]) can all be known at
-%% compile time.
--define(PRIM_FILE_call(F, H, A),
- case H of
- [] -> apply(?PRIM_FILE, F, A);
- _ -> apply(?PRIM_FILE, F, [H | A])
- end).
-
suite() -> [].
all() ->
[read_write_file, {group, dirs}, {group, files},
- delete_a, delete_b, rename_a, rename_b, {group, errors},
- {group, compression}, {group, links}, list_dir_limit, list_dir].
+ delete, rename, {group, errors}, {group, links},
+ list_dir_limit, list_dir].
groups() ->
[{dirs, [],
- [make_del_dir_a, make_del_dir_b, cur_dir_0a, cur_dir_0b,
- cur_dir_1a, cur_dir_1b]},
+ [make_del_dir, cur_dir_0, cur_dir_1]},
{files, [],
[{group, open}, {group, pos}, {group, file_info},
truncate, sync, datasync, advise, large_write, allocate]},
@@ -98,22 +70,14 @@ groups() ->
append, exclusive]},
{pos, [], [pos1, pos2]},
{file_info, [],
- [file_info_basic_file_a, file_info_basic_file_b,
- file_info_basic_directory_a,
- file_info_basic_directory_b, file_info_bad_a,
- file_info_bad_b, file_info_times_a, file_info_times_b,
- file_write_file_info_a, file_write_file_info_b,
- file_read_file_info_opts, file_write_file_info_opts,
- file_write_read_file_info_opts
+ [file_info_basic_file,file_info_basic_directory, file_info_bad,
+ file_info_times, file_write_file_info, file_read_file_info_opts,
+ file_write_file_info_opts, file_write_read_file_info_opts
]},
{errors, [],
[e_delete, e_rename, e_make_dir, e_del_dir]},
- {compression, [],
- [read_compressed, read_not_really_compressed,
- write_compressed, compress_errors]},
{links, [],
- [make_link_a, make_link_b, read_link_info_for_non_link,
- symlinks_a, symlinks_b, list_dir_error]}].
+ [make_link, read_link_info_for_non_link, symlinks, list_dir_error]}].
init_per_testcase(large_write, Config) ->
{ok, Started} = application:ensure_all_started(os_mon),
@@ -246,39 +210,27 @@ read_write_file(Config) when is_list(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-make_del_dir_a(Config) when is_list(Config) ->
- make_del_dir(Config, [], "_a").
-
-make_del_dir_b(Config) when is_list(Config) ->
- {ok, Handle} = ?PRIM_FILE:start(),
- Result = make_del_dir(Config, Handle, "_b"),
- ok = ?PRIM_FILE:stop(Handle),
- %% Just to make sure the state of the server makes a difference
- {error, einval} = ?PRIM_FILE_call(get_cwd, Handle, []),
- Result.
-
-make_del_dir(Config, Handle, Suffix) ->
+make_del_dir(Config) when is_list(Config) ->
RootDir = proplists:get_value(priv_dir,Config),
NewDir = filename:join(RootDir,
atom_to_list(?MODULE)
- ++"_mk-dir"++Suffix),
- ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
- {error, eexist} = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
- ok = ?PRIM_FILE_call(del_dir, Handle, [NewDir]),
- {error, enoent} = ?PRIM_FILE_call(del_dir, Handle, [NewDir]),
+ ++"_mk-dir"),
+ ok = ?PRIM_FILE:make_dir(NewDir),
+ {error, eexist} = ?PRIM_FILE:make_dir(NewDir),
+ ok = ?PRIM_FILE:del_dir(NewDir),
+ {error, enoent} = ?PRIM_FILE:del_dir(NewDir),
%% Make sure we are not in a directory directly under test_server
%% as that would result in eacces errors when trying to delete '..',
%% because there are processes having that directory as current.
- ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
- {ok, CurrentDir} = ?PRIM_FILE_call(get_cwd, Handle, []),
+ ok = ?PRIM_FILE:make_dir(NewDir),
+ {ok, CurrentDir} = ?PRIM_FILE:get_cwd(),
case {os:type(), length(NewDir) >= 260 } of
{{win32,_}, true} ->
io:format("Skip set_cwd for windows path longer than 260 (MAX_PATH)\n", []),
io:format("\nNewDir = ~p\n", [NewDir]);
_ ->
- ok = ?PRIM_FILE_call(set_cwd, Handle, [NewDir])
+ ok = ?PRIM_FILE:set_cwd(NewDir)
end,
try
%% Check that we get an error when trying to create...
@@ -286,14 +238,14 @@ make_del_dir(Config, Handle, Suffix) ->
NewDir2 = filename:join(RootDir,
atom_to_list(?MODULE)
++"_mk-dir-noexist/foo"),
- {error, enoent} = ?PRIM_FILE_call(make_dir, Handle, [NewDir2]),
+ {error, enoent} = ?PRIM_FILE:make_dir(NewDir2),
%% a nameless directory
- {error, enoent} = ?PRIM_FILE_call(make_dir, Handle, [""]),
+ {error, enoent} = ?PRIM_FILE:make_dir(""),
%% a directory with illegal name
- {error, badarg} = ?PRIM_FILE_call(make_dir, Handle, ['mk-dir']),
+ {error, badarg} = ?PRIM_FILE:make_dir('mk-dir'),
%% a directory with illegal name, even if it's a (bad) list
- {error, badarg} = ?PRIM_FILE_call(make_dir, Handle, [[1,2,3,{}]]),
+ {error, badarg} = ?PRIM_FILE:make_dir([1,2,3,{}]),
%% Maybe this isn't an error, exactly, but worth mentioning anyway:
%% ok = ?PRIM_FILE:make_dir([$f,$o,$o,0,$b,$a,$r])),
@@ -306,125 +258,101 @@ make_del_dir(Config, Handle, Suffix) ->
%% Try deleting some bad directories
%% Deleting the parent directory to the current, sounds dangerous, huh?
%% Don't worry ;-) the parent directory should never be empty, right?
- case ?PRIM_FILE_call(del_dir, Handle, [".."]) of
+ case ?PRIM_FILE:del_dir("..") of
{error, eexist} -> ok;
{error, eacces} -> ok; %OpenBSD
{error, einval} -> ok %FreeBSD
end,
- {error, enoent} = ?PRIM_FILE_call(del_dir, Handle, [""]),
- {error, badarg} = ?PRIM_FILE_call(del_dir, Handle, [[3,2,1,{}]])
+ {error, enoent} = ?PRIM_FILE:del_dir(""),
+ {error, badarg} = ?PRIM_FILE:del_dir([3,2,1,{}])
after
- ok = ?PRIM_FILE_call(set_cwd, Handle, [CurrentDir])
+ ok = ?PRIM_FILE:set_cwd(CurrentDir)
end,
ok.
-cur_dir_0a(Config) when is_list(Config) ->
- cur_dir_0(Config, []).
-
-cur_dir_0b(Config) when is_list(Config) ->
- {ok, Handle} = ?PRIM_FILE:start(),
- Result = cur_dir_0(Config, Handle),
- ok = ?PRIM_FILE:stop(Handle),
- Result.
-
-cur_dir_0(Config, Handle) ->
+cur_dir_0(Config) when is_list(Config) ->
%% Find out the current dir, and cd to it ;-)
- {ok,BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, []),
+ {ok,BaseDir} = ?PRIM_FILE:get_cwd(),
Dir1 = BaseDir ++ "", %% Check that it's a string
- ok = ?PRIM_FILE_call(set_cwd, Handle, [Dir1]),
- DirName = atom_to_list(?MODULE) ++
- case Handle of
- [] ->
- "_curdir";
- _ ->
- "_curdir_h"
- end,
+ ok = ?PRIM_FILE:set_cwd(Dir1),
+ DirName = atom_to_list(?MODULE) ++ "_curdir",
%% Make a new dir, and cd to that
RootDir = proplists:get_value(priv_dir,Config),
NewDir = filename:join(RootDir, DirName),
- ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
+ ok = ?PRIM_FILE:make_dir(NewDir),
case {os:type(), length(NewDir) >= 260} of
{{win32,_}, true} ->
io:format("Skip set_cwd for windows path longer than 260 (MAX_PATH):\n"),
io:format("\nNewDir = ~p\n", [NewDir]);
_ ->
io:format("cd to ~s",[NewDir]),
- ok = ?PRIM_FILE_call(set_cwd, Handle, [NewDir]),
+ ok = ?PRIM_FILE:set_cwd(NewDir),
%% Create a file in the new current directory, and check that it
%% really is created there
UncommonName = "uncommon.fil",
{ok,Fd} = ?PRIM_FILE:open(UncommonName, [read, write]),
ok = ?PRIM_FILE:close(Fd),
- {ok,NewDirFiles} = ?PRIM_FILE_call(list_dir, Handle, ["."]),
+ {ok,NewDirFiles} = ?PRIM_FILE:list_dir("."),
true = lists:member(UncommonName,NewDirFiles),
%% Delete the directory and return to the old current directory
%% and check that the created file isn't there (too!)
expect({error, einval}, {error, eacces}, {error, eexist},
- ?PRIM_FILE_call(del_dir, Handle, [NewDir])),
- ?PRIM_FILE_call(delete, Handle, [UncommonName]),
- {ok,[]} = ?PRIM_FILE_call(list_dir, Handle, ["."]),
- ok = ?PRIM_FILE_call(set_cwd, Handle, [Dir1]),
+ ?PRIM_FILE:del_dir(NewDir)),
+ ?PRIM_FILE:delete(UncommonName),
+ {ok,[]} = ?PRIM_FILE:list_dir("."),
+ ok = ?PRIM_FILE:set_cwd(Dir1),
io:format("cd back to ~s",[Dir1]),
- ok = ?PRIM_FILE_call(del_dir, Handle, [NewDir]),
- {error, enoent} = ?PRIM_FILE_call(set_cwd, Handle, [NewDir]),
- ok = ?PRIM_FILE_call(set_cwd, Handle, [Dir1]),
+ ok = ?PRIM_FILE:del_dir(NewDir),
+ {error, enoent} = ?PRIM_FILE:set_cwd(NewDir),
+ ok = ?PRIM_FILE:set_cwd(Dir1),
io:format("cd back to ~s",[Dir1]),
- {ok,OldDirFiles} = ?PRIM_FILE_call(list_dir, Handle, ["."]),
+ {ok,OldDirFiles} = ?PRIM_FILE:list_dir("."),
false = lists:member(UncommonName,OldDirFiles)
end,
%% Try doing some bad things
{error, badarg} =
- ?PRIM_FILE_call(set_cwd, Handle, [{foo,bar}]),
+ ?PRIM_FILE:set_cwd({foo,bar}),
{error, enoent} =
- ?PRIM_FILE_call(set_cwd, Handle, [""]),
+ ?PRIM_FILE:set_cwd(""),
{error, enoent} =
- ?PRIM_FILE_call(set_cwd, Handle, [".......a......"]),
+ ?PRIM_FILE:set_cwd(".......a......"),
{ok,BaseDir} =
- ?PRIM_FILE_call(get_cwd, Handle, []), %% Still there?
+ ?PRIM_FILE:get_cwd(), %% Still there?
%% On Windows, there should only be slashes, no backslashes,
%% in the return value of get_cwd().
%% (The test is harmless on Unix, because filenames usually
%% don't contain backslashes.)
- {ok, BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, []),
+ {ok, BaseDir} = ?PRIM_FILE:get_cwd(),
false = lists:member($\\, BaseDir),
ok.
%% Tests ?PRIM_FILE:get_cwd/1.
-cur_dir_1a(Config) when is_list(Config) ->
- cur_dir_1(Config, []).
-
-cur_dir_1b(Config) when is_list(Config) ->
- {ok, Handle} = ?PRIM_FILE:start(),
- Result = cur_dir_1(Config, Handle),
- ok = ?PRIM_FILE:stop(Handle),
- Result.
-
-cur_dir_1(Config, Handle) ->
+cur_dir_1(Config) when is_list(Config) ->
case os:type() of
{win32, _} ->
- win_cur_dir_1(Config, Handle);
+ win_cur_dir_1(Config);
_ ->
{error, enotsup} =
- ?PRIM_FILE_call(get_cwd, Handle, ["d:"])
+ ?PRIM_FILE:get_cwd("d:")
end,
ok.
-win_cur_dir_1(_Config, Handle) ->
- {ok, BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, []),
+win_cur_dir_1(_Config) ->
+ {ok, BaseDir} = ?PRIM_FILE:get_cwd(),
%% Get the drive letter from the current directory,
%% and try to get current directory for that drive.
[Drive, $:|_] = BaseDir,
- {ok, BaseDir} = ?PRIM_FILE_call(get_cwd, Handle, [[Drive, $:]]),
+ {ok, BaseDir} = ?PRIM_FILE:get_cwd([Drive, $:]),
io:format("BaseDir = ~s\n", [BaseDir]),
%% Unfortunately, there is no way to move away from the
@@ -446,12 +374,12 @@ open1(Config) when is_list(Config) ->
Name = filename:join(NewDir, "foo1.fil"),
{ok,Fd1} = ?PRIM_FILE:open(Name, [read, write]),
{ok,Fd2} = ?PRIM_FILE:open(Name, [read]),
- Str = "{a,tuple}.\n",
- Length = length(Str),
- ?PRIM_FILE:write(Fd1,Str),
+ Bin = list_to_binary("{a,tuple}.\n"),
+ Length = byte_size(Bin),
+ ?PRIM_FILE:write(Fd1,Bin),
{ok,0} = ?PRIM_FILE:position(Fd1,bof),
- {ok, Str} = ?PRIM_FILE:read(Fd1,Length),
- {ok, Str} = ?PRIM_FILE:read(Fd2,Length),
+ {ok, Bin} = ?PRIM_FILE:read(Fd1,Length),
+ {ok, Bin} = ?PRIM_FILE:read(Fd2,Length),
ok = ?PRIM_FILE:close(Fd2),
{ok,0} = ?PRIM_FILE:position(Fd1,bof),
ok = ?PRIM_FILE:truncate(Fd1),
@@ -471,13 +399,13 @@ modes(Config) when is_list(Config) ->
++"_open_modes"),
ok = ?PRIM_FILE:make_dir(NewDir),
Name1 = filename:join(NewDir, "foo1.fil"),
- Marker = "hello, world",
- Length = length(Marker),
+ Marker = <<"hello, world">>,
+ Length = byte_size(Marker),
%% write
{ok, Fd1} = ?PRIM_FILE:open(Name1, [write]),
ok = ?PRIM_FILE:write(Fd1, Marker),
- ok = ?PRIM_FILE:write(Fd1, ".\n"),
+ ok = ?PRIM_FILE:write(Fd1, <<".\n">>),
ok = ?PRIM_FILE:close(Fd1),
%% read
@@ -496,12 +424,6 @@ modes(Config) when is_list(Config) ->
{ok, Marker} = ?PRIM_FILE:read(Fd4, Length),
ok = ?PRIM_FILE:close(Fd4),
- %% read and binary
- BinaryMarker = list_to_binary(Marker),
- {ok, Fd5} = ?PRIM_FILE:open(Name1, [read, binary]),
- {ok, BinaryMarker} = ?PRIM_FILE:read(Fd5, Length),
- ok = ?PRIM_FILE:close(Fd5),
-
ok.
close(Config) when is_list(Config) ->
@@ -528,9 +450,9 @@ access(Config) when is_list(Config) ->
Name = filename:join(RootDir,
atom_to_list(?MODULE)
++"_access.fil"),
- Str = "ABCDEFGH",
+ Bin = <<"ABCDEFGH">>,
{ok,Fd1} = ?PRIM_FILE:open(Name, [write]),
- ?PRIM_FILE:write(Fd1,Str),
+ ?PRIM_FILE:write(Fd1,Bin),
ok = ?PRIM_FILE:close(Fd1),
%% Check that we can't write when in read only mode
{ok,Fd2} = ?PRIM_FILE:open(Name, [read]),
@@ -542,7 +464,7 @@ access(Config) when is_list(Config) ->
end,
ok = ?PRIM_FILE:close(Fd2),
{ok, Fd3} = ?PRIM_FILE:open(Name, [read]),
- {ok, Str} = ?PRIM_FILE:read(Fd3,length(Str)),
+ {ok, Bin} = ?PRIM_FILE:read(Fd3,byte_size(Bin)),
ok = ?PRIM_FILE:close(Fd3),
ok.
@@ -564,7 +486,7 @@ read_write(Config) when is_list(Config) ->
ok.
read_write_test(File) ->
- Marker = "hello, world",
+ Marker = <<"hello, world">>,
ok = ?PRIM_FILE:write(File, Marker),
{ok, 0} = ?PRIM_FILE:position(File, 0),
{ok, Marker} = ?PRIM_FILE:read(File, 100),
@@ -590,15 +512,15 @@ pread_write(Config) when is_list(Config) ->
ok.
pread_write_test(File) ->
- Marker = "hello, world",
- Len = length(Marker),
+ Marker = <<"hello, world">>,
+ Len = byte_size(Marker),
ok = ?PRIM_FILE:write(File, Marker),
{ok, Marker} = ?PRIM_FILE:pread(File, 0, 100),
eof = ?PRIM_FILE:pread(File, 100, 1),
ok = ?PRIM_FILE:pwrite(File, Len, Marker),
{ok, Marker} = ?PRIM_FILE:pread(File, Len, 100),
eof = ?PRIM_FILE:pread(File, 100, 1),
- MM = Marker ++ Marker,
+ MM = <<Marker/binary,Marker/binary>>,
{ok, MM} = ?PRIM_FILE:pread(File, 0, 100),
ok = ?PRIM_FILE:close(File),
ok.
@@ -655,24 +577,24 @@ pos1(Config) when is_list(Config) ->
atom_to_list(?MODULE)
++"_pos1.fil"),
{ok, Fd1} = ?PRIM_FILE:open(Name, [write]),
- ?PRIM_FILE:write(Fd1,"ABCDEFGH"),
+ ?PRIM_FILE:write(Fd1,<<"ABCDEFGH">>),
ok = ?PRIM_FILE:close(Fd1),
{ok, Fd2} = ?PRIM_FILE:open(Name, [read]),
%% Start pos is first char
io:format("Relative positions"),
- {ok, "A"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, <<"A">>} = ?PRIM_FILE:read(Fd2,1),
{ok, 2} = ?PRIM_FILE:position(Fd2,{cur,1}),
- {ok, "C"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, <<"C">>} = ?PRIM_FILE:read(Fd2,1),
{ok, 0} = ?PRIM_FILE:position(Fd2,{cur,-3}),
- {ok, "A"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, <<"A">>} = ?PRIM_FILE:read(Fd2,1),
%% Backwards from first char should be an error
{ok,0} = ?PRIM_FILE:position(Fd2,{cur,-1}),
{error, einval} = ?PRIM_FILE:position(Fd2,{cur,-1}),
%% Reset position and move again
{ok, 0} = ?PRIM_FILE:position(Fd2,0),
{ok, 2} = ?PRIM_FILE:position(Fd2,{cur,2}),
- {ok, "C"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, <<"C">>} = ?PRIM_FILE:read(Fd2,1),
%% Go a lot forwards
{ok, 13} = ?PRIM_FILE:position(Fd2,{cur,10}),
eof = ?PRIM_FILE:read(Fd2,1),
@@ -684,27 +606,27 @@ pos1(Config) when is_list(Config) ->
{ok, 8} = ?PRIM_FILE:position(Fd2,cur),
eof = ?PRIM_FILE:read(Fd2,1),
{ok, 7} = ?PRIM_FILE:position(Fd2,7),
- {ok, "H"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, <<"H">>} = ?PRIM_FILE:read(Fd2,1),
{ok, 0} = ?PRIM_FILE:position(Fd2,0),
- {ok, "A"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, <<"A">>} = ?PRIM_FILE:read(Fd2,1),
{ok, 3} = ?PRIM_FILE:position(Fd2,3),
- {ok, "D"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, <<"D">>} = ?PRIM_FILE:read(Fd2,1),
{ok, 12} = ?PRIM_FILE:position(Fd2,12),
eof = ?PRIM_FILE:read(Fd2,1),
{ok, 3} = ?PRIM_FILE:position(Fd2,3),
- {ok, "D"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, <<"D">>} = ?PRIM_FILE:read(Fd2,1),
%% Try the {bof,X} notation
{ok, 3} = ?PRIM_FILE:position(Fd2,{bof,3}),
- {ok, "D"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, <<"D">>} = ?PRIM_FILE:read(Fd2,1),
%% Try eof positions
io:format("EOF positions"),
{ok, 8} = ?PRIM_FILE:position(Fd2,{eof,0}),
eof = ?PRIM_FILE:read(Fd2,1),
{ok, 7} = ?PRIM_FILE:position(Fd2,{eof,-1}),
- {ok, "H"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, <<"H">>} = ?PRIM_FILE:read(Fd2,1),
{ok, 0} = ?PRIM_FILE:position(Fd2,{eof,-8}),
- {ok, "A"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, <<"A">>} = ?PRIM_FILE:read(Fd2,1),
{error, einval} = ?PRIM_FILE:position(Fd2,{eof,-9}),
ok.
@@ -714,7 +636,7 @@ pos2(Config) when is_list(Config) ->
atom_to_list(?MODULE)
++"_pos2.fil"),
{ok,Fd1} = ?PRIM_FILE:open(Name, [write]),
- ?PRIM_FILE:write(Fd1,"ABCDEFGH"),
+ ?PRIM_FILE:write(Fd1,<<"ABCDEFGH">>),
ok = ?PRIM_FILE:close(Fd1),
{ok, Fd2} = ?PRIM_FILE:open(Name, [read]),
{error, einval} = ?PRIM_FILE:position(Fd2,-1),
@@ -722,35 +644,25 @@ pos2(Config) when is_list(Config) ->
%% Make sure that we still can search after an error.
{ok, 0} = ?PRIM_FILE:position(Fd2, 0),
{ok, 3} = ?PRIM_FILE:position(Fd2, {bof,3}),
- {ok, "D"} = ?PRIM_FILE:read(Fd2,1),
+ {ok, <<"D">>} = ?PRIM_FILE:read(Fd2,1),
io:format("DONE"),
ok.
-
-file_info_basic_file_a(Config) when is_list(Config) ->
- file_info_basic_file(Config, [], "_a").
-
-file_info_basic_file_b(Config) when is_list(Config) ->
- {ok, Handle} = ?PRIM_FILE:start(),
- Result = file_info_basic_file(Config, Handle, "_b"),
- ok = ?PRIM_FILE:stop(Handle),
- Result.
-
-file_info_basic_file(Config, Handle, Suffix) ->
+file_info_basic_file(Config) when is_list(Config) ->
RootDir = proplists:get_value(priv_dir, Config),
%% Create a short file.
Name = filename:join(RootDir,
atom_to_list(?MODULE)
- ++"_basic_test"++Suffix++".fil"),
+ ++"_basic_test"".fil"),
{ok,Fd1} = ?PRIM_FILE:open(Name, [write]),
?PRIM_FILE:write(Fd1, "foo bar"),
ok = ?PRIM_FILE:close(Fd1),
%% Test that the file has the expected attributes.
%% The times are tricky, so we will save them to a separate test case.
- {ok, FileInfo} = ?PRIM_FILE_call(read_file_info, Handle, [Name]),
+ {ok, FileInfo} = ?PRIM_FILE:read_file_info(Name),
#file_info{size = Size, type = Type, access = Access,
atime = AccessTime, mtime = ModifyTime} =
FileInfo,
@@ -768,39 +680,30 @@ file_info_basic_file(Config, Handle, Suffix) ->
ok.
-file_info_basic_directory_a(Config) when is_list(Config) ->
- file_info_basic_directory(Config, []).
-
-file_info_basic_directory_b(Config) when is_list(Config) ->
- {ok, Handle} = ?PRIM_FILE:start(),
- Result = file_info_basic_directory(Config, Handle),
- ok = ?PRIM_FILE:stop(Handle),
- Result.
-
-file_info_basic_directory(Config, Handle) ->
+file_info_basic_directory(Config) when is_list(Config) ->
%% Note: filename:join/1 removes any trailing slash,
%% which is essential for ?PRIM_FILE:read_file_info/1 to work on
%% platforms such as Windows95.
RootDir = filename:join([proplists:get_value(priv_dir, Config)]),
%% Test that the RootDir directory has the expected attributes.
- test_directory(RootDir, read_write, Handle),
+ test_directory(RootDir, read_write),
%% Note that on Windows file systems, "/" or "c:/" are *NOT* directories.
%% Therefore, test that ?PRIM_FILE:read_file_info/1 behaves
%% as if they were directories.
case os:type() of
{win32, _} ->
- test_directory("/", read_write, Handle),
- test_directory("c:/", read_write, Handle),
- test_directory("c:\\", read_write, Handle);
+ test_directory("/", read_write),
+ test_directory("c:/", read_write),
+ test_directory("c:\\", read_write);
_ ->
- test_directory("/", read, Handle)
+ test_directory("/", read)
end,
ok.
-test_directory(Name, ExpectedAccess, Handle) ->
- {ok, FileInfo} = ?PRIM_FILE_call(read_file_info, Handle, [Name]),
+test_directory(Name, ExpectedAccess) ->
+ {ok, FileInfo} = ?PRIM_FILE:read_file_info(Name),
#file_info{size = Size, type = Type, access = Access,
atime = AccessTime, mtime = ModifyTime} =
FileInfo,
@@ -824,45 +727,24 @@ all_integers([]) ->
%% Try something nonexistent.
-file_info_bad_a(Config) when is_list(Config) ->
- file_info_bad(Config, []).
-
-file_info_bad_b(Config) when is_list(Config) ->
- {ok, Handle} = ?PRIM_FILE:start(),
- Result = file_info_bad(Config, Handle),
- ok = ?PRIM_FILE:stop(Handle),
- Result.
-
-file_info_bad(Config, Handle) ->
+file_info_bad(Config) when is_list(Config) ->
RootDir = filename:join([proplists:get_value(priv_dir, Config)]),
- {error, enoent} =
- ?PRIM_FILE_call(
- read_file_info, Handle,
- [filename:join(RootDir,
- atom_to_list(?MODULE)++"_nonexistent")]),
+ NonExistent = filename:join(RootDir, atom_to_list(?MODULE)++"_nonexistent"),
+ {error, enoent} = ?PRIM_FILE:read_file_info(NonExistent),
ok.
%% Test that the file times behave as they should.
-file_info_times_a(Config) when is_list(Config) ->
- file_info_times(Config, [], "_a").
-
-file_info_times_b(Config) when is_list(Config) ->
- {ok, Handle} = ?PRIM_FILE:start(),
- Result = file_info_times(Config, Handle, "_b"),
- ok = ?PRIM_FILE:stop(Handle),
- Result.
-
-file_info_times(Config, Handle, Suffix) ->
+file_info_times(Config) when is_list(Config) ->
%% We have to try this twice, since if the test runs across the change
%% of a month the time diff calculations will fail. But it won't happen
%% if you run it twice in succession.
test_server:m_out_of_n(
1,2,
- fun() -> file_info_int(Config, Handle, Suffix) end),
+ fun() -> file_info_int(Config) end),
ok.
-file_info_int(Config, Handle, Suffix) ->
+file_info_int(Config) ->
%% Note: filename:join/1 removes any trailing slash,
%% which is essential for ?PRIM_FILE:read_file_info/1 to work on
%% platforms such as Windows95.
@@ -872,14 +754,14 @@ file_info_int(Config, Handle, Suffix) ->
Name = filename:join(RootDir,
atom_to_list(?MODULE)
- ++"_file_info"++Suffix++".fil"),
+ ++"_file_info.fil"),
{ok,Fd1} = ?PRIM_FILE:open(Name, [write]),
?PRIM_FILE:write(Fd1,"foo"),
%% check that the file got a modify date max a few seconds away from now
{ok, #file_info{type = regular,
atime = AccTime1, mtime = ModTime1}} =
- ?PRIM_FILE_call(read_file_info, Handle, [Name]),
+ ?PRIM_FILE:read_file_info(Name),
Now = erlang:localtime(),
io:format("Now ~p",[Now]),
io:format("Open file Acc ~p Mod ~p",[AccTime1,ModTime1]),
@@ -897,7 +779,7 @@ file_info_int(Config, Handle, Suffix) ->
ok = ?PRIM_FILE:close(Fd1),
{ok, #file_info{size = Size, type = regular, access = Access,
atime = AccTime2, mtime = ModTime2}} =
- ?PRIM_FILE_call(read_file_info, Handle, [Name]),
+ ?PRIM_FILE:read_file_info(Name),
io:format("Closed file Acc ~p Mod ~p",[AccTime2,ModTime2]),
true = time_dist(ModTime1, ModTime2) >= 0,
@@ -909,7 +791,7 @@ file_info_int(Config, Handle, Suffix) ->
{ok, #file_info{size = DSize, type = directory,
access = DAccess,
atime = AccTime3, mtime = ModTime3}} =
- ?PRIM_FILE_call(read_file_info, Handle, [RootDir]),
+ ?PRIM_FILE:read_file_info(RootDir),
%% this dir was modified only a few secs ago
io:format("Dir Acc ~p; Mod ~p; Now ~p",
[AccTime3, ModTime3, Now]),
@@ -936,16 +818,7 @@ filter_atime(Atime, Config) ->
%% Test the write_file_info/2 function.
-file_write_file_info_a(Config) when is_list(Config) ->
- file_write_file_info(Config, [], "_a").
-
-file_write_file_info_b(Config) when is_list(Config) ->
- {ok, Handle} = ?PRIM_FILE:start(),
- Result = file_write_file_info(Config, Handle, "_b"),
- ok = ?PRIM_FILE:stop(Handle),
- Result.
-
-file_write_file_info(Config, Handle, Suffix) ->
+file_write_file_info(Config) when is_list(Config) ->
RootDir = get_good_directory(Config),
io:format("RootDir = ~p", [RootDir]),
@@ -955,16 +828,16 @@ file_write_file_info(Config, Handle, Suffix) ->
Name = filename:join(RootDir,
atom_to_list(?MODULE)
- ++"_write_file_info_ro"++Suffix),
+ ++"_write_file_info_ro"),
ok = ?PRIM_FILE:write_file(Name, "hello"),
Time = {{1997, 01, 02}, {12, 35, 42}},
Info = #file_info{mode=8#400, atime=Time, mtime=Time, ctime=Time},
- ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, Info]),
+ ok = ?PRIM_FILE:write_file_info(Name, Info),
%% Read back the times.
{ok, ActualInfo} =
- ?PRIM_FILE_call(read_file_info, Handle, [Name]),
+ ?PRIM_FILE:read_file_info(Name),
#file_info{mode=_Mode, atime=ActAtime, mtime=Time,
ctime=ActCtime} = ActualInfo,
FilteredAtime = filter_atime(Time, Config),
@@ -980,14 +853,11 @@ file_write_file_info(Config, Handle, Suffix) ->
{error, eacces} = ?PRIM_FILE:write_file(Name, "hello again"),
%% Make the file writable again.
-
- ?PRIM_FILE_call(write_file_info, Handle,
- [Name, #file_info{mode=8#600}]),
+ ?PRIM_FILE:write_file_info(Name, #file_info{mode=8#600}),
ok = ?PRIM_FILE:write_file(Name, "hello again"),
%% And unwritable.
- ?PRIM_FILE_call(write_file_info, Handle,
- [Name, #file_info{mode=8#400}]),
+ ?PRIM_FILE:write_file_info(Name, #file_info{mode=8#400}),
{error, eacces} = ?PRIM_FILE:write_file(Name, "hello again"),
%% Write the times again.
@@ -995,9 +865,9 @@ file_write_file_info(Config, Handle, Suffix) ->
NewTime = {{1997, 02, 15}, {13, 18, 20}},
NewInfo = #file_info{atime=NewTime, mtime=NewTime, ctime=NewTime},
- ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, NewInfo]),
+ ok = ?PRIM_FILE:write_file_info(Name, NewInfo),
{ok, ActualInfo2} =
- ?PRIM_FILE_call(read_file_info, Handle, [Name]),
+ ?PRIM_FILE:read_file_info(Name),
#file_info{atime=NewActAtime, mtime=NewTime,
ctime=NewActCtime} = ActualInfo2,
NewFilteredAtime = filter_atime(NewTime, Config),
@@ -1012,14 +882,12 @@ file_write_file_info(Config, Handle, Suffix) ->
%% Make the file writeable again, so that we can remove the
%% test suites ... :-)
- ?PRIM_FILE_call(write_file_info, Handle,
- [Name, #file_info{mode=8#600}]),
+ ?PRIM_FILE:write_file_info(Name, #file_info{mode=8#600}),
ok.
%% Test the write_file_info/3 function.
file_write_file_info_opts(Config) when is_list(Config) ->
- {ok, Handle} = ?PRIM_FILE:start(),
RootDir = get_good_directory(Config),
io:format("RootDir = ~p", [RootDir]),
@@ -1028,7 +896,7 @@ file_write_file_info_opts(Config) when is_list(Config) ->
lists:foreach(fun
({FI, Opts}) ->
- ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts])
+ ok = ?PRIM_FILE:write_file_info(Name, FI, Opts)
end, [
{#file_info{ mode=8#600, atime = Time, mtime = Time, ctime = Time}, Opts} ||
Opts <- [[{time, posix}]],
@@ -1038,7 +906,7 @@ file_write_file_info_opts(Config) when is_list(Config) ->
%% REM: determine date range dependent on time_t = Uint32 | Sint32 | Sint64 | Uint64
%% Determine time_t on os:type()?
lists:foreach(fun ({FI, Opts}) ->
- ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts])
+ ok = ?PRIM_FILE:write_file_info(Name, FI, Opts)
end, [ {#file_info{ mode=8#400, atime = Time, mtime = Time, ctime = Time}, Opts} ||
Opts <- [[{time, universal}],[{time, local}]],
Time <- [
@@ -1050,11 +918,9 @@ file_write_file_info_opts(Config) when is_list(Config) ->
{{2037,2,3},{23,59,59}},
erlang:localtime()
]]),
- ok = ?PRIM_FILE:stop(Handle),
ok.
file_read_file_info_opts(Config) when is_list(Config) ->
- {ok, Handle} = ?PRIM_FILE:start(),
RootDir = get_good_directory(Config),
io:format("RootDir = ~p", [RootDir]),
@@ -1063,41 +929,38 @@ file_read_file_info_opts(Config) when is_list(Config) ->
lists:foreach(fun
(Opts) ->
- {ok,_} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts])
+ {ok,_} = ?PRIM_FILE:read_file_info(Name, Opts)
end, [[{time, Type}] || Type <- [local, universal, posix]]),
- ok = ?PRIM_FILE:stop(Handle),
ok.
%% Test the write and read back *_file_info/3 functions.
file_write_read_file_info_opts(Config) when is_list(Config) ->
- {ok, Handle} = ?PRIM_FILE:start(),
RootDir = get_good_directory(Config),
io:format("RootDir = ~p", [RootDir]),
Name = filename:join(RootDir, atom_to_list(?MODULE) ++"_read_write_file_info_opts"),
ok = ?PRIM_FILE:write_file(Name, "hello_opts2"),
- ok = file_write_read_file_info_opts(Handle, Name, {{1989, 04, 28}, {19,30,22}}, [{time, local}]),
- ok = file_write_read_file_info_opts(Handle, Name, {{1989, 04, 28}, {19,30,22}}, [{time, universal}]),
+ ok = file_write_read_file_info_opts(Name, {{1989, 04, 28}, {19,30,22}}, [{time, local}]),
+ ok = file_write_read_file_info_opts(Name, {{1989, 04, 28}, {19,30,22}}, [{time, universal}]),
%% will not work on platforms with unsigned time_t
- %ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, local}]),
- %ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, universal}]),
- ok = file_write_read_file_info_opts(Handle, Name, 1, [{time, posix}]),
+ %ok = file_write_read_file_info_opts(Name, {{1930, 04, 28}, {19,30,22}}, [{time, local}]),
+ %ok = file_write_read_file_info_opts(Name, {{1930, 04, 28}, {19,30,22}}, [{time, universal}]),
+ ok = file_write_read_file_info_opts(Name, 1, [{time, posix}]),
%% will not work on platforms with unsigned time_t
- %ok = file_write_read_file_info_opts(Handle, Name, -1, [{time, posix}]),
- %ok = file_write_read_file_info_opts(Handle, Name, -300000, [{time, posix}]),
- ok = file_write_read_file_info_opts(Handle, Name, 300000, [{time, posix}]),
- ok = file_write_read_file_info_opts(Handle, Name, 0, [{time, posix}]),
+ %ok = file_write_read_file_info_opts(Name, -1, [{time, posix}]),
+ %ok = file_write_read_file_info_opts(Name, -300000, [{time, posix}]),
+ ok = file_write_read_file_info_opts(Name, 300000, [{time, posix}]),
+ ok = file_write_read_file_info_opts(Name, 0, [{time, posix}]),
- ok = ?PRIM_FILE:stop(Handle),
ok.
-file_write_read_file_info_opts(Handle, Name, Mtime, Opts) ->
- {ok, FI} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]),
+file_write_read_file_info_opts(Name, Mtime, Opts) ->
+ {ok, FI} = ?PRIM_FILE:read_file_info(Name, Opts),
FI2 = FI#file_info{ mtime = Mtime },
- ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI2, Opts]),
- {ok, FI3} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]),
+ ok = ?PRIM_FILE:write_file_info(Name, FI2, Opts),
+ {ok, FI3} = ?PRIM_FILE:read_file_info(Name, Opts),
io:format("Expecting mtime = ~p, got ~p~n", [FI2#file_info.mtime, FI3#file_info.mtime]),
FI2 = FI3,
ok.
@@ -1175,8 +1038,8 @@ advise(Config) when is_list(Config) ->
atom_to_list(?MODULE)
++"_advise.fil"),
- Line1 = "Hello\n",
- Line2 = "World!\n",
+ Line1 = <<"Hello\n">>,
+ Line2 = <<"World!\n">>,
{ok, Fd} = ?PRIM_FILE:open(Advise, [write]),
ok = ?PRIM_FILE:advise(Fd, 0, 0, normal),
@@ -1226,7 +1089,7 @@ advise(Config) when is_list(Config) ->
{ok, Fd9} = ?PRIM_FILE:open(Advise, [read]),
Offset = 0,
%% same as a 0 length in some implementations
- Length = length(Line1) + length(Line2),
+ Length = byte_size(Line1) + byte_size(Line2),
ok = ?PRIM_FILE:advise(Fd9, Offset, Length, sequential),
{ok, Line1} = ?PRIM_FILE:read_line(Fd9),
{ok, Line2} = ?PRIM_FILE:read_line(Fd9),
@@ -1250,23 +1113,18 @@ do_large_write(Name) ->
Chunk = <<0:ChunkSize/unit:8>>,
Data = zip_data(lists:duplicate(Chunks, Chunk), Interleave),
Size = Chunks * ChunkSize + Chunks, % 4 G + 32
- Wordsize = erlang:system_info(wordsize),
- case prim_file:write_file(Name, Data) of
- ok when Wordsize =:= 8 ->
- {ok,#file_info{size=Size}} = file:read_file_info(Name),
- {ok,Fd} = prim_file:open(Name, [read]),
- check_large_write(Fd, ChunkSize, 0, Interleave);
- {error,einval} when Wordsize =:= 4 ->
- ok
- end.
+ ok = ?PRIM_FILE:write_file(Name, Data),
+ {ok,#file_info{size=Size}} = file:read_file_info(Name),
+ {ok,Fd} = ?PRIM_FILE:open(Name, [read]),
+ check_large_write(Fd, ChunkSize, 0, Interleave).
check_large_write(Fd, ChunkSize, Pos, [X|Interleave]) ->
Pos1 = Pos + ChunkSize,
- {ok,Pos1} = prim_file:position(Fd, {cur,ChunkSize}),
- {ok,[X]} = prim_file:read(Fd, 1),
+ {ok,Pos1} = ?PRIM_FILE:position(Fd, {cur,ChunkSize}),
+ {ok,<<X>>} = ?PRIM_FILE:read(Fd, 1),
check_large_write(Fd, ChunkSize, Pos1+1, Interleave);
check_large_write(Fd, _, _, []) ->
- eof = prim_file:read(Fd, 1),
+ eof = ?PRIM_FILE:read(Fd, 1),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1338,71 +1196,53 @@ allocate_and_assert(Fd, Offset, Length) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-delete_a(Config) when is_list(Config) ->
- delete(Config, [], "_a").
-
-delete_b(Config) when is_list(Config) ->
- {ok, Handle} = ?PRIM_FILE:start(),
- Result = delete(Config, Handle, "_b"),
- ok = ?PRIM_FILE:stop(Handle),
- Result.
-
-delete(Config, Handle, Suffix) ->
+delete(Config) when is_list(Config) ->
RootDir = proplists:get_value(priv_dir,Config),
Name = filename:join(RootDir,
atom_to_list(?MODULE)
- ++"_delete"++Suffix++".fil"),
+ ++"_delete.fil"),
{ok, Fd1} = ?PRIM_FILE:open(Name, [write]),
?PRIM_FILE:write(Fd1,"ok.\n"),
ok = ?PRIM_FILE:close(Fd1),
%% Check that the file is readable
{ok, Fd2} = ?PRIM_FILE:open(Name, [read]),
ok = ?PRIM_FILE:close(Fd2),
- ok = ?PRIM_FILE_call(delete, Handle, [Name]),
+ ok = ?PRIM_FILE:delete(Name),
%% Check that the file is not readable anymore
{error, _} = ?PRIM_FILE:open(Name, [read]),
%% Try deleting a nonexistent file
- {error, enoent} = ?PRIM_FILE_call(delete, Handle, [Name]),
+ {error, enoent} = ?PRIM_FILE:delete(Name),
ok.
-rename_a(Config) when is_list(Config) ->
- rename(Config, [], "_a").
-
-rename_b(Config) when is_list(Config) ->
- {ok, Handle} = ?PRIM_FILE:start(),
- Result = rename(Config, Handle, "_b"),
- ok = ?PRIM_FILE:stop(Handle),
- Result.
-
-rename(Config, Handle, Suffix) ->
+rename(Config) when is_list(Config) ->
RootDir = proplists:get_value(priv_dir,Config),
- FileName1 = atom_to_list(?MODULE)++"_rename"++Suffix++".fil",
- FileName2 = atom_to_list(?MODULE)++"_rename"++Suffix++".ful",
+ FileName1 = atom_to_list(?MODULE)++"_rename.fil",
+ FileName2 = atom_to_list(?MODULE)++"_rename.ful",
Name1 = filename:join(RootDir, FileName1),
Name2 = filename:join(RootDir, FileName2),
{ok,Fd1} = ?PRIM_FILE:open(Name1, [write]),
ok = ?PRIM_FILE:close(Fd1),
%% Rename, and check that it really changed name
- ok = ?PRIM_FILE_call(rename, Handle, [Name1, Name2]),
+ ok = ?PRIM_FILE:rename(Name1, Name2),
{error, _} = ?PRIM_FILE:open(Name1, [read]),
{ok, Fd2} = ?PRIM_FILE:open(Name2, [read]),
ok = ?PRIM_FILE:close(Fd2),
%% Try renaming something to itself
- ok = ?PRIM_FILE_call(rename, Handle, [Name2, Name2]),
+ ok = ?PRIM_FILE:rename(Name2, Name2),
%% Try renaming something that doesn't exist
{error, enoent} =
- ?PRIM_FILE_call(rename, Handle, [Name1, Name2]),
+ ?PRIM_FILE:rename(Name1, Name2),
%% Try renaming to something else than a string
{error, badarg} =
- ?PRIM_FILE_call(rename, Handle, [Name1, foobar]),
+ ?PRIM_FILE:rename(Name1, foobar),
%% Move between directories
DirName1 = filename:join(RootDir,
atom_to_list(?MODULE)
- ++"_rename_dir"++Suffix),
+ ++"_rename_dir"),
DirName2 = filename:join(RootDir,
atom_to_list(?MODULE)
- ++"_second_rename_dir"++Suffix),
+ ++"_second_rename_dir"),
Name1foo = filename:join(DirName1, "foo.fil"),
Name2foo = filename:join(DirName2, "foo.fil"),
Name2bar = filename:join(DirName2, "bar.dir"),
@@ -1410,21 +1250,21 @@ rename(Config, Handle, Suffix) ->
%% The name has to include the full file name, path is not enough
expect(
{error, eexist}, {error, eisdir},
- ?PRIM_FILE_call(rename, Handle, [Name2, DirName1])),
+ ?PRIM_FILE:rename(Name2, DirName1)),
ok =
- ?PRIM_FILE_call(rename, Handle, [Name2, Name1foo]),
+ ?PRIM_FILE:rename(Name2, Name1foo),
%% Now rename the directory
- ok = ?PRIM_FILE_call(rename, Handle, [DirName1, DirName2]),
+ ok = ?PRIM_FILE:rename(DirName1, DirName2),
%% And check that the file is there now
{ok,Fd3} = ?PRIM_FILE:open(Name2foo, [read]),
ok = ?PRIM_FILE:close(Fd3),
%% Try some dirty things now: move the directory into itself
{error, Msg1} =
- ?PRIM_FILE_call(rename, Handle, [DirName2, Name2bar]),
+ ?PRIM_FILE:rename(DirName2, Name2bar),
io:format("Errmsg1: ~p",[Msg1]),
%% move dir into a file in itself
{error, Msg2} =
- ?PRIM_FILE_call(rename, Handle, [DirName2, Name2foo]),
+ ?PRIM_FILE:rename(DirName2, Name2foo),
io:format("Errmsg2: ~p",[Msg2]),
ok.
@@ -1466,7 +1306,7 @@ e_delete(Config) when is_list(Config) ->
Base, #file_info {mode=0}),
{error, eacces} = ?PRIM_FILE:delete(Afile),
?PRIM_FILE:write_file_info(
- Base, #file_info {mode=8#600})
+ Base, #file_info {mode=8#700})
end,
ok.
@@ -1602,7 +1442,7 @@ e_make_dir(Config) when is_list(Config) ->
?PRIM_FILE:write_file_info(Base, #file_info {mode=0}),
{error, eacces} =
?PRIM_FILE:make_dir(filename:join(Base, "xxxx")),
- ?PRIM_FILE:write_file_info(Base, #file_info {mode=8#600})
+ ?PRIM_FILE:write_file_info(Base, #file_info {mode=8#700})
end,
ok.
@@ -1652,170 +1492,24 @@ e_del_dir(Config) when is_list(Config) ->
?PRIM_FILE:write_file_info(Base, #file_info {mode=0}),
{error, eacces} = ?PRIM_FILE:del_dir(ADirectory),
?PRIM_FILE:write_file_info(
- Base, #file_info {mode=8#600})
- end,
- ok.
-
-
-%% Trying reading and positioning from a compressed file.
-
-read_compressed(Config) when is_list(Config) ->
- Data = proplists:get_value(data_dir, Config),
- Real = filename:join(Data, "realmen.html.gz"),
- {ok, Fd} = ?PRIM_FILE:open(Real, [read, compressed]),
- try_read_file(Fd).
-
-%% Trying reading and positioning from an uncompressed file,
-%% but with the compressed flag given.
-
-read_not_really_compressed(Config) when is_list(Config) ->
- Data = proplists:get_value(data_dir, Config),
- Priv = proplists:get_value(priv_dir, Config),
-
- %% The file realmen.html might have got CRs added (by WinZip).
- %% Remove them, or the file positions will not be correct.
-
- Real = filename:join(Data, "realmen.html"),
- RealPriv = filename:join(Priv,
- atom_to_list(?MODULE)++"_realmen.html"),
- {ok, RealDataBin} = ?PRIM_FILE:read_file(Real),
- RealData = remove_crs(binary_to_list(RealDataBin), []),
- ok = ?PRIM_FILE:write_file(RealPriv, RealData),
- {ok, Fd} = ?PRIM_FILE:open(RealPriv, [read, compressed]),
- try_read_file(Fd).
-
-remove_crs([$\r|Rest], Result) ->
- remove_crs(Rest, Result);
-remove_crs([C|Rest], Result) ->
- remove_crs(Rest, [C|Result]);
-remove_crs([], Result) ->
- lists:reverse(Result).
-
-try_read_file(Fd) ->
- %% Seek to the current position (nothing should happen).
-
- {ok, 0} = ?PRIM_FILE:position(Fd, 0),
- {ok, 0} = ?PRIM_FILE:position(Fd, {cur, 0}),
-
- %% Read a few lines from a compressed file.
-
- ShouldBe = "<TITLE>Real Programmers Don't Use PASCAL</TITLE>\n",
- {ok, ShouldBe} = ?PRIM_FILE:read(Fd, length(ShouldBe)),
-
- %% Now seek forward.
-
- {ok, 381} = ?PRIM_FILE:position(Fd, 381),
- Back = "Back in the good old days -- the \"Golden Era\" " ++
- "of computers, it was\n",
- {ok, Back} = ?PRIM_FILE:read(Fd, length(Back)),
-
- %% Try to search forward relative to the current position.
-
- {ok, CurPos} = ?PRIM_FILE:position(Fd, {cur, 0}),
- RealPos = 4273,
- {ok, RealPos} = ?PRIM_FILE:position(Fd, {cur, RealPos-CurPos}),
- RealProg = "<LI> Real Programmers aren't afraid to use GOTOs.\n",
- {ok, RealProg} = ?PRIM_FILE:read(Fd, length(RealProg)),
-
- %% Seek backward.
-
- AfterTitle = length("<TITLE>"),
- {ok, AfterTitle} = ?PRIM_FILE:position(Fd, AfterTitle),
- Title = "Real Programmers Don't Use PASCAL</TITLE>\n",
- {ok, Title} = ?PRIM_FILE:read(Fd, length(Title)),
-
- %% Done.
-
- ?PRIM_FILE:close(Fd),
- ok.
-
-write_compressed(Config) when is_list(Config) ->
- Priv = proplists:get_value(priv_dir, Config),
- MyFile = filename:join(Priv,
- atom_to_list(?MODULE)++"_test.gz"),
-
- %% Write a file.
-
- {ok, Fd} = ?PRIM_FILE:open(MyFile, [write, compressed]),
- {ok, 0} = ?PRIM_FILE:position(Fd, 0),
- Prefix = "hello\n",
- End = "end\n",
- ok = ?PRIM_FILE:write(Fd, Prefix),
- {ok, 143} = ?PRIM_FILE:position(Fd, 143),
- ok = ?PRIM_FILE:write(Fd, End),
- ok = ?PRIM_FILE:close(Fd),
-
- %% Read the file and verify the contents.
-
- {ok, Fd1} = ?PRIM_FILE:open(MyFile, [read, compressed]),
- {ok, Prefix} = ?PRIM_FILE:read(Fd1, length(Prefix)),
- Second = lists:duplicate(143-length(Prefix), 0) ++ End,
- {ok, Second} = ?PRIM_FILE:read(Fd1, length(Second)),
- ok = ?PRIM_FILE:close(Fd1),
-
- %% Ensure that the file is compressed.
-
- TotalSize = 143 + length(End),
- case ?PRIM_FILE:read_file_info(MyFile) of
- {ok, #file_info{size=Size}} when Size < TotalSize ->
- ok;
- {ok, #file_info{size=Size}} when Size == TotalSize ->
- ct:fail(file_not_compressed)
+ Base, #file_info {mode=8#700})
end,
-
- %% Write again to ensure that the file is truncated.
-
- {ok, Fd2} = ?PRIM_FILE:open(MyFile, [write, compressed]),
- NewString = "aaaaaaaaaaa",
- ok = ?PRIM_FILE:write(Fd2, NewString),
- ok = ?PRIM_FILE:close(Fd2),
- {ok, Fd3} = ?PRIM_FILE:open(MyFile, [read, compressed]),
- {ok, NewString} = ?PRIM_FILE:read(Fd3, 1024),
- ok = ?PRIM_FILE:close(Fd3),
-
- ok.
-
-compress_errors(Config) when is_list(Config) ->
- Data = proplists:get_value(data_dir, Config),
- {error, enoent} = ?PRIM_FILE:open("non_existing__",
- [compressed, read]),
- {error, einval} = ?PRIM_FILE:open("non_existing__",
- [compressed, read, write]),
-
- %% Read a corrupted .gz file.
-
- Corrupted = filename:join(Data, "corrupted.gz"),
- {ok, Fd} = ?PRIM_FILE:open(Corrupted, [read, compressed]),
- {error, eio} = ?PRIM_FILE:read(Fd, 100),
- ?PRIM_FILE:close(Fd),
-
ok.
-%% Test creating a hard link.
-make_link_a(Config) when is_list(Config) ->
- make_link(Config, [], "_a").
-
-%% Test creating a hard link.
-make_link_b(Config) when is_list(Config) ->
- {ok, Handle} = ?PRIM_FILE:start(),
- Result = make_link(Config, Handle, "_b"),
- ok = ?PRIM_FILE:stop(Handle),
- Result.
-
-make_link(Config, Handle, Suffix) ->
+make_link(Config) when is_list(Config) ->
RootDir = proplists:get_value(priv_dir, Config),
NewDir = filename:join(RootDir,
atom_to_list(?MODULE)
- ++"_make_link"++Suffix),
- ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
+ ++"_make_link"),
+ ok = ?PRIM_FILE:make_dir(NewDir),
Name = filename:join(NewDir, "a_file"),
ok = ?PRIM_FILE:write_file(Name, "some contents\n"),
Alias = filename:join(NewDir, "an_alias"),
Result =
- case ?PRIM_FILE_call(make_link, Handle, [Name, Alias]) of
+ case ?PRIM_FILE:make_link(Name, Alias) of
{error, enotsup} ->
{skipped, "Links not supported on this platform"};
ok ->
@@ -1826,12 +1520,12 @@ make_link(Config, Handle, Suffix) ->
%% since they are not used on symbolic links.
{ok, Info} =
- ?PRIM_FILE_call(read_link_info, Handle, [Name]),
+ ?PRIM_FILE:read_link_info(Name),
{ok, Info} =
- ?PRIM_FILE_call(read_link_info, Handle, [Alias]),
+ ?PRIM_FILE:read_link_info(Alias),
#file_info{links = 2, type = regular} = Info,
{error, eexist} =
- ?PRIM_FILE_call(make_link, Handle, [Name, Alias]),
+ ?PRIM_FILE:make_link(Name, Alias),
ok
end,
@@ -1843,30 +1537,19 @@ read_link_info_for_non_link(Config) when is_list(Config) ->
{ok, #file_info{type=directory}} = ?PRIM_FILE:read_link_info("."),
ok.
-%% Test operations on symbolic links (for Unix).
-symlinks_a(Config) when is_list(Config) ->
- symlinks(Config, [], "_a").
-
-%% Test operations on symbolic links (for Unix).
-symlinks_b(Config) when is_list(Config) ->
- {ok, Handle} = ?PRIM_FILE:start(),
- Result = symlinks(Config, Handle, "_b"),
- ok = ?PRIM_FILE:stop(Handle),
- Result.
-
-symlinks(Config, Handle, Suffix) ->
+symlinks(Config) when is_list(Config) ->
RootDir = proplists:get_value(priv_dir, Config),
NewDir = filename:join(RootDir,
atom_to_list(?MODULE)
- ++"_make_symlink"++Suffix),
- ok = ?PRIM_FILE_call(make_dir, Handle, [NewDir]),
+ ++"_make_symlink"),
+ ok = ?PRIM_FILE:make_dir(NewDir),
Name = filename:join(NewDir, "a_plain_file"),
ok = ?PRIM_FILE:write_file(Name, "some stupid content\n"),
Alias = filename:join(NewDir, "a_symlink_alias"),
Result =
- case ?PRIM_FILE_call(make_symlink, Handle, [Name, Alias]) of
+ case ?PRIM_FILE:make_symlink(Name, Alias) of
{error, enotsup} ->
{skipped, "Links not supported on this platform"};
{error, eperm} ->
@@ -1874,20 +1557,20 @@ symlinks(Config, Handle, Suffix) ->
{skipped, "Windows user not privileged to create links"};
ok ->
{ok, Info1} =
- ?PRIM_FILE_call(read_file_info, Handle, [Name]),
+ ?PRIM_FILE:read_file_info(Name),
{ok, Info1} =
- ?PRIM_FILE_call(read_file_info, Handle, [Alias]),
+ ?PRIM_FILE:read_file_info(Alias),
{ok, Info1} =
- ?PRIM_FILE_call(read_link_info, Handle, [Name]),
+ ?PRIM_FILE:read_link_info(Name),
#file_info{links = 1, type = regular} = Info1,
{ok, Info2} =
- ?PRIM_FILE_call(read_link_info, Handle, [Alias]),
+ ?PRIM_FILE:read_link_info(Alias),
#file_info{links=1, type=symlink} = Info2,
{ok, Name} =
- ?PRIM_FILE_call(read_link, Handle, [Alias]),
+ ?PRIM_FILE:read_link(Alias),
{ok, Name} =
- ?PRIM_FILE_call(read_link_all, Handle, [Alias]),
+ ?PRIM_FILE:read_link_all(Alias),
%% If all is good, delete dir again (avoid hanging dir on windows)
rm_rf(?PRIM_FILE,NewDir),
ok
@@ -1907,10 +1590,9 @@ list_dir_limit(Config) when is_list(Config) ->
RootDir = proplists:get_value(priv_dir, Config),
NewDir = filename:join(RootDir,
atom_to_list(?MODULE)++"_list_dir_limit"),
- {ok, Handle1} = ?PRIM_FILE:start(),
- ok = ?PRIM_FILE_call(make_dir, Handle1, [NewDir]),
+ ok = ?PRIM_FILE:make_dir(NewDir),
Ref = erlang:start_timer(MaxTime*1000, self(), []),
- Result = list_dir_limit_loop(NewDir, Handle1, Ref, MaxNumber, 0),
+ Result = list_dir_limit_loop(NewDir, Ref, MaxNumber, 0),
Time = case erlang:cancel_timer(Ref) of
false -> MaxTime;
T -> MaxTime - (T div 1000)
@@ -1920,21 +1602,18 @@ list_dir_limit(Config) when is_list(Config) ->
{error, _Reason, N} -> N;
_ -> 0
end,
- {ok, Handle2} = ?PRIM_FILE:start(),
- list_dir_limit_cleanup(NewDir, Handle2, Number, 0),
- ok = ?PRIM_FILE:stop(Handle1),
- ok = ?PRIM_FILE:stop(Handle2),
+ list_dir_limit_cleanup(NewDir, Number, 0),
{ok, Number} = Result,
{comment,
"Created " ++ integer_to_list(Number) ++ " files in "
++ integer_to_list(Time) ++ " seconds."}.
-list_dir_limit_loop(Dir, Handle, _Ref, N, Cnt) when Cnt >= N ->
- list_dir_check(Dir, Handle, Cnt);
-list_dir_limit_loop(Dir, Handle, Ref, N, Cnt) ->
+list_dir_limit_loop(Dir, _Ref, N, Cnt) when Cnt >= N ->
+ list_dir_check(Dir, Cnt);
+list_dir_limit_loop(Dir, Ref, N, Cnt) ->
receive
{timeout, Ref, []} ->
- list_dir_check(Dir, Handle, Cnt)
+ list_dir_check(Dir, Cnt)
after 0 ->
Name = integer_to_list(Cnt),
case ?PRIM_FILE:write_file(filename:join(Dir, Name), Name) of
@@ -1942,23 +1621,23 @@ list_dir_limit_loop(Dir, Handle, Ref, N, Cnt) ->
Next = Cnt + 1,
case Cnt rem 100 of
0 ->
- case list_dir_check(Dir, Handle, Next) of
+ case list_dir_check(Dir, Next) of
{ok, Next} ->
list_dir_limit_loop(
- Dir, Handle, Ref, N, Next);
+ Dir, Ref, N, Next);
Other ->
Other
end;
_ ->
- list_dir_limit_loop(Dir, Handle, Ref, N, Next)
+ list_dir_limit_loop(Dir, Ref, N, Next)
end;
{error, Reason} ->
{error, Reason, Cnt}
end
end.
-list_dir_check(Dir, Handle, Cnt) ->
- case ?PRIM_FILE:list_dir(Handle, Dir) of
+list_dir_check(Dir, Cnt) ->
+ case ?PRIM_FILE:list_dir(Dir) of
{ok, ListDir} ->
case length(ListDir) of
Cnt ->
@@ -1975,18 +1654,18 @@ list_dir_check(Dir, Handle, Cnt) ->
%% Deletes N files while ignoring errors, then continues deleting
%% as long as they exist.
-list_dir_limit_cleanup(Dir, Handle, N, Cnt) when Cnt >= N ->
+list_dir_limit_cleanup(Dir, N, Cnt) when Cnt >= N ->
Name = integer_to_list(Cnt),
- case ?PRIM_FILE:delete(Handle, filename:join(Dir, Name)) of
+ case ?PRIM_FILE:delete(filename:join(Dir, Name)) of
ok ->
- list_dir_limit_cleanup(Dir, Handle, N, Cnt+1);
+ list_dir_limit_cleanup(Dir, N, Cnt+1);
_ ->
ok
end;
-list_dir_limit_cleanup(Dir, Handle, N, Cnt) ->
+list_dir_limit_cleanup(Dir, N, Cnt) ->
Name = integer_to_list(Cnt),
- ?PRIM_FILE:delete(Handle, filename:join(Dir, Name)),
- list_dir_limit_cleanup(Dir, Handle, N, Cnt+1).
+ ?PRIM_FILE:delete(filename:join(Dir, Name)),
+ list_dir_limit_cleanup(Dir, N, Cnt+1).
%%%
%%% Test list_dir() on a non-existing pathname.
@@ -1995,7 +1674,7 @@ list_dir_limit_cleanup(Dir, Handle, N, Cnt) ->
list_dir_error(Config) ->
Priv = proplists:get_value(priv_dir, Config),
NonExisting = filename:join(Priv, "non-existing-dir"),
- {error,enoent} = prim_file:list_dir(NonExisting),
+ {error,enoent} = ?PRIM_FILE:list_dir(NonExisting),
ok.
%%%
@@ -2063,7 +1742,7 @@ do_run_large_file_test(Config, Run, Name0) ->
{'DOWN',Mref,_,_,_} -> ok;
{Tester,done} -> ok
end,
- prim_file:delete(Name)
+ ?PRIM_FILE:delete(Name)
end),
%% Run the test case.
@@ -2108,12 +1787,25 @@ free_memory() ->
{value, {buffered_memory, Buffed}} -> Buffed;
false -> 0
end),
- TotFree div (1024*1024)
+ usable_mem(TotFree) div (1024*1024)
catch
error : undef ->
ct:fail({"os_mon not built"})
end.
+usable_mem(Memory) ->
+ case test_server:is_valgrind() of
+ true ->
+ %% Valgrind uses extra memory for the V- and A-bits.
+ %% http://valgrind.org/docs/manual/mc-manual.html#mc-manual.value
+ %% Docs says it uses "compression to represent the V bits compactly"
+ %% but let's be conservative and cut usable memory in half.
+ Memory div 2;
+ false ->
+ Memory
+ end.
+
+
%%%-----------------------------------------------------------------
%%% Utilities
rm_rf(Mod,Dir) ->
diff --git a/lib/kernel/test/sendfile_SUITE.erl b/lib/kernel/test/sendfile_SUITE.erl
index bfa564c32c..0c0b1cbcb6 100644
--- a/lib/kernel/test/sendfile_SUITE.erl
+++ b/lib/kernel/test/sendfile_SUITE.erl
@@ -23,30 +23,41 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
--compile(export_all).
-
-all() -> [{group,async_threads},
- {group,no_async_threads}].
-
-groups() ->
- [{async_threads,[],tcs()},
- {no_async_threads,[],tcs()}].
-
-tcs() ->
- [t_sendfile_small
- ,t_sendfile_big_all
- ,t_sendfile_big_size
- ,t_sendfile_many_small
- ,t_sendfile_partial
- ,t_sendfile_offset
- ,t_sendfile_sendafter
- ,t_sendfile_recvafter
- ,t_sendfile_recvafter_remoteclose
- ,t_sendfile_sendduring
- ,t_sendfile_recvduring
- ,t_sendfile_closeduring
- ,t_sendfile_crashduring
- ].
+-export([all/0, init_per_suite/1, end_per_suite/1, init_per_testcase/2]).
+
+-export([sendfile_server/2, sendfile_do_recv/2, init/1, handle_event/2]).
+
+-export(
+ [t_sendfile_small/1,
+ t_sendfile_big_all/1,
+ t_sendfile_big_size/1,
+ t_sendfile_many_small/1,
+ t_sendfile_partial/1,
+ t_sendfile_offset/1,
+ t_sendfile_sendafter/1,
+ t_sendfile_recvafter/1,
+ t_sendfile_recvafter_remoteclose/1,
+ t_sendfile_sendduring/1,
+ t_sendfile_recvduring/1,
+ t_sendfile_closeduring/1,
+ t_sendfile_crashduring/1,
+ t_sendfile_arguments/1]).
+
+all() ->
+ [t_sendfile_small,
+ t_sendfile_big_all,
+ t_sendfile_big_size,
+ t_sendfile_many_small,
+ t_sendfile_partial,
+ t_sendfile_offset,
+ t_sendfile_sendafter,
+ t_sendfile_recvafter,
+ t_sendfile_recvafter_remoteclose,
+ t_sendfile_sendduring,
+ t_sendfile_recvduring,
+ t_sendfile_closeduring,
+ t_sendfile_crashduring,
+ t_sendfile_arguments].
init_per_suite(Config) ->
case {os:type(),os:version()} of
@@ -72,28 +83,18 @@ init_per_suite(Config) ->
end_per_suite(Config) ->
file:delete(proplists:get_value(big_file, Config)).
-init_per_group(async_threads,Config) ->
- case erlang:system_info(thread_pool_size) of
- 0 ->
- {skip,"No async threads"};
- _ ->
- [{sendfile_opts,[{use_threads,true}]}|Config]
- end;
-init_per_group(no_async_threads,Config) ->
- [{sendfile_opts,[{use_threads,false}]}|Config].
-
-end_per_group(_,_Config) ->
- ok.
-
init_per_testcase(TC,Config) when TC == t_sendfile_recvduring;
TC == t_sendfile_sendduring ->
Filename = proplists:get_value(small_file, Config),
Send = fun(Sock) ->
{_Size, Data} = sendfile_file_info(Filename),
- {ok,D} = file:open(Filename, [raw,binary,read]),
- prim_file:sendfile(D, Sock, 0, 0, 0,
- [],[],[]),
+ {ok,Fd} = file:open(Filename, [raw,binary,read]),
+ %% Determine whether the driver has native support by
+ %% hitting the raw module directly; file:sendfile/5 will
+ %% land in the fallback if it doesn't.
+ RawModule = Fd#file_descriptor.module,
+ {ok, _Ignored} = RawModule:sendfile(Fd,Sock,0,0,0,[],[],[]),
Data
end,
@@ -105,9 +106,8 @@ init_per_testcase(TC,Config) when TC == t_sendfile_recvduring;
ct:log("Error: ~p",[Error]),
{skip,"Not supported"}
end;
-init_per_testcase(_Tc,Config) ->
- Config ++ [{sendfile_opts,[{use_threads,false}]}].
-
+init_per_testcase(_TC,Config) ->
+ Config.
t_sendfile_small(Config) when is_list(Config) ->
Filename = proplists:get_value(small_file, Config),
@@ -124,7 +124,7 @@ t_sendfile_small(Config) when is_list(Config) ->
t_sendfile_many_small(Config) when is_list(Config) ->
Filename = proplists:get_value(small_file, Config),
FileOpts = proplists:get_value(file_opts, Config, []),
- SendfileOpts = proplists:get_value(sendfile_opts, Config),
+ SendfileOpts = proplists:get_value(sendfile_opts, Config, []),
error_logger:add_report_handler(?MODULE,[self()]),
@@ -151,7 +151,7 @@ t_sendfile_many_small(Config) when is_list(Config) ->
t_sendfile_big_all(Config) when is_list(Config) ->
Filename = proplists:get_value(big_file, Config),
- SendfileOpts = proplists:get_value(sendfile_opts, Config),
+ SendfileOpts = proplists:get_value(sendfile_opts, Config, []),
Send = fun(Sock) ->
{ok, #file_info{size = Size}} =
@@ -165,7 +165,7 @@ t_sendfile_big_all(Config) when is_list(Config) ->
t_sendfile_big_size(Config) ->
Filename = proplists:get_value(big_file, Config),
FileOpts = proplists:get_value(file_opts, Config, []),
- SendfileOpts = proplists:get_value(sendfile_opts, Config),
+ SendfileOpts = proplists:get_value(sendfile_opts, Config, []),
SendAll = fun(Sock) ->
{ok, #file_info{size = Size}} =
@@ -180,7 +180,7 @@ t_sendfile_big_size(Config) ->
t_sendfile_partial(Config) ->
Filename = proplists:get_value(small_file, Config),
FileOpts = proplists:get_value(file_opts, Config, []),
- SendfileOpts = proplists:get_value(sendfile_opts, Config),
+ SendfileOpts = proplists:get_value(sendfile_opts, Config, []),
SendSingle = fun(Sock) ->
{_Size, <<Data:5/binary,_/binary>>} =
@@ -217,7 +217,7 @@ t_sendfile_partial(Config) ->
t_sendfile_offset(Config) ->
Filename = proplists:get_value(small_file, Config),
FileOpts = proplists:get_value(file_opts, Config, []),
- SendfileOpts = proplists:get_value(sendfile_opts, Config),
+ SendfileOpts = proplists:get_value(sendfile_opts, Config, []),
Send = fun(Sock) ->
{_Size, <<_:5/binary,Data:3/binary,_/binary>> = AllData} =
@@ -233,7 +233,7 @@ t_sendfile_offset(Config) ->
t_sendfile_sendafter(Config) ->
Filename = proplists:get_value(small_file, Config),
- SendfileOpts = proplists:get_value(sendfile_opts, Config),
+ SendfileOpts = proplists:get_value(sendfile_opts, Config, []),
Send = fun(Sock) ->
{Size, Data} = sendfile_file_info(Filename),
@@ -246,7 +246,7 @@ t_sendfile_sendafter(Config) ->
t_sendfile_recvafter(Config) ->
Filename = proplists:get_value(small_file, Config),
- SendfileOpts = proplists:get_value(sendfile_opts, Config),
+ SendfileOpts = proplists:get_value(sendfile_opts, Config, []),
Send = fun(Sock) ->
{Size, Data} = sendfile_file_info(Filename),
@@ -279,7 +279,7 @@ t_sendfile_recvafter_remoteclose(Config) ->
t_sendfile_sendduring(Config) ->
Filename = proplists:get_value(big_file, Config),
- SendfileOpts = proplists:get_value(sendfile_opts, Config),
+ SendfileOpts = proplists:get_value(sendfile_opts, Config, []),
Send = fun(Sock) ->
{ok, #file_info{size = Size}} =
@@ -296,7 +296,7 @@ t_sendfile_sendduring(Config) ->
t_sendfile_recvduring(Config) ->
Filename = proplists:get_value(big_file, Config),
- SendfileOpts = proplists:get_value(sendfile_opts, Config),
+ SendfileOpts = proplists:get_value(sendfile_opts, Config, []),
Send = fun(Sock) ->
{ok, #file_info{size = Size}} =
@@ -315,7 +315,7 @@ t_sendfile_recvduring(Config) ->
t_sendfile_closeduring(Config) ->
Filename = proplists:get_value(big_file, Config),
- SendfileOpts = proplists:get_value(sendfile_opts, Config),
+ SendfileOpts = proplists:get_value(sendfile_opts, Config, []),
Send = fun(Sock,SFServPid) ->
spawn_link(fun() ->
@@ -345,7 +345,7 @@ t_sendfile_closeduring(Config) ->
t_sendfile_crashduring(Config) ->
Filename = proplists:get_value(big_file, Config),
- SendfileOpts = proplists:get_value(sendfile_opts, Config),
+ SendfileOpts = proplists:get_value(sendfile_opts, Config, []),
error_logger:add_report_handler(?MODULE,[self()]),
@@ -373,6 +373,36 @@ t_sendfile_crashduring(Config) ->
end
end.
+t_sendfile_arguments(Config) ->
+ Filename = proplists:get_value(small_file, Config),
+
+ {ok, Listener} = gen_tcp:listen(0,
+ [{packet, 0}, {active, false}, {reuseaddr, true}]),
+ {ok, Port} = inet:port(Listener),
+
+ ErrorCheck =
+ fun(Reason, Offset, Length, Opts) ->
+ {ok, Sender} = gen_tcp:connect({127, 0, 0, 1}, Port,
+ [{packet, 0}, {active, false}]),
+ {ok, Receiver} = gen_tcp:accept(Listener),
+ {ok, Fd} = file:open(Filename, [read, raw]),
+ {error, Reason} = file:sendfile(Fd, Sender, Offset, Length, Opts),
+ gen_tcp:close(Receiver),
+ gen_tcp:close(Sender),
+ file:close(Fd)
+ end,
+
+ ErrorCheck(einval, -1, 0, []),
+ ErrorCheck(einval, 0, -1, []),
+ ErrorCheck(badarg, gurka, 0, []),
+ ErrorCheck(badarg, 0, gurka, []),
+ ErrorCheck(badarg, 0, 0, gurka),
+ ErrorCheck(badarg, 0, 0, [{chunk_size, gurka}]),
+
+ gen_tcp:close(Listener),
+
+ ok.
+
%% Generic sendfile server code
sendfile_send(Send) ->
sendfile_send({127,0,0,1},Send).
diff --git a/lib/kernel/test/seq_trace_SUITE.erl b/lib/kernel/test/seq_trace_SUITE.erl
index be23a1933f..cf4bf11328 100644
--- a/lib/kernel/test/seq_trace_SUITE.erl
+++ b/lib/kernel/test/seq_trace_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
-export([token_set_get/1, tracer_set_get/1, print/1,
send/1, distributed_send/1, recv/1, distributed_recv/1,
trace_exit/1, distributed_exit/1, call/1, port/1,
- match_set_seq_token/1, gc_seq_token/1]).
+ match_set_seq_token/1, gc_seq_token/1, label_capability_mismatch/1]).
%% internal exports
-export([simple_tracer/2, one_time_receiver/0, one_time_receiver/1,
@@ -47,7 +47,7 @@ all() ->
[token_set_get, tracer_set_get, print, send,
distributed_send, recv, distributed_recv, trace_exit,
distributed_exit, call, port, match_set_seq_token,
- gc_seq_token].
+ gc_seq_token, label_capability_mismatch].
groups() ->
[].
@@ -90,8 +90,8 @@ do_token_set_get(TsType) ->
%% Test that initial seq_trace is disabled
[] = seq_trace:get_token(),
%% Test setting and reading the different fields
- 0 = seq_trace:set_token(label,17),
- {label,17} = seq_trace:get_token(label),
+ 0 = seq_trace:set_token(label,{my_label,1}),
+ {label,{my_label,1}} = seq_trace:get_token(label),
false = seq_trace:set_token(print,true),
{print,true} = seq_trace:get_token(print),
false = seq_trace:set_token(send,true),
@@ -101,12 +101,12 @@ do_token_set_get(TsType) ->
false = seq_trace:set_token(TsType,true),
{TsType,true} = seq_trace:get_token(TsType),
%% Check the whole token
- {Flags,17,0,Self,0} = seq_trace:get_token(), % all flags are set
+ {Flags,{my_label,1},0,Self,0} = seq_trace:get_token(), % all flags are set
%% Test setting and reading the 'serial' field
{0,0} = seq_trace:set_token(serial,{3,5}),
{serial,{3,5}} = seq_trace:get_token(serial),
%% Check the whole token, test that a whole token can be set and get
- {Flags,17,5,Self,3} = seq_trace:get_token(),
+ {Flags,{my_label,1},5,Self,3} = seq_trace:get_token(),
seq_trace:set_token({Flags,19,7,Self,5}),
{Flags,19,7,Self,5} = seq_trace:get_token(),
%% Check that receive timeout does not reset token
@@ -166,11 +166,13 @@ do_send(TsType) ->
seq_trace:reset_trace(),
start_tracer(),
Receiver = spawn(?MODULE,one_time_receiver,[]),
+ Label = make_ref(),
+ seq_trace:set_token(label,Label),
set_token_flags([send, TsType]),
Receiver ! send,
Self = self(),
seq_trace:reset_trace(),
- [{0,{send,_,Self,Receiver,send}, Ts}] = stop_tracer(1),
+ [{Label,{send,_,Self,Receiver,send}, Ts}] = stop_tracer(1),
check_ts(TsType, Ts).
distributed_send(Config) when is_list(Config) ->
@@ -184,14 +186,19 @@ do_distributed_send(TsType) ->
seq_trace:reset_trace(),
start_tracer(),
Receiver = spawn(Node,?MODULE,one_time_receiver,[]),
+
+ %% Make sure complex labels survive the trip.
+ Label = make_ref(),
+ seq_trace:set_token(label,Label),
set_token_flags([send,TsType]),
+
Receiver ! send,
Self = self(),
seq_trace:reset_trace(),
stop_node(Node),
- [{0,{send,_,Self,Receiver,send}, Ts}] = stop_tracer(1),
+ [{Label,{send,_,Self,Receiver,send}, Ts}] = stop_tracer(1),
check_ts(TsType, Ts).
-
+
recv(Config) when is_list(Config) ->
lists:foreach(fun do_recv/1, ?TIMESTAMP_MODES).
@@ -220,7 +227,12 @@ do_distributed_recv(TsType) ->
seq_trace:reset_trace(),
rpc:call(Node,?MODULE,start_tracer,[]),
Receiver = spawn(Node,?MODULE,one_time_receiver,[]),
+
+ %% Make sure complex labels survive the trip.
+ Label = make_ref(),
+ seq_trace:set_token(label,Label),
set_token_flags(['receive',TsType]),
+
Receiver ! 'receive',
%% let the other process receive the message:
receive after 1 -> ok end,
@@ -229,7 +241,7 @@ do_distributed_recv(TsType) ->
Result = rpc:call(Node,?MODULE,stop_tracer,[1]),
stop_node(Node),
ok = io:format("~p~n",[Result]),
- [{0,{'receive',_,Self,Receiver,'receive'}, Ts}] = Result,
+ [{Label,{'receive',_,Self,Receiver,'receive'}, Ts}] = Result,
check_ts(TsType, Ts).
trace_exit(Config) when is_list(Config) ->
@@ -240,7 +252,12 @@ do_trace_exit(TsType) ->
start_tracer(),
Receiver = spawn_link(?MODULE, one_time_receiver, [exit]),
process_flag(trap_exit, true),
+
+ %% Make sure complex labels survive the trip.
+ Label = make_ref(),
+ seq_trace:set_token(label,Label),
set_token_flags([send, TsType]),
+
Receiver ! {before, exit},
%% let the other process receive the message:
receive
@@ -254,8 +271,8 @@ do_trace_exit(TsType) ->
Result = stop_tracer(2),
seq_trace:reset_trace(),
ok = io:format("~p~n", [Result]),
- [{0, {send, {0,1}, Self, Receiver, {before, exit}}, Ts0},
- {0, {send, {1,2}, Receiver, Self,
+ [{Label, {send, {0,1}, Self, Receiver, {before, exit}}, Ts0},
+ {Label, {send, {1,2}, Receiver, Self,
{'EXIT', Receiver, {exit, {before, exit}}}}, Ts1}] = Result,
check_ts(TsType, Ts0),
check_ts(TsType, Ts1).
@@ -291,6 +308,74 @@ do_distributed_exit(TsType) ->
{'EXIT', Receiver, {exit, {before, exit}}}}, Ts}] = Result,
check_ts(TsType, Ts).
+label_capability_mismatch(Config) when is_list(Config) ->
+ Releases = ["20_latest"],
+ Available = [Rel || Rel <- Releases, test_server:is_release_available(Rel)],
+ case Available of
+ [] -> {skipped, "No incompatible releases available"};
+ _ ->
+ lists:foreach(fun do_incompatible_labels/1, Available),
+ lists:foreach(fun do_compatible_labels/1, Available),
+ ok
+ end.
+
+do_incompatible_labels(Rel) ->
+ Cookie = atom_to_list(erlang:get_cookie()),
+ {ok, Node} = test_server:start_node(
+ list_to_atom(atom_to_list(?MODULE)++"_"++Rel), peer,
+ [{args, " -setcookie "++Cookie}, {erl, [{release, Rel}]}]),
+
+ {_,Dir} = code:is_loaded(?MODULE),
+ Mdir = filename:dirname(Dir),
+ true = rpc:call(Node,code,add_patha,[Mdir]),
+ seq_trace:reset_trace(),
+ rpc:call(Node,?MODULE,start_tracer,[]),
+ Receiver = spawn(Node,?MODULE,one_time_receiver,[]),
+
+ %% This node does not support arbitrary labels, so it must fail with a
+ %% timeout as the token is dropped silently.
+ seq_trace:set_token(label,make_ref()),
+ seq_trace:set_token('receive',true),
+
+ Receiver ! 'receive',
+ %% let the other process receive the message:
+ receive after 10 -> ok end,
+ seq_trace:reset_trace(),
+
+ {error,timeout} = rpc:call(Node,?MODULE,stop_tracer,[1]),
+ stop_node(Node),
+ ok.
+
+do_compatible_labels(Rel) ->
+ Cookie = atom_to_list(erlang:get_cookie()),
+ {ok, Node} = test_server:start_node(
+ list_to_atom(atom_to_list(?MODULE)++"_"++Rel), peer,
+ [{args, " -setcookie "++Cookie}, {erl, [{release, Rel}]}]),
+
+ {_,Dir} = code:is_loaded(?MODULE),
+ Mdir = filename:dirname(Dir),
+ true = rpc:call(Node,code,add_patha,[Mdir]),
+ seq_trace:reset_trace(),
+ rpc:call(Node,?MODULE,start_tracer,[]),
+ Receiver = spawn(Node,?MODULE,one_time_receiver,[]),
+
+ %% This node does not support arbitrary labels, but small integers should
+ %% still work.
+ Label = 1234,
+ seq_trace:set_token(label,Label),
+ seq_trace:set_token('receive',true),
+
+ Receiver ! 'receive',
+ %% let the other process receive the message:
+ receive after 10 -> ok end,
+ Self = self(),
+ seq_trace:reset_trace(),
+ Result = rpc:call(Node,?MODULE,stop_tracer,[1]),
+ stop_node(Node),
+ ok = io:format("~p~n",[Result]),
+ [{Label,{'receive',_,Self,Receiver,'receive'}, _}] = Result,
+ ok.
+
call(doc) ->
"Tests special forms {is_seq_trace} and {get_seq_token} "
"in trace match specs.";
@@ -698,6 +783,24 @@ do_shrink(N) ->
erlang:garbage_collect(),
do_shrink(N-1).
+%% Test that messages from a port does not clear the token
+port_clean_token(Config) when is_list(Config) ->
+ seq_trace:reset_trace(),
+ Label = make_ref(),
+ seq_trace:set_token(label, Label),
+ {label,Label} = seq_trace:get_token(label),
+
+ %% Create a port and get messages from it
+ %% We use os:cmd as a convenience as it does
+ %% open_port, port_command, port_close and receives replies.
+ %% Maybe it is not ideal to rely on the internal implementation
+ %% of os:cmd but it will have to do.
+ os:cmd("ls"),
+
+ %% Make sure that the seq_trace token is still there
+ {label,Label} = seq_trace:get_token(label),
+
+ ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/kernel/test/wrap_log_reader_SUITE.erl b/lib/kernel/test/wrap_log_reader_SUITE.erl
index 40a016aed0..59b088ca73 100644
--- a/lib/kernel/test/wrap_log_reader_SUITE.erl
+++ b/lib/kernel/test/wrap_log_reader_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -428,13 +428,14 @@ stop() ->
ok = wrap_log_test:stop(),
dl_wait().
-%% Give disk logs opened by 'logger' and 'wlt' time to close after
+%% Give disk logs opened by 'wlr_logger' and 'wlt' time to close after
%% receiving EXIT signals.
dl_wait() ->
case disk_log:accessible_logs() of
{[], []} ->
ok;
- _ ->
+ _X ->
+ erlang:display(_X),
timer:sleep(100),
dl_wait()
end.
@@ -507,27 +508,27 @@ add_ext(Name, Ext) ->
%% disk_log.
open(Log, File, Where) ->
- logger ! {open, self(), Log, File},
+ wlr_logger ! {open, self(), Log, File},
rec1(ok, Where).
open_ext(Log, File, Where) ->
- logger ! {open_ext, self(), Log, File},
+ wlr_logger ! {open_ext, self(), Log, File},
rec1(ok, Where).
close(Log) ->
- logger ! {close, self(), Log},
+ wlr_logger ! {close, self(), Log},
rec(ok, ?LINE).
sync(Log) ->
- logger ! {sync, self(), Log},
+ wlr_logger ! {sync, self(), Log},
rec(ok, ?LINE).
log_terms(File, Terms) ->
- logger ! {log_terms, self(), File, Terms},
+ wlr_logger ! {log_terms, self(), File, Terms},
rec(ok, ?LINE).
blog_terms(File, Terms) ->
- logger ! {blog_terms, self(), File, Terms},
+ wlr_logger ! {blog_terms, self(), File, Terms},
rec(ok, ?LINE).
rec1(M, Where) ->
diff --git a/lib/kernel/test/wrap_log_reader_SUITE_data/wrap_log_test.erl b/lib/kernel/test/wrap_log_reader_SUITE_data/wrap_log_test.erl
index 38449b6bb3..d2bac40192 100644
--- a/lib/kernel/test/wrap_log_reader_SUITE_data/wrap_log_test.erl
+++ b/lib/kernel/test/wrap_log_reader_SUITE_data/wrap_log_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,9 +36,9 @@
-endif.
init() ->
- spawn(fun() -> start(logger) end),
+ spawn(fun() -> start(wlr_logger) end),
spawn(fun() -> start2(wlt) end),
- wait_registered(logger),
+ wait_registered(wlr_logger),
wait_registered(wlt),
ok.
@@ -52,9 +52,9 @@ wait_registered(Name) ->
end.
stop() ->
- catch logger ! exit,
+ catch wlr_logger ! exit,
catch wlt ! exit,
- wait_unregistered(logger),
+ wait_unregistered(wlr_logger),
wait_unregistered(wlt),
ok.
@@ -82,47 +82,47 @@ loop() ->
{open, Pid, Name, File} ->
R = disk_log:open([{name, Name}, {type, wrap}, {file, File},
{size, {?fsize, ?fno}}]),
- ?format("logger: open ~p -> ~p~n", [Name, R]),
+ ?format("wlr_logger: open ~p -> ~p~n", [Name, R]),
Pid ! R,
loop();
{open_ext, Pid, Name, File} ->
R = disk_log:open([{name, Name}, {type, wrap}, {file, File},
{format, external}, {size, {?fsize, ?fno}}]),
- ?format("logger: open ~p -> ~p~n", [Name, R]),
+ ?format("wlr_logger: open ~p -> ~p~n", [Name, R]),
Pid ! R,
loop();
{close, Pid, Name} ->
R = disk_log:close(Name),
- ?format("logger: close ~p -> ~p~n", [Name, R]),
+ ?format("wlr_logger: close ~p -> ~p~n", [Name, R]),
Pid ! R,
loop();
{sync, Pid, Name} ->
R = disk_log:sync(Name),
- ?format("logger: sync ~p -> ~p~n", [Name, R]),
+ ?format("wlr_logger: sync ~p -> ~p~n", [Name, R]),
Pid ! R,
loop();
{log_terms, Pid, Name, Terms} ->
R = disk_log:log_terms(Name, Terms),
- ?format("logger: log_terms ~p -> ~p~n", [Name, R]),
+ ?format("wlr_logger: log_terms ~p -> ~p~n", [Name, R]),
Pid ! R,
loop();
{blog_terms, Pid, Name, Terms} ->
R = disk_log:blog_terms(Name, Terms),
- ?format("logger: blog_terms ~p -> ~p~n", [Name, R]),
+ ?format("wlr_logger: blog_terms ~p -> ~p~n", [Name, R]),
Pid ! R,
loop();
exit ->
- ?format("Stopping logger~n", []),
+ ?format("Stopping wlr_logger~n", []),
exit(normal);
_Else ->
- ?format("logger: ignored: ~p~n", [_Else]),
+ ?format("wlr_logger: ignored: ~p~n", [_Else]),
loop()
end.
diff --git a/lib/kernel/test/zlib_SUITE.erl b/lib/kernel/test/zlib_SUITE.erl
index 4b67fce9a8..52ae1b3ae6 100644
--- a/lib/kernel/test/zlib_SUITE.erl
+++ b/lib/kernel/test/zlib_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,60 +21,56 @@
-module(zlib_SUITE).
-include_lib("common_test/include/ct.hrl").
-
--compile(export_all).
-
--define(error(Format,Args),
- put(test_server_loc,{?MODULE,?LINE}),
- error(Format,Args,?MODULE,?LINE)).
-
-%% Learn erts team how to really write tests ;-)
--define(m(ExpectedRes,Expr),
- fun() ->
- ACtual1 = (catch (Expr)),
- try case ACtual1 of
- ExpectedRes -> ACtual1
- end
- catch
- error:{case_clause,ACtuAl} ->
- ?error("Not Matching Actual result was:~n ~p ~n",
- [ACtuAl]),
- ACtuAl
- end
- end()).
-
--define(BARG, {'EXIT',{badarg,[{zlib,_,_,_}|_]}}).
--define(DATA_ERROR, {'EXIT',{data_error,[{zlib,_,_,_}|_]}}).
-
-init_per_testcase(_Func, Config) ->
- Config.
-
-end_per_testcase(_Func, _Config) ->
- ok.
-
-error(Format, Args, File, Line) ->
- io:format("~p:~p: ERROR: " ++ Format, [File,Line|Args]),
- group_leader() ! {failed, File, Line}.
-
-%% Hopefully I don't need this to get it to work with the testserver..
-%% Fail = #'REASON'{file = filename:basename(File),
-%% line = Line,
-%% desc = Args},
-%% case global:whereis_name(mnesia_test_case_sup) of
-%% undefined ->
-%% ignore;
-%% Pid ->
-%% Pid ! Fail
-%% %% global:send(mnesia_test_case_sup, Fail),
-%% end,
-%% log("<>ERROR<>~n" ++ Format, Args, File, Line).
+-include_lib("common_test/include/ct_event.hrl").
+
+-export([suite/0, all/0, groups/0]).
+
+%% API group
+-export([api_open_close/1]).
+-export([api_deflateInit/1, api_deflateSetDictionary/1, api_deflateReset/1,
+ api_deflateParams/1, api_deflate/1, api_deflateEnd/1]).
+-export([api_inflateInit/1, api_inflateReset/1, api_inflate2/1, api_inflate3/1,
+ api_inflateChunk/1, api_safeInflate/1, api_inflateEnd/1]).
+-export([api_inflateSetDictionary/1, api_inflateGetDictionary/1]).
+-export([api_crc32/1, api_adler32/1]).
+-export([api_un_compress/1, api_un_zip/1, api_g_un_zip/1]).
+
+%% Examples group
+-export([intro/1]).
+
+%% Usage group
+-export([zip_usage/1, gz_usage/1, gz_usage2/1, compress_usage/1,
+ dictionary_usage/1, large_deflate/1, crc/1, adler/1,
+ only_allow_owner/1, sub_heap_binaries/1]).
+
+%% Bench group
+-export([inflate_bench_zeroed/1, inflate_bench_rand/1,
+ deflate_bench_zeroed/1, deflate_bench_rand/1,
+ chunk_bench_zeroed/1, chunk_bench_rand/1]).
+
+%% Others
+-export([smp/1, otp_9981/1, otp_7359/1]).
+
+-define(m(Guard, Expression),
+ fun() ->
+ Actual = (catch (Expression)),
+ case Actual of
+ Guard -> Actual;
+ _Other ->
+ ct:fail("Failed to match ~p, actual result was ~p",
+ [??Guard, Actual])
+ end
+ end()).
+
+-define(EXIT(Reason), {'EXIT',{Reason,[{_,_,_,_}|_]}}).
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap,{minutes,1}}].
all() ->
- [{group, api}, {group, examples}, {group, func}, smp,
+ [{group, api}, {group, examples}, {group, func},
+ {group, bench}, smp,
otp_9981,
otp_7359].
@@ -84,28 +80,19 @@ groups() ->
api_deflateSetDictionary, api_deflateReset,
api_deflateParams, api_deflate, api_deflateEnd,
api_inflateInit, api_inflateSetDictionary, api_inflateGetDictionary,
- api_inflateSync, api_inflateReset, api_inflate, api_inflateChunk,
- api_inflateEnd, api_setBufsz, api_getBufsz, api_crc32,
- api_adler32, api_getQSize, api_un_compress, api_un_zip,
+ api_inflateReset, api_inflate2, api_inflate3, api_inflateChunk,
+ api_safeInflate, api_inflateEnd, api_crc32,
+ api_adler32, api_un_compress, api_un_zip,
api_g_un_zip]},
{examples, [], [intro]},
{func, [],
[zip_usage, gz_usage, gz_usage2, compress_usage,
- dictionary_usage, large_deflate, crc, adler]}].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
+ dictionary_usage, large_deflate, crc, adler,
+ only_allow_owner, sub_heap_binaries]},
+ {bench,
+ [inflate_bench_zeroed, inflate_bench_rand,
+ deflate_bench_zeroed, deflate_bench_rand,
+ chunk_bench_zeroed, chunk_bench_rand]}].
%% Test open/0 and close/1.
api_open_close(Config) when is_list(Config) ->
@@ -113,7 +100,7 @@ api_open_close(Config) when is_list(Config) ->
Fd2 = zlib:open(),
?m(false,Fd1 == Fd2),
?m(ok,zlib:close(Fd1)),
- ?m(?BARG, zlib:close(Fd1)),
+ ?m(?EXIT(not_initialized), zlib:close(Fd1)),
?m(ok,zlib:close(Fd2)),
%% Make sure that we don't get any EXIT messages if trap_exit is enabled.
@@ -128,9 +115,11 @@ api_open_close(Config) when is_list(Config) ->
%% Test deflateInit/2 and /6.
api_deflateInit(Config) when is_list(Config) ->
Z1 = zlib:open(),
- ?m(?BARG, zlib:deflateInit(gurka, none)),
- ?m(?BARG, zlib:deflateInit(gurka, gurka)),
- ?m(?BARG, zlib:deflateInit(Z1, gurka)),
+
+ ?m(?EXIT(badarg), zlib:deflateInit(gurka, none)),
+
+ ?m(?EXIT(bad_compression_level), zlib:deflateInit(gurka, gurka)),
+ ?m(?EXIT(bad_compression_level), zlib:deflateInit(Z1, gurka)),
Levels = [none, default, best_speed, best_compression] ++ lists:seq(0,9),
lists:foreach(fun(Level) ->
Z = zlib:open(),
@@ -138,20 +127,30 @@ api_deflateInit(Config) when is_list(Config) ->
?m(ok,zlib:close(Z))
end, Levels),
%% /6
- ?m(?BARG, zlib:deflateInit(Z1,gurka,deflated,-15,8,default)),
-
- ?m(?BARG, zlib:deflateInit(Z1,default,undefined,-15,8,default)),
-
- ?m(?BARG, zlib:deflateInit(Z1,default,deflated,48,8,default)),
- ?m(?BARG, zlib:deflateInit(Z1,default,deflated,-20,8,default)),
- ?m(?BARG, zlib:deflateInit(Z1,default,deflated,-7,8,default)),
- ?m(?BARG, zlib:deflateInit(Z1,default,deflated,7,8,default)),
-
- ?m(?BARG, zlib:deflateInit(Z1,default,deflated,-15,0,default)),
- ?m(?BARG, zlib:deflateInit(Z1,default,deflated,-15,10,default)),
-
- ?m(?BARG, zlib:deflateInit(Z1,default,deflated,-15,8,0)),
- ?m(?BARG, zlib:deflateInit(Z1,default,deflated,-15,8,undefined)),
+ ?m(?EXIT(bad_compression_level),
+ zlib:deflateInit(Z1,gurka,deflated,-15,8,default)),
+
+ ?m(?EXIT(bad_compression_method),
+ zlib:deflateInit(Z1,default,undefined,-15,8,default)),
+
+ ?m(?EXIT(bad_compression_strategy),
+ zlib:deflateInit(Z1,default,deflated,-15,8,0)),
+ ?m(?EXIT(bad_compression_strategy),
+ zlib:deflateInit(Z1,default,deflated,-15,8,undefined)),
+
+ ?m(?EXIT(bad_windowbits),
+ zlib:deflateInit(Z1,default,deflated,48,8,default)),
+ ?m(?EXIT(bad_windowbits),
+ zlib:deflateInit(Z1,default,deflated,-20,8,default)),
+ ?m(?EXIT(bad_windowbits),
+ zlib:deflateInit(Z1,default,deflated,-7,8,default)),
+ ?m(?EXIT(bad_windowbits),
+ zlib:deflateInit(Z1,default,deflated,7,8,default)),
+
+ ?m(?EXIT(bad_memlevel),
+ zlib:deflateInit(Z1,default,deflated,-15,0,default)),
+ ?m(?EXIT(bad_memlevel),
+ zlib:deflateInit(Z1,default,deflated,-15,10,default)),
lists:foreach(fun(Level) ->
Z = zlib:open(),
@@ -167,7 +166,7 @@ api_deflateInit(Config) when is_list(Config) ->
?m(ok, zlib:deflateInit(Z12,default,deflated,-Wbits,8,default)),
?m(ok,zlib:close(Z11)),
?m(ok,zlib:close(Z12))
- end, lists:seq(8, 15)),
+ end, lists:seq(9, 15)),
lists:foreach(fun(MemLevel) ->
Z = zlib:open(),
@@ -183,7 +182,11 @@ api_deflateInit(Config) when is_list(Config) ->
?m(ok,zlib:close(Z))
end, Strategies),
?m(ok, zlib:deflateInit(Z1,default,deflated,-15,8,default)),
- ?m({'EXIT',_}, zlib:deflateInit(Z1,none,deflated,-15,8,default)), %% ??
+
+ %% Let it crash for any reason; we don't care about the order in which the
+ %% parameters are checked.
+ ?m(?EXIT(_), zlib:deflateInit(Z1,none,deflated,-15,8,default)),
+
?m(ok, zlib:close(Z1)).
%% Test deflateSetDictionary.
@@ -192,17 +195,17 @@ api_deflateSetDictionary(Config) when is_list(Config) ->
?m(ok, zlib:deflateInit(Z1, default)),
?m(Id when is_integer(Id), zlib:deflateSetDictionary(Z1, <<1,1,2,3,4,5,1>>)),
?m(Id when is_integer(Id), zlib:deflateSetDictionary(Z1, [1,1,2,3,4,5,1])),
- ?m(?BARG, zlib:deflateSetDictionary(Z1, gurka)),
- ?m(?BARG, zlib:deflateSetDictionary(Z1, 128)),
- ?m(_, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)),
- ?m({'EXIT',{stream_error,_}},zlib:deflateSetDictionary(Z1,<<1,1,2,3,4,5,1>>)),
+ ?m(?EXIT(badarg), zlib:deflateSetDictionary(Z1, gurka)),
+ ?m(?EXIT(badarg), zlib:deflateSetDictionary(Z1, 128)),
+ ?m(L when is_list(L), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)),
+ ?m(?EXIT(stream_error), zlib:deflateSetDictionary(Z1,<<1,1,2,3,4,5,1>>)),
?m(ok, zlib:close(Z1)).
%% Test deflateReset.
api_deflateReset(Config) when is_list(Config) ->
Z1 = zlib:open(),
?m(ok, zlib:deflateInit(Z1, default)),
- ?m(_, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)),
+ ?m(L when is_list(L), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)),
?m(ok, zlib:deflateReset(Z1)),
?m(ok, zlib:deflateReset(Z1)),
%% FIXME how do I make this go wrong??
@@ -210,12 +213,46 @@ api_deflateReset(Config) when is_list(Config) ->
%% Test deflateParams.
api_deflateParams(Config) when is_list(Config) ->
+ Levels = [none, default, best_speed, best_compression] ++ lists:seq(0, 9),
+ Strategies = [filtered, huffman_only, rle, default],
+
Z1 = zlib:open(),
?m(ok, zlib:deflateInit(Z1, default)),
- ?m(_, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)),
- ?m(ok, zlib:deflateParams(Z1, best_compression, huffman_only)),
- ?m(_, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, sync)),
- ?m(ok, zlib:close(Z1)).
+
+ ApiTest =
+ fun(Level, Strategy) ->
+ ?m(ok, zlib:deflateParams(Z1, Level, Strategy)),
+ ?m(ok, zlib:deflateReset(Z1))
+ end,
+
+ [ ApiTest(Level, Strategy) || Level <- Levels, Strategy <- Strategies ],
+
+ ?m(ok, zlib:close(Z1)),
+
+ FlushTest =
+ fun FlushTest(Size, Level, Strategy) ->
+ Z = zlib:open(),
+ ok = zlib:deflateInit(Z, default),
+ Data = gen_determ_rand_bytes(Size),
+ case zlib:deflate(Z, Data, none) of
+ [<<120, 156>>] ->
+ %% All data is present in the internal zlib state, and will
+ %% be flushed on deflateParams.
+
+ ok = zlib:deflateParams(Z, Level, Strategy),
+ Compressed = [<<120, 156>>, zlib:deflate(Z, <<>>, finish)],
+ Data = zlib:uncompress(Compressed),
+ zlib:close(Z),
+
+ FlushTest(Size + (1 bsl 10), Level, Strategy);
+ _Other ->
+ ok
+ end
+ end,
+
+ [ FlushTest(1, Level, Strategy) || Level <- Levels, Strategy <- Strategies ],
+
+ ok.
%% Test deflate.
api_deflate(Config) when is_list(Config) ->
@@ -231,11 +268,13 @@ api_deflate(Config) when is_list(Config) ->
?m(B when is_list(B), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, full)),
?m(B when is_list(B), zlib:deflate(Z1, <<>>, finish)),
- ?m(?BARG, zlib:deflate(gurka, <<1,1,1,1,1,1,1,1,1>>, full)),
- ?m(?BARG, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, asdj)),
- ?m(?BARG, zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, 198)),
+ ?m(?EXIT(badarg), zlib:deflate(gurka, <<1,1,1,1,1,1,1,1,1>>, full)),
+
+ ?m(?EXIT(bad_flush_mode), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, asdj)),
+ ?m(?EXIT(bad_flush_mode), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, 198)),
+
%% Causes problems ERROR REPORT
- ?m(?BARG, zlib:deflate(Z1, [asdj,asd], none)),
+ ?m(?EXIT(badarg), zlib:deflate(Z1, [asdj,asd], none)),
?m(ok, zlib:close(Z1)).
@@ -244,11 +283,11 @@ api_deflateEnd(Config) when is_list(Config) ->
Z1 = zlib:open(),
?m(ok, zlib:deflateInit(Z1, default)),
?m(ok, zlib:deflateEnd(Z1)),
- ?m({'EXIT', {einval,_}}, zlib:deflateEnd(Z1)), %% ??
- ?m(?BARG, zlib:deflateEnd(gurka)),
+ ?m(?EXIT(not_initialized), zlib:deflateEnd(Z1)),
+ ?m(?EXIT(badarg), zlib:deflateEnd(gurka)),
?m(ok, zlib:deflateInit(Z1, default)),
?m(B when is_list(B), zlib:deflate(Z1, <<"Kilroy was here">>)),
- ?m({'EXIT', {data_error,_}}, zlib:deflateEnd(Z1)),
+ ?m(?EXIT(data_error), zlib:deflateEnd(Z1)),
?m(ok, zlib:deflateInit(Z1, default)),
?m(B when is_list(B), zlib:deflate(Z1, <<"Kilroy was here">>)),
?m(B when is_list(B), zlib:deflate(Z1, <<"Kilroy was here">>, finish)),
@@ -259,9 +298,9 @@ api_deflateEnd(Config) when is_list(Config) ->
%% Test inflateInit /1 and /2.
api_inflateInit(Config) when is_list(Config) ->
Z1 = zlib:open(),
- ?m(?BARG, zlib:inflateInit(gurka)),
+ ?m(?EXIT(badarg), zlib:inflateInit(gurka)),
?m(ok, zlib:inflateInit(Z1)),
- ?m({'EXIT',{einval,_}}, zlib:inflateInit(Z1, 15)), %% ??
+ ?m(?EXIT(already_initialized), zlib:inflateInit(Z1, 15)),
lists:foreach(fun(Wbits) ->
Z11 = zlib:open(),
?m(ok, zlib:inflateInit(Z11,Wbits)),
@@ -270,33 +309,34 @@ api_inflateInit(Config) when is_list(Config) ->
?m(ok,zlib:close(Z11)),
?m(ok,zlib:close(Z12))
end, lists:seq(8,15)),
- ?m(?BARG, zlib:inflateInit(gurka, -15)),
- ?m(?BARG, zlib:inflateInit(Z1, 7)),
- ?m(?BARG, zlib:inflateInit(Z1, -7)),
- ?m(?BARG, zlib:inflateInit(Z1, 48)),
- ?m(?BARG, zlib:inflateInit(Z1, -16)),
+ ?m(?EXIT(badarg), zlib:inflateInit(gurka, -15)),
+ ?m(?EXIT(bad_windowbits), zlib:inflateInit(Z1, 7)),
+ ?m(?EXIT(bad_windowbits), zlib:inflateInit(Z1, -7)),
+ ?m(?EXIT(bad_windowbits), zlib:inflateInit(Z1, 48)),
+ ?m(?EXIT(bad_windowbits), zlib:inflateInit(Z1, -16)),
?m(ok, zlib:close(Z1)).
%% Test inflateSetDictionary.
api_inflateSetDictionary(Config) when is_list(Config) ->
Z1 = zlib:open(),
?m(ok, zlib:inflateInit(Z1)),
- ?m(?BARG, zlib:inflateSetDictionary(gurka,<<1,1,1,1,1>>)),
- ?m(?BARG, zlib:inflateSetDictionary(Z1,102)),
- ?m(?BARG, zlib:inflateSetDictionary(Z1,gurka)),
+ ?m(?EXIT(badarg), zlib:inflateSetDictionary(gurka,<<1,1,1,1,1>>)),
+ ?m(?EXIT(badarg), zlib:inflateSetDictionary(Z1,102)),
+ ?m(?EXIT(badarg), zlib:inflateSetDictionary(Z1,gurka)),
Dict = <<1,1,1,1,1>>,
- ?m({'EXIT',{stream_error,_}}, zlib:inflateSetDictionary(Z1,Dict)),
+ ?m(?EXIT(stream_error), zlib:inflateSetDictionary(Z1,Dict)),
?m(ok, zlib:close(Z1)).
%% Test inflateGetDictionary.
api_inflateGetDictionary(Config) when is_list(Config) ->
Z1 = zlib:open(),
+ zlib:inflateInit(Z1),
IsOperationSupported =
case catch zlib:inflateGetDictionary(Z1) of
- {'EXIT',{einval,_}} -> true;
- {'EXIT',{enotsup,_}} -> false
+ ?EXIT(not_supported) -> false;
+ _ -> true
end,
- _ = zlib:close(Z1),
+ zlib:close(Z1),
api_inflateGetDictionary_if_supported(IsOperationSupported).
api_inflateGetDictionary_if_supported(false) ->
@@ -306,64 +346,53 @@ api_inflateGetDictionary_if_supported(true) ->
Z1 = zlib:open(),
?m(ok, zlib:deflateInit(Z1)),
Dict = <<"foobar barfoo foo bar far boo">>,
- ?m(_, zlib:deflateSetDictionary(Z1, Dict)),
+ Checksum = zlib:deflateSetDictionary(Z1, Dict),
Payload = <<"foobarbarbar">>,
Compressed = zlib:deflate(Z1, Payload, finish),
?m(ok, zlib:close(Z1)),
- % Decompress and test dictionary extraction
+ % Decompress and test dictionary extraction with inflate/2
Z2 = zlib:open(),
?m(ok, zlib:inflateInit(Z2)),
?m(<<>>, iolist_to_binary(zlib:inflateGetDictionary(Z2))),
- ?m({'EXIT',{stream_error,_}}, zlib:inflateSetDictionary(Z2, Dict)),
- ?m({'EXIT',{{need_dictionary,_},_}}, zlib:inflate(Z2, Compressed)),
+ ?m(?EXIT(stream_error), zlib:inflateSetDictionary(Z2, Dict)),
+ ?m(?EXIT({need_dictionary,Checksum}), zlib:inflate(Z2, Compressed)),
?m(ok, zlib:inflateSetDictionary(Z2, Dict)),
?m(Dict, iolist_to_binary(zlib:inflateGetDictionary(Z2))),
- ?m(Payload, iolist_to_binary(zlib:inflate(Z2, Compressed))),
+ Payload = iolist_to_binary(zlib:inflate(Z2, [])),
?m(ok, zlib:close(Z2)),
- ?m(?BARG, zlib:inflateSetDictionary(Z2, Dict)),
- ok.
+ ?m(?EXIT(not_initialized), zlib:inflateSetDictionary(Z2, Dict)),
-%% Test inflateSync.
-api_inflateSync(Config) when is_list(Config) ->
- {skip,"inflateSync/1 sucks"}.
-%% Z1 = zlib:open(),
-%% ?m(ok, zlib:deflateInit(Z1)),
-%% B1list0 = zlib:deflate(Z1, "gurkan gurra ger galna tunnor", full),
-%% B2 = zlib:deflate(Z1, "grodan boll", finish),
-%% io:format("~p\n", [B1list0]),
-%% io:format("~p\n", [B2]),
-%% ?m(ok, zlib:deflateEnd(Z1)),
-%% B1 = clobber(14, list_to_binary(B1list0)),
-%% Compressed = list_to_binary([B1,B2]),
-%% io:format("~p\n", [Compressed]),
-
-%% ?m(ok, zlib:inflateInit(Z1)),
-%% ?m(?BARG, zlib:inflateSync(gurka)),
-%% ?m({'EXIT',{data_error,_}}, zlib:inflate(Z1, Compressed)),
-%% ?m(ok, zlib:inflateSync(Z1)),
-%% Ubs = zlib:inflate(Z1, []),
-%% <<"grodan boll">> = list_to_binary(Ubs),
-%% ?m(ok, zlib:close(Z1)).
-
-clobber(N, Bin) when is_binary(Bin) ->
- T = list_to_tuple(binary_to_list(Bin)),
- Byte = case element(N, T) of
- 255 -> 254;
- B -> B+1
- end,
- list_to_binary(tuple_to_list(setelement(N, T, Byte))).
+ %% ... And do the same for inflate/3
+ Z3 = zlib:open(),
+ ?m(ok, zlib:inflateInit(Z3)),
+ ?m(<<>>, iolist_to_binary(zlib:inflateGetDictionary(Z3))),
+ ?m(?EXIT(stream_error), zlib:inflateSetDictionary(Z3, Dict)),
+
+ {need_dictionary, Checksum, _Output = []} =
+ zlib:inflate(Z3, Compressed, [{exception_on_need_dict, false}]),
+
+ ?m(ok, zlib:inflateSetDictionary(Z3, Dict)),
+ ?m(Dict, iolist_to_binary(zlib:inflateGetDictionary(Z3))),
+
+ Payload = iolist_to_binary(
+ zlib:inflate(Z3, [], [{exception_on_need_dict, false}])),
+
+ ?m(ok, zlib:close(Z3)),
+ ?m(?EXIT(not_initialized), zlib:inflateSetDictionary(Z3, Dict)),
+
+ ok.
%% Test inflateReset.
api_inflateReset(Config) when is_list(Config) ->
Z1 = zlib:open(),
?m(ok, zlib:inflateInit(Z1)),
- ?m(?BARG, zlib:inflateReset(gurka)),
+ ?m(?EXIT(badarg), zlib:inflateReset(gurka)),
?m(ok, zlib:inflateReset(Z1)),
?m(ok, zlib:close(Z1)).
-%% Test inflate.
-api_inflate(Config) when is_list(Config) ->
+%% Test inflate/2
+api_inflate2(Config) when is_list(Config) ->
Data = [<<1,2,2,3,3,3,4,4,4,4>>],
Compressed = zlib:compress(Data),
Z1 = zlib:open(),
@@ -373,12 +402,32 @@ api_inflate(Config) when is_list(Config) ->
?m(ok, zlib:inflateEnd(Z1)),
?m(ok, zlib:inflateInit(Z1)),
?m(Data, zlib:inflate(Z1, Compressed)),
- ?m(?BARG, zlib:inflate(gurka, Compressed)),
- ?m(?BARG, zlib:inflate(Z1, 4384)),
- ?m(?BARG, zlib:inflate(Z1, [atom_list])),
+ ?m(?EXIT(badarg), zlib:inflate(gurka, Compressed)),
+ ?m(?EXIT(badarg), zlib:inflate(Z1, 4384)),
+ ?m(?EXIT(badarg), zlib:inflate(Z1, [atom_list])),
?m(ok, zlib:inflateEnd(Z1)),
?m(ok, zlib:inflateInit(Z1)),
- ?m({'EXIT',{data_error,_}}, zlib:inflate(Z1, <<2,1,2,1,2>>)),
+ ?m(?EXIT(data_error), zlib:inflate(Z1, <<2,1,2,1,2>>)),
+ ?m(ok, zlib:close(Z1)).
+
+%% Test inflate/3; same as inflate/2 but with the default options inverted.
+api_inflate3(Config) when is_list(Config) ->
+ Data = [<<1,2,2,3,3,3,4,4,4,4>>],
+ Options = [{exception_on_need_dict, false}],
+ Compressed = zlib:compress(Data),
+ Z1 = zlib:open(),
+ ?m(ok, zlib:inflateInit(Z1)),
+ ?m([], zlib:inflate(Z1, <<>>, Options)),
+ ?m(Data, zlib:inflate(Z1, Compressed)),
+ ?m(ok, zlib:inflateEnd(Z1)),
+ ?m(ok, zlib:inflateInit(Z1)),
+ ?m(Data, zlib:inflate(Z1, Compressed, Options)),
+ ?m(?EXIT(badarg), zlib:inflate(gurka, Compressed, Options)),
+ ?m(?EXIT(badarg), zlib:inflate(Z1, 4384, Options)),
+ ?m(?EXIT(badarg), zlib:inflate(Z1, [atom_list], Options)),
+ ?m(ok, zlib:inflateEnd(Z1)),
+ ?m(ok, zlib:inflateInit(Z1)),
+ ?m(?EXIT(data_error), zlib:inflate(Z1, <<2,1,2,1,2>>, Options)),
?m(ok, zlib:close(Z1)).
%% Test inflateChunk.
@@ -388,69 +437,109 @@ api_inflateChunk(Config) when is_list(Config) ->
Part1 = binary:part(Data, 0, ChunkSize),
Part2 = binary:part(Data, ChunkSize, ChunkSize),
Part3 = binary:part(Data, ChunkSize * 2, ChunkSize),
+
Compressed = zlib:compress(Data),
Z1 = zlib:open(),
+
zlib:setBufSize(Z1, ChunkSize),
+
?m(ok, zlib:inflateInit(Z1)),
- ?m([], zlib:inflateChunk(Z1, <<>>)),
- ?m({more, Part1}, zlib:inflateChunk(Z1, Compressed)),
- ?m({more, Part2}, zlib:inflateChunk(Z1)),
- ?m(Part3, zlib:inflateChunk(Z1)),
- ?m(ok, zlib:inflateEnd(Z1)),
+ 0 = iolist_size(zlib:inflateChunk(Z1, <<>>)),
+
+ {more, Part1AsIOList} = zlib:inflateChunk(Z1, Compressed),
+ {more, Part2AsIOList} = zlib:inflateChunk(Z1),
+ {more, Part3AsIOList} = zlib:inflateChunk(Z1),
+
+ [] = zlib:inflateChunk(Z1),
+ [] = zlib:inflateChunk(Z1),
+ [] = zlib:inflateChunk(Z1),
+
+ ?m(Part1, iolist_to_binary(Part1AsIOList)),
+ ?m(Part2, iolist_to_binary(Part2AsIOList)),
+ ?m(Part3, iolist_to_binary(Part3AsIOList)),
+
+ ?m(ok, zlib:inflateEnd(Z1)),
?m(ok, zlib:inflateInit(Z1)),
- ?m({more, Part1}, zlib:inflateChunk(Z1, Compressed)),
+
+ ?m({more, Part1AsIOList}, zlib:inflateChunk(Z1, Compressed)),
?m(ok, zlib:inflateReset(Z1)),
- zlib:setBufSize(Z1, size(Data)),
- ?m(Data, zlib:inflateChunk(Z1, Compressed)),
- ?m(ok, zlib:inflateEnd(Z1)),
+ zlib:setBufSize(Z1, byte_size(Data) + 1),
+
+ DataAsIOList = zlib:inflateChunk(Z1, Compressed),
+ ?m(Data, iolist_to_binary(DataAsIOList)),
+ ?m(ok, zlib:inflateEnd(Z1)),
?m(ok, zlib:inflateInit(Z1)),
- ?m(?BARG, zlib:inflateChunk(gurka, Compressed)),
- ?m(?BARG, zlib:inflateChunk(Z1, 4384)),
- ?m({'EXIT',{data_error,_}}, zlib:inflateEnd(Z1)),
+
+ ?m(?EXIT(badarg), zlib:inflateChunk(gurka, Compressed)),
+ ?m(?EXIT(badarg), zlib:inflateChunk(Z1, 4384)),
+
+ ?m(?EXIT(data_error), zlib:inflateEnd(Z1)),
+
?m(ok, zlib:close(Z1)).
-%% Test inflateEnd.
-api_inflateEnd(Config) when is_list(Config) ->
+%% Test safeInflate as a mirror of inflateChunk, but ignore the stuff about
+%% exact chunk sizes.
+api_safeInflate(Config) when is_list(Config) ->
+ Data = << <<(I rem 150)>> || I <- lists:seq(1, 20 bsl 10) >>,
+ Compressed = zlib:compress(Data),
Z1 = zlib:open(),
- ?m({'EXIT',{einval,_}}, zlib:inflateEnd(Z1)),
- ?m(ok, zlib:inflateInit(Z1)),
- ?m(?BARG, zlib:inflateEnd(gurka)),
- ?m({'EXIT',{data_error,_}}, zlib:inflateEnd(Z1)),
- ?m({'EXIT',{einval,_}}, zlib:inflateEnd(Z1)),
+
?m(ok, zlib:inflateInit(Z1)),
- ?m(B when is_list(B), zlib:inflate(Z1, zlib:compress("abc"))),
+
+ SafeInflateLoop =
+ fun
+ Loop({continue, Chunk}, Output) ->
+ Loop(zlib:safeInflate(Z1, []), [Output, Chunk]);
+ Loop({finished, Chunk}, Output) ->
+ [Output, Chunk]
+ end,
+
+ Decompressed = SafeInflateLoop(zlib:safeInflate(Z1, Compressed), []),
+ Data = iolist_to_binary(Decompressed),
+
?m(ok, zlib:inflateEnd(Z1)),
- ?m(ok, zlib:close(Z1)).
+ ?m(ok, zlib:inflateInit(Z1)),
-%% Test getBufsz.
-api_getBufsz(Config) when is_list(Config) ->
- Z1 = zlib:open(),
- ?m(Val when is_integer(Val), zlib:getBufSize(Z1)),
- ?m(?BARG, zlib:getBufSize(gurka)),
- ?m(ok, zlib:close(Z1)).
+ {continue, Partial} = zlib:safeInflate(Z1, Compressed),
+ PBin = iolist_to_binary(Partial),
+ PSize = byte_size(PBin),
+ <<PBin:PSize/binary, Rest/binary>> = Data,
-%% Test setBufsz.
-api_setBufsz(Config) when is_list(Config) ->
- Z1 = zlib:open(),
- ?m(?BARG, zlib:setBufSize(Z1, gurka)),
- ?m(?BARG, zlib:setBufSize(gurka, 1232330)),
- Sz = ?m( Val when is_integer(Val), zlib:getBufSize(Z1)),
- ?m(ok, zlib:setBufSize(Z1, Sz*2)),
- DSz = Sz*2,
- ?m(DSz, zlib:getBufSize(Z1)),
+ ?m(ok, zlib:inflateReset(Z1)),
+
+ {continue, Partial} = zlib:safeInflate(Z1, Compressed),
+ PBin = iolist_to_binary(Partial),
+ PSize = byte_size(PBin),
+ <<PBin:PSize/binary, Rest/binary>> = Data,
+
+ ?m(ok, zlib:inflateReset(Z1)),
+
+ SafeInflateLoop(zlib:safeInflate(Z1, Compressed), []),
+
+ ?m({finished, []}, zlib:safeInflate(Z1, Compressed)),
+ ?m({finished, []}, zlib:safeInflate(Z1, Compressed)),
+
+ ?m(ok, zlib:inflateReset(Z1)),
+ ?m(?EXIT(badarg), zlib:safeInflate(gurka, Compressed)),
+ ?m(?EXIT(badarg), zlib:safeInflate(Z1, 4384)),
+ ?m(?EXIT(data_error), zlib:inflateEnd(Z1)),
?m(ok, zlib:close(Z1)).
-%%% Debug function ??
-%% Test getQSize.
-api_getQSize(Config) when is_list(Config) ->
+%% Test inflateEnd.
+api_inflateEnd(Config) when is_list(Config) ->
Z1 = zlib:open(),
- Q = ?m(Val when is_integer(Val), zlib:getQSize(Z1)),
- io:format("QSize ~p ~n", [Q]),
- ?m(?BARG, zlib:getQSize(gurka)),
+ ?m(?EXIT(not_initialized), zlib:inflateEnd(Z1)),
+ ?m(ok, zlib:inflateInit(Z1)),
+ ?m(?EXIT(badarg), zlib:inflateEnd(gurka)),
+ ?m(?EXIT(data_error), zlib:inflateEnd(Z1)),
+ ?m(?EXIT(not_initialized), zlib:inflateEnd(Z1)),
+ ?m(ok, zlib:inflateInit(Z1)),
+ ?m(B when is_list(B), zlib:inflate(Z1, zlib:compress("abc"))),
+ ?m(ok, zlib:inflateEnd(Z1)),
?m(ok, zlib:close(Z1)).
%% Test crc32.
@@ -458,8 +547,8 @@ api_crc32(Config) when is_list(Config) ->
Z1 = zlib:open(),
?m(ok, zlib:deflateInit(Z1,best_speed,deflated,-15,8,default)),
Bin = <<1,1,1,1,1,1,1,1,1>>,
- Compressed1 = ?m(_, zlib:deflate(Z1, Bin, none)),
- Compressed2 = ?m(_, zlib:deflate(Z1, <<>>, finish)),
+ Compressed1 = ?m(L when is_list(L), zlib:deflate(Z1, Bin, none)),
+ Compressed2 = ?m(L when is_list(L), zlib:deflate(Z1, <<>>, finish)),
Compressed = list_to_binary(Compressed1 ++ Compressed2),
CRC1 = ?m( CRC1 when is_integer(CRC1), zlib:crc32(Z1)),
?m(CRC1 when is_integer(CRC1), zlib:crc32(Z1,Bin)),
@@ -467,15 +556,15 @@ api_crc32(Config) when is_list(Config) ->
?m(CRC2 when is_integer(CRC2), zlib:crc32(Z1,Compressed)),
CRC2 = ?m(CRC2 when is_integer(CRC2), zlib:crc32(Z1,0,Compressed)),
?m(CRC3 when CRC2 /= CRC3, zlib:crc32(Z1,234,Compressed)),
- ?m(?BARG, zlib:crc32(gurka)),
- ?m(?BARG, zlib:crc32(Z1, not_a_binary)),
- ?m(?BARG, zlib:crc32(gurka, <<1,1,2,4,4>>)),
- ?m(?BARG, zlib:crc32(Z1, 2298929, not_a_binary)),
- ?m(?BARG, zlib:crc32(Z1, not_an_int, <<123,123,123,35,231>>)),
- ?m(?BARG, zlib:crc32_combine(Z1, not_an_int, 123123, 123)),
- ?m(?BARG, zlib:crc32_combine(Z1, noint, 123123, 123)),
- ?m(?BARG, zlib:crc32_combine(Z1, 123123, noint, 123)),
- ?m(?BARG, zlib:crc32_combine(Z1, 123123, 123, noint)),
+ ?m(?EXIT(badarg), zlib:crc32(gurka)),
+ ?m(?EXIT(badarg), zlib:crc32(Z1, not_a_binary)),
+ ?m(?EXIT(badarg), zlib:crc32(gurka, <<1,1,2,4,4>>)),
+ ?m(?EXIT(badarg), zlib:crc32(Z1, 2298929, not_a_binary)),
+ ?m(?EXIT(badarg), zlib:crc32(Z1, not_an_int, <<123,123,123,35,231>>)),
+ ?m(?EXIT(badarg), zlib:crc32_combine(Z1, not_an_int, 123123, 123)),
+ ?m(?EXIT(badarg), zlib:crc32_combine(Z1, noint, 123123, 123)),
+ ?m(?EXIT(badarg), zlib:crc32_combine(Z1, 123123, noint, 123)),
+ ?m(?EXIT(badarg), zlib:crc32_combine(Z1, 123123, 123, noint)),
?m(ok, zlib:deflateEnd(Z1)),
?m(ok, zlib:close(Z1)).
@@ -484,74 +573,129 @@ api_adler32(Config) when is_list(Config) ->
Z1 = zlib:open(),
?m(ok, zlib:deflateInit(Z1,best_speed,deflated,-15,8,default)),
Bin = <<1,1,1,1,1,1,1,1,1>>,
- Compressed1 = ?m(_, zlib:deflate(Z1, Bin, none)),
- Compressed2 = ?m(_, zlib:deflate(Z1, <<>>, finish)),
+ Compressed1 = ?m(L when is_list(L), zlib:deflate(Z1, Bin, none)),
+ Compressed2 = ?m(L when is_list(L), zlib:deflate(Z1, <<>>, finish)),
Compressed = list_to_binary(Compressed1 ++ Compressed2),
?m(ADLER1 when is_integer(ADLER1), zlib:adler32(Z1,Bin)),
?m(ADLER1 when is_integer(ADLER1), zlib:adler32(Z1,binary_to_list(Bin))),
ADLER2 = ?m(ADLER2 when is_integer(ADLER2), zlib:adler32(Z1,Compressed)),
?m(ADLER2 when is_integer(ADLER2), zlib:adler32(Z1,1,Compressed)),
?m(ADLER3 when ADLER2 /= ADLER3, zlib:adler32(Z1,234,Compressed)),
- ?m(?BARG, zlib:adler32(Z1, not_a_binary)),
- ?m(?BARG, zlib:adler32(gurka, <<1,1,2,4,4>>)),
- ?m(?BARG, zlib:adler32(Z1, 2298929, not_a_binary)),
- ?m(?BARG, zlib:adler32(Z1, not_an_int, <<123,123,123,35,231>>)),
- ?m(?BARG, zlib:adler32_combine(Z1, noint, 123123, 123)),
- ?m(?BARG, zlib:adler32_combine(Z1, 123123, noint, 123)),
- ?m(?BARG, zlib:adler32_combine(Z1, 123123, 123, noint)),
+ ?m(?EXIT(badarg), zlib:adler32(Z1, not_a_binary)),
+ ?m(?EXIT(badarg), zlib:adler32(gurka, <<1,1,2,4,4>>)),
+ ?m(?EXIT(badarg), zlib:adler32(Z1, 2298929, not_a_binary)),
+ ?m(?EXIT(badarg), zlib:adler32(Z1, not_an_int, <<123,123,123,35,231>>)),
+ ?m(?EXIT(badarg), zlib:adler32_combine(Z1, noint, 123123, 123)),
+ ?m(?EXIT(badarg), zlib:adler32_combine(Z1, 123123, noint, 123)),
+ ?m(?EXIT(badarg), zlib:adler32_combine(Z1, 123123, 123, noint)),
?m(ok, zlib:deflateEnd(Z1)),
?m(ok, zlib:close(Z1)).
%% Test compress.
api_un_compress(Config) when is_list(Config) ->
- ?m(?BARG,zlib:compress(not_a_binary)),
+ ?m(?EXIT(badarg),zlib:compress(not_a_binary)),
Bin = <<1,11,1,23,45>>,
Comp = zlib:compress(Bin),
- ?m(?BARG,zlib:uncompress(not_a_binary)),
- ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<171,171,171,171,171>>)),
- ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<>>)),
- ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<120>>)),
- ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<120,156>>)),
- ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<120,156,3>>)),
- ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<120,156,3,0>>)),
- ?m({'EXIT',{data_error,_}}, zlib:uncompress(<<0,156,3,0,0,0,0,1>>)),
+ ?m(?EXIT(badarg),zlib:uncompress(not_a_binary)),
+ ?m(?EXIT(data_error), zlib:uncompress(<<171,171,171,171,171>>)),
+ ?m(?EXIT(data_error), zlib:uncompress(<<>>)),
+ ?m(?EXIT(data_error), zlib:uncompress(<<120>>)),
+ ?m(?EXIT(data_error), zlib:uncompress(<<120,156>>)),
+ ?m(?EXIT(data_error), zlib:uncompress(<<120,156,3>>)),
+ ?m(?EXIT(data_error), zlib:uncompress(<<120,156,3,0>>)),
+ ?m(?EXIT(data_error), zlib:uncompress(<<0,156,3,0,0,0,0,1>>)),
?m(Bin, zlib:uncompress(binary_to_list(Comp))),
?m(Bin, zlib:uncompress(Comp)).
%% Test zip.
api_un_zip(Config) when is_list(Config) ->
- ?m(?BARG,zlib:zip(not_a_binary)),
+ ?m(?EXIT(badarg),zlib:zip(not_a_binary)),
Bin = <<1,11,1,23,45>>,
Comp = zlib:zip(Bin),
?m(Comp, zlib:zip(binary_to_list(Bin))),
- ?m(?BARG,zlib:unzip(not_a_binary)),
- ?m({'EXIT',{data_error,_}}, zlib:unzip(<<171,171,171,171,171>>)),
- ?m({'EXIT',{data_error,_}}, zlib:unzip(<<>>)),
+ ?m(?EXIT(badarg),zlib:unzip(not_a_binary)),
+ ?m(?EXIT(data_error), zlib:unzip(<<171,171,171,171,171>>)),
+ ?m(?EXIT(data_error), zlib:unzip(<<>>)),
?m(Bin, zlib:unzip(Comp)),
?m(Bin, zlib:unzip(binary_to_list(Comp))),
%% OTP-6396
- B = <<131,104,19,100,0,13,99,95,99,105,100,95,99,115,103,115,110,95,50,97,1,107,0,4,208,161,246,29,107,0,3,237,166,224,107,0,6,66,240,153,0,2,10,1,0,8,97,116,116,97,99,104,101,100,104,2,100,0,22,117,112,100,97,116,101,95,112,100,112,95,99,111,110,116,101,120,116,95,114,101,113,107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,12,3,197,31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,104,116,73,64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,5,0,33,4,4,10,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,1,114,45,97,112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,50,52,48,4,103,112,114,115,8,0,104,2,104,2,100,0,8,97,99,116,105,118,97,116,101,104,23,100,0,11,112,100,112,95,99,111,110,116,1,120,116,100,0,7,112,114,105,109,97,114,121,97,1,100,0,9,117,110,100,101,102,105,110,101,100,97,1,97,4,97,4,97,7,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,10100,100,0,9,117,110,100,101,102,105,110,101,100,100,0,5,102,97,108,115,101,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,1,101,100,97,0,100,0,9,117,110,100,101,102,105,110,101,100,107,0,4,16,0,1,144,107,0,4,61,139,186,181,107,0,4,10,8,201,49,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,0,101,100,100,0,9,117,110,100,101,102,105,110,101,100,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,21,106,108,0,0,0,3,104,2,97,1,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,167,20,104,2,97,4,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,21,104,2,97,10,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,16,97,26,106,100,0,5,118,101,114,57,57,100,0,9,117,110,0,101,102,105,110,101,100,107,0,2,0,244,107,0,4,10,6,102,195,107,0,4,10,6,102,195,100,0,9,117,110,100,101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,107,0,125,248,143,0,203,25115,157,116,65,185,65,172,55,87,164,88,225,50,203,251,115,157,116,65,185,65,172,55,87,164,88,225,50,0,0,82,153,50,0,200,98,87,148,237,193,185,65,149,167,69,144,14,16,153,50,3,81,70,94,13,109,193,1,120,5,181,113,198,118,50,3,81,70,94,13,109,193,185,120,5,181,113,198,118,153,3,81,70,94,13,109,193,185,120,5,181,113,198,118,153,50,16,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,113,92,2,119,128,0,0,108,0,0,1,107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,12,3,11,97,31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,104,116,73,64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,0,33,4,4,10,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,101,114,45,97,112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,50,52,48,4,103,112,114,115,8,0,106>>,
+ B =
+ <<131,104,19,100,0,13,99,95,99,105,100,95,99,115,103,115,110,95,50,97,
+ 1,107,0,4,208,161,246,29,107,0,3,237,166,224,107,0,6,66,240,153,0,2,
+ 10,1,0,8,97,116,116,97,99,104,101,100,104,2,100,0,22,117,112,100,97,
+ 116,101,95,112,100,112,95,99,111,110,116,101,120,116,95,114,101,113,
+ 107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,12,3,197,
+ 31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,104,116,73,
+ 64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,5,0,33,4,4,10
+ ,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,1,114,45,97,
+ 112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,50,52,48,4,
+ 103,112,114,115,8,0,104,2,104,2,100,0,8,97,99,116,105,118,97,116,101,
+ 104,23,100,0,11,112,100,112,95,99,111,110,116,1,120,116,100,0,7,112,
+ 114,105,109,97,114,121,97,1,100,0,9,117,110,100,101,102,105,110,101,
+ 100,97,1,97,4,97,4,97,7,100,0,9,117,110,100,101,102,105,110,101,100,
+ 100,0,9,117,110,100,101,102,105,110,10100,100,0,9,117,110,100,101,
+ 102,105,110,101,100,100,0,5,102,97,108,115,101,100,0,9,117,110,100,
+ 101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,
+ 100,0,9,117,110,100,101,102,105,1,101,100,97,0,100,0,9,117,110,100,
+ 101,102,105,110,101,100,107,0,4,16,0,1,144,107,0,4,61,139,186,181,
+ 107,0,4,10,8,201,49,100,0,9,117,110,100,101,102,105,110,101,100,100,
+ 0,9,117,110,100,101,102,105,0,101,100,100,0,9,117,110,100,101,102,
+ 105,110,101,100,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97,
+ 16,97,21,106,108,0,0,0,3,104,2,97,1,104,2,104,3,98,0,0,7,214,97,11,
+ 97,20,104,3,97,17,97,167,20,104,2,97,4,104,2,104,3,98,0,0,7,214,97,
+ 11,97,20,104,3,97,17,97,16,97,21,104,2,97,10,104,2,104,3,98,0,0,7,
+ 214,97,11,97,20,104,3,97,17,97,16,97,26,106,100,0,5,118,101,114,57,
+ 57,100,0,9,117,110,0,101,102,105,110,101,100,107,0,2,0,244,107,0,4,
+ 10,6,102,195,107,0,4,10,6,102,195,100,0,9,117,110,100,101,102,105,
+ 110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,107,0,125,
+ 248,143,0,203,25115,157,116,65,185,65,172,55,87,164,88,225,50,203,
+ 251,115,157,116,65,185,65,172,55,87,164,88,225,50,0,0,82,153,50,0,
+ 200,98,87,148,237,193,185,65,149,167,69,144,14,16,153,50,3,81,70,94,
+ 13,109,193,1,120,5,181,113,198,118,50,3,81,70,94,13,109,193,185,120,
+ 5,181,113,198,118,153,3,81,70,94,13,109,193,185,120,5,181,113,198,
+ 118,153,50,16,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,113,92,2,119,128,0,0,
+ 108,0,0,1,107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,
+ 12,3,11,97,31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,
+ 104,116,73,64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,0,
+ 33,4,4,10,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,101,
+ 114,45,97,112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,
+ 50,52,48,4,103,112,114,115,8,0,106>>,
+
Z = zlib:zip(B),
?m(B, zlib:unzip(Z)).
%% Test gunzip.
api_g_un_zip(Config) when is_list(Config) ->
- ?m(?BARG,zlib:gzip(not_a_binary)),
+ ?m(?EXIT(badarg),zlib:gzip(not_a_binary)),
Bin = <<1,11,1,23,45>>,
Comp = zlib:gzip(Bin),
+
?m(Comp, zlib:gzip(binary_to_list(Bin))),
- ?m(?BARG, zlib:gunzip(not_a_binary)),
- ?m(?DATA_ERROR, zlib:gunzip(<<171,171,171,171,171>>)),
- ?m(?DATA_ERROR, zlib:gunzip(<<>>)),
+ ?m(?EXIT(badarg), zlib:gunzip(not_a_binary)),
+ ?m(?EXIT(data_error), zlib:gunzip(<<171,171,171,171,171>>)),
+ ?m(?EXIT(data_error), zlib:gunzip(<<>>)),
?m(Bin, zlib:gunzip(Comp)),
?m(Bin, zlib:gunzip(binary_to_list(Comp))),
+ %% RFC 1952:
+ %%
+ %% "A gzip file consists of a series of "members" (compressed data
+ %% sets). [...] The members simply appear one after another in the file,
+ %% with no additional information before, between, or after them."
+ Concatenated = <<Bin/binary, Bin/binary>>,
+ ?m(Concatenated, zlib:gunzip([Comp, Comp])),
+
+ %% Don't explode if the uncompressed size is a perfect multiple of the
+ %% internal inflate chunk size.
+ ChunkSizedData = <<0:16384/unit:8>>,
+ ?m(ChunkSizedData, zlib:gunzip(zlib:gzip(ChunkSizedData))),
+
%% Bad CRC; bad length.
BadCrc = bad_crc_data(),
- ?m({'EXIT',{data_error,_}},(catch zlib:gunzip(BadCrc))),
+ ?m(?EXIT(data_error),(catch zlib:gunzip(BadCrc))),
BadLen = bad_len_data(),
- ?m({'EXIT',{data_error,_}},(catch zlib:gunzip(BadLen))),
+ ?m(?EXIT(data_error),(catch zlib:gunzip(BadLen))),
ok.
bad_crc_data() ->
@@ -594,30 +738,15 @@ intro(Config) when is_list(Config) ->
large_deflate(Config) when is_list(Config) ->
large_deflate_do().
large_deflate_do() ->
- Z = zlib:open(),
- Plain = rand_bytes(zlib:getBufSize(Z)*5),
- ok = zlib:deflateInit(Z),
- _ZlibHeader = zlib:deflate(Z, [], full),
- Deflated = zlib:deflate(Z, Plain, full),
- ?m(ok, zlib:close(Z)),
- ?m(Plain, zlib:unzip(list_to_binary([Deflated, 3, 0]))).
-
-rand_bytes(Sz) ->
- L = <<8,2,3,6,1,2,3,2,3,4,8,7,3,7,2,3,4,7,5,8,9,3>>,
- rand_bytes(erlang:md5(L),Sz).
-
-rand_bytes(Bin, Sz) when byte_size(Bin) >= Sz ->
- <<Res:Sz/binary, _/binary>> = Bin,
- Res;
-rand_bytes(Bin, Sz) ->
- rand_bytes(<<(erlang:md5(Bin))/binary, Bin/binary>>, Sz).
-
+ Plain = gen_determ_rand_bytes(64 bsl 10),
+ Deflated = zlib:zip(Plain),
+ ?m(Plain, zlib:unzip(Deflated)).
%% Test a standard compressed zip file.
zip_usage(Config) when is_list(Config) ->
zip_usage(zip_usage({get_arg,Config}));
zip_usage({get_arg,Config}) ->
- Out = conf(data_dir,Config),
+ Out = get_data_dir(Config),
{ok,ZIP} = file:read_file(filename:join(Out,"zipdoc.zip")),
{ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")),
{run,ZIP,ORIG};
@@ -672,13 +801,13 @@ zip_usage({run,ZIP,ORIG}) ->
?m(ok, zlib:deflateInit(Z, default, deflated, -15, 8, default)),
C2 = zlib:deflate(Z, ORIG, finish),
- ?m(true, C1 == list_to_binary(C2)),
+ ?m(ORIG, zlib:unzip(C2)),
?m(ok, zlib:deflateEnd(Z)),
?m(ok, zlib:deflateInit(Z, none, deflated, -15, 8, filtered)),
?m(ok, zlib:deflateParams(Z, default, default)),
C3 = zlib:deflate(Z, ORIG, finish),
- ?m(true, C1 == list_to_binary(C3)),
+ ?m(ORIG, zlib:unzip(C3)),
?m(ok, zlib:deflateEnd(Z)),
ok = zlib:close(Z),
@@ -688,7 +817,7 @@ zip_usage({run,ZIP,ORIG}) ->
gz_usage(Config) when is_list(Config) ->
gz_usage(gz_usage({get_arg,Config}));
gz_usage({get_arg,Config}) ->
- Out = conf(data_dir,Config),
+ Out = get_data_dir(Config),
{ok,GZIP} = file:read_file(filename:join(Out,"zipdoc.1.gz")),
{ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")),
{ok,GZIP2} = file:read_file(filename:join(Out,"zipdoc.txt.gz")),
@@ -709,7 +838,7 @@ gz_usage2(Config) ->
case os:find_executable("gzip") of
Name when is_list(Name) ->
Z = zlib:open(),
- Out = conf(data_dir,Config),
+ Out = get_data_dir(Config),
{ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")),
Compressed = zlib:gzip(ORIG),
GzOutFile = filename:join(Out,"out.gz"),
@@ -737,7 +866,7 @@ gz_usage2(Config) ->
compress_usage(Config) when is_list(Config) ->
compress_usage(compress_usage({get_arg,Config}));
compress_usage({get_arg,Config}) ->
- Out = conf(data_dir,Config),
+ Out = get_data_dir(Config),
{ok,C1} = file:read_file(filename:join(Out,"png-compressed.zlib")),
{run,C1};
compress_usage({run,C1}) ->
@@ -792,7 +921,7 @@ compress_usage({run,C1}) ->
crc(Config) when is_list(Config) ->
crc(crc({get_arg,Config}));
crc({get_arg,Config}) ->
- Out = conf(data_dir,Config),
+ Out = get_data_dir(Config),
{ok,C1} = file:read_file(filename:join(Out,"zipdoc")),
{run,C1};
crc({run,C1}) ->
@@ -821,7 +950,7 @@ crc({run,C1}) ->
adler(Config) when is_list(Config) ->
adler(adler({get_arg,Config}));
adler({get_arg,Config}) ->
- Out = conf(data_dir,Config),
+ Out = get_data_dir(Config),
File1 = filename:join(Out,"zipdoc"),
{ok,C1} = file:read_file(File1),
{run,C1};
@@ -869,10 +998,14 @@ dictionary_usage({run}) ->
%% Now uncompress.
Z2 = zlib:open(),
?m(ok, zlib:inflateInit(Z2)),
- {'EXIT',{{need_dictionary,DictID},_}} = (catch zlib:inflate(Z2, Compressed)),
+
+ ?m(?EXIT({need_dictionary, DictID}), zlib:inflate(Z2, Compressed)),
+
?m(ok, zlib:inflateSetDictionary(Z2, Dict)),
?m(ok, zlib:inflateSetDictionary(Z2, binary_to_list(Dict))),
+
Uncompressed = ?m(B when is_list(B), zlib:inflate(Z2, [])),
+
?m(ok, zlib:inflateEnd(Z2)),
?m(ok, zlib:close(Z2)),
?m(Data, list_to_binary(Uncompressed)).
@@ -882,33 +1015,73 @@ split_bin(<<Part:1997/binary,Rest/binary>>, Acc) ->
split_bin(Last,Acc) ->
lists:reverse([Last|Acc]).
+only_allow_owner(Config) when is_list(Config) ->
+ Z = zlib:open(),
+ Owner = self(),
+
+ ?m(ok, zlib:inflateInit(Z)),
+ ?m(ok, zlib:inflateReset(Z)),
+
+ {Pid, Ref} = spawn_monitor(
+ fun() ->
+ ?m(?EXIT(not_on_controlling_process), zlib:inflateReset(Z)),
+ Owner ! '$transfer_ownership',
+ receive
+ '$ownership_transferred' ->
+ ?m(ok, zlib:inflateReset(Z))
+ after 200 ->
+ ct:fail("Never received transfer signal.")
+ end
+ end),
+ ownership_transfer_check(Z, Pid, Ref).
+
+ownership_transfer_check(Z, WorkerPid, Ref) ->
+ receive
+ '$transfer_ownership' ->
+ zlib:set_controlling_process(Z, WorkerPid),
+ WorkerPid ! '$ownership_transferred',
+ ownership_transfer_check(Z, WorkerPid, Ref);
+ {'DOWN', Ref, process, WorkerPid, normal} ->
+ ok;
+ {'DOWN', Ref, process, WorkerPid, Reason} ->
+ ct:fail("Spawned worker crashed with reason ~p.", [Reason])
+ after 200 ->
+ ct:fail("Spawned worker timed out.")
+ end.
+
+sub_heap_binaries(Config) when is_list(Config) ->
+ Compressed = zlib:compress(<<"gurka">>),
+ ConfLen = erlang:length(Config),
+
+ HeapBin = <<ConfLen:8/integer, Compressed/binary>>,
+ <<_:8/integer, SubHeapBin/binary>> = HeapBin,
+
+ ?m(<<"gurka">>, zlib:uncompress(SubHeapBin)),
+ ok.
%% Check concurrent access to zlib driver.
smp(Config) ->
- case erlang:system_info(smp_support) of
- true ->
- NumOfProcs = lists:min([8,erlang:system_info(schedulers)]),
- io:format("smp starting ~p workers\n",[NumOfProcs]),
-
- %% Tests to run in parallel.
- Funcs = [zip_usage, gz_usage, compress_usage, dictionary_usage,
- crc, adler],
-
- %% We get all function arguments here to avoid repeated parallel
- %% file read access.
- FnAList = lists:map(fun(F) -> {F,?MODULE:F({get_arg,Config})}
- end, Funcs),
-
- Pids = [spawn_link(?MODULE, worker, [rand:uniform(9999),
- list_to_tuple(FnAList),
- self()])
- || _ <- lists:seq(1,NumOfProcs)],
- wait_pids(Pids);
-
- false ->
- {skipped,"No smp support"}
- end.
+ NumOfProcs = lists:min([8,erlang:system_info(schedulers)]),
+ io:format("smp starting ~p workers\n",[NumOfProcs]),
+
+ %% Tests to run in parallel.
+ Funcs =
+ [zip_usage, gz_usage, compress_usage, dictionary_usage,
+ crc, adler],
+
+ %% We get all function arguments here to avoid repeated parallel
+ %% file read access.
+ UsageArgs =
+ list_to_tuple([{F, ?MODULE:F({get_arg,Config})} || F <- Funcs]),
+ Parent = self(),
+
+ WorkerFun =
+ fun() ->
+ worker(rand:uniform(9999), UsageArgs, Parent)
+ end,
+ Pids = [spawn_link(WorkerFun) || _ <- lists:seq(1, NumOfProcs)],
+ wait_pids(Pids).
worker(Seed, FnATpl, Parent) ->
io:format("smp worker ~p, seed=~p~n",[self(),Seed]),
@@ -999,43 +1172,98 @@ otp_9981(Config) when is_list(Config) ->
Ports = lists:sort(erlang:ports()),
ok.
+-define(BENCH_SIZE, (16 bsl 20)).
+
+-define(DECOMPRESS_BENCH(Name, What, Data),
+ Name(Config) when is_list(Config) ->
+ Uncompressed = Data,
+ Compressed = zlib:compress(Uncompressed),
+ What(Compressed, byte_size(Uncompressed))).
+
+-define(COMPRESS_BENCH(Name, What, Data),
+ Name(Config) when is_list(Config) ->
+ Compressed = Data,
+ What(Compressed, byte_size(Compressed))).
+?DECOMPRESS_BENCH(inflate_bench_zeroed, throughput_bench_inflate,
+ <<0:(8 * ?BENCH_SIZE)>>).
+?DECOMPRESS_BENCH(inflate_bench_rand, throughput_bench_inflate,
+ gen_determ_rand_bytes(?BENCH_SIZE)).
+
+?DECOMPRESS_BENCH(chunk_bench_zeroed, throughput_bench_chunk,
+ <<0:(8 * ?BENCH_SIZE)>>).
+?DECOMPRESS_BENCH(chunk_bench_rand, throughput_bench_chunk,
+ gen_determ_rand_bytes(?BENCH_SIZE)).
+
+?COMPRESS_BENCH(deflate_bench_zeroed, throughput_bench_deflate,
+ <<0:(8 * ?BENCH_SIZE)>>).
+?COMPRESS_BENCH(deflate_bench_rand, throughput_bench_deflate,
+ gen_determ_rand_bytes(?BENCH_SIZE)).
+
+throughput_bench_inflate(Compressed, Size) ->
+ Z = zlib:open(),
+ zlib:inflateInit(Z),
+
+ submit_throughput_results(Size,
+ fun() ->
+ zlib:inflate(Z, Compressed)
+ end).
+
+throughput_bench_deflate(Uncompressed, Size) ->
+ Z = zlib:open(),
+ zlib:deflateInit(Z),
+
+ submit_throughput_results(Size,
+ fun() ->
+ zlib:deflate(Z, Uncompressed, finish)
+ end).
+
+throughput_bench_chunk(Compressed, Size) ->
+ Z = zlib:open(),
+ zlib:inflateInit(Z),
+
+ ChunkLoop =
+ fun
+ Loop({more, _}) -> Loop(zlib:inflateChunk(Z));
+ Loop(_) -> ok
+ end,
+
+ submit_throughput_results(Size,
+ fun() ->
+ ChunkLoop(zlib:inflateChunk(Z, Compressed))
+ end).
+
+submit_throughput_results(Size, Fun) ->
+ TimeTaken = measure_perf_counter(Fun, millisecond),
+
+ KBPS = trunc((Size bsr 10) / (TimeTaken / 1000)),
+ ct_event:notify(#event{ name = benchmark_data, data = [{value,KBPS}] }),
+ {comment, io_lib:format("~p ms, ~p KBPS", [TimeTaken, KBPS])}.
+
+measure_perf_counter(Fun, Unit) ->
+ Start = os:perf_counter(Unit),
+ Fun(),
+ os:perf_counter(Unit) - Start.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Helps with testing directly %%%%%%%%%%%%%
-conf(What,Config) ->
- try proplists:get_value(What,Config) of
- undefined ->
- "./zlib_SUITE_data";
- Dir ->
- Dir
+get_data_dir(Config) ->
+ try proplists:get_value(data_dir,Config) of
+ undefined ->
+ "./zlib_SUITE_data";
+ Dir ->
+ Dir
catch
- _:_ -> "./zlib_SUITE_data"
+ _:_ -> "./zlib_SUITE_data"
end.
-t() -> t([all]).
-
-t(What) when not is_list(What) ->
- t([What]);
-t(What) ->
- lists:foreach(fun(T) ->
- try ?MODULE:T([])
- catch _E:_R ->
- Line = get(test_server_loc),
- io:format("Failed ~p:~p ~p ~p ~p~n",
- [T,Line,_E,_R, erlang:get_stacktrace()])
- end
- end, expand(What)).
-
-expand(All) ->
- lists:reverse(expand(All,[])).
-expand([H|T], Acc) ->
- case ?MODULE:H(suite) of
- [] -> expand(T,[H|Acc]);
- Cs ->
- R = expand(Cs, Acc),
- expand(T, R)
- end;
-expand([], Acc) -> Acc.
-
+%% Generates a bunch of statistically random bytes using the size as seed.
+gen_determ_rand_bytes(Size) ->
+ gen_determ_rand_bytes(Size, erlang:md5_init(), <<>>).
+gen_determ_rand_bytes(Size, _Context, Acc) when Size =< 0 ->
+ Acc;
+gen_determ_rand_bytes(Size, Context0, Acc) when Size > 0 ->
+ Context = erlang:md5_update(Context0, <<Size/integer>>),
+ Checksum = erlang:md5_final(Context),
+ gen_determ_rand_bytes(Size - 16, Context, <<Acc/binary, Checksum/binary>>).
diff --git a/lib/kernel/test/zzz_SUITE.erl b/lib/kernel/test/zzz_SUITE.erl
new file mode 100644
index 0000000000..59c7fd7404
--- /dev/null
+++ b/lib/kernel/test/zzz_SUITE.erl
@@ -0,0 +1,37 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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(zzz_SUITE).
+
+%% The sole purpose of this test suite is for things we want to run last
+%% before the VM terminates.
+
+-export([all/0]).
+
+-export([lc_graph/1]).
+
+
+all() ->
+ [lc_graph].
+
+lc_graph(_Config) ->
+ %% Create "lc_graph" file in current working dir
+ %% if lock checker is enabled.
+ erts_debug:lc_graph(),
+ ok.
diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk
index 4edecd8969..df95174c9f 100644
--- a/lib/kernel/vsn.mk
+++ b/lib/kernel/vsn.mk
@@ -1 +1 @@
-KERNEL_VSN = 5.3
+KERNEL_VSN = 6.1
diff --git a/lib/megaco/doc/src/Makefile b/lib/megaco/doc/src/Makefile
index 8b9ce31d0e..5e085b60b0 100644
--- a/lib/megaco/doc/src/Makefile
+++ b/lib/megaco/doc/src/Makefile
@@ -1,7 +1,7 @@
-#
+#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
+# Copyright Ericsson AB 2000-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -43,7 +43,7 @@ include files.mk
# ----------------------------------------------------
XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \
- $(XML_PART_FILES) $(XML_CHAPTER_FILES)
+ $(XML_PART_FILES) $(XML_CHAPTER_FILES)
INTERNAL_HTML_FILES = $(TECHNICAL_DESCR_FILES:%.xml=$(HTMLDIR)/%.html)
@@ -70,10 +70,6 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-INDEX_FILE = index.html
-INDEX_SRC = $(INDEX_FILE).src
-INDEX_TARGET = $(DOCDIR)/$(INDEX_FILE)
-
STANDARD_DIR = ../standard
STANDARDS = $(STANDARD_DIR)/rfc3525.txt \
$(STANDARD_DIR)/rfc4234.txt \
@@ -81,10 +77,10 @@ STANDARDS = $(STANDARD_DIR)/rfc3525.txt \
$(STANDARD_DIR)/implementors_guide_v10-13.pdf
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
+XML_FLAGS +=
+DVIPS_FLAGS +=
# ----------------------------------------------------
@@ -101,7 +97,7 @@ $(HTMLDIR)/%.png: %.png
docs: pdf html man
-ldocs: local_docs $(INDEX_TARGET)
+ldocs: local_docs
$(TOP_PDF_FILE): $(XML_FILES)
@@ -118,25 +114,18 @@ clean_man:
clean_html:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
imgs: $(IMG_FILES:%=$(HTMLDIR)/%)
-man: $(MAN3_FILES)
-
-$(INDEX_TARGET): $(INDEX_SRC) $(APP_FILE)
- sed -e 's/%VSN%/$(VSN)/' \
- -e 's/%ERLANG_SITE%/www\.erlang\.se\//' \
- -e 's/%UP_ONE_LEVEL%/..\/..\/..\/doc\/index.html/' \
- -e 's/%OFF_PRINT%/pdf\/megaco-$(VSN).pdf/' $< > $@
+man: $(MAN3_FILES)
-debug opt:
+debug opt:
info:
@echo "->Makefile<-"
@echo ""
- @echo "INDEX_FILE = $(INDEX_FILE)"
- @echo "INDEX_SRC = $(INDEX_SRC)"
- @echo "INDEX_TARGET = $(INDEX_TARGET)"
+ @echo "HTML_REF_MAN_FILE = $(HTML_REF_MAN_FILE)"
@echo ""
@echo "XML_APPLICATION_FILES = $(XML_APPLICATION_FILES)"
@echo "XML_PART_FILES = $(XML_PART_FILES)"
@@ -158,7 +147,7 @@ info:
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
@@ -193,4 +182,3 @@ $(HTMLDIR)/megaco_transport_mechanisms.html: megaco_transport_mechanisms.xml
$(HTMLDIR)/megaco_transport.html: megaco_transport.xml
$(HTMLDIR)/megaco_udp.html: megaco_udp.xml
$(HTMLDIR)/megaco_user.html: megaco_user.xml
-
diff --git a/lib/megaco/doc/src/book.gif b/lib/megaco/doc/src/book.gif
deleted file mode 100644
index 94b3868792..0000000000
--- a/lib/megaco/doc/src/book.gif
+++ /dev/null
Binary files differ
diff --git a/lib/megaco/doc/src/book.xml b/lib/megaco/doc/src/book.xml
index 47ad9b6a5e..06ff315de7 100644
--- a/lib/megaco/doc/src/book.xml
+++ b/lib/megaco/doc/src/book.xml
@@ -4,14 +4,14 @@
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<header titlestyle="normal">
<copyright>
- <year>2000</year><year>2016</year>
+ <year>2000</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
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
@@ -19,7 +19,7 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-
+
</legalnotice>
<title>Megaco/H.248</title>
@@ -46,4 +46,3 @@
</releasenotes>
<index></index>
</book>
-
diff --git a/lib/megaco/doc/src/fascicules.xml b/lib/megaco/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/megaco/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/megaco/doc/src/files.mk b/lib/megaco/doc/src/files.mk
index 5e7d849ab6..e40889c3fb 100644
--- a/lib/megaco/doc/src/files.mk
+++ b/lib/megaco/doc/src/files.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2016. All Rights Reserved.
+# Copyright Ericsson AB 2001-2017. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -36,9 +36,7 @@ XML_REF3_FILES = \
megaco_udp.xml
XML_PART_FILES = \
- part.xml \
- part_notes.xml \
- part_notes_history.xml
+ part.xml
XML_EXTRA_FILES = \
notes_history.xml
@@ -61,11 +59,6 @@ IMG_FILES = \
single_node_config.gif \
distr_node_config.gif \
megaco_sys_arch.gif \
- user_guide.gif \
- note.gif \
- notes.gif \
- ref_man.gif \
- book.gif \
MG-startup_flow_noMID.gif \
MGC_startup_call_flow.gif \
MG_startup_call_flow.gif \
diff --git a/lib/megaco/doc/src/index.html.src b/lib/megaco/doc/src/index.html.src
deleted file mode 100644
index b3ff9c3ae7..0000000000
--- a/lib/megaco/doc/src/index.html.src
+++ /dev/null
@@ -1,113 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<!-- This file is obsolete -->
-<HTML>
-<!--
- ``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.
-
- The Initial Developer of the Original Code is Ericsson Utvecklings AB.
- Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
- AB. All Rights Reserved.''
-
- $Id$
--->
-<HEAD>
-<TITLE>Megaco %VSN%</TITLE>
-</HEAD>
-
-<BODY BGCOLOR="#FFFFFF">
-
-<CENTER>
-<A HREF="http://%ERLANG_SITE%">
- <IMG ALT="Erlang/OTP" BORDER=0 SRC="html/min_head.gif">
-</A><BR>
-
-<FONT SIZE="-1">
-[<A HREF="%UP_ONE_LEVEL%">Up</A> |
-<A HREF="http://%ERLANG_SITE%">Erlang/OTP</A>]
-</FONT><BR>
-
-<P><FONT SIZE="+3">Megaco</FONT><BR>
-Version %VSN%
-</CENTER>
-
-<P><TABLE>
-<TR>
-<TD>
-<!-- IMG ALIGN=LEFT ALT="MEGACO" SRC="html/megaco.gif" -->
-</TD>
-
-<TD>
- <p>The <STRONG>Megaco</STRONG> application is a framework
-for building applications on top of the Megaco/H.248 protocol.</p>
-</TD>
-</TR>
-</TABLE>
-
-<P><CENTER>
-<TABLE CELLPADDING=15>
-<TR>
-<TD ALIGN=CENTER>
-<A HREF="html/users_guide.html">
- <IMG ALT="User's Guide" BORDER=0 SRC="html/user_guide.gif">
-</A>
-<BR>
-<FONT SIZE="-1">
-<A HREF="html/users_guide.html">User's Guide</A>
-</FONT>
-</TD>
-
-<TD ALIGN=CENTER>
-<A HREF="html/index.html">
- <IMG ALT="Reference Manual" BORDER=0 SRC="html/ref_man.gif">
-</A>
-<BR>
-<FONT SIZE="-1">
-<A HREF="html/index.html">Reference Manual</A>
-</FONT>
-</TD>
-
-</TR>
-
-<TR>
-<TD ALIGN=CENTER>
-<A HREF="html/release_notes.html">
- <IMG ALT="Release Notes" BORDER=0 SRC="html/notes.gif">
-</A>
-<BR>
-<FONT SIZE="-1">
-<A HREF="html/release_notes.html">Release Notes</A>
-</FONT>
-</TD>
-
-<TD ALIGN=CENTER>
-<A HREF="%OFF_PRINT%">
- <IMG ALT="Off-Print" BORDER=0 SRC="html/book.gif">
-</A>
-<BR>
-<FONT SIZE="-1">
-<A HREF="%OFF_PRINT%">Off-Print</A>
-</FONT>
-</TD>
-</TR>
-</TABLE>
-</CENTER>
-
-<P><CENTER>
-<HR>
-<FONT SIZE="-1">
-Copyright &copy; 1991-2001
-<A HREF="http://www.erlang.se/">Ericsson Utvecklings AB</A>
-</FONT>
-</CENTER>
-</BODY>
-</HTML>
diff --git a/lib/megaco/doc/src/note.gif b/lib/megaco/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/megaco/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/megaco/doc/src/notes.gif b/lib/megaco/doc/src/notes.gif
deleted file mode 100644
index e000cca26a..0000000000
--- a/lib/megaco/doc/src/notes.gif
+++ /dev/null
Binary files differ
diff --git a/lib/megaco/doc/src/notes.xml b/lib/megaco/doc/src/notes.xml
index 068389c0c2..b697c3f631 100644
--- a/lib/megaco/doc/src/notes.xml
+++ b/lib/megaco/doc/src/notes.xml
@@ -11,7 +11,7 @@
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
@@ -19,9 +19,9 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-
+
</legalnotice>
-
+
<title>Megaco Release Notes</title>
<prepared>Lars Thors&eacute;n, H&aring;kan Mattsson, Micael Karlberg</prepared>
<docno></docno>
@@ -35,9 +35,39 @@
bugfixes for every release of Megaco. Each release of Megaco
thus constitutes one section in this document. The title of each
section is the version number of Megaco.</p>
-
-
- <section><title>Megaco 3.18.2</title>
+
+
+ <section><title>Megaco 3.18.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Megaco 3.18.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Megaco 3.18.2</title>
<section><title>Improvements and New Features</title>
<list>
@@ -142,7 +172,7 @@
</item>
</list>
</section>
-
+
</section>
<section><title>Megaco 3.17.0.2</title>
@@ -158,7 +188,7 @@
</item>
</list>
</section>
-
+
</section>
<section><title>Megaco 3.17.0.1</title>
@@ -190,7 +220,7 @@
<list type="bulleted">
<item>
<p>Allow whitespaces in installation path. </p>
- <p>It is now possible to give configure and make an
+ <p>It is now possible to give configure and make an
installation/release path with whitespaces in it. </p>
<p>Own Id: OTP-10107</p>
</item>
@@ -202,24 +232,24 @@
<section>
<title>Fixed bugs and malfunctions</title>
-
+
<!--
<p>-</p>
-->
-
+
<list type="bulleted">
<item>
- <p>Buffer overrun error while flex scanner processing
+ <p>Buffer overrun error while flex scanner processing
property parm groups. </p>
- <p>This error occured only for large messages if a
- buffer realloc was needed while processing the
+ <p>This error occured only for large messages if a
+ buffer realloc was needed while processing the
property parm groups. </p>
<p>Own Id: OTP-10998</p>
<p>Aux Id: Seq 12263</p>
</item>
-
+
</list>
-
+
</section>
<section>
@@ -229,10 +259,10 @@
<!--
<list type="bulleted">
<item>
- <p>A number of binary encoding alternatives has been removed.
+ <p>A number of binary encoding alternatives has been removed.
The binary encoding option <c>driver</c> has been removed
- since this (the use of the asn1 linked in driver) is
- now default and there is now way to <em>not</em> use it.
+ since this (the use of the asn1 linked in driver) is
+ now default and there is now way to <em>not</em> use it.
See <seealso marker="megaco_encode#binary_config">configuration of binary encoding</seealso> for more info. </p>
</item>
@@ -270,19 +300,19 @@
<section>
<title>Fixed bugs and malfunctions</title>
-
+
<p>-</p>
-
+
<!--
<list type="bulleted">
<item>
<p>Fixing miscellaneous things detected by dialyzer. </p>
<p>Own Id: OTP-9075</p>
</item>
-
+
</list>
-->
-
+
</section>
<section>
@@ -293,10 +323,10 @@
<list type="bulleted">
<item>
- <p>A number of binary encoding alternatives has been removed.
+ <p>A number of binary encoding alternatives has been removed.
The binary encoding option <c>driver</c> has been removed
- since this (the use of the asn1 linked in driver) is
- now default and there is now way to <em>not</em> use it.
+ since this (the use of the asn1 linked in driver) is
+ now default and there is now way to <em>not</em> use it.
See <seealso marker="megaco_encode#binary_config">configuration of binary encoding</seealso> for more info. </p>
</item>
@@ -322,7 +352,7 @@
<list type="bulleted">
<item>
<p>Allow whitespaces in installation path. </p>
- <p>It is now possible to give configure and make an
+ <p>It is now possible to give configure and make an
installation/release path with whitespaces in it. </p>
<p>Own Id: OTP-10107</p>
</item>
@@ -332,8 +362,8 @@
</item>
<item>
- <p>Removed use of deprecated system flag,
- <c>global_haeps_size</c>, in the measurement tool
+ <p>Removed use of deprecated system flag,
+ <c>global_haeps_size</c>, in the measurement tool
<c>mstone1</c>. </p>
</item>
@@ -343,19 +373,19 @@
<section>
<title>Fixed bugs and malfunctions</title>
-
+
<p>-</p>
-
+
<!--
<list type="bulleted">
<item>
<p>Fixing miscellaneous things detected by dialyzer. </p>
<p>Own Id: OTP-9075</p>
</item>
-
+
</list>
-->
-
+
</section>
<section>
@@ -365,8 +395,8 @@
<!--
<list type="bulleted">
<item>
- <p>Due to the change in the flex driver API,
- we may no longer be able to build and/or use
+ <p>Due to the change in the flex driver API,
+ we may no longer be able to build and/or use
the flex driver without reentrant support. </p>
<p>Own Id: OTP-9795</p>
</item>
@@ -400,8 +430,8 @@
</item>
<item>
- <p>Removed use of deprecated system flag,
- <c>scheduler_bind_type</c>, in the measurement tool
+ <p>Removed use of deprecated system flag,
+ <c>scheduler_bind_type</c>, in the measurement tool
<c>mstone1</c>. </p>
<p>Own Id: OTP-9949</p>
</item>
@@ -412,19 +442,19 @@
<section>
<title>Fixed bugs and malfunctions</title>
-
+
<p>-</p>
-
+
<!--
<list type="bulleted">
<item>
<p>Fixing miscellaneous things detected by dialyzer. </p>
<p>Own Id: OTP-9075</p>
</item>
-
+
</list>
-->
-
+
</section>
<section>
@@ -434,8 +464,8 @@
<!--
<list type="bulleted">
<item>
- <p>Due to the change in the flex driver API,
- we may no longer be able to build and/or use
+ <p>Due to the change in the flex driver API,
+ we may no longer be able to build and/or use
the flex driver without reentrant support. </p>
<p>Own Id: OTP-9795</p>
</item>
@@ -467,8 +497,8 @@
</item>
<item>
- <p>ASN.1 no longer makes use of a driver to accelerate encode/decode,
- instead it uses NIFs. The encoding config option is <em>still</em>
+ <p>ASN.1 no longer makes use of a driver to accelerate encode/decode,
+ instead it uses NIFs. The encoding config option is <em>still</em>
the same, i.e. <c>driver</c>. </p>
<p>Own Id: OTP-9672</p>
</item>
@@ -491,19 +521,19 @@
<section>
<title>Fixed bugs and malfunctions</title>
-
+
<p>-</p>
-
+
<!--
<list type="bulleted">
<item>
<p>Fixing miscellaneous things detected by dialyzer. </p>
<p>Own Id: OTP-9075</p>
</item>
-
+
</list>
-->
-
+
</section>
<section>
@@ -513,8 +543,8 @@
<!--
<list type="bulleted">
<item>
- <p>Due to the change in the flex driver API,
- we may no longer be able to build and/or use
+ <p>Due to the change in the flex driver API,
+ we may no longer be able to build and/or use
the flex driver without reentrant support. </p>
<p>Own Id: OTP-9795</p>
</item>
@@ -551,19 +581,19 @@
<section>
<title>Fixed bugs and malfunctions</title>
-
+
<p>-</p>
-
+
<!--
<list type="bulleted">
<item>
<p>Fixing miscellaneous things detected by dialyzer. </p>
<p>Own Id: OTP-9075</p>
</item>
-
+
</list>
-->
-
+
</section>
</section> <!-- 3.15.1.1 -->
@@ -582,8 +612,8 @@
<!--
<list type="bulleted">
<item>
- <p>Updated the
- <seealso marker="megaco_performance">performance</seealso>
+ <p>Updated the
+ <seealso marker="megaco_performance">performance</seealso>
chapter. </p>
<p>Own Id: OTP-8696</p>
</item>
@@ -637,7 +667,7 @@
<!--
<list type="bulleted">
<item>
- <p>Eliminated a possible race condition while creating
+ <p>Eliminated a possible race condition while creating
pending counters. </p>
<p>Own Id: OTP-8634</p>
<p>Aux Id: Seq 11579</p>
@@ -666,8 +696,8 @@
<list type="bulleted">
<item>
- <p>Updated the
- <seealso marker="megaco_performance">performance</seealso>
+ <p>Updated the
+ <seealso marker="megaco_performance">performance</seealso>
chapter. </p>
<p>Own Id: OTP-8696</p>
</item>
@@ -694,14 +724,14 @@
<item>
<p>Fix shared libraries installation. </p>
- <p>The flex shared lib(s) were incorrectly installed as data
+ <p>The flex shared lib(s) were incorrectly installed as data
files. </p>
<p>Peter Lemenkov</p>
<p>Own Id: OTP-8627</p>
</item>
<item>
- <p>Eliminated a possible race condition while creating
+ <p>Eliminated a possible race condition while creating
pending counters. </p>
<p>Own Id: OTP-8634</p>
<p>Aux Id: Seq 11579</p>
@@ -757,14 +787,14 @@
<item>
<p>Fix shared libraries installation. </p>
- <p>The flex shared lib(s) were incorrectly installed as data
+ <p>The flex shared lib(s) were incorrectly installed as data
files. </p>
<p>Peter Lemenkov</p>
<p>Own Id: OTP-8627</p>
</item>
<item>
- <p>Eliminated a possible race condition while creating
+ <p>Eliminated a possible race condition while creating
pending counters. </p>
<p>Own Id: OTP-8634</p>
<p>Aux Id: Seq 11579</p>
@@ -792,18 +822,18 @@
<list type="bulleted">
<item>
- <p>Various changes to configure and makefile(s) to facilitate cross
+ <p>Various changes to configure and makefile(s) to facilitate cross
compilation (and other build system improvements). </p>
<p>Own Id: OTP-8323</p>
</item>
<item>
- <p>Added a help target in the test Makefile to explain
- the most useful make targets, used when testing the
+ <p>Added a help target in the test Makefile to explain
+ the most useful make targets, used when testing the
application using the test-server provided with megaco.</p>
<p>Own Id: OTP-8362</p>
</item>
-
+
<item>
<p>Adapted megaco_filter to the new internal format.</p>
<p>Own Id: OTP-8403</p>
@@ -820,16 +850,16 @@
<list type="bulleted">
<item>
- <p>Callbacks, when the callback module is unknown (undefined),
+ <p>Callbacks, when the callback module is unknown (undefined),
results in warning messages. </p>
<p>A race condition scenario. As part of a cancelation operation,
replies with waiting acknowledgements is cancelled. This includes
- informing the user (via a call to the handle_trans_ack callback
- function). It is possible that at this point the connection data
- has been removed, which makes it impossible for megaco to
- perform this operation, resulting in the warning message. The
- solution is to also store the callback module with the other
- reply information, to be used when cleaning up after a
+ informing the user (via a call to the handle_trans_ack callback
+ function). It is possible that at this point the connection data
+ has been removed, which makes it impossible for megaco to
+ perform this operation, resulting in the warning message. The
+ solution is to also store the callback module with the other
+ reply information, to be used when cleaning up after a
cancelation. </p>
<p>Own Id: OTP-8328</p>
<p>Aux Id: Seq 11384</p>
@@ -863,8 +893,8 @@
</item>
<item>
- <p>The documentation is now built with open source tools
- (<em>xsltproc</em> and <em>fop</em>) that exists on most
+ <p>The documentation is now built with open source tools
+ (<em>xsltproc</em> and <em>fop</em>) that exists on most
platforms. One visible change is that the frames are removed.</p>
<p>Own Id: OTP-8249</p>
</item>
@@ -910,11 +940,4 @@
</section>
</section> <!-- 3.13 -->
-
- <!-- section>
- <title>Release notes history</title>
- <p>For information about older versions see
- <url href="part_notes_history_frame.html">release notes history</url>.</p
- </section> -->
</chapter>
-
diff --git a/lib/megaco/doc/src/part_notes.xml b/lib/megaco/doc/src/part_notes.xml
deleted file mode 100644
index 7a838c5718..0000000000
--- a/lib/megaco/doc/src/part_notes.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2000</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Megaco/H.248 Release Notes</title>
- <prepared>Lars Thors&eacute;n, H&aring;kan Mattsson, Micael Karlberg</prepared>
- <docno></docno>
- <date>2007-06-15</date>
- <rev>%VSN%</rev>
- <file>part_notes.xml</file>
- </header>
- <description>
- <p>The Megaco application is a framework for building
- applications on top of the Megaco/H.248 protocol.</p>
- <p>For information about older versions see
- <url href="part_notes_history_frame.html">release notes history</url>.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/megaco/doc/src/part_notes_history.xml b/lib/megaco/doc/src/part_notes_history.xml
deleted file mode 100644
index 0d8f1f2fb5..0000000000
--- a/lib/megaco/doc/src/part_notes_history.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2006</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Megaco Release Notes History</title>
- <prepared>Micael Karklberg</prepared>
- <responsible>OTP</responsible>
- <docno></docno>
- <approved>OTP</approved>
- <checked></checked>
- <date>2007-06-15</date>
- <rev>A</rev>
- <file>part_notes_history.xml</file>
- </header>
- <description>
- <p>The Megaco application is a framework for building
- applications on top of the Megaco/H.248 protocol.</p>
- </description>
- <include file="notes_history"></include>
-</part>
-
diff --git a/lib/megaco/doc/src/ref_man.gif b/lib/megaco/doc/src/ref_man.gif
deleted file mode 100644
index b13c4efd53..0000000000
--- a/lib/megaco/doc/src/ref_man.gif
+++ /dev/null
Binary files differ
diff --git a/lib/megaco/doc/src/user_guide.gif b/lib/megaco/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/megaco/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/megaco/doc/src/warning.gif b/lib/megaco/doc/src/warning.gif
deleted file mode 100644
index 96af52360e..0000000000
--- a/lib/megaco/doc/src/warning.gif
+++ /dev/null
Binary files differ
diff --git a/lib/megaco/vsn.mk b/lib/megaco/vsn.mk
index 9c6ba5bba0..f4c82c537a 100644
--- a/lib/megaco/vsn.mk
+++ b/lib/megaco/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = megaco
-MEGACO_VSN = 3.18.2
+MEGACO_VSN = 3.18.4
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(MEGACO_VSN)$(PRE_VSN)"
diff --git a/lib/mnesia/doc/src/Makefile b/lib/mnesia/doc/src/Makefile
index 39f2b28637..d9647fc081 100644
--- a/lib/mnesia/doc/src/Makefile
+++ b/lib/mnesia/doc/src/Makefile
@@ -1,8 +1,8 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
+#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -14,7 +14,7 @@
# 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%
#
@@ -44,39 +44,34 @@ XML_REF3_FILES = \
mnesia_registry.xml
XML_PART_FILES = \
- part.xml \
- part_notes.xml \
- part_notes_history.xml
+ part.xml
XML_CHAPTER_FILES = \
Mnesia_chap1.xml \
+ Mnesia_overview.xml \
+ Mnesia_chap8.xml \
+ notes.xml
+
+XML_CHAPTER_GEN_FILES = \
Mnesia_chap2.xml \
Mnesia_chap3.xml \
Mnesia_chap4.xml \
Mnesia_chap5.xml \
Mnesia_chap7.xml \
- Mnesia_chap8.xml \
Mnesia_App_A.xml \
Mnesia_App_B.xml \
- Mnesia_App_C.xml \
- notes.xml
+ Mnesia_App_C.xml
BOOK_FILES = book.xml
-
XML_FILES = \
$(BOOK_FILES) $(XML_CHAPTER_FILES) \
$(XML_PART_FILES) $(XML_REF3_FILES) $(XML_APPLICATION_FILES)
+XML_GEN_FILES = $(XML_CHAPTER_GEN_FILES:%=$(XMLDIR)/%)
+
GIF_FILES = \
- book.gif \
- company.gif \
- mnesia.gif \
- note.gif \
- notes.gif \
- ref_man.gif \
- user_guide.gif \
- warning.gif
+ company.gif
XML_HTML_FILES = \
notes_history.xml
@@ -89,7 +84,7 @@ HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
$(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
INFO_FILE = ../../info
-EXTRA_FILES = summary.html.src \
+EXTRA_FILES = \
$(DEFAULT_GIF_FILES) \
$(DEFAULT_HTML_FILES) \
$(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html) \
@@ -102,10 +97,10 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
+XML_FLAGS +=
+DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -123,6 +118,7 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
@@ -134,11 +130,11 @@ gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
$(INDEX_TARGET): $(INDEX_SRC) ../../vsn.mk
sed -e 's;%VSN%;$(VSN);' $< > $@
-debug opt:
+debug opt:
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
diff --git a/lib/mnesia/doc/src/Mnesia_chap2.xmlsrc b/lib/mnesia/doc/src/Mnesia_chap2.xmlsrc
index 37389ce5ae..8135e14301 100644
--- a/lib/mnesia/doc/src/Mnesia_chap2.xmlsrc
+++ b/lib/mnesia/doc/src/Mnesia_chap2.xmlsrc
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -327,7 +327,7 @@
<section>
<title>Initial Database Content</title>
<p>After the insertion of the employee named <c>klacke</c>,
- the databse has the following records:</p>
+ the database has the following records:</p>
<marker id="table2_1"></marker>
<table>
<row>
diff --git a/lib/mnesia/doc/src/Mnesia_chap5.xmlsrc b/lib/mnesia/doc/src/Mnesia_chap5.xmlsrc
index 62759c624b..481e6651e6 100644
--- a/lib/mnesia/doc/src/Mnesia_chap5.xmlsrc
+++ b/lib/mnesia/doc/src/Mnesia_chap5.xmlsrc
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -226,8 +226,10 @@
not known beforehand, all fragments are searched for
matching records.</p>
<p>Notice that in <c>ordered_set</c> tables, the records
- are ordered per fragment, and the the order is undefined in
- results returned by <c>select</c> and <c>match_object</c>.</p>
+ are ordered per fragment, and the order is undefined in
+ results returned by <c>select</c> and <c>match_object</c>,
+ as well as <c>first</c>, <c>next</c>, <c>prev</c> and
+ <c>last</c>.</p>
<p>The following code illustrates how a <c>Mnesia</c> table is
converted to be a fragmented table and how more fragments
are added later:</p>
diff --git a/lib/mnesia/doc/src/book.gif b/lib/mnesia/doc/src/book.gif
deleted file mode 100644
index 94b3868792..0000000000
--- a/lib/mnesia/doc/src/book.gif
+++ /dev/null
Binary files differ
diff --git a/lib/mnesia/doc/src/company.erl b/lib/mnesia/doc/src/company.erl
index 20e3235347..fc04aa77bf 100644
--- a/lib/mnesia/doc/src/company.erl
+++ b/lib/mnesia/doc/src/company.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,7 +19,12 @@
%%
-module(company).
--compile(export_all).
+-export([init/0,insert_emp/3,mk_projs/2,females/0,all_females/0,
+ g/0,female_bosses/0, raise_females/1, over_write/2, raise/2,
+ bad_raise/2, get_emps/2, get_emps2/2, filter/2, filter_deps/3,
+ search_deps/3, bench1/0, dotimes/2, dist_init/0, remove_proj/1,
+ del_in_projs/1, sync/0, tabs/0, find_male_on_second_floor/0,
+ panic/1, fill_tables/0]).
%0
diff --git a/lib/mnesia/doc/src/company_o.erl b/lib/mnesia/doc/src/company_o.erl
index 7300e9d4bb..b4b3638596 100644
--- a/lib/mnesia/doc/src/company_o.erl
+++ b/lib/mnesia/doc/src/company_o.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,7 +19,11 @@
%%
-module(company_o).
--compile(export_all).
+
+-export([sinit/0, init/0,insert_emp/3,females/0,
+ female_bosses/0, raise_females/1, over_write/2, raise/2,
+ bad_raise/2, get_emps/2, get_emps2/2]).
+
-import(mnesia, [transaction/1]).
diff --git a/lib/mnesia/doc/src/fascicules.xml b/lib/mnesia/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/mnesia/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/mnesia/doc/src/mnesia.gif b/lib/mnesia/doc/src/mnesia.gif
deleted file mode 100644
index fbbabee5aa..0000000000
--- a/lib/mnesia/doc/src/mnesia.gif
+++ /dev/null
Binary files differ
diff --git a/lib/mnesia/doc/src/mnesia_frag_hash.xml b/lib/mnesia/doc/src/mnesia_frag_hash.xml
index 51b32129b6..c233acdb05 100644
--- a/lib/mnesia/doc/src/mnesia_frag_hash.xml
+++ b/lib/mnesia/doc/src/mnesia_frag_hash.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2002</year>
- <year>2016</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -130,7 +130,7 @@
<name>key_to_frag_number(State, Key) -> FragNum | abort(Reason)</name>
<fsummary>Resolves the key of a record into a fragment number.</fsummary>
<type>
- <v>FragNum = integer()()</v>
+ <v>FragNum = integer()</v>
<v>Reason = term()</v>
</type>
<desc>
diff --git a/lib/mnesia/doc/src/note.gif b/lib/mnesia/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/mnesia/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/mnesia/doc/src/notes.gif b/lib/mnesia/doc/src/notes.gif
deleted file mode 100644
index e000cca26a..0000000000
--- a/lib/mnesia/doc/src/notes.gif
+++ /dev/null
Binary files differ
diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml
index 3ca4026190..29c35d221c 100644
--- a/lib/mnesia/doc/src/notes.xml
+++ b/lib/mnesia/doc/src/notes.xml
@@ -4,14 +4,14 @@
<chapter>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
@@ -39,7 +39,153 @@
thus constitutes one section in this document. The title of each
section is the version number of Mnesia.</p>
- <section><title>Mnesia 4.15</title>
+ <section><title>Mnesia 4.15.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed type spec for <c>mnesia:change_config/2</c>.</p>
+ <p>
+ Own Id: OTP-15201 Aux Id: PR-1881 </p>
+ </item>
+ <item>
+ <p>
+ When master node is set do not force a load from
+ ram_copies replica when there are no available
+ disc_copies, since that would load an empty table. Wait
+ until a disk replica is available or until user
+ explicitly force_loads the table.</p>
+ <p>
+ Own Id: OTP-15221 Aux Id: ERIERL-217 </p>
+ </item>
+ <item>
+ <p>
+ Allow to add replicas even if all other replicas are down
+ when the other replicas are not stored on disk.</p>
+ <p>
+ Own Id: OTP-15226 Aux Id: ERIERL-221 </p>
+ </item>
+ <item>
+ <p>
+ Fixed <c>mnesia:delete_object/1</c> bug, where
+ delete_object was deleting the record if it was written
+ in the same transaction even if it was written to a
+ different value.</p>
+ <p>
+ Own Id: OTP-15231 Aux Id: PR-1858 </p>
+ </item>
+ <item>
+ <p>
+ Fixed a bug where the bag table index data was not
+ deleted when objects were deleted.</p>
+ <p>
+ Own Id: OTP-15243</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.15.4</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Calls to <c>erlang:get_stacktrace()</c> are removed.
+ </p>
+ <p>
+ Own Id: OTP-14861</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.15.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ When master node is set do not force a load from
+ ram_copies replica when there are no available
+ disc_copies, since that would load an empty table. Wait
+ until a disk replica is available or until user
+ explicitly force_loads the table.</p>
+ <p>
+ Own Id: OTP-15221 Aux Id: ERIERL-217 </p>
+ </item>
+ <item>
+ <p>
+ Allow to add replicas even if all other replicas are down
+ when the other replicase are not stored on disk.</p>
+ <p>
+ Own Id: OTP-15226 Aux Id: ERIERL-221 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.15.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Removed a quadratic behavior in startup. This change
+ implies that backend plugins (if used) must be set when
+ the schema is created or via configuration parameters
+ before mnesia is started.</p>
+ <p>
+ Own Id: OTP-14829 Aux Id: ERIERL-84 </p>
+ </item>
+ <item>
+ <p>
+ Bad timing could crash mnesia after a checkpoint was
+ deactivated and reactivated with the same checkpoint name
+ on different tables.</p>
+ <p>
+ Own Id: OTP-14841 Aux Id: ERIERL-113 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.15.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix backup error handling, the real failure reason was
+ not returned.</p>
+ <p>
+ Own Id: OTP-14776 Aux Id: ERIERL-103 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.15.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ General Unicode improvements.</p>
+ <p>
+ Own Id: OTP-14462</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.15</title>
<section><title>Improvements and New Features</title>
<list>
@@ -891,9 +1037,9 @@
</item>
</list>
</section>
-
- </section>
-
+
+ </section>
+
<section><title>Mnesia 4.4.13</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -962,7 +1108,7 @@
</section>
<section><title>Mnesia 4.4.10</title>
-
+
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
@@ -992,7 +1138,7 @@
</item>
</list>
</section>
-
+
</section>
@@ -1010,7 +1156,7 @@
</item>
</list>
</section>
-
+
</section>
<section><title>Mnesia 4.4.8</title>
@@ -1035,7 +1181,7 @@
</item>
</list>
</section>
-
+
</section>
<section><title>Mnesia 4.4.7</title>
@@ -1069,7 +1215,7 @@
</section>
- <section><title>Mnesia 4.4.6</title>
+ <section><title>Mnesia 4.4.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
@@ -1260,9 +1406,4 @@
</section>
</section>
- <!-- section>
- <title>Previous Notes</title>
- <p>For information about older versions see <url href="part_notes_history_frame.html">release notes history</url>.</p>
- </section -->
</chapter>
-
diff --git a/lib/mnesia/doc/src/part_notes.xml b/lib/mnesia/doc/src/part_notes.xml
deleted file mode 100644
index 1e4e4bc60a..0000000000
--- a/lib/mnesia/doc/src/part_notes.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>MNESIA Release Notes</title>
- <prepared>Claes Wikstr&ouml;m, Hans Nilsson and H&aring;kan Mattsson</prepared>
- <docno></docno>
- <date>1997-05-27</date>
- <rev>1.2</rev>
- <file>part_notes.xml</file>
- </header>
- <description>
- <p><em>Mnesia</em> is a Distributed DataBase Management
- System (DBMS), appropriate for telecommunications applications and other
- Erlang applications which require continuous operation and exhibit soft
- real-time properties. </p>
- <p>For information about older versions see
- <url href="part_notes_history_frame.html">release notes history</url>.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/mnesia/doc/src/part_notes_history.xml b/lib/mnesia/doc/src/part_notes_history.xml
deleted file mode 100644
index a1c6f5aef0..0000000000
--- a/lib/mnesia/doc/src/part_notes_history.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2004</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>MNESIA Release Notes</title>
- <prepared>Claes Wikstr&ouml;m, Hans Nilsson and H&aring;kan Mattsson</prepared>
- <docno></docno>
- <date>1997-05-27</date>
- <rev>1.2</rev>
- <file>part_notes_history.sgml</file>
- </header>
- <description>
- <p><em>Mnesia</em> is a Distributed DataBase Management
- System (DBMS), appropriate for telecommunications applications and other
- Erlang applications which require continuous operation and exhibit soft
- real-time properties. </p>
- </description>
- <include file="notes_history"></include>
-</part>
-
diff --git a/lib/mnesia/doc/src/ref_man.gif b/lib/mnesia/doc/src/ref_man.gif
deleted file mode 100644
index b13c4efd53..0000000000
--- a/lib/mnesia/doc/src/ref_man.gif
+++ /dev/null
Binary files differ
diff --git a/lib/mnesia/doc/src/summary.html.src b/lib/mnesia/doc/src/summary.html.src
deleted file mode 100644
index 2941a2f46a..0000000000
--- a/lib/mnesia/doc/src/summary.html.src
+++ /dev/null
@@ -1 +0,0 @@
-A heavy duty real-time distributed database \ No newline at end of file
diff --git a/lib/mnesia/doc/src/user_guide.gif b/lib/mnesia/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/mnesia/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/mnesia/doc/src/warning.gif b/lib/mnesia/doc/src/warning.gif
deleted file mode 100644
index 96af52360e..0000000000
--- a/lib/mnesia/doc/src/warning.gif
+++ /dev/null
Binary files differ
diff --git a/lib/mnesia/src/mnesia.app.src b/lib/mnesia/src/mnesia.app.src
index 6b49fc6c88..c755b4d4b9 100644
--- a/lib/mnesia/src/mnesia.app.src
+++ b/lib/mnesia/src/mnesia.app.src
@@ -49,4 +49,4 @@
]},
{applications, [kernel, stdlib]},
{mod, {mnesia_app, []}},
- {runtime_dependencies, ["stdlib-2.0","kernel-3.0","erts-7.0"]}]}.
+ {runtime_dependencies, ["stdlib-3.4","kernel-5.3","erts-9.0"]}]}.
diff --git a/lib/mnesia/src/mnesia.erl b/lib/mnesia/src/mnesia.erl
index 3b771e8c5b..223dba3f90 100644
--- a/lib/mnesia/src/mnesia.erl
+++ b/lib/mnesia/src/mnesia.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -151,7 +151,8 @@
{'snmp', SnmpStruct::term()} |
{'storage_properties', [{Backend::module(), [BackendProp::_]}]} |
{'type', 'set' | 'ordered_set' | 'bag'} |
- {'local_content', boolean()}.
+ {'local_content', boolean()} |
+ {'user_properties', proplists:proplist()}.
-type t_result(Res) :: {'atomic', Res} | {'aborted', Reason::term()}.
-type activity() :: 'ets' | 'async_dirty' | 'sync_dirty' | 'transaction' | 'sync_transaction' |
@@ -167,6 +168,9 @@
-type snmp_struct() :: [{atom(), snmp_type() | tuple_of(snmp_type())}].
-type snmp_type() :: 'fix_string' | 'string' | 'integer'.
-type tuple_of(_T) :: tuple().
+-type config_key() :: extra_db_nodes | dc_dump_limit.
+-type config_value() :: [node()] | number().
+-type config_result() :: {ok, config_value()} | {error, term()}.
-define(DEFAULT_ACCESS, ?MODULE).
@@ -176,8 +180,8 @@
%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> mnesia_lib:other_val(Var);
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
Value -> Value
end.
@@ -277,7 +281,8 @@ stop() ->
Other -> Other
end.
--spec change_config(Config::atom(), Value::_) -> ok | {error, term()}.
+-spec change_config(Config::config_key(), Value::config_value()) ->
+ config_result().
change_config(extra_db_nodes, Ns) when is_list(Ns) ->
mnesia_controller:connect_nodes(Ns);
change_config(dc_dump_limit, N) when is_number(N), N > 0 ->
@@ -778,12 +783,16 @@ do_delete_object(Tid, Ts, Tab, Val, LockKind) ->
?ets_insert(Store, {Oid, Val, delete_object});
_ ->
case ?ets_match_object(Store, {Oid, '_', write}) of
- [] ->
- ?ets_match_delete(Store, {Oid, Val, '_'}),
- ?ets_insert(Store, {Oid, Val, delete_object});
- _ ->
- ?ets_delete(Store, Oid),
- ?ets_insert(Store, {Oid, Oid, delete})
+ [] ->
+ ?ets_match_delete(Store, {Oid, Val, '_'}),
+ ?ets_insert(Store, {Oid, Val, delete_object});
+ Ops ->
+ case lists:member({Oid, Val, write}, Ops) of
+ true ->
+ ?ets_delete(Store, Oid),
+ ?ets_insert(Store, {Oid, Oid, delete});
+ false -> ok
+ end
end
end,
ok;
@@ -2283,9 +2292,9 @@ list_index_plugins([{N,M,F} | T] = Ps, Legend) ->
lists:foldl(fun({N1,_,_}, Wa) ->
erlang:max(Wa, length(pp_ix_name(N1)))
end, 0, Ps)),
- io:fwrite(Legend ++ "~-" ++ W ++ "s - ~s:~s~n",
+ io:fwrite(Legend ++ "~-" ++ W ++ "s - ~s:~ts~n",
[pp_ix_name(N), atom_to_list(M), atom_to_list(F)]),
- [io:fwrite(Indent ++ "~-" ++ W ++ "s - ~s:~s~n",
+ [io:fwrite(Indent ++ "~-" ++ W ++ "s - ~s:~ts~n",
[pp_ix_name(N1), atom_to_list(M1), atom_to_list(F1)])
|| {N1,M1,F1} <- T].
@@ -2681,7 +2690,7 @@ del_table_index(Tab, Ix) ->
-spec transform_table(Tab::table(), Fun, [Attr]) -> t_result(ok) when
Attr :: atom(),
- Fun:: fun((Record::tuple()) -> Transformed::tuple()).
+ Fun:: fun((Record::tuple()) -> Transformed::tuple()) | ignore.
transform_table(Tab, Fun, NewA) ->
try val({Tab, record_name}) of
OldRN -> mnesia_schema:transform_table(Tab, Fun, NewA, OldRN)
@@ -2692,7 +2701,7 @@ transform_table(Tab, Fun, NewA) ->
-spec transform_table(Tab::table(), Fun, [Attr], RecName) -> t_result(ok) when
RecName :: atom(),
Attr :: atom(),
- Fun:: fun((Record::tuple()) -> Transformed::tuple()).
+ Fun:: fun((Record::tuple()) -> Transformed::tuple()) | ignore.
transform_table(Tab, Fun, NewA, NewRN) ->
mnesia_schema:transform_table(Tab, Fun, NewA, NewRN).
diff --git a/lib/mnesia/src/mnesia.hrl b/lib/mnesia/src/mnesia.hrl
index da7e662288..fe48a6fe3d 100644
--- a/lib/mnesia/src/mnesia.hrl
+++ b/lib/mnesia/src/mnesia.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -47,6 +47,10 @@
-define(catch_val(Var), (try ?ets_lookup_element(mnesia_gvar, Var, 2)
catch error:_ -> {'EXIT', {badarg, []}} end)).
+-define(catch_val_and_stack(Var),
+ (try ?ets_lookup_element(mnesia_gvar, Var, 2)
+ catch error:_:_Stacktrace -> {'EXIT', _Stacktrace} end)).
+
%% It's important that counter is first, since we compare tid's
-record(tid,
diff --git a/lib/mnesia/src/mnesia_bup.erl b/lib/mnesia/src/mnesia_bup.erl
index 3e55deb958..e57fc5199d 100644
--- a/lib/mnesia/src/mnesia_bup.erl
+++ b/lib/mnesia/src/mnesia_bup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -90,9 +90,9 @@ iterate(Mod, Fun, Opaque, Acc) ->
catch throw:Err ->
close_read(R2),
Err;
- _:Reason ->
+ _:Reason:Stacktrace ->
close_read(R2),
- {error, {Reason, erlang:get_stacktrace()}}
+ {error, {Reason, Stacktrace}}
end
catch throw:{error,_} = Err ->
Err
@@ -198,9 +198,9 @@ do_read_schema_section(R) ->
try
{R3, RawSchema} = safe_apply(R2, read, [R2#restore.bup_data]),
do_read_schema_section(R3, verify_header(RawSchema), [])
- catch T:E ->
+ catch T:E:S ->
close_read(R2),
- erlang:raise(T,E,erlang:get_stacktrace())
+ erlang:raise(T,E,S)
end.
do_read_schema_section(R, {ok, B, C, []}, Acc) ->
@@ -920,7 +920,7 @@ create_dat_files([{schema, Tab, TabDef} | Tail], Ext, LocalTabs) ->
ok ->
ok;
{error, Reason} ->
- mnesia_lib:fatal("Cannot rename file ~p -> ~p: ~p~n",
+ mnesia_lib:fatal("Cannot rename file ~tp -> ~tp: ~tp~n",
[TmpFile, DclFile, Reason])
end
end
@@ -1016,7 +1016,7 @@ disc_only_swap_fun(disc_only_copies, Expunge, Open, Close) ->
ok ->
ok;
{error, Reason} ->
- mnesia_lib:fatal("Cannot rename file ~p -> ~p: ~p~n",
+ mnesia_lib:fatal("Cannot rename file ~tp -> ~tp: ~tp~n",
[TmpFile, DatFile, Reason])
end
end;
diff --git a/lib/mnesia/src/mnesia_checkpoint.erl b/lib/mnesia/src/mnesia_checkpoint.erl
index 8659e4622c..3273d3d27e 100644
--- a/lib/mnesia/src/mnesia_checkpoint.erl
+++ b/lib/mnesia/src/mnesia_checkpoint.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017
+%% Copyright Ericsson AB 1996-2018
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -683,14 +683,14 @@ retainer_create(_Cp, R, Tab, Name, Ext = {ext, Alias, Mod}) ->
Cs = val({Tab, cstruct}),
Mod:load_table(Alias, T, {retainer, create_table},
mnesia_schema:cs2list(Cs)),
- dbg_out("Checkpoint retainer created ~p ~p~n", [Name, Tab]),
+ dbg_out("Checkpoint retainer created ~p ~tp~n", [Name, Tab]),
R#retainer{store = {Ext, T}, really_retain = true};
retainer_create(_Cp, R, Tab, Name, disc_only_copies) ->
Fname = tab2retainer({Tab, Name}),
file:delete(Fname),
Args = [{file, Fname}, {type, set}, {keypos, 2}, {repair, false}],
{ok, _} = mnesia_lib:dets_sync_open({Tab, Name}, Args),
- dbg_out("Checkpoint retainer created ~p ~p~n", [Name, Tab]),
+ dbg_out("Checkpoint retainer created ~p ~tp~n", [Name, Tab]),
R#retainer{store = {dets, {Tab, Name}}, really_retain = true};
retainer_create(Cp, R, Tab, Name, Storage) ->
T = ?ets_new_table(mnesia_retainer, [set, public, {keypos, 2}]),
@@ -698,7 +698,7 @@ retainer_create(Cp, R, Tab, Name, Storage) ->
ReallyR = R#retainer.really_retain,
ReallyCp = lists:member(Tab, Overriders),
ReallyR2 = prepare_ram_tab(Tab, T, Storage, ReallyR, ReallyCp),
- dbg_out("Checkpoint retainer created ~p ~p~n", [Name, Tab]),
+ dbg_out("Checkpoint retainer created ~p ~tp~n", [Name, Tab]),
R#retainer{store = {ets, T}, really_retain = ReallyR2}.
%% Copy the dumped table into retainer if needed
@@ -849,7 +849,7 @@ retainer_loop(Cp = #checkpoint_args{is_activated=false, name=Name}) ->
retainer_loop(Cp#checkpoint_args{iterators = Iters});
{system, From, Msg} ->
- dbg_out("~p got {system, ~p, ~p}~n", [?MODULE, From, Msg]),
+ dbg_out("~p got {system, ~p, ~tp}~n", [?MODULE, From, Msg]),
sys:handle_system_msg(Msg, From, Cp#checkpoint_args.supervisor,
?MODULE, [], Cp)
end;
@@ -857,9 +857,9 @@ retainer_loop(Cp = #checkpoint_args{is_activated=false, name=Name}) ->
retainer_loop(Cp = #checkpoint_args{name=Name}) ->
receive
{_From, {retain, Tid, Tab, Key, OldRecs}} ->
- R = val({Tab, {retainer, Name}}),
+ R = ?catch_val({Tab, {retainer, Name}}),
PendingTab = Cp#checkpoint_args.pending_tab,
- case R#retainer.really_retain of
+ case is_record(R, retainer) andalso R#retainer.really_retain of
true ->
Store = R#retainer.store,
try true = ets:member(PendingTab, Tid),
@@ -938,11 +938,11 @@ retainer_loop(Cp = #checkpoint_args{name=Name}) ->
retainer_loop(Cp#checkpoint_args{iterators = Iters});
{system, From, Msg} ->
- dbg_out("~p got {system, ~p, ~p}~n", [?MODULE, From, Msg]),
+ dbg_out("~p got {system, ~p, ~tp}~n", [?MODULE, From, Msg]),
sys:handle_system_msg(Msg, From, Cp#checkpoint_args.supervisor,
?MODULE, [], Cp);
Msg ->
- dbg_out("~p got ~p~n", [?MODULE, Msg])
+ dbg_out("~p got ~tp~n", [?MODULE, Msg])
end.
maybe_activate(Cp)
@@ -1269,9 +1269,9 @@ system_code_change(Cp, _Module, _OldVsn, _Extra) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> mnesia_lib:other_val(Var);
- _VaLuE_ -> _VaLuE_
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
+ Value -> Value
end.
-
diff --git a/lib/mnesia/src/mnesia_controller.erl b/lib/mnesia/src/mnesia_controller.erl
index 6b93935cb4..882de0d613 100644
--- a/lib/mnesia/src/mnesia_controller.erl
+++ b/lib/mnesia/src/mnesia_controller.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -185,9 +185,10 @@ max_loaders() ->
worker_res
}).
+%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> mnesia_lib:other_val(Var);
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
Value -> Value
end.
@@ -446,7 +447,7 @@ try_schedule_late_disc_load(Tabs, Reason, MsgTag) ->
[BadNodes]),
try_schedule_late_disc_load(Tabs, Reason, MsgTag);
{aborted, AbortReason} ->
- fatal("Cannot late_load_tables~p: ~p~n",
+ fatal("Cannot late_load_tables ~tp: ~tp~n",
[[Tabs, Reason, MsgTag], AbortReason])
end.
@@ -535,7 +536,7 @@ try_merge_schema(Nodes, Told0, UserFun) ->
end,
try_merge_schema(Nodes, Told, UserFun);
{atomic, {"Cannot get cstructs", Node, Reason}} ->
- dbg_out("Cannot get cstructs, Node ~p ~p~n", [Node, Reason]),
+ dbg_out("Cannot get cstructs, Node ~p ~tp~n", [Node, Reason]),
timer:sleep(300), % Avoid a endless loop look alike
try_merge_schema(Nodes, Told0, UserFun);
{aborted, {shutdown, _}} -> %% One of the nodes is going down
@@ -771,22 +772,6 @@ handle_call({unannounce_add_table_copy, [Tab, Node], From}, ReplyTo, State) ->
noreply(State#state{early_msgs = [{call, Msg, undefined} | Msgs]})
end;
-handle_call({net_load, Tab, Cs}, From, State) ->
- State2 =
- case State#state.schema_is_merged of
- true ->
- Worker = #net_load{table = Tab,
- opt_reply_to = From,
- reason = {dumper,{add_table_copy, unknown}},
- cstruct = Cs
- },
- add_worker(Worker, State);
- false ->
- reply(From, {not_loaded, schema_not_merged}),
- State
- end,
- noreply(State2);
-
handle_call(Msg, From, State) when State#state.schema_is_merged /= true ->
%% Buffer early messages
Msgs = State#state.early_msgs,
@@ -826,12 +811,12 @@ handle_call({del_other, Who}, _From, State = #state{others=Others0}) ->
{reply, ok, State#state{others=Others}};
handle_call(Msg, _From, State) ->
- error("~p got unexpected call: ~p~n", [?SERVER_NAME, Msg]),
+ error("~p got unexpected call: ~tp~n", [?SERVER_NAME, Msg]),
noreply(State).
late_disc_load(TabsR, Reason, RemoteLoaders, From,
State = #state{loader_queue = LQ, late_loader_queue = LLQ}) ->
- verbose("Intend to load tables: ~p~n", [TabsR]),
+ verbose("Intend to load tables: ~tp~n", [TabsR]),
?eval_debug_fun({?MODULE, late_disc_load},
[{tabs, TabsR},
{reason, Reason},
@@ -1118,7 +1103,7 @@ handle_cast({adopt_orphans, Node, Tabs}, State) ->
noreply(State2);
handle_cast(Msg, State) ->
- error("~p got unexpected cast: ~p~n", [?SERVER_NAME, Msg]),
+ error("~p got unexpected cast: ~tp~n", [?SERVER_NAME, Msg]),
noreply(State).
handle_sync_tabs([Tab | Tabs], From) ->
@@ -1166,7 +1151,7 @@ handle_info(#dumper_done{worker_pid=Pid, worker_res=Res}, State) ->
State3 = opt_start_worker(State2),
noreply(State3);
true ->
- fatal("Dumper failed: ~p~n state: ~p~n", [Res, State]),
+ fatal("Dumper failed: ~p~n state: ~tp~n", [Res, State]),
{stop, fatal, State}
end;
@@ -1249,7 +1234,7 @@ handle_info(#sender_done{worker_pid=Pid, worker_res=Res}, State) ->
true ->
%% No need to send any message to the table receiver
%% since it will soon get a mnesia_down anyway
- fatal("Sender failed: ~p~n state: ~p~n", [Res, State]),
+ fatal("Sender failed: ~p~n state: ~tp~n", [Res, State]),
{stop, fatal, State}
end;
@@ -1257,7 +1242,7 @@ handle_info({'EXIT', Pid, R}, State) when Pid == State#state.supervisor ->
?SAFE(set(mnesia_status, stopping)),
case State#state.dumper_pid of
undefined ->
- dbg_out("~p was ~p~n", [?SERVER_NAME, R]),
+ dbg_out("~p was ~tp~n", [?SERVER_NAME, R]),
{stop, shutdown, State};
_ ->
noreply(State#state{is_stopping = true})
@@ -1266,12 +1251,12 @@ handle_info({'EXIT', Pid, R}, State) when Pid == State#state.supervisor ->
handle_info({'EXIT', Pid, R}, State) when Pid == State#state.dumper_pid ->
case State#state.dumper_queue of
[#schema_commit_lock{}|Workers] -> %% Schema trans crashed or was killed
- dbg_out("WARNING: Dumper ~p exited ~p~n", [Pid, R]),
+ dbg_out("WARNING: Dumper ~p exited ~tp~n", [Pid, R]),
State2 = State#state{dumper_queue = Workers, dumper_pid = undefined},
State3 = opt_start_worker(State2),
noreply(State3);
_Other ->
- fatal("Dumper or schema commit crashed: ~p~n state: ~p~n", [R, State]),
+ fatal("Dumper or schema commit crashed: ~p~n state: ~tp~n", [R, State]),
{stop, fatal, State}
end;
@@ -1280,15 +1265,15 @@ handle_info(Msg = {'EXIT', Pid, R}, State) when R /= wait_for_tables_timeout ->
true ->
%% No need to send any message to the table receiver
%% since it will soon get a mnesia_down anyway
- fatal("Sender crashed: ~p~n state: ~p~n", [{Pid,R}, State]),
+ fatal("Sender crashed: ~p~n state: ~tp~n", [{Pid,R}, State]),
{stop, fatal, State};
false ->
case lists:keymember(Pid, 1, get_loaders(State)) of
true ->
- fatal("Loader crashed: ~p~n state: ~p~n", [R, State]),
+ fatal("Loader crashed: ~p~n state: ~tp~n", [R, State]),
{stop, fatal, State};
false ->
- error("~p got unexpected info: ~p~n", [?SERVER_NAME, Msg]),
+ error("~p got unexpected info: ~tp~n", [?SERVER_NAME, Msg]),
noreply(State)
end
end;
@@ -1308,7 +1293,7 @@ handle_info({'EXIT', Pid, wait_for_tables_timeout}, State) ->
noreply(State);
handle_info(Msg, State) ->
- error("~p got unexpected info: ~p~n", [?SERVER_NAME, Msg]),
+ error("~p got unexpected info: ~tp~n", [?SERVER_NAME, Msg]),
noreply(State).
sync_tab_timeout(Pid, [{{sync_tab, Tab}, Pids} | Tail]) ->
@@ -1456,7 +1441,8 @@ orphan_tables([Tab | Tabs], Node, Ns, Local, Remote) ->
L = [Tab | Local],
orphan_tables(Tabs, Node, Ns, L, Remote);
Masters ->
- R = [{Tab, Masters} | Remote],
+ %% Do not disc_load table from RamCopyHolders
+ R = [{Tab, Masters -- RamCopyHolders} | Remote],
orphan_tables(Tabs, Node, Ns, Local, R)
end;
_ ->
@@ -2054,7 +2040,7 @@ opt_start_sender2([Sender|R], Pids, Kept, LoaderQ) ->
Pid = spawn_link(?MODULE, send_and_reply,[self(), Sender]),
opt_start_sender2(R,[{Pid,Sender}|Pids],Kept,LoaderQ);
true ->
- verbose("Send table failed ~p not active on this node ~n", [Tab]),
+ verbose("Send table failed ~tp not active on this node ~n", [Tab]),
Sender#send_table.receiver_pid ! {copier_done, node()},
opt_start_sender2(R,Pids, Kept, LoaderQ)
end.
@@ -2161,6 +2147,15 @@ load_table_fun(#net_load{cstruct=Cs, table=Tab, reason=Reason, opt_reply_to=Repl
{dumper,{add_table_copy,_}} -> true;
_ -> false
end,
+
+ OnlyRamCopies = case Cs of
+ #cstruct{disc_copies = DC,
+ disc_only_copies = DOC,
+ external_copies = Ext} ->
+ [] =:= (DC ++ (DOC ++ Ext)) -- [node()];
+ _ ->
+ false
+ end,
if
ReadNode == node() ->
%% Already loaded locally
@@ -2172,6 +2167,8 @@ load_table_fun(#net_load{cstruct=Cs, table=Tab, reason=Reason, opt_reply_to=Repl
end;
AccessMode == read_only, not AddTableCopy ->
fun() -> disc_load_table(Tab, Reason, ReplyTo) end;
+ Active =:= [], AddTableCopy, OnlyRamCopies ->
+ fun() -> disc_load_table(Tab, Reason, ReplyTo) end;
true ->
fun() ->
%% Either we cannot read the table yet
@@ -2239,7 +2236,7 @@ disc_load_table(Tab, Reason, ReplyTo) ->
Done#loader_done{is_loaded = false,
reply = Res};
true ->
- fatal("Cannot load table ~p from disc: ~p~n", [Tab, Res])
+ fatal("Cannot load table ~tp from disc: ~tp~n", [Tab, Res])
end.
filter_active(Tab) ->
diff --git a/lib/mnesia/src/mnesia_dumper.erl b/lib/mnesia/src/mnesia_dumper.erl
index eb02a585a6..a2880d6cf4 100644
--- a/lib/mnesia/src/mnesia_dumper.erl
+++ b/lib/mnesia/src/mnesia_dumper.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -191,9 +191,8 @@ do_perform_dump(Cont, InPlace, InitBy, Regulator, OldVersion) ->
try insert_recs(Recs, InPlace, InitBy, Regulator, OldVersion) of
Version ->
do_perform_dump(C2, InPlace, InitBy, Regulator, Version)
- catch _:R when R =/= fatal ->
- ST = erlang:get_stacktrace(),
- Reason = {"Transaction log dump error: ~p~n", [{R, ST}]},
+ catch _:R:ST when R =/= fatal ->
+ Reason = {"Transaction log dump error: ~tp~n", [{R, ST}]},
close_files(InPlace, {error, Reason}, InitBy),
exit(Reason)
end;
@@ -325,11 +324,10 @@ perform_update(Tid, SchemaOps, _DumperMode, _UseDir) ->
?eval_debug_fun({?MODULE, post_dump}, [InitBy]),
close_files(InPlace, ok, InitBy),
ok
- catch _:Reason when Reason =/= fatal ->
- ST = erlang:get_stacktrace(),
+ catch _:Reason:ST when Reason =/= fatal ->
Error = {error, {"Schema update error", {Reason, ST}}},
close_files(InPlace, Error, InitBy),
- fatal("Schema update error ~p ~p", [{Reason,ST}, SchemaOps])
+ fatal("Schema update error ~tp ~tp", [{Reason,ST}, SchemaOps])
end.
insert_ops(_Tid, _Storage, [], _InPlace, _InitBy, _) -> ok;
@@ -1166,7 +1164,7 @@ needs_dump_ets(Tab) ->
DcdF = mnesia_lib:tab2dcd(Tab),
case file:read_file_info(DcdF) of
{error, Reason} ->
- mnesia_lib:dbg_out("File ~p info_error ~p ~n",
+ mnesia_lib:dbg_out("File ~tp info_error ~tp ~n",
[DcdF, Reason]),
true;
{ok, DcdInfo} ->
@@ -1205,7 +1203,7 @@ prepare_open(Tab, UpdateInPlace) ->
Tmp = mnesia_lib:tab2tmp(Tab),
try ok = mnesia_lib:copy_file(Dat, Tmp)
catch error:Error ->
- fatal("Cannot copy dets file ~p to ~p: ~p~n",
+ fatal("Cannot copy dets file ~tp to ~tp: ~tp~n",
[Dat, Tmp, Error])
end,
Tmp
@@ -1441,7 +1439,7 @@ start_regulator() ->
{ok, Pid} ->
Pid;
{error, Reason} ->
- fatal("Failed to start ~n: ~p~n", [N, Reason])
+ fatal("Failed to start ~n: ~tp~n", [N, Reason])
end
end.
@@ -1471,8 +1469,9 @@ regulate(RegulatorPid) ->
{regulated, RegulatorPid} -> ok
end.
+%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> mnesia_lib:other_val(Var);
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
Value -> Value
end.
diff --git a/lib/mnesia/src/mnesia_event.erl b/lib/mnesia/src/mnesia_event.erl
index b06043bc61..49b3990086 100644
--- a/lib/mnesia/src/mnesia_event.erl
+++ b/lib/mnesia/src/mnesia_event.erl
@@ -103,11 +103,11 @@ handle_any_event({mnesia_system_event, Event}, State) ->
handle_any_event({mnesia_table_event, Event}, State) ->
handle_table_event(Event, State);
handle_any_event(Msg, State) ->
- report_error("~p got unexpected event: ~p~n", [?MODULE, Msg]),
+ report_error("~p got unexpected event: ~tp~n", [?MODULE, Msg]),
{ok, State}.
handle_table_event({Oper, Record, TransId}, State) ->
- report_info("~p performed by ~p on record:~n\t~p~n",
+ report_info("~p performed by ~p on record:~n\t~tp~n",
[Oper, TransId, Record]),
{ok, State}.
@@ -155,7 +155,7 @@ handle_system_event({mnesia_down, Node}, State) ->
end;
handle_system_event({mnesia_overload, Details}, State) ->
- report_warning("Mnesia is overloaded: ~w~n", [Details]),
+ report_warning("Mnesia is overloaded: ~tw~n", [Details]),
{ok, State};
handle_system_event({mnesia_info, Format, Args}, State) ->
@@ -175,16 +175,16 @@ handle_system_event({mnesia_fatal, Format, Args, BinaryCore}, State) ->
{ok, State#state{dumped_core = true}};
handle_system_event({inconsistent_database, Reason, Node}, State) ->
- report_error("mnesia_event got {inconsistent_database, ~w, ~w}~n",
+ report_error("mnesia_event got {inconsistent_database, ~tw, ~w}~n",
[Reason, Node]),
{ok, State};
handle_system_event({mnesia_user, Event}, State) ->
- report_info("User event: ~p~n", [Event]),
+ report_info("User event: ~tp~n", [Event]),
{ok, State};
handle_system_event(Msg, State) ->
- report_error("mnesia_event got unexpected system event: ~p~n", [Msg]),
+ report_error("mnesia_event got unexpected system event: ~tp~n", [Msg]),
{ok, State}.
report_info(Format0, Args0) ->
diff --git a/lib/mnesia/src/mnesia_frag.erl b/lib/mnesia/src/mnesia_frag.erl
index c39f30e140..8f7dd321b0 100644
--- a/lib/mnesia/src/mnesia_frag.erl
+++ b/lib/mnesia/src/mnesia_frag.erl
@@ -1,7 +1,7 @@
%%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1157,9 +1157,10 @@ remove_node(Node, Cs) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Helpers
+%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> mnesia_lib:other_val(Var);
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
Value -> Value
end.
diff --git a/lib/mnesia/src/mnesia_index.erl b/lib/mnesia/src/mnesia_index.erl
index c79f790973..098265d5fc 100644
--- a/lib/mnesia/src/mnesia_index.erl
+++ b/lib/mnesia/src/mnesia_index.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -155,7 +155,7 @@ del_object_bag_([IxK|IxKs], Found, Type, Tab, Key, Obj, Ixt) ->
bag ->
db_match_erase(Ixt, {IxK, Key});
ordered ->
- db_erase(Ixt, {{IxK, Key}})
+ db_erase(Ixt, {IxK, Key})
end;
_ ->
ok
@@ -420,7 +420,7 @@ make_ram_index(Tab, Storage, [Pos | Tail]) ->
add_ram_index(Tab, Storage, {Pos, _Pref}) ->
Type = ordered,
- verbose("Creating index for ~w ~p ~p~n", [Tab, Pos, Type]),
+ verbose("Creating index for ~tw ~p ~p~n", [Tab, Pos, Type]),
SetOrBag = val({Tab, setorbag}),
IxValsF = index_vals_f(Storage, Tab, Pos),
IxFun = fun(Val, Key) -> {{Val, Key}} end,
diff --git a/lib/mnesia/src/mnesia_late_loader.erl b/lib/mnesia/src/mnesia_late_loader.erl
index e273329ffc..45afda6e4b 100644
--- a/lib/mnesia/src/mnesia_late_loader.erl
+++ b/lib/mnesia/src/mnesia_late_loader.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -87,13 +87,13 @@ loop(State) ->
loop(State);
{system, From, Msg} ->
- mnesia_lib:dbg_out("~p got {system, ~p, ~p}~n",
+ mnesia_lib:dbg_out("~p got {system, ~p, ~tp}~n",
[?SERVER_NAME, From, Msg]),
Parent = State#state.supervisor,
sys:handle_system_msg(Msg, From, Parent, ?MODULE, [], State);
Msg ->
- mnesia_lib:error("~p got unexpected message: ~p~n",
+ mnesia_lib:error("~p got unexpected message: ~tp~n",
[?SERVER_NAME, Msg]),
loop(State)
end.
diff --git a/lib/mnesia/src/mnesia_lib.erl b/lib/mnesia/src/mnesia_lib.erl
index 1fdc656600..a884b8e086 100644
--- a/lib/mnesia/src/mnesia_lib.erl
+++ b/lib/mnesia/src/mnesia_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -116,7 +116,7 @@
lock_table/1,
mkcore/1,
not_active_here/1,
- other_val/1,
+ other_val/2,
overload_read/0,
overload_read/1,
overload_set/2,
@@ -435,8 +435,8 @@ validate_record(Tab, Obj) ->
%%
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> other_val(Var);
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> other_val(Var, Stacktrace);
_VaLuE_ -> _VaLuE_
end.
@@ -446,9 +446,9 @@ set(Var, Val) ->
unset(Var) ->
?ets_delete(mnesia_gvar, Var).
-other_val(Var) ->
+other_val(Var, Stacktrace) ->
case other_val_1(Var) of
- error -> pr_other(Var);
+ error -> pr_other(Var, Stacktrace);
Val -> Val
end.
@@ -460,16 +460,16 @@ other_val_1(Var) ->
_ -> error
end.
--spec pr_other(_) -> no_return().
-pr_other(Var) ->
+-spec pr_other(_, _) -> no_return().
+pr_other(Var, Stacktrace) ->
Why =
case is_running() of
no -> {node_not_running, node()};
_ -> {no_exists, Var}
end,
- verbose("~p (~p) val(mnesia_gvar, ~w) -> ~p ~p ~n",
+ verbose("~p (~tp) val(mnesia_gvar, ~tw) -> ~p ~tp ~n",
[self(), process_info(self(), registered_name),
- Var, Why, erlang:get_stacktrace()]),
+ Var, Why, Stacktrace]),
mnesia:abort(Why).
%% Some functions for list valued variables
@@ -654,7 +654,7 @@ coredump() ->
coredump(CrashInfo) ->
Core = mkcore(CrashInfo),
Out = core_file(),
- important("Writing Mnesia core to file: ~p...~p~n", [Out, CrashInfo]),
+ important("Writing Mnesia core to file: ~tp...~tp~n", [Out, CrashInfo]),
_ = file:write_file(Out, Core),
Out.
@@ -844,7 +844,7 @@ vcore() ->
case file:list_dir(Cwd) of
{ok, Files}->
CoreFiles = lists:sort(lists:zf(Filter, Files)),
- show("Mnesia core files: ~p~n", [CoreFiles]),
+ show("Mnesia core files: ~tp~n", [CoreFiles]),
vcore(lists:last(CoreFiles));
Error ->
Error
@@ -853,17 +853,17 @@ vcore() ->
vcore(Bin) when is_binary(Bin) ->
Core = binary_to_term(Bin),
Fun = fun({Item, Info}) ->
- show("***** ~p *****~n", [Item]),
+ show("***** ~tp *****~n", [Item]),
case catch vcore_elem({Item, Info}) of
{'EXIT', Reason} ->
- show("{'EXIT', ~p}~n", [Reason]);
+ show("{'EXIT', ~tp}~n", [Reason]);
_ -> ok
end
end,
lists:foreach(Fun, Core);
vcore(File) ->
- show("~n***** Mnesia core: ~p *****~n", [File]),
+ show("~n***** Mnesia core: ~tp *****~n", [File]),
case file:read_file(File) of
{ok, Bin} ->
vcore(Bin);
@@ -879,7 +879,7 @@ vcore_elem({schema_file, {ok, B}}) ->
vcore_elem({logfile, {ok, BinList}}) ->
Fun = fun({F, Info}) ->
- show("----- logfile: ~p -----~n", [F]),
+ show("----- logfile: ~tp -----~n", [F]),
case Info of
{ok, B} ->
Fname = "/tmp/mnesia_vcore_elem.TMP",
@@ -887,7 +887,7 @@ vcore_elem({logfile, {ok, BinList}}) ->
mnesia_log:view(Fname),
file:delete(Fname);
_ ->
- show("~p~n", [Info])
+ show("~tp~n", [Info])
end
end,
lists:foreach(Fun, BinList);
@@ -895,12 +895,12 @@ vcore_elem({logfile, {ok, BinList}}) ->
vcore_elem({crashinfo, {Format, Args}}) ->
show(Format, Args);
vcore_elem({gvar, L}) ->
- show("~p~n", [lists:sort(L)]);
+ show("~tp~n", [lists:sort(L)]);
vcore_elem({transactions, Info}) ->
mnesia_tm:display_info(user, Info);
vcore_elem({_Item, Info}) ->
- show("~p~n", [Info]).
+ show("~tp~n", [Info]).
fix_error(X) ->
set(last_error, X), %% for debugabililty
@@ -1018,7 +1018,7 @@ report_system_event({'EXIT', Reason}, Event) ->
end;
Error ->
- Msg = "Mnesia(~p): Cannot report event ~p: ~p (~p)~n",
+ Msg = "Mnesia(~tp): Cannot report event ~tp: ~tp (~tp)~n",
error_logger:format(Msg, [node(), Event, Reason, Error])
end,
ok;
diff --git a/lib/mnesia/src/mnesia_loader.erl b/lib/mnesia/src/mnesia_loader.erl
index c710470a2c..2cdae0c906 100644
--- a/lib/mnesia/src/mnesia_loader.erl
+++ b/lib/mnesia/src/mnesia_loader.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,9 +34,10 @@
-include("mnesia.hrl").
+%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> mnesia_lib:other_val(Var);
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
Value -> Value
end.
@@ -46,7 +47,7 @@ val(Var) ->
disc_load_table(Tab, Reason) ->
Storage = val({Tab, storage_type}),
Type = val({Tab, setorbag}),
- dbg_out("Getting table ~p (~p) from disc: ~p~n",
+ dbg_out("Getting table ~tp (~p) from disc: ~tp~n",
[Tab, Storage, Reason]),
?eval_debug_fun({?MODULE, do_get_disc_copy},
[{tab, Tab},
@@ -56,7 +57,7 @@ disc_load_table(Tab, Reason) ->
do_get_disc_copy2(Tab, Reason, Storage, Type).
do_get_disc_copy2(Tab, _Reason, Storage, _Type) when Storage == unknown ->
- verbose("Local table copy of ~p has recently been deleted, ignored.~n",
+ verbose("Local table copy of ~tp has recently been deleted, ignored.~n",
[Tab]),
{not_loaded, storage_unknown};
do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_copies ->
@@ -66,7 +67,7 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_copies ->
EtsOpts = proplists:get_value(ets, StorageProps, []),
Args = [{keypos, 2}, public, named_table, Type | EtsOpts],
case Reason of
- {dumper, _} -> %% Resources already allocated
+ {dumper, DR} when is_atom(DR) -> %% Resources already allocated
ignore;
_ ->
mnesia_monitor:mktab(Tab, Args),
@@ -90,8 +91,8 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == ram_copies ->
EtsOpts = proplists:get_value(ets, StorageProps, []),
Args = [{keypos, 2}, public, named_table, Type | EtsOpts],
case Reason of
- {dumper, _} -> %% Resources allready allocated
- ignore;
+ {dumper, DR} when is_atom(DR) ->
+ ignore; %% Resources already allocated
_ ->
mnesia_monitor:mktab(Tab, Args),
Fname = mnesia_lib:tab2dcd(Tab),
@@ -130,7 +131,7 @@ do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_only_copies -
{repair, mnesia_monitor:get_env(auto_repair)}
| DetsOpts],
case Reason of
- {dumper, _} ->
+ {dumper, DR} when is_atom(DR) ->
mnesia_index:init_index(Tab, Storage),
snmpify(Tab, Storage),
set({Tab, load_node}, node()),
@@ -199,20 +200,20 @@ net_load_table(Tab, Reason, Ns, _Cs) ->
try_net_load_table(Tab, Reason, Ns, val({Tab, cstruct})).
try_net_load_table(Tab, _Reason, [], _Cs) ->
- verbose("Copy failed. No active replicas of ~p are available.~n", [Tab]),
+ verbose("Copy failed. No active replicas of ~tp are available.~n", [Tab]),
{not_loaded, none_active};
try_net_load_table(Tab, Reason, Ns, Cs) ->
Storage = mnesia_lib:cs_to_storage_type(node(), Cs),
do_get_network_copy(Tab, Reason, Ns, Storage, Cs).
do_get_network_copy(Tab, _Reason, _Ns, unknown, _Cs) ->
- verbose("Local table copy of ~p has recently been deleted, ignored.~n", [Tab]),
+ verbose("Local table copy of ~tp has recently been deleted, ignored.~n", [Tab]),
{not_loaded, storage_unknown};
do_get_network_copy(Tab, Reason, Ns, Storage, Cs) ->
[Node | Tail] = Ns,
case lists:member(Node,val({current, db_nodes})) of
true ->
- dbg_out("Getting table ~p (~p) from node ~p: ~p~n",
+ dbg_out("Getting table ~tp (~p) from node ~p: ~tp~n",
[Tab, Storage, Node, Reason]),
?eval_debug_fun({?MODULE, do_get_network_copy},
[{tab, Tab}, {reason, Reason},
@@ -222,7 +223,7 @@ do_get_network_copy(Tab, Reason, Ns, Storage, Cs) ->
set({Tab, load_node}, Node),
set({Tab, load_reason}, Reason),
mnesia_controller:i_have_tab(Tab),
- dbg_out("Table ~p copied from ~p to ~p~n", [Tab, Node, node()]),
+ dbg_out("Table ~tp copied from ~p to ~p~n", [Tab, Node, node()]),
{loaded, ok};
Err = {error, _} when element(1, Reason) == dumper ->
{not_loaded,Err};
@@ -286,12 +287,12 @@ init_receiver(Node, Tab,Storage,Cs,Reason) ->
element(1,Reason) == dumper ->
{error,Result};
{atomic, {error,Result}} ->
- fatal("Cannot create table ~p: ~p~n",
+ fatal("Cannot create table ~tp: ~tp~n",
[[Tab, Storage], Result]);
{atomic, Result} -> Result;
{aborted, nomore} -> restart;
{aborted, _Reas} ->
- verbose("Receiver failed on ~p from ~p:~nReason: ~p~n",
+ verbose("Receiver failed on ~tp from ~p:~nReason: ~tp~n",
[Tab,Node,_Reas]),
down %% either this node or sender is dying
end,
@@ -313,7 +314,7 @@ start_remote_sender(Node,Tab,Storage) ->
{SenderPid, TabSize, DetsData};
%% Protocol conversion hack
{copier_done, Node} ->
- verbose("Sender of table ~p crashed on node ~p ~n", [Tab, Node]),
+ verbose("Sender of table ~tp crashed on node ~p ~n", [Tab, Node]),
down(Tab, Storage)
end.
@@ -374,7 +375,7 @@ do_init_table(Tab,Storage,Cs,SenderPid,
tab_receiver(Node,Tab,Storage,Cs,OrigTabRec);
Reason ->
Msg = "[d]ets:init table failed",
- verbose("~s: ~p: ~p~n", [Msg, Tab, Reason]),
+ verbose("~ts: ~tp: ~tp~n", [Msg, Tab, Reason]),
down(Tab, Storage)
end;
Error ->
@@ -432,7 +433,7 @@ tab_receiver(Node, Tab, Storage, Cs, OrigTabRec) ->
%% Protocol conversion hack
{copier_done, Node} ->
- verbose("Sender of table ~p crashed on node ~p ~n", [Tab, Node]),
+ verbose("Sender of table ~tp crashed on node ~p ~n", [Tab, Node]),
down(Tab, Storage);
{'EXIT', Pid, Reason} ->
@@ -490,7 +491,7 @@ ext_load_table(Mod, Alias, Tab, Reason) ->
ext_init_table(Action, Alias, Mod, Tab, Fun, State, Sender) ->
case Fun(Action) of
{copier_done, Node} ->
- verbose("Receiver of table ~p crashed on ~p (more)~n", [Tab, Node]),
+ verbose("Receiver of table ~tp crashed on ~p (more)~n", [Tab, Node]),
down(Tab, {ext,Alias,Mod});
{Data, NewFun} ->
case Mod:receive_data(Data, Alias, Tab, Sender, State) of
@@ -535,7 +536,7 @@ init_table(Tab, _, Fun, _DetsInfo,_) ->
try
true = ets:init_table(Tab, Fun),
ok
- catch _:Else -> {Else, erlang:get_stacktrace()}
+ catch _:Else:Stacktrace -> {Else, Stacktrace}
end.
@@ -553,7 +554,7 @@ finish_copy(Storage,Tab,Cs,SenderPid,DatBin,OrigTabRec) ->
ok;
{error, Reason} ->
Msg = "Failed to handle last",
- verbose("~s: ~p: ~p~n", [Msg, Tab, Reason]),
+ verbose("~ts: ~tp: ~tp~n", [Msg, Tab, Reason]),
down(Tab, Storage)
end.
@@ -777,9 +778,9 @@ do_send_table(Pid, Tab, Storage, RemoteS) ->
throw:receiver_died ->
cleanup_tab_copier(Pid, Storage, Tab),
ok;
- error:Reason -> %% Prepare failed
+ error:Reason:Stacktrace -> %% Prepare failed
cleanup_tab_copier(Pid, Storage, Tab),
- {error, {tab_copier, Tab, {Reason, erlang:get_stacktrace()}}}
+ {error, {tab_copier, Tab, {Reason, Stacktrace}}}
after
unlink(whereis(mnesia_tm))
end.
@@ -859,7 +860,7 @@ send_more(Pid, N, Chunk, DataState, Tab, Storage) ->
send_more(Pid, 1, NewChunk, Init(), Tab, Storage);
{copier_done, Node} when Node == node(Pid)->
- verbose("Receiver of table ~p crashed on ~p (more)~n", [Tab, Node]),
+ verbose("Receiver of table ~tp crashed on ~p (more)~n", [Tab, Node]),
throw(receiver_died)
end.
@@ -937,7 +938,7 @@ finish_copy(Pid, Tab, Storage, RemoteS, NeedLock) ->
{Pid, no_more} -> % Dont bother about the spurious 'more' message
no_more;
{copier_done, Node} ->
- verbose("Tab receiver ~p crashed (more): ~p~n", [Tab, Node]),
+ verbose("Tab receiver ~tp crashed (more): ~p~n", [Tab, Node]),
receiver_died
end
end,
diff --git a/lib/mnesia/src/mnesia_locker.erl b/lib/mnesia/src/mnesia_locker.erl
index 59fd89059f..f68626413e 100644
--- a/lib/mnesia/src/mnesia_locker.erl
+++ b/lib/mnesia/src/mnesia_locker.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -97,10 +97,11 @@ init(Parent) ->
end,
loop(#state{supervisor = Parent}).
+%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> mnesia_lib:other_val(Var);
- _VaLuE_ -> _VaLuE_
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
+ Value -> Value
end.
reply(From, R) ->
@@ -245,7 +246,7 @@ loop(State) ->
do_stop();
{system, From, Msg} ->
- verbose("~p got {system, ~p, ~p}~n", [?MODULE, From, Msg]),
+ verbose("~p got {system, ~p, ~tp}~n", [?MODULE, From, Msg]),
Parent = State#state.supervisor,
sys:handle_system_msg(Msg, From, Parent, ?MODULE, [], State);
@@ -254,7 +255,7 @@ loop(State) ->
loop(State);
Msg ->
- error("~p got unexpected message: ~p~n", [?MODULE, Msg]),
+ error("~p got unexpected message: ~tp~n", [?MODULE, Msg]),
loop(State)
end.
diff --git a/lib/mnesia/src/mnesia_log.erl b/lib/mnesia/src/mnesia_log.erl
index 9536effd42..03411ace41 100644
--- a/lib/mnesia/src/mnesia_log.erl
+++ b/lib/mnesia/src/mnesia_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -310,7 +310,7 @@ verify_no_exists(Fname) ->
false ->
ok;
true ->
- fatal("Log file exists: ~p~n", [Fname])
+ fatal("Log file exists: ~tp~n", [Fname])
end.
open_log(Name, Header, Fname) ->
@@ -331,7 +331,7 @@ open_log(Name, Header, Fname, Exists, Repair) ->
open_log(Name, Header, Fname, Exists, Repair, Mode) ->
Args = [{file, Fname}, {name, Name}, {repair, Repair}, {mode, Mode}],
-%% io:format("~p:open_log: ~p ~p~n", [?MODULE, Name, Fname]),
+%% io:format("~p:open_log: ~tp ~tp~n", [?MODULE, Name, Fname]),
case mnesia_monitor:open_log(Args) of
{ok, Log} when Exists == true ->
Log;
@@ -344,19 +344,19 @@ open_log(Name, Header, Fname, Exists, Repair, Mode) ->
write_header(Log, Header),
Log;
{repaired, Log, _Recover, BadBytes} ->
- mnesia_lib:important("Data may be missing, log ~p repaired: Lost ~p bytes~n",
+ mnesia_lib:important("Data may be missing, log ~tp repaired: Lost ~p bytes~n",
[Fname, BadBytes]),
Log;
{error, Reason = {file_error, _Fname, emfile}} ->
- fatal("Cannot open log file ~p: ~p~n", [Fname, Reason]);
+ fatal("Cannot open log file ~tp: ~tp~n", [Fname, Reason]);
{error, Reason} when Repair == true ->
file:delete(Fname),
- mnesia_lib:important("Data may be missing, Corrupt logfile deleted: ~p, ~p ~n",
+ mnesia_lib:important("Data may be missing, Corrupt logfile deleted: ~tp, ~tp ~n",
[Fname, Reason]),
%% Create a new
open_log(Name, Header, Fname, false, false, read_write);
{error, Reason} ->
- fatal("Cannot open log file ~p: ~p~n", [Fname, Reason])
+ fatal("Cannot open log file ~tp: ~tp~n", [Fname, Reason])
end.
write_header(Log, Header) ->
@@ -381,7 +381,7 @@ close_log(Log) ->
{error, {read_only_mode, Log}} ->
ok;
{error, Reason} ->
- mnesia_lib:important("Failed syncing ~p to_disk reason ~p ~n",
+ mnesia_lib:important("Failed syncing ~tp to_disk reason ~tp ~n",
[Log, Reason])
end,
mnesia_monitor:close_log(Log).
@@ -464,13 +464,13 @@ chunk_log(_Log, eof) ->
chunk_log(Log, Cont) ->
case disk_log:chunk(Log, Cont) of
{error, Reason} ->
- fatal("Possibly truncated ~p file: ~p~n",
+ fatal("Possibly truncated ~tp file: ~tp~n",
[Log, Reason]);
{C2, Chunk, _BadBytes} ->
%% Read_only case, should we warn about the bad log file?
%% BUGBUG Should we crash if Repair == false ??
%% We got to check this !!
- mnesia_lib:important("~p repaired, lost ~p bad bytes~n", [Log, _BadBytes]),
+ mnesia_lib:important("~tp repaired, lost ~p bad bytes~n", [Log, _BadBytes]),
{C2, Chunk};
Other ->
Other
@@ -505,7 +505,7 @@ prepare_decision_log_dump(false, Prev) ->
ok ->
prepare_decision_log_dump(true, Prev);
{error, Reason} ->
- fatal("Cannot rename decision log file ~p -> ~p: ~p~n",
+ fatal("Cannot rename decision log file ~tp -> ~tp: ~tp~n",
[decision_log_file(), Prev, Reason])
end;
prepare_decision_log_dump(true, Prev) ->
@@ -522,7 +522,7 @@ confirm_decision_log_dump() ->
ok ->
file:delete(previous_decision_log_file());
{error, Reason} ->
- fatal("Cannot confirm decision log dump: ~p~n",
+ fatal("Cannot confirm decision log dump: ~tp~n",
[Reason])
end.
@@ -561,7 +561,7 @@ view() ->
lists:foreach(fun(F) -> view(F) end, log_files()).
view(File) ->
- mnesia_lib:show("***** ~p ***** ~n", [File]),
+ mnesia_lib:show("***** ~tp ***** ~n", [File]),
case exists(File) of
false ->
nolog;
@@ -574,25 +574,25 @@ view(File) ->
{repaired, _, _, _} ->
view_file(start, N);
{error, Reason} ->
- error("Cannot open log ~p: ~p~n", [File, Reason])
+ error("Cannot open log ~tp: ~tp~n", [File, Reason])
end
end.
view_file(C, Log) ->
case disk_log:chunk(Log, C) of
{error, Reason} ->
- error("** Possibly truncated FILE ~p~n", [Reason]),
+ error("** Possibly truncated FILE ~tp~n", [Reason]),
error;
eof ->
disk_log:close(Log),
eof;
{C2, Terms, _BadBytes} ->
- dbg_out("Lost ~p bytes in ~p ~n", [_BadBytes, Log]),
- lists:foreach(fun(X) -> mnesia_lib:show("~p~n", [X]) end,
+ dbg_out("Lost ~p bytes in ~tp ~n", [_BadBytes, Log]),
+ lists:foreach(fun(X) -> mnesia_lib:show("~tp~n", [X]) end,
Terms),
view_file(C2, Log);
{C2, Terms} ->
- lists:foreach(fun(X) -> mnesia_lib:show("~p~n", [X]) end,
+ lists:foreach(fun(X) -> mnesia_lib:show("~tp~n", [X]) end,
Terms),
view_file(C2, Log)
end.
@@ -750,12 +750,12 @@ abort_write_fun(B, What, Args) ->
abort_write(B, What, Args, Reason) ->
Mod = B#backup_args.module,
Opaque = B#backup_args.opaque,
- dbg_out("Failed to perform backup. M=~p:F=~p:A=~p -> ~p~n",
+ dbg_out("Failed to perform backup. M=~p:F=~tp:A=~tp -> ~tp~n",
[Mod, What, Args, Reason]),
- try apply(Mod, abort_write, [Opaque]) of
- {ok, _Res} -> throw({error, Reason})
+ try {ok, _Res} = apply(Mod, abort_write, [Opaque]) of
+ _ -> throw({error, Reason})
catch _:Other ->
- error("Failed to abort backup. ~p:~p~p -> ~p~n",
+ error("Failed to abort backup. ~p:~tp~tp -> ~tp~n",
[Mod, abort_write, [Opaque], Other]),
throw({error, Reason})
end.
@@ -802,7 +802,7 @@ select_source(Tab, Name, PrevName) ->
{PrevName, retainer};
_ ->
%% Do a full backup anyway
- dbg_out("Incremental backup escalated to full backup: ~p~n", [Tab]),
+ dbg_out("Incremental backup escalated to full backup: ~tp~n", [Tab]),
{Name, table}
end
end.
diff --git a/lib/mnesia/src/mnesia_monitor.erl b/lib/mnesia/src/mnesia_monitor.erl
index 22a24b6dc9..4cfe16dec0 100644
--- a/lib/mnesia/src/mnesia_monitor.erl
+++ b/lib/mnesia/src/mnesia_monitor.erl
@@ -178,10 +178,10 @@ check_protocol([{Node, {reject, _Mon, Version, Protocol}} | Tail], Protocols) ->
[Node, Protocols, Version, Protocol]),
check_protocol(Tail, Protocols);
check_protocol([{error, _Reason} | Tail], Protocols) ->
- dbg_out("~p connect failed error: ~p~n", [?MODULE, _Reason]),
+ dbg_out("~p connect failed error: ~tp~n", [?MODULE, _Reason]),
check_protocol(Tail, Protocols);
check_protocol([{badrpc, _Reason} | Tail], Protocols) ->
- dbg_out("~p connect failed badrpc: ~p~n", [?MODULE, _Reason]),
+ dbg_out("~p connect failed badrpc: ~tp~n", [?MODULE, _Reason]),
check_protocol(Tail, Protocols);
check_protocol([], [Protocol | _Protocols]) ->
set(protocol_version, Protocol),
@@ -246,10 +246,10 @@ start_proc(Who, Mod, Fun, Args) ->
proc_lib:start_link(mnesia_sp, init_proc, Args2, infinity).
terminate_proc(Who, R, State) when R /= shutdown, R /= killed ->
- fatal("~p crashed: ~p state: ~p~n", [Who, R, State]);
+ fatal("~p crashed: ~p state: ~tp~n", [Who, R, State]);
terminate_proc(Who, Reason, _State) ->
- mnesia_lib:verbose("~p terminated: ~p~n", [Who, Reason]),
+ mnesia_lib:verbose("~p terminated: ~tp~n", [Who, Reason]),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -294,7 +294,7 @@ init([Parent]) ->
{ok, #state{supervisor = Parent}}
catch _:Reason ->
- mnesia_lib:report_fatal("Bad configuration: ~p~n", [Reason]),
+ mnesia_lib:report_fatal("Bad configuration: ~tp~n", [Reason]),
{stop, {bad_config, Reason}}
end.
@@ -333,7 +333,7 @@ handle_call({mktab, Tab, Args}, _From, State) ->
catch error:ExitReason ->
Msg = "Cannot create ets table",
Reason = {system_limit, Msg, Tab, Args, ExitReason},
- fatal("~p~n", [Reason]),
+ fatal("~tp~n", [Reason]),
{noreply, State}
end;
@@ -353,7 +353,7 @@ handle_call({open_dets, Tab, Args}, _From, State) ->
{error, Reason} ->
Msg = "Cannot open dets table",
Error = {error, {Msg, Tab, Args, Reason}},
- fatal("~p~n", [Error]),
+ fatal("~tp~n", [Error]),
{noreply, State}
end;
@@ -385,7 +385,7 @@ handle_call({reopen_log, Name, Fname, Head}, _From, State) ->
{error, Reason} ->
Msg = "Cannot rename disk_log file",
Error = {error, {Msg, Name, Fname, Head, Reason}},
- fatal("~p~n", [Error]),
+ fatal("~tp~n", [Error]),
{noreply, State}
end;
@@ -400,7 +400,7 @@ handle_call({close_log, Name}, _From, State) ->
{error, Reason} ->
Msg = "Cannot close disk_log file",
Error = {error, {Msg, Name, Reason}},
- fatal("~p~n", [Error]),
+ fatal("~tp~n", [Error]),
{noreply, State}
end;
@@ -461,7 +461,7 @@ handle_call(init, _From, State) ->
{reply, EarlyNodes, State2};
handle_call(Msg, _From, State) ->
- error("~p got unexpected call: ~p~n", [?MODULE, Msg]),
+ error("~p got unexpected call: ~tp~n", [?MODULE, Msg]),
{noreply, State}.
accept_protocol(Mon, Version, Protocol, From, State) ->
@@ -535,7 +535,7 @@ handle_cast({inconsistent_database, Context, Node}, State) ->
{noreply, State};
handle_cast(Msg, State) ->
- error("~p got unexpected cast: ~p~n", [?MODULE, Msg]),
+ error("~p got unexpected cast: ~tp~n", [?MODULE, Msg]),
{noreply, State}.
%%----------------------------------------------------------------------
@@ -572,7 +572,7 @@ handle_info(Msg = {'EXIT',Pid,_}, State) ->
%% We have probably got an exit signal from
%% disk_log or dets
Hint = "Hint: check that the disk still is writable",
- fatal("~p got unexpected info: ~p; ~p~n",
+ fatal("~p got unexpected info: ~tp; ~p~n",
[?MODULE, Msg, Hint])
end;
@@ -599,13 +599,13 @@ handle_info({disk_log, _Node, Log, Info}, State) ->
{truncated, _No} ->
ok;
_ ->
- mnesia_lib:important("Warning Log file ~p error reason ~s~n",
+ mnesia_lib:important("Warning Log file ~tp error reason ~ts~n",
[Log, disk_log:format_error(Info)])
end,
{noreply, State};
handle_info(Msg, State) ->
- error("~p got unexpected info (~p): ~p~n", [?MODULE, State, Msg]).
+ error("~p got unexpected info (~tp): ~tp~n", [?MODULE, State, Msg]).
process_q(State = #state{mq=[]}) -> {noreply,State};
process_q(State = #state{mq=[{info,Msg}|R]}) ->
diff --git a/lib/mnesia/src/mnesia_recover.erl b/lib/mnesia/src/mnesia_recover.erl
index b204fb282f..2ccea1ea6d 100644
--- a/lib/mnesia/src/mnesia_recover.erl
+++ b/lib/mnesia/src/mnesia_recover.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -177,10 +177,10 @@ disconnect(Node) ->
log_decision(D) ->
cast({log_decision, D}).
+%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _Reason} ->
- mnesia_lib:other_val(Var);
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
Value -> Value
end.
@@ -762,7 +762,7 @@ handle_call(sync, _From, State) ->
{reply, ok, State};
handle_call(Msg, _From, State) ->
- error("~p got unexpected call: ~p~n", [?MODULE, Msg]),
+ error("~p got unexpected call: ~tp~n", [?MODULE, Msg]),
{noreply, State}.
do_log_mnesia_up(Node) ->
@@ -881,7 +881,7 @@ handle_cast({log_dump_overload, Flag}, State) when is_boolean(Flag) ->
{noreply, State#state{log_dump_overload = Flag}};
handle_cast(Msg, State) ->
- error("~p got unexpected cast: ~p~n", [?MODULE, Msg]),
+ error("~p got unexpected cast: ~tp~n", [?MODULE, Msg]),
{noreply, State}.
%%----------------------------------------------------------------------
@@ -927,11 +927,11 @@ handle_info({force_decision, Tid}, State) ->
end;
handle_info({'EXIT', Pid, R}, State) when Pid == State#state.supervisor ->
- mnesia_lib:dbg_out("~p was ~p~n",[?MODULE, R]),
+ mnesia_lib:dbg_out("~p was ~tp~n",[?MODULE, R]),
{stop, shutdown, State};
handle_info(Msg, State) ->
- error("~p got unexpected info: ~p~n", [?MODULE, Msg]),
+ error("~p got unexpected info: ~tp~n", [?MODULE, Msg]),
{noreply, State}.
%%----------------------------------------------------------------------
diff --git a/lib/mnesia/src/mnesia_schema.erl b/lib/mnesia/src/mnesia_schema.erl
index f71ee26d7c..ef38adca1e 100644
--- a/lib/mnesia/src/mnesia_schema.erl
+++ b/lib/mnesia/src/mnesia_schema.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -181,9 +181,10 @@ exit_on_error({error, Reason}) ->
exit_on_error(GoodRes) ->
GoodRes.
+%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> mnesia_lib:other_val(Var);
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
Value -> Value
end.
@@ -386,7 +387,7 @@ delete_schema(Ns) when is_list(Ns), Ns /= [] ->
[] ->
ok;
BadReplies ->
- verbose("~s: ~p~n", [Reason, BadReplies]),
+ verbose("~s: ~tp~n", [Reason, BadReplies]),
{error, {"All nodes not running", BadReplies}}
end;
{_Replies, BadNs} ->
@@ -467,10 +468,10 @@ opt_create_dir(UseDir, Dir) when UseDir == true->
false ->
case file:make_dir(Dir) of
ok ->
- verbose("Create Directory ~p~n", [Dir]),
+ verbose("Create Directory ~tp~n", [Dir]),
ok;
{error, Reason} ->
- verbose("Cannot create mnesia dir ~p~n", [Reason]),
+ verbose("Cannot create mnesia dir ~tp~n", [Reason]),
{error, {"Cannot create Mnesia dir", Dir, Reason}}
end
end;
@@ -952,19 +953,9 @@ get_index_plugins() ->
get_schema_user_property(mnesia_index_plugins).
get_schema_user_property(Key) ->
- Tab = schema,
- %% Must work reliably both within transactions and outside of transactions
- Res = case get(mnesia_activity_state) of
- undefined ->
- dirty_read_table_property(Tab, Key);
- _ ->
- do_read_table_property(Tab, Key)
- end,
- case Res of
- undefined ->
- [];
- {_, Types} ->
- Types
+ case dirty_read_table_property(schema, Key) of
+ undefined -> [];
+ {_, Types} -> Types
end.
get_ext_types_disc() ->
@@ -1470,7 +1461,7 @@ verify_backend_type(Name, Module) ->
[] ->
ok;
_Other ->
- io:fwrite(user, "Missing backend_type exports: ~p~n", [_Other]),
+ io:fwrite(user, "Missing backend_type exports: ~tp~n", [_Other]),
mnesia:abort({bad_type, {backend_type,Name,Module}})
end.
@@ -1776,7 +1767,7 @@ make_del_table_copy(Tab, Node) ->
mnesia:abort({combine_error, Tab, "Last replica"});
[] ->
ensure_active(Cs),
- dbg_out("Last replica deleted in table ~p~n", [Tab]),
+ dbg_out("Last replica deleted in table ~tp~n", [Tab]),
make_delete_table(Tab, whole_table);
_ when Tab == schema ->
%% ensure_active(Cs2),
@@ -2178,13 +2169,13 @@ do_write_table_property(Tab, Prop) ->
case change_prop_in_existing_op(Tab, Prop, write_property, Store) of
true ->
dbg_out("change_prop_in_existing_op"
- "(~p,~p,write_property,Store) -> true~n",
+ "(~tp,~p,write_property,Store) -> true~n",
[Tab,Prop]),
%% we have merged the table prop into the create_table op
ok;
false ->
dbg_out("change_prop_in_existing_op"
- "(~p,~p,write_property,Store) -> false~n",
+ "(~tp,~p,write_property,Store) -> false~n",
[Tab,Prop]),
%% this must be an existing table
get_tid_ts_and_lock(Tab, none),
@@ -2315,13 +2306,13 @@ do_delete_table_property(Tab, PropKey) ->
case change_prop_in_existing_op(Tab, PropKey, delete_property, Store) of
true ->
dbg_out("change_prop_in_existing_op"
- "(~p,~p,delete_property,Store) -> true~n",
+ "(~tp,~p,delete_property,Store) -> true~n",
[Tab,PropKey]),
%% we have merged the table prop into the create_table op
ok;
false ->
dbg_out("change_prop_in_existing_op"
- "(~p,~p,delete_property,Store) -> false~n",
+ "(~tp,~p,delete_property,Store) -> false~n",
[Tab,PropKey]),
%% this must be an existing table
get_tid_ts_and_lock(Tab, none),
@@ -2435,17 +2426,17 @@ prepare_op(_Tid, {op, sync_trans}, {part, CoordPid}) ->
{sync_trans, CoordPid} ->
{false, optional};
{mnesia_down, _Node} = Else ->
- mnesia_lib:verbose("sync_op terminated due to ~p~n", [Else]),
+ mnesia_lib:verbose("sync_op terminated due to ~tp~n", [Else]),
mnesia:abort(Else);
{'EXIT', _, _} = Else ->
- mnesia_lib:verbose("sync_op terminated due to ~p~n", [Else]),
+ mnesia_lib:verbose("sync_op terminated due to ~tp~n", [Else]),
mnesia:abort(Else)
end;
prepare_op(_Tid, {op, sync_trans}, {coord, Nodes}) ->
case receive_sync(Nodes, []) of
{abort, Reason} ->
- mnesia_lib:verbose("sync_op terminated due to ~p~n", [Reason]),
+ mnesia_lib:verbose("sync_op terminated due to ~tp~n", [Reason]),
mnesia:abort(Reason);
Pids ->
[Pid ! {sync_trans, self()} || Pid <- Pids],
@@ -2705,10 +2696,10 @@ prepare_op(_Tid, {op, transform, Fun, TabDef}, _WaitFor) ->
Objs ->
mnesia_lib:db_fixtable(Storage, Tab, false),
{true, Objs, mandatory}
- catch _:Reason ->
+ catch _:Reason:Stacktrace ->
mnesia_lib:db_fixtable(Storage, Tab, false),
- mnesia_lib:important("Transform function failed: '~p' in '~p'",
- [Reason, erlang:get_stacktrace()]),
+ mnesia_lib:important("Transform function failed: '~tp' in '~tp'",
+ [Reason, Stacktrace]),
exit({"Bad transform function", Tab, Fun, node(), Reason})
end
end;
@@ -2719,7 +2710,7 @@ prepare_op(_Tid, {op, merge_schema, TabDef}, _WaitFor) ->
ok ->
{true, optional};
Error ->
- verbose("Merge_Schema ~p failed on ~p: ~p~n", [_Tid,node(),Error]),
+ verbose("Merge_Schema ~p failed on ~p: ~tp~n", [_Tid,node(),Error]),
mnesia:abort({bad_commit, Error})
end;
prepare_op(_Tid, _Op, _WaitFor) ->
@@ -3133,7 +3124,7 @@ ext_real_suffixes(Ext) ->
[M || {_,M} <- Ext])
catch
error:E ->
- verbose("Cant find real ext suffixes (~p)~n", [E]),
+ verbose("Cant find real ext suffixes (~tp)~n", [E]),
[]
end.
@@ -3142,7 +3133,7 @@ ext_tmp_suffixes(Ext) ->
[M || {_,M} <- Ext])
catch
error:E ->
- verbose("Cant find tmp ext suffixes (~p)~n", [E]),
+ verbose("Cant find tmp ext suffixes (~tp)~n", [E]),
[]
end.
@@ -3153,14 +3144,14 @@ info() ->
info(Tab) ->
Props = get_table_properties(Tab),
- io:format("-- Properties for ~w table --- ~n",[Tab]),
+ io:format("-- Properties for ~tw table --- ~n",[Tab]),
info2(Tab, Props).
info2(Tab, [{cstruct, _V} | Tail]) -> % Ignore cstruct
info2(Tab, Tail);
info2(Tab, [{frag_hash, _V} | Tail]) -> % Ignore frag_hash
info2(Tab, Tail);
info2(Tab, [{P, V} | Tail]) ->
- io:format("~-20w -> ~p~n",[P,V]),
+ io:format("~-20tw -> ~tp~n",[P,V]),
info2(Tab, Tail);
info2(_, []) ->
io:format("~n", []).
@@ -3726,7 +3717,7 @@ merge_versions(AnythingNew, Cs, RemoteCs, Force) ->
ok;
true ->
Str = io_lib:format("Bad cookies. Cannot merge definitions of "
- "table ~w. Local = ~w, Remote = ~w~n",
+ "table ~tw. Local = ~w, Remote = ~w~n",
[Cs#cstruct.name, Cs, RemoteCs]),
throw(Str)
end,
@@ -3746,7 +3737,7 @@ merge_versions(AnythingNew, Cs, RemoteCs, Force) ->
do_merge_versions(AnythingNew, Cs, RemoteCs);
true ->
Str1 = io_lib:format("Cannot merge definitions of "
- "table ~w. Local = ~w, Remote = ~w~n",
+ "table ~tw. Local = ~w, Remote = ~w~n",
[Cs#cstruct.name, Cs, RemoteCs]),
throw(Str1)
end.
diff --git a/lib/mnesia/src/mnesia_subscr.erl b/lib/mnesia/src/mnesia_subscr.erl
index c2748f5bae..21a308cfb6 100644
--- a/lib/mnesia/src/mnesia_subscr.erl
+++ b/lib/mnesia/src/mnesia_subscr.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -264,7 +264,7 @@ handle_call({change, How}, _From, State) ->
{reply, Reply, State};
handle_call(Msg, _From, State) ->
- error("~p got unexpected call: ~p~n", [?MODULE, Msg]),
+ error("~p got unexpected call: ~tp~n", [?MODULE, Msg]),
{noreply, State}.
%%----------------------------------------------------------------------
@@ -274,7 +274,7 @@ handle_call(Msg, _From, State) ->
%% {stop, Reason, State} (terminate/2 is called)
%%----------------------------------------------------------------------
handle_cast(Msg, State) ->
- error("~p got unexpected cast: ~p~n", [?MODULE, Msg]),
+ error("~p got unexpected cast: ~tp~n", [?MODULE, Msg]),
{noreply, State}.
%%----------------------------------------------------------------------
@@ -292,7 +292,7 @@ handle_info({'EXIT', Pid, _Reason}, State) ->
{noreply, State};
handle_info(Msg, State) ->
- error("~p got unexpected info: ~p~n", [?MODULE, Msg]),
+ error("~p got unexpected info: ~tp~n", [?MODULE, Msg]),
{noreply, State}.
%%----------------------------------------------------------------------
diff --git a/lib/mnesia/src/mnesia_text.erl b/lib/mnesia/src/mnesia_text.erl
index 21adca813a..cc21621ff4 100644
--- a/lib/mnesia/src/mnesia_text.erl
+++ b/lib/mnesia/src/mnesia_text.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -87,18 +87,18 @@ validate_tab(_) -> error(badtab).
make_tabs([{Tab, Def} | Tail]) ->
try mnesia:table_info(Tab, where_to_read) of
Node ->
- io:format("** Table ~w already exists on ~p, just entering data~n",
+ io:format("** Table ~tw already exists on ~p, just entering data~n",
[Tab, Node]),
make_tabs(Tail)
catch exit:_ -> %% non-existing table
case mnesia:create_table(Tab, Def) of
{aborted, Reason} ->
- io:format("** Failed to create table ~w ~n"
- "** Reason = ~w, Args = ~p~n",
+ io:format("** Failed to create table ~tw ~n"
+ "** Reason = ~tw, Args = ~tp~n",
[Tab, Reason, Def]),
[Tab | make_tabs(Tail)];
_ ->
- io:format("New table ~w~n", [Tab]),
+ io:format("New table ~tw~n", [Tab]),
make_tabs(Tail)
end
end;
@@ -139,12 +139,12 @@ collect_data(Tabs, [{Line, Term} | Tail]) when is_tuple(Term) ->
{value, _} ->
[Term | collect_data(Tabs, Tail)];
_Other ->
- io:format("Object:~p at line ~w unknown\n", [Term,Line]),
+ io:format("Object:~tp at line ~w unknown\n", [Term,Line]),
error(undefined_object)
end;
collect_data(_Tabs, []) -> [];
collect_data(_Tabs, [H|_T]) ->
- io:format("Object:~p unknown\n", [H]),
+ io:format("Object:~tp unknown\n", [H]),
error(undefined_object).
error(What) -> throw({error, What}).
@@ -178,7 +178,7 @@ read_term_from_stream(Stream, File, Line) ->
{ok, {Line, Term}, EndLine};
{error, {NewLine,Mod,What}} ->
Str = Mod:format_error(What),
- io:format("Error in line:~p of:~p ~s\n",
+ io:format("Error in line:~p of:~tp ~ts\n",
[NewLine, File, Str]),
error
end;
diff --git a/lib/mnesia/src/mnesia_tm.erl b/lib/mnesia/src/mnesia_tm.erl
index 305bf14bcf..4b3fffc735 100644
--- a/lib/mnesia/src/mnesia_tm.erl
+++ b/lib/mnesia/src/mnesia_tm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -121,10 +121,11 @@ init(Parent) ->
proc_lib:init_ack(Parent, {ok, self()}),
doit_loop(#state{supervisor = Parent}).
+%% Local function in order to avoid external function call
val(Var) ->
- case ?catch_val(Var) of
- {'EXIT', _} -> mnesia_lib:other_val(Var);
- _VaLuE_ -> _VaLuE_
+ case ?catch_val_and_stack(Var) of
+ {'EXIT', Stacktrace} -> mnesia_lib:other_val(Var, Stacktrace);
+ Value -> Value
end.
reply({From,Ref}, R) ->
@@ -314,7 +315,7 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
?eval_debug_fun({?MODULE, do_abort, pre}, [{tid, Tid}]),
case gb_trees:lookup(Tid, Participants) of
none ->
- verbose("Tried to abort a non participant transaction ~p: ~p~n",
+ verbose("Tried to abort a non participant transaction ~p: ~tp~n",
[Tid, Reason]),
mnesia_locker:release_tid(Tid),
doit_loop(State);
@@ -417,7 +418,7 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
{From, {unblock_me, Tab}} ->
case lists:member(Tab, State#state.blocked_tabs) of
false ->
- verbose("Wrong dirty Op blocked on ~p ~p ~p",
+ verbose("Wrong dirty Op blocked on ~p ~tp ~p",
[node(), Tab, From]),
reply(From, unblocked),
doit_loop(State);
@@ -466,11 +467,11 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
end;
{system, From, Msg} ->
- dbg_out("~p got {system, ~p, ~p}~n", [?MODULE, From, Msg]),
+ dbg_out("~p got {system, ~p, ~tp}~n", [?MODULE, From, Msg]),
sys:handle_system_msg(Msg, From, Sup, ?MODULE, [], State);
Msg ->
- verbose("** ERROR ** ~p got unexpected message: ~p~n", [?MODULE, Msg]),
+ verbose("** ERROR ** ~p got unexpected message: ~tp~n", [?MODULE, Msg]),
doit_loop(State)
end.
@@ -556,7 +557,7 @@ handle_exit(Pid, Reason, State) ->
%% We got exit from a local fool
doit_loop(State);
{P = #participant{}, _RestP} ->
- fatal("Participant ~p in transaction ~p died ~p~n",
+ fatal("Participant ~p in transaction ~p died ~tp~n",
[P#participant.pid, P#participant.tid, Reason]),
NewPs = gb_trees:delete(P#participant.tid,State#state.participants),
doit_loop(State#state{participants = NewPs})
@@ -597,9 +598,9 @@ recover_coordinator(Tid, Etabs) ->
false -> %% When killed before store havn't been copied to
ok %% to the new nested trans store.
end
- catch _:Reason ->
- dbg_out("Recovery of coordinator ~p failed:~n",
- [Tid, {Reason, erlang:get_stacktrace()}]),
+ catch _:Reason:Stacktrace ->
+ dbg_out("Recovery of coordinator ~p failed: ~tp~n",
+ [Tid, {Reason, Stacktrace}]),
Protocol = asym_trans,
tell_outcome(Tid, Protocol, node(), CheckNodes, TellNodes)
end,
@@ -825,8 +826,7 @@ execute_transaction(Fun, Args, Factor, Retries, Type) ->
catch throw:Value -> %% User called throw
Reason = {aborted, {throw, Value}},
return_abort(Fun, Args, Reason);
- error:Reason ->
- ST = erlang:get_stacktrace(),
+ error:Reason:ST ->
check_exit(Fun, Args, Factor, Retries, {Reason,ST}, Type);
_:Reason ->
check_exit(Fun, Args, Factor, Retries, Reason, Type)
@@ -941,7 +941,7 @@ decr(_X) -> 0.
return_abort(Fun, Args, Reason) ->
{_Mod, Tid, Ts} = get(mnesia_activity_state),
- dbg_out("Transaction ~p calling ~p with ~p failed: ~n ~p~n",
+ dbg_out("Transaction ~p calling ~tp with ~tp failed: ~n ~tp~n",
[Tid, Fun, Args, Reason]),
OldStore = Ts#tidstore.store,
Nodes = get_elements(nodes, OldStore),
@@ -1714,7 +1714,7 @@ commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
mnesia_schema:undo_prepare_commit(Tid, C0);
Msg ->
- verbose("** ERROR ** commit_participant ~p, got unexpected msg: ~p~n",
+ verbose("** ERROR ** commit_participant ~p, got unexpected msg: ~tp~n",
[Tid, Msg])
end;
{Tid, {do_abort, Reason}} ->
@@ -1730,7 +1730,7 @@ commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
Msg ->
reply(Coord, {do_abort, Tid, self(), {bad_commit,internal}}),
- verbose("** ERROR ** commit_participant ~p, got unexpected msg: ~p~n",
+ verbose("** ERROR ** commit_participant ~p, got unexpected msg: ~tp~n",
[Tid, Msg])
end
catch _:Reason ->
@@ -1796,15 +1796,14 @@ do_update(Tid, Storage, [Op | Ops], OldRes) ->
try do_update_op(Tid, Storage, Op) of
ok -> do_update(Tid, Storage, Ops, OldRes);
NewRes -> do_update(Tid, Storage, Ops, NewRes)
- catch _:Reason ->
+ catch _:Reason:ST ->
%% This may only happen when we recently have
%% deleted our local replica, changed storage_type
%% or transformed table
%% BUGBUG: Updates may be lost if storage_type is changed.
%% Determine actual storage type and try again.
%% BUGBUG: Updates may be lost if table is transformed.
- ST = erlang:get_stacktrace(),
- verbose("do_update in ~w failed: ~p -> {'EXIT', ~p}~n",
+ verbose("do_update in ~w failed: ~tp -> {'EXIT', ~tp}~n",
[Tid, Op, {Reason, ST}]),
do_update(Tid, Storage, Ops, OldRes)
end;
@@ -1914,12 +1913,11 @@ commit_clear([H|R], Tid, Storage, Tab, K, Obj)
do_snmp(_, []) -> ok;
do_snmp(Tid, [Head|Tail]) ->
try mnesia_snmp_hook:update(Head)
- catch _:Reason ->
+ catch _:Reason:ST ->
%% This should only happen when we recently have
%% deleted our local replica or recently deattached
%% the snmp table
- ST = erlang:get_stacktrace(),
- verbose("do_snmp in ~w failed: ~p -> {'EXIT', ~p}~n",
+ verbose("do_snmp in ~w failed: ~tp -> {'EXIT', ~tp}~n",
[Tid, Head, {Reason, ST}])
end,
do_snmp(Tid, Tail).
@@ -2151,7 +2149,7 @@ pr_participant(Stream, P) ->
true -> Commit0
end,
pr_tid(Stream, P#participant.tid),
- io:format(Stream, "with participant objects ~p~n", [Commit]).
+ io:format(Stream, "with participant objects ~tp~n", [Commit]).
pr_tid(Stream, Tid) ->
@@ -2193,7 +2191,7 @@ search_pr_participant(S, [ P | Tail]) ->
true -> Commit0
end,
- io:format("~p~n", [Commit]),
+ io:format("~tp~n", [Commit]),
search_pr_participant(S,Tail); %% !!!!!
true ->
search_pr_participant(S, Tail)
@@ -2212,14 +2210,14 @@ display_pid_info(Pid) ->
Other
end,
Reds = fetch(reductions, Info),
- LM = length(fetch(messages, Info)),
+ LM = fetch(message_queue_len, Info),
pformat(io_lib:format("~p", [Pid]),
- io_lib:format("~p", [Call]),
- io_lib:format("~p", [Curr]), Reds, LM)
+ io_lib:format("~tp", [Call]),
+ io_lib:format("~tp", [Curr]), Reds, LM)
end.
pformat(A1, A2, A3, A4, A5) ->
- io:format( "~-12s ~-21s ~-21s ~9w ~4w~n", [A1,A2,A3,A4,A5]).
+ io:format( "~-12s ~-21ts ~-21ts ~9w ~4w~n", [A1,A2,A3,A4,A5]).
fetch(Key, Info) ->
case lists:keysearch(Key, 1, Info) of
diff --git a/lib/mnesia/test/mnesia_SUITE.erl b/lib/mnesia/test/mnesia_SUITE.erl
index 3ec4847c5d..24c1def6da 100644
--- a/lib/mnesia/test/mnesia_SUITE.erl
+++ b/lib/mnesia/test/mnesia_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,12 @@
%%
-module(mnesia_SUITE).
-author('[email protected]').
--compile([export_all]).
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_suite/1, end_per_suite/1,
+ init_per_group/2, end_per_group/2,
+ suite/0, all/0, groups/0]).
+-export([app/1, appup/1, clean_up_suite/1, silly/0]).
+
-include_lib("common_test/include/ct.hrl").
-include("mnesia_test_lib.hrl").
@@ -92,16 +97,8 @@ groups() ->
%% benchmarks
{heavy, [], [{group, measure}]},
{measure, [], [{mnesia_measure_test, all}]},
- {prediction, [],
- [{group, mnesia_measure_test, prediction}]},
- {fairness, [],
- [{group, mnesia_measure_test, fairness}]},
{benchmarks, [],
[{group, mnesia_measure_test, benchmarks}]},
- {consumption, [],
- [{group, mnesia_measure_test, consumption}]},
- {scalability, [],
- [{group, mnesia_measure_test, scalability}]},
%% This test suite is an extract of the grand Mnesia suite
%% it contains OTP R4B specific test cases
{otp_r4b, [],
diff --git a/lib/mnesia/test/mnesia_atomicity_test.erl b/lib/mnesia/test/mnesia_atomicity_test.erl
index cc32ba3826..4764f9e7c0 100644
--- a/lib/mnesia/test/mnesia_atomicity_test.erl
+++ b/lib/mnesia/test/mnesia_atomicity_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,9 +22,37 @@
-module(mnesia_atomicity_test).
-author('[email protected]').
-author('[email protected]').
--compile([export_all]).
-include("mnesia_test_lib.hrl").
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_group/2, end_per_group/2,
+ all/0, groups/0]).
+-export([explicit_abort_in_middle_of_trans/1,
+ runtime_error_in_middle_of_trans/1,
+ mnesia_down_during_infinite_trans/1,
+ kill_self_in_middle_of_trans/1, throw_in_middle_of_trans/1,
+ lock_waiter_sw_r/1, lock_waiter_sw_rt/1, lock_waiter_sw_wt/1,
+ lock_waiter_wr_r/1, lock_waiter_srw_r/1, lock_waiter_sw_sw/1,
+ lock_waiter_sw_w/1, lock_waiter_sw_wr/1, lock_waiter_sw_srw/1,
+ lock_waiter_wr_wt/1, lock_waiter_srw_wt/1,
+ lock_waiter_wr_sw/1, lock_waiter_srw_sw/1, lock_waiter_wr_w/1,
+ lock_waiter_srw_w/1, lock_waiter_r_sw/1, lock_waiter_r_w/1,
+ lock_waiter_r_wt/1, lock_waiter_rt_sw/1, lock_waiter_rt_w/1,
+ lock_waiter_rt_wt/1, lock_waiter_wr_wr/1,
+ lock_waiter_srw_srw/1, lock_waiter_wt_r/1, lock_waiter_wt_w/1,
+ lock_waiter_wt_rt/1, lock_waiter_wt_wt/1, lock_waiter_wt_wr/1,
+ lock_waiter_wt_srw/1, lock_waiter_wt_sw/1, lock_waiter_w_wr/1,
+ lock_waiter_w_srw/1, lock_waiter_w_sw/1, lock_waiter_w_r/1,
+ lock_waiter_w_w/1, lock_waiter_w_rt/1, lock_waiter_w_wt/1,
+ restart_r_one/1, restart_w_one/1, restart_rt_one/1,
+ restart_wt_one/1, restart_wr_one/1, restart_sw_one/1,
+ restart_r_two/1, restart_w_two/1, restart_rt_two/1,
+ restart_wt_two/1, restart_wr_two/1, restart_sw_two/1
+ ]
+ ).
+
+-export([perform_restarted_transaction/1, sync_tid_release/0]).
+
init_per_testcase(Func, Conf) ->
mnesia_test_lib:init_per_testcase(Func, Conf).
diff --git a/lib/mnesia/test/mnesia_bench_SUITE.erl b/lib/mnesia/test/mnesia_bench_SUITE.erl
index 7c86db383d..8a225629e6 100644
--- a/lib/mnesia/test/mnesia_bench_SUITE.erl
+++ b/lib/mnesia/test/mnesia_bench_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,13 @@
%%
-module(mnesia_bench_SUITE).
-author('[email protected]').
--compile(export_all).
+
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_suite/1, end_per_suite/1,
+ init_per_group/2, end_per_group/2,
+ suite/0, all/0, groups/0]).
+
+-export([tpcb_conflict_ramcopies/1, tpcb_conflict_disk_only_copies/1]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
suite() -> [{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]}].
diff --git a/lib/mnesia/test/mnesia_consistency_test.erl b/lib/mnesia/test/mnesia_consistency_test.erl
index 2fe1bd34e6..46bafaf65c 100644
--- a/lib/mnesia/test/mnesia_consistency_test.erl
+++ b/lib/mnesia/test/mnesia_consistency_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,78 @@
%%
-module(mnesia_consistency_test).
-author('[email protected]').
--compile([export_all]).
+
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_group/2, end_per_group/2,
+ all/0, groups/0]).
+
+-export([consistency_after_change_table_copy_type/1,
+ consistency_after_rename_of_node/1,
+ consistency_after_restart_1_ram/1,
+ consistency_after_restart_1_disc/1,
+ consistency_after_restart_1_disc_only/1,
+ consistency_after_restart_2_ram/1,
+ consistency_after_restart_2_disc/1,
+ consistency_after_restart_2_disc_only/1,
+ consistency_after_dump_tables_1_ram/1,
+ consistency_after_dump_tables_2_ram/1,
+ consistency_after_add_replica_2_ram/1,
+ consistency_after_add_replica_2_disc/1,
+ consistency_after_add_replica_2_disc_only/1,
+ consistency_after_add_replica_3_ram/1,
+ consistency_after_add_replica_3_disc/1,
+ consistency_after_add_replica_3_disc_only/1,
+ consistency_after_del_replica_2_ram/1,
+ consistency_after_del_replica_2_disc/1,
+ consistency_after_del_replica_2_disc_only/1,
+ consistency_after_del_replica_3_ram/1,
+ consistency_after_del_replica_3_disc/1,
+ consistency_after_del_replica_3_disc_only/1,
+ consistency_after_move_replica_2_ram/1,
+ consistency_after_move_replica_2_disc/1,
+ consistency_after_move_replica_2_disc_only/1,
+ consistency_after_move_replica_3_ram/1,
+ consistency_after_move_replica_3_disc/1,
+ consistency_after_move_replica_3_disc_only/1,
+ consistency_after_transform_table_ram/1,
+ consistency_after_transform_table_disc/1,
+ consistency_after_transform_table_disc_only/1,
+ consistency_after_fallback_2_ram/1,
+ consistency_after_fallback_2_disc/1,
+ consistency_after_fallback_2_disc_only/1,
+ consistency_after_fallback_3_ram/1,
+ consistency_after_fallback_3_disc/1,
+ consistency_after_fallback_3_disc_only/1,
+ consistency_after_restore_clear_ram/1,
+ consistency_after_restore_clear_disc/1,
+ consistency_after_restore_clear_disc_only/1,
+ consistency_after_restore_recreate_ram/1,
+ consistency_after_restore_recreate_disc/1,
+ consistency_after_restore_recreate_disc_only/1,
+ updates_during_checkpoint_activation_1_ram/1,
+ updates_during_checkpoint_activation_1_disc/1,
+ updates_during_checkpoint_activation_1_disc_only/1,
+ updates_during_checkpoint_activation_2_ram/1,
+ updates_during_checkpoint_activation_2_disc/1,
+ updates_during_checkpoint_activation_2_disc_only/1,
+ updates_during_checkpoint_activation_3_ram/1,
+ updates_during_checkpoint_activation_3_disc/1,
+ updates_during_checkpoint_activation_3_disc_only/1,
+ updates_during_checkpoint_iteration_2_ram/1,
+ updates_during_checkpoint_iteration_2_disc/1,
+ updates_during_checkpoint_iteration_2_disc_only/1,
+ load_table_with_activated_checkpoint_ram/1,
+ load_table_with_activated_checkpoint_disc/1,
+ load_table_with_activated_checkpoint_disc_only/1,
+ add_table_copy_to_table_checkpoint_ram/1,
+ add_table_copy_to_table_checkpoint_disc/1,
+ add_table_copy_to_table_checkpoint_disc_only/1,
+ inst_fallback_process_dies/1, fatal_when_inconsistency/1,
+ after_delete/1,cause_switch_before/1, cause_switch_after/1,
+ cause_abort_before/1, cause_abort_after/1,
+ change_schema_before/1, change_schema_after/1]).
+
+-export([change_tab/3]).
-include("mnesia_test_lib.hrl").
diff --git a/lib/mnesia/test/mnesia_cost.erl b/lib/mnesia/test/mnesia_cost.erl
index a3fc8dfe20..b5d5253147 100644
--- a/lib/mnesia/test/mnesia_cost.erl
+++ b/lib/mnesia/test/mnesia_cost.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@
%%
-module(mnesia_cost).
--compile(export_all).
+-export([go/0, go/1]).
%% This code exercises the mnesia system and produces a bunch
%% of measurements on what various things cost
@@ -156,64 +156,3 @@ do_dirty(I, F) when I /= 0 ->
F(),
do_dirty(I-1, F);
do_dirty(_,_) -> ok.
-
-
-
-table_load([N1,N2| _ ] = Ns) ->
- Nodes = [N1,N2],
- rpc:multicall(Ns, mnesia, lkill, []),
- ok = mnesia:delete_schema(Ns),
- ok = mnesia:create_schema(Nodes),
- rpc:multicall(Nodes, mnesia, start, []),
- TabDef = [{disc_copies,[N1]},{ram_copies,[N2]},
- {attributes,record_info(fields,item)},{record_name,item}],
- Tabs = [list_to_atom("tab" ++ integer_to_list(I)) || I <- lists:seq(1,400)],
-
- [mnesia:create_table(Tab,TabDef) || Tab <- Tabs],
-
-%% InitTab = fun(Tab) ->
-%% mnesia:write_lock_table(Tab),
-%% InitRec = fun(Key) -> mnesia:write(Tab,#item{a=Key},write) end,
-%% lists:foreach(InitRec, lists:seq(1,100))
-%% end,
-%%
-%% {Time,{atomic,ok}} = timer:tc(mnesia,transaction, [fun() ->lists:foreach(InitTab, Tabs) end]),
- mnesia:dump_log(),
-%% io:format("Init took ~p msec ~n", [Time/1000]),
- rpc:call(N2, mnesia, stop, []), timer:sleep(1000),
- mnesia:stop(), timer:sleep(500),
- %% Warmup
- ok = mnesia:start([{no_table_loaders, 1}]),
- timer:tc(mnesia, wait_for_tables, [Tabs, infinity]),
- mnesia:dump_log(),
- rpc:call(N2, mnesia, dump_log, []),
- io:format("Initialized ~n",[]),
-
- mnesia:stop(), timer:sleep(1000),
- ok = mnesia:start([{no_table_loaders, 1}]),
- {T1, ok} = timer:tc(mnesia, wait_for_tables, [Tabs, infinity]),
- io:format("Loading from disc with 1 loader ~p msec~n",[T1/1000]),
- mnesia:stop(), timer:sleep(1000),
- ok = mnesia:start([{no_table_loaders, 4}]),
- {T2, ok} = timer:tc(mnesia, wait_for_tables, [Tabs, infinity]),
- io:format("Loading from disc with 4 loader ~p msec~n",[T2/1000]),
-
- %% Warmup
- rpc:call(N2, ?MODULE, remote_load, [Tabs,4]),
- io:format("Initialized ~n",[]),
-
-
- T3 = rpc:call(N2, ?MODULE, remote_load, [Tabs,1]),
- io:format("Loading from net with 1 loader ~p msec~n",[T3/1000]),
-
- T4 = rpc:call(N2, ?MODULE, remote_load, [Tabs,4]),
- io:format("Loading from net with 4 loader ~p msec~n",[T4/1000]),
-
- ok.
-
-remote_load(Tabs,Loaders) ->
- ok = mnesia:start([{no_table_loaders, Loaders}]),
-%% io:format("~p ~n", [mnesia_controller:get_info(500)]),
- {Time, ok} = timer:tc(mnesia, wait_for_tables, [Tabs, infinity]),
- timer:sleep(1000), mnesia:stop(), timer:sleep(1000),
- Time.
diff --git a/lib/mnesia/test/mnesia_dirty_access_test.erl b/lib/mnesia/test/mnesia_dirty_access_test.erl
index 6d970ac990..67ef1fe901 100644
--- a/lib/mnesia/test/mnesia_dirty_access_test.erl
+++ b/lib/mnesia/test/mnesia_dirty_access_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,9 +21,37 @@
%%
-module(mnesia_dirty_access_test).
-author('[email protected]').
--compile([export_all]).
-include("mnesia_test_lib.hrl").
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_group/2, end_per_group/2,
+ all/0, groups/0]).
+
+-export([dirty_write_ram/1, dirty_write_disc/1, dirty_write_disc_only/1, dirty_write_xets/1,
+ dirty_read_ram/1, dirty_read_disc/1, dirty_read_disc_only/1, dirty_read_xets/1,
+ dirty_update_counter_ram/1, dirty_update_counter_disc/1,
+ dirty_update_counter_disc_only/1, dirty_update_counter_xets/1,
+ dirty_delete_ram/1, dirty_delete_disc/1, dirty_delete_disc_only/1, dirty_delete_xets/1,
+ dirty_delete_object_ram/1, dirty_delete_object_disc/1,
+ dirty_delete_object_disc_only/1, dirty_delete_object_xets/1,
+ dirty_match_object_ram/1, dirty_match_object_disc/1,
+ dirty_match_object_disc_only/1, dirty_match_object_xets/1,
+ dirty_index_match_object_ram/1, dirty_index_match_object_disc/1,
+ dirty_index_match_object_disc_only/1, dirty_index_match_object_xets/1,
+ dirty_index_read_ram/1, dirty_index_read_disc/1,
+ dirty_index_read_disc_only/1, dirty_index_read_xets/1,
+ dirty_index_update_set_ram/1, dirty_index_update_set_disc/1,
+ dirty_index_update_set_disc_only/1, dirty_index_update_set_xets/1,
+ dirty_index_update_bag_ram/1, dirty_index_update_bag_disc/1,
+ dirty_index_update_bag_disc_only/1, dirty_index_update_bag_xets/1,
+ dirty_iter_ram/1, dirty_iter_disc/1, dirty_iter_disc_only/1,dirty_iter_xets/1,
+ del_table_copy_1/1, del_table_copy_2/1, del_table_copy_3/1,
+ add_table_copy_1/1, add_table_copy_2/1, add_table_copy_3/1,
+ add_table_copy_4/1, move_table_copy_1/1, move_table_copy_2/1,
+ move_table_copy_3/1, move_table_copy_4/1]).
+
+-export([update_trans/3]).
+
init_per_testcase(Func, Conf) ->
mnesia_test_lib:init_per_testcase(Func, Conf).
diff --git a/lib/mnesia/test/mnesia_durability_test.erl b/lib/mnesia/test/mnesia_durability_test.erl
index 97bc84a2d8..ccbfdc9738 100644
--- a/lib/mnesia/test/mnesia_durability_test.erl
+++ b/lib/mnesia/test/mnesia_durability_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,34 @@
%%
-module(mnesia_durability_test).
-author('[email protected]').
--compile([export_all]).
+
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_group/2, end_per_group/2,
+ all/0, groups/0]).
+
+-export([durability_of_disc_copies/1,
+ durability_of_disc_only_copies/1,
+ load_latest_data/1, load_local_contents_directly/1,
+ load_directly_when_all_are_ram_copiesA/1,
+ load_directly_when_all_are_ram_copiesB/1,
+ load_when_last_replica_becomes_available/1,
+ load_when_down_from_all_other_replica_nodes/1,
+ late_load_transforms_into_disc_load/1,
+ late_load_leads_to_hanging/1,
+ force_load_when_nobody_intents_to_load/1,
+ force_load_when_someone_has_decided_to_load/1,
+ force_load_when_someone_else_has_loaded/1,
+ force_load_when_we_has_loaded/1,
+ force_load_on_a_non_local_table/1,
+ force_load_when_the_table_does_not_exist/1,
+ late_load_all_ram_cs_ram_nodes1/1,
+ late_load_all_ram_cs_ram_nodes2/1,
+ master_nodes/1, starting_master_nodes/1,
+ master_on_non_local_tables/1,
+ remote_force_load_with_local_master_node/1,
+ master_node_with_ram_copy_2/1, master_node_with_ram_copy_3/1,
+ dump_ram_copies/1, dump_disc_copies/1, dump_disc_only/1]).
+
-include("mnesia_test_lib.hrl").
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -65,7 +92,8 @@ groups() ->
{load_tables_with_master_tables, [],
[master_nodes, starting_master_nodes,
master_on_non_local_tables,
- remote_force_load_with_local_master_node]},
+ remote_force_load_with_local_master_node,
+ master_node_with_ram_copy_2, master_node_with_ram_copy_3]},
{durability_of_dump_tables, [],
[dump_ram_copies, dump_disc_copies, dump_disc_only]}].
@@ -1139,6 +1167,107 @@ remote_force_load_with_local_master_node(Config) when is_list(Config) ->
?verify_mnesia(Nodes, []).
+master_node_with_ram_copy_2(Config) when is_list(Config) ->
+ [A, B] = Nodes = ?acquire_nodes(2, Config),
+ Tab = ?FUNCTION_NAME,
+ ?match({atomic,ok}, mnesia:create_table(Tab, [{disc_copies, [A]}, {ram_copies, [B]}])),
+ ?match({atomic,ok}, mnesia:sync_transaction(?SDwrite({Tab, 1, init}))),
+
+ %% Test that we don't load from ram_copies
+ ?match(stopped, rpc:call(A, mnesia, stop, [])),
+ ?match(stopped, rpc:call(B, mnesia, stop, [])),
+ ?match(ok, rpc:call(B, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])),
+ ?match(ok, rpc:call(A, mnesia, start, [])),
+ ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match([{Tab, 1, init}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, init}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])),
+
+ %% Test that master_nodes set to ram_copy node require force_load
+ ?match(ok, rpc:call(A, mnesia, set_master_nodes, [[B]])),
+ ?match(stopped, rpc:call(A, mnesia, stop, [])),
+ ?match(stopped, rpc:call(B, mnesia, stop, [])),
+ ?match(ok, rpc:call(B, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])),
+ ?match(ok, rpc:call(A, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])),
+
+ ?match(yes, rpc:call(A, mnesia, force_load_table, [Tab])),
+ ?match(ok, rpc:call(A, mnesia, wait_for_tables, [[Tab], 1000])),
+ ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])),
+ ?match([{Tab, 1, init}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, init}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])),
+
+ ?verify_mnesia(Nodes, []).
+
+
+master_node_with_ram_copy_3(Config) when is_list(Config) ->
+ [A, B, C] = Nodes = ?acquire_nodes(3, Config),
+ Tab = ?FUNCTION_NAME,
+ ?match({atomic,ok}, mnesia:create_table(Tab, [{disc_copies, [A,C]}, {ram_copies, [B]}])),
+ ?match({atomic,ok}, mnesia:sync_transaction(?SDwrite({Tab, 1, init}))),
+
+ %% Test that we don't load from ram_copies
+ ?match(stopped, rpc:call(A, mnesia, stop, [])),
+ ?match(stopped, rpc:call(C, mnesia, stop, [])),
+ ?match(stopped, rpc:call(B, mnesia, stop, [])),
+ ?match(ok, rpc:call(B, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])),
+ ?match(ok, rpc:call(A, mnesia, start, [])),
+ ?match(ok, rpc:call(C, mnesia, start, [])),
+ ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match(ok, rpc:call(A, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match([{Tab, 1, init}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, init}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, init}], rpc:call(C, mnesia, dirty_read, [{Tab, 1}])),
+
+ %% Test that master_nodes set to ram_copy node will wait until loaded
+ ?match(ok, rpc:call(A, mnesia, set_master_nodes, [[B]])),
+ ?match(stopped, rpc:call(A, mnesia, stop, [])),
+ ?match({atomic,ok}, rpc:call(B, mnesia, sync_transaction, [?SDwrite({Tab, 1, update})])),
+ ?match(stopped, rpc:call(C, mnesia, stop, [])),
+ ?match({atomic,ok}, rpc:call(B, mnesia, sync_transaction, [?SDwrite({Tab, 1, ram_copies})])),
+ ?match(stopped, rpc:call(B, mnesia, stop, [])),
+ ?match(ok, rpc:call(B, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match(ok, rpc:call(A, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(A, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match(ok, rpc:call(C, mnesia, start, [])),
+ ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match(ok, rpc:call(A, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match([{Tab, 1, update}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, update}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, update}], rpc:call(C, mnesia, dirty_read, [{Tab, 1}])),
+
+ %% Test that master_nodes set to ram_copy node requires force load
+ ?match({atomic,ok}, mnesia:sync_transaction(?SDwrite({Tab, 1, init}))),
+ ?match(ok, rpc:call(A, mnesia, set_master_nodes, [[B]])),
+ ?match(ok, rpc:call(C, mnesia, set_master_nodes, [[B]])),
+
+ ?match(stopped, rpc:call(A, mnesia, stop, [])),
+ ?match({atomic,ok}, rpc:call(B, mnesia, sync_transaction, [?SDwrite({Tab, 1, update})])),
+ ?match(stopped, rpc:call(C, mnesia, stop, [])),
+ ?match({atomic,ok}, rpc:call(B, mnesia, sync_transaction, [?SDwrite({Tab, 1, ram_copies})])),
+ ?match(stopped, rpc:call(B, mnesia, stop, [])),
+ ?match(ok, rpc:call(B, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match(ok, rpc:call(A, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(A, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match(ok, rpc:call(C, mnesia, start, [])),
+ ?match({timeout, [Tab]}, rpc:call(A, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 500])),
+ ?match(yes, rpc:call(C, mnesia, force_load_table, [Tab])),
+
+ ?match(ok, rpc:call(A, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match(ok, rpc:call(C, mnesia, wait_for_tables, [[Tab], 3000])),
+ ?match([{Tab, 1, update}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, update}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])),
+ ?match([{Tab, 1, update}], rpc:call(C, mnesia, dirty_read, [{Tab, 1}])),
+
+ ?verify_mnesia(Nodes, []).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1389,7 +1518,7 @@ do_disc_durability(Config,CopyType) ->
[{Tab_bag, 22, a_2222}], [{Tab_bag, 33, a_3333}],
[{Tab_set, counter, 10}]]),
- timer:sleep(1000), %% Debugging strange msgs..
+ timer:sleep(500), %% Debugging strange msgs..
?log("Flushed ~p ~n", [mnesia_test_lib:flush()]),
?verify_mnesia(Nodes, []).
diff --git a/lib/mnesia/test/mnesia_evil_backup.erl b/lib/mnesia/test/mnesia_evil_backup.erl
index 0fa72c4305..45b11f2f3f 100644
--- a/lib/mnesia/test/mnesia_evil_backup.erl
+++ b/lib/mnesia/test/mnesia_evil_backup.erl
@@ -28,10 +28,23 @@
-module(mnesia_evil_backup).
-author('[email protected]').
--compile(export_all).
-include("mnesia_test_lib.hrl").
-%%-export([Function/Arity, ...]).
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_group/2, end_per_group/2,
+ all/0, groups/0]).
+
+-export([backup/1, bad_backup/1, global_backup_checkpoint/1,
+ traverse_backup/1,
+ selective_backup_checkpoint/1,
+ incremental_backup_checkpoint/1, install_fallback/1,
+ uninstall_fallback/1, local_fallback/1,
+ sops_with_checkpoint/1,
+ restore_errors/1, restore_clear/1, restore_keep/1,
+ restore_recreate/1, restore_clear_ram/1
+ ]).
+
+-export([check_tab/2]).
init_per_testcase(Func, Conf) ->
mnesia_test_lib:init_per_testcase(Func, Conf).
diff --git a/lib/mnesia/test/mnesia_evil_coverage_test.erl b/lib/mnesia/test/mnesia_evil_coverage_test.erl
index 6e34040bc4..a451c8d0c8 100644
--- a/lib/mnesia/test/mnesia_evil_coverage_test.erl
+++ b/lib/mnesia/test/mnesia_evil_coverage_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,7 +23,33 @@
-author('[email protected]').
-include("mnesia_test_lib.hrl").
--compile([export_all]).
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_group/2, end_per_group/2,
+ all/0, groups/0]).
+
+-export([system_info/1, table_info/1, error_description/1,
+ db_node_lifecycle/1, evil_delete_db_node/1, start_and_stop/1,
+ checkpoint/1, table_lifecycle/1, storage_options/1,
+ add_copy_conflict/1, add_copy_when_going_down/1,
+ add_copy_with_down/1,
+ replica_management/1, clear_table_during_load/1,
+ schema_availability/1, local_content/1,
+ replica_location/1, user_properties/1, unsupp_user_props/1,
+ sorted_ets/1, index_cleanup/1,
+ change_table_access_mode/1, change_table_load_order/1,
+ set_master_nodes/1, offline_set_master_nodes/1,
+ dump_tables/1, dump_log/1, wait_for_tables/1, force_load_table/1,
+ snmp_open_table/1, snmp_close_table/1, snmp_get_next_index/1,
+ snmp_get_row/1, snmp_get_mnesia_key/1, snmp_update_counter/1,
+ snmp_order/1, subscribe_standard/1, subscribe_extended/1,
+ foldl/1, info/1, schema_0/1, schema_1/1, view_0/1, view_1/1, view_2/1,
+ lkill/1, kill/1,
+ record_name_dirty_access_ram/1,
+ record_name_dirty_access_disc/1,
+ record_name_dirty_access_disc_only/1,
+ record_name_dirty_access_xets/1]).
+
+-export([info_check/8, index_size/1]).
-define(cleanup(N, Config),
mnesia_test_lib:prepare_test_case([{reload_appls, [mnesia]}],
@@ -40,13 +66,14 @@ all() ->
db_node_lifecycle, evil_delete_db_node, start_and_stop,
checkpoint, table_lifecycle, storage_options,
add_copy_conflict,
- add_copy_when_going_down, replica_management, clear_table_during_load,
+ add_copy_when_going_down, add_copy_with_down, replica_management,
+ clear_table_during_load,
schema_availability, local_content,
{group, table_access_modifications}, replica_location,
{group, table_sync}, user_properties, unsupp_user_props,
{group, record_name}, {group, snmp_access},
{group, subscriptions}, {group, iteration},
- {group, debug_support}, sorted_ets,
+ {group, debug_support}, sorted_ets, index_cleanup,
{mnesia_dirty_access_test, all},
{mnesia_trans_access_test, all},
{mnesia_evil_backup, all}].
@@ -707,6 +734,49 @@ add_copy_when_going_down(Config) ->
?match_receive({test,{aborted,_}}),
?verify_mnesia([Node2], []).
+add_copy_with_down(suite) -> [];
+add_copy_with_down(Config) ->
+ %% Allow add_table_copy() with ram_copies even all other replicas are down
+ Nodes = [Node1, Node2, Node3] = ?acquire_nodes(3, Config),
+ ?match({atomic, ok}, mnesia:create_table(a, [{ram_copies, [Node3]}, {disc_copies, [Node2]}])),
+ stopped = rpc:call(Node2, mnesia, stop, []),
+ stopped = rpc:call(Node3, mnesia, stop, []),
+ ?match({aborted, _}, mnesia:add_table_copy(a, Node1, ram_copies)),
+ ?match({aborted, _}, mnesia:del_table_copy(a, Node2)),
+ ok = rpc:call(Node3, mnesia, start, []),
+ ?match({aborted, _}, mnesia:add_table_copy(a, Node1, ram_copies)),
+ ?match([], mnesia_test_lib:start_mnesia([Node2], [a])),
+ ?match({atomic, ok}, mnesia:change_table_copy_type(a, Node2, ram_copies)),
+ stopped = rpc:call(Node2, mnesia, stop, []),
+ stopped = rpc:call(Node3, mnesia, stop, []),
+ ?match({atomic, ok}, mnesia:add_table_copy(a, Node1, ram_copies)),
+ ?match(ok, mnesia:dirty_write({a,1,1})),
+ ?match([], mnesia_test_lib:start_mnesia([Node2,Node3], [a])),
+ ?match([{a,1,1}], rpc:call(Node1, mnesia, dirty_read, [{a,1}])),
+ ?match([{a,1,1}], rpc:call(Node2, mnesia, dirty_read, [{a,1}])),
+ ?match([{a,1,1}], rpc:call(Node3, mnesia, dirty_read, [{a,1}])),
+
+ ?match({atomic, ok}, mnesia:del_table_copy(a, Node1)),
+ stopped = rpc:call(Node2, mnesia, stop, []),
+ stopped = rpc:call(Node3, mnesia, stop, []),
+ ?match({atomic, ok}, mnesia:add_table_copy(a, Node1, disc_copies)),
+ ?match(ok, mnesia:dirty_write({a,1,1})),
+ ?match([], mnesia_test_lib:start_mnesia([Node2,Node3], [a])),
+ ?match([{a,1,1}], rpc:call(Node1, mnesia, dirty_read, [{a,1}])),
+ ?match([{a,1,1}], rpc:call(Node2, mnesia, dirty_read, [{a,1}])),
+ ?match([{a,1,1}], rpc:call(Node3, mnesia, dirty_read, [{a,1}])),
+
+ ?match({atomic, ok}, mnesia:del_table_copy(a, Node1)),
+ stopped = rpc:call(Node2, mnesia, stop, []),
+ stopped = rpc:call(Node3, mnesia, stop, []),
+ ?match({atomic, ok}, mnesia:add_table_copy(a, Node1, disc_only_copies)),
+ ?match(ok, mnesia:dirty_write({a,1,1})),
+ ?match([], mnesia_test_lib:start_mnesia([Node2,Node3], [a])),
+ ?match([{a,1,1}], rpc:call(Node1, mnesia, dirty_read, [{a,1}])),
+ ?match([{a,1,1}], rpc:call(Node2, mnesia, dirty_read, [{a,1}])),
+ ?match([{a,1,1}], rpc:call(Node3, mnesia, dirty_read, [{a,1}])),
+
+ ?verify_mnesia(Nodes, []).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Add, drop and move replicas, change storage types
@@ -2489,3 +2559,55 @@ sorted_ets(Config) when is_list(Config) ->
?match({atomic, [{rec,1,1}, {rec,2,1}]}, mnesia:transaction(TestIt)).
+index_cleanup(Config) when is_list(Config) ->
+ [N1, N2] = All = ?acquire_nodes(2, Config),
+ ?match({atomic, ok}, mnesia:create_table(i_set, [{type, set}, {ram_copies, [N1]}, {index, [val]},
+ {disc_only_copies, [N2]}])),
+ ?match({atomic, ok}, mnesia:create_table(i_bag, [{type, bag}, {ram_copies, [N1]}, {index, [val]},
+ {disc_only_copies, [N2]}])),
+ ?match({atomic, ok}, mnesia:create_table(i_oset, [{type, ordered_set}, {ram_copies, [N1, N2]},
+ {index, [val]}])),
+
+ Tabs = [i_set, i_bag, i_oset],
+
+ Add = fun(Tab) ->
+ Write = fun(Tab) ->
+ Recs = [{Tab, N, N rem 5} || N <- lists:seq(1,10)],
+ [ok = mnesia:write(Rec) || Rec <- Recs],
+ Recs
+ end,
+ {atomic, Recs} = mnesia:sync_transaction(Write, [Tab]),
+ lists:sort(Recs)
+ end,
+
+ IRead = fun(Tab) ->
+ Read = fun(Tab) ->
+ [mnesia:index_read(Tab, N, val) || N <- lists:seq(0,4)]
+ end,
+ {atomic, Recs} = mnesia:transaction(Read, [Tab]),
+ lists:sort(lists:flatten(Recs))
+ end,
+
+ Delete = fun(Rec) ->
+ Del = fun() -> mnesia:delete_object(Rec) end,
+ {atomic, ok} = mnesia:sync_transaction(Del),
+ ok
+ end,
+
+
+ Recs = [Add(Tab) || Tab <- Tabs],
+ ?match(Recs, [IRead(Tab) || Tab <- Tabs]),
+ [Delete(Rec) || Rec <- lists:flatten(Recs)],
+
+ [?match({Tab,0}, {Tab,mnesia:table_info(Tab, size)}) || Tab <- Tabs],
+
+ [?match({Tab,Node,0, _}, rpc:call(Node, ?MODULE, index_size, [Tab]))
+ || Node <- All, Tab <- Tabs],
+ ?verify_mnesia(All, []).
+
+index_size(Tab) ->
+ %% White box testing
+ case mnesia:table_info(Tab, index_info) of
+ {index, _, [{_, {ram, Ref}}=Dbg]} -> {Tab, node(), ets:info(Ref, size), Dbg};
+ {index, _, [{_, {dets, Ref}}=Dbg]} -> {Tab, node(), dets:info(Ref, size), Dbg}
+ end.
diff --git a/lib/mnesia/test/mnesia_examples_test.erl b/lib/mnesia/test/mnesia_examples_test.erl
index 808e62d9c2..3bbb6e4d77 100644
--- a/lib/mnesia/test/mnesia_examples_test.erl
+++ b/lib/mnesia/test/mnesia_examples_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,14 @@
%%
-module(mnesia_examples_test).
-author('[email protected]').
--compile([export_all]).
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_group/2, end_per_group/2,
+ all/0, groups/0]).
+-export([bup/1, company/1, meter/1,
+ replica_test/1, sticky_replica_test/1, dist_test/1,
+ conflict_test/1, frag_test/1, frag2_test/1, remote_test/1,
+ remote_frag2_test/1, opt_load/1]).
+
-include("mnesia_test_lib.hrl").
init_per_testcase(Func, Conf) ->
diff --git a/lib/mnesia/test/mnesia_frag_test.erl b/lib/mnesia/test/mnesia_frag_test.erl
index 9f2102beb2..7b37fcb684 100644
--- a/lib/mnesia/test/mnesia_frag_test.erl
+++ b/lib/mnesia/test/mnesia_frag_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,7 +23,17 @@
-author('[email protected]').
-include("mnesia_test_lib.hrl").
--compile([export_all]).
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_group/2, end_per_group/2,
+ all/0, groups/0]).
+
+
+-export([nice_single/1, nice_multi/1, nice_access/1, iter_access/1,
+ consistency/1, evil_create/1, evil_delete/1, evil_change/1, evil_combine/1,
+ evil_loop/1, evil_delete_db_node/1]).
+
+
+-export([frag_dist/1]).
init_per_testcase(Func, Conf) ->
mnesia_test_lib:init_per_testcase(Func, Conf).
@@ -845,16 +855,7 @@ frag_rec_dist(Tab) ->
Fun = fun() -> mnesia:table_info(Tab, frag_size) end,
[Size || {_, Size} <- mnesia:activity(sync_dirty, Fun, mnesia_frag)].
-table_size(Tab) ->
- Node = mnesia:table_info(Tab, where_to_read),
- rpc:call(Node, mnesia, table_info, [Tab, size]).
-
sort_res(List) when is_list(List) ->
lists:sort(List);
sort_res(Else) ->
Else.
-
-rev_res(List) when is_list(List) ->
- lists:reverse(List);
-rev_res(Else) ->
- Else.
diff --git a/lib/mnesia/test/mnesia_install_test.erl b/lib/mnesia/test/mnesia_install_test.erl
index 103f85b3d6..2aee5137c3 100644
--- a/lib/mnesia/test/mnesia_install_test.erl
+++ b/lib/mnesia/test/mnesia_install_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,8 +21,13 @@
%%
-module(mnesia_install_test).
-author('[email protected]').
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_group/2, end_per_group/2,
+ all/0, groups/0]).
+
+-export([silly_durability/1, silly_move/1, silly_upgrade/1, conflict/1, dist/1,
+ silly/0, silly2/1]).
--compile([export_all]).
-include("mnesia_test_lib.hrl").
init_per_testcase(Func, Conf) ->
diff --git a/lib/mnesia/test/mnesia_isolation_test.erl b/lib/mnesia/test/mnesia_isolation_test.erl
index 63940ec05c..49bcec14af 100644
--- a/lib/mnesia/test/mnesia_isolation_test.erl
+++ b/lib/mnesia/test/mnesia_isolation_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,7 +22,36 @@
-module(mnesia_isolation_test).
-author('[email protected]').
--compile([export_all]).
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_group/2, end_per_group/2,
+ all/0, groups/0]).
+
+-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,
+ 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,
+ snmp_open_table/1, snmp_close_table/1,
+ change_table_copy_type/1, change_table_access/1,
+ add_table_copy/1, del_table_copy/1, dump_tables/1,
+ del_table_copy_1/1, del_table_copy_2/1, del_table_copy_3/1,
+ add_table_copy_1/1, add_table_copy_2/1, add_table_copy_3/1,
+ add_table_copy_4/1, move_table_copy_1/1, move_table_copy_2/1,
+ move_table_copy_3/1, move_table_copy_4/1,
+ dirty_updates_visible_direct/1,
+ dirty_reads_regardless_of_trans/1,
+ trans_update_invisibible_outside_trans/1,
+ trans_update_visible_inside_trans/1, write_shadows/1,
+ delete_shadows/1, write_delete_shadows_bag/1,
+ write_delete_shadows_bag2/1,
+ shadow_search/1, snmp_shadows/1,
+ rr_kill_copy/1, foldl/1, first_next/1]).
+
+-export([do_fun/4, burst_counter/3, burst_incr/2, get_held/0, get_info/1,
+ get_sticky/0, op/4, update_own/3, update_shared/3]).
+
-include("mnesia_test_lib.hrl").
init_per_testcase(Func, Conf) ->
@@ -668,16 +697,6 @@ unbound2(Config) when is_list(Config) ->
{B, {atomic, [{ul,{key,{17,42}},val}]}}]),
ok.
-receiver() ->
- receive
- {_Pid, begin_trans} ->
- receiver();
- Else ->
- Else
- after
- 10000 ->
- timeout
- end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1544,7 +1563,8 @@ trans_update_visible_inside_trans(Config) when is_list(Config) ->
?match({atomic, ok}, mnesia:create_table([{name, Tab},
{ram_copies, [Node1]}])),
ValPos = 3,
- RecA = {Tab, a, 1},
+ RecA = {Tab, a, 1},
+ RecA2 = {Tab, a, 2},
PatA = {Tab, '$1', 1},
RecB = {Tab, b, 3},
PatB = {Tab, '$1', 3},
@@ -1579,6 +1599,14 @@ trans_update_visible_inside_trans(Config) when is_list(Config) ->
?match([], mnesia:index_read(Tab, 3, ValPos)),
%% delete_object
+ ?match(ok, mnesia:delete_object(RecA2)),
+ ?match([RecA], mnesia:read({Tab, a})),
+ ?match([RecA], mnesia:wread({Tab, a})),
+ ?match([RecA], mnesia:match_object(PatA)),
+ ?match([a], mnesia:all_keys(Tab)),
+ ?match([RecA], mnesia:index_match_object(PatA, ValPos)),
+ ?match([RecA], mnesia:index_read(Tab, 1, ValPos)),
+
?match(ok, mnesia:delete_object(RecA)),
?match([], mnesia:read({Tab, a})),
?match([], mnesia:wread({Tab, a})),
diff --git a/lib/mnesia/test/mnesia_majority_test.erl b/lib/mnesia/test/mnesia_majority_test.erl
index 9811de6ae7..aae27e069e 100644
--- a/lib/mnesia/test/mnesia_majority_test.erl
+++ b/lib/mnesia/test/mnesia_majority_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,13 @@
%%
-module(mnesia_majority_test).
-author('[email protected]').
--compile(export_all).
+-export([init_per_testcase/2, end_per_testcase/2,
+ all/0]).
+
+-export([write/1, wread/1, delete/1, clear_table/1, frag/1,
+ change_majority/1, frag_change_majority/1
+ ]).
+
-include("mnesia_test_lib.hrl").
init_per_testcase(Func, Conf) ->
diff --git a/lib/mnesia/test/mnesia_measure_test.erl b/lib/mnesia/test/mnesia_measure_test.erl
index ad71fafecb..8eb3590168 100644
--- a/lib/mnesia/test/mnesia_measure_test.erl
+++ b/lib/mnesia/test/mnesia_measure_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,15 @@
%%
-module(mnesia_measure_test).
-author('[email protected]').
--compile([export_all]).
+
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_group/2, end_per_group/2,
+ all/0, groups/0]).
+
+-export([cost/1, dbn_meters/1,
+ ram_tpcb/1, disc_tpcb/1, disc_only_tpcb/1,
+ ram_meter/1, disc_meter/1, disc_only_meter/1]).
+
-include("mnesia_test_lib.hrl").
@@ -39,41 +47,12 @@ end_per_testcase(Func, Conf) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
all() ->
- [{group, prediction}, {group, consumption},
- {group, scalability}, {group, benchmarks}].
+ [{group, benchmarks}].
groups() ->
- [{prediction, [],
- [reader_disturbed_by_node_down,
- writer_disturbed_by_node_down,
- reader_disturbed_by_node_up,
- writer_disturbed_by_node_up,
- reader_disturbed_by_schema_ops,
- writer_disturbed_by_schema_ops,
- reader_disturbed_by_checkpoint,
- writer_disturbed_by_checkpoint,
- reader_disturbed_by_dump_log,
- writer_disturbed_by_dump_log,
- reader_disturbed_by_backup, writer_disturbed_by_backup,
- reader_disturbed_by_restore,
- writer_disturbed_by_restore, {group, fairness}]},
- {fairness, [],
- [reader_competing_with_reader,
- reader_competing_with_writer,
- writer_competing_with_reader,
- writer_competing_with_writer]},
- {consumption, [],
- [measure_resource_consumption,
- determine_resource_leakage]},
- {scalability, [],
- [determine_system_limits, performance_at_min_config,
- performance_at_max_config, performance_at_full_load,
- resource_consumption_at_min_config,
- resource_consumption_at_max_config,
- resource_consumption_at_full_load]},
- {benchmarks, [],
+ [{benchmarks, [],
[{group, meter}, cost, dbn_meters,
- measure_all_api_functions, {group, tpcb}]},
+ {group, tpcb}]},
{tpcb, [], [ram_tpcb, disc_tpcb, disc_only_tpcb]},
{meter, [], [ram_meter, disc_meter, disc_only_meter]}].
diff --git a/lib/mnesia/test/mnesia_nice_coverage_test.erl b/lib/mnesia/test/mnesia_nice_coverage_test.erl
index ffbe36e48d..f8c6b2ce20 100644
--- a/lib/mnesia/test/mnesia_nice_coverage_test.erl
+++ b/lib/mnesia/test/mnesia_nice_coverage_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,13 @@
%%
-module(mnesia_nice_coverage_test).
-author('[email protected]').
--compile([export_all]).
+
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_group/2, end_per_group/2,
+ all/0, groups/0]).
+
+-export([nice/1]).
+
-include("mnesia_test_lib.hrl").
-record(nice_tab, {key, val}).
diff --git a/lib/mnesia/test/mnesia_qlc_test.erl b/lib/mnesia/test/mnesia_qlc_test.erl
index 5067e86521..e66fd84995 100644
--- a/lib/mnesia/test/mnesia_qlc_test.erl
+++ b/lib/mnesia/test/mnesia_qlc_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,9 +21,18 @@
%%
-module(mnesia_qlc_test).
--compile(export_all).
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_group/2, end_per_group/2,
+ all/0, groups/0]).
+
+-export([frag/1, info/1, mnesia_down/1,
+ dirty_nice_ram_copies/1, dirty_nice_disc_copies/1,
+ dirty_nice_disc_only_copies/1,
+ trans_nice_ram_copies/1, trans_nice_disc_copies/1,
+ trans_nice_disc_only_copies/1, atomic_eval/1,
+ nested_qlc/1
+ ]).
--export([all/0,groups/0,init_per_group/2,end_per_group/2]).
-include("mnesia_test_lib.hrl").
-include_lib("stdlib/include/qlc.hrl").
diff --git a/lib/mnesia/test/mnesia_recovery_test.erl b/lib/mnesia/test/mnesia_recovery_test.erl
index 130b87346f..b5749408f8 100644
--- a/lib/mnesia/test/mnesia_recovery_test.erl
+++ b/lib/mnesia/test/mnesia_recovery_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,80 @@
%%
-module(mnesia_recovery_test).
-author('[email protected]').
--compile([export_all]).
+
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_group/2, end_per_group/2,
+ all/0, groups/0]).
+
+-export([coord_dies/1, after_full_disc_partition/1,
+ disc_less/1, garb_decision/1,
+ system_upgrade/1,
+ delete_during_start/1,
+ no_master_2/1, no_master_3/1, one_master_2/1, one_master_3/1,
+ two_master_2/1, two_master_3/1, all_master_2/1,
+ all_master_3/1,
+ dirty_read_during_down/1, trans_read_during_down/1,
+ mnesia_down_during_startup_disk_ram/1,
+ mnesia_down_during_startup_init_ram/1,
+ mnesia_down_during_startup_init_disc/1,
+ mnesia_down_during_startup_init_disc_only/1,
+ mnesia_down_during_startup_tm_ram/1,
+ mnesia_down_during_startup_tm_disc/1,
+ mnesia_down_during_startup_tm_disc_only/1,
+ with_checkpoint_same/1, with_checkpoint_other/1,
+ explicit_stop_during_snmp/1,
+ sym_trans_before_commit_kill_coord_node/1,
+ sym_trans_before_commit_kill_coord_pid/1,
+ sym_trans_before_commit_kill_part_after_ask/1,
+ sym_trans_before_commit_kill_part_before_ask/1,
+ sym_trans_after_commit_kill_coord_node/1,
+ sym_trans_after_commit_kill_coord_pid/1,
+ sym_trans_after_commit_kill_part_after_ask/1,
+ sym_trans_after_commit_kill_part_do_commit_pre/1,
+ sym_trans_after_commit_kill_part_do_commit_post/1,
+ sync_dirty_pre_kill_part/1,
+ sync_dirty_pre_kill_coord_node/1,
+ sync_dirty_pre_kill_coord_pid/1,
+ sync_dirty_post_kill_part/1,
+ sync_dirty_post_kill_coord_node/1,
+ sync_dirty_post_kill_coord_pid/1,
+ async_dirty_pre_kill_part/1,
+ async_dirty_pre_kill_coord_node/1,
+ async_dirty_pre_kill_coord_pid/1,
+ async_dirty_post_kill_part/1,
+ async_dirty_post_kill_coord_node/1,
+ async_dirty_post_kill_coord_pid/1,
+ asymtrans_part_ask/1,
+ asymtrans_part_commit_vote/1,
+ asymtrans_part_pre_commit/1,
+ asymtrans_part_log_commit/1,
+ asymtrans_part_do_commit/1,
+ asymtrans_coord_got_votes/1,
+ asymtrans_coord_pid_got_votes/1,
+ asymtrans_coord_log_commit_rec/1,
+ asymtrans_coord_pid_log_commit_rec/1,
+ asymtrans_coord_log_commit_dec/1,
+ asymtrans_coord_pid_log_commit_dec/1,
+ asymtrans_coord_rec_acc_pre_commit_log_commit/1,
+ asymtrans_coord_pid_rec_acc_pre_commit_log_commit/1,
+ asymtrans_coord_rec_acc_pre_commit_done_commit/1,
+ asymtrans_coord_pid_rec_acc_pre_commit_done_commit/1,
+ after_corrupt_files_decision_log_head/1,
+ after_corrupt_files_decision_log_tail/1,
+ after_corrupt_files_latest_log_head/1,
+ after_corrupt_files_latest_log_tail/1,
+ after_corrupt_files_table_dat_head/1,
+ after_corrupt_files_table_dat_tail/1,
+ after_corrupt_files_schema_dat_head/1,
+ after_corrupt_files_schema_dat_tail/1]).
+
+-export([reader/2, check/0, get_all_retainers/1,
+ verify_data/2, verify_where2read/1,
+ do_trans_loop/2,
+ start_stop/3, do_sym_trans/2, do_sync_dirty/2, do_async_dirty/2,
+ do_asym_trans/2, garb_handler/1, mymnesia_start/1
+ ]).
+
-include("mnesia_test_lib.hrl").
-include_lib("kernel/include/file.hrl").
@@ -657,6 +730,7 @@ do_trans_loop2(Tab, Father) ->
do_trans_loop2(Tab, Father);
Else ->
?error("Transaction failed: ~p ~n", [Else]),
+ io:format("INFO: ~p~n",[erlang:process_info(self())]),
Father ! test_done,
exit(shutdown)
end.
diff --git a/lib/mnesia/test/mnesia_registry_test.erl b/lib/mnesia/test/mnesia_registry_test.erl
index 3df37a2c8c..c15b8e97af 100644
--- a/lib/mnesia/test/mnesia_registry_test.erl
+++ b/lib/mnesia/test/mnesia_registry_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,12 @@
%%
-module(mnesia_registry_test).
-author('[email protected]').
--compile([export_all]).
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_group/2, end_per_group/2,
+ all/0, groups/0]).
+
+-export([good_dump/1, bad_dump/1, dump_registry/2, restore_registry/2]).
+
-include("mnesia_test_lib.hrl").
init_per_testcase(Func, Conf) ->
diff --git a/lib/mnesia/test/mnesia_schema_recovery_test.erl b/lib/mnesia/test/mnesia_schema_recovery_test.erl
index ca2dd74b34..e4199758c1 100644
--- a/lib/mnesia/test/mnesia_schema_recovery_test.erl
+++ b/lib/mnesia/test/mnesia_schema_recovery_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,79 @@
%%
-module(mnesia_schema_recovery_test).
-author('[email protected]').
--compile([export_all]).
+
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_group/2, end_per_group/2,
+ all/0, groups/0]).
+
+-export([interrupted_before_create_ram/1,
+ interrupted_before_create_disc/1,
+ interrupted_before_create_do/1,
+ interrupted_before_create_nostore/1,
+ interrupted_before_delete_ram/1,
+ interrupted_before_delete_disc/1,
+ interrupted_before_delete_do/1,
+ interrupted_before_add_ram/1,
+ interrupted_before_add_disc/1,
+ interrupted_before_add_do/1,
+ interrupted_before_add_kill_copier/1,
+ interrupted_before_move_ram/1,
+ interrupted_before_move_disc/1,
+ interrupted_before_move_do/1,
+ interrupted_before_move_kill_copier/1,
+ interrupted_before_delcopy_ram/1,
+ interrupted_before_delcopy_disc/1,
+ interrupted_before_delcopy_do/1,
+ interrupted_before_delcopy_kill_copier/1,
+ interrupted_before_addindex_ram/1,
+ interrupted_before_addindex_disc/1,
+ interrupted_before_addindex_do/1,
+ interrupted_before_delindex_ram/1,
+ interrupted_before_delindex_disc/1,
+ interrupted_before_delindex_do/1,
+ interrupted_before_change_type_ram2disc/1,
+ interrupted_before_change_type_ram2do/1,
+ interrupted_before_change_type_disc2ram/1,
+ interrupted_before_change_type_disc2do/1,
+ interrupted_before_change_type_do2ram/1,
+ interrupted_before_change_type_do2disc/1,
+ interrupted_before_change_type_other_node/1,
+ interrupted_before_change_schema_type/1,
+ interrupted_after_create_ram/1,
+ interrupted_after_create_disc/1,
+ interrupted_after_create_do/1,
+ interrupted_after_create_nostore/1,
+ interrupted_after_delete_ram/1,
+ interrupted_after_delete_disc/1,
+ interrupted_after_delete_do/1,
+ interrupted_after_add_ram/1,
+ interrupted_after_add_disc/1,
+ interrupted_after_add_do/1,
+ interrupted_after_add_kill_copier/1,
+ interrupted_after_move_ram/1,
+ interrupted_after_move_disc/1,
+ interrupted_after_move_do/1,
+ interrupted_after_move_kill_copier/1,
+ interrupted_after_delcopy_ram/1,
+ interrupted_after_delcopy_disc/1,
+ interrupted_after_delcopy_do/1,
+ interrupted_after_delcopy_kill_copier/1,
+ interrupted_after_addindex_ram/1,
+ interrupted_after_addindex_disc/1,
+ interrupted_after_addindex_do/1,
+ interrupted_after_delindex_ram/1,
+ interrupted_after_delindex_disc/1,
+ interrupted_after_delindex_do/1,
+ interrupted_after_change_type_ram2disc/1,
+ interrupted_after_change_type_ram2do/1,
+ interrupted_after_change_type_disc2ram/1,
+ interrupted_after_change_type_disc2do/1,
+ interrupted_after_change_type_do2ram/1,
+ interrupted_after_change_type_do2disc/1,
+ interrupted_after_change_type_other_node/1,
+ interrupted_after_change_schema_type/1]).
+
+
-include("mnesia_test_lib.hrl").
init_per_testcase(Func, Conf) ->
diff --git a/lib/mnesia/test/mnesia_test_lib.erl b/lib/mnesia/test/mnesia_test_lib.erl
index 0fabdc7929..1cdac3cde6 100644
--- a/lib/mnesia/test/mnesia_test_lib.erl
+++ b/lib/mnesia/test/mnesia_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -470,9 +470,9 @@ get_suite(Mod, {group, Suite}) ->
{_, _, TCList} = lists:keyfind(Suite, 1, Groups),
TCList
catch
- _:Reason ->
+ _:Reason:Stacktrace ->
io:format("Not implemented ~p ~p (~p ~p)~n",
- [Mod,Suite,Reason, erlang:get_stacktrace()]),
+ [Mod,Suite,Reason,Stacktrace]),
'NYI'
end;
get_suite(Mod, all) ->
@@ -774,7 +774,7 @@ init_nodes([], _File, _Line) ->
%% Returns [Name, Host]
node_to_name_and_host(Node) ->
- string:tokens(atom_to_list(Node), [$@]).
+ string:lexemes(atom_to_list(Node), [$@]).
lookup_config(Key,Config) ->
case lists:keysearch(Key,1,Config) of
diff --git a/lib/mnesia/test/mnesia_test_lib.hrl b/lib/mnesia/test/mnesia_test_lib.hrl
index ba7eb10ea2..b8eeb5783f 100644
--- a/lib/mnesia/test/mnesia_test_lib.hrl
+++ b/lib/mnesia/test/mnesia_test_lib.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -55,25 +55,25 @@
?error("Not Matching Actual result was:~n ~p~n",[_AR_0]),
{fail,_AR_0}
catch
- exit:{aborted, _ER_1} when
+ exit:{aborted, _ER_1}:Stacktrace when
element(1, _ER_1) =:= node_not_running;
element(1, _ER_1) =:= bad_commit;
element(1, _ER_1) =:= cyclic ->
%% Need to re-raise these to restart transaction
- erlang:raise(exit, {aborted, _ER_1}, erlang:get_stacktrace());
- exit:_AR_1 ->
+ erlang:raise(exit, {aborted, _ER_1}, Stacktrace);
+ exit:_AR_1:Stacktrace ->
case fun(_AR_EXIT_) -> {'EXIT', _AR_EXIT_} end(_AR_1) of
_AR_2 = ExpectedRes ->
?verbose("ok, ~n Result as expected:~p~n",[_AR_2]),
{success,_AR_2};
_AR_2 ->
?error("Not Matching Actual result was:~n ~p~n ~p~n",
- [_AR_2, erlang:get_stacktrace()]),
+ [_AR_2, Stacktrace]),
{fail,_AR_2}
end;
- _T1_:_AR_1 ->
+ _T1_:_AR_1:Stacktrace ->
?error("Not Matching Actual result was:~n ~p~n ~p~n",
- [{_T1_,_AR_1}, erlang:get_stacktrace()]),
+ [{_T1_,_AR_1}, Stacktrace]),
{fail,{_T1_,_AR_1}}
end
end()).
diff --git a/lib/mnesia/test/mnesia_trans_access_test.erl b/lib/mnesia/test/mnesia_trans_access_test.erl
index 4ed73ea859..723a85fd2c 100644
--- a/lib/mnesia/test/mnesia_trans_access_test.erl
+++ b/lib/mnesia/test/mnesia_trans_access_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,28 @@
%%
-module(mnesia_trans_access_test).
-author('[email protected]').
--compile([export_all]).
+
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_group/2, end_per_group/2,
+ all/0, groups/0]).
+
+-export([write/1, read/1, wread/1, delete/1, delete_object/1,
+ match_object/1, select/1, select14/1, all_keys/1, transaction/1,
+ basic_nested/1, mix_of_nested_activities/1,
+ nested_trans_both_ok/1, nested_trans_child_dies/1,
+ nested_trans_parent_dies/1, nested_trans_both_dies/1,
+ index_match_object/1, index_read/1,index_write/1,
+ index_update_set/1, index_update_bag/1,
+ add_table_index_ram/1, add_table_index_disc/1,
+ add_table_index_disc_only/1, create_live_table_index_ram/1,
+ create_live_table_index_disc/1,
+ create_live_table_index_disc_only/1, del_table_index_ram/1,
+ del_table_index_disc/1, del_table_index_disc_only/1,
+ idx_schema_changes_ram/1, idx_schema_changes_disc/1,
+ idx_schema_changes_disc_only/1]).
+
+-export([do_nested/1]).
+
-include("mnesia_test_lib.hrl").
init_per_testcase(Func, Conf) ->
diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk
index 81b15d65db..1cfb35c774 100644
--- a/lib/mnesia/vsn.mk
+++ b/lib/mnesia/vsn.mk
@@ -1 +1 @@
-MNESIA_VSN = 4.15
+MNESIA_VSN = 4.15.5
diff --git a/lib/observer/doc/src/Makefile b/lib/observer/doc/src/Makefile
index b38278a156..e843772f0b 100644
--- a/lib/observer/doc/src/Makefile
+++ b/lib/observer/doc/src/Makefile
@@ -9,11 +9,11 @@
# 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.
-#
+#
# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
# AB. All Rights Reserved.''
-#
+#
# $Id$
#
include $(ERL_TOP)/make/target.mk
@@ -45,17 +45,15 @@ XML_REF3_FILES = \
XML_REF6_FILES = observer_app.xml
XML_PART_FILES = \
- part.xml \
- part_notes.xml \
- part_notes_history.xml
+ part.xml
XML_CHAPTER_FILES = \
+ introduction_ug.xml \
crashdump_ug.xml \
etop_ug.xml \
observer_ug.xml \
ttb_ug.xml \
- notes.xml \
- notes_history.xml
+ notes.xml
BOOK_FILES = book.xml
@@ -69,9 +67,7 @@ ONLY_HTML_FILE =
GIF_FILES = \
et_processes.gif \
- et_modsprocs.gif \
- note.gif
-
+ et_modsprocs.gif
# ----------------------------------------------------
HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
@@ -88,9 +84,9 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
+XML_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -109,6 +105,7 @@ html: gifs $(HTML_REF_MAN_FILE) $(ONLY_HTML_FILE:%=$(HTMLDIR)/%)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN1DIR)/*
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
@@ -123,12 +120,12 @@ man: $(MAN1_FILES) $(MAN3_FILES) $(MAN6_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-debug opt:
+debug opt:
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
@@ -148,4 +145,3 @@ release_docs_spec: docs
release_spec:
-
diff --git a/lib/observer/doc/src/fascicules.xml b/lib/observer/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/observer/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/observer/doc/src/note.gif b/lib/observer/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/observer/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/observer/doc/src/notes.xml b/lib/observer/doc/src/notes.xml
index d329be5d5a..4d1a9a4f55 100644
--- a/lib/observer/doc/src/notes.xml
+++ b/lib/observer/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,226 @@
<p>This document describes the changes made to the Observer
application.</p>
+<section><title>Observer 2.8.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Observer 2.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Added possibility to garbage collect selected processes
+ and fixed a crash when the saved config file contained
+ bad data.</p>
+ <p>
+ Own Id: OTP-14993 Aux Id: PR-1666 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Use uri_string module instead of http_uri.</p>
+ <p>
+ Own Id: OTP-14902</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Observer 2.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ etop.hrl used a relative path to include
+ observer_backend.hrl, this is now changed to use
+ include_lib instead. runtime_tools/include is added to
+ the tertiary bootstrap.</p>
+ <p>
+ Own Id: OTP-14842 Aux Id: ERL-534 </p>
+ </item>
+ <item>
+ <p>
+ If a crashdump was truncated in the attributes section
+ for a module, crashdump_viewer would crash when a module
+ view was opened from the GUI. This bug was introduced in
+ OTP-20.2 and is now corrected.</p>
+ <p>
+ Own Id: OTP-14846 Aux Id: ERL-537 </p>
+ </item>
+ <item>
+ <p>
+ Optimized ets and mnesia table view tab in observer gui,
+ listing 10000 tables was previously very slow.</p>
+ <p>
+ Own Id: OTP-14856 Aux Id: ERIERL-117 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ When a process has many links and/or monitors, it could
+ earlier take very long time to display the process
+ information window. This is now improved by only showing
+ a few links and monitors, and then an link named
+ "more..." to expand the rest.</p>
+ <p>
+ Own Id: OTP-14725</p>
+ </item>
+ <item>
+ <p>
+ More crash dump info such as: process binary virtual heap
+ stats, full info for process causing out-of-mem during
+ GC, more port related info, and dirty scheduler info.</p>
+ <p>
+ Own Id: OTP-14820</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Observer 2.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A bug introduced in OTP-20 would make Crashdump Viewer
+ crash when trying to expand an empty binary. This is now
+ corrected.</p>
+ <p>
+ Own Id: OTP-14642</p>
+ </item>
+ <item>
+ <p>
+ If a match spec in the config file contained more than
+ one clause, observer would earlier crash when trying to
+ display it in the GUI. This is now corrected.</p>
+ <p>
+ Own Id: OTP-14643 Aux Id: ERL-489 </p>
+ </item>
+ <item>
+ <p>Writing of crash dumps is significantly faster.</p>
+ <p>Maps are now included in crash dumps.</p>
+ <p>Constants terms would only be shown in one process,
+ while other processes referencing the same constant term
+ would show a marker for incomplete heap. </p>
+ <p>
+ Own Id: OTP-14685 Aux Id: OTP-14611, OTP-14603, OTP-14595 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Binaries and some other data in crash dumps are now
+ encoded in base64 (instead of in hex), which will reduce
+ the size of crash dumps.</p>
+ <p>A few bugs in the handling of sub binaries in
+ <c>crashdump_viewer</c> have been fixed.</p>
+ <p>
+ Own Id: OTP-14686</p>
+ </item>
+ <item>
+ <p>
+ In order to allow future improvements, Crashdump Viewer
+ now checks the version tag of the crashdump to see that
+ it is a known format. If the crashdump version is newer
+ than Crashdump Viewer is prepared to read, then an
+ information dialog is displayed before Crashdump Viewer
+ terminates.</p>
+ <p>
+ If an incomplete process heap is discovered in a
+ crashdump, Crashdump Viewer will now display a warning
+ for this, similar to the warning displayed when a
+ crashdump is truncated. Incomplete heaps can occur if for
+ instance the literals are not included, which is the case
+ for all dumps prior to OTP-20.2.</p>
+ <p>
+ Own Id: OTP-14755</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Observer 2.5</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>The following improvements are done to Crashdump
+ Viewer:</p> <list> <item>Reading of crash dumps with many
+ binaries is optimized.</item> <item>A progress bar is
+ shown when the detail view for a process is
+ opened.</item> <item>The <c>cdv</c> script now sets
+ <c>ERL_CRASH_DUMP_SECONDS=0</c> to avoid generating a new
+ crash dump from the node running the Crashdump
+ Viewer.</item> <item>A warning dialog is shown if the
+ node running the Crashdump Viewer could potentially
+ overwrite the crash dump under inspection.</item>
+ <item>Bugfix: In some situations, Crashdump Viewer could
+ not find the end of the 'Last calls' section in a crash
+ dump, and would erroneously mark the crash dump as
+ truncated. This is now corrected.</item> <item>Bugfix: In
+ some situations, process info for a specific process
+ would be marked as truncated by Crashdump Viewer, even if
+ the crash dump was truncated in the binary section - and
+ not related to the process in question. This is now
+ corrected.</item> </list>
+ <p>
+ Own Id: OTP-14386</p>
+ </item>
+ <item>
+ <p>
+ General Unicode improvements.</p>
+ <p>
+ Own Id: OTP-14462</p>
+ </item>
+ <item>
+ <p>
+ Tools are updated to show Unicode atoms correctly.</p>
+ <p>
+ Own Id: OTP-14464</p>
+ </item>
+ <item>
+ <p>
+ Add system statistics and limits to frontpage in
+ observer.</p>
+ <p>
+ Own Id: OTP-14536</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Observer 2.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/observer/doc/src/part_notes.xml b/lib/observer/doc/src/part_notes.xml
deleted file mode 100644
index ba15c39cda..0000000000
--- a/lib/observer/doc/src/part_notes.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Observer Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p>The <em>OBSERVER</em> application contains tools for tracing
- and investigation of distributed systems.</p>
- <p>For information about older versions, see
- <url href="part_notes_history_frame.html">Release Notes History</url>.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/observer/doc/src/part_notes_history.xml b/lib/observer/doc/src/part_notes_history.xml
deleted file mode 100644
index e60210924c..0000000000
--- a/lib/observer/doc/src/part_notes_history.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2006</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Observer Release Notes History</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p>The <em>OBSERVER</em> application contains tools for tracing
- and investigation of distributed systems.</p>
- </description>
- <include file="notes_history"></include>
-</part>
-
diff --git a/lib/observer/include/etop.hrl b/lib/observer/include/etop.hrl
index 002937e522..cda68422ab 100644
--- a/lib/observer/include/etop.hrl
+++ b/lib/observer/include/etop.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,4 +18,4 @@
%% %CopyrightEnd%
%%
--include("../../runtime_tools/include/observer_backend.hrl").
+-include_lib("runtime_tools/include/observer_backend.hrl").
diff --git a/lib/observer/priv/bin/cdv b/lib/observer/priv/bin/cdv
index d14fd47e41..2a509c16af 100755
--- a/lib/observer/priv/bin/cdv
+++ b/lib/observer/priv/bin/cdv
@@ -1,4 +1,4 @@
#!/bin/sh
-erl -noinput -s crashdump_viewer script_start $@
+erl -env ERL_CRASH_DUMP_SECONDS 0 -noinput -s crashdump_viewer script_start $@
diff --git a/lib/observer/priv/bin/cdv.bat b/lib/observer/priv/bin/cdv.bat
index 18136a30d6..fa87c08adf 100644
--- a/lib/observer/priv/bin/cdv.bat
+++ b/lib/observer/priv/bin/cdv.bat
@@ -1,2 +1,2 @@
@ECHO OFF
-CALL werl -s crashdump_viewer script_start %*
+CALL werl -env ERL_CRASH_DUMP_SECONDS 0 -s crashdump_viewer script_start %*
diff --git a/lib/observer/src/cdv_atom_cb.erl b/lib/observer/src/cdv_atom_cb.erl
index a123354c8f..87f613124c 100644
--- a/lib/observer/src/cdv_atom_cb.erl
+++ b/lib/observer/src/cdv_atom_cb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@ get_info(_) ->
{Info,TW}.
format({Bin,q}) when is_binary(Bin) ->
- [$'|binary_to_list(Bin)];
+ [$'|lists:flatten(io_lib:format("~ts",[Bin]))];
format({Bin,nq}) when is_binary(Bin) ->
lists:flatten(io_lib:format("~ts",[Bin]));
format(D) ->
diff --git a/lib/observer/src/cdv_bin_cb.erl b/lib/observer/src/cdv_bin_cb.erl
index 5472d36a6f..a4a542297c 100644
--- a/lib/observer/src/cdv_bin_cb.erl
+++ b/lib/observer/src/cdv_bin_cb.erl
@@ -38,6 +38,7 @@ init_bin_page(Parent,{Type,Bin}) ->
[{"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)}},
@@ -56,7 +57,7 @@ format_bin_fun(Format,Bin) ->
binary_to_term_fun(Bin) ->
fun() ->
try binary_to_term(Bin) of
- Term -> plain_html(io_lib:format("~p",[Term]))
+ Term -> plain_html(io_lib:format("~tp",[Term]))
catch error:badarg ->
Warning = "This binary can not be converted to an Erlang term",
observer_html_lib:warning(Warning)
@@ -70,6 +71,8 @@ hex_binary_fun(Bin) ->
plain_html(io_lib:format("~s",[S]))
end.
+format_hex(<<>>,_) ->
+ [];
format_hex(<<B1:4,B2:4>>,_) ->
[integer_to_list(B1,16),integer_to_list(B2,16)];
format_hex(<<B1:4,B2:4,Bin/binary>>,0) ->
diff --git a/lib/observer/src/cdv_detail_wx.erl b/lib/observer/src/cdv_detail_wx.erl
index 27057fd27f..4b1984c394 100644
--- a/lib/observer/src/cdv_detail_wx.erl
+++ b/lib/observer/src/cdv_detail_wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@
-behaviour(wx_object).
--export([start_link/4]).
+-export([start_link/5]).
-export([init/1, handle_event/2, handle_cast/2, terminate/2, code_change/3,
handle_call/3, handle_info/2]).
@@ -39,27 +39,51 @@
-define(ID_NOTEBOOK, 604).
%% Detail view
-start_link(Id, Data, ParentFrame, Callback) ->
- wx_object:start_link(?MODULE, [Id, Data, ParentFrame, Callback, self()], []).
+start_link(Id, Data, ParentFrame, Callback, App) ->
+ wx_object:start_link(?MODULE,[Id,Data,ParentFrame,Callback,App,self()],[]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-init([Id, Data, ParentFrame, Callback, Parent]) ->
+init([Id, Data, ParentFrame, Callback, App, Parent]) ->
+ display_progress(ParentFrame,App),
case Callback:get_details(Id, Data) of
{ok,Details} ->
- init(Id,ParentFrame,Callback,Parent,Details);
+ display_progress_pulse(Callback,Id),
+ init(Id,ParentFrame,Callback,App,Parent,Details);
{yes_no, Info, Fun} ->
+ destroy_progress(App),
case observer_lib:display_yes_no_dialog(Info) of
?wxID_YES -> Fun();
?wxID_NO -> ok
end,
{stop,normal};
{info,Info} ->
+ destroy_progress(App),
observer_lib:display_info_dialog(ParentFrame,Info),
{stop,normal}
end.
-init(Id,ParentFrame,Callback,Parent,{Title,Info,TW}) ->
+%% Display progress bar only if the calling app is crashdump_viewer
+display_progress(ParentFrame,cdv) ->
+ observer_lib:display_progress_dialog(ParentFrame,
+ "Crashdump Viewer",
+ "Reading data");
+display_progress(_,_) ->
+ ok.
+
+%% Display pulse while creating process detail page with much data
+display_progress_pulse(cdv_proc_cb,Pid) ->
+ observer_lib:report_progress({ok,"Displaying data for "++Pid}),
+ observer_lib:report_progress({ok,start_pulse});
+display_progress_pulse(_,_) ->
+ ok.
+
+destroy_progress(cdv) ->
+ observer_lib:sync_destroy_progress_dialog();
+destroy_progress(_) ->
+ ok.
+
+init(Id,ParentFrame,Callback,App,Parent,{Title,Info,TW}) ->
Frame=wxFrame:new(ParentFrame, ?wxID_ANY, [Title],
[{style, ?wxDEFAULT_FRAME_STYLE}, {size, {850,600}}]),
MenuBar = wxMenuBar:new(),
@@ -88,6 +112,7 @@ init(Id,ParentFrame,Callback,Parent,{Title,Info,TW}) ->
wxFrame:connect(Frame, close_window),
wxMenu:connect(Frame, command_menu_selected),
wxFrame:show(Frame),
+ destroy_progress(App),
{Frame, #state{parent=Parent,
id=Id,
frame=Frame,
@@ -133,7 +158,7 @@ handle_event(Event, _State) ->
error({unhandled_event, Event}).
handle_info(_Info, State) ->
- %% io:format("~p: ~p, Handle info: ~p~n", [?MODULE, ?LINE, _Info]),
+ %% io:format("~p: ~p, Handle info: ~tp~n", [?MODULE, ?LINE, _Info]),
{noreply, State}.
handle_call(Call, From, _State) ->
diff --git a/lib/observer/src/cdv_dist_cb.erl b/lib/observer/src/cdv_dist_cb.erl
index 2b4c9f56d1..ad1eb6e73c 100644
--- a/lib/observer/src/cdv_dist_cb.erl
+++ b/lib/observer/src/cdv_dist_cb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -78,7 +78,7 @@ init_gen_page(Parent, Info) ->
cdv_info_wx:start_link(Parent,{Fields,Info,[]}).
format({creations,Creations}) ->
- string:join([integer_to_list(C) || C <- Creations],",");
+ lists:flatten(lists:join(",",[integer_to_list(C) || C <- Creations]));
format(D) ->
D.
diff --git a/lib/observer/src/cdv_html_wx.erl b/lib/observer/src/cdv_html_wx.erl
index 0ab0ba4315..d9efa7fc2f 100644
--- a/lib/observer/src/cdv_html_wx.erl
+++ b/lib/observer/src/cdv_html_wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -52,8 +52,12 @@ init([ParentWin, HtmlText]) ->
init(ParentWin, HtmlText, undefined, cdv).
init(ParentWin, HtmlText, Tab, App) ->
+ %% If progress dialog is shown, remove it now - and sett cursor busy instead
+ observer_lib:destroy_progress_dialog(),
+ wx_misc:beginBusyCursor(),
HtmlWin = observer_lib:html_window(ParentWin),
wxHtmlWindow:setPage(HtmlWin,HtmlText),
+ wx_misc:endBusyCursor(),
{HtmlWin, #state{panel=HtmlWin,expand_table=Tab,app=App}}.
%%%%%%%%%%%%%%%%%%%%%%% Callbacks %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -62,7 +66,7 @@ handle_info(active, State) ->
{noreply, State};
handle_info(Info, State) ->
- io:format("~p:~p: Unhandled info: ~p~n", [?MODULE, ?LINE, Info]),
+ io:format("~p:~p: Unhandled info: ~tp~n", [?MODULE, ?LINE, Info]),
{noreply, State}.
terminate(_Reason, _State) ->
@@ -72,7 +76,7 @@ code_change(_, _, State) ->
{ok, State}.
handle_call(Msg, _From, State) ->
- io:format("~p~p: Unhandled Call ~p~n",[?MODULE, ?LINE, Msg]),
+ io:format("~p~p: Unhandled Call ~tp~n",[?MODULE, ?LINE, Msg]),
{reply, ok, State}.
handle_cast({detail_win_closed, Id},#state{expand_wins=Opened0}=State) ->
@@ -80,7 +84,7 @@ handle_cast({detail_win_closed, Id},#state{expand_wins=Opened0}=State) ->
{noreply, State#state{expand_wins=Opened}};
handle_cast(Msg, State) ->
- io:format("~p~p: Unhandled cast ~p~n",[?MODULE, ?LINE, Msg]),
+ io:format("~p~p: Unhandled cast ~tp~n",[?MODULE, ?LINE, Msg]),
{noreply, State}.
handle_event(#wx{event=#wxHtmlLink{type=command_html_link_clicked,
@@ -90,21 +94,21 @@ handle_event(#wx{event=#wxHtmlLink{type=command_html_link_clicked,
case Target of
"#Binary?" ++ BinSpec ->
[{"offset",Off},{"size",Size},{"pos",Pos}] =
- httpd:parse_query(BinSpec),
+ uri_string:dissect_query(BinSpec),
Id = {cdv, {list_to_integer(Off),
list_to_integer(Size),
list_to_integer(Pos)}},
expand(Id,cdv_bin_cb,State);
"#OBSBinary?" ++ BinSpec ->
[{"key1",Preview},{"key2",Size},{"key3",Hash}] =
- httpd:parse_query(BinSpec),
+ uri_string:dissect_query(BinSpec),
Id = {obs, {Tab, {list_to_integer(Preview),
list_to_integer(Size),
list_to_integer(Hash)}}},
expand(Id,cdv_bin_cb,State);
"#Term?" ++ TermKeys ->
[{"key1",Key1},{"key2",Key2},{"key3",Key3}] =
- httpd:parse_query(TermKeys),
+ uri_string:dissect_query(TermKeys),
Id = {cdv, {Tab,{list_to_integer(Key1),
list_to_integer(Key2),
list_to_integer(Key3)}}},
@@ -118,16 +122,17 @@ handle_event(#wx{event=#wxHtmlLink{type=command_html_link_clicked,
{noreply, NewState};
handle_event(Event, State) ->
- io:format("~p:~p: Unhandled event ~p\n", [?MODULE,?LINE,Event]),
+ io:format("~p:~p: Unhandled event ~tp\n", [?MODULE,?LINE,Event]),
{noreply, State}.
%%%-----------------------------------------------------------------
%%% Internal
-expand(Id,Callback,#state{expand_wins=Opened0}=State) ->
+expand(Id,Callback,#state{expand_wins=Opened0, app=App}=State) ->
Opened =
case lists:keyfind(Id,1,Opened0) of
false ->
- EW = cdv_detail_wx:start_link(Id,[],State#state.panel,Callback),
+ EW = cdv_detail_wx:start_link(Id,[],State#state.panel,
+ Callback,App),
wx_object:get_pid(EW) ! active,
[{Id,EW}|Opened0];
{_,EW} ->
diff --git a/lib/observer/src/cdv_info_wx.erl b/lib/observer/src/cdv_info_wx.erl
index 01fe6b15f2..0a23d4ae3f 100644
--- a/lib/observer/src/cdv_info_wx.erl
+++ b/lib/observer/src/cdv_info_wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -65,7 +65,7 @@ handle_info(active, State) ->
{noreply, State};
handle_info(Info, State) ->
- io:format("~p:~p: Unhandled info: ~p~n", [?MODULE, ?LINE, Info]),
+ io:format("~p:~p: Unhandled info: ~tp~n", [?MODULE, ?LINE, Info]),
{noreply, State}.
terminate(_Reason, _State) ->
@@ -88,13 +88,17 @@ handle_call(new_dump, _From, #state{callback=Callback,panel=Panel,
{reply, ok, State#state{fpanel=NewFPanel,trunc_warn=TW}};
handle_call(Msg, _From, State) ->
- io:format("~p~p: Unhandled Call ~p~n",[?MODULE, ?LINE, Msg]),
+ io:format("~p~p: Unhandled Call ~tp~n",[?MODULE, ?LINE, Msg]),
{reply, ok, State}.
handle_cast(Msg, State) ->
- io:format("~p~p: Unhandled cast ~p~n",[?MODULE, ?LINE, Msg]),
+ io:format("~p~p: Unhandled cast ~tp~n",[?MODULE, ?LINE, Msg]),
{noreply, State}.
+handle_event(#wx{obj=MoreEntry,event=#wxMouse{type=left_down},userData={more,More}}, State) ->
+ observer_lib:add_scroll_entries(MoreEntry,More),
+ {noreply, State};
+
handle_event(#wx{event=#wxMouse{type=left_down},userData=Target}, State) ->
cdv_virtual_list_wx:start_detail_win(Target),
{noreply, State};
@@ -108,7 +112,7 @@ handle_event(#wx{obj=Obj,event=#wxMouse{type=leave_window}},State) ->
{noreply, State};
handle_event(Event, State) ->
- io:format("~p:~p: Unhandled event ~p\n", [?MODULE,?LINE,Event]),
+ io:format("~p:~p: Unhandled event ~tp\n", [?MODULE,?LINE,Event]),
{noreply, State}.
%%%-----------------------------------------------------------------
diff --git a/lib/observer/src/cdv_mem_cb.erl b/lib/observer/src/cdv_mem_cb.erl
index abeddc7335..99ffdda765 100644
--- a/lib/observer/src/cdv_mem_cb.erl
+++ b/lib/observer/src/cdv_mem_cb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -49,9 +49,7 @@ gen_mem_info_fields([]) ->
[].
upper(Key) ->
- string:join([string:to_upper([H]) ++ T ||
- [H|T] <- string:tokens(Key,"_")]," ").
-
+ lists:join(" ", [string:titlecase(Word) || Word <- string:split(Key, "_", all)]).
%%%-----------------------------------------------------------------
%%% Allocated areas page
diff --git a/lib/observer/src/cdv_multi_wx.erl b/lib/observer/src/cdv_multi_wx.erl
index b511503752..79a44245aa 100644
--- a/lib/observer/src/cdv_multi_wx.erl
+++ b/lib/observer/src/cdv_multi_wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -94,7 +94,7 @@ handle_info(active, State) ->
{noreply, NewState};
handle_info(Info, State) ->
- io:format("~p:~p: Unhandled info: ~p~n", [?MODULE, ?LINE, Info]),
+ io:format("~p:~p: Unhandled info: ~tp~n", [?MODULE, ?LINE, Info]),
{noreply, State}.
terminate(_Reason, _State) ->
@@ -112,11 +112,11 @@ handle_call(new_dump, _From, State) ->
{reply, ok, NewState};
handle_call(Msg, _From, State) ->
- io:format("~p:~p: Unhandled Call ~p~n",[?MODULE, ?LINE, Msg]),
+ io:format("~p:~p: Unhandled Call ~tp~n",[?MODULE, ?LINE, Msg]),
{reply, ok, State}.
handle_cast(Msg, State) ->
- io:format("~p:~p: Unhandled cast ~p~n",[?MODULE, ?LINE, Msg]),
+ io:format("~p:~p: Unhandled cast ~tp~n",[?MODULE, ?LINE, Msg]),
{noreply, State}.
handle_event(#wx{event=#wxCommand{type=command_listbox_selected,
@@ -136,7 +136,7 @@ handle_event(#wx{event=#wxCommand{type=command_listbox_selected,
{noreply,NewState};
handle_event(Event, State) ->
- io:format("~p:~p: Unhandled event ~p\n", [?MODULE,?LINE,Event]),
+ io:format("~p:~p: Unhandled event ~tp\n", [?MODULE,?LINE,Event]),
{noreply, State}.
%%%%%%%%%%%%%%%%%%%%%%% Internal %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/observer/src/cdv_port_cb.erl b/lib/observer/src/cdv_port_cb.erl
index b5cbe8132d..cbd5f696a6 100644
--- a/lib/observer/src/cdv_port_cb.erl
+++ b/lib/observer/src/cdv_port_cb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,7 +34,8 @@
-define(COL_CONN, ?COL_ID+1).
-define(COL_NAME, ?COL_CONN+1).
-define(COL_CTRL, ?COL_NAME+1).
--define(COL_SLOT, ?COL_CTRL+1).
+-define(COL_QUEUE, ?COL_CTRL+1).
+-define(COL_SLOT, ?COL_QUEUE+1).
@@ -44,6 +45,7 @@ col_to_elem(?COL_ID) -> #port.id;
col_to_elem(?COL_CONN) -> #port.connected;
col_to_elem(?COL_NAME) -> #port.name;
col_to_elem(?COL_CTRL) -> #port.controls;
+col_to_elem(?COL_QUEUE) -> #port.queue;
col_to_elem(?COL_SLOT) -> #port.slot.
col_spec() ->
@@ -51,6 +53,7 @@ col_spec() ->
{"Connected", ?wxLIST_FORMAT_LEFT, 120},
{"Name", ?wxLIST_FORMAT_LEFT, 150},
{"Controls", ?wxLIST_FORMAT_LEFT, 200},
+ {"Queue", ?wxLIST_FORMAT_RIGHT, 100},
{"Slot", ?wxLIST_FORMAT_RIGHT, 50}].
get_info(_) ->
@@ -96,9 +99,17 @@ format(D) ->
info_fields() ->
[{"Overview",
[{"Name", name},
+ {"State", state},
+ {"Task Flags", task_flags},
{"Connected", {click,connected}},
{"Slot", slot},
- {"Controls", controls}]},
+ {"Controls", controls},
+ {"Input bytes", input},
+ {"Output bytes", output},
+ {"Queue bytes", queue},
+ {"Port data", port_data}]},
{scroll_boxes,
[{"Links",1,{click,links}},
- {"Monitors",1,{click,monitors}}]}].
+ {"Monitors",1,{click,monitors}},
+ {"Suspended",1,{click,suspended}}
+ ]}].
diff --git a/lib/observer/src/cdv_proc_cb.erl b/lib/observer/src/cdv_proc_cb.erl
index 592150146b..2497b4889e 100644
--- a/lib/observer/src/cdv_proc_cb.erl
+++ b/lib/observer/src/cdv_proc_cb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -71,7 +71,7 @@ get_details(Id, _) ->
Proplist0 =
crashdump_viewer:to_proplist(record_info(fields,proc),Info),
Proplist = [{expand_table,Tab}|Proplist0],
- Title = io_lib:format("~s (~s)",[Info#proc.name, Id]),
+ Title = io_lib:format("~ts (~s)",[Info#proc.name, Id]),
{ok,{Title,Proplist,TW}};
{error,{other_node,NodeId}} ->
Info = "The process you are searching for was residing on "
@@ -149,6 +149,10 @@ info_fields() ->
{"Old Heap", old_heap},
{"Heap Unused", heap_unused},
{"Old Heap Unused", old_heap_unused},
+ {"Binary vheap", bin_vheap},
+ {"Old Binary vheap", old_bin_vheap},
+ {"Binary vheap unused", bin_vheap_unused},
+ {"Old Binary vheap unused", old_bin_vheap_unused},
{"Number of Heap Fragements", num_heap_frag},
{"Heap Fragment Data",heap_frag_data},
{"New Heap Start", new_heap_start},
diff --git a/lib/observer/src/cdv_sched_cb.erl b/lib/observer/src/cdv_sched_cb.erl
index 192aaf31a7..a3695a9418 100644
--- a/lib/observer/src/cdv_sched_cb.erl
+++ b/lib/observer/src/cdv_sched_cb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,7 +31,8 @@
%% Columns
-define(COL_ID, 0).
--define(COL_PROC, ?COL_ID+1).
+-define(COL_TYPE, ?COL_ID+1).
+-define(COL_PROC, ?COL_TYPE+1).
-define(COL_PORT, ?COL_PROC+1).
-define(COL_RQL, ?COL_PORT+1).
-define(COL_PQL, ?COL_RQL+1).
@@ -39,6 +40,7 @@
%% Callbacks for cdv_virtual_list_wx
col_to_elem(id) -> col_to_elem(?COL_ID);
col_to_elem(?COL_ID) -> #sched.name;
+col_to_elem(?COL_TYPE) -> #sched.type;
col_to_elem(?COL_PROC) -> #sched.process;
col_to_elem(?COL_PORT) -> #sched.port;
col_to_elem(?COL_RQL) -> #sched.run_q;
@@ -46,6 +48,7 @@ col_to_elem(?COL_PQL) -> #sched.port_q.
col_spec() ->
[{"Id", ?wxLIST_FORMAT_RIGHT, 50},
+ {"Type", ?wxLIST_FORMAT_CENTER, 100},
{"Current Process", ?wxLIST_FORMAT_CENTER, 130},
{"Current Port", ?wxLIST_FORMAT_CENTER, 130},
{"Run Queue Length", ?wxLIST_FORMAT_RIGHT, 180},
@@ -73,7 +76,8 @@ detail_pages() ->
[{"Scheduler Information", fun init_gen_page/2}].
init_gen_page(Parent, Info0) ->
- Fields = info_fields(),
+ Type = proplists:get_value(type, Info0),
+ Fields = info_fields(Type),
Details = proplists:get_value(details, Info0),
Info = if is_map(Details) -> Info0 ++ maps:to_list(Details);
true -> Info0
@@ -81,15 +85,16 @@ init_gen_page(Parent, Info0) ->
cdv_info_wx:start_link(Parent,{Fields,Info,[]}).
%%% Internal
-info_fields() ->
+info_fields(Type) ->
[{"Scheduler Overview",
[{"Id", id},
+ {"Type", type},
{"Current Process",process},
{"Current Port", port},
{"Sleep Info Flags", sleep_info},
{"Sleep Aux Work", sleep_aux}
]},
- {"Run Queues",
+ {run_queues_header(Type),
[{"Flags", runq_flags},
{"Priority Max Length", runq_max},
{"Priority High Length", runq_high},
@@ -116,3 +121,8 @@ info_fields() ->
{" ", {currp_stack, 11}}
]}
].
+
+run_queues_header(normal) ->
+ "Run Queues";
+run_queues_header(DirtyX) ->
+ "Run Queues (common for all '" ++ atom_to_list(DirtyX) ++ "' schedulers)".
diff --git a/lib/observer/src/cdv_table_wx.erl b/lib/observer/src/cdv_table_wx.erl
index df16230b70..0f28a51017 100644
--- a/lib/observer/src/cdv_table_wx.erl
+++ b/lib/observer/src/cdv_table_wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -74,7 +74,7 @@ handle_info(active, State) ->
{noreply, State};
handle_info(Info, State) ->
- io:format("~p:~p: Unhandled info: ~p~n", [?MODULE, ?LINE, Info]),
+ io:format("~p:~p: Unhandled info: ~tp~n", [?MODULE, ?LINE, Info]),
{noreply, State}.
terminate(_Reason, _State) ->
@@ -84,15 +84,15 @@ code_change(_, _, State) ->
{ok, State}.
handle_call(Msg, _From, State) ->
- io:format("~p~p: Unhandled Call ~p~n",[?MODULE, ?LINE, Msg]),
+ io:format("~p~p: Unhandled Call ~tp~n",[?MODULE, ?LINE, Msg]),
{reply, ok, State}.
handle_cast(Msg, State) ->
- io:format("~p~p: Unhandled cast ~p~n",[?MODULE, ?LINE, Msg]),
+ io:format("~p~p: Unhandled cast ~tp~n",[?MODULE, ?LINE, Msg]),
{noreply, State}.
handle_event(Event, State) ->
- io:format("~p:~p: Unhandled event ~p\n", [?MODULE,?LINE,Event]),
+ io:format("~p:~p: Unhandled event ~tp\n", [?MODULE,?LINE,Event]),
{noreply, State}.
%%%%%%%%%%%%%%%%%%%%%%% Internal %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/observer/src/cdv_term_cb.erl b/lib/observer/src/cdv_term_cb.erl
index f0d90dde7c..91de6449c4 100644
--- a/lib/observer/src/cdv_term_cb.erl
+++ b/lib/observer/src/cdv_term_cb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,23 +30,31 @@ detail_pages() ->
[{"Term", fun init_term_page/2}].
init_term_page(ParentWin, {Type, [Term, Tab]}) ->
+ observer_lib:report_progress({ok,"Expanding term"}),
+ observer_lib:report_progress({ok,start_pulse}),
Expanded = expand(Term, true),
BinSaved = expand(Term, Tab),
+ observer_lib:report_progress({ok,stop_pulse}),
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_term_fun(Format,Term,Tab) ->
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}
catch error:badarg ->
Warning = "This term can not be formatted with " ++ Format,
observer_html_lib:warning(Warning)
+ after
+ observer_lib:report_progress({ok,stop_pulse})
end
end.
@@ -57,13 +65,7 @@ expand(['#CDVBin',Offset,Size,Pos], true) ->
{ok,Bin} = crashdump_viewer:expand_binary({Offset,Size,Pos}),
Bin;
expand(Bin, Tab) when is_binary(Bin), not is_boolean(Tab) ->
- Size = byte_size(Bin),
- PrevSize = min(Size, 10) * 8,
- <<Preview:PrevSize, _/binary>> = Bin,
- Hash = erlang:phash2(Bin),
- Key = {Preview, Size, Hash},
- ets:insert(Tab, {Key,Bin}),
- ['#OBSBin',Preview,Size,Hash];
+ observer_lib:make_obsbin(Bin, Tab);
expand([H|T], Expand) ->
case expand(T, Expand) of
ET when is_list(ET) ->
diff --git a/lib/observer/src/cdv_virtual_list_wx.erl b/lib/observer/src/cdv_virtual_list_wx.erl
index ebf58865e9..2702301021 100644
--- a/lib/observer/src/cdv_virtual_list_wx.erl
+++ b/lib/observer/src/cdv_virtual_list_wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -73,7 +73,7 @@ start_detail_win(Id) ->
"#Port"++_ ->
start_detail_win(Id, port);
_ ->
- io:format("cdv: unknown identifier: ~p~n",[Id]),
+ io:format("cdv: unknown identifier: ~tp~n",[Id]),
ignore
end.
@@ -174,7 +174,7 @@ do_start_detail_win(Id, #state{panel=Panel,detail_wins=Opened,
case lists:keyfind(Id, 1, Opened) of
false ->
Data = call(Holder, {get_data, self(), Id}),
- case cdv_detail_wx:start_link(Id, Data, Panel, Callback) of
+ case cdv_detail_wx:start_link(Id, Data, Panel, Callback, cdv) of
{error, _} -> Opened;
IW -> [{Id, IW} | Opened]
end;
@@ -195,7 +195,7 @@ call(Holder, What) when is_pid(Holder) ->
erlang:demonitor(Ref),
Res
after 5000 ->
- io:format("Hanging call ~p~n",[What]),
+ io:format("Hanging call ~tp~n",[What]),
""
end;
call(_,_) ->
@@ -214,7 +214,7 @@ handle_info(active, State) ->
{noreply, State};
handle_info(Info, State) ->
- io:format("~p:~p, Unexpected info: ~p~n", [?MODULE, ?LINE, Info]),
+ io:format("~p:~p, Unexpected info: ~tp~n", [?MODULE, ?LINE, Info]),
{noreply, State}.
terminate(_Reason, #state{holder=Holder}) ->
@@ -236,7 +236,7 @@ handle_call(new_dump, _From,
{reply, ok, State#state{detail_wins=[],holder=NewHolder,trunc_warn=TW}};
handle_call(Msg, _From, State) ->
- io:format("~p:~p: Unhandled call ~p~n",[?MODULE, ?LINE, Msg]),
+ io:format("~p:~p: Unhandled call ~tp~n",[?MODULE, ?LINE, Msg]),
{reply, ok, State}.
handle_cast({start_detail_win,Id}, State) ->
@@ -248,7 +248,7 @@ handle_cast({detail_win_closed, Id},#state{detail_wins=Opened}=State) ->
{noreply, State#state{detail_wins=Opened2}};
handle_cast(Msg, State) ->
- io:format("~p:~p: Unhandled cast ~p~n", [?MODULE, ?LINE, Msg]),
+ io:format("~p:~p: Unhandled cast ~tp~n", [?MODULE, ?LINE, Msg]),
{noreply, State}.
%%%%%%%%%%%%%%%%%%%%LOOP%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -322,7 +322,7 @@ handle_event(#wx{event=#wxList{type=command_list_item_activated,
{noreply, State};
handle_event(Event, State) ->
- io:format("~p:~p: handle event ~p\n", [?MODULE, ?LINE, Event]),
+ io:format("~p:~p: handle event ~tp\n", [?MODULE, ?LINE, Event]),
{noreply, State}.
@@ -382,7 +382,7 @@ table_holder(#holder{callback=Callback, attrs=Attrs, info=Info}=S0) ->
stop ->
ok;
What ->
- io:format("Table holder got ~p~n",[What]),
+ io:format("Table holder got ~tp~n",[What]),
table_holder(S0)
end.
diff --git a/lib/observer/src/cdv_wx.erl b/lib/observer/src/cdv_wx.erl
index 1e3fb6289e..78a897111c 100644
--- a/lib/observer/src/cdv_wx.erl
+++ b/lib/observer/src/cdv_wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -130,8 +130,9 @@ init(File0) ->
{ok,File} ->
%% Set window title
T1 = "Crashdump Viewer: ",
+ FileLength = string:length(File),
Title =
- if length(File) > 70 ->
+ if FileLength > 70 ->
T1 ++ filename:basename(File);
true ->
T1 ++ File
@@ -306,7 +307,7 @@ handle_info({'EXIT', Pid, normal}, #state{server=Pid}=State) ->
{stop, normal, State};
handle_info({'EXIT', Pid, _Reason}, State) ->
- io:format("Child (~s) crashed exiting: ~p ~p~n",
+ io:format("Child (~s) crashed exiting: ~p ~tp~n",
[pid2panel(Pid, State), Pid,_Reason]),
{stop, normal, State};
@@ -412,15 +413,25 @@ load_dump(Frame,undefined) ->
error
end;
load_dump(Frame,FileName) ->
- ok = observer_lib:display_progress_dialog("Crashdump Viewer",
+ case maybe_warn_filename(FileName) of
+ continue ->
+ do_load_dump(Frame,FileName);
+ stop ->
+ error
+ end.
+
+do_load_dump(Frame,FileName) ->
+ ok = observer_lib:display_progress_dialog(wx:null(),
+ "Crashdump Viewer",
"Loading crashdump"),
crashdump_viewer:read_file(FileName),
case observer_lib:wait_for_progress() of
ok ->
%% Set window title
T1 = "Crashdump Viewer: ",
+ FileLength = string:length(FileName),
Title =
- if length(FileName) > 70 ->
+ if FileLength > 70 ->
T1 ++ filename:basename(FileName);
true ->
T1 ++ FileName
@@ -431,6 +442,33 @@ load_dump(Frame,FileName) ->
error
end.
+maybe_warn_filename(FileName) ->
+ case os:getenv("ERL_CRASH_DUMP_SECONDS")=="0" orelse
+ os:getenv("ERL_CRASH_DUMP_BYTES")=="0" of
+ true ->
+ continue;
+ false ->
+ DumpName = case os:getenv("ERL_CRASH_DUMP") of
+ false -> filename:absname("erl_crash.dump");
+ Name -> filename:absname(Name)
+ end,
+ case filename:absname(FileName) of
+ DumpName ->
+ Warning =
+ "WARNING: the current crashdump might be overwritten "
+ "if the crashdump_viewer node crashes.\n\n"
+ "Renaming the file before inspecting it will "
+ "remove the problem.\n\n"
+ "Do you want to continue?",
+ case observer_lib:display_yes_no_dialog(Warning) of
+ ?wxID_YES -> continue;
+ ?wxID_NO -> stop
+ end;
+ _ ->
+ continue
+ end
+ end.
+
%%%-----------------------------------------------------------------
%%% Find help document (HTML files)
get_help_doc(HelpId) ->
diff --git a/lib/observer/src/crashdump_viewer.erl b/lib/observer/src/crashdump_viewer.erl
index 8d70f5e2c8..14b086ff58 100644
--- a/lib/observer/src/crashdump_viewer.erl
+++ b/lib/observer/src/crashdump_viewer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,17 +26,31 @@
%% Tables
%% ------
%% cdv_dump_index_table: This table holds all tags read from the
-%% crashdump. Each tag indicates where the information about a
-%% specific item starts. The table entry for a tag includes the start
-%% position for this item-information. In a crash dump file, all tags
-%% start with a "=" at the beginning of a line.
+%% crashdump, except the 'binary' tag. Each tag indicates where the
+%% information about a specific item starts. The table entry for a
+%% tag includes the start position for this item-information. In a
+%% crash dump file, all tags start with a "=" at the beginning of a
+%% line.
+%%
+%% cdv_binary_index_table: This table holds all 'binary' tags. The hex
+%% address for each binary is converted to its integer value before
+%% storing Address -> Start Position in this table. The hex value of
+%% the address is never used for lookup.
+%%
+%% cdv_reg_proc_table: This table holds mappings between pid and
+%% registered name. This is used for timers and monitors.
+%%
+%% cdv_heap_file_chars: For each 'proc_heap' and 'literals' tag, this
+%% table contains the number of characters to read from the crash dump
+%% file. This is used for giving an indication in percent of the
+%% progress when parsing this data.
+%%
%%
%% Process state
%% -------------
%% file: The name of the crashdump currently viewed.
%% dump_vsn: The version number of the crashdump
%% wordsize: 4 | 8, the number of bytes in a word.
-%% binaries: a gb_tree containing binaries or links to binaries in the dump
%%
%% User API
@@ -74,6 +88,9 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
+%% Test support
+-export([get_dump_versions/0]).
+
%% Debug support
-export([debug/1,stop_debug/0]).
@@ -87,7 +104,11 @@
-define(max_line_size,100). % max number of bytes (i.e. characters) the
% line_head/1 function can return
-define(not_available,"N/A").
+-define(binary_size_progress_limit,10000).
+-define(max_dump_version,[0,5]).
+%% The value of the next define must be divisible by 4.
+-define(base64_chunk_size, (4*256)).
%% All possible tags - use macros in order to avoid misspelling in the code
-define(abort,abort).
@@ -95,6 +116,10 @@
-define(allocator,allocator).
-define(atoms,atoms).
-define(binary,binary).
+-define(dirty_cpu_scheduler,dirty_cpu_scheduler).
+-define(dirty_cpu_run_queue,dirty_cpu_run_queue).
+-define(dirty_io_scheduler,dirty_io_scheduler).
+-define(dirty_io_run_queue,dirty_io_run_queue).
-define(ende,ende).
-define(erl_crash_dump,erl_crash_dump).
-define(ets,ets).
@@ -104,8 +129,11 @@
-define(index_table,index_table).
-define(instr_data,instr_data).
-define(internal_ets,internal_ets).
+-define(literals,literals).
-define(loaded_modules,loaded_modules).
-define(memory,memory).
+-define(memory_map,memory_map).
+-define(memory_status,memory_status).
-define(mod,mod).
-define(no_distribution,no_distribution).
-define(node,node).
@@ -122,7 +150,8 @@
-define(visible_node,visible_node).
--record(state,{file,dump_vsn,wordsize=4,num_atoms="unknown",binaries}).
+-record(state,{file,dump_vsn,wordsize=4,num_atoms="unknown"}).
+-record(dec_opts, {bin_addr_adj=0,base64=true}).
%%%-----------------------------------------------------------------
%%% Debugging
@@ -200,13 +229,14 @@ do_script_start(StartFun) ->
{'EXIT', Pid, normal} ->
ok;
{'EXIT', Pid, Reason} ->
- io:format("\ncdv crash: ~p\n",[Reason])
+ io:format("\ncdv crash: ~tp\n",[Reason])
end;
_ ->
- io:format("\ncdv crash: ~p\n",[unknown_reason])
+ %io:format("\ncdv crash: ~p\n",[unknown_reason])
+ ok
end;
Error ->
- io:format("\ncdv start failed: ~p\n",[Error])
+ io:format("\ncdv start failed: ~tp\n",[Error])
end.
usage() ->
@@ -290,6 +320,11 @@ port(Id) ->
expand_binary(Pos) ->
call({expand_binary,Pos}).
+%%%-----------------------------------------------------------------
+%%% For testing only - called from crashdump_viewer_SUITE
+get_dump_versions() ->
+ call(get_dump_versions).
+
%%====================================================================
%% Server functions
%%====================================================================
@@ -305,6 +340,8 @@ expand_binary(Pos) ->
init([]) ->
ets:new(cdv_dump_index_table,[ordered_set,named_table,public]),
ets:new(cdv_reg_proc_table,[ordered_set,named_table,public]),
+ ets:new(cdv_binary_index_table,[ordered_set,named_table,public]),
+ ets:new(cdv_heap_file_chars,[ordered_set,named_table,public]),
{ok, #state{}}.
%%--------------------------------------------------------------------
@@ -337,10 +374,12 @@ handle_call(general_info,_From,State=#state{file=File}) ->
ets:insert(cdv_reg_proc_table,
{cdv_dump_node_name,GenInfo#general_info.node_name}),
{reply,{ok,GenInfo,TW},State#state{wordsize=WS, num_atoms=NumAtoms}};
-handle_call({expand_binary,{Offset,Size,Pos}},_From,State=#state{file=File}) ->
+handle_call({expand_binary,{Offset,Size,Pos}},_From,
+ #state{file=File,dump_vsn=DumpVsn}=State) ->
Fd = open(File),
pos_bof(Fd,Pos),
- {Bin,_Line} = get_binary(Offset,Size,val(Fd)),
+ DecodeOpts = get_decode_opts(DumpVsn),
+ {Bin,_Line} = get_binary(Offset,Size,bytes(Fd),DecodeOpts),
close(Fd),
{reply,{ok,Bin},State};
handle_call(procs_summary,_From,State=#state{file=File,wordsize=WS}) ->
@@ -348,9 +387,9 @@ handle_call(procs_summary,_From,State=#state{file=File,wordsize=WS}) ->
Procs = procs_summary(File,WS),
{reply,{ok,Procs,TW},State};
handle_call({proc_details,Pid},_From,
- State=#state{file=File,wordsize=WS,dump_vsn=DumpVsn,binaries=B})->
+ State=#state{file=File,wordsize=WS,dump_vsn=DumpVsn})->
Reply =
- case get_proc_details(File,Pid,WS,DumpVsn,B) of
+ case get_proc_details(File,Pid,WS,DumpVsn) of
{ok,Proc,TW} ->
{ok,Proc,TW};
Other ->
@@ -413,9 +452,11 @@ handle_call(loaded_mods,_From,State=#state{file=File}) ->
TW = truncated_warning([?mod]),
{_CC,_OC,Mods} = loaded_mods(File),
{reply,{ok,Mods,TW},State};
-handle_call({loaded_mod_details,Mod},_From,State=#state{file=File}) ->
+handle_call({loaded_mod_details,Mod},_From,
+ #state{dump_vsn=DumpVsn,file=File}=State) ->
TW = truncated_warning([{?mod,Mod}]),
- ModInfo = get_loaded_mod_details(File,Mod),
+ DecodeOpts = get_decode_opts(DumpVsn),
+ ModInfo = get_loaded_mod_details(File,Mod,DecodeOpts),
{reply,{ok,ModInfo,TW},State};
handle_call(funs,_From,State=#state{file=File}) ->
TW = truncated_warning([?fu]),
@@ -449,8 +490,9 @@ handle_call(index_tables,_From,State=#state{file=File}) ->
handle_call(schedulers,_From,State=#state{file=File}) ->
Schedulers=schedulers(File),
TW = truncated_warning([?scheduler]),
- {reply,{ok,Schedulers,TW},State}.
-
+ {reply,{ok,Schedulers,TW},State};
+handle_call(get_dump_versions,_From,State=#state{dump_vsn=DumpVsn}) ->
+ {reply,{ok,{?max_dump_version,DumpVsn}},State}.
%%--------------------------------------------------------------------
@@ -462,9 +504,9 @@ handle_call(schedulers,_From,State=#state{file=File}) ->
%%--------------------------------------------------------------------
handle_cast({read_file,File}, _State) ->
case do_read_file(File) of
- {ok,Binaries,DumpVsn} ->
+ {ok,DumpVsn} ->
observer_lib:report_progress({ok,done}),
- {noreply, #state{file=File,binaries=Binaries,dump_vsn=DumpVsn}};
+ {noreply, #state{file=File,dump_vsn=DumpVsn}};
Error ->
end_progress(Error),
{noreply, #state{}}
@@ -512,9 +554,9 @@ unexpected(_Fd,{eof,_LastLine},_Where) ->
ok; % truncated file
unexpected(Fd,{part,What},Where) ->
skip_rest_of_line(Fd),
- io:format("WARNING: Found unexpected line in ~s:~n~s ...~n",[Where,What]);
+ io:format("WARNING: Found unexpected line in ~ts:~n~ts ...~n",[Where,What]);
unexpected(_Fd,What,Where) ->
- io:format("WARNING: Found unexpected line in ~s:~n~s~n",[Where,What]).
+ io:format("WARNING: Found unexpected line in ~ts:~n~ts~n",[Where,What]).
truncated_warning([]) ->
[];
@@ -701,9 +743,24 @@ skip(Fd,<<>>) ->
end.
-val(Fd) ->
- val(Fd, "-1").
-val(Fd, NoExist) ->
+string(Fd) ->
+ string(Fd, "-1").
+string(Fd,NoExist) ->
+ case bytes(Fd,noexist) of
+ noexist -> NoExist;
+ Val -> byte_list_to_string(Val)
+ end.
+
+byte_list_to_string(ByteList) ->
+ Bin = list_to_binary(ByteList),
+ case unicode:characters_to_list(Bin) of
+ Str when is_list(Str) -> Str;
+ _ -> ByteList
+ end.
+
+bytes(Fd) ->
+ bytes(Fd, "-1").
+bytes(Fd, NoExist) ->
case get_rest_of_line(Fd) of
{eof,[]} -> NoExist;
[] -> NoExist;
@@ -731,32 +788,6 @@ get_rest_of_line_1(Fd, <<>>, Acc) ->
eof -> {eof,lists:reverse(Acc)}
end.
-get_lines_to_empty(Fd) ->
- case get_chunk(Fd) of
- {ok,Bin} ->
- get_lines_to_empty(Fd,Bin,[],[]);
- eof ->
- []
- end.
-get_lines_to_empty(Fd,<<$\n:8,Bin/binary>>,[],Lines) ->
- put_chunk(Fd,Bin),
- lists:reverse(Lines);
-get_lines_to_empty(Fd,<<$\n:8,Bin/binary>>,Acc,Lines) ->
- get_lines_to_empty(Fd,Bin,[],[lists:reverse(Acc)|Lines]);
-get_lines_to_empty(Fd,<<$\r:8,Bin/binary>>,Acc,Lines) ->
- get_lines_to_empty(Fd,Bin,Acc,Lines);
-get_lines_to_empty(Fd,<<$\s:8,Bin/binary>>,[],Lines) ->
- get_lines_to_empty(Fd,Bin,[],Lines);
-get_lines_to_empty(Fd,<<Char:8,Bin/binary>>,Acc,Lines) ->
- get_lines_to_empty(Fd,Bin,[Char|Acc],Lines);
-get_lines_to_empty(Fd,<<>>,Acc,Lines) ->
- case get_chunk(Fd) of
- {ok,Bin} ->
- get_lines_to_empty(Fd,Bin,Acc,Lines);
- eof ->
- lists:reverse(Lines,[lists:reverse(Acc)])
- end.
-
split(Str) ->
split($ ,Str,[]).
split(Char,Str) ->
@@ -786,11 +817,12 @@ parse_vsn_str(Str,WS) ->
%%%-----------------------------------------------------------------
-%%% Traverse crash dump and insert index in table for each heading
-%%%
-%%% Progress is reported during the time and MUST be checked with
-%%% crashdump_viewer:get_progress/0 until it returns {ok,done}.
+%%% Traverse crash dump and insert index in table for each heading.
+%%% Progress is reported during the time.
do_read_file(File) ->
+ erase(?literals), %Clear literal cache.
+ put(truncated,false), %Not truncated (yet).
+ erase(truncated_reason), %Not truncated (yet).
case file:read_file_info(File) of
{ok,#file_info{type=regular,
access=FileA,
@@ -802,21 +834,24 @@ do_read_file(File) ->
{Tag,Id,Rest,N1} = tag(Fd,TagAndRest,1),
case Tag of
?erl_crash_dump ->
- reset_index_table(),
- insert_index(Tag,Id,N1+1),
- put_last_tag(Tag,""),
- indexify(Fd,Rest,N1),
- end_progress(),
- check_if_truncated(),
- [{DumpVsn0,_}] = lookup_index(?erl_crash_dump),
- DumpVsn = [list_to_integer(L) ||
- L<-string:tokens(DumpVsn0,".")],
- Binaries = read_binaries(Fd,DumpVsn),
- close(Fd),
- {ok,Binaries,DumpVsn};
+ case check_dump_version(Id) of
+ {ok,DumpVsn} ->
+ reset_tables(),
+ insert_index(Tag,Id,N1+1),
+ put_last_tag(Tag,""),
+ DecodeOpts = get_decode_opts(DumpVsn),
+ indexify(Fd,DecodeOpts,Rest,N1),
+ end_progress(),
+ check_if_truncated(),
+ close(Fd),
+ {ok,DumpVsn};
+ Error ->
+ close(Fd),
+ Error
+ end;
_Other ->
R = io_lib:format(
- "~s is not an Erlang crash dump~n",
+ "~ts is not an Erlang crash dump~n",
[File]),
close(Fd),
{error,R}
@@ -824,32 +859,73 @@ do_read_file(File) ->
{ok,<<"<Erlang crash dump>",_Rest/binary>>} ->
%% old version - no longer supported
R = io_lib:format(
- "The crashdump ~s is in the pre-R10B format, "
+ "The crashdump ~ts is in the pre-R10B format, "
"which is no longer supported.~n",
[File]),
close(Fd),
{error,R};
_Other ->
R = io_lib:format(
- "~s is not an Erlang crash dump~n",
+ "~ts is not an Erlang crash dump~n",
[File]),
close(Fd),
{error,R}
end;
_other ->
- R = io_lib:format("~s is not an Erlang crash dump~n",[File]),
+ R = io_lib:format("~ts is not an Erlang crash dump~n",[File]),
{error,R}
end.
-indexify(Fd,Bin,N) ->
+check_dump_version(Vsn) ->
+ DumpVsn = [list_to_integer(L) || L<-string:lexemes(Vsn,".")],
+ if DumpVsn > ?max_dump_version ->
+ Info =
+ "This Crashdump Viewer is too old for the given "
+ "Erlang crash dump. Please use a newer version of "
+ "Crashdump Viewer.",
+ {error,Info};
+ true ->
+ {ok,DumpVsn}
+ end.
+
+indexify(Fd,DecodeOpts,Bin,N) ->
case binary:match(Bin,<<"\n=">>) of
{Start,Len} ->
Pos = Start+Len,
<<_:Pos/binary,TagAndRest/binary>> = Bin,
{Tag,Id,Rest,N1} = tag(Fd,TagAndRest,N+Pos),
- insert_index(Tag,Id,N1+1), % +1 to get past newline
- put_last_tag(Tag,Id),
- indexify(Fd,Rest,N1);
+ NewPos = N1+1, % +1 to get past newline
+ case Tag of
+ ?binary ->
+ %% Binaries are stored in a separate table in
+ %% order to minimize lookup time. Key is the
+ %% translated address.
+ {HexAddr,_} = get_hex(Id),
+ Addr = HexAddr bor DecodeOpts#dec_opts.bin_addr_adj,
+ insert_binary_index(Addr,NewPos);
+ _ ->
+ insert_index(Tag,Id,NewPos)
+ end,
+ case put_last_tag(Tag,Id) of
+ {?proc_heap,LastId} ->
+ [{_,LastPos}] = lookup_index(?proc_heap,LastId),
+ ets:insert(cdv_heap_file_chars,{LastId,N+Start+1-LastPos});
+ {?literals,[]} ->
+ case get(truncated_reason) of
+ undefined ->
+ [{_,LastPos}] = lookup_index(?literals,[]),
+ ets:insert(cdv_heap_file_chars,
+ {literals,N+Start+1-LastPos});
+ _ ->
+ %% Literals are truncated. Make sure we never
+ %% attempt to read in the literals. (Heaps that
+ %% references literals will show markers for
+ %% incomplete heaps, but will otherwise work.)
+ delete_index(?literals, [])
+ end;
+ _ -> ok
+ end,
+ indexify(Fd,DecodeOpts,Rest,N1);
nomatch ->
case progress_read(Fd) of
{ok,Chunk0} when is_binary(Chunk0) ->
@@ -860,7 +936,7 @@ indexify(Fd,Bin,N) ->
_ ->
{Chunk0,N+byte_size(Bin)}
end,
- indexify(Fd,Chunk,N1);
+ indexify(Fd,DecodeOpts,Chunk,N1);
eof ->
eof
end
@@ -896,7 +972,12 @@ check_if_truncated() ->
find_truncated_proc(TruncatedTag)
end.
-find_truncated_proc({?atoms,_Id}) ->
+find_truncated_proc({Tag,_Id}) when Tag==?atoms;
+ Tag==?binary;
+ Tag==?instr_data;
+ Tag==?literals;
+ Tag==?memory_status;
+ Tag==?memory_map ->
put(truncated_proc,false);
find_truncated_proc({Tag,Pid}) ->
case is_proc_tag(Tag) of
@@ -986,7 +1067,7 @@ general_info(File) ->
instr_info=InstrInfo}.
get_slogan_and_sysvsn(Fd,Acc) ->
- case val(Fd,eof) of
+ case string(Fd,eof) of
"Slogan: " ++ SloganPart when Acc==[] ->
get_slogan_and_sysvsn(Fd,[SloganPart]);
"System version: " ++ SystemVsn ->
@@ -1000,14 +1081,14 @@ get_slogan_and_sysvsn(Fd,Acc) ->
get_general_info(Fd,GenInfo) ->
case line_head(Fd) of
"Compiled" ->
- get_general_info(Fd,GenInfo#general_info{compile_time=val(Fd)});
+ get_general_info(Fd,GenInfo#general_info{compile_time=bytes(Fd)});
"Taints" ->
- Val = case val(Fd) of "-1" -> "(none)"; Line -> Line end,
+ Val = case string(Fd) of "-1" -> "(none)"; Line -> Line end,
get_general_info(Fd,GenInfo#general_info{taints=Val});
"Atoms" ->
- get_general_info(Fd,GenInfo#general_info{num_atoms=val(Fd)});
+ get_general_info(Fd,GenInfo#general_info{num_atoms=bytes(Fd)});
"Calling Thread" ->
- get_general_info(Fd,GenInfo#general_info{thread=val(Fd)});
+ get_general_info(Fd,GenInfo#general_info{thread=bytes(Fd)});
"=" ++ _next_tag ->
GenInfo;
Other ->
@@ -1045,14 +1126,14 @@ procs_summary(File,WS) ->
%%-----------------------------------------------------------------
%% Page with one process
-get_proc_details(File,Pid,WS,DumpVsn,Binaries) ->
+get_proc_details(File,Pid,WS,DumpVsn) ->
case lookup_index(?proc,Pid) of
[{_,Start}] ->
Fd = open(File),
{{Stack,MsgQ,Dict},TW} =
case truncated_warning([{?proc,Pid}]) of
[] ->
- {expand_memory(Fd,Pid,DumpVsn,Binaries),[]};
+ expand_memory(Fd,Pid,DumpVsn);
TW0 ->
{{[],[],[]},TW0}
end,
@@ -1068,15 +1149,15 @@ get_proc_details(File,Pid,WS,DumpVsn,Binaries) ->
get_procinfo(Fd,Fun,Proc,WS) ->
case line_head(Fd) of
"State" ->
- State = case val(Fd) of
+ State = case bytes(Fd) of
"Garbing" -> "Garbing\n(limited info)";
State0 -> State0
end,
get_procinfo(Fd,Fun,Proc#proc{state=State},WS);
"Name" ->
- get_procinfo(Fd,Fun,Proc#proc{name=val(Fd)},WS);
+ get_procinfo(Fd,Fun,Proc#proc{name=string(Fd)},WS);
"Spawned as" ->
- IF = val(Fd),
+ IF = string(Fd),
case Proc#proc.name of
undefined ->
get_procinfo(Fd,Fun,Proc#proc{name=IF,init_func=IF},WS);
@@ -1085,17 +1166,17 @@ get_procinfo(Fd,Fun,Proc,WS) ->
end;
"Message queue length" ->
%% stored as integer so we can sort on it
- get_procinfo(Fd,Fun,Proc#proc{msg_q_len=list_to_integer(val(Fd))},WS);
+ get_procinfo(Fd,Fun,Proc#proc{msg_q_len=list_to_integer(bytes(Fd))},WS);
"Reductions" ->
%% stored as integer so we can sort on it
- get_procinfo(Fd,Fun,Proc#proc{reds=list_to_integer(val(Fd))},WS);
+ get_procinfo(Fd,Fun,Proc#proc{reds=list_to_integer(bytes(Fd))},WS);
"Stack+heap" ->
%% stored as integer so we can sort on it
get_procinfo(Fd,Fun,Proc#proc{stack_heap=
- list_to_integer(val(Fd))*WS},WS);
+ list_to_integer(bytes(Fd))*WS},WS);
"Memory" ->
%% stored as integer so we can sort on it
- get_procinfo(Fd,Fun,Proc#proc{memory=list_to_integer(val(Fd))},WS);
+ get_procinfo(Fd,Fun,Proc#proc{memory=list_to_integer(bytes(Fd))},WS);
{eof,_} ->
Proc; % truncated file
Other ->
@@ -1117,67 +1198,79 @@ all_procinfo(Fd,Fun,Proc,WS,LineHead) ->
case LineHead of
%% - START - moved from get_procinfo -
"Spawned by" ->
- case val(Fd) of
+ case bytes(Fd) of
"[]" ->
get_procinfo(Fd,Fun,Proc,WS);
Parent ->
get_procinfo(Fd,Fun,Proc#proc{parent=Parent},WS)
end;
"Started" ->
- get_procinfo(Fd,Fun,Proc#proc{start_time=val(Fd)},WS);
+ get_procinfo(Fd,Fun,Proc#proc{start_time=bytes(Fd)},WS);
"Last scheduled in for" ->
get_procinfo(Fd,Fun,Proc#proc{current_func=
{"Last scheduled in for",
- val(Fd)}},WS);
+ string(Fd)}},WS);
"Current call" ->
get_procinfo(Fd,Fun,Proc#proc{current_func={"Current call",
- val(Fd)}},WS);
+ string(Fd)}},WS);
"Number of heap fragments" ->
- get_procinfo(Fd,Fun,Proc#proc{num_heap_frag=val(Fd)},WS);
+ get_procinfo(Fd,Fun,Proc#proc{num_heap_frag=bytes(Fd)},WS);
"Heap fragment data" ->
- get_procinfo(Fd,Fun,Proc#proc{heap_frag_data=val(Fd)},WS);
+ get_procinfo(Fd,Fun,Proc#proc{heap_frag_data=bytes(Fd)},WS);
"OldHeap" ->
- Bytes = list_to_integer(val(Fd))*WS,
+ Bytes = list_to_integer(bytes(Fd))*WS,
get_procinfo(Fd,Fun,Proc#proc{old_heap=Bytes},WS);
"Heap unused" ->
- Bytes = list_to_integer(val(Fd))*WS,
+ Bytes = list_to_integer(bytes(Fd))*WS,
get_procinfo(Fd,Fun,Proc#proc{heap_unused=Bytes},WS);
"OldHeap unused" ->
- Bytes = list_to_integer(val(Fd))*WS,
+ Bytes = list_to_integer(bytes(Fd))*WS,
get_procinfo(Fd,Fun,Proc#proc{old_heap_unused=Bytes},WS);
+ "BinVHeap" ->
+ Bytes = list_to_integer(bytes(Fd))*WS,
+ get_procinfo(Fd,Fun,Proc#proc{bin_vheap=Bytes},WS);
+ "OldBinVHeap" ->
+ Bytes = list_to_integer(bytes(Fd))*WS,
+ get_procinfo(Fd,Fun,Proc#proc{old_bin_vheap=Bytes},WS);
+ "BinVHeap unused" ->
+ Bytes = list_to_integer(bytes(Fd))*WS,
+ get_procinfo(Fd,Fun,Proc#proc{bin_vheap_unused=Bytes},WS);
+ "OldBinVHeap unused" ->
+ Bytes = list_to_integer(bytes(Fd))*WS,
+ get_procinfo(Fd,Fun,Proc#proc{old_bin_vheap_unused=Bytes},WS);
"New heap start" ->
- get_procinfo(Fd,Fun,Proc#proc{new_heap_start=val(Fd)},WS);
+ get_procinfo(Fd,Fun,Proc#proc{new_heap_start=bytes(Fd)},WS);
"New heap top" ->
- get_procinfo(Fd,Fun,Proc#proc{new_heap_top=val(Fd)},WS);
+ get_procinfo(Fd,Fun,Proc#proc{new_heap_top=bytes(Fd)},WS);
"Stack top" ->
- get_procinfo(Fd,Fun,Proc#proc{stack_top=val(Fd)},WS);
+ get_procinfo(Fd,Fun,Proc#proc{stack_top=bytes(Fd)},WS);
"Stack end" ->
- get_procinfo(Fd,Fun,Proc#proc{stack_end=val(Fd)},WS);
+ get_procinfo(Fd,Fun,Proc#proc{stack_end=bytes(Fd)},WS);
"Old heap start" ->
- get_procinfo(Fd,Fun,Proc#proc{old_heap_start=val(Fd)},WS);
+ get_procinfo(Fd,Fun,Proc#proc{old_heap_start=bytes(Fd)},WS);
"Old heap top" ->
- get_procinfo(Fd,Fun,Proc#proc{old_heap_top=val(Fd)},WS);
+ get_procinfo(Fd,Fun,Proc#proc{old_heap_top=bytes(Fd)},WS);
"Old heap end" ->
- get_procinfo(Fd,Fun,Proc#proc{old_heap_end=val(Fd)},WS);
+ get_procinfo(Fd,Fun,Proc#proc{old_heap_end=bytes(Fd)},WS);
%% - END - moved from get_procinfo -
"Last calls" ->
- get_procinfo(Fd,Fun,Proc#proc{last_calls=get_lines_to_empty(Fd)},WS);
+ get_procinfo(Fd,Fun,Proc#proc{last_calls=get_last_calls(Fd)},WS);
"Link list" ->
- {Links,Monitors,MonitoredBy} = parse_link_list(val(Fd),[],[],[]),
+ {Links,Monitors,MonitoredBy} = get_link_list(Fd),
get_procinfo(Fd,Fun,Proc#proc{links=Links,
monitors=Monitors,
mon_by=MonitoredBy},WS);
"Program counter" ->
- get_procinfo(Fd,Fun,Proc#proc{prog_count=val(Fd)},WS);
+ get_procinfo(Fd,Fun,Proc#proc{prog_count=string(Fd)},WS);
"CP" ->
- get_procinfo(Fd,Fun,Proc#proc{cp=val(Fd)},WS);
+ get_procinfo(Fd,Fun,Proc#proc{cp=string(Fd)},WS);
"arity = " ++ Arity ->
%%! Temporary workaround
get_procinfo(Fd,Fun,Proc#proc{arity=Arity--"\r\n"},WS);
"Run queue" ->
- get_procinfo(Fd,Fun,Proc#proc{run_queue=val(Fd)},WS);
+ get_procinfo(Fd,Fun,Proc#proc{run_queue=string(Fd)},WS);
"Internal State" ->
- get_procinfo(Fd,Fun,Proc#proc{int_state=val(Fd)},WS);
+ get_procinfo(Fd,Fun,Proc#proc{int_state=string(Fd)},WS);
"=" ++ _next_tag ->
Proc;
Other ->
@@ -1185,86 +1278,124 @@ all_procinfo(Fd,Fun,Proc,WS,LineHead) ->
get_procinfo(Fd,Fun,Proc,WS)
end.
-parse_link_list([SB|Str],Links,Monitors,MonitoredBy) when SB==$[; SB==$] ->
- parse_link_list(Str,Links,Monitors,MonitoredBy);
-parse_link_list("#Port"++_=Str,Links,Monitors,MonitoredBy) ->
- {Link,Rest} = parse_port(Str),
- parse_link_list(Rest,[Link|Links],Monitors,MonitoredBy);
-parse_link_list("<"++_=Str,Links,Monitors,MonitoredBy) ->
- {Link,Rest} = parse_pid(Str),
- parse_link_list(Rest,[Link|Links],Monitors,MonitoredBy);
-parse_link_list("{to,"++Str,Links,Monitors,MonitoredBy) ->
- {Mon,Rest} = parse_monitor(Str),
- parse_link_list(Rest,Links,[Mon|Monitors],MonitoredBy);
-parse_link_list("{from,"++Str,Links,Monitors,MonitoredBy) ->
- {Mon,Rest} = parse_monitor(Str),
- parse_link_list(Rest,Links,Monitors,[Mon|MonitoredBy]);
-parse_link_list(", "++Rest,Links,Monitors,MonitoredBy) ->
- parse_link_list(Rest,Links,Monitors,MonitoredBy);
-parse_link_list([],Links,Monitors,MonitoredBy) ->
- {lists:reverse(Links),lists:reverse(Monitors),lists:reverse(MonitoredBy)};
-parse_link_list(Unexpected,Links,Monitors,MonitoredBy) ->
- io:format("WARNING: found unexpected data in link list:~n~s~n",[Unexpected]),
- parse_link_list([],Links,Monitors,MonitoredBy).
-
-
-parse_port(Str) ->
- {Port,Rest} = parse_link(Str,[]),
- {{Port,Port},Rest}.
-
-parse_pid(Str) ->
- {Pid,Rest} = parse_link(Str,[]),
- {{Pid,Pid},Rest}.
-
-parse_monitor("{"++Str) ->
- %% Named process
- {Name,Node,Rest1} = parse_name_node(Str,[]),
- Pid = get_pid_from_name(Name,Node),
- case parse_link(string:strip(Rest1,left,$,),[]) of
- {Ref,"}"++Rest2} ->
- %% Bug in break.c - prints an extra "}" for remote
- %% nodes... thus the strip
- {{Pid,"{"++Name++","++Node++"} ("++Ref++")"},
- string:strip(Rest2,left,$})};
- {Ref,[]} ->
- {{Pid,"{"++Name++","++Node++"} ("++Ref++")"},[]}
+%% The end of the 'Last calls' section is meant to be an empty line,
+%% but in some cases this is not the case, so we also need to look for
+%% the next heading which currently (OTP-20.1) can be "Link list: ",
+%% "Dictionary: " or "Reductions: ". We do this by looking for ": "
+%% and when found, pushing the heading back into the saved chunk.
+%%
+%% Note that the 'Last calls' section is only present if the
+%% 'save_calls' process flag is set.
+get_last_calls(Fd) ->
+ case get_chunk(Fd) of
+ {ok,Bin} ->
+ get_last_calls(Fd,Bin,[],[]);
+ eof ->
+ []
+ end.
+get_last_calls(Fd,<<$\n:8,Bin/binary>>,[],Lines) ->
+ %% Empty line - we're done
+ put_chunk(Fd,Bin),
+ lists:reverse(Lines);
+get_last_calls(Fd,<<$::8>>,Acc,Lines) ->
+ case get_chunk(Fd) of
+ {ok,Bin} ->
+ %% Could be a colon followed by a space - see next function clause
+ get_last_calls(Fd,<<$::8,Bin/binary>>,Acc,Lines);
+ eof ->
+ %% Truncated here - either we've got the next heading, or
+ %% it was truncated in a last call function, in which case
+ %% we note that it was truncated
+ case byte_list_to_string(lists:reverse(Acc)) of
+ NextHeading when NextHeading=="Link list";
+ NextHeading=="Dictionary";
+ NextHeading=="Reductions" ->
+ put_chunk(Fd,list_to_binary(NextHeading++":")),
+ lists:reverse(Lines);
+ LastCallFunction->
+ lists:reverse(Lines,[LastCallFunction++":...(truncated)"])
+ end
end;
-parse_monitor(Str) ->
- case parse_link(Str,[]) of
- {Pid,","++Rest1} ->
- case parse_link(Rest1,[]) of
- {Ref,"}"++Rest2} ->
- {{Pid,Pid++" ("++Ref++")"},Rest2};
- {Ref,[]} ->
- {{Pid,Pid++" ("++Ref++")"},[]}
- end;
- {Pid,[]} ->
- {{Pid,Pid++" (unknown_ref)"},[]}
+get_last_calls(Fd,<<$\::8,$\s:8,Bin/binary>>,Acc,Lines) ->
+ %% ": " - means we have the next heading in Acc - save it back
+ %% into the chunk and return the lines we've found
+ HeadingBin = list_to_binary(lists:reverse(Acc,[$:])),
+ put_chunk(Fd,<<HeadingBin/binary,Bin/binary>>),
+ lists:reverse(Lines);
+get_last_calls(Fd,<<$\n:8,Bin/binary>>,Acc,Lines) ->
+ get_last_calls(Fd,Bin,[],[byte_list_to_string(lists:reverse(Acc))|Lines]);
+get_last_calls(Fd,<<$\r:8,Bin/binary>>,Acc,Lines) ->
+ get_last_calls(Fd,Bin,Acc,Lines);
+get_last_calls(Fd,<<$\s:8,Bin/binary>>,[],Lines) ->
+ get_last_calls(Fd,Bin,[],Lines);
+get_last_calls(Fd,<<Char:8,Bin/binary>>,Acc,Lines) ->
+ get_last_calls(Fd,Bin,[Char|Acc],Lines);
+get_last_calls(Fd,<<>>,Acc,Lines) ->
+ case get_chunk(Fd) of
+ {ok,Bin} ->
+ get_last_calls(Fd,Bin,Acc,Lines);
+ eof ->
+ lists:reverse(Lines,[byte_list_to_string(lists:reverse(Acc))])
end.
-parse_link(">"++Rest,Acc) ->
- {lists:reverse(Acc,">"),Rest};
-parse_link([H|T],Acc) ->
- parse_link(T,[H|Acc]);
-parse_link([],Acc) ->
- %% truncated
- {lists:reverse(Acc),[]}.
+get_link_list(Fd) ->
+ case get_chunk(Fd) of
+ {ok,<<"[",Bin/binary>>} ->
+ #{links:=Links,
+ mons:=Monitors,
+ mon_by:=MonitoredBy} =
+ get_link_list(Fd,Bin,#{links=>[],mons=>[],mon_by=>[]}),
+ {lists:reverse(Links),
+ lists:reverse(Monitors),
+ lists:reverse(MonitoredBy)};
+ eof ->
+ {[],[],[]}
+ end.
+
+get_link_list(Fd,<<NL:8,_/binary>>=Bin,Acc) when NL=:=$\r; NL=:=$\n->
+ skip(Fd,Bin),
+ Acc;
+get_link_list(Fd,Bin,Acc) ->
+ case binary:split(Bin,[<<", ">>,<<"]">>]) of
+ [Link,Rest] ->
+ get_link_list(Fd,Rest,get_link(Link,Acc));
+ [Incomplete] ->
+ case get_chunk(Fd) of
+ {ok,More} ->
+ get_link_list(Fd,<<Incomplete/binary,More/binary>>,Acc);
+ eof ->
+ Acc
+ end
+ end.
+
+get_link(<<"#Port",_/binary>>=PortBin,#{links:=Links}=Acc) ->
+ PortStr = binary_to_list(PortBin),
+ Acc#{links=>[{PortStr,PortStr}|Links]};
+get_link(<<"<",_/binary>>=PidBin,#{links:=Links}=Acc) ->
+ PidStr = binary_to_list(PidBin),
+ Acc#{links=>[{PidStr,PidStr}|Links]};
+get_link(<<"{to,",Bin/binary>>,#{mons:=Monitors}=Acc) ->
+ Acc#{mons=>[parse_monitor(Bin)|Monitors]};
+get_link(<<"{from,",Bin/binary>>,#{mon_by:=MonitoredBy}=Acc) ->
+ Acc#{mon_by=>[parse_monitor(Bin)|MonitoredBy]};
+get_link(Unexpected,Acc) ->
+ io:format("WARNING: found unexpected data in link list:~n~ts~n",[Unexpected]),
+ Acc.
-parse_name_node(","++Rest,Name) ->
- parse_name_node(Rest,Name,[]);
-parse_name_node([H|T],Name) ->
- parse_name_node(T,[H|Name]);
-parse_name_node([],Name) ->
- %% truncated
- {lists:reverse(Name),[],[]}.
-
-parse_name_node("}"++Rest,Name,Node) ->
- {lists:reverse(Name),lists:reverse(Node),Rest};
-parse_name_node([H|T],Name,Node) ->
- parse_name_node(T,Name,[H|Node]);
-parse_name_node([],Name,Node) ->
- %% truncated
- {lists:reverse(Name),lists:reverse(Node),[]}.
+parse_monitor(MonBin) ->
+ case binary:split(MonBin,[<<",">>,<<"{">>,<<"}">>],[global]) of
+ [PidBin,RefBin,<<>>] ->
+ PidStr = binary_to_list(PidBin),
+ RefStr = binary_to_list(RefBin),
+ {PidStr,PidStr++" ("++RefStr++")"};
+ [<<>>,NameBin,NodeBin,<<>>,RefBin,<<>>] ->
+ %% Named process
+ NameStr = binary_to_list(NameBin),
+ NodeStr = binary_to_list(NodeBin),
+ PidStr = get_pid_from_name(NameStr,NodeStr),
+ RefStr = binary_to_list(RefBin),
+ {PidStr,"{"++NameStr++","++NodeStr++"} ("++RefStr++")"}
+ end.
get_pid_from_name(Name,Node) ->
case ets:lookup(cdv_reg_proc_table,cdv_dump_node_name) of
@@ -1310,70 +1441,86 @@ maybe_other_node2(Channel) ->
end.
-expand_memory(Fd,Pid,DumpVsn,Binaries) ->
- BinAddrAdj = get_bin_addr_adj(DumpVsn),
+expand_memory(Fd,Pid,DumpVsn) ->
+ DecodeOpts = get_decode_opts(DumpVsn),
put(fd,Fd),
- Dict = read_heap(Fd,Pid,BinAddrAdj,Binaries),
- Expanded = {read_stack_dump(Fd,Pid,BinAddrAdj,Dict),
- read_messages(Fd,Pid,BinAddrAdj,Dict),
- read_dictionary(Fd,Pid,BinAddrAdj,Dict)},
+ Dict0 = case get(?literals) of
+ undefined ->
+ Literals = read_literals(Fd,DecodeOpts),
+ put(?literals,Literals),
+ put(fd,Fd),
+ Literals;
+ Literals ->
+ Literals
+ end,
+ Dict = read_heap(Fd,Pid,DecodeOpts,Dict0),
+ Expanded = {read_stack_dump(Fd,Pid,DecodeOpts,Dict),
+ read_messages(Fd,Pid,DecodeOpts,Dict),
+ read_dictionary(Fd,Pid,DecodeOpts,Dict)},
erase(fd),
- Expanded.
-
-%%%-----------------------------------------------------------------
-%%% This is a workaround for a bug in dump versions prior to 0.3:
-%%% Addresses were truncated to 32 bits. This could cause binaries to
-%%% get the same address as heap terms in the dump. To work around it
-%%% we always store binaries on very high addresses in the gb_tree.
-get_bin_addr_adj(DumpVsn) when DumpVsn < [0,3] ->
- 16#f bsl 64;
-get_bin_addr_adj(_) ->
- 0.
-
-%%%
-%%% Read binaries.
-%%%
-read_binaries(Fd,DumpVsn) ->
- AllBinaries = lookup_index(?binary),
- AddrAdj = get_bin_addr_adj(DumpVsn),
- Fun = fun({Addr0,Pos},Dict0) ->
- pos_bof(Fd,Pos),
- {HexAddr,_} = get_hex(Addr0),
- Addr = HexAddr bor AddrAdj,
- Bin =
- case line_head(Fd) of
- {eof,_} -> '#CDVTruncatedBinary';
- _Size -> {'#CDVBin',Pos}
- end,
- gb_trees:enter(Addr,Bin,Dict0)
- end,
- progress_foldl("Processing binaries",Fun,gb_trees:empty(),AllBinaries).
+ IncompleteWarning =
+ case erase(incomplete_heap) of
+ undefined ->
+ [];
+ true ->
+ ["WARNING: This process has an incomplete heap. "
+ "Some information might be missing."]
+ end,
+ {Expanded,IncompleteWarning}.
+
+read_literals(Fd,DecodeOpts) ->
+ case lookup_index(?literals,[]) of
+ [{_,Start}] ->
+ [{_,Chars}] = ets:lookup(cdv_heap_file_chars,literals),
+ init_progress("Reading literals",Chars),
+ pos_bof(Fd,Start),
+ read_heap(DecodeOpts,gb_trees:empty());
+ [] ->
+ gb_trees:empty()
+ end.
+
+get_decode_opts(DumpVsn) ->
+ BinAddrAdj = if
+ DumpVsn < [0,3] ->
+ %% This is a workaround for a bug in dump
+ %% versions prior to 0.3: Addresses were
+ %% truncated to 32 bits. This could cause
+ %% binaries to get the same address as heap
+ %% terms in the dump. To work around it we
+ %% always store binaries on very high
+ %% addresses in the gb_tree.
+ 16#f bsl 64;
+ true ->
+ 0
+ end,
+ Base64 = DumpVsn >= [0,5],
+ #dec_opts{bin_addr_adj=BinAddrAdj,base64=Base64}.
%%%
%%% Read top level section.
%%%
-read_stack_dump(Fd,Pid,BinAddrAdj,Dict) ->
+read_stack_dump(Fd,Pid,DecodeOpts,Dict) ->
case lookup_index(?proc_stack,Pid) of
[{_,Start}] ->
pos_bof(Fd,Start),
- read_stack_dump1(Fd,BinAddrAdj,Dict,[]);
+ read_stack_dump1(Fd,DecodeOpts,Dict,[]);
[] ->
[]
end.
-read_stack_dump1(Fd,BinAddrAdj,Dict,Acc) ->
+read_stack_dump1(Fd,DecodeOpts,Dict,Acc) ->
%% This function is never called if the dump is truncated in {?proc_heap,Pid}
- case val(Fd) of
+ case bytes(Fd) of
"=" ++ _next_tag ->
lists:reverse(Acc);
Line ->
- Stack = parse_top(Line,BinAddrAdj,Dict),
- read_stack_dump1(Fd,BinAddrAdj,Dict,[Stack|Acc])
+ Stack = parse_top(Line,DecodeOpts,Dict),
+ read_stack_dump1(Fd,DecodeOpts,Dict,[Stack|Acc])
end.
-parse_top(Line0, BinAddrAdj, D) ->
+parse_top(Line0, DecodeOpts, D) ->
{Label,Line1} = get_label(Line0),
- {Term,Line,D} = parse_term(Line1, BinAddrAdj, D),
+ {Term,Line,D} = parse_term(Line1, DecodeOpts, D),
[] = skip_blanks(Line),
{Label,Term}.
@@ -1381,27 +1528,27 @@ parse_top(Line0, BinAddrAdj, D) ->
%%% Read message queue.
%%%
-read_messages(Fd,Pid,BinAddrAdj,Dict) ->
+read_messages(Fd,Pid,DecodeOpts,Dict) ->
case lookup_index(?proc_messages,Pid) of
[{_,Start}] ->
pos_bof(Fd,Start),
- read_messages1(Fd,BinAddrAdj,Dict,[]);
+ read_messages1(Fd,DecodeOpts,Dict,[]);
[] ->
[]
end.
-read_messages1(Fd,BinAddrAdj,Dict,Acc) ->
+read_messages1(Fd,DecodeOpts,Dict,Acc) ->
%% This function is never called if the dump is truncated in {?proc_heap,Pid}
- case val(Fd) of
+ case bytes(Fd) of
"=" ++ _next_tag ->
lists:reverse(Acc);
Line ->
- Msg = parse_message(Line,BinAddrAdj,Dict),
- read_messages1(Fd,BinAddrAdj,Dict,[Msg|Acc])
+ Msg = parse_message(Line,DecodeOpts,Dict),
+ read_messages1(Fd,DecodeOpts,Dict,[Msg|Acc])
end.
-parse_message(Line0, BinAddrAdj, D) ->
- {Msg,":"++Line1,_} = parse_term(Line0, BinAddrAdj, D),
- {Token,Line,_} = parse_term(Line1, BinAddrAdj, D),
+parse_message(Line0, DecodeOpts, D) ->
+ {Msg,":"++Line1,_} = parse_term(Line0, DecodeOpts, D),
+ {Token,Line,_} = parse_term(Line1, DecodeOpts, D),
[] = skip_blanks(Line),
{Msg,Token}.
@@ -1409,26 +1556,26 @@ parse_message(Line0, BinAddrAdj, D) ->
%%% Read process dictionary
%%%
-read_dictionary(Fd,Pid,BinAddrAdj,Dict) ->
+read_dictionary(Fd,Pid,DecodeOpts,Dict) ->
case lookup_index(?proc_dictionary,Pid) of
[{_,Start}] ->
pos_bof(Fd,Start),
- read_dictionary1(Fd,BinAddrAdj,Dict,[]);
+ read_dictionary1(Fd,DecodeOpts,Dict,[]);
[] ->
[]
end.
-read_dictionary1(Fd,BinAddrAdj,Dict,Acc) ->
+read_dictionary1(Fd,DecodeOpts,Dict,Acc) ->
%% This function is never called if the dump is truncated in {?proc_heap,Pid}
- case val(Fd) of
+ case bytes(Fd) of
"=" ++ _next_tag ->
lists:reverse(Acc);
Line ->
- Msg = parse_dictionary(Line,BinAddrAdj,Dict),
- read_dictionary1(Fd,BinAddrAdj,Dict,[Msg|Acc])
+ Msg = parse_dictionary(Line,DecodeOpts,Dict),
+ read_dictionary1(Fd,DecodeOpts,Dict,[Msg|Acc])
end.
-parse_dictionary(Line0, BinAddrAdj, D) ->
- {Entry,Line,_} = parse_term(Line0, BinAddrAdj, D),
+parse_dictionary(Line0, DecodeOpts, D) ->
+ {Entry,Line,_} = parse_term(Line0, DecodeOpts, D),
[] = skip_blanks(Line),
Entry.
@@ -1436,34 +1583,39 @@ parse_dictionary(Line0, BinAddrAdj, D) ->
%%% Read heap data.
%%%
-read_heap(Fd,Pid,BinAddrAdj,Dict0) ->
+read_heap(Fd,Pid,DecodeOpts,Dict0) ->
case lookup_index(?proc_heap,Pid) of
[{_,Pos}] ->
+ [{_,Chars}] = ets:lookup(cdv_heap_file_chars,Pid),
+ init_progress("Reading process heap",Chars),
pos_bof(Fd,Pos),
- read_heap(BinAddrAdj,Dict0);
+ read_heap(DecodeOpts,Dict0);
[] ->
Dict0
end.
-read_heap(BinAddrAdj,Dict0) ->
+read_heap(DecodeOpts,Dict0) ->
%% This function is never called if the dump is truncated in {?proc_heap,Pid}
case get(fd) of
end_of_heap ->
+ end_progress(),
Dict0;
Fd ->
- case val(Fd) of
+ case bytes(Fd) of
"=" ++ _next_tag ->
+ end_progress(),
put(fd, end_of_heap),
Dict0;
Line ->
- Dict = parse(Line,BinAddrAdj,Dict0),
- read_heap(BinAddrAdj,Dict)
+ update_progress(length(Line)+1),
+ Dict = parse(Line,DecodeOpts,Dict0),
+ read_heap(DecodeOpts,Dict)
end
end.
-parse(Line0, BinAddrAdj, Dict0) ->
+parse(Line0, DecodeOpts, Dict0) ->
{Addr,":"++Line1} = get_hex(Line0),
- {_Term,Line,Dict} = parse_heap_term(Line1, Addr, BinAddrAdj, Dict0),
+ {_Term,Line,Dict} = parse_heap_term(Line1, Addr, DecodeOpts, Dict0),
[] = skip_blanks(Line),
Dict.
@@ -1491,50 +1643,67 @@ get_ports(File) ->
%% Converting port string to tuple to secure correct sorting. This is
%% converted back in cdv_port_cb:format/1.
port_to_tuple("#Port<"++Port) ->
- [I1,I2] = string:tokens(Port,".>"),
+ [I1,I2] = string:lexemes(Port,".>"),
{list_to_integer(I1),list_to_integer(I2)}.
get_portinfo(Fd,Port) ->
case line_head(Fd) of
+ "State" ->
+ get_portinfo(Fd,Port#port{state=bytes(Fd)});
+ "Task Flags" ->
+ get_portinfo(Fd,Port#port{task_flags=bytes(Fd)});
"Slot" ->
%% stored as integer so we can sort on it
- get_portinfo(Fd,Port#port{slot=list_to_integer(val(Fd))});
+ get_portinfo(Fd,Port#port{slot=list_to_integer(bytes(Fd))});
"Connected" ->
%% stored as pid so we can sort on it
- Connected0 = val(Fd),
+ Connected0 = bytes(Fd),
Connected =
try list_to_pid(Connected0)
catch error:badarg -> Connected0
end,
get_portinfo(Fd,Port#port{connected=Connected});
"Links" ->
- Pids = split_pid_list_no_space(val(Fd)),
+ Pids = split_pid_list_no_space(bytes(Fd)),
Links = [{Pid,Pid} || Pid <- Pids],
get_portinfo(Fd,Port#port{links=Links});
"Registered as" ->
- get_portinfo(Fd,Port#port{name=val(Fd)});
+ get_portinfo(Fd,Port#port{name=string(Fd)});
"Monitors" ->
- Monitors0 = string:tokens(val(Fd),"()"),
+ Monitors0 = string:lexemes(bytes(Fd),"()"),
Monitors = [begin
- [Pid,Ref] = string:tokens(Mon,","),
+ [Pid,Ref] = string:lexemes(Mon,","),
{Pid,Pid++" ("++Ref++")"}
end || Mon <- Monitors0],
get_portinfo(Fd,Port#port{monitors=Monitors});
+ "Suspended" ->
+ Pids = split_pid_list_no_space(bytes(Fd)),
+ Suspended = [{Pid,Pid} || Pid <- Pids],
+ get_portinfo(Fd,Port#port{suspended=Suspended});
"Port controls linked-in driver" ->
- Str = lists:flatten(["Linked in driver: " | val(Fd)]),
+ Str = lists:flatten(["Linked in driver: " | string(Fd)]),
get_portinfo(Fd,Port#port{controls=Str});
"Port controls forker process" ->
- Str = lists:flatten(["Forker process: " | val(Fd)]),
+ Str = lists:flatten(["Forker process: " | string(Fd)]),
get_portinfo(Fd,Port#port{controls=Str});
"Port controls external process" ->
- Str = lists:flatten(["External proc: " | val(Fd)]),
+ Str = lists:flatten(["External proc: " | string(Fd)]),
get_portinfo(Fd,Port#port{controls=Str});
"Port is a file" ->
- Str = lists:flatten(["File: "| val(Fd)]),
+ Str = lists:flatten(["File: "| string(Fd)]),
get_portinfo(Fd,Port#port{controls=Str});
"Port is UNIX fd not opened by emulator" ->
- Str = lists:flatten(["UNIX fd not opened by emulator: "| val(Fd)]),
+ Str = lists:flatten(["UNIX fd not opened by emulator: "| string(Fd)]),
get_portinfo(Fd,Port#port{controls=Str});
+ "Input" ->
+ get_portinfo(Fd,Port#port{input=list_to_integer(bytes(Fd))});
+ "Output" ->
+ get_portinfo(Fd,Port#port{output=list_to_integer(bytes(Fd))});
+ "Queue" ->
+ get_portinfo(Fd,Port#port{queue=list_to_integer(bytes(Fd))});
+ "Port Data" ->
+ get_portinfo(Fd,Port#port{port_data=string(Fd)});
+
"=" ++ _next_tag ->
Port;
Other ->
@@ -1566,23 +1735,23 @@ tab_is_named(#ets_table{}) -> "no".
get_etsinfo(Fd,EtsTable = #ets_table{details=Ds},WS) ->
case line_head(Fd) of
"Slot" ->
- get_etsinfo(Fd,EtsTable#ets_table{slot=list_to_integer(val(Fd))},WS);
+ get_etsinfo(Fd,EtsTable#ets_table{slot=list_to_integer(bytes(Fd))},WS);
"Table" ->
- get_etsinfo(Fd,EtsTable#ets_table{id=val(Fd)},WS);
+ get_etsinfo(Fd,EtsTable#ets_table{id=string(Fd)},WS);
"Name" ->
- get_etsinfo(Fd,EtsTable#ets_table{name=val(Fd)},WS);
+ get_etsinfo(Fd,EtsTable#ets_table{name=string(Fd)},WS);
"Ordered set (AVL tree), Elements" ->
skip_rest_of_line(Fd),
get_etsinfo(Fd,EtsTable#ets_table{data_type="tree"},WS);
"Buckets" ->
%% A bug in erl_db_hash.c prints a space after the buckets
%% - need to strip the string to make list_to_integer/1 happy.
- Buckets = list_to_integer(string:strip(val(Fd))),
+ Buckets = list_to_integer(string:trim(bytes(Fd),both,"\s")),
get_etsinfo(Fd,EtsTable#ets_table{buckets=Buckets},WS);
"Objects" ->
- get_etsinfo(Fd,EtsTable#ets_table{size=list_to_integer(val(Fd))},WS);
+ get_etsinfo(Fd,EtsTable#ets_table{size=list_to_integer(bytes(Fd))},WS);
"Words" ->
- Words = list_to_integer(val(Fd)),
+ Words = list_to_integer(bytes(Fd)),
Bytes =
case Words of
-1 -> -1; % probably truncated
@@ -1592,37 +1761,39 @@ get_etsinfo(Fd,EtsTable = #ets_table{details=Ds},WS) ->
"=" ++ _next_tag ->
EtsTable;
"Chain Length Min" ->
- Val = val(Fd),
+ Val = bytes(Fd),
get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{chain_min=>Val}},WS);
"Chain Length Avg" ->
- Val = try list_to_float(string:strip(val(Fd))) catch _:_ -> "-" end,
+ Val = try list_to_float(string:trim(bytes(Fd),both,"\s"))
+ catch _:_ -> "-"
+ end,
get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{chain_avg=>Val}},WS);
"Chain Length Max" ->
- Val = val(Fd),
+ Val = bytes(Fd),
get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{chain_max=>Val}},WS);
"Chain Length Std Dev" ->
- Val = val(Fd),
+ Val = bytes(Fd),
get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{chain_stddev=>Val}},WS);
"Chain Length Expected Std Dev" ->
- Val = val(Fd),
+ Val = bytes(Fd),
get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{chain_exp_stddev=>Val}},WS);
"Fixed" ->
- Val = val(Fd),
+ Val = bytes(Fd),
get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{fixed=>Val}},WS);
"Type" ->
- Val = val(Fd),
+ Val = bytes(Fd),
get_etsinfo(Fd,EtsTable#ets_table{data_type=Val},WS);
"Protection" ->
- Val = val(Fd),
+ Val = bytes(Fd),
get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{protection=>Val}},WS);
"Compressed" ->
- Val = val(Fd),
+ Val = bytes(Fd),
get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{compressed=>Val}},WS);
"Write Concurrency" ->
- Val = val(Fd),
+ Val = bytes(Fd),
get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{write_c=>Val}},WS);
"Read Concurrency" ->
- Val = val(Fd),
+ Val = bytes(Fd),
get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{read_c=>Val}},WS);
Other ->
unexpected(Fd,Other,"ETS info"),
@@ -1672,9 +1843,9 @@ get_timerinfo(Fd,Id) ->
get_timerinfo_1(Fd,Timer) ->
case line_head(Fd) of
"Message" ->
- get_timerinfo_1(Fd,Timer#timer{msg=val(Fd)});
+ get_timerinfo_1(Fd,Timer#timer{msg=string(Fd)});
"Time left" ->
- TimeLeft = list_to_integer(val(Fd) -- " ms"),
+ TimeLeft = list_to_integer(bytes(Fd) -- " ms"),
get_timerinfo_1(Fd,Timer#timer{time=TimeLeft});
"=" ++ _next_tag ->
Timer;
@@ -1743,37 +1914,37 @@ get_nodeinfo(Fd,Channel,Type,Start) ->
get_nodeinfo(Fd,Nod) ->
case line_head(Fd) of
"Name" ->
- get_nodeinfo(Fd,Nod#nod{name=val(Fd)});
+ get_nodeinfo(Fd,Nod#nod{name=bytes(Fd)});
"Controller" ->
- get_nodeinfo(Fd,Nod#nod{controller=val(Fd)});
+ get_nodeinfo(Fd,Nod#nod{controller=bytes(Fd)});
"Creation" ->
%% Throwing away elements like "(refc=1)", which might be
%% printed from a debug compiled emulator.
Creations = lists:flatmap(fun(C) -> try [list_to_integer(C)]
catch error:badarg -> []
end
- end, string:tokens(val(Fd)," ")),
+ end, string:lexemes(bytes(Fd)," ")),
get_nodeinfo(Fd,Nod#nod{creation={creations,Creations}});
"Remote link" ->
- Procs = val(Fd), % e.g. "<0.31.0> <4322.54.0>"
+ Procs = bytes(Fd), % e.g. "<0.31.0> <4322.54.0>"
{Local,Remote} = split(Procs),
Str = Local++" <-> "++Remote,
NewRemLinks = [{Local,Str} | Nod#nod.remote_links],
get_nodeinfo(Fd,Nod#nod{remote_links=NewRemLinks});
"Remote monitoring" ->
- Procs = val(Fd), % e.g. "<0.31.0> <4322.54.0>"
+ Procs = bytes(Fd), % e.g. "<0.31.0> <4322.54.0>"
{Local,Remote} = split(Procs),
Str = Local++" -> "++Remote,
NewRemMon = [{Local,Str} | Nod#nod.remote_mon],
get_nodeinfo(Fd,Nod#nod{remote_mon=NewRemMon});
"Remotely monitored by" ->
- Procs = val(Fd), % e.g. "<0.31.0> <4322.54.0>"
+ Procs = bytes(Fd), % e.g. "<0.31.0> <4322.54.0>"
{Local,Remote} = split(Procs),
Str = Local++" <- "++Remote,
NewRemMonBy = [{Local,Str} | Nod#nod.remote_mon_by],
get_nodeinfo(Fd,Nod#nod{remote_mon_by=NewRemMonBy});
"Error" ->
- get_nodeinfo(Fd,Nod#nod{error="ERROR: "++val(Fd)});
+ get_nodeinfo(Fd,Nod#nod{error="ERROR: "++string(Fd)});
"=" ++ _next_tag ->
Nod;
Other ->
@@ -1783,12 +1954,15 @@ get_nodeinfo(Fd,Nod) ->
%%-----------------------------------------------------------------
%% Page with details about one loaded modules
-get_loaded_mod_details(File,Mod) ->
+get_loaded_mod_details(File,Mod,DecodeOpts) ->
[{_,Start}] = lookup_index(?mod,Mod),
Fd = open(File),
pos_bof(Fd,Start),
InitLM = #loaded_mod{mod=Mod,old_size="No old code exists"},
- ModInfo = get_loaded_mod_info(Fd,InitLM,fun all_modinfo/3),
+ Fun = fun(F, LM, LineHead) ->
+ all_modinfo(F, LM, LineHead, DecodeOpts)
+ end,
+ ModInfo = get_loaded_mod_info(Fd,InitLM,Fun),
close(Fd),
ModInfo.
@@ -1817,9 +1991,9 @@ loaded_mods(File) ->
get_loaded_mod_totals(Fd,{CC,OC}) ->
case line_head(Fd) of
"Current code" ->
- get_loaded_mod_totals(Fd,{val(Fd),OC});
+ get_loaded_mod_totals(Fd,{bytes(Fd),OC});
"Old code" ->
- get_loaded_mod_totals(Fd,{CC,val(Fd)});
+ get_loaded_mod_totals(Fd,{CC,bytes(Fd)});
"=" ++ _next_tag ->
{CC,OC};
Other ->
@@ -1830,10 +2004,10 @@ get_loaded_mod_totals(Fd,{CC,OC}) ->
get_loaded_mod_info(Fd,LM,Fun) ->
case line_head(Fd) of
"Current size" ->
- CS = list_to_integer(val(Fd)),
+ CS = list_to_integer(bytes(Fd)),
get_loaded_mod_info(Fd,LM#loaded_mod{current_size=CS},Fun);
"Old size" ->
- OS = list_to_integer(val(Fd)),
+ OS = list_to_integer(bytes(Fd)),
get_loaded_mod_info(Fd,LM#loaded_mod{old_size=OS},Fun);
"=" ++ _next_tag ->
LM;
@@ -1846,59 +2020,48 @@ get_loaded_mod_info(Fd,LM,Fun) ->
main_modinfo(_Fd,LM,_LineHead) ->
LM.
-all_modinfo(Fd,LM,LineHead) ->
+all_modinfo(Fd,LM,LineHead,DecodeOpts) ->
case LineHead of
"Current attributes" ->
- Str = hex_to_str(val(Fd,"")),
+ Str = get_attribute(Fd, DecodeOpts),
LM#loaded_mod{current_attrib=Str};
"Current compilation info" ->
- Str = hex_to_str(val(Fd,"")),
+ Str = get_attribute(Fd, DecodeOpts),
LM#loaded_mod{current_comp_info=Str};
"Old attributes" ->
- Str = hex_to_str(val(Fd,"")),
+ Str = get_attribute(Fd, DecodeOpts),
LM#loaded_mod{old_attrib=Str};
"Old compilation info" ->
- Str = hex_to_str(val(Fd,"")),
+ Str = get_attribute(Fd, DecodeOpts),
LM#loaded_mod{old_comp_info=Str};
Other ->
unexpected(Fd,Other,"loaded modules info"),
LM
end.
-
-hex_to_str(Hex) ->
- Term = hex_to_term(Hex,[]),
- io_lib:format("~p~n",[Term]).
-
-hex_to_term([X,Y|Hex],Acc) ->
- MS = hex_to_dec([X]),
- LS = hex_to_dec([Y]),
- Z = 16*MS+LS,
- hex_to_term(Hex,[Z|Acc]);
-hex_to_term([],Acc) ->
- Bin = list_to_binary(lists:reverse(Acc)),
- case catch binary_to_term(Bin) of
- {'EXIT',_Reason} ->
- {"WARNING: The term is probably truncated!",
- "I can not do binary_to_term.",
- Bin};
- Term ->
- Term
- end;
-hex_to_term(Rest,Acc) ->
- {"WARNING: The term is probably truncated!",
- "I can not convert hex to term.",
- Rest,list_to_binary(lists:reverse(Acc))}.
-
-
-hex_to_dec("F") -> 15;
-hex_to_dec("E") -> 14;
-hex_to_dec("D") -> 13;
-hex_to_dec("C") -> 12;
-hex_to_dec("B") -> 11;
-hex_to_dec("A") -> 10;
-hex_to_dec(N) -> list_to_integer(N).
-
+get_attribute(Fd, DecodeOpts) ->
+ Term = do_get_attribute(Fd, DecodeOpts),
+ io_lib:format("~tp~n",[Term]).
+
+do_get_attribute(Fd, DecodeOpts) ->
+ Bytes = bytes(Fd, ""),
+ try get_binary(Bytes, DecodeOpts) of
+ {Bin,_} ->
+ try binary_to_term(Bin) of
+ Term ->
+ Term
+ catch
+ _:_ ->
+ {"WARNING: The term is probably truncated!",
+ "I cannot do binary_to_term/1.",
+ Bin}
+ end
+ catch
+ _:_ ->
+ {"WARNING: The term is probably truncated!",
+ "I cannot convert to binary.",
+ Bytes}
+ end.
%%-----------------------------------------------------------------
%% Page with list of all funs
@@ -1909,17 +2072,17 @@ funs(File) ->
get_funinfo(Fd,Fu) ->
case line_head(Fd) of
"Module" ->
- get_funinfo(Fd,Fu#fu{module=val(Fd)});
+ get_funinfo(Fd,Fu#fu{module=bytes(Fd)});
"Uniq" ->
- get_funinfo(Fd,Fu#fu{uniq=list_to_integer(val(Fd))});
+ get_funinfo(Fd,Fu#fu{uniq=list_to_integer(bytes(Fd))});
"Index" ->
- get_funinfo(Fd,Fu#fu{index=list_to_integer(val(Fd))});
+ get_funinfo(Fd,Fu#fu{index=list_to_integer(bytes(Fd))});
"Address" ->
- get_funinfo(Fd,Fu#fu{address=val(Fd)});
+ get_funinfo(Fd,Fu#fu{address=bytes(Fd)});
"Native_address" ->
- get_funinfo(Fd,Fu#fu{native_address=val(Fd)});
+ get_funinfo(Fd,Fu#fu{native_address=bytes(Fd)});
"Refc" ->
- get_funinfo(Fd,Fu#fu{refc=list_to_integer(val(Fd))});
+ get_funinfo(Fd,Fu#fu{refc=list_to_integer(bytes(Fd))});
"=" ++ _next_tag ->
Fu;
Other ->
@@ -1999,7 +2162,7 @@ get_meminfo(Fd,Acc) ->
{eof,_last_line} ->
lists:reverse(Acc);
Key ->
- get_meminfo(Fd,[{list_to_atom(Key),val(Fd)}|Acc])
+ get_meminfo(Fd,[{list_to_atom(Key),bytes(Fd)}|Acc])
end.
%%-----------------------------------------------------------------
@@ -2023,7 +2186,7 @@ get_allocareainfo(Fd,Acc) ->
{eof,_last_line} ->
lists:reverse(Acc);
Key ->
- Val = val(Fd),
+ Val = bytes(Fd),
AllocInfo =
case split(Val) of
{Alloc,[]} ->
@@ -2061,7 +2224,7 @@ get_allocatorinfo1(Fd,Acc,Max) ->
{eof,_last_line} ->
pad_and_reverse(Acc,Max,[]);
Key ->
- Values = get_all_vals(val(Fd),[]),
+ Values = get_all_vals(bytes(Fd),[]),
L = length(Values),
Max1 = if L > Max -> L; true -> Max end,
get_allocatorinfo1(Fd,[{Key,Values}|Acc],Max1)
@@ -2198,7 +2361,7 @@ get_size_value(Key,Data) ->
%% and Value is the sum over all allocator instances of each type.
sort_allocator_types([{Name,Data}|Allocators],Acc,DoTotal) ->
Type =
- case string:tokens(Name,"[]") of
+ case string:lexemes(Name,"[]") of
[T,_Id] -> T;
[Name] -> Name;
Other -> Other
@@ -2316,13 +2479,13 @@ get_hashtableinfo(Fd,Name,Start) ->
get_hashtableinfo1(Fd,HashTable) ->
case line_head(Fd) of
"size" ->
- get_hashtableinfo1(Fd,HashTable#hash_table{size=val(Fd)});
+ get_hashtableinfo1(Fd,HashTable#hash_table{size=bytes(Fd)});
"used" ->
- get_hashtableinfo1(Fd,HashTable#hash_table{used=val(Fd)});
+ get_hashtableinfo1(Fd,HashTable#hash_table{used=bytes(Fd)});
"objs" ->
- get_hashtableinfo1(Fd,HashTable#hash_table{objs=val(Fd)});
+ get_hashtableinfo1(Fd,HashTable#hash_table{objs=bytes(Fd)});
"depth" ->
- get_hashtableinfo1(Fd,HashTable#hash_table{depth=val(Fd)});
+ get_hashtableinfo1(Fd,HashTable#hash_table{depth=bytes(Fd)});
"=" ++ _next_tag ->
HashTable;
Other ->
@@ -2353,15 +2516,15 @@ get_indextableinfo(Fd,Name,Start) ->
get_indextableinfo1(Fd,IndexTable) ->
case line_head(Fd) of
"size" ->
- get_indextableinfo1(Fd,IndexTable#index_table{size=val(Fd)});
+ get_indextableinfo1(Fd,IndexTable#index_table{size=bytes(Fd)});
"used" ->
- get_indextableinfo1(Fd,IndexTable#index_table{used=val(Fd)});
+ get_indextableinfo1(Fd,IndexTable#index_table{used=bytes(Fd)});
"limit" ->
- get_indextableinfo1(Fd,IndexTable#index_table{limit=val(Fd)});
+ get_indextableinfo1(Fd,IndexTable#index_table{limit=bytes(Fd)});
"rate" ->
- get_indextableinfo1(Fd,IndexTable#index_table{rate=val(Fd)});
+ get_indextableinfo1(Fd,IndexTable#index_table{rate=bytes(Fd)});
"entries" ->
- get_indextableinfo1(Fd,IndexTable#index_table{entries=val(Fd)});
+ get_indextableinfo1(Fd,IndexTable#index_table{entries=bytes(Fd)});
"=" ++ _next_tag ->
IndexTable;
Other ->
@@ -2373,77 +2536,146 @@ get_indextableinfo1(Fd,IndexTable) ->
%%-----------------------------------------------------------------
%% Page with scheduler table information
schedulers(File) ->
- case lookup_index(?scheduler) of
- [] ->
- [];
- Schedulers ->
- Fd = open(File),
- R = lists:map(fun({Name,Start}) ->
- get_schedulerinfo(Fd,Name,Start)
- end,
- Schedulers),
- close(Fd),
- R
- end.
+ Fd = open(File),
-get_schedulerinfo(Fd,Name,Start) ->
+ Schds0 = case lookup_index(?scheduler) of
+ [] ->
+ [];
+ Normals ->
+ [{Normals, #sched{type=normal}}]
+ end,
+ Schds1 = case lookup_index(?dirty_cpu_scheduler) of
+ [] ->
+ Schds0;
+ DirtyCpus ->
+ [{DirtyCpus, get_dirty_runqueue(Fd, ?dirty_cpu_run_queue)}
+ | Schds0]
+ end,
+ Schds2 = case lookup_index(?dirty_io_scheduler) of
+ [] ->
+ Schds1;
+ DirtyIos ->
+ [{DirtyIos, get_dirty_runqueue(Fd, ?dirty_io_run_queue)}
+ | Schds1]
+ end,
+
+ R = schedulers1(Fd, Schds2, []),
+ close(Fd),
+ R.
+
+schedulers1(_Fd, [], Acc) ->
+ Acc;
+schedulers1(Fd, [{Scheds,Sched0} | Tail], Acc0) ->
+ Acc1 = lists:foldl(fun({Name,Start}, AccIn) ->
+ [get_schedulerinfo(Fd,Name,Start,Sched0) | AccIn]
+ end,
+ Acc0,
+ Scheds),
+ schedulers1(Fd, Tail, Acc1).
+
+get_schedulerinfo(Fd,Name,Start,Sched0) ->
pos_bof(Fd,Start),
- get_schedulerinfo1(Fd,#sched{name=Name}).
+ get_schedulerinfo1(Fd,Sched0#sched{name=list_to_integer(Name)}).
+
+sched_type(?dirty_cpu_run_queue) -> dirty_cpu;
+sched_type(?dirty_io_run_queue) -> dirty_io.
-get_schedulerinfo1(Fd,Sched=#sched{details=Ds}) ->
+get_schedulerinfo1(Fd, Sched) ->
+ case get_schedulerinfo2(Fd, Sched) of
+ {more, Sched2} ->
+ get_schedulerinfo1(Fd, Sched2);
+ {done, Sched2} ->
+ Sched2
+ end.
+
+get_schedulerinfo2(Fd, Sched=#sched{details=Ds}) ->
case line_head(Fd) of
"Current Process" ->
- get_schedulerinfo1(Fd,Sched#sched{process=val(Fd, "None")});
+ {more, Sched#sched{process=bytes(Fd, "None")}};
"Current Port" ->
- get_schedulerinfo1(Fd,Sched#sched{port=val(Fd, "None")});
+ {more, Sched#sched{port=bytes(Fd, "None")}};
+
+ "Scheduler Sleep Info Flags" ->
+ {more, Sched#sched{details=Ds#{sleep_info=>bytes(Fd, "None")}}};
+ "Scheduler Sleep Info Aux Work" ->
+ {more, Sched#sched{details=Ds#{sleep_aux=>bytes(Fd, "None")}}};
+
+ "Current Process State" ->
+ {more, Sched#sched{details=Ds#{currp_state=>bytes(Fd)}}};
+ "Current Process Internal State" ->
+ {more, Sched#sched{details=Ds#{currp_int_state=>bytes(Fd)}}};
+ "Current Process Program counter" ->
+ {more, Sched#sched{details=Ds#{currp_prg_cnt=>string(Fd)}}};
+ "Current Process CP" ->
+ {more, Sched#sched{details=Ds#{currp_cp=>string(Fd)}}};
+ "Current Process Limited Stack Trace" ->
+ %% If there shall be last in scheduler information block
+ {done, Sched#sched{details=get_limited_stack(Fd, 0, Ds)}};
+
+ "=" ++ _next_tag ->
+ {done, Sched};
+
+ Other ->
+ case Sched#sched.type of
+ normal ->
+ get_runqueue_info2(Fd, Other, Sched);
+ _ ->
+ unexpected(Fd,Other,"dirty scheduler information"),
+ {done, Sched}
+ end
+ end.
+
+get_dirty_runqueue(Fd, Tag) ->
+ case lookup_index(Tag) of
+ [{_, Start}] ->
+ pos_bof(Fd,Start),
+ get_runqueue_info1(Fd,#sched{type=sched_type(Tag)});
+ [] ->
+ #sched{}
+ end.
+
+get_runqueue_info1(Fd, Sched) ->
+ case get_runqueue_info2(Fd, line_head(Fd), Sched) of
+ {more, Sched2} ->
+ get_runqueue_info1(Fd, Sched2);
+ {done, Sched2} ->
+ Sched2
+ end.
+
+get_runqueue_info2(Fd, LineHead, Sched=#sched{details=Ds}) ->
+ case LineHead of
"Run Queue Max Length" ->
- RQMax = list_to_integer(val(Fd)),
+ RQMax = list_to_integer(bytes(Fd)),
RQ = RQMax + Sched#sched.run_q,
- get_schedulerinfo1(Fd,Sched#sched{run_q=RQ, details=Ds#{runq_max=>RQMax}});
+ {more, Sched#sched{run_q=RQ, details=Ds#{runq_max=>RQMax}}};
"Run Queue High Length" ->
- RQHigh = list_to_integer(val(Fd)),
+ RQHigh = list_to_integer(bytes(Fd)),
RQ = RQHigh + Sched#sched.run_q,
- get_schedulerinfo1(Fd,Sched#sched{run_q=RQ, details=Ds#{runq_high=>RQHigh}});
+ {more, Sched#sched{run_q=RQ, details=Ds#{runq_high=>RQHigh}}};
"Run Queue Normal Length" ->
- RQNorm = list_to_integer(val(Fd)),
+ RQNorm = list_to_integer(bytes(Fd)),
RQ = RQNorm + Sched#sched.run_q,
- get_schedulerinfo1(Fd,Sched#sched{run_q=RQ, details=Ds#{runq_norm=>RQNorm}});
+ {more, Sched#sched{run_q=RQ, details=Ds#{runq_norm=>RQNorm}}};
"Run Queue Low Length" ->
- RQLow = list_to_integer(val(Fd)),
+ RQLow = list_to_integer(bytes(Fd)),
RQ = RQLow + Sched#sched.run_q,
- get_schedulerinfo1(Fd,Sched#sched{run_q=RQ, details=Ds#{runq_low=>RQLow}});
+ {more, Sched#sched{run_q=RQ, details=Ds#{runq_low=>RQLow}}};
"Run Queue Port Length" ->
- RQ = list_to_integer(val(Fd)),
- get_schedulerinfo1(Fd,Sched#sched{port_q=RQ});
-
- "Scheduler Sleep Info Flags" ->
- get_schedulerinfo1(Fd,Sched#sched{details=Ds#{sleep_info=>val(Fd, "None")}});
- "Scheduler Sleep Info Aux Work" ->
- get_schedulerinfo1(Fd,Sched#sched{details=Ds#{sleep_aux=>val(Fd, "None")}});
+ RQ = list_to_integer(bytes(Fd)),
+ {more, Sched#sched{port_q=RQ}};
"Run Queue Flags" ->
- get_schedulerinfo1(Fd,Sched#sched{details=Ds#{runq_flags=>val(Fd, "None")}});
+ {more, Sched#sched{details=Ds#{runq_flags=>bytes(Fd, "None")}}};
- "Current Process State" ->
- get_schedulerinfo1(Fd,Sched#sched{details=Ds#{currp_state=>val(Fd)}});
- "Current Process Internal State" ->
- get_schedulerinfo1(Fd,Sched#sched{details=Ds#{currp_int_state=>val(Fd)}});
- "Current Process Program counter" ->
- get_schedulerinfo1(Fd,Sched#sched{details=Ds#{currp_prg_cnt=>val(Fd)}});
- "Current Process CP" ->
- get_schedulerinfo1(Fd,Sched#sched{details=Ds#{currp_cp=>val(Fd)}});
- "Current Process Limited Stack Trace" ->
- %% If there shall be last in scheduler information block
- Sched#sched{details=get_limited_stack(Fd, 0, Ds)};
"=" ++ _next_tag ->
- Sched;
+ {done, Sched};
Other ->
unexpected(Fd,Other,"scheduler information"),
- Sched
+ {done, Sched}
end.
get_limited_stack(Fd, N, Ds) ->
- case val(Fd) of
+ case string(Fd) of
Addr = "0x" ++ _ ->
get_limited_stack(Fd, N+1, Ds#{{currp_stack, N} => Addr});
"=" ++ _next_tag ->
@@ -2455,100 +2687,134 @@ get_limited_stack(Fd, N, Ds) ->
%%%-----------------------------------------------------------------
%%% Parse memory in crashdump version 0.1 and newer
%%%
-parse_heap_term([$l|Line0], Addr, BinAddrAdj, D0) -> %Cons cell.
- {H,"|"++Line1,D1} = parse_term(Line0, BinAddrAdj, D0),
- {T,Line,D2} = parse_term(Line1, BinAddrAdj, D1),
+parse_heap_term([$l|Line0], Addr, DecodeOpts, D0) -> %Cons cell.
+ {H,"|"++Line1,D1} = parse_term(Line0, DecodeOpts, D0),
+ {T,Line,D2} = parse_term(Line1, DecodeOpts, D1),
Term = [H|T],
D = gb_trees:insert(Addr, Term, D2),
{Term,Line,D};
-parse_heap_term([$t|Line0], Addr, BinAddrAdj, D) -> %Tuple
+parse_heap_term([$t|Line0], Addr, DecodeOpts, D) -> %Tuple
{N,":"++Line} = get_hex(Line0),
- parse_tuple(N, Line, Addr, BinAddrAdj, D, []);
-parse_heap_term([$F|Line0], Addr, _BinAddrAdj, D0) -> %Float
+ parse_tuple(N, Line, Addr, DecodeOpts, D, []);
+parse_heap_term([$F|Line0], Addr, _DecodeOpts, D0) -> %Float
{N,":"++Line1} = get_hex(Line0),
{Chars,Line} = get_chars(N, Line1),
Term = list_to_float(Chars),
D = gb_trees:insert(Addr, Term, D0),
{Term,Line,D};
-parse_heap_term("B16#"++Line0, Addr, _BinAddrAdj, D0) -> %Positive big number.
+parse_heap_term("B16#"++Line0, Addr, _DecodeOpts, D0) -> %Positive big number.
{Term,Line} = get_hex(Line0),
D = gb_trees:insert(Addr, Term, D0),
{Term,Line,D};
-parse_heap_term("B-16#"++Line0, Addr, _BinAddrAdj, D0) -> %Negative big number
+parse_heap_term("B-16#"++Line0, Addr, _DecodeOpts, D0) -> %Negative big number
{Term0,Line} = get_hex(Line0),
Term = -Term0,
D = gb_trees:insert(Addr, Term, D0),
{Term,Line,D};
-parse_heap_term("B"++Line0, Addr, _BinAddrAdj, D0) -> %Decimal big num
+parse_heap_term("B"++Line0, Addr, _DecodeOpts, D0) -> %Decimal big num
case string:to_integer(Line0) of
{Int,Line} when is_integer(Int) ->
D = gb_trees:insert(Addr, Int, D0),
{Int,Line,D}
end;
-parse_heap_term([$P|Line0], Addr, _BinAddrAdj, D0) -> % External Pid.
+parse_heap_term([$P|Line0], Addr, _DecodeOpts, D0) -> % External Pid.
{Pid0,Line} = get_id(Line0),
Pid = ['#CDVPid'|Pid0],
D = gb_trees:insert(Addr, Pid, D0),
{Pid,Line,D};
-parse_heap_term([$p|Line0], Addr, _BinAddrAdj, D0) -> % External Port.
+parse_heap_term([$p|Line0], Addr, _DecodeOpts, D0) -> % External Port.
{Port0,Line} = get_id(Line0),
Port = ['#CDVPort'|Port0],
D = gb_trees:insert(Addr, Port, D0),
{Port,Line,D};
-parse_heap_term("E"++Line0, Addr, _BinAddrAdj, D0) -> %Term encoded in external format.
- {Bin,Line} = get_binary(Line0),
+parse_heap_term("E"++Line0, Addr, DecodeOpts, D0) -> %Term encoded in external format.
+ {Bin,Line} = get_binary(Line0, DecodeOpts),
Term = binary_to_term(Bin),
D = gb_trees:insert(Addr, Term, D0),
{Term,Line,D};
-parse_heap_term("Yh"++Line0, Addr, _BinAddrAdj, D0) -> %Heap binary.
- {Term,Line} = get_binary(Line0),
+parse_heap_term("Yh"++Line0, Addr, DecodeOpts, D0) -> %Heap binary.
+ {Term,Line} = get_binary(Line0, DecodeOpts),
D = gb_trees:insert(Addr, Term, D0),
{Term,Line,D};
-parse_heap_term("Yc"++Line0, Addr, BinAddrAdj, D0) -> %Reference-counted binary.
+parse_heap_term("Yc"++Line0, Addr, DecodeOpts, D0) -> %Reference-counted binary.
{Binp0,":"++Line1} = get_hex(Line0),
{Offset,":"++Line2} = get_hex(Line1),
{Sz,Line} = get_hex(Line2),
- Binp = Binp0 bor BinAddrAdj,
- Term = case gb_trees:lookup(Binp, D0) of
- {value,Bin} -> cdvbin(Offset,Sz,Bin);
- none -> '#CDVNonexistingBinary'
- end,
- D = gb_trees:insert(Addr, Term, D0),
- {Term,Line,D};
-parse_heap_term("Ys"++Line0, Addr, BinAddrAdj, D0) -> %Sub binary.
+ Binp = Binp0 bor DecodeOpts#dec_opts.bin_addr_adj,
+ case lookup_binary_index(Binp) of
+ [{_,Start}] ->
+ SymbolicBin = {'#CDVBin',Start},
+ Term = cdvbin(Offset, Sz, SymbolicBin),
+ D1 = gb_trees:insert(Addr, Term, D0),
+ D = gb_trees:insert(Binp, SymbolicBin, D1),
+ {Term,Line,D};
+ [] ->
+ Term = '#CDVNonexistingBinary',
+ D1 = gb_trees:insert(Addr, Term, D0),
+ D = gb_trees:insert(Binp, Term, D1),
+ {Term,Line,D}
+ end;
+parse_heap_term("Ys"++Line0, Addr, DecodeOpts, D0) -> %Sub binary.
{Binp0,":"++Line1} = get_hex(Line0),
{Offset,":"++Line2} = get_hex(Line1),
- {Sz,Line} = get_hex(Line2),
- Binp = Binp0 bor BinAddrAdj,
- Term = case gb_trees:lookup(Binp, D0) of
- {value,Bin} -> cdvbin(Offset,Sz,Bin);
- none when Binp0=/=Binp ->
- %% Might it be on the heap?
- case gb_trees:lookup(Binp0, D0) of
- {value,Bin} -> cdvbin(Offset,Sz,Bin);
- none -> '#CDVNonexistingBinary'
- end;
- none -> '#CDVNonexistingBinary'
- end,
- D = gb_trees:insert(Addr, Term, D0),
- {Term,Line,D}.
-
+ {Sz,Line3} = get_hex(Line2),
+ {Term,Line,D1} = deref_bin(Binp0, Offset, Sz, Line3, DecodeOpts, D0),
+ D = gb_trees:insert(Addr, Term, D1),
+ {Term,Line,D};
+parse_heap_term("Mf"++Line0, Addr, DecodeOpts, D0) -> %Flatmap.
+ {Size,":"++Line1} = get_hex(Line0),
+ {Keys,":"++Line2,D1} = parse_term(Line1, DecodeOpts, D0),
+ {Values,Line,D2} = parse_tuple(Size, Line2, Addr,DecodeOpts, D1, []),
+ Pairs = zip_tuples(tuple_size(Keys), Keys, Values, []),
+ Map = maps:from_list(Pairs),
+ D = gb_trees:update(Addr, Map, D2),
+ {Map,Line,D};
+parse_heap_term("Mh"++Line0, Addr, DecodeOpts, D0) -> %Head node in a hashmap.
+ {MapSize,":"++Line1} = get_hex(Line0),
+ {N,":"++Line2} = get_hex(Line1),
+ {Nodes,Line,D1} = parse_tuple(N, Line2, Addr, DecodeOpts, D0, []),
+ Map = maps:from_list(flatten_hashmap_nodes(Nodes)),
+ MapSize = maps:size(Map), %Assertion.
+ D = gb_trees:update(Addr, Map, D1),
+ {Map,Line,D};
+parse_heap_term("Mn"++Line0, Addr, DecodeOpts, D) -> %Interior node in a hashmap.
+ {N,":"++Line} = get_hex(Line0),
+ parse_tuple(N, Line, Addr, DecodeOpts, D, []).
parse_tuple(0, Line, Addr, _, D0, Acc) ->
Tuple = list_to_tuple(lists:reverse(Acc)),
D = gb_trees:insert(Addr, Tuple, D0),
{Tuple,Line,D};
-parse_tuple(N, Line0, Addr, BinAddrAdj, D0, Acc) ->
- case parse_term(Line0, BinAddrAdj, D0) of
+parse_tuple(N, Line0, Addr, DecodeOpts, D0, Acc) ->
+ case parse_term(Line0, DecodeOpts, D0) of
{Term,[$,|Line],D} when N > 1 ->
- parse_tuple(N-1, Line, Addr, BinAddrAdj, D, [Term|Acc]);
+ parse_tuple(N-1, Line, Addr, DecodeOpts, D, [Term|Acc]);
{Term,Line,D}->
- parse_tuple(N-1, Line, Addr, BinAddrAdj, D, [Term|Acc])
+ parse_tuple(N-1, Line, Addr, DecodeOpts, D, [Term|Acc])
end.
-parse_term([$H|Line0], BinAddrAdj, D) -> %Pointer to heap term.
+zip_tuples(0, _T1, _T2, Acc) ->
+ Acc;
+zip_tuples(N, T1, T2, Acc) when N =< tuple_size(T1) ->
+ zip_tuples(N-1, T1, T2, [{element(N, T1),element(N, T2)}|Acc]).
+
+flatten_hashmap_nodes(Tuple) ->
+ flatten_hashmap_nodes_1(tuple_size(Tuple), Tuple, []).
+
+flatten_hashmap_nodes_1(0, _Tuple, Acc) ->
+ Acc;
+flatten_hashmap_nodes_1(N, Tuple0, Acc0) ->
+ case element(N, Tuple0) of
+ [K|V] ->
+ flatten_hashmap_nodes_1(N-1, Tuple0, [{K,V}|Acc0]);
+ Tuple when is_tuple(Tuple) ->
+ Acc = flatten_hashmap_nodes_1(N-1, Tuple0, Acc0),
+ flatten_hashmap_nodes_1(tuple_size(Tuple), Tuple, Acc)
+ end.
+
+parse_term([$H|Line0], DecodeOpts, D) -> %Pointer to heap term.
{Ptr,Line} = get_hex(Line0),
- deref_ptr(Ptr, Line, BinAddrAdj, D);
+ deref_ptr(Ptr, Line, DecodeOpts, D);
parse_term([$N|Line], _, D) -> %[] (nil).
{[],Line,D};
parse_term([$I|Line0], _, D) -> %Small.
@@ -2565,11 +2831,11 @@ parse_term([$p|Line0], _, D) -> %Port.
parse_term([$S|Str0], _, D) -> %Information string.
Str = lists:reverse(skip_blanks(lists:reverse(Str0))),
{Str,[],D};
-parse_term([$D|Line0], _, D) -> %DistExternal
+parse_term([$D|Line0], DecodeOpts, D) -> %DistExternal
try
{AttabSize,":"++Line1} = get_hex(Line0),
{Attab, "E"++Line2} = parse_atom_translation_table(AttabSize, Line1, []),
- {Bin,Line3} = get_binary(Line2),
+ {Bin,Line3} = get_binary(Line2, DecodeOpts),
{try
erts_debug:dist_ext_to_term(Attab, Bin)
catch
@@ -2595,32 +2861,62 @@ skip_dist_ext([C|Cs], KeptCs) ->
parse_atom([$A|Line0], D) ->
{N,":"++Line1} = get_hex(Line0),
{Chars, Line} = get_chars(N, Line1),
- {list_to_atom(Chars), Line, D}.
+ {binary_to_atom(list_to_binary(Chars),utf8), Line, D}.
parse_atom_translation_table(0, Line0, As) ->
{list_to_tuple(lists:reverse(As)), Line0};
parse_atom_translation_table(N, Line0, As) ->
{A, Line1, _} = parse_atom(Line0, []),
parse_atom_translation_table(N-1, Line1, [A|As]).
-
-
-deref_ptr(Ptr, Line, BinAddrAdj, D0) ->
- case gb_trees:lookup(Ptr, D0) of
+
+deref_ptr(Ptr, Line, DecodeOpts, D) ->
+ Lookup = fun(D0) ->
+ gb_trees:lookup(Ptr, D0)
+ end,
+ do_deref_ptr(Lookup, Line, DecodeOpts, D).
+
+deref_bin(Binp0, Offset, Sz, Line, DecodeOpts, D) ->
+ Binp = Binp0 bor DecodeOpts#dec_opts.bin_addr_adj,
+ Lookup = fun(D0) ->
+ lookup_binary(Binp, Offset, Sz, D0)
+ end,
+ do_deref_ptr(Lookup, Line, DecodeOpts, D).
+
+lookup_binary(Binp, Offset, Sz, D) ->
+ case lookup_binary_index(Binp) of
+ [{_,Start}] ->
+ Term = cdvbin(Offset, Sz, {'#CDVBin',Start}),
+ {value,Term};
+ [] ->
+ case gb_trees:lookup(Binp, D) of
+ {value,<<_:Offset/bytes,Sub:Sz/bytes,_/bytes>>} ->
+ {value,Sub};
+ {value,SymbolicBin} ->
+ {value,cdvbin(Offset, Sz, SymbolicBin)};
+ none ->
+ none
+ end
+ end.
+
+do_deref_ptr(Lookup, Line, DecodeOpts, D0) ->
+ case Lookup(D0) of
{value,Term} ->
{Term,Line,D0};
none ->
case get(fd) of
end_of_heap ->
+ put(incomplete_heap,true),
{['#CDVIncompleteHeap'],Line,D0};
Fd ->
- case val(Fd) of
+ case bytes(Fd) of
"="++_ ->
put(fd, end_of_heap),
- deref_ptr(Ptr, Line, BinAddrAdj, D0);
+ do_deref_ptr(Lookup, Line, DecodeOpts, D0);
L ->
- D = parse(L, BinAddrAdj, D0),
- deref_ptr(Ptr, Line, BinAddrAdj, D)
+ update_progress(length(L)+1),
+ D = parse(L, DecodeOpts, D0),
+ do_deref_ptr(Lookup, Line, DecodeOpts, D)
end
end
end.
@@ -2683,37 +2979,104 @@ get_label([$:|Line], Acc) ->
get_label([H|T], Acc) ->
get_label(T, [H|Acc]).
-get_binary(Line0) ->
- {N,":"++Line} = get_hex(Line0),
- do_get_binary(N, Line, []).
-
-get_binary(Offset,Size,Line0) ->
- {_N,":"++Line} = get_hex(Line0),
- do_get_binary(Size, lists:sublist(Line,(Offset*2)+1,Size*2), []).
-
-do_get_binary(0, Line, Acc) ->
+get_binary(Line0,DecodeOpts) ->
+ case get_hex(Line0) of
+ {N,":"++Line} ->
+ get_binary_1(N, Line, DecodeOpts);
+ _ ->
+ {'#CDVTruncatedBinary',[]}
+ end.
+
+get_binary_1(N,Line,#dec_opts{base64=false}) ->
+ get_binary_hex(N, Line, [], false);
+get_binary_1(N,Line0,#dec_opts{base64=true}) ->
+ NumBytes = ((N+2) div 3) * 4,
+ {Base64,Line} = lists:split(NumBytes, Line0),
+ Bin = get_binary_base64(list_to_binary(Base64), <<>>, false),
+ {Bin,Line}.
+
+get_binary(Offset,Size,Line0,DecodeOpts) ->
+ case get_hex(Line0) of
+ {_N,":"++Line} ->
+ get_binary_1(Offset,Size,Line,DecodeOpts);
+ _ ->
+ {'#CDVTruncatedBinary',[]}
+ end.
+
+get_binary_1(Offset,Size,Line,#dec_opts{base64=false}) ->
+ Progress = Size > ?binary_size_progress_limit,
+ Progress andalso init_progress("Reading binary",Size),
+ get_binary_hex(Size, lists:sublist(Line,(Offset*2)+1,Size*2), [],
+ Progress);
+get_binary_1(StartOffset,Size,Line,#dec_opts{base64=true}) ->
+ Progress = Size > ?binary_size_progress_limit,
+ Progress andalso init_progress("Reading binary",Size),
+ EndOffset = StartOffset + Size,
+ StartByte = (StartOffset div 3) * 4,
+ EndByte = ((EndOffset + 2) div 3) * 4,
+ NumBytes = EndByte - StartByte,
+ case list_to_binary(Line) of
+ <<_:StartByte/bytes,Base64:NumBytes/bytes,_/bytes>> ->
+ Bin0 = get_binary_base64(Base64, <<>>, Progress),
+ Skip = StartOffset - (StartOffset div 3) * 3,
+ <<_:Skip/bytes,Bin:Size/bytes,_/bytes>> = Bin0,
+ {Bin,[]};
+ _ ->
+ {'#CDVTruncatedBinary',[]}
+ end.
+
+get_binary_hex(0, Line, Acc, Progress) ->
+ Progress andalso end_progress(),
{list_to_binary(lists:reverse(Acc)),Line};
-do_get_binary(N, [A,B|Line], Acc) ->
+get_binary_hex(N, [A,B|Line], Acc, Progress) ->
Byte = (get_hex_digit(A) bsl 4) bor get_hex_digit(B),
- do_get_binary(N-1, Line, [Byte|Acc]);
-do_get_binary(_N, [], _Acc) ->
+ Progress andalso update_progress(),
+ get_binary_hex(N-1, Line, [Byte|Acc], Progress);
+get_binary_hex(_N, [], _Acc, Progress) ->
+ Progress andalso end_progress(),
{'#CDVTruncatedBinary',[]}.
+get_binary_base64(<<Chunk0:?base64_chunk_size/bytes,T/bytes>>,
+ Acc0, Progress) ->
+ Chunk = base64:decode(Chunk0),
+ Acc = <<Acc0/binary,Chunk/binary>>,
+ Progress andalso update_progress(?base64_chunk_size * 3 div 4),
+ get_binary_base64(T, Acc, Progress);
+get_binary_base64(Chunk0, Acc, Progress) ->
+ case Progress of
+ true ->
+ update_progress(?base64_chunk_size * 3 div 4),
+ end_progress();
+ false ->
+ ok
+ end,
+ Chunk = base64:decode(Chunk0),
+ <<Acc/binary,Chunk/binary>>.
+
cdvbin(Offset,Size,{'#CDVBin',Pos}) ->
['#CDVBin',Offset,Size,Pos];
cdvbin(Offset,Size,['#CDVBin',_,_,Pos]) ->
['#CDVBin',Offset,Size,Pos];
cdvbin(_,_,'#CDVTruncatedBinary') ->
- '#CDVTruncatedBinary'.
+ '#CDVTruncatedBinary';
+cdvbin(_,_,'#CDVNonexistingBinary') ->
+ '#CDVNonexistingBinary'.
%%-----------------------------------------------------------------
-%% Functions for accessing the cdv_dump_index_table
-reset_index_table() ->
- ets:delete_all_objects(cdv_dump_index_table).
+%% Functions for accessing tables
+reset_tables() ->
+ ets:delete_all_objects(cdv_dump_index_table),
+ ets:delete_all_objects(cdv_reg_proc_table),
+ ets:delete_all_objects(cdv_binary_index_table),
+ ets:delete_all_objects(cdv_heap_file_chars).
insert_index(Tag,Id,Pos) ->
ets:insert(cdv_dump_index_table,{{Tag,Pos},Id}).
+delete_index(Tag,Id) ->
+ Ms = [{{{Tag,'$1'},Id},[],[true]}],
+ ets:select_delete(cdv_dump_index_table, Ms).
+
lookup_index({Tag,Id}) ->
lookup_index(Tag,Id);
lookup_index(Tag) ->
@@ -2724,6 +3087,12 @@ lookup_index(Tag,Id) ->
count_index(Tag) ->
ets:select_count(cdv_dump_index_table,[{{{Tag,'_'},'_'},[],[true]}]).
+insert_binary_index(Addr,Pos) ->
+ ets:insert(cdv_binary_index_table,{Addr,Pos}).
+
+lookup_binary_index(Addr) ->
+ ets:lookup(cdv_binary_index_table,Addr).
+
%%-----------------------------------------------------------------
%% Convert tags read from crashdump to atoms used as first part of key
@@ -2733,6 +3102,10 @@ tag_to_atom("allocated_areas") -> ?allocated_areas;
tag_to_atom("allocator") -> ?allocator;
tag_to_atom("atoms") -> ?atoms;
tag_to_atom("binary") -> ?binary;
+tag_to_atom("dirty_cpu_scheduler") -> ?dirty_cpu_scheduler;
+tag_to_atom("dirty_cpu_run_queue") -> ?dirty_cpu_run_queue;
+tag_to_atom("dirty_io_scheduler") -> ?dirty_io_scheduler;
+tag_to_atom("dirty_io_run_queue") -> ?dirty_io_run_queue;
tag_to_atom("end") -> ?ende;
tag_to_atom("erl_crash_dump") -> ?erl_crash_dump;
tag_to_atom("ets") -> ?ets;
@@ -2742,6 +3115,7 @@ tag_to_atom("hidden_node") -> ?hidden_node;
tag_to_atom("index_table") -> ?index_table;
tag_to_atom("instr_data") -> ?instr_data;
tag_to_atom("internal_ets") -> ?internal_ets;
+tag_to_atom("literals") -> ?literals;
tag_to_atom("loaded_modules") -> ?loaded_modules;
tag_to_atom("memory") -> ?memory;
tag_to_atom("mod") -> ?mod;
@@ -2759,14 +3133,16 @@ tag_to_atom("scheduler") -> ?scheduler;
tag_to_atom("timer") -> ?timer;
tag_to_atom("visible_node") -> ?visible_node;
tag_to_atom(UnknownTag) ->
- io:format("WARNING: Found unexpected tag:~s~n",[UnknownTag]),
+ io:format("WARNING: Found unexpected tag:~ts~n",[UnknownTag]),
list_to_atom(UnknownTag).
%%%-----------------------------------------------------------------
%%% Store last tag for use when truncated, and reason if aborted
put_last_tag(?abort,Reason) ->
- %% Don't overwrite the real last tag
- put(truncated_reason,Reason);
+ %% Don't overwrite the real last tag, and make sure to return
+ %% the previous last tag.
+ put(truncated_reason,Reason),
+ get(last_tag);
put_last_tag(Tag,Id) ->
put(last_tag,{Tag,Id}).
@@ -2794,23 +3170,6 @@ to_value_list(Record) ->
Values.
%%%-----------------------------------------------------------------
-%%% Fold over List and report progress in percent.
-%%% Report is the text to be presented in the progress dialog.
-%%% Acc0 is the initial accumulator and will be passed to Fun as the
-%%% second arguement, i.e. Fun = fun(Item,Acc) -> NewAcc end.
-progress_foldl(Report,Fun,Acc0,List) ->
- init_progress(Report, length(List)),
- progress_foldl1(Fun,Acc0,List).
-
-progress_foldl1(Fun,Acc,[H|T]) ->
- update_progress(),
- progress_foldl1(Fun,Fun(H,Acc),T);
-progress_foldl1(_Fun,Acc,[]) ->
- end_progress(),
- Acc.
-
-
-%%%-----------------------------------------------------------------
%%% Map over List and report progress in percent.
%%% Report is the text to be presented in the progress dialog.
%%% Distribute the load over a number of processes, and File is opened
diff --git a/lib/observer/src/crashdump_viewer.hrl b/lib/observer/src/crashdump_viewer.hrl
index 6a93a089fd..856e558e6c 100644
--- a/lib/observer/src/crashdump_viewer.hrl
+++ b/lib/observer/src/crashdump_viewer.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -80,6 +80,10 @@
old_heap,
heap_unused,
old_heap_unused,
+ bin_vheap,
+ old_bin_vheap,
+ bin_vheap_unused,
+ old_bin_vheap_unused,
new_heap_start,
new_heap_top,
stack_top,
@@ -95,19 +99,27 @@
-record(port,
{id,
+ state,
+ task_flags=0,
slot,
connected,
links,
name,
monitors,
- controls}).
+ suspended,
+ controls,
+ input,
+ output,
+ queue,
+ port_data}).
-record(sched,
{name,
+ type,
process,
port,
run_q=0,
- port_q=0,
+ port_q,
details=#{}
}).
diff --git a/lib/observer/src/etop_tr.erl b/lib/observer/src/etop_tr.erl
index 8e43f8bb35..c7e62e8332 100644
--- a/lib/observer/src/etop_tr.erl
+++ b/lib/observer/src/etop_tr.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -89,14 +89,14 @@ handle_data(Last, {_, Pid, out, _, Time2} = G, Store) ->
end,
New;
false ->
- io:format("Erlang top got garbage ~p~n", [G]),
+ io:format("Erlang top got garbage ~tp~n", [G]),
Last
end;
handle_data(_W, {drop, D}, _) -> %% Error case we are missing data here!
io:format("Erlang top dropped data ~p~n", [D]),
[];
handle_data(Last, G, _) ->
- io:format("Erlang top got garbage ~p~n", [G]),
+ io:format("Erlang top got garbage ~tp~n", [G]),
Last.
elapsed({Me1, S1, Mi1}, {Me2, S2, Mi2}) ->
diff --git a/lib/observer/src/etop_txt.erl b/lib/observer/src/etop_txt.erl
index 183641119a..cd3ec62c13 100644
--- a/lib/observer/src/etop_txt.erl
+++ b/lib/observer/src/etop_txt.erl
@@ -48,7 +48,6 @@ do_update(Prev,Config) ->
do_update(standard_io,Info,Prev,Config).
do_update(Fd,Info,Prev,Config) ->
- Encoding = encoding(Fd),
{Cpu,NProcs,RQ,Clock} = loadinfo(Info,Prev),
io:nl(Fd),
writedoubleline(Fd),
@@ -72,7 +71,7 @@ do_update(Fd,Info,Prev,Config) ->
io:nl(Fd),
writepinfo_header(Fd),
writesingleline(Fd),
- writepinfo(Fd,Info#etop_info.procinfo,Encoding),
+ writepinfo(Fd,Info#etop_info.procinfo,modifier(Fd)),
writedoubleline(Fd),
io:nl(Fd),
Info.
@@ -93,26 +92,27 @@ writepinfo(Fd,[#etop_proc_info{pid=Pid,
cf=MFA,
mq=MQ}
|T],
- Encoding) ->
- io:fwrite(Fd,proc_format(Encoding),
- [Pid,to_list(Name,Encoding),Time,Reds,Mem,MQ,
- formatmfa(MFA,Encoding)]),
- writepinfo(Fd,T,Encoding);
+ Modifier) ->
+ io:fwrite(Fd,proc_format(Modifier),
+ [Pid,to_string(Name,Modifier),Time,Reds,Mem,MQ,
+ to_string(MFA,Modifier)]),
+ writepinfo(Fd,T,Modifier);
writepinfo(_Fd,[],_) ->
ok.
+proc_format(Modifier) ->
+ "~-15w~-20"++Modifier++"s~8w~8w~8w~8w ~-20"++Modifier++"s~n".
-formatmfa({M, F, A},latin1) ->
- io_lib:format("~w:~w/~w",[M, F, A]);
-formatmfa({M, F, A},_) ->
- io_lib:format("~w:~tw/~w",[M, F, A]);
-formatmfa(Other,_) ->
- %% E.g. when running hipe - the current_function for some
- %% processes will be 'undefined'
- io_lib:format("~w",[Other]).
+to_string({M,F,A},Modifier) ->
+ io_lib:format("~w:~"++Modifier++"w/~w",[M,F,A]);
+to_string(Other,Modifier) ->
+ io_lib:format("~"++Modifier++"w",[Other]).
-to_list(Name,_) when is_atom(Name) -> atom_to_list(Name);
-to_list({_M,_F,_A}=MFA,Encoding) -> formatmfa(MFA,Encoding).
+modifier(Device) ->
+ case encoding(Device) of
+ latin1 -> "";
+ _ -> "t"
+ end.
encoding(Device) ->
case io:getopts(Device) of
@@ -122,7 +122,3 @@ encoding(Device) ->
latin1
end.
-proc_format(latin1) ->
- "~-15w~-20s~8w~8w~8w~8w ~-20s~n";
-proc_format(_) ->
- "~-15w~-20ts~8w~8w~8w~8w ~-20ts~n".
diff --git a/lib/observer/src/multitrace.erl b/lib/observer/src/multitrace.erl
index a01eeec6ae..35b70c63a3 100644
--- a/lib/observer/src/multitrace.erl
+++ b/lib/observer/src/multitrace.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -103,16 +103,16 @@ print_func(Out,{trace_ts,P,call,{M,F,A},C,Ts},N) ->
io:format(Out,
"~w: ~s~n"
"Process : ~w~n"
- "Call : ~w:~w/~w~n"
- "Arguments : ~p~n"
- "Caller : ~w~n~n",
+ "Call : ~w:~tw/~w~n"
+ "Arguments : ~tp~n"
+ "Caller : ~tw~n~n",
[N,ts(Ts),P,M,F,length(A),A,C]);
print_func(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
io:format(Out,
"~w: ~s~n"
"Process : ~w~n"
- "Return from : ~w:~w/~w~n"
- "Return value : ~p~n~n",
+ "Return from : ~w:~tw/~w~n"
+ "Return value : ~tp~n~n",
[N,ts(Ts),P,M,F,A,R]).
@@ -181,7 +181,7 @@ handle_schedule(Out,{trace_ts,P,out,Info,Ts},_TI,S) ->
"out:~n"
"Process : ~w~n"
"Time : ~s~n"
- "Function : ~w~n~n",[P,ts(Ts),Info]),
+ "Function : ~tw~n~n",[P,ts(Ts),Info]),
case lists:keysearch(P,1,S) of
{value,{P,List}} ->
lists:keyreplace(P,1,S,{P,[{out,Ts}|List]});
@@ -193,7 +193,7 @@ handle_schedule(Out,{trace_ts,P,in,Info,Ts},_TI,S) ->
"in:~n"
"Process : ~w~n"
"Time : ~s~n"
- "Function : ~w~n~n",[P,ts(Ts),Info]),
+ "Function : ~tw~n~n",[P,ts(Ts),Info]),
case lists:keysearch(P,1,S) of
{value,{P,List}} ->
lists:keyreplace(P,1,S,{P,[{in,Ts}|List]});
diff --git a/lib/observer/src/observer.app.src b/lib/observer/src/observer.app.src
index 3a5bd172e7..d73293a5f9 100644
--- a/lib/observer/src/observer.app.src
+++ b/lib/observer/src/observer.app.src
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -65,8 +65,7 @@
{registered, []},
{applications, [kernel, stdlib]},
{env, []},
- {runtime_dependencies, ["wx-1.2","stdlib-2.0","runtime_tools-1.8.14",
- "kernel-3.0","inets-5.10","et-1.5",
- "erts-7.0"]}]}.
+ {runtime_dependencies, ["wx-1.2","stdlib-3.5","runtime_tools-1.8.14",
+ "kernel-3.0","et-1.5","erts-7.0"]}]}.
diff --git a/lib/observer/src/observer_alloc_wx.erl b/lib/observer/src/observer_alloc_wx.erl
index ef425f0874..54e246f247 100644
--- a/lib/observer/src/observer_alloc_wx.erl
+++ b/lib/observer/src/observer_alloc_wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -79,8 +79,8 @@ init([Notebook, Parent, Config]) ->
max = #{}
}
}
- catch _:Err ->
- io:format("~p crashed ~p: ~p~n",[?MODULE, Err, erlang:get_stacktrace()]),
+ catch _:Err:Stacktrace ->
+ io:format("~p crashed ~tp: ~tp~n",[?MODULE, Err, Stacktrace]),
{stop, Err}
end.
@@ -183,7 +183,7 @@ handle_info({'EXIT', Old, _}, State = #state{appmon=Old}) ->
{noreply, State#state{active=false, appmon=undefined}};
handle_info(_Event, State) ->
- %% io:format("~p:~p: ~p~n",[?MODULE,?LINE,_Event]),
+ %% io:format("~p:~p: ~tp~n",[?MODULE,?LINE,_Event]),
{noreply, State}.
terminate(_Event, #state{}) ->
diff --git a/lib/observer/src/observer_app_wx.erl b/lib/observer/src/observer_app_wx.erl
index bc4f1fe117..2a481966da 100644
--- a/lib/observer/src/observer_app_wx.erl
+++ b/lib/observer/src/observer_app_wx.erl
@@ -320,7 +320,7 @@ handle_info({'EXIT', _, noconnection}, State) ->
handle_info({'EXIT', _, normal}, State) ->
{noreply, State};
handle_info(_Event, State) ->
- %% io:format("~p:~p: ~p~n",[?MODULE,?LINE,_Event]),
+ %% io:format("~p:~p: ~tp~n",[?MODULE,?LINE,_Event]),
{noreply, State}.
%%%%%%%%%%
diff --git a/lib/observer/src/observer_html_lib.erl b/lib/observer/src/observer_html_lib.erl
index 1f1306c370..0c4e32af49 100644
--- a/lib/observer/src/observer_html_lib.erl
+++ b/lib/observer/src/observer_html_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -142,13 +142,13 @@ dict_table(Tab,{Key0,Value0}, Even) ->
tr(color(Even), [td("VALIGN=center",pre(Key)), td(pre(Value))]).
proc_state(Tab,{Key0,Value0}, Even) ->
- Key = lists:flatten(io_lib:format("~s",[Key0])),
+ Key = lists:flatten(io_lib:format("~ts",[Key0])),
Value = all_or_expand(Tab,Value0),
tr(color(Even), [td("VALIGN=center",Key), td(pre(Value))]).
all_or_expand(Tab,Term) ->
- Preview = io_lib:format("~P",[Term,8]),
- Check = io_lib:format("~P",[Term,100]),
+ Preview = io_lib:format("~tP",[Term,8]),
+ Check = io_lib:format("~tP",[Term,100]),
Exp = Preview=/=Check,
all_or_expand(Tab,Term,Preview,Exp).
all_or_expand(_Tab,Term,Str,false)
@@ -166,13 +166,8 @@ all_or_expand(Tab,Term,Preview,true)
"Click to expand above term")];
all_or_expand(Tab,Bin,_PreviewStr,_Expand)
when is_binary(Bin) ->
- Size = byte_size(Bin),
- PrevSize = min(Size, 10) * 8,
- <<Preview:PrevSize, _/binary>> = Bin,
- Hash = erlang:phash2(Bin),
- Key = {Preview, Size, Hash},
- ets:insert(Tab,{Key,Bin}),
- Term = io_lib:format("~p", [['#OBSBin',Preview,Size,Hash]]),
+ OBSBin = observer_lib:make_obsbin(Bin,Tab),
+ 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));
@@ -283,24 +278,24 @@ href_proc_port("['#CDVPort'"++T,Acc,LTB) ->
%% Port written by crashdump_viewer:parse_term(...)
{Port0,Rest} = split($],T),
PortStr=
- case string:tokens(Port0,",.|") of
+ case string:lexemes(Port0,",.|") of
[X,Y] ->
Port = "#Port&lt;"++X++"."++Y++"&gt;",
href(Port,Port);
Ns ->
- "#Port&lt;" ++ string:join(Ns,".") ++"...&gt;"
+ "#Port&lt;" ++ lists:join($.,Ns) ++"...&gt;"
end,
href_proc_port(Rest,[PortStr|Acc],LTB);
href_proc_port("['#CDVPid'"++T,Acc,LTB) ->
%% Pid written by crashdump_viewer:parse_term(...)
{Pid0,Rest} = split($],T),
PidStr =
- case string:tokens(Pid0,",.|") of
+ case string:lexemes(Pid0,",.|") of
[X,Y,Z] ->
Pid = "&lt;"++X++"."++Y++"."++Z++"&gt;",
href(Pid,Pid);
Ns ->
- "&lt;" ++ string:join(Ns,".") ++ "...&gt;"
+ "&lt;" ++ lists:join($.,Ns) ++ "...&gt;"
end,
href_proc_port(Rest,[PidStr|Acc],LTB);
href_proc_port("'#CDVIncompleteHeap'"++T,Acc,LTB)->
@@ -337,28 +332,37 @@ href_proc_port([],Acc,_) ->
href_proc_bin(From, T, Acc, LTB) ->
{OffsetSizePos,Rest} = split($],T),
BinStr =
- case string:tokens(OffsetSizePos,",.| \n") of
+ case string:lexemes(OffsetSizePos,",.| \n") of
[Offset,SizeStr,Pos] when From =:= cdv ->
- Id = {list_to_integer(Offset),10,list_to_integer(Pos)},
- {ok,PreviewBin} = crashdump_viewer:expand_binary(Id),
- PreviewStr = preview_string(list_to_integer(SizeStr), PreviewBin),
- if LTB ->
- href("TARGET=\"expanded\"",
- ["#Binary?offset="++Offset++
- "&size="++SizeStr++
- "&pos="++Pos],
- PreviewStr);
- true ->
- PreviewStr
- end;
- [Preview,SizeStr,Md5] when From =:= obs ->
+ Size = list_to_integer(SizeStr),
+ PreviewSize = min(Size,10),
+ Id = {list_to_integer(Offset),PreviewSize,list_to_integer(Pos)},
+ case crashdump_viewer:expand_binary(Id) of
+ {ok, '#CDVTruncatedBinary'} ->
+ lists:flatten(
+ "<FONT COLOR=\"#FF0000\">"
+ "&lt;&lt;...(Truncated Binary)&gt;&gt;"
+ "</FONT>");
+ {ok, PreviewBin} ->
+ PreviewStr = preview_string(Size, PreviewBin),
+ if LTB ->
+ href("TARGET=\"expanded\"",
+ ["#Binary?offset="++Offset++
+ "&size="++SizeStr++
+ "&pos="++Pos],
+ PreviewStr);
+ true ->
+ PreviewStr
+ end
+ end;
+ [PreviewIntStr,PreviewBitSizeStr,SizeStr,Md5] when From =:= obs ->
Size = list_to_integer(SizeStr),
- PrevSize = min(Size, 10) * 8,
- PreviewStr = preview_string(Size,
- <<(list_to_integer(Preview)):PrevSize>>),
+ PreviewInt = list_to_integer(PreviewIntStr),
+ PreviewBitSize = list_to_integer(PreviewBitSizeStr),
+ PreviewStr = preview_string(Size,<<PreviewInt:PreviewBitSize>>),
if LTB ->
href("TARGET=\"expanded\"",
- ["#OBSBinary?key1="++Preview++
+ ["#OBSBinary?key1="++PreviewIntStr++
"&key2="++SizeStr++
"&key3="++Md5],
PreviewStr);
@@ -372,14 +376,14 @@ href_proc_bin(From, T, Acc, LTB) ->
preview_string(Size, PreviewBin) when Size > 10 ->
["&lt;&lt;",
- remove_lgt(io_lib:format("~p",[PreviewBin])),
+ remove_lgt(io_lib:format("~tp",[PreviewBin])),
"...(",
observer_lib:to_str({bytes,Size}),
")",
"&gt;&gt"];
preview_string(_, PreviewBin) ->
["&lt;&lt;",
- remove_lgt(io_lib:format("~p",[PreviewBin])),
+ remove_lgt(io_lib:format("~tp",[PreviewBin])),
"&gt;&gt"].
remove_lgt(Deep) ->
diff --git a/lib/observer/src/observer_lib.erl b/lib/observer/src/observer_lib.erl
index c7ee294719..7c68b0ebb6 100644
--- a/lib/observer/src/observer_lib.erl
+++ b/lib/observer/src/observer_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,8 @@
-export([get_wx_parent/1,
display_info_dialog/2, display_yes_no_dialog/1,
- display_progress_dialog/2, destroy_progress_dialog/0,
+ display_progress_dialog/3,
+ destroy_progress_dialog/0, sync_destroy_progress_dialog/0,
wait_for_progress/0, report_progress/1,
user_term/3, user_term_multiline/3,
interval_dialog/4, start_timer/1, start_timer/2, stop_timer/1, timer_config/1,
@@ -30,7 +31,9 @@
create_attrs/0,
set_listctrl_col_size/2,
create_status_bar/1,
- html_window/1, html_window/2
+ html_window/1, html_window/2,
+ make_obsbin/2,
+ add_scroll_entries/2
]).
-include_lib("wx/include/wx.hrl").
@@ -39,6 +42,9 @@
-define(SINGLE_LINE_STYLE, ?wxBORDER_NONE bor ?wxTE_READONLY bor ?wxTE_RICH2).
-define(MULTI_LINE_STYLE, ?SINGLE_LINE_STYLE bor ?wxTE_MULTILINE).
+-define(NUM_SCROLL_ITEMS,8).
+
+-define(pulse_timeout,50).
get_wx_parent(Window) ->
Parent = wxWindow:getParent(Window),
@@ -297,8 +303,10 @@ to_str(No) when is_integer(No) ->
integer_to_list(No);
to_str(Float) when is_float(Float) ->
io_lib:format("~.3f", [Float]);
+to_str({trunc, Float}) when is_float(Float) ->
+ float_to_list(Float, [{decimals,0}]);
to_str(Term) ->
- io_lib:format("~w", [Term]).
+ io_lib:format("~tw", [Term]).
create_menus([], _MenuBar, _Type) -> ok;
create_menus(Menus, MenuBar, Type) ->
@@ -393,17 +401,18 @@ get_box_info({Title, left, List}) -> {Title, ?wxALIGN_LEFT, List};
get_box_info({Title, right, List}) -> {Title, ?wxALIGN_RIGHT, List}.
add_box(Panel, OuterBox, Cursor, Title, Proportion, {Format, List}) ->
- Box = wxStaticBoxSizer:new(?wxVERTICAL, Panel, [{label, Title}]),
+ NumStr = " ("++integer_to_list(length(List))++")",
+ Box = wxStaticBoxSizer:new(?wxVERTICAL, Panel, [{label, Title ++ NumStr}]),
Scroll = wxScrolledWindow:new(Panel),
wxScrolledWindow:enableScrolling(Scroll,true,true),
wxScrolledWindow:setScrollbars(Scroll,1,1,0,0),
ScrollSizer = wxBoxSizer:new(?wxVERTICAL),
wxScrolledWindow:setSizer(Scroll, ScrollSizer),
wxWindow:setBackgroundStyle(Scroll, ?wxBG_STYLE_SYSTEM),
- add_entries(Format, List, Scroll, ScrollSizer, Cursor),
+ Entries = add_entries(Format, List, Scroll, ScrollSizer, Cursor),
wxSizer:add(Box,Scroll,[{proportion,1},{flag,?wxEXPAND}]),
wxSizer:add(OuterBox,Box,[{proportion,Proportion},{flag,?wxEXPAND}]),
- {Scroll,ScrollSizer,length(List)}.
+ {Scroll,ScrollSizer,length(Entries)}.
add_entries(click, List, Scroll, ScrollSizer, Cursor) ->
Add = fun(Link) ->
@@ -411,7 +420,20 @@ add_entries(click, List, Scroll, ScrollSizer, Cursor) ->
wxWindow:setBackgroundStyle(TC, ?wxBG_STYLE_SYSTEM),
wxSizer:add(ScrollSizer,TC, [{flag,?wxEXPAND}])
end,
- [Add(Link) || Link <- List];
+ if length(List) > ?NUM_SCROLL_ITEMS ->
+ {List1,Rest} = lists:split(?NUM_SCROLL_ITEMS,List),
+ LinkEntries = [Add(Link) || Link <- List1],
+ NStr = integer_to_list(length(Rest)),
+ TC = link_entry2(Scroll,
+ {{more,{Rest,Scroll,ScrollSizer}},"more..."},
+ Cursor,
+ "Click to see " ++ NStr ++ " more entries"),
+ wxWindow:setBackgroundStyle(TC, ?wxBG_STYLE_SYSTEM),
+ E = wxSizer:add(ScrollSizer,TC, [{flag,?wxEXPAND}]),
+ LinkEntries ++ [E];
+ true ->
+ [Add(Link) || Link <- List]
+ end;
add_entries(plain, List, Scroll, ScrollSizer, _) ->
Add = fun(String) ->
TC = wxStaticText:new(Scroll, ?wxID_ANY, String),
@@ -419,6 +441,23 @@ add_entries(plain, List, Scroll, ScrollSizer, _) ->
end,
[Add(String) || String <- List].
+add_scroll_entries(MoreEntry,{List, Scroll, ScrollSizer}) ->
+ wx:batch(
+ fun() ->
+ wxSizer:remove(ScrollSizer,?NUM_SCROLL_ITEMS),
+ wxStaticText:destroy(MoreEntry),
+ Cursor = wxCursor:new(?wxCURSOR_HAND),
+ Add = fun(Link) ->
+ TC = link_entry(Scroll, Link, Cursor),
+ wxWindow:setBackgroundStyle(TC, ?wxBG_STYLE_SYSTEM),
+ wxSizer:add(ScrollSizer,TC, [{flag,?wxEXPAND}])
+ end,
+ Entries = [Add(Link) || Link <- List],
+ wxCursor:destroy(Cursor),
+ wxSizer:layout(ScrollSizer),
+ wxSizer:setVirtualSizeHints(ScrollSizer,Scroll),
+ Entries
+ end).
create_box(_Panel, {scroll_boxes,[]}) ->
undefined;
@@ -445,7 +484,7 @@ create_box(Panel, {scroll_boxes,Data}) ->
{_,H} = wxWindow:getSize(Dummy),
wxTextCtrl:destroy(Dummy),
- MaxH = if MaxL > 8 -> 8*H;
+ MaxH = if MaxL > ?NUM_SCROLL_ITEMS -> ?NUM_SCROLL_ITEMS*H;
true -> MaxL*H
end,
[wxWindow:setMinSize(B,{0,MaxH}) || {B,_,_} <- Boxes],
@@ -474,7 +513,7 @@ create_box(Parent, Data) ->
link_entry(Panel,Value);
_ ->
Value = to_str(Value0),
- case string:sub_word(lists:sublist(Value, 80),1,$\n) of
+ case string:nth_lexeme(lists:sublist(Value, 80),1, [$\n]) of
Value ->
%% Short string, no newlines - show all
wxStaticText:new(Panel, ?wxID_ANY, Value);
@@ -500,25 +539,27 @@ create_box(Parent, Data) ->
link_entry(Panel, Link) ->
Cursor = wxCursor:new(?wxCURSOR_HAND),
- TC = link_entry2(Panel, to_link(Link), Cursor),
+ TC = link_entry(Panel, Link, Cursor),
wxCursor:destroy(Cursor),
TC.
link_entry(Panel, Link, Cursor) ->
- link_entry2(Panel, to_link(Link), Cursor).
+ link_entry2(Panel,to_link(Link),Cursor).
link_entry2(Panel,{Target,Str},Cursor) ->
+ link_entry2(Panel,{Target,Str},Cursor,"Click to see properties for " ++ Str).
+link_entry2(Panel,{Target,Str},Cursor,ToolTipText) ->
TC = wxStaticText:new(Panel, ?wxID_ANY, Str),
wxWindow:setForegroundColour(TC,?wxBLUE),
wxWindow:setCursor(TC, Cursor),
wxWindow:connect(TC, left_down, [{userData,Target}]),
wxWindow:connect(TC, enter_window),
wxWindow:connect(TC, leave_window),
- ToolTip = wxToolTip:new("Click to see properties for " ++ Str),
+ ToolTip = wxToolTip:new(ToolTipText),
wxWindow:setToolTip(TC, ToolTip),
TC.
to_link(RegName={Name, Node}) when is_atom(Name), is_atom(Node) ->
- Str = io_lib:format("{~p,~p}", [Name, Node]),
+ Str = io_lib:format("{~tp,~p}", [Name, Node]),
{RegName, Str};
to_link(TI = {_Target, _Identifier}) ->
TI;
@@ -639,11 +680,11 @@ parse_string(Str) ->
Tokens = case erl_scan:string(Str, 1, [text]) of
{ok, Ts, _} -> Ts;
{error, {_SLine, SMod, SError}, _} ->
- throw(io_lib:format("~s", [SMod:format_error(SError)]))
+ throw(io_lib:format("~ts", [SMod:format_error(SError)]))
end,
- case lib:extended_parse_term(Tokens) of
+ case erl_eval:extended_parse_term(Tokens) of
{error, {_PLine, PMod, PError}} ->
- throw(io_lib:format("~s", [PMod:format_error(PError)]));
+ throw(io_lib:format("~ts", [PMod:format_error(PError)]));
Res -> Res
end
catch
@@ -685,11 +726,11 @@ create_status_bar(Panel) ->
%%%-----------------------------------------------------------------
%%% Progress dialog
-define(progress_handler,cdv_progress_handler).
-display_progress_dialog(Title,Str) ->
+display_progress_dialog(Parent,Title,Str) ->
Caller = self(),
Env = wx:get_env(),
spawn_link(fun() ->
- progress_handler(Caller,Env,Title,Str)
+ progress_handler(Caller,Env,Parent,Title,Str)
end),
ok.
@@ -704,6 +745,11 @@ wait_for_progress() ->
destroy_progress_dialog() ->
report_progress(finish).
+sync_destroy_progress_dialog() ->
+ Ref = erlang:monitor(process,?progress_handler),
+ destroy_progress_dialog(),
+ receive {'DOWN',Ref,process,_,_} -> ok end.
+
report_progress(Progress) ->
case whereis(?progress_handler) of
Pid when is_pid(Pid) ->
@@ -713,31 +759,38 @@ report_progress(Progress) ->
ok
end.
-progress_handler(Caller,Env,Title,Str) ->
+progress_handler(Caller,Env,Parent,Title,Str) ->
register(?progress_handler,self()),
wx:set_env(Env),
- PD = progress_dialog(Env,Title,Str),
- try progress_loop(Title,PD,Caller)
+ PD = progress_dialog(Env,Parent,Title,Str),
+ try progress_loop(Title,PD,Caller,infinity)
catch closed -> normal end.
-progress_loop(Title,PD,Caller) ->
+progress_loop(Title,PD,Caller,Pulse) ->
receive
{progress,{ok,done}} -> % to make wait_for_progress/0 return
Caller ! continue,
- progress_loop(Title,PD,Caller);
+ progress_loop(Title,PD,Caller,Pulse);
+ {progress,{ok,start_pulse}} ->
+ update_progress_pulse(PD),
+ progress_loop(Title,PD,Caller,?pulse_timeout);
+ {progress,{ok,stop_pulse}} ->
+ progress_loop(Title,PD,Caller,infinity);
{progress,{ok,Percent}} when is_integer(Percent) ->
update_progress(PD,Percent),
- progress_loop(Title,PD,Caller);
+ progress_loop(Title,PD,Caller,Pulse);
{progress,{ok,Msg}} ->
update_progress_text(PD,Msg),
- progress_loop(Title,PD,Caller);
+ progress_loop(Title,PD,Caller,Pulse);
{progress,{error, Reason}} ->
+ {Dialog,_,_} = PD,
+ Parent = wxWindow:getParent(Dialog),
finish_progress(PD),
FailMsg =
if is_list(Reason) -> Reason;
true -> file:format_error(Reason)
end,
- display_info_dialog(PD,"Crashdump Viewer Error",FailMsg),
+ display_info_dialog(Parent,"Crashdump Viewer Error",FailMsg),
Caller ! error,
unregister(?progress_handler),
unlink(Caller);
@@ -745,25 +798,76 @@ progress_loop(Title,PD,Caller) ->
finish_progress(PD),
unregister(?progress_handler),
unlink(Caller)
+ after Pulse ->
+ update_progress_pulse(PD),
+ progress_loop(Title,PD,Caller,?pulse_timeout)
end.
-progress_dialog(_Env,Title,Str) ->
- PD = wxProgressDialog:new(Title,Str,
- [{maximum,101},
- {style,
- ?wxPD_APP_MODAL bor
- ?wxPD_SMOOTH bor
- ?wxPD_AUTO_HIDE}]),
- wxProgressDialog:setMinSize(PD,{200,-1}),
- PD.
+progress_dialog(_Env,Parent,Title,Str) ->
+ progress_dialog_new(Parent,Title,Str).
update_progress(PD,Value) ->
- try wxProgressDialog:update(PD,Value)
+ try progress_dialog_update(PD,Value)
catch _:_ -> throw(closed) %% Port or window have died
end.
update_progress_text(PD,Text) ->
- try wxProgressDialog:update(PD,0,[{newmsg,Text}])
+ try progress_dialog_update(PD,Text)
+ catch _:_ -> throw(closed) %% Port or window have died
+ end.
+update_progress_pulse(PD) ->
+ try progress_dialog_pulse(PD)
catch _:_ -> throw(closed) %% Port or window have died
end.
finish_progress(PD) ->
- wxProgressDialog:destroy(PD).
+ try progress_dialog_update(PD,100)
+ catch _:_ -> ok
+ after progress_dialog_destroy(PD)
+ end.
+
+progress_dialog_new(Parent,Title,Str) ->
+ Dialog = wxDialog:new(Parent, ?wxID_ANY, Title,
+ [{style,?wxDEFAULT_DIALOG_STYLE}]),
+ Panel = wxPanel:new(Dialog),
+ Sizer = wxBoxSizer:new(?wxVERTICAL),
+ Message = wxStaticText:new(Panel, 1, Str,[{size,{220,-1}}]),
+ Gauge = wxGauge:new(Panel, 2, 100, [{style, ?wxGA_HORIZONTAL}]),
+ SizerFlags = ?wxEXPAND bor ?wxLEFT bor ?wxRIGHT bor ?wxTOP,
+ wxSizer:add(Sizer, Message, [{flag,SizerFlags},{border,15}]),
+ wxSizer:add(Sizer, Gauge, [{flag, SizerFlags bor ?wxBOTTOM},{border,15}]),
+ wxPanel:setSizer(Panel, Sizer),
+ wxSizer:setSizeHints(Sizer, Dialog),
+ wxDialog:show(Dialog),
+ {Dialog,Message,Gauge}.
+
+progress_dialog_update({_,_,Gauge},Value) when is_integer(Value) ->
+ wxGauge:setValue(Gauge,Value);
+progress_dialog_update({_,Message,Gauge},Text) when is_list(Text) ->
+ wxGauge:setValue(Gauge,0),
+ wxStaticText:setLabel(Message,Text).
+progress_dialog_pulse({_,_,Gauge}) ->
+ wxGauge:pulse(Gauge).
+progress_dialog_destroy({Dialog,_,_}) ->
+ wxDialog:destroy(Dialog).
+
+make_obsbin(Bin,Tab) ->
+ Size = byte_size(Bin),
+ {Preview,PreviewBitSize} =
+ try
+ %% The binary might be a unicode string, in which case we
+ %% don't want to split it in the middle of a grapheme
+ %% cluster - thus trying string:length and slice.
+ PL1 = min(string:length(Bin), 10),
+ PB1 = string:slice(Bin,0,PL1),
+ PS1 = byte_size(PB1) * 8,
+ <<P1:PS1>> = PB1,
+ {P1,PS1}
+ catch _:_ ->
+ %% Probably not a string, so just split anywhere
+ PS2 = min(Size, 10) * 8,
+ <<P2:PS2, _/binary>> = Bin,
+ {P2,PS2}
+ end,
+ Hash = erlang:phash2(Bin),
+ Key = {Preview, Size, Hash},
+ ets:insert(Tab, {Key,Bin}),
+ ['#OBSBin',Preview,PreviewBitSize,Size,Hash].
diff --git a/lib/observer/src/observer_perf_wx.erl b/lib/observer/src/observer_perf_wx.erl
index fcc51310c8..21c6d26f49 100644
--- a/lib/observer/src/observer_perf_wx.erl
+++ b/lib/observer/src/observer_perf_wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2012-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.
@@ -86,8 +86,8 @@ init([Notebook, Parent, Config]) ->
secs=maps:get(secs, Config, ?DISP_SECONDS)}
},
{Panel, State0}
- catch _:Err ->
- io:format("~p crashed ~p: ~p~n",[?MODULE, Err, erlang:get_stacktrace()]),
+ catch _:Err:Stacktrace ->
+ io:format("~p crashed ~tp: ~tp~n",[?MODULE, Err, Stacktrace]),
{stop, Err}
end.
@@ -235,7 +235,7 @@ handle_info({'EXIT', Old, _}, State = #state{appmon=Old}) ->
{noreply, State#state{active=false, appmon=undefined}};
handle_info(_Event, State) ->
- %% io:format("~p:~p: ~p~n",[?MODULE,?LINE,_Event]),
+ %% io:format("~p:~p: ~tp~n",[?MODULE,?LINE,_Event]),
{noreply, State}.
%%%%%%%%%%
diff --git a/lib/observer/src/observer_port_wx.erl b/lib/observer/src/observer_port_wx.erl
index 8339267659..445f3dd6b1 100644
--- a/lib/observer/src/observer_port_wx.erl
+++ b/lib/observer/src/observer_port_wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -242,6 +242,10 @@ handle_event(#wx{id=?ID_REFRESH_INTERVAL},
Timer = observer_lib:interval_dialog(Grid, Timer0, 10, 5*60),
{noreply, State#state{timer=Timer}};
+handle_event(#wx{obj=MoreEntry,event=#wxMouse{type=left_down},userData={more,More}}, State) ->
+ observer_lib:add_scroll_entries(MoreEntry,More),
+ {noreply, State};
+
handle_event(#wx{event=#wxMouse{type=left_down}, userData=TargetPid}, State) ->
observer ! {open_link, TargetPid},
{noreply, State};
@@ -338,7 +342,7 @@ handle_info({info, {port_info_not_available,NodeName}},
{noreply, State};
handle_info({error, Error}, #state{panel=Panel} = State) ->
- Str = io_lib:format("ERROR: ~s~n",[Error]),
+ Str = io_lib:format("ERROR: ~ts~n",[Error]),
observer_lib:display_info_dialog(Panel, Str),
{noreply, State};
diff --git a/lib/observer/src/observer_pro_wx.erl b/lib/observer/src/observer_pro_wx.erl
index 3083297f31..04e654a37e 100644
--- a/lib/observer/src/observer_pro_wx.erl
+++ b/lib/observer/src/observer_pro_wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@
handle_event/2, handle_cast/2]).
-include_lib("wx/include/wx.hrl").
--include("../include/etop.hrl").
+-include("etop.hrl").
-include("observer_defs.hrl").
-include("etop_defs.hrl").
@@ -50,6 +50,7 @@
-define(ID_TRACE_NEW, 208).
-define(ID_TRACE_ALL, 209).
-define(ID_ACCUMULATE, 210).
+-define(ID_GARBAGE_COLLECT, 211).
-define(TRACE_PIDS_STR, "Trace selected process identifiers").
-define(TRACE_NAMES_STR, "Trace selected processes, "
@@ -147,11 +148,11 @@ create_list_box(Panel, Holder) ->
ListCtrl = wxListCtrl:new(Panel, [{style, Style},
{onGetItemText,
fun(_, Row, Col) ->
- call(Holder, {get_row, self(), Row, Col})
+ safe_call(Holder, {get_row, self(), Row, Col})
end},
{onGetItemAttr,
fun(_, Item) ->
- call(Holder, {get_attr, self(), Item})
+ safe_call(Holder, {get_attr, self(), Item})
end}
]),
Li = wxListItem:new(),
@@ -208,17 +209,26 @@ start_procinfo(Pid, Frame, Opened) ->
Opened
end.
+
+safe_call(Holder, What) ->
+ case call(Holder, What, 2000) of
+ Res when is_atom(Res) -> "";
+ Res -> Res
+ end.
+
call(Holder, What) ->
+ call(Holder, What, infinity).
+
+call(Holder, What, TMO) ->
Ref = erlang:monitor(process, Holder),
Holder ! What,
receive
- {'DOWN', Ref, _, _, _} -> "";
+ {'DOWN', Ref, _, _, _} -> holder_dead;
{Holder, Res} ->
erlang:demonitor(Ref),
Res
- after 2000 ->
- io:format("Hanging call ~p~n",[What]),
- ""
+ after TMO ->
+ timeout
end.
%%%%%%%%%%%%%%%%%%%%%%% Callbacks %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -256,7 +266,7 @@ handle_info(not_active, #state{timer=Timer0}=State) ->
{noreply, State#state{timer=Timer}};
handle_info(Info, State) ->
- io:format("~p:~p, Unexpected info: ~p~n", [?MODULE, ?LINE, Info]),
+ io:format("~p:~p, Unexpected info: ~tp~n", [?MODULE, ?LINE, Info]),
{noreply, State}.
terminate(_Reason, #state{holder=Holder}) ->
@@ -269,15 +279,18 @@ code_change(_, _, State) ->
handle_call(get_config, _, #state{holder=Holder, timer=Timer}=State) ->
Conf = observer_lib:timer_config(Timer),
- Accum = call(Holder, {get_accum, self()}),
+ Accum = case safe_call(Holder, {get_accum, self()}) of
+ Bool when is_boolean(Bool) -> Bool;
+ _ -> false
+ end,
{reply, Conf#{acc=>Accum}, State};
handle_call(Msg, _From, State) ->
- io:format("~p:~p: Unhandled call ~p~n",[?MODULE, ?LINE, Msg]),
+ io:format("~p:~p: Unhandled call ~tp~n",[?MODULE, ?LINE, Msg]),
{reply, ok, State}.
handle_cast(Msg, State) ->
- io:format("~p:~p: Unhandled cast ~p~n", [?MODULE, ?LINE, Msg]),
+ io:format("~p:~p: Unhandled cast ~tp~n", [?MODULE, ?LINE, Msg]),
{noreply, State}.
%%%%%%%%%%%%%%%%%%%%LOOP%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -316,6 +329,9 @@ handle_event(#wx{id=?ID_KILL}, #state{right_clicked_pid=Pid, sel=Sel0}=State) ->
Sel = rm_selected(Pid,Sel0),
{noreply, State#state{sel=Sel}};
+handle_event(#wx{id=?ID_GARBAGE_COLLECT}, #state{sel={_, Pids}}=State) ->
+ _ = [rpc:call(node(Pid), erlang, garbage_collect, [Pid]) || Pid <- Pids],
+ {noreply, State};
handle_event(#wx{id=?ID_PROC},
#state{panel=Panel, right_clicked_pid=Pid, procinfo_menu_pids=Opened}=State) ->
@@ -370,6 +386,7 @@ handle_event(#wx{event=#wxList{type=command_list_item_right_click,
wxMenu:append(Menu, ?ID_TRACE_NAMES,
"Trace selected processes by name (all nodes)",
[{help, ?TRACE_NAMES_STR}]),
+ wxMenu:append(Menu, ?ID_GARBAGE_COLLECT, "Garbage collect processes"),
wxMenu:append(Menu, ?ID_KILL, "Kill process " ++ pid_to_list(P)),
wxWindow:popupMenu(Panel, Menu),
wxMenu:destroy(Menu),
@@ -401,7 +418,7 @@ handle_event(#wx{event=#wxList{type=command_list_item_activated}},
{noreply, State#state{procinfo_menu_pids=Opened2}};
handle_event(Event, State) ->
- io:format("~p:~p: handle event ~p\n", [?MODULE, ?LINE, Event]),
+ io:format("~p:~p: handle event ~tp\n", [?MODULE, ?LINE, Event]),
{noreply, State}.
@@ -465,7 +482,7 @@ init_table_holder(Parent, Accum0, Attrs) ->
Backend = spawn_link(node(), observer_backend, procs_info, [self()]),
Accum = case Accum0 of
true -> true;
- false -> []
+ _ -> []
end,
table_holder(#holder{parent=Parent,
info=array:new(),
@@ -559,7 +576,7 @@ table_holder(#holder{info=Info, attrs=Attrs,
%% Node crashed will be noticed soon..
table_holder(S0#holder{backend_pid=undefined});
_What ->
- %% io:format("~p: Table holder got ~p~n",[?MODULE, _What]),
+ %% io:format("~p: Table holder got ~tp~n",[?MODULE, _What]),
table_holder(S0)
end.
@@ -572,7 +589,8 @@ change_accum(true, S0) ->
S0#holder{accum=true};
change_accum(false, S0=#holder{info=Info}) ->
self() ! refresh,
- S0#holder{accum=lists:sort(array:to_list(Info))}.
+ Accum = [{Pid, Reds} || #etop_proc_info{pid=Pid, reds=Reds} <- array:to_list(Info)],
+ S0#holder{accum=lists:sort(Accum)}.
handle_update_old(#etop_info{procinfo=ProcInfo0},
S0=#holder{parent=Parent, sort=Sort=#sort{sort_key=KeyField}}) ->
diff --git a/lib/observer/src/observer_procinfo.erl b/lib/observer/src/observer_procinfo.erl
index 10decd8b62..f436886735 100644
--- a/lib/observer/src/observer_procinfo.erl
+++ b/lib/observer/src/observer_procinfo.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -56,7 +56,7 @@ init([Pid, ParentFrame, Parent]) ->
Table = ets:new(observer_expand,[set,public]),
Title=case observer_wx:try_rpc(node(Pid), erlang, process_info, [Pid, registered_name]) of
[] -> io_lib:format("~p",[Pid]);
- {registered_name, Registered} -> io_lib:format("~p (~p)",[Registered, Pid]);
+ {registered_name, Registered} -> io_lib:format("~tp (~p)",[Registered, Pid]);
undefined -> throw(process_undefined)
end,
Frame=wxFrame:new(ParentFrame, ?wxID_ANY, [atom_to_list(node(Pid)), $:, Title],
@@ -120,6 +120,10 @@ handle_event(#wx{id=?REFRESH}, #state{frame=Frame, pid=Pid, pages=Pages, expand_
end,
{noreply, State};
+handle_event(#wx{obj=MoreEntry,event=#wxMouse{type=left_down},userData={more,More}}, State) ->
+ observer_lib:add_scroll_entries(MoreEntry,More),
+ {noreply, State};
+
handle_event(#wx{event=#wxMouse{type=left_down}, userData=TargetPid}, State) ->
observer ! {open_link, TargetPid},
{noreply, State};
@@ -144,14 +148,14 @@ handle_event(#wx{event=#wxHtmlLink{linkInfo=#wxHtmlLinkInfo{href=Href}}},
observer ! {open_link, Href},
{noreply, State};
Callback ->
- [{"key1",Key1},{"key2",Key2},{"key3",Key3}] = httpd:parse_query(Rest),
+ [{"key1",Key1},{"key2",Key2},{"key3",Key3}] = uri_string:dissect_query(Rest),
Id = {obs, {T,{list_to_integer(Key1),
list_to_integer(Key2),
list_to_integer(Key3)}}},
Opened =
case lists:keyfind(Id,1,Opened0) of
false ->
- Win = cdv_detail_wx:start_link(Id,[],Frame,Callback),
+ Win = cdv_detail_wx:start_link(Id,[],Frame,Callback,obs),
[{Id,Win}|Opened0];
{_,Win} ->
wxFrame:raise(Win),
@@ -171,7 +175,7 @@ handle_info({get_debug_info, From}, State = #state{notebook=Notebook}) ->
From ! {procinfo_debug, Notebook},
{noreply, State};
handle_info(_Info, State) ->
- %% io:format("~p: ~p, Handle info: ~p~n", [?MODULE, ?LINE, Info]),
+ %% io:format("~p: ~p, Handle info: ~tp~n", [?MODULE, ?LINE, Info]),
{noreply, State}.
handle_call(Call, From, _State) ->
@@ -253,8 +257,6 @@ init_stack_page(Parent, Pid) ->
[Pid, current_stacktrace])
of
{current_stacktrace,RawBt} ->
- observer_wx:try_rpc(node(Pid), erlang, process_info,
- [Pid, current_stacktrace]),
wxListCtrl:deleteAllItems(LCtrl),
wx:foldl(fun({M, F, A, Info}, Row) ->
_Item = wxListCtrl:insertItem(LCtrl, Row, ""),
@@ -263,7 +265,7 @@ init_stack_page(Parent, Pid) ->
wxListCtrl:setItem(LCtrl, Row, 0, observer_lib:to_str({M,F,A})),
FileLine = case Info of
[{file,File},{line,Line}] ->
- io_lib:format("~s:~w", [File,Line]);
+ io_lib:format("~ts:~w", [File,Line]);
_ ->
[]
end,
@@ -454,7 +456,8 @@ local_pid_str(Pid) ->
global_pid_node_pref(Pid) ->
%% Global PID node prefix : X of <X.Y.Z>
- string:strip(string:sub_word(pid_to_list(Pid),1,$.),left,$<).
+ [NodePrefix|_] = string:lexemes(pid_to_list(Pid),"<."),
+ NodePrefix.
io_get_data(Pid) ->
Pid ! {self(), get_data_and_close},
@@ -487,5 +490,5 @@ io_request({put_chars, Encoding, Module, Function, Args}, State) ->
{error, {error, Function}, State}
end;
io_request(_Req, State) ->
- %% io:format("~p: Unknown req: ~p ~n",[?LINE, _Req]),
+ %% io:format("~p: Unknown req: ~tp ~n",[?LINE, _Req]),
{ok, {error, request}, State}.
diff --git a/lib/observer/src/observer_sys_wx.erl b/lib/observer/src/observer_sys_wx.erl
index db86c05bed..8c2ffd77b4 100644
--- a/lib/observer/src/observer_sys_wx.erl
+++ b/lib/observer/src/observer_sys_wx.erl
@@ -48,7 +48,7 @@ start_link(Notebook, Parent, Config) ->
init([Notebook, Parent, Config]) ->
SysInfo = observer_backend:sys_info(),
- {Sys, Mem, Cpu, Stats} = info_fields(),
+ {Sys, Mem, Cpu, Stats, Limits} = info_fields(),
Panel = wxPanel:new(Notebook),
Sizer = wxBoxSizer:new(?wxVERTICAL),
HSizer0 = wxBoxSizer:new(?wxHORIZONTAL),
@@ -63,17 +63,26 @@ init([Notebook, Parent, Config]) ->
wxSizer:add(HSizer1, FPanel2, [{flag, ?wxEXPAND}, {proportion, 1}]),
wxSizer:add(HSizer1, FPanel3, [{flag, ?wxEXPAND}, {proportion, 1}]),
+ HSizer2 = wxBoxSizer:new(?wxHORIZONTAL),
+ {FPanel4, _FSizer4, Fields4} = observer_lib:display_info(Panel, observer_lib:fill_info(Limits, SysInfo)),
+ wxSizer:add(HSizer2, FPanel4, [{flag, ?wxEXPAND}, {proportion, 1}]),
+
+
BorderFlags = ?wxLEFT bor ?wxRIGHT,
wxSizer:add(Sizer, HSizer0, [{flag, ?wxEXPAND bor BorderFlags bor ?wxTOP},
{proportion, 0}, {border, 5}]),
wxSizer:add(Sizer, HSizer1, [{flag, ?wxEXPAND bor BorderFlags bor ?wxBOTTOM},
{proportion, 0}, {border, 5}]),
+ wxSizer:add(Sizer, HSizer2, [{flag, ?wxEXPAND bor BorderFlags bor ?wxBOTTOM},
+ {proportion, 0}, {border, 5}]),
+
wxPanel:setSizer(Panel, Sizer),
Timer = observer_lib:start_timer(Config, 10),
{Panel, #sys_wx_state{parent=Parent,
parent_notebook=Notebook,
panel=Panel, sizer=Sizer,
- timer=Timer, fields=Fields0 ++ Fields1++Fields2++Fields3}}.
+ timer=Timer, fields=Fields0 ++ Fields1++Fields2++Fields3++Fields4}}.
+
create_sys_menu(Parent) ->
View = {"View", [#create_menu{id = ?ID_REFRESH, text = "Refresh\tCtrl-R"},
@@ -83,14 +92,40 @@ create_sys_menu(Parent) ->
update_syspage(#sys_wx_state{node = undefined}) -> ignore;
update_syspage(#sys_wx_state{node = Node, fields=Fields, sizer=Sizer}) ->
SysInfo = observer_wx:try_rpc(Node, observer_backend, sys_info, []),
- {Sys, Mem, Cpu, Stats} = info_fields(),
+ {Sys, Mem, Cpu, Stats, Limits} = info_fields(),
observer_lib:update_info(Fields,
observer_lib:fill_info(Sys, SysInfo) ++
observer_lib:fill_info(Mem, SysInfo) ++
observer_lib:fill_info(Cpu, SysInfo) ++
- observer_lib:fill_info(Stats, SysInfo)),
+ observer_lib:fill_info(Stats, SysInfo)++
+ observer_lib:fill_info(Limits, SysInfo)),
+
wxSizer:layout(Sizer).
+
+maybe_convert(undefined) -> "Not available";
+maybe_convert(V) -> observer_lib:to_str(V).
+
+get_dist_buf_busy_limit_info() ->
+ fun(Data) ->
+ maybe_convert(proplists:get_value(dist_buf_busy_limit, Data))
+ end.
+
+get_limit_count_info(Count, Limit) ->
+ fun(Data) ->
+ C = proplists:get_value(Count, Data),
+ L = proplists:get_value(Limit, Data),
+ lists:flatten(
+ io_lib:format("~s / ~s ~s",
+ [maybe_convert(C), maybe_convert(L),
+ if
+ C =:= undefined -> "";
+ L =:= undefined -> "";
+ true -> io_lib:format("(~s % used)",[observer_lib:to_str({trunc, (C / L) *100})])
+ end]))
+ end.
+
+
info_fields() ->
Sys = [{"System and Architecture",
[{"System Version", otp_release},
@@ -122,14 +157,20 @@ info_fields() ->
]}],
Stats = [{"Statistics", right,
[{"Up time", {time_ms, uptime}},
- {"Max Processes", process_limit},
- {"Processes", process_count},
{"Run Queue", run_queue},
{"IO Input", {bytes, io_input}},
{"IO Output", {bytes, io_output}}
]}
],
- {Sys, Mem, Cpu, Stats}.
+ Limits = [{"System statistics / limit",
+ [{"Atoms", get_limit_count_info(atom_count, atom_limit)},
+ {"Processes", get_limit_count_info(process_count, process_limit)},
+ {"Ports", get_limit_count_info(port_count, port_limit)},
+ {"ETS", get_limit_count_info(ets_count, ets_limit)},
+ {"Distribution buffer busy limit", get_dist_buf_busy_limit_info()}
+ ]}],
+ {Sys, Mem, Cpu, Stats, Limits}.
+
%%%%%%%%%%%%%%%%%%%%%%% Callbacks %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -158,7 +199,7 @@ handle_info(not_active, #sys_wx_state{timer = Timer} = State) ->
{noreply, State#sys_wx_state{timer = observer_lib:stop_timer(Timer)}};
handle_info(Info, State) ->
- io:format("~p:~p: Unhandled info: ~p~n", [?MODULE, ?LINE, Info]),
+ io:format("~p:~p: Unhandled info: ~tp~n", [?MODULE, ?LINE, Info]),
{noreply, State}.
terminate(_Reason, _State) ->
@@ -171,11 +212,11 @@ handle_call(get_config, _, #sys_wx_state{timer=Timer}=State) ->
{reply, observer_lib:timer_config(Timer), State};
handle_call(Msg, _From, State) ->
- io:format("~p~p: Unhandled Call ~p~n",[?MODULE, ?LINE, Msg]),
+ io:format("~p~p: Unhandled Call ~tp~n",[?MODULE, ?LINE, Msg]),
{reply, ok, State}.
handle_cast(Msg, State) ->
- io:format("~p~p: Unhandled cast ~p~n",[?MODULE, ?LINE, Msg]),
+ io:format("~p~p: Unhandled cast ~tp~n",[?MODULE, ?LINE, Msg]),
{noreply, State}.
handle_event(#wx{id = ?ID_REFRESH, event = #wxCommand{type = command_menu_selected}},
@@ -194,5 +235,5 @@ handle_event(#wx{id = ?ID_REFRESH_INTERVAL,
{noreply, State#sys_wx_state{timer=Timer}};
handle_event(Event, State) ->
- io:format("~p:~p: Unhandled event ~p\n", [?MODULE,?LINE,Event]),
+ io:format("~p:~p: Unhandled event ~tp\n", [?MODULE,?LINE,Event]),
{noreply, State}.
diff --git a/lib/observer/src/observer_trace_wx.erl b/lib/observer/src/observer_trace_wx.erl
index b960c61ff0..2c3b46a3a1 100644
--- a/lib/observer/src/observer_trace_wx.erl
+++ b/lib/observer/src/observer_trace_wx.erl
@@ -683,7 +683,7 @@ handle_event(#wx{id=?REMOVE_NODES}, #state{n_view=Nview, nodes=Ns0} = State) ->
{noreply, State#state{nodes = Ns}};
handle_event(#wx{id=ID, event = What}, State) ->
- io:format("~p:~p: Unhandled event: ~p, ~p ~n", [?MODULE, ?LINE, ID, What]),
+ io:format("~p:~p: Unhandled event: ~p, ~tp ~n", [?MODULE, ?LINE, ID, What]),
{noreply, State}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -729,7 +729,7 @@ handle_info({update_ms, NewMs}, State) ->
{noreply, State#state{match_specs=NewMs}};
handle_info(Any, State) ->
- io:format("~p~p: received unexpected message: ~p\n", [?MODULE, self(), Any]),
+ io:format("~p~p: received unexpected message: ~tp\n", [?MODULE, self(), Any]),
{noreply, State}.
terminate(_Reason, #state{nodes=_Nodes}) ->
@@ -1046,33 +1046,33 @@ format_trace(Trace, Size, TS0={_,_,MS}) ->
case element(4, Trace) of
{dbg,ok} -> "";
Message ->
- io_lib:format("~s (~100p) << ~100p~n", [TS,From,Message])
+ io_lib:format("~s (~100p) << ~100tp~n", [TS,From,Message])
end;
'send' ->
Message = element(4, Trace),
To = element(5, Trace),
- io_lib:format("~s (~100p) ~100p ! ~100p~n", [TS,From,To,Message]);
+ io_lib:format("~s (~100p) ~100p ! ~100tp~n", [TS,From,To,Message]);
call ->
case element(4, Trace) of
MFA when Size == 5 ->
Message = element(5, Trace),
- io_lib:format("~s (~100p) call ~s (~100p) ~n", [TS,From,ffunc(MFA),Message]);
+ io_lib:format("~s (~100p) call ~ts (~100tp) ~n", [TS,From,ffunc(MFA),Message]);
MFA ->
- io_lib:format("~s (~100p) call ~s~n", [TS,From,ffunc(MFA)])
+ io_lib:format("~s (~100p) call ~ts~n", [TS,From,ffunc(MFA)])
end;
return_from ->
MFA = element(4, Trace),
Ret = element(5, Trace),
- io_lib:format("~s (~100p) returned from ~s -> ~100p~n", [TS,From,ffunc(MFA),Ret]);
+ io_lib:format("~s (~100p) returned from ~ts -> ~100tp~n", [TS,From,ffunc(MFA),Ret]);
return_to ->
MFA = element(4, Trace),
- io_lib:format("~s (~100p) returning to ~s~n", [TS,From,ffunc(MFA)]);
+ io_lib:format("~s (~100p) returning to ~ts~n", [TS,From,ffunc(MFA)]);
spawn when Size == 5 ->
Pid = element(4, Trace),
MFA = element(5, Trace),
- io_lib:format("~s (~100p) spawn ~100p as ~s~n", [TS,From,Pid,ffunc(MFA)]);
+ io_lib:format("~s (~100p) spawn ~100p as ~ts~n", [TS,From,Pid,ffunc(MFA)]);
Op ->
- io_lib:format("~s (~100p) ~100p ~s~n", [TS,From,Op,ftup(Trace,4,Size)])
+ io_lib:format("~s (~100p) ~100p ~ts~n", [TS,From,Op,ftup(Trace,4,Size)])
end.
%%% These f* functions returns non-flat strings
@@ -1080,24 +1080,24 @@ format_trace(Trace, Size, TS0={_,_,MS}) ->
%% {M,F,[A1, A2, ..., AN]} -> "M:F(A1, A2, ..., AN)"
%% {M,F,A} -> "M:F/A"
ffunc({M,F,Argl}) when is_list(Argl) ->
- io_lib:format("~100p:~100p(~s)", [M, F, fargs(Argl)]);
+ io_lib:format("~100p:~100tp(~ts)", [M, F, fargs(Argl)]);
ffunc({M,F,Arity}) ->
- io_lib:format("~100p:~100p/~100p", [M,F,Arity]);
-ffunc(X) -> io_lib:format("~100p", [X]).
+ io_lib:format("~100p:~100tp/~100p", [M,F,Arity]);
+ffunc(X) -> io_lib:format("~100tp", [X]).
%% Integer -> "Integer"
%% [A1, A2, ..., AN] -> "A1, A2, ..., AN"
fargs(Arity) when is_integer(Arity) -> integer_to_list(Arity);
fargs([]) -> [];
-fargs([A]) -> io_lib:format("~100p", [A]); %% last arg
-fargs([A|Args]) -> [io_lib:format("~100p,", [A]) | fargs(Args)];
-fargs(A) -> io_lib:format("~100p", [A]). % last or only arg
+fargs([A]) -> io_lib:format("~100tp", [A]); %% last arg
+fargs([A|Args]) -> [io_lib:format("~100tp,", [A]) | fargs(Args)];
+fargs(A) -> io_lib:format("~100tp", [A]). % last or only arg
%% {A_1, A_2, ..., A_N} -> "A_Index A_Index+1 ... A_Size"
ftup(Trace, Index, Index) ->
- io_lib:format("~100p", [element(Index, Trace)]);
+ io_lib:format("~100tp", [element(Index, Trace)]);
ftup(Trace, Index, Size) ->
- [io_lib:format("~100p ", [element(Index, Trace)])
+ [io_lib:format("~100tp ", [element(Index, Trace)])
| ftup(Trace, Index+1, Size)].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1125,18 +1125,19 @@ get_config(#state{def_proc_flags = ProcFlags,
write_file(Frame, Filename, Config) ->
Str =
- ["%%%\n%%% This file is generated by Observer\n",
+ ["%%% ",epp:encoding_to_string(utf8), "\n"
+ "%%%\n%%% This file is generated by Observer\n",
"%%%\n%%% DO NOT EDIT!\n%%%\n",
- [io_lib:format("~p.~n",[MSTerm]) ||
+ [io_lib:format("~tp.~n",[MSTerm]) ||
MSTerm <- proplists:get_value(match_specs, Config)],
io_lib:format("~p.~n",[lists:keyfind(procflags, 1, Config)]),
io_lib:format("~p.~n",[lists:keyfind(portflags, 1, Config)]),
- io_lib:format("~p.~n",[lists:keyfind(output, 1, Config)]),
- [io_lib:format("~p.~n",[ModuleTerm]) ||
+ io_lib:format("~tp.~n",[lists:keyfind(output, 1, Config)]),
+ [io_lib:format("~tp.~n",[ModuleTerm]) ||
ModuleTerm <- proplists:get_value(trace_p, Config)]
],
- case file:write_file(Filename, list_to_binary(Str)) of
+ case file:write_file(Filename, unicode:characters_to_binary(Str)) of
ok ->
success;
{error, Reason} ->
@@ -1200,7 +1201,7 @@ make_ms(MS) ->
make_ms(Name,Term,FunStr).
make_ms(Name, Term, FunStr) ->
- #match_spec{name=Name, term=Term, str=io_lib:format("~w", Term), func = FunStr}.
+ #match_spec{name=Name, term=Term, str=io_lib:format("~tw", [Term]), func = FunStr}.
parse_tp({tp, Mod, FAs}, State) ->
Patterns = [#tpattern{m=Mod,fa={F,A}, ms=make_ms(List)} ||
diff --git a/lib/observer/src/observer_traceoptions_wx.erl b/lib/observer/src/observer_traceoptions_wx.erl
index 285c298c4b..ea292b92af 100644
--- a/lib/observer/src/observer_traceoptions_wx.erl
+++ b/lib/observer/src/observer_traceoptions_wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -487,7 +487,7 @@ edit_ms(TextCtrl, Label0, Parent) ->
_ -> Label0
end,
#match_spec{name=Label, term=MatchSpec,
- str=io_lib:format("~w",[MatchSpec]),
+ str=io_lib:format("~tw",[MatchSpec]),
func=Str}
catch
throw:cancel ->
@@ -511,18 +511,18 @@ ms_from_string(Str) ->
Tokens = case erl_scan:string(Str) of
{ok, Ts, _} -> Ts;
{error, {SLine, SMod, SError}, _} ->
- throw(io_lib:format("~w: ~s", [SLine,SMod:format_error(SError)]))
+ throw(io_lib:format("~w: ~ts", [SLine,SMod:format_error(SError)]))
end,
Exprs = case erl_parse:parse_exprs(Tokens) of
{ok, T} -> T;
{error, {PLine, PMod, PError}} ->
- throw(io_lib:format("~w: ~s", [PLine,PMod:format_error(PError)]))
+ throw(io_lib:format("~w: ~ts", [PLine,PMod:format_error(PError)]))
end,
Term = case Exprs of
[{'fun', _, {clauses, Clauses}}|_] ->
case ms_transform:transform_from_shell(dbg,Clauses,orddict:new()) of
{error, [{_,[{MSLine,Mod,MSInfo}]}],_} ->
- throw(io_lib:format("~w: ~p", [MSLine,Mod:format_error(MSInfo)]));
+ throw(io_lib:format("~w: ~tp", [MSLine,Mod:format_error(MSInfo)]));
{error, _} ->
throw("Could not convert fun() to match spec");
Ms ->
@@ -536,7 +536,7 @@ ms_from_string(Str) ->
{error, List} -> throw([[Error, $\n] || {_, Error} <- List])
end
catch error:_Reason ->
- %% io:format("Bad term: ~s~n ~p in ~p~n", [Str, _Reason, erlang:get_stacktrace()]),
+ %% io:format("Bad term: ~ts~n ~tp in ~tp~n", [Str, _Reason, Stacktrace]),
throw("Invalid term")
end.
@@ -556,7 +556,8 @@ filter_listbox_data(Input, Data, ListBox) ->
filter_listbox_data(Input, Data, ListBox, true).
filter_listbox_data(Input, Data, ListBox, AddClientData) ->
- FilteredData = [X || X = {Str, _} <- Data, re:run(Str, Input) =/= nomatch],
+ FilteredData = [X || X = {Str, _} <- Data,
+ re:run(Str, Input, [unicode]) =/= nomatch],
wxListBox:clear(ListBox),
wxListBox:appendStrings(ListBox, [Str || {Str,_} <- FilteredData]),
AddClientData andalso
@@ -618,7 +619,7 @@ create_styled_txtctrl(Parent) ->
keyWords() ->
L = ["after","begin","case","try","cond","catch","andalso","orelse",
- "end","fun","if","let","of","query","receive","when","bnot","not",
+ "end","fun","if","let","of","receive","when","bnot","not",
"div","rem","band","and","bor","bxor","bsl","bsr","or","xor"],
lists:flatten([K ++ " " || K <- L] ++ [0]).
@@ -648,9 +649,9 @@ parse_function_names(Choices) ->
parse_function_names([], Acc) ->
lists:reverse(Acc);
parse_function_names([{H, Term}|T], Acc) ->
- IsFun = re:run(H, ".*-fun-\\d*?-"),
- IsLc = re:run(H, ".*-lc\\$\\^\\d*?/\\d*?-\\d*?-"),
- IsLbc = re:run(H, ".*-lbc\\$\\^\\d*?/\\d*?-\\d*?-"),
+ IsFun = re:run(H, ".*-fun-\\d*?-", [unicode,ucp]),
+ IsLc = re:run(H, ".*-lc\\$\\^\\d*?/\\d*?-\\d*?-", [unicode,ucp]),
+ IsLbc = re:run(H, ".*-lbc\\$\\^\\d*?/\\d*?-\\d*?-", [unicode,ucp]),
Parsed =
if IsFun =/= nomatch -> "Fun: " ++ H;
IsLc =/= nomatch -> "List comprehension: " ++ H;
diff --git a/lib/observer/src/observer_tv_table.erl b/lib/observer/src/observer_tv_table.erl
index 789e060cfb..d6dcee2cda 100644
--- a/lib/observer/src/observer_tv_table.erl
+++ b/lib/observer/src/observer_tv_table.erl
@@ -258,7 +258,7 @@ handle_event(#wx{event=#wxList{type=command_list_item_selected, itemIndex=Index}
State = #state{pid=Pid, grid=Grid, status=StatusBar}) ->
N = wxListCtrl:getItemCount(Grid),
Str = get_row(Pid, Index, all),
- wxStatusBar:setStatusText(StatusBar, io_lib:format("Objects: ~w: ~s",[N, Str])),
+ wxStatusBar:setStatusText(StatusBar, io_lib:format("Objects: ~w: ~ts",[N, Str])),
{noreply, State#state{selected=Index}};
handle_event(#wx{event=#wxList{type=command_list_item_activated, itemIndex=Index}},
@@ -278,7 +278,7 @@ handle_event(#wx{id=?ID_DELETE},
State = #state{grid=Grid, pid=Pid, status=StatusBar, selected=Index}) ->
Str = get_row(Pid, Index, all),
Pid ! {delete, Index},
- wxStatusBar:setStatusText(StatusBar, io_lib:format("Deleted object: ~s",[Str])),
+ wxStatusBar:setStatusText(StatusBar, io_lib:format("Deleted object: ~ts",[Str])),
wxListCtrl:setItemState(Grid, Index, 0, ?wxLIST_STATE_FOCUSED),
{noreply, State#state{selected=undefined}};
@@ -338,7 +338,7 @@ handle_event(#wx{id=?SEARCH_ENTRY, event=#wxCommand{type=command_text_enter,cmdS
Pid ! {mark_search_hit, false},
case search(Pid, Str, Pos, Dir, Case) of
false ->
- wxStatusBar:setStatusText(SB, io_lib:format("Not found (regexp): ~s",[Str])),
+ wxStatusBar:setStatusText(SB, io_lib:format("Not found (regexp): ~ts",[Str])),
Pid ! {mark_search_hit, Find#find.start},
wxListCtrl:refreshItem(Grid, Find#find.start),
{noreply, State#state{search=Search#search{find=Find#find{found=false}}}};
@@ -372,7 +372,7 @@ handle_event(#wx{id=?SEARCH_ENTRY, event=#wxCommand{cmdString=Str}},
Pid ! {mark_search_hit, false},
case search(Pid, Str, Cont#find.start, Dir, Case) of
false ->
- wxStatusBar:setStatusText(SB, io_lib:format("Not found (regexp): ~s",[Str])),
+ wxStatusBar:setStatusText(SB, io_lib:format("Not found (regexp): ~ts",[Str])),
{noreply, State};
Row ->
wxListCtrl:ensureVisible(Grid, Row),
@@ -395,19 +395,19 @@ handle_event(#wx{id=?ID_REFRESH_INTERVAL},
{noreply, State#state{timer=Timer}};
handle_event(_Event, State) ->
- %io:format("~p:~p, handle event ~p\n", [?MODULE, ?LINE, Event]),
+ %io:format("~p:~p, handle event ~tp\n", [?MODULE, ?LINE, Event]),
{noreply, State}.
handle_sync_event(_Event, _Obj, _State) ->
- %io:format("~p:~p, handle sync_event ~p\n", [?MODULE, ?LINE, Event]),
+ %io:format("~p:~p, handle sync_event ~tp\n", [?MODULE, ?LINE, Event]),
ok.
handle_call(_Event, _From, State) ->
- %io:format("~p:~p, handle call (~p) ~p\n", [?MODULE, ?LINE, From, Event]),
+ %io:format("~p:~p, handle call (~p) ~tp\n", [?MODULE, ?LINE, From, Event]),
{noreply, State}.
handle_cast(_Event, State) ->
- %io:format("~p:~p, handle cast ~p\n", [?MODULE, ?LINE, Event]),
+ %io:format("~p:~p, handle cast ~tp\n", [?MODULE, ?LINE, Event]),
{noreply, State}.
handle_info({no_rows, N}, State = #state{grid=Grid, status=StatusBar}) ->
@@ -433,7 +433,7 @@ handle_info(refresh_interval, State = #state{pid=Pid}) ->
handle_info({error, Error}, State = #state{frame=Frame}) ->
ErrorStr =
try io_lib:format("~ts", [Error]), Error
- catch _:_ -> io_lib:format("~p", [Error])
+ catch _:_ -> io_lib:format("~tp", [Error])
end,
Dlg = wxMessageDialog:new(Frame, ErrorStr),
wxMessageDialog:showModal(Dlg),
@@ -441,7 +441,7 @@ handle_info({error, Error}, State = #state{frame=Frame}) ->
{noreply, State};
handle_info(_Event, State) ->
- %% io:format("~p:~p, handle info ~p\n", [?MODULE, ?LINE, _Event]),
+ %% io:format("~p:~p, handle info ~tp\n", [?MODULE, ?LINE, _Event]),
{noreply, State}.
terminate(_Event, #state{pid=Pid, attrs=Attrs}) ->
@@ -554,7 +554,7 @@ table_holder(S0 = #holder{parent=Parent, pid=Pid, table=Table}) ->
edit_row(Row, Term, S0),
table_holder(S0);
What ->
- io:format("Table holder got ~p~n",[What]),
+ io:format("Table holder got ~tp~n",[What]),
Parent ! {refresh, 0, S0#holder.n-1},
table_holder(S0)
end.
@@ -641,7 +641,7 @@ search([Str, Row, Dir0, CaseSens],
true -> 1;
false -> -1
end,
- Res = case re:compile(Str, Opt) of
+ Res = case re:compile(Str, [unicode|Opt]) of
{ok, Re} -> re_search(Row, Dir, N, Re, Table);
{error, _} -> false
end,
@@ -665,7 +665,7 @@ get_row(From, Row, Col, Table) ->
[Object|_] when Col =:= all ->
From ! {self(), format(Object)};
[Object|_] when Col =:= all_multiline ->
- From ! {self(), io_lib:format("~p", [Object])};
+ From ! {self(), io_lib:format("~tp", [Object])};
[Object|_] when Col =:= term ->
From ! {self(), Object};
[Object|_] when tuple_size(Object) >= Col ->
@@ -801,7 +801,7 @@ format(Bin) when is_binary(Bin), byte_size(Bin) > 100 ->
io_lib:format("<<#Bin:~w>>", [byte_size(Bin)]);
format(Bin) when is_binary(Bin) ->
try
- true = printable_list(unicode:characters_to_list(Bin)),
+ true = io_lib:printable_list(unicode:characters_to_list(Bin)),
io_lib:format("<<\"~ts\">>", [Bin])
catch _:_ ->
io_lib:format("~w", [Bin])
@@ -809,7 +809,7 @@ format(Bin) when is_binary(Bin) ->
format(Float) when is_float(Float) ->
io_lib:format("~.3g", [Float]);
format(Term) ->
- io_lib:format("~w", [Term]).
+ io_lib:format("~tw", [Term]).
format_tuple(Tuple, I, Max) when I < Max ->
[format(element(I, Tuple)), $,|format_tuple(Tuple, I+1, Max)];
@@ -820,7 +820,7 @@ format_tuple(_Tuple, 1, 0) ->
format_list([]) -> "[]";
format_list(List) ->
- case printable_list(List) of
+ case io_lib:printable_list(List) of
true -> io_lib:format("\"~ts\"", [map_printable_list(List)]);
false -> [$[ | make_list(List)]
end.
@@ -849,26 +849,3 @@ map_printable_list([$\e|Cs]) ->
map_printable_list([]) -> [];
map_printable_list([C|Cs]) ->
[C|map_printable_list(Cs)].
-
-%% printable_list([Char]) -> bool()
-%% Return true if CharList is a list of printable characters, else
-%% false.
-
-printable_list([C|Cs]) when is_integer(C), C >= $ , C =< 255 ->
- printable_list(Cs);
-printable_list([$\n|Cs]) ->
- printable_list(Cs);
-printable_list([$\r|Cs]) ->
- printable_list(Cs);
-printable_list([$\t|Cs]) ->
- printable_list(Cs);
-printable_list([$\v|Cs]) ->
- printable_list(Cs);
-printable_list([$\b|Cs]) ->
- printable_list(Cs);
-printable_list([$\f|Cs]) ->
- printable_list(Cs);
-printable_list([$\e|Cs]) ->
- printable_list(Cs);
-printable_list([]) -> true;
-printable_list(_Other) -> false. %Everything else is false
diff --git a/lib/observer/src/observer_tv_wx.erl b/lib/observer/src/observer_tv_wx.erl
index 9564bdfa1c..814f3a1260 100644
--- a/lib/observer/src/observer_tv_wx.erl
+++ b/lib/observer/src/observer_tv_wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -38,13 +38,13 @@
-define(ID_SYSTEM_TABLES, 406).
-define(ID_TABLE_INFO, 407).
-define(ID_SHOW_TABLE, 408).
-
--record(opt, {type=ets,
- sys_hidden=true,
- unread_hidden=true,
- sort_key=2,
- sort_incr=true
- }).
+
+-record(opts, {type=ets,
+ sys_hidden=true,
+ unread_hidden=true}).
+
+-record(sort, {sort_incr=true,
+ sort_key=2}).
-record(state,
{
@@ -52,9 +52,9 @@
grid,
panel,
node=node(),
- opt=#opt{},
+ opts=#opts{},
+ holder,
selected,
- tabs,
timer
}).
@@ -64,8 +64,18 @@ start_link(Notebook, Parent, Config) ->
init([Notebook, Parent, Config]) ->
Panel = wxPanel:new(Notebook),
Sizer = wxBoxSizer:new(?wxVERTICAL),
- Style = ?wxLC_REPORT bor ?wxLC_SINGLE_SEL bor ?wxLC_HRULES,
- Grid = wxListCtrl:new(Panel, [{winid, ?GRID}, {style, Style}]),
+
+ Opts=#opts{type=maps:get(type, Config, ets),
+ sys_hidden=maps:get(sys_hidden, Config, true),
+ unread_hidden=maps:get(unread_hidden, Config, true)},
+
+ Style = ?wxLC_REPORT bor ?wxLC_VIRTUAL bor ?wxLC_SINGLE_SEL bor ?wxLC_HRULES,
+ Self = self(),
+ Attrs = observer_lib:create_attrs(),
+ 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}],
+ Grid = wxListCtrl:new(Panel, [{winid, ?GRID}, {style, Style} | CBs]),
wxSizer:add(Sizer, Grid, [{flag, ?wxEXPAND bor ?wxALL},
{proportion, 1}, {border, 5}]),
wxWindow:setSizer(Panel, Sizer),
@@ -95,38 +105,26 @@ init([Notebook, Parent, Config]) ->
wxWindow:setFocus(Grid),
{Panel, #state{grid=Grid, parent=Parent, panel=Panel,
- timer=Config,
- opt=#opt{type=maps:get(type, Config, ets),
- sys_hidden=maps:get(sys_hidden, Config, true),
- unread_hidden=maps:get(unread_hidden, Config, true)}
- }}.
+ opts=Opts, timer=Config, holder=Holder}}.
handle_event(#wx{id=?ID_REFRESH},
- State = #state{node=Node, grid=Grid, opt=Opt}) ->
- Tables = get_tables(Node, Opt),
- {Tabs,Sel} = update_grid(Grid, sel(State), Opt, Tables),
- Sel =/= undefined andalso wxListCtrl:ensureVisible(Grid, Sel),
- {noreply, State#state{tabs=Tabs, selected=Sel}};
+ State = #state{holder=Holder, node=Node, opts=Opts}) ->
+ Tables = get_tables(Node, Opts),
+ Holder ! {refresh, Tables},
+ {noreply, State};
handle_event(#wx{event=#wxList{type=command_list_col_click, col=Col}},
- State = #state{node=Node, grid=Grid,
- opt=Opt0=#opt{sort_key=Key, sort_incr=Bool}}) ->
- Opt = case col2key(Col) of
- Key -> Opt0#opt{sort_incr=not Bool};
- NewKey -> Opt0#opt{sort_key=NewKey}
- end,
- Tables = get_tables(Node, Opt),
- {Tabs,Sel} = update_grid(Grid, sel(State), Opt, Tables),
- wxWindow:setFocus(Grid),
- {noreply, State#state{opt=Opt, tabs=Tabs, selected=Sel}};
+ State = #state{holder=Holder}) ->
+ Holder ! {sort, Col},
+ {noreply, State};
-handle_event(#wx{id=Id}, State = #state{node=Node, grid=Grid, opt=Opt0})
+handle_event(#wx{id=Id}, State = #state{node=Node, holder=Holder, grid=Grid, opts=Opt0})
when Id >= ?ID_ETS, Id =< ?ID_SYSTEM_TABLES ->
Opt = case Id of
- ?ID_ETS -> Opt0#opt{type=ets};
- ?ID_MNESIA -> Opt0#opt{type=mnesia};
- ?ID_UNREADABLE -> Opt0#opt{unread_hidden= not Opt0#opt.unread_hidden};
- ?ID_SYSTEM_TABLES -> Opt0#opt{sys_hidden= not Opt0#opt.sys_hidden}
+ ?ID_ETS -> Opt0#opts{type=ets};
+ ?ID_MNESIA -> Opt0#opts{type=mnesia};
+ ?ID_UNREADABLE -> Opt0#opts{unread_hidden= not Opt0#opts.unread_hidden};
+ ?ID_SYSTEM_TABLES -> Opt0#opts{sys_hidden= not Opt0#opts.sys_hidden}
end,
case get_tables2(Node, Opt) of
Error = {error, _} ->
@@ -135,9 +133,9 @@ handle_event(#wx{id=Id}, State = #state{node=Node, grid=Grid, opt=Opt0})
self() ! Error,
{noreply, State};
Tables ->
- {Tabs, Sel} = update_grid(Grid, sel(State), Opt, Tables),
+ Holder ! {refresh, Tables},
wxWindow:setFocus(Grid),
- {noreply, State#state{opt=Opt, tabs=Tabs, selected=Sel}}
+ {noreply, State#state{opts=Opt}}
end;
handle_event(#wx{event=#wxSize{size={W,_}}}, State=#state{grid=Grid}) ->
@@ -146,19 +144,18 @@ handle_event(#wx{event=#wxSize{size={W,_}}}, State=#state{grid=Grid}) ->
handle_event(#wx{event=#wxList{type=command_list_item_activated,
itemIndex=Index}},
- State=#state{grid=Grid, node=Node, opt=#opt{type=Type}, tabs=Tabs}) ->
- Table = lists:nth(Index+1, Tabs),
- case Table#tab.protection of
- private ->
- self() ! {error, "Table has 'private' protection and can not be read"};
- _ ->
- observer_tv_table:start_link(Grid, [{node,Node}, {type,Type}, {table,Table}])
+ State=#state{holder=Holder, node=Node, opts=#opts{type=Type}, grid=Grid}) ->
+ case get_table(Holder, Index) of
+ #tab{protection=private} ->
+ self() ! {error, "Table has 'private' protection and can not be read"};
+ #tab{}=Table ->
+ observer_tv_table:start_link(Grid, [{node,Node}, {type,Type}, {table,Table}]);
+ _ -> ignore
end,
{noreply, State};
handle_event(#wx{event=#wxList{type=command_list_item_right_click}},
State=#state{panel=Panel}) ->
-
Menu = wxMenu:new(),
wxMenu:append(Menu, ?ID_TABLE_INFO, "Table info"),
wxMenu:append(Menu, ?ID_SHOW_TABLE, "Show Table Content"),
@@ -167,32 +164,33 @@ handle_event(#wx{event=#wxList{type=command_list_item_right_click}},
{noreply, State};
handle_event(#wx{event=#wxList{type=command_list_item_selected, itemIndex=Index}},
- State) ->
+ State=#state{holder=Holder}) ->
+ Holder ! {selected, Index},
{noreply, State#state{selected=Index}};
handle_event(#wx{id=?ID_TABLE_INFO},
- State = #state{grid=Grid, node=Node, opt=#opt{type=Type}, tabs=Tabs, selected=Sel}) ->
+ State = #state{holder=Holder, grid=Grid, node=Node, opts=#opts{type=Type}, selected=Sel}) ->
case Sel of
undefined ->
{noreply, State};
R when is_integer(R) ->
- Table = lists:nth(Sel+1, Tabs),
+ Table = get_table(Holder, Sel),
display_table_info(Grid, Node, Type, Table),
{noreply, State}
end;
handle_event(#wx{id=?ID_SHOW_TABLE},
- State=#state{grid=Grid, node=Node, opt=#opt{type=Type}, tabs=Tabs, selected=Sel}) ->
+ State=#state{holder=Holder, grid=Grid, node=Node, opts=#opts{type=Type}, selected=Sel}) ->
case Sel of
undefined ->
{noreply, State};
R when is_integer(R) ->
- Table = lists:nth(Sel+1, Tabs),
- case Table#tab.protection of
- private ->
+ case get_table(Holder, R) of
+ #tab{protection=private} ->
self() ! {error, "Table has 'private' protection and can not be read"};
- _ ->
- observer_tv_table:start_link(Grid, [{node,Node}, {type,Type}, {table,Table}])
+ #tab{}=Table ->
+ observer_tv_table:start_link(Grid, [{node,Node}, {type,Type}, {table,Table}]);
+ _ -> ignore
end,
{noreply, State}
end;
@@ -202,14 +200,14 @@ handle_event(#wx{id=?ID_REFRESH_INTERVAL},
Timer = observer_lib:interval_dialog(Grid, Timer0, 10, 5*60),
{noreply, State#state{timer=Timer}};
-handle_event(Event, _State) ->
- error({unhandled_event, Event}).
+handle_event(_Event, State) ->
+ {noreply, State}.
handle_sync_event(_Event, _Obj, _State) ->
ok.
-handle_call(get_config, _, #state{timer=Timer, opt=Opt}=State) ->
- #opt{type=Type, sys_hidden=Sys, unread_hidden=Unread} = Opt,
+handle_call(get_config, _, #state{timer=Timer, opts=Opt}=State) ->
+ #opts{type=Type, sys_hidden=Sys, unread_hidden=Unread} = Opt,
Conf0 = observer_lib:timer_config(Timer),
Conf = Conf0#{type=>Type, sys_hidden=>Sys, unread_hidden=>Unread},
{reply, Conf, State};
@@ -220,50 +218,68 @@ handle_call(Event, From, _State) ->
handle_cast(Event, _State) ->
error({unhandled_cast, Event}).
-handle_info(refresh_interval, State = #state{node=Node, grid=Grid, opt=Opt,
- tabs=OldTabs}) ->
- case get_tables(Node, Opt) of
- OldTabs ->
- %% no change
- {noreply, State};
- Tables ->
- {Tabs, Sel} = update_grid(Grid, sel(State), Opt, Tables),
- Sel =/= undefined andalso wxListCtrl:ensureVisible(Grid, Sel),
- {noreply, State#state{tabs=Tabs, selected=Sel}}
- end;
+handle_info(refresh_interval, State = #state{holder=Holder, node=Node, opts=Opt}) ->
+ Tables = get_tables(Node, Opt),
+ Holder ! {refresh, Tables},
+ {noreply, State};
-handle_info({active, Node}, State = #state{parent=Parent, grid=Grid, opt=Opt0,
- timer=Timer0}) ->
- {Tables, Opt} = case Opt0#opt.type =:= mnesia andalso get_tables2(Node, Opt0) of
+handle_info({active, Node}, State = #state{parent=Parent, holder=Holder, grid=Grid,
+ opts=Opt0, timer=Timer0}) ->
+ {Tables, Opt} = case Opt0#opts.type =:= mnesia andalso get_tables2(Node, Opt0) of
Ts when is_list(Ts) ->
{Ts, Opt0};
_ -> % false or error getting mnesia tables
- Opt1 = Opt0#opt{type=ets},
+ Opt1 = Opt0#opts{type=ets},
{get_tables(Node, Opt1), Opt1}
end,
- {Tabs,Sel} = update_grid(Grid, sel(State), Opt, Tables),
+ Holder ! {refresh, Tables},
wxWindow:setFocus(Grid),
create_menus(Parent, Opt),
Timer = observer_lib:start_timer(Timer0, 10),
- {noreply, State#state{node=Node, tabs=Tabs, timer=Timer, opt=Opt, selected=Sel}};
+ {noreply, State#state{node=Node, timer=Timer, opts=Opt}};
handle_info(not_active, State = #state{timer = Timer0}) ->
Timer = observer_lib:stop_timer(Timer0),
{noreply, State#state{timer=Timer}};
-handle_info({error, Error}, #state{panel=Panel,opt=Opt}=State) ->
- Str = io_lib:format("ERROR: ~s~n",[Error]),
+handle_info({error, Error}, #state{panel=Panel,opts=Opt}=State) ->
+ Str = io_lib:format("ERROR: ~ts~n",[Error]),
observer_lib:display_info_dialog(Panel,Str),
- case Opt#opt.type of
+ case Opt#opts.type of
mnesia -> wxMenuBar:check(observer_wx:get_menubar(), ?ID_ETS, true);
_ -> ok
end,
- {noreply, State#state{opt=Opt#opt{type=ets}}};
+ {noreply, State#state{opts=Opt#opts{type=ets}}};
+
+handle_info({refresh, Min, Min}, State = #state{grid=Grid}) ->
+ wxListCtrl:setItemCount(Grid, Min+1),
+ wxListCtrl:refreshItem(Grid, Min), %% Avoid assert in wx below if Max is 0
+ observer_wx:set_status(io_lib:format("Tables: ~w", [Min+1])),
+ {noreply, State};
+handle_info({refresh, Min, Max}, State = #state{grid=Grid}) ->
+ wxListCtrl:setItemCount(Grid, Max+1),
+ Max > 0 andalso wxListCtrl:refreshItems(Grid, Min, Max),
+ observer_wx:set_status(io_lib:format("Tables: ~w", [Max+1])),
+ {noreply, State};
+
+handle_info({selected, New, Size}, #state{grid=Grid, selected=Old} = State) ->
+ if
+ is_integer(Old), Old < Size ->
+ wxListCtrl:setItemState(Grid, Old, 0, ?wxLIST_STATE_SELECTED);
+ true -> ignore
+ end,
+ if is_integer(New) ->
+ wxListCtrl:setItemState(Grid, New, 16#FFFF, ?wxLIST_STATE_SELECTED),
+ wxListCtrl:ensureVisible(Grid, New);
+ true -> ignore
+ end,
+ {noreply, State#state{selected=New}};
handle_info(_Event, State) ->
{noreply, State}.
-terminate(_Event, _State) ->
+terminate(_Event, #state{holder=Holder}) ->
+ Holder ! stop,
ok.
code_change(_, _, State) ->
@@ -271,7 +287,7 @@ code_change(_, _, State) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-create_menus(Parent, #opt{sys_hidden=Sys, unread_hidden=UnR, type=Type}) ->
+create_menus(Parent, #opts{sys_hidden=Sys, unread_hidden=UnR, type=Type}) ->
MenuEntries = [{"View",
[#create_menu{id = ?ID_TABLE_INFO, text = "Table information\tCtrl-I"},
separator,
@@ -298,7 +314,7 @@ get_tables(Node, Opts) ->
Res ->
Res
end.
-get_tables2(Node, #opt{type=Type, sys_hidden=Sys, unread_hidden=Unread}) ->
+get_tables2(Node, #opts{type=Type, sys_hidden=Sys, unread_hidden=Unread}) ->
Args = [Type, [{sys_hidden,Sys}, {unread_hidden,Unread}]],
case rpc:call(Node, observer_backend, get_table_list, Args) of
{badrpc, Error} ->
@@ -386,49 +402,134 @@ list_to_strings([A]) -> integer_to_list(A);
list_to_strings([A|B]) ->
integer_to_list(A) ++ " ," ++ list_to_strings(B).
-update_grid(Grid, Selected, Opt, Tables) ->
- wx:batch(fun() -> update_grid2(Grid, Selected, Opt, Tables) end).
-
-update_grid2(Grid, {SelName,SelId}, #opt{sort_key=Sort,sort_incr=Dir}, Tables) ->
- wxListCtrl:deleteAllItems(Grid),
- Update =
- fun(#tab{name = Name, id = Id, owner = Owner, size = Size, memory = Memory,
- protection = Protection, reg_name = RegName},
- {Row, Sel}) ->
- _Item = wxListCtrl:insertItem(Grid, Row, ""),
- if (Row rem 2) =:= 0 ->
- wxListCtrl:setItemBackgroundColour(Grid, Row, ?BG_EVEN);
- true -> ignore
- end,
- if Protection == private ->
- wxListCtrl:setItemTextColour(Grid, Row, {200,130,50});
- true -> ignore
- end,
-
- lists:foreach(fun({_, ignore}) -> ignore;
- ({Col, Val}) ->
- wxListCtrl:setItem(Grid, Row, Col, observer_lib:to_str(Val))
- end,
- [{0,Name}, {1,Size}, {2, Memory div 1024},
- {3,Owner}, {4,RegName}, {5,Id}]),
- if SelName =:= Name, SelId =:= Id ->
- wxListCtrl:setItemState(Grid, Row, 16#FFFF, ?wxLIST_STATE_SELECTED),
- {Row+1, Row};
- true ->
- wxListCtrl:setItemState(Grid, Row, 0, ?wxLIST_STATE_SELECTED),
- {Row+1, Sel}
- end
- end,
- ProcInfo = case Dir of
- false -> lists:reverse(lists:keysort(Sort, Tables));
- true -> lists:keysort(Sort, Tables)
- end,
- {_, Sel} = lists:foldl(Update, {0, undefined}, ProcInfo),
- {ProcInfo, Sel}.
-
-sel(#state{selected=Sel, tabs=Tabs}) ->
- try lists:nth(Sel+1, Tabs) of
- #tab{name=Name, id=Id} -> {Name, Id}
- catch _:_ ->
- {undefined, undefined}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Table holder needs to be in a separate process otherwise
+%% the callback get_row/3 may deadlock if the process do
+%% wx calls when callback is invoked.
+
+get_table(Table, Item) ->
+ get_row(Table, Item, all).
+
+get_row(Table, Item, Column) ->
+ Ref = erlang:monitor(process, Table),
+ Table ! {get_row, self(), Item, Column},
+ receive
+ {'DOWN', Ref, _, _, _} -> "";
+ {Table, Res} ->
+ erlang:demonitor(Ref),
+ Res
end.
+
+get_attr(Table, Item) ->
+ Ref = erlang:monitor(process, Table),
+ Table ! {get_attr, self(), Item},
+ receive
+ {'DOWN', Ref, _, _, _} -> wx:null();
+ {Table, Res} ->
+ erlang:demonitor(Ref),
+ Res
+ end.
+
+-record(holder, {node, parent, pid,
+ tabs=array:new(),
+ sort=#sort{},
+ attrs,
+ sel
+ }).
+
+init_table_holder(Parent, Attrs) ->
+ Parent ! refresh,
+ table_holder(#holder{node=node(), parent=Parent, attrs=Attrs}).
+
+table_holder(S0 = #holder{parent=Parent, tabs=Tabs0, sel=Sel0}) ->
+ receive
+ {get_attr, From, Row} ->
+ get_attr(From, Row, S0),
+ table_holder(S0);
+ {get_row, From, Row, Col} ->
+ get_row(From, Row, Col, Tabs0),
+ table_holder(S0);
+ {sort, Col} ->
+ STab = get_sel(Sel0, Tabs0),
+ Parent ! {refresh, 0, array:size(Tabs0)-1},
+ S1 = sort(col2key(Col), S0),
+ Sel = sel_idx(STab, S1#holder.tabs),
+ Parent ! {selected, Sel, array:size(Tabs0)},
+ table_holder(S1#holder{sel=Sel});
+ {refresh, Tabs1} ->
+ STab = get_sel(Sel0, Tabs0),
+ Tabs = case S0#holder.sort of
+ #sort{sort_incr=false, sort_key=Col} ->
+ array:from_list(lists:reverse(lists:keysort(Col, Tabs1)));
+ #sort{sort_key=Col} ->
+ array:from_list(lists:keysort(Col, Tabs1))
+ end,
+ Parent ! {refresh, 0, array:size(Tabs)-1},
+ Sel = sel_idx(STab, Tabs),
+ Parent ! {selected, Sel,array:size(Tabs)},
+ table_holder(S0#holder{tabs=Tabs, sel=Sel});
+ {selected, Sel} ->
+ table_holder(S0#holder{sel=Sel});
+ stop ->
+ ok;
+ What ->
+ io:format("Table holder got ~tp~n",[What]),
+ Parent ! {refresh, 0, array:size(Tabs0)-1},
+ table_holder(S0)
+ end.
+
+get_sel(undefined, _Tabs) ->
+ undefined;
+get_sel(Idx, Tabs) ->
+ array:get(Idx, Tabs).
+
+sel_idx(undefined, _Tabs) ->
+ undefined;
+sel_idx(Tab, Tabs) ->
+ Find = fun(Idx, C, Acc) -> C =:= Tab andalso throw({found, Idx}), Acc end,
+ try array:foldl(Find, undefined, Tabs)
+ catch {found, Idx} -> Idx
+ end.
+
+sort(Col, #holder{sort=#sort{sort_key=Col, sort_incr=Incr}=S, tabs=Table0}=H) ->
+ Table = lists:reverse(array:to_list(Table0)),
+ H#holder{sort=S#sort{sort_incr=(not Incr)},
+ tabs=array:from_list(Table)};
+sort(Col, #holder{sort=#sort{sort_incr=Incr}=S, tabs=Table0}=H) ->
+ Table = case Incr of
+ false -> lists:reverse(lists:keysort(Col, array:to_list(Table0)));
+ true -> lists:keysort(Col, array:to_list(Table0))
+ end,
+ H#holder{sort=S#sort{sort_key=Col},
+ tabs=array:from_list(Table)}.
+
+get_row(From, Row, Col, Table) ->
+ Object = array:get(Row, Table),
+ From ! {self(), get_col(Col, Object)}.
+
+get_col(all, Rec) ->
+ Rec;
+get_col(2, #tab{}=Rec) -> %% Memory in kB
+ observer_lib:to_str(element(#tab.memory, Rec) div 1024);
+get_col(Col, #tab{}=Rec) ->
+ case element(col2key(Col), Rec) of
+ ignore -> "";
+ Val -> observer_lib:to_str(Val)
+ end;
+get_col(_, _) ->
+ "".
+
+get_attr(From, Row, #holder{tabs=Tabs, attrs=Attrs}) ->
+ EvenOdd = case (Row rem 2) > 0 of
+ true -> Attrs#attrs.odd;
+ false -> Attrs#attrs.even
+ end,
+ What = try array:get(Row, Tabs) of
+ #tab{protection=private} ->
+ Attrs#attrs.deleted;
+ _ ->
+ EvenOdd
+ catch _ ->
+ EvenOdd
+ end,
+ From ! {self(), What}.
diff --git a/lib/observer/src/observer_wx.erl b/lib/observer/src/observer_wx.erl
index 9b9e80f479..453e3bdc2d 100644
--- a/lib/observer/src/observer_wx.erl
+++ b/lib/observer/src/observer_wx.erl
@@ -459,7 +459,7 @@ handle_info({'EXIT', Pid, Reason}, State) ->
normal ->
{noreply, State};
_ ->
- io:format("Observer: Child (~s) crashed exiting: ~p ~p~n",
+ io:format("Observer: Child (~s) crashed exiting: ~p ~tp~n",
[pid2panel(Pid, State), Pid, Reason]),
{stop, normal, State}
end;
@@ -504,7 +504,7 @@ save_config(Panels) ->
File = config_file(),
case filelib:ensure_dir(File) of
ok ->
- Format = [io_lib:format("~p.~n",[Conf]) || Conf <- Configs],
+ Format = [io_lib:format("~tp.~n",[Conf]) || Conf <- Configs],
_ = file:write_file(File, Format);
_ ->
ignore
@@ -732,7 +732,7 @@ get_nodes() ->
{Nodes, lists:reverse(Menues)}.
epmd_nodes(Names) ->
- [_, Host] = string:tokens(atom_to_list(node()),"@"),
+ [_, Host] = string:lexemes(atom_to_list(node()),"@"),
[list_to_atom(Name ++ [$@|Host]) || {Name, _} <- Names].
update_node_list(State = #state{menubar=MenuBar}) ->
diff --git a/lib/observer/src/ttb.erl b/lib/observer/src/ttb.erl
index 09b0bc6710..29a572d7fe 100644
--- a/lib/observer/src/ttb.erl
+++ b/lib/observer/src/ttb.erl
@@ -100,7 +100,7 @@ do_tracer(Clients,PI,Traci) ->
{ok, H} = inet:gethostname(),
H;
_ ->
- [_,H] = string:tokens(atom_to_list(N),"@"),
+ [_,H] = string:lexemes(atom_to_list(N),"@"),
H
end,
case catch dbg:tracer(N,port,dbg:trace_port(ip,IpPortSpec)) of
@@ -635,7 +635,7 @@ stop(Opts) when is_list(Opts) ->
ok;
{_, {stopped, _}} ->
%% Printout moved out of the ttb loop to avoid occasional deadlock
- io:format("Stored logs in ~s~n", [element(2, Result)]);
+ io:format("Stored logs in ~ts~n", [element(2, Result)]);
{_, _} ->
ok
end,
@@ -792,7 +792,7 @@ do_stop({FetchOrFormat, UserDir}, Sender, NodeInfo, SessionInfo) ->
write_config(?last_config, all),
Localhost = host(node()),
Dir = get_fetch_dir(UserDir, proplists:get_value(logfile, SessionInfo)),
- file:make_dir(Dir),
+ ok = filelib:ensure_dir(filename:join(Dir,"*")),
%% The nodes are traversed twice here because
%% the meta tracing in observer_backend must be
%% stopped before dbg is stopped, and dbg must
@@ -900,21 +900,29 @@ fetch_report(Localhost, Dir, Node, MetaFile) ->
fetch(Localhost,Dir,Node,MetaFile) ->
case (host(Node) == Localhost) orelse is_local(MetaFile) of
- true -> % same host, just move the files
+ true -> % same host, just move the files
Files = get_filenames(Node,MetaFile),
lists:foreach(
- fun(File0) ->
- Dest = filename:join(Dir,filename:basename(File0)),
- file:rename(File0, Dest)
- end,
- Files);
+ fun(File0) ->
+ Dest = filename:join(Dir,filename:basename(File0)),
+ file:rename(File0, Dest)
+ end,
+ Files);
false ->
{ok, LSock} = gen_tcp:listen(0, [binary,{packet,2},{active,false}]),
{ok,Port} = inet:port(LSock),
- rpc:cast(Node,observer_backend,ttb_fetch,
- [MetaFile,{Port,Localhost}]),
+ Enc = file:native_name_encoding(),
+ Args =
+ case rpc:call(Node,erlang,function_exported,
+ [observer_backend,ttb_fetch,3]) of
+ true ->
+ [MetaFile,{Port,Localhost},Enc];
+ false ->
+ [MetaFile,{Port,Localhost}]
+ end,
+ rpc:cast(Node,observer_backend,ttb_fetch,Args),
{ok, Sock} = gen_tcp:accept(LSock),
- receive_files(Dir,Sock,undefined),
+ receive_files(Dir,Sock,undefined,Enc),
ok = gen_tcp:close(LSock),
ok = gen_tcp:close(Sock)
end.
@@ -929,25 +937,48 @@ get_filenames(_N, {local,F,_}) ->
get_filenames(N, F) ->
rpc:call(N, observer_backend,ttb_get_filenames,[F]).
-receive_files(Dir,Sock,Fd) ->
+receive_files(Dir,Sock,Fd,Enc) ->
case gen_tcp:recv(Sock, 0) of
{ok, <<0,Bin/binary>>} ->
file:write(Fd,Bin),
- receive_files(Dir,Sock,Fd);
- {ok, <<1,Bin/binary>>} ->
- File0 = binary_to_list(Bin),
+ receive_files(Dir,Sock,Fd,Enc);
+ {ok, <<Code,Bin/binary>>} when Code==1; Code==2; Code==3 ->
+ File0 = decode_filename(Code,Bin,Enc),
File = filename:join(Dir,File0),
{ok,Fd1} = file:open(File,[raw,write]),
- receive_files(Dir,Sock,Fd1);
+ receive_files(Dir,Sock,Fd1,Enc);
{error, closed} ->
ok = file:close(Fd)
end.
+decode_filename(1,Bin,_Enc) ->
+ %% Old version of observer_backend - filename encoded with
+ %% list_to_binary
+ binary_to_list(Bin);
+decode_filename(2,Bin,Enc) ->
+ %% Successfully encoded filename with correct encoding
+ unicode:characters_to_list(Bin,Enc);
+decode_filename(3,Bin,latin1) ->
+ %% Filename encoded with faulty encoding. This has to be utf8
+ %% remote and latin1 here, and the filename actually containing
+ %% characters outside the latin1 range. So making an escaped
+ %% variant of the filename and warning about it.
+ File0 = unicode:characters_to_list(Bin,utf8),
+ File = [ case X of
+ High when High > 255 ->
+ ["\\\\x{",erlang:integer_to_list(X, 16),$}];
+ Low ->
+ Low
+ end || X <- File0 ],
+ io:format("Warning: fetching file with faulty filename encoding ~ts~n"
+ "Will be written as ~ts~n",
+ [File0,File]),
+ File.
+
host(Node) ->
- [_name,Host] = string:tokens(atom_to_list(Node),"@"),
+ [_name,Host] = string:lexemes(atom_to_list(Node),"@"),
Host.
-
wait_for_fetch([]) ->
ok;
wait_for_fetch(Nodes) ->
@@ -1033,7 +1064,7 @@ collect_files(Dirs) ->
lists:map(fun(Dir) ->
MetaFiles = filelib:wildcard(filename:join(Dir,"*.ti")),
lists:map(fun(M) ->
- Sub = string:left(M,length(M)-3),
+ Sub = filename:rootname(M,".ti"),
case filelib:is_file(Sub) of
true -> Sub;
false -> Sub++".*.wrp"
@@ -1087,7 +1118,7 @@ read_traci(File) ->
{ok,B} ->
interpret_binary(B,dict:new(),[]);
_ ->
- io:format("Warning: no meta data file: ~s~n",[MetaFile]),
+ io:format("Warning: no meta data file: ~ts~n",[MetaFile]),
{dict:new(),[]}
end.
@@ -1303,7 +1334,7 @@ get_term(B) ->
end.
display_warning(Item,Warning) ->
- io:format("Warning: {~w,~w}~n",[Warning,Item]).
+ io:format("Warning: {~tw,~tw}~n",[Warning,Item]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/observer/src/ttb_et.erl b/lib/observer/src/ttb_et.erl
index 95e8e9aa07..f90a7f6dcf 100644
--- a/lib/observer/src/ttb_et.erl
+++ b/lib/observer/src/ttb_et.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -137,13 +137,13 @@ processes(E0) ->
E = label(E0),
{{FromProc,FromNode},{ToProc,ToNode}} =
get_actors(E#event.from,E#event.to),
- {true,E#event{from = io_lib:format("~w~n~w",[FromProc,FromNode]),
- to = io_lib:format("~w~n~w",[ToProc,ToNode])}}.
+ {true,E#event{from = io_lib:format("~tw~n~w",[FromProc,FromNode]),
+ to = io_lib:format("~tw~n~w",[ToProc,ToNode])}}.
mods_and_procs(E) ->
ActorFun = fun({M,_F,_A},{Proc,Node}) ->
- io_lib:format("~w~n~w~n~w",[M,Proc,Node])
+ io_lib:format("~w~n~tw~n~w",[M,Proc,Node])
end,
calltrace_filter(E,ActorFun).
@@ -155,13 +155,13 @@ modules(E) ->
funcs_and_procs(E) ->
ActorFun = fun({M,F,A},{Proc,Node}) ->
- io_lib:format("~s~n~w~n~w",[mfa(M,F,A),Proc,Node])
+ io_lib:format("~ts~n~tw~n~w",[mfa(M,F,A),Proc,Node])
end,
calltrace_filter(E,ActorFun).
functions(E) ->
ActorFun = fun({M,F,A},{_Proc,Node}) ->
- io_lib:format("~s~n~w",[mfa(M,F,A),Node])
+ io_lib:format("~ts~n~w",[mfa(M,F,A),Node])
end,
calltrace_filter(E,ActorFun).
@@ -221,7 +221,7 @@ label(Event=#event{label=L,contents=C}) ->
false -> Event
end.
label(L,{M,F,A}) -> label(L,M,F,A);
-label(L,Other) -> io_lib:format("~w ~w",[L,Other]).
+label(L,Other) -> io_lib:format("~w ~tw",[L,Other]).
label(call,M,F,A) -> "call " ++ mfa(M,F,A);
label(return_from,M,F,A) -> "return_from " ++ mfa(M,F,A);
label(return_to,M,F,A) -> "return_to " ++ mfa(M,F,A);
diff --git a/lib/observer/test/Makefile b/lib/observer/test/Makefile
index 6100af5e17..a44e54fc52 100644
--- a/lib/observer/test/Makefile
+++ b/lib/observer/test/Makefile
@@ -27,7 +27,8 @@ MODULES = \
ttb_SUITE \
client \
server \
- crashdump_helper
+ crashdump_helper \
+ crashdump_helper_unicode
ERL_FILES= $(MODULES:%=%.erl)
@@ -46,7 +47,7 @@ RELSYSDIR = $(RELEASE_PATH)/observer_test
# FLAGS
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS +=
+ERL_COMPILE_FLAGS += +warnings_as_errors +nowarn_export_all
EBIN = .
diff --git a/lib/observer/test/crashdump_helper.erl b/lib/observer/test/crashdump_helper.erl
index f37d9057cb..145ff56b71 100644
--- a/lib/observer/test/crashdump_helper.erl
+++ b/lib/observer/test/crashdump_helper.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,7 +19,9 @@
%%
-module(crashdump_helper).
--export([n1_proc/2,remote_proc/2]).
+-export([n1_proc/2,remote_proc/2,
+ dump_maps/0,create_maps/0,
+ create_binaries/0,create_sub_binaries/1]).
-compile(r18).
-include_lib("common_test/include/ct.hrl").
@@ -60,7 +62,9 @@ n1_proc(Creator,_N2,Pid2,Port2,_L) ->
put(ref,Ref),
put(pid,Pid),
put(bin,Bin),
+ put(bins,create_binaries()),
put(sub_bin,SubBin),
+ put(sub_bins,create_sub_binaries(get(bins))),
put(bignum,83974938738373873),
put(neg_bignum,-38748762783736367),
put(ext_pid,Pid2),
@@ -79,6 +83,7 @@ n1_proc(Creator,_N2,Pid2,Port2,_L) ->
link(OtherPid), % own node
link(Pid2), % external node
erlang:monitor(process,OtherPid),
+ erlang:monitor(process,init), % named process
erlang:monitor(process,Pid2),
code:load_file(?MODULE),
@@ -92,3 +97,49 @@ remote_proc(P1,Creator) ->
Creator ! {self(),done},
receive after infinity -> ok end
end).
+
+create_binaries() ->
+ Sizes = lists:seq(60, 70) ++ lists:seq(120, 140),
+ [begin
+ <<H:16/unit:8>> = erlang:md5(<<Size:32>>),
+ Data = ((H bsl (8*150)) div (H+7919)),
+ <<Data:Size/unit:8>>
+ end || Size <- Sizes].
+
+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]].
+
+create_sub_binary(Bin, Start, LenSub) ->
+ Len = byte_size(Bin) - LenSub - Start,
+ <<_:Start/bytes,Sub:Len/bytes,_/bytes>> = Bin,
+ Sub.
+
+%%%
+%%% Test dumping of maps. Dumping of maps only from OTP 20.2.
+%%%
+
+dump_maps() ->
+ Parent = self(),
+ F = fun() ->
+ register(aaaaaaaa_maps, self()),
+ put(maps, create_maps()),
+ Parent ! {self(),done},
+ receive _ -> ok end
+ end,
+ Pid = spawn_link(F),
+ receive
+ {Pid,done} ->
+ {ok,Pid}
+ end.
+
+create_maps() ->
+ Map0 = maps:from_list([{I,[I,I+1]} || I <- lists:seq(1, 40)]),
+ Map1 = maps:from_list([{I,{a,[I,I*I],{}}} || I <- lists:seq(1, 100)]),
+ Map2 = maps:from_list([{{I},(I*I) bsl 24} || I <- lists:seq(1, 10000)]),
+ Map3 = lists:foldl(fun(I, A) ->
+ A#{I=>I*I}
+ end, Map2, lists:seq(-10, 0)),
+ #{a=>Map0,b=>Map1,c=>Map2,d=>Map3,e=>#{}}.
diff --git a/lib/observer/test/crashdump_helper_unicode.erl b/lib/observer/test/crashdump_helper_unicode.erl
new file mode 100644
index 0000000000..60c3d20315
--- /dev/null
+++ b/lib/observer/test/crashdump_helper_unicode.erl
@@ -0,0 +1,22 @@
+-module(crashdump_helper_unicode).
+-behaviour(gen_server).
+-export([start/0, init/1, handle_call/3, handle_cast/2]).
+-record(state, {s,a,b,lb}).
+
+start() ->
+ gen_server:start({local, 'unicode_reg_name_αβ'}, ?MODULE, [], []).
+
+init([]) ->
+ process_flag(trap_exit, true),
+ ets:new('tab_αβ',[set,named_table]),
+ Bin = <<"bin αβ"/utf8>>,
+ LongBin = <<"long bin αβ - a utf8 binary which can be expanded αβ"/utf8>>,
+ {ok, #state{s = "unicode_string_αβ",
+ a = 'unicode_atom_αβ',
+ b = Bin,
+ lb = LongBin}}.
+
+handle_call(_Info, _From, State) ->
+ {reply, ok, State}.
+handle_cast(_Info, State) ->
+ {noreply, State}.
diff --git a/lib/observer/test/crashdump_viewer_SUITE.erl b/lib/observer/test/crashdump_viewer_SUITE.erl
index 1fd94ffb3c..864454cdff 100644
--- a/lib/observer/test/crashdump_viewer_SUITE.erl
+++ b/lib/observer/test/crashdump_viewer_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
%% Test functions
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
start_stop/1,load_file/1,not_found_items/1,
- non_existing/1,not_a_crashdump/1,old_crashdump/1]).
+ non_existing/1,not_a_crashdump/1,old_crashdump/1,new_crashdump/1]).
-export([init_per_suite/1, end_per_suite/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
@@ -76,13 +76,14 @@ end_per_testcase(Case, Config) ->
end,
ok.
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() -> [].
all() ->
[start_stop,
non_existing,
not_a_crashdump,
old_crashdump,
+ new_crashdump,
load_file,
not_found_items
].
@@ -212,6 +213,25 @@ not_a_crashdump(Config) when is_list(Config) ->
ok = crashdump_viewer:stop().
+%% Try to load a file with newer version than this crashdump viewer can handle
+new_crashdump(Config) ->
+ Dump = hd(?config(dumps,Config)),
+ ok = start_backend(Dump),
+ {ok,{MaxVsn,CurrentVsn}} = crashdump_viewer:get_dump_versions(),
+ if MaxVsn =/= CurrentVsn ->
+ ct:fail("Current dump version is not equal to cdv's max version");
+ true ->
+ ok
+ end,
+ ok = crashdump_viewer:stop(),
+ NewerVsn = lists:join($.,[integer_to_list(X+1) || X <- MaxVsn]),
+ PrivDir = ?config(priv_dir,Config),
+ NewDump = filename:join(PrivDir,"new_erl_crash.dump"),
+ ok = file:write_file(NewDump,"=erl_crash_dump:"++NewerVsn++"\n"),
+ {error, Reason} = start_backend(NewDump),
+ "This Crashdump Viewer is too old" ++_ = Reason,
+ ok = crashdump_viewer:stop().
+
%% Load files into the tool and view all pages
load_file(Config) when is_list(Config) ->
case ?t:is_debug() of
@@ -328,7 +348,7 @@ browse_file(File) ->
io:format(" info read",[]),
- lookat_all_pids(Procs),
+ lookat_all_pids(Procs,is_truncated(File),incomplete_allowed(File)),
io:format(" pids ok",[]),
lookat_all_ports(Ports),
io:format(" ports ok",[]),
@@ -339,6 +359,21 @@ browse_file(File) ->
Procs. % used as second arg to special/2
+is_truncated(File) ->
+ case filename:extension(File) of
+ ".trunc"++_ ->
+ true;
+ _ ->
+ false
+ end.
+
+incomplete_allowed(File) ->
+ %% Incomplete heap is allowed for native libs, since some literals
+ %% are not dumped - and for pre OTP-20 (really pre 20.2) releases,
+ %% since literals were not dumped at all then.
+ Rel = get_rel_from_dump_name(File),
+ Rel < 20 orelse test_server:is_native(lists).
+
special(File,Procs) ->
case filename:extension(File) of
".full_dist" ->
@@ -364,6 +399,17 @@ special(File,Procs) ->
crashdump_viewer:expand_binary({SOffset,SSize,SPos}),
io:format(" expand binary ok",[]),
+ Binaries = crashdump_helper:create_binaries(),
+ verify_binaries(Binaries, proplists:get_value(bins,Dict)),
+ io:format(" binaries ok",[]),
+
+ SubBinaries = crashdump_helper:create_sub_binaries(Binaries),
+ verify_binaries(SubBinaries, proplists:get_value(sub_bins,Dict)),
+ io:format(" sub binaries ok",[]),
+
+ #proc{last_calls=LastCalls} = ProcDetails,
+ true = length(LastCalls) =< 4,
+
['#CDVPid',X1,Y1,Z1] = proplists:get_value(ext_pid,Dict),
ChannelStr1 = integer_to_list(X1),
ExtPid =
@@ -413,34 +459,176 @@ special(File,Procs) ->
old_attrib=undefined,
old_comp_info=undefined}=Mod2,
ok;
- %% ".strangemodname" ->
- %% {ok,Mods,[]} = crashdump_viewer:loaded_modules(),
- %% lookat_all_mods(Mods),
- %% ok;
- %% ".sort" ->
- %% %% sort ports, atoms and modules ????
- %% ok;
- %% ".trunc" ->
- %% %% ????
- %% ok;
- ".trunc.bytes" ->
+ ".trunc_mod" ->
+ ModName = atom_to_list(?helper_mod),
+ {ok,Mod=#loaded_mod{},[TW]} =
+ crashdump_viewer:loaded_mod_details(ModName),
+ "WARNING: The crash dump is truncated here."++_ = TW,
+ #loaded_mod{current_attrib=CA,current_comp_info=CCI,
+ old_attrib=OA,old_comp_info=OCI} = Mod,
+ case lists:all(fun(undefined) ->
+ true;
+ (S) when is_list(S) ->
+ io_lib:printable_unicode_list(lists:flatten(S));
+ (_) -> false
+ end,
+ [CA,CCI,OA,OCI]) of
+ true ->
+ ok;
+ false ->
+ ct:fail({should_be_printable_strings_or_undefined,
+ {CA,CCI,OA,OCI}})
+ end,
+ ok;
+ ".trunc_bin1" ->
+ %% This is 'full_dist' truncated after the first
+ %% "=binary:"
+ %% i.e. no binary exist in the dump
+ [#proc{pid=Pid0}|_Rest] = lists:keysort(#proc.name,Procs),
+ Pid = pid_to_list(Pid0),
+ %%WarnIncompleteHeap = ["WARNING: This process has an incomplete heap. Some information might be missing."],
+ {ok,ProcDetails=#proc{},[]} =
+ crashdump_viewer:proc_details(Pid),
+ io:format(" process details ok",[]),
+
+ #proc{dict=Dict} = ProcDetails,
+
+ '#CDVNonexistingBinary' = proplists:get_value(bin,Dict),
+ '#CDVNonexistingBinary' = proplists:get_value(sub_bin,Dict),
+
+ io:format(" nonexisting binaries ok",[]),
+ ok;
+ ".trunc_bin2" ->
+ %% This is 'full_dist' truncated after the first
+ %% "=binary:Addr\n
+ %% Size"
+ %% i.e. binaries are truncated
+ [#proc{pid=Pid0}|_Rest] = lists:keysort(#proc.name,Procs),
+ Pid = pid_to_list(Pid0),
+ {ok,ProcDetails=#proc{},[]} = crashdump_viewer:proc_details(Pid),
+ io:format(" process details ok",[]),
+
+ #proc{dict=Dict} = ProcDetails,
+
+ ['#CDVBin',Offset,Size,Pos] = proplists:get_value(bin,Dict),
+ {ok,'#CDVTruncatedBinary'} =
+ crashdump_viewer:expand_binary({Offset,Size,Pos}),
+ ['#CDVBin',SOffset,SSize,SPos] = proplists:get_value(sub_bin,Dict),
+ {ok,'#CDVTruncatedBinary'} =
+ crashdump_viewer:expand_binary({SOffset,SSize,SPos}),
+
+ io:format(" expand truncated binary ok",[]),
+ ok;
+ ".trunc_bin3" ->
+ %% This is 'full_dist' truncated after the first
+ %% "=binary:Addr\n
+ %% Size:"
+ %% i.e. same as 'trunc_bin2', except the colon exists also
+ [#proc{pid=Pid0}|_Rest] = lists:keysort(#proc.name,Procs),
+ Pid = pid_to_list(Pid0),
+ {ok,ProcDetails=#proc{},[]} = crashdump_viewer:proc_details(Pid),
+ io:format(" process details ok",[]),
+
+ #proc{dict=Dict} = ProcDetails,
+
+ ['#CDVBin',Offset,Size,Pos] = proplists:get_value(bin,Dict),
+ {ok,'#CDVTruncatedBinary'} =
+ crashdump_viewer:expand_binary({Offset,Size,Pos}),
+ ['#CDVBin',SOffset,SSize,SPos] = proplists:get_value(sub_bin,Dict),
+ {ok,'#CDVTruncatedBinary'} =
+ crashdump_viewer:expand_binary({SOffset,SSize,SPos}),
+
+ io:format(" expand truncated binary ok",[]),
+ ok;
+ ".trunc_bin4" ->
+ %% This is 'full_dist' truncated after the first
+ %% "=binary:Addr\n
+ %% Size:BinaryMissinOneByte"
+ %% i.e. the full binary is truncated, but the sub binary is complete
+ [#proc{pid=Pid0}|_Rest] = lists:keysort(#proc.name,Procs),
+ Pid = pid_to_list(Pid0),
+ {ok,ProcDetails=#proc{},[]} = crashdump_viewer:proc_details(Pid),
+ io:format(" process details ok",[]),
+
+ #proc{dict=Dict} = ProcDetails,
+
+ ['#CDVBin',Offset,Size,Pos] = proplists:get_value(bin,Dict),
+ {ok,'#CDVTruncatedBinary'} =
+ crashdump_viewer:expand_binary({Offset,Size,Pos}),
+ io:format(" expand truncated binary ok",[]),
+ ['#CDVBin',SOffset,SSize,SPos] = proplists:get_value(sub_bin,Dict),
+ {ok,<<_:SSize/binary>>} =
+ crashdump_viewer:expand_binary({SOffset,SSize,SPos}),
+ io:format(" expand complete sub binary ok",[]),
+
+ ok;
+ ".trunc_bytes" ->
{ok,_,[TW]} = crashdump_viewer:general_info(),
{match,_} = re:run(TW,"CRASH DUMP SIZE LIMIT REACHED"),
+ io:format(" size limit information ok",[]),
+ ok;
+ ".unicode" ->
+ #proc{pid=Pid0} =
+ lists:keyfind("'unicode_reg_name_αβ'",#proc.name,Procs),
+ Pid = pid_to_list(Pid0),
+ {ok,#proc{},[]} = crashdump_viewer:proc_details(Pid),
+ io:format(" unicode registered name ok",[]),
+
+ {ok,[#ets_table{id="'tab_αβ'",name="'tab_αβ'"}],[]} =
+ crashdump_viewer:ets_tables(Pid),
+ io:format(" unicode table name ok",[]),
+
+ ok;
+ ".maps" ->
+ %% I registered a process as aaaaaaaa_maps in the map dump
+ %% to make sure it will be the first in the list when sorted
+ %% on names.
+ [#proc{pid=Pid0,name=Name}|_Rest] = lists:keysort(#proc.name,Procs),
+ "aaaaaaaa_maps" = Name,
+ Pid = pid_to_list(Pid0),
+ {ok,ProcDetails=#proc{},[]} = crashdump_viewer:proc_details(Pid),
+ io:format(" process details ok",[]),
+
+ #proc{dict=Dict} = ProcDetails,
+ %% io:format("~p\n", [Dict]),
+ Maps = crashdump_helper:create_maps(),
+ Maps = proplists:get_value(maps,Dict),
+ io:format(" maps ok",[]),
ok;
_ ->
ok
end,
ok.
+verify_binaries([H|T1], [H|T2]) ->
+ %% Heap binary.
+ verify_binaries(T1, T2);
+verify_binaries([Bin|T1], [['#CDVBin',Offset,Size,Pos]|T2]) ->
+ %% Refc binary.
+ {ok,<<Bin:Size/binary>>} = crashdump_viewer:expand_binary({Offset,Size,Pos}),
+ verify_binaries(T1, T2);
+verify_binaries([], []) ->
+ ok.
-lookat_all_pids([]) ->
+lookat_all_pids([],_,_) ->
ok;
-lookat_all_pids([#proc{pid=Pid0}|Procs]) ->
+lookat_all_pids([#proc{pid=Pid0}|Procs],TruncAllowed,IncompAllowed) ->
Pid = pid_to_list(Pid0),
- {ok,_ProcDetails=#proc{},_ProcTW} = crashdump_viewer:proc_details(Pid),
- {ok,_Ets,_EtsTW} = crashdump_viewer:ets_tables(Pid),
- {ok,_Timers,_TimersTW} = crashdump_viewer:timers(Pid),
- lookat_all_pids(Procs).
+ {ok,_ProcDetails=#proc{},ProcTW} = crashdump_viewer:proc_details(Pid),
+ {ok,_Ets,EtsTW} = crashdump_viewer:ets_tables(Pid),
+ {ok,_Timers,TimersTW} = crashdump_viewer:timers(Pid),
+ case {ProcTW,EtsTW,TimersTW} of
+ {[],[],[]} ->
+ ok;
+ {["WARNING: This process has an incomplete heap."++_],[],[]}
+ when IncompAllowed ->
+ ok; % native libs, literals might not be included in dump
+ _ when TruncAllowed ->
+ ok; % truncated dump
+ TWs ->
+ ct:fail({unexpected_warning,TWs})
+ end,
+ lookat_all_pids(Procs,TruncAllowed,IncompAllowed).
lookat_all_ports([]) ->
ok;
@@ -486,17 +674,64 @@ do_create_dumps(DataDir,Rel) ->
end,
case Rel of
current ->
- CD3 = dump_with_args(DataDir,Rel,"instr","+Mim true"),
+ CD3 = dump_with_args(DataDir,Rel,"instr","+Muatags true"),
CD4 = dump_with_strange_module_name(DataDir,Rel,"strangemodname"),
- Bytes = rand:uniform(300000) + 100,
- CD5 = dump_with_args(DataDir,Rel,"trunc.bytes",
- "-env ERL_CRASH_DUMP_BYTES " ++
- integer_to_list(Bytes)),
- {[CD1,CD2,CD3,CD4,CD5], DosDump};
+ CD5 = dump_with_size_limit_reached(DataDir,Rel,"trunc_bytes"),
+ CD6 = dump_with_unicode_atoms(DataDir,Rel,"unicode"),
+ CD7 = dump_with_maps(DataDir,Rel,"maps"),
+ TruncDumpMod = truncate_dump_mod(CD1),
+ TruncatedDumpsBinary = truncate_dump_binary(CD1),
+ {[CD1,CD2,CD3,CD4,CD5,CD6,CD7,TruncDumpMod|TruncatedDumpsBinary],
+ DosDump};
_ ->
{[CD1,CD2], DosDump}
end.
+truncate_dump_mod(File) ->
+ {ok,Bin} = file:read_file(File),
+ ModNameBin = atom_to_binary(?helper_mod,latin1),
+ NewLine = case os:type() of
+ {win32,_} -> <<"\r\n">>;
+ _ -> <<"\n">>
+ end,
+ RE = <<NewLine/binary,"=mod:",ModNameBin/binary,
+ NewLine/binary,"Current size: [0-9]*",
+ NewLine/binary,"Current attributes: ...">>,
+ {match,[{Pos,Len}]} = re:run(Bin,RE),
+ Size = Pos + Len,
+ <<Truncated:Size/binary,_/binary>> = Bin,
+ DumpName = filename:rootname(File) ++ ".trunc_mod",
+ file:write_file(DumpName,Truncated),
+ DumpName.
+
+truncate_dump_binary(File) ->
+ {ok,Bin} = file:read_file(File),
+ BinTag = <<"\n=binary:">>,
+ Colon = <<":">>,
+ NewLine = case os:type() of
+ {win32,_} -> <<"\r\n">>;
+ _ -> <<"\n">>
+ end,
+ %% Split after "our binary" created by crashdump_helper
+ %% (it may not be the first binary).
+ RE = <<"\n=binary:(?=[0-9A-Z]+",NewLine/binary,"FF:AQID)">>,
+ [StartBin,AfterTag] = re:split(Bin,RE,[{parts,2}]),
+ [AddrAndSize,BinaryAndRest] = binary:split(AfterTag,Colon),
+ [Binary,_Rest] = binary:split(BinaryAndRest,NewLine),
+ TruncSize = byte_size(Binary) - 2,
+ <<TruncBinary:TruncSize/binary,_/binary>> = Binary,
+ TruncName = filename:rootname(File) ++ ".trunc_bin",
+ write_trunc_files(TruncName,StartBin,
+ [BinTag,AddrAndSize,Colon,TruncBinary],1).
+
+write_trunc_files(TruncName0,Bin,[Part|Parts],N) ->
+ TruncName = TruncName0++integer_to_list(N),
+ Bin1 = <<Bin/binary,Part/binary>>,
+ ok = file:write_file(TruncName,Bin1),
+ [TruncName|write_trunc_files(TruncName0,Bin1,Parts,N+1)];
+write_trunc_files(_,_,[],_) ->
+ [].
+
%% Create a dump which has three visible nodes, one hidden and one
%% not connected node, and with monitors and links between nodes.
@@ -573,6 +808,48 @@ dump_with_strange_module_name(DataDir,Rel,DumpName) ->
?t:stop_node(n1),
CD.
+dump_with_size_limit_reached(DataDir,Rel,DumpName) ->
+ Tmp = dump_with_args(DataDir,Rel,DumpName,""),
+ {ok,#file_info{size=Max}} = file:read_file_info(Tmp),
+ ok = file:delete(Tmp),
+ dump_with_size_limit_reached(DataDir,Rel,DumpName,Max).
+
+dump_with_size_limit_reached(DataDir,Rel,DumpName,Max) ->
+ Bytes = max(15,rand:uniform(Max)),
+ CD = dump_with_args(DataDir,Rel,DumpName,
+ "-env ERL_CRASH_DUMP_BYTES " ++
+ integer_to_list(Bytes)),
+ {ok,#file_info{size=Size}} = file:read_file_info(CD),
+ if Size =< Bytes ->
+ %% This means that the dump was actually smaller than the
+ %% randomly selected truncation size, so we'll just do it
+ %% again with a smaller number
+ ok = file:delete(CD),
+ dump_with_size_limit_reached(DataDir,Rel,DumpName,Size-3);
+ true ->
+ CD
+ end.
+
+dump_with_unicode_atoms(DataDir,Rel,DumpName) ->
+ Opt = rel_opt(Rel),
+ Pz = "-pz \"" ++ filename:dirname(code:which(?MODULE)) ++ "\"",
+ PzOpt = [{args,Pz}],
+ {ok,N1} = ?t:start_node(n1,peer,Opt ++ PzOpt),
+ {ok,_Pid} = rpc:call(N1,crashdump_helper_unicode,start,[]),
+ CD = dump(N1,DataDir,Rel,DumpName),
+ ?t:stop_node(n1),
+ CD.
+
+dump_with_maps(DataDir,Rel,DumpName) ->
+ Opt = rel_opt(Rel),
+ Pz = "-pz \"" ++ filename:dirname(code:which(?MODULE)) ++ "\"",
+ PzOpt = [{args,Pz}],
+ {ok,N1} = ?t:start_node(n1,peer,Opt ++ PzOpt),
+ {ok,_Pid} = rpc:call(N1,crashdump_helper,dump_maps,[]),
+ CD = dump(N1,DataDir,Rel,DumpName),
+ ?t:stop_node(n1),
+ CD.
+
dump(Node,DataDir,Rel,DumpName) ->
Crashdump = filename:join(DataDir, dump_prefix(Rel)++DumpName),
rpc:call(Node,os,putenv,["ERL_CRASH_DUMP",Crashdump]),
@@ -625,6 +902,11 @@ dump_prefix(current) ->
dump_prefix(Rel) ->
lists:concat(["r",Rel,"_dump."]).
+get_rel_from_dump_name(File) ->
+ Name = filename:basename(File),
+ ["r"++Rel|_] = string:split(Name,"_"),
+ list_to_integer(Rel).
+
compat_rel(current) ->
"";
compat_rel(Rel) ->
diff --git a/lib/observer/test/observer_SUITE.erl b/lib/observer/test/observer_SUITE.erl
index 41726b1521..40f5d44847 100644
--- a/lib/observer/test/observer_SUITE.erl
+++ b/lib/observer/test/observer_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -113,8 +113,14 @@ appup_file(Config) when is_list(Config) ->
basic(suite) -> [];
basic(doc) -> [""];
basic(Config) when is_list(Config) ->
- timer:send_after(100, "foobar"), %% Otherwise the timer server gets added to procs
+ %% Start these before
+ wx:new(),
+ wx:destroy(),
+ timer:send_after(100, "foobar"),
+ {foo, node@machine} ! dummy_msg, %% start distribution stuff
+ %% Otherwise ever lasting servers gets added to procs
ProcsBefore = processes(),
+ ProcInfoBefore = [{P,process_info(P)} || P <- ProcsBefore],
NumProcsBefore = length(ProcsBefore),
ok = observer:start(),
@@ -145,8 +151,10 @@ basic(Config) when is_list(Config) ->
ProcsAfter = processes(),
NumProcsAfter = length(ProcsAfter),
if NumProcsAfter=/=NumProcsBefore ->
+ BeforeNotAfter = ProcsBefore -- ProcsAfter,
ct:log("Before but not after:~n~p~n",
- [[{P,process_info(P)} || P <- ProcsBefore -- ProcsAfter]]),
+ [[{P,I} || {P,I} <- ProcInfoBefore,
+ lists:member(P,BeforeNotAfter)]]),
ct:log("After but not before:~n~p~n",
[[{P,process_info(P)} || P <- ProcsAfter -- ProcsBefore]]),
ct:fail("leaking processes");
@@ -304,10 +312,10 @@ table_win(Config) when is_list(Config) ->
%% Test PR-1296/OTP-14151
%% Clicking a link to a port before the port tab has been activated the
%% first time crashes observer.
-port_win_when_tab_not_initiated(Config) ->
+port_win_when_tab_not_initiated(_Config) ->
{ok,Port} = gen_tcp:listen(0,[]),
ok = observer:start(),
- Notebook = setup_whitebox_testing(),
+ _Notebook = setup_whitebox_testing(),
observer ! {open_link,erlang:port_to_list(Port)},
timer:sleep(1000),
observer:stop(),
diff --git a/lib/observer/test/ttb_SUITE.erl b/lib/observer/test/ttb_SUITE.erl
index c06ec21f36..33133dd78d 100644
--- a/lib/observer/test/ttb_SUITE.erl
+++ b/lib/observer/test/ttb_SUITE.erl
@@ -2,7 +2,7 @@
%% %CopyrightBegin%
%%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -222,7 +222,7 @@ file_fetch(Config) when is_list(Config) ->
?line ?t:capture_stop(),
?line [StoreString] = ?t:capture_get(),
?line UploadDir =
- lists:last(string:tokens(lists:flatten(StoreString),"$ \n")),
+ lists:last(string:lexemes(lists:flatten(StoreString),"$ \n")),
%% check that files are no longer in original directories...
?line ok = check_gone(ThisDir,atom_to_list(Node)++"-file_fetch"),
@@ -778,37 +778,37 @@ otp_4967_2(suite) ->
otp_4967_2(doc) ->
["OTP-4967: Trace message sent to {Name, Node}"];
otp_4967_2(Config) when is_list(Config) ->
- io:format("1: ~p",[now()]),
+ io:format("1: ~p",[erlang:timestamp()]),
?line Privdir = priv_dir(Config),
- io:format("2: ~p",[now()]),
+ io:format("2: ~p",[erlang:timestamp()]),
?line File = filename:join(Privdir,"otp_4967"),
- io:format("3: ~p",[now()]),
+ io:format("3: ~p",[erlang:timestamp()]),
?line S = self(),
- io:format("4: ~p",[now()]),
+ io:format("4: ~p",[erlang:timestamp()]),
?line {ok,[Node]} =
ttb:tracer(node(),[{file, File},
{handler,{fun myhandler/4, S}}]),
- io:format("5: ~p",[now()]),
+ io:format("5: ~p",[erlang:timestamp()]),
%% Test that delayed registration of a process works.
receive after 200 -> ok end,
?line register(otp_4967,self()),
- io:format("6: ~p",[now()]),
+ io:format("6: ~p",[erlang:timestamp()]),
?line {ok,[{S,[{matched,Node,1}]}]} = ttb:p(self(),s),
- io:format("7: ~p",[now()]),
+ io:format("7: ~p",[erlang:timestamp()]),
?line {otp_4967,node()} ! heihopp,
- io:format("8: ~p",[now()]),
+ io:format("8: ~p",[erlang:timestamp()]),
?line stopped = ttb:stop([format]),
- io:format("9: ~p",[now()]),
+ io:format("9: ~p",[erlang:timestamp()]),
?line Msgs = flush(),
- io:format("10: ~p",[now()]),
+ io:format("10: ~p",[erlang:timestamp()]),
?line io:format("Messages received: \n~p\n",[Msgs]),
- io:format("11: ~p",[now()]),
+ io:format("11: ~p",[erlang:timestamp()]),
?line true = lists:member(heihopp,Msgs), % the heihopp message itself
- io:format("13: ~p",[now()]),
+ io:format("13: ~p",[erlang:timestamp()]),
?line {value,{trace_ts,_,send,heihopp,{_,otp_4967,Node},{_,_,_}}} =
lists:keysearch(heihopp,4,Msgs), % trace trace of the heihopp message
- io:format("14: ~p",[now()]),
+ io:format("14: ~p",[erlang:timestamp()]),
?line end_of_trace = lists:last(Msgs), % end of the trace
ok.
@@ -1035,8 +1035,8 @@ logfile_name_in_fetch_dir(Config) when is_list(Config) ->
?line {ServerNode, ClientNode} = start_client_and_server(),
?line begin_trace(ServerNode, ClientNode, {local, ?FNAME}),
?line {_,Dir} = ttb:stop([return_fetch_dir]),
- ?line P1 = lists:nth(3, string:tokens(filename:basename(Dir), "_")),
- ?line P2 = hd(string:tokens(P1, "-")),
+ ?line P1 = lists:nth(3, string:lexemes(filename:basename(Dir), "_")),
+ ?line P2 = hd(string:lexemes(P1, "-")),
?line _File = P2.
logfile_name_in_fetch_dir(cleanup,_Config) ->
?line stop_client_and_server().
diff --git a/lib/observer/vsn.mk b/lib/observer/vsn.mk
index 21edfcd184..21c8f4e6c9 100644
--- a/lib/observer/vsn.mk
+++ b/lib/observer/vsn.mk
@@ -1 +1 @@
-OBSERVER_VSN = 2.4
+OBSERVER_VSN = 2.8.1
diff --git a/lib/odbc/doc/src/Makefile b/lib/odbc/doc/src/Makefile
index b66d00a88b..a6311ceede 100644
--- a/lib/odbc/doc/src/Makefile
+++ b/lib/odbc/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
+# Copyright Ericsson AB 1999-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -38,11 +38,9 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# Target Specs
# ----------------------------------------------------
XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = odbc.xml
+XML_REF3_FILES = odbc.xml
-XML_PART_FILES = part.xml \
- part_notes.xml \
- part_notes_history.xml
+XML_PART_FILES = part.xml
XML_HTML_FILES = \
notes_history.xml
@@ -52,21 +50,15 @@ XML_CHAPTER_FILES = \
getting_started.xml \
databases.xml \
error_handling.xml \
- notes.xml
+ notes.xml
BOOK_FILES = book.xml
XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \
- $(XML_PART_FILES) $(XML_CHAPTER_FILES)
+ $(XML_PART_FILES) $(XML_CHAPTER_FILES)
GIF_FILES = \
- book.gif \
- odbc.gif \
- note.gif \
- notes.gif \
- ref_man.gif \
- user_guide.gif \
- odbc_app_arc.gif
+ odbc_app_arc.gif
# ----------------------------------------------------
@@ -87,10 +79,10 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
+XML_FLAGS +=
+DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -109,6 +101,7 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
@@ -117,12 +110,12 @@ man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%) # We depend just to copy them to ../html
-debug opt:
+debug opt:
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
diff --git a/lib/odbc/doc/src/book.gif b/lib/odbc/doc/src/book.gif
deleted file mode 100644
index 94b3868792..0000000000
--- a/lib/odbc/doc/src/book.gif
+++ /dev/null
Binary files differ
diff --git a/lib/odbc/doc/src/fascicules.xml b/lib/odbc/doc/src/fascicules.xml
deleted file mode 100644
index 91251d4b20..0000000000
--- a/lib/odbc/doc/src/fascicules.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
-
diff --git a/lib/odbc/doc/src/note.gif b/lib/odbc/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/odbc/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/odbc/doc/src/notes.gif b/lib/odbc/doc/src/notes.gif
deleted file mode 100644
index e000cca26a..0000000000
--- a/lib/odbc/doc/src/notes.gif
+++ /dev/null
Binary files differ
diff --git a/lib/odbc/doc/src/notes.xml b/lib/odbc/doc/src/notes.xml
index cc25a21c74..dba7663bb9 100644
--- a/lib/odbc/doc/src/notes.xml
+++ b/lib/odbc/doc/src/notes.xml
@@ -4,14 +4,14 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2016</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
@@ -21,7 +21,7 @@
limitations under the License.
</legalnotice>
-
+
<title>ODBC Release Notes</title>
<prepared>otp_appnotes</prepared>
<docno>nil</docno>
@@ -32,7 +32,37 @@
<p>This document describes the changes made to the odbc application.
</p>
- <section><title>ODBC 2.12</title>
+ <section><title>ODBC 2.12.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>ODBC 2.12.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>ODBC 2.12</title>
<section><title>Improvements and New Features</title>
<list>
@@ -568,9 +598,9 @@
</section>
-
+
<section><title>ODBC 2.10.7</title>
-
+
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
@@ -583,7 +613,7 @@
</list>
</section>
-
+
<section><title>Improvements and New Features</title>
<list>
<item>
@@ -720,7 +750,7 @@
</section>
<section><title>ODBC 2.10.5</title>
-
+
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
@@ -732,12 +762,12 @@
</item>
</list>
</section>
-
+
</section>
<section><title>ODBC 2.10.4</title>
-
+
<section><title>Improvements and New Features</title>
<list>
<item>
@@ -756,7 +786,7 @@
</item>
</list>
</section>
-
+
</section>
<section><title>ODBC 2.10.3</title>
@@ -787,7 +817,7 @@
</section>
<section><title>ODBC 2.10.2</title>
-
+
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
@@ -802,9 +832,9 @@
</section>
</section>
-
+
<section><title>ODBC 2.10.1</title>
-
+
<section><title>Improvements and New Features</title>
<list>
<item>
@@ -852,7 +882,7 @@
</section>
<section><title>ODBC 2.10</title>
-
+
<section><title>Improvements and New Features</title>
<list>
<item>
@@ -865,11 +895,11 @@
</item>
</list>
</section>
-
+
</section>
<section><title>ODBC 2.0.9</title>
-
+
<section><title>Improvements and New Features</title>
<list>
<item>
@@ -897,9 +927,9 @@
</item>
</list>
</section>
-
+
</section>
-
+
<section>
<title>ODBC 2.0.8</title>
@@ -1142,9 +1172,5 @@
</item>
</list>
</section>
- <!-- p>For information about older versions see
- <url href="part_notes_history_frame.html">release notes history</url>.</p -->
</section>
</chapter>
-
-
diff --git a/lib/odbc/doc/src/odbc.gif b/lib/odbc/doc/src/odbc.gif
deleted file mode 100644
index fbbabee5aa..0000000000
--- a/lib/odbc/doc/src/odbc.gif
+++ /dev/null
Binary files differ
diff --git a/lib/odbc/doc/src/odbc_index.gif b/lib/odbc/doc/src/odbc_index.gif
deleted file mode 100644
index fbbabee5aa..0000000000
--- a/lib/odbc/doc/src/odbc_index.gif
+++ /dev/null
Binary files differ
diff --git a/lib/odbc/doc/src/part_notes.xml b/lib/odbc/doc/src/part_notes.xml
deleted file mode 100644
index 8f1dbd3fbc..0000000000
--- a/lib/odbc/doc/src/part_notes.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>ODBC Release Notes</title>
- <prepared>Ingela Anderton Andin</prepared>
- <docno></docno>
- <date>2004-09-07</date>
- <rev></rev>
- <file>part_notes.sgml</file>
- </header>
- <description>
- <p>An interface to relational SQL-databases built on ODBC (Open
- Database Connectivity). </p>
- <p>For information about older versions see
- <url href="part_notes_history_frame.html">release notes history</url>.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
-
diff --git a/lib/odbc/doc/src/part_notes_history.xml b/lib/odbc/doc/src/part_notes_history.xml
deleted file mode 100644
index 6f855f6ed1..0000000000
--- a/lib/odbc/doc/src/part_notes_history.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Odbc</title>
- <prepared>Ingela Anderton Andin</prepared>
- <docno></docno>
- <date>2004-09-30</date>
- <rev></rev>
- <file>part_notes.sgml</file>
- </header>
- <include file="notes_history"></include>
-</part>
-
-
diff --git a/lib/odbc/doc/src/ref_man.gif b/lib/odbc/doc/src/ref_man.gif
deleted file mode 100644
index b13c4efd53..0000000000
--- a/lib/odbc/doc/src/ref_man.gif
+++ /dev/null
Binary files differ
diff --git a/lib/odbc/doc/src/user_guide.gif b/lib/odbc/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/odbc/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/odbc/doc/src/warning.gif b/lib/odbc/doc/src/warning.gif
deleted file mode 100644
index 96af52360e..0000000000
--- a/lib/odbc/doc/src/warning.gif
+++ /dev/null
Binary files differ
diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk
index 2e313570e1..bb21016fad 100644
--- a/lib/odbc/vsn.mk
+++ b/lib/odbc/vsn.mk
@@ -1 +1 @@
-ODBC_VSN = 2.12
+ODBC_VSN = 2.12.2
diff --git a/lib/orber/AUTHORS b/lib/orber/AUTHORS
deleted file mode 100644
index a77bdcf140..0000000000
--- a/lib/orber/AUTHORS
+++ /dev/null
@@ -1,8 +0,0 @@
-Original Authors:
-Lars Thorsen
-Per Danielsson
-Peter Lundell
-Niclas Eklund
-Babbis Xagorarakis
-
-Contributors:
diff --git a/lib/orber/COSS/CosNaming/CosNaming_BindingIterator_impl.erl b/lib/orber/COSS/CosNaming/CosNaming_BindingIterator_impl.erl
deleted file mode 100644
index 760c003f82..0000000000
--- a/lib/orber/COSS/CosNaming/CosNaming_BindingIterator_impl.erl
+++ /dev/null
@@ -1,94 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: CosNaming_BindingIterator_impl.erl
-%%
-%%-----------------------------------------------------------------
--module('CosNaming_BindingIterator_impl').
-
--include_lib("orber/include/corba.hrl").
--include("CosNaming.hrl").
--include("orber_cosnaming.hrl").
-
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([init/1, terminate/2, code_change/3]).
--export([next_one/1, next_n/2, destroy/1]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: init/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-init(State) ->
- {ok, State}.
-
-%%-----------------------------------------------------------------
-%% Func: terminate/2
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-next_one([]) ->
- NoBinding = #'CosNaming_Binding'{binding_name=[],
- binding_type=nobject},
- {reply, {false, NoBinding}, []};
-next_one([Binding]) ->
- {reply, {true, Binding}, []};
-next_one([Binding|Rest]) ->
- {reply, {true, Binding}, Rest}.
-
-next_n([], _) ->
- {reply, {false, []}, []};
-next_n(List, HowMany) ->
- {More, Acc, NewList} = split(List, HowMany, []),
- {reply, {More, Acc}, NewList}.
-
-split([], _, Acc) ->
- {false, Acc, []};
-split(Rest, 0, Acc) ->
- {true, Acc, Rest};
-split([H|T], N, Acc) ->
- split(T, N-1, [H|Acc]).
-
-
-destroy(OE_State) ->
- {stop, normal, ok, OE_State}.
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
diff --git a/lib/orber/COSS/CosNaming/CosNaming_NamingContextExt_impl.erl b/lib/orber/COSS/CosNaming/CosNaming_NamingContextExt_impl.erl
deleted file mode 100644
index 88049a509f..0000000000
--- a/lib/orber/COSS/CosNaming/CosNaming_NamingContextExt_impl.erl
+++ /dev/null
@@ -1,756 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2017. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: CosNaming_NamingContextExt_impl.erl
-%% Modified:
-%%
-%%-----------------------------------------------------------------
-%% README:
-%% (1)
-%%
-%%-----------------------------------------------------------------
--module('CosNaming_NamingContextExt_impl').
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include("CosNaming.hrl").
--include("CosNaming_NamingContext.hrl").
--include("CosNaming_NamingContextExt.hrl").
--include("orber_cosnaming.hrl").
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
-%% Mandatory callbacks
--export([init/1,
- terminate/2,
- code_change/3]).
-
-%% Inherrit from CosNaming::NamingContext
--export([bind/4,
- rebind/4,
- bind_context/4,
- rebind_context/4,
- resolve/3,
- unbind/3,
- new_context/2,
- bind_new_context/3,
- list/3,
- destroy/2]).
-
-%% CosNaming::NamingContextExt
--export([to_string/3,
- to_name/3,
- to_url/4,
- resolve_str/3]).
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
--export([dump/0,
- install/2]).
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
-%% DEBUG INFO
--define(DEBUG_LEVEL, 5).
-
-%%======================================================================
-%% External functions
-%%======================================================================
-%%---------------------------------------------------------------------%
-%% Function : init/1
-%% Description: Initiates the server
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%%----------------------------------------------------------------------
-init([]) ->
- {ok, term_to_binary('undefined')};
-
-init(DBKey) ->
- _F = ?write_function(#orber_CosNaming{name_context=DBKey,
- nameindex=[]}),
- write_result(mnesia:transaction(_F)),
- {ok, DBKey}.
-
-%%---------------------------------------------------------------------%
-%% Function : terminate
-%% Description: Shutdown the server
-%% Returns : any (ignored by gen_server)
-%%----------------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-%%---------------------------------------------------------------------%
-%% Function : code_change
-%% Description: Convert process state when code is changed
-%% Returns : {ok, State}
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%---------------------------------------------------------------------%
-%% Function : install
-%% Arguments : Timeout - abort if timeout triggered.
-%% Options - mnesia options
-%% Description:
-%% Returns :
-%%----------------------------------------------------------------------
-install(Timeout, Options) ->
- %% Fetch a list of the defined tables to see if 'CosNaming' is defined.
- AllTabs = mnesia:system_info(tables),
- DB_tables_created =
- case lists:member('orber_CosNaming', AllTabs) of
- true ->
- case lists:member({local_content, true},
- Options) of
- true->
- mnesia:add_table_copy('orber_CosNaming',
- node(),
- ram_copies);
- _->
- mnesia:create_table('orber_CosNaming',[{attributes,
- record_info(fields,
- 'orber_CosNaming')}
- |Options])
- end;
- _ ->
- mnesia:create_table('orber_CosNaming',[{attributes,
- record_info(fields,
- 'orber_CosNaming')}
- |Options])
- end,
- Wait = mnesia:wait_for_tables(['orber_CosNaming'], Timeout),
- %% Check if any error has occured yet. If there are errors, return them.
-
- if
- DB_tables_created == {atomic, ok},
- Wait == ok ->
- _F = ?write_function(#orber_CosNaming{name_context=
- term_to_binary('undefined'),
- nameindex=[]}),
- write_result(mnesia:transaction(_F));
- true ->
- {error, [DB_tables_created, Wait]}
- end.
-
-
-%%----------------------------------------------------------------------
-%% Interface CosNaming::NamingContext
-%%----------------------------------------------------------------------
-%%----------------------------------------------------------------------
-%% Function : bind
-%% Arguments :
-%% Description:
-%% Returns :
-%%----------------------------------------------------------------------
-bind(OE_THIS, OE_State, [N], Obj) ->
- SubobjKey = corba:get_subobject_key(OE_THIS),
- _BF =
- fun() ->
- case mnesia:wread({orber_CosNaming, SubobjKey}) of
- [#orber_CosNaming{nameindex = X}] ->
- case lists:keysearch(N, 1, X) of
- {value, _} ->
- {'EXCEPTION', #'CosNaming_NamingContext_AlreadyBound'{}};
- false ->
- mnesia:write(#orber_CosNaming{name_context=SubobjKey,
- nameindex=[{N, nobject, Obj} | X]})
- end;
- Other ->
- orber:dbg("[~p] ~p:bind(~p, ~p);~n"
- "DB access returned ~p",
- [?LINE, ?MODULE, N, SubobjKey, Other], ?DEBUG_LEVEL),
- {'EXCEPTION', #'CosNaming_NamingContext_CannotProceed'{rest_of_name=[N],
- cxt=OE_THIS}}
- end
- end,
- case mnesia:transaction(_BF) of
- {atomic, {'EXCEPTION', E}} ->
- corba:raise(E);
- {atomic, ok} ->
- {reply, ok, OE_State};
- Other ->
- orber:dbg("[~p] ~p:bind(~p, ~p);~n"
- "DB transaction returned ~p",
- [?LINE, ?MODULE, N, SubobjKey, Other], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
-bind(OE_THIS, OE_State, [H|T], Obj) ->
- SubobjKey = corba:get_subobject_key(OE_THIS),
- _RF = ?read_function({orber_CosNaming, SubobjKey}),
- case orber_cosnaming_utils:query_result(mnesia:transaction(_RF)) of
- error ->
- corba:raise(#'CosNaming_NamingContext_CannotProceed'{rest_of_name=[H|T],
- cxt=OE_THIS});
- X ->
- case lists:keysearch(H, 1, X) of
- {value, {H, ncontext, NC}} when is_record(NC, 'IOP_IOR') ->
- {reply, 'CosNaming_NamingContext':bind(NC, T, Obj), OE_State};
- {value, {H, ncontext, NC}} ->
- bind(NC, OE_State, T, Obj);
- _ ->
- corba:raise(#'CosNaming_NamingContext_CannotProceed'
- {rest_of_name=[H|T], cxt=OE_THIS})
- end
- end;
-bind(_OE_THIS, _OE_State, [], _Obj) ->
- orber:dbg("[~p] CosNaming_NamingContextExt:bind();~n"
- "Invoked this operation with an empty list",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_YES}).
-
-%%----------------------------------------------------------------------
-%% Function : rebind
-%% Arguments :
-%% Description:
-%% Returns :
-%%----------------------------------------------------------------------
-rebind(OE_THIS, OE_State, [N], Obj) ->
- SubobjKey = corba:get_subobject_key(OE_THIS),
- _RBF =
- fun() ->
- case mnesia:wread({orber_CosNaming, SubobjKey}) of
- [#orber_CosNaming{nameindex = X}] ->
- KList =
- case lists:keysearch(N, 1, X) of
- {value, {N, _, _V}} ->
- lists:keyreplace(N, 1, X, {N, nobject, Obj});
- false ->
- [{N, nobject, Obj} | X]
- end,
- mnesia:write(#orber_CosNaming{name_context=SubobjKey,
- nameindex=KList});
- Other ->
- orber:dbg("[~p] ~p:rebind(~p, ~p);~n"
- "DB access returned ~p",
- [?LINE, ?MODULE, N, SubobjKey, Other], ?DEBUG_LEVEL),
- {'EXCEPTION', #'CosNaming_NamingContext_CannotProceed'{rest_of_name=[N],
- cxt=OE_THIS}}
- end
- end,
- case mnesia:transaction(_RBF) of
- {atomic, {'EXCEPTION', E}} ->
- corba:raise(E);
- {atomic, ok} ->
- {reply, ok, OE_State};
- Other ->
- orber:dbg("[~p] ~p:rebind(~p, ~p);~n"
- "DB transaction returned ~p",
- [?LINE, ?MODULE, N, SubobjKey, Other], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
-rebind(OE_THIS, OE_State, [H|T], Obj) ->
- SubobjKey = corba:get_subobject_key(OE_THIS),
- _RF = ?read_function({orber_CosNaming, SubobjKey}),
- case orber_cosnaming_utils:query_result(mnesia:transaction(_RF)) of
- error ->
- corba:raise(#'CosNaming_NamingContext_CannotProceed'{rest_of_name=[H|T],
- cxt=OE_THIS});
- X ->
- case lists:keysearch(H, 1, X) of
- {value, {H, ncontext, NC}} when is_record(NC, 'IOP_IOR') ->
- {reply, 'CosNaming_NamingContext':rebind(NC, T, Obj), OE_State};
- {value, {H, ncontext, NC}} ->
- rebind(NC, OE_State, T, Obj);
- _ ->
- corba:raise(#'CosNaming_NamingContext_CannotProceed'
- {rest_of_name=[H|T], cxt=OE_THIS})
- end
- end;
-rebind(_OE_THIS, _OE_State, [], _Obj) ->
- orber:dbg("[~p] CosNaming_NamingContextExt:rebind();~n"
- "Invoked this operation with an empty list",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_YES}).
-
-%%----------------------------------------------------------------------
-%% Function : bind_context
-%% Arguments :
-%% Description:
-%% Returns :
-%%----------------------------------------------------------------------
-bind_context(OE_THIS, OE_State, [N], Obj) ->
- SubobjKey = corba:get_subobject_key(OE_THIS),
- _BCF =
- fun() ->
- case mnesia:wread({orber_CosNaming, SubobjKey}) of
- [#orber_CosNaming{nameindex = X}] ->
- case lists:keysearch(N, 1, X) of
- {value, _} ->
- {'EXCEPTION', #'CosNaming_NamingContext_AlreadyBound'{}};
- false ->
- mnesia:write(#orber_CosNaming{name_context=SubobjKey,
- nameindex=
- [{N, ncontext, Obj} | X]})
- end;
- Other ->
- orber:dbg("[~p] ~p:bind_context(~p, ~p);~n"
- "DB access returned ~p",
- [?LINE, ?MODULE, N, SubobjKey, Other], ?DEBUG_LEVEL),
- {'EXCEPTION', #'CosNaming_NamingContext_CannotProceed'{rest_of_name=[N],
- cxt=OE_THIS}}
- end
- end,
- case mnesia:transaction(_BCF) of
- {atomic, {'EXCEPTION', E}} ->
- corba:raise(E);
- {atomic, ok} ->
- {reply, ok, OE_State};
- Other ->
- orber:dbg("[~p] ~p:bind_context(~p, ~p);~n"
- "DB transaction returned ~p",
- [?LINE, ?MODULE, N, SubobjKey, Other], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
-bind_context(OE_THIS, OE_State, [H|T], Obj) ->
- SubobjKey = corba:get_subobject_key(OE_THIS),
- _RF = ?read_function({orber_CosNaming, SubobjKey}),
- case orber_cosnaming_utils:query_result(mnesia:transaction(_RF)) of
- error ->
- corba:raise(#'CosNaming_NamingContext_CannotProceed'{rest_of_name=[H|T],
- cxt=OE_THIS});
- X ->
- case lists:keysearch(H, 1, X) of
- {value, {H, ncontext, NC}} when is_record(NC, 'IOP_IOR') ->
- {reply, 'CosNaming_NamingContext':bind_context(NC, T, Obj),
- OE_State};
- {value, {H, ncontext, NC}} ->
- bind_context(NC, OE_State, T, Obj);
- _ ->
- corba:raise(#'CosNaming_NamingContext_CannotProceed'
- {rest_of_name=[H|T], cxt=OE_THIS})
- end
- end;
-bind_context(_OE_THIS, _OE_State, [], _Obj) ->
- orber:dbg("[~p] CosNaming_NamingContextExt:bind_context();~n"
- "Invoked this operation with an empty list",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_YES}).
-
-%%----------------------------------------------------------------------
-%% Function : rebind_context
-%% Arguments :
-%% Description:
-%% Returns :
-%%----------------------------------------------------------------------
-rebind_context(OE_THIS, OE_State, [N], Obj) ->
- SubobjKey = corba:get_subobject_key(OE_THIS),
- _RBCF =
- fun() ->
- case mnesia:wread({orber_CosNaming, SubobjKey}) of
- [#orber_CosNaming{nameindex = X}] ->
- KList =
- case lists:keysearch(N, 1, X) of
- {value, {N, _, _V}} ->
- lists:keyreplace(N, 1, X, {N, ncontext, Obj});
- false ->
- [{N, ncontext, Obj} | X]
- end,
- mnesia:write(#orber_CosNaming{name_context=SubobjKey,
- nameindex= KList});
- Other ->
- orber:dbg("[~p] ~p:rebind_context(~p, ~p);~n"
- "DB access returned ~p",
- [?LINE, ?MODULE, N, SubobjKey, Other], ?DEBUG_LEVEL),
- {'EXCEPTION', #'CosNaming_NamingContext_CannotProceed'{rest_of_name=[N],
- cxt=OE_THIS}}
- end
- end,
- case mnesia:transaction(_RBCF) of
- {atomic, {'EXCEPTION', E}} ->
- corba:raise(E);
- {atomic, ok} ->
- {reply, ok, OE_State};
- Other ->
- orber:dbg("[~p] ~p:rebind_context(~p, ~p);~n"
- "DB transaction returned ~p",
- [?LINE, ?MODULE, N, SubobjKey, Other], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
-rebind_context(OE_THIS, OE_State, [H|T], Obj) ->
- SubobjKey = corba:get_subobject_key(OE_THIS),
- _RF = ?read_function({orber_CosNaming, SubobjKey}),
- case orber_cosnaming_utils:query_result(mnesia:transaction(_RF)) of
- error ->
- corba:raise(#'CosNaming_NamingContext_CannotProceed'{rest_of_name=[H|T],
- cxt=OE_THIS});
- X ->
- case lists:keysearch(H, 1, X) of
- {value, {H,ncontext, NC}} when is_record(NC, 'IOP_IOR') ->
- {reply, 'CosNaming_NamingContext':rebind_context(NC, T, Obj),
- OE_State};
- {value, {H,ncontext, NC}} ->
- rebind_context(NC, OE_State, T, Obj);
- _ ->
- corba:raise(#'CosNaming_NamingContext_CannotProceed'
- {rest_of_name=[H|T], cxt=OE_THIS})
- end
- end;
-rebind_context(_OE_THIS, _OE_State, [], _Obj) ->
- orber:dbg("[~p] CosNaming_NamingContextExt:rebind_context();~n"
- "Invoked this operation with an empty list",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_YES}).
-
-%%----------------------------------------------------------------------
-%% Function : resolve
-%% Arguments :
-%% Description:
-%% Returns :
-%%----------------------------------------------------------------------
-resolve(OE_THIS, OE_State, [N]) ->
- SubobjKey = corba:get_subobject_key(OE_THIS),
- _RF = ?read_function({orber_CosNaming, SubobjKey}),
- case orber_cosnaming_utils:query_result(mnesia:transaction(_RF)) of
- error ->
- corba:raise(#'CosNaming_NamingContext_CannotProceed'{rest_of_name=[N],
- cxt=OE_THIS});
- X ->
- case lists:keysearch(N, 1, X) of
- {value, {N, _, Value}} ->
- {reply, Value, OE_State};
- false ->
- corba:raise(#'CosNaming_NamingContext_NotFound'
- {rest_of_name=[N], why='not_object'})
- end
- end;
-resolve(OE_THIS, OE_State, [H|T]) ->
- SubobjKey = corba:get_subobject_key(OE_THIS),
- _RF = ?read_function({orber_CosNaming, SubobjKey}),
- case orber_cosnaming_utils:query_result(mnesia:transaction(_RF)) of
- error ->
- corba:raise(#'CosNaming_NamingContext_CannotProceed'{rest_of_name=[H|T],
- cxt=OE_THIS});
- X ->
- case lists:keysearch(H, 1, X) of
- {value, {H, ncontext, NC}} when is_record(NC, 'IOP_IOR') ->
- {reply, 'CosNaming_NamingContext':resolve(NC, T), OE_State};
- {value, {H, ncontext, NC}} ->
- resolve(NC, OE_State, T);
- _ ->
- corba:raise(#'CosNaming_NamingContext_CannotProceed'
- {rest_of_name=[H|T], cxt=OE_THIS})
- end
- end;
-resolve(_OE_THIS, _OE_State, []) ->
- orber:dbg("[~p] CosNaming_NamingContextExt:resolve();~n"
- "Invoked this operation with an empty list",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_YES}).
-
-%%----------------------------------------------------------------------
-%% Function : unbind
-%% Arguments :
-%% Description:
-%% Returns :
-%%----------------------------------------------------------------------
-unbind(OE_THIS, OE_State, [N]) ->
- SubobjKey = corba:get_subobject_key(OE_THIS),
- _UBF =
- fun() ->
- case mnesia:wread({orber_CosNaming, SubobjKey}) of
- [#orber_CosNaming{nameindex = X}] ->
- KList = lists:keydelete(N, 1, X),
- mnesia:write(#orber_CosNaming{name_context=SubobjKey,
- nameindex= KList});
- Other ->
- orber:dbg("[~p] ~p:unbind(~p, ~p);~n"
- "DB transaction returned ~p",
- [?LINE, ?MODULE, N, SubobjKey, Other], ?DEBUG_LEVEL),
- {'EXCEPTION', #'CosNaming_NamingContext_CannotProceed'{rest_of_name=[N],
- cxt=OE_THIS}}
- end
- end,
- case mnesia:transaction(_UBF) of
- {atomic, {'EXCEPTION', E}} ->
- corba:raise(E);
- {atomic, ok} ->
- {reply, ok, OE_State};
- Other ->
- orber:dbg("[~p] ~p:unbind(~p, ~p);~n"
- "DB transaction returned ~p",
- [?LINE, ?MODULE, N, SubobjKey, Other], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
-unbind(OE_THIS, OE_State, [H|T]) ->
- SubobjKey = corba:get_subobject_key(OE_THIS),
- _RF = ?read_function({orber_CosNaming, SubobjKey}),
- case orber_cosnaming_utils:query_result(mnesia:transaction(_RF)) of
- error ->
- corba:raise(#'CosNaming_NamingContext_CannotProceed'{rest_of_name=[H|T],
- cxt=OE_THIS});
- X ->
- case lists:keysearch(H, 1, X) of
- {value, {H, ncontext, NC}} when is_record(NC, 'IOP_IOR') ->
- {reply, 'CosNaming_NamingContext':unbind(NC, T), OE_State};
- {value, {H, ncontext, NC}} ->
- unbind(NC, OE_State, T);
- _ ->
- corba:raise(#'CosNaming_NamingContext_CannotProceed'
- {rest_of_name=[H|T], cxt=OE_THIS})
- end
- end;
-unbind(_OE_THIS, _OE_State, []) ->
- orber:dbg("[~p] CosNaming_NamingContextExt:unbind();~n"
- "Invoked this operation with an empty list",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_YES}).
-
-
-%%----------------------------------------------------------------------
-%% Function : new_context
-%% Arguments :
-%% Description:
-%% Returns :
-%%----------------------------------------------------------------------
-new_context(_OE_THIS, OE_State) ->
- DBKey = term_to_binary({{erlang:system_time(),
- erlang:unique_integer()},
- node()}),
- %% Create a record in the table and set the key to a newly
- {reply,
- 'CosNaming_NamingContextExt':oe_create(DBKey,
- [{pseudo, true}|?CREATE_OPTS]),
- OE_State}.
-
-%%----------------------------------------------------------------------
-%% Function : bind_new_context
-%% Arguments :
-%% Description:
-%% Returns :
-%%----------------------------------------------------------------------
-bind_new_context(OE_THIS, OE_State, N) ->
- DBKey = term_to_binary({{erlang:system_time(),
- erlang:unique_integer()},
- node()}),
- %% Create a record in the table and set the key to a newly
- %% generated objectkey.
- %%?PRINTDEBUG("bind_new_context"),
- NewCtx = 'CosNaming_NamingContextExt':oe_create(DBKey,
- [{pseudo, true}|?CREATE_OPTS]),
- %% Bind the created name context to a name
- case catch bind_context(OE_THIS, OE_State, N, NewCtx) of
- {'EXCEPTION', E} ->
- 'CosNaming_NamingContextExt':destroy(NewCtx),
- corba:raise(E);
- {reply, ok, _} ->
- {reply, NewCtx, OE_State}
- end.
-
-
-%%----------------------------------------------------------------------
-%% Function : list
-%% Arguments :
-%% Description:
-%% Returns :
-%%----------------------------------------------------------------------
-list(OE_THIS, OE_State, HowMany) ->
- SubobjKey = corba:get_subobject_key(OE_THIS),
- _RF = ?read_function({orber_CosNaming, SubobjKey}),
- case orber_cosnaming_utils:query_result(mnesia:transaction(_RF)) of
- error ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO});
- X ->
- case convert_list(X, HowMany, 0, []) of
- {false, List} ->
- {reply, {ok, List, ?ORBER_NIL_OBJREF}, OE_State};
- {true, List, Rest} ->
- %% By setting HowMany to '-1' it will never match
- %% the Counter. Hence, the whole list will be transformed.
- {false, List2} = convert_list(Rest, -1, 0, []),
- BIterator = 'CosNaming_BindingIterator':
- oe_create(List2, ?CREATE_OPTS),
- {reply, {ok, List, BIterator}, OE_State}
- end
- end.
-
-convert_list([], _, _, Acc) ->
- {false, Acc};
-convert_list(Rest, Counter, Counter, Acc) ->
- {true, Acc, Rest};
-convert_list([{N, T, _O}|Rest], HowMany, Counter, Acc) ->
- convert_list(Rest, HowMany, Counter+1,
- [#'CosNaming_Binding'{binding_name=[N],
- binding_type=T}|Acc]).
-
-%%----------------------------------------------------------------------
-%% Function : destroy
-%% Arguments :
-%% Description:
-%% Returns :
-%%----------------------------------------------------------------------
-destroy(OE_THIS, OE_State) ->
- SubobjKey = corba:get_subobject_key(OE_THIS),
- try begin
- true = (byte_size(SubobjKey) < 20),
- undefined = binary_to_term(SubobjKey)
- end
- of
- _ ->
- corba:raise(#'NO_PERMISSION'{completion_status=?COMPLETED_NO})
- catch
- error:_ -> %% Not atom 'undefined', carry on...
- _DF =
- fun() ->
- case mnesia:wread({orber_CosNaming, SubobjKey}) of
- [#orber_CosNaming{nameindex = []}] ->
- mnesia:delete({orber_CosNaming, SubobjKey});
- Other when is_list(Other) ->
- orber:dbg("[~p] ~p:destroy(~p);~n"
- "DB access returned ~p",
- [?LINE, ?MODULE, SubobjKey, Other], ?DEBUG_LEVEL),
- {'EXCEPTION', #'CosNaming_NamingContext_NotEmpty'{}}
- end
- end,
- case mnesia:transaction(_DF) of
- {atomic, {'EXCEPTION', E}} ->
- corba:raise(E);
- {atomic, ok} ->
- {reply, ok, OE_State};
- Other ->
- orber:dbg("[~p] ~p:destroy(~p);~n"
- "DB transaction returned ~p",
- [?LINE, ?MODULE, SubobjKey, Other], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end
- end.
-
-%%----------------------------------------------------------------------
-%% Interface CosNaming::NamingContextExt
-%%----------------------------------------------------------------------
-%%----------------------------------------------------------------------
-%% Function : to_string
-%% Arguments : Name
-%% Description:
-%% Returns : StringName |
-%% {'EXCEPTION', NamingContext::InvalidName{}}
-%%----------------------------------------------------------------------
-to_string(_OE_This, OE_State, Name) ->
- {reply, orber_cosnaming_utils:name2string(Name), OE_State}.
-
-
-%%----------------------------------------------------------------------
-%% Function : to_name
-%% Arguments : StringName
-%% Description:
-%% Returns : Name |
-%% {'EXCEPTION', NamingContext::InvalidName{}}
-%%----------------------------------------------------------------------
-to_name(_OE_This, OE_State, StringName) ->
- {reply, orber_cosnaming_utils:string2name(StringName), OE_State}.
-
-
-%%----------------------------------------------------------------------
-%% Function : to_url
-%% Arguments : Address
-%% StringName
-%% Description:
-%% Returns : URLString |
-%% {'EXCEPTION', NamingContext::InvalidName{}}
-%% {'EXCEPTION', NamingContextExt::InvalidAddress{}}
-%%----------------------------------------------------------------------
-to_url(_, _, "", _) ->
- %% Empty address not allowed.
- corba:raise(#'CosNaming_NamingContextExt_InvalidAddress'{});
-to_url(_OE_This, OE_State, Address, "") ->
- %% Empty stringname => use corbaloc
- orber_cosnaming_utils:check_addresses(Address),
- {reply, "corbaloc:"++orber_cosnaming_utils:escape_string(Address), OE_State};
-to_url(_OE_This, OE_State, Address, StringName) ->
- %% Non-empty stringname => use corbaname
- orber_cosnaming_utils:check_addresses(Address),
- orber_cosnaming_utils:check_name(StringName),
- {reply,
- "corbaname:"++orber_cosnaming_utils:escape_string(Address)++"#"++
- orber_cosnaming_utils:escape_string(StringName),
- OE_State}.
-
-%%----------------------------------------------------------------------
-%% Function : resolve_str
-%% Arguments : StringName
-%% Description:
-%% Returns : Object |
-%% {'EXCEPTION', NamingContext::InvalidName{}}
-%% {'EXCEPTION', NamingContext::NotFound{why, rest_of_name}}
-%% {'EXCEPTION', NamingContext::CannotProceed{cxt, rest_of_name}}
-%%----------------------------------------------------------------------
-resolve_str(OE_This, OE_State, StringName) ->
- Name = orber_cosnaming_utils:string2name(StringName),
- resolve(OE_This, OE_State, Name).
-
-%%======================================================================
-%% Internal functions
-%%======================================================================
-%% Check a write transaction
-write_result({atomic,ok}) -> ok;
-write_result(_What) ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
-
-
-%%----------------------------------------------------------------------
-%% Debugging functions
-%%----------------------------------------------------------------------
-dump() ->
- case catch mnesia:dirty_first('orber_CosNaming') of
- {'EXIT', R} ->
- io:format("Exited with ~p\n",[R]);
- Key ->
- dump_print(Key),
- dump_loop(Key)
- end.
-
-dump_loop(PreviousKey) ->
- case catch mnesia:dirty_next('orber_CosNaming', PreviousKey) of
- {'EXIT', R} ->
- io:format("Exited with ~p\n",[R]);
- '$end_of_table' ->
- ok;
- Key ->
- dump_print(Key),
- dump_loop(Key)
- end.
-
-dump_print(Key) ->
- case catch mnesia:dirty_read({'orber_CosNaming', Key}) of
- {'EXIT', R} ->
- io:format("Exited with ~p\n",[R]);
- [X] ->
- io:format("name_context: ~p\n-----------------------------\n"
- " nameindex structure\n-----------------------------\n~p\n\n",
- [binary_to_term(X#orber_CosNaming.name_context),
- X#orber_CosNaming.nameindex]);
- _ ->
- ok
- end.
-
-%%-------------------------- END OF MODULE -----------------------------
diff --git a/lib/orber/COSS/CosNaming/Makefile b/lib/orber/COSS/CosNaming/Makefile
deleted file mode 100644
index 108663396c..0000000000
--- a/lib/orber/COSS/CosNaming/Makefile
+++ /dev/null
@@ -1,153 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-EBIN=../../ebin
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(ORBER_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/orber-$(VSN)
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES = \
- CosNaming_NamingContextExt_impl \
- CosNaming_BindingIterator_impl \
- lname \
- lname_component \
- orber_cosnaming_utils
-
-ERL_FILES = $(MODULES:%=%.erl)
-HRL_FILES = lname.hrl \
- orber_cosnaming.hrl
-GEN_ERL_FILES = \
- oe_cos_naming.erl \
- CosNaming_Name.erl \
- CosNaming_NamingContext.erl \
- CosNaming_BindingIterator.erl \
- CosNaming_NameComponent.erl \
- CosNaming_Binding.erl \
- CosNaming_BindingList.erl \
- CosNaming_NamingContext_NotFound.erl \
- CosNaming_NamingContext_AlreadyBound.erl \
- CosNaming_NamingContext_CannotProceed.erl \
- CosNaming_NamingContext_InvalidName.erl \
- CosNaming_NamingContext_NotEmpty.erl
-
-GEN_EXT_ERL_FILES = \
- oe_cos_naming_ext.erl \
- CosNaming_NamingContextExt.erl \
- CosNaming_NamingContextExt_InvalidAddress.erl
-
-GEN_HRL_FILES = \
- oe_cos_naming.hrl \
- CosNaming.hrl \
- CosNaming_NamingContext.hrl \
- CosNaming_BindingIterator.hrl
-
-GEN_EXT_HRL_FILES = \
- oe_cos_naming_ext.hrl \
- CosNaming_NamingContextExt.hrl
-
-GEN_FILES = $(GEN_ERL_FILES) $(GEN_HRL_FILES) \
- $(GEN_EXT_ERL_FILES) $(GEN_EXT_HRL_FILES)
-
-TARGET_FILES = \
- $(GEN_EXT_ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR)) \
- $(GEN_ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR)) \
- $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-IDL_FILE = cos_naming.idl \
- cos_naming_ext.idl
-
-APP_FILE =
-#APP_SRC = $(APP_FILE).src
-#APP_TARGET = $(EBIN)/$(APP_FILE)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/orber/ebin
-# The -pa option is just used temporary until erlc can handle
-# includes from other directories than ../include .
-ERL_COMPILE_FLAGS += \
- $(ERL_IDL_FLAGS) \
- -I$(ERL_TOP)/lib/orber/include \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,app_vsn,"orber_$(ORBER_VSN)"}'
-
-YRL_FLAGS =
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-opt: $(TARGET_FILES) $(APP_TARGET)
-
-debug:
- @${MAKE} TYPE=debug
-
-clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) IDL-GENERATED
- rm -f errs core *~
-
-$(APP_TARGET): $(APP_SRC)
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $(APP_SRC) > $(APP_TARGET)
-
-docs:
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-IDL-GENERATED: cos_naming_ext.idl cos_naming.idl
- $(gen_verbose)erlc $(ERL_IDL_FLAGS) +'{this,"CosNaming::NamingContext"}' \
- +'{this,"CosNaming::NamingContextExt"}' cos_naming_ext.idl
- $(V_at)erlc $(ERL_IDL_FLAGS) +'{this,"CosNaming::NamingContext"}' cos_naming.idl
- $(V_at)>IDL-GENERATED
-
-$(GEN_FILES): IDL-GENERATED
-
-$(TARGET_FILES): IDL-GENERATED
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) "$(RELSYSDIR)/ebin"
- $(INSTALL_DIR) "$(RELSYSDIR)/COSS/CosNaming"
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(IDL_FILE) "$(RELSYSDIR)/COSS/CosNaming"
- $(INSTALL_DATA) $(GEN_FILES) "$(RELSYSDIR)/COSS/CosNaming"
-
-
-release_docs_spec:
-
diff --git a/lib/orber/COSS/CosNaming/cos_naming.idl b/lib/orber/COSS/CosNaming/cos_naming.idl
deleted file mode 100644
index 3cd6c99c23..0000000000
--- a/lib/orber/COSS/CosNaming/cos_naming.idl
+++ /dev/null
@@ -1,77 +0,0 @@
-// Naming Service v1.0 described in CORBAservices:
-// Common Object Services Specification, chapter 3
-// OMG IDL for CosNaming Module, p 3-6
-
-#pragma prefix "omg.org"
-
-module CosNaming
-{
- typedef string Istring;
- struct NameComponent {
- Istring id;
- Istring kind;
- };
-
- typedef sequence <NameComponent> Name;
-
- enum BindingType {nobject, ncontext};
-
- struct Binding {
- Name binding_name;
- BindingType binding_type;
- };
-
- typedef sequence <Binding> BindingList;
-
-
- interface BindingIterator;
- interface NamingContext;
-
- interface NamingContext {
-
- enum NotFoundReason { missing_node, not_context, not_object};
-
- exception NotFound {
- NotFoundReason why;
- Name rest_of_name;
- };
-
- exception CannotProceed {
- NamingContext cxt;
- Name rest_of_name;
- };
-
- exception InvalidName{};
- exception AlreadyBound {};
- exception NotEmpty{};
-
- void bind(in Name n, in Object obj)
- raises(NotFound, CannotProceed, InvalidName, AlreadyBound);
- void rebind(in Name n, in Object obj)
- raises(NotFound, CannotProceed, InvalidName);
- void bind_context(in Name n, in NamingContext nc)
- raises(NotFound, CannotProceed,InvalidName, AlreadyBound);
- void rebind_context(in Name n, in NamingContext nc)
- raises(NotFound, CannotProceed, InvalidName);
- Object resolve (in Name n)
- raises(NotFound, CannotProceed, InvalidName);
- void unbind(in Name n)
- raises(NotFound, CannotProceed, InvalidName);
- NamingContext new_context();
- NamingContext bind_new_context(in Name n)
- raises(NotFound, AlreadyBound, CannotProceed, InvalidName);
- void destroy( )
- raises(NotEmpty);
- void list (in unsigned long how_many,
- out BindingList bl,
- out BindingIterator bi);
- };
-
- interface BindingIterator {
- boolean next_one(out Binding b);
- boolean next_n(in unsigned long how_many,
- out BindingList bl);
- void destroy();
- };
-};
-
diff --git a/lib/orber/COSS/CosNaming/cos_naming_ext.idl b/lib/orber/COSS/CosNaming/cos_naming_ext.idl
deleted file mode 100644
index 8099a0005c..0000000000
--- a/lib/orber/COSS/CosNaming/cos_naming_ext.idl
+++ /dev/null
@@ -1,37 +0,0 @@
-// Naming Service v1.0 described in CORBAservices:
-// Common Object Services Specification, chapter 3
-// OMG IDL for CosNaming Module, p 3-6
-
-#ifndef _COSNAMINGEXT_IDL_
-#define _COSNAMINGEXT_IDL_
-
-
-#include<cos_naming.idl>
-
-#pragma prefix "omg.org"
-
-module CosNaming
-{
- interface NamingContextExt:NamingContext {
-
- typedef string StringName;
- typedef string Address;
- typedef string URLString;
-
- StringName to_string(in Name n)
- raises(InvalidName);
-
- Name to_name(in StringName sn)
- raises(InvalidName);
-
- exception InvalidAddress{};
-
- URLString to_url(in Address addr,in StringName sn)
- raises(InvalidAddress, InvalidName);
-
- Object resolve_str(in StringName n)
- raises(NotFound, CannotProceed, InvalidName);
- };
-};
-
-#endif//_COSNAMINGEXT_IDL_
diff --git a/lib/orber/COSS/CosNaming/lname.erl b/lib/orber/COSS/CosNaming/lname.erl
deleted file mode 100644
index 41f9f68d20..0000000000
--- a/lib/orber/COSS/CosNaming/lname.erl
+++ /dev/null
@@ -1,134 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: lname.erl
-%%-----------------------------------------------------------------
--module(lname).
-
--include_lib("orber/include/corba.hrl").
--include("CosNaming.hrl").
--include("lname.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([create/0, insert_component/3, get_component/2, delete_component/2,
- num_component/1, equal/2, less_than/2,
- to_idl_form/1, from_idl_form/1, check_name/1, new/1]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%% DEBUG INFO
--define(DEBUG_LEVEL, 5).
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-create() ->
- [].
-
-insert_component(_, I, _) when I < 1->
- corba:raise(#'LName_NoComponent'{});
-insert_component([], I, _) when I > 1->
- corba:raise(#'LName_NoComponent'{});
-insert_component(Name, 1, Component) when is_record(Component,
- 'CosNaming_NameComponent') ->
- [Component |Name];
-insert_component([H|T], I, Component) when is_record(Component,
- 'CosNaming_NameComponent') ->
- [H |insert_component(T, I-1, Component)];
-insert_component(_, _, Component) ->
- orber:dbg("[~p] ~p:insert_component(~p); Not a NameComponent.~n",
- [?LINE, ?MODULE, Component], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-get_component(_, I) when I < 1->
- corba:raise(#'LName_NoComponent'{});
-get_component([], _) ->
- corba:raise(#'LName_NoComponent'{});
-get_component([H|_T], 1) ->
- H;
-get_component([_|T], I) ->
- get_component(T, I-1).
-
-delete_component(_, I) when I < 1->
- corba:raise(#'LName_NoComponent'{});
-delete_component([], _) ->
- corba:raise(#'LName_NoComponent'{});
-delete_component([_|T], 1) ->
- T;
-delete_component([H|T], I) ->
- [H | delete_component(T, I-1)].
-
-num_component(Name) ->
- num_component(Name, 0).
-
-equal(Name, N) ->
- N == Name.
-
-less_than(Name, N) ->
- Name < N.
-
-to_idl_form(Name) ->
- case check_name(Name) of
- false ->
- corba:raise(#'LName_InvalidName'{});
- true ->
- Name
- end.
-
-from_idl_form(Name) ->
- Name.
-
-%%destroy() -> % not needed in erlang
-%% ok.
-
-%%-----------------------------------------------------------------
-%% External Functions not in the CosNaming standard
-%%-----------------------------------------------------------------
-new([]) ->
- [];
-new([{Id, Kind} | List]) ->
- [lname_component:new(Id, Kind) | new(List)];
-new([Id |List]) when is_list(Id) ->
- [lname_component:new(Id) | new(List)].
-
-%%-----------------------------------------------------------------
-%% Internal Functions
-%%-----------------------------------------------------------------
-num_component([], N) ->
- N;
-num_component([_|T], N) ->
- num_component(T, N+1).
-
-check_name([]) ->
- true;
-check_name([H|T]) ->
- case catch lname_component:get_id(H) of
- {'EXCEPTION', _E} ->
- false;
- _ ->
- check_name(T)
- end.
diff --git a/lib/orber/COSS/CosNaming/lname.hrl b/lib/orber/COSS/CosNaming/lname.hrl
deleted file mode 100644
index 0c0eef86ab..0000000000
--- a/lib/orber/COSS/CosNaming/lname.hrl
+++ /dev/null
@@ -1,34 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: lname.hrl
-%%-----------------------------------------------------------------
-
-%% LName interface exceptions
--record('LName_NoComponent', {'OE_ID'="PIDL:LName/NoComponent:1.0"}).
--record('LName_InvalidName', {'OE_ID'="PIDL:LName/InvalidName:1.0"}).
-% This exception is not used in our implementation.
--record('LName_Overflow', {'OE_ID'="PIDL:LName/Overflow:1.0"}).
-
-%% LNameComponent interface exceptions
--record('LNameComponent_NotSet',
- {'OE_ID'="PIDL:LNameComponent/NotSet:1.0"}).
diff --git a/lib/orber/COSS/CosNaming/lname_component.erl b/lib/orber/COSS/CosNaming/lname_component.erl
deleted file mode 100644
index 4dead49a78..0000000000
--- a/lib/orber/COSS/CosNaming/lname_component.erl
+++ /dev/null
@@ -1,84 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: lname_component.erl
-%%-----------------------------------------------------------------
--module(lname_component).
-
--include_lib("orber/include/corba.hrl").
--include("lname.hrl").
--include("CosNaming.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([get_id/1, set_id/2, get_kind/1, set_kind/2, create/0, new/1, new/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-create() ->
- #'CosNaming_NameComponent'{id="", kind=""}.
-
-get_id(NC) when is_record(NC, 'CosNaming_NameComponent'),
- NC#'CosNaming_NameComponent'.id == undefined ->
- corba:raise(#'LNameComponent_NotSet'{});
-get_id(NC) when is_record(NC, 'CosNaming_NameComponent'),
- NC#'CosNaming_NameComponent'.id == "" ->
- corba:raise(#'LNameComponent_NotSet'{});
-get_id(NC) when is_record(NC, 'CosNaming_NameComponent') ->
- NC#'CosNaming_NameComponent'.id.
-
-set_id(NC, Id) when is_record(NC, 'CosNaming_NameComponent') andalso is_list(Id)->
- NC#'CosNaming_NameComponent'{id=Id}.
-
-get_kind(NC) when is_record(NC, 'CosNaming_NameComponent') andalso
- NC#'CosNaming_NameComponent'.kind == undefined ->
- corba:raise(#'LNameComponent_NotSet'{});
-get_kind(NC) when is_record(NC, 'CosNaming_NameComponent') andalso
- NC#'CosNaming_NameComponent'.kind == "" ->
- corba:raise(#'LNameComponent_NotSet'{});
-get_kind(NC) when is_record(NC, 'CosNaming_NameComponent') ->
- NC#'CosNaming_NameComponent'.kind.
-
-set_kind(NC, Kind) when is_record(NC, 'CosNaming_NameComponent') andalso is_list(Kind) ->
- NC#'CosNaming_NameComponent'{kind=Kind}.
-
-%%destroy() -> % not needed in erlang
-%% true.
-
-%%-----------------------------------------------------------------
-%% External Functions not in the CosNaming standard
-%%-----------------------------------------------------------------
-new(Id) when is_list(Id) ->
- #'CosNaming_NameComponent'{id=Id, kind=""}.
-new(Id, Kind) when is_list(Id) andalso is_list(Kind) ->
- #'CosNaming_NameComponent'{id=Id, kind=Kind}.
-
-%%-----------------------------------------------------------------
-%% Internal Functions
-%%-----------------------------------------------------------------
diff --git a/lib/orber/COSS/CosNaming/orber_cosnaming.hrl b/lib/orber/COSS/CosNaming/orber_cosnaming.hrl
deleted file mode 100644
index 2950f7a11f..0000000000
--- a/lib/orber/COSS/CosNaming/orber_cosnaming.hrl
+++ /dev/null
@@ -1,64 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%--------------------------------------------------------------------
-
--ifndef(ORBER_COSNAMING_HRL).
--define(ORBER_COSNAMING_HRL, true).
-
-%%-----------------------------------------------------------------
-%% Mnesia Table definition record
-%%-----------------------------------------------------------------
--record('orber_CosNaming', {name_context, nameindex}).
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
-
--define(CREATE_OPTS, [{no_security, orber:partial_security()}]).
-
-%%-define(dirty_query_context, true).
-
-%% This macro returns a read fun suitable for evaluation in a transaction
--define(read_function(Objkey),
- fun() ->
- mnesia:read(Objkey)
- end).
-
-%% This macro returns a write fun suitable for evaluation in a transaction
--define(write_function(R),
- fun() ->
- mnesia:write(R)
- end).
-
-%% This macro returns a delete fun suitable for evaluation in a transaction
--define(delete_function(R),
- fun() ->
- mnesia:delete(R)
- end).
-
--ifdef(dirty_query_context).
--define(query_check(Q_res), Q_res).
--else.
--define(query_check(Q_res), {atomic, Q_res}).
--endif.
-
--endif.
diff --git a/lib/orber/COSS/CosNaming/orber_cosnaming_utils.erl b/lib/orber/COSS/CosNaming/orber_cosnaming_utils.erl
deleted file mode 100644
index c21e46036b..0000000000
--- a/lib/orber/COSS/CosNaming/orber_cosnaming_utils.erl
+++ /dev/null
@@ -1,762 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_cosnaming_utils.erl
-%% Modified:
-%%
-%%-----------------------------------------------------------------
--module(orber_cosnaming_utils).
-
--include("orber_cosnaming.hrl").
--include("CosNaming.hrl").
--include("CosNaming_NamingContext.hrl").
--include("CosNaming_NamingContextExt.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([query_result/1]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([addresses/1, name/1,
- check_addresses/1, check_name/1,
- key/1, select_type/1, lookup/1, lookup/2,
- escape_string/1, unescape_string/1,
- name2string/1, string2name/1]).
-
-%%-----------------------------------------------------------------
-%% Records
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% Defines
-%%-----------------------------------------------------------------
-%% DEFAULT VALUES:
-%%
-%% IIOP:
-%% - port: 2809
-%% - iiop version: 1.0
--define(DEF_VERS, {1,0}).
--define(DEF_PORT, 2809).
--define(DEF_KEY, "NameService").
--define(HTTP_DEF_PORT, 80).
-
-%% DEBUG INFO
--define(DEBUG_LEVEL, 5).
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-%% Check a read transaction
-query_result({atomic, Qres}) ->
- case Qres of
- [Hres] ->
- Hres#orber_CosNaming.nameindex;
- [Hres|Tres] ->
- orber:dbg("[~p] orber_cosnaming_utils:query_result(~p);~n"
- "Multiple Hits: ~p", [?LINE, Qres, [Hres|Tres]], ?DEBUG_LEVEL),
- error;
- [] ->
- orber:dbg("[~p] orber_cosnaming_utils:query_result();~n"
- "No hit", [?LINE], ?DEBUG_LEVEL),
- error;
- Other ->
- orber:dbg("[~p] orber_cosnaming_utils:query_result(~p);~n"
- "Mnesia Access Failed ~p", [?LINE, Qres, Other], ?DEBUG_LEVEL),
- error
- end;
-query_result({aborted, Qres}) ->
- orber:dbg("[~p] orber_cosnaming_utils:query_result(~p);~n"
- "Mnesia Access Aborted", [?LINE, Qres], ?DEBUG_LEVEL),
- error;
-query_result(What) ->
- orber:dbg("[~p] orber_cosnaming_utils:query_result(~p);~n"
- "Mnesia Access Failed", [?LINE, What], ?DEBUG_LEVEL),
- error.
-
-
-%%----------------------------------------------------------------------
-%% Function : check_addresses
-%% Arguments :
-%% Description:
-%% Returns :
-%%----------------------------------------------------------------------
-check_addresses(Str) ->
- {_, Rest2} = addresses(Str),
- case key(Rest2) of
- {_, []} ->
- ok;
- What ->
- orber:dbg("[~p] orber_cosnaming_utils:check_addresses(~p);~n"
- "Key ~p", [?LINE, Str, What], ?DEBUG_LEVEL),
- corba:raise(#'CosNaming_NamingContextExt_InvalidAddress'{})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : check_name
-%% Arguments :
-%% Description:
-%% Returns :
-%%----------------------------------------------------------------------
-check_name(Str) ->
- name(Str).
-
-%%----------------------------------------------------------------------
-%% Function : select_type
-%% Arguments : A corbaloc/corbaname-string.
-%% Description:
-%% Returns : A tuple which contain data about what connection we want to use |
-%% {'EXCEPTION', #'CosNaming_NamingContextExt_InvalidAddress'{}}
-%%----------------------------------------------------------------------
-select_type([$c, $o, $r, $b, $a, $l, $o, $c, $:|Rest1]) ->
- {Addresses, Rest2} = addresses(Rest1),
- case key(Rest2) of
- {Key, []} ->
- {corbaloc, Addresses, Key};
- What ->
- orber:dbg("[~p] orber_cosnaming_utils:select_type(~p);~n"
- "Key ~p", [?LINE, Rest1, What], ?DEBUG_LEVEL),
- corba:raise(#'CosNaming_NamingContextExt_InvalidAddress'{})
- end;
-select_type([$c, $o, $r, $b, $a, $n, $a, $m, $e, $:|Rest1]) ->
- {Addresses, Rest2} = addresses(Rest1),
- {Key, Rest3} = key(Rest2),
- Name = name(Rest3),
- {corbaname, Addresses, Key, string2name(Name)};
-
-select_type([$f, $i, $l, $e, $:, $/ |Rest]) ->
- file(Rest);
-select_type([$f, $t, $p, $:, $/, $/ |Rest]) ->
- ftp(Rest);
-select_type([$h, $t, $t, $p, $:, $/, $/ |Rest]) ->
- http(Rest);
-
-select_type(What) ->
- orber:dbg("[~p] orber_cosnaming_utils:select_type(~p);~n"
- "Malformed or unsupported type.",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'CosNaming_NamingContextExt_InvalidAddress'{}).
-
-
-%%----------------------------------------------------------------------
-%% Function : addresses
-%% Arguments : A corbaloc string.
-%% Description:
-%% Returns : A list of addresses an the remaining part possibly containg
-%% a Key and a stringified Name
-%%----------------------------------------------------------------------
-addresses(Str) ->
- addresses(address(protocol, Str, [], []), []).
-
-addresses({false, rir, Rest}, []) ->
- {rir, Rest};
-addresses({false, Adr, Rest}, Addresses) ->
- {lists:reverse([Adr|Addresses]), Rest};
-addresses({true, Adr, Rest}, Addresses) ->
- addresses(address(protocol, Rest, [], []), [Adr|Addresses]).
-%% Which protocol.
-address(protocol, [$:|T], [], []) ->
- address(version, T, [], [iiop]);
-address(protocol, [$i, $i, $o, $p, $:|T], [], []) ->
- address(version, T, [], [iiop]);
-address(protocol, [$s,$s,$l, $i, $o, $p, $:|T], [], []) ->
- address(version, T, [], [ssliop]);
-address(protocol, [$r, $i, $r, $:|T], [], []) ->
- {false, rir, T};
-address(protocol, What, _, _) ->
- orber:dbg("[~p] orber_cosnaming_utils:address(~p);~n"
- "Malformed or unsupported protocol.",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'CosNaming_NamingContextExt_InvalidAddress'{});
-
-
-%% Parsed one address, no version found or port found.
-address(version, [$,|T], Acc, Previous) ->
- {true, lists:reverse([?DEF_PORT, lists:reverse(Acc), ?DEF_VERS|Previous]), T};
-address(version, [$/|T], Acc, Previous) ->
- {false, lists:reverse([?DEF_PORT, lists:reverse(Acc), ?DEF_VERS|Previous]), T};
-%% Found iiop version.
-address(version, [$@|T], Acc, Previous) ->
- case Acc of
- [Minor, $., Major] ->
- address(address, T, [], [{Major-$0, Minor-$0}|Previous]);
- What ->
- orber:dbg("[~p] orber_cosnaming_utils:address(~p);~n"
- "Malformed or unsupported version.",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'CosNaming_NamingContextExt_InvalidAddress'{})
- end;
-
-%% Found no iiop version, switch to ipv6.
-address(version, [$[|T], [], Previous) ->
- address(ipv6, T, [], [?DEF_VERS|Previous]);
-
-%% Found no iiop version, switch to port. In this case Acc contains the
-%% Host.
-address(version, [$:|T], Acc, Previous) ->
- address(port, T, [], [lists:reverse(Acc), ?DEF_VERS|Previous]);
-
-%% Found IPv6
-address(address, [$[|T], [], Previous) ->
- address(ipv6, T, [], Previous);
-
-%% Found port
-address(address, [$:|T], Acc, Previous) ->
- address(port, T, [], [lists:reverse(Acc)|Previous]);
-
-address(ipv6, [$]|T], Acc, Previous) ->
- address(address, T, Acc, Previous);
-
-%% Parsed one address, port not found.
-address(address, [$,|T], [], Previous) ->
- {true, lists:reverse([?DEF_PORT|Previous]), T};
-address(address, [$/|T], [], Previous) ->
- {false, lists:reverse([?DEF_PORT|Previous]), T};
-address(address, [$,|T], Acc, Previous) ->
- {true, lists:reverse([?DEF_PORT, lists:reverse(Acc)|Previous]), T};
-address(address, [$/|T], Acc, Previous) ->
- {false, lists:reverse([?DEF_PORT, lists:reverse(Acc)|Previous]), T};
-
-%% Parsed one address.
-address(port, [$/|T], Acc, Previous) ->
- case catch list_to_integer(lists:reverse(Acc)) of
- Port when is_integer(Port) ->
- {false, lists:reverse([Port|Previous]), T};
- What ->
- orber:dbg("[~p] orber_cosnaming_utils:address(~p);~n"
- "Malformed port.", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'CosNaming_NamingContextExt_InvalidAddress'{})
- end;
-address(port, [$,|T], Acc, Previous) ->
- case catch list_to_integer(lists:reverse(Acc)) of
- Port when is_integer(Port) ->
- {true, lists:reverse([Port|Previous]), T};
- What ->
- orber:dbg("[~p] orber_cosnaming_utils:address(~p);~n"
- "Malformed port.", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'CosNaming_NamingContextExt_InvalidAddress'{})
- end;
-
-%% EOS, check how far we have reached so far and add necessary default values.
-address(version, [], Acc, Previous) ->
- {false, lists:reverse([?DEF_PORT, lists:reverse(Acc), ?DEF_VERS|Previous]), []};
-address(port, [], [], Previous) ->
- {false, lists:reverse([?DEF_PORT|Previous]), []};
-address(port, [], Acc, Previous) ->
- case catch list_to_integer(lists:reverse(Acc)) of
- Port when is_integer(Port) ->
- {false, lists:reverse([Port|Previous]), []};
- What ->
- orber:dbg("[~p] orber_cosnaming_utils:address(~p);~n"
- "Malformed port.", [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'CosNaming_NamingContextExt_InvalidAddress'{})
- end;
-address(address, [], [], Previous) ->
- {false, lists:reverse([?DEF_PORT|Previous]), []};
-address(address, [], Acc, Previous) ->
- {false, lists:reverse([?DEF_PORT, lists:reverse(Acc)|Previous]), []};
-
-address(Type, [H|T], Acc, Previous) ->
- address(Type, T, [H|Acc], Previous).
-
-%%----------------------------------------------------------------------
-%% Function : key
-%% Arguments : A string which contain a Key we want to use and, if defined,
-%% stringified NameComponent sequence.
-%% Description:
-%% Returns : The Key and the remaining part, i.e., a stringified
-%% NameComponent sequence.
-%%----------------------------------------------------------------------
-key(Str) ->
- key(Str, []).
-key([], []) ->
- {?DEF_KEY, []};
-key([], Acc) ->
- {lists:reverse(Acc), []};
-key([$#|T], []) ->
- {?DEF_KEY, T};
-key([$#|T], Acc) ->
- {lists:reverse(Acc), T};
-key([$/|T], []) ->
- key(T, []);
-key([H|T], Acc) ->
- key(T, [H|Acc]).
-
-%%----------------------------------------------------------------------
-%% Function : name
-%% Arguments : A string describing a NameComponent sequence.
-%% Description:
-%% Returns : The input string |
-%% {'EXCEPTION', #'CosNaming_NamingContext_InvalidName'{}}
-%%----------------------------------------------------------------------
-name(Str) ->
- name(Str, []).
-name([], Acc) ->
- lists:reverse(Acc);
-name([$., $/|_T], _) ->
- corba:raise(#'CosNaming_NamingContext_InvalidName'{});
-name([$/, $/|_T], _) ->
- corba:raise(#'CosNaming_NamingContext_InvalidName'{});
-name([$/|T], []) ->
- name(T, []);
-name([H|T], Acc) ->
- name(T, [H|Acc]).
-
-
-%%----------------------------------------------------------------------
-%% Function : file
-%% Arguments : A string describing connection parameters.
-%% Description:
-%% Returns : A tuple consisting of data extracted from the given string.
-%%----------------------------------------------------------------------
-file(File) ->
- {file, File}.
-
-%%----------------------------------------------------------------------
-%% Function : ftp
-%% Arguments : A string describing connection parameters.
-%% Description:
-%% Returns : A tuple consisting of data extracted from the given string.
-%%----------------------------------------------------------------------
-ftp(Address) ->
- %% Perhaps we should run some checks here?
- {ftp, Address}.
-
-%%----------------------------------------------------------------------
-%% Function : http
-%% Arguments : A string describing connection parameters.
-%% Description:
-%% Returns : A tuple consisting of data extracted from the given string.
-%%----------------------------------------------------------------------
-http(Address) ->
- case string:tokens(Address, ":") of
- [Host, Rest] ->
- %% At his stage we know that address contains a Port number.
- {Port, Key} = split_to_slash(Rest, []),
- case catch list_to_integer(Port) of
- PortInt when is_integer(PortInt) ->
- {http, Host, PortInt, Key};
- _ ->
- orber:dbg("[~p] orber_cosnaming_utils:http(~p);~n"
- "Malformed key; should be http://Host:Port/path/name.html~n"
- "or http://Host/path/name.html",
- [?LINE, Address], ?DEBUG_LEVEL),
- corba:raise(#'CosNaming_NamingContextExt_InvalidAddress'{})
- end;
- [Address] ->
- %% Use default port
- {Host, Key} = split_to_slash(Address, []),
- {http, Host, ?HTTP_DEF_PORT, Key};
- _What ->
- orber:dbg("[~p] orber_cosnaming_utils:http(~p);~n"
- "Malformed key; should be http://Host:Port/path/name.html~n"
- "or http://Host/path/name.html",
- [?LINE, Address], ?DEBUG_LEVEL),
- corba:raise(#'CosNaming_NamingContextExt_InvalidAddress'{})
- end.
-
-split_to_slash([], _Acc) ->
- orber:dbg("[~p] orber_cosnaming_utils:split_to_slash();~n"
- "No Key given Host:Port/Key.html", [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'CosNaming_NamingContextExt_InvalidAddress'{});
-split_to_slash([$/|Rest], Acc) ->
- {lists:reverse(Acc), [$/|Rest]};
-split_to_slash([H|T], Acc) ->
- split_to_slash(T, [H|Acc]).
-
-%%----------------------------------------------------------------------
-%% Function : lookup
-%% Arguments : A tuple which contain data about what connection we want to use.
-%% Description:
-%% Returns : Object |
-%% {'EXCEPTION', E}
-%%----------------------------------------------------------------------
-lookup(Data) ->
- lookup(Data, []).
-
-lookup({corbaname, rir, _Key, []}, Ctx) ->
- %% If no object key supplied NameService is defined to be default.
- corba:resolve_initial_references("NameService", Ctx);
-lookup({corbaname, rir, Key, Name}, Ctx) ->
- NS = corba:resolve_initial_references(Key, Ctx),
- 'CosNaming_NamingContext':resolve(NS, Ctx, Name);
-
-lookup({corbaloc, rir, Key}, Ctx) ->
- corba:resolve_initial_references(Key, Ctx);
-
-lookup({corbaname, [], _Key, _Name}, _Ctx) ->
- corba:raise(#'CosNaming_NamingContextExt_InvalidAddress'{});
-lookup({corbaname, Addresses, Key, ""}, Ctx) ->
- %% Not Name-string defined, which is the same as corbaloc.
- lookup({corbaloc, Addresses, Key}, Ctx);
-lookup({corbaname, [[iiop, Vers, Host, Port]|Addresses], Key, Name}, Ctx) ->
- NS = iop_ior:create_external(Vers, key2id(Key), Host, Port, Key),
- case catch 'CosNaming_NamingContext':resolve(NS, Ctx, Name) of
- {'EXCEPTION', _} ->
- lookup({corbaname, Addresses, Key, Name}, Ctx);
- Obj ->
- Obj
- end;
-%%% Corbaname via SSL
-lookup({corbaname, [[ssliop, Vers, Host, Port]|Addresses], Key, Name}, Ctx) ->
- SSLComponent =
- #'IOP_TaggedComponent'{tag=?TAG_SSL_SEC_TRANS,
- component_data=#'SSLIOP_SSL'{target_supports = 2,
- target_requires = 2,
- port = Port}},
- NS = iop_ior:create_external(Vers, key2id(Key), Host, Port, Key, [SSLComponent]),
- case catch 'CosNaming_NamingContext':resolve(NS, Ctx, Name) of
- {'EXCEPTION', _} ->
- lookup({corbaname, Addresses, Key, Name}, Ctx);
- Obj ->
- Obj
- end;
-lookup({corbaname, [_|Addresses], Key, Name}, Ctx) ->
- lookup({corbaname, Addresses, Key, Name}, Ctx);
-
-lookup({corbaloc, [], _Key}, _Ctx) ->
- corba:raise(#'CosNaming_NamingContextExt_InvalidAddress'{});
-lookup({corbaloc, [[iiop, Vers, Host, Port]|Addresses], Key}, Ctx) ->
- ObjRef = iop_ior:create_external(Vers, key2id(Key), Host, Port, Key),
- OldVal = put(orber_forward_notify, true),
- case catch corba_object:non_existent(ObjRef, Ctx) of
- {location_forward, Result} ->
- put(orber_forward_notify, OldVal),
- Result;
- false ->
- put(orber_forward_notify, OldVal),
- ObjRef;
- true ->
- put(orber_forward_notify, OldVal),
- lookup({corbaloc, Addresses, Key}, Ctx);
- _ ->
- %% May be located on a version using '_not_existent'
- %% see CORBA2.3.1 page 15-34 try again.
- case catch corba_object:not_existent(ObjRef, Ctx) of
- {location_forward, Result} ->
- put(orber_forward_notify, OldVal),
- Result;
- false ->
- put(orber_forward_notify, OldVal),
- ObjRef;
- _ ->
- put(orber_forward_notify, OldVal),
- lookup({corbaloc, Addresses, Key}, Ctx)
- end
- end;
-
-%%% Corbaloc via SSL
-lookup({corbaloc, [[ssliop, Vers, Host, Port]|Addresses], Key}, Ctx) ->
- SSLComponent =
- #'IOP_TaggedComponent'{tag=?TAG_SSL_SEC_TRANS,
- component_data=#'SSLIOP_SSL'{target_supports = 2,
- target_requires = 2,
- port = Port}},
- ObjRef = iop_ior:create_external(Vers, key2id(Key), Host, Port, Key, [SSLComponent]),
- OldVal = put(orber_forward_notify, true),
-
- case catch corba_object:non_existent(ObjRef, Ctx) of
- {location_forward, Result} ->
- put(orber_forward_notify, OldVal),
- Result;
- false ->
- put(orber_forward_notify, OldVal),
- ObjRef;
- true ->
- put(orber_forward_notify, OldVal),
- lookup({corbaloc, Addresses, Key}, Ctx);
- _ ->
- %% May be located on a version using '_not_existent'
- %% see CORBA2.3.1 page 15-34 try again.
- case catch corba_object:not_existent(ObjRef, Ctx) of
- {location_forward, Result} ->
- put(orber_forward_notify, OldVal),
- Result;
- false ->
- put(orber_forward_notify, OldVal),
- ObjRef;
- _ ->
- put(orber_forward_notify, OldVal),
- lookup({corbaloc, Addresses, Key}, Ctx)
- end
- end;
-
-lookup({corbaloc, [_|Addresses], Key}, Ctx) ->
- lookup({corbaloc, Addresses, Key}, Ctx);
-
-
-lookup({file, File}, _Ctx) ->
- case file:read_file(File) of
- {ok, IOR} ->
- binary_to_list(IOR);
- {error, Reason} ->
- orber:dbg("[~p] orber_cosnaming_utils:lookup(~p);~n"
- "Failed to access file: ~p.",
- [?LINE, File, Reason], ?DEBUG_LEVEL),
- corba:raise(#'CosNaming_NamingContext_InvalidName'{})
- end;
-lookup({http, Host, Port, Key}, _Ctx) ->
- SetupTimeout = orber:iiop_setup_connection_timeout(),
- SendTimeout = orber:iiop_timeout(),
- {ok, Socket} = create_connection(Host, Port, SetupTimeout),
- Request = "GET " ++ Key ++ " HTTP/1.0\r\n\r\n",
- case gen_tcp:send(Socket, Request) of
- ok ->
- receive_msg(Socket, [], SendTimeout);
- {error, Reason} ->
- orber:dbg("[~p] orber_cosnaming_utils:lookup();~n"
- "Failed to send request: ~p.",
- [?LINE, Reason], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO})
- end;
-lookup({ftp, _Address}, _Ctx) ->
- corba:raise(#'CosNaming_NamingContextExt_InvalidAddress'{});
-lookup(_, _Ctx) ->
- corba:raise(#'CosNaming_NamingContextExt_InvalidAddress'{}).
-
-
-receive_msg(Socket, Acc, Timeout) ->
- receive
- {tcp_closed, Socket} ->
- case re:split(Acc,"\r\n\r\n",[{return,list}]) of
- [_Header, Body] ->
- Body;
- What ->
- orber:dbg("[~p] orber_cosnaming_utils:receive_msg();~n"
- "HTTP server closed the connection before sending a complete reply: ~p.",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO})
- end;
- {tcp, Socket, Response} ->
- receive_msg(Socket, Acc ++ Response, Timeout);
- {tcp_error, Socket, Reason} ->
- orber:dbg("[~p] orber_cosnaming_utils:receive_msg();~n"
- "connection failed: ~p.",
- [?LINE, Reason], ?DEBUG_LEVEL),
- gen_tcp:close(Socket),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO})
- after Timeout ->
- gen_tcp:close(Socket),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO})
- end.
-
-create_connection(Host, Port, Timeout) ->
- case gen_tcp:connect(Host,Port,[{packet,0},{reuseaddr,true}], Timeout) of
- {ok,Socket} ->
- {ok,Socket};
- Error ->
- orber:dbg("[~p] orber_cosnaming_utils:create_connection(~p, ~p, ~p);~n"
- "Reason: ~p",
- [?LINE, Host, Port, Timeout, Error], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : key2id
-%% Arguments : An objectkey (e.g. NameService)
-%% Description:
-%% Returns : The associated IFR-id
-%%----------------------------------------------------------------------
-key2id(Key) ->
- %% We need this test to avoid returning an exit if an XX:typeID()
- %% fails (e.g. the module doesn't exist).
- case catch key2id_helper(Key) of
- {ok, Id} ->
- Id;
- _ ->
- ""
- end.
-
-
-key2id_helper("NameService") ->
- {ok, 'CosNaming_NamingContext':typeID()};
-key2id_helper("RootPOA") ->
- {ok, "IDL:omg.org/PortableServer/POA:1.0"};
-key2id_helper("POACurrent") ->
- {ok, "IDL:omg.org/PortableServer/Current:1.0"};
-key2id_helper("InterfaceRepository") ->
- {ok, "IDL:omg.org/CORBA/Repository:1.0"};
-key2id_helper("TradingService") ->
- {ok, "IDL:omg.org/CosTrading/Lookup:1.0"};
-key2id_helper("TransactionCurrent") ->
- {ok, "IDL:omg.org/CosTransactions/Current:1.0"};
-key2id_helper("DynAnyFactory") ->
- {ok, "IDL:omg.org/DynamicAny/DynAnyFactory:1.0"};
-key2id_helper("ORBPolicyManager") ->
- {ok, "IDL:omg.org/CORBA/PolicyManager:1.0"};
-key2id_helper("PolicyCurrent") ->
- {ok, "IDL:omg.org/CORBA/PolicyCurrent:1.0"};
-key2id_helper("NotificationService") ->
- {ok, "IDL:omg.org/CosNotifyChannelAdmin/EventChannelFactory:1.0"};
-key2id_helper("TypedNotificationService") ->
- {ok, "IDL:omg.org/CosTypedNotifyChannelAdmin::TypedEventChannelFactory:1.0"};
-key2id_helper("CodecFactory") ->
- {ok, "IDL:omg.org/IOP/CodecFactory:1.0"};
-key2id_helper("PICurrent") ->
- {ok, "IDL:omg.org/PortableInterceptors/Current:1.0"};
-%% Should we use SecurityLevel1 instead?? This key can be either.
-key2id_helper("SecurityCurrent") ->
- {ok, "IDL:omg.org/SecurityLevel2/Current:1.0"};
-%% Unknown - use the empty string. Might not work for all other ORB's but it's
-%% the only option we've got.
-key2id_helper(_) ->
- {ok, ""}.
-
-
-
-%%----------------------------------------------------------------------
-%% Function : name2string
-%% Arguments : A sequence of NameComponents
-%% Description:
-%% Returns : A string describing the sequence.
-%%----------------------------------------------------------------------
-name2string(Name) ->
- name2string(lists:reverse(Name), []).
-name2string([], Acc) ->
- lists:flatten(Acc);
-name2string([#'CosNaming_NameComponent'{id="", kind=""}], Acc) ->
- name2string([], [$.|Acc]);
-name2string([#'CosNaming_NameComponent'{id=ID, kind=""}], Acc) ->
- name2string([], [convert_reserved(ID)|Acc]);
-name2string([#'CosNaming_NameComponent'{id=ID, kind=Kind}], Acc) ->
- name2string([], [convert_reserved(ID), $., convert_reserved(Kind)|Acc]);
-name2string([#'CosNaming_NameComponent'{id="", kind=""}|T], Acc) ->
- name2string(T, [$/, $.|Acc]);
-name2string([#'CosNaming_NameComponent'{id=ID, kind=""}|T], Acc) ->
- name2string(T, [$/, convert_reserved(ID)|Acc]);
-name2string([#'CosNaming_NameComponent'{id=ID, kind=Kind}|T], Acc) ->
- name2string(T, [$/, convert_reserved(ID), $., convert_reserved(Kind)|Acc]);
-name2string(What, Acc) ->
- orber:dbg("[~p] orber_cosnaming_utils:name2string(~p)~n"
- "Malformed NameComponent: ~p",
- [?LINE, Acc, What], ?DEBUG_LEVEL),
- corba:raise(#'CosNaming_NamingContext_InvalidName'{}).
-
-%% '/' and '.' are reserved as separators but can be overridden by using '\'.
-convert_reserved([]) ->
- [];
-convert_reserved([$/|T]) ->
- [$\\, $/|convert_reserved(T)];
-convert_reserved([$.|T]) ->
- [$\\, $.|convert_reserved(T)];
-convert_reserved([$\\, H|T]) ->
- [$\\, H|convert_reserved(T)];
-convert_reserved([H|T]) ->
- [H|convert_reserved(T)].
-
-
-%%----------------------------------------------------------------------
-%% Function : string2name
-%% Arguments : A string describing a sequence of NameComponents.
-%% Description:
-%% Returns : A sequence of NameComponents
-%%----------------------------------------------------------------------
-string2name([]) ->
- [];
-string2name(Str) ->
- {NC, Rest} = get_NC(id, Str, [], []),
- [NC|string2name(Rest)].
-
-get_NC(id, [], ID, _Kind) ->
- {#'CosNaming_NameComponent'{id=lists:reverse(ID), kind=""}, []};
-get_NC(kind, [], ID, Kind) ->
- {#'CosNaming_NameComponent'{id=lists:reverse(ID), kind=lists:reverse(Kind)}, []};
-%% // is not allowed; must be /./
-get_NC(id, [$/|_T], [], _) ->
- orber:dbg("[~p] orber_cosnaming_utils:get_NC();~n"
- "'//' not allowed, use '/./'", [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'CosNaming_NamingContext_InvalidName'{});
-get_NC(id, [$., $/|T], [], _) ->
- {#'CosNaming_NameComponent'{id="", kind=""}, T};
-%% End of this ID/Kind; in this case kind eq. "".
-get_NC(id, [$/|T], ID, _Kind) ->
- {#'CosNaming_NameComponent'{id=lists:reverse(ID), kind=""}, T};
-get_NC(kind, [$/|T], ID, Kind) ->
- {#'CosNaming_NameComponent'{id=lists:reverse(ID), kind=lists:reverse(Kind)}, T};
-%% ID exist but it's not allowed to write "id1./id2.kind2".
-get_NC(id, [$., $/|_T], _, _) ->
- orber:dbg("[~p] orber_cosnaming_utils:get_NC();~n"
- "'id1./id2.kind2' not allowed, use 'id1/id2.kind2'",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'CosNaming_NamingContext_InvalidName'{});
-get_NC(id, [$\\, $., H|T], ID, Kind) ->
- get_NC(id, T, [H, $.|ID], Kind);
-get_NC(id, [$\\, $/, H|T], ID, Kind) ->
- get_NC(id, T, [H, $/|ID], Kind);
-get_NC(kind, [$\\, $., H|T], ID, Kind) ->
- get_NC(kind, T, ID, [H|Kind]);
-get_NC(kind, [$\\, $/, H|T], ID, Kind) ->
- get_NC(kind, T, ID, [H|Kind]);
-get_NC(id, [$.|T], ID, Kind) ->
- get_NC(kind, T, ID, Kind);
-get_NC(id, [H|T], ID, Kind) ->
- get_NC(id, T, [H|ID], Kind);
-get_NC(kind, [H|T], ID, Kind) ->
- get_NC(kind, T, ID, [H|Kind]);
-get_NC(Type, Data, ID, Kind) ->
- orber:dbg("[~p] orber_cosnaming_utils:get_NC(~p, ~p, ~p, ~p);~n"
- "Unknown", [?LINE, Type, Data, ID, Kind], ?DEBUG_LEVEL),
- corba:raise(#'CosNaming_NamingContext_InvalidName'{}).
-
-
-%% Converts \< to '%3c'
-escape_string(Str) ->
- escape_string(Str, []).
-escape_string([], Acc) ->
- lists:reverse(Acc);
-escape_string([$\\, Char |T], Acc) ->
- escape_string(T, [code_character(16#0f band Char),
- code_character(16#0f band (Char bsr 4)),$%|Acc]);
-escape_string([Char|T], Acc) ->
- escape_string(T, [Char|Acc]).
-
-
-code_character(N) when N < 10 ->
- $0 + N;
-code_character(N) ->
- $a + (N - 10).
-
-%% Converts '%3c' to \<
-unescape_string(Str) ->
- unescape_string(Str, []).
-unescape_string([], Acc) ->
- lists:reverse(Acc);
-unescape_string([$%, H1, H2 |T], Acc) ->
- I1 = hex2int(H1),
- I2 = hex2int(H2),
- I = I1 * 16 + I2,
- unescape_string(T, [I, $\\|Acc]);
-unescape_string([H|T], Acc) ->
- unescape_string(T, [H|Acc]).
-
-hex2int(H) when H >= $a ->
- 10 + H - $a;
-hex2int(H) when H >= $A ->
- 10 + H -$A;
-hex2int(H) ->
- H - $0.
-
-%%-------------------------- END OF MODULE -----------------------------
diff --git a/lib/orber/Makefile b/lib/orber/Makefile
deleted file mode 100644
index 7db588f206..0000000000
--- a/lib/orber/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include vsn.mk
-VSN=$(ORBER_VSN)
-
-# ----------------------------------------------------
-# Common Macros
-# ----------------------------------------------------
-
-SUB_DIRECTORIES = COSS/CosNaming src java_src c_src examples doc/src priv
-
-SPECIAL_TARGETS =
-
-# ----------------------------------------------------
-# Default Subdir Targets
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_subdir.mk
-
diff --git a/lib/orber/c_src/InitialReference.cc b/lib/orber/c_src/InitialReference.cc
deleted file mode 100644
index 053f3c9c8e..0000000000
--- a/lib/orber/c_src/InitialReference.cc
+++ /dev/null
@@ -1,206 +0,0 @@
-/**
- *<copyright>
- * <year>1997-2007</year>
- * <holder>Ericsson AB, All Rights Reserved</holder>
- *</copyright>
- *<legalnotice>
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * The Initial Developer of the Original Code is Ericsson AB.
- *</legalnotice>
- */
-/**
- * InitialReference is a class which generates the INIT reference
- * which can be used by the InitialReferences interface.
- *
- * creation date: 1997-11-04
- */
-#include "InitialReference.hh"
-
-InitialReference::InitialReference()
-{
- host = 0;
- iorString = 0;
-};
-
-InitialReference::~InitialReference()
-{
- if(host){
- delete host;
- delete iorString;
- }
-};
-
- /**
- * Returns the stringified objectreference to the initial reference server
- */
-char* InitialReference::stringified_ior(char* newhost, int newport)
-{
- STRINGSTREAM iorByteString;
- STRINGSTREAM profileData;
-
- STRINGBUF *s;
- STRINGBUF *profileDataBuf;
- STRINGBUF *iorByteStringBuf;
- long profileDataLength = 0;
- char *str;
-
- // byte_order followed by ' {"", [{0, '
- // char iorBytesFirstPart[] = {0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0};
- char iorBytesFirstPart[48] = {0,0,0,0,0,0,0,32,73,68,76,58,79,114,98,101,114,47,73,110,105,116,105,97,108,82,101,102,101,114,101,110,99,101,115,58,49,46,48,0,0,0,0,1,0,0,0,0};
- // the objectkey "INIT
- char iorBytesLastPart[8] = {0,0,0,4,73,78,73,84};
-
- // Fix the ProfileData struct.
- char pdPrefix[4] = {0,1,0,0};
- char hsize[4];
- char profileDataLengthBytes[4];
- char portbytes[2];
- long hostLength = strlen(newhost);
-
-
- if(host)
- if(strcmp(newhost, host) == 0 && newport == port)
- return iorString;
- else {
- delete host;
- delete iorString;
- }
- host = new char[hostLength+1];
- memcpy(host, newhost, hostLength+1);
- port = newport;
-
- enc_ulong(hostLength + 1, hsize);
- enc_ushort(port, portbytes);
-
- profileDataBuf = profileData.rdbuf();
-
- profileDataBuf->sputn(pdPrefix, 4);
- profileDataBuf->sputn(hsize, 4);
- profileDataBuf->sputn(host, hostLength);
- profileDataBuf->sputc(0);
- profileDataLength = 4 + 4 + hostLength + 1;
-
- profileDataLength = align(profileDataBuf, profileDataLength, 2);
-
- profileDataBuf->sputn(portbytes, 2);
- profileDataLength += 2;
-
- profileDataLength = align(profileDataBuf, profileDataLength, 4);
-
- profileDataBuf->sputn(iorBytesLastPart, 8);
- profileDataLength += 8;
- //cout << "pd length: " << profileDataLength << "\n";
-
- enc_ulong(profileDataLength, profileDataLengthBytes);
-
- // Fix the whole IOR
-
- iorByteStringBuf = iorByteString.rdbuf();
-
- iorByteStringBuf->sputn(iorBytesFirstPart, 48);
- iorByteStringBuf->sputn(profileDataLengthBytes, 4);
-#ifdef HAVE_SSTREAM
- iorByteStringBuf->sputn(profileData.str().data(), profileDataLength);
-#else
- str = profileData.str();
- iorByteStringBuf->sputn(str, profileDataLength);
- delete str;
-#endif
-
- createIOR(iorByteString, 48 + 4 + profileDataLength);
-
- return iorString;
-}
-
-
-void InitialReference::enc_ushort(int s, char *byteArray)
-{
- byteArray[0] = (char) ((s >> 8) & 0xFF);
- byteArray[1] = (char) ((s >> 0) & 0xFF);
-
- return;
-}
-
-void InitialReference::enc_ulong(long l, char *byteArray)
-{
- byteArray[0] = (char) ((l >> 24) & 0xFF);
- byteArray[1] = (char) ((l >> 16) & 0xFF);
- byteArray[2] = (char) ((l >> 8) & 0xFF);
- byteArray[3] = (char) ((l >> 0) & 0xFF);
-
- return;
-}
-
-void InitialReference::createIOR(strstream& byte, long length)
-{
- STRINGBUF *stringbuf;
- STRINGSTREAM string;
-
- int i;
-#ifdef HAVE_SSTREAM
- const char *c;
- const char *bytestr = byte.str().c_str();
-#else
- char *c;
- char *bytestr = byte.str();
-#endif
- int b, n1, n2, c1, c2;
-
- stringbuf = string.rdbuf();
- stringbuf->sputn("IOR:",4);
-
- for(i = 0, c = bytestr; i < length; c++, i++)
- {
- b = *c;
- if(b<0) b+= 256;
- n1 = b / 16;
- n2 = b % 16;
- c1 = (n1 < 10) ? ('0' + n1) : ('a' + (n1 - 10));
- c2 = (n2 < 10) ? ('0' + n2) : ('a' + (n2 - 10));
-
- stringbuf->sputc(c1);
- stringbuf->sputc(c2);
-
- }
-
- stringbuf->sputc(0);
-
- delete bytestr;
-
-#ifdef HAVE_SSTREAM
- iorString = (char *)string.str().c_str();
-#else
- iorString = string.str();
-#endif
-
- return;
-}
-
-long InitialReference::align(STRINGBUF* sbuf, long currentLength,
- int alignment)
-{
- long length = currentLength;
-
- int remainder = alignment - (currentLength % alignment);
- if (remainder == alignment) return length;
-
- for (int i = 0; i < remainder; i++)
- {
- sbuf->sputc(0);
- length++;
- }
- return length;
-}
-
-
diff --git a/lib/orber/c_src/InitialReference.hh b/lib/orber/c_src/InitialReference.hh
deleted file mode 100644
index 79725522db..0000000000
--- a/lib/orber/c_src/InitialReference.hh
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- *<copyright>
- * <year>1997-2007</year>
- * <holder>Ericsson AB, All Rights Reserved</holder>
- *</copyright>
- *<legalnotice>
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * The Initial Developer of the Original Code is Ericsson AB.
- *</legalnotice>
- */
-/*
- * InitialReference is a class for creating an external IOR for the object
- * reference INIT.
- */
-#ifndef _INITIALREFERENCE_HH
-#define _INITIALREFERENCE_HH
-#include <stdio.h>
-#include <string.h>
-
-#if HAVE_SSTREAM
-#include <sstream>
-typedef std::stringstream STRINGSTREAM;
-typedef std::stringbuf STRINGBUF;
-#else
-#include <strstream.h>
-typedef strstream STRINGSTREAM;
-typedef strstreambuf STRINGBUF;
-#endif
-
-class InitialReference {
-private:
- char* iorString;
- char* host;
- int port;
-
- void enc_ushort(int s, char *byteArray);
- void enc_ulong(long l, char *byteArray);
- void createIOR(STRINGSTREAM& byte, long length);
- long align(STRINGBUF* sbuf, long currentLength, int alignment);
-
-public:
- InitialReference();
- ~InitialReference();
-
- char* stringified_ior(char* host, int port);
-
-};
-
-#endif
diff --git a/lib/orber/c_src/Makefile b/lib/orber/c_src/Makefile
deleted file mode 100644
index bad1d3ddb0..0000000000
--- a/lib/orber/c_src/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-# Invoke with GNU make or clearmake -C gnu.
-#
-
-include $(ERL_TOP)/make/run_make.mk
diff --git a/lib/orber/c_src/Makefile.in b/lib/orber/c_src/Makefile.in
deleted file mode 100644
index 980e780451..0000000000
--- a/lib/orber/c_src/Makefile.in
+++ /dev/null
@@ -1,100 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-CXX = @CXX@
-CC = @CC@
-LIBS = @LIBS@
-
-OBJDIR = ../priv/obj/$(TARGET)
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(ORBER_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/orber-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-CC_FILES = \
- InitialReference.cc
-
-HH_FILES = \
- InitialReference.hh
-
-ALL_CFLAGS = @CFLAGS@ @DEFS@ $(CFLAGS)
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt: $(OBJDIR) orber
-
-ifeq ($(findstring win32,$(TARGET)),win32)
-orber:
- $(V_colon)echo "Nothing to build on NT"
-else
-orber:
- $(V_colon)echo "Nothing to build"
-endif
-
-clean:
-
-docs:
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-$(OBJDIR):
- -mkdir -p $(OBJDIR)
-
-$(OBJDIR)/%.o: %.c
- $(V_CC) -c -o $@ $(ALL_CFLAGS) $<
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-ifeq ($(findstring win32,$(TARGET)),win32)
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/priv/src"
- $(INSTALL_DIR) "$(RELSYSDIR)/priv/include"
- $(INSTALL_PROGRAM) $(CC_FILES) "$(RELSYSDIR)/priv/src"
- $(INSTALL_PROGRAM) $(HH_FILES) "$(RELSYSDIR)/priv/include"
-else
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/priv/src"
- $(INSTALL_DIR) "$(RELSYSDIR)/priv/include"
- $(INSTALL_DATA) $(CC_FILES) "$(RELSYSDIR)/priv/src"
- $(INSTALL_DATA) $(HH_FILES) "$(RELSYSDIR)/priv/include"
-endif
-
-
-release_docs_spec:
diff --git a/lib/orber/c_src/main.cc b/lib/orber/c_src/main.cc
deleted file mode 100644
index 109aaf824a..0000000000
--- a/lib/orber/c_src/main.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- *<copyright>
- * <year>1997-2007</year>
- * <holder>Ericsson AB, All Rights Reserved</holder>
- *</copyright>
- *<legalnotice>
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * The Initial Developer of the Original Code is Ericsson AB.
- *</legalnotice>
- */
-
-#include "InitialReference.hh"
-
-main()
-{
- InitialReference ir;
-
- cout << ir.stringified_ior("fingolfin", 4001) << "\n";
-
-
-}
diff --git a/lib/orber/doc/etc/.gitignore b/lib/orber/doc/etc/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/orber/doc/etc/.gitignore
+++ /dev/null
diff --git a/lib/orber/doc/html/.gitignore b/lib/orber/doc/html/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/orber/doc/html/.gitignore
+++ /dev/null
diff --git a/lib/orber/doc/javadoc/.gitignore b/lib/orber/doc/javadoc/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/orber/doc/javadoc/.gitignore
+++ /dev/null
diff --git a/lib/orber/doc/man1/.gitignore b/lib/orber/doc/man1/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/orber/doc/man1/.gitignore
+++ /dev/null
diff --git a/lib/orber/doc/man3/.gitignore b/lib/orber/doc/man3/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/orber/doc/man3/.gitignore
+++ /dev/null
diff --git a/lib/orber/doc/pdf/.gitignore b/lib/orber/doc/pdf/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/orber/doc/pdf/.gitignore
+++ /dev/null
diff --git a/lib/orber/doc/src/CosNaming.xml b/lib/orber/doc/src/CosNaming.xml
deleted file mode 100644
index d69b604f2f..0000000000
--- a/lib/orber/doc/src/CosNaming.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosNaming</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>1997-06-10</date>
- <rev>A</rev>
- </header>
- <module>CosNaming</module>
- <modulesummary>The CosNaming service is a collection of interfaces that together define the naming service.</modulesummary>
- <description>
- <p>The naming service provides the principal mechanism for clients to find
- objects in an ORB based world. The naming service provides an initial naming
- context that functions as the root context for all names. Given this context
- clients can navigate in the name space. </p>
- <p>Types that are declared on the CosNaming level are:</p>
- <code type="none"><![CDATA[
-typedef string Istring;
-struct NameComponent {
- Istring id;
- Istring kind;
-};
-
-typedef sequence <NameComponent> Name;
-
-enum BindingType {nobject, ncontext};
-
-struct Binding {
- Name binding_name;
- BindingType binding_type;
-};
-
-typedef sequence <Binding> BindingList;
- ]]></code>
- <p>To get access to the record definitions for the structs use:
- <c>-include_lib("orber/COSS/CosNaming.hrl").</c>.</p>
- <p>Names are not an ORB object but the can be structured in components as seen by
- the definition above. There are no requirements on names so the service can support
- many different conventions and standards.</p>
- <p>There are two different interfaces supported in the service:</p>
- <list type="bulleted">
- <item>NamingContext</item>
- <item>BindingIterator</item>
- </list>
- </description>
-
-</erlref>
-
diff --git a/lib/orber/doc/src/CosNaming_BindingIterator.xml b/lib/orber/doc/src/CosNaming_BindingIterator.xml
deleted file mode 100644
index 69b0f42b22..0000000000
--- a/lib/orber/doc/src/CosNaming_BindingIterator.xml
+++ /dev/null
@@ -1,99 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNaming_BindingIterator</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>1997-06-10</date>
- <rev>A</rev>
- </header>
- <module>CosNaming_BindingIterator</module>
- <modulesummary>This interface supports iteration over a name binding list.</modulesummary>
- <description>
- <p>This interface allows a client to iterate over the Bindinglist it has been
- initiated with.</p>
- <p>The type <c>NameComponent</c> used below is defined as:</p>
- <code type="none">
- -record('CosNaming_NameComponent', {id, kind=""}).
- </code>
- <p><c>id</c> and <c>kind</c> are strings. </p>
- <p>The type <c>Binding</c> used below is defined as:</p>
- <code type="none">
- -record('CosNaming_Binding', {binding_name, binding_type}).
- </code>
- <p><c>binding_name</c> is a <c>Name = [NameComponent]</c> and
- <c>binding_type</c> is an enum which
- has the values <c>nobject</c> and <c>ncontext</c>.</p>
- <p>Both these records are defined in the file <c>CosNaming.hrl</c> and it
- is included with:</p>
- <code type="none">
- -include_lib("orber/COSS/CosNaming/CosNaming.hrl").
- </code>
- </description>
- <funcs>
- <func>
- <name>next_one(BindinIterator) -> Return</name>
- <fsummary>Return a binding</fsummary>
- <type>
- <v>BindingIterator = #objref</v>
- <v>Return = {bool(), Binding}</v>
- </type>
- <desc>
- <p>This operation returns the next binding and a boolean. The latter
- is set to true if the binding is valid otherwise false. If the boolean
- is false there are no more bindings to retrieve.</p>
- </desc>
- </func>
- <func>
- <name>next_n(BindinIterator, HowMany) -> Return</name>
- <fsummary>Return a binding list</fsummary>
- <type>
- <v>BindingIterator = #objref</v>
- <v>HowMany = int()</v>
- <v>BindingList = [Binding]</v>
- <v>Return = {bool(), BindingList}</v>
- </type>
- <desc>
- <p>This operation returns a binding list with at most HowMany bindings.
- If there are no more bindings it returns false otherwise true.</p>
- </desc>
- </func>
- <func>
- <name>destroy(BindingIterator) -> Return</name>
- <fsummary>Destroy the iterator object</fsummary>
- <type>
- <v>BindingIterator = #objref</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>This operation destroys the binding iterator.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/orber/doc/src/CosNaming_NamingContext.xml b/lib/orber/doc/src/CosNaming_NamingContext.xml
deleted file mode 100644
index 96a6367cbb..0000000000
--- a/lib/orber/doc/src/CosNaming_NamingContext.xml
+++ /dev/null
@@ -1,250 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosNaming_NamingContext</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>1997-06-10</date>
- <rev>A</rev>
- </header>
- <module>CosNaming_NamingContext</module>
- <modulesummary>This interface supports different bind and access functions for names in a context.</modulesummary>
- <description>
- <p>This is the object that defines name scopes, names must be unique within a
- naming context. Objects may have multiple names and may exist in multiple
- naming contexts. Name context may be named in other contexts and cycles are
- permitted.</p>
- <p>The type <c>NameComponent</c> used below is defined as:</p>
- <code type="none">
- -record('CosNaming_NameComponent', {id, kind=""}).
- </code>
- <p>where <c>id</c> and <c>kind</c> are strings. </p>
- <p>The type <c>Binding</c> used below is defined as:</p>
- <code type="none">
- -record('CosNaming_Binding', {binding_name, binding_type}).
- </code>
- <p>where <c>binding_name</c> is a Name and <c>binding_type</c> is an enum which
- has the values <c>nobject</c> and <c>ncontext</c>.</p>
- <p>Both these records are defined in the file <c>CosNaming.hrl</c> and it
- is included with:</p>
- <code type="none">
- -include_lib("orber/COSS/CosNaming/CosNaming.hrl").
- </code>
- <p>There are a number of exceptions that can be returned from functions in this
- interface.</p>
- <list type="bulleted">
- <item>
- <p>NotFound is defined as </p>
- <code type="none">
--record('CosNaming_NamingContext_NotFound',
- {rest_of_name, why}). </code>
- </item>
- <item>
- <p>CannotProceed is defined as </p>
- <code type="none">
--record('CosNaming_NamingContext_CannotProceed',
- {rest_of_name, cxt}). </code>
- </item>
- <item>
- <p>InvalidName is defined as </p>
- <code type="none">
--record('CosNaming_NamingContext_InvalidName', {}). </code>
- </item>
- <item>
- <p>NotFound is defined as </p>
- <code type="none">
--record('CosNaming_NamingContext_NotFound', {}). </code>
- </item>
- <item>
- <p>AlreadyBound is defined as </p>
- <code type="none">
--record('CosNaming_NamingContext_AlreadyBound', {}). </code>
- </item>
- <item>
- <p>NotEmpty is defined as </p>
- <code type="none">
--record('CosNaming_NamingContext_NotEmpty', {). </code>
- </item>
- </list>
- <p>These exceptions are defined in the file <c>CosNaming_NamingContext.hrl</c> and it
- is included with:</p>
- <code type="none">
- -include_lib("orber/COSS/CosNaming/CosNaming_NamingContext.hrl").
- </code>
- </description>
- <funcs>
- <func>
- <name>bind(NamingContext, Name, Object) -> Return</name>
- <fsummary>Bind a Name to an Object</fsummary>
- <type>
- <v>NameContext = #objref</v>
- <v>Name = [NameComponent]</v>
- <v>Object = #objref</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>Creates a binding of a name and an object in the naming context.
- Naming contexts that are bound using <em>bind()</em> do not participate
- in name resolution.</p>
- </desc>
- </func>
- <func>
- <name>rebind(NamingContext, Name, Object) -> Return</name>
- <fsummary>Bind an Object to the Name even if the Name already is bound</fsummary>
- <type>
- <v>NamingContext = #objref</v>
- <v>Name = [NameComponent]</v>
- <v>Object = #objref</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>Creates a binding of a name and an object in the naming context even
- if the name is already bound. Naming contexts that are bound using
- <em>rebind()</em> do not participate in name resolution.</p>
- </desc>
- </func>
- <func>
- <name>bind_context(NamingContext1, Name, NamingContex2) -> Return</name>
- <fsummary>Bind a Name to an NamingContext</fsummary>
- <type>
- <v>NamingContext1 = NamingContext2 =#objref</v>
- <v>Name = [NameComponent]</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>The bind_context function creates a binding of a name and a naming context in
- the current context.
- Naming contexts that are bound using <em>bind_context()</em> participate
- in name resolution.</p>
- </desc>
- </func>
- <func>
- <name>rebind_context(NamingContext1, Name, NamingContex2) -> Return</name>
- <fsummary>Bind an NamingContext to the Name even if the Name already is bound</fsummary>
- <type>
- <v>NamingContext1 = NamingContext2 =#objref</v>
- <v>Name = [NameComponent]</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>The rebind_context function creates a binding of a name and a naming context in
- the current context even if the name already is bound.
- Naming contexts that are bound using <em>rebind_context()</em> participate
- in name resolution.</p>
- </desc>
- </func>
- <func>
- <name>resolve(NamingContext, Name) -> Return</name>
- <fsummary>Retrieve an Object bound to Name</fsummary>
- <type>
- <v>NamingContext = #objref</v>
- <v>Name = [NameComponent]</v>
- <v>Return = Object</v>
- <v>Object = #objref</v>
- </type>
- <desc>
- <p>The resolve function is the way to retrieve an object bound to a name in
- the naming context. The given name must match exactly the bound name. The
- type of the object is not returned, clients are responsible for narrowing
- the object to the correct type.</p>
- </desc>
- </func>
- <func>
- <name>unbind(NamingContext, Name) -> Return</name>
- <fsummary>Remove the binding for a Name</fsummary>
- <type>
- <v>NamingContext = #objref</v>
- <v>Name = [NameComponent]</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>The unbind operation removes a name binding from the naming context.</p>
- </desc>
- </func>
- <func>
- <name>new_context(NamingContext) -> Return</name>
- <fsummary>Create a new NamingContext</fsummary>
- <type>
- <v>NamingContext = #objref</v>
- <v>Return = #objref</v>
- </type>
- <desc>
- <p>The new_context operation creates a new naming context.</p>
- </desc>
- </func>
- <func>
- <name>bind_new_context(NamingContext, Name) -> Return</name>
- <fsummary>Create a new NamingContext and bind it to a Name</fsummary>
- <type>
- <v>NamingContext = #objref</v>
- <v>Name = [NameComponent]</v>
- <v>Return = #objref</v>
- </type>
- <desc>
- <p>The new_context operation creates a new naming context and binds it to
- Name in the current context.</p>
- </desc>
- </func>
- <func>
- <name>destroy(NamingContext) -> Return</name>
- <fsummary>Destroy a NamingContext</fsummary>
- <type>
- <v>NamingContext = #objref</v>
- <v>Return = ok</v>
- </type>
- <desc>
- <p>The destroy operation disposes the NamingContext object and removes it from the
- name server. The context must be empty e.g. not contain any bindings to be
- removed.</p>
- </desc>
- </func>
- <func>
- <name>list(NamingContext, HowMany) -> Return</name>
- <fsummary>List returns a all bindings in the context</fsummary>
- <type>
- <v>NamingContext = #objref</v>
- <v>HowMany = int()</v>
- <v>Return = {ok, BindingList, BindingIterator}</v>
- <v>BindingList = [Binding]</v>
- <v>BindingIterator = #objref</v>
- </type>
- <desc>
- <p>The list operation returns a BindingList with a number of bindings up-to
- HowMany from the context. It also returns a BindinIterator which can be used to
- step through the list. If the total number of existing bindings are less
- than, or equal to, the <c>HowMany</c> parameter a NIL object reference
- is returned.</p>
- <p></p>
- <note>
- <p>One must destroy the BindingIterator, unless it is a NIL object
- reference, by using 'BindingIterator':destroy(). Otherwise one can get
- dangling objects.</p>
- </note>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/orber/doc/src/CosNaming_NamingContextExt.xml b/lib/orber/doc/src/CosNaming_NamingContextExt.xml
deleted file mode 100644
index a571b97ccb..0000000000
--- a/lib/orber/doc/src/CosNaming_NamingContextExt.xml
+++ /dev/null
@@ -1,103 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2000</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>CosNaming_NamingContextExt</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>2000-08-16</date>
- <rev>A</rev>
- </header>
- <module>CosNaming_NamingContextExt</module>
- <modulesummary>This interface contains operation for converting a Name sequence to a string and back.</modulesummary>
- <description>
- <p>To get access to the record definitions for the structures use: <br></br>
-</p>
- <code type="none">
- -include_lib("orber/COSS/CosNaming/CosNaming.hrl").
- </code>
- <p>This module also exports the functions described in:</p>
- <list type="bulleted">
- <item>
- <p><seealso marker="CosNaming_NamingContext">CosNaming_NamingContext</seealso></p>
- </item>
- </list>
- </description>
- <funcs>
- <func>
- <name>to_string(NamingContext, Name) -> Return</name>
- <fsummary>Stringify a <c>Name</c>sequence to a string</fsummary>
- <type>
- <v>NameContext = #objref</v>
- <v>Name = [NameComponent]</v>
- <v>Return = string() | {'EXCEPTION', NamingContext::InvalidName{}}</v>
- </type>
- <desc>
- <p>Stringifies a <c>Name</c> sequence to a string.</p>
- </desc>
- </func>
- <func>
- <name>to_name(NamingContext, NameString) -> Return</name>
- <fsummary>Convert a stringified <c>Name</c>to a <c>Name</c>sequence</fsummary>
- <type>
- <v>NameContext = #objref</v>
- <v>NameString = string()</v>
- <v>Return = [NameComponent] | {'EXCEPTION', NamingContext::InvalidName{}}</v>
- </type>
- <desc>
- <p>Converts a stringified <c>Name</c> to a <c>Name</c> sequence.</p>
- </desc>
- </func>
- <func>
- <name>to_url(NamingContext, AddressString, NameString) -> Return</name>
- <fsummary>Return an URL string constructed from the given Address and Name strings</fsummary>
- <type>
- <v>NameContext = #objref</v>
- <v>Address = NameString = string()</v>
- <v>Return = URLString | {'EXCEPTION', NamingContext::InvalidName{}} | {'EXCEPTION', NamingContextExt::InvalidAddress{}}</v>
- </type>
- <desc>
- <p>This operation takes a <c>corbaloc</c> string and a stringified <c>Name</c>
- sequence as input and returns a fully formed URL string.</p>
- </desc>
- </func>
- <func>
- <name>resolve_str(NamingContext, NameString) -> Return</name>
- <fsummary>Return the object associated, if any, with the given name string</fsummary>
- <type>
- <v>NameContext = #objref</v>
- <v>NameString = string()</v>
- <v>Return = #objref | {'EXCEPTION', NamingContext::InvalidName{}} | {'EXCEPTION', NamingContext::NotFound{why, rest_of_name}} | {'EXCEPTION', NamingContext::CannotProceed{cxt, rest_of_name}}</v>
- </type>
- <desc>
- <p>This operation takes a stringified <c>Name</c> sequence as input and
- returns the associated, if any, object.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/orber/doc/src/Makefile b/lib/orber/doc/src/Makefile
deleted file mode 100644
index ecb0206443..0000000000
--- a/lib/orber/doc/src/Makefile
+++ /dev/null
@@ -1,177 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(ORBER_VSN)
-APPLICATION=orber
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = \
- any.xml \
- corba.xml \
- corba_object.xml \
- orber.xml \
- CosNaming.xml \
- CosNaming_NamingContext.xml \
- CosNaming_NamingContextExt.xml \
- CosNaming_BindingIterator.xml \
- lname.xml \
- lname_component.xml \
- orber_ifr.xml \
- orber_tc.xml \
- Module_Interface.xml \
- interceptors.xml \
- fixed.xml \
- orber_diagnostics.xml \
- orber_acl.xml
-
-XML_PART_FILES = \
- part.xml \
- part_notes.xml
-
-XML_CHAPTER_FILES = \
- ch_contents.xml \
- ch_introduction.xml \
- ch_orber_kernel.xml \
- ch_ifr.xml \
- ch_install.xml \
- ch_idl_to_erlang_mapping.xml \
- ch_naming_service.xml \
- ch_stubs.xml \
- ch_security.xml \
- notes.xml \
- ch_exceptions.xml \
- ch_interceptors.xml \
- ch_orberweb.xml \
- ch_debugging.xml
-
-BOOK_FILES = book.xml
-
-XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \
- $(XML_PART_FILES) $(XML_CHAPTER_FILES)
-
-TECHNICAL_DESCR_FILES =
-
-GIF_FILES = \
- book.gif \
- notes.gif \
- ref_man.gif \
- user_guide.gif \
- name.gif \
- orbs.gif \
- theORB.gif \
- iiop.gif \
- dependent.gif \
- interceptor_operations.gif \
- menuframe.gif \
- dataframe1.gif \
- dataframe2.gif \
- dataframe3.gif \
- dataframe4.gif \
- dataframe5.gif \
- dataframe6.gif \
- dataframe7.gif \
- dataframe8.gif \
- firewall_nat.gif
-
-# ----------------------------------------------------
-
-INTERNAL_HTML_FILES = $(TECHNICAL_DESCR_FILES:%.xml=$(HTMLDIR)/%.html)
-
-HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html) \
- $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
-
-INFO_FILE = ../../info
-EXTRA_FILES = summary.html.src \
- $(DEFAULT_GIF_FILES) \
- $(DEFAULT_HTML_FILES) \
- $(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html)
-
-MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
-
-HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
-
-TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-$(HTMLDIR)/%.gif: %.gif
- $(INSTALL_DATA) $< $@
-
-
-docs: pdf html man
-
-$(TOP_PDF_FILE): $(XML_FILES)
-
-pdf: $(TOP_PDF_FILE)
-
-html: gifs $(HTML_REF_MAN_FILE)
-
-clean clean_docs:
- rm -rf $(HTMLDIR)/*
- rm -f $(MAN3DIR)/*
- rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
- rm -f $(JD_HTML) $(JD_PACK)
-
-man: $(MAN3_FILES)
-
-gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-
-debug opt:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_docs_spec: docs
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
- $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(HTMLDIR)/* \
- "$(RELSYSDIR)/doc/html"
- $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
- $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
-
-release_spec:
diff --git a/lib/orber/doc/src/Module_Interface.xml b/lib/orber/doc/src/Module_Interface.xml
deleted file mode 100644
index a809bcf02f..0000000000
--- a/lib/orber/doc/src/Module_Interface.xml
+++ /dev/null
@@ -1,356 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1999</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Module_Interface</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>1999-09-03</date>
- <rev>A</rev>
- </header>
- <module>Module_Interface</module>
- <modulesummary>Orber generated stubs/skeletons.</modulesummary>
- <description>
- <p>This module contains the stub/skeleton functions generated by IC.</p>
- <p>Starting a Orber server can be done in three ways:</p>
- <list type="bulleted">
- <item>Normal - when the server dies Orber forgets all knowledge of the server.</item>
- <item>Supervisor child - adding the configuration parameter <c>{sup_child, true}</c>
- the <c>oe_create_link/2</c> function returns <c>{ok, Pid, ObjRef}</c> which
- can be handled by the application <em>supervisor/stdlib-1.7</em> or later. </item>
- <item>Persistent object reference - adding the configuration parameters <c>{persistent, true}</c>
- and <c>{regname, {global, term()}}</c> Orber will remember the object reference until the
- server terminates with reason <em>normal</em> or <em>shutdown</em>. Hence,
- if the server is started as a <em>transient</em> supervisor child we do not
- receive a 'OBJECT_NOT_EXIST' exception when it has crashed and is being restarted.</item>
- </list>
- <p>The Orber stub can be used to start a <c>pseudo object</c>, which will create a non-server implementation.
- A pseudo object introduce some limitations:</p>
- <list type="bulleted">
- <item>The functions <c>oe_create_link/2</c> is equal to <c>oe_create/2</c>, i.e.,
- no link can or will be created.</item>
- <item>The <c>BIF:s self()</c> and <c>process_flag(trap_exit,true)</c> behaves incorrectly.</item>
- <item>The <c>IC</c> option <c>{{impl, "M::I"}, "other_impl"}</c> has no effect. The call-back
- functions must be implemented in a file called <c>M_I_impl.erl</c></item>
- <item>The <c>IC</c> option <c>from</c> has no effect. </item>
- <item>The call-back functions must be implemented as if the <c>IC</c> option
- <c>{this, "M::I"}</c> was used.</item>
- <item>Server <c>State</c> changes have no effect. The user can provide information via
- the <c>Env</c> start parameter and the State returned from <c>init/2</c> will be the State
- passed in following invocations.</item>
- <item>If a call-back function replies with the <c>Timeout</c> parameter set it have no effect.</item>
- <item>Operations defined as <c>oneway</c> are blocking until the operation replies.</item>
- <item>The option <c>{pseudo, true}</c> overrides all other start options.</item>
- <item>Only the functions, besides own definitions, <c>init/2</c> (called via oe_create*/2) and
- <c>terminate/2</c> (called via corba:dispose/1) must be implemented.</item>
- </list>
- <p>By adopting the rules for <c>pseudo</c> objects described above we can use <c>oe_create/2</c>
- to create <c>server</c> or <c>pseudo</c> objects, by excluding or including the
- option <c>{pseudo, true}</c>, without changing the call-back module.
- </p>
- <p>If you start a object without <c>{regname, RegName}</c> it can only be accessed through the returned object key.
- Started with a <c>{regname, RegName}</c> the name is registered locally or globally.
- </p>
- <warning>
- <p>To avoid flooding Orber with old object references start erlang using the flag
- <em>-orber objectkeys_gc_time Time</em>, which will remove all object references
- related to servers being dead for Time seconds. To avoid extra overhead, i.e., performing
- garbage collect if no persistent objects are started, the objectkeys_gc_time default value
- is <em>infinity</em>. For more information, see the orber and corba documentation.</p>
- </warning>
- </description>
- <funcs>
- <func>
- <name>Module_Interface:typeID() -> TypeId</name>
- <fsummary>Return the Type ID related to this stub/skeleton</fsummary>
- <type>
- <v>TypeId = string(), e.g., "IDL:Module/Interface:1.0"</v>
- </type>
- <desc>
- <p>Returns the Type ID related to this stub/skeleton</p>
- </desc>
- </func>
- <func>
- <name>Module_Interface:oe_create() -> ObjRef</name>
- <fsummary>Start a Orber server.</fsummary>
- <type>
- <v>ObjRef = #object reference</v>
- </type>
- <desc>
- <p>Start a Orber server.</p>
- </desc>
- </func>
- <func>
- <name>Module_Interface:oe_create_link() -> ObjRef</name>
- <fsummary>Start a linked Orber server.</fsummary>
- <type>
- <v>ObjRef = #object reference</v>
- </type>
- <desc>
- <p>Start a linked Orber server.</p>
- </desc>
- </func>
- <func>
- <name>Module_Interface:oe_create(Env) -> ObjRef</name>
- <fsummary>Start a Orber server.</fsummary>
- <type>
- <v>Env = term()</v>
- <v>ObjRef = #object reference</v>
- </type>
- <desc>
- <p>Start a Orber server passing Env to <c>init/1</c>.</p>
- </desc>
- </func>
- <func>
- <name>Module_Interface:oe_create_link(Env) -> ObjRef</name>
- <fsummary>Start a linked Orber server.</fsummary>
- <type>
- <v>Env = term()</v>
- <v>ObjRef = #object reference</v>
- </type>
- <desc>
- <p>Start a linked Orber server passing Env to <c>init/1</c>.</p>
- </desc>
- </func>
- <func>
- <name>Module_Interface:oe_create(Env, Options) -> ObjRef</name>
- <fsummary>Start a Orber stub/skeleton</fsummary>
- <type>
- <v>Env = term()</v>
- <v>ObjRef = #object reference</v>
- <v>Options = [{sup_child, false} | {persistent, Bool} | {regname, RegName} | {pseudo, Bool} | {local_typecheck, Bool} | {survive_exit, Bool} | {create_options, [CreateOpts]}]</v>
- <v>Bool = true | false</v>
- <v>RegName = {global, term()} | {local, atom()}</v>
- <v>CreateOpts = {debug, [Dbg]} | {timeout, Time}</v>
- <v>Dbg = trace | log | statistics | {log_to_file, FileName}</v>
- </type>
- <desc>
- <p>Start a Orber server passing Env to <c>init/1</c>.</p>
- <p>If the option <c>{pseudo, true}</c> is used, all other options are overridden.
- As default, this option is set to false.</p>
- <p>This function cannot be used for starting a server as supervisor child.
- If started as <c>persistent</c>, the options <c>[{persistent, true}, {regname, {global, term()}}]</c> must be used and
- Orber will only forget the object reference if it terminates with reason <em>normal</em> or <em>shutdown</em>.</p>
- <p>The option <c>{local_typecheck, boolean()}</c>, which overrides the
- <seealso marker="ch_install#flags">Local Typechecking</seealso>
- environment flag, turns on or off typechecking. If activated,
- parameters, replies and raised exceptions will be checked to ensure that
- the data is correct, when invoking operations on CORBA Objects within
- the same Orber domain. Due to the extra overhead, this option
- <em>MAY ONLY</em> be used during testing and development.</p>
- <p><c>{survive_exit, boolean()}</c> overrides the
- <seealso marker="ch_install#flags">EXIT Tolerance</seealso>
- environment flag. If activated, the server will not terminate, even though
- the call-back module returns EXIT.</p>
- <p><c>Time</c> specifies how long time, in milliseconds, the server is allowed to
- spend initializing. For more information about the <c>Dbg</c> options,
- see the <c>sys</c> module.</p>
- </desc>
- </func>
- <func>
- <name>Module_Interface:oe_create_link(Env, Options) -> Return</name>
- <fsummary>Start a Orber stub/skeleton</fsummary>
- <type>
- <v>Env = term()</v>
- <v>Return = ObjRef | {ok, Pid, ObjRef}</v>
- <v>ObjRef = #object reference</v>
- <v>Options = [{sup_child, Bool} | {persistent, Bool} | {regname, RegName} | {pseudo, Bool} | {local_typecheck, Bool} | {survive_exit, Bool} | {create_options, [CreateOpts]}]</v>
- <v>Bool = true | false</v>
- <v>RegName = {global, term()} | {local, atom()}</v>
- <v>CreateOpts = {debug, [Dbg]} | {timeout, Time}</v>
- <v>Dbg = trace | log | statistics | {log_to_file, FileName}</v>
- <v></v>
- <v></v>
- <v></v>
- </type>
- <desc>
- <p>Start a linked Orber server passing Env to <c>init/1</c>.</p>
- <p>If the option <c>{pseudo, true}</c> is used, all other options are overridden and no link will be created.
- As default, this option is set to false.</p>
- <p>This function can be used for starting a server as persistent or supervisor child. At the moment
- <c>[{persistent, true}, {regname, {global, term()}}]</c> must be used to start
- a server as persistent, i.e., if a server died and is in the process of being restarted
- a call to the server will not raise <c>'OBJECT_NOT_EXIST'</c> exception.
- Orber will only forget the object reference if it terminates with reason <em>normal</em> or <em>shutdown</em>,
- hence, the server must be started as <em>transient</em> (for more information see the
- supervisor documentation).</p>
- <p>The options <c>{local_typecheck, boolean()}</c> and <c>{survive_exit, boolean()}</c>
- behaves in the same way as for <c>oe_create/2</c>.</p>
- <p><c>Time</c> specifies how long time, in milliseconds, the server is allowed to
- spend initializing. For more information about the <c>Dbg</c> options,
- see the <c>sys</c> module.</p>
- </desc>
- </func>
- <func>
- <name>Module_Interface:own_functions(ObjRef, Arg1, ..., ArgN) -> Reply</name>
- <name>Module_Interface:own_functions(ObjRef, Options, Arg1, ..., ArgN) -> Reply</name>
- <fsummary>User defined function which is not a part of Orber</fsummary>
- <type>
- <v>ObjRef = #object reference</v>
- <v>Options = [Option] | Timeout</v>
- <v>Option = {timeout, Timeout} | {context, [Context]}</v>
- <v>Timeout = infinity | integer(milliseconds)</v>
- <v>Context = #'IOP_ServiceContext'{context_id = CtxId, context_data = CtxData}</v>
- <v>CtxId = ?ORBER_GENERIC_CTX_ID</v>
- <v>CtxData = {interface, Interface} | {userspecific, term()} | {configuration, Options}</v>
- <v>Interface = string()</v>
- <v>Options = [{Key, Value}]</v>
- <v>Key = ssl_client_verify | ssl_client_depth | ssl_client_certfile | ssl_client_cacertfile |
- ssl_client_password | ssl_client_keyfile | ssl_client_ciphers | ssl_client_cachetimeout</v>
- <v>Value = allowed value associated with the given key</v>
- <v>ArgX = specified in the IDL-code.</v>
- <v>Reply = specified in the IDL-code.</v>
- </type>
- <desc>
- <p>The default value for the <c>Timeout</c> option is <c>infinity</c>.
- IPv4 or IPv6 addresses are accepted as local Interface.</p>
- <p>The <em>configuration</em> context is used to override the global
- SSL client side
- <seealso marker="ch_install#config">configuration</seealso>.</p>
- <p>To gain access to <c>#'IOP_ServiceContext'{}</c> record and the
- <c>?ORBER_GENERIC_CTX_ID</c> macro, you must add
- <c>-include_lib("orber/include/corba.hrl").</c> to your module.</p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>CALLBACK FUNCTIONS</title>
- <p>The following functions should be exported from a <c>CORBA</c>
- callback module. Note, a complete template of the call-back module can
- be generated automatically by compiling the IDL-file with the IC option
- <c>{be,erl_template}</c>. One should also add
- the same compile options, for example <c>this</c> or <c>from</c>,
- used when generating the stub/skeleton modules.</p>
- </section>
- <funcs>
- <func>
- <name>Module_Interface_impl:init(Env) -> CallReply</name>
- <fsummary>User defined function which is not a part of Orber</fsummary>
- <type>
- <v>Env = term()</v>
- <v>CallReply = {ok, State} | {ok, State, Timeout} | ignore | {stop, StopReason}</v>
- <v>State = term()</v>
- <v>Timeout = int() >= 0 | infinity</v>
- <v>StopReason = term()</v>
- </type>
- <desc>
- <p>Whenever a new server is started, <em>init/1</em> is the first function called in the specified call-back module.</p>
- </desc>
- </func>
- <func>
- <name>Module_Interface_impl:terminate(Reason, State) -> ok</name>
- <fsummary>User defined function which is not a part of Orber</fsummary>
- <type>
- <v>Reason = term()</v>
- <v>State = term()</v>
- </type>
- <desc>
- <p>This call-back function is called whenever the server is about to terminate.</p>
- </desc>
- </func>
- <func>
- <name>Module_Interface_impl:code_change(OldVsn, State, Extra) -> CallReply</name>
- <fsummary>User defined function which is not a part of Orber</fsummary>
- <type>
- <v>OldVsn = undefined | term()</v>
- <v>State = term()</v>
- <v>Extra = term()</v>
- <v>CallReply = {ok, NewState}</v>
- <v>NewState = term()</v>
- </type>
- <desc>
- <p>Update the internal <c>State</c>.</p>
- </desc>
- </func>
- <func>
- <name>Module_Interface_impl:handle_info(Info, State) -> CallReply</name>
- <fsummary>User defined function which is not a part of Orber</fsummary>
- <type>
- <v>Info = term()</v>
- <v>State = term()</v>
- <v>CallReply = {noreply, State} | {noreply, State, Timeout} | {stop, StopReason, State}</v>
- <v>Timeout = int() >= 0 | infinity</v>
- <v>StopReason = normal | shutdown | term()</v>
- </type>
- <desc>
- <p>If the configuration parameter <em>{{handle_info, "Module::Interface"}, true}</em>
- is passed to IC and <em>process_flag(trap_exit,true)</em> is set in the <em>init()</em>
- call-back this function must be exported. </p>
- <note>
- <p>To be able to handle the <c>Timeout</c> option in <c>CallReply</c> in the call-back
- module the configuration parameter <em>{{handle_info, "Module::Interface"}, true}</em> must
- be passed to IC. </p>
- </note>
- </desc>
- </func>
- <func>
- <name>Module_Interface_impl:own_functions(State, Arg1, ..., ArgN) -> CallReply</name>
- <name>Module_Interface_impl:own_functions(This, State, Arg1, ..., ArgN) -> CallReply</name>
- <name>Module_Interface_impl:own_functions(This, From, State, Arg1, ..., ArgN) -> ExtCallReply</name>
- <name>Module_Interface_impl:own_functions(From, State, Arg1, ..., ArgN) -> ExtCallReply</name>
- <fsummary>User defined function which is not a part of Orber</fsummary>
- <type>
- <v>This = the servers #object reference</v>
- <v>State = term()</v>
- <v>ArgX = specified in the IDL-code.</v>
- <v>CallReply = {reply, Reply, State} | {reply, Reply, State, Timeout} | {stop, StopReason, Reply, State} | {stop, StopReason, State} | corba:raise(Exception)</v>
- <v>ExtCallReply = CallReply | corba:reply(From, Reply), {noreply, State} | corba:reply(From, Reply), {noreply, State, Timeout}</v>
- <v>Reply = specified in the IDL-code.</v>
- <v>Timeout = int() >= 0 | infinity</v>
- <v>StopReason = normal | shutdown | term()</v>
- </type>
- <desc>
- <p>All two-way functions must return one of the listed replies or raise any of
- the exceptions listed in the IDL code (i.e. raises(...)).
- If the IC compile options <em>this</em> and/or <em>from</em> are used,
- the implementation must accept the <em>This</em> and/or <em>From</em>
- parameters.</p>
- </desc>
- </func>
- <func>
- <name>Module_Interface_impl:own_functions(State, Arg1, ..., ArgN) -> CastReply</name>
- <name>Module_Interface_impl:own_functions(This, State, Arg1, ..., ArgN) -> CastReply</name>
- <fsummary>User defined function which is not a part of Orber</fsummary>
- <type>
- <v>This = the servers #object reference</v>
- <v>State = term()</v>
- <v>CastReply = {noreply, State} | {noreply, State, Timeout} | {stop, StopReason, State}</v>
- <v>ArgX = specified in the IDL-code.</v>
- <v>Reply = specified in the IDL-code.</v>
- <v>Timeout = int() >= 0 | infinity</v>
- <v>StopReason = normal | shutdown | term()</v>
- </type>
- <desc>
- <p>All one-way functions must return one of the listed replies.
- If the IC compile option <em>this</em> is used,
- the implementation must accept the <em>This</em> parameter.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/orber/doc/src/Orber/InitialReference.java b/lib/orber/doc/src/Orber/InitialReference.java
deleted file mode 100644
index 35a8c2437b..0000000000
--- a/lib/orber/doc/src/Orber/InitialReference.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1997-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/**
- * InitialReference is a class which generates the INIT reference
- * which can be used by the InitialReferences interface.
- */
-package Orber;
-
-public class InitialReference
-{
-
- /**
- * Constructor.
- */
- public InitialReference(){;}
-
- /**
- * Returns the stringified objectreference to the initial reference server
- */
- public String stringified_ior(String host, int port)
- {
- String iorByteString;
- String profileData;
- String iorString;
-
- // byte_order followed by ' {"", [{0, '
- // char iorBytesFirstPart[] = {0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0};
- char iorBytesFirstPart[] = {0,0,0,0,0,0,0,32,73,68,76,58,79,114,98,101,114,47,73,110,105,116,105,97,108,82,101,102,101,114,101,110,99,101,115,58,49,46,48,0,0,0,0,1,0,0,0,0};
- // the objectkey "INIT
- char iorBytesLastPart[] = {0,0,0,4,73,78,73,84};
-
- // Fix the ProfileData struct.
- char pdPrefix[] = {0,1,0,0};
- char nullbyte[] = {0};
- profileData = new String(pdPrefix) + enc_ulong(host.length() + 1) + host + new String(nullbyte);
- profileData = align(profileData, 2);
- profileData += enc_ushort(port);
- profileData = align(profileData, 4);
- profileData += new String(iorBytesLastPart);
- // Fix the whole IOR
- iorByteString = new String(iorBytesFirstPart) + enc_ulong(profileData.length()) +
- profileData;
-
- // System.out.print("Start[" + profileData.length() + "]");
- // System.out.print("[");
- // for(int x = 0; x < iorByteString.length(); x++)
- // {
- // System.out.print((int) iorByteString.charAt(x) + ",");
- // }
- // System.out.println("]");
-
- iorString = createIOR(iorByteString);
- // System.out.println(iorString);
- return iorString;
- }
-
-
- private String enc_ushort(int s)
- {
- char byteArray[] = {(char) ((s >>> 8) & 0xFF),
- (char) ((s >>> 0) & 0xFF)};
-
- return new String(byteArray);
- }
-
- private String enc_ulong(int l)
- {
- char byteArray[] = {(char) ((l >>> 24) & 0xFF),
- (char) ((l >>> 16) & 0xFF),
- (char) ((l >>> 8) & 0xFF),
- (char) ((l >>> 0) & 0xFF)};
-
- return new String(byteArray);
-
- }
-
- private String createIOR(String bytes)
- {
- int i;
- StringBuffer sb = new StringBuffer("IOR:");
-
- for(i = 0; i < bytes.length(); i++)
- {
- int b = bytes.charAt(i);
- if(b<0) b+= 256;
- int n1 = b / 16;
- int n2 = b % 16;
- int c1 = (n1 < 10) ? ('0' + n1) : ('a' + (n1 - 10));
- int c2 = (n2 < 10) ? ('0' + n2) : ('a' + (n2 - 10));
- sb.append((char)c1);
- sb.append((char)c2);
- }
-
- return sb.toString();
- }
-
- private String align(String buffer, int alignment)
- {
- String s = buffer;
- char nullbyte[] = {0};
-
- int remainder = alignment - (buffer.length() % alignment);
- if (remainder == alignment) return s;
-
- for (int i = 0; i < remainder; i++)
- {
- s += new String(nullbyte);
- }
- return s;
- }
-
-
-}
diff --git a/lib/orber/doc/src/Orber/Makefile b/lib/orber/doc/src/Orber/Makefile
deleted file mode 100644
index 16a3994499..0000000000
--- a/lib/orber/doc/src/Orber/Makefile
+++ /dev/null
@@ -1,71 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(ORBER_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/orber-$(VSN)
-
-#
-# JAVA macros
-#
-JAVA_CLASSES = \
- InitialReference
-
-JAVA_FILES= $(JAVA_CLASSES:%=%.java)
-
-CLASSPATH = ../..
-
-# ----------------------------------------------------
-# Flags
-# ----------------------------------------------------
-JAVA_OPTIONS =
-
-# ----------------------------------------------------
-# Make Rules
-# ----------------------------------------------------
-
-debug opt:
-
-clean:
-
-docs:
-
-# ----------------------------------------------------
-# Release Targets
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/java_src/Orber
- $(INSTALL_DATA) $(JAVA_FILES) $(RELSYSDIR)/java_src/Orber
-
-release_docs_spec:
-
diff --git a/lib/orber/doc/src/any.xml b/lib/orber/doc/src/any.xml
deleted file mode 100644
index f51712c97e..0000000000
--- a/lib/orber/doc/src/any.xml
+++ /dev/null
@@ -1,117 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1998</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>any</title>
- <prepared></prepared>
- <docno></docno>
- <checked></checked>
- <date>1998-04-20</date>
- <rev>A</rev>
- </header>
- <module>any</module>
- <modulesummary>the corba any type</modulesummary>
- <description>
- <p>This module contains functions that gives an interface to the CORBA any type.</p>
- <p>Note that the <c>any</c> interface in orber does not contain a destroy
- function because the any type is represented as an Erlang record and
- therefor will be removed by the garbage collector when not in use.</p>
- <p>The type <c>TC</c> used below describes an IDL type and is a tuple according
- to the to the Erlang language mapping.</p>
- <p>The type <c>Any</c> used below is defined as:</p>
- <code type="none">
- -record(any, {typecode, value}).
- </code>
- <p>where <c>typecode</c> is a TC tuple and <c>value</c> is an Erlang term of
- the type defined by the typecode field.</p>
- </description>
- <funcs>
- <func>
- <name>create() -> Result</name>
- <name>create(Typecode, Value) -> Result</name>
- <fsummary>Create an any record</fsummary>
- <type>
- <v>Typecode = TC</v>
- <v>Value = term()</v>
- <v>Result = Any</v>
- </type>
- <desc>
- <p>The create/0 function creates an empty any record and the create/2
- function creates an initialized record.</p>
- </desc>
- </func>
- <func>
- <name>set_typecode(A, Typecode) -> Result</name>
- <fsummary>Set the typecode field</fsummary>
- <type>
- <v>A = Any</v>
- <v>Typecode = TC</v>
- <v>Result = Any</v>
- </type>
- <desc>
- <p>This function sets the typecode of <em>A</em> and returns a
- new any record.</p>
- </desc>
- </func>
- <func>
- <name>get_typecode(A) -> Result</name>
- <fsummary>Fetch the typecode</fsummary>
- <type>
- <v>A = Any</v>
- <v>Result = TC</v>
- </type>
- <desc>
- <p>This function returns the typecode of <em>A</em>.</p>
- </desc>
- </func>
- <func>
- <name>set_value(A, Value) -> Result</name>
- <fsummary>Set the value field</fsummary>
- <type>
- <v>A = Any</v>
- <v>Value = term()</v>
- <v>Result = Any</v>
- </type>
- <desc>
- <p>This function sets the value of <em>A</em> and returns a
- new any record.</p>
- </desc>
- </func>
- <func>
- <name>get_value(A) -> Result</name>
- <fsummary>Fetch the value</fsummary>
- <type>
- <v>A = Any</v>
- <v>Result = term()</v>
- </type>
- <desc>
- <p>This function returns the value of <em>A</em>.
- </p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/orber/doc/src/book.gif b/lib/orber/doc/src/book.gif
deleted file mode 100644
index 94b3868792..0000000000
--- a/lib/orber/doc/src/book.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/book.xml b/lib/orber/doc/src/book.xml
deleted file mode 100644
index 81bd5a8f65..0000000000
--- a/lib/orber/doc/src/book.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE book SYSTEM "book.dtd">
-
-<book xmlns:xi="http://www.w3.org/2001/XInclude">
- <header titlestyle="normal">
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>orber</title>
- <prepared></prepared>
- <docno></docno>
- <date>1998-04-25</date>
- <rev>2.0</rev>
- </header>
- <insidecover>
- </insidecover>
- <pagetext>Orber</pagetext>
- <preamble>
- <contents level="2"></contents>
- </preamble>
- <parts lift="no">
- <xi:include href="part.xml"/>
- </parts>
- <applications>
- <xi:include href="ref_man.xml"/>
- </applications>
- <releasenotes>
- <xi:include href="notes.xml"/>
- </releasenotes>
- <listofterms></listofterms>
- <index></index>
-</book>
-
diff --git a/lib/orber/doc/src/ch_contents.xml b/lib/orber/doc/src/ch_contents.xml
deleted file mode 100644
index b783e63aee..0000000000
--- a/lib/orber/doc/src/ch_contents.xml
+++ /dev/null
@@ -1,173 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>The Orber Application</title>
- <prepared></prepared>
- <docno></docno>
- <date>1998-05-05</date>
- <rev>B</rev>
- <file>ch_contents.xml</file>
- </header>
-
- <section>
- <title>Content Overview</title>
- <p>The Orber documentation is divided into three sections:
- </p>
- <list type="bulleted">
- <item>
- <p>PART ONE - The User's Guide
- <br></br>
-Description of the Orber Application including IDL-to-Erlang
- language mapping, services and a small tutorial demonstrating
- the development of a simple service.</p>
- </item>
- <item>
- <p>PART TWO - Release Notes
- <br></br>
-A concise history of Orber.</p>
- </item>
- <item>
- <p>PART THREE - The Reference Manual
- <br></br>
- A quick reference guide, including a
- brief description, to all the functions available in Orber.</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Brief Description of the User's Guide</title>
- <p>The User's Guide contains the following parts:</p>
- <list type="bulleted">
- <item>
- <p>ORB kernel and IIOP support</p>
- </item>
- <item>
- <p>Interface Repository</p>
- </item>
- <item>
- <p>IDL to Erlang mapping</p>
- </item>
- <item>
- <p>CosNaming Service</p>
- </item>
- <item>
- <p>Resolving initial reference from Java or C++</p>
- </item>
- <item>
- <p>Tutorial - creating a simple service </p>
- </item>
- <item>
- <p>CORBA Exceptions </p>
- </item>
- <item>
- <p>Interceptors</p>
- </item>
- <item>
- <p>OrberWeb</p>
- </item>
- <item>
- <p>Debugging
- </p>
- </item>
- </list>
-
- <section>
- <title>ORB Kernel and IIOP Support</title>
- <p>The ORB kernel which has IIOP support will allow the creation
- of persistent server objects in Erlang. These objects can also
- be accessed via Erlang and Java environments. For the moment a
- Java enabled ORB is needed to generate Java from IDL to use
- Java server objects (this has been tested using OrbixWeb).</p>
- </section>
-
- <section>
- <title>Interface Repository</title>
- <p>The IFR is an interface repository used for some type-checking
- when coding/decoding IIOP. The IFR is capable of storing all
- interfaces and declarations of OMG IDL.</p>
- </section>
-
- <section>
- <title>IDL to Erlang Mapping</title>
- <p>The OMG IDL mapping for Erlang, which is necessary to access the
- functionality of Orber, is described, The mapping structure is
- included as the basic and the constructed OMG IDL types
- references, invocations and Erlang characteristics. An example is
- also provided.</p>
- </section>
-
- <section>
- <title>CosNaming Service</title>
- <p>Orber contains a CosNaming compliant service.</p>
- </section>
-
- <section>
- <title>Resolving Initial References from Java or C++</title>
- <p>A couple of classes are added to Orber to simplify initial
- reference access from Java or C++.
- </p>
- <p><em>Resolving initial reference from Java</em> <br></br>
- A class with only one method which returns an <term id="IOR"><termdef>Interoperable Object Reference</termdef></term>on the
- external string format to the INIT object (see "Interoperable
- Naming Service" specification).</p>
- <p><em>Resolving initial reference from C++</em> <br></br>
-
- A class (and header file) with only one method which returns
- an IOR on the external string format to the INIT object (see
- "Interoperable Naming Service" specification).</p>
- </section>
-
- <section>
- <title>Orber Stub/Skeleton</title>
- <p>An example which describes the API and behavior of Orber stubs and skeletons. </p>
- </section>
-
- <section>
- <title>CORBA Exceptions</title>
- <p>A listing of all system exceptions supported by Orber and how one should
- handle them. This chapter also describe how to generate user defined
- exceptions.</p>
- </section>
-
- <section>
- <title>Interceptors</title>
- <p>Descibes how to implement and activate interceptors.</p>
- </section>
-
- <section>
- <title>OrberWeb</title>
- <p>Offers the possibility to administrate and supervise Orber via a GUI.</p>
- </section>
-
- <section>
- <title>Debugging</title>
- <p>Describes how to use different tools when debugging and/or developing
- new applications using Orber. Also includes a FAQ, which deal with
- the most common mistakes when using Orber.
- </p>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/orber/doc/src/ch_debugging.xml b/lib/orber/doc/src/ch_debugging.xml
deleted file mode 100644
index a036cf5231..0000000000
--- a/lib/orber/doc/src/ch_debugging.xml
+++ /dev/null
@@ -1,210 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2001</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Debugging</title>
- <prepared></prepared>
- <docno></docno>
- <date>2001-11-29</date>
- <rev></rev>
- <file>ch_debugging.xml</file>
- </header>
-
- <section>
- <title>Tools and FAQ</title>
- <p>Persons who use Orber for the first time may find it hard to tell what goes
- wrong when trying to setup communication between an Orber-ORB and ORB:s supplied
- by another vendor or another Orber-ORB. The purpose of this chapter is to inform
- about the most common mistakes and what tools one can use to overcome these
- problems. </p>
-
- <section>
- <title>Tools</title>
- <p>To begin with, Orber can be configured to run in debug mode. There are four ways
- to set this parameter:</p>
- <list type="bulleted">
- <item><em>erl -orber orber_debug_level 10</em> - can be added to a start-script.</item>
- <item><em>corba:orb_init([{orber_debug_level, 10}])</em> - this operation must
- be invoked <em>before</em> starting Orber.</item>
- <item><em>orber:configure(orber_debug_level, 10)</em> - this operation can
- be invoked at any time.</item>
- <item><em>OrberWeb</em> - via the <c>Configuration</c> menu one can easily change
- the configuration. For more information, see the OrberWeb chapter in this
- User's Guide.</item>
- </list>
- <p>When Orber runs i debug mode, printouts will be generated if anything abnormal occurs
- (not necessarily an error). An error message typically looks like:</p>
- <code type="none">
-=ERROR REPORT==== 29-Nov-2001::14:09:55 ===
-=================== Orber =================
-[410] corba:common_create(orber_test_server, [{pseudo,truce}]);
-not a boolean(truce).
-===========================================
- </code>
- <p>In the example above, we tried to create an object with an incorrect option (i.e. should
- have been <c>{pseudo,true}</c>).</p>
- <p>If you are not able to solve the problem, you should include all generated reports when
- contacting support or using the erlang-questions mailing list.</p>
- <p>It is easy to forget to, for example, set all fields in a struct, which
- one may not discover when developing an application using Orber. When using
- a typed language, such faults would cause a compile time error. To avoid
- these mistakes, Orber allows the user to activate automatic typechecking
- of all local invocations of CORBA Objects. For this feature to be really
- useful, the user must create test suites which cover as much as
- possible. For example, invoking an operation with invalid or incorrect
- arguments should also be tested. This option can be activated for one object
- or all object via:</p>
- <list type="bulleted">
- <item><em>'MyModuyle_MyInterface':oe_create(Env, [{local_typecheck, true}])</em> -
- This approach will only activate, or deactivate, typechecking for
- the returned instance. Naturally, this option can also be passed
- to <c>oe_create_link/2</c>, <c>corba:create/4</c> and
- <c>corba:create_link/4</c>.</item>
- <item><em>erl -orber flags 2</em> - can be added to a start-script.
- All object invocations will be typechecked, unless overridden by the
- previous option.</item>
- <item><em>corba:orb_init([{flags, 16#0002}])</em> - this operation must
- be invoked <em>before</em> starting Orber. Behaves as the previous
- option.</item>
- </list>
- <p>If incorrect data is passed or returned, Orber uses the <c>error_logger</c>
- to generate logs, which can look like:</p>
- <code type="none">
-=ERROR REPORT==== 10-Jul-2002::12:36:09 ===
-========= Orber Typecheck Request =========
-Invoked......: MyModule_MyInterface:foo/1
-Typecode.....: [{tk_enum,"IDL:MyModule/enumerant:1.0",
- "enumerant",
- ["one","two"]}]
-Arguments....: [three]
-Result.......: {'EXCEPTION',{'MARSHAL',[],102,'COMPLETED_NO'}}
-===========================================
- </code>
- <p>Note, that the arity is equivalent to the IDL-file. In the example above,
- an undefined enumerant was used. In most cases, it is useful to set the
- configuration parameter <c>orber_debug_level 10</c> as well. Due to the
- extra overhead, this option <em>MAY ONLY</em> be used during testing and
- development.
- For more information, see also
- <seealso marker="ch_install#config">configuration settings</seealso>.</p>
- <p>It is also possible to trace all communication between an Orber-ORB and, for example,
- a Java-ORB, communicating via IIOP. All you need to do is to activate an
- <seealso marker="ch_interceptors">interceptor</seealso>. Normally, the users must
- implement the interceptor themselves, but for your convenience Orber includes three
- pre-compiled interceptors called <c>orber_iiop_tracer</c>,
- <c>orber_iiop_tracer_silent</c> and <c>orber_iiop_tracer_stealth</c>.</p>
- <warning>
- <p>Logging all traffic is <em>expensive</em>. Hence, only use the supplied
- interceptors during test and development.</p>
- </warning>
- <p>The <c>orber_iiop_tracer</c> and <c>orber_iiop_tracer_silent</c> interceptors
- uses the <c>error_logger</c> module to generate the logs. If the traffic
- is intense you probably want to write the reports to a log-file.
- This is done by, for example, invoking:</p>
- <code type="none">
-erl> error_logger:tty(false).
-erl> error_logger:logfile({open, "/tmp/IIOPTrace"}).
- </code>
- <p>The <c>IIOPTrace</c> file will contain, if you use the <c>orber_iiop_tracer</c>
- interceptor, reports which looks like:</p>
- <code type="none">
-=INFO REPORT==== 13-Jul-2005::18:22:39 ===
-=============== new_out_connection =======
-Node : myNode@myHost
-From : 192.0.0.10:47987
-To : 192.0.0.20:4001
-==========================================
-
-=INFO REPORT==== 29-Nov-2001::15:26:28 ===
-=============== out_request ==============
-Connection: {"192.0.0.20",4001,"192.0.0.10",47987}
-Operation : resolve
-Parameters: [[{'CosNaming_NameComponent',
- "AIK","SwedishIcehockeyChampions"}]]
-Context : [{'IOP_ServiceContext',1,
- {'CONV_FRAME_CodeSetContext',65537,65801}}]
-==========================================
- </code>
- <p>The <c>orber_iiop_tracer_silent</c> will not log GIOP encoded data. To activate
- one the interceptors, you have two options:</p>
- <list type="bulleted">
- <item><em>erl -orber interceptors "{native,[orber_iiop_tracer]}"</em> - can be added to a start-script.</item>
- <item><em>corba:orb_init([{interceptors, {native, [orber_iiop_tracer_silent]}}])</em> - this operation must
- be invoked <em>before</em> starting Orber.</item>
- </list>
- <p>It is also possible to active and deactivate an interceptor during
- run-time, but this will only affect currently existing connections.
- For more information, consult Orber's Reference Manual regarding the
- operations <c>orber:activate_audit_trail/0/1</c> and
- <c>orber:activate_audit_trail/0/1.</c></p>
- </section>
-
- <section>
- <title>FAQ</title>
- <p><em>Q: When my client, typically written in C++ or Java, invoke narrow on an Orber object reference it fails?</em></p>
- <p>A: You must register your application in the IFR by invoking <c>oe_register()</c>.
- If the object was created by a COS-application, you must run install
- (e.g. <c>cosEventApp:install()</c>).</p>
- <p>A: Confirm, by consulting the IDL specifications, that the received object reference really
- inherit from the interface you are trying to narrow it to.</p>
- <br></br>
- <p><em>Q: I am trying to register my application in the IFR but it fails. Why?</em></p>
- <p>A: If one, or more, interface in your IDL-specification inherits from
- other interface(s), you must register them before registering your
- application. Note, this also apply when you inherit interfaces
- supported by a COS-application. Hence, they must be installed prior to
- registration of your application.</p>
- <br></br>
- <p><em>Q: I have a Orber client and server residing on two different Orber instances but I only get the 'OBJECT_NOT_EXIST' exception, even though I am sure that the object is still alive?</em></p>
- <p>A: If the two Orber-ORB's are not intended to be a part of multi-node ORB, make sure that the
- two Orber-ORB's have different <em>domain</em> names set (see
- <seealso marker="ch_install#config">configuration settings</seealso>). The easiest way
- to confirm this is to invoke <c>orber:info()</c> on each node.</p>
- <br></br>
- <p><em>Q: When I'm trying to install and/or start Orber it fails?</em></p>
- <p>A: Make sure that no other Orber-ORB is already running on the same node. If so,
- change the <c>iiop_port</c> configuration parameter (see
- <seealso marker="ch_install#config">configuration settings</seealso>).</p>
- <br></br>
- <p><em>Q: My Orber server is invoked via IIOP but Orber cannot marshal the reply?</em></p>
- <p>A: Consult your IDL file to confirm that your replies are of the correct
- type. If it is correct and the return type is, for example,
- a struct, make sure you have set every field in the struct. If
- you do not do that it will be set to the atom 'undefined', which
- most certainly is not correct.</p>
- <br></br>
- <p>A: Check that you handle <c>inout</c> and <c>out</c> parameters correctly
- (see the IDL specification). For example, a function which have one
- out-parameter and should return void, then your call-back module
- should return <c>{reply, {ok, OutParam}, State}</c>. Note, even though
- the return value is void (IDL) you must reply with ok.</p>
- <br></br>
- <p><em>Q: I cannot run Orber as a multi-node ORB?</em></p>
- <p>A: Make sure that the Erlang distribution have been started for each
- node and the <c>cookies</c> are correct. For more information,
- consult the <c>System Documentation</c></p>
- <br></br>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/orber/doc/src/ch_exceptions.xml b/lib/orber/doc/src/ch_exceptions.xml
deleted file mode 100644
index 52735dc394..0000000000
--- a/lib/orber/doc/src/ch_exceptions.xml
+++ /dev/null
@@ -1,238 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2001</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CORBA System and User Defined Exceptions</title>
- <prepared></prepared>
- <docno></docno>
- <date>2000-12-19</date>
- <rev></rev>
- <file>ch_exceptions.xml</file>
- </header>
-
- <section>
- <title>System Exceptions</title>
- <p><c>Orber</c>, or any other <c>ORB</c>, may raise a <c>System Exceptions</c>.
- These exceptions contain status- and minor-fields and may not appear in the
- operations raises exception IDL-definition.</p>
-
- <section>
- <title>Status Field</title>
- <p>The status field indicates if the request was completed or not and will be
- assigned one of the following Erlang atoms:</p>
- <table>
- <row>
- <cell align="center" valign="middle"><em>Status</em></cell>
- <cell align="center" valign="middle"><em>Description</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">'COMPLETED_YES'</cell>
- <cell align="left" valign="middle">The operation was invoked on the target object but an error occurred after the object replied. This occur, for example, if a server replies but Orber is not able to marshal and send the reply to the client ORB.</cell>
- </row>
- <row>
- <cell align="left" valign="middle">'COMPLETED_NO'</cell>
- <cell align="left" valign="middle">Orber failed to invoke the operation on the target object. This occur, for example, if the object no longer exists.</cell>
- </row>
- <row>
- <cell align="left" valign="middle">'COMPLETED_MAYBE'</cell>
- <cell align="left" valign="middle">Orber invoked the operation on the target object but an error occurred and it is impossible to decide if the request really reached the object or not.</cell>
- </row>
- <tcaption>System Exceptions Status</tcaption>
- </table>
- </section>
-
- <section>
- <title>Minor Field</title>
- <p>The minor field contains an integer (VMCID), which is related to a more
- specific reason why an invocation failed. The function
- <c>orber:exception_info/1</c> can be used to map the minor code to a string.
- Note, for VMCID:s not assigned by the OMG or Orber, the documentation
- for that particular ORB must be consulted.</p>
- </section>
-
- <section>
- <title>Supported System Exceptions</title>
- <p>The OMG CORBA specification defines the following exceptions:</p>
- <list type="bulleted">
- <item><em>'BAD_CONTEXT'</em> - if a request does not contain a correct
- context this exception is raised.</item>
- <item><em>'BAD_INV_ORDER'</em> - this exception indicates that operations
- has been invoked operations in the wrong order, which would cause,
- for example, a dead-lock.</item>
- <item><em>'BAD_OPERATION'</em> - raised if the target object exists, but
- that the invoked operation is not supported.</item>
- <item><em>'BAD_PARAM'</em> - is thrown if, for example, a parameter is out
- of range or otherwise considered illegal.</item>
- <item><em>'BAD_TYPECODE'</em> - if illegal type code is passed, for example,
- encapsulated in an any data type the <c>'BAD_TYPECODE'</c> exception
- will be raised.</item>
- <item><em>'BAD_QOS'</em> - raised whenever an object cannot support the
- required quality of service.</item>
- <item><em>'CODESET_INCOMPATIBLE'</em> - raised if two ORB's cannot
- communicate due to different representation of, for example,
- <c>char</c> and/or <c>wchar</c>.</item>
- <item><em>'COMM_FAILURE'</em> - raised if an ORB is unable to setup
- communication or it is lost while an operation is in progress.</item>
- <item><em>'DATA_CONVERSION'</em> - raised if an ORB cannot convert data
- received to the native representation. See also the
- <c>'CODESET_INCOMPATIBLE'</c> exception.</item>
- <item><em>'FREE_MEM'</em> - the ORB failed to free dynamic memory and
- failed.</item>
- <item><em>'IMP_LIMIT'</em> - an implementation limit was exceeded in the
- ORB at run time. A object factory may, for example, limit the
- number of object clients are allowed to create.</item>
- <item><em>'INTERNAL'</em> - an internal failure occurred in an ORB, which
- is unrecognized. You may consider contacting the ORB providers
- support.</item>
- <item><em>'INTF_REPOS'</em> - the ORB was not able to reach the interface
- repository, or some other failure relating to the interface
- repository is detected.</item>
- <item><em>'INITIALIZE'</em> - the ORB initialization failed due to, for
- example, network or configuration error.</item>
- <item><em>'INVALID_TRANSACTION'</em> - is raised if the request carried an
- invalid transaction context.</item>
- <item><em>'INV_FLAG'</em> - an invalid flag was passed to an operation,
- which caused, for example, a connection to be closed.</item>
- <item><em>'INV_IDENT'</em> - this exception indicates that an IDL
- identifier is incorrect.</item>
- <item><em>'INV_OBJREF'</em> - this exception is raised if an object
- reference is malformed or a nil reference (see
- also corba:create_nil_objref/0).</item>
- <item><em>'INV_POLICY'</em> - the invocation cannot be made due to an
- incompatibility between policy overrides that apply to the
- particular invocation.</item>
- <item><em>'MARSHAL'</em> - this exception may be raised by the client- or
- server-side when either ORB is unable to marshal/unmarshal requests or
- replies.</item>
- <item><em>'NO_IMPLEMENT'</em> - if the operation exists but no implementation
- exists, this exception is raised.</item>
- <item><em>'NO_MEMORY'</em> - the ORB has run out of memory.</item>
- <item><em>'NO_PERMISSION'</em> - the caller has insufficient privileges,
- such as, for example, bad <c>SSL</c> certificate.</item>
- <item><em>'NO_RESOURCES'</em> - a general platform resource limit
- exceeded.</item>
- <item><em>'NO_RESPONSE'</em> - no response available of a deferred
- synchronous request.</item>
- <item><em>'OBJ_ADAPTER'</em> - indicates administrative mismatch; the object
- adapter is not able to associate an object with the implementation
- repository.</item>
- <item><em>'OBJECT_NOT_EXIST'</em> - the object have been disposed or
- terminated; clients should remove all copies of the object reference
- and initiate desired recovery process.</item>
- <item><em>'PERSIST_STORE'</em> - the ORB was not able to establish a
- connection to its persistent storage or data contained in the
- the storage is corrupted.</item>
- <item><em>'REBIND'</em> - a request resulted in, for example, a
- <c>'LOCATION_FORWARD'</c> message; if the policies are incompatible
- this exception is raised.</item>
- <item><em>'TIMEOUT'</em> - raised if a request fail to complete within the
- given time-limit.</item>
- <item><em>'TRANSACTION_MODE'</em> - a transaction policy mismatch detected.</item>
- <item><em>'TRANSACTION_REQUIRED'</em> - a transaction is required for the
- invoked operation but the request contained no transaction context.</item>
- <item><em>'TRANSACTION_ROLLEDBACK'</em> - the transaction associated with
- the request has already been rolled back or will be.</item>
- <item><em>'TRANSACTION_UNAVAILABLE'</em> - no transaction context can be
- supplied since the ORB is unable to contact the Transaction
- Service.</item>
- <item><em>'TRANSIENT'</em> - the ORB could not determine the current status
- of an object since it could not be reached. The error may be
- temporary.</item>
- <item><em>'UNKNOWN'</em> - is thrown if an implementation throws a
- non-CORBA, or unrecognized, exception.</item>
- </list>
- </section>
- </section>
-
- <section>
- <title>User Defined Exceptions</title>
- <p>User exceptions is defined in IDL-files and is listed in operations raises
- exception listing. For example, if we have the following IDL code:</p>
- <code type="none">
-module MyModule {
-
- exception MyException {};
- exception MyExceptionMsg { string ExtraInfo; };
-
- interface MyInterface {
-
- void foo()
- raises(MyException);
-
- void bar()
- raises(MyException, MyExceptionMsg);
-
- void baz();
- };
-};
- </code>
- </section>
-
- <section>
- <title>Throwing Exceptions</title>
- <p>To be able to raise <c>MyException</c> or <c>MyExceptionMsg</c> exceptions,
- the generated <c>MyModule.hrl</c> must be included, and typical usage is:</p>
- <code type="none">
--module('MyModule_MyInterface_impl').
--include("MyModule.hrl").
-
-bar(State) ->
- case TestingSomething of
- ok ->
- {reply, ok, State};
- {error, Reason} when list(Reason) ->
- corba:raise(#'MyModule_MyExceptionMsg'{'ExtraInfo' = Reason});
- error ->
- corba:raise(#'MyModule_MyException'{})
- end.
- </code>
- </section>
-
- <section>
- <title>Catching Exceptions</title>
- <p>Depending on which operation we invoke we must be able to handle:</p>
- <list type="bulleted">
- <item>foo - <c>MyException</c> or a system exception.</item>
- <item>bar - <c>MyException</c>, <c>MyExceptionMsg</c> or a system
- exception.</item>
- <item>baz - a system exception.</item>
- </list>
- <p>Catching and matching exceptions can bee done in different ways:</p>
- <code type="none">
- case catch 'MyModule_MyInterface':bar(MIReference) of
- ok ->
- %% The operation raised no exception.
- ok;
- {'EXCEPTION', #'MyModule_MyExceptionMsg'{'ExtraInfo' = Reason}} ->
- %% If we want to log the Reason we must extract 'ExtraInfo'.
- error_logger:error_msg("Operation 'bar' raised: ~p~n", [Reason]),
- ... do something ...;
- {'EXCEPTION', E} when record(E, 'OBJECT_NOT_EXIST') ->
- ... do something ...;
- {'EXCEPTION', E} ->
- ... do something ...
- end.
- </code>
- </section>
-</chapter>
-
diff --git a/lib/orber/doc/src/ch_idl_to_erlang_mapping.xml b/lib/orber/doc/src/ch_idl_to_erlang_mapping.xml
deleted file mode 100644
index a0feda3f84..0000000000
--- a/lib/orber/doc/src/ch_idl_to_erlang_mapping.xml
+++ /dev/null
@@ -1,1504 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>OMG IDL to Erlang Mapping</title>
- <prepared></prepared>
- <docno></docno>
- <date>1998-10-10</date>
- <rev></rev>
- <file>ch_idl_to_erlang_mapping.xml</file>
- </header>
-
- <section>
- <title>OMG IDL to Erlang Mapping - Overview</title>
- <p>The purpose of OMG IDL, <em>Interface Definition Language</em>, mapping
- is to act as translator between platforms and languages. An IDL
- specification is supposed to describe data types, object types etc.</p>
- <p>CORBA is independent of the programming language used to construct
- clients or implementations. In order to use the ORB, it is
- necessary for programmers to know how to access ORB functionality
- from their programming languages. It translates different IDL constructs
- to a specific programming language. This chapter
- describes the mapping of OMG IDL constructs to the Erlang programming
- language.</p>
- </section>
-
- <section>
- <title>OMG IDL Mapping Elements</title>
- <p>A complete language mapping will allow the programmer to have
- access to all ORB functionality in a way that is convenient for
- a specified programming language.
- </p>
- <p>All mapping must define the following elements:
- </p>
- <list type="bulleted">
- <item>All OMG IDL basic and constructed types</item>
- <item>References to constants defined in OMG IDL</item>
- <item>References to objects defined in OMG IDL</item>
- <item>Invocations of operations, including passing of
- parameters and receiving of results</item>
- <item>Exceptions, including what happens when an operation
- raises an exception and how the exception parameters are
- accessed</item>
- <item>Access to attributes</item>
- <item>Signatures for operations defined by the ORB, such as
- dynamic invocation interface, the object adapters etc.</item>
- <item>Scopes;
- OMG IDL has several levels of scopes, which are mapped to Erlang's
- two scopes.</item>
- </list>
- </section>
-
- <section>
- <title>Getting Started</title>
- <p>To begin with, we should decide which type of objects (i.e. servers) we
- need and if two, or more, should export the same functionality. Let us
- assume that we want to create a system for DB (database) access for different
- kind of users. For example, anyone with a valid password may extract
- data, but only a few may update the DB. Usually, an application
- is defined within a <c>module</c>, and all global datatypes are defined
- on the top-level. To begin with we create a module and the interfaces we
- need:</p>
- <code type="none">
-// DB IDL
-#ifndef _DB_IDL_
-#define _DB_IDL_
-// A module is simply a container
-module DB {
-
- // An interface maps to a CORBA::Object.
- interface CommonUser {
-
- };
-
- // Inherit the Consumer interface
- interface Administrator : CommonUser {
-
- };
-
- interface Access {
-
- };
-
-};
-#endif </code>
- <p>Since the <c>Administrator</c> should be able to do the same things as the
- <c>CommonUser</c>, the previous inherits from the latter. The <c>Access</c>
- interface will grant access to the DB.
- Now we are ready to define the functionality and data types we need. But, this
- requires that we know a little bit more about the OMG IDL.</p>
- <note>
- <p>The OMG defines a set of reserved case insensitive key-words, which may
- <em>NOT</em> be used as identifiers (e.g. module name). For more
- information, see
- <seealso marker="#key_words">Reserved Compiler Names and Keywords</seealso></p>
- </note>
- </section>
-
- <section>
- <title>Basic OMG IDL Types</title>
- <p>The OMG IDL mapping is strongly typed and, even if you have a good knowledge
- of CORBA types, it is essential to read carefully the following mapping to
- Erlang types.</p>
- <p>The mapping of basic types is straightforward. Note that the
- OMG IDL double type is mapped to an Erlang float which does not
- support the full double value range.</p>
- <table>
- <row>
- <cell align="left" valign="middle">OMG IDL type</cell>
- <cell align="left" valign="middle">Erlang type</cell>
- <cell align="left" valign="middle">Note</cell>
- </row>
- <row>
- <cell align="left" valign="middle">float</cell>
- <cell align="left" valign="middle">Erlang float</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">double</cell>
- <cell align="left" valign="middle">Erlang float</cell>
- <cell align="left" valign="middle">value range not supported</cell>
- </row>
- <row>
- <cell align="left" valign="middle">short</cell>
- <cell align="left" valign="middle">Erlang integer</cell>
- <cell align="left" valign="middle">-2^15 .. 2^15-1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">unsigned short</cell>
- <cell align="left" valign="middle">Erlang integer</cell>
- <cell align="left" valign="middle">0 .. 2^16-1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">long</cell>
- <cell align="left" valign="middle">Erlang integer</cell>
- <cell align="left" valign="middle">-2^31 .. 2^31-1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">unsigned long</cell>
- <cell align="left" valign="middle">Erlang integer</cell>
- <cell align="left" valign="middle">0 .. 2^32-1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">long long</cell>
- <cell align="left" valign="middle">Erlang integer</cell>
- <cell align="left" valign="middle">-2^63 .. 2^63-1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">unsigned long long</cell>
- <cell align="left" valign="middle">Erlang integer</cell>
- <cell align="left" valign="middle">0 .. 2^64-1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">char</cell>
- <cell align="left" valign="middle">Erlang integer</cell>
- <cell align="left" valign="middle">ISO-8859-1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">wchar</cell>
- <cell align="left" valign="middle">Erlang integer</cell>
- <cell align="left" valign="middle">UTF-16 (ISO-10646-1:1993)</cell>
- </row>
- <row>
- <cell align="left" valign="middle">boolean</cell>
- <cell align="left" valign="middle">Erlang atom</cell>
- <cell align="left" valign="middle">true/false</cell>
- </row>
- <row>
- <cell align="left" valign="middle">octet</cell>
- <cell align="left" valign="middle">Erlang integer</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">any</cell>
- <cell align="left" valign="middle">Erlang record</cell>
- <cell align="left" valign="middle">#any{typecode, value}</cell>
- </row>
- <row>
- <cell align="left" valign="middle">long double</cell>
- <cell align="left" valign="middle">Not supported</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">Object</cell>
- <cell align="left" valign="middle">Orber object reference</cell>
- <cell align="left" valign="middle">Internal Representation</cell>
- </row>
- <row>
- <cell align="left" valign="middle">void</cell>
- <cell align="left" valign="middle">Erlang atom</cell>
- <cell align="left" valign="middle">ok</cell>
- </row>
- <tcaption>OMG IDL basic types</tcaption>
- </table>
- <p>The <c>any</c> value is written as a record with the field typecode which
- contains the <term id="Type Code"><termdef>Type Code is a full definition of a type </termdef></term>representation,
- <seealso marker="#tk_values">see also the Type Code table</seealso>,
- and the value field itself.</p>
- <p>Functions with return type <c>void</c> will return the atom <c>ok</c>.</p>
- </section>
-
- <section>
- <title>Template OMG IDL Types and Complex Declarators</title>
- <p>Constructed types all have native mappings as shown in the table
- below.</p>
- <table>
- <row>
- <cell align="left" valign="middle"><em>Type</em></cell>
- <cell align="left" valign="middle"><em>IDL code</em></cell>
- <cell align="left" valign="middle"><em>Maps to</em></cell>
- <cell align="left" valign="middle"><em>Erlang code</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>string</em></cell>
- <cell align="left" valign="middle">typedef string S; <br></br>
-void op(in S a);</cell>
- <cell align="left" valign="middle">Erlang string</cell>
- <cell align="left" valign="middle">ok = op(Obj, "Hello World"),</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>wstring</em></cell>
- <cell align="left" valign="middle">typedef wstring S; <br></br>
-void op(in S a);</cell>
- <cell align="left" valign="middle">Erlang list of Integers</cell>
- <cell align="left" valign="middle">ok = op(Obj, "Hello World"),</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>sequence</em></cell>
- <cell align="left" valign="middle">typedef sequence &lt;long, 3&gt; S; <br></br>
-void op(in S a);</cell>
- <cell align="left" valign="middle">Erlang list</cell>
- <cell align="left" valign="middle">ok = op(Obj, [1, 2, 3]),</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>array</em></cell>
- <cell align="left" valign="middle">typedef string S[2]; <br></br>
-void op(in S a);</cell>
- <cell align="left" valign="middle">Erlang tuple</cell>
- <cell align="left" valign="middle">ok = op(Obj, {"one", "two"}),</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>fixed</em></cell>
- <cell align="left" valign="middle">typedef fixed&lt;3,2> myFixed; <br></br>
-void op(in myFixed a);</cell>
- <cell align="left" valign="middle">Erlang tuple</cell>
- <cell align="left" valign="middle">MF = fixed:create(3, 2, 314), <br></br>
-ok = op(Obj, MF),</cell>
- </row>
- <tcaption>OMG IDL Template and Complex Declarators</tcaption>
- </table>
-
- <section>
- <title>String/WString Data Types</title>
- <p>A <c>string</c> consists of all possible 8-bit quantities except null.
- Most ORB:s uses, including Orber, the character set Latin-1 (ISO-8859-1).
- The <c>wstring</c> type is represented as a list of integers, where
- each integer represents a wide character. In this case Orber uses, as
- most other ORB:s, the UTF-16 (ISO-10646-1:1993) character set.</p>
- <p>When defining a a string or wstring they can be of limited length or
- null terminated:</p>
- <code type="none"><![CDATA[
-// Null terminated
-typedef string myString;
-typedef wstring myWString;
-// Maximum length 10
-typedef string<10> myString10;
-typedef wstring<10> myWString10;
- ]]></code>
- <p>If we want to define a char/string or wchar/wstring constant, we can
- use octal (\OOO - one, two or three octal digits),
- hexadecimal (\xHH - one or two hexadecimal digits) and unicode (\uHHHH -
- one, two, three or four hexadecimal digits.) representation as well.
- For example:</p>
- <code type="none">
-const string SwedensBestSoccerTeam = "\101" "\x49" "\u004B";
-const wstring SwedensBestHockeyTeam = L"\101\x49\u004B";
-const char aChar = '\u004B';
-const wchar aWchar = L'\u004C';
- </code>
- <p>Naturally, we can use <c>"Erlang"</c>, <c>L"Rocks"</c>, <c>'A'</c>
- and <c>L'A'</c> as well.</p>
- </section>
-
- <section>
- <title>Sequence Data Type</title>
- <p>A sequence can be defined to be of a maximum length or unbounded, and may
- contain Basic and Template types and scoped names:</p>
- <code type="none"><![CDATA[
-typedef sequence <short, 1> aShortSequence;
-typedef sequence <long> aLongSequence;
-typedef sequence <aLongSequence> anEvenLongerSequence;
- ]]></code>
- </section>
-
- <section>
- <title>Array Data Type</title>
- <p>Arrays are multidimensional, fixed-size arrays. The indices is language
- mapping specific, which is why one should not pass them as arguments
- to another ORB.</p>
- <code type="none">
-typedef long myMatrix[2][3];
- </code>
- </section>
-
- <section>
- <title>Fixed Data Type</title>
- <p>A Fixed Point literal consists of an integer part (decimal digits),
- decimal point and a fraction part (decimal digits),
- followed by a <c>D</c> or <c>d</c>. Either the integer part or the
- fraction part may be missing; the decimal point may be missing,
- but not d/D. The integer part must be a positive integer less than 32.
- The Fraction part must be a positive integer less than or equal to
- the Integer part.</p>
- <code type="none">
-const fixed myFixed1 = 3.14D;
-const fixed myFixed2 = .14D;
-const fixed myFixed3 = 0.14D;
-const fixed myFixed4 = 3.D;
-const fixed myFixed5 = 3D;
- </code>
- <p>It is also possible to use unary (+-) and binary (+-*/) operators:</p>
- <code type="none">
-const fixed myFixed6 = 3D + 0.14D;
-const fixed myFixed7 = -3.14D;
- </code>
- <p>The Fixed Point examples above are, so called, <em>anonymous</em>
- definitions. In later CORBA specifications these have been deprecated
- as function parameters or return values. Hence, we strongly recommend that
- you do not use them. Instead, you should use:</p>
- <code type="none"><![CDATA[
-typedef fixed<5,3> myFixed53;
-const myFixed53 myFixed53constant = 03.140d;
-typedef fixed<3,2> myFixed32;
-const myFixed32 myFixed32constant = 3.14d;
-
-myFixed53 foo(in myFixed32 MF); // OK
-void bar(in fixed<5,3> MF); // Illegal
- ]]></code>
- </section>
- <p>For more information, see <seealso marker="fixed">Fixed</seealso> in
- Orber's Reference Manual.</p>
- <p>Now we continue to work on our IDL specification. To begin with, we want
- to limit the size of the logon parameters (Id and password). Since the
- <c>UserID</c> and <c>Password</c> parameters, only will be used when
- invoking operations on the <c>Access</c> interface, we may choose to define
- them within the scope that interface. To keep it simple our DB will contain
- employee information. Hence, as the DB key we choose an integer
- (<c>EmployeeNo</c>).</p>
- <code type="none"><![CDATA[
-// DB IDL
-#ifndef _DB_IDL_
-#define _DB_IDL_
-module DB {
-
- typedef unsigned long EmployeeNo;
-
- interface CommonUser {
-
- any lookup(in EmployeeNo ENo);
-
- };
-
- interface Administrator : CommonUser {
-
- void delete(in EmployeeNo ENo);
-
- };
-
- interface Access {
-
- typedef string<10> UserID;
- typedef string<10> Password;
-
- CommonUser logon(in UserID ID, in Password PW);
-
- };
-
-};
-#endif ]]></code>
- <p>But what should, for example, the <c>lookup</c> operation return? One option
- is to use the <c>any</c> data type. But, depending on what kind of data it
- encapsulates, this datatype can be rather expensive to use. We might find a
- solution to our problems among the <c>Constructed</c> IDL types.</p>
- </section>
-
- <section>
- <title>Constructed OMG IDL Types</title>
- <p>Constructed types all have native mappings as shown in the table
- below.</p>
- <table>
- <row>
- <cell align="left" valign="middle"><em>Type</em></cell>
- <cell align="left" valign="middle"><em>IDL code</em></cell>
- <cell align="left" valign="middle"><em>Maps to</em></cell>
- <cell align="left" valign="middle"><em>Erlang code</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>struct</em></cell>
- <cell align="left" valign="middle">struct myStruct { <br></br>
-long a; <br></br>
-short b; <br></br>
-}; <br></br>
-void op(in myStruct a);</cell>
- <cell align="left" valign="middle">Erlang record</cell>
- <cell align="left" valign="middle">ok = op(Obj, #'myStruct'{a=300, b=127}),</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>union</em></cell>
- <cell align="left" valign="middle">union myUnion switch(long) { <br></br>
-case 1: long a; <br></br>
-}; <br></br>
-void op(in myUnion a);</cell>
- <cell align="left" valign="middle">Erlang record</cell>
- <cell align="left" valign="middle">ok = op(Obj, #'myUnion'{label=1, value=66}),</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>enum</em></cell>
- <cell align="left" valign="middle">enum myEnum {one, two}; <br></br>
-void op(in myEnum a);</cell>
- <cell align="left" valign="middle">Erlang atom</cell>
- <cell align="left" valign="middle">ok = op(Obj, one),</cell>
- </row>
- <tcaption>OMG IDL constructed types</tcaption>
- </table>
-
- <section>
- <title>Struct Data Type</title>
- <p>A <c>struct</c> may have Basic, Template, Scoped Names and Constructed
- types as members. By using forward declaration we can define a recursive struct:</p>
- <code type="none"><![CDATA[
-struct myStruct; // Forward declaration
-typedef sequence<myStruct> myStructSeq;
-struct myStruct {
- myStructSeq chain;
-};
-
-// Deprecated definition (anonymous) not supported by IC
-struct myStruct {
- sequence<myStruct> chain;
-};
- ]]></code>
- </section>
-
- <section>
- <title>Enum Data Type</title>
- <p>The maximum number of identifiers which may defined in an enumeration
- is 2&sup3;&sup2;. The order in which the identifiers are named in the
- specification of an enumeration defines the relative order of the
- identifiers.</p>
- </section>
-
- <section>
- <title>Union Data Type</title>
- <p>A <c>union</c> may consist of:</p>
- <list type="bulleted">
- <item>Identifier</item>
- <item>Switch - may be an integer, char, boolean, enum or scoped name.</item>
- <item>Body - with or without a <c>default</c> case; may appear at
- most once.</item>
- </list>
- <p>A case label must match the defined type of the discriminator, and may only
- contain a default case if the values given in the non-default labels do
- not cover the entire range of the union's discriminant type. For example:</p>
- <code type="none">
-// Illegal default; all cases covered by
-// non-default cases.
-union BooleanUnion switch(boolean) {
- case TRUE: long TrueValue;
- case FALSE: long FalseValue;
- default: long DefaultValue;
-};
-// OK
-union BooleanUnion2 switch(boolean) {
- case TRUE: long TrueValue;
- default: long DefaultValue;
-};
- </code>
- <p>It is not necessary to list all possible values of the union discriminator
- in the body. Hence, the value of a union is the value of the discriminator
- and, in given order, one of the following:</p>
- <list type="ordered">
- <item>If the discriminator match a label, explicitly listed in a
- case statement, the value must be of the same type.</item>
- <item>If the union contains a default label, the value must match the
- type of the default label.</item>
- <item>No value. Orber then inserts the Erlang atom <c>undefined</c>
- in the value field when receiving a union from an external
- ORB.</item>
- </list>
- <p>The above can be summed up to:</p>
- <code type="none">
-// If the discriminator equals 1 or 2 the value
-// is a long. Otherwise, the atom undefined.
-union LongUnion switch(long) {
- case 1:
- case 2: long TrueValue;
-};
-// If the discriminator equals 1 or 2 the value
-// is a long. Otherwise, a boolean.
-union LongUnion2 switch(long) {
- case 1:
- case 2: long TrueValue;
- default: boolean DefaultValue;
-};
- </code>
- <p>In the same way as structs, unions can be recursive if forward
- declaration is used (anonymous types is deprecated and not supported):</p>
- <code type="none"><![CDATA[
-// Forward declaration
-union myUnion;
-typedef sequence<myUnion>myUnionSeq;
-union myUnion switch (long) {
- case 1 : myUnionSeq chain;
- default: boolean DefaultValue;
-};
- ]]></code>
-
- <note>
- <p>Recursive types (union and struct) require Light IFR. I.e. the
- IC option {light_ifr, true} is used and that Orber is configured in such a way that
- Light IFR is activated. Recursive TypeCode is currently not supported, which is
- why these cannot be encapsulated in an any data type.</p>
- </note>
-
- </section>
- <warning>
- <p>Every field in, for example, a struct must be initiated. Otherwise
- it will be set to the atom <c>undefined</c>, which Orber cannot
- encode when communicating via IIOP. In the example above, invoking
- the operation with #'myStruct'{a=300} will fail (equal to
- #'myStruct'{a=300, b=undefined})</p>
- </warning>
- <p>Now we can continue to work on our IDL specification. To begin with, we should
- determine the return value of the <c>lookup</c> operation. Since the <c>any</c>
- type can be rather expensive we can use a <c>struct</c> or a <c>union</c> instead.
- If we intend to return the same information about a employee every time we can
- use a struct. Let us assume that the DB contains the name, address, employee
- number and department.</p>
- <code type="none"><![CDATA[
-// DB IDL
-#ifndef _DB_IDL_
-#define _DB_IDL_
-module DB {
-
- typedef unsigned long EmployeeNo;
-
- enum Department {Department1, Department2};
-
- struct employee {
- EmployeeNo No;
- string Name;
- string Address;
- Department Dpt;
- };
-
- typedef employee EmployeeData;
-
- interface CommonUser {
-
- EmployeeData lookup(in EmployeeNo ENo);
-
- };
-
- interface Administrator : CommonUser {
-
- void delete(in EmployeeNo ENo);
-
- };
-
- interface Access {
-
- typedef string<10> UserID;
- typedef string<10> Password;
-
- // Since Administrator inherits from CommonUser
- // the returned Object can be of either type.
- CommonUser logon(in UserID ID, in Password PW);
-
- };
-
-};
-#endif ]]></code>
- <p>We can also define exceptions (i.e. not system exception) thrown by
- each interface. Since exceptions are thoroughly described in the chapter
- <seealso marker="ch_exceptions">System and User Defined Exceptions</seealso>,
- we choose not to. Hence, we are now ready to compile our IDL-file by
- invoking:</p>
- <pre>
-$ <input>erlc DB.idl</input>
- </pre>
- <p>or:</p>
- <pre>
-$ <input>erl</input>
-Erlang (BEAM) emulator version 5.1.1 [threads:0]
-
-Eshell V5.1.1 (abort with ^G)
-1> <input>ic:gen('DB').</input>
-ok
-2> <input>halt().</input>
- </pre>
- <p>The next step is to implement our servers. But, to be able to do that,
- we need to know how we can access data type definitions. For example,
- since a struct is mapped to an Erlang record we must include an hrl-file
- in our callback module.</p>
- </section>
-
- <section>
- <title>Scoped Names and Generated Files</title>
-
- <section>
- <title>Scoped Names</title>
- <p>Within a scope all identifiers must be unique. The following kinds of
- definitions form scopes in the OMG IDL:</p>
- <list type="bulleted">
- <item><em>module</em></item>
- <item><em>interface</em></item>
- <item><em>operation</em></item>
- <item><em>valuetype</em></item>
- <item><em>struct</em></item>
- <item><em>union</em></item>
- <item><em>exception</em></item>
- </list>
- <p>For example, since enumerants do not form a scope, the following IDL code
- is not valid:</p>
- <code type="none">
-module MyModule {
- // 'two' is not unique
- enum MyEnum {one, two};
- enum MyOtherEnum {two, three};
-};
- </code>
- <p>But, since Erlang only has two levels of scope, <em>module</em> and
- <em>function</em>, the OMG IDL scope is mapped as follows:</p>
- <list type="bulleted">
- <item><em>Function Scope</em> - used for constants, operations and attributes.</item>
- <item><em>Erlang Module Scope</em> - the Erlang module scope
- handles the remaining OMG IDL scopes.</item>
- </list>
- <p>An Erlang module, corresponding to an IDL global name, is derived by
- converting occurrences of "::" to underscore, and eliminating
- the leading "::". Hence, accessing <c>MyEnum</c> from another module, one
- use <c>MyModule::MyEnum</c></p>
- <p>For example, an operation <c>foo</c> defined in interface <c>I</c>, which
- is defined in module <c>M</c>, would be written in IDL as <c>M::I::foo</c>
- and as <c>'M_I':foo</c> in Erlang - <c>foo</c> is the function
- name and <c>'M_I'</c> is the name of the Erlang module. Applying this
- knowledge to a stripped version of the DB.idl gives:</p>
- <code type="none"><![CDATA[
-// DB IDL
-#ifndef _DB_IDL_
-#define _DB_IDL_
-// ++ topmost scope ++
-// IC generates oe_XX.erl and oe_XX.hrl.
-// XX is equal to the name of the IDL-file.
-// Tips: create one IDL-file for each top module
-// and give the file the same name (DB.idl).
-// The oe_XX.erl module is used to register data
-// in the IFR.
-module DB {
-
- // ++ Module scope ++
- // To access 'EmployeeNo' from another scope, use:
- // DB::EmployeeNo, DB::Access etc.
- typedef unsigned long EmployeeNo;
-
- enum Department {Department1, Department2};
-
- // Definitions of this struct is contained in:
- // DB.hrl
- // Access functions exported by:
- // DB_employee.erl
- struct employee {
- ... CUT ...
- };
-
- typedef employee EmployeeData;
-
- ... CUT ...
-
- // If this interface should inherit an interface
- // in another module (e.g. OtherModule) use:
- // interface Access : OtherModule::OtherInterface
- interface Access {
-
- // ++ interface scope ++
- // Types within this scope is accessible via:
- // DB::Access::UserID
- // The Stub/Skeleton for this interface is
- // placed in the module:
- // DB_Access.erl
- typedef string<10> UserID;
- typedef string<10> Password;
-
- // Since Administrator inherits from CommonUser
- // the returned Object can be of either type.
- // This operation is exported from:
- // DB_Access.erl
- CommonUser logon(in UserID ID, in Password PW);
-
- };
-
-};
-#endif ]]></code>
- <p>Using underscores in IDL names can lead to ambiguities
- due to the name mapping described above. It is advisable to
- avoid the use of underscores in identifiers. For example, the following
- definition would generate two structures named <c>x_y_z</c>.</p>
- <code type="none">
-module x {
-
- struct y_z {
- ...
- };
-
- interface y {
-
- struct z {
- ...
- };
- };
-};
- </code>
- </section>
-
- <section>
- <title>Generated Files</title>
- <p>Several files can be generated for each scope.</p>
- <list type="bulleted">
- <item>An Erlang source code file (<c>.erl</c>) is generated
- for top level scope as well as the Erlang header file.</item>
- <item>An Erlang header file (<c>.hrl</c>) will be generated for
- each scope. The header file will contain record definitions
- for all <c>struct</c>, <c>union</c> and <c>exception</c>
- types in that scope.</item>
- <item>Modules that contain at least one constant definition,
- will produce Erlang source code files (<c>.erl</c>).
- That Erlang file will contain constant functions for
- that scope.
- Modules that contain no constant definitions are considered
- empty and no code will be produced for them, but only for
- their included modules/interfaces.</item>
- <item>Interfaces will produce Erlang source code files (<c>.erl</c>),
- this code will contain all operation stub code and implementation
- functions.</item>
- <item>In addition to the scope-related files, an Erlang source file will
- be generated for each definition of the types <c>struct</c>,
- <c>union</c> and <c>exception</c> (these are the types that
- will be represented in Erlang as records).
- This file will contain special access functions for that record.</item>
- <item>The top level scope will produce two files, one header file
- (<c>.hrl</c>) and one Erlang source file (<c>.erl</c>).
- These files are named as the IDL file, prefixed with <c>oe_</c>.</item>
- </list>
- <p>After compiling DB.idl, the following files have been generated:</p>
- <list type="bulleted">
- <item><c>oe_DB.hrl</c> and <c>oe_DB.erl</c> for the top scope level.</item>
- <item><c>DB.hrl</c> for the module <c>DB</c>.</item>
- <item><c>DB_Access.hrl</c> and <c>DB_Access.erl</c> for the interface
- <c>DB_Access</c>.</item>
- <item><c>DB_CommonUser.hrl</c> and <c>DB_CommonUser.erl</c> for the interface
- <c>DB_CommonUser</c>.</item>
- <item><c>DB_Administrator.hrl</c> and <c>DB_Administrator.erl</c> for the interface
- <c>DB_Administrator</c>.</item>
- <item><c>DB_employee.erl</c> for the structure <c>employee</c> in module
- <c>DB</c>.</item>
- </list>
- <p>Since the <c>employee</c> struct is defined in the top level scope,
- the Erlang record definition is found in <c>DB.hrl</c>. IC also generates
- stubs/skeletons (e.g. <c>DB_CommonUser.erl</c>) and access functions for
- some datatypes (e.g. <c>DB_employee.erl</c>). How the stubs/skeletons are
- used is thoroughly described in
- <seealso marker="ch_stubs">Stubs/Skeletons</seealso> and
- <seealso marker="Module_Interface">Module_Interface</seealso>.</p>
- </section>
- </section>
-
- <section>
- <title>Typecode, Identity and Name Access Functions</title>
- <p>As mentioned in a previous section, <c>struct</c>, <c>union</c> and
- <c>exception</c> types yield record definitions and access code
- for that record.
- For <c>struct</c>, <c>union</c>, <c>exception</c>, <c>array</c> and
- <c>sequence</c> types, a special file is generated that holds access
- functions for <c>TypeCode</c>, <c>Identity</c> and <c>Name</c>.
- These functions are put in the file corresponding to the scope where
- they are defined. For example, the module <c>DB_employee.erl</c>,
- representing the <c>employee</c> struct, exports the following functions:</p>
- <list type="bulleted">
- <item>tc/0 - returns the type code for the struct.</item>
- <item>id/0 - returns the IFR identity of the struct. In this case
- the returned value is <c>"IDL:DB/employee:1.0"</c>, but
- if the struct was defined in the scope of <c>CommonUser</c>,
- the result would be <c>"IDL:DB/CommonUser/employee:1.0"</c>.
- However, the user usually do not need to know the Id, just
- which Erlang module contains the correct Id.</item>
- <item>name/0 - returns the scoped name of the struct. The <c>employee</c>
- struct name is <c>"DB_employee"</c>.</item>
- </list>
- <p><term id="Type Codes"><termdef>Type codes give a complete description of the type including all its components and structure.</termdef></term>are, for example, used in <seealso marker="any">Any</seealso> values.
- Hence, we can encapsulate the <c>employee</c> struct in an <c>any</c>
- type by:</p>
- <code type="none">
-%% Erlang code
-....
-AnEmployee = #'DB_employee'{'No' = 1,
- 'Name' = "Adam Ivan Kendall",
- 'Address' = "Rasunda, Solna",
- 'Dpt' = 'Department1'},
-EmployeeTC = 'DB_employee':tc(),
-EmployeeAny = any:create(EmployeeTC, AnEmployee),
-....
- </code>
- <p>For more information, see the
- <seealso marker="#tk_values">Type Code listing</seealso>.</p>
- </section>
-
- <section>
- <title>References to Constants</title>
- <p>Constants are generated as Erlang functions, and are accessed by a
- single function call. The functions are put in the file
- corresponding to the scope where they are defined. There is no
- need for an object to be started to access a constant.</p>
- <p>Example:</p>
- <code type="none">
-// m.idl
-module m {
- const float pi = 3.14;
-
- interface i {
- const float pi = 3.1415;
- };
-};
- </code>
- <p>Since the two constants are defined in different scopes, the IDL code
- above is valid, but not necessarily a good approach. After compiling
- <c>m.idl</c>, the constant definitions can be extracted by invoking:</p>
- <pre>
-$ <input>erlc m.idl</input>
-$ <input>erlc m.erl</input>
-$ <input>erl</input>
-Erlang (BEAM) emulator version 5.1.1 [threads:0]
-
-Eshell V5.1.1 (abort with ^G)
-1> <input>m:pi().</input>
-3.14
-2> <input>m_i:pi().</input>
-3.1415
-3> <input>halt().</input>
- </pre>
- </section>
-
- <section>
- <title>References to Objects Defined in OMG IDL</title>
- <p>Objects are accessed by object references. An object reference
- is an opaque Erlang term created and maintained by the ORB.</p>
- <p>Objects are implemented by providing implementations for all
- operations and attributes of the Object, <seealso marker="#op_impl">see operation implementation</seealso>.</p>
- </section>
-
- <section>
- <title>Exceptions</title>
- <p>Exceptions are handled as Erlang catch and throws. Exceptions
- are translated to messages over an IIOP bridge but converted
- back to a throw on the receiving side. Object implementations
- that invoke operations on other objects must be aware of the
- possibility of a non-local return. This includes invocation of
- ORB and IFR services. See also the
- <seealso marker="ch_exceptions">Exceptions</seealso> section.</p>
- <p>Exception parameters are mapped as an Erlang record and accessed
- as such.</p>
- <p>An object implementation that raises an exception will use the
- <c>corba:raise/1</c> function, passing the exception record as
- parameter.</p>
- </section>
-
- <section>
- <title>Access to Attributes</title>
- <p>Attributes are accessed through their access functions. An
- attribute implicitly defines the <c>_get</c> and <c>_set</c>
- operations. These operations are handled in the same way as
- normal operations. The <c>_get</c> operation is defined as a <c>readonly</c>
- attribute.</p>
- <code type="none">
-readonly attribute long RAttribute;
-attribute long RWAttribute;
- </code>
- <p>The <c>RAttribute</c> requires that you implement, in your call-back module,
- <c>_get_RAttribute</c>. For the <c>RWAttribute</c> it is necessary to implement
- <c>_get_RWAttribute</c> and <c>_set_RWAttribute</c>.</p>
- </section>
-
- <section>
- <title>Invocations of Operations</title>
- <marker id="op_impl"></marker>
- <p>A standard Erlang <c>gen_server</c> behavior is used for
- object implementation. The <c>gen_server</c> state is then
- used as the object internal state. Implementation of the object
- function is achieved by implementing its methods and attribute operations.
- These functions will usually have the internal state as their first parameter,
- followed by any <c>in</c> and <c>inout</c> parameters. </p>
- <p>Do not confuse the
- object internal state with its object reference. The object internal state is
- an Erlang term which has a format defined by the user.</p>
- <note>
- <p>It is not always the case that the internal state will be the first parameter, as stubs can use their own object reference as the first parameter (see the IC documentation).</p>
- </note>
- <p>A function call will invoke an operation. The first
- parameter of the function should be the object reference and then
- all <c>in</c> and <c>inout</c> parameters follow in the same
- order as specified in the IDL specification. The result will be a return value
- unless the function has <c>inout</c> or <c>out</c> parameters specified;
- in which case, a tuple of the return value, followed by the parameters will
- be returned.</p>
- <p>Example:</p>
- <code type="none">
-// IDL
-module m {
- interface i {
- readonly attribute long RAttribute;
- attribute long RWAttribute;
- long foo(in short a);
- long bar(in char c, inout string s, out long count);
- void baz(out long Id);
- };
-};
- </code>
- <p>Is used in Erlang as :</p>
- <code type="none">
-%% Erlang code
-....
-Obj = ... %% get object reference
-RAttr = m_i:'_get_RAttribute'(Obj),
-RWAttr = m_i:'_get_RWAttribute'(Obj),
-ok = m_i:'_set_RWAttribute'(Obj, Long),
-R1 = m_i:foo(Obj, 55),
-{R2, S, Count} = m_i:bar(Obj, $a, "hello"),
-....
- </code>
- <p>Note how the <c>inout</c> parameter is passed <em>and</em>
- returned. There is no way to use a single occurrence of a
- variable for this in Erlang. Also note, that <c>ok</c>, Orber's
- representation of the IDL-type <c>void</c>, must be returned by
- <c>baz</c> and <c>'_set_RWAttribute'</c>.
- These operations can be implemented in the call-back module as:</p>
- <code type="none">
-'_set_RWAttribute'(State, Long) ->
- {reply, ok, State}.
-
-'_get_RWAttribute'(State) ->
- {reply, Long, State}.
-
-'_get_RAttribute'(State) ->
- {reply, Long, State}.
-
-foo(State, AShort) ->
- {reply, ALong, State}.
-
-bar(State, AShort, AString) ->
- {reply, {ALong, "MyString", ALong}, State}.
-
-baz(State) ->
- {reply, {ok, AId}, State}.
- </code>
- <p>The operations may require more arguments (depends on IC options used). For
- more information, see <seealso marker="ch_stubs">Stubs/Skeletons</seealso>
- and <seealso marker="Module_Interface">Module_Interface</seealso>.</p>
- <warning>
- <p>A function can also be defined to be <c>oneway</c>, i.e.
- asynchronous. But, since the behavior of a oneway operation is not
- defined in the OMG specifications (i.e. the behavior can differ depending on
- which other ORB Orber is communicating with), one should avoid using it.</p>
- </warning>
- </section>
-
- <section>
- <title>Implementing the DB Application</title>
- <p>Now we are ready to implement the call-back modules. There are three modules
- we must create:</p>
- <list type="bulleted">
- <item>DB_Access_impl.erl</item>
- <item>DB_CommonUser_impl.erl</item>
- <item>DB_Administrator_impl.erl</item>
- </list>
- <p>An easy way to accomplish that, is to use the IC backend <c>erl_template</c>,
- which will generate a complete call-back module. One should also add
- the same compile options, for example <c>this</c> or <c>from</c>,
- used when generating the stub/skeleton modules:</p>
- <code type="none">
-$> erlc +"{be,erl_template}" DB.idl
- </code>
- <p>We begin with implementing the <c>DB_Access_impl.erl</c> module, which,
- if we used <c>erl_template</c>, will look like the following. All we need
- to do is to add the logic to the <c>logon</c> operation.</p>
- <code type="none"><![CDATA[
-%%----------------------------------------------------------------------
-%% <LICENSE>
-%%
-%% $Id$
-%%
-%%----------------------------------------------------------------------
-%% Module : DB_Access_impl.erl
-%%
-%% Source : /home/user/example/DB.idl
-%%
-%% Description :
-%%
-%% Creation date: 2005-05-20
-%%
-%%----------------------------------------------------------------------
--module('DB_Access_impl').
-
--export([logon/3]).
-
-%%----------------------------------------------------------------------
-%% Internal Exports
-%%----------------------------------------------------------------------
--export([init/1,
- terminate/2,
- code_change/3,
- handle_info/2]).
-
-%%----------------------------------------------------------------------
-%% Include Files
-%%----------------------------------------------------------------------
-
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
-
-
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
--record(state, {}).
-
-%%======================================================================
-%% API Functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : logon/3
-%% Arguments : State - term()
-%% ID = String()
-%% PW = String()
-%% Returns : ReturnValue = OE_Reply
-%% OE_Reply = Object_Ref()
-%% Raises :
-%% Description:
-%%----------------------------------------------------------------------
-logon(State, ID, PW) ->
- %% Check if the ID/PW is valid and what
- %% type of user it is (Common or Administrator).
- OE_Reply
- = case check_user(ID, PW) of
- {ok, administrator} ->
- 'DB_Administrator':oe_create();
- {ok, common} ->
- 'DB_CommonUser':oe_create();
- error ->
- %% Here we should throw an exception
- corba:raise(....)
- end,
- {reply, OE_Reply, State}.
-
-%%======================================================================
-%% Internal Functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : init/1
-%% Arguments : Env = term()
-%% Returns : {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Raises : -
-%% Description: Initiates the server
-%%----------------------------------------------------------------------
-init(_Env) ->
- {ok, #state{}}.
-
-
-%%----------------------------------------------------------------------
-%% Function : terminate/2
-%% Arguments : Reason = normal | shutdown | term()
-%% State = term()
-%% Returns : ok
-%% Raises : -
-%% Description: Invoked when the object is terminating.
-%%----------------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-
-%%----------------------------------------------------------------------
-%% Function : code_change/3
-%% Arguments : OldVsn = undefined | term()
-%% State = NewState = term()
-%% Extra = term()
-%% Returns : {ok, NewState}
-%% Raises : -
-%% Description: Invoked when the object should update its internal state
-%% due to code replacement.
-%%----------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-
-%%----------------------------------------------------------------------
-%% Function : handle_info/2
-%% Arguments : Info = normal | shutdown | term()
-%% State = NewState = term()
-%% Returns : {noreply, NewState} |
-%% {noreply, NewState, Timeout} |
-%% {stop, Reason, NewState}
-%% Raises : -
-%% Description: Invoked when, for example, the server traps exits.
-%%----------------------------------------------------------------------
-handle_info(_Info, State) ->
- {noreply, State}.
- ]]></code>
- <p>Since <c>DB_Administrator</c> inherits from <c>DB_CommonUser</c>,
- we must implement <c>delete</c> in the <c>DB_Administrator_impl.erl</c>
- module, and <c>lookup</c> in <c>DB_Administrator_impl.erl</c><em>and</em><c>DB_CommonUser_impl.erl</c>. But wait, is that really necessary? Actually,
- it is not. We simple use the IC compile option <em>impl</em>:</p>
- <pre>
-$ <input>erlc +'{{impl, "DB::CommonUser"}, "DBUser_impl"}'\
- +'{{impl, "DB::Administrator"}, "DBUser_impl"}' DB.idl</input>
-$ <input>erlc *.erl</input>
- </pre>
- <p>Instead of creating, and not the least, maintaining two call-back modules,
- we only have to deal with <c>DBUser_impl.erl</c>. If we generated the
- templates, we simply rename <c>DB_Administrator_impl.erl</c> to
- <c>DBUser_impl.erl</c>. See also the
- <seealso marker="ch_exceptions">Exceptions</seealso> chapter.
- In the following example, only the implementation of the API functions
- are shown:</p>
- <code type="none">
-%%======================================================================
-%% API Functions
-%%======================================================================
-%%----------------------------------------------------------------------
-%% Function : delete/2
-%% Arguments : State - term()
-%% ENo = unsigned_Long()
-%% Returns : ReturnValue = ok
-%% Raises :
-%% Description:
-%%----------------------------------------------------------------------
-delete(State, ENo) ->
- %% How we access the DB, for example mnesia, is not shown here.
- case delete_employee(No) of
- ok ->
- {reply, ok, State};
- error ->
- %% Here we should throw an exception if
- %% there is no match.
- corba:raise(....)
- end.
-
-%%----------------------------------------------------------------------
-%% Function : lookup/2
-%% Arguments : State - term()
-%% ENo = unsigned_Long()
-%% Returns : ReturnValue = OE_Reply
-%% OE_Reply = #'DB_employee'{No,Name,Address,Dpt}
-%% No = unsigned_Long()
-%% Name = String()
-%% Address = String()
-%% Dpt = Department
-%% Department = 'Department1' | 'Department2'
-%% Raises :
-%% Description:
-%%----------------------------------------------------------------------
-lookup(State, ENo) ->
- %% How we access the DB, for example mnesia, is not shown here.
- case lookup_employee(ENo) of
- %% We assume that we receive a 'DB_employee' struct
- {ok, Employee} ->
- OE_Reply = Employee,
- {reply, OE_Reply, State};
- error ->
- %% Here we should throw an exception if
- %% there is no match.
- corba:raise(....)
- end.
- </code>
- <p>After you have compiled both call-back modules, and implemented the missing
- functionality (e.g. lookup_employee/1), we can test our application:</p>
- <code type="none">
-%% Erlang code
-....
-%% Create an Access object
-Acc = 'DB_Access':oe_create(),
-
-%% Login is Common user and Administrator
-Adm = 'DB_Access':logon(A, "admin", "pw"),
-Com = 'DB_Access':logon(A, "comm", "pw"),
-
-%% Lookup existing employee
-Employee = 'DB_Administrator':lookup(Adm, 1),
-Employee = 'DB_CommonUser':lookup(Adm, 1),
-
-%% If we try the same using the DB_CommonUser interface
-%% it result in an exit since that operation is not exported.
-{'EXIT', _} = (catch 'DB_CommonUser':delete(Adm, 1)),
-
-%% Try to delete the employee via the CommonUser Object
-{'EXCEPTION', _} = (catch 'DB_Administrator':delete(Com, 1)),
-
-%% Invoke delete operation on the Administrator object
-ok = 'DB_Administrator':delete(Adm, 1),
-....
- </code>
- </section>
-
- <section>
- <title>Reserved Compiler Names and Keywords</title>
- <marker id="key_words"></marker>
- <p>The use of some names is strongly discouraged due to
- ambiguities. However, the use of some names is prohibited
- when using the Erlang mapping , as they are strictly reserved for IC.</p>
- <p>IC reserves all identifiers starting with <c>OE_</c> and <c>oe_</c>
- for internal use.</p>
- <p>Note also, that an identifier in IDL can contain alphabetic,
- digits and underscore characters, but the first character
- <em>must</em> be alphabetic.
- </p>
- <p>The OMG defines a set of reserved words, shown below, for use as keywords.
- These may <em>not</em> be used as, for example, identifiers. The keywords
- which are not in bold face was introduced in the OMG CORBA-3.0
- specification.</p>
- <table>
- <row>
- <cell align="left" valign="middle"><em>abstract</em></cell>
- <cell align="left" valign="middle"><em>exception</em></cell>
- <cell align="left" valign="middle"><em>inout</em></cell>
- <cell align="left" valign="middle">provides</cell>
- <cell align="left" valign="middle"><em>truncatable</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>any</em></cell>
- <cell align="left" valign="middle">emits</cell>
- <cell align="left" valign="middle"><em>interface</em></cell>
- <cell align="left" valign="middle"><em>public</em></cell>
- <cell align="left" valign="middle"><em>typedef</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>attribute</em></cell>
- <cell align="left" valign="middle"><em>enum</em></cell>
- <cell align="left" valign="middle"><em>local</em></cell>
- <cell align="left" valign="middle">publishes</cell>
- <cell align="left" valign="middle">typeid</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>boolean</em></cell>
- <cell align="left" valign="middle">eventtype</cell>
- <cell align="left" valign="middle"><em>long</em></cell>
- <cell align="left" valign="middle"><em>raises</em></cell>
- <cell align="left" valign="middle">typeprefix</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>case</em></cell>
- <cell align="left" valign="middle"><em>factory</em></cell>
- <cell align="left" valign="middle"><em>module</em></cell>
- <cell align="left" valign="middle"><em>readonly</em></cell>
- <cell align="left" valign="middle"><em>unsigned</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>char</em></cell>
- <cell align="left" valign="middle"><em>FALSE</em></cell>
- <cell align="left" valign="middle">multiple</cell>
- <cell align="left" valign="middle">setraises</cell>
- <cell align="left" valign="middle"><em>union</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">component</cell>
- <cell align="left" valign="middle">finder</cell>
- <cell align="left" valign="middle"><em>native</em></cell>
- <cell align="left" valign="middle"><em>sequence</em></cell>
- <cell align="left" valign="middle">uses</cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>const</em></cell>
- <cell align="left" valign="middle"><em>fixed</em></cell>
- <cell align="left" valign="middle"><em>Object</em></cell>
- <cell align="left" valign="middle"><em>short</em></cell>
- <cell align="left" valign="middle"><em>ValueBase</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">consumes</cell>
- <cell align="left" valign="middle"><em>float</em></cell>
- <cell align="left" valign="middle"><em>octet</em></cell>
- <cell align="left" valign="middle"><em>string</em></cell>
- <cell align="left" valign="middle"><em>valuetype</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>context</em></cell>
- <cell align="left" valign="middle">getraises</cell>
- <cell align="left" valign="middle"><em>oneway</em></cell>
- <cell align="left" valign="middle"><em>struct</em></cell>
- <cell align="left" valign="middle"><em>void</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>custom</em></cell>
- <cell align="left" valign="middle">home</cell>
- <cell align="left" valign="middle"><em>out</em></cell>
- <cell align="left" valign="middle"><em>supports</em></cell>
- <cell align="left" valign="middle"><em>wchar</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>default</em></cell>
- <cell align="left" valign="middle">import</cell>
- <cell align="left" valign="middle">primarykey</cell>
- <cell align="left" valign="middle"><em>switch</em></cell>
- <cell align="left" valign="middle"><em>wstring</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle"><em>double</em></cell>
- <cell align="left" valign="middle"><em>in</em></cell>
- <cell align="left" valign="middle"><em>private</em></cell>
- <cell align="left" valign="middle"><em>TRUE</em></cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <tcaption>OMG IDL keywords</tcaption>
- </table>
- <p>The keywords listed above must be written exactly as shown. Any usage
- of identifiers that collide with a keyword is illegal. For example,
- <em>long</em> is a valid keyword; <em>Long</em> and <em>LONG</em> are
- illegal as keywords and identifiers. But, since the OMG must be able
- to expand the IDL grammar, it is possible to use <em>Escaped Identifiers</em>. For example, it is not unlikely that <c>native</c>
- have been used in IDL-specifications as identifiers. One option is to
- change all occurrences to <c>myNative</c>. Usually, it is necessary
- to change programming language code that depends upon that IDL as well.
- Since Escaped Identifiers just disable type checking (i.e. if it is a reserved
- word or not) and leaves everything else unchanged, it is only necessary to
- update the IDL-specification. To escape an identifier, simply prefix it
- with <em>_</em>. The following IDL-code is illegal:</p>
- <code type="none">
-typedef string native;
-interface i {
- void foo(in native Arg);
- };
-};
- </code>
- <p>With Escaped Identifiers the code will look like:</p>
- <code type="none">
-typedef string _native;
-interface i {
- void foo(in _native Arg);
- };
-};
- </code>
- </section>
-
- <section>
- <title>Type Code Representation</title>
- <marker id="tk_values"></marker>
- <p>Type Codes are used in <c>any</c> values. To avoid mistakes, you should
- use access functions exported by the Data Types modules
- (e.g. struct, union etc) or the <seealso marker="orber_tc">orber_tc</seealso>
- module.</p>
- <table>
- <row>
- <cell align="left" valign="middle"><em>Type Code</em></cell>
- <cell align="left" valign="middle"><em>Example</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">tk_null</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">tk_void</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">tk_short</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">tk_long</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">tk_longlong</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">tk_ushort</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">tk_ulong</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">tk_ulonglong</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">tk_float</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">tk_double</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">tk_boolean</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">tk_char</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">tk_wchar</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">tk_octet</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">tk_any</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">tk_TypeCode</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">tk_Principal</cell>
- <cell align="left" valign="middle"></cell>
- </row>
- <row>
- <cell align="left" valign="middle">{tk_objref, IFRId, Name}</cell>
- <cell align="left" valign="middle">{tk_objref, "IDL:M1\I1:1.0", "I1"}</cell>
- </row>
- <row>
- <cell align="left" valign="middle">{tk_struct, IFRId, Name, [{ElemName, ElemTC}]}</cell>
- <cell align="left" valign="middle">{tk_struct, "IDL:M1\S1:1.0", "S1", [{"a", tk_long}, {"b", tk_char}]}</cell>
- </row>
- <row>
- <cell align="left" valign="middle">{tk_union, IFRId, Name, DiscrTC, DefaultNr, [{Label, ElemName, ElemTC}]} <br></br>
-Note: DefaultNr tells which of tuples in the case list that is default, or -1 if no default</cell>
- <cell align="left" valign="middle">{tk_union, "IDL:U1:1.0", "U1", tk_long, 1, [{1, "a", tk_long}, {default, "b", tk_char}]}</cell>
- </row>
- <row>
- <cell align="left" valign="middle">{tk_enum, IFRId, Name, [ElemName]}</cell>
- <cell align="left" valign="middle">{tk_enum, "IDL:E1:1.0", "E1", ["a1", "a2"]}</cell>
- </row>
- <row>
- <cell align="left" valign="middle">{tk_string, Length}</cell>
- <cell align="left" valign="middle">{tk_string, 5}</cell>
- </row>
- <row>
- <cell align="left" valign="middle">{tk_wstring, Length}</cell>
- <cell align="left" valign="middle">{tk_wstring, 7}</cell>
- </row>
- <row>
- <cell align="left" valign="middle">{tk_fixed, Digits, Scale}</cell>
- <cell align="left" valign="middle">{tk_fixed, 3, 2}</cell>
- </row>
- <row>
- <cell align="left" valign="middle">{tk_sequence, ElemTC, Length}</cell>
- <cell align="left" valign="middle">{tk_sequence, tk_long, 4}</cell>
- </row>
- <row>
- <cell align="left" valign="middle">{tk_array, ElemTC, Length}</cell>
- <cell align="left" valign="middle">{tk_array, tk_char, 9}</cell>
- </row>
- <row>
- <cell align="left" valign="middle">{tk_alias, IFRId, Name, TC}</cell>
- <cell align="left" valign="middle">{tk_alias, "IDL:T1:1.0", "T1", tk_short}</cell>
- </row>
- <row>
- <cell align="left" valign="middle">{tk_except, IFRId, Name, [{ElemName, ElemTC}]}</cell>
- <cell align="left" valign="middle">{tk_except, "IDL:Exc1:1.0", "Exc1", [{"a", tk_long}, {"b", {tk_string, 0}}]}</cell>
- </row>
- <tcaption>Type Code tuples</tcaption>
- </table>
- </section>
-</chapter>
-
diff --git a/lib/orber/doc/src/ch_ifr.xml b/lib/orber/doc/src/ch_ifr.xml
deleted file mode 100644
index 09302ab6cc..0000000000
--- a/lib/orber/doc/src/ch_ifr.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Interface Repository</title>
- <prepared></prepared>
- <docno></docno>
- <date>1998-10-10</date>
- <rev></rev>
- <file>ch_ifr.xml</file>
- </header>
-
- <section>
- <title>Interface Repository(IFR)</title>
- <p>The IFR is an interface repository built on the Mnesia
- application. Orber uses the IFR for some type-checking
- when coding/decoding IIOP. The IFR is capable of storing all
- interfaces and declarations of OMG IDL.
- </p>
- <p>The interface repository is mainly used for dynamical
- interfaces, and as none are currently supported this function
- is only really used for retrieving information about interfaces.</p>
- <p>Functions relating to the manipulation of the IFR including,
- initialization of the IFR, as well as, locating, creating and
- destroying initial references are detailed further in the Manual
- Pages.
- </p>
- </section>
-</chapter>
-
diff --git a/lib/orber/doc/src/ch_install.xml b/lib/orber/doc/src/ch_install.xml
deleted file mode 100644
index 9bc974225d..0000000000
--- a/lib/orber/doc/src/ch_install.xml
+++ /dev/null
@@ -1,1001 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Installing Orber</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>1998-09-28</date>
- <rev></rev>
- <file>ch_install.xml</file>
- </header>
-
- <section>
- <title>Installation Process </title>
- <p>This chapter describes how to install Orber in an Erlang
- Environment.</p>
-
- <section>
- <title>Preparation</title>
- <p>To begin with, you must decide if you want to run Orber as a:</p>
- <list type="bulleted">
- <item><em>Single node (non-distributed)</em> - all communication with other
- Orber instances and ORB's supplied by other vendors use the OMG
- GIOP protocol.</item>
- <item><em>Multi node (distributed)</em> - all Orber nodes, within the same
- <c>domain</c>, communicate via the Erlang distribution protocol.
- For all other Orber instances, i.e. not part of the same <c>domain</c>,
- and ORB's supplied by other vendors, the OMG GIOP protocol
- is used.</item>
- </list>
- <p>Which approach to use is highly implementation specific, but a few
- things you should consider:</p>
- <list type="bulleted">
- <item>All nodes within an Orber domain should have the same
- security level.</item>
- <item>If the capacity is greater than load (volume of traffic)
- a single-node Orber might be a good solution.</item>
- <item>In some cases the distributed system architecture requires a
- single-node <term id="Orber installation"><termdef>is the structure of the ORB or ORBs as defined during the install process is called the "installation".</termdef></term>.</item>
- <item>A multi-node Orber makes it possible to load balance
- and create a more fault tolerant system. The Objects
- can also have a uniform view if you use distributed
- Mnesia tables.</item>
- <item>Since the GIOP protocol creates a larger overhead than the
- Erlang distribution protocol, the performance will be better
- when communicating with Objects within the same Orber domain
- compared with inter ORB communication (GIOP).</item>
- </list>
- <p>You also have to decide if you want Orber to store internal data using
- <c>disc_copies</c> and/or <c>ram_copies</c>. Which storage type you should
- depends if/how you intend to use Mnesia in your application. If you
- intend to use <c>disc_copies</c> you must start with creating a Mnesia
- schema, which contain information about the location of the Erlang nodes
- where Orber is planned to be run. For more background information,
- see the Mnesia documentation.</p>
- <p>In some cases it is absolutely necessary to change the default configuration
- of Orber. For example, if two Orber-ORB's shall be able to communicate
- via GIOP, they must have a unique <c>domain</c> domain. Consult the
- <seealso marker="ch_install#config">configuration settings</seealso>
- section. If you encounter any problems; see the chapter about
- <em>Debugging</em> in this User's Guide.</p>
- </section>
-
- <section>
- <title>Jump Start Orber</title>
- <p>The easiest way to start Orber is to use <c>orber:jump_start(Port)</c>,
- which start a single-node ORB with (most likely) a unique
- domain (i.e. "IP-number:Port"). This function may only be used
- during development and testing. For any other situation, install and
- start Orber as described in the following sections.
- The listen port, i.e. iiop_port configuration parameter, is set to
- the supplied Port.</p>
- <warning>
- <p>How Orber is configured when using <c>orber:jump_start(Port)</c>
- may change at any time without warning. Hence, this operation must
- not be used in systems delivered to a customer.</p>
- </warning>
- </section>
-
- <section>
- <title>Install Single Node Orber</title>
- <p>Since a single node Orber communicate via the OMG GIOP protocol it is not
- necessary to start the Erlang distribution (i.e. using <c>-name/-sname</c>).</p>
- <p>If we use <c>ram_copies</c> there is no need for creating a disk based
- schema. Simply use:</p>
- <code type="none">
-erl> mnesia:start().
-erl> corba:orb_init([{domain, "MyRAMSingleNodeORB"}]).
-erl> orber:install([node()], [{ifr_storage_type, ram_copies}]).
-erl> orber:start().
- </code>
- <p>If you installation requires <c>disc_copies</c> you must begin with
- creating a Mnesia schema. Otherwise, the installation is similar
- to a RAM installation:</p>
- <code type="none">
-erl> mnesia:create_schema([node()]).
-erl> mnesia:start().
-erl> corba:orb_init([{domain, "MyDiskSingleNodeORB"}]).
-erl> orber:install([node()], [{ifr_storage_type, disc_copies},
- {nameservice_storage_type, disc_copies}]).
-erl> orber:start().
- </code>
- <p>You can still choose to store the IFR data as ram_copies, but then
- the data must be re-installed (i.e. invoke <c>orber:install/2</c>)
- if the node is restarted. Hence, since the IFR data is rather static
- you should use <c>disc_copies</c>. For more information see the
- <c>orber</c> section in the reference manual.</p>
- <p>If you do not need to change Orber's configuration you can skip
- <seealso marker="corba">orb_init/1</seealso>.
- But, you <em>should</em> at least set the IIOP timeout parameters.</p>
- </section>
-
- <section>
- <title>Install RAM Based Multi Node Orber</title>
- <p>Within a domain Orber uses the Erlang distribution protocol. Hence, you
- <em>must</em> start it first by, for example, using:</p>
- <code type="none">
-hostA> erl -sname nodeA
- </code>
- <p>In this example, we assume that we want to use two nodes; <c>nodeA</c> and
- <c>nodeB</c>. Since Mnesia must know which other nodes should a part
- of the distribution we either need to add the Mnesia configuration
- parameter <c>extra_db_nodes</c> or use <c>mnesia:change_config/2</c>. To
- begin with, Mnesia must be started on all nodes before we can install
- Orber:</p>
- <code type="none">
-nodeA@hostA> mnesia:start().
-nodeA@hostA> mnesia:change_config(extra_db_nodes,
- [nodeA@hostA, nodeB@hostB]).
- </code>
- <p>After that the above have been repeated on <c>nodeB</c> we must
- first make sure that both nodes will use the same domain name, then
- we can install Orber:</p>
- <code type="none">
-nodeA@hostA> corba:orb_init([{domain, "MyRAMMultiNodeORB"}]).
-nodeA@hostA> orber:install([nodeA@hostA, nodeB@hostB],
- [{ifr_storage_type, ram_copies}]).
-nodeA@hostA> orber:start().
- </code>
- <p>Note that you can only invoke <c>orber:install/1/2</c> on one of the
- nodes. Now we can start Orber on the other node:</p>
- <code type="none">
-nodeB@hostB> corba:orb_init([{domain, "MyRAMMultiNodeORB"}]).
-nodeB@hostB> orber:start().
- </code>
- </section>
-
- <section>
- <title>Install Disk Based Multi Node Orber</title>
- <p>As for RAM based multi-node Orber installations, the Erlang distribution
- must be started (e.g. erl -sname nodeA). The major difference is that
- when it is disk based a Mnesia schema must be created:</p>
- <code type="none">
-nodeA@hostA> mnesia:create_schema([nodeA@hostA, nodeB@hostB]).
-nodeA@hostA> mnesia:start().
- </code>
- <p>In this example, we assume that we want to use two nodes; <c>nodeA</c> and
- <c>nodeB</c>. Since it is not possible to create a schema on more than
- one node. Hence, all we have to do is to start Mnesia (i.e. invoke
- <c>mnesia:start()</c>) on <c>nodeB</c>.</p>
- <p>After Mnesia have been started on all nodes, you must confirm that all
- nodes have the same domain name, then Orber is ready to be installed:</p>
- <code type="none">
-nodeA@hostA> corba:orb_init([{domain, "MyDiskMultiNodeORB"}]).
-nodeA@hostA> orber:install([nodeA@hostA, nodeB@hostB],
- [{ifr_storage_type, disc_copies}]).
-nodeA@hostA> orber:start().
- </code>
- <p>Note that you can only invoke <c>orber:install/1/2</c> on one of the
- nodes. Now we can start Orber on the other node:</p>
- <code type="none">
-nodeB@hostB> corba:orb_init([{domain, "MyDiskMultiNodeORB"}]).
-nodeB@hostB> orber:start().
- </code>
- </section>
-
- </section>
-
- <section>
- <title>Configuration</title>
- <marker id="config"></marker>
- <p>It is essential that one configure Orber properly, to avoid, for example,
- malicious attacks and automatically terminate IIOP connections no longer
- in use. An easy way to extract information about Orber's configuration
- parameters is to invoke the operation
- <seealso marker="orber">orber:info/1/2</seealso>.
- Orber offer the following configuration parameters:</p>
- <table>
- <row>
- <cell align="center" valign="middle"><em>Key</em></cell>
- <cell align="center" valign="middle"><em>Range</em></cell>
- <cell align="center" valign="middle"><em>Default</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">domain</cell>
- <cell align="left" valign="middle">string()</cell>
- <cell align="left" valign="middle">"ORBER"</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_port</cell>
- <cell align="left" valign="middle">integer() >= 0</cell>
- <cell align="left" valign="middle">4001</cell>
- </row>
- <row>
- <cell align="left" valign="middle">nat_iiop_port</cell>
- <cell align="left" valign="middle">integer() > 0 | {local, integer(), [{integer(), integer()}]}</cell>
- <cell align="left" valign="middle">The same as <c>iiop_port</c></cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_out_ports</cell>
- <cell align="left" valign="middle">0 | {integer(),integer()}</cell>
- <cell align="left" valign="middle">0</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_out_ports_attempts</cell>
- <cell align="left" valign="middle">integer() > 0</cell>
- <cell align="left" valign="middle">1</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_out_ports_random</cell>
- <cell align="left" valign="middle">true | false</cell>
- <cell align="left" valign="middle">false</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_max_fragments</cell>
- <cell align="left" valign="middle">integer() > 0 | infinity</cell>
- <cell align="left" valign="middle">infinity</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_max_in_requests</cell>
- <cell align="left" valign="middle">integer() > 0 | infinity</cell>
- <cell align="left" valign="middle">infinity</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_max_in_connections</cell>
- <cell align="left" valign="middle">integer() > 0</cell>
- <cell align="left" valign="middle">infinity</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_backlog</cell>
- <cell align="left" valign="middle">integer() > 0</cell>
- <cell align="left" valign="middle">5</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_packet_size</cell>
- <cell align="left" valign="middle">integer() > 0 | infinity</cell>
- <cell align="left" valign="middle">infinity</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ip_address</cell>
- <cell align="left" valign="middle">string() | {multiple, [string()]}</cell>
- <cell align="left" valign="middle">All interfaces</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ip_address_local</cell>
- <cell align="left" valign="middle">string()</cell>
- <cell align="left" valign="middle">Defined by the underlying system</cell>
- </row>
- <row>
- <cell align="left" valign="middle">nat_ip_address</cell>
- <cell align="left" valign="middle">string() | {multiple, [string()]} | {local, string(), [{string(), string()}]}</cell>
- <cell align="left" valign="middle">The same as <c>ip_address</c></cell>
- </row>
- <row>
- <cell align="left" valign="middle">objectkeys_gc_time</cell>
- <cell align="left" valign="middle">integer() > 0 | infinity</cell>
- <cell align="left" valign="middle">infinity</cell>
- </row>
- <row>
- <cell align="left" valign="middle">giop_version</cell>
- <cell align="left" valign="middle">{1,0} | {1,1} | {1,2}</cell>
- <cell align="left" valign="middle">{1,1}</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_setup_connection_timeout</cell>
- <cell align="left" valign="middle">integer() > 0 | infinity</cell>
- <cell align="left" valign="middle">infinity</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_connection_timeout</cell>
- <cell align="left" valign="middle">integer() > 0 | infinity</cell>
- <cell align="left" valign="middle">infinity</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_in_connection_timeout</cell>
- <cell align="left" valign="middle">integer() > 0 | infinity</cell>
- <cell align="left" valign="middle">infinity</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_out_keepalive</cell>
- <cell align="left" valign="middle">true | false</cell>
- <cell align="left" valign="middle">false</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_in_keepalive</cell>
- <cell align="left" valign="middle">true | false</cell>
- <cell align="left" valign="middle">false</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_timeout</cell>
- <cell align="left" valign="middle">integer() > 0 | infinity</cell>
- <cell align="left" valign="middle">infinity</cell>
- </row>
- <row>
- <cell align="left" valign="middle">interceptors</cell>
- <cell align="left" valign="middle">{native, [atom()]}</cell>
- <cell align="left" valign="middle">-</cell>
- </row>
- <row>
- <cell align="left" valign="middle">local_interceptors</cell>
- <cell align="left" valign="middle">{native, [atom()]}</cell>
- <cell align="left" valign="middle">-</cell>
- </row>
- <row>
- <cell align="left" valign="middle">orbInitRef</cell>
- <cell align="left" valign="middle">[string()] | undefined</cell>
- <cell align="left" valign="middle">undefined</cell>
- </row>
- <row>
- <cell align="left" valign="middle">orbDefaultInitRef</cell>
- <cell align="left" valign="middle">string() | undefined</cell>
- <cell align="left" valign="middle">undefined</cell>
- </row>
- <row>
- <cell align="left" valign="middle">orber_debug_level</cell>
- <cell align="left" valign="middle">0 - 10</cell>
- <cell align="left" valign="middle">0</cell>
- </row>
- <row>
- <cell align="left" valign="middle">flags</cell>
- <cell align="left" valign="middle">integer() >= 0</cell>
- <cell align="left" valign="middle">0</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_acl</cell>
- <cell align="left" valign="middle">[{atom(), string()}] | [{atom(), string(), [string()]}]</cell>
- <cell align="left" valign="middle">[]</cell>
- </row>
- <row>
- <cell align="left" valign="middle">secure</cell>
- <cell align="left" valign="middle">no | ssl</cell>
- <cell align="left" valign="middle">no</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ssl_generation</cell>
- <cell align="left" valign="middle">2 | 3</cell>
- <cell align="left" valign="middle">2</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_ssl_port</cell>
- <cell align="left" valign="middle">integer() >= 0</cell>
- <cell align="left" valign="middle">4002</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_ssl_accept_timeout</cell>
- <cell align="left" valign="middle">integer() > 0 | infinity</cell>
- <cell align="left" valign="middle">infinity</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_ssl_backlog</cell>
- <cell align="left" valign="middle">integer() > 0</cell>
- <cell align="left" valign="middle">5</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_ssl_ip_address_local</cell>
- <cell align="left" valign="middle">string()</cell>
- <cell align="left" valign="middle">Defined by the underlying system</cell>
- </row>
- <row>
- <cell align="left" valign="middle">nat_iiop_ssl_port</cell>
- <cell align="left" valign="middle">integer() > 0 | {local, integer(), [{integer(), integer()}]}</cell>
- <cell align="left" valign="middle">The same as <c>iiop_ssl_port</c></cell>
- </row>
- <row>
- <cell align="left" valign="middle">ssl_server_options</cell>
- <cell align="left" valign="middle">list()</cell>
- <cell align="left" valign="middle">See the <seealso marker="ssl:ssl">SSL application</seealso>
- for valid options.</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ssl_client_options</cell>
- <cell align="left" valign="middle">list()</cell>
- <cell align="left" valign="middle">See the <seealso marker="ssl:ssl">SSL application</seealso>
- for valid options.</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_ssl_out_keepalive</cell>
- <cell align="left" valign="middle">true | false</cell>
- <cell align="left" valign="middle">false</cell>
- </row>
- <row>
- <cell align="left" valign="middle">iiop_ssl_in_keepalive</cell>
- <cell align="left" valign="middle">true | false</cell>
- <cell align="left" valign="middle">false</cell>
- </row>
- <tcaption>Orber Configuration Parameters</tcaption>
- </table>
- <br></br>
- <br></br>
- <p><em>Comments on the table 'Orber Configuration Parameters':</em></p>
- <taglist>
- <tag><em>domain</em></tag>
- <item>Since Orber domains, they are supposed to communicate via IIOP,
- <em>MUST</em> have unique names, communication will
- fail if two domains have the same name. The domain name <em>MAY NOT</em>
- contain <c>^G</c> (i.e. <c>\007</c>).</item>
- <tag><em>iiop_port</em></tag>
- <item>If set to 0 the OS will pick any vacant port.
- <br></br>
-<em>Note:</em>On a UNIX system it is preferable to
- have a IIOP port higher than 1023, since it is not recommended to
- run Erlang as a root user.</item>
- <tag><em>nat_iiop_port</em></tag>
- <item>The value is either an integer or <c>{local, DefaultNATPort, [{Port, NATPort}]}</c>. See also
- <seealso marker="ch_install#firewall">Firewall Configuration</seealso>.</item>
- <tag><em>iiop_out_ports</em></tag>
- <item>When set to 0 any available port will be used.
- If a range is specified, Orber will only
- use the local ports within the interval when trying to connect to
- another ORB (Orber acts as a client ORB). If all ports are in use
- communication will fail. Hence, it is <em>absolutely necessary</em> to
- set <c>iiop_connection_timeout</c> as well. Otherwise, connections
- no longer in use will block further communication. If one use, for
- example, <c>erl -orber iiop_out_ports "{5000,5020}"</c>, Orber
- will only use port 5000 to 5020 when connecting.
- If communicating via SSL, make sure you use a version that supports
- the local <c>{port, Port}</c> option. See also
- <seealso marker="ch_install#firewall">Firewall Configuration</seealso>.</item>
- <tag><em>iiop_out_ports_random</em></tag>
- <item>Requires that <c>iiop_out_ports</c> define a port range. If that is the
- case Orber will select a port randomly from that sequence.</item>
- <tag><em>iiop_out_ports_attempts</em></tag>
- <item>Requires that <c>iiop_out_ports</c> define a port range. If so Orber will
- accept a number of timeouts, defined by this parameter, when trying to connect
- to another ORB.</item>
- <tag><em>iiop_max_fragments</em></tag>
- <item>Limits the number of IIOP fragments allowed per request.</item>
- <tag><em>iiop_max_in_requests</em></tag>
- <item>Limits the number of concurrent incoming requests per incoming connection.</item>
- <tag><em>iiop_max_in_connections</em></tag>
- <item>Limits the number of concurrent incoming connections.</item>
- <tag><em>iiop_backlog</em></tag>
- <item>Defines the maximum length the queue of pending incoming
- connections may grow to.</item>
- <tag><em>iiop_packet_size</em></tag>
- <item>Defines the maximum size of incoming requests.
- If this limit is exceeded, the connection is closed.</item>
- <tag><em>ip_address</em></tag>
- <item>This option is used if orber only should
- listen on a specific ip interface on a multi-interface host or if
- exported IOR:s should contain multiple components. The value is
- the IPv4 or IPv6 address as a string or <c>{multiple, IPList}</c>.
- The latter requires that the object is available via the all IP addresses
- found in the list.</item>
- <tag><em>ip_address_local</em></tag>
- <item>This option defines the default local interface Orber will
- use when connecting to another ORB via IIOP, i.e., Orber act as the
- client side ORB. The value is a IPv4 or IPv6 address as a string.
- It is possible to override <c>ip_address_local</c> by defining
- <c>iiop_acl</c> or passing the Orber generic <c>interface</c> Context.
- If this option is not used, the underlying OS will choose which interface to
- use. For more information, see the
- <seealso marker="ch_install#interfaces">Interface Configuration</seealso>
- section.</item>
- <tag><em>nat_ip_address</em></tag>
- <item>The value is the ip address as
- a string (IPv4 or IPv6), <c>{multiple, IPList}</c> or
- <c>{local, DefaultNATIPAddress, [{IPAddress, NATIPAddress}]}</c>. See also
- <seealso marker="ch_install#firewall">Firewall Configuration</seealso>.</item>
- <tag><em>objectkeys_gc_time</em></tag>
- <item>This option should be set if objects are started
- using the option <c>{persistent, true}</c>.
- The value is <c>integer()</c> seconds.</item>
- <tag><em>giop_version</em></tag>
- <item>Defines the default GIOP protocol version.</item>
- <tag><em>iiop_setup_connection_timeout</em></tag>
- <item>The value is an integer (seconds) or the atom infinity.
- This option is only valid for client-side
- connections. If this option is set, attempts to connect to other ORB's
- will timeout after the given time limit. Note, if the time limit is large
- the TCP protocol may timeout before the supplied value.</item>
- <tag><em>iiop_connection_timeout</em></tag>
- <item>The value is an integer (timeout in seconds between 0 and 1000000)
- or the atom infinity. This option is only valid for client object
- connections, i.e., will have no effect on server connections. Setting this
- option will cause client connections to be terminated, if and only if,
- there are no pending requests. If there are a client still waiting for
- a reply, Orber will try again after the given seconds have passed. The main
- purpose for this option is to reduce the number of open connections; it is,
- for example, not necessary to keep a connection, only used once a day,
- open at all time.</item>
- <tag><em>iiop_in_connection_timeout</em></tag>
- <item>The same as for <c>iiop_connection_timeout</c>. The only difference is
- that this option only affects incoming connections (i.e. Orber act as
- server-side ORB).</item>
- <tag><em>iiop_out_keepalive</em></tag>
- <item>Enables periodic transmission on a connected socket, when no other
- data is being exchanged. If the other end does not respond, the
- connection is considered broken and will be terminated.
- When enabled the SO_KEEPALIVE socket level option is set.</item>
- <tag><em>iiop_in_keepalive</em></tag>
- <item>The same as for <c>iiop_out_keepalive</c>. The only difference is
- that this option only affects incoming connections.</item>
- <tag><em>iiop_timeout</em></tag>
- <item>The value is an integer (timeout in seconds between 0 and 1000000)
- or the atom infinity. This option is only valid on the client side.
- Setting this option, cause all intra-ORB requests to timeout and
- raise a system exception, e.g. <c>TIMEOUT</c>, if no replies are delivered
- within the given time limit.</item>
- <tag><em>interceptors</em></tag>
- <item>If one set this parameter, e.g.,
- <c>erl -orber interceptors "{native, ['myInterceptor']}"</c>,
- Orber will use the supplied interceptor(s) for all inter-ORB
- communication. <c>'myInterceptor'</c> is the module name of the
- interceptor. For more information, see the interceptor chapter
- in the User's Guide and the Reference Manual.</item>
- <tag><em>local_interceptors</em></tag>
- <item>If defined, its value will be
- used when activating local interceptors via
- <seealso marker="ch_install#flags">Orber Environment Flags</seealso>.
- If not defined, but the flag is set, Orber will use the value of
- the <c>interceptors</c> parameter.</item>
- <tag><em>orbInitRef</em></tag>
- <item>Setting this option, e.g.,
- <c>erl -orber orbInitRef [\"NameService=corbaloc::host.com/NameService\"]</c>,
- will alter the location from where <c>corba:resolve_initial_references(Key)</c>
- tries to find an object matching the given Key. The keys will also appear when
- invoking <c>corba:list_initial_services()</c>. This variable overrides
- <c>orbDefaultInitRef</c></item>
- <tag><em>orbDefaultInitRef</em></tag>
- <item>If a matching Key for <c>orbInitRef</c> is not
- found, and this variable is set, it determines the location from where
- <c>orber:resolve_initial_references(Key)</c> tries to find an object
- matching the given Key. Usage:
- <c>erl -orber orbDefaultInitRef \"corbaloc::host.com\"</c>.</item>
- <tag><em>orber_debug_level</em></tag>
- <item>The range is 0 to 10.
- Using level 10 is the most verbose configuration.
- This option will generate reports, using the <c>error_logger</c>,
- for abnormal situations. It is not recommended to use this option
- for delivered systems since some of the reports is not to be considered
- as errors. The main purpose is to assist during development.</item>
- <tag><em>flags</em></tag>
- <item>No flags are activated in the default case.
- The available configuration settings are described in
- <seealso marker="ch_install#flags">Orber Environment Flags</seealso>.</item>
- <tag><em>iiop_acl</em></tag>
- <item>This option must be activated by setting
- <seealso marker="ch_install#flags">Orber Environment Flags</seealso> parameter.
- The value of this parameter shall be a list of <c>[{Direction, Filter}]</c>
- and/or <c>[{Direction, Filter, [Interfaces]}]</c>. The <c>Direction</c>,
- <c>tcp_in</c>, <c>ssl_in</c>, <c>tcp_out</c> or <c>ssl_out</c>, determines if
- the Access Control List (ACL) applies to incoming or outgoing connections
- and IIOP or IIOP over SSL. The <c>Filter</c> uses a extended format of
- Classless Inter Domain Routing (CIDR). For example, <c>"123.123.123.10"</c> limits
- the connection to that particular host, while <c>"123.123.123.10/17"</c> allows
- connections to or from any host equal to the 17 most significant bits. Orber
- also allow the user to specify a certain port or port range, for example,
- <c>"123.123.123.10/17#4001"</c> and <c>"123.123.123.10/17#4001/5001"</c>
- respectively. IPv4 or none compressed IPv6 strings are accepted. <br></br>
-
- The list of <c>Interfaces</c>, IPv4 or IPv6 strings, may only contain
- <em>one</em> address for outgoing connections. For incoming connections,
- the <c>Interfaces</c> list may contain several IP strings. If set for
- outgoing connections, and access is granted, Orber will use that local
- interface when connecting to the server-side ORB. For incoming connections,
- the client-side ORB is required to use one of the listed interfaces locally.
- If it fail to do so, access will be denied. The module
- <seealso marker="orber_acl">orber_acl</seealso> provides operations for
- evaluating the access control for filters and addresses. See also the
- <seealso marker="ch_install#interfaces">Interface Configuration</seealso>
- and
- <seealso marker="ch_install#firewall">Firewall Configuration</seealso>
- chapters.</item>
- <tag><em>secure</em></tag>
- <item>Determines the security mode Orber will use, which is either
- <c>no</c> if it is an insecure domain or the type of security
- mechanism used. Currently, per default, Orber is compliant with
- <c>CSIv1</c> level 0, which means IIOP via SSL/TLS.
- The security chapter later in this manual describes how to get security
- in Orber and how the options are used.</item>
- <tag><em>ssl_generation</em></tag>
- <item>Defines which SSL version, i.e. available API, is installed. The
- default value, <c>2</c>, refers to SSL-3.1 or later, but earlier than SSL-4.0.
- If set to <c>3</c> SSL-4.0, or later, must be available. Currently it not possible
- to use <c>1</c>, it is only reserved for future use.</item>
- <tag><em>iiop_ssl_port</em></tag>
- <item>If set, the value must be an
- integer greater than zero and not equal to <em>iiop_port</em>.</item>
- <tag><em>iiop_ssl_accept_timeout</em></tag>
- <item>The value is an integer (timeout in seconds) or the atom infinity and
- determine how long the SSL handshake may take. This option should
- be set to avoid if a client never initiate the handshake.</item>
- <tag><em>iiop_ssl_backlog</em></tag>
- <item>Defines the maximum length the queue of pending incoming
- connections may grow to.</item>
- <tag><em>iiop_ssl_ip_address_local</em></tag>
- <item>This option defines the default local interface Orber will
- use when connecting to another ORB via IIOP SSL, i.e., Orber act as the
- client side ORB. The value is a IPv4 or IPv6 address as a string.
- It is possible to override <c>iiop_ssl_ip_address_local</c> by defining
- <c>iiop_acl</c> or passing the Orber generic <c>interface</c> Context.
- If this option is not used, the underlying OS will choose which interface to
- use. For more information, see the
- <seealso marker="ch_install#interfaces">Interface Configuration</seealso>
- section.</item>
- <tag><em>nat_iiop_ssl_port</em></tag>
- <item>If set, the value must be an integer greater than zero or
- <c>{local, DefaultNATPort, [{Port, NATPort}]}</c>. See also
- <seealso marker="ch_install#firewall">Firewall Configuration</seealso>.</item>
- <tag><em>ssl_server_options</em></tag>
- <item>A list of the SSL options when Orber is the server.
- In general it's just to remove the 'ssl_server_' prefix from the old options,
- i.e. <c>ssl_server_verify</c> will just be <c>verify</c> in this option list.
- See the <seealso marker="ssl:ssl">SSL application</seealso> for the correct list of possible
- options and their values.
- </item>
- <tag><em>ssl_client_options</em></tag>
- <item>A list of the SSL options when Orber is the client.
- In general it's just to remove the <c>ssl_client_</c> prefix from the old options,
- i.e. <c>ssl_client_depth</c> will just be <c>depth</c> in this option list.
- See the <seealso marker="ssl:ssl">SSL application</seealso> for the correct list of possible
- options and their values.
- </item>
- <tag><em>iiop_ssl_out_keepalive</em></tag>
- <item>Enables periodic transmission on a connected socket, when no other
- data is being exchanged. If the other end does not respond, the
- connection is considered broken and will be terminated.
- When enabled the SO_KEEPALIVE socket level option is set. Requires that
- the installed SSL version support the <em>keepalive</em> option
- and that the <em>ssl_generation</em> points to this version.</item>
- <tag><em>iiop_ssl_in_keepalive</em></tag>
- <item>The same as for <c>iiop_ssl_out_keepalive</c>. The only difference is
- that this option only affects incoming connections.</item>
- </taglist>
- <p>It is possible to invoke operations using the extra timeout parameter:</p>
- <pre>
-erl> module_interface:function(ObjRef, Timeout, ..Arguments..).
-erl> module_interface:function(ObjRef, [{timeout, Timeout}], ..Arguments..).
-erl> module_interface:function(ObjRef, ..Arguments..). </pre>
- <p>The extra Timeout argument will override the configuration parameter
- <c>iiop_timeout</c>. It is, however, not possible to use <c>infinity</c>
- to override the Timeout parameter. The Timeout option is also valid for
- objects which resides within the same <term id="Orber domain"><termdef>A domain containing several Erlang nodes, which are communicating by using the Erlang internal format. An Orber domain looks as one ORB from the environment.</termdef></term>.</p>
- <p>The <c>iiop_setup_connection_timeout</c>, <c>iiop_timeout</c>,
- <c>iiop_connection_timeout</c> and <c>iiop_in_connection_timeout</c>
- variables should be used. The specified values is implementation specific,
- i.e., WAN or LAN, but they should range from
- <c>iiop_setup_connection_timeout</c> to <c>iiop_connection_timeout</c>.</p>
- <p>To change these settings in the configuration file, the
- <c>-config</c> flag must be added to the erl command. See the
- Reference Manual
- <em>config(4)</em> for further information. The values can also
- be sent separately as
- options to the Erlang node when it is started, see the Reference
- Manual
- <em>erl(1)</em> for further information. </p>
-
- <section>
- <marker id="flags"></marker>
- <title>Orber Environment Flags</title>
- <p>The <c>Environment Flags</c> allows the user to activate debugging
- facilities or change Orber's behavior. The latter may result in that
- Orber is no longer compliant with the OMG standard, which may be necessary
- when communicating with a non-compliant ORB.</p>
- <table>
- <row>
- <cell align="left" valign="middle"><em>Hexadecimal Value</em></cell>
- <cell align="left" valign="middle"><em>OMG Compliant</em></cell>
- <cell align="left" valign="middle"><em>Description</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">0001</cell>
- <cell align="left" valign="middle">no</cell>
- <cell align="left" valign="middle">Exclude CodeSet Component</cell>
- </row>
- <row>
- <cell align="left" valign="middle">0002</cell>
- <cell align="left" valign="middle">yes</cell>
- <cell align="left" valign="middle">Local Typechecking</cell>
- </row>
- <row>
- <cell align="left" valign="middle">0004</cell>
- <cell align="left" valign="middle">yes</cell>
- <cell align="left" valign="middle">Use Host Name in IOR</cell>
- </row>
- <row>
- <cell align="left" valign="middle">0008</cell>
- <cell align="left" valign="middle">yes</cell>
- <cell align="left" valign="middle">Enable NAT</cell>
- </row>
- <row>
- <cell align="left" valign="middle">0020</cell>
- <cell align="left" valign="middle">yes</cell>
- <cell align="left" valign="middle">Local Interceptors</cell>
- </row>
- <row>
- <cell align="left" valign="middle">0080</cell>
- <cell align="left" valign="middle">yes</cell>
- <cell align="left" valign="middle">Light IFR</cell>
- </row>
- <row>
- <cell align="left" valign="middle">0100</cell>
- <cell align="left" valign="middle">yes</cell>
- <cell align="left" valign="middle">Use IPv6</cell>
- </row>
- <row>
- <cell align="left" valign="middle">0200</cell>
- <cell align="left" valign="middle">yes</cell>
- <cell align="left" valign="middle">EXIT Tolerance</cell>
- </row>
- <row>
- <cell align="left" valign="middle">0400</cell>
- <cell align="left" valign="middle">yes</cell>
- <cell align="left" valign="middle">Enable Incoming ACL</cell>
- </row>
- <row>
- <cell align="left" valign="middle">0800</cell>
- <cell align="left" valign="middle">yes</cell>
- <cell align="left" valign="middle">Enable Outgoing ACL</cell>
- </row>
- <row>
- <cell align="left" valign="middle">1000</cell>
- <cell align="left" valign="middle">yes</cell>
- <cell align="left" valign="middle">Use Current Interface in IOR</cell>
- </row>
- <tcaption>Orber Environment Flags</tcaption>
- </table>
- <p>Any combination of the flags above may be used and changes the
- behavior as follows:</p>
- <list type="bulleted">
- <item><em>Exclude CodeSet Component</em> - instruct Orber to exclude
- the CodeSet component in exported IOR:s. When activated, no
- negotiating regarding character and wide character conversions
- between the client and the server will occur. This flag will,
- most likely, cause problems if your IDL specification contains
- the data types wchar and/or wstring.</item>
- <item><em>Local Typechecking</em> -
- If activated, parameters, replies and raised exceptions
- will be checked to ensure that the data is correct. If an error
- occurs, the <c>error_logger</c> is used to generate reports.
- One <em>MAY NOT</em> use this option for delivered systems due
- to the extra overhead. Since this option activates typechecking
- for all objects generated on the target node, it is also possible
- to use the option <c>{local_typecheck, boolean()}</c>, when
- invoking <c>oe_create/2</c>, <c>oe_create_link/2</c>,
- <c>corba:create/4</c> or <c>corba:create_link/4</c>, to override
- the configuration parameter.</item>
- <item><em>Use Host Name in IOR</em> - normally Orber inserts the IP-number
- in IOR:s when they are exported. In some cases, this will cause
- the clients to open two connections instead of one.</item>
- <item><em>Enable NAT</em> - if this flag is set, it is possible to use
- the NAT (Network Address Translation) configuration parameters
- (<c>nat_iiop_port</c>, <c>nat_iiop_ssl_port</c> and
- <c>nat_ip_address</c>).</item>
- <item><em>Local Interceptors</em> - use interceptors for local
- invocations.</item>
- <item><em>Light IFR</em> - if the IFR is not explicitly used and this
- flag is set, Orber will use a minimal IFR to reduce memory usage
- and installation time.</item>
- <item><em>Use IPv6</em> - when this option is activated, Orber will use
- <c>IPv6</c> for inter-ORB communication.</item>
- <item><em>EXIT Tolerance</em> - servers will survive even though the
- call-back module caused an EXIT.</item>
- <item><em>Enable Incoming ACL</em> - activates access control for incoming
- connections.</item>
- <item><em>Enable Outgoing ACL</em> - activates access control for outgoing
- connections.</item>
- <item><em>Use Current Interface in IOR</em> - when set, Orber will add
- the interface the request came via to exported local IOR:s.</item>
- </list>
- <p>Invoking the operation
- <seealso marker="orber">orber:info/1/2</seealso> will display the currently
- set flags in a readable way.</p>
- </section>
- </section>
-
- <section>
- <title>Firewall Configuration</title>
- <marker id="firewall"></marker>
- <p>Firewalls are used to protect objects from clients in other networks or
- sub-networks, but also to restrict which hosts internal objects may connect to
- (i.e. <c>inbound protection</c> and <c>outbound protection</c>). A firewall
- can limit access based on:</p>
- <list type="bulleted">
- <item><em>Transport Level</em> - performs access control decisions based on
- address information in TCP headers.</item>
- <item><em>Application Level</em> - understands GIOP messages and the specific
- transport level inter-ORB Protocol supported e.g. IIOP.</item>
- </list>
- <p>This section describes how to configure a <c>Transport Level</c> firewall. It
- must have prior knowledge of the source to destination mappings, and
- conceptually has a configuration table containing tuples of the form:
- <c>({inhost:inport}, {outhost:outport})</c>. If there are no port restrictions
- it is rather easy to configure the firewall. Otherwise, we must consider the
- following alternatives:</p>
- <list type="bulleted">
- <item><em>Incoming Requests</em> - Orber only uses the port-numbers specified
- by the configuration parameters <em>iiop_port</em> and
- <em>iiop_ssl_port</em>. Other ORB's may use several ports but it should
- be possible to change this behavior. Consult the other ORBs
- documentation.</item>
- <item><em>Outgoing Requests</em> - Most ORB's, Orber included,
- ask the OS to supply a vacant local port when connecting to the
- server-side ORB. It is possible to change this behavior when using
- Orber (i.e. set the configuration parameter <em>iiop_out_ports</em>).</item>
- </list>
- <warning>
- <p>Using the option <c>iiop_out_ports</c> may result in that Orber runs out of
- valid ports numbers. For example, other applications may steal some of the
- ports or the number of concurrent outgoing connections to other ORBs may be
- higher than expected. To reduce, but not eliminate, the risk you should use
- <c>iiop_connection_timeout</c>.</p>
- </warning>
- <p>Firewall configuration example:</p>
- <pre>
-# "Plain" IIOP
-To: Orber-IPNo:(iiop_port) From: ORB-IPNo:X
-To: ORB-IPNo:Z From: Orber-IPNo:(iiop_out_ports | Any Port)
-
-# IIOP via SSL
-To: Orber-IPNo:(iiop_port) From: ORB-IPNo:X
-To: Orber-IPNo:(iiop_ssl_port) From: ORB-IPNo:Y
-To: ORB-IPNo:Z From: Orber-IPNo:(iiop_out_ports | Any Port)
- </pre>
- <p>If the communication take place via a
- <seealso marker="ch_install#firewall_nat">TCP Firewall with NAT</seealso>
- (Network Address Translation), we must activate this behavior and define
- the external address and/or ports.</p>
- <marker id="firewall_nat"></marker>
- <image file="firewall_nat.gif">
- <icaption>
-TCP Firewall With NAT</icaption>
- </image>
- <p>Using NAT makes it possible to use different host data for different network
- domains. This way we can share Internet Protocol address resources or
- obscure resources. To enable this feature the
- <seealso marker="ch_install#flags">Enable NAT</seealso> flag must be set and
- <c>nat_iiop_port</c>, <c>nat_iiop_ssl_port</c> and <c>nat_ip_address</c>
- configured, which maps to <c>iiop_port</c>, <c>iiop_ssl_port</c> and
- <c>ip_address</c> respectively. Hence, the firewall must be configured to
- translate the external to the internal representation correctly. If these NAT parameters
- are assigned a single port number or IP address, only those will be used when
- an IOR is exported to another ORB. When <c>ip_address</c> is set to
- <c>{multiple, [IPAddress]}</c>, <c>nat_ip_address</c> should be configured in the same
- way, so that each NAT IP address can be translated to a valid address by the firewall.
- If objects are supposed to be accessible via different interfaces and port, see also
- <seealso marker="ch_install#interfaces">Interface Configuration</seealso>,
- the options <c>{local, DefaultNATIPAddress, [{IPAddress, NATIPAddress}]}</c> and/or
- <c>{local, DefaultNATPort, [{Port, NATPort}]}</c> shall be used. The default NAT IP address
- and port, should be translated to the value of <c>ip_address_local</c> and the default
- listen port by the firewall. If the IP address and/or port is not found in the list,
- the default values will be inserted in the IOR. The firewall must be able to translate
- these correctly.</p>
- <p>If it is necessary to limit the access to an ORB within a secure network,
- but other applications running on the same host may not be blocked out,
- one can use a <em>Application Level</em> firewall or Orber Access Control
- List (ACL). The latter makes it possible for the user to define which hosts
- may communicate, either as server or client, with Orber. This is achieved by
- defining the configuration parameter
- <seealso marker="ch_install#config">iiop_acl</seealso>. The Classless Inter
- Domain Routing (CIDR) <c>Filter</c> determines which peer interfaces and
- ports the other ORB may use.</p>
- <table>
- <row>
- <cell align="left" valign="middle"><em>Filter</em></cell>
- <cell align="left" valign="middle"><em>Peer Interface(s)</em></cell>
- <cell align="left" valign="middle"><em>Peer Port(s)</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">"10.1.1.1"</cell>
- <cell align="left" valign="middle">10.1.1.1</cell>
- <cell align="left" valign="middle">any</cell>
- </row>
- <row>
- <cell align="left" valign="middle">"10.1.1.1/8"</cell>
- <cell align="left" valign="middle">10.0.0.0-10.255.255.255</cell>
- <cell align="left" valign="middle">any</cell>
- </row>
- <row>
- <cell align="left" valign="middle">"10.1.1.1/8#4001"</cell>
- <cell align="left" valign="middle">10.0.0.0-10.255.255.255</cell>
- <cell align="left" valign="middle">4001</cell>
- </row>
- <row>
- <cell align="left" valign="middle">"10.1.1.1/8#4001/5001"</cell>
- <cell align="left" valign="middle">10.0.0.0-10.255.255.255</cell>
- <cell align="left" valign="middle">4001-5001</cell>
- </row>
- <tcaption>Orber ACL Filters</tcaption>
- </table>
- <p>Orber ACL, also allows the user to define which local interface(s) may be used,
- but will not detect <c>spoofing</c>. The operation
- <seealso marker="orber_acl">orber_acl:match/2/3</seealso> makes it easy to
- verify whether access would be granted or not. For example, if Orber would
- be started with the ACL <c>[{tcp_out, "10.1.1.1/8#4001/5001"}]</c>, then
- <c>orber_acl:match/2</c> would behave as follows:</p>
- <code type="none">
-erl> orber_acl:match({11,1,1,1}, tcp_out).
-false
-
-erl> orber_acl:match({10,1,1,1}, tcp_out).
-true
-
-erl> orber_acl:match({11,1,1,1}, tcp_out, true).
-{false,[],0}
-
-erl> orber_acl:match({10,1,1,1}, tcp_out, true).
-{true,[],{4001,5001}}
- </code>
- <p>Only if the returned boolean is true the extra return values makes a
- difference. In the example above, <c>{true,[],{4001,5001}}</c> means that
- Orber may connect to <c>"10.1.1.1"</c>, using any local interface,
- if the server-side ORB listens for incoming connect requests on a port
- within the range 4001-5001. Note, invoking the <c>orber_acl:match/2/3</c>
- operation, will not result in a connect attempt by Orber. The reason for
- this, is that this function may be used on a live node as well as in test
- environment. Hence, if a local interface is currently not available or no
- server-side ORB available via the given host/port(s), will not be detected
- by Orber.</p>
- </section>
-
- <section>
- <title>Interface Configuration</title>
- <marker id="interfaces"></marker>
- <p>In many cases it is sufficient to simply configure the underlying OS which
- local interfaces shall be used for all applications. But, in some cases
- it is required, due to, for example, the firewall configuration, that different
- local interfaces are used for different applications. Some times, it is even
- necessary to use a specific interface for a single CORBA object. This section
- describe how one can alter this in different ways.</p>
- <p>The default behavior is that Orber lets the OS configuration decide which interface
- will be added in IOR:s exported to another ORB and the local interface used
- when connecting to another ORB (Orber act as client side ORB). The latter can be
- overridden by setting the configuration parameters <c>iiop_ssl_ip_address_local</c>
- and/or <c>ip_address_local</c>, which will affect IIOP via SSL and IIOP
- respectively. These parameters can be overridden by using the Orber generic
- <c>interface</c> Context or defining an ACL (Access Control List). The latter
- always takes precedence if a local interface is included (e.g.
- <c>[{tcp_out, "10.0.0.0/8", ["10.0.0.1"]}]</c>). If the interface is excluded
- (e.g. <c>[{tcp_out, "10.0.0.0/8"}]</c>), the interface chosen will, in the following
- order, be determined by
- <c>#'IOP_ServiceContext'{}</c>, <c>ip_address_local/iiop_ssl_ip_address_local</c> or
- the configuration of the underlying system.</p>
- <p>Adding the interface context, for generated stubs/skeletons, is done in the
- following way:</p>
- <code type="none">
-Ctx = #'IOP_ServiceContext'{context_id = ?ORBER_GENERIC_CTX_ID,
- context_data = {interface, "10.0.0.1"}},
-'CosNaming_NamingContext':resolve(NS, [{context, [Ctx]}], Name),
- </code>
- <p>It is also possible to add the context to
- <c>corba:string_to_object/2, corba:resolve_initial_references/2, corba:resolve_initial_references_remote/3, corba:list_initial_services_remote/2, corba_object:not_existent/2, corba_object:non_existent/2</c> and <c>corba_object:is_a/3</c>.
- The operations exported by <c>corba_object</c> are affected
- if the supplied IOR is external. The function <c>corba:string_to_object/2</c>
- might require the interface context if a <c>corbaloc</c> or a <c>corbaloc</c>
- string is passed (See the
- <seealso marker="ch_naming_service#interop_ns">INS</seealso> chapter),
- while <c>corba:resolve_initial_references_remote/3</c> and
- <c>corba:list_initial_services_remote/2</c> always connect to another ORB and
- it might be necessary to add the context.
- The remaining <c>corba</c> operations are affected if calls are re-directed
- by setting the <c>orbInitRef</c> and/or <c>orbDefaultInitRef</c> configuration
- parameters. For more information, see the Reference Manual for each module.</p>
- <p>Configuring which interface(s) that shall be used when exporting an IOR to
- another ORB, is determined by <c>nat_ip_address</c>, setting the flag
- <seealso marker="ch_install#flags">16#1000</seealso>
- and <c>ip_address</c>, in that order. Orber listens for incoming connections
- either via all interfaces or the interface defined by <c>ip_address</c>. It is
- also possible to add and remove extra listen interfaces by using
- <c>orber:add_listen_interface/2/3</c> and <c>orber:remove_listen_interface/1</c>.
- In this case one should set the 16#1000 flag and, if necessary, set the
- configuration parameters
- <c>{local, DefaultNATIPAddress, [{IPAddress, NATIPAddress}]}</c> and/or
- <c>{local, DefaultNATPort, [{Port, NATPort}]}</c>.</p>
- </section>
-</chapter>
-
diff --git a/lib/orber/doc/src/ch_interceptors.xml b/lib/orber/doc/src/ch_interceptors.xml
deleted file mode 100644
index 392fe7de82..0000000000
--- a/lib/orber/doc/src/ch_interceptors.xml
+++ /dev/null
@@ -1,279 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2001</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Orber Interceptors</title>
- <prepared>Nick</prepared>
- <docno></docno>
- <date>2001-08-16</date>
- <rev></rev>
- <file>ch_interceptors.xml</file>
- </header>
-
- <section>
- <title>Using Interceptors</title>
- <p>For Inter-ORB communication, e.g., via <c>IIOP</c>, it is possible
- to intercept requests and replies. To be able to use <c>Interceptors</c>
- Orber the configuration parameter <c>interceptors</c> must be defined.</p>
-
- <section>
- <title>Configure Orber to Use Interceptors</title>
- <p>The configuration parameter <c>interceptors</c> must be defined, e.g.,
- as command line option:</p>
- <code type="none">
-erl -orber interceptors "{native, ['myInterceptor']}"
- </code>
- <p>It is possible to use more than one interceptor; simply add them to the
- list and they will be invoked in the same order as they appear in the list.</p>
- <p>One can also active and deactivate an interceptor during
- run-time, but this will only affect currently existing connections.
- For more information, consult Orber's Reference Manual regarding the
- operations <c>orber:activate_audit_trail/0/1</c> and
- <c>orber:activate_audit_trail/0/1.</c></p>
- </section>
-
- <section>
- <title>Creating Interceptors</title>
- <p>Each supplied interceptor <em>must</em> export the following functions:</p>
- <list type="bulleted">
- <item><em>new_out_connection/3/5</em> - one of these operations is called when
- a client application calls an object residing on remote ORB.
- If an interceptor exports both versions, arity 3 and 5, which
- operation that will be invoked is Orber internal.</item>
- <item><em>new_in_connection/3/5</em> - one of these operations is invoked
- when a client side ORB tries to set up a connection to the target ORB.
- If an interceptor exports both versions, arity 3 and 5, which
- operation that will be invoked is Orber internal.</item>
- <item><em>out_request/6</em> - supplies all request data on the client side
- ORB.</item>
- <item><em>out_request_encoded/6</em> - similar to <c>out_request</c>
- but the request body is encode.</item>
- <item><em>in_request_encoded/6</em> - after a new request arrives at the
- target ORB the request data is passed to the interceptor in
- encoded format.</item>
- <item><em>in_request/6</em> - prior to invoking the operation on the
- target object, the interceptor <c>in_request</c> is called.</item>
- <item><em>out_reply/6</em> - after the target object replied the
- <c>out_reply</c> operation is called with the result of the object
- invocation.</item>
- <item><em>out_reply_encoded/6</em> - before sending a reply back to the
- client side ORB this operation is called with the result in
- encoded format.</item>
- <item><em>in_reply_encoded/6</em> - after the client side ORB receives
- a reply this function is called with the reply in encoded
- format.</item>
- <item><em>in_reply/6</em> - before delivering the reply to the client
- this operation is invoked.</item>
- <item><em>closed_in_connection/1</em> - when a connection is terminated
- on the client side this function is called.</item>
- <item><em>closed_out_connection/1</em> - if an outgoing connection is
- terminated this operation will be invoked.</item>
- </list>
- <p>The operations <c>new_out_connection</c>, <c>new_in_connection</c>,
- <c>closed_in_connection</c> and <c>closed_out_connection</c> operations
- are only invoked <em>once</em> per connection. The remaining operations
- are called, as shown below, for every Request/Reply to/from remote
- CORBA Objects.</p>
- <marker id="interceptor_operations"></marker>
- <image file="interceptor_operations.gif">
- <icaption>
-The Invocation Order of Interceptor Functions.</icaption>
- </image>
- </section>
- </section>
-
- <section>
- <title>Interceptor Example</title>
- <p>Assume we want to create a simple access service which purpose is to:</p>
- <list type="bulleted">
- <item>Only allow incoming request from ORB's residing on a certain set of
- nodes.</item>
- <item>Restrict the objects any client may invoke operations on.</item>
- <item>Only allow outgoing requests to call a limited set of external
- ORB's.</item>
- <item>Add a checksum to each binary request/reply body.</item>
- </list>
- <p>To restricts the access we use a <c>protected</c> and <c>named</c> ets-table
- holding all information. How the ets-table is initiated and maintained
- is implementation specific, but it contain
- <c>{Node, ObjectTable, ChecksumModule}</c> where <c>Node</c> is used as
- ets-key, <c>ObjectTable</c> is a reference to another ets-table in which
- we store which objects the clients are allowed to invoke operations on
- and <c>ChecksumModule</c> determines which module we should use to handle
- the checksums. </p>
- <code type="none">
-new_in_connection(Arg, Host, Port) ->
- %% Since we only use one interceptor we do not care about the
- %% input Arg since it is set do undefined by Orber.
- case ets:lookup(in_access_table, Host) of
- [] ->
- %% We may want to log the Host/Port to see if someone tried
- %% to hack in to our system.
- exit("Access not granted");
- [{Host, ObjTable, ChecksumModule}] ->
- {ObjTable, ChecksumModule}
- end.
- </code>
- <p>The returned tuple, i.e., {ObjTable, ChecksumModule}, will be passed
- as the first argument whenever invoking one of the interceptor functions.
- Unless the connection attempt did not fail we are now ready for receiving
- requests from the client side ORB.</p>
- <p>When a new request comes in the first interceptor function to be invoked is
- <c>in_request_encoded</c>. We will remove the checksum from the coded
- request body in the following way:</p>
- <code type="none">
-in_request_encoded({ObjTable, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) ->
- NewBin = ChecksumModule:remove_checksum(Bin),
- {NewBin, Extra}.
- </code>
- <p>If the checksum check fails the <c>ChecksumModule</c> should invoke exit/1.
- But if the check succeeded we are now ready to check if the client-ORB
- objects are allowed to invoke operations on the target object. Please note,
- it is possible to run both checks in <c>in_request_encoded</c>. Please
- note, the checksum calculation must be relatively fast to ensure a
- good throughput.</p>
- <p>If we want to we can restrict any clients to only use a subset of operations
- exported by a server:</p>
- <code type="none">
-in_request({ObjTable, ChecksumModule}, ObjKey, Ctx, Op, Params, Extra) ->
- case ets:lookup(ObjTable, {ObjKey, Op}) of
- [] ->
- exit("Client tried to invoke illegal operation");
- [SomeData] ->
- {Params, Extra}
- end.
- </code>
- <p>At this point Orber are now ready to invoke the operation on the target
- object. Since we do not care about what the reply is the <c>out_reply</c>
- function do nothing, i.e.:</p>
- <code type="none">
-out_reply(_, _, _, _, Reply, Extra) ->
- {Reply, Extra}.
- </code>
- <p>If the client side ORB expects a checksum to be added to the reply we
- add it by using:</p>
- <code type="none">
-out_reply_encoded({ObjTable, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) ->
- NewBin = ChecksumModule:add_checksum(Bin),
- {NewBin, Extra}.
- </code>
- <warning>
- <p>If we manipulate the binary as above the behavior <em>must</em>
- be <c>Bin == remove_checksum(add_checksum(Bin))</c>.</p>
- </warning>
- <p>For outgoing requests the principle is the same. Hence, it is not further
- described here. The complete interceptor module would look like:</p>
- <code type="none">
-
--module(myInterceptor).
-
-%% Interceptor functions.
--export([new_out_connection/3,
- new_in_connection/3,
- closed_in_connection/1,
- closed_out_connection/1,
- in_request_encoded/6,
- in_reply_encoded/6,
- out_reply_encoded/6,
- out_request_encoded/6,
- in_request/6,
- in_reply/6,
- out_reply/6,
- out_request/6]).
-
-new_in_connection(Arg, Host, Port) ->
- %% Since we only use one interceptor we do not care about the
- %% input Arg since it is set do undefined by Orber.
- case ets:lookup(in_access_table, Host) of
- [] ->
- %% We may want to log the Host/Port to see if someone tried
- %% to hack in to our system.
- exit("Access not granted");
- [{Host, ObjTable, ChecksumModule}] ->
- {ObjTable, ChecksumModule}
- end.
-
-new_out_connection(Arg, Host, Port) ->
- case ets:lookup(out_access_table, Host) of
- [] ->
- exit("Access not granted");
- [{Host, ObjTable, ChecksumModule}] ->
- {ObjTable, ChecksumModule}
- end.
-
-in_request_encoded({_, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) ->
- NewBin = ChecksumModule:remove_checksum(Bin),
- {NewBin, Extra}.
-
-in_request({ObjTable, _}, ObjKey, Ctx, Op, Params, Extra) ->
- case ets:lookup(ObjTable, {ObjKey, Op}) of
- [] ->
- exit("Client tried to invoke illegal operation");
- [SomeData] ->
- {Params, Extra}
- end.
-
-out_reply(_, _, _, _, Reply, Extra) ->
- {Reply, Extra}.
-
-out_reply_encoded({_, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) ->
- NewBin = ChecksumModule:add_checksum(Bin),
- {NewBin, Extra}.
-
-out_request({ObjTable, _}, ObjKey, Ctx, Op, Params, Extra) ->
- case ets:lookup(ObjTable, {ObjKey, Op}) of
- [] ->
- exit("Client tried to invoke illegal operation");
- [SomeData] ->
- {Params, Extra}
- end.
-
-out_request_encoded({_, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) ->
- NewBin = ChecksumModule:add_checksum(Bin),
- {NewBin, Extra}.
-
-in_reply_encoded({_, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) ->
- NewBin = ChecksumModule:remove_checksum(Bin),
- {NewBin, Extra}.
-
-in_reply(_, _, _, _, Reply, Extra) ->
- {Reply, Extra}.
-
-closed_in_connection(Arg) ->
- %% Nothing to clean up.
- Arg.
-
-closed_out_connection(Arg) ->
- %% Nothing to clean up.
- Arg.
- </code>
- <note>
- <p>One can also use interceptors for debugging purposes, e.g.,
- print which objects and operations are invoked with which arguments
- and the outcome of the operation. In conjunction with the configuration
- parameter <c>orber_debug_level</c> it is rather easy to find out what
- went wrong or just to log the traffic. </p>
- </note>
- </section>
-</chapter>
-
diff --git a/lib/orber/doc/src/ch_introduction.xml b/lib/orber/doc/src/ch_introduction.xml
deleted file mode 100644
index f04fedd0a7..0000000000
--- a/lib/orber/doc/src/ch_introduction.xml
+++ /dev/null
@@ -1,145 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Introduction to Orber</title>
- <prepared>Megan Lynch</prepared>
- <docno></docno>
- <date>1998-09-21</date>
- <rev></rev>
- <file>ch_introduction.xml</file>
- </header>
-
- <section>
- <title>Overview</title>
- <p>The Orber application is a CORBA compliant Object Request Brokers
- (ORB), which provides CORBA functionality in an Erlang
- environment. Essentially, the ORB channels communication or
- transactions between nodes in a
- heterogeneous environment.
- </p>
- <p><term id="CORBA"><termdef>Common Object Request Broker Architecture is a common communication standard developed by the OMG (Object Management Group)</termdef></term>(Common Object Request Broker
- Architecture) provides an interface definition language allowing
- efficient system integration and also supplies standard
- specifications for some services.
- </p>
- <p>The Orber application contains the following parts:</p>
- <list type="bulleted">
- <item>
- <p>ORB kernel and IIOP support</p>
- </item>
- <item>
- <p>Interface Repository</p>
- </item>
- <item>
- <p>Interface Definition Language Mapping for Erlang</p>
- </item>
- <item>
- <p>CosNaming Service</p>
- </item>
- </list>
-
- <section>
- <title>Benefits</title>
- <p>Orber provides CORBA functionality in an Erlang environment that enables:
- </p>
- <list type="bulleted">
- <item>
- <p><em>Platform interoperability and transparency</em></p>
- <p>Orber enables communication between
- OTP applications or Erlang environment applications and
- other platforms; for example, Windows NT, Solaris
- etc, allowing platform transparency. This is especially helpful in situations where there
- are many users with different platforms. For example,
- booking airline tickets would require the airline database
- and hundreds of travel agents (who may not have the same
- platform) to book seats on flights. </p>
- </item>
- <item>
- <p><em>Application level interoperability and transparency</em></p>
- <p>As Orber is a CORBA compliant application, its purpose is
- to provide interoperability and transparency on the application
- level.
- Orber simplifies the distributed system software by defining the
- environment as objects, which in effect, views
- everything as identical regardless of programming
- languages. <br></br>
- Previously, time-consuming programming was
- required to facilitate communication between different languages.
- However, with CORBA compliant Orber the Application
- Programmer is relieved of this task. This makes
- communication on an application level relatively transparent to the user.</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Purpose and Dependencies</title>
- <p>The system architecture and OTP dependencies of Orber are illustrated in figure 1 below:</p>
- <marker id="dependent"></marker>
- <image file="dependent.gif">
- <icaption>
-Figure 1: Orber Dependencies and Structure.</icaption>
- </image>
- <p>Orber is dependent on Mnesia (see the Mnesia
- documentation) - an Erlang database management application
- used to store object information.</p>
- <note>
- <p>Although Orber does not have a run-time
- application dependency to IC (an <term id="IDL"><termdef>Interface Definition Language - IDL is the OMG specified interface definition language, used to define the CORBA object interfaces.</termdef></term>compiler for
- Erlang), it is necessary when building
- services and applications. See the IC documentation for
- further details.</p>
- </note>
- <marker id="orbs"></marker>
- <image file="orbs.gif">
- <icaption>
-Figure 2: ORB interface between Java and Erlang Environment Nodes.</icaption>
- </image>
- <p>This simplified illustration in figure 2 demonstrates how Orber can facilitate communication in a heterogeneous environment. The Erlang Nodes running
- OTP and the other Node running applications written in Java can
- communicate via an <term id="ORB"><termdef>Object Request Broker - ORB open software bus architecture specified by the OMG which allows object components to communicate in a heterogeneous environment.</termdef></term>(Object Request Broker). Using
- Orber means that CORBA functions can be used to achieve this
- communication.
- </p>
- <p>For example, if one of the above nodes requests an object, it does not
- need to know if that object is located on the same, or
- different, Erlang or Java nodes. The ORB will channel the
- information creating platform and application transparency for
- the user.
- </p>
- </section>
-
- <section>
- <title>Prerequisites</title>
- <p>To fully understand the concepts presented in the
- documentation, it is recommended that the user is familiar
- with distributed programming and CORBA (Common Object Request
- Broker Architecture).
- </p>
- <p>Recommended reading includes <em>Open Telecom Platform Documentation Set</em> and <em>Concurrent Programming in Erlang</em>.
- </p>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/orber/doc/src/ch_naming_service.xml b/lib/orber/doc/src/ch_naming_service.xml
deleted file mode 100644
index bcbab2a597..0000000000
--- a/lib/orber/doc/src/ch_naming_service.xml
+++ /dev/null
@@ -1,465 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>CosNaming Service</title>
- <prepared></prepared>
- <docno></docno>
- <date>1998-10-10</date>
- <rev></rev>
- <file>ch_naming_service.xml</file>
- </header>
-
- <section>
- <title>Overview of the CosNaming Service</title>
- <p>The CosNaming Service is a service developed to help users and
- programmers identify objects by human readable names rather than by a
- reference. By binding a name to a naming context (another object), a
- contextual reference is formed. This is helpful when navigating in the
- object space. In addition, identifying objects by name allows you to evolve
- and/or relocate objects without client code modification.</p>
- <p>The CosNaming service has some concepts that are important:</p>
- <list type="bulleted">
- <item>
- <p><em>name binding</em> - a name to object association.</p>
- </item>
- <item>
- <p><em>naming context</em> - is an object that contains a set of
- name bindings in which each name is unique. Different names can be
- bound to the same object.
- </p>
- </item>
- <item>
- <p><em>to bind a name</em> - is to create a name binding in a given
- context.</p>
- </item>
- <item>
- <p><em>to resolve a name</em> - is to determine the object associated
- with the name in a given context.</p>
- </item>
- </list>
- <p>A name is always resolved in a context, there no absolute names exist.
- Because a context is like any other object, it can also be bound to
- a name
- in a naming context.
- This will result in a naming graph (a directed graph with notes and
- labeled edges). The graph allows more complex names to refer to an
- object. Given a context, you can use a sequence to reference an object.
- This sequence is henceforth referred to as <em>name</em> and the
- individual
- elements in the sequence as <em>name components</em>. All but the
- last name component are bound to naming contexts.
- </p>
- <p>The diagram in figure 1 illustrates how the Naming Service provides a
- contextual relationship between objects, NamingContexts and
- NameBindings to create an object locality, as the
- object itself, has no name.
- </p>
- <marker id="name"></marker>
- <image file="name.gif">
- <icaption>
-Figure 1: Contextual object relationships using the Naming Service.</icaption>
- </image>
- <p>The naming contexts provide a directory of contextual
- reference and naming for objects (an object can appear to
- have more than one name).
- </p>
- <p>In figure 1 the object to the right can either be
- called <c>alpha</c> from one context or <c>gamma</c> from another.
- </p>
- <p>The Naming Service has an initial naming context, which is shown
- in the diagram as the top-most object in the naming graph.
- It has two names <c>beta</c> and <c>epsilon</c>, which are bound to other
- naming contexts. The initial naming context is a well known location
- used to share a common name space between multiple programs.
- You can traverse the naming graph until you reach a name, which is
- bound to an object, which is not a naming context.
- </p>
- <p>We recommend reading <em>chapter 12, CORBA Fundamentals and Programming</em>, for detailed information regarding the
- Naming Service. </p>
- </section>
-
- <section>
- <title>The Basic Use-cases of the Naming Service</title>
- <p>The basic use-cases of the Naming Service are:
- </p>
- <list type="bulleted">
- <item>Fetch initial reference to the naming service.</item>
- <item>Creating a naming context.</item>
- <item>Binding and unbinding names to objects.</item>
- <item>Resolving a name to an object.</item>
- <item>Listing the bindings of a naming context.</item>
- <item>Destroying a naming context.</item>
- </list>
-
- <section>
- <title>Fetch Initial Reference to the Naming Service</title>
- <p>In order to use the naming service you have to fetch an
- initial reference to it. This is done with:</p>
- <code type="none">
-NS = corba:resolve_initial_references("NameService").
- </code>
- <note>
- <p>NS in the other use-cases refers to this initial reference.</p>
- </note>
- </section>
-
- <section>
- <title>Creating a Naming Context</title>
- <p>There are two functions for creating a naming context.
- The first function, which only creates a naming context object is:</p>
- <code type="none">
-NC = 'CosNaming_NamingContext':new_context(NS).
- </code>
- <p>The other function creates a naming context and binds it to a name in
- an already existing naming context (the initial context in this
- example):
- </p>
- <code type="none">
-NC = 'CosNaming_NamingContext':bind_new_context(NS, lname:new(["new"])).
- </code>
- </section>
-
- <section>
- <title>Binding and Unbinding Names to Objects</title>
- <p>The following steps illustrate how to bind/unbind an object reference
- to/from a name. For the example below, assume that the NamingContexts
- in the path are already bound to the name <c>/workgroup/services</c>,
- and that reference to the services context are in the variable
- <c>Sc</c>.</p>
- <list type="ordered">
- <item>
- <p>Use the naming library functions to create a name</p>
- <code type="none">
-Name = lname:new(["object"]).
- </code>
- </item>
- <item>
- <p>Use CosNaming::NamingContext::bind() to bind a name to an object</p>
- <code type="none">
-'CosNaming_NamingContext':bind(Sc, Name, Object).
- </code>
- </item>
- <item>
- <p>Use CosNaming::NamingContext::unbind() to remove the NameBinding from an object</p>
- <code type="none">
-'CosNaming_NamingContext':unbind(Sc, Name).
- </code>
- </item>
- </list>
- <note>
- <p>Objects can have more than one name, to indicate different paths to
- the same object.</p>
- </note>
- </section>
-
- <section>
- <title>Resolving a Name to an Object</title>
- <p>The following steps show how to retrieve the object reference to the service context
- above (/workgroup/services). </p>
- <list type="ordered">
- <item>
- <p>Use the naming library functions to create a name path:</p>
- <code type="none">
-Name = lname:new(["workgroup", "services"]).
- </code>
- </item>
- <item>
- <p>Use CosNaming::NamingContext::resolve() to to resolve the name to an object</p>
- <code type="none">
-Sc = 'CosNaming_NamingContext':resolve(NS, Name).
- </code>
- </item>
- </list>
- <p>An alternative is to use:</p>
- <code type="none">
-Sc = corba:string_to_object("corbaname:rir:/NameService#workgroup/services/").
- </code>
- <p>The <c>corbaname</c> schema is described further in the Interoperable
- Naming Service section.</p>
- </section>
-
- <section>
- <title>Listing the Bindings in a NamingContext</title>
- <list type="ordered">
- <item>
- <p>Use CosNaming::NamingContext::list() to list all the bindings in a context</p>
- <p>The following code retrieves and lists up to 10 bindings from a context.</p>
- <code type="none">
-{BList, BIterator} = 'CosNaming_NamingContext':list(Sc, 10).
-
-lists:foreach(fun({{Id, Kind},BindingType}) -> case BindingType of
- nobject ->
- io:format("id: %s, kind: %s, type: object~n", [Id, Kind]);
- _ ->
- io:format("id: %s, kind: %s, type: ncontext~n", [Id, Kind])
- end end,
- Blist).
- </code>
- </item>
- </list>
- <note>
- <p>Normally a <term id="BindingIterator"><termdef>The binding iterator (Like a book mark) indicates which objects have been read from the list.</termdef></term>is helpful in situations where you have a large number of objects
- in a list, as the programmer then can traverse it more easily.
- In Erlang it is not needed, because lists are easily handled in the
- language itself.</p>
- </note>
- <warning>
- <p>Remember that the BindingIterator (BIterator in the example) is an object and therefore
- <em>must be removed</em> otherwise dangling processes will occur.
- Use <c>CosNaming::BindingIterator::destroy()</c> to remove it.</p>
- </warning>
- <code type="none">
- 'CosNaming_NamingContext':destroy(BIterator).
- </code>
- </section>
-
- <section>
- <title>Destroying a Naming Context</title>
- <p>The naming contexts are persistent and must be explicitly removed.
- (they are also removed if all Orber nodes in the domain are stopped).</p>
- <list type="ordered">
- <item>
- <p>Use CosNaming::NamingContext::destroy() to remove a NamingContext</p>
- <code type="none">
-'CosNaming_NamingContext':destroy(Sc).
- </code>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Interoperable Naming Service</title>
- <marker id="interop_ns"></marker>
- <p>The OMG specifies URL schemes, which represent a CORBA object and a CORBA object
- bound in a NamingContext, for resolving references from other ORB:s. As of today,
- three schemes are defined:</p>
- <list type="bulleted">
- <item>IOR</item>
- <item>corbaloc</item>
- <item>corbaname</item>
- </list>
-
- <section>
- <title>IOR</title>
- <p>A stringified IOR is a valid URL format but difficult for humans to handle
- through non-electronic means. This URL format does not depend on a specific
- Name Service and, thus, is robust and insulates the client from the encapsulated
- transport information and object key used to reference the object.</p>
- </section>
-
- <section>
- <title>corbaloc</title>
- <p>The notation of this scheme is similar to the more well known URL <c>HTTP</c>, and
- the full <c>corbaloc</c> BNF is:</p>
- <code type="none"><![CDATA[
-<corbaloc> = "corbaloc:"<obj_addr_list>["/"<key_string>]
-<obj_addr_list> = [<obj_addr>","]*<obj_addr>
-<obj_addr> = <prot_addr> | <future_prot_addr>
-<prot_addr> = <rir_prot_addr> | <iiop_prot_addr>
-<rir_prot_addr> = <rir_prot_token>":"
-<rir_prot_token> = rir
-<future_prot_addr> = <future_prot_id><future_prot_addr>
-<future_prot_id> = <future_prot_token>":"
-<iiop_prot_addr> = <iiop_id><iiop_addr>
-<iiop_id> = <iiop_default> | <iiop_prot_token>":"
-<iiop_default> = ":"
-<iiop_prot_token> = "iiop"
-<iiop_addr> = <version><host>[":"<port>]
-<host> = <DNS-style Host Name> | <ip_v4_address> | "["<ip_v6_address>"]"
-<version> = <major>"."<minor>"@" | empty_string
-<port> = number
-<major> = number
-<minor> = number
-<DNS-style Host Name> = string
-<ip_v4_address> = string
-<ip_v6_address> = string
-<key_string> = for example NameService
- ]]></code>
- <p>The <c>corbaloc</c> scheme consists of 3 parts:</p>
- <list type="bulleted">
- <item>Protocol - as of today <c>iiop</c> or <c>rir</c> is supported.
- Using <c>rir</c> means that we will resolve the given Key locally, i.e.,
- the same as using <c>corba:resolve_initial_references("NameService").</c></item>
- <item>IIOP address - this address can be divided into <c>Version</c>, <c>Host</c>
- and <c>Port</c>. If the version or port are left out they will be set to the default
- values <c>1.0</c> and <c>2809</c> respectively.</item>
- <item>KeyString - an object key, e.g., "NameService". If no Key is
- supplied the default value "NameService" will be used.</item>
- </list>
- <p>A <c>corbaloc</c> can be passed used together with
- <c>corba:string_to_object("corbaloc::[email protected]:4001/NameService")</c> or set as the
- configuration variables <c>orbInitilRef</c> or <c>orbDefaultInitilRef</c> and calling
- <c>corba:resolve_initial_references("NameService")</c>. For more information see the Orber
- installation chapter. <c>corbaloc</c> can also be used together with <c>corbaname</c>
- to gain an easy access to a Name Service.</p>
- <p>Currently, the OMG defines a set of reserved keys and the type of object,
- listed below, they should be associated with. The <c>NameService</c>
- key may <em>not</em> be changed in Orber. If you want to add one of the
- reserved keys as an initial service, simply use:</p>
- <code type="none">
-1> Factory = cosNotificationApp:start_global_factory().
-2> corba:add_initial_service("NotificationService", Factory).
- </code>
- <p>This object can then be easily resolved by any other ORB, supporting
- the Interoperable Naming Service, by using:</p>
- <code type="none">
-3> NF = corba:string_to_object("corbaloc::[email protected]:4001/NotificationService").
- </code>
- <table>
- <row>
- <cell align="center" valign="middle"><em>String Name</em></cell>
- <cell align="center" valign="middle"><em>Object Type</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">RootPOA</cell>
- <cell align="left" valign="middle">PortableServer::POA</cell>
- </row>
- <row>
- <cell align="left" valign="middle">POACurrent</cell>
- <cell align="left" valign="middle">PortableServer::Current</cell>
- </row>
- <row>
- <cell align="left" valign="middle">InterfaceRepository</cell>
- <cell align="left" valign="middle">CORBA::Repository</cell>
- </row>
- <row>
- <cell align="left" valign="middle">NameService</cell>
- <cell align="left" valign="middle">CosNaming::NamingContext</cell>
- </row>
- <row>
- <cell align="left" valign="middle">TradingService</cell>
- <cell align="left" valign="middle">CosTrading::Lookup</cell>
- </row>
- <row>
- <cell align="left" valign="middle">SecurityCurrent</cell>
- <cell align="left" valign="middle">SecurityLevel1::Current/SecurityLevel2::Current</cell>
- </row>
- <row>
- <cell align="left" valign="middle">TransactionCurrent</cell>
- <cell align="left" valign="middle">CosTransaction::Current</cell>
- </row>
- <row>
- <cell align="left" valign="middle">DynAnyFactory</cell>
- <cell align="left" valign="middle">DynamicAny::DynAnyFactory</cell>
- </row>
- <row>
- <cell align="left" valign="middle">ORBPolicyManager</cell>
- <cell align="left" valign="middle">CORBA::PolicyManager</cell>
- </row>
- <row>
- <cell align="left" valign="middle">PolicyCurrent</cell>
- <cell align="left" valign="middle">CORBA::PolicyCurrent</cell>
- </row>
- <row>
- <cell align="left" valign="middle">NotificationService</cell>
- <cell align="left" valign="middle">CosNotifyChannelAdmin::EventChannelFactory</cell>
- </row>
- <row>
- <cell align="left" valign="middle">TypedNotificationService</cell>
- <cell align="left" valign="middle">CosTypedNotifyChannelAdmin::TypedEventChannelFactory</cell>
- </row>
- <row>
- <cell align="left" valign="middle">CodecFactory</cell>
- <cell align="left" valign="middle">IOP::CodecFactory</cell>
- </row>
- <row>
- <cell align="left" valign="middle">PICurrent</cell>
- <cell align="left" valign="middle">PortableInterceptors::Current</cell>
- </row>
- <tcaption>Currently reserved key strings</tcaption>
- </table>
- </section>
-
- <section>
- <title>corbaname</title>
- <p>The <c>corbaname</c> URL scheme is an extension of the <c>corbaloc</c> scheme, and
- the full <c>corbaname</c> BNF is:</p>
- <code type="none"><![CDATA[
-<corbaname> = "corbaname:"<obj_addr_list>["/"<key_string>]["#"<string_name>]
-<obj_addr_list> = as described above.
-<key_string> = as described above.
- ]]></code>
- <p>The <c>string_name</c>, concatenated to the <c>corbaloc</c> string, identifies
- a binding in a naming context. A name component consists of two parts, i.e.,
- <c>id</c> and <c>kind</c>, which is represented as follows:</p>
- <table>
- <row>
- <cell align="center" valign="middle"><em>String Name</em></cell>
- <cell align="center" valign="middle"><em>Name Sequence</em></cell>
- <cell align="center" valign="middle"><em>Comment</em></cell>
- </row>
- <row>
- <cell align="left" valign="middle">"id1/./id3.kind3"</cell>
- <cell align="left" valign="middle">[{"id1",""},{"",""},{"id3","kind3"}]</cell>
- <cell align="left" valign="middle">The first component has no kind defined while the second component's both fields are empty.</cell>
- </row>
- <row>
- <cell align="left" valign="middle">"id1//id3.kind3"</cell>
- <cell align="left" valign="middle">ERROR</cell>
- <cell align="left" valign="middle">Not allowed, must insert a '.' between the '//'.</cell>
- </row>
- <row>
- <cell align="left" valign="middle">"id1.kind1/."</cell>
- <cell align="left" valign="middle">[{"id1","kind1"},{"",""}]</cell>
- <cell align="left" valign="middle">The first component's fields are both set while the second component's both fields are empty.</cell>
- </row>
- <row>
- <cell align="left" valign="middle">"id1.kind1/id2."</cell>
- <cell align="left" valign="middle">ERROR</cell>
- <cell align="left" valign="middle">An Id with a trailing '.' is not allowed.</cell>
- </row>
- <row>
- <cell align="left" valign="middle">"i\\/d1/i\\.d2"</cell>
- <cell align="left" valign="middle">[{"i/d1",""},{"i.d2",""}]</cell>
- <cell align="left" valign="middle">Since '.' and '/' are used to separate the components, these tokens must be escaped to be correctly converted.</cell>
- </row>
- <tcaption>Stringified Name representation</tcaption>
- </table>
- <p>After creating a stringified Name we can either use:</p>
- <code type="none">
-NameStr = "org.erlang",
-NS = corba:resolve_initial_references("NameService"),
-Obj = 'CosNaming_NamingContextExt':resolve_str(NS, NameStr),
- </code>
- <p>or concatenate the Name String using:</p>
- <code type="none">
-NameStr = "Swedish/Soccer/Champions",
-Address = "corbaname:iiop:[email protected]:2000/NameService",
-NS = corba:resolve_initial_references("NameService"),
-URLStr = 'CosNaming_NamingContextExt':to_url(NS, Address, NameStr),
-Obj = corba:string_to_object(URLStr),
- </code>
- <p>Using the first alternative, the configuration variables <c>orbInitilRef</c> and
- <c>orbDefaultInitilRef</c>, will determine which other ORB's or the local
- Name Service Orber will try to resolve the given string from. The second
- alternative allows us to override any settings of the configuration variables.</p>
- <p>The function <c>to_url/3</c> will perform any necessary escapes compliant with
- IETF/RFC 2396. US-ASCII alphanumeric characters and
- <c><![CDATA["," | "/" | ":" | "?" | "@" | "&" | "=" | "+" | "$" | ";" | "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"]]></c>
- are not escaped.</p>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/orber/doc/src/ch_orber_kernel.xml b/lib/orber/doc/src/ch_orber_kernel.xml
deleted file mode 100644
index 396e1360fd..0000000000
--- a/lib/orber/doc/src/ch_orber_kernel.xml
+++ /dev/null
@@ -1,103 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>The Orber Application</title>
- <prepared></prepared>
- <docno></docno>
- <date>1998-10-05</date>
- <rev></rev>
- <file>ch_orber_kernel.xml</file>
- </header>
-
- <section>
- <title>ORB Kernel and IIOP </title>
- <p>This chapter gives a brief overview of the ORB and its relation
- to objects in a distributed environment and the usage of Domains
- in Orber.
- Also Internet-Inter ORB Protocol (<term id="IIOP"><termdef>Internet-Inter ORB Protocol</termdef></term>) is discussed and how this
- protocol facilitates communication between ORBs to
- allow the accessory of persistent server objects in Erlang. </p>
- </section>
-
- <section>
- <title>The Object Request Broker (ORB)</title>
- <p>An ORB kernel can be best described as the middle-ware, which
- creates relationships between clients and servers, but is
- defined by its interfaces. This allows transparency for the
- user, as they do not have to be aware of where the requested
- object is located. Thus, the programmer can work with any other
- platform provided that an IDL mapping and interfaces exist.
- </p>
- <p>The IDL mapping which is described in a later chapter is the
- translator between other platforms, and languages. However, it
- is the ORB, which provides objects with a structure by which
- they can communicate with other objects.
- </p>
- <p>ORBs intercept and direct messages from one object, pass this
- message using IIOP to another ORB, which then directs the
- message to the indicated object.
- </p>
- <p>An ORB is the base on which interfaces, communication stubs
- and mapping can be built to enable communication between
- objects. Orber uses <term id="domains"><termdef>A domain allows a more efficient communication protocol to be used between objects not on the same node without the need of an ORB</termdef></term>to group objects of different nodes
- </p>
- <p>How the ORB provides communication is shown very simply in figure 1 below: </p>
- <marker id="theORB"></marker>
- <image file="theORB.gif">
- <icaption>
-Figure 1: How the Object Request Broker works.</icaption>
- </image>
- <p>The domain in Orber gives an extra aspect to the distributed object
- environment as each domain has one ORB, but it is distributed over
- a number of object in different nodes. The domain binds objects on
- nodes more closely than distributed objects in different domains. The
- advantage of a domain is that a faster communication exists between
- nodes and objects of the same domain. An internal communication protocol
- (other than IIOP) allows a
- more efficient communication between these objects. </p>
- <note>
- <p>Unlike objects, domains can only have one name
- so that no communication ambiguities exist between domains.</p>
- </note>
- </section>
-
- <section>
- <title>Internet Inter-Object Protocol (IIOP)</title>
- <p>IIOP is a communication protocol developed by the OMG to
- facilitate communication in a distributed object-oriented
- environment.
- </p>
- <p>Figure 2 below demonstrates how IIOP works between objects:</p>
- <marker id="iiop"></marker>
- <image file="iiop.gif">
- <icaption>
-Figure 2: IIOP communication between domains and objects.</icaption>
- </image>
- <note>
- <p>Within the Orber domains the objects communicate without
- using the IIOP. However, the user is unaware of the difference in protocols, as this difference is not visible. </p>
- </note>
- </section>
-</chapter>
-
diff --git a/lib/orber/doc/src/ch_orberweb.xml b/lib/orber/doc/src/ch_orberweb.xml
deleted file mode 100644
index be1d7fb983..0000000000
--- a/lib/orber/doc/src/ch_orberweb.xml
+++ /dev/null
@@ -1,222 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2001</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>OrberWeb</title>
- <prepared>Nick</prepared>
- <docno></docno>
- <date>2001-11-22</date>
- <rev></rev>
- <file>ch_orberweb.xml</file>
- </header>
-
- <section>
- <title>Using OrberWeb</title>
- <p><c>OrberWeb</c> is intended to make things easier when developing and
- testing applications using <c>Orber</c>. The user is able to interact
- with <c>Orber</c> via a GUI by using a web browser.</p>
- <p><c>OrberWeb</c> requires that the application <c>WebTool</c> is available and
- started on at least one node; if so <c>OrberWeb</c> can usually be used to
- to access <c>Orber</c> nodes supporting the Interoperable Naming
- Service. How to start OrberWeb is described in
- <seealso marker="ch_orberweb#startorberweb">Starting OrberWeb</seealso></p>
- <p>The <c>OrberWeb</c> GUI consists of a <em>Menu Frame</em> and a
- <em>Data Frames</em>.</p>
-
- <section>
- <title>The Menu Frame</title>
- <p>The menu frame consists of:</p>
- <list type="bulleted">
- <item><em>Node List</em> - which node to access.</item>
- <item><em>Configuration</em> - see how Orber on the current node is configured.</item>
- <item><em>Name Service</em> - browse the NameService and add/remove a Context/Object.</item>
- <item><em>IFR Types</em> - see which types are registered in IFR.</item>
- <item><em>Create Object</em> - create a new object and, possibly, store it in the NameService.</item>
- </list>
- <p></p>
- <marker id="menuframe"></marker>
- <image file="menuframe.gif">
- <icaption>The Menu Frame.</icaption>
- </image>
- <p>Which nodes we can access is determined by what is returned when invoking <c>[node()|nodes()]</c>.
- If you cannot see a desired node in the list, you have to call <c>net_adm:ping(Node)</c>.
- But this requires that the node is started with the distribution switched on
- (e.g. <c>erl -sname myNode</c>); this also goes for the node <c>OrberWeb</c> is running on.</p>
- </section>
-
- <section>
- <title>The Configuration Data Frame</title>
- <p>When accessing the <em>Configuration</em> page OrberWeb presents a table containing the
- <seealso marker="ch_install#config">configuration settings</seealso> for the target node.</p>
- <p></p>
- <marker id="dataframe3"></marker>
- <image file="dataframe3.gif">
- <icaption>Configuration Settings.</icaption>
- </image>
- <p>It is also possible to change those configuration parameters which can be changed when Orber
- is already started. The Key-Value pairs is given as a list of tuples, e.g.,
- <em>[{orber_debug_level, 5}, {iiop_timeout, 60}, {giop_version, {1,2}}]</em>. If one tries to update a parameter
- which may not be changed an error message will be displayed.</p>
- </section>
-
- <section>
- <title>The IFR Data Frame</title>
- <p>All types registered in the IFR (Interface Repository) which have an associated IFR-id
- can be viewed via the IFR Data Frame. This gives the user an easy way to confirm that
- all necessary IDL-specifications have been properly registered. All available types are
- listed when choosing <c>IFR Types</c> in the menu frame:</p>
- <p></p>
- <marker id="dataframe1"></marker>
- <image file="dataframe1.gif">
- <icaption>Select Type.</icaption>
- </image>
- <p>After selecting a type all definitions of that particular type will be displayed. If no such
- bindings exists the table will be empty.</p>
- <p>Since Orber adds definitions to the IFR when it is installed (e.g. CosNaming), not only
- types defined by the user will show up in the table. In the figure below you find the
- the NameService exceptions listed.</p>
- <p></p>
- <marker id="dataframe2"></marker>
- <image file="dataframe2.gif">
- <icaption>List Registered Exceptions.</icaption>
- </image>
- </section>
-
- <section>
- <title>The NameService Data Frame</title>
- <p>The NameService main purpose is to make possible to bind object references, which
- can client applications can resolve and invoke operations on. Initially, the NameService
- is empty. The most common scenario, is that user applications create Contexts and add objects
- in the NameService. OrberWeb allows the user to do the very same thing.</p>
- <p>When referencing an object or context you must use stringified NameComponents.
- For more information see the <seealso marker="ch_naming_service">Interoperable Naming Service</seealso>.
- In the following example we will use the string <em>org/erlang/TheObjectName</em>, where
- <em>org</em> and <em>erlang</em> will be contexts and <em>TheObjectName</em>
- the name the object will be bound to.</p>
- <p>Since the NameService is empty in the beginning, the only thing we can do is creating
- a new context. Simply write <em>org</em> in the input field and press <c>New Context</c>.
- If OrberWeb was able to create the context or not, is shown in the completion message.
- If successful, just press the <c>Go Back</c> button. Now, a link named <em>org</em> should
- be listed in the table. In the right column the context type is displayed. Contexts are
- associated with <em>ncontext</em> and objects with <em>nobject</em>.</p>
- <p></p>
- <marker id="dataframe5"></marker>
- <image file="dataframe5.gif">
- <icaption>Add a New Context.</icaption>
- </image>
- <p>To create the next level context (i.e. erlang), simply follow the link and repeat the procedure.
- If done correctly, a table containing the same data as the following figure should be the result
- if you follow the <em>erlang</em> link. Note, that the path is displayed in the yellow
- field.</p>
- <p></p>
- <p>If a context does not contain any sub-contexts or object bindings, it is possible to
- delete the context. If these requirements are met, a <c>Delete Context</c> button will appear.
- A completion status message will be displayed after deleting the context.</p>
- <p></p>
- <marker id="dataframe6"></marker>
- <image file="dataframe6.gif">
- <icaption>Delete Context.</icaption>
- </image>
- <p>Now it is possible to bind an object using the complete name string. To find out how this is
- done using OrberWeb see <seealso marker="ch_orberweb#create">Object Creation</seealso>.
- For now, we will just assume that an object have been created and bound as <em>TheObjectName</em>. </p>
- <p></p>
- <marker id="dataframe7"></marker>
- <image file="dataframe7.gif">
- <icaption>Object Stored in the NameService.</icaption>
- </image>
- <p>If you follow the <em>TheObjectName</em> link, data about the bound object will be
- presented. Note, depending on which type of object it is, the information given differs.
- It would, for example, not be possible to display a Pid for all types of objects since
- it might reside on a Java-ORB. In the figure below a CosNotification FilterFactory have
- been bound under the name <em>org/erlang/TheObjectName</em>.</p>
- <p></p>
- <marker id="dataframe8"></marker>
- <image file="dataframe8.gif">
- <icaption>Object Data.</icaption>
- </image>
- <p>OrberWeb also makes it possible to remove a binding and dispose the associated object.
- Pressing <em>Unbind</em> the binding will be removed but the object will still exist.
- But, if the <em>Unbind and Dispose</em> button is pressed, the binding will be removed
- and the object terminated.</p>
- </section>
-
- <section>
- <title>The Object Creation Data Frame</title>
- <marker id="create"></marker>
- <p>This part makes it possible to create a new object and, if wanted, store it the
- NameService.</p>
- <p></p>
- <marker id="dataframe4"></marker>
- <image file="dataframe4.gif">
- <icaption>Create a New Object.</icaption>
- </image>
- <list type="bulleted">
- <item><em>Module</em> - simply type the name of the module of the object type
- you want to create. If the module begins with a capital letter, we normally must
- write <c>'Module_Interface'</c>. But, when using OrberWeb, you shall <em>NOT</em>.
- Since we cannot create linked objects this is not an option.</item>
- <item><em>Arguments</em> - the supplied arguments must be written as a single Erlang term.
- That is, as a list or tuple containing other Erlang terms. The arguments will be
- passed to the <c>init</c> function of the object. It is, however, not possible
- to use Erlang records. If OrberWeb is not able to parse the arguments, an error message
- will be displayed. If left empty, an empty list will be passed.</item>
- <item><em>Options</em> - the options can be the ones listed under
- <seealso marker="Module_Interface">Module_Interface</seealso> in Orber's Reference manual.
- Hence, they are not further described here. But, as an example, in the figure above
- we started the object as globally registered. If no options supplied the object
- will be started as default.</item>
- <item><em>Name String</em> - if left empty the object will <em>not</em> be registered in the
- NameService. Hence, it is important that you can access the object in another way,
- otherwise a zombie process is created. In the previous section we used the name string
- <em>org/erlang/TheObjectName</em>. If we choose the same name here, the listed contexts
- (i.e. <em>org</em> and <em>erlang</em>) must be created <em>before</em> we can create
- and bind the object to <em>TheObjectName</em>. If this requirement is not met, OrberWeb
- cannot bind the object. Hence, the object will be terminated and an error message
- displayed.</item>
- <item><em>Operation to use</em> - which option choosed will determine the behavior of OrberWeb.
- If you choose <em>bind</em> and a binding already exists an error message will be
- displayed and the newly started object terminated. But if you choose <em>rebind</em>
- any existing binding will over-written.</item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Starting OrberWeb</title>
- <marker id="startorberweb"></marker>
- <p>You may choose to start OrberWeb on node, on which Orber is running or not. But
- the Erlang distribution must be started (e.g. by using -sname aNodeName). Now, all
- you have to do is to invoke:</p>
- <code type="none">
-
-erl> webtool:start().
-WebTool is available at http://localhost:8888/
-Or http://127.0.0.1:8888/
- </code>
- <p>Type one of the URL:s in your web-browser. If you want to access the WebTool application
- from different machine, just replace <c>localhost</c> with its name. For more information,
- see the WebTool documentation.</p>
- </section>
-</chapter>
-
diff --git a/lib/orber/doc/src/ch_security.xml b/lib/orber/doc/src/ch_security.xml
deleted file mode 100644
index 151e417079..0000000000
--- a/lib/orber/doc/src/ch_security.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>How to use security in Orber</title>
- <prepared></prepared>
- <docno></docno>
- <date>1999-09-01</date>
- <rev></rev>
- <file>ch_security.xml</file>
- </header>
-
- <section>
- <title>Security in Orber</title>
-
- <section>
- <title>Introduction</title>
- <p>Orber SSL provides authentication, privacy and integrity for your
- Erlang applications. Based on the Secure Sockets Layer protocol, the
- Orber SSL ensures that your Orber clients and servers can
- communicate securely over any network.
- This is done by tunneling IIOP through an SSL connection. To get
- the node secure you will also need to have a firewall which
- only lets through connections to certain ports.</p>
- </section>
-
- <section>
- <title>Enable Usage of Secure Connections</title>
- <p>To enable a secure Orber domain you have to set the configuration variable
- <em>secure</em> which currently only can have one of two values;
- <em>no</em> if no security for IIOP should be used and <em>ssl</em> if
- secure connections is needed (<em>ssl</em> is currently the only supported
- security mechanism).</p>
- <p>The default is no security.</p>
- </section>
-
- <section>
- <title>Configurations when Orber is Used on the Server Side</title>
- <p>There is a variable to conficure Orber's SSL behavior on the server side.</p>
- <list type="bulleted">
- <item><em>ssl_server_options</em> - which is a list of options to ssl.
- See the <seealso marker="ssl:ssl">SSL</seealso> application for further
- descriptions on these options.</item>
- </list>
- <p>There also exist an API function for accessing the value of this variable:</p>
- <list type="bulleted">
- <item>orber:ssl_server_options/0</item>
- </list>
- </section>
-
- <section>
- <title>Configurations when Orber is Used on the Client Side</title>
- <p>When the Orber enabled application is the client side in the secure connection the
- different configurations can be set per client process instead and not for the whole domain
- as for incoming calls.</p>
- <p>There is a variable to set default values for the domain but they can be changed
- per client process.</p>
- <list type="bulleted">
- <item><em>ssl_client_options</em> - which is a list of options to ssl.
- See the <seealso marker="ssl:ssl">SSL</seealso> application for further
- descriptions on these options.</item>
- </list>
- <p>There also exist two API functions for accessing and changing the values of this
- variable in the client processes.</p>
- <p>Access function:</p>
- <list type="bulleted">
- <item>orber:ssl_client_options/0</item>
- </list>
- <p>Modify function:</p>
- <list type="bulleted">
- <item>orber:set_ssl_client_options/1</item>
- </list>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/orber/doc/src/ch_stubs.xml b/lib/orber/doc/src/ch_stubs.xml
deleted file mode 100644
index 144191a66a..0000000000
--- a/lib/orber/doc/src/ch_stubs.xml
+++ /dev/null
@@ -1,284 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Orber Stubs/Skeletons</title>
- <prepared></prepared>
- <docno></docno>
- <date>1999-09-03</date>
- <rev>A</rev>
- <file>ch_stubs.xml</file>
- </header>
-
- <section>
- <title>Orber Stubs and Skeletons Description</title>
- <p>This example describes the API and behavior of Orber stubs and skeletons.
- </p>
-
- <section>
- <title>Server Start</title>
- <p>Orber servers can be started in several ways. The chosen start functions determines
- how the server can be accessed and its behavior.
- </p>
- <p>Using <c>Module_Interface:oe_create()</c> or <c>oe_create_link()</c>:
- </p>
- <list type="bulleted">
- <item>No initial data can be passed.</item>
- <item>Cannot be used as a supervisor child start function.</item>
- <item>Only accessible through the object reference returned by the start function.
- The object reference is no longer valid if the server dies and is restarted.</item>
- </list>
- <p>Using <c>Module_Interface:oe_create(Env)</c> or <c>oe_create_link(Env)</c>:</p>
- <list type="bulleted">
- <item>Initial data can be passed using <c>Env</c>.</item>
- <item>Cannot be used as a supervisor child start function.</item>
- <item>Only accessible through the object reference returned by the start function.
- The object reference is no longer valid if the server dies and is restarted.</item>
- </list>
- <p>Using <c>Module_Interface:oe_create(Env, Options)</c>:</p>
- <list type="bulleted">
- <item>Initial data can be passed using <c>Env</c>.</item>
- <item>Cannot be used as a supervisor child start function.</item>
- <item>Accessible through the object reference returned by the start function. If the option
- <c>{regname, RegName}</c> is used the object reference stays valid even if the
- server has been restarted.</item>
- <item>If the options <c>{persistent, true}</c> and <c>{regname, {global, Name}}</c> is used,
- the result from an object invocation will be the exception 'OBJECT_NOT_EXIST'
- only if the object has terminated with reason
- <c>normal</c> or <c>shutdown</c>. If the object is in the process of restarting, the result
- will be <c>{error, Reason}</c> or a system exception is raised.</item>
- <item>The option <c>{pseudo, true}</c> makes it possible to start create non-server objects.
- There are, however, some limitations, which are further described in the
- <c>Pseudo objects</c> section.</item>
- </list>
- <p>Using <c>Module_Interface:oe_create_link(Env, Options)</c>:</p>
- <list type="bulleted">
- <item>Initial data can be passed using <c>Env</c>.</item>
- <item>Can be used as a supervisor child start function if the option <c>{sup_child, true}</c> used.</item>
- <item>Accessible through the object reference returned by the start function. If the option
- <c>{regname, RegName}</c> is used the object reference stays valid even if the
- server has been restarted.</item>
- <item>If the options <c>{persistent, true}</c> and <c>{regname, {global, Name}}</c> is used,
- the result from an object invocation will be the exception 'OBJECT_NOT_EXIST'
- only if the object has terminated with reason
- <c>normal</c> or <c>shutdown</c>. If the object is in the process of restarting, the result
- will be <c>{error, Reason}</c> or a system exception is raised.</item>
- <item>For starting a server as a supervisor child you should use the options
- <c>[{persistent, true}, {regname, {global, Name}}, {sup_child, true}]</c> and of type <em>transient</em>.
- This configuration allows you to delegate restarts to the supervisor and still be able to
- use the same object reference and be able to see if the server is permanently terminated.
- Please note you must use <em>supervisor/stdlib-1.7</em> or later and that the it returns
- <c>{ok, Pid, Object}</c> instead of just <c>Object</c>.</item>
- <item>Using the option <c>{pseudo, true}</c> have the same effect as using
- <c>oe_create/2</c>.</item>
- </list>
- <warning>
- <p>To avoid flooding Orber with old object references start erlang using the flag
- <em>-orber objectkeys_gc_time Time</em>, which will remove all object references
- related to servers being dead for Time seconds. To avoid extra overhead, i.e., performing
- garbage collect if no persistent objects are started, the objectkeys_gc_time default value
- is <em>infinity</em>. For more information, see the orber and corba documentation.</p>
- </warning>
- <warning>
- <p>Orber still allow <c>oe_create(Env, {Type,RegName})</c> and <c>oe_create_link(Env, {Type,RegName})</c> to be used,
- but may not in future releases.</p>
- </warning>
- </section>
-
- <section>
- <title>Pseudo Objects</title>
- <p>This section describes Orber pseudo objects.
- </p>
- <p>The Orber stub can be used to start a <c>pseudo object</c>, which will create a non-server implementation.
- A pseudo object introduce some limitations:</p>
- <list type="bulleted">
- <item>The functions <c>oe_create_link/2</c> is equal to <c>oe_create/2</c>, i.e.,
- no link can or will be created.</item>
- <item>The <c>BIF:s self()</c> and <c>process_flag(trap_exit,true)</c> behaves incorrectly.</item>
- <item>The <c>IC</c> option <c>{{impl, "M::I"}, "other_impl"}</c> has no effect. The call-back
- functions must be implemented in a file called <c>M_I_impl.erl</c></item>
- <item>The call-back functions must be implemented as if the <c>IC</c> option
- <c>{this, "M::I"}</c> was used.</item>
- <item>The gen_server <c>State</c> changes have no effect. The user can provide information via
- the <c>Env</c> start parameter and the State returned from <c>init/2</c> will be the State
- passed in following invocations.</item>
- <item>The server reply <c>Timeout</c> has no effect.</item>
- <item>The compile option <c>from</c> has no effect.</item>
- <item>The option <c>{pseudo, true}</c> overrides all other start options.</item>
- <item>Only the functions, besides own definitions, <c>init/2</c> (called via oe_create*/2) and
- <c>terminate/2</c> (called via corba:dispose/1) must be implemented.</item>
- </list>
- <p>By adopting the rules for <c>pseudo</c> objects described above we can use <c>oe_create/2</c>
- to create <c>server</c> or <c>pseudo</c> objects, by excluding or including the
- option <c>{pseudo, true}</c>, without changing the call-back module.</p>
- <p>To create a pseudo object do the following:</p>
- <code type="none">
-fingolfin 127> erl
-Erlang (BEAM) emulator version 4.9
-
-Eshell V4.9 (abort with ^G)
-1> ic:gen(myDefinition, [{this, "MyModule::MyInterface"}]).
-Erlang IDL compiler version 20
-ok
-2> make:all().
-Recompile: oe_MyDefinition
-Recompile: MyModule_MyInterface
-Recompile: MyModule_MyInterface_impl
-up_to_date
-3> PseudoObj = MyModule_MyInterface:oe_create(Env, [{pseudo, true}]).
- </code>
- <p>The call-back functions must be implemented as <c>MyFunction(OE_THIS, State, Args)</c>,
- and called by <c>MyModule_MyInterface:MyFunction(PseudoObj, Args)</c>.</p>
- </section>
-
- <section>
- <title>Call-back Module</title>
- <p>This section provides an example of how a call-back module may be implemented.</p>
- <note>
- <p>Arguments and Replies are determined by the IDL-code and, hence, not
- further described here.</p>
- </note>
- <code type="none">
-%%%-----------------------------------------------------------
-%%% File : Module_Interface_impl.erl
-%%% Author :
-%%% Purpose :
-%%% Created :
-%%%-----------------------------------------------------------
-
--module('Module_Interface_impl').
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib(".. ..").
-
-%%--------------- EXPORTS-------------------------------------
-%% Arity depends on IC configuration parameters and the IDL
-%% specification.
--export([own_function/X]).
-
-
-%%--------------- gen_server specific ------------------------
--export([init/1, terminate/2, code_change/3, handle_info/2]).
-
-%%------------------------------------------------------------
-%% function : server specific
-%%------------------------------------------------------------
-init(InitialData) ->
- %% 'trap_exit' optional (have no effect if pseudo object).
- process_flag(trap_exit,true),
-
- %%--- Possible replies ---
- %% Reply and await next request
- {ok, State}.
-
- %% Reply and if no more requests within Time the special
- %% timeout message should be handled in the
- %% Module_Interface_impl:handle_info/2 call-back function (use the
- %% IC option {{handle_info, "Module::Interface"}, true}).
- {ok, State, Timeout}
-
- %% Return ignore in order to inform the parent, especially if it is a
- %% supervisor, that the server, as an example, did not start in
- %% accordance with the configuration data.
- ignore
- %% If the initializing procedure fails, the reason
- %% is supplied as StopReason.
- {stop, StopReason}
-
-terminate(Reason, State) ->
- ok.
-
-code_change(OldVsn, State, Extra) ->
- {ok, NewState}.
-
-%% If use IC option {{handle_info, "Module::Interface"}, true}.
-%% (have no effect if pseudo object).
-handle_info(Info, State) ->
- %%--- Possible replies ---
- %% Await the next invocation.
- {noreply, State}.
- %% Stop with Reason.
- {stop, Reason, State}.
-
-%%--- two-way ------------------------------------------------
-%% If use IC option {this, "Module:Interface"}
-%% (Required for pseudo objects)
-own_function(This, State, .. Arguments ..) ->
-%% IC options this and from
-own_function(This, From, State, .. Arguments ..) ->
-%% IC option from
-own_function(From, State, .. Arguments ..) ->
- %% Send explicit reply to client.
- corba:reply(From, Reply),
- %%--- Possible replies ---
- {noreply, State}
- {noreply, State, Timeout}
-
-
-%% If not use IC option {this, "Module:Interface"}
-own_function(State, .. Arguments ..) ->
- %%--- Possible replies ---
- %% Reply and await next request
- {reply, Reply, State}
-
- %% Reply and if no more requests within Time the special
- %% timeout message should be handled in the
- %% Module_Interface_impl:handle_info/2 call-back function (use the
- %% IC option {{handle_info, "Module::Interface"}, true}).
- {reply, Reply, State, Timeout}
-
- %% Stop the server and send Reply to invoking object.
- {stop, StopReason, Reply, State}
-
- %% Stop the server and send no reply to invoking object.
- {stop, StopReason, State}
-
- %% Raise exception. Any changes to the internal State is lost.
- corba:raise(Exception).
-
-%%--- one-way ------------------------------------------------
-%% If use IC option {this, "Module:Interface"}
-%% (Required for pseudo objects)
-own_function(This, State, .. Arguments ..) ->
-
-%% If not use IC option {this, "Module:Interface"}
-own_function(State, .. Arguments ..) ->
- %%--- Possible results ---
- {noreply, State}
-
- %% Release and if no more requests within Time the special
- %% timeout message should be handled in the
- %% Module_Interface_impl:handle_info/2 call-back function (use the
- %% IC option {{handle_info, "Module::Interface"}, true}).
- {noreply, State, Timeout}
-
- %% Stop the server with StopReason.
- {stop, StopReason, State}
-
-%%--------------- END OF MODULE ------------------------------
- </code>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/orber/doc/src/corba.xml b/lib/orber/doc/src/corba.xml
deleted file mode 100644
index d89f035dba..0000000000
--- a/lib/orber/doc/src/corba.xml
+++ /dev/null
@@ -1,454 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>corba</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>1997-06-10</date>
- <rev>A</rev>
- </header>
- <module>corba</module>
- <modulesummary>The functions on CORBA module level</modulesummary>
- <description>
- <p>This module contains functions that are specified on the CORBA module
- level. It also contains some functions for creating and disposing
- objects.</p>
- </description>
- <funcs>
- <func>
- <name>create(Module, TypeID) -> Object</name>
- <name>create(Module, TypeID, Env) -> Object</name>
- <name>create(Module, TypeID, Env, Optons1) -> Object</name>
- <name>create_link(Module, TypeID) -> Object</name>
- <name>create_link(Module, TypeID, Env) -> Object</name>
- <name>create_link(Module, TypeID, Env, Options2) -> Reply</name>
- <fsummary>Create and start a new server object</fsummary>
- <type>
- <v>Module = atom()</v>
- <v>TypeID = string()</v>
- <v>Env = term()</v>
- <v>Options1 = [{persistent, Bool} | {regname, RegName} | {local_typecheck, Bool}]</v>
- <v>Options2 = [{sup_child, Bool} | {persistent, Bool} | {regname, RegName} | {pseudo, Bool} | {local_typecheck, Bool}]</v>
- <v>RegName = {local, atom()} | {global, term()}</v>
- <v>Reply = #objref | {ok, Pid, #objref}</v>
- <v>Bool = true | false</v>
- <v>Object = #objref</v>
- </type>
- <desc>
- <p>These functions start a new server object. If you start it
- without <em>RegName</em> it can only be accessed through the
- returned object key. Started with a <em>RegName</em> the name is
- registered locally or globally. </p>
- <p><em>TypeID</em> is the repository ID of the server object type and
- could for example look like "IDL:StackModule/Stack:1.0". </p>
- <p><em>Module</em> is the name of the interface API module. </p>
- <p><em>Env</em> is the arguments passed which will be passed to the
- implementations <em>init</em> call-back function.</p>
- <p>A server started with create/2, create/3 or create/4 does not care
- about the parent, which means that the parent is not handled
- explicitly in the generic process part. </p>
- <p>A server started with create_link2, create_link/3 or create_link/4
- is initially linked to the caller, the parent, and it will
- terminate whenever the parent process terminates, and with the same
- reason as the parent. If the server traps exits, the terminate/2
- call-back function is called in order to clean up before the
- termination. These functions should be used if the server is a
- worker in a supervision tree.</p>
- <p>If you use the option <c>{sup_child, true}</c> create_link/4 will return
- <c>{ok, Pid, #objref}</c>, otherwise <c>#objref</c>, and make it possible
- to start a server as a supervisor child (stdlib-1.7 or later).</p>
- <p>If you use the option <c>{persistent, true}</c> you also must use the option
- <c>{regname, {global, Name}}</c>. This combination makes it possible to tell
- the difference between a server permanently terminated or in the process of restarting.</p>
- <p>The option <c>{pseudo, true}</c>, allow us to create an object which is not a
- server. Using <c>{pseudo, true}</c> overrides all other start options.
- For more information see section <c>Module_Interface</c>.</p>
- <p>If a server is started using the option <c>{persistent, true}</c> the object key
- will not be removed unless it terminates with reason <em>normal</em> or <em>shutdown</em>.
- Hence, if persistent servers is used as supervisor children they should be <em>transient</em>
- and the <em>objectkeys_gc_time</em> should be modified (default equals <c>infinity</c>).</p>
- <p>The option <c>{local_typecheck, boolean()}</c>, which overrides the
- <seealso marker="ch_install#flags">Local Typechecking</seealso>
- environment flag, turns on or off typechecking. If activated,
- parameters, replies and raised exceptions will be checked to ensure that
- the data is correct, when invoking operations on CORBA Objects within
- the same Orber domain. Due to the extra overhead, this option
- <em>MAY ONLY</em> be used during testing and development.</p>
- <code type="none">
-Example:
-
- corba:create('StackModule_Stack', "IDL:StackModule/Stack:1.0", {10, test})
- </code>
- </desc>
- </func>
- <func>
- <name>dispose(Object) -> ok</name>
- <fsummary>Stop a server object</fsummary>
- <type>
- <v>Object = #objref</v>
- </type>
- <desc>
- <p>This function is used for terminating the execution of a
- server object. Invoking this operation on a NIL object reference,
- e.g., the return value of <c>corba:create_nil_objref/0</c>, always
- return ok. For valid object references, invoking this operation
- more than once, will result in a system exception.</p>
- </desc>
- </func>
- <func>
- <name>create_nil_objref() -> Object</name>
- <fsummary>Stop a server object</fsummary>
- <type>
- <v>Object = #objref representing NIL.</v>
- </type>
- <desc>
- <p>Creates an object reference that represents the NIL value.
- Attempts to invoke operations using the returned object reference
- will return a system exception.</p>
- </desc>
- </func>
- <func>
- <name>create_subobject_key(Object, Key) -> Result</name>
- <fsummary>Add an Erlang term to a private key field</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Key = term()</v>
- <v>Result = #objref</v>
- </type>
- <desc>
- <p>This function is used to create a subobject in a server object.
- It can for example be useful when one wants unique access to
- separate rows in a mnesia or an ETS table. The <em>Result</em> is
- an object reference that will be seen as a unique reference to
- the outside world but will access the same server object where one
- can use the <em>get_subobject_key/1</em> function to get the private
- key value.</p>
- <p><em>Key</em> is stored in the object reference <em>Object</em>.
- If it is a binary it will be stored as is and otherwise it is
- converted to a binary before storage.</p>
- </desc>
- </func>
- <func>
- <name>get_subobject_key(Object) -> Result</name>
- <fsummary>Fetch the contents of the private key field</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Result = #binary</v>
- </type>
- <desc>
- <p>This function is used to fetch a subobject key from the object
- reference <em>Object</em>. The result is a always a binary, if it
- was an Erlang term that was stored with <em>create_subobject_key/2</em>
- one can to do <em>binary_to_term/1</em> to get the real value. </p>
- </desc>
- </func>
- <func>
- <name>get_pid(Object) -> Result</name>
- <fsummary>Get the process id from an object key</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Result = #pid | {error, Reason} | {'EXCEPTION',E}</v>
- </type>
- <desc>
- <p>This function is to get the process id from an object, which is a
- must when CORBA objects is started/handled in a supervisor tree.
- The function will throw exceptions if the key is not found or
- some other error occurs.</p>
- </desc>
- </func>
- <func>
- <name>raise(Exception)</name>
- <fsummary>Generate an Erlang throw</fsummary>
- <type>
- <v>Exception = record()</v>
- </type>
- <desc>
- <p>This function is used for raising corba exceptions as an
- Erlang user generated exit signal. It will throw the tuple
- <c>{'EXCEPTION', </c><em>Exception</em><c>}</c>.</p>
- </desc>
- </func>
- <func>
- <name>reply(To, Reply) -> true</name>
- <fsummary>Send explicit reply to client</fsummary>
- <type>
- <v>To = client reference</v>
- <v>Reply = IDL type</v>
- </type>
- <desc>
- <p>This function can be used by a CORBA object to explicitly send
- a reply to a client that invoked a two-way operation. If this operation
- is used, it is <em>not</em> possible to return a reply in the call-back
- module.
- <br></br>
-<em>To</em> must be the <em>From</em> argument provided to the
- callback function, which requires that the IC option <em>from</em>
- was used when compiling the IDL-file.</p>
- </desc>
- </func>
- <func>
- <name>resolve_initial_references(ObjectId) -> Object</name>
- <name>resolve_initial_references(ObjectId, Contexts) -> Object</name>
- <fsummary>Return the object reference for the given object id</fsummary>
- <type>
- <v>ObjectId = string()</v>
- <v>Contexts = [Context]</v>
- <v>Context = #'IOP_ServiceContext'{context_id = CtxId, context_data = CtxData}</v>
- <v>CtxId = ?ORBER_GENERIC_CTX_ID</v>
- <v>CtxData = {interface, Interface} | {userspecific, term()} | {configuration, Options}</v>
- <v>Interface = string()</v>
- <v>Options = [{Key, Value}]</v>
- <v>Key = ssl_client_options</v>
- <v>Value = allowed value associated with the given key</v>
- <v>Object = #objref</v>
- </type>
- <desc>
- <p>This function returns the object reference associated with the given
- object id. Initially, only <c>"NameService"</c> is available. To add or remove
- services use <c>add_initial_service/2</c> or <c>remove_initial_service/1</c>.</p>
- <p>The <em>configuration</em> context is used to override the global
- SSL client side
- <seealso marker="ch_install#config">configuration</seealso>.</p>
- </desc>
- </func>
- <func>
- <name>add_initial_service(ObjectId, Object) -> boolean()</name>
- <fsummary>Add a new initial service and associate it with the given id</fsummary>
- <type>
- <v>ObjectId = string()</v>
- <v>Object = #objref</v>
- </type>
- <desc>
- <p>This operation allows us to add initial services, which can be accessed by
- using <c>resolve_initial_references/1</c> or the <c>corbaloc</c> schema.
- If using an Id defined by the OMG, the given object must be of the
- correct type; for more information see the
- <seealso marker="ch_naming_service#interop_ns">Interoperable Naming Service</seealso>.
- Returns <c>false</c> if the given id already exists.</p>
- </desc>
- </func>
- <func>
- <name>remove_initial_service(ObjectId) -> boolean()</name>
- <fsummary>Remove association between the given id and service</fsummary>
- <type>
- <v>ObjectId = string()</v>
- </type>
- <desc>
- <p>If we don not want a certain service to be accessible, invoking this function
- will remove the association. Returns <c>true</c> if able to terminate the
- binding. If no such binding existed <c>false</c> is returned.</p>
- </desc>
- </func>
- <func>
- <name>list_initial_services() -> [ObjectId]</name>
- <fsummary>Return a list of supported object id's</fsummary>
- <type>
- <v>ObjectId = string()</v>
- </type>
- <desc>
- <p>This function returns a list of allowed object id's.</p>
- </desc>
- </func>
- <func>
- <name>resolve_initial_references_remote(ObjectId, Address) -> Object</name>
- <name>resolve_initial_references_remote(ObjectId, Address, Contexts) -> Object</name>
- <fsummary>Return the object reference for the given object id</fsummary>
- <type>
- <v>ObjectId = string()</v>
- <v>Address = [RemoteModifier]</v>
- <v>RemoteModifier = string()</v>
- <v>Contexts = [Context]</v>
- <v>Context = #'IOP_ServiceContext'{context_id = CtxId, context_data = CtxData}</v>
- <v>CtxId = ?ORBER_GENERIC_CTX_ID</v>
- <v>CtxData = {interface, Interface} | {userspecific, term()} | {configuration, Options}</v>
- <v>Interface = string()</v>
- <v>Options = [{Key, Value}]</v>
- <v>Key = ssl_client_options</v>
- <v>Value = allowed value associated with the given key</v>
- <v>Object = #objref</v>
- </type>
- <desc>
- <p>This function returns the object reference for the object id asked
- for.
- The remote modifier string has the following format:
- <c>"iiop://"&lt;host&gt;":"&lt;port&gt;</c> where <c>&lt;host&gt; = &lt;DNS hostname&gt; |
- &lt;IPv4 address&gt; | "["&lt;IPv6 address&gt;"]"</c>.
- </p>
- <p>The <em>configuration</em> context is used to override the global
- SSL client side
- <seealso marker="ch_install#config">configuration</seealso>.</p>
- <warning>
- <p>This operation is not supported by most ORB's. Hence, use
- <c>corba:string_to_object/1</c> instead.</p>
- </warning>
- </desc>
- </func>
- <func>
- <name>list_initial_services_remote(Address) -> [ObjectId]</name>
- <name>list_initial_services_remote(Address, Contexts) -> [ObjectId]</name>
- <fsummary>Return a list of supported object id's</fsummary>
- <type>
- <v>Address = [RemoteModifier]</v>
- <v>RemoteModifier = string()</v>
- <v>Contexts = [Context]</v>
- <v>Context = #'IOP_ServiceContext'{context_id = CtxId, context_data = CtxData}</v>
- <v>CtxId = ?ORBER_GENERIC_CTX_ID</v>
- <v>CtxData = {interface, Interface} | {userspecific, term()} | {configuration, Options}</v>
- <v>Interface = string()</v>
- <v>Options = [{Key, Value}]</v>
- <v>Key = ssl_client_options</v>
- <v>Value = allowed value associated with the given key</v>
- <v>ObjectId = string()</v>
- </type>
- <desc>
- <p>This function returns a list of allowed object id's.
- The remote modifier string has the following format:
- <c>"iiop://"&lt;host&gt;":"&lt;port&gt;</c> where <c>&lt;host&gt; = &lt;DNS hostname&gt; |
- &lt;IPv4 address&gt; | "["&lt;IPv6 address&gt;"]"</c>.
- </p>
- <p>The <em>configuration</em> context is used to override the global
- SSL client side
- <seealso marker="ch_install#config">configuration</seealso>.</p>
- <warning>
- <p>This operation is not supported by most ORB's. Hence, avoid
- using it.</p>
- </warning>
- </desc>
- </func>
- <func>
- <name>object_to_string(Object) -> IOR_string</name>
- <fsummary>Convert the object reference to the external string representation</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>IOR_string = string()</v>
- </type>
- <desc>
- <p>This function returns the object reference as the external string
- representation of an IOR.</p>
- </desc>
- </func>
- <func>
- <name>string_to_object(IOR_string) -> Object</name>
- <name>string_to_object(IOR_string, Contexts) -> Object</name>
- <fsummary>Convert the external string representation to an object reference</fsummary>
- <type>
- <v>IOR_string = string()</v>
- <v>Contexts = [Context]</v>
- <v>Context = #'IOP_ServiceContext'{context_id = CtxId, context_data = CtxData}</v>
- <v>CtxId = ?ORBER_GENERIC_CTX_ID</v>
- <v>CtxData = {interface, Interface} | {userspecific, term()} | {configuration, Options}</v>
- <v>Interface = string()</v>
- <v>Options = [{Key, Value}]</v>
- <v>Key = ssl_client_options</v>
- <v>Value = allowed value associated with the given key</v>
- <v>Object = #objref</v>
- </type>
- <desc>
- <p>This function takes a <c>corbaname</c>, <c>corbaloc</c> or an IOR on the
- external string representation and returns the object reference.</p>
- <p>To lookup the NameService reference, simply use
- <c>"corbaloc:iiop:[email protected]:4001/NameService"</c></p>
- <p>We can also resolve an object from the NameService by using
- <c>"corbaname:iiop:[email protected]:4001/NameService#org/Erlang/MyObj"</c></p>
- <p>To lookup the NameService reference with an IPv6 address, simply use
- <c>"corbaloc:iiop:1.2@[FEC1:0:3:0:0312:44AF:FAB1:3D01]:4001/NameService"</c></p>
- <p>For more information about <c>corbaname</c> and <c>corbaloc</c>, see
- the User's Guide (Interoperable Naming Service).</p>
- <p>The <em>configuration</em> context is used to override the global
- SSL client side
- <seealso marker="ch_install#config">configuration</seealso>.</p>
- <p>How to handle the interface context is further described in the User's Guide.</p>
- </desc>
- </func>
- <func>
- <name>print_object(Data [, Type]) -> ok | {'EXCEPTION', E} | {'EXIT', R} | string()</name>
- <fsummary>Print the supplied object</fsummary>
- <type>
- <v>Data = IOR_string | #objref (local or external) | corbaloc/corbaname string</v>
- <v>Type = IoDevice | error_report | {error_report, Reason} | info_msg | {info_msg, Comment} | string</v>
- <v>IoDevice = see the io-module</v>
- <v>Reason = Comment = string()</v>
- </type>
- <desc>
- <p>The object represented by the supplied data is dissected and presented
- in a more readable form. The Type parameter is optional; if not supplied
- standard output is used. For <c>error_report</c> and <c>info_msg</c>
- the <c>error_logger</c> module is used, with or without Reason or Comment.
- If the atom <c>string</c> is supplied this function will return a flat
- list. The <c>IoDevice</c> is passed to the operation <c>io:format/2</c>.</p>
- <p>If the supplied object is a local reference, the output is equivalent
- to an object exported from the node this function is invoked on.</p>
- </desc>
- </func>
- <func>
- <name>add_alternate_iiop_address(Object, Host, Port) -> NewObject | {'EXCEPTION', E}</name>
- <fsummary>Add ALTERNATE_IIOP_ADDRESS component to the supplied local object</fsummary>
- <type>
- <v>Object = NewObject = local #objref</v>
- <v>Host = string()</v>
- <v>Port = integer()</v>
- </type>
- <desc>
- <p>This operation creates a new instance of the supplied object
- containing an ALTERNATE_IIOP_ADDRESS component. Only the new instance
- contains the new component. When this object is passed to another
- ORB, which supports the ALTERNATE_IIOP_ADDRESS, requests will be routed
- to the alternate address if it is not possible to communicate with
- the main address.</p>
- <p>The ALTERNATE_IIOP_ADDRESS component requires that IIOP-1.2 is used.
- Hence, make sure both Orber and the other ORB is correctly configured.</p>
- <p></p>
- <note>
- <p>Make sure that the given <c>Object</c> is accessible via the
- alternate Host/port. For example, if the object is correctly started as
- <c>local</c> or <c>pseudo</c>, the object should be available on all
- nodes within a multi-node Orber installation. Since only one instance
- exists for other object types, it will not be possible to access it
- if the node it was started on terminates.</p>
- </note>
- </desc>
- </func>
- <func>
- <name>orb_init(KeyValueList) -> ok | {'EXIT', Reason}</name>
- <fsummary>Configure Orber before starting it</fsummary>
- <type>
- <v>KeyValueList = [{Key, Value}]</v>
- <v>Key = any key listed in the configuration chapter</v>
- <v>Value = allowed value associated with the given key</v>
- </type>
- <desc>
- <p>This function allows the user to configure Orber in, for example,
- an Erlang shell. Orber may <em>NOT</em> be started prior to invoking
- this operation. For more information, see
- <seealso marker="ch_install#config">configuration settings</seealso>
- in the User's Guide.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/orber/doc/src/corba_object.xml b/lib/orber/doc/src/corba_object.xml
deleted file mode 100644
index 09a4b0bc3c..0000000000
--- a/lib/orber/doc/src/corba_object.xml
+++ /dev/null
@@ -1,194 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>corba_object</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>1997-11-10</date>
- <rev>A</rev>
- </header>
- <module>corba_object</module>
- <modulesummary>The CORBA Object interface functions</modulesummary>
- <description>
- <p>This module contains the CORBA Object interface functions that can be
- called for all objects.</p>
- </description>
- <funcs>
- <func>
- <name>get_interface(Object) -> InterfaceDef</name>
- <fsummary>Fetch the interface description</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>InterfaceDef = term()</v>
- </type>
- <desc>
- <p>This function returns the full interface description for an object.</p>
- </desc>
- </func>
- <func>
- <name>is_nil(Object) -> boolean()</name>
- <fsummary>Return true, if the given object is a NIL object reference, otherwise false</fsummary>
- <type>
- <v>Object = #objref</v>
- </type>
- <desc>
- <p>This function checks if the object reference has a nil object value,
- which denotes no object. It is the reference that is tested and no
- object implementation is involved in the test. </p>
- </desc>
- </func>
- <func>
- <name>is_a(Object, Logical_type_id) -> Return</name>
- <name>is_a(Object, Logical_type_id, Contexts) -> Return</name>
- <fsummary>Return true if the target object is an, or inherit from, object of the given type</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Logical_type_id = string()</v>
- <v>Contexts = [Context]</v>
- <v>Context = #'IOP_ServiceContext'{context_id = CtxId, context_data = CtxData}</v>
- <v>CtxId = ?ORBER_GENERIC_CTX_ID</v>
- <v>CtxData = {interface, Interface} | {userspecific, term()} | {configuration, Options}</v>
- <v>Interface = string()</v>
- <v>Options = [{Key, Value}]</v>
- <v>Key = ssl_client_options</v>
- <v>Value = allowed value associated with the given key</v>
- <v>Return = boolean() | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>The <em>Logical_type_id</em> is a string that is a share type
- identifier (repository id). The function returns true if the object
- is an instance of that type or an ancestor of the "most derived"
- type of that object.</p>
- <p>The <em>configuration</em> context is used to override the global
- SSL client side
- <seealso marker="ch_install#config">configuration</seealso>.</p>
- <p>Note: Other ORB suppliers may not support this function completely
- according to the OMG specification. Thus, a <em>is_a</em> call may
- raise an exception or respond unpredictable if the Object is
- located on a remote node.</p>
- </desc>
- </func>
- <func>
- <name>is_remote(Object) -> boolean()</name>
- <fsummary>Determine whether or not an object reference is remote</fsummary>
- <type>
- <v>Object = #objref</v>
- </type>
- <desc>
- <p>This function returns true if an object reference is remote
- otherwise false. </p>
- </desc>
- </func>
- <func>
- <name>non_existent(Object) -> Return</name>
- <name>non_existent(Object, Contexts) -> Return</name>
- <fsummary>Return false if the target object do not exist, otherwise true</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Contexts = [Context]</v>
- <v>Context = #'IOP_ServiceContext'{context_id = CtxId, context_data = CtxData}</v>
- <v>CtxId = ?ORBER_GENERIC_CTX_ID</v>
- <v>CtxData = {interface, Interface} | {userspecific, term()} | {configuration, Options}</v>
- <v>Interface = string()</v>
- <v>Options = [{Key, Value}]</v>
- <v>Key = ssl_client_options</v>
- <v>Value = allowed value associated with the given key</v>
- <v>Return = boolean() | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This function can be used to test if the object has been destroyed.
- It does this without invoking any application level code. The ORB
- returns true if it knows that the object is destroyed otherwise
- false.</p>
- <p>The <em>configuration</em> context is used to override the global
- SSL client side
- <seealso marker="ch_install#config">configuration</seealso>.</p>
- <p>Note: The OMG have specified two different operators, <c>_not_existent</c> (CORBA version 2.0 and 2.2) and
- <c>_non_existent</c> (CORBA version 2.3), to be used for this function. It is not mandatory to support
- both versions. Thus, a <em>non_existent</em> call may raise an exception or respond unpredictable
- if the Object is located on a remote node. Depending on which version, ORB:s you intend to
- communicate with supports, you can either use this function or <c>not_existent/1</c>.</p>
- </desc>
- </func>
- <func>
- <name>not_existent(Object) -> Return</name>
- <name>not_existent(Object, Contexts) -> Return</name>
- <fsummary>Return false if the target object do not exist, otherwise true</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Contexts = [Context]</v>
- <v>Context = #'IOP_ServiceContext'{context_id = CtxId, context_data = CtxData}</v>
- <v>CtxId = ?ORBER_GENERIC_CTX_ID</v>
- <v>CtxData = {interface, Interface} | {userspecific, term()} | {configuration, Options}</v>
- <v>Interface = string()</v>
- <v>Options = [{Key, Value}]</v>
- <v>Key = ssl_client_options</v>
- <v>Value = allowed value associated with the given key</v>
- <v>Return = boolean() | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>This function is implemented due to Interoperable purposes. Behaves as
- <c>non_existent</c> except the operator <c>_not_existent</c> is used when
- communicating with other ORB:s.</p>
- <p>The <em>configuration</em> context is used to override the global
- SSL client side
- <seealso marker="ch_install#config">configuration</seealso>.</p>
- </desc>
- </func>
- <func>
- <name>is_equivalent(Object, OtherObject) -> boolean()</name>
- <fsummary>Return true if the target object and the supplied object easily can be determined to be equal, otherwise false</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>OtherObject = #objref</v>
- </type>
- <desc>
- <p>This function is used to determine if two object references are
- equivalent so far the ORB easily can determine. It returns
- <em>true</em> if the target object reference is equal to the
- other object reference and <em>false</em> otherwise.</p>
- </desc>
- </func>
- <func>
- <name>hash(Object, Maximum) -> int()</name>
- <fsummary>Return a hash value based on the target object</fsummary>
- <type>
- <v>Object = #objref</v>
- <v>Maximum = int()</v>
- </type>
- <desc>
- <p>This function returns a hash value based on the object reference
- that not will change during the lifetime of the object.
- The <em>Maximum</em> parameter denotes the upper bound of the value.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/orber/doc/src/dataframe1.gif b/lib/orber/doc/src/dataframe1.gif
deleted file mode 100644
index 21bd0afbc5..0000000000
--- a/lib/orber/doc/src/dataframe1.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/dataframe2.gif b/lib/orber/doc/src/dataframe2.gif
deleted file mode 100644
index 26778932b4..0000000000
--- a/lib/orber/doc/src/dataframe2.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/dataframe3.gif b/lib/orber/doc/src/dataframe3.gif
deleted file mode 100644
index db8ffef7d1..0000000000
--- a/lib/orber/doc/src/dataframe3.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/dataframe4.gif b/lib/orber/doc/src/dataframe4.gif
deleted file mode 100644
index f64c7f3733..0000000000
--- a/lib/orber/doc/src/dataframe4.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/dataframe5.gif b/lib/orber/doc/src/dataframe5.gif
deleted file mode 100644
index 80e17945a2..0000000000
--- a/lib/orber/doc/src/dataframe5.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/dataframe6.gif b/lib/orber/doc/src/dataframe6.gif
deleted file mode 100644
index fb1c5d7827..0000000000
--- a/lib/orber/doc/src/dataframe6.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/dataframe7.gif b/lib/orber/doc/src/dataframe7.gif
deleted file mode 100644
index 1e18078f0a..0000000000
--- a/lib/orber/doc/src/dataframe7.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/dataframe8.gif b/lib/orber/doc/src/dataframe8.gif
deleted file mode 100644
index ef95c9a11f..0000000000
--- a/lib/orber/doc/src/dataframe8.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/dependent.gif b/lib/orber/doc/src/dependent.gif
deleted file mode 100644
index c65c427421..0000000000
--- a/lib/orber/doc/src/dependent.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/example_part.xml b/lib/orber/doc/src/example_part.xml
deleted file mode 100644
index 61c9524cc3..0000000000
--- a/lib/orber/doc/src/example_part.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2002</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Service Implementation</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2002-06-25</date>
- <rev>A</rev>
- </header>
- <description>
- <p>This chapter describe how to implement Orber based CORBA services.</p>
- </description>
- <include file="ch_stubs"></include>
-</part>
-
diff --git a/lib/orber/doc/src/fascicules.xml b/lib/orber/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/orber/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/orber/doc/src/firewall_nat.gif b/lib/orber/doc/src/firewall_nat.gif
deleted file mode 100644
index 3a80aac724..0000000000
--- a/lib/orber/doc/src/firewall_nat.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/fixed.xml b/lib/orber/doc/src/fixed.xml
deleted file mode 100644
index a751476cf7..0000000000
--- a/lib/orber/doc/src/fixed.xml
+++ /dev/null
@@ -1,161 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2002</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>fixed</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2002-05-22</date>
- <rev>A</rev>
- </header>
- <module>fixed</module>
- <modulesummary>the corba fixed type</modulesummary>
- <description>
- <p>This module contains functions that gives an interface to the CORBA fixed type.</p>
- <p>The type <c>Fixed</c> used below is defined as:</p>
- <code type="none">
- -record(fixed, {digits, scale, value}).
- </code>
- <p>where <c>digits</c> is the total amount of digits it consists of and
- <c>scale</c> is the number of fractional digits. The <c>value</c> field
- contains the actual Fixed value represented as an integer. The limitations
- of each field are:</p>
- <list type="bulleted">
- <item>Digits - integer(), -1 > Digits &lt; 32</item>
- <item>Scale - integer(), -1 > Scale =&lt; Digits</item>
- <item>Value - integer(), range (31 digits): &plusmn;9999999999999999999999999999999</item>
- </list>
- <p>Since the Value part is represented by an integer, it is vital that the
- Digits and Scale values are correct. This also means that trailing zeros
- cannot be left out in some cases:</p>
- <list type="bulleted">
- <item>fixed&lt;5,3> eq. 03.140d eq. 3140</item>
- <item>fixed&lt;3,2> eq. 3.14d eq. 314</item>
- </list>
- <p>Leading zeros can be left out.</p>
- <p>For your convenience, this module exports functions which handle
- unary (<c>-</c>) and binary (<c>+-*/</c>) operations legal for the Fixed type.
- Since a unary <c>+</c> have no effect, this module do not export such a
- function. Any of the binary operations may cause an overflow (i.e. more than
- 31 significant digits; leading and trailing zeros are not considered
- significant). If this is the case, the Digit and Scale values are adjusted
- and the Value truncated (no rounding performed). This behavior is
- compliant with the OMG CORBA specification. Each binary operation have
- the following upper bounds:</p>
- <list type="bulleted">
- <item><em>Fixed1 + Fixed2</em> - <c><![CDATA[fixed<max(d1-s1,d2-s2) + max(s1,s2) + 1, max(s1,s2)>]]></c></item>
- <item><em>Fixed1 - Fixed2</em> - <c><![CDATA[fixed<max(d1-s1,d2-s2) + max(s1,s2) + 1, max(s1,s2)>]]></c></item>
- <item><em>Fixed1 * Fixed2</em> - <c><![CDATA[fixed<d1+d2, s1+s2>]]></c></item>
- <item><em>Fixed1 / Fixed2</em> - <c><![CDATA[fixed<(d1-s1+s2) + Sinf ,Sinf >]]></c></item>
- </list>
- <p>A quotient may have an arbitrary number of decimal places, which is
- denoted by a scale of Sinf.</p>
- </description>
- <funcs>
- <func>
- <name>create(Digits, Scale, Value) -> Result</name>
- <fsummary>Create a fixed type</fsummary>
- <type>
- <v>Result = Fixed Type | {'EXCEPTION', #'BAD_PARAM'{}}</v>
- </type>
- <desc>
- <p>This function creates a new instance of a <c>Fixed Type</c>. If
- the limitations is not fulfilled (e.g. overflow) an exception is
- raised.</p>
- </desc>
- </func>
- <func>
- <name>get_typecode(Fixed) -> Result</name>
- <fsummary>Create TypeCode representing the supplied fixed type</fsummary>
- <type>
- <v>Result = TypeCode | {'EXCEPTION', #'BAD_PARAM'{}}</v>
- </type>
- <desc>
- <p>Returns the TypeCode which represents the supplied Fixed type.
- If the parameter is not of the correct type, an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>add(Fixed1, Fixed2) -> Result</name>
- <fsummary>Add the supplied Fixed types</fsummary>
- <type>
- <v>Result = Fixed1 + Fixed2 | {'EXCEPTION', #'BAD_PARAM'{}}</v>
- </type>
- <desc>
- <p>Performs a Fixed type addition.
- If the parameters are not of the correct type, an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>subtract(Fixed1, Fixed2) -> Result</name>
- <fsummary>Subtract Fixed2 from Fixed1</fsummary>
- <type>
- <v>Result = Fixed1 - Fixed2 | {'EXCEPTION', #'BAD_PARAM'{}}</v>
- </type>
- <desc>
- <p>Performs a Fixed type subtraction.
- If the parameters are not of the correct type, an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>multiply(Fixed1, Fixed2) -> Result</name>
- <fsummary>Multiply Fixed1 with Fixed2</fsummary>
- <type>
- <v>Result = Fixed1 * Fixed2 | {'EXCEPTION', #'BAD_PARAM'{}}</v>
- </type>
- <desc>
- <p>Performs a Fixed type multiplication.
- If the parameters are not of the correct type, an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>divide(Fixed1, Fixed2) -> Result</name>
- <fsummary>Divide Fixed1 with Fixed2</fsummary>
- <type>
- <v>Result = Fixed1 / Fixed2 | {'EXCEPTION', #'BAD_PARAM'{}}</v>
- </type>
- <desc>
- <p>Performs a Fixed type division.
- If the parameters are not of the correct type, an exception is raised.</p>
- </desc>
- </func>
- <func>
- <name>unary_minus(Fixed) -> Result</name>
- <fsummary>Negate the supplied Fixed Type</fsummary>
- <type>
- <v>Result = -Fixed | {'EXCEPTION', #'BAD_PARAM'{}}</v>
- </type>
- <desc>
- <p>Negates the supplied Fixed type.
- If the parameter is not of the correct type, an exception is raised.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/orber/doc/src/ifr_notes.txt b/lib/orber/doc/src/ifr_notes.txt
deleted file mode 100644
index 54f79be8cd..0000000000
--- a/lib/orber/doc/src/ifr_notes.txt
+++ /dev/null
@@ -1,53 +0,0 @@
--*-Mode: Outline;-*-
-
-* Transactions.
- Transaction handling (or the use of mnesia:async_dirty) is not very
- good at error checking. Code to handle errors from transactions must
- be added. Right now it is not possible to mix atomic transactions
- with dirty 'transactions' (i.e. async_dirty) and still check the
- results consistently. This must be fixed if we are to read with
- async_dirty instead of transaction, since we still want to do all
- the writes with transaction and not async_dirty.
- (This point might be moot. Simple reads are now done with
- mnesia:dirty_read/1 outside of transactions).
-
-* Unresolved issues.
- There are some places in the source code marked with '***' where the
- code should be verified. It mostly concerns minor unresolved
- unclarities in the specification.
-
-** orber_ifr_contained.erl
- In move/4 there is a call to orber_ifr_contained:lookup_name/5. The
- third argument, Levels_to_search, is set to -1, which means search
- all contained objects. This is probably correct.
-
-** orber_ifr_interfacedef.erl
- The function describe_interface/1 describes the interface without
- its inherited interfaces. It is not clear whether this is correct or
- not. It is possible to get a description of the inherited interfaces
- by mapping describe_interface/1 on the list if interfaces returned
- by get_base_interfaces/1. Also, since the structs
- InterfaceDescription and FullInterfaceDescription both have a field
- named base_interfaces, it is possible to get a description of the
- inherited attributes by examining that field and applying a describe
- function.
-
-** orber_ifr_orb.erl
- create_union_tc/4 sets the fifth element in the typecode tuple to
- -1, meaning no default case.
-
-** orber_ifr_repository.erl
- The PrimitiveDef with kind pk_objref has an empty Id and an empty
- Name. This is perhaps not correct.
-
-** orber_ifr_typecode.erl
- None of the functions in this module are fully implemented and they
- should not be used.
-
-** orber_ifr_uniondef.erl
-*** '_set_members'/2
- What should the value of the discriminator-typecode be when updating
- the type attribute? (CORBA 2.0, p 6-20). For now we just leave it
- unchanged, but this is perhaps not the right thing to do.
-
-* Exceptions should give more information about the failure.
diff --git a/lib/orber/doc/src/iiop.gif b/lib/orber/doc/src/iiop.gif
deleted file mode 100644
index d2f2fd128c..0000000000
--- a/lib/orber/doc/src/iiop.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/GridBagEx.gif b/lib/orber/doc/src/images/GridBagEx.gif
deleted file mode 100644
index 16c326d88c..0000000000
--- a/lib/orber/doc/src/images/GridBagEx.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/OpenBookIcon.gif b/lib/orber/doc/src/images/OpenBookIcon.gif
deleted file mode 100644
index 86384f7733..0000000000
--- a/lib/orber/doc/src/images/OpenBookIcon.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/blue-ball-small.gif b/lib/orber/doc/src/images/blue-ball-small.gif
deleted file mode 100644
index d4c5cde5b0..0000000000
--- a/lib/orber/doc/src/images/blue-ball-small.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/blue-ball.gif b/lib/orber/doc/src/images/blue-ball.gif
deleted file mode 100644
index edc29b786c..0000000000
--- a/lib/orber/doc/src/images/blue-ball.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/class-index.gif b/lib/orber/doc/src/images/class-index.gif
deleted file mode 100644
index 7f276bcb24..0000000000
--- a/lib/orber/doc/src/images/class-index.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/constructor-index.gif b/lib/orber/doc/src/images/constructor-index.gif
deleted file mode 100644
index 435cac4238..0000000000
--- a/lib/orber/doc/src/images/constructor-index.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/constructors.gif b/lib/orber/doc/src/images/constructors.gif
deleted file mode 100644
index d1a6ae507c..0000000000
--- a/lib/orber/doc/src/images/constructors.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/cyan-ball-small.gif b/lib/orber/doc/src/images/cyan-ball-small.gif
deleted file mode 100644
index 7f74357443..0000000000
--- a/lib/orber/doc/src/images/cyan-ball-small.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/cyan-ball.gif b/lib/orber/doc/src/images/cyan-ball.gif
deleted file mode 100644
index 97ca1f2b6e..0000000000
--- a/lib/orber/doc/src/images/cyan-ball.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/error-index.gif b/lib/orber/doc/src/images/error-index.gif
deleted file mode 100644
index 22835ff8c6..0000000000
--- a/lib/orber/doc/src/images/error-index.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/exception-index.gif b/lib/orber/doc/src/images/exception-index.gif
deleted file mode 100644
index e3830d9c52..0000000000
--- a/lib/orber/doc/src/images/exception-index.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/green-ball-small.gif b/lib/orber/doc/src/images/green-ball-small.gif
deleted file mode 100644
index 17fea5b32b..0000000000
--- a/lib/orber/doc/src/images/green-ball-small.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/green-ball.gif b/lib/orber/doc/src/images/green-ball.gif
deleted file mode 100644
index 71e1b2ec2d..0000000000
--- a/lib/orber/doc/src/images/green-ball.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/interface-index.gif b/lib/orber/doc/src/images/interface-index.gif
deleted file mode 100644
index bf93dda9e3..0000000000
--- a/lib/orber/doc/src/images/interface-index.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/magenta-ball-small.gif b/lib/orber/doc/src/images/magenta-ball-small.gif
deleted file mode 100644
index bd0584b3c6..0000000000
--- a/lib/orber/doc/src/images/magenta-ball-small.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/magenta-ball.gif b/lib/orber/doc/src/images/magenta-ball.gif
deleted file mode 100644
index 5da03b84d2..0000000000
--- a/lib/orber/doc/src/images/magenta-ball.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/method-index.gif b/lib/orber/doc/src/images/method-index.gif
deleted file mode 100644
index a05e705116..0000000000
--- a/lib/orber/doc/src/images/method-index.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/methods.gif b/lib/orber/doc/src/images/methods.gif
deleted file mode 100644
index 949e01b8a3..0000000000
--- a/lib/orber/doc/src/images/methods.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/package-index.gif b/lib/orber/doc/src/images/package-index.gif
deleted file mode 100644
index f894d4210d..0000000000
--- a/lib/orber/doc/src/images/package-index.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/red-ball-small.gif b/lib/orber/doc/src/images/red-ball-small.gif
deleted file mode 100644
index f6b3c372ca..0000000000
--- a/lib/orber/doc/src/images/red-ball-small.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/red-ball.gif b/lib/orber/doc/src/images/red-ball.gif
deleted file mode 100644
index dca9296014..0000000000
--- a/lib/orber/doc/src/images/red-ball.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/variable-index.gif b/lib/orber/doc/src/images/variable-index.gif
deleted file mode 100644
index 65cc029e72..0000000000
--- a/lib/orber/doc/src/images/variable-index.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/variables.gif b/lib/orber/doc/src/images/variables.gif
deleted file mode 100644
index e8a735399a..0000000000
--- a/lib/orber/doc/src/images/variables.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/yellow-ball-small.gif b/lib/orber/doc/src/images/yellow-ball-small.gif
deleted file mode 100644
index 8e5f57cdfc..0000000000
--- a/lib/orber/doc/src/images/yellow-ball-small.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/images/yellow-ball.gif b/lib/orber/doc/src/images/yellow-ball.gif
deleted file mode 100644
index 2b8c0bb3d6..0000000000
--- a/lib/orber/doc/src/images/yellow-ball.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/interceptor_operations.gif b/lib/orber/doc/src/interceptor_operations.gif
deleted file mode 100644
index cd72f7fcb7..0000000000
--- a/lib/orber/doc/src/interceptor_operations.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/interceptors.xml b/lib/orber/doc/src/interceptors.xml
deleted file mode 100644
index 0aade8ffb4..0000000000
--- a/lib/orber/doc/src/interceptors.xml
+++ /dev/null
@@ -1,284 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2001</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>interceptors</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>1999-09-03</date>
- <rev>A</rev>
- </header>
- <module>interceptors</module>
- <modulesummary>Describe the functions which must be exported by any supplied Orber native interceptor.</modulesummary>
- <description>
- <p>This module contains the mandatory functions for user supplied native
- interceptors and their intended behavior. See also the User's Guide.</p>
- <warning>
- <p>Using <c>Interceptors</c> may reduce the through-put significantly
- if the supplied interceptors invoke expensive operations. Hence,
- one should always supply interceptors which cause as little overhead
- as possible.</p>
- </warning>
- <warning>
- <p>It is possible to alter the <c>Data</c>, <c>Bin</c> and <c>Args</c>
- parameter for the <c>in_reply</c> and <c>out_reply</c>,
- <c>in_reply_encoded</c>, <c>in_request_encoded</c>,
- <c>out_reply_encoded</c> and <c>out_request_encoded</c>,
- <c>in_request</c> and <c>out_request</c> respectively. But,
- if it is done incorrectly, the consequences can be serious.</p>
- </warning>
- <note>
- <p>The <c>Extra</c> parameter is set to 'undefined' by Orber when calling
- the first interceptor and may be set to any Erlang term. If an
- interceptor change this parameter it will be passed on to the next
- interceptor in the list uninterpreted.</p>
- </note>
- <note>
- <p>The <c>Ref</c> parameter is set to 'undefined' by Orber when calling
- <c>new_in_connection</c> or <c>new_out_connection</c> using
- the first interceptor. The user supplied interceptor may set <c>NewRef</c>
- to any Erlang term. If an interceptor change this parameter it will be
- passed on to the next interceptor in the list uninterpreted.</p>
- </note>
- </description>
- <funcs>
- <func>
- <name>new_in_connection(Ref, PeerHost, PeerPort) -> NewRef</name>
- <name>new_in_connection(Ref, PeerHost, PeerPort, SocketHost, SocketPort) -> NewRef</name>
- <fsummary>Invoke when a new client ORB wants to setup a connection</fsummary>
- <type>
- <v>Ref = term() | undefined</v>
- <v>PeerHost = SocketHost = string(), e.g., "myHost@myServer" or "192.0.0.10"</v>
- <v>PeerPort = SocketPort = integer()</v>
- <v>NewRef = term() | {'EXIT', Reason}</v>
- </type>
- <desc>
- <p>When a new connection is requested by a client side ORB this operation
- is invoked. If more than one interceptor is supplied, e.g.,
- <c>{native, ['myInterceptor1', 'myInterceptor2']}</c>, the return value
- from 'myInterceptor1' is passed to 'myInterceptor2' as <c>Ref</c>.
- Initially, Orber uses the atom 'undefined' as <c>Ref</c> parameter
- when calling the first interceptor. The return value from the last
- interceptor, in the example above 'myInterceptor2', is passed
- to all other functions exported by the interceptors. Hence,
- the <c>Ref</c> parameter can, for example, be used as a unique
- identifier to mnesia or ets where information/restrictions for
- this connection is stored.</p>
- <p>The PeerHost and PeerPort variables supplied data of
- the client ORB which requested a new connection. SocketHost
- and SocketPort are the local interface and port the client
- connected to.</p>
- <p>If, for some reason, we do not allow the client ORB to connect
- simply invoke <c>exit(Reason)</c>.</p>
- </desc>
- </func>
- <func>
- <name>new_out_connection(Ref, PeerHost, PeerPort) -> NewRef</name>
- <name>new_out_connection(Ref, PeerHost, PeerPort, SocketHost, SocketPort) -> NewRef</name>
- <fsummary>Invoke when setting up a new connection to a server side ORB</fsummary>
- <type>
- <v>Ref = term() | undefined</v>
- <v>PeerHost = SocketHost = string(), e.g., "myHost@myServer" or "192.0.0.10"</v>
- <v>PeerPort = SocketPort = integer()</v>
- <v>NewRef = term() | {'EXIT', Reason}</v>
- </type>
- <desc>
- <p>When a new connection is set up this function is invoked. Behaves
- just like <c>new_in_connection</c>; the only difference is that
- the PeerHost and PeerPort variables identifies the target ORB's bootstrap
- data and SocketHost and SocketPort are the local interface and port
- the client ORB connected via.</p>
- </desc>
- </func>
- <func>
- <name>closed_in_connection(Ref) -> NewRef</name>
- <fsummary>Invoke when an existing connection to a client side ORB have been terminated</fsummary>
- <type>
- <v>Ref = term()</v>
- <v>NewRef = term()</v>
- </type>
- <desc>
- <p>When an existing connection is terminated this operation is invoked.
- The main purpose of this function is to make it possible for a user
- to clean up all data associated with the associated connection.</p>
- <p>The input parameter <c>Ref</c> is the return value from
- <c>new_in_connection/3</c>.</p>
- </desc>
- </func>
- <func>
- <name>closed_out_connection(Ref) -> NewRef</name>
- <fsummary>Invoke when an existing connection to a server side ORB have been terminated</fsummary>
- <type>
- <v>Ref = term()</v>
- <v>NewRef = term()</v>
- </type>
- <desc>
- <p>When an existing connection is terminated this operation is invoked.
- The main purpose of this function is to make it possible for a user
- to clean up all data associated with the associated connection.</p>
- <p>The input parameter <c>Ref</c> is the return value from
- <c>new_out_connection/3</c>.</p>
- </desc>
- </func>
- <func>
- <name>in_reply(Ref, Obj, Ctx, Op, Data, Extra) -> Reply</name>
- <fsummary>Invoke when replies arrives at the client side ORB</fsummary>
- <type>
- <v>Ref = term()</v>
- <v>Obj = #objref</v>
- <v>Ctx = [#'IOP_ServiceContext'{}]</v>
- <v>Op = atom()</v>
- <v>Data = [Result, OutParameter1, ..., OutPramaterN]</v>
- <v>Reply = {NewData, NewExtra}</v>
- </type>
- <desc>
- <p>When replies are delivered from the server side ORB to the client side
- ORB this operation is invoked. The <c>Data</c> parameter is a list in which
- the first element is the return value value from the target object and
- the rest is a all parameters defined as <c>out</c> or <c>inout</c> in
- the IDL-specification.</p>
- </desc>
- </func>
- <func>
- <name>in_reply_encoded(Ref, Obj, Ctx, Op, Bin, Extra) -> Reply</name>
- <fsummary>Invoke when replies arrives at the client side ORB with undecoded reply body</fsummary>
- <type>
- <v>Ref = term()</v>
- <v>Obj = #objref</v>
- <v>Ctx = [#'IOP_ServiceContext'{}]</v>
- <v>Op = atom()</v>
- <v>Bin = #binary</v>
- <v>Reply = {NewBin, NewExtra}</v>
- </type>
- <desc>
- <p>When replies are delivered from the server side ORB to the client side
- ORB this operation is invoked. The <c>Bin</c> parameter is the reply
- body still uncoded.</p>
- </desc>
- </func>
- <func>
- <name>in_request(Ref, Obj, Ctx, Op, Args, Extra) -> Reply</name>
- <fsummary>Invoke when requests arrive at the server side ORB</fsummary>
- <type>
- <v>Ref = term()</v>
- <v>Obj = #objref</v>
- <v>Ctx = [#'IOP_ServiceContext'{}]</v>
- <v>Op = atom()</v>
- <v>Args = [Argument] - defined in the IDL-specification</v>
- <v>Reply = {NewArgs, NewExtra}</v>
- </type>
- <desc>
- <p>When a new request arrives at the server side ORB this operation is
- invoked.</p>
- </desc>
- </func>
- <func>
- <name>in_request_encoded(Ref, Obj, Ctx, Op, Bin, Extra) -> Reply</name>
- <fsummary>Invoke when requests arrive at the server side ORB with undecoded request body</fsummary>
- <type>
- <v>Ref = term()</v>
- <v>Obj = #objref</v>
- <v>Ctx = [#'IOP_ServiceContext'{}]</v>
- <v>Op = atom()</v>
- <v>Bin = #binary</v>
- <v>Reply = {NewBin, NewExtra}</v>
- </type>
- <desc>
- <p>When a new request arrives at the server side ORB this operation is
- invoked before decoding the request body.</p>
- </desc>
- </func>
- <func>
- <name>out_reply(Ref, Obj, Ctx, Op, Data, Extra) -> Reply</name>
- <fsummary>Invoke after the target object replied</fsummary>
- <type>
- <v>Ref = term()</v>
- <v>Obj = #objref</v>
- <v>Ctx = [#'IOP_ServiceContext'{}]</v>
- <v>Op = atom()</v>
- <v>Data = [Result, OutParameter1, ..., OutPramaterN]</v>
- <v>Reply = {NewData, NewExtra}</v>
- </type>
- <desc>
- <p>After the target object have been invoked this operation is invoked
- with the result. The <c>Data</c> parameter is a list in which
- the first element is the return value value from the target object and
- the rest is a all parameters defined as <c>out</c> or <c>inout</c> in
- the IDL-specification.</p>
- </desc>
- </func>
- <func>
- <name>out_reply_encoded(Ref, Obj, Ctx, Op, Bin, Extra) -> Reply</name>
- <fsummary>Invoke after the target object replied with the reply encoded</fsummary>
- <type>
- <v>Ref = term()</v>
- <v>Obj = #objref</v>
- <v>Ctx = [#'IOP_ServiceContext'{}]</v>
- <v>Op = atom()</v>
- <v>Bin = #binary</v>
- <v>Reply = {NewBin, NewExtra}</v>
- </type>
- <desc>
- <p>This operation is similar to <c>out_reply</c>; the only difference is
- that the reply body have been encoded.</p>
- </desc>
- </func>
- <func>
- <name>out_request(Ref, Obj, Ctx, Op, Args, Extra) -> Reply</name>
- <fsummary>Invoke on the client side ORB before encoding and sending the request</fsummary>
- <type>
- <v>Ref = term()</v>
- <v>Obj = #objref</v>
- <v>Ctx = [#'IOP_ServiceContext'{}]</v>
- <v>Op = atom()</v>
- <v>Args = [Argument] - defined in the IDL-specification</v>
- <v>Reply = {NewArgs, NewExtra}</v>
- </type>
- <desc>
- <p>Before a request is sent to the server side ORB, <c>out_request</c> is
- invoked.</p>
- </desc>
- </func>
- <func>
- <name>out_request_encoded(Ref, Obj, Ctx, Op, Bin, Extra) -> Reply</name>
- <fsummary>Invoke on the client side ORB before sending the request</fsummary>
- <type>
- <v>Ref = term()</v>
- <v>Obj = #objref</v>
- <v>Ctx = [#'IOP_ServiceContext'{}]</v>
- <v>Op = atom()</v>
- <v>Bin = #binary</v>
- <v>Reply = {NewBin, NewExtra}</v>
- </type>
- <desc>
- <p>This operation is similar to <c>out_request</c>; the only
- difference is that the request body have been encoded.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/orber/doc/src/intro_part.xml b/lib/orber/doc/src/intro_part.xml
deleted file mode 100644
index 7e5520e42e..0000000000
--- a/lib/orber/doc/src/intro_part.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2002</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Introduction to Orber and the IFR</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2002-06-25</date>
- <rev>A</rev>
- </header>
- <description>
- <p>This chapter contains an introduction to Orber and the IFR
- (Interface Repository).</p>
- </description>
- <include file="ch_introduction"></include>
- <include file="ch_orber_kernel"></include>
- <include file="ch_ifr"></include>
-</part>
-
diff --git a/lib/orber/doc/src/lname.xml b/lib/orber/doc/src/lname.xml
deleted file mode 100644
index 09d6859777..0000000000
--- a/lib/orber/doc/src/lname.xml
+++ /dev/null
@@ -1,166 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>lname</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>1997-06-10</date>
- <rev>A</rev>
- </header>
- <module>lname</module>
- <modulesummary>Interface that supports the name pseudo-objects.</modulesummary>
- <description>
- <p>This interface is a part of the names library which is used to hide the
- representation of names. In Orbers Erlang mapping the pseudo-object names
- and the real IDL names have the same representation but it is desirable that
- the clients uses the names library so they will not be dependent of the representation.
- The lname interface supports handling of names e.g. adding and removing name
- components.</p>
- <p>Note that the lname interface in orber does not contain a destroy function because
- the Names are represented as standard Erlang lists and therefor will be removed
- by the garbage collector when not in use.</p>
- <p>The type <c>NameComponent</c> used below is defined as:</p>
- <code type="none">
- -record('CosNaming_NameComponent', {id, kind=""}).
- </code>
- <p><c>id</c> and <c>kind</c> are strings. </p>
- <p>The record is defined in the file <c>CosNaming.hrl</c> and it
- is included with:</p>
- <code type="none">
- -include_lib("orber/COSS/CosNaming/CosNaming.hrl").
- </code>
- </description>
- <funcs>
- <func>
- <name>create() -> Return</name>
- <fsummary>Create a new name</fsummary>
- <type>
- <v>Return = [NameComponent]</v>
- </type>
- <desc>
- <p>This function returns a new name.</p>
- </desc>
- </func>
- <func>
- <name>insert_component(Name, N, NameComponent) -> Return</name>
- <fsummary>Insert a new name component in a name</fsummary>
- <type>
- <v>Name = [NameComponent]</v>
- <v>N = int()</v>
- <v>Return = Name</v>
- </type>
- <desc>
- <p>This function returns a name where the new name component has been inserted as
- component <c>N</c> in Name.</p>
- </desc>
- </func>
- <func>
- <name>get_component(Name, N) -> Return</name>
- <fsummary>Get a name component from a name</fsummary>
- <type>
- <v>Name = [NameComponent]</v>
- <v>N = int()</v>
- <v>Return = NameComponent</v>
- </type>
- <desc>
- <p>This function returns the <c>N:th</c> name component in Name.</p>
- </desc>
- </func>
- <func>
- <name>delete_component(Name, N) -> Return</name>
- <fsummary>Delete a name component from a name</fsummary>
- <type>
- <v>Name = [NameComponent]</v>
- <v>N = int()</v>
- <v>Return = Name</v>
- </type>
- <desc>
- <p>This function deletes the <c>N:th</c> name component from Name and returns
- the new name.</p>
- </desc>
- </func>
- <func>
- <name>num_component(Name) -> Return</name>
- <fsummary>Count the number of name components in a name</fsummary>
- <type>
- <v>Name = [NameComponent]</v>
- <v>Return = int()</v>
- </type>
- <desc>
- <p>This function returns a the number of name components in Name.</p>
- </desc>
- </func>
- <func>
- <name>equal(Name1, Name2) -> Return</name>
- <fsummary>Test if two names are equal</fsummary>
- <type>
- <v>Name1 = Name2 = [NameComponent]</v>
- <v>Return = bool()</v>
- </type>
- <desc>
- <p>This function returns true if the two names are equal and false otherwise.</p>
- </desc>
- </func>
- <func>
- <name>less_than(Name1, Name2) -> Return</name>
- <fsummary>Test if one name is lesser than the other</fsummary>
- <type>
- <v>Name1 = Name2 = [NameComponent]</v>
- <v>Return = bool()</v>
- </type>
- <desc>
- <p>This function returns true if Name1 are lesser than Name2 and false otherwise.</p>
- </desc>
- </func>
- <func>
- <name>to_idl_form(Name) -> Return</name>
- <fsummary>Transform a pseudo name to an IDL name</fsummary>
- <type>
- <v>Name = [NameComponent]</v>
- <v>Return = Name</v>
- </type>
- <desc>
- <p>This function just checks if Name is a correct IDL name before returning it
- because the name representation is the same for pseudo and IDL names in orber.</p>
- </desc>
- </func>
- <func>
- <name>from_idl_form(Name) -> Return</name>
- <fsummary>Transform an IDL name to a pseudo name</fsummary>
- <type>
- <v>Name = [NameComponent]</v>
- <v>Return = Name</v>
- </type>
- <desc>
- <p>This function just returns the Name because the name representation is the
- same for pseudo and IDL names in orber.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/orber/doc/src/lname_component.xml b/lib/orber/doc/src/lname_component.xml
deleted file mode 100644
index 631e5d0244..0000000000
--- a/lib/orber/doc/src/lname_component.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>lname_component</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>1997-06-10</date>
- <rev>A</rev>
- </header>
- <module>lname_component</module>
- <modulesummary>Interface that supports the name pseudo-objects.</modulesummary>
- <description>
- <p>This interface is a part of the name library, which is used to hide the
- representation of names. In Orbers Erlang mapping the pseudo-object names
- and the real IDL names have the same representation but it is desirable that
- the clients uses the names library so they will not be dependent of the representation.
- The lname_component interface supports handling of name components e.g. set and get
- of the struct members.</p>
- <p>Note that the lname_component interface in orber does not contain a destroy
- function because the NameComponents are represented as Erlang records and
- therefor will be removed by the garbage collector when not in use.</p>
- <p>The type <c>NameComponent</c> used below is defined as:</p>
- <code type="none">
- -record('CosNaming_NameComponent', {id, kind=""}).
- </code>
- <p><c>id</c> and <c>kind</c> are strings. </p>
- <p>The record is defined in the file <c>CosNaming.hrl</c> and it
- is included with:</p>
- <code type="none">
- -include_lib("orber/COSS/CosNaming/CosNaming.hrl").
- </code>
- </description>
- <funcs>
- <func>
- <name>create() -> Return</name>
- <fsummary>Create a new name component</fsummary>
- <type>
- <v>Return = NameComponent</v>
- </type>
- <desc>
- <p>This function returns a new name component.</p>
- </desc>
- </func>
- <func>
- <name>get_id(NameComponent) -> Return</name>
- <fsummary>Get the id field of a name component</fsummary>
- <type>
- <v>Return = string()</v>
- </type>
- <desc>
- <p>This function returns the id string of a name component.</p>
- </desc>
- </func>
- <func>
- <name>set_id(NameComponent, Id) -> Return</name>
- <fsummary>Set the id field of a name component</fsummary>
- <type>
- <v>Id = string()</v>
- <v>Return = NameComponent</v>
- </type>
- <desc>
- <p>This function sets the id string of a name component and returns the component.</p>
- </desc>
- </func>
- <func>
- <name>get_kind(NameComponent) -> Return</name>
- <fsummary>Get the kind field of a name component</fsummary>
- <type>
- <v>Return = string()</v>
- </type>
- <desc>
- <p>This function returns the id string of a name component.</p>
- </desc>
- </func>
- <func>
- <name>set_kind(NameComponent, Kind) -> Return</name>
- <fsummary>Set the kind field of a name component</fsummary>
- <type>
- <v>Kind = string()</v>
- <v>Return = NameComponent</v>
- </type>
- <desc>
- <p>This function sets the kind string of a name component and returns the component.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/orber/doc/src/menuframe.gif b/lib/orber/doc/src/menuframe.gif
deleted file mode 100644
index 57a437e6b0..0000000000
--- a/lib/orber/doc/src/menuframe.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/name.gif b/lib/orber/doc/src/name.gif
deleted file mode 100644
index d2df460092..0000000000
--- a/lib/orber/doc/src/name.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/notes.gif b/lib/orber/doc/src/notes.gif
deleted file mode 100644
index e000cca26a..0000000000
--- a/lib/orber/doc/src/notes.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/notes.xml b/lib/orber/doc/src/notes.xml
deleted file mode 100644
index 5a82270b28..0000000000
--- a/lib/orber/doc/src/notes.xml
+++ /dev/null
@@ -1,839 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Orber Release Notes</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>99-02-12</date>
- <rev>A</rev>
- <file>notes.xml</file>
- </header>
-
- <section><title>Orber 3.8.3</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Fix some dialyzer warnings</p>
- <p>
- Own Id: OTP-14006</p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>Orber 3.8.2</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>
- Internal changes</p>
- <p>
- Own Id: OTP-13551</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Orber 3.8.1</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> Suppress Dialyzer warnings. </p>
- <p>
- Own Id: OTP-12862</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Orber 3.8</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> Remove the usage of erlang:now() from all Corba
- applications and use the new rand module instead of
- random. </p>
- <p>
- Own Id: OTP-12687</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Orber 3.7.1</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p> Fixed problem with IPv6 addresses in Service Context
- when orber is default configured for IPv4. </p>
- <p>
- Own Id: OTP-12193</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Orber 3.7</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p> The following functions have been corrected so they
- work properly with IPv6 addresses. </p> <list>
- <item><c>corba:resolve_initial_references_remote/2/3</c></item>
- <item><c>corba:list_initial_references_remote/1/2</c></item>
- <item><c>corba:string_to_object/1/2</c></item> </list>
- <p>
- Own Id: OTP-12016</p>
- </item>
- <item>
- <p> A couple of macros were malformed, missing commas:
- PROFILEBODY_1_1_TYPEDEF and PROFILEBODY_1_2_TYPEDEF.
- Thanks to Vlad Dumitrescu. </p>
- <p>
- Own Id: OTP-12062</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> It is now possible to add listen interfaces for IPv6
- when orber is default configured for IPv4 and the other
- way around. For more information, consult the User's
- Guide and the orber module Reference Manual. </p>
- <p>
- Own Id: OTP-12007</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Orber 3.6.27</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Some local implementations of removing the last element
- from a list are replaced by <c>lists:droplast/1</c>. Note
- that this requires at least <c>stdlib-2.0</c>, which is
- the stdlib version delivered in OTP 17.0. (Thanks to Hans
- Svensson)</p>
- <p>
- Own Id: OTP-11678</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Orber 3.6.26.1</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> Postscript files no longer needed for the generation
- of PDF files have been removed. </p>
- <p>
- Own Id: OTP-11016</p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Orber 3.6.26</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Fix bug in corbaloc/corbaname over ssl.</p>
- <p>
- Own Id: OTP-10675</p>
- </item>
- </list>
- </section>
-
- </section>
-
- <section><title>Orber 3.6.25</title>
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p> Some examples overflowing the width of PDF pages have
- been corrected. </p>
- <p>
- Own Id: OTP-10665</p>
- </item>
- </list>
- </section>
-
- <section><title>Known Bugs and Problems</title>
- <list>
- <item>
- <p>
- Own Id: OTP-10675 Aux Id: seq12154
- </p>
- </item>
- </list>
- </section>
-</section>
-
-<section><title>Orber 3.6.24</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Fix number of arguments in orber dbg printout</p>
- <p>
- Own Id: OTP-9887</p>
- </item>
- <item>
- <p> The descriptions of <c>ssl_server_options</c> and
- <c>ssl_client_options</c> are corrected.<br/> Seq. Id:
- seq12018 </p>
- <p>
- Own Id: OTP-9966 Aux Id: OTP-9773 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Orber 3.6.23</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p> Remove usage of ssl:seed/1 in orber test cases. </p>
- <p>
- Own Id: OTP-9728</p>
- </item>
- </list>
- </section>
-
-
- <section><title>Improvements and New Features</title>
- <list>
- <item>
- <p>Erlang/OTP can now be built using parallel make if you
- limit the number of jobs, for instance using '<c>make
- -j6</c>' or '<c>make -j10</c>'. '<c>make -j</c>' does not
- work at the moment because of some missing
- dependencies.</p>
- <p>
- Own Id: OTP-9451</p>
- </item>
- <item>
- <p> The SSL option handling has been changed. There are
- now two new orber options <c>ssl_server_options</c> and
- <c>ssl_client_options</c> which takes a list of options
- to the socket. </p> <p> The old options are now
- deprecated and removed from the documentation but they
- can still be used for backward compatibility as long as
- the two new options not are used. </p> <p> If
- <c>ssl_server_options</c> and <c>ssl_client_options</c>
- contain an TCP option that <c>orber</c> needs to set to a
- specific value it will be skipped and a warning will be
- written to the error_log. </p>
- <p>
- Own Id: OTP-9773 Aux Id: seq11932 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section><title>Orber 3.6.22</title>
-
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p> XML files have been corrected. </p>
- <p>
- Own Id: OTP-9550 Aux Id: OTP-9541 </p>
- </item>
- </list>
- </section>
-
-</section>
-
-<section>
- <title>Orber 3.6.21</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Eliminated Dialyzer warnings.</p>
- <p>
- Own Id: OTP-9326 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.20</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Eliminated Dialyzer warnings when using exit or throw.</p>
- <p>
- Own Id: OTP-9050 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.19</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Partial support for recursive structs and unions.
- Only available for the erl_corba backend and requires
- that Light IFR is used. I.e. the IC option {light_ifr, true}
- and that Orber is configured in such a way that Light IFR
- is activated. Recursive TypeCode is currently not supported.</p>
- <p>
- Own Id: OTP-8868 Aux Id: seq11633</p>
- </item>
- </list>
- </section>
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The SSL option {ssl_imp, old} was not used if ssl_generation was
- set to 2. Only R14B was affected by this.</p>
- <p>Own Id: OTP-8994 Aux Id: seq11747</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.18</title>
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>A corbaloc http string could return an EXIT message, instead
- of a system exception, if the HTTP server closed the socket
- without returning a complete message. I.e. header and a body
- containing a stringified IOR.</p>
- <p>Own Id: OTP-8900 Aux Id: seq11704</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.17</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Eliminated warnings for auto-imported BIF clashes.</p>
- <p>
- Own Id: OTP-8840</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.16</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Test suites published.</p>
- <p>
- Own Id: OTP-8543O Aux Id:</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>Added missing trailing bracket to define in hrl-file.</p>
- <p>Own Id: OTP-8489 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.15</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- Added the configuration parameters iiop_out_ports_attempts and
- iiop_out_ports_random.</p>
- <p>
- Own Id: OTP-8448 Aux Id: seq11498</p>
- </item>
- <item>
- <p>
- Removed obsolete SSL dependency.</p>
- <p>
- Own Id: OTP-8374 Aux Id:</p>
- </item>
- <item>
- <p>
- Removed the usage of the codeinclude tag in the documentation.</p>
- <p>
- Own Id: OTP-8409 Aux Id:</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>Removed superfluous VT in the documentation.</p>
- <p>Own Id: OTP-8353 Aux Id:</p>
- </item>
- <item>
- <p>Removed superfluous backslash in the documentation.</p>
- <p>Own Id: OTP-8354 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.14</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>
- The documentation is now built with open source tools (xsltproc and fop)
- that exists on most platforms. One visible change is that the frames are removed.</p>
- <p>
- Own Id: OTP-8201 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.13</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Obsolete guards, e.g. record vs is_record, has been changed
- to avoid compiler warnings.</p>
- <p>Own Id: OTP-7987</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.12</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Only the source instance of InitialReference.java is now
- included. Users are adviced to use the Interoperable
- Naming Service (INS) instead. INS is a part of the OMG
- standard specification.</p>
- <p>*** POTENTIAL INCOMPATIBILITY ***</p>
- <p>Own Id: OTP-7906 Aux Id: seq11243</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.11</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Updated file headers.</p>
- <p>Own Id: OTP-7837</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.10</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Documentation source included in open source releases.</p>
- <p>Own Id: OTP-7595</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.9</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Updated file headers.</p>
- <p>Own Id: OTP-7011</p>
- </item>
- <item>
- <p>Now compliant with the new behavior of stdlib.</p>
- <p>Own Id: OTP-7030 Aux Id: seq10827</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.8</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>When a local port range has been defined (i.e. iiop_out_ports),
- Orber set the socket option reuseaddr to true and after one
- timed out connection attempt no other port in the given range
- is used for that particular connect attempt.</p>
- <p>Own Id: OTP-6844 Aux Id: </p>
- </item>
- <item>
- <p>Possible to override global SSL parameters when using
- local interfaces.</p>
- <p>Own Id: OTP-6869 Aux Id: seq10742</p>
- </item>
- </list>
- </section>
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The parameter ssl_client_ciphers was used on the server side as well
- instead of ssl_server_ciphers.</p>
- <p>Own Id: OTP-6868 Aux Id:</p>
- </item>
- <item>
- <p>The configuration parameter iiop_max_in_requests was ignored, until
- the first incoming request arrived, if iiop_packet_size was set.</p>
- <p>Own Id: OTP-6912 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.7</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>The documentation source has been converted from SGML to XML.</p>
- <p>Own Id: OTP-6754 Aux Id: </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.6</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>It is now possible to configure incoming connections which
- overrides some global configuration parameters. See
- orber:add_listen_interface/2/3.</p>
- <p>Own Id: OTP-6696 Aux Id: </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.5</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Removed some unused code.</p>
- <p>Own Id: OTP-6527 Aux Id: </p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.4</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Orber can now be configured so that different NAT parameters
- can be specified for different interfaces.</p>
- <p>Own Id: OTP-6165 Aux Id: </p>
- </item>
- <item>
- <p>It is now possible to set the keepalive option for incoming
- and outgoing IIOP connections. For more information, see the
- Configuration chapter in the User's Guide.</p>
- <p>Own Id: OTP-6370 Aux Id: seq10532</p>
- </item>
- <item>
- <p>The new function orber:close_connection/1/2 allows a client
- to close connections to an object residing on a remote ORB.</p>
- <p>Own Id: OTP-6371 Aux Id: seq10532</p>
- </item>
- <item>
- <p>Orber now use the SSL two-phase accept strategy to avoid
- that new incoming connections via SSL are not blocked
- by a previous connect attempt that never initiated the
- SSL handshake. Note, the configuration parameter
- iiop_ssl_accept_timeout should be set (default infinity).
- For more information, see the Configuration chapter in the
- User's Guide. If Orber is started in secure mode, the
- installed SSL version must support ssl:ssl_accept/1/2 and
- ssl:transport_accept/1/2.</p>
- <p>Own Id: OTP-6372 Aux Id: seq10105</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The operation orber_ifr:contents/2 could only handle dk_All.</p>
- <p>Own Id: OTP-6385 Aux Id:</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.3</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>When installing Orber it is now possible to set the priority
- for Orber internal Mnesia tables. For more information, see the
- Reference Manual regarding orber:install/2.</p>
- <p>Own Id: OTP-5907 Aux Id: seq10156</p>
- </item>
- <item>
- <p>The operation corba_object:is_a/2/3 now only connect to a remote
- ORB if necessary (i.e. the target object inherits from objects
- associated with the given IFR id).</p>
- <p>Own Id: OTP-5908</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The operation corba_object:is_remote/1 always returned
- true, which was introduced in orber-3.2.10.</p>
- <p>Own Id: OTP-5909</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.2</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Native interceptors may now export new_in_connection and
- new_out_connection operations with arity 5. If this is the
- case, information about the local interface and port is
- passed to the interceptor. Orber's built in interceptors
- have been changed to include this information as well.</p>
- <p>Own Id: OTP-5671</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>In some cases, e.g. incorrect GIOP headers or a CancelRequest
- containing a non-existing RequestId, the incoming connection
- would be terminated.</p>
- <p>Own Id: OTP-5672 Aux Id: seq10037</p>
- </item>
- <item>
- <p>If combining the 'Use Current Interface in IOR' and
- 'Use IPv6' flags, exported IOR:s contained an incorrect
- host address.</p>
- <p>Own Id: OTP-5673</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6.1</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>Reduced overhead when using outgoing ACL with a local interface
- defined.</p>
- <p>Own Id: OTP-5659</p>
- </item>
- <item>
- <p>Added guards to ensure that, when so required, a list
- of IOP_ServiceContext's is passed instead of, for example,
- just the context record.</p>
- <p>Own Id: OTP-5660</p>
- </item>
- </list>
- </section>
-
- <section>
- <title>Fixed Bugs and Malfunctions</title>
- <list type="bulleted">
- <item>
- <p>The documentation referred to two different context definitions,
- the incorrect ServiceContext and the correct IOP_ServiceContext.
- The hrl file PATH/include/corba.hrl also contained the incorrect
- record definition. This has now been updated so that only
- IOP_ServiceContext is used and referred to.</p>
- <p>Own Id: OTP-5658</p>
- </item>
- </list>
- </section>
- </section>
-
- <section>
- <title>Orber 3.6</title>
-
- <section>
- <title>Improvements and New Features</title>
- <list type="bulleted">
- <item>
- <p>It is now possible to define a Access Control List (ACL),
- which limits the host and ports Orber may connect to or
- accept connections from.</p>
- <p>Own Id: OTP-5567</p>
- </item>
- <item>
- <p>It is now possible to add, and remove, listen interfaces.
- For more information, consult the User's Guide and the
- orber module Reference Manual.</p>
- <p>Own Id: OTP-5568</p>
- </item>
- <item>
- <p>It is now possible to activate and deactivate Audit/Trail
- logging. One of the three built in interceptors will be used
- depending on the requested verbosity.</p>
- <p>Own Id: OTP-5569</p>
- </item>
- <item>
- <p>It is now possible to configure Orber to add the interface,
- to exported local IOR:s, a Request came via.</p>
- <p>Own Id: OTP-5570</p>
- </item>
- <item>
- <p>It is now possible to instruct Orber which local interface an outgoing Request
- shall be sent via. To accomplish this the Orber generic context must be
- added added to each invocation.</p>
- <p>Own Id: OTP-5571</p>
- </item>
- <item>
- <p>It is now possible to define a default local interface,
- which Orber will use when connecting to another ORB.</p>
- <p>Own Id: OTP-5583</p>
- </item>
- </list>
- </section>
- </section>
-</chapter>
-
diff --git a/lib/orber/doc/src/orber.gif b/lib/orber/doc/src/orber.gif
deleted file mode 100644
index d78cf7d8ed..0000000000
--- a/lib/orber/doc/src/orber.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/orber.xml b/lib/orber/doc/src/orber.xml
deleted file mode 100644
index d8c6936515..0000000000
--- a/lib/orber/doc/src/orber.xml
+++ /dev/null
@@ -1,653 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>orber</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>1997-06-10</date>
- <rev>A</rev>
- </header>
- <module>orber</module>
- <modulesummary>The main module of the Orber application</modulesummary>
- <description>
- <p>This module contains the functions for starting and stopping the
- application. It also has some utility functions to get some of
- the configuration information from running application.</p>
- </description>
- <funcs>
- <func>
- <name>start() -> ok</name>
- <name>start(Type) -> ok</name>
- <fsummary>Start the Orber application</fsummary>
- <type>
- <v>Type = temporary | permanent</v>
- </type>
- <desc>
- <p>Starts the Orber application (it also starts mnesia if it is not running).
- Which <c>Type</c> parameter is supplied determines the behavior. If not
- supplied Orber is started as <c>temporary</c>.
- See the Reference Manual <em>application(3)</em> for further information. </p>
- </desc>
- </func>
- <func>
- <name>jump_start(Attributes) -> ok | {'EXIT', Reason}</name>
- <fsummary>Start the Orber application during tests</fsummary>
- <type>
- <v>Attributes = Port | Options</v>
- <v>Port = integer()</v>
- <v>Options = [{Key, Value}]</v>
- <v>Key = any key listed in the configuration chapter</v>
- <v>Value = allowed value associated with the given key</v>
- </type>
- <desc>
- <p>Installs and starts the Orber and the Mnesia applications with the configuration
- parameters <c>domain</c> and <c>iiop_port</c> set to <c>"IP-number:Port"</c>
- and the supplied Port respectively. Theses settings are in most cases
- sufficient to ensure that no clash with any other Orber instance occur.
- If this operation fails, check if the listen port (iiop_port) is already
- in use. This function <em>MAY ONLY</em> be used during development and
- tests; how Orber is configured when using this operation may change
- at any time without warning.</p>
- </desc>
- </func>
- <func>
- <name>stop() -> ok</name>
- <fsummary>Stop the Orber application</fsummary>
- <desc>
- <p>Stops the Orber application.</p>
- </desc>
- </func>
- <func>
- <name>info() -> ok</name>
- <name>info(IoType) -> ok | {'EXIT', Reason} | string()</name>
- <fsummary>Generate Info Report, which contain Orber's configuration settings</fsummary>
- <type>
- <v>IoType = info_msg | string | io | {io, IoDevice}</v>
- </type>
- <desc>
- <p>Generates an Info Report, which contain Orber's configuration settings.
- If no <c>IoType</c> is supplied, <c>info_msg</c> is used (see the
- error_logger documentation). When the atom string is supplied this
- function will return a flat list. For <c>io</c> and <c>{io, IoDevice}</c>,
- <c>io:format/1</c> and <c>io:format/3</c> is used respectively.</p>
- </desc>
- </func>
- <func>
- <name>exception_info(Exception) -> {ok, string()} | {error, Reason}</name>
- <fsummary>Return a printable string, which describes the supplied exception</fsummary>
- <desc>
- <p>Returns a printable string, which describes the supplied exception
- in greater detail. Note, this function is mainly intended for
- system exceptions.</p>
- </desc>
- </func>
- <func>
- <name>is_system_exception(Exception) -> true | false</name>
- <fsummary>Return true if the supplied exception is a system defined exception otherwise false</fsummary>
- <desc>
- <p>Returns true if the supplied exception is a system defined
- exception, otherwise false.</p>
- </desc>
- </func>
- <func>
- <name>get_tables() -> [Tables]</name>
- <fsummary>Get the Mnesia tables Orber uses.</fsummary>
- <desc>
- <p>Returns a list of the Orber specific Mnesia tables. This list is
- required to restore Mnesia if it has been partitioned.</p>
- </desc>
- </func>
- <func>
- <name>get_ORBInitRef() -> string() | undefined</name>
- <fsummary>Get the initial reference address.</fsummary>
- <desc>
- <p>This function returns undefined if we will resolve references locally,
- otherwise a string describing which host we will contact if the Key given
- to <c>corba:resolve_initial_references/1</c> matches the Key set
- in this configuration variable. For more information
- see the user's guide.</p>
- </desc>
- </func>
- <func>
- <name>get_ORBDefaultInitRef() -> string() | undefined</name>
- <fsummary>Get the initial reference address.</fsummary>
- <desc>
- <p>This function returns undefined if we will resolve references locally,
- otherwise a string describing which host, or hosts, from which we
- will try to resolve the Key given to
- <c>corba:resolve_initial_references/1</c>. For more information
- see the user's guide.</p>
- </desc>
- </func>
- <func>
- <name>domain() -> string()</name>
- <fsummary>Display the Orber domain name</fsummary>
- <desc>
- <p>This function returns the domain name of the current Orber domain
- as a string.</p>
- </desc>
- </func>
- <func>
- <name>iiop_port() -> int()</name>
- <fsummary>Display the IIOP port number</fsummary>
- <desc>
- <p>This function returns the port-number, which is used by the IIOP
- protocol. It can be configured by setting the application variable
- <em>iiop_port</em>, if it is not set it will have the default number
- 4001.</p>
- </desc>
- </func>
- <func>
- <name>iiop_out_ports() -> 0 | {Min, Max}</name>
- <fsummary>Display the ports Orber may use when connecting to another ORB</fsummary>
- <desc>
- <p>The return value of this operation is what the configuration
- parameter <seealso marker="ch_install#config">iiop_out_ports</seealso>
- has been set to.</p>
- </desc>
- </func>
-
- <func>
- <name>iiop_out_ports_random() -> true | false</name>
- <fsummary>Determine if Orber should select local ports randomly</fsummary>
- <desc>
- <p>Return the value of the configuration parameter
- <seealso marker="ch_install#config">iiop_out_ports_random</seealso>.</p>
- </desc>
- </func>
-
- <func>
- <name>iiop_out_ports_attempts() -> int()</name>
- <fsummary>Display if Orber should accept more than one timeout connecting to another ORB</fsummary>
- <desc>
- <p>Return the value of the configuration parameter
- <seealso marker="ch_install#config">iiop_out_ports_attempts</seealso>.</p>
- </desc>
- </func>
-
-
- <func>
- <name>iiop_ssl_port() -> int()</name>
- <fsummary>Display the IIOP port number used for secure connections</fsummary>
- <desc>
- <p>This function returns the port-number, which is used by the secure IIOP
- protocol. It can be configured by setting the application variable
- <em>iiop_ssl_port</em>, if it is not set it will have the default number
- 4002 if Orber is to configured to run in secure mode. Otherwise it returns -1.</p>
- </desc>
- </func>
- <func>
- <name>iiop_timeout() -> int() (milliseconds)</name>
- <fsummary>Display the IIOP timeout value</fsummary>
- <desc>
- <p>This function returns the timeout value after which outgoing IIOP requests terminate.
- It can be configured by setting the application variable
- <em>iiop_timeout TimeVal (seconds)</em>, if it is not set it will have the default value
- <em>infinity</em>. If a request times out a system exception, e.g.
- <em>TIMEOUT</em>, is raised.</p>
- <p>Note: the iiop_timeout configuration parameter (TimeVal) may only range between 0 and 1000000 seconds.
- Otherwise, the default value is used.</p>
- <p>Note: Earlier IC versions required that the compile option <c>{timeout,"module::interface"}</c>,
- was used, which allow the user to add an extra timeout parameter, e.g.,
- <c>module_interface:function(ObjRef, Timeout, ... Arguments ...)</c> or
- <c>module_interface:function(ObjRef, [{timeout, Timeout}], ... Arguments ...)</c>,
- instead of <c>module_interface:function(ObjRef, ... Arguments ...)</c>.
- This is no longer the case and if the extra Timeout is used,
- argument will override the configuration parameter <c>iiop_timeout</c>.
- It is, however, not possible
- to use <c>infinity</c> to override the Timeout parameter. The Timeout
- option is also valid for objects which resides within the same Orber domain.</p>
- </desc>
- </func>
- <func>
- <name>iiop_connection_timeout() -> int() (milliseconds)</name>
- <fsummary>Display the IIOP connection timeout value</fsummary>
- <desc>
- <p>This function returns the timeout value after which outgoing IIOP connections terminate.
- It can be configured by setting the application variable
- <em>iiop_connection_timeout TimeVal (seconds)</em>, if it is not set it will have the default value
- <em>infinity</em>. The connection will not be terminated if there are
- pending requests.</p>
- <p>Note: the iiop_connection_timeout configuration parameter (TimeVal) may only range between 0 and 1000000 seconds.
- Otherwise, the default value is used.</p>
- </desc>
- </func>
- <func>
- <name>iiop_connections() -> Result</name>
- <name>iiop_connections(Direction) -> Result</name>
- <fsummary>List all existing connections to/from other ORB's</fsummary>
- <type>
- <v>Direction = in | out | inout</v>
- <v>Result = [{Host, Port}] | [{Host, Port, Interface}] | {'EXIT',Reason}</v>
- <v>Host = string()</v>
- <v>Port = integer()</v>
- <v>Interface = string()</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>The list returned by this operation contain tuples of remote hosts/ports
- Orber is currently connected to. If no Direction is not supplied, both
- incoming and outgoing connections are included.</p>
- <p>If a specific local interface has been defined for the connection,
- this will be added to the returned tuple.</p>
- </desc>
- </func>
- <func>
- <name>iiop_connections_pending() -> Result</name>
- <fsummary>List all connections to another ORB currently being set up</fsummary>
- <type>
- <v>Result = [{Host, Port}] | [{Host, Port, Interface}] | {'EXIT',Reason}</v>
- <v>Host = string()</v>
- <v>Port = integer()</v>
- <v>Interface = string()</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>In some cases a connection attempt (i.e. trying to communicate with
- another ORB) may block due to a number of reasons. This operation
- allows the user to check if this is the case. The returned list
- contain tuples of remote hosts/ports. Normally, the list is empty.</p>
- <p>If a specific local interface has been defined for the connection,
- this will be added to the returned tuple.</p>
- </desc>
- </func>
- <func>
- <name>iiop_in_connection_timeout() -> int() (milliseconds)</name>
- <fsummary>Display the IIOP connection timeout value for incoming connections</fsummary>
- <desc>
- <p>This function returns the timeout value after which incoming IIOP
- connections terminate. It can be configured by setting the application
- variable <em>iiop_in_connection_timeout TimeVal (seconds)</em>, if it is
- not set it will have the default value <em>infinity</em>. The connection
- will not be terminated if there are pending requests.</p>
- <p>Note: the iiop_in_connection_timeout configuration parameter (TimeVal) may
- only range between 0 and 1000000 seconds. Otherwise, the default value is
- used.</p>
- </desc>
- </func>
- <func>
- <name>iiop_acl() -> Result</name>
- <fsummary>Return the ACL configuration</fsummary>
- <type>
- <v>Result = [{Direction, Filter}] | [{Direction, Filter, [Interface]}]</v>
- <v>Direction = tcp_in | ssl_in | tcp_out | ssl_out</v>
- <v>Filter = string()</v>
- <v>Interface = string()</v>
- </type>
- <desc>
- <p>Returns the ACL configuration. The <c>Filter</c> uses a extended format of
- Classless Inter Domain Routing (CIDR). For example, <c>"123.123.123.10"</c> limits
- the connection to that particular host, while <c>"123.123.123.10/17"</c> allows
- connections to or from any host equal to the 17 most significant bits. Orber
- also allow the user to specify a certain port or port range, for example,
- <c>"123.123.123.10/17#4001"</c> and <c>"123.123.123.10/17#4001/5001"</c>
- respectively. IPv4 or none compressed IPv6 strings are accepted. <br></br>
-
- The list of <c>Interfaces</c>, IPv4 or IPv6 strings, are currently only used
- for outgoing connections and may only contain <em>one</em> address. If set and
- access is granted, Orber will use that local interface when connecting to the
- other ORB. The module <seealso marker="orber_acl">orber_acl</seealso>
- provides operations for evaluating the access control for filters and addresses.</p>
- </desc>
- </func>
- <func>
- <name>activate_audit_trail() -> Result</name>
- <name>activate_audit_trail(Verbosity) -> Result</name>
- <fsummary>Activate IIOP audit/trail</fsummary>
- <type>
- <v>Verbosity = stealth | normal | verbose</v>
- <v>Result = ok | {error, Reason}</v>
- <v>Reason = string()</v>
- </type>
- <desc>
- <p>Activates audit/trail for all existing incoming and outgoing IIOP
- connections. The <c>Verbosity</c> parameter, <c>stealth</c>,
- <c>normal</c> or <c>verbose</c>, determines which of the built in
- interceptors is used (<c>orber_iiop_tracer_stealth</c>,
- <c>orber_iiop_tracer_silent</c> or <c>orber_iiop_tracer</c> respectively).
- If no verbosity level is supplied, then the <c>normal</c> will be used.</p>
- <p>In case Orber is configured to use other interceptors, the audit/trail
- interceptors will simply be added to that list.</p>
- </desc>
- </func>
- <func>
- <name>deactivate_audit_trail() -> Result</name>
- <fsummary>Deactivate IIOP audit/trail</fsummary>
- <type>
- <v>Result = ok | {error, Reason}</v>
- <v>Reason = string()</v>
- </type>
- <desc>
- <p>Deactivates audit/trail for all existing incoming and outgoing IIOP
- connections. In case Orber is configured to use other interceptors,
- those will still be used.</p>
- </desc>
- </func>
- <func>
- <name>add_listen_interface(IP, Type) -> Result</name>
- <name>add_listen_interface(IP, Type, Port) -> Result</name>
- <name>add_listen_interface(IP, Type, ConfigurationParameters) -> Result</name>
- <fsummary>Add a new listen process for incoming connection</fsummary>
- <type>
- <v>IP = string</v>
- <v>Type = normal | ssl</v>
- <v>Port = integer() > 0</v>
- <v>ConfigurationParameters = [{Key, Value}]</v>
- <v>Key = flags | ip_family | iiop_in_connection_timeout | iiop_max_fragments | iiop_max_in_requests | interceptors | iiop_port | iiop_ssl_port | ssl_server_options</v>
- <v>Value = as described in the User's Guide or below</v>
- <v>Result = {ok, Ref} | {error, Reason} | {'EXCEPTION', #'BAD_PARAM'{}}</v>
- <v>Ref = #Ref</v>
- <v>Reason = string()</v>
- </type>
- <desc>
- <p>Create a new process that handle requests for creating a new incoming
- IIOP connection via the given interface and port. If the latter is
- excluded, Orber will use the value of the <c>iiop_port</c> or
- <c>iiop_ssl_port</c> configuration parameters.
- The <c>Type</c> parameter determines if it is
- supposed to be IIOP or IIOP via SSL. If successful, the returned
- <c>#Ref</c> shall be passed to <c>orber:remove_listen_interface/1</c>
- when the connection shall be terminated.</p>
- <p>It is also possible to supply configuration parameters that override
- the global configuration. The <em>iiop_in_connection_timeout</em>,
- <em>iiop_max_fragments</em>, <em>iiop_max_in_requests</em> and
- <em>interceptors</em> parameters simply overrides the global
- counterparts (See the
- <seealso marker="ch_install#config">Configuration</seealso> chapter
- in the User's Guide).
- But for the following parameters there are a few restrictions:</p>
- <list type="bulleted">
- <item><em>flags</em> - currently it is only possible to override the global
- setting for the <c>Use Current Interface in IOR</c> and
- <c>Exclude CodeSet Component</c> flags.</item>
- <item><em>ip_family</em> - can be set to <c>inet</c> or <c>inet6</c> and is
- used to get a listen interface that uses another IP version than the default
- set with flags at startup.</item>
- <item><em>iiop_port</em> - requires that <c>Use Current Interface in IOR</c>
- is activated and the supplied <c>Type</c> is <c>normal</c>. If so,
- exported IOR:s will contain the IIOP port defined by this configuration
- parameter. Otherwise, the global setting will be used.</item>
- <item><em>iiop_ssl_port</em> - almost equivalent to <c>iiop_port</c>.
- The difference is that <c>Type</c> shall be <c>ssl</c> and that
- exported IOR:s will contain the IIOP via SSL port defined by this configuration
- parameter.</item>
- </list>
- <p>If it is not possible to add a listener based on the supplied interface
- and port, the error message is one of the ones described in <c>inet</c>
- and/or <c>ssl</c> documentation.</p>
- </desc>
- </func>
- <func>
- <name>remove_listen_interface(Ref) -> ok</name>
- <fsummary>Terminate listen process for incoming connection</fsummary>
- <type>
- <v>Ref = #Ref</v>
- </type>
- <desc>
- <p>Terminates the listen process, associated with the supplied <c>#Ref</c>,
- for incoming a connection. The Ref parameter is the return value from
- the <c>orber:add_listen_interface/2/3</c> operation. When terminating
- the connection, all associated requests will not deliver a reply to
- the clients.</p>
- </desc>
- </func>
- <func>
- <name>close_connection(Connection) -> Result</name>
- <name>close_connection(Connection, Interface) -> Result</name>
- <fsummary>Terminate outgoing connection(s)</fsummary>
- <type>
- <v>Connection = Object | [{Host, Port}]</v>
- <v>Object = #objref (external)</v>
- <v>Host = string()</v>
- <v>Port = string()</v>
- <v>Interface = string()</v>
- <v>Result = ok | {'EXCEPTION', #'BAD_PARAM'{}}</v>
- </type>
- <desc>
- <p>Will try to close all outgoing connections to the host/port combinations
- found in the supplied object reference or the given list of hosts/ports.
- If a <c>#'IOP_ServiceContext'{}</c> containing a local interface has been
- used when communicating with the remote object
- (see also <seealso marker="Module_Interface">Module_Interface</seealso>),
- that interface shall be passed as the second argument. Otherwise, connections
- via the default local interface, will be terminated.</p>
- <p></p>
- <note>
- <p>Since several clients maybe communicates via the same connection,
- they will be affected when invoking this operation. Other clients may
- re-create the connection by invoking an operation on the target object.</p>
- </note>
- </desc>
- </func>
- <func>
- <name>secure() -> no | ssl</name>
- <fsummary>Display the security mode Orber is running in</fsummary>
- <desc>
- <p>This function returns the security mode Orber is running in, which is either no if it is an
- insecure domain or the type of security mechanism used. For the moment the only security
- mechanism is ssl. This is configured by setting the application variable
- <em>secure</em>.</p>
- </desc>
- </func>
- <func>
- <name>ssl_server_options() -> list()</name>
- <fsummary>Display the SSL server options</fsummary>
- <desc>
- <p>This function returns the list of SSL options set for the Orber domain as server.
- This is configured by setting the application variable
- <em>ssl_server_options</em>.</p>
- </desc>
- </func>
- <func>
- <name>ssl_client_options() -> list()</name>
- <fsummary>Display the SSL client options</fsummary>
- <desc>
- <p>This function returns the list of SSL options used in outgoing calls in the current process.
- The default value is configured by setting the application variable
- <em>ssl_client_options</em>.</p>
- </desc>
- </func>
- <func>
- <name>set_ssl_client_options(Options) -> ok</name>
- <fsummary>Set the SSL options for the client</fsummary>
- <type>
- <v>Options = list()</v>
- </type>
- <desc>
- <p>This function takes a list of SSL options as parameter and sets
- it for the current process.</p>
- </desc>
- </func>
- <func>
- <name>objectkeys_gc_time() -> int() (seconds)</name>
- <fsummary>Display the Object Keys GC time value</fsummary>
- <desc>
- <p>This function returns the timeout value after which after which terminated object keys,
- related to servers started with the configuration parameter <c>{persistent, true}</c>,
- will be removed.
- It can be configured by setting the application variable <em>objectkeys_gc_time TimeVal (seconds)</em>,
- if it is not set it will have the default value <em>infinity</em>. </p>
- <p>Objects terminating with reason <em>normal</em> or <em>shutdown</em> are removed automatically.</p>
- <p>Note: the objectkeys_gc_time configuration parameter (TimeVal) may only range between 0 and 1000000 seconds.
- Otherwise, the default value is used.</p>
- </desc>
- </func>
- <func>
- <name>orber_nodes() -> RetVal</name>
- <fsummary>Displays which nodes that this orber domain consist of.</fsummary>
- <type>
- <v>RetVal = [node()]</v>
- </type>
- <desc>
- <p>This function returns the list of node names that this orber
- domain consists of. </p>
- </desc>
- </func>
- <func>
- <name>install(NodeList) -> ok</name>
- <name>install(NodeList, Options) -> ok</name>
- <fsummary>Install the Orber application</fsummary>
- <type>
- <v>NodeList = [node()]</v>
- <v>Options = [Option]</v>
- <v>Option = {install_timeout, Timeout} | {ifr_storage_type, TableType} | {nameservice_storage_type, TableType} | {initialreferences_storage_type, TableType} | {load_order, Priority}</v>
- <v>Timeout = infinity | integer()</v>
- <v>TableType = disc_copies | ram_copies</v>
- <v>Priority = integer()</v>
- </type>
- <desc>
- <p>This function installs all the necessary mnesia tables and
- load default data in some of them. If one or more Orber tables
- already exists the installation fails. The function
- <em>uninstall</em> may be used, if it is safe, i.e., no other
- application is running Orber.</p>
- <p>Preconditions:</p>
- <list type="bulleted">
- <item>a mnesia schema must exist before the installation</item>
- <item>mnesia is running on the other nodes if the new installation
- shall be a multi node domain</item>
- </list>
- <p>Mnesia will be started by the function if it is not already running on
- the installation node and if it was started it will be stopped
- afterwards.</p>
- <p>The options that can be sent to the installation program is:</p>
- <list type="bulleted">
- <item><c>{install_timeout, Timeout}</c> - this timeout is how long we
- will wait for the tables to be created. The Timeout value can be
- <em>infinity</em> or an integer number in milliseconds.
- Default is infinity.</item>
- <item><c>{ifr_storage_type, TableType}</c> - this option sets the
- type of tables used for the interface repository.
- The TableType can be disc_copies or ram_copies. Default is
- disc_copies.</item>
- <item><c>{initialreferences_storage_type, TableType}</c> - this option
- sets the type of table used for storing initial references.
- The TableType can be disc_copies or ram_copies. Default is
- ram_copies.</item>
- <item><c>{nameservice_storage_type, TableType}</c> - the default
- behavior of Orber is to install the NameService as ram_copies.
- This option makes it possible to change this to disc_copies. But
- the user should be aware of that if a node is restarted, all
- local object references stored in the NameService is not valid.
- Hence, you cannot switch to disc_copies and expect exactly the same
- behavior as before.</item>
- <item><c>{load_order, Priority}</c> - per default the priority is set to 0.
- Using this option it will change the priority of in which order
- Mnesia will load Orber internal tables. For more information,
- consult the Mnesia documentation.</item>
- </list>
- </desc>
- </func>
- <func>
- <name>uninstall() -> ok</name>
- <fsummary>Uninstall the Orber application</fsummary>
- <desc>
- <p>This function stops the Orber application, terminates all server
- objects and removes all Orber related mnesia tables.</p>
- <p>Note: Since other applications may be running on the same node
- using mnesia <em>uninstall</em> will not stop the mnesia application.</p>
- </desc>
- </func>
- <func>
- <name>add_node(Node, Options) -> RetVal</name>
- <fsummary>Add a new node to a group of Orber nodes.</fsummary>
- <type>
- <v>Node = node()</v>
- <v>Options = IFRStorageType | [KeyValue] </v>
- <v>IFRStorageType = StorageType</v>
- <v>StorageType = disc_copies | ram_copies</v>
- <v>KeyValue = {ifr_storage_type, StorageType} | {initialreferences_storage_type, StorageType} | {nameservice_storage_type, StorageType} | {type, Type} </v>
- <v>Type = temporary | permanent</v>
- <v>RetVal = ok | exit()</v>
- </type>
- <desc>
- <p>This function add given node to a existing Orber node group and starts
- Orber on the new node. <c>orber:add_node</c> is called from a member in the Orber
- node group.</p>
- <p>Preconditions for new node:</p>
- <list type="bulleted">
- <item>Erlang started on the new node using the option <c>-mnesia extra_db_nodes</c>, e.g.,
- <c>erl -sname new_node_name -mnesia extra_db_nodes ConnectToNodes_List</c></item>
- <item>The new node's <c>domain</c> name is the same for the nodes we want to connect to.</item>
- <item>Mnesia is running on the new node (no new schema created).</item>
- <item>If the new node will use <c>disc_copies</c> the schema type must be changed using:
- <c>mnesia:change_table_copy_type(schema, node(), disc_copies).</c></item>
- </list>
- <p>Orber will be started by the function on the new node.</p>
- <p>Fails if:</p>
- <list type="bulleted">
- <item>Orber already installed on given node.</item>
- <item>Mnesia not started as described above on the new node.</item>
- <item>Impossible to copy data in Mnesia tables to the new node.</item>
- <item>Not able to start Orber on the new node, due to, for example, the
- <c>iiop_port</c> is already in use.</item>
- </list>
- <p>The function do not remove already copied tables after a failure.
- Use <c>orber:remove_node</c> to remove these tables.</p>
- </desc>
- </func>
- <func>
- <name>remove_node(Node) -> RetVal</name>
- <fsummary>Removes a node from a group of Orber nodes.</fsummary>
- <type>
- <v>Node = node()</v>
- <v>RetVal = ok | exit()</v>
- </type>
- <desc>
- <p>This function removes given node from a Orber node group. The Mnesia
- application is not stopped.</p>
- </desc>
- </func>
- <func>
- <name>configure(Key, Value) -> ok | {'EXIT', Reason}</name>
- <fsummary>Change Orber configuration.</fsummary>
- <type>
- <v>Key = orbDefaultInitRef | orbInitRef | giop_version | iiop_timeout | iiop_connection_timeout | iiop_setup_connection_timeout | iiop_in_connection_timeout | objectkeys_gc_time | orber_debug_level</v>
- <v>Value = allowed value associated with the given key</v>
- </type>
- <desc>
- <p>This function allows the user to configure Orber in, for example,
- an Erlang shell. It is possible to invoke <c>configure</c> at any time
- the keys specified above.</p>
- <p>Any other key must be set before installing and starting Orber.</p>
- <p>Trying to change the configuration in any other way is <em>NOT</em>
- allowed since it may affect the behavior of Orber.</p>
- <p>For more information regarding allowed values, see
- <seealso marker="ch_install#config">configuration settings</seealso>
- in the User's Guide.</p>
- <p></p>
- <note>
- <p>Configuring the IIOP timeout values will not affect already
- existing connections. If you want a guaranteed uniform behavior, you
- must set these parameters from the start.</p>
- </note>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/orber/doc/src/orber_acl.xml b/lib/orber/doc/src/orber_acl.xml
deleted file mode 100644
index 5feda83ef6..0000000000
--- a/lib/orber/doc/src/orber_acl.xml
+++ /dev/null
@@ -1,107 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2005</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>orber_acl</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2005-05-19</date>
- <rev>A</rev>
- </header>
- <module>orber_acl</module>
- <modulesummary>Orber ACL operations</modulesummary>
- <description>
- <p>This module contains functions intended for analyzing Access
- Control List (ACL) filters. The filters uses a extended format of
- Classless Inter Domain Routing (CIDR).
- For example, <c>"123.123.123.10"</c> limits
- the connection to that particular host, while <c>"123.123.123.10/17"</c> allows
- connections to or from any host equal to the 17 most significant bits. Orber
- also allow the user to specify a certain port or port range, for example,
- <c>"123.123.123.10/17#4001"</c> and <c>"123.123.123.10/17#4001/5001"</c>
- respectively. IPv4 or none compressed IPv6 strings are accepted.</p>
- </description>
- <funcs>
- <func>
- <name>match(IP, Direction) -> boolean()</name>
- <name>match(IP, Direction, GetInfo) -> Reply</name>
- <fsummary>Verify if the IP address versus the current configuration</fsummary>
- <type>
- <v>IP = tuple() | [integer()]</v>
- <v>Direction = tcp_in | ssl_in | tcp_out | ssl_out</v>
- <v>GetInfo = boolean()</v>
- <v>Reply = boolean() | {boolean(), [Interface], PortInfo}</v>
- <v>Interface = string()</v>
- <v>PortInfo = integer() | {integer(), integer()}</v>
- </type>
- <desc>
- <p>If <c>GetInfo</c> is not supplied or set to false, this operation returns
- a boolean which tells if the IPv4 or IPv6 address would pass the ACL
- filter, defined by the <c>iiop_acl</c> configuration parameter, or not.
- When <c>GetInfo</c> is set to true, a tuple which, besides the boolean
- that tells if access was granted, also include the defined
- interfaces and port(s). This operation requires that Orber is running and
- can be used on a live node to determine if Orber has been properly configured.</p>
- </desc>
- </func>
- <func>
- <name>verify(IP, Filter, Family) -> Reply</name>
- <fsummary>Verify if the IP address versus the Filter</fsummary>
- <type>
- <v>IP = string()</v>
- <v>Filter = string()</v>
- <v>Family = inet | inet6</v>
- <v>Reply = true | {false, From, To} | {error, string()}</v>
- <v>From = string()</v>
- <v>To = string()</v>
- </type>
- <desc>
- <p>This operation returns true if the IPv4 or IPv6 address would pass the
- supplied ACL. If that is not the case, a tuple containing the accepted range
- is returned. This operation should only be used for test purposes.</p>
- </desc>
- </func>
- <func>
- <name>range(Filter, Family) -> Reply</name>
- <fsummary>Get range of Filter</fsummary>
- <type>
- <v>Filter = string()</v>
- <v>Family = inet | inet6</v>
- <v>Reply = {ok, From, To} | {error, string()}</v>
- <v>From = string()</v>
- <v>To = string()</v>
- </type>
- <desc>
- <p>Returns the range of accepted IP addresses based on the supplied filter.
- This operation should only be used for test purposes.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/orber/doc/src/orber_diagnostics.xml b/lib/orber/doc/src/orber_diagnostics.xml
deleted file mode 100644
index 3aad304535..0000000000
--- a/lib/orber/doc/src/orber_diagnostics.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2003</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>orber_diagnostics</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>2003-04-17</date>
- <rev>A</rev>
- </header>
- <module>orber_diagnostics</module>
- <modulesummary>Diagnostics API for Orber</modulesummary>
- <description>
- <p>This module contains functions which makes it possible to run simple
- tests.</p>
- <p></p>
- <warning>
- <p>Functions exported by this module may only be used during
- test and development phase.</p>
- </warning>
- </description>
- <funcs>
- <func>
- <name>nameservice() -> Result</name>
- <name>nameservice(Flags) -> Result</name>
- <fsummary>Display all objects stored in the Name Service</fsummary>
- <type>
- <v>Flags = integer()</v>
- <v>Result = ok | {'EXCEPTION', E}</v>
- </type>
- <desc>
- <p>Displays all objects stored in the NameService. Existent checks are, per
- default, also performed on all local objects. This can also be activated
- for external objects by setting the flag <c>16#01</c>. The displayed
- information is the stringified Name described in
- <seealso marker="CosNaming_NamingContextExt">CosNaming_NamingContextExt</seealso>,
- non existent status (true | false | external | undefined) and the IFR-Id:</p>
- <code type="none">
-host/
-host/resources/
-host/resources/MyObj/ [false] IDL:MyMod/MyIntf:1.0 </code>
- </desc>
- </func>
- <func>
- <name>missing_modules() -> Count</name>
- <fsummary>Echo missing modules required by Orber</fsummary>
- <type>
- <v>Count = integer()</v>
- </type>
- <desc>
- <p>This operation list missing modules generated by IC and required by
- Orber. Requires that all API:s are registered in the IFR.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/orber/doc/src/orber_ifr.xml b/lib/orber/doc/src/orber_ifr.xml
deleted file mode 100644
index a667d7d9e4..0000000000
--- a/lib/orber/doc/src/orber_ifr.xml
+++ /dev/null
@@ -1,1035 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>orber_ifr</title>
- <prepared></prepared>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date>1997-10-13</date>
- <rev>A</rev>
- </header>
- <module>orber_ifr</module>
- <modulesummary>The Interface Repository stores representations of IDL information</modulesummary>
- <description>
- <p>This module contains functions for managing the Interface
- Repository (IFR). This documentation should be used in conjunction
- with the documentation in chapter 6 of <term id="CORBA"></term>2.3.
- Whenever the term IFR object is used in this manual page, it
- refers to a pseudo object used only for interaction with the IFR
- rather than a CORBA object.</p>
- </description>
-
- <section>
- <title>Initialization of the IFR</title>
- <p>The following functions are used to initialize the Interface
- Repository and to obtain the initial reference to the
- repository.</p>
- </section>
- <funcs>
- <func>
- <name>init(Nodes,Timeout) -> ok</name>
- <fsummary>Intialize the IFR</fsummary>
- <type>
- <v>Nodes = list()</v>
- <v>Timeout = integer() | infinity</v>
- </type>
- <desc>
- <p>This function should be called to initialize the IFR. It
- creates the necessary mnesia-tables. A mnesia schema should
- exist, and mnesia must be running.</p>
- </desc>
- </func>
- <func>
- <name>find_repository() -> #IFR_Repository_objref</name>
- <fsummary>Find the IFR object reference for the Repository</fsummary>
- <desc>
- <p>Find the IFR object reference for the Repository. This
- reference should be used when adding objects to the IFR, and
- when extracting information from the IFR.
- The first time this function is called, it will create the
- repository and all the primitive definitions.</p>
- </desc>
- </func>
- </funcs>
-
- <section>
- <title>General methods</title>
- <p>The following functions are the methods of the IFR. The first
- argument is always an #IFR_objref, i.e. the IFR (pseudo)object
- on which to apply this method. These functions are useful when
- the type of IFR object is not know, but they are somewhat slower
- than the specific functions listed below which only accept a
- particular type of IFR object as the first argument.</p>
- </section>
- <funcs>
- <func>
- <name>get_def_kind(Objref) -> Return</name>
- <fsummary>Return the definition kind of the IFR object</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Return = atom() (one of dk_none, dk_all, dk_Attribute, dk_Constant, dk_Exception, dk_Interface, dk_Module, dk_Operation, dk_Typedef, dk_Alias, dk_Struct, dk_Union, dk_Enum, dk_Primitive, dk_String, dk_Wstring, dk_Fixed, dk_Sequence, dk_Array, dk_Repository)</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind. Returns the definition
- kind of the IFR object.</p>
- </desc>
- </func>
- <func>
- <name>destroy(Objref) -> Return</name>
- <fsummary>Destroy, except IRObject, Contained and Container, target object and its contents</fsummary>
- <type>
- <v>Objref = #IFR_object</v>
- <v>Return = tuple()</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind except IRObject,
- Contained and Container. Destroys that object and its
- contents (if any). Returns whatever mnesia:transaction
- returns.</p>
- </desc>
- </func>
- <func>
- <name>get_id(Objref) -> Return</name>
- <fsummary>Return the target object's repository id</fsummary>
- <type>
- <v>Objref = #IFR_object</v>
- <v>Return = string()</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Contained. Returns the repository id of that object.</p>
- </desc>
- </func>
- <func>
- <name>set_id(Objref,Id) -> ok</name>
- <fsummary>Set the target object's repository id</fsummary>
- <type>
- <v>Objref = #IFR_object</v>
- <v>Id = string()</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Contained. Sets the repository id of that object.</p>
- </desc>
- </func>
- <func>
- <name>get_name(Objref) -> Return</name>
- <fsummary>Return the name of the target object</fsummary>
- <type>
- <v>Objref = #IFR_object</v>
- <v>Return = string()</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Contained. Returns the name of that object.</p>
- </desc>
- </func>
- <func>
- <name>set_name(Objref,Name) -> ok</name>
- <fsummary>Set given name to target object</fsummary>
- <type>
- <v>Objref = #IFR_object</v>
- <v>Name = string()</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Contained. Sets the name of that object.</p>
- </desc>
- </func>
- <func>
- <name>get_version(Objref) -> Return</name>
- <fsummary>Return the version of the target object</fsummary>
- <type>
- <v>Objref = #IFR_object</v>
- <v>Return = string()</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Contained. Returns the version of that object.</p>
- </desc>
- </func>
- <func>
- <name>set_version(Objref,Version) -> ok</name>
- <fsummary>Set given version of the target object</fsummary>
- <type>
- <v>Objref = #IFR_object</v>
- <v>Version = string()</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Contained. Sets the version of that object.</p>
- </desc>
- </func>
- <func>
- <name>get_defined_in(Objref) -> Return</name>
- <fsummary>Return the Container the target object is contained in</fsummary>
- <type>
- <v>Objref = #IFR_object</v>
- <v>Return = #IFR_Container_objref</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Contained. Returns the Container object that the object is
- defined in.</p>
- </desc>
- </func>
- <func>
- <name>get_absolute_name(Objref) -> Return</name>
- <fsummary>Return the absolute name of the target object</fsummary>
- <type>
- <v>Objref = #IFR_object</v>
- <v>Return = string()</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Contained. Returns the absolute (scoped) name of that
- object.</p>
- </desc>
- </func>
- <func>
- <name>get_containing_repository(Objref) -> Return</name>
- <fsummary>Get the most derived Contained object associated with the target object</fsummary>
- <type>
- <v>Objref = #IFR_object</v>
- <v>Return = #IFR_Repository_objref</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Contained. Returns the Repository that is eventually reached
- by recursively following the object's defined_in attribute.</p>
- </desc>
- </func>
- <func>
- <name>describe(Objref) -> Return</name>
- <fsummary>Return a tuple which describe the target object</fsummary>
- <type>
- <v>Objref = #IFR_object</v>
- <v>Return = tuple() (a contained_description record) | {exception, _}</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Contained. Returns a tuple describing the object.</p>
- </desc>
- </func>
- <func>
- <name>move(Objref,New_container,New_name,New_version) -> Return</name>
- <fsummary>Move the target object from its current location to given Container, name and version</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>New_container = #IFR_Container_objref</v>
- <v>New_name = string()</v>
- <v>New_version = string()</v>
- <v>Return = ok | {exception, _}</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Contained. New_container is an IFR object of any kind that
- inherits from Container. Removes Objref from its current
- Container, and adds it to New_container. The name attribute
- is changed to New_name and the version attribute is changed
- to New_version.</p>
- </desc>
- </func>
- <func>
- <name>lookup(Objref,Search_name) -> Return</name>
- <fsummary>Return the IFR object identified by the given name</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Search_name = string()</v>
- <v>Return = #IFR_object</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Container. Returns an IFR object identified by search_name
- (a scoped name).</p>
- </desc>
- </func>
- <func>
- <name>contents(Objref,Limit_type,Exclude_inherited) -> Return</name>
- <fsummary>Return the content of the target object limited by the given constraints</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Limit_type = atom() (one of dk_none, dk_all, dk_Attribute, dk_Constant, dk_Exception, dk_Interface, dk_Module, dk_Operation, dk_Typedef, dk_Alias, dk_Struct, dk_Union, dk_Enum, dk_Primitive, dk_String, dk_Wstring, dk_Fixed, dk_Sequence, dk_Array, dk_Repository)</v>
- <v>Exclude_inherited = atom() (true or false)</v>
- <v>Return = list() (a list of IFR#_objects)</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Container. Returns the contents of that IFR object.</p>
- </desc>
- </func>
- <func>
- <name>lookup_name(Objref,Search_name,Levels_to_search, Limit_type, Exclude_inherited) -> Return</name>
- <fsummary>Return a list of IFR objects matching the given name</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Search_name = string()</v>
- <v>Levels_to_search = integer()</v>
- <v>Limit_type = atom() (one of dk_none, dk_all, dk_Attribute, dk_Constant, dk_Exception, dk_Interface, dk_Module, dk_Operation, dk_Typedef, dk_Alias, dk_Struct, dk_Union, dk_Enum, dk_Primitive, dk_String, dk_Wstring, dk_Fixed, dk_Sequence, dk_Array, dk_Repository)</v>
- <v>Exclude_inherited = atom() (true or false)</v>
- <v>Return = list() (a list of #IFR_objects)</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Container. Returns a list of #IFR_objects with an id
- matching Search_name.</p>
- </desc>
- </func>
- <func>
- <name>describe_contents(Objref, Limit_type, Exclude_inherited, Max_returned_objs) -> Return</name>
- <fsummary>Return a list of descriptions of the IFR objects contained by the target Container object</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Limit_type = atom() (one of dk_none, dk_all, dk_Attribute, dk_Constant, dk_Exception, dk_Interface, dk_Module, dk_Operation, dk_Typedef, dk_Alias, dk_Struct, dk_Union, dk_Enum, dk_Primitive, dk_String, dk_Wstring, dk_Fixed, dk_Sequence, dk_Array, dk_Repository)</v>
- <v>Exclude_inherited = atom() (true or false)</v>
- <v>Return = list() (a list of tuples (contained_description records) | {exception, _}</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Container. Returns a list of descriptions of the IFR objects
- in this Container's contents.</p>
- </desc>
- </func>
- <func>
- <name>create_module(Objref,Id,Name,Version) -> Return</name>
- <fsummary>Create an IFR object of given type</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Id = string()</v>
- <v>Name = string()</v>
- <v>Version = string()</v>
- <v>Return = #IFR_ModuleDef_objref</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Container. Creates an IFR object of the type ModuleDef.</p>
- </desc>
- </func>
- <func>
- <name>create_constant(Objref,Id,Name,Version,Type,Value) -> Return</name>
- <fsummary>Create a ConstantDef IFR object</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Id = string()</v>
- <v>Name = string()</v>
- <v>Version = string()</v>
- <v>Type = #IFR_IDLType_objref</v>
- <v>Value = any()</v>
- <v>Return = #IFR_ConstantDef_objref</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Container. Creates an IFR object of the type ConstantDef.</p>
- </desc>
- </func>
- <func>
- <name>create_struct(Objref,Id,Name,Version,Members) -> Return</name>
- <fsummary>Create a StructDef IFR object</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Id = string()</v>
- <v>Name = string()</v>
- <v>Version = string()</v>
- <v>Members = list() (list of structmember records)</v>
- <v>Return = #IFR_StructDef_objref</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Container. Creates an IFR object of the type StructDef.</p>
- </desc>
- </func>
- <func>
- <name>create_union(Objref,Id,Name,Version,Discriminator_type,Members) -> Return</name>
- <fsummary>Create a UnionDef IFR object</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Id = string()</v>
- <v>Name = string()</v>
- <v>Version = string()</v>
- <v>Discriminator_type = #IFR_IDLType_Objref</v>
- <v>Members = list() (list of unionmember records)</v>
- <v>Return = #IFR_UnionDef_objref</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Container. Creates an IFR object of the type UnionDef.</p>
- </desc>
- </func>
- <func>
- <name>create_enum(Objref,Id,Name,Version,Members) -> Return</name>
- <fsummary>Create a EnumDef IFR object</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Id = string()</v>
- <v>Name = string()</v>
- <v>Version = string()</v>
- <v>Members = list() (list of strings)</v>
- <v>Return = #IFR_EnumDef_objref</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Container. Creates an IFR object of the type EnumDef.</p>
- </desc>
- </func>
- <func>
- <name>create_alias(Objref,Id,Name,Version,Original_type) -> Return</name>
- <fsummary>Create a AliasDef IFR object</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Id = string()</v>
- <v>Name = string()</v>
- <v>Version = string()</v>
- <v>Original_type = #IFR_IDLType_Objref</v>
- <v>Return = #IFR_AliasDef_objref</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Container. Creates an IFR object of the type AliasDef.</p>
- </desc>
- </func>
- <func>
- <name>create_interface(Objref,Id,Name,Version,Base_interfaces) -> Return</name>
- <fsummary>Create a InterfaceDef IFR object</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Id = string()</v>
- <v>Name = string()</v>
- <v>Version = string()</v>
- <v>Base_interfaces = list() (a list of IFR_InterfaceDef_objrefs that this interface inherits from</v>
- <v>Return = #IFR_InterfaceDef_objref</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Container. Creates an IFR object of the type InterfaceDef.</p>
- </desc>
- </func>
- <func>
- <name>create_exception(Objref,Id,Name,Version,Members) -> Return</name>
- <fsummary>Create a ExceptionDef IFR object</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Id = string()</v>
- <v>Name = string()</v>
- <v>Version = string()</v>
- <v>Members = list() (list of structmember records)</v>
- <v>Return = #IFR_ExceptionDef_objref</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- Container. Creates an IFR object of the type ExceptionDef.</p>
- </desc>
- </func>
- <func>
- <name>get_type(Objref) -> Return</name>
- <fsummary>Return the typecode of the target object</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Return = tuple() (a typecode tuple)</v>
- </type>
- <desc>
- <p>Objref is an IFR object of any kind that inherits from
- IDLType or an IFR object of the kind ConstantDef,
- ExceptionDef or AttributeDef. Returns the typecode of the
- IFR object.</p>
- </desc>
- </func>
- <func>
- <name>lookup_id(Objref,Search_id) -> Return</name>
- <fsummary>Return the IFR object matching the given id</fsummary>
- <type>
- <v>Objref = #IFR_Repository_objref</v>
- <v>Search_id = string()</v>
- <v>Return = #IFR_objref</v>
- </type>
- <desc>
- <p>Returns an IFR object matching the Search_id.</p>
- </desc>
- </func>
- <func>
- <name>get_primitive(Objref,Kind) -> Return</name>
- <fsummary>Return a PrimitiveDef of the specified kind</fsummary>
- <type>
- <v>Objref = #IFR_Repository_objref</v>
- <v>Kind = atom() (one of pk_null, pk_void, pk_short, pk_long, pk_ushort, pk_ulong, pk_float, pk_double, pk_boolean, pk_char, pk_octet, pk_any, pk_TypeCode, pk_Principal, pk_string, pk_wstring, pk_fixed, pk_objref)</v>
- <v>Return = #IFR_PrimitiveDef_objref</v>
- </type>
- <desc>
- <p>Returns a PrimitiveDef of the specified kind.</p>
- </desc>
- </func>
- <func>
- <name>create_string(Objref,Bound) -> Return</name>
- <fsummary>Create an IFR objref of the type StringDef</fsummary>
- <type>
- <v>Objref = #IFR_Repository_objref</v>
- <v>Bound = integer() (unsigned long /= 0)</v>
- <v>Return = #IFR_StringDef_objref</v>
- </type>
- <desc>
- <p>Creates an IFR objref of the type StringDef.</p>
- </desc>
- </func>
- <func>
- <name>create_wstring(Objref,Bound) -> Return</name>
- <fsummary>Create an IFR objref of the type WstringDef</fsummary>
- <type>
- <v>Objref = #IFR_Repository_objref</v>
- <v>Bound = integer() (unsigned long /= 0)</v>
- <v>Return = #IFR_WstringDef_objref</v>
- </type>
- <desc>
- <p>Creates an IFR objref of the type WstringDef.</p>
- </desc>
- </func>
- <func>
- <name>create_fixed(Objref,Digits,Scale) -> Return</name>
- <fsummary>Create an IFR objref of the type FixedDef</fsummary>
- <type>
- <v>Objref = #IFR_Repository_objref</v>
- <v>Digits = Scale = integer()</v>
- <v>Return = #IFR_FixedDef_objref</v>
- </type>
- <desc>
- <p>Creates an IFR objref of the type FixedDef.</p>
- </desc>
- </func>
- <func>
- <name>create_sequence(Objref,Bound,Element_type) -> Return</name>
- <fsummary>Create an IFR objref of the type SequenceDef</fsummary>
- <type>
- <v>Objref = #IFR_Repository_objref</v>
- <v>Bound = integer() (unsigned long)</v>
- <v>Element_type = #IFR_IDLType_objref</v>
- <v>Return = #IFR_SequenceDef_objref</v>
- </type>
- <desc>
- <p>Creates an IFR objref of the type SequenceDef.</p>
- </desc>
- </func>
- <func>
- <name>create_array(Objref,Length,Element_type) -> Return</name>
- <fsummary>Create an IFR objref of the type ArrayDef</fsummary>
- <type>
- <v>Objref = #IFR_Repository_objref</v>
- <v>Bound = integer() (unsigned long)</v>
- <v>Element_type = #IFR_IDLType_objref</v>
- <v>Return = #IFR_ArrayDef_objref</v>
- </type>
- <desc>
- <p>Creates an IFR objref of the type ArrayDef.</p>
- </desc>
- </func>
- <func>
- <name>create_idltype(Objref,Typecode) -> Return</name>
- <fsummary>Create an IFR objref of the type IDLType</fsummary>
- <type>
- <v>Objref = #IFR_Repository_objref</v>
- <v>Typecode = tuple() (a typecode tuple)</v>
- <v>Return = #IFR_IDLType_objref</v>
- </type>
- <desc>
- <p>Creates an IFR objref of the type IDLType.</p>
- </desc>
- </func>
- <func>
- <name>get_type_def(Objref) -> Return</name>
- <fsummary>Return an IFR object of the type IDLType describing the type of the target object</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Return = #IFR_IDLType_objref</v>
- </type>
- <desc>
- <p>Objref is an IFR object of the kind ConstantDef or
- AttributeDef. Returns an IFR object of the type IDLType
- describing the type of the IFR object.</p>
- </desc>
- </func>
- <func>
- <name>set_type_def(Objref,TypeDef) -> Return</name>
- <fsummary>Set given TypeDef of the target object</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>TypeDef = #IFR_IDLType_objref</v>
- <v>Return = ok | {exception, _}</v>
- </type>
- <desc>
- <p>Objref is an IFR object of the kind ConstantDef or
- AttributeDef. Sets the type_def of the IFR Object.</p>
- </desc>
- </func>
- <func>
- <name>get_value(Objref) -> Return</name>
- <fsummary>Return the value attribute of the target ConstantDef object</fsummary>
- <type>
- <v>Objref = #IFR_ConstantDef_objref</v>
- <v>Return = any()</v>
- </type>
- <desc>
- <p>Returns the value attribute of an IFR Object of the type ConstantDef.</p>
- </desc>
- </func>
- <func>
- <name>set_value(Objref,Value) -> Return</name>
- <fsummary>Set the value attribute of the target ConstantDef object</fsummary>
- <type>
- <v>Objref = #IFR_ConstantDef_objref</v>
- <v>Value = any()</v>
- <v>Return = ok | {exception, _}</v>
- </type>
- <desc>
- <p>Sets the value attribute of an IFR Object of the type ConstantDef.</p>
- </desc>
- </func>
- <func>
- <name>get_members(Objref) -> Return</name>
- <fsummary>Return the members of the target object</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Return = list()</v>
- </type>
- <desc>
- <p>Objref is an IFR object the kind StructDef, UnionDef,
- EnumDef or ExceptionDef.
- For StructDef, UnionDef and ExceptionDef: Returns a list of
- structmember records that are the constituent parts of the
- object.
- For EnumDef: Returns a list of strings describing the
- enumerations.</p>
- </desc>
- </func>
- <func>
- <name>set_members(Objref,Members) -> Return</name>
- <fsummary>Set the members attribute of the target object</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Members = list()</v>
- <v>Return = ok | {exception, _}</v>
- </type>
- <desc>
- <p>Objref is an IFR object the kind StructDef, UnionDef,
- EnumDef or ExceptionDef.
- For StructDef, UnionDef and ExceptionDef: Members is a list
- of structmember records.
- For EnumDef: Members is a list of strings describing the
- enumerations.
- Sets the members attribute, which are the constituent parts of the
- exception.</p>
- </desc>
- </func>
- <func>
- <name>get_discriminator_type(Objref) -> Return</name>
- <fsummary>Get the discriminator typecode of the target object</fsummary>
- <type>
- <v>Objref = #IFR_UnionDef_objref</v>
- <v>Return = tuple() (a typecode tuple)</v>
- </type>
- <desc>
- <p>Returns the discriminator typecode of an IFR object of the type
- UnionDef.</p>
- </desc>
- </func>
- <func>
- <name>get_discriminator_type_def(Objref) -> Return</name>
- <fsummary>Return IDLType object describing the discriminator type of the target object</fsummary>
- <type>
- <v>Objref = #IFR_UnionDef_objref</v>
- <v>Return = #IFR_IDLType_objref</v>
- </type>
- <desc>
- <p>Returns an IFR object of the type IDLType describing the
- discriminator type of an IFR object of the type UnionDef.</p>
- </desc>
- </func>
- <func>
- <name>set_discriminator_type_def(Objref,TypeDef) -> Return</name>
- <fsummary>Set the attribute discriminator_type_def for the target object to the given TypeDef</fsummary>
- <type>
- <v>Objref = #IFR_UnionDef_objref</v>
- <v>Return = #IFR_IDLType_objref</v>
- </type>
- <desc>
- <p>Sets the attribute discriminator_type_def, an IFR object of
- the type IDLType describing the discriminator type of an IFR
- object of the type UnionDef.</p>
- </desc>
- </func>
- <func>
- <name>get_original_type_def(Objref) -> Return</name>
- <fsummary>Return an IFR object of the type IDLType describing the original type</fsummary>
- <type>
- <v>Objref = #IFR_AliasDef_objref</v>
- <v>Return = #IFR_IDLType_objref</v>
- </type>
- <desc>
- <p>Returns an IFR object of the type IDLType describing the
- original type.</p>
- </desc>
- </func>
- <func>
- <name>set_original_type_def(Objref,TypeDef) -> Return</name>
- <fsummary>Set the original_type_def attribute which describes the original type</fsummary>
- <type>
- <v>Objref = #IFR_AliasDef_objref</v>
- <v>Typedef = #IFR_IDLType_objref</v>
- <v>Return = ok | {exception, _}</v>
- </type>
- <desc>
- <p>Sets the original_type_def attribute which describes the
- original type.</p>
- </desc>
- </func>
- <func>
- <name>get_kind(Objref) -> Return</name>
- <fsummary>Return an atom describing the primitive type</fsummary>
- <type>
- <v>Objref = #IFR_PrimitiveDef_objref</v>
- <v>Return = atom()</v>
- </type>
- <desc>
- <p>Returns an atom describing the primitive type (See CORBA 2.0
- p 6-21).</p>
- </desc>
- </func>
- <func>
- <name>get_bound(Objref) -> Return</name>
- <fsummary>Get the maximum size of the target object</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Return = integer (unsigned long)</v>
- </type>
- <desc>
- <p>Objref is an IFR object the kind StringDef or SequenceDef.
- For StringDef: returns the maximum number of characters in
- the string.
- For SequenceDef: Returns the maximum number of elements in
- the sequence. Zero indicates an unbounded sequence.</p>
- </desc>
- </func>
- <func>
- <name>set_bound(Objref,Bound) -> Return</name>
- <fsummary>Set the maximum size of the target object</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Bound = integer (unsigned long)</v>
- <v>Return = ok | {exception, _}</v>
- </type>
- <desc>
- <p>Objref is an IFR object the kind StringDef or SequenceDef.
- For StringDef: Sets the maximum number of characters in the
- string. Bound must not be zero.
- For SequenceDef: Sets the maximum number of elements in the
- sequence. Zero indicates an unbounded sequence.</p>
- </desc>
- </func>
- <func>
- <name>get_element_type(Objref) -> Return</name>
- <fsummary>Return the typecode of the elements in the IFR object</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Return = tuple() (a typecode tuple)</v>
- </type>
- <desc>
- <p>Objref is an IFR object the kind SequenceDef or ArrayDef.
- Returns the typecode of the elements in the IFR object.</p>
- </desc>
- </func>
- <func>
- <name>get_element_type_def(Objref) -> Return</name>
- <fsummary>Return an IFR object of the type IDLType describing the type of the elements in Objref</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Return = #IFR_IDLType_objref</v>
- </type>
- <desc>
- <p>Objref is an IFR object the kind SequenceDef or ArrayDef.
- Returns an IFR object of the type IDLType describing the
- type of the elements in Objref.</p>
- </desc>
- </func>
- <func>
- <name>set_element_type_def(Objref,TypeDef) -> Return</name>
- <fsummary>Set the element_type_def attribute of the target object to the given TypeDef</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>TypeDef = #IFR_IDLType_objref</v>
- <v>Return = ok | {exception, _}</v>
- </type>
- <desc>
- <p>Objref is an IFR object the kind SequenceDef or ArrayDef.
- Sets the element_type_def attribute, an IFR object of the
- type IDLType describing the type of the elements in Objref.</p>
- </desc>
- </func>
- <func>
- <name>get_length(Objref) -> Return</name>
- <fsummary>Return the number of elements in the array</fsummary>
- <type>
- <v>Objref = #IFR_ArrayDef_objref</v>
- <v>Return = integer() (unsigned long)</v>
- </type>
- <desc>
- <p>Returns the number of elements in the array.</p>
- </desc>
- </func>
- <func>
- <name>set_length(Objref,Length) -> Return</name>
- <fsummary>Set the number of elements in the array</fsummary>
- <type>
- <v>Objref = #IFR_ArrayDef_objref</v>
- <v>Length = integer() (unsigned long)</v>
- </type>
- <desc>
- <p>Sets the number of elements in the array.</p>
- </desc>
- </func>
- <func>
- <name>get_mode(Objref) -> Return</name>
- <fsummary>Get the mode of the target object (AttributeDef or OperationDef)</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Return = atom()</v>
- </type>
- <desc>
- <p>Objref is an IFR object the kind AttributeDef or OperationDef.
- For AttributeDef: Return is an atom ('ATTR_NORMAL' or
- 'ATTR_READONLY') specifying the read/write access for this
- attribute.
- For OperationDef: Return is an atom ('OP_NORMAL' or
- 'OP_ONEWAY') specifying the mode of the operation.</p>
- </desc>
- </func>
- <func>
- <name>set_mode(Objref,Mode) -> Return</name>
- <fsummary>Set the mode of the target object (AttributeDef or OperationDef) to the given mode</fsummary>
- <type>
- <v>Objref = #IFR_objref</v>
- <v>Mode = atom()</v>
- <v>Return = ok | {exception, _}</v>
- </type>
- <desc>
- <p>Objref is an IFR object the kind AttributeDef or OperationDef.
- For AttributeDef: Sets the read/write access for this
- attribute. Mode is an atom ('ATTR_NORMAL' or
- 'ATTR_READONLY').
- For OperationDef: Sets the mode of the operation. Mode is an
- atom ('OP_NORMAL' or 'OP_ONEWAY').</p>
- </desc>
- </func>
- <func>
- <name>get_result(Objref) -> Return</name>
- <fsummary>Return typecode describing the type of the value returned by the operation</fsummary>
- <type>
- <v>Objref = #IFR_OperationDef_objref</v>
- <v>Return = tuple() (a typecode tuple)</v>
- </type>
- <desc>
- <p>Returns a typecode describing the type of the value returned by the
- operation.</p>
- </desc>
- </func>
- <func>
- <name>get_result_def(Objref) -> Return</name>
- <fsummary>Return an IFR object of the type IDLType describing the type of the result</fsummary>
- <type>
- <v>Objref = #IFR_OperationDef_objref</v>
- <v>Return = #IFR_IDLType_objref</v>
- </type>
- <desc>
- <p>Returns an IFR object of the type IDLType describing the type of the
- result.</p>
- </desc>
- </func>
- <func>
- <name>set_result_def(Objref,ResultDef) -> Return</name>
- <fsummary>Set the type_def attribute of the target object to the given ResultDef</fsummary>
- <type>
- <v>Objref = #IFR_OperationDef_objref</v>
- <v>ResultDef = #IFR_IDLType_objref</v>
- <v>Return = ok | {exception, _}</v>
- </type>
- <desc>
- <p>Sets the type_def attribute, an IFR Object of the type IDLType
- describing the result.</p>
- </desc>
- </func>
- <func>
- <name>get_params(Objref) -> Return</name>
- <fsummary>Return a list of parameter description records describing the parameters of the target OperationDef</fsummary>
- <type>
- <v>Objref = #IFR_OperationDef_objref</v>
- <v>Return = list() (list of parameter description records)</v>
- </type>
- <desc>
- <p>Returns a list of parameter description records, which describes the
- parameters of the OperationDef.</p>
- </desc>
- </func>
- <func>
- <name>set_params(Objref,Params) -> Return</name>
- <fsummary>Set the params attribute of the target object to the given parameter description records</fsummary>
- <type>
- <v>Objref = #IFR_OperationDef_objref</v>
- <v>Params = list() (list of parameter description records)</v>
- <v>Return = ok | {exception, _}</v>
- </type>
- <desc>
- <p>Sets the params attribute, a list of parameter description records.</p>
- </desc>
- </func>
- <func>
- <name>get_contexts(Objref) -> Return</name>
- <fsummary>Return a list of context identifiers for the operation</fsummary>
- <type>
- <v>Objref = #IFR_OperationDef_objref</v>
- <v>Return = list() (list of strings)</v>
- </type>
- <desc>
- <p>Returns a list of context identifiers for the operation.</p>
- </desc>
- </func>
- <func>
- <name>set_contexts(Objref,Contexts) -> Return</name>
- <fsummary>Set the context attribute for the operation</fsummary>
- <type>
- <v>Objref = #IFR_OperationDef_objref</v>
- <v>Contexts = list() (list of strings)</v>
- <v>Return = ok | {exception, _}</v>
- </type>
- <desc>
- <p>Sets the context attribute for the operation.</p>
- </desc>
- </func>
- <func>
- <name>get_exceptions(Objref) -> Return</name>
- <fsummary>Return a list of exception types that can be raised by the target object</fsummary>
- <type>
- <v>Objref = #IFR_OperationDef_objref</v>
- <v>Return = list() (list of #IFR_ExceptionDef_objrefs)</v>
- </type>
- <desc>
- <p>Returns a list of exception types that can be raised by this
- operation.</p>
- </desc>
- </func>
- <func>
- <name>set_exceptions(Objref,Exceptions) -> Return</name>
- <fsummary>Set the exceptions attribute for the target object</fsummary>
- <type>
- <v>Objref = #IFR_OperationDef_objref</v>
- <v>Exceptions = list() (list of #IFR_ExceptionDef_objrefs)</v>
- <v>Return = ok | {exception, _}</v>
- </type>
- <desc>
- <p>Sets the exceptions attribute for this operation.</p>
- </desc>
- </func>
- <func>
- <name>get_base_interfaces(Objref) -> Return</name>
- <fsummary>Return a list of InterfaceDefs from which the target InterfaceDef object inherit</fsummary>
- <type>
- <v>Objref = #IFR_InterfaceDef_objref</v>
- <v>Return = list() (list of #IFR_InterfaceDef_objrefs)</v>
- </type>
- <desc>
- <p>Returns a list of InterfaceDefs from which this InterfaceDef inherits.</p>
- </desc>
- </func>
- <func>
- <name>set_base_interfaces(Objref,BaseInterfaces) -> Return</name>
- <fsummary>Set the BaseInterfaces attribute</fsummary>
- <type>
- <v>Objref = #IFR_InterfaceDef_objref</v>
- <v>BaseInterfaces = list() (list of #IFR_InterfaceDef_objrefs)</v>
- <v>Return = ok | {exception, _}</v>
- </type>
- <desc>
- <p>Sets the BaseInterfaces attribute.</p>
- </desc>
- </func>
- <func>
- <name>is_a(Objref,Interface_id) -> Return</name>
- <fsummary>Return a boolean if the target InterfaceDef match or inherit from the given id</fsummary>
- <type>
- <v>Objref = #IFR_InterfaceDef_objref</v>
- <v>Interface_id = #IFR_InterfaceDef_objref</v>
- <v>Return = atom() (true or false)</v>
- </type>
- <desc>
- <p>Returns true if the InterfaceDef either is identical to or
- inherits from Interface_id.</p>
- </desc>
- </func>
- <func>
- <name>describe_interface(Objref) -> Return</name>
- <fsummary>Return a full inter face description record describing the InterfaceDef</fsummary>
- <type>
- <v>Objref = #IFR_InterfaceDef_objref</v>
- <v>Return = tuple() (a fullinterfacedescription record)</v>
- </type>
- <desc>
- <p>Returns a full inter face description record describing the InterfaceDef.</p>
- </desc>
- </func>
- <func>
- <name>create_attribute(Objref,Id,Name,Version,Type,Mode) -> Return</name>
- <fsummary>Create an IFR object of the type AttributeDef contained in the target InterfaceDef object</fsummary>
- <type>
- <v>Objref = #IFR_InterfaceDef_objref</v>
- <v>Id = string()</v>
- <v>Name = string()</v>
- <v>Version = string()</v>
- <v>Type = #IFR_IDLType_objref</v>
- <v>Mode = atom() ('ATTR_NORMAL' or 'ATTR_READONLY')</v>
- <v>Return = #IFR_AttributeDef_objref</v>
- </type>
- <desc>
- <p>Creates an IFR object of the type AttributeDef contained in this
- InterfaceDef.</p>
- </desc>
- </func>
- <func>
- <name>create_operation(Objref,Id,Name,Version,Result,Mode,Params, Exceptions,Contexts) -> Return</name>
- <fsummary>Create an IFR object of the type OperationDef contained in the target InterfaceDef object</fsummary>
- <type>
- <v>Objref = #IFR_InterfaceDef_objref</v>
- <v>Id = string()</v>
- <v>Name = string()</v>
- <v>Version = string()</v>
- <v>Result = #IFR_IDLType_objref</v>
- <v>Mode = atom() ('OP_NORMAL' or 'OP_ONEWAY')</v>
- <v>Params = list() (list of parameter description records)</v>
- <v>Exceptions = list() (list of #IFR_ExceptionDef_objrefs)</v>
- <v>Contexts = list() (list of strings)</v>
- <v>Return = #IFR_OperationDef_objref</v>
- </type>
- <desc>
- <p>Creates an IFR object of the type OperationDef contained in this
- InterfaceDef.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/orber/doc/src/orber_tc.xml b/lib/orber/doc/src/orber_tc.xml
deleted file mode 100644
index 0cab8a5e4b..0000000000
--- a/lib/orber/doc/src/orber_tc.xml
+++ /dev/null
@@ -1,259 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1998</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>orber_tc</title>
- <prepared>Lars Thors&eacute;n</prepared>
- <responsible>Lars Thors&eacute;n</responsible>
- <docno></docno>
- <approved>Lars Thors&eacute;n</approved>
- <checked></checked>
- <date>1998-04-20</date>
- <rev>A</rev>
- </header>
- <module>orber_tc</module>
- <modulesummary>Help functions for IDL typecodes</modulesummary>
- <description>
- <p>This module contains some functions that gives support in creating
- IDL typecodes that can be used in for example the any types typecode field.
- For the simple types it is meaningless to use this API but the functions exist
- to get the interface complete.</p>
- <p>The type <c>TC</c> used below describes an IDL type and is a tuple according
- to the to the Erlang language mapping.</p>
- </description>
- <funcs>
- <func>
- <name>null() -> TC</name>
- <name>void() -> TC</name>
- <name>short() -> TC</name>
- <name>unsigned_short() -> TC</name>
- <name>long() -> TC</name>
- <name>unsigned_long() -> TC</name>
- <name>long_long() -> TC</name>
- <name>unsigned_long_long() -> TC</name>
- <name>wchar() -> TC</name>
- <name>float() -> TC</name>
- <name>double() -> TC</name>
- <name>boolean() -> TC</name>
- <name>char() -> TC</name>
- <name>octet() -> TC</name>
- <name>any() -> TC</name>
- <name>typecode() -> TC</name>
- <name>principal() -> TC</name>
- <fsummary>Return the IDL typecode</fsummary>
- <desc>
- <p>These functions return the IDL typecodes for simple types.</p>
- </desc>
- </func>
- <func>
- <name>object_reference(Id, Name) -> TC</name>
- <fsummary>Return the object_reference IDL typecode</fsummary>
- <type>
- <v>Id = string()</v>
- <d>the repository ID</d>
- <v>Name = string()</v>
- <d>the type name of the object</d>
- </type>
- <desc>
- <p>Function returns the IDL typecode for object_reference.</p>
- </desc>
- </func>
- <func>
- <name>struct(Id, Name, ElementList) -> TC</name>
- <fsummary>Return the struct IDL typecode</fsummary>
- <type>
- <v>Id = string()</v>
- <d>the repository ID</d>
- <v>Name = string()</v>
- <d>the type name of the struct</d>
- <v>ElementList = [{MemberName, TC}]</v>
- <d>a list of the struct elements</d>
- <v>MemberName = string()</v>
- <d>the element name</d>
- </type>
- <desc>
- <p>Function returns the IDL typecode for struct.</p>
- </desc>
- </func>
- <func>
- <name>union(Id, Name, DiscrTC, Default, ElementList) -> TC</name>
- <fsummary>Return the union IDL typecode</fsummary>
- <type>
- <v>Id = string()</v>
- <d>the repository ID</d>
- <v>Name = string()</v>
- <d>the type name of the union</d>
- <v>DiscrTC = TC</v>
- <d>the typecode for the unions discriminant</d>
- <v>Default = integer()</v>
- <d>a value that indicates which tuple in the element list that is default (value &lt; 0 means no default)</d>
- <v>ElementList = [{Label, MemberName, TC}]</v>
- <d>a list of the union elements</d>
- <v>Label = term()</v>
- <d>the label value should be of the <em>DiscrTC</em>type</d>
- <v>MemberName = string()</v>
- <d>the element name</d>
- </type>
- <desc>
- <p>Function returns the IDL typecode for union.</p>
- </desc>
- </func>
- <func>
- <name>enum(Id, Name, ElementList) -> TC</name>
- <fsummary>Return the enum IDL typecode</fsummary>
- <type>
- <v>Id = string()</v>
- <d>the repository ID</d>
- <v>Name = string()</v>
- <d>the type name of the enum</d>
- <v>ElementList = [MemberName]</v>
- <d>a list of the enums elements</d>
- <v>MemberName = string()</v>
- <d>the element name</d>
- </type>
- <desc>
- <p>Function returns the IDL typecode for enum.</p>
- </desc>
- </func>
- <func>
- <name>string(Length) -> TC</name>
- <fsummary>Return the string IDL typecode</fsummary>
- <type>
- <v>Length = integer()</v>
- <d>the length of the string (0 means unbounded)</d>
- </type>
- <desc>
- <p>Function returns the IDL typecode for string.</p>
- </desc>
- </func>
- <func>
- <name>wstring(Length) -> TC</name>
- <fsummary>Return the wstring IDL typecode</fsummary>
- <type>
- <v>Length = integer()</v>
- <d>the length of the wstring (0 means unbounded)</d>
- </type>
- <desc>
- <p>Function returns the IDL typecode for wstring.</p>
- </desc>
- </func>
- <func>
- <name>fixed(Digits, Scale) -> TC</name>
- <fsummary>Return the fixed IDL typecode</fsummary>
- <type>
- <v>Digits = Scale = integer()</v>
- <d>the digits and scale parameters of a Fixed type</d>
- </type>
- <desc>
- <p>Function returns the IDL typecode for fixed.</p>
- </desc>
- </func>
- <func>
- <name>sequence(ElemTC, Length) -> TC</name>
- <fsummary>Return the sequence IDL typecode</fsummary>
- <type>
- <v>ElemTC = TC</v>
- <d>the typecode for the sequence elements</d>
- <v>Length = integer()</v>
- <d>the length of the sequence (0 means unbounded)</d>
- </type>
- <desc>
- <p>Function returns the IDL typecode for sequence.</p>
- </desc>
- </func>
- <func>
- <name>array(ElemTC, Length) -> TC</name>
- <fsummary>Return the array IDL typecode</fsummary>
- <type>
- <v>ElemTC = TC</v>
- <d>the typecode for the array elements</d>
- <v>Length = integer()</v>
- <d>the length of the array</d>
- </type>
- <desc>
- <p>Function returns the IDL typecode for array.</p>
- </desc>
- </func>
- <func>
- <name>alias(Id, Name, AliasTC) -> TC</name>
- <fsummary>Return the alias IDL typecode</fsummary>
- <type>
- <v>Id = string()</v>
- <d>the repository ID</d>
- <v>Name = string()</v>
- <d>the type name of the alias</d>
- <v>AliasTC = TC</v>
- <d>the typecode for the type which the alias refer to</d>
- </type>
- <desc>
- <p>Function returns the IDL typecode for alias.</p>
- </desc>
- </func>
- <func>
- <name>exception(Id, Name, ElementList) -> TC</name>
- <fsummary>Return the exception IDL typecode</fsummary>
- <type>
- <v>Id = string()</v>
- <d>the repository ID</d>
- <v>Name = string()</v>
- <d>the type name of the exception</d>
- <v>ElementList = [{MemberName, TC}]</v>
- <d>a list of the exception elements</d>
- <v>MemberName = string()</v>
- <d>the element name</d>
- </type>
- <desc>
- <p>Function returns the IDL typecode for exception.</p>
- </desc>
- </func>
- <func>
- <name>get_tc(Object) -> TC</name>
- <name>get_tc(Id) -> TC</name>
- <fsummary>Fetch typecode</fsummary>
- <type>
- <v>Object = record()</v>
- <d>an IDL specified struct, union or exception</d>
- <v>Id = string()</v>
- <d>the repository ID</d>
- </type>
- <desc>
- <p>If the get_tc/1 gets a record that is and IDL specified
- struct, union or exception as a parameter it returns the
- typecode.</p>
- <p>If the parameter is a repository ID it uses the Interface Repository
- to get the typecode.</p>
- </desc>
- </func>
- <func>
- <name>check_tc(TC) -> boolean()</name>
- <fsummary>Check syntax of an IDL typecode</fsummary>
- <desc>
- <p>Function checks the syntax of an IDL typecode.</p>
- </desc>
- </func>
- </funcs>
-
-</erlref>
-
diff --git a/lib/orber/doc/src/orbs.gif b/lib/orber/doc/src/orbs.gif
deleted file mode 100644
index 47f2c85441..0000000000
--- a/lib/orber/doc/src/orbs.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/part.xml b/lib/orber/doc/src/part.xml
deleted file mode 100644
index ef84b8c05a..0000000000
--- a/lib/orber/doc/src/part.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Orber User's Guide</title>
- <prepared></prepared>
- <docno></docno>
- <date>1998-04-26</date>
- <rev>2.2</rev>
- </header>
- <description>
- <p>The <em>Orber</em> application is an Erlang implementation of a
- CORBA Object Request Broker.</p>
- </description>
- <xi:include href="ch_contents.xml"/>
- <xi:include href="ch_introduction.xml"/>
- <xi:include href="ch_orber_kernel.xml"/>
- <xi:include href="ch_ifr.xml"/>
- <xi:include href="ch_install.xml"/>
- <xi:include href="ch_idl_to_erlang_mapping.xml"/>
- <xi:include href="ch_naming_service.xml"/>
- <xi:include href="ch_security.xml"/>
- <xi:include href="ch_stubs.xml"/>
- <xi:include href="ch_exceptions.xml"/>
- <xi:include href="ch_interceptors.xml"/>
- <xi:include href="ch_orberweb.xml"/>
- <xi:include href="ch_debugging.xml"/>
-</part>
-
diff --git a/lib/orber/doc/src/part_notes.xml b/lib/orber/doc/src/part_notes.xml
deleted file mode 100644
index 61d9d4c3b9..0000000000
--- a/lib/orber/doc/src/part_notes.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Orber Release Notes</title>
- <prepared>Lars Thors&eacute;n, Peter Lundell</prepared>
- <docno></docno>
- <date>1999-04-20</date>
- <rev>2.0</rev>
- </header>
- <description>
- <p>The Orber Application is an Erlang implementation of a CORBA Object
- Request Broker.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/orber/doc/src/ref_man.gif b/lib/orber/doc/src/ref_man.gif
deleted file mode 100644
index b13c4efd53..0000000000
--- a/lib/orber/doc/src/ref_man.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/ref_man.xml b/lib/orber/doc/src/ref_man.xml
deleted file mode 100644
index 6fa409538d..0000000000
--- a/lib/orber/doc/src/ref_man.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE application SYSTEM "application.dtd">
-
-<application xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Orber Reference Manual</title>
- <prepared></prepared>
- <docno></docno>
- <date>1998-05-05</date>
- <rev>2.0</rev>
- </header>
- <description>
- <p>The <em>Orber</em> application is an Erlang implementation of a
- CORBA Object Request Broker.</p>
- </description>
- <xi:include href="any.xml"/>
- <xi:include href="fixed.xml"/>
- <xi:include href="corba.xml"/>
- <xi:include href="corba_object.xml"/>
- <xi:include href="orber.xml"/>
- <xi:include href="orber_ifr.xml"/>
- <xi:include href="orber_tc.xml"/>
- <xi:include href="orber_acl.xml"/>
- <xi:include href="CosNaming.xml"/>
- <xi:include href="CosNaming_NamingContext.xml"/>
- <xi:include href="CosNaming_NamingContextExt.xml"/>
- <xi:include href="CosNaming_BindingIterator.xml"/>
- <xi:include href="lname.xml"/>
- <xi:include href="lname_component.xml"/>
- <xi:include href="Module_Interface.xml"/>
- <xi:include href="interceptors.xml"/>
- <xi:include href="orber_diagnostics.xml"/>
-</application>
-
diff --git a/lib/orber/doc/src/summary.html.src b/lib/orber/doc/src/summary.html.src
deleted file mode 100644
index f88ee7218f..0000000000
--- a/lib/orber/doc/src/summary.html.src
+++ /dev/null
@@ -1 +0,0 @@
-A CORBA Object Request Broker
diff --git a/lib/orber/doc/src/theORB.gif b/lib/orber/doc/src/theORB.gif
deleted file mode 100644
index 976672b8df..0000000000
--- a/lib/orber/doc/src/theORB.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/doc/src/tools_debugging_part.xml b/lib/orber/doc/src/tools_debugging_part.xml
deleted file mode 100644
index 94af44833c..0000000000
--- a/lib/orber/doc/src/tools_debugging_part.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2002</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Tools, Debugging and FAQ</title>
- <prepared>Niclas Eklund</prepared>
- <docno></docno>
- <date>2002-06-25</date>
- <rev>A</rev>
- </header>
- <description>
- <p>This chapter describe the available tools and debugging facilities for Orber.
- Also contain a FAQ listing of the most common mistakes.</p>
- </description>
- <include file="ch_orberweb"></include>
- <include file="ch_debugging"></include>
-</part>
-
diff --git a/lib/orber/doc/src/user_guide.gif b/lib/orber/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/orber/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/orber/ebin/.gitignore b/lib/orber/ebin/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/orber/ebin/.gitignore
+++ /dev/null
diff --git a/lib/orber/examples/Makefile b/lib/orber/examples/Makefile
deleted file mode 100644
index bf1ff13707..0000000000
--- a/lib/orber/examples/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(ORBER_VSN)
-
-# ----------------------------------------------------
-# Common Macros
-# ----------------------------------------------------
-
-SUB_DIRECTORIES = Stack
-
-SPECIAL_TARGETS =
-
-# ----------------------------------------------------
-# Default Subdir Targets
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_subdir.mk
-
diff --git a/lib/orber/examples/Stack/InitialReferences.idl b/lib/orber/examples/Stack/InitialReferences.idl
deleted file mode 100644
index 7c1dddc7c4..0000000000
--- a/lib/orber/examples/Stack/InitialReferences.idl
+++ /dev/null
@@ -1,12 +0,0 @@
-typedef string ObjectId;
-typedef sequence <ObjectId> ObjectIdList;
-
-module Orber {
-interface InitialReferences {
-
- Object get(in ObjectId id);
-
- ObjectIdList list();
-
-};
-};
diff --git a/lib/orber/examples/Stack/Makefile b/lib/orber/examples/Stack/Makefile
deleted file mode 100644
index 5348c624e3..0000000000
--- a/lib/orber/examples/Stack/Makefile
+++ /dev/null
@@ -1,128 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-
-EBIN= ../../ebin
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(ORBER_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/orber-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-IDL_FILES = \
- stack.idl \
- InitialReferences.idl
-
-GEN_ERL_MODULES = \
- oe_stack \
- StackModule_Stack \
- StackModule_StackFactory \
- StackModule_EmptyStack
-
-MODULES= \
- StackModule_Stack_impl \
- StackModule_StackFactory_impl \
- stack_factory \
- stack_client
-
-GEN_HRL_FILES = \
- oe_stack.hrl \
- StackModule.hrl \
- StackModule_Stack.hrl \
- StackModule_StackFactory.hrl
-
-HRL_FILES=
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-GEN_FILES = $(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES)
-
-JAVA_CLASSES = \
- StackClient
-
-JAVA_FILES= $(JAVA_CLASSES:%=%.java)
-CLASS_FILES= $(JAVA_CLASSES:%=%.class)
-
-TARGET_FILES = \
- $(GEN_ERL_MODULES:%=$(EBIN)/%.$(EMULATOR)) \
- $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-TEST_TARGET_FILES =
-
-CPP_FILES = StackClient.cc
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/orber/ebin -pa $(ERL_TOP)/lib/ic/ebin
-# The -pa option is just used temporary until erlc can handle
-# includes from other directories than ../include .
-ERL_COMPILE_FLAGS += \
- $(ERL_IDL_FLAGS) \
- -pa $(ERL_TOP)/lib/orber -I$(ERL_TOP)/lib/orber
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
-
-clean:
- rm -f $(TARGET_FILES) $(GEN_ERL_MODULES:%=%.erl) $(GEN_HRL_FILES) $(CLASS_FILES) IDL-GENERATED
- rm -f errs core *~
-
-docs:
-
-test: $(TEST_TARGET_FILES)
-
-IDL-GENERATED: stack.idl
- $(gen_verbose)erlc $(ERL_IDL_FLAGS) stack.idl
- $(V_at)>IDL-GENERATED
-
-$(GEN_FILES): IDL-GENERATED
-
-$(TARGET_FILES): IDL-GENERATED
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/examples/Stack"
- $(INSTALL_DATA) $(ERL_FILES) $(JAVA_FILES) $(CPP_FILES) $(IDL_FILES) "$(RELSYSDIR)/examples/Stack"
-
-
-release_docs_spec:
-
-
diff --git a/lib/orber/examples/Stack/StackClient.cc b/lib/orber/examples/Stack/StackClient.cc
deleted file mode 100644
index 4d393390c4..0000000000
--- a/lib/orber/examples/Stack/StackClient.cc
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- * <copyright>
- * <year>2000-2007</year>
- * <holder>Ericsson AB, All Rights Reserved</holder>
- *</copyright>
- *<legalnotice>
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * The Initial Developer of the Original Code is Ericsson AB.
- *</legalnotice>
- */
-/**
- * This module gives an example how it is possible to setup a connection
- * Orbix3.0.1 and Orber3.0.2
- */
-
-
-#define USE_IIOP
-
-#include <iostream.h>
-#include <stdio.h>
-#include <fstream.h>
-#include <stdlib.h>
-
-#include "NamingService.hh"
-#include "InitialReference.hh"
-#include "InitialReferences.hh"
-#include "stack.hh"
-
-
-int main(int argc, char** argv) {
-
- CORBA::Object_ptr nsRef, initRef, objRef;
- InitialReference init;
- Orber::InitialReferences_var initp;
- CosNaming::NamingContext_var Ns;
- CosNaming::NameComponent nc;
- CosNaming::Name_var name;
- StackModule::StackFactory_var stackFac;
- StackModule::Stack_var stack;
-
- if (argc < 3) {
- cout << "usage: " << argv[0] << " <hostname>" << " <srvport>" << endl;
- exit (-1);
- }
-
- string srvHost = argv[1];
- long srvPort = atoi(argv[2]);
-
- cout << "Using host: " << srvHost << " Port: " << srvPort << endl;
-
- try
- {
- // Create Initial reference (objectkey "INIT").
- const string s = init.stringified_ior(srvHost, srvPort);
- initRef = CORBA::Orbix.string_to_object(s);
- initp = Orber::InitialReferences::_narrow(initRef);
- nsRef = initp->get("NameService");
- Ns = CosNaming::NamingContext::_narrow(nsRef);
-
- // Create a name component.
- name = new CosNaming::Name(1);
- name->length(1);
- name[0].id = CORBA::string_dup("StackFactory");
- name[0].kind = CORBA::string_dup("");
-
- // Look up the Object in the NamingService.
- objRef = Ns->resolve(name);
- stackFac = StackModule::StackFactory::_narrow(objRef);
- stack = stackFac->create_stack();
-
- // push & pop
- stack->push(8);
- stack->push(7);
- stack->push(6);
- cout << "Stack: " << stack->pop()
- << " " << stack->pop()
- << " " << stack->pop() << endl;
-
- } catch(...) {
- cerr << "call failed" << endl;
- cerr << "Unexpected exception " << endl;
- exit(1);
- }
- cout << "Completed successfully" << endl;
- return 0;
-}
diff --git a/lib/orber/examples/Stack/StackClient.java b/lib/orber/examples/Stack/StackClient.java
deleted file mode 100644
index 55e967a330..0000000000
--- a/lib/orber/examples/Stack/StackClient.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1997-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/*
- * Stack example.
- */
-
-package StackModule;
-import org.omg.CORBA.*;
-import org.omg.CORBA.SystemException;
-import org.omg.CORBA.ORB.*;
-
-public class StackClient
-{
- public static void main(String args[])
- {
- org.omg.CORBA.Object objRef;
- StackFactory sfRef = null;
- Stack sRef = null;
- // The argument can look like
- // "corbaname::host:4001/#StackFactory"
- String corbaName = new String(args[0]);
- try{
- ORB orb = ORB.init(args, null);
-
- objRef = orb.string_to_object(corbaName);
- sfRef = StackFactoryHelper.narrow(objRef);
- sRef = sfRef.create_stack();
-
- sRef.push(4);
- sRef.push(7);
- sRef.push(1);
- sRef.push(1);
-
- try{
- System.out.println(sRef.pop());
- System.out.println(sRef.pop());
- System.out.println(sRef.pop());
- System.out.println(sRef.pop());
- // The following operation shall
- // return an EmptyStack exception
- System.out.println(sRef.pop());
- }
- catch(EmptyStack es) {
- System.out.println("Empty stack");
- };
-
- sfRef.destroy_stack(sRef);
- }
- catch(SystemException se)
- {
- System.out.println("Unexpected exception: " + se.toString());
- return;
- }
- }
-}
diff --git a/lib/orber/examples/Stack/StackModule_StackFactory_impl.erl b/lib/orber/examples/Stack/StackModule_StackFactory_impl.erl
deleted file mode 100644
index 76e449971f..0000000000
--- a/lib/orber/examples/Stack/StackModule_StackFactory_impl.erl
+++ /dev/null
@@ -1,41 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% StackModule_StackFactory_impl example file.
-
--module('StackModule_StackFactory_impl').
--include_lib("orber/include/corba.hrl").
--export([create_stack/1, destroy_stack/2, init/1, terminate/2]).
-
-
-init(_Env) ->
- {ok, []}.
-
-terminate(_From, _Reason) ->
- ok.
-
-create_stack(State) ->
- %% Just a create we don't want a link.
- {reply, 'StackModule_Stack':oe_create(), State}.
-
-destroy_stack(State, Stack) ->
- {reply, corba:dispose(Stack), State}.
diff --git a/lib/orber/examples/Stack/StackModule_Stack_impl.erl b/lib/orber/examples/Stack/StackModule_Stack_impl.erl
deleted file mode 100644
index ff4dc90829..0000000000
--- a/lib/orber/examples/Stack/StackModule_Stack_impl.erl
+++ /dev/null
@@ -1,47 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% StackModule_Stack_impl example file.
-
--module('StackModule_Stack_impl').
--include_lib("orber/include/corba.hrl").
--include("StackModule.hrl").
--export([pop/1, push/2, empty/1, init/1, terminate/2]).
-
-
-init(_Env) ->
- {ok, []}.
-
-terminate(_From, _Reason) ->
- ok.
-
-push(Stack, Val) ->
- {reply, ok, [Val | Stack]}.
-
-pop([Val | Stack]) ->
- {reply, Val, Stack};
-pop([]) ->
- corba:raise(#'StackModule_EmptyStack'{}).
-
-empty(_) ->
- {reply, ok, []}.
-
diff --git a/lib/orber/examples/Stack/stack.idl b/lib/orber/examples/Stack/stack.idl
deleted file mode 100644
index f21f93917b..0000000000
--- a/lib/orber/examples/Stack/stack.idl
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef _STACK_IDL
-#define _STACK_IDL
-
-module StackModule {
-
- exception EmptyStack {};
-
- interface Stack {
-
- long pop() raises(StackModule::EmptyStack);
-
- void push(in long value);
-
- void empty();
-
- };
-
- interface StackFactory {
-
- StackModule::Stack create_stack();
- void destroy_stack(in StackModule::Stack s);
-
- };
-
-};
-
-#endif
diff --git a/lib/orber/examples/Stack/stack_client.erl b/lib/orber/examples/Stack/stack_client.erl
deleted file mode 100644
index 6e32195b1b..0000000000
--- a/lib/orber/examples/Stack/stack_client.erl
+++ /dev/null
@@ -1,56 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% stack_client example file.
-
--module('stack_client').
-
--export([run/0]).
-
-
-run() ->
- case catch corba:string_to_object("corbaname:rir:/NameService#StackFactory") of
- {'EXCEPTION', _E} ->
- io:format("The stack factory server is not registered~n",[]);
- SF ->
- %% Create the stack
- SS = 'StackModule_StackFactory':create_stack(SF),
-
- 'StackModule_Stack':push(SS, 4),
- 'StackModule_Stack':push(SS, 7),
- 'StackModule_Stack':push(SS, 1),
- 'StackModule_Stack':push(SS, 1),
- Res = 'StackModule_Stack':pop(SS),
- io:format("~w~n", [Res]),
- Res1 = 'StackModule_Stack':pop(SS),
- io:format("~w~n", [Res1]),
- Res2 = 'StackModule_Stack':pop(SS),
- io:format("~w~n", [Res2]),
- Res3 = 'StackModule_Stack':pop(SS),
- io:format("~w~n", [Res3]),
-
- %% Remove the stack
- 'StackModule_StackFactory':destroy_stack(SF, SS)
-
- end.
-
-
diff --git a/lib/orber/examples/Stack/stack_factory.erl b/lib/orber/examples/Stack/stack_factory.erl
deleted file mode 100644
index b5b455ae5a..0000000000
--- a/lib/orber/examples/Stack/stack_factory.erl
+++ /dev/null
@@ -1,38 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% stack_factory example file.
-
--module('stack_factory').
--include_lib("orber/include/corba.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming.hrl").
--include_lib("orber/COSS/CosNaming/lname.hrl").
-
--export([start/0]).
-
-start() ->
- SFok = 'StackModule_StackFactory':oe_create(),
- NS = corba:resolve_initial_references("NameService"),
- NC = lname_component:set_id(lname_component:create(), "StackFactory"),
- N = lname:insert_component(lname:create(), 1, NC),
- 'CosNaming_NamingContext':bind(NS, N, SFok).
-
diff --git a/lib/orber/include/corba.hrl b/lib/orber/include/corba.hrl
deleted file mode 100644
index fb1c2a5a94..0000000000
--- a/lib/orber/include/corba.hrl
+++ /dev/null
@@ -1,149 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%------------------------------------------------------------
-%% File: corba.hrl
-%%
-%% Description:
-%% Standard header file for the Orber Erlang CORBA environment
-%%
-%%-----------------------------------------------------------------
--ifndef(corba_hrl).
--define(corba_hrl, true).
-
-%%
-%% Implementation repository record (not used and can therefor be changed)
-%%
--record(orb_ImplDef, {node, module, typename, start=start, args=[[]], pid}).
-
-%%
-%% Any record
-%%
--record(any, {typecode, value}).
-
-%%
-%% Any record
-%%
--record(fixed, {digits, scale, value}).
-
-%%
-%% Service context record
-%%
--record('IOP_ServiceContext', {context_id, context_data}).
-
-%%
-%% Exception recod for the resolve initial reference functions
-%%
--record('InvalidName', {'OE_ID'="IDL:omg.org/CORBA/ORB/InvalidName:1.0"}).
-
-%% Orber OMG assigned TAG's
-%% Service Context IDs 0x45524904 - 0x45524907 ("ERI\x04" - "ERI\x07")
-%% Component IDs 0x45524904 - 0x45524907 ("ERI\x04" - "ERI\x07")
-%% ORB type IDs 0x45524904 - 0x45524907 ("ERI\x04" - "ERI\x07")
--define(ORBER_ORB_TYPE_1, 16#45524904).
-%-define(ORBER_ORB_TYPE_2, 16#45524905).
-%-define(ORBER_ORB_TYPE_3, 16#45524906).
-%-define(ORBER_ORB_TYPE_4, 16#45524907).
-
-%-define(ORBER_COMPONENT_1, 16#45524904).
-%-define(ORBER_COMPONENT_2, 16#45524905).
-%-define(ORBER_COMPONENT_3, 16#45524906).
-%-define(ORBER_COMPONENT_4, 16#45524907).
-
--define(ORBER_GENERIC_CTX_ID, 16#45524904).
-%-define(ORBER_SERVICE_CTX_2, 16#45524905).
-%-define(ORBER_SERVICE_CTX_3, 16#45524906).
-%-define(ORBER_SERVICE_CTX_4, 16#45524907).
-
-%%
-%% System exceptions
-%%
-
-%% VMCID
-%% VMCID base assigned to OMG
--define(CORBA_OMGVMCID, 16#4f4d0000).
-
-%% Orber's VMCID base - "ER\x00\x00" - "ER\x0f\xff".
-%% Range 16#45520000 -> 16#45520fff
--define(ORBER_VMCID, 16#45520000).
-
-%% Some other Vendors VMCID bases.
--define(IONA_VMCID_1, 16#4f4f0000).
--define(IONA_VMCID_2, 16#49540000).
--define(SUN_VMCID, 16#53550000).
--define(BORLAND_VMCID, 16#56420000).
--define(TAO_VMCID, 16#54410000).
--define(PRISMTECH_VMCID,16#50540000).
-
--define(ex_body, {'OE_ID'="", minor=?ORBER_VMCID, completion_status}).
-
--record('UNKNOWN', ?ex_body).
--record('BAD_PARAM', ?ex_body).
--record('NO_MEMORY', ?ex_body).
--record('IMP_LIMIT', ?ex_body).
--record('COMM_FAILURE', ?ex_body).
--record('INV_OBJREF', ?ex_body).
--record('NO_PERMISSION', ?ex_body).
--record('INTERNAL', ?ex_body).
--record('MARSHAL', ?ex_body).
--record('INITIALIZE', ?ex_body).
--record('NO_IMPLEMENT', ?ex_body).
--record('BAD_TYPECODE', ?ex_body).
--record('BAD_OPERATION', ?ex_body).
--record('NO_RESOURCES', ?ex_body).
--record('NO_RESPONSE', ?ex_body).
--record('PERSIST_STORE', ?ex_body).
--record('BAD_INV_ORDER', ?ex_body).
--record('TRANSIENT', ?ex_body).
--record('FREE_MEM', ?ex_body).
--record('INV_IDENT', ?ex_body).
--record('INV_FLAG', ?ex_body).
--record('INTF_REPOS', ?ex_body).
--record('BAD_CONTEXT', ?ex_body).
--record('OBJ_ADAPTER', ?ex_body).
--record('DATA_CONVERSION', ?ex_body).
--record('OBJECT_NOT_EXIST', ?ex_body).
--record('TRANSACTION_REQUIRED', ?ex_body).
--record('TRANSACTION_ROLLEDBACK', ?ex_body).
--record('INVALID_TRANSACTION', ?ex_body).
--record('INV_POLICY', ?ex_body).
--record('CODESET_INCOMPATIBLE', ?ex_body).
--record('REBIND', ?ex_body).
--record('TIMEOUT', ?ex_body).
--record('TRANSACTION_UNAVAILABLE', ?ex_body).
--record('TRANSACTION_MODE', ?ex_body).
--record('BAD_QOS', ?ex_body).
-
-%% Defines for the enum exception_type (is also used for reply_status)
--define(NO_EXCEPTION, 'no_exception').
--define(USER_EXCEPTION, 'user_exception').
--define(SYSTEM_EXCEPTION, 'system_exception').
-
-%% Defines for the enum completion_status.
--define(COMPLETED_YES, 'COMPLETED_YES').
--define(COMPLETED_NO, 'COMPLETED_NO').
--define(COMPLETED_MAYBE, 'COMPLETED_MAYBE').
-
-
--undef(ex_body).
-
-
--endif.
diff --git a/lib/orber/include/ifr_types.hrl b/lib/orber/include/ifr_types.hrl
deleted file mode 100644
index ceb8bbe885..0000000000
--- a/lib/orber/include/ifr_types.hrl
+++ /dev/null
@@ -1,73 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : ifr_types.hrl
-%% Purpose : Record definitions for structs used in the interface repository
-%%----------------------------------------------------------------------
-
-
-%%%----------------------------------------------------------------------
-%%% *********************************************************************
-%%% * *
-%%% * PLEASE NOTE *
-%%% * *
-%%% * If a record is removed or added in this file, select/2 in *
-%%% * orber_ifr.erl _MUST_ be updated accordingly. *
-%%% * *
-%%% *********************************************************************
-%%%----------------------------------------------------------------------
-
--record(contained_description, {kind, value}).
-
--record(structmember, {name, type, type_def}).
-
--record(unionmember, {name, label, type, type_def}).
-
--record(container_description, {contained_object, kind, value}).
-
--record(moduledescription, {name, id, defined_in, version}).
-
--record(constantdescription, {name, id, defined_in, version, type, value}).
-
--record(typedescription, {name, id, defined_in, version, type}).
-
--define(make_typedescription(Obj,Object_type),
- #typedescription{name = Obj#Object_type.name,
- id = Obj#Object_type.id,
- defined_in = Obj#Object_type.defined_in,
- version = Obj#Object_type.version,
- type = Obj#Object_type.type}).
-
--record(exceptiondescription, {name, id, defined_in, version, type}).
-
--record(attributedescription, {name, id, defined_in, version, type, mode}).
-
--record(parameterdescription, {name, type, type_def, mode}).
-
--record(operationdescription, {name, id, defined_in, version, result, mode,
- contexts, parameters, exceptions}).
-
--record(fullinterfacedescription, {name, id, defined_in, version, operations,
- attributes, base_interfaces, type}).
-
--record(interfacedescription, {name, id, defined_in, version,
- base_interfaces}).
diff --git a/lib/orber/include/orber_pi.hrl b/lib/orber/include/orber_pi.hrl
deleted file mode 100644
index 7d1fa1edf2..0000000000
--- a/lib/orber/include/orber_pi.hrl
+++ /dev/null
@@ -1,77 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_pi.hrl
-%% Purpose :
-%%----------------------------------------------------------------------
-
-%%=============== CONSTANTS ==================================
-%%-------- PortableInterceptor::Interceptor (local) ----------
-%% Reply Status
--define('PortableInterceptor_SUCCESSFUL', 0).
--define('PortableInterceptor_SYSTEM_EXCEPTION', 1).
--define('PortableInterceptor_USER_EXCEPTION', 2).
--define('PortableInterceptor_LOCATION_FORWARD', 3).
--define('PortableInterceptor_LOCATION_FORWARD_PERMANENT', 4).
--define('PortableInterceptor_TRANSPORT_RETRY', 5).
-
-
-%%=============== EXCEPTIONS =================================
-%%-------- PortableInterceptor::Interceptor (local) ----------
-%% forward eq. CORBA::Object, premanent eq. boolean
--record('PortableInterceptor_ForwardRequest', {'OE_ID'="local", forward, permanent}).
--record('PortableInterceptor_InvalidSlot', {'OE_ID'="local"}).
-
-%%--------------- IOP_N::Codec (local) -----------------------
--record('IOP_N_Codec_InvalidTypeForEncoding', {'OE_ID'="local"}).
--record('IOP_N_Codec_FormatMismatch', {'OE_ID'="local"}).
--record('IOP_N_Codec_TypeMismatch', {'OE_ID'="local"}).
-
-%%--------------- IOP_N (Module level) -----------------------
--define('IOP_N_ENCODING_CDR_ENCAPS', 0).
-
-%%--------------- IOP_N::CodecFactory (Module level) ---------
--record('IOP_N_CodecFactory_UnknownEncoding', {'OE_ID'="local"}).
-
-%%--------------- IOP_N::ORBInitInfo (Module level) ----------
-%% name eq. string()
--record('PortableInterceptor_ORBInitInfo_DuplicateName', {'OE_ID'="local", name}).
--record('PortableInterceptor_ORBInitInfo_InvalidName', {'OE_ID'="local"}).
-
-
-%%=============== DATA STRUCTURES ============================
-%%--------------- IOP_N (Module level) -----------------------
--record('IOP_N_Encoding',
- {format, %% Currently only 'IOP_N_ENCODING_CDR_ENCAPS' allowed.
- major_version, %% 1 only
- minor_version}). %% 0,1 or 2
-
-
-%%--------------- Dynamic (Module level) ---------------------
-%% argument eq. #any{},
-%% mode eq. CORBA::ParameterMode - PARAM_IN, PARAM_OUT, PARAM_INOUT.
--record('Dynamic_Parameter',
- {argument,
- mode}).
-
-%%--------------- END OF MODULE ------------------------------
-
diff --git a/lib/orber/info b/lib/orber/info
deleted file mode 100644
index c92ea38dd8..0000000000
--- a/lib/orber/info
+++ /dev/null
@@ -1,2 +0,0 @@
-group: orb
-short: A CORBA Object Request Broker
diff --git a/lib/orber/java_src/Makefile b/lib/orber/java_src/Makefile
deleted file mode 100644
index d8a8843d00..0000000000
--- a/lib/orber/java_src/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(ORBER_VSN)
-
-# ----------------------------------------------------
-# Common Macros
-# ----------------------------------------------------
-
-SUB_DIRECTORIES = Orber
-
-SPECIAL_TARGETS =
-
-# ----------------------------------------------------
-# Default Subdir Targets
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_subdir.mk
-
diff --git a/lib/orber/java_src/Orber/InitialReference.java b/lib/orber/java_src/Orber/InitialReference.java
deleted file mode 100644
index 35a8c2437b..0000000000
--- a/lib/orber/java_src/Orber/InitialReference.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 1997-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
- */
-/**
- * InitialReference is a class which generates the INIT reference
- * which can be used by the InitialReferences interface.
- */
-package Orber;
-
-public class InitialReference
-{
-
- /**
- * Constructor.
- */
- public InitialReference(){;}
-
- /**
- * Returns the stringified objectreference to the initial reference server
- */
- public String stringified_ior(String host, int port)
- {
- String iorByteString;
- String profileData;
- String iorString;
-
- // byte_order followed by ' {"", [{0, '
- // char iorBytesFirstPart[] = {0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0};
- char iorBytesFirstPart[] = {0,0,0,0,0,0,0,32,73,68,76,58,79,114,98,101,114,47,73,110,105,116,105,97,108,82,101,102,101,114,101,110,99,101,115,58,49,46,48,0,0,0,0,1,0,0,0,0};
- // the objectkey "INIT
- char iorBytesLastPart[] = {0,0,0,4,73,78,73,84};
-
- // Fix the ProfileData struct.
- char pdPrefix[] = {0,1,0,0};
- char nullbyte[] = {0};
- profileData = new String(pdPrefix) + enc_ulong(host.length() + 1) + host + new String(nullbyte);
- profileData = align(profileData, 2);
- profileData += enc_ushort(port);
- profileData = align(profileData, 4);
- profileData += new String(iorBytesLastPart);
- // Fix the whole IOR
- iorByteString = new String(iorBytesFirstPart) + enc_ulong(profileData.length()) +
- profileData;
-
- // System.out.print("Start[" + profileData.length() + "]");
- // System.out.print("[");
- // for(int x = 0; x < iorByteString.length(); x++)
- // {
- // System.out.print((int) iorByteString.charAt(x) + ",");
- // }
- // System.out.println("]");
-
- iorString = createIOR(iorByteString);
- // System.out.println(iorString);
- return iorString;
- }
-
-
- private String enc_ushort(int s)
- {
- char byteArray[] = {(char) ((s >>> 8) & 0xFF),
- (char) ((s >>> 0) & 0xFF)};
-
- return new String(byteArray);
- }
-
- private String enc_ulong(int l)
- {
- char byteArray[] = {(char) ((l >>> 24) & 0xFF),
- (char) ((l >>> 16) & 0xFF),
- (char) ((l >>> 8) & 0xFF),
- (char) ((l >>> 0) & 0xFF)};
-
- return new String(byteArray);
-
- }
-
- private String createIOR(String bytes)
- {
- int i;
- StringBuffer sb = new StringBuffer("IOR:");
-
- for(i = 0; i < bytes.length(); i++)
- {
- int b = bytes.charAt(i);
- if(b<0) b+= 256;
- int n1 = b / 16;
- int n2 = b % 16;
- int c1 = (n1 < 10) ? ('0' + n1) : ('a' + (n1 - 10));
- int c2 = (n2 < 10) ? ('0' + n2) : ('a' + (n2 - 10));
- sb.append((char)c1);
- sb.append((char)c2);
- }
-
- return sb.toString();
- }
-
- private String align(String buffer, int alignment)
- {
- String s = buffer;
- char nullbyte[] = {0};
-
- int remainder = alignment - (buffer.length() % alignment);
- if (remainder == alignment) return s;
-
- for (int i = 0; i < remainder; i++)
- {
- s += new String(nullbyte);
- }
- return s;
- }
-
-
-}
diff --git a/lib/orber/java_src/Orber/Makefile b/lib/orber/java_src/Orber/Makefile
deleted file mode 100644
index 3414fb2e76..0000000000
--- a/lib/orber/java_src/Orber/Makefile
+++ /dev/null
@@ -1,71 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(ORBER_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/orber-$(VSN)
-
-#
-# JAVA macros
-#
-JAVA_CLASSES = \
- InitialReference
-
-JAVA_FILES= $(JAVA_CLASSES:%=%.java)
-
-CLASSPATH = ../..
-
-# ----------------------------------------------------
-# Flags
-# ----------------------------------------------------
-JAVA_OPTIONS =
-
-# ----------------------------------------------------
-# Make Rules
-# ----------------------------------------------------
-
-debug opt:
-
-clean:
-
-docs:
-
-# ----------------------------------------------------
-# Release Targets
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/java_src/Orber"
- $(INSTALL_DATA) $(JAVA_FILES) "$(RELSYSDIR)/java_src/Orber"
-
-release_docs_spec:
-
diff --git a/lib/orber/prebuild.skip b/lib/orber/prebuild.skip
deleted file mode 100644
index d6c7895b9c..0000000000
--- a/lib/orber/prebuild.skip
+++ /dev/null
@@ -1,5 +0,0 @@
-priv
-src/PKIXAttributeCertificate.asn1db
-src/PKIX1Explicit88.asn1db
-src/OrberCSIv2.asn1db
-src/PKIX1Implicit88.asn1db
diff --git a/lib/orber/priv/Makefile b/lib/orber/priv/Makefile
deleted file mode 100644
index 268c16c4c7..0000000000
--- a/lib/orber/priv/Makefile
+++ /dev/null
@@ -1,67 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2001-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-include ../vsn.mk
-VSN = $(ORBER_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/orber-$(VSN)
-
-#
-# Macros
-#
-HELP_FILES = \
- orber_help.txt
-
-HTML_FILES = \
- orber.tool \
- blank.html \
- info_frames.html \
- main_frame.html \
- start_info.html
-
-#
-# Rules
-#
-
-debug opt:
-
-docs:
-
-clean:
-
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/priv"
- $(INSTALL_DATA) $(HELP_FILES) $(HTML_FILES) "$(RELSYSDIR)/priv"
-
-release_docs_spec:
-
-
diff --git a/lib/orber/priv/Orber/.gitignore b/lib/orber/priv/Orber/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/orber/priv/Orber/.gitignore
+++ /dev/null
diff --git a/lib/orber/priv/bin/.gitignore b/lib/orber/priv/bin/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/orber/priv/bin/.gitignore
+++ /dev/null
diff --git a/lib/orber/priv/blank.html b/lib/orber/priv/blank.html
deleted file mode 100644
index 44e86908a0..0000000000
--- a/lib/orber/priv/blank.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<HTML>
-<HEAD></HEAD>
-<BODY BGCOLOR="#FFFFFF">
-&nbsp;
-</BODY>
-</HTML> \ No newline at end of file
diff --git a/lib/orber/priv/info_frames.html b/lib/orber/priv/info_frames.html
deleted file mode 100644
index 75456a67a4..0000000000
--- a/lib/orber/priv/info_frames.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>OrberWeb</TITLE>
-</HEAD>
-<FRAMESET ROWS="85%,15%" BORDER="0">
-<FRAME NAME="main" SRC="./start_info.html">
-<FRAME NAME="proc_data" SRC="./blank.html">
-</FRAMESET>
-</HTML> \ No newline at end of file
diff --git a/lib/orber/priv/main_frame.html b/lib/orber/priv/main_frame.html
deleted file mode 100644
index 056a92812e..0000000000
--- a/lib/orber/priv/main_frame.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>OrberWeb</TITLE>
-</HEAD>
-<FRAMESET COLS="15%,85%" >
- <FRAME NAME="left" SRC="/orber_erl/orber_web_server/menu">
- <FRAME NAME="main" SRC="./info_frames.html">
-</FRAMESET>
-</HTML> \ No newline at end of file
diff --git a/lib/orber/priv/obj/.gitignore b/lib/orber/priv/obj/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/orber/priv/obj/.gitignore
+++ /dev/null
diff --git a/lib/orber/priv/orber.tool b/lib/orber/priv/orber.tool
deleted file mode 100644
index 910a7d7e45..0000000000
--- a/lib/orber/priv/orber.tool
+++ /dev/null
@@ -1,2 +0,0 @@
-{version,"1.2"}.
-[{config_func,{orber_web_server,config_data,[]}}].
diff --git a/lib/orber/priv/orber_help.txt b/lib/orber/priv/orber_help.txt
deleted file mode 100644
index a6580dc30a..0000000000
--- a/lib/orber/priv/orber_help.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-
- Help for the Orber administration tool
- --------------------------------------
-
-
-
-
-
- The purpose of this tool is to supply an easy way to
- access Orber nodes and via a GUI explore:
- - NameService
- - Configuration settings
- - Interface Repository
-
- All nodes that are known to this tool is shown in the node
- window, normally this is all Erlang nodes visible with the
- [node()|nodes()] commands.
-
-
-The Node window
----------------
-
- The node window monitor nodes.
-
-
-Technical Detail
-----------------
-
- Trouble shooting
- ----------------
-
- Q. Why doesn't all my nodes show up in the node window?
-
- A. Are the nodes visible with the [node()|nodes()] commands
- in the shell? If not you must do net:ping(NodeName) to add
- nodes to the Erlang distribution.
-
- Q. When trying to access a node I get no valid response?
-
- A. Make sure that Orber is running on the node.
diff --git a/lib/orber/priv/start_info.html b/lib/orber/priv/start_info.html
deleted file mode 100644
index 0ad521c90a..0000000000
--- a/lib/orber/priv/start_info.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<HTML>
-<HEAD>
-</HEAD>
-<BODY BGCOLOR="#FFFFFF">
-<TABLE WIDTH=100% HEIGHT=100%>
-<TR VALIGN="middle">
-<TD ALIGN="center">
-
-<TABLE WIDTH="60%">
-<TR>
-<TD ALIGN="center">
-<FONT SIZE=6>Welcome to the Web based Orber Admin Tool
-</FONT></TD>
-</TR>
-
-<TR>
-<TD><BR><BR><BR><BR>
-</TD>
-</TR>
-
-<TR>
-<TD ALIGN="center">&nbsp;
-</TD>
-</TR>
-</TABLE>
-
-</TD>
-</TR>
-</TABLE>
-</BODY>
-</HTML> \ No newline at end of file
diff --git a/lib/orber/src/CORBA.idl b/lib/orber/src/CORBA.idl
deleted file mode 100644
index 3cd8790f49..0000000000
--- a/lib/orber/src/CORBA.idl
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef _CORBA_IDL
-#define _CORBA_IDL
-
-#pragma prefix "omg.org"
-
-//******************************************************************
-//
-//Policy Object:
-//
-//******************************************************************
-
-module CORBA {
-
- // Policy typedefs
- typedef unsigned long PolicyType;
- typedef string Identifier;
- typedef string ScopedName;
- typedef string RepositoryId;
-
-};
-
-#endif
diff --git a/lib/orber/src/Makefile b/lib/orber/src/Makefile
deleted file mode 100644
index 7fec29a000..0000000000
--- a/lib/orber/src/Makefile
+++ /dev/null
@@ -1,263 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/orber-$(ORBER_VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-
-MODULES= \
- orber \
- corba \
- corba_boa \
- corba_object \
- any \
- iop_ior \
- orber_tc \
- orber_typedefs \
- orber_request_number \
- orber_objectkeys \
- orber_initial_references \
- cdrlib \
- cdr_encode \
- cdr_decode \
- orber_iiop \
- orber_iiop_net \
- orber_iiop_net_accept \
- orber_iiop_insup \
- orber_iiop_inproxy \
- orber_iiop_inrequest \
- orber_iiop_pm \
- orber_iiop_outsup \
- orber_iiop_outproxy \
- orber_iiop_socketsup \
- orber_socket \
- orber_ifr \
- orber_ifr_aliasdef \
- orber_ifr_arraydef \
- orber_ifr_attributedef \
- orber_ifr_constantdef \
- orber_ifr_contained \
- orber_ifr_container \
- orber_ifr_enumdef \
- orber_ifr_exceptiondef \
- orber_ifr_idltype \
- orber_ifr_interfacedef \
- orber_ifr_irobject \
- orber_ifr_moduledef \
- orber_ifr_operationdef \
- orber_ifr_orb \
- orber_ifr_primitivedef \
- orber_ifr_repository \
- orber_ifr_sequencedef \
- orber_ifr_stringdef \
- orber_ifr_wstringdef \
- orber_ifr_structdef \
- orber_ifr_typecode \
- orber_ifr_typedef \
- orber_ifr_uniondef \
- orber_ifr_fixeddef \
- orber_ifr_utils \
- OrberApp_IFR_impl \
- orber_pi \
- orber_web \
- orber_web_server \
- orber_iiop_tracer \
- orber_iiop_tracer_silent \
- orber_iiop_tracer_stealth \
- fixed \
- orber_exceptions \
- orber_diagnostics \
- orber_acl \
- orber_env \
- orber_tb
-
-ASN_MODULES = OrberCSIv2
-ASN_SET = $(ASN_MODULES:%=%.set.asn)
-ASN_ASNS = $(ASN_MODULES:%=%.asn1)
-GEN_ASN_ERL = $(ASN_MODULES:%=%.erl)
-GEN_ASN_HRL = $(ASN_MODULES:%=%.hrl)
-GEN_ASN_DBS = $(ASN_MODULES:%=%.asn1db)
-GEN_ASN_TABLES = $(ASN_MODULES:%=%.table)
-
-PKIX_FILES = \
- OrberCSIv2.asn1 \
- PKIXAttributeCertificate.asn1 \
- PKIX1Explicit88.asn1 \
- PKIX1Algorithms88.asn1 \
- PKIX1Implicit88.asn1 \
- OrberCSIv2.set.asn
-
-EXTERNAL_HRL_FILES= ../include/corba.hrl \
- ../include/ifr_types.hrl \
- ../include/orber_pi.hrl
-
-INTERNAL_HRL_FILES = \
- orber_iiop.hrl \
- ifr_objects.hrl \
- orber_ifr.hrl
-
-ERL_FILES= $(MODULES:%=%.erl)
-
-GEN_ERL_FILES1 = \
- oe_erlang.erl \
- erlang_pid.erl \
- erlang_port.erl \
- erlang_ref.erl \
- erlang_binary.erl
-
-GEN_ERL_FILES2 = \
- oe_CORBA.erl
-
-GEN_ERL_FILES3 = \
- oe_OrberIFR.erl \
- OrberApp_IFR.erl
-
-GEN_ERL_FILES = $(GEN_ERL_FILES1) $(GEN_ERL_FILES2) \
- $(GEN_ERL_FILES3) \
-# $(GEN_ASN_ERL)
-
-GEN_HRL_FILES1 = \
- oe_erlang.hrl \
- erlang.hrl
-
-GEN_HRL_FILES2 = \
- CORBA.hrl \
- oe_CORBA.hrl
-
-GEN_HRL_FILES3 = \
- OrberApp_IFR.hrl \
- oe_OrberIFR.hrl \
- OrberApp.hrl
-
-GEN_HRL_FILES_EXT = $(GEN_HRL_FILES1)
-
-GEN_HRL_FILES_LOC = $(GEN_HRL_FILES2) $(GEN_HRL_FILES3) \
-# $(GEN_ASN_HRL)
-
-
-GEN_FILES = \
- $(GEN_ERL_FILES) \
- $(GEN_HRL_FILES_LOC) \
- $(GEN_HRL_FILES_EXT) \
-# $(GEN_ASN_DBS) \
-# $(GEN_ASN_TABLES)
-
-TARGET_FILES = \
- $(GEN_ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR)) \
- $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-
-APPUP_FILE = orber.appup
-APPUP_SRC = $(APPUP_FILE).src
-APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
-
-APP_FILE = orber.app
-APP_SRC = $(APP_FILE).src
-APP_TARGET = $(EBIN)/$(APP_FILE)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/orber/ebin
-# The -pa option is just used temporary until erlc can handle
-# includes from other directories than ../include .
-ERL_COMPILE_FLAGS += $(ERL_IDL_FLAGS) \
- -I$(ERL_TOP)/lib/orber/include \
- +'{parse_transform,sys_pre_attributes}' \
- +'{attribute,insert,app_vsn,"orber_$(ORBER_VSN)"}'
-
-ASN_FLAGS = -bber +der +compact_bit_string +nowarn_unused_record
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-debug:
- @${MAKE} TYPE=debug opt
-
-opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
-
-clean:
- rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET) IDL-GENERATED
- rm -f errs core *~
-
-$(APP_TARGET): $(APP_SRC) ../vsn.mk
- $(vsn_verbose)sed -e 's;%VSN%;$(ORBER_VSN);' $< > $@
-
-$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
- $(vsn_verbose)sed -e 's;%VSN%;$(ORBER_VSN);' $< > $@
-
-docs:
-
-# ----------------------------------------------------
-# Special Build Targets
-# ----------------------------------------------------
-
-IDL-GENERATED: $(ERL_TOP)/lib/ic/include/erlang.idl CORBA.idl OrberIFR.idl
- $(gen_verbose)erlc $(ERL_IDL_FLAGS) $(ERL_TOP)/lib/ic/include/erlang.idl
- $(V_at)erlc $(ERL_IDL_FLAGS) CORBA.idl
- $(V_at)erlc $(ERL_IDL_FLAGS) +'{this,"Orber::IFR"}' OrberIFR.idl
- $(V_at)>IDL-GENERATED
-
-$(GEN_ERL_FILES): IDL-GENERATED
-$(TARGET_FILES): IDL-GENERATED
-
-$(GEN_ASN_ERL) $(GEN_ASN_HRL): OrberCSIv2.asn1 OrberCSIv2.set.asn
- $(asn_verbose)erlc $(ERL_COMPILE_FLAGS) $(ASN_FLAGS) +'{inline,"OrberCSIv2"}' OrberCSIv2.set.asn
- $(V_at)rm -f $(GEN_ASN_ERL:%.erl=%.beam)
-
-# erlc $(ERL_COMPILE_FLAGS) $(ASN_FLAGS) OrberCSIv2.asn1 ;\
-# erlc $(GEN_ASN_ERL)
-# Use the following when we safely can inline the ASN1 runtime code.
-# Requires igor (part of syntax_tools (introduced in R10B
-# erlc $(ERL_COMPILE_FLAGS) $(ASN_FLAGS) +'{inline,"OrberCSIv2"}' OrberCSIv2.set.asn ; \
-
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-
-release_spec: opt
- $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
- $(INSTALL_DIR) "$(RELSYSDIR)/src"
- $(INSTALL_DATA) $(ERL_FILES) $(YRL_FILE) $(GEN_HRL_FILES_LOC) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src"
- $(INSTALL_DIR) "$(RELSYSDIR)/include"
- $(INSTALL_DATA) $(EXTERNAL_HRL_FILES) $(GEN_HRL_FILES_EXT) "$(RELSYSDIR)/include"
-
-
-release_docs_spec:
-
-
diff --git a/lib/orber/src/OrberApp_IFR_impl.erl b/lib/orber/src/OrberApp_IFR_impl.erl
deleted file mode 100644
index 069f4ad17a..0000000000
--- a/lib/orber/src/OrberApp_IFR_impl.erl
+++ /dev/null
@@ -1,102 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File : OrberApp_IFR_impl.erl
-%% Purpose :
-%%-----------------------------------------------------------------
-
--module('OrberApp_IFR_impl').
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/include/ifr_types.hrl").
--include_lib("orber/include/corba.hrl").
-
-%%--------------- IMPORTS ------------------------------------
-
-%%--------------- EXPORTS ------------------------------------
-%% External
--export([get_absolute_name/3, get_user_exception_type/3]).
-
-%%--------------- gen_server specific exports ----------------
--export([init/1, terminate/2, code_change/3]).
-
-%%--------------- LOCAL DEFINITIONS --------------------------
--define(DEBUG_LEVEL, 6).
-
-
-init(State) ->
- {ok, State}.
-terminate(_Reason, _State) ->
- ok.
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%-----------------------------------------------------------
-%%------- Exported external functions -----------------------
-%%-----------------------------------------------------------
-%%----------------------------------------------------------%
-%% function : get_absolute_name
-%% Arguments: TypeID - string()
-%% Returns : Fully scooped name - string()
-%%-----------------------------------------------------------
-
-get_absolute_name(_OE_THIS, _State, []) ->
- orber:dbg("[~p] OrberApp_IFR_impl:get_absolute_name(); no TypeID supplied.",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 11), completion_status=?COMPLETED_MAYBE});
-
-get_absolute_name(_OE_THIS, State, TypeID) ->
- Rep = orber_ifr:find_repository(),
- Key = orber_ifr:'Repository_lookup_id'(Rep, TypeID),
- [$:, $: |N] = orber_ifr:'Contained__get_absolute_name'(Key),
- {reply, change_colons_to_underscore(N, []), State}.
-
-change_colons_to_underscore([$:, $: | T], Acc) ->
- change_colons_to_underscore(T, [$_ |Acc]);
-change_colons_to_underscore([H |T], Acc) ->
- change_colons_to_underscore(T, [H |Acc]);
-change_colons_to_underscore([], Acc) ->
- lists:reverse(Acc).
-
-%%----------------------------------------------------------%
-%% function : get_user_exception_type
-%% Arguments: TypeID - string()
-%% Returns : Fully scooped name - string()
-%%-----------------------------------------------------------
-
-get_user_exception_type(_OE_THIS, _State, []) ->
- orber:dbg("[~p] OrberApp_IFR_impl:get_user_exception_type(); no TypeID supplied.",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 11), completion_status=?COMPLETED_MAYBE});
-
-get_user_exception_type(_OE_THIS, State, TypeId) ->
- Rep = orber_ifr:find_repository(),
- ExceptionDef = orber_ifr:'Repository_lookup_id'(Rep, TypeId),
- ContainedDescr = orber_ifr_exceptiondef:describe(ExceptionDef),
- ExceptionDescr = ContainedDescr#contained_description.value,
- {reply, ExceptionDescr#exceptiondescription.type, State}.
-
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-%%--------------- MISC FUNCTIONS, E.G. DEBUGGING -------------
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/orber/src/OrberCSIv2.asn1 b/lib/orber/src/OrberCSIv2.asn1
deleted file mode 100644
index d776ce2b47..0000000000
--- a/lib/orber/src/OrberCSIv2.asn1
+++ /dev/null
@@ -1,45 +0,0 @@
-OrberCSIv2 DEFINITIONS ::=
-
-BEGIN
-
- IMPORTS
-
- -- IMPORTed module OIDs MAY change if [PKIXPROF] changes
- -- PKIX1Explicit88 Certificate Extensions
- Certificate
- FROM PKIX1Explicit88 {iso(1) identified-organization(3)
- dod(6) internet(1) security(5) mechanisms(5)
- pkix(7) id-mod(0) id-pkix1-explicit-88(1)}
- -- PKIXAttributeCertificate
- AttributeCertificate
- FROM PKIXAttributeCertificate {iso(1) identified-organization(3) dod(6)
- internet(1) security(5) mechanisms(5) pkix(7) id-mod(0)
- id-mod-attribute-cert(12)};
-
-
-
- -- Authorization Token
- -- AttributeCertificate - [IETF ID PKIXAC].
- -- Certificate - [IETF RFC 2459].
-
- VerifyingCertChain ::= SEQUENCE OF Certificate
-
- AttributeCertChain ::= SEQUENCE {
- attributeCert AttributeCertificate,
- certificateChain VerifyingCertChain
- }
-
-
- -- The ASN.1 encoding of identity tokens of this type is defined
- -- as follows (ITTX509CertChain):
- CertificateChain ::= SEQUENCE SIZE (1..MAX) OF Certificate
-
-
- -- The object identifier allocated for the GSSUP mechanism is defined as follows:
- -- GSS Exported Name Object Form for GSSUP Mechanism
- gssup-mechanism OBJECT IDENTIFIER ::= { iso-itu-t (2) international-organization (23) omg (130) security (1) authentication (1) gssup-mechanism (1) }
-
- -- Scoped-Username GSS Name Form
- scoped-username OBJECT IDENTIFIER ::= { iso-itu-t (2) international-organization (23) omg (130) security (1) naming (2) scoped-username(1) }
-
-END
diff --git a/lib/orber/src/OrberCSIv2.set.asn b/lib/orber/src/OrberCSIv2.set.asn
deleted file mode 100644
index 11fbcc167f..0000000000
--- a/lib/orber/src/OrberCSIv2.set.asn
+++ /dev/null
@@ -1,5 +0,0 @@
-OrberCSIv2.asn1
-PKIXAttributeCertificate.asn1
-PKIX1Explicit88.asn1
-PKIX1Algorithms88.asn1
-PKIX1Implicit88.asn1
diff --git a/lib/orber/src/OrberIFR.idl b/lib/orber/src/OrberIFR.idl
deleted file mode 100644
index 6d53217658..0000000000
--- a/lib/orber/src/OrberIFR.idl
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _ORBER_IFR_IDL
-#define _ORBER_IFR_IDL
-
-module OrberApp
-{
- interface IFR {
- string get_absolute_name(in string TypeID);
- CORBA::TypeCode get_user_exception_type(in string TypeID);
- };
-};
-
-#endif
diff --git a/lib/orber/src/PKIX1Algorithms88.asn1 b/lib/orber/src/PKIX1Algorithms88.asn1
deleted file mode 100644
index e78de69b0e..0000000000
--- a/lib/orber/src/PKIX1Algorithms88.asn1
+++ /dev/null
@@ -1,274 +0,0 @@
- PKIX1Algorithms88 { iso(1) identified-organization(3) dod(6)
- internet(1) security(5) mechanisms(5) pkix(7) id-mod(0)
- id-mod-pkix1-algorithms(17) }
-
- DEFINITIONS EXPLICIT TAGS ::= BEGIN
-
- -- EXPORTS All;
-
- -- IMPORTS NONE;
-
- --
- -- One-way Hash Functions
- --
-
- md2 OBJECT IDENTIFIER ::= {
- iso(1) member-body(2) us(840) rsadsi(113549)
- digestAlgorithm(2) 2 }
-
- md5 OBJECT IDENTIFIER ::= {
- iso(1) member-body(2) us(840) rsadsi(113549)
- digestAlgorithm(2) 5 }
-
- id-sha1 OBJECT IDENTIFIER ::= {
- iso(1) identified-organization(3) oiw(14) secsig(3)
- algorithms(2) 26 }
-
- --
- -- DSA Keys and Signatures
- --
-
- -- OID for DSA public key
-
- id-dsa OBJECT IDENTIFIER ::= {
- iso(1) member-body(2) us(840) x9-57(10040) x9algorithm(4) 1 }
-
- -- encoding for DSA public key
-
- DSAPublicKey ::= INTEGER -- public key, y
-
- Dss-Parms ::= SEQUENCE {
- p INTEGER,
- q INTEGER,
- g INTEGER }
-
- -- OID for DSA signature generated with SHA-1 hash
-
- id-dsa-with-sha1 OBJECT IDENTIFIER ::= {
- iso(1) member-body(2) us(840) x9-57 (10040) x9algorithm(4) 3 }
-
- -- encoding for DSA signature generated with SHA-1 hash
-
- Dss-Sig-Value ::= SEQUENCE {
- r INTEGER,
- s INTEGER }
-
- --
- -- RSA Keys and Signatures
- --
-
- -- arc for RSA public key and RSA signature OIDs
-
- pkcs-1 OBJECT IDENTIFIER ::= {
- iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
-
- -- OID for RSA public keys
-
- rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 }
-
- -- OID for RSA signature generated with MD2 hash
-
- md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 }
-
- -- OID for RSA signature generated with MD5 hash
-
- md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 }
-
- -- OID for RSA signature generated with SHA-1 hash
-
- sha1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 }
-
- -- encoding for RSA public key
-
- RSAPublicKey ::= SEQUENCE {
- modulus INTEGER, -- n
- publicExponent INTEGER } -- e
-
- --
- -- Diffie-Hellman Keys
- --
-
- dhpublicnumber OBJECT IDENTIFIER ::= {
- iso(1) member-body(2) us(840) ansi-x942(10046)
- number-type(2) 1 }
-
- -- encoding for DSA public key
-
- DHPublicKey ::= INTEGER -- public key, y = g^x mod p
-
- DomainParameters ::= SEQUENCE {
- p INTEGER, -- odd prime, p=jq +1
- g INTEGER, -- generator, g
- q INTEGER, -- factor of p-1
- j INTEGER OPTIONAL, -- subgroup factor, j>= 2
- validationParms ValidationParms OPTIONAL }
-
- ValidationParms ::= SEQUENCE {
- seed BIT STRING,
- pgenCounter INTEGER }
-
- --
- -- KEA Keys
- --
-
- id-keyExchangeAlgorithm OBJECT IDENTIFIER ::=
- { 2 16 840 1 101 2 1 1 22 }
-
- KEA-Parms-Id ::= OCTET STRING
-
- --
- -- Elliptic Curve Keys, Signatures, and Curves
- --
-
- ansi-X9-62 OBJECT IDENTIFIER ::= {
- iso(1) member-body(2) us(840) 10045 }
-
- FieldID ::= SEQUENCE { -- Finite field
- fieldType OBJECT IDENTIFIER,
- parameters ANY DEFINED BY fieldType }
-
- -- Arc for ECDSA signature OIDS
-
- id-ecSigType OBJECT IDENTIFIER ::= { ansi-X9-62 signatures(4) }
-
- -- OID for ECDSA signatures with SHA-1
-
- ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { id-ecSigType 1 }
-
- -- OID for an elliptic curve signature
- -- format for the value of an ECDSA signature value
-
- ECDSA-Sig-Value ::= SEQUENCE {
- r INTEGER,
- s INTEGER }
-
- -- recognized field type OIDs are defined in the following arc
-
- id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1) }
-
- -- where fieldType is prime-field, the parameters are of type Prime-p
-
- prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 }
-
- Prime-p ::= INTEGER -- Finite field F(p), where p is an odd prime
-
- -- where fieldType is characteristic-two-field, the parameters are
- -- of type Characteristic-two
-
- characteristic-two-field OBJECT IDENTIFIER ::= { id-fieldType 2 }
-
- Characteristic-two ::= SEQUENCE {
- m INTEGER, -- Field size 2^m
- basis OBJECT IDENTIFIER,
- parameters ANY DEFINED BY basis }
-
- -- recognized basis type OIDs are defined in the following arc
-
- id-characteristic-two-basis OBJECT IDENTIFIER ::= {
- characteristic-two-field basisType(3) }
-
- -- gnbasis is identified by OID gnBasis and indicates
- -- parameters are NULL
-
- gnBasis OBJECT IDENTIFIER ::= { id-characteristic-two-basis 1 }
-
- -- parameters for this basis are NULL
-
- -- trinomial basis is identified by OID tpBasis and indicates
- -- parameters of type Pentanomial
-
- tpBasis OBJECT IDENTIFIER ::= { id-characteristic-two-basis 2 }
-
- -- Trinomial basis representation of F2^m
- -- Integer k for reduction polynomial xm + xk + 1
-
- Trinomial ::= INTEGER
-
- -- for pentanomial basis is identified by OID ppBasis and indicates
- -- parameters of type Pentanomial
-
- ppBasis OBJECT IDENTIFIER ::= { id-characteristic-two-basis 3 }
-
- -- Pentanomial basis representation of F2^m
- -- reduction polynomial integers k1, k2, k3
- -- f(x) = x**m + x**k3 + x**k2 + x**k1 + 1
-
- Pentanomial ::= SEQUENCE {
- k1 INTEGER,
- k2 INTEGER,
- k3 INTEGER }
-
- -- The object identifiers gnBasis, tpBasis and ppBasis name
- -- three kinds of basis for characteristic-two finite fields
-
- FieldElement ::= OCTET STRING -- Finite field element
-
- ECPoint ::= OCTET STRING -- Elliptic curve point
-
- -- Elliptic Curve parameters may be specified explicitly,
- -- specified implicitly through a "named curve", or
- -- inherited from the CA
-
- EcpkParameters ::= CHOICE {
- ecParameters ECParameters,
- namedCurve OBJECT IDENTIFIER,
- implicitlyCA NULL }
-
- ECParameters ::= SEQUENCE { -- Elliptic curve parameters
- version ECPVer,
- fieldID FieldID,
- curve Curve,
- base ECPoint, -- Base point G
- order INTEGER, -- Order n of the base point
- cofactor INTEGER OPTIONAL } -- The integer h = #E(Fq)/n
-
- ECPVer ::= INTEGER {ecpVer1(1)}
-
- Curve ::= SEQUENCE {
- a FieldElement, -- Elliptic curve coefficient a
- b FieldElement, -- Elliptic curve coefficient b
- seed BIT STRING OPTIONAL }
-
- id-publicKeyType OBJECT IDENTIFIER ::= { ansi-X9-62 keyType(2) }
-
- id-ecPublicKey OBJECT IDENTIFIER ::= { id-publicKeyType 1 }
-
- -- Named Elliptic Curves in ANSI X9.62.
-
- ellipticCurve OBJECT IDENTIFIER ::= { ansi-X9-62 curves(3) }
-
- c-TwoCurve OBJECT IDENTIFIER ::= {
- ellipticCurve characteristicTwo(0) }
-
- c2pnb163v1 OBJECT IDENTIFIER ::= { c-TwoCurve 1 }
- c2pnb163v2 OBJECT IDENTIFIER ::= { c-TwoCurve 2 }
- c2pnb163v3 OBJECT IDENTIFIER ::= { c-TwoCurve 3 }
- c2pnb176w1 OBJECT IDENTIFIER ::= { c-TwoCurve 4 }
- c2tnb191v1 OBJECT IDENTIFIER ::= { c-TwoCurve 5 }
- c2tnb191v2 OBJECT IDENTIFIER ::= { c-TwoCurve 6 }
- c2tnb191v3 OBJECT IDENTIFIER ::= { c-TwoCurve 7 }
- c2onb191v4 OBJECT IDENTIFIER ::= { c-TwoCurve 8 }
- c2onb191v5 OBJECT IDENTIFIER ::= { c-TwoCurve 9 }
- c2pnb208w1 OBJECT IDENTIFIER ::= { c-TwoCurve 10 }
- c2tnb239v1 OBJECT IDENTIFIER ::= { c-TwoCurve 11 }
- c2tnb239v2 OBJECT IDENTIFIER ::= { c-TwoCurve 12 }
- c2tnb239v3 OBJECT IDENTIFIER ::= { c-TwoCurve 13 }
- c2onb239v4 OBJECT IDENTIFIER ::= { c-TwoCurve 14 }
- c2onb239v5 OBJECT IDENTIFIER ::= { c-TwoCurve 15 }
- c2pnb272w1 OBJECT IDENTIFIER ::= { c-TwoCurve 16 }
- c2pnb304w1 OBJECT IDENTIFIER ::= { c-TwoCurve 17 }
- c2tnb359v1 OBJECT IDENTIFIER ::= { c-TwoCurve 18 }
- c2pnb368w1 OBJECT IDENTIFIER ::= { c-TwoCurve 19 }
- c2tnb431r1 OBJECT IDENTIFIER ::= { c-TwoCurve 20 }
-
- primeCurve OBJECT IDENTIFIER ::= { ellipticCurve prime(1) }
-
- prime192v1 OBJECT IDENTIFIER ::= { primeCurve 1 }
- prime192v2 OBJECT IDENTIFIER ::= { primeCurve 2 }
- prime192v3 OBJECT IDENTIFIER ::= { primeCurve 3 }
- prime239v1 OBJECT IDENTIFIER ::= { primeCurve 4 }
- prime239v2 OBJECT IDENTIFIER ::= { primeCurve 5 }
- prime239v3 OBJECT IDENTIFIER ::= { primeCurve 6 }
- prime256v1 OBJECT IDENTIFIER ::= { primeCurve 7 }
-
- END
diff --git a/lib/orber/src/PKIX1Explicit88.asn1 b/lib/orber/src/PKIX1Explicit88.asn1
deleted file mode 100644
index 9b8068fed0..0000000000
--- a/lib/orber/src/PKIX1Explicit88.asn1
+++ /dev/null
@@ -1,619 +0,0 @@
-PKIX1Explicit88 { iso(1) identified-organization(3) dod(6) internet(1)
- security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-explicit(18) }
-
-DEFINITIONS EXPLICIT TAGS ::=
-
-BEGIN
-
--- EXPORTS ALL --
-
--- IMPORTS NONE --
-
--- UNIVERSAL Types defined in 1993 and 1998 ASN.1
--- and required by this specification
-
--- UniversalString ::= [UNIVERSAL 28] IMPLICIT OCTET STRING
- -- UniversalString is defined in ASN.1:1993
-
--- BMPString ::= [UNIVERSAL 30] IMPLICIT OCTET STRING
- -- BMPString is the subtype of UniversalString and models
- -- the Basic Multilingual Plane of ISO/IEC/ITU 10646-1
-
--- UTF8String ::= [UNIVERSAL 12] IMPLICIT OCTET STRING
- -- The content of this type conforms to RFC 2279.
-
--- PKIX specific OIDs
-
-id-pkix OBJECT IDENTIFIER ::=
- { iso(1) identified-organization(3) dod(6) internet(1)
- security(5) mechanisms(5) pkix(7) }
-
--- PKIX arcs
-
-id-pe OBJECT IDENTIFIER ::= { id-pkix 1 }
- -- arc for private certificate extensions
-id-qt OBJECT IDENTIFIER ::= { id-pkix 2 }
- -- arc for policy qualifier types
-id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }
- -- arc for extended key purpose OIDS
-id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
- -- arc for access descriptors
-
--- policyQualifierIds for Internet policy qualifiers
-
-id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 }
- -- OID for CPS qualifier
-id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 }
- -- OID for user notice qualifier
-
--- access descriptor definitions
-
-id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
-id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
-id-ad-timeStamping OBJECT IDENTIFIER ::= { id-ad 3 }
-id-ad-caRepository OBJECT IDENTIFIER ::= { id-ad 5 }
-
--- attribute data types
-
-Attribute ::= SEQUENCE {
- type AttributeType,
- values SET OF AttributeValue }
- -- at least one value is required
-
-AttributeType ::= OBJECT IDENTIFIER
-
-AttributeValue ::= ANY
-
-AttributeTypeAndValue ::= SEQUENCE {
- type AttributeType,
- value AttributeValue }
-
--- suggested naming attributes: Definition of the following
--- information object set may be augmented to meet local
--- requirements. Note that deleting members of the set may
--- prevent interoperability with conforming implementations.
--- presented in pairs: the AttributeType followed by the
--- type definition for the corresponding AttributeValue
---Arc for standard naming attributes
-id-at OBJECT IDENTIFIER ::= { joint-iso-ccitt(2) ds(5) 4 }
-
--- Naming attributes of type X520name
-
-id-at-name AttributeType ::= { id-at 41 }
-id-at-surname AttributeType ::= { id-at 4 }
-id-at-givenName AttributeType ::= { id-at 42 }
-id-at-initials AttributeType ::= { id-at 43 }
-id-at-generationQualifier AttributeType ::= { id-at 44 }
-
-X520name ::= CHOICE {
- teletexString TeletexString (SIZE (1..ub-name)),
- printableString PrintableString (SIZE (1..ub-name)),
- universalString UniversalString (SIZE (1..ub-name)),
- utf8String UTF8String (SIZE (1..ub-name)),
- bmpString BMPString (SIZE (1..ub-name)) }
-
--- Naming attributes of type X520CommonName
-
-id-at-commonName AttributeType ::= { id-at 3 }
-
-X520CommonName ::= CHOICE {
- teletexString TeletexString (SIZE (1..ub-common-name)),
- printableString PrintableString (SIZE (1..ub-common-name)),
- universalString UniversalString (SIZE (1..ub-common-name)),
- utf8String UTF8String (SIZE (1..ub-common-name)),
- bmpString BMPString (SIZE (1..ub-common-name)) }
-
--- Naming attributes of type X520LocalityName
-
-id-at-localityName AttributeType ::= { id-at 7 }
-
-X520LocalityName ::= CHOICE {
- teletexString TeletexString (SIZE (1..ub-locality-name)),
- printableString PrintableString (SIZE (1..ub-locality-name)),
- universalString UniversalString (SIZE (1..ub-locality-name)),
- utf8String UTF8String (SIZE (1..ub-locality-name)),
- bmpString BMPString (SIZE (1..ub-locality-name)) }
-
--- Naming attributes of type X520StateOrProvinceName
-
-id-at-stateOrProvinceName AttributeType ::= { id-at 8 }
-
-X520StateOrProvinceName ::= CHOICE {
- teletexString TeletexString (SIZE (1..ub-state-name)),
- printableString PrintableString (SIZE (1..ub-state-name)),
- universalString UniversalString (SIZE (1..ub-state-name)),
- utf8String UTF8String (SIZE (1..ub-state-name)),
- bmpString BMPString (SIZE(1..ub-state-name)) }
-
--- Naming attributes of type X520OrganizationName
-
-id-at-organizationName AttributeType ::= { id-at 10 }
-
-X520OrganizationName ::= CHOICE {
- teletexString TeletexString
- (SIZE (1..ub-organization-name)),
- printableString PrintableString
- (SIZE (1..ub-organization-name)),
- universalString UniversalString
- (SIZE (1..ub-organization-name)),
- utf8String UTF8String
- (SIZE (1..ub-organization-name)),
- bmpString BMPString
- (SIZE (1..ub-organization-name)) }
-
--- Naming attributes of type X520OrganizationalUnitName
-
-id-at-organizationalUnitName AttributeType ::= { id-at 11 }
-
-X520OrganizationalUnitName ::= CHOICE {
- teletexString TeletexString
- (SIZE (1..ub-organizational-unit-name)),
- printableString PrintableString
- (SIZE (1..ub-organizational-unit-name)),
- universalString UniversalString
- (SIZE (1..ub-organizational-unit-name)),
- utf8String UTF8String
- (SIZE (1..ub-organizational-unit-name)),
- bmpString BMPString
- (SIZE (1..ub-organizational-unit-name)) }
-
--- Naming attributes of type X520Title
-
-id-at-title AttributeType ::= { id-at 12 }
-
-X520Title ::= CHOICE {
- teletexString TeletexString (SIZE (1..ub-title)),
- printableString PrintableString (SIZE (1..ub-title)),
- universalString UniversalString (SIZE (1..ub-title)),
- utf8String UTF8String (SIZE (1..ub-title)),
- bmpString BMPString (SIZE (1..ub-title)) }
-
--- Naming attributes of type X520dnQualifier
-
-id-at-dnQualifier AttributeType ::= { id-at 46 }
-
-X520dnQualifier ::= PrintableString
-
--- Naming attributes of type X520countryName (digraph from IS 3166)
-
-id-at-countryName AttributeType ::= { id-at 6 }
-
-X520countryName ::= PrintableString (SIZE (2))
-
--- Naming attributes of type X520SerialNumber
-
-id-at-serialNumber AttributeType ::= { id-at 5 }
-
-X520SerialNumber ::= PrintableString (SIZE (1..ub-serial-number))
-
--- Naming attributes of type X520Pseudonym
-
-id-at-pseudonym AttributeType ::= { id-at 65 }
-
-X520Pseudonym ::= CHOICE {
- teletexString TeletexString (SIZE (1..ub-pseudonym)),
- printableString PrintableString (SIZE (1..ub-pseudonym)),
- universalString UniversalString (SIZE (1..ub-pseudonym)),
- utf8String UTF8String (SIZE (1..ub-pseudonym)),
- bmpString BMPString (SIZE (1..ub-pseudonym)) }
-
--- Naming attributes of type DomainComponent (from RFC 2247)
-
-id-domainComponent AttributeType ::=
- { 0 9 2342 19200300 100 1 25 }
-
-DomainComponent ::= IA5String
-
--- Legacy attributes
-
-pkcs-9 OBJECT IDENTIFIER ::=
- { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 }
-
-id-emailAddress AttributeType ::= { pkcs-9 1 }
-
-EmailAddress ::= IA5String (SIZE (1..ub-emailaddress-length))
-
--- naming data types --
-
-Name ::= CHOICE { -- only one possibility for now --
- rdnSequence RDNSequence }
-
-RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
-
-DistinguishedName ::= RDNSequence
-
-RelativeDistinguishedName ::=
- SET SIZE (1 .. MAX) OF AttributeTypeAndValue
-
--- Directory string type --
-
-DirectoryString ::= CHOICE {
- teletexString TeletexString (SIZE (1..MAX)),
- printableString PrintableString (SIZE (1..MAX)),
- universalString UniversalString (SIZE (1..MAX)),
- utf8String UTF8String (SIZE (1..MAX)),
- bmpString BMPString (SIZE (1..MAX)) }
-
--- certificate and CRL specific structures begin here
-
-Certificate ::= SEQUENCE {
- tbsCertificate TBSCertificate,
- signatureAlgorithm AlgorithmIdentifier,
- signature BIT STRING }
-
-TBSCertificate ::= SEQUENCE {
- version [0] Version DEFAULT v1,
- serialNumber CertificateSerialNumber,
- signature AlgorithmIdentifier,
- issuer Name,
- validity Validity,
- subject Name,
- subjectPublicKeyInfo SubjectPublicKeyInfo,
- issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
- -- If present, version MUST be v2 or v3
- subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
- -- If present, version MUST be v2 or v3
- extensions [3] Extensions OPTIONAL
- -- If present, version MUST be v3 -- }
-
-Version ::= INTEGER { v1(0), v2(1), v3(2) }
-
-CertificateSerialNumber ::= INTEGER
-
-Validity ::= SEQUENCE {
- notBefore Time,
- notAfter Time }
-
-Time ::= CHOICE {
- utcTime UTCTime,
- generalTime GeneralizedTime }
-
-UniqueIdentifier ::= BIT STRING
-
-SubjectPublicKeyInfo ::= SEQUENCE {
- algorithm AlgorithmIdentifier,
- subjectPublicKey BIT STRING }
-
-Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
-
-Extension ::= SEQUENCE {
- extnID OBJECT IDENTIFIER,
- critical BOOLEAN DEFAULT FALSE,
- extnValue OCTET STRING }
-
--- CRL structures
-
-CertificateList ::= SEQUENCE {
- tbsCertList TBSCertList,
- signatureAlgorithm AlgorithmIdentifier,
- signature BIT STRING }
-
-TBSCertList ::= SEQUENCE {
- version Version OPTIONAL,
- -- if present, MUST be v2
- signature AlgorithmIdentifier,
- issuer Name,
- thisUpdate Time,
- nextUpdate Time OPTIONAL,
- revokedCertificates SEQUENCE OF SEQUENCE {
- userCertificate CertificateSerialNumber,
- revocationDate Time,
- crlEntryExtensions Extensions OPTIONAL
- -- if present, MUST be v2
- } OPTIONAL,
- crlExtensions [0] Extensions OPTIONAL }
- -- if present, MUST be v2
-
--- Version, Time, CertificateSerialNumber, and Extensions were
--- defined earlier for use in the certificate structure
-
-AlgorithmIdentifier ::= SEQUENCE {
- algorithm OBJECT IDENTIFIER,
- parameters ANY DEFINED BY algorithm OPTIONAL }
- -- contains a value of the type
- -- registered for use with the
- -- algorithm object identifier value
-
--- X.400 address syntax starts here
-
-ORAddress ::= SEQUENCE {
- built-in-standard-attributes BuiltInStandardAttributes,
- built-in-domain-defined-attributes
- BuiltInDomainDefinedAttributes OPTIONAL,
- -- see also teletex-domain-defined-attributes
- extension-attributes ExtensionAttributes OPTIONAL }
-
--- Built-in Standard Attributes
-
-BuiltInStandardAttributes ::= SEQUENCE {
- country-name CountryName OPTIONAL,
- administration-domain-name AdministrationDomainName OPTIONAL,
- network-address [0] IMPLICIT NetworkAddress OPTIONAL,
- -- see also extended-network-address
- terminal-identifier [1] IMPLICIT TerminalIdentifier OPTIONAL,
- private-domain-name [2] PrivateDomainName OPTIONAL,
- organization-name [3] IMPLICIT OrganizationName OPTIONAL,
- -- see also teletex-organization-name
- numeric-user-identifier [4] IMPLICIT NumericUserIdentifier
- OPTIONAL,
- personal-name [5] IMPLICIT PersonalName OPTIONAL,
- -- see also teletex-personal-name
- organizational-unit-names [6] IMPLICIT OrganizationalUnitNames
- OPTIONAL }
- -- see also teletex-organizational-unit-names
-
-CountryName ::= [APPLICATION 1] CHOICE {
- x121-dcc-code NumericString
- (SIZE (ub-country-name-numeric-length)),
- iso-3166-alpha2-code PrintableString
- (SIZE (ub-country-name-alpha-length)) }
-
-AdministrationDomainName ::= [APPLICATION 2] CHOICE {
- numeric NumericString (SIZE (0..ub-domain-name-length)),
- printable PrintableString (SIZE (0..ub-domain-name-length)) }
-
-NetworkAddress ::= X121Address -- see also extended-network-address
-
-X121Address ::= NumericString (SIZE (1..ub-x121-address-length))
-
-TerminalIdentifier ::= PrintableString (SIZE
-(1..ub-terminal-id-length))
-
-PrivateDomainName ::= CHOICE {
- numeric NumericString (SIZE (1..ub-domain-name-length)),
- printable PrintableString (SIZE (1..ub-domain-name-length)) }
-
-OrganizationName ::= PrintableString
- (SIZE (1..ub-organization-name-length))
- -- see also teletex-organization-name
-
-NumericUserIdentifier ::= NumericString
- (SIZE (1..ub-numeric-user-id-length))
-
-PersonalName ::= SET {
- surname [0] IMPLICIT PrintableString
- (SIZE (1..ub-surname-length)),
- given-name [1] IMPLICIT PrintableString
- (SIZE (1..ub-given-name-length)) OPTIONAL,
- initials [2] IMPLICIT PrintableString
- (SIZE (1..ub-initials-length)) OPTIONAL,
- generation-qualifier [3] IMPLICIT PrintableString
- (SIZE (1..ub-generation-qualifier-length))
- OPTIONAL }
- -- see also teletex-personal-name
-
-OrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units)
- OF OrganizationalUnitName
- -- see also teletex-organizational-unit-names
-
-OrganizationalUnitName ::= PrintableString (SIZE
- (1..ub-organizational-unit-name-length))
-
--- Built-in Domain-defined Attributes
-
-BuiltInDomainDefinedAttributes ::= SEQUENCE SIZE
- (1..ub-domain-defined-attributes) OF
- BuiltInDomainDefinedAttribute
-
-BuiltInDomainDefinedAttribute ::= SEQUENCE {
- type PrintableString (SIZE
- (1..ub-domain-defined-attribute-type-length)),
- value PrintableString (SIZE
- (1..ub-domain-defined-attribute-value-length)) }
-
--- Extension Attributes
-
-ExtensionAttributes ::= SET SIZE (1..ub-extension-attributes) OF
- ExtensionAttribute
-
-ExtensionAttribute ::= SEQUENCE {
- extension-attribute-type [0] IMPLICIT INTEGER
- (0..ub-extension-attributes),
- extension-attribute-value [1]
- ANY DEFINED BY extension-attribute-type }
-
--- Extension types and attribute values
-
-common-name INTEGER ::= 1
-
-CommonName ::= PrintableString (SIZE (1..ub-common-name-length))
-
-teletex-common-name INTEGER ::= 2
-
-TeletexCommonName ::= TeletexString (SIZE (1..ub-common-name-length))
-
-teletex-organization-name INTEGER ::= 3
-
-TeletexOrganizationName ::=
- TeletexString (SIZE (1..ub-organization-name-length))
-
-teletex-personal-name INTEGER ::= 4
-
-TeletexPersonalName ::= SET {
- surname [0] IMPLICIT TeletexString
- (SIZE (1..ub-surname-length)),
- given-name [1] IMPLICIT TeletexString
- (SIZE (1..ub-given-name-length)) OPTIONAL,
- initials [2] IMPLICIT TeletexString
- (SIZE (1..ub-initials-length)) OPTIONAL,
- generation-qualifier [3] IMPLICIT TeletexString
- (SIZE (1..ub-generation-qualifier-length))
- OPTIONAL }
-
-teletex-organizational-unit-names INTEGER ::= 5
-
-TeletexOrganizationalUnitNames ::= SEQUENCE SIZE
- (1..ub-organizational-units) OF TeletexOrganizationalUnitName
-
-TeletexOrganizationalUnitName ::= TeletexString
- (SIZE (1..ub-organizational-unit-name-length))
-
-pds-name INTEGER ::= 7
-
-PDSName ::= PrintableString (SIZE (1..ub-pds-name-length))
-
-physical-delivery-country-name INTEGER ::= 8
-
-PhysicalDeliveryCountryName ::= CHOICE {
- x121-dcc-code NumericString (SIZE
-(ub-country-name-numeric-length)),
- iso-3166-alpha2-code PrintableString
- (SIZE (ub-country-name-alpha-length)) }
-
-postal-code INTEGER ::= 9
-
-PostalCode ::= CHOICE {
- numeric-code NumericString (SIZE (1..ub-postal-code-length)),
- printable-code PrintableString (SIZE (1..ub-postal-code-length)) }
-
-physical-delivery-office-name INTEGER ::= 10
-
-PhysicalDeliveryOfficeName ::= PDSParameter
-
-physical-delivery-office-number INTEGER ::= 11
-
-PhysicalDeliveryOfficeNumber ::= PDSParameter
-
-extension-OR-address-components INTEGER ::= 12
-
-ExtensionORAddressComponents ::= PDSParameter
-
-physical-delivery-personal-name INTEGER ::= 13
-
-PhysicalDeliveryPersonalName ::= PDSParameter
-
-physical-delivery-organization-name INTEGER ::= 14
-
-PhysicalDeliveryOrganizationName ::= PDSParameter
-
-extension-physical-delivery-address-components INTEGER ::= 15
-
-ExtensionPhysicalDeliveryAddressComponents ::= PDSParameter
-
-unformatted-postal-address INTEGER ::= 16
-
-UnformattedPostalAddress ::= SET {
- printable-address SEQUENCE SIZE (1..ub-pds-physical-address-lines)
- OF PrintableString (SIZE (1..ub-pds-parameter-length))
- OPTIONAL,
- teletex-string TeletexString
- (SIZE (1..ub-unformatted-address-length)) OPTIONAL }
-
-street-address INTEGER ::= 17
-
-StreetAddress ::= PDSParameter
-
-post-office-box-address INTEGER ::= 18
-
-PostOfficeBoxAddress ::= PDSParameter
-
-poste-restante-address INTEGER ::= 19
-
-PosteRestanteAddress ::= PDSParameter
-
-unique-postal-name INTEGER ::= 20
-
-UniquePostalName ::= PDSParameter
-
-local-postal-attributes INTEGER ::= 21
-
-LocalPostalAttributes ::= PDSParameter
-
-PDSParameter ::= SET {
- printable-string PrintableString
- (SIZE(1..ub-pds-parameter-length)) OPTIONAL,
- teletex-string TeletexString
- (SIZE(1..ub-pds-parameter-length)) OPTIONAL }
-
-extended-network-address INTEGER ::= 22
-
-ExtendedNetworkAddress ::= CHOICE {
- e163-4-address SEQUENCE {
- number [0] IMPLICIT NumericString
- (SIZE (1..ub-e163-4-number-length)),
- sub-address [1] IMPLICIT NumericString
- (SIZE (1..ub-e163-4-sub-address-length))
- OPTIONAL },
- psap-address [0] IMPLICIT PresentationAddress }
-
-PresentationAddress ::= SEQUENCE {
- pSelector [0] EXPLICIT OCTET STRING OPTIONAL,
- sSelector [1] EXPLICIT OCTET STRING OPTIONAL,
- tSelector [2] EXPLICIT OCTET STRING OPTIONAL,
- nAddresses [3] EXPLICIT SET SIZE (1..MAX) OF OCTET STRING }
-
-terminal-type INTEGER ::= 23
-
-TerminalType ::= INTEGER {
- telex (3),
- teletex (4),
- g3-facsimile (5),
- g4-facsimile (6),
- ia5-terminal (7),
- videotex (8) } (0..ub-integer-options)
-
--- Extension Domain-defined Attributes
-
-teletex-domain-defined-attributes INTEGER ::= 6
-
-TeletexDomainDefinedAttributes ::= SEQUENCE SIZE
- (1..ub-domain-defined-attributes) OF TeletexDomainDefinedAttribute
-
-TeletexDomainDefinedAttribute ::= SEQUENCE {
- type TeletexString
- (SIZE (1..ub-domain-defined-attribute-type-length)),
- value TeletexString
- (SIZE (1..ub-domain-defined-attribute-value-length)) }
-
--- specifications of Upper Bounds MUST be regarded as mandatory
--- from Annex B of ITU-T X.411 Reference Definition of MTS Parameter
--- Upper Bounds
-
--- Upper Bounds
-ub-name INTEGER ::= 32768
-ub-common-name INTEGER ::= 64
-ub-locality-name INTEGER ::= 128
-ub-state-name INTEGER ::= 128
-ub-organization-name INTEGER ::= 64
-ub-organizational-unit-name INTEGER ::= 64
-ub-title INTEGER ::= 64
-ub-serial-number INTEGER ::= 64
-ub-match INTEGER ::= 128
-ub-emailaddress-length INTEGER ::= 128
-ub-common-name-length INTEGER ::= 64
-ub-country-name-alpha-length INTEGER ::= 2
-ub-country-name-numeric-length INTEGER ::= 3
-ub-domain-defined-attributes INTEGER ::= 4
-ub-domain-defined-attribute-type-length INTEGER ::= 8
-ub-domain-defined-attribute-value-length INTEGER ::= 128
-ub-domain-name-length INTEGER ::= 16
-ub-extension-attributes INTEGER ::= 256
-ub-e163-4-number-length INTEGER ::= 15
-ub-e163-4-sub-address-length INTEGER ::= 40
-ub-generation-qualifier-length INTEGER ::= 3
-ub-given-name-length INTEGER ::= 16
-ub-initials-length INTEGER ::= 5
-ub-integer-options INTEGER ::= 256
-ub-numeric-user-id-length INTEGER ::= 32
-ub-organization-name-length INTEGER ::= 64
-ub-organizational-unit-name-length INTEGER ::= 32
-ub-organizational-units INTEGER ::= 4
-ub-pds-name-length INTEGER ::= 16
-ub-pds-parameter-length INTEGER ::= 30
-ub-pds-physical-address-lines INTEGER ::= 6
-ub-postal-code-length INTEGER ::= 16
-ub-pseudonym INTEGER ::= 128
-ub-surname-length INTEGER ::= 40
-ub-terminal-id-length INTEGER ::= 24
-ub-unformatted-address-length INTEGER ::= 180
-ub-x121-address-length INTEGER ::= 16
-
--- Note - upper bounds on string types, such as TeletexString, are
--- measured in characters. Excepting PrintableString or IA5String, a
--- significantly greater number of octets will be required to hold
--- such a value. As a minimum, 16 octets, or twice the specified
--- upper bound, whichever is the larger, should be allowed for
--- TeletexString. For UTF8String or UniversalString at least four
--- times the upper bound should be allowed.
-
-END
diff --git a/lib/orber/src/PKIX1Implicit88.asn1 b/lib/orber/src/PKIX1Implicit88.asn1
deleted file mode 100644
index ced270baf6..0000000000
--- a/lib/orber/src/PKIX1Implicit88.asn1
+++ /dev/null
@@ -1,349 +0,0 @@
-PKIX1Implicit88 { iso(1) identified-organization(3) dod(6) internet(1)
- security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-implicit(19) }
-
-DEFINITIONS IMPLICIT TAGS ::=
-
-BEGIN
-
--- EXPORTS ALL --
-
-IMPORTS
- id-pe, id-kp, id-qt-unotice, id-qt-cps,
- -- delete following line if "new" types are supported --
- -- BMPString,
- -- UTF8String, end "new" types --
- ORAddress, Name, RelativeDistinguishedName,
- CertificateSerialNumber, Attribute, DirectoryString
- FROM PKIX1Explicit88 { iso(1) identified-organization(3)
- dod(6) internet(1) security(5) mechanisms(5) pkix(7)
- id-mod(0) id-pkix1-explicit(18) };
-
-
--- ISO arc for standard certificate and CRL extensions
-
-id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29}
-
--- authority key identifier OID and syntax
-
-id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 }
-
-AuthorityKeyIdentifier ::= SEQUENCE {
- keyIdentifier [0] KeyIdentifier OPTIONAL,
- authorityCertIssuer [1] GeneralNames OPTIONAL,
- authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
- -- authorityCertIssuer and authorityCertSerialNumber MUST both
- -- be present or both be absent
-
-KeyIdentifier ::= OCTET STRING
-
--- subject key identifier OID and syntax
-
-id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 }
-
-SubjectKeyIdentifier ::= KeyIdentifier
-
--- key usage extension OID and syntax
-
-id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
-
-KeyUsage ::= BIT STRING {
- digitalSignature (0),
- nonRepudiation (1),
- keyEncipherment (2),
- dataEncipherment (3),
- keyAgreement (4),
- keyCertSign (5),
- cRLSign (6),
- encipherOnly (7),
- decipherOnly (8) }
-
--- private key usage period extension OID and syntax
-
-id-ce-privateKeyUsagePeriod OBJECT IDENTIFIER ::= { id-ce 16 }
-
-PrivateKeyUsagePeriod ::= SEQUENCE {
- notBefore [0] GeneralizedTime OPTIONAL,
- notAfter [1] GeneralizedTime OPTIONAL }
- -- either notBefore or notAfter MUST be present
-
--- certificate policies extension OID and syntax
-
-id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 }
-
-anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 }
-
-CertificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
-
-PolicyInformation ::= SEQUENCE {
- policyIdentifier CertPolicyId,
- policyQualifiers SEQUENCE SIZE (1..MAX) OF
- PolicyQualifierInfo OPTIONAL }
-
-CertPolicyId ::= OBJECT IDENTIFIER
-
-PolicyQualifierInfo ::= SEQUENCE {
- policyQualifierId PolicyQualifierId,
- qualifier ANY DEFINED BY policyQualifierId }
-
--- Implementations that recognize additional policy qualifiers MUST
--- augment the following definition for PolicyQualifierId
-
-PolicyQualifierId ::=
- OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
-
--- CPS pointer qualifier
-
-CPSuri ::= IA5String
-
--- user notice qualifier
-
-UserNotice ::= SEQUENCE {
- noticeRef NoticeReference OPTIONAL,
- explicitText DisplayText OPTIONAL}
-
-NoticeReference ::= SEQUENCE {
- organization DisplayText,
- noticeNumbers SEQUENCE OF INTEGER }
-
-DisplayText ::= CHOICE {
- ia5String IA5String (SIZE (1..200)),
- visibleString VisibleString (SIZE (1..200)),
- bmpString BMPString (SIZE (1..200)),
- utf8String UTF8String (SIZE (1..200)) }
-
--- policy mapping extension OID and syntax
-
-id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 }
-
-PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
- issuerDomainPolicy CertPolicyId,
- subjectDomainPolicy CertPolicyId }
-
--- subject alternative name extension OID and syntax
-
-id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 }
-
-SubjectAltName ::= GeneralNames
-
-GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
-
-GeneralName ::= CHOICE {
- otherName [0] AnotherName,
- rfc822Name [1] IA5String,
- dNSName [2] IA5String,
- x400Address [3] ORAddress,
- directoryName [4] Name,
- ediPartyName [5] EDIPartyName,
- uniformResourceIdentifier [6] IA5String,
- iPAddress [7] OCTET STRING,
- registeredID [8] OBJECT IDENTIFIER }
-
--- AnotherName replaces OTHER-NAME ::= TYPE-IDENTIFIER, as
--- TYPE-IDENTIFIER is not supported in the '88 ASN.1 syntax
-
-AnotherName ::= SEQUENCE {
- type-id OBJECT IDENTIFIER,
- value [0] EXPLICIT ANY DEFINED BY type-id }
-
-EDIPartyName ::= SEQUENCE {
- nameAssigner [0] DirectoryString OPTIONAL,
- partyName [1] DirectoryString }
-
--- issuer alternative name extension OID and syntax
-
-id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 }
-
-IssuerAltName ::= GeneralNames
-
-id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 }
-
-SubjectDirectoryAttributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
-
--- basic constraints extension OID and syntax
-
-id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 }
-
-BasicConstraints ::= SEQUENCE {
- cA BOOLEAN DEFAULT FALSE,
- pathLenConstraint INTEGER (0..MAX) OPTIONAL }
-
--- name constraints extension OID and syntax
-
-id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 }
-
-NameConstraints ::= SEQUENCE {
- permittedSubtrees [0] GeneralSubtrees OPTIONAL,
- excludedSubtrees [1] GeneralSubtrees OPTIONAL }
-
-GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
-
-GeneralSubtree ::= SEQUENCE {
- base GeneralName,
- minimum [0] BaseDistance DEFAULT 0,
- maximum [1] BaseDistance OPTIONAL }
-
-BaseDistance ::= INTEGER (0..MAX)
-
--- policy constraints extension OID and syntax
-
-id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 }
-
-PolicyConstraints ::= SEQUENCE {
- requireExplicitPolicy [0] SkipCerts OPTIONAL,
- inhibitPolicyMapping [1] SkipCerts OPTIONAL }
-
-SkipCerts ::= INTEGER (0..MAX)
-
--- CRL distribution points extension OID and syntax
-
-id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= {id-ce 31}
-
-CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
-
-DistributionPoint ::= SEQUENCE {
- distributionPoint [0] DistributionPointName OPTIONAL,
- reasons [1] ReasonFlags OPTIONAL,
- cRLIssuer [2] GeneralNames OPTIONAL }
-
-DistributionPointName ::= CHOICE {
- fullName [0] GeneralNames,
- nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
-
-ReasonFlags ::= BIT STRING {
- unused (0),
- keyCompromise (1),
- cACompromise (2),
- affiliationChanged (3),
- superseded (4),
- cessationOfOperation (5),
- certificateHold (6),
- privilegeWithdrawn (7),
- aACompromise (8) }
-
--- extended key usage extension OID and syntax
-
-id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37}
-
-ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
-
-
-KeyPurposeId ::= OBJECT IDENTIFIER
-
--- permit unspecified key uses
-
-anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 }
-
--- extended key purpose OIDs
-
-id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 }
-id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 }
-id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 }
-id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 }
-id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 }
-id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 }
-
--- inhibit any policy OID and syntax
-
-id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 }
-
-InhibitAnyPolicy ::= SkipCerts
-
--- freshest (delta)CRL extension OID and syntax
-
-id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 }
-
-FreshestCRL ::= CRLDistributionPoints
-
--- authority info access
-
-id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
-
-AuthorityInfoAccessSyntax ::=
- SEQUENCE SIZE (1..MAX) OF AccessDescription
-
-AccessDescription ::= SEQUENCE {
- accessMethod OBJECT IDENTIFIER,
- accessLocation GeneralName }
-
--- subject info access
-
-id-pe-subjectInfoAccess OBJECT IDENTIFIER ::= { id-pe 11 }
-
-SubjectInfoAccessSyntax ::=
- SEQUENCE SIZE (1..MAX) OF AccessDescription
-
--- CRL number extension OID and syntax
-
-id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 }
-
-CRLNumber ::= INTEGER (0..MAX)
-
--- issuing distribution point extension OID and syntax
-
-id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-ce 28 }
-
-IssuingDistributionPoint ::= SEQUENCE {
- distributionPoint [0] DistributionPointName OPTIONAL,
- onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE,
- onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE,
- onlySomeReasons [3] ReasonFlags OPTIONAL,
- indirectCRL [4] BOOLEAN DEFAULT FALSE,
- onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
-
-id-ce-deltaCRLIndicator OBJECT IDENTIFIER ::= { id-ce 27 }
-
-BaseCRLNumber ::= CRLNumber
-
--- CRL reasons extension OID and syntax
-
-id-ce-cRLReasons OBJECT IDENTIFIER ::= { id-ce 21 }
-
-CRLReason ::= ENUMERATED {
- unspecified (0),
- keyCompromise (1),
- cACompromise (2),
- affiliationChanged (3),
- superseded (4),
- cessationOfOperation (5),
- certificateHold (6),
- removeFromCRL (8),
- privilegeWithdrawn (9),
- aACompromise (10) }
-
--- certificate issuer CRL entry extension OID and syntax
-
-id-ce-certificateIssuer OBJECT IDENTIFIER ::= { id-ce 29 }
-
-CertificateIssuer ::= GeneralNames
-
--- hold instruction extension OID and syntax
-
-id-ce-holdInstructionCode OBJECT IDENTIFIER ::= { id-ce 23 }
-
-HoldInstructionCode ::= OBJECT IDENTIFIER
-
--- ANSI x9 holdinstructions
-
--- ANSI x9 arc holdinstruction arc
-
-holdInstruction OBJECT IDENTIFIER ::=
- {joint-iso-itu-t(2) member-body(2) us(840) x9cm(10040) 2}
-
--- ANSI X9 holdinstructions referenced by this standard
-
-id-holdinstruction-none OBJECT IDENTIFIER ::=
- {holdInstruction 1} -- deprecated
-
-id-holdinstruction-callissuer OBJECT IDENTIFIER ::=
- {holdInstruction 2}
-
-id-holdinstruction-reject OBJECT IDENTIFIER ::=
- {holdInstruction 3}
-
--- invalidity date CRL entry extension OID and syntax
-
-id-ce-invalidityDate OBJECT IDENTIFIER ::= { id-ce 24 }
-
-InvalidityDate ::= GeneralizedTime
-
-END
diff --git a/lib/orber/src/PKIXAttributeCertificate.asn1 b/lib/orber/src/PKIXAttributeCertificate.asn1
deleted file mode 100644
index 7d93e6b37e..0000000000
--- a/lib/orber/src/PKIXAttributeCertificate.asn1
+++ /dev/null
@@ -1,189 +0,0 @@
- PKIXAttributeCertificate {iso(1) identified-organization(3) dod(6)
- internet(1) security(5) mechanisms(5) pkix(7) id-mod(0)
- id-mod-attribute-cert(12)}
-
- DEFINITIONS IMPLICIT TAGS ::=
-
- BEGIN
-
- -- EXPORTS ALL --
-
- IMPORTS
-
- -- IMPORTed module OIDs MAY change if [PKIXPROF] changes
- -- PKIX Certificate Extensions
- Attribute, AlgorithmIdentifier, CertificateSerialNumber,
- Extensions, UniqueIdentifier,
- id-pkix, id-pe, id-kp, id-ad, id-at
- FROM PKIX1Explicit88 {iso(1) identified-organization(3)
- dod(6) internet(1) security(5) mechanisms(5)
- pkix(7) id-mod(0) id-pkix1-explicit-88(1)}
-
- GeneralName, GeneralNames, id-ce
- FROM PKIX1Implicit88 {iso(1) identified-organization(3)
- dod(6) internet(1) security(5) mechanisms(5)
- pkix(7) id-mod(0) id-pkix1-implicit-88(2)} ;
-
- id-pe-ac-auditIdentity OBJECT IDENTIFIER ::= { id-pe 4 }
- id-pe-aaControls OBJECT IDENTIFIER ::= { id-pe 6 }
- id-pe-ac-proxying OBJECT IDENTIFIER ::= { id-pe 10 }
- id-ce-targetInformation OBJECT IDENTIFIER ::= { id-ce 55 }
-
- id-aca OBJECT IDENTIFIER ::= { id-pkix 10 }
- id-aca-authenticationInfo OBJECT IDENTIFIER ::= { id-aca 1 }
- id-aca-accessIdentity OBJECT IDENTIFIER ::= { id-aca 2 }
- id-aca-chargingIdentity OBJECT IDENTIFIER ::= { id-aca 3 }
- id-aca-group OBJECT IDENTIFIER ::= { id-aca 4 }
- -- { id-aca 5 } is reserved
- id-aca-encAttrs OBJECT IDENTIFIER ::= { id-aca 6 }
-
- id-at-role OBJECT IDENTIFIER ::= { id-at 72}
- id-at-clearance OBJECT IDENTIFIER ::=
- { joint-iso-ccitt(2) ds(5) module(1)
- selected-attribute-types(5) clearance (55) }
-
- -- Uncomment this if using a 1988 level ASN.1 compiler
- -- UTF8String ::= [UNIVERSAL 12] IMPLICIT OCTET STRING
-
- AttributeCertificate ::= SEQUENCE {
- acinfo AttributeCertificateInfo,
- signatureAlgorithm AlgorithmIdentifier,
- signatureValue BIT STRING
- }
-
- AttributeCertificateInfo ::= SEQUENCE {
- version AttCertVersion, -- version is v2
- holder Holder,
- issuer AttCertIssuer,
- signature AlgorithmIdentifier,
- serialNumber CertificateSerialNumber,
- attrCertValidityPeriod AttCertValidityPeriod,
- attributes SEQUENCE OF Attribute,
- issuerUniqueID UniqueIdentifier OPTIONAL,
- extensions Extensions OPTIONAL
- }
-
- AttCertVersion ::= INTEGER { v2(1) }
-
- Holder ::= SEQUENCE {
- baseCertificateID [0] IssuerSerial OPTIONAL,
- -- the issuer and serial number of
- -- the holder's Public Key Certificate
- entityName [1] GeneralNames OPTIONAL,
- -- the name of the claimant or role
- objectDigestInfo [2] ObjectDigestInfo OPTIONAL
- -- used to directly authenticate the
- -- holder, for example, an executable
- }
-
- ObjectDigestInfo ::= SEQUENCE {
- digestedObjectType ENUMERATED {
- publicKey (0),
- publicKeyCert (1),
- otherObjectTypes (2) },
- -- otherObjectTypes MUST NOT
- -- MUST NOT be used in this profile
- otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
- digestAlgorithm AlgorithmIdentifier,
- objectDigest BIT STRING
- }
-
- AttCertIssuer ::= CHOICE {
- v1Form GeneralNames, -- MUST NOT be used in this
- -- profile
- v2Form [0] V2Form -- v2 only
- }
-
- V2Form ::= SEQUENCE {
- issuerName GeneralNames OPTIONAL,
- baseCertificateID [0] IssuerSerial OPTIONAL,
- objectDigestInfo [1] ObjectDigestInfo OPTIONAL
- -- issuerName MUST be present in this profile
- -- baseCertificateID and objectDigestInfo MUST
- -- NOT be present in this profile
- }
-
- IssuerSerial ::= SEQUENCE {
- issuer GeneralNames,
- serial CertificateSerialNumber,
- issuerUID UniqueIdentifier OPTIONAL
- }
-
- AttCertValidityPeriod ::= SEQUENCE {
- notBeforeTime GeneralizedTime,
- notAfterTime GeneralizedTime
- }
-
- Targets ::= SEQUENCE OF Target
-
- Target ::= CHOICE {
- targetName [0] GeneralName,
- targetGroup [1] GeneralName,
- targetCert [2] TargetCert
- }
-
- TargetCert ::= SEQUENCE {
- targetCertificate IssuerSerial,
- targetName GeneralName OPTIONAL,
- certDigestInfo ObjectDigestInfo OPTIONAL
- }
-
- IetfAttrSyntax ::= SEQUENCE {
- policyAuthority[0] GeneralNames OPTIONAL,
- values SEQUENCE OF CHOICE {
- octets OCTET STRING,
- oid OBJECT IDENTIFIER,
- string UTF8String
- }
- }
-
- SvceAuthInfo ::= SEQUENCE {
- service GeneralName,
- ident GeneralName,
- authInfo OCTET STRING OPTIONAL
- }
-
- RoleSyntax ::= SEQUENCE {
- roleAuthority [0] GeneralNames OPTIONAL,
- roleName [1] GeneralName
- }
-
- Clearance ::= SEQUENCE {
- policyId [0] OBJECT IDENTIFIER,
- classList [1] ClassList DEFAULT {unclassified},
- securityCategories
- [2] SET OF SecurityCategory OPTIONAL
- }
-
- ClassList ::= BIT STRING {
- unmarked (0),
- unclassified (1),
- restricted (2),
- confidential (3),
- secret (4),
- topSecret (5)
- }
-
- SecurityCategory ::= SEQUENCE {
- type [0] IMPLICIT OBJECT IDENTIFIER,
- value [1] ANY DEFINED BY type
- }
-
- AAControls ::= SEQUENCE {
- pathLenConstraint INTEGER (0..MAX) OPTIONAL,
- permittedAttrs [0] AttrSpec OPTIONAL,
- excludedAttrs [1] AttrSpec OPTIONAL,
- permitUnSpecified BOOLEAN DEFAULT TRUE
- }
-
- AttrSpec::= SEQUENCE OF OBJECT IDENTIFIER
-
- ACClearAttrs ::= SEQUENCE {
- acIssuer GeneralName,
- acSerial INTEGER,
- attrs SEQUENCE OF Attribute
- }
-
- ProxyInfo ::= SEQUENCE OF Targets
-
- END
diff --git a/lib/orber/src/any.erl b/lib/orber/src/any.erl
deleted file mode 100644
index ec7c3ba83a..0000000000
--- a/lib/orber/src/any.erl
+++ /dev/null
@@ -1,74 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: any.erl
-%% Description:
-%% This file conatins the interface for the any type
-%%
-%%-----------------------------------------------------------------
--module(any).
-
--include_lib("orber/include/corba.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([create/0, create/2,
- set_typecode/2, get_typecode/1,
- set_value/2, get_value/1]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-create() ->
- #any{}.
-
-create(TC, V) ->
- case orber_tc:check_tc(TC) of
- true ->
- #any{typecode=TC, value=V};
- false ->
- corba:raise(#'BAD_TYPECODE'{completion_status=?COMPLETED_NO})
- end.
-
-set_typecode(Any, TC) ->
- case orber_tc:check_tc(TC) of
- true ->
- Any#any{typecode=TC};
- false ->
- corba:raise(#'BAD_TYPECODE'{completion_status=?COMPLETED_NO})
- end.
-
-get_typecode(Any) ->
- Any#any.typecode.
-
-set_value(Any, V) ->
- Any#any{value=V}.
-
-get_value(Any) ->
- Any#any.value.
-
diff --git a/lib/orber/src/cdr_decode.erl b/lib/orber/src/cdr_decode.erl
deleted file mode 100644
index fd021988c9..0000000000
--- a/lib/orber/src/cdr_decode.erl
+++ /dev/null
@@ -1,1536 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: cdr_decode.erl
-%%
-%% Description:
-%% This file contains all decoding functions for the CDR
-%% format.
-%%
-%%-----------------------------------------------------------------
--module(cdr_decode).
-
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/include/ifr_types.hrl").
--include_lib("orber/include/corba.hrl").
-
--include_lib("orber/src/ifr_objects.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([dec_giop_message_header/1, dec_reply_header/4,
- dec_reply_body/6, dec_locate_reply_header/4,
- dec_locate_reply_body/5, dec_message_header/3, dec_request_body/6,
- dec_octet_sequence_bin/6, dec_message/2, peek_request_id/2]).
-
-%%-----------------------------------------------------------------
-%% Functions which only are exported for the testcases.
-%%-----------------------------------------------------------------
--export([dec_type/5, dec_byte_order/1, dec_system_exception/4, dec_user_exception/4,
- dec_byte_order_list/1]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
--define(DEBUG_LEVEL, 9).
-
--define(ODD(N), (N rem 2) == 1).
-
-%%-----------------------------------------------------------------
-%% Func: dec_message/3
-%% Args:
-%% TypeCodes - is the type_codes of the return value and out parameters
-%% when one decodes a reply.
-%% Bytes - is the the message as a byte sequence.
-%% Returns:
-%% A tupple which contains the decoded message,
-%% {ok, Header, Parameters, TypeCodes}.
-%%-----------------------------------------------------------------
-dec_message(TypeCodes, Bytes) ->
- Message = dec_giop_message_header(Bytes),
- case Message#giop_message.message_type of
- ?GIOP_MSG_REQUEST ->
- {Version, ReqHdr, Rest, Len, ByteOrder} =
- dec_request_header(Message#giop_message.giop_version,
- Message#giop_message.message, ?GIOP_HEADER_SIZE,
- Message#giop_message.byte_order, Bytes),
- dec_request_body(Version, ReqHdr, Rest, Len, ByteOrder, Bytes);
- ?GIOP_MSG_REPLY ->
- dec_reply(Message#giop_message.giop_version,
- TypeCodes, Message#giop_message.message, ?GIOP_HEADER_SIZE,
- Message#giop_message.byte_order);
- ?GIOP_MSG_CANCEL_REQUEST ->
- dec_cancel_request(Message#giop_message.giop_version,
- Message#giop_message.message, ?GIOP_HEADER_SIZE,
- Message#giop_message.byte_order);
- ?GIOP_MSG_LOCATE_REQUEST ->
- dec_locate_request(Message#giop_message.giop_version,
- Message#giop_message.message, ?GIOP_HEADER_SIZE,
- Message#giop_message.byte_order);
- ?GIOP_MSG_LOCATE_REPLY ->
- dec_locate_reply(Message#giop_message.giop_version,
- Message#giop_message.message, ?GIOP_HEADER_SIZE,
- Message#giop_message.byte_order);
- ?GIOP_MSG_CLOSE_CONNECTION ->
- 'close_connection';
- ?GIOP_MSG_MESSAGE_ERROR ->
- 'message_error';
- ?GIOP_MSG_FRAGMENT ->
- dec_fragment_header(Message#giop_message.giop_version,
- Message#giop_message.message, ?GIOP_HEADER_SIZE,
- Message#giop_message.byte_order, Bytes)
- end.
-
-%%-----------------------------------------------------------------
-%% Func: dec_giop_message_header/1
-%% Args:
-%% Bytes - is the the message as a byte sequence.
-%% Returns:
-%% A giop_message record.
-%%-----------------------------------------------------------------
-%% Magic|Version|BO| Type | Size | Body
-dec_giop_message_header(<<"GIOP",1:8,0:8,1:8,MessType:8,
- MessSize:32/little-unsigned-integer,Message/binary>>) ->
- #giop_message{magic = "GIOP", giop_version = {1,0},
- byte_order = little, message_type = MessType,
- message_size = MessSize, message = Message};
-dec_giop_message_header(<<"GIOP",1:8,0:8,0:8,MessType:8,
- MessSize:32/big-unsigned-integer,Message/binary>>) ->
- #giop_message{magic = "GIOP", giop_version = {1,0},
- byte_order = big, message_type = MessType,
- message_size = MessSize, message = Message};
-dec_giop_message_header(<<"GIOP",1:8,Minor:8,Flags:8,MessType:8,
- MessSize:32/little-unsigned-integer,Message/binary>>) when
- ((Flags band 16#01) == 16#01) ->
- #giop_message{magic = "GIOP", giop_version = {1,Minor},
- byte_order = little, fragments = ((Flags band 16#02) == 16#02),
- message_type = MessType, message_size = MessSize, message = Message};
-dec_giop_message_header(<<"GIOP",1:8,Minor:8,Flags:8,MessType:8,
- MessSize:32/big-unsigned-integer,Message/binary>>) ->
- #giop_message{magic = "GIOP", giop_version = {1,Minor},
- byte_order = big, fragments = ((Flags band 16#02) == 16#02),
- message_type = MessType, message_size = MessSize, message = Message};
-dec_giop_message_header(<<Hdr:?GIOP_HEADER_SIZE/binary, _Body/binary>>) ->
- orber:dbg("[~p] cdr_decode:dec_giop_message_header(~p);~n"
- "Orber cannot decode the GIOP-header.", [?LINE, Hdr], ?DEBUG_LEVEL),
- exit(message_error);
-dec_giop_message_header(Other) ->
- orber:dbg("[~p] cdr_decode:dec_giop_message_header(~p);~n"
- "Orber cannot decode the GIOP-header.", [?LINE, Other], ?DEBUG_LEVEL),
- exit(message_error).
-
-
-peek_request_id(big, <<ReqId:32/big-unsigned-integer,_/binary>>) ->
- ReqId;
-peek_request_id(little, <<ReqId:32/little-unsigned-integer,_/binary>>) ->
- ReqId.
-
-%%-----------------------------------------------------------------
-%% Func: dec_message_header/2
-%% Args:
-%% Header - #giop_message{}
-%% Bytes - is the the message body as a byte sequence.
-%% Returns:
-%%-----------------------------------------------------------------
-dec_message_header(TypeCodes, Message, Bytes) ->
- case Message#giop_message.message_type of
- ?GIOP_MSG_REQUEST ->
- dec_request_header(Message#giop_message.giop_version,
- Message#giop_message.message, ?GIOP_HEADER_SIZE,
- Message#giop_message.byte_order, Bytes);
- ?GIOP_MSG_REPLY ->
- dec_reply(Message#giop_message.giop_version,
- TypeCodes, Message#giop_message.message, ?GIOP_HEADER_SIZE,
- Message#giop_message.byte_order);
- ?GIOP_MSG_CANCEL_REQUEST ->
- dec_cancel_request(Message#giop_message.giop_version,
- Message#giop_message.message, ?GIOP_HEADER_SIZE,
- Message#giop_message.byte_order);
- ?GIOP_MSG_LOCATE_REQUEST ->
- dec_locate_request(Message#giop_message.giop_version,
- Message#giop_message.message, ?GIOP_HEADER_SIZE,
- Message#giop_message.byte_order);
- ?GIOP_MSG_LOCATE_REPLY ->
- dec_locate_reply(Message#giop_message.giop_version,
- Message#giop_message.message, ?GIOP_HEADER_SIZE,
- Message#giop_message.byte_order);
- ?GIOP_MSG_CLOSE_CONNECTION ->
- 'close_connection';
- ?GIOP_MSG_MESSAGE_ERROR ->
- 'message_error';
- ?GIOP_MSG_FRAGMENT ->
- dec_fragment_header(Message#giop_message.giop_version,
- Message#giop_message.message, ?GIOP_HEADER_SIZE,
- Message#giop_message.byte_order, Bytes)
- end.
-
-
-%%-----------------------------------------------------------------
-%% Func: dec_byte_order/1
-%% Args:
-%% The message as a byte sequence.
-%% Returns:
-%% A tuple {Endianness, Rest} where Endianness is big or little.
-%% Rest is the remaining message byte sequence.
-%%-----------------------------------------------------------------
-dec_byte_order(<<0:8,T/binary>>) ->
- {big, T};
-dec_byte_order(<<1:8,T/binary>>) ->
- {little, T}.
-
-%%-----------------------------------------------------------------
-%% Func: dec_byte_order_list/1
-%% Args:
-%% The message as a byte sequence.
-%% Returns:
-%% A tuple {Endianness, Rest} where Endianness is big or little.
-%% Rest is the remaining message byte sequence.
-%%-----------------------------------------------------------------
-dec_byte_order_list([0|T]) ->
- {big, T};
-dec_byte_order_list([1|T]) ->
- {little, T}.
-
-%%-----------------------------------------------------------------
-%% Func : dec_response_flags
-%% Args :
-%% Returns : boolean
-%%-----------------------------------------------------------------
-%% FIX ME!! Not correct flag handling.
-dec_response_flags(_Version, <<0:8, Rest/binary>>, Len) ->
- {false, Rest, Len+1};
-dec_response_flags(_Version, <<1:8, Rest/binary>>, Len) ->
- {true_oneway, Rest, Len+1};
-dec_response_flags(_Version, <<3:8, Rest/binary>>, Len) ->
- {true, Rest, Len+1};
-dec_response_flags(_Version, <<X:8, Rest/binary>>, Len) ->
- %% Not only the Response flag is set, test which.
- if
- %% Since the 6 most significant bits are unused we'll accept this for now.
- ((X band 16#03) == 16#03) ->
- {true, Rest, Len+1};
- ((X band 16#01) == 16#01) ->
- {true_oneway, Rest, Len+1};
- true ->
- {false, Rest, Len+1}
- end.
-
-%%-----------------------------------------------------------------
-%% Func : dec_target_addr
-%% Args : Octet
-%% Returns : boolean
-%%-----------------------------------------------------------------
-dec_target_addr(Version, Message, Len, ByteOrder, RequestId, Type) ->
- case dec_type(?TARGETADDRESS, Version, Message, Len, ByteOrder, [], 0) of
- {#'GIOP_TargetAddress'{label = ?GIOP_KeyAddr, value = KeyAddr}, Rest3, Len3, C} ->
- {dec_target_key(KeyAddr, RequestId, Version, Type), Rest3, Len3, C};
- {#'GIOP_TargetAddress'{label = ?GIOP_ProfileAddr,
- value = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP,
- profile_data=PA}},
- Rest3, Len3, C} ->
- {dec_target_key(PA, RequestId, Version, Type), Rest3, Len3, C};
- {#'GIOP_TargetAddress'{label = ?GIOP_ReferenceAddr,
- value = #'GIOP_IORAddressingInfo'{
- selected_profile_index = _PI,
- ior = IOR}}, Rest3, Len3, C} ->
- {dec_target_key(iop_ior:get_objkey(IOR), RequestId, Version, Type),
- Rest3, Len3, C};
- Other ->
- orber:dbg("[~p] cdr_decode:dec_target_addr(~p);~n"
- "Unsupported TargetAddress.", [?LINE, Other], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 12), completion_status=?COMPLETED_MAYBE})
- end.
-
-%%-----------------------------------------------------------------
-%% Func : dec_target_key
-%% Args : Octet
-%% Returns : boolean
-%%-----------------------------------------------------------------
-dec_target_key(Key, RequestId, Version, Type) ->
- %% The Type argument is used as an identifier of which operation it is.
- %% We need it to be able to tell the difference if it's, for example,
- %% a request or locate-request.
- case corba:string_to_objkey_local(Key) of
- {location_forward, Object} ->
- throw({Type, Object, RequestId, Version, Key});
- ObjRef ->
- ObjRef
- end.
-
-%%-----------------------------------------------------------------
-%% Func: dec_request_header/3
-%% Args:
-%% Message - The message
-%% Len0 - Number of bytes already read.
-%% ByteOrder - little or big
-%% Returns:
-%%-----------------------------------------------------------------
-dec_request_header(Version, Message, Len0, ByteOrder, _Buffer) when Version == {1,2} ->
- {Request_id, Rest1, Len1, _} = dec_type('tk_ulong', Version, Message, Len0,
- ByteOrder, [], 0),
- {ResponseFlags, Rest2, Len2} = dec_response_flags(Version, Rest1, Len1),
- {_, Rest2b, Len2b, _} = dec_type({'tk_array', 'tk_octet', 3}, Version, Rest2, Len2, ByteOrder, [], 0),
- {Object_key, Rest3, Len3, _} = dec_target_addr(Version, Rest2b, Len2b, ByteOrder, Request_id,
- 'location_forward'),
- {Operation, Rest4, Len4, _} = dec_type({'tk_string', 0}, Version, Rest3, Len3, ByteOrder, [], 0),
- {Context, Rest5, Len5} = dec_service_context(Version, Rest4, Len4, ByteOrder),
- {Version, #request_header{service_context=Context,
- request_id=Request_id,
- response_expected=ResponseFlags,
- object_key=Object_key,
- operation=list_to_atom(Operation),
- requesting_principal=""}, Rest5, Len5, ByteOrder};
-dec_request_header(Version, Message, Len0, ByteOrder, _Buffer) ->
- {Context, Rest1, Len1} = dec_service_context(Version, Message, Len0, ByteOrder),
- {Request_id, Rest2, Len2, _} = dec_type('tk_ulong', Version, Rest1, Len1, ByteOrder, [], 0),
- {Response_expected, Rest3, Len3, _} = dec_type('tk_boolean', Version, Rest2, Len2,
- ByteOrder, [], 0),
- {ObjKey, Rest4, Len4, _} = dec_type({'tk_sequence', 'tk_octet', 0}, Version, Rest3,
- Len3, ByteOrder, [], 0),
- Object_key = dec_target_key(ObjKey, Request_id, Version, 'location_forward'),
- {Operation, Rest5, Len5, _} = dec_type({'tk_string', 0}, Version, Rest4, Len4, ByteOrder, [], 0),
- {Principal, Rest, Len, _} = dec_type({'tk_string', 0}, Version, Rest5,Len5, ByteOrder, [], 0),
- {Version, #request_header{service_context=Context,
- request_id=Request_id,
- response_expected=Response_expected,
- object_key=Object_key,
- operation=list_to_atom(Operation),
- requesting_principal=Principal}, Rest, Len, ByteOrder}.
-
-
-%%-----------------------------------------------------------------
-%% Func: dec_service_context/4
-%% Args: Version - e.g. 1.2
-%% Message - The message
-%% Len - Number of bytes already read.
-%% ByteOrder - little or big
-%% Returns:
-%%-----------------------------------------------------------------
-dec_service_context(Version, Message, Len, ByteOrder) ->
- {Context, Rest, Len1} = dec_type(?IOP_SERVICECONTEXT, Version, Message,
- Len, ByteOrder),
- {dec_used_contexts(Version, Context, []), Rest, Len1}.
-
-dec_used_contexts(_Version, [], Ctxs) ->
- Ctxs;
-dec_used_contexts({1,0}, [#'IOP_ServiceContext'{context_id=?IOP_CodeSets}|T], Ctxs) ->
- %% Not supported by 1.0, drop it.
- dec_used_contexts({1,0}, T, Ctxs);
-dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_CodeSets,
- context_data = Bytes}|T], Ctxs) ->
- {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)),
- {CodeCtx, _, _} = dec_type(?CONV_FRAME_CODESETCONTEXT, Version,
- Rest, 1, ByteOrder),
- dec_used_contexts(Version, T,
- [#'IOP_ServiceContext'{context_id=?IOP_CodeSets,
- context_data = CodeCtx}|Ctxs]);
-dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_BI_DIR_IIOP,
- context_data = Bytes}|T], Ctxs) ->
- {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)),
- {BiDirCtx, _, _} = dec_type(?IIOP_BIDIRIIOPSERVICECONTEXT, Version,
- Rest, 1, ByteOrder),
- dec_used_contexts(Version, T,
- [#'IOP_ServiceContext'{context_id=?IOP_BI_DIR_IIOP,
- context_data = BiDirCtx}|Ctxs]);
-dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_FT_REQUEST,
- context_data = Bytes}|T], Ctxs) ->
- {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)),
- {Ctx, _, _} = dec_type(?FT_FTRequestServiceContext, Version,
- Rest, 1, ByteOrder),
- dec_used_contexts(Version, T,
- [#'IOP_ServiceContext'{context_id=?IOP_FT_REQUEST,
- context_data = Ctx}|Ctxs]);
-dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_FT_GROUP_VERSION,
- context_data = Bytes}|T], Ctxs) ->
- {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)),
- {Ctx, _, _} = dec_type(?FT_FTGroupVersionServiceContext, Version,
- Rest, 1, ByteOrder),
- dec_used_contexts(Version, T,
- [#'IOP_ServiceContext'{context_id=?IOP_FT_GROUP_VERSION,
- context_data = Ctx}|Ctxs]);
-dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = Bytes}|T], Ctxs) ->
- {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)),
- {Ctx, _, _} = dec_type(?CSI_SASContextBody, Version,
- Rest, 1, ByteOrder),
- dec_used_contexts(Version, T,
- [#'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = Ctx}|Ctxs]);
-dec_used_contexts(Version, [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = Bytes}|T], Ctxs) ->
- {ByteOrder, Rest} = dec_byte_order(list_to_binary(Bytes)),
- {Ctx, _, _} = dec_type(?ORBER_GENERIC_CTX, Version,
- Rest, 1, ByteOrder),
- dec_used_contexts(Version, T,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = binary_to_term(list_to_binary(Ctx))}|Ctxs]);
-dec_used_contexts(Version, [H|T], Ctxs) ->
- dec_used_contexts(Version, T, [H|Ctxs]).
-
-%%-----------------------------------------------------------------
-%% Func: dec_request_body
-%% Args: Version - e.g. 1.2
-%% Returns:
-%%-----------------------------------------------------------------
-dec_request_body(Version, ReqHdr, Rest, Len, ByteOrder, Buffer) ->
- {Parameters, TypeCodes, _} =
- dec_request_body(Version, ReqHdr#request_header.object_key,
- ReqHdr#request_header.operation,
- Rest, Len, ByteOrder, Buffer, Len),
- {Version, ReqHdr, Parameters, TypeCodes}.
-
-dec_request_body(Version, Object_key, Operation, Body, Len, ByteOrder, Buffer, Counter)
- when Version == {1,2} ->
- case orber_typedefs:get_op_def(Object_key, Operation) of
- {RetType, [], OutParameters} ->
- {[], {RetType, [], OutParameters}, Len};
- {RetType, InParameters, OutParameters} ->
- {Rest, Len1, NewC} = dec_align(Body, Len, 8, Counter),
- {Parameters, Len2} = dec_parameters(Version, InParameters, Rest, Len1,
- ByteOrder, Buffer, NewC),
- {Parameters, {RetType, InParameters, OutParameters}, Len2}
- end;
-dec_request_body(Version, Object_key, Operation, Body, Len, ByteOrder, Buffer, Counter) ->
- {RetType, InParameters, OutParameters} =
- orber_typedefs:get_op_def(Object_key, Operation),
- {Parameters, Len1} = dec_parameters(Version, InParameters, Body, Len, ByteOrder, Buffer, Counter),
- {Parameters, {RetType, InParameters, OutParameters}, Len1}.
-
-dec_parameters(_, [], _, Len, _, _, _) ->
- {[], Len};
-dec_parameters(Version, [P1 |InParList], Body, Len, ByteOrder, Buffer, Counter) ->
- {Object, Rest, Len1, NewCounter} = dec_type(P1, Version, Body, Len, ByteOrder, Buffer, Counter),
- {List, Len2} = dec_parameters(Version, InParList, Rest, Len1, ByteOrder, Buffer, NewCounter),
- {[Object | List], Len2}.
-
-%%-----------------------------------------------------------------
-%% Func: dec_reply/5
-%% Args:
-%% Message - The message
-%% Len0 - Number of bytes already read.
-%% ByteOrder - little or big
-%% Returns:
-%% A tuple {ReplyHeader, Result} where ReplyHeader is a
-%% reply_header record and Result the decode result.
-%%-----------------------------------------------------------------
-dec_reply(Version, TypeCodes, Message, Len0, ByteOrder) ->
- {ReplyHeader, Rest, Len} = dec_reply_header(Version, Message, Len0, ByteOrder),
- {Result, Par} =
- case ReplyHeader#reply_header.reply_status of
- 'no_exception' ->
- {R, P, _} = dec_reply_body(Version, TypeCodes, Rest, Len, ByteOrder, Message),
- {R, P};
- 'system_exception' ->
- {R, _} = dec_system_exception(Version, Rest, Len, ByteOrder),
- {R, []};
- 'user_exception' ->
- {R, _} = dec_user_exception(Version, Rest, Len, ByteOrder),
- {R, []};
- 'location_forward' ->
- {R, _, _} = dec_reply_body(Version, {{'tk_objref', "", ""}, [],[]},
- Rest, Len, ByteOrder, Message),
- {R, []};
- %% This is deprecated in later version than CORBA-2.3.1. We'll leave it for
- %% now.
- 'location_forward_perm' ->
- {R, _, _} = dec_reply_body(Version, {{'tk_objref', "", ""}, [],[]},
- Rest, Len, ByteOrder, Message),
- {R, []};
- 'needs_addressing_mode' ->
- {R, _, _} = dec_reply_body(Version, {'tk_short', [],[]},
- Rest, Len, ByteOrder, Message),
- {R, []}
- end,
- {ReplyHeader, Result, Par}.
-
-
-%% ## NEW IIOP 1.2 ##
-dec_reply_header(Version, Message, Len0, ByteOrder) when Version == {1,2} ->
- {Request_id, Rest1, Len1} = dec_type('tk_ulong', Version, Message, Len0, ByteOrder),
- {ReplyStatus, Rest2, Len2} = dec_reply_status(Version, Rest1, Len1, ByteOrder),
- {Context, Rest, Len3} = dec_service_context(Version, Rest2, Len2, ByteOrder),
- {#reply_header{service_context=Context, request_id=Request_id, reply_status=ReplyStatus},
- Rest, Len3};
-
-dec_reply_header(Version, Message, Len0, ByteOrder) ->
- {Context, Rest1, Len1} = dec_service_context(Version, Message, Len0, ByteOrder),
- {Request_id, Rest2, Len2} = dec_type('tk_ulong', Version, Rest1, Len1, ByteOrder),
- {ReplyStatus, Rest, Len3} = dec_reply_status(Version, Rest2, Len2, ByteOrder),
- {#reply_header{service_context=Context, request_id=Request_id, reply_status=ReplyStatus},
- Rest, Len3}.
-
-dec_reply_status(Version, Status, Len, ByteOrder) ->
- {L, Rest, Len1}= dec_type('tk_ulong', Version, Status, Len, ByteOrder),
- {dec_giop_reply_status_type(L), Rest, Len1}.
-
-dec_reply_body(_, {'tk_void', _, []}, <<>>, Len, _, _) ->
- %% This case is mainly to be able to avoid removing non-existent alignment for
- %% IIOP-1.2 messages if the body should be empty, i.e., void return value and
- %% no out parameters.
- {ok, [], Len};
-dec_reply_body(Version, {RetType, _InParameters, OutParameters}, Body, Len,
- ByteOrder, Bytes) when Version == {1,2} ->
- {Rest, Len1, Counter} = dec_align(Body, Len, 8, Len),
- {Result, Rest2, Len2, C} = dec_type(RetType, Version, Rest, Len1, ByteOrder, Bytes, Counter),
- {Par, Len3} = dec_parameters(Version, OutParameters, Rest2, Len2, ByteOrder, Bytes, C),
- {Result, Par, Len3};
-dec_reply_body(Version, {RetType, _InParameters, OutParameters}, Body, Len, ByteOrder, Bytes) ->
- {Result, Rest, Len1, C} = dec_type(RetType, Version, Body, Len, ByteOrder, Bytes, Len),
- {Par, Len2} = dec_parameters(Version, OutParameters, Rest, Len1, ByteOrder, Bytes, C),
- {Result, Par, Len2}.
-
-
-%%-----------------------------------------------------------------
-%% Func: dec_cancel_request/3
-%% Args:
-%% Message - The message
-%% Len - Number of bytes already read.
-%% ByteOrder - little or big
-%% Returns:
-%% A cancel_request_header record.
-%%-----------------------------------------------------------------
-dec_cancel_request(Version, Message, Len, ByteOrder) ->
- {Request_id, _, _} = dec_type('tk_ulong', Version, Message, Len, ByteOrder),
- #cancel_request_header{request_id=Request_id}.
-
-%%-----------------------------------------------------------------
-%% Func: dec_locate_request/3
-%% Args:
-%% Message - The message
-%% Len - Number of bytes already read.
-%% ByteOrder - little or big
-%% Returns:
-%% A locate_request_header record.
-%%-----------------------------------------------------------------
-%% ## NEW IIOP 1.2 ##
-dec_locate_request(Version, Message, Len, ByteOrder) when Version == {1,2} ->
- {Request_id, Rest, Len1} = dec_type('tk_ulong', Version, Message, Len, ByteOrder),
- {Object_key, _, _, _} = dec_target_addr(Version, Rest, Len1, ByteOrder, Request_id,
- 'object_forward'),
- {Version, #locate_request_header{request_id=Request_id, object_key=Object_key}};
-dec_locate_request(Version, Message, Len, ByteOrder) ->
- {Request_id, Rest, Len1} = dec_type('tk_ulong', Version, Message, Len, ByteOrder),
- {ObjKey, _, _} = dec_type({'tk_sequence', 'tk_octet', 0}, Version, Rest,
- Len1, ByteOrder),
- Object_key = dec_target_key(ObjKey, Request_id, Version, 'object_forward'),
- {Version, #locate_request_header{request_id=Request_id, object_key=Object_key}}.
-
-
-%%-----------------------------------------------------------------
-%% Func: dec_locate_reply/3
-%% Args:
-%% Message - The message
-%% Len - Number of bytes already read.
-%% ByteOrder - little or big
-%% Returns:
-%% A locate_reply_header record.
-%%-----------------------------------------------------------------
-dec_locate_reply(Version, Message, Len, ByteOrder) ->
- {ReplyHeader, Rest1, Len1} = dec_locate_reply_header(Version, Message, Len, ByteOrder),
- {ReplyHeader, dec_locate_reply_body(Version, ReplyHeader#locate_reply_header.locate_status, Rest1,
- Len1, ByteOrder)}.
-
-dec_locate_reply_header(Version, Message, Len, ByteOrder) ->
- {Request_id, Rest1, Len1} = dec_type('tk_ulong', Version, Message, Len, ByteOrder),
- {Locate_status, Rest2, Len2} = dec_locate_status(Version, Rest1, Len1, ByteOrder),
- {#locate_reply_header{request_id=Request_id, locate_status=Locate_status}, Rest2, Len2}.
-
-dec_locate_reply_body(Version, LocateStatus, Rest, Len, ByteOrder) when Version == {1,2} ->
- %% In CORBA-2.3.1 the LocateReply body didn't align the body (8-octet
- %% boundry) for IIOP-1.2. This have been changed in CORBA-2.4 and
- %% changed back in CORBA-2.6. Hence, we should not change this.
- case LocateStatus of
- 'object_forward' ->
- {ObjRef, _, _, _} = dec_objref(Version, Rest, Len, ByteOrder),
- ObjRef;
- 'object_forward_perm' ->
- %% This is deprecated in later version than CORBA-2.3.1. We'll leave it for
- %% now.
- {ObjRef, _, _, _} = dec_objref(Version, Rest, Len, ByteOrder),
- ObjRef;
- 'loc_system_exception' ->
- %% This should be updated but since 'dec_system_exception' removes
- %% alignment, which the LocateReplyBody don't have, for 1.2 we
- %% pretend it's 1.1 for now.
- {SysExc, _} = dec_system_exception({1,1}, Rest, Len, ByteOrder),
- corba:raise(SysExc);
- 'loc_needs_addressing_mode' ->
- %% Not supported.
- [];
- _ ->
- []
- end;
-dec_locate_reply_body(Version, LocateStatus, Rest, Len, ByteOrder) ->
- case LocateStatus of
- 'object_forward' ->
- {ObjRef, _, _, _} = dec_objref(Version, Rest, Len, ByteOrder),
- ObjRef;
- _ ->
- []
- end.
-
-dec_locate_status(Version, Bytes, Len, ByteOrder) ->
- {L, Rest, Len1} = dec_type('tk_ulong', Version, Bytes, Len, ByteOrder),
- {dec_giop_locate_status_type(L), Rest, Len1}.
-
-
-%%-----------------------------------------------------------------
-%% Func: dec_fragment_header/5
-%% Args:
-%% Message - The message
-%% Len0 - Number of bytes already read.
-%% ByteOrder - little or big
-%% Returns:
-%%-----------------------------------------------------------------
-dec_fragment_header(Version, Message, Len0, ByteOrder, _Buffer) when Version == {1,2} ->
- {RequestId, Rest1, Len1, _} = dec_type('tk_ulong', Version, Message, Len0,
- ByteOrder, [], 0),
- {Version, #fragment_header{request_id=RequestId}, Rest1, Len1, ByteOrder};
-dec_fragment_header(Version, _Message, _Len0, _ByteOrder, _Buffer) ->
- %% The FragmentHeader is IIOP-1.2 specific. Hence, do nothing here.
- orber:dbg("[~p] cdr_decode:dec_fragment_header(~p)~n"
- "Orber only supports fragmented messages for IIOP-1.2.",
- [?LINE, Version], ?DEBUG_LEVEL),
- exit(message_error).
-% {Version, #fragment_header{}, Message, Len0, ByteOrder}.
-
-%%-----------------------------------------------------------------
-%% Func: dec_giop_reply_status_type
-%% Args:
-%% An integer status code
-%% Returns:
-%% An atom which is the reply status
-%%-----------------------------------------------------------------
-dec_giop_reply_status_type(0) ->
- 'no_exception';
-dec_giop_reply_status_type(1) ->
- 'user_exception';
-dec_giop_reply_status_type(2) ->
- 'system_exception';
-dec_giop_reply_status_type(3) ->
- 'location_forward';
-%% ## IIOP-1.2 ##
-dec_giop_reply_status_type(4) ->
- 'location_forward_perm';
-dec_giop_reply_status_type(5) ->
- 'needs_addressing_mode'.
-
-%%-----------------------------------------------------------------
-%% Func: dec_giop_locate_status_type
-%% Args:
-%% An integer status code
-%% Returns:
-%% An atom which is the reply status
-%%-----------------------------------------------------------------
-dec_giop_locate_status_type(0) ->
- 'unknown_object';
-dec_giop_locate_status_type(1) ->
- 'object_here';
-dec_giop_locate_status_type(2) ->
- 'object_forward';
-%% ## IIOP-1.2 ##
-dec_giop_locate_status_type(3) ->
- 'object_forward_perm';
-dec_giop_locate_status_type(4) ->
- 'loc_system_exception';
-dec_giop_locate_status_type(5) ->
- 'loc_needs_addressing_mode'.
-
-
-%%-----------------------------------------------------------------
-%% Func: dec_type/5
-%%-----------------------------------------------------------------
-dec_type(Type, Version, Bytes, Len, ByteOrder) ->
- {Val, Rest, Len2, _} =
- dec_type(Type, Version, Bytes, Len, ByteOrder, [], 0),
- {Val, Rest, Len2}.
-
-dec_type('tk_null', _Version, Bytes, Len, _, _, C) ->
- {'null', Bytes, Len, C};
-dec_type('tk_void', _Version, Bytes, Len, _, _, C) ->
- {'ok', Bytes, Len, C};
-dec_type('tk_short', _Version, Bytes, Len, ByteOrder, _, C) ->
- {Rest, Len1, NewC} = dec_align(Bytes, Len, 2, C),
- {Short, Rest1} = cdrlib:dec_short(ByteOrder, Rest),
- {Short, Rest1, Len1 + 2, NewC+2};
-dec_type('tk_long', _Version, Bytes, Len, ByteOrder, _, C) ->
- {Rest, Len1, NewC} = dec_align(Bytes, Len, 4, C),
- {Long, Rest1} = cdrlib:dec_long(ByteOrder, Rest),
- {Long, Rest1, Len1 + 4, NewC+4};
-dec_type('tk_longlong', _Version, Bytes, Len, ByteOrder, _, C) ->
- {Rest, Len1, NewC} = dec_align(Bytes, Len, 8, C),
- {Long, Rest1} = cdrlib:dec_longlong(ByteOrder, Rest),
- {Long, Rest1, Len1 + 8, NewC+8};
-dec_type('tk_ushort', _Version, Bytes, Len, ByteOrder, _, C) ->
- {Rest, Len1, NewC} = dec_align(Bytes, Len, 2, C),
- {Short, Rest1} = cdrlib:dec_unsigned_short(ByteOrder, Rest),
- {Short, Rest1, Len1 + 2, NewC+2};
-dec_type('tk_ulong', _Version, Bytes, Len, ByteOrder, _, C) ->
- {Rest, Len1, NewC} = dec_align(Bytes, Len, 4, C),
- {Long, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
- {Long, Rest1, Len1 + 4, NewC+4};
-dec_type('tk_ulonglong', _Version, Bytes, Len, ByteOrder, _, C) ->
- {Rest, Len1, NewC} = dec_align(Bytes, Len, 8, C),
- {Long, Rest1} = cdrlib:dec_unsigned_longlong(ByteOrder, Rest),
- {Long, Rest1, Len1 + 8, NewC+8};
-dec_type('tk_float', _Version, Bytes, Len, ByteOrder, _, C) ->
- {Rest, Len1, NewC} = dec_align(Bytes, Len, 4, C),
- {Float, Rest1} = cdrlib:dec_float(ByteOrder, Rest),
- {Float, Rest1, Len1 + 4, NewC+4};
-dec_type('tk_double', _Version, Bytes, Len, ByteOrder, _, C) ->
- {Rest, Len1, NewC} = dec_align(Bytes, Len, 8, C),
- {Double, Rest1} = cdrlib:dec_double(ByteOrder, Rest),
- {Double, Rest1, Len1 + 8, NewC+8};
-dec_type('tk_boolean', _Version, Bytes, Len, _, _, C) ->
- {Bool, Rest} = cdrlib:dec_bool(Bytes),
- {Bool, Rest, Len + 1, C+1};
-dec_type('tk_char', _Version, Bytes, Len, _, _, C) ->
- {Char, Rest} = cdrlib:dec_char(Bytes),
- {Char, Rest, Len + 1, C+1};
-dec_type('tk_wchar', {1,2}, Bytes, Len, _ByteOrder, _, C) ->
- %% For IIOP-1.2 a wchar is almost encoded the same way as an octet-sequence.
- %% The only difference is that the length-value is an octet as well.
- case cdrlib:dec_octet(Bytes) of
- {2, Rest1} ->
- %% Currently we only allow 2-bytes wchar.
- {WChar, Rest2} = cdrlib:dec_unsigned_short(big, Rest1),
- {WChar, Rest2, Len+3, C+3};
- {What, _} ->
- orber:dbg("[~p] cdr_decode:dec_type(~p); unsupported wchar",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'DATA_CONVERSION'{completion_status=?COMPLETED_NO})
- end;
-%% For 1.1 the wchar is limited to the use of two-octet fixed-length encoding.
-dec_type('tk_wchar', _Version, Bytes, Len, ByteOrder, _, C) ->
- {Rest, Len1, NewC} = dec_align(Bytes, Len, 2, C),
- {WChar, Rest2} = cdrlib:dec_unsigned_short(ByteOrder, Rest),
- {WChar, Rest2, Len1 + 2, NewC+2};
-dec_type('tk_octet', _Version, Bytes, Len, _, _, C) ->
- {Octet, Rest} = cdrlib:dec_octet(Bytes),
- {Octet, Rest, Len + 1, C+1};
-dec_type('tk_any', Version, Bytes, Len, ByteOrder, Buff, C) ->
- {TypeCode, Rest1, Len1, NewC} = dec_type('tk_TypeCode', Version, Bytes, Len, ByteOrder, Buff, C),
- {Value, Rest2, Len2, NewC2} = dec_type(TypeCode, Version, Rest1, Len1, ByteOrder, Buff, NewC),
- {#any{typecode=TypeCode, value=Value}, Rest2, Len2, NewC2};
-dec_type('tk_TypeCode', Version, Bytes, Len, ByteOrder, Buff, C) ->
- dec_type_code(Version, Bytes, Len, ByteOrder, Buff, C);
-dec_type('tk_Principal', Version, Bytes, Len, ByteOrder, Buff, C) ->
- dec_sequence(Version, Bytes, 'tk_octet', Len, ByteOrder, Buff, C);
-dec_type({'tk_objref', _IFRId, _Name}, Version, Bytes, Len, ByteOrder, Buff, C) ->
- dec_objref(Version, Bytes, Len, ByteOrder, Buff, C);
-dec_type({'tk_struct', IFRId, Name, ElementList}, Version, Bytes, Len, ByteOrder, Buff, C) ->
- dec_struct(Version, IFRId, Name, ElementList, Bytes, Len, ByteOrder, Buff, C);
-dec_type({'tk_union', IFRId, Name, DiscrTC, Default, ElementList},
- Version, Bytes, Len, ByteOrder, Buff, C) ->
- dec_union(Version, IFRId, Name, DiscrTC, Default, ElementList, Bytes, Len, ByteOrder, Buff, C);
-dec_type({'tk_enum', _IFRId, _Name, ElementList}, _Version, Bytes, Len, ByteOrder, _, C) ->
- {Rest, Len1, NewC} = dec_align(Bytes, Len, 4, C),
- {Enum, Rest1} = cdrlib:dec_enum(ByteOrder, ElementList, Rest),
- {Enum, Rest1, Len1 + 4, NewC+4};
-dec_type({'tk_string', _MaxLength}, Version, Bytes, Len, ByteOrder, Buff, C) ->
- dec_string(Version, Bytes, Len, ByteOrder, Buff, C);
-dec_type({'tk_wstring', _MaxLength}, Version, Bytes, Len, ByteOrder, Buff, C) ->
- dec_wstring(Version, Bytes, Len, ByteOrder, Buff, C);
-dec_type({'tk_sequence', ElemTC, _MaxLength}, Version, Bytes, Len, ByteOrder, Buff, C) ->
- dec_sequence(Version, Bytes, ElemTC, Len, ByteOrder, Buff, C);
-dec_type({'tk_array', ElemTC, Size}, Version, Bytes, Len, ByteOrder, Buff, C) ->
- dec_array(Version, Bytes, Size, ElemTC, Len, ByteOrder, Buff, C);
-dec_type({'tk_alias', _IFRId, _Name, TC}, Version, Bytes, Len, ByteOrder, Buff, C) ->
- dec_type(TC, Version, Bytes, Len, ByteOrder, Buff, C);
-%dec_type({'tk_except', IFRId, Name, ElementList}, Version, Bytes, Len, ByteOrder) ->
-dec_type({'tk_fixed', Digits, Scale}, _Version, Bytes, Len, _ByteOrder, _Buff, C) ->
- dec_fixed(Digits, Scale, Bytes, Len, C);
-dec_type(Type, _, _, _, _, _, _) ->
- orber:dbg("[~p] cdr_decode:dec_type(~p)~n"
- "Incorrect TypeCode or unsupported type.",
- [?LINE, Type], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 13), completion_status=?COMPLETED_MAYBE}).
-
-stringify_enum({tk_enum,_,_,_}, Label) ->
- atom_to_list(Label);
-stringify_enum(_, Label) ->
- Label.
-
-%%-----------------------------------------------------------------
-%% Func: dec_fixed
-%%-----------------------------------------------------------------
-%% Digits eq. total number of digits.
-%% Scale eq. position of the decimal point.
-%% E.g. fixed<5,2> - "123.45"
-%% E.g. fixed<4,2> - "12.34"
-%% These are encoded as:
-%% ## <5,2> ## ## <4,2> ##
-%% 1,2 0,1 eq. 1 octet
-%% 3,4 2,3
-%% 5,0xC 4,0xC
-%%
-%% Each number is encoded as a half-octet. Note, for <4,2> a zero is
-%% added first to to be able to create "even" octets.
-dec_fixed(0, 0, Bytes, Len, C) ->
- {#fixed{digits = 0, scale = 0, value = ""}, Bytes, Len, C};
-dec_fixed(Digits, Scale, Bytes, Len, C) ->
- case ?ODD(Digits) of
- true ->
- {Fixed, Bytes2, Len2, C2, Sign} = dec_fixed_2(Digits, Scale, Bytes, Len, C),
- case Sign of
- ?FIXED_POSITIVE ->
- {#fixed{digits = Digits, scale = Scale,
- value = list_to_integer(Fixed)}, Bytes2, Len2, C2};
- ?FIXED_NEGATIVE ->
- {#fixed{digits = Digits, scale = Scale,
- value = -list_to_integer(Fixed)}, Bytes2, Len2, C2}
- end;
- false ->
- %% If the length (of fixed) is even a zero is added first.
- %% Subtract that we've read 1 digit.
- <<0:4,D2:4,T/binary>> = Bytes,
- {Fixed, Bytes2, Len2, C2, Sign} = dec_fixed_2(Digits-1, Scale, T, Len+1, C+1),
- case Sign of
- ?FIXED_POSITIVE ->
- {#fixed{digits = Digits, scale = Scale,
- value = list_to_integer([D2+48|Fixed])}, Bytes2, Len2, C2};
- ?FIXED_NEGATIVE ->
- {#fixed{digits = Digits, scale = Scale,
- value = -list_to_integer([D2+48|Fixed])}, Bytes2, Len2, C2}
- end
- end.
-
-dec_fixed_2(1, _Scale, <<D1:4,?FIXED_POSITIVE:4,T/binary>>, Len, C) ->
- {[D1+48], T, Len+1, C+1, ?FIXED_POSITIVE};
-dec_fixed_2(1, _Scale, <<D1:4,?FIXED_NEGATIVE:4,T/binary>>, Len, C) ->
- {[D1+48], T, Len+1, C+1, ?FIXED_NEGATIVE};
-dec_fixed_2(Digits, Scale, _Bytes, _Len, _C) when Digits =< 0 ->
- orber:dbg("[~p] cdr_decode:dec_fixed_2(~p, ~p)~n"
- "Malformed fixed type.", [?LINE, Digits, Scale], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 14), completion_status=?COMPLETED_MAYBE});
-dec_fixed_2(Digits, Scale, <<>>, _Len, _C) ->
- orber:dbg("[~p] cdr_decode:dec_fixed_2(~p, ~p)~n"
- "The fixed type received was to short.",
- [?LINE, Digits, Scale], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 14), completion_status=?COMPLETED_MAYBE});
-dec_fixed_2(Digits, Scale, <<D1:4,D2:4,T/binary>>, Len, C) ->
- {Seq, Rest2, Len2, NewC2, Sign} = dec_fixed_2(Digits-2, Scale, T, Len+1, C+1),
- {[D1+48, D2+48 | Seq], Rest2, Len2, NewC2, Sign}.
-
-%%-----------------------------------------------------------------
-%% Func: dec_sequence/7 and dec_sequence/8
-%%-----------------------------------------------------------------
-dec_sequence(_Version, Message, 'tk_octet', Len, ByteOrder, _Buff, C) ->
- {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
- {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
- <<OctetSeq:Size/binary, Rest2/binary>> = Rest1,
- {binary_to_list(OctetSeq), Rest2, Len1+4+Size, NewC+4+Size};
-dec_sequence(_Version, Message, 'tk_char', Len, ByteOrder, _Buff, C) ->
- {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
- {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
- <<OctetSeq:Size/binary, Rest2/binary>> = Rest1,
- {binary_to_list(OctetSeq), Rest2, Len1+4+Size, NewC+4+Size};
-%% We test if it's a sequence of struct's or unions. By doing this we only
-%% have to look up the IFR-ID once instead of N times (N eq length of sequence).
-dec_sequence(Version, Message, {'tk_struct', IFRId, ShortName, ElementList},
- Len, ByteOrder, Buff, C) when IFRId /= "", ShortName /= "" ->
- {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
- {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
- case IFRId of
- ?SYSTEM_TYPE ->
- dec_sequence_struct(Version, Rest1, Size, ElementList, Len1 + 4,
- ByteOrder, Buff, NewC+4, ShortName);
- _ ->
- Name = ifrid_to_name(IFRId, ?IFR_StructDef),
- dec_sequence_struct(Version, Rest1, Size, ElementList, Len1 + 4,
- ByteOrder, Buff, NewC+4, Name)
- end;
-dec_sequence(Version, Message,
- {'tk_union', ?SYSTEM_TYPE, TCName, DiscrTC, Default, ElementList},
- Len, ByteOrder, Buff, C) ->
- {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
- {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
- dec_sequence_union(Version, Rest1, Size, DiscrTC, Default, ElementList, Len1 + 4,
- ByteOrder, Buff, NewC+4, TCName);
-dec_sequence(Version, Message,
- {'tk_union', IFRId, _TCName, DiscrTC, Default, ElementList},
- Len, ByteOrder, Buff, C) ->
- {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
- {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
- Name = ifrid_to_name(IFRId, ?IFR_UnionDef),
- dec_sequence_union(Version, Rest1, Size, DiscrTC, Default, ElementList, Len1 + 4,
- ByteOrder, Buff, NewC+4, Name);
-dec_sequence(Version, Message, TypeCode, Len, ByteOrder, Buff, C) ->
- {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
- {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
- dec_sequence(Version, Rest1, Size, TypeCode, Len1 + 4, ByteOrder, Buff, NewC+4).
-
-
-dec_sequence(_, Message, 0, _Type, Len, _ByteOrder, _Buff, C) ->
- {[], Message, Len, C};
-dec_sequence(Version, Message, N, Type, Len, ByteOrder, Buff, C) ->
- {Object, Rest1, Len1, NewC} = dec_type(Type, Version, Message, Len, ByteOrder, Buff, C),
- {Seq, Rest2, Len2, NewC2} = dec_sequence(Version, Rest1, N - 1, Type, Len1, ByteOrder, Buff, NewC),
- {[Object | Seq], Rest2, Len2, NewC2}.
-
-dec_sequence_struct(_, Message, 0, _Type, Len, _ByteOrder, _Buff, C, _Name) ->
- {[], Message, Len, C};
-dec_sequence_struct(Version, Message, N, TypeCodeList, Len, ByteOrder, Buff, C, Name) ->
- {Struct, Rest1, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C),
- {Seq, Rest2, Len2, NewC2} = dec_sequence_struct(Version, Rest1, N - 1, TypeCodeList, Len1, ByteOrder,
- Buff, NewC, Name),
- {[list_to_tuple([Name |Struct]) | Seq], Rest2, Len2, NewC2}.
-
-
-dec_sequence_union(_, Message, 0, _DiscrTC, _Default, _ElementList,
- Len, _ByteOrder, _Buff, C, _Name) ->
- {[], Message, Len, C};
-dec_sequence_union(Version, Message, N, DiscrTC, Default, ElementList,
- Len, ByteOrder, Buff, C, Name) when is_list(ElementList) ->
-
- {Label, Rest1, Len1, NewC} = dec_type(DiscrTC, Version, Message, Len, ByteOrder, Buff, C),
- Result = dec_union(Version, stringify_enum(DiscrTC, Label), ElementList, Default,
- Rest1, Len1, ByteOrder, Buff, NewC),
- {Value, Rest2, Len2, NewC3} = case Result of
- {default, R, L, NewC2} ->
- dec_union(Version, default, ElementList, Default,
- R, L, ByteOrder, Buff, NewC2);
- X ->
- X
- end,
- {Seq, Rest3, Len3, NewC4} = dec_sequence_union(Version, Rest2, N - 1,
- DiscrTC, Default, ElementList,
- Len2, ByteOrder,
- Buff, NewC3, Name),
- {[{Name, Label, Value} | Seq], Rest3, Len3, NewC4};
-dec_sequence_union(Version, Message, N, _DiscrTC, _Default, Module,
- Len, ByteOrder, Buff, C, Name) when is_atom(Module) ->
- case catch Module:tc() of
- {tk_union, _, _, DiscrTC, Default, ElementList} ->
- dec_sequence_union(Version, Message, N, DiscrTC, Default, ElementList,
- Len, ByteOrder, Buff, C, Name);
- What ->
- orber:dbg("[~p] ~p:dec_sequence_union(~p). Union module doesn't exist or incorrect.",
- [?LINE, ?MODULE, What], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE})
- end.
-
-
-
-%% A special case; when something is encapsulated (i.e. sent as octet-sequence)
-%% we sometimes don not want the result to be converted to a list.
-dec_octet_sequence_bin(_Version, Message, Len, ByteOrder, _Buff, C) ->
- {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
- {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
- <<OctetSeq:Size/binary, Rest2/binary>> = Rest1,
- {OctetSeq, Rest2, Len1+4+Size, NewC+4+Size}.
-
-%%-----------------------------------------------------------------
-%% Func: dec_array/5
-%%-----------------------------------------------------------------
-dec_array(Version, Message, Size, TypeCode, Len, ByteOrder, Buff, C) ->
- {Seq, Rest1, Len1, NewC} = dec_sequence(Version, Message, Size, TypeCode, Len,
- ByteOrder, Buff, C),
- {list_to_tuple(Seq), Rest1, Len1, NewC}.
-
-
-%%-----------------------------------------------------------------
-%% Func: dec_string/4
-%%-----------------------------------------------------------------
-dec_string(_Version, Message, Len, ByteOrder, _Buff, C) ->
- {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
- {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
- if
- Size > 0 ->
- DataSize = Size-1,
- <<String:DataSize/binary, _Null:1/binary, Rest2/binary>> = Rest1,
- {binary_to_list(String), Rest2, Len1+4+Size, NewC+4+Size};
- true ->
- {"", Rest1, Len1 + 4, NewC+4}
- end.
-
-%%-----------------------------------------------------------------
-%% Func: dec_string/4
-%%-----------------------------------------------------------------
-dec_wstring({1,2}, Message, Len, ByteOrder, Buff, C) ->
- {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
- {Octets, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
- if
- Octets == 0 ->
- {"", Rest1, Len1 + 4, NewC+4};
- Octets > 0 ->
- Size = round(Octets/2),
- {String, Rest2, Len2, NewC2} =
- dec_sequence({1,2}, Rest1, Size, 'tk_ushort',
- Len1 + 4, big, Buff, NewC+4),
- {String, Rest2, Len2, NewC2};
- true ->
- orber:dbg("[~p] cdr_decode:dec_wstring(~p);",
- [?LINE, Rest1], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO})
- end;
-dec_wstring(Version, Message, Len, ByteOrder, Buff, C) ->
- {Rest, Len1, NewC} = dec_align(Message, Len, 4, C),
- {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
- if
- Size > 0 ->
- {String, Rest2, Len2, NewC2} = dec_sequence(Version, Rest1, Size - 1, 'tk_wchar',
- Len1 + 4, ByteOrder, Buff, NewC+4),
- %% Remove the NULL character.
- {_, Rest3} = cdrlib:dec_unsigned_short(ByteOrder, Rest2),
- {String, Rest3, Len2 + 2, NewC2+2};
- Size == 0 ->
- {"", Rest1, Len1 + 4, NewC+4};
- true ->
- orber:dbg("[~p] cdr_decode:dec_wstring(~p);",
- [?LINE, Rest1], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO})
- end.
-
-
-%%-----------------------------------------------------------------
-%% Func: dec_union/9
-%%-----------------------------------------------------------------
-%% ## NEW IIOP 1.2 ##
-dec_union(Version, ?SYSTEM_TYPE, Name, DiscrTC, Default, ElementList, Bytes,
- Len, ByteOrder, Buff, C) ->
- {Label, Rest1, Len1, NewC} = dec_type(DiscrTC, Version, Bytes, Len, ByteOrder, Buff, C),
- {Value, Rest2, Len2, NewC3} = dec_union(Version, Label, ElementList, Default,
- Rest1, Len1, ByteOrder, Buff, NewC),
- {{Name, Label, Value}, Rest2, Len2, NewC3};
-
-
-dec_union(Version, IFRId, _, DiscrTC, Default, ElementList, Bytes, Len,
- ByteOrder, Buff, C) when is_list(ElementList) ->
- {Label, Rest1, Len1, NewC} = dec_type(DiscrTC, Version, Bytes, Len, ByteOrder, Buff, C),
- Result = dec_union(Version, stringify_enum(DiscrTC, Label), ElementList, Default,
- Rest1, Len1, ByteOrder, Buff, NewC),
- {Value, Rest2, Len2, NewC3} = case Result of
- {default, R, L, NewC2} ->
- dec_union(Version, default, ElementList, Default,
- R, L, ByteOrder, Buff, NewC2);
- X ->
- X
- end,
- Name = ifrid_to_name(IFRId, ?IFR_UnionDef),
- {{Name, Label, Value}, Rest2, Len2, NewC3};
-dec_union(Version, IFRId, _, _DiscrTC, _Default, Module, Bytes, Len,
- ByteOrder, Buff, C) when is_atom(Module) ->
- case catch Module:tc() of
- {tk_union, _, Name, DiscrTC, Default, ElementList} ->
- dec_union(Version, IFRId, Name, DiscrTC, Default, ElementList, Bytes, Len,
- ByteOrder, Buff, C);
- What ->
- orber:dbg("[~p] ~p:dec_union(~p). Union module doesn't exist or incorrect.",
- [?LINE, ?MODULE, What], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE})
- end.
-
-
-
-dec_union(_, _, [], Default, Message, Len, _, _Buff, C) when Default < 0 ->
- {undefined, Message, Len, C};
-dec_union(_, _, [], _Default, Message, Len, _, _Buff, C) ->
- {default, Message, Len, C};
-dec_union(Version, Label, [{Label, _Name, Type}|_List], _Default, Message, Len, ByteOrder, Buff, C) ->
- dec_type(Type, Version, Message, Len, ByteOrder, Buff, C);
-dec_union(Version, Label, [_H|List], Default, Message, Len, ByteOrder, Buff, C) ->
- dec_union(Version, Label, List, Default, Message, Len, ByteOrder, Buff, C).
-
-%%-----------------------------------------------------------------
-%% Func: dec_struct/7
-%%-----------------------------------------------------------------
-dec_struct(Version, "", "", TypeCodeList, Message, Len, ByteOrder, Buff, C) ->
- {Struct, Rest, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C),
- {list_to_tuple(Struct), Rest, Len1, NewC};
-dec_struct(Version, [], Name, TypeCodeList, Message, Len, ByteOrder, Buff, C) ->
- %% This case is used when communicating with ORB:s which don't supply the IFRId
- %% field in struct type codes (used in any)
- {Struct, Rest, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C),
- {list_to_tuple([list_to_atom(Name) |Struct]), Rest, Len1, NewC};
-dec_struct(Version, ?SYSTEM_TYPE, ShortName, TypeCodeList, Message, Len, ByteOrder, Buff, C) ->
- {Struct, Rest, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C),
- {list_to_tuple([ShortName |Struct]), Rest, Len1, NewC};
-dec_struct(Version, IFRId, _ShortName, TypeCodeList, Message, Len, ByteOrder, Buff, C) ->
- Name = ifrid_to_name(IFRId, ?IFR_StructDef),
- {Struct, Rest, Len1, NewC} = dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C),
- {list_to_tuple([Name |Struct]), Rest, Len1, NewC}.
-
-dec_struct1(_, [], Message, Len, _ByteOrder, _, C) ->
- {[], Message, Len, C};
-dec_struct1(Version, [{_ElemName, ElemType} | TypeCodeList], Message, Len, ByteOrder, Buff, C) ->
- {Element, Rest, Len1, NewC} = dec_type(ElemType, Version, Message, Len, ByteOrder, Buff, C),
- {Struct, Rest1, Len2, NewC2} = dec_struct1(Version, TypeCodeList, Rest, Len1, ByteOrder, Buff, NewC),
- {[Element |Struct], Rest1, Len2, NewC2};
-dec_struct1(Version, Module, Message, Len, ByteOrder, Buff, C) ->
- case catch Module:tc() of
- {tk_struct, _, _, TypeCodeList} ->
- dec_struct1(Version, TypeCodeList, Message, Len, ByteOrder, Buff, C);
- What ->
- orber:dbg("[~p] ~p:dec_struct1(~p). Struct module doesn't exist or incorrect.",
- [?LINE, ?MODULE, What], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE})
- end.
-
-ifrid_to_name([], Type) ->
- orber:dbg("[~p] ~p:ifrid_to_name([], ~p). No Id supplied.",
- [?LINE, ?MODULE, Type], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?CORBA_OMGVMCID bor 11),
- completion_status=?COMPLETED_MAYBE});
-ifrid_to_name(Id, Type) ->
- case orber:light_ifr() of
- true ->
- orber_ifr:get_module(Id, Type);
- false ->
- case catch ifrid_to_name_helper(Id, Type) of
- {'EXCEPTION', E} ->
- corba:raise(E);
- {'EXIT',{aborted,{no_exists,_}}} ->
- case orber:get_lightweight_nodes() of
- false ->
- orber:dbg("[~p] cdr_decode:ifrid_to_name(~p, ~p). IFRid not found.",
- [?LINE, Id, Type], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE});
- Nodes ->
- L = length(Nodes),
- IFR = get_ifr_node(Nodes, rand:uniform(L), L),
- list_to_atom('OrberApp_IFR':get_absolute_name(IFR, Id))
- end;
- {'EXIT', Other} ->
- orber:dbg("[~p] cdr_decode:ifrid_to_name(~p). Unknown: ~p",
- [?LINE, Id, Other], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE});
- Name ->
- list_to_atom(Name)
- end
- end.
-
-ifrid_to_name_helper(Id, ?IFR_UnionDef) ->
- case mnesia:dirty_index_read(ir_UnionDef, Id, #ir_UnionDef.id) of
- [#ir_UnionDef{absolute_name = [$:,$:|N]}] ->
- change_colons_to_underscore(N, []);
- Other ->
- orber:dbg("[~p] cdr_decode:ifrid_to_name(~p). IFR Id not found: ~p",
- [?LINE, Id, Other], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 9),
- completion_status=?COMPLETED_MAYBE})
- end;
-ifrid_to_name_helper(Id, ?IFR_StructDef) ->
- case mnesia:dirty_index_read(ir_StructDef, Id, #ir_StructDef.id) of
- [#ir_StructDef{absolute_name = [$:,$:|N]}] ->
- change_colons_to_underscore(N, []);
- Other ->
- orber:dbg("[~p] cdr_decode:ifrid_to_name(~p). IFR Id not found: ~p",
- [?LINE, Id, Other], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 10),
- completion_status=?COMPLETED_MAYBE})
- end;
-ifrid_to_name_helper(Id, ?IFR_ExceptionDef) ->
- case mnesia:dirty_index_read(ir_ExceptionDef, Id, #ir_ExceptionDef.id) of
- [#ir_ExceptionDef{absolute_name = [$:,$:|N]}] ->
- change_colons_to_underscore(N, []);
- Other ->
- orber:dbg("[~p] cdr_decode:ifrid_to_name(~p). IFR Id not found: ~p",
- [?LINE, Id, Other], ?DEBUG_LEVEL),
- corba:raise(#'UNKNOWN'{minor=(?CORBA_OMGVMCID bor 1),
- completion_status=?COMPLETED_MAYBE})
- end.
-
-change_colons_to_underscore([$:, $: | T], Acc) ->
- change_colons_to_underscore(T, [$_ |Acc]);
-change_colons_to_underscore([H |T], Acc) ->
- change_colons_to_underscore(T, [H |Acc]);
-change_colons_to_underscore([], Acc) ->
- lists:reverse(Acc).
-
-get_ifr_node([], _, _) ->
- %% Were not able to contact any of the given nodes.
- orber:dbg("[~p] cdr_decode:get_ifr_node([]). No Node available.",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{minor=(?ORBER_VMCID bor 1), completion_status=?COMPLETED_MAYBE});
-get_ifr_node(Nodes, N, L) ->
- Node = lists:nth(N, Nodes),
- case catch corba:resolve_initial_references_remote("OrberIFR", [Node]) of
- IFR when is_record(IFR, 'IOP_IOR') ->
- IFR;
- _ ->
- %% Not able to commincate with the node. Try next one.
- NewL = L-1,
- get_ifr_node(lists:delete(Node, Nodes), rand:uniform(NewL), NewL)
- end.
-
-
-%%-----------------------------------------------------------------
-%% Func: dec_objref/4
-%%-----------------------------------------------------------------
-dec_objref(Version, Message, Len, ByteOrder) ->
- dec_objref(Version, Message, Len, ByteOrder, [], 0).
-dec_objref(Version, Message, Len, ByteOrder, _Buff, C) ->
- {IOR, Rest, Length} = iop_ior:decode(Version, Message, Len, ByteOrder),
- {IOR, Rest, Length, C+Length-Len}.
-
-%%-----------------------------------------------------------------
-%% Func: dec_system_exception/4 and dec_user_exception/4
-%%-----------------------------------------------------------------
-dec_system_exception(Version, Message, Len, ByteOrder) when Version == {1,2} ->
- {Rest0, Len0, _Counter} = dec_align(Message, Len, 8, Len),
- {TypeId, Rest1, Len1} = dec_type({'tk_string', 0}, Version, Rest0, Len0, ByteOrder),
- Name = orber_exceptions:get_name(TypeId, ?SYSTEM_EXCEPTION),
- {Struct, _Rest2, Len2} =
- dec_exception_1(Version, [{"minor",'tk_ulong'},
- {"completed",
- {'tk_enum', "", "completion_status",
- ["COMPLETED_YES", "COMPLETED_NO",
- "COMPLETED_MAYBE"]}}],
- Rest1, Len1, ByteOrder),
- {list_to_tuple([Name, "" |Struct]), Len2};
-dec_system_exception(Version, Message, Len, ByteOrder) ->
- {TypeId, Rest1, Len1} = dec_type({'tk_string', 0}, Version, Message, Len, ByteOrder),
- Name = orber_exceptions:get_name(TypeId, ?SYSTEM_EXCEPTION),
- {Struct, _Rest2, Len2} =
- dec_exception_1(Version, [{"minor",'tk_ulong'},
- {"completed",
- {'tk_enum', "", "completion_status",
- ["COMPLETED_YES", "COMPLETED_NO",
- "COMPLETED_MAYBE"]}}],
- Rest1, Len1, ByteOrder),
- {list_to_tuple([Name, "" |Struct]), Len2}.
-
-dec_user_exception(Version, Message, Len, ByteOrder) when Version == {1,2} ->
- {Rest0, Len0, _Counter} = dec_align(Message, Len, 8, Len),
- {TypeId, Rest1, Len1} = dec_type({'tk_string', 0}, Version, Rest0, Len0, ByteOrder),
- Name = ifrid_to_name(TypeId, ?IFR_ExceptionDef),
- {'tk_except', _, _, ElementList} = get_user_exception_type(TypeId),
- {Struct, _Rest2, Len2} = dec_exception_1(Version, ElementList, Rest1, Len1,
- ByteOrder),
- {list_to_tuple([Name, TypeId |Struct]), Len2};
-dec_user_exception(Version, Message, Len, ByteOrder) ->
- {TypeId, Rest1, Len1} = dec_type({'tk_string', 0}, Version, Message, Len, ByteOrder),
- Name = ifrid_to_name(TypeId, ?IFR_ExceptionDef),
- {'tk_except', _, _, ElementList} = get_user_exception_type(TypeId),
- {Struct, _Rest2, Len2} = dec_exception_1(Version, ElementList, Rest1, Len1,
- ByteOrder),
- {list_to_tuple([Name, TypeId |Struct]), Len2}.
-
-dec_exception_1(_, [], Message, Len, _ByteOrder) ->
- {[], Message, Len};
-dec_exception_1(Version, [{_ElemName, ElemType} | ElementList], Message,
- Len, ByteOrder) ->
- {Element, Rest, Len1} = dec_type(ElemType, Version, Message, Len, ByteOrder),
- {Struct, Rest1, Len2} = dec_exception_1(Version, ElementList, Rest, Len1,
- ByteOrder),
- {[Element |Struct], Rest1, Len2}.
-
-
-get_user_exception_type(TypeId) ->
- case orber:light_ifr() of
- true ->
- orber_ifr:get_tc(TypeId, ?IFR_ExceptionDef);
- false ->
- case orber:get_lightweight_nodes() of
- false ->
- case mnesia:dirty_index_read(ir_ExceptionDef, TypeId,
- #ir_ExceptionDef.id) of
- [ExcDef] when is_record(ExcDef, ir_ExceptionDef) ->
- ExcDef#ir_ExceptionDef.type;
- Other ->
- orber:dbg("[~p] cdr_decode:get_user_exception_type(~p). IFR Id not found: ~p",
- [?LINE, TypeId, Other], ?DEBUG_LEVEL),
- corba:raise(#'UNKNOWN'{minor=(?CORBA_OMGVMCID bor 1),
- completion_status=?COMPLETED_MAYBE})
- end;
- Nodes ->
- L = length(Nodes),
- IFR = get_ifr_node(Nodes, rand:uniform(L), L),
- 'OrberApp_IFR':get_user_exception_type(IFR, TypeId)
- end
- end.
-
-%%-----------------------------------------------------------------
-%% Func: dec_type_code/4
-%%-----------------------------------------------------------------
-dec_type_code(Version, Message, Len, ByteOrder, Buff, C) ->
- {TypeNo, Message1, Len1, NewC} = dec_type('tk_ulong', Version, Message, Len, ByteOrder, Buff, C),
- TC = dec_type_code(TypeNo, Version, Message1, Len1, ByteOrder, Buff, NewC),
- erase(orber_indirection),
- TC.
-
-%%-----------------------------------------------------------------
-%% Func: dec_type_code/5
-%%-----------------------------------------------------------------
-dec_type_code(0, _, Message, Len, _, _, C) ->
- {'tk_null', Message, Len, C};
-dec_type_code(1, _, Message, Len, _, _, C) ->
- {'tk_void', Message, Len, C};
-dec_type_code(2, _, Message, Len, _, _, C) ->
- {'tk_short', Message, Len, C};
-dec_type_code(3, _, Message, Len, _, _, C) ->
- {'tk_long', Message, Len, C};
-dec_type_code(23, _, Message, Len, _, _, C) ->
- {'tk_longlong', Message, Len, C};
-dec_type_code(25, _, Message, Len, _, _, C) ->
- {'tk_longdouble', Message, Len, C};
-dec_type_code(4, _, Message, Len, _, _, C) ->
- {'tk_ushort', Message, Len, C};
-dec_type_code(5, _, Message, Len, _, _, C) ->
- {'tk_ulong', Message, Len, C};
-dec_type_code(24, _, Message, Len, _, _, C) ->
- {'tk_ulonglong', Message, Len, C};
-dec_type_code(6, _, Message, Len, _, _, C) ->
- {'tk_float', Message, Len, C};
-dec_type_code(7, _, Message, Len, _, _, C) ->
- {'tk_double', Message, Len, C};
-dec_type_code(8, _, Message, Len, _, _, C) ->
- {'tk_boolean', Message, Len, C};
-dec_type_code(9, _, Message, Len, _, _, C) ->
- {'tk_char', Message, Len, C};
-dec_type_code(26, _, Message, Len, _, _, C) ->
- {'tk_wchar', Message, Len, C};
-dec_type_code(10, _, Message, Len, _, _, C) ->
- {'tk_octet', Message, Len, C};
-dec_type_code(11, _, Message, Len, _, _, C) ->
- {'tk_any', Message, Len, C};
-dec_type_code(12, _, Message, Len, _, _, C) ->
- {'tk_TypeCode', Message, Len, C};
-dec_type_code(13, _, Message, Len, _, _, C) ->
- {'tk_Principal', Message, Len, C};
-dec_type_code(14, Version, Message, Len, ByteOrder, Buff, C) ->
- {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
- %% Decode marshalled parameters, eg get the byteorder first
- {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
- {{RepId, Name}, <<>>, _Len2, NewC} =
- dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
- {"name", {'tk_string', 0}}]},
- Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
- {{'tk_objref', RepId, Name}, Message1, Len1, NewC};
-dec_type_code(15, Version, Message, Len, ByteOrder, Buff, C) ->
- {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
- %% Decode marshalled parameters, eg get the byteorder first
- {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
- {{RepId, Name, ElementList}, <<>>, _Len2, NewC} =
- dec_type({'tk_struct', "", "",
- [{"repository ID", {'tk_string', 0}},
- {"name", {'tk_string', 0}},
- {"element list",
- {'tk_sequence', {'tk_struct', "","",
- [{"member name", {'tk_string', 0}},
- {"member type", 'tk_TypeCode'}]},
- 0}}]},
- Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
- {{'tk_struct', RepId, Name, ElementList}, Message1, Len1, NewC};
-dec_type_code(16, Version, Message, Len, ByteOrder, Buff, C) ->
- {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
- %% Decode marshalled parameters, eg get the byteorder first
- {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
- {{RepId, Name, DiscrTC, Default}, Rest2, RestLen2, NewC} =
- dec_type({'tk_struct', "", "",
- [{"repository ID", {'tk_string', 0}},
- {"name", {'tk_string', 0}},
- {"discriminant type", 'tk_TypeCode'},
- {"default used", 'tk_long'}]},
- Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
- {ElementList, <<>>, _RestLen3, NewC2} =
- dec_type({'tk_sequence', {'tk_struct', "","",
- [{"label value", DiscrTC},
- {"member name", {'tk_string', 0}},
- {"member type", 'tk_TypeCode'}]}, 0},
- Version, Rest2, RestLen2, ByteOrder1, Buff, NewC),
- NewElementList =
- case check_enum(DiscrTC) of
- true ->
- lists:map(fun({L,N,T}) -> {atom_to_list(L),N,T} end, ElementList);
- false ->
- ElementList
- end,
- {{'tk_union', RepId, Name, DiscrTC, Default, NewElementList}, Message1, Len1, NewC2};
-dec_type_code(17, Version, Message, Len, ByteOrder, Buff, C) ->
- {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
- %% Decode marshalled parameters, eg get the byteorder first
- {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
- {{RepId, Name, ElementList}, <<>>, _Len2, NewC} =
- dec_type({'tk_struct', "", "",
- [{"repository ID", {'tk_string', 0}},
- {"name", {'tk_string', 0}},
- {"element list",
- {'tk_sequence', {'tk_string', 0}, 0}}]},
- Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
- {{'tk_enum', RepId, Name, ElementList}, Message1, Len1, NewC};
-dec_type_code(18, Version, Message, Len, ByteOrder, Buff, C) ->
- {MaxLength, Message1, Len1, NewC} =
- dec_type('tk_ulong', Version, Message, Len, ByteOrder, Buff, C),
- {{'tk_string', MaxLength}, Message1, Len1, NewC};
-dec_type_code(19, Version, Message, Len, ByteOrder, Buff, C) ->
- {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
- %% Decode marshalled parameters, eg get the byteorder first
- {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
- {{ElemTC, MaxLength}, <<>>, _Len2, NewC} =
- dec_type({'tk_struct', "", "", [{"element type", 'tk_TypeCode'},
- {"max length", 'tk_ulong'}]},
- Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
- {{'tk_sequence', ElemTC, MaxLength}, Message1, Len1, NewC};
-dec_type_code(20, Version, Message, Len, ByteOrder, Buff, C) ->
- {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
- %% Decode marshalled parameters, eg get the byteorder first
- {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
- {{ElemTC, Length}, <<>>, _Len2, NewC} =
- dec_type({'tk_struct', "", "", [{"element type", 'tk_TypeCode'},
- {"length", 'tk_ulong'}]},
- Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
- {{'tk_array', ElemTC, Length}, Message1, Len1, NewC};
-dec_type_code(21, Version, Message, Len, ByteOrder, Buff, C) ->
- {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
- %% Decode marshalled parameters, eg ge a byteorder first
- {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
- {{RepId, Name, TC}, <<>>, _Len2, NewC} =
- dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
- {"name", {'tk_string', 0}},
- {"TypeCode", 'tk_TypeCode'}]},
- Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
- {{'tk_alias', RepId, Name, TC}, Message1, Len1, NewC};
-dec_type_code(22, Version, Message, Len, ByteOrder, Buff, C) ->
- {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
- %% Decode marshalled parameters, eg get the byteorder first
- {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
- {{RepId, Name, ElementList}, <<>>, _Len2, NewC} =
- dec_type({'tk_struct', "", "",
- [{"repository ID", {'tk_string', 0}},
- {"name", {'tk_string', 0}},
- {"element list",
- {'tk_sequence', {'tk_struct', "","",
- [{"member name", {'tk_string', 0}},
- {"member type", 'tk_TypeCode'}]},
- 0}}]},
- Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
- {{'tk_except', RepId, Name, ElementList}, Message1, Len1, NewC};
-dec_type_code(27, Version, Message, Len, ByteOrder, Buff, C) ->
- {MaxLength, Message1, Len1, NewC} =
- dec_type('tk_ulong', Version, Message, Len, ByteOrder, Buff, C),
- {{'tk_wstring', MaxLength}, Message1, Len1, NewC};
-dec_type_code(28, Version, Message, Len, ByteOrder, Buff, C) ->
- {Digits, Message1, Len1, C1} =
- dec_type('tk_ushort', Version, Message, Len, ByteOrder, Buff, C),
- {Scale, Message2, Len2, C2} =
- dec_type('tk_short', Version, Message1, Len1, ByteOrder, Buff, C1),
- {{'tk_fixed', Digits, Scale}, Message2, Len2, C2};
-dec_type_code(29, Version, Message, Len, ByteOrder, Buff, C) ->
- {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
- {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
- {{RepId, Name, ValueModifier, TC, ElementList}, <<>>, _Len2, NewC} =
- dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
- {"name", {'tk_string', 0}},
- {"ValueModifier", 'tk_short'},
- {"TypeCode", 'tk_TypeCode'},
- {"element list",
- {'tk_sequence',
- {'tk_struct', "","",
- [{"member name", {'tk_string', 0}},
- {"member type", 'tk_TypeCode'},
- {"Visibility", 'tk_short'}]},
- 0}}]},
- Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
- {{'tk_value', RepId, Name, ValueModifier, TC, ElementList}, Message1, Len1, NewC};
-dec_type_code(30, Version, Message, Len, ByteOrder, Buff, C) ->
- {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
- {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
- {{RepId, Name, TC}, <<>>, _Len2, NewC} =
- dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
- {"name", {'tk_string', 0}},
- {"TypeCode", 'tk_TypeCode'}]},
- Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
- {{'tk_value_box', RepId, Name, TC}, Message1, Len1, NewC};
-dec_type_code(31, Version, Message, Len, ByteOrder, Buff, C) ->
- {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
- {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
- {{RepId, Name}, <<>>, _Len2, NewC} =
- dec_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
- {"name", {'tk_string', 0}}]},
- Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
- {{'tk_native', RepId, Name}, Message1, Len1, NewC};
-dec_type_code(32, Version, Message, Len, ByteOrder, Buff, C) ->
- {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
- {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
- {{RepId, Name}, <<>>, _Len2, NewC} =
- dec_type({'tk_struct', "", "", [{"RepositoryId", {'tk_string', 0}},
- {"name", {'tk_string', 0}}]},
- Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
- {{'tk_abstract_interface', RepId, Name}, Message1, Len1, NewC};
-dec_type_code(33, Version, Message, Len, ByteOrder, Buff, C) ->
- {ComplexParams, Message1, Len1, Ex} = decode_complex_tc_parameters(Version, Message, Len, ByteOrder),
- {ByteOrder1, Rest1} = dec_byte_order(ComplexParams),
- {{RepId, Name}, <<>>, _Len2, NewC} =
- dec_type({'tk_struct', "", "", [{"RepositoryId", {'tk_string', 0}},
- {"name", {'tk_string', 0}}]},
- Version, Rest1, 1, ByteOrder1, Buff, C+1+Ex),
- {{'tk_local_interface', RepId, Name}, Message1, Len1, NewC};
-dec_type_code(16#ffffffff, Version, Message, Len, ByteOrder, Buff, C) ->
- {Indirection, Message1, Len1, NewC} =
- dec_type('tk_long', Version, Message, Len, ByteOrder, Buff, C),
- Position = C+Indirection,
- case put(orber_indirection, Position) of
- Position ->
-%% {{'none', Indirection}, Message1, Len1, NewC};
- %% Recursive TypeCode. Break the loop.
- orber:dbg("[~p] cdr_decode:dec_type_code(~p); Recursive TC not supported.",
- [?LINE,Position], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO});
- _ ->
- <<_:Position/binary, SubBuff/binary>> = Buff,
- {TC, _, _, _} = dec_type_code(Version, SubBuff, Position, ByteOrder, Buff, Position),
- {TC, Message1, Len1, NewC}
- end;
-dec_type_code(Type, _, _, _, _, _, _) ->
- orber:dbg("[~p] cdr_decode:dec_type_code(~p); No match.",
- [?LINE, Type], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 8), completion_status=?COMPLETED_MAYBE}).
-
-check_enum({'tk_enum', _, _, _}) ->
- true;
-check_enum(_) ->
- false.
-
-
-decode_complex_tc_parameters(_Version, Message, Len, ByteOrder) ->
- {Rest, Len1, NewC} = dec_align(Message, Len, 4, 0),
- {Size, Rest1} = cdrlib:dec_unsigned_long(ByteOrder, Rest),
- <<OctetSeq:Size/binary, Rest2/binary>> = Rest1,
- {OctetSeq, Rest2, Len1+4+Size, NewC+4}.
-
-%%-----------------------------------------------------------------
-%% Func: dec_align/3
-%% Args:
-%% R - The byte sequence that shall be aligned.
-%% Len - The number of bytes read so far.
-%% Alignment - The alignment as an integer (for example: 2,4,8).
-%% Returns:
-%% An aligned byte sequence.
-%%-----------------------------------------------------------------
-dec_align(R, Len, Alignment, C) ->
- Rem = Len rem Alignment,
- if Rem == 0 ->
- {R, Len, C};
- true ->
- Diff = Alignment - Rem,
- <<_:Diff/binary,Rest/binary>> = R,
- {Rest, Len + Diff, C + Diff}
- end.
-
-%%---------------- EOF MODULE ----------------------------------------
diff --git a/lib/orber/src/cdr_encode.erl b/lib/orber/src/cdr_encode.erl
deleted file mode 100644
index 2c42d5bd7e..0000000000
--- a/lib/orber/src/cdr_encode.erl
+++ /dev/null
@@ -1,1172 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: cdr_encode.erl
-%%
-%% Description:
-%% This file contains all encoding functions for the CDR
-%% format.
-%%
-%%-----------------------------------------------------------------
--module(cdr_encode).
-
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([enc_giop_msg_type/1,
- enc_request/1, enc_request_split/1,
- enc_reply/1, enc_reply_split/1,
- enc_type/3, enc_type/5,
- enc_cancel_request/1,
- enc_locate_request/1,
- enc_locate_reply/1,
- enc_close_connection/1,
- enc_message_error/1,
- enc_fragment/1,
- enc_giop_message_header/5,
- validate_request_body/1,
- validate_reply_body/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
--define(DEBUG_LEVEL, 9).
-
--define(ODD(N), (N rem 2) == 1).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: enc_giop_message_header/5
-%%-----------------------------------------------------------------
-%% The header size is known so we know that the size will be aligned.
-%% MessSize already includes the header length.
-%%-----------------------------------------------------------------
-enc_giop_message_header(#giop_env{version = {Major,Minor}}, MessType,
- _Flags, MessSize, Message) ->
- Type = enc_giop_msg_type(MessType),
- %% The Flag handling must be fixed, i.e., it's not correct to only use '0'.
- %% If IIOP-1.0 a boolean (FALSE == 0), otherwise, IIOP-1.1 or 1.2,
- %% an octet. The octet bits represents:
- %% * The least significant the byteorder (0 eq. big-endian)
- %% * The second least significant indicates if the message is fragmented.
- %% If set to 0 it's not fragmented.
- %% * The most significant 6 bits are reserved. Hence, must be set to 0.
- %% Since we currently don't support fragmented messages and we always
- %% encode using big-endian it's ok to use '0' for now.
- list_to_binary([ <<"GIOP",Major:8,Minor:8,0:8,
- Type:8,MessSize:32/big-unsigned-integer>> | Message]).
-
-enc_byte_order(Env, Message) ->
- enc_type('tk_boolean', Env, 'false', Message, 0).
-
-%%-----------------------------------------------------------------
-%% Func: enc_parameters/2
-%%-----------------------------------------------------------------
-enc_parameters(_, [], [], Message, Len) ->
- {Message, Len};
-enc_parameters(_, [], P, _, _) ->
- orber:dbg("[~p] cdr_encode:encode_parameters(~p); to many parameters.",
- [?LINE, P], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 17), completion_status=?COMPLETED_MAYBE});
-enc_parameters(_, _, [], TC, _) ->
- orber:dbg("[~p] cdr_encode:encode_parameters(~p); to few parameters.",
- [?LINE, TC], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 17), completion_status=?COMPLETED_MAYBE});
-enc_parameters(Env, [PT1 |TypeList], [ P1 | Parameters], Message, Len) ->
- {Message1, Len1} = enc_type(PT1, Env, P1, Message, Len),
- enc_parameters(Env, TypeList, Parameters, Message1, Len1).
-
-%%-----------------------------------------------------------------
-%% Func: enc_request/8
-%%-----------------------------------------------------------------
-%% ## NEW IIOP 1.2 ##
-enc_request(#giop_env{version = {1,2}} = Env) ->
- Flags = 1, %% LTH Not correct, just placeholder
- {Message, Len} = enc_request_id(Env, [], ?GIOP_HEADER_SIZE),
- {Message1, Len1} = enc_response_flags(Env, Message, Len),
- {Message2, Len2} = enc_reserved(Env, {0,0,0}, Message1, Len1),
- {Message3, Len3} = enc_target_address(Env, Message2, Len2),
- {Message4, Len4} = enc_operation(Env, Message3, Len3),
- {Message5, Len5} = enc_service_context(Env, Message4, Len4),
- {Message6, Len6} = enc_request_body(Env, Message5, Len5),
- enc_giop_message_header(Env, 'request', Flags, Len6 - ?GIOP_HEADER_SIZE,
- lists:reverse(Message6));
-enc_request(#giop_env{version = Version} = Env) ->
- Flags = 1, %% LTH Not correct, just placeholder
- {Message0, Len0} = enc_service_context(Env, [], ?GIOP_HEADER_SIZE),
- {Message, Len} = enc_request_id(Env, Message0, Len0),
- {Message1, Len1} = enc_response(Env, Message, Len),
- {Message1b, Len1b} =
- if
- Version /= {1,0} ->
- enc_reserved(Env, {0,0,0}, Message1, Len1);
- true ->
- {Message1, Len1}
- end,
- {Message2, Len2} = enc_object_key(Env, Message1b, Len1b),
- {Message3, Len3} = enc_operation(Env, Message2, Len2),
- {Message4, Len4} = enc_principal(Env, Message3, Len3),
- {Message5, Len5} = enc_request_body(Env, Message4, Len4),
- enc_giop_message_header(Env, 'request', Flags, Len5 - ?GIOP_HEADER_SIZE,
- lists:reverse(Message5)).
-
-%% ## NEW IIOP 1.2 ##
-enc_request_split(#giop_env{version = {1,2}} = Env) ->
- Flags = 1, %% LTH Not correct, just placeholder
- {Message, Len} = enc_request_id(Env, [], ?GIOP_HEADER_SIZE),
- {Message1, Len1} = enc_response_flags(Env, Message, Len),
- {Message2, Len2} = enc_reserved(Env, {0,0,0}, Message1, Len1),
- {Message3, Len3} = enc_target_address(Env, Message2, Len2),
- {Message4, Len4} = enc_operation(Env, Message3, Len3),
- {Message5, Len5} = enc_service_context(Env, Message4, Len4),
- {Body, Len6} = enc_request_body(Env, [], Len5),
- {lists:reverse(Message5), list_to_binary(lists:reverse(Body)),
- Len5 - ?GIOP_HEADER_SIZE, Len6-Len5, Flags};
-enc_request_split(#giop_env{version = Version} = Env) ->
- Flags = 1, %% LTH Not correct, just placeholder
- {Message0, Len0} = enc_service_context(Env, [], ?GIOP_HEADER_SIZE),
- {Message, Len} = enc_request_id(Env, Message0, Len0),
- {Message1, Len1} = enc_response(Env, Message, Len),
- {Message1b, Len1b} =
- if
- Version /= {1,0} ->
- enc_reserved(Env, {0,0,0}, Message1, Len1);
- true ->
- {Message1, Len1}
- end,
- {Message2, Len2} = enc_object_key(Env, Message1b, Len1b),
- {Message3, Len3} = enc_operation(Env, Message2, Len2),
- {Message4, Len4} = enc_principal(Env, Message3, Len3),
- {Body, Len5} = enc_request_body(Env, [], Len4),
- {lists:reverse(Message4), list_to_binary(lists:reverse(Body)),
- Len4 - ?GIOP_HEADER_SIZE, Len5-Len4, Flags}.
-
-enc_principal(Env, Mess, Len) ->
- enc_type({'tk_string', 0}, Env, atom_to_list(node()), Mess, Len).
-
-enc_operation(Env, Mess, Len) ->
- enc_type({'tk_string', 0}, Env, atom_to_list(Env#giop_env.op), Mess, Len).
-
-enc_object_key(Env, Mess, Len) ->
- enc_type({'tk_sequence', 'tk_octet', 0}, Env, Env#giop_env.objkey, Mess, Len).
-
-enc_reserved(Env, Reserved, Mess, Len) ->
- enc_type({'tk_array', 'tk_octet', 3}, Env, Reserved, Mess, Len).
-
-enc_response(Env, Mess, Len) ->
- enc_type('tk_boolean', Env, Env#giop_env.response_expected, Mess, Len).
-
-enc_request_id(Env, Mess, Len) ->
- enc_type('tk_ulong', Env, Env#giop_env.request_id, Mess, Len).
-
-enc_service_context(Env, Message, Len) ->
- Ctxs = enc_used_contexts(Env, Env#giop_env.ctx, []),
- enc_type(?IOP_SERVICECONTEXT, Env, Ctxs, Message, Len).
-
-enc_used_contexts(_Env, [], Message) ->
- Message;
-enc_used_contexts(#giop_env{version = {1, 0}} = Env,
- [#'IOP_ServiceContext'{context_id=?IOP_CodeSets}|T], Ctxs) ->
- %% Not supported by 1.0, drop it.
- enc_used_contexts(Env, T, Ctxs);
-enc_used_contexts(Env, [#'IOP_ServiceContext'{context_id=?IOP_CodeSets,
- context_data = CodeSetCtx}|T],
- Ctxs) ->
- %% Encode ByteOrder
- {Bytes0, Len0} = cdr_encode:enc_type('tk_octet', Env, 0, [], 0),
- {Bytes1, _Len1} = enc_type(?CONV_FRAME_CODESETCONTEXT, Env, CodeSetCtx,
- Bytes0, Len0),
- Bytes = list_to_binary(lists:reverse(Bytes1)),
- enc_used_contexts(Env, T,
- [#'IOP_ServiceContext'{context_id=?IOP_CodeSets,
- context_data = Bytes}|Ctxs]);
-enc_used_contexts(Env, [#'IOP_ServiceContext'{context_id=?IOP_BI_DIR_IIOP,
- context_data = BiDirCtx}|T],
- Ctxs) ->
- %% Encode ByteOrder
- {Bytes0, Len0} = cdr_encode:enc_type('tk_octet', Env, 0, [], 0),
- {Bytes1, _Len1} = enc_type(?IIOP_BIDIRIIOPSERVICECONTEXT, Env, BiDirCtx,
- Bytes0, Len0),
- Bytes = list_to_binary(lists:reverse(Bytes1)),
- enc_used_contexts(Env, T,
- [#'IOP_ServiceContext'{context_id=?IOP_BI_DIR_IIOP,
- context_data = Bytes}|Ctxs]);
-enc_used_contexts(Env, [#'IOP_ServiceContext'{context_id=?IOP_FT_REQUEST,
- context_data = Ctx}|T],
- Ctxs) ->
- %% Encode ByteOrder
- {Bytes0, Len0} = cdr_encode:enc_type('tk_octet', Env, 0, [], 0),
- {Bytes1, _Len1} = enc_type(?FT_FTRequestServiceContext, Env, Ctx,
- Bytes0, Len0),
- Bytes = list_to_binary(lists:reverse(Bytes1)),
- enc_used_contexts(Env, T,
- [#'IOP_ServiceContext'{context_id=?IOP_FT_REQUEST,
- context_data = Bytes}|Ctxs]);
-enc_used_contexts(Env, [#'IOP_ServiceContext'{context_id=?IOP_FT_GROUP_VERSION,
- context_data = Ctx}|T],
- Ctxs) ->
- %% Encode ByteOrder
- {Bytes0, Len0} = cdr_encode:enc_type('tk_octet', Env, 0, [], 0),
- {Bytes1, _Len1} = enc_type(?FT_FTGroupVersionServiceContext, Env, Ctx,
- Bytes0, Len0),
- Bytes = list_to_binary(lists:reverse(Bytes1)),
- enc_used_contexts(Env, T,
- [#'IOP_ServiceContext'{context_id=?IOP_FT_GROUP_VERSION,
- context_data = Bytes}|Ctxs]);
-enc_used_contexts(Env, [#'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = Ctx}|T],
- Ctxs) ->
- %% Encode ByteOrder
- {Bytes0, Len0} = cdr_encode:enc_type('tk_octet', Env, 0, [], 0),
- {Bytes1, _Len1} = enc_type(?CSI_SASContextBody, Env, Ctx,
- Bytes0, Len0),
- Bytes = list_to_binary(lists:reverse(Bytes1)),
- enc_used_contexts(Env, T,
- [#'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = Bytes}|Ctxs]);
-enc_used_contexts(Env, [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface, _I}}|T],
- Ctxs) ->
- %% This shall not be forwarded.
- enc_used_contexts(Env, T, Ctxs);
-enc_used_contexts(Env, [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {configuration, _O}}|T],
- Ctxs) ->
- %% This shall not be forwarded.
- enc_used_contexts(Env, T, Ctxs);
-enc_used_contexts(Env, [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = Ctx}|T],
- Ctxs) ->
- %% Encode ByteOrder
- {Bytes0, Len0} = cdr_encode:enc_type('tk_octet', Env, 0, [], 0),
- {Bytes1, _Len1} = enc_type(?ORBER_GENERIC_CTX, Env,
- binary_to_list(term_to_binary(Ctx)),
- Bytes0, Len0),
- Bytes = list_to_binary(lists:reverse(Bytes1)),
- enc_used_contexts(Env, T,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = Bytes}|Ctxs]);
-enc_used_contexts(Env, [H|T], Ctxs) ->
- enc_used_contexts(Env, T, [H|Ctxs]).
-
-%% ## NEW IIOP 1.2 ##
-enc_target_address(#giop_env{objkey = TargetAddr} = Env, Mess, Len)
- when is_record(TargetAddr, 'GIOP_TargetAddress') ->
- enc_type(?TARGETADDRESS, Env, TargetAddr, Mess, Len);
-enc_target_address(#giop_env{objkey = IORInfo} = Env, Mess, Len)
- when is_record(IORInfo, 'GIOP_IORAddressingInfo') ->
- enc_type(?TARGETADDRESS, Env, #'GIOP_TargetAddress'{label = ?GIOP_ReferenceAddr,
- value = IORInfo},
- Mess, Len);
-enc_target_address(#giop_env{objkey = TP} = Env, Mess, Len)
- when is_record(TP, 'IOP_TaggedProfile') ->
- enc_type(?TARGETADDRESS, Env, #'GIOP_TargetAddress'{label = ?GIOP_ProfileAddr,
- value = TP},
- Mess, Len);
-enc_target_address(#giop_env{objkey = ObjKey} = Env, Mess, Len) ->
- enc_type(?TARGETADDRESS, Env, #'GIOP_TargetAddress'{label = ?GIOP_KeyAddr,
- value = ObjKey},
- Mess, Len).
-
-%% FIX ME!! This is temporary, not proper flag handling.
-enc_response_flags(#giop_env{response_expected = true} = Env, Mess, Len) ->
- enc_type('tk_octet', Env, 3, Mess, Len);
-enc_response_flags(#giop_env{response_expected = false} = Env, Mess, Len) ->
- enc_type('tk_octet', Env, 0, Mess, Len).
-
-%%-----------------------------------------------------------------
-%% Func: enc_request_body/5
-%%-----------------------------------------------------------------
-enc_request_body(#giop_env{tc = {_, [], _}}, Message, Len) ->
- %% This case is used to avoid adding alignment even though no body will be added.
- {Message, Len};
-enc_request_body(#giop_env{version = {1,2},
- tc = {_RetType, InParameters, _OutParameters},
- parameters = Parameters} = Env,
- Message, Len) ->
- {Message1, Len1} = enc_align(Message, Len, 8),
- enc_parameters(Env, InParameters, Parameters, Message1, Len1);
-enc_request_body(#giop_env{tc = {_RetType, InParameters, _OutParameters},
- parameters = Parameters} = Env,
- Message, Len) ->
- enc_parameters(Env, InParameters, Parameters, Message, Len).
-
-%%-----------------------------------------------------------------
-%% Func: validate_request_body/1
-%%-----------------------------------------------------------------
-validate_request_body(#giop_env{tc = {_RetType, InParameters, _OutParameters},
- parameters = Parameters} = Env) ->
- enc_parameters(Env, InParameters, Parameters, [], 0).
-
-%%-----------------------------------------------------------------
-%% Func: enc_reply/6
-%%-----------------------------------------------------------------
-%% ## NEW IIOP 1.2 ##
-enc_reply(#giop_env{version = {1,2}} = Env) ->
- Flags = 1, %% LTH Not correct, just placeholder
- {Message, Len} = enc_request_id(Env, [], ?GIOP_HEADER_SIZE),
- {Message1, Len1} = enc_reply_status(Env, Message, Len),
- {Message2, Len2} = enc_service_context(Env, Message1, Len1),
- {Message3, Len3} = enc_reply_body(Env, Message2, Len2),
- enc_giop_message_header(Env, 'reply', Flags, Len3 - ?GIOP_HEADER_SIZE,
- lists:reverse(Message3));
-enc_reply(Env) ->
- Flags = 1, %% LTH Not correct, just placeholder
- {Message, Len} = enc_service_context(Env, [], ?GIOP_HEADER_SIZE),
- {Message1, Len1} = enc_request_id(Env, Message, Len),
- {Message2, Len2} = enc_reply_status(Env, Message1, Len1),
- {Message3, Len3} = enc_reply_body(Env, Message2, Len2),
- enc_giop_message_header(Env, 'reply', Flags, Len3 - ?GIOP_HEADER_SIZE,
- lists:reverse(Message3)).
-
-%% ## NEW IIOP 1.2 ##
-enc_reply_split(#giop_env{version = {1,2}} = Env) ->
- Flags = 1, %% LTH Not correct, just placeholder
- {Message, Len0} = enc_request_id(Env, [], ?GIOP_HEADER_SIZE),
- {Message1, Len1} = enc_reply_status(Env, Message, Len0),
- {Message2, Len2} = enc_service_context(Env, Message1, Len1),
- {Body, Len} = enc_reply_body(Env, [], Len2),
- {lists:reverse(Message2), list_to_binary(lists:reverse(Body)),
- Len2 - ?GIOP_HEADER_SIZE, Len-Len2, Flags};
-enc_reply_split(Env) ->
- Flags = 1, %% LTH Not correct, just placeholder
- {Message, Len0} = enc_service_context(Env, [], ?GIOP_HEADER_SIZE),
- {Message1, Len1} = enc_request_id(Env, Message, Len0),
- {Message2, Len2} = enc_reply_status(Env, Message1, Len1),
- {Body, Len} = enc_reply_body(Env, [], Len2),
- {lists:reverse(Message2), list_to_binary(lists:reverse(Body)),
- Len2 - ?GIOP_HEADER_SIZE, Len-Len2, Flags}.
-
-enc_reply_status(Env, Mess, Len) ->
- L = enc_giop_reply_status_type(Env#giop_env.reply_status),
- enc_type('tk_ulong', Env, L, Mess, Len).
-
-%%-----------------------------------------------------------------
-%% Func: enc_reply_body/6
-%%-----------------------------------------------------------------
-enc_reply_body(#giop_env{tc = {'tk_void', _, []}, result = ok,
- parameters = []}, Message, Len) ->
- %% This case is mainly to be able to avoid adding alignment for
- %% IIOP-1.2 messages if the body should be empty, i.e., void return value and
- %% no out parameters.
- {Message, Len};
-enc_reply_body(#giop_env{version = {1,2},
- tc = {RetType, _InParameters, OutParameters},
- parameters = Parameters, result = Result} = Env,
- Message, Len) ->
- {Message1, Len1} = enc_align(Message, Len, 8),
- {Message2, Len2} = enc_type(RetType, Env, Result, Message1, Len1),
- enc_parameters(Env, OutParameters, Parameters, Message2, Len2);
-enc_reply_body(#giop_env{tc = {RetType, _InParameters, OutParameters},
- parameters = Parameters, result = Result} = Env,
- Message, Len) ->
- {Message1, Len1} = enc_type(RetType, Env, Result, Message, Len),
- enc_parameters(Env, OutParameters, Parameters, Message1, Len1).
-
-
-%%-----------------------------------------------------------------
-%% Func: validate_reply_body/3
-%%-----------------------------------------------------------------
-validate_reply_body(Env, {'EXCEPTION', Exception}) ->
- {TypeOfException, ExceptionTypeCode, NewExc} =
- orber_exceptions:get_def(Exception),
- {'tk_except', TypeOfException, ExceptionTypeCode,
- (catch enc_reply_body(Env#giop_env{tc = {ExceptionTypeCode, [], []},
- result = NewExc, parameters = []}, [], 0))};
-validate_reply_body(#giop_env{tc = {_RetType, _InParameters, []}} = Env, Reply) ->
- enc_reply_body(Env#giop_env{result = Reply}, [], 0);
-validate_reply_body(Env, Reply) when is_tuple(Reply) ->
- [Result|Parameters] = tuple_to_list(Reply),
- enc_reply_body(Env#giop_env{result = Result, parameters = Parameters}, [], 0);
-validate_reply_body(Env, Reply) ->
- enc_reply_body(Env#giop_env{result = Reply}, [], 0).
-
-%%-----------------------------------------------------------------
-%% Func: enc_cancel_request/2
-%%-----------------------------------------------------------------
-enc_cancel_request(Env) ->
- Flags = 1, %% LTH Not correct, just placeholder
- {Message, Len} = enc_request_id(Env, [], ?GIOP_HEADER_SIZE),
- enc_giop_message_header(Env, 'cancel_request', Flags, Len - ?GIOP_HEADER_SIZE,
- lists:reverse(Message)).
-
-%%-----------------------------------------------------------------
-%% Func: enc_locate_request/3
-%%-----------------------------------------------------------------
-%% ## NEW IIOP 1.2 ##
-enc_locate_request(#giop_env{version = {1,2}} = Env) ->
- Flags = 1, %% LTH Not correct, just placeholder
- {Message, Len} = enc_request_id(Env, [], ?GIOP_HEADER_SIZE),
- {Message1, Len1} = enc_target_address(Env, Message, Len),
- enc_giop_message_header(Env, 'locate_request', Flags, Len1-?GIOP_HEADER_SIZE,
- lists:reverse(Message1));
-enc_locate_request(Env) ->
- Flags = 1, %% LTH Not correct, just placeholder
- {Message, Len} = enc_request_id(Env, [], ?GIOP_HEADER_SIZE),
- {Message1, Len1} = enc_object_key(Env, Message, Len),
- enc_giop_message_header(Env, 'locate_request', Flags, Len1-?GIOP_HEADER_SIZE,
- lists:reverse(Message1)).
-
-%%-----------------------------------------------------------------
-%% Func: enc_locate_reply
-%%-----------------------------------------------------------------
-%% No forward etc. Just encode the status.
-enc_locate_reply(#giop_env{tc = undefined} = Env) ->
- Flags = 1, %% LTH Not correct, just placeholder
- {Message, Len} = enc_request_id(Env, [], ?GIOP_HEADER_SIZE),
- {Message1, Len1} = enc_locate_status(Env, Message, Len),
- enc_giop_message_header(Env, 'locate_reply', Flags, Len1 - ?GIOP_HEADER_SIZE,
- lists:reverse(Message1));
-enc_locate_reply(Env) ->
- Flags = 1, %% LTH Not correct, just placeholder
- {Message, Len} = enc_request_id(Env, [], ?GIOP_HEADER_SIZE),
- {Message1, Len1} = enc_locate_status(Env, Message, Len),
- {Message2, Len2} = enc_locate_reply_body(Env, Message1, Len1),
- enc_giop_message_header(Env, 'locate_reply', Flags, Len2 - ?GIOP_HEADER_SIZE,
- lists:reverse(Message2)).
-
-enc_locate_reply_body(#giop_env{tc = TC, result = Data} = Env, Message, Len) ->
- %% In CORBA-2.3.1 the LocateReply body didn't align the body (8-octet
- %% boundry) for IIOP-1.2. This have been changed in later specs.
- %% Un-comment the line below when we want to be CORBA-2.4 compliant.
- %% But in CORB-2.6 this was changed once again (i.e. no alignment).
- %% The best solution is to keep it as is.
- enc_type(TC, Env, Data, Message, Len).
-
-enc_locate_status(Env, Mess, Len) ->
- L = enc_giop_locate_status_type(Env#giop_env.reply_status),
- enc_type('tk_ulong', Env, L, Mess, Len).
-%%-----------------------------------------------------------------
-%% Func: enc_close_connection/1
-%%-----------------------------------------------------------------
-enc_close_connection(Env) ->
- Flags = 1, %% LTH Not correct, just placeholder
- enc_giop_message_header(Env, 'close_connection', Flags, 0, []).
-
-%%-----------------------------------------------------------------
-%% Func: enc_message_error/1
-%%-----------------------------------------------------------------
-enc_message_error(Env) ->
- Flags = 1, %% LTH Not correct, just placeholder
- enc_giop_message_header(Env, 'message_error', Flags, 0, []).
-
-%%-----------------------------------------------------------------
-%% Func: enc_fragment/1
-%%-----------------------------------------------------------------
-enc_fragment(Env) ->
- Flags = 1, %% LTH Not correct, just placeholder
- enc_giop_message_header(Env, 'fragment', Flags, 0, []).
-
-%%-----------------------------------------------------------------
-%% Func: enc_giop_msg_type
-%% Args: An integer message type code
-%% Returns: An atom which is the message type code name
-%%-----------------------------------------------------------------
-enc_giop_msg_type('request') ->
- 0;
-enc_giop_msg_type('reply') ->
- 1;
-enc_giop_msg_type('cancel_request') ->
- 2;
-enc_giop_msg_type('locate_request') ->
- 3;
-enc_giop_msg_type('locate_reply') ->
- 4;
-enc_giop_msg_type('close_connection') ->
- 5;
-enc_giop_msg_type('message_error') ->
- 6;
-enc_giop_msg_type('fragment') ->
- 7.
-
-
-%%-----------------------------------------------------------------
-%% Func: enc_giop_reply_status_type
-%% Args: An atom which is the reply status
-%% Returns: An integer status code
-%%-----------------------------------------------------------------
-enc_giop_reply_status_type(?NO_EXCEPTION) ->
- 0;
-enc_giop_reply_status_type(?USER_EXCEPTION) ->
- 1;
-enc_giop_reply_status_type(?SYSTEM_EXCEPTION) ->
- 2;
-enc_giop_reply_status_type('location_forward') ->
- 3;
-%% ## NEW IIOP 1.2 ##
-enc_giop_reply_status_type('location_forward_perm') ->
- 4;
-enc_giop_reply_status_type('needs_addressing_mode') ->
- 5.
-
-%%-----------------------------------------------------------------
-%% Func: enc_giop_locate_status_type
-%% Args: An integer status code
-%% Returns: An atom which is the reply status
-%%-----------------------------------------------------------------
-enc_giop_locate_status_type('unknown_object') ->
- 0;
-enc_giop_locate_status_type('object_here') ->
- 1;
-enc_giop_locate_status_type('object_forward') ->
- 2;
-%% ## NEW IIOP 1.2 ##
-enc_giop_locate_status_type('object_forward_perm') ->
- 3;
-enc_giop_locate_status_type('loc_system_exception') ->
- 4;
-enc_giop_locate_status_type('loc_needs_addressing_mode') ->
- 5.
-
-%%-----------------------------------------------------------------
-%% Func: enc_type/3
-%%-----------------------------------------------------------------
-enc_type(Env, TypeCode, Value) ->
- {Bytes, _Len} = enc_type(TypeCode, Env, Value, [], 0),
- list_to_binary(lists:reverse(Bytes)).
-
-%%-----------------------------------------------------------------
-%% Func: enc_type/5
-%%-----------------------------------------------------------------
-enc_type('tk_null', _Env, null, Bytes, Len) ->
- {Bytes, Len};
-enc_type('tk_void', _Env, ok, Bytes, Len) ->
- {Bytes, Len};
-enc_type('tk_short', _Env, Value, Bytes, Len) ->
- {Rest, Len1} = enc_align(Bytes, Len, 2),
- {cdrlib:enc_short(Value, Rest), Len1 + 2};
-enc_type('tk_long', _Env, Value, Bytes, Len) ->
- {Rest, Len1} = enc_align(Bytes, Len, 4),
- {cdrlib:enc_long(Value, Rest ), Len1 + 4};
-enc_type('tk_longlong', _Env, Value, Bytes, Len) ->
- {Rest, Len1} = enc_align(Bytes, Len, 8),
- {cdrlib:enc_longlong(Value, Rest ), Len1 + 8};
-enc_type('tk_ushort', _Env, Value, Bytes, Len) ->
- {Rest, Len1} = enc_align(Bytes, Len, 2),
- {cdrlib:enc_unsigned_short(Value, Rest), Len1 + 2};
-enc_type('tk_ulong', _Env, Value, Bytes, Len) ->
- {Rest, Len1} = enc_align(Bytes, Len, 4),
- {cdrlib:enc_unsigned_long(Value, Rest), Len1 + 4};
-enc_type('tk_ulonglong', _Env, Value, Bytes, Len) ->
- {Rest, Len1} = enc_align(Bytes, Len, 8),
- {cdrlib:enc_unsigned_longlong(Value, Rest), Len1 + 8};
-enc_type('tk_float', _Env, Value, Bytes, Len) ->
- {Rest, Len1} = enc_align(Bytes, Len, 4),
- {cdrlib:enc_float(Value, Rest), Len1 + 4};
-enc_type('tk_double', _Env, Value, Bytes, Len) ->
- {Rest, Len1} = enc_align(Bytes, Len, 8),
- {cdrlib:enc_double(Value, Rest), Len1 + 8};
-enc_type('tk_boolean', _Env, Value, Bytes, Len) ->
- {cdrlib:enc_bool(Value, Bytes), Len + 1};
-enc_type('tk_char', _Env, Value, Bytes, Len) ->
- {cdrlib:enc_char(Value, Bytes), Len + 1};
-%% The wchar decoding can be 1, 2 or 4 bytes but for now we only accept 2.
-enc_type('tk_wchar', #giop_env{version = {1,2}}, Value, Bytes, Len) ->
- Bytes1 = cdrlib:enc_octet(2, Bytes),
- {cdrlib:enc_unsigned_short(Value, Bytes1), Len + 3};
-enc_type('tk_wchar', _Env, Value, Bytes, Len) ->
- {Rest, Len1} = enc_align(Bytes, Len, 2),
- {cdrlib:enc_unsigned_short(Value, Rest), Len1 + 2};
-enc_type('tk_octet', _Env, Value, Bytes, Len) ->
- {cdrlib:enc_octet(Value, Bytes), Len + 1};
-enc_type('tk_any', Env, Any, Bytes, Len) when is_record(Any, any) ->
- {Rest, Len1} = enc_type('tk_TypeCode', Env, Any#any.typecode, Bytes, Len),
- enc_type(Any#any.typecode, Env, Any#any.value, Rest, Len1);
-enc_type('tk_TypeCode', Env, Value, Bytes, Len) ->
- enc_type_code(Value, Env, Bytes, Len);
-enc_type('tk_Principal', Env, Value, Bytes, Len) ->
- %% Set MaxLength no 0 (i.e. unlimited).
- enc_sequence(Env, Value, 0, 'tk_octet', Bytes, Len);
-enc_type({'tk_objref', _IFRId, Name}, Env, Value, Bytes, Len) ->
- enc_objref(Env, Name,Value, Bytes, Len);
-enc_type({'tk_struct', _IFRId, _Name, ElementList}, Env, Value, Bytes, Len) ->
- enc_struct(Env, Value, ElementList, Bytes, Len);
-enc_type({'tk_union', _IFRId, _Name, DiscrTC, Default, ElementList},
- Env, Value, Bytes, Len) ->
- enc_union(Env, Value, DiscrTC, Default, ElementList, Bytes, Len);
-enc_type({'tk_enum', _IFRId, _Name, ElementList}, _Env, Value, Bytes, Len) ->
- {Rest, Len1} = enc_align(Bytes, Len, 4),
- {cdrlib:enc_enum(atom_to_list(Value), ElementList, Rest), Len1 + 4};
-enc_type({'tk_string', MaxLength}, Env, Value, Bytes, Len) ->
- enc_string(Env, Value, MaxLength, Bytes, Len);
-enc_type({'tk_wstring', MaxLength}, Env, Value, Bytes, Len) ->
- enc_wstring(Env, Value, MaxLength, Bytes, Len);
-enc_type({'tk_sequence', ElemTC, MaxLength}, Env, Value, Bytes, Len) ->
- enc_sequence(Env, Value, MaxLength, ElemTC, Bytes, Len);
-enc_type({'tk_array', ElemTC, Size}, Env, Value, Bytes, Len) ->
- enc_array(Env, Value, Size, ElemTC, Bytes, Len);
-enc_type({'tk_alias', _IFRId, _Name, TC}, Env, Value, Bytes, Len) ->
- enc_type(TC, Env, Value, Bytes, Len);
-enc_type({'tk_except', IFRId, Name, ElementList}, Env, Value, Bytes, Len) ->
- enc_exception(Env, Name, IFRId, Value, ElementList, Bytes, Len);
-enc_type({'tk_fixed', Digits, Scale}, Env, Value, Bytes, Len) ->
- enc_fixed(Env, Digits, Scale, Value, Bytes, Len);
-enc_type(Type, _, Value, _, _) ->
- orber:dbg("[~p] cdr_encode:type(~p, ~p)~n"
- "Incorrect TypeCode or unsupported type.",
- [?LINE, Type, Value], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 13), completion_status=?COMPLETED_MAYBE}).
-
-
-
-
-%%-----------------------------------------------------------------
-%% Func: enc_fixed
-%%-----------------------------------------------------------------
-%% Digits eq. total number of digits.
-%% Scale eq. position of the decimal point.
-%% E.g. fixed<5,2> - "123.45" eq. #fixed{digits = 5, scale = 2, value = 12345}
-%% E.g. fixed<4,2> - "12.34" eq. #fixed{digits = 4, scale = 2, value = 1234}
-%% These are encoded as:
-%% ## <5,2> ## ## <4,2> ##
-%% 1,2 0,1 eq. 1 octet
-%% 3,4 2,3
-%% 5,0xC 4,0xC
-%%
-%% Each number is encoded as a half-octet. Note, for <4,2> a zero is
-%% added first to to be able to create "even" octets.
-enc_fixed(Env, Digits, Scale,
- #fixed{digits = Digits, scale = Scale, value = Value}, Bytes, Len)
- when is_integer(Value) andalso is_integer(Digits) andalso is_integer(Scale)
- andalso Digits < 32 andalso Digits >= Scale ->
- %% This isn't very efficient and we should improve it before supporting it
- %% officially.
- Odd = ?ODD(Digits),
- case integer_to_list(Value) of
- [$-|ValueList] when Odd == true ->
- Padded = lists:duplicate((Digits-length(ValueList)), 0) ++ ValueList,
- enc_fixed_2(Env, Digits, Scale, Padded,
- Bytes, Len, ?FIXED_NEGATIVE);
- [$-|ValueList] ->
- Padded = lists:duplicate((Digits-length(ValueList)), 0) ++ ValueList,
- enc_fixed_2(Env, Digits, Scale, [0|Padded],
- Bytes, Len, ?FIXED_NEGATIVE);
- ValueList when Odd == true ->
- Padded = lists:duplicate((Digits-length(ValueList)), 0) ++ ValueList,
- enc_fixed_2(Env, Digits, Scale, Padded,
- Bytes, Len, ?FIXED_POSITIVE);
- ValueList ->
- Padded = lists:duplicate((Digits-length(ValueList)), 0) ++ ValueList,
- enc_fixed_2(Env, Digits, Scale, [0|Padded],
- Bytes, Len, ?FIXED_POSITIVE)
- end;
-enc_fixed(_Env, Digits, Scale, Fixed, _Bytes, _Len) ->
- orber:dbg("[~p] cdr_encode:enc_fixed(~p, ~p, ~p)~n"
- "The supplied fixed type incorrect. Check that the 'digits' and 'scale' field~n"
- "match the definition in the IDL-specification. The value field must be~n"
- "a list of Digits length.",
- [?LINE, Digits, Scale, Fixed], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE}).
-
-enc_fixed_2(_Env, _Digits, _Scale, [D1], Bytes, Len, Sign) ->
- {[<<D1:4,Sign:4>>|Bytes], Len+1};
-enc_fixed_2(Env, Digits, Scale, [D1, D2|Ds], Bytes, Len, Sign) ->
- %% We could convert the ASCII-value to digit values but the bit-syntax will
- %% truncate it correctly.
- enc_fixed_2(Env, Digits, Scale, Ds, [<<D1:4,D2:4>> | Bytes], Len+1, Sign);
-enc_fixed_2(_Env, Digits, Scale, Value, _Bytes, _Len, Sign) ->
- orber:dbg("[~p] cdr_encode:enc_fixed_2(~p, ~p, ~p, ~p)~n"
- "The supplied fixed type incorrect. Most likely the 'digits' field don't match the~n"
- "supplied value. Hence, check that the value is correct.",
- [?LINE, Digits, Scale, Value, Sign], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE}).
-
-
-
-%%-----------------------------------------------------------------
-%% Func: enc_sequence/5
-%%-----------------------------------------------------------------
-%% This is a special case used when encoding encapsualted data, i.e., contained
-%% in an octet-sequence.
-enc_sequence(_Env, Sequence, MaxLength, 'tk_octet', Bytes, Len)
- when is_binary(Sequence) ->
- {ByteSequence, Len1} = enc_align(Bytes, Len, 4),
- Size = size(Sequence),
- if
- Size > MaxLength, MaxLength > 0 ->
- orber:dbg("[~p] cdr_encode:enc_sequnce(~p, ~p). Sequence exceeds max.",
- [?LINE, Sequence, MaxLength], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 19),
- completion_status=?COMPLETED_MAYBE});
- true ->
- ByteSequence1 = cdrlib:enc_unsigned_long(Size, ByteSequence),
- {[Sequence |ByteSequence1], Len1 + 4 + Size}
- end;
-enc_sequence(Env, Sequence, MaxLength, TypeCode, Bytes, Len) ->
- Length = length(Sequence),
- if
- Length > MaxLength, MaxLength > 0 ->
- orber:dbg("[~p] cdr_encode:enc_sequnce(~p, ~p). Sequence exceeds max.",
- [?LINE, Sequence, MaxLength], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 19),
- completion_status=?COMPLETED_MAYBE});
- true ->
- {ByteSequence, Len1} = enc_align(Bytes, Len, 4),
- ByteSequence1 = cdrlib:enc_unsigned_long(Length, ByteSequence),
- enc_sequence1(Env, Sequence, TypeCode, ByteSequence1, Len1 + 4)
- end.
-
-%%-----------------------------------------------------------------
-%% Func: enc_sequence1/4
-%%-----------------------------------------------------------------
-enc_sequence1(_Env, [], _TypeCode, Bytes, Len) ->
- {Bytes, Len};
-enc_sequence1(_Env, CharSeq, 'tk_char', Bytes, Len) ->
- {[list_to_binary(CharSeq) |Bytes], Len + length(CharSeq)};
-enc_sequence1(_Env, OctetSeq, 'tk_octet', Bytes, Len) ->
- {[list_to_binary(OctetSeq) |Bytes], Len + length(OctetSeq)};
-enc_sequence1(Env, [Object| Rest], TypeCode, Bytes, Len) ->
- {ByteSequence, Len1} = enc_type(TypeCode, Env, Object, Bytes, Len),
- enc_sequence1(Env, Rest, TypeCode, ByteSequence, Len1).
-
-%%-----------------------------------------------------------------
-%% Func: enc_array/4
-%%-----------------------------------------------------------------
-enc_array(Env, Array, Size, TypeCode, Bytes, Len) when size(Array) == Size ->
- Sequence = tuple_to_list(Array),
- enc_sequence1(Env, Sequence, TypeCode, Bytes, Len);
-enc_array(_,Array, Size, _, _, _) ->
- orber:dbg("[~p] cdr_encode:enc_array(~p, ~p). Incorrect size.",
- [?LINE, Array, Size], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 15), completion_status=?COMPLETED_MAYBE}).
-
-%%-----------------------------------------------------------------
-%% Func: enc_string/4
-%%-----------------------------------------------------------------
-enc_string(_Env, String, MaxLength, Bytes, Len) ->
- StrLen = length(String),
- if
- StrLen > MaxLength, MaxLength > 0 ->
- orber:dbg("[~p] cdr_encode:enc_string(~p, ~p). String exceeds max.",
- [?LINE, String, MaxLength], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 16),
- completion_status=?COMPLETED_MAYBE});
- true ->
- {ByteSequence, Len1} = enc_align(Bytes, Len, 4),
- ByteSequence1 = cdrlib:enc_unsigned_long(StrLen + 1, ByteSequence),
- {cdrlib:enc_octet(0, [String | ByteSequence1]), Len1 + StrLen + 5}
- end.
-
-
-%%-----------------------------------------------------------------
-%% Func: enc_wstring/4
-%%-----------------------------------------------------------------
-enc_wstring(#giop_env{version = {1,2}} = Env, String, MaxLength, Bytes, Len) ->
- %% Encode the length of the string (ulong).
- {Bytes1, Len1} = enc_align(Bytes, Len, 4),
- %% For IIOP-1.2 the length is the total number of octets. Hence, since the wchar's
- %% we accepts is encoded as <<255, 255>> the total size is 2*length of the list.
- ListLen = length(String),
- if
- ListLen > MaxLength, MaxLength > 0 ->
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 16),
- completion_status=?COMPLETED_MAYBE});
- true ->
- StrLen = ListLen * 2,
- Bytes2 = cdrlib:enc_unsigned_long(StrLen, Bytes1),
- %% For IIOP-1.2 no terminating null character is used.
- enc_sequence1(Env, String, 'tk_ushort', Bytes2, Len1+4)
- end;
-enc_wstring(Env, String, MaxLength, Bytes, Len) ->
- %% Encode the length of the string (ulong).
- {Bytes1, Len1} = enc_align(Bytes, Len, 4),
- ListLen = length(String),
- if
- ListLen > MaxLength, MaxLength > 0 ->
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 16),
- completion_status=?COMPLETED_MAYBE});
- true ->
- StrLen = ListLen + 1,
- Bytes2 = cdrlib:enc_unsigned_long(StrLen, Bytes1),
- {Bytes3, Len3} = enc_sequence1(Env, String, 'tk_wchar', Bytes2, Len1+4),
- %% The terminating null character is also a wchar.
- {cdrlib:enc_unsigned_short(0, Bytes3), Len3+2}
- end.
-
-
-%%-----------------------------------------------------------------
-%% Func: enc_union/5
-%%-----------------------------------------------------------------
-enc_union(Env, {_, Label, Value}, DiscrTC, Default, TypeCodeList,
- Bytes, Len) when is_list(TypeCodeList) ->
- {ByteSequence, Len1} = enc_type(DiscrTC, Env, Label, Bytes, Len),
- Label2 = stringify_enum(DiscrTC,Label),
- enc_union2(Env, {Label2, Value},TypeCodeList, Default,
- ByteSequence, Len1, undefined);
-enc_union(Env, Value, _DiscrTC, _Default, Module, Bytes, Len) when is_atom(Module) ->
- case catch Module:tc() of
- {tk_union, _, _, DiscrTC, Default, ElementList} ->
- enc_union(Env, Value, DiscrTC, Default, ElementList, Bytes, Len);
- What ->
- orber:dbg("[~p] ~p:enc_union(~p). Union module doesn't exist or incorrect.",
- [?LINE, ?MODULE, What], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE})
- end.
-
-enc_union2(_Env, _What, [], Default, Bytes, Len, _) when Default < 0 ->
- {Bytes, Len};
-enc_union2(Env, {_, Value}, [], _Default, Bytes, Len, Type) ->
- enc_type(Type, Env, Value, Bytes, Len);
-enc_union2(Env, {Label,Value} ,[{Label, _Name, Type} |_List],
- _Default, Bytes, Len, _) ->
- enc_type(Type, Env, Value, Bytes, Len);
-enc_union2(Env, Union ,[{default, _Name, Type} |List], Default, Bytes, Len, _) ->
- enc_union2(Env, Union, List, Default, Bytes, Len, Type);
-enc_union2(Env, Union,[_ | List], Default, Bytes, Len, DefaultType) ->
- enc_union2(Env, Union, List, Default, Bytes, Len, DefaultType).
-
-stringify_enum({tk_enum, _,_,_}, Label) ->
- atom_to_list(Label);
-stringify_enum(_, Label) ->
- Label.
-%%-----------------------------------------------------------------
-%% Func: enc_struct/4
-%%-----------------------------------------------------------------
-enc_struct(Env, Struct, TypeCodeList, Bytes, Len) when is_list(TypeCodeList) ->
- [_Name | StructList] = tuple_to_list(Struct),
- enc_struct1(Env, StructList, TypeCodeList, Bytes, Len);
-enc_struct(Env, Struct, Module, Bytes, Len) ->
- [Module | StructList] = tuple_to_list(Struct),
- case catch Module:tc() of
- {tk_struct, _, _, TypeCodeList} ->
- enc_struct1(Env, StructList, TypeCodeList, Bytes, Len);
- What ->
- orber:dbg("[~p] ~p:enc_struct([], ~p). Struct module doesn't exist or incorrect.",
- [?LINE, ?MODULE, What], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE})
- end.
-
-enc_struct1(_Env, [], [], Bytes, Len) ->
- {Bytes, Len};
-enc_struct1(Env, [Object | Rest], [{_ElemName, ElemType} | TypeCodeList], Bytes,
- Len) ->
- {ByteSequence, Len1} = enc_type(ElemType, Env, Object, Bytes, Len),
- enc_struct1(Env, Rest, TypeCodeList, ByteSequence, Len1).
-
-%%-----------------------------------------------------------------
-%% Func: enc_objref/4
-%%-----------------------------------------------------------------
-enc_objref(Env, _Name, Value, Bytes, Len) ->
- iop_ior:code(Env, Value, Bytes, Len).
-
-%%-----------------------------------------------------------------
-%% Func: enc_exception/5
-%%-----------------------------------------------------------------
-enc_exception(Env, _Name, IFRId, Value, ElementList, Bytes, Len) ->
- [_Name1, _TypeId | Args] = tuple_to_list(Value),
- {Bytes1, Len1} = enc_type({'tk_string', 0}, Env, IFRId , Bytes, Len),
- enc_exception_1(Env, Args, ElementList, Bytes1, Len1).
-
-enc_exception_1(_Env, [], [], Bytes, Len) ->
- {Bytes, Len};
-enc_exception_1(Env, [Arg |Args], [{_ElemName, ElemType} |ElementList],
- Bytes, Len) ->
- {Bytes1, Len1} = enc_type(ElemType, Env, Arg, Bytes, Len),
- enc_exception_1(Env, Args, ElementList, Bytes1, Len1).
-
-
-%%-----------------------------------------------------------------
-%% Func: enc_type_code/3
-%%-----------------------------------------------------------------
-enc_type_code('tk_null', Env, Message, Len) ->
- enc_type('tk_ulong', Env, 0, Message, Len);
-enc_type_code('tk_void', Env, Message, Len) ->
- enc_type('tk_ulong', Env, 1, Message, Len);
-enc_type_code('tk_short', Env, Message, Len) ->
- enc_type('tk_ulong', Env, 2, Message, Len);
-enc_type_code('tk_long', Env, Message, Len) ->
- enc_type('tk_ulong', Env, 3, Message, Len);
-enc_type_code('tk_longlong', Env, Message, Len) ->
- enc_type('tk_ulong', Env, 23, Message, Len);
-enc_type_code('tk_longdouble', Env, Message, Len) ->
- enc_type('tk_ulong', Env, 25, Message, Len);
-enc_type_code('tk_ushort', Env, Message, Len) ->
- enc_type('tk_ulong', Env, 4, Message, Len);
-enc_type_code('tk_ulong', Env, Message, Len) ->
- enc_type('tk_ulong', Env, 5, Message, Len);
-enc_type_code('tk_ulonglong', Env, Message, Len) ->
- enc_type('tk_ulong', Env, 24, Message, Len);
-enc_type_code('tk_float', Env, Message, Len) ->
- enc_type('tk_ulong', Env, 6, Message, Len);
-enc_type_code('tk_double', Env, Message, Len) ->
- enc_type('tk_ulong', Env, 7, Message, Len);
-enc_type_code('tk_boolean', Env, Message, Len) ->
- enc_type('tk_ulong', Env, 8, Message, Len);
-enc_type_code('tk_char', Env, Message, Len) ->
- enc_type('tk_ulong', Env, 9, Message, Len);
-enc_type_code('tk_wchar', Env, Message, Len) ->
- enc_type('tk_ulong', Env, 26, Message, Len);
-enc_type_code('tk_octet', Env, Message, Len) ->
- enc_type('tk_ulong', Env, 10, Message, Len);
-enc_type_code('tk_any', Env, Message, Len) ->
- enc_type('tk_ulong', Env, 11, Message, Len);
-enc_type_code('tk_TypeCode', Env, Message, Len) ->
- enc_type('tk_ulong', Env, 12, Message, Len);
-enc_type_code('tk_Principal', Env, Message, Len) ->
- enc_type('tk_ulong', Env, 13, Message, Len);
-enc_type_code({'tk_objref', RepId, Name}, Env, Message, Len) ->
- {Message1, Len1} = enc_type('tk_ulong', Env, 14, Message, Len),
- {Message2, _} = enc_byte_order(Env, []),
- {ComplexParams, Len2} = enc_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
- {"name", {'tk_string', 0}}]},
- Env,
- {"", RepId, Name},
- Message2, 1),
- encode_complex_tc_paramters(lists:reverse(ComplexParams), Len2, Message1, Len1);
-enc_type_code({'tk_struct', RepId, SimpleName, ElementList}, Env, Message, Len) ->
- %% Using SimpleName should be enough (and we avoid some overhead).
- %% Name = ifrid_to_name(RepId),
- {Message1, Len1} = enc_type('tk_ulong', Env, 15, Message, Len),
- {Message2, _} = enc_byte_order(Env, []),
- {ComplexParams, Len2} = enc_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
- {"name", {'tk_string', 0}},
- {"element list",
- {'tk_sequence', {'tk_struct', "","",
- [{"member name", {'tk_string', 0}},
- {"member type", 'tk_TypeCode'}]},
- 0}}]},
- Env,
- {"", RepId, SimpleName,
- lists:map(fun({N,T}) -> {"",N,T} end, ElementList)},
- Message2, 1),
- encode_complex_tc_paramters(lists:reverse(ComplexParams), Len2, Message1, Len1);
-enc_type_code({'tk_union', RepId, Name, DiscrTC, Default, ElementList},
- Env, Message, Len) ->
- NewElementList =
- case check_enum(DiscrTC) of
- true ->
- lists:map(fun({L,N,T}) -> {"",list_to_atom(L),N,T} end, ElementList);
- false ->
- lists:map(fun({L,N,T}) -> {"",L,N,T} end, ElementList)
- end,
- {Message1, Len1} = enc_type('tk_ulong', Env, 16, Message, Len),
- {Message2, _} = enc_byte_order(Env, []),
- {ComplexParams, Len2} = enc_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
- {"name", {'tk_string', 0}},
- {"discriminant type", 'tk_TypeCode'},
- {"default used", 'tk_long'},
- {"element list",
- {'tk_sequence', {'tk_struct', "","",
- [{"label value", DiscrTC},
- {"member name", {'tk_string', 0}},
- {"member type", 'tk_TypeCode'}]},
- 0}}]},
- Env,
- {"", RepId, Name, DiscrTC, Default, NewElementList},
- Message2, 1),
- encode_complex_tc_paramters(lists:reverse(ComplexParams), Len2, Message1, Len1);
-enc_type_code({'tk_enum', RepId, Name, ElementList}, Env, Message, Len) ->
- {Message1, Len1} = enc_type('tk_ulong', Env, 17, Message, Len),
- {Message2, _} = enc_byte_order(Env, []),
- {ComplexParams, Len2} = enc_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
- {"name", {'tk_string', 0}},
- {"element list",
- {'tk_sequence', {'tk_string', 0}, 0}}]},
- Env,
- {"", RepId, Name, ElementList},
- Message2, 1),
- encode_complex_tc_paramters(lists:reverse(ComplexParams), Len2, Message1, Len1);
-enc_type_code({'tk_string', MaxLength}, Env, Message, Len) ->
- enc_type({'tk_struct', "", "", [{"TCKind", 'tk_ulong'},
- {"max length", 'tk_ulong'}]},
- Env,
- {"", 18, MaxLength},
- Message, Len);
-enc_type_code({'tk_wstring', MaxLength}, Env, Message, Len) ->
- enc_type({'tk_struct', "", "", [{"TCKind", 'tk_ulong'},
- {"max length", 'tk_ulong'}]},
- Env,
- {"", 27, MaxLength},
- Message, Len);
-enc_type_code({'tk_sequence', ElemTC, MaxLength}, Env, Message, Len) ->
- {Message1, Len1} = enc_type('tk_ulong', Env, 19, Message, Len),
- {Message2, _} = enc_byte_order(Env, []),
- {ComplexParams, Len2} = enc_type({'tk_struct', "", "", [{"element type", 'tk_TypeCode'},
- {"max length", 'tk_ulong'}]},
- Env,
- {"", ElemTC, MaxLength},
- Message2, 1),
- encode_complex_tc_paramters(lists:reverse(ComplexParams), Len2, Message1, Len1);
-enc_type_code({'tk_array', ElemTC, Length}, Env, Message, Len) ->
- {Message1, Len1} = enc_type('tk_ulong', Env, 20, Message, Len),
- {Message2, _} = enc_byte_order(Env, []),
- {ComplexParams, Len2} = enc_type({'tk_struct', "", "", [{"element type", 'tk_TypeCode'},
- {"length", 'tk_ulong'}]},
- Env,
- {"", ElemTC, Length},
- Message2, 1),
- encode_complex_tc_paramters(lists:reverse(ComplexParams), Len2, Message1, Len1);
-enc_type_code({'tk_alias', RepId, Name, TC}, Env, Message, Len) ->
- {Message1, Len1} = enc_type('tk_ulong', Env, 21, Message, Len),
- {Message2, _} = enc_byte_order(Env, []),
- {ComplexParams, Len2} = enc_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
- {"name", {'tk_string', 0}},
- {"TypeCode", 'tk_TypeCode'}]},
- Env,
- {"", RepId, Name, TC},
- Message2, 1),
- encode_complex_tc_paramters(lists:reverse(ComplexParams), Len2, Message1, Len1);
-enc_type_code({'tk_except', RepId, Name, ElementList}, Env, Message, Len) ->
- {Message1, Len1} = enc_type('tk_ulong', Env, 22, Message, Len),
- {Message2, _} = enc_byte_order(Env, []),
- {ComplexParams, Len2} = enc_type({'tk_struct', "", "", [{"repository ID", {'tk_string', 0}},
- {"name", {'tk_string', 0}},
- {"element list",
- {'tk_sequence',
- {'tk_struct', "", "",
- [{"member name", {'tk_string', 0}},
- {"member type", 'tk_TypeCode'}]}, 0}}]},
- Env,
- {"", RepId, Name,
- lists:map(fun({N,T}) -> {"",N,T} end, ElementList)},
- Message2, 1),
- encode_complex_tc_paramters(lists:reverse(ComplexParams), Len2, Message1, Len1);
-enc_type_code({'tk_fixed', Digits, Scale}, Env, Message, Len) ->
- enc_type({'tk_struct', "", "", [{"TCKind", 'tk_ulong'},
- {"digits", 'tk_ushort'},
- {"scale", 'tk_short'}]},
- Env,
- {"", 28, Digits, Scale},
- Message, Len);
-enc_type_code({'tk_value', RepId, Name, ValueModifier, TC, ElementList}, Env, Message, Len) ->
- {Message1, Len1} = enc_type('tk_ulong', Env, 29, Message, Len),
- {Message2, _} = enc_byte_order(Env, []),
- {ComplexParams, Len2} = enc_type({'tk_struct', "", "",
- [{"repository ID", {'tk_string', 0}},
- {"name", {'tk_string', 0}},
- {"ValueModifier", 'tk_short'},
- {"TypeCode", 'tk_TypeCode'},
- {"element list",
- {'tk_sequence',
- {'tk_struct', "","",
- [{"member name", {'tk_string', 0}},
- {"member type", 'tk_TypeCode'},
- {"Visibility", 'tk_short'}]},
- 0}}]},
- Env,
- {"", RepId, Name, ValueModifier, TC,
- lists:map(fun({N,T,V}) -> {"",N,T,V} end, ElementList)},
- Message2, 1),
- encode_complex_tc_paramters(lists:reverse(ComplexParams), Len2, Message1, Len1);
-enc_type_code({'tk_value_box', RepId, Name, TC}, Env, Message, Len) ->
- {Message1, Len1} = enc_type('tk_ulong', Env, 30, Message, Len),
- {Message2, _} = enc_byte_order(Env, []),
- {ComplexParams, Len2} = enc_type({'tk_struct', "", "",
- [{"repository ID", {'tk_string', 0}},
- {"name", {'tk_string', 0}},
- {"TypeCode", 'tk_TypeCode'}]},
- Env,
- {"", RepId, Name, TC},
- Message2, 1),
- encode_complex_tc_paramters(lists:reverse(ComplexParams), Len2, Message1, Len1);
-enc_type_code({'tk_native', RepId, Name}, Env, Message, Len) ->
- {Message1, Len1} = enc_type('tk_ulong', Env, 31, Message, Len),
- {Message2, _} = enc_byte_order(Env, []),
- {ComplexParams, Len2} = enc_type({'tk_struct', "", "",
- [{"repository ID", {'tk_string', 0}},
- {"name", {'tk_string', 0}}]},
- Env,
- {"", RepId, Name},
- Message2, 1),
- encode_complex_tc_paramters(lists:reverse(ComplexParams), Len2, Message1, Len1);
-enc_type_code({'tk_abstract_interface', RepId, Name}, Env, Message, Len) ->
- {Message1, Len1} = enc_type('tk_ulong', Env, 32, Message, Len),
- {Message2, _} = enc_byte_order(Env, []),
- {ComplexParams, Len2} = enc_type({'tk_struct', "", "",
- [{"RepositoryId", {'tk_string', 0}},
- {"name", {'tk_string', 0}}]},
- Env,
- {"", RepId, Name},
- Message2, 1),
- encode_complex_tc_paramters(lists:reverse(ComplexParams), Len2, Message1, Len1);
-enc_type_code({'tk_local_interface', RepId, Name}, Env, Message, Len) ->
- {Message1, Len1} = enc_type('tk_ulong', Env, 33, Message, Len),
- {Message2, _} = enc_byte_order(Env, []),
- {ComplexParams, Len2} = enc_type({'tk_struct', "", "",
- [{"RepositoryId", {'tk_string', 0}},
- {"name", {'tk_string', 0}}]},
- Env,
- {"", RepId, Name},
- Message2, 1),
- encode_complex_tc_paramters(lists:reverse(ComplexParams), Len2, Message1, Len1);
-enc_type_code({'none', Indirection}, Env, Message, Len) -> %% placeholder
- enc_type({'tk_struct', "", "", [{"TCKind", 'tk_ulong'},
- {"indirection", 'tk_long'}]},
- Env,
- {"", 16#ffffffff, Indirection},
- Message, Len);
-enc_type_code(Type, _, _, _) ->
- orber:dbg("[~p] cdr_encode:enc_type_code(~p); No match.",
- [?LINE, Type], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 7), completion_status=?COMPLETED_MAYBE}).
-
-check_enum({'tk_enum', _, _, _}) ->
- true;
-check_enum(_) ->
- false.
-
-encode_complex_tc_paramters(Value, ValueLength, Message, Len) ->
- {Message1, _Len1} = enc_align(Message, Len, 4),
- Message2 = cdrlib:enc_unsigned_long(ValueLength, Message1),
- {[Value |Message2], Len+ValueLength+4}.
-
-%%-----------------------------------------------------------------
-%% Func: enc_align/1
-%%-----------------------------------------------------------------
-enc_align(R, Len, Alignment) ->
- Rem = Len rem Alignment,
- if Rem == 0 ->
- {R, Len};
- true ->
- Diff = Alignment - Rem,
- {add_bytes(R, Diff), Len + Diff}
- end.
-
-add_bytes(R, 0) ->
- R;
-add_bytes(R, 1) ->
- [<<16#01:8>> | R];
-add_bytes(R, 2) ->
- [<<16#02:8, 16#02:8>> | R];
-add_bytes(R, 3) ->
- [<<16#03:8, 16#03:8, 16#03:8>> | R];
-add_bytes(R, 4) ->
- [<<16#04:8, 16#04:8, 16#04:8, 16#04:8>> | R];
-add_bytes(R, 5) ->
- [<<16#05:8, 16#05:8, 16#05:8, 16#05:8, 16#05:8>> | R];
-add_bytes(R, 6) ->
- [<<16#06:8, 16#06:8, 16#06:8, 16#06:8, 16#06:8, 16#06:8>> | R];
-add_bytes(R, 7) ->
- [<<16#07:8, 16#07:8, 16#07:8, 16#07:8, 16#07:8, 16#07:8, 16#07:8>> | R];
-add_bytes(R,N) ->
- add_bytes([<<16#08:8>> | R], N - 1).
-
diff --git a/lib/orber/src/cdrlib.erl b/lib/orber/src/cdrlib.erl
deleted file mode 100644
index a181681382..0000000000
--- a/lib/orber/src/cdrlib.erl
+++ /dev/null
@@ -1,415 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: cdrlib.erl
-%%
-%% Description:
-%% CDR basic type encode/decode functions
-%%
-%%-----------------------------------------------------------------
--module(cdrlib).
-
--include_lib("orber/include/corba.hrl").
--include("orber_iiop.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([ %% IIOP 1.0 -
- enc_short/2, dec_short/2,
- enc_unsigned_short/2, dec_unsigned_short/2,
- enc_long/2, dec_long/2,
- enc_unsigned_long/2, dec_unsigned_long/2,
- enc_bool/2, dec_bool/1,
- enc_float/2, dec_float/2,
- enc_double/2, dec_double/2,
- enc_char/2, dec_char/1,
- enc_octet/2, dec_octet/1,
- enc_enum/3, dec_enum/3,
- %% IIOP 1.1 -
- enc_longlong/2, dec_longlong/2,
- enc_unsigned_longlong/2, dec_unsigned_longlong/2
- %%enc_longdouble/2, dec_longdouble/2
- %%enc_fixed/4, dec_fixed/2
- ]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
--define(DEBUG_LEVEL, 10).
-
-%%-----------------------------------------------------------------
-%% short
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: enc_short/2
-%%-----------------------------------------------------------------
-enc_short(X, Message) when is_integer(X) andalso X >= ?SHORTMIN andalso X =< ?SHORTMAX ->
- [<<X:16/big-signed-integer>> | Message];
-enc_short(X, _Message) when is_integer(X) ->
- orber:dbg("[~p] cdrlib:enc_short(~p); Out of range.", [?LINE, X], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 1), completion_status=?COMPLETED_NO});
-enc_short(X, _Message) ->
- orber:dbg("[~p] cdrlib:enc_short(~p); not integer.", [?LINE, X], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 2), completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------------
-%% Func: dec_short/2
-%%-----------------------------------------------------------------
-dec_short(big, <<Short:16/big-signed-integer,Rest/binary>>) ->
- {Short, Rest};
-dec_short(little, <<Short:16/little-signed-integer,Rest/binary>>) ->
- {Short, Rest}.
-
-%%-----------------------------------------------------------------
-%% unsigned short
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: enc_unsigned_short/2
-%%-----------------------------------------------------------------
-enc_unsigned_short(X, Message) when is_integer(X) andalso X >= ?USHORTMIN andalso X =< ?USHORTMAX ->
- [<<X:16/big-unsigned-integer>> | Message];
-enc_unsigned_short(X, _Message) when is_integer(X) ->
- orber:dbg("[~p] cdrlib:enc_unsigned_short(~p); Out of range.",
- [?LINE, X], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 1), completion_status=?COMPLETED_NO});
-enc_unsigned_short(X, _Message) ->
- orber:dbg("[~p] cdrlib:enc_unsigned_short(~p); not integer >= 0",
- [?LINE, X], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 2), completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------------
-%% Func: dec_unsigned_short/2
-%%-----------------------------------------------------------------
-dec_unsigned_short(big, <<UShort:16/big-unsigned-integer,Rest/binary>>) ->
- {UShort, Rest};
-dec_unsigned_short(little, <<UShort:16/little-unsigned-integer,Rest/binary>>) ->
- {UShort, Rest}.
-
-%%-----------------------------------------------------------------
-%% long
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: enc_long/2
-%%-----------------------------------------------------------------
-enc_long(X, Message) when is_integer(X) andalso X >= ?LONGMIN andalso X =< ?LONGMAX ->
- [<<X:32/big-signed-integer>> | Message];
-enc_long(X, _Message) when is_integer(X) ->
- orber:dbg("[~p] cdrlib:enc_long(~p); Out of range.",[?LINE, X], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 1), completion_status=?COMPLETED_NO});
-enc_long(X, _Message) ->
- orber:dbg("[~p] cdrlib:enc_long(~p); not integer.",
- [?LINE, X], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 2), completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------------
-%% Func: dec_long/2
-%%-----------------------------------------------------------------
-dec_long(big, <<Long:32/big-signed-integer,Rest/binary>>) ->
- {Long, Rest};
-dec_long(little, <<Long:32/little-signed-integer,Rest/binary>>) ->
- {Long, Rest}.
-
-%%-----------------------------------------------------------------
-%% unsigned_long
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: enc_unsigned_long/2
-%%-----------------------------------------------------------------
-enc_unsigned_long(X, Message) when is_integer(X) andalso X >= ?ULONGMIN andalso X =< ?ULONGMAX ->
- [<<X:32/big-unsigned-integer>> | Message];
-enc_unsigned_long(X, _Message) when is_integer(X) ->
- orber:dbg("[~p] cdrlib:enc_unsigned_long(~p); Out of range.",
- [?LINE, X], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 1), completion_status=?COMPLETED_NO});
-enc_unsigned_long(X, _Message) ->
- orber:dbg("[~p] cdrlib:enc_unsigned_long(~p); not integer >=0 ",
- [?LINE, X], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 2), completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------------
-%% Func: dec_unsigned_long/2
-%%-----------------------------------------------------------------
-dec_unsigned_long(big, <<ULong:32/big-unsigned-integer,Rest/binary>>) ->
- {ULong, Rest};
-dec_unsigned_long(little, <<ULong:32/little-unsigned-integer,Rest/binary>>) ->
- {ULong, Rest}.
-
-%%-----------------------------------------------------------------
-%% boolean
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: enc_bool/2
-%%-----------------------------------------------------------------
-enc_bool(true, Message) -> [<<1:8>>| Message];
-enc_bool(false, Message) -> [<<0:8>>| Message];
-enc_bool(X, _Message) ->
- orber:dbg("[~p] cdrlib:enc_bool(~p); Must be 'true' or 'false'",
- [?LINE, X], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 3), completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------------
-%% Func: dec_bool/1
-%%-----------------------------------------------------------------
-dec_bool(<<1:8,Rest/binary>>) -> {true, Rest};
-dec_bool(<<0:8,Rest/binary>>) -> {false, Rest};
-dec_bool(<<X:8,_Rest/binary>>) ->
- orber:dbg("[~p] cdrlib:dec_bool(~p); Not a boolean (1 or 0).",
- [?LINE, X], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 3), completion_status=?COMPLETED_NO}).
-
-
-%%-----------------------------------------------------------------
-%% Func: enc_float/2
-%%-----------------------------------------------------------------
-enc_float(X, Message) when is_number(X) ->
- [<<X:32/big-float>> | Message];
-enc_float(X, _Message) ->
- orber:dbg("[~p] cdrlib:enc_float(~p); not a number.", [?LINE, X], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 4), completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------------
-%% Func: dec_float/2
-%%-----------------------------------------------------------------
-dec_float(big, <<Float:32/big-float,Rest/binary>>) ->
- {Float, Rest};
-dec_float(little, <<Float:32/little-float,Rest/binary>>) ->
- {Float, Rest}.
-
-%%-----------------------------------------------------------------
-%% Func: enc_double/2
-%%-----------------------------------------------------------------
-enc_double(X, Message) when is_number(X) ->
- [<<X:64/big-float>> | Message];
-enc_double(X, _Message) ->
- orber:dbg("[~p] cdrlib:enc_double(~p); not a number.", [?LINE, X], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 4), completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------------
-%% Func: dec_double/2
-%%-----------------------------------------------------------------
-dec_double(big, <<Double:64/big-float,Rest/binary>>) ->
- {Double, Rest};
-dec_double(little, <<Double:64/little-float,Rest/binary>>) ->
- {Double, Rest}.
-
-%%-----------------------------------------------------------------
-%% char
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: enc_char/2
-%%-----------------------------------------------------------------
-enc_char(X, Message) when is_integer(X) andalso X =< 255, X >= 0 ->
- [<<X:8>> | Message];
-enc_char(X,_) ->
- orber:dbg("[~p] cdrlib:enc_char(~p); not a char.", [?LINE, X], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 6),completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------------
-%% Func: dec_char/1
-%%-----------------------------------------------------------------
-dec_char(<<Char:8,Rest/binary>>) ->
- {Char, Rest}.
-
-%%-----------------------------------------------------------------
-%% octet
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: enc_octet/2
-%%-----------------------------------------------------------------
-enc_octet(X, Message) when is_integer(X) andalso X =< 255, X >= 0 ->
- [<<X:8/big-unsigned-integer>> | Message];
-enc_octet(X, _Message) ->
- orber:dbg("[~p] cdrlib:enc_octet(~p); not an octet.", [?LINE, X], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 6),completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------------
-%% Func: dec_octet/1
-%%-----------------------------------------------------------------
-dec_octet(<<Octet:8/big-unsigned-integer,Rest/binary>>) ->
- {Octet, Rest}.
-
-%%-----------------------------------------------------------------
-%% enum
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: enc_enum/3
-%%-----------------------------------------------------------------
-enc_enum(Enum, ElemList, Message) ->
- Val = getEnumValue(ElemList,Enum, 0),
- enc_unsigned_long(Val, Message).
-
-getEnumValue([],Enum, _) ->
- orber:dbg("[~p] cdrlib:enc_enum/enc_r_enum(~p); not exist.",
- [?LINE, Enum], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 5),
- completion_status=?COMPLETED_NO});
-getEnumValue([Enum|_List], Enum, N) ->
- N;
-getEnumValue([_ |List], Enum, N) ->
- getEnumValue(List, Enum, N + 1).
-
-%%-----------------------------------------------------------------
-%% Func: dec_enum/2
-%%-----------------------------------------------------------------
-dec_enum(ByteOrder, ElemList, Message) ->
- {N, Rest} = dec_unsigned_long(ByteOrder, Message),
- case catch lists:nth(N + 1, ElemList) of
- {'EXIT', _} ->
- orber:dbg("[~p] cdrlib:dec_enum(~p, ~p); not defined.",
- [?LINE, N, ElemList], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 5),
- completion_status=?COMPLETED_NO});
- X ->
- {list_to_atom(X), Rest}
- end.
-
-
-%%-----------------------------------------------------------------
-%% IIOP 1.1 -
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% longlong
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: enc_longlong/2
-%%-----------------------------------------------------------------
-enc_longlong(X, Message) when is_integer(X) andalso X >= ?LONGLONGMIN andalso X =< ?LONGLONGMAX ->
- [<<X:64/big-signed-integer>> | Message];
-enc_longlong(X, _Message) when is_integer(X) ->
- orber:dbg("[~p] cdrlib:enc_longlong(~p); Out of range.",
- [?LINE, X], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 1), completion_status=?COMPLETED_NO});
-enc_longlong(X, _Message) ->
- orber:dbg("[~p] cdrlib:enc_longlong(~p); not integer.",
- [?LINE, X], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 2), completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------------
-%% Func: dec_longlong/2
-%%-----------------------------------------------------------------
-dec_longlong(big, <<LongLong:64/big-signed-integer,Rest/binary>>) ->
- {LongLong, Rest};
-dec_longlong(little, <<LongLong:64/little-signed-integer,Rest/binary>>) ->
- {LongLong, Rest}.
-
-%%-----------------------------------------------------------------
-%% Func: enc_unsigned_longlong/2
-%%-----------------------------------------------------------------
-enc_unsigned_longlong(X, Message) when is_integer(X) andalso X >= ?ULONGLONGMIN andalso X =< ?ULONGLONGMAX ->
- [<<X:64/big-unsigned-integer>> | Message];
-enc_unsigned_longlong(X, _Message) when is_integer(X) ->
- orber:dbg("[~p] cdrlib:enc_unsigned_longlong(~p); Out of range.",
- [?LINE, X], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 1), completion_status=?COMPLETED_NO});
-enc_unsigned_longlong(X, _Message) ->
- orber:dbg("[~p] cdrlib:enc_unsigned_longlong(~p); not integer >= 0.",
- [?LINE, X], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 2), completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------------
-%% Func: dec_unsigned_longlong/2
-%%-----------------------------------------------------------------
-dec_unsigned_longlong(big, <<ULongLong:64/big-unsigned-integer,Rest/binary>>) ->
- {ULongLong, Rest};
-dec_unsigned_longlong(little, <<ULongLong:64/little-unsigned-integer,Rest/binary>>) ->
- {ULongLong, Rest}.
-
-%%%-----------------------------------------------------------------
-%%% long double [S=1 | E=15 | F=112]
-%%% X = (-1)^S * 2^(E-16383) * 1.F
-%%%-----------------------------------------------------------------
-%-define(LONGDOUBLE_BASE, 16#10000000000000000000000000000).
-%-define(LONGDOUBLE_BIAS, 16383).
-%%%-----------------------------------------------------------------
-%%% Func: enc_longdouble/2
-%%%-----------------------------------------------------------------
-%enc_longdouble(X, Message) when number(X) ->
-% {S, E, F} = enc_ieee(X, ?LONGDOUBLE_BASE, ?LONGDOUBLE_BIAS),
-% [ (S bsl 7) bor ((E bsr 8) band 16#7f),
-% E band 16#ff,
-% (F bsr 104) band 16#ff,
-% (F bsr 96) band 16#ff,
-% (F bsr 88) band 16#ff,
-% (F bsr 80) band 16#ff,
-% (F bsr 72) band 16#ff,
-% (F bsr 64) band 16#ff,
-% (F bsr 56) band 16#ff,
-% (F bsr 48) band 16#ff,
-% (F bsr 40) band 16#ff,
-% (F bsr 32) band 16#ff,
-% (F bsr 24) band 16#ff,
-% (F bsr 16) band 16#ff,
-% (F bsr 8) band 16#ff,
-% F band 16#ff | Message];
-%enc_longdouble(X, Message) ->
-% corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 4), completion_status=?COMPLETED_NO}).
-
-%%%-----------------------------------------------------------------
-%%% Func: dec_longdouble/2
-%%%-----------------------------------------------------------------
-%dec_longdouble([X15,X14,X13,X12,X11,X10,X9,X8,X7,X6,X5,X4,X3,X2,X1,X0 | R], big) ->
-
-% E = (X15 band 16#7f) bsl 8 + X14,
-
-% F = (X13 bsl 104) + (X12 bsl 96) +
-% (X11 bsl 88) + (X10 bsl 80) + (X9 bsl 72) +
-% (X8 bsl 64) + (X7 bsl 56) + (X6 bsl 48) +
-% (X5 bsl 40) + (X4 bsl 32) + (X3 bsl 24) +
-% (X2 bsl 16) + (X1 bsl 8) + X0,
-
-% if
-% E == 0, F == 0 ->
-% { 0.0, R};
-% X15 >= 16#80 ->
-% { - math:pow(2, E-?LONGDOUBLE_BIAS) * (1 + F / ?LONGDOUBLE_BASE), R};
-% true ->
-% { math:pow(2, E-?LONGDOUBLE_BIAS) * (1 + F / ?LONGDOUBLE_BASE), R}
-% end;
-%dec_longdouble([X15,X14,X13,X12,X11,X10,X9,X8,X7,X6,X5,X4,X3,X2,X1,X0 | R], little) ->
-
-% E = (X0 band 16#7f) bsl 8 + X1,
-
-% F =
-% (X2 bsl 104) + (X3 bsl 96) +
-% (X4 bsl 88) + (X5 bsl 80) + (X6 bsl 72) +
-% (X7 bsl 64) + (X8 bsl 56) + (X9 bsl 48) +
-% (X10 bsl 40) + (X11 bsl 32) + (X12 bsl 24) +
-% (X13 bsl 16) + (X14 bsl 8) + X15,
-
-% if
-% E == 0, F == 0 ->
-% { 0.0, R};
-% X0 >= 16#80 ->
-% { - math:pow(2, E-?DOUBLE_BIAS) * (1 + F / ?DOUBLE_BASE), R};
-% true ->
-% { math:pow(2, E-?DOUBLE_BIAS) * (1 + F / ?DOUBLE_BASE), R}
-% end.
-
-%%------------------ END OF MODULE -----------------------------------
-
diff --git a/lib/orber/src/corba.erl b/lib/orber/src/corba.erl
deleted file mode 100644
index 23ce01ffc3..0000000000
--- a/lib/orber/src/corba.erl
+++ /dev/null
@@ -1,2206 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%--------------------------------------------------------------------
-%% File: corba.erl
-%%
-%% Description:
-%% This file contains the CORBA::ORB interface plus some
-%% Orber specific functions.
-%%-----------------------------------------------------------------
--module(corba).
-
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
-%%-----------------------------------------------------------------
-%% Standard interface CORBA
-%%-----------------------------------------------------------------
--export([orb_init/1, orb_init/2]).
-%%-----------------------------------------------------------------
-%% Standard interface CORBA::ORB
-%%-----------------------------------------------------------------
--export([%create_list/2,
- %create_operation_list/2,
- %% get_default_context/1,
- %% 'BOA_init/2,
- resolve_initial_references/1,
- resolve_initial_references/2,
- resolve_initial_references_local/1,
- list_initial_services/0,
- add_initial_service/2,
- remove_initial_service/1,
- resolve_initial_references_remote/2,
- resolve_initial_references_remote/3,
- list_initial_services_remote/1,
- list_initial_services_remote/2,
- object_to_string/1, object_to_string/2,
- object_to_string/3, object_to_string/4,
- string_to_object/1,
- string_to_object/2]).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([create/2,
- create/3,
- create/4,
- create_link/2,
- create_link/3,
- create_link/4,
- create_remote/3,
- create_remote/5,
- create_link_remote/3,
- create_link_remote/5,
- create_nil_objref/0,
- dispose/1,
- create_subobject_key/2,
- get_subobject_key/1,
- get_pid/1,
- raise/1, raise_with_state/2,
- print_object/1,
- print_object/2,
- add_alternate_iiop_address/3,
- add_FTGroup_component/4,
- add_FTPrimary_component/1,
- call_internal/10]).
-
-%%-----------------------------------------------------------------
-%% Internal (inside orber implementation) exports
-%%-----------------------------------------------------------------
--export([call/4, call/5, reply/2,
- cast/4, cast/5, locate/1, locate/2, locate/3,
- request_from_iiop/6,
- common_create/5,
- mk_objkey/4,
- mk_light_objkey/2,
- objkey_to_string/1,
- string_to_objkey/1,
- string_to_objkey_local/1,
- call_relay/3,
- cast_relay/2,
- handle_init/2,
- handle_terminate/3,
- handle_info/3,
- handle_code_change/4,
- handle_call/7,
- handle_call/10,
- handle_cast/9,
- handle_cast/6,
- get_implicit_context/1]).
-
-%%-----------------------------------------------------------------
-%% Internal definitions
-%%-----------------------------------------------------------------
--define(DEBUG_LEVEL, 5).
-
--record(is, {flags = 0}).
-
-%% Defines possible configuration parameters a user can add when
-%% creating new CORBA objects.
--record(options, {sup_child = false,
- persistent = false,
- regname = [],
- pseudo = false,
- object_flags = ?ORB_INIT_FLAGS,
- object_flags_set = ?ORB_INIT_FLAGS,
- create_options = [],
- passive = false,
- group_id = 0,
- internal_state}).
-
--record(extra, {timeout = infinity,
- context = []}).
-
-
-%%--------------------------------------------------------------------
-%% FT stuff
-%%--------------------------------------------------------------------
--define(IDL_MODULES, [oe_TimeBase,
- oe_CosEventComm,
- oe_CosEventChannelAdmin,
- oe_CosNotification,
- oe_CosNotifyComm,
- oe_CosNotifyFilter,
- oe_GIOP]).
-
--define(groupid_to_table(Integer),
- list_to_atom("ft_" ++ integer_to_list(Integer))).
-
--define(RM_TABLE_SPEC,
- [{attributes, record_info(fields, ft_replication_manager)}]).
--define(RO_TABLE_SPEC,
- [{attributes, record_info(fields, ft_replicated_object)}]).
--define(RR_TABLE_SPEC,
- [{attributes, record_info(fields, ft_reply_retention)}]).
-
-%% how long we're allowed to wait for database tables to be available.
--define(TABLE_TIMEOUT, infinite).
-
-%-record(rm_state, {default_options, type_options, node_port_ips}).
-
-%-record(node_port_ip, {node, port, ip}).
-
--record(ft_replication_manager, {object_group_id,
- type_id,
- primary,
- iogr,
- ref_version,
- options}).
-
--record(ft_replicated_object, {group_id, state}).
--record(ft_reply_retention, {retention_id, reply}).
-
-%-record(ft_properties, {replications_style,
-% membership_style,
-% consistency_style,
-% initial_number_replicas,
-% minimum_number_replicas}).
-
-% one should change things work with stdlib:proplist and clean up the mess.
-%-record(ft_criteria, {ft_properties,
-% object_location,
-% object_init,
-% object_impl}).
-
-%%------------------------------------------------------------
-%%
-%% Implementation of CORBA CORBA::ORB interfaces
-%%
-%%------------------------------------------------------------
-
-%%create_list(Count) ->
-%% corba_nvlist:create_list(Count).
-
-%%create_operation_list(OpDef) ->
-%% corba_nvlist:create_operation_list(OpDef).
-
-orb_init(KeyValueList) ->
- orb_init(KeyValueList, "ORBER").
-
-orb_init([], _Name) ->
- ok;
-orb_init(KeyValueList, _Name) ->
- orber:multi_configure(KeyValueList).
-
-%%-----------------------------------------------------------------
-%% Initial reference handling
-%%-----------------------------------------------------------------
-resolve_initial_references(ObjectId) ->
- resolve_initial_references(ObjectId, []).
-resolve_initial_references(ObjectId, Ctx) ->
- case use_local_host(ObjectId) of
- true ->
- orber_initial_references:get(ObjectId);
- Ref ->
- string_to_object(Ref, Ctx)
- end.
-
-resolve_initial_references_local(ObjectId) ->
- orber_initial_references:get(ObjectId).
-
-list_initial_services() ->
- Local = orber_initial_references:list(),
- case orber:get_ORBInitRef() of
- undefined ->
- Local;
- InitRef ->
- orber_tb:unique(Local ++ get_prefixes(InitRef, []))
- end.
-
-get_prefixes([], Acc) ->
- Acc;
-%% A list of ORBInitRef's
-get_prefixes([H|T], Acc) when is_list(H) ->
- [Key|_] = string:tokens(H, "="),
- get_prefixes(T, [Key|Acc]);
-%% A single ORBInitRef
-get_prefixes(InitRef, _Acc) when is_list(InitRef) ->
- [Key|_] = string:tokens(InitRef, "="),
- [Key];
-get_prefixes(What, _) ->
- orber:dbg("[~p] corba:get_prefixes(~p);~nMalformed argument?",
- [?LINE, What], ?DEBUG_LEVEL),
- raise(#'BAD_PARAM'{completion_status = ?COMPLETED_NO}).
-
-
-use_local_host(ObjectId) ->
- case orber:get_ORBInitRef() of
- undefined ->
- case orber:get_ORBDefaultInitRef() of
- undefined ->
- true;
- DefRef ->
- DefRef++"/"++ObjectId
- end;
- InitRef ->
- case check_prefixes(InitRef, ObjectId) of
- false ->
- case orber:get_ORBDefaultInitRef() of
- undefined ->
- true;
- DefRef ->
- DefRef++"/"++ObjectId
- end;
- UseRef ->
- strip_junk(UseRef)
- end
- end.
-
-
-check_prefixes([], _) ->
- false;
-%% A list of ORBInitRef's
-check_prefixes([H|T], ObjectId) when is_list(H) ->
- case prefix(ObjectId, H) of
- false ->
- check_prefixes(T, ObjectId);
- UseRef ->
- UseRef
- end;
-%% A single ORBInitRef
-check_prefixes(InitRef, ObjectId) when is_list(InitRef) ->
- case prefix(ObjectId, InitRef) of
- false ->
- false;
- UseRef ->
- UseRef
- end;
-check_prefixes(What,_) ->
- orber:dbg("[~p] corba:check_prefixes(~p);~nMalformed argument?",
- [?LINE, What], ?DEBUG_LEVEL),
- raise(#'BAD_PARAM'{completion_status = ?COMPLETED_NO}).
-
-
-%% Valid is, for example, "NameService = corbaloc::host/NameService".
-%% Hence, we must remove ' ' and '='.
-strip_junk([32|T]) ->
- strip_junk(T);
-strip_junk([$=|T]) ->
- strip_junk(T);
-strip_junk(Ref) ->
- Ref.
-
-add_initial_service(ObjectId, ObjectRef) ->
- orber_initial_references:add(ObjectId, ObjectRef).
-
-remove_initial_service(ObjectId) ->
- orber_initial_references:remove(ObjectId).
-
-resolve_initial_references_remote(ObjectId, Address) ->
- resolve_initial_references_remote(ObjectId, Address, []).
-
-resolve_initial_references_remote(_ObjectId, [], _Ctx) ->
- raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO});
-resolve_initial_references_remote(ObjectId, [RemoteModifier| Rest], Ctx)
- when is_list(RemoteModifier) ->
- case parse_remote_modifier(RemoteModifier) of
- {error, _} ->
- resolve_initial_references_remote(ObjectId, Rest, Ctx);
- {ok, Host, Port} ->
- IOR = iop_ior:create_external(orber:giop_version(), "",
- Host, list_to_integer(Port), "INIT"),
- %% We know it's an external referens. Hence, no need to check.
- {_, Key} = iop_ior:get_key(IOR),
- orber_iiop:request(Key, 'get', [ObjectId],
- {{'tk_objref', 12, "object"},
- [{'tk_string', 0}],
- []}, 'true', infinity, IOR, Ctx)
- end.
-
-list_initial_services_remote(Address) ->
- list_initial_services_remote(Address, []).
-
-list_initial_services_remote([], _Ctx) ->
- raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO});
-list_initial_services_remote([RemoteModifier| Rest], Ctx) when is_list(RemoteModifier) ->
- case parse_remote_modifier(RemoteModifier) of
- {error, _} ->
- resolve_initial_references_remote(Rest, Ctx);
- {ok, Host, Port} ->
- IOR = iop_ior:create_external(orber:giop_version(), "",
- Host, list_to_integer(Port), "INIT"),
- %% We know it's an external referens. Hence, no need to check.
- {_, Key} = iop_ior:get_key(IOR),
- orber_iiop:request(Key, 'list', [],
- {{'tk_sequence', {'tk_string',0},0},
- [], []}, 'true', infinity, IOR, Ctx)
- end;
-list_initial_services_remote(_, _) ->
- raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-
-parse_remote_modifier("iiop://" ++ Rest) ->
- parse_host_version(Rest);
-parse_remote_modifier(_RemoteModifier) ->
- {error, not_supported}.
-
-parse_host_version("[" ++ Rest) ->
- parse_ipv6(Rest, []);
-parse_host_version(Rest) ->
- parse_ipv4_or_dnsname(Rest, []).
-
-
-parse_ipv4_or_dnsname([$: |Rest], Acc) ->
- {ok, lists:reverse(Acc), Rest};
-parse_ipv4_or_dnsname([C |Rest], Acc) ->
- parse_ipv4_or_dnsname(Rest, [C |Acc]).
-
-parse_ipv6("]:" ++ Rest, Acc) ->
- {ok, lists:reverse(Acc), Rest};
-parse_ipv6([C |Rest], Acc) ->
- parse_ipv6(Rest, [C |Acc]).
-
-
-%%-----------------------------------------------------------------
-%% Objectreference convertions
-%%-----------------------------------------------------------------
-object_to_string(Object) ->
- iop_ior:string_code(Object).
-
-object_to_string(Object, [H|_] = Hosts) when is_list(H) ->
- iop_ior:string_code(Object, Hosts);
-object_to_string(_Object, _Hosts) ->
- raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-object_to_string(Object, [H|_] = Hosts, Port) when is_list(H) andalso
- is_integer(Port) ->
- iop_ior:string_code(Object, Hosts, Port);
-object_to_string(_Object, _Hosts, _Port) ->
- raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-object_to_string(Object, [H|_] = Hosts, Port, SSLPort) when is_list(H) andalso
- is_integer(Port) andalso
- is_integer(SSLPort)->
- iop_ior:string_code(Object, Hosts, Port, SSLPort);
-object_to_string(_Object, _Hosts, _Port, _SSLPort) ->
- raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-
-string_to_object(IORString) ->
- string_to_object(IORString, []).
-
-string_to_object(IORString, Ctx) when is_list(Ctx) ->
- case lists:prefix("IOR", IORString) of
- true ->
- {ObjRef, _, _} = iop_ior:string_decode(IORString),
- ObjRef;
- _ ->
- %% CORBA-2.4 allows both IOR and ior prefix.
- case lists:prefix("ior", IORString) of
- true ->
- {ObjRef, _, _} = iop_ior:string_decode(IORString),
- ObjRef;
- _ ->
- Data = orber_cosnaming_utils:select_type(IORString),
- case orber_cosnaming_utils:lookup(Data, Ctx) of
- String when is_list(String) ->
- {Obj, _, _} = iop_ior:string_decode(String),
- Obj;
- ObjRef ->
- ObjRef
- end
- end
- end;
-string_to_object(IORString, Ctx) ->
- orber:dbg("[~p] corba:string_to_object(~p, ~p);~n"
- "Failed to supply a context list.",
- [?LINE, IORString, Ctx], ?DEBUG_LEVEL),
- raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%------------------------------------------------------------
-%%
-%% Implementation of NON-standard functions
-%%
-%%------------------------------------------------------------
-create(Module, TypeID) ->
- create(Module, TypeID, []).
-
-create(Module, TypeID, Env) ->
- common_create(Module, TypeID, Env, [], 'start').
-
-create(Module, TypeID, Env, {Type, RegName}) ->
- common_create(Module, TypeID, Env, [{regname, {Type, RegName}}], 'start');
-create(Module, TypeID, Env, Options) ->
- common_create(Module, TypeID, Env, Options, 'start').
-
-
-create_link(Module, TypeID) ->
- create_link(Module, TypeID, []).
-
-create_link(Module, TypeID, Env) ->
- common_create(Module, TypeID, Env, [], 'start_link').
-
-create_link(Module, TypeID, Env, {Type, RegName}) ->
- common_create(Module, TypeID, Env, [{regname, {Type, RegName}}], 'start_link');
-create_link(Module, TypeID, Env, Options) ->
- common_create(Module, TypeID, Env, Options, 'start_link').
-
-
-create_remote(Node, Module, TypeID) ->
- create_remote(Node, Module, TypeID, []).
-
-create_remote(Node, Module, TypeID, Env) ->
- common_create_remote(Node, Module, TypeID, Env, [], 'start').
-
-create_remote(Node, Module, TypeID, Env, {Type, RegName}) ->
- common_create_remote(Node, Module, TypeID, Env, [{regname, {Type, RegName}}], 'start');
-create_remote(Node, Module, TypeID, Env, Options) ->
- common_create_remote(Node, Module, TypeID, Env, Options, 'start').
-
-
-create_link_remote(Node, Module, TypeID) ->
- create_link_remote(Node, Module, TypeID, []).
-
-create_link_remote(Node, Module, TypeID, Env) ->
- common_create_remote(Node, Module, TypeID, Env, [], 'start_link').
-
-create_link_remote(Node, Module, TypeID, Env, {Type, RegName}) ->
- common_create_remote(Node, Module, TypeID, Env, [{regname, {Type, RegName}}], 'start_link');
-create_link_remote(Node, Module, TypeID, Env, Options) ->
- common_create_remote(Node, Module, TypeID, Env, Options, 'start_link').
-
-common_create_remote(Node, Module, TypeID, Env, {Type, RegName}, StartMethod) ->
- common_create_remote(Node, Module, TypeID, Env, [{regname, {Type, RegName}}], StartMethod);
-common_create_remote(Node, Module, TypeID, Env, Options, StartMethod) ->
- case node_check(Node) of
- true ->
- rpc:call(Node, corba, common_create, [Module, TypeID, Env, Options, StartMethod]);
- _ ->
- orber:dbg("[~p] corba:common_create_remote(~p);~n"
- "Node not in current domain.", [?LINE, Node], ?DEBUG_LEVEL),
- raise(#'OBJ_ADAPTER'{completion_status=?COMPLETED_NO})
- end.
-
-node_check(Node) ->
- lists:member(Node,orber:orber_nodes()).
-
-common_create(Module, _TypeID, Env, Options, StartMethod) when is_list(Options) ->
- Opt = evaluate_options(Options, #options{}),
- case Opt#options.regname of
- [] ->
- ok;
- {'local', Atom} when is_atom(Atom) andalso Opt#options.persistent == false ->
- ok;
- {'global', _} ->
- ok;
- Why ->
- orber:dbg("[~p] corba:common_create(~p, ~p);~n"
- "Bad name type or combination(~p).",
- [?LINE, Module, Options, Why], ?DEBUG_LEVEL),
- raise(#'BAD_PARAM'{minor=(?ORBER_VMCID bor 1),
- completion_status=?COMPLETED_NO})
- end,
- case Opt of
- #options{pseudo = false, passive = false} ->
- case gen_server:StartMethod(Module, {Opt#options.object_flags, Env},
- Opt#options.create_options) of
- {ok, Pid} ->
- case catch mk_objkey(Module, Pid, Opt#options.regname,
- Opt#options.persistent,
- Opt#options.object_flags) of
- {'EXCEPTION', E} ->
- %% This branch is only used if we couldn't register
- %% our new objectkey due to an internal error in orber.
- gen_server:call(Pid, stop),
- raise(E);
- {'EXIT', _} ->
- %% This branch takes care of exit values
- %% which aren't expected (due to bug).
- gen_server:call(Pid, stop),
- raise(#'BAD_PARAM'{minor=(?ORBER_VMCID bor 1),
- completion_status=?COMPLETED_NO});
- Objkey when Opt#options.sup_child == true ->
- {ok, Pid, Objkey};
- Objkey ->
- Objkey
- end;
- X ->
- X
- end;
- #options{pseudo = true, passive = false} ->
- ModuleImpl = list_to_atom(lists:concat([Module, '_impl'])),
- case ModuleImpl:init(Env) of
- {ok, State} ->
- create_subobject_key(mk_pseudo_objkey(Module, ModuleImpl,
- Opt#options.object_flags),
- State);
- {ok, State,_} ->
- create_subobject_key(mk_pseudo_objkey(Module, ModuleImpl,
- Opt#options.object_flags),
- State);
- Reason ->
- orber:dbg("[~p] corba:common_create(~p);~n"
- "'init' function incorrect(~p).",
- [?LINE, ModuleImpl, Reason], ?DEBUG_LEVEL),
- raise(#'BAD_PARAM'{minor=(?ORBER_VMCID bor 1),
- completion_status=?COMPLETED_NO})
- end;
- #options{pseudo = false, passive = true} ->
- ModuleImpl = list_to_atom(lists:concat([Module, '_impl'])),
- create_subobject_key(mk_passive_objkey(Module, ModuleImpl,
- Opt#options.object_flags),
- ?groupid_to_table(Opt#options.group_id));
- What ->
- orber:dbg("[~p] corba:common_create(~p, ~p);~n"
- "not a boolean(~p).",
- [?LINE, Module, Options, What], ?DEBUG_LEVEL),
- raise(#'BAD_PARAM'{minor=(?ORBER_VMCID bor 1),
- completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : dispose
-%% Arguments : Object
-%% Returns :
-%% Description: Terminate the object represented by the supplied reference.
-%%----------------------------------------------------------------------
-dispose(?ORBER_NIL_OBJREF) ->
- ok;
-dispose(Obj) ->
- corba_boa:dispose(Obj).
-
-%%----------------------------------------------------------------------
-%% Function : create_nil_objref
-%% Arguments : -
-%% Returns : A NIL object reference
-%% Description:
-%%----------------------------------------------------------------------
-create_nil_objref() ->
- ?ORBER_NIL_OBJREF.
-
-%%----------------------------------------------------------------------
-%% Function : create_subobject_key
-%% Arguments : A local object reference and an Erlang term().
-%% Returns : A new instance of the supplied reference with the
-%% sub-object field changed to the given value.
-%% Description: Initially, this field is set to 'undefined'
-%%----------------------------------------------------------------------
-create_subobject_key(Objkey, B) when is_binary(B) ->
- iop_ior:set_privfield(Objkey, B);
-create_subobject_key(Objkey, T) ->
- create_subobject_key(Objkey, term_to_binary(T)).
-
-%%----------------------------------------------------------------------
-%% Function : get_subobject_key
-%% Arguments : A local object reference
-%% Returns : Erlang term().
-%% Description: Return the value set by using create_subobject_key/2
-%%----------------------------------------------------------------------
-get_subobject_key(Objkey) ->
- iop_ior:get_privfield(Objkey).
-
-%%----------------------------------------------------------------------
-%% Function : get_pid
-%% Arguments : A local object reference
-%% Returns : If the object is local and is associated with a pid, this
-%% pid is returned. Otherwise, external- or pseudo-object,
-%% an exception is raised.
-%% Description:
-%%----------------------------------------------------------------------
-get_pid(Objkey) ->
- case iop_ior:get_key(Objkey) of
- {'internal', Key, _, _, _} ->
- orber_objectkeys:get_pid(Key);
- {'internal_registered', Key, _, _, _} when is_atom(Key) ->
- case whereis(Key) of
- undefined ->
- raise(#'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO});
- Pid ->
- Pid
- end;
- R ->
- orber:dbg("[~p] corba:get_pid(~p);~n"
- "Probably a pseudo- or external object(~p).",
- [?LINE, Objkey, R], ?DEBUG_LEVEL),
- raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : raise
-%% Arguments : Local exception representation.
-%% Returns : Throws the exception.
-%% Description:
-%%----------------------------------------------------------------------
-%% To avoid dialyzer warnings due to the use of exit/throw.
--spec raise(term()) -> no_return().
-raise(E) ->
- throw({'EXCEPTION', E}).
-
-%%----------------------------------------------------------------------
-%% Function : raise_with_state
-%% Arguments : Local exception representation.
-%% Returns : Throws the exception.
-%% Description:
-%%----------------------------------------------------------------------
-%% To avoid dialyzer warnings due to the use of exit/throw.
--spec raise_with_state(term(), term()) -> no_return().
-raise_with_state(E, State) ->
- throw({reply, {'EXCEPTION', E}, State}).
-
-%%----------------------------------------------------------------------
-%% Function : reply
-%% Arguments : To - pid
-%% Reply - Erlang term().
-%% Returns :
-%% Description: Used to reply to the invoker but still be able
-%% to do some more work in the callback module.
-%%----------------------------------------------------------------------
-reply(To, Reply) ->
- gen_server:reply(To, Reply).
-
-%%----------------------------------------------------------------------
-%% Function : print_object
-%% Arguments : An object represented as one of the following:
-%% - local (tuple)
-%% - IOR
-%% - stringified IOR
-%% - corbaloc- or corbaname-schema
-%% IoDevice - the same as the io-module defines.
-%% Returns :
-%% Description: Prints the object's components and profiles.
-%%----------------------------------------------------------------------
-print_object(Object) ->
- iop_ior:print(Object).
-print_object(Object, IoDevice) ->
- iop_ior:print(IoDevice, Object).
-
-%%----------------------------------------------------------------------
-%% Function : add_alternate_iiop_address
-%% Arguments : Local object (tuple or IOR).
-%% IP - IP-string
-%% Port - integer().
-%% Returns : A local IOR with a TAG_ALTERNATE_IIOP_ADDRESS component.
-%% Description:
-%%----------------------------------------------------------------------
-add_alternate_iiop_address(Obj, Host, Port) when is_list(Host) andalso is_integer(Port) ->
- TC = #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
- component_data = #'ALTERNATE_IIOP_ADDRESS'{
- 'HostID' = Host,
- 'Port' = Port}},
- iop_ior:add_component(Obj, TC);
-add_alternate_iiop_address(_, Host, Port) ->
- orber:dbg("[~p] corba:add_alternate_iiop_address(~p, ~p);~n"
- "Incorrect argument(s). Host must be IP-string and Port an integer.",
- [?LINE, Host, Port], ?DEBUG_LEVEL),
- raise(#'BAD_PARAM'{completion_status = ?COMPLETED_NO}).
-
-
-%%----------------------------------------------------------------------
-%% Function : add_FTGroup_component
-%% Arguments : Local object (tuple or IOR).
-%% FTDomain - FT Domain. String().
-%% GroupID - Replicated object group's id. Integer(). (ulonglong)
-%% GroupVer - Object group's version number. Integer(). (ulong)
-%% Returns : A local IOR with one TAG_FT_GROUP component.
-%% Description:
-%%----------------------------------------------------------------------
-add_FTGroup_component(Obj, FTDomain, GroupID, GroupVer)
- when is_list(FTDomain) andalso is_integer(GroupID) andalso is_integer(GroupVer) andalso
- GroupID >= ?ULONGLONGMIN andalso GroupID =< ?ULONGLONGMAX andalso
- GroupVer >= ?ULONGMIN andalso GroupVer =< ?ULONGMAX ->
- TC = #'IOP_TaggedComponent'{tag = ?TAG_FT_GROUP,
- component_data = #'FT_TagFTGroupTaggedComponent'{
- version = #'GIOP_Version'{major = 1, minor = 0},
- ft_domain_id = FTDomain,
- object_group_id = GroupID,
- object_group_ref_version = GroupVer}},
- iop_ior:add_component(Obj, TC);
-add_FTGroup_component(_Obj, FTDomain, GroupID, GroupVer) ->
- orber:dbg("[~p] corba:add_FTGroup_component(~p, ~p, ~p);~n"
- "Incorrect argument(s).",
- [?LINE, FTDomain, GroupID, GroupVer], ?DEBUG_LEVEL),
- raise(#'BAD_PARAM'{completion_status = ?COMPLETED_NO}).
-
-
-%%----------------------------------------------------------------------
-%% Function : add_FTPrimary_component
-%% Arguments : Local object (tuple or IOR).
-%% Returns : A local IOR with one TAG_FT_PRIMARY component.
-%% Description:
-%%----------------------------------------------------------------------
-add_FTPrimary_component(Obj) ->
- TC = #'IOP_TaggedComponent'{
- tag=?TAG_FT_PRIMARY,
- component_data=#'FT_TagFTPrimaryTaggedComponent'{primary = true}},
- iop_ior:add_component(Obj, TC).
-
-
-%%-----------------------------------------------------------------
-%% Generic functions for accessing the call-back modules (i.e. X_impl.erl).
-%% These functions are invoked by the generated stubs.
-%%-----------------------------------------------------------------
-handle_init(M, {Flags, Env}) ->
- case M:init(Env) of
- {ok, State} ->
- {ok, {#is{flags = Flags}, State}};
- {ok,State,Timeout} ->
- {ok, {#is{flags = Flags}, State}, Timeout};
- Other ->
- %% E.g. ignore | {stop, Reason}
- Other
- end.
-
-
-handle_terminate(M, Reason, {_InternalState, State}) ->
- catch (M:terminate(Reason, State)).
-
-handle_info(M, Info, {InternalState, State}) ->
- case catch M:handle_info(Info, State) of
- {noreply,NewState} ->
- {noreply, {InternalState, NewState}};
- {noreply, NewState, Timeout} ->
- {noreply, {InternalState, NewState}, Timeout};
- {stop, Reason, NewState} ->
- {stop, Reason, {InternalState, NewState}};
- {'EXIT', Why} ->
- handle_exit(InternalState, State, Why, true,
- {M, handle_info}, [Info, State])
- end.
-
-handle_code_change(M, OldVsn, {InternalState, State}, Extra) ->
- {ok, NewState} = M:code_change(OldVsn, State, Extra),
- {ok, {InternalState, NewState}}.
-
-
-%% This function handles call Pre- & Post-conditions.
-handle_call(M, F, A, {InternalState, State}, Ctx, This, From,
- PreData, PostData, Stub) ->
- CArgs = call_state(A, State, This, From),
- case catch invoke_precond(PreData, Stub, F, CArgs) of
- {'EXIT', Why} ->
- handle_exit(InternalState, State, Why, false, PreData, [Stub, F, CArgs]);
- {'EXCEPTION', E} ->
- {reply, {'EXCEPTION', E}, {InternalState, State}};
- ok ->
- Result = handle_call2(M, F, CArgs, InternalState, State, Ctx),
- case catch invoke_postcond(PostData, Stub, F, CArgs, Result) of
- {'EXIT', Why} ->
- handle_exit(InternalState, State, Why, false, PostData, A);
- {'EXCEPTION', E} ->
- {reply, {'EXCEPTION', E}, {InternalState, State}};
- ok ->
- Result
- end
- end.
-
-
-invoke_precond(false, _, _, _) ->
- ok;
-invoke_precond({CondM, CondF}, Stub, F, CArgs) ->
- CondM:CondF(Stub, F, CArgs).
-
-%% We must remove the Internal State before invoking post-cond.
-invoke_postcond(false, _, _, _, _) ->
- ok;
-invoke_postcond({CondM, CondF}, Stub, F, CArgs, {reply, Reply, {_, NS}}) ->
- CondM:CondF(Stub, F, CArgs, {reply, Reply, NS});
-invoke_postcond({CondM, CondF}, Stub, F, CArgs, {reply, Reply, {_, NS}, Timeout}) ->
- CondM:CondF(Stub, F, CArgs, {reply, Reply, NS, Timeout});
-invoke_postcond({CondM, CondF}, Stub, F, CArgs, {stop, Reason, Reply, {_, NS}}) ->
- CondM:CondF(Stub, F, CArgs, {stop, Reason, Reply, NS});
-invoke_postcond({CondM, CondF}, Stub, F, CArgs, {stop, Reason, {_, NS}}) ->
- CondM:CondF(Stub, F, CArgs, {stop, Reason, NS});
-invoke_postcond({CondM, CondF}, Stub, F, CArgs, {noreply,{_, NS}}) ->
- CondM:CondF(Stub, F, CArgs, {noreply,NS});
-invoke_postcond({CondM, CondF}, Stub, F, CArgs, {noreply,{_, NS}, Timeout}) ->
- CondM:CondF(Stub, F, CArgs, {noreply, NS, Timeout});
-invoke_postcond({CondM, CondF}, Stub, F, CArgs, Result) ->
- CondM:CondF(Stub, F, CArgs, Result).
-
-
-handle_call(M, F, A, {InternalState, State}, Ctx, This, From) ->
- handle_call2(M, F, call_state(A, State, This, From), InternalState, State, Ctx).
-
-handle_call2(M, F, A, InternalState, State, []) ->
- case catch apply(M, F, A) of
- {reply, Reply, NewState} ->
- {reply, add_context(Reply), {InternalState, NewState}};
- {reply, Reply, NewState, Timeout} ->
- {reply, add_context(Reply), {InternalState, NewState}, Timeout};
- {stop, Reason, Reply, NewState} ->
- {stop, Reason, add_context(Reply), {InternalState, NewState}};
- {stop, Reason, NewState} ->
- {stop, Reason, {InternalState, NewState}};
- {noreply,NewState} ->
- {noreply,{InternalState, NewState}};
- {noreply,NewState,Timeout} ->
- {noreply,{InternalState, NewState},Timeout};
- {'EXIT', Reason} ->
- handle_exit(InternalState, State, Reason, false, {M, F}, A);
- {'EXCEPTION', E} ->
- {reply, add_context({'EXCEPTION', E}), {InternalState, State}};
- {Reply, NewState} ->
- {reply, add_context(Reply), {InternalState, NewState}}
- end;
-handle_call2(M, F, A, InternalState, State, Ctx) ->
- %% Set the new Context.
- put(oe_server_in_context, Ctx),
- case catch apply(M, F, A) of
- {reply, Reply, NewState} ->
- put(oe_server_in_context, undefined),
- {reply, add_context(Reply), {InternalState, NewState}};
- {reply, Reply, NewState, Timeout} ->
- put(oe_server_in_context, undefined),
- {reply, add_context(Reply), {InternalState, NewState}, Timeout};
- {stop, Reason, Reply, NewState} ->
- {stop, Reason, add_context(Reply), {InternalState, NewState}};
- {stop, Reason, NewState} ->
- {stop, Reason, {InternalState, NewState}};
- {noreply,NewState} ->
- put(oe_server_in_context, undefined),
- {noreply, {InternalState, NewState}};
- {noreply, {InternalState, NewState}, Timeout} ->
- put(oe_server_in_context, undefined),
- {noreply, {InternalState, NewState},Timeout};
- {'EXIT', Reason} ->
- handle_exit(InternalState, State, Reason, false, {M, F}, A);
- {'EXCEPTION', E} ->
- put(oe_server_in_context, undefined),
- {reply, add_context({'EXCEPTION', E}), {InternalState, State}};
- {Reply, NewState} ->
- put(oe_server_in_context, undefined),
- {reply, add_context(Reply), {InternalState, NewState}}
- end.
-
-call_state(A, State, false, false) ->
- [State|A];
-call_state(A, State, false, From) ->
- [From, State|A];
-call_state(A, State, This, false) ->
- [This, State|A];
-call_state(A, State, This, From) ->
- [This, From, State|A].
-
-cast_state(A, State, false) ->
- [State|A];
-cast_state(A, State, This) ->
- [This, State|A].
-
-add_context(Reply) ->
- %% Reset oe_server_out_context
- case put(oe_server_out_context, undefined) of
- undefined ->
- Reply;
- _OutCtx ->
- %% The previous value wasn't 'undefined', which means that
- %% the server supplied a return context.
- Reply
- end.
-
-
-%% This function handles call Pre- & Post-conditions.
-handle_cast(M, F, A, {InternalState, State}, Ctx, This, PreData, PostData, Stub) ->
- CArgs = cast_state(A, State, This),
- case catch invoke_precond(PreData, Stub, F, CArgs) of
- {'EXIT', Why} ->
- handle_exit(InternalState, State, Why, true, PreData, [Stub, F, CArgs]);
- {'EXCEPTION', _} ->
- {noreply, {InternalState, State}};
- ok ->
- Result = handle_cast2(M, F, CArgs, InternalState, State, Ctx),
- case catch invoke_postcond(PostData, Stub, F, CArgs, Result) of
- {'EXIT', Why} ->
- handle_exit(InternalState, State, Why, true, PostData, A);
- {'EXCEPTION', _} ->
- {noreply, {InternalState, State}};
- ok ->
- Result
- end
- end.
-
-
-handle_cast(M, F, A, {InternalState, State}, Ctx, This) ->
- handle_cast2(M, F, cast_state(A, State, This), InternalState, State, Ctx).
-
-handle_cast2(M, F, A, InternalState, State, []) ->
- case catch apply(M, F, A) of
- {noreply, NewState} ->
- {noreply, {InternalState, NewState}};
- {noreply, NewState, Timeout} ->
- {noreply, {InternalState, NewState}, Timeout};
- {stop, Reason, NewState} ->
- {stop, Reason, {InternalState, NewState}};
- {'EXCEPTION', _} ->
- {noreply, {InternalState, State}};
- {'EXIT', Reason} ->
- handle_exit(InternalState, State, Reason, true, {M, F}, A);
- NewState ->
- {noreply, {InternalState, NewState}}
- end;
-handle_cast2(M, F, A, InternalState, State, Ctx) ->
- put(oe_server_in_context, Ctx),
- case catch apply(M, F, A) of
- {noreply, NewState} ->
- put(oe_server_in_context, undefined),
- {noreply, {InternalState, NewState}};
- {noreply, NewState, Timeout} ->
- put(oe_server_in_context, undefined),
- {noreply, {InternalState, NewState}, Timeout};
- {stop, Reason, NewState} ->
- {stop, Reason, {InternalState, NewState}};
- {'EXCEPTION', _} ->
- put(oe_server_in_context, undefined),
- {noreply, {InternalState, State}};
- {'EXIT', Reason} ->
- handle_exit(InternalState, State, Reason, true, {M, F}, A);
- NewState ->
- put(oe_server_in_context, undefined),
- {noreply, {InternalState, NewState}}
- end.
-
-handle_exit(InternalState, State, {undef, [{M, F, _, _}|_]} = Reason,
- OnewayOp, {M, F}, A) ->
- case catch check_exports(M:module_info(exports), F) of
- {'EXIT',{undef,_}} ->
- %% No such module.
- orber:dbg("~p.beam doesn't exist.~n"
- "Check IC compile options (e.g. 'impl') and that the~n"
- "beam-file is load-able.",
- [M], ?DEBUG_LEVEL),
- reply_after_exit(InternalState, State, Reason, OnewayOp,
- #'OBJ_ADAPTER'{minor=(?ORBER_VMCID bor 1),
- completion_status=?COMPLETED_MAYBE});
- "" ->
- orber:dbg("~p:~p/~p doesn't exist.~n"
- "Check spelling, export-attributes etc",
- [M, F, length(A)], ?DEBUG_LEVEL),
- reply_after_exit(InternalState, State, Reason, OnewayOp,
- #'OBJ_ADAPTER'{minor=(?ORBER_VMCID bor 2),
- completion_status=?COMPLETED_MAYBE});
- Exports when is_list(Exports) ->
- orber:dbg("~p:~p/~p doesn't exist.~n"
- "~p:~p~s do exists.~nCheck export-attributes etc",
- [M, F, length(A), M, F, Exports], ?DEBUG_LEVEL),
- reply_after_exit(InternalState, State, Reason, OnewayOp,
- #'OBJ_ADAPTER'{minor=(?ORBER_VMCID bor 3),
- completion_status=?COMPLETED_MAYBE});
- _ ->
- %% Should never happen
- reply_after_exit(InternalState, State, Reason, OnewayOp,
- #'OBJ_ADAPTER'{minor=(?ORBER_VMCID bor 4),
- completion_status=?COMPLETED_MAYBE})
- end;
-handle_exit(InternalState, State, {undef, [{M2, F2, A2, _}|_]} = Reason,
- OnewayOp, {M, F}, A) ->
- case catch check_exports(M2:module_info(exports), F2) of
- {'EXIT',{undef,_}} ->
- %% No such module.
- orber:dbg("~p.beam doesn't exist.~n"
- "~p:~p/~p invoked an operation on the module above.~n"
- "Check IC compile options and that the beam-file is load-able.",
- [M2, M, F, length(A)], ?DEBUG_LEVEL),
- reply_after_exit(InternalState, State, Reason, OnewayOp,
- #'OBJ_ADAPTER'{minor=(?ORBER_VMCID bor 5),
- completion_status=?COMPLETED_MAYBE});
- "" ->
- orber:dbg("~p:~p/~p doesn't exist.~n"
- "~p:~p/~p invoked the operation above~n"
- "Check spelling, export-attributes etc",
- [M2, F2, length(A2), M, F, length(A)], ?DEBUG_LEVEL),
- reply_after_exit(InternalState, State, Reason, OnewayOp,
- #'OBJ_ADAPTER'{minor=(?ORBER_VMCID bor 6),
- completion_status=?COMPLETED_MAYBE});
- Exports when is_list(Exports) ->
- orber:dbg("~p:~p/~p doesn't exist.~n"
- "~p:~p~s do exist(s).~nCheck export-attributes etc~n"
- "~p:~p/~p invoked the operation above~n",
- [M2, F2, length(A2), M2, F2, Exports, M, F, length(A)], ?DEBUG_LEVEL),
- reply_after_exit(InternalState, State, Reason, OnewayOp,
- #'OBJ_ADAPTER'{minor=(?ORBER_VMCID bor 7),
- completion_status=?COMPLETED_MAYBE});
- _ ->
- %% Should never happen
- reply_after_exit(InternalState, State, Reason, OnewayOp,
- #'OBJ_ADAPTER'{minor=(?ORBER_VMCID bor 4),
- completion_status=?COMPLETED_MAYBE})
- end;
-%% Misc errors. We separate between direct and in-direct errors. Due to different
-%% notation we must separate between different cases.
-handle_exit(InternalState, State, {{case_clause,_}, [{M, F, _}|_]} = Reason,
- OnewayOp, {M, F}, A) ->
- orber:dbg("~p:~p/~p contains a 'case_clause' error.",
- [M, F, length(A)], ?DEBUG_LEVEL),
- reply_after_exit(InternalState, State, Reason, OnewayOp,
- #'OBJ_ADAPTER'{minor=(?ORBER_VMCID bor 8),
- completion_status=?COMPLETED_MAYBE});
-handle_exit(InternalState, State, {Reason, [{M, F, _}|_]}, OnewayOp, {M, F}, A) ->
- orber:dbg("~p:~p/~p contains a '~p' error.",
- [M, F, length(A), Reason], ?DEBUG_LEVEL),
- reply_after_exit(InternalState, State, Reason, OnewayOp,
- #'OBJ_ADAPTER'{minor=(?ORBER_VMCID bor 8),
- completion_status=?COMPLETED_MAYBE});
-handle_exit(InternalState, State, {function_clause, [{M2, F2, A2}|_]} = Reason,
- OnewayOp, {M, F}, A) ->
- orber:dbg("~p:~p/~p contains a 'function_clause' error.~n"
- "Invoked via the operation:~n"
- "~p:~p/~p",
- [M2, F2, length(A2), M, F, length(A)], ?DEBUG_LEVEL),
- reply_after_exit(InternalState, State, Reason, OnewayOp,
- #'OBJ_ADAPTER'{minor=(?ORBER_VMCID bor 9),
- completion_status=?COMPLETED_MAYBE});
-handle_exit(InternalState, State, {{case_clause,_}, [{M2, F2, A2}|_]} = Reason,
- OnewayOp, {M, F}, A) ->
- orber:dbg("~p:~p/~p contains a 'case_clause' error.~n"
- "Invoked via the operation:~n"
- "~p:~p/~p",
- [M2, F2, A2, M, F, length(A)], ?DEBUG_LEVEL),
- reply_after_exit(InternalState, State, Reason, OnewayOp,
- #'OBJ_ADAPTER'{minor=(?ORBER_VMCID bor 9),
- completion_status=?COMPLETED_MAYBE});
-handle_exit(InternalState, State, {Reason, [{M2, F2, A2}|_]} = Reason,
- OnewayOp, {M, F}, A) ->
- orber:dbg("~p:~p/~p contains a '~p' error.~n"
- "Invoked via the operation:~n"
- "~p:~p/~p",
- [M2, F2, A2, Reason, M, F, length(A)], ?DEBUG_LEVEL),
- reply_after_exit(InternalState, State, Reason, OnewayOp,
- #'OBJ_ADAPTER'{minor=(?ORBER_VMCID bor 9),
- completion_status=?COMPLETED_MAYBE});
-handle_exit(InternalState, State, Reason, OnewayOp, {M, F}, A) ->
- orber:dbg("~p:~p(~p) ->~n"
- " {EXIT, ~p}~n",
- [M, F, A, Reason], ?DEBUG_LEVEL),
- reply_after_exit(InternalState, State, Reason, OnewayOp,
- #'OBJ_ADAPTER'{minor=(?ORBER_VMCID bor 10),
- completion_status=?COMPLETED_MAYBE}).
-
-
-reply_after_exit(#is{flags = Flags} = InternalState, State,
- Reason, OnewayOp, Exc) ->
- case ?ORB_FLAG_TEST(Flags, ?ORB_SURVIVE_EXIT) of
- false ->
- exit(Reason);
- true when OnewayOp == false ->
- put(oe_server_in_context, undefined),
- {reply, {'EXCEPTION', Exc}, {InternalState, State}};
- true ->
- %% One-way operation. Cannot return exception.
- put(oe_server_in_context, undefined),
- {noreply, {InternalState, State}}
- end.
-
-
-check_exports(Exports, Op) ->
- check_exports(Exports, Op, []).
-
-check_exports([], _, Acc) ->
- Acc;
-check_exports([{Op, Arity}|Rest], Op, Acc) ->
- check_exports(Rest, Op, Acc ++ "/" ++ integer_to_list(Arity));
-check_exports([_|Rest], Op, Acc) ->
- check_exports(Rest, Op, Acc).
-
-
-%%-----------------------------------------------------------------
-%% Corba:call - the function for reqests
-%%-----------------------------------------------------------------
-call(Obj, Func, Args, TypesOrMod) ->
- call_helper(Obj, Func, Args, TypesOrMod, infinity, []).
-
-call(Obj, Func, Args, TypesOrMod, [{context, Ctx}]) ->
- call_helper(Obj, Func, Args, TypesOrMod, infinity, Ctx);
-call(Obj, Func, Args, TypesOrMod, [{timeout, Timeout}]) ->
- call_helper(Obj, Func, Args, TypesOrMod, Timeout, []);
-call(Obj, Func, Args, TypesOrMod, Extra) when is_list(Extra) ->
- ExtraData = extract_extra_data(Extra, #extra{}),
- call_helper(Obj, Func, Args, TypesOrMod, ExtraData#extra.timeout,
- ExtraData#extra.context);
-call(Obj, Func, Args, TypesOrMod, Timeout) ->
- call_helper(Obj, Func, Args, TypesOrMod, Timeout, []).
-
-call_helper(Obj, Func, Args, TypesOrMod, Timeout, InCtx) ->
- Ctx = get_implicit_context(InCtx),
- case iop_ior:get_key(Obj) of
- {'internal', Key, _, Flags, Mod} ->
- Pid = orber_objectkeys:get_pid(Key),
- call_internal(Pid, Obj, Func, Args, TypesOrMod,
- ?ORB_FLAG_TEST(Flags, ?ORB_TYPECHECK),
- ?ORB_FLAG_TEST(Flags, ?ORB_USE_PI), Mod, Timeout, Ctx);
- {'internal_registered', Key, _, Flags, Mod} ->
- call_internal(Key, Obj, Func, Args, TypesOrMod,
- ?ORB_FLAG_TEST(Flags, ?ORB_TYPECHECK),
- ?ORB_FLAG_TEST(Flags, ?ORB_USE_PI), Mod, Timeout, Ctx);
- {'external', Key} when is_atom(TypesOrMod) ->
- case catch TypesOrMod:oe_tc(Func) of
- {'EXIT', What} ->
- orber:dbg("[~p] corba:call_helper(~p);~n"
- "The call-back module does not exist or"
- " incorrect IC-version used.~nReason: ~p",
- [?LINE, TypesOrMod, What], ?DEBUG_LEVEL),
- raise(#'TRANSIENT'{minor=(?ORBER_VMCID bor 7),
- completion_status=?COMPLETED_NO});
- undefined ->
- raise(#'BAD_OPERATION'{minor = (?ORBER_VMCID bor 4),
- completion_status=?COMPLETED_NO});
- Types ->
- orber_iiop:request(Key, Func, Args, Types, 'true', Timeout, Obj, Ctx)
- end;
- {'external', Key} ->
- orber_iiop:request(Key, Func, Args, TypesOrMod, 'true', Timeout, Obj, Ctx)
- end.
-
-get_implicit_context([]) ->
- case get(oe_server_in_context) of
- undefined ->
- [];
- ImplCtx ->
- ImplCtx
- end;
-get_implicit_context(Ctx) ->
- case get(oe_server_in_context) of
- undefined ->
- Ctx;
- ImplCtx ->
- %% Both defined. An explicit interface context overrides
- %% an implicit.
- case check_for_interface_ctx(Ctx) of
- false ->
- ImplCtx;
- true ->
- remove_interface_ctx(ImplCtx, Ctx)
- end
- end.
-
-check_for_interface_ctx([]) ->
- false;
-check_for_interface_ctx([#'IOP_ServiceContext'
- {context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface, _I}}|_]) ->
- true;
-check_for_interface_ctx([_|T]) ->
- check_for_interface_ctx(T).
-
-remove_interface_ctx([], Acc) ->
- Acc;
-remove_interface_ctx([#'IOP_ServiceContext'
- {context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface, _I}}|T], Acc) ->
- remove_interface_ctx(T, Acc);
-remove_interface_ctx([H|T], Acc) ->
- remove_interface_ctx(T, [H|Acc]).
-
-
-extract_extra_data([], ED) ->
- ED;
-extract_extra_data([{context, Ctx}|T], ED) ->
- extract_extra_data(T, ED#extra{context = Ctx});
-extract_extra_data([{timeout, Timeout}|T], ED) ->
- extract_extra_data(T, ED#extra{timeout = Timeout}).
-
-call_internal(Pid, Obj, Func, Args, Types, Check, PI, Mod, Timeout, Ctx)
- when is_pid(Pid) andalso node(Pid) == node() ->
- invoke_pi_request(PI, Obj, Ctx, Func, Args),
- typecheck_request(Check, Args, Types, Func),
- case catch gen_server:call(Pid, {Obj, Ctx, Func, Args}, Timeout) of
- {'EXCEPTION', E} ->
- invoke_pi_reply(PI, Obj, Ctx, Func, {'EXCEPTION', E}),
- typecheck_reply(Check, {'EXCEPTION', E}, Mod, Func),
- raise(E);
- {'EXIT',{timeout, _}} ->
- Exc = #'TIMEOUT'{completion_status=?COMPLETED_MAYBE},
- invoke_pi_reply(PI, Obj, Ctx, Func, {'EXCEPTION', Exc}),
- raise(Exc);
- {'EXIT',R} ->
- orber:dbg("[~p] corba:call_internal(~p, ~p, ~p);~ncall exit(~p).",
- [?LINE, Func, Args, Types, R], ?DEBUG_LEVEL),
- Exc = #'TRANSIENT'{minor=(?ORBER_VMCID bor 4),
- completion_status=?COMPLETED_NO},
- invoke_pi_reply(PI, Obj, Ctx, Func, {'EXCEPTION', Exc}),
- raise(Exc);
- Res ->
- invoke_pi_reply(PI, Obj, Ctx, Func, Res),
- typecheck_reply(Check, Res, Types, Func),
- Res
- end;
-call_internal(Pid, Obj, Func, Args, Types, Check, PI,
- _Mod, Timeout, Ctx) when is_pid(Pid) ->
- typecheck_request(Check, Args, Types, Func),
- case catch rpc:call(node(Pid), corba, call_relay,
- [Pid, {Obj, Ctx, Func, Args}, Timeout]) of
- {'EXCEPTION', E} ->
- invoke_pi_reply(PI, Obj, Ctx, Func, {'EXCEPTION', E}),
- typecheck_reply(Check, {'EXCEPTION', E}, Types, Func),
- raise(E);
- {badrpc, {'EXIT',R}} ->
- orber:dbg("[~p] corba:call_internal(~p, ~p, ~p);~ncall exit(~p).",
- [?LINE, Func, Args, Types, R], ?DEBUG_LEVEL),
- Exc = #'TRANSIENT'{minor=(?ORBER_VMCID bor 3),
- completion_status=?COMPLETED_MAYBE},
- invoke_pi_reply(PI, Obj, Ctx, Func, {'EXCEPTION', Exc}),
- raise(Exc);
- {badrpc,nodedown} ->
- orber:dbg("[~p] corba:call_internal(~p, ~p, ~p);~nNode ~p down.",
- [?LINE, Func, Args, Types, node(Pid)], ?DEBUG_LEVEL),
- Exc = #'TRANSIENT'{minor=(?ORBER_VMCID bor 2),
- completion_status=?COMPLETED_NO},
- invoke_pi_reply(PI, Obj, Ctx, Func, {'EXCEPTION', Exc}),
- raise(Exc);
- {badrpc, Reason} ->
- orber:dbg("[~p] corba:call_internal(~p, ~p, ~p);~n"
- "Unable to invoke operation due to: ~p",
- [?LINE, Func, Args, Types, Reason], ?DEBUG_LEVEL),
- Exc = #'TRANSIENT'{minor=(?ORBER_VMCID bor 5),
- completion_status=?COMPLETED_MAYBE},
- invoke_pi_reply(PI, Obj, Ctx, Func, {'EXCEPTION', Exc}),
- raise(Exc);
- Res ->
- invoke_pi_reply(PI, Obj, Ctx, Func, Res),
- typecheck_reply(Check, Res, Types, Func),
- Res
- end;
-
-%% This case handles if the reference is created as a Pseudo object.
-%% Just call apply/3.
-call_internal({pseudo, Module}, Obj, Func, Args, Types, Check, PI,
- _Mod, _Timeout, Ctx) ->
- OldCtx = put(oe_server_in_context, Ctx),
- invoke_pi_request(PI, Obj, Ctx, Func, Args),
- typecheck_request(Check, Args, Types, Func),
- State = binary_to_term(get_subobject_key(Obj)),
- case catch apply(Module, Func, [Obj, State|Args]) of
- {noreply, _} ->
- put(oe_server_in_context, OldCtx),
- ok;
- {noreply, _, _} ->
- put(oe_server_in_context, OldCtx),
- ok;
- {reply, Reply, _} ->
- put(oe_server_in_context, OldCtx),
- invoke_pi_reply(PI, Obj, Ctx, Func, Reply),
- typecheck_reply(Check, Reply, Types, Func),
- Reply;
- {reply, Reply, _, _} ->
- put(oe_server_in_context, OldCtx),
- invoke_pi_reply(PI, Obj, Ctx, Func, Reply),
- typecheck_reply(Check, Reply, Types, Func),
- Reply;
- {stop, _, Reply, _} ->
- put(oe_server_in_context, OldCtx),
- invoke_pi_reply(PI, Obj, Ctx, Func, Reply),
- typecheck_reply(Check, Reply, Types, Func),
- Reply;
- {stop, _, _} ->
- put(oe_server_in_context, OldCtx),
- ok;
- {'EXCEPTION', E} ->
- put(oe_server_in_context, OldCtx),
- invoke_pi_reply(PI, Obj, Ctx, Func, {'EXCEPTION', E}),
- typecheck_reply(Check, {'EXCEPTION', E}, Types, Func),
- raise(E);
- {'EXIT', What} ->
- put(oe_server_in_context, OldCtx),
- orber:dbg("[~p] corba:call_internal(~p, ~p, ~p);~n"
- "Pseudo object exit(~p).",
- [?LINE, Func, Args, Types, What], ?DEBUG_LEVEL),
- Exc = #'TRANSIENT'{minor=(?ORBER_VMCID bor 4),
- completion_status=?COMPLETED_MAYBE},
- invoke_pi_reply(PI, Obj, Ctx, Func, {'EXCEPTION', Exc}),
- raise(Exc);
- Unknown ->
- put(oe_server_in_context, OldCtx),
- orber:dbg("[~p] corba:call_internal(~p, ~p, ~p);~n"
- "Pseudo object failed due to bad return value (~p).",
- [?LINE, Func, Args, Types, Unknown], ?DEBUG_LEVEL),
- Exc = #'TRANSIENT'{minor=(?ORBER_VMCID bor 6),
- completion_status=?COMPLETED_MAYBE},
- invoke_pi_reply(PI, Obj, Ctx, Func, {'EXCEPTION', Exc}),
- raise(Exc)
- end;
-call_internal({passive, Module}, Obj, Func, Args, Types, Check, PI,
- Mod, Timeout, Ctx) ->
- invoke_pi_request(PI, Obj, Ctx, Func, Args),
- typecheck_request(Check, Args, Types, Func),
- GroupID = binary_to_term(get_subobject_key(Obj)),
- Transaction =
- fun() ->
- ObjectGroup = read_object_group(GroupID),
- call_primary_protected(ObjectGroup, Module, Obj,
- Func, Args, GroupID,
- get_FTRequestCtx(Ctx))
- end,
- case mnesia:transaction(Transaction) of
- {atomic, Reply} ->
- %% this check should be inside transaction so that
- %% failing typecheck_reply would result in transaction
- %% abortion. Or not. call_internal(Registered...) does not
- %% cancel the state transition even if the result isn't type compliant.
- %% So, we do likewise.
- typecheck_reply(Check, Reply, Mod, Func),
- Reply;
- {aborted, {not_primary, Primary, _}} ->
- FTRequestCtx = mk_FTRequestCtx(10000000),
- case rpc:call(Primary, corba, call_internal,
- [{passive, Module}, Obj, Func, Args,
- Types, Check, PI, Mod, Timeout,
- [FTRequestCtx|Ctx]]) of
- {badrpc, Reason} ->
- orber:dbg("[~p] corba:call_passive(~p, ~p, ~p); ~n"
- " badrpc(~p).",
- [?LINE, Func, Args, Types, Reason],?DEBUG_LEVEL),
- raise(#'TRANSIENT'{minor=0,
- completion_status=?COMPLETED_MAYBE});
- %% one should keep trying request_duration_policy_value -time.
- {'EXCEPTION', E} ->
- invoke_pi_reply(PI, Obj, Ctx, Func, {'EXCEPTION', E}),
- raise(E);
- Reply ->
- %% is this typecheck_reply neccessary? The check is made
- %% on the remote node...
- invoke_pi_reply(PI, Obj, Ctx, Func, Reply),
- typecheck_reply(Check, Reply, Mod, Func),
- Reply
- %% generate RetentionID's and call Primary node with flag that tells
- %% the node not to escalate rpc call's to next node if the primary
- %% has changed again.
- %% raise({not_primary, Primary});
- end;
- {aborted, {throw, {'EXCEPTION', E}}} ->
- invoke_pi_reply(PI, Obj, Ctx, Func, {'EXCEPTION', E}),
- typecheck_reply(Check, {'EXCEPTION', E}, Mod, Func),
- raise(E);
- {aborted, {'EXIT', What}} ->
- orber:dbg("[~p] corba:call_passive(~p, ~p, ~p); " ++
- "Passive object exit(~p).",
- [?LINE, Func, Args, Types, What], ?DEBUG_LEVEL),
- Exc = #'TRANSIENT'{minor=(?ORBER_VMCID bor 4),
- completion_status=?COMPLETED_MAYBE},
- invoke_pi_reply(PI, Obj, Ctx, Func, {'EXCEPTION', Exc}),
- raise(Exc);
- {aborted, Unknown} ->
- orber:dbg("[~p] corba:call_passive(~p, ~p, ~p); " ++
- "Passive object failed due to bad return value (~p).",
- [?LINE, Func, Args, Types, Unknown], ?DEBUG_LEVEL),
- Exc = #'TRANSIENT'{minor=(?ORBER_VMCID bor 6),
- completion_status=?COMPLETED_MAYBE},
- invoke_pi_reply(PI, Obj, Ctx, Func, {'EXCEPTION', Exc}),
- raise(Exc)
- end;
-call_internal(Registered, Obj, Func, Args, Types, Check, PI,
- _Mod, Timeout, Ctx) when is_atom(Registered)->
- invoke_pi_request(PI, Obj, Ctx, Func, Args),
- typecheck_request(Check, Args, Types, Func),
- case whereis(Registered) of
- undefined ->
- Exc = #'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO},
- invoke_pi_reply(PI, Obj, Ctx, Func, {'EXCEPTION', Exc}),
- raise(Exc);
- P ->
- case catch gen_server:call(P, {Obj, Ctx, Func, Args}, Timeout) of
- {'EXCEPTION', E} ->
- invoke_pi_reply(PI, Obj, Ctx, Func, {'EXCEPTION', E}),
- typecheck_reply(Check, {'EXCEPTION', E}, Types, Func),
- raise(E);
- {'EXIT',{timeout, _}} ->
- Exc = #'TIMEOUT'{completion_status=?COMPLETED_MAYBE},
- invoke_pi_reply(PI, Obj, Ctx, Func, {'EXCEPTION', Exc}),
- raise(Exc);
- {'EXIT',R} ->
- orber:dbg("[~p] corba:call_internal(~p, ~p, ~p).~n"
- "call exit(~p).",
- [?LINE, Func, Args, Types, R], ?DEBUG_LEVEL),
- Exc = #'TRANSIENT'{minor=(?ORBER_VMCID bor 5),
- completion_status=?COMPLETED_MAYBE},
- invoke_pi_reply(PI, Obj, Ctx, Func, {'EXCEPTION', Exc}),
- raise(Exc);
- Res ->
- invoke_pi_reply(PI, Obj, Ctx, Func, Res),
- typecheck_reply(Check, Res, Types, Func),
- Res
- end
- end.
-
-invoke_pi_request(false, _Obj, _Ctx, _Func, _Args) ->
- ok;
-invoke_pi_request(_, Obj, Ctx, Func, Args) ->
- case orber:get_cached_interceptors() of
- {native, PIs} ->
- orber_pi:out_request(PIs, Obj, Ctx, Func, "localhost", Args);
- _ ->
- ok
- end.
-
-invoke_pi_reply(false, _Obj, _Ctx, _Func, _Res) ->
- ok;
-invoke_pi_reply(_, Obj, Ctx, Func, Res) ->
- case orber:get_cached_interceptors() of
- {native, PIs} ->
- orber_pi:in_reply(PIs, Obj, Ctx, Func, "localhost", Res);
- _ ->
- ok
- end.
-
-typecheck_request(false, _, _, _) ->
- ok;
-typecheck_request(true, Args, Mod, Func) when is_atom(Mod) ->
- case catch Mod:oe_tc(Func) of
- undefined ->
- raise(#'BAD_OPERATION'{minor = (?ORBER_VMCID bor 4),
- completion_status=?COMPLETED_NO});
- {'EXIT', What} ->
- orber:dbg("[~p] corba:typecheck_request(~p, ~p, ~p);~n"
- "The call-back module does not exist or incorrect"
- "IC-version used.~nReason: ~p",
- [?LINE, Mod, Func, Args, What], ?DEBUG_LEVEL),
- raise(#'TRANSIENT'{minor=(?ORBER_VMCID bor 7),
- completion_status=?COMPLETED_NO});
- Types ->
- typecheck_request_helper(Types, Args, Mod, Func)
- end;
-typecheck_request(true, Args, Types, Func) ->
- typecheck_request_helper(Types, Args, Types, Func).
-
-typecheck_request_helper(Types, Args, Mod, Func) ->
- case catch cdr_encode:validate_request_body(
- #giop_env{version = {1,2}, tc = Types, parameters = Args,
- host = orber:host(), iiop_port = orber:iiop_port(),
- iiop_ssl_port = orber:iiop_ssl_port(),
- domain = orber:domain(),
- partial_security = orber:partial_security(),
- flags = orber:get_flags()}) of
- {'EXCEPTION', E} ->
- {_, TC, _} = Types,
- error_logger:error_msg("========= Orber Typecheck Request =========~n"
- "Invoked......: ~p:~p/~p~n"
- "Typecode.....: ~p~n"
- "Arguments....: ~p~n"
- "Result.......: ~p~n"
- "===========================================~n",
- [Mod, Func, length(TC), TC, Args, {'EXCEPTION', E}]),
- raise(E);
- {'EXIT',R} ->
- {_, TC, _} = Types,
- error_logger:error_msg("========= Orber Typecheck Request =========~n"
- "Invoked......: ~p:~p/~p~n"
- "Typecode.....: ~p~n"
- "Arguments....: ~p~n"
- "Result.......: ~p~n"
- "===========================================~n",
- [Mod, Func, length(TC), TC, Args, {'EXIT',R}]),
- raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE});
- _ ->
- ok
- end.
-
-typecheck_reply(true, Args, Mod, Func) when is_atom(Mod) ->
- case catch Mod:oe_tc(Func) of
- undefined ->
- raise(#'BAD_OPERATION'{minor = (?ORBER_VMCID bor 4),
- completion_status=?COMPLETED_NO});
- {'EXIT', What} ->
- orber:dbg("[~p] corba:typecheck_reply(~p, ~p, ~p);~n"
- "The call-back module does not exist or incorrect"
- " IC-version used.~nReason: ~p",
- [?LINE, Mod, Func, Args, What], ?DEBUG_LEVEL),
- raise(#'TRANSIENT'{minor=(?ORBER_VMCID bor 7),
- completion_status=?COMPLETED_NO});
- Types ->
- typecheck_reply_helper(Types, Args, Mod, Func)
- end;
-typecheck_reply(true, Args, Types, Func) ->
- typecheck_reply_helper(Types, Args, Types, Func);
-typecheck_reply(_, _, _, _) ->
- ok.
-
-typecheck_reply_helper(Types, Args, Mod, Func) ->
- case catch cdr_encode:validate_reply_body(
- #giop_env{version = {1,2}, tc = Types,
- host = orber:host(), iiop_port = orber:iiop_port(),
- iiop_ssl_port = orber:iiop_ssl_port(),
- domain = orber:domain(),
- partial_security = orber:partial_security(),
- flags = orber:get_flags()}, Args) of
- {'tk_except', ExcType, ExcTC, {'EXCEPTION', E}} ->
- {_, TC, _} = Types,
- error_logger:error_msg("========== Orber Typecheck Reply ==========~n"
- "Invoked........: ~p:~p/~p~n"
- "Exception Type.: ~p~n"
- "Typecode.......: ~p~n"
- "Raised.........: ~p~n"
- "Result.........: ~p~n"
- "===========================================~n",
- [Mod, Func, length(TC), ExcType, ExcTC, Args, {'EXCEPTION', E}]),
- raise(E);
- {'EXCEPTION', E} ->
- {RetType, TC, OutParams} = Types,
- error_logger:error_msg("========== Orber Typecheck Reply ==========~n"
- "Invoked......: ~p:~p/~p~n"
- "Typecode.....: ~p~n"
- "Reply........: ~p~n"
- "Result.......: ~p~n"
- "===========================================~n",
- [Mod, Func, length(TC), [RetType | OutParams], Args, {'EXCEPTION', E}]),
- raise(E);
- {'tk_except', ExcType, ExcTC, {'EXIT',R}} ->
- {_, TC, _} = Types,
- error_logger:error_msg("========== Orber Typecheck Reply ==========~n"
- "Invoked........: ~p:~p/~p~n"
- "Exception Type.: ~p~n"
- "Typecode.......: ~p~n"
- "Raised.........: ~p~n"
- "Result.........: ~p~n"
- "===========================================~n",
- [Mod, Func, length(TC), ExcType, ExcTC, Args, {'EXIT',R}]),
- raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE});
- {'EXIT',R} ->
- {RetType, TC, OutParams} = Types,
- error_logger:error_msg("========== Orber Typecheck Reply ==========~n"
- "Invoked........: ~p:~p/~p~n"
- "Typecode.......: ~p~n"
- "Reply..........: ~p~n"
- "Result.........: ~p~n"
- "===========================================~n",
- [Mod, Func, length(TC), [RetType | OutParams], Args, {'EXIT',R}]),
- raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE});
- _ ->
- ok
- end.
-
-call_relay(Pid, Data, Timeout) ->
- case whereis(orber_objkeyserver) of
- undefined ->
- raise(#'TRANSIENT'{minor=(?ORBER_VMCID bor 1), completion_status=?COMPLETED_MAYBE});
- _ ->
- case catch gen_server:call(Pid, Data, Timeout) of
- {'EXCEPTION', E} ->
- raise(E);
- {'EXIT',{timeout, _}} ->
- raise(#'TIMEOUT'{completion_status=?COMPLETED_MAYBE});
- {'EXIT',R} ->
- orber:dbg("[~p] corba:call_internal(~p);~n"
- "call exit(~p).", [?LINE, Data, R], ?DEBUG_LEVEL),
- exit(R);
- Res ->
- Res
- end
- end.
-
-%%-----------------------------------------------------------------
-%% Corba:cast - the function for ONEWAY requests
-%%-----------------------------------------------------------------
-cast(Obj, Func, Args, TypesOrMod) ->
- cast_helper(Obj, Func, Args, TypesOrMod, []).
-
-cast(Obj, Func, Args, TypesOrMod, [{context, Ctx}]) ->
- cast_helper(Obj, Func, Args, TypesOrMod, Ctx).
-
-cast_helper(Obj, Func, Args, TypesOrMod, InCtx) ->
- Ctx = get_implicit_context(InCtx),
- case iop_ior:get_key(Obj) of
- {'internal', Key, _, Flags, Mod} ->
- Pid = orber_objectkeys:get_pid(Key),
- cast_internal(Pid, Obj, Func, Args, TypesOrMod,
- ?ORB_FLAG_TEST(Flags, ?ORB_TYPECHECK),
- ?ORB_FLAG_TEST(Flags, ?ORB_USE_PI), Mod, Ctx);
- {'internal_registered', Key, _, Flags, Mod} ->
- cast_internal(Key, Obj, Func, Args, TypesOrMod,
- ?ORB_FLAG_TEST(Flags, ?ORB_TYPECHECK),
- ?ORB_FLAG_TEST(Flags, ?ORB_USE_PI), Mod, Ctx);
- {'external', Key} when is_atom(TypesOrMod) ->
- case catch TypesOrMod:oe_tc(Func) of
- {'EXIT', What} ->
- orber:dbg("[~p] corba:cast_helper(~p);~n"
- "The call-back module does not exist or incorrect"
- " IC-version used.~nReason: ~p",
- [?LINE, TypesOrMod, What], ?DEBUG_LEVEL),
- raise(#'TRANSIENT'{minor=(?ORBER_VMCID bor 7),
- completion_status=?COMPLETED_NO});
- undefined ->
- raise(#'BAD_OPERATION'{minor = (?ORBER_VMCID bor 4),
- completion_status=?COMPLETED_NO});
- Types ->
- orber_iiop:request(Key, Func, Args, Types, 'false', infinity,
- Obj, Ctx)
- end;
- {'external', Key} ->
- orber_iiop:request(Key, Func, Args, TypesOrMod, 'false', infinity,
- Obj, Ctx)
- end.
-
-cast_internal(Pid, Obj, Func, Args, Types, Check, PI, _Mod, Ctx)
- when is_pid(Pid) andalso node(Pid) == node() ->
- invoke_pi_request(PI, Obj, Ctx, Func, Args),
- typecheck_request(Check, Args, Types, Func),
- catch gen_server:cast(Pid, {Obj, Ctx, Func, Args}),
- ok;
-cast_internal(Pid, Obj, Func, Args, Types, Check, PI, Mod, Ctx) when is_pid(Pid) ->
- invoke_pi_request(PI, Obj, Ctx, Func, Args),
- typecheck_request(Check, Args, Types, Func),
- case catch rpc:call(node(Pid), corba, cast_relay, [Pid, {Obj, Ctx, Func, Args}]) of
- {'EXCEPTION', E} ->
- typecheck_reply(Check, {'EXCEPTION', E}, Mod, Func),
- raise(E);
- {badrpc, {'EXIT', _R}} ->
- raise(#'TRANSIENT'{minor=(?ORBER_VMCID bor 3),
- completion_status=?COMPLETED_MAYBE});
- {badrpc,nodedown} ->
- orber:dbg("[~p] corba:cast_internal(~p, ~p, ~p);~nNode ~p down.",
- [?LINE, Func, Args, Types, node(Pid)], ?DEBUG_LEVEL),
- raise(#'TRANSIENT'{minor=(?ORBER_VMCID bor 2),
- completion_status=?COMPLETED_NO});
- Other ->
- orber:dbg("[~p] corba:cast_internal(~p, ~p, ~p);~n"
- "Communication with node: ~p failed with reason: ~p.",
- [?LINE, Func, Args, Types, node(Pid), Other], ?DEBUG_LEVEL),
- raise(#'TRANSIENT'{minor=(?ORBER_VMCID bor 5),
- completion_status=?COMPLETED_MAYBE})
- end;
-
-%% This case handles if the reference is created as a Pseudo object.
-%% Just call apply/3.
-cast_internal({pseudo, Module}, Obj, Func, Args, Types, Check, PI, _Mod, Ctx) ->
- OldCtx = put(oe_server_in_context, Ctx),
- invoke_pi_request(PI, Obj, Ctx, Func, Args),
- typecheck_request(Check, Args, Types, Func),
- State = binary_to_term(get_subobject_key(Obj)),
- catch apply(Module, Func, [Obj, State|Args]),
- put(oe_server_in_context, OldCtx),
- ok;
-cast_internal(Registered, Obj, Func, Args, Types, Check, PI, _Mod, Ctx) ->
- invoke_pi_request(PI, Obj, Ctx, Func, Args),
- typecheck_request(Check, Args, Types, Func),
- case whereis(Registered) of
- undefined ->
- raise(#'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO});
- P ->
- gen_server:cast(P, {Obj, Ctx, Func, Args})
- end.
-
-cast_relay(Pid, Data) ->
- case whereis(orber_objkeyserver) of
- undefined ->
- raise(#'TRANSIENT'{minor=(?ORBER_VMCID bor 1),
- completion_status=?COMPLETED_NO});
- _ ->
- gen_server:cast(Pid, Data)
- end.
-
-%%-----------------------------------------------------------------
-%% Corba:locate - this function is for the moment just used for tests
-%%-----------------------------------------------------------------
-locate(Obj) ->
- locate(Obj, infinity, []).
-
-locate(Obj, Timeout) ->
- locate(Obj, Timeout, []).
-
-locate(Obj, Timeout, Ctx) ->
- case iop_ior:get_key(Obj) of
- {'external', Key} ->
- orber_iiop:locate(Key, Timeout, Obj, Ctx);
- _ ->
- orber_objectkeys:check(iop_ior:get_objkey(Obj))
- end.
-
-%%-----------------------------------------------------------------
-%% Incomming request from iiop
-%%-----------------------------------------------------------------
-%% Operations which do not allow object invokation.
-request_from_iiop(Obj, '_is_a', [Args], _, _, _) ->
- catch corba_object:is_a(Obj, Args);
-%% First the OMG specified this operation to be '_not_existent' and then
-%% changed it to '_non_existent' without suggesting that both must be supported.
-%% See CORBA2.3.1 page 15-34, Minor revision 2.3.1: October 1999
-request_from_iiop(Obj, '_not_existent', _, _, _, _) ->
- catch corba_object:non_existent(Obj);
-request_from_iiop(Obj, '_non_existent', _, _, _, _) ->
- catch corba_object:non_existent(Obj);
-request_from_iiop(_, '_FT_HB', _, _, _, _) ->
- ok;
-
-%% "Ordinary" operations.
-request_from_iiop({Mod, _, _, _, _, _}, oe_get_interface,
- _, _, _, _ServiceCtx) when is_atom(Mod) ->
- case catch Mod:oe_get_interface() of
- {'EXIT', What} ->
- orber:dbg("[~p] corba:request_from_iiop(~p);~n"
- "The call-back module does not exist or"
- " incorrect IC-version used.~nReason: ~p",
- [?LINE, Mod, What], ?DEBUG_LEVEL),
- {'EXCEPTION', #'TRANSIENT'{minor=(?ORBER_VMCID bor 7),
- completion_status=?COMPLETED_NO}};
- undefined ->
- {'EXCEPTION', #'BAD_OPERATION'{minor = (?ORBER_VMCID bor 4),
- completion_status='COMPLETED_NO'}};
- Interface ->
- Interface
- end;
-request_from_iiop({_Mod, pseudo, Module, _UserDef, _OrberDef, _Flags} = ObjRef,
- Func, Args, Types, ResponseExpected, _ServiceCtx) ->
- State = binary_to_term(get_subobject_key(ObjRef)),
- case ResponseExpected of
- true ->
- case catch apply(Module, Func, [ObjRef, State|Args]) of
- {noreply, _} ->
- ok;
- {noreply, _, _} ->
- ok;
- {reply, Reply, _} ->
- Reply;
- {reply, Reply, _, _} ->
- Reply;
- {stop, _, Reply, _} ->
- Reply;
- {stop, _, _} ->
- ok;
- {'EXCEPTION', E} ->
- {'EXCEPTION', E};
- {'EXIT', {undef, _}} ->
- orber:dbg("[~p] corba:request_from_iiop(~p, ~p, ~p);~n"
- "The call-back module does not exist.",
- [?LINE, Func, Args, Types], ?DEBUG_LEVEL),
- {'EXCEPTION', #'TRANSIENT'{minor=(?ORBER_VMCID bor 4),
- completion_status=?COMPLETED_NO}};
- {'EXIT', What} ->
- orber:dbg("[~p] corba:request_from_iiop(~p, ~p, ~p);~n"
- "Pseudo object exit(~p).~n"
- "The call-back module probably contain an error.",
- [?LINE, Func, Args, Types, What], ?DEBUG_LEVEL),
- {'EXCEPTION', #'TRANSIENT'{minor=(?ORBER_VMCID bor 4),
- completion_status=?COMPLETED_MAYBE}};
- Unknown ->
- orber:dbg("[~p] corba:request_from_iiop(~p, ~p, ~p);~n"
- "Pseudo object failed(~p);~n"
- "Confirm that the return value is correct"
- " (e.g. {reply, Reply, State})",
- [?LINE, Func, Args, Types, Unknown], ?DEBUG_LEVEL),
- {'EXCEPTION', #'TRANSIENT'{minor=(?ORBER_VMCID bor 6),
- completion_status=?COMPLETED_MAYBE}}
- end;
- false ->
- catch apply(Module, Func, [ObjRef, State|Args]),
- ok;
- true_oneway ->
- catch apply(Module, Func, [ObjRef, State|Args]),
- ok
- end;
-% FOR PASSIVE REPLICATION! (Response IS expected --- one way semantics doesn't
-% really mix with intentions to be consistent & fault tolerant.)
-request_from_iiop({_Mod, passive, Module, _UserDef, _OrberDef, _Flags} = ObjRef,
- Func, Args, Types, true, Ctx) ->
- GroupID = binary_to_term(get_subobject_key(ObjRef)),
- FTGroupVersionCtx = get_FTGroupVersionCtx(Ctx),
- Transaction =
- fun() ->
- ObjectGroup = read_object_group(GroupID),
- check_version_context(ObjectGroup,
- FTGroupVersionCtx),
- call_primary_protected(ObjectGroup,
- Module,
- ObjRef,
- Func,
- Args,
- GroupID,
- get_FTRequestCtx(Ctx))
- end,
- case mnesia:transaction(Transaction) of
- {atomic, Reply} ->
- Reply;
- {aborted, {too_old_reference, IOGR}} ->
- {oe_location_forward_perm, IOGR};
- {aborted, {not_primary, _Primary, IOGR}} ->
- case FTGroupVersionCtx of
- [] ->
- {oe_location_forward_perm, IOGR};
- _ ->
- {'EXCEPTION', #'TRANSIENT'{minor = 0,
- completion_status = ?COMPLETED_NO}}
- end;
- {aborted, {throw, {'EXCEPTION', E}}} ->
- {'EXCEPTION', E};
- {aborted, {'EXIT', What}} ->
- orber:dbg("[~p] corba:call_passive(~p, ~p, ~p);~n"
- "Passive object exit(~p).",
- [?LINE, Func, Args, Types, What], ?DEBUG_LEVEL),
- {'EXCEPTION', #'TRANSIENT'{minor = 0,
- completion_status=?COMPLETED_MAYBE}};
- {aborted, Unknown} ->
- orber:dbg("[~p] corba:call_passive(~p, ~p, ~p);~n"
- "Passive object failed due to bad return value (~p).",
- [?LINE, Func, Args, Types, Unknown], ?DEBUG_LEVEL),
- {'EXCEPTION', #'TRANSIENT'{minor = 0,
- completion_status=?COMPLETED_MAYBE}}
- end;
-request_from_iiop({_Mod, _Type, Key, _UserDef, _OrberDef, _Flags} = ObjRef,
- Func, Args, Types, true, _ServiceCtx) ->
- case catch gen_server:call(convert_key_to_pid(Key),
- {ObjRef, [], Func, Args}, infinity) of
- {'EXIT', What} ->
- orber:dbg("[~p] corba:request_from_iiop(~p, ~p, ~p);~n"
- "gen_server:call exit: ~p",
- [?LINE, Func, Args, Types, What], ?DEBUG_LEVEL),
- {'EXCEPTION', #'TRANSIENT'{minor=(?ORBER_VMCID bor 4),
- completion_status=?COMPLETED_MAYBE}};
- Result ->
- Result
- end;
-request_from_iiop({_Mod, _Type, Key, _UserDef, _OrberDef, _Flags} = ObjRef,
- Func, Args, Types, _, _ServiceCtx) ->
- case catch gen_server:cast(convert_key_to_pid(Key),
- {ObjRef, [], Func, Args}) of
- {'EXIT', What} ->
- orber:dbg("[~p] corba:request_from_iiop(~p, ~p, ~p);~n"
- "gen_server:cast exit: ~p",
- [?LINE, Func, Args, Types, What], ?DEBUG_LEVEL),
- {'EXCEPTION', #'TRANSIENT'{minor=(?ORBER_VMCID bor 4),
- completion_status=?COMPLETED_MAYBE}};
- Result ->
- Result
- end.
-
-%%------------------------------------------------------------
-%% Internal stuff
-%%------------------------------------------------------------
-
-convert_key_to_pid(Key) when is_binary(Key) ->
- orber_objectkeys:get_pid(Key);
-convert_key_to_pid(Name) when is_atom(Name) ->
- Name.
-
-mk_objkey(Mod, Pid, RegName, Persistent) ->
- mk_objkey(Mod, Pid, RegName, Persistent, 0).
-
-mk_objkey(Mod, Pid, [], _, Flags) when is_pid(Pid) ->
- Key = make_objkey(),
- case orber_objectkeys:register(Key, Pid, false) of
- ok ->
- {Mod, 'key', Key, term_to_binary(undefined), 0, Flags};
- R ->
- orber:dbg("[~p] corba:mk_objkey(~p);~n"
- "unable to store key(~p).", [?LINE, Mod, R], ?DEBUG_LEVEL),
- raise(#'INTERNAL'{minor=(?ORBER_VMCID bor 2), completion_status=?COMPLETED_NO})
- end;
-mk_objkey(Mod, Pid, {'global', RegName}, Persitent, Flags) when is_pid(Pid) ->
- Key = term_to_binary(RegName),
- case orber_objectkeys:register(Key, Pid, Persitent) of
- ok ->
- {Mod, 'key', Key, term_to_binary(undefined), 0, Flags};
- R ->
- orber:dbg("[~p] corba:mk_objkey(~p, ~p);~n"
- "unable to store key(~p).",
- [?LINE, Mod, RegName, R], ?DEBUG_LEVEL),
- raise(#'INTERNAL'{minor=(?ORBER_VMCID bor 2), completion_status=?COMPLETED_NO})
- end;
-mk_objkey(Mod, Pid, {'local', RegName}, Persistent, Flags) when is_pid(Pid) andalso is_atom(RegName) ->
- register(RegName, Pid),
- Key = make_objkey(),
- case orber_objectkeys:register(Key, Pid, Persistent) of
- ok ->
- {Mod, 'registered', RegName, term_to_binary(undefined), 0, Flags};
- R ->
- orber:dbg("[~p] corba:mk_objkey(~p, ~p);~n"
- "unable to store key(~p).",
- [?LINE, Mod, RegName, R], ?DEBUG_LEVEL),
- raise(#'INTERNAL'{minor=(?ORBER_VMCID bor 2), completion_status=?COMPLETED_NO})
- end.
-
-
-mk_light_objkey(Mod, RegName) ->
- {Mod, 'registered', RegName, term_to_binary(undefined), 0, 0}.
-
-mk_pseudo_objkey(Mod, Module, Flags) ->
- {Mod, 'pseudo', Module, term_to_binary(undefined), 0, Flags}.
-
-mk_passive_objkey(Mod, Module, Flags) ->
- {Mod, 'passive', Module, term_to_binary(undefined), 0, Flags}.
-
-make_objkey() ->
- term_to_binary({{erlang:system_time(),
- erlang:unique_integer()},
- node()}).
-
-objkey_to_string({_Mod, 'registered', 'orber_init', _UserDef, _OrberDef, _Flags}) ->
- "INIT";
-objkey_to_string({Mod, Type, Key, UserDef, OrberDef, Flags}) ->
- orber:domain() ++ [ 7 | binary_to_list(term_to_binary({Mod, Type, Key, UserDef, OrberDef, Flags}))];
-objkey_to_string(External_object_key) ->
- External_object_key.
-
-string_to_objkey("INIT") ->
- {orber_initial_references, 'registered', 'orber_init', term_to_binary(undefined), 0, 0};
-string_to_objkey(String) ->
- case prefix(orber:domain(), String) of
- [7 | Rest] ->
- binary_to_term(list_to_binary(Rest));
- _ ->
- String
- end.
-%% This function may only be used when we know it's a local reference (i.e. target
-%% key in a request; IOR's passed as argument or reply doesn't qualify)!
-string_to_objkey_local("INIT") ->
- {orber_initial_references, 'registered', 'orber_init', term_to_binary(undefined), 0, 0};
-string_to_objkey_local(String) ->
- case prefix(orber:domain(), String) of
- [7 | Rest] ->
- binary_to_term(list_to_binary(Rest));
- _ ->
- case resolve_initial_references(String) of
- ?ORBER_NIL_OBJREF ->
- orber:dbg("[~p] corba:string_to_objkey_local(~p);~n"
- "Invalid ObjektKey.", [?LINE, String], ?DEBUG_LEVEL),
- ?ORBER_NIL_OBJREF;
- Object ->
- {location_forward, Object}
- end
- end.
-
-prefix([], L2) ->
- L2;
-prefix([E |L1], [E | L2]) ->
- prefix(L1, L2);
-prefix(_, _) ->
- false.
-
-
-evaluate_options([], Options) ->
- GlobalFlags = orber:get_flags(),
- Options2 = check_flag(Options, ?ORB_TYPECHECK,
- ?ORB_ENV_LOCAL_TYPECHECKING, GlobalFlags),
- Options3 = check_flag(Options2, ?ORB_USE_PI, ?ORB_ENV_USE_PI, GlobalFlags),
- check_flag(Options3, ?ORB_SURVIVE_EXIT, ?ORB_ENV_SURVIVE_EXIT, GlobalFlags);
-%% Pseudo or not.
-evaluate_options([{pseudo, false}|Rest], Options) ->
- evaluate_options(Rest, Options);
-evaluate_options([{pseudo, true}|Rest], #options{passive = false} = Options) ->
- evaluate_options(Rest, Options#options{pseudo = true});
-%% FT stuff
-evaluate_options([{passive, true}|Rest], #options{pseudo = false} = Options) ->
- evaluate_options(Rest, Options#options{passive = true});
-evaluate_options([{group_id, ID}|Rest], Options) when is_integer(ID) ->
- evaluate_options(Rest, Options#options{group_id = ID});
-%% Options accepted by gen_server (e.g. dbg).
-evaluate_options([{create_options, COpt}|Rest], Options) when is_list(COpt) ->
- evaluate_options(Rest, Options#options{create_options = COpt});
-%% When starting object as supervisor child.
-evaluate_options([{sup_child, false}|Rest], Options) ->
- evaluate_options(Rest, Options);
-evaluate_options([{sup_child, true}|Rest], Options) ->
- evaluate_options(Rest, Options#options{sup_child = true});
-%% Persistent object-key
-evaluate_options([{persistent, false}|Rest], Options) ->
- evaluate_options(Rest, Options);
-evaluate_options([{persistent, true}|Rest], Options) ->
- evaluate_options(Rest, Options#options{persistent = true});
-evaluate_options([{regname, []}|Rest], Options) ->
- evaluate_options(Rest, Options);
-evaluate_options([{regname, Name}|Rest], Options) ->
- evaluate_options(Rest, Options#options{regname = Name});
-evaluate_options([{survive_exit, false}|Rest],
- #options{object_flags_set = FlagsSet} = Options) ->
- %% This option overrides a global setting.
- evaluate_options(Rest, Options#options{object_flags_set =
- (?ORB_SURVIVE_EXIT bor FlagsSet)});
-evaluate_options([{survive_exit, true}|Rest],
- #options{object_flags = Flags,
- object_flags_set = FlagsSet} = Options) ->
- evaluate_options(Rest, Options#options{object_flags =
- (?ORB_SURVIVE_EXIT bor Flags),
- object_flags_set =
- (?ORB_SURVIVE_EXIT bor FlagsSet)});
-evaluate_options([{local_typecheck, false}|Rest],
- #options{object_flags_set = FlagsSet} = Options) ->
- %% This option overrides a global setting.
- evaluate_options(Rest, Options#options{object_flags_set =
- (?ORB_TYPECHECK bor FlagsSet)});
-evaluate_options([{local_typecheck, true}|Rest],
- #options{object_flags = Flags,
- object_flags_set = FlagsSet} = Options) ->
- evaluate_options(Rest, Options#options{object_flags = (?ORB_TYPECHECK bor Flags),
- object_flags_set =
- (?ORB_TYPECHECK bor FlagsSet)});
-evaluate_options([{local_interceptors, false}|Rest],
- #options{object_flags_set = FlagsSet} = Options) ->
- %% This option overrides a global setting.
- evaluate_options(Rest, Options#options{object_flags_set =
- (?ORB_USE_PI bor FlagsSet)});
-evaluate_options([{local_interceptors, true}|Rest],
- #options{object_flags = Flags,
- object_flags_set = FlagsSet} = Options) ->
- evaluate_options(Rest, Options#options{object_flags = (?ORB_USE_PI bor Flags),
- object_flags_set =
- (?ORB_USE_PI bor FlagsSet)});
-%% Temporary option.
-evaluate_options([{no_security, true}|Rest],
- #options{object_flags = Flags} = Options) ->
- %% We do not allow this option to be set globally.
- evaluate_options(Rest, Options#options{object_flags = (?ORB_NO_SECURITY bor Flags)});
-evaluate_options([{no_security, false}|Rest], Options) ->
- %% We do not allow this option to be set globally.
- evaluate_options(Rest, Options);
-evaluate_options([{Key, Value}|_], _) ->
- orber:dbg("[~p] corba:evaluate_options(~p, ~p);~n"
- "Option not recognized, illegal value or combination.~n"
- "Allowed settings:~n"
- "survive_exit.......: boolean()~n"
- "sup_child..........: boolean()~n"
- "persistent.........: boolean()~n"
- "pseudo.............: boolean()~n"
- "local_typecheck....: boolean()~n"
- "local_interceptors.: boolean()~n"
- "regname............: {local, atom()} | {global, term()}",
- [?LINE, Key, Value], ?DEBUG_LEVEL),
- raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-check_flag(#options{object_flags = Flags,
- object_flags_set = FlagsSet} = Options, Flag,
- FlagConstant, GlobalFlags) ->
- %% Option activated/deactived by a supplied option.
- case ?ORB_FLAG_TEST(FlagsSet, Flag) of
- true ->
- Options;
- false ->
- %% Not the above. Globally defined?
- case ?ORB_FLAG_TEST(GlobalFlags, FlagConstant) of
- true ->
- Options#options{object_flags = (Flag bor Flags)};
- false ->
- Options
- end
- end.
-
-%%%%%%%%%%%%%%%%% FOR PASSIVE REPLICATION!
-% Note should be called inside transaction. Does not catch exceptions.
-% let's not allow corba:reply from transaction... (no {noreply, ...} messages)
-% should the object be able to stop itself by returning {stop, ...}?
-% how about corba:dispose then? Deleting table representing object group and
-% corresponding entry in ft_replication_manager -table might just do the job?
-% No {stop, ...} messages for now
-% Exceptions falls through. They are expected to be caught by transaction in a
-% form of {aborted, {throw, {'EXCEPTION', ...}}}
-call_passive(Module, Obj, Func, Args, GroupID) ->
- [Record] = mnesia:read(ft_replicated_object, GroupID, sticky_write),
- State = Record#ft_replicated_object.state,
-
- case apply(Module, Func, [Obj, State|Args]) of
- {reply, Reply, NewState} ->
- {Reply, NewState};
- {reply, Reply, NewState, _} ->
- {Reply, NewState}
- end,
- mnesia:write(ft_replicated_object,
- #ft_replicated_object{group_id = GroupID, state = NewState},
- sticky_write),
- Reply.
-
-
-
-% FTRequestCtx protected object call
-% One should protect agains aged reply. If expirations_time is reached and
-% request is retransmitted, one might return BAD_CONTEXT -exception!
-call_RQprotected(Module, Obj, Func, Args, GroupID, RQCtx) ->
- case mnesia:read(ft_reply_retention, RQCtx, sticky_write) of
- % fresh request
- [] ->
- Reply = call_passive(Module, Obj, Func, Args, GroupID),
- mnesia:write(ft_reply_retention,
- #ft_reply_retention{retention_id= RQCtx,reply= Reply},
- sticky_write),
- Reply;
- % retransmitted request
- [#ft_reply_retention{reply = Reply}] ->
- Reply
- end.
-
-
-
-% call_primary_protected. Protects agains calling non-primary node.
-% normal case, without FTRequest Service Context
-call_primary_protected(#ft_replication_manager{primary = Primary},
- Module,
- Obj,
- Func,
- Args,
- GroupID,
- []) when Primary == node() ->
- call_passive(Module, Obj, Func, Args, GroupID);
-% normal case, with FTRequest Service Context
-call_primary_protected(#ft_replication_manager{primary = Primary},
- Module,
- Obj,
- Func,
- Args,
- GroupID,
- RetentionID) when Primary == node() ->
- call_RQprotected(Module, Obj, Func, Args, GroupID, RetentionID);
-% case where primary resides in another node
-call_primary_protected(#ft_replication_manager{primary = Primary,
- iogr = IOGR},
- _Module, _Obj, _Func, _Args, _GroupID, _) ->
- mnesia:abort({not_primary, Primary, IOGR}).
-
-
-
-% no context
-check_version_context(_, []) ->
- ok;
-% client's IOGR is current.
-check_version_context(#ft_replication_manager{ref_version = CurrentVer},
- GroupVer) when CurrentVer == GroupVer ->
- ok;
-% client's IOGR is old.
-check_version_context(#ft_replication_manager{ref_version = CurrentVer,
- iogr = IOGR},
- GroupVer) when CurrentVer > GroupVer ->
- mnesia:abort({too_old_reference, IOGR});
-% client's IOGR is too new!
-check_version_context(#ft_replication_manager{ref_version = CurrentVer},
- GroupVer) when CurrentVer < GroupVer ->
- raise(#'INV_OBJREF'{completion_status = ?COMPLETED_NO}).
-
-
-
-read_object_group(GroupID) ->
- case mnesia:read({ft_replication_manager, GroupID}) of
- [] ->
- raise(#'OBJECT_NOT_EXIST'{completion_status = ?COMPLETED_NO});
- [ObjectGroup] ->
- ObjectGroup
- end.
-
-
-
-mk_FTRequestCtx(Expiration_time) ->
- #'FT_FTRequestServiceContext'{
- client_id = atom_to_list(node()),
- retention_id = orber_request_number:get(),
- expiration_time = Expiration_time}.
-
-
-
-get_FTRequestCtx([#'FT_FTRequestServiceContext'
- {client_id = Client_ID, retention_id = Retention_ID,
- expiration_time = Expiration_time}|_Ctxs]) ->
- {Client_ID, Retention_ID, Expiration_time};
-get_FTRequestCtx([]) ->
- [];
-get_FTRequestCtx([_Ctx|Ctxs]) ->
- get_FTRequestCtx(Ctxs).
-
-
-
-get_FTGroupVersionCtx([#'FT_FTGroupVersionServiceContext'
- {object_group_ref_version = Version}|_Ctxs]) ->
- Version;
-get_FTGroupVersionCtx([]) ->
- [];
-get_FTGroupVersionCtx([_Ctx|Ctxs]) ->
- get_FTGroupVersionCtx(Ctxs).
-
diff --git a/lib/orber/src/corba_boa.erl b/lib/orber/src/corba_boa.erl
deleted file mode 100644
index 12b063a5db..0000000000
--- a/lib/orber/src/corba_boa.erl
+++ /dev/null
@@ -1,135 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: corba_boa.erl
-%%
-%% Description:
-%% This file contains the CORBA::BOA interface
-%%
-%%-----------------------------------------------------------------
--module(corba_boa).
-
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([%create/3,
- dispose/1,
- get_id/1]).
-% change_implementation/2,
-% set_exception/3,
-% impl_is_ready/1,
-% deactivate_impl/1,
-% obj_is_ready/2,
-% deactivate_obj/1,
-% get_principal/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
--define(DEBUG_LEVEL, 5).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-%create(Id, Interface, Implementation) ->
-% corba:create(Implementation#orb_ImplDef.module,
-% Interface#fullinterfacedescription.id).
-
-dispose(Object) ->
- case binary_to_term(iop_ior:get_privfield(Object)) of
- undefined ->
- case catch iop_ior:get_key(Object) of
- {'internal', Key, _, _, _} ->
- case orber_objectkeys:get_pid(Key) of
- {error, Reason} ->
- orber:dbg("[~p] corba_boa:dispose(~p); object not found(~p)",
- [?LINE, Object, Reason], ?DEBUG_LEVEL),
- corba:raise(#'TRANSIENT'{completion_status=?COMPLETED_NO});
- Pid ->
- gen_server:call(Pid, stop)
- end;
- {'internal_registered', Key, _, _, _} ->
- case Key of
- {pseudo, Module} ->
- Module:terminate(normal, undefined),
- ok;
- _ ->
- case whereis(Key) of
- undefined ->
- corba:raise(#'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO});
- Pid ->
- gen_server:call(Pid, stop)
- end
- end;
- {'external', _} ->
- orber:dbg("[~p] corba_boa:dispose(~p); external object.",
- [?LINE, Object], ?DEBUG_LEVEL),
- %% Must be fixed !!!!!!!!
- corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO})
- end;
- Other ->
- case iop_ior:get_key(Object) of
- {_, {pseudo, Module}, _, _, _} ->
- Module:terminate(normal, Other),
- ok;
- Why ->
- orber:dbg("[~p] corba_boa:dispose(~p); probably subobject key set(~p)",
- [?LINE, Object, Why], ?DEBUG_LEVEL),
- corba:raise(#'NO_PERMISSION'{completion_status=?COMPLETED_NO})
- end
- end.
-
-get_id(Object) ->
- iop_ior:get_objkey(Object).
-
-%change_implementation(Object, ImplementationDef) ->
-% ok.
-
-%get_principal(Object, Env) ->
-% ok.
-
-%set_exception(Major, Id, Param) ->
-% ok.
-
-%impl_is_ready(ImplementationDef) ->
-% ok.
-
-%deactivate_impl(ImplementationDef) ->
-% ok.
-
-%obj_is_ready(Object, ImplementationDef) ->
-% ok.
-
-%deactivate_obj(Object) ->
-% ok.
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
diff --git a/lib/orber/src/corba_nvlist.erl b/lib/orber/src/corba_nvlist.erl
deleted file mode 100644
index 4a1361842b..0000000000
--- a/lib/orber/src/corba_nvlist.erl
+++ /dev/null
@@ -1,98 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: corba_nvlist.erl
-%% Description:
-%% This file contains the CORBA::NVList handling
-%%
-%%-----------------------------------------------------------------
--module(corba_nvlist).
-
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
-%%-----------------------------------------------------------------
-%% Standard interface CORBA::NVList
-%%-----------------------------------------------------------------
--export([add_item/6,
- free/1,
- free_memory/1,
- get_count/1]).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([create_list/1,
- create_operation_list/1]).
-
-%%------------------------------------------------------------
-%% Implementation of standard interface CORBA::NVList
-%%------------------------------------------------------------
-add_item(List, Id, TC, Value, Len, ArgFlags) ->
- {ok, List}.
-
-free(List) ->
- ok.
-
-free_memory(List) ->
- ok.
-
-get_count(List) ->
- {ok, 0}.
-
-%%------------------------------------------------------------
-%% Implementation of extra functions which creates NVList:s
-%% theese ae used by the standard functions with the same name
-%% in the CORBA::ORB interface
-%%------------------------------------------------------------
-
-create_list(Count) ->
- {ok, create_list_2(Count, [])}.
-
-create_list_2(0, Acc) ->
- Acc;
-create_list_2(N, Acc) ->
- create_list_2(N-1, [[] | Acc]).
-
-create_operation_list(OpDef) ->
- OpArgList = OpDef,
- {ok, create_operation_list_2(OpArgList, [])}.
-
-create_operation_list_2([], Acc) ->
- Acc;
-create_operation_list_2([OpArg | OpArgList], Acc) ->
- Rec = parse_oparg_def(OpArg),
- create_operation_list_2(OpArgList, [Rec | Acc]).
-
-parse_oparg_def(OpArg) ->
- OpArg.
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/orber/src/corba_object.erl b/lib/orber/src/corba_object.erl
deleted file mode 100644
index bf31226067..0000000000
--- a/lib/orber/src/corba_object.erl
+++ /dev/null
@@ -1,221 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: corba_object.erl
-%%
-%% Description:
-%% This file contains the CORBA::Object interface
-%%
-%%-----------------------------------------------------------------
--module(corba_object).
-
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/src/ifr_objects.hrl").
-
-%%-----------------------------------------------------------------
-%% Standard interface CORBA::Object
-%%-----------------------------------------------------------------
--export([get_interface/1,
- is_nil/1,
- is_a/2,
- is_a/3,
- is_remote/1,
- non_existent/1,
- non_existent/2,
- not_existent/1,
- not_existent/2,
- is_equivalent/2,
- hash/2,
- create_request/6]).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
--define(DEBUG_LEVEL, 5).
-
-%%------------------------------------------------------------
-%% Implementation of standard interface
-%%------------------------------------------------------------
-get_interface(Obj) ->
- case orber_env:light_ifr() of
- false ->
- TypeId = iop_ior:get_typeID(Obj),
- case mnesia:dirty_index_read(ir_InterfaceDef, TypeId, #ir_InterfaceDef.id) of
- %% If all we get is an empty list there are no such
- %% object registered in the IFR.
- [] ->
- orber:dbg("[~p] corba_object:get_interface(~p); TypeID ~p not found in IFR.",
- [?LINE, Obj, TypeId], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO});
- [#ir_InterfaceDef{ir_Internal_ID=Ref}] ->
- orber_ifr_interfacedef:describe_interface({ir_InterfaceDef, Ref})
- end;
- true ->
- case catch iop_ior:get_key(Obj) of
- {'external', _Key} ->
- orber:dbg("[~p] corba_object:get_interface(~p); Invalid object reference.",
- [?LINE, Obj], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO});
- {_Local, _Key, _, _, Module} ->
- case catch Module:oe_get_interface() of
- {'EXIT', What} ->
- orber:dbg("[~p] corba_object:get_interface(~p);~n"
- "The call-back module does not exist or incorrect IC-version used.~n"
- "Reason: ~p", [?LINE, Module, What], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO});
- InterfaceDesc ->
- InterfaceDesc
- end
- end
- end.
-
-
-is_nil(Object) when is_record(Object, 'IOP_IOR') ->
- iop_ior:check_nil(Object);
-is_nil({I,T,K,P,O,F}) ->
- iop_ior:check_nil({I,T,K,P,O,F});
-is_nil(Obj) ->
- orber:dbg("[~p] corba_object:is_nil(~p); Invalid object reference.",
- [?LINE, Obj], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO}).
-
-is_a(Obj, Logical_type_id) ->
- is_a(Obj, Logical_type_id, []).
-
-is_a(?ORBER_NIL_OBJREF, _, _Ctx) ->
- false;
-is_a(#'IOP_IOR'{type_id = Logical_type_id}, Logical_type_id, _Ctx) ->
- true;
-is_a(Obj, Logical_type_id, Ctx) when is_list(Ctx) ->
- case catch iop_ior:get_key(Obj) of
- {'external', Key} ->
- orber_iiop:request(Key, '_is_a', [Logical_type_id],
- {orber_tc:boolean(),[orber_tc:string(0)],[]},
- true, infinity, Obj, corba:get_implicit_context(Ctx));
- {_Local, _Key, _, _, Module} ->
- case catch Module:oe_is_a(Logical_type_id) of
- {'EXIT', What} ->
- orber:dbg("[~p] corba_object:is_a(~p);~n"
- "The call-back module does not exist or incorrect IC-version used.~n"
- "Reason: ~p", [?LINE, Module, What], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO});
- Boolean ->
- Boolean
- end;
- _ ->
- orber:dbg("[~p] corba_object:is_a(~p, ~p); Invalid object reference.",
- [?LINE, Obj, Logical_type_id], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO})
- end;
-is_a(Obj, Logical_type_id, Ctx) ->
- orber:dbg("[~p] corba_object:is_a(~p, ~p, ~p);~n"
- "Failed to supply a context list.",
- [?LINE, Obj, Logical_type_id, Ctx], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-
-non_existent(Obj) ->
- non_existent(Obj, []).
-
-non_existent(?ORBER_NIL_OBJREF, _Ctx) ->
- true;
-non_existent(Obj, Ctx) ->
- existent_helper(Obj, '_non_existent', Ctx).
-
-not_existent(Obj) ->
- not_existent(Obj, []).
-
-not_existent(?ORBER_NIL_OBJREF, _Ctx) ->
- true;
-not_existent(Obj, Ctx) ->
- existent_helper(Obj, '_not_existent', Ctx).
-
-
-existent_helper(Obj, Op, Ctx) when is_list(Ctx) ->
- case catch iop_ior:get_key(Obj) of
- {'internal', Key, _, _, _} ->
- case catch orber_objectkeys:get_pid(Key) of
- {'EXCEPTION', E} when is_record(E,'OBJECT_NOT_EXIST') ->
- true;
- {'EXCEPTION', X} ->
- corba:raise(X);
- {'EXIT', R} ->
- orber:dbg("[~p] corba_object:non_existent(~p); exit(~p).",
- [?LINE, Obj, R], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO});
- _ ->
- false
- end;
- {'internal_registered', Key, _, _, _} ->
- case Key of
- {pseudo, _} ->
- false;
- _->
- case whereis(Key) of
- undefined ->
- true;
- _P ->
- false
- end
- end;
- {'external', Key} ->
- orber_iiop:request(Key, Op, [],
- {orber_tc:boolean(), [],[]}, 'true',
- infinity, Obj, corba:get_implicit_context(Ctx));
- true ->
- false
- end;
-existent_helper(Obj, Op, Ctx) ->
- orber:dbg("[~p] corba_object:existent_helper(~p, ~p, ~p);~n"
- "Failed to supply a context list.",
- [?LINE, Obj, Op, Ctx], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-
-is_remote(Obj) ->
- case catch iop_ior:get_key(Obj) of
- {'external', _} ->
- true;
- _ ->
- false
- end.
-
-
-is_equivalent(Obj, Obj) ->
- true;
-is_equivalent({I,T,K,P,_,_}, {I,T,K,P,_,_}) ->
- true;
-is_equivalent(_, _) ->
- false.
-
-hash(Obj, Maximum) ->
- erlang:phash(iop_ior:get_key(Obj), Maximum).
-
-
-create_request(_Obj, _Ctx, _Op, _ArgList, NamedValueResult, _ReqFlags) ->
- {ok, NamedValueResult, []}.
diff --git a/lib/orber/src/fixed.erl b/lib/orber/src/fixed.erl
deleted file mode 100644
index 8d6239991d..0000000000
--- a/lib/orber/src/fixed.erl
+++ /dev/null
@@ -1,306 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%--------------------------------------------------------------------
-%% File : fixed.erl
-%% Purpose :
-%%--------------------------------------------------------------------
-
--module(fixed).
-
--include_lib("orber/include/corba.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([create/3, add/2, subtract/2, divide/2, multiply/2, unary_minus/1,
- get_typecode/1]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% Definitions
-%%-----------------------------------------------------------------
--define(get_max(__X, __Y), if __X > __Y -> __X; true -> __Y end).
--define(get_min(__X, __Y), if __X > __Y -> __Y; true -> __X end).
-
--define(BASE, 100000000000000000000000000000000).
--define(FIXED_MAX, 9999999999999999999999999999999).
--define(FIXED_MIN, -9999999999999999999999999999999).
-
--define(DEBUG_LEVEL, 5).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-create(Digits, Scale, Value) when is_integer(Digits) andalso Digits >= 0 andalso Digits < 32 andalso
- is_integer(Scale) andalso Scale >= 0 andalso Digits >= Scale andalso
- is_integer(Value) andalso Value =< ?FIXED_MAX andalso
- Value >= ?FIXED_MIN ->
- case count_digits(abs(Value)) of
- Dig when Dig =< Digits ->
- #fixed{digits = Digits, scale = Scale, value = Value};
- Overflow ->
- orber:dbg("[~p] fixed:create(~p, ~p, ~p).~n"
- "The Value exceeds the Digits limit: ~p, ~p",
- [?LINE, Digits, Scale, Value, Digits, Overflow], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end;
-create(Digits, Scale, Value) ->
- orber:dbg("[~p] fixed:add(~p, ~p, ~p).~n"
- "At least one of the supplied arguments is incorrect.~n"
- "Digits and Scale must be a positive integer with the following~n"
- "limits:~n"
- " * 0 =< Digits < 32~n"
- " * Digits >= Scale~n"
- " * Value range +/- 9999999999999999999999999999999",
- [?LINE, Digits, Scale, Value], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-
-get_typecode(#fixed{digits = Digits, scale = Scale}) ->
- {tk_fixed, Digits, Scale};
-get_typecode(Other) ->
- orber:dbg("[~p] fixed:get_typecode(~p).
-The supplied argument is not a Fixed Type.", [?LINE, Other], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-add(#fixed{digits = D1, scale = S1, value = V1},
- #fixed{digits = D2, scale = S2, value = V2}) ->
- Scale = ?get_max(S1, S2),
- Digits = ?get_max((D1-S1), (D2-S2)) + Scale +1,
- %% We must normalize the values before adding. Why?
- %% 4.23 and 5.2 are represented as 423 and 52. To be able to get the
- %% correct result we must add 4230 and 5200 == 9430.
- {PV1, PV2} = normalize(S1, V1, S2, V2),
- check_fixed_overflow(#fixed{digits = Digits,
- scale = Scale,
- value = (PV1 + PV2)});
-add(F1, F2) ->
- orber:dbg("[~p] fixed:add(~p, ~p).~n"
- "At least one of the supplied arguments is not a Fixed Type.",
- [?LINE, F1, F2], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-
-subtract(#fixed{digits = D1, scale = S1, value = V1},
- #fixed{digits = D2, scale = S2, value = V2}) ->
- Scale = ?get_max(S1, S2),
- Digits = ?get_max((D1-S1), (D2-S2)) + Scale +1,
- {PV1, PV2} = normalize(S1, V1, S2, V2),
- check_fixed_overflow(#fixed{digits = Digits,
- scale = Scale,
- value = (PV1 - PV2)});
-subtract(F1, F2) ->
- orber:dbg("[~p] fixed:subtract(~p, ~p).~n"
- "At least one of the supplied arguments is not a Fixed Type.",
- [?LINE, F1, F2], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-divide(#fixed{digits = D1, scale = S1, value = V1},
- #fixed{digits = _D2, scale = S2, value = V2}) ->
- {PV1, PV2} = normalize(S1, V1, S2, V2),
- DigitsMin = (D1-S1+S2),
- R1 = (PV1 div PV2),
- R2 = (R1*?BASE + (PV1 rem PV2) * (?BASE div PV2)),
- {Result2, Sinf} = delete_zeros_value(R2, 0, R1),
- check_fixed_overflow(#fixed{digits = DigitsMin + Sinf, scale = Sinf,
- value = Result2});
-divide(F1, F2) ->
- orber:dbg("[~p] fixed:divide(~p, ~p).~n"
- "At least one of the supplied arguments is not a Fixed Type.",
- [?LINE, F1, F2], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-
-multiply(#fixed{digits = D1, scale = S1, value = V1},
- #fixed{digits = D2, scale = S2, value = V2}) ->
- check_fixed_overflow(#fixed{digits = (D1+D2),
- scale = (S1+S2),
- value = V1*V2});
-multiply(F1, F2) ->
- orber:dbg("[~p] fixed:multiply(~p, ~p).~n"
- "At least one of the supplied arguments is not a Fixed Type.",
- [?LINE, F1, F2], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-unary_minus(Fixed) when is_record(Fixed, fixed) ->
- Fixed#fixed{value = -(Fixed#fixed.value)};
-unary_minus(Fixed) ->
- orber:dbg("[~p] fixed:unary_minus(~p).~n"
- "The supplied argument is not a Fixed Type.",
- [?LINE, Fixed], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-%% Pretty?! No, but since we now the upper-limit this is the fastest way
-%% to calculate 10^x
-power(0) -> 1;
-power(1) -> 10;
-power(2) -> 100;
-power(3) -> 1000;
-power(4) -> 10000;
-power(5) -> 100000;
-power(6) -> 1000000;
-power(7) -> 10000000;
-power(8) -> 100000000;
-power(9) -> 1000000000;
-power(10) -> 10000000000;
-power(11) -> 100000000000;
-power(12) -> 1000000000000;
-power(13) -> 10000000000000;
-power(14) -> 100000000000000;
-power(15) -> 1000000000000000;
-power(16) -> 10000000000000000;
-power(17) -> 100000000000000000;
-power(18) -> 1000000000000000000;
-power(19) -> 10000000000000000000;
-power(20) -> 100000000000000000000;
-power(21) -> 1000000000000000000000;
-power(22) -> 10000000000000000000000;
-power(23) -> 100000000000000000000000;
-power(24) -> 1000000000000000000000000;
-power(25) -> 10000000000000000000000000;
-power(26) -> 100000000000000000000000000;
-power(27) -> 1000000000000000000000000000;
-power(28) -> 10000000000000000000000000000;
-power(29) -> 100000000000000000000000000000;
-power(30) -> 1000000000000000000000000000000;
-power(31) -> 10000000000000000000000000000000;
-power(_) -> 10000000000000000000000000000000.
-
-
-
-%% If the result of an operation (+, -, * or /) causes overflow we use this
-%% operation. However, since these calculations are performed during compiletime,
-%% shouldn't the IDL-specification be changed to not cause overflow?! But, since
-%% the OMG standard allows this we must support it.
-check_fixed_overflow(#fixed{digits = Digits, scale = Scale, value = Value}) ->
- case count_digits(abs(Value)) of
- overflow ->
- {N, NewVal} = cut_overflow(0, Value),
- if
- N > Scale ->
- #fixed{digits = 31, scale = 0, value = NewVal};
- true ->
- NewScale = Scale - N,
- {NewVal2, Removed} = delete_zeros(NewVal, NewScale),
- #fixed{digits = 31, scale = NewScale-Removed, value = NewVal2}
- end;
- Count when Count > Digits ->
- Diff = Count-Digits,
- if
- Diff > Scale ->
- #fixed{digits = Digits, scale = 0,
- value = (Value div power(Diff))};
- true ->
- NewScale = Scale-Diff,
- {NewVal, Removed} = delete_zeros((Value div power(Diff)), NewScale),
- #fixed{digits = Digits-Removed,
- scale = NewScale-Removed,
- value = NewVal}
- end;
- Count ->
- {NewVal, Removed} = delete_zeros(Value, Scale),
- #fixed{digits = Count-Removed, scale = Scale-Removed, value = NewVal}
- end.
-
-%% This function see to that the values are of the same baase.
-normalize(S, V1, S, V2) ->
- {V1, V2};
-normalize(S1, V1, S2, V2) when S1 > S2 ->
- {V1, V2*power(S1-S2)};
-normalize(S1, V1, S2, V2) ->
- {V1*power(S2-S1), V2}.
-
-%% If we have access to the integer part of the fixed type we use this
-%% operation to remove all trailing zeros. If we know the scale, length of
-%% fraction part, we can use delete_zeros as well. But, after a division
-%% it's hard to know the scale and we don't need to calcluate the integer part.
-delete_zeros_value(0, N, _) ->
- {0, 32-N};
-delete_zeros_value(X, N, M) when X > M, (X rem 10) == 0 ->
- delete_zeros_value((X div 10), N+1, M);
-delete_zeros_value(X, N, _) ->
- {X, 32-N}.
-
-%% If we know the exact scale of a fixed type we can use this operation to
-%% remove all trailing zeros.
-delete_zeros(0, _) ->
- {0,0};
-delete_zeros(X, Max) ->
- delete_zeros(X, 0, Max).
-delete_zeros(X, Max, Max) ->
- {X, Max};
-delete_zeros(X, N, Max) when (X rem 10) == 0 ->
- delete_zeros((X div 10), N+1, Max);
-delete_zeros(X, N, _) ->
- {X, N}.
-
-cut_overflow(N, X) when X > ?FIXED_MAX ->
- cut_overflow(N+1, (X div 10));
-cut_overflow(N, X) ->
- {N, X}.
-
-%% A fast way to check the size of a fixed data type.
-count_digits(X) when X > ?FIXED_MAX -> overflow;
-count_digits(X) when X >= 1000000000000000000000000000000 -> 31;
-count_digits(X) when X >= 100000000000000000000000000000 -> 30;
-count_digits(X) when X >= 10000000000000000000000000000 -> 29;
-count_digits(X) when X >= 1000000000000000000000000000 -> 28;
-count_digits(X) when X >= 100000000000000000000000000 -> 27;
-count_digits(X) when X >= 10000000000000000000000000 -> 26;
-count_digits(X) when X >= 1000000000000000000000000 -> 25;
-count_digits(X) when X >= 100000000000000000000000 -> 24;
-count_digits(X) when X >= 10000000000000000000000 -> 23;
-count_digits(X) when X >= 1000000000000000000000 -> 22;
-count_digits(X) when X >= 100000000000000000000 -> 21;
-count_digits(X) when X >= 10000000000000000000 -> 20;
-count_digits(X) when X >= 1000000000000000000 -> 19;
-count_digits(X) when X >= 100000000000000000 -> 18;
-count_digits(X) when X >= 10000000000000000 -> 17;
-count_digits(X) when X >= 1000000000000000 -> 16;
-count_digits(X) when X >= 100000000000000 -> 15;
-count_digits(X) when X >= 10000000000000 -> 14;
-count_digits(X) when X >= 1000000000000 -> 13;
-count_digits(X) when X >= 100000000000 -> 12;
-count_digits(X) when X >= 10000000000 -> 11;
-count_digits(X) when X >= 1000000000 -> 10;
-count_digits(X) when X >= 100000000 -> 9;
-count_digits(X) when X >= 10000000 -> 8;
-count_digits(X) when X >= 1000000 -> 7;
-count_digits(X) when X >= 100000 -> 6;
-count_digits(X) when X >= 10000 -> 5;
-count_digits(X) when X >= 1000 -> 4;
-count_digits(X) when X >= 100 -> 3;
-count_digits(X) when X >= 10 -> 2;
-count_digits(_X) -> 1.
-
-%%-----------------------------------------------------------------
-%%------------- END OF MODULE -------------------------------------
-%%-----------------------------------------------------------------
diff --git a/lib/orber/src/ifr_objects.hrl b/lib/orber/src/ifr_objects.hrl
deleted file mode 100644
index 3feedbc652..0000000000
--- a/lib/orber/src/ifr_objects.hrl
+++ /dev/null
@@ -1,422 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%%----------------------------------------------------------------------
-%%% File : ir_objects.hrl
-%%% Purpose : Record definitions for the IR DB
-%%%----------------------------------------------------------------------
-
-%%%----------------------------------------------------------------------
-%%% *********************************************************************
-%%% * *
-%%% * PLEASE NOTE *
-%%% * *
-%%% * If a record is removed or added in this file, the corresponding *
-%%% * database initialization code _MUST_ be updated accordingly. *
-%%% * *
-%%% * The initialization code is defined in a macro in this file. *
-%%% * *
-%%% * Also remember to update select/2 in orber_ifr.erl when adding *
-%%% * or deleting a record in this file. *
-%%% * *
-%%% *********************************************************************
-%%%----------------------------------------------------------------------
-
-%% Interface objects
-
-%% There are eight interface objects in an interface repository:
-%% Repository, ModuleDef, InterfaceDef, AttributeDef, OperationDef,
-%% TypedefDef, ConstantDef and ExceptionDef (CORBA V2.0, page 6-5/6).
-
-% The other objects defined here are used to build the above objects
-% (CORBA V2.0, page 6-7).
-
-% Object references are stored as mnesia object IDs, i.e. a tuple with
-% the table name and the ir_Internal_ID.
-
-% Inheritance strategy. We incorporate the inherited object into the
-% inheriting object. The record element 'inherited_objects' is a list
-% of objects that "this" object inherits from (i.e. full object
-% records and not object references).
-
-% The record element 'ir_Internal_ID' is a tag that uniquely
-% identifies a record. See the function orber_ifr:unique().
-
- % IRObject, page 6-9
--record(ir_IRObject, {ir_Internal_ID,def_kind}).
-
- % Contained, page 6-9
--record(ir_Contained, {ir_Internal_ID, %[IRObject]
- def_kind, %from IRObject
- id,
- name,
- version,
- defined_in,
- absolute_name,
- containing_repository}).
-
- % Container, page 6-10
--record(ir_Container, {ir_Internal_ID, %[IRObject]
- def_kind, %from IRObject
- contents}).
-
- % IDLType, page 6-15
--record(ir_IDLType, {ir_Internal_ID, %[IRObject]
- def_kind, %from IRObject
- type}).
-
- % Repository, page 6-16
--record(ir_Repository, {ir_Internal_ID, %[Container]
- def_kind, %from IRObject
- contents, %from Container
- primitivedefs}).
-
- % ModuleDef, page 6-17
--record(ir_ModuleDef, {ir_Internal_ID, %[Container,Contained]
- def_kind, %from IRObject
- contents, %from Container
- id, %from Contained
- name, %from Contained
- version, %from Contained
- defined_in, %from Contained
- absolute_name, %from Contained
- containing_repository %from Contained
- }).
-
- % ConstantDef, page 6-17
--record(ir_ConstantDef, {ir_Internal_ID, %[Contained]
- def_kind, %from IRObject
- id, %from Contained
- name, %from Contained
- version, %from Contained
- defined_in, %from Contained
- absolute_name, %from Contained
- containing_repository, %from Contained
- type,
- type_def,
- value}).
-
- % TypedefDef, page 6-18
--record(ir_TypedefDef, {ir_Internal_ID, %[Contained,IDLType]
- def_kind, %from IRObject
- id, %from Contained
- name, %from Contained
- version, %from Contained
- defined_in, %from Contained
- absolute_name, %from Contained
- containing_repository, %from Contained
- type %from IDLType
- }).
-
- % StructDef, page 6-19
--record(ir_StructDef, {ir_Internal_ID, %[TypedefDef]
- def_kind, %from IRObject
- id, %from Contained
- name, %from Contained
- version, %from Contained
- defined_in, %from Contained
- absolute_name, %from Contained
- containing_repository, %from Contained
- type, %from IDLType
- members}).
-
- % UnionDef, page 6-19
--record(ir_UnionDef, {ir_Internal_ID, %[TypedefDef]
- def_kind, %from IRObject
- id, %from Contained
- name, %from Contained
- version, %from Contained
- defined_in, %from Contained
- absolute_name, %from Contained
- containing_repository, %from Contained
- type, %from IDLType
- discriminator_type,
- discriminator_type_def,
- members}).
-
- % EnumDef, page 6-20
--record(ir_EnumDef, {ir_Internal_ID, %[TypedefDef]
- def_kind, %from IRObject
- id, %from Contained
- name, %from Contained
- version, %from Contained
- defined_in, %from Contained
- absolute_name, %from Contained
- containing_repository, %from Contained
- type, %from IDLType
- members}).
-
- % AliasDef, page 6-21
--record(ir_AliasDef, {ir_Internal_ID, %[TypedefDef]
- def_kind, %from IRObject
- id, %from Contained
- name, %from Contained
- version, %from Contained
- defined_in, %from Contained
- absolute_name, %from Contained
- containing_repository, %from Contained
- type, %from IDLType
- original_type_def}).
-
- % PrimitiveDef, page 6-21
--record(ir_PrimitiveDef, {ir_Internal_ID, %[IDLType]
- def_kind, %from IRObject
- type, %from IDLType
- kind}).
-
- % StringDef, page 6-22
--record(ir_StringDef, {ir_Internal_ID, %[IDLType]
- def_kind, %from IRObject
- type, %from IDLType
- bound}).
-
--record(ir_WstringDef, {ir_Internal_ID, %[IDLType]
- def_kind, %from IRObject
- type, %from IDLType
- bound}).
-
- % SequenceDef, page 6-22
--record(ir_SequenceDef, {ir_Internal_ID, %[IDLType]
- def_kind, %from IRObject
- type, %from IDLType
- bound,
- element_type,
- element_type_def}).
-
- % ArrayDef, page 6-23
--record(ir_ArrayDef, {ir_Internal_ID, %[IDLType]
- def_kind, %from IRObject
- type, %from IDLType
- length,
- element_type,
- element_type_def}).
-
- % ExceptionDef, page 6-23
--record(ir_ExceptionDef, {ir_Internal_ID, %[Contained]
- def_kind, %from IRObject
- id, %from Contained
- name, %from Contained
- version, %from Contained
- defined_in, %from Contained
- absolute_name, %from Contained
- containing_repository, %from Contained
- type,
- members}).
-
- % AttributeDef, page 6-24
--record(ir_AttributeDef, {ir_Internal_ID, %[Contained]
- def_kind, %from IRObject
- id, %from Contained
- name, %from Contained
- version, %from Contained
- defined_in, %from Contained
- absolute_name, %from Contained
- containing_repository, %from Contained
- type,
- type_def,
- mode}).
-
- % OperationDef, page 6-25
--record(ir_OperationDef, {ir_Internal_ID, %[Contained]
- def_kind, %from IRObject
- id, %from Contained
- name, %from Contained
- version, %from Contained
- defined_in, %from Contained
- absolute_name, %from Contained
- containing_repository, %from Contained
- result,
- result_def,
- params,
- mode,
- contexts,
- exceptions}).
-
- % InterfaceDef, page 6-27
--record(ir_InterfaceDef, {ir_Internal_ID, %[Container,Contained,IDLType]
- def_kind, %from IRObject
- contents, %from Container
- id, %from Contained
- name, %from Contained
- version, %from Contained
- defined_in, %from Contained
- absolute_name, %from Contained
- containing_repository, %from Contained
- type, %from IDLType
- base_interfaces}).
-
- % TypeCode, page 6-33
-
--record(ir_FixedDef, {ir_Internal_ID, %[IDLType]
- def_kind, %from IRObject
- type, %from IDLType
- digits,
- scale}).
-
-
-% TypeCodes cannot be defined as records, since each type code has a
-% quite unique structure depending on the type. The old TypeCode
-% record definition is left here as a comment in case we want to
-% change back to the old style.
-
-%% ir_TypeCode does not have a field ir_Internal_ID. TypeCodes are
-%% never explicitly written to the database as separate DB-records.
-%% TypeCodes are stored as full records whenever they are used in an
-%% IFR-object.
-%%-record(ir_TypeCode, {kind,
-%% parameter_list}).
-
- % ORB, page 6-39
--record(ir_ORB, {ir_Internal_ID, % *** Do we need any attributes
- dummy}). % for this table? ORB is a pseudo-
- % object so perhaps the table is
- % unnecessary?
-
--record(orber_light_ifr, {id, %% IFR-id
- module,
- type,
- base_id}).
-
--define(IFR_ModuleDef, 0).
--define(IFR_ConstantDef, 1).
--define(IFR_StructDef, 2).
--define(IFR_UnionDef, 3).
--define(IFR_EnumDef, 4).
--define(IFR_AliasDef, 5).
--define(IFR_InterfaceDef, 6).
--define(IFR_ExceptionDef, 7).
-
-
-%%%----------------------------------------------------------------------
-%%% 'ifr_object_list' is used by other modules. Do NOT remove or rename
-%%% this list!
-%%% An addition or deletion of a record above must be duplicated here in
-%%% this list and in the macro 'ifr_record_tuple_list' below.
--define(ifr_object_list, [ir_ModuleDef,
- ir_Contained,
- ir_AttributeDef,
- ir_Repository,
- ir_OperationDef,
- ir_InterfaceDef,
- ir_TypedefDef,
- ir_Container,
- ir_EnumDef,
- ir_UnionDef,
- ir_StringDef,
- ir_WstringDef,
- ir_ORB,
- ir_IDLType,
- ir_ExceptionDef,
- ir_IRObject,
- ir_PrimitiveDef,
- ir_ArrayDef,
- ir_AliasDef,
- ir_ConstantDef,
- ir_StructDef,
- ir_SequenceDef,
- ir_FixedDef]).
-
--define(ifr_light_object_list, [orber_light_ifr]).
-
--define(cr_fun_tuple(Table, Options),
- {Table,
- fun() ->
- case mnesia:create_table(Table,[{attributes,
- record_info(fields,
- Table)}]++Options)of
- {atomic,ok} ->
- ok;
- R ->
- R
- end
- end}
- ).
-
--define(cr_fun_tuple_local(Table, IFR_storage_type),
- {Table,
- fun() ->
- case mnesia:add_table_copy(Table,node(), IFR_storage_type)of
- {atomic,ok} ->
- ok;
- R ->
- R
- end
- end}
- ).
-
--define(ifr_record_tuple_list(Options),
- [?cr_fun_tuple(ir_IRObject, Options),
- ?cr_fun_tuple(ir_Contained, [{index, [#ir_Contained.id]}|Options]),
- ?cr_fun_tuple(ir_Container, Options),
- ?cr_fun_tuple(ir_IDLType, Options),
- ?cr_fun_tuple(ir_Repository, Options),
- ?cr_fun_tuple(ir_ModuleDef, [{index, [#ir_ModuleDef.id]}|Options]),
- ?cr_fun_tuple(ir_ConstantDef, [{index, [#ir_ConstantDef.id]}|Options]),
- ?cr_fun_tuple(ir_TypedefDef, [{index, [#ir_TypedefDef.id]}|Options]),
- ?cr_fun_tuple(ir_StructDef, [{index, [#ir_StructDef.id]}|Options]),
- ?cr_fun_tuple(ir_UnionDef, [{index, [#ir_UnionDef.id]}|Options]),
- ?cr_fun_tuple(ir_EnumDef, [{index, [#ir_EnumDef.id]}|Options]),
- ?cr_fun_tuple(ir_AliasDef, [{index, [#ir_AliasDef.id]}|Options]),
- ?cr_fun_tuple(ir_PrimitiveDef, Options),
- ?cr_fun_tuple(ir_StringDef, Options),
- ?cr_fun_tuple(ir_WstringDef, Options),
- ?cr_fun_tuple(ir_SequenceDef, Options),
- ?cr_fun_tuple(ir_ArrayDef, Options),
- ?cr_fun_tuple(ir_ExceptionDef, [{index, [#ir_ExceptionDef.id]}|Options]),
- ?cr_fun_tuple(ir_AttributeDef, [{index, [#ir_AttributeDef.id]}|Options]),
- ?cr_fun_tuple(ir_OperationDef, [{index, [#ir_OperationDef.id]}|Options]),
- ?cr_fun_tuple(ir_InterfaceDef, [{index, [#ir_InterfaceDef.id]}| Options]),
-% ?cr_fun_tuple(ir_TypeCode, Options),
- ?cr_fun_tuple(ir_ORB, Options),
- ?cr_fun_tuple(ir_FixedDef, Options)]).
-
--define(ifr_light_record_tuple_list(Options),
- [?cr_fun_tuple(orber_light_ifr, Options)]).
-
-
--define(ifr_record_tuple_list_local(IFR_storage_type),
- [?cr_fun_tuple_local(ir_IRObject, IFR_storage_type),
- ?cr_fun_tuple_local(ir_Contained, IFR_storage_type),
- ?cr_fun_tuple_local(ir_Container, IFR_storage_type),
- ?cr_fun_tuple_local(ir_IDLType, IFR_storage_type),
- ?cr_fun_tuple_local(ir_Repository, IFR_storage_type),
- ?cr_fun_tuple_local(ir_ModuleDef, IFR_storage_type),
- ?cr_fun_tuple_local(ir_ConstantDef, IFR_storage_type),
- ?cr_fun_tuple_local(ir_TypedefDef, IFR_storage_type),
- ?cr_fun_tuple_local(ir_StructDef, IFR_storage_type),
- ?cr_fun_tuple_local(ir_UnionDef, IFR_storage_type),
- ?cr_fun_tuple_local(ir_EnumDef, IFR_storage_type),
- ?cr_fun_tuple_local(ir_AliasDef, IFR_storage_type),
- ?cr_fun_tuple_local(ir_PrimitiveDef, IFR_storage_type),
- ?cr_fun_tuple_local(ir_StringDef, IFR_storage_type),
- ?cr_fun_tuple_local(ir_WstringDef, IFR_storage_type),
- ?cr_fun_tuple_local(ir_SequenceDef, IFR_storage_type),
- ?cr_fun_tuple_local(ir_ArrayDef, IFR_storage_type),
- ?cr_fun_tuple_local(ir_ExceptionDef, IFR_storage_type),
- ?cr_fun_tuple_local(ir_AttributeDef, IFR_storage_type),
- ?cr_fun_tuple_local(ir_OperationDef, IFR_storage_type),
- ?cr_fun_tuple_local(ir_InterfaceDef, IFR_storage_type),
-% ?cr_fun_tuple_local(ir_TypeCode, IFR_storage_type),
- ?cr_fun_tuple_local(ir_ORB, IFR_storage_type),
- ?cr_fun_tuple_local(ir_FixedDef, IFR_storage_type)]).
-
--define(ifr_light_record_tuple_list_local(IFR_storage_type),
- [?cr_fun_tuple_local(orber_light_ifr, IFR_storage_type)]).
diff --git a/lib/orber/src/iop_ior.erl b/lib/orber/src/iop_ior.erl
deleted file mode 100644
index a78a6b96e5..0000000000
--- a/lib/orber/src/iop_ior.erl
+++ /dev/null
@@ -1,1717 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: iop_ior.erl
-%% Description:
-%% This file contains the IOP::IOR handling
-%%
-%%-----------------------------------------------------------------
--module(iop_ior).
-
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([code/4, decode/4, string_decode/1,
- string_code/1, string_code/2, string_code/3, string_code/4,
- get_key/1, get_key/2, get_typeID/1, create/9,
- get_objkey/1, check_nil/1, get_privfield/1, set_privfield/2,
- get_orbfield/1, set_orbfield/2,
- get_flagfield/1, set_flagfield/2,
- create_external/5, create_external/6, print/1, print/2,
- get_alt_addr/1, add_component/2, get_peerdata/1]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
--define(DEBUG_LEVEL, 6).
-
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: create/5/6
-%%-----------------------------------------------------------------
-%% There are a few restrictions if a certain IIOP-version may contain certain components
-%% and contexts The ones we currently, and the ones we perhaps will, support is:
-%%
-%% Feature 1.0 1.1 1.2
-%% TransactionService Service Context yes yes yes
-%% CodeSets Service Context yes yes
-%% Object by Value Service Context yes
-%% Bi-Directional IIOP Service Context yes
-%% IOR components in IIOP profile yes yes
-%% TAG_ORB_TYPE yes yes
-%% TAG_CODE_SETS yes yes
-%% TAG_ALTERNATE_IIOP_ADDRESS yes
-%% TAG_SSL_SEC_TRANS yes yes
-%% Extended IDL data types yes yes
-%% Bi-Directional GIOP Features yes
-%% Value types and Abstract Interfaces yes
-%%
-%% CSIv2:
-%% A target that supports unprotected IIOP invocations shall specify in the
-%% corresponding TAG_INTERNET_IOP profile a nonzero port number at which the
-%% target will accept unprotected invocations.9 A target that supports only
-%% protected IIOP invocations shall specify a port number of 0 (zero) in the
-%% corresponding TAG_INTERNET_IOP profile.
-%%-----------------------------------------------------------------
-create({1, 0}, TypeID, Hosts, IIOPPort, _, Objkey, _, _, _) ->
- Template = #'IIOP_ProfileBody_1_0'{iiop_version =
- #'IIOP_Version'{major=1, minor=0},
- port = IIOPPort,
- object_key = Objkey},
- #'IOP_IOR'{type_id=TypeID,
- profiles=duplicate_1_0_profiles(Hosts, Template, [])};
-create({1, Minor}, TypeID, Hosts, IIOPPort, -1, Objkey, MC, _, _) ->
- Template = #'IIOP_ProfileBody_1_1'{iiop_version =
- #'IIOP_Version'{major=1, minor=Minor},
- port = IIOPPort,
- object_key = Objkey,
- components = MC},
- #'IOP_IOR'{type_id=TypeID,
- profiles=duplicate_1_1_profiles(Hosts, Template, [])};
-
-create({1, Minor}, TypeID, Hosts, IIOPPort, SSLPort, Objkey, MC, Flags, EnvFlags) ->
- V=#'IIOP_Version'{major=1, minor=Minor},
- UseCSIv2 = ?ORB_FLAG_TEST(EnvFlags, ?ORB_ENV_USE_CSIV2),
- Template =
- case ?ORB_FLAG_TEST(Flags, ?ORB_NO_SECURITY) of
- true ->
- #'IIOP_ProfileBody_1_1'{iiop_version = V,
- port = IIOPPort,
- object_key = Objkey,
- components = MC};
- false when UseCSIv2 == false ->
- #'IIOP_ProfileBody_1_1'{iiop_version=V,
- port=IIOPPort,
- object_key=Objkey,
- components= [#'IOP_TaggedComponent'
- {tag=?TAG_SSL_SEC_TRANS,
- component_data=#'SSLIOP_SSL'{target_supports = 2,
- target_requires = 2,
- port = SSLPort}}|MC]};
- false when UseCSIv2 == true ->
- #'IIOP_ProfileBody_1_1'
- {iiop_version=V,
- port=0,
- object_key=Objkey,
- components= [#'IOP_TaggedComponent'
- {tag = ?TAG_CSI_SEC_MECH_LIST,
- component_data =
- #'CSIIOP_CompoundSecMechList'
- {stateful = false,
- mechanism_list =
- [#'CSIIOP_CompoundSecMech'
- {target_requires = 6,
- transport_mech =
- #'IOP_TaggedComponent'
- {tag=?TAG_TLS_SEC_TRANS,
- component_data=#'CSIIOP_TLS_SEC_TRANS'
- {target_supports = 7,
- target_requires = 8,
- addresses =
- [#'CSIIOP_TransportAddress'{host_name = "Host",
- port = SSLPort}]}},
- as_context_mech =
- #'CSIIOP_AS_ContextSec'
- {target_supports = 9, target_requires = 10,
- client_authentication_mech = [1, 255],
- target_name = [2,255]},
- sas_context_mech =
- #'CSIIOP_SAS_ContextSec'
- {target_supports = 11, target_requires = 12,
- privilege_authorities =
- [#'CSIIOP_ServiceConfiguration'
- {syntax = ?ULONGMAX,
- name = [3,255]}],
- supported_naming_mechanisms = [[4,255],[5,255]],
- supported_identity_types = ?ULONGMAX}}]}}|MC]}
- end,
- #'IOP_IOR'{type_id=TypeID,
- profiles=duplicate_1_1_profiles(Hosts, Template, [])};
-create(Version, TypeID, Host, IIOPPort, SSLPort, Objkey, MC, _, _) ->
- orber:dbg("[~p] iop_ior:create(~p, ~p, ~p, ~p, ~p, ~p, ~p);~n"
- "Unsupported IIOP-version.",
- [?LINE, Version, TypeID, Host, IIOPPort, SSLPort, Objkey, MC],
- ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO}).
-
-
-
-
-duplicate_1_1_profiles([], _, Profiles) ->
- Profiles;
-duplicate_1_1_profiles([H|T], Template, Profiles) ->
- duplicate_1_1_profiles(T, Template,
- [#'IOP_TaggedProfile'
- {tag=?TAG_INTERNET_IOP,
- profile_data =
- Template#'IIOP_ProfileBody_1_1'{host = H}}|Profiles]).
-
-duplicate_1_0_profiles([], _, Profiles) ->
- Profiles;
-duplicate_1_0_profiles([H|T], Template, Profiles) ->
- duplicate_1_0_profiles(T, Template,
- [#'IOP_TaggedProfile'
- {tag=?TAG_INTERNET_IOP,
- profile_data =
- Template#'IIOP_ProfileBody_1_0'{host = H}}|Profiles]).
-
-
-%%-----------------------------------------------------------------
-%% Func: create_external/5/6
-%%-----------------------------------------------------------------
-create_external(Version, TypeID, Host, IIOP_port, Objkey) ->
- create_external(Version, TypeID, Host, IIOP_port, Objkey, []).
-create_external({1, 0}, TypeID, Host, IIOP_port, Objkey, _MC) ->
- V=#'IIOP_Version'{major=1,
- minor=0},
- PB=#'IIOP_ProfileBody_1_0'{iiop_version=V,
- host=Host,
- port=IIOP_port,
- object_key=Objkey},
- #'IOP_IOR'{type_id=TypeID, profiles=[#'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP,
- profile_data=PB}]};
-create_external({1, 1}, TypeID, Host, IIOP_port, Objkey, Components) ->
- V=#'IIOP_Version'{major=1,
- minor=1},
- PB=#'IIOP_ProfileBody_1_1'{iiop_version=V,
- host=Host,
- port=IIOP_port,
- object_key=Objkey,
- components=Components},
- #'IOP_IOR'{type_id=TypeID,
- profiles=[#'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP,
- profile_data=PB}]};
-create_external({1, 2}, TypeID, Host, IIOP_port, Objkey, Components) ->
- V=#'IIOP_Version'{major=1,
- minor=2},
- PB=#'IIOP_ProfileBody_1_1'{iiop_version=V,
- host=Host,
- port=IIOP_port,
- object_key=Objkey,
- components=Components},
- #'IOP_IOR'{type_id=TypeID,
- profiles=[#'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP,
- profile_data=PB}]};
-create_external(Version, TypeID, Host, IIOP_port, Objkey, MC) ->
- orber:dbg("[~p] iop_ior:create_external(~p, ~p, ~p, ~p, ~p, ~p);~n"
- "Unsupported IIOP-version.",
- [?LINE, Version, TypeID, Host, IIOP_port, Objkey, MC], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------------
-%% Func: get_peerdata/1
-%%-----------------------------------------------------------------
-%% Probably an external IOR.
-get_peerdata(#'IOP_IOR'{} = IOR) ->
- get_peerdata(get_key(IOR), IOR, [], []);
-%% Local object reference.
-get_peerdata(_) ->
- [].
-
-%% "Plain" TCP/IP.
-get_peerdata({'external', {Host, Port, _InitObjkey, Index, TaggedProfile,
- #host_data{protocol = normal,
- csiv2_mech = undefined}}},
- IOR, Acc, Indexes) ->
- Alts = get_alt_addr(TaggedProfile),
- get_peerdata(get_key(IOR, [Index|Indexes]), IOR, [{Host, Port}|Alts] ++ Acc,
- [Index|Indexes]);
-%% "Plain" SSL
-get_peerdata({'external', {Host, _Port, _InitObjkey, Index, TaggedProfile,
- #host_data{protocol = ssl,
- ssl_data = #'SSLIOP_SSL'{port = Port},
- csiv2_mech = undefined}}},
- IOR, Acc, Indexes) ->
- Alts = get_alt_addr(TaggedProfile),
- get_peerdata(get_key(IOR, [Index|Indexes]), IOR, [{Host, Port}|Alts] ++ Acc,
- [Index|Indexes]);
-%% TEMPORARY FIX TO SKIP CSIv2 DATA.
-get_peerdata({'external', {Host, _Port, _InitObjkey, Index, TaggedProfile,
- #host_data{protocol = ssl,
- ssl_data = #'SSLIOP_SSL'{port = Port}}}},
- IOR, Acc, Indexes) ->
- Alts = get_alt_addr(TaggedProfile),
- get_peerdata(get_key(IOR, [Index|Indexes]), IOR, [{Host, Port}|Alts] ++ Acc,
- [Index|Indexes]);
-%% CSIv2 over SSL (TAG_TLS_SEC_TRANS) using the SAS protocol. Note port must equal 0.
-get_peerdata({'external',
- {_Host, 0, _InitObjkey, Index, TaggedProfile,
- #host_data{protocol = ssl,
- csiv2_mech =
- #'CSIIOP_CompoundSecMech'{target_requires = _TR} = _Mech,
- csiv2_addresses = Addresses}}},
- IOR, Acc, Indexes) ->
- Alts = get_alt_addr(TaggedProfile),
- get_peerdata(get_key(IOR, [Index|Indexes]), IOR, Addresses ++ Alts ++ Acc,
- [Index|Indexes]);
-%% CSIv2 over SSL (TAG_NULL_TAG) using the SAS protocol.
-get_peerdata({'external',
- {Host, _Port, _InitObjkey, Index, TaggedProfile,
- #host_data{protocol = ssl,
- ssl_data = #'SSLIOP_SSL'{port = Port},
- csiv2_mech = Mech}}},
- IOR, Acc, Indexes) when is_record(Mech, 'CSIIOP_CompoundSecMech') ->
- Alts = get_alt_addr(TaggedProfile),
- get_peerdata(get_key(IOR, [Index|Indexes]), IOR, [{Host, Port}|Alts] ++ Acc,
- [Index|Indexes]);
-%% CSIv2 over TCP (TAG_NULL_TAG) using the SAS protocol.
-get_peerdata({'external',
- {Host, Port, _InitObjkey, Index, TaggedProfile,
- #host_data{protocol = normal,
- csiv2_mech = Mech}}},
- IOR, Acc, Indexes) when is_record(Mech, 'CSIIOP_CompoundSecMech') ->
- Alts = get_alt_addr(TaggedProfile),
- get_peerdata(get_key(IOR, [Index|Indexes]), IOR, [{Host, Port}|Alts] ++ Acc,
- [Index|Indexes]);
-get_peerdata(undefined, _IOR, Acc, _Indexes) ->
- Acc;
-%% Local object reference.
-get_peerdata(_, _, _, _) ->
- [].
-
-%%-----------------------------------------------------------------
-%% Func: get_key/1
-%%-----------------------------------------------------------------
-get_key(#'IOP_IOR'{profiles=P}) ->
- get_key_1(P, false, 0, undefined, #host_data{});
-get_key({Module, Type, Key, _UserDef, OrberDef, Flags}) ->
- if
- is_binary(Key) ->
- {'internal', Key, OrberDef, Flags, Module};
- Type == pseudo ->
- {'internal_registered', {pseudo, Key}, OrberDef, Flags, Module};
- is_atom(Key) ->
- {'internal_registered', Key, OrberDef, Flags, Module}
- end;
-get_key(What) ->
- orber:dbg("[~p] iop_ior:get_key(~p); Invalid IOR",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO}).
-
-
-get_key(#'IOP_IOR'{profiles=P}, Exclude) ->
- get_key_1(P, true, 0, Exclude, #host_data{});
-get_key(What, _Exclude) ->
- orber:dbg("[~p] iop_ior:get_key(~p); Invalid IOR",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO}).
-
-
-get_key_1([], false, _, _, _) ->
- orber:dbg("[~p] iop_ior:get_key_1([]); bad object reference, profile not found.",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO});
-get_key_1([], true, _, _, _) ->
- undefined;
-%%--------- Local IIOP-1.0 Profile ---------
-get_key_1([#'IOP_TaggedProfile'
- {tag=?TAG_INTERNET_IOP,
- profile_data=#'IIOP_ProfileBody_1_0'
- {object_key={Module, Type, Key, _UserDef, OrberDef, Flags}}}|_],
- _Retry, _Counter, _Exclude, _HD) ->
- if
- is_binary(Key) ->
- {'internal', Key, OrberDef, Flags, Module};
- Type == pseudo ->
- {'internal_registered', {pseudo, Key}, OrberDef, Flags, Module};
- is_atom(Key) ->
- {'internal_registered', Key, OrberDef, Flags, Module}
- end;
-%%--------- Local IIOP-1.1 & IIOP-1.2 Profiles ---------
-get_key_1([#'IOP_TaggedProfile'
- {tag=?TAG_INTERNET_IOP,
- profile_data=#'IIOP_ProfileBody_1_1'
- {object_key={Module, Type, Key, _UserDef, OrberDef, Flags}}}|_],
- _Retry, _Counter, _Exclude, _HD) ->
- if
- is_binary(Key) ->
- {'internal', Key, OrberDef, Flags, Module};
- Type == pseudo ->
- {'internal_registered', {pseudo, Key}, OrberDef, Flags, Module};
- Type == passive ->
- %% CHECK FOR PRIMARY COMPONENT & GROUPID! Better yet, do not.
- %% This is internal key and is supposed to be well formed.
- %% Also, internal keys are not searched for primary member or
- %% groupid in the component-section of IOR. ObjectKey will tell
- %% GroupID and database read transaction will tell primary member.
- {'internal_registered', {passive, Key}, OrberDef, Flags, Module};
- is_atom(Key) ->
- {'internal_registered', Key, OrberDef, Flags, Module}
- end;
-%%--------- External IIOP-1.0 Profile ---------
-get_key_1([#'IOP_TaggedProfile'
- {tag=?TAG_INTERNET_IOP,
- profile_data=#'IIOP_ProfileBody_1_0'
- {host = Host, port = Port, object_key= ObjectKey}} = TP|P],
- _Retry, Counter, Exclude, HD) when Exclude == undefined ->
- %% This case is "necessary" if an ORB adds several IIOP-profiles since,
- %% for example, wchar isn't supported for 1.0.
- case get_key_1(P, true, Counter+1, Exclude, HD) of
- undefined ->
- %% We now it's IIOP-1.0 and it doesn't contain any
- %% components. Hence, no need to check for it.
- {'external', {Host, Port, ObjectKey, Counter, TP,
- HD#host_data{version = {1,0}}}};
- LaterVersion ->
- LaterVersion
- end;
-get_key_1([#'IOP_TaggedProfile'
- {tag=?TAG_INTERNET_IOP,
- profile_data=#'IIOP_ProfileBody_1_0'
- {host = Host, port = Port, object_key= ObjectKey}} = TP|P],
- Retry, Counter, Exclude, HD) ->
- case lists:member(Counter, Exclude) of
- true ->
- get_key_1(P, Retry, Counter+1, Exclude, HD);
- false ->
- %% This case is "necessary" if an ORB adds several IIOP-profiles since,
- %% for example, wchar isn't supported for 1.0.
- case get_key_1(P, true, Counter+1, Exclude, HD) of
- undefined ->
- {'external', {Host, Port, ObjectKey, Counter, TP,
- HD#host_data{version = {1,0}}}};
- LaterVersion ->
- LaterVersion
- end
- end;
-%%--------- External IIOP-1.1 & IIOP-1.2 Profiles ---------
-get_key_1([#'IOP_TaggedProfile'
- {tag=?TAG_INTERNET_IOP,
- profile_data=#'IIOP_ProfileBody_1_1'
- {iiop_version = #'IIOP_Version'{major=Major, minor=Minor},
- host = Host, port = Port, object_key= ObjectKey,
- components = Components}} = TP|P],
- Retry, Counter, Exclude, HD) when Exclude == undefined ->
- case check_components(Components, Port, HD#host_data{version = {Major,Minor}}) of
- #host_data{csiv2_mech = undefined} when Port == 0 ->
- get_key_1(P, Retry, Counter+1, Exclude, HD);
- NewHD ->
- {'external', {Host, Port, ObjectKey, Counter, TP, NewHD}}
- end;
-get_key_1([#'IOP_TaggedProfile'
- {tag=?TAG_INTERNET_IOP,
- profile_data=#'IIOP_ProfileBody_1_1'
- {iiop_version = #'IIOP_Version'{major=Major, minor=Minor},
- host = Host, port = Port, object_key= ObjectKey,
- components = Components}} = TP|P],
- Retry, Counter, Exclude, HD) ->
- case lists:member(Counter, Exclude) of
- true ->
- get_key_1(P, Retry, Counter+1, Exclude, HD);
- false ->
- case check_components(Components, Port,
- HD#host_data{version = {Major,Minor}}) of
- #host_data{csiv2_mech = undefined} when Port == 0 ->
- get_key_1(P, Retry, Counter+1, Exclude, HD);
- NewHD ->
- {'external', {Host, Port, ObjectKey, Counter, TP, NewHD}}
- end
- end;
-get_key_1([_ | P], Retry, Counter, Exclude, HD) ->
- get_key_1(P, Retry, Counter+1, Exclude, HD).
-
-check_components([], _, HostData) ->
- HostData;
-check_components([#'IOP_TaggedComponent'{tag=?TAG_SSL_SEC_TRANS,
- component_data=SSLStruct}|Rest],
- Port, HostData) when is_record(SSLStruct, 'SSLIOP_SSL') ->
- check_components(Rest, Port, HostData#host_data{protocol = ssl,
- ssl_data = SSLStruct});
-%% CSIv2 Components
-check_components([#'IOP_TaggedComponent'{tag=?TAG_CSI_SEC_MECH_LIST,
- component_data=Data}|Rest],
- Port, HostData) when is_record(Data, 'CSIIOP_CompoundSecMechList') ->
- case check_sec_mech(Data#'CSIIOP_CompoundSecMechList'.mechanism_list, Port) of
- undefined ->
- check_components(Rest, Port, HostData);
- {ok, Protocol, Mech, Addresses} ->
- check_components(Rest, Port,
- HostData#host_data
- {protocol = Protocol,
- csiv2_mech = Mech,
- csiv2_statefull = Data#'CSIIOP_CompoundSecMechList'.stateful,
- csiv2_addresses = Addresses});
- {ok, Mech} ->
- check_components(Rest, Port,
- HostData#host_data
- {csiv2_mech = Mech,
- csiv2_statefull = Data#'CSIIOP_CompoundSecMechList'.stateful})
- end;
-%% FT Components
-check_components([#'IOP_TaggedComponent'
- {tag=?TAG_FT_HEARTBEAT_ENABLED,
- component_data=
- #'FT_TagFTHeartbeatEnabledTaggedComponent'
- {heartbeat_enabled = Boolean}}|Rest],
- Port, HostData) ->
- check_components(Rest, Port, HostData#host_data{ft_heartbeat = Boolean});
-check_components([#'IOP_TaggedComponent'
- {tag=?TAG_FT_PRIMARY,
- component_data=
- #'FT_TagFTPrimaryTaggedComponent'{primary = Boolean}}|Rest],
- Port, HostData) ->
- check_components(Rest, Port, HostData#host_data{ft_primary = Boolean});
-check_components([#'IOP_TaggedComponent'
- {tag=?TAG_FT_GROUP,
- component_data=#'FT_TagFTGroupTaggedComponent'
- {version = #'GIOP_Version'{major = 1, minor = 0},
- ft_domain_id = FTDomain,
- object_group_id = GroupID,
- object_group_ref_version = GroupVer}}|Rest],
- Port, HostData) ->
- check_components(Rest, Port, HostData#host_data{ft_domain = FTDomain,
- ft_group = GroupID,
- ft_ref_version = GroupVer});
-%% CodeSets Component
-check_components([#'IOP_TaggedComponent'{tag=?TAG_CODE_SETS,
- component_data=#'CONV_FRAME_CodeSetComponentInfo'
- {'ForCharData' = Char,
- 'ForWcharData' = Wchar}}|Rest],
- Port, HostData) ->
- CharData = check_char_codeset(Char),
- WcharData = check_wchar_codeset(Wchar),
- check_components(Rest, Port, HostData#host_data{charset = CharData,
- wcharset = WcharData});
-%% Not used
-check_components([_ | Rest], Port, HostData) ->
- check_components(Rest, Port, HostData).
-
-check_sec_mech([], _) ->
- undefined;
-%% Not supported yet.
-%check_sec_mech([#'CSIIOP_CompoundSecMech'
-% {target_requires = TR,
-% transport_mech=
-% #'IOP_TaggedComponent'{tag=?TAG_SECIOP_SEC_TRANS}} = Mech|_],
-% Port) ->
-% {ok, seciop, Mech};
-check_sec_mech([#'CSIIOP_CompoundSecMech'
- {target_requires = TR,
- transport_mech=
- #'IOP_TaggedComponent'{tag = ?TAG_TLS_SEC_TRANS,
- component_data = CD}} = Mech|_], _Port)
- when TR =< ?CSIv2_MAX_TARGET_REQUIRES ->
- {ok, ssl, Mech, extract_host_port(CD#'CSIIOP_TLS_SEC_TRANS'.addresses, [])};
-%% The TAG_NULL_TAG component shall be used in the 'transport_mech' field to
-%% indicate that a mechanism does not implement security functionality at the
-%% transport layer.
-%% If the port field in TAG_INTERNET_IOP equals 0 we must find a TAG_TLS_SEC_TRANS
-%% or TAG_SECIOP_SEC_TRANS mechanism.
-check_sec_mech([#'CSIIOP_CompoundSecMech'
- {transport_mech=
- #'IOP_TaggedComponent'{tag = ?TAG_NULL_TAG}}|Rest], 0) ->
- check_sec_mech(Rest, 0);
-check_sec_mech([#'CSIIOP_CompoundSecMech'
- {target_requires = TR,
- transport_mech=
- #'IOP_TaggedComponent'{tag = ?TAG_NULL_TAG}} = Mech|_], _Port)
- when TR =< ?CSIv2_MAX_TARGET_REQUIRES ->
- {ok, Mech};
-%% Unrecognized or the peer requires more than we support.
-check_sec_mech([_ | Rest], Port) ->
- check_sec_mech(Rest, Port).
-
-extract_host_port([], Acc) ->
- Acc;
-extract_host_port([#'CSIIOP_TransportAddress'{host_name = Host,
- port = Port}|Rest], Acc) ->
- extract_host_port(Rest, [{Host, Port}|Acc]).
-
-
-check_char_codeset(#'CONV_FRAME_CodeSetComponent'{native_code_set=?ISO8859_1_ID}) ->
- ?ISO8859_1_ID;
-check_char_codeset(#'CONV_FRAME_CodeSetComponent'{native_code_set=?ISO646_IRV_ID}) ->
- ?ISO646_IRV_ID;
-check_char_codeset(#'CONV_FRAME_CodeSetComponent'{conversion_code_sets=Converters}) ->
- %% Since the list of Converters usually is very short (0 or 1 element) we
- %% can use lists:member.
- case lists:member(?ISO8859_1_ID, Converters) of
- true ->
- ?ISO8859_1_ID;
- false ->
- %% Since we are 100% sure strings will be (e.g. IFR-ids) used we
- %% can raise an exception at this point.
- orber:dbg("[~p] iop_ior:check_char_codeset(~p);~n"
- "Orber cannot communicate with this ORB.~n"
- "It doesn't support a Char CodeSet known to Orber.",
- [?LINE, Converters], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status = ?COMPLETED_NO})
- end.
-
-check_wchar_codeset(#'CONV_FRAME_CodeSetComponent'{native_code_set=?UTF_16_ID}) ->
- ?UTF_16_ID;
-check_wchar_codeset(#'CONV_FRAME_CodeSetComponent'{native_code_set=?UCS_2_ID}) ->
- ?UCS_2_ID;
-check_wchar_codeset(#'CONV_FRAME_CodeSetComponent'{conversion_code_sets=Converters}) ->
- case lists:member(?UTF_16_ID, Converters) of
- true ->
- ?UTF_16_ID;
- false ->
- %% We should not raise an exception here since we do not know if
- %% wchar/wstring is used.
- ?UTF_16_ID
-% ?UNSUPPORTED_WCHAR
- end.
-
-
-%%-----------------------------------------------------------------
-%% Func: add_component/2
-%%-----------------------------------------------------------------
-add_component(Objref, Component) when is_record(Objref, 'IOP_IOR') ->
- add_component_ior(Objref, Component);
-add_component(Objref, Component) ->
- add_component_local(Objref, Component, orber:giop_version()).
-
-add_component_local(_, Component, {1,0}) ->
- orber:dbg("[~p] iop_ior:add_component(~p);~n"
- "IIOP-1.0 objects cannot contain any components.",
- [?LINE, Component], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status = ?COMPLETED_NO});
-add_component_local(_, #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS}
- = Component, {1,1}) ->
- orber:dbg("[~p] iop_ior:add_component(~p);~n"
- "IIOP-1.1 objects may not contain ALTERNATE_IIOP_ADDRESS components.",
- [?LINE, Component], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status = ?COMPLETED_NO});
-add_component_local({Mod, Type, Key, UserDef, OrberDef, Flags}, Component, Version) ->
- EnvFlags = orber:get_flags(),
- MC = case ?ORB_FLAG_TEST(EnvFlags, ?ORB_ENV_EXCLUDE_CODESET_COMPONENT) of
- true ->
- [Component];
- false ->
- [#'IOP_TaggedComponent'{tag=?TAG_CODE_SETS,
- component_data=?DEFAULT_CODESETS},
- Component]
- end,
- case ?ORB_FLAG_TEST(EnvFlags, ?ORB_ENV_ENABLE_NAT) of
- false ->
- create(Version, Mod:typeID(), orber:host(), orber:iiop_port(),
- orber:iiop_ssl_port(),
- {Mod, Type, Key, UserDef, OrberDef, Flags},
- MC, Flags, EnvFlags);
- true ->
- create(Version, Mod:typeID(), orber:nat_host(),
- orber:nat_iiop_port(), orber:nat_iiop_ssl_port(),
- {Mod, Type, Key, UserDef, OrberDef, Flags},
- MC, Flags, EnvFlags)
-
- end.
-
-add_component_ior(#'IOP_IOR'{profiles=P} = IOR, Component) ->
- case add_component_ior_helper(P, Component, false, []) of
- {false, _} ->
- orber:dbg("[~p] iop_ior:add_component_ior(~p);~n"
- "The IOR do not contain a valid IIOP-version for the supplied component.",
- [?LINE, Component], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status = ?COMPLETED_NO});
- {_, NewProfiles} ->
- IOR#'IOP_IOR'{profiles=NewProfiles}
- end.
-
-add_component_ior_helper([], _Component, Status, Acc) ->
- {Status, Acc};
-add_component_ior_helper([#'IOP_TaggedProfile'
- {tag=?TAG_INTERNET_IOP,
- profile_data=#'IIOP_ProfileBody_1_1'
- {iiop_version= #'IIOP_Version'{minor=1}}}|T],
- #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS}
- = Component, Status, Acc) ->
- %% 'ALTERNATE_IIOP_ADDRESS' may only be added to IIOP-1.2 IOR's.
- add_component_ior_helper(T, Component, Status, Acc);
-add_component_ior_helper([#'IOP_TaggedProfile'
- {tag=?TAG_INTERNET_IOP,
- profile_data=#'IIOP_ProfileBody_1_1'
- {object_key=Objkey,
- components=Components} = PB} = H|T],
- Component, _Status, Acc) when is_tuple(Objkey) ->
- %% The objectkey must be a tuple if it's a local object. We cannot(!!) add components
- %% to an external IOR.
- add_component_ior_helper(T, Component, true,
- [H#'IOP_TaggedProfile'
- {profile_data=PB#'IIOP_ProfileBody_1_1'
- {components = [Component|Components]}}|Acc]);
-add_component_ior_helper([_|T], Component, Status, Acc) ->
- add_component_ior_helper(T, Component, Status, Acc).
-
-%%-----------------------------------------------------------------
-%% Func: get_alt_addr/1
-%%-----------------------------------------------------------------
-%% TAG_ALTERNATE_IIOP_ADDRESS may only occur in IIOP-1.2 IOR's.
-get_alt_addr(#'IOP_TaggedProfile'
- {tag=?TAG_INTERNET_IOP,
- profile_data=#'IIOP_ProfileBody_1_1'{iiop_version=
- #'IIOP_Version'{minor=2},
- components=Components}}) ->
- get_alt_addr_helper(Components, []);
-get_alt_addr(_) ->
- [].
-
-get_alt_addr_helper([], Acc) -> Acc;
-get_alt_addr_helper([#'IOP_TaggedComponent'{tag=?TAG_ALTERNATE_IIOP_ADDRESS,
- component_data=#'ALTERNATE_IIOP_ADDRESS'
- {'HostID'=Host, 'Port'=Port}}|T], Acc) ->
- get_alt_addr_helper(T, [{Host, Port}|Acc]);
-get_alt_addr_helper([_|T], Acc) ->
- get_alt_addr_helper(T, Acc).
-
-%%-----------------------------------------------------------------
-%% Func: get_typeID/1
-%%-----------------------------------------------------------------
-get_typeID(#'IOP_IOR'{type_id=TypeID}) ->
- TypeID;
-get_typeID({Mod, _Type, _Key, _UserDef, _OrberDef, _Flags}) ->
- Mod:typeID().
-
-%%-----------------------------------------------------------------
-%% Func: get_objkey/1
-%%-----------------------------------------------------------------
-get_objkey(#'IOP_IOR'{profiles=P}) ->
- get_objkey_1(P);
-get_objkey({Id, Type, Key, UserDef, OrberDef, Flags}) ->
- {Id, Type, Key, UserDef, OrberDef, Flags}.
-
-get_objkey_1([]) ->
- orber:dbg("[~p] iop_ior:get_objkey_1([]); bad object key, profile not found.",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO});
-get_objkey_1([#'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB} |_]) ->
- [_, _, _, _, ObjectKey | _] = tuple_to_list(PB),
- ObjectKey;
-get_objkey_1([_ | P]) ->
- get_objkey_1(P).
-
-%%-----------------------------------------------------------------
-%% Func: get_privfield/1
-%%-----------------------------------------------------------------
-get_privfield(#'IOP_IOR'{profiles=P}) ->
- get_privfield_1(P);
-get_privfield({_Id, _Type, _Key, UserDef, _OrberDef, _Flags}) ->
- UserDef.
-
-get_privfield_1([]) ->
- orber:dbg("[~p] iop_ior:get_privfield_1([]); bad object key, profile not found.",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO});
-get_privfield_1([#'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB}|_]) ->
- [_, _, _, _, ObjectKey | _] = tuple_to_list(PB),
- case ObjectKey of
- {_Id, _Type, _Key, UserDef, _OrberDef, _Flags} ->
- UserDef;
- _ ->
- orber:dbg("[~p] iop_ior:get_privfield_1(~p); bad object key.",
- [?LINE, ObjectKey], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO})
- end;
-get_privfield_1([_| P]) ->
- get_privfield_1(P).
-
-%%-----------------------------------------------------------------
-%% Func: set_privfield/2
-%%-----------------------------------------------------------------
-set_privfield(#'IOP_IOR'{type_id=Id, profiles=P}, UserData) ->
- #'IOP_IOR'{type_id=Id, profiles=set_privfield_1(P, UserData)};
-set_privfield({Id, Type, Key, _, OrberDef, Flags}, UserData) ->
- {Id, Type, Key, UserData, OrberDef, Flags}.
-
-set_privfield_1([], _) ->
- orber:dbg("[~p] iop_ior:set_privfield_1([]); bad object key, profile not found or external object.",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO});
-set_privfield_1([#'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB}|P], UserData) ->
- [RecName, Version, Host, IIOP_port, ObjectKey | Rest] = tuple_to_list(PB),
- case ObjectKey of
- {Id, Type, Key, _, OrberDef, Flags} ->
- [#'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP,
- profile_data=list_to_tuple([RecName,
- Version, Host,
- IIOP_port,
- {Id, Type, Key, UserData, OrberDef, Flags}|
- Rest])} |
- set_privfield_1(P, UserData)];
- _ ->
- [#'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB} | set_privfield_1(P, UserData)]
- end;
-set_privfield_1([PB| P], UserData) ->
- [PB | set_privfield_1(P, UserData)].
-
-%%-----------------------------------------------------------------
-%% Func: get_orbfield/1
-%%-----------------------------------------------------------------
-get_orbfield(#'IOP_IOR'{profiles=P}) ->
- get_orbfield_1(P);
-get_orbfield({_Id, _Type, _Key, _UserDef, OrberDef, _Flags}) ->
- OrberDef.
-
-get_orbfield_1([]) ->
- orber:dbg("[~p] iop_ior:get_orbfield_1([]);~n"
- "bad object key, profile not found.", [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO});
-get_orbfield_1([#'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB}|_]) ->
- [_, _, _, _, ObjectKey | _] = tuple_to_list(PB),
- case ObjectKey of
- {_Id, _Type, _Key, _UserDef, OrberDef, _Flags} ->
- OrberDef;
- _ ->
- orber:dbg("[~p] iop_ior:get_orbfield_1(~p);~n"
- "bad object key.", [?LINE, ObjectKey], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO})
- end;
-get_orbfield_1([_| P]) ->
- get_orbfield_1(P).
-
-%%-----------------------------------------------------------------
-%% Func: set_orbfield/2
-%%-----------------------------------------------------------------
-set_orbfield(#'IOP_IOR'{type_id=Id, profiles=P}, OrberDef) ->
- #'IOP_IOR'{type_id=Id, profiles=set_orbfield_1(P, OrberDef)};
-set_orbfield({Id, Type, Key, Priv, _, Flags}, OrberDef) ->
- {Id, Type, Key, Priv, OrberDef, Flags}.
-
-set_orbfield_1([], _) ->
- orber:dbg("[~p] iop_ior:set_orbfield_1([]);~n"
- "bad object key, profile not found or external object.",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO});
-set_orbfield_1([#'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB}| P], OrberDef) ->
- [RecName, Version, Host, IIOP_port, ObjectKey | Rest] = tuple_to_list(PB),
- case ObjectKey of
- {Id, Type, Key, Priv, _, Flags} ->
- [#'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP,
- profile_data=list_to_tuple([RecName,
- Version, Host,
- IIOP_port,
- {Id, Type, Key, Priv, OrberDef, Flags}|
- Rest])} |
- set_orbfield_1(P, OrberDef)];
- _ ->
- [#'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB} | set_orbfield_1(P, OrberDef)]
- end;
-set_orbfield_1([PB| P], OrberDef) ->
- [PB | set_orbfield_1(P, OrberDef)].
-
-%%-----------------------------------------------------------------
-%% Func: get_flagfield/1
-%%-----------------------------------------------------------------
-get_flagfield(#'IOP_IOR'{profiles=P}) ->
- get_flagfield_1(P);
-get_flagfield({_Id, _Type, _Key, _UserDef, _OrberDef, Flags}) ->
- Flags.
-
-get_flagfield_1([]) ->
- orber:dbg("[~p] iop_ior:get_flagfield_1([]); bad object key, profile not found.",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO});
-get_flagfield_1([#'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB}|_]) ->
- [_, _, _, _, ObjectKey | _] = tuple_to_list(PB),
- case ObjectKey of
- {_Id, _Type, _Key, _UserDef, _OrberDef, Flags} ->
- Flags;
- _ ->
- orber:dbg("[~p] iop_ior:get_flagfield_1(~p); bad object key.",
- [?LINE, ObjectKey], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO})
- end;
-get_flagfield_1([_| P]) ->
- get_flagfield_1(P).
-
-%%-----------------------------------------------------------------
-%% Func: set_flagfield/2
-%%-----------------------------------------------------------------
-set_flagfield(#'IOP_IOR'{type_id=Id, profiles=P}, Flags) ->
- #'IOP_IOR'{type_id=Id, profiles=set_flagfield_1(P, Flags)};
-set_flagfield({Id, Type, Key, Priv, OrberDef, _}, Flags) ->
- {Id, Type, Key, Priv, OrberDef, Flags}.
-
-set_flagfield_1([], _) ->
- orber:dbg("[~p] iop_ior:set_flagfield_1([]); bad object key, profile not found or external object.",
- [?LINE], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO});
-set_flagfield_1([#'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB}| P], Flags) ->
- [RecName, Version, Host, IIOP_port, ObjectKey | Rest] = tuple_to_list(PB),
- case ObjectKey of
- {Id, Type, Key, Priv, OrberDef, _} ->
- [#'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP,
- profile_data=list_to_tuple([RecName,
- Version, Host,
- IIOP_port,
- {Id, Type, Key, Priv, OrberDef, Flags}|
- Rest])} |
- set_flagfield_1(P, Flags)];
- _ ->
- [#'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB} | set_flagfield_1(P, Flags)]
- end;
-set_flagfield_1([PB| P], Flags) ->
- [PB | set_flagfield_1(P, Flags)].
-
-%%-----------------------------------------------------------------
-%% Func: check_nil/1
-%%-----------------------------------------------------------------
-check_nil(#'IOP_IOR'{type_id="", profiles=[]}) ->
- true;
-check_nil({Id, _, _, _, _, _}) when is_atom(Id) ->
- false;
-check_nil({Id, _, _, _, _, _}) ->
- case binary_to_list(Id) of
- "" ->
- true;
- _ ->
- false
- end;
-check_nil(_) ->
- false.
-
-
-
-%%----------------------------------------------------------------------
-%% Function : print
-%% Arguments : An object represented as one of the following:
-%% - local (tuple)
-%% - IOR
-%% - stringified IOR
-%% - corbaloc- or corbaname-schema
-%% IoDevice - the same as the io-module defines.
-%% Returns :
-%% Description: Prints the object's components.
-%%----------------------------------------------------------------------
-print(Object) ->
- print(undefined, Object).
-print(IoDevice, #'IOP_IOR'{type_id="", profiles=[]}) ->
- print_it(IoDevice,
- "================== IOR ====================~n"
- "NIL Object Reference.~n"
- "================== END ====================~n");
-print(IoDevice, IORStr) when is_list(IORStr) ->
- IOR = corba:string_to_object(IORStr),
- print_helper(IoDevice, IOR);
-print(IoDevice, IOR) when is_record(IOR, 'IOP_IOR') ->
- print_helper(IoDevice, IOR);
-print(IoDevice, {Mod, Type, Key, UserDef, OrberDef, Flags}) ->
- EnvFlags = orber:get_flags(),
- MC = case ?ORB_FLAG_TEST(EnvFlags, ?ORB_ENV_EXCLUDE_CODESET_COMPONENT) of
- true ->
- [];
- false ->
- [#'IOP_TaggedComponent'{tag=?TAG_CODE_SETS,
- component_data=?DEFAULT_CODESETS}]
- end,
- IOR = case ?ORB_FLAG_TEST(EnvFlags, ?ORB_ENV_ENABLE_NAT) of
- false ->
- create(orber:giop_version(), Mod:typeID(), orber:host(),
- orber:iiop_port(), orber:iiop_ssl_port(),
- {Mod, Type, Key, UserDef, OrberDef, Flags},
- MC, Flags, EnvFlags);
- true ->
- create(orber:giop_version(), Mod:typeID(), orber:nat_host(),
- orber:nat_iiop_port(), orber:nat_iiop_ssl_port(),
- {Mod, Type, Key, UserDef, OrberDef, Flags},
- MC, Flags, EnvFlags)
-
- end,
- print_helper(IoDevice, IOR);
-print(_, _) ->
- exit("Bad parameter").
-
-print_helper(IoDevice, #'IOP_IOR'{type_id=TypeID, profiles=Profs}) ->
- Data = io_lib:format("================== IOR ====================~n"
- "------------------ IFR ID -----------------~n~s~n",
- [TypeID]),
- NewData = print_profiles(Profs, []),
- print_it(IoDevice, lists:flatten([Data|NewData])).
-
-print_profiles([], Acc) ->
- lists:flatten([Acc | io_lib:format("================== END ====================~n", [])]);
-print_profiles([#'IOP_TaggedProfile'
- {tag=?TAG_INTERNET_IOP,
- profile_data = #'IIOP_ProfileBody_1_0'{iiop_version=
- #'IIOP_Version'{major=Major,
- minor=Minor},
- host=Host, port=Port,
- object_key=Objkey}}|T], Acc) ->
- Profile = io_lib:format("~n------------------ IIOP Profile -----------~n"
- "Version.............: ~p.~p~n"
- "Host................: ~s~n"
- "Port................: ~p~n",
- [Major, Minor, Host, Port]),
- ObjKeyStr = print_objkey(Objkey),
- print_profiles(T, [Profile, ObjKeyStr | Acc]);
-print_profiles([#'IOP_TaggedProfile'
- {tag=?TAG_INTERNET_IOP,
- profile_data = #'IIOP_ProfileBody_1_1'{iiop_version=
- #'IIOP_Version'{major=Major,
- minor=Minor},
- host=Host,
- port=Port,
- object_key=Objkey,
- components=Components}}|T], Acc) ->
- Profile = io_lib:format("~n------------------ IIOP Profile -----------~n"
- "Version.............: ~p.~p~n"
- "Host................: ~s~n"
- "Port................: ~p~n",
- [Major, Minor, Host, Port]),
- ComponentsStr = print_components(Components, []),
- ObjKeyStr = print_objkey(Objkey),
- print_profiles(T, [Profile, ObjKeyStr, ComponentsStr |Acc]);
-print_profiles([#'IOP_TaggedProfile'{tag=?TAG_MULTIPLE_COMPONENTS,
- profile_data = Components}|T], Acc) ->
- MComp = io_lib:format("~n------------------ Multiple Components ----~n", []),
- ComponentsStr = print_components(Components, []),
- print_profiles(T, [MComp, ComponentsStr | Acc]);
-print_profiles([#'IOP_TaggedProfile'{tag=?TAG_SCCP_IOP,
- profile_data = _Data}|T], Acc) ->
- SCCP = io_lib:format("~n------------------ SCCP IOP ---------------~n", []),
- print_profiles(T, [SCCP | Acc]);
-print_profiles([#'IOP_TaggedProfile'{tag=Tag,
- profile_data = Data}|T], Acc) ->
- TAG = io_lib:format("~n------------------ TAG ~p -----------------~n"
- "Data................: ~p~n", [Tag, Data]),
- print_profiles(T, [TAG|Acc]).
-
-print_components([], Data) -> lists:flatten(lists:reverse(Data));
-print_components([#'IOP_TaggedComponent'{tag=?TAG_ORB_TYPE,
- component_data=ORB}|T], Data) ->
- OType = io_lib:format(" TAG_ORB_TYPE~n"
- "ORB Type............: ~p~n", [ORB]),
- print_components(T, [OType | Data]);
-print_components([#'IOP_TaggedComponent'{tag=?TAG_CODE_SETS,
- component_data=
- #'CONV_FRAME_CodeSetComponentInfo'
- {'ForCharData' = Char,
- 'ForWcharData' = Wchar}}|T], Data) ->
- CharSet = io_lib:format(" TAG_CODE_SETS~n"
- "Native Char.........: ~p~n"
- "Char Conversion.....: ~p~n"
- "Native Wchar........: ~p~n"
- "Wchar Conversion....: ~p~n",
- [Char#'CONV_FRAME_CodeSetComponent'.native_code_set,
- Char#'CONV_FRAME_CodeSetComponent'.conversion_code_sets,
- Wchar#'CONV_FRAME_CodeSetComponent'.native_code_set,
- Wchar#'CONV_FRAME_CodeSetComponent'.conversion_code_sets]),
- print_components(T, [CharSet | Data]);
-print_components([#'IOP_TaggedComponent'{tag=?TAG_ALTERNATE_IIOP_ADDRESS,
- component_data=#'ALTERNATE_IIOP_ADDRESS'
- {'HostID'=Host, 'Port'=Port}}|T], Data) ->
- AltAddr = io_lib:format(" TAG_ALTERNATE_IIOP_ADDRESS~n"
- "Alternate Address...: ~s:~p~n", [Host, Port]),
- print_components(T, [AltAddr | Data]);
-print_components([#'IOP_TaggedComponent'{tag=?TAG_SSL_SEC_TRANS,
- component_data=#'SSLIOP_SSL'
- {target_supports=Supports,
- target_requires=Requires,
- port=Port}}|T], Data) ->
- SSL = io_lib:format(" TAG_SSL_SEC_TRANS~n"
- "SSL Port............: ~p~n"
- "SSL Requires........: ~p~n"
- "SSL Supports........: ~p~n", [Port, Requires, Supports]),
- print_components(T, [SSL | Data]);
-%% Fault Tolerant Components
-print_components([#'IOP_TaggedComponent'{tag=?TAG_FT_GROUP,
- component_data=#'FT_TagFTGroupTaggedComponent'
- {version = Version,
- ft_domain_id = DomainId,
- object_group_id = ObjectGroupId,
- object_group_ref_version = ObjGrRefVer}}|T], Data) ->
- Comp = io_lib:format(" TAG_FT_GROUP~n"
- "Version.............: ~p~n"
- "Domain Id...........: ~p~n"
- "Obj Group Id........: ~p~n"
- "Obj Group Ref Ver...: ~p~n",
- [Version, DomainId, ObjectGroupId, ObjGrRefVer]),
- print_components(T, [Comp | Data]);
-print_components([#'IOP_TaggedComponent'{tag=?TAG_FT_PRIMARY,
- component_data=#'FT_TagFTPrimaryTaggedComponent'
- {primary = Primary}}|T], Data) ->
- Comp = io_lib:format(" TAG_FT_PRIMARY~n"
- "Primary.............: ~p~n", [Primary]),
- print_components(T, [Comp | Data]);
-print_components([#'IOP_TaggedComponent'{tag=?TAG_FT_HEARTBEAT_ENABLED,
- component_data=#'FT_TagFTHeartbeatEnabledTaggedComponent'
- {heartbeat_enabled = HBE}}|T], Data) ->
- Comp = io_lib:format(" TAG_FT_HEARTBEAT_ENABLED~n"
- "Heart Beat Enabled..: ~p~n", [HBE]),
- print_components(T, [Comp | Data]);
-%% Security - CSIIOP
-print_components([#'IOP_TaggedComponent'{tag=?TAG_CSI_SEC_MECH_LIST,
- component_data=#'CSIIOP_CompoundSecMechList'
- {stateful=Stateful,
- mechanism_list = MechList}}|T], Data) ->
- Comp = io_lib:format(" TAG_CSI_SEC_MECH_LIST~n"
- "Stateful............: ~p~n"
- "Mechanisms..........: ~p~n", [Stateful, MechList]),
- print_components(T, [Comp | Data]);
-print_components([#'IOP_TaggedComponent'{tag=?TAG_TLS_SEC_TRANS,
- component_data=#'CSIIOP_TLS_SEC_TRANS'
- {target_supports = TargetS,
- target_requires = TargetR,
- addresses = Addresses}}|T], Data) ->
- Comp = io_lib:format(" TAG_TLS_SEC_TRANS~n"
- "Target Supports.....: ~p~n"
- "Target Requires.....: ~p~n"
- "Addresses...........: ~p~n",
- [TargetS, TargetR, Addresses]),
- print_components(T, [Comp | Data]);
-print_components([#'IOP_TaggedComponent'{tag=?TAG_SECIOP_SEC_TRANS,
- component_data=#'CSIIOP_SECIOP_SEC_TRANS'
- {target_supports = TargetS,
- target_requires = TargetR,
- mech_oid = MechOID,
- target_name = TargetName,
- addresses = Addresses}}|T], Data) ->
- Comp = io_lib:format(" TAG_SECIOP_SEC_TRANS~n"
- "Target Supports.....: ~p~n"
- "Target Requires.....: ~p~n"
- "Mechanism OID.......: ~p~n"
- "Target Name.........: ~p~n"
- "Addresses...........: ~p~n",
- [TargetS, TargetR, MechOID, TargetName, Addresses]),
- print_components(T, [Comp | Data]);
-%% Unused components.
-print_components([#'IOP_TaggedComponent'{tag=TAG,
- component_data=CData}|T], Data) ->
- Unused = io_lib:format("Unused Component....: ~s~n", [match_tag(TAG)]),
- Octets = print_octets(CData, [], 1, []),
- print_components(T, [lists:flatten([Unused | Octets])| Data]).
-
-
-print_objkey(Objkey) when is_tuple(Objkey) ->
- io_lib:format("Local Object........:~n~p~n", [Objkey]);
-print_objkey(Objkey) ->
- Hdr = io_lib:format("External Object.....: ~n", []),
- Octets = print_octets(Objkey, [], 1, []),
- lists:flatten([Hdr | Octets]).
-
-print_octets([], [], _, Data) ->
- lists:reverse(Data);
-print_octets([], Acc, C, Data) ->
- Filling = lists:duplicate((4*(9-C)), 32),
- FData = io_lib:format("~s", [Filling]),
- Rest = io_lib:format(" ~p~n", [lists:reverse(Acc)]),
- [lists:reverse(Data), FData | Rest];
-print_octets([H|T], Acc, 8, Data) when H > 31 , H < 127 ->
- D1 = io_lib:format("~4w", [H]),
- D2 = io_lib:format(" ~p~n", [lists:reverse([H|Acc])]),
- print_octets(T, [], 1, [D2, D1 | Data]);
-print_octets([H|T], Acc, 1, Data) when H > 31 , H < 127 ->
- D1 = io_lib:format("~3w", [H]),
- print_octets(T, [H|Acc], 2, [D1 | Data]);
-print_octets([H|T], Acc, C, Data) when H > 31 , H < 127 ->
- D1 = io_lib:format("~4w", [H]),
- print_octets(T, [H|Acc], C+1, [D1 | Data]);
-print_octets([H|T], Acc, 8, Data) ->
- D1 = io_lib:format("~4w", [H]),
- D2 = io_lib:format(" ~p~n", [lists:reverse([$.|Acc])]),
- print_octets(T, [], 1, [D2, D1 | Data]);
-print_octets([H|T], Acc, 1, Data) ->
- D1 = io_lib:format("~3w", [H]),
- print_octets(T, [$.|Acc], 2, [D1|Data]);
-print_octets([H|T], Acc, C, Data) ->
- D1 = io_lib:format("~4w", [H]),
- print_octets(T, [$.|Acc], C+1, [D1|Data]).
-
-print_it(undefined, Data) ->
- io:format(Data);
-print_it(error_report, Data) ->
- error_logger:error_report(Data);
-print_it(info_msg, Data) ->
- error_logger:info_msg(Data);
-print_it(string, Data) ->
- lists:flatten(Data);
-print_it({error_report, Msg}, Data) ->
- error_logger:error_report(io_lib:format("================== Reason =================~n~s~n~s",
- [Msg, Data]));
-print_it({info_msg, Msg}, Data) ->
- error_logger:info_msg(io_lib:format("================== Comment ================~n~s~n~s",
- [Msg, Data]));
-print_it(IoDevice, Data) ->
- io:format(IoDevice, Data, []).
-
-match_tag(?TAG_ORB_TYPE) -> ?TAG_ORB_TYPE_STR;
-match_tag(?TAG_CODE_SETS) -> ?TAG_CODE_SETS_STR;
-match_tag(?TAG_POLICIES) -> ?TAG_POLICIES_STR;
-match_tag(?TAG_ALTERNATE_IIOP_ADDRESS) -> ?TAG_ALTERNATE_IIOP_ADDRESS_STR;
-match_tag(?TAG_COMPLETE_OBJECT_KEY) -> ?TAG_COMPLETE_OBJECT_KEY_STR;
-match_tag(?TAG_ENDPOINT_ID_POSITION) -> ?TAG_ENDPOINT_ID_POSITION_STR;
-match_tag(?TAG_LOCATION_POLICY) -> ?TAG_LOCATION_POLICY_STR;
-match_tag(?TAG_ASSOCIATION_OPTIONS) -> ?TAG_ASSOCIATION_OPTIONS_STR;
-match_tag(?TAG_SEC_NAME) -> ?TAG_SEC_NAME_STR;
-match_tag(?TAG_SPKM_1_SEC_MECH) -> ?TAG_SPKM_1_SEC_MECH_STR;
-match_tag(?TAG_SPKM_2_SEC_MECH) -> ?TAG_SPKM_2_SEC_MECH_STR;
-match_tag(?TAG_KerberosV5_SEC_MECH) -> ?TAG_KerberosV5_SEC_MECH_STR;
-match_tag(?TAG_CSI_ECMA_Secret_SEC_MECH) -> ?TAG_CSI_ECMA_Secret_SEC_MECH_STR;
-match_tag(?TAG_CSI_ECMA_Hybrid_SEC_MECH) -> ?TAG_CSI_ECMA_Hybrid_SEC_MECH_STR;
-match_tag(?TAG_SSL_SEC_TRANS) -> ?TAG_SSL_SEC_TRANS_STR;
-match_tag(?TAG_CSI_ECMA_Public_SEC_MECH) -> ?TAG_CSI_ECMA_Public_SEC_MECH_STR;
-match_tag(?TAG_GENERIC_SEC_MECH) -> ?TAG_GENERIC_SEC_MECH_STR;
-match_tag(?TAG_FIREWALL_TRANS) -> ?TAG_FIREWALL_TRANS_STR;
-match_tag(?TAG_SCCP_CONTACT_INFO) -> ?TAG_SCCP_CONTACT_INFO_STR;
-match_tag(?TAG_JAVA_CODEBASE) -> ?TAG_JAVA_CODEBASE_STR;
-match_tag(?TAG_TRANSACTION_POLICY) -> ?TAG_TRANSACTION_POLICY_STR;
-match_tag(?TAG_FT_GROUP) -> ?TAG_FT_GROUP_STR;
-match_tag(?TAG_FT_PRIMARY) -> ?TAG_FT_PRIMARY_STR;
-match_tag(?TAG_FT_HEARTBEAT_ENABLED) -> ?TAG_FT_HEARTBEAT_ENABLED_STR;
-match_tag(?TAG_MESSAGE_ROUTERS) -> ?TAG_MESSAGE_ROUTERS_STR;
-match_tag(?TAG_OTS_POLICY) -> ?TAG_OTS_POLICY_STR;
-match_tag(?TAG_INV_POLICY) -> ?TAG_INV_POLICY_STR;
-match_tag(?TAG_CSI_SEC_MECH_LIST) -> ?TAG_CSI_SEC_MECH_LIST_STR;
-match_tag(?TAG_NULL_TAG) -> ?TAG_NULL_TAG_STR;
-match_tag(?TAG_SECIOP_SEC_TRANS) -> ?TAG_SECIOP_SEC_TRANS_STR;
-match_tag(?TAG_TLS_SEC_TRANS) -> ?TAG_TLS_SEC_TRANS_STR;
-match_tag(?TAG_DCE_STRING_BINDING) -> ?TAG_DCE_STRING_BINDING_STR;
-match_tag(?TAG_DCE_BINDING_NAME) -> ?TAG_DCE_BINDING_NAME_STR;
-match_tag(?TAG_DCE_NO_PIPES) -> ?TAG_DCE_NO_PIPES_STR;
-match_tag(?TAG_DCE_SEC_MECH) -> ?TAG_DCE_SEC_MECH_STR;
-match_tag(?TAG_INET_SEC_TRANS) -> ?TAG_INET_SEC_TRANS_STR;
-match_tag(Tag) -> integer_to_list(Tag).
-
-%%-----------------------------------------------------------------
-%% Func: string_code/1
-%%-----------------------------------------------------------------
-string_code(IOR) ->
- Flags = orber:get_flags(),
- case ?ORB_FLAG_TEST(Flags, ?ORB_ENV_ENABLE_NAT) of
- false ->
- string_code(IOR, Flags, orber:host(),
- orber:iiop_port(), orber:iiop_ssl_port());
- true ->
- string_code(IOR, Flags, orber:nat_host(),
- orber:nat_iiop_port(), orber:nat_iiop_ssl_port())
- end.
-
-string_code(IOR, Host) ->
- Flags = orber:get_flags(),
- case ?ORB_FLAG_TEST(Flags, ?ORB_ENV_ENABLE_NAT) of
- false ->
- string_code(IOR, Flags, Host,
- orber:iiop_port(), orber:iiop_ssl_port());
- true ->
- string_code(IOR, Flags, Host,
- orber:nat_iiop_port(), orber:nat_iiop_ssl_port())
- end.
-
-string_code(IOR, Host, Port) ->
- Flags = orber:get_flags(),
- case ?ORB_FLAG_TEST(Flags, ?ORB_ENV_ENABLE_NAT) of
- false ->
- string_code(IOR, Flags, Host, Port, orber:iiop_ssl_port());
- true ->
- string_code(IOR, Flags, Host, Port, orber:nat_iiop_ssl_port())
- end.
-
-string_code(IOR, Host, Port, SSLPort) ->
- string_code(IOR, orber:get_flags(), Host, Port, SSLPort).
-
-string_code(IOR, Flags, IP, Port, SSLPort) ->
- Env = #giop_env{version = orber:giop_version(),
- flags = Flags, host = IP, iiop_port = Port,
- iiop_ssl_port = SSLPort, domain = orber:domain(),
- partial_security = orber:partial_security()},
- {IorByteSeq0, Length0} = cdr_encode:enc_type('tk_octet', Env, 0, [], 0),
- {IorByteSeq, _} = code(Env, IOR, IorByteSeq0, Length0),
- IorByteSeq1 = binary_to_list(list_to_binary(lists:reverse(IorByteSeq))),
- IorHexSeq = bytestring_to_hexstring(IorByteSeq1),
- [$I,$O,$R,$: | IorHexSeq].
-
-%%-----------------------------------------------------------------
-%% Func: code/3
-%%-----------------------------------------------------------------
-code(#giop_env{version = Version} = Env, #'IOP_IOR'{type_id=TypeId, profiles=Profiles}, Bytes, Len) ->
- ProfileSeq =code_profile_datas(Version, Profiles),
- %% Byte order
- cdr_encode:enc_type(?IOR_TYPEDEF,
- Env,
- #'IOP_IOR'{type_id=TypeId, profiles=ProfileSeq},
- Bytes, Len);
-%% No Local Interface supplied. Use configuration parameters.
-code(#giop_env{version = Version, host = 0, flags = EnvFlags} = Env,
- {Mod, Type, Key, UserDef, OrberDef, Flags}, Bytes, Len) ->
- MC = case ?ORB_FLAG_TEST(EnvFlags, ?ORB_ENV_EXCLUDE_CODESET_COMPONENT) of
- true ->
- [];
- false ->
- [#'IOP_TaggedComponent'{tag=?TAG_CODE_SETS,
- component_data=?DEFAULT_CODESETS}]
- end,
- IOR = case ?ORB_FLAG_TEST(EnvFlags, ?ORB_ENV_ENABLE_NAT) of
- false ->
- create(Version, Mod:typeID(), orber_env:host(),
- orber_env:iiop_port(), orber_env:iiop_ssl_port(),
- {Mod, Type, Key, UserDef, OrberDef, Flags},
- MC, Flags, EnvFlags);
- true ->
- create(Version, Mod:typeID(), orber_env:nat_host(),
- orber_env:nat_iiop_port(), orber_env:nat_iiop_ssl_port(),
- {Mod, Type, Key, UserDef, OrberDef, Flags},
- MC, Flags, EnvFlags)
-
- end,
- code(Env, IOR, Bytes, Len);
-code(#giop_env{version = Version, host = Host, iiop_port = IIOPort,
- iiop_ssl_port = SSLPort, flags = EnvFlags} = Env,
- {Mod, Type, Key, UserDef, OrberDef, Flags}, Bytes, Len) ->
- MC = case ?ORB_FLAG_TEST(EnvFlags, ?ORB_ENV_EXCLUDE_CODESET_COMPONENT) of
- true ->
- [];
- false ->
- [#'IOP_TaggedComponent'{tag=?TAG_CODE_SETS,
- component_data=?DEFAULT_CODESETS}]
- end,
- IOR = case ?ORB_FLAG_TEST(EnvFlags, ?ORB_ENV_ENABLE_NAT) of
- false ->
- create(Version, Mod:typeID(), Host, check_port(IIOPort, normal),
- check_port(SSLPort, ssl),
- {Mod, Type, Key, UserDef, OrberDef, Flags},
- MC, Flags, EnvFlags);
- true ->
- create(Version, Mod:typeID(), orber_env:nat_host(Host),
- orber_env:nat_iiop_port(check_port(IIOPort, normal)),
- orber_env:nat_iiop_ssl_port(check_port(SSLPort, ssl)),
- {Mod, Type, Key, UserDef, OrberDef, Flags},
- MC, Flags, EnvFlags)
- end,
- code(Env, IOR, Bytes, Len).
-
-check_port(Port, _Type) when is_integer(Port) ->
- Port;
-check_port(_, normal) ->
- orber:iiop_port();
-check_port(_, ssl) ->
- orber:iiop_ssl_port().
-
-code_profile_datas(_, []) ->
- [];
-code_profile_datas(Version, [#'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=P} | Profiles]) ->
- NewBytes = list_to_binary(code_profile_data(Version, P)),
- [#'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=NewBytes} |
- code_profile_datas(Version, Profiles)];
-%% Multiple Components
-code_profile_datas(Version, [#'IOP_TaggedProfile'{tag=?TAG_MULTIPLE_COMPONENTS,
- profile_data=P} | Profiles]) ->
- Comps= code_comp(Version, P, []),
- {Bytes, Length} = cdr_encode:enc_type('tk_octet', Version, 0, [], 0),
- {Bytes1, _Length1} = cdr_encode:enc_type(?IOP_TAGGEDCOMPONENT_SEQ, Version, Comps, Bytes, Length),
- Profs = binary_to_list(list_to_binary(lists:reverse(Bytes1))),
- [#'IOP_TaggedProfile'{tag=?TAG_MULTIPLE_COMPONENTS,
- profile_data=Profs}| code_profile_datas(Version, Profiles)];
-code_profile_datas(Version, [#'IOP_TaggedProfile'{tag=N, profile_data=P} | Profiles]) ->
- [#'IOP_TaggedProfile'{tag=N, profile_data=P} | code_profile_datas(Version, Profiles)];
-code_profile_datas(_, Data) ->
- orber:dbg("[~p] iop_ior:code_profile_datas(~p); unsupported TaggedProfile.",
- [?LINE, Data], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO}).
-
-code_profile_data(Version, ProfileData) ->
- [RecTag, V, H, P, O |Rest] = tuple_to_list(ProfileData),
- {Bytes, Length} = cdr_encode:enc_type('tk_octet', Version, 0, [], 0),
- {Bytes1, Length1} = cdr_encode:enc_type(?IIOP_VERSION, Version, V, Bytes, Length),
- {Bytes2, Length2} = cdr_encode:enc_type({'tk_string', 0}, Version,
- H, Bytes1, Length1),
- {Bytes3, Length3} = cdr_encode:enc_type('tk_ushort', Version, P, Bytes2, Length2),
- {Bytes4, Length4} = cdr_encode:enc_type({'tk_sequence', 'tk_octet', 0}, Version,
- corba:objkey_to_string(O), Bytes3, Length3),
- {Bytes5, _Length5} = code_profile_data_1(Version, RecTag, Rest, Bytes4, Length4),
- Bytes6 = lists:reverse(Bytes5),
- lists:flatten(Bytes6).
-
-code_profile_data_1(_Version, 'IIOP_ProfileBody_1_0', [], Bytes, Length) ->
- {Bytes, Length};
-code_profile_data_1(Version, 'IIOP_ProfileBody_1_1', [TaggedComponentSeq], Bytes, Length) ->
- Comps = code_comp(Version, TaggedComponentSeq, []),
- cdr_encode:enc_type(?IOP_TAGGEDCOMPONENT_SEQ, Version, Comps, Bytes, Length);
-code_profile_data_1(_,V,S,_,_) ->
- orber:dbg("[~p] iop_ior:code_profile_datas(~p, ~p); probably unsupported IIOP-version",
- [?LINE, V, S], ?DEBUG_LEVEL),
- corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}).
-
-code_comp(_Version, [], CompData) ->
- CompData;
-code_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_CODE_SETS,
- component_data=CodeSet}|Comps], CompData) ->
- {Bytes0, Len0} = cdr_encode:enc_type('tk_octet', Version, 0, [], 0),
- {Bytes1, _Len1} = cdr_encode:enc_type(?CONV_FRAME_CODESETCOMPONENTINFO, Version,
- CodeSet, Bytes0, Len0),
- Bytes = binary_to_list(list_to_binary(lists:reverse(Bytes1))),
- code_comp(Version, Comps, [#'IOP_TaggedComponent'{tag=?TAG_CODE_SETS,
- component_data=Bytes}|CompData]);
-code_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_ORB_TYPE,
- component_data=ORBType}|Comps], CompData) ->
- {Bytes0, Len0} = cdr_encode:enc_type('tk_octet', Version, 0, [], 0),
- {Bytes1, _Len1} = cdr_encode:enc_type(?ORB_TYPE, Version,
- ORBType, Bytes0, Len0),
- Bytes = binary_to_list(list_to_binary(lists:reverse(Bytes1))),
- code_comp(Version, Comps, [#'IOP_TaggedComponent'{tag=?TAG_ORB_TYPE,
- component_data=Bytes}|CompData]);
-code_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_ALTERNATE_IIOP_ADDRESS,
- component_data=AltAddr}|Comps], CompData) ->
- {Bytes0, Len0} = cdr_encode:enc_type('tk_octet', Version, 0, [], 0),
- {Bytes1, _Len1} = cdr_encode:enc_type(?ALTERNATE_IIOP_ADDRESS, Version,
- AltAddr, Bytes0, Len0),
- Bytes = binary_to_list(list_to_binary(lists:reverse(Bytes1))),
- code_comp(Version, Comps, [#'IOP_TaggedComponent'{tag=?TAG_ALTERNATE_IIOP_ADDRESS,
- component_data=Bytes}|CompData]);
-code_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_SSL_SEC_TRANS,
- component_data=SSLStruct}|Comps], CompData) ->
- {Bytes0, Len0} = cdr_encode:enc_type('tk_octet', Version, 0, [], 0),
- {Bytes1, _Len1} = cdr_encode:enc_type(?SSLIOP_SSL, Version,
- SSLStruct, Bytes0, Len0),
- Bytes = binary_to_list(list_to_binary(lists:reverse(Bytes1))),
- code_comp(Version, Comps, [#'IOP_TaggedComponent'{tag=?TAG_SSL_SEC_TRANS,
- component_data=Bytes}|CompData]);
-%% Fault Tolerant Components
-code_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_FT_GROUP,
- component_data=Data}|Comps], CompData) ->
- {Bytes0, Len0} = cdr_encode:enc_type('tk_octet', Version, 0, [], 0),
- {Bytes1, _Len1} = cdr_encode:enc_type(?FT_TagFTGroupTaggedComponent, Version,
- Data, Bytes0, Len0),
- Bytes = binary_to_list(list_to_binary(lists:reverse(Bytes1))),
- code_comp(Version, Comps, [#'IOP_TaggedComponent'{tag=?TAG_FT_GROUP,
- component_data=Bytes}|CompData]);
-code_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_FT_PRIMARY,
- component_data=Data}|Comps], CompData) ->
- {Bytes0, Len0} = cdr_encode:enc_type('tk_octet', Version, 0, [], 0),
- {Bytes1, _Len1} = cdr_encode:enc_type(?FT_TagFTPrimaryTaggedComponent, Version,
- Data, Bytes0, Len0),
- Bytes = binary_to_list(list_to_binary(lists:reverse(Bytes1))),
- code_comp(Version, Comps, [#'IOP_TaggedComponent'{tag=?TAG_FT_PRIMARY,
- component_data=Bytes}|CompData]);
-code_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_FT_HEARTBEAT_ENABLED,
- component_data=Data}|Comps], CompData) ->
- {Bytes0, Len0} = cdr_encode:enc_type('tk_octet', Version, 0, [], 0),
- {Bytes1, _Len1} = cdr_encode:enc_type(?FT_TagFTHeartbeatEnabledTaggedComponent, Version,
- Data, Bytes0, Len0),
- Bytes = binary_to_list(list_to_binary(lists:reverse(Bytes1))),
- code_comp(Version, Comps, [#'IOP_TaggedComponent'{tag=?TAG_FT_HEARTBEAT_ENABLED,
- component_data=Bytes}|CompData]);
-%% Security - CSIIOP
-code_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_CSI_SEC_MECH_LIST,
- component_data=Data}|Comps], CompData) ->
- NewData = Data#'CSIIOP_CompoundSecMechList'
- {mechanism_list = code_sec_mech(Version,
- Data#'CSIIOP_CompoundSecMechList'.mechanism_list,
- [])},
- {Bytes0, Len0} = cdr_encode:enc_type('tk_octet', Version, 0, [], 0),
- {Bytes1, _Len1} = cdr_encode:enc_type(?CSIIOP_CompoundSecMechList, Version,
- NewData, Bytes0, Len0),
- Bytes = binary_to_list(list_to_binary(lists:reverse(Bytes1))),
- code_comp(Version, Comps, [#'IOP_TaggedComponent'{tag=?TAG_CSI_SEC_MECH_LIST,
- component_data=Bytes}|CompData]);
-code_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_TLS_SEC_TRANS,
- component_data=Data}|Comps],
- CompData) ->
- {Bytes0, Len0} = cdr_encode:enc_type('tk_octet', Version, 0, [], 0),
- {Bytes1, _Len1} = cdr_encode:enc_type(?CSIIOP_TLS_SEC_TRANS, Version,
- Data, Bytes0, Len0),
- Bytes = binary_to_list(list_to_binary(lists:reverse(Bytes1))),
- code_comp(Version, Comps, [#'IOP_TaggedComponent'{tag=?TAG_TLS_SEC_TRANS,
- component_data=Bytes}|CompData]);
-code_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_SECIOP_SEC_TRANS,
- component_data=Data}|Comps], CompData) ->
- {Bytes0, Len0} = cdr_encode:enc_type('tk_octet', Version, 0, [], 0),
- {Bytes1, _Len1} = cdr_encode:enc_type(?CSIIOP_SECIOP_SEC_TRANS, Version,
- Data, Bytes0, Len0),
- Bytes = binary_to_list(list_to_binary(lists:reverse(Bytes1))),
- code_comp(Version, Comps, [#'IOP_TaggedComponent'{tag=?TAG_SECIOP_SEC_TRANS,
- component_data=Bytes}|CompData]);
-code_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_NULL_TAG}|Comps], CompData) ->
- %% The body of the TAG_NULL_TAG component is a sequence of octets of
- %% length 0.
- {Bytes0, Len0} = cdr_encode:enc_type('tk_octet', Version, 0, [], 0),
- {Bytes1, _Len1} = cdr_encode:enc_type({'tk_sequence', 'tk_octet', 0}, Version,
- [], Bytes0, Len0),
- Bytes = binary_to_list(list_to_binary(lists:reverse(Bytes1))),
- code_comp(Version, Comps, [#'IOP_TaggedComponent'{tag=?TAG_NULL_TAG,
- component_data=Bytes}|CompData]);
-%% Unsupported/not used component.
-code_comp(Version, [C|Comps], CompData) ->
- code_comp(Version, Comps, [C|CompData]).
-
-
-code_sec_mech(_, [], Acc) ->
- %% We must preserver the order!!
- lists:reverse(Acc);
-code_sec_mech(Version, [#'CSIIOP_CompoundSecMech'{transport_mech = TagComp} = CSM|T],
- Acc) ->
- [EncTagComp] = code_comp(Version, [TagComp], []),
- code_sec_mech(Version, T, [CSM#'CSIIOP_CompoundSecMech'
- {transport_mech = EncTagComp}|Acc]).
-
-
-%%-----------------------------------------------------------------
-%% Func: string_decode/1
-%%-----------------------------------------------------------------
-string_decode([$I,$O,$R,$: | IorHexSeq]) ->
- Version = orber:giop_version(),
- IorByteSeq = list_to_binary(hexstring_to_bytestring(IorHexSeq)),
- {ByteOrder, IorRest} = cdr_decode:dec_byte_order(IorByteSeq),
- decode(Version, IorRest, 1, ByteOrder);
-string_decode([$i,$o,$r,$: | IorHexSeq]) ->
- Version = orber:giop_version(),
- IorByteSeq = list_to_binary(hexstring_to_bytestring(IorHexSeq)),
- {ByteOrder, IorRest} = cdr_decode:dec_byte_order(IorByteSeq),
- decode(Version, IorRest, 1, ByteOrder);
-string_decode(What) ->
- orber:dbg("[~p] iop_ior:string_decode(~p); Should be IOR:.. or ior:..",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------------
-%% Func: decode/3
-%%-----------------------------------------------------------------
-decode(Version, IorByteSeq, Len, ByteOrder) ->
- {#'IOP_IOR'{type_id=TypeId, profiles=Profiles}, Rest, Length} =
- cdr_decode:dec_type(?IOR_TYPEDEF, Version, IorByteSeq, Len, ByteOrder),
- L = decode_profiles(Version, Profiles),
- {#'IOP_IOR'{type_id=TypeId, profiles=L}, Rest, Length}.
-
-decode_profiles(_, []) ->
- [];
-decode_profiles(Version, [P | Profiles]) ->
- Struct = decode_profile(Version, P),
- L = decode_profiles(Version, Profiles),
- [Struct | L].
-
-decode_profile(Version, #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=ProfileData}) ->
- {ByteOrder, Rest} = cdr_decode:dec_byte_order(list_to_binary(ProfileData)),
- Length = 1,
- {V, Rest1, Length1} = cdr_decode:dec_type(?IIOP_VERSION, Version, Rest, Length,
- ByteOrder),
- {H, Rest2, Length2} = cdr_decode:dec_type({'tk_string', 0}, Version, Rest1, Length1,
- ByteOrder),
- {P, Rest3, Length3} = cdr_decode:dec_type('tk_ushort', Version, Rest2, Length2,
- ByteOrder),
- {ObjKey, Rest4, Length4} = cdr_decode:dec_type({'tk_sequence', 'tk_octet', 0},
- Version, Rest3, Length3,
- ByteOrder),
- Struct = decode_profile_1(V, H, P, ObjKey, Version, Rest4, Length4, ByteOrder),
- #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=Struct};
-%% Multiple Components
-decode_profile(Version, #'IOP_TaggedProfile'{tag=?TAG_MULTIPLE_COMPONENTS,
- profile_data=ProfileData}) ->
- {ByteOrder, Rest} = cdr_decode:dec_byte_order(list_to_binary(ProfileData)),
- {Components, <<>>, _Length1} =cdr_decode:dec_type(?IOP_TAGGEDCOMPONENT_SEQ, Version, Rest, 1, ByteOrder),
- CompData = decode_comp(Version, Components, []),
- #'IOP_TaggedProfile'{tag=?TAG_MULTIPLE_COMPONENTS, profile_data=CompData};
-decode_profile(_, #'IOP_TaggedProfile'{tag=N, profile_data=ProfileData}) ->
- #'IOP_TaggedProfile'{tag=N, profile_data=ProfileData};
-decode_profile(_, Data) ->
- orber:dbg("[~p] iop_ior:decode_profile(~p); unsupported TaggedProfile.",
- [?LINE, Data], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO}).
-
-decode_profile_1(#'IIOP_Version'{major=1, minor=0}, H, P, ObjKey, _Version, _Rest, _Length, _ByteOrder) ->
- #'IIOP_ProfileBody_1_0'{iiop_version=#'IIOP_Version'{major=1,
- minor=0},
- host=H, port=P,
- object_key=corba:string_to_objkey(ObjKey)};
-decode_profile_1(#'IIOP_Version'{major=1, minor=1}, H, P, ObjKey, Version, Rest, Length, ByteOrder) ->
- {Components, <<>>, _Length1} =cdr_decode:dec_type(?IOP_TAGGEDCOMPONENT_SEQ, Version, Rest, Length, ByteOrder),
- CompData = decode_comp(Version, Components, []),
- #'IIOP_ProfileBody_1_1'{iiop_version=#'IIOP_Version'{major=1,
- minor=1},
- host=H, port=P,
- object_key=corba:string_to_objkey(ObjKey),
- components=CompData};
-decode_profile_1(#'IIOP_Version'{major=1, minor=2}, H, P, ObjKey, Version, Rest, Length, ByteOrder) ->
- {Components, <<>>, _Length1} =cdr_decode:dec_type(?IOP_TAGGEDCOMPONENT_SEQ, Version, Rest, Length, ByteOrder),
- CompData = decode_comp(Version, Components, []),
- #'IIOP_ProfileBody_1_1'{iiop_version=#'IIOP_Version'{major=1,
- minor=2},
- host=H, port=P,
- object_key=corba:string_to_objkey(ObjKey),
- components=CompData};
-decode_profile_1(V, _, _, _, _, _, _,_) ->
- orber:dbg("[~p] iop_ior:decode_profile_1(~p); probably unsupported IIOP-version.",
- [?LINE, V], ?DEBUG_LEVEL),
- corba:raise(#'NO_IMPLEMENT'{completion_status=?COMPLETED_NO}).
-
-decode_comp(_Version, [], Components) ->
- Components;
-decode_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_CODE_SETS,
- component_data=Bytes}|Comps],
- Components) ->
- {ByteOrder, Rest} = cdr_decode:dec_byte_order(list_to_binary(Bytes)),
- {CodeSet, _, _} = cdr_decode:dec_type(?CONV_FRAME_CODESETCOMPONENTINFO,
- Version, Rest, 1, ByteOrder),
- decode_comp(Version, Comps,
- [#'IOP_TaggedComponent'{tag=?TAG_CODE_SETS,
- component_data=CodeSet}|Components]);
-decode_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_ORB_TYPE,
- component_data=Bytes}|Comps],
- Components) ->
- {ByteOrder, Rest} = cdr_decode:dec_byte_order(list_to_binary(Bytes)),
- {ORBType, _, _} = cdr_decode:dec_type(?ORB_TYPE,
- Version, Rest, 1, ByteOrder),
- decode_comp(Version, Comps,
- [#'IOP_TaggedComponent'{tag=?TAG_ORB_TYPE,
- component_data=ORBType}|Components]);
-decode_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_ALTERNATE_IIOP_ADDRESS,
- component_data=Bytes}|Comps],
- Components) ->
- {ByteOrder, Rest} = cdr_decode:dec_byte_order(list_to_binary(Bytes)),
- {AltIIOP, _, _} = cdr_decode:dec_type(?ALTERNATE_IIOP_ADDRESS,
- Version, Rest, 1, ByteOrder),
- decode_comp(Version, Comps,
- [#'IOP_TaggedComponent'{tag=?TAG_ALTERNATE_IIOP_ADDRESS,
- component_data=AltIIOP}|Components]);
-decode_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_SSL_SEC_TRANS,
- component_data=Data}|Comps], Components) ->
- {ByteOrder, R} = cdr_decode:dec_byte_order(list_to_binary(Data)),
- {SSLStruct, _Rest1, _Length1} = cdr_decode:dec_type(?SSLIOP_SSL, Version, R, 1,
- ByteOrder),
- decode_comp(Version, Comps,
- [#'IOP_TaggedComponent'{tag=?TAG_SSL_SEC_TRANS,
- component_data=SSLStruct}|Components]);
-%% Fault Tolerant Components
-decode_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_FT_GROUP,
- component_data=Data}|Comps], Components) ->
- {ByteOrder, R} = cdr_decode:dec_byte_order(list_to_binary(Data)),
- {DecodedData, _Rest1, _Length1} = cdr_decode:dec_type(?FT_TagFTGroupTaggedComponent, Version, R, 1,
- ByteOrder),
- decode_comp(Version, Comps,
- [#'IOP_TaggedComponent'{tag=?TAG_FT_GROUP,
- component_data=DecodedData}|Components]);
-decode_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_FT_PRIMARY,
- component_data=Data}|Comps], Components) ->
- {ByteOrder, R} = cdr_decode:dec_byte_order(list_to_binary(Data)),
- {DecodedData, _Rest1, _Length1} = cdr_decode:dec_type(?FT_TagFTPrimaryTaggedComponent, Version, R, 1,
- ByteOrder),
- decode_comp(Version, Comps,
- [#'IOP_TaggedComponent'{tag=?TAG_FT_PRIMARY,
- component_data=DecodedData}|Components]);
-decode_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_FT_HEARTBEAT_ENABLED,
- component_data=Data}|Comps], Components) ->
- {ByteOrder, R} = cdr_decode:dec_byte_order(list_to_binary(Data)),
- {DecodedData, _Rest1, _Length1} = cdr_decode:dec_type(?FT_TagFTHeartbeatEnabledTaggedComponent, Version, R, 1,
- ByteOrder),
- decode_comp(Version, Comps,
- [#'IOP_TaggedComponent'{tag=?TAG_FT_HEARTBEAT_ENABLED,
- component_data=DecodedData}|Components]);
-%% Security - CSIIOP
-decode_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_CSI_SEC_MECH_LIST,
- component_data=Data}|Comps], Components) ->
- {ByteOrder, R} = cdr_decode:dec_byte_order(list_to_binary(Data)),
- {DecodedData, _Rest1, _Length1} = cdr_decode:dec_type(?CSIIOP_CompoundSecMechList, Version, R, 1,
- ByteOrder),
- NewDecodedData = DecodedData#'CSIIOP_CompoundSecMechList'
- {mechanism_list = decode_sec_mech(Version,
- DecodedData#'CSIIOP_CompoundSecMechList'.mechanism_list,
- [])},
- decode_comp(Version, Comps,
- [#'IOP_TaggedComponent'{tag=?TAG_CSI_SEC_MECH_LIST,
- component_data=NewDecodedData}|Components]);
-decode_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_TLS_SEC_TRANS,
- component_data=Data}|Comps], Components) ->
- {ByteOrder, R} = cdr_decode:dec_byte_order(list_to_binary(Data)),
- {DecodedData, _Rest1, _Length1} = cdr_decode:dec_type(?CSIIOP_TLS_SEC_TRANS, Version, R, 1,
- ByteOrder),
- decode_comp(Version, Comps,
- [#'IOP_TaggedComponent'{tag=?TAG_TLS_SEC_TRANS,
- component_data=DecodedData}|Components]);
-decode_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_SECIOP_SEC_TRANS,
- component_data=Data}|Comps], Components) ->
- {ByteOrder, R} = cdr_decode:dec_byte_order(list_to_binary(Data)),
- {DecodedData, _Rest1, _Length1} = cdr_decode:dec_type(?CSIIOP_SECIOP_SEC_TRANS, Version, R, 1,
- ByteOrder),
- decode_comp(Version, Comps,
- [#'IOP_TaggedComponent'{tag=?TAG_SECIOP_SEC_TRANS,
- component_data=DecodedData}|Components]);
-decode_comp(Version, [#'IOP_TaggedComponent'{tag=?TAG_NULL_TAG,
- component_data=_Data}|Comps], Components) ->
- %% The body of the TAG_NULL_TAG component is a sequence of octets of
- %% length 0.
- decode_comp(Version, Comps,
- [#'IOP_TaggedComponent'{tag=?TAG_NULL_TAG,
- component_data=[]}|Components]);
-
-decode_comp(Version, [C|Comps], Components) ->
- %% Not used but we cannot discard it.
- decode_comp(Version, Comps, [C|Components]).
-
-
-decode_sec_mech(_Version, [], Acc) ->
- %% We must preserver the order!!
- lists:reverse(Acc);
-decode_sec_mech(Version, [#'CSIIOP_CompoundSecMech'{transport_mech = TagComp} = CSM|T],
- Acc) ->
- [DecTagComp] = decode_comp(Version, [TagComp], []),
- decode_sec_mech(Version, T, [CSM#'CSIIOP_CompoundSecMech'
- {transport_mech = DecTagComp}|Acc]).
-
-
-%%-----------------------------------------------------------------
-%% Func: hexstring_to_bytestring/1
-%%-----------------------------------------------------------------
-hexstring_to_bytestring(HexString) ->
- ByteString = hexstring_to_bytestring(HexString, []),
- lists:reverse(ByteString).
-
-hexstring_to_bytestring([], Acc) ->
- Acc;
-hexstring_to_bytestring([H1, H2 |Rest], Acc) ->
- I1 = hex_to_int(H1),
- I2 = hex_to_int(H2),
- I = I1 * 16 + I2,
- Acc2 = cdrlib:enc_octet(I, Acc),
- hexstring_to_bytestring(Rest, Acc2).
-
-
-hex_to_int(H) when H >= $a ->
- 10 + H - $a;
-hex_to_int(H) when H >= $A ->
- 10 + H -$A;
-hex_to_int(H) ->
- H - $0.
-%%-----------------------------------------------------------------
-%% Func: bytestring_to_hexstring/1
-%% Args: A byte string
-%% Returns: A list of hexadecimal digits (onebyte will be represented as
-%% two hexadecimal digits).
-%%-----------------------------------------------------------------
-bytestring_to_hexstring(ByteString) ->
- HexString = bytestring_to_hexstring(ByteString, []),
- lists:reverse(HexString).
-
-bytestring_to_hexstring([], Acc) ->
- Acc;
-bytestring_to_hexstring([B |Rest], Acc) ->
- [C1, C2] = int_to_hex(B),
- bytestring_to_hexstring(Rest,[C2, C1| Acc]).
-
-int_to_hex(B) when B < 256, B >= 0 ->
- N1 = B div 16,
- N2 = B rem 16,
- [code_character(N1),
- code_character(N2)].
-
-code_character(N) when N < 10 ->
- $0 + N;
-code_character(N) ->
- $a + (N - 10).
-
diff --git a/lib/orber/src/orber.app.src b/lib/orber/src/orber.app.src
deleted file mode 100644
index 217c1b247f..0000000000
--- a/lib/orber/src/orber.app.src
+++ /dev/null
@@ -1,111 +0,0 @@
-{application, orber,
- [{description, "The Erlang ORB application"},
- {vsn, "%VSN%"},
- {modules,
- [
- 'CosNaming_Binding',
- 'CosNaming_BindingIterator',
- 'CosNaming_BindingList',
- 'CosNaming_BindingIterator_impl',
- 'CosNaming_Name',
- 'CosNaming_NameComponent',
- 'CosNaming_NamingContext',
- 'CosNaming_NamingContext_AlreadyBound',
- 'CosNaming_NamingContext_CannotProceed',
- 'CosNaming_NamingContext_InvalidName',
- 'CosNaming_NamingContext_NotEmpty',
- 'CosNaming_NamingContext_NotFound',
- 'CosNaming_NamingContextExt',
- 'CosNaming_NamingContextExt_impl',
- 'CosNaming_NamingContextExt_InvalidAddress',
- 'OrberApp_IFR',
- 'OrberApp_IFR_impl',
- 'oe_OrberIFR',
- 'any',
- 'cdr_decode',
- 'cdr_encode',
- 'cdrlib',
- 'corba',
- 'corba_boa',
- 'corba_object',
- 'erlang_pid',
- 'erlang_port',
- 'erlang_ref',
- 'erlang_binary',
- 'iop_ior',
- 'lname',
- 'lname_component',
- 'oe_CORBA',
- 'oe_cos_naming',
- 'oe_cos_naming_ext',
- 'oe_erlang',
- 'orber',
- 'orber_cosnaming_utils',
- 'orber_ifr',
- 'orber_ifr_aliasdef',
- 'orber_ifr_arraydef',
- 'orber_ifr_attributedef',
- 'orber_ifr_constantdef',
- 'orber_ifr_contained',
- 'orber_ifr_container',
- 'orber_ifr_enumdef',
- 'orber_ifr_exceptiondef',
- 'orber_ifr_idltype',
- 'orber_ifr_interfacedef',
- 'orber_ifr_irobject',
- 'orber_ifr_moduledef',
- 'orber_ifr_operationdef',
- 'orber_ifr_orb',
- 'orber_ifr_primitivedef',
- 'orber_ifr_repository',
- 'orber_ifr_sequencedef',
- 'orber_ifr_stringdef',
- 'orber_ifr_wstringdef',
- 'orber_ifr_structdef',
- 'orber_ifr_typecode',
- 'orber_ifr_typedef',
- 'orber_ifr_uniondef',
- 'orber_ifr_fixeddef',
- 'orber_ifr_utils',
- 'orber_iiop',
- 'orber_iiop_inproxy',
- 'orber_iiop_inrequest',
- 'orber_iiop_insup',
- 'orber_iiop_net',
- 'orber_iiop_net_accept',
- 'orber_iiop_outproxy',
- 'orber_iiop_outsup',
- 'orber_iiop_pm',
- 'orber_iiop_socketsup',
- 'orber_initial_references',
- 'orber_pi',
- 'orber_objectkeys',
- 'orber_request_number',
- 'orber_socket',
- 'orber_tc',
- 'orber_typedefs',
- 'orber_web',
- 'orber_web_server',
- 'orber_iiop_tracer',
- 'orber_iiop_tracer_silent',
- 'orber_iiop_tracer_stealth',
- 'fixed',
- 'orber_exceptions',
- 'orber_diagnostics',
- 'orber_acl',
- 'orber_tb',
- 'orber_env'
- ]
- },
- {registered, [orber_sup, orber_iiop_sup, orber_iiop_net, orber_iiop_outsup,
- orber_iiop_insup, orber_init, orber_reqno,
- orber_objkeyserver, orber_iiop_socketsup,
- orber_iiop_pm, orber_env]},
- {applications, [stdlib, kernel, mnesia]},
- {env, []},
- {mod, {orber, []}},
- {runtime_dependencies, ["stdlib-2.5","ssl-5.3.4","mnesia-4.12","kernel-3.0",
- "inets-5.10","erts-7.0"]}
-]}.
-
-
diff --git a/lib/orber/src/orber.appup.src b/lib/orber/src/orber.appup.src
deleted file mode 100644
index 6c3b2833b7..0000000000
--- a/lib/orber/src/orber.appup.src
+++ /dev/null
@@ -1,7 +0,0 @@
-{"%VSN%",
- [
- ],
- [
- ]
-}.
-
diff --git a/lib/orber/src/orber.erl b/lib/orber/src/orber.erl
deleted file mode 100644
index f5e2429f5d..0000000000
--- a/lib/orber/src/orber.erl
+++ /dev/null
@@ -1,1238 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber.erl
-%%
-%% Description:
-%% This file contains the Orber application interface
-%%
-%%-----------------------------------------------------------------
--module(orber).
-
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/src/ifr_objects.hrl").
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([start/0, start/1, stop/0, install/1, install/2, orber_nodes/0, iiop_port/0,
- domain/0, iiop_ssl_port/0, iiop_out_ports/0, iiop_out_ports_random/0,
- iiop_out_ports_attempts/0,
- ssl_server_options/0, ssl_client_options/0, set_ssl_client_options/1,
- ssl_server_certfile/0, ssl_client_certfile/0, set_ssl_client_certfile/1,
- ssl_server_verify/0, ssl_client_verify/0, set_ssl_client_verify/1,
- ssl_server_depth/0, ssl_client_depth/0, set_ssl_client_depth/1,
- ssl_server_cacertfile/0,ssl_client_cacertfile/0, set_ssl_client_cacertfile/1,
- ssl_client_keyfile/0, ssl_client_password/0, ssl_server_keyfile/0, ssl_server_password/0,
- ssl_client_ciphers/0, ssl_server_ciphers/0, ssl_client_cachetimeout/0, ssl_server_cachetimeout/0,
- uninstall/0, giop_version/0, info/0, info/1, is_running/0, add_node/2,
- remove_node/1, iiop_timeout/0, iiop_connection_timeout/0,
- iiop_setup_connection_timeout/0, objectkeys_gc_time/0,
- is_lightweight/0, get_lightweight_nodes/0,
- start_lightweight/0, start_lightweight/1,
- get_ORBDefaultInitRef/0, get_ORBInitRef/0,
- get_interceptors/0, get_local_interceptors/0,
- get_cached_interceptors/0, set_interceptors/1,
- jump_start/0, jump_start/1, jump_stop/0,
- iiop_connections/0, iiop_connections/1, iiop_connections_pending/0,
- typechecking/0,
- exclude_codeset_ctx/0, exclude_codeset_component/0, bidir_context/0, use_FT/0,
- use_CSIv2/0, get_flags/0, secure/0, multi_jump_start/1, multi_jump_start/2,
- multi_jump_start/3, get_tables/0, iiop_in_connection_timeout/0,
- partial_security/0, nat_iiop_ssl_port/0, nat_iiop_port/0, ip_version/0,
- light_ifr/0, iiop_max_in_requests/0, iiop_max_in_connections/0,
- iiop_max_fragments/0, iiop_backlog/0, iiop_ssl_backlog/0,
- find_sockname_by_peername/2, find_peername_by_sockname/2, iiop_acl/0,
- add_listen_interface/2, add_listen_interface/3, remove_listen_interface/1,
- reconfigure_out_connections/1,
- reconfigure_out_connection/3, reconfigure_out_connection/4,
- reconfigure_in_connections/1, reconfigure_in_connection/2,
- activate_audit_trail/0, activate_audit_trail/1, deactivate_audit_trail/0,
- iiop_ssl_ip_address_local/0, ip_address_local/0,
- close_connection/1, close_connection/2, is_system_exception/1,
- exception_info/1]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([nat_host/0, host/0, ip_address_variable_defined/0, start/2, init/1,
- get_debug_level/0, debug_level_print/3, dbg/3, error/3,
- configure/2, configure_override/2, multi_configure/1,
- mjs/1, mjs/2, js/0, js/1]).
-
-%%-----------------------------------------------------------------
-%% Internal definitions
-%%-----------------------------------------------------------------
-%% Defines possible configuration parameters a user can add when,
-%% for example, installing Orber.
--record(options, {ifr_storage_type = disc_copies,
- install_timeout = infinity,
- local_content = false,
- nameservice_storage_type = ram_copies,
- initialreferences_storage_type = ram_copies,
- type = temporary,
- load_order = 0}).
-
--define(ORBER_TABS, [orber_CosNaming, orber_objkeys, orber_references]).
-
--define(DEBUG_LEVEL, 5).
-
--define(FORMAT(_F, _A), lists:flatten(io_lib:format(_F, _A))).
--define(EFORMAT(_F, _A), exit(lists:flatten(io_lib:format(_F, _A)))).
-
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-
-jump_stop() ->
- stop(),
- uninstall(),
- mnesia:stop().
-
-js() ->
- application:load(orber),
- jump_start([{iiop_port, iiop_port()},
- {interceptors, {native, [orber_iiop_tracer_silent]}},
- {orber_debug_level, 10},
- {flags, (?ORB_ENV_LOCAL_TYPECHECKING bor get_flags())}]).
-
-js(Port) when is_integer(Port) ->
- application:load(orber),
- jump_start([{iiop_port, Port},
- {interceptors, {native, [orber_iiop_tracer_silent]}},
- {orber_debug_level, 10},
- {flags, (?ORB_ENV_LOCAL_TYPECHECKING bor get_flags())}]).
-
-jump_start() ->
- application:load(orber),
- jump_start([{iiop_port, iiop_port()}]).
-
-
-jump_start(Port) when is_integer(Port) ->
- application:load(orber),
- jump_start([{iiop_port, Port}]);
-jump_start(Options) when is_list(Options) ->
- application:load(orber),
- mnesia:start(),
- Port = case lists:keysearch(iiop_port, 1, Options) of
- {value, {iiop_port, Value}} ->
- Value;
- _ ->
- iiop_port()
- end,
- corba:orb_init([{iiop_port, Port}|Options]),
- install([node()], [{ifr_storage_type, ram_copies}]),
- start(),
- %% We need to use this operation if Port == 0 to see what the OS
- %% assigned.
- NewPort = orber_env:iiop_port(),
- Domain = orber_env:ip_address() ++ [$:|integer_to_list(NewPort)],
- orber_env:configure_override(domain, Domain),
- info();
-jump_start(Options) ->
- exit({error, Options}).
-
-
-mjs(Nodes) ->
- application:load(orber),
- multi_js_helper(Nodes, iiop_port(),
- [{interceptors, {native, [orber_iiop_tracer_silent]}},
- {orber_debug_level, 10},
- {flags, (?ORB_ENV_LOCAL_TYPECHECKING bor get_flags())}]).
-
-mjs(Nodes, Port) ->
- application:load(orber),
- multi_js_helper(Nodes, Port,
- [{interceptors, {native, [orber_iiop_tracer_silent]}},
- {orber_debug_level, 10},
- {flags, (?ORB_ENV_LOCAL_TYPECHECKING bor get_flags())}]).
-
-
-multi_jump_start(Nodes) ->
- application:load(orber),
- multi_js_helper(Nodes, iiop_port(), []).
-
-multi_jump_start(Nodes, Port) ->
- multi_js_helper(Nodes, Port, []).
-
-multi_jump_start(Nodes, Port, Options) ->
- multi_js_helper(Nodes, Port, Options).
-
-multi_js_helper(Nodes, Port, InitOptions) when is_list(Nodes) andalso
- is_integer(Port) andalso
- is_list(InitOptions) ->
- %% We MUST delete the option iiop_port.
- Options = lists:keydelete(iiop_port, 1, InitOptions),
- case node() of
- nonode@nohost ->
- {error, "The distribution is not started"};
- _ ->
- mnesia:start(),
- corba:orb_init([{iiop_port, Port}|Options]),
- install([node()], [{ifr_storage_type, ram_copies}]),
- start(),
- NewPort = orber_env:iiop_port(),
- Domain = orber_env:ip_address() ++ [$:|integer_to_list(NewPort)],
- orber_env:configure_override(domain, Domain),
- case jump_start_slaves(Nodes, NewPort,
- [{domain, Domain}|Options], [], []) of
- {ok, NodeData} ->
- info(),
- {ok, [{node(), NewPort}|NodeData]};
- Other ->
- Other
- end
- end.
-
-jump_start_slaves([], _, _, [], NodeData) ->
- rpc:multicall([node() | nodes()], global, sync, []),
- {ok, NodeData};
-jump_start_slaves([], _, _, Errors, _) ->
- {error, Errors};
-jump_start_slaves([{Host, N}|T], Port, Options, Errors, NodeData) ->
- case create_nodes(Host, N, Port, Options, Errors, NodeData) of
- {ok, NewNodeData} ->
- jump_start_slaves(T, Port, Options, Errors, NewNodeData);
- {error, NewErrors} ->
- jump_start_slaves(T, Port, Options, NewErrors, NodeData)
- end;
-jump_start_slaves([Host|T], Port, Options, Errors, NodeData) ->
- case catch create_node(Host, Port+1, Options) of
- {ok, NewNode} ->
- jump_start_slaves(T, Port, Options, Errors, [{NewNode, Port+1}|NodeData]);
- {error, Reason} ->
- jump_start_slaves(T, Port, Options, [{Host, Port, Reason}|Errors],
- NodeData);
- Other ->
- jump_start_slaves(T, Port, Options, [{Host, Port, Other}|Errors],
- NodeData)
- end.
-
-create_nodes(_, 0, _, _, [], NodeData) ->
- {ok, NodeData};
-create_nodes(_, 0, _, _, Errors, _) ->
- {error, Errors};
-create_nodes(Host, N, Port, Options, Errors, NodeData) ->
- case catch create_node(Host, Port+N, Options) of
- {ok, NewNode} ->
- create_nodes(Host, N-1, Port, Options, Errors,
- [{NewNode, Port+N}|NodeData]);
- {error, Reason} ->
- create_nodes(Host, N-1, Port, Options,
- [{Host, Port+N, Reason}|Errors], NodeData);
- Other ->
- create_nodes(Host, N-1, Port, Options,
- [{Host, Port+N, Other}|Errors], NodeData)
- end.
-
-
-create_node(Host, Port, Options) ->
- case slave:start_link(Host, list_to_atom(integer_to_list(Port))) of
- {ok, NewNode} ->
- case net_adm:ping(NewNode) of
- pong ->
- ok = rpc:call(NewNode, mnesia, start, []),
- {ok,_} = rpc:call(NewNode, mnesia, change_config, [extra_db_nodes, [node()]]),
- ok = rpc:call(NewNode, corba, orb_init, [[{iiop_port, Port}|Options]]),
- ok = rpc:call(NewNode, orber, add_node, [NewNode, ram_copies]),
- {ok, NewNode};
- _ ->
- {error, "net_adm:ping(Node) failed"}
- end;
- {error, Reason} ->
- {error, Reason}
- end.
-
-
-start() ->
- start(temporary).
-
-start(Type) when Type == permanent; Type == temporary ->
- application:start(mnesia),
- TableTest = test_tables(),
- case lists:member(not_member, TableTest) of
- true ->
- exit({error,"Orber Mnesia Table(s) missing. Orber not properly installed."});
- _->
- try_starting(Type)
- end.
-
-start_lightweight() ->
- application:start(orber).
-
-start_lightweight(Nodes) when is_list(Nodes) ->
- configure(lightweight, Nodes),
- application:set_env(orber, lightweight, Nodes),
- application:start(orber);
-start_lightweight(_) ->
- exit({error,"Argument not correct; must be a list of nodes."}).
-
-stop() ->
- application:stop(orber).
-
-
-get_tables() ->
- case light_ifr() of
- false ->
- ?ifr_object_list++?ORBER_TABS;
- true ->
- ?ifr_light_object_list ++?ORBER_TABS
- end.
-
-iiop_port() ->
- orber_env:iiop_port().
-
-nat_iiop_port() ->
- orber_env:nat_iiop_port().
-
-iiop_out_ports() ->
- orber_env:iiop_out_ports().
-
-iiop_out_ports_random() ->
- orber_env:iiop_out_ports_random().
-
-iiop_out_ports_attempts() ->
- orber_env:iiop_out_ports_attempts().
-
-orber_nodes() ->
- case catch mnesia:table_info(orber_objkeys,ram_copies) of
- Nodes when is_list(Nodes) ->
- Nodes;
- _ ->
- [node()]
- end.
-
-domain() ->
- orber_env:domain().
-
-
-ip_address_variable_defined() ->
- orber_env:ip_address_variable_defined().
-
-
-nat_host() ->
- orber_env:nat_host().
-
-host() ->
- orber_env:host().
-
-giop_version() ->
- orber_env:giop_version().
-
-iiop_timeout() ->
- orber_env:iiop_timeout().
-
-iiop_connection_timeout() ->
- orber_env:iiop_connection_timeout().
-
-iiop_setup_connection_timeout() ->
- orber_env:iiop_setup_connection_timeout().
-
-iiop_in_connection_timeout() ->
- orber_env:iiop_in_connection_timeout().
-
-find_peername_by_sockname(Host, Port) ->
- orber_iiop_net:sockname2peername(Host, Port) ++
- orber_iiop_pm:sockname2peername(Host, Port).
-
-find_sockname_by_peername(Host, Port) ->
- orber_iiop_net:peername2sockname(Host, Port) ++
- orber_iiop_pm:peername2sockname(Host, Port).
-
-%%----------------------------------------------------------------------
-%% Function : iiop_connections
-%% Arguments : Direction - in | out | inout
-%% Returns : Connections - [{Host, Port}] | [{Host, Port, Interface}]
-%% Host - string
-%% Port - integer
-%% Interface - string
-%% Raises :
-%% Description: List existing in- and/or out-bound connections.
-%%----------------------------------------------------------------------
-iiop_connections() ->
- iiop_connections(inout).
-
-iiop_connections(inout) ->
- orber_iiop_pm:list_existing_connections() ++ orber_iiop_net:connections();
-iiop_connections(in) ->
- orber_iiop_net:connections();
-iiop_connections(out) ->
- orber_iiop_pm:list_existing_connections().
-
-%%----------------------------------------------------------------------
-%% Function : close_connection
-%% Arguments : ObjRef - #'IOP_IOR'{} | [{Host, Port}] |
-%% Interface - string (optional)
-%% Host - string
-%% Port - integer
-%% Returns : ok | {'EXCEPTION', #'BAD_PARAM'{}}
-%% Raises :
-%% Description: Close outgoing connections.
-%%----------------------------------------------------------------------
-close_connection(ObjRef) ->
- close_connection(ObjRef, 0).
-
-close_connection(ObjRef, Interface) when is_record(ObjRef, 'IOP_IOR') ->
- case iop_ior:get_peerdata(ObjRef) of
- [] ->
- ok;
- PeerData ->
- orber_iiop_pm:close_connection(PeerData, Interface)
- end;
-close_connection(PeerData, Interface) when is_list(PeerData) ->
- orber_iiop_pm:close_connection(PeerData, Interface);
-close_connection(What, Interface) ->
- orber:dbg("[~p] orber:close_connection(~p, ~p);~n"
- "Incorrect type of arguments.",
- [?LINE, What, Interface], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------------------
-%% Function : iiop_connections_pending
-%% Arguments : -
-%% Returns : Connections - [{Host, Port}]
-%% Host - string
-%% Port - integer
-%% Raises :
-%% Description: List outbound connections that are being setup. Usefull
-%% when suspecting firewall problems.
-%%----------------------------------------------------------------------
-iiop_connections_pending() ->
- orber_iiop_pm:list_setup_connections().
-
-
-iiop_max_fragments() ->
- orber_env:iiop_max_fragments().
-
-iiop_max_in_requests() ->
- orber_env:iiop_max_in_requests().
-
-iiop_max_in_connections() ->
- orber_env:iiop_max_in_connections().
-
-iiop_backlog() ->
- orber_env:iiop_backlog().
-
-iiop_acl() ->
- orber_env:iiop_acl().
-
-ip_address_local() ->
- orber_env:ip_address_local().
-
-get_flags() ->
- orber_env:get_flags().
-
-typechecking() ->
- orber_env:typechecking().
-
-exclude_codeset_ctx() ->
- orber_env:exclude_codeset_ctx().
-
-exclude_codeset_component() ->
- orber_env:exclude_codeset_component().
-
-partial_security() ->
- orber_env:partial_security().
-
-use_CSIv2() ->
- orber_env:use_CSIv2().
-
-use_FT() ->
- orber_env:use_FT().
-
-ip_version() ->
- orber_env:ip_version().
-
-light_ifr() ->
- orber_env:light_ifr().
-
-bidir_context() ->
- orber_env:bidir_context().
-
-objectkeys_gc_time() ->
- orber_env:objectkeys_gc_time().
-
-
-%%-----------------------------------------------------------------
-%% CosNaming::NamingContextExt operations
-%%-----------------------------------------------------------------
-get_ORBInitRef() ->
- orber_env:get_ORBInitRef().
-
-get_ORBDefaultInitRef() ->
- orber_env:get_ORBDefaultInitRef().
-
-
-%%-----------------------------------------------------------------
-%% Interceptor opertaions (see orber_pi.erl)
-%%-----------------------------------------------------------------
-get_interceptors() ->
- orber_env:get_interceptors().
-
-get_local_interceptors() ->
- orber_env:get_local_interceptors().
-
-get_cached_interceptors() ->
- orber_env:get_cached_interceptors().
-
-set_interceptors(Val) ->
- orber_env:set_interceptors(Val).
-
-
-%%-----------------------------------------------------------------
-%% Light weight Orber operations
-%%-----------------------------------------------------------------
-is_lightweight() ->
- orber_env:is_lightweight().
-
-get_lightweight_nodes() ->
- orber_env:get_lightweight_nodes().
-
-%%-----------------------------------------------------------------
-%% Security access operations (SSL)
-%%-----------------------------------------------------------------
-secure() ->
- orber_env:secure().
-
-iiop_ssl_backlog() ->
- orber_env:iiop_ssl_backlog().
-
-iiop_ssl_ip_address_local() ->
- orber_env:iiop_ssl_ip_address_local().
-
-iiop_ssl_port() ->
- orber_env:iiop_ssl_port().
-
-nat_iiop_ssl_port() ->
- orber_env:nat_iiop_ssl_port().
-
-ssl_server_options() ->
- orber_env:ssl_server_options().
-
-ssl_client_options() ->
- orber_env:ssl_client_options().
-
-set_ssl_client_options(Value) ->
- orber_env:set_ssl_client_options(Value).
-
-ssl_server_certfile() ->
- orber_env:ssl_server_certfile().
-
-ssl_client_certfile() ->
- orber_env:ssl_client_certfile().
-
-set_ssl_client_certfile(Value) ->
- orber_env:set_ssl_client_certfile(Value).
-
-ssl_server_verify() ->
- orber_env:ssl_server_verify().
-
-ssl_client_verify() ->
- orber_env:ssl_client_verify().
-
-set_ssl_client_verify(Value) ->
- orber_env:set_ssl_client_verify(Value).
-
-ssl_server_depth() ->
- orber_env:ssl_server_depth().
-
-ssl_client_depth() ->
- orber_env:ssl_client_depth().
-
-set_ssl_client_depth(Value) ->
- orber_env:set_ssl_client_depth(Value).
-
-ssl_server_cacertfile() ->
- orber_env:ssl_server_cacertfile().
-
-ssl_client_cacertfile() ->
- orber_env:ssl_client_cacertfile().
-
-set_ssl_client_cacertfile(Value) ->
- orber_env:set_ssl_client_cacertfile(Value).
-
-ssl_client_password() ->
- orber_env:ssl_client_password().
-
-ssl_server_password() ->
- orber_env:ssl_server_password().
-
-ssl_client_keyfile() ->
- orber_env:ssl_client_keyfile().
-
-ssl_server_keyfile() ->
- orber_env:ssl_server_keyfile().
-
-ssl_client_ciphers() ->
- orber_env:ssl_client_ciphers().
-
-ssl_server_ciphers() ->
- orber_env:ssl_server_ciphers().
-
-ssl_client_cachetimeout() ->
- orber_env:ssl_client_cachetimeout().
-
-ssl_server_cachetimeout() ->
- orber_env:ssl_server_cachetimeout().
-
-%%----------------------------------------------------------------------
-%% Function : activate_audit_trail
-%% Arguments : Verbosity - stealth | normal | verbose
-%% Returns : -
-%% Raises :
-%% Description: Activate the appropriate interceptor for the requested direction(s).
-%%----------------------------------------------------------------------
-activate_audit_trail() ->
- activate_audit_trail(normal).
-
-activate_audit_trail(stealth) ->
- do_activate(orber_iiop_tracer_stealth);
-activate_audit_trail(verbose) ->
- do_activate(orber_iiop_tracer);
-activate_audit_trail(_) ->
- do_activate(orber_iiop_tracer_silent).
-
-do_activate(Interceptor) ->
- Options =
- case orber_env:get_interceptors() of
- {native, PIs} ->
- [{interceptors,
- {native, [Interceptor|remove_built_in_interceptors(PIs, [])]}}];
- _ ->
- [{interceptors, {native, [Interceptor]}}]
- end,
- reconfigure_in_connections(Options),
- reconfigure_out_connections(Options).
-
-remove_built_in_interceptors([orber_iiop_tracer_stealth|T], Acc) ->
- remove_built_in_interceptors(T, Acc);
-remove_built_in_interceptors([orber_iiop_tracer|T], Acc) ->
- remove_built_in_interceptors(T, Acc);
-remove_built_in_interceptors([orber_iiop_tracer_silent|T], Acc) ->
- remove_built_in_interceptors(T, Acc);
-remove_built_in_interceptors([H|T], Acc) ->
- remove_built_in_interceptors(T, [H|Acc]);
-remove_built_in_interceptors([], Acc) ->
- %% We must use the same order as defined by the interceptors parameter
- lists:reverse(Acc).
-
-%%----------------------------------------------------------------------
-%% Function : deactivate_audit_trail
-%% Arguments : -
-%% Returns : -
-%% Raises :
-%% Description: Dectivate interceptors for the requested direction(s).
-%%----------------------------------------------------------------------
-deactivate_audit_trail() ->
- Options
- = case orber_env:get_interceptors() of
- {native, PIs} ->
- [{interceptors, {native, PIs}}];
- _ ->
- [{interceptors, false}]
- end,
- reconfigure_in_connections(Options),
- reconfigure_out_connections(Options).
-
-%%----------------------------------------------------------------------
-%% Function : add_listen_interface
-%% Arguments : IP - string
-%% Type - normal | ssl
-%% Port - integer > 0
-%% Options - [{Key, Value}]
-%% Key - atom() valid configuration parameter
-%% Value - a valid value for the given Key
-%% Returns : #Ref
-%% Raises :
-%% Description: Add a new listen process, which will accept new incoming
-%% connections.
-%%----------------------------------------------------------------------
-add_listen_interface(IP, normal) ->
- orber_iiop_net:add(IP, normal, [{iiop_port, orber_env:iiop_port()}]);
-add_listen_interface(IP, ssl) ->
- orber_iiop_net:add(IP, ssl, [{iiop_ssl_port, orber_env:iiop_ssl_port()}]).
-
-add_listen_interface(IP, normal, Port) when is_integer(Port) andalso Port > 0 ->
- orber_iiop_net:add(IP, normal, [{iiop_port, Port}]);
-add_listen_interface(IP, ssl, Port) when is_integer(Port) andalso Port > 0 ->
- orber_iiop_net:add(IP, ssl, [{iiop_ssl_port, Port}]);
-add_listen_interface(IP, Type, Options) when is_list(Options) ->
- orber_iiop_net:add(IP, Type, Options);
-add_listen_interface(IP, Type, Port) when is_integer(Port) ->
- orber:dbg("[~p] orber:add_listen_interface(~p, ~p, ~p);~n"
- "The port number must be greater than 0.",
- [?LINE, IP, Type, Port], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO});
-add_listen_interface(IP, Type, Extra) ->
- orber:dbg("[~p] orber:add_listen_interface(~p, ~p, ~p);~n"
- "Incorrect argument(s).",
- [?LINE, IP, Type, Extra], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%----------------------------------------------------------------------
-%% Function : remove_listen_interface
-%% Arguments : Ref - #Ref
-%% Returns : #Ref
-%% Raises :
-%% Description: Terminate the listen process and all related inproxies
-%% associated with the supplied reference.
-%%----------------------------------------------------------------------
-remove_listen_interface(Ref) ->
- orber_iiop_net:remove(Ref).
-
-%%----------------------------------------------------------------------
-%% Function : reconfigure_out_connections
-%% Arguments : Options - see corba:orb_init
-%% Returns : ok | {error, Reason}
-%% Raises :
-%% Description: Reconfigure the behavior of all outgoing IIOP connections.
-%%----------------------------------------------------------------------
-reconfigure_out_connections(Options) ->
- orber_iiop_pm:reconfigure(Options).
-
-%%----------------------------------------------------------------------
-%% Function : reconfigure_out_connections
-%% Arguments : Options - see corba:orb_init
-%% Host - string()
-%% Port - integer()
-%% Interface - string
-%% Returns : ok | {error, Reason}
-%% Raises :
-%% Description: Reconfigure the behavior of all outgoing connections.
-%%----------------------------------------------------------------------
-reconfigure_out_connection(Options, Host, Port) ->
- orber_iiop_pm:reconfigure(Options, Host, Port).
-reconfigure_out_connection(Options, Host, Port, Interface) ->
- orber_iiop_pm:reconfigure(Options, Host, Port, Interface).
-
-%%----------------------------------------------------------------------
-%% Function : reconfigure_in_connections
-%% Arguments : Options - see corba:orb_init
-%% Returns : ok | {error, Reason}
-%% Raises :
-%% Description: Reconfigure the behavior of all incoming IIOP connections.
-%%----------------------------------------------------------------------
-reconfigure_in_connections(Options) ->
- orber_iiop_net:reconfigure(Options).
-
-%%----------------------------------------------------------------------
-%% Function : reconfigure_in_connections
-%% Arguments : Options - see corba:orb_init
-%% Ref - The #Ref returned by add_listen_interface/2/3
-%% Returns : ok | {error, Reason}
-%% Raises :
-%% Description: Reconfigure the behavior of all incoming IIOP connections.
-%%----------------------------------------------------------------------
-reconfigure_in_connection(Options, Ref) ->
- orber_iiop_net:reconfigure(Options, Ref).
-
-
-%%-----------------------------------------------------------------
-%% Configuration settings
-%%-----------------------------------------------------------------
-info() ->
- orber_env:info().
-
-info(IoDevice) ->
- orber_env:info(IoDevice).
-
-%%-----------------------------------------------------------------
-%% EXCEPTION mapping
-%%-----------------------------------------------------------------
-exception_info(Exc) ->
- orber_exceptions:dissect(Exc).
-
-is_system_exception(Exc) ->
- orber_exceptions:is_system_exception(Exc).
-
-%%-----------------------------------------------------------------
-%% Installation interface functions
-%%-----------------------------------------------------------------
-install(Nodes) ->
- install(Nodes, []).
-
-install([], Options) ->
- install([node()], Options);
-install(Nodes, Options) when is_list(Nodes) andalso is_list(Options)->
- case orber_tb:is_running() of
- false ->
- application:load(orber),
- case mnesia:system_info(is_running) of
- no ->
- application:start(mnesia),
- Outcome = install_orber(Nodes, Options),
- application:stop(mnesia),
- Outcome;
- yes ->
- install_orber(Nodes, Options)
- end;
- _ ->
- exit({error, "Orber is already running on this node."})
- end.
-
-
-
-install_orber(Nodes, Options) ->
- #options{ifr_storage_type = IFRType, install_timeout = Timeout,
- local_content = LocalContent, nameservice_storage_type = NSType,
- initialreferences_storage_type = InitType,
- load_order = LoadOrder}
- = check_options(Options, #options{}),
- MnesiaOptions = [{local_content, LocalContent},
- {load_order, LoadOrder}],
- TableTest = test_tables(),
- case lists:member(is_member, TableTest) of
- true ->
- case LocalContent of
- true ->
- orber_ifr:initialize(Timeout, {localCopy,IFRType},
- light_ifr());
- _->
- exit("Orber Mnesia Table(s) already exist. Cannot install Orber.")
- end;
- _ ->
- orber_ifr:initialize(Timeout, [{IFRType, Nodes} |MnesiaOptions],
- light_ifr())
- end,
- orber_objectkeys:install(Timeout, [{ram_copies, Nodes} |MnesiaOptions]),
- 'CosNaming_NamingContextExt_impl':install(Timeout, [{NSType, Nodes} |MnesiaOptions]),
- orber_initial_references:install(Timeout, [{InitType, Nodes} |MnesiaOptions]),
- oe_cos_naming:oe_register(),
- oe_cos_naming_ext:oe_register(),
- oe_erlang:oe_register(),
- oe_OrberIFR:oe_register(),
- oe_CORBA:oe_register(),
- case NSType of
- ram_copies ->
- case mnesia:dump_tables(['orber_CosNaming']) of
- {atomic, ok} ->
- ok;
- {aborted, {has_no_disc,_}} ->
- ok;
- {aborted, Reason} ->
- ?EFORMAT("Unable to dump mnesia tables: ~p", [Reason])
- end;
- _ ->
- ok
- end.
-
-check_options([], Options) ->
- Options;
-check_options([{ifr_storage_type, Type}|T], Options)
- when Type == disc_copies; Type == ram_copies ->
- check_options(T, Options#options{ifr_storage_type = Type});
-check_options([{nameservice_storage_type, Type}|T], Options)
- when Type == disc_copies; Type == ram_copies ->
- check_options(T, Options#options{nameservice_storage_type = Type});
-check_options([{initialreferences_storage_type, Type}|T], Options)
- when Type == disc_copies; Type == ram_copies ->
- check_options(T, Options#options{initialreferences_storage_type = Type});
-check_options([{install_timeout, Timeout}|T], Options)
- when Timeout == infinity orelse is_integer(Timeout) ->
- check_options(T, Options#options{install_timeout = Timeout});
-check_options([{local_content, Bool}|T], Options)
- when Bool == true; Bool == false ->
- check_options(T, Options#options{local_content = Bool});
-check_options([{type, Type}|T], Options)
- when Type == temporary; Type == permanent ->
- check_options(T, Options#options{type = Type});
-check_options([{load_order, LoadOrder}|T], Options)
- when is_integer(LoadOrder) ->
- check_options(T, Options#options{load_order = LoadOrder});
-check_options([H|_], _) ->
- ?EFORMAT("Option unknown or incorrect value: ~w", [H]).
-
-
-
-try_starting(Type) ->
- case application:start(orber, Type) of
- ok ->
- case partial_security() of
- true ->
- error_logger:warning_msg(
- "=================== Orber =================~n"
- "*******************************************~n"
- "**** WARNING - WARNING - WARNING **********~n"
- "**** WARNING - WARNING - WARNING **********~n"
- "**** WARNING - WARNING - WARNING **********~n"
- "**** WARNING - WARNING - WARNING **********~n"
- "*******************************************~n"
- " ORBER STARTED WITH AN INSECURE OPTION:~n"
- " ~n"
- " {flags, ~p}~n"
- " ~n"
- " THIS OPTION MAY ONLY BE USED DURING TESTS~n"
- " ~n"
- "===========================================~n",
- [?ORB_ENV_PARTIAL_SECURITY]),
- ok;
- false ->
- ok
- end;
- {error,{already_started,orber}} ->
- {error,{already_started,orber}};
- Reason ->
- dbg("[~p] orber:try_starting(~p) failed: ~n~p",
- [?LINE, Type, Reason], ?DEBUG_LEVEL),
- {error, "Unable to start Orber. Is the listen port vacant?"}
- end.
-
-test_tables() ->
- AllTabs = mnesia:system_info(tables),
- lists:map(fun(Tab) ->
- case lists:member(Tab,AllTabs) of
- false ->
- not_member;
- _ ->
- is_member
- end
- end,
- get_tables()).
-
-%%-----------------------------------------------------------------
-%% UnInstallation interface functions
-%%-----------------------------------------------------------------
-uninstall() ->
- orber_objectkeys:stop_all(),
- application:stop(orber),
- delete_orber_tables(get_tables()).
-
-delete_orber_tables([]) -> ok;
-delete_orber_tables([Tab1|Rest]) ->
- mnesia:delete_table(Tab1),
- delete_orber_tables(Rest).
-
-%%-----------------------------------------------------------------
-%% Add and remove node interface functions
-%%-----------------------------------------------------------------
-add_node(Node, StorageType) when is_atom(Node) andalso is_atom(StorageType) ->
- add_node(Node, [{ifr_storage_type, StorageType}]);
-add_node(Node, OptionList) when is_atom(Node) andalso is_list(OptionList) ->
- case rpc:call(Node, mnesia, system_info, [is_running]) of
- {badrpc, Reason} ->
- ?EFORMAT("Node ~p do not respond. add_node/2 failed: ~p",
- [Node, Reason]);
- yes ->
- case rpc:call(Node, orber, is_running, []) of
- false ->
- %% We need to "load" orber to make sure that
- %% application environment variables is loaded.
- rpc:call(Node, application, load, [orber]),
- Options = check_options(OptionList, #options{}),
- case rpc:call(Node, orber, light_ifr, []) of
- false ->
- copy_tables(?ifr_object_list, Node, Options);
- true ->
- copy_tables(?ifr_light_object_list, Node, Options)
- end;
- true ->
- ?EFORMAT("Orber is already running on ~p. add_node failed.",
- [Node]);
- Reason ->
- ?EFORMAT("Unable to reach node ~p. add_node/1 failed: ~p",
- [Node, Reason])
- end;
- no ->
- ?EFORMAT("Mnesia not running on node ~p. add_node/2 failed.",
- [Node]);
- starting ->
- ?EFORMAT("Mnesia not fully started on node ~p. add_node/2 failed.",
- [Node]);
- stopping ->
- ?EFORMAT("Mnesia stopping on node ~p. add_node/2 failed.", [Node])
- end.
-
-%% We have to copy the tables in two steps, i.e., orber tables should be ram_copies
-%% while the user may choose to install the rest as disc_copies.
-copy_tables([], Node, Options) ->
- copy_orber_tables(?ORBER_TABS, Node, Options);
-copy_tables([T1|Trest], Node, Options) ->
- case mnesia:add_table_copy(T1, Node, Options#options.ifr_storage_type) of
- {atomic, ok} ->
- copy_tables(Trest, Node, Options);
- {aborted, Reason} ->
- ?EFORMAT("orber:add_node/2 failed: ~p. Unable to copy IFR table(s): ~p",
- [mnesia:error_description(Reason), [T1|Trest]])
- end.
-
-copy_orber_tables([], Node, Options) ->
- case rpc:call(Node, application, start, [orber, Options#options.type]) of
- ok ->
- ok;
- Reason ->
- ?EFORMAT("All tables installed but failed to start orber on node ~p: ~p",
- [Node, Reason])
- end;
-copy_orber_tables([orber_CosNaming|TTail], Node, Options) ->
- case mnesia:add_table_copy(orber_CosNaming, Node,
- Options#options.nameservice_storage_type) of
- {atomic, ok} ->
- copy_orber_tables(TTail, Node, Options);
- {aborted, Reason} ->
- ?EFORMAT("orber:add_node/2 failed: ~p. Unable to copy system table(s): ~p",
- [mnesia:error_description(Reason), [orber_CosNaming|TTail]])
- end;
-copy_orber_tables([orber_references|TTail], Node, Options) ->
- case mnesia:add_table_copy(orber_references, Node,
- Options#options.initialreferences_storage_type) of
- {atomic, ok} ->
- copy_orber_tables(TTail, Node, Options);
- {aborted, Reason} ->
- ?EFORMAT("orber:add_node/2 failed: ~p. Unable to copy system table(s): ~p",
- [mnesia:error_description(Reason), [orber_references|TTail]])
- end;
-copy_orber_tables([THead|TTail], Node, Options) ->
- case mnesia:add_table_copy(THead, Node, ram_copies) of
- {atomic, ok} ->
- copy_orber_tables(TTail, Node, Options);
- {aborted, Reason} ->
- ?EFORMAT("orber:add_node/2 failed: ~p. Unable to copy system table(s): ~p",
- [mnesia:error_description(Reason), [THead|TTail]])
- end.
-
-remove_node(Node) when is_atom(Node) ->
- case rpc:call(Node, mnesia, system_info, [is_running]) of
- yes ->
- case rpc:call(Node, orber, is_running, []) of
- true ->
- rpc:call(Node, orber, stop, []),
- remove_tables(get_tables(), Node);
- false ->
- remove_tables(get_tables(), Node);
- Reason ->
- ?EFORMAT("Unable to reach node: ~p. remove_node/1 failed: ~p",
- [Node, Reason])
- end;
- no ->
- case rpc:call(Node, mnesia, start, []) of
- ok ->
- remove_tables(get_tables(), Node),
- rpc:call(Node, mnesia, stop, []);
- Reason ->
- ?EFORMAT("Unable to reach node: ~p. remove_node/1 failed: ~p",
- [Node, Reason])
- end;
- Reason ->
- ?EFORMAT("Problem with ~p. remove_node/1 failed: ~p", [Node, Reason])
- end.
-
-
-remove_tables(Tables, Node) ->
- case remove_tables(Tables, Node, []) of
- ok ->
- ok;
- {error, Node, Failed} ->
- ?EFORMAT("orber:remove_node(~p) failed. Unable to remove table(s): ~p",
- [Node, Failed])
- end.
-
-remove_tables([], _, []) ->
- ok;
-remove_tables([], Node, Failed) ->
- {error, Node, Failed};
-remove_tables([T1|Trest], Node, Failed) ->
- case mnesia:del_table_copy(T1, Node) of
- {atomic, ok} ->
- remove_tables(Trest, Node, Failed);
- {aborted, Reason} ->
- remove_tables(Trest, Node, [{T1, Reason}|Failed])
- end.
-
-%%-----------------------------------------------------------------
-%% Internal interface functions
-%%-----------------------------------------------------------------
-%%----------------------------------------------------------------------
-%% Function : is_running
-%% Arguments :
-%% Returns :
-%% Raises :
-%% Description:
-%%----------------------------------------------------------------------
-is_running() ->
- orber_tb:is_running().
-
-%%----------------------------------------------------------------------
-%% Function : check_giop
-%% Arguments :
-%% Returns :
-%% Raises :
-%% Description:
-%%----------------------------------------------------------------------
-check_giop_version() ->
- case giop_version() of
- {1,0} ->
- ok;
- {1,1} ->
- ok;
- {1,2} ->
- ok;
- X ->
- X
- end.
-
-%%----------------------------------------------------------------------
-%% Function : dbg
-%% Arguments :
-%% Returns :
-%% Raises :
-%% Description: Note, dbg replaces debug_level_print.
-%%
-%% The following levels are used (0-10):
-%% 10: cdrlib.erl
-%% 9: cdr_encode.erl cdr_decode.erl orber_ifr.erl orber_pi.erl
-%% 8: orber_iiop_outrequest.erl orber_iiop_inrequest.erl
-%% 7: orber_iiop_outproxy.erl orber_iiop_inproxy.erl
-%% 6: iop_ior.erl, orber_objectkeys.erl, Orber_IFR_impl.erl orber_socket.erl
-%% 5: corba.erl, corba_boa.erl, corba_object.erl
-%% 4: Reserved for Cos-services!
-%% 3: Reserved for Cos-services!
-%% 2: Reserved for client applications!
-%% 1: Reserved for client applications!
-%% 0: No logging!
-%%
-%% A higher value will result in a finer granularity.
-%%----------------------------------------------------------------------
-get_debug_level() ->
- orber_env:get_debug_level().
-
-debug_level_print(Format, Data, RequestedLevel) ->
- dbg(Format, Data, RequestedLevel).
-
-dbg(Format, Data, RequestedLevel) ->
- case orber_env:get_debug_level() of
- 0 ->
- ok;
- Level when is_integer(Level) andalso Level >= RequestedLevel ->
- if
- RequestedLevel > 4 ->
- %% Use catch if incorrect format used somewhere.
- catch error_logger:error_msg("=================== Orber =================~n"++
- Format++
- "~n===========================================~n",
- Data);
- RequestedLevel > 2 ->
- %% Use catch if incorrect format used somewhere.
- catch error_logger:error_msg("=========== Orber COS Application =========~n"++
- Format++
- "~n===========================================~n",
- Data);
- true ->
- %% Use catch if incorrect format used somewhere.
- catch error_logger:error_msg("========== Orber Client Application =======~n"++
- Format++
- "~n===========================================~n",
- Data)
- end,
- ok;
- _ ->
- ok
- end.
-
-error(Format, Data, RequestedLevel) ->
- if
- RequestedLevel > 4 ->
- %% Use catch if incorrect format used somewhere.
- catch error_logger:error_msg("=================== Orber =================~n"++
- Format++
- "~n===========================================~n",
- Data);
- RequestedLevel > 2 ->
- %% Use catch if incorrect format used somewhere.
- catch error_logger:error_msg("=========== Orber COS Application =========~n"++
- Format++
- "~n===========================================~n",
- Data);
- true ->
- %% Use catch if incorrect format used somewhere.
- catch error_logger:error_msg("========== Orber Client Application =======~n"++
- Format++
- "~n===========================================~n",
- Data)
- end,
- ok.
-
-configure(Key, Value) ->
- orber_env:configure(Key, Value, check).
-
-configure_override(Key, Value) ->
- orber_env:configure(Key, Value, loaded).
-
-multi_configure(KeyValueList) ->
- orber_env:multi_configure(KeyValueList).
-
-
-%%-----------------------------------------------------------------
-%% Server functions
-%%-----------------------------------------------------------------
-start(_, _) ->
- supervisor:start_link({local, orber_sup}, orber, orb_init).
-
-init(orb_init) ->
- case check_giop_version() of
- ok ->
- case is_lightweight() of
- true ->
- SupFlags = {one_for_one, 5, 1000},
- ChildSpec = [
- {orber_iiop_sup, {orber_iiop, start_sup, [[]]},
- permanent,
- 10000, supervisor, [orber_iiop]},
- {orber_reqno, {orber_request_number, start,
- [[]]},
- permanent,
- 10000, worker, [orber_request_number]}
- ],
- {ok, {SupFlags, ChildSpec}};
- false ->
- case orber_tb:wait_for_tables(get_tables()) of
- ok ->
- orber_objectkeys:remove_old_keys(),
- SupFlags = {one_for_one, 5, 1000},
- ChildSpec = [
- {orber_iiop_sup, {orber_iiop, start_sup, [[]]},
- permanent,
- 10000, supervisor, [orber_iiop]},
- {orber_init, {orber_initial_references, start,
- [[]]},
- permanent,
- 10000, worker, [orber_initial_references]},
- {orber_reqno, {orber_request_number, start,
- [[]]},
- permanent,
- 10000, worker, [orber_request_number]},
- {orber_objkeyserver, {orber_objectkeys, start,
- [[orber_nodes(), 0]]},
- permanent,
- 10000, worker, [orber_objectkeys]},
- {orber_env, {orber_env, start, [[]]},
- permanent, 10000, worker, [orber_env]}
- ],
- {ok, {SupFlags, ChildSpec}};
- StopReason ->
- {stop, StopReason}
- end
- end;
- X ->
- {stop, ?FORMAT("GIOP ~p not an implemeted version", [X])}
- end.
-
diff --git a/lib/orber/src/orber_acl.erl b/lib/orber/src/orber_acl.erl
deleted file mode 100644
index 55d84afbab..0000000000
--- a/lib/orber/src/orber_acl.erl
+++ /dev/null
@@ -1,397 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_acl.erl
-%%
-%% Description:
-%% Handling ACL's (Access Control Lists).
-%%
-%% Creation date: 040723
-%%
-%%-----------------------------------------------------------------
--module(orber_acl).
-
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([init_acl/1, init_acl/2, clear_acl/0,
- match/2, match/3, verify/3, range/1, range/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--define(ACL_DB, orber_acl_db).
-
--define(DEBUG_LEVEL, 5).
--define(CONTINUE, -1).
--define(STOP, -2).
-
--define(FORMAT(_F, _A), {error, lists:flatten(io_lib:format(_F, _A))}).
--define(EFORMAT(_F, _A), exit(lists:flatten(io_lib:format(_F, _A)))).
-
-%%-----------------------------------------------------------------
-%% Record Definitions
-%%-----------------------------------------------------------------
--record(acl, {key, bits = ?CONTINUE, mask, interfaces = [],
- ports = 0, flags = 0}).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% function : verify/1
-%% Arguments: IP - string()
-%% Filter - string() see init_acl
-%% Family - inet | inet6
-%% Returns : boolean()
-%% Exception:
-%% Effect :
-%%-----------------------------------------------------------------
-verify(IP, Filter, Family) ->
- DB = ets:new(orber_temporary_acl_table_created_by_user,
- [set, public, {keypos, 2}]),
- Result =
- case catch verify_helper(IP, Filter, Family, DB) of
- true ->
- true;
- {ok, Low, High} ->
- {false, Low, High};
- What ->
- {error, ?FORMAT("Uknown Error: ~p\n", [What])}
- end,
- ets:delete(DB),
- Result.
-
-verify_helper(IP, Filter, Family, DB) ->
- init_acl([{tcp_in, Filter}], Family, DB),
- {ok, IPTuple} = inet:getaddr(IP, Family),
- case match_helper(tuple_to_list(IPTuple), tcp_in, DB, false, tcp_in) of
- true ->
- true;
- false ->
- range(Filter, Family)
- end.
-
-%%-----------------------------------------------------------------
-%% function : range/1/2
-%% Arguments: Filter - string(). See init_acl
-%% Family - inet | inet6
-%% Returns : {ok, From, To}
-%% From - To - string()
-%% Exception:
-%% Effect :
-%%-----------------------------------------------------------------
-range(Filter) ->
- range(Filter, inet).
-
-range(Filter, inet) ->
- range_safe(Filter, inet, ".", 16#FF, "255", 8, "~p.", "~p", 3);
-range(Filter, Family) ->
- range_safe(Filter, Family, ":", 16#FFFF, "FFFF", 16, "~.16B:", "~.16B", 7).
-
-range_safe(Filter, Family, Separator, Max, MaxStr, N, F1, F2, X) ->
- case catch range_helper(Filter, Family, Separator, Max, MaxStr, N, F1, F2, X) of
- {ok, Low, High} ->
- {ok, Low, High};
- {'EXIT',{format,Why}} ->
- {error, ?FORMAT("Unable to format string: ~p\n", [Why])};
- {'EXIT', E} ->
- {error, ?FORMAT("Exit: ~p\n", [E])};
- What ->
- {error, ?FORMAT("Unknown Error: ~p\n", [What])}
- end.
-
-range_helper(Filter, Family, Separator, Max, MaxStr, N, F1, F2, X) ->
- {MaskStr, Bits, _Ports} = tokenize(Filter, Family),
- {ok, MaskTuple} = inet:getaddr(MaskStr, Family),
- NoOfFull = Bits div N,
- Mask = get_mask(N, (Bits rem N)),
- case split(NoOfFull, tuple_to_list(MaskTuple)) of
- {Full, [Partial|_DontCare]} ->
- Beginning = pp(Full, [], F1),
- MiddleLow = io_lib:format(F2, [(Mask band Partial) + ((Mask bxor Max) band 0)]),
- MiddleHigh = io_lib:format(F2, [(Mask band Partial) + ((Mask bxor Max) band Max)]),
- EndLow = lists:duplicate((X-NoOfFull), Separator ++ "0"),
- EndHigh = lists:duplicate((X-NoOfFull), Separator ++ MaxStr),
- Low = lists:flatten([Beginning, MiddleLow, EndLow]),
- High = lists:flatten([Beginning, MiddleHigh, EndHigh]),
- {ok, Low, High};
- {Full, []} ->
- Address = lists:flatten(pp(Full, [], F1)),
- {ok, Address, Address}
- end.
-
-pp([], Acc, _) ->
- Acc;
-pp([H|T], Acc, Format) ->
- pp(T, Acc ++ io_lib:format(Format, [H]), Format).
-
-split(N, List) when is_integer(N) andalso N >= 0 andalso is_list(List) ->
- case split(N, List, []) of
- Fault when is_atom(Fault) ->
- erlang:error(Fault, [N,List]);
- Result ->
- Result
- end;
-split(N, List) ->
- erlang:error(badarg, [N,List]).
-
-split(0, L, R) ->
- {lists:reverse(R, []), L};
-split(N, [H|T], R) ->
- split(N-1, T, [H|R]);
-split(_, [], _) ->
- badarg.
-
-
-%%-----------------------------------------------------------------
-%% function : clear_acl/0
-%% Arguments: -
-%% Returns :
-%% Exception:
-%% Effect :
-%%-----------------------------------------------------------------
-clear_acl() ->
- clear_acl(?ACL_DB).
-clear_acl(DB) ->
- (catch ets:delete(DB)),
- ok.
-
-%%-----------------------------------------------------------------
-%% function : init_acl/1/2
-%% Arguments: Filters - [{Direction, Filter}] | [{Direction, Filter, [Interfaces]}]
-%% Direction - tcp_in | ssl_in | tcp_out | ssl_out
-%% Filter - string(). Examples:
-%% * "123.456.789.10" - match against all bits.
-%% * "123.456.789.10/17" - match against the 17 most significant bits.
-%% * "123.456.789.10/17#4001" - as above but only allow port 4001
-%% * "123.456.789.10/17#4001/5001" - as above but only allow port 4001-5001
-%% Family - inet | inet6
-%% Returns : ok | {'EXCEPTION', E}
-%% Exception: 'BAD_PARAM'
-%% Effect :
-%%-----------------------------------------------------------------
-init_acl(Filters) ->
- DB = ets:new(?ACL_DB, [set, public, named_table, {keypos, 2}]),
- case ?ORB_FLAG_TEST(orber:get_flags(), ?ORB_ENV_USE_IPV6) of
- false ->
- init_acl(Filters, inet, DB);
- true ->
- init_acl(Filters, inet6, DB)
- end.
-
-init_acl(Filters, Family) ->
- DB = ets:new(?ACL_DB, [set, public, named_table, {keypos, 2}]),
- init_acl(Filters, Family, DB).
-
-init_acl([], _, DB) ->
- {ok, DB};
-init_acl([Data|T], Family, DB) ->
- {Direction, Filter, Interfaces} =
- case Data of
- {D, F, I} ->
- {D, F, I};
- {D, F} ->
- {D, F, []}
- end,
- {MaskStr, Bits, Ports} = tokenize(Filter, Family),
- case inet:getaddr(MaskStr, Family) of
- {ok, Addr} when size(Addr) == 4 ->
- create_mask(tuple_to_list(Addr), Bits div 8,
- get_mask8((Bits rem 8)), DB, Direction, Interfaces, Ports),
- init_acl(T, Family, DB);
- {ok, Addr} ->
- create_mask(tuple_to_list(Addr), Bits div 16,
- get_mask16((Bits rem 16)), DB, Direction, Interfaces, Ports),
- init_acl(T, Family, DB)
- end.
-
-create_mask(List, Div, Mask, DB, Direction, Interfaces, Ports) ->
- case split(Div, List) of
- {[], [Partial|_DontCare]} ->
- %% Less than 8/16 bits (depends on family).
- add_parts([], Direction, (Partial band Mask), Mask, DB,
- Interfaces, Ports);
- {Full, [Partial|_DontCare]} ->
- add_parts(Full, Direction, (Partial band Mask), Mask, DB,
- Interfaces, Ports);
- {Full, []} ->
- %% 32 bits.
- add_parts(Full, Direction, ?STOP, Mask, DB, Interfaces, Ports)
- end.
-
-add_parts([], Parent, Bits, Mask, DB, Interfaces, Ports) ->
- ets:insert(DB, #acl{key = Parent, bits = Bits,
- mask = Mask, interfaces = Interfaces, ports = Ports});
-add_parts([H|T], Parent, Bits, Mask, DB, Interfaces, Ports) ->
- Key = {Parent, H},
- ets:insert(DB, #acl{key = Key}),
- add_parts(T, Key, Bits, Mask, DB, Interfaces, Ports).
-
-
-%%-----------------------------------------------------------------
-%% function : match/1/2
-%% Arguments: IP - tuple() | [integer()]
-%% Direction - tcp_in | ssl_in | tcp_out | ssl_out
-%% All - boolean()
-%% Returns :
-%% Exception:
-%% Effect :
-%%-----------------------------------------------------------------
-match(IPTuple, Direction) when is_tuple(IPTuple) ->
- match_helper(tuple_to_list(IPTuple), Direction, ?ACL_DB, false, Direction);
-match(IPList, Direction) ->
- match_helper(IPList, Direction, ?ACL_DB, false, Direction).
-
-match(IPTuple, Direction, All) when is_tuple(IPTuple) ->
- match_helper(tuple_to_list(IPTuple), Direction, ?ACL_DB, All, Direction);
-match(IPList, Direction, All) ->
- match_helper(IPList, Direction, ?ACL_DB, All, Direction).
-
-match_helper([], _, _, false, _) -> false;
-match_helper([], _, _, true, _) -> {false, [], 0};
-match_helper([H|T], Parent, DB, All, Direction) ->
- case ets:lookup(DB, {Parent, H}) of
- [#acl{bits = ?CONTINUE}] ->
- match_helper(T, {Parent, H}, DB, All, Direction);
- [#acl{bits = ?STOP}] when All == false ->
- true;
- [#acl{bits = ?STOP, interfaces = I, ports = Ports}] ->
- {true, I, Ports};
- [#acl{bits = Bits, mask = Mask}] when All == false ->
- Bits == (hd(T) band Mask);
- [#acl{bits = Bits, mask = Mask, interfaces = I, ports = Ports}] ->
- {Bits == (hd(T) band Mask), I, Ports};
- _ ->
- %% Less than 8/16 significant bits (depends on family).
- %% Should we even allow this?
- case ets:lookup(DB, Direction) of
- [#acl{bits = Bits, mask = Mask}] when is_integer(Bits) andalso
- All == false ->
- Bits == (H band Mask);
- [#acl{bits = Bits, mask = Mask,
- interfaces = I, ports = Ports}] when is_integer(Bits) ->
- {Bits == (H band Mask), I, Ports};
- _ when All == false ->
- false;
- _ ->
- {false, [], 0}
- end
- end.
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% function : tokenize/1
-%% Arguments: Filter - string(). Examples:
-%% * "123.456.789.10" - match against all.
-%% * "123.456.789.10/17" - match against the 17 most significant bits.
-%% * "123.456.789.10/17#4001" - as above but only allow port 4001
-%% * "123.456.789.10/17#4001/5001" - as above but only allow port 4001-5001
-%% Family - inet | inet6
-%% Returns : {MaskStr, Bits, Ports}
-%% MaskStr - string()
-%% Bits - integer()
-%% Ports - integer() | {integer(), integer()}
-%% Exception:
-%% Effect :
-%%-----------------------------------------------------------------
-tokenize(Filter, Family) ->
- case string:tokens(Filter, "/#") of
- [MaskStr] when Family == inet ->
- {MaskStr, 32, 0};
- [MaskStr] when Family == inet6 ->
- {MaskStr, 128, 0};
- [MaskStr, BitString] ->
- {MaskStr, list_to_integer(BitString), 0};
- [MaskStr, BitString, Port] ->
- {MaskStr, list_to_integer(BitString), list_to_integer(Port)};
- [MaskStr, BitString, MinPort, MaxPort] ->
- {MaskStr, list_to_integer(BitString),
- {list_to_integer(MinPort), list_to_integer(MaxPort)}};
- What ->
- ?EFORMAT("Invalid Filter: ~p\nReason: ~p\n", [Filter, What])
- end.
-
-
-%%-----------------------------------------------------------------
-%% function : get_mask/2
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%-----------------------------------------------------------------
-get_mask(8, Bits) ->
- get_mask8(Bits);
-get_mask(16, Bits) ->
- get_mask16(Bits).
-
-%%-----------------------------------------------------------------
-%% function : get_mask8/1
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%-----------------------------------------------------------------
-get_mask8(0) -> 2#00000000;
-get_mask8(1) -> 2#10000000;
-get_mask8(2) -> 2#11000000;
-get_mask8(3) -> 2#11100000;
-get_mask8(4) -> 2#11110000;
-get_mask8(5) -> 2#11111000;
-get_mask8(6) -> 2#11111100;
-get_mask8(7) -> 2#11111110.
-
-%%-----------------------------------------------------------------
-%% function : get_mask16/1
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%-----------------------------------------------------------------
-get_mask16(0) -> 2#0000000000000000;
-get_mask16(1) -> 2#1000000000000000;
-get_mask16(2) -> 2#1100000000000000;
-get_mask16(3) -> 2#1110000000000000;
-get_mask16(4) -> 2#1111000000000000;
-get_mask16(5) -> 2#1111100000000000;
-get_mask16(6) -> 2#1111110000000000;
-get_mask16(7) -> 2#1111111000000000;
-get_mask16(8) -> 2#1111111100000000;
-get_mask16(9) -> 2#1111111110000000;
-get_mask16(10) -> 2#1111111111000000;
-get_mask16(11) -> 2#1111111111100000;
-get_mask16(12) -> 2#1111111111110000;
-get_mask16(13) -> 2#1111111111111000;
-get_mask16(14) -> 2#1111111111111100;
-get_mask16(15) -> 2#1111111111111110.
-
-
-%%-----------------------------------------------------------------
-%%------------- END OF MODULE -------------------------------------
-%%-----------------------------------------------------------------
diff --git a/lib/orber/src/orber_diagnostics.erl b/lib/orber/src/orber_diagnostics.erl
deleted file mode 100644
index 18d28fcf35..0000000000
--- a/lib/orber/src/orber_diagnostics.erl
+++ /dev/null
@@ -1,241 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_diagnostics.erl
-%%
-%% Description:
-%%
-%%-----------------------------------------------------------------
-
--module(orber_diagnostics).
-
-
-%%-----------------------------------------------------------------
-%% Includes
-%%-----------------------------------------------------------------
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/src/ifr_objects.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming_NamingContext.hrl").
--include_lib("orber/COSS/CosNaming/orber_cosnaming.hrl").
-
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([nameservice/0, nameservice/1,
- objectkeys/0,
- missing_modules/0]).
-
-%%-----------------------------------------------------------------
-%% Internal Exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
--define(DEBUG_LEVEL, 5).
-
--define(DIAGNOSTICS_PING_EXTERNAL, 16#01).
-
-%%-----------------------------------------------------------------
-%% Function : missing_modules
-%% Args : -
-%% Returns :
-%%-----------------------------------------------------------------
-missing_modules() ->
- List =
- case orber:light_ifr() of
- false ->
- Unions = mnesia:dirty_select(ir_UnionDef,
- [{#ir_UnionDef{absolute_name='$1',
- _='_'},
- [], ['$1']}]),
- Structs = mnesia:dirty_select(ir_StructDef,
- [{#ir_StructDef{absolute_name='$1',
- _='_'},
- [], ['$1']}]),
- Exc = mnesia:dirty_select(ir_ExceptionDef,
- [{#ir_ExceptionDef{absolute_name='$1',
- _='_'},
- [], ['$1']}]),
- Interface = mnesia:dirty_select(ir_InterfaceDef,
- [{#ir_InterfaceDef{absolute_name='$1',
- _='_'},
- [], ['$1']}]),
- Acc1 = create_module_names(Unions, [], ?IFR_UnionDef),
- Acc2 = create_module_names(Structs, Acc1, ?IFR_StructDef),
- Acc3 = create_module_names(Exc, Acc2, ?IFR_ExceptionDef),
- create_module_names(Interface, Acc3, ?IFR_InterfaceDef);
- true ->
- mnesia:dirty_select(orber_light_ifr,
- [{#orber_light_ifr{module='$1',
- type='$2', _='_'},
- [{'=/=', '$2', ?IFR_ModuleDef},
- {'=/=', '$2', ?IFR_ConstantDef},
- {'=/=', '$2', ?IFR_AliasDef},
- {'=/=', '$2', ?IFR_EnumDef}], ['$$']}])
- end,
- io:format("Need to check for ~p modules.~n", [length(List)]),
- Count = missing_modules_helper(List, 0),
- io:format("Check completed. ~p missing modules.~n", [Count]),
- Count.
-
-create_module_names([], Acc, _) ->
- Acc;
-create_module_names([[$:,$:|N]|T], Acc, Type) ->
- create_module_names(T, [[change_colons_to_underscore(N, []), Type]|Acc], Type).
-
-change_colons_to_underscore([$:, $: | T], Acc) ->
- change_colons_to_underscore(T, [$_ |Acc]);
-change_colons_to_underscore([H |T], Acc) ->
- change_colons_to_underscore(T, [H |Acc]);
-change_colons_to_underscore([], Acc) ->
- list_to_atom(lists:reverse(Acc)).
-
-missing_modules_helper([], ErrorsFound) ->
- ErrorsFound;
-missing_modules_helper([[Mod, Type]|T], ErrorsFound) when Type == ?IFR_StructDef;
- Type == ?IFR_UnionDef;
- Type == ?IFR_ExceptionDef ->
- case catch Mod:tc() of
- {'EXIT', _} ->
- io:format("Missing (~s): ~p~n", [type2str(Type), Mod]),
- missing_modules_helper(T, ErrorsFound + 1);
- _ ->
- missing_modules_helper(T, ErrorsFound)
- end;
-missing_modules_helper([[Mod, Type]|T], ErrorsFound) when Type == ?IFR_InterfaceDef ->
- case catch Mod:oe_get_interface() of
- {'EXIT', {undef,[{Mod, _, _, _}|_]}} ->
- io:format("Missing (Interface): ~p~n", [Mod]),
- missing_modules_helper(T, ErrorsFound + 1);
- {'EXIT', {undef,[{OtherMod, _, _, _}|_]}} ->
- io:format("Missing (Inherited by the ~p Interface): ~p~n",
- [Mod, OtherMod]),
- missing_modules_helper(T, ErrorsFound + 1);
- _ ->
- missing_modules_helper(T, ErrorsFound)
- end;
-missing_modules_helper([_|T], ErrorsFound) ->
- missing_modules_helper(T, ErrorsFound).
-
-type2str(?IFR_StructDef) ->
- "Struct";
-type2str(?IFR_UnionDef) ->
- "Union";
-type2str(?IFR_ExceptionDef) ->
- "Exception".
-
-
-%%-----------------------------------------------------------------
-%% Function : nameservice
-%% Args : - | integer()
-%% Returns :
-%%-----------------------------------------------------------------
-nameservice() ->
- nameservice(0).
-
-nameservice(Flags) ->
- case catch ns(?ORB_FLAG_TEST(Flags, ?DIAGNOSTICS_PING_EXTERNAL)) of
- ok ->
- ok;
- {'EXCEPTION', E} ->
- orber:dbg("[~p] orber_diagnostics:nameservice(~p);~n"
- "Reason: ~p", [?LINE, Flags, E], ?DEBUG_LEVEL),
- corba:raise(E);
- What ->
- orber:dbg("[~p] orber_diagnostics:nameservice(~p);~n"
- "Reason: ~p", [?LINE, Flags, What], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-ns(Ping) ->
- NS = corba:resolve_initial_references("NameService"),
- display_names(NS, "", Ping).
-
-
-display_names(NS, Prefix, Ping) ->
- {ok, [], Iter} = 'CosNaming_NamingContextExt':list(NS, 0),
- More = not corba_object:is_nil(Iter),
- iter_names(NS, Prefix, Iter, More, Ping).
-
-iter_names(_NS, _Prefix, Iter, false, _) ->
- destroy_iter(Iter);
-iter_names(NS, Prefix, Iter, true, Ping) ->
- {More, #'CosNaming_Binding'{binding_name = Name, binding_type = Type}} =
- 'CosNaming_BindingIterator':next_one(Iter),
- Fun = fun(#'CosNaming_NameComponent'{id = Id, kind = Kind}, Acc) ->
- case Kind of
- "" -> Acc ++ Id ++ "/";
- _ -> Acc ++ Id ++ "." ++ Kind ++ "/"
- end
- end,
- Prefix2 = lists:foldl(Fun, Prefix, Name),
- if
- More == false ->
- ignore;
- Type == nobject ->
- Object = 'CosNaming_NamingContext':resolve(NS, Name),
- Status =
- case corba_object:is_remote(Object) of
- false ->
- corba_object:non_existent(Object);
- _ when Ping == true ->
- case catch corba_object:non_existent(Object) of
- Boolean when is_atom(Boolean) ->
- Boolean;
- _Other ->
- undefined
- end;
- _ ->
- external
- end,
- io:format("~s [~p] ~s\n",
- [Prefix2, Status, iop_ior:get_typeID(Object)]);
- Type == ncontext ->
- Context = 'CosNaming_NamingContext':resolve(NS, Name),
- io:format("~s\n", [Prefix2]),
- display_names(Context, Prefix2, Ping)
- end,
- iter_names(NS, Prefix, Iter, More, Ping).
-
-destroy_iter(Iter) ->
- case corba_object:is_nil(Iter) of
- false ->
- 'CosNaming_BindingIterator':destroy(Iter),
- ok;
- true ->
- ok
- end.
-
-objectkeys() ->
- ok.
-
-
-
-%%---------------- END OF MODULE ----------------------------------
diff --git a/lib/orber/src/orber_env.erl b/lib/orber/src/orber_env.erl
deleted file mode 100644
index 3000af6cd3..0000000000
--- a/lib/orber/src/orber_env.erl
+++ /dev/null
@@ -1,1545 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_env.erl
-%%
-%% Description:
-%% Handling environment parameters for Orber.
-%%
-%% Creation date: 040723
-%%
-%%-----------------------------------------------------------------
--module(orber_env).
-
--behaviour(gen_server).
-
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([start/1, configure/2, configure/3, configure_override/2,
- multi_configure/1, get_env/1, set_env/2, get_keys/0, env/1,
- info/0, info/1]).
-
--export([iiop_acl/0, iiop_port/0, nat_iiop_port/0, nat_iiop_port/1, iiop_out_ports/0,
- domain/0, ip_address_variable_defined/0, nat_host/0, nat_host/1, host/0,
- ip_address/0, ip_address/1, giop_version/0, iiop_timeout/0, iiop_out_ports_random/0,
- iiop_connection_timeout/0, iiop_setup_connection_timeout/0, iiop_out_ports_attempts/0,
- iiop_in_connection_timeout/0, iiop_max_fragments/0, iiop_max_in_requests/0,
- iiop_max_in_connections/0, iiop_backlog/0, objectkeys_gc_time/0,
- get_ORBInitRef/0, get_ORBDefaultInitRef/0, get_interceptors/0,
- get_local_interceptors/0, get_cached_interceptors/0,
- set_interceptors/1, is_lightweight/0, get_lightweight_nodes/0, secure/0,
- iiop_ssl_backlog/0, iiop_ssl_port/0, nat_iiop_ssl_port/0, nat_iiop_ssl_port/1,
- ssl_server_options/0, ssl_client_options/0, set_ssl_client_options/1,
- ssl_server_certfile/0, ssl_client_certfile/0, set_ssl_client_certfile/1,
- ssl_server_verify/0, ssl_client_verify/0, set_ssl_client_verify/1,
- ssl_server_depth/0, ssl_client_depth/0, set_ssl_client_depth/1,
- ssl_server_cacertfile/0, ssl_client_cacertfile/0,
- set_ssl_client_cacertfile/1, ssl_client_password/0,
- ssl_server_password/0, ssl_client_keyfile/0, ssl_server_keyfile/0,
- ssl_client_ciphers/0, ssl_server_ciphers/0, ssl_client_cachetimeout/0,
- ssl_server_cachetimeout/0,
- get_flags/0, typechecking/0,
- exclude_codeset_ctx/0, exclude_codeset_component/0, partial_security/0,
- use_CSIv2/0, use_FT/0, ip_version/0, light_ifr/0, bidir_context/0,
- get_debug_level/0, getaddrstr/2, addr2str/1, iiop_packet_size/0,
- iiop_ssl_ip_address_local/0, ip_address_local/0, iiop_in_keepalive/0,
- iiop_out_keepalive/0, iiop_ssl_in_keepalive/0, iiop_ssl_out_keepalive/0,
- iiop_ssl_accept_timeout/0, ssl_generation/0]).
-
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([init/1, terminate/2, handle_call/3]).
--export([handle_cast/2, handle_info/2, code_change/3]).
-
-%%-----------------------------------------------------------------
-%% Record Definitions Etc.
-%%-----------------------------------------------------------------
--define(DEBUG_LEVEL, 5).
-
--define(FORMAT(_F, _A), {error, lists:flatten(io_lib:format(_F, _A))}).
--define(EFORMAT(_F, _A), exit(lists:flatten(io_lib:format(_F, _A)))).
-
--define(ENV_DB, orber_env_db).
-
--define(ENV_KEYS,
- [flags, iiop_port, nat_iiop_port, iiop_out_ports, domain, ip_address,
- nat_ip_address, giop_version, iiop_timeout, iiop_connection_timeout,
- iiop_setup_connection_timeout, iiop_in_connection_timeout, iiop_acl,
- iiop_max_fragments, iiop_max_in_requests, iiop_max_in_connections,
- iiop_backlog, objectkeys_gc_time, orbInitRef, orbDefaultInitRef,
- interceptors, local_interceptors, lightweight, ip_address_local,
- secure, iiop_ssl_ip_address_local, iiop_ssl_backlog,
- iiop_ssl_port, nat_iiop_ssl_port, ssl_server_certfile,
- ssl_client_certfile, ssl_server_verify, ssl_client_verify, ssl_server_depth,
- ssl_client_depth, ssl_server_cacertfile, ssl_client_cacertfile,
- ssl_client_password, ssl_server_password, ssl_client_keyfile,
- ssl_server_keyfile, ssl_client_ciphers, ssl_server_ciphers,
- ssl_client_cachetimeout, ssl_server_cachetimeout, orber_debug_level,
- iiop_packet_size, iiop_in_keepalive, iiop_out_keepalive,
- iiop_ssl_in_keepalive, iiop_ssl_out_keepalive, iiop_ssl_accept_timeout,
- ssl_server_options, ssl_client_options]).
-
-%% The 'flags' parameter must be first in the list.
-%-define(ENV_KEYS,
-% [{flags, ?ORB_ENV_INIT_FLAGS}, {iiop_port, 4001}, nat_iiop_port,
-% {iiop_out_ports, 0}, {domain, "ORBER"}, ip_address, nat_ip_address,
-% {giop_version, {1, 1}}, {iiop_timeout, infinity},
-% {iiop_connection_timeout, infinity}, {iiop_setup_connection_timeout, infinity},
-% {iiop_in_connection_timeout, infinity}, {iiop_acl, []},
-% {iiop_max_fragments, infinity}, {iiop_max_in_requests, infinity},
-% {iiop_max_in_connections, infinity}, {iiop_backlog, 5},
-% {objectkeys_gc_time, infinity},
-% {orbInitRef, undefined}, {orbDefaultInitRef, undefined},
-% {interceptors, false}, {local_interceptors, false}, {lightweight, false},
-% {secure, no}, {iiop_ssl_backlog, 5}, {iiop_ssl_port, 4002},
-% nat_iiop_ssl_port, {ssl_server_certfile, []}, {ssl_client_certfile, []},
-% {ssl_server_verify, 0}, {ssl_client_verify, 0}, {ssl_server_depth, 1},
-% {ssl_client_depth, 1}, {ssl_server_cacertfile, []},
-% {ssl_client_cacertfile, []}, {ssl_client_password, []},
-% {ssl_server_password, []}, {ssl_client_keyfile, []},
-% {ssl_server_keyfile, []}, {ssl_client_ciphers, []},
-% {ssl_server_ciphers, []}, {ssl_client_cachetimeout, infinity},
-% {ssl_server_cachetimeout, infinity}, {orber_debug_level, 0}]).
-
--record(parameters, {key, value, flags = 0}).
-
--record(env, {acl, parameters, flags = 0}).
-
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% function :
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%-----------------------------------------------------------------
-start(Opts) ->
- gen_server:start_link({local, orber_env}, ?MODULE, Opts, []).
-
-%%-----------------------------------------------------------------
-%% function : get_keys
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%-----------------------------------------------------------------
-get_keys() ->
- ?ENV_KEYS.
-
-%%-----------------------------------------------------------------
-%% function : get_env
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%-----------------------------------------------------------------
-get_env(Key) when is_atom(Key) ->
- case catch ets:lookup(?ENV_DB, Key) of
- [#parameters{value = Val}] ->
- {ok, Val};
- _ ->
- undefined
- end.
-
-%%-----------------------------------------------------------------
-%% function : get_env
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%-----------------------------------------------------------------
-set_env(Key, Value) when is_atom(Key) ->
- case catch ets:insert(?ENV_DB, #parameters{key = Key, value = Value}) of
- true ->
- ok;
- _ ->
- undefined
- end.
-
-
-%%-----------------------------------------------------------------
-%% function : info
-%% Arguments: IoDervice - info_msg | string | io | {io, Dev}
-%% Returns :
-%% Exception:
-%% Effect :
-%%-----------------------------------------------------------------
-info() ->
- info(info_msg).
-
-info(IoDevice) ->
- Info =
- case orber_tb:is_running() of
- true ->
- Info1 = create_main_info(),
- Info2 = create_flag_info(Info1),
- create_security_info(secure(), Info2);
- _ ->
- lists:flatten(
- io_lib:format("======= Orber Execution Environment ======~n"
- " *** Orber is not running ***~n"
- "==========================================~n",
- []))
- end,
- case IoDevice of
- info_msg ->
- error_logger:info_msg(Info);
- string ->
- Info;
- io ->
- io:format("~s", [Info]);
- {io, Dev} ->
- io:format(Dev, "~s", [Info]);
- _ ->
- exit("Bad parameter")
- end.
-
-create_main_info() ->
- {Major, Minor} = giop_version(),
- {orber, _, OrberVsn} = lists:keyfind(orber, 1, application:loaded_applications()),
- [io_lib:format("======= Orber Execution Environment ======~n"
- "Orber version.................: ~s~n"
- "Orber domain..................: ~s~n"
- "IIOP port number..............: ~p~n"
- "IIOP NAT port number..........: ~p~n"
- "Interface(s)..................: ~p~n"
- "Interface(s) NAT..............: ~p~n"
- "Local Interface (default).....: ~p~n"
- "Nodes in domain...............: ~p~n"
- "GIOP version (default)........: ~p.~p~n"
- "IIOP out timeout..............: ~p msec~n"
- "IIOP out connection timeout...: ~p msec~n"
- "IIOP setup connection timeout.: ~p msec~n"
- "IIOP out ports................: ~p~n"
- "IIOP out ports attempts.......: ~p~n"
- "IIOP out ports random.........: ~p~n"
- "IIOP out connections..........: ~p~n"
- "IIOP out connections (pending): ~p~n"
- "IIOP out keepalive............: ~p~n"
- "IIOP in connections...........: ~p~n"
- "IIOP in connection timeout....: ~p msec~n"
- "IIOP in keepalive.............: ~p~n"
- "IIOP max fragments............: ~p~n"
- "IIOP max in requests..........: ~p~n"
- "IIOP max in connections.......: ~p~n"
- "IIOP backlog..................: ~p~n"
- "IIOP ACL......................: ~p~n"
- "IIOP maximum packet size......: ~p~n"
- "Object Keys GC interval.......: ~p~n"
- "Using Interceptors............: ~p~n"
- "Using Local Interceptors......: ~p~n"
- "Debug Level...................: ~p~n"
- "orbInitRef....................: ~p~n"
- "orbDefaultInitRef.............: ~p~n",
- [OrberVsn, domain(), iiop_port(), nat_iiop_port(), host(),
- nat_host(), ip_address_local(),
- orber:orber_nodes(), Major, Minor,
- iiop_timeout(), iiop_connection_timeout(),
- iiop_setup_connection_timeout(), iiop_out_ports(),
- iiop_out_ports_attempts(), iiop_out_ports_random(),
- orber:iiop_connections(out), orber:iiop_connections_pending(),
- iiop_out_keepalive(), orber:iiop_connections(in),
- iiop_in_connection_timeout(), iiop_in_keepalive(),
- iiop_max_fragments(), iiop_max_in_requests(),
- iiop_max_in_connections(), iiop_backlog(), iiop_acl(),
- iiop_packet_size(), objectkeys_gc_time(), get_interceptors(),
- get_local_interceptors(), get_debug_level(), get_ORBInitRef(),
- get_ORBDefaultInitRef()])].
-
-create_flag_info(Info) ->
- case get_flags() of
- ?ORB_ENV_INIT_FLAGS ->
- [Info, "System Flags Set..............: -\n"];
- Flags ->
- FlagData = check_flags(?ORB_ENV_FLAGS, Flags, []),
- [Info, "System Flags Set..............: \n", FlagData, "\n"]
- end.
-
-check_flags([], _, Acc) ->
- Acc;
-check_flags([{Flag, Txt}|T], Flags, Acc) when ?ORB_FLAG_TEST(Flags, Flag) ->
- check_flags(T, Flags, [" - ", Txt, "\n"|Acc]);
-check_flags([_|T], Flags, Acc) ->
- check_flags(T, Flags, Acc).
-
-
-create_security_info(no, Info) ->
- lists:flatten([Info, "=========================================\n"]);
-create_security_info(ssl, Info) ->
- lists:flatten([Info,
- io_lib:format("ORB security..................: ssl~n"
- "SSL generation................: ~p~n"
- "SSL IIOP in keepalive.........: ~p~n"
- "SSL IIOP out keepalive........: ~p~n"
- "SSL IIOP port number..........: ~p~n"
- "SSL IIOP NAT port number......: ~p~n"
- "SSL IIOP accept timeout.......: ~p~n"
- "SSL IIOP backlog..............: ~p~n"
- "SSL IIOP Local Interface......: ~p~n"
- "SSL server options............: ~p~n"
- "SSL server certfile...........: ~p~n"
- "SSL server verification type..: ~p~n"
- "SSL server verification depth.: ~p~n"
- "SSL server cacertfile.........: ~p~n"
- "SSL server keyfile............: ~p~n"
- "SSL server password...........: ~p~n"
- "SSL server ciphers............: ~p~n"
- "SSL server cachetimeout.......: ~p~n"
- "SSL client options............: ~p~n"
- "SSL client certfile...........: ~p~n"
- "SSL client verification type..: ~p~n"
- "SSL client verification depth.: ~p~n"
- "SSL client cacertfile.........: ~p~n"
- "SSL client keyfile............: ~p~n"
- "SSL client password...........: ~p~n"
- "SSL client ciphers............: ~p~n"
- "SSL client cachetimeout.......: ~p~n"
- "=========================================~n",
- [ssl_generation(), iiop_ssl_port(),
- iiop_ssl_in_keepalive(), iiop_ssl_out_keepalive(),
- nat_iiop_ssl_port(), iiop_ssl_accept_timeout(),
- iiop_ssl_backlog(), iiop_ssl_ip_address_local(),
- ssl_server_options(),
- ssl_server_certfile(), ssl_server_verify(),
- ssl_server_depth(), ssl_server_cacertfile(),
- ssl_server_keyfile(), ssl_server_password(),
- ssl_server_ciphers(), ssl_server_cachetimeout(),
- ssl_client_options(),
- ssl_client_certfile(), ssl_client_verify(),
- ssl_client_depth(), ssl_client_cacertfile(),
- ssl_client_keyfile(), ssl_client_password(),
- ssl_client_ciphers(), ssl_client_cachetimeout()])]).
-
-
-%%-----------------------------------------------------------------
-%% function : iiop_acl
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%-----------------------------------------------------------------
-iiop_acl() ->
- case application:get_env(orber, iiop_acl) of
- {ok, ACL} when is_list(ACL) ->
- ACL;
- _ ->
- []
- end.
-
-iiop_packet_size() ->
- case application:get_env(orber, iiop_packet_size) of
- {ok, Max} when is_integer(Max) andalso Max > 0 ->
- Max;
- _ ->
- infinity
- end.
-
-
-iiop_port() ->
- case application:get_env(orber, iiop_port) of
- {ok, Port} when is_integer(Port) andalso Port >= 0 ->
- Port;
- _ ->
- 4001
- end.
-
-nat_iiop_port() ->
- case application:get_env(orber, nat_iiop_port) of
- {ok, Port} when is_integer(Port) andalso Port > 0 ->
- Port;
- {ok, {local, Default, _NATList}} ->
- Default;
- _ ->
- iiop_port()
- end.
-
-nat_iiop_port(LocalPort) ->
- case application:get_env(orber, nat_iiop_port) of
- {ok, Port} when is_integer(Port) andalso Port > 0 ->
- Port;
- {ok, {local, Default, NATList}} ->
- orber_tb:keysearch(LocalPort, NATList, Default);
- _ ->
- iiop_port()
- end.
-
-iiop_out_ports() ->
- case application:get_env(orber, iiop_out_ports) of
- {ok, {Min, Max}} when is_integer(Min) andalso is_integer(Max) andalso Min =< Max ->
- {Min, Max};
- {ok, {Max, Min}} when is_integer(Min) andalso is_integer(Max) andalso Min < Max ->
- {Min, Max};
- _ ->
- 0
- end.
-
-iiop_out_ports_random() ->
- case application:get_env(orber, iiop_out_ports_random) of
- {ok, true} ->
- true;
- _ ->
- false
- end.
-
-iiop_out_ports_attempts() ->
- case application:get_env(orber, iiop_out_ports_attempts) of
- {ok, No} when is_integer(No) andalso No > 0 ->
- No;
- _ ->
- 1
- end.
-
-
-domain() ->
- case application:get_env(orber, domain) of
- {ok, Domain} when is_list(Domain) ->
- Domain;
- {ok, Domain} when is_atom(Domain) ->
- atom_to_list(Domain);
- _ ->
- "ORBER"
- end.
-
-ip_address_variable_defined() ->
- case application:get_env(orber, ip_address) of
- undefined ->
- false;
- {ok,{multiple, _}} ->
- false;
- _ ->
- [Host] = host(),
- Host
- end.
-
-nat_host() ->
- case application:get_env(orber, nat_ip_address) of
- {ok,I} when is_list(I) ->
- [I];
- {ok,{multiple, [I|_] = IList}} when is_list(I) ->
- IList;
- {ok,{local, Default, _NATList}} ->
- [Default];
- _ ->
- host()
- end.
-
-nat_host([Host]) ->
- case application:get_env(orber, nat_ip_address) of
- {ok,I} when is_list(I) ->
- [I];
- {ok,{multiple, [I|_] = IList}} when is_list(I) ->
- IList;
- {ok,{local, Default, NATList}} ->
- [orber_tb:keysearch(Host, NATList, Default)];
- _ ->
- host()
- end.
-
-
-host() ->
- case application:get_env(orber, ip_address) of
- {ok,I} when is_list(I) ->
- [I];
- {ok,{multiple, [I|_] = IList}} when is_list(I) ->
- IList;
- %% IPv4. For IPv6 we only accept a string, but we must support this format
- %% for IPv4
- {ok, {A1, A2, A3, A4}} when is_integer(A1+A2+A3+A4) ->
- [integer_to_list(A1) ++ "." ++ integer_to_list(A2) ++ "." ++ integer_to_list(A3)
- ++ "." ++ integer_to_list(A4)];
- _ ->
- Flags = get_flags(),
- case ?ORB_FLAG_TEST(Flags, ?ORB_ENV_HOSTNAME_IN_IOR) of
- true ->
- {ok, Hostname} = inet:gethostname(),
- [Hostname];
- _ ->
- case ?ORB_FLAG_TEST(Flags, ?ORB_ENV_USE_IPV6) of
- false ->
- [ip_address(inet)];
- true ->
- [ip_address(inet6)]
- end
- end
- end.
-
-ip_address_local() ->
- case application:get_env(orber, ip_address_local) of
- {ok,I} when is_list(I) ->
- [I];
- _ ->
- []
- end.
-
-
-ip_address() ->
- ip_address(ip_version()).
-
-ip_address(inet) ->
- {ok, Hostname} = inet:gethostname(),
- {ok, {A1, A2, A3, A4}} = inet:getaddr(Hostname, inet),
- integer_to_list(A1) ++ "." ++ integer_to_list(A2) ++ "." ++ integer_to_list(A3)
- ++ "." ++ integer_to_list(A4);
-ip_address(inet6) ->
- {ok, Hostname} = inet:gethostname(),
- {ok, {A1, A2, A3, A4, A5, A6, A7, A8}} = inet:getaddr(Hostname, inet6),
- int16_to_hex(A1) ++ ":" ++int16_to_hex(A2) ++ ":" ++
- int16_to_hex(A3) ++ ":" ++ int16_to_hex(A4) ++ ":" ++
- int16_to_hex(A5) ++ ":" ++ int16_to_hex(A6) ++ ":" ++
- int16_to_hex(A7) ++ ":" ++ int16_to_hex(A8).
-
-getaddrstr(Hostname, inet) ->
- {ok, {A1, A2, A3, A4}} = inet:getaddr(Hostname, inet),
- integer_to_list(A1) ++ "." ++ integer_to_list(A2) ++ "." ++ integer_to_list(A3)
- ++ "." ++ integer_to_list(A4);
-getaddrstr(Hostname, inet6) ->
- {ok, {A1, A2, A3, A4, A5, A6, A7, A8}} = inet:getaddr(Hostname, inet6),
- int16_to_hex(A1) ++ ":" ++int16_to_hex(A2) ++ ":" ++
- int16_to_hex(A3) ++ ":" ++ int16_to_hex(A4) ++ ":" ++
- int16_to_hex(A5) ++ ":" ++ int16_to_hex(A6) ++ ":" ++
- int16_to_hex(A7) ++ ":" ++ int16_to_hex(A8).
-
-addr2str({A1, A2, A3, A4}) ->
- integer_to_list(A1) ++ "." ++ integer_to_list(A2) ++ "." ++ integer_to_list(A3)
- ++ "." ++ integer_to_list(A4);
-addr2str({A1, A2, A3, A4, A5, A6, A7, A8}) ->
- int16_to_hex(A1) ++ ":" ++int16_to_hex(A2) ++ ":" ++
- int16_to_hex(A3) ++ ":" ++ int16_to_hex(A4) ++ ":" ++
- int16_to_hex(A5) ++ ":" ++ int16_to_hex(A6) ++ ":" ++
- int16_to_hex(A7) ++ ":" ++ int16_to_hex(A8).
-
-
-int16_to_hex(0) ->
- [$0];
-int16_to_hex(I) ->
- N1 = ((I bsr 8) band 16#ff),
- N2 = (I band 16#ff),
- [code_character(N1 div 16), code_character(N1 rem 16),
- code_character(N2 div 16), code_character(N2 rem 16)].
-
-code_character(N) when N < 10 ->
- $0 + N;
-code_character(N) ->
- $A + (N - 10).
-
-giop_version() ->
- case application:get_env(orber, giop_version) of
- {ok, {Major, Minor}} ->
- {Major, Minor};
- _ ->
- {1, 1}
- end.
-
-iiop_timeout() ->
- case application:get_env(orber, iiop_timeout) of
- {ok, Int} when is_integer(Int) ->
- if
- Int > 1000000 ->
- error_logger:error_msg("Orber 'iiop_timeout' badly configured.~n"
- "Time to large (>1000000 sec), swithed to 'infinity'~n"),
- infinity;
- true ->
- %% Convert to msec.
- Int*1000
- end;
- _ ->
- infinity
- end.
-
-iiop_connection_timeout() ->
- case application:get_env(orber, iiop_connection_timeout) of
- {ok, Int} when is_integer(Int) ->
- if
- Int > 1000000 ->
- error_logger:error_msg("Orber 'iiop_connection_timeout' badly configured.~n"
- "Time to large (>1000000 sec), swithed to 'infinity'~n"),
- infinity;
- true ->
- %% Convert to msec.
- Int*1000
- end;
- _ ->
- infinity
- end.
-
-iiop_setup_connection_timeout() ->
- case application:get_env(orber, iiop_setup_connection_timeout) of
- {ok, Int} when is_integer(Int) ->
- %% Convert to msec.
- Int*1000;
- _ ->
- infinity
- end.
-
-iiop_in_connection_timeout() ->
- case application:get_env(orber, iiop_in_connection_timeout) of
- {ok, Int} when is_integer(Int) ->
- if
- Int > 1000000 ->
- error_logger:error_msg("Orber 'iiop_connection_timeout' badly configured.~n"
- "Time to large (>1000000 sec), swithed to 'infinity'~n"),
- infinity;
- true ->
- %% Convert to msec.
- Int*1000
- end;
- _ ->
- infinity
- end.
-
-iiop_max_fragments() ->
- case application:get_env(orber, iiop_max_fragments) of
- {ok, Max} when is_integer(Max) andalso Max > 0 ->
- Max;
- _ ->
- infinity
- end.
-
-iiop_max_in_requests() ->
- case application:get_env(orber, iiop_max_in_requests) of
- {ok, Max} when is_integer(Max) andalso Max > 0 ->
- Max;
- _ ->
- infinity
- end.
-
-iiop_max_in_connections() ->
- case application:get_env(orber, iiop_max_in_connections) of
- {ok, Max} when is_integer(Max) andalso Max > 0 ->
- Max;
- _ ->
- infinity
- end.
-
-iiop_backlog() ->
- case application:get_env(orber, iiop_backlog) of
- {ok, Int} when is_integer(Int) andalso Int >= 0 ->
- Int;
- _ ->
- 5
- end.
-
-iiop_in_keepalive() ->
- case application:get_env(orber, iiop_in_keepalive) of
- {ok, true} ->
- true;
- _ ->
- false
- end.
-
-iiop_out_keepalive() ->
- case application:get_env(orber, iiop_out_keepalive) of
- {ok, true} ->
- true;
- _ ->
- false
- end.
-
-
-
-get_flags() ->
- case get(oe_orber_flags) of
- undefined ->
- case application:get_env(orber, flags) of
- undefined ->
- put(oe_orber_flags, ?ORB_ENV_INIT_FLAGS),
- ?ORB_ENV_INIT_FLAGS;
- {ok, Flags} ->
- put(oe_orber_flags, Flags),
- Flags
- end;
- Flags when is_integer(Flags) ->
- Flags
- end.
-
-typechecking() ->
- ?ORB_FLAG_TEST(get_flags(), ?ORB_ENV_LOCAL_TYPECHECKING).
-
-exclude_codeset_ctx() ->
- ?ORB_FLAG_TEST(get_flags(), ?ORB_ENV_EXCLUDE_CODESET_CTX).
-
-exclude_codeset_component() ->
- ?ORB_FLAG_TEST(get_flags(), ?ORB_ENV_EXCLUDE_CODESET_COMPONENT).
-
-partial_security() ->
- ?ORB_FLAG_TEST(get_flags(), ?ORB_ENV_PARTIAL_SECURITY).
-
-use_CSIv2() ->
- ?ORB_FLAG_TEST(get_flags(), ?ORB_ENV_USE_CSIV2).
-
-use_FT() ->
- ?ORB_FLAG_TEST(get_flags(), ?ORB_ENV_USE_FT).
-
-ip_version() ->
- case ?ORB_FLAG_TEST(get_flags(), ?ORB_ENV_USE_IPV6) of
- false ->
- inet;
- true ->
- inet6
- end.
-
-light_ifr() ->
- ?ORB_FLAG_TEST(get_flags(), ?ORB_ENV_LIGHT_IFR).
-
-bidir_context() ->
- Flags = get_flags(),
- if
- ?ORB_FLAG_TEST(Flags, ?ORB_ENV_USE_BI_DIR_IIOP) ->
- [#'IOP_ServiceContext'
- {context_id=?IOP_BI_DIR_IIOP,
- context_data =
- #'IIOP_BiDirIIOPServiceContext'{listen_points =
- [#'IIOP_ListenPoint'{host=host(),
- port=iiop_port()}]}}];
- true ->
- []
- end.
-
-objectkeys_gc_time() ->
- case application:get_env(orber, objectkeys_gc_time) of
- {ok, Int} when is_integer(Int) ->
- if
- Int > 1000000 ->
- error_logger:error_msg("Orber 'objectkeys_gc_time' badly configured.~n"
- "Time to large (>1000000 sec), swithed to 'infinity'~n"),
- infinity;
- true ->
- Int
- end;
- _ ->
- infinity
- end.
-
-get_ORBInitRef() ->
- case application:get_env(orber, orbInitRef) of
- {ok, Ref} when is_list(Ref) ->
- Ref;
- _ ->
- undefined
- end.
-
-get_ORBDefaultInitRef() ->
- case application:get_env(orber, orbDefaultInitRef) of
- {ok, Ref} when is_list(Ref) ->
- Ref;
- _ ->
- undefined
- end.
-
-get_debug_level() ->
- case application:get_env(orber, orber_debug_level) of
- {ok, Level} when is_integer(Level) ->
- Level;
- _ ->
- 0
- end.
-
-
-%%-----------------------------------------------------------------
-%% Interceptor opertaions (see orber_pi.erl)
-%%-----------------------------------------------------------------
-get_interceptors() ->
- case application:get_env(orber, interceptors) of
- {ok, {native, PIs}} when is_list(PIs) ->
- {native, PIs};
- {ok, {portable, PIs}} when is_list(PIs) ->
- {portable, PIs};
- _ ->
- false
- end.
-
-get_local_interceptors() ->
- case application:get_env(orber, local_interceptors) of
- {ok, {native, PIs}} when is_list(PIs) ->
- {native, PIs};
- {ok, {portable, PIs}} when is_list(PIs) ->
- {portable, PIs};
- _ ->
- false
- end.
-
-
-get_cached_interceptors() ->
- case get(oe_orber_interceptor_cache) of
- undefined ->
- PIs = case application:get_env(orber, local_interceptors) of
- {ok, {native, LPIs}} when is_list(LPIs) ->
- {native, LPIs};
- {ok, {portable, LPIs}} when is_list(LPIs) ->
- {portable, LPIs};
- _ ->
- get_interceptors()
- end,
- put(oe_orber_interceptor_cache, PIs),
- PIs;
- PIs ->
- PIs
- end.
-
-
-set_interceptors({Type, InterceptorList}) when is_list(InterceptorList) ->
- configure(interceptors, {Type, InterceptorList});
-set_interceptors(_) ->
- exit({error, "Usage: {Type, ModuleList}"}).
-
-
-%%-----------------------------------------------------------------
-%% Light weight Orber operations
-%%-----------------------------------------------------------------
-is_lightweight() ->
- case application:get_env(orber, lightweight) of
- {ok, L} when is_list(L) ->
- true;
- _ ->
- false
- end.
-get_lightweight_nodes() ->
- case application:get_env(orber, lightweight) of
- {ok, L} when is_list(L) ->
- L;
- _ ->
- false
- end.
-
-
-%%-----------------------------------------------------------------
-%% Security access operations (SSL)
-%%-----------------------------------------------------------------
-secure() ->
- case application:get_env(orber, secure) of
- {ok, V} ->
- V;
- _ ->
- no
- end.
-
-ssl_generation() ->
- case application:get_env(orber, ssl_generation) of
- {ok, V} ->
- V;
- _ ->
- 2
- end.
-
-iiop_ssl_ip_address_local() ->
- case application:get_env(orber, iiop_ssl_ip_address_local) of
- {ok,I} when is_list(I) ->
- [I];
- _ ->
- []
- end.
-
-iiop_ssl_backlog() ->
- case application:get_env(orber, iiop_ssl_backlog) of
- {ok, Int} when is_integer(Int), Int >= 0 ->
- Int;
- _ ->
- 5
- end.
-
-iiop_ssl_in_keepalive() ->
- case application:get_env(orber, iiop_ssl_in_keepalive) of
- {ok, true} ->
- true;
- _ ->
- false
- end.
-
-iiop_ssl_out_keepalive() ->
- case application:get_env(orber, iiop_ssl_out_keepalive) of
- {ok, true} ->
- true;
- _ ->
- false
- end.
-
-iiop_ssl_accept_timeout() ->
- case application:get_env(orber, iiop_ssl_accept_timeout) of
- {ok, N} when is_integer(N) ->
- N * 1000;
- _ ->
- infinity
- end.
-
-iiop_ssl_port() ->
- case application:get_env(orber, secure) of
- {ok, ssl} ->
- case application:get_env(orber, iiop_ssl_port) of
- {ok, Port} when is_integer(Port) ->
- Port;
- _ ->
- 4002
- end;
- _ ->
- -1
- end.
-
-nat_iiop_ssl_port() ->
- case application:get_env(orber, secure) of
- {ok, ssl} ->
- case application:get_env(orber, nat_iiop_ssl_port) of
- {ok, Port} when is_integer(Port) andalso Port > 0 ->
- Port;
- {ok, {local, Default, _NATList}} ->
- Default;
- _ ->
- iiop_ssl_port()
- end;
- _ ->
- -1
- end.
-
-nat_iiop_ssl_port(LocalPort) ->
- case application:get_env(orber, secure) of
- {ok, ssl} ->
- case application:get_env(orber, nat_iiop_ssl_port) of
- {ok, Port} when is_integer(Port) andalso Port > 0 ->
- Port;
- {ok, {local, Default, NATList}} ->
- orber_tb:keysearch(LocalPort, NATList, Default);
- _ ->
- iiop_ssl_port()
- end;
- _ ->
- -1
- end.
-
-ssl_server_options() ->
- case application:get_env(orber, ssl_server_options) of
- {ok, V1} when is_list(V1) ->
- V1;
- _ ->
- []
- end.
-
-ssl_client_options() ->
- case application:get_env(orber, ssl_client_options) of
- {ok, V1} when is_list(V1) ->
- V1;
- _ ->
- []
- end.
-
-check_ssl_opts(Value) ->
- check_ssl_opts(Value, []).
-check_ssl_opts([], []) ->
- ok;
-check_ssl_opts([], Acc) ->
- {error, Acc};
-check_ssl_opts([{active, _} |T], Acc) ->
- check_ssl_opts(T, [active |Acc]);
-check_ssl_opts([{packet, _} |T], Acc) ->
- check_ssl_opts(T, [packet |Acc]);
-check_ssl_opts([{mode, _} |T], Acc) ->
- check_ssl_opts(T, [mode |Acc]);
-check_ssl_opts([list |T], Acc) ->
- check_ssl_opts(T, [list |Acc]);
-check_ssl_opts([binary |T], Acc) ->
- check_ssl_opts(T, [binary |Acc]);
-check_ssl_opts([_ |T], Acc) ->
- check_ssl_opts(T, Acc).
-
-set_ssl_client_options(Value) when is_list(Value) ->
- case check_ssl_opts(Value) of
- ok ->
- ok;
- {error, List} ->
- exit(lists:flatten(
- io_lib:format("TCP options ~p is not allowed in set_ssl_client_options()",
- [List])))
- end,
- put(ssl_client_options, Value), ok.
-
-ssl_server_certfile() ->
- case application:get_env(orber, ssl_server_certfile) of
- {ok, V1} when is_list(V1) ->
- V1;
- {ok, V2} when is_atom(V2) ->
- atom_to_list(V2);
- _ ->
- []
- end.
-
-ssl_client_certfile() ->
- case get(ssl_client_certfile) of
- undefined ->
- case application:get_env(orber, ssl_client_certfile) of
- {ok, V1} when is_list(V1) ->
- V1;
- {ok, V2} when is_atom(V2) ->
- atom_to_list(V2);
- _ ->
- []
- end;
- V ->
- V
- end.
-
-set_ssl_client_certfile(Value) when is_list(Value) ->
- put(ssl_client_certfile, Value).
-
-ssl_server_verify() ->
- Verify = case application:get_env(orber, ssl_server_verify) of
- {ok, V} when is_integer(V) ->
- V;
- _ ->
- 0
- end,
- if
- Verify =< 2, Verify >= 0 ->
- Verify;
- true ->
- 0
- end.
-
-ssl_client_verify() ->
- Verify = case get(ssl_client_verify) of
- undefined ->
- case application:get_env(orber, ssl_client_verify) of
- {ok, V1} when is_integer(V1) ->
- V1;
- _ ->
- 0
- end;
- V2 ->
- V2
- end,
- if
- Verify =< 2, Verify >= 0 ->
- Verify;
- true ->
- 0
- end.
-
-set_ssl_client_verify(Value) when is_integer(Value) andalso Value =< 2 andalso Value >= 0 ->
- put(ssl_client_verify, Value), ok.
-
-ssl_server_depth() ->
- case application:get_env(orber, ssl_server_depth) of
- {ok, V1} when is_integer(V1) ->
- V1;
- _ ->
- 1
- end.
-
-ssl_client_depth() ->
- case get(ssl_client_depth) of
- undefined ->
- case application:get_env(orber, ssl_client_depth) of
- {ok, V1} when is_integer(V1) ->
- V1;
- _ ->
- 1
- end;
- V2 ->
- V2
- end.
-
-set_ssl_client_depth(Value) when is_integer(Value) ->
- put(ssl_client_depth, Value), ok.
-
-
-
-ssl_server_cacertfile() ->
- case application:get_env(orber, ssl_server_cacertfile) of
- {ok, V1} when is_list(V1) ->
- V1;
- {ok, V2} when is_atom(V2) ->
- atom_to_list(V2);
- _ ->
- []
- end.
-
-ssl_client_cacertfile() ->
- case get(ssl_client_cacertfile) of
- undefined ->
- case application:get_env(orber, ssl_client_cacertfile) of
- {ok, V1} when is_list(V1) ->
- V1;
- {ok, V2} when is_atom(V2) ->
- atom_to_list(V2);
- _ ->
- []
- end;
- V3 ->
- V3
- end.
-
-set_ssl_client_cacertfile(Value) when is_list(Value) ->
- put(ssl_client_cacertfile, Value), ok.
-
-
-ssl_client_password() ->
- case application:get_env(orber, ssl_client_password) of
- {ok, V1} when is_list(V1) ->
- V1;
- _ ->
- []
- end.
-
-ssl_server_password() ->
- case application:get_env(orber, ssl_server_password) of
- {ok, V1} when is_list(V1) ->
- V1;
- _ ->
- []
- end.
-
-ssl_client_keyfile() ->
- case application:get_env(orber, ssl_client_keyfile) of
- {ok, V1} when is_list(V1) ->
- V1;
- _ ->
- []
- end.
-
-ssl_server_keyfile() ->
- case application:get_env(orber, ssl_server_keyfile) of
- {ok, V1} when is_list(V1) ->
- V1;
- _ ->
- []
- end.
-
-ssl_client_ciphers() ->
- case application:get_env(orber, ssl_client_ciphers) of
- {ok, V1} when is_list(V1) ->
- V1;
- _ ->
- []
- end.
-
-ssl_server_ciphers() ->
- case application:get_env(orber, ssl_server_ciphers) of
- {ok, V1} when is_list(V1) ->
- V1;
- _ ->
- []
- end.
-
-ssl_client_cachetimeout() ->
- case application:get_env(orber, ssl_client_cachetimeout) of
- {ok, V1} when is_integer(V1) ->
- V1;
- _ ->
- infinity
- end.
-
-ssl_server_cachetimeout() ->
- case application:get_env(orber, ssl_server_cachetimeout) of
- {ok, V1} when is_integer(V1) ->
- V1;
- _ ->
- infinity
- end.
-
-%%-----------------------------------------------------------------
-%% function : configure
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%-----------------------------------------------------------------
-configure(Key, Value) when is_atom(Key) ->
- configure(Key, Value, check);
-configure(Key, _) ->
- ?EFORMAT("Given key (~p) not an atom.", [Key]).
-
-configure_override(Key, Value) when is_atom(Key) ->
- configure(Key, Value, loaded);
-configure_override(Key, _) ->
- ?EFORMAT("Given key (~p) not an atom.", [Key]).
-
-%%-----------------------------------------------------------------
-%% function : multi_configure
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%-----------------------------------------------------------------
-multi_configure(KeyValueList) when is_list(KeyValueList) ->
- case orber_tb:is_loaded() of
- false ->
- application:load(orber),
- multi_configure_helper(KeyValueList, loaded);
- true ->
- case orber_tb:is_running() of
- false ->
- multi_configure_helper(KeyValueList, loaded);
- true ->
- multi_configure_helper(KeyValueList, running)
- end
- end;
-multi_configure(KeyValueList) ->
- ?EFORMAT("Given configuration parameters not a Key-Value-pair list: ~p",
- [KeyValueList]).
-
-multi_configure_helper([], _) ->
- ok;
-multi_configure_helper([{Key, Value}|T], Status) ->
- configure(Key, Value, Status),
- multi_configure_helper(T, Status);
-multi_configure_helper([What|_], _) ->
- ?EFORMAT("Incorrect configuration parameters supplied: ~p", [What]).
-
-
-%%------ Keys we can update at any time -----
-%% Initial Services References
-configure(orbDefaultInitRef, String, Status) when is_list(String) ->
- do_configure(orbDefaultInitRef, String, Status);
-configure(orbDefaultInitRef, undefined, Status) ->
- do_configure(orbDefaultInitRef, undefined, Status);
-configure(orbInitRef, String, Status) when is_list(String) ->
- do_configure(orbInitRef, String, Status);
-configure(orbInitRef, undefined, Status) ->
- do_configure(orbInitRef, undefined, Status);
-%% IIOP-version
-configure(giop_version, {1, 0}, Status) ->
- do_configure(giop_version, {1, 0}, Status);
-configure(giop_version, {1, 1}, Status) ->
- do_configure(giop_version, {1, 1}, Status);
-configure(giop_version, {1, 2}, Status) ->
- do_configure(giop_version, {1, 2}, Status);
-%% configure 'iiop_timout' will only have effect on new requests.
-configure(iiop_timeout, infinity, Status) ->
- do_configure(iiop_timeout, infinity, Status);
-configure(iiop_timeout, Value, Status) when is_integer(Value) andalso Value =< 1000000 ->
- do_configure(iiop_timeout, Value, Status);
-%% Backlog
-configure(iiop_backlog, Value, Status) when is_integer(Value) andalso Value >= 0 ->
- do_configure(iiop_backlog, Value, Status);
-%% configure 'iiop_in_keepalive' will only have effect on new connections.
-configure(iiop_in_keepalive, true, Status) ->
- do_configure(iiop_in_keepalive, true, Status);
-configure(iiop_in_keepalive, false, Status) ->
- do_configure(iiop_in_keepalive, false, Status);
-%% configure 'iiop_out_keepalive' will only have effect on new connections.
-configure(iiop_out_keepalive, true, Status) ->
- do_configure(iiop_out_keepalive, true, Status);
-configure(iiop_out_keepalive, false, Status) ->
- do_configure(iiop_out_keepalive, false, Status);
-%% configure 'iiop_connection_timout' will only have effect on new connections.
-configure(iiop_connection_timeout, infinity, Status) ->
- do_configure(iiop_connection_timeout, infinity, Status);
-configure(iiop_connection_timeout, Value, Status) when is_integer(Value) andalso Value =< 1000000 ->
- do_configure(iiop_connection_timeout, Value, Status);
-%% configure 'iiop_in_connection_timout' will only have effect on new connections.
-configure(iiop_in_connection_timeout, infinity, Status) ->
- do_configure(iiop_in_connection_timeout, infinity, Status);
-configure(iiop_in_connection_timeout, Value, Status) when is_integer(Value) andalso Value =< 1000000 ->
- do_configure(iiop_in_connection_timeout, Value, Status);
-%% configure 'iiop_setup_connection_timeout' will only have effect on new connections.
-configure(iiop_setup_connection_timeout, infinity, Status) ->
- do_configure(iiop_setup_connection_timeout, infinity, Status);
-configure(iiop_setup_connection_timeout, Value, Status) when is_integer(Value) ->
- do_configure(iiop_setup_connection_timeout, Value, Status);
-%% configure 'iiop_max_fragments' will only have effect on new connections.
-configure(iiop_max_fragments, infinity, Status) ->
- do_configure(iiop_max_fragments, infinity, Status);
-configure(iiop_max_fragments, Value, Status) when is_integer(Value) andalso Value > 0 ->
- do_configure(iiop_max_fragments, Value, Status);
-%% configure 'iiop_max_in_requests' will only have effect on new connections.
-configure(iiop_max_in_requests, infinity, Status) ->
- do_configure(iiop_max_in_requests, infinity, Status);
-configure(iiop_max_in_requests, Value, Status) when is_integer(Value) andalso Value > 0 ->
- do_configure(iiop_max_in_requests, Value, Status);
-%% configure 'iiop_max_in_connections' will only have effect on new connections.
-configure(iiop_max_in_connections, infinity, Status) ->
- do_configure(iiop_max_in_connections, infinity, Status);
-configure(iiop_max_in_connections, Value, Status) when is_integer(Value) andalso Value > 0 ->
- do_configure(iiop_max_in_connections, Value, Status);
-%% Garbage Collect the object keys DB.
-configure(objectkeys_gc_time, infinity, Status) ->
- do_configure(objectkeys_gc_time, infinity, Status);
-configure(objectkeys_gc_time, Value, Status) when is_integer(Value) andalso Value =< 1000000 ->
- do_configure(objectkeys_gc_time, Value, Status);
-%% Orber debug printouts
-configure(orber_debug_level, Value, Status) when is_integer(Value) ->
- do_configure(orber_debug_level, Value, Status);
-
-%%------ Keys we cannot change if Orber is running -----
-%% Set the listen port
-configure(iiop_port, Value, Status) when is_integer(Value) ->
- do_safe_configure(iiop_port, Value, Status);
-%% Set the NAT listen port
-configure(nat_iiop_port, Value, Status) when is_integer(Value) andalso Value > 0 ->
- do_safe_configure(nat_iiop_port, Value, Status);
-configure(nat_iiop_port, {local, Value1, Value2}, Status) when is_integer(Value1) andalso
- Value1 > 0 andalso
- is_list(Value2) ->
- do_safe_configure(nat_iiop_port, {local, Value1, Value2}, Status);
-%% Set Maximum Packet Size
-configure(iiop_packet_size, Max, Status) when is_integer(Max) andalso Max > 0 ->
- do_safe_configure(iiop_packet_size, Max, Status);
-%% IIOP interceptors
-configure(interceptors, Value, Status) when is_tuple(Value) ->
- do_safe_configure(interceptors, Value, Status);
-%% Local interceptors
-configure(local_interceptors, Value, Status) when is_tuple(Value) ->
- do_safe_configure(local_interceptors, Value, Status);
-%% Orber Domain
-configure(domain, Value, Status) when is_list(Value) ->
- do_safe_configure(domain, Value, Status);
-%% Set the IP-address we should use
-configure(ip_address, Value, Status) when is_list(Value) ->
- do_safe_configure(ip_address, Value, Status);
-configure(ip_address, {multiple, Value}, Status) when is_list(Value) ->
- do_safe_configure(ip_address, {multiple, Value}, Status);
-configure(ip_address_local, Value, Status) when is_list(Value) ->
- do_safe_configure(ip_address_local, Value, Status);
-%% Set the NAT IP-address we should use
-configure(nat_ip_address, Value, Status) when is_list(Value) ->
- do_safe_configure(nat_ip_address, Value, Status);
-configure(nat_ip_address, {multiple, Value}, Status) when is_list(Value) ->
- do_safe_configure(nat_ip_address, {multiple, Value}, Status);
-configure(nat_ip_address, {local, Value1, Value2}, Status) when is_list(Value1) andalso
- is_list(Value2) ->
- do_safe_configure(nat_ip_address, {local, Value1, Value2}, Status);
-%% Set the range of ports we may use on this machine when connecting to a server.
-configure(iiop_out_ports, {Min, Max}, Status) when is_integer(Min) andalso is_integer(Max) ->
- do_safe_configure(iiop_out_ports, {Min, Max}, Status);
-configure(iiop_out_ports_attempts, Max, Status) when is_integer(Max) andalso Max > 0 ->
- do_safe_configure(iiop_out_ports_attempts, Max, Status);
-configure(iiop_out_ports_random, true, Status) ->
- do_safe_configure(iiop_out_ports_random, true, Status);
-configure(iiop_out_ports_random, false, Status) ->
- do_safe_configure(iiop_out_ports_random, false, Status);
-%% Set the lightweight option.
-configure(lightweight, Value, Status) when is_list(Value) ->
- do_safe_configure(lightweight, Value, Status);
-%% Configre the System Flags
-configure(flags, Value, Status) when is_integer(Value) ->
- do_safe_configure(flags, Value, Status);
-%% Configre the ACL
-configure(iiop_acl, Value, Status) when is_list(Value) ->
- do_safe_configure(iiop_acl, Value, Status);
-
-%% SSL settings
-%% configure 'iiop_in_keepalive' will only have effect on new connections.
-configure(iiop_ssl_in_keepalive, true, Status) ->
- do_configure(iiop_ssl_in_keepalive, true, Status);
-configure(iiop_ssl_in_keepalive, false, Status) ->
- do_configure(iiop_ssl_in_keepalive, false, Status);
-%% configure 'iiop_ssl_out_keepalive' will only have effect on new connections.
-configure(iiop_ssl_out_keepalive, true, Status) ->
- do_configure(iiop_ssl_out_keepalive, true, Status);
-configure(iiop_ssl_out_keepalive, false, Status) ->
- do_configure(iiop_ssl_out_keepalive, false, Status);
-configure(iiop_ssl_accept_timeout, infinity, Status) ->
- do_configure(iiop_ssl_accept_timeout, infinity, Status);
-configure(iiop_ssl_accept_timeout, Value, Status) when is_integer(Value) andalso Value >= 0 ->
- do_configure(iiop_ssl_accept_timeout, Value, Status);
-configure(ssl_generation, Generation, Status) when is_integer(Generation) andalso Generation >= 2 ->
- do_safe_configure(ssl_generation, Generation, Status);
-configure(secure, ssl, Status) ->
- do_safe_configure(secure, ssl, Status);
-configure(iiop_ssl_ip_address_local, Value, Status) when is_list(Value) ->
- do_safe_configure(iiop_ssl_ip_address_local, Value, Status);
-configure(iiop_ssl_backlog, Value, Status) when is_integer(Value) andalso Value >= 0 ->
- do_safe_configure(iiop_ssl_backlog, Value, Status);
-configure(nat_iiop_ssl_port, Value, Status) when is_integer(Value) andalso Value > 0 ->
- do_safe_configure(nat_iiop_ssl_port, Value, Status);
-configure(nat_iiop_ssl_port, {local, Value1, Value2}, Status) when is_integer(Value1) andalso
- Value1 > 0 andalso
- is_list(Value2) ->
- do_safe_configure(nat_iiop_ssl_port, {local, Value1, Value2}, Status);
-configure(iiop_ssl_port, Value, Status) when is_integer(Value) ->
- do_safe_configure(iiop_ssl_port, Value, Status);
-
-%% New SSL options
-configure(ssl_server_options, Value, Status) when is_list(Value) ->
- do_safe_configure(ssl_server_options, Value, Status);
-configure(ssl_client_options, Value, Status) when is_list(Value) ->
- do_safe_configure(ssl_client_options, Value, Status);
-
-%% Old SSL options
-configure(ssl_server_certfile, Value, Status) when is_list(Value) ->
- do_safe_configure(ssl_server_certfile, Value, Status);
-configure(ssl_server_certfile, Value, Status) when is_atom(Value) ->
- do_safe_configure(ssl_server_certfile, atom_to_list(Value), Status);
-configure(ssl_client_certfile, Value, Status) when is_list(Value) ->
- do_safe_configure(ssl_client_certfile, Value, Status);
-configure(ssl_client_certfile, Value, Status) when is_atom(Value) ->
- do_safe_configure(ssl_client_certfile, atom_to_list(Value), Status);
-configure(ssl_server_verify, Value, Status) when is_integer(Value) ->
- do_safe_configure(ssl_server_verify, Value, Status);
-configure(ssl_client_verify, Value, Status) when is_integer(Value) ->
- do_safe_configure(ssl_client_verify, Value, Status);
-configure(ssl_server_depth, Value, Status) when is_integer(Value) ->
- do_safe_configure(ssl_server_depth, Value, Status);
-configure(ssl_client_depth, Value, Status) when is_integer(Value) ->
- do_safe_configure(ssl_client_depth, Value, Status);
-configure(ssl_server_cacertfile, Value, Status) when is_list(Value) ->
- do_safe_configure(ssl_server_cacertfile, Value, Status);
-configure(ssl_server_cacertfile, Value, Status) when is_atom(Value) ->
- do_safe_configure(ssl_server_cacertfile, atom_to_list(Value), Status);
-configure(ssl_client_cacertfile, Value, Status) when is_list(Value) ->
- do_safe_configure(ssl_client_cacertfile, Value, Status);
-configure(ssl_client_cacertfile, Value, Status) when is_atom(Value) ->
- do_safe_configure(ssl_client_cacertfile, atom_to_list(Value), Status);
-configure(ssl_client_password, Value, Status) when is_list(Value) ->
- do_safe_configure(ssl_client_password, Value, Status);
-configure(ssl_client_password, Value, Status) when is_atom(Value) ->
- do_safe_configure(ssl_client_password, atom_to_list(Value), Status);
-configure(ssl_client_keyfile, Value, Status) when is_list(Value) ->
- do_safe_configure(ssl_client_keyfile, Value, Status);
-configure(ssl_client_keyfile, Value, Status) when is_atom(Value) ->
- do_safe_configure(ssl_client_keyfile, atom_to_list(Value), Status);
-configure(ssl_server_password, Value, Status) when is_list(Value) ->
- do_safe_configure(ssl_server_password, Value, Status);
-configure(ssl_client_password, Value, Status) when is_atom(Value) ->
- do_safe_configure(ssl_server_password, atom_to_list(Value), Status);
-configure(ssl_server_keyfile, Value, Status) when is_list(Value) ->
- do_safe_configure(ssl_server_keyfile, Value, Status);
-configure(ssl_server_keyfile, Value, Status) when is_atom(Value) ->
- do_safe_configure(ssl_server_keyfile, atom_to_list(Value), Status);
-configure(ssl_server_ciphers, Value, Status) when is_list(Value) ->
- do_safe_configure(ssl_server_ciphers, Value, Status);
-configure(ssl_server_ciphers, Value, Status) when is_atom(Value) ->
- do_safe_configure(ssl_server_ciphers, atom_to_list(Value), Status);
-configure(ssl_client_ciphers, Value, Status) when is_list(Value) ->
- do_safe_configure(ssl_client_ciphers, Value, Status);
-configure(ssl_client_ciphers, Value, Status) when is_atom(Value) ->
- do_safe_configure(ssl_client_ciphers, atom_to_list(Value), Status);
-configure(ssl_client_cachetimeout, Value, Status) when is_integer(Value) andalso Value > 0 ->
- do_safe_configure(ssl_client_cachetimeout, Value, Status);
-configure(ssl_server_cachetimeout, Value, Status) when is_integer(Value) andalso Value > 0 ->
- do_safe_configure(ssl_server_cachetimeout, Value, Status);
-
-configure(Key, Value, _) ->
- ?EFORMAT("Bad configuration parameter: {~p, ~p}", [Key, Value]).
-
-%% This function may be used as long as it is safe to change a value at any time.
-do_configure(Key, Value, check) ->
- case orber_tb:is_loaded() of
- false ->
- application:load(orber),
- application:set_env(orber, Key, Value);
- true ->
- application:set_env(orber, Key, Value)
- end;
-do_configure(Key, Value, _) ->
- application:set_env(orber, Key, Value).
-
-%% This function MUST(!!) be used when we cannot change a value if Orber is running.
-do_safe_configure(_, _, running) ->
- exit("Orber already running, the given key may not be updated!");
-do_safe_configure(Key, Value, check) ->
- case orber_tb:is_loaded() of
- false ->
- application:load(orber),
- application:set_env(orber, Key, Value);
- true ->
- case orber_tb:is_running() of
- false ->
- application:set_env(orber, Key, Value);
- true ->
- ?EFORMAT("Orber already running. {~p, ~p} may not be updated!",
- [Key, Value])
- end
- end;
-do_safe_configure(Key, Value, loaded) ->
- application:set_env(orber, Key, Value).
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Server functions
-%%-----------------------------------------------------------------
-init(_Opts) ->
- {ok, #env{acl = orber_acl:init_acl(iiop_acl()),
- parameters = init_env()}}.
-
-terminate(_Reason, _State) ->
- ok.
-
-handle_call(_, _From, State) ->
- {reply, ok, State}.
-
-handle_cast(_, State) ->
- {noreply, State}.
-
-handle_info(_, State) ->
- {noreply, State}.
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%-----------------------------------------------------------------
-%% function : env
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect : Used when Key always exists (Default Value)
-%%-----------------------------------------------------------------
-env(Key) ->
- [#parameters{value = Val}] = ets:lookup(?ENV_DB, Key),
- Val.
-
-%%-----------------------------------------------------------------
-%% function : init_env
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%-----------------------------------------------------------------
-init_env() ->
- application:load(orber),
- DB = ets:new(?ENV_DB, [set, public, named_table, {keypos, 2}]),
-% init_env(?ENV_KEYS),
- DB.
-
-%init_env([{H,D}|T]) ->
-% case application:get_env(orber, H) of
-% {ok, V} ->
-% ets:insert(?ENV_DB, #parameters{key = H, value = V, flags = 0}),
-% init_env(T);
-% _ ->
-% ets:insert(?ENV_DB, #parameters{key = H, value = D, flags = 0}),
-% init_env(T)
-% end;
-%init_env([H|T]) ->
-% case application:get_env(orber, H) of
-% {ok, V} ->
-% ets:insert(?ENV_DB, #parameters{key = H, value = V, flags = 0}),
-% init_env(T);
-% _ ->
-% ets:insert(?ENV_DB, #parameters{key = H, value = undefined, flags = 0}),
-% init_env(T)
-% end;
-%init_env([]) ->
-% ok.
-
-%%-----------------------------------------------------------------
-%%------------- END OF MODULE -------------------------------------
-%%-----------------------------------------------------------------
diff --git a/lib/orber/src/orber_exceptions.erl b/lib/orber/src/orber_exceptions.erl
deleted file mode 100644
index 2519775eb3..0000000000
--- a/lib/orber/src/orber_exceptions.erl
+++ /dev/null
@@ -1,718 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_exceptions.erl
-%%
-%% Description:
-%%
-%%-----------------------------------------------------------------
-
--module(orber_exceptions).
-
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/src/ifr_objects.hrl").
--include_lib("orber/include/ifr_types.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([dissect/1,
- get_def/1,
- get_name/2,
- type/1,
- is_system_exception/1]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export(['UNKNOWN'/1,
- 'BAD_PARAM'/1,
- 'NO_MEMORY'/1,
- 'IMP_LIMIT'/1,
- 'COMM_FAILURE'/1,
- 'INV_OBJREF'/1,
- 'NO_PERMISSION'/1,
- 'INTERNAL'/1,
- 'MARSHAL'/1,
- 'INITIALIZE'/1,
- 'NO_IMPLEMENT'/1,
- 'BAD_TYPECODE'/1,
- 'BAD_OPERATION'/1,
- 'NO_RESOURCES'/1,
- 'NO_RESPONSE'/1,
- 'PERSIST_STORE'/1,
- 'BAD_INV_ORDER'/1,
- 'TRANSIENT'/1,
- 'FREE_MEM'/1,
- 'INV_IDENT'/1,
- 'INV_FLAG'/1,
- 'INTF_REPOS'/1,
- 'BAD_CONTEXT'/1,
- 'OBJ_ADAPTER'/1,
- 'DATA_CONVERSION'/1,
- 'OBJECT_NOT_EXIST'/1,
- 'TRANSACTION_REQUIRED'/1,
- 'TRANSACTION_ROLLEDBACK'/1,
- 'INVALID_TRANSACTION'/1,
- 'INV_POLICY'/1,
- 'CODESET_INCOMPATIBLE'/1,
- 'REBIND'/1,
- 'TIMEOUT'/1,
- 'TRANSACTION_UNAVAILABLE'/1,
- 'TRANSACTION_MODE'/1,
- 'BAD_QOS'/1]).
-
-
--define(DEBUG_LEVEL, 5).
-
-%%-----------------------------------------------------------------
-%% Function : is_system_exception
-%% Arguments : Exception - record()
-%% Returns : true | false
-%% Raises :
-%% Description: Check if CORBA system exception or user defined
-%%-----------------------------------------------------------------
-is_system_exception({'EXCEPTION', E}) ->
- is_system_exception(E);
-is_system_exception(E) when is_tuple(E) ->
- ?SYSTEM_EXCEPTION == type(element(1, E));
-is_system_exception(_E) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%-----------------------------------------------------------------
-%% Function : type
-%% Arguments : ExceptionName - atom()
-%% Returns : ?SYSTEM_EXCEPTION | ?USER_EXCEPTION
-%% Raises :
-%% Description: Check if CORBA system exception or user defined
-%%-----------------------------------------------------------------
-type('UNKNOWN') -> ?SYSTEM_EXCEPTION;
-type('BAD_PARAM') -> ?SYSTEM_EXCEPTION;
-type('NO_MEMORY') -> ?SYSTEM_EXCEPTION;
-type('IMP_LIMIT') -> ?SYSTEM_EXCEPTION;
-type('COMM_FAILURE') -> ?SYSTEM_EXCEPTION;
-type('INV_OBJREF') -> ?SYSTEM_EXCEPTION;
-type('NO_PERMISSION') -> ?SYSTEM_EXCEPTION;
-type('INTERNAL') -> ?SYSTEM_EXCEPTION;
-type('MARSHAL') -> ?SYSTEM_EXCEPTION;
-type('INITIALIZE') -> ?SYSTEM_EXCEPTION;
-type('NO_IMPLEMENT') -> ?SYSTEM_EXCEPTION;
-type('BAD_TYPECODE') -> ?SYSTEM_EXCEPTION;
-type('BAD_OPERATION') -> ?SYSTEM_EXCEPTION;
-type('NO_RESOURCES') -> ?SYSTEM_EXCEPTION;
-type('NO_RESPONSE') -> ?SYSTEM_EXCEPTION;
-type('PERSIST_STORE') -> ?SYSTEM_EXCEPTION;
-type('BAD_INV_ORDER') -> ?SYSTEM_EXCEPTION;
-type('TRANSIENT') -> ?SYSTEM_EXCEPTION;
-type('FREE_MEM') -> ?SYSTEM_EXCEPTION;
-type('INV_IDENT') -> ?SYSTEM_EXCEPTION;
-type('INV_FLAG') -> ?SYSTEM_EXCEPTION;
-type('INTF_REPOS') -> ?SYSTEM_EXCEPTION;
-type('BAD_CONTEXT') -> ?SYSTEM_EXCEPTION;
-type('OBJ_ADAPTER') -> ?SYSTEM_EXCEPTION;
-type('DATA_CONVERSION') -> ?SYSTEM_EXCEPTION;
-type('OBJECT_NOT_EXIST') -> ?SYSTEM_EXCEPTION;
-type('TRANSACTION_REQUIRED') -> ?SYSTEM_EXCEPTION;
-type('TRANSACTION_ROLLEDBACK') -> ?SYSTEM_EXCEPTION;
-type('INVALID_TRANSACTION') -> ?SYSTEM_EXCEPTION;
-type('INV_POLICY') -> ?SYSTEM_EXCEPTION;
-type('CODESET_INCOMPATIBLE') -> ?SYSTEM_EXCEPTION;
-type('REBIND') -> ?SYSTEM_EXCEPTION;
-type('TIMEOUT') -> ?SYSTEM_EXCEPTION;
-type('TRANSACTION_UNAVAILABLE') -> ?SYSTEM_EXCEPTION;
-type('TRANSACTION_MODE') -> ?SYSTEM_EXCEPTION;
-type('BAD_QOS') -> ?SYSTEM_EXCEPTION;
-type(_) -> ?USER_EXCEPTION.
-
-%%-----------------------------------------------------------------
-%% Function : get_def
-%% Arguments : Exception - record()
-%% Returns : {Type, TypeCode, Exc}
-%% Raises :
-%% Description: Returns the TC for the supplied exception
-%%-----------------------------------------------------------------
-get_def(Exception) ->
- [Exc, TypeId | _] = tuple_to_list(Exception),
- case type(Exc) of
- ?SYSTEM_EXCEPTION ->
- {?SYSTEM_EXCEPTION, get_system_exception_def(Exc), Exception};
- ?USER_EXCEPTION ->
- case orber:light_ifr() of
- true ->
- case catch orber_ifr:get_tc(TypeId, ?IFR_ExceptionDef) of
- {'EXCEPTION', NewExc} ->
- {?SYSTEM_EXCEPTION,
- get_system_exception_def(NewExc),
- NewExc};
- TC ->
- {?USER_EXCEPTION, TC, Exception}
- end;
- false ->
- case mnesia:dirty_index_read(ir_ExceptionDef, TypeId,
- #ir_ExceptionDef.id) of
- [ExcDef] when is_record(ExcDef, ir_ExceptionDef) ->
- {?USER_EXCEPTION,
- ExcDef#ir_ExceptionDef.type,
- Exception};
- Other ->
- orber:dbg("[~p] ~p:get_user_exception_type(~p).~n"
- "IFR Id not found: ~p",
- [?LINE, ?MODULE, TypeId, Other], ?DEBUG_LEVEL),
- NewExc = #'UNKNOWN'{minor=(?CORBA_OMGVMCID bor 1),
- completion_status=?COMPLETED_MAYBE},
- {?SYSTEM_EXCEPTION,
- get_system_exception_def(NewExc),
- NewExc}
- end
- end
- end.
-
-%%-----------------------------------------------------------------
-%% Function : get_name
-%% Arguments : TypeId - string()
-%% Type - ?SYSTEM_EXCEPTION ( | ?USER_EXCEPTION)
-%% Returns : ExceptionName - atom()
-%% Raises : #'UNKNOWN'{}
-%% Description: Extract exception name
-%%-----------------------------------------------------------------
-get_name(TypeId, ?SYSTEM_EXCEPTION) ->
- ExcName =
- case string:tokens(TypeId, ":/") of
- [_IDL, _OMGORG, _CORBA, Name, _Version] when is_list(Name) ->
- list_to_atom(Name);
- [_IDL, _CORBA, Name, _Version] when is_list(Name) ->
- %% We should remove this case but we keep it for now due to backward
- %% compatible reasons.
- list_to_atom(Name);
- Other ->
- %% The CORBA-spec states that this exception should be raised if
- %% it's a system exception we do not support.
- orber:dbg("[~p] ~p:get_system_exception_name(~p).~n"
- "Unknown System Exception: ~p",
- [?LINE, ?MODULE, TypeId, Other], ?DEBUG_LEVEL),
- corba:raise(#'UNKNOWN'{minor=(?CORBA_OMGVMCID bor 2),
- completion_status=?COMPLETED_MAYBE})
- end,
- case type(ExcName) of
- ?SYSTEM_EXCEPTION ->
- ExcName;
- What ->
- orber:dbg("[~p] ~p:get_system_exception_name(~p).~n"
- "Unknown System Exception: ~p",
- [?LINE, ?MODULE, TypeId, What], ?DEBUG_LEVEL),
- corba:raise(#'UNKNOWN'{minor=(?CORBA_OMGVMCID bor 2),
- completion_status=?COMPLETED_MAYBE})
- end.
-
-
-%%-----------------------------------------------------------------
-%% Generate system exception TypeCode
-%%-----------------------------------------------------------------
-get_system_exception_def(ExcName) when is_atom(ExcName) ->
- Name = atom_to_list(ExcName),
- {'tk_except', "IDL:omg.org/CORBA/" ++ Name ++ ":1.0", Name,
- [{"minor",'tk_ulong'},
- {"completed",
- {'tk_enum', "", "completion_status",
- ["COMPLETED_YES", "COMPLETED_NO",
- "COMPLETED_MAYBE"]}}]};
-get_system_exception_def(Exc) ->
- get_system_exception_def(element(1, Exc)).
-
-
-%%-----------------------------------------------------------------
-%% Mapping minor codes to a printable string.
-%%-----------------------------------------------------------------
-dissect({'EXCEPTION', Exc}) ->
- dissect(Exc);
-dissect(Exception) when is_tuple(Exception) ->
- [Exc, TypeId | _] = tuple_to_list(Exception),
- case type(Exc) of
- ?USER_EXCEPTION ->
- {ok, lists:flatten(io_lib:format("~n------------- EXCEPTION INFO --------------
-User Defined Exception.: ~p
-IFR Id.................: ~s
--------------------------------------------~n", [Exc, TypeId]))};
- ?SYSTEM_EXCEPTION ->
- case map_exc(Exception) of
- {ok, String} ->
- {ok, lists:flatten(String)};
- {error, Reason} ->
- {error, Reason}
- end
- end;
-dissect(_What) ->
- {error, "Not a correct exception supplied to orber_exceptions:dissect/1"}.
-
-map_exc({Name, _, Minor, Status}) when is_integer(Minor) ->
- case lookup_vendor(Minor) of
- {true, Vendor, VMCID} ->
- case catch ?MODULE:Name(Minor) of
- MinorInfo when is_list(MinorInfo) ->
- {ok, io_lib:format("~n------------- EXCEPTION INFO --------------
-Vendor.....: ~s
-VMCID......: ~s
-Exception..: ~p
-Status.....: ~p
-Minor Code.: ~p
-Info.......: ~s
--------------------------------------------~n",
- [Vendor, VMCID, Name, Status, (Minor band 16#fff), MinorInfo])};
- _ ->
- {ok, io_lib:format("~n------------- EXCEPTION INFO --------------
-Vendor.....: ~s
-VMCID......: ~s
-Exception..: ~p
-Status.....: ~p
-Minor Code.: ~p
-Info.......: -
-------------------------------------~n", [Vendor, VMCID, Name, Status, (Minor band 16#fff)])}
- end;
- {false, Vendor, VMCID} ->
- {ok, io_lib:format("~n------------- EXCEPTION INFO --------------
-Vendor.....: ~s
-VMCID......: ~s
-Exception..: ~p
-Status.....: ~p
-Minor Code.: ~p
-Info.......: -
--------------------------------------------~n", [Vendor, VMCID, Name, Status, (Minor band 16#fff)])}
- end;
-map_exc(_) ->
- {error, "Not a correct exception supplied to orber_exceptions:map_exc/1"}.
-
-lookup_vendor(Minor) when (?ORBER_VMCID bxor Minor) < 16#0fff ->
- {true, "Orber", "0x45520000"};
-lookup_vendor(Minor) when (?CORBA_OMGVMCID bxor Minor) < 16#0fff ->
- {true, "OMG", "0x4f4d0000"};
-lookup_vendor(Minor) when (?IONA_VMCID_1 bxor Minor) < 16#0fff ->
- {false, "IONA", "0x4f4f0000"};
-lookup_vendor(Minor) when (?IONA_VMCID_2 bxor Minor) < 16#0fff ->
- {false, "IONA", "0x49540000"};
-lookup_vendor(Minor) when (?SUN_VMCID bxor Minor) < 16#0fff ->
- {false, "SUN", "0x53550000"};
-lookup_vendor(Minor) when (?BORLAND_VMCID bxor Minor) < 16#0fff ->
- {false, "Borland", "0x56420000"};
-lookup_vendor(Minor) when (?TAO_VMCID bxor Minor) < 16#0fff ->
- {false, "TAO", "0x54410000"};
-lookup_vendor(Minor) when (?PRISMTECH_VMCID bxor Minor) < 16#0fff ->
- {false, "PrismTech", "0x50540000"};
-lookup_vendor(Minor) when is_integer(Minor), Minor =< ?ULONGMAX ->
- {false, "undefined", extract_VMCID(Minor)};
-lookup_vendor(Minor) when is_integer(Minor), Minor =< ?ULONGMAX ->
- {false, "Unknown", "Unable to extract it"}.
-
-extract_VMCID(Int) ->
- int_to_hex_str(3, ((Int bsr 8) band 16#fffff0), ["00"]).
-
-int_to_hex_str(0, _, Acc) ->
- lists:flatten(["0x" | Acc]);
-int_to_hex_str(N, Int, Acc) ->
- int_to_hex_str(N-1, (Int bsr 8), [int_to_hex((16#ff band Int))|Acc]).
-
-int_to_hex(B) when B < 256, B >= 0 ->
- N1 = B div 16,
- N2 = B rem 16,
- [code_character(N1),
- code_character(N2)].
-code_character(N) when N < 10 ->
- $0 + N;
-code_character(N) ->
- $a + (N - 10).
-
-
-%% The following functions all maps to a system exception.
-%% UNKNOWN - OMG
-'UNKNOWN'(?CORBA_OMGVMCID bor 1) -> "Unlisted user exception received
-by client";
-'UNKNOWN'(?CORBA_OMGVMCID bor 2) -> "Non-standard System Exception
-not supported";
-%% UNKNOWN - Orber
-'UNKNOWN'(?ORBER_VMCID bor 1) -> "Missing beam-file. Unable to extract TC.";
-'UNKNOWN'(_) -> "-".
-
-
-%% BAD_PARAM - OMG
-'BAD_PARAM'(?CORBA_OMGVMCID bor 1) -> "Failure to register, unregister, or
-lookup value factory";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 2) -> "RID already defined in IFR";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 3) -> "Name already used in the context in IFR";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 4) -> "Target is not a valid container";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 5) -> "Name clash in inherited context";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 6) -> "Incorrect type for abstract interface";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 7) -> "string_to_object conversion failed
-due to bad scheme name";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 8) -> "string_to_object conversion failed
-due to bad address";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 9) -> "string_to_object conversion failed
-due to bad bad schema specific part";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 10) -> "string_to_object conversion failed
-due to non specific reason";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 11) -> "Attempt to derive abstract interface
-from non-abstract base interface
-in the Interface Repository";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 12) -> "Attempt to let a ValueDef support
-more than one non-abstract interface
-in the Interface Repository";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 13) -> "Attempt to use an incomplete
-TypeCode as a parameter";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 14) -> "Invalid object id passed to
-POA::create_reference_by_id";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 15) -> "Bad name argument in TypeCode operation";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 16) -> "Bad RepositoryId argument in TypeCode
-operation";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 17) -> "Invalid member name in TypeCode operation";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 18) -> "Duplicate label value in create_union_tc";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 19) -> "Incompatible TypeCode of label and
-discriminator in create_union_tc";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 20) -> "Supplied discriminator type illegitimate
-in create_union_tc";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 21) -> "Any passed to ServerRequest::set_exception
-does not contain an exception";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 22) -> "Unlisted user exception passed to
-ServerRequest::set_exception";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 23) -> "wchar transmission code set not
-in service context";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 24) -> "Service context is not in OMG-defined range";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 25) -> "Enum value out of range";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 26) -> "Invalid service context Id in portable
-interceptor";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 27) -> "Attempt to call register_initial_reference
-with a null Object";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 28) -> "Invalid component Id in
-portable interceptor";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 29) -> "Invalid profile Id in portable
-interceptor";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 30) -> "Two or more Policy objects with the
-same PolicyType value supplied to
-Object::set_policy_overrides or
-PolicyManager::set_policy_overrides";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 31) -> "Attempt to define a oneway
-operation with non-void result,
-out or inout parameters or user
-exceptions";
-'BAD_PARAM'(?CORBA_OMGVMCID bor 32) -> "DII asked to create request
-for an implicit operation";
-%% BAD_PARAM - Orber
-'BAD_PARAM'(?ORBER_VMCID bor 1) -> "Bad return value from the objects
-init-function (create phase) or invalid
-options suuplied";
-'BAD_PARAM'(_) -> "-".
-
-%% NO_MEMORY - OMG
-'NO_MEMORY'(_) -> "-".
-
-%% IMP_LIMIT - OMG
-'IMP_LIMIT'(?CORBA_OMGVMCID bor 1) -> "Unable to use any profile in IOR";
-%% IMP_LIMIT - Orber
-'IMP_LIMIT'(?ORBER_VMCID bor 1) -> "All ports assigned to the configuration
-parameter 'iiop_out_ports' are in use";
-'IMP_LIMIT'(_) -> "-".
-
-%% COMM_FAILURE - OMG
-%% COMM_FAILURE - Orber
-'COMM_FAILURE'(?ORBER_VMCID bor 1) -> "Unable to connect to another ORB -
-probably inactive";
-'COMM_FAILURE'(?ORBER_VMCID bor 2) -> "Unable to connect to another ORB -
-interceptor(s) rejected it or behaves
-badly";
-'COMM_FAILURE'(?ORBER_VMCID bor 3) -> "Request terminated by another process";
-'COMM_FAILURE'(?ORBER_VMCID bor 4) -> "Unable to connect to another ORB - timed out";
-'COMM_FAILURE'(_) -> "-".
-
-%% INV_OBJREF - OMG
-'INV_OBJREF'(?CORBA_OMGVMCID bor 1) -> "wchar Code Set support not specified";
-'INV_OBJREF'(?CORBA_OMGVMCID bor 2) -> "Codeset component required for type using wchar or wstring data";
-'INV_OBJREF'(_) -> "-".
-
-%% NO_PERMISSION - OMG
-'NO_PERMISSION'(_) -> "-".
-
-%% INTERNAL - OMG
-%% INTERNAL - Orber
-'INTERNAL'(?ORBER_VMCID bor 1) -> "Unable to connect to an Orber installation";
-'INTERNAL'(?ORBER_VMCID bor 2) -> "Failed to register internal objectkey in the database";
-'INTERNAL'(_) -> "-".
-
-%% MARSHAL - OMG
-'MARSHAL'(?CORBA_OMGVMCID bor 1) -> "Unable to locate value factory";
-'MARSHAL'(?CORBA_OMGVMCID bor 2) -> "ServerRequest::set_result called
-before ServerRequest::ctx when the
-operation IDL contains a context
-clause";
-'MARSHAL'(?CORBA_OMGVMCID bor 3) -> "NVList passed to
-ServerRequest::arguments does not
-describe all parameters passed
-by client";
-'MARSHAL'(?CORBA_OMGVMCID bor 4) -> "Attempt to marshal Local object";
-'MARSHAL'(?CORBA_OMGVMCID bor 5) -> "wchar or wstring data erroneosly
-sent by client over GIOP 1.0
-connection";
-'MARSHAL'(?CORBA_OMGVMCID bor 6) -> "wchar or wstring data erroneously
-returned by server over GIOP 1.0
-connection";
-%% MARSHAL - Orber
-'MARSHAL'(?ORBER_VMCID bor 1) -> "Integer overflow";
-'MARSHAL'(?ORBER_VMCID bor 2) -> "Passed a non-integer,
-when it must be an integer";
-'MARSHAL'(?ORBER_VMCID bor 3) -> "Incorrect boolean";
-'MARSHAL'(?ORBER_VMCID bor 4) -> "Passed a non-number,
-when it must be a float, double
-or long double";
-'MARSHAL'(?ORBER_VMCID bor 5) -> "Bad enumerant - does not exist";
-'MARSHAL'(?ORBER_VMCID bor 6) -> "Passed something else but character
-or octet";
-'MARSHAL'(?ORBER_VMCID bor 7) -> "Unable to marshal the supplied
-typecode";
-'MARSHAL'(?ORBER_VMCID bor 8) -> "Unable to un-marshal the supplied
-typecode";
-'MARSHAL'(?ORBER_VMCID bor 9) -> "Union IFR-id does not exist";
-'MARSHAL'(?ORBER_VMCID bor 10) -> "Struct IFR-id does not exist";
-'MARSHAL'(?ORBER_VMCID bor 11) -> "Empty string supplied as IFR-id";
-'MARSHAL'(?ORBER_VMCID bor 12) -> "Unable to decode target address";
-'MARSHAL'(?ORBER_VMCID bor 13) -> "Incorrect TypeCode or unsupported
-data type";
-'MARSHAL'(?ORBER_VMCID bor 14) -> "The Fixed type does not match the
-defined digits/scale parameters";
-'MARSHAL'(?ORBER_VMCID bor 15) -> "The supplied array is to long or to short";
-'MARSHAL'(?ORBER_VMCID bor 16) -> "String/Wstring exceeds maximum length";
-'MARSHAL'(?ORBER_VMCID bor 17) -> "To few or to many parameters supplied";
-'MARSHAL'(?ORBER_VMCID bor 18) -> "Unable to decode message header";
-'MARSHAL'(?ORBER_VMCID bor 19) -> "Sequnce exceeds maximum length";
-'MARSHAL'(_) -> "-".
-
-%% INITIALIZE - OMG
-'INITIALIZE'(_) -> "-".
-
-%% NO_IMPLEMENT - OMG
-'NO_IMPLEMENT'(?CORBA_OMGVMCID bor 1) -> "Missing local value implementation";
-'NO_IMPLEMENT'(?CORBA_OMGVMCID bor 2) -> "Incompatible value implementation version";
-'NO_IMPLEMENT'(?CORBA_OMGVMCID bor 3) -> "Unable to use any profile in IOR";
-'NO_IMPLEMENT'(?CORBA_OMGVMCID bor 4) -> "Attempt to use DII on Local object";
-'NO_IMPLEMENT'(_) -> "-".
-
-
-%% BAD_TYPECODE - OMG
-'BAD_TYPECODE'(?CORBA_OMGVMCID bor 1) -> "Attempt to marshal incomplete
-TypeCode";
-'BAD_TYPECODE'(?CORBA_OMGVMCID bor 2) -> "Member type code illegitimate
-in TypeCode operation";
-'BAD_TYPECODE'(_) -> "-".
-
-%% BAD_OPERATION - OMG
-'BAD_OPERATION'(?CORBA_OMGVMCID bor 1) -> "ServantManager returned wrong
-servant type";
-%% BAD_OPERATION - Orber
-'BAD_OPERATION'(?ORBER_VMCID bor 1) -> "Incorrect instance type for this
-operation";
-'BAD_OPERATION'(?ORBER_VMCID bor 2) -> "Incorrect instance type for this
-operation (one-way)";
-'BAD_OPERATION'(?ORBER_VMCID bor 3) -> "The IC option 'handle_info' was
-not used when compiling the stub";
-'BAD_OPERATION'(?ORBER_VMCID bor 4) -> "Incorrect instance type for the
-invoked operation (two- or one-way)";
-'BAD_OPERATION'(_) -> "-".
-
-%% NO_RESOURCES - OMG
-'NO_RESOURCES'(?CORBA_OMGVMCID bor 1) -> "Portable Interceptor operation
-not supported in this binding";
-'NO_RESOURCES'(_) -> "-".
-
-%% NO_RESPONSE - OMG
-'NO_RESPONSE'(_) -> "-".
-
-%% PERSIST_STORE - OMG
-'PERSIST_STORE'(_) -> "-".
-
-%% BAD_INV_ORDER - OMG
-'BAD_INV_ORDER'(?CORBA_OMGVMCID bor 1) -> "Dependency exists in IFR preventing
-destruction of this object";
-'BAD_INV_ORDER'(?CORBA_OMGVMCID bor 2) -> "Attempt to destroy indestructible
-objects in IFR";
-'BAD_INV_ORDER'(?CORBA_OMGVMCID bor 3) -> "Operation would deadlock";
-'BAD_INV_ORDER'(?CORBA_OMGVMCID bor 4) -> "ORB has shutdown";
-'BAD_INV_ORDER'(?CORBA_OMGVMCID bor 5) -> "Attempt to invoke send or invoke
-operation of the same Request object
-more than once";
-'BAD_INV_ORDER'(?CORBA_OMGVMCID bor 6) -> "Attempt to set a servant manager
-after one has already been set";
-'BAD_INV_ORDER'(?CORBA_OMGVMCID bor 7) -> "ServerRequest::arguments called more
-than once or after a call to
-ServerRequest:: set_exception";
-'BAD_INV_ORDER'(?CORBA_OMGVMCID bor 8) -> "ServerRequest::ctx called more than
-once or before ServerRequest::arguments or
-after ServerRequest::ctx, ServerRequest::set_result
-or ServerRequest::set_exception";
-'BAD_INV_ORDER'(?CORBA_OMGVMCID bor 9) -> "ServerRequest::set_result called more
-than once or before ServerRequest::arguments
-or after ServerRequest::set_result or
-ServerRequest::set_exception";
-'BAD_INV_ORDER'(?CORBA_OMGVMCID bor 10) -> "Attempt to send a DII request after
-it was sent previously";
-'BAD_INV_ORDER'(?CORBA_OMGVMCID bor 11) -> "Attempt to poll a DII request or to
-retrieve its result before the request
-was sent";
-'BAD_INV_ORDER'(?CORBA_OMGVMCID bor 12) -> "Attempt to poll a DII request or to
-retrieve its result after the result
-was retrieved previously";
-'BAD_INV_ORDER'(?CORBA_OMGVMCID bor 13) -> "Attempt to poll a synchronous DII
-request or to retrieve results from
-a synchronous DII request";
-'BAD_INV_ORDER'(?CORBA_OMGVMCID bor 14) -> "Invalid portable interceptor call";
-'BAD_INV_ORDER'(?CORBA_OMGVMCID bor 15) -> "Service context add failed in portable
-interceptor because a service context
-with the given id already exists";
-'BAD_INV_ORDER'(?CORBA_OMGVMCID bor 16) -> "Registration of PolicyFactory failed
-because a factory already exists for
-the given PolicyType";
-'BAD_INV_ORDER'(?CORBA_OMGVMCID bor 17) -> "POA cannot create POAs while undergoing
-destruction";
-'BAD_INV_ORDER'(_) -> "-".
-
-%% TRANSIENT - OMG
-'TRANSIENT'(?CORBA_OMGVMCID bor 1) -> "Request discarded because of resource
-exhaustion in POA, or because POA
-is in discarding state";
-'TRANSIENT'(?CORBA_OMGVMCID bor 2) -> "No usable profile in IOR";
-'TRANSIENT'(?CORBA_OMGVMCID bor 3) -> "Request cancelled";
-'TRANSIENT'(?CORBA_OMGVMCID bor 4) -> "POA destroyed";
-%% TRANSIENT - Orber
-'TRANSIENT'(?ORBER_VMCID bor 1) -> "Orber is being restarted, or should be,
-on one node in the multi-node Orber
-installation";
-'TRANSIENT'(?ORBER_VMCID bor 2) -> "The node the target object resides on
-is down (multi-node Orber installation)";
-'TRANSIENT'(?ORBER_VMCID bor 3) -> "Received EXIT when invoking an operation
-on an object residing on another
-node in a multi-node Orber installation";
-'TRANSIENT'(?ORBER_VMCID bor 4) -> "Received EXIT when invoking an operation
-on a local object";
-'TRANSIENT'(?ORBER_VMCID bor 5) -> "Received unknown reply when invoking an
-operation on an object residing on
-another node in a multi-node Orber
-installation";
-'TRANSIENT'(?ORBER_VMCID bor 6) -> "Received unknown reply when invoking an
-operation on a local object";
-'TRANSIENT'(?ORBER_VMCID bor 7) -> "Either the stub/skeleton does not exist or an
-incorrect IC-version was used, which does not generate
-the oe_tc/1 or oe_get_interface/1 functions";
-'TRANSIENT'(_) -> "-".
-
-%% FREE_MEM - OMG
-'FREE_MEM'(_) -> "-".
-
-%% INV_IDENT - OMG
-'INV_IDENT'(_) -> "-".
-
-%% INV_FLAG - OMG
-'INV_FLAG'(_) -> "-".
-
-%% INTF_REPOS - OMG
-'INTF_REPOS'(?CORBA_OMGVMCID bor 1) -> "Interface Repository not available";
-'INTF_REPOS'(?CORBA_OMGVMCID bor 2) -> "No entry for requested interface in
-Interface Repository";
-'INTF_REPOS'(_) -> "-".
-
-%% BAD_CONTEXT - OMG
-'BAD_CONTEXT'(_) -> "-".
-
-%% OBJ_ADAPTER - OMG
-'OBJ_ADAPTER'(?CORBA_OMGVMCID bor 1) -> "System exception in
-AdapterActivator::unknown_adapter";
-'OBJ_ADAPTER'(?CORBA_OMGVMCID bor 2) -> "Servant not found [ServantManager]";
-'OBJ_ADAPTER'(?CORBA_OMGVMCID bor 3) -> "No default servant available [POA policy]";
-'OBJ_ADAPTER'(?CORBA_OMGVMCID bor 4) -> "No servant manager available [POA Policy]";
-'OBJ_ADAPTER'(?CORBA_OMGVMCID bor 5) -> "Violation of POA policy by
-ServantActivator::incarnate";
-'OBJ_ADAPTER'(?CORBA_OMGVMCID bor 6) -> "Exception in
-PortableInterceptor::IORInterceptor.components_established";
-%% OBJ_ADAPTER - Orber
-'OBJ_ADAPTER'(?ORBER_VMCID bor 1) -> "Call-back module does not exist";
-'OBJ_ADAPTER'(?ORBER_VMCID bor 2) -> "Missing function or incorrect arity in
-call-back module";
-'OBJ_ADAPTER'(?ORBER_VMCID bor 3) -> "Function exported but arity incorrect";
-'OBJ_ADAPTER'(?ORBER_VMCID bor 4) -> "Unknown error. Call-back module generated
-EXIT";
-'OBJ_ADAPTER'(?ORBER_VMCID bor 5) -> "Call-back module invoked operation on a
-non-existing module";
-'OBJ_ADAPTER'(?ORBER_VMCID bor 6) -> "Missing function or incorrect arity in
-a module invoked via the call-back module";
-'OBJ_ADAPTER'(?ORBER_VMCID bor 7) -> "Function exported but arity incorrect in
-a module invoked via the call-back module";
-'OBJ_ADAPTER'(?ORBER_VMCID bor 8) -> "Call-back module contains a function_clause,
-case_clause or badarith error";
-'OBJ_ADAPTER'(?ORBER_VMCID bor 9) -> "Call-back module invoked operation exported
-by another module which contains a function_clause, case_clause or badarith error";
-'OBJ_ADAPTER'(?ORBER_VMCID bor 10) -> "Unknown EXIT returned by call-back module";
-'OBJ_ADAPTER'(_) -> "-".
-
-%% DATA_CONVERSION - OMG
-'DATA_CONVERSION'(?CORBA_OMGVMCID bor 1) -> "Character does not map to negotiated
-transmission code set";
-'DATA_CONVERSION'(_) -> "-".
-
-%% OBJECT_NOT_EXIST - OMG
-'OBJECT_NOT_EXIST'(?CORBA_OMGVMCID bor 1) -> "Attempt to pass an unactivated
-(unregistered) value as an object reference";
-'OBJECT_NOT_EXIST'(?CORBA_OMGVMCID bor 2) -> "Failed to create or locate Object
-Adapter";
-'OBJECT_NOT_EXIST'(?CORBA_OMGVMCID bor 3) -> "Biomolecular Sequence Analysis
-Service is no longer available";
-'OBJECT_NOT_EXIST'(?CORBA_OMGVMCID bor 4) -> "Object Adapter inactive";
-'OBJECT_NOT_EXIST'(_) -> "-".
-
-%% TRANSACTION_REQUIRED - OMG
-'TRANSACTION_REQUIRED'(_) -> "-".
-
-%% TRANSACTION_ROLLEDBACK - OMG
-'TRANSACTION_ROLLEDBACK'(_) -> "-".
-
-%% INVALID_TRANSACTION - OMG
-'INVALID_TRANSACTION'(_) -> "-".
-
-%% INV_POLICY - OMG
-'INV_POLICY'(?CORBA_OMGVMCID bor 1) -> "Unable to reconcile IOR specified
-policy with effective policy override";
-'INV_POLICY'(?CORBA_OMGVMCID bor 2) -> "Invalid PolicyType";
-'INV_POLICY'(?CORBA_OMGVMCID bor 3) -> "No PolicyFactory has been registered
-for the given PolicyType";
-'INV_POLICY'(_) -> "-".
-
-%% CODESET_INCOMPATIBLE - OMG
-'CODESET_INCOMPATIBLE'(_) -> "-".
-
-%% REBIND - OMG
-'REBIND'(_) -> "-".
-
-%% TIMEOUT - OMG
-'TIMEOUT'(_) -> "-".
-
-%% TRANSACTION_UNAVAILABLE - OMG
-'TRANSACTION_UNAVAILABLE'(_) -> "-".
-
-%% TRANSACTION_MODE - OMG
-'TRANSACTION_MODE'(_) -> "-".
-
-%% BAD_QOS - OMG
-'BAD_QOS'(_) -> "-".
-
diff --git a/lib/orber/src/orber_ifr.erl b/lib/orber/src/orber_ifr.erl
deleted file mode 100644
index 70e0cb3fca..0000000000
--- a/lib/orber/src/orber_ifr.erl
+++ /dev/null
@@ -1,1820 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : corba_ir_impl.erl
-%% Purpose : Interface Repository for CORBA
-%%----------------------------------------------------------------------
-
-%%% NOTES:
-%%%
-%%% For details about known deficiencies in this CORBA IFR
-%%% implementation, see the file ../doc/src/notes.txt.
-%%%
-
--module(orber_ifr).
-
--export([
-%%% Public interfaces:
- init/2,
- find_repository/0,
- 'IRObject__get_def_kind'/1,
- %%'IRObject_destroy'/1,
- 'Contained__get_def_kind'/1,
- %%'Contained_destroy'/1,
- 'Contained__get_id'/1,
- 'Contained__set_id'/2,
- 'Contained__get_name'/1,
- 'Contained__set_name'/2,
- 'Contained__get_version'/1,
- 'Contained__set_version'/2,
- 'Contained__get_defined_in'/1,
- 'Contained__get_absolute_name'/1,
- 'Contained__get_containing_repository'/1,
- 'Contained_describe'/1,
- 'Contained_move'/4,
- 'Container__get_def_kind'/1,
- 'Container_destroy'/1,
- 'Container_lookup'/2,
- 'Container_contents'/3,
- 'Container_lookup_name'/5,
- 'Container_describe_contents'/4,
- 'Container_create_module'/4,
- 'Container_create_constant'/6,
- 'Container_create_struct'/5,
- 'Container_create_union'/6,
- 'Container_create_enum'/5,
- 'Container_create_alias'/5,
- 'Container_create_interface'/5,
- 'Container_create_exception'/5,
- 'IDLType__get_def_kind'/1,
- 'IDLType_destroy'/1,
- 'IDLType__get_type'/1,
- 'Repository__get_def_kind'/1,
- 'Repository_destroy'/1,
- 'Repository_lookup'/2,
- 'Repository_contents'/3,
- 'Repository_lookup_name'/5,
- 'Repository_describe_contents'/4,
- 'Repository_create_module'/4,
- 'Repository_create_constant'/6,
- 'Repository_create_struct'/5,
- 'Repository_create_union'/6,
- 'Repository_create_enum'/5,
- 'Repository_create_alias'/5,
- 'Repository_create_interface'/5,
- 'Repository_create_exception'/5,
- 'Repository_lookup_id'/2,
- 'Repository_get_primitive'/2,
- 'Repository_create_string'/2,
- 'Repository_create_wstring'/2,
- 'Repository_create_sequence'/3,
- 'Repository_create_array'/3,
- 'Repository_create_idltype'/2, %not in CORBA 2.0
- 'ModuleDef__get_def_kind'/1,
- 'ModuleDef_destroy'/1,
- 'ModuleDef_lookup'/2,
- 'ModuleDef_contents'/3,
- 'ModuleDef_lookup_name'/5,
- 'ModuleDef_describe_contents'/4,
- 'ModuleDef_create_module'/4,
- 'ModuleDef_create_constant'/6,
- 'ModuleDef_create_struct'/5,
- 'ModuleDef_create_union'/6,
- 'ModuleDef_create_enum'/5,
- 'ModuleDef_create_alias'/5,
- 'ModuleDef_create_interface'/5,
- 'ModuleDef_create_exception'/5,
- 'ModuleDef__get_id'/1,
- 'ModuleDef__set_id'/2,
- 'ModuleDef__get_name'/1,
- 'ModuleDef__set_name'/2,
- 'ModuleDef__get_version'/1,
- 'ModuleDef__set_version'/2,
- 'ModuleDef__get_defined_in'/1,
- 'ModuleDef__get_absolute_name'/1,
- 'ModuleDef__get_containing_repository'/1,
- 'ModuleDef_describe'/1,
- 'ModuleDef_move'/4,
- 'ConstantDef__get_def_kind'/1,
- 'ConstantDef_destroy'/1,
- 'ConstantDef__get_id'/1,
- 'ConstantDef__set_id'/2,
- 'ConstantDef__get_name'/1,
- 'ConstantDef__set_name'/2,
- 'ConstantDef__get_version'/1,
- 'ConstantDef__set_version'/2,
- 'ConstantDef__get_defined_in'/1,
- 'ConstantDef__get_absolute_name'/1,
- 'ConstantDef__get_containing_repository'/1,
- 'ConstantDef_describe'/1,
- 'ConstantDef_move'/4,
- 'ConstantDef__get_type'/1,
- 'ConstantDef__get_type_def'/1,
- 'ConstantDef__set_type_def'/2,
- 'ConstantDef__get_value'/1,
- 'ConstantDef__set_value'/2,
- 'TypedefDef__get_def_kind'/1,
- 'TypedefDef_destroy'/1,
- 'TypedefDef__get_id'/1,
- 'TypedefDef__set_id'/2,
- 'TypedefDef__get_name'/1,
- 'TypedefDef__set_name'/2,
- 'TypedefDef__get_version'/1,
- 'TypedefDef__set_version'/2,
- 'TypedefDef__get_defined_in'/1,
- 'TypedefDef__get_absolute_name'/1,
- 'TypedefDef__get_containing_repository'/1,
- 'TypedefDef_describe'/1,
- 'TypedefDef_move'/4,
- 'TypedefDef__get_type'/1,
- 'StructDef__get_def_kind'/1,
- 'StructDef_destroy'/1,
- 'StructDef__get_id'/1,
- 'StructDef__set_id'/2,
- 'StructDef__get_name'/1,
- 'StructDef__set_name'/2,
- 'StructDef__get_version'/1,
- 'StructDef__set_version'/2,
- 'StructDef__get_defined_in'/1,
- 'StructDef__get_absolute_name'/1,
- 'StructDef__get_containing_repository'/1,
- 'StructDef_describe'/1,
- 'StructDef_move'/4,
- 'StructDef__get_type'/1,
- 'StructDef__get_members'/1,
- 'StructDef__set_members'/2,
- 'UnionDef__get_def_kind'/1,
- 'UnionDef_destroy'/1,
- 'UnionDef__get_id'/1,
- 'UnionDef__set_id'/2,
- 'UnionDef__get_name'/1,
- 'UnionDef__set_name'/2,
- 'UnionDef__get_version'/1,
- 'UnionDef__set_version'/2,
- 'UnionDef__get_defined_in'/1,
- 'UnionDef__get_absolute_name'/1,
- 'UnionDef__get_containing_repository'/1,
- 'UnionDef_describe'/1,
- 'UnionDef_move'/4,
- 'UnionDef__get_type'/1,
- 'UnionDef__get_discriminator_type'/1,
- 'UnionDef__get_discriminator_type_def'/1,
- 'UnionDef__set_discriminator_type_def'/2,
- 'UnionDef__get_members'/1,
- 'UnionDef__set_members'/2,
- 'EnumDef__get_def_kind'/1,
- 'EnumDef_destroy'/1,
- 'EnumDef__get_id'/1,
- 'EnumDef__set_id'/2,
- 'EnumDef__get_name'/1,
- 'EnumDef__set_name'/2,
- 'EnumDef__get_version'/1,
- 'EnumDef__set_version'/2,
- 'EnumDef__get_defined_in'/1,
- 'EnumDef__get_absolute_name'/1,
- 'EnumDef__get_containing_repository'/1,
- 'EnumDef_describe'/1,
- 'EnumDef_move'/4,
- 'EnumDef__get_type'/1,
- 'EnumDef__get_members'/1,
- 'EnumDef__set_members'/2,
- 'AliasDef__get_def_kind'/1,
- 'AliasDef_destroy'/1,
- 'AliasDef__get_id'/1,
- 'AliasDef__set_id'/2,
- 'AliasDef__get_name'/1,
- 'AliasDef__set_name'/2,
- 'AliasDef__get_version'/1,
- 'AliasDef__set_version'/2,
- 'AliasDef__get_defined_in'/1,
- 'AliasDef__get_absolute_name'/1,
- 'AliasDef__get_containing_repository'/1,
- 'AliasDef_describe'/1,
- 'AliasDef_move'/4,
- 'AliasDef__get_type'/1,
- 'AliasDef__get_original_type_def'/1,
- 'AliasDef__set_original_type_def'/2,
- 'PrimitiveDef__get_def_kind'/1,
- 'PrimitiveDef_destroy'/1,
- 'PrimitiveDef__get_type'/1,
- 'PrimitiveDef__get_kind'/1,
- 'StringDef__get_def_kind'/1,
- 'StringDef_destroy'/1,
- 'StringDef__get_type'/1,
- 'StringDef__get_bound'/1,
- 'StringDef__set_bound'/2,
- 'WstringDef__get_def_kind'/1,
- 'WstringDef_destroy'/1,
- 'WstringDef__get_type'/1,
- 'WstringDef__get_bound'/1,
- 'WstringDef__set_bound'/2,
- 'FixedDef__get_def_kind'/1,
- 'FixedDef_destroy'/1,
- 'FixedDef__get_type'/1,
- 'FixedDef__get_digits'/1,
- 'FixedDef__set_digits'/2,
- 'FixedDef__get_scale'/1,
- 'FixedDef__set_scale'/2,
- 'SequenceDef__get_def_kind'/1,
- 'SequenceDef_destroy'/1,
- 'SequenceDef__get_type'/1,
- 'SequenceDef__get_bound'/1,
- 'SequenceDef__set_bound'/2,
- 'SequenceDef__get_element_type'/1,
- 'SequenceDef__get_element_type_def'/1,
- 'SequenceDef__set_element_type_def'/2,
- 'ArrayDef__get_def_kind'/1,
- 'ArrayDef_destroy'/1,
- 'ArrayDef__get_type'/1,
- 'ArrayDef__get_length'/1,
- 'ArrayDef__set_length'/2,
- 'ArrayDef__get_element_type'/1,
- 'ArrayDef__get_element_type_def'/1,
- 'ArrayDef__set_element_type_def'/2,
- 'ExceptionDef__get_def_kind'/1,
- 'ExceptionDef_destroy'/1,
- 'ExceptionDef__get_id'/1,
- 'ExceptionDef__set_id'/2,
- 'ExceptionDef__get_name'/1,
- 'ExceptionDef__set_name'/2,
- 'ExceptionDef__get_version'/1,
- 'ExceptionDef__set_version'/2,
- 'ExceptionDef__get_defined_in'/1,
- 'ExceptionDef__get_absolute_name'/1,
- 'ExceptionDef__get_containing_repository'/1,
- 'ExceptionDef_describe'/1,
- 'ExceptionDef_move'/4,
- 'ExceptionDef__get_type'/1,
- 'ExceptionDef__get_members'/1,
- 'ExceptionDef__set_members'/2,
- 'AttributeDef__get_def_kind'/1,
- 'AttributeDef_destroy'/1,
- 'AttributeDef__get_id'/1,
- 'AttributeDef__set_id'/2,
- 'AttributeDef__get_name'/1,
- 'AttributeDef__set_name'/2,
- 'AttributeDef__get_version'/1,
- 'AttributeDef__set_version'/2,
- 'AttributeDef__get_defined_in'/1,
- 'AttributeDef__get_absolute_name'/1,
- 'AttributeDef__get_containing_repository'/1,
- 'AttributeDef_describe'/1,
- 'AttributeDef_move'/4,
- 'AttributeDef__get_type'/1,
- 'AttributeDef__get_type_def'/1,
- 'AttributeDef__set_type_def'/2,
- 'AttributeDef__get_mode'/1,
- 'AttributeDef__set_mode'/2,
- 'OperationDef__get_def_kind'/1,
- 'OperationDef_destroy'/1,
- 'OperationDef__get_id'/1,
- 'OperationDef__set_id'/2,
- 'OperationDef__get_name'/1,
- 'OperationDef__set_name'/2,
- 'OperationDef__get_version'/1,
- 'OperationDef__set_version'/2,
- 'OperationDef__get_defined_in'/1,
- 'OperationDef__get_absolute_name'/1,
- 'OperationDef__get_containing_repository'/1,
- 'OperationDef_describe'/1,
- 'OperationDef_move'/4,
- 'OperationDef__get_result'/1,
- 'OperationDef__get_result_def'/1,
- 'OperationDef__set_result_def'/2,
- 'OperationDef__get_params'/1,
- 'OperationDef__set_params'/2,
- 'OperationDef__get_mode'/1,
- 'OperationDef__set_mode'/2,
- 'OperationDef__get_contexts'/1,
- 'OperationDef__set_contexts'/2,
- 'OperationDef__get_exceptions'/1,
- 'OperationDef__set_exceptions'/2,
- 'InterfaceDef__get_def_kind'/1,
- 'InterfaceDef_destroy'/1,
- 'InterfaceDef_lookup'/2,
- 'InterfaceDef_contents'/3,
- 'InterfaceDef_lookup_name'/5,
- 'InterfaceDef_describe_contents'/4,
- 'InterfaceDef_create_module'/4,
- 'InterfaceDef_create_constant'/6,
- 'InterfaceDef_create_struct'/5,
- 'InterfaceDef_create_union'/6,
- 'InterfaceDef_create_enum'/5,
- 'InterfaceDef_create_alias'/5,
- 'InterfaceDef_create_interface'/5,
- 'InterfaceDef_create_exception'/5,
- 'InterfaceDef__get_id'/1,
- 'InterfaceDef__set_id'/2,
- 'InterfaceDef__get_name'/1,
- 'InterfaceDef__set_name'/2,
- 'InterfaceDef__get_version'/1,
- 'InterfaceDef__set_version'/2,
- 'InterfaceDef__get_defined_in'/1,
- 'InterfaceDef__get_absolute_name'/1,
- 'InterfaceDef__get_containing_repository'/1,
- 'InterfaceDef_describe'/1,
- 'InterfaceDef_move'/4,
- 'InterfaceDef__get_type'/1,
- 'InterfaceDef__get_base_interfaces'/1,
- 'InterfaceDef__set_base_interfaces'/2,
- 'InterfaceDef_is_a'/2,
- 'InterfaceDef_describe_interface'/1,
- 'InterfaceDef_create_attribute'/6,
- 'InterfaceDef_create_operation'/9,
- %%'TypeCode_equal'/2,
- %%'TypeCode_kind'/1,
- %%'TypeCode_id'/1,
- %%'TypeCode_name'/1,
- %%'TypeCode_member_count'/1,
- %%'TypeCode_member_name'/2,
- %%'TypeCode_member_type'/2,
- %%'TypeCode_member_label'/2,
- %%'TypeCode_discriminator_type'/1,
- %%'TypeCode_default_index'/1,
- %%'TypeCode_length'/1,
- %%'TypeCode_content_type'/1,
- %%'TypeCode_param_count'/1,
- %%'TypeCode_parameter'/2,
- 'ORB_create_struct_tc'/3,
- 'ORB_create_union_tc'/4,
- 'ORB_create_enum_tc'/3,
- 'ORB_create_alias_tc'/3,
- 'ORB_create_exception_tc'/3,
- 'ORB_create_interface_tc'/2,
- 'ORB_create_string_tc'/1,
- 'ORB_create_wstring_tc'/1,
- 'ORB_create_sequence_tc'/2,
- 'ORB_create_recursive_sequence_tc'/2,
- 'ORB_create_array_tc'/2,
-%%% "Methods" of the IFR "objects"
- get_def_kind/1,
- destroy/1,
- get_id/1,
- set_id/2,
- get_name/1,
- set_name/2,
- get_version/1,
- set_version/2,
- get_defined_in/1,
- get_absolute_name/1,
- get_containing_repository/1,
- describe/1,
- move/4,
- lookup/2,
- contents/3,
- lookup_name/5,
- describe_contents/4,
- create_module/4,
- create_constant/6,
- create_struct/5,
- create_union/6,
- create_enum/5,
- create_alias/5,
- create_interface/5,
- create_exception/5,
- get_type/1,
- lookup_id/2,
- get_primitive/2,
- create_string/2,
- create_wstring/2,
- create_sequence/3,
- create_array/3,
- create_idltype/2, %not in CORBA 2.0
- create_fixed/3,
- get_type_def/1,
- set_type_def/2,
- get_value/1,
- set_value/2,
- get_members/1,
- set_members/2,
- get_discriminator_type/1,
- get_discriminator_type_def/1,
- set_discriminator_type_def/2,
- get_original_type_def/1,
- set_original_type_def/2,
- get_kind/1,
- get_bound/1,
- set_bound/2,
- get_element_type/1,
- get_element_type_def/1,
- set_element_type_def/2,
- get_length/1,
- set_length/2,
- get_mode/1,
- set_mode/2,
- get_result/1,
- get_result_def/1,
- set_result_def/2,
- get_params/1,
- set_params/2,
- get_contexts/1,
- set_contexts/2,
- get_exceptions/1,
- set_exceptions/2,
- get_base_interfaces/1,
- set_base_interfaces/2,
- is_a/2,
- describe_interface/1,
- create_attribute/6,
- create_operation/9
- ]).
-
-%% Light IFR operations
--export([initialize/3,
- get_module/2,
- get_tc/2,
- add_module/3, add_module/4,
- add_constant/3, add_constant/4,
- add_struct/3, add_struct/4,
- add_union/3, add_union/4,
- add_enum/3, add_enum/4,
- add_alias/3, add_alias/4,
- add_interface/3, add_interface/4,
- add_exception/3, add_exception/4,
- remove/2,
- add_items/3]).
-
-
--include_lib("orber/include/corba.hrl").
--include("orber_ifr.hrl").
--include("ifr_objects.hrl").
-
-%%======================================================================
-%% Public interfaces to the IFR
-%%======================================================================
-%%=================== Light IFR operations =============================
-%%----------------------------------------------------------------------
-%% Function : get_module
-%% Arguments : Id - string()
-%% Type - ?IFR_ModuleDef | ?IFR_ConstantDef | ?IFR_StructDef |
-%% ?IFR_UnionDef | ?IFR_EnumDef | ?IFR_AliasDef |
-%% ?IFR_InterfaceDef | ?IFR_ExceptionDef
-%% Returns : Module - atom() | {'EXCEPTION', E}
-%% Raises : #'MARSHAL'{}
-%% Description:
-%%----------------------------------------------------------------------
-get_module(Id, Type) ->
- case mnesia:dirty_read(orber_light_ifr, Id) of
- [#orber_light_ifr{module = Module, type = Type}] ->
- Module;
- What ->
- orber:dbg("[~p] ~p:get_module(~p, ~p).~n"
- "Id doesn't exist, mismatch Id vs Type or DB error: ~p",
- [?LINE, ?MODULE, Id, Type, What], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE})
- end.
-
-
-%%----------------------------------------------------------------------
-%% Function : get_tc
-%% Arguments : Id - string()
-%% Type - ?IFR_ModuleDef | ?IFR_ConstantDef | ?IFR_StructDef |
-%% ?IFR_UnionDef | ?IFR_EnumDef | ?IFR_AliasDef |
-%% ?IFR_InterfaceDef | ?IFR_ExceptionDef
-%% Returns : Module - atom() | {'EXCEPTION', E}
-%% Raises : #'MARSHAL'{}
-%% Description: This function may *only* return correct TypeCode or raise
-%% a system exception!!
-%%----------------------------------------------------------------------
-get_tc(Id, Type) ->
- case catch mnesia:dirty_read(orber_light_ifr, Id) of
- [#orber_light_ifr{module = Module, type = Type}] ->
- case catch Module:tc() of
- {'EXIT', Reason} ->
- case Reason of
- {undef,[{Module, tc,[],_}|_]} ->
- orber:dbg("[~p] ~p:get_tc(~p);~nMissing ~p:tc()~n",
- [?LINE, ?MODULE, Id, Module], ?DEBUG_LEVEL),
- corba:raise(#'UNKNOWN'{minor=(?ORBER_VMCID bor 1),
- completion_status=?COMPLETED_MAYBE});
- _ ->
- orber:dbg("[~p] ~p:get_tc(~p, ~p);~nEXIT reason: ~p~n",
- [?LINE, ?MODULE, Id, Module, Reason],
- ?DEBUG_LEVEL),
- corba:raise(#'UNKNOWN'{minor=(?CORBA_OMGVMCID bor 1),
- completion_status=?COMPLETED_MAYBE})
- end;
- TC ->
- TC
- end;
- What when Type == ?IFR_ExceptionDef ->
- orber:dbg("[~p] ~p:get_tc(~p, ExceptionDef);~nUnknown: ~p~n",
- [?LINE, ?MODULE, Id, What], ?DEBUG_LEVEL),
- corba:raise(#'UNKNOWN'{completion_status=?COMPLETED_MAYBE});
- What ->
- orber:dbg("[~p] ~p:get_tc(~p, ~p);~nUnknown: ~p~n",
- [?LINE, ?MODULE, Id, Type, What], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : initialize
-%% Arguments : Timeout - integer() | infinity
-%% Options - [{Key, Value}]
-%% LightIFR - true | false
-%% Returns : ok | {'EXCEPTION', E}
-%% Raises : #'INTF_REPOS'{}
-%% Description:
-%%----------------------------------------------------------------------
-initialize(Timeout, Options, LightIFR) ->
- orber_ifr_utils:init_DB(Timeout, Options, LightIFR).
-
-%%----------------------------------------------------------------------
-%% Function : add_X
-%% Arguments : Id - string()
-%% Module - atom()
-%% BaseId - string()
-%% Returns :
-%% Raises :
-%% Description:
-%%----------------------------------------------------------------------
-add_module(Id, Module, BaseId) ->
- add_it(Id, Module, BaseId, ?IFR_ModuleDef, false).
-add_module(Id, Module, BaseId, Transaction) ->
- add_it(Id, Module, BaseId, ?IFR_ModuleDef, Transaction).
-
-add_constant(Id, Module, BaseId) ->
- add_it(Id, Module, BaseId, ?IFR_ConstantDef, false).
-add_constant(Id, Module, BaseId, Transaction) ->
- add_it(Id, Module, BaseId, ?IFR_ConstantDef, Transaction).
-
-add_struct(Id, Module, BaseId) ->
- add_it(Id, Module, BaseId, ?IFR_StructDef, false).
-add_struct(Id, Module, BaseId, Transaction) ->
- add_it(Id, Module, BaseId, ?IFR_StructDef, Transaction).
-
-add_union(Id, Module, BaseId) ->
- add_it(Id, Module, BaseId, ?IFR_UnionDef, false).
-add_union(Id, Module, BaseId, Transaction) ->
- add_it(Id, Module, BaseId, ?IFR_UnionDef, Transaction).
-
-add_enum(Id, Module, BaseId) ->
- add_it(Id, Module, BaseId, ?IFR_EnumDef, false).
-add_enum(Id, Module, BaseId, Transaction) ->
- add_it(Id, Module, BaseId, ?IFR_EnumDef, Transaction).
-
-add_alias(Id, Module, BaseId) ->
- add_it(Id, Module, BaseId, ?IFR_AliasDef, false).
-add_alias(Id, Module, BaseId, Transaction) ->
- add_it(Id, Module, BaseId, ?IFR_AliasDef, Transaction).
-
-add_interface(Id, Module, BaseId) ->
- add_it(Id, Module, BaseId, ?IFR_InterfaceDef, false).
-add_interface(Id, Module, BaseId, Transaction) ->
- add_it(Id, Module, BaseId, ?IFR_InterfaceDef, Transaction).
-
-add_exception(Id, Module, BaseId) ->
- add_it(Id, Module, BaseId, ?IFR_ExceptionDef, false).
-add_exception(Id, Module, BaseId, Transaction) ->
- add_it(Id, Module, BaseId, ?IFR_ExceptionDef, Transaction).
-
-
-%%----------------------------------------------------------------------
-%% Function : add_it
-%% Arguments : Id - string()
-%% Module - atom()
-%% BaseId - string()
-%% Type - ?IFR_ModuleDef | ?IFR_ConstantDef | ?IFR_StructDef |
-%% ?IFR_UnionDef | ?IFR_EnumDef | ?IFR_AliasDef |
-%% ?IFR_InterfaceDef | ?IFR_ExceptionDef
-%% Transaction - true | false
-%% Returns :
-%% Raises :
-%% Description:
-%%----------------------------------------------------------------------
-add_it(Id, Module, BaseId, Type, true) ->
- F = fun() ->
- D = #orber_light_ifr{id = Id, module = Module,
- type = Type, base_id = BaseId},
- mnesia:write(D)
- end,
- case mnesia:transaction(F) of
- {aborted, Reason} ->
- orber:dbg("[~p] orber_ifr:add_it(~p). aborted:~n~p~n",
- [?LINE, Id, Reason], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO});
- {atomic, _} ->
- ok
- end;
-add_it(Id, Module, BaseId, Type, false) ->
- D = #orber_light_ifr{id = Id, module = Module,
- type = Type, base_id = BaseId},
- mnesia:write(D).
-
-%%----------------------------------------------------------------------
-%% Function : remove
-%% Arguments : BaseId - atom()
-%% Options - [KeyValue]
-%% KeyValue - {storage, mnesia | ets}
-%% Returns :
-%% Raises :
-%% Description:
-%%----------------------------------------------------------------------
-remove(ContainerId, _Options) ->
- F = fun() ->
- MatchHead = #orber_light_ifr{id = '$1', base_id = ContainerId, _='_'},
- Result = '$1',
- IdList = mnesia:select(orber_light_ifr,
- [{MatchHead, [], [Result]}],
- write),
- lists:foreach(fun(RefId) ->
- mnesia:delete({orber_light_ifr, RefId})
- end, IdList)
- end,
- case mnesia:transaction(F) of
- {aborted, Reason} ->
- orber:dbg("[~p] orber_ifr:remove(~p). aborted:~n~p~n",
- [?LINE, ContainerId, Reason], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO});
- {atomic, _} ->
- ok
- end.
-
-%%----------------------------------------------------------------------
-%% Function : add_items
-%% Arguments : ContainerId - atom()
-%% Options - [KeyValue]
-%% KeyValue - {storage, mnesia | ets}
-%% Items - [{Id, Module, Type}]
-%% Id - string()
-%% Module - atom()
-%% Type - struct | except | union | interface
-%% Returns :
-%% Raises :
-%% Description:
-%%----------------------------------------------------------------------
-add_items(ContainerId, _Options, Items) ->
- F = fun() ->
- mnesia:write_lock_table(orber_light_ifr),
- add_items_helper(Items, ContainerId)
- end,
- case mnesia:transaction(F) of
- {aborted, Reason} ->
- orber:dbg("[~p] orber_ifr:add_items(~p). aborted:~n~p~n",
- [?LINE, ContainerId, Reason], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO});
- {atomic, _} ->
- ok
- end.
-
-add_items_helper([{Id, Module, struct}|T], ContainerId) ->
- add_it(Id, Module, ContainerId, ?IFR_StructDef, false),
- add_items_helper(T, ContainerId);
-add_items_helper([{Id, Module, interface}|T], ContainerId) ->
- add_it(Id, Module, ContainerId, ?IFR_InterfaceDef, false),
- add_items_helper(T, ContainerId);
-add_items_helper([{Id, Module, except}|T], ContainerId) ->
- add_it(Id, Module, ContainerId, ?IFR_ExceptionDef, false),
- add_items_helper(T, ContainerId);
-add_items_helper([{Id, Module, union}|T], ContainerId) ->
- add_it(Id, Module, ContainerId, ?IFR_UnionDef, false),
- add_items_helper(T, ContainerId);
-add_items_helper([ok], _) ->
- ok.
-
-
-%%=================== End Light IFR operations =========================
-
-%% Initialize the database
-init(Nodes, Timeout) when is_atom(Timeout) orelse is_integer(Timeout) ->
- orber_ifr_utils:init_DB(Timeout, [{disc_copies, Nodes}]);
-init(Timeout, Nodes) ->
- orber_ifr_utils:init_DB(Timeout, [{disc_copies, Nodes}]).
-
-
-%%% Find the repository
-find_repository() ->
- orber_ifr_utils:create_repository().
-
-'IRObject__get_def_kind'(Objref) ->
- orber_ifr_irobject:'_get_def_kind'(Objref).
-%%'IRObject_destroy'(Objref) ->
-%% orber_ifr_irobject:destroy(Objref).
-
-'Contained__get_def_kind'(Objref) ->
- orber_ifr_contained:'_get_def_kind'(Objref).
-%%'Contained_destroy'(Objref) ->
-%% orber_ifr_contained:destroy(Objref).
-'Contained__get_id'(Objref) ->
- orber_ifr_contained:'_get_id'(Objref).
-'Contained__set_id'(Objref,Id) ->
- orber_ifr_contained:'_set_id'(Objref,Id).
-'Contained__get_name'(Objref) ->
- orber_ifr_contained:'_get_name'(Objref).
-'Contained__set_name'(Objref,Name) ->
- orber_ifr_contained:'_set_name'(Objref,Name).
-'Contained__get_version'(Objref) ->
- orber_ifr_contained:'_get_version'(Objref).
-'Contained__set_version'(Objref,Version) ->
- orber_ifr_contained:'_set_version'(Objref,Version).
-'Contained__get_defined_in'(Objref) ->
- orber_ifr_contained:'_get_defined_in'(Objref).
-'Contained__get_absolute_name'(Objref) ->
- orber_ifr_contained:'_get_absolute_name'(Objref).
-'Contained__get_containing_repository'(Objref) ->
- orber_ifr_contained:'_get_containing_repository'(Objref).
-'Contained_describe'(Objref) ->
- orber_ifr_contained:describe(Objref).
-'Contained_move'(Objref,New_container,New_name,New_version) ->
- orber_ifr_contained:move(Objref,New_container,New_name,New_version).
-
-'Container__get_def_kind'(Objref) ->
- orber_ifr_container:'_get_def_kind'(Objref).
-'Container_destroy'(Objref) ->
- orber_ifr_container:destroy(Objref).
-'Container_lookup'(Objref,Search_name) ->
- orber_ifr_container:lookup(Objref,Search_name).
-'Container_contents'(Objref,Limit_type,Exclude_inherited) ->
- orber_ifr_container:contents(Objref,Limit_type,Exclude_inherited).
-'Container_lookup_name'(Objref,Search_name,Levels_to_search,Limit_type,
- Exclude_inherited) ->
- orber_ifr_container:lookup_name(Objref,Search_name,Levels_to_search,Limit_type,
- Exclude_inherited).
-'Container_describe_contents'(Objref,Limit_type,Exclude_inherited,
- Max_returned_objs) ->
- orber_ifr_container:describe_contents(Objref,Limit_type,Exclude_inherited,
- Max_returned_objs).
-'Container_create_module'(Objref,Id,Name,Version) ->
- orber_ifr_container:create_module(Objref,Id,Name,Version).
-'Container_create_constant'(Objref,Id,Name,Version,Type,Value) ->
- orber_ifr_container:create_constant(Objref,Id,Name,Version,Type,Value).
-'Container_create_struct'(Objref,Id,Name,Version,Members) ->
- orber_ifr_container:create_struct(Objref,Id,Name,Version,Members).
-'Container_create_union'(Objref,Id,Name,Version,Discriminator_type,Members) ->
- orber_ifr_container:create_union(Objref,Id,Name,Version,Discriminator_type,
- Members).
-'Container_create_enum'(Objref,Id,Name,Version,Members) ->
- orber_ifr_container:create_enum(Objref,Id,Name,Version,Members).
-'Container_create_alias'(Objref,Id,Name,Version,Original_type) ->
- orber_ifr_container:create_alias(Objref,Id,Name,Version,Original_type).
-'Container_create_interface'(Objref,Id,Name,Version,Base_interfaces) ->
- orber_ifr_container:create_interface(Objref,Id,Name,Version,Base_interfaces).
-'Container_create_exception'(Objref,Id,Name,Version,Members) ->
- orber_ifr_container:create_exception(Objref,Id,Name,Version,Members).
-
-'IDLType__get_def_kind'(Objref) ->
- orber_ifr_idltype:'_get_def_kind'(Objref).
-'IDLType_destroy'(Objref) ->
- orber_ifr_idltype:destroy(Objref).
-'IDLType__get_type'(Objref) ->
- orber_ifr_idltype:'_get_type'(Objref).
-
-'Repository__get_def_kind'(Objref) ->
- orber_ifr_repository:'_get_def_kind'(Objref).
--spec 'Repository_destroy'(_) -> no_return().
-'Repository_destroy'(Objref) ->
- orber_ifr_repository:destroy(Objref).
-'Repository_lookup'(Objref,Search_name) ->
- orber_ifr_repository:lookup(Objref,Search_name).
-'Repository_contents'(Objref,Limit_type,Exclude_inherited) ->
- orber_ifr_repository:contents(Objref,Limit_type,Exclude_inherited).
-'Repository_lookup_name'(Objref,Search_name,Levels_to_search,Limit_type,
- Exclude_inherited) ->
- orber_ifr_repository:lookup_name(Objref,Search_name,Levels_to_search,Limit_type,
- Exclude_inherited).
-'Repository_describe_contents'(Objref,Limit_type,Exclude_inherited,
- Max_returned_objs) ->
- orber_ifr_repository:describe_contents(Objref,Limit_type,Exclude_inherited,
- Max_returned_objs).
-'Repository_create_module'(Objref,Id,Name,Version) ->
- orber_ifr_repository:create_module(Objref,Id,Name,Version).
-'Repository_create_constant'(Objref,Id,Name,Version,Type,Value) ->
- orber_ifr_repository:create_constant(Objref,Id,Name,Version,Type,Value).
-'Repository_create_struct'(Objref,Id,Name,Version,Members) ->
- orber_ifr_repository:create_struct(Objref,Id,Name,Version,Members).
-'Repository_create_union'(Objref,Id,Name,Version,Discriminator_type,Members) ->
- orber_ifr_repository:create_union(Objref,Id,Name,Version,Discriminator_type,
- Members).
-'Repository_create_enum'(Objref,Id,Name,Version,Members) ->
- orber_ifr_repository:create_enum(Objref,Id,Name,Version,Members).
-'Repository_create_alias'(Objref,Id,Name,Version,Original_type) ->
- orber_ifr_repository:create_alias(Objref,Id,Name,Version,Original_type).
-'Repository_create_interface'(Objref,Id,Name,Version,Base_interfaces) ->
- orber_ifr_repository:create_interface(Objref,Id,Name,Version,Base_interfaces).
-'Repository_create_exception'(Objref,Id,Name,Version,Members) ->
- orber_ifr_repository:create_exception(Objref,Id,Name,Version,Members).
-'Repository_lookup_id'(Objref,Search_id) ->
- lookup_id(Objref,Search_id).
-'Repository_get_primitive'(Objref,Kind) ->
- orber_ifr_repository:get_primitive(Objref,Kind).
-'Repository_create_string'(Objref,Bound) ->
- orber_ifr_repository:create_string(Objref,Bound).
-'Repository_create_wstring'(Objref,Bound) ->
- orber_ifr_repository:create_wstring(Objref,Bound).
-'Repository_create_sequence'(Objref,Bound,Element_type) ->
- orber_ifr_repository:create_sequence(Objref,Bound,Element_type).
-'Repository_create_array'(Objref,Length,Element_type) ->
- orber_ifr_repository:create_array(Objref,Length,Element_type).
-'Repository_create_idltype'(Objref,Typecode) ->
- orber_ifr_repository:create_idltype(Objref,Typecode).
-
-'ModuleDef__get_def_kind'(Objref) ->
- orber_ifr_moduledef:'_get_def_kind'(Objref).
-'ModuleDef_destroy'(Objref) ->
- orber_ifr_moduledef:destroy(Objref).
-'ModuleDef_lookup'(Objref,Search_name) ->
- orber_ifr_moduledef:lookup(Objref,Search_name).
-'ModuleDef_contents'(Objref,Limit_type,Exclude_inherited) ->
- orber_ifr_moduledef:contents(Objref,Limit_type,Exclude_inherited).
-'ModuleDef_lookup_name'(Objref,Search_name,Levels_to_search,Limit_type,
- Exclude_inherited) ->
- orber_ifr_moduledef:lookup_name(Objref,Search_name,Levels_to_search,Limit_type,
- Exclude_inherited).
-'ModuleDef_describe_contents'(Objref,Limit_type,Exclude_inherited,
- Max_returned_objs) ->
- orber_ifr_moduledef:describe_contents(Objref,Limit_type,Exclude_inherited,
- Max_returned_objs).
-'ModuleDef_create_module'(Objref,Id,Name,Version) ->
- orber_ifr_moduledef:create_module(Objref,Id,Name,Version).
-'ModuleDef_create_constant'(Objref,Id,Name,Version,Type,Value) ->
- orber_ifr_moduledef:create_constant(Objref,Id,Name,Version,Type,Value).
-'ModuleDef_create_struct'(Objref,Id,Name,Version,Members) ->
- orber_ifr_moduledef:create_struct(Objref,Id,Name,Version,Members).
-'ModuleDef_create_union'(Objref,Id,Name,Version,Discriminator_type,Members) ->
- orber_ifr_moduledef:create_union(Objref,Id,Name,Version,Discriminator_type,
- Members).
-'ModuleDef_create_enum'(Objref,Id,Name,Version,Members) ->
- orber_ifr_moduledef:create_enum(Objref,Id,Name,Version,Members).
-'ModuleDef_create_alias'(Objref,Id,Name,Version,Original_type) ->
- orber_ifr_moduledef:create_alias(Objref,Id,Name,Version,Original_type).
-'ModuleDef_create_interface'(Objref,Id,Name,Version,Base_interfaces) ->
- orber_ifr_moduledef:create_interface(Objref,Id,Name,Version,Base_interfaces).
-'ModuleDef_create_exception'(Objref,Id,Name,Version,Members) ->
- orber_ifr_moduledef:create_exception(Objref,Id,Name,Version,Members).
-'ModuleDef__get_id'(Objref) ->
- orber_ifr_moduledef:'_get_id'(Objref).
-'ModuleDef__set_id'(Objref,Id) ->
- orber_ifr_moduledef:'_set_id'(Objref,Id).
-'ModuleDef__get_name'(Objref) ->
- orber_ifr_moduledef:'_get_name'(Objref).
-'ModuleDef__set_name'(Objref,Name) ->
- orber_ifr_moduledef:'_set_name'(Objref,Name).
-'ModuleDef__get_version'(Objref) ->
- orber_ifr_moduledef:'_get_version'(Objref).
-'ModuleDef__set_version'(Objref,Version) ->
- orber_ifr_moduledef:'_set_version'(Objref,Version).
-'ModuleDef__get_defined_in'(Objref) ->
- orber_ifr_moduledef:'_get_defined_in'(Objref).
-'ModuleDef__get_absolute_name'(Objref) ->
- orber_ifr_moduledef:'_get_absolute_name'(Objref).
-'ModuleDef__get_containing_repository'(Objref) ->
- orber_ifr_moduledef:'_get_containing_repository'(Objref).
-'ModuleDef_describe'(Objref) ->
- orber_ifr_moduledef:describe(Objref).
-'ModuleDef_move'(Objref,New_container,New_name,New_version) ->
- orber_ifr_moduledef:move(Objref,New_container,New_name,New_version).
-
-'ConstantDef__get_def_kind'(Objref) ->
- orber_ifr_constantdef:'_get_def_kind'(Objref).
-'ConstantDef_destroy'(Objref) ->
- orber_ifr_constantdef:destroy(Objref).
-'ConstantDef__get_id'(Objref) ->
- orber_ifr_constantdef:'_get_id'(Objref).
-'ConstantDef__set_id'(Objref,Id) ->
- orber_ifr_constantdef:'_set_id'(Objref,Id).
-'ConstantDef__get_name'(Objref) ->
- orber_ifr_constantdef:'_get_name'(Objref).
-'ConstantDef__set_name'(Objref,Name) ->
- orber_ifr_constantdef:'_set_name'(Objref,Name).
-'ConstantDef__get_version'(Objref) ->
- orber_ifr_constantdef:'_get_version'(Objref).
-'ConstantDef__set_version'(Objref,Version) ->
- orber_ifr_constantdef:'_set_version'(Objref,Version).
-'ConstantDef__get_defined_in'(Objref) ->
- orber_ifr_constantdef:'_get_defined_in'(Objref).
-'ConstantDef__get_absolute_name'(Objref) ->
- orber_ifr_constantdef:'_get_absolute_name'(Objref).
-'ConstantDef__get_containing_repository'(Objref) ->
- orber_ifr_constantdef:'_get_containing_repository'(Objref).
-'ConstantDef_describe'(Objref) ->
- orber_ifr_constantdef:describe(Objref).
-'ConstantDef_move'(Objref,New_container,New_name,New_version) ->
- orber_ifr_constantdef:move(Objref,New_container,New_name,New_version).
-'ConstantDef__get_type'(Objref) ->
- orber_ifr_constantdef:'_get_type'(Objref).
-'ConstantDef__get_type_def'(Objref) ->
- orber_ifr_constantdef:'_get_type_def'(Objref).
-'ConstantDef__set_type_def'(Objref,TypeDef) ->
- orber_ifr_constantdef:'_set_type_def'(Objref,TypeDef).
-'ConstantDef__get_value'(Objref) ->
- orber_ifr_constantdef:'_get_value'(Objref).
-'ConstantDef__set_value'(Objref,Value) ->
- orber_ifr_constantdef:'_set_value'(Objref,Value).
-
-'TypedefDef__get_def_kind'(Objref) ->
- orber_ifr_typedef:'_get_def_kind'(Objref).
-'TypedefDef_destroy'(Objref) ->
- orber_ifr_typedef:destroy(Objref).
-'TypedefDef__get_id'(Objref) ->
- orber_ifr_typedef:'_get_id'(Objref).
-'TypedefDef__set_id'(Objref,Id) ->
- orber_ifr_typedef:'_set_id'(Objref,Id).
-'TypedefDef__get_name'(Objref) ->
- orber_ifr_typedef:'_get_name'(Objref).
-'TypedefDef__set_name'(Objref,Name) ->
- orber_ifr_typedef:'_set_name'(Objref,Name).
-'TypedefDef__get_version'(Objref) ->
- orber_ifr_typedef:'_get_version'(Objref).
-'TypedefDef__set_version'(Objref,Version) ->
- orber_ifr_typedef:'_set_version'(Objref,Version).
-'TypedefDef__get_defined_in'(Objref) ->
- orber_ifr_typedef:'_get_defined_in'(Objref).
-'TypedefDef__get_absolute_name'(Objref) ->
- orber_ifr_typedef:'_get_absolute_name'(Objref).
-'TypedefDef__get_containing_repository'(Objref) ->
- orber_ifr_typedef:'_get_containing_repository'(Objref).
-'TypedefDef_describe'(Objref) ->
- orber_ifr_typedef:describe(Objref).
-'TypedefDef_move'(Objref,New_container,New_name,New_version) ->
- orber_ifr_typedef:move(Objref,New_container,New_name,New_version).
-'TypedefDef__get_type'(Objref) ->
- orber_ifr_typedef:'_get_type'(Objref).
-
-'StructDef__get_def_kind'(Objref) ->
- orber_ifr_structdef:'_get_def_kind'(Objref).
-'StructDef_destroy'(Objref) ->
- orber_ifr_structdef:destroy(Objref).
-'StructDef__get_id'(Objref) ->
- orber_ifr_structdef:'_get_id'(Objref).
-'StructDef__set_id'(Objref,Id) ->
- orber_ifr_structdef:'_set_id'(Objref,Id).
-'StructDef__get_name'(Objref) ->
- orber_ifr_structdef:'_get_name'(Objref).
-'StructDef__set_name'(Objref,Name) ->
- orber_ifr_structdef:'_set_name'(Objref,Name).
-'StructDef__get_version'(Objref) ->
- orber_ifr_structdef:'_get_version'(Objref).
-'StructDef__set_version'(Objref,Version) ->
- orber_ifr_structdef:'_set_version'(Objref,Version).
-'StructDef__get_defined_in'(Objref) ->
- orber_ifr_structdef:'_get_defined_in'(Objref).
-'StructDef__get_absolute_name'(Objref) ->
- orber_ifr_structdef:'_get_absolute_name'(Objref).
-'StructDef__get_containing_repository'(Objref) ->
- orber_ifr_structdef:'_get_containing_repository'(Objref).
-'StructDef_describe'(Objref) ->
- orber_ifr_structdef:describe(Objref).
-'StructDef_move'(Objref,New_container,New_name,New_version) ->
- orber_ifr_structdef:move(Objref,New_container,New_name,New_version).
-'StructDef__get_type'(Objref) ->
- orber_ifr_structdef:'_get_type'(Objref).
-'StructDef__get_members'(Objref) ->
- orber_ifr_structdef:'_get_members'(Objref).
-'StructDef__set_members'(Objref,Members) ->
- orber_ifr_structdef:'_set_members'(Objref,Members).
-
-'UnionDef__get_def_kind'(Objref) ->
- orber_ifr_uniondef:'_get_def_kind'(Objref).
-'UnionDef_destroy'(Objref) ->
- orber_ifr_uniondef:destroy(Objref).
-'UnionDef__get_id'(Objref) ->
- orber_ifr_uniondef:'_get_id'(Objref).
-'UnionDef__set_id'(Objref,Id) ->
- orber_ifr_uniondef:'_set_id'(Objref,Id).
-'UnionDef__get_name'(Objref) ->
- orber_ifr_uniondef:'_get_name'(Objref).
-'UnionDef__set_name'(Objref,Name) ->
- orber_ifr_uniondef:'_set_name'(Objref,Name).
-'UnionDef__get_version'(Objref) ->
- orber_ifr_uniondef:'_get_version'(Objref).
-'UnionDef__set_version'(Objref,Version) ->
- orber_ifr_uniondef:'_set_version'(Objref,Version).
-'UnionDef__get_defined_in'(Objref) ->
- orber_ifr_uniondef:'_get_defined_in'(Objref).
-'UnionDef__get_absolute_name'(Objref) ->
- orber_ifr_uniondef:'_get_absolute_name'(Objref).
-'UnionDef__get_containing_repository'(Objref) ->
- orber_ifr_uniondef:'_get_containing_repository'(Objref).
-'UnionDef_describe'(Objref) ->
- orber_ifr_uniondef:describe(Objref).
-'UnionDef_move'(Objref,New_container,New_name,New_version) ->
- orber_ifr_uniondef:move(Objref,New_container,New_name,New_version).
-'UnionDef__get_type'(Objref) ->
- orber_ifr_uniondef:'_get_type'(Objref).
-'UnionDef__get_discriminator_type'(Objref) ->
- orber_ifr_uniondef:'_get_discriminator_type'(Objref).
-'UnionDef__get_discriminator_type_def'(Objref) ->
- orber_ifr_uniondef:'_get_discriminator_type_def'(Objref).
-'UnionDef__set_discriminator_type_def'(Objref,TypeDef) ->
- orber_ifr_uniondef:'_set_discriminator_type_def'(Objref,TypeDef).
-'UnionDef__get_members'(Objref) ->
- orber_ifr_uniondef:'_get_members'(Objref).
-'UnionDef__set_members'(Objref,Members) ->
- orber_ifr_uniondef:'_set_members'(Objref,Members).
-
-'EnumDef__get_def_kind'(Objref) ->
- orber_ifr_enumdef:'_get_def_kind'(Objref).
-'EnumDef_destroy'(Objref) ->
- orber_ifr_enumdef:destroy(Objref).
-'EnumDef__get_id'(Objref) ->
- orber_ifr_enumdef:'_get_id'(Objref).
-'EnumDef__set_id'(Objref,Id) ->
- orber_ifr_enumdef:'_set_id'(Objref,Id).
-'EnumDef__get_name'(Objref) ->
- orber_ifr_enumdef:'_get_name'(Objref).
-'EnumDef__set_name'(Objref,Name) ->
- orber_ifr_enumdef:'_set_name'(Objref,Name).
-'EnumDef__get_version'(Objref) ->
- orber_ifr_enumdef:'_get_version'(Objref).
-'EnumDef__set_version'(Objref,Version) ->
- orber_ifr_enumdef:'_set_version'(Objref,Version).
-'EnumDef__get_defined_in'(Objref) ->
- orber_ifr_enumdef:'_get_defined_in'(Objref).
-'EnumDef__get_absolute_name'(Objref) ->
- orber_ifr_enumdef:'_get_absolute_name'(Objref).
-'EnumDef__get_containing_repository'(Objref) ->
- orber_ifr_enumdef:'_get_containing_repository'(Objref).
-'EnumDef_describe'(Objref) ->
- orber_ifr_enumdef:describe(Objref).
-'EnumDef_move'(Objref,New_container,New_name,New_version) ->
- orber_ifr_enumdef:move(Objref,New_container,New_name,New_version).
-'EnumDef__get_type'(Objref) ->
- orber_ifr_enumdef:'_get_type'(Objref).
-'EnumDef__get_members'(Objref) ->
- orber_ifr_enumdef:'_get_members'(Objref).
-'EnumDef__set_members'(Objref,Members) ->
- orber_ifr_enumdef:'_set_members'(Objref,Members).
-
-'AliasDef__get_def_kind'(Objref) ->
- orber_ifr_aliasdef:'_get_def_kind'(Objref).
-'AliasDef_destroy'(Objref) ->
- orber_ifr_aliasdef:destroy(Objref).
-'AliasDef__get_id'(Objref) ->
- orber_ifr_aliasdef:'_get_id'(Objref).
-'AliasDef__set_id'(Objref,Id) ->
- orber_ifr_aliasdef:'_set_id'(Objref,Id).
-'AliasDef__get_name'(Objref) ->
- orber_ifr_aliasdef:'_get_name'(Objref).
-'AliasDef__set_name'(Objref,Name) ->
- orber_ifr_aliasdef:'_set_name'(Objref,Name).
-'AliasDef__get_version'(Objref) ->
- orber_ifr_aliasdef:'_get_version'(Objref).
-'AliasDef__set_version'(Objref,Version) ->
- orber_ifr_aliasdef:'_set_version'(Objref,Version).
-'AliasDef__get_defined_in'(Objref) ->
- orber_ifr_aliasdef:'_get_defined_in'(Objref).
-'AliasDef__get_absolute_name'(Objref) ->
- orber_ifr_aliasdef:'_get_absolute_name'(Objref).
-'AliasDef__get_containing_repository'(Objref) ->
- orber_ifr_aliasdef:'_get_containing_repository'(Objref).
-'AliasDef_describe'(Objref) ->
- orber_ifr_aliasdef:describe(Objref).
-'AliasDef_move'(Objref,New_container,New_name,New_version) ->
- orber_ifr_aliasdef:move(Objref,New_container,New_name,New_version).
-'AliasDef__get_type'(Objref) ->
- orber_ifr_aliasdef:'_get_type'(Objref).
-'AliasDef__get_original_type_def'(Objref) ->
- orber_ifr_aliasdef:'_get_original_type_def'(Objref).
-'AliasDef__set_original_type_def'(Objref,TypeDef) ->
- orber_ifr_aliasdef:'_set_original_type_def'(Objref,TypeDef).
-
-'PrimitiveDef__get_def_kind'(Objref) ->
- orber_ifr_primitivedef:'_get_def_kind'(Objref).
-'PrimitiveDef_destroy'(Objref) ->
- orber_ifr_primitivedef:destroy(Objref).
-'PrimitiveDef__get_type'(Objref) ->
- orber_ifr_primitivedef:'_get_type'(Objref).
-'PrimitiveDef__get_kind'(Objref) ->
- orber_ifr_primitivedef:'_get_kind'(Objref).
-
-'StringDef__get_def_kind'(Objref) ->
- orber_ifr_stringdef:'_get_def_kind'(Objref).
-'StringDef_destroy'(Objref) ->
- orber_ifr_stringdef:destroy(Objref).
-'StringDef__get_type'(Objref) ->
- orber_ifr_stringdef:'_get_type'(Objref).
-'StringDef__get_bound'(Objref) ->
- orber_ifr_stringdef:'_get_bound'(Objref).
-'StringDef__set_bound'(Objref,Bound) ->
- orber_ifr_stringdef:'_set_bound'(Objref,Bound).
-
-'WstringDef__get_def_kind'(Objref) ->
- orber_ifr_wstringdef:'_get_def_kind'(Objref).
-'WstringDef_destroy'(Objref) ->
- orber_ifr_wstringdef:destroy(Objref).
-'WstringDef__get_type'(Objref) ->
- orber_ifr_wstringdef:'_get_type'(Objref).
-'WstringDef__get_bound'(Objref) ->
- orber_ifr_wstringdef:'_get_bound'(Objref).
-'WstringDef__set_bound'(Objref,Bound) ->
- orber_ifr_wstringdef:'_set_bound'(Objref,Bound).
-
-'FixedDef__get_def_kind'(Objref) ->
- orber_ifr_fixeddef:'_get_def_kind'(Objref).
-'FixedDef_destroy'(Objref) ->
- orber_ifr_fixeddef:destroy(Objref).
-'FixedDef__get_type'(Objref) ->
- orber_ifr_fixeddef:'_get_type'(Objref).
-'FixedDef__get_digits'(Objref) ->
- orber_ifr_fixeddef:'_get_digits'(Objref).
-'FixedDef__set_digits'(Objref,Digits) ->
- orber_ifr_fixeddef:'_set_digits'(Objref,Digits).
-'FixedDef__get_scale'(Objref) ->
- orber_ifr_fixeddef:'_get_scale'(Objref).
-'FixedDef__set_scale'(Objref,Scale) ->
- orber_ifr_fixeddef:'_set_scale'(Objref,Scale).
-
-'SequenceDef__get_def_kind'(Objref) ->
- orber_ifr_sequencedef:'_get_def_kind'(Objref).
-'SequenceDef_destroy'(Objref) ->
- orber_ifr_sequencedef:destroy(Objref).
-'SequenceDef__get_type'(Objref) ->
- orber_ifr_sequencedef:'_get_type'(Objref).
-'SequenceDef__get_bound'(Objref) ->
- orber_ifr_sequencedef:'_get_bound'(Objref).
-'SequenceDef__set_bound'(Objref,Bound) ->
- orber_ifr_sequencedef:'_set_bound'(Objref,Bound).
-'SequenceDef__get_element_type'(Objref) ->
- orber_ifr_sequencedef:'_get_element_type'(Objref).
-'SequenceDef__get_element_type_def'(Objref) ->
- orber_ifr_sequencedef:'_get_element_type_def'(Objref).
-'SequenceDef__set_element_type_def'(Objref,TypeDef) ->
- orber_ifr_sequencedef:'_set_element_type_def'(Objref,TypeDef).
-
-'ArrayDef__get_def_kind'(Objref) ->
- orber_ifr_arraydef:'_get_def_kind'(Objref).
-'ArrayDef_destroy'(Objref) ->
- orber_ifr_arraydef:destroy(Objref).
-'ArrayDef__get_type'(Objref) ->
- orber_ifr_arraydef:'_get_type'(Objref).
-'ArrayDef__get_length'(Objref) ->
- orber_ifr_arraydef:'_get_length'(Objref).
-'ArrayDef__set_length'(Objref,Length) ->
- orber_ifr_arraydef:'_set_length'(Objref,Length).
-'ArrayDef__get_element_type'(Objref) ->
- orber_ifr_arraydef:'_get_element_type'(Objref).
-'ArrayDef__get_element_type_def'(Objref) ->
- orber_ifr_arraydef:'_get_element_type_def'(Objref).
-'ArrayDef__set_element_type_def'(Objref,TypeDef) ->
- orber_ifr_arraydef:'_set_element_type_def'(Objref,TypeDef).
-
-'ExceptionDef__get_def_kind'(Objref) ->
- orber_ifr_exceptiondef:'_get_def_kind'(Objref).
-'ExceptionDef_destroy'(Objref) ->
- orber_ifr_exceptiondef:destroy(Objref).
-'ExceptionDef__get_id'(Objref) ->
- orber_ifr_exceptiondef:'_get_id'(Objref).
-'ExceptionDef__set_id'(Objref,Id) ->
- orber_ifr_exceptiondef:'_set_id'(Objref,Id).
-'ExceptionDef__get_name'(Objref) ->
- orber_ifr_exceptiondef:'_get_name'(Objref).
-'ExceptionDef__set_name'(Objref,Name) ->
- orber_ifr_exceptiondef:'_set_name'(Objref,Name).
-'ExceptionDef__get_version'(Objref) ->
- orber_ifr_exceptiondef:'_get_version'(Objref).
-'ExceptionDef__set_version'(Objref,Version) ->
- orber_ifr_exceptiondef:'_set_version'(Objref,Version).
-'ExceptionDef__get_defined_in'(Objref) ->
- orber_ifr_exceptiondef:'_get_defined_in'(Objref).
-'ExceptionDef__get_absolute_name'(Objref) ->
- orber_ifr_exceptiondef:'_get_absolute_name'(Objref).
-'ExceptionDef__get_containing_repository'(Objref) ->
- orber_ifr_exceptiondef:'_get_containing_repository'(Objref).
-'ExceptionDef_describe'(Objref) ->
- orber_ifr_exceptiondef:describe(Objref).
-'ExceptionDef_move'(Objref,New_container,New_name,New_version) ->
- orber_ifr_exceptiondef:move(Objref,New_container,New_name,New_version).
-'ExceptionDef__get_type'(Objref) ->
- orber_ifr_exceptiondef:'_get_type'(Objref).
-'ExceptionDef__get_members'(Objref) ->
- orber_ifr_exceptiondef:'_get_members'(Objref).
-'ExceptionDef__set_members'(Objref,Members) ->
- orber_ifr_exceptiondef:'_set_members'(Objref,Members).
-
-'AttributeDef__get_def_kind'(Objref) ->
- orber_ifr_attributedef:'_get_def_kind'(Objref).
-'AttributeDef_destroy'(Objref) ->
- orber_ifr_attributedef:destroy(Objref).
-'AttributeDef__get_id'(Objref) ->
- orber_ifr_attributedef:'_get_id'(Objref).
-'AttributeDef__set_id'(Objref,Id) ->
- orber_ifr_attributedef:'_set_id'(Objref,Id).
-'AttributeDef__get_name'(Objref) ->
- orber_ifr_attributedef:'_get_name'(Objref).
-'AttributeDef__set_name'(Objref,Name) ->
- orber_ifr_attributedef:'_set_name'(Objref,Name).
-'AttributeDef__get_version'(Objref) ->
- orber_ifr_attributedef:'_get_version'(Objref).
-'AttributeDef__set_version'(Objref,Version) ->
- orber_ifr_attributedef:'_set_version'(Objref,Version).
-'AttributeDef__get_defined_in'(Objref) ->
- orber_ifr_attributedef:'_get_defined_in'(Objref).
-'AttributeDef__get_absolute_name'(Objref) ->
- orber_ifr_attributedef:'_get_absolute_name'(Objref).
-'AttributeDef__get_containing_repository'(Objref) ->
- orber_ifr_attributedef:'_get_containing_repository'(Objref).
-'AttributeDef_describe'(Objref) ->
- orber_ifr_attributedef:describe(Objref).
-'AttributeDef_move'(Objref,New_container,New_name,New_version) ->
- orber_ifr_attributedef:move(Objref,New_container,New_name,New_version).
-'AttributeDef__get_type'(Objref) ->
- orber_ifr_attributedef:'_get_type'(Objref).
-'AttributeDef__get_type_def'(Objref) ->
- orber_ifr_attributedef:'_get_type_def'(Objref).
-'AttributeDef__set_type_def'(Objref,TypeDef) ->
- orber_ifr_attributedef:'_set_type_def'(Objref,TypeDef).
-'AttributeDef__get_mode'(Objref) ->
- orber_ifr_attributedef:'_get_mode'(Objref).
-'AttributeDef__set_mode'(Objref,Mode) ->
- orber_ifr_attributedef:'_set_mode'(Objref,Mode).
-
-'OperationDef__get_def_kind'(Objref) ->
- orber_ifr_operationdef:'_get_def_kind'(Objref).
-'OperationDef_destroy'(Objref) ->
- orber_ifr_operationdef:destroy(Objref).
-'OperationDef__get_id'(Objref) ->
- orber_ifr_operationdef:'_get_id'(Objref).
-'OperationDef__set_id'(Objref,Id) ->
- orber_ifr_operationdef:'_set_id'(Objref,Id).
-'OperationDef__get_name'(Objref) ->
- orber_ifr_operationdef:'_get_name'(Objref).
-'OperationDef__set_name'(Objref,Name) ->
- orber_ifr_operationdef:'_set_name'(Objref,Name).
-'OperationDef__get_version'(Objref) ->
- orber_ifr_operationdef:'_get_version'(Objref).
-'OperationDef__set_version'(Objref,Version) ->
- orber_ifr_operationdef:'_set_version'(Objref,Version).
-'OperationDef__get_defined_in'(Objref) ->
- orber_ifr_operationdef:'_get_defined_in'(Objref).
-'OperationDef__get_absolute_name'(Objref) ->
- orber_ifr_operationdef:'_get_absolute_name'(Objref).
-'OperationDef__get_containing_repository'(Objref) ->
- orber_ifr_operationdef:'_get_containing_repository'(Objref).
-'OperationDef_describe'(Objref) ->
- orber_ifr_operationdef:describe(Objref).
-'OperationDef_move'(Objref,New_container,New_name,New_version) ->
- orber_ifr_operationdef:move(Objref,New_container,New_name,New_version).
-'OperationDef__get_result'(Objref) ->
- orber_ifr_operationdef:'_get_result'(Objref).
-'OperationDef__get_result_def'(Objref) ->
- orber_ifr_operationdef:'_get_result_def'(Objref).
-'OperationDef__set_result_def'(Objref,ResultDef) ->
- orber_ifr_operationdef:'_set_result_def'(Objref,ResultDef).
-'OperationDef__get_params'(Objref) ->
- orber_ifr_operationdef:'_get_params'(Objref).
-'OperationDef__set_params'(Objref,Params) ->
- orber_ifr_operationdef:'_set_params'(Objref,Params).
-'OperationDef__get_mode'(Objref) ->
- orber_ifr_operationdef:'_get_mode'(Objref).
-'OperationDef__set_mode'(Objref,Mode) ->
- orber_ifr_operationdef:'_set_mode'(Objref,Mode).
-'OperationDef__get_contexts'(Objref) ->
- orber_ifr_operationdef:'_get_contexts'(Objref).
-'OperationDef__set_contexts'(Objref,Contexts) ->
- orber_ifr_operationdef:'_set_contexts'(Objref,Contexts).
-'OperationDef__get_exceptions'(Objref) ->
- orber_ifr_operationdef:'_get_exceptions'(Objref).
-'OperationDef__set_exceptions'(Objref,Exceptions) ->
- orber_ifr_operationdef:'_set_exceptions'(Objref,Exceptions).
-
-'InterfaceDef__get_def_kind'(Objref) ->
- orber_ifr_interfacedef:'_get_def_kind'(Objref).
-'InterfaceDef_destroy'(Objref) ->
- orber_ifr_interfacedef:destroy(Objref).
-'InterfaceDef_lookup'(Objref,Search_name) ->
- orber_ifr_interfacedef:lookup(Objref,Search_name).
-'InterfaceDef_contents'(Objref,Limit_type,Exclude_inherited) ->
- orber_ifr_interfacedef:contents(Objref,Limit_type,Exclude_inherited).
-'InterfaceDef_lookup_name'(Objref,Search_name,Levels_to_search,Limit_type,
- Exclude_inherited) ->
- orber_ifr_interfacedef:lookup_name(Objref,Search_name,Levels_to_search,Limit_type,
- Exclude_inherited).
-'InterfaceDef_describe_contents'(Objref,Limit_type,Exclude_inherited,
- Max_returned_objs) ->
- orber_ifr_interfacedef:describe_contents(Objref,Limit_type,Exclude_inherited,
- Max_returned_objs).
-'InterfaceDef_create_module'(Objref,Id,Name,Version) ->
- orber_ifr_interfacedef:create_module(Objref,Id,Name,Version).
-'InterfaceDef_create_constant'(Objref,Id,Name,Version,Type,Value) ->
- orber_ifr_interfacedef:create_constant(Objref,Id,Name,Version,Type,Value).
-'InterfaceDef_create_struct'(Objref,Id,Name,Version,Members) ->
- orber_ifr_interfacedef:create_struct(Objref,Id,Name,Version,Members).
-'InterfaceDef_create_union'(Objref,Id,Name,Version,Discriminator_type,
- Members) ->
- orber_ifr_interfacedef:create_union(Objref,Id,Name,Version,Discriminator_type,
- Members).
-'InterfaceDef_create_enum'(Objref,Id,Name,Version,Members) ->
- orber_ifr_interfacedef:create_enum(Objref,Id,Name,Version,Members).
-'InterfaceDef_create_alias'(Objref,Id,Name,Version,Original_type) ->
- orber_ifr_interfacedef:create_alias(Objref,Id,Name,Version,Original_type).
-'InterfaceDef_create_interface'(Objref,Id,Name,Version,Base_interfaces) ->
- orber_ifr_interfacedef:create_interface(Objref,Id,Name,Version,Base_interfaces).
-'InterfaceDef_create_exception'(Objref,Id,Name,Version,Members) ->
- orber_ifr_interfacedef:create_exception(Objref,Id,Name,Version,Members).
-'InterfaceDef__get_id'(Objref) ->
- orber_ifr_interfacedef:'_get_id'(Objref).
-'InterfaceDef__set_id'(Objref,Id) ->
- orber_ifr_interfacedef:'_set_id'(Objref,Id).
-'InterfaceDef__get_name'(Objref) ->
- orber_ifr_interfacedef:'_get_name'(Objref).
-'InterfaceDef__set_name'(Objref,Name) ->
- orber_ifr_interfacedef:'_set_name'(Objref,Name).
-'InterfaceDef__get_version'(Objref) ->
- orber_ifr_interfacedef:'_get_version'(Objref).
-'InterfaceDef__set_version'(Objref,Version) ->
- orber_ifr_interfacedef:'_set_version'(Objref,Version).
-'InterfaceDef__get_defined_in'(Objref) ->
- orber_ifr_interfacedef:'_get_defined_in'(Objref).
-'InterfaceDef__get_absolute_name'(Objref) ->
- orber_ifr_interfacedef:'_get_absolute_name'(Objref).
-'InterfaceDef__get_containing_repository'(Objref) ->
- orber_ifr_interfacedef:'_get_containing_repository'(Objref).
-'InterfaceDef_describe'(Objref) ->
- orber_ifr_interfacedef:describe(Objref).
-'InterfaceDef_move'(Objref,New_container,New_name,New_version) ->
- orber_ifr_interfacedef:move(Objref,New_container,New_name,New_version).
-'InterfaceDef__get_type'(Objref) ->
- orber_ifr_interfacedef:'_get_type'(Objref).
-'InterfaceDef__get_base_interfaces'(Objref) ->
- orber_ifr_interfacedef:'_get_base_interfaces'(Objref).
-'InterfaceDef__set_base_interfaces'(Objref,BaseInterfaces) ->
- orber_ifr_interfacedef:'_set_base_interfaces'(Objref,BaseInterfaces).
-'InterfaceDef_is_a'(Objref,Interface_id) ->
- orber_ifr_interfacedef:is_a(Objref,Interface_id).
-'InterfaceDef_describe_interface'(Objref) ->
- orber_ifr_interfacedef:describe_interface(Objref).
-'InterfaceDef_create_attribute'(Objref,Id,Name,Version,Type,Mode) ->
- orber_ifr_interfacedef:create_attribute(Objref,Id,Name,Version,Type,Mode).
-'InterfaceDef_create_operation'(Objref,Id,Name,Version,Result,Mode,Params,
- Exceptions,Contexts) ->
- orber_ifr_interfacedef:create_operation(Objref,Id,Name,Version,Result,Mode,
- Params,Exceptions,Contexts).
-
-%%'TypeCode_equal'(Objref,Tc) ->
-%% orber_ifr_typecode:equal(Objref,Tc).
-%%'TypeCode_kind'(Objref) ->
-%% orber_ifr_typecode:kind(Objref).
-%%'TypeCode_id'(Objref) ->
-%% orber_ifr_typecode:id(Objref).
-%%'TypeCode_name'(Objref) ->
-%% orber_ifr_typecode:name(Objref).
-%%'TypeCode_member_count'(Objref) ->
-%% orber_ifr_typecode:member_count(Objref).
-%%'TypeCode_member_name'(Objref,Index) ->
-%% orber_ifr_typecode:member_name(Objref,Index).
-%%'TypeCode_member_type'(Objref,Index) ->
-%% orber_ifr_typecode:member_type(Objref,Index).
-%%'TypeCode_member_label'(Objref,Index) ->
-%% orber_ifr_typecode:member_label(Objref,Index).
-%%'TypeCode_discriminator_type'(Objref) ->
-%% orber_ifr_typecode:discriminator_type(Objref).
-%%'TypeCode_default_index'(Objref) ->
-%% orber_ifr_typecode:default_index(Objref).
-%%'TypeCode_length'(Objref) ->
-%% orber_ifr_typecode:length(Objref).
-%%'TypeCode_content_type'(Objref) ->
-%% orber_ifr_typecode:content_type(Objref).
-%%'TypeCode_param_count'(Objref) ->
-%% orber_ifr_typecode:param_count(Objref).
-%%'TypeCode_parameter'(Objref,Index) ->
-%% orber_ifr_typecode:parameter(Objref,Index).
-
-'ORB_create_struct_tc'(Id,Name,Members) ->
- orber_ifr_orb:create_struct_tc(Id,Name,Members).
-'ORB_create_union_tc'(Id,Name,Discriminator_type,Members) ->
- orber_ifr_orb:create_union_tc(Id,Name,Discriminator_type,Members).
-'ORB_create_enum_tc'(Id,Name,Members) ->
- orber_ifr_orb:create_enum_tc(Id,Name,Members).
-'ORB_create_alias_tc'(Id,Name,Original_type) ->
- orber_ifr_orb:create_alias_tc(Id,Name,Original_type).
-'ORB_create_exception_tc'(Id,Name,Members) ->
- orber_ifr_orb:create_exception_tc(Id,Name,Members).
-'ORB_create_interface_tc'(Id,Name) ->
- orber_ifr_orb:create_interface_tc(Id,Name).
-'ORB_create_string_tc'(Bound) ->
- orber_ifr_orb:create_string_tc(Bound).
-'ORB_create_wstring_tc'(Bound) ->
- orber_ifr_orb:create_wstring_tc(Bound).
-'ORB_create_sequence_tc'(Bound,Element_type) ->
- orber_ifr_orb:create_sequence_tc(Bound,Element_type).
--spec 'ORB_create_recursive_sequence_tc'(_,_) -> no_return().
-'ORB_create_recursive_sequence_tc'(Bound,Offset) ->
- orber_ifr_orb:create_recursive_sequence_tc(Bound,Offset).
-'ORB_create_array_tc'(Length,Element_type) ->
- orber_ifr_orb:create_array_tc(Length,Element_type).
-
-%%%---------------------------------------------------------------
-%%% "Methods" of the IFR "objects"
-
-get_def_kind(Objref) ->
- Mod = obj2mod(Objref),
- Mod:'_get_def_kind'(Objref).
-
-%% Light IFR Operations
-destroy(#orber_light_ifr_ref{data = #lightdata{id = Id}}) ->
- F = fun() ->
- MatchHead = #orber_light_ifr{id = '$1', base_id = Id, _='_'},
- Result = '$1',
- IdList = mnesia:select(orber_light_ifr,
- [{MatchHead, [], [Result]}],
- write),
- lists:foreach(fun(RefId) ->
- mnesia:delete({orber_light_ifr, RefId})
- end, IdList)
- end,
- case mnesia:transaction(F) of
- {aborted, _} ->
- exit({"FAILED TO DELETE:", Id});
- {atomic, _} ->
- ok
- end;
-destroy(Objref) ->
- %% Destroying an ir_IRObject, ir_Contained or ir_Container directly
- %% is not allowed
- Mod = obj2mod(Objref),
- Mod:destroy(Objref).
-
-%%%---------------------------------------------------------------
-%%%
-
-get_id(Objref) ->
- Mod = obj2mod(Objref),
- Mod:'_get_id'(Objref).
-
-set_id(Objref,Id) ->
- Mod = obj2mod(Objref),
- Mod:'_set_id'(Objref,Id).
-
-get_name(Objref) ->
- Mod = obj2mod(Objref),
- Mod:'_get_name'(Objref).
-
-set_name(Objref,Name) ->
- Mod = obj2mod(Objref),
- Mod:'_set_name'(Objref,Name).
-
-get_version(Objref) ->
- Mod = obj2mod(Objref),
- Mod:'_get_version'(Objref).
-
-set_version(Objref,Version) ->
- Mod = obj2mod(Objref),
- Mod:'_set_version'(Objref,Version).
-
-get_defined_in(Objref) ->
- Mod = obj2mod(Objref),
- Mod:'_get_defined_in'(Objref).
-
-get_absolute_name(Objref) ->
- Mod = obj2mod(Objref),
- Mod: '_get_absolute_name'(Objref).
-
-get_containing_repository(Objref) ->
- Mod = obj2mod(Objref),
- Mod:'_get_containing_repository'(Objref).
-
-describe(Objref) ->
- Mod = obj2mod(Objref),
- Mod:describe(Objref).
-
-move(Objref,New_container,New_name,New_version) ->
- Mod = obj2mod(Objref),
- Mod:move(Objref,New_container,New_name,New_version).
-
-%%%---------------------------------------------------------------
-%%%
-
-lookup(Objref,Search_name) ->
- Mod = obj2mod(Objref),
- Mod:lookup(Objref,Search_name).
-
-%% Light IFR Operation
-contents(#orber_light_ifr_ref{data = #lightdata{id = _Id}},
- _Limit_type, _Exclude_inherited) ->
- [];
-contents(Objref,Limit_type,Exclude_inherited) ->
- Mod = obj2mod(Objref),
- Mod:contents(Objref,Limit_type,Exclude_inherited).
-
-lookup_name(Objref,Search_name,Levels_to_search,Limit_type,Exclude_inherited) ->
- Mod = obj2mod(Objref),
- Mod:lookup_name(Objref,Search_name,Levels_to_search,Limit_type,Exclude_inherited).
-
-
-describe_contents(Objref,Limit_type,Exclude_inherited,Max_returned_objs) ->
- Mod = obj2mod(Objref),
- Mod:describe_contents(Objref,Limit_type,Exclude_inherited,Max_returned_objs).
-
-create_module(Objref,Id,Name,Version) ->
- Mod = obj2mod(Objref),
- Mod:create_module(Objref,Id,Name,Version).
-
-create_constant(Objref,Id,Name,Version,Type,Value) ->
- Mod = obj2mod(Objref),
- Mod:create_constant(Objref,Id,Name,Version,Type,Value).
-
-create_struct(Objref,Id,Name,Version,Members) ->
- Mod = obj2mod(Objref),
- Mod:create_struct(Objref,Id,Name,Version,Members).
-
-create_union(Objref,Id,Name,Version,Discriminator_type,Members) ->
- Mod = obj2mod(Objref),
- Mod:create_union(Objref,Id,Name,Version,Discriminator_type,Members).
-
-create_enum(Objref,Id,Name,Version,Members) ->
- Mod = obj2mod(Objref),
- Mod:create_enum(Objref,Id,Name,Version,Members).
-
-create_alias(Objref,Id,Name,Version,Original_type) ->
- Mod = obj2mod(Objref),
- Mod:create_alias(Objref,Id,Name,Version,Original_type).
-
-create_interface(Objref,Id,Name,Version,Base_interfaces) ->
- Mod = obj2mod(Objref),
- Mod:create_interface(Objref,Id,Name,Version,Base_interfaces).
-
-create_exception(Objref,Id,Name,Version,Members) ->
- Mod = obj2mod(Objref),
- Mod:create_exception(Objref,Id,Name,Version,Members).
-
-%%%---------------------------------------------------------------
-%%%
-
-get_type(Objref) ->
- Mod = obj2mod(Objref),
- Mod:'_get_type'(Objref).
-
-%%%---------------------------------------------------------------
-%%%
-
-%% This list should contain the data in most-likely-to-be-accessed-order.
--define(INDEXED_TABLE_LIST, [{ir_ExceptionDef, #ir_ExceptionDef.id},
- {ir_InterfaceDef, #ir_InterfaceDef.id},
- {ir_ModuleDef, #ir_ModuleDef.id},
- {ir_StructDef, #ir_StructDef.id},
- {ir_UnionDef, #ir_UnionDef.id},
- {ir_AliasDef, #ir_AliasDef.id},
- {ir_TypedefDef, #ir_TypedefDef.id},
- {ir_ConstantDef, #ir_ConstantDef.id},
- {ir_EnumDef, #ir_EnumDef.id},
- {ir_AttributeDef, #ir_AttributeDef.id},
- {ir_Contained, #ir_Contained.id},
- {ir_OperationDef, #ir_OperationDef.id}]).
-
-
-lookup_id(#orber_light_ifr_ref{}, Id) ->
- case mnesia:dirty_read(orber_light_ifr, Id) of
- [] ->
- [];
- [#orber_light_ifr{module = Mod}] ->
- #orber_light_ifr_ref{data = #lightdata{scope = atom_to_list(Mod),
- id = Id}}
- end;
-lookup_id(_Objref,Id) ->
- %% We used the operation below before but it's very expensive.
- %% orber_ifr_repository:lookup_id(Objref,Id)
- lookup_id_helper(?INDEXED_TABLE_LIST, Id).
-
-lookup_id_helper([], _) ->
- [];
-lookup_id_helper([{Tab, IdNum}|T], Id) ->
- case mnesia:dirty_index_read(Tab, Id, IdNum) of
- [] ->
- lookup_id_helper(T, Id);
- [FoundIt] ->
- {Tab, element(2, FoundIt)}
- end.
-
-get_primitive(Objref,Kind) ->
- orber_ifr_repository:get_primitive(Objref,Kind).
-
-create_string(Objref,Bound) ->
- orber_ifr_repository:create_string(Objref,Bound).
-
-create_wstring(Objref,Bound) ->
- orber_ifr_repository:create_wstring(Objref,Bound).
-
-create_sequence(Objref,Bound,Element_type) ->
- orber_ifr_repository:create_sequence(Objref,Bound,Element_type).
-
-create_array(Objref,Length,Element_type) ->
- orber_ifr_repository:create_array(Objref,Length,Element_type).
-
-create_idltype(Objref,Typecode) -> %not in CORBA 2.0
- orber_ifr_repository:create_idltype(Objref,Typecode).
-
-create_fixed(Objref, Digits, Scale) ->
- orber_ifr_repository:create_fixed(Objref, Digits, Scale).
-
-%%%---------------------------------------------------------------
-%%%
-
-get_type_def(Objref) ->
- Mod = obj2mod(Objref),
- Mod:'_get_type_def'(Objref).
-
-set_type_def(Objref,TypeDef) ->
- Mod = obj2mod(Objref),
- Mod:'_set_type_def'(Objref,TypeDef).
-
-get_value(Objref) ->
- orber_ifr_constantdef:'_get_value'(Objref).
-
-set_value(Objref,Value) ->
- orber_ifr_constantdef: '_set_value'(Objref,Value).
-
-%%%---------------------------------------------------------------
-%%%
-
-get_members(Objref) ->
- Mod = obj2mod(Objref),
- Mod:'_get_members'(Objref).
-
-set_members(Objref,Members) ->
- Mod = obj2mod(Objref),
- Mod:'_set_members'(Objref,Members).
-
-%%%---------------------------------------------------------------
-%%%
-
-get_discriminator_type(Objref) ->
- orber_ifr_uniondef:'_get_discriminator_type'(Objref).
-
-get_discriminator_type_def(Objref) ->
- orber_ifr_uniondef:'_get_discriminator_type_def'(Objref).
-
-set_discriminator_type_def(Objref,TypeDef) ->
- orber_ifr_uniondef:'_set_discriminator_type_def'(Objref,TypeDef).
-
-%%%---------------------------------------------------------------
-%%%
-
-get_original_type_def(Objref) ->
- orber_ifr_aliasdef:'_get_original_type_def'(Objref).
-
-set_original_type_def(Objref,TypeDef) ->
- orber_ifr_aliasdef:'_set_original_type_def'(Objref,TypeDef).
-
-%%%---------------------------------------------------------------
-%%%
-
-get_kind(Objref) ->
- orber_ifr_primitivedef:'_get_kind'(Objref).
-
-%%%---------------------------------------------------------------
-%%%
-
-get_bound(Objref) ->
- Mod = obj2mod(Objref),
- Mod:'_get_bound'(Objref).
-
-set_bound(Objref,Bound) ->
- Mod = obj2mod(Objref),
- Mod:'_set_bound'(Objref,Bound).
-
-%%%---------------------------------------------------------------
-%%%
-
-get_element_type(Objref) ->
- Mod = obj2mod(Objref),
- Mod:'_get_element_type'(Objref).
-
-get_element_type_def(Objref) ->
- Mod = obj2mod(Objref),
- Mod:'_get_element_type_def'(Objref).
-
-set_element_type_def(Objref,TypeDef) ->
- Mod = obj2mod(Objref),
- Mod:'_set_element_type_def'(Objref,TypeDef).
-
-%%%---------------------------------------------------------------
-%%%
-
-get_length(Objref) ->
- orber_ifr_arraydef:'_get_length'(Objref).
-
-set_length(Objref,Length) ->
- orber_ifr_arraydef:'_set_length'(Objref,Length).
-
-%%%---------------------------------------------------------------
-%%%
-
-get_mode(Objref) ->
- Mod = obj2mod(Objref),
- Mod:'_get_mode'(Objref).
-
-set_mode(Objref,Mode) ->
- Mod = obj2mod(Objref),
- Mod:'_set_mode'(Objref,Mode).
-
-%%%---------------------------------------------------------------
-%%%
-
-get_result(Objref) ->
- orber_ifr_operationdef:'_get_result'(Objref).
-
-get_result_def(Objref) ->
- orber_ifr_operationdef:'_get_result_def'(Objref).
-
-set_result_def(Objref,ResultDef) ->
- orber_ifr_operationdef:'_set_result_def'(Objref,ResultDef).
-
-get_params(Objref) ->
- orber_ifr_operationdef:'_get_params'(Objref).
-
-set_params(Objref,Params) ->
- orber_ifr_operationdef:'_set_params'(Objref,Params).
-
-get_contexts(Objref) ->
- orber_ifr_operationdef:'_get_contexts'(Objref).
-
-set_contexts(Objref,Contexts) ->
- orber_ifr_operationdef:'_set_contexts'(Objref,Contexts).
-
-get_exceptions(Objref) ->
- orber_ifr_operationdef:'_get_exceptions'(Objref).
-
-set_exceptions(Objref,Exceptions) ->
- orber_ifr_operationdef:'_set_exceptions'(Objref,Exceptions).
-
-%%%---------------------------------------------------------------
-%%%
-
-get_base_interfaces(Objref) ->
- orber_ifr_interfacedef:'_get_base_interfaces'(Objref).
-
-set_base_interfaces(Objref,BaseInterfaces) ->
- orber_ifr_interfacedef:'_set_base_interfaces'(Objref,BaseInterfaces).
-
-is_a(Objref,Interface_id) ->
- orber_ifr_interfacedef:is_a(Objref,Interface_id).
-
-describe_interface(Objref) ->
- orber_ifr_interfacedef:describe_interface(Objref).
-
-create_attribute(Objref,Id,Name,Version,Type,Mode) ->
- orber_ifr_interfacedef:create_attribute(Objref,Id,Name,Version,Type,Mode).
-
-create_operation(Objref,Id,Name,Version,Result,Mode,Params,Exceptions,Contexts) ->
- orber_ifr_interfacedef:create_operation(Objref,Id,Name,Version,Result,Mode,
- Params,Exceptions,Contexts).
-
-obj2mod({ir_IRObject, _}) ->
- orber_ifr_irobject;
-obj2mod({ir_Contained, _}) ->
- orber_ifr_contained;
-obj2mod({ir_Container, _}) ->
- orber_ifr_container;
-obj2mod({ir_IDLType, _}) ->
- orber_ifr_idltype;
-obj2mod({ir_Repository, _}) ->
- orber_ifr_repository;
-obj2mod({ir_ModuleDef, _}) ->
- orber_ifr_moduledef;
-obj2mod({ir_ConstantDef, _}) ->
- orber_ifr_constantdef;
-obj2mod({ir_TypedefDef, _}) ->
- orber_ifr_typedef;
-obj2mod({ir_StructDef, _}) ->
- orber_ifr_structdef;
-obj2mod({ir_UnionDef, _}) ->
- orber_ifr_uniondef;
-obj2mod({ir_EnumDef, _}) ->
- orber_ifr_enumdef;
-obj2mod({ir_AliasDef, _}) ->
- orber_ifr_aliasdef;
-obj2mod({ir_PrimitiveDef, _}) ->
- orber_ifr_primitivedef;
-obj2mod({ir_StringDef, _}) ->
- orber_ifr_stringdef;
-obj2mod({ir_WstringDef, _}) ->
- orber_ifr_wstringdef;
-obj2mod({ir_SequenceDef, _}) ->
- orber_ifr_sequencedef;
-obj2mod({ir_ArrayDef, _}) ->
- orber_ifr_arraydef;
-obj2mod({ir_ExceptionDef, _}) ->
- orber_ifr_exceptiondef;
-obj2mod({ir_AttributeDef, _}) ->
- orber_ifr_attributedef;
-obj2mod({ir_OperationDef, _}) ->
- orber_ifr_operationdef;
-obj2mod({ir_InterfaceDef, _}) ->
- orber_ifr_interfacedef;
-obj2mod({ir_FixedDef, _}) ->
- orber_ifr_fidxeddef;
-obj2mod(Obj) ->
- orber:dbg("[~p] orber_ifr:obj2mod(~p); unknown.",
- [?LINE, Obj], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO}).
-
-
diff --git a/lib/orber/src/orber_ifr.hrl b/lib/orber/src/orber_ifr.hrl
deleted file mode 100644
index 10634f58c0..0000000000
--- a/lib/orber/src/orber_ifr.hrl
+++ /dev/null
@@ -1,35 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr.hrl
-%% Purpose : Macros for the Interface Repository
-%%----------------------------------------------------------------------
-
-
--record(lightdata, {scope, id}).
--record(orber_light_ifr_ref, {data}).
-
-%% "Type" checking
--define(tcheck(Type, Thing), when Type == Thing ; Thing == orber_light_ifr_ref).
-
--define(DEBUG_LEVEL, 9).
-
diff --git a/lib/orber/src/orber_ifr_aliasdef.erl b/lib/orber/src/orber_ifr_aliasdef.erl
deleted file mode 100644
index 04a92be5e3..0000000000
--- a/lib/orber/src/orber_ifr_aliasdef.erl
+++ /dev/null
@@ -1,135 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_aliasdef.erl
-%% Purpose : Code for Aliasdef
-%%----------------------------------------------------------------------
-
--module(orber_ifr_aliasdef).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- '_get_id'/1,
- '_set_id'/2,
- '_get_name'/1,
- '_set_name'/2,
- '_get_version'/1,
- '_set_version'/2,
- '_get_defined_in'/1,
- '_get_absolute_name'/1,
- '_get_containing_repository'/1,
- describe/1,
- move/4,
- '_get_type'/1,
- '_get_original_type_def'/1,
- '_set_original_type_def'/2
- ]).
-
--import(orber_ifr_utils,[get_field/2,
- get_object/1,
- set_object/1
- ]).
-
--include("orber_ifr.hrl").
--include("ifr_objects.hrl").
-
-%%%======================================================================
-%%% AliasDef (TypedefDef(Contained(IRObject), IDLType(IRObject)))
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType, ObjID}) ?tcheck(ir_AliasDef, ObjType) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType,ObjID}).
-
-destroy({ObjType, ObjID}) ?tcheck(ir_AliasDef, ObjType) ->
- F = fun() -> ObjList = cleanup_for_destroy({ObjType, ObjID}),
- orber_ifr_irobject:destroy([{ObjType,ObjID} | ObjList])
- end,
- orber_ifr_utils:ifr_transaction_write(F).
-
-cleanup_for_destroy({ObjType,ObjID}) ?tcheck(ir_AliasDef, ObjType) ->
- orber_ifr_idltype:cleanup_for_destroy(
- '_get_original_type_def'({ObjType,ObjID})) ++
- orber_ifr_typedef:cleanup_for_destroy({ObjType,ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from Contained
-
-'_get_id'({ObjType, ObjID}) ?tcheck(ir_AliasDef, ObjType) ->
- orber_ifr_contained:'_get_id'({ObjType,ObjID}).
-
-'_set_id'({ObjType, ObjID}, EO_Value) ?tcheck(ir_AliasDef, ObjType) ->
- orber_ifr_contained:'_set_id'({ObjType,ObjID},EO_Value).
-
-'_get_name'({ObjType, ObjID}) ?tcheck(ir_AliasDef, ObjType) ->
- orber_ifr_contained:'_get_name'({ObjType,ObjID}).
-
-'_set_name'({ObjType, ObjID}, EO_Value) ?tcheck(ir_AliasDef, ObjType) ->
- orber_ifr_contained:'_set_name'({ObjType,ObjID}, EO_Value).
-
-'_get_version'({ObjType, ObjID}) ?tcheck(ir_AliasDef, ObjType) ->
- orber_ifr_contained:'_get_version'({ObjType,ObjID}).
-
-'_set_version'({ObjType, ObjID}, EO_Value) ?tcheck(ir_AliasDef, ObjType) ->
- orber_ifr_contained:'_set_version'({ObjType,ObjID},EO_Value).
-
-'_get_defined_in'({ObjType, ObjID}) ?tcheck(ir_AliasDef, ObjType) ->
- orber_ifr_contained:'_get_defined_in'({ObjType,ObjID}).
-
-'_get_absolute_name'({ObjType, ObjID}) ?tcheck(ir_AliasDef,ObjType) ->
- orber_ifr_contained:'_get_absolute_name'({ObjType,ObjID}).
-
-'_get_containing_repository'({ObjType, ObjID}) ?tcheck(ir_AliasDef, ObjType) ->
- orber_ifr_contained:'_get_containing_repository'({ObjType,ObjID}).
-
-describe({ObjType, ObjID}) ?tcheck(ir_AliasDef, ObjType) ->
- orber_ifr_contained:describe({ObjType,ObjID}).
-
-move({ObjType, ObjID}, New_container, New_name, New_version)
- ?tcheck(ir_AliasDef, ObjType) ->
- orber_ifr_contained:move({ObjType,ObjID},New_container,New_name,
- New_version).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IDLType
-
-'_get_type'({ObjType, ObjID}) ?tcheck(ir_AliasDef, ObjType) ->
- orber_ifr_idltype:'_get_type'({ObjType, ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-'_get_original_type_def'({ObjType, ObjID})
- ?tcheck(ir_AliasDef, ObjType) ->
- get_field({ObjType,ObjID},original_type_def).
-
-'_set_original_type_def'({ObjType, ObjID}, EO_Value)
- ?tcheck(ir_AliasDef, ObjType) ->
- AliasDef = get_object({ObjType, ObjID}),
- New_AliasDef = AliasDef#ir_AliasDef{type = {tk_alias,
- AliasDef#ir_AliasDef.id,
- AliasDef#ir_AliasDef.name,
- EO_Value#ir_IDLType.type},
- original_type_def = EO_Value},
- set_object(New_AliasDef).
diff --git a/lib/orber/src/orber_ifr_arraydef.erl b/lib/orber/src/orber_ifr_arraydef.erl
deleted file mode 100644
index 1513914a08..0000000000
--- a/lib/orber/src/orber_ifr_arraydef.erl
+++ /dev/null
@@ -1,104 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_arraydef.erl
-%% Purpose : Code for Arraydef
-%%----------------------------------------------------------------------
-
--module(orber_ifr_arraydef).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- '_get_type'/1,
- '_get_length'/1,
- '_set_length'/2,
- '_get_element_type'/1,
- '_get_element_type_def'/1,
- '_set_element_type_def'/2
- ]).
-
--import(orber_ifr_utils,[get_field/2,
- get_object/1,
- set_object/1
- ]).
-
--include("orber_ifr.hrl").
--include("ifr_objects.hrl").
-
-%%%======================================================================
-%%% ArrayDef (IDLType(IRObject))
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType, ObjID}) ?tcheck(ir_ArrayDef, ObjType) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType,ObjID}).
-
-destroy({ObjType, ObjID}) ?tcheck(ir_ArrayDef, ObjType) ->
- F = fun() -> ObjList = cleanup_for_destroy({ObjType, ObjID}),
- orber_ifr_irobject:destroy([{ObjType,ObjID} | ObjList])
- end,
- orber_ifr_utils:ifr_transaction_write(F).
-
-cleanup_for_destroy({ObjType,ObjID}) ?tcheck(ir_ArrayDef, ObjType) ->
- orber_ifr_idltype:cleanup_for_destroy(
- '_get_element_type_def'({ObjType,ObjID})) ++
- orber_ifr_idltype:cleanup_for_destroy({ObjType,ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IDLType
-
-'_get_type'({ObjType, ObjID}) ?tcheck(ir_ArrayDef, ObjType) ->
- orber_ifr_idltype:'_get_type'({ObjType, ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-'_get_length'({ObjType, ObjID}) ?tcheck(ir_ArrayDef, ObjType) ->
- get_field({ObjType,ObjID},length).
-
-'_set_length'({ObjType, ObjID}, EO_Value) ?tcheck(ir_ArrayDef, ObjType) ->
- ArrayDef = get_object({ObjType, ObjID}),
- New_ArrayDef =
- ArrayDef#ir_ArrayDef{type = {tk_array,
- ArrayDef#ir_ArrayDef.type,
- ArrayDef#ir_ArrayDef.length},
- length = EO_Value},
- set_object(New_ArrayDef).
-
-'_get_element_type'({ObjType, ObjID}) ?tcheck(ir_ArrayDef, ObjType) ->
- get_field({ObjType,ObjID},element_type).
-
-'_get_element_type_def'({ObjType, ObjID}) ?tcheck(ir_ArrayDef, ObjType) ->
- get_field({ObjType,ObjID},element_type_def).
-
-'_set_element_type_def'({ObjType, ObjID}, EO_Value)
- ?tcheck(ir_ArrayDef, ObjType) ->
- ArrayDef = get_object({ObjType, ObjID}),
- New_type = {tk_array,
- EO_Value#ir_IDLType.type,
- ArrayDef#ir_ArrayDef.length},
- New_ArrayDef = ArrayDef#ir_ArrayDef{type = New_type,
- element_type = New_type,
- element_type_def = EO_Value},
- set_object(New_ArrayDef).
diff --git a/lib/orber/src/orber_ifr_attributedef.erl b/lib/orber/src/orber_ifr_attributedef.erl
deleted file mode 100644
index bf7d1d2b63..0000000000
--- a/lib/orber/src/orber_ifr_attributedef.erl
+++ /dev/null
@@ -1,138 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_attributedef.erl
-%% Purpose : Code for Attributedef
-%%----------------------------------------------------------------------
-
--module(orber_ifr_attributedef).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- '_get_id'/1,
- '_set_id'/2,
- '_get_name'/1,
- '_set_name'/2,
- '_get_version'/1,
- '_set_version'/2,
- '_get_defined_in'/1,
- '_get_absolute_name'/1,
- '_get_containing_repository'/1,
- describe/1,
- move/4,
- '_get_type'/1,
- '_get_type_def'/1,
- '_set_type_def'/2,
- '_get_mode'/1,
- '_set_mode'/2
- ]).
-
--import(orber_ifr_utils,[get_field/2,
- set_field/3,
- get_object/1,
- set_object/1
- ]).
-
--include("orber_ifr.hrl").
--include("ifr_objects.hrl").
-
-%%%----------------------------------------------------------------------
-%% AttributeDef (Contained(IRObject))
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType, ObjID}) ?tcheck(ir_AttributeDef, ObjType) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType,ObjID}).
-
-destroy({ObjType, ObjID}) ?tcheck(ir_AttributeDef, ObjType) ->
- F = fun() -> ObjList = cleanup_for_destroy({ObjType, ObjID}),
- orber_ifr_irobject:destroy([{ObjType,ObjID} | ObjList])
- end,
- orber_ifr_utils:ifr_transaction_write(F).
-
-cleanup_for_destroy({ObjType,ObjID}) ?tcheck(ir_AttributeDef, ObjType) ->
- orber_ifr_idltype:cleanup_for_destroy(
- orber_ifr_idltype:'_get_type_def'({ObjType,ObjID})) ++
- orber_ifr_contained:cleanup_for_destroy({ObjType,ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from Contained
-
-'_get_id'({ObjType, ObjID}) ?tcheck(ir_AttributeDef, ObjType) ->
- orber_ifr_contained:'_get_id'({ObjType,ObjID}).
-
-'_set_id'({ObjType, ObjID}, EO_Value) ?tcheck(ir_AttributeDef, ObjType) ->
- orber_ifr_contained:'_set_id'({ObjType,ObjID},EO_Value).
-
-'_get_name'({ObjType, ObjID}) ?tcheck(ir_AttributeDef, ObjType) ->
- orber_ifr_contained:'_get_name'({ObjType,ObjID}).
-
-'_set_name'({ObjType, ObjID}, EO_Value) ?tcheck(ir_AttributeDef, ObjType) ->
- orber_ifr_contained:'_set_name'({ObjType,ObjID}, EO_Value).
-
-'_get_version'({ObjType, ObjID}) ?tcheck(ir_AttributeDef, ObjType) ->
- orber_ifr_contained:'_get_version'({ObjType,ObjID}).
-
-'_set_version'({ObjType, ObjID}, EO_Value) ?tcheck(ir_AttributeDef, ObjType) ->
- orber_ifr_contained:'_set_version'({ObjType,ObjID},EO_Value).
-
-'_get_defined_in'({ObjType, ObjID}) ?tcheck(ir_AttributeDef, ObjType) ->
- orber_ifr_contained:'_get_defined_in'({ObjType,ObjID}).
-
-'_get_absolute_name'({ObjType, ObjID}) ?tcheck(ir_AttributeDef, ObjType) ->
- orber_ifr_contained:'_get_absolute_name'({ObjType,ObjID}).
-
-'_get_containing_repository'({ObjType, ObjID})
- ?tcheck(ir_AttributeDef, ObjType) ->
- orber_ifr_contained:'_get_containing_repository'({ObjType,ObjID}).
-
-describe({ObjType, ObjID}) ?tcheck(ir_AttributeDef, ObjType) ->
- orber_ifr_contained:describe({ObjType,ObjID}).
-
-move({ObjType, ObjID}, New_container, New_name, New_version)
- ?tcheck(ir_AttributeDef, ObjType) ->
- orber_ifr_contained:move({ObjType,ObjID},New_container,New_name,
- New_version).
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-'_get_type'({ObjType, ObjID}) ?tcheck(ir_AttributeDef, ObjType) ->
- get_field({ObjType,ObjID},type).
-
-'_get_type_def'({ObjType, ObjID}) ?tcheck(ir_AttributeDef, ObjType) ->
- get_field({ObjType,ObjID},type_def).
-
-'_set_type_def'({ObjType, ObjID},EO_Value) ?tcheck(ir_AttributeDef, ObjType) ->
- AttributeDef = get_object({ObjType, ObjID}),
- New_AttributeDef =
- AttributeDef#ir_AttributeDef{type = EO_Value#ir_IDLType.type,
- type_def = EO_Value},
- set_object(New_AttributeDef).
-
-'_get_mode'({ObjType, ObjID}) ?tcheck(ir_AttributeDef, ObjType) ->
- get_field({ObjType,ObjID},mode).
-
-'_set_mode'({ObjType, ObjID}, EO_Value) ?tcheck(ir_AttributeDef, ObjType) ->
- set_field({ObjType,ObjID}, mode, EO_Value).
diff --git a/lib/orber/src/orber_ifr_constantdef.erl b/lib/orber/src/orber_ifr_constantdef.erl
deleted file mode 100644
index b9d4393177..0000000000
--- a/lib/orber/src/orber_ifr_constantdef.erl
+++ /dev/null
@@ -1,148 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_constantdef.erl
-%% Purpose : Code for Constantdef
-%%----------------------------------------------------------------------
-
--module(orber_ifr_constantdef).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- '_get_id'/1,
- '_set_id'/2,
- '_get_name'/1,
- '_set_name'/2,
- '_get_version'/1,
- '_set_version'/2,
- '_get_defined_in'/1,
- '_get_absolute_name'/1,
- '_get_containing_repository'/1,
- describe/1,
- move/4,
- '_get_type'/1,
- '_get_type_def'/1,
- '_set_type_def'/2,
- '_get_value'/1,
- '_set_value'/2
- ]).
-
--import(orber_ifr_utils,[get_field/2,
- set_field/3,
- get_object/1,
- set_object/1
- ]).
-
--include_lib("orber/include/corba.hrl").
--include("orber_ifr.hrl").
--include("ifr_objects.hrl").
-
-%%%======================================================================
-%%% ConstantDef (Contained(IRObject))
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType,ObjID}) ?tcheck(ir_ConstantDef,ObjType) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType, ObjID}).
-
-destroy({ObjType, ObjID}) ?tcheck(ir_ConstantDef, ObjType) ->
- F = fun() -> ObjList = cleanup_for_destroy({ObjType,ObjID}),
- orber_ifr_irobject:destroy([{ObjType,ObjID} | ObjList])
- end,
- orber_ifr_utils:ifr_transaction_write(F).
-
-cleanup_for_destroy({ObjType,ObjID}) ?tcheck(ir_ConstantDef, ObjType) ->
- orber_ifr_idltype:cleanup_for_destroy(
- '_get_type_def'({ObjType,ObjID})) ++
- orber_ifr_contained:cleanup_for_destroy({ObjType,ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from Contained
-
-'_get_id'({ObjType, ObjID}) ?tcheck(ir_ConstantDef, ObjType) ->
- orber_ifr_contained:'_get_id'({ObjType,ObjID}).
-
-'_set_id'({ObjType, ObjID}, EO_Value) ?tcheck(ir_ConstantDef, ObjType) ->
- orber_ifr_contained:'_set_id'({ObjType,ObjID},EO_Value).
-
-'_get_name'({ObjType, ObjID}) ?tcheck(ir_ConstantDef, ObjType) ->
- orber_ifr_contained:'_get_name'({ObjType,ObjID}).
-
-'_set_name'({ObjType, ObjID}, EO_Value) ?tcheck(ir_ConstantDef, ObjType) ->
- orber_ifr_contained:'_set_name'({ObjType,ObjID}, EO_Value).
-
-'_get_version'({ObjType, ObjID}) ?tcheck(ir_ConstantDef,ObjType) ->
- orber_ifr_contained:'_get_version'({ObjType,ObjID}).
-
-'_set_version'({ObjType, ObjID}, EO_Value) ?tcheck(ir_ConstantDef, ObjType) ->
- orber_ifr_contained:'_set_version'({ObjType,ObjID},EO_Value).
-
-'_get_defined_in'({ObjType, ObjID}) ?tcheck(ir_ConstantDef, ObjType) ->
- orber_ifr_contained:'_get_defined_in'({ObjType,ObjID}).
-
-'_get_absolute_name'({ObjType, ObjID}) ?tcheck(ir_ConstantDef, ObjType) ->
- orber_ifr_contained:'_get_absolute_name'({ObjType,ObjID}).
-
-'_get_containing_repository'({ObjType, ObjID})
- ?tcheck(ir_ConstantDef, ObjType) ->
- orber_ifr_contained:'_get_containing_repository'({ObjType,ObjID}).
-
-describe({ObjType, ObjID}) ?tcheck(ir_ConstantDef, ObjType) ->
- orber_ifr_contained:describe({ObjType,ObjID}).
- %
-move({ObjType, ObjID}, New_container, New_name, New_version)
- ?tcheck(ir_ConstantDef, ObjType) ->
- orber_ifr_contained:move({ObjType,ObjID},New_container,New_name,
- New_version).
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-'_get_type'({ObjType, ObjID}) ?tcheck(ir_ConstantDef, ObjType) ->
- get_field({ObjType,ObjID},type).
-
-'_get_type_def'({ObjType,ObjID}) ?tcheck(ir_ConstantDef,ObjType) ->
- get_field({ObjType,ObjID},type_def).
-
-'_set_type_def'({ObjType, ObjID}, EO_Value) ?tcheck(ir_ConstantDef, ObjType) ->
- ConstantDef = get_object({ObjType, ObjID}),
- New_ConstantDef = ConstantDef#ir_ConstantDef{type=EO_Value#ir_IDLType.type,
- type_def = EO_Value},
- set_object(New_ConstantDef).
-
-'_get_value'({ObjType, ObjID}) ?tcheck(ir_ConstantDef, ObjType) ->
- get_field({ObjType,ObjID},value).
-
-'_set_value'({ObjType, ObjID}, EO_Value) ?tcheck(ir_ConstantDef, ObjType) ->
- Typecode = get_field({ObjType,ObjID},type),
- {Value_typecode, _} = EO_Value,
- case Value_typecode == Typecode of
- true ->
- set_field({ObjType, ObjID}, value, EO_Value);
- false ->
- orber:dbg("[~p] ~p:destroy(~p, ~p, ~p);~n"
- "Wrong typecode in set_value.~n",
- [?LINE, ?MODULE, ObjType, ObjID, EO_Value], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO})
- end.
diff --git a/lib/orber/src/orber_ifr_contained.erl b/lib/orber/src/orber_ifr_contained.erl
deleted file mode 100644
index 2a67fa98fd..0000000000
--- a/lib/orber/src/orber_ifr_contained.erl
+++ /dev/null
@@ -1,248 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_contained.erl
-%% Purpose : Code for Contained
-%%----------------------------------------------------------------------
-
--module(orber_ifr_contained).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- '_get_id'/1,
- '_set_id'/2,
- '_get_name'/1,
- '_set_name'/2,
- '_get_version'/1,
- '_set_version'/2,
- '_get_defined_in'/1,
- '_get_absolute_name'/1,
- '_get_containing_repository'/1,
- describe/1,
- describe/2, %not in CORBA 2.0
- move/4
- ]).
-
--import(orber_ifr_utils,[get_object/1,
- get_field/2,
- set_field/3,
- construct/3,
- select/2,
- write_result/1,
- ifr_transaction_read_write/1
- ]).
-
--include("orber_ifr.hrl").
--include("ifr_objects.hrl").
--include_lib("orber/include/ifr_types.hrl").
--include_lib("orber/include/corba.hrl").
-
-%%%======================================================================
-%%% Contained (IRObject)
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType,ObjID}) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType,ObjID}).
-
-%%% Note, that the destroy function is meant to be called within a
-%%% transaction called in the destroy function of an object which
-%%% inherits from Contained. A Contained should only be destroyed by
-%%% destroying the object that inherits from a Contained. An attempt
-%%% to call this function in user code will result in unpredictable
-%%% results.
-
-%%% Don't type check the object reference. We need to be able to
-%%% handle several types of objects that inherit from Contained.
-
-destroy(Contained_objref) ->
- ObjList = cleanup_for_destroy(Contained_objref),
- orber_ifr_irobject:destroy([Contained_objref | ObjList]).
-
-cleanup_for_destroy(Contained_objref) ->
- Defined_in = '_get_defined_in'(Contained_objref),
- [Container_obj] = mnesia:read(Defined_in),
- New_container_obj =
- construct(Container_obj,contents,
- lists:filter(fun(X) -> X /= Contained_objref end,
- select(Container_obj,contents))),
- [fun() -> mnesia:write(New_container_obj) end].
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-'_get_id'({ObjType,ObjID}) ->
- get_field({ObjType,ObjID},id).
-
-'_set_id'({ObjType,ObjID}, EO_Value) ->
- set_field({ObjType, ObjID}, id, EO_Value).
-
-'_get_name'({ObjType,ObjID}) ->
- get_field({ObjType,ObjID},name).
-
-'_set_name'({ObjType,ObjID}, EO_Value) ->
- set_field({ObjType, ObjID}, name, EO_Value).
-
-'_get_version'({ObjType,ObjID}) ->
- get_field({ObjType,ObjID},version).
-
-'_set_version'({ObjType,ObjID}, EO_Value) ->
- set_field({ObjType, ObjID}, version, EO_Value).
-
-'_get_defined_in'({ObjType,ObjID}) ->
- get_field({ObjType,ObjID},defined_in).
-
-'_get_absolute_name'({ObjType,ObjID}) ->
- get_field({ObjType,ObjID},absolute_name).
-
-'_get_containing_repository'({ObjType,ObjID}) ->
- get_field({ObjType,ObjID},containing_repository).
-
-describe(ObjRef) ->
- Def_kind = '_get_def_kind'(ObjRef),
- Object = get_object(ObjRef),
- describe(Object,Def_kind).
-
-describe(Object,Def_kind) ->
- Value =
- case Def_kind of
- dk_Module ->
- #moduledescription{name = Object#ir_ModuleDef.name,
- id = Object#ir_ModuleDef.id,
- defined_in = Object#ir_ModuleDef.defined_in,
- version = Object#ir_ModuleDef.version};
- dk_Constant ->
- #constantdescription{name = Object#ir_ConstantDef.name,
- id = Object#ir_ConstantDef.id,
- defined_in =
- Object#ir_ConstantDef.defined_in,
- version = Object#ir_ConstantDef.version,
- type = Object#ir_ConstantDef.type,
- value = Object#ir_ConstantDef.value};
- dk_Typedef ->
- #typedescription{name = Object#ir_TypedefDef.name,
- id = Object#ir_TypedefDef.id,
- defined_in = Object#ir_TypedefDef.defined_in,
- version = Object#ir_TypedefDef.version,
- type = Object#ir_TypedefDef.type};
- dk_Struct ->
- ?make_typedescription(Object,ir_StructDef);
- dk_Union ->
- ?make_typedescription(Object,ir_UnionDef);
- dk_Enum ->
- ?make_typedescription(Object,ir_EnumDef);
- dk_Alias ->
- ?make_typedescription(Object,ir_AliasDef);
- dk_Exception ->
- #exceptiondescription{name = Object#ir_ExceptionDef.name,
- id = Object#ir_ExceptionDef.id,
- defined_in =
- Object#ir_ExceptionDef.defined_in,
- version = Object#ir_ExceptionDef.version,
- type = Object#ir_ExceptionDef.type};
- dk_Attribute ->
- #attributedescription{name = Object#ir_AttributeDef.name,
- id = Object#ir_AttributeDef.id,
- defined_in =
- Object#ir_AttributeDef.defined_in,
- version = Object#ir_AttributeDef.version,
- type = Object#ir_AttributeDef.type,
- mode = Object#ir_AttributeDef.mode};
- dk_Operation ->
- #operationdescription{name = Object#ir_OperationDef.name,
- id = Object#ir_OperationDef.id,
- defined_in =
- Object#ir_OperationDef.defined_in,
- version = Object#ir_OperationDef.version,
- result = Object#ir_OperationDef.result,
- mode = Object#ir_OperationDef.mode,
- contexts =
- Object#ir_OperationDef.contexts,
- parameters =
- Object#ir_OperationDef.params,
- exceptions =
- Object#ir_OperationDef.exceptions};
- dk_Interface ->
- #interfacedescription{name = Object#ir_InterfaceDef.name,
- id = Object#ir_InterfaceDef.id,
- defined_in =
- Object#ir_InterfaceDef.defined_in,
- version = Object#ir_InterfaceDef.version,
- base_interfaces =
- Object#ir_InterfaceDef.base_interfaces};
- _ ->
- undefined
- end,
- #contained_description{kind=Def_kind, value=Value}.
-
-move({ObjType,ObjID},{NewContainerType,NewContainerID},New_name,New_version) ->
- Move_OK =
- ('_get_containing_repository'({NewContainerType,NewContainerID}) ==
- '_get_containing_repository'({ObjType,ObjID}))
- and
- case NewContainerType of
- ir_Repository ->
- lists:member(ObjType,[ir_ConstantDef,ir_TypedefDef,
- ir_ExceptionDef,ir_InterfaceDef,
- ir_ModuleDef]);
- ir_ModuleDef ->
- lists:member(ObjType,[ir_ConstantDef,ir_TypedefDef,
- ir_ExceptionDef,ir_ModuleDef,
- ir_InterfaceDef]);
- ir_InterfaceDef ->
- lists:member(ObjType,[ir_ConstantDef,ir_TypedefDef,
- ir_ExceptionDef,ir_AttributeDef,
- ir_OperationDef]);
- _ ->
- false
- end
- and
- (orber_ifr_container:lookup_name({NewContainerType,NewContainerID},
- New_name, -1, % *** -1?
- dk_All, false) == []),
- move(Move_OK,{ObjType,ObjID},{NewContainerType,NewContainerID},New_name,
- New_version).
-
-move(true, Contained_objref, New_container, New_name, New_version) ->
- F = fun() -> Defined_in = '_get_defined_in'(Contained_objref),
- [Old_container_obj] = mnesia:read(Defined_in),
- New_old_container_obj =
- construct(Old_container_obj,contents,
- lists:filter(fun(X) -> X /= Contained_objref
- end, select(Old_container_obj,
- contents))),
- [New_container_obj] = mnesia:read(New_container),
- Contents = orber_ifr_container:contents(New_container, dk_All,
- true),
- New_new_container_obj =
- construct(construct(construct(New_container_obj, contents,
- [Contained_objref | Contents]),
- name,New_name),version,New_version),
- mnesia:write(New_old_container_obj),
- mnesia:write(New_new_container_obj)
- end,
- write_result(ifr_transaction_read_write(F));
-
-move(false, _Contained_objref, _New_container, _New_name, _New_version) ->
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO}).
diff --git a/lib/orber/src/orber_ifr_container.erl b/lib/orber/src/orber_ifr_container.erl
deleted file mode 100644
index e085985bc4..0000000000
--- a/lib/orber/src/orber_ifr_container.erl
+++ /dev/null
@@ -1,464 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_container.erl
-%% Purpose : Code for Container
-%%----------------------------------------------------------------------
-
--module(orber_ifr_container).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- lookup/2,
- contents/3,
- lookup_name/5,
- describe_contents/4,
- make_absolute_name/2, %not in CORBA 2.0
- make_containing_repository/1, %not in CORBA 2.0
- add_to_container/5, %not in CORBA 2.0
- create_module/4,
- create_constant/6,
- create_struct/5,
- create_union/6,
- create_enum/5,
- create_alias/5,
- create_interface/5,
- create_exception/5
- ]).
-
--import(orber_ifr_utils,[get_field/2,select/2,construct/3,makeref/1,unique/0]).
--import(lists,[map/2,filter/2,flatten/1,sublist/2]).
-
--include_lib("orber/include/corba.hrl").
--include("orber_ifr.hrl").
--include("ifr_objects.hrl").
--include_lib("orber/include/ifr_types.hrl").
-
-%%%======================================================================
-%%% Container (IRObject)
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'(ObjRef) ->
- orber_ifr_irobject:'_get_def_kind'(ObjRef).
-
-%%% Note, that the destroy function is meant to be called within a
-%%% transaction called in the destroy function of an object which
-%%% inherits from Container. A Container should only be destroyed by
-%%% destroying the object that inherits from a Container. An attempt
-%%% to call this function in user code will result in unpredictable
-%%% results.
-
-%%% Don't type check the object reference. We need to be able to handle several
-%%% types of objects that inherit from Container.
-
-destroy(Container_objref) ->
- ObjList = cleanup_for_destroy(Container_objref),
- orber_ifr_irobject:destroy([Container_objref | ObjList]).
-
-cleanup_for_destroy(Container_objref) ->
- Contents = get_field(Container_objref, contents),
- map(fun destroy_thing/1, Contents) ++ Contents.
-
-%%% Destroy objects which inherit from Contained, i.e. objects that populate
-%%% the contents list of a Container.
-
-destroy_thing({ObjType,ObjID}) when ObjType == ir_ModuleDef ->
- orber_ifr_moduledef:cleanup_for_destroy({ObjType,ObjID});
-destroy_thing({ObjType,ObjID}) when ObjType == ir_ConstantDef ->
- orber_ifr_constantdef:cleanup_for_destroy({ObjType,ObjID});
-destroy_thing({ObjType,ObjID}) when ObjType == ir_TypedefDef ->
- orber_ifr_typedef:cleanup_for_destroy({ObjType,ObjID});
-destroy_thing({ObjType,ObjID}) when ObjType == ir_StructDef ->
- orber_ifr_structdef:cleanup_for_destroy({ObjType,ObjID});
-destroy_thing({ObjType,ObjID}) when ObjType == ir_UnionDef ->
- orber_ifr_uniondef:cleanup_for_destroy({ObjType,ObjID});
-destroy_thing({ObjType,ObjID}) when ObjType == ir_EnumDef ->
- orber_ifr_enumdef:cleanup_for_destroy({ObjType,ObjID});
-destroy_thing({ObjType,ObjID}) when ObjType == ir_AliasDef ->
- orber_ifr_aliasdef:cleanup_for_destroy({ObjType,ObjID});
-destroy_thing({ObjType,ObjID}) when ObjType == ir_ExceptionDef ->
- orber_ifr_exceptiondef:cleanup_for_destroy({ObjType,ObjID});
-destroy_thing({ObjType,ObjID}) when ObjType == ir_AttributeDef ->
- orber_ifr_attributedef:cleanup_for_destroy({ObjType,ObjID});
-destroy_thing({ObjType,ObjID}) when ObjType == ir_OperationDef ->
- orber_ifr_operationdef:cleanup_for_destroy({ObjType,ObjID});
-destroy_thing({ObjType,ObjID}) when ObjType == ir_InterfaceDef ->
- orber_ifr_interfacedef:cleanup_for_destroy({ObjType,ObjID});
-destroy_thing({_ObjType,_ObjID}) ->
- %% Unknown object in Container contents.
- true.
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-lookup(ObjRef, Search_name) ->
- Contents = contents(ObjRef, dk_All, false),
-
- %% We now have the contents (a list of object references).
- %% Let's find all objects with the correct name.
-
- case filter(fun({Type,ID}) ->
- orber_ifr_contained:'_get_absolute_name'({Type,ID}) ==
- Search_name
- end,
- Contents) of
- [Obj] ->
- Obj;
- X ->
- X
- end.
-
-
-contents(ObjRef, Limit_type, Exclude_inherited) ->
- Contents =
- flatten(get_field(ObjRef, contents) ++
- inherited_contents(ObjRef,Exclude_inherited)),
- AllContents =
- Contents ++
- flatten(subcontents(Limit_type,Contents)),
- limit_contents(Limit_type,AllContents).
-
-
-subcontents(_,[]) -> [];
-subcontents(Limit_type,Contents) ->
- map(fun(ObjRef) -> contents(ObjRef,Limit_type) end, Contents).
-
-contents({ir_Repository,ObjID},Limit_type) ->
- orber_ifr_repository:contents({ir_Repository,ObjID},Limit_type,false);
-contents({ir_ModuleDef,ObjID},Limit_type) ->
- orber_ifr_moduledef:contents({ir_ModuleDef,ObjID},Limit_type,false);
-contents({ir_InterfaceDef,ObjID},Limit_type) ->
- orber_ifr_interfacedef:contents({ir_InterfaceDef,ObjID},Limit_type,false);
-contents(_,_) -> [].
-
-limit_contents(dk_All,Contents) -> Contents;
-limit_contents(Limit_type,Contents) ->
- filter(fun(Obj_Ref) -> '_get_def_kind'(Obj_Ref) == Limit_type end,
- Contents).
-
-
-lookup_name(ObjRef, Search_name, Levels_to_search,
- Limit_type, Exclude_inherited) ->
- Contents = get_field(ObjRef, contents),
- AllContents = Contents ++ inherited_contents(ObjRef, Exclude_inherited),
- lookup_name(AllContents, Search_name, Levels_to_search, Limit_type).
-
-inherited_contents({ir_InterfaceDef,ObjID}, false) ->
- map(fun(ObjRef) -> get_field(ObjRef,contents) end,
- orber_ifr_interfacedef:'_get_base_interfaces'({ir_InterfaceDef,ObjID}));
-inherited_contents(_, false) -> [];
-inherited_contents(_, true) -> [].
-
-lookup_name(Contents, Search_name, Level, Limit_type) ->
- filter(fun(X) ->
- (orber_ifr_contained:'_get_id'(X) == Search_name)
- and
- ('_get_def_kind'(X) == Limit_type)
- end, Contents) ++
- sublookup_name(Contents, Search_name, Level - 1, Limit_type).
-
-sublookup_name([],_,_,_) -> [];
-sublookup_name(_,_,0,_) -> [];
-sublookup_name(Contents, Search_name, Level, Limit_type) ->
- map(fun(X) ->
- Conts = subcontents(X),
- lookup_name(Conts, Search_name, Level - 1, Limit_type)
- end, Contents).
-
-subcontents({ir_Repository,ObjID}) ->
- get_field({ir_Repository,ObjID}, contents);
-subcontents({ir_ModuleDefObjType,ObjID}) ->
- get_field({ir_ModuleDef,ObjID}, contents);
-subcontents({ir_InterfaceDef,ObjID}) ->
- get_field({ir_InterfaceDef,ObjID}, contents);
-subcontents(_) -> [].
-
-describe_contents(ObjRef, Limit_type, Exclude_inherited,
- Max_returned_objs) ->
- Limited_contents = contents(ObjRef,Limit_type,Exclude_inherited),
- describe_contents(Limited_contents, Max_returned_objs, []).
-
-describe_contents(_, 0, Acc) ->
- Acc;
-describe_contents([], _Max_returned_objs, Acc) ->
- Acc;
-describe_contents([H|T], Max_returned_objs, Acc) ->
- Desc = orber_ifr_contained:describe(H),
- describe_contents(T, Max_returned_objs-1, [Desc|Acc]).
-
-
-%% This is a kludge. Se p. 6-11 in CORBA 2.0.
-make_absolute_name({ObjType,ObjID}, Name) ->
- case ObjType of
- ir_Repository ->
- "::" ++ Name;
- _ ->
- orber_ifr_contained:'_get_absolute_name'({ObjType,ObjID}) ++
- "::" ++ Name
- end.
-
-%% This is a kludge. Se p. 6-15 in CORBA 2.0.
-make_containing_repository({ObjType,ObjID}) ->
- case ObjType of
- ir_Repository ->
- {ir_Repository,ObjID};
- _ ->
- orber_ifr_contained:'_get_containing_repository'({ObjType, ObjID})
- end.
-
-add_to_container(ContainerRef,Object, Id, Table, Index) ->
- F = fun() ->
- [Container_obj] = mnesia:wread(ContainerRef),
- case mnesia:index_read(Table, Id, Index) of
- [] ->
- ObjectRef = makeref(Object),
- New_container_obj =
- construct(Container_obj,contents,
- [ObjectRef | select(Container_obj,contents)]),
- mnesia:write(New_container_obj),
- mnesia:write(Object);
- _ ->
- mnesia:abort("duplicate")
- end
- end,
- case mnesia:transaction(F) of
- {aborted, "duplicate"} ->
- %% Must keep the misspelled word (must match IC generated code).
- exit({allready_registered, Id});
- {aborted, Reason} ->
- orber:dbg("[~p] orber_ifr_container:add_to_container(~p). aborted:~n~p~n",
- [?LINE, Id, Reason], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO});
- {atomic, _} ->
- ok
- end.
-
-add_to_light(#orber_light_ifr_ref{data = Data} = LRef, Id, Type, Name) ->
- BaseId = get_base_id(Data#lightdata.id, Id),
- NewScope = scoped_name(Data#lightdata.scope, Name, Type),
- F = fun() ->
- D = #orber_light_ifr{id = Id,
- module = list_to_atom(NewScope),
- type = Type, base_id = BaseId},
- mnesia:write(D)
- end,
- case mnesia:transaction(F) of
- {aborted, Reason} ->
- orber:dbg("[~p] orber_ifr_container:add_to_light(~p). aborted:~n~p~n",
- [?LINE, Id, Reason], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO});
- {atomic, _} ->
- LRef#orber_light_ifr_ref{data = Data#lightdata{scope = NewScope,
- id = BaseId}}
- end.
-
-get_base_id("", Id) ->
- Id;
-get_base_id(Id, _) ->
- Id.
-
-scoped_name("", Name, _) ->
- Name;
-scoped_name(Scope, _, ?IFR_ConstantDef) ->
- Scope;
-scoped_name(Scope, Name, _) ->
- Scope ++ "_" ++ Name.
-
-create_module(#orber_light_ifr_ref{} = LRef, Id, Name, _Version) ->
- add_to_light(LRef, Id, ?IFR_ModuleDef, Name);
-create_module(ObjRef, Id, Name, Version) ->
- New_module = #ir_ModuleDef{ir_Internal_ID = unique(),
- def_kind = dk_Module,
- contents = [],
- id = Id,
- name = Name,
- version = Version,
- defined_in = ObjRef,
- absolute_name =
- make_absolute_name(ObjRef, Name),
- containing_repository =
- make_containing_repository(ObjRef)},
- add_to_container(ObjRef,New_module, Id, ir_ModuleDef, #ir_ModuleDef.id),
- makeref(New_module).
-
-create_constant(#orber_light_ifr_ref{} = LRef, Id, Name, _Version, _Type, _Value) ->
- add_to_light(LRef, Id, ?IFR_ConstantDef, Name);
-create_constant(ObjRef, Id, Name, Version, Type, Value) ->
- IDL_typecode = get_field(Type,type),
- {Typecode, _} = Value,
- case IDL_typecode == Typecode of
- false ->
- orber:dbg("[~p] ~p:create_constant(~p, ~p, ~p, ~p, ~p, ~p);~n"
- "Wrong type.~n",
- [?LINE, ?MODULE, ObjRef, Id, Name, Version, Type, Value],
- ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO});
- true ->
- New_constant = #ir_ConstantDef{ir_Internal_ID = unique(),
- def_kind = dk_Constant,
- id = Id,
- name = Name,
- version = Version,
- defined_in = ObjRef,
- absolute_name =
- make_absolute_name(ObjRef, Name),
- containing_repository =
- make_containing_repository(ObjRef),
- type = get_field(Type,type),
- type_def = Type,
- value = Value},
- add_to_container(ObjRef,New_constant,
- Id, ir_ConstantDef, #ir_ConstantDef.id),
- makeref(New_constant)
- end.
-
-create_struct(#orber_light_ifr_ref{} = LRef, Id, Name, _Version, _Members) ->
- add_to_light(LRef, Id, ?IFR_StructDef, Name);
-create_struct(ObjRef, Id, Name, Version, Members) ->
- New_struct = #ir_StructDef{ir_Internal_ID = unique(),
- def_kind = dk_Struct,
- id = Id,
- name = Name,
- version = Version,
- defined_in = ObjRef,
- absolute_name =
- make_absolute_name(ObjRef, Name),
- containing_repository =
- make_containing_repository(ObjRef),
- type = {tk_struct, Id, Name,
- map(fun(#structmember{name=MemName,
- type=Type}) ->
- {MemName,Type} end,
- Members)},
- members = Members},
- add_to_container(ObjRef, New_struct, Id, ir_StructDef, #ir_StructDef.id),
- makeref(New_struct).
-
-create_union(#orber_light_ifr_ref{} = LRef, Id, Name, _Version,
- _Discriminator_type, _Members) ->
- add_to_light(LRef, Id, ?IFR_UnionDef, Name);
-create_union(ObjRef, Id, Name, Version,
- Discriminator_type, Members) ->
- Discriminator_type_code = get_field(Discriminator_type, type),
- New_union = #ir_UnionDef{ir_Internal_ID = unique(),
- def_kind = dk_Union,
- id = Id,
- name = Name,
- version = Version,
- defined_in = ObjRef,
- absolute_name =
- make_absolute_name(ObjRef, Name),
- containing_repository =
- make_containing_repository(ObjRef),
- type = {tk_union, Id, Name,
- Discriminator_type_code, -1,
- map(fun(#unionmember{name=MemName,
- label=Label,
- type=Type}) ->
- {Label,MemName,Type} end,
- Members)},
- discriminator_type = Discriminator_type_code,
- discriminator_type_def = Discriminator_type,
- members = Members},
- add_to_container(ObjRef, New_union, Id, ir_UnionDef, #ir_UnionDef.id),
- makeref(New_union).
-
-create_enum(#orber_light_ifr_ref{} = LRef, Id, Name, _Version, _Members) ->
- add_to_light(LRef, Id, ?IFR_EnumDef, Name);
-create_enum(ObjRef, Id, Name, Version, Members) ->
- New_enum = #ir_EnumDef{ir_Internal_ID = unique(),
- def_kind = dk_Enum,
- id = Id,
- name = Name,
- version = Version,
- defined_in = ObjRef,
- absolute_name =
- make_absolute_name(ObjRef, Name),
- containing_repository =
- make_containing_repository(ObjRef),
- type = {tk_enum, Id, Name, Members},
- members = Members},
- add_to_container(ObjRef, New_enum, Id, ir_EnumDef, #ir_EnumDef.id),
- makeref(New_enum).
-
-create_alias(#orber_light_ifr_ref{} = LRef, Id, Name, _Version, _Original_type) ->
- add_to_light(LRef, Id, ?IFR_AliasDef, Name);
-create_alias(ObjRef, Id, Name, Version, Original_type) ->
- New_alias = #ir_AliasDef{ir_Internal_ID = unique(),
- def_kind = dk_Alias,
- id = Id,
- name = Name,
- version = Version,
- defined_in = ObjRef,
- absolute_name =
- make_absolute_name(ObjRef, Name),
- containing_repository =
- make_containing_repository(ObjRef),
- type = {tk_alias, Id, Name,
- get_field(Original_type,type)},
- original_type_def = Original_type},
- add_to_container(ObjRef, New_alias, Id, ir_AliasDef, #ir_AliasDef.id),
- makeref(New_alias).
-
-create_interface(#orber_light_ifr_ref{} = LRef, Id, Name, _Version, _Base_interfaces) ->
- add_to_light(LRef, Id, ?IFR_InterfaceDef, Name);
-create_interface(ObjRef, Id, Name, Version, Base_interfaces) ->
- New_interface = #ir_InterfaceDef{ir_Internal_ID = unique(),
- def_kind = dk_Interface,
- contents = [],
- id = Id,
- name = Name,
- version = Version,
- defined_in = ObjRef,
- absolute_name =
- make_absolute_name(ObjRef,Name),
- containing_repository =
- make_containing_repository(ObjRef),
- type = {tk_objref, Id, Name},
- base_interfaces = Base_interfaces},
- add_to_container(ObjRef, New_interface, Id, ir_InterfaceDef, #ir_InterfaceDef.id),
- makeref(New_interface).
-
-create_exception(#orber_light_ifr_ref{} = LRef, Id, Name, _Version, _Members) ->
- add_to_light(LRef, Id, ?IFR_ExceptionDef, Name);
-create_exception(ObjRef, Id, Name, Version, Members) ->
- New_exception = #ir_ExceptionDef{ir_Internal_ID = unique(),
- def_kind = dk_Exception,
- id = Id,
- name = Name,
- version = Version,
- defined_in = ObjRef,
- absolute_name =
- make_absolute_name(ObjRef,Name),
- containing_repository =
- make_containing_repository(ObjRef),
- type = {tk_except, Id, Name,
- map(fun(#structmember{name=MemName,
- type=Type})
- ->
- {MemName,Type} end,
- Members)},
- members = Members},
- add_to_container(ObjRef, New_exception, Id, ir_ExceptionDef, #ir_ExceptionDef.id),
- makeref(New_exception).
diff --git a/lib/orber/src/orber_ifr_enumdef.erl b/lib/orber/src/orber_ifr_enumdef.erl
deleted file mode 100644
index b1820046bb..0000000000
--- a/lib/orber/src/orber_ifr_enumdef.erl
+++ /dev/null
@@ -1,130 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_enumdef.erl
-%% Purpose : Code for Enumdef
-%%----------------------------------------------------------------------
-
--module(orber_ifr_enumdef).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- '_get_id'/1,
- '_set_id'/2,
- '_get_name'/1,
- '_set_name'/2,
- '_get_version'/1,
- '_set_version'/2,
- '_get_defined_in'/1,
- '_get_absolute_name'/1,
- '_get_containing_repository'/1,
- describe/1,
- move/4,
- '_get_type'/1,
- '_get_members'/1,
- '_set_members'/2
- ]).
-
--import(orber_ifr_utils,[get_field/2,
- get_object/1,
- set_object/1
- ]).
-
--include("orber_ifr.hrl").
--include("ifr_objects.hrl").
-
-%%%======================================================================
-%%% EnumDef (TypedefDef(Contained(IRObject), IDLType(IRObject)))
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType, ObjID}) ?tcheck(ir_EnumDef, ObjType) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType,ObjID}).
-
-destroy({ObjType, ObjID}) ?tcheck(ir_EnumDef, ObjType) ->
- F = fun() -> ObjList = cleanup_for_destroy({ObjType, ObjID}),
- orber_ifr_irobject:destroy([{ObjType, ObjID} | ObjList])
- end,
- orber_ifr_utils:ifr_transaction_write(F).
-
-cleanup_for_destroy({ObjType,ObjID}) ?tcheck(ir_EnumDef, ObjType) ->
- orber_ifr_typedef:cleanup_for_destroy({ObjType,ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from Contained
-
-'_get_id'({ObjType, ObjID}) ?tcheck(ir_EnumDef, ObjType) ->
- orber_ifr_contained:'_get_id'({ObjType,ObjID}).
-
-'_set_id'({ObjType, ObjID}, EO_Value) ?tcheck(ir_EnumDef, ObjType) ->
- orber_ifr_contained:'_set_id'({ObjType,ObjID},EO_Value).
-
-'_get_name'({ObjType, ObjID}) ?tcheck(ir_EnumDef, ObjType) ->
- orber_ifr_contained:'_get_name'({ObjType,ObjID}).
-
-'_set_name'({ObjType, ObjID}, EO_Value) ?tcheck(ir_EnumDef, ObjType) ->
- orber_ifr_contained:'_set_name'({ObjType,ObjID}, EO_Value).
-
-'_get_version'({ObjType, ObjID}) ?tcheck(ir_EnumDef, ObjType) ->
- orber_ifr_contained:'_get_version'({ObjType,ObjID}).
-
-'_set_version'({ObjType, ObjID}, EO_Value) ?tcheck(ir_EnumDef, ObjType) ->
- orber_ifr_contained:'_set_version'({ObjType,ObjID},EO_Value).
-
-'_get_defined_in'({ObjType, ObjID}) ?tcheck(ir_EnumDef, ObjType) ->
- orber_ifr_contained:'_get_defined_in'({ObjType,ObjID}).
-
-'_get_absolute_name'({ObjType, ObjID}) ?tcheck(ir_EnumDef, ObjType) ->
- orber_ifr_contained:'_get_absolute_name'({ObjType,ObjID}).
-
-'_get_containing_repository'({ObjType, ObjID}) ?tcheck(ir_EnumDef, ObjType) ->
- orber_ifr_contained:'_get_containing_repository'({ObjType,ObjID}).
-
-describe({ObjType, ObjID}) ?tcheck(ir_EnumDef, ObjType) ->
- orber_ifr_contained:describe({ObjType,ObjID}).
-
-move({ObjType, ObjID}, New_container, New_name, New_version)
- ?tcheck(ir_EnumDef, ObjType) ->
- orber_ifr_contained:move({ObjType,ObjID},New_container,New_name,New_version).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IDLType
-
-'_get_type'({ObjType, ObjID}) ?tcheck(ir_EnumDef, ObjType) ->
- orber_ifr_idltype:'_get_type'({ObjType, ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-'_get_members'({ObjType, ObjID}) ?tcheck(ir_EnumDef, ObjType) ->
- get_field({ObjType,ObjID},members).
-
-'_set_members'({ObjType, ObjID}, EO_Value) ?tcheck(ir_EnumDef, ObjType) ->
- EnumDef = get_object({ObjType, ObjID}),
- New_EnumDef = EnumDef#ir_EnumDef{type = {tk_enum,
- EnumDef#ir_EnumDef.id,
- EnumDef#ir_EnumDef.name,
- EO_Value},
- members = EO_Value},
- set_object(New_EnumDef).
diff --git a/lib/orber/src/orber_ifr_exceptiondef.erl b/lib/orber/src/orber_ifr_exceptiondef.erl
deleted file mode 100644
index a9e477f01a..0000000000
--- a/lib/orber/src/orber_ifr_exceptiondef.erl
+++ /dev/null
@@ -1,145 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_exceptiondef.erl
-%% Purpose : Code for Exceptiondef
-%%----------------------------------------------------------------------
-
--module(orber_ifr_exceptiondef).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- '_get_id'/1,
- '_set_id'/2,
- '_get_name'/1,
- '_set_name'/2,
- '_get_version'/1,
- '_set_version'/2,
- '_get_defined_in'/1,
- '_get_absolute_name'/1,
- '_get_containing_repository'/1,
- describe/1,
- %%lookup_id/1, %not in CORBA 2.0
- move/4,
- '_get_type'/1,
- '_get_members'/1,
- '_set_members'/2
- ]).
-
--import(orber_ifr_utils,[get_field/2,
- get_object/1,
- set_object/1
- ]).
--import(lists,[map/2]).
-
--include("orber_ifr.hrl").
--include("ifr_objects.hrl").
--include_lib("orber/include/ifr_types.hrl").
-
-%%%======================================================================
-%%% ExceptionDef (Contained(IRObject))
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType, ObjID}) ?tcheck(ir_ExceptionDef, ObjType) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType,ObjID}).
-
-destroy({ObjType, ObjID}) ?tcheck(ir_ExceptionDef, ObjType) ->
- F = fun() -> ObjList = cleanup_for_destroy({ObjType, ObjID}),
- orber_ifr_irobject:destroy([{ObjType,ObjID} | ObjList])
- end,
- orber_ifr_utils:ifr_transaction_write(F).
-
-cleanup_for_destroy({ObjType,ObjID}) ?tcheck(ir_ExceptionDef, ObjType) ->
- lists:map(fun(X) -> orber_ifr_idltype:cleanup_for_destroy(
- X#structmember.type_def)
- end,
- '_get_members'({ObjType, ObjID})) ++
- orber_ifr_contained:cleanup_for_destroy({ObjType,ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from Contained
-
-'_get_id'({ObjType, ObjID}) ?tcheck(ir_ExceptionDef, ObjType) ->
- orber_ifr_contained:'_get_id'({ObjType,ObjID}).
-
-'_set_id'({ObjType, ObjID}, EO_Value) ?tcheck(ir_ExceptionDef, ObjType) ->
- orber_ifr_contained:'_set_id'({ObjType,ObjID},EO_Value).
-
-'_get_name'({ObjType, ObjID}) ?tcheck(ir_ExceptionDef, ObjType) ->
- orber_ifr_contained:'_get_name'({ObjType,ObjID}).
-
-'_set_name'({ObjType, ObjID}, EO_Value) ?tcheck(ir_ExceptionDef, ObjType) ->
- orber_ifr_contained:'_set_name'({ObjType,ObjID}, EO_Value).
-
-'_get_version'({ObjType, ObjID}) ?tcheck(ir_ExceptionDef, ObjType) ->
- orber_ifr_contained:'_get_version'({ObjType,ObjID}).
-
-'_set_version'({ObjType, ObjID}, EO_Value) ?tcheck(ir_ExceptionDef, ObjType) ->
- orber_ifr_contained:'_set_version'({ObjType,ObjID},EO_Value).
-
-'_get_defined_in'({ObjType, ObjID}) ?tcheck(ir_ExceptionDef, ObjType) ->
- orber_ifr_contained:'_get_defined_in'({ObjType,ObjID}).
-
-'_get_absolute_name'({ObjType, ObjID}) ?tcheck(ir_ExceptionDef, ObjType) ->
- orber_ifr_contained:'_get_absolute_name'({ObjType,ObjID}).
-
-'_get_containing_repository'({ObjType, ObjID})
- ?tcheck(ir_ExceptionDef, ObjType) ->
- orber_ifr_contained:'_get_containing_repository'({ObjType,ObjID}).
-
-describe({ObjType, ObjID}) ?tcheck(ir_ExceptionDef, ObjType) ->
- orber_ifr_contained:describe({ObjType,ObjID}).
-
-move({ObjType, ObjID}, New_container, New_name, New_version)
- ?tcheck(ir_ExceptionDef, ObjType) ->
- orber_ifr_contained:move({ObjType,ObjID},New_container,New_name,
- New_version).
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-'_get_type'({ObjType, ObjID}) ?tcheck(ir_ExceptionDef, ObjType) ->
- get_field({ObjType,ObjID},type).
-
-'_get_members'({ObjType, ObjID}) ?tcheck(ir_ExceptionDef, ObjType) ->
- get_field({ObjType,ObjID},members).
-
-'_set_members'({ObjType, ObjID}, EO_Value) ?tcheck(ir_ExceptionDef, ObjType) ->
- ExceptionDef = get_object({ObjType, ObjID}),
- Members=map(fun(Exceptionmember) ->
- Exceptionmember#structmember{type=tk_void}
- end, EO_Value),
- New_ExceptionDef =
- ExceptionDef#ir_ExceptionDef{type =
- {tk_except,
- ExceptionDef#ir_ExceptionDef.id,
- ExceptionDef#ir_ExceptionDef.name,
- map(fun(#structmember{name=Name,
- type=Type}) ->
- {Name,Type}
- end,
- EO_Value)},
- members=Members},
- set_object(New_ExceptionDef).
diff --git a/lib/orber/src/orber_ifr_fixeddef.erl b/lib/orber/src/orber_ifr_fixeddef.erl
deleted file mode 100644
index fc1b354af0..0000000000
--- a/lib/orber/src/orber_ifr_fixeddef.erl
+++ /dev/null
@@ -1,80 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_fixeddef.erl
-%% Description :
-%%
-%%----------------------------------------------------------------------
--module(orber_ifr_fixeddef).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- '_get_type'/1,
- '_get_digits'/1,
- '_set_digits'/2,
- '_get_scale'/1,
- '_set_scale'/2]).
-
--import(orber_ifr_utils, [get_field/2,
- set_field/3]).
-
--include("orber_ifr.hrl").
-
-%%%======================================================================
-%%% FixedDef (IDLType(IRObject))
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType,ObjID}) ?tcheck(ir_FixedDef, ObjType) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType,ObjID}).
-
-destroy({ObjType, ObjID}) ?tcheck(ir_FixedDef, ObjType) ->
- F = fun() -> ObjList = cleanup_for_destroy({ObjType, ObjID}),
- orber_ifr_irobject:destroy([{ObjType,ObjID} | ObjList])
- end,
- orber_ifr_utils:ifr_transaction_write(F).
-
-cleanup_for_destroy({ObjType,ObjID}) ?tcheck(ir_FixedDef, ObjType) ->
- orber_ifr_idltype:cleanup_for_destroy({ObjType,ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IDLType
-
-'_get_type'({ObjType, ObjID}) ?tcheck(ir_FixedDef, ObjType) ->
- orber_ifr_idltype:'_get_type'({ObjType, ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-'_get_digits'({ObjType, ObjID}) ?tcheck(ir_FixedDef, ObjType) ->
- get_field({ObjType,ObjID},digits).
-'_get_scale'({ObjType, ObjID}) ?tcheck(ir_FixedDef, ObjType) ->
- get_field({ObjType,ObjID},scale).
-
-'_set_digits'({ObjType, ObjID}, EO_Value)
- ?tcheck(ir_FixedDef, ObjType) ->
- set_field({ObjType, ObjID}, digits, EO_Value).
-'_set_scale'({ObjType, ObjID}, EO_Value)
- ?tcheck(ir_FixedDef, ObjType) ->
- set_field({ObjType, ObjID}, scale, EO_Value).
diff --git a/lib/orber/src/orber_ifr_idltype.erl b/lib/orber/src/orber_ifr_idltype.erl
deleted file mode 100644
index 44ab86c41a..0000000000
--- a/lib/orber/src/orber_ifr_idltype.erl
+++ /dev/null
@@ -1,75 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_idltype.erl
-%% Purpose : Code for Idltype
-%%----------------------------------------------------------------------
-
--module(orber_ifr_idltype).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- '_get_type'/1,
- '_get_type_def'/1
- ]).
-
--import(orber_ifr_utils,[get_field/2]).
-
--include("orber_ifr.hrl").
--include("ifr_objects.hrl").
-
-%%%======================================================================
-%%% IDLType (IRObject)
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType, ObjID}) ?tcheck(ir_IDLType, ObjType) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType, ObjID}).
-
-%%% Don't type check the object reference. We need to be able to
-%%% handle several types of objects that inherit from IDLType.
-
-destroy(IDLType_objref) ->
- F = fun() -> ObjList = cleanup_for_destroy(IDLType_objref),
- orber_ifr_irobject:destroy(ObjList)
- end,
- orber_ifr_utils:ifr_transaction_write(F).
-
-cleanup_for_destroy(IDLType_objref) ->
- [IDLType_objref].
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-%% What is this ? You cannot check this for ir_IDLType here !
-%% ( an object type cannot be both .... )
-%%'_get_type'({ObjType,ObjID}) ?tcheck(ir_IDLType, ObjType) ->
-%% get_field({ObjType,ObjID},type).
-
-
-'_get_type'({ObjType,ObjID}) ->
- get_field({ObjType,ObjID},type).
-
-'_get_type_def'({ObjType,ObjID}) ->
- get_field({ObjType,ObjID},type_def).
diff --git a/lib/orber/src/orber_ifr_interfacedef.erl b/lib/orber/src/orber_ifr_interfacedef.erl
deleted file mode 100644
index 1195f1eff6..0000000000
--- a/lib/orber/src/orber_ifr_interfacedef.erl
+++ /dev/null
@@ -1,340 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_interfacedef.erl
-%% Purpose : Code for Interfacedef
-%%----------------------------------------------------------------------
-
--module(orber_ifr_interfacedef).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- lookup/2,
- contents/3,
- lookup_name/5,
- describe_contents/4,
- create_module/4,
- create_constant/6,
- create_struct/5,
- create_union/6,
- create_enum/5,
- create_alias/5,
- create_interface/5,
- create_exception/5,
- '_get_id'/1,
- '_set_id'/2,
- '_get_name'/1,
- '_set_name'/2,
- '_get_version'/1,
- '_set_version'/2,
- '_get_defined_in'/1,
- '_get_absolute_name'/1,
- '_get_containing_repository'/1,
- describe/1,
- move/4,
- '_get_type'/1,
- '_get_base_interfaces'/1,
- '_set_base_interfaces'/2,
- is_a/2,
- describe_interface/1,
- create_attribute/6,
- create_operation/9
- ]).
-
--import(orber_ifr_utils,[get_object/1,
- get_field/2,
- set_field/3,
- select/2,
- makeref/1,
- unique/0
- ]).
--import(orber_ifr_container,[make_absolute_name/2,
- make_containing_repository/1
- ]).
-
--include("orber_ifr.hrl").
--include("ifr_objects.hrl").
--include_lib("orber/include/ifr_types.hrl").
-
-
-%%%======================================================================
-%%% InterfaceDef (Container(IRObject), Contained(IRObject), IDLType(IRObject))
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType, ObjID}) ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType,ObjID}).
-
-destroy({ObjType, ObjID}) ?tcheck(ir_InterfaceDef, ObjType) ->
- F = fun() -> ObjList = cleanup_for_destroy({ObjType,ObjID}),
- orber_ifr_irobject:destroy([{ObjType,ObjID} | ObjList])
- end,
- orber_ifr_utils:ifr_transaction_write(F).
-
-cleanup_for_destroy({ObjType,ObjID}) ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_contained:cleanup_for_destroy({ObjType,ObjID}) ++
- orber_ifr_container:cleanup_for_destroy({ObjType,ObjID}) ++
- orber_ifr_idltype:cleanup_for_destroy({ObjType,ObjID}).
-
-
-%% BUG ! You can't remove inherited !!!!!
-%%cleanup_for_destroy({ObjType,ObjID}) ?tcheck(ir_InterfaceDef, ObjType) ->
-%% lists:map(fun(X) -> cleanup_for_destroy(X) end,
-%% '_get_base_interfaces'({ObjType,ObjID})) ++ <<<<<<<<<< Here
-%% orber_ifr_contained:cleanup_for_destroy({ObjType,ObjID}) ++
-%% orber_ifr_container:cleanup_for_destroy({ObjType,ObjID}) ++
-%% orber_ifr_idltype:cleanup_for_destroy({ObjType,ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from Container
-
-lookup({ObjType, ObjID}, Search_name) ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_container:lookup({ObjType,ObjID}, Search_name).
-
-contents({ObjType, ObjID}, Limit_type, Exclude_inherited)
- ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_container:contents({ObjType,ObjID},Limit_type,Exclude_inherited).
-
-lookup_name({ObjType, ObjID}, Search_name, Levels_to_search, Limit_type,
- Exclude_inherited) ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_container:lookup_name({ObjType,ObjID}, Search_name,
- Levels_to_search, Limit_type,
- Exclude_inherited).
-
-describe_contents({ObjType, ObjID}, Limit_type, Exclude_inherited,
- Max_returned_objs) ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_container:describe_contents({ObjType,ObjID}, Limit_type,
- Exclude_inherited,
- Max_returned_objs).
-
-create_module({ObjType, ObjID}, Id, Name, Version)
- ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_container:create_module({ObjType, ObjID}, Id, Name, Version).
-
-create_constant({ObjType, ObjID}, Id, Name, Version, Type, Value)
- ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_container:create_constant({ObjType, ObjID}, Id, Name, Version,
- Type, Value).
-
-create_struct({ObjType, ObjID}, Id, Name, Version, Members)
- ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_container:create_struct({ObjType,ObjID},Id,Name,Version,Members).
-
-create_union({ObjType, ObjID}, Id, Name, Version, Discriminator_type, Members)
- ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_container:create_union({ObjType, ObjID}, Id, Name, Version,
- Discriminator_type, Members).
-
-create_enum({ObjType, ObjID}, Id, Name, Version, Members)
- ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_container:create_enum({ObjType, ObjID},Id,Name,Version,Members).
-
-create_alias({ObjType, ObjID}, Id, Name, Version, Original_type)
- ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_container:create_alias({ObjType, ObjID}, Id, Name, Version,
- Original_type).
-
-create_interface({ObjType, ObjID}, Id, Name, Version, Base_interfaces)
- ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_container:create_interface({ObjType, ObjID}, Id, Name, Version,
- Base_interfaces).
-
-create_exception({ObjType, ObjID}, Id, Name, Version, Members)
- ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_container:create_exception({ObjType, ObjID}, Id, Name, Version,
- Members).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from Contained
-
-'_get_id'({ObjType, ObjID}) ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_contained:'_get_id'({ObjType,ObjID}).
-
-'_set_id'({ObjType, ObjID}, EO_Value) ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_contained:'_set_id'({ObjType,ObjID},EO_Value).
-
-'_get_name'({ObjType, ObjID}) ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_contained:'_get_name'({ObjType,ObjID}).
-
-'_set_name'({ObjType, ObjID}, EO_Value) ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_contained:'_set_name'({ObjType,ObjID}, EO_Value).
-
-'_get_version'({ObjType, ObjID}) ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_contained:'_get_version'({ObjType,ObjID}).
-
-'_set_version'({ObjType, ObjID}, EO_Value) ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_contained:'_set_version'({ObjType,ObjID},EO_Value).
-
-'_get_defined_in'({ObjType, ObjID}) ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_contained:'_get_defined_in'({ObjType,ObjID}).
-
-'_get_absolute_name'({ObjType, ObjID}) ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_contained:'_get_absolute_name'({ObjType,ObjID}).
-
-'_get_containing_repository'({ObjType, ObjID})
- ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_contained:'_get_containing_repository'({ObjType,ObjID}).
-
-describe({ObjType, ObjID}) ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_contained:describe({ObjType,ObjID}).
-
-move({ObjType, ObjID}, New_container, New_name, New_version)
- ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_contained:move({ObjType,ObjID},New_container,New_name,
- New_version).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IDLType
-
-'_get_type'({ObjType, ObjID}) ?tcheck(ir_InterfaceDef, ObjType) ->
- orber_ifr_idltype:'_get_type'({ObjType, ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-'_get_base_interfaces'({ObjType,ObjID}) ?tcheck(ir_InterfaceDef, ObjType) ->
- get_field({ObjType,ObjID},base_interfaces).
-
-'_set_base_interfaces'({ObjType, ObjID}, EO_Value)
- ?tcheck(ir_InterfaceDef, ObjType) ->
- set_field({ObjType,ObjID}, base_interfaces, EO_Value).
-
-
-
-is_a({ObjType, ObjID}, Interface_id) ?tcheck(ir_InterfaceDef, ObjType) ->
- Base_interfaces = '_get_base_interfaces'({ObjType, ObjID}),
- lists:any(fun(X) ->
- case catch orber_ifr_contained:'_get_id'(X) of
- Interface_id ->
- 'true';
- _ ->
- 'false'
- end
- end,
- Base_interfaces).
-
-describe_interface({ObjType, ObjID}) ?tcheck(ir_InterfaceDef, ObjType) ->
-
-%%% *** Should we exclude the inherited operations here? Probably not,
-%%% but I'm not sure at all.
-
-%%% OpContents = orber_ifr_container:contents({ObjType,ObjID}, dk_Operation,
-%%% true),
-
- %% If it is OK to set Exclude_inherited to true (as in the above
- %% code which is commented out), the following code is faster than
- %% calling the contents/3 above. Otherwise we have to rethink
- %% this.
-
- Object = get_object({ObjType, ObjID}),
-
-%%% Contents = select(Object, contents),
- %% This is faster:
- Contents = Object#ir_InterfaceDef.contents,
-
- ContentsObjects = lists:map(fun(ObjRef) ->
- get_object(ObjRef)
- end,
- Contents),
- OpContents = lists:filter(fun(Obj) ->
- select(Obj,def_kind) == dk_Operation
- end,
- ContentsObjects),
-
- Ops = lists:map(fun(Obj) ->
- orber_ifr_contained:describe(Obj,dk_Operation)
- end, OpContents),
-
-%%% *** See the comment above on the Exclude_inherited parameter, and
-%%% the circumstances when not to use contents/3.
-
-%%% AttrContents = orber_ifr_container:contents({ObjType,ObjID}, dk_Attribute,
-%%% true),
-
- AttrContents = lists:filter(fun(Obj) ->
- select(Obj,def_kind) == dk_Attribute
- end,
- ContentsObjects),
- Attrs = lists:map(fun(Obj) ->
- orber_ifr_contained:describe(Obj,dk_Attribute)
- end, AttrContents),
-
- #fullinterfacedescription{name = Object#ir_InterfaceDef.name,
- id = Object#ir_InterfaceDef.id,
- defined_in = Object#ir_InterfaceDef.defined_in,
- version = Object#ir_InterfaceDef.version,
- operations = Ops,
- attributes = Attrs,
- base_interfaces =
- Object#ir_InterfaceDef.base_interfaces,
- type = Object#ir_InterfaceDef.type
- }.
-
-create_attribute(#orber_light_ifr_ref{} = LRef, _Id, _Name, _Version, _Type, _Mode) ->
- LRef;
-create_attribute({ObjType, ObjID}, Id, Name, Version, Type, Mode)
- ?tcheck(ir_InterfaceDef, ObjType) ->
- New_attribute = #ir_AttributeDef{ir_Internal_ID = unique(),
- def_kind = dk_Attribute,
- id = Id,
- name = Name,
- version = Version,
- defined_in = {ObjType, ObjID},
- absolute_name =
- make_absolute_name({ObjType,ObjID}, Name),
- containing_repository =
- make_containing_repository({ObjType,ObjID}),
- type = get_field(Type,type),
- type_def = Type,
- mode = Mode},
- orber_ifr_container:add_to_container({ObjType,ObjID}, New_attribute,
- Id, ir_AttributeDef,
- #ir_AttributeDef.id),
- makeref(New_attribute).
-
-create_operation(#orber_light_ifr_ref{} = LRef, _Id, _Name, _Version, _Result,
- _Mode, _Params, _Exceptions, _Contexts) ->
- LRef;
-create_operation({ObjType, ObjID}, Id, Name, Version, Result, Mode, Params,
- Exceptions, Contexts) ?tcheck(ir_InterfaceDef, ObjType) ->
- New_operation = #ir_OperationDef{ir_Internal_ID = unique(),
- def_kind = dk_Operation,
- id = Id,
- name = Name,
- version = Version,
- defined_in = {ObjType, ObjID},
- absolute_name =
- make_absolute_name({ObjType,ObjID}, Name),
- containing_repository =
- make_containing_repository({ObjType,ObjID}),
- result = get_field(Result,type),
- result_def = Result,
- mode = Mode,
- params = Params,
- exceptions = Exceptions,
- contexts = Contexts},
- orber_ifr_container:add_to_container({ObjType,ObjID}, New_operation,
- Id, ir_OperationDef,
- #ir_OperationDef.id),
- makeref(New_operation).
diff --git a/lib/orber/src/orber_ifr_irobject.erl b/lib/orber/src/orber_ifr_irobject.erl
deleted file mode 100644
index 1111f00f81..0000000000
--- a/lib/orber/src/orber_ifr_irobject.erl
+++ /dev/null
@@ -1,73 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_irobject.erl
-%% Purpose : Code for IRObject
-%%----------------------------------------------------------------------
-
--module(orber_ifr_irobject).
-
--export(['_get_def_kind'/1,
- destroy/1
- ]).
-
--import(orber_ifr_utils,[get_field/2]).
-
--include("orber_ifr.hrl").
--include_lib("orber/include/corba.hrl").
-
-%%%======================================================================
-%%% IRObject
-
-'_get_def_kind'({ObjType,ObjID}) ->
- get_field({ObjType,ObjID},def_kind).
-
-%%% Note, that the destroy function is meant to be called within a
-%%% transaction called in the destroy function of an object which
-%%% inherits from IRObject. An IRObject should only be destroyed by
-%%% destroying the object that inherits from an IRObject. An attempt
-%%% to call this function in user code will result in unpredictable
-%%% results.
-
-%%% Don't type check the object reference. We need to be able to
-%%% handle several types of objects that inherit from IRObject.
-
-destroy(L) when is_list(L) ->
- destroy2(lists:reverse(L)).
-
-destroy2([Things_HD | Things_TL]) ->
- destroy2(Things_HD),
- destroy2(Things_TL);
-
-destroy2([]) ->
- ok;
-destroy2(F) when is_function(F) ->
- F();
-destroy2(Thing) when is_tuple(Thing) ->
- mnesia:delete(Thing),
- ok;
-destroy2(Thing) ->
- orber:dbg("[~p] ~p:destroy2(~p);~n"
- "Strange argument for destroy.~n",
- [?LINE, ?MODULE, Thing], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO}).
-
diff --git a/lib/orber/src/orber_ifr_moduledef.erl b/lib/orber/src/orber_ifr_moduledef.erl
deleted file mode 100644
index add0feb31a..0000000000
--- a/lib/orber/src/orber_ifr_moduledef.erl
+++ /dev/null
@@ -1,184 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_moduledef.erl
-%% Purpose : Code for Moduledef
-%%----------------------------------------------------------------------
-
--module(orber_ifr_moduledef).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- lookup/2,
- contents/3,
- lookup_name/5,
- describe_contents/4,
- create_module/4,
- create_constant/6,
- create_struct/5,
- create_union/6,
- create_enum/5,
- create_alias/5,
- create_interface/5,
- create_exception/5,
- '_get_id'/1,
- '_set_id'/2,
- '_get_name'/1,
- '_set_name'/2,
- '_get_version'/1,
- '_set_version'/2,
- '_get_defined_in'/1,
- '_get_absolute_name'/1,
- '_get_containing_repository'/1,
- describe/1,
- move/4
- ]).
-
--include("orber_ifr.hrl").
-
-%%%======================================================================
-%%% ModuleDef (Container(IRObject), Contained(IRObject))
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType, ObjID}) ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType, ObjID}).
-
-destroy({ObjType, ObjID}) ?tcheck(ir_ModuleDef, ObjType) ->
- F = fun() -> '_clean'({ObjType, ObjID}) end,
- orber_ifr_utils:ifr_transaction_write(F).
-
-'_clean'(ObjRef) ->
- ObjList = cleanup_for_destroy(ObjRef),
- orber_ifr_irobject:destroy([ObjRef | ObjList]).
-
-
-cleanup_for_destroy({ObjType,ObjID}) ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_container:cleanup_for_destroy({ObjType,ObjID}) ++
- orber_ifr_contained:cleanup_for_destroy({ObjType,ObjID}).
-
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from Container
-
-lookup({ObjType, ObjID}, Search_name) ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_container:lookup({ObjType, ObjID}, Search_name).
-
-contents({ObjType, ObjID}, Limit_type, Exclude_inherited)
- ?tcheck(ir_ModuleDef, ObjType)->
- orber_ifr_container:contents({ObjType, ObjID},Limit_type,
- Exclude_inherited).
-
-lookup_name({ObjType, ObjID}, Search_name, Levels_to_search, Limit_type,
- Exclude_inherited)
- ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_container:lookup_name({ObjType,ObjID}, Search_name,
- Levels_to_search, Limit_type,
- Exclude_inherited).
-
-describe_contents({ObjType, ObjID}, Limit_type, Exclude_inherited,
- Max_returned_objs)
- ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_container:describe_contents({ObjType, ObjID}, Limit_type,
- Exclude_inherited,Max_returned_objs).
-
-create_module({ObjType, ObjID}, Id, Name, Version)
- ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_container:create_module({ObjType, ObjID}, Id, Name, Version).
-
-create_constant({ObjType, ObjID}, Id, Name, Version, Type, Value)
- ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_container:create_constant({ObjType, ObjID}, Id, Name, Version,
- Type, Value).
-
-create_struct({ObjType, ObjID}, Id, Name, Version, Members)
- ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_container:create_struct({ObjType,ObjID},Id,Name,Version,Members).
-
-create_union({ObjType, ObjID}, Id, Name, Version, Discriminator_type, Members)
- ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_container:create_union({ObjType, ObjID}, Id, Name, Version,
- Discriminator_type, Members).
-
-create_enum({ObjType, ObjID}, Id, Name, Version, Members)
- ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_container:create_enum({ObjType, ObjID},Id,Name,Version,Members).
-
-create_alias({ObjType, ObjID}, Id, Name, Version, Original_type)
- ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_container:create_alias({ObjType, ObjID}, Id, Name, Version,
- Original_type).
-
-create_interface({ObjType, ObjID}, Id, Name, Version, Base_interfaces)
- ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_container:create_interface({ObjType, ObjID}, Id, Name, Version,
- Base_interfaces).
-
-create_exception({ObjType, ObjID}, Id, Name, Version, Members)
- ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_container:create_exception({ObjType, ObjID}, Id, Name, Version,
- Members).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from Contained
-
-'_get_id'({ObjType, ObjID}) ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_contained:'_get_id'({ObjType,ObjID}).
-
-'_set_id'({ObjType,ObjID},EO_Value) ?tcheck(ir_ModuleDef,ObjType) ->
- orber_ifr_contained:'_set_id'({ObjType,ObjID},EO_Value).
-
-'_get_name'({ObjType, ObjID}) ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_contained:'_get_name'({ObjType,ObjID}).
-
-'_set_name'({ObjType, ObjID}, EO_Value) ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_contained:'_set_name'({ObjType,ObjID}, EO_Value).
-
-'_get_version'({ObjType, ObjID}) ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_contained:'_get_version'({ObjType,ObjID}).
-
-'_set_version'({ObjType, ObjID}, EO_Value) ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_contained:'_set_version'({ObjType,ObjID},EO_Value).
-
-'_get_defined_in'({ObjType, ObjID}) ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_contained:'_get_defined_in'({ObjType,ObjID}).
-
-'_get_absolute_name'({ObjType, ObjID}) ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_contained:'_get_absolute_name'({ObjType,ObjID}).
-
-'_get_containing_repository'({ObjType, ObjID}) ?tcheck(ir_ModuleDef,ObjType) ->
- orber_ifr_contained:'_get_containing_repository'({ObjType,ObjID}).
-
-describe({ObjType, ObjID}) ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_contained:describe({ObjType,ObjID}).
-
-move({ObjType, ObjID}, New_container, New_name, New_version)
- ?tcheck(ir_ModuleDef, ObjType) ->
- orber_ifr_contained:move({ObjType,ObjID},New_container,New_name,
- New_version).
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-%%% none %%
diff --git a/lib/orber/src/orber_ifr_operationdef.erl b/lib/orber/src/orber_ifr_operationdef.erl
deleted file mode 100644
index 4bc368487c..0000000000
--- a/lib/orber/src/orber_ifr_operationdef.erl
+++ /dev/null
@@ -1,192 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_operationdef.erl
-%% Purpose : Code for Operationdef
-%%----------------------------------------------------------------------
-
--module(orber_ifr_operationdef).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- '_get_id'/1,
- '_set_id'/2,
- '_get_name'/1,
- '_set_name'/2,
- '_get_version'/1,
- '_set_version'/2,
- '_get_defined_in'/1,
- '_get_absolute_name'/1,
- '_get_containing_repository'/1,
- describe/1,
- move/4,
- '_get_result'/1,
- '_get_result_def'/1,
- '_set_result_def'/2,
- '_get_params'/1,
- '_set_params'/2,
- '_get_mode'/1,
- '_set_mode'/2,
- '_get_contexts'/1,
- '_set_contexts'/2,
- '_get_exceptions'/1,
- '_set_exceptions'/2
- ]).
-
--import(orber_ifr_utils,[get_field/2,
- set_field/3,
- get_object/1,
- set_object/1
- ]).
-
--include("orber_ifr.hrl").
--include("ifr_objects.hrl").
--include_lib("orber/include/ifr_types.hrl").
--include_lib("orber/include/corba.hrl").
-
-%%%======================================================================
-%%% OperationDef (Contained(IRObject))
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType, ObjID}) ?tcheck(ir_OperationDef, ObjType) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType,ObjID}).
-
-destroy({ObjType, ObjID}) ?tcheck(ir_OperationDef, ObjType) ->
- F = fun() -> ObjList = cleanup_for_destroy({ObjType, ObjID}),
- orber_ifr_irobject:destroy([{ObjType,ObjID} | ObjList])
- end,
- orber_ifr_utils:ifr_transaction_write(F).
-
-cleanup_for_destroy({ObjType,ObjID}) ?tcheck(ir_OperationDef, ObjType) ->
- lists:map(fun(X) -> Idl = X#parameterdescription.type_def,
- orber_ifr_idltype:cleanup_for_destroy(Idl)
- end,
- '_get_params'({ObjType,ObjID})) ++
- orber_ifr_idltype:cleanup_for_destroy('_get_result_def'({ObjType,
- ObjID})) ++
- orber_ifr_contained:cleanup_for_destroy({ObjType,ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from Contained
-
-'_get_id'({ObjType, ObjID}) ?tcheck(ir_OperationDef, ObjType) ->
- orber_ifr_contained:'_get_id'({ObjType,ObjID}).
-
-'_set_id'({ObjType, ObjID}, EO_Value) ?tcheck(ir_OperationDef, ObjType) ->
- orber_ifr_contained:'_set_id'({ObjType,ObjID},EO_Value).
-
-'_get_name'({ObjType, ObjID}) ?tcheck(ir_OperationDef, ObjType) ->
- orber_ifr_contained:'_get_name'({ObjType,ObjID}).
-
-'_set_name'({ObjType, ObjID}, EO_Value) ?tcheck(ir_OperationDef, ObjType) ->
- orber_ifr_contained:'_set_name'({ObjType,ObjID}, EO_Value).
-
-'_get_version'({ObjType, ObjID}) ?tcheck(ir_OperationDef, ObjType) ->
- orber_ifr_contained:'_get_version'({ObjType,ObjID}).
-
-'_set_version'({ObjType, ObjID}, EO_Value) ?tcheck(ir_OperationDef, ObjType) ->
- orber_ifr_contained:'_set_version'({ObjType,ObjID},EO_Value).
-
-'_get_defined_in'({ObjType, ObjID}) ?tcheck(ir_OperationDef, ObjType) ->
- orber_ifr_contained:'_get_defined_in'({ObjType,ObjID}).
-
-'_get_absolute_name'({ObjType, ObjID}) ?tcheck(ir_OperationDef, ObjType) ->
- orber_ifr_contained:'_get_absolute_name'({ObjType,ObjID}).
-
-'_get_containing_repository'({ObjType, ObjID}) ?tcheck(ir_OperationDef, ObjType) ->
- orber_ifr_contained:'_get_containing_repository'({ObjType,ObjID}).
-
-describe({ObjType, ObjID}) ?tcheck(ir_OperationDef, ObjType) ->
- orber_ifr_contained:describe({ObjType,ObjID}).
-
-move({ObjType, ObjID}, New_container, New_name, New_version)
- ?tcheck(ir_OperationDef, ObjType) ->
- orber_ifr_contained:move({ObjType,ObjID},New_container,New_name,New_version).
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-'_get_result'({ObjType, ObjID})
- ?tcheck(ir_OperationDef, ObjType) ->
- get_field({ObjType,ObjID},result).
-
-'_get_result_def'({ObjType, ObjID})
- ?tcheck(ir_OperationDef, ObjType) ->
- get_field({ObjType,ObjID},result_def).
-
-'_set_result_def'({ObjType, ObjID}, EO_Value)
- ?tcheck(ir_OperationDef, ObjType) ->
- OperationDef = get_object({ObjType, ObjID}),
- New_OperationDef =
- OperationDef#ir_OperationDef{result = EO_Value#ir_IDLType.type,
- result_def = EO_Value},
- set_object(New_OperationDef).
-
-'_get_params'({ObjType,ObjID}) ?tcheck(ir_OperationDef,ObjType) ->
- get_field({ObjType,ObjID},params).
-
-'_set_params'({ObjType, ObjID}, EO_Value)
- ?tcheck(ir_OperationDef, ObjType) ->
- set_field({ObjType,ObjID}, params, EO_Value).
-
-'_get_mode'({ObjType, ObjID}) ?tcheck(ir_OperationDef, ObjType) ->
- get_field({ObjType,ObjID},mode).
-
-'_set_mode'({ObjType, ObjID}, EO_Value) ?tcheck(ir_OperationDef, ObjType) ->
- OperationDef = get_object({ObjType, ObjID}),
- Set_OK = case EO_Value of
- 'OP_ONEWAY' ->
- (OperationDef#ir_OperationDef.result == tk_void)
- and
- lists:foldl(fun(#parameterdescription{mode=Mode},AccIn) ->
- (Mode == 'PARAM_IN') and AccIn
- end,
- true,OperationDef#ir_OperationDef.params);
- _ ->
- true
- end,
- set_mode(Set_OK,{ObjType,ObjID},EO_Value).
-
-set_mode(true,Objref,EO_Value) ->
- set_field(Objref,mode,EO_Value);
-set_mode(false, Objref, EO_Value) ->
- orber:dbg("[~p] ~p:destroy(~p, ~p);~n"
- "Illegal '_set_mode'.~n",
- [?LINE, ?MODULE, Objref, EO_Value], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO}).
-
-'_get_contexts'({ObjType, ObjID}) ?tcheck(ir_OperationDef, ObjType) ->
- get_field({ObjType,ObjID},contexts).
-
-'_set_contexts'({ObjType, ObjID}, EO_Value)
- ?tcheck(ir_OperationDef, ObjType) ->
- set_field({ObjType,ObjID}, contexts, EO_Value).
-
-'_get_exceptions'({ObjType, ObjID}) ?tcheck(ir_OperationDef, ObjType) ->
- get_field({ObjType,ObjID},exceptions).
-
-'_set_exceptions'({ObjType, ObjID}, EO_Value)
- ?tcheck(ir_OperationDef, ObjType) ->
- set_field({ObjType,ObjID}, exceptions, EO_Value).
diff --git a/lib/orber/src/orber_ifr_orb.erl b/lib/orber/src/orber_ifr_orb.erl
deleted file mode 100644
index 3969bbf37a..0000000000
--- a/lib/orber/src/orber_ifr_orb.erl
+++ /dev/null
@@ -1,100 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_orb.erl
-%% Purpose : Code for Orb
-%%----------------------------------------------------------------------
-
--module(orber_ifr_orb).
-
--export([create_struct_tc/3,
- create_union_tc/4,
- create_enum_tc/3,
- create_alias_tc/3,
- create_exception_tc/3,
- create_interface_tc/2,
- create_string_tc/1,
- create_wstring_tc/1,
- create_sequence_tc/2,
- create_recursive_sequence_tc/2,
- create_array_tc/2
- ]).
-
-
--include("orber_ifr.hrl").
--include_lib("orber/include/ifr_types.hrl").
--include_lib("orber/include/corba.hrl").
-
-%%%======================================================================
-%%% ORB
-
-%%%----------------------------------------------------------------------
-%%% Inherited interfaces
-
-%% none %%
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-create_struct_tc(Id, Name, Members) ->
- {tk_struct,Id,Name,lists:map(fun(#structmember{name=MemName,type=Type}) ->
- {MemName,Type} end,
- Members)}.
-
-create_union_tc(Id, Name, Discriminator_type, Members) ->
- {tk_union, Id, Name, Discriminator_type, -1, % *** is -1 correct???
- lists:map(fun(#unionmember{name=MemName, label=Label, type=Type}) ->
- {Label,MemName,Type} end,
- Members)}.
-
-create_enum_tc(Id, Name, Members) ->
- {tk_enum, Id, Name, Members}.
-
-create_alias_tc(Id, Name, Original_type) ->
- {tk_alias, Id, Name, orber_ifr_utils:get_field(Original_type,type)}.
-
-create_exception_tc(Id, Name, Members) ->
- {tk_except,Id,Name,lists:map(fun(#structmember{name=MemName,type=Type}) ->
- {MemName,Type} end,
- Members)}.
-
-create_interface_tc(Id, Name) ->
- {tk_objref, Id, Name}.
-
-create_string_tc(Bound) ->
- {tk_string, Bound}.
-
-create_wstring_tc(Bound) ->
- {tk_wstring, Bound}.
-
-create_sequence_tc(Bound, Element_type) ->
- {tk_sequence,Element_type,Bound}.
-
--spec create_recursive_sequence_tc(_, _) -> no_return().
-create_recursive_sequence_tc(Bound, Offset) ->
- orber:dbg("[~p] ~p:create_recursive_sequence_tc(~p, ~p);~n"
- "Create_recursive_sequence is not implemented.~n",
- [?LINE, ?MODULE, Bound, Offset], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO}).
-
-create_array_tc(Length, Element_type) ->
- {tk_array, Element_type, Length}.
diff --git a/lib/orber/src/orber_ifr_primitivedef.erl b/lib/orber/src/orber_ifr_primitivedef.erl
deleted file mode 100644
index bf91bc87bb..0000000000
--- a/lib/orber/src/orber_ifr_primitivedef.erl
+++ /dev/null
@@ -1,70 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_primitivedef.erl
-%% Purpose : Code for Primitivedef
-%%----------------------------------------------------------------------
-
--module(orber_ifr_primitivedef).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- '_get_type'/1,
- '_get_kind'/1
- ]).
-
--import(orber_ifr_utils,[get_field/2
- ]).
-
--include("orber_ifr.hrl").
-
-%%%======================================================================
-%%% PrimitiveDef (IDLType(IRObject))
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType, ObjID}) ?tcheck(ir_PrimitiveDef, ObjType) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType,ObjID}).
-
-destroy({ObjType, ObjID}) ?tcheck(ir_PrimitiveDef, ObjType) ->
- F = fun() -> ObjList = cleanup_for_destroy({ObjType, ObjID}),
- orber_ifr_irobject:destroy([{ObjType,ObjID} | ObjList])
- end,
- orber_ifr_utils:ifr_transaction_write(F).
-
-cleanup_for_destroy({ObjType,ObjID}) ?tcheck(ir_PrimitiveDef, ObjType) ->
- orber_ifr_idltype:cleanup_for_destroy({ObjType,ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IDLType
-
-'_get_type'({ObjType, ObjID}) ?tcheck(ir_PrimitiveDef, ObjType) ->
- orber_ifr_idltype:'_get_type'({ObjType, ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-'_get_kind'({ObjType, ObjID}) ?tcheck(ir_PrimitiveDef, ObjType) ->
- get_field({ObjType,ObjID},kind).
-
diff --git a/lib/orber/src/orber_ifr_repository.erl b/lib/orber/src/orber_ifr_repository.erl
deleted file mode 100644
index 8d52573e53..0000000000
--- a/lib/orber/src/orber_ifr_repository.erl
+++ /dev/null
@@ -1,288 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_repository.erl
-%% Purpose : Code for Repository
-%%----------------------------------------------------------------------
-
--module(orber_ifr_repository).
-
--export(['_get_def_kind'/1,
- destroy/1,
- lookup/2,
- contents/3,
- lookup_name/5,
- describe_contents/4,
- create_module/4,
- create_constant/6,
- create_struct/5,
- create_union/6,
- create_enum/5,
- create_alias/5,
- create_interface/5,
- create_exception/5,
- lookup_id/2,
- get_primitive/2,
- create_string/2,
- create_wstring/2,
- create_fixed/3,
- create_sequence/3,
- create_array/3,
- create_idltype/2, %not in CORBA 2.0
- create_primitivedef/1, %not in CORBA 2.0
- create_primitivedef/2 %not in CORBA 2.0
- ]).
-
-
--include("orber_ifr.hrl").
--include("ifr_objects.hrl").
--include_lib("orber/include/corba.hrl").
-
-%%%======================================================================
-%%% Repository (Container (IRObject))
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType, ObjID}) ?tcheck(ir_Repository, ObjType) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType, ObjID}).
-
--spec destroy(_) -> no_return().
-destroy({ObjType, ObjID}) ?tcheck(ir_Repository, ObjType) ->
- orber:dbg("[~p] ~p:destroy(~p, ~p);~n"
- "Destroying a repository is an error.~n",
- [?LINE, ?MODULE, ObjType, ObjID], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO}).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from Container
-
-lookup({ObjType,ObjID}, Search_name) ?tcheck(ir_Repository, ObjType) ->
- orber_ifr_container:lookup({ObjType, ObjID}, Search_name).
-
-contents({ObjType,ObjID}, Limit_type, Exclude_inherited)
- ?tcheck(ir_Repository, ObjType) ->
- orber_ifr_container:contents({ObjType,ObjID},Limit_type,Exclude_inherited).
-
-lookup_name({ObjType,ObjID}, Search_name, Levels_to_search, Limit_type,
- Exclude_inherited) ?tcheck(ir_Repository, ObjType) ->
- orber_ifr_container:lookup_name({ObjType, ObjID}, Search_name,
- Levels_to_search, Limit_type,
- Exclude_inherited).
-
-describe_contents({ObjType,ObjID}, Limit_type, Exclude_inherited,
- Max_returned_objs) ?tcheck(ir_Repository, ObjType) ->
- orber_ifr_container:describe_contents({ObjType, ObjID}, Limit_type,
- Exclude_inherited,Max_returned_objs).
-
-create_module({ObjType,ObjID}, Id, Name, Version)
- ?tcheck(ir_Repository, ObjType) ->
- orber_ifr_container:create_module({ObjType,ObjID}, Id, Name, Version).
-
-create_constant({ObjType,ObjID}, Id, Name, Version, Type, Value)
- ?tcheck(ir_Repository, ObjType) ->
- orber_ifr_container:create_constant({ObjType,ObjID}, Id, Name, Version,
- Type, Value).
-
-create_struct({ObjType,ObjID}, Id, Name, Version, Members)
- ?tcheck(ir_Repository, ObjType) ->
- orber_ifr_container:create_struct({ObjType,ObjID}, Id, Name, Version,
- Members).
-
-create_union({ObjType,ObjID}, Id, Name, Version, Discriminator_type, Members)
- ?tcheck(ir_Repository, ObjType) ->
- orber_ifr_container:create_union({ObjType,ObjID}, Id, Name, Version,
- Discriminator_type, Members).
-
-create_enum({ObjType,ObjID}, Id, Name, Version, Members)
- ?tcheck(ir_Repository, ObjType) ->
- orber_ifr_container:create_enum({ObjType,ObjID},Id,Name,Version,Members).
-
-create_alias({ObjType,ObjID}, Id, Name, Version, Original_type)
- ?tcheck(ir_Repository, ObjType) ->
- orber_ifr_container:create_alias({ObjType,ObjID}, Id, Name, Version,
- Original_type).
-
-create_interface({ObjType,ObjID}, Id, Name, Version, Base_interfaces)
- ?tcheck(ir_Repository, ObjType) ->
- orber_ifr_container:create_interface({ObjType,ObjID}, Id, Name, Version,
- Base_interfaces).
-
-create_exception({ObjType, ObjID}, Id, Name, Version, Members)
- ?tcheck(ir_Repository, ObjType) ->
- orber_ifr_container:create_exception({ObjType, ObjID}, Id, Name, Version,
- Members).
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-lookup_id({ObjType,ObjID}, Search_id) ?tcheck(ir_Repository, ObjType) ->
- Contents = orber_ifr_container:contents({ObjType, ObjID}, dk_All, false),
- case lists:filter(fun(X) -> orber_ifr_contained:'_get_id'(X) == Search_id
- end, Contents) of
- [] ->
- [];
- [ObjRef] ->
- ObjRef;
- [H|T] ->
- %% This case is just a safety-guard; orber_ifr_container:contents
- %% sometimes return duplicates due to inheritance.
- case lists:any(fun(X) -> X =/= H end, T) of
- false ->
- H;
- true ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end
- end.
-
-get_primitive({ObjType,ObjID}, Kind) ?tcheck(ir_Repository, ObjType) ->
- Primitivedefs = orber_ifr_utils:get_field({ObjType,ObjID}, primitivedefs),
- lists:filter(fun(X) -> orber_ifr_primitivedef:'_get_kind'(X) == Kind end,
- Primitivedefs).
-
-%% It is probably incorrect to add the anonymous typedefs (string,
-%% sequence and array) to the field primitivdefs in the Repository.
-%% It is probably also not correct to add them to the contents field.
-%% Perhaps it is necessary to add another field in the ir_Repository
-%% record for anonymous typedefs? Then again, perhaps it is not
-%% necessary to keep the anonymous typedefs anywhere? According to
-%% the specification it is the callers responsibility to destroy the
-%% anonymous typedef if it is not successfully used.
-
-create_string({ObjType,_ObjID}, Bound) ?tcheck(ir_Repository, ObjType) ->
- New_string = #ir_StringDef{ir_Internal_ID = orber_ifr_utils:unique(),
- def_kind = dk_String,
- type = {tk_string, Bound},
- bound = Bound},
- orber_ifr_utils:makeref(New_string).
-
-create_wstring({ObjType,_ObjID}, Bound) ?tcheck(ir_Repository, ObjType) ->
- NewWstring = #ir_WstringDef{ir_Internal_ID = orber_ifr_utils:unique(),
- def_kind = dk_Wstring,
- type = {tk_wstring, Bound},
- bound = Bound},
- orber_ifr_utils:makeref(NewWstring).
-
-create_fixed({ObjType,_ObjID}, Digits, Scale) ?tcheck(ir_Repository, ObjType) ->
- NewFixed = #ir_FixedDef{ir_Internal_ID = orber_ifr_utils:unique(),
- def_kind = dk_Fixed,
- type = {tk_fixed, Digits, Scale},
- digits = Digits,
- scale = Scale},
- orber_ifr_utils:makeref(NewFixed).
-
-create_sequence({ObjType,_ObjID}, Bound, Element_type)
- ?tcheck(ir_Repository, ObjType) ->
- Element_typecode = orber_ifr_utils:get_field(Element_type, type),
- New_sequence = #ir_SequenceDef{ir_Internal_ID = orber_ifr_utils:unique(),
- def_kind = dk_Sequence,
- type = {tk_sequence,Element_typecode,Bound},
- bound = Bound,
- element_type = Element_typecode,
- element_type_def = Element_type},
- orber_ifr_utils:makeref(New_sequence).
-
-create_array({ObjType,_ObjID}, Length, Element_type)
- ?tcheck(ir_Repository, ObjType) ->
- Element_typecode = orber_ifr_utils:get_field(Element_type, type),
- New_array = #ir_ArrayDef{ir_Internal_ID = orber_ifr_utils:unique(),
- def_kind = dk_Array,
- type = {tk_array, Element_typecode, Length},
- length = Length,
- element_type = Element_typecode,
- element_type_def = Element_type},
- orber_ifr_utils:makeref(New_array).
-
-%%%----------------------------------------------------------------------
-%%% Extra interfaces (not in the IDL-spec for the IFR).
-
-create_idltype(#orber_light_ifr_ref{} = LRef, _Typecode) ->
- LRef;
-create_idltype({ObjType,_ObjID}, Typecode) ?tcheck(ir_Repository, ObjType) ->
- New_idltype = #ir_IDLType{ir_Internal_ID = orber_ifr_utils:unique(),
- def_kind = dk_none,
- type=Typecode},
- orber_ifr_utils:set_object(New_idltype),
- orber_ifr_utils:makeref(New_idltype).
-
-create_primitivedef(Pkind) ->
- create_primitivedef(Pkind, true).
-create_primitivedef(Pkind, Transaction) ->
- Typecode = case Pkind of
- pk_void ->
- tk_void;
- pk_short ->
- tk_short;
- pk_long ->
- tk_long;
- pk_longlong ->
- tk_longlong;
- pk_ushort ->
- tk_ushort;
- pk_ulong ->
- tk_ulong;
- pk_ulonglong ->
- tk_ulonglong;
- pk_float ->
- tk_float;
- pk_double ->
- tk_double;
- pk_boolean ->
- tk_boolean;
- pk_char ->
- tk_char;
- pk_wchar ->
- tk_wchar;
- pk_fixed ->
- tk_fixed;
- pk_octet ->
- tk_octet;
- pk_any ->
- tk_any;
- pk_TypeCode ->
- tk_TypeCode;
- pk_Principal ->
- tk_Principal;
- pk_string ->
- orber_ifr_orb:create_string_tc(0);
- pk_wstring ->
- orber_ifr_orb:create_wstring_tc(0);
- pk_objref ->
- %%*** what should the Id and Name be here?
- orber_ifr_orb:create_interface_tc("", "");
- _ ->
- orber:dbg("[~p] ~p:destroy(~p);~n"
- "Illegal primitivekin.~n",
- [?LINE, ?MODULE, Pkind], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO})
- end,
- New_primitivedef = #ir_PrimitiveDef{ir_Internal_ID = orber_ifr_utils:unique(),
- def_kind = dk_Primitive,
- type = Typecode,
- kind = Pkind},
- case Transaction of
- true ->
- orber_ifr_utils:set_object(New_primitivedef);
- false ->
- mnesia:write(New_primitivedef)
- end,
- orber_ifr_utils:makeref(New_primitivedef).
diff --git a/lib/orber/src/orber_ifr_sequencedef.erl b/lib/orber/src/orber_ifr_sequencedef.erl
deleted file mode 100644
index f3a9806828..0000000000
--- a/lib/orber/src/orber_ifr_sequencedef.erl
+++ /dev/null
@@ -1,104 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_sequencedef.erl
-%% Purpose : Code for Sequencedef
-%%----------------------------------------------------------------------
-
--module(orber_ifr_sequencedef).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- '_get_type'/1,
- '_get_bound'/1,
- '_set_bound'/2,
- '_get_element_type'/1,
- '_get_element_type_def'/1,
- '_set_element_type_def'/2
- ]).
-
--import(orber_ifr_utils,[get_field/2,
- get_object/1,
- set_object/1
- ]).
-
--include("orber_ifr.hrl").
--include("ifr_objects.hrl").
-
-%%%======================================================================
-%%% SequenceDef (IDLType(IRObject))
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType,ObjID}) ?tcheck(ir_SequenceDef,ObjType) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType,ObjID}).
-
-destroy({ObjType, ObjID}) ?tcheck(ir_SequenceDef, ObjType) ->
- F = fun() -> ObjList = cleanup_for_destroy({ObjType, ObjID}),
- orber_ifr_irobject:destroy([{ObjType,ObjID} | ObjList])
- end,
- orber_ifr_utils:ifr_transaction_write(F).
-
-cleanup_for_destroy({ObjType,ObjID}) ?tcheck(ir_SequenceDef, ObjType) ->
- orber_ifr_idltype:cleanup_for_destroy(
- '_get_element_type_def'({ObjType,ObjID})) ++
- orber_ifr_idltype:cleanup_for_destroy({ObjType,ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IDLType
-
-'_get_type'({ObjType, ObjID}) ?tcheck(ir_SequenceDef, ObjType) ->
- orber_ifr_idltype:'_get_type'({ObjType, ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-'_get_bound'({ObjType, ObjID}) ?tcheck(ir_SequenceDef, ObjType) ->
- get_field({ObjType,ObjID},bound).
-
-'_set_bound'({ObjType, ObjID}, EO_Value) ?tcheck(ir_SequenceDef, ObjType) ->
- SequenceDef = get_object({ObjType, ObjID}),
- New_SequenceDef =
- SequenceDef#ir_SequenceDef{type = {tk_sequence,
- SequenceDef#ir_SequenceDef.type,
- SequenceDef#ir_SequenceDef.bound},
- bound = EO_Value},
- set_object(New_SequenceDef).
-
-'_get_element_type'({ObjType, ObjID}) ?tcheck(ir_SequenceDef, ObjType) ->
- get_field({ObjType,ObjID},element_type).
-
-'_get_element_type_def'({ObjType, ObjID}) ?tcheck(ir_SequenceDef, ObjType) ->
- get_field({ObjType,ObjID},element_type_def).
-
-'_set_element_type_def'({ObjType, ObjID}, EO_Value)
- ?tcheck(ir_SequenceDef, ObjType) ->
- SequenceDef = get_object({ObjType, ObjID}),
- New_type = {tk_sequence,
- EO_Value#ir_IDLType.type,
- SequenceDef#ir_SequenceDef.bound},
- New_SequenceDef = SequenceDef#ir_SequenceDef{type = New_type,
- element_type = New_type,
- element_type_def = EO_Value},
- set_object(New_SequenceDef).
diff --git a/lib/orber/src/orber_ifr_stringdef.erl b/lib/orber/src/orber_ifr_stringdef.erl
deleted file mode 100644
index b206a218c1..0000000000
--- a/lib/orber/src/orber_ifr_stringdef.erl
+++ /dev/null
@@ -1,75 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_stringdef.erl
-%% Purpose : Code for Stringdef
-%%----------------------------------------------------------------------
-
--module(orber_ifr_stringdef).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- '_get_type'/1,
- '_get_bound'/1,
- '_set_bound'/2
- ]).
-
--import(orber_ifr_utils,[get_field/2,
- set_field/3
- ]).
-
--include("orber_ifr.hrl").
-
-%%%======================================================================
-%%% StringDef (IDLType(IRObject))
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType,ObjID}) ?tcheck(ir_StringDef, ObjType) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType,ObjID}).
-
-destroy({ObjType, ObjID}) ?tcheck(ir_StringDef, ObjType) ->
- F = fun() -> ObjList = cleanup_for_destroy({ObjType, ObjID}),
- orber_ifr_irobject:destroy([{ObjType,ObjID} | ObjList])
- end,
- orber_ifr_utils:ifr_transaction_write(F).
-
-cleanup_for_destroy({ObjType,ObjID}) ?tcheck(ir_StringDef, ObjType) ->
- orber_ifr_idltype:cleanup_for_destroy({ObjType,ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IDLType
-
-'_get_type'({ObjType, ObjID}) ?tcheck(ir_StringDef, ObjType) ->
- orber_ifr_idltype:'_get_type'({ObjType, ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-'_get_bound'({ObjType, ObjID}) ?tcheck(ir_StringDef, ObjType) ->
- get_field({ObjType,ObjID},bound).
-
-'_set_bound'({ObjType, ObjID}, EO_Value)
- ?tcheck(ir_StringDef, ObjType) ->
- set_field({ObjType, ObjID}, bound, EO_Value).
diff --git a/lib/orber/src/orber_ifr_structdef.erl b/lib/orber/src/orber_ifr_structdef.erl
deleted file mode 100644
index 3a9cde353e..0000000000
--- a/lib/orber/src/orber_ifr_structdef.erl
+++ /dev/null
@@ -1,156 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_structdef.erl
-%% Purpose : Code for Structdef
-%%----------------------------------------------------------------------
-
--module(orber_ifr_structdef).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- '_get_id'/1,
- '_set_id'/2,
- '_get_name'/1,
- '_set_name'/2,
- '_get_version'/1,
- '_set_version'/2,
- '_get_defined_in'/1,
- '_get_absolute_name'/1,
- '_get_containing_repository'/1,
- describe/1,
- move/4,
- '_get_type'/1,
- '_get_members'/1,
- '_set_members'/2
- ]).
-
--import(orber_ifr_utils,[get_field/2,get_object/1,set_object/1]).
--import(lists,[map/2]).
-
--include("orber_ifr.hrl").
--include("ifr_objects.hrl").
--include_lib("orber/include/ifr_types.hrl").
-
-%%%======================================================================
-%%% StructDef (TypedefDef(Contained(IRObject), IDLType(IRObject)))
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType, ObjID}) ?tcheck(ir_StructDef, ObjType) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType,ObjID}).
-
-destroy({ObjType, ObjID}) ?tcheck(ir_StructDef, ObjType) ->
- F = fun() -> ObjList = cleanup_for_destroy({ObjType, ObjID}),
- orber_ifr_irobject:destroy([{ObjType, ObjID} | ObjList])
- end,
- orber_ifr_utils:ifr_transaction_write(F).
-
-cleanup_for_destroy({ObjType,ObjID}) ?tcheck(ir_StructDef, ObjType) ->
- map(fun(X) -> orber_ifr_idltype:cleanup_for_destroy(
- X#structmember.type_def)
- end,
- '_get_members'({ObjType, ObjID})
- ) ++
- orber_ifr_typedef:cleanup_for_destroy({ObjType,ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from Contained
-
-'_get_id'({ObjType, ObjID}) ?tcheck(ir_StructDef, ObjType) ->
- orber_ifr_contained:'_get_id'({ObjType,ObjID}).
-
-'_set_id'({ObjType, ObjID},EO_Value) ?tcheck(ir_StructDef,ObjType) ->
- orber_ifr_contained:'_set_id'({ObjType,ObjID},EO_Value).
-
-'_get_name'({ObjType, ObjID}) ?tcheck(ir_StructDef, ObjType) ->
- orber_ifr_contained:'_get_name'({ObjType,ObjID}).
-
-'_set_name'({ObjType, ObjID}, EO_Value) ?tcheck(ir_StructDef, ObjType) ->
- orber_ifr_contained:'_set_name'({ObjType,ObjID}, EO_Value).
-
-'_get_version'({ObjType, ObjID}) ?tcheck(ir_StructDef, ObjType) ->
- orber_ifr_contained:'_get_version'({ObjType,ObjID}).
-
-'_set_version'({ObjType, ObjID}, EO_Value) ?tcheck(ir_StructDef, ObjType) ->
- orber_ifr_contained:'_set_version'({ObjType,ObjID},EO_Value).
-
-'_get_defined_in'({ObjType, ObjID}) ?tcheck(ir_StructDef, ObjType) ->
- orber_ifr_contained:'_get_defined_in'({ObjType,ObjID}).
-
-'_get_absolute_name'({ObjType, ObjID}) ?tcheck(ir_StructDef, ObjType) ->
- orber_ifr_contained:'_get_absolute_name'({ObjType,ObjID}).
-
-'_get_containing_repository'({ObjType, ObjID}) ?tcheck(ir_StructDef,ObjType) ->
- orber_ifr_contained:'_get_containing_repository'({ObjType,ObjID}).
-
-describe({ObjType, ObjID}) ?tcheck(ir_StructDef, ObjType) ->
- orber_ifr_contained:describe({ObjType,ObjID}).
-
-move({ObjType, ObjID}, New_container, New_name, New_version)
- ?tcheck(ir_StructDef, ObjType) ->
- orber_ifr_contained:move({ObjType,ObjID},New_container,New_name,
- New_version).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IDLType
-
-'_get_type'({ObjType, ObjID}) ?tcheck(ir_StructDef, ObjType) ->
- orber_ifr_idltype:'_get_type'({ObjType, ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-'_get_members'({ObjType, ObjID}) ?tcheck(ir_StructDef, ObjType) ->
- get_field({ObjType,ObjID},members).
-
-'_set_members'({ObjType, ObjID}, EO_Value) ?tcheck(ir_StructDef, ObjType) ->
- StructDef = get_object({ObjType, ObjID}),
- Members = map(fun(Structmember) -> Structmember#structmember{type=tk_void}
- end, EO_Value),
- New_StructDef =
- StructDef#ir_StructDef{type =
- {tk_struct,
- StructDef#ir_StructDef.id,
- StructDef#ir_StructDef.name,
- map(fun(#structmember{name=Name,type=Type}) ->
- {Name,Type}
- end,
- EO_Value)},
- members=Members},
- set_object(New_StructDef).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/orber/src/orber_ifr_typecode.erl b/lib/orber/src/orber_ifr_typecode.erl
deleted file mode 100644
index 52263be719..0000000000
--- a/lib/orber/src/orber_ifr_typecode.erl
+++ /dev/null
@@ -1,108 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_typecode.erl
-%% Purpose : Code for Typecode
-%%----------------------------------------------------------------------
-
-%%% NOTE:
-%%% Only make_typcode is for real here. All of the TypeCode interfaces
-%%% specified in the IDL specification needs to be implemented.
-%%%
-
--module(orber_ifr_typecode).
-
--export([
- equal/2,
- kind/1,
- id/1,
- name/1,
- member_count/1,
- member_name/2,
- member_type/2,
- member_label/2,
- discriminator_type/1,
- default_index/1,
- '_length'/1,
- content_type/1,
- param_count/1,
- parameter/2
- ]).
-
--import(orber_ifr_utils,[get_field/2]).
-
--include("orber_ifr.hrl").
--include("ifr_objects.hrl").
--include_lib("orber/include/corba.hrl").
-
-
-
-%%%----------------------------------------------------------------------
-%%% Inherited interfaces
-
-%% none %%
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-equal({ObjType, ObjID}, {Tc_ObjType, Tc_ObjID})
-?tcheck(ir_TypeCode, ObjType) ->
- get_field({ObjType,ObjID},kind) == get_field({Tc_ObjType,Tc_ObjID},kind).
-
-kind({ObjType, ObjID}) ->
- {ok, {ObjType, ObjID}}.
-
-id({ObjType, ObjID}) ->
- {ok, {ObjType, ObjID}}.
-
-name({ObjType, ObjID}) ->
- {ok, {ObjType, ObjID}}.
-
-member_count({ObjType, ObjID}) ->
- {ok, {ObjType, ObjID}}.
-
-member_name({ObjType, ObjID}, _Index) ->
- {ok, {ObjType, ObjID}}.
-
-member_type({ObjType, ObjID}, _Index) ->
- {ok, {ObjType, ObjID}}.
-
-member_label({ObjType, ObjID}, _Index) ->
- {ok, {ObjType, ObjID}}.
-
-discriminator_type({ObjType, ObjID}) ->
- {ok, {ObjType, ObjID}}.
-
-default_index({ObjType, ObjID}) ->
- {ok, {ObjType, ObjID}}.
-
-'_length'({ObjType, ObjID}) ->
- {ok, {ObjType, ObjID}}.
-
-content_type({ObjType, ObjID}) ->
- {ok, {ObjType, ObjID}}.
-
-param_count({ObjType, ObjID}) ->
- {ok, {ObjType, ObjID}}.
-
-parameter({ObjType, ObjID}, _Index) ->
- {ok, {ObjType, ObjID}}.
diff --git a/lib/orber/src/orber_ifr_typedef.erl b/lib/orber/src/orber_ifr_typedef.erl
deleted file mode 100644
index 3441d7e7af..0000000000
--- a/lib/orber/src/orber_ifr_typedef.erl
+++ /dev/null
@@ -1,125 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_typedef.erl
-%% Purpose : Code for Typedef
-%%----------------------------------------------------------------------
-
--module(orber_ifr_typedef).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- '_get_id'/1,
- '_set_id'/2,
- '_get_name'/1,
- '_set_name'/2,
- '_get_version'/1,
- '_set_version'/2,
- '_get_defined_in'/1,
- '_get_absolute_name'/1,
- '_get_containing_repository'/1,
- describe/1,
- move/4,
- '_get_type'/1
- ]).
-
-
--include("orber_ifr.hrl").
-
-%%%======================================================================
-%%% TypedefDef (Contained(IRObject), IDLType(IRObject))
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType, ObjID}) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType, ObjID}).
-
-%%% Note, that the destroy function is meant to be called within a
-%%% transaction called in the destroy function of an object which
-%%% inherits from TypedefDef. A TypedefDef should only be destroyed by
-%%% destroying the object that inherits from a TypedefDef. An attempt
-%%% to call this function in user code will result in unpredictable
-%%% results.
-
-%%% Don't type check the object reference. We need to be able to
-%%% handle several types of objects that inherit from TypedefDef.
-
-destroy(TypedefDef_objref) ->
- F = fun() -> ObjList = cleanup_for_destroy(TypedefDef_objref),
- orber_ifr_irobject:destroy([TypedefDef_objref | ObjList])
- end,
- orber_ifr_utils:ifr_transaction_write(F).
-
-cleanup_for_destroy(TypedefDef_objref) ->
- orber_ifr_contained:cleanup_for_destroy(TypedefDef_objref) ++
- orber_ifr_idltype:cleanup_for_destroy(TypedefDef_objref).
-
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from Contained
-
-'_get_id'({ObjType, ObjID}) ->
- orber_ifr_contained:'_get_id'({ObjType,ObjID}).
-
-'_set_id'({ObjType, ObjID}, EO_Value) ->
- orber_ifr_contained:'_set_id'({ObjType,ObjID},EO_Value).
-
-'_get_name'({ObjType, ObjID}) ->
- orber_ifr_contained:'_get_name'({ObjType,ObjID}).
-
-'_set_name'({ObjType, ObjID}, EO_Value) ->
- orber_ifr_contained:'_set_name'({ObjType,ObjID}, EO_Value).
-
-'_get_version'({ObjType, ObjID}) ->
- orber_ifr_contained:'_get_version'({ObjType,ObjID}).
-
-'_set_version'({ObjType, ObjID}, EO_Value) ->
- orber_ifr_contained:'_set_version'({ObjType,ObjID},EO_Value).
-
-'_get_defined_in'({ObjType,ObjID}) ->
- orber_ifr_contained:'_get_defined_in'({ObjType,ObjID}).
-
-'_get_absolute_name'({ObjType, ObjID}) ->
- orber_ifr_contained:'_get_absolute_name'({ObjType,ObjID}).
-
-'_get_containing_repository'({ObjType,ObjID}) ->
- orber_ifr_contained:'_get_containing_repository'({ObjType,ObjID}).
-
-describe({ObjType, ObjID}) ->
- orber_ifr_contained:describe({ObjType,ObjID}).
-
-move({ObjType, ObjID}, New_container, New_name, New_version) ->
- orber_ifr_contained:move({ObjType,ObjID},New_container,New_name,
- New_version).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IDLType
-
-'_get_type'({ObjType, ObjID}) ->
- orber_ifr_idltype:'_get_type'({ObjType, ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-%%% none %%
diff --git a/lib/orber/src/orber_ifr_uniondef.erl b/lib/orber/src/orber_ifr_uniondef.erl
deleted file mode 100644
index 64d55ee581..0000000000
--- a/lib/orber/src/orber_ifr_uniondef.erl
+++ /dev/null
@@ -1,176 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_uniondef.erl
-%% Purpose : Code for Uniondef
-%%----------------------------------------------------------------------
-
--module(orber_ifr_uniondef).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- '_get_id'/1,
- '_set_id'/2,
- '_get_name'/1,
- '_set_name'/2,
- '_get_version'/1,
- '_set_version'/2,
- '_get_defined_in'/1,
- '_get_absolute_name'/1,
- '_get_containing_repository'/1,
- describe/1,
- move/4,
- '_get_type'/1,
- '_get_discriminator_type'/1,
- '_get_discriminator_type_def'/1,
- '_set_discriminator_type_def'/2,
- '_get_members'/1,
- '_set_members'/2
- ]).
-
--import(orber_ifr_utils,[get_field/2,
- get_object/1,
- set_object/1
- ]).
-
--import(lists,[map/2]).
-
--include("orber_ifr.hrl").
--include("ifr_objects.hrl").
--include_lib("orber/include/ifr_types.hrl").
-
-%%%======================================================================
-%%% UnionDef (TypedefDef(Contained(IRObject), IDLType(IRObject)))
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType, ObjID}) ?tcheck(ir_UnionDef, ObjType) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType, ObjID}).
-
-destroy({ObjType, ObjID}) ?tcheck(ir_UnionDef, ObjType) ->
- F = fun() -> ObjList = cleanup_for_destroy({ObjType, ObjID}),
- orber_ifr_irobject:destroy([{ObjType, ObjID} | ObjList])
- end,
- orber_ifr_utils:ifr_transaction_write(F).
-
-cleanup_for_destroy({ObjType,ObjID}) ?tcheck(ir_UnionDef, ObjType) ->
- map(fun(X) -> orber_ifr_idltype:cleanup_for_destroy(
- X#unionmember.type_def)
- end,
- '_get_members'({ObjType, ObjID})
- ) ++
- orber_ifr_idltype:cleanup_for_destroy(
- '_get_discriminator_type_def'({ObjType,ObjID})) ++
- orber_ifr_typedef:cleanup_for_destroy({ObjType,ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from Contained
-
-'_get_id'({ObjType, ObjID}) ?tcheck(ir_UnionDef, ObjType) ->
- orber_ifr_contained:'_get_id'({ObjType,ObjID}).
-
-'_set_id'({ObjType, ObjID}, EO_Value) ?tcheck(ir_UnionDef, ObjType) ->
- orber_ifr_contained:'_set_id'({ObjType,ObjID},EO_Value).
-
-'_get_name'({ObjType, ObjID}) ?tcheck(ir_UnionDef, ObjType) ->
- orber_ifr_contained:'_get_name'({ObjType,ObjID}).
-
-'_set_name'({ObjType,ObjID},EO_Value) ?tcheck(ir_UnionDef,ObjType) ->
- orber_ifr_contained:'_set_name'({ObjType,ObjID}, EO_Value).
-
-'_get_version'({ObjType, ObjID}) ?tcheck(ir_UnionDef, ObjType) ->
- orber_ifr_contained:'_get_version'({ObjType,ObjID}).
-
-'_set_version'({ObjType, ObjID}, EO_Value) ?tcheck(ir_UnionDef, ObjType) ->
- orber_ifr_contained:'_set_version'({ObjType,ObjID},EO_Value).
-
-'_get_defined_in'({ObjType, ObjID}) ?tcheck(ir_UnionDef, ObjType) ->
- orber_ifr_contained:'_get_defined_in'({ObjType,ObjID}).
-
-'_get_absolute_name'({ObjType, ObjID}) ?tcheck(ir_UnionDef,ObjType) ->
- orber_ifr_contained:'_get_absolute_name'({ObjType,ObjID}).
-
-'_get_containing_repository'({ObjType, ObjID}) ?tcheck(ir_UnionDef, ObjType) ->
- orber_ifr_contained:'_get_containing_repository'({ObjType,ObjID}).
-
-describe({ObjType, ObjID}) ?tcheck(ir_UnionDef, ObjType) ->
- orber_ifr_contained:describe({ObjType,ObjID}).
-
-move({ObjType, ObjID}, New_container, New_name, New_version)
- ?tcheck(ir_UnionDef, ObjType) ->
- orber_ifr_contained:move({ObjType,ObjID}, New_container, New_name,
- New_version).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IDLType
-
-'_get_type'({ObjType, ObjID}) ?tcheck(ir_UnionDef, ObjType) ->
- orber_ifr_idltype:'_get_type'({ObjType, ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-'_get_discriminator_type'({ObjType, ObjID}) ?tcheck(ir_UnionDef, ObjType) ->
- get_field({ObjType,ObjID},discriminator_type).
-
-'_get_discriminator_type_def'({ObjType, ObjID}) ?tcheck(ir_UnionDef,ObjType) ->
- get_field({ObjType,ObjID},discriminator_type_def).
-
-'_set_discriminator_type_def'({ObjType, ObjID}, EO_Value)
- ?tcheck(ir_UnionDef, ObjType) ->
- UnionDef = get_object({ObjType, ObjID}),
- NewUnionDef = UnionDef#ir_UnionDef{type = EO_Value#ir_IDLType.type,
- discriminator_type =
- EO_Value#ir_IDLType.type,
- discriminator_type_def = EO_Value},
- set_object(NewUnionDef).
-
-'_get_members'({ObjType, ObjID}) ?tcheck(ir_UnionDef, ObjType) ->
- get_field({ObjType,ObjID},members).
-
-%%% *** What should the value of the discriminator-typecode be when
-%%% updating the type attribute? (CORBA 2.0, p 6-20). For now we just
-%%% leave it unchanged, but this is perhaps not the right thing to do.
-
--define(discr_tc(TC),element(4,TC)).
--define(default(TC),element(5,TC)).
-
-'_set_members'({ObjType, ObjID}, EO_Value) ?tcheck(ir_UnionDef, ObjType) ->
- UnionDef = get_object({ObjType, ObjID}),
- Members=map(fun(Unionmember) -> Unionmember#unionmember{type=tk_void} end,
- EO_Value),
- NewUnionDef = UnionDef#ir_UnionDef{type =
- {tk_union,
- UnionDef#ir_UnionDef.id,
- UnionDef#ir_UnionDef.name,
- ?discr_tc(UnionDef#ir_UnionDef.type),
- ?default(UnionDef#ir_UnionDef.type),
- map(fun(#unionmember{name=Name,
- label=Label,
- type=Type}) ->
- {Label,Name,Type}
- end,
- EO_Value)},
- members = Members},
- set_object(NewUnionDef).
diff --git a/lib/orber/src/orber_ifr_utils.erl b/lib/orber/src/orber_ifr_utils.erl
deleted file mode 100644
index 95a1d504bc..0000000000
--- a/lib/orber/src/orber_ifr_utils.erl
+++ /dev/null
@@ -1,437 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_utils.erl
-%% Purpose : Common function for the Interface Repository
-%%----------------------------------------------------------------------
-
--module(orber_ifr_utils).
-
--export([
- select/2,
- index/2,
- construct/3,
- get_object/1,
- set_object/1,
- get_field/2,
- set_field/3,
- write_result/1,
- read_result/1,
- ifr_transaction_read/1,
- ifr_transaction_write/1,
- ifr_transaction_read_write/1,
- makeref/1,
- unique/0,
- existence_check/2,
- existence_check/3,
- create_repository/0,
- init_DB/2, init_DB/3
- ]).
-
--include_lib("orber/include/corba.hrl").
--include("orber_ifr.hrl").
--include("ifr_objects.hrl").
-
-
-%%======================================================================
-%% Internal stuff
-
-%%----------------------------------------------------------------------
-%% Make a record selection.
-%%
-%% This code *must* be amended whenever a new record is added in the
-%% files ifr_objects.hrl or ../include/ifr_types.hrl
-
-select(Record,Field) when is_record(Record,ir_IRObject) ->
- select(Record,record_info(fields,ir_IRObject),Field);
-select(Record,Field) when is_record(Record,ir_Contained) ->
- select(Record,record_info(fields,ir_Contained),Field);
-select(Record,Field) when is_record(Record,ir_Container) ->
- select(Record,record_info(fields,ir_Container),Field);
-select(Record,Field) when is_record(Record,ir_IDLType) ->
- select(Record,record_info(fields,ir_IDLType),Field);
-select(Record,Field) when is_record(Record,ir_Repository) ->
- select(Record,record_info(fields,ir_Repository),Field);
-select(Record,Field) when is_record(Record,ir_ModuleDef) ->
- select(Record,record_info(fields,ir_ModuleDef),Field);
-select(Record,Field) when is_record(Record,ir_ConstantDef) ->
- select(Record,record_info(fields,ir_ConstantDef),Field);
-select(Record,Field) when is_record(Record,ir_TypedefDef) ->
- select(Record,record_info(fields,ir_TypedefDef),Field);
-select(Record,Field) when is_record(Record,ir_StructDef) ->
- select(Record,record_info(fields,ir_StructDef),Field);
-select(Record,Field) when is_record(Record,ir_UnionDef) ->
- select(Record,record_info(fields,ir_UnionDef),Field);
-select(Record,Field) when is_record(Record,ir_EnumDef) ->
- select(Record,record_info(fields,ir_EnumDef),Field);
-select(Record,Field) when is_record(Record,ir_AliasDef) ->
- select(Record,record_info(fields,ir_AliasDef),Field);
-select(Record,Field) when is_record(Record,ir_PrimitiveDef) ->
- select(Record,record_info(fields,ir_PrimitiveDef),Field);
-select(Record,Field) when is_record(Record,ir_StringDef) ->
- select(Record,record_info(fields,ir_StringDef),Field);
-select(Record,Field) when is_record(Record,ir_WstringDef) ->
- select(Record,record_info(fields,ir_WstringDef),Field);
-select(Record,Field) when is_record(Record,ir_SequenceDef) ->
- select(Record,record_info(fields,ir_SequenceDef),Field);
-select(Record,Field) when is_record(Record,ir_ArrayDef) ->
- select(Record,record_info(fields,ir_ArrayDef),Field);
-select(Record,Field) when is_record(Record,ir_ExceptionDef) ->
- select(Record,record_info(fields,ir_ExceptionDef),Field);
-select(Record,Field) when is_record(Record,ir_AttributeDef) ->
- select(Record,record_info(fields,ir_AttributeDef),Field);
-select(Record,Field) when is_record(Record,ir_OperationDef) ->
- select(Record,record_info(fields,ir_OperationDef),Field);
-select(Record,Field) when is_record(Record,ir_InterfaceDef) ->
- select(Record,record_info(fields,ir_InterfaceDef),Field);
-select(Record,Field) when is_record(Record,ir_FixedDef) ->
- select(Record,record_info(fields,ir_FixedDef),Field);
-select([],_) -> [];
-select(Record,Field) ->
- orber:dbg("[~p] orber_ifr_utils:select(~p, ~p);~n"
- "Unknown Record Type~n", [?LINE, Record,Field], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO}).
-
--define(ELEMENT_OFFSET, 2).
-
-select(Record,Fields,Field) ->
- Index = index(Fields,Field),
- element(?ELEMENT_OFFSET + Index, Record).
-
-index(List,Element) ->
- index(List,Element,0).
-
-index([H|_T],Element,Index) when H == Element ->
- Index;
-index([_H|T],Element,Index) ->
- index(T,Element,Index+1);
-index([],Element,Index) ->
- orber:dbg("[~p] orber_ifr_utils:index(~p, ~p);~n"
- "Index error.~n", [?LINE, Element, Index], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO}).
-
-%%%----------------------------------------------------------------------
-%%% Construct a record.
-%%%
-%%% This code *must* be amended whenever a new record is added in the
-%%% files ifr_objects.hrl or ../include/ifr_types.hrl
-
-construct(Record,Field,Value) when is_record(Record,ir_IRObject) ->
- construct(Record,record_info(fields,ir_IRObject),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_Contained) ->
- construct(Record,record_info(fields,ir_Contained),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_Container) ->
- construct(Record,record_info(fields,ir_Container),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_IDLType) ->
- construct(Record,record_info(fields,ir_IDLType),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_Repository) ->
- construct(Record,record_info(fields,ir_Repository),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_ModuleDef) ->
- construct(Record,record_info(fields,ir_ModuleDef),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_ConstantDef) ->
- construct(Record,record_info(fields,ir_ConstantDef),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_TypedefDef) ->
- construct(Record,record_info(fields,ir_TypedefDef),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_StructDef) ->
- construct(Record,record_info(fields,ir_StructDef),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_UnionDef) ->
- construct(Record,record_info(fields,ir_UnionDef),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_EnumDef) ->
- construct(Record,record_info(fields,ir_EnumDef),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_AliasDef) ->
- construct(Record,record_info(fields,ir_AliasDef),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_PrimitiveDef) ->
- construct(Record,record_info(fields,ir_PrimitiveDef),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_StringDef) ->
- construct(Record,record_info(fields,ir_StringDef),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_WstringDef) ->
- construct(Record,record_info(fields,ir_WstringDef),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_SequenceDef) ->
- construct(Record,record_info(fields,ir_SequenceDef),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_ArrayDef) ->
- construct(Record,record_info(fields,ir_ArrayDef),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_ExceptionDef) ->
- construct(Record,record_info(fields,ir_ExceptionDef),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_AttributeDef) ->
- construct(Record,record_info(fields,ir_AttributeDef),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_OperationDef) ->
- construct(Record,record_info(fields,ir_OperationDef),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_InterfaceDef) ->
- construct(Record,record_info(fields,ir_InterfaceDef),Field,Value);
-construct(Record,Field,Value) when is_record(Record,ir_FixedDef) ->
- construct(Record,record_info(fields,ir_FixedDef),Field,Value);
-construct(Record,Field,Value) ->
- orber:dbg("[~p] orber_ifr_utils:construct(~p, ~p, ~p);~n"
- "Unknown Record Type~n",
- [?LINE, Record,Field,Value], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO}).
-
-construct(Record,Fields,Field,Value) ->
- Index = index(Fields,Field),
- setelement(?ELEMENT_OFFSET + Index,Record,Value).
-
-%%%----------------------------------------------------------------------
-%%% Read an object from the database
-
-get_object(Objref) ->
-%%% Use mnesia:dirty_read/1. It is much faster than doing a transaction.
- case mnesia:dirty_read(Objref) of
- [Res] ->
- Res;
- [] ->
- [];
- Other ->
- orber:dbg("[~p] orber_ifr_utils:get_object(~p);~n",
- [?LINE, Other], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO})
- end.
-%%% This is the old code, with a transaction. We might have to revert back
-%%% to this at some future time...
-%% _F = ?read_function(Objref),
-%% read_result(ifr_transaction_read(_F)).
-
-%%%----------------------------------------------------------------------
-%%% Write an object to the database
-
-set_object(Object) ->
- _F = fun() -> mnesia:write(Object) end,
- write_result(ifr_transaction_write(_F)).
-
-%%%----------------------------------------------------------------------
-%%% Get the value of a field in a record in the DB
-
-get_field(Objref,FieldName) ->
- Object = get_object(Objref),
- select(Object,FieldName).
-
-%%%----------------------------------------------------------------------
-%%% Atomically set the value of a field in a record in the DB
-
-set_field(Objref,FieldName,Value) ->
- _F = fun() -> Object = get_object(Objref),
- New_object = construct(Object,FieldName,Value),
- mnesia:write(New_object)
- end,
- write_result(ifr_transaction_write(_F)).
-
-
-%%%----------------------------------------------------------------------
-%%% Check a write transaction
-
-write_result({atomic,ok}) -> ok;
-write_result(Wres) ->
- orber:dbg("[~p] orber_ifr_utils:write_result(~p);~n",
- [?LINE, Wres], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO}).
-
-%%%----------------------------------------------------------------------
-%%% Extract the data from a read
-
-read_result({atomic,[Qres]}) -> Qres;
-read_result({atomic,[]}) -> [];
-read_result(Qres) ->
- orber:dbg("[~p] orber_ifr_utils:read_result(~p);~n",
- [?LINE, Qres], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO}).
-
-%%%----------------------------------------------------------------------
-%%% Execute a transaction or a dirty read/write.
-%%%
-%%% Since nested transctions will upgrade the inner activity to the
-%%% same kind as the outer, we cannot use the check the result in the
-%%% above simplistic manner. Therefore we will not mix transaction
-%%% with async_dirty (or any of the other transaction-like
-%%% activities). A rather extensive rewrite of the query extraction
-%%% code must be done first.
-
-ifr_transaction_read(Fun) -> % read synchronously
- Tr = mnesia:transaction(Fun),
- {atomic, _} = Tr,
- Tr.
-ifr_transaction_write(Fun) -> % write synchronously
- Tr = mnesia:transaction(Fun),
- {atomic, _} = Tr,
- Tr.
-ifr_transaction_read_write(Fun) -> % write synchronously
- Tr = mnesia:transaction(Fun),
- {atomic, _} = Tr,
- Tr.
-
-%%%----------------------------------------------------------------------
-%%% Make an object reference from an object
-
-makeref(Obj) ->
- [ObjType, ObjID | _] = tuple_to_list(Obj),
- {ObjType, ObjID}.
-
-%%%----------------------------------------------------------------------
-%%% Make a unique tag.
-%%%
-%%% The call to term_to_binary is made to hide the representation of the
-%%% unique tag. I do this because the tuple generated takes a lot of space
-%%% when I dump the database. A binary is simply printed as #Bin, which
-%%% is much less obtrusive.
-
-unique() -> term_to_binary({node(), {erlang:system_time(),
- erlang:unique_integer()}}).
-
-%%%----------------------------------------------------------------------
-%%% Check for an existing object with the Id of the object which is
-%%% about to be created.
-
-existence_check({ObjType, ObjID}, Id) ->
- Rep = case ObjType of
- ir_Repository ->
- {ObjType, ObjID};
- _ ->
- orber_ifr_contained:'_get_containing_repository'({ObjType,
- ObjID})
- end,
- case orber_ifr_repository:lookup_id(Rep, Id) of
- [] ->
- ok;
- What ->
- orber:dbg("[~p] orber_ifr_utils:existence_check(~p, ~p, ~p);~n"
- "Name clash(?): ~p",
- [?LINE, ObjType, ObjID, Id, What], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO})
- end.
-
-existence_check(Id, Tab, FieldNum) ->
- case mnesia:dirty_index_read(Tab, Id, FieldNum) of
- [] ->
- ok;
- What ->
- orber:dbg("[~p] orber_ifr_utils:existence_check(~p, ~p, ~p);~n"
- "Name clash(?): ~p",
- [?LINE, Id, Tab, FieldNum, What], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO})
- end.
-
-%%======================================================================
-%% Database initialization
-
-init_DB(Timeout, Options) ->
- init_DB(Timeout, Options, false).
-
-init_DB(Timeout, Options, LightIFR) ->
- Func = case Options of
- {localCopy, IFR_storage_type} when LightIFR == true ->
- ?ifr_light_record_tuple_list_local(IFR_storage_type);
- {localCopy, IFR_storage_type} ->
- ?ifr_record_tuple_list_local(IFR_storage_type);
- _ when LightIFR == true ->
- ?ifr_light_record_tuple_list(Options);
- _ ->
- ?ifr_record_tuple_list(Options)
- end,
- create_tables(Func),
- Wait = wait_for_tables(LightIFR, Timeout),
- db_error_check([Wait],"Database table waiting failed.").
-
-wait_for_tables(true, Timeout) ->
- mnesia:wait_for_tables(?ifr_light_object_list, Timeout);
-wait_for_tables(_, Timeout) ->
- mnesia:wait_for_tables(?ifr_object_list, Timeout).
-
-db_error_check(Checkval,_Message) ->
- case lists:any(fun(X) -> X/= ok end, Checkval) of
- true ->
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO});
- false ->
- ok
- end.
-
-create_tables([{T,F}|Rest]) ->
- case F() of
- ok ->
- create_tables2(Rest);
- {aborted,{already_exists,_}} ->
- exit({error, "Orber Mnesia Table(s) already exist. Cannot install Orber."});
- Reason ->
- orber:dbg("[~p] orber_ifr_utils:create_tables(~p);~n"
- "Failed to create the Mnesia table.~n"
- "Reason: ~p", [?LINE, T, Reason], ?DEBUG_LEVEL),
- exit({error, "Unable to create Mnesia Table"})
- end.
-
-create_tables2([]) ->
- ok;
-create_tables2([{T,F}|Rest]) ->
- case F() of
- ok ->
- create_tables2(Rest);
- Reason ->
- orber:dbg("[~p] orber_ifr_utils:create_tables2(~p);~n"
- "Failed to create the Mnesia table.~n"
- "Reason: ~p", [?LINE, T, Reason], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO})
- end.
-
-
-%%%----------------------------------------------------------------------
-%%% Create an interface repository. This function should only be called
-%%% once, after the database has been set up and initialized.
-
-create_repository() ->
- case orber:light_ifr() of
- true ->
- #orber_light_ifr_ref{data = #lightdata{scope = "",
- id = ""}};
- false ->
- _R = fun() ->
- Pat = mnesia:table_info(ir_Repository, wild_pattern),
- case [X#ir_Repository.ir_Internal_ID ||
- X <- mnesia:match_object(Pat)] of
- [] ->
- PrimitiveDefs = create_primitivedefs(),
- New = #ir_Repository{ir_Internal_ID = unique(),
- def_kind = dk_Repository,
- contents = [],
- primitivedefs = PrimitiveDefs},
- mnesia:write(New),
- {ir_Repository,New#ir_Repository.ir_Internal_ID};
- [Rep_ID] ->
- {ir_Repository,Rep_ID};
- Error ->
- mnesia:abort(Error)
- end
- end,
- case mnesia:transaction(_R) of
- {atomic, RepRef} ->
- RepRef;
- {aborted, Error} ->
- orber:dbg("[~p] orber_ifr_utils:create_repository() failed;~n"
- "Reason: ~p", [?LINE, Error], ?DEBUG_LEVEL),
- corba:raise(#'INTF_REPOS'{completion_status=?COMPLETED_NO})
- end
- end.
-
-create_primitivedefs() ->
- lists:map(fun(Pk) ->
- orber_ifr_repository:create_primitivedef(Pk, false)
- end,
- [pk_void,pk_short,pk_long,pk_longlong,pk_ulonglong,pk_ushort,pk_ulong,
- pk_float,pk_double,pk_boolean,pk_char,pk_wchar,pk_octet,pk_any,
- pk_TypeCode,pk_Principal,pk_string,pk_wstring,pk_objref]).
-
-
diff --git a/lib/orber/src/orber_ifr_wstringdef.erl b/lib/orber/src/orber_ifr_wstringdef.erl
deleted file mode 100644
index 2ff7d84c7a..0000000000
--- a/lib/orber/src/orber_ifr_wstringdef.erl
+++ /dev/null
@@ -1,73 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_ifr_wstringdef.erl
-%% Description :
-%%
-%%----------------------------------------------------------------------
--module(orber_ifr_wstringdef).
-
--export(['_get_def_kind'/1,
- destroy/1,
- cleanup_for_destroy/1, %not in CORBA 2.0
- '_get_type'/1,
- '_get_bound'/1,
- '_set_bound'/2]).
-
--import(orber_ifr_utils, [get_field/2,
- set_field/3]).
-
--include("orber_ifr.hrl").
-
-%%%======================================================================
-%%% WstringDef (IDLType(IRObject))
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IRObject
-
-'_get_def_kind'({ObjType,ObjID}) ?tcheck(ir_WstringDef, ObjType) ->
- orber_ifr_irobject:'_get_def_kind'({ObjType,ObjID}).
-
-destroy({ObjType, ObjID}) ?tcheck(ir_WstringDef, ObjType) ->
- F = fun() -> ObjList = cleanup_for_destroy({ObjType, ObjID}),
- orber_ifr_irobject:destroy([{ObjType,ObjID} | ObjList])
- end,
- orber_ifr_utils:ifr_transaction_write(F).
-
-cleanup_for_destroy({ObjType,ObjID}) ?tcheck(ir_WstringDef, ObjType) ->
- orber_ifr_idltype:cleanup_for_destroy({ObjType,ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Interfaces inherited from IDLType
-
-'_get_type'({ObjType, ObjID}) ?tcheck(ir_WstringDef, ObjType) ->
- orber_ifr_idltype:'_get_type'({ObjType, ObjID}).
-
-%%%----------------------------------------------------------------------
-%%% Non-inherited interfaces
-
-'_get_bound'({ObjType, ObjID}) ?tcheck(ir_WstringDef, ObjType) ->
- get_field({ObjType,ObjID},bound).
-
-'_set_bound'({ObjType, ObjID}, EO_Value)
- ?tcheck(ir_WstringDef, ObjType) ->
- set_field({ObjType, ObjID}, bound, EO_Value).
diff --git a/lib/orber/src/orber_iiop.erl b/lib/orber/src/orber_iiop.erl
deleted file mode 100644
index 8cb39c7365..0000000000
--- a/lib/orber/src/orber_iiop.erl
+++ /dev/null
@@ -1,551 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_iiop.erl
-%% Description:
-%% This file contains the interface to the iiop operations
-%%
-%%-----------------------------------------------------------------
--module(orber_iiop).
-
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
--behaviour(supervisor).
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([start_sup/1, request/8, locate/4]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([init/1, terminate/2, handle_call/3]).
-
-%%-----------------------------------------------------------------
-%% Internal defines
-%%-----------------------------------------------------------------
--define(DEBUG_LEVEL, 7).
-
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: start_sup/1
-%%-----------------------------------------------------------------
-start_sup(Opts) ->
- supervisor:start_link({local, orber_iiop_sup}, ?MODULE,
- {orber_iiop_sup, Opts}).
-
-%%%-----------------------------------------------------------------
-%%% Func: connect/1
-%%%-----------------------------------------------------------------
-%connect(OrbName) ->
-% orber_iiop_net:connect(OrbName).
-
-%%%-----------------------------------------------------------------
-%%% Func: request/5
-%%%-----------------------------------------------------------------
-request({Host, Port, InitObjkey, Index, TaggedProfile, HostData},
- Op, Parameters, TypeCodes, ResponseExpected, Timeout, IOR, UserCtx) ->
- {{Proxy, SysCtx, Interceptors, LocalInterface}, ObjKey, Version} =
- connect(Host, Port, InitObjkey, Timeout, [Index], HostData,
- TaggedProfile, IOR, UserCtx),
- Ctx = add_user_context(SysCtx, UserCtx),
- RequestId = orber_request_number:get(),
- Env = #giop_env{interceptors = Interceptors, type = out,
- flags = orber_env:get_flags(), host = LocalInterface,
- version = Version, ctx = Ctx, request_id = RequestId, op = Op,
- parameters = Parameters, tc = TypeCodes, objkey = ObjKey,
- response_expected = ResponseExpected},
- Message = encode_request(Env),
- case catch orber_iiop_outproxy:request(Proxy, ResponseExpected, Timeout,
- Message, RequestId) of
- {'EXCEPTION', MsgExc} ->
- corba:raise(MsgExc);
- _ when ResponseExpected == false ->
- ok;
- {reply, ReplyHeader, Rest, Len, ByteOrder, Bytes} ->
- case catch decode_reply_body(Interceptors, ObjKey, Op, ReplyHeader,
- Version, TypeCodes, Rest, Len, ByteOrder,
- Bytes) of
- {'EXCEPTION', DecodeException} ->
- %% We cannot log this exception since it may be a correct exception.
- corba:raise(DecodeException);
- {'EXIT', message_error} ->
- orber:dbg("[~p] orber_iiop:request(reply, ~p, ~p, ~p)~n"
- "Got exit(message_error)",
- [?LINE, Rest, Version, TypeCodes], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE});
- {'EXIT', Why} ->
- orber:dbg("[~p] orber_iiop:request(reply, ~p, ~p, ~p)~n"
- "Got exit(~p)",
- [?LINE, Rest, Version, TypeCodes, Why], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE});
- 'message_error' ->
- orber:dbg("[~p] orber_iiop:request(reply, ~p, ~p, ~p);~n"
- "Got message_error",
- [?LINE, Rest, Version, TypeCodes], ?DEBUG_LEVEL),
- %% Perhaps a resend should be done when a message error occurs
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE});
- {Result, Par} ->
- %% Check request id
- case ReplyHeader#reply_header.reply_status of
- 'no_exception' ->
- case Par of
- [] ->
- Result;
- _ ->
- list_to_tuple([Result | Par])
- end;
- 'system_exception' ->
- corba:raise(Result);
- 'user_exception' ->
- corba:raise(Result);
- 'location_forward' ->
- case get(orber_forward_notify) of
- true ->
- {location_forward, Result};
- _ ->
- case catch corba:call(Result, Op, Parameters,
- TypeCodes,
- [{timeout, Timeout},
- {context, UserCtx}]) of
- {'EXCEPTION', E} ->
- corba:raise(E);
- {'EXIT', Reason} ->
- orber:dbg("[~p] orber_iiop:request(reply, ~p, ~p, ~p)~n"
- "location_forward resulted in exit(~p)",
- [?LINE, Rest, Version, TypeCodes, Reason], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO});
- NewResult ->
- NewResult
- end
- end;
- 'location_forward_perm' ->
- %% We should notify the client in this case.
- case get(orber_forward_notify) of
- true ->
- {location_forward, Result};
- _ ->
- case catch corba:call(Result, Op, Parameters,
- TypeCodes,
- [{timeout, Timeout},
- {context, UserCtx}]) of
- {'EXCEPTION', E} ->
- corba:raise(E);
- {'EXIT', Reason} ->
- orber:dbg("[~p] orber_iiop:request(reply, ~p, ~p, ~p)~n"
- "location_forward_perm resulted in exit(~p)",
- [?LINE, Rest, Version, TypeCodes, Reason], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO});
- NewResult ->
- NewResult
- end
- end;
- 'needs_addressing_mode' ->
- orber:dbg("[~p] orber_iiop:request(reply, ~p, ~p, ~p)~n"
- "needs_addressing_mode not supported.",
- [?LINE, Rest, Version, TypeCodes], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO})
- end
- end;
- What ->
- orber:dbg("[~p] orber_iiop:request(reply, ~p, ~p, ~p)~n"
- "outproxy-request: ~p", [?LINE, Message, Version, TypeCodes, What], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO})
- end.
-
--dialyzer({no_improper_lists, encode_request/1}).
-encode_request(#giop_env{interceptors = false} = Env) ->
- case catch cdr_encode:enc_request(Env) of
- {'EXCEPTION', Exc} ->
- orber:dbg("[~p] orber_iiop:request(~p)~n"
- "Got exception(~p)",
- [?LINE, Env, Exc], ?DEBUG_LEVEL),
- corba:raise(Exc);
- {'EXIT', R} ->
- orber:dbg("[~p] orber_iiop:request:( ~p )~n"
- "Got exit(~p)",
- [?LINE, Env, R], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO});
- Msg ->
- Msg
- end;
-encode_request(#giop_env{interceptors = {native, Ref, PIs},
- objkey = ObjKey, ctx = Ctx, op = Op,
- parameters = Params} = Env) ->
- Parameters = orber_pi:out_request(PIs, ObjKey, Ctx, Op, Ref, Params),
- case catch cdr_encode:enc_request_split(Env) of
- {'EXCEPTION', Exc} ->
- orber:dbg("[~p] orber_iiop:request( ~p, ~p); exception(~p)",
- [?LINE, Env, Parameters, Exc], ?DEBUG_LEVEL),
- corba:raise(Exc);
- {'EXIT', R} ->
- orber:dbg("[~p] orber_iiop:request:( ~p, ~p); got exit(~p)",
- [?LINE, Env, Parameters, R], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO});
- {Hdr, Body, HdrLen, _, Flags} ->
- NewBody = orber_pi:out_request_enc(PIs, ObjKey, Ctx, Op, Ref, Body),
- cdr_encode:enc_giop_message_header(Env, 'request', Flags,
- HdrLen+size(NewBody),
- [Hdr|NewBody])
- end;
-encode_request(Env) ->
- case catch cdr_encode:enc_request(Env) of
- {'EXCEPTION', Exc} ->
- orber:dbg("[~p] orber_iiop:request( ~p ); exception(~p)",
- [?LINE, Env, Exc], ?DEBUG_LEVEL),
- corba:raise(Exc);
- {'EXIT', R} ->
- orber:dbg("[~p] orber_iiop:request:( ~p ); got exit(~p)",
- [?LINE, Env, R], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO});
- Msg ->
- Msg
- end.
-
-%%-----------------------------------------------------------------
-%% Func: locate/1
-%%-----------------------------------------------------------------
-locate({Host, Port, InitObjkey, Index, TaggedProfile, HostData},
- Timeout, IOR, UserCtx) ->
- {{Proxy, _Ctx, _Interceptors, LocalInterface}, ObjKey, Version} =
- connect(Host, Port, InitObjkey, Timeout, [Index], HostData,
- TaggedProfile, IOR, UserCtx),
- RequestId = orber_request_number:get(),
- Env = #giop_env{version = Version, objkey = ObjKey, request_id = RequestId,
- flags = orber_env:get_flags(), host = LocalInterface},
- Result =
- case catch cdr_encode:enc_locate_request(Env) of
- {'EXCEPTION', EncE} ->
- orber:dbg("[~p] orber_iiop:locate(~p); exception(~p)",
- [?LINE, ObjKey, EncE], ?DEBUG_LEVEL),
- corba:raise(EncE);
- {'EXIT', EncR} ->
- orber:dbg("[~p] orber_iiop:locate(~p); exit(~p)",
- [?LINE, ObjKey, EncR], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO});
- Request ->
- (catch orber_iiop_outproxy:request(Proxy, true, Timeout,
- Request, RequestId))
- end,
- case Result of
- {'EXCEPTION', MsgExc} ->
- corba:raise(MsgExc);
- {locate_reply, ReplyHeader, Rest, Len, ByteOrder} ->
- case catch cdr_decode:dec_locate_reply_body(Version,
- ReplyHeader#locate_reply_header.locate_status,
- Rest, Len, ByteOrder) of
- {'EXCEPTION', DecodeException} ->
- orber:dbg("[~p] orber_iiop:locate(locate_reply, ~p, ~p); exception(~p)",
- [?LINE, Rest, Version, DecodeException], ?DEBUG_LEVEL),
- corba:raise(DecodeException);
- {'EXIT', message_error} ->
- orber:dbg("[~p] orber_iiop:locate(locate_reply, ~p, ~p); exit(message_error)",
- [?LINE, Rest, Version], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE});
- {'EXIT', R} ->
- orber:dbg("[~p] orber_iiop:locate(locate_reply, ~p, ~p); exit(~p)",
- [?LINE, Rest, Version, R], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE});
- [] ->
- ReplyHeader#locate_reply_header.locate_status;
- ObjRef ->
- {ReplyHeader#locate_reply_header.locate_status, ObjRef}
- end;
- Other ->
- orber:dbg("[~p] orber_iiop:locate(~p); exit(~p)",
- [?LINE, ObjKey, Other], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO})
- end.
-
-%%%-----------------------------------------------------------------
-%%% Func: cancel/1
-%%%-----------------------------------------------------------------
-%cancel(X) ->
-% ok.
-
-%%%-----------------------------------------------------------------
-%%% Func: message_error/1
-%%%-----------------------------------------------------------------
-%message_error(X) ->
-% ok.
-
-%%-----------------------------------------------------------------
-%% Server functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: init/1
-%%-----------------------------------------------------------------
-init({orber_iiop_sup, Opts}) ->
- IIOP_port = orber:iiop_port(),
- SSL_port = orber:iiop_ssl_port(),
- SupFlags = {one_for_one, 5, 1000}, %Max 5 restarts in 1 second
- PortList = if
- SSL_port > -1 ->
- [{port, ssl, SSL_port}];
- true ->
- []
- end,
- ChildSpec =
- case orber:is_lightweight() of
- true ->
- [
- {orber_iiop_outsup, {orber_iiop_outsup, start,
- [sup, Opts]},
- permanent, 10000, supervisor, [orber_iiop_outsup]},
- {orber_iiop_pm, {orber_iiop_pm, start,
- [Opts]},
- permanent, 10000, worker, [orber_iiop_pm]}
- ];
- false ->
- [{orber_iiop_outsup, {orber_iiop_outsup, start,
- [sup, Opts]},
- permanent, 10000, supervisor, [orber_iiop_outsup]},
- {orber_iiop_pm, {orber_iiop_pm, start,
- [Opts]},
- permanent, 10000, worker, [orber_iiop_pm]},
- {orber_iiop_insup, {orber_iiop_insup, start,
- [sup, Opts]},
- permanent, 10000, supervisor, [orber_iiop_insup]},
- {orber_iiop_socketsup, {orber_iiop_socketsup, start,
- [sup, Opts]},
- permanent, 10000, supervisor, [orber_iiop_socketsup]},
- {orber_iiop_net, {orber_iiop_net, start,
- [[{port, normal, IIOP_port} | PortList]]},
- permanent, 10000, worker, [orber_iiop_net]}]
- end,
- {ok, {SupFlags, ChildSpec}}.
-
-
-
-
-
-%%-----------------------------------------------------------------
-%% Func: terminate/2
-%%-----------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-%%-----------------------------------------------------------------
-%% Func: handle_call/3
-%%-----------------------------------------------------------------
-handle_call(_Req, _From, State) ->
- {reply, ok, State}.
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-add_user_context([], UserCtx) -> UserCtx;
-add_user_context(SysCtx, []) -> SysCtx;
-add_user_context(SysCtx, UserCtx) -> SysCtx ++ UserCtx.
-
-decode_reply_body(false, _ObjKey, _Op, ReplyHeader, Version, TypeCodes,
- Rest, Len, ByteOrder, Bytes) ->
- case ReplyHeader#reply_header.reply_status of
- 'no_exception' ->
- {R, P, _} = cdr_decode:dec_reply_body(Version, TypeCodes, Rest, Len, ByteOrder, Bytes),
- {R, P};
- 'system_exception' ->
- {R, _} = cdr_decode:dec_system_exception(Version, Rest, Len, ByteOrder),
- {R, []};
- 'user_exception' ->
- {R, _} = cdr_decode:dec_user_exception(Version, Rest, Len, ByteOrder),
- {R, []};
- 'location_forward' ->
- {R, _, _} = cdr_decode:dec_reply_body(Version, {{'tk_objref', "", ""}, [],[]},
- Rest, Len, ByteOrder, Bytes),
- {R, []};
- 'location_forward_perm' ->
- {R, _, _} = cdr_decode:dec_reply_body(Version, {{'tk_objref', "", ""}, [],[]},
- Rest, Len, ByteOrder, Bytes),
- {R, []};
- 'needs_addressing_mode' ->
- {R, _, _} = cdr_decode:dec_reply_body(Version, {'tk_short', [],[]},
- Rest, Len, ByteOrder, Bytes),
- {R, []}
- end;
-decode_reply_body(Interceptors, ObjKey, Op, ReplyHeader, Version, TypeCodes,
- RestIn, Len, ByteOrder, Bytes) ->
- Rest =
- case Interceptors of
- {portable, _PIs} ->
- RestIn;
- {native, Ref, PIs} ->
- orber_pi:in_reply_enc(PIs, ObjKey,
- ReplyHeader#reply_header.service_context,
- Op, Ref, RestIn)
- end,
- Reply =
- case ReplyHeader#reply_header.reply_status of
- 'no_exception' ->
- {R, P, _} = cdr_decode:dec_reply_body(Version, TypeCodes, Rest, Len, ByteOrder, Bytes),
- {R, P};
- 'system_exception' ->
- {R, _} = cdr_decode:dec_system_exception(Version, Rest, Len, ByteOrder),
- {R, []};
- 'user_exception' ->
- {R, _} = cdr_decode:dec_user_exception(Version, Rest, Len, ByteOrder),
- {R, []};
- 'location_forward' ->
- {R, _, _} = cdr_decode:dec_reply_body(Version, {{'tk_objref', "", ""}, [],[]},
- Rest, Len, ByteOrder, Bytes),
- {R, []};
- 'location_forward_perm' ->
- {R, _, _} = cdr_decode:dec_reply_body(Version, {{'tk_objref', "", ""}, [],[]},
- Rest, Len, ByteOrder, Bytes),
- {R, []};
- 'needs_addressing_mode' ->
- {R, _, _} = cdr_decode:dec_reply_body(Version, {'tk_short', [],[]},
- Rest, Len, ByteOrder, Bytes),
- {R, []}
- end,
- case Interceptors of
- {portable, _PI} ->
- Reply;
- {native, Refs, PI} ->
- orber_pi:in_reply(PI, ObjKey,
- ReplyHeader#reply_header.service_context,
- Op, Refs, Reply)
- end.
-
-%% "Plain" TCP/IP.
-connect(Host, Port, Objkey, Timeout, Index,
- #host_data{protocol = normal, csiv2_mech = undefined} = HostData,
- TaggedProfile, IOR, Ctx) ->
- connect2([{Host, Port}], Objkey, Timeout, Index, HostData,
- TaggedProfile, IOR, Ctx);
-%% "Plain" SSL
-connect(Host, _, Objkey, Timeout, Index,
- #host_data{protocol = ssl,
- ssl_data = #'SSLIOP_SSL'{port = Port},
- csiv2_mech = undefined} = HostData,
- TaggedProfile, IOR, Ctx) ->
- connect2([{Host, Port}], Objkey, Timeout, Index, HostData,
- TaggedProfile, IOR, Ctx);
-%% TEMPORARY FIX TO AVOID RUNNING CSIv2.
-connect(Host, _, Objkey, Timeout, Index,
- #host_data{protocol = ssl,
- ssl_data = #'SSLIOP_SSL'{port = Port}} = HostData,
- TaggedProfile, IOR, Ctx) ->
- connect2([{Host, Port}], Objkey, Timeout, Index, HostData,
- TaggedProfile, IOR, Ctx);
-%% CSIv2 over SSL (TAG_TLS_SEC_TRANS) using the SAS protocol. Note port must equal 0.
-connect(_Host, 0, Objkey, Timeout, Index,
- #host_data{protocol = ssl,
- csiv2_mech =
- #'CSIIOP_CompoundSecMech'{target_requires = _TR} = _Mech,
- csiv2_addresses = Addresses} = HostData,
- TaggedProfile, IOR, Ctx) ->
- NewCtx = [#'IOP_ServiceContext'
- {context_id=?IOP_SecurityAttributeService,
- context_data = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'
- {client_context_id = 0, %% Always 0 when stateless.
- authorization_token =
- [#'CSI_AuthorizationElement'{the_element = []}],
- identity_token =
- #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTAbsent,
- value = true},
- client_authentication_token = []}}}|Ctx],
- connect2(Addresses, Objkey, Timeout, Index, HostData,
- TaggedProfile, IOR, NewCtx);
-%% CSIv2 over SSL (TAG_NULL_TAG) using the SAS protocol.
-connect(Host, _, Objkey, Timeout, Index,
- #host_data{protocol = ssl,
- ssl_data = #'SSLIOP_SSL'{port = Port},
- csiv2_mech = Mech} = HostData,
- TaggedProfile, IOR, Ctx) when is_record(Mech, 'CSIIOP_CompoundSecMech') ->
- connect2([{Host, Port}], Objkey, Timeout, Index, HostData,
- TaggedProfile, IOR, Ctx);
-%% CSIv2 over TCP (TAG_NULL_TAG) using the SAS protocol.
-connect(Host, Port, Objkey, Timeout, Index,
- #host_data{protocol = normal,
- csiv2_mech = Mech} = HostData,
- TaggedProfile, IOR, Ctx) when is_record(Mech, 'CSIIOP_CompoundSecMech') ->
- connect2([{Host, Port}], Objkey, Timeout, Index, HostData,
- TaggedProfile, IOR, Ctx);
-connect(_Host, _Port, _Objkey, _Timeout, _Index, HostData, _TaggedProfile,
- IOR, _Ctx) ->
- orber:dbg("[~p] orber_iiop:connect(~p)~n"
- "Unable to use the supplied IOR.~n"
- "Connection Data: ~p", [?LINE, IOR, HostData], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO}).
-
-
-
-connect2(HostPort, Objkey, Timeout, Index, HostData, TaggedProfile, IOR, Ctx) ->
- case try_connect(HostPort, HostData#host_data.protocol, Timeout, HostData, Ctx) of
- error ->
- Alts = iop_ior:get_alt_addr(TaggedProfile),
- case try_connect(Alts, HostData#host_data.protocol, Timeout, HostData, Ctx) of
- error ->
- case iop_ior:get_key(IOR, Index) of
- undefined ->
- corba:raise(#'COMM_FAILURE'{completion_status = ?COMPLETED_NO});
- {'external', {NewHost, NewPort, NewObjkey, NewIndex,
- NewTaggedProfile, NewHostData}} ->
- connect(NewHost, NewPort, NewObjkey, Timeout, [NewIndex|Index],
- NewHostData, NewTaggedProfile, IOR, Ctx);
- _What ->
- orber:dbg("[~p] orber_iiop:connect2(~p)~n"
- "Illegal IOR; contains a mixture of local and external profiles.",
- [?LINE, IOR], ?DEBUG_LEVEL),
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO})
- end;
- X ->
- {X, Objkey, HostData#host_data.version}
- end;
- X ->
- {X, Objkey, HostData#host_data.version}
- end.
-
-try_connect([], _, _, _, _) ->
- error;
-try_connect([{Host, Port}|T], SocketType, Timeout, HostData, Ctx) ->
- case catch orber_iiop_pm:connect(Host, Port, SocketType, Timeout,
- HostData#host_data.charset,
- HostData#host_data.wcharset, Ctx) of
- {ok, P, Ctx2, Int, Interface} ->
- {P, Ctx2, Int, Interface};
- {'EXCEPTION', #'BAD_CONTEXT'{} = CtxExc} ->
- orber:dbg("[~p] orber_iiop:try_connect(~p, ~p) failed~n",
- [?LINE, Host, Port], ?DEBUG_LEVEL),
- corba:raise(CtxExc);
- {'EXCEPTION', _PMExc} ->
- try_connect(T, SocketType, Timeout, HostData, Ctx);
- {'EXIT',{timeout,_}} ->
- orber:dbg("[~p] orber_iiop:try_connect(~p, ~p, ~p)~n"
- "Connect attempt timed out",
- [?LINE, Host, Port, Timeout], ?DEBUG_LEVEL),
- try_connect(T, SocketType, Timeout, HostData, Ctx);
- {'EXIT', What} ->
- orber:dbg("[~p] orber_iiop:try_connect(~p, ~p, ~p)~n"
- "Connect attempt resulted in: ~p",
- [?LINE, Host, Port, Timeout, What], ?DEBUG_LEVEL),
- try_connect(T, SocketType, Timeout, HostData, Ctx)
- end.
-
diff --git a/lib/orber/src/orber_iiop.hrl b/lib/orber/src/orber_iiop.hrl
deleted file mode 100644
index ec502b6f09..0000000000
--- a/lib/orber/src/orber_iiop.hrl
+++ /dev/null
@@ -1,1016 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File: orber_iiop.hrl
-%%
-%%----------------------------------------------------------------------
--ifndef(orber_iiop_hrl).
--define(orber_iiop_hrl, true).
-
--include_lib("orber/include/corba.hrl").
-
-%% The identifiers which indicates if a fixed value has a negative or
-%% positive scale.
--define(FIXED_NEGATIVE, 13).
--define(FIXED_POSITIVE, 12).
-
-%% Used instead of IFR-id's in TypeCode definitions for internal data types.
--define(SYSTEM_TYPE, 0).
-
-%% Major version of GIOP protocol which are supported
--define(GIOP_MAJOR, 1).
-
-%% Minor version of GIOP protocol which are supported
--define(GIOP_MINOR, 0).
-
-%% Major version of IIOP protocol which are supported
--define(IIOP_MAJOR, 1).
-
-%% Minor version of IIOP protocol which are supported
--define(IIOP_MINOR, 0).
-
-%% Fragment flags for the flags bitfield in GIOP message headers
--define(GIOP_BYTE_ORDER_MSB, 0).
--define(GIOP_BYTE_ORDER_LSB, 1).
-
-%% Fragment flags for the flags bitfield in GIOP message headers
--define(GIOP_MORE_FRAGMENTS_FALSE, 0).
--define(GIOP_MORE_FRAGMENTS_TRUE, 1).
-
-%% GIOP Message Types
--define(GIOP_MSG_REQUEST, 0).
--define(GIOP_MSG_REPLY, 1).
--define(GIOP_MSG_CANCEL_REQUEST, 2).
--define(GIOP_MSG_LOCATE_REQUEST, 3).
--define(GIOP_MSG_LOCATE_REPLY, 4).
--define(GIOP_MSG_CLOSE_CONNECTION, 5).
--define(GIOP_MSG_MESSAGE_ERROR, 6).
--define(GIOP_MSG_FRAGMENT, 7).
-
-%% PROFILE_ID's
--define(TAG_INTERNET_IOP, 0).
--define(TAG_MULTIPLE_COMPONENTS, 1).
--define(TAG_SCCP_IOP, 2).
-
-
-%% COMPONENT_ID's
--define(TAG_ORB_TYPE, 0).
--define(TAG_CODE_SETS, 1).
--define(TAG_POLICIES, 2).
--define(TAG_ALTERNATE_IIOP_ADDRESS, 3).
--define(TAG_COMPLETE_OBJECT_KEY, 5).
--define(TAG_ENDPOINT_ID_POSITION, 6).
--define(TAG_LOCATION_POLICY, 12).
--define(TAG_ASSOCIATION_OPTIONS, 13).
--define(TAG_SEC_NAME, 14).
--define(TAG_SPKM_1_SEC_MECH, 15).
--define(TAG_SPKM_2_SEC_MECH, 16).
--define(TAG_KerberosV5_SEC_MECH, 17).
--define(TAG_CSI_ECMA_Secret_SEC_MECH, 18).
--define(TAG_CSI_ECMA_Hybrid_SEC_MECH, 19).
--define(TAG_SSL_SEC_TRANS, 20).
--define(TAG_CSI_ECMA_Public_SEC_MECH, 21).
--define(TAG_GENERIC_SEC_MECH, 22).
--define(TAG_FIREWALL_TRANS, 23).
--define(TAG_SCCP_CONTACT_INFO, 24).
--define(TAG_JAVA_CODEBASE, 25).
--define(TAG_TRANSACTION_POLICY, 26).
--define(TAG_FT_GROUP, 27).
--define(TAG_FT_PRIMARY, 28).
--define(TAG_FT_HEARTBEAT_ENABLED, 29).
--define(TAG_MESSAGE_ROUTERS, 30).
--define(TAG_OTS_POLICY, 31).
--define(TAG_INV_POLICY, 32).
--define(TAG_CSI_SEC_MECH_LIST, 33).
--define(TAG_NULL_TAG, 34).
--define(TAG_SECIOP_SEC_TRANS, 35).
--define(TAG_TLS_SEC_TRANS, 36).
--define(TAG_DCE_STRING_BINDING, 100).
--define(TAG_DCE_BINDING_NAME, 101).
--define(TAG_DCE_NO_PIPES, 102).
--define(TAG_DCE_SEC_MECH, 103).
--define(TAG_INET_SEC_TRANS, 123).
-
-%% COMPONENT_ID strings
--define(TAG_ORB_TYPE_STR, "TAG_ORB_TYPE").
--define(TAG_CODE_SETS_STR, "TAG_CODE_SETS").
--define(TAG_POLICIES_STR, "TAG_POLICIES").
--define(TAG_ALTERNATE_IIOP_ADDRESS_STR, "TAG_ALTERNATE_IIOP_ADDRESS").
--define(TAG_COMPLETE_OBJECT_KEY_STR, "TAG_COMPLETE_OBJECT_KEY").
--define(TAG_ENDPOINT_ID_POSITION_STR, "TAG_ENDPOINT_ID_POSITION").
--define(TAG_LOCATION_POLICY_STR, "TAG_LOCATION_POLICY").
--define(TAG_ASSOCIATION_OPTIONS_STR, "TAG_ASSOCIATION_OPTIONS").
--define(TAG_SEC_NAME_STR, "TAG_SEC_NAME").
--define(TAG_SPKM_1_SEC_MECH_STR, "TAG_SPKM_1_SEC_MECH").
--define(TAG_SPKM_2_SEC_MECH_STR, "TAG_SPKM_2_SEC_MECH").
--define(TAG_KerberosV5_SEC_MECH_STR, "TAG_KerberosV5_SEC_MECH").
--define(TAG_CSI_ECMA_Secret_SEC_MECH_STR, "TAG_CSI_ECMA_Secret_SEC_MECH").
--define(TAG_CSI_ECMA_Hybrid_SEC_MECH_STR, "TAG_CSI_ECMA_Hybrid_SEC_MECH").
--define(TAG_SSL_SEC_TRANS_STR, "TAG_SSL_SEC_TRANS").
--define(TAG_CSI_ECMA_Public_SEC_MECH_STR, "(TAG_CSI_ECMA_Public_SEC_MECH").
--define(TAG_GENERIC_SEC_MECH_STR, "TAG_GENERIC_SEC_MECH").
--define(TAG_FIREWALL_TRANS_STR, "TAG_FIREWALL_TRANS").
--define(TAG_SCCP_CONTACT_INFO_STR, "TAG_SCCP_CONTACT_INFO").
--define(TAG_JAVA_CODEBASE_STR, "TAG_JAVA_CODEBASE").
--define(TAG_TRANSACTION_POLICY_STR, "TAG_TRANSACTION_POLICY").
--define(TAG_FT_GROUP_STR, "TAG_FT_GROUP").
--define(TAG_FT_PRIMARY_STR, "TAG_FT_PRIMARY").
--define(TAG_FT_HEARTBEAT_ENABLED_STR, "TAG_FT_HEARTBEAT_ENABLED").
--define(TAG_MESSAGE_ROUTERS_STR, "TAG_MESSAGE_ROUTERS").
--define(TAG_OTS_POLICY_STR, "TAG_OTS_POLICY").
--define(TAG_INV_POLICY_STR, "TAG_INV_POLICY").
--define(TAG_CSI_SEC_MECH_LIST_STR, "TAG_CSI_SEC_MECH_LIST").
--define(TAG_NULL_TAG_STR, "TAG_NULL_TAG").
--define(TAG_SECIOP_SEC_TRANS_STR, "TAG_SECIOP_SEC_TRANS").
--define(TAG_TLS_SEC_TRANS_STR, "TAG_TLS_SEC_TRANS").
--define(TAG_DCE_STRING_BINDING_STR, "TAG_DCE_STRING_BINDING").
--define(TAG_DCE_BINDING_NAME_STR, "TAG_DCE_BINDING_NAME").
--define(TAG_DCE_NO_PIPES_STR, "TAG_DCE_NO_PIPES").
--define(TAG_DCE_SEC_MECH_STR, "TAG_DCE_SEC_MECH").
--define(TAG_INET_SEC_TRANS_STR, "TAG_INET_SEC_TRANS").
-
-%% GIOP header size
--define(GIOP_HEADER_SIZE, 12).
-
-%% CODESET's we support.
-%% Latin-1. This CodeSet is default if no information exists in the IOR.
--define(ISO8859_1_ID, 16#00010001).
-
-%% UTF-16, UCS Transformation Format 16-bit form
--define(UTF_16_ID, 16#00010109).
-
-%% X/Open UTF-8; UCS Transformation Format 8 (UTF-8)
--define(UTF_8_ID, 16#05010001).
-
-%% The limited UTF-16 without the surrogate mechanism is called UCS-2.
-%% The two-byte subset which is identical with the original Unicode.
-%% UCS-2, Level 1. Used by JDK-1.3 as native wchar.
--define(UCS_2_ID, 16#00010100).
-
-%% ISO 646:1991 IRV (International Reference Version).
-%% Used by JavaIDL as Native Char (JDK-1.3). A.k.a PCS.
--define(ISO646_IRV_ID, 16#00010020).
-
-%% Fallback is *not* the same thing as default!!
--define(FALLBACK_CHAR, 16#05010001).
--define(FALLBACK_WCHAR, 16#00010109).
-
-%% This is used when the wchar codeset is unknown.
--define(UNSUPPORTED_WCHAR, 0).
-
-%% Integer limits
--define(SHORTMIN, -32768).
--define(SHORTMAX, 32767).
--define(USHORTMIN, 0).
--define(USHORTMAX, 65535).
--define(LONGMIN, -2147483648).
--define(LONGMAX, 2147483647).
--define(ULONGMIN, 0).
--define(ULONGMAX, 4294967295).
--define(LONGLONGMIN, -9223372036854775808).
--define(LONGLONGMAX, 9223372036854775807).
--define(ULONGLONGMIN, 0).
--define(ULONGLONGMAX, 18446744073709551615).
-
-
--define(ORBER_GENERIC_CTX, {'tk_sequence', 'tk_octet', 0}).
-
-
-%%----------------------------------------------------------------------
-%% GIOP Message Header
-%%
-%% magic: identifies the GIOP message headers, array of four characters.
-%% giop_version: contains the version number of the giop protocol being
-%% used in the message.
-%% byte_order: indicating the byte order being used in subsequent
-%% elements of the message.
-%% 0 - big-endian byte ordering, 1 - little-endian byte ordering
-%% fragments: true if more fragments follow, otherwise false.
-%% message_type: indicating the type of the message
-%% message_size: gives the length of the message following the message
-%% headerin octets.
-%%----------------------------------------------------------------------
--record(giop_message, {magic,
- giop_version,
- byte_order,
- fragments = false,
- message_type,
- message_size,
- message}).
-
-
-
-%%----------------------------------------------------------------------
-%% Request Message Header
-%%
-%% service_context: contains ORB service data being passed from client to server.
-%% (IOP::ServiceContextList)
-%% request_id: id used to assosciate reply messages with request messages.
-%% response_expected: true if the request is expected to have a reply message.
-%% object_key: identifies the object wich is the target of the invocation.
-%% operation: contains the name of the operation being invoked.
-%% requesting_principal: contains a value that identifying the requesting
-%% principal.
-%%----------------------------------------------------------------------
--record(request_header, {service_context, request_id, response_expected, object_key, operation, requesting_principal}).
-
-
-
-%%----------------------------------------------------------------------
-%% Reply Message Header
-%%
-%% service_context: contains ORB service data being passed from client to server.
-%% (IOP::ServiceContextList)
-%% request_id: id used to assosciate reply messages with request messages.
-%% reply_status: indicates the completion status of the request
-%%----------------------------------------------------------------------
--record(reply_header, {service_context, request_id, reply_status}).
-
-
-
-%%----------------------------------------------------------------------
-%% Cancel Request Message Header
-%%
-%% request_id: id used to assosciate reply messages with request messages.
-%%----------------------------------------------------------------------
--record(cancel_request_header, {request_id}).
-
-
-
-%%----------------------------------------------------------------------
-%% Locate Request Message Header
-%%
-%% request_id: id used to assosciate reply messages with request messages.
-%% object_key: identifies the object being located (octet sequence).
-%%----------------------------------------------------------------------
--record(locate_request_header, {request_id, object_key}).
-
-
-
-%%----------------------------------------------------------------------
-%% Locate Reply Message Header
-%%
-%% request_id: id used to assosciate reply messages with request messages.
-%% locate_status: indicates the completion status of the locate request
-%%----------------------------------------------------------------------
--record(locate_reply_header, {request_id, locate_status}).
-
-
-
-%%----------------------------------------------------------------------
-%% Profile Body
-%%
-%% iiop_version: describes the version of IIOP that the agent at the
-%% specified address is prepared to receive.
-%% host: identifies the internet host to which the GIOP messages
-%% for the specified object may be sent.
-%% port: contains the TCP?IP port number where the target agnet is listening
-%% for connection requests.
-%% object_key: is an opaque value supplied by the agent producing the IOR.
-%%----------------------------------------------------------------------
--record(profile_body, {iiop_version,host,port,object_key}).
-
-%%----------------------------------------------------------------------
-%% Version
-%%
-%% major: major version number of iiop protocol
-%% minor: minor version number of iiop protocol.
-%%
-%% When an agnet generates profiles specifying a particular version,
-%% it must be able to accept messages complying with the specified
-%% version or any porevious minor version.
-%%----------------------------------------------------------------------
--record(version, {major,minor}).
-
-%%----------------------------------------------------------------------
-%% Fragment Message Header
-%%
-%% request_id:
-%%----------------------------------------------------------------------
--record(fragment_header, {request_id}).
-
-
-%%----------------------------------------------------------------------
-%% ORB_FLAGS macros. Used in the local object references {_,_,_,_,_,Flags}.
-%%
-%%----------------------------------------------------------------------
-
-%% Definition of flag positions:
--define(ORB_SEC_ATTRIBUTES, 16#01).
--define(ORB_CONTEXT, 16#02).
--define(ORB_TYPECHECK, 16#04).
--define(ORB_NO_SECURITY, 16#08).
--define(ORB_SURVIVE_EXIT, 16#10).
--define(ORB_USE_PI, 16#20).
-
--define(ORB_INIT_FLAGS, 16#00).
-
-%%----------------------------------------------------------------------
-%% Flags used as configuration parameters (application env).
-%%
-%%----------------------------------------------------------------------
--define(ORB_ENV_EXCLUDE_CODESET_COMPONENT, 16#01). %% FIXED!!
--define(ORB_ENV_LOCAL_TYPECHECKING, 16#02). %% FIXED!!
--define(ORB_ENV_HOSTNAME_IN_IOR, 16#04). %% FIXED!!
--define(ORB_ENV_ENABLE_NAT, 16#08). %% FIXED!!
--define(ORB_ENV_PARTIAL_SECURITY, 16#10). %% FIXED FOR NOW!! INTERNAL
--define(ORB_ENV_USE_PI, 16#20). %% FIXED!!
--define(ORB_ENV_USE_FT, 16#40). %% WILL PROBABLY BE FIXED!!
--define(ORB_ENV_LIGHT_IFR, 16#80). %% FIXED!!
--define(ORB_ENV_USE_IPV6, 16#100). %% FIXED!!
--define(ORB_ENV_SURVIVE_EXIT, 16#200). %% FIXED!!
--define(ORB_ENV_USE_ACL_INCOMING, 16#400). %% FIXED!!
--define(ORB_ENV_USE_ACL_OUTGOING, 16#800). %% FIXED!!
--define(ORB_ENV_LOCAL_INTERFACE, 16#1000). %% FIXED!!
-
--define(ORB_ENV_USE_BI_DIR_IIOP, 16#2000). %% CAN BE CHANGED
--define(ORB_ENV_USE_CSIV2, 16#4000). %% CAN BE CHANGED
--define(ORB_ENV_EXCLUDE_CODESET_CTX, 16#8000). %% CAN BE CHANGED
-
-
--define(ORB_ENV_INIT_FLAGS, 16#00).
-
--define(ORB_ENV_FLAGS,
- [{?ORB_ENV_EXCLUDE_CODESET_CTX, "Exclude CodeSet Ctx"},
- {?ORB_ENV_LOCAL_TYPECHECKING, "Local Typechecking"},
- {?ORB_ENV_HOSTNAME_IN_IOR, "Use Hostname in IOR"},
- {?ORB_ENV_EXCLUDE_CODESET_COMPONENT, "Exclude CodeSet Component"},
- {?ORB_ENV_ENABLE_NAT, "NAT Enabled"},
- {?ORB_ENV_USE_CSIV2, "CSIv2 Activated"},
- {?ORB_ENV_USE_FT, "Fault Tolerance Activated"},
- {?ORB_ENV_USE_IPV6, "IPv6 Activated"},
- {?ORB_ENV_SURVIVE_EXIT, "EXIT Tolerance Activated"},
- {?ORB_ENV_USE_PI, "Local Interceptors"},
- {?ORB_ENV_LIGHT_IFR, "Light IFR"},
- {?ORB_ENV_USE_BI_DIR_IIOP, "Use BiDirIIOP"},
- {?ORB_ENV_USE_ACL_INCOMING, "Use ACL for Incoming Connections"},
- {?ORB_ENV_USE_ACL_OUTGOING, "Use ACL for Outgoing Connections"},
- {?ORB_ENV_LOCAL_INTERFACE, "Use the Proxy Interface in Exported IOR:s"}]).
-
-
-%%----------------------------------------------------------------------
-%% Definition of flag operations
-%%
-%%----------------------------------------------------------------------
-%% USAGE: Boolean = ?ORB_FLAG_TEST(Flags, ?ORB_SEC_ATTRIBUTES)
--define(ORB_FLAG_TEST(_F1, _I1), ((_F1 band _I1) == _I1)).
-
-%% USAGE: NewFlags = ?ORB_SET_TRUE(Flags, ?ORB_CONTEXT)
--define(ORB_SET_TRUE(_F2, _I2), (_I2 bor _F2)).
-
-%% USAGE: NewFlags = ?ORB_SET_FALSE(Flags, ?ORB_CONTEXT)
--define(ORB_SET_FALSE(_F3, _I3), ((_I3 bxor 16#ff) band _F3)).
-
-%% USAGE: NewFlags = ?ORB_SET_FALSE_LIST(Flags, [?ORB_SEC_ATTRIBUTES, ?ORB_SOME])
--define(ORB_SET_FALSE_LIST(_F4, _IList1),
- lists:foldl(fun(_I4, _F5) ->
- ((_I4 bxor 16#ff) band _F5)
- end,
- _F4, _IList1)).
-
-%% USAGE: NewFlags = ?ORB_SET_TRUE_LIST(Flags, [?ORB_SEC_ATTRIBUTES, ?ORB_SOME])
--define(ORB_SET_TRUE_LIST(_F6, _IList2),
- lists:foldl(fun(_I6, _F7) ->
- (_I6 bor _F7)
- end,
- _F6, _IList2)).
-
-%% USAGE: Boolean = ?ORB_FLAG_TEST_LIST(Flags, [?ORB_CONTEXT, ?ORB_THING])
--define(ORB_FLAG_TEST_LIST(_F8, _IList3),
- lists:all(fun(_I7) ->
- ((_F8 band _I7) == _I7)
- end,
- _IList3)).
-
-%%----------------------------------------------------------------------
-%% IOR
-%%
-%%----------------------------------------------------------------------
--record('IOP_IOR', {type_id, profiles}).
--record('IOP_TaggedProfile', {tag, profile_data}).
--record('IIOP_ProfileBody_1_0', {iiop_version,
- host,
- port,
- object_key}).
--record('IIOP_ProfileBody_1_1', {iiop_version,
- host,
- port,
- object_key,
- components}).
-
--record('GIOP_Version', {major, minor}).
-
--record('IIOP_Version', {major, minor}).
-
--record('SSLIOP_SSL', {target_supports, target_requires, port}).
-
--record('IOP_TaggedComponent', {tag, component_data}).
-
--record('GIOP_TargetAddress', {label, value}).
-
--record('GIOP_IORAddressingInfo', {selected_profile_index, ior}).
-
-
-%%
-%% Nil object reference
-%%
--define(ORBER_NIL_OBJREF, #'IOP_IOR' {type_id = "", profiles = []}).
-
--define(IOR_TYPEDEF, {'tk_struct', ?SYSTEM_TYPE, 'IOP_IOR',
- [{"type_id", {'tk_string', 0}},
- {"profiles", {'tk_sequence', {'tk_struct', ?SYSTEM_TYPE,
- 'IOP_TaggedProfile',
- [{"tag", 'tk_ulong'},
- {"profile_data",
- {'tk_sequence', 'tk_octet', 0}}]}, 0}}]}).
-
--define(GIOP_VERSION, {'tk_struct', ?SYSTEM_TYPE, 'GIOP_Version',
- [{"major", 'tk_octet'},
- {"minor", 'tk_octet'}]}).
-
--define(IIOP_VERSION, {'tk_struct', ?SYSTEM_TYPE, 'IIOP_Version',
- [{"major vsn", 'tk_octet'},
- {"minor vsn", 'tk_octet'}]}).
--define(IOP_TAGGEDCOMPONENT, {'tk_struct', ?SYSTEM_TYPE,
- 'IOP_TaggedComponent',
- [{"tag", 'tk_ulong'},
- {"component_data",
- {'tk_sequence',
- 'tk_octet', 0}}]}).
--define(IOP_TAGGEDCOMPONENT_SEQ, {'tk_sequence', ?IOP_TAGGEDCOMPONENT, 0}).
-
--define(PROFILEBODY_1_0_TYPEDEF, {'tk_struct', ?SYSTEM_TYPE, 'IIOP_ProfileBody_1_0',
- [{"iiop_version", ?IIOP_VERSION },
- {"host", {'tk_string', 0}},
- {"port", 'tk_ushort'},
- {"object_key", {'tk_sequence', 'tk_octet', 0}}]}).
-
--define(PROFILEBODY_1_1_TYPEDEF, {'tk_struct', ?SYSTEM_TYPE, 'IIOP_ProfileBody_1_1',
- [{"iiop_version",?IIOP_VERSION },
- {"host", {'tk_string', 0}},
- {"port", 'tk_ushort'},
- {"object_key", {'tk_sequence', 'tk_octet', 0}},
- {"components", ?IOP_TAGGEDCOMPONENT_SEQ}]}).
-
--define(PROFILEBODY_1_2_TYPEDEF, {'tk_struct', ?SYSTEM_TYPE, 'IIOP_ProfileBody_1_1',
- [{"iiop_version",?IIOP_VERSION },
- {"host", {'tk_string', 0}},
- {"port", 'tk_ushort'},
- {"object_key", {'tk_sequence', 'tk_octet', 0}},
- {"components", ?IOP_TAGGEDCOMPONENT_SEQ}]}).
-
--define(SSLIOP_SSL, {'tk_struct', ?SYSTEM_TYPE, 'SSLIOP_SSL',
- [{"target_supports", 'tk_ushort'},
- {"target_requires", 'tk_ushort'},
- {"port", 'tk_ushort'}]}).
-
--define(GIOP_KeyAddr, 0).
--define(GIOP_ProfileAddr, 1).
--define(GIOP_ReferenceAddr, 2).
-
--define(TARGETADDRESS, {'tk_union', ?SYSTEM_TYPE, 'GIOP_TargetAddress', 'tk_short', -1,
- [{?GIOP_KeyAddr, "object_key", {'tk_sequence', 'tk_octet', 0}},
- {?GIOP_ProfileAddr, "profile", {'tk_struct', ?SYSTEM_TYPE,
- 'IOP_TaggedProfile',
- [{"tag", 'tk_ulong'},
- {"profile_data",
- {'tk_sequence', 'tk_octet', 0}}]}},
- {?GIOP_ReferenceAddr, "ior", {'tk_struct', ?SYSTEM_TYPE,
- 'GIOP_IORAddressingInfo',
- [{"selected_profile_index", 'tk_ulong'},
- {"ior", ?IOR_TYPEDEF}]}}]}).
-
-% Zero or more instances of the TAG_ALTERNATE_IIOP_ADDRESS component type
-% may be included in a version 1.2 TAG_INTERNET_IOP Profile.
--record('ALTERNATE_IIOP_ADDRESS', {'HostID', 'Port'}).
--define(ALTERNATE_IIOP_ADDRESS, {'tk_struct', ?SYSTEM_TYPE,
- 'ALTERNATE_IIOP_ADDRESS',
- [{"HostID", {'tk_string', 0}},
- {"Port", 'tk_ushort'}]}).
-% The TAG_ORB_TYPE component can appear at most once in any IOR profile. For
-% profiles supporting IIOP 1.1 or greater, it is optionally present.
--define(ORB_TYPE, 'tk_ulong').
-
--record('CONV_FRAME_CodeSetComponent', {native_code_set, conversion_code_sets}).
--record('CONV_FRAME_CodeSetComponentInfo', {'ForCharData', 'ForWcharData'}).
--define(CONV_FRAME_CODESETCOMPONENT, {'tk_struct', ?SYSTEM_TYPE,
- 'CONV_FRAME_CodeSetComponent',
- [{"native_code_set", 'tk_ulong'},
- {"conversion_code_sets",
- {'tk_sequence', 'tk_ulong', 0}}]}).
--define(CONV_FRAME_CODESETCOMPONENTINFO, {'tk_struct', ?SYSTEM_TYPE,
- 'CONV_FRAME_CodeSetComponentInfo',
- [{"ForCharData",
- ?CONV_FRAME_CODESETCOMPONENT},
- {"ForWcharData",
- ?CONV_FRAME_CODESETCOMPONENT}]}).
-
-
-
-
--define(DEFAULT_FOR_CHAR, #'CONV_FRAME_CodeSetComponent'{native_code_set=?ISO8859_1_ID,
- conversion_code_sets=[]}).
--define(DEFAULT_FOR_WCHAR, #'CONV_FRAME_CodeSetComponent'{native_code_set=?UTF_16_ID,
- conversion_code_sets=[]}).
--define(DEFAULT_CODESETS,
- #'CONV_FRAME_CodeSetComponentInfo'{'ForCharData' = ?DEFAULT_FOR_CHAR,
- 'ForWcharData' = ?DEFAULT_FOR_WCHAR}).
-
-%% Fragmentation - IIOP-1.1 & 1.2
--record('GIOP_FragmentHeader_1_2', {request_id}).
-
--define(GIOP_FragmentHeader_1_2, {'tk_struct', ?SYSTEM_TYPE,
- 'GIOP_FragmentHeader_1_2',
- [{"request_id", 'tk_ulong'}]}).
-
-%%------ MISC Definitions -------
-%% TimeBase::TimeT (TimeBase.idl) is defined as
-%% typedef unsigned long long TimeT;
--define(TimeBase_TimeT, 'tk_ulonglong').
-
-%%------ Fault Tolerant Definitions -------
-
-%% Specification for Interoperable Object Group References
--define(FT_FTDomainId, {'tk_string', 0}).
--define(FT_ObjectGroupId, 'tk_ulonglong').
--define(FT_ObjectGroupRefVersion, 'tk_ulong').
-%% A GIOP::Version of 1.0 indicates that the implementation is compliant
-%% with the CORBA-2.6 specification.
-%% tag = TAG_FT_GROUP
--record('FT_TagFTGroupTaggedComponent', {version = #'GIOP_Version'{major = 1,
- minor = 0},
- ft_domain_id, object_group_id,
- object_group_ref_version}).
--define(FT_TagFTGroupTaggedComponent, {'tk_struct', ?SYSTEM_TYPE, 'FT_TagFTGroupTaggedComponent',
- [{"version", ?GIOP_VERSION},
- {"ft_domain_id", ?FT_FTDomainId},
- {"object_group_id", ?FT_ObjectGroupId},
- {"object_group_ref_version", ?FT_ObjectGroupRefVersion}]}).
-
-%% tag = TAG_FT_PRIMARY;
--record('FT_TagFTPrimaryTaggedComponent', {primary}).
--define(FT_TagFTPrimaryTaggedComponent, {'tk_struct', ?SYSTEM_TYPE, 'FT_TagFTPrimaryTaggedComponent',
- [{"primary", 'tk_boolean'}]}).
-
-
-%% Specification for Most Recent Object Group Reference
-%% context_id = FT_GROUP_VERSION;
--record('FT_FTGroupVersionServiceContext', {object_group_ref_version}).
--define(FT_FTGroupVersionServiceContext, {'tk_struct', ?SYSTEM_TYPE, 'FT_FTGroupVersionServiceContext',
- [{"object_group_ref_version", ?FT_ObjectGroupRefVersion}]}).
-
-%% Specification for Transparent Reinvocation
--define(FT_PolicyType_REQUEST_DURATION_POLICY, 47).
-
-%% context_id = FT_REQUEST
--record('FT_FTRequestServiceContext', {client_id, retention_id, expiration_time}).
--define(FT_FTRequestServiceContext, {'tk_struct', ?SYSTEM_TYPE, 'FT_FTRequestServiceContext',
- [{"client_id", {'tk_string', 0}},
- {"retention_id", 'tk_long'},
- {"expiration_time", ?TimeBase_TimeT}]}).
-
-%% Specification for Transport Heartbeats
--define(FT_PolicyType_HEARTBEAT_POLICY, 48).
--define(FT_PolicyType_HEARTBEAT_ENABLED_POLICY, 49).
-
-%% tag = TAG_FT_HEARTBEAT_ENABLED;
--record('FT_TagFTHeartbeatEnabledTaggedComponent', {heartbeat_enabled}).
--define(FT_TagFTHeartbeatEnabledTaggedComponent, {'tk_struct', ?SYSTEM_TYPE, 'FT_TagFTHeartbeatEnabledTaggedComponent',
- [{"heartbeat_enabled", 'tk_boolean'}]}).
-
-
-%%------ CSI stuff - required by the SAS protocol. -------
-%% This constant defines the current level we support.
--define(CSIv2_MAX_TARGET_REQUIRES, 16#488).
-
-%% NOTE! The OMG VMCID is incorrect in the SAS specification, should be
-%% OMGVMCID = 0x4f4d0000;
--define(CSI_OMGVMCID, ?CORBA_OMGVMCID).
-
-%% ASN.1 Encoding of an OBJECT IDENTIFIER
--define(CSI_OID, {'tk_sequence', 'tk_octet', 0}).
--define(CSI_OIDList, {'tk_sequence', ?CSI_OID, 0}).
-
-%% An X509CertificateChain contains an ASN.1 BER encoded SEQUENCE
-%% [1..MAX] OF X.509 certificates encapsulated in a sequence of octets. The
-%% subject:s certificate shall come first in the list. Each following
-%% certificate shall directly certify the one preceding it. The ASN.1
-%% representation of Certificate is as defined in [IETF RFC 2459].
--define(CSI_X509CertificateChain, {'tk_sequence', 'tk_octet', 0}).
-
-%% an X.501 type name or Distinguished Name encapsulated in a sequence of
-%% octets containing the ASN.1 encoding.
--define(CSI_X501DistinguishedName, {'tk_sequence', 'tk_octet', 0}).
-
-%% UTF-8 Encoding of String
--define(CSI_UTF8String, {'tk_sequence', 'tk_octet', 0}).
-
-%% A sequence of octets containing a GSStoken. Initial context tokens are
-%% ASN.1 encoded as defined in [IETF RFC 2743] Section 3.1,
-%% "Mechanism-Independent token Format", pp. 81-82. Initial context tokens
-%% contain an ASN.1 tag followed by a token length, a mechanism identifier,
-%% and a mechanism-specific token (i.e. a GSSUP::InitialContextToken). The
-%% encoding of all other GSS tokens (e.g. error tokens and final context
-%% tokens) is mechanism dependent.
--define(CSI_GSSToken, {'tk_sequence', 'tk_octet', 0}).
-
-%% An encoding of a GSS Mechanism-Independent Exported Name Object as
-%% defined in [IETF RFC 2743] Section 3.2, "GSS Mechanism-Independent
-%% Exported Name Object Format," p. 84.
--define(CSI_GSS_NT_ExportedName, {'tk_sequence', 'tk_octet', 0}).
--define(CSI_GSS_NT_ExportedNameList, {'tk_sequence', ?CSI_GSS_NT_ExportedName, 0}).
-
-%% The MsgType enumeration defines the complete set of service context
-%% message types used by the CSI context management protocols, including
-%% those message types pertaining only to the stateful application of the
-%% protocols (to insure proper alignment of the identifiers between
-%% stateless and stateful implementations). Specifically, the
-%% MTMessageInContext is not sent by stateless clients (although it may
-%% be received by stateless targets).
--define(CSI_MsgType, 'tk_short').
--define(CSI_MsgType_MTEstablishContext, 0).
--define(CSI_MsgType_MTCompleteEstablishContext, 1).
--define(CSI_MsgType_MTContextError, 4).
--define(CSI_MsgType_MTMessageInContext, 5).
-
-%% The ContextId type is used carry session identifiers. A stateless
-%% application of the service context protocol is indicated by a session
-%% identifier value of 0.
--define(CSI_ContextId, 'tk_ulonglong').
-
-%% The AuthorizationElementType defines the contents and encoding of
-%% the_element field of the AuthorizationElement.
-%% The high order 20-bits of each AuthorizationElementType constant
-%% shall contain the Vendor Minor Codeset ID (VMCID) of the
-%% organization that defined the element type. The low order 12 bits
-%% shall contain the organization-scoped element type identifier. The
-%% high-order 20 bits of all element types defined by the OMG shall
-%% contain the VMCID allocated to the OMG (that is, 0x4F4D0).
--define(CSI_AuthorizationElementType, 'tk_ulong').
-
-%% An AuthorizationElementType of X509AttributeCertChain indicates that
-%% the_element field of the AuthorizationElement contains an ASN.1 BER
-%% SEQUENCE composed of an (X.509) AttributeCertificate followed by a
-%% SEQUENCE OF (X.509) Certificate. The two-part SEQUENCE is encapsulated
-%% in an octet stream. The chain of identity certificates is provided
-%% to certify the attribute certificate. Each certificate in the chain
-%% shall directly certify the one preceding it. The first certificate
-%% in the chain shall certify the attribute certificate. The ASN.1
-%% representation of (X.509) Certificate is as defined in [IETF RFC 2459].
-%% The ASN.1 representation of (X.509) AtributeCertificate is as defined
-%% in [IETF ID PKIXAC].
--define(CSI_X509AttributeCertChain, (?CSI_OMGVMCID bor 1)).
--define(CSI_AuthorizationElementContents, {'tk_sequence', 'tk_octet', 0}).
-
-%% The AuthorizationElement contains one element of an authorization token.
-%% Each element of an authorization token is logically a PAC.
-%% The AuthorizationToken is made up of a sequence of AuthorizationElements
-%% --- NOTE ---
-%% OMG only defines 'CSI_X509AttributeCertChain' so we use it as default value.
--record('CSI_AuthorizationElement', {the_type = ?CSI_X509AttributeCertChain,
- the_element = []}).
--define(CSIIOP_AuthorizationElement, {'tk_struct', ?SYSTEM_TYPE, 'CSI_AuthorizationElement',
- [{"the_type", ?CSI_AuthorizationElementType},
- {"the_element", ?CSI_AuthorizationElementContents}]}).
--define(CSI_AuthorizationToken, {'tk_sequence', ?CSIIOP_AuthorizationElement, 0}).
-
-%% Additional standard identity token types shall only be defined by the
-%% OMG. All IdentityTokenType constants shall be a power of 2.
--define(CSI_IdentityTokenType, 'tk_ulong').
--define(CSI_IdentityTokenType_ITTAbsent, 0).
--define(CSI_IdentityTokenType_ITTAnonymous, 1).
--define(CSI_IdentityTokenType_ITTPrincipalName, 2).
--define(CSI_IdentityTokenType_ITTX509CertChain, 4).
--define(CSI_IdentityTokenType_ITTDistinguishedName, 8).
-
--define(CSI_IdentityExtension, {'tk_sequence', 'tk_octet', 0}).
--record('CSI_IdentityToken', {label, value}).
--define(CSI_IdentityToken,
- {'tk_union', ?SYSTEM_TYPE, 'CSI_IdentityToken',
- ?CSI_IdentityTokenType, 5,
- [{?CSI_IdentityTokenType_ITTAbsent, "absent", 'tk_boolean'},
- {?CSI_IdentityTokenType_ITTAnonymous, "anonymous", 'tk_boolean'},
- {?CSI_IdentityTokenType_ITTPrincipalName, "principal_name", ?CSI_GSS_NT_ExportedName},
- {?CSI_IdentityTokenType_ITTX509CertChain, "certificate_chain", ?CSI_X509CertificateChain},
- {?CSI_IdentityTokenType_ITTDistinguishedName, "dn", ?CSI_X501DistinguishedName},
- {default, "id", ?CSI_IdentityExtension}]}).
-
--record('CSI_EstablishContext', {client_context_id, authorization_token,
- identity_token, client_authentication_token}).
--define(CSI_EstablishContext, {'tk_struct', ?SYSTEM_TYPE, 'CSI_EstablishContext',
- [{"client_context_id", ?CSI_ContextId},
- {"authorization_token", ?CSI_AuthorizationToken},
- {"identity_token", ?CSI_IdentityToken},
- {"client_authentication_token", ?CSI_GSSToken}]}).
-
--record('CSI_CompleteEstablishContext', {client_context_id, context_stateful,
- final_context_token}).
--define(CSI_CompleteEstablishContext, {'tk_struct', ?SYSTEM_TYPE, 'CSI_CompleteEstablishContext',
- [{"client_context_id", ?CSI_ContextId},
- {"context_stateful", 'tk_boolean'},
- {"final_context_token", ?CSI_GSSToken}]}).
-
--record('CSI_ContextError', {client_context_id, major_status,
- minor_status, error_token}).
--define(CSI_ContextError, {'tk_struct', ?SYSTEM_TYPE, 'CSI_ContextError',
- [{"client_context_id", ?CSI_ContextId},
- {"major_status", 'tk_long'},
- {"minor_status", 'tk_long'},
- {"error_token", ?CSI_GSSToken}]}).
-
-% Not sent by stateless clients. If received by a stateless server, a
-% ContextError message should be returned, indicating the session does
-% not exist.
--record('CSI_MessageInContext', {client_context_id, discard_context}).
--define(CSI_MessageInContext, {'tk_struct', ?SYSTEM_TYPE, 'CSI_MessageInContext',
- [{"client_context_id", ?CSI_ContextId},
- {"discard_context", 'tk_boolean'}]}).
-
--record('CSI_SASContextBody', {label, value}).
--define(CSI_SASContextBody,
- {'tk_union', ?SYSTEM_TYPE, 'CSI_SASContextBody', ?CSI_MsgType, -1,
- [{?CSI_MsgType_MTEstablishContext, "establish_msg", ?CSI_EstablishContext},
- {?CSI_MsgType_MTCompleteEstablishContext, "complete_msg", ?CSI_CompleteEstablishContext},
- {?CSI_MsgType_MTContextError, "error_msg", ?CSI_ContextError},
- {?CSI_MsgType_MTMessageInContext, "in_context_msg", ?CSI_MessageInContext}]}).
-
-%% The following type represents the string representation of an ASN.1
-%% OBJECT IDENTIFIER (OID). OIDs are represented by the string "oid:"
-%% followed by the integer base 10 representation of the OID separated
-%% by dots. For example, the OID corresponding to the OMG is represented
-%% as: "oid:2.23.130"
--define(CSI_StringOID, {'tk_string', 0}).
-
-
-%% The GSS Object Identifier for the KRB5 mechanism is:
-%% { iso(1) member-body(2) United States(840) mit(113554) infosys(1)
-%% gssapi(2) krb5(2) }
-%% Type ?CSI_StringOID
--define(CSI_KRB5MechOID, "oid:1.2.840.113554.1.2.2").
-
-%% The GSS Object Identifier for name objects of the Mechanism-independent
-%% Exported Name Object type is:
-%% { iso(1) org(3) dod(6) internet(1) security(5) nametypes(6)
-%% gss-api-exported-name(4) }
-%% Type ?CSI_StringOID
--define(CSI_GSS_NT_Export_Name_OID, "oid:1.3.6.1.5.6.4").
-
-%% The GSS Object Identifier for the scoped-username name form is:
-%% { iso-itu-t (2) international-organization (23) omg (130) security (1)
-%% naming (2) scoped-username(1) }
-%% Type ?CSI_StringOID
--define(CSI_GSS_NT_Scoped_Username_OID, "oid:2.23.130.1.2.1").
-
-%%------ GSSUP stuff - required by the SAS protocol. -------
-%% The GSS Object Identifier allocated for the username/password mechanism is defined
-%% below.
-%% { iso-itu-t (2) international-organization (23) omg (130)
-%% security (1) authentication (1) gssup-mechanism (1) }
-%% Type ?CSI_StringOID
--define(GSSUP_GSSUPMechOID, "oid:2.23.130.1.1.1").
-
-%% The following structure defines the inner contents of the
-%% username password initial context token. This structure is
-%% CDR encapsulated and appended at the end of the
-%% username/password GSS (initial context) Token.
--record('GSSUP_InitialContextToken', {username, password, target_name}).
--define(GSSUP_InitialContextToken, {'tk_struct', ?SYSTEM_TYPE, 'GSSUP_InitialContextToken',
- [{"username", ?CSI_UTF8String},
- {"password", ?CSI_UTF8String},
- {"target_name", ?CSI_GSS_NT_ExportedName}]}).
-
--define(GSSUP_ErrorCode, 'tk_ulong').
-
-%% GSSUP Mechanism-Specific Error Token
--record('GSSUP_ErrorToken', {error_code}).
--define(GSSUP_ErrorToken, {'tk_struct', ?SYSTEM_TYPE, 'GSSUP_ErrorToken',
- [{"error_code", ?GSSUP_ErrorCode}]}).
-
-%% The context validator has chosen not to reveal the GSSUP
-%% specific cause of the failure.
-%% Type ?GSSUP_ErrorCode
--define(GSSUP_GSS_UP_S_G_UNSPECIFIED, 1).
-
-%% The user identified in the username field of the
-%% GSSUP::InitialContextToken is unknown to the target.
-%% Type ?GSSUP_ErrorCode
--define(GSSUP_GSS_UP_S_G_NOUSER, 2).
-
-%% The password supplied in the GSSUP::InitialContextToken was
-%% incorrect.
-%% Type ?GSSUP_ErrorCode
--define(GSSUP_GSS_UP_S_G_BAD_PASSWORD, 3).
-
-%% The target_name supplied in the GSSUP::InitialContextToken does
-%% not match a target_name in a mechanism definition of the target.
-%% Type ?GSSUP_ErrorCode
--define(GSSUP_GSS_UP_S_G_BAD_TARGET, 4).
-
-
-%%----- CSIIOP stuff - required by the SAS protocol. -----
-
-% AssociationOptions
--define(CSIIOP_AssociationOptions, 'tk_ushort').
-%% AssociationOptions - constant definitions
--define(CSIIOP_AssociationOptions_NoProtection, 1).
--define(CSIIOP_AssociationOptions_Integrity, 2).
--define(CSIIOP_AssociationOptions_Confidentiality, 4).
--define(CSIIOP_AssociationOptions_DetectReplay, 8).
--define(CSIIOP_AssociationOptions_DetectMisordering, 16).
--define(CSIIOP_AssociationOptions_EstablishTrustInTarget, 32).
--define(CSIIOP_AssociationOptions_EstablishTrustInClient, 64).
--define(CSIIOP_AssociationOptions_NoDelegation, 128).
--define(CSIIOP_AssociationOptions_SimpleDelegation, 256).
--define(CSIIOP_AssociationOptions_CompositeDelegation, 512).
--define(CSIIOP_AssociationOptions_IdentityAssertion, 1024).
--define(CSIIOP_AssociationOptions_DelegationByClient, 2048).
-
-%% The high order 20-bits of each ServiceConfigurationSyntax constant
-%% shall contain the Vendor Minor Codeset ID (VMCID) of the
-%% organization that defined the syntax. The low order 12 bits shall
-%% contain the organization-scoped syntax identifier. The high-order 20
-%% bits of all syntaxes defined by the OMG shall contain the VMCID
-%% allocated to the OMG (that is, 0x4F4D0).
-%% NOTE! The OMG VMCID is incorrect in the SAS specification, should be
-%% OMGVMCID = 0x4f4d0000;
--define(CSIIOP_ServiceConfigurationSyntax, 'tk_ulong').
--define(CSIIOP_ServiceConfigurationSyntax_SCS_GeneralNames, (?CSI_OMGVMCID bor 0)).
--define(CSIIOP_ServiceConfigurationSyntax_SCS_GSSExportedName, (?CSI_OMGVMCID bor 1)).
-
--define(CSIIOP_ServiceSpecificName, {'tk_sequence', 'tk_octet', 0}).
-
-%% The name field of the ServiceConfiguration structure identifies a
-%% privilege authority in the format identified in the syntax field. If the
-%% syntax is SCS_GeneralNames, the name field contains an ASN.1 (BER)
-%% SEQUENCE [1..MAX] OF GeneralName, as defined by the type GeneralNames in
-%% [IETF RFC 2459]. If the syntax is SCS_GSSExportedName, the name field
-%% contains a GSS exported name encoded according to the rules in
-%% [IETF RFC 2743] Section 3.2, "Mechanism-Independent Exported Name
-%% Object Format," p. 84 (CORBA-2.6)
--record('CSIIOP_ServiceConfiguration', {syntax, name}).
--define(CSIIOP_ServiceConfiguration, {'tk_struct', ?SYSTEM_TYPE, 'CSIIOP_ServiceConfiguration',
- [{"syntax", ?CSIIOP_ServiceConfigurationSyntax},
- {"name", ?CSIIOP_ServiceSpecificName}]}).
--define(CSIIOP_ServiceConfigurationList, {'tk_sequence', ?CSIIOP_ServiceConfiguration, 0}).
-
-%% The body of the TAG_NULL_TAG component is a sequence of octets of
-%% length 0.
-
-%% type used to define AS layer functionality within a compound mechanism
-%% definition
--record('CSIIOP_AS_ContextSec', {target_supports = 0, target_requires = 0,
- client_authentication_mech, target_name}).
--define(CSIIOP_AS_ContextSec, {'tk_struct', ?SYSTEM_TYPE, 'CSIIOP_AS_ContextSec',
- [{"target_supports", ?CSIIOP_AssociationOptions},
- {"target_requires", ?CSIIOP_AssociationOptions},
- {"client_authentication_mech", ?CSI_OID},
- {"target_name", ?CSI_GSS_NT_ExportedName}]}).
-
-%% type used to define SAS layer functionality within a compound mechanism
-%% definition
--record('CSIIOP_SAS_ContextSec', {target_supports = 0, target_requires = 0,
- privilege_authorities,
- supported_naming_mechanisms,
- supported_identity_types}).
--define(CSIIOP_SAS_ContextSec, {'tk_struct', ?SYSTEM_TYPE, 'CSIIOP_SAS_ContextSec',
- [{"target_supports", ?CSIIOP_AssociationOptions},
- {"target_requires", ?CSIIOP_AssociationOptions},
- {"privilege_authorities", ?CSIIOP_ServiceConfigurationList},
- {"supported_naming_mechanisms", ?CSI_OIDList},
- {"supported_identity_types", ?CSI_IdentityTokenType}]}).
-
-%% Type used in the body of a TAG_CSI_SEC_MECH_LIST component to describe a
-%% compound mechanism
--record('CSIIOP_CompoundSecMech', {target_requires = 0, transport_mech,
- as_context_mech, sas_context_mech}).
--define(CSIIOP_CompoundSecMech, {'tk_struct', ?SYSTEM_TYPE, 'CSIIOP_CompoundSecMech',
- [{"target_requires", ?CSIIOP_AssociationOptions},
- {"transport_mech", ?IOP_TAGGEDCOMPONENT},
- {"as_context_mech", ?CSIIOP_AS_ContextSec},
- {"sas_context_mech", ?CSIIOP_SAS_ContextSec}]}).
--define(CSIIOP_CompoundSecMechanisms, {'tk_sequence', ?CSIIOP_CompoundSecMech, 0}).
-
-%% type corresponding to the body of a TAG_CSI_SEC_MECH_LIST component
--record('CSIIOP_CompoundSecMechList', {stateful = false, mechanism_list}).
--define(CSIIOP_CompoundSecMechList, {'tk_struct', ?SYSTEM_TYPE, 'CSIIOP_CompoundSecMechList',
- [{"stateful", 'tk_boolean'},
- {"mechanism_list", ?CSIIOP_CompoundSecMechanisms}]}).
-%% CSIIOP::TransportAddress
--record('CSIIOP_TransportAddress', {host_name, port}).
--define(CSIIOP_TransportAddress, {'tk_struct', ?SYSTEM_TYPE, 'CSIIOP_TransportAddress',
- [{"host_name", {'tk_string', 0}},
- {"port", 'tk_ushort'}]}).
--define(CSIIOP_TransportAddressList, {'tk_sequence', ?CSIIOP_TransportAddress, 0}).
-
-%% Tagged component (TAG_TLS_SEC_TRANS) for configuring TLS/SSL as a CSIv2
-%% transport mechanism.
--record('CSIIOP_TLS_SEC_TRANS', {target_supports, target_requires, addresses}).
--define(CSIIOP_TLS_SEC_TRANS, {'tk_struct', ?SYSTEM_TYPE, 'CSIIOP_TLS_SEC_TRANS',
- [{"target_supports", ?CSIIOP_AssociationOptions},
- {"target_requires", ?CSIIOP_AssociationOptions},
- {"addresses", ?CSIIOP_TransportAddressList}]}).
-
-%% Tagged component (TAG_SECIOP_SEC_TRANS) for configuring SECIOP as a CSIv2
-%% transport mechanism
--record('CSIIOP_SECIOP_SEC_TRANS', {target_supports = 0, target_requires = 0, mech_oid,
- target_name, addresses}).
--define(CSIIOP_SECIOP_SEC_TRANS, {'tk_struct', ?SYSTEM_TYPE, 'CSIIOP_SECIOP_SEC_TRANS',
- [{"target_supports", ?CSIIOP_AssociationOptions},
- {"target_requires", ?CSIIOP_AssociationOptions},
- {"mech_oid", ?CSI_OID},
- {"target_name", ?CSI_GSS_NT_ExportedName},
- {"addresses", ?CSIIOP_TransportAddressList}]}).
-
-
-%%-- ServiceContext ID's ------------
-%% Describes what type of context included, i.e.,
-%% typedef unsigned long ServiceId;
-%% struct ServiceContext {
-%% ServiceId context_id;
-%% sequence <octet> context_data;
-%% };
-
-%% The record is defined in include/corba.hrl.
-%%-record('IOP_ServiceContext', {context_id, context_data}).
--define(IOP_SERVICECONTEXT, {'tk_sequence',
- {'tk_struct', ?SYSTEM_TYPE, 'IOP_ServiceContext',
- [{"context_id", 'tk_ulong'},
- {"context_data",
- {'tk_sequence', 'tk_octet', 0}}]}, 0}).
-
--record('CONV_FRAME_CodeSetContext', {char_data, wchar_data}).
--define(CONV_FRAME_CODESETCONTEXT, {'tk_struct', ?SYSTEM_TYPE, 'CONV_FRAME_CodeSetContext',
- [{"char_data", 'tk_ulong'},
- {"wchar_data", 'tk_ulong'}]}).
-
-
--record('IIOP_ListenPoint', {host, port}).
--define(IIOP_LISTENPOINT, {'tk_struct', ?SYSTEM_TYPE, 'IIOP_ListenPoint',
- [{"host", {'tk_string', 0}},
- {"port", 'tk_ushort'}]}).
-
--record('IIOP_BiDirIIOPServiceContext', {listen_points}).
--define(IIOP_BIDIRIIOPSERVICECONTEXT,
- {'tk_struct', ?SYSTEM_TYPE, 'IIOP_BiDirIIOPServiceContext',
- [{"listen_points", {'tk_sequence', ?IIOP_LISTENPOINT, 0}}]}).
-
--define(IOP_TransactionService, 0).
--define(IOP_CodeSets, 1).
--define(IOP_ChainBypassCheck, 2).
--define(IOP_ChainBypassInfo, 3).
--define(IOP_LogicalThreadId, 4).
--define(IOP_BI_DIR_IIOP, 5).
--define(IOP_SendingContextRunTime, 6).
--define(IOP_INVOCATION_POLICIES, 7).
--define(IOP_FORWARDED_IDENTITY, 8).
--define(IOP_UnknownExceptionInfo, 9).
--define(IOP_RTCorbaPriority, 10).
--define(IOP_RTCorbaPriorityRange, 11).
--define(IOP_FT_GROUP_VERSION, 12).
--define(IOP_FT_REQUEST, 13).
--define(IOP_ExceptionDetailMessage, 14).
--define(IOP_SecurityAttributeService, 15).
-
-
-
-%%----------------------------------------------------------------------
-%% host_data
-%%----------------------------------------------------------------------
--record(host_data, {protocol = normal, ssl_data, version, csiv2_mech,
- csiv2_statefull = false, csiv2_addresses = [],
- charset = ?ISO8859_1_ID, wcharset = ?UTF_16_ID,
- ft_heartbeat = false, ft_primary = false, ft_domain,
- ft_group, ft_ref_version}).
-
-%%----------------------------------------------------------------------
-%% giop_env
-%%----------------------------------------------------------------------
--record(giop_env, {interceptors, type, version, bytes, ctx = [],
- request_id, op, parameters = [], tc, response_expected,
- objkey, reply_status, result, flags, host, iiop_port,
- iiop_ssl_port, domain, partial_security}).
-
--endif.
-
-%%----------------------------------------------------------------------
-%% END OF MODULE
-%%----------------------------------------------------------------------
diff --git a/lib/orber/src/orber_iiop_inproxy.erl b/lib/orber/src/orber_iiop_inproxy.erl
deleted file mode 100644
index b595586f84..0000000000
--- a/lib/orber/src/orber_iiop_inproxy.erl
+++ /dev/null
@@ -1,399 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_iiop_inproxy.erl
-%%
-%% Description:
-%% This file contains the IIOP "proxy" for incomming connections
-%%
-%%-----------------------------------------------------------------
--module(orber_iiop_inproxy).
-
--behaviour(gen_server).
-
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/include/corba.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([start/0, start/1]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- code_change/3, terminate/2, post_accept/3, stop/1]).
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
--define(DEBUG_LEVEL, 7).
-
--record(state, {stype, socket, db, timeout, max_fragments,
- max_requests, request_counter = 1, giop_env, peer}).
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: start/0
-%%-----------------------------------------------------------------
-start() ->
- ignore.
-
-%%-----------------------------------------------------------------
-%% Func: start/1
-%%-----------------------------------------------------------------
-start(Opts) ->
- gen_server:start_link(orber_iiop_inproxy, Opts, []).
-
-post_accept(Pid, ssl, Socket) ->
- (catch gen_server:cast(Pid, {post_accept, ssl, Socket})),
- ok;
-post_accept(_, _, _) ->
- ok.
-
-%%-----------------------------------------------------------------
-%% Internal interface functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: stop/1
-%%-----------------------------------------------------------------
-stop(Pid) ->
- gen_server:cast(Pid, stop).
-
-%%-----------------------------------------------------------------
-%% Server functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: init/1
-%%-----------------------------------------------------------------
-init({connect, Type, Socket, Ref, Options}) ->
- process_flag(trap_exit, true),
- Flags = orber_tb:keysearch(flags, Options, orber_env:get_flags()),
- {Address, Port} = PeerData = orber_socket:peerdata(Type, Socket),
- {LAddress, LPort} = LocalData = orber_socket:sockdata(Type, Socket),
- case {?ORB_FLAG_TEST(Flags, ?ORB_ENV_LOCAL_INTERFACE), LPort} of
- {true, 0} ->
- orber_tb:info("Unable to lookup the local address and port number.~n"
- "Closing the incoming connection.", []),
- ignore;
- _ ->
- orber_iiop_net:add_connection(Socket, Type, PeerData, LocalData, Ref),
- Interceptors =
- case orber_tb:keysearch(interceptors, Options,
- orber_env:get_interceptors()) of
- {native, PIs} ->
- {native, orber_pi:new_in_connection(PIs, Address, Port,
- LAddress, LPort), PIs};
- Other ->
- Other
- end,
- Env =
- case ?ORB_FLAG_TEST(Flags, ?ORB_ENV_LOCAL_INTERFACE) of
- true when Type == ssl ->
- #giop_env{interceptors = Interceptors,
- flags = Flags, host = [LAddress],
- iiop_port =
- orber_tb:keysearch(iiop_port, Options,
- orber_env:iiop_port()),
- iiop_ssl_port = LPort,
- domain = orber:domain(),
- partial_security = orber:partial_security()};
- true ->
- #giop_env{interceptors = Interceptors,
- flags = Flags, host = [LAddress],
- iiop_port = LPort,
- iiop_ssl_port =
- orber_tb:keysearch(iiop_ssl_port, Options,
- orber_env:iiop_ssl_port()),
- domain = orber:domain(),
- partial_security = orber:partial_security()};
- false ->
- case ?ORB_FLAG_TEST(Flags, ?ORB_ENV_ENABLE_NAT) of
- false ->
- #giop_env{interceptors = Interceptors,
- flags = Flags, host = orber:host(),
- iiop_port = orber:iiop_port(),
- iiop_ssl_port = orber:iiop_ssl_port(),
- domain = orber:domain(),
- partial_security = orber:partial_security()};
- true ->
- #giop_env{interceptors = Interceptors,
- flags = Flags,
- host =
- orber_tb:keysearch(nat_ip_address, Options,
- orber_env:nat_host()),
- iiop_port =
- orber_tb:keysearch(nat_iiop_port, Options,
- orber_env:nat_iiop_port()),
- iiop_ssl_port =
- orber_tb:keysearch(nat_iiop_ssl_port, Options,
- orber_env:nat_iiop_ssl_port()),
- domain = orber:domain(),
- partial_security = orber:partial_security()}
- end
- end,
- Timeout = orber_tb:keysearch(iiop_in_connection_timeout, Options,
- orber_env:iiop_in_connection_timeout()),
- MaxFrags = orber_tb:keysearch(iiop_max_fragments, Options,
- orber_env:iiop_max_fragments()),
- MaxRequests = orber_tb:keysearch(iiop_max_in_requests, Options,
- orber_env:iiop_max_in_requests()),
- {ok, #state{stype = Type,
- socket = Socket,
- db = ets:new(orber_incoming_requests, [set]),
- timeout = Timeout,
- max_fragments = MaxFrags,
- max_requests = MaxRequests,
- giop_env = Env, peer = PeerData}, Timeout}
- end.
-
-
-%%-----------------------------------------------------------------
-%% Func: terminate/2
-%%-----------------------------------------------------------------
-%% We may want to kill all proxies before terminating, but the best
-%% option should be to let the requests complete (especially for one-way
-%% functions it's a better alternative.
-terminate(_Reason, #state{db = IncRequests, giop_env = Env}) ->
- ets:delete(IncRequests),
- case Env#giop_env.interceptors of
- false ->
- ok;
- {native, Ref, PIs} ->
- orber_pi:closed_in_connection(PIs, Ref);
- {_Type, _PIs} ->
- ok
- end.
-
-%%-----------------------------------------------------------------
-%% Func: handle_call/3
-%%-----------------------------------------------------------------
-handle_call(stop, _From, State) ->
- {stop, normal, ok, State};
-handle_call(_, _, State) ->
- {noreply, State, State#state.timeout}.
-
-%%-----------------------------------------------------------------
-%% Func: handle_cast/2
-%%-----------------------------------------------------------------
-handle_cast({post_accept, Type, Socket}, State) ->
- Timeout = orber_env:iiop_ssl_accept_timeout(),
- case catch orber_socket:post_accept(Type, Socket, Timeout) of
- ok ->
- {noreply, State};
- _Failed ->
- orber_socket:close(Type, Socket),
- {stop, normal, State}
- end;
-handle_cast(stop, State) ->
- {stop, normal, State};
-handle_cast(_, State) ->
- {noreply, State, State#state.timeout}.
-
-%%-----------------------------------------------------------------
-%% Func: handle_info/2
-%%-----------------------------------------------------------------
-%% Normal invocation
-handle_info({tcp, Socket, Bytes}, State) ->
- handle_msg(normal, Socket, Bytes, State);
-handle_info({ssl, Socket, Bytes}, State) ->
- handle_msg(ssl, Socket, Bytes, State);
-%% Errors, closed connection
-handle_info({tcp_closed, _Socket}, State) ->
- {stop, normal, State};
-handle_info({tcp_error, _Socket, _Reason}, State) ->
- {stop, normal, State};
-handle_info({ssl_closed, _Socket}, State) ->
- {stop, normal, State};
-handle_info({ssl_error, _Socket, _Reason}, State) ->
- {stop, normal, State};
-%% Servant termination.
-handle_info({'EXIT', Pid, normal}, State) ->
- ets:delete(State#state.db, Pid),
- {noreply, decrease_counter(State), State#state.timeout};
-handle_info({message_error, _Pid, ReqId}, State) ->
- ets:delete(State#state.db, ReqId),
- {noreply, State, State#state.timeout};
-handle_info(timeout, State) ->
- case ets:info(State#state.db, size) of
- 0 ->
- %% No pending requests, close the connection.
- {stop, normal, State};
- _Amount ->
- %% Still pending request, cannot close the connection.
- {noreply, State, State#state.timeout}
- end;
-handle_info({reconfigure, Options}, State) ->
- {noreply, update_state(State, Options), State#state.timeout};
-handle_info(_X,State) ->
- {noreply, State, State#state.timeout}.
-
-handle_msg(Type, Socket, Bytes, #state{stype = Type, socket = Socket,
- giop_env = Env} = State) ->
- case catch cdr_decode:dec_giop_message_header(Bytes) of
- %% Only when using IIOP-1.2 may the client send this message.
- %% Introduced in CORBA-2.6
- #giop_message{message_type = ?GIOP_MSG_CLOSE_CONNECTION,
- giop_version = {1,2}} ->
- {stop, normal, State};
- #giop_message{message_type = ?GIOP_MSG_CLOSE_CONNECTION} ->
- {noreply, State, State#state.timeout};
- #giop_message{message_type = ?GIOP_MSG_CANCEL_REQUEST} = GIOPHdr ->
- ReqId = cdr_decode:peek_request_id(GIOPHdr#giop_message.byte_order,
- GIOPHdr#giop_message.message),
- case ets:lookup(State#state.db, ReqId) of
- [{RId, PPid}] ->
- ets:delete(State#state.db, RId),
- PPid ! {self(), cancel_request_header};
- [] ->
- send_msg_error(Type, Socket, Bytes,
- Env#giop_env{version =
- GIOPHdr#giop_message.giop_version},
- "No such request id")
- end,
- {noreply, State, State#state.timeout};
- %% A fragment; we must have received a Request or LocateRequest
- %% with fragment-flag set to true.
- %% We need to decode the header to get the request-id.
- #giop_message{message_type = ?GIOP_MSG_FRAGMENT,
- giop_version = {1,2}} = GIOPHdr ->
- ReqId = cdr_decode:peek_request_id(GIOPHdr#giop_message.byte_order,
- GIOPHdr#giop_message.message),
- case ets:lookup(State#state.db, ReqId) of
- [{_RId, PPid}] when GIOPHdr#giop_message.fragments == true ->
- PPid ! {self(), GIOPHdr};
- [{RId, PPid}] ->
- ets:delete(State#state.db, RId),
- PPid ! {self(), GIOPHdr};
- [] ->
- send_msg_error(Type, Socket, Bytes,
- Env#giop_env{version =
- GIOPHdr#giop_message.giop_version},
- "No such fragment id")
- end,
- {noreply, State, State#state.timeout};
- %% Must be a Request or LocateRequest which have been fragmented.
- %% We need to decode the header to get the request-id.
- #giop_message{fragments = true,
- giop_version = {1,2}} = GIOPHdr ->
- ReqId = cdr_decode:peek_request_id(GIOPHdr#giop_message.byte_order,
- GIOPHdr#giop_message.message),
- Pid =
- orber_iiop_inrequest:
- start_fragment_collector(GIOPHdr, Bytes,
- Type, Socket,
- ReqId, self(),
- State#state.max_fragments,
- Env#giop_env{version = {1,2},
- request_id = ReqId}),
- ets:insert(State#state.db, {Pid, ReqId}),
- ets:insert(State#state.db, {ReqId, Pid}),
- {noreply, increase_counter(State), State#state.timeout};
- GIOPHdr when is_record(GIOPHdr, giop_message) ->
- Pid = orber_iiop_inrequest:start(GIOPHdr, Bytes, Type, Socket,
- Env#giop_env{version =
- GIOPHdr#giop_message.giop_version}),
- ets:insert(State#state.db, {Pid, undefined}),
- {noreply, increase_counter(State), State#state.timeout};
- {'EXIT', message_error} ->
- send_msg_error(Type, Socket, Bytes,
- Env#giop_env{version = orber_env:giop_version()},
- "Unable to decode the GIOP-header"),
- {noreply, State, State#state.timeout}
- end;
-handle_msg(Type, _, Bytes, State) ->
- orber:dbg("[~p] orber_iiop_inproxy:handle_msg(~p);~n"
- "Received a message from a socket of a different type.~n"
- "Should be ~p but was ~p.",
- [?LINE, Bytes, State#state.stype, Type], ?DEBUG_LEVEL),
- {noreply, State, State#state.timeout}.
-
-send_msg_error(Type, Socket, Data, Env, Msg) ->
- orber:dbg("[~p] orber_iiop_inproxy:handle_msg(~p); ~p.",
- [?LINE, Data, Msg], ?DEBUG_LEVEL),
- Reply = cdr_encode:enc_message_error(Env),
- orber_socket:write(Type, Socket, Reply).
-
-increase_counter(#state{max_requests = infinity} = State) ->
- State;
-increase_counter(#state{max_requests = Max,
- request_counter = Counter} = State) when Max > Counter ->
- orber_socket:setopts(State#state.stype, State#state.socket, [{active, once}]),
- State#state{request_counter = Counter + 1};
-increase_counter(State) ->
- State#state{request_counter = State#state.request_counter + 1}.
-
-decrease_counter(#state{max_requests = infinity} = State) ->
- State;
-decrease_counter(#state{max_requests = Max,
- request_counter = Counter} = State) when Max =< Counter ->
- orber_socket:setopts(State#state.stype, State#state.socket, [{active, once}]),
- State#state{request_counter = Counter - 1};
-decrease_counter(State) ->
- State#state{request_counter = State#state.request_counter - 1}.
-
-update_state(#state{giop_env = Env} = State,
- [{interceptors, false}|Options]) ->
- update_state(State#state{giop_env =
- Env#giop_env{interceptors = false}}, Options);
-update_state(#state{giop_env = #giop_env{interceptors = false, host = [SH],
- iiop_port = SP} = Env,
- peer = {PH, PP}, stype = normal} = State,
- [{interceptors, {native, LPIs}}|Options]) ->
- %% No Interceptor(s). Add the same Ref used by the built in interceptors.
- update_state(State#state{giop_env =
- Env#giop_env{interceptors =
- {native, {PH, PP, SH, SP}, LPIs}}},
- Options);
-update_state(#state{giop_env = #giop_env{interceptors = false, host = [SH],
- iiop_ssl_port = SP} = Env,
- peer = {PH, PP}, stype = ssl} = State,
- [{interceptors, {native, LPIs}}|Options]) ->
- %% No Interceptor(s). Add the same Ref used by the built in interceptors.
- update_state(State#state{giop_env =
- Env#giop_env{interceptors =
- {native, {PH, PP, SH, SP}, LPIs}}},
- Options);
-update_state(#state{giop_env = #giop_env{interceptors = {native, Ref, _}} = Env} =
- State,
- [{interceptors, {native, LPIs}}|Options]) ->
- %% Interceptor(s) already in use. We must use the same Ref as before.
- update_state(State#state{giop_env =
- Env#giop_env{interceptors = {native, Ref, LPIs}}},
- Options);
-update_state(State, [H|T]) ->
- orber:dbg("[~p] orber_iiop_inproxy:update_state(~p, ~p)~n"
- "Couldn't change the state.",
- [?LINE, H, State], ?DEBUG_LEVEL),
- update_state(State, T);
-update_state(State, []) ->
- State.
-
-%%-----------------------------------------------------------------
-%% Func: code_change/3
-%%-----------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
diff --git a/lib/orber/src/orber_iiop_inrequest.erl b/lib/orber/src/orber_iiop_inrequest.erl
deleted file mode 100644
index 9d84b63398..0000000000
--- a/lib/orber/src/orber_iiop_inrequest.erl
+++ /dev/null
@@ -1,541 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%--------------------------------------------------------------------
-%% File: orber_iiop_inrequest.erl
-%%
-%% Description:
-%% This file contains the handling of incomming requests
-%%
-%%-----------------------------------------------------------------
--module(orber_iiop_inrequest).
-
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/orber_pi.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([start/5, start_fragment_collector/8]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([handle_message/5, fragment_collector/8]).
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
--define(DEBUG_LEVEL, 8).
-
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-start(GIOPHdr, Message, Type, Socket, Env) ->
- spawn_link(orber_iiop_inrequest, handle_message,
- [GIOPHdr, Message, Type, Socket, Env]).
-
-start_fragment_collector(GIOPHdr, Message, Type, Socket, ReqId, Proxy, MaxFrags, Env) ->
- spawn_link(orber_iiop_inrequest, fragment_collector,
- [GIOPHdr, Message, Type, Socket, ReqId, Proxy, MaxFrags, Env]).
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% Func: fragment_collector/4
-%%-----------------------------------------------------------------
-fragment_collector(GIOPHdr, Bytes, SocketType, Socket, ReqId, Proxy, MaxFrags, Env) ->
- case catch collect(Proxy, [], GIOPHdr#giop_message.byte_order, ReqId,
- MaxFrags, 0) of
- {ok, Buffer} ->
- NewGIOP = GIOPHdr#giop_message
- {message = list_to_binary([GIOPHdr#giop_message.message|Buffer])},
- %% NOTE, the third argument to dec_message_header must be complete
- %% message (i.e. AllBytes), otherwise we cannot handle indirection.
- case handle_message(NewGIOP, list_to_binary([Bytes| Buffer]),
- SocketType, Socket, Env) of
- message_error ->
- Proxy ! {message_error, self(), ReqId},
- ok;
- _ ->
- ok
- end;
- ok ->
- ok;
- {'EXCEPTION', E} ->
- Proxy ! {message_error, self(), ReqId},
- Reply = marshal_exception(Env, ReqId, E, enc_reply),
- orber_socket:write(SocketType, Socket, Reply)
- end.
-
-
-
-collect(_Proxy, _Buffer, _ByteOrder, _ReqId, MaxFrags, MaxFrags) ->
- orber:dbg("[~p] ~p:collect(~p)~nMax fragments limit reached.",
- [?LINE, ?MODULE, MaxFrags], ?DEBUG_LEVEL),
- {'EXCEPTION', #'IMP_LIMIT'{completion_status=?COMPLETED_NO}};
-collect(Proxy, Buffer, ByteOrder, ReqId, MaxFrags, FragCounter) ->
- receive
- {Proxy, #giop_message{byte_order = ByteOrder,
- message = Message,
- fragments = true} = GIOPHdr} ->
- {_, #fragment_header{request_id=ReqId}, FragBody, _, _} =
- cdr_decode:dec_message_header(null, GIOPHdr, Message),
- collect(Proxy, [FragBody | Buffer], ByteOrder, ReqId,
- MaxFrags, FragCounter+1);
- {Proxy, #giop_message{byte_order = ByteOrder,
- message = Message,
- fragments = false} = GIOPHdr} ->
- {_, #fragment_header{request_id=ReqId}, FragBody, _, _} =
- cdr_decode:dec_message_header(null, GIOPHdr, Message),
- {ok, lists:reverse([FragBody | Buffer])};
- {Proxy, GIOPHdr, _Data, _} ->
- orber:dbg("[~p] orber_iiop_inrequest:collect(~p, ~p)~n"
- "Incorrect Fragment. Might be different byteorder.",
- [?LINE, ByteOrder, GIOPHdr], ?DEBUG_LEVEL),
- {'EXCEPTION', #'MARSHAL'{completion_status=?COMPLETED_NO}};
- {Proxy, cancel_request_header} ->
- ok;
- Other ->
- orber:dbg("[~p] ~p:collect(~p)~n"
- "Unable to collect all fragments: ~p",
- [?LINE, ?MODULE, Buffer, Other], ?DEBUG_LEVEL),
- {'EXCEPTION', #'MARSHAL'{completion_status=?COMPLETED_NO}}
- end.
-
-
-%%-----------------------------------------------------------------
-%% Func: handle_message/4
-%%-----------------------------------------------------------------
-handle_message(GIOPHdr, Message, SocketType, Socket, Env) ->
- %% Warning. We shouldn't set the flags like this here. But, for now, we'll
- %% do it due to performance reasons.
- put(oe_orber_flags, Env#giop_env.flags),
- case catch cdr_decode:dec_message_header(null, GIOPHdr, Message) of
- Hdr when is_record(Hdr, cancel_request_header) ->
- %% We just skips this message for the moment, the standard require that
- %% the client handles the reply anyway.
- message_error;
- {location_forward, Object, ReqId, Version, OldObj} ->
- Reply = call_interceptors_out(Env#giop_env{version = Version},
- ReqId, [Object], OldObj,
- 'location_forward',
- "location_forward",
- {{'tk_objref', "", ""}, [],[]}),
- orber_socket:write(SocketType, Socket, Reply);
- {object_forward, Object, ReqId, Version, _OldObj} ->
- Reply = handle_locate_request(Env#giop_env{version = Version},
- {object_forward, Object, ReqId}),
- orber_socket:write(SocketType, Socket, Reply);
- {Version, Hdr} when is_record(Hdr, locate_request_header) ->
- Reply = handle_locate_request(Env#giop_env{version = Version}, Hdr),
- orber_socket:write(SocketType, Socket, Reply);
- {Version, ReqHdr, Rest, Len, ByteOrder} when is_record(ReqHdr, request_header) ->
- handle_request(Env#giop_env{version = Version}, ReqHdr, Rest, Len,
- ByteOrder, SocketType, Socket, Message);
- Other ->
- %% This cluase takes care of all erranous messages.
- orber:dbg("[~p] orber_iiop_inrequest:handle_message(~p)~n"
- "Decoding Msg Header failed: ~p",
- [?LINE, Message, Other], ?DEBUG_LEVEL),
- Reply = cdr_encode:enc_message_error(Env),
- orber_socket:write(SocketType, Socket, Reply),
- message_error
- end.
-
-
-send_reply(oneway, _SocketType, _Socket) ->
- ok;
-send_reply(Reply, SocketType, Socket) ->
- orber_socket:write(SocketType, Socket, Reply).
-
-%%-----------------------------------------------------------------
-%% Func: handle_request
-%%-----------------------------------------------------------------
-handle_request(#giop_env{interceptors = false} = Env, ReqHdr, Rest, Len, ByteOrder,
- SocketType, Socket, Message) ->
- NewEnv = check_context(ReqHdr#request_header.service_context, [], Env),
- case decode_body(NewEnv, ReqHdr, Rest, Len, ByteOrder, Message, enc_reply) of
- {error, E} ->
- orber_socket:write(SocketType, Socket, E);
- {NewEnv2, Hdr, Par, TypeCodes} ->
- Result = invoke_request(Hdr, Par, SocketType, TypeCodes, Env),
- Reply = evaluate(NewEnv2, Hdr, Result, TypeCodes,
- enc_reply, 'no_exception'),
- send_reply(Reply, SocketType, Socket)
- end;
-handle_request(Env, ReqHdr, Rest, Len, ByteOrder, SocketType, Socket, Message) ->
- NewEnv = check_context(ReqHdr#request_header.service_context, [], Env),
- case catch call_interceptors(SocketType, NewEnv, ReqHdr,
- Rest, Len, ByteOrder, Message) of
- {error, E} ->
- %% Failed to decode body.
- orber_socket:write(SocketType, Socket, E);
- {'EXCEPTION', Exc} ->
- orber:dbg("[~p] orber_iiop_inrequest:handle_message(~p)~n"
- "Invoking the interceptors resulted in: ~p",
- [?LINE, Message, Exc], ?DEBUG_LEVEL),
- Reply = marshal_exception(NewEnv,
- ReqHdr#request_header.request_id,
- Exc, enc_reply),
- orber_socket:write(SocketType, Socket, Reply);
- {'EXIT', R} ->
- orber:dbg("[~p] orber_iiop_inrequest:handle_message(~p)~n"
- "Invoking the interceptors resulted in: ~p",
- [?LINE, ReqHdr, R], ?DEBUG_LEVEL),
- Reply = marshal_exception(NewEnv,
- ReqHdr#request_header.request_id,
- #'MARSHAL'{completion_status=?COMPLETED_MAYBE},
- enc_reply),
- orber_socket:write(SocketType, Socket, Reply);
- Reply ->
- send_reply(Reply, SocketType, Socket)
- end.
-
-check_context([], [], Env) ->
- Env;
-check_context([], Acc, Env) ->
- Env#giop_env{ctx = Acc};
-check_context([#'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'
- {client_context_id = _Id,
- authorization_token = _AuthToken,
- identity_token = _IdToken,
- client_authentication_token = _CAuthToken}}|Rest], Acc, Env) ->
- check_context(Rest, [#'IOP_ServiceContext'
- {context_id=?IOP_SecurityAttributeService,
- context_data = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTCompleteEstablishContext,
- value = #'CSI_CompleteEstablishContext'
- {client_context_id = 0,
- context_stateful = false,
- final_context_token = [0,255]}}}|Acc], Env);
-check_context([_|Rest], Acc, Env) ->
- check_context(Rest, Acc, Env).
-
-
-%%-----------------------------------------------------------------
-%% Func: call_interceptors
-%%-----------------------------------------------------------------
--dialyzer({no_improper_lists, call_interceptors/7}).
-call_interceptors(SocketType, #giop_env{interceptors = {native, Ref, PIs},
- ctx = Ctx} = Env,
- ReqHdr, Rest, Len, ByteOrder, Msg) ->
- NewRest = orber_pi:in_request_enc(PIs, ReqHdr, Ref, Rest),
- case decode_body(Env, ReqHdr, NewRest, Len, ByteOrder, Msg, enc_reply) of
- {NewEnv, Hdr, Par, TypeCodes} ->
- NewPar = orber_pi:in_request(PIs, ReqHdr, Ref, Par),
- ResultInv = invoke_request(Hdr, NewPar, SocketType, TypeCodes, NewEnv),
- Result = orber_pi:out_reply(PIs, ReqHdr, Ref, ResultInv, Ctx),
-
- case evaluate(NewEnv, ReqHdr, Result, TypeCodes, enc_reply_split,
- 'no_exception') of
- {ReplyHdr, Reply, HdrL, _BodyL, Flags} ->
- NewReply = orber_pi:out_reply_enc(PIs, ReqHdr, Ref, Reply, Ctx),
- MessSize = HdrL+size(NewReply),
- cdr_encode:enc_giop_message_header(NewEnv, 'reply', Flags,
- MessSize, [ReplyHdr|NewReply]);
- Other ->
- Other
- end;
- Other ->
- Other
- end;
-call_interceptors(SocketType, #giop_env{interceptors = {portable, _PIs}} = Env,
- ReqHdr, Rest, Len, ByteOrder, Msg) ->
- case decode_body(Env, ReqHdr, Rest, Len, ByteOrder, Msg, enc_reply) of
- {NewEnv, Hdr, Par, TypeCodes} ->
- Result = invoke_request(Hdr, Par, SocketType, TypeCodes, NewEnv),
- evaluate(NewEnv, ReqHdr, Result, TypeCodes, enc_reply, 'no_exception');
- Other ->
- Other
- end.
-
-%%-----------------------------------------------------------------
-%% Func: call_interceptors_out
-%%-----------------------------------------------------------------
--dialyzer({no_improper_lists, call_interceptors_out/7}).
-call_interceptors_out(#giop_env{interceptors = {native, Ref, PIs}, ctx = Ctx} = Env,
- ReqId, Result, Obj, Type, Operation, TypeCodes) ->
- ReqHdr = #request_header{object_key = Obj,
- service_context = Ctx,
- response_expected = true,
- request_id = ReqId,
- operation = Operation},
- NewResult = (catch orber_pi:out_reply(PIs, ReqHdr, Ref, Result, Ctx)),
- {ReplyHdr, Reply, HdrL, _BodyL, Flags} =
- evaluate(Env, ReqHdr, NewResult, TypeCodes, enc_reply_split, Type),
- NewReply =
- case catch orber_pi:out_reply_enc(PIs, ReqHdr, Ref, Reply, Ctx) of
- {'EXCEPTION', Exception} ->
- %% Since evaluate don't need TypeCodes or Status no need to supply
- %% them.
- evaluate(Env, ReqHdr, {'EXCEPTION', Exception}, undefined,
- enc_reply_split, undefined);
- {'EXIT', E} ->
- orber:dbg("[~p] orber_iiop_inrequest:handle_location_forward(~p)~n"
- "Resulted in exit: ~p", [?LINE, PIs, E], ?DEBUG_LEVEL),
- marshal_exception(Env, ReqId,
- #'MARSHAL'{completion_status=?COMPLETED_NO},
- enc_reply);
- R ->
- R
- end,
- MessSize = HdrL+size(NewReply),
- cdr_encode:enc_giop_message_header(Env, 'reply', Flags, MessSize,
- [ReplyHdr|NewReply]);
-call_interceptors_out(#giop_env{interceptors = {portable, _PIs}} = Env,
- ReqId, Result, _Obj, Type, _, TypeCodes) ->
- Hdr = #request_header{response_expected = true,
- request_id = ReqId},
- evaluate(Env, Hdr, Result, TypeCodes, enc_reply, Type);
-call_interceptors_out(Env, ReqId, Result, _Obj, Type, _, TypeCodes) ->
- Hdr = #request_header{response_expected = true,
- request_id = ReqId},
- evaluate(Env, Hdr, Result, TypeCodes, enc_reply, Type).
-
-
-%%-----------------------------------------------------------------
-%% Func: decode_body/2
-%%-----------------------------------------------------------------
-decode_body(#giop_env{version = Version} = Env, ReqHdr, Rest, Len,
- ByteOrder, Message, Func) ->
- case catch cdr_decode:dec_request_body(Version, ReqHdr, Rest, Len,
- ByteOrder, Message) of
- {NewVersion, ReqHdr, Par, TypeCodes} ->
- {Env#giop_env{version = NewVersion}, ReqHdr, Par, TypeCodes};
- {'EXCEPTION', E} ->
- orber:dbg("[~p] orber_iiop_inrequest:decode_body(~p, ~p)~n"
- "Failed decoding request body: ~p",
- [?LINE, ReqHdr, Message, E], ?DEBUG_LEVEL),
- {error, marshal_exception(Env, ReqHdr#request_header.request_id,
- E, Func)};
- Other ->
- %% This cluase takes care of all erranous messages.
- orber:dbg("[~p] orber_iiop_inrequest:decode_body(~p, ~p)~n"
- "Failed decoding request body: ~p",
- [?LINE, ReqHdr, Message, Other], ?DEBUG_LEVEL),
- {error, marshal_exception(Env, ReqHdr#request_header.request_id,
- #'MARSHAL'{completion_status=?COMPLETED_NO},
- Func)}
- end.
-
-
-%%-----------------------------------------------------------------
-%% Func: handle_locate_request/2
-%%-----------------------------------------------------------------
-handle_locate_request(Env, {object_forward, Object, ReqId}) ->
- case catch cdr_encode:enc_locate_reply(
- Env#giop_env{request_id = ReqId,
- tc = {'tk_objref', "", ""},
- result = Object,
- reply_status = 'object_forward'}) of
- {'EXCEPTION', Exception} ->
- orber:dbg("[~p] orber_iiop_inrequest:handle_locate_request(object_forward)~n"
- "Raised the exception: ~p", [?LINE, Exception], ?DEBUG_LEVEL),
- marshal_locate_exception(Env, ReqId, Exception);
- {'EXIT', E} ->
- orber:dbg("[~p] orber_iiop_inrequest:handle_locate_request(object_forward)~n"
- "Resulted in exit: ~p", [?LINE, E], ?DEBUG_LEVEL),
- marshal_locate_exception(Env, ReqId,
- #'MARSHAL'{completion_status=?COMPLETED_NO});
- R ->
- R
- end;
-handle_locate_request(Env, Hdr) ->
- Location = orber_objectkeys:check(Hdr#locate_request_header.object_key),
- case catch cdr_encode:enc_locate_reply(
- Env#giop_env{request_id = Hdr#locate_request_header.request_id,
- reply_status = Location}) of
- {'EXCEPTION', Exception} ->
- orber:dbg("[~p] orber_iiop_inrequest:handle_locate_request(~p)~n"
- "Raised the exception: ~p",
- [?LINE, Location, Exception], ?DEBUG_LEVEL),
- marshal_locate_exception(Env, Hdr#locate_request_header.request_id, Exception);
- {'EXIT', E} ->
- orber:dbg("[~p] orber_iiop_inrequest:handle_locate_request(~p)~n"
- "Resulted in exit: ~p", [?LINE, Location, E], ?DEBUG_LEVEL),
- marshal_locate_exception(Env, Hdr#locate_request_header.request_id,
- #'MARSHAL'{completion_status=?COMPLETED_NO});
- R ->
- R
- end.
-
-%%-----------------------------------------------------------------
-%% Func: invoke_request/2
-%%-----------------------------------------------------------------
-invoke_request(Hdr, Par, normal, TypeCodes, #giop_env{iiop_ssl_port = SSLPort,
- partial_security = PartialSec}) ->
- Result =
- case SSLPort of
- -1 ->
- corba:request_from_iiop(Hdr#request_header.object_key,
- Hdr#request_header.operation,
- Par, [], Hdr#request_header.response_expected,
- Hdr#request_header.service_context);
- _ ->
- case Hdr#request_header.object_key of
- {_,registered,orber_init,_,_,_} ->
- corba:request_from_iiop(Hdr#request_header.object_key,
- Hdr#request_header.operation,
- Par, [],
- Hdr#request_header.response_expected,
- Hdr#request_header.service_context);
- {_,_,_,_,_,Flags} when PartialSec == true,
- ?ORB_FLAG_TEST(Flags, ?ORB_NO_SECURITY) == true ->
- corba:request_from_iiop(Hdr#request_header.object_key,
- Hdr#request_header.operation,
- Par, [],
- Hdr#request_header.response_expected,
- Hdr#request_header.service_context);
- _ ->
- orber:dbg("[~p] orber_iiop_inrequest:invoke_request(~p)~n"
- "SSL do not permit",
- [?LINE, Hdr#request_header.object_key], ?DEBUG_LEVEL),
- {'EXCEPTION', #'NO_PERMISSION'{completion_status=?COMPLETED_NO}}
- end
- end,
- result_to_list(Result, TypeCodes);
-invoke_request(Hdr, Par, ssl, TypeCodes, _) ->
- Result = corba:request_from_iiop(Hdr#request_header.object_key,
- Hdr#request_header.operation,
- Par, [], Hdr#request_header.response_expected,
- Hdr#request_header.service_context),
- result_to_list(Result, TypeCodes).
-
-%%-----------------------------------------------------------------
-%% Func: evaluate/4
-%%-----------------------------------------------------------------
-evaluate(_, Hdr,_,_,_,_) when Hdr#request_header.response_expected == 'false' ->
- oneway;
-evaluate(Env, Hdr, _, _, Func, _)
- when Hdr#request_header.response_expected == 'true_oneway' ->
- %% Special case which only occurs when using IIOP-1.2
- cdr_encode:Func(Env#giop_env{request_id = Hdr#request_header.request_id,
- reply_status = 'no_exception',
- tc = {tk_null,[],[]}, result = null});
-evaluate(Env, Hdr, {'EXCEPTION', Exc}, _, Func, _) ->
- %% The exception can be user defined. Hence, we must check the result.
- case catch marshal_exception(Env, Hdr#request_header.request_id, Exc, Func) of
- {'EXCEPTION', Exception} ->
- orber:dbg("[~p] orber_iiop_inrequest:evaluate(~p)~n"
- "Encoding (reply) exception: ~p",
- [?LINE, Hdr, Exception], ?DEBUG_LEVEL),
- marshal_exception(Env, Hdr#request_header.request_id, Exception, Func);
- {'EXIT', E} ->
- orber:dbg("[~p] orber_iiop_inrequest:evaluate(~p)~n"
- "Encode (reply) resulted in: ~p",
- [?LINE, Hdr, E], ?DEBUG_LEVEL),
- marshal_exception(Env, Hdr#request_header.request_id,
- #'MARSHAL'{completion_status=?COMPLETED_YES}, Func);
- R ->
- R
- end;
-evaluate(#giop_env{version = {1,2}} = Env, Hdr, {'location_forward_perm', NewIOR}, _,
- Func, _)->
- case catch cdr_encode:Func(#giop_env{version = {1,2},
- request_id = Hdr#request_header.request_id,
- reply_status = 'location_forward_perm',
- tc = {{'tk_objref', "", ""}, [],[]},
- result = NewIOR}) of
- {'EXCEPTION', Exception} ->
- orber:dbg("[~p] orber_iiop_inrequest:evaluate(~p) " ++
- "Encoding (reply) exception: ~p",
- [?LINE, Hdr, Exception], ?DEBUG_LEVEL),
- marshal_exception(Env, Hdr#request_header.request_id, Exception, Func);
- {'EXIT', E} ->
- orber:dbg("[~p] orber_iiop_inrequest:evaluate(~p) " ++
- "Encode (reply) resulted in: ~p",
- [?LINE, Hdr, E], ?DEBUG_LEVEL),
- marshal_exception(Env, Hdr#request_header.request_id,
- #'MARSHAL'{completion_status=?COMPLETED_YES}, Func);
- R ->
- R
- end;
-evaluate(Env, Hdr, [Res |OutPar], TypeCodes, Func, Type) ->
- case catch cdr_encode:Func(Env#giop_env{request_id = Hdr#request_header.request_id,
- reply_status = Type,
- tc = TypeCodes, result = Res,
- parameters = OutPar}) of
- {'EXCEPTION', Exception} ->
- orber:dbg("[~p] orber_iiop_inrequest:evaluate(~p, ~p, ~p)~n"
- "Encode exception: ~p",
- [?LINE, Hdr, Res, OutPar, Exception], ?DEBUG_LEVEL),
- marshal_exception(Env, Hdr#request_header.request_id, Exception, Func);
- {'EXIT', E} ->
- orber:dbg("[~p] orber_iiop_inrequest:evaluate(~p, ~p, ~p)~n"
- "Encode exit: ~p",
- [?LINE, Hdr, Res, OutPar, E], ?DEBUG_LEVEL),
- marshal_exception(Env, Hdr#request_header.request_id,
- #'MARSHAL'{completion_status=?COMPLETED_YES}, Func);
- R ->
- R
- end;
-evaluate(Env, Hdr, What, TypeCodes, Func, _) ->
- orber:dbg("[~p] orber_iiop_inrequest:evaluate(~p)~n"
- "Bad reply: ~p~n"
- "Should be: ~p~n"
- "GIOP Env : ~p", [?LINE, Hdr, What, TypeCodes, Env], ?DEBUG_LEVEL),
- marshal_exception(Env, Hdr#request_header.request_id,
- #'INTERNAL'{completion_status=?COMPLETED_MAYBE}, Func).
-
-%%-----------------------------------------------------------------
-%% Utility Functions
-%%-----------------------------------------------------------------
-result_to_list({'oe_location_forward_perm', NewIOR}, _) ->
- {'location_forward_perm', NewIOR};
-result_to_list({'EXCEPTION', E}, _) ->
- {'EXCEPTION', E};
-result_to_list(Result, {_TkRes, _, []}) ->
- [Result];
-result_to_list(Result, {_TkRes, _, _TkOut}) ->
- tuple_to_list(Result).
-
-marshal_exception(Env, Id, Exception, Func) ->
- {TypeOfException, ExceptionTypeCode, NewExc} =
- orber_exceptions:get_def(Exception),
- cdr_encode:Func(Env#giop_env{request_id = Id,
- reply_status = TypeOfException,
- tc = {ExceptionTypeCode, [], []},
- result = NewExc}).
-
-marshal_locate_exception(#giop_env{version = {1,2}} = Env, Id, Exception) ->
- case orber_exceptions:get_def(Exception) of
- {?SYSTEM_EXCEPTION, ExceptionTypeCode, NewExc} ->
- cdr_encode:enc_locate_reply(
- Env#giop_env{request_id = Id,
- reply_status = 'loc_system_exception',
- tc = ExceptionTypeCode, result = NewExc});
- _ ->
- %% This case is impossible (i.e. Orber only throws system
- %% exceptions). But to be on the safe side...
- marshal_locate_exception(Env, Id, #'MARSHAL'
- {completion_status=?COMPLETED_YES})
- end;
-marshal_locate_exception(Env, _Id, _Exception) ->
- %% There is no way to define an exception for IIOP-1.0/1.1 in a
- %% locate_reply.
- cdr_encode:enc_message_error(Env).
diff --git a/lib/orber/src/orber_iiop_insup.erl b/lib/orber/src/orber_iiop_insup.erl
deleted file mode 100644
index 2885cf06c0..0000000000
--- a/lib/orber/src/orber_iiop_insup.erl
+++ /dev/null
@@ -1,86 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_iiop_insup.erl
-%%
-%% Description:
-%% This file contains the IIOP communication supervisor which
-%% holds all active "in proxies"
-%%
-%%-----------------------------------------------------------------
--module(orber_iiop_insup).
-
--behaviour(supervisor).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([start/2, start_connection/4]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([init/1, terminate/2]).
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: start/2
-%%-----------------------------------------------------------------
-start(sup, Opts) ->
- supervisor:start_link({local, orber_iiop_insup}, orber_iiop_insup,
- {sup, Opts});
-start(_A1, _A2) ->
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Server functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: init/1
-%%-----------------------------------------------------------------
-init({sup, _Opts}) ->
- SupFlags = {simple_one_for_one, 500, 100},
- ChildSpec = [
- {name1, {orber_iiop_inproxy, start, []}, temporary,
- 10000, worker, [orber_iiop_inproxy]}
- ],
- {ok, {SupFlags, ChildSpec}};
-init(_Opts) ->
- {ok, []}.
-
-
-%%-----------------------------------------------------------------
-%% Func: terminate/1
-%%-----------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-%%-----------------------------------------------------------------
-%% Func: start_connection/2
-%%-----------------------------------------------------------------
-start_connection(Type, Socket, Ref, ProxyOptions) ->
- supervisor:start_child(orber_iiop_insup, [{connect, Type, Socket,
- Ref, ProxyOptions}]).
-
diff --git a/lib/orber/src/orber_iiop_net.erl b/lib/orber/src/orber_iiop_net.erl
deleted file mode 100644
index e7f54891a2..0000000000
--- a/lib/orber/src/orber_iiop_net.erl
+++ /dev/null
@@ -1,511 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_iiop_net.erl
-%%
-%% Description:
-%% This file contains the IIOP communication server
-%%
-%%-----------------------------------------------------------------
--module(orber_iiop_net).
-
--behaviour(gen_server).
-
--include_lib("orber/src/orber_iiop.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([start/1, connect/5, connections/0,
- sockname2peername/2, peername2sockname/2,
- add_connection/5,
- add/3, remove/1, reconfigure/1, reconfigure/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([init/1, terminate/2, handle_call/3,
- handle_cast/2, handle_info/2, code_change/3]).
-
-%%-----------------------------------------------------------------
-%% Server state record and definitions
-%%-----------------------------------------------------------------
--define(CONNECTION_DB, orber_iiop_net_db).
-
--record(state, {ports=[], max_connections, db, counter = 1, queue}).
-
--record(connection, {pid, socket, type, peerdata, localdata, ref = 0}).
-
--record(listen, {pid, socket, port, type, ref = 0, options, proxy_options = []}).
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: start/1
-%%-----------------------------------------------------------------
-start(Opts) ->
- gen_server:start_link({local, orber_iiop_net}, orber_iiop_net, Opts, []).
-
-add(IP, normal, Options) ->
- Port = orber_tb:keysearch(iiop_port, Options, orber_env:iiop_port()),
- gen_server:call(orber_iiop_net, {add, IP, normal, Port, Options}, infinity);
-add(IP, ssl, Options) ->
- Port = orber_tb:keysearch(iiop_ssl_port, Options, orber_env:iiop_ssl_port()),
- gen_server:call(orber_iiop_net, {add, IP, ssl, Port, Options}, infinity).
-
-remove(Ref) ->
- gen_server:call(orber_iiop_net, {remove, Ref}, infinity).
-
-reconfigure(Options) ->
- lists:foreach(fun(P) ->
- P ! {reconfigure, Options}
- end,
- do_select([{#connection{pid = '$1', _='_'},
- [], ['$1']}])).
-
-reconfigure(Options, Ref) ->
- case do_select([{#connection{ref = Ref, pid = '$1', _='_'},
- [], ['$1']}]) of
- [Pid] when is_pid(Pid) ->
- Pid ! {reconfigure, Options},
- ok;
- _ ->
- {error, "No proxy matched the supplied reference"}
- end.
-
-connect(Type, S, AcceptPid, Ref, ProxyOptions) ->
- gen_server:call(orber_iiop_net, {connect, Type, S, AcceptPid,
- Ref, ProxyOptions}, infinity).
-
-connections() ->
- do_select([{#connection{peerdata = '$1', _='_'}, [], ['$1']}]).
-
-sockname2peername(SockHost, SockPort) ->
- do_select([{#connection{peerdata = '$1',
- localdata = {match_type(SockHost),
- match_type(SockPort)},
- _='_'}, [], ['$1']}]).
-
-
-peername2sockname(PeerHost, PeerPort) ->
- do_select([{#connection{peerdata = {match_type(PeerHost),
- match_type(PeerPort)},
- localdata = '$1',
- _='_'}, [], ['$1']}]).
-
-do_select(Pattern) ->
- case catch ets:select(?CONNECTION_DB, Pattern) of
- {'EXIT', _What} ->
- [];
- Result ->
- Result
- end.
-
-match_type(0) ->
- %% Wildcard port number
- '_';
-match_type("") ->
- %% Wildcard host
- '_';
-match_type(Key) ->
- %% Wildcard not used.
- Key.
-
-add_connection(Socket, Type, PeerData, LocalData, Ref) ->
- ets:insert(?CONNECTION_DB, #connection{pid = self(), socket = Socket,
- type = Type, peerdata = PeerData,
- localdata = LocalData, ref = Ref}).
-
-%%-----------------------------------------------------------------
-%% Server functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: init/1
-%%-----------------------------------------------------------------
-init(Options) ->
- process_flag(trap_exit, true),
- {ok, parse_options(Options,
- #state{max_connections = orber:iiop_max_in_connections(),
- db = ets:new(?CONNECTION_DB, [set, public,
- named_table,
- {keypos, 2}]),
- queue = queue:new()})}.
-
-%%-----------------------------------------------------------------
-%% Func: terminate/1
-%%-----------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-%%-----------------------------------------------------------------
-%% Func: get_options/2
-%%-----------------------------------------------------------------
-get_options(normal, _Options) ->
- [];
-get_options(ssl, Options) ->
- SSLOpts =
- case orber_tb:keysearch(ssl_server_options, Options,
- orber_env:ssl_server_options()) of
- [] ->
- Verify = orber_tb:keysearch(ssl_server_verify, Options,
- orber_env:ssl_server_verify()),
- Depth = orber_tb:keysearch(ssl_server_depth, Options,
- orber_env:ssl_server_depth()),
- Cert = orber_tb:keysearch(ssl_server_certfile, Options,
- orber_env:ssl_server_certfile()),
- CaCert = orber_tb:keysearch(ssl_server_cacertfile, Options,
- orber_env:ssl_server_cacertfile()),
- Pwd = orber_tb:keysearch(ssl_server_password, Options,
- orber_env:ssl_server_password()),
- Key = orber_tb:keysearch(ssl_server_keyfile, Options,
- orber_env:ssl_server_keyfile()),
- Ciphers = orber_tb:keysearch(ssl_server_ciphers, Options,
- orber_env:ssl_server_ciphers()),
- Timeout = orber_tb:keysearch(ssl_server_cachetimeout, Options,
- orber_env:ssl_server_cachetimeout()),
- KeepAlive = orber_tb:keysearch(ssl_server_cachetimeout, Options,
- orber_env:iiop_ssl_in_keepalive()),
- [{verify, Verify},
- {depth, Depth},
- {certfile, Cert},
- {cacertfile, CaCert},
- {password, Pwd},
- {keyfile, Key},
- {ciphers, Ciphers},
- {cachetimeout, Timeout},
- {keepalive, KeepAlive}];
- Opts ->
- case orber_tb:check_illegal_tcp_options(Opts) of
- ok ->
- check_old_ssl_server_options(Options),
- Opts;
- {error, IllegalOpts} ->
- error_logger:error_report([{application, orber},
- "TCP options not allowed to set on a connection",
- IllegalOpts]),
- error("Illegal TCP option")
- end
- end,
- ssl_server_extra_options(SSLOpts, []).
-
-%%-----------------------------------------------------------------
-%% Func: parse_options/2
-%%-----------------------------------------------------------------
-parse_options([{port, Type, Port} | Rest], State) ->
- Options = get_options(Type, []),
- Family = orber_env:ip_version(),
- IPFamilyOptions =
- case Family of
- inet -> [inet];
- inet6 -> [inet6, {ipv6_v6only, true}]
- end,
- Options2 =
- case orber_env:ip_address_variable_defined() of
- false ->
- IPFamilyOptions ++ Options;
- Host ->
- {ok, IP} = inet:getaddr(Host, Family),
- IPFamilyOptions ++ [{ip, IP} |Options]
- end,
-
- {ok, Listen, NewPort} = orber_socket:listen(Type, Port, Options2, true),
- {ok, Pid} = orber_iiop_socketsup:start_accept(Type, Listen, 0),
- link(Pid),
- ets:insert(?CONNECTION_DB, #listen{pid = Pid, socket = Listen,
- port = NewPort, type = Type,
- options = Options2}),
- parse_options(Rest, State);
-parse_options([], State) ->
- State.
-
-ssl_server_extra_options([], Acc) ->
- Acc;
-ssl_server_extra_options([{_Type, []}|T], Acc) ->
- ssl_server_extra_options(T, Acc);
-ssl_server_extra_options([{_Type, infinity}|T], Acc) ->
- ssl_server_extra_options(T, Acc);
-ssl_server_extra_options([{Type, Value}|T], Acc) ->
- ssl_server_extra_options(T, [{Type, Value}|Acc]).
-
-filter_options([], Acc) ->
- Acc;
-filter_options([{verify, _}|T], Acc) ->
- filter_options(T, Acc);
-filter_options([{depth, _}|T], Acc) ->
- filter_options(T, Acc);
-filter_options([{certfile, _}|T], Acc) ->
- filter_options(T, Acc);
-filter_options([{cacertfile, _}|T], Acc) ->
- filter_options(T, Acc);
-filter_options([{password, _}|T], Acc) ->
- filter_options(T, Acc);
-filter_options([{keyfile, _}|T], Acc) ->
- filter_options(T, Acc);
-filter_options([{ciphers, _}|T], Acc) ->
- filter_options(T, Acc);
-filter_options([{cachetimeout, _}|T], Acc) ->
- filter_options(T, Acc);
-filter_options([H|T], Acc) ->
- filter_options(T, [H|Acc]).
-
-%%-----------------------------------------------------------------
-%% Func: handle_call/3
-%%-----------------------------------------------------------------
-handle_call({remove, Ref}, _From, State) ->
- case do_select([{#listen{ref = Ref, pid = '$1', socket = '$2',
- type = '$3', _='_'}, [], [{{'$1', '$2', '$3'}}]}]) of
- [{Pid, Listen, Type}|_] when is_pid(Pid) ->
- unlink(Pid),
- ets:delete(?CONNECTION_DB, Pid),
- %% Just close the listen socket. Will cause the accept processs
- %% to terminate.
- orber_socket:close(Type, Listen),
- stop_proxies(do_select([{#connection{ref = Ref, pid = '$1', _='_'},
- [], ['$1']}])),
- {reply, ok,
- State#state{queue =
- from_list(
- lists:keydelete(Pid, 1,
- queue:to_list(State#state.queue)))}};
- _ ->
- {reply, ok, State}
- end;
-handle_call({add, IP, Type, Port, AllOptions}, _From, State) ->
- Family = orber_tb:keysearch(ip_family, AllOptions, orber_env:ip_version()),
- IPFamilyOptions =
- case Family of
- inet -> [inet];
- inet6 -> [inet6, {ipv6_v6only, true}]
- end,
- case inet:getaddr(IP, Family) of
- {ok, IPTuple} ->
- try
- Options = IPFamilyOptions ++ [{ip, IPTuple} |get_options(Type, AllOptions)],
- Ref = make_ref(),
- ProxyOptions = filter_options(AllOptions, []),
- case orber_socket:listen(Type, Port, Options, false) of
- {ok, Listen, NewPort} ->
- {ok, Pid} = orber_iiop_socketsup:start_accept(Type, Listen, Ref,
- ProxyOptions),
- link(Pid),
- ets:insert(?CONNECTION_DB, #listen{pid = Pid,
- socket = Listen,
- port = NewPort,
- type = Type, ref = Ref,
- options = Options,
- proxy_options = ProxyOptions}),
- {reply, {ok, Ref}, State};
- Error ->
- {reply, Error, State}
- end
- catch
- error:Reason ->
- {reply, {error, Reason}, State}
- end;
- Other ->
- {reply, Other, State}
- end;
-handle_call({connect, Type, Socket, _AcceptPid, AccepRef, ProxyOptions}, _From, State)
- when State#state.max_connections == infinity;
- State#state.max_connections > State#state.counter ->
- case catch access_allowed(Type, Socket, Type) of
- true ->
- case orber_iiop_insup:start_connection(Type, Socket,
- AccepRef, ProxyOptions) of
- {ok, Pid} when is_pid(Pid) ->
- link(Pid),
- {reply, {ok, Pid, true}, update_counter(State, 1)};
- Other ->
- {reply, Other, State}
- end;
- _ ->
- {H, P} = orber_socket:peerdata(Type, Socket),
- orber_tb:info("Blocked connect attempt from ~s - ~p", [H, P]),
- {reply, denied, State}
- end;
-handle_call({connect, Type, Socket, AcceptPid, AccepRef, ProxyOptions}, _From,
- #state{queue = Q} = State) ->
- case catch access_allowed(Type, Socket, Type) of
- true ->
- case orber_iiop_insup:start_connection(Type, Socket,
- AccepRef, ProxyOptions) of
- {ok, Pid} when is_pid(Pid) ->
- link(Pid),
- Ref = erlang:make_ref(),
- {reply, {ok, Pid, Ref},
- update_counter(State#state{queue =
- queue:in({AcceptPid, Ref}, Q)}, 1)};
- Other ->
- {reply, Other, State}
- end;
- _ ->
- {H, P} = orber_socket:peerdata(Type, Socket),
- orber_tb:info("Blocked connect attempt from ~s - ~p", [H, P]),
- {reply, denied, State}
- end;
-handle_call(_, _, State) ->
- {noreply, State}.
-
-stop_proxies([H|T]) ->
- catch orber_iiop_inproxy:stop(H),
- stop_proxies(T);
-stop_proxies([]) ->
- ok.
-
-access_allowed(Type, Socket, Type) ->
- Flags = orber:get_flags(),
- case ?ORB_FLAG_TEST(Flags, ?ORB_ENV_USE_ACL_INCOMING) of
- false ->
- true;
- true ->
- SearchFor =
- case Type of
- normal ->
- tcp_in;
- ssl ->
- ssl_in
- end,
- {ok, {Host, Port}} = orber_socket:peername(Type, Socket),
- case orber_acl:match(Host, SearchFor, true) of
- {true, [], 0} ->
- true;
- {true, [], Port} ->
- true;
- {true, [], {Min, Max}} when Port >= Min, Port =< Max ->
- true;
- {true, Interfaces, 0} ->
- get_sockethost(Type, Socket),
- lists:member(get_sockethost(Type, Socket), Interfaces);
- {true, Interfaces, Port} ->
- lists:member(get_sockethost(Type, Socket), Interfaces);
- {true, Interfaces, {Min, Max}} when Port >= Min, Port =< Max ->
- lists:member(get_sockethost(Type, Socket), Interfaces);
- _ ->
- false
- end
- end.
-
-get_sockethost(Type, Socket) ->
- case orber_socket:peername(Type, Socket) of
- {ok, {Addr, _Port}} ->
- orber_env:addr2str(Addr);
- _ ->
- false
- end.
-
-%%------------------------------------------------------------
-%% Standard gen_server cast handle
-%%------------------------------------------------------------
-handle_cast(_, State) ->
- {noreply, State}.
-
-%%------------------------------------------------------------
-%% Standard gen_server handles
-%%------------------------------------------------------------
-handle_info({'EXIT', Pid, _Reason}, State) when is_pid(Pid) ->
- case ets:lookup(?CONNECTION_DB, Pid) of
- [#listen{pid = Pid, socket = Listen, port = Port, type = Type,
- ref = Ref, options = Options, proxy_options = POpts}] ->
- ets:delete(?CONNECTION_DB, Pid),
- unlink(Pid),
- {ok, NewPid} = orber_iiop_socketsup:start_accept(Type, Listen,
- Ref, POpts),
- link(NewPid),
- ets:insert(?CONNECTION_DB, #listen{pid = NewPid, socket = Listen,
- port = Port, type = Type,
- ref = Ref, options = Options,
- proxy_options = POpts}),
- %% Remove the connection if it's in the queue.
- {noreply,
- State#state{queue =
- from_list(
- lists:keydelete(Pid, 1,
- queue:to_list(State#state.queue)))}};
- [#connection{pid = Pid}] ->
- ets:delete(?CONNECTION_DB, Pid),
- unlink(Pid),
- case queue:out(State#state.queue) of
- {empty, _} ->
- {noreply, update_counter(State, -1)};
- {{value, {AcceptPid, Ref}}, Q} ->
- AcceptPid ! {Ref, ok},
- {noreply, update_counter(State#state{queue = Q}, -1)}
- end;
- [] ->
- {noreply, State}
- end;
-handle_info(_, State) ->
- {noreply, State}.
-
-from_list(List) ->
- from_list(List, queue:new()).
-
-from_list([], Q) ->
- Q;
-from_list([H|T], Q) ->
- NewQ = queue:in(H, Q),
- from_list(T, NewQ).
-
-
-%%-----------------------------------------------------------------
-%% Func: code_change/3
-%%-----------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%-----------------------------------------------------------------
-%% Internal Functions
-%%-----------------------------------------------------------------
-update_counter(#state{max_connections = infinity} = State, _) ->
- State;
-update_counter(State, Value) ->
- State#state{counter = State#state.counter + Value}.
-
-
-check_old_ssl_server_options(Options) ->
- try
- 0 = orber_tb:keysearch(ssl_server_verify, Options,
- orber_env:ssl_server_verify()),
- 1 = orber_tb:keysearch(ssl_server_depth, Options,
- orber_env:ssl_server_depth()),
- [] = orber_tb:keysearch(ssl_server_certfile, Options,
- orber_env:ssl_server_certfile()),
- [] = orber_tb:keysearch(ssl_server_cacertfile, Options,
- orber_env:ssl_server_cacertfile()),
- [] = orber_tb:keysearch(ssl_server_password, Options,
- orber_env:ssl_server_password()),
- [] = orber_tb:keysearch(ssl_server_keyfile, Options,
- orber_env:ssl_server_keyfile()),
- [] = orber_tb:keysearch(ssl_server_ciphers, Options,
- orber_env:ssl_server_ciphers()),
- infinity = orber_tb:keysearch(ssl_server_cachetimeout, Options,
- orber_env:ssl_server_cachetimeout()),
- false = orber_tb:keysearch(iiop_ssl_in_keepalive, Options,
- orber_env:iiop_ssl_in_keepalive())
- catch
- _:_ ->
- io:format("hej\n",[]),
- error_logger:warning_report([{application, orber},
- "Ignoring deprecated ssl server options used together with the ssl_server_options"])
- end.
-
diff --git a/lib/orber/src/orber_iiop_net_accept.erl b/lib/orber/src/orber_iiop_net_accept.erl
deleted file mode 100644
index 2a53d55cea..0000000000
--- a/lib/orber/src/orber_iiop_net_accept.erl
+++ /dev/null
@@ -1,95 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_iiop_net_accept.erl
-%%
-%% Description:
-%% This file contains the process which are waiting in accept for new
-%% connections.
-%%
-%%
-%%-----------------------------------------------------------------
--module(orber_iiop_net_accept).
-
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([start/4]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([net_accept/5]).
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: start/2
-%%-----------------------------------------------------------------
-start(Type, Listen, Ref, ProxyOptions) ->
- Pid = proc_lib:spawn_link(?MODULE, net_accept,
- [Type, Listen, self(), Ref, ProxyOptions]),
- {ok, Pid}.
-
-%%-----------------------------------------------------------------
-%% Internal Functions
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% Func: net_accept/3
-%%-----------------------------------------------------------------
-net_accept(Type, ListenFd, Parent, Ref, ProxyOptions) ->
- case catch orber_socket:accept(Type, ListenFd) of
- {'EXCEPTION', _E} ->
- ok;
- S ->
- case orber_iiop_net:connect(Type, S, self(), Ref, ProxyOptions) of
- {ok, Pid, ReadyToGo} ->
- case orber_socket:controlling_process(Type, S, Pid) of
- ok ->
- orber_iiop_inproxy:post_accept(Pid, Type, S);
- _Reason ->
- orber_socket:close(Type, S),
- gen_server:cast(Pid, stop),
- orber_socket:clear(Type, S)
- end,
- ready_to_go(ReadyToGo);
- denied ->
- orber_socket:close(Type, S),
- orber_socket:clear(Type, S);
- _ ->
- orber_socket:close(Type, S),
- orber_socket:clear(Type, S)
- end,
- net_accept(Type, ListenFd, Parent, Ref, ProxyOptions)
- end.
-
-ready_to_go(true) ->
- ok;
-ready_to_go(Ref) ->
- receive
- {Ref, ok} ->
- ok
- end.
-
diff --git a/lib/orber/src/orber_iiop_outproxy.erl b/lib/orber/src/orber_iiop_outproxy.erl
deleted file mode 100644
index 1406a1ad56..0000000000
--- a/lib/orber/src/orber_iiop_outproxy.erl
+++ /dev/null
@@ -1,511 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_iiop_outproxy.erl
-%%
-%% Description:
-%% This file contains the IIOP "proxy" for outgoing connections
-%%
-%%
-%%-----------------------------------------------------------------
--module(orber_iiop_outproxy).
-
--behaviour(gen_server).
-
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/include/corba.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([start/0, start/1, request/5, cancel/2, cancel/3]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- code_change/3, terminate/2, stop/2, stop/1, checkheaders/1]).
-
-%%-----------------------------------------------------------------
-%% Macros/Defines
-%%-----------------------------------------------------------------
--define(DEBUG_LEVEL, 7).
-
--record(state, {stype, socket, db, timeout, client_timeout, host, port, parent,
- error_reason = {'EXCEPTION', #'COMM_FAILURE'
- {completion_status=?COMPLETED_MAYBE}}}).
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-start() ->
- ignore.
-
-start(Opts) ->
- gen_server:start_link(orber_iiop_outproxy, Opts, []).
-
-request(Pid, true, Timeout, Msg, RequestId) ->
- %% Why not simply use gen_server:call? We must be able to receive
- %% more than one reply (i.e. fragmented messages).
- MRef = erlang:monitor(process, Pid),
- gen_server:cast(Pid, {request, Timeout, Msg, RequestId, self(), MRef}),
- receive
- {MRef, Reply} ->
- erlang:demonitor(MRef, [flush]),
- Reply;
- {'DOWN', MRef, _, Pid, _Reason} when is_pid(Pid) ->
- receive
- %% Clear EXIT message from queue
- {'EXIT', _Pid, _What} ->
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_MAYBE})
- after 0 ->
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_MAYBE})
- end;
- {fragmented, GIOPHdr, Bytes, RequestId, MRef} ->
- collect_fragments(GIOPHdr, [], Bytes, Pid, RequestId, MRef)
- end;
-request(Pid, _, _, Msg, _RequestId) ->
- %% No response expected
- gen_server:cast(Pid, {oneway_request, Msg}).
-
-cancel(Pid, RequestId) ->
- gen_server:cast(Pid, {cancel, RequestId}).
-
-cancel(Pid, RequestId, MRef) ->
- gen_server:cast(Pid, {cancel, RequestId, MRef, self()}).
-
-%%-----------------------------------------------------------------
-%% Internal interface functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: stop/2
-%%-----------------------------------------------------------------
-stop(Pid, Timeout) ->
- gen_server:call(Pid, stop, Timeout).
-stop(Pid) ->
- gen_server:cast(Pid, stop).
-
-
-%%-----------------------------------------------------------------
-%% Server functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: init/1
-%%-----------------------------------------------------------------
-init({connect, Host, Port, SocketType, SocketOptions, Parent, Key, NewKey}) ->
- process_flag(trap_exit, true),
- case catch orber_socket:connect(SocketType, Host, Port,
- orber_socket:get_ip_family_opts(Host) ++ SocketOptions) of
- {'EXCEPTION', _E} ->
- ignore;
- %% We used to reply the below but since this would generate a CRASH REPORT
- %% if '-boot start_sasl' used. Due to a request to change this behaviour
- %% we did.
- %% {stop, {'EXCEPTION', E}};
- Socket ->
- SockData = orber_socket:sockdata(SocketType, Socket),
- orber_iiop_pm:add_connection(Key, NewKey, SockData),
- Timeout = orber:iiop_connection_timeout(),
- {ok, #state{stype = SocketType, socket = Socket,
- db = ets:new(orber_outgoing_requests, [set]),
- timeout = Timeout, client_timeout = orber:iiop_timeout(),
- host = Host, port = Port, parent = Parent}, Timeout}
- end.
-
-%%-----------------------------------------------------------------
-%% Func: terminate/2
-%%-----------------------------------------------------------------
-terminate(_Reason, #state{db = OutRequests, error_reason = ER}) ->
- %% Kill all proxies and delete table before terminating
- notify_clients(OutRequests, ets:first(OutRequests), ER),
- ets:delete(OutRequests),
- ok.
-
-notify_clients(_, '$end_of_table', _ER) ->
- ok;
-notify_clients(OutRequests, Key, ER) ->
- case ets:lookup(OutRequests, Key) of
- [{_, Pid, TRef, MRef}] ->
- cancel_timer(TRef),
- Pid ! {MRef, ER},
- notify_clients(OutRequests, ets:next(OutRequests, Key), ER)
- end.
-
-%%-----------------------------------------------------------------
-%% Func: handle_call/3
-%%-----------------------------------------------------------------
-handle_call(stop, _From, State) ->
- {stop, normal, ok, State};
-handle_call(X, From, State) ->
- orber:dbg("[~p] orber_iiop_outproxy:handle_call(~p);~n"
- "Un-recognized call from ~p", [?LINE, X, From], ?DEBUG_LEVEL),
- {noreply, State, State#state.timeout}.
-
-%%-----------------------------------------------------------------
-%% Func: handle_cast/2
-%%-----------------------------------------------------------------
-handle_cast({request, Timeout, Msg, RequestId, From, MRef},
- #state{client_timeout = DefaultTimeout} = State) ->
- orber_socket:write(State#state.stype, State#state.socket, Msg),
- true = ets:insert(State#state.db, {RequestId, From,
- start_timer(Timeout, DefaultTimeout, RequestId),
- MRef}),
- {noreply, State, State#state.timeout};
-handle_cast({oneway_request, Msg}, State) ->
- orber_socket:write(State#state.stype, State#state.socket, Msg),
- {noreply, State, State#state.timeout};
-handle_cast({cancel, ReqId}, State) ->
- case ets:lookup(State#state.db, ReqId) of
- [{ReqId, _From, TRef, _MRef}] ->
- cancel_timer(TRef),
- ets:delete(State#state.db, ReqId),
- orber:dbg("[~p] orber_iiop_outproxy:handle_info(~p);~n"
- "Request cancelled", [?LINE, State], ?DEBUG_LEVEL),
- {noreply, State, State#state.timeout};
- _ ->
- {noreply, State, State#state.timeout}
- end;
-handle_cast({cancel, ReqId, MRef, From}, State) ->
- case ets:lookup(State#state.db, ReqId) of
- [{ReqId, From, TRef, MRef}] ->
- cancel_timer(TRef),
- ets:delete(State#state.db, ReqId),
- From ! {MRef, ReqId, cancelled},
- orber:dbg("[~p] orber_iiop_outproxy:handle_info(~p);
-Request cancelled", [?LINE, State], ?DEBUG_LEVEL),
- {noreply, State, State#state.timeout};
- _ ->
- From ! {MRef, ReqId, cancelled},
- {noreply, State, State#state.timeout}
- end;
-handle_cast(stop, State) ->
- {stop, normal, State};
-handle_cast(X, State) ->
- orber:dbg("[~p] orber_iiop_outproxy:handle_cast(~p);
-Un-recognized cast.", [?LINE, X], ?DEBUG_LEVEL),
- {noreply, State, State#state.timeout}.
-
-%%-----------------------------------------------------------------
-%% Func: handle_info/2
-%%-----------------------------------------------------------------
-handle_info({tcp, _Socket, Bytes}, State) ->
- handle_reply(Bytes, State);
-handle_info({ssl, _Socket, Bytes}, State) ->
- handle_reply(Bytes, State);
-handle_info({tcp_closed, _Socket}, State) ->
- {stop, normal, State};
-handle_info({ssl_closed, _Socket}, State) ->
- {stop, normal, State};
-handle_info({tcp_error, Socket, Reason}, #state{socket = Socket, host = Host,
- port = Port} = State) ->
- orber:error("[~p] IIOP proxy received the TCP error message: ~p~n"
- "The server-side ORB is located at '~p:~p'~n"
- "See the gen_tcp/inet documentation for more information.",
- [?LINE, Reason, Host, Port], ?DEBUG_LEVEL),
- {stop, normal, State};
-handle_info({ssl_error, Socket, Reason}, #state{socket = Socket, host = Host,
- port = Port} = State) ->
- orber:error("[~p] IIOP proxy received the SSL error message: ~p~n"
- "The server-side ORB is located at '~p:~p'~n"
- "See the SSL-application documentation for more information.",
- [?LINE, Reason, Host, Port], ?DEBUG_LEVEL),
- {stop, normal, State};
-handle_info({timeout, _TRef, ReqId}, State) ->
- case ets:lookup(State#state.db, ReqId) of
- [{ReqId, Pid, _, MRef}] ->
- ets:delete(State#state.db, ReqId),
- Pid ! {MRef, {'EXCEPTION', #'TIMEOUT'{completion_status=?COMPLETED_MAYBE}}},
- orber:dbg("[~p] orber_iiop_outproxy:handle_info(~p, ~p);~n"
- "Request timed out",
- [?LINE, State#state.host, State#state.port], ?DEBUG_LEVEL),
- {noreply, State, State#state.timeout};
- _ ->
- {noreply, State, State#state.timeout}
- end;
-handle_info(stop, State) ->
- {stop, normal, State};
-handle_info(timeout, State) ->
- case ets:info(State#state.db, size) of
- 0 ->
- orber:dbg("[~p] orber_iiop_outproxy:handle_info(~p, ~p);~n"
- "Outgoing connection timed out after ~p msec",
- [?LINE, State#state.host, State#state.port,
- State#state.timeout], ?DEBUG_LEVEL),
- {stop, normal, State};
- _Amount ->
- %% Still pending request, cannot close the connection.
- {noreply, State, State#state.timeout}
- end;
-handle_info({'EXIT', Parent, Reason}, #state{parent = Parent} = State) ->
- orber:dbg("[~p] orber_iiop_outproxy:handle_info(~p);~nParent terminated.",
- [?LINE, Reason], ?DEBUG_LEVEL),
- {stop, normal, State};
-handle_info({reconfigure, _Options}, State) ->
- %% Currently there are no parameters that can be changed.
- {noreply, State, State#state.timeout};
-handle_info(X, State) ->
- orber:dbg("[~p] orber_iiop_outproxy:handle_info(~p);~nUn-recognized info.",
- [?LINE, X], ?DEBUG_LEVEL),
- {noreply, State, State#state.timeout}.
-
-
-handle_reply(Bytes, State) ->
- %% Check IIOP headers and fetch request id
- case catch checkheaders(cdr_decode:dec_giop_message_header(Bytes)) of
- {'reply', ReplyHeader, Rest, Len, ByteOrder} ->
- case ets:lookup(State#state.db, ReplyHeader#reply_header.request_id) of
- [{_, Pid, TRef, MRef}] ->
- %% Send reply to the correct request process
- cancel_timer(TRef),
- Pid ! {MRef, {reply, ReplyHeader, Rest, Len, ByteOrder, Bytes}},
- ets:delete(State#state.db, ReplyHeader#reply_header.request_id),
- {noreply, State, State#state.timeout};
- _ ->
- {noreply, State, State#state.timeout}
- end;
- {'locate_reply', LocateReplyHeader, LocateRest, LocateLen, LocateByteOrder} ->
- case ets:lookup(State#state.db,
- LocateReplyHeader#locate_reply_header.request_id) of
- [{_, Pid, TRef, MRef}] ->
- %% Send reply to the correct request process
- cancel_timer(TRef),
- Pid ! {MRef, {locate_reply, LocateReplyHeader,
- LocateRest, LocateLen, LocateByteOrder}},
- ets:delete(State#state.db,
- LocateReplyHeader#locate_reply_header.request_id),
- {noreply, State, State#state.timeout};
- _ ->
- {noreply, State, State#state.timeout}
- end;
- {fragment, GIOPHdr, ReqId, false} ->
- %% Last fragment, cancel timer and remove from DB.
- case ets:lookup(State#state.db, ReqId) of
- [{_, Pid, TRef, MRef}] ->
- cancel_timer(TRef),
- Pid ! {fragment, GIOPHdr, ReqId, MRef},
- ets:delete(State#state.db, ReqId),
- {noreply, State, State#state.timeout};
- _ ->
- %% Probably cancelled
- {noreply, State, State#state.timeout}
- end;
- {fragment, GIOPHdr, ReqId, _} ->
- %% More fragments expected
- case ets:lookup(State#state.db, ReqId) of
- [{_, Pid, _, MRef}] ->
- Pid ! {fragment, GIOPHdr, ReqId, MRef},
- {noreply, State, State#state.timeout};
- _ ->
- %% Probably cancelled
- {noreply, State, State#state.timeout}
- end;
- {fragmented, GIOPHdr, ReqId} ->
- %% This the initial message (i.e. a LocateReply or Reply).
- case ets:lookup(State#state.db, ReqId) of
- [{_, Pid, _TRef, MRef}] ->
- Pid ! {fragmented, GIOPHdr, Bytes, ReqId, MRef},
- {noreply, State, State#state.timeout};
- _ ->
- {noreply, State, State#state.timeout}
- end;
- {'EXCEPTION', DecodeException} ->
- orber:dbg("[~p] orber_iiop_outproxy:handle_reply(~p); decode exception(~p).",
- [?LINE, Bytes, DecodeException], ?DEBUG_LEVEL),
- {noreply, State, State#state.timeout};
- {'EXIT', message_error} ->
- orber:dbg("[~p] orber_iiop_outproxy:handle_reply(~p); message error.",
- [?LINE, Bytes], ?DEBUG_LEVEL),
- ME = cdr_encode:enc_message_error(#giop_env{version =
- orber:giop_version()}),
- orber_socket:write(State#state.stype, State#state.socket, ME),
- {noreply, State, State#state.timeout};
- {'EXIT', R} ->
- orber:dbg("[~p] orber_iiop_outproxy:handle_reply(~p); got exit(~p)",
- [?LINE, Bytes, R], ?DEBUG_LEVEL),
- {noreply, State, State#state.timeout};
- close_connection ->
- orber:dbg("[~p] orber_iiop_outproxy:handle_reply();
-The Server-side ORB closed the connection.", [?LINE], ?DEBUG_LEVEL),
- {stop, normal, State};
- {error, no_reply} ->
- {noreply, State, State#state.timeout};
- X ->
- orber:dbg("[~p] orber_iiop_outproxy:handle_reply(~p); message error(~p).",
- [?LINE, Bytes, X], ?DEBUG_LEVEL),
- {noreply, State, State#state.timeout}
- end.
-
-
-%%-----------------------------------------------------------------
-%% Func: code_change/3
-%%-----------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-checkheaders(#giop_message{message_type = ?GIOP_MSG_CLOSE_CONNECTION}) ->
- close_connection;
-checkheaders(#giop_message{message_type = ?GIOP_MSG_FRAGMENT,
- giop_version = {1,2},
- fragments = MoreFrag} = GIOPHdr) ->
- %% A fragment; we must have received a Request or LocateRequest
- %% with fragment-flag set to true.
- %% We need to decode the header to get the request-id.
- ReqId = cdr_decode:peek_request_id(GIOPHdr#giop_message.byte_order,
- GIOPHdr#giop_message.message),
- {fragment, GIOPHdr, ReqId, MoreFrag};
-checkheaders(#giop_message{fragments = true,
- giop_version = {1,2}} = GIOPHdr) ->
- %% Must be a Reply or LocateReply which have been fragmented.
- %% We need to decode the header to get the request-id.
- ReqId = cdr_decode:peek_request_id(GIOPHdr#giop_message.byte_order,
- GIOPHdr#giop_message.message),
- {fragmented, GIOPHdr, ReqId};
-checkheaders(#giop_message{fragments = false,
- message_type = ?GIOP_MSG_REPLY} = GIOPHdr) ->
- {ReplyHeader, Rest, Len} =
- cdr_decode:dec_reply_header(GIOPHdr#giop_message.giop_version,
- GIOPHdr#giop_message.message,
- ?GIOP_HEADER_SIZE,
- GIOPHdr#giop_message.byte_order),
- {'reply', ReplyHeader, Rest, Len, GIOPHdr#giop_message.byte_order};
-checkheaders(#giop_message{fragments = false,
- message_type = ?GIOP_MSG_LOCATE_REPLY} = GIOPHdr) ->
- {LocateReplyHeader, Rest, Len} =
- cdr_decode:dec_locate_reply_header(GIOPHdr#giop_message.giop_version,
- GIOPHdr#giop_message.message,
- ?GIOP_HEADER_SIZE,
- GIOPHdr#giop_message.byte_order),
- {'locate_reply', LocateReplyHeader, Rest, Len, GIOPHdr#giop_message.byte_order};
-checkheaders(What) ->
- orber:dbg("[~p] orber_iiop_outproxy:checkheaders(~p)
-Un-recognized GIOP header.", [?LINE, What], ?DEBUG_LEVEL),
- {error, no_reply}.
-
-
-cancel_timer(infinity) ->
- ok;
-cancel_timer(TRef) ->
- erlang:cancel_timer(TRef).
-
-start_timer(infinity, infinity, _) ->
- infinity;
-start_timer(infinity, Timeout, RequestId) ->
- erlang:start_timer(Timeout, self(), RequestId);
-start_timer(Timeout, _, RequestId) ->
- erlang:start_timer(Timeout, self(), RequestId).
-
-
-
-collect_fragments(GIOPHdr1, InBuffer, Bytes, Proxy, RequestId, MRef) ->
- receive
- %% There are more framents to come; just collect this message and wait for
- %% the rest.
- {fragment, #giop_message{byte_order = _ByteOrder,
- message = Message,
- fragments = true} = GIOPHdr2, RequestId, MRef} ->
- case catch cdr_decode:dec_message_header(null, GIOPHdr2, Message) of
- {_, #fragment_header{}, FragBody, _, _} ->
- collect_fragments(GIOPHdr1, [FragBody|InBuffer],
- Bytes, Proxy, RequestId, MRef);
- Other ->
- cancel(Proxy, RequestId, MRef),
- clear_queue(Proxy, RequestId, MRef),
- orber:dbg("[~p] orber_iiop:collect_fragments(~p)",
- [?LINE, Other], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 18),
- completion_status=?COMPLETED_YES})
- end;
- %% This is the last fragment. Now we can but together the fragments, decode
- %% the reply and send it to the client.
- {fragment, #giop_message{byte_order = ByteOrder,
- message = Message} = GIOPHdr2, RequestId, MRef} ->
- erlang:demonitor(MRef, [flush]),
- case catch cdr_decode:dec_message_header(null, GIOPHdr2, Message) of
- {_, #fragment_header{}, FragBody, _, _} ->
- %% This buffer is all the fragments concatenated.
- Buffer = lists:reverse([FragBody|InBuffer]),
-
- %% Create a GIOP-message which is exactly as if hadn't been fragmented.
- NewGIOP = GIOPHdr1#giop_message
- {message = list_to_binary([GIOPHdr1#giop_message.message|Buffer]),
- fragments = false},
- case checkheaders(NewGIOP) of
- {'reply', ReplyHeader, Rest, Len, ByteOrder} ->
- %% We must keep create a copy of all bytes, as if the
- %% message wasn't fragmented, to be able handle TypeCode
- %% indirection.
- {'reply', ReplyHeader, Rest, Len, ByteOrder,
- list_to_binary([Bytes|Buffer])};
- {'locate_reply', ReplyHdr, Rest, Len, ByteOrder} ->
- {'locate_reply', ReplyHdr, Rest, Len, ByteOrder};
- Error ->
- orber:dbg("[~p] orber_iiop:collect_fragments(~p, ~p);
-Unable to decode Reply or LocateReply header",[?LINE, NewGIOP, Error], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 18),
- completion_status=?COMPLETED_YES})
- end;
- Other ->
- orber:dbg("[~p] orber_iiop:collect_fragments(~p);",
- [?LINE, Other], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{minor=(?ORBER_VMCID bor 18),
- completion_status=?COMPLETED_YES})
- end;
- {MRef, {'EXCEPTION', E}} ->
- orber:dbg("[~p] orber_iiop:collect_fragments(~p);",
- [?LINE, E], ?DEBUG_LEVEL),
- erlang:demonitor(MRef, [flush]),
- corba:raise(E);
- {'DOWN', MRef, _, Proxy, Reason} when is_pid(Proxy) ->
- orber:dbg("[~p] orber_iiop:collect_fragments(~p);~n"
- "Monitor generated a DOWN message.",
- [?LINE, Reason], ?DEBUG_LEVEL),
- receive
- %% Clear EXIT message from queue
- {'EXIT', _Proxy, _What} ->
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_MAYBE})
- after 0 ->
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_MAYBE})
- end
- end.
-
-clear_queue(Proxy, RequestId, MRef) ->
- receive
- {fragment, _, RequestId, MRef} ->
- clear_queue(Proxy, RequestId, MRef);
- {MRef, RequestId, cancelled} ->
- %% This is the last message that the proxy will send
- %% after we've cancelled the request.
- erlang:demonitor(MRef, [flush]),
- ok;
- {'DOWN', MRef, _, Proxy, _Reason} ->
- %% The proxy terminated. Clear EXIT message from queue
- receive
- {'EXIT', Proxy, _What} ->
- ok
- after 0 ->
- ok
- end
- end.
-
diff --git a/lib/orber/src/orber_iiop_outsup.erl b/lib/orber/src/orber_iiop_outsup.erl
deleted file mode 100644
index f3627e01a0..0000000000
--- a/lib/orber/src/orber_iiop_outsup.erl
+++ /dev/null
@@ -1,88 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_iiop_outsup.erl
-%%
-%% Description:
-%% This file contains the outgoing IIOP communication supervisor which
-%% holds all active "proxies"
-%%
-%%-----------------------------------------------------------------
--module(orber_iiop_outsup).
-
--behaviour(supervisor).
-
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([start/2, connect/7]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([init/1, terminate/2]).
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: start/2
-%%-----------------------------------------------------------------
-start(sup, Opts) ->
- supervisor:start_link({local, orber_iiop_outsup}, orber_iiop_outsup,
- {sup, Opts});
-start(_A1, _A2) ->
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Server functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: init/1
-%%-----------------------------------------------------------------
-init({sup, _Opts}) ->
- SupFlags = {simple_one_for_one, 500, 100},
- ChildSpec = [
- {name2, {orber_iiop_outproxy, start, []}, temporary,
- 10000, worker, [orber_iiop_outproxy]}
- ],
- {ok, {SupFlags, ChildSpec}};
-init(_Opts) ->
- {ok, []}.
-
-
-%%-----------------------------------------------------------------
-%% Func: terminate/1
-%%-----------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-%%-----------------------------------------------------------------
-%% Func: connect/6
-%%-----------------------------------------------------------------
-connect(Host, Port, SocketType, SocketOptions, Parent, Key, NewKey) ->
- supervisor:start_child(orber_iiop_outsup,
- [{connect, Host, Port, SocketType,
- SocketOptions, Parent, Key, NewKey}]).
-
diff --git a/lib/orber/src/orber_iiop_pm.erl b/lib/orber/src/orber_iiop_pm.erl
deleted file mode 100644
index 72084227aa..0000000000
--- a/lib/orber/src/orber_iiop_pm.erl
+++ /dev/null
@@ -1,894 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_iiop_pm.erl
-%% Description:
-%% This file contains the mapping of addresses on the format {Host, Port}
-%% to a proxy pid.
-%%
-%%-----------------------------------------------------------------
--module(orber_iiop_pm).
-
--behaviour(gen_server).
-
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("kernel/include/inet.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([start/0, start/1]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([connect/7,
- close_connection/1, close_connection/2,
- list_existing_connections/0,
- list_setup_connections/0,
- list_all_connections/0,
- init/1, handle_call/3, handle_cast/2, handle_info/2,
- code_change/3, terminate/2, stop/0, setup_connection/8,
- reconfigure/1, reconfigure/3, reconfigure/4, add_connection/3,
- sockname2peername/2, peername2sockname/2]).
-
-%%-----------------------------------------------------------------
-%% Macros/Defines
-%%-----------------------------------------------------------------
--define(DEBUG_LEVEL, 7).
-
--define(PM_CONNECTION_DB, orber_iiop_pm_db).
-
--record(state, {connections, queue}).
-
--record(connection, {hp, child, interceptors, slave,
- flags = 0, alias = 0, socketdata = {"Unavailable", 0}}).
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-start() ->
- ignore.
-start(Opts) ->
- gen_server:start_link({local, 'orber_iiop_pm'}, ?MODULE, Opts, []).
-
-
-connect(Host, Port, SocketType, Timeout, Chars, Wchars, Ctx)
- when SocketType == normal ->
- Key = create_key(Host, Port, Ctx),
- case ets:lookup(?PM_CONNECTION_DB, Key) of
- [#connection{child = connecting}] ->
- gen_server:call(orber_iiop_pm, {connect, Host, Port, SocketType,
- [], Chars, Wchars, Key}, Timeout);
- [] ->
- gen_server:call(orber_iiop_pm, {connect, Host, Port, SocketType,
- [], Chars, Wchars, Key}, Timeout);
- [#connection{hp = {_, _, 0}, child = P, interceptors = I}] ->
- {ok, P, [], I, 0};
- [#connection{hp = {_, _, Interface}, child = P, interceptors = I}] ->
- {ok, P, [], I, [Interface]}
- end;
-connect(Host, Port, SocketType, Timeout, Chars, Wchars, Ctx)
- when SocketType == ssl ->
- Key = create_key(Host, Port, Ctx),
- case ets:lookup(?PM_CONNECTION_DB, Key) of
- [#connection{child = connecting}] ->
- SocketOptions = get_ssl_socket_options(Ctx),
- gen_server:call(orber_iiop_pm, {connect, Host, Port, SocketType,
- SocketOptions, Chars, Wchars, Key},
- Timeout);
- [] ->
- SocketOptions = get_ssl_socket_options(Ctx),
- gen_server:call(orber_iiop_pm, {connect, Host, Port, SocketType,
- SocketOptions, Chars, Wchars, Key},
- Timeout);
- [#connection{hp = {_, _, 0}, child = P, interceptors = I}] ->
- {ok, P, [], I, 0};
- [#connection{hp = {_, _, Interface}, child = P, interceptors = I}] ->
- {ok, P, [], I, [Interface]}
- end.
-
-get_ssl_socket_options([]) ->
- SSLOpts =
- case orber_env:ssl_client_options() of
- [] ->
- [{verify, orber_env:ssl_client_verify()},
- {depth, orber_env:ssl_client_depth()},
- {certfile, orber_env:ssl_client_certfile()},
- {cacertfile, orber_env:ssl_client_cacertfile()},
- {password, orber_env:ssl_client_password()},
- {keyfile, orber_env:ssl_client_keyfile()},
- {ciphers, orber_env:ssl_client_ciphers()},
- {cachetimeout, orber_env:ssl_client_cachetimeout()},
- {keepalive, orber_env:iiop_ssl_out_keepalive()}];
- Opts ->
- case orber_tb:check_illegal_tcp_options(Opts) of
- ok ->
- check_old_ssl_client_options([]),
- Opts;
- {error, IllegalOpts} ->
- error_logger:error_report([{application, orber},
- "TCP options not allowed to set on a connection",
- IllegalOpts]),
- error("Illegal TCP option")
- end
- end,
- ssl_client_extra_options(SSLOpts, []);
-get_ssl_socket_options([#'IOP_ServiceContext'
- {context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {configuration, Options}}|_]) ->
- SSLOpts =
- case orber_tb:keysearch(ssl_client_options, Options,
- orber_env:ssl_client_options()) of
- [] ->
- Verify = orber_tb:keysearch(ssl_client_verify, Options,
- orber_env:ssl_client_verify()),
- Depth = orber_tb:keysearch(ssl_client_depth, Options,
- orber_env:ssl_client_depth()),
- Cert = orber_tb:keysearch(ssl_client_certfile, Options,
- orber_env:ssl_client_certfile()),
- CaCert = orber_tb:keysearch(ssl_client_cacertfile, Options,
- orber_env:ssl_client_cacertfile()),
- Pwd = orber_tb:keysearch(ssl_client_password, Options,
- orber_env:ssl_client_password()),
- Key = orber_tb:keysearch(ssl_client_keyfile, Options,
- orber_env:ssl_client_keyfile()),
- Ciphers = orber_tb:keysearch(ssl_client_ciphers, Options,
- orber_env:ssl_client_ciphers()),
- Timeout = orber_tb:keysearch(ssl_client_cachetimeout, Options,
- orber_env:ssl_client_cachetimeout()),
- KeepAlive = orber_tb:keysearch(ssl_server_cachetimeout, Options,
- orber_env:iiop_ssl_out_keepalive()),
- [{verify, Verify},
- {depth, Depth},
- {certfile, Cert},
- {cacertfile, CaCert},
- {password, Pwd},
- {keyfile, Key},
- {ciphers, Ciphers},
- {cachetimeout, Timeout},
- {keepalive, KeepAlive}];
- Opts ->
- case orber_tb:check_illegal_tcp_options(Opts) of
- ok ->
- check_old_ssl_client_options(Options),
- Opts;
- {error, IllegalOpts} ->
- error_logger:error_report([{application, orber},
- "TCP options not allowed to set on a connection",
- IllegalOpts]),
- error("Illegal TCP option")
- end
- end,
- ssl_client_extra_options(SSLOpts, []);
-get_ssl_socket_options([_|T]) ->
- get_ssl_socket_options(T).
-
-
-ssl_client_extra_options([], Acc) ->
- Acc;
-ssl_client_extra_options([{_Type, []}|T], Acc) ->
- ssl_client_extra_options(T, Acc);
-ssl_client_extra_options([{_Type, infinity}|T], Acc) ->
- ssl_client_extra_options(T, Acc);
-ssl_client_extra_options([{Type, Value}|T], Acc) ->
- ssl_client_extra_options(T, [{Type, Value}|Acc]).
-
-add_connection(Key, Key, SockData) ->
- case ets:lookup(?PM_CONNECTION_DB, Key) of
- [Connection] ->
- ets:insert(?PM_CONNECTION_DB,
- Connection#connection{socketdata = SockData});
- [] ->
- ets:insert(?PM_CONNECTION_DB,
- #connection{hp= Key, child = connecting,
- socketdata = SockData})
- end;
-add_connection(Key, NewKey, SockData) ->
- add_connection(Key, Key, SockData),
- add_connection(NewKey, NewKey, SockData).
-
-get_socket_data(Key) ->
- case ets:lookup(?PM_CONNECTION_DB, Key) of
- [#connection{socketdata = SockData}] ->
- SockData;
- _ ->
- {"Unable to extract socket information", 0}
- end.
-
-sockname2peername(SockHost, SockPort) ->
- orber_tb:unique(
- do_select([{#connection{hp = {'$1', '$2', '_'},
- socketdata = {match_type(SockHost),
- match_type(SockPort)},
- _='_'}, [], [{{'$1', '$2'}}]}])).
-
-
-peername2sockname(PeerHost, PeerPort) ->
- orber_tb:unique(
- do_select([{#connection{hp = {match_type(PeerHost),
- match_type(PeerPort),
- '_'},
- socketdata = '$1',
- _='_'}, [], ['$1']}])).
-
-match_type(0) ->
- %% Wildcard port number
- '_';
-match_type("") ->
- %% Wildcard host
- '_';
-match_type(Key) ->
- %% Wildcard not used.
- Key.
-
-create_key(Host, Port, []) ->
- {Host, Port, 0};
-create_key(Host, Port,
- [#'IOP_ServiceContext'
- {context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface, Interface}}|_]) when is_list(Interface) ->
- {Host, Port, Interface};
-create_key(Host, Port,
- [#'IOP_ServiceContext'
- {context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface, Interface}}|_]) ->
- orber:dbg("[~p] orber_iiop_pm:create_key(~p, ~p);~n"
- "The supplied interface must be a string.",
- [?LINE, Host, Port, Interface], ?DEBUG_LEVEL),
- corba:raise(#'BAD_CONTEXT'{completion_status=?COMPLETED_NO});
-create_key(Host, Port, [_|T]) ->
- create_key(Host, Port, T).
-
-reconfigure(Options) ->
- {Local, Proxy} = check_options(Options, [], []),
- reconfigure_local(Local),
- reconfigure_proxy(Proxy).
-
-
-reconfigure(Options, Host, Port) ->
- reconfigure(Options, Host, Port, 0).
-reconfigure(Options, Host, Port, Interface) ->
- case ets:lookup(?PM_CONNECTION_DB, {Host, Port, Interface}) of
- [#connection{child = P}] when is_pid(P) ->
- case check_options(Options, [], []) of
- {[], Proxy} ->
- reconfigure_proxy(Proxy, [P]);
- {Local, Proxy} ->
- reconfigure_proxy(Proxy, [P]),
- gen_server:call(orber_iiop_pm, {reconfigure, Local,
- Host, Port, Interface}, infinity)
- end;
- _ ->
- {error, "No proxy matched the supplied reference"}
- end.
-
-reconfigure_local([]) ->
- ok;
-reconfigure_local(Options) ->
- gen_server:call(orber_iiop_pm, {reconfigure, Options}, infinity).
-
-reconfigure_proxy([]) ->
- ok;
-reconfigure_proxy(Options) ->
- reconfigure_proxy(Options, do_select([{#connection{child = '$1', _='_'},
- [], ['$1']}])).
-
-reconfigure_proxy(Options, [Pid|T]) ->
- Pid ! {reconfigure, Options},
- reconfigure_proxy(Options, T);
-reconfigure_proxy(_Options, []) ->
- ok.
-
-
-check_options([{interceptors, false}|Options], Local, Proxy) ->
- check_options(Options, [{interceptors, false}|Local], Proxy);
-check_options([{interceptors, {native, LPIs}}|Options], Local, Proxy) ->
- check_options(Options, [{interceptors, {native, LPIs}}|Local], Proxy);
-check_options([{fake, option}|Options], Local, Proxy) ->
- check_options(Options, Local, [{fake, option}|Proxy]);
-check_options([_|Options], Local, Proxy) ->
- check_options(Options, Local, Proxy);
-check_options([], Local, Proxy) ->
- {Local, Proxy}.
-
-
-close_connection(PeerData) ->
- close_connection(PeerData, 0).
-
-close_connection(PeerData, Interface) ->
- gen_server:call(orber_iiop_pm, {disconnect, PeerData, Interface}, infinity).
-
-
-list_existing_connections() ->
- transform(
- lists:sort(
- do_select([{#connection{hp = {'$2','$3','$4'}, child = '$1', _='_'},
- [{is_pid, '$1'}], [{{'$1', '$2','$3','$4'}}]}])), []).
-
-list_setup_connections() ->
- transform(
- lists:sort(
- do_select([{#connection{hp = {'$1','$2','$3'}, child = connecting, _='_'}, [],
- [{{'$1','$2','$3'}}]}])), []).
-
-list_all_connections() ->
- transform(
- lists:sort(
- do_select([{#connection{hp = {'$2','$3','$4'}, child = '$1', _='_'}, [],
- [{{'$1','$2','$3', '$4'}}]}])), []).
-
-%% Since the connections interface can be 0 or an ip-address we want to
-%% transform those containing 0.
-transform([{C, H, P, 0}, {C, H, P, I}|T], Acc) ->
- %% ACL defined interface. Drop the anonymous one.
- transform(T, [{H, P, I}|Acc]);
-transform([{_C, H, P, 0}|T], Acc) ->
- %% No interface supplied. Drop the 0.
- transform(T, [{H, P}|Acc]);
-transform([{_C, H, P, I}|T], Acc) ->
- %% Interface supplied. Keep it.
- transform(T, [{H, P, I}|Acc]);
-transform([{H,P,0}|T], Acc) ->
- transform(T, [{H,P}|Acc]);
-transform([{H,P,I}|T], Acc) ->
- transform(T, [{H,P,I}|Acc]);
-transform([H|T], Acc) ->
- transform(T, [H|Acc]);
-transform([], Acc) ->
- Acc.
-
-do_select(Pattern) ->
- case catch ets:select(?PM_CONNECTION_DB, Pattern) of
- {'EXIT', _What} ->
- [];
- Result ->
- Result
- end.
-
-%%-----------------------------------------------------------------
-%% Internal interface functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: stop/0 (Only used for test purpose !!!!!!)
-%%-----------------------------------------------------------------
-stop() ->
- gen_server:call(orber_iiop_pm, stop).
-
-%%-----------------------------------------------------------------
-%% Server functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: init/1
-%%-----------------------------------------------------------------
-init(_Opts) ->
- process_flag(trap_exit, true),
- {ok, #state{connections = ets:new(orber_iiop_pm_db,
- [{keypos, 2}, set, public, named_table]),
- queue = ets:new(orber_iiop_pm_queue, [bag])}}.
-
-%%-----------------------------------------------------------------
-%% Func: terminate/2
-%%-----------------------------------------------------------------
-terminate(_Reason, #state{queue = Q}) ->
- %% Kill all proxies and close table before terminating
- stop_all_proxies(ets:first(?PM_CONNECTION_DB)),
- ets:delete(?PM_CONNECTION_DB),
- ets:delete(Q),
- ok.
-
-stop_all_proxies('$end_of_table') ->
- ok;
-stop_all_proxies(Key) ->
- case ets:lookup(?PM_CONNECTION_DB, Key) of
- [] ->
- ok;
- [#connection{child = connecting, interceptors = I}] ->
- invoke_connection_closed(I);
- [#connection{child = P, interceptors = I}] ->
- invoke_connection_closed(I),
- catch orber_iiop_outproxy:stop(P)
- end,
- stop_all_proxies(ets:next(?PM_CONNECTION_DB, Key)).
-
-%%-----------------------------------------------------------------
-%% Func: handle_call/3
-%%-----------------------------------------------------------------
-handle_call({connect, Host, Port, SocketType, SocketOptions, Chars, Wchars, Key},
- From, State) ->
- case ets:lookup(?PM_CONNECTION_DB, Key) of
- [#connection{child = connecting}] ->
- %% Another client already requested a connection to the given host/port.
- %% Just add this client to the queue.
- ets:insert(State#state.queue, {Key, From}),
- {noreply, State};
- [#connection{hp = {_,_,0}, child = P, interceptors = I}] ->
- %% This case will occur if the PortMapper completed a connection
- %% between the client's ets:lookup and receiving this request.
- {reply, {ok, P, [], I, 0}, State};
- [#connection{hp = {_,_,Intf}, child = P, interceptors = I}] ->
- %% This case will occur if the PortMapper completed a connection
- %% between the client's ets:lookup and receiving this request.
- {reply, {ok, P, [], I, [Intf]}, State};
- [] ->
- %% The first time a connection is requested to the given host/port.
- case catch spawn_link(?MODULE, setup_connection,
- [self(), Host, Port, SocketType,
- SocketOptions, Chars, Wchars, Key]) of
- Slave when is_pid(Slave) ->
- ets:insert(?PM_CONNECTION_DB,
- #connection{hp = Key, child = connecting,
- interceptors = false, slave = Slave}),
- ets:insert(State#state.queue, {Key, From}),
- {noreply, State};
- What ->
- orber:dbg("[~p] orber_iiop_pm:handle_call(connect);~n"
- "Unable to invoke setup_connection due to: ~n~p~n",
- [?LINE, What], ?DEBUG_LEVEL),
- {reply,
- {'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}},
- State}
- end
- end;
-handle_call({disconnect, PeerData, Interface}, _From, State) ->
- {reply, do_disconnect(PeerData, Interface, State), State};
-handle_call({reconfigure, Options, Host, Port, Interface},
- _From, State) ->
- case ets:lookup(?PM_CONNECTION_DB, {Host, Port, Interface}) of
- [] ->
- {reply, {error, "No proxy matched the supplied reference"}, State};
- [Connection] ->
- NewConnection = update_connection(Connection, Options),
- ets:insert(?PM_CONNECTION_DB, NewConnection),
- {reply, ok, State}
- end;
-handle_call({reconfigure, Options}, _From, State) ->
- case catch update_db(ets:first(?PM_CONNECTION_DB), Options) of
- ok ->
- {reply, ok, State};
- _What ->
- {reply, {error, "Unable to change configuration"}, State}
- end;
-handle_call(stop, _From, State) ->
- {stop, normal, ok, State};
-handle_call(_, _, State) ->
- {noreply, State}.
-
-update_db('$end_of_table', _) ->
- ok;
-update_db(Key, Options) ->
- [Connection] = ets:lookup(?PM_CONNECTION_DB, Key),
- NewConnection = update_connection(Connection, Options),
- ets:insert(?PM_CONNECTION_DB, NewConnection),
- update_db(ets:next(?PM_CONNECTION_DB, Key), Options).
-
-
-update_connection(Connection, [{interceptors, false}|Options]) ->
- update_connection(Connection#connection{interceptors = false}, Options);
-update_connection(#connection{interceptors = false,
- hp = {PH, PP, _},
- socketdata = {SH, SP}} = Connection,
- [{interceptors, {native, LPIs}}|Options]) ->
- %% No Interceptor(s). Add the same Ref used by the built in interceptors.
- update_connection(Connection#connection{interceptors =
- {native, {PH, PP, SH, SP}, LPIs}},
- Options);
-update_connection(#connection{interceptors = {native, Ref, _}} = Connection,
- [{interceptors, {native, LPIs}}|Options]) ->
- %% Interceptor(s) already in use. We must use the same Ref as before.
- update_connection(Connection#connection{interceptors =
- {native, Ref, LPIs}},
- Options);
-update_connection(Connection, [H|T]) ->
- orber:dbg("[~p] orber_iiop_pm:update_connection(~p, ~p)~n"
- "Unable to update the connection.~n",
- [?LINE, Connection, H], ?DEBUG_LEVEL),
- update_connection(Connection, T);
-update_connection(Connection, []) ->
- Connection.
-
-do_disconnect([], _Interface, _State) ->
- ok;
-do_disconnect([{Host, Port}|T], Interface, State) ->
- case ets:lookup(?PM_CONNECTION_DB, {Host, Port, Interface}) of
- [] ->
- ok;
- [#connection{child = connecting, interceptors = I}] ->
- ets:delete(?PM_CONNECTION_DB, {Host, Port, Interface}),
- Exc = {'EXCEPTION',#'INTERNAL'{completion_status = ?COMPLETED_NO}},
- send_reply_to_queue(ets:lookup(State#state.queue,
- {Host, Port, Interface}), Exc),
- ets:delete(State#state.queue, {Host, Port, Interface}),
- invoke_connection_closed(I);
- [#connection{child = P, interceptors = I}] ->
- unlink(P),
- catch orber_iiop_outproxy:stop(P),
- ets:delete(?PM_CONNECTION_DB, {Host, Port, Interface}),
- invoke_connection_closed(I)
- end,
- do_disconnect(T, Interface, State).
-
-%%-----------------------------------------------------------------
-%% Func: handle_cast/2
-%%-----------------------------------------------------------------
-handle_cast(stop, State) ->
- {stop, normal, State};
-handle_cast(_, State) ->
- {noreply, State}.
-
-%%-----------------------------------------------------------------
-%% Func: handle_info/2
-%%-----------------------------------------------------------------
-%% Trapping exits
-handle_info({'EXIT', Pid, Reason}, State) ->
- %% Check the most common scenario first, i.e., a proxy terminates.
- case ets:match_object(?PM_CONNECTION_DB, #connection{child = Pid, _='_'}) of
- [#connection{hp = K, interceptors = I}] ->
- ets:delete(?PM_CONNECTION_DB, K),
- invoke_connection_closed(I),
- {noreply, State};
- [#connection{hp = K, interceptors = I}, #connection{hp = K2}] ->
- ets:delete(?PM_CONNECTION_DB, K),
- ets:delete(?PM_CONNECTION_DB, K2),
- invoke_connection_closed(I),
- {noreply, State};
- [] when Reason == normal ->
- %% This might have been a spawned 'setup_connection' which terminated
- %% after sucessfully setting up a new connection.
- {noreply, State};
- [] ->
- %% Wasn't a proxy. Hence, we must test if it was a spawned
- %% 'setup_connection' that failed.
- case ets:match_object(?PM_CONNECTION_DB, #connection{slave = Pid, _='_'}) of
- [#connection{hp = K, child = connecting, interceptors = I}] ->
- ets:delete(?PM_CONNECTION_DB, K),
- invoke_connection_closed(I),
- Exc = {'EXCEPTION',#'INTERNAL'{completion_status = ?COMPLETED_NO}},
- send_reply_to_queue(ets:lookup(State#state.queue, K), Exc),
- ets:delete(State#state.queue, K),
- orber:dbg("[~p] orber_iiop_pm:handle_info(setup_failed ~p);~n"
- "It was not possible to create a connection to the"
- " given host/port.",
- [?LINE, K], ?DEBUG_LEVEL),
- {noreply, State};
- [#connection{hp = K, child = connecting, interceptors = I},
- #connection{hp = K2}] ->
- ets:delete(?PM_CONNECTION_DB, K),
- ets:delete(?PM_CONNECTION_DB, K2),
- invoke_connection_closed(I),
- Exc = {'EXCEPTION',#'INTERNAL'{completion_status = ?COMPLETED_NO}},
- send_reply_to_queue(ets:lookup(State#state.queue, K), Exc),
- ets:delete(State#state.queue, K),
- orber:dbg("[~p] orber_iiop_pm:handle_info(setup_failed ~p);~n"
- "It was not possible to create a connection to the"
- " given host/port.",
- [?LINE, K], ?DEBUG_LEVEL),
- {noreply, State};
- _ ->
- {noreply, State}
- end
- end;
-handle_info({setup_failed, {Host, Port, _} = Key, Key, Exc}, State) ->
- %% Deletet the data from the connection DB first to avoid clients from
- %% trying to access it again.
- ets:delete(?PM_CONNECTION_DB, Key),
- %% Now we can send whatever exception received.
- send_reply_to_queue(ets:lookup(State#state.queue, Key), Exc),
- ets:delete(State#state.queue, Key),
- orber:dbg("[~p] orber_iiop_pm:handle_info(setup_failed ~p ~p);~n"
- "It was not possible to create a connection to the given host/port.",
- [?LINE, Host, Port], ?DEBUG_LEVEL),
- {noreply, State};
-handle_info({setup_failed, {Host, Port, _} = Key, NewKey, Exc}, State) ->
- %% Deletet the data from the connection DB first to avoid clients from
- %% trying to access it again.
- ets:delete(?PM_CONNECTION_DB, Key),
- ets:delete(?PM_CONNECTION_DB, NewKey),
- %% Now we can send whatever exception received.
- send_reply_to_queue(ets:lookup(State#state.queue, Key), Exc),
- ets:delete(State#state.queue, Key),
- orber:dbg("[~p] orber_iiop_pm:handle_info(setup_failed ~p ~p);~n"
- "It was not possible to create a connection to the given host/port.",
- [?LINE, Host, Port], ?DEBUG_LEVEL),
- {noreply, State};
-handle_info({setup_successfull, Key, Key, {Child, Ctx, Int}}, State) ->
- %% Create a link to the proxy and store it in the connection DB.
- link(Child),
- case ets:lookup(?PM_CONNECTION_DB, Key) of
- [Connection] ->
- ets:insert(?PM_CONNECTION_DB,
- Connection#connection{hp = Key, child = Child,
- interceptors = Int,
- slave = undefined});
- [] ->
- ets:insert(?PM_CONNECTION_DB,
- #connection{hp = Key, child = Child,
- interceptors = Int,
- slave = undefined})
- end,
- %% Send the Proxy reference to all waiting clients.
- case Key of
- {_, _, 0} ->
- send_reply_to_queue(ets:lookup(State#state.queue, Key),
- {ok, Child, Ctx, Int, 0});
- {_, _, Interface} ->
- send_reply_to_queue(ets:lookup(State#state.queue, Key),
- {ok, Child, Ctx, Int, [Interface]})
- end,
- %% Reset the queue.
- ets:delete(State#state.queue, Key),
- {noreply, State};
-handle_info({setup_successfull, Key, NewKey, {Child, Ctx, Int}}, State) ->
- %% Create a link to the proxy and store it in the connection DB.
- link(Child),
- case ets:lookup(?PM_CONNECTION_DB, NewKey) of
- [Connection] ->
- ets:insert(?PM_CONNECTION_DB,
- Connection#connection{hp = NewKey, child = Child,
- interceptors = Int,
- slave = undefined});
- [] ->
- ets:insert(?PM_CONNECTION_DB,
- #connection{hp = NewKey, child = Child,
- interceptors = Int,
- slave = undefined})
- end,
- case ets:lookup(?PM_CONNECTION_DB, Key) of
- [Connection2] ->
- ets:insert(?PM_CONNECTION_DB,
- Connection2#connection{hp = Key, child = Child,
- interceptors = Int,
- slave = undefined});
- [] ->
- ets:insert(?PM_CONNECTION_DB,
- #connection{hp = Key, child = Child,
- interceptors = Int,
- slave = undefined})
- end,
- %% Send the Proxy reference to all waiting clients.
- case NewKey of
- {_, _, 0} ->
- send_reply_to_queue(ets:lookup(State#state.queue, Key),
- {ok, Child, Ctx, Int, 0});
- {_, _, Interface} ->
- send_reply_to_queue(ets:lookup(State#state.queue, Key),
- {ok, Child, Ctx, Int, [Interface]})
- end,
- %% Reset the queue.
- ets:delete(State#state.queue, Key),
- {noreply, State};
-handle_info(_, State) ->
- {noreply, State}.
-
-
-send_reply_to_queue([], _) ->
- ok;
-send_reply_to_queue([{_, Client}|T], Reply) ->
- gen_server:reply(Client, Reply),
- send_reply_to_queue(T, Reply).
-
-%%-----------------------------------------------------------------
-%% Func: code_change/3
-%%-----------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-setup_connection(PMPid, Host, Port, SocketType, SocketOptions, Chars, Wchars, Key) ->
- case catch access_allowed(Host, Port, SocketType, Key) of
- ok ->
- do_setup_connection(PMPid, Host, Port, SocketType, SocketOptions,
- Chars, Wchars, Key, Key);
- {ok, Interface} ->
- do_setup_connection(PMPid, Host, Port, SocketType,
- [{ip, Interface}|SocketOptions],
- Chars, Wchars, Key, Key);
- {ok, Interface, NewKey} ->
- do_setup_connection(PMPid, Host, Port, SocketType,
- [{ip, Interface}|SocketOptions],
- Chars, Wchars, Key, NewKey);
- false ->
- orber_tb:info("Blocked connect attempt to ~s - ~p", [Host, Port]),
- PMPid ! {setup_failed, Key, Key,
- {'EXCEPTION', #'NO_PERMISSION'{completion_status=?COMPLETED_NO}}},
- ok;
- Reason ->
- orber:dbg("[~p] orber_iiop_pm:handle_call(connect ~p ~p); failed~n"
- "Reason: ~p",
- [?LINE, Host, Port, Reason], ?DEBUG_LEVEL),
- PMPid ! {setup_failed, Key, Key,
- {'EXCEPTION', #'COMM_FAILURE'{completion_status=?COMPLETED_NO}}},
- ok
- end.
-
-
-do_setup_connection(PMPid, Host, Port, SocketType, SocketOptions, Chars,
- Wchars, Key, NewKey) ->
- case catch orber_iiop_outsup:connect(Host, Port, SocketType,
- SocketOptions, PMPid, Key, NewKey) of
- {error, {'EXCEPTION', E}} ->
- orber:dbg("[~p] orber_iiop_pm:handle_call(connect ~p ~p);~n"
- "Raised Exc: ~p",
- [?LINE, Host, Port, E], ?DEBUG_LEVEL),
- PMPid ! {setup_failed, Key, NewKey, {'EXCEPTION', E}},
- ok;
- {error, Reason} ->
- orber:dbg("[~p] orber_iiop_pm:handle_call(connect ~p ~p);~n"
- "Got EXIT: ~p",
- [?LINE, Host, Port, Reason], ?DEBUG_LEVEL),
- PMPid ! {setup_failed, Key, NewKey,
- {'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}}},
- ok;
- {ok, undefined} ->
- orber:dbg("[~p] orber_iiop_pm:handle_call(connect ~p ~p);~n"
- "Probably no listener on the given Node/Port or timedout.",
- [?LINE, Host, Port], ?DEBUG_LEVEL),
- PMPid ! {setup_failed, Key, NewKey,
- {'EXCEPTION', #'COMM_FAILURE'{minor=(?ORBER_VMCID bor 1),
- completion_status=?COMPLETED_NO}}},
- ok;
- {ok, Child} ->
- case init_interceptors(Host, Port, get_socket_data(Key)) of
- {'EXCEPTION', E} ->
- PMPid ! {setup_failed, Key, NewKey, {'EXCEPTION', E}},
- ok;
- Interceptors ->
- BiDirCtx = orber:bidir_context(),
- Ctx = case orber:exclude_codeset_ctx() of
- true ->
- BiDirCtx;
- _ ->
- CodeSetCtx =
- #'CONV_FRAME_CodeSetContext'
- {char_data = Chars,
- wchar_data = Wchars},
- [#'IOP_ServiceContext'
- {context_id=?IOP_CodeSets,
- context_data = CodeSetCtx} | BiDirCtx]
- end,
- PMPid ! {setup_successfull, Key, NewKey,
- {Child, Ctx, Interceptors}},
- ok
- end
- end.
-
-access_allowed(Host, Port, Type, {_,_,UserInterface}) ->
- Flags = orber:get_flags(),
- case ?ORB_FLAG_TEST(Flags, ?ORB_ENV_USE_ACL_OUTGOING) of
- false when UserInterface == 0 ->
- get_local_interface(Type);
- false ->
- inet:getaddr(UserInterface, get_ip_family(UserInterface));
- true ->
- SearchFor =
- case Type of
- normal ->
- tcp_out;
- ssl ->
- ssl_out
- end,
- {ok, Ip} = inet:getaddr(Host, get_ip_family(Host)),
- case orber_acl:match(Ip, SearchFor, true) of
- {true, [], 0} ->
- get_local_interface(Type);
- {true, [], Port} ->
- get_local_interface(Type);
- {true, [], {Min, Max}} when Port >= Min, Port =< Max ->
- get_local_interface(Type);
- {true, [Interface], 0} ->
- {ok, NewIp} = inet:getaddr(Interface, get_ip_family(Interface)),
- {ok, NewIp, {Host, Port, 0}};
- {true, [Interface], Port} ->
-
- {ok, NewIp} = inet:getaddr(Interface, get_ip_family(Interface)),
- {ok, NewIp, {Host, Port, 0}};
- {true, [Interface], {Min, Max}} when Port >= Min, Port =< Max ->
-
- {ok, NewIp} = inet:getaddr(Interface, get_ip_family(Interface)),
- {ok, NewIp, {Host, Port, 0}};
- _ ->
- false
- end
- end.
-
-get_local_interface(normal) ->
- case orber_env:ip_address_local() of
- [] ->
- ok;
- [Interface] ->
- inet:getaddr(Interface, get_ip_family(Interface))
- end;
-get_local_interface(ssl) ->
- case orber_env:iiop_ssl_ip_address_local() of
- [] ->
- ok;
- [Interface] ->
- inet:getaddr(Interface, get_ip_family(Interface))
- end.
-
-get_ip_family(Addr) ->
- [Family] = orber_socket:get_ip_family_opts(Addr),
- Family.
-
-invoke_connection_closed(false) ->
- ok;
-invoke_connection_closed({native, Ref, PIs}) ->
- (catch orber_pi:closed_out_connection(PIs, Ref));
-invoke_connection_closed({_Type, _PIs}) ->
- ok.
-
-
-init_interceptors(Host, Port, {SHost, SPort}) ->
- case orber:get_interceptors() of
- {native, PIs} ->
- case catch orber_pi:new_out_connection(PIs, Host, Port, SHost, SPort) of
- {'EXIT', R} ->
- orber:dbg("[~p] orber_iiop_pm:init_interceptors(~p); Got Exit: ~p.~n"
- "One or more Interceptor incorrect or undefined?",
- [?LINE, PIs, R], ?DEBUG_LEVEL),
- {'EXCEPTION', #'COMM_FAILURE'{minor=(?ORBER_VMCID bor 2),
- completion_status=?COMPLETED_NO}};
- IntRef ->
- {native, IntRef, PIs}
- end;
- Other ->
- %% Either 'false' or {Type, PIs}.
- Other
- end.
-
-
-check_old_ssl_client_options(Options) ->
- try
- 0 = orber_tb:keysearch(ssl_client_verify, Options,
- orber_env:ssl_client_verify()),
- 1 = orber_tb:keysearch(ssl_client_depth, Options,
- orber_env:ssl_client_depth()),
- [] = orber_tb:keysearch(ssl_client_certfile, Options,
- orber_env:ssl_client_certfile()),
- [] = orber_tb:keysearch(ssl_client_cacertfile, Options,
- orber_env:ssl_client_cacertfile()),
- [] = orber_tb:keysearch(ssl_client_password, Options,
- orber_env:ssl_client_password()),
- [] = orber_tb:keysearch(ssl_client_keyfile, Options,
- orber_env:ssl_client_keyfile()),
- [] = orber_tb:keysearch(ssl_client_ciphers, Options,
- orber_env:ssl_client_ciphers()),
- infinity = orber_tb:keysearch(ssl_client_cachetimeout, Options,
- orber_env:ssl_client_cachetimeout()),
- false = orber_tb:keysearch(iiop_ssl_out_keepalive, Options,
- orber_env:iiop_ssl_out_keepalive())
-
- catch
- _:_ ->
- error_logger:warning_report([{application, orber},
- "Ignoring deprecated ssl client options used together with the ssl_client_options"])
- end.
-
-
-
-
-%%-----------------------------------------------------------------
-%% END OF MODULE
-%%-----------------------------------------------------------------
diff --git a/lib/orber/src/orber_iiop_socketsup.erl b/lib/orber/src/orber_iiop_socketsup.erl
deleted file mode 100644
index 43b5444c82..0000000000
--- a/lib/orber/src/orber_iiop_socketsup.erl
+++ /dev/null
@@ -1,86 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_iiop_socketsup.erl
-%% Description:
-%% This file contains the supervisor for the socket accept processes.
-%%
-%%-----------------------------------------------------------------
--module(orber_iiop_socketsup).
-
--behaviour(supervisor).
-
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([start/2, start_accept/3, start_accept/4]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([init/1, terminate/2]).
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: start/2
-%%-----------------------------------------------------------------
-start(sup, Opts) ->
- supervisor:start_link({local, orber_iiop_socketsup}, orber_iiop_socketsup,
- {sup, Opts});
-start(_A1, _A2) ->
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Server functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: init/1
-%%-----------------------------------------------------------------
-init({sup, _Opts}) ->
- SupFlags = {simple_one_for_one, 500, 100},
- ChildSpec = [
- {name3, {orber_iiop_net_accept, start, []}, temporary,
- 10000, worker, [orber_iiop_net_accept]}
- ],
- {ok, {SupFlags, ChildSpec}};
-init(_Opts) ->
- {ok, []}.
-
-
-%%-----------------------------------------------------------------
-%% Func: terminate/2
-%%-----------------------------------------------------------------
-terminate(_Reason, _State) ->
- ok.
-
-%%-----------------------------------------------------------------
-%% Func: start_connection/1
-%%-----------------------------------------------------------------
-start_accept(Type, Listen, Ref) ->
- start_accept(Type, Listen, Ref, []).
-start_accept(Type, Listen, Ref, ProxyOptions) ->
- supervisor:start_child(orber_iiop_socketsup, [Type, Listen, Ref, ProxyOptions]).
-
diff --git a/lib/orber/src/orber_iiop_tracer.erl b/lib/orber/src/orber_iiop_tracer.erl
deleted file mode 100644
index 8d6cd2e8b8..0000000000
--- a/lib/orber/src/orber_iiop_tracer.erl
+++ /dev/null
@@ -1,232 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%--------------------------------------------------------------------
-%% File : orber_iiop_tracer.erl
-%% Purpose : Use for debugging only.
-%%--------------------------------------------------------------------
-
--module(orber_iiop_tracer).
-
-
-
-
-
-%% Interceptor functions.
--export([new_out_connection/5,
- new_in_connection/5,
- closed_in_connection/1,
- closed_out_connection/1,
- in_request_encoded/6,
- in_reply_encoded/6,
- out_reply_encoded/6,
- out_request_encoded/6,
- in_request/6,
- in_reply/6,
- out_reply/6,
- out_request/6]).
-
-
-%%--------------- INTERCEPTOR FUNCTIONS ----------------------
-%%------------------------------------------------------------
-%% function : new_in_connection
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-new_in_connection(_Arg, PHost, PPort, SHost, SPort) ->
- error_logger:info_msg("=============== new_in_connection ========~n"
- "Node : ~p~n"
- "From : ~s:~p~n"
- "To : ~s:~p~n"
- "==========================================~n",
- [node(), PHost, PPort, SHost, SPort]),
- {PHost, PPort, SHost, SPort}.
-
-%%------------------------------------------------------------
-%% function : new_out_connection
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-new_out_connection(_Arg, PHost, PPort, SHost, SPort) ->
- error_logger:info_msg("=============== new_out_connection =======~n"
- "Node : ~p~n"
- "From : ~s:~p~n"
- "To : ~s:~p~n"
- "==========================================~n",
- [node(), SHost, SPort, PHost, PPort]),
- {PHost, PPort, SHost, SPort}.
-
-%%------------------------------------------------------------
-%% function : closed_in_connection
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-closed_in_connection(Arg) ->
- error_logger:info_msg("=============== closed_in_connection =====~n"
- "Node : ~p~n"
- "Connection: ~p~n"
- "==========================================~n",
- [node(), Arg]),
- Arg.
-
-%%------------------------------------------------------------
-%% function : closed_out_connection
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-closed_out_connection(Arg) ->
- error_logger:info_msg("=============== closed_out_connection ====~n"
- "Node : ~p~n"
- "Connection: ~p~n"
- "==========================================~n",
- [node(), Arg]),
- Arg.
-
-%%------------------------------------------------------------
-%% function : in_request_encoded
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-in_request_encoded(Ref, _ObjKey, Ctx, Op, Bin, Args) ->
- error_logger:info_msg("=============== in_request_encoded =======~n"
- "Connection: ~p~n"
- "Operation : ~p~n"
- "Body : ~p~n"
- "Context : ~p~n"
- "==========================================~n",
- [Ref, Op, Bin, Ctx]),
- {Bin, Args}.
-
-%%------------------------------------------------------------
-%% function : in_reply_encoded
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-in_reply_encoded(Ref, _ObjKey, Ctx, Op, Bin, Args) ->
- error_logger:info_msg("============== in_reply_encoded ==========~n"
- "Connection: ~p~n"
- "Operation : ~p~n"
- "Body : ~p~n"
- "Context : ~p~n"
- "==========================================~n",
- [Ref, Op, Bin, Ctx]),
- {Bin, Args}.
-
-%%------------------------------------------------------------
-%% function : out_reply_encoded
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-out_reply_encoded(Ref, ObjKey, Ctx, Op, Bin, Args) ->
- error_logger:info_msg("============== out_reply_encoded =========~n"
- "Connection: ~p~n"
- "Operation : ~p~n"
- "Body : ~p~n"
- "Context : ~p~n"
- "Object : ~p~n"
- "==========================================~n",
- [Ref, Op, Bin, Ctx, ObjKey]),
- {Bin, Args}.
-
-%%------------------------------------------------------------
-%% function : out_request_encoded
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-out_request_encoded(Ref, _ObjKey, Ctx, Op, Bin, Args) ->
- error_logger:info_msg("============== out_request_encoded =======~n"
- "Connection: ~p~n"
- "Operation : ~p~n"
- "Body : ~p~n"
- "Context : ~p~n"
- "==========================================~n",
- [Ref, Op, Bin, Ctx]),
- {Bin, Args}.
-
-%%------------------------------------------------------------
-%% function : in_request
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-in_request(Ref, ObjKey, Ctx, Op, Params, Args) ->
- error_logger:info_msg("=============== in_request ===============~n"
- "Connection: ~p~n"
- "Operation : ~p~n"
- "Parameters: ~p~n"
- "Context : ~p~n"
- "Object : ~p~n"
- "==========================================~n",
- [Ref, Op, Params, Ctx, ObjKey]),
- {Params, Args}.
-
-%%------------------------------------------------------------
-%% function : in_reply
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-in_reply(Ref, _ObjKey, Ctx, Op, Reply, Args) ->
- error_logger:info_msg("=============== in_reply =================~n"
- "Connection: ~p~n"
- "Operation : ~p~n"
- "Reply : ~p~n"
- "Context : ~p~n"
- "==========================================~n",
- [Ref, Op, Reply, Ctx]),
- {Reply, Args}.
-
-%%------------------------------------------------------------
-%% function : out_reply
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-out_reply(Ref, ObjKey, Ctx, Op, Reply, Args) ->
- error_logger:info_msg("=============== out_reply ================~n"
- "Connection: ~p~n"
- "Operation : ~p~n"
- "Reply : ~p~n"
- "Context : ~p~n"
- "Object : ~p~n"
- "==========================================~n",
- [Ref, Op, Reply, Ctx, ObjKey]),
- {Reply, Args}.
-
-%%------------------------------------------------------------
-%% function : out_request
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-out_request(Ref, _ObjKey, Ctx, Op, Params, Args) ->
- error_logger:info_msg("=============== out_request ==============~n"
- "Connection: ~p~n"
- "Operation : ~p~n"
- "Parameters: ~p~n"
- "Context : ~p~n"
- "==========================================~n",
- [Ref, Op, Params, Ctx]),
- {Params, Args}.
-
-
-
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
-
diff --git a/lib/orber/src/orber_iiop_tracer_silent.erl b/lib/orber/src/orber_iiop_tracer_silent.erl
deleted file mode 100644
index 659de0acee..0000000000
--- a/lib/orber/src/orber_iiop_tracer_silent.erl
+++ /dev/null
@@ -1,191 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%--------------------------------------------------------------------
-%% File : orber_iiop_tracer_silent.erl
-%% Purpose : Use for debugging only.
-%%--------------------------------------------------------------------
-
--module(orber_iiop_tracer_silent).
-
-
-%% Interceptor functions.
--export([new_out_connection/5,
- new_in_connection/5,
- closed_in_connection/1,
- closed_out_connection/1,
- in_request_encoded/6,
- in_reply_encoded/6,
- out_reply_encoded/6,
- out_request_encoded/6,
- in_request/6,
- in_reply/6,
- out_reply/6,
- out_request/6]).
-
-
-%%--------------- INTERCEPTOR FUNCTIONS ----------------------
-%%------------------------------------------------------------
-%% function : new_in_connection
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-new_in_connection(_Arg, PHost, PPort, SHost, SPort) ->
- error_logger:info_msg("=============== new_in_connection ========~n"
- "Node : ~p~n"
- "From : ~s:~p~n"
- "To : ~s:~p~n"
- "==========================================~n",
- [node(), PHost, PPort, SHost, SPort]),
- {PHost, PPort, SHost, SPort}.
-
-%%------------------------------------------------------------
-%% function : new_out_connection
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-new_out_connection(_Arg, PHost, PPort, SHost, SPort) ->
- error_logger:info_msg("=============== new_out_connection =======~n"
- "Node : ~p~n"
- "From : ~s:~p~n"
- "To : ~s:~p~n"
- "==========================================~n",
- [node(), SHost, SPort, PHost, PPort]),
- {PHost, PPort, SHost, SPort}.
-
-%%------------------------------------------------------------
-%% function : closed_in_connection
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-closed_in_connection(Arg) ->
- error_logger:info_msg("=============== closed_in_connection =====~n"
- "Node : ~p~n"
- "Connection: ~p~n"
- "==========================================~n",
- [node(), Arg]),
- Arg.
-
-%%------------------------------------------------------------
-%% function : closed_out_connection
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-closed_out_connection(Arg) ->
- error_logger:info_msg("=============== closed_out_connection ====~n"
- "Node : ~p~n"
- "Connection: ~p~n"
- "==========================================~n",
- [node(), Arg]),
- Arg.
-
-%%------------------------------------------------------------
-%% function : in_request_encoded
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-in_request_encoded(_Ref, _ObjKey, _Ctx, _Op, Bin, Args) ->
- {Bin, Args}.
-
-%%------------------------------------------------------------
-%% function : in_reply_encoded
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-in_reply_encoded(_Ref, _ObjKey, _Ctx, _Op, Bin, Args) ->
- {Bin, Args}.
-
-%%------------------------------------------------------------
-%% function : out_reply_encoded
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-out_reply_encoded(_Ref, _ObjKey, _Ctx, _Op, Bin, Args) ->
- {Bin, Args}.
-
-%%------------------------------------------------------------
-%% function : out_request_encoded
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-out_request_encoded(_Ref, _ObjKey, _Ctx, _Op, Bin, Args) ->
- {Bin, Args}.
-
-%%------------------------------------------------------------
-%% function : in_request
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-in_request(Ref, _ObjKey, _Ctx, Op, Params, Args) ->
- error_logger:info_msg("=============== in_request ===============~n"
- "Connection: ~p~n"
- "Operation : ~p~n"
- "Parameters: ~p~n"
- "==========================================~n",
- [Ref, Op, Params]),
- {Params, Args}.
-
-%%------------------------------------------------------------
-%% function : in_reply
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-in_reply(Ref, _ObjKey, _Ctx, Op, Reply, Args) ->
- error_logger:info_msg("=============== in_reply =================~n"
- "Connection: ~p~n"
- "Operation : ~p~n"
- "Reply : ~p~n"
- "==========================================~n",
- [Ref, Op, Reply]),
- {Reply, Args}.
-
-%%------------------------------------------------------------
-%% function : out_reply
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-out_reply(Ref, _ObjKey, _Ctx, Op, Reply, Args) ->
- error_logger:info_msg("=============== out_reply ================~n"
- "Connection: ~p~n"
- "Operation : ~p~n"
- "Reply : ~p~n"
- "==========================================~n",
- [Ref, Op, Reply]),
- {Reply, Args}.
-
-%%------------------------------------------------------------
-%% function : out_request
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-out_request(Ref, _ObjKey, _Ctx, Op, Params, Args) ->
- error_logger:info_msg("=============== out_request ==============~n"
- "Connection: ~p~n"
- "Operation : ~p~n"
- "Parameters: ~p~n"
- "==========================================~n",
- [Ref, Op, Params]),
- {Params, Args}.
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
-
diff --git a/lib/orber/src/orber_iiop_tracer_stealth.erl b/lib/orber/src/orber_iiop_tracer_stealth.erl
deleted file mode 100644
index 8eaa945d3f..0000000000
--- a/lib/orber/src/orber_iiop_tracer_stealth.erl
+++ /dev/null
@@ -1,187 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%--------------------------------------------------------------------
-%% File : orber_iiop_tracer_stealth.erl
-%% Purpose : Use for debugging only.
-%%--------------------------------------------------------------------
-
--module(orber_iiop_tracer_stealth).
-
-
-%% Interceptor functions.
--export([new_out_connection/5,
- new_in_connection/5,
- closed_in_connection/1,
- closed_out_connection/1,
- in_request_encoded/6,
- in_reply_encoded/6,
- out_reply_encoded/6,
- out_request_encoded/6,
- in_request/6,
- in_reply/6,
- out_reply/6,
- out_request/6]).
-
-
-%%--------------- INTERCEPTOR FUNCTIONS ----------------------
-%%------------------------------------------------------------
-%% function : new_in_connection
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-new_in_connection(_Arg, PHost, PPort, SHost, SPort) ->
- error_logger:info_msg("=============== new_in_connection ========~n"
- "Node : ~p~n"
- "From : ~s:~p~n"
- "To : ~s:~p~n"
- "==========================================~n",
- [node(), PHost, PPort, SHost, SPort]),
- {PHost, PPort, SHost, SPort}.
-
-%%------------------------------------------------------------
-%% function : new_out_connection
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-new_out_connection(_Arg, PHost, PPort, SHost, SPort) ->
- error_logger:info_msg("=============== new_out_connection =======~n"
- "Node : ~p~n"
- "From : ~s:~p~n"
- "To : ~s:~p~n"
- "==========================================~n",
- [node(), SHost, SPort, PHost, PPort]),
- {PHost, PPort, SHost, SPort}.
-
-%%------------------------------------------------------------
-%% function : closed_in_connection
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-closed_in_connection(Arg) ->
- error_logger:info_msg("=============== closed_in_connection =====~n"
- "Node : ~p~n"
- "Connection: ~p~n"
- "==========================================~n",
- [node(), Arg]),
- Arg.
-
-%%------------------------------------------------------------
-%% function : closed_out_connection
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-closed_out_connection(Arg) ->
- error_logger:info_msg("=============== closed_out_connection ====~n"
- "Node : ~p~n"
- "Connection: ~p~n"
- "==========================================~n",
- [node(), Arg]),
- Arg.
-
-%%------------------------------------------------------------
-%% function : in_request_encoded
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-in_request_encoded(_Ref, _ObjKey, _Ctx, _Op, Bin, Args) ->
- {Bin, Args}.
-
-%%------------------------------------------------------------
-%% function : in_reply_encoded
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-in_reply_encoded(_Ref, _ObjKey, _Ctx, _Op, Bin, Args) ->
- {Bin, Args}.
-
-%%------------------------------------------------------------
-%% function : out_reply_encoded
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-out_reply_encoded(_Ref, _ObjKey, _Ctx, _Op, Bin, Args) ->
- {Bin, Args}.
-
-%%------------------------------------------------------------
-%% function : out_request_encoded
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-out_request_encoded(_Ref, _ObjKey, _Ctx, _Op, Bin, Args) ->
- {Bin, Args}.
-
-%%------------------------------------------------------------
-%% function : in_request
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-in_request(Ref, _ObjKey, _Ctx, Op, Params, Args) ->
- error_logger:info_msg("=============== in_request ===============~n"
- "Connection: ~p~n"
- "Operation : ~p~n"
- "==========================================~n",
- [Ref, Op]),
- {Params, Args}.
-
-%%------------------------------------------------------------
-%% function : in_reply
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-in_reply(Ref, _ObjKey, _Ctx, Op, Reply, Args) ->
- error_logger:info_msg("=============== in_reply =================~n"
- "Connection: ~p~n"
- "Operation : ~p~n"
- "==========================================~n",
- [Ref, Op]),
- {Reply, Args}.
-
-%%------------------------------------------------------------
-%% function : out_reply
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-out_reply(Ref, _ObjKey, _Ctx, Op, Reply, Args) ->
- error_logger:info_msg("=============== out_reply ================~n"
- "Connection: ~p~n"
- "Operation : ~p~n"
- "==========================================~n",
- [Ref, Op]),
- {Reply, Args}.
-
-%%------------------------------------------------------------
-%% function : out_request
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-out_request(Ref, _ObjKey, _Ctx, Op, Params, Args) ->
- error_logger:info_msg("=============== out_request ==============~n"
- "Connection: ~p~n"
- "Operation : ~p~n"
- "==========================================~n",
- [Ref, Op]),
- {Params, Args}.
-
-%%======================================================================
-%% END OF MODULE
-%%======================================================================
-
diff --git a/lib/orber/src/orber_initial_references.erl b/lib/orber/src/orber_initial_references.erl
deleted file mode 100644
index 9140563881..0000000000
--- a/lib/orber/src/orber_initial_references.erl
+++ /dev/null
@@ -1,328 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_initial_references.erl
-%%
-%% Description:
-%% This file contains the CORBA::InitialReferences interface
-%%
-%%-----------------------------------------------------------------
--module(orber_initial_references).
-
--behaviour(gen_server).
-
--include_lib("orber/include/corba.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([start/1, shutdown/1, init/1,
- terminate/2, handle_call/3, code_change/3,
- get/2, list/1, add/3, remove/2,
- get/1, list/0, add/2, remove/1,
- typeID/0, install/2, oe_is_a/1, oe_tc/1, oe_get_interface/0]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([handle_cast/2, handle_info/2]).
-
-%%-----------------------------------------------------------------
-%% Mnesia Table definition record
-%%-----------------------------------------------------------------
--record(orber_references, {key, objref, type}).
-
--define(DEBUG_LEVEL, 6).
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-start(Env) ->
- gen_server:start_link({local, 'orber_init'}, ?MODULE, Env, []).
-
-shutdown(EO_this) ->
- gen_server:call(EO_this, stop).
-
-
-install(Timeout, Options) ->
- AllTabs = mnesia:system_info(tables),
- DB_Result = case lists:member(orber_references, AllTabs) of
- true ->
- case lists:member({local_content, true},
- Options) of
- true->
- mnesia:add_table_copy(orber_references,
- node(),
- ram_copies);
- _ ->
- mnesia:create_table(orber_references,
- [{attributes,
- record_info(fields,
- orber_references)}
- |Options])
- end;
- _ ->
- mnesia:create_table(orber_references,
- [{attributes,
- record_info(fields,
- orber_references)}
- |Options])
- end,
-
- Wait = mnesia:wait_for_tables([orber_references], Timeout),
- %% Check if any error has occurred yet. If there are errors, return them.
- if
- DB_Result == {atomic, ok},
- Wait == ok ->
- ok;
- true ->
- {error, {DB_Result, Wait}}
- end.
-
-
-%%-----------------------------------------------------------------
-%% InitialReferences Interface
-%%-----------------------------------------------------------------
-'get'(Id) ->
- case read(Id) of
- {'EXCEPTION', E} ->
- corba:raise(E);
- Result ->
- Result
- end.
-
-list() ->
- case list_keys() of
- {'EXCEPTION', E} ->
- corba:raise(E);
- Result ->
- Result
- end.
-
-
-add(Id, ObjRef) ->
- case write(Id, ObjRef, external) of
- {'EXCEPTION', E} ->
- corba:raise(E);
- Result ->
- Result
- end.
-
-
-remove(Id) ->
- case delete(Id) of
- {'EXCEPTION', E} ->
- corba:raise(E);
- Result ->
- Result
- end.
-
-
-'get'(EO_this, Id) ->
- corba:call(EO_this, 'get', [Id], ?MODULE).
-
-list(EO_this) ->
- corba:call(EO_this, 'list', [], ?MODULE).
-
-add(EO_this, Id, ObjRef) ->
- corba:call(EO_this, 'add', [Id, ObjRef], ?MODULE).
-
-remove(EO_this, Id) ->
- corba:call(EO_this, 'remove', [Id], ?MODULE).
-
-typeID() ->
- "IDL:Orber/InitialReferences:1.0".
-
-oe_is_a("IDL:Orber/InitialReferences:1.0") ->
- true;
-oe_is_a(_) ->
- false.
-
-%%-----------------------------------------------------------------
-%% Internal interface functions
-%%-----------------------------------------------------------------
-init([]) ->
- case mnesia:wait_for_tables(['orber_references'], infinity) of
- ok ->
- NSObjKey = 'CosNaming_NamingContextExt':oe_create([], [{pseudo, true},
- {no_security, orber:partial_security()}]),
- rewrite("NameService", NSObjKey),
- ErlIfr = 'OrberApp_IFR':oe_create([], [{pseudo, true}]),
- rewrite("OrberIFR", ErlIfr),
- {ok, []};
- StopReason ->
- {stop, StopReason}
- end.
-
-terminate(_Reason, _State) ->
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Handle incomming calls
-handle_call({_EO_this, _OE_Context, 'get', [Id]}, _From, State) ->
- {'reply', read(Id), State};
-handle_call({_EO_this, _OE_Context, 'list', []}, _From, State) ->
- {'reply', list_keys(), State};
-
-handle_call({_EO_this, _OE_Context, 'add', [Id, ObjectRef]}, _From, State) ->
- {'reply', write(Id, ObjectRef, external), State};
-
-handle_call({_EO_this, _OE_Context, 'remove', [Id]}, _From, State) ->
- {'reply', delete(Id), State};
-handle_call('stop', _From, State) ->
- {'stop', normal, 'ok', State};
-handle_call(_Req, _From,State) ->
- {'reply', {'ok', 'nil', 'nil'}, State}.
-
-oe_tc(get) ->
- {{'tk_objref', 12, "object"}, [{'tk_string', 0}], []};
-oe_tc(list) ->
- {{'tk_sequence',{'tk_string', 0}, 0}, [], []};
-oe_tc(add) ->
- {'tk_boolean', [{'tk_string', 0}, {'tk_objref', 12, "object"}], []};
-oe_tc(remove) ->
- {'tk_boolean', [{'tk_string', 0}], []};
-oe_tc(_) ->
- undefined.
-
-oe_get_interface() ->
- [{"get", oe_tc(get)},
- {"list", oe_tc(list)},
- {"add", oe_tc(add)}].
-
-
-%%-----------------------------------------------------------------
-%% Standard gen_server cast handle
-%%-----------------------------------------------------------------
-handle_cast(_, State) ->
- {noreply, State}.
-
-
-%%-----------------------------------------------------------------
-%% Standard gen_server handles
-%%-----------------------------------------------------------------
-handle_info(_, State) ->
- {noreply, State}.
-
-%%-----------------------------------------------------------------
-%% Func: code_change/3
-%%-----------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-read(Key) ->
- case mnesia:dirty_read({orber_references, Key}) of
- [] ->
- corba:create_nil_objref();
- [#orber_references{objref = ObjRef}] ->
- ObjRef;
- What ->
- orber:dbg("[~p] orber_initial_references:lookup(~p);~n"
- "Failed to read from DB: ~p",
- [?LINE, Key, What], ?DEBUG_LEVEL),
- {'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}}
- end.
-
-write(Key, ObjRef, Type) ->
- _WF = fun() ->
- case mnesia:wread({orber_references, Key}) of
- [] ->
- %% No key exists. Ok to register.
- mnesia:write(#orber_references{key=Key, objref = ObjRef,
- type=Type});
- [X] ->
- orber:dbg("[~p] orber_initial_references:write(~p);~n"
- "Already bound to: ~p",
- [?LINE, Key, X], ?DEBUG_LEVEL),
- false;
- Why ->
- %% Something else occured.
- orber:dbg("[~p] orber_initial_references:write(~p);~n"
- "Error reading from DB (~p)", [?LINE, Key, Why], ?DEBUG_LEVEL),
- mnesia:abort({'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}})
- end
- end,
- case mnesia:transaction(_WF) of
- {atomic, ok} ->
- true;
- {atomic, Result} ->
- Result;
- {aborted, Reason} ->
- Reason
- end.
-
-rewrite(Key, ObjRef) ->
- rewrite(Key, ObjRef, internal).
-rewrite(Key, ObjRef, Type) ->
- _WF = fun() ->
- mnesia:write(#orber_references{key=Key, objref = ObjRef, type=Type})
- end,
- case mnesia:transaction(_WF) of
- {atomic, ok} ->
- true;
- {aborted, Reason} ->
- orber:dbg("[~p] orber_initial_references:rewrite(~p);~n"
- "Error over writing in DB (~p)",
- [?LINE, Key, Reason], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-
-delete(Key) ->
- _DF = fun() ->
- case mnesia:read({orber_references, Key}) of
- [] ->
- %% No key exists.
- orber:dbg("[~p] orber_initial_references:delete(~p);~n"
- "Does not exist.", [?LINE, Key], ?DEBUG_LEVEL),
- false;
- [_X] ->
- mnesia:delete({orber_references, Key});
- Why ->
- %% Something else occured.
- orber:dbg("[~p] orber_initial_references:delete(~p);~n"
- "Error reading from DB (~p)",
- [?LINE, Key, Why], ?DEBUG_LEVEL),
- mnesia:abort({'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}})
- end
- end,
- case mnesia:transaction(_DF) of
- {atomic, ok} ->
- true;
- {atomic, Result} ->
- Result;
- {aborted, Reason} ->
- Reason
- end.
-
-list_keys() ->
- _LF = fun() -> mnesia:all_keys(orber_references) end,
- case mnesia:transaction(_LF) of
- {atomic, Result} ->
- %% We do not want OrberIFR to exported, remove it.
- lists:delete("OrberIFR", Result);
- {aborted, Reason} ->
- orber:dbg("[~p] orber_initial_references:list_keys();~n"
- "Error reading from DB (~p)", [?LINE, Reason], ?DEBUG_LEVEL),
- {'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}}
- end.
diff --git a/lib/orber/src/orber_interceptors.erl b/lib/orber/src/orber_interceptors.erl
deleted file mode 100644
index 4bfb2ae9a5..0000000000
--- a/lib/orber/src/orber_interceptors.erl
+++ /dev/null
@@ -1,154 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_interceptors.erl
-%%
-%% Description:
-%% This file contains the code for calling interceptors
-%%
-%%-----------------------------------------------------------------
--module(orber_interceptors).
-
--include_lib("orber/include/corba.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([call_send_message_interceptors/2, call_receive_message_interceptors/1,
- call_request_interceptors/2]).
--export([push_system_message_interceptor/2, pop_system_message_interceptor/1,
- create_interceptor_table/0]).
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-call_receive_message_interceptors(Bytes) ->
- case getInMessageInterceptors() of
- [] ->
- Bytes;
- Interceptors ->
- apply_message_interceptors(Interceptors, receive_message, corba:create_nil_objref(),
- lists:flatten(Bytes))
- end.
-call_send_message_interceptors(ObjRef, Bytes) ->
- case getOutMessageInterceptors() of
- [] ->
- Bytes;
- Interceptors ->
- apply_message_interceptors(Interceptors, send_message, ObjRef, lists:flatten(Bytes))
- end.
-
-
-call_request_interceptors(in, Bytes) ->
- case getInRequestInterceptors() of
- [] ->
- Bytes;
- Interceptors ->
- Bytes
- end;
-call_request_interceptors(out, Bytes) ->
- case getOutRequestInterceptors() of
- [] ->
- Bytes;
- Interceptors ->
- Bytes
- end.
-
-create_interceptor_table() ->
- %% Should be replicated mnesia
- ets:new(orber_interceptors, [protected, named_table, set]),
- ets:insert(orber_interceptors, {message_in_interceptors, []}),
- ets:insert(orber_interceptors, {message_out_interceptors, []}).
-
-push_system_message_interceptor(in, Mod) ->
- case ets:lookup(orber_interceptors, message_in_interceptors) of
- [{_, Interceptors}] ->
- ets:insert(orber_interceptors, {message_in_interceptors, [Mod | Interceptors]});
- _ ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
-push_system_message_interceptor(out, Mod) ->
- case ets:lookup(orber_interceptors, message_out_interceptors) of
- [{_, Interceptors}] ->
- ets:insert(orber_interceptors, {message_out_interceptors, Interceptors ++ [Mod]});
- _ ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-pop_system_message_interceptor(in) ->
- case ets:lookup(orber_interceptors, message_in_interceptors) of
- [{_, []}] ->
- ok;
- [{_, [_ | Interceptors]}] ->
- ets:insert(orber_interceptors, {message_in_interceptors, Interceptors});
- _ ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end;
-pop_system_message_interceptor(out) ->
- case ets:lookup(orber_interceptors, message_out_interceptors) of
- [{_, []}] ->
- ok;
- [{_, Interceptors}] ->
- ets:insert(orber_interceptors, {message_out_interceptors, lists:droplast(Interceptors)});
- _ ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-getInMessageInterceptors() ->
- case ets:lookup(orber_interceptors, message_in_interceptors) of
- [{_, Interceptors}] ->
- Interceptors;
- _ ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-getOutMessageInterceptors() ->
- case ets:lookup(orber_interceptors, message_out_interceptors) of
- [{_, Interceptors}] ->
- Interceptors;
- _ ->
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO})
- end.
-
-
-getInRequestInterceptors() ->
- [].
-
-getOutRequestInterceptors() ->
- [].
-
-
-apply_message_interceptors([], F, ObjRef, Bytes) ->
- Bytes;
-apply_message_interceptors([M | Rest], F, ObjRef, Bytes) ->
- apply_message_interceptors(Rest, F, ObjRef, apply(M, F, [ObjRef, Bytes])).
-
diff --git a/lib/orber/src/orber_objectkeys.erl b/lib/orber/src/orber_objectkeys.erl
deleted file mode 100644
index 12ed1a2f85..0000000000
--- a/lib/orber/src/orber_objectkeys.erl
+++ /dev/null
@@ -1,571 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_objectkeys.erl
-%%
-%% Description:
-%% This file contains the object keyserver in Orber
-%%
-%%-----------------------------------------------------------------
--module(orber_objectkeys).
-
--behaviour(gen_server).
-
--include_lib("orber/include/corba.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([start/1, stop/0, stop_all/0, get_pid/1, is_persistent/1,
- register/2, register/3, delete/1, create_schema/1, check/1,
- remove_old_keys/0]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([init/1, terminate/2, install/2, handle_call/3, handle_info/2, code_change/3]).
--export([handle_cast/2, dump/0, get_key_from_pid/1, gc/1]).
-
-%%-----------------------------------------------------------------
-%% Mnesia Table definition record
-%%-----------------------------------------------------------------
--record(orber_objkeys, {object_key, pid, persistent=false, timestamp}).
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
--define(dirty_query_context, true).
-
-%% This macro returns a read fun suitable for evaluation in a transaction
--define(read_function(Objkey),
- fun() ->
- mnesia:dirty_read(Objkey)
- end).
-
-%% This macro returns a write fun suitable for evaluation in a transaction
--define(write_function(R),
- fun() ->
- mnesia:dirty_write(R)
- end).
-
-%% This macro returns a delete fun suitable for evaluation in a transaction
--define(delete_function(R),
- fun() ->
- mnesia:delete(R)
- end).
-
-%% Use this fun inside a transaction to get a list of all keys.
--define(match_function(),
- fun() ->
- mnesia:match_object({orber_objkeys, '_', '_','_','_'})
- end).
-
--ifdef(dirty_query_context).
--define(query_check(Q_res), Q_res).
--else.
--define(query_check(Q_res), {atomic, Q_res}).
--endif.
-
-
--define(CHECK_EXCEPTION(Res), case Res of
- {'EXCEPTION', E} ->
- corba:raise(E);
- R ->
- R
- end).
-
--define(DEBUG_LEVEL, 6).
-
-
-
-%%-----------------------------------------------------------------
-%% Debugging function
-%%-----------------------------------------------------------------
-dump() ->
- case catch mnesia:dirty_first('orber_objkeys') of
- {'EXIT', R} ->
- io:format("Exited with ~p\n",[R]);
- Key ->
- dump_print(Key),
- dump_loop(Key)
- end.
-
-dump_loop(PreviousKey) ->
- case catch mnesia:dirty_next('orber_objkeys', PreviousKey) of
- {'EXIT', R} ->
- io:format("Exited with ~p\n",[R]);
- '$end_of_table' ->
- ok;
- Key ->
- dump_print(Key),
- dump_loop(Key)
- end.
-
-dump_print(Key) ->
- case catch mnesia:dirty_read({'orber_objkeys', Key}) of
- {'EXIT', R} ->
- io:format("Exited with ~p\n",[R]);
- [X] ->
- io:format("object_key: ~p, pid: ~p, persistent: ~p, timestamp: ~p\n",
- [binary_to_term(X#orber_objkeys.object_key),
- X#orber_objkeys.pid,
- X#orber_objkeys.persistent,
- X#orber_objkeys.timestamp]);
- _ ->
- ok
- end.
-
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-start(Opts) ->
- gen_server:start_link({local, orber_objkeyserver}, orber_objectkeys, Opts, []).
-
-stop() ->
- gen_server:call(orber_objkeyserver, stop, infinity).
-
-remove_old_keys() ->
- %% This function may ONLY be used when restarting a crashed node.
- %% We must remove all objects started with {global, "name"} otherwise
- %% we cannot restart the node using the same name.
- Fun = fun() ->
- Node = node(),
- mnesia:write_lock_table(orber_objkeys),
- Objects = mnesia:match_object(orber_objkeys,
- mnesia:table_info(orber_objkeys,
- wild_pattern),
- read),
- lists:foreach(fun(Obj) ->
- case node(Obj#orber_objkeys.pid) of
- Node ->
- mnesia:delete({orber_objkeys,
- Obj#orber_objkeys.object_key});
- _->
- ok
- end
- end,
- Objects),
- ok
- end,
- write_result(mnesia:transaction(Fun)).
-
-stop_and_remove_local(Reason) ->
- %% This function may ONLY be used when this server terminates with reason
- %% normal or shutdown.
- Fun = fun() ->
- Node = node(),
- mnesia:write_lock_table(orber_objkeys),
- Objects = mnesia:match_object(orber_objkeys,
- mnesia:table_info(orber_objkeys,
- wild_pattern),
- read),
- lists:foreach(fun(Obj) ->
- case node(Obj#orber_objkeys.pid) of
- Node ->
- exit(Obj#orber_objkeys.pid, Reason),
- mnesia:delete({orber_objkeys,
- Obj#orber_objkeys.object_key});
- _->
- ok
- end
- end,
- Objects),
- ok
- end,
- write_result(mnesia:transaction(Fun)).
-
-stop_all() ->
- Fun = ?match_function(),
- case mnesia:transaction(Fun) of
- {atomic, Objects} ->
- lists:foreach(fun(Obj) ->
- gen_server:call(Obj#orber_objkeys.pid,
- stop, infinity)
- end,
- Objects);
- R ->
- R
- end.
-
-get_pid(Objkey) ->
- case catch ets:lookup_element(orber_objkeys, Objkey, 3) of
- Pid when is_pid(Pid) ->
- Pid;
- dead ->
- {error, "unable to contact object"};
- _ ->
- %% This call is necessary if a persistent object have died
- %% and the objectkey server is currently updating the Pid
- %% to equal 'dead'. Without this case 'OBJECT_NOT_EXIST'
- %% would be raised which is uncorrect if the object is
- %% persistent.
- ?CHECK_EXCEPTION(gen_server:call(orber_objkeyserver,
- {get_pid, Objkey},
- infinity))
- end.
-
-is_persistent(Pid) when is_pid(Pid) ->
- case catch get_key_from_pid(Pid) of
- {'EXCEPTION', _} ->
- corba:raise(#'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO});
- Key ->
- is_persistent(Key)
- end;
-is_persistent(Objkey) ->
- case catch ets:lookup_element(orber_objkeys, Objkey, 4) of
- {'EXIT', _R} ->
- corba:raise(#'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO});
- Boolean ->
- Boolean
- end.
-
-
-gc(Sec) when is_integer(Sec) ->
- Fun = fun() ->
- mnesia:write_lock_table(orber_objkeys),
- Objects = mnesia:match_object({orber_objkeys, '_', dead, true,'_'}),
- lists:foreach(fun(Obj) ->
- case timetest(Sec, Obj#orber_objkeys.timestamp) of
- true ->
- mnesia:delete({orber_objkeys,
- Obj#orber_objkeys.object_key});
- _->
- ok
- end
- end,
- Objects),
- ok
- end,
- write_result(mnesia:transaction(Fun)).
-
-register(Objkey, Pid) ->
- 'register'(Objkey, Pid, false).
-
-register(Objkey, Pid, Type) when is_pid(Pid) ->
- ?CHECK_EXCEPTION(gen_server:call(orber_objkeyserver,
- {register, Objkey, Pid, Type},
- infinity));
-register(Objkey, Pid, Type) ->
- orber:dbg("[~p] orber_objectkeys:register(~p, ~p); Not a Pid ~p",
- [?LINE, Objkey, Type, Pid], ?DEBUG_LEVEL),
- corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}).
-
-delete(Objkey) ->
- ?CHECK_EXCEPTION(gen_server:call(orber_objkeyserver,
- {delete, Objkey}, infinity)).
-
-check(Objkey) ->
- ?CHECK_EXCEPTION(gen_server:call(orber_objkeyserver,
- {check, Objkey}, infinity)).
-
-%%-----------------------------------------------------------------
-%% Server functions
-%%-----------------------------------------------------------------
-init(_Env) ->
- case mnesia:wait_for_tables(['orber_objkeys'], infinity) of
- ok ->
- process_flag(trap_exit, true),
- start_gc_timer(orber:objectkeys_gc_time());
- StopReason ->
- {stop, StopReason}
- end.
-
-terminate(shutdown, _State) ->
- stop_and_remove_local(shutdown),
- ok;
-terminate(normal, _State) ->
- stop_and_remove_local(normal),
- ok;
-terminate(_Reason, _State) ->
- ok.
-
-start_gc_timer(infinity) ->
- {ok, []};
-start_gc_timer(Time) ->
- timer:start(),
- case timer:send_after(timer:seconds(Time),
- orber_objkeyserver, {oe_gc, Time}) of
- {ok, _} ->
- {ok, []};
- StopReason ->
- {stop, StopReason}
- end.
-
-install(Timeout, Options) ->
- %% check if there already exists a database. If not, create one.
- %% DB_initialized = perhaps_create_schema(Nodelist),
- %% check if mnesia is running. If not, start mnesia.
- perhaps_start_mnesia(),
-
- %% Do we have a complete set of IFR tables? If not, create them.
- AllTabs = mnesia:system_info(tables),
-
- DB_Result = case lists:member(orber_objkeys, AllTabs) of
- true ->
- case lists:member({local_content, true},
- Options) of
- true->
- mnesia:add_table_copy(orber_objkeys,
- node(),
- ram_copies);
- _ ->
- mnesia:create_table(orber_objkeys,
- [{attributes,
- record_info(fields,
- orber_objkeys)}
- |Options])
- end;
- _ ->
- mnesia:create_table(orber_objkeys,
- [{attributes,
- record_info(fields,
- orber_objkeys)}
- |Options])
- end,
-
- Wait = mnesia:wait_for_tables([orber_objkeys], Timeout),
- %% Check if any error has occurred yet. If there are errors, return them.
- if
- DB_Result == {atomic, ok},
- Wait == ok ->
- ok;
- true ->
- {error, {DB_Result, Wait}}
- end.
-
-%%-----------------------------------------------------------------
-%% Func: handle_call/3
-%%
-%% Comment:
-%% In objectkey gen_server all exceptions are tupples and corba:raise
-%% may not be used. It is too time consuming to add catches in every
-%% function before returning. On the client side there is a case which
-%% maps every tupple on the format {'exception', E} to corba:raise(E).
-%%-----------------------------------------------------------------
-handle_call(stop, _From, State) ->
- {stop, normal, [], State};
-handle_call({get, Objkey}, _From, State) ->
- R = query_result(mnesia:dirty_read({orber_objkeys, Objkey})),
- {reply, R, State};
-
-handle_call({register, Objkey, Pid, Type}, _From, State) ->
- _WF = fun() ->
- case mnesia:wread({orber_objkeys, Objkey}) of
- [] ->
- %% No key exists. Ok to register.
- mnesia:write(#orber_objkeys{object_key=Objkey, pid=Pid,
- persistent=Type,
- timestamp=erlang:monotonic_time(seconds)});
- [X] when X#orber_objkeys.persistent==true,
- X#orber_objkeys.pid == dead ->
- %% A persistent object is being restarted. Update Pid & time.
- mnesia:write(X#orber_objkeys{pid=Pid, timestamp=erlang:monotonic_time(seconds)});
- [X] when is_pid(X#orber_objkeys.pid) ->
- %% Object exists, i.e., trying to create an object with
- %% the same name.
- orber:dbg("[~p] orber_objectkeys:register(~p, ~p); Object already exists.",
- [?LINE, Objkey, Type], ?DEBUG_LEVEL),
- {'EXCEPTION', #'BAD_PARAM'{completion_status=?COMPLETED_NO}};
- Why ->
- %% Something else occured.
- orber:dbg("[~p] orber_objectkeys:register(~p, ~p); error reading from DB(~p)",
- [?LINE, Objkey, Type, Why], ?DEBUG_LEVEL),
- {'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}}
- end
- end,
- R = write_result(mnesia:transaction(_WF)),
- if
- R == ok andalso is_pid(Pid) ->
- link(Pid);
- true ->
- true
- end,
- {reply, R, State};
-
-handle_call({delete, Objkey}, _From, State) ->
- ?query_check(Qres) = mnesia:dirty_read({orber_objkeys, Objkey}),
- case Qres of
- [] ->
- true;
- [X] when is_pid(X#orber_objkeys.pid) ->
- unlink(X#orber_objkeys.pid);
- _ ->
- true
- end,
- _F = ?delete_function({orber_objkeys, Objkey}),
- R = write_result(mnesia:transaction(_F)),
- {reply, R, State};
-
-handle_call({get_pid, Objkey}, _From, State) ->
- _F = fun() ->
- mnesia:read({orber_objkeys, Objkey})
- end,
- case mnesia:transaction(_F) of
- {atomic, [X]} when is_pid(X#orber_objkeys.pid) ->
- {reply, X#orber_objkeys.pid, State};
- {atomic, [X]} when X#orber_objkeys.pid == dead ->
- {reply,
- {'EXCEPTION', #'TRANSIENT'{completion_status=?COMPLETED_NO}},
- State};
- _Res ->
- {reply,
- {'EXCEPTION', #'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO}},
- State}
- end;
-handle_call({check, {_, 'key', Objkey, _, _, _}}, _From, State) ->
- ?query_check(Qres) = mnesia:dirty_read({orber_objkeys, Objkey}),
- case Qres of
- [_X] ->
- {reply, 'object_here', State};
- _ ->
- {reply, 'unknown_object', State}
- end;
-handle_call({check, {_, 'registered', Objkey, _, _, _}}, _From, State) ->
- case whereis(Objkey) of
- undefined ->
- case catch ets:lookup_element(orber_objkeys, Objkey, 4) of
- true ->
- {reply, 'object_here', State};
- _->
- {reply, 'unknown_object', State}
- end;
- _ ->
- {reply, 'object_here', State}
- end;
-handle_call({check, {_, 'pseudo', Module, _, _, _}}, _From, State) ->
- case code:is_loaded(Module) of
- false ->
- {reply, 'unknown_object', State};
- _ ->
- {reply, 'object_here', State}
- end;
-
-handle_call({check, "INIT"}, _From, State) ->
- {reply, 'object_here', State};
-handle_call({check, _}, _From, State) ->
- {reply, 'unknown_object', State}.
-
-
-handle_info({'EXIT', Pid, Reason}, State) when is_pid(Pid) ->
- _WF = fun() ->
- case mnesia:match_object({orber_objkeys, '_', Pid,'_','_'}) of
- [] ->
- ok;
- [X] when X#orber_objkeys.persistent==false ->
- mnesia:delete({orber_objkeys, X#orber_objkeys.object_key});
- [X] when is_pid(X#orber_objkeys.pid) andalso
- X#orber_objkeys.persistent==true andalso
- Reason /= normal andalso
- Reason /= shutdown ->
- mnesia:write(X#orber_objkeys{pid=dead,
- timestamp=erlang:monotonic_time(seconds)});
- [X] when X#orber_objkeys.persistent==true ->
- mnesia:delete({orber_objkeys, X#orber_objkeys.object_key});
- _->
- ok
- end
- end,
- case write_result(mnesia:transaction(_WF)) of
- ok ->
- unlink(Pid);
- _->
- true
- end,
- {noreply, State};
-
-handle_info({oe_gc, Secs}, State) ->
- catch gc(Secs),
- {noreply, State}.
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%-----------------------------------------------------------------
-%% Internal Functions
-%%-----------------------------------------------------------------
-
-timetest(S, TimeStamp) ->
- TimeStamp+S < erlang:monotonic_time(seconds).
-
-get_key_from_pid(Pid) ->
- case mnesia:dirty_match_object({orber_objkeys, '_', Pid,'_','_'}) of
- [Keys] ->
- Keys#orber_objkeys.object_key;
- _ ->
- corba:raise(#'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO})
- end.
-
-%remove_keys([], _) ->
-% ok;
-%remove_keys([H|T], R) when H#orber_objkeys.persistent==false ->
-% _F = ?delete_function({orber_objkeys, H#orber_objkeys.object_key}),
-% write_result(mnesia:transaction(_F)),
-% remove_keys(T, R).
-
-%%-----------------------------------------------------------------
-%% Check a read transaction
-query_result(?query_check(Qres)) ->
- case Qres of
- [Hres] ->
- Hres#orber_objkeys.pid;
- [] ->
- {'EXCEPTION', #'OBJECT_NOT_EXIST'{completion_status=?COMPLETED_NO}};
- Other ->
- orber:dbg("[~p] orber_objectkeys:query_result(); DB lookup failed(~p)",
- [?LINE, Other], ?DEBUG_LEVEL),
- {'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}}
- end.
-
-%%-----------------------------------------------------------------
-%% Check a write transaction
-write_result({atomic,ok}) -> ok;
-write_result(Foo) ->
- orber:dbg("[~p] orber_objectkeys:query_result(); DB write failed(~p)",
- [?LINE, Foo], ?DEBUG_LEVEL),
- {'EXCEPTION', #'INTERNAL'{completion_status=?COMPLETED_NO}}.
-
-
-create_schema(Nodes) ->
- case mnesia:system_info(use_dir) of
- false ->
- mnesia:create_schema(Nodes);
- _ ->
- ok
- end.
-
-perhaps_start_mnesia() ->
- case mnesia:system_info(is_running) of
- no ->
- mnesia:start();
- _ ->
- ok
- end.
-
-
-%%------------------------------------------------------------
-%% Standard gen_server cast handle
-%%
-handle_cast(_, State) ->
- {noreply, State}.
-
-
diff --git a/lib/orber/src/orber_pi.erl b/lib/orber/src/orber_pi.erl
deleted file mode 100644
index 19bb7af6c0..0000000000
--- a/lib/orber/src/orber_pi.erl
+++ /dev/null
@@ -1,1213 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_pi.erl
-%% Purpose :
-%% Comments:
-%% * Each Interceptor is represented by Module where
-%% Module - refers to a module which must export the functions:
-%% (1) receive_request
-%% (2) send_other
-%% (3) receive_service_contexts
-%% (4) send_reply
-%% (5) send_exception
-%% (6) send_request
-%% (7) send_poll
-%% (8) receive_reply
-%% (9) receive_exception
-%% (10) receive_other
-%% or
-%% (11) new_out_connection
-%% (12) new_in_connection
-%% (13) in_request
-%% (14) out_reply
-%% (15) out_request
-%% (16) in_reply
-%%
-%% Functions (1) - (10) for Portable and (11) - (16) for
-%% Native Interceptors.
-%%
-%%----------------------------------------------------------------------
-
--module(orber_pi).
-
-%%--------------- INCLUDES -----------------------------------
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
--include_lib("orber/include/orber_pi.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
-%%--------------- EXPORTS-------------------------------------
-%% API external
--export([%% Native Intercepotors API
- new_out_connection/5,
- new_in_connection/5,
- closed_in_connection/2,
- closed_out_connection/2,
- in_request_enc/4,
- out_reply_enc/5,
- out_request_enc/6,
- in_reply_enc/6,
- in_request/4,
- out_reply/5,
- out_request/6,
- in_reply/6,
- %% Portable Interceptors
- server_start_receive/7,
- server_start_send/2,
- client_receive/2,
- client_send/2,
- codefactory_create_codec/1,
- codec_encode/2,
- codec_encode_value/2,
- codec_decode/2,
- codec_decode_value/3,
- %% RequestInfo
- '_get_request_id'/1,
- '_get_operation'/1,
- '_get_arguments'/1,
- '_get_exceptions'/1,
- '_get_contexts'/1,
- '_get_operation_context'/1,
- '_get_result'/1,
- '_get_response_expected'/1,
- '_get_sync_scope'/1,
- '_get_reply_status'/1,
- '_get_forward_reference'/1,
- get_slot/2,
- get_request_service_context/2,
- get_reply_service_context/2,
- %% ClientRequestInfo (inherrits RequestInfo)
- '_get_target'/1,
- '_get_effective_target'/1,
- '_get_effective_profile'/1,
- '_get_received_exception'/1,
- '_get_received_exception_id'/1,
- get_effective_component/2,
- get_effective_components/2,
- get_request_policy/2,
- add_request_service_policy/3,
- %% ServerRequestInfo (inherrits RequestInfo)
- '_get_sending_exception'/1,
- '_get_object_id'/1,
- '_get_adapter_id'/1,
- '_get_target_most_derived_interface'/1,
- get_server_policy/2,
- set_slot/3,
- target_is_a/2,
- add_reply_service_context/3]).
-
-%%=============== DATA STRUCTURES ============================
-%%--------------- ClientRequestInfo --------------------------
--record('ClientRequestInfo',
- {request_id,
- operation,
- arguments,
- exceptions,
- contexts,
- operation_context,
- result,
- response_expected,
- sync_scope = 'SYNC_NONE',
- reply_status,
- forward_reference,
- endian,
- target,
- effective_target,
- effective_profile,
- received_exception,
- received_exception_id}).
-
--define(createInitCRI(_ReqID, _Op, _Args, _Ctxs, _OpCtx, _RespExp, _Target,
- _ETarget, _EProf),
- #'ClientRequestInfo'{request_id = _ReqID,
- operation = _Op,
- arguments = _Args,
- contexts = _Ctxs,
- operation_context = _OpCtx,
- response_expected = _RespExp,
- target = _Target,
- effective_target = _ETarget,
- effective_profile = _EProf}).
-
-
-%%--------------- ServerRequestInfo --------------------------
--record('ServerRequestInfo',
- {request_id,
- operation,
- arguments,
- exceptions,
- contexts,
- operation_context,
- result,
- response_expected,
- sync_scope = 'SYNC_NONE',
- reply_status,
- forward_reference,
- endian,
- sending_exception,
- object_id,
- adapter_id,
- target_most_derived_interface}).
-
--define(createInitSRI(_ReqID, _Op, _RespExp),
- #'ServerRequestInfo'{request_id = _ReqID,
- operation = _Op,
- response_expected = _RespExp}).
-
-
-%%--------------- DEFINES ------------------------------------
--define(DEBUG_LEVEL, 9).
-
--define(EFORMAT(_F, _A), exit(lists:flatten(io_lib:format(_F, _A)))).
-
-%%------------------------------------------------------------
-%%------------- NATIVE INTERCEPTOR FUNCTIONS------------------
-%%------------------------------------------------------------
-%% function : new_in_connection
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-new_in_connection(PIs, Host, Port, SHost, SPort) ->
- case catch new_in_connection(PIs, undefined, Host, Port, SHost, SPort) of
- {'EXIT', R} ->
- orber:dbg("[~p] orber_pi:new_in_connection(~p); exit(~p)",
- [?LINE, PIs, R], ?DEBUG_LEVEL),
- ?EFORMAT("Supplied Interceptors unable to create a valid new_in_connection"
- "Reason: ~p", [{'EXIT', R}]);
- {'EXCEPTION', E} ->
- orber:dbg("[~p] orber_pi:new_in_connection(~p); exception(~p)",
- [?LINE, PIs, E], ?DEBUG_LEVEL),
- ?EFORMAT("Supplied Interceptors unable to create a valid new_in_connection"
- "Reason: ~p", [{'EXCEPTION', E}]);
- Ref ->
- Ref
- end.
-
-new_in_connection([], Ref, _, _, _, _) ->
- Ref;
-new_in_connection([Mod|T], Ref, Host, Port, SHost, SPort) ->
- case get_arity(Mod, new_in_connection) of
- 5 ->
- NewRef = Mod:new_in_connection(Ref, Host, Port, SHost, SPort),
- new_in_connection(T, NewRef, Host, Port, SHost, SPort);
- 3 ->
- NewRef = Mod:new_in_connection(Ref, Host, Port),
- new_in_connection(T, NewRef, Host, Port, SHost, SPort)
- end.
-
-get_arity(Mod, Func) ->
- get_arity(Mod, Func, true).
-get_arity(Mod, Func, Retry) ->
- case erlang:function_exported(Mod, Func, 5) of
- true ->
- 5;
- false ->
- case erlang:function_exported(Mod, Func, 3) of
- true ->
- 3;
- false when Retry == true ->
- {module, _} = code:ensure_loaded(Mod),
- get_arity(Mod, Func, false);
- false ->
- exit("Unable to load interceptor")
- end
- end.
-
-%%------------------------------------------------------------
-%% function : closed_in_connection
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-closed_in_connection(PIs, Ref) ->
- case catch closed_in_connection_helper(PIs, Ref) of
- {'EXIT', R} ->
- orber:dbg("[~p] orber_pi:closed_in_connection(~p, ~p); exit(~p)",
- [?LINE, PIs, Ref, R], ?DEBUG_LEVEL),
- ok;
- {'EXCEPTION', E} ->
- orber:dbg("[~p] orber_pi:closed_in_connection(~p, ~p); exception(~p)",
- [?LINE, PIs, Ref, E], ?DEBUG_LEVEL),
- ok;
- _ ->
- ok
- end.
-
-closed_in_connection_helper([], _Ref) ->
- ok;
-closed_in_connection_helper([Mod|T], Ref) ->
- NewRef = Mod:closed_in_connection(Ref),
- closed_in_connection_helper(T, NewRef).
-
-
-%%------------------------------------------------------------
-%% function : new_out_connection
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-new_out_connection(PIs, Host, Port, SHost, SPort) ->
- case catch new_out_connection(PIs, undefined, Host, Port, SHost, SPort) of
- {'EXIT', R} ->
- orber:dbg("[~p] orber_pi:new_out_connection(~p); exit(~p)",
- [?LINE, PIs, R], ?DEBUG_LEVEL),
- ?EFORMAT("Supplied Interceptors unable to create a valid new_out_connection"
- "Reason: ~p", [{'EXIT', R}]);
- {'EXCEPTION', E} ->
- orber:dbg("[~p] orber_pi:new_out_connection(~p); exception(~p)",
- [?LINE, PIs, E], ?DEBUG_LEVEL),
- ?EFORMAT("Supplied Interceptors unable to create a valid new_out_connection"
- "Reason: ~p", [{'EXCEPTION', E}]);
- Ref ->
- Ref
- end.
-
-new_out_connection([], Ref, _, _, _, _) ->
- Ref;
-new_out_connection([Mod|T], Ref, Host, Port, SHost, SPort) ->
- case get_arity(Mod, new_out_connection) of
- 5 ->
- NewRef = Mod:new_out_connection(Ref, Host, Port, SHost, SPort),
- new_out_connection(T, NewRef, Host, Port, SHost, SPort);
- 3 ->
- NewRef = Mod:new_out_connection(Ref, Host, Port),
- new_out_connection(T, NewRef, Host, Port, SHost, SPort)
- end.
-
-%%------------------------------------------------------------
-%% function : closed_out_connection
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-closed_out_connection(PIs, Ref) ->
- case catch closed_out_connection_helper(PIs, Ref) of
- {'EXIT', R} ->
- orber:dbg("[~p] orber_pi:closed_out_connection(~p); exit(~p)",
- [?LINE, PIs, R], ?DEBUG_LEVEL),
- ok;
- {'EXCEPTION', E} ->
- orber:dbg("[~p] orber_pi:closed_out_connection(~p); exception(~p)",
- [?LINE, PIs, E], ?DEBUG_LEVEL),
- ok;
- _ ->
- ok
- end.
-
-closed_out_connection_helper([], _Ref) ->
- ok;
-closed_out_connection_helper([Mod|T], Ref) ->
- NewRef = Mod:closed_out_connection(Ref),
- closed_out_connection_helper(T, NewRef).
-
-%%------------------------------------------------------------
-%% function : in_request_enc
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect : Intercepts an incoming request (server-side).
-%%------------------------------------------------------------
-in_request_enc(PIs, ReqHdr, Ref, Msg) ->
- case catch in_request_enc(PIs, ReqHdr, Ref, Msg, undefined) of
- {'EXIT', R} ->
- orber:dbg("[~p] orber_pi:in_request_enc(~p, ~p, ~p); exit(~p)",
- [?LINE, PIs, Ref, Msg, R], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO});
- {'EXCEPTION', E} ->
- orber:dbg("[~p] orber_pi:in_request_enc(~p, ~p, ~p); exception(~p)",
- [?LINE, PIs, Ref, Msg, E], ?DEBUG_LEVEL),
- corba:raise(E);
- NewMsg ->
- NewMsg
- end.
-
-in_request_enc([], _, _, Msg, _) ->
- Msg;
-in_request_enc([Mod|T], ReqHdr, Ref, Msg, Args) ->
- {NewMsg, NewArgs} = Mod:in_request_encoded(Ref, ReqHdr#request_header.object_key,
- ReqHdr#request_header.service_context,
- ReqHdr#request_header.operation,
- Msg, Args),
- in_request_enc(T, ReqHdr, Ref, NewMsg, NewArgs).
-
-%%------------------------------------------------------------
-%% function : in_request
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect : Intercepts an incoming request (server-side).
-%%------------------------------------------------------------
-in_request(PIs, ReqHdr, Ref, Msg) ->
- case catch in_request(PIs, ReqHdr, Ref, Msg, undefined) of
- {'EXIT', R} ->
- orber:dbg("[~p] orber_pi:in_request(~p, ~p, ~p); exit(~p)",
- [?LINE, PIs, Ref, Msg, R], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO});
- {'EXCEPTION', E} ->
- orber:dbg("[~p] orber_pi:in_request(~p, ~p, ~p); exception(~p)",
- [?LINE, PIs, Ref, Msg, E], ?DEBUG_LEVEL),
- corba:raise(E);
- NewMsg ->
- NewMsg
- end.
-
-in_request([], _, _, Msg, _) ->
- Msg;
-in_request([Mod|T], ReqHdr, Ref, Msg, Args) ->
- {NewMsg, NewArgs} = Mod:in_request(Ref, ReqHdr#request_header.object_key,
- ReqHdr#request_header.service_context,
- ReqHdr#request_header.operation,
- Msg, Args),
- in_request(T, ReqHdr, Ref, NewMsg, NewArgs).
-
-%%------------------------------------------------------------
-%% function : out_reply_enc
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect : Intercept an outgoing reply (server-side).
-%%------------------------------------------------------------
-out_reply_enc(PIs, ReqHdr, Ref, Msg, Ctx) ->
- case catch out_reply_enc(PIs, ReqHdr, Ref, Msg, undefined, Ctx) of
- {'EXIT', R} ->
- orber:dbg("[~p] orber_pi:out_reply_enc(~p, ~p, ~p); exit(~p)",
- [?LINE, PIs, Ref, Msg, R], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE});
- {'EXCEPTION', E} ->
- orber:dbg("[~p] orber_pi:out_reply_enc(~p, ~p, ~p); exception(~p)",
- [?LINE, PIs, Ref, Msg, E], ?DEBUG_LEVEL),
- corba:raise(E);
- NewMsg ->
- NewMsg
- end.
-out_reply_enc([], _, _, Msg, _, _) ->
- Msg;
-out_reply_enc([Mod|T], ReqHdr, Ref, Msg, Args, Ctx) ->
- {NewMsg, NewArgs} = Mod:out_reply_encoded(Ref, ReqHdr#request_header.object_key,
- Ctx, %% Out Context.
- ReqHdr#request_header.operation,
- Msg, Args),
- out_reply_enc(T, ReqHdr, Ref, NewMsg, NewArgs, Ctx).
-
-
-%%------------------------------------------------------------
-%% function : out_reply
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect : Intercept an outgoing reply (server-side).
-%%------------------------------------------------------------
-out_reply(PIs, ReqHdr, Ref, Msg, Ctx) ->
- case catch out_reply(PIs, ReqHdr, Ref, Msg, undefined, Ctx) of
- {'EXIT', R} ->
- orber:dbg("[~p] orber_pi:out_reply(~p, ~p, ~p); exit(~p)",
- [?LINE, PIs, Ref, Msg, R], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE});
- NewMsg ->
- NewMsg
- end.
-out_reply([], _, _, Msg, _, _) ->
- Msg;
-out_reply([Mod|T], ReqHdr, Ref, Msg, Args, Ctx) ->
- {NewMsg, NewArgs} = Mod:out_reply(Ref, ReqHdr#request_header.object_key,
- Ctx, %% Out Context.
- ReqHdr#request_header.operation,
- Msg, Args),
- out_reply(T, ReqHdr, Ref, NewMsg, NewArgs, Ctx).
-
-
-%%------------------------------------------------------------
-%% function : out_request_enc
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect : Intercept an outgoing request (client-side).
-%%------------------------------------------------------------
-out_request_enc(PIs, ObjKey, Ctx, Op, Ref, Msg) ->
- case catch out_request_enc(PIs, ObjKey, Ctx, Op, Ref, Msg, undefined) of
- {'EXIT', R} ->
- orber:dbg("[~p] orber_pi:out_request_enc(~p, ~p, ~p); exit(~p)",
- [?LINE, PIs, Ref, Msg, R], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO});
- {'EXCEPTION', E} ->
- orber:dbg("[~p] orber_pi:out_request_enc(~p, ~p, ~p); exception(~p)",
- [?LINE, PIs, Ref, Msg, E], ?DEBUG_LEVEL),
- corba:raise(E);
- NewMsg ->
- NewMsg
- end.
-
-out_request_enc([], _, _, _, _, Msg, _) ->
- Msg;
-out_request_enc([Mod|T], ObjKey, Ctx, Op, Ref, Msg, Args) ->
- {NewMsg, NewArgs} = Mod:out_request_encoded(Ref, ObjKey, Ctx, Op, Msg, Args),
- out_request_enc(T, ObjKey, Ctx, Op, Ref, NewMsg, NewArgs).
-
-
-%%------------------------------------------------------------
-%% function : out_request
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect : Intercept an outgoing request (client-side).
-%%------------------------------------------------------------
-out_request(PIs, ObjKey, Ctx, Op, Ref, Msg) ->
- case catch out_request(PIs, ObjKey, Ctx, Op, Ref, Msg, undefined) of
- {'EXIT', R} ->
- orber:dbg("[~p] orber_pi:out_request(~p, ~p, ~p); exit(~p)",
- [?LINE, PIs, Ref, Msg, R], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_NO});
- {'EXCEPTION', E} ->
- orber:dbg("[~p] orber_pi:out_request(~p, ~p, ~p); exception(~p)",
- [?LINE, PIs, Ref, Msg, E], ?DEBUG_LEVEL),
- corba:raise(E);
- NewMsg ->
- NewMsg
- end.
-
-out_request([], _, _, _, _, Msg, _) ->
- Msg;
-out_request([Mod|T], ObjKey, Ctx, Op, Ref, Msg, Args) ->
- {NewMsg, NewArgs} = Mod:out_request(Ref, ObjKey, Ctx, Op, Msg, Args),
- out_request(T, ObjKey, Ctx, Op, Ref, NewMsg, NewArgs).
-
-
-%%------------------------------------------------------------
-%% function :in_reply_enc
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect : Intercept an incoming reply (client-side)
-%%------------------------------------------------------------
-in_reply_enc(PIs, ObjKey, Ctx, Op, Ref, Msg) ->
- case catch in_reply_enc(PIs, ObjKey, Ctx, Op, Ref, Msg, undefined) of
- {'EXIT', R} ->
- orber:dbg("[~p] orber_pi:in_reply_enc(~p, ~p, ~p); exit(~p)",
- [?LINE, PIs, Ref, Msg, R], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE});
- {'EXCEPTION', E} ->
- orber:dbg("[~p] orber_pi:in_reply_enc(~p, ~p, ~p); exception(~p)",
- [?LINE, PIs, Ref, Msg, E], ?DEBUG_LEVEL),
- corba:raise(E);
- NewMsg ->
- NewMsg
- end.
-
-in_reply_enc([], _, _, _, _, Msg, _) ->
- Msg;
-in_reply_enc([Mod|T], ObjKey, Ctx, Op, Ref, Msg, Args) ->
- {NewMsg, NewArgs} = Mod:in_reply_encoded(Ref, ObjKey, Ctx, Op, Msg, Args),
- in_reply_enc(T, ObjKey, Ctx, Op, Ref, NewMsg, NewArgs).
-
-%%------------------------------------------------------------
-%% function :in_reply
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect : Intercept an incoming reply (client-side)
-%%------------------------------------------------------------
-in_reply(PIs, ObjKey, Ctx, Op, Ref, Msg) ->
- case catch in_reply(PIs, ObjKey, Ctx, Op, Ref, Msg, undefined) of
- {'EXIT', R} ->
- orber:dbg("[~p] orber_pi:in_reply(~p, ~p, ~p); exit(~p)",
- [?LINE, PIs, Ref, Msg, R], ?DEBUG_LEVEL),
- corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE});
- NewMsg ->
- NewMsg
- end.
-
-in_reply([], _, _, _, _, Msg, _) ->
- Msg;
-in_reply([Mod|T], ObjKey, Ctx, Op, Ref, Msg, Args) ->
- {NewMsg, NewArgs} = Mod:in_reply(Ref, ObjKey, Ctx, Op, Msg, Args),
- in_reply(T, ObjKey, Ctx, Op, Ref, NewMsg, NewArgs).
-
-
-
-
-%%------------------------------------------------------------
-%%------------- CODEC FUNCTIONS ------------------------------
-%%------------------------------------------------------------
-%% function : codefactory_create_codec
-%% Arguments: #IOP_N_Encoding{}
-%% Returns : CodecRef
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-codefactory_create_codec(#'IOP_N_Encoding'{format = 'IOP_N_ENCODING_CDR_ENCAPS',
- major_version = Major,
- minor_version = Minor})
- when is_integer(Major) andalso is_integer(Minor) ->
- {Major, Minor};
-codefactory_create_codec(_) ->
- corba:raise(#'IOP_N_CodecFactory_UnknownEncoding'{}).
-
-%%------------------------------------------------------------
-%% function : codec_encode
-%% Arguments: Version - GIOP version
-%% Any - #any{}
-%% Returns : CORBA::OctetSeq
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-codec_encode(Version, Any) when is_record(Any, any) ->
- %% Encode ByteOrder
- {Bytes, Len} = cdr_encode:enc_type('tk_octet', Version, 0, [], 0),
- {Bytes2, _Len2} = cdr_encode:enc_type('tk_any', Version, Any, Bytes, Len),
- list_to_binary(lists:reverse(Bytes2));
-codec_encode(_Version, _Any) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%------------------------------------------------------------
-%% function : codec_encode_value
-%% Arguments: Version - GIOP version
-%% Any - #any{}
-%% Returns : CORBA::OctetSeq
-%% Exception:
-%% Effect : Encode the Any#any.value only.
-%%------------------------------------------------------------
-codec_encode_value(Version, #any{typecode = TC, value = Val}) ->
- %% Encode ByteOrder
- {Bytes, Len} = cdr_encode:enc_type('tk_octet', Version, 0, [], 0),
- {Bytes2, _Len2} = cdr_encode:enc_type(TC, Version, Val, Bytes, Len),
- list_to_binary(lists:reverse(Bytes2));
-codec_encode_value(_Version, _NotAnAny) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%------------------------------------------------------------
-%% function : codec_decode
-%% Arguments: Version - GIOP version
-%% Bytes - CORBA::OctetSeq
-%% Returns : Any - #any{}
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-codec_decode(Version, Bytes) when is_binary(Bytes) ->
- {ByteOrder, Rest} = cdr_decode:dec_byte_order(Bytes),
- case catch cdr_decode:dec_type('tk_any', Version, Rest, 0, ByteOrder) of
- {Any, [], _} ->
- Any;
- _->
- corba:raise(#'IOP_N_Codec_FormatMismatch'{})
- end;
-codec_decode(_Version, _Any) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-%%------------------------------------------------------------
-%% function : codec_decode_value
-%% Arguments: Version - GIOP version
-%% Bytes - CORBA::OctetSeq
-%% TypeCode - CORBA::TypeCode
-%% Returns : Any - #any{}
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-codec_decode_value(Version, Bytes, TypeCode) when is_binary(Bytes) ->
- {ByteOrder, Rest} = cdr_decode:dec_byte_order(Bytes),
- case catch cdr_decode:dec_type(TypeCode, Version, Rest, 0, ByteOrder) of
- {Val, [], _} ->
- #any{typecode = TypeCode, value = Val};
- _->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO})
- end;
-codec_decode_value(_Version, _Bytes, _TypeCode) ->
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}).
-
-
-%%------------------------------------------------------------
-%%------------- SERVER SIDE FUNCTIONS ------------------------
-%%------------------------------------------------------------
-%% To make a long story short, you find an conceptual description
-%% of how, and in which order, the different functions is
-%% supposed to be invoked.
-%%
-%%request_from_iiop(Bytes) ->
-%% Reply =
-%% case receive_service_contexts(ServerRequestInfo) of
-%% SYSTEM EXC ->
-%% send_exception(..);
-%% ForwardRequest EXC ->
-%% send_other(..);
-%% NoEXC ->
-%% case receive_request(..) of
-%% SYSTEM EXC ->
-%% send_exception(..);
-%% ForwardRequest EXC ->
-%% send_other(..);
-%% No EXC ->
-%% InvokeServer
-%% end
-%% end,
-%% case Reply of
-%% EXC ->
-%% send_exception(..);
-%% No EXC, Normal Reply ->
-%% case send_reply(..) of
-%% SYSTEM EXC ->
-%% send_exception(..);
-%% ForwardRequest EXC ->
-%% send_other(..);
-%% No Exc ->
-%% Done
-%% end;
-%% No EXC, LOCATION_FORWARD ->
-%% send_other(..)
-%% end.
-%%
-%%
-%%------------------------------------------------------------
-%% function : server_start_receive
-%% Arguments: Msg - #giop_message{}
-%% PIs - a list of Interceptors (see 'Comments' in the module header)
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-server_start_receive(PIs, Version, ReqHdr, Rest, Len, ByteOrder, Msg) ->
- cdr_decode:dec_request_body(Version, ReqHdr, Rest, Len, ByteOrder, Msg),
- SRI = ?createInitSRI(ReqHdr#request_header.request_id,
- ReqHdr#request_header.operation,
- ReqHdr#request_header.response_expected),
- server_receive(receive_service_contexts, SRI, PIs, [], PIs).
-
-server_receive(receive_service_contexts, SRI, [], _Acc, PIs) ->
- server_receive(receive_request, SRI, PIs, [], PIs);
-server_receive(receive_service_contexts, SRI, [H|T], Acc, PIs) ->
- case catch receive_service_contexts(SRI, H) of
- {'EXCEPTION', #'PortableInterceptor_ForwardRequest'{forward=_Obj,
- permanent=_Bool}} ->
- server_send(send_other, SRI, Acc, [], PIs);
- {'EXCEPTION', _E} ->
- server_send(send_exception, SRI, Acc, [], PIs);
- _ ->
- server_receive(receive_service_contexts, SRI, T, Acc, PIs)
- end;
-server_receive(receive_request, SRI, [], _Acc, _PIs) ->
- %% Done with receive interceptors, now we can call the server.
- SRI;
-server_receive(receive_request, SRI, [H|T], Acc, PIs) ->
- case catch receive_request(SRI, H) of
- {'EXCEPTION', #'PortableInterceptor_ForwardRequest'{forward=_Obj,
- permanent=_Bool}} ->
- server_send(send_other, SRI, Acc, [], PIs);
- {'EXCEPTION', _E} ->
- server_send(send_exception, SRI, Acc, [], PIs);
- _ ->
- server_receive(receive_request, SRI, T, Acc, PIs)
- end.
-
-
-%%------------------------------------------------------------
-%% function : server_start_send
-%% Arguments: SRI - ServerRequestInfo
-%% PIs - a list of Interceptors (see 'Comments' in the module header)
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-server_start_send(PIs, SRI) ->
- case SRI#'ServerRequestInfo'.reply_status of
- 'PortableInterceptor_SUCCESSFUL' ->
- server_send(send_reply, SRI, PIs, [], PIs);
- 'PortableInterceptor_SYSTEM_EXCEPTION' ->
- server_send(send_exception, SRI, PIs, [], PIs);
- 'PortableInterceptor_USER_EXCEPTION' ->
- server_send(send_exception, SRI, PIs, [], PIs);
- _ ->
- server_send(send_other, SRI, PIs, [], PIs)
- end.
-
-server_send(_, SRI, [], _Acc, _PIs) ->
- %% Done
- SRI;
-server_send(send_exception, SRI, [H|T], Acc, PIs) ->
- case catch send_exception(SRI, H) of
- {'EXCEPTION', #'PortableInterceptor_ForwardRequest'{forward=_Obj,
- permanent=_Bool}} ->
- server_send(send_other, SRI, Acc, [], PIs);
- {'EXCEPTION', _E} ->
- server_send(send_exception, SRI, Acc, [], PIs);
- _ ->
- server_send(send_exception, SRI, T, Acc, PIs)
- end;
-server_send(send_other, SRI, [H|T], Acc, PIs) ->
- case catch send_other(SRI, H) of
- {'EXCEPTION', #'PortableInterceptor_ForwardRequest'{forward=_Obj,
- permanent=_Bool}} ->
- server_send(send_other, SRI, T, Acc, PIs);
- {'EXCEPTION', _E} ->
- server_send(send_exception, SRI, T, Acc, PIs);
- _ ->
- server_send(send_other, SRI, T, Acc, PIs)
- end;
-server_send(send_reply, SRI, [H|T], Acc, PIs) ->
- case catch send_reply(SRI, H) of
- {'EXCEPTION', _E} ->
- server_send(send_exception, SRI, T, Acc, PIs);
- _ ->
- server_send(send_reply, SRI, T, Acc, PIs)
- end.
-
-receive_request(SRI, Mod) ->
- apply(Mod, receive_request, [SRI]).
-
-send_other(SRI, Mod) ->
- apply(Mod, send_other, [SRI]).
-
-receive_service_contexts(SRI, Mod) ->
- apply(Mod, receive_service_contexts, [SRI]).
-
-send_reply(SRI, Mod) ->
- apply(Mod, send_reply, [SRI]).
-
-send_exception(SRI, Mod) ->
- apply(Mod, send_exception, [SRI]).
-
-
-%%------------------------------------------------------------
-%%------------- CLIENT SIDE FUNCTIONS ------------------------
-%%------------------------------------------------------------
-%% To make a long story short, you find an conceptual description
-%% of how, and in which order, the different functions is
-%% supposed to be invoked.
-%%
-%%request(Data) ->
-%% Reply =
-%% case send_request(CRI) of
-%% SYSTEM EXC ->
-%% receive_exception(..);
-%% ForwardRequest EXC ->
-%% receive_other(..);
-%% NoEXC ->
-%% IIOP-send
-%% end,
-%% case Reply of
-%% EXC ->
-%% receive_exception(..); May raise system exc => receive_other(..);
-%% No EXC, Normal Reply ->
-%% receive_reply(..) May raise system exc => receive_exception(..);
-%% Non-normal reply (e.g. LOCATION_FORWARD) ->
-%% receive_other(..) May raise system exc => receive_exception(..);
-%% end.
-%%------------------------------------------------------------
-%% function : client_send
-%% Arguments: CRI - ClientRequestInfo
-%% PIs - a list of Interceptors (see 'Comments' in the module header)
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-
-client_send(CRI, PIs) ->
- client_send(send_request, CRI, PIs, [], PIs).
-
-client_send(send_request, CRI, [], _, _) ->
- CRI;
-client_send(send_request, CRI, [H|T], Acc, PIs) ->
- case catch send_request(CRI, H) of
- {'EXCEPTION', #'PortableInterceptor_ForwardRequest'{forward=_Obj,
- permanent=_Bool}} ->
- client_receive(receive_other, CRI, T, [], PIs);
- {'EXCEPTION', _E} ->
- client_receive(receive_exception, CRI, Acc, [], PIs);
- _ ->
- client_send(send_request, CRI, T, Acc, PIs)
- end.
-
-
-
-%%------------------------------------------------------------
-%% function : client_receive
-%% Arguments: CRI - ClientRequestInfo
-%% PIs - a list of Interceptors (see 'Comments' in the module header)
-%% Returns :
-%% Exception:
-%% Effect :
-%%------------------------------------------------------------
-
-client_receive(CRI, PIs) ->
- case CRI#'ClientRequestInfo'.reply_status of
- 'PortableInterceptor_SUCCESSFUL' ->
- client_receive(receive_reply, CRI, PIs, [], PIs);
- 'PortableInterceptor_SYSTEM_EXCEPTION' ->
- client_receive(receive_exception, CRI, PIs, [], PIs);
- 'PortableInterceptor_USER_EXCEPTION' ->
- client_receive(receive_exception, CRI, PIs, [], PIs);
- _ ->
- client_receive(receive_other, CRI, PIs, [], PIs)
- end.
-
-client_receive(_, CRI, [], _, _) ->
- %% Done
- CRI;
-client_receive(receive_reply, CRI, [H|T], Acc, PIs) ->
- case catch receive_reply(CRI, H) of
- {'EXCEPTION', _E} ->
- client_receive(receive_exception, CRI, T, [H|Acc], PIs);
- _ ->
- client_receive(receive_reply, CRI, T, [H|Acc], PIs)
- end;
-client_receive(receive_exception, CRI, [H|T], Acc, PIs) ->
- case catch receive_exception(CRI, H) of
- {'EXCEPTION', #'PortableInterceptor_ForwardRequest'{forward=_Obj,
- permanent=_Bool}} ->
- client_receive(receive_other, CRI, T, [], PIs);
- {'EXCEPTION', _E} ->
- client_receive(receive_exception, CRI, T, [H|Acc], PIs);
- _ ->
- client_receive(receive_exception, CRI, T, [H|Acc], PIs)
- end;
-client_receive(receive_other, CRI, [H|T], Acc, PIs) ->
- case catch receive_other(CRI, H) of
- {'EXCEPTION', #'PortableInterceptor_ForwardRequest'{forward=_Obj,
- permanent=_Bool}} ->
- client_receive(receive_other, CRI, T, [], PIs);
- {'EXCEPTION', _E} ->
- client_receive(receive_exception, CRI, T, [H|Acc], PIs);
- _ ->
- client_receive(receive_other, CRI, T, [H|Acc], PIs)
- end.
-
-
-
-send_request(CRI, Mod) ->
- apply(Mod, send_request, [CRI]).
-
-receive_reply(CRI, Mod) ->
- apply(Mod, receive_reply, [CRI]).
-
-receive_other(CRI, Mod) ->
- apply(Mod, receive_other, [CRI]).
-
-receive_exception(CRI, Mod) ->
- apply(Mod, receive_exception, [CRI]).
-
-%%------------------------------------------------------------
-%% Functions for retrieving info from RequestInfo
-%% ServerRequestInfo and ClientRequestInfo. The ones matching
-%% both ServerRequestInfo and ClientRequestInfo eq. RequestInfo.
-%% Note, RequestInfo is inherrited by the others.
-%%------------------------------------------------------------
-%%-----------------------------------------------------------%
-%% function : _get_request_id
-%% Arguments: ClientRequestInfo or ServerRequestInfo
-%% Returns : ulong()
-%%------------------------------------------------------------
-'_get_request_id'(#'ClientRequestInfo'{request_id = ID}) ->
- ID;
-'_get_request_id'(#'ServerRequestInfo'{request_id = ID}) ->
- ID.
-
-%%-----------------------------------------------------------%
-%% function : _get_operation
-%% Arguments: ClientRequestInfo or ServerRequestInfo
-%% Returns : string()
-%%------------------------------------------------------------
-'_get_operation'(#'ClientRequestInfo'{operation = Op}) ->
- Op;
-'_get_operation'(#'ServerRequestInfo'{operation = Op}) ->
- Op.
-
-%%-----------------------------------------------------------%
-%% function : _get_arguments
-%% Arguments: ClientRequestInfo or ServerRequestInfo
-%% Returns : A list of #'Dynamic_Parameter'{}
-%%------------------------------------------------------------
-'_get_arguments'(#'ClientRequestInfo'{arguments = Args}) ->
- Args;
-'_get_arguments'(#'ServerRequestInfo'{arguments = Args}) ->
- Args.
-
-%%-----------------------------------------------------------%
-%% function : _get_exceptions
-%% Arguments: ClientRequestInfo or ServerRequestInfo
-%% Returns : A list of CORBA::TypeCode
-%%------------------------------------------------------------
-'_get_exceptions'(#'ClientRequestInfo'{exceptions = Exc}) ->
- Exc;
-'_get_exceptions'(#'ServerRequestInfo'{exceptions = Exc}) ->
- Exc.
-
-%%-----------------------------------------------------------%
-%% function : _get_contexts
-%% Arguments: ClientRequestInfo or ServerRequestInfo
-%% Returns : A list of CORBA::StringSeq
-%%------------------------------------------------------------
-'_get_contexts'(#'ClientRequestInfo'{contexts = Ctx}) ->
- Ctx;
-'_get_contexts'(#'ServerRequestInfo'{contexts = Ctx}) ->
- Ctx.
-
-%%-----------------------------------------------------------%
-%% function : _get_operation_context
-%% Arguments: ClientRequestInfo or ServerRequestInfo
-%% Returns : A list of CORBA::StringSeq
-%%------------------------------------------------------------
-'_get_operation_context'(#'ClientRequestInfo'{operation_context = OpCtx}) ->
- OpCtx;
-'_get_operation_context'(#'ServerRequestInfo'{operation_context = OpCtx}) ->
- OpCtx.
-
-%%-----------------------------------------------------------%
-%% function : _get_result
-%% Arguments: ClientRequestInfo or ServerRequestInfo
-%% Returns : #any{}
-%%------------------------------------------------------------
-'_get_result'(#'ClientRequestInfo'{result = Res}) ->
- Res;
-'_get_result'(#'ServerRequestInfo'{result = Res}) ->
- Res.
-
-%%-----------------------------------------------------------%
-%% function : _get_response_expected
-%% Arguments: ClientRequestInfo or ServerRequestInfo
-%% Returns : boolean()
-%%------------------------------------------------------------
-'_get_response_expected'(#'ClientRequestInfo'{response_expected = Bool}) ->
- Bool;
-'_get_response_expected'(#'ServerRequestInfo'{response_expected = Bool}) ->
- Bool.
-
-%%-----------------------------------------------------------%
-%% function : _get_sync_scope
-%% Arguments: ClientRequestInfo or ServerRequestInfo
-%% Returns : Messaging::SyncScoope ('SYNC_NONE', 'SYNC_WITH_TRANSPORT',
-%% 'SYNC_WITH_SERVER', 'SYNC_WITH_TARGET')
-%%------------------------------------------------------------
-'_get_sync_scope'(#'ClientRequestInfo'{sync_scope = SS}) ->
- SS;
-'_get_sync_scope'(#'ServerRequestInfo'{sync_scope = SS}) ->
- SS.
-
-%%-----------------------------------------------------------%
-%% function : _get_reply_status
-%% Arguments: ClientRequestInfo or ServerRequestInfo
-%% Returns : ReplyStatus (short), defined in orber_pi.hrl
-%%------------------------------------------------------------
-'_get_reply_status'(#'ClientRequestInfo'{reply_status = RS}) ->
- RS;
-'_get_reply_status'(#'ServerRequestInfo'{reply_status = RS}) ->
- RS.
-
-%%-----------------------------------------------------------%
-%% function : _get_forward_reference
-%% Arguments: ClientRequestInfo or ServerRequestInfo
-%% Returns : Object
-%%------------------------------------------------------------
-'_get_forward_reference'(#'ClientRequestInfo'{forward_reference = FR}) ->
- FR;
-'_get_forward_reference'(#'ServerRequestInfo'{forward_reference = FR}) ->
- FR.
-
-%%------------------------------------------------------------
-%% function : get_slot
-%% Arguments: ClientRequestInfo or ServerRequestInfo
-%% SlotId - ulong()
-%% Returns : {'EXCEPTION', #'PortableInterceptor_InvalidSlot'{}}
-%%------------------------------------------------------------
--spec get_slot(_, _) -> no_return().
-get_slot(_XRI, _SlotId) ->
- corba:raise(#'PortableInterceptor_InvalidSlot'{}).
-
-%%------------------------------------------------------------
-%% function : get_request_service_context
-%% Arguments: ClientRequestInfo or ServerRequestInfo
-%% ServiceId - IOP::ServiceId (defined in orber_iiop.hrl)
-%% Returns : IOP::ServiceContext
-%%------------------------------------------------------------
-get_request_service_context(#'ClientRequestInfo'{contexts = Ctx}, _ServiceId) ->
- Ctx;
-get_request_service_context(#'ServerRequestInfo'{contexts = Ctx}, _ServiceId) ->
- Ctx.
-
-%%------------------------------------------------------------
-%% function : get_reply_service_context
-%% Arguments: ClientRequestInfo or ServerRequestInfo
-%% ServiceId - IOP::ServiceId (defined in orber_iiop.hrl)
-%% Returns : IOP::ServiceContext
-%%------------------------------------------------------------
-get_reply_service_context(#'ClientRequestInfo'{contexts = Ctx}, _ServiceId) ->
- Ctx;
-get_reply_service_context(#'ServerRequestInfo'{contexts = Ctx}, _ServiceId) ->
- Ctx.
-
-%%------------------------------------------------------------
-%%-------------- ClientRequestInfo only ----------------------
-%%-----------------------------------------------------------%
-%% function : _get_target
-%% Arguments: ClientRequestInfo
-%% Returns : Object
-%%------------------------------------------------------------
-'_get_target'(#'ClientRequestInfo'{target = Target}) ->
- Target.
-
-%%-----------------------------------------------------------%
-%% function : _get_effective_target
-%% Arguments: ClientRequestInfo
-%% Returns : Object
-%%------------------------------------------------------------
-'_get_effective_target'(#'ClientRequestInfo'{effective_target = ET}) ->
- ET.
-
-%%-----------------------------------------------------------%
-%% function : _get_effective_profile
-%% Arguments: ClientRequestInfo
-%% Returns : IOP:TaggedProfile
-%%------------------------------------------------------------
-'_get_effective_profile'(#'ClientRequestInfo'{effective_profile = EP}) ->
- EP.
-
-%%-----------------------------------------------------------%
-%% function : _get_received_exception
-%% Arguments: ClientRequestInfo
-%% Returns : #any{}
-%%------------------------------------------------------------
-'_get_received_exception'(#'ClientRequestInfo'{received_exception = RE}) ->
- RE.
-
-%%-----------------------------------------------------------%
-%% function : _get_received_exception
-%% Arguments: ClientRequestInfo
-%% Returns : CORBA::RepositoryId
-%%------------------------------------------------------------
-'_get_received_exception_id'(#'ClientRequestInfo'{received_exception_id = REId}) ->
- REId.
-
-%%------------------------------------------------------------
-%% function : get_effective_component
-%% Arguments: ClientRequestInfo
-%% Returns : IOR::TaggedComponent
-%%------------------------------------------------------------
-get_effective_component(#'ClientRequestInfo'{target = Target}, _Id) ->
- Target.
-
-%%------------------------------------------------------------
-%% function : get_effective_components
-%% Arguments: ClientRequestInfo
-%% Id -IOP::ComponentId (ulong())
-%% Returns : IOP_N::TaggedComponentSeq
-%%------------------------------------------------------------
-get_effective_components(#'ClientRequestInfo'{target = Target}, _Id) ->
- Target.
-
-%%------------------------------------------------------------
-%% function : get_request_policy
-%% Arguments: ClientRequestInfo
-%% Type - CORBA::PolicyType
-%% Returns : IOP_N::TaggedComponentSeq
-%%------------------------------------------------------------
-get_request_policy(#'ClientRequestInfo'{target = Target}, _Type) ->
- Target.
-
-%%------------------------------------------------------------
-%% function : add_request_service_context
-%% Arguments: ClientRequestInfo
-%% Ctx - IOP::ServiceContext
-%% Replace - boolean()
-%% Returns : -
-%%------------------------------------------------------------
-add_request_service_policy(#'ClientRequestInfo'{target = _Target},
- _Ctx, _Replace) ->
- ok.
-
-%%------------------------------------------------------------
-%%-------------- ServerRequestInfo only ----------------------
-%%-----------------------------------------------------------%
-%% function : _get_sending_exception
-%% Arguments: ServerRequestInfo
-%% Returns : #any{}
-%%------------------------------------------------------------
-'_get_sending_exception'(#'ServerRequestInfo'{sending_exception = Exc}) ->
- Exc.
-
-%%-----------------------------------------------------------%
-%% function : _get_object_id
-%% Arguments: ServerRequestInfo
-%% Returns : CORBA::OctetSeq
-%%------------------------------------------------------------
-'_get_object_id'(#'ServerRequestInfo'{object_id = OI}) ->
- OI.
-
-%%-----------------------------------------------------------%
-%% function : _get_adapter_id
-%% Arguments: ServerRequestInfo
-%% Returns : CORBA::OctetSeq
-%%------------------------------------------------------------
-'_get_adapter_id'(#'ServerRequestInfo'{adapter_id = AI}) ->
- AI.
-
-%%-----------------------------------------------------------%
-%% function : _get_target_most_derived_interface
-%% Arguments: ServerRequestInfo
-%% Returns : CORBA::RepositoryId
-%%------------------------------------------------------------
-'_get_target_most_derived_interface'(#'ServerRequestInfo'
- {target_most_derived_interface = TMDI}) ->
- TMDI.
-
-%%------------------------------------------------------------
-%% function : get_server_policy
-%% Arguments: ServerRequestInfo
-%% PolicyType - CORBA::PolicyType
-%% Returns : CORBA::Policy
-%%------------------------------------------------------------
-get_server_policy(#'ServerRequestInfo'{contexts = Ctxs}, _PolicyType) ->
- Ctxs.
-
-%%------------------------------------------------------------
-%% function : set_slot
-%% Arguments: ServerRequestInfo
-%% SlotId - ulong()
-%% Data - #any{}
-%% Returns : {'EXCEPTION', #'PortableInterceptor_InvalidSlot'{}}
-%%------------------------------------------------------------
--spec set_slot(_, _, _) -> no_return().
-set_slot(_SRI, _SlotId, _Data) ->
- corba:raise(#'PortableInterceptor_InvalidSlot'{}).
-
-%%-----------------------------------------------------------%
-%% function : target_is_a
-%% Arguments: ServerRequestInfo
-%% IFRId - CORBA::RepositoryId
-%% Returns : boolean()
-%%------------------------------------------------------------
-target_is_a(#'ServerRequestInfo'{object_id = ObjId}, IFRId) ->
- corba_object:is_a(ObjId, IFRId).
-
-%%------------------------------------------------------------
-%% function : add_reply_service_context
-%% Arguments: ServerRequestInfo
-%% Ctx - IOP::ServiceContext
-%% Replace - boolean()
-%% Returns : -
-%%------------------------------------------------------------
-add_reply_service_context(#'ServerRequestInfo'{contexts = Ctxs}, _Ctx, _Replace) ->
- Ctxs.
-
-
-%%--------------- END OF MODULE ------------------------------
diff --git a/lib/orber/src/orber_request_number.erl b/lib/orber/src/orber_request_number.erl
deleted file mode 100644
index 755b999c13..0000000000
--- a/lib/orber/src/orber_request_number.erl
+++ /dev/null
@@ -1,83 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_request_number.erl
-%%
-%% Description:
-%% This file contains the request number server in Orber
-%%
-%%-----------------------------------------------------------------
--module(orber_request_number).
-
--behaviour(gen_server).
-
--include_lib("orber/src/orber_iiop.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([start/1, get/0, reset/0]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([init/1, terminate/2, handle_call/3]).
--export([handle_cast/2, handle_info/2, code_change/3]).
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-start(Opts) ->
- gen_server:start_link({local, orber_reqno}, orber_request_number, Opts, []).
-
-get() ->
- gen_server:call(orber_reqno, get, infinity).
-
-reset() ->
- gen_server:call(orber_reqno, reset, infinity).
-
-%%-----------------------------------------------------------------
-%% Server functions
-%%-----------------------------------------------------------------
-init(_Opts) ->
- {ok, 0}.
-
-terminate(_Reason, _State) ->
- ok.
-%% Max is ulong 0 .. 2^32-1
-handle_call(get, _From, State) when State < ?ULONGMAX ->
- {reply, State, State+1};
-handle_call(get, _From, _State) ->
- {reply, ?ULONGMAX, 0};
-handle_call(reset, _From, _State) ->
- {reply, ok, 0}.
-
-handle_cast(_, State) ->
- {noreply, State}.
-
-handle_info(_, State) ->
- {noreply, State}.
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-
diff --git a/lib/orber/src/orber_socket.erl b/lib/orber/src/orber_socket.erl
deleted file mode 100644
index 9b39dad928..0000000000
--- a/lib/orber/src/orber_socket.erl
+++ /dev/null
@@ -1,530 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_socket.erl
-%%
-%% Description:
-%% This file contains a standard interface to the sockets to handle the differences
-%% between the implementations used.
-%%
-%%-----------------------------------------------------------------
--module(orber_socket).
-
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([start/0, connect/4, listen/3, listen/4, accept/2, accept/3, write/3,
- controlling_process/3, close/2, peername/2, sockname/2,
- peerdata/2, peercert/2, sockdata/2, setopts/3,
- clear/2, shutdown/3, post_accept/2, post_accept/3,
- get_ip_family_opts/1]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% Internal defines
-%%-----------------------------------------------------------------
--define(DEBUG_LEVEL, 6).
-
-%%-----------------------------------------------------------------
-%% External functions
-%%-----------------------------------------------------------------
-start() ->
- inet_db:start().
-
-%%-----------------------------------------------------------------
-%% Invoke the required setopts (i.e., inet or ssl)
-setopts(normal, Socket, Opts) ->
- inet:setopts(Socket, Opts);
-setopts(ssl, Socket, Opts) ->
- ssl:setopts(Socket, Opts).
-
-%%-----------------------------------------------------------------
-%% Connect to IIOP Port at Host in CDR mode, in order to
-%% establish a connection.
-%%
-connect(Type, Host, Port, Options) ->
- Timeout = orber:iiop_setup_connection_timeout(),
- Generation = orber_env:ssl_generation(),
- Options1 = check_options(Type, Options, Generation),
- Options2 =
- case Type of
- normal ->
- [{keepalive, orber_env:iiop_out_keepalive()}|Options1];
- _ ->
- Options1
- end,
- case orber:iiop_out_ports() of
- {Min, Max} when Type == normal ->
- multi_connect(get_port_sequence(Min, Max), orber_env:iiop_out_ports_attempts(),
- Type, Host, Port, [binary, {reuseaddr, true},
- {packet,cdr}| Options2], Timeout);
- {Min, Max} when Generation > 2 ->
- multi_connect(get_port_sequence(Min, Max), orber_env:iiop_out_ports_attempts(),
- Type, Host, Port, [binary, {reuseaddr, true},
- {packet,cdr}| Options2], Timeout);
- {Min, Max} ->
- %% reuseaddr not available for older SSL versions
- multi_connect(get_port_sequence(Min, Max), orber_env:iiop_out_ports_attempts(),
- Type, Host, Port, [binary, {packet,cdr}| Options2], Timeout);
- _ ->
- connect(Type, Host, Port, [binary, {packet,cdr}| Options2], Timeout)
- end.
-
-connect(normal, Host, Port, Options, Timeout) ->
- case catch gen_tcp:connect(Host, Port, Options, Timeout) of
- {ok, Socket} ->
- Socket;
- {error, timeout} ->
- orber:dbg("[~p] orber_socket:connect(normal, ~p, ~p, ~p);~n"
- "Timeout after ~p msec.",
- [?LINE, Host, Port, Options, Timeout], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{minor=(?ORBER_VMCID bor 4),
- completion_status=?COMPLETED_NO});
- Error ->
- orber:dbg("[~p] orber_socket:connect(normal, ~p, ~p, ~p);~n"
- "Failed with reason: ~p",
- [?LINE, Host, Port, Options, Error], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO})
- end;
-connect(ssl, Host, Port, Options, Timeout) ->
- case catch ssl:connect(Host, Port, Options, Timeout) of
- {ok, Socket} ->
- Socket;
- {error, timeout} ->
- orber:dbg("[~p] orber_socket:connect(ssl, ~p, ~p, ~p);~n"
- "Timeout after ~p msec.",
- [?LINE, Host, Port, Options, Timeout], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{minor=(?ORBER_VMCID bor 4),
- completion_status=?COMPLETED_NO});
- Error ->
- orber:dbg("[~p] orber_socket:connect(ssl, ~p, ~p, ~p);~n"
- "Failed with reason: ~p",
- [?LINE, Host, Port, Options, Error], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO})
- end.
-
-multi_connect([], _Retries, Type, Host, Port, Options, _) ->
- orber:dbg("[~p] orber_socket:multi_connect(~p, ~p, ~p, ~p);~n"
- "Unable to use any of the sockets defined by 'iiop_out_ports'.~n"
- "Either all ports are in use or to many connections already exists.",
- [?LINE, Type, Host, Port, Options], ?DEBUG_LEVEL),
- corba:raise(#'IMP_LIMIT'{minor=(?ORBER_VMCID bor 1), completion_status=?COMPLETED_NO});
-multi_connect([CurrentPort|Rest], Retries, normal, Host, Port, Options, Timeout) ->
- case catch gen_tcp:connect(Host, Port, [{port, CurrentPort}|Options], Timeout) of
- {ok, Socket} ->
- Socket;
- {error, timeout} when Retries =< 1 ->
- orber:dbg("[~p] orber_socket:multi_connect(normal, ~p, ~p, ~p);~n"
- "Timeout after ~p msec.",
- [?LINE, Host, Port, [{port, CurrentPort}|Options],
- Timeout], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{minor=(?ORBER_VMCID bor 4),
- completion_status=?COMPLETED_NO});
- _ ->
- multi_connect(Rest, Retries - 1, normal, Host, Port, Options, Timeout)
- end;
-multi_connect([CurrentPort|Rest], Retries, ssl, Host, Port, Options, Timeout) ->
- case catch ssl:connect(Host, Port, [{port, CurrentPort}|Options], Timeout) of
- {ok, Socket} ->
- Socket;
- {error, timeout} when Retries =< 1 ->
- orber:dbg("[~p] orber_socket:multi_connect(ssl, ~p, ~p, ~p);~n"
- "Timeout after ~p msec.",
- [?LINE, Host, Port, [{port, CurrentPort}|Options],
- Timeout], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{minor=(?ORBER_VMCID bor 4),
- completion_status=?COMPLETED_NO});
- _ ->
- multi_connect(Rest, Retries - 1, ssl, Host, Port, Options, Timeout)
- end.
-
-
-get_port_sequence(Min, Max) ->
- case orber_env:iiop_out_ports_random() of
- true ->
- Seq = lists:seq(Min, Max),
- random_sequence((Max - Min) + 1, Seq, []);
- _ ->
- lists:seq(Min, Max)
- end.
-
-random_sequence(0, _, Acc) ->
- Acc;
-random_sequence(Length, Seq, Acc) ->
- Nth = rand:uniform(Length),
- Value = lists:nth(Nth, Seq),
- NewSeq = lists:delete(Value, Seq),
- random_sequence(Length-1, NewSeq, [Value|Acc]).
-
-%%-----------------------------------------------------------------
-%% Create a listen socket at Port in CDR mode for
-%% data connection.
-%%
-listen(Type, Port, Options) ->
- listen(Type, Port, Options, true).
-
-listen(normal, Port, Options, Exception) ->
- Options1 = check_options(normal, Options, 0),
- Backlog = orber:iiop_backlog(),
- Keepalive = orber_env:iiop_in_keepalive(),
- Options2 = case orber:iiop_max_in_requests() of
- infinity ->
- Options1;
- _MaxRequests ->
- [{active, once}|Options1]
- end,
- Options3 = case orber_env:iiop_packet_size() of
- infinity ->
- Options2;
- MaxSize ->
- [{packet_size, MaxSize}|Options2]
- end,
- Options4 = [binary, {packet,cdr}, {keepalive, Keepalive},
- {reuseaddr,true}, {backlog, Backlog} |
- Options3],
-
- case catch gen_tcp:listen(Port, Options4) of
- {ok, ListenSocket} ->
- {ok, ListenSocket, check_port(Port, normal, ListenSocket)};
- {error, Reason} when Exception == false ->
- {error, Reason};
- {error, eaddrinuse} ->
- orber:dbg("[~p] orber_socket:listen(normal, ~p, ~p);~n"
- "Looks like the listen port is already in use.~n"
- "Check if another Orber is started~n"
- "on the same node and uses the same listen port (iiop_port). But it may also~n"
- "be used by any other application; confirm with 'netstat'.",
- [?LINE, Port, Options4], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO});
- Error ->
- orber:dbg("[~p] orber_socket:listen(normal, ~p, ~p);~n"
- "Failed with reason: ~p",
- [?LINE, Port, Options4, Error], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO})
- end;
-listen(ssl, Port, Options, Exception) ->
- Backlog = orber:iiop_ssl_backlog(),
- Generation = orber_env:ssl_generation(),
- Options1 = check_options(ssl, Options, Generation),
- Options2 = case orber:iiop_max_in_requests() of
- infinity ->
- Options1;
- _MaxRequests ->
- [{active, once}|Options1]
- end,
- Options3 = case orber_env:iiop_packet_size() of
- infinity ->
- Options2;
- MaxSize ->
- [{packet_size, MaxSize}|Options2]
- end,
- Options4 = if
- Generation > 2 ->
- [{reuseaddr, true} |Options3];
- true ->
- Options3
- end,
- Options5 = [binary, {packet,cdr}, {backlog, Backlog} | Options4],
- case catch ssl:listen(Port, Options5) of
- {ok, ListenSocket} ->
- {ok, ListenSocket, check_port(Port, ssl, ListenSocket)};
- {error, Reason} when Exception == false ->
- {error, Reason};
- {error, eaddrinuse} ->
- orber:dbg("[~p] orber_socket:listen(ssl, ~p, ~p);~n"
- "Looks like the listen port is already in use. Check if~n"
- "another Orber is started on the same node and uses the~n"
- "same listen port (iiop_port). But it may also~n"
- "be used by any other application; confirm with 'netstat'.",
- [?LINE, Port, Options5], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO});
- Error ->
- orber:dbg("[~p] orber_socket:listen(ssl, ~p, ~p);~n"
- "Failed with reason: ~p",
- [?LINE, Port, Options5, Error], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO})
- end.
-
-%%-----------------------------------------------------------------
-%% Wait in accept on the socket
-%%
-accept(Type, ListenSocket) ->
- accept(Type, ListenSocket, infinity).
-
-accept(normal, ListenSocket, _Timeout) ->
- case catch gen_tcp:accept(ListenSocket) of
- {ok, S} ->
- S;
- Error ->
- orber:dbg("[~p] orber_socket:accept(normal, ~p);~n"
- "Failed with reason: ~p",
- [?LINE, ListenSocket, Error], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO})
- end;
-accept(ssl, ListenSocket, Timeout) ->
- case catch ssl:transport_accept(ListenSocket, Timeout) of
- {ok, S} ->
- S;
- Error ->
- orber:dbg("[~p] orber_socket:accept(ssl, ~p);~n"
- "Failed with reason: ~p",
- [?LINE, ListenSocket, Error], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO})
- end.
-
-post_accept(Type, Socket) ->
- post_accept(Type, Socket, infinity).
-
-post_accept(normal, _Socket, _Timeout) ->
- ok;
-post_accept(ssl, Socket, Timeout) ->
- case catch ssl:ssl_accept(Socket, Timeout) of
- ok ->
- ok;
- Error ->
- orber:dbg("[~p] orber_socket:post_accept(ssl, ~p);~n"
- "Failed with reason: ~p",
- [?LINE, Socket, Error], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO})
- end.
-
-
-%%-----------------------------------------------------------------
-%% Close the socket
-%%
-close(normal, Socket) ->
- (catch gen_tcp:close(Socket));
-close(ssl, Socket) ->
- (catch ssl:close(Socket)).
-
-%%-----------------------------------------------------------------
-%% Write to socket
-%%
-write(normal, Socket, Bytes) ->
- gen_tcp:send(Socket, Bytes);
-write(ssl, Socket, Bytes) ->
- ssl:send(Socket, Bytes).
-
-%%-----------------------------------------------------------------
-%% Change the controlling process for the socket
-%%
-controlling_process(normal, Socket, Pid) ->
- gen_tcp:controlling_process(Socket, Pid);
-controlling_process(ssl, Socket, Pid) ->
- ssl:controlling_process(Socket, Pid).
-
-%%-----------------------------------------------------------------
-%% Get peername
-%%
-peername(normal, Socket) ->
- inet:peername(Socket);
-peername(ssl, Socket) ->
- ssl:peername(Socket).
-
-%%-----------------------------------------------------------------
-%% Get peercert
-%%
-peercert(ssl, Socket) ->
- ssl:peercert(Socket);
-peercert(Type, _Socket) ->
- orber:dbg("[~p] orber_socket:peercert(~p);~n"
- "Only available for SSL sockets.",
- [?LINE, Type], ?DEBUG_LEVEL),
- {error, ebadsocket}.
-
-%%-----------------------------------------------------------------
-%% Get peerdata
-%%
-peerdata(normal, Socket) ->
- create_data(inet:peername(Socket));
-peerdata(ssl, Socket) ->
- create_data(ssl:peername(Socket)).
-
-%%-----------------------------------------------------------------
-%% Get sockname
-%%
-sockname(normal, Socket) ->
- inet:sockname(Socket);
-sockname(ssl, Socket) ->
- ssl:sockname(Socket).
-
-%%-----------------------------------------------------------------
-%% Get sockdata
-%%
-sockdata(normal, Socket) ->
- create_data(inet:sockname(Socket));
-sockdata(ssl, Socket) ->
- create_data(ssl:sockname(Socket)).
-
-
-create_data({ok, {Addr, Port}}) ->
- {orber_env:addr2str(Addr), Port};
-create_data(What) ->
- orber:dbg("[~p] orber_socket:peername() or orber_socket:sockname();~n"
- "Failed with reason: ~p", [?LINE, What], ?DEBUG_LEVEL),
- {"Unable to lookup peer- or sockname", 0}.
-
-
-%%-----------------------------------------------------------------
-%% Shutdown Connection
-%% How = read | write | read_write
-shutdown(normal, Socket, How) ->
- gen_tcp:shutdown(Socket, How);
-shutdown(ssl, Socket, How) ->
- Generation = orber_env:ssl_generation(),
- if
- Generation > 2 ->
- ssl:shutdown(Socket, How);
- How == read_write ->
- %% Older versions of SSL do no support shutdown.
- %% For now we'll use this solution instead.
- close(ssl, Socket);
- true ->
- {error, undefined}
- end.
-
-%%-----------------------------------------------------------------
-%% Remove Messages from queue
-%%
-clear(normal, Socket) ->
- tcp_clear(Socket);
-clear(ssl, Socket) ->
- ssl_clear(Socket).
-
-
-
-%% Inet also checks for the following messages:
-%% * {S, {data, Data}}
-%% * {inet_async, S, Ref, Status},
-%% * {inet_reply, S, Status}
-%% SSL doesn't.
-tcp_clear(Socket) ->
- receive
- {tcp, Socket, _Data} ->
- tcp_clear(Socket);
- {tcp_closed, Socket} ->
- tcp_clear(Socket);
- {tcp_error, Socket, _Reason} ->
- tcp_clear(Socket)
- after 0 ->
- ok
- end.
-
-ssl_clear(Socket) ->
- receive
- {ssl, Socket, _Data} ->
- ssl_clear(Socket);
- {ssl_closed, Socket} ->
- ssl_clear(Socket);
- {ssl_error, Socket, _Reason} ->
- ssl_clear(Socket)
- after 0 ->
- ok
- end.
-
-
-
-%%-----------------------------------------------------------------
-%% Check Port. If the user supplies 0 we pick any vacant port. But then
-%% we must change the associated environment variable
-check_port(0, normal, Socket) ->
- case inet:port(Socket) of
- {ok, Port} ->
- orber:configure_override(iiop_port, Port),
- Port;
- What ->
- orber:dbg("[~p] orber_socket:check_port(~p);~n"
- "Unable to extract the port number via inet:port/1~n",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO})
- end;
-check_port(0, ssl, Socket) ->
- case ssl:sockname(Socket) of
- {ok, {_Address, Port}} ->
- orber:configure_override(iiop_ssl_port, Port),
- Port;
- What ->
- orber:dbg("[~p] orber_socket:check_port(~p);~n"
- "Unable to extract the port number via ssl:sockname/1~n",
- [?LINE, What], ?DEBUG_LEVEL),
- corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO})
- end;
-check_port(Port, _, _) ->
- Port.
-
-%%-----------------------------------------------------------------
-%% Check Options.
-check_options(normal, Options, _Generation) ->
- Options;
-check_options(ssl, Options, Generation) ->
- if
- Generation > 2 ->
- [{ssl_imp, new}|Options];
- true ->
- [{ssl_imp, old}|Options]
- end.
-
-
-%%-----------------------------------------------------------------
-%% Check IP Family.
-get_ip_family_opts(Host) ->
- case inet:parse_address(Host) of
- {ok, {_,_,_,_}} ->
- [inet];
- {ok, {_,_,_,_,_,_,_,_}} ->
- [inet6];
- {error, einval} ->
- check_family_for_name(Host, orber_env:ip_version())
- end.
-
-check_family_for_name(Host, inet) ->
- case inet:getaddr(Host, inet) of
- {ok, _Address} ->
- [inet];
- {error, _} ->
- case inet:getaddr(Host, inet6) of
- {ok, _Address} ->
- [inet6];
- {error, _} ->
- [inet]
- end
- end;
-check_family_for_name(Host, inet6) ->
- case inet:getaddr(Host, inet6) of
- {ok, _Address} ->
- [inet6];
- {error, _} ->
- case inet:getaddr(Host, inet) of
- {ok, _Address} ->
- [inet];
- {error, _} ->
- [inet6]
- end
- end.
-
diff --git a/lib/orber/src/orber_tb.erl b/lib/orber/src/orber_tb.erl
deleted file mode 100644
index 6a758330cd..0000000000
--- a/lib/orber/src/orber_tb.erl
+++ /dev/null
@@ -1,222 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File: orber_tb.erl
-%%
-%% Description:
-%% Handling MISC functions.
-%%
-%% Creation date: 040723
-%%
-%%----------------------------------------------------------------------
--module(orber_tb).
-
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
-%% Avoid warning for local function error/2 clashing with autoimported BIF.
--compile({no_auto_import,[error/2]}).
--export([wait_for_tables/1, wait_for_tables/2, wait_for_tables/3,
- is_loaded/0, is_loaded/1, is_running/0, is_running/1,
- info/2, error/2, unique/1, keysearch/2, keysearch/3,
- check_illegal_tcp_options/1]).
-
-%%----------------------------------------------------------------------
-%% Internal exports
-%%----------------------------------------------------------------------
--define(DEBUG_LEVEL, 5).
-
--define(FORMAT(_F, _A), {error, lists:flatten(io_lib:format(_F, _A))}).
--define(EFORMAT(_F, _A), exit(lists:flatten(io_lib:format(_F, _A)))).
-
-%%----------------------------------------------------------------------
-%% Record Definitions
-%%----------------------------------------------------------------------
-
-%%----------------------------------------------------------------------
-%% External functions
-%%----------------------------------------------------------------------
-%%----------------------------------------------------------------------
-%% Function : is_loaded/is_running
-%% Arguments :
-%% Returns :
-%% Raises :
-%% Description:
-%%----------------------------------------------------------------------
-is_loaded() ->
- is_loaded(orber).
-is_loaded(Appl) ->
- find_application(application:loaded_applications(), Appl).
-
-is_running() ->
- is_running(orber).
-is_running(Appl) ->
- find_application(application:which_applications(), Appl).
-
-find_application([], _) ->
- false;
-find_application([{Appl, _, _} |_], Appl) ->
- true;
-find_application([_ |As], Appl) ->
- find_application(As, Appl).
-
-%%----------------------------------------------------------------------
-%% function : keysearch/2/3
-%% Arguments: KeyValue - [{Key, Value}]
-%% Key - term()
-%% Value - term()
-%% Default - term()
-%% Returns : Value | Default
-%% Exception:
-%% Effect :
-%%----------------------------------------------------------------------
-keysearch(Key, KeyValue) ->
- keysearch(Key, KeyValue, undefined).
-keysearch(Key, KeyValue, Default) ->
- case lists:keysearch(Key, 1, KeyValue) of
- {value, {Key, Value}} ->
- Value;
- _ ->
- Default
- end.
-
-%%----------------------------------------------------------------------
-%% function : wait_for_tables/1
-%% Arguments: Tables - list of mnesia tables
-%% Timeout - integer (no point in allowing infinity)
-%% Attempts - integer > 0 How many times should we try
-%% Returns :
-%% Exception:
-%% Effect :
-%%----------------------------------------------------------------------
-wait_for_tables(Tables) ->
- wait_for_tables(Tables, 30000, -1).
-wait_for_tables(Tables, Timeout) ->
- wait_for_tables(Tables, Timeout, -1).
-wait_for_tables(Tables, _Timeout, 0) ->
- error("Mnesia failed to load the some or all of the following"
- "tables:~n~p", [Tables]),
- {error, "The requested Mnesia tables not yet available."};
-wait_for_tables(Tables, Timeout, Attempts) ->
- case mnesia:wait_for_tables(Tables, Timeout) of
- ok ->
- ok;
- {timeout, BadTabList} ->
- info("Mnesia hasn't loaded the following tables (~p msec):~n~p",
- [Timeout, BadTabList]),
- wait_for_tables(BadTabList, Timeout, Attempts-1);
- {error, Reason} ->
- error("Mnesia failed to load the some or all of the following"
- "tables:~n~p", [Tables]),
- {error, Reason}
- end.
-
-%%----------------------------------------------------------------------
-%% function : unique/1
-%% Arguments: List - [term()]
-%% Returns : [term()]
-%% Exception:
-%% Effect : Remove all duplicates from the list.
-%%----------------------------------------------------------------------
-unique([]) -> [];
-unique(List) ->
- Sorted = lists:sort(List),
- unique(hd(Sorted),
- tl(Sorted), []).
-
-unique(A, [A|R], Acc) ->
- unique(A, R, Acc);
-unique(A, [B|R], Acc) ->
- unique(B, R, [A|Acc]);
-unique(A, [], Acc) ->
- lists:reverse([A|Acc]).
-
-
-%%----------------------------------------------------------------------
-%% function : info/2
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%----------------------------------------------------------------------
-info(Format, Args) ->
- catch error_logger:info_msg("=================== Orber =================~n"++
- Format++
- "~n===========================================~n",
- Args).
-
-%%----------------------------------------------------------------------
-%% function : error/2
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%----------------------------------------------------------------------
-error(Format, Args) ->
- catch error_logger:error_msg("=================== Orber =================~n"++
- Format++
- "~n===========================================~n",
- Args).
-
-
-
-
-
-%%----------------------------------------------------------------------
-%% function : check_illegal_tcp_options/1
-%% Arguments:
-%% Returns :
-%% Exception:
-%% Effect :
-%%----------------------------------------------------------------------
-check_illegal_tcp_options(Options) ->
- check_illegal_tcp_options(Options, []).
-
-check_illegal_tcp_options([],[]) ->
- ok;
-check_illegal_tcp_options([],IllegalOpts) ->
- {error, IllegalOpts};
-check_illegal_tcp_options([{active, V} |T], IllegalOpts) ->
- check_illegal_tcp_options(T,[{active, V} |IllegalOpts]);
-check_illegal_tcp_options([{packet, V} |T], IllegalOpts) ->
- check_illegal_tcp_options(T,[{packet, V} |IllegalOpts]);
-check_illegal_tcp_options([{mode, V} |T], IllegalOpts) ->
- check_illegal_tcp_options(T,[{mode, V} |IllegalOpts]);
-check_illegal_tcp_options([list |T], IllegalOpts) ->
- check_illegal_tcp_options(T,[list |IllegalOpts]);
-check_illegal_tcp_options([binary |T], IllegalOpts) ->
- check_illegal_tcp_options(T,[binary |IllegalOpts]);
-check_illegal_tcp_options([{reuseaddr, V} |T], IllegalOpts) ->
- check_illegal_tcp_options(T,[{reuseaddr, V} |IllegalOpts]);
-check_illegal_tcp_options([_H|T], IllegalOpts) ->
- check_illegal_tcp_options(T, IllegalOpts).
-
-%%----------------------------------------------------------------------
-%% Internal functions
-%%----------------------------------------------------------------------
-
-%%----------------------------------------------------------------------
-%%------------- END OF MODULE ------------------------------------------
-%%----------------------------------------------------------------------
diff --git a/lib/orber/src/orber_tc.erl b/lib/orber/src/orber_tc.erl
deleted file mode 100644
index 9a8a9259ed..0000000000
--- a/lib/orber/src/orber_tc.erl
+++ /dev/null
@@ -1,284 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_tc.erl
-%% Description:
-%% This file contains utility functions to create TypeCodes
-%%
-%%-----------------------------------------------------------------
--module(orber_tc).
-
--include_lib("orber/include/ifr_types.hrl").
--include_lib("orber/include/corba.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([null/0, void/0, short/0, unsigned_short/0,
- long/0, longdouble/0, unsigned_long/0, long_long/0,
- unsigned_long_long/0, float/0, double/0,
- boolean/0, char/0, wchar/0, octet/0, any/0,
- typecode/0, principal/0,
- object_reference/2, struct/3,
- union/5, enum/3,
- string/1, wstring/1, sequence/2, array/2, alias/3,
- exception/3, fixed/2, value/5, value_box/3, native/2, abstract_interface/2,
- get_tc/1, check_tc/1]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
--define(DEBUG_LEVEL, 5).
-
-%%-----------------------------------------------------------------
-%% A number of function which can be used to create TypeCodes
-null() ->
- tk_null.
-void() ->
- tk_void.
-short() ->
- tk_short.
-unsigned_short() ->
- tk_ushort.
-long() ->
- tk_long.
-unsigned_long() ->
- tk_ulong.
-long_long() ->
- tk_longlong.
-unsigned_long_long() ->
- tk_ulonglong.
-float() ->
- tk_float.
-double() ->
- tk_double.
-longdouble() ->
- tk_longdouble.
-
-boolean() ->
- tk_boolean.
-char() ->
- tk_char.
-wchar() ->
- tk_wchar.
-octet() ->
- tk_octet.
-any() ->
- tk_any.
-typecode() ->
- tk_TypeCode.
-principal() ->
- tk_Principal.
-
-object_reference(Id, Name) ->
- {tk_objref, Id, Name}.
-
-struct(Id, Name, ElementList) ->
- {tk_struct, Id, Name, ElementList}.
-
-union(Id, Name, DiscrTC, Default, ElementList) ->
- {tk_union, Id, Name, DiscrTC, Default, ElementList}.
-
-enum(Id, Name, ElementList) ->
- {tk_enum, Id, Name, ElementList}.
-
-string(Length) ->
- {tk_string, Length}.
-
-wstring(Length) ->
- {tk_wstring, Length}.
-
-sequence(ElemTC, Length) ->
- {tk_sequence, ElemTC, Length}.
-
-array(ElemTC, Length) ->
- {tk_array, ElemTC, Length}.
-
-alias(Id, Name, TC) ->
- {tk_alias, Id, Name, TC}.
-
-exception(Id, Name, ElementList) ->
- {tk_except, Id, Name, ElementList}.
-
-fixed(Digits, Scale) ->
- {tk_fixed, Digits, Scale}.
-
-value(RepId, Name, ValueModifier, TC, ElementList) ->
- {tk_value, RepId, Name, ValueModifier, TC, ElementList}.
-
-value_box(RepId, Name, TC) ->
- {tk_value_box, RepId, Name, TC}.
-
-native(RepId, Name) ->
- {tk_native, RepId, Name}.
-
-abstract_interface(RepId, Name) ->
- {tk_abstract_interface, RepId, Name}.
-
-
-%%-----------------------------------------------------------------
-%% Get TypeCode (can be used for constructed types like structs,
-%% unions and exceptions)
-%%
-get_tc(T) when is_tuple(T) ->
- Type = element(1, T),
- case catch Type:tc() of
- {'EXIT', R} ->
- orber:dbg("[~p] ~p:get_tc(~p); Exit: ~p",
- [?LINE, ?MODULE, T, R], ?DEBUG_LEVEL),
- corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO});
- X ->
- X
- end;
-%% This call can be used if one have the IFR id and wants a typecode.
-get_tc(IFRId) when is_list(IFRId) ->
- Rep = orber_ifr:find_repository(),
- Def = orber_ifr:lookup_id(Rep, IFRId),
- Descr = orber_ifr:describe(Def),
- TypeDescr = Descr#contained_description.value,
- TypeDescr#typedescription.type.
-
-
-%%-----------------------------------------------------------------
-%% Check TypeCode format
-%%
-check_tc('tk_null') -> true;
-check_tc('tk_void') -> true;
-check_tc('tk_short') -> true;
-check_tc('tk_ushort') -> true;
-check_tc('tk_long') -> true;
-check_tc('tk_ulong') -> true;
-check_tc('tk_longlong') -> true;
-check_tc('tk_ulonglong') -> true;
-check_tc('tk_float') -> true;
-check_tc('tk_double') -> true;
-check_tc('tk_longdouble') -> true;
-check_tc('tk_boolean') -> true;
-check_tc('tk_char') -> true;
-check_tc('tk_wchar') -> true;
-check_tc('tk_octet') -> true;
-check_tc('tk_any') -> true;
-check_tc('tk_TypeCode') -> true;
-check_tc('tk_Principal') -> true;
-check_tc({'tk_objref', RepId, Name}) when is_list(RepId) andalso
- is_list(Name) -> true;
-check_tc({'tk_struct', RepId, Name, ElementList}) when is_list(RepId) andalso
- is_list(Name) ->
- Fun = fun(X) ->
- case X of
- {MemberName, MemberTC} when is_list(MemberName) ->
- check_tc(MemberTC);
- _ ->
- false
- end
- end,
- lists:all(Fun, ElementList);
-check_tc({'tk_union', RepId, Name, DiscrTC,
- Default, ElementList}) when is_list(RepId) andalso
- is_list(Name) andalso
- is_integer(Default) ->
- case check_tc(DiscrTC) of
- false ->
- false;
- true ->
- Fun = fun(X) ->
- case X of
- {_, MemberName, MemberTC} when
- is_list(MemberName) ->
- check_tc(MemberTC);
- _ ->
- false
- end
- end,
- lists:all(Fun, ElementList)
- end;
-check_tc({'tk_enum', RepId, Name, ElementList}) when is_list(RepId) andalso
- is_list(Name) ->
- Fun = fun(X) ->
- if
- is_list(X) ->
- true;
- true ->
- false
- end
- end,
- lists:all(Fun, ElementList);
-check_tc({'tk_string', MaxLength}) when is_integer(MaxLength) -> true;
-check_tc({'tk_wstring', MaxLength}) when is_integer(MaxLength) -> true;
-check_tc({'tk_fixed', Digits, Scale}) when is_integer(Digits) andalso
- is_integer(Scale) -> true;
-check_tc({'tk_sequence', ElemTC, MaxLength}) when is_integer(MaxLength) ->
- check_tc(ElemTC);
-check_tc({'tk_array', ElemTC, Length}) when is_integer(Length) ->
- check_tc(ElemTC);
-check_tc({'tk_alias', RepId, Name, TC}) when is_list(RepId) andalso
- is_list(Name) ->
- check_tc(TC);
-check_tc({'tk_except', RepId, Name, ElementList}) when is_list(RepId) andalso
- is_list(Name) ->
- Fun = fun(X) ->
- case X of
- {MemberName, TC} when is_list(MemberName) ->
- check_tc(TC);
- _ ->
- false
- end
- end,
- lists:all(Fun, ElementList);
-check_tc({'tk_value', RepId, Name, ValueModifier,
- TC, ElementList}) when is_list(RepId) andalso
- is_list(Name) andalso
- is_integer(ValueModifier) ->
- case check_tc(TC) of
- false ->
- false;
- true ->
- Fun = fun(X) ->
- case X of
- {MemberName, MemberTC, Visibility} when
- is_list(MemberName) andalso is_integer(Visibility) ->
- check_tc(MemberTC);
- _ ->
- false
- end
- end,
- lists:all(Fun, ElementList)
- end;
-check_tc({'tk_value_box', RepId, Name, TC}) when is_list(RepId) andalso
- is_list(Name) ->
- check_tc(TC);
-check_tc({'tk_native', RepId, Name}) when is_list(RepId) andalso
- is_list(Name) -> true;
-check_tc({'tk_abstract_interface', RepId, Name}) when is_list(RepId) andalso
- is_list(Name) -> true;
-check_tc({'none', Indirection}) when is_integer(Indirection) -> true;
-check_tc(_) -> false.
-
diff --git a/lib/orber/src/orber_typedefs.erl b/lib/orber/src/orber_typedefs.erl
deleted file mode 100644
index 30c03974c2..0000000000
--- a/lib/orber/src/orber_typedefs.erl
+++ /dev/null
@@ -1,83 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File: orber_typedefs.erl
-%% Description:
-%% This file contains some functions for internal typedef checking
-%%
-%%-----------------------------------------------------------------
--module(orber_typedefs).
-
--include("orber_iiop.hrl").
--include_lib("orber/include/corba.hrl").
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([get_op_def/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
--define(DEBUG_LEVEL, 5).
-
-%%-----------------------------------------------------------------
-%% External interface functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% Func: get_op_def/2
-%%
-get_op_def(_Objkey, '_is_a') ->
- {orber_tc:boolean(),[orber_tc:string(0)],[]};
-%% First the OMG specified this operation to be '_not_existent' and then
-%% changed it to '_non_existent' without suggesting that both must be supported.
-%% See CORBA2.3.1 page 15-34, Minor revision 2.3.1: October 1999
-get_op_def(_Objkey, '_not_existent') ->
- {orber_tc:boolean(),[],[]};
-get_op_def(_Objkey, '_non_existent') ->
- {orber_tc:boolean(),[],[]};
-%% Defined in the Fault Tolerant section of the CORBA specification.
-get_op_def(_Objkey, '_FT_HB') ->
- {orber_tc:void(),[],[]};
-get_op_def(Objkey, Op) ->
- case catch iop_ior:get_key(Objkey) of
- {_Local, _Key, _, _, Module} ->
- case catch Module:oe_tc(Op) of
- {'EXIT', What} ->
- orber:dbg("[~p] orber_typedefs:get_op_def(~p);~n"
- "The call-back module does not exist or incorrect~n"
- "IC-version used. Reason:~n~p",
- [?LINE, Module, What], ?DEBUG_LEVEL),
- corba:raise(#'TRANSIENT'{minor=(?ORBER_VMCID bor 7),
- completion_status=?COMPLETED_NO});
- undefined ->
- corba:raise(#'BAD_OPERATION'{minor = (?ORBER_VMCID bor 4),
- completion_status=?COMPLETED_NO});
- TC ->
- TC
- end;
- _ ->
- corba:raise(#'INV_OBJREF'{completion_status=?COMPLETED_NO})
- end.
-
diff --git a/lib/orber/src/orber_web.erl b/lib/orber/src/orber_web.erl
deleted file mode 100644
index cc24b2cb19..0000000000
--- a/lib/orber/src/orber_web.erl
+++ /dev/null
@@ -1,864 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_web.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module(orber_web).
-
--export([menu/2,
- configure/2,
- info/2,
- nameservice/2,
- ifr_select/2,
- ifr_data/2,
- create/2,
- delete_ctx/2,
- add_ctx/2,
- delete_obj/2]).
-
-%%----------------------------------------------------------------------
-%%-------------- Defines & Includes ------------------------------------
-%%----------------------------------------------------------------------
-
--include("ifr_objects.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming_NamingContext.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
--define(DEBUG_LEVEL, 5).
-
--define(INFO_DATA,
- [{iiop_timeout, "IIOP Request Timeout"},
- {iiop_connection_timeout, "IIOP Connection Timeout"},
- {iiop_setup_connection_timeout, "IIOP Setup Connection Timeout"},
- {iiop_port, "IIOP Port"},
- {domain, "Orber Domain"},
- {orber_nodes, "Nodes in Domain"},
- {giop_version, "Default GIOP Version"},
- {objectkeys_gc_time, "Objectkeys GC"},
- {get_interceptors, "Using Interceptors"},
- {get_debug_level, "Debug Level"},
- {get_ORBInitRef, "ORBInitRef"},
- {get_ORBDefaultInitRef, "ORBDefaultInitRef"}]).
-
--define(IFR_DATA, [{"ir_ModuleDef", "Modules"},
- {"ir_InterfaceDef", "Interfaces"},
- {"ir_StructDef", "Structs"},
- {"ir_UnionDef", "Unions"},
- {"ir_ExceptionDef", "Exceptions"},
- {"ir_ConstantDef", "Constants"},
- {"ir_EnumDef", "Enumerants"},
- {"ir_AliasDef", "Aliases"},
- {"ir_AttributeDef", "Attributes"},
- {"ir_OperationDef", "Operations"},
- {"ir_Contained", "Contained"},
- {"ir_TypedefDef", "Typedef"}]).
-
-
-%%----------------------------------------------------------------------
-%%-------------- External API ------------------------------------------
-%%----------------------------------------------------------------------
-%% Function : create
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-create(_Env, [{"node",NodeStr}]) ->
- Node = list_to_atom(NodeStr),
- is_running(Node, NodeStr),
- ["<BODY BGCOLOR=\"#FFFFFF\">
- <TABLE border=0 BGCOLOR=\"#FFFFFF\">
- <TD ALIGN=\"center\" COLSPAN=2><FONT SIZE=6>Create a New Object</FONT></TD></TR>
- <TR><TD><FORM METHOD=\"POST\" ACTION=\"./create\">
- <TR><TD><INPUT TYPE=\"HIDDEN\" NAME=\"node\" VALUE=\"", NodeStr, "\">
- <TR><TD><B>Module</B></TD><TD><INPUT TYPE=\"TEXT\" SIZE=\"50\" NAME=\"module\" VALUE=\"\"></TD></TR>
- <TR><TD><B>Arguments</B></TD><TD><INPUT TYPE=\"TEXT\" SIZE=\"50\" NAME=\"arguments\"></TD></TR>
- <TR><TD><B>Options</B></TD><TD><INPUT TYPE=\"TEXT\" SIZE=\"50\" NAME=\"options\"></TD></TR>
- <TR><TD><B>Name String</B></TD><TD><INPUT TYPE=\"TEXT\" SIZE=\"50\" NAME=\"namestr\"></TD></TR>
- <TR><TD><B>Operation to use</B></TD>
- <TD><B>&nbsp;&nbsp;&nbsp;<INPUT type=\"radio\" name=\"bind\" value=\"bind\" CHECKED=\"true\">Bind</B>
- <B>&nbsp;&nbsp;&nbsp;<INPUT type=\"radio\" name=\"bind\" value=\"rebind\">Rebind</B></TD></TR>
- <TR><TD ALIGN=\"center\" COLSPAN=2><INPUT TYPE=\"SUBMIT\" VALUE=\"Create it\"></FORM></TD></TR></TABLE>"];
-create(_Env, [{"node",NodeStr}, {"module", ModStr}, {"arguments",ArgsStr},
- {"options",OptionsStr}, {"namestr", Name}, {"bind", How}]) ->
- Node = list_to_atom(NodeStr),
- Mod = list_to_atom(ModStr),
- Args = parse_data(ArgsStr),
- Options = parse_data(OptionsStr),
- case catch rpc:call(Node, Mod, oe_create, [Args, [{sup_child, true}|Options]]) of
- {ok, Pid, Object} ->
- case catch bind(Node, Object, Name, How) of
- {ok, IOR} ->
- ["<BODY BGCOLOR=\"#FFFFFF\"><BR><B>Successfully created the object:</B><BR><BR>", IOR];
- {ok, IOR, Path} ->
- ["<BODY BGCOLOR=\"#FFFFFF\"><BR><B>Successfully created and stored the object as: \"",
- Path, "\" (", pid_to_list(Pid), ")</B><BR><BR>", IOR];
- What ->
- rpc:call(Node, corba, dispose, [Object]),
- orber:dbg("[~p] orber_web:create(~p, ~p, ~p, ~p, ~p);
-Unable to bind object: ~p", [?LINE, Node, Mod, Args, Options, Name, What], ?DEBUG_LEVEL),
- ["<BODY BGCOLOR=\"#FFFFFF\">Unable to bind object in the NameService using: ", Name]
- end;
- Object when element(2, Object) == pseudo ->
- case catch bind(Node, Object, Name, How) of
- {ok, IOR} ->
- ["<BODY BGCOLOR=\"#FFFFFF\"><BR><B>Successfully created the object:</B><BR><BR>", IOR];
- {ok, IOR, _} ->
- ["<BODY BGCOLOR=\"#FFFFFF\"><BR><B>Successfully created and stored the object as :\"", Name, "\"</B><BR><BR>", IOR];
- What ->
- rpc:call(Node, corba, dispose, [Object]),
- orber:dbg("[~p] orber_web:create(~p, ~p, ~p, ~p, ~p);
-Unable to bind object: ~p", [?LINE, Node, Mod, Args, Options, Name, What], ?DEBUG_LEVEL),
- ["<BODY BGCOLOR=\"#FFFFFF\">Unable to bind object in the NameService using: ", Name]
- end;
- What->
- orber:dbg("[~p] orber_web:create(~p, ~p, ~p, ~p, ~p);
-Unable to create object: ~p", [?LINE, Node, Mod, Args, Options, Name, What], ?DEBUG_LEVEL),
- ["<BODY BGCOLOR=\"#FFFFFF\">Unable to create the object."]
- end.
-
-bind(Node, Obj, "", _) ->
- IOR = rpc:call(Node, corba, object_to_string, [Obj]),
- {ok, IOR};
-bind(Node, Obj, NameStr, How) ->
- NS = check(rpc:call(Node, corba, resolve_initial_references, ["NameService"])),
- Name = check(rpc:call(Node, 'CosNaming_NamingContextExt', to_name, [NS, NameStr])),
- case How of
- "bind" ->
- check(rpc:call(Node, 'CosNaming_NamingContext', bind, [NS, Name, Obj])),
- IOR = rpc:call(Node, corba, object_to_string, [Obj]),
- {ok, IOR, NameStr};
- "rebind" ->
- check(rpc:call(Node, 'CosNaming_NamingContext', rebind, [NS, Name, Obj])),
- IOR = rpc:call(Node, corba, object_to_string, [Obj]),
- {ok, IOR, NameStr}
- end.
-
-
-%%----------------------------------------------------------------------
-%% Function : delete_ctx
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-delete_ctx(_Env, [{"node",NodeStr}, {"context", Ref}]) ->
- Node = list_to_atom(NodeStr),
- {Ctx, NS} = remote_resolve(Node, Ref),
- Name = check(rpc:call(Node, 'CosNaming_NamingContextExt', to_name, [NS, Ref])),
- check(rpc:call(Node, 'CosNaming_NamingContextExt', unbind, [NS, Name])),
- check(rpc:call(Node, 'CosNaming_NamingContextExt', destroy, [Ctx])),
- ["<BODY BGCOLOR=\"#FFFFFF\">
- <TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=1>
- <FONT SIZE=6>Successfully deleted the Context: ", Ref, "</FONT>\n
- </TD></TR></TABLE>
- <FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-2) VALUE=\"Go Back\">\n</FORM>"].
-
-%%----------------------------------------------------------------------
-%% Function : add_ctx
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-add_ctx(_Env, [{"node",_NodeStr}, {"context", "root"}, {"id", ""}]) ->
- ["<BODY BGCOLOR=\"#FFFFFF\">
- <TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=1>
- <FONT SIZE=4>You must supply a NameString such as:<BR>
- See also 'Interoperable Naming Service' in the User's Guide.</FONT>\n
- </TD></TR></TABLE>
- <FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-1) VALUE=\"Go Back\">\n</FORM>"];
-add_ctx(_Env, [{"node",NodeStr}, {"context", "root"}, {"id", Id}]) ->
- Node = list_to_atom(NodeStr),
- NS = check(rpc:call(Node, corba, resolve_initial_references, ["NameService"])),
- Name = check(rpc:call(Node, 'CosNaming_NamingContextExt', to_name, [NS, Id])),
- check(rpc:call(Node, 'CosNaming_NamingContextExt', bind_new_context, [NS, Name])),
- ["<BODY BGCOLOR=\"#FFFFFF\">
- <TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=1>
- <FONT SIZE=6>Successfully bound the new Context: ", Id, "</FONT>\n
- </TD></TR></TABLE>
- <FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-1) VALUE=\"Go Back\">\n</FORM>"];
-add_ctx(_Env, [{"node",NodeStr}, {"context", Ref}, {"id", Id}]) ->
- NameStr = Ref ++ "/" ++ Id,
- Node = list_to_atom(NodeStr),
- NS = check(rpc:call(Node, corba, resolve_initial_references, ["NameService"])),
- Name = check(rpc:call(Node, 'CosNaming_NamingContextExt', to_name, [NS, NameStr])),
- check(rpc:call(Node, 'CosNaming_NamingContextExt', bind_new_context, [NS, Name])),
- ["<BODY BGCOLOR=\"#FFFFFF\">
- <TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=1>
- <FONT SIZE=6>Successfully bound the new Context: ", NameStr, "</FONT>\n
- </TD></TR></TABLE>
- <FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-1) VALUE=\"Go Back\">\n</FORM>"].
-
-%%----------------------------------------------------------------------
-%% Function : delete_obj
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-delete_obj(_Env, [{"node",NodeStr}, {"context", Ref}, {"action", "unbind"}]) ->
- Node = list_to_atom(NodeStr),
- NS = check(rpc:call(Node, corba, resolve_initial_references, ["NameService"])),
- Name = check(rpc:call(Node, 'CosNaming_NamingContextExt', to_name, [NS, Ref])),
- check(rpc:call(Node, 'CosNaming_NamingContextExt', unbind, [NS, Name])),
- ["<BODY BGCOLOR=\"#FFFFFF\">
- <TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=1>
- <FONT SIZE=6>Successfully unbound the Object: ", Ref, "</FONT>\n
- </TD></TR></TABLE>
- <FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-2) VALUE=\"Go Back\">\n</FORM>"];
-delete_obj(_Env, [{"node",NodeStr}, {"context", Ref}, {"action", "both"}]) ->
- Node = list_to_atom(NodeStr),
- {Obj, NS} = remote_resolve(Node, Ref),
- check(rpc:call(Node, corba, dispose, [Obj])),
- Name = check(rpc:call(Node, 'CosNaming_NamingContextExt', to_name, [NS, Ref])),
- check(rpc:call(Node, 'CosNaming_NamingContextExt', unbind, [NS, Name])),
- ["<BODY BGCOLOR=\"#FFFFFF\">
- <TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=1>
- <FONT SIZE=6>Successfully disposed an unbound the Object: ", Ref, "</FONT>\n
- </TD></TR></TABLE>
- <FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-2) VALUE=\"Go Back\">\n</FORM>"].
-
-
-
-%%----------------------------------------------------------------------
-%% Function : nameservice
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-nameservice(_Env, [{"node",NodeStr}, {"context", "root"}]) ->
- Node = list_to_atom(NodeStr),
- is_running(Node, NodeStr),
- Object = check(rpc:call(Node, corba, resolve_initial_references, ["NameService"])),
- Prefix = "<TR><TD><A HREF=\"./nameservice?node=" ++ NodeStr ++ "&context=",
- case catch create_context_list(Node, NodeStr, Prefix, Object, "root") of
- {ok, Data} ->
- ["<BODY BGCOLOR=\"#FFFFFF\">
- <TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=2>
- <FONT SIZE=6>NameService</FONT>\n
- </TD></TR><TR BGCOLOR=\"#FFFF00\"><TD ALIGN=\"center\" COLSPAN=2>
- <FONT SIZE=4>Root Context</FONT>\n
- </TD></TR>", Data,
- "<TR><TD><FORM Name=addctx METHOD=\"POST\" ACTION=\"./add_ctx\">
- <INPUT TYPE=\"HIDDEN\" NAME=\"node\" VALUE=\"", NodeStr, "\">
- <INPUT TYPE=\"HIDDEN\" NAME=\"context\" VALUE=\"root\">
- <INPUT TYPE=\"TEXT\" SIZE=\"20\" NAME=\"id\"></TD>
- <TD><INPUT TYPE=\"SUBMIT\" VALUE=\"New Context\"></TD></FORM></TR></TABLE>"];
- Why ->
- orber:dbg("[~p] orber_web:nameservice(~p, root);
-Unable to create context list: ~p", [?LINE, NodeStr, Why], ?DEBUG_LEVEL),
- throw({error, "<BODY BGCOLOR=\"#FFFFFF\">Unable to create a look up the Root Context data"})
- end;
-nameservice(_Env, [{"node",NodeStr}, {"context", Ref}]) ->
- Node = list_to_atom(NodeStr),
- {Object, _NS} = remote_resolve(Node, Ref),
- Prefix = "<TR><TD><A HREF=\"./nameservice?node=" ++ NodeStr ++ "&context="++Ref++"/",
- case catch create_context_list(Node, NodeStr, Prefix, Object, Ref) of
- {ok, Data} ->
- ["<BODY BGCOLOR=\"#FFFFFF\">
- <TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=2>
- <FONT SIZE=6>NameService</FONT></TD></TR>
- <TR BGCOLOR=\"#FFFF00\"><TD ALIGN=\"center\" COLSPAN=2>
- <FONT SIZE=4>", Ref, "</FONT></TD></TR>", Data,
- "<TR><TD><FORM Name=addctx METHOD=\"POST\" ACTION=\"./add_ctx\">
- <INPUT TYPE=\"HIDDEN\" NAME=\"node\" VALUE=\"", NodeStr, "\">
- <INPUT TYPE=\"HIDDEN\" NAME=\"context\" VALUE=\"", Ref, "\">
- <INPUT TYPE=\"TEXT\" SIZE=\"20\" NAME=\"id\"></TD>
- <TD><INPUT TYPE=\"SUBMIT\" VALUE=\"New Context\"></TD></FORM></TR>
- </TABLE>
- <FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-1) VALUE=\"Go Back\"></FORM></TD>"];
- Why ->
- orber:dbg("[~p] orber_web:nameservice(~p, ~p);
-Unable to create context list: ~p", [?LINE, NodeStr, Ref, Why], ?DEBUG_LEVEL),
- throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Unable to look up the Context: ", Ref,
- "<BR><BR>If You just deleted it, use the 'Go Back' button next time."]})
- end;
-nameservice(_Env, [{"node",NodeStr}, {"context", Ref}, {"object", Obj}]) ->
- case catch create_object_data(NodeStr, Ref, Obj) of
- {ok, Data} ->
- Data;
- Why ->
- orber:dbg("[~p] orber_web:nameservice(~p, ~p, ~p);
-Unable to create data for object: ~p", [?LINE, NodeStr, Ref, Obj, Why], ?DEBUG_LEVEL),
- throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Unable to look up the Object stored as: ", Ref,
- "<BR><BR>If You just unbound it, use the 'Go Back' button next time."]})
- end.
-
-create_context_list(Node, NodeStr, Prefix, Object, Ref) ->
- case check(rpc:call(Node, 'CosNaming_NamingContext', list, [Object, 100])) of
- {ok, [], BI} when Ref == "root" ->
- catch rpc:call(Node, 'CosNaming_BindingIterator', destroy, [BI]),
- {ok, "<TR><TD ALIGN=\"center\" COLSPAN=2><FONT SIZE=3><B>EMPTY<B></FONT></TD></TR>"};
- {ok, [], BI} ->
- catch rpc:call(Node, 'CosNaming_BindingIterator', destroy, [BI]),
- {ok, "<TR><TD ALIGN=\"center\"><FONT SIZE=3><B>EMPTY<B></FONT></TD>
- <TD ALIGN=\"center\"><FORM Name=deletectx METHOD=\"POST\" ACTION=\"./delete_ctx\">
- <INPUT TYPE=\"HIDDEN\" NAME=\"node\" VALUE=\"" ++ NodeStr ++ "\">
- <INPUT TYPE=\"HIDDEN\" NAME=\"context\" VALUE=\"" ++ Ref ++ "\">
- <INPUT TYPE=\"SUBMIT\" VALUE=\"Delete Context\"></FORM></TD></TR>"};
- {ok, BL, BI} when length(BL) < 100 ->
- catch rpc:call(Node, 'CosNaming_BindingIterator', destroy, [BI]),
- {ok, convert_contexts(BL, [], Prefix, Object, Node)};
- {ok, BL, BI} ->
- Data = convert_contexts(BL, [], Prefix, Object, Node),
- {ok, create_context_list_helper(Node, BI, Data, Object, Prefix)}
- end.
-
-create_context_list_helper(Node, BI, Acc, Ctx, Prefix) ->
- case check(rpc:call(Node, 'CosNaming_BindingIterator', next_n, [BI, 100])) of
- {true, BL} ->
- NewAcc = convert_contexts(BL, Acc, Prefix, Ctx, Node),
- create_context_list_helper(Node, BI, NewAcc, Ctx, Prefix);
- {false, BL} ->
- catch rpc:call(Node, 'CosNaming_BindingIterator', destroy, [BI]),
- convert_contexts(BL, Acc, Prefix, Ctx, Node)
- end.
-
-convert_contexts([], Acc, _Prefix, _Ctx, _Node) ->
- Acc;
-convert_contexts([#'CosNaming_Binding'{binding_name = Name,
- binding_type = ncontext}|T],
- Acc, Prefix, Ctx, Node) ->
- NameStr = check(rpc:call(Node, 'CosNaming_NamingContextExt', to_string, [Ctx, Name])),
- convert_contexts(T, [Prefix, NameStr, "\" TARGET=main><B>", NameStr, "</B></A></TD><TD><B>ncontext</B></TD></TR>"|Acc],
- Prefix, Ctx, Node);
-convert_contexts([#'CosNaming_Binding'{binding_name = Name,
- binding_type = nobject}|T],
- Acc, Prefix, Ctx, Node) ->
- NameStr = check(rpc:call(Node, 'CosNaming_NamingContextExt', to_string, [Ctx, Name])),
- convert_contexts(T, [Prefix, NameStr, "&object=o \" TARGET=main><B>", NameStr, "</B></A></TD><TD><B>nobject</B></A></TD></TR>"|Acc],
- Prefix, Ctx, Node).
-
-
-create_object_data(NodeStr, Ref, _Obj) ->
- Node = list_to_atom(NodeStr),
- {Object, _NS} = remote_resolve(Node, Ref),
- LongIORStr = check(rpc:call(Node, corba, object_to_string, [Object])),
- IFRId = check(rpc:call(Node, iop_ior, get_typeID, [Object])),
- Exists = check(rpc:call(Node, corba_object, non_existent, [Object])),
- IORStr = split_IOR(1, LongIORStr, []),
- {Data, External}
- = case rpc:call(Node, iop_ior, get_key, [Object]) of
- {external, {Host, Port, _OK, _, _, #host_data{version = {Ma, Mi}}}} ->
- {[{"IFR Id", IFRId},
- {"Stored As", Ref},
- {"External Object", "true"},
- {"Non Existent", atom_to_list(Exists)},
- {"Host", Host},
- {"Port", integer_to_list(Port)},
- {"IIOP Version", integer_to_list(Ma) ++"."++ integer_to_list(Mi)},
- {"IOR String", IORStr}], true};
- {'internal', _Key, _, _, _} ->
- Pid = check(rpc:call(Node, corba, get_pid, [Object])),
- Interface = check(rpc:call(Node, corba, request_from_iiop,
- [Object, oe_get_interface, false, false, false, []])),
- InterfaceData = parse_interface(Interface, []),
- {[{"IFR Id", IFRId},
- {"Stored As", Ref},
- {"External Object", "false"},
- {"Non Existent", atom_to_list(Exists)},
- {"Pid", pid_to_list(Pid)},
- {"IOR String", IORStr}|InterfaceData], false};
- {'internal_registered', {pseudo, Key}, _, _, _} ->
- Interface = check(rpc:call(Node, corba, request_from_iiop,
- [Object, oe_get_interface, false, false, false, []])),
- InterfaceData = parse_interface(Interface, []),
- {[{"IFR Id", IFRId},
- {"Stored As", Ref},
- {"External Object", "false"},
- {"Non Existent", atom_to_list(Exists)},
- {"Pseudo Object", atom_to_list(Key)},
- {"IOR", IORStr}|InterfaceData], false};
- {'internal_registered', Key, _, _, _} ->
- Pid = check(rpc:call(Node, corba, get_pid, [Object])),
- Interface = check(rpc:call(Node, corba, request_from_iiop,
- [Object, oe_get_interface, false, false, false, []])),
- InterfaceData = parse_interface(Interface, []),
- {[{"IFR Id", IFRId},
- {"Stored As", Ref},
- {"External Object", "false"},
- {"Non Existent", atom_to_list(Exists)},
- {"Locally Registered", atom_to_list(Key)},
- {"Pid", pid_to_list(Pid)},
- {"IOR String", IORStr}|InterfaceData], false}
- end,
- Buttons = case {Exists, External} of
- {false, false} ->
- ["<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\">
- <TD><FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-1) VALUE=\"Go Back\"></FORM></TD>
-
- <TD ALIGN=\"center\"><FORM Name=unbindobj METHOD=\"POST\" ACTION=\"./delete_obj\">
- <INPUT TYPE=\"HIDDEN\" NAME=\"node\" VALUE=\"", NodeStr, "\">
- <INPUT TYPE=\"HIDDEN\" NAME=\"context\" VALUE=\"", Ref, "\">
- <INPUT TYPE=\"HIDDEN\" NAME=\"action\" VALUE=\"unbind\">
- <INPUT TYPE=\"SUBMIT\" VALUE=\"Unbind\"></FORM></TD>
- <TD ALIGN=\"center\"><FORM Name=unbinddeletobj METHOD=\"POST\" ACTION=\"./delete_obj\">
- <INPUT TYPE=\"HIDDEN\" NAME=\"node\" VALUE=\"", NodeStr, "\">
- <INPUT TYPE=\"HIDDEN\" NAME=\"context\" VALUE=\"", Ref, "\">
- <INPUT TYPE=\"HIDDEN\" NAME=\"action\" VALUE=\"both\">
- <INPUT TYPE=\"SUBMIT\" VALUE=\"Unbind & Dispose\"></FORM></TD></TR></TABLE>"];
- _ ->
- ["<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\">
- <TD><FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-1) VALUE=\"Go Back\"></FORM></TD>
- <TD ALIGN=\"center\"><FORM Name=unbindobj METHOD=\"POST\" ACTION=\"./delete_obj\">
- <INPUT TYPE=\"HIDDEN\" NAME=\"node\" VALUE=\"", NodeStr, "\">
- <INPUT TYPE=\"HIDDEN\" NAME=\"context\" VALUE=\"", Ref, "\">
- <INPUT TYPE=\"HIDDEN\" NAME=\"action\" VALUE=\"unbind\">
- <INPUT TYPE=\"SUBMIT\" VALUE=\"Unbind\"></FORM></TD></TR></TABLE>"]
- end,
- {ok, ["<BODY BGCOLOR=\"#FFFFFF\">",
- simple_table("2", "NameService", [{"Key", "Value"}|Data]),
- Buttons]}.
-
-parse_interface([], [{_, Op}|Acc]) ->
- [{"Operations", Op}|Acc];
-parse_interface([], []) ->
- [{"Operations", "-"}];
-parse_interface([{Operation,{_,Args,_}}|T], Acc) ->
- parse_interface(T, [{"", Operation ++ "/" ++ integer_to_list(length(Args))}|Acc]).
-
-
-split_IOR(_, [], Acc) ->
- lists:reverse(Acc);
-split_IOR(50, Str, Acc) ->
- split_IOR(1, Str, ["<BR>"|Acc]);
-split_IOR(N, [H|T], Acc) ->
- split_IOR(N+1, T, [H|Acc]).
-
-
-
-%%----------------------------------------------------------------------
-%% Function : configure
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-configure(_Env, [{"node",NodeStr}, {"data", DataStr}]) ->
- Node = list_to_atom(NodeStr),
- Data = parse_data(DataStr),
- case catch rpc:call(Node, orber, multi_configure, [Data]) of
- ok ->
- "<BODY BGCOLOR=\"#FFFFFF\">Configuration successfull.";
- Why ->
- orber:dbg("[~p] orber_web:configure(~p, ~p);
-Unable to change configuration due to: ~p", [?LINE, NodeStr, DataStr, Why], ?DEBUG_LEVEL),
- "<BODY BGCOLOR=\"#FFFFFF\">Unable to change the configuration.<BR>
- Check the spelling and/or if it is possible to update all the keys if Orber is started."
- end.
-
-
-%%----------------------------------------------------------------------
-%% Function : ifr_select
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-ifr_select(_Env, [{"node",NodeStr}]) ->
- Node = list_to_atom(NodeStr),
- is_running(Node, NodeStr),
- ["<BODY BGCOLOR=\"#FFFFFF\">
- <TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=1>
- <FONT SIZE=6>Interface Repository</FONT>
- </TD></TR>", create_ifr_table(?IFR_DATA, NodeStr, []), "</TABLE>"].
-
-%%----------------------------------------------------------------------
-%% Function : ifr_data
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-ifr_data(_Env, [{"node",NodeStr}, {"table", TableStr}]) ->
- Node = list_to_atom(NodeStr),
- Table = list_to_atom(TableStr),
- WildPattern = get_wild_pattern(Table, Node),
- Records = check(rpc:call(Node, mnesia, dirty_match_object, [WildPattern])),
- Data = extract_ids(Records, []),
- ["<BODY BGCOLOR=\"#FFFFFF\">",
- simple_table("1", "Interface Repository", [TableStr|Data]),
- "<FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-1) VALUE=\"Go Back\"></FORM>"].
-
-extract_ids([], Acc) ->
- lists:sort(Acc);
-extract_ids([#ir_ModuleDef{id=Id}|T], Acc) ->
- extract_ids(T, [Id|Acc]);
-extract_ids([#ir_InterfaceDef{id=Id}|T], Acc) ->
- extract_ids(T, [Id|Acc]);
-extract_ids([#ir_StructDef{id=Id}|T], Acc) ->
- extract_ids(T, [Id|Acc]);
-extract_ids([#ir_UnionDef{id=Id}|T], Acc) ->
- extract_ids(T, [Id|Acc]);
-extract_ids([#ir_ExceptionDef{id=Id}|T], Acc) ->
- extract_ids(T, [Id|Acc]);
-extract_ids([#ir_ConstantDef{id=Id}|T], Acc) ->
- extract_ids(T, [Id|Acc]);
-extract_ids([#ir_EnumDef{id=Id}|T], Acc) ->
- extract_ids(T, [Id|Acc]);
-extract_ids([#ir_AliasDef{id=Id}|T], Acc) ->
- extract_ids(T, [Id|Acc]);
-extract_ids([#ir_AttributeDef{id=Id}|T], Acc) ->
- extract_ids(T, [Id|Acc]);
-extract_ids([#ir_OperationDef{id=Id}|T], Acc) ->
- extract_ids(T, [Id|Acc]);
-extract_ids([#ir_Contained{id=Id}|T], Acc) ->
- extract_ids(T, [Id|Acc]);
-extract_ids([#ir_TypedefDef{id=Id}|T], Acc) ->
- extract_ids(T, [Id|Acc]).
-
-get_wild_pattern(ir_ModuleDef, Node) ->
- P = check(rpc:call(Node, mnesia, table_info, [ir_ModuleDef, wild_pattern])),
- P#ir_ModuleDef{id='$1'};
-get_wild_pattern(ir_InterfaceDef, Node) ->
- P = check(rpc:call(Node, mnesia, table_info, [ir_InterfaceDef, wild_pattern])),
- P#ir_InterfaceDef{id='$1'};
-get_wild_pattern(ir_StructDef, Node) ->
- P = check(rpc:call(Node, mnesia, table_info, [ir_StructDef, wild_pattern])),
- P#ir_StructDef{id='$1'};
-get_wild_pattern(ir_UnionDef, Node) ->
- P = check(rpc:call(Node, mnesia, table_info, [ir_UnionDef, wild_pattern])),
- P#ir_UnionDef{id='$1'};
-get_wild_pattern(ir_ExceptionDef, Node) ->
- P = check(rpc:call(Node, mnesia, table_info, [ir_ExceptionDef, wild_pattern])),
- P#ir_ExceptionDef{id='$1'};
-get_wild_pattern(ir_ConstantDef, Node) ->
- P = check(rpc:call(Node, mnesia, table_info, [ir_ConstantDef, wild_pattern])),
- P#ir_ConstantDef{id='$1'};
-get_wild_pattern(ir_EnumDef, Node) ->
- P = check(rpc:call(Node, mnesia, table_info, [ir_EnumDef, wild_pattern])),
- P#ir_EnumDef{id='$1'};
-get_wild_pattern(ir_AliasDef, Node) ->
- P = check(rpc:call(Node, mnesia, table_info, [ir_AliasDef, wild_pattern])),
- P#ir_AliasDef{id='$1'};
-get_wild_pattern(ir_AttributeDef, Node) ->
- P = check(rpc:call(Node, mnesia, table_info, [ir_AttributeDef, wild_pattern])),
- P#ir_AttributeDef{id='$1'};
-get_wild_pattern(ir_OperationDef, Node) ->
- P = check(rpc:call(Node, mnesia, table_info, [ir_OperationDef, wild_pattern])),
- P#ir_OperationDef{id='$1'};
-get_wild_pattern(ir_Contained, Node) ->
- P = check(rpc:call(Node, mnesia, table_info, [ir_Contained, wild_pattern])),
- P#ir_Contained{id='$1'};
-get_wild_pattern(ir_TypedefDef, Node) ->
- P = check(rpc:call(Node, mnesia, table_info, [ir_TypedefDef, wild_pattern])),
- P#ir_TypedefDef{id='$1'}.
-
-create_ifr_table([], _Node, Result) ->
- lists:append(lists:reverse(Result));
-create_ifr_table([{Table,Desc}|Rest], Node, Result) ->
- create_ifr_table(Rest, Node,
- ["<TR><TD><A HREF=\"./ifr_data?node=" ++ Node ++
- "&table="++Table++"\" TARGET=main><B>" ++ Desc ++"</B></A></TD></TR>"|Result]).
-
-
-%%----------------------------------------------------------------------
-%% Function : info
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-info(_Env, [{"node",NodeStr}]) ->
- Node = list_to_atom(NodeStr),
- is_running(Node, NodeStr),
- Data = create_info_data(?INFO_DATA, Node, []),
- ["<BODY BGCOLOR=\"#FFFFFF\">",
- simple_table("2", "Configuration", [{"Key", "Value"}|Data],
- ["<TR><TD><FORM METHOD=\"POST\" ACTION=\"./configure\">
- <INPUT TYPE=\"HIDDEN\" NAME=\"node\" VALUE=\"", NodeStr, "\">
- <INPUT TYPE=\"TEXT\" SIZE=\"35\" NAME=\"data\" VALUE=\"[{Key, Value}]\">
- </TD><TD><INPUT TYPE=\"SUBMIT\" VALUE=\"Change it\"></TD></FORM></TR>"])].
-
-
-create_info_data([], _Node, Result) ->
- lists:reverse(Result);
-create_info_data([{Func,Desc}|Rest], Node, Result) ->
- Data = convert_type(check(rpc:call(Node, orber, Func, []))),
- create_info_data(Rest, Node, [{Desc, Data}|Result]).
-
-convert_type(Data) when is_integer(Data) ->
- integer_to_list(Data);
-convert_type(Data) when is_atom(Data) ->
- atom_to_list(Data);
-convert_type(Data) when is_float(Data) ->
- float_to_list(Data);
-convert_type(Data) when is_pid(Data) ->
- pid_to_list(Data);
-convert_type(Data) when is_port(Data) ->
- erlang:port_to_list(Data);
-convert_type(Data) when is_tuple(Data) ->
- io_lib:write(Data);
-convert_type([]) ->
- [];
-convert_type(Data) when is_list(Data) ->
- case io_lib:printable_list(Data) of
- true->
- Data;
- _->
- io_lib:write(Data)
- end;
-convert_type(_Data) ->
- [].
-
-
-%%----------------------------------------------------------------------
-%% Function : menu
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-menu(_Env, Args)->
- ["<BODY BGCOLOR=\"#FFFFFF\">", node_selections_javascripts(), node_body(Args, [node()|nodes()])].
-
-menu_title()->
- " <TABLE WIDTH=\"100%\" BORDER=\"0\">
- <TR><TD ALIGN=\"center\"><FONT SIZE=5>Menu</FONT></TD></TR>
- </TABLE>\n".
-
-
-node_body([], Nodes)->
- Node = node(),
- [node_selections_javascripts(), node_selection(Node, Nodes), menu_title(),
- menu_options(atom_to_list(Node))];
-node_body([{"node",Node}|_], Nodes)->
- [node_selections_javascripts(), node_selection(list_to_atom(Node), Nodes), menu_title(),
- menu_options(Node)];
-node_body([_|Rest], Nodes) ->
- node_body(Rest, Nodes).
-
-
-
-%%----------------------------------------------------------------------
-%% Function : node_selections_javascripts
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-node_selections_javascripts()->
- "<SCRIPT>
- function node_selected()
- {
- parent.frames.main.location=\"/orber/start_info.html\"
- window.location =\"./menu?node=\" + " ++
- "document.node_selection.nodes[document.node_selection.nodes.selectedIndex].value;
- }
- </SCRIPT>".
-
-
-
-%%----------------------------------------------------------------------
-%% Function : node_selection
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-node_selection(Node, Nodes)->
- ["<FORM ACTION=\"./node_info\" NAME=node_selection>\n
- <TABLE WIDTH=\"100%\" BORDER=\"0\">\n
- <TR><TD ALIGN=\"center\">\n
- <SELECT NAME=nodes onChange=\"node_selected()\">\n",
- print_nodes(Node, Nodes),
- "</SELECT>\n
- </TD></TR>\n
- </TABLE>\n
- </FORM>"].
-
-%%----------------------------------------------------------------------
-%% Function : print_nodes
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-print_nodes(Node,Nodes)->
- print_nodes_helper([Node|lists:delete(Node,Nodes)]).
-
-print_nodes_helper([])->
- [];
-print_nodes_helper([Node|Rest])->
- NodeStr = atom_to_list(Node),
- ["<OPTION value=\"", NodeStr, "\">", NodeStr, "\n" | print_nodes_helper(Rest)].
-
-%%----------------------------------------------------------------------
-%% Function : print_nodes
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-menu_options(Node)->
- ["<UL><LI><A HREF=\"./info?node=", Node, "\" TARGET=main><B>Configuration</B></A></UL>",
- "<UL><LI><A HREF=\"./nameservice?node=", Node, "&context=root\" TARGET=main><B>Name Service</B></A></UL>",
- "<UL><LI><A HREF=\"./ifr_select?node=", Node, "\" TARGET=main><B>IFR Types</B></A></UL>",
- "<UL><LI><A HREF=\"./create?node=", Node, "\" TARGET=main><B>Create Object</B></A></UL>",
- "<FORM Name=reload><INPUT TYPE=\"button\" onClick=\"node_selected()\" VALUE=\"Reload\">\n</FORM>",
- "<!--<A HREF=\"../../orber/application_help.html\" TARGET=main>Help</A>-->"].
-
-%%----------------------------------------------------------------------
-%%----------------- MISC Functions -------------------------------------
-%%----------------------------------------------------------------------
-%% Function : simple_table
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-simple_table(Cols, Title, Data) ->
- ["<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=",
- Cols, "><FONT SIZE=6>", Title, "</FONT>\n</TD></TR>", add_data(Data), "</TABLE>"].
-
-simple_table(Cols, Title, Data, Extra) ->
- ["<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=",
- Cols, "><FONT SIZE=6>", Title, "</FONT>\n</TD></TR>", add_data(Data),
- Extra, "</TABLE>"].
-
-
-% Temporarily removed to avoid a silly dialyzer warning
-%add_data([]) ->
-% "";
-add_data([{C1, C2, C3, C4}|T]) ->
- add_data(T, ["<TR BGCOLOR=\"#FFFF00\"><TD><B>" ++ C1 ++ "</B></TD><TD><B>"
- ++ C2 ++ "</B></TD><TD><B>" ++ C3 ++ "</B></TD><TD><B>"
- ++ C4 ++ "</B></TD></TR>"]);
-add_data([{C1, C2, C3}|T]) ->
- add_data(T, ["<TR BGCOLOR=\"#FFFF00\"><TD><B>" ++ C1 ++ "</B></TD><TD><B>"
- ++ C2 ++ "</B></TD><TD><B>" ++ C3 ++ "</B></TD></TR>"]);
-add_data([{C1, C2}|T]) ->
- add_data(T, ["<TR BGCOLOR=\"#FFFF00\"><TD><B>" ++ C1 ++ "</B></TD><TD><B>"
- ++ C2 ++ "</B></TD></TR>"]);
-add_data([C1|T]) ->
- add_data(T, ["<TR BGCOLOR=\"#FFFF00\"><TD><B>" ++ C1 ++ "</B></TD></TR>"]).
-
-
-add_data([], Acc) ->
- lists:reverse(Acc);
-add_data([{C1, C2, C3, C4}|T], Acc) ->
- add_data(T, ["<TR><TD><B>"++C1++"</B></TD><TD>"++C2++"</TD><TD>"
- ++C3++"</TD><TD>"++C4++"</TD></TR>"|Acc]);
-add_data([{C1, C2, C3}|T], Acc) ->
- add_data(T, ["<TR><TD><B>"++C1++"</B></TD><TD>"++C2++"</TD><TD>"
- ++C3++"</TD></TR>"|Acc]);
-add_data([{C1, C2}|T], Acc) ->
- add_data(T, ["<TR><TD><B>"++C1++"</B></TD><TD>"++C2++"</TD></TR>"|Acc]);
-add_data([C1|T], Acc) ->
- add_data(T, ["<TR><TD>"++C1++"</TD></TR>"|Acc]).
-
-%%----------------------------------------------------------------------
-%% Function : check
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-check(Data) ->
- check(Data, "").
-
-check({badrpc, {'EXCEPTION', E}}, Comment) ->
- EList = atom_to_list(element(1, E)),
- throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Got the exception: ", EList, "<BR><BR>", Comment]});
-check({badrpc,{'EXIT',{undef,_}}}, Comment) ->
- throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Tried to invoke undefined module or operation.<BR><BR>", Comment]});
-check({badrpc,nodedown}, Comment) ->
- throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Node down - unable to complete the requested operation.<BR><BR>", Comment]});
-check({badrpc, {'EXIT', _R}}, Comment) ->
- throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Invoking the requested operation resulted in an EXIT.<BR><BR>", Comment]});
-check({badrpc, {'EXIT', _R1, _R2}}, Comment) ->
- throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Invoking the requested operation resulted in an EXIT.<BR><BR>", Comment]});
-check({'EXCEPTION', E}, Comment) ->
- EList = atom_to_list(element(1, E)),
- throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Got the exception: ", EList, "<BR><BR>", Comment]});
-check({'EXIT',{undef,_}}, Comment) ->
- throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Tried to invoke operation using undefined module or operation.<BR><BR>", Comment]});
-check({'EXIT', _R}, Comment) ->
- throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Invoking the requested operation resulted in an EXIT.<BR><BR>", Comment]});
-check({'EXIT', _R1, _R2}, Comment) ->
- throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Invoking the requested operation resulted in an EXIT.<BR><BR>", Comment]});
-check(Reply, _) ->
- Reply.
-
-
-%%----------------------------------------------------------------------
-%% Function : is_running
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-is_running(Node, NodeStr) ->
- case rpc:call(Node, application, which_applications, []) of
- {badrpc, _} ->
- throw(["<BODY BGCOLOR=\"#FFFFFF\">
- <TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=1>
- <FONT SIZE=6>Orber not started on node: ", NodeStr, "</FONT>
- </TD></TR></TABLE>"]);
- Apps ->
- is_running2(Apps, NodeStr)
- end.
-
-is_running2([], NodeStr) ->
- throw(["<BODY BGCOLOR=\"#FFFFFF\">
- <TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=1>
- <FONT SIZE=6>Orber not started on node: ", NodeStr, "</FONT>
- </TD></TR></TABLE>"]);
-is_running2([{orber, _, _} |_], _) ->
- true;
-is_running2([_ |As], NodeStr) ->
- is_running2(As, NodeStr).
-
-
-%%----------------------------------------------------------------------
-%% Function : parse_data
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-parse_data([])->
- [];
-parse_data(Options)->
- case erl_scan:string(Options ++ ".") of
- {ok,Tokens,_Line} ->
- case erl_parse:parse_term(Tokens) of
- {ok,X}->
- X;
- Why ->
- orber:dbg("[~p] orber_web:parse_data(~p);
-erl_parse:parse_term failed.
-Malformed data: ~p", [?LINE, Options, Why], ?DEBUG_LEVEL),
- throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Unable to parse supplied data: ",
- Options]})
- end;
- Why ->
- orber:dbg("[~p] orber_web:parse_data(~p);
-erl_scan:string failed.
-Malformed data: ~p", [?LINE, Options, Why], ?DEBUG_LEVEL),
- throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Unable to parse supplied data: ", Options]})
- end.
-
-%%----------------------------------------------------------------------
-%% Function : remote_resolve
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-remote_resolve(Node, Ref) ->
- NS = check(rpc:call(Node, corba, resolve_initial_references, ["NameService"]),
- "Failed to resolve initial refrence (NameService)"),
- case rpc:call(Node, 'CosNaming_NamingContextExt', resolve_str, [NS, Ref]) of
- {'EXCEPTION', E} when is_record(E, 'CosNaming_NamingContext_NotFound') ->
- throw({ok, ["<BODY BGCOLOR=\"#FFFFFF\">Unable to look up the Object: ", Ref,
- "<BR><BR>Reason: CosNaming_NamingContext_NotFound",
- "<BR><BR>If You just deleted it, use the 'Go Back' button next time."]});
- {'EXCEPTION', E} when is_record(E, 'CosNaming_NamingContext_CannotProceed') ->
- throw({ok, ["<BODY BGCOLOR=\"#FFFFFF\">Unable to look up the Object: ", Ref,
- "<BR><BR>Reason: CosNaming_NamingContext_CannotProceed",
- "<BR><BR>If You just deleted it, use the 'Go Back' button next time."]});
- {badrpc, {'EXCEPTION', E}} when is_record(E, 'CosNaming_NamingContext_NotFound') ->
- throw({ok, ["<BODY BGCOLOR=\"#FFFFFF\">Unable to look up the Object: ", Ref,
- "<BR><BR>Reason: CosNaming_NamingContext_NotFound",
- "<BR><BR>If You just deleted it, use the 'Go Back' button next time."]});
- {badrpc, {'EXCEPTION', E}} when is_record(E, 'CosNaming_NamingContext_CannotProceed') ->
- throw({ok, ["<BODY BGCOLOR=\"#FFFFFF\">Unable to look up the Object: ", Ref,
- "<BR><BR>Reason: CosNaming_NamingContext_CannotProceed",
- "<BR><BR>If You just deleted it, use the 'Go Back' button next time."]});
- FoundObj ->
- {FoundObj, NS}
- end.
-
-
-
-%%----------------------------------------------------------------------
-%% END OF MODULE
-%%----------------------------------------------------------------------
diff --git a/lib/orber/src/orber_web_server.erl b/lib/orber/src/orber_web_server.erl
deleted file mode 100644
index 3506894df2..0000000000
--- a/lib/orber/src/orber_web_server.erl
+++ /dev/null
@@ -1,190 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_web_server.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module(orber_web_server).
-
--behaviour(gen_server).
-
--export([init/1,handle_call/3,handle_cast/2,handle_info/2]).
--export([terminate/2,code_change/3]).
--export([start/0,stop/0,start_link/0]).
-
--export([config_data/0, menu/2, configure/2, info/2, nameservice/2,
- default_selection/2, ifr_select/2, ifr_data/2, create/2,
- delete_ctx/2, add_ctx/2, delete_obj/2, flash_msg/2]).
-
-%%----------------------------------------------------------------------
-%%-------------- Defines & Includes ------------------------------------
-%%----------------------------------------------------------------------
--define(HTML_HEADER,
- "Cache-Control:no-cache\r\nPragma:no-cache\r\nExpires:Thu, 01 Dec 1994 16:00:00 GMT\r\nContent-type: text/html\r\n\r\n<HTML BGCOLOR=\"#FFFFFF\">\n<HEAD>\n<TITLE>Orber O&D</TITLE>\n</HEAD>\n").
-
-
--define(HTML_END, "</BODY></HTML>").
-
--define(DEBUG_LEVEL, 5).
-
--record(state, {}).
--include("ifr_objects.hrl").
-
-%%----------------------------------------------------------------------
-%%-------------- External API ------------------------------------------
-%%----------------------------------------------------------------------
-%% Function : start/start_link/stop
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-start_link()->
- gen_server:start_link({local,?MODULE},?MODULE,[],[]).
-start()->
- gen_server:start({local,?MODULE},?MODULE,[],[]).
-stop()->
- gen_server:call(?MODULE,stop,1000).
-
-%%----------------------------------------------------------------------
-%% Function : config_data
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-config_data()->
- {orber,[{web_data,{"OrberWeb","/orber/main_frame.html"}},
- {alias,{"/orber", code:priv_dir(orber)}},
- {start,{child,{{local,?MODULE},{?MODULE,start_link,[]},
- permanent,100,worker,[?MODULE]}}},
- {alias,{erl_alias,"/orber_erl",[orber_web_server]}}
- ]}.
-
-
-menu(Env,Input) ->
- Args = httpd:parse_query(Input),
- [?HTML_HEADER, gen_server:call(?MODULE, {menu, Env, Args}), ?HTML_END].
-
-configure(Env,Input) ->
- Args = httpd:parse_query(Input),
- [?HTML_HEADER, gen_server:call(?MODULE, {configure, Env, Args}), ?HTML_END].
-
-nameservice(Env,Input) ->
- Args = httpd:parse_query(Input),
- [?HTML_HEADER, gen_server:call(?MODULE, {nameservice, Env, Args}), ?HTML_END].
-
-info(Env,Input) ->
- Args = httpd:parse_query(Input),
- [?HTML_HEADER, gen_server:call(?MODULE, {info, Env, Args}), ?HTML_END].
-
-default_selection(Env,Input) ->
- Args = httpd:parse_query(Input),
- [?HTML_HEADER, gen_server:call(?MODULE, {default_selection, Env, Args}), ?HTML_END].
-
-flash_msg(Env, Input) ->
- Args = httpd:parse_query(Input),
- [?HTML_HEADER, gen_server:call(?MODULE, {nameservice, Env, Args}), ?HTML_END].
-
-ifr_select(Env, Input) ->
- Args = httpd:parse_query(Input),
- [?HTML_HEADER, gen_server:call(?MODULE, {ifr_select, Env, Args}), ?HTML_END].
-
-ifr_data(Env, Input) ->
- Args = httpd:parse_query(Input),
- [?HTML_HEADER, gen_server:call(?MODULE, {ifr_data, Env, Args}), ?HTML_END].
-
-create(Env, Input) ->
- Args = httpd:parse_query(Input),
- [?HTML_HEADER, gen_server:call(?MODULE, {create, Env, Args}), ?HTML_END].
-
-delete_ctx(Env, Input) ->
- Args = httpd:parse_query(Input),
- [?HTML_HEADER, gen_server:call(?MODULE, {delete_ctx, Env, Args}), ?HTML_END].
-
-add_ctx(Env, Input) ->
- Args = httpd:parse_query(Input),
- [?HTML_HEADER, gen_server:call(?MODULE, {add_ctx, Env, Args}), ?HTML_END].
-
-delete_obj(Env, Input) ->
- Args = httpd:parse_query(Input),
- [?HTML_HEADER, gen_server:call(?MODULE, {delete_obj, Env, Args}), ?HTML_END].
-
-%%----------------------------------------------------------------------
-%%-------------- Callback Functions ------------------------------------
-%%----------------------------------------------------------------------
-%% Function : MISC gen_server specific callback functions
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-init(_Arg)->
- {ok, #state{}}.
-
-terminate(_,_State)->
- ok.
-
-handle_cast(_,State)->
- {noreply,State}.
-
-handle_info(_,State)->
- {noreply,State}.
-
-code_change(_Old_vsn,State,_Extra)->
- {ok,State}.
-
-%%----------------------------------------------------------------------
-%% Function : handle_call
-%% Returns :
-%% Description:
-%%----------------------------------------------------------------------
-handle_call({Function, Env, Args}, _From, State)->
- case catch orber_web:Function(Env, Args) of
- {'EXIT', R} ->
- orber:dbg("[~p] orber_web:~p(~p);~nEXIT: ~p",
- [?LINE, Function, Args, R], ?DEBUG_LEVEL),
- {reply, "<BODY BGCOLOR=\"#FFFFFF\">Internal Error", State};
- {'EXIT', R1, R2} ->
- orber:dbg("[~p] orber_web:~p(~p);~nEXIT: ~p~n~p",
- [?LINE, Function, Args, R1, R2], ?DEBUG_LEVEL),
- {reply, "<BODY BGCOLOR=\"#FFFFFF\">Internal Error", State};
- {badrpc, Why} ->
- orber:dbg("[~p] orber_web:~p(~p);~nbadrpc: ~p",
- [?LINE, Function, Args, Why], ?DEBUG_LEVEL),
- {reply, "<BODY BGCOLOR=\"#FFFFFF\">Internal Error", State};
- {'EXCEPTION', E} ->
- orber:dbg("[~p] orber_web:~p(~p);~nEXCEPTION: ~p",
- [?LINE, Function, Args, E], ?DEBUG_LEVEL),
- {reply, "<BODY BGCOLOR=\"#FFFFFF\">Internal Error", State};
- {error, Data} ->
- orber:dbg("[~p] orber_web:~p(~p); ~nReason: ~p",
- [?LINE, Function, Args, Data], ?DEBUG_LEVEL),
- {reply, Data, State};
- Reply ->
- {reply, Reply, State}
- end;
-handle_call(stop, _From, State)->
- {stop, normal, ok, State};
-handle_call(What, _From, State)->
- orber:dbg("[~p] orber_web_server:handle_call(~p);",
- [?LINE, What], ?DEBUG_LEVEL),
- {reply, "<BODY BGCOLOR=\"#FFFFFF\"><FONT SIZE=6>Unknown Request</FONT>", State}.
-
-%%----------------------------------------------------------------------
-%% END OF MODULE
-%%----------------------------------------------------------------------
diff --git a/lib/orber/test/Makefile b/lib/orber/test/Makefile
deleted file mode 100644
index 782ee2730b..0000000000
--- a/lib/orber/test/Makefile
+++ /dev/null
@@ -1,220 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../vsn.mk
-VSN=$(ORBER_VSN)
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/orber_test
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-TEST_SPEC_FILE = orber.spec
-COVER_FILE = orber.cover
-
-
-IDL_FILES = \
- orber_test.idl \
- iiop_test.idl \
- orber_test_server.idl
-
-IDLOUTDIR = idl_output
-
-MODULES = \
- cdrcoding_11_SUITE \
- cdrcoding_10_SUITE \
- cdrcoding_12_SUITE \
- cdrlib_SUITE \
- corba_SUITE \
- iop_ior_11_SUITE \
- iop_ior_10_SUITE \
- iop_ior_12_SUITE \
- iiop_module_do_test_impl \
- iiop_module_test_impl \
- lname_SUITE \
- naming_context_SUITE \
- orber_SUITE \
- orber_test_server_impl \
- orber_test_timeout_server_impl \
- orber_test_lib \
- csiv2_SUITE \
- multi_ORB_SUITE \
- data_types_SUITE \
- tc_SUITE \
- generated_SUITE \
- orber_web_SUITE \
- interceptors_SUITE \
- orber_acl_SUITE \
- orber_firewall_ipv4_in_SUITE \
- orber_firewall_ipv6_in_SUITE \
- orber_firewall_ipv4_out_SUITE \
- orber_firewall_ipv6_out_SUITE \
- orber_nat_SUITE \
- ip_v4v6_interop_SUITE
-
-GEN_MOD_ORBER = \
- oe_orber_test \
- Module_Except1 \
- Module_Except2 \
- Module_Except3 \
- Module_Except4 \
- Module_HEADER \
- Module_I1 \
- Module_I2 \
- Module_Struct0 \
- Module_Struct1 \
- Module_Struct2 \
- Module_Union \
- Module_Union1 \
- Module_Union2
-
-GEN_HRL_ORBER = \
- oe_orber_test.hrl \
- Module.hrl \
- Module_I1.hrl \
- Module_I2.hrl
-
-GEN_MOD_IIOP = \
- oe_iiop_test \
- iiop_module_Except1 \
- iiop_module_Struct1 \
- iiop_module_Union1 \
- iiop_module_do_test \
- iiop_module_test \
- iiop_module_test_retval
-
-GEN_HRL_IIOP = \
- oe_iiop_test.hrl \
- iiop_module.hrl \
- iiop_module_do_test.hrl \
- iiop_module_test.hrl
-
-GEN_MOD_TEST_SERVER = \
- oe_orber_test_server \
- orber_test_server \
- orber_test_server_ComplexUserDefinedException \
- orber_test_server_UserDefinedException \
- orber_test_server_struc \
- orber_test_server_uni \
- orber_test_server_uni_d \
- orber_test_timeout_server \
- orber_parent_inherrit \
- orber_test_server_rec_struct \
- orber_test_server_rec_struct_seq \
- orber_test_server_rec_union \
- orber_test_server_rec_union_seq
-
-GEN_HRL_TEST_SERVER = \
- oe_orber_test_server.hrl \
- orber_test_server.hrl \
- orber_test_timeout_server.hrl
-
-GEN_MODULES = $(GEN_MOD_ORBER) $(GEN_MOD_IIOP) \
- $(GEN_MOD_TEST_SERVER)
-
-ERL_FILES = $(MODULES:%=%.erl)
-
-HRL_FILES =
-
-GEN_HRL_FILES = $(GEN_HRL_ORBER) $(GEN_HRL_IIOP) \
- $(GEN_HRL_TEST_SERVER)
-
-GEN_FILES = \
- $(GEN_HRL_FILES:%=$(IDLOUTDIR)/%) \
- $(GEN_MODULES:%=$(IDLOUTDIR)/%.erl)
-
-GEN_TARGET_FILES = $(GEN_MODULES:%=$(IDLOUTDIR)/%.$(EMULATOR))
-
-SUITE_TARGET_FILES = $(MODULES:%=%.$(EMULATOR))
-
-TARGET_FILES = \
- $(GEN_TARGET_FILES) \
- $(SUITE_TARGET_FILES)
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_IDL_FLAGS += -pa $(ERL_TOP)/lib/orber/ebin -pa $(ERL_TOP)/lib/ic/ebin
-
-ERL_COMPILE_FLAGS += $(ERL_IDL_FLAGS) \
- -pa $(ERL_TOP)/lib/ic/ebin \
- -pa $(ERL_TOP)/lib/orber/ebin \
- -I$(ERL_TOP)/lib/orber \
- -I$(ERL_TOP)/lib/orber/test/$(IDLOUTDIR)
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-tests debug opt: $(TARGET_FILES)
-
-clean:
- rm -f idl_output/*
- rm -f $(TARGET_FILES)
- rm -f errs core *~
- rm IDL-GENERATED
-
-
-docs:
-
-# ----------------------------------------------------
-# Special Targets
-# ----------------------------------------------------
-
-IDL-GENERATED: orber_test.idl iiop_test.idl orber_test_server.idl
- erlc $(ERL_IDL_FLAGS) -o$(IDLOUTDIR) orber_test.idl
- erlc $(ERL_IDL_FLAGS) -o$(IDLOUTDIR) \
- +'{preproc_flags,"-I../COSS/CosNaming"}' iiop_test.idl
- erlc $(ERL_IDL_FLAGS) -o$(IDLOUTDIR) \
- +'{cfgfile,"orber_test_server.cfg"}' orber_test_server.idl
- >IDL-GENERATED
-
-$(GEN_FILES): IDL-GENERATED
-
-$(TARGET_FILES): IDL-GENERATED
-
-# ----------------------------------------------------
-# Release Targets
-# ----------------------------------------------------
-# We don't copy generated intermediate erlang and hrl files
-
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec:
-
-release_docs_spec:
-
-release_tests_spec: tests
- $(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(IDL_FILES) $(TEST_SPEC_FILE) $(COVER_FILE) \
- $(ERL_FILES) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(SUITE_TARGET_FILES) "$(RELSYSDIR)"
- chmod -R u+w "$(RELSYSDIR)"
- $(INSTALL_DIR) "$(RELSYSDIR)/$(IDLOUTDIR)"
- $(INSTALL_DATA) $(GEN_TARGET_FILES) $(GEN_FILES) \
- "$(RELSYSDIR)/$(IDLOUTDIR)"
-
diff --git a/lib/orber/test/cdrcoding_10_SUITE.erl b/lib/orber/test/cdrcoding_10_SUITE.erl
deleted file mode 100644
index 24de589615..0000000000
--- a/lib/orber/test/cdrcoding_10_SUITE.erl
+++ /dev/null
@@ -1,587 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%%
-%% Description:
-%% Test suite for the CDR encode/decode functions
-%%
-%%-----------------------------------------------------------------
--module(cdrcoding_10_SUITE).
-
--include("idl_output/Module.hrl").
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
--define(default_timeout, test_server:minutes(20)).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [{types, [],
- [do_register, null_type, void_type, principal_type,
- objref_type, struct_type, union_type, string_type,
- array_type, any_type, typecode_type, alias_type,
- exception_type, do_unregister]}].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-cases() ->
- [{group, types}, reply, cancel_request,
- close_connection, message_error].
-%% request, locate_request, locate_reply].
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-
-init_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) when is_list(Config) ->
- orber:jump_start(0),
- if
- is_list(Config) ->
- Config;
- true ->
- exit("Config not a list")
- end.
-
-end_per_suite(Config) when is_list(Config) ->
- orber:jump_stop(),
- Config.
-
-%%-----------------------------------------------------------------
-%% Test Case: type encoding tests
-%% Description: Just testing the complex types, the others are
-%% tested in the cdrlib SUITE.
-%%-----------------------------------------------------------------
-%types(Config) when list(Config) ->
-% 'oe_orber_test':'oe_register'(),
-% null_type(),
-% void_type(),
-% principal_type(),
-% objref_type(),
-% struct_type(),
-% union_type(),
-% string_type(),
-% array_type(),
-% any_type(),
-% typecode_type(),
-% alias_type(),
-% exception_type(),
-% 'oe_orber_test':'oe_unregister'(),
-% ok.
-
-do_register(Config) when is_list(Config) ->
- io:format("Pwd: ~p, mod: ~p~n",[c:pwd(), c:m('oe_orber_test')]),
- 'oe_orber_test':'oe_register'(),
- ok.
-
-do_unregister(Config) when is_list(Config) ->
- 'oe_orber_test':'oe_unregister'(),
- ok.
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: null
-%%-----------------------------------------------------------------
-null_type(Config) when is_list(Config) ->
- B = cdr_encode:enc_type(#giop_env{version = {1, 0}}, 'tk_null', 'null'),
- {'null', <<>>, _} = cdr_decode:dec_type('tk_null', {1, 0}, B, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: void
-%%-----------------------------------------------------------------
-void_type(Config) when is_list(Config) ->
- B = cdr_encode:enc_type(#giop_env{version = {1, 0}}, 'tk_void', 'ok'),
- {'ok', <<>>, _} = cdr_decode:dec_type('tk_void', {1, 0}, B, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: principal
-%%-----------------------------------------------------------------
-principal_type(Config) when is_list(Config) ->
- B0 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, 'tk_Principal', "principal"),
- {"principal", <<>>, _} = cdr_decode:dec_type('tk_Principal', {1, 0}, B0, 0, big),
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, 'tk_Principal', ""),
- {"", <<>>, _} = cdr_decode:dec_type('tk_Principal', {1, 0}, B1, 0, big),
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, 'tk_Principal', "principal"),
- {"principal", <<>>, _} =
- cdr_decode:dec_type('tk_Principal', {1, 0}, B2, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: object reference
-%%-----------------------------------------------------------------
-version() -> #'IIOP_Version'{major=1,minor=0}.
-
-objref(0) ->
- PB = #'IIOP_ProfileBody_1_0'{iiop_version=version(),
- host="my.hostname.org",
- port=4040,
- object_key="ExternalKey: which is an arbitary octet sequence"},
- TP = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB},
- #'IOP_IOR'{type_id="IDL:Module/Interface:1.0", profiles=[TP]};
-objref(1) ->
- K = corba_fake_mk_objkey("IDL:Module/Interface:1.0", key,
- list_to_pid("<0.100.0>")),
- PB = #'IIOP_ProfileBody_1_0'{iiop_version=version(),
- host="my.hostname.org",
- port=4040,
- object_key=K},
- TP = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB},
- #'IOP_IOR'{type_id="IDL:Module/Interface:1.0", profiles=[TP]};
-objref(2) ->
- K = corba_fake_mk_objkey("IDL:Module/Interface:1.0", registered,
- list_to_atom("orber_nameservice")),
- PB = #'IIOP_ProfileBody_1_0'{iiop_version=version(),
- host="my.hostname.org",
- port=4040,
- object_key=K},
- TP = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB},
- #'IOP_IOR'{type_id="IDL:Module/Interface:1.0", profiles=[TP]}.
-
-objref_type(Config) when is_list(Config) ->
- T = {'tk_objref', "IDL:Module/Interface:1.0", "Interface"},
- Objref0 = objref(0),
- B0 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T, Objref0),
- {Objref0, <<>>, _} = cdr_decode:dec_type(T, {1, 0}, B0, 0, big),
- Objref1 = objref(1),
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T, Objref1),
- {Objref1, <<>>, _} = cdr_decode:dec_type(T, {1, 0}, B1, 0, big),
- Objref2 = objref(2),
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T, Objref2),
- {Objref2, <<>>, _} = cdr_decode:dec_type(T, {1, 0}, B2, 0, big),
- ok.
-
-
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: struct
-%%-----------------------------------------------------------------
-struct_type(Config) when is_list(Config) ->
- T0 = {'tk_struct',"IDL:Module/Struct0:1.0", "Module_Struct0",
- [{"long", 'tk_long'}, {"short", 'tk_short'}, {"character", 'tk_char'}]},
- S0 = #'Module_Struct0'{l=-4711, s=17, c=$a},
- B0 = cdr_encode:enc_type({1, 0}, T0, S0),
- {S0, <<>>, _} = cdr_decode:dec_type(T0, {1, 0}, B0, 0, big),
-
- T1 = {'tk_struct', "IDL:Module/Struct1:1.0", "Module_Struct1",
- [{"string", {'tk_string', 0}}, {"ushort", 'tk_ushort'}, {"ulong", 'tk_ulong'}]},
- S1 = #'Module_Struct1'{s="Hi !!!!", us=17, ul=4711},
- B1 = cdr_encode:enc_type({1, 0}, T1, S1),
- {S1, <<>>, _} = cdr_decode:dec_type(T1, {1, 0}, B1, 0, big),
-
- T2 = {'tk_struct', "IDL:Module/Struct2:1.0", "Module_Struct2",
- [{"long_sequence", {'tk_sequence', 'tk_long', 0}},
- {"enum", {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum", ["horse", "pig", "cow"]}},
- {"octet", 'tk_octet'}]},
- S2 = #'Module_Struct2'{long_sequence=[4711, 350000, 0, -3030, -600000], e=cow, o=$X},
- B2 = cdr_encode:enc_type({1, 0}, T2, S2),
- {S2, <<>>, _} = cdr_decode:dec_type(T2, {1, 0}, B2, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: union
-%%-----------------------------------------------------------------
-union_type(Config) when is_list(Config) ->
- T0 = {'tk_union', "IDL:Module/Union:1.0", "Union", 'tk_short', 2,
- [{0, "First", 'tk_short'},
- {1, "Second", {'tk_string', 0}},
- {2, "Third", 'tk_char'}]},
- S0 = #'Module_Union'{label=1, value="Foo Bar !"},
- B0 = cdr_encode:enc_type({1, 0}, T0, S0),
- {S0, <<>>, _} = cdr_decode:dec_type(T0, {1, 0}, B0, 0, big),
- S1 = #'Module_Union'{label=0, value=-17},
- B1 = cdr_encode:enc_type({1, 0}, T0, S1),
- {S1, <<>>, _} = cdr_decode:dec_type(T0, {1, 0}, B1, 0, big),
- S2 = #'Module_Union'{label=2, value=$X},
- B2 = cdr_encode:enc_type({1, 0}, T0, S2),
- {S2, <<>>, _} = cdr_decode:dec_type(T0, {1, 0}, B2, 0, big),
- T1 = {'tk_union', "IDL:Module/Union1:1.0", "Union1",
- {'tk_enum', "IDL:Module/Enum:1.0",
- "Module_Enum", ["horse", "pig", "cow"]}, "pig",
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence', {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum', "IDL:Module/Enum1:1.0",
- "Module_Enum1", ["orange", "banana", "apple"]}}]},
- S3 = #'Module_Union1'{label=pig, value=["Foo", "Bar", "!"]},
- B3 = cdr_encode:enc_type({1, 0}, T1, S3),
- {S3, <<>>, _} = cdr_decode:dec_type(T1, {1, 0}, B3, 0, big),
- S4 = #'Module_Union1'{label=cow, value=apple},
- B4 = cdr_encode:enc_type({1, 0}, T1, S4),
- {S4, <<>>, _} = cdr_decode:dec_type(T1, {1, 0}, B4, 0, big),
- S5 = #'Module_Union1'{label=horse, value=17},
- B5 = cdr_encode:enc_type({1, 0}, T1, S5),
- {S5, <<>>, _} = cdr_decode:dec_type(T1, {1, 0}, B5, 0, big),
- T2 = {'tk_union', "IDL:Module/Union2:1.0", "Union2",
- {'tk_enum', "IDL:Module/Enum:1.0",
- "Module_Enum", ["horse", "pig", "cow"]}, "pig",
- [{"horse", "First", {'tk_array', 'tk_long', 3}},
- {"pig", "Second",
- {'tk_union', "IDL:Module/Union:1.0", "Union", 'tk_short', 2,
- [{0, "First", 'tk_short'},
- {1, "Second", {'tk_string', 0}},
- {2, "Third", 'tk_char'}]}},
- {"cow", "Third", {'tk_union', "IDL:Module/Union1:1.0", "Union1",
- {'tk_enum', "IDL:Module/Enum:1.0",
- "Module_Enum", ["horse", "pig", "cow"]}, "pig",
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence',
- {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum',
- "IDL:Module/Enum1:1.0",
- "Module_Enum1",
- ["orange", "banana",
- "apple"]}}]}}]},
- S6 = #'Module_Union2'{label=pig, value=#'Module_Union'{label=0, value=-17}},
- B6 = cdr_encode:enc_type({1, 0}, T2, S6),
- {S6, <<>>, _} = cdr_decode:dec_type(T2, {1, 0}, B6, 0, big),
- S7 = #'Module_Union2'{label=cow, value=#'Module_Union1'{label=pig,
- value=["Foo", "Bar", "!"]}},
- B7 = cdr_encode:enc_type({1, 0}, T2, S7),
- {S7, <<>>, _} = cdr_decode:dec_type(T2, {1, 0}, B7, 0, big),
- S8 = #'Module_Union2'{label=horse, value={-17, 1234567890, -987654321}},
- B8 = cdr_encode:enc_type({1, 0}, T2, S8),
- {S8, <<>>, _} = cdr_decode:dec_type(T2, {1, 0}, B8, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: string
-%%-----------------------------------------------------------------
-string_type(Config) when is_list(Config) ->
- S0 = "Foo Bar ???",
- B0 = cdr_encode:enc_type({1, 0}, {'tk_string', 0}, S0),
- {S0, <<>>, _} = cdr_decode:dec_type({'tk_string', 0}, {1, 0}, B0, 0, big),
- S1 = "Yes, Foo Bar !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! more than 5000 characters",
- B1 = cdr_encode:enc_type({1, 0}, {'tk_string', 0}, S1),
- {S1, <<>>, _} = cdr_decode:dec_type({'tk_string', 0}, {1, 0}, B1, 0, big),
- S2 = "",
- B2 = cdr_encode:enc_type({1, 0}, {'tk_string', 0}, S2),
- {S2, <<>>, _} = cdr_decode:dec_type({'tk_string', 0}, {1, 0}, B2, 0, big),
- S3 = "\0",
- B3 = cdr_encode:enc_type({1, 0}, {'tk_string', 0}, S3),
- {S3, <<>>, _} = cdr_decode:dec_type({'tk_string', 0}, {1, 0}, B3, 0, big),
- S4 = "~n",
- B4 = cdr_encode:enc_type({1, 0}, {'tk_string', 0}, S4),
- {S4, <<>>, _} = cdr_decode:dec_type({'tk_string', 0}, {1, 0}, B4, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: array
-%%-----------------------------------------------------------------
-array_type(Config) when is_list(Config) ->
- T0 = {'tk_array', 'tk_long', 5},
- S0 = {-100, 0, 30000, -900100900, 123456789},
- B0 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T0, S0),
- {S0, <<>>, _} = cdr_decode:dec_type(T0, {1, 0}, B0, 0, big),
- T1 = {'tk_array', {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum", ["horse", "pig", "cow"]}, 2},
- S1 = {pig, cow},
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T1, S1),
- {S1, <<>>, _} = cdr_decode:dec_type(T1, {1, 0}, B1, 0, big),
- T2 = {'tk_array', {'tk_union', "IDL:Module/Union:1.0", "Union",
- {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum", ["horse", "pig", "cow"]}, "pig",
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence', {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum', "IDL:Module/Enum1:1.0",
- "Module_Enum1", ["orange", "banana", "apple"]}}]}, 2},
- S2 = {#'Module_Union'{label=cow, value=banana}, #'Module_Union'{label=pig, value=["This", "is", "a", "test", ""]}},
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T2, S2),
- {S2, <<>>, _} = cdr_decode:dec_type(T2, {1, 0}, B2, 0, big),
- T3 = {'tk_array', {'tk_objref', "IDL:Module/Interface:1.0", "Interface"}, 3},
- S3 = {objref(0), objref(1), objref(2)},
- B3 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T3, S3),
- {S3, <<>>, _} = cdr_decode:dec_type(T3, {1, 0}, B3, 0, big),
- ok.
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: TypeCode
-%%-----------------------------------------------------------------
-any_type(Config) when is_list(Config) ->
- T = 'tk_any',
- TC = {'tk_struct', "IDL:Module/Struct2:1.0", "Module_Struct2",
- [{"long_sequence", {'tk_sequence', 'tk_long', 0}},
- {"enum", {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum",
- ["horse", "pig", "cow"]}},
- {"octet", 'tk_octet'}]},
- S = #'Module_Struct2'{long_sequence=[4711, 350000, 0, -3030, -600000],
- e=cow, o=$X},
- Any = #any{typecode=TC,value=S},
- B = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T,Any),
- {Any, <<>>, _} = cdr_decode:dec_type(T, {1, 0}, B, 0, big),
- TC1 = {'tk_array', {'tk_union', "IDL:Module/Union:1.0", "Union",
- {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum",
- ["horse", "pig", "cow"]}, 1,
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence', {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum', "IDL:Module/Enum1:1.0",
- "Module_Enum1", ["orange", "banana",
- "apple"]}}]},2},
- S1 = {#'Module_Union'{label=cow, value=banana}, #'Module_Union'{label=pig, value=["This", "is", "a", "test", ""]}},
- Any1 = #any{typecode=TC1,value=S1},
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T,Any1),
- {Any1, <<>>, _} = cdr_decode:dec_type(T, {1, 0}, B1, 0, big),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: TypeCode
-%%-----------------------------------------------------------------
-typecode_type(Config) when is_list(Config) ->
- T = 'tk_TypeCode',
- TC = {'tk_array', {'tk_union', "IDL:Module/Union:1.0", "Union",
- {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum",
- ["horse", "pig", "cow"]}, 1,
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence', {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum', "IDL:Module/Enum1:1.0",
- "Module_Enum1", ["orange", "banana",
- "apple"]}}]}, 10},
- B = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T,TC),
- {TC, <<>>, _} = cdr_decode:dec_type(T, {1, 0}, B, 0, big),
- TC1 = {'tk_union', "IDL:Module/Union2:1.0", "Union2",
- {'tk_enum', "IDL:Module/Enum:1.0",
- "Module_Enum", ["horse", "pig", "cow"]}, 2,
- [{"horse", "First", 'tk_long'},
- {"pig", "Second",
- {'tk_union', "IDL:Module/Union:1.0", "Union", 'tk_short', 2,
- [{0, "First", 'tk_short'},
- {1, "Second", {'tk_string', 0}},
- {2, "Third", 'tk_char'}]}},
- {"cow", "Third", {'tk_union', "IDL:Module/Union1:1.0", "Union1",
- {'tk_enum', "IDL:Module/Enum:1.0",
- "Module_Enum", ["horse", "pig", "cow"]}, 2,
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence',
- {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum',
- "IDL:Module/Enum1:1.0",
- "Module_Enum1",
- ["orange", "banana",
- "apple"]}}]}}]},
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T, TC1),
- {TC1, <<>>, _} = cdr_decode:dec_type(T, {1, 0}, B1, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: TypeCode
-%%-----------------------------------------------------------------
-alias_type(Config) when is_list(Config) ->
- T = {'tk_alias', "IDL:Module/Alias:1.0", "Alias",
- {'tk_struct', "IDL:Module/Struct2:1.0", "Module_Struct2",
- [{"long_sequence", {'tk_sequence', 'tk_long', 0}},
- {"enum", {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum",
- ["horse", "pig", "cow"]}},
- {"octet", 'tk_octet'}]}},
- S = #'Module_Struct2'{long_sequence=[4711, 350000, 0, -3030, -600000],
- e=cow, o=$X},
- B = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T,S),
- {S, <<>>, _} = cdr_decode:dec_type(T, {1, 0}, B, 0, big),
- T1 = {'tk_alias', "IDL:Module/Alias1:1.0", "Alias1",
- {'tk_sequence', {'tk_union', "IDL:Module/Union:1.0", "Union",
- {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum",
- ["horse", "pig", "cow"]}, 2,
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence', {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum', "IDL:Module/Enum1:1.0",
- "Module_Enum1", ["orange", "banana",
- "apple"]}}]},0}},
- S1 = [#'Module_Union'{label=cow, value=banana}, #'Module_Union'{label=pig, value=["This", "is", "a", "test", ""]}],
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T1, S1),
- {S1, <<>>, _} = cdr_decode:dec_type(T1, {1, 0}, B1, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: exception
-%%-----------------------------------------------------------------
-exception_type(Config) when is_list(Config) ->
- system_exceptions(),
- user_exceptions(),
- ok.
-
-system_exceptions() ->
- E = #'UNKNOWN'{completion_status=?COMPLETED_YES},
- {system_exception, T, E} = orber_exceptions:get_def(E),
- B = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T,E),
- {E, _} = cdr_decode:dec_system_exception({1, 0}, B, 0, big),
- E1 = #'INV_OBJREF'{completion_status=?COMPLETED_NO},
- {system_exception, T1, E1} = orber_exceptions:get_def(E1),
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T1,E1),
- {E1, _} = cdr_decode:dec_system_exception({1, 0}, B1, 0, big),
- E2 = #'BAD_OPERATION'{completion_status=?COMPLETED_NO},
- {system_exception, T2, E2} = orber_exceptions:get_def(E2),
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T2,E2),
- {E2, _} = cdr_decode:dec_system_exception({1, 0}, B2, 0, big),
- E3 = #'INTF_REPOS'{completion_status=?COMPLETED_MAYBE},
- {system_exception, T3, E3} = orber_exceptions:get_def(E3),
- B3 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T3,E3),
- {E3, _} = cdr_decode:dec_system_exception({1, 0}, B3, 0, big),
- ok.
-
-user_exceptions() ->
- E = #'Module_Except1'{rest_of_name=["I","am","testing","exceptions"], why="Error"},
- {user_exception, T, E} = orber_exceptions:get_def(E),
- B = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T, E),
- {E, _} = cdr_decode:dec_user_exception({1, 0}, B, 0, big),
- E1 = #'Module_Except2'{e=banana,
- s=#'Module_Struct2'{long_sequence=[12,-4040,
- 1234567898],
- e=horse,
- o=$a}},
- {user_exception, T1, E1} = orber_exceptions:get_def(E1),
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T1, E1),
- {E1, _} = cdr_decode:dec_user_exception({1, 0}, B1, 0, big),
- E2 = #'Module_Except3'{u=#'Module_Union1'{label=pig,value=["high","and","low"]},s=1313, o=objref(0)},
- {user_exception, T2, E2} = orber_exceptions:get_def(E2),
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T2, E2),
- {E2, _} = cdr_decode:dec_user_exception({1, 0}, B2, 0, big),
- E3 = #'Module_Except4'{},
- {user_exception, T3, E3} = orber_exceptions:get_def(E3),
- B3 = cdr_encode:enc_type(#giop_env{version = {1, 0}}, T3, E3),
- {E3, _} = cdr_decode:dec_user_exception({1, 0}, B3, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: request encoding test
-%% Description: Precondition the stack must be started so the
-%% objectkey is valid.
-%%-----------------------------------------------------------------
-%request(_) ->
-% exit(not_implemented).
-
-%%-----------------------------------------------------------------
-%% Test Case: reply encoding test
-%% Description:
-%%-----------------------------------------------------------------
-reply(Config) when is_list(Config) ->
- R = #reply_header{service_context=[], request_id=1,
- reply_status='no_exception'},
- B = cdr_encode:enc_reply(
- #giop_env{version = {1, 0}, request_id = 1,
- reply_status = 'no_exception',
- tc = {'tk_long', [], [{'tk_sequence',
- {'tk_string', 0}, 0}]},
- result = 1200, parameters = [["foo","Bar"]],
- ctx = []}),
- {R, 1200, [["foo","Bar"]]} =
- cdr_decode:dec_message({'tk_long', [], [{'tk_sequence', {'tk_string', 0},0}]},
- B),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: cancel_request encoding test
-%% Description:
-%%-----------------------------------------------------------------
-cancel_request(Config) when is_list(Config) ->
- R = #cancel_request_header{request_id=1},
- B = cdr_encode:enc_cancel_request(#giop_env{version = {1, 0},
- request_id = 1}),
- R = cdr_decode:dec_message([], B),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: locate_request encoding test
-%% Description:
-%%-----------------------------------------------------------------
-locate_request(Config) when is_list(Config) ->
- io:format("Function not imlpemented yet"),
- exit(not_implemented).
-
-%%-----------------------------------------------------------------
-%% Test Case: locate_reply encoding test
-%% Description:
-%%-----------------------------------------------------------------
-locate_reply(Config) when is_list(Config) ->
- io:format("Function not imlpemented yet"),
- exit(not_implemented).
-
-%%-----------------------------------------------------------------
-%% Test Case: close_connection encoding test
-%% Description:
-%%-----------------------------------------------------------------
-close_connection(Config) when is_list(Config) ->
- B = cdr_encode:enc_close_connection(#giop_env{version = {1, 0}}),
- 'close_connection' = cdr_decode:dec_message([], B),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: message_error encoding test
-%% Description:
-%%-----------------------------------------------------------------
-message_error(Config) when is_list(Config) ->
- B = cdr_encode:enc_message_error(#giop_env{version = {1, 0}}),
- 'message_error' = cdr_decode:dec_message([], B),
- ok.
-
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-corba_fake_mk_objkey(Id, 'key', Pid) when is_pid(Pid) ->
- Key = make_objkey(),
- {list_to_binary(Id), 'key', Key, term_to_binary(undefined),
- term_to_binary(undefined), term_to_binary(undefined)};
-corba_fake_mk_objkey(Id, 'key', RegName) when is_atom(RegName) ->
- Key = term_to_binary(RegName),
- {list_to_binary(Id), 'key', Key, term_to_binary(undefined),
- term_to_binary(undefined), term_to_binary(undefined)};
-corba_fake_mk_objkey(Id, 'registered', RegName) when is_atom(RegName) ->
- {list_to_binary(Id), 'registered', RegName, term_to_binary(undefined),
- term_to_binary(undefined), term_to_binary(undefined)}.
-
-make_objkey() ->
- term_to_binary({{erlang:system_time(),
- erlang:unique_integer()},
- node()}).
diff --git a/lib/orber/test/cdrcoding_11_SUITE.erl b/lib/orber/test/cdrcoding_11_SUITE.erl
deleted file mode 100644
index ff5d2852d6..0000000000
--- a/lib/orber/test/cdrcoding_11_SUITE.erl
+++ /dev/null
@@ -1,587 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%%
-%% Description:
-%% Test suite for the CDR encode/decode functions
-%%
-%%-----------------------------------------------------------------
--module(cdrcoding_11_SUITE).
-
-
--include("idl_output/Module.hrl").
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
--define(default_timeout, test_server:minutes(5)).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [{types, [],
- [do_register, null_type, void_type, principal_type,
- objref_type, struct_type, union_type, string_type,
- array_type, any_type, typecode_type, alias_type,
- exception_type, do_unregister]}].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-cases() ->
- [{group, types}, reply, cancel_request,
- close_connection, message_error].
-%% request, locate_request, locate_reply].
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-
-init_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) when is_list(Config) ->
- orber:jump_start(0),
- if
- is_list(Config) ->
- Config;
- true ->
- exit("Config not a list")
- end.
-
-end_per_suite(Config) when is_list(Config) ->
- orber:jump_stop(),
- Config.
-
-%%-----------------------------------------------------------------
-%% Test Case: type encoding tests
-%% Description: Just testing the complex types, the others are
-%% tested in the cdrlib SUITE.
-%%-----------------------------------------------------------------
-%types(Config) when list(Config) ->
-% 'oe_orber_test':'oe_register'(),
-% null_type(),
-% void_type(),
-% principal_type(),
-% objref_type(),
-% struct_type(),
-% union_type(),
-% string_type(),
-% array_type(),
-% any_type(),
-% typecode_type(),
-% alias_type(),
-% exception_type(),
-% 'oe_orber_test':'oe_unregister'(),
-% ok.
-
-do_register(Config) when is_list(Config) ->
- 'oe_orber_test':'oe_register'(),
- ok.
-
-do_unregister(Config) when is_list(Config) ->
- 'oe_orber_test':'oe_unregister'(),
- ok.
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: null
-%%-----------------------------------------------------------------
-null_type(Config) when is_list(Config) ->
- B = cdr_encode:enc_type(#giop_env{version = {1, 1}}, 'tk_null', 'null'),
- {'null', <<>>, _} = cdr_decode:dec_type('tk_null', {1, 1}, B, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: void
-%%-----------------------------------------------------------------
-void_type(Config) when is_list(Config) ->
- B = cdr_encode:enc_type(#giop_env{version = {1, 1}}, 'tk_void', 'ok'),
- {'ok', <<>>, _} = cdr_decode:dec_type('tk_void', {1, 1}, B, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: principal
-%%-----------------------------------------------------------------
-principal_type(Config) when is_list(Config) ->
- B0 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, 'tk_Principal', "principal"),
- {"principal", <<>>, _} = cdr_decode:dec_type('tk_Principal', {1, 1}, B0, 0, big),
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, 'tk_Principal', ""),
- {"", <<>>, _} = cdr_decode:dec_type('tk_Principal', {1, 1}, B1, 0, big),
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, 'tk_Principal', "principal"),
- {"principal", <<>>, _} =
- cdr_decode:dec_type('tk_Principal', {1, 1}, B2, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: object reference
-%%-----------------------------------------------------------------
-version() -> #'IIOP_Version'{major=1,minor=1}.
-
-objref(0) ->
- PB = #'IIOP_ProfileBody_1_1'{iiop_version=version(),
- host="my.hostname.org",
- port=4040,
- object_key="ExternalKey: which is an arbitary octet sequence",
- components=[]},
- TP = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB},
- #'IOP_IOR'{type_id="IDL:Module/Interface:1.0", profiles=[TP]};
-objref(1) ->
- K = corba_fake_mk_objkey("IDL:Module/Interface:1.0", key,
- list_to_pid("<0.100.0>")),
- PB = #'IIOP_ProfileBody_1_1'{iiop_version=version(),
- host="my.hostname.org",
- port=4040,
- object_key=K, components=[]},
- TP = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB},
- #'IOP_IOR'{type_id="IDL:Module/Interface:1.0", profiles=[TP]};
-objref(2) ->
- K = corba_fake_mk_objkey("IDL:Module/Interface:1.0", registered,
- list_to_atom("orber_nameservice")),
- PB = #'IIOP_ProfileBody_1_1'{iiop_version=version(),
- host="my.hostname.org",
- port=4040,
- object_key=K, components=[]},
- TP = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB},
- #'IOP_IOR'{type_id="IDL:Module/Interface:1.0", profiles=[TP]}.
-
-objref_type(Config) when is_list(Config) ->
- T = {'tk_objref', "IDL:Module/Interface:1.0", "Interface"},
- Objref0 = objref(0),
- B0 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T, Objref0),
- {Objref0, <<>>, _} = cdr_decode:dec_type(T, {1, 1}, B0, 0, big),
- Objref1 = objref(1),
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T, Objref1),
- {Objref1, <<>>, _} = cdr_decode:dec_type(T, {1, 1}, B1, 0, big),
- Objref2 = objref(2),
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T, Objref2),
- {Objref2, <<>>, _} = cdr_decode:dec_type(T, {1, 1}, B2, 0, big),
- ok.
-
-
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: struct
-%%-----------------------------------------------------------------
-struct_type(Config) when is_list(Config) ->
- T0 = {'tk_struct',"IDL:Module/Struct0:1.0", "Module_Struct0",
- [{"long", 'tk_long'}, {"short", 'tk_short'}, {"character", 'tk_char'}]},
- S0 = #'Module_Struct0'{l=-4711, s=17, c=$a},
- B0 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T0, S0),
- {S0, <<>>, _} = cdr_decode:dec_type(T0, {1, 1}, B0, 0, big),
-
- T1 = {'tk_struct', "IDL:Module/Struct1:1.0", "Module_Struct1",
- [{"string", {'tk_string', 0}}, {"ushort", 'tk_ushort'}, {"ulong", 'tk_ulong'}]},
- S1 = #'Module_Struct1'{s="Hi !!!!", us=17, ul=4711},
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T1, S1),
- {S1, <<>>, _} = cdr_decode:dec_type(T1, {1, 1}, B1, 0, big),
-
- T2 = {'tk_struct', "IDL:Module/Struct2:1.0", "Module_Struct2",
- [{"long_sequence", {'tk_sequence', 'tk_long', 0}},
- {"enum", {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum", ["horse", "pig", "cow"]}},
- {"octet", 'tk_octet'}]},
- S2 = #'Module_Struct2'{long_sequence=[4711, 350000, 0, -3030, -600000], e=cow, o=$X},
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T2, S2),
- {S2, <<>>, _} = cdr_decode:dec_type(T2, {1, 1}, B2, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: union
-%%-----------------------------------------------------------------
-union_type(Config) when is_list(Config) ->
- T0 = {'tk_union', "IDL:Module/Union:1.0", "Union", 'tk_short', 2,
- [{0, "First", 'tk_short'},
- {1, "Second", {'tk_string', 0}},
- {2, "Third", 'tk_char'}]},
- S0 = #'Module_Union'{label=1, value="Foo Bar !"},
- B0 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T0, S0),
- {S0, <<>>, _} = cdr_decode:dec_type(T0, {1, 1}, B0, 0, big),
- S1 = #'Module_Union'{label=0, value=-17},
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T0, S1),
- {S1, <<>>, _} = cdr_decode:dec_type(T0, {1, 1}, B1, 0, big),
- S2 = #'Module_Union'{label=2, value=$X},
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T0, S2),
- {S2, <<>>, _} = cdr_decode:dec_type(T0, {1, 1}, B2, 0, big),
- T1 = {'tk_union', "IDL:Module/Union1:1.0", "Union1",
- {'tk_enum', "IDL:Module/Enum:1.0",
- "Module_Enum", ["horse", "pig", "cow"]}, "pig",
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence', {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum', "IDL:Module/Enum1:1.0",
- "Module_Enum1", ["orange", "banana", "apple"]}}]},
- S3 = #'Module_Union1'{label=pig, value=["Foo", "Bar", "!"]},
- B3 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T1, S3),
- {S3, <<>>, _} = cdr_decode:dec_type(T1, {1, 1}, B3, 0, big),
- S4 = #'Module_Union1'{label=cow, value=apple},
- B4 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T1, S4),
- {S4, <<>>, _} = cdr_decode:dec_type(T1, {1, 1}, B4, 0, big),
- S5 = #'Module_Union1'{label=horse, value=17},
- B5 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T1, S5),
- {S5, <<>>, _} = cdr_decode:dec_type(T1, {1, 1}, B5, 0, big),
- T2 = {'tk_union', "IDL:Module/Union2:1.0", "Union2",
- {'tk_enum', "IDL:Module/Enum:1.0",
- "Module_Enum", ["horse", "pig", "cow"]}, "pig",
- [{"horse", "First", {'tk_array', 'tk_long', 3}},
- {"pig", "Second",
- {'tk_union', "IDL:Module/Union:1.0", "Union", 'tk_short', 2,
- [{0, "First", 'tk_short'},
- {1, "Second", {'tk_string', 0}},
- {2, "Third", 'tk_char'}]}},
- {"cow", "Third", {'tk_union', "IDL:Module/Union1:1.0", "Union1",
- {'tk_enum', "IDL:Module/Enum:1.0",
- "Module_Enum", ["horse", "pig", "cow"]}, "pig",
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence',
- {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum',
- "IDL:Module/Enum1:1.0",
- "Module_Enum1",
- ["orange", "banana",
- "apple"]}}]}}]},
- S6 = #'Module_Union2'{label=pig, value=#'Module_Union'{label=0, value=-17}},
- B6 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T2, S6),
- {S6, <<>>, _} = cdr_decode:dec_type(T2, {1, 1}, B6, 0, big),
- S7 = #'Module_Union2'{label=cow, value=#'Module_Union1'{label=pig,
- value=["Foo", "Bar", "!"]}},
- B7 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T2, S7),
- {S7, <<>>, _} = cdr_decode:dec_type(T2, {1, 1}, B7, 0, big),
- S8 = #'Module_Union2'{label=horse, value={-17, 1234567890, -987654321}},
- B8 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T2, S8),
- {S8, <<>>, _} = cdr_decode:dec_type(T2, {1, 1}, B8, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: string
-%%-----------------------------------------------------------------
-string_type(Config) when is_list(Config) ->
- S0 = "Foo Bar ???",
- B0 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, {'tk_string', 0}, S0),
- {S0, <<>>, _} = cdr_decode:dec_type({'tk_string', 0}, {1, 1}, B0, 0, big),
- S1 = "Yes, Foo Bar !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! more than 5000 characters",
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, {'tk_string', 0}, S1),
- {S1, <<>>, _} = cdr_decode:dec_type({'tk_string', 0}, {1, 1}, B1, 0, big),
- S2 = "",
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, {'tk_string', 0}, S2),
- {S2, <<>>, _} = cdr_decode:dec_type({'tk_string', 0}, {1, 1}, B2, 0, big),
- S3 = "\0",
- B3 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, {'tk_string', 0}, S3),
- {S3, <<>>, _} = cdr_decode:dec_type({'tk_string', 0}, {1, 1}, B3, 0, big),
- S4 = "~n",
- B4 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, {'tk_string', 0}, S4),
- {S4, <<>>, _} = cdr_decode:dec_type({'tk_string', 0}, {1, 1}, B4, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: array
-%%-----------------------------------------------------------------
-array_type(Config) when is_list(Config) ->
- T0 = {'tk_array', 'tk_long', 5},
- S0 = {-100, 0, 30000, -900100900, 123456789},
- B0 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T0, S0),
- {S0, <<>>, _} = cdr_decode:dec_type(T0, {1, 1}, B0, 0, big),
- T1 = {'tk_array', {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum", ["horse", "pig", "cow"]}, 2},
- S1 = {pig, cow},
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T1, S1),
- {S1, <<>>, _} = cdr_decode:dec_type(T1, {1, 1}, B1, 0, big),
- T2 = {'tk_array', {'tk_union', "IDL:Module/Union:1.0", "Union",
- {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum", ["horse", "pig", "cow"]}, "pig",
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence', {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum', "IDL:Module/Enum1:1.0",
- "Module_Enum1", ["orange", "banana", "apple"]}}]}, 2},
- S2 = {#'Module_Union'{label=cow, value=banana}, #'Module_Union'{label=pig, value=["This", "is", "a", "test", ""]}},
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T2, S2),
- {S2, <<>>, _} = cdr_decode:dec_type(T2, {1, 1}, B2, 0, big),
- T3 = {'tk_array', {'tk_objref', "IDL:Module/Interface:1.0", "Interface"}, 3},
- S3 = {objref(0), objref(1), objref(2)},
- B3 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T3, S3),
- {S3, <<>>, _} = cdr_decode:dec_type(T3, {1, 1}, B3, 0, big),
- ok.
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: TypeCode
-%%-----------------------------------------------------------------
-any_type(Config) when is_list(Config) ->
- T = 'tk_any',
- TC = {'tk_struct', "IDL:Module/Struct2:1.0", "Module_Struct2",
- [{"long_sequence", {'tk_sequence', 'tk_long', 0}},
- {"enum", {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum",
- ["horse", "pig", "cow"]}},
- {"octet", 'tk_octet'}]},
- S = #'Module_Struct2'{long_sequence=[4711, 350000, 0, -3030, -600000],
- e=cow, o=$X},
- Any = #any{typecode=TC,value=S},
- B = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T,Any),
- {Any, <<>>, _} = cdr_decode:dec_type(T, {1, 1}, B, 0, big),
- TC1 = {'tk_array', {'tk_union', "IDL:Module/Union:1.0", "Union",
- {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum",
- ["horse", "pig", "cow"]}, 1,
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence', {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum', "IDL:Module/Enum1:1.0",
- "Module_Enum1", ["orange", "banana",
- "apple"]}}]},2},
- S1 = {#'Module_Union'{label=cow, value=banana}, #'Module_Union'{label=pig, value=["This", "is", "a", "test", ""]}},
- Any1 = #any{typecode=TC1,value=S1},
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T,Any1),
- {Any1, <<>>, _} = cdr_decode:dec_type(T, {1, 1}, B1, 0, big),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: TypeCode
-%%-----------------------------------------------------------------
-typecode_type(Config) when is_list(Config) ->
- T = 'tk_TypeCode',
- TC = {'tk_array', {'tk_union', "IDL:Module/Union:1.0", "Union",
- {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum",
- ["horse", "pig", "cow"]}, 1,
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence', {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum', "IDL:Module/Enum1:1.0",
- "Module_Enum1", ["orange", "banana",
- "apple"]}}]}, 10},
- B = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T,TC),
- {TC, <<>>, _} = cdr_decode:dec_type(T, {1, 1}, B, 0, big),
- TC1 = {'tk_union', "IDL:Module/Union2:1.0", "Union2",
- {'tk_enum', "IDL:Module/Enum:1.0",
- "Module_Enum", ["horse", "pig", "cow"]}, 2,
- [{"horse", "First", 'tk_long'},
- {"pig", "Second",
- {'tk_union', "IDL:Module/Union:1.0", "Union", 'tk_short', 2,
- [{0, "First", 'tk_short'},
- {1, "Second", {'tk_string', 0}},
- {2, "Third", 'tk_char'}]}},
- {"cow", "Third", {'tk_union', "IDL:Module/Union1:1.0", "Union1",
- {'tk_enum', "IDL:Module/Enum:1.0",
- "Module_Enum", ["horse", "pig", "cow"]}, 2,
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence',
- {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum',
- "IDL:Module/Enum1:1.0",
- "Module_Enum1",
- ["orange", "banana",
- "apple"]}}]}}]},
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T, TC1),
- {TC1, <<>>, _} = cdr_decode:dec_type(T, {1, 1}, B1, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: TypeCode
-%%-----------------------------------------------------------------
-alias_type(Config) when is_list(Config) ->
- T = {'tk_alias', "IDL:Module/Alias:1.0", "Alias",
- {'tk_struct', "IDL:Module/Struct2:1.0", "Module_Struct2",
- [{"long_sequence", {'tk_sequence', 'tk_long', 0}},
- {"enum", {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum",
- ["horse", "pig", "cow"]}},
- {"octet", 'tk_octet'}]}},
- S = #'Module_Struct2'{long_sequence=[4711, 350000, 0, -3030, -600000],
- e=cow, o=$X},
- B = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T,S),
- {S, <<>>, _} = cdr_decode:dec_type(T, {1, 1}, B, 0, big),
- T1 = {'tk_alias', "IDL:Module/Alias1:1.0", "Alias1",
- {'tk_sequence', {'tk_union', "IDL:Module/Union:1.0", "Union",
- {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum",
- ["horse", "pig", "cow"]}, 2,
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence', {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum', "IDL:Module/Enum1:1.0",
- "Module_Enum1", ["orange", "banana",
- "apple"]}}]},0}},
- S1 = [#'Module_Union'{label=cow, value=banana}, #'Module_Union'{label=pig, value=["This", "is", "a", "test", ""]}],
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T1, S1),
- {S1, <<>>, _} = cdr_decode:dec_type(T1, {1, 1}, B1, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: exception
-%%-----------------------------------------------------------------
-exception_type(Config) when is_list(Config) ->
- system_exceptions(),
- user_exceptions(),
- ok.
-
-system_exceptions() ->
- E = #'UNKNOWN'{completion_status=?COMPLETED_YES},
- {system_exception, T, E} = orber_exceptions:get_def(E),
- B = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T,E),
- {E, _} = cdr_decode:dec_system_exception({1, 1}, B, 0, big),
- E1 = #'INV_OBJREF'{completion_status=?COMPLETED_NO},
- {system_exception, T1, E1} = orber_exceptions:get_def(E1),
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T1,E1),
- {E1, _} = cdr_decode:dec_system_exception({1, 1}, B1, 0, big),
- E2 = #'BAD_OPERATION'{completion_status=?COMPLETED_NO},
- {system_exception, T2, E2} = orber_exceptions:get_def(E2),
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T2,E2),
- {E2, _} = cdr_decode:dec_system_exception({1, 1}, B2, 0, big),
- E3 = #'INTF_REPOS'{completion_status=?COMPLETED_MAYBE},
- {system_exception, T3, E3} = orber_exceptions:get_def(E3),
- B3 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T3,E3),
- {E3, _} = cdr_decode:dec_system_exception({1, 1}, B3, 0, big),
- ok.
-
-user_exceptions() ->
- E = #'Module_Except1'{rest_of_name=["I","am","testing","exceptions"], why="Error"},
- {user_exception, T, E} = orber_exceptions:get_def(E),
- B = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T, E),
- {E, _} = cdr_decode:dec_user_exception({1, 1}, B, 0, big),
- E1 = #'Module_Except2'{e=banana,
- s=#'Module_Struct2'{long_sequence=[12,-4040,
- 1234567898],
- e=horse,
- o=$a}},
- {user_exception, T1, E1} = orber_exceptions:get_def(E1),
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T1, E1),
- {E1, _} = cdr_decode:dec_user_exception({1, 1}, B1, 0, big),
- E2 = #'Module_Except3'{u=#'Module_Union1'{label=pig,value=["high","and","low"]},s=1313, o=objref(0)},
- {user_exception, T2, E2} = orber_exceptions:get_def(E2),
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T2, E2),
- {E2, _} = cdr_decode:dec_user_exception({1, 1}, B2, 0, big),
- E3 = #'Module_Except4'{},
- {user_exception, T3, E3} = orber_exceptions:get_def(E3),
- B3 = cdr_encode:enc_type(#giop_env{version = {1, 1}}, T3, E3),
- {E3, _} = cdr_decode:dec_user_exception({1, 1}, B3, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: request encoding test
-%% Description: Precondition the stack must be started so the
-%% objectkey is valid.
-%%-----------------------------------------------------------------
-%request(_) ->
-% exit(not_implemented).
-
-%%-----------------------------------------------------------------
-%% Test Case: reply encoding test
-%% Description:
-%%-----------------------------------------------------------------
-reply(Config) when is_list(Config) ->
- R = #reply_header{service_context=[], request_id=1,
- reply_status='no_exception'},
- B = cdr_encode:enc_reply(#giop_env{version = {1, 1}, request_id = 1,
- reply_status = 'no_exception',
- tc = {'tk_long', [], [{'tk_sequence',
- {'tk_string', 0}, 0}]},
- result = 1200, parameters = [["foo","Bar"]],
- ctx = []}),
- {R, 1200, [["foo","Bar"]]} =
- cdr_decode:dec_message({'tk_long', [], [{'tk_sequence', {'tk_string', 0},0}]},
- B),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: cancel_request encoding test
-%% Description:
-%%-----------------------------------------------------------------
-cancel_request(Config) when is_list(Config) ->
- R = #cancel_request_header{request_id=1},
- B = cdr_encode:enc_cancel_request(#giop_env{version = {1, 1},
- request_id = 1}),
- R = cdr_decode:dec_message([], B),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: locate_request encoding test
-%% Description:
-%%-----------------------------------------------------------------
-locate_request(Config) when is_list(Config) ->
- io:format("Function not imlpemented yet"),
- exit(not_implemented).
-
-%%-----------------------------------------------------------------
-%% Test Case: locate_reply encoding test
-%% Description:
-%%-----------------------------------------------------------------
-locate_reply(Config) when is_list(Config) ->
- io:format("Function not imlpemented yet"),
- exit(not_implemented).
-
-%%-----------------------------------------------------------------
-%% Test Case: close_connection encoding test
-%% Description:
-%%-----------------------------------------------------------------
-close_connection(Config) when is_list(Config) ->
- B = cdr_encode:enc_close_connection(#giop_env{version = {1, 1}}),
- 'close_connection' = cdr_decode:dec_message([], B),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: message_error encoding test
-%% Description:
-%%-----------------------------------------------------------------
-message_error(Config) when is_list(Config) ->
- B = cdr_encode:enc_message_error(#giop_env{version = {1, 1}}),
- 'message_error' = cdr_decode:dec_message([], B),
- ok.
-
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-corba_fake_mk_objkey(Id, 'key', Pid) when is_pid(Pid) ->
- Key = make_objkey(),
- {list_to_binary(Id), 'key', Key, term_to_binary(undefined),
- term_to_binary(undefined), term_to_binary(undefined)};
-corba_fake_mk_objkey(Id, 'key', RegName) when is_atom(RegName) ->
- Key = term_to_binary(RegName),
- {list_to_binary(Id), 'key', Key, term_to_binary(undefined),
- term_to_binary(undefined), term_to_binary(undefined)};
-corba_fake_mk_objkey(Id, 'registered', RegName) when is_atom(RegName) ->
- {list_to_binary(Id), 'registered', RegName, term_to_binary(undefined),
- term_to_binary(undefined), term_to_binary(undefined)}.
-
-make_objkey() ->
- term_to_binary({{erlang:system_time(),
- erlang:unique_integer()},
- node()}).
diff --git a/lib/orber/test/cdrcoding_12_SUITE.erl b/lib/orber/test/cdrcoding_12_SUITE.erl
deleted file mode 100644
index 13178b7774..0000000000
--- a/lib/orber/test/cdrcoding_12_SUITE.erl
+++ /dev/null
@@ -1,575 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%%
-%% Description:
-%% Test suite for the CDR encode/decode functions
-%%
-%%-----------------------------------------------------------------
-
--module(cdrcoding_12_SUITE).
-
--include("idl_output/Module.hrl").
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
--define(default_timeout, test_server:minutes(5)).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [{types, [],
- [do_register, null_type, void_type, principal_type,
- objref_type, struct_type, union_type, string_type,
- array_type, any_type, typecode_type, alias_type,
- exception_type, do_unregister]}].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-cases() ->
- [{group, types}, reply, cancel_request,
- close_connection, message_error].
-%% request, locate_request, locate_reply].
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-
-init_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) when is_list(Config) ->
- orber:jump_start(0),
- if
- is_list(Config) ->
- Config;
- true ->
- exit("Config not a list")
- end.
-
-end_per_suite(Config) when is_list(Config) ->
- orber:jump_stop(),
- Config.
-
-%%-----------------------------------------------------------------
-%% Test Case: type encoding tests
-%% Description: Just testing the complex types, the others are
-%% tested in the cdrlib SUITE.
-%%-----------------------------------------------------------------
-
-do_register(Config) when is_list(Config) ->
- 'oe_orber_test':'oe_register'(),
- ok.
-
-do_unregister(Config) when is_list(Config) ->
- 'oe_orber_test':'oe_unregister'(),
- ok.
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: null
-%%-----------------------------------------------------------------
-null_type(Config) when is_list(Config) ->
- B = cdr_encode:enc_type(#giop_env{version = {1, 2}}, 'tk_null', 'null'),
- {'null', <<>>, _} = cdr_decode:dec_type('tk_null', {1, 2}, B, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: void
-%%-----------------------------------------------------------------
-void_type(Config) when is_list(Config) ->
- B = cdr_encode:enc_type(#giop_env{version = {1, 2}}, 'tk_void', 'ok'),
- {'ok', <<>>, _} = cdr_decode:dec_type('tk_void', {1, 2}, B, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: principal
-%%-----------------------------------------------------------------
-principal_type(Config) when is_list(Config) ->
- B0 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, 'tk_Principal', "principal"),
- {"principal", <<>>, _} = cdr_decode:dec_type('tk_Principal', {1, 2}, B0, 0, big),
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, 'tk_Principal', ""),
- {"", <<>>, _} = cdr_decode:dec_type('tk_Principal', {1, 2}, B1, 0, big),
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, 'tk_Principal', "principal"),
- {"principal", <<>>, _} =
- cdr_decode:dec_type('tk_Principal', {1, 2}, B2, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: object reference
-%%-----------------------------------------------------------------
-version() -> #'IIOP_Version'{major=1,minor=2}.
-
-objref(0) ->
- PB = #'IIOP_ProfileBody_1_1'{iiop_version=version(),
- host="my.hostname.org",
- port=4040,
- object_key="ExternalKey: which is an arbitary octet sequence",
- components=[]},
- TP = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB},
- #'IOP_IOR'{type_id="IDL:Module/Interface:1.0", profiles=[TP]};
-objref(1) ->
- K = corba_fake_mk_objkey("IDL:Module/Interface:1.0", key,
- list_to_pid("<0.100.0>")),
- PB = #'IIOP_ProfileBody_1_1'{iiop_version=version(),
- host="my.hostname.org",
- port=4040,
- object_key=K, components=[]},
- TP = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB},
- #'IOP_IOR'{type_id="IDL:Module/Interface:1.0", profiles=[TP]};
-objref(2) ->
- K = corba_fake_mk_objkey("IDL:Module/Interface:1.0", registered,
- list_to_atom("orber_nameservice")),
- PB = #'IIOP_ProfileBody_1_1'{iiop_version=version(),
- host="my.hostname.org",
- port=4040,
- object_key=K, components=[]},
- TP = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB},
- #'IOP_IOR'{type_id="IDL:Module/Interface:1.0", profiles=[TP]}.
-
-objref_type(Config) when is_list(Config) ->
- T = {'tk_objref', "IDL:Module/Interface:1.0", "Interface"},
- Objref0 = objref(0),
- B0 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T, Objref0),
- {Objref0, <<>>, _} = cdr_decode:dec_type(T, {1, 2}, B0, 0, big),
- Objref1 = objref(1),
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T, Objref1),
- {Objref1, <<>>, _} = cdr_decode:dec_type(T, {1, 2}, B1, 0, big),
- Objref2 = objref(2),
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T, Objref2),
- {Objref2, <<>>, _} = cdr_decode:dec_type(T, {1, 2}, B2, 0, big),
- ok.
-
-
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: struct
-%%-----------------------------------------------------------------
-struct_type(Config) when is_list(Config) ->
- T0 = {'tk_struct',"IDL:Module/Struct0:1.0", "Module_Struct0",
- [{"long", 'tk_long'}, {"short", 'tk_short'}, {"character", 'tk_char'}]},
- S0 = #'Module_Struct0'{l=-4711, s=17, c=$a},
- B0 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T0, S0),
- {S0, <<>>, _} = cdr_decode:dec_type(T0, {1, 2}, B0, 0, big),
-
- T1 = {'tk_struct', "IDL:Module/Struct1:1.0", "Module_Struct1",
- [{"string", {'tk_string', 0}}, {"ushort", 'tk_ushort'}, {"ulong", 'tk_ulong'}]},
- S1 = #'Module_Struct1'{s="Hi !!!!", us=17, ul=4711},
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T1, S1),
- {S1, <<>>, _} = cdr_decode:dec_type(T1, {1, 2}, B1, 0, big),
-
- T2 = {'tk_struct', "IDL:Module/Struct2:1.0", "Module_Struct2",
- [{"long_sequence", {'tk_sequence', 'tk_long', 0}},
- {"enum", {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum", ["horse", "pig", "cow"]}},
- {"octet", 'tk_octet'}]},
- S2 = #'Module_Struct2'{long_sequence=[4711, 350000, 0, -3030, -600000], e=cow, o=$X},
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T2, S2),
- {S2, <<>>, _} = cdr_decode:dec_type(T2, {1, 2}, B2, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: union
-%%-----------------------------------------------------------------
-union_type(Config) when is_list(Config) ->
- T0 = {'tk_union', "IDL:Module/Union:1.0", "Union", 'tk_short', 2,
- [{0, "First", 'tk_short'},
- {1, "Second", {'tk_string', 0}},
- {2, "Third", 'tk_char'}]},
- S0 = #'Module_Union'{label=1, value="Foo Bar !"},
- B0 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T0, S0),
- {S0, <<>>, _} = cdr_decode:dec_type(T0, {1, 2}, B0, 0, big),
- S1 = #'Module_Union'{label=0, value=-17},
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T0, S1),
- {S1, <<>>, _} = cdr_decode:dec_type(T0, {1, 2}, B1, 0, big),
- S2 = #'Module_Union'{label=2, value=$X},
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T0, S2),
- {S2, <<>>, _} = cdr_decode:dec_type(T0, {1, 2}, B2, 0, big),
- T1 = {'tk_union', "IDL:Module/Union1:1.0", "Union1",
- {'tk_enum', "IDL:Module/Enum:1.0",
- "Module_Enum", ["horse", "pig", "cow"]}, "pig",
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence', {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum', "IDL:Module/Enum1:1.0",
- "Module_Enum1", ["orange", "banana", "apple"]}}]},
- S3 = #'Module_Union1'{label=pig, value=["Foo", "Bar", "!"]},
- B3 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T1, S3),
- {S3, <<>>, _} = cdr_decode:dec_type(T1, {1, 2}, B3, 0, big),
- S4 = #'Module_Union1'{label=cow, value=apple},
- B4 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T1, S4),
- {S4, <<>>, _} = cdr_decode:dec_type(T1, {1, 2}, B4, 0, big),
- S5 = #'Module_Union1'{label=horse, value=17},
- B5 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T1, S5),
- {S5, <<>>, _} = cdr_decode:dec_type(T1, {1, 2}, B5, 0, big),
- T2 = {'tk_union', "IDL:Module/Union2:1.0", "Union2",
- {'tk_enum', "IDL:Module/Enum:1.0",
- "Module_Enum", ["horse", "pig", "cow"]}, "pig",
- [{"horse", "First", {'tk_array', 'tk_long', 3}},
- {"pig", "Second",
- {'tk_union', "IDL:Module/Union:1.0", "Union", 'tk_short', 2,
- [{0, "First", 'tk_short'},
- {1, "Second", {'tk_string', 0}},
- {2, "Third", 'tk_char'}]}},
- {"cow", "Third", {'tk_union', "IDL:Module/Union1:1.0", "Union1",
- {'tk_enum', "IDL:Module/Enum:1.0",
- "Module_Enum", ["horse", "pig", "cow"]}, "pig",
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence',
- {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum',
- "IDL:Module/Enum1:1.0",
- "Module_Enum1",
- ["orange", "banana",
- "apple"]}}]}}]},
- S6 = #'Module_Union2'{label=pig, value=#'Module_Union'{label=0, value=-17}},
- B6 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T2, S6),
- {S6, <<>>, _} = cdr_decode:dec_type(T2, {1, 2}, B6, 0, big),
- S7 = #'Module_Union2'{label=cow, value=#'Module_Union1'{label=pig,
- value=["Foo", "Bar", "!"]}},
- B7 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T2, S7),
- {S7, <<>>, _} = cdr_decode:dec_type(T2, {1, 2}, B7, 0, big),
- S8 = #'Module_Union2'{label=horse, value={-17, 1234567890, -987654321}},
- B8 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T2, S8),
- {S8, <<>>, _} = cdr_decode:dec_type(T2, {1, 2}, B8, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: string
-%%-----------------------------------------------------------------
-string_type(Config) when is_list(Config) ->
- S0 = "Foo Bar ???",
- B0 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, {'tk_string', 0}, S0),
- {S0, <<>>, _} = cdr_decode:dec_type({'tk_string', 0}, {1, 2}, B0, 0, big),
- S1 = "Yes, Foo Bar !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! more than 5000 characters",
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, {'tk_string', 0}, S1),
- {S1, <<>>, _} = cdr_decode:dec_type({'tk_string', 0}, {1, 2}, B1, 0, big),
- S2 = "",
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, {'tk_string', 0}, S2),
- {S2, <<>>, _} = cdr_decode:dec_type({'tk_string', 0}, {1, 2}, B2, 0, big),
- S3 = "\0",
- B3 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, {'tk_string', 0}, S3),
- {S3, <<>>, _} = cdr_decode:dec_type({'tk_string', 0}, {1, 2}, B3, 0, big),
- S4 = "~n",
- B4 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, {'tk_string', 0}, S4),
- {S4, <<>>, _} = cdr_decode:dec_type({'tk_string', 0}, {1, 2}, B4, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: array
-%%-----------------------------------------------------------------
-array_type(Config) when is_list(Config) ->
- T0 = {'tk_array', 'tk_long', 5},
- S0 = {-100, 0, 30000, -900100900, 123456789},
- B0 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T0, S0),
- {S0, <<>>, _} = cdr_decode:dec_type(T0, {1, 2}, B0, 0, big),
- T1 = {'tk_array', {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum", ["horse", "pig", "cow"]}, 2},
- S1 = {pig, cow},
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T1, S1),
- {S1, <<>>, _} = cdr_decode:dec_type(T1, {1, 2}, B1, 0, big),
- T2 = {'tk_array', {'tk_union', "IDL:Module/Union:1.0", "Union",
- {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum", ["horse", "pig", "cow"]}, "pig",
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence', {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum', "IDL:Module/Enum1:1.0",
- "Module_Enum1", ["orange", "banana", "apple"]}}]}, 2},
- S2 = {#'Module_Union'{label=cow, value=banana}, #'Module_Union'{label=pig, value=["This", "is", "a", "test", ""]}},
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T2, S2),
- {S2, <<>>, _} = cdr_decode:dec_type(T2, {1, 2}, B2, 0, big),
- T3 = {'tk_array', {'tk_objref', "IDL:Module/Interface:1.0", "Interface"}, 3},
- S3 = {objref(0), objref(1), objref(2)},
- B3 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T3, S3),
- {S3, <<>>, _} = cdr_decode:dec_type(T3, {1, 2}, B3, 0, big),
- ok.
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: TypeCode
-%%-----------------------------------------------------------------
-any_type(Config) when is_list(Config) ->
- T = 'tk_any',
- TC = {'tk_struct', "IDL:Module/Struct2:1.0", "Module_Struct2",
- [{"long_sequence", {'tk_sequence', 'tk_long', 0}},
- {"enum", {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum",
- ["horse", "pig", "cow"]}},
- {"octet", 'tk_octet'}]},
- S = #'Module_Struct2'{long_sequence=[4711, 350000, 0, -3030, -600000],
- e=cow, o=$X},
- Any = #any{typecode=TC,value=S},
- B = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T,Any),
- {Any, <<>>, _} = cdr_decode:dec_type(T, {1, 2}, B, 0, big),
- TC1 = {'tk_array', {'tk_union', "IDL:Module/Union:1.0", "Union",
- {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum",
- ["horse", "pig", "cow"]}, 1,
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence', {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum', "IDL:Module/Enum1:1.0",
- "Module_Enum1", ["orange", "banana",
- "apple"]}}]},2},
- S1 = {#'Module_Union'{label=cow, value=banana}, #'Module_Union'{label=pig, value=["This", "is", "a", "test", ""]}},
- Any1 = #any{typecode=TC1,value=S1},
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T,Any1),
- {Any1, <<>>, _} = cdr_decode:dec_type(T, {1, 2}, B1, 0, big),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: TypeCode
-%%-----------------------------------------------------------------
-typecode_type(Config) when is_list(Config) ->
- T = 'tk_TypeCode',
- TC = {'tk_array', {'tk_union', "IDL:Module/Union:1.0", "Union",
- {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum",
- ["horse", "pig", "cow"]}, 1,
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence', {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum', "IDL:Module/Enum1:1.0",
- "Module_Enum1", ["orange", "banana",
- "apple"]}}]}, 10},
- B = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T,TC),
- {TC, <<>>, _} = cdr_decode:dec_type(T, {1, 2}, B, 0, big),
- TC1 = {'tk_union', "IDL:Module/Union2:1.0", "Union2",
- {'tk_enum', "IDL:Module/Enum:1.0",
- "Module_Enum", ["horse", "pig", "cow"]}, 2,
- [{"horse", "First", 'tk_long'},
- {"pig", "Second",
- {'tk_union', "IDL:Module/Union:1.0", "Union", 'tk_short', 2,
- [{0, "First", 'tk_short'},
- {1, "Second", {'tk_string', 0}},
- {2, "Third", 'tk_char'}]}},
- {"cow", "Third", {'tk_union', "IDL:Module/Union1:1.0", "Union1",
- {'tk_enum', "IDL:Module/Enum:1.0",
- "Module_Enum", ["horse", "pig", "cow"]}, 2,
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence',
- {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum',
- "IDL:Module/Enum1:1.0",
- "Module_Enum1",
- ["orange", "banana",
- "apple"]}}]}}]},
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T, TC1),
- {TC1, <<>>, _} = cdr_decode:dec_type(T, {1, 2}, B1, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: TypeCode
-%%-----------------------------------------------------------------
-alias_type(Config) when is_list(Config) ->
- T = {'tk_alias', "IDL:Module/Alias:1.0", "Alias",
- {'tk_struct', "IDL:Module/Struct2:1.0", "Module_Struct2",
- [{"long_sequence", {'tk_sequence', 'tk_long', 0}},
- {"enum", {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum",
- ["horse", "pig", "cow"]}},
- {"octet", 'tk_octet'}]}},
- S = #'Module_Struct2'{long_sequence=[4711, 350000, 0, -3030, -600000],
- e=cow, o=$X},
- B = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T,S),
- {S, <<>>, _} = cdr_decode:dec_type(T, {1, 2}, B, 0, big),
- T1 = {'tk_alias', "IDL:Module/Alias1:1.0", "Alias1",
- {'tk_sequence', {'tk_union', "IDL:Module/Union:1.0", "Union",
- {'tk_enum', "IDL:Module/Enum:1.0", "Module_Enum",
- ["horse", "pig", "cow"]}, 2,
- [{"horse", "First", 'tk_ushort'},
- {"pig", "Second", {'tk_sequence', {'tk_string', 0}, 0}},
- {"cow", "Third", {'tk_enum', "IDL:Module/Enum1:1.0",
- "Module_Enum1", ["orange", "banana",
- "apple"]}}]},0}},
- S1 = [#'Module_Union'{label=cow, value=banana}, #'Module_Union'{label=pig, value=["This", "is", "a", "test", ""]}],
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T1, S1),
- {S1, <<>>, _} = cdr_decode:dec_type(T1, {1, 2}, B1, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Encode/decode test of type: exception
-%%-----------------------------------------------------------------
-exception_type(Config) when is_list(Config) ->
- system_exceptions(),
- user_exceptions(),
- ok.
-
-system_exceptions() ->
- E = #'UNKNOWN'{completion_status=?COMPLETED_YES},
- {system_exception, T, E} = orber_exceptions:get_def(E),
- B = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T,E),
- {E, _} = cdr_decode:dec_system_exception({1, 2}, B, 0, big),
- E1 = #'INV_OBJREF'{completion_status=?COMPLETED_NO},
- {system_exception, T1, E1} = orber_exceptions:get_def(E1),
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T1,E1),
- {E1, _} = cdr_decode:dec_system_exception({1, 2}, B1, 0, big),
- E2 = #'BAD_OPERATION'{completion_status=?COMPLETED_NO},
- {system_exception, T2, E2} = orber_exceptions:get_def(E2),
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T2,E2),
- {E2, _} = cdr_decode:dec_system_exception({1, 2}, B2, 0, big),
- E3 = #'INTF_REPOS'{completion_status=?COMPLETED_MAYBE},
- {system_exception, T3, E3} = orber_exceptions:get_def(E3),
- B3 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T3,E3),
- {E3, _} = cdr_decode:dec_system_exception({1, 2}, B3, 0, big),
- ok.
-
-user_exceptions() ->
- E = #'Module_Except1'{rest_of_name=["I","am","testing","exceptions"], why="Error"},
- {user_exception, T, E} = orber_exceptions:get_def(E),
- B = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T, E),
- {E, _} = cdr_decode:dec_user_exception({1, 2}, B, 0, big),
- E1 = #'Module_Except2'{e=banana,
- s=#'Module_Struct2'{long_sequence=[12,-4040,
- 1234567898],
- e=horse,
- o=$a}},
- {user_exception, T1, E1} = orber_exceptions:get_def(E1),
- B1 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T1, E1),
- {E1, _} = cdr_decode:dec_user_exception({1, 2}, B1, 0, big),
- E2 = #'Module_Except3'{u=#'Module_Union1'{label=pig,value=["high","and","low"]},s=1313, o=objref(0)},
- {user_exception, T2, E2} = orber_exceptions:get_def(E2),
- B2 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T2, E2),
- {E2, _} = cdr_decode:dec_user_exception({1, 2}, B2, 0, big),
- E3 = #'Module_Except4'{},
- {user_exception, T3, E3} = orber_exceptions:get_def(E3),
- B3 = cdr_encode:enc_type(#giop_env{version = {1, 2}}, T3, E3),
- {E3, _} = cdr_decode:dec_user_exception({1, 2}, B3, 0, big),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: request encoding test
-%% Description: Precondition the stack must be started so the
-%% objectkey is valid.
-%%-----------------------------------------------------------------
-%request(_) ->
-% exit(not_implemented).
-
-%%-----------------------------------------------------------------
-%% Test Case: reply encoding test
-%% Description:
-%%-----------------------------------------------------------------
-reply(Config) when is_list(Config) ->
- R = #reply_header{service_context=[], request_id=1,
- reply_status='no_exception'},
- B = cdr_encode:enc_reply(#giop_env{version = {1, 2}, request_id = 1,
- reply_status = 'no_exception',
- tc = {'tk_long', [], [{'tk_sequence',
- {'tk_string', 0}, 0}]},
- result = 1200,
- parameters = [["foo","Bar"]],
- ctx = []}),
-
- {R, 1200, [["foo","Bar"]]} =
- cdr_decode:dec_message({'tk_long', [], [{'tk_sequence', {'tk_string', 0},0}]},
- B),
-
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: cancel_request encoding test
-%% Description:
-%%-----------------------------------------------------------------
-cancel_request(Config) when is_list(Config) ->
- R = #cancel_request_header{request_id=1},
- B = cdr_encode:enc_cancel_request(#giop_env{version = {1, 2},
- request_id = 1}),
- R = cdr_decode:dec_message([], B),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: locate_request encoding test
-%% Description:
-%%-----------------------------------------------------------------
-locate_request(Config) when is_list(Config) ->
- io:format("Function not imlpemented yet"),
- exit(not_implemented).
-
-%%-----------------------------------------------------------------
-%% Test Case: locate_reply encoding test
-%% Description:
-%%-----------------------------------------------------------------
-locate_reply(Config) when is_list(Config) ->
- io:format("Function not imlpemented yet"),
- exit(not_implemented).
-
-%%-----------------------------------------------------------------
-%% Test Case: close_connection encoding test
-%% Description:
-%%-----------------------------------------------------------------
-close_connection(Config) when is_list(Config) ->
- B = cdr_encode:enc_close_connection(#giop_env{version = {1, 2}}),
- 'close_connection' = cdr_decode:dec_message([], B),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: message_error encoding test
-%% Description:
-%%-----------------------------------------------------------------
-message_error(Config) when is_list(Config) ->
- B = cdr_encode:enc_message_error(#giop_env{version = {1, 2}}),
- 'message_error' = cdr_decode:dec_message([], B),
- ok.
-
-
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-corba_fake_mk_objkey(Id, 'key', Pid) when is_pid(Pid) ->
- Key = make_objkey(),
- {list_to_binary(Id), 'key', Key, term_to_binary(undefined),
- term_to_binary(undefined), term_to_binary(undefined)};
-corba_fake_mk_objkey(Id, 'key', RegName) when is_atom(RegName) ->
- Key = term_to_binary(RegName),
- {list_to_binary(Id), 'key', Key, term_to_binary(undefined),
- term_to_binary(undefined), term_to_binary(undefined)};
-corba_fake_mk_objkey(Id, 'registered', RegName) when is_atom(RegName) ->
- {list_to_binary(Id), 'registered', RegName, term_to_binary(undefined),
- term_to_binary(undefined), term_to_binary(undefined)}.
-
-make_objkey() ->
- term_to_binary({{erlang:system_time(),
- erlang:unique_integer()},
- node()}).
diff --git a/lib/orber/test/cdrlib_SUITE.erl b/lib/orber/test/cdrlib_SUITE.erl
deleted file mode 100644
index 93adc861c5..0000000000
--- a/lib/orber/test/cdrlib_SUITE.erl
+++ /dev/null
@@ -1,479 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%%
-%% Description:
-%% Test suite for the CDR basic type encode/decode functions
-%%
-%%-----------------------------------------------------------------
--module(cdrlib_SUITE).
-
--include_lib("common_test/include/ct.hrl").
-
--define(default_timeout, test_server:minutes(3)).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [short, ushort, long, ulong, longlong, ulonglong,
- boolean, character, octet, float, double, enum].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: short integer test
-%% Description:
-%%-----------------------------------------------------------------
-short(_) ->
- short_big_loop([-32768, -4040, -1, 0, 4040, 32767]),
- short_little_loop([-32768, -4040, -1, 0, 4040, 32767]),
- bad_short().
-
-short_big_loop([]) ->
- ok;
-short_big_loop([X |List]) ->
- [CodedType] = cdrlib:enc_short(X, []),
- {X, <<>>} = cdrlib:dec_short(big, CodedType),
- short_big_loop(List),
- ok.
-
-short_little_loop([]) ->
- ok;
-short_little_loop([X |List]) ->
- CodedType = enc_short_little(X, []),
- {X, <<>>} = cdrlib:dec_short(little, CodedType),
- short_little_loop(List),
- ok.
-
-enc_short_little(X, Message) ->
- list_to_binary([(X) band 16#ff, ((X) bsr 8) band 16#ff | Message]).
-
-bad_short() ->
- {'EXCEPTION', _} = (catch cdrlib:enc_short('atom', [])),
- [CodedType] = cdrlib:enc_char($a, []),
- {'EXIT', _} = (catch cdrlib:dec_short(big, CodedType)),
- ok.
-%%-----------------------------------------------------------------
-%% Test Case: unsigned short integer test
-%% Description:
-%%-----------------------------------------------------------------
-ushort(_) ->
- ushort_big_loop([0, 4040, 65535]),
- ushort_little_loop([0, 4040, 65535]),
- bad_ushort().
-
-ushort_big_loop([]) ->
- ok;
-ushort_big_loop([X |List]) ->
- [CodedType] = cdrlib:enc_unsigned_short(X, []),
- {X, <<>>} = cdrlib:dec_unsigned_short(big, CodedType),
- ushort_big_loop(List),
- ok.
-
-ushort_little_loop([]) ->
- ok;
-ushort_little_loop([X |List]) ->
- CodedType = enc_ushort_little(X, []),
- {X, <<>>} = cdrlib:dec_unsigned_short(little, CodedType),
- ushort_little_loop(List),
- ok.
-
-enc_ushort_little(X, Message) ->
- list_to_binary([(X) band 16#ff, ((X) bsr 8) band 16#ff | Message]).
-
-bad_ushort() ->
- ok.
-%%-----------------------------------------------------------------
-%% Test Case: long integer test
-%% Description:
-%%-----------------------------------------------------------------
-long(_) ->
- long_big_loop([-2147483648, -40404040, -32768, -4040, -1,
- 0, 4040, 32767, 40404040, 2147483647]),
- long_little_loop([-2147483648, -40404040, -32768, -4040, -1,
- 0, 4040, 32767, 40404040, 2147483647]),
- bad_long().
-
-
-long_big_loop([]) ->
- ok;
-long_big_loop([X |List]) ->
- [CodedType] = cdrlib:enc_long(X, []),
- {X, <<>>} = cdrlib:dec_long(big, CodedType),
- long_big_loop(List),
- ok.
-
-long_little_loop([]) ->
- ok;
-long_little_loop([X |List]) ->
- CodedType = enc_long_little(X, []),
- {X, <<>>} = cdrlib:dec_long(little, CodedType),
- long_little_loop(List),
- ok.
-
-enc_long_little(X, Message) ->
- list_to_binary([(X) band 16#ff, ((X) bsr 8) band 16#ff, ((X) bsr 16) band 16#ff,
- ((X) bsr 24) band 16#ff | Message]).
-
-bad_long() ->
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: unsigned long integer test
-%% Description:
-%%-----------------------------------------------------------------
-ulong(_) ->
- ulong_big_loop([0, 4040, 65535, 40404040, 2147483647, 4294967295]),
- ulong_little_loop([0, 4040, 65535, 40404040, 2147483647, 4294967295]),
- bad_ulong().
-
-
-ulong_big_loop([]) ->
- ok;
-ulong_big_loop([X |List]) ->
- [CodedType] = cdrlib:enc_unsigned_long(X, []),
- {X, <<>>} = cdrlib:dec_unsigned_long(big, CodedType),
- ulong_big_loop(List),
- ok.
-
-ulong_little_loop([]) ->
- ok;
-ulong_little_loop([X |List]) ->
- CodedType = enc_ulong_little(X, []),
- {X, <<>>} = cdrlib:dec_unsigned_long(little, CodedType),
- ulong_little_loop(List),
- ok.
-
-enc_ulong_little(X, Message) ->
- list_to_binary([(X) band 16#ff, ((X) bsr 8) band 16#ff, ((X) bsr 16) band 16#ff,
- ((X) bsr 24) band 16#ff | Message]).
-
-
-bad_ulong() ->
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: long integer test
-%% Description:
-%%-----------------------------------------------------------------
-longlong(_) ->
- longlong_big_loop([-2147483648, -40404040, -32768, -4040, -1,
- 0, 4040, 32767, 40404040, 2147483647]),
- longlong_little_loop([-2147483648, -40404040, -32768, -4040, -1,
- 0, 4040, 32767, 40404040, 2147483647]),
- bad_longlong().
-
-
-longlong_big_loop([]) ->
- ok;
-longlong_big_loop([X |List]) ->
- [CodedType] = cdrlib:enc_longlong(X, []),
- {X, <<>>} = cdrlib:dec_longlong(big, CodedType),
- longlong_big_loop(List),
- ok.
-
-longlong_little_loop([]) ->
- ok;
-longlong_little_loop([X |List]) ->
- CodedType = enc_longlong_little(X, []),
- {X, <<>>} = cdrlib:dec_longlong(little, CodedType),
- longlong_little_loop(List),
- ok.
-
-enc_longlong_little(X, Message) ->
- list_to_binary([(X) band 16#ff, ((X) bsr 8) band 16#ff, ((X) bsr 16) band 16#ff,
- ((X) bsr 24) band 16#ff, ((X) bsr 32) band 16#ff, ((X) bsr 40) band 16#ff,
- ((X) bsr 48) band 16#ff, ((X) bsr 56) band 16#ff | Message]).
-
-bad_longlong() ->
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: unsigned long integer test
-%% Description:
-%%-----------------------------------------------------------------
-ulonglong(_) ->
- ulonglong_big_loop([0, 4040, 65535, 40404040, 2147483647, 4294967295]),
- ulonglong_little_loop([0, 4040, 65535, 40404040, 2147483647, 4294967295]),
- bad_ulonglong().
-
-
-ulonglong_big_loop([]) ->
- ok;
-ulonglong_big_loop([X |List]) ->
- [CodedType] = cdrlib:enc_unsigned_longlong(X, []),
- {X, <<>>} = cdrlib:dec_unsigned_longlong(big, CodedType),
- ulonglong_big_loop(List),
- ok.
-
-ulonglong_little_loop([]) ->
- ok;
-ulonglong_little_loop([X |List]) ->
- CodedType = enc_ulonglong_little(X, []),
- {X, <<>>} = cdrlib:dec_unsigned_longlong(little, CodedType),
- ulonglong_little_loop(List),
- ok.
-
-enc_ulonglong_little(X, Message) ->
- list_to_binary([(X) band 16#ff, ((X) bsr 8) band 16#ff, ((X) bsr 16) band 16#ff,
- ((X) bsr 24) band 16#ff, ((X) bsr 32) band 16#ff, ((X) bsr 40) band 16#ff,
- ((X) bsr 48) band 16#ff, ((X) bsr 56) band 16#ff | Message]).
-
-bad_ulonglong() ->
- ok.
-
-
-
-%%-----------------------------------------------------------------
-%% Test Case: boolean test
-%% Description:
-%%-----------------------------------------------------------------
-boolean(_) ->
- [CodedTrue] = cdrlib:enc_bool('true', []),
- {'true', <<>>} = cdrlib:dec_bool(CodedTrue),
- [CodedFalse] = cdrlib:enc_bool('false', []),
- {'false', <<>>} = cdrlib:dec_bool(CodedFalse),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: character test
-%% Description:
-%%-----------------------------------------------------------------
-character(_) ->
- [Coded_0] = cdrlib:enc_char($0, []),
- {$0, <<>>} = cdrlib:dec_char(Coded_0),
- [Coded_a] = cdrlib:enc_char($a, []),
- {$a, <<>>} = cdrlib:dec_char(Coded_a),
- [Coded_Z] = cdrlib:enc_char($Z, []),
- {$Z, <<>>} = cdrlib:dec_char(Coded_Z),
- [Coded_dollar] = cdrlib:enc_char($$, []),
- {$$, <<>>} = cdrlib:dec_char(Coded_dollar),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: octet test
-%% Description:
-%%-----------------------------------------------------------------
-octet(_) ->
- [Coded_ff] = cdrlib:enc_octet(16#ff, []),
- {16#ff, <<>>} = cdrlib:dec_octet(Coded_ff),
- [Coded_00] = cdrlib:enc_octet(16#00, []),
- {16#00, <<>>} = cdrlib:dec_octet(Coded_00),
- [Coded_5a] = cdrlib:enc_octet(16#5a, []),
- {16#5a, <<>>} = cdrlib:dec_octet(Coded_5a),
- [Coded_48] = cdrlib:enc_octet(16#48, []),
- {16#48, <<>>} = cdrlib:dec_octet(Coded_48),
- ok.
-
-
-
-%%-----------------------------------------------------------------
-%% Test Case: float test
-%% Description:
-%%-----------------------------------------------------------------
-float(_) ->
- G = 16#7fffff / 16#800000 + 1.0,
- H1 = math:pow(2, 127),
- H2 = math:pow(2, -126),
- float_big_loop([-H1 * G, -H1 * 1.0, -H2 * G, -H2 * 1.0,
- -4040.313131, -3.141592, 0.0, 3.141592, 4040.313131,
- H1 * G, H1 * 1.0, H2 * G, H2 * 1.0]),
- float_little_loop([-H1 * G, -H1 * 1.0, -H2 * G, -H2 * 1.0,
- -4040.313131, -3.141592, 0.0, 3.141592, 4040.313131,
- H1 * G, H1 * 1.0, H2 * G, H2 * 1.0]),
- ok.
-
-float_big_loop([]) ->
- ok;
-float_big_loop([X |List]) ->
- [CodedType] = cdrlib:enc_float(X, []),
- {Y, <<>>} = cdrlib:dec_float(big, CodedType),
- float_comp(X,Y),
- float_big_loop(List),
- ok.
-
-float_little_loop([]) ->
- ok;
-float_little_loop([X |List]) ->
- [CodedType] = enc_float_little(X, []),
- {Y, <<>>} = cdrlib:dec_float(little, CodedType),
- float_comp(X,Y),
- float_little_loop(List),
- ok.
-
-float_comp(X,Y) when X == 0.0, Y == 0.0 ->
- ok;
-float_comp(X,Y) ->
- Div = abs(Y) / abs(X),
- %% io:format("~p~n", [float_to_list(Div)]),
- true = (Div < 1.0000001),
- true = (Div > 0.9999999),
- ok.
-
-enc_float_little(X, Message) ->
- [ <<X:32/little-float>> | Message].
-
-%%-----------------------------------------------------------------
-%% Test Case: double test
-%% Description:
-%%-----------------------------------------------------------------
-double(_) ->
- F = 16#0fffffffffffff / 16#10000000000000 + 1.0,
- E1 = math:pow(2, 1023),
- E2 = math:pow(2, -1022),
- G = 16#7fffff / 16#800000 + 1.0,
- H1 = math:pow(2, 128),
- H2 = math:pow(2, -127),
- double_big_loop([-E1 * F, -E1 * 1.0, -E2 * F, -E2 * 1.0,
- -H1 * G, -H1 * 1.0, -H2 * G, -H2 * 1.0,
- -4040.313131, -3.141592, 0.0, 3.141592, 4040.313131,
- H1 * G, H1 * 1.0, H2 * G, H2 * 1.0,
- E1 * F, E1 * 1.0, E2 * F, E2 * 1.0]),
- double_little_loop([-E1 * F, -E1 * 1.0, -E2 * F, -E2 * 1.0,
- -H1 * G, -H1 * 1.0, -H2 * G, -H2 * 1.0,
- -4040.313131, -3.141592, 0.0, 3.141592, 4040.313131,
- H1 * G, H1 * 1.0, H2 * G, H2 * 1.0,
- E1 * F, E1 * 1.0, E2 * F, E2 * 1.0]),
- ok.
-
-double_big_loop([]) ->
- ok;
-double_big_loop([X |List]) ->
- [CodedType] = cdrlib:enc_double(X, []),
- {Y, <<>>} = cdrlib:dec_double(big, CodedType),
- double_comp(X,Y),
- double_big_loop(List),
- ok.
-
-double_little_loop([]) ->
- ok;
-double_little_loop([X |List]) ->
- [CodedType] = enc_double_little(X, []),
- {Y, <<>>} = cdrlib:dec_double(little, CodedType),
- double_comp(X,Y),
- double_little_loop(List),
- ok.
-
-enc_double_little(X, Message) ->
- [ <<X:64/little-float>> | Message].
-
-double_comp(X,Y) when X == 0.0, Y == 0.0 ->
- ok;
-double_comp(X,Y) ->
- Div = abs(Y) / abs(X),
- %% io:format("~p~n", [float_to_list(Div)]),
- true = (Div < 1.00000000000001),
- true = (Div > 0.99999999999999),
- ok.
-
-double_should_be_ok(_) ->
- F = 16#0fffffffffffff / 16#10000000000000 + 1.0,
- E1 = math:pow(2, 1024), % erlang can't handle this.
- E2 = math:pow(2, -1023),
- double_big_loop([-E1 * F, -E1 * 1.0, -E2 * F, -E2 * 1.0,
- E1 * F, E1 * 1.0, E2 * F, E2 * 1.0]),
- double_little_loop([-E1 * F, -E1 * 1.0, -E2 * F, -E2 * 1.0,
- E1 * F, E1 * 1.0, E2 * F, E2 * 1.0]),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: enum test
-%% Description:
-%%-----------------------------------------------------------------
-enum(_) ->
- enum_big(),
- enum_little(),
- ok.
-
-enum_big() ->
- [Coded_a] = cdrlib:enc_enum(a,[a,b,c],[]),
- {a, <<>>} = cdrlib:dec_enum(big, ["a","b","c"], Coded_a),
- [Coded_b] = cdrlib:enc_enum(b,[a,b,c],[]),
- {b, <<>>} = cdrlib:dec_enum(big, ["a","b","c"], Coded_b),
- [Coded_c] = cdrlib:enc_enum(c,[a,b,c],[]),
- {c, <<>>} = cdrlib:dec_enum(big, ["a","b","c"], Coded_c),
- ok.
-
-enum_little() ->
- Coded_a = enc_r_enum(a,[a,b,c],[]),
- {a, <<>>} = cdrlib:dec_enum(little, ["a","b","c"], Coded_a),
- Coded_b = enc_r_enum(b,[a,b,c],[]),
- {b, <<>>} = cdrlib:dec_enum(little, ["a","b","c"], Coded_b),
- Coded_c = enc_r_enum(c,[a,b,c],[]),
- {c, <<>>} = cdrlib:dec_enum(little, ["a","b","c"], Coded_c),
- ok.
-
-enc_r_enum(Enum, ElemList, Message) ->
- Val = getEnumValue(ElemList,Enum, 0),
- enc_r_unsigned_long(Val, Message).
-
-getEnumValue([Enum |_List], Enum, N) ->
- N;
-getEnumValue([_ |List], Enum, N) ->
- getEnumValue(List, Enum, N + 1).
-
-enc_r_unsigned_long(X, Message) ->
- list_to_binary([(X) band 16#ff, ((X) bsr 8) band 16#ff,
- ((X) bsr 16) band 16#ff, ((X) bsr 24) band 16#ff | Message]).
diff --git a/lib/orber/test/corba_SUITE.erl b/lib/orber/test/corba_SUITE.erl
deleted file mode 100644
index 22bb8dd2f9..0000000000
--- a/lib/orber/test/corba_SUITE.erl
+++ /dev/null
@@ -1,897 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%%
-%% Description:
-%% Test suite for corba/boa/object/orber API functions
-%%
-%%-----------------------------------------------------------------
--module(corba_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
-
--define(default_timeout, test_server:minutes(5)).
-
--define(match(ExpectedRes,Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~nRESULT: ~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([pseudo_calls/2, pseudo_casts/2]).
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-cases() ->
- [exception_info_api, corba_api, object_api, orber_api,
- orber_objectkeys_api, orber_pseudo_objects,
- callback_ok_api, callback_arity_api,
- callback_module_api, callback_function_api,
- callback_precond_api, callback_postcond_api,
- callback_exit_api, callback_badarith_api,
- callback_case_clause_api, callback_function_clause_api].
-
-%% boa_api, request, locate_request, locate_reply].
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-
-init_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) ->
- corba:orb_init([{orber_debug_level, 10}, {giop_version, {1,2}},
- {iiop_port, 0}]),
- mnesia:delete_schema([node()]),
- mnesia:create_schema([node()]),
- orber:install([node()]),
- application:start(mnesia),
- application:start(orber),
- if
- is_list(Config) ->
- Config;
- true ->
- exit("Config not a list")
- end.
-
-end_per_suite(Config) ->
- application:stop(orber),
- application:stop(mnesia),
- mnesia:delete_schema([node()]),
- Config.
-
-%%-----------------------------------------------------------------
-%% API tests for pseudo interface CORBA
-%%-----------------------------------------------------------------
-corba_api(_) ->
- NIL = corba:create_nil_objref(),
- ok = corba:dispose(NIL),
- NS = corba:resolve_initial_references("NameService"),
- List = corba:list_initial_services(),
- ["NameService"] = List,
- NSstring = corba:object_to_string(NS),
- NS1 = corba:string_to_object(NSstring),
- NSstring = corba:object_to_string(NS1),
- true = corba:add_initial_service("MyData", NS),
- NS = corba:resolve_initial_references("MyData"),
- [_,_] = corba:list_initial_services(),
- false = corba:remove_initial_service("Wrong"),
- NIL = corba:resolve_initial_references("Wrong"),
- NS = corba:string_to_object("corbaloc:rir:/MyData"),
- true = corba:remove_initial_service("MyData"),
- ["NameService"] = corba:list_initial_services(),
-
- %% This is a collection of different stringified IOR:s (correct & incorrect)
- %% which we use to test IOR encode/decode.
- IOR1 = ?match({'IOP_IOR',_,_}, corba:string_to_object("IOR:000303030000000d49444c3a746573743a312e3000030303000000040000000000000100000102010000000a3132372e302e302e31009d610000002dabacab3131303432343836383731005f526f6f74504f4100414c4c5f504f410000cafebabe3e2316570000000003030300000002000000210000007800010202000000010040020200000022000000080003030300000000004000400000000806066781020101010000001b0401000806066781020101010000000b40616469726f6e2e636f6d010400000000000000000000020000000806066781020101010000000b06092a864886f712010202010000000f000000010000002c00030303000100010000000400010020000101090001010005010001000101090000000200010100050100010000000000000184000102010000000a3132372e302e302e310000000000002dabacab3131303432343836383731005f526f6f74504f4100414c4c5f504f410000cafebabe3e231657000000000303030000000300000021000000ec000102020000000200060202000000240000001c0001006600060202000000010000000a3132372e302e302e31009d600000000000000000000000000400000000000000000000020000000806066781020101010000000b06092a864886f712010202010000000f00460202000000240000001c0001006600060202000000010000000a3132372e302e302e31009d62004000400000000806066781020101010000001b0401000806066781020101010000000b40616469726f6e2e636f6d010400000000000000000000020000000806066781020101010000000b06092a864886f712010202010000000f00000014000000080001006600069d5e000000010000002c000303030001000100000004000100200001010900010100050100010001010900000002000101000501000100000000000000dc000102010000000a3132372e302e302e31009d5f0000002dabacab3131303432343836383731005f526f6f74504f4100414c4c5f504f410000cafebabe3e23165700000000030303000000020000002100000054000102020000000100000202000000220000000800030303000000000000000000000000000000000400000000000000000000020000000806066781020101010000000b06092a864886f712010202010000000f000000010000002c00030303000100010000000400010020000101090001010005010001000101090000000200010100050100010000000000000080000102010000000a3132372e302e302e31009d5d0000002dabacab3131303432343836383731005f526f6f74504f4100414c4c5f504f410000cafebabe3e2316570000000003030300000001000000010000002c0003030300010001000000040001002000010109000101000501000100010109000000020001010005010001")),
- IOR2 = ?match({'IOP_IOR',_,_}, corba:string_to_object("IOR:000303030000000d49444c3a746573743a312e30000303030000000100000000000000e0000102010000000a3132372e302e302e31009d5f00000034abacab3131303432343836383731005f526f6f74504f410049494f505f43534976325f504f410000cafebabe3e23165700000000000000020000002100000054000102020000000100000202000000220000000800030303000000000000000000000000000000000400000000000000000000020000000806066781020101010000000b06092a864886f712010202010000000f000000010000002c0003030300010001000000040001002000010109000101000501000100010109000000020001010005010001")),
- IOR3 = ?match({'IOP_IOR',_,_}, corba:string_to_object("IOR:000303030000000d49444c3a746573743a312e3000030303000000010000000000000108000102010000000a3132372e302e302e31009d6100000037abacab3131303432343836383731005f526f6f74504f410049494f505f43534976325f55505f504f410000cafebabe3e231657000000000100000002000000210000007800010202000000010040020200000022000000080003030300000000004000400000000806066781020101010000001b0401000806066781020101010000000b40616469726f6e2e636f6d010400000000000000000000020000000806066781020101010000000b06092a864886f712010202010000000f000000010000002c0003030300010001000000040001002000010109000101000501000100010109000000020001010005010001")),
- IOR4 = ?match({'IOP_IOR',_,_}, corba:string_to_object("IOR:000303030000000d49444c3a746573743a312e3000030303000000010000000000000080000102010000000a3132372e302e302e31009d5d0000002eabacab3131303432343836383731005f526f6f74504f410049494f505f504f410000cafebabe3e23165700000000020200000001000000010000002c0003030300010001000000040001002000010109000101000501000100010109000000020001010005010001")),
- IOR5 = ?match({'IOP_IOR',_,_}, corba:string_to_object("IOR:000303030000000d49444c3a746573743a312e30000303030000000100000000000000fc000102010000000a3132372e302e302e3100000000000033abacab3131303432343836383731005f526f6f74504f4100544c535f43534976325f504f410000cafebabe3e231657000000000100000002000000210000007000010202000000010006020200000024000000220001006600060202000000010000000f3132382e3233302e3230382e353500019d6000000000020200000000000000000400000000000000000000020000000806066781020101010000000b06092a864886f712010202010000000f000000010000002c0003030300010001000000040001002000010109000101000501000100010109000000020001010005010001")),
- IOR6 = ?match({'IOP_IOR',_,_}, corba:string_to_object("IOR:000303030000000d49444c3a746573743a312e3000030303000000010000000000000124000102010000000a3132372e302e302e3100000000000036abacab3131303432343836383731005f526f6f74504f4100544c535f43534976325f55505f504f410000cafebabe3e23165700000000020200000002000000210000009400010202000000010046020200000024000000220001006600060202000000010000000f3132382e3233302e3230382e353500019d620040004002020000000806066781020101010000001b0401000806066781020101010000000b40616469726f6e2e636f6d010400000000000000000000020000000806066781020101010000000b06092a864886f712010202010000000f000000010000002c0003030300010001000000040001002000010109000101000501000100010109000000020001010005010001")),
- IOR7 = ?match({'IOP_IOR',_,_}, corba:string_to_object("IOR:000303030000000d49444c3a746573743a312e3000030303000000010000000000000090000102010000000a3132372e302e302e310000000000002dabacab3131303432343836383731005f526f6f74504f4100544c535f504f410000cafebabe3e231657000000000303030000000200000014000000080001006600069d5e000000010000002c0003030300010001000000040001002000010109000101000501000100010109000000020001010005010001")),
- IOR1 = corba:string_to_object(corba:object_to_string(IOR1)),
- IOR2 = corba:string_to_object(corba:object_to_string(IOR2)),
- IOR3 = corba:string_to_object(corba:object_to_string(IOR3)),
- IOR4 = corba:string_to_object(corba:object_to_string(IOR4)),
- IOR5 = corba:string_to_object(corba:object_to_string(IOR5)),
- IOR6 = corba:string_to_object(corba:object_to_string(IOR6)),
- IOR7 = corba:string_to_object(corba:object_to_string(IOR7)),
- ?match(ok, corba:print_object(IOR1)),
- ?match(ok, corba:print_object(IOR2)),
- ?match(ok, corba:print_object(IOR3)),
- ?match(ok, corba:print_object(IOR4)),
- ?match(ok, corba:print_object(IOR5)),
- ?match(ok, corba:print_object(IOR6)),
- ?match(ok, corba:print_object(IOR7)),
- ?match(ok, corba:print_object("IOR:000303030000000d49444c3a746573743a312e300003030300000002000000000000003000010001000000136d792e686f73742e65726c616e672e6f72670001801a02020000000c424f410a00000a0000070a010000000100000024000303030000000100000001000000140003030300010001000000000001010900000000")),
- [IP] = ?match([_], orber:host()),
- ?match(#'IOP_IOR'{profiles=[#'IOP_TaggedProfile'
- {tag=?TAG_INTERNET_IOP,
- profile_data=#'IIOP_ProfileBody_1_1'
- {host = IP}}]},
- corba:string_to_object(corba:object_to_string(NS))),
- ?match(#'IOP_IOR'{profiles=[#'IOP_TaggedProfile'
- {tag=?TAG_INTERNET_IOP,
- profile_data=#'IIOP_ProfileBody_1_1'
- {host = "127.0.0.1"}}]},
- corba:string_to_object(corba:object_to_string(NS, ["127.0.0.1"]))),
- ?match(#'IOP_IOR'{profiles=[#'IOP_TaggedProfile'
- {tag=?TAG_INTERNET_IOP,
- profile_data=#'IIOP_ProfileBody_1_1'
- {host = "127.0.0.1", port = 5468}}]},
- corba:string_to_object(corba:object_to_string(NS, ["127.0.0.1"],
- 5468))),
- ok.
-
-%%-----------------------------------------------------------------
-%% API tests for interface BOA
-%%-----------------------------------------------------------------
-boa_api(_) ->
- ok.
-
-%%-----------------------------------------------------------------
-%% API tests for interface OBJECT
-%%-----------------------------------------------------------------
-object_api(_) ->
- oe_orber_test_server:oe_register(),
- EC = orber_test_server:oe_create(),
- NS = corba:resolve_initial_references("NameService"),
- %% testing corba_object:is_a(Obj, IFRID) locally.
- orber_test_lib:corba_object_tests(EC, NS),
-
- ?match(false, corba_object:non_existent(NS)),
-
- corba:dispose(EC),
- oe_orber_test_server:oe_unregister(),
- ok.
-
-%%-----------------------------------------------------------------
-%% API tests for orbers main module
-%%-----------------------------------------------------------------
-orber_api(_) ->
- ok = orber:uninstall(),
- orber:install([node()]),
- application:start(orber),
- NodeList = orber:orber_nodes(),
- NL = node(),
- [NL] = NodeList,
- ok.
-
-%%-----------------------------------------------------------------
-%% API tests for exception mapping
-%%-----------------------------------------------------------------
-exception_info_api(_) ->
- {ok, S1} = orber:exception_info({'EXCEPTION',{'MARSHAL',[],1163001858,'COMPLETED_NO'}}),
- {ok, S2} = orber:exception_info({'EXCEPTION',{'MARSHAL',[],1330446337,'COMPLETED_NO'}}),
- {ok, S3} = orber:exception_info({'EXCEPTION',{'MARSHAL',[],1398079490,'COMPLETED_NO'}}),
- {ok, S4} = orber:exception_info({'EXCEPTION',{'MARSHAL',[],1347813377,'COMPLETED_NO'}}),
- {ok, S5} = orber:exception_info({'EXCEPTION', {'CosNaming_NamingContext_InvalidName',"IDL:omg.org/CosNaming/NamingContext/InvalidName:1.0"}}),
- error_logger:info_msg("~s", [S1]),
- error_logger:info_msg("~s", [S2]),
- error_logger:info_msg("~s", [S3]),
- error_logger:info_msg("~s", [S4]),
- error_logger:info_msg("~s", [S5]),
- ok.
-
-%%-----------------------------------------------------------------
-%% API tests for orbers pseudo objects.
-%%-----------------------------------------------------------------
-orber_pseudo_objects(_) ->
- oe_orber_test_server:oe_register(),
- Obj1=(catch orber_test_server:oe_create(state,[{pseudo,true},
- {local_typecheck, true}])),
- ?match({_,pseudo,orber_test_server_impl, _,_, _}, Obj1),
- Obj2=(catch orber_test_server:oe_create([],[{pseudo, truce}])),
- ?match({'EXCEPTION',{'BAD_PARAM',[],_,'COMPLETED_NO'}}, Obj2),
- spawn(?MODULE, pseudo_calls, [20, Obj1]),
- ?match({ok, 10000}, orber_test_server:pseudo_call_delay(Obj1, 10000)),
- spawn(?MODULE, pseudo_casts, [20, Obj1]),
- ?match(ok, orber_test_server:pseudo_cast_delay(Obj1, 10000)),
-
- ?match('object_here', corba:locate(Obj1)),
-
- NS = corba:resolve_initial_references("NameService"),
-
- orber_test_lib:corba_object_tests(Obj1, NS),
-
- ?match("IDL:omg.org/orber_test/server:1.0",orber_test_server:typeID()),
-
- %% Test if exceptions are handled properly.
- ?match({'EXCEPTION',{'BAD_QOS',_,_,_}},
- orber_test_server:pseudo_call_raise_exc(Obj1, 1)),
- ?match({'EXCEPTION',{'BAD_QOS',_,_,_}},
- orber_test_server:pseudo_call_raise_exc(Obj1, 2)),
-
- %% Test if exit is handled properly.
- ?match({'EXCEPTION',{'TRANSIENT',_,_,_}},
- orber_test_server:stop_brutal(Obj1)),
-
- orber_test_lib:test_coding(Obj1, true),
-
- %% possible to use subobject key?
- ?match(state, binary_to_term(corba:get_subobject_key(Obj1))),
-
- ?match({'EXCEPTION',{'INV_OBJREF',[],_,'COMPLETED_NO'}},
- corba:get_pid(Obj1)),
- ?match(false, corba_object:non_existent(Obj1)),
-
- ?match(ok, corba:dispose(Obj1)),
-
- ?match(false, corba_object:non_existent(Obj1)),
-
- %% Try if it's possible to stringify and recover the object reference.
- IOR_string = (catch corba:object_to_string(Obj1)),
- Obj3 =(catch corba:string_to_object(IOR_string)),
- ?match(IOR_string, corba:object_to_string(Obj3)),
-
- Obj4=(catch orber_test_server:oe_create(undefined,[{pseudo,true}])),
- ?match(ok, corba:dispose(Obj4)),
- oe_orber_test_server:oe_unregister(),
- ok.
-
-%%-----------------------------------------------------------------
-%% API tests for orbers objectkeys server.
-%%-----------------------------------------------------------------
-orber_objectkeys_api(_) ->
- Obj0=(catch orber_test_server:oe_create([], [{sup_child, true}])),
- Obj1=(catch orber_test_server:oe_create([], [{persistent, true},
- {regname, {local,obj1}}])),
- Obj2=(catch orber_test_server:oe_create([], [{persistent, true},
- {regname, {global,{obj2, 12345}}}])),
-
- %% Obj0 is supposed to be a child started by a supervisor (r6) which
- %% handles not only {ok, Pid} but also {ok,Pid, Returnvalue}. In our
- %% case the Returnvalue is an ObjectRef.
- ?match({ok,_,{_,key,_, _,_, _}}, Obj0),
- {ok,_,Obj0Ref} = Obj0,
- corba:dispose(Obj0Ref),
-
- %% Only 'global' servers are at the moment allowed to be persistent.
- ?match({'EXCEPTION',{'BAD_PARAM',[],_,'COMPLETED_NO'}}, Obj1),
-
- %% We created a persistent object successfully.
- ?match({_,key,_,_,_, _}, Obj2),
-
- %% Get key and Pid
- {_,_,Key,_,_, _} = Obj2,
- PID=(catch orber_objectkeys:get_pid(Key)),
-
- %% Use the two different ways to look up if the server is persistent.
- ?match(true, orber_objectkeys:is_persistent(Key)),
- ?match(true, orber_objectkeys:is_persistent(PID)),
-
- %% Create servers using every possible way.
- O1=(catch orber_test_server:oe_create()),
- O2=(catch orber_test_server:oe_create_link()),
- O3=(catch orber_test_server:oe_create([])),
- O4=(catch orber_test_server:oe_create_link([])),
- %% NOTE!!! Next four lines requires that we still support RegName instead of
- %% only OptionList as the second argument to oe_create*/2. Remove these when that
- %% is no longer the case.
- O5=(catch orber_test_server:oe_create([], {'local', o5})),
- O6=(catch orber_test_server:oe_create([], {'global', {o6, obj}})),
- O7=(catch orber_test_server:oe_create_link([], {'local', o7})),
- O8=(catch orber_test_server:oe_create_link([], {'global', {o8, obj}})),
-
- %% Test if all the object references are correct.
- ?match({_,key,_,_,_, _}, O1),
- ?match({_,key,_,_,_, _}, O2),
- ?match({_,key,_,_,_, _}, O3),
- ?match({_,key,_,_,_, _}, O4),
- ?match({_, registered, o5, _,_, _}, O5),
- ?match({_,key,_,_,_, _}, O6),
- ?match({_, registered, o7, _,_, _}, O7),
- ?match({_,key,_,_,_, _}, O8),
-
- %% Test if persistent.
- {_,_,Key1,_,_, _} = O1,
- PID1=(catch orber_objectkeys:get_pid(Key1)),
- ?match(false, orber_objectkeys:is_persistent(Key1)),
- ?match(false, orber_objectkeys:is_persistent(PID1)),
-
- %% all the servers are alive(?!).
- ?match(false, corba_object:non_existent(O1)),
- ?match(false, corba_object:non_existent(O2)),
- ?match(false, corba_object:non_existent(O3)),
- ?match(false, corba_object:non_existent(O4)),
- ?match(false, corba_object:non_existent(O5)),
- ?match(false, corba_object:non_existent(O6)),
- ?match(false, corba_object:non_existent(O7)),
- ?match(false, corba_object:non_existent(O8)),
- ?match(false, corba_object:non_existent(Obj2)),
-
- %% Does locate work?
- ?match('object_here', corba:locate(O1)),
- ?match('object_here', corba:locate(O2)),
- ?match('object_here', corba:locate(O3)),
- ?match('object_here', corba:locate(O4)),
- ?match('object_here', corba:locate(O5)),
- ?match('object_here', corba:locate(O6)),
- ?match('object_here', corba:locate(O7)),
- ?match('object_here', corba:locate(O8)),
- ?match('object_here', corba:locate(Obj2)),
-
- %% Terminate all servers with reason 'normal'.
- catch corba:dispose(O1),
- catch corba:dispose(O2),
- catch corba:dispose(O3),
- catch corba:dispose(O4),
- catch corba:dispose(O5),
- catch corba:dispose(O6),
- catch corba:dispose(O7),
- catch corba:dispose(O8),
- catch corba:dispose(Obj2),
-
-
- %% To make sure that orber_objectkeys-server is able to
- %% clean up we wait.
- timer:sleep(2000),
-
- %% all the servers are dead(?!). If one of these test-cases
- %% fails the only error can be that we didn't sleep long enough, i.e.,
- %% try a longer timeout. If still fails something is wrong.
- ?match(true, corba_object:non_existent(O1)),
- ?match(true, corba_object:non_existent(O2)),
- ?match(true, corba_object:non_existent(O3)),
- ?match(true, corba_object:non_existent(O4)),
- ?match(true, corba_object:non_existent(O5)),
- ?match(true, corba_object:non_existent(O6)),
- ?match(true, corba_object:non_existent(O7)),
- ?match(true, corba_object:non_existent(O8)),
- ?match(true, corba_object:non_existent(Obj2)),
-
- %% Create a new persistent server.
- Obj3=(catch orber_test_server:oe_create([],
- [{persistent, true},
- {regname, {global,{obj2, 12345}}}])),
-
- %% OK?!
- ?match({_,key,_,_,_, _}, Obj3),
-
- %% Try to create a server with the same name (naturally it fails).
- ?match({'EXCEPTION',{'INTERNAL',[],_,'COMPLETED_NO'}},
- orber_test_server:oe_create([],
- [{persistent, true},
- {regname, {global,{obj2, 12345}}}])),
- %% Try to remove all 'dead' servers. No server should be removed.
- orber_objectkeys:gc(0),
-
- %% Kill object brutal, i.e., not with reason 'normal' or 'shutdown'.
- P3 = corba:get_pid(Obj3),
- exit(P3, kill),
-
- {_,_,Key3,_,_, _} = Obj3,
-
- %% Give time to clean up.
- timer:sleep(2000),
- ?match({'EXCEPTION',{'TRANSIENT',[],_,'COMPLETED_NO'}},
- gen_server:call(orber_objkeyserver,
- {get_pid, Key3},
- infinity)),
-
- ?match(false,corba_object:non_existent(Obj3)),
-
- %% Run gc wit a "huge" time-limit. Will not erase the dead object.
- orber_objectkeys:gc(10000),
- ?match(false,corba_object:non_existent(Obj3)),
-
- %% Run gc with minimum time-limit. Will erase the dead object.
- orber_objectkeys:gc(0),
- ?match(true,corba_object:non_existent(Obj3)),
-
- %% Create a new persistent server.
- Obj4=(catch orber_test_server:oe_create([],
- [{persistent, true},
- {regname, {global,{obj2, 12345}}}])),
-
- %% OK?!
- ?match({_,key,_,_,_, _}, Obj4),
- %% Kill object brutal, i.e., not with reason 'normal' or 'shutdown'.
- P4 = corba:get_pid(Obj4),
- exit(P4, kill),
-
- %% Give time to clean up.
- timer:sleep(2000),
-% ?match({'EXCEPTION',{'COMM_FAILURE',[],0,'COMPLETED_NO'}},
- ?match({error, _},
- corba:get_pid(Obj4)),
-
- ?match(false,corba_object:non_existent(Obj4)),
-
- %% Restart the object.
- Obj5=(catch orber_test_server:oe_create([],
- [{persistent, true},
- {regname, {global,{obj2, 12345}}}])),
- %% OK?!
- ?match({_,key,_,_,_, _}, Obj5),
-
- %% Run gc with minimum time-limit.
- orber_objectkeys:gc(0),
- ?match(false,corba_object:non_existent(Obj5)),
- corba:dispose(Obj5),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% API tests for callback functions
-%%-----------------------------------------------------------------
--define(DO_EXIT_FLAG, 0).
--define(NO_EXIT_FLAG, 16#10).
-
--define(DO_EXIT, {is, 0}).
--define(NO_EXIT, {is, 16#10}).
-
-
-
-%% Successful callback API tests
-callback_ok_api(_) ->
- %% Init
- ?match({ok, {?DO_EXIT, state}}, corba:handle_init(?MODULE, {?DO_EXIT_FLAG, state})),
- %% Terminate
- ?match(ok, corba:handle_terminate(?MODULE, "reason", {?DO_EXIT, state})),
- %% Handle_call
- ?match({reply,ok,{?DO_EXIT,state}},
- corba:handle_call(?MODULE, foo, [],
- {?DO_EXIT, state}, [], false, false)),
- %% Handle_cast
- ?match({noreply, {?DO_EXIT,state}},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?DO_EXIT, state}, [], false)),
- %% Handle_call precond/postcond
- ?match({reply, ok, {?DO_EXIT, state}},
- corba:handle_call(?MODULE, foo, [],
- {?DO_EXIT, state}, [], false, false, {?MODULE, precond},
- {?MODULE, postcond}, ?MODULE)),
- %% Handle_cast precond/postcond
- ?match({noreply, {?DO_EXIT, state}},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?DO_EXIT, state}, [], false, {?MODULE, precond},
- {?MODULE, postcond}, ?MODULE)),
- %% Handle_info
- ?match({noreply, {?DO_EXIT, state}},
- corba:handle_info(?MODULE, "info", {?DO_EXIT, state})),
- ok.
-
-%% Callback arity API tests
-callback_arity_api(_) ->
- %% Handle_call - stay-alive == false
- ?match({'EXIT', {undef,_}},
- corba:handle_call(?MODULE, foo, [to, many, arguments],
- {?DO_EXIT, state}, [], false, false)),
- %% Handle_call - stay-alive == true
- ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}}, _},
- corba:handle_call(?MODULE, foo, [to, many, arguments],
- {?NO_EXIT, state}, [], false, false)),
- %% Handle_call - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_call(?MODULE, foo, [],
- {?DO_EXIT, arity}, [], false, false)),
- %% Handle_call - stay-alive == true
- ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}}, _},
- corba:handle_call(?MODULE, foo, [],
- {?NO_EXIT, arity}, [], false, false)),
- %% Handle_cast - stay-alive == false
- ?match({'EXIT', {undef,_}},
- corba:handle_cast(?MODULE, foo_1w, [to, many, arguments],
- {?DO_EXIT, state}, [], false)),
- %% Handle_cast - stay-alive == true
- ?match({noreply, {?NO_EXIT, state}},
- corba:handle_cast(?MODULE, foo_1w, [to, many, arguments],
- {?NO_EXIT, state}, [], false)),
- %% Handle_cast - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?DO_EXIT, arity}, [], false)),
- %% Handle_cast - stay-alive == true
- ?match({noreply, {?NO_EXIT, arity}},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?NO_EXIT, arity}, [], false)),
- %% Handle_info - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_info(?MODULE, "info", {?DO_EXIT, arity})),
-
- %% Handle_info - stay-alive == true
- ?match({noreply, {?NO_EXIT, arity}},
- corba:handle_info(?MODULE, "info", {?NO_EXIT, arity})),
- ok.
-
-%% Module callback API tests
-callback_module_api(_) ->
- %% Handle_call - stay-alive == false
- ?match({'EXIT', {undef,_}},
- corba:handle_call(wrong_mod, foo, [],
- {?DO_EXIT, state}, [], false, false)),
- %% Handle_call - stay-alive == true
- ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}}, _},
- corba:handle_call(wrong_mod, foo, [],
- {?NO_EXIT, state}, [], false, false)),
- %% Handle_cast - stay-alive == false
- ?match({'EXIT', {undef,_}},
- corba:handle_cast(wrong_mod, foo_1w, [],
- {?DO_EXIT, state}, [], false)),
- %% Handle_cast - stay-alive == true
- ?match({noreply, {?NO_EXIT, state}},
- corba:handle_cast(wrong_mod, foo_1w, [],
- {?NO_EXIT, state}, [], false)),
- %% Handle_info - stay-alive == false.
- ?match({'EXIT', _},
- corba:handle_info(wrong_mod, "info", {?DO_EXIT, state})),
-
- %% Handle_info - stay-alive == true.
- ?match({noreply, {?NO_EXIT, state}},
- corba:handle_info(wrong_mod, "info", {?NO_EXIT, state})),
- ok.
-
-%% Function callback API tests
-callback_function_api(_) ->
- %% Handle_call - stay-alive == false
- ?match({'EXIT', {undef,_}},
- corba:handle_call(?MODULE, bad_function, [],
- {?DO_EXIT, state}, [], false, false)),
- %% Handle_call - stay-alive == true
- ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}}, _},
- corba:handle_call(?MODULE, bad_function, [],
- {?NO_EXIT, state}, [], false, false)),
- %% Handle_cast - stay-alive == false
- ?match({'EXIT', {undef,_}},
- corba:handle_cast(?MODULE, bad_function, [],
- {?DO_EXIT, state}, [], false)),
- %% Handle_cast - stay-alive == true
- ?match({noreply, {?NO_EXIT, state}},
- corba:handle_cast(?MODULE, bad_function, [],
- {?NO_EXIT, state}, [], false)),
- %% Handle_info - stay-alive == false. Note, we cannot use ?MODULE here.
- ?match({'EXIT', _},
- corba:handle_info(corba, "info", {?DO_EXIT, state})),
-
- %% Handle_info - stay-alive == true. Note, we cannot use ?MODULE here.
- ?match({noreply, {?NO_EXIT, state}},
- corba:handle_info(corba, "info", {?NO_EXIT, state})),
- ok.
-
-%% Precond callback API tests
-callback_precond_api(_) ->
- %% Handle_call - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_call(?MODULE, foo, [],
- {?DO_EXIT, state}, [], false, false, {wrong_mod, precond},
- {?MODULE, postcond}, ?MODULE)),
- %% Handle_call - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_call(?MODULE, foo, [],
- {?DO_EXIT, state}, [], false, false, {?MODULE, bad_precond},
- {?MODULE, postcond}, ?MODULE)),
- %% Handle_call - stay-alive == true
- ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}},_},
- corba:handle_call(?MODULE, foo, [],
- {?NO_EXIT, state}, [], false, false, {wrong_mod, precond},
- {?MODULE, postcond}, ?MODULE)),
- %% Handle_call - stay-alive == true
- ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}},_},
- corba:handle_call(?MODULE, foo, [],
- {?NO_EXIT, state}, [], false, false, {?MODULE, bad_precond},
- {?MODULE, postcond}, ?MODULE)),
- %% Handle_cast - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?DO_EXIT, state}, [], false, {wrong_mod, precond},
- {?MODULE, postcond}, ?MODULE)),
- %% Handle_cast - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?DO_EXIT, state}, [], false, {?MODULE, bad_precond},
- {?MODULE, postcond}, ?MODULE)),
- %% Handle_cast - stay-alive == true
- ?match({noreply, {?NO_EXIT, state}},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?NO_EXIT, state}, [], false, {wrong_mod, precond},
- {?MODULE, postcond}, ?MODULE)),
- %% Handle_cast - stay-alive == true
- ?match({noreply, {?NO_EXIT, state}},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?NO_EXIT, state}, [], false, {?MODULE, bad_precond},
- {?MODULE, postcond}, ?MODULE)),
- ok.
-
-
-%% Postcond callback API tests
-callback_postcond_api(_) ->
- %% Handle_call - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_call(?MODULE, foo, [],
- {?DO_EXIT, state}, [], false, false, {?MODULE, precond},
- {wrong_mod, postcond}, ?MODULE)),
- %% Handle_call - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_call(?MODULE, foo, [],
- {?DO_EXIT, state}, [], false, false, {?MODULE, precond},
- {?MODULE, bad_postcond}, ?MODULE)),
- %% Handle_call - stay-alive == true
- ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}},_},
- corba:handle_call(?MODULE, foo, [],
- {?NO_EXIT, state}, [], false, false, {?MODULE, precond},
- {wrong_mod, postcond}, ?MODULE)),
- %% Handle_call - stay-alive == true
- ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}},_},
- corba:handle_call(?MODULE, foo, [],
- {?NO_EXIT, state}, [], false, false, {?MODULE, precond},
- {?MODULE, bad_postcond}, ?MODULE)),
- %% Handle_cast - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?DO_EXIT, state}, [], false, {?MODULE, precond},
- {wrong_mod, postcond}, ?MODULE)),
- %% Handle_cast - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?DO_EXIT, state}, [], false, {?MODULE, precond},
- {?MODULE, bad_postcond}, ?MODULE)),
- %% Handle_cast - stay-alive == true
- ?match({noreply, {?NO_EXIT, state}},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?NO_EXIT, state}, [], false, {?MODULE, precond},
- {wrong_mod, postcond}, ?MODULE)),
- %% Handle_cast - stay-alive == true
- ?match({noreply, {?NO_EXIT, state}},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?NO_EXIT, state}, [], false, {?MODULE, precond},
- {?MODULE, bad_postcond}, ?MODULE)),
- ok.
-
-
-%% Callback exit API tests
-callback_exit_api(_) ->
- %% Handle_call - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_call(?MODULE, foo, [],
- {?DO_EXIT, exit}, [], false, false)),
- %% Handle_call - stay-alive == true
- ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}}, _},
- corba:handle_call(?MODULE, foo, [],
- {?NO_EXIT, exit}, [], false, false)),
- %% Handle_cast - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?DO_EXIT, exit}, [], false)),
- %% Handle_cast - stay-alive == true
- ?match({noreply, {?NO_EXIT, exit}},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?NO_EXIT, exit}, [], false)),
- %% Handle_info - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_info(?MODULE, "info", {?DO_EXIT, exit})),
-
- %% Handle_info - stay-alive == true
- ?match({noreply, {?NO_EXIT, exit}},
- corba:handle_info(?MODULE, "info", {?NO_EXIT, exit})),
- ok.
-
-
-%% Callback badarith API tests
-callback_badarith_api(_) ->
- %% Handle_call - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_call(?MODULE, foo, [],
- {?DO_EXIT, badarith}, [], false, false)),
- %% Handle_call - stay-alive == true
- ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}},_},
- corba:handle_call(?MODULE, foo, [],
- {?NO_EXIT, badarith}, [], false, false)),
- %% Handle_cast - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?DO_EXIT, badarith}, [], false)),
- %% Handle_cast - stay-alive == true
- ?match({noreply, {?NO_EXIT, badarith}},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?NO_EXIT, badarith}, [], false)),
- %% Handle_info - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_info(?MODULE, "info", {?DO_EXIT, badarith})),
-
- %% Handle_info - stay-alive == true
- ?match({noreply, {?NO_EXIT, badarith}},
- corba:handle_info(?MODULE, "info", {?NO_EXIT, badarith})),
- ok.
-
-%% Callback case_clause API tests
-callback_case_clause_api(_) ->
- %% Handle_call - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_call(?MODULE, foo, [],
- {?DO_EXIT, case_clause}, [], false, false)),
- %% Handle_call - stay-alive == true
- ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}}, _},
- corba:handle_call(?MODULE, foo, [],
- {?NO_EXIT, case_clause}, [], false, false)),
- %% Handle_cast - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?DO_EXIT, case_clause}, [], false)),
- %% Handle_cast - stay-alive == true
- ?match({noreply, {?NO_EXIT, case_clause}},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?NO_EXIT, case_clause}, [], false)),
- %% Handle_info - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_info(?MODULE, "info", {?DO_EXIT, case_clause})),
-
- %% Handle_info - stay-alive == true
- ?match({noreply, {?NO_EXIT, case_clause}},
- corba:handle_info(?MODULE, "info", {?NO_EXIT, case_clause})),
- ok.
-
-%% Callback function_clause API tests
-callback_function_clause_api(_) ->
- %% Handle_call - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_call(?MODULE, foo, [],
- {?DO_EXIT, function_clause}, [], false, false)),
- %% Handle_call - stay-alive == true
- ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}}, _},
- corba:handle_call(?MODULE, foo, [],
- {?NO_EXIT, function_clause}, [], false, false)),
- %% Handle_cast - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?DO_EXIT, function_clause}, [], false)),
- %% Handle_cast - stay-alive == true
- ?match({noreply, {?NO_EXIT, function_clause}},
- corba:handle_cast(?MODULE, foo_1w, [],
- {?NO_EXIT, function_clause}, [], false)),
- %% Handle_info - stay-alive == false
- ?match({'EXIT', _},
- corba:handle_info(?MODULE, "info", {?DO_EXIT, function_clause})),
- %% Handle_info - stay-alive == true
- ?match({noreply, {?NO_EXIT, function_clause}},
- corba:handle_info(?MODULE, "info", {?NO_EXIT, function_clause})),
- ok.
-
-%% Faked mandatory operations
-init(State) ->
- evaluate_state(State),
- {ok, State}.
-terminate(_Reason, State) ->
- evaluate_state(State),
- ok.
-
-code_change(_OldVsn, State, _Extra) ->
- evaluate_state(State),
- {ok, State}.
-handle_call(_,_, State) ->
- evaluate_state(State),
- {noreply, State}.
-handle_cast(_, State) ->
- evaluate_state(State),
- {noreply, State}.
-handle_info(_Info, State) ->
- evaluate_state(State),
- {noreply, State}.
-
-foo(State) ->
- evaluate_state(State),
- {reply, ok, State}.
-foo(State, _Arg) ->
- evaluate_state(State),
- {reply, ok, State}.
-
-foo_1w(State) ->
- evaluate_state(State),
- {noreply, State}.
-foo_1w(State, _Arg) ->
- evaluate_state(State),
- {noreply, State}.
-
-precond(_Module, _Function, _Args) ->
- ok.
-
-postcond(_Module, _Function, _Args, _Result) ->
- ok.
-
-evaluate_state(exit) ->
- exit("exit on purpose");
-evaluate_state(badarith) ->
- 10 * atom;
-evaluate_state(case_clause) ->
- case 10 of
- false ->
- ok
- end;
-evaluate_state(module) ->
- non_existing_module:bar();
-evaluate_state(function) ->
- ?MODULE:non_existing_function();
-evaluate_state(arity) ->
- ?MODULE:foo(to, many, arguments);
-evaluate_state(function_clause) ->
- evaluate_state(incorrect_state);
-evaluate_state(state) ->
- ok.
-
-%%-----------------------------------------------------------------
-%% Local functions.
-%%-----------------------------------------------------------------
-
-pseudo_calls(0, _) ->
- ok;
-pseudo_calls(Times, Obj) ->
- orber_test_server:pseudo_call(Obj),
- New = Times - 1,
- pseudo_calls(New, Obj).
-pseudo_casts(0, _) ->
- ok;
-pseudo_casts(Times, Obj) ->
- orber_test_server:pseudo_cast(Obj),
- New = Times - 1,
- pseudo_casts(New, Obj).
diff --git a/lib/orber/test/csiv2_SUITE.erl b/lib/orber/test/csiv2_SUITE.erl
deleted file mode 100644
index 7844060582..0000000000
--- a/lib/orber/test/csiv2_SUITE.erl
+++ /dev/null
@@ -1,889 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(csiv2_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/src/ifr_objects.hrl").
--include("idl_output/orber_test_server.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming_NamingContextExt.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming_NamingContext.hrl").
-%%-include_lib("orber/src/OrberCSIv2.hrl").
-
--define(default_timeout, test_server:minutes(5)).
-
--define(match(ExpectedRes,Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~nRESULT: ~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
--define(REQUEST_ID, 0).
-
--define(REPLY_FRAG_1, <<71,73,79,80,1,2,2,1,0,0,0,41,0,0,0,?REQUEST_ID,0,0,0,0,0,0,0,1,78,69,79,0,0,0,0,2,0,10,0,0,0,0,0,0,0,0,0,18,0,0,0,0,0,0,0,4,49>>).
-%% The fragments are identical for requests and replies.
--define(FRAG_2, <<71,73,79,80,1,2,2,7,0,0,0,5,0,0,0,?REQUEST_ID,50>>).
--define(FRAG_3, <<71,73,79,80,1,2,2,7,0,0,0,5,0,0,0,?REQUEST_ID,51>>).
--define(FRAG_4, <<71,73,79,80,1,2,0,7,0,0,0,5,0,0,0,?REQUEST_ID,0>>).
-
-%% Should X509 DER generated by, for example, OpenSSL
--define(X509DER,
- <<42>>).
-
-%% Should X509 PEM generated by, for example, OpenSSL
--define(X509PEM,
- <<42>>).
-
-%% IOR exported by VB (CSIv2 activated).
--define(VB_IOR,
- #'IOP_IOR'
- {type_id = "IDL:omg.org/CosNotifyComm/SequencePushConsumer:1.0",
- profiles =
- [#'IOP_TaggedProfile'
- {tag = ?TAG_INTERNET_IOP,
- profile_data =
- #'IIOP_ProfileBody_1_1'{
- iiop_version = #'IIOP_Version'{major = 1,
- minor = 2},
- host = "127.0.0.1",
- port = 0,
- object_key = [0,86,66,1,0,0,0,24,47,70,77,65,95,67,73,82,80,77,65,78,95,80,79,65,95,83,69,67,85,82,69,0,0,0,0,4,0,0,4,186,0,0,2,10,81,218,65,185],
- components =
- [#'IOP_TaggedComponent'{tag = ?TAG_SSL_SEC_TRANS,
- component_data = #'SSLIOP_SSL'{
- target_supports = 102,
- target_requires = 66,
- port = 49934}},
- #'IOP_TaggedComponent'{tag = ?TAG_CSI_SEC_MECH_LIST,
- component_data =
- #'CSIIOP_CompoundSecMechList'{stateful = true,
- mechanism_list =
- [#'CSIIOP_CompoundSecMech'
- {target_requires = 66,
- transport_mech = #'IOP_TaggedComponent'{
- tag = ?TAG_TLS_SEC_TRANS,
- component_data =
- #'CSIIOP_TLS_SEC_TRANS'{
- target_supports = 102,
- target_requires = 66,
- addresses =
- [#'CSIIOP_TransportAddress'
- {host_name = "127.0.0.1",
- port = 49934}]}},
- as_context_mech =
- #'CSIIOP_AS_ContextSec'{
- target_supports = 0,
- target_requires = 0,
- client_authentication_mech = [],
- target_name = []},
- sas_context_mech =
- #'CSIIOP_SAS_ContextSec'{
- target_supports = 1024,
- target_requires = 0,
- privilege_authorities =
- [#'CSIIOP_ServiceConfiguration'
- {syntax = 1447174401,
- name = "Borland"}],
- supported_naming_mechanisms = [[6,
- 6,
- 103,
- 129,
- 2,
- 1,
- 1,
- 1]],
- supported_identity_types = 15}}]}},
- #'IOP_TaggedComponent'
- {tag = ?TAG_CODE_SETS,
- component_data =
- #'CONV_FRAME_CodeSetComponentInfo'{'ForCharData' =
- #'CONV_FRAME_CodeSetComponent'{
- native_code_set = 65537,
- conversion_code_sets = [83951617]},
- 'ForWcharData' =
- #'CONV_FRAME_CodeSetComponent'{
- native_code_set = 65801,
- conversion_code_sets = []}}},
- #'IOP_TaggedComponent'{tag = ?TAG_ORB_TYPE,
- component_data = 1447645952},
- #'IOP_TaggedComponent'{tag = 1447645955,
- component_data = [0,5,7,1,127]}]}}]}).
-
-%% Common basic types
--define(OID, {2,23,130,1,1,1}).
-
--define(OCTET_STR, [1,2,3,4]).
-
--define(BIT_STR, [0,1,0,1,1]).
-
--define(BOOLEAN, false).
-
--define(ANY, [19,5,111,116,112,67,65]).
-
--ifdef(false).
-%% PKIX1Explicit88
--define(AlgorithmIdentifier,
- #'AlgorithmIdentifier'{algorithm = ?OID,
- parameters = ?ANY}).
-
--define(Validity, #'Validity'{notBefore = {utcTime, "19820102070533.8"},
- notAfter = {generalTime, "19820102070533.8"}}).
-
--define(SubjectPublicKeyInfo,
- #'SubjectPublicKeyInfo'{algorithm = ?AlgorithmIdentifier,
- subjectPublicKey = ?BIT_STR}).
-
--define(AttributeTypeAndValue,
- #'AttributeTypeAndValue'{type = ?OID,
- value = <<19,11,69,114,105,99,115,115,111,110,32,65,66>>}).
-
--define(RelativeDistinguishedName, [?AttributeTypeAndValue]).
-
--define(RDNSequence, [?RelativeDistinguishedName]).
-
--define(Name, {rdnSequence, ?RDNSequence}).
-
--define(Version, v3).
-
--define(CertificateSerialNumber, 1).
-
--define(UniqueIdentifier, ?BIT_STR).
-
--define(Extension, #'Extension'{extnID = ?OID,
- critical = ?BOOLEAN,
- extnValue = ?OCTET_STR}).
-
--define(Extensions, [?Extension]).
-
--define(TBSCertificate,
- #'TBSCertificate'{version = ?Version,
- serialNumber = ?CertificateSerialNumber,
- signature = ?AlgorithmIdentifier,
- issuer = ?Name,
- validity = ?Validity,
- subject = ?Name,
- subjectPublicKeyInfo = ?SubjectPublicKeyInfo,
- issuerUniqueID = ?UniqueIdentifier,
- subjectUniqueID = ?UniqueIdentifier,
- extensions = ?Extensions}).
-
--define(Certificate, #'Certificate'{tbsCertificate = ?TBSCertificate,
- signatureAlgorithm = ?AlgorithmIdentifier,
- signature = ?BIT_STR}).
-
-%% PKIX1Implicit88
-
--define(GeneralName, {registeredID, ?OID}).
-
--define(GeneralNames, [?GeneralName]).
-
-%% PKIXAttributeCertificate
--define(AttCertValidityPeriod,
- #'AttCertValidityPeriod'{notBeforeTime = "19820102070533.8",
- notAfterTime = "19820102070533.8"}).
-
-
--define(Attribute, #'Attribute'{type = ?OID,
- values = []}).
-
--define(Attributes, [?Attribute]).
-
--define(IssuerSerial, #'IssuerSerial'{issuer = ?GeneralNames,
- serial = ?CertificateSerialNumber,
- issuerUID = ?UniqueIdentifier}).
-
--define(DigestedObjectType, publicKey). %% Enum
-
--define(ObjectDigestInfo,
- #'ObjectDigestInfo'{digestedObjectType = ?DigestedObjectType,
- otherObjectTypeID = ?OID,
- digestAlgorithm = ?AlgorithmIdentifier,
- objectDigest = ?BIT_STR}).
-
--define(V2Form, #'V2Form'{issuerName = ?GeneralNames,
- baseCertificateID = ?IssuerSerial,
- objectDigestInfo = ?ObjectDigestInfo}).
-
--define(AttCertVersion, v2).
-
--define(Holder, #'Holder'{baseCertificateID = ?IssuerSerial,
- entityName = ?GeneralNames,
- objectDigestInfo = ?ObjectDigestInfo}).
-
--define(AttCertIssuer, {v2Form, ?V2Form}).
-
--define(AttributeCertificateInfo,
- #'AttributeCertificateInfo'{version = ?AttCertVersion,
- holder = ?Holder,
- issuer = ?AttCertIssuer,
- signature = ?AlgorithmIdentifier,
- serialNumber = ?CertificateSerialNumber,
- attrCertValidityPeriod = ?AttCertValidityPeriod,
- attributes = ?Attributes,
- issuerUniqueID = ?UniqueIdentifier,
- extensions = ?Extensions}).
-
--define(AttributeCertificate,
- #'AttributeCertificate'{acinfo = ?AttributeCertificateInfo,
- signatureAlgorithm = ?AlgorithmIdentifier,
- signatureValue = ?BIT_STR}).
-
-
-%% OrberCSIv2
--define(AttributeCertChain,
- #'AttributeCertChain'{attributeCert = ?AttributeCertificate,
- certificateChain = ?CertificateChain}).
-
--define(CertificateChain, [?Certificate]).
-
--define(VerifyingCertChain, [?Certificate]).
-
--endif.
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, cases/0,
- init_per_suite/1, end_per_suite/1,
- init_per_testcase/2, end_per_testcase/2,
-% code_CertificateChain_api/1,
-% code_AttributeCertChain_api/1,
-% code_VerifyingCertChain_api/1,
-% code_AttributeCertificate_api/1,
-% code_Certificate_api/1,
-% code_TBSCertificate_api/1,
-% code_CertificateSerialNumber_api/1,
-% code_Version_api/1,
-% code_AlgorithmIdentifier_api/1,
-% code_Name_api/1,
-% code_RDNSequence_api/1,
-% code_RelativeDistinguishedName_api/1,
-% code_AttributeTypeAndValue_api/1,
-% code_Attribute_api/1,
-% code_Validity_api/1,
-% code_SubjectPublicKeyInfo_api/1,
-% code_UniqueIdentifier_api/1,
-% code_Extensions_api/1,
-% code_Extension_api/1,
-% code_AttributeCertificateInfo_api/1,
-% code_AttCertVersion_api/1,
-% code_Holder_api/1,
-% code_AttCertIssuer_api/1,
-% code_AttCertValidityPeriod_api/1,
-% code_V2Form_api/1,
-% code_IssuerSerial_api/1,
-% code_ObjectDigestInfo_api/1,
-% code_OpenSSL509_api/1,
- ssl_server_peercert_api/1,
- ssl_client_peercert_api/1]).
-
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([fake_server_ORB/5]).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% NOTE - the fragment test cases must bu first since we explicitly set a request
-%% id. Otherwise, the request-id counter would be increased and we cannot know
-%% what it is.
-cases() ->
- [ssl_server_peercert_api, ssl_client_peercert_api].
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-
-init_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- Dog=test_server:timetrap(?default_timeout),
- orber:jump_start(0),
- oe_orber_test_server:oe_register(),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- oe_orber_test_server:oe_unregister(),
- orber:jump_stop(),
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) ->
- try crypto:start() of
- ok ->
- case orber_test_lib:ssl_version() of
- no_ssl ->
- {skip, "SSL is not installed!"};
- _ ->
- Config
- end
- catch _:_ ->
- {skip, "Crypto did not start"}
- end.
-
-end_per_suite(Config) ->
- application:stop(crypto),
- Config.
-
-%%-----------------------------------------------------------------
-%% API tests for ORB to ORB, no security
-%%-----------------------------------------------------------------
-
-
-%%-----------------------------------------------------------------
-%% Encode and decode ASN.1 X509
-%%-----------------------------------------------------------------
-
--ifdef(false).
-%% OrberCSIv2
-%%-----------------------------------------------------------------
-%% Code CertificateChain
-code_CertificateChain_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
- 'OrberCSIv2':encode('CertificateChain', ?CertificateChain)),
- ?match({ok, [#'Certificate'{}]},
- 'OrberCSIv2':decode('CertificateChain', list_to_binary(Enc))),
- ok.
-
-%% Code AttributeCertChain
-code_AttributeCertChain_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
- 'OrberCSIv2':encode('AttributeCertChain', ?AttributeCertChain)),
- ?match({ok, #'AttributeCertChain'{}},
- 'OrberCSIv2':decode('AttributeCertChain', list_to_binary(Enc))),
- ok.
-
-%% Code VerifyingCertChain
-code_VerifyingCertChain_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
- 'OrberCSIv2':encode('VerifyingCertChain', ?VerifyingCertChain)),
- ?match({ok, [#'Certificate'{}]},
- 'OrberCSIv2':decode('VerifyingCertChain', list_to_binary(Enc))),
- ok.
-
-%% PKIXAttributeCertificate
-%%-----------------------------------------------------------------
-%% Code AttributeCertificate
-code_AttributeCertificate_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
- 'OrberCSIv2':encode('AttributeCertificate', ?AttributeCertificate)),
- ?match({ok, #'AttributeCertificate'{}},
- 'OrberCSIv2':decode('AttributeCertificate', list_to_binary(Enc))),
- ok.
-
-%% Code AttributeCertificateInfo
-code_AttributeCertificateInfo_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
- 'OrberCSIv2':encode('AttributeCertificateInfo', ?AttributeCertificateInfo)),
- ?match({ok, #'AttributeCertificateInfo'{}},
- 'OrberCSIv2':decode('AttributeCertificateInfo', list_to_binary(Enc))),
- ok.
-
-%% Code AttCertVersion
-code_AttCertVersion_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
- 'OrberCSIv2':encode('AttCertVersion', ?AttCertVersion)),
- ?match({ok, ?AttCertVersion},
- 'OrberCSIv2':decode('AttCertVersion', list_to_binary(Enc))),
- ok.
-
-%% Code Holder
-code_Holder_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
- 'OrberCSIv2':encode('Holder', ?Holder)),
- ?match({ok, #'Holder'{}},
- 'OrberCSIv2':decode('Holder', list_to_binary(Enc))),
- ok.
-
-%% Code AttCertIssuer
-code_AttCertIssuer_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
- 'OrberCSIv2':encode('AttCertIssuer', ?AttCertIssuer)),
- ?match({ok, {v2Form, _}},
- 'OrberCSIv2':decode('AttCertIssuer', list_to_binary(Enc))),
- ok.
-
-%% Code AttCertValidityPeriod
-code_AttCertValidityPeriod_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _}, 'OrberCSIv2':encode('AttCertValidityPeriod', ?AttCertValidityPeriod)),
- ?match({ok, #'AttCertValidityPeriod'{}},
- 'OrberCSIv2':decode('AttCertValidityPeriod', list_to_binary(Enc))),
- ok.
-
-%% Code V2Form
-code_V2Form_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
- 'OrberCSIv2':encode('V2Form', ?V2Form)),
- ?match({ok, #'V2Form'{}},
- 'OrberCSIv2':decode('V2Form', list_to_binary(Enc))),
- ok.
-
-%% Code IssuerSerial
-code_IssuerSerial_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
- 'OrberCSIv2':encode('IssuerSerial', ?IssuerSerial)),
- ?match({ok, #'IssuerSerial'{}},
- 'OrberCSIv2':decode('IssuerSerial', list_to_binary(Enc))),
- ok.
-
-%% Code ObjectDigestInfo
-code_ObjectDigestInfo_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
- 'OrberCSIv2':encode('ObjectDigestInfo', ?ObjectDigestInfo)),
- ?match({ok, #'ObjectDigestInfo'{}},
- 'OrberCSIv2':decode('ObjectDigestInfo', list_to_binary(Enc))),
- ok.
-
-%% PKIX1Explicit88
-%%-----------------------------------------------------------------
-%% Code Certificate
-code_Certificate_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
- 'OrberCSIv2':encode('Certificate', ?Certificate)),
- ?match({ok, #'Certificate'{}},
- 'OrberCSIv2':decode('Certificate', list_to_binary(Enc))),
- ok.
-
-%% Code TBSCertificate
-code_TBSCertificate_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
- 'OrberCSIv2':encode('TBSCertificate', ?TBSCertificate)),
- ?match({ok, #'TBSCertificate'{}},
- 'OrberCSIv2':decode('TBSCertificate', list_to_binary(Enc))),
- ok.
-
-%% Code CertificateSerialNumber"];
-code_CertificateSerialNumber_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _},
- 'OrberCSIv2':encode('CertificateSerialNumber', ?CertificateSerialNumber)),
- ?match({ok, ?CertificateSerialNumber},
- 'OrberCSIv2':decode('CertificateSerialNumber', list_to_binary(Enc))),
- ok.
-
-%% Code Version
-code_Version_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _}, 'OrberCSIv2':encode('Version', ?Version)),
- ?match({ok, ?Version}, 'OrberCSIv2':decode('Version', list_to_binary(Enc))),
- ok.
-
-%% Code AlgorithmIdentifier
-code_AlgorithmIdentifier_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _}, 'OrberCSIv2':encode('AlgorithmIdentifier', ?AlgorithmIdentifier)),
- ?match({ok, #'AlgorithmIdentifier'{}},
- 'OrberCSIv2':decode('AlgorithmIdentifier', list_to_binary(Enc))),
- ok.
-
-%% Code Name
-code_Name_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _}, 'OrberCSIv2':encode('Name', ?Name)),
- ?match({ok, {rdnSequence,_}},
- 'OrberCSIv2':decode('Name', list_to_binary(Enc))),
- ok.
-
-%% Code RDNSequence
-code_RDNSequence_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _}, 'OrberCSIv2':encode('RDNSequence', ?RDNSequence)),
- ?match({ok, [[#'AttributeTypeAndValue'{}]]},
- 'OrberCSIv2':decode('RDNSequence', list_to_binary(Enc))),
- ok.
-
-%% Code RelativeDistinguishedName
-code_RelativeDistinguishedName_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _}, 'OrberCSIv2':encode('RelativeDistinguishedName', ?RelativeDistinguishedName)),
- ?match({ok, [#'AttributeTypeAndValue'{}]},
- 'OrberCSIv2':decode('RelativeDistinguishedName', list_to_binary(Enc))),
- ok.
-
-%% Code AttributeTypeAndValue
-code_AttributeTypeAndValue_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _}, 'OrberCSIv2':encode('AttributeTypeAndValue', ?AttributeTypeAndValue)),
- ?match({ok, #'AttributeTypeAndValue'{}},
- 'OrberCSIv2':decode('AttributeTypeAndValue', list_to_binary(Enc))),
- ok.
-
-%% Code Attribute"];
-code_Attribute_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _}, 'OrberCSIv2':encode('Attribute', ?Attribute)),
- ?match({ok, #'Attribute'{}},
- 'OrberCSIv2':decode('Attribute', list_to_binary(Enc))),
- ok.
-
-%% Code Validity
-code_Validity_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _}, 'OrberCSIv2':encode('Validity', ?Validity)),
- ?match({ok, #'Validity'{}},
- 'OrberCSIv2':decode('Validity', list_to_binary(Enc))),
- ok.
-
-%% Code SubjectPublicKeyInfo
-code_SubjectPublicKeyInfo_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _}, 'OrberCSIv2':encode('SubjectPublicKeyInfo', ?SubjectPublicKeyInfo)),
- ?match({ok, #'SubjectPublicKeyInfo'{}},
- 'OrberCSIv2':decode('SubjectPublicKeyInfo', list_to_binary(Enc))),
- ok.
-
-%% Code UniqueIdentifier
-code_UniqueIdentifier_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _}, 'OrberCSIv2':encode('UniqueIdentifier', ?UniqueIdentifier)),
- ?match({ok, _}, 'OrberCSIv2':decode('UniqueIdentifier', list_to_binary(Enc))),
- ok.
-
-%% Code Extensions
-code_Extensions_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _}, 'OrberCSIv2':encode('Extensions', ?Extensions)),
- ?match({ok, [#'Extension'{}]},
- 'OrberCSIv2':decode('Extensions', list_to_binary(Enc))),
- ok.
-
-%% Code Extension
-code_Extension_api(_Config) ->
- {ok, Enc} =
- ?match({ok, _}, 'OrberCSIv2':encode('Extension', ?Extension)),
- ?match({ok, #'Extension'{}},
- 'OrberCSIv2':decode('Extension', list_to_binary(Enc))),
- ok.
-
-%% OpenSSL generated x509 Certificate
-%%-----------------------------------------------------------------
-%% Code OpenSSL generated x509 Certificate
-code_OpenSSL509_api(_Config) ->
- {ok, Cert} =
- ?match({ok, #'Certificate'{}},
- 'OrberCSIv2':decode('Certificate', ?X509DER)),
- AttrCertChain = #'AttributeCertChain'{attributeCert = ?AttributeCertificate,
- certificateChain = [Cert]},
- {ok, EAttrCertChain} =
- ?match({ok, _}, 'OrberCSIv2':encode('AttributeCertChain', AttrCertChain)),
- ?match({ok, #'AttributeCertChain'{}},
- 'OrberCSIv2':decode('AttributeCertChain', list_to_binary(EAttrCertChain))),
- ok.
-
--endif.
-
-%%-----------------------------------------------------------------
-%% Test ssl:peercert
-%%-----------------------------------------------------------------
-%% Test ssl:peercert (server side)
-ssl_server_peercert_api(_Config) ->
- Options = orber_test_lib:get_options(iiop_ssl, server,
- 2, [{iiop_ssl_port, 0}]),
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node(Options)),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_ssl_port, []),
- SSLOptions = orber_test_lib:get_options(ssl, client),
- {ok, Socket} =
- ?match({ok, _}, fake_client_ORB(ssl, ServerHost, ServerPort, SSLOptions)),
- {ok, _PeerCert} = ?match({ok, _}, orber_socket:peercert(ssl, Socket)),
- %% ?match({ok, {rdnSequence, _}}, orber_socket:peercert(ssl, Socket, [pkix, subject])),
- %% ?match({ok, {rdnSequence, _}}, orber_socket:peercert(ssl, Socket, [ssl, subject])),
- % ?match({ok, #'Certificate'{}},
- % 'OrberCSIv2':decode('Certificate', PeerCert)),
- destroy_fake_ORB(ssl, Socket),
- ok.
-
-%% Test ssl:peercert (client side)
-ssl_client_peercert_api(_Config) ->
- Options = orber_test_lib:get_options(iiop_ssl, client,
- 2, [{iiop_ssl_port, 0}]),
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node(Options)),
- crypto:start(),
- ssl:start(),
- SSLOptions = orber_test_lib:get_options(ssl, server),
- {ok, LSock} = ?match({ok, _}, ssl:listen(0, SSLOptions)),
- {ok, {_Address, LPort}} = ?match({ok, {_, _}}, ssl:sockname(LSock)),
- IOR = ?match({'IOP_IOR',_,_},
- iop_ior:create_external({1, 2}, "IDL:FAKE:1.0",
- "localhost", 6004, "FAKE",
- [#'IOP_TaggedComponent'
- {tag=?TAG_SSL_SEC_TRANS,
- component_data=#'SSLIOP_SSL'
- {target_supports = 2,
- target_requires = 2,
- port = LPort}}])),
- spawn(orber_test_lib, remote_apply,
- [ClientNode, corba_object, non_existent, [IOR]]),
- {ok, Socket} = ?match({ok, _}, ssl:transport_accept(LSock)),
- ?match(ok, ssl:ssl_accept(Socket)),
-
- {ok, _PeerCert} = ?match({ok, _}, orber_socket:peercert(ssl, Socket)),
- %% ?match({ok, {rdnSequence, _}}, orber_socket:peercert(ssl, Socket, [pkix, subject])),
- %% ?match({ok, {rdnSequence, _}}, orber_socket:peercert(ssl, Socket, [ssl, subject])),
- % ?match({ok, #'Certificate'{}},
- % 'OrberCSIv2':decode('Certificate', PeerCert)),
- ssl:close(Socket),
- ssl:close(LSock),
- ssl:stop(),
- ok.
-
-%%-----------------------------------------------------------------
-%% Local functions.
-%%-----------------------------------------------------------------
--ifdef(false).
-%% Not used yet.
-context_test(Obj) ->
- IDToken1 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTAbsent,
- value = true},
- IDToken2 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTAnonymous,
- value = false},
- IDToken3 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTPrincipalName,
- value = [0,255]},
- IDToken4 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTX509CertChain,
- value = [1,255]},
- IDToken5 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTDistinguishedName,
- value = [2,255]},
- IDToken6 = #'CSI_IdentityToken'{label = ?ULONGMAX,
- value = [3,255]},
-
- MTEstablishContext1 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
- [#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken1,
- client_authentication_token = [1, 255]}},
- MTEstablishContext2 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
- [#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken2,
- client_authentication_token = [1, 255]}},
- MTEstablishContext3 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
- [#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken3,
- client_authentication_token = [1, 255]}},
- MTEstablishContext4 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
- [#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken4,
- client_authentication_token = [1, 255]}},
- MTEstablishContext5 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
- [#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken5,
- client_authentication_token = [1, 255]}},
- MTEstablishContext6 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
- [#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken6,
- client_authentication_token = [1, 255]}},
- MTCompleteEstablishContext = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTCompleteEstablishContext,
- value = #'CSI_CompleteEstablishContext'{client_context_id = ?ULONGLONGMAX,
- context_stateful = false,
- final_context_token = [1, 255]}},
- MTContextError = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTContextError,
- value = #'CSI_ContextError'{client_context_id = ?ULONGLONGMAX,
- major_status = 1,
- minor_status = 2,
- error_token = [2,255]}},
- MTMessageInContext = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTMessageInContext,
- value = #'CSI_MessageInContext'{client_context_id = ?ULONGLONGMAX,
- discard_context = true}},
- Ctx = [#'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = MTEstablishContext1},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = MTEstablishContext2},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = MTEstablishContext3},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = MTEstablishContext4},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = MTEstablishContext5},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = MTEstablishContext6},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = MTCompleteEstablishContext},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = MTContextError},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = MTMessageInContext}],
- ?match(ok, orber_test_server:testing_iiop_context(Obj, [{context, Ctx}])).
-
-
-fake_server_ORB(Type, Port, Options) ->
- start_ssl(Type),
- {ok, ListenSocket, NewPort} =
- orber_socket:listen(Type, Port,
- [{active, false}|Options]),
- Socket = orber_socket:accept(Type, ListenSocket),
- orber_socket:post_accept(Type, Socket),
- {ok, Socket, NewPort}.
-
--endif.
-
-fake_server_ORB(Type, Port, Options, Action, Data) ->
- start_ssl(Type),
- {ok, ListenSocket, _NewPort} =
- orber_socket:listen(Type, Port, [{active, false}|Options]),
- Socket = orber_socket:accept(Type, ListenSocket),
- orber_socket:post_accept(Type, Socket),
- do_server_action(Type, Socket, Action, Data),
- orber_socket:close(Type, Socket),
- ok.
-
-start_ssl(ssl) ->
- crypto:start(),
- ssl:start();
-start_ssl(_) ->
- ok.
-
-
-destroy_fake_ORB(ssl, Socket) ->
- orber_socket:close(ssl, Socket),
- ssl:stop();
-destroy_fake_ORB(Type, Socket) ->
- orber_socket:close(Type, Socket).
-
-fake_client_ORB(Type, Host, Port, Options) ->
- start_ssl(Type),
- Socket = orber_socket:connect(Type, Host, Port, [{active, false}|Options]),
- {ok, Socket}.
-
--ifdef(false).
-%% Not used yet.
-
-fake_client_ORB(Type, Host, Port, Options, Action, Data) ->
- start_ssl(Type),
- Socket = orber_socket:connect(Type, Host, Port, [{active, false}|Options]),
- Result = do_client_action(Type, Socket, Action, Data),
- orber_socket:close(Type, Socket),
- Result.
-
-do_client_action(Type, Socket, fragments, FragList) ->
- ok = send_data(Type, Socket, FragList),
- {ok, Bytes} = gen_tcp:recv(Socket, 0),
- {#reply_header{request_id = ?REQUEST_ID, reply_status = no_exception}, ok, [Par]} =
- cdr_decode:dec_message({tk_void,[tk_any],[tk_any]}, Bytes),
- Par;
-do_client_action(Type, Socket, fragments_max, FragList) ->
- ok = send_data(Type, Socket, FragList),
- {ok, Bytes} = gen_tcp:recv(Socket, 0),
- {#reply_header{request_id = ?REQUEST_ID, reply_status = system_exception}, Exc, []} =
- cdr_decode:dec_message({tk_void,[tk_any],[tk_any]}, Bytes),
- Exc;
-do_client_action(Type, Socket, message_error, Data) ->
- ok = send_data(Type, Socket, Data),
- {ok,Bytes} = gen_tcp:recv(Socket, 0),
- 'message_error' = cdr_decode:dec_message({tk_void,[tk_any],[tk_any]}, Bytes),
- ok;
-do_client_action(_Type, _Socket, _Action, _Data) ->
- ok.
-
--endif.
-
-do_server_action(Type, Socket, fragments, FragList) ->
- {ok, _B} = gen_tcp:recv(Socket, 0),
- ok = send_data(Type, Socket, FragList);
-do_server_action(_Type, _Socket, _Action, _Data) ->
- ok.
-
-
-send_data(_Type, _Socket, []) ->
- ok;
-send_data(Type, Socket, [H|T]) ->
- orber_socket:write(Type, Socket, H),
- send_data(Type, Socket, T).
-
diff --git a/lib/orber/test/data_types_SUITE.erl b/lib/orber/test/data_types_SUITE.erl
deleted file mode 100644
index 3873bfbaf6..0000000000
--- a/lib/orber/test/data_types_SUITE.erl
+++ /dev/null
@@ -1,187 +0,0 @@
-%%-----------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File : data_types_SUITE.erl
-%% Purpose :
-%%-----------------------------------------------------------------
-
--module(data_types_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
-
--define(default_timeout, test_server:minutes(3)).
-
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [fixed_type, any_type].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: Fixed Point Datatype
-%% Description:
-%%-----------------------------------------------------------------
-fixed_type(_) ->
- Val1 = ?match({fixed,3,2,314}, orber_test_server:val1()),
- _Val2 = ?match({fixed,3,2,314}, orber_test_server:val2()),
- _Val3 = ?match({fixed,3,2,314}, orber_test_server:val3()),
- Val4 = ?match({fixed,3,2,314}, orber_test_server:val4()),
- Val5 = ?match({fixed,2,2,14}, orber_test_server:val5()),
- _Val6 = ?match({fixed,1,0,3}, orber_test_server:val6()),
- Val7 = ?match({fixed,2,2,-14}, orber_test_server:val7()),
- _Val8 = ?match({fixed,1,0,-3}, orber_test_server:val8()),
- Val9 = ?match({fixed,3,2,328}, orber_test_server:val9()),
- Val10 = ?match({fixed,4,4,4396}, orber_test_server:val10()),
- Val11 = ?match({fixed,31,29,2242857142857142857142857142857}, orber_test_server:val11()),
- Val12 = ?match({fixed,9,6,123140001}, orber_test_server:val12()),
- Val13 = ?match({fixed,9,1,123140001}, orber_test_server:val13()),
- Val14 = ?match({fixed,14,6,-12313876959999}, orber_test_server:val14()),
- Val15 = ?match({fixed,14,6,12314123240001}, orber_test_server:val15()),
- Val16 = ?match({fixed,17,7,15163459846280001}, orber_test_server:val16()),
- _Val17 = ?match({fixed,3,2,402}, orber_test_server:val17()),
- _Val18 = ?match({fixed,5,4,40401}, orber_test_server:val18()),
- _Val19 = ?match({fixed,3,0,200}, orber_test_server:val19()),
- Val20 = ?match({fixed,31,0,1999999999999999999999999999999}, orber_test_server:val20()),
- Val21 = ?match({fixed,1,0,0}, orber_test_server:val21()),
- Val22 = ?match({fixed,31,0,9999999999999999999999999999998}, orber_test_server:val22()),
- Val23 = ?match({fixed,1,0,1}, orber_test_server:val23()),
- _Val24 = ?match({fixed,5,0,19998}, orber_test_server:val24()),
- _Val25 = ?match({fixed,2,0,40}, orber_test_server:val25()),
- Val26 = ?match({fixed,31,0,9999999999999999999999999999999}, orber_test_server:val26()),
-
- ?match(Val1, fixed:create(3,2,314)),
- Val27 = ?match({fixed,6,2,314}, fixed:create(6,2,314)),
-
- ?match({tk_fixed,3,2}, fixed:get_typecode(Val1)),
- ?match({tk_fixed,6,2}, fixed:get_typecode(Val27)),
- ?match({'EXCEPTION',{'BAD_PARAM',_,_,_}}, fixed:create(3,2,3140)),
- ?match({'EXCEPTION',{'BAD_PARAM',_,_,_}}, fixed:create(5,6,314)),
- ?match({'EXCEPTION',{'BAD_PARAM',_,_,_}}, fixed:create(32,2,314)),
- ?match(Val10, fixed:multiply(Val4, Val5)),
- ?match(Val16, fixed:multiply(Val12, Val13)),
- ?match(Val22, fixed:multiply(Val26, Val26)),
-
- ?match(Val9, fixed:add(Val4, Val5)),
- ?match(Val15, fixed:add(Val12, Val13)),
- ?match(Val20, fixed:add(Val26, Val26)),
-
- ?match(Val11, fixed:divide(Val4, Val5)),
- ?match(Val23, fixed:divide(Val26, Val26)),
-
- ?match(Val14, fixed:subtract(Val12, Val13)),
- ?match(Val21, fixed:subtract(Val26, Val26)),
-
- ?match(Val7, fixed:unary_minus(Val5)),
- ?match(Val5, fixed:unary_minus(Val7)),
-
-
-
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: Any type
-%% Description:
-%%-----------------------------------------------------------------
-any_type(_) ->
- ?match(#any{typecode=undefined, value=undefined},
- any:create()),
- ?match(#any{typecode=tk_short, value=undefined},
- any:set_typecode(any:create(), tk_short)),
- ?match({'EXCEPTION', #'BAD_TYPECODE'{}},
- any:set_typecode(any:create(), "wrong")),
- ?match({'EXCEPTION', #'BAD_TYPECODE'{}},
- any:create("wrong", 1)),
- ?match(#any{typecode=tk_short, value = 1},
- any:create(tk_short, 1)),
- ?match(tk_short,
- any:get_typecode(any:create(tk_short, 1))),
- ?match(1,
- any:get_value(any:create(tk_short, 1))),
- ?match(#any{typecode=tk_short, value=2},
- any:set_value(any:create(tk_short, 1), 2)),
-
- ok.
diff --git a/lib/orber/test/generated_SUITE.erl b/lib/orber/test/generated_SUITE.erl
deleted file mode 100644
index 3550941dfd..0000000000
--- a/lib/orber/test/generated_SUITE.erl
+++ /dev/null
@@ -1,372 +0,0 @@
-%%-----------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File : generated_SUITE.erl
-%% Purpose :
-%%-----------------------------------------------------------------
-
--module(generated_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
-
--define(default_timeout, test_server:minutes(3)).
-
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
--define(nomatch(Not, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- Not ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS);
- _ ->
- AcTuAlReS
- end
- end()).
-
-
--define(checktc(_Op),
- fun(TC) ->
- case orber_tc:check_tc(TC) of
- false ->
- io:format("###### ERROR ERROR ######~n~p - ~p~n", [Op, TC]),
- exit(TC);
- true ->
- true
- end
- end).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- ['OrberApp_IFR', erlang_binary, erlang_pid, erlang_port,
- erlang_ref, 'CosNaming_Binding',
- 'CosNaming_BindingList', 'CosNaming_Name',
- 'CosNaming_NameComponent',
- 'CosNaming_NamingContextExt_InvalidAddress',
- 'CosNaming_NamingContext_AlreadyBound',
- 'CosNaming_NamingContext_CannotProceed',
- 'CosNaming_NamingContext_InvalidName',
- 'CosNaming_NamingContext_NotEmpty',
- 'CosNaming_NamingContext_NotFound',
- 'CosNaming_BindingIterator', 'CosNaming_NamingContext',
- 'CosNaming_NamingContextExt'].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case:'OrberApp_IFR'
-%% Description:
-%%-----------------------------------------------------------------
-'OrberApp_IFR'(_) ->
- ?nomatch(undefined, 'OrberApp_IFR':oe_tc(get_absolute_name)),
- ?nomatch(undefined, 'OrberApp_IFR':oe_tc(get_user_exception_type)),
- ?match(undefined, 'OrberApp_IFR':oe_tc(undefined)),
- ?match([_|_], 'OrberApp_IFR':oe_get_interface()),
- ?match("IDL:OrberApp/IFR:1.0", 'OrberApp_IFR':typeID()),
- check_tc('OrberApp_IFR':oe_get_interface()),
- ?match(true, 'OrberApp_IFR':oe_is_a('OrberApp_IFR':typeID())),
- ?match(false, 'OrberApp_IFR':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: erlang_binary
-%% Description:
-%%-----------------------------------------------------------------
-erlang_binary(_) ->
- ?match(true, orber_tc:check_tc(erlang_binary:tc())),
- ?match("IDL:erlang/binary:1.0", erlang_binary:id()),
- ?match("erlang_binary", erlang_binary:name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: erlang_pid
-%% Description:
-%%-----------------------------------------------------------------
-erlang_pid(_) ->
- ?match(true, orber_tc:check_tc(erlang_pid:tc())),
- ?match("IDL:erlang/pid:1.0", erlang_pid:id()),
- ?match("erlang_pid", erlang_pid:name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: erlang_port
-%% Description:
-%%-----------------------------------------------------------------
-erlang_port(_) ->
- ?match(true, orber_tc:check_tc(erlang_port:tc())),
- ?match("IDL:erlang/port:1.0", erlang_port:id()),
- ?match("erlang_port", erlang_port:name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: erlang_ref
-%% Description:
-%%-----------------------------------------------------------------
-erlang_ref(_) ->
- ?match(true, orber_tc:check_tc(erlang_ref:tc())),
- ?match("IDL:erlang/ref:1.0", erlang_ref:id()),
- ?match("erlang_ref", erlang_ref:name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNaming_Binding'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNaming_Binding'(_) ->
- ?match(true, orber_tc:check_tc('CosNaming_Binding':tc())),
- ?match("IDL:omg.org/CosNaming/Binding:1.0", 'CosNaming_Binding':id()),
- ?match("CosNaming_Binding", 'CosNaming_Binding':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNaming_BindingList'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNaming_BindingList'(_) ->
- ?match(true, orber_tc:check_tc('CosNaming_BindingList':tc())),
- ?match("IDL:omg.org/CosNaming/BindingList:1.0", 'CosNaming_BindingList':id()),
- ?match("CosNaming_BindingList", 'CosNaming_BindingList':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNaming_Name'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNaming_Name'(_) ->
- ?match(true, orber_tc:check_tc('CosNaming_Name':tc())),
- ?match("IDL:omg.org/CosNaming/Name:1.0", 'CosNaming_Name':id()),
- ?match("CosNaming_Name", 'CosNaming_Name':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNaming_NameComponent'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNaming_NameComponent'(_) ->
- ?match(true, orber_tc:check_tc('CosNaming_NameComponent':tc())),
- ?match("IDL:omg.org/CosNaming/NameComponent:1.0", 'CosNaming_NameComponent':id()),
- ?match("CosNaming_NameComponent", 'CosNaming_NameComponent':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNaming_NamingContextExt_InvalidAddress'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNaming_NamingContextExt_InvalidAddress'(_) ->
- ?match(true, orber_tc:check_tc('CosNaming_NamingContextExt_InvalidAddress':tc())),
- ?match("IDL:omg.org/CosNaming/NamingContextExt/InvalidAddress:1.0", 'CosNaming_NamingContextExt_InvalidAddress':id()),
- ?match("CosNaming_NamingContextExt_InvalidAddress", 'CosNaming_NamingContextExt_InvalidAddress':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNaming_NamingContext_AlreadyBound'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNaming_NamingContext_AlreadyBound'(_) ->
- ?match(true, orber_tc:check_tc('CosNaming_NamingContext_AlreadyBound':tc())),
- ?match("IDL:omg.org/CosNaming/NamingContext/AlreadyBound:1.0", 'CosNaming_NamingContext_AlreadyBound':id()),
- ?match("CosNaming_NamingContext_AlreadyBound", 'CosNaming_NamingContext_AlreadyBound':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNaming_NamingContext_CannotProceed'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNaming_NamingContext_CannotProceed'(_) ->
- ?match(true, orber_tc:check_tc('CosNaming_NamingContext_CannotProceed':tc())),
- ?match("IDL:omg.org/CosNaming/NamingContext/CannotProceed:1.0", 'CosNaming_NamingContext_CannotProceed':id()),
- ?match("CosNaming_NamingContext_CannotProceed", 'CosNaming_NamingContext_CannotProceed':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNaming_NamingContext_InvalidName'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNaming_NamingContext_InvalidName'(_) ->
- ?match(true, orber_tc:check_tc('CosNaming_NamingContext_InvalidName':tc())),
- ?match("IDL:omg.org/CosNaming/NamingContext/InvalidName:1.0", 'CosNaming_NamingContext_InvalidName':id()),
- ?match("CosNaming_NamingContext_InvalidName", 'CosNaming_NamingContext_InvalidName':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNaming_NamingContext_NotEmpty'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNaming_NamingContext_NotEmpty'(_) ->
- ?match(true, orber_tc:check_tc('CosNaming_NamingContext_NotEmpty':tc())),
- ?match("IDL:omg.org/CosNaming/NamingContext/NotEmpty:1.0", 'CosNaming_NamingContext_NotEmpty':id()),
- ?match("CosNaming_NamingContext_NotEmpty", 'CosNaming_NamingContext_NotEmpty':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNaming_NamingContext_NotFound'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNaming_NamingContext_NotFound'(_) ->
- ?match(true, orber_tc:check_tc('CosNaming_NamingContext_NotFound':tc())),
- ?match("IDL:omg.org/CosNaming/NamingContext/NotFound:1.0", 'CosNaming_NamingContext_NotFound':id()),
- ?match("CosNaming_NamingContext_NotFound", 'CosNaming_NamingContext_NotFound':name()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNaming_BindingIterator'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNaming_BindingIterator'(_) ->
- ?nomatch(undefined, 'CosNaming_BindingIterator':oe_tc(next_one)),
- ?nomatch(undefined, 'CosNaming_BindingIterator':oe_tc(next_n)),
- ?nomatch(undefined, 'CosNaming_BindingIterator':oe_tc(destroy)),
- ?match(undefined, 'CosNaming_BindingIterator':oe_tc(undefined)),
- ?match([_|_], 'CosNaming_BindingIterator':oe_get_interface()),
- ?match("IDL:omg.org/CosNaming/BindingIterator:1.0",
- 'CosNaming_BindingIterator':typeID()),
- check_tc('CosNaming_BindingIterator':oe_get_interface()),
- ?match(true, 'CosNaming_BindingIterator':oe_is_a('CosNaming_BindingIterator':typeID())),
- ?match(false, 'CosNaming_BindingIterator':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNaming_NamingContext'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNaming_NamingContext'(_) ->
- ?nomatch(undefined, 'CosNaming_NamingContext':oe_tc(bind)),
- ?nomatch(undefined, 'CosNaming_NamingContext':oe_tc(rebind)),
- ?nomatch(undefined, 'CosNaming_NamingContext':oe_tc(bind_context)),
- ?nomatch(undefined, 'CosNaming_NamingContext':oe_tc(rebind_context)),
- ?nomatch(undefined, 'CosNaming_NamingContext':oe_tc(resolve)),
- ?nomatch(undefined, 'CosNaming_NamingContext':oe_tc(unbind)),
- ?nomatch(undefined, 'CosNaming_NamingContext':oe_tc(new_context)),
- ?nomatch(undefined, 'CosNaming_NamingContext':oe_tc(bind_new_context)),
- ?nomatch(undefined, 'CosNaming_NamingContext':oe_tc(destroy)),
- ?nomatch(undefined, 'CosNaming_NamingContext':oe_tc(list)),
- ?match(undefined, 'CosNaming_NamingContext':oe_tc(undefined)),
- ?match([_|_], 'CosNaming_NamingContext':oe_get_interface()),
- ?match("IDL:omg.org/CosNaming/NamingContext:1.0",
- 'CosNaming_NamingContext':typeID()),
- check_tc('CosNaming_NamingContext':oe_get_interface()),
- ?match(true, 'CosNaming_NamingContext':oe_is_a('CosNaming_NamingContext':typeID())),
- ?match(false, 'CosNaming_NamingContext':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: 'CosNaming_NamingContexExt'
-%% Description:
-%%-----------------------------------------------------------------
-'CosNaming_NamingContextExt'(_) ->
- ?nomatch(undefined, 'CosNaming_NamingContextExt':oe_tc(to_string)),
- ?nomatch(undefined, 'CosNaming_NamingContextExt':oe_tc(to_name)),
- ?nomatch(undefined, 'CosNaming_NamingContextExt':oe_tc(to_url)),
- ?nomatch(undefined, 'CosNaming_NamingContextExt':oe_tc(resolve_str)),
- ?nomatch(undefined, 'CosNaming_NamingContextExt':oe_tc(bind)),
- ?nomatch(undefined, 'CosNaming_NamingContextExt':oe_tc(rebind)),
- ?nomatch(undefined, 'CosNaming_NamingContextExt':oe_tc(bind_context)),
- ?nomatch(undefined, 'CosNaming_NamingContextExt':oe_tc(rebind_context)),
- ?nomatch(undefined, 'CosNaming_NamingContextExt':oe_tc(new_context)),
- ?nomatch(undefined, 'CosNaming_NamingContextExt':oe_tc(bind_new_context)),
- ?nomatch(undefined, 'CosNaming_NamingContextExt':oe_tc(destroy)),
- ?nomatch(undefined, 'CosNaming_NamingContextExt':oe_tc(list)),
- ?match(undefined, 'CosNaming_NamingContextExt':oe_tc(undefined)),
- ?match([_|_], 'CosNaming_NamingContextExt':oe_get_interface()),
- ?match("IDL:omg.org/CosNaming/NamingContextExt:1.0",
- 'CosNaming_NamingContextExt':typeID()),
- check_tc('CosNaming_NamingContextExt':oe_get_interface()),
- ?match(true, 'CosNaming_NamingContextExt':oe_is_a('CosNaming_NamingContextExt':typeID())),
- ?match(true, 'CosNaming_NamingContextExt':oe_is_a('CosNaming_NamingContext':typeID())),
- ?match(false, 'CosNaming_NamingContextExt':oe_is_a("wrong")),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% MISC functions
-%%-----------------------------------------------------------------
-check_tc([]) ->
- ok;
-check_tc([{Op, {RetType, InParameters, OutParameters}}|T]) ->
- io:format("checked - ~s~n", [Op]),
- lists:all(?checktc(Op), [RetType|InParameters]),
- lists:all(?checktc(Op), OutParameters),
- check_tc(T).
-
-
diff --git a/lib/orber/test/idl_output/.gitignore b/lib/orber/test/idl_output/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/orber/test/idl_output/.gitignore
+++ /dev/null
diff --git a/lib/orber/test/iiop_module_do_test_impl.erl b/lib/orber/test/iiop_module_do_test_impl.erl
deleted file mode 100644
index 3e433ace72..0000000000
--- a/lib/orber/test/iiop_module_do_test_impl.erl
+++ /dev/null
@@ -1,113 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(iiop_module_do_test_impl).
-
-
--export([run_all/3, run_userexception/2, run_systemexception/2]).
--export([createTestContext/0]).
-
--export([start/0, stop/0]).
--export([init/1, terminate/2]).
-
-
-init(_) ->
- {ok, []}.
-
-terminate(Reason, _State) ->
- io:format("~p terminating with reason ~p~n", [?MODULE, Reason]),
- ok.
-
-createTestContext() ->
- NS = corba:resolve_initial_references("NameService"),
- NC = lname_component:set_id(lname_component:create(), "iiop_test"),
- N = lname:insert_component(lname:create(), 1, NC),
- 'CosNaming_NamingContext':bind_new_context(NS, N).
-
-start() ->
- SFok = corba:create('iiop_module_do_test', "IDL:iiop_module/do_test:1.0"),
- NS = corba:resolve_initial_references("NameService"),
- NC1 = lname_component:set_id(lname_component:create(), "iiop_test"),
- NC2 = lname_component:set_id(lname_component:create(), "erl_dotest"),
- N = lname:insert_component(lname:create(), 1, NC1),
- N1 = lname:insert_component(N, 2, NC2),
- 'CosNaming_NamingContext':bind(NS, N1, SFok),
- SFok.
-
-stop() ->
- NS = corba:resolve_initial_references("NameService"),
- NC1 = lname_component:set_id(lname_component:create(), "iiop_test"),
- NC2 = lname_component:set_id(lname_component:create(), "erl_dotest"),
- N = lname:insert_component(lname:create(), 1, NC1),
- N1 = lname:insert_component(N, 2, NC2),
- 'CosNaming_NamingContext':unbind(NS, N1).
-
-run_all(S, X, TL) ->
- ok = iiop_module_test:send_void(X),
- {tk_short, P1} = lists:nth(1, TL),
- {R1, IO1, O1} = iiop_module_test:send_short(X, P1, P1),
- RL1= [{tk_short, R1}],
- IOL1= [{tk_short, IO1}],
- OL1= [{tk_short, O1}],
- {tk_ushort, P2} = lists:nth(2, TL),
- {R2, IO2, O2} = iiop_module_test:send_ushort(X, P2, P2),
- RL2= [{tk_ushort, R2}|RL1],
- IOL2= [{tk_ushort, IO2}|IOL1],
- OL2= [{tk_ushort, O2}|OL1],
- {tk_long, P3} = lists:nth(3, TL),
- {R3, IO3, O3} = iiop_module_test:send_long(X, P3, P3),
- RL3= [{tk_long, R3}|RL2],
- IOL3= [{tk_long, IO3}|IOL2],
- OL3= [{tk_long, O3}|OL2],
- {tk_ulong, P4} = lists:nth(4, TL),
- {R4, IO4, O4} = iiop_module_test:send_ulong(X, P4, P4),
- RL4= [{tk_ulong, R4}|RL3],
- IOL4= [{tk_ulong, IO4}|IOL3],
- OL4= [{tk_ulong, O4}|OL3],
- {tk_float, P5} = lists:nth(5, TL),
- {R5, IO5, O5} = iiop_module_test:send_float(X, P5, P5),
- RL5= [{tk_float, R5}|RL4],
- IOL5= [{tk_float, IO5}|IOL4],
- OL5= [{tk_float, O5}|OL4],
- {tk_double, P6} = lists:nth(6, TL),
- {R6, IO6, O6} = iiop_module_test:send_double(X, P6, P6),
- RL6= [{tk_double, R6}|RL5],
- IOL6= [{tk_double, IO6}|IOL5],
- OL6= [{tk_double, O6}|OL5],
- {tk_boolean, P7} = lists:nth(7, TL),
- {R7, IO7, O7} = iiop_module_test:send_boolean(X, P7, P7),
- RL7= [{tk_boolean, R7}|RL6],
- IOL7= [{tk_boolean, IO7}|IOL6],
- OL7= [{tk_boolean, O7}|OL6],
- {tk_char, P8} = lists:nth(8, TL),
- {R8, IO8, O8} = iiop_module_test:send_char(X, P8, P8),
- RL= [{tk_char, R8} |RL7],
- IOL= [{tk_char, IO8} |IOL7],
- OL= [{tk_char, O8} |OL7],
- {{lists:reverse(RL),lists:reverse(IOL),lists:reverse(OL)}, S}.
-
-run_systemexception(S, X) ->
- iiop_module_test:ret_systemexception(X),
- {ok, S}.
-
-run_userexception(S, X) ->
- iiop_module_test:ret_userexception(X),
- {ok, S}.
diff --git a/lib/orber/test/iiop_module_test_impl.erl b/lib/orber/test/iiop_module_test_impl.erl
deleted file mode 100644
index c2ec427d5d..0000000000
--- a/lib/orber/test/iiop_module_test_impl.erl
+++ /dev/null
@@ -1,129 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(iiop_module_test_impl).
--include_lib("orber/include/corba.hrl").
--include("idl_output/iiop_module.hrl").
-
-
--export([send_void/1, send_short/3, send_ushort/3]).
--export([send_long/3, send_ulong/3, send_float/3]).
--export([send_double/3, send_boolean/3, send_char/3]).
--export([send_octet/3, send_any/3, send_object/3]).
--export([send_struct1/3, send_union1/3, send_enum1/3]).
--export([send_string/3, send_sequence1/3, send_array1/3]).
--export([ret_systemexception/1, ret_userexception/1]).
-
-
-
--export([start/0, stop/0]).
--export([init/1, terminate/2]).
-
-
-init(_) ->
- {ok, []}.
-
-terminate(Reason, _State) ->
- io:format("~p terminating with reason ~p~n", [?MODULE, Reason]),
- ok.
-
-
-start() ->
- SFok = corba:create('iiop_module_test', "IDL:iiop_module/test:1.0"),
- NS = corba:resolve_initial_references("NameService"),
- NC1 = lname_component:set_id(lname_component:create(), "iiop_test"),
- NC2 = lname_component:set_id(lname_component:create(), "erl_test"),
- N = lname:insert_component(lname:create(), 1, NC1),
- N1 = lname:insert_component(N, 2, NC2),
- 'CosNaming_NamingContext':bind(NS, N1, SFok),
- SFok.
-
-stop() ->
- NS = corba:resolve_initial_references("NameService"),
- NC1 = lname_component:set_id(lname_component:create(), "iiop_test"),
- NC2 = lname_component:set_id(lname_component:create(), "erl_test"),
- N = lname:insert_component(lname:create(), 1, NC1),
- N1 = lname:insert_component(N, 2, NC2),
- 'CosNaming_NamingContext':unbind(NS, N1).
-
-
-
-send_void(S) ->
- {ok, S}.
-
-send_short(S, P1, P2) ->
- {{P1, P1, P2}, S}.
-
-send_ushort(S, P1, P2) ->
- {{P1, P1, P2}, S}.
-
-send_long(S, P1, P2) ->
- {{P1, P1, P2}, S}.
-
-send_ulong(S, P1, P2) ->
- {{P1, P1, P2}, S}.
-
-send_float(S, P1, P2) ->
- {{P1, P1, P2}, S}.
-
-send_double(S, P1, P2) ->
- {{P1, P1, P2}, S}.
-
-send_boolean(S, P1, P2) ->
- {{P1, P1, P2}, S}.
-
-send_char(S, P1, P2) ->
- {{P1, P1, P2}, S}.
-
-send_octet(S, P1, P2) ->
- {{P1, P1, P2}, S}.
-
-send_any(S, P1, P2) ->
- {{P1, P1, P2}, S}.
-
-send_object(S, P1, P2) ->
- {{P1, P1, P2}, S}.
-
-send_struct1(S, P1, P2) ->
- {{P1, P1, P2}, S}.
-
-send_union1(S, P1, P2) ->
- {{P1, P1, P2}, S}.
-
-send_enum1(S, P1, P2) ->
- {{P1, P1, P2}, S}.
-
-send_string(S, P1, P2) ->
- {{P1, P1, P2}, S}.
-
-send_sequence1(S, P1, P2) ->
- {{P1, P1, P2}, S}.
-
-send_array1(S, P1, P2) ->
- {{P1, P1, P2}, S}.
-
-ret_systemexception(S) ->
- throw(#'BAD_PARAM'{}),
- {ok, S}.
-
-ret_userexception(S) ->
- throw(#iiop_module_Except1{why="not readable",rest_of_name=["foo", "bar"]}),
- {ok, S}.
diff --git a/lib/orber/test/iiop_test.idl b/lib/orber/test/iiop_test.idl
deleted file mode 100644
index 0b20a66edd..0000000000
--- a/lib/orber/test/iiop_test.idl
+++ /dev/null
@@ -1,112 +0,0 @@
-//
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-//
-#include "cos_naming.idl"
-
-module iiop_module
-{
-
- typedef long Array1[10];
-
- enum Enum1 {horse, pig, cow};
-
- typedef sequence<long> Sequence1;
-
- typedef Sequence1 Sequence2;
-
- struct Struct1 {
- string s;
- unsigned short us;
- unsigned long ul;
- };
-
- union Union1 switch (short) {
- case 0: short First;
- case 1: string Second;
- case 2: char Third;
- };
-
- exception Except1 {
- string why;
- sequence <string> rest_of_name;
- };
-
- typedef sequence<any> test_values;
- struct test_retval {
- test_values R;
- test_values InOut;
- test_values Out;
- };
-
- interface test;
-
- interface do_test {
- void run_systemexception(in test x)
- raises(CosNaming::NamingContext::NotFound,
- CosNaming::NamingContext::CannotProceed,
- CosNaming::NamingContext::InvalidName);
- void run_userexception(in test x)
- raises(iiop_module::Except1,
- CosNaming::NamingContext::NotFound,
- CosNaming::NamingContext::CannotProceed,
- CosNaming::NamingContext::InvalidName);
- test_retval run_all(in test x, in test_values tlist)
- raises(iiop_module::Except1,
- CosNaming::NamingContext::NotFound,
- CosNaming::NamingContext::CannotProceed,
- CosNaming::NamingContext::InvalidName);
- };
-
- interface test {
- // Function to run all tests from java to erlang
- // and return the answers
- // Primitive types
- void send_void();
- short send_short(in short p1, inout short p2, out short p3);
- unsigned short send_ushort(in unsigned short p1, inout unsigned short p2,
- out unsigned short p3);
- long send_long(in long p1, inout long p2, out long p3);
- unsigned long send_ulong(in unsigned long p1, inout unsigned long p2,
- out unsigned long p3);
- float send_float(in float p1, inout float p2, out float p3);
- double send_double(in double p1, inout double p2, out double p3);
- boolean send_boolean(in boolean p1, inout boolean p2, out boolean p3);
- char send_char(in char p1, inout char p2, out char p3);
- octet send_octet(in octet p1, inout octet p2, out octet p3);
- any send_any(in any p1, inout any p2, out any p3);
- Object send_object(in Object p1, inout Object p2, out Object p3);
- // TypeCode send_typecode(in TypeCode p1, inout TypeCode p2, out TypeCode p3);
- // Principal send_principal(in Principal p); //tested in every request
-
- // Complex types
- Struct1 send_struct1(in Struct1 p1, inout Struct1 p2, out Struct1 p3);
- Union1 send_union1(in Union1 p1, inout Union1 p2, out Union1 p3);
- Enum1 send_enum1(in Enum1 p1, inout Enum1 p2, out Enum1 p3);
- string send_string(in string p1, inout string p2, out string p3);
- Sequence1 send_sequence1(in Sequence1 p1, inout Sequence1 p2,
- out Sequence1 p3);
- Array1 send_array1(in Array1 p1, inout Array1 p2, out Array1 p3);
-
- void ret_systemexception();
- void ret_userexception() raises(iiop_module::Except1);
-
-
- };
-
-};
diff --git a/lib/orber/test/iiop_test_impl.erl b/lib/orber/test/iiop_test_impl.erl
deleted file mode 100644
index 26694f8e08..0000000000
--- a/lib/orber/test/iiop_test_impl.erl
+++ /dev/null
@@ -1,35 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(iiop_test_impl).
--include_lib("orber/include/corba.hrl").
--include_lib("orber/test/iiop_test.hrl").
--export([]).
-
-
-init(Env) ->
- {ok, []}.
-
-terminate(From, Reason) ->
- ok.
-
-send_void(State) ->
- {ok, State}.
-
diff --git a/lib/orber/test/interceptors_SUITE.erl b/lib/orber/test/interceptors_SUITE.erl
deleted file mode 100644
index cec4cd1fab..0000000000
--- a/lib/orber/test/interceptors_SUITE.erl
+++ /dev/null
@@ -1,349 +0,0 @@
-%%-----------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File : interceptors_SUITE.erl
-%% Purpose :
-%%-----------------------------------------------------------------
-
--module(interceptors_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
--define(default_timeout, test_server:minutes(3)).
-
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
--define(nomatch(Not, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- Not ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS);
- _ ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS
- end
- end()).
-
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([in_reply/6, out_request/6]).
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [local_pseudo, local_default, local_local, local_global].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- corba:orb_init([{flags, (?ORB_ENV_USE_PI bor ?ORB_ENV_LOCAL_TYPECHECKING)},
- {local_interceptors, {native, [?MODULE]}}]),
- orber:jump_start(2945),
- oe_orber_test_server:oe_register(),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- oe_orber_test_server:oe_unregister(),
- orber:jump_stop(),
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: local_pseudo
-%% Description:
-%%-----------------------------------------------------------------
-local_pseudo(_) ->
- ?match({native, [?MODULE]}, orber:get_local_interceptors()),
- %% Global settings
- Obj1 = orber_test_server:oe_create(state,[{pseudo,true}]),
- Result11 = orber_test_server:testing_iiop_ushort(Obj1, ?USHORTMAX),
- ?match([?USHORTMAX], put(out_request, undefined)),
- ?match(Result11, put(in_reply, undefined)),
-
- Result12 = ?match({'EXCEPTION',_},
- orber_test_server:testing_iiop_ushort(Obj1, ?USHORTMAX+1)),
- ?match([(?USHORTMAX+1)], put(out_request, undefined)),
- ?nomatch(Result12, put(in_reply, undefined)),
-
- Result13 = orber_test_server:testing_iiop_oneway_delay(Obj1, 0),
- ?match([0], put(out_request, undefined)),
- ?nomatch(Result13, put(in_reply, undefined)),
-
- Result14 = ?match({'EXCEPTION', _},
- orber_test_server:raise_local_exception(Obj1)),
- ?match([], put(out_request, undefined)),
- ?match(Result14, put(in_reply, undefined)),
-
- Result15 = ?match({'EXCEPTION',_}, orber_test_server:stop_brutal(Obj1)),
- ?match([], put(out_request, undefined)),
- ?match(Result15, put(in_reply, undefined)),
-
- %% Per-object
- Obj2 = orber_test_server:oe_create(state,[{pseudo,true},
- {local_interceptors, false}]),
-
- Result21 = orber_test_server:testing_iiop_ushort(Obj2, ?USHORTMAX),
- ?nomatch([?USHORTMAX], put(out_request, undefined)),
- ?nomatch(Result21, put(in_reply, undefined)),
-
- Obj3 = orber_test_server:oe_create(state,[{pseudo,true},
- {local_interceptors, true}]),
-
- Result31 = orber_test_server:testing_iiop_ushort(Obj3, ?USHORTMAX),
- ?match([?USHORTMAX], put(out_request, undefined)),
- ?match(Result31, put(in_reply, undefined)),
-
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: local_default
-%% Description:
-%%-----------------------------------------------------------------
-local_default(_) ->
- ?match({native, [?MODULE]}, orber:get_local_interceptors()),
- %% Global settings
- Obj1 = orber_test_server:oe_create(state, []),
- Result11 = orber_test_server:testing_iiop_ushort(Obj1, ?USHORTMAX),
- ?match([?USHORTMAX], put(out_request, undefined)),
- ?match(Result11, put(in_reply, undefined)),
-
- Result12 = ?match({'EXCEPTION',_},
- orber_test_server:testing_iiop_ushort(Obj1, ?USHORTMAX+1)),
- ?match([(?USHORTMAX+1)], put(out_request, undefined)),
- ?nomatch(Result12, put(in_reply, undefined)),
-
- Result13 = orber_test_server:testing_iiop_oneway_delay(Obj1, 0),
- ?match([0], put(out_request, undefined)),
- ?nomatch(Result13, put(in_reply, undefined)),
-
- Result14 = ?match({'EXCEPTION', _},
- orber_test_server:raise_local_exception(Obj1)),
- ?match([], put(out_request, undefined)),
- ?match(Result14, put(in_reply, undefined)),
-
- Result15 = ?match({'EXCEPTION',_}, orber_test_server:stop_brutal(Obj1)),
- ?match([], put(out_request, undefined)),
- ?match(Result15, put(in_reply, undefined)),
-
-
- %% Per-object
- Obj2 = orber_test_server:oe_create(state,[{local_interceptors, false}]),
-
- Result21 = orber_test_server:testing_iiop_ushort(Obj2, ?USHORTMAX),
- ?nomatch([?USHORTMAX], put(out_request, undefined)),
- ?nomatch(Result21, put(in_reply, undefined)),
- corba:dispose(Obj2),
-
- Obj3 = orber_test_server:oe_create(state,[{local_interceptors, true}]),
-
- Result31 = orber_test_server:testing_iiop_ushort(Obj3, ?USHORTMAX),
- ?match([?USHORTMAX], put(out_request, undefined)),
- ?match(Result31, put(in_reply, undefined)),
- corba:dispose(Obj3),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: local_local
-%% Description:
-%%-----------------------------------------------------------------
-local_local(_) ->
- ?match({native, [?MODULE]}, orber:get_local_interceptors()),
- %% Global settings
- Obj1 = orber_test_server:oe_create(state, [{regname, {local, regname}}]),
- Result11 = orber_test_server:testing_iiop_ushort(Obj1, ?USHORTMAX),
- ?match([?USHORTMAX], put(out_request, undefined)),
- ?match(Result11, put(in_reply, undefined)),
-
- Result12 = ?match({'EXCEPTION',_},
- orber_test_server:testing_iiop_ushort(Obj1, ?USHORTMAX+1)),
- ?match([(?USHORTMAX+1)], put(out_request, undefined)),
- ?nomatch(Result12, put(in_reply, undefined)),
-
- Result13 = orber_test_server:testing_iiop_oneway_delay(Obj1, 0),
- ?match([0], put(out_request, undefined)),
- ?nomatch(Result13, put(in_reply, undefined)),
-
- Result14 = ?match({'EXCEPTION', _},
- orber_test_server:raise_local_exception(Obj1)),
- ?match([], put(out_request, undefined)),
- ?match(Result14, put(in_reply, undefined)),
-
- Result15 = ?match({'EXCEPTION',_}, orber_test_server:stop_brutal(Obj1)),
- ?match([], put(out_request, undefined)),
- ?match(Result15, put(in_reply, undefined)),
-
- %% Per-object
- Obj2 = orber_test_server:oe_create(state,[{regname, {local, regname}},
- {local_interceptors, false}]),
-
- Result21 = orber_test_server:testing_iiop_ushort(Obj2, ?USHORTMAX),
- ?nomatch([?USHORTMAX], put(out_request, undefined)),
- ?nomatch(Result21, put(in_reply, undefined)),
- corba:dispose(Obj2),
-
- Obj3 = orber_test_server:oe_create(state,[{regname, {local, regname}},
- {local_interceptors, true}]),
-
- Result31 = orber_test_server:testing_iiop_ushort(Obj3, ?USHORTMAX),
- ?match([?USHORTMAX], put(out_request, undefined)),
- ?match(Result31, put(in_reply, undefined)),
- corba:dispose(Obj3),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: local_global
-%% Description:
-%%-----------------------------------------------------------------
-local_global(_) ->
- ?match({native, [?MODULE]}, orber:get_local_interceptors()),
- %% Global settings
- Obj1 = orber_test_server:oe_create(state, [{regname, {global, regname}}]),
- Result11 = orber_test_server:testing_iiop_ushort(Obj1, ?USHORTMAX),
- ?match([?USHORTMAX], put(out_request, undefined)),
- ?match(Result11, put(in_reply, undefined)),
-
- Result12 = ?match({'EXCEPTION',_},
- orber_test_server:testing_iiop_ushort(Obj1, ?USHORTMAX+1)),
- ?match([(?USHORTMAX+1)], put(out_request, undefined)),
- ?nomatch(Result12, put(in_reply, undefined)),
-
- Result13 = orber_test_server:testing_iiop_oneway_delay(Obj1, 0),
- ?match([0], put(out_request, undefined)),
- ?nomatch(Result13, put(in_reply, undefined)),
-
- Result14 = ?match({'EXCEPTION', _},
- orber_test_server:raise_local_exception(Obj1)),
- ?match([], put(out_request, undefined)),
- ?match(Result14, put(in_reply, undefined)),
-
- Result15 = ?match({'EXCEPTION',_}, orber_test_server:stop_brutal(Obj1)),
- ?match([], put(out_request, undefined)),
- ?match(Result15, put(in_reply, undefined)),
-
- %% Per-object
- Obj2 = orber_test_server:oe_create(state,[{regname, {global, regname}},
- {local_interceptors, false}]),
-
- Result21 = orber_test_server:testing_iiop_ushort(Obj2, ?USHORTMAX),
- ?nomatch([?USHORTMAX], put(out_request, undefined)),
- ?nomatch(Result21, put(in_reply, undefined)),
- corba:dispose(Obj2),
-
- Obj3 = orber_test_server:oe_create(state,[{regname, {global, regname}},
- {local_interceptors, true}]),
-
- Result31 = orber_test_server:testing_iiop_ushort(Obj3, ?USHORTMAX),
- ?match([?USHORTMAX], put(out_request, undefined)),
- ?match(Result31, put(in_reply, undefined)),
- corba:dispose(Obj3),
- ok.
-
-
-
-
-%%-----------------------------------------------------------------
-%% Local functions
-%%-----------------------------------------------------------------
-%%-----------------------------------------------------------------
-%% function : in_reply
-%%-----------------------------------------------------------------
-in_reply(Ref, _ObjKey, Ctx, Op, Reply, _Args) ->
- error_logger:info_msg("=============== in_reply =================
-Connection: ~p
-Operation : ~p
-Reply : ~p
-Context : ~p
-==========================================~n",
- [Ref, Op, Reply, Ctx]),
- put(in_reply, Reply),
- {Reply, "NewArgs"}.
-
-%%-----------------------------------------------------------------
-%% function : out_request
-%%-----------------------------------------------------------------
-out_request(Ref, _ObjKey, Ctx, Op, Params, _Args) ->
- error_logger:info_msg("=============== out_request ==============
-Connection: ~p
-Operation : ~p
-Parameters: ~p
-Context : ~p
-==========================================~n",
- [Ref, Op, Params, Ctx]),
- put(out_request, Params),
- {Params, "NewArgs"}.
diff --git a/lib/orber/test/iop_ior_10_SUITE.erl b/lib/orber/test/iop_ior_10_SUITE.erl
deleted file mode 100644
index 68a6793f62..0000000000
--- a/lib/orber/test/iop_ior_10_SUITE.erl
+++ /dev/null
@@ -1,184 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%%
-%% Description:
-%% Test suite for the IOR functions
-%%
-%%-----------------------------------------------------------------
--module(iop_ior_10_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
--define(default_timeout, test_server:minutes(3)).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [encoding, create_and_get_ops].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: IOR encoding test
-%% Description: Just testing the string_encoding function because the
-%% other encodings is called from them.
-%%-----------------------------------------------------------------
-encoding(_) ->
- V = #'IIOP_Version'{major=1,minor=0},
- M0 = 'Module_Interface',
- T0 = "IDL:Module/Interface:1.0",
- H0 = "my.hostname.org",
- P0 = 4040,
- N0 = 'name',
- O0 = corba_fake_mk_objkey(M0, registered, N0),
- PB0 = #'IIOP_ProfileBody_1_0'{iiop_version=V, host=H0, port=P0, object_key=O0},
- TP0 = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB0},
- S0 = #'IOP_IOR'{type_id=T0, profiles=[TP0]},
- N1 = list_to_pid("<0.100.0>"),
- O1 = corba_fake_mk_objkey(M0, key, N1),
- PB1 = #'IIOP_ProfileBody_1_0'{iiop_version=V, host=H0, port=P0, object_key=O1},
- TP1 = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB1},
- S1 = #'IOP_IOR'{type_id=T0, profiles=[TP1]},
- O2 = "This is an external objectkey",
- PB2 = #'IIOP_ProfileBody_1_0'{iiop_version=V, host=H0, port=P0, object_key=O2},
- TP2 = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB2},
- S2 = #'IOP_IOR'{type_id=T0, profiles=[TP2]},
- C0 = iop_ior:string_code(S0),
- {S0, <<>>, _} = iop_ior:string_decode(C0),
- C1 = iop_ior:string_code(S1),
- {S1, <<>>, _} = iop_ior:string_decode(C1),
- C2 = iop_ior:string_code(S2),
- {S2, <<>>, _} = iop_ior:string_decode(C2),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: IOR creation test
-%% Description:
-%%-----------------------------------------------------------------
-create_and_get_ops(_) ->
- V = #'IIOP_Version'{major=1,minor=0},
- M0 = 'Module_Interface',
- T0 = "IDL:Module/Interface:1.0",
- H0 = "my.hostname.org",
- P0 = 4040,
- N0 = 'name',
- O0 = corba_fake_mk_objkey(M0, registered, N0),
- PB0 = #'IIOP_ProfileBody_1_0'{iiop_version=V, host=H0, port=P0, object_key=O0},
- TP0 = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB0},
- S0 = #'IOP_IOR'{type_id=T0, profiles=[TP0]},
- S0 = iop_ior:create({1, 0}, T0, [H0], P0, -1, O0, [], 0, 0),
- N1 = list_to_pid("<0.100.0>"),
- O1 = corba_fake_mk_objkey(M0, key, N1),
- {_,_,K1,_,_,_} = O1,
- PB1 = #'IIOP_ProfileBody_1_0'{iiop_version=V, host=H0, port=P0, object_key=O1},
- TP1 = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB1},
- S1 = #'IOP_IOR'{type_id=T0, profiles=[TP1]},
- S1 = iop_ior:create({1, 0}, T0, [H0], P0, -1, O1, [], 0, 0),
- O2 = "This is an external objectkey",
- PB2 = #'IIOP_ProfileBody_1_0'{iiop_version=V, host=H0, port=P0, object_key=O2},
- TP2 = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB2},
- S2 = #'IOP_IOR'{type_id=T0, profiles=[TP2]},
- {'internal_registered', N0, _, _, M0} = iop_ior:get_key(S0),
- {'internal', K1, _, _, M0} = iop_ior:get_key(S1),
- {'external', {H0, P0, O2, _,_,
- #host_data{protocol = normal,
- ssl_data = undefined,
- version = {1,0},
- csiv2_mech = undefined,
- csiv2_statefull = false,
- charset = 65537,
- wcharset = 65801,
- ft_heartbeat = false,
- ft_primary = false,
- ft_group = undefined,
- csiv2_addresses = []}}}
- = iop_ior:get_key(S2),
- T0 = iop_ior:get_typeID(S0),
- O0 = iop_ior:get_objkey(S0),
- O1 = iop_ior:get_objkey(S1),
- O2 = iop_ior:get_objkey(S2),
- ok.
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-corba_fake_mk_objkey(Id, 'key', Pid) when is_pid(Pid) ->
- Key = make_objkey(),
- {Id, 'key', Key, term_to_binary(undefined), 0, 0};
-corba_fake_mk_objkey(Id, 'key', RegName) when is_atom(RegName) ->
- Key = term_to_binary(RegName),
- {Id, 'key', Key, term_to_binary(undefined), 0, 0};
-corba_fake_mk_objkey(Id, 'registered', RegName) when is_atom(RegName) ->
- {Id, 'registered', RegName, term_to_binary(undefined), 0, 0}.
-
-
-make_objkey() ->
- term_to_binary({{erlang:system_time(),
- erlang:unique_integer()},
- node()}).
diff --git a/lib/orber/test/iop_ior_11_SUITE.erl b/lib/orber/test/iop_ior_11_SUITE.erl
deleted file mode 100644
index 8276feeb93..0000000000
--- a/lib/orber/test/iop_ior_11_SUITE.erl
+++ /dev/null
@@ -1,203 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%%
-%% Description:
-%% Test suite for the IOR functions
-%%
-%%-----------------------------------------------------------------
--module(iop_ior_11_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
--define(default_timeout, test_server:minutes(3)).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [encoding, create_and_get_ops].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: IOR encoding test
-%% Description: Just testing the string_encoding function because the
-%% other encodings is called from them.
-%%-----------------------------------------------------------------
-encoding(_) ->
- V = #'IIOP_Version'{major=1,minor=1},
- M0 = 'Module_Interface',
- T0 = "IDL:Module/Interface:1.0",
- H0 = "my.hostname.org",
- P0 = 4040,
- N0 = 'name',
- Components = case orber:iiop_ssl_port() of
- -1 ->
- [];
- SSLPort ->
- [#'IOP_TaggedComponent'{tag=?TAG_SSL_SEC_TRANS,
- component_data=[0 |
- cdrlib:enc_unsigned_short(2,
- cdrlib:enc_unsigned_short(2,
- cdrlib:enc_unsigned_short(SSLPort, [])))]}]
- end,
- O0 = corba_fake_mk_objkey(M0, registered, N0),
- PB0 = #'IIOP_ProfileBody_1_1'{iiop_version=V, host=H0, port=P0, object_key=O0,
- components=Components},
- TP0 = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB0},
- S0 = #'IOP_IOR'{type_id=T0, profiles=[TP0]},
- N1 = list_to_pid("<0.100.0>"),
- O1 = corba_fake_mk_objkey(M0, key, N1),
- PB1 = #'IIOP_ProfileBody_1_1'{iiop_version=V, host=H0, port=P0, object_key=O1,
- components=[]},
- TP1 = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB1},
- S1 = #'IOP_IOR'{type_id=T0, profiles=[TP1]},
- O2 = "This is an external objectkey",
- PB2 = #'IIOP_ProfileBody_1_1'{iiop_version=V, host=H0, port=P0, object_key=O2,
- components=[]},
- TP2 = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB2},
- S2 = #'IOP_IOR'{type_id=T0, profiles=[TP2]},
- C0 = iop_ior:string_code(S0),
- {S0, <<>>, _} = iop_ior:string_decode(C0),
- C1 = iop_ior:string_code(S1),
- {S1, <<>>, _} = iop_ior:string_decode(C1),
- C2 = iop_ior:string_code(S2),
- {S2, <<>>, _} = iop_ior:string_decode(C2),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: IOR creation test
-%% Description:
-%%-----------------------------------------------------------------
-create_and_get_ops(_) ->
- V = #'IIOP_Version'{major=1,minor=1},
- CSC = #'IOP_TaggedComponent'{tag=?TAG_CODE_SETS,
- component_data=?DEFAULT_CODESETS},
- M0 = 'Module_Interface',
- T0 = "IDL:Module/Interface:1.0",
- H0 = "my.hostname.org",
- P0 = 4040,
- N0 = 'name',
- O0 = corba_fake_mk_objkey(M0, registered, N0),
- PB0 = #'IIOP_ProfileBody_1_1'
- {iiop_version=V, host=H0, port=P0, object_key=O0,
- components=[CSC]},
- TP0 = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB0},
- S0 = #'IOP_IOR'{type_id=T0, profiles=[TP0]},
- S0 = iop_ior:create({1, 1}, T0, [H0], P0, -1, O0, [CSC], 0, 0),
- N1 = list_to_pid("<0.100.0>"),
- O1 = corba_fake_mk_objkey(M0, key, N1),
- {_,_,K1,_,_,_} = O1,
- PB1 = #'IIOP_ProfileBody_1_1'
- {iiop_version=V, host=H0, port=P0, object_key=O1,
- components=[CSC]},
- TP1 = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB1},
- S1 = #'IOP_IOR'{type_id=T0, profiles=[TP1]},
- S1 = iop_ior:create({1, 1}, T0, [H0], P0, -1, O1, [CSC], 0, 0),
- O2 = "This is an external objectkey",
- PB2 = #'IIOP_ProfileBody_1_1'{iiop_version=V, host=H0, port=P0, object_key=O2,
- components=[]},
- TP2 = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB2},
- S2 = #'IOP_IOR'{type_id=T0, profiles=[TP2]},
- {'internal_registered', N0, _, _, M0} = iop_ior:get_key(S0),
- {'internal', K1, _, _, M0} = iop_ior:get_key(S1),
- {'external', {H0, P0, O2, _,_,
- #host_data{protocol = normal,
- ssl_data = undefined,
- version = {1,1},
- csiv2_mech = undefined,
- csiv2_statefull = false,
- charset = 65537,
- wcharset = 65801,
- ft_heartbeat = false,
- ft_primary = false,
- ft_group = undefined,
- csiv2_addresses = []}}} =
- iop_ior:get_key(S2),
- T0 = iop_ior:get_typeID(S0),
- O0 = iop_ior:get_objkey(S0),
- O1 = iop_ior:get_objkey(S1),
- O2 = iop_ior:get_objkey(S2),
- ok.
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-corba_fake_mk_objkey(Id, 'key', Pid) when is_pid(Pid) ->
- Key = make_objkey(),
- {Id, 'key', Key, term_to_binary(undefined), 0, 0};
-corba_fake_mk_objkey(Id, 'key', RegName) when is_atom(RegName) ->
- Key = term_to_binary(RegName),
- {Id, 'key', Key, term_to_binary(undefined), 0, 0};
-corba_fake_mk_objkey(Id, 'registered', RegName) when is_atom(RegName) ->
- {Id, 'registered', RegName, term_to_binary(undefined), 0, 0}.
-
-make_objkey() ->
- term_to_binary({{erlang:system_time(),
- erlang:unique_integer()},
- node()}).
diff --git a/lib/orber/test/iop_ior_12_SUITE.erl b/lib/orber/test/iop_ior_12_SUITE.erl
deleted file mode 100644
index 802b0b11a2..0000000000
--- a/lib/orber/test/iop_ior_12_SUITE.erl
+++ /dev/null
@@ -1,204 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File : iop_ior_12_SUITE.erl
-%% Description : Test suite for the IOR functions
-%%
-%%----------------------------------------------------------------------
--module(iop_ior_12_SUITE).
-
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
--define(default_timeout, test_server:minutes(3)).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [encoding, create_and_get_ops].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: IOR encoding test
-%% Description: Just testing the string_encoding function because the
-%% other encodings is called from them.
-%%-----------------------------------------------------------------
-encoding(_) ->
- V = #'IIOP_Version'{major=1,minor=2},
- M0 = 'Module_Interface',
- T0 = "IDL:Module/Interface:1.0",
- H0 = "my.hostname.org",
- P0 = 4040,
- N0 = 'name',
- Components = case orber:iiop_ssl_port() of
- -1 ->
- [];
- SSLPort ->
- [#'IOP_TaggedComponent'{tag=?TAG_SSL_SEC_TRANS,
- component_data=[0 |
- cdrlib:enc_unsigned_short(2,
- cdrlib:enc_unsigned_short(2,
- cdrlib:enc_unsigned_short(SSLPort, [])))]}]
- end,
- O0 = corba_fake_mk_objkey(M0, registered, N0),
- PB0 = #'IIOP_ProfileBody_1_1'{iiop_version=V, host=H0, port=P0, object_key=O0,
- components=Components},
- TP0 = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB0},
- S0 = #'IOP_IOR'{type_id=T0, profiles=[TP0]},
- N1 = list_to_pid("<0.100.0>"),
- O1 = corba_fake_mk_objkey(M0, key, N1),
- PB1 = #'IIOP_ProfileBody_1_1'{iiop_version=V, host=H0, port=P0, object_key=O1,
- components=[]},
- TP1 = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB1},
- S1 = #'IOP_IOR'{type_id=T0, profiles=[TP1]},
- O2 = "This is an external objectkey",
- PB2 = #'IIOP_ProfileBody_1_1'{iiop_version=V, host=H0, port=P0, object_key=O2,
- components=[]},
- TP2 = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB2},
- S2 = #'IOP_IOR'{type_id=T0, profiles=[TP2]},
- C0 = iop_ior:string_code(S0),
- {S0, <<>>, _} = iop_ior:string_decode(C0),
- C1 = iop_ior:string_code(S1),
- {S1, <<>>, _} = iop_ior:string_decode(C1),
- C2 = iop_ior:string_code(S2),
- {S2, <<>>, _} = iop_ior:string_decode(C2),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: IOR creation test
-%% Description:
-%%-----------------------------------------------------------------
-create_and_get_ops(_) ->
- V = #'IIOP_Version'{major=1,minor=2},
- CSC = #'IOP_TaggedComponent'{tag=?TAG_CODE_SETS,
- component_data=?DEFAULT_CODESETS},
- M0 = 'Module_Interface',
- T0 = "IDL:Module/Interface:1.0",
- H0 = "my.hostname.org",
- P0 = 4040,
- N0 = 'name',
- O0 = corba_fake_mk_objkey(M0, registered, N0),
- PB0 = #'IIOP_ProfileBody_1_1'
- {iiop_version=V, host=H0, port=P0, object_key=O0,
- components=[CSC]},
- TP0 = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB0},
- S0 = #'IOP_IOR'{type_id=T0, profiles=[TP0]},
- S0 = iop_ior:create({1, 2}, T0, [H0], P0, -1, O0, [CSC], 0, 0),
- N1 = list_to_pid("<0.100.0>"),
- O1 = corba_fake_mk_objkey(M0, key, N1),
- {_,_,K1,_,_,_} = O1,
- PB1 = #'IIOP_ProfileBody_1_1'
- {iiop_version=V, host=H0, port=P0, object_key=O1,
- components=[CSC]},
- TP1 = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB1},
- S1 = #'IOP_IOR'{type_id=T0, profiles=[TP1]},
- S1 = iop_ior:create({1, 2}, T0, [H0], P0, -1, O1, [CSC], 0, 0),
- O2 = "This is an external objectkey",
- PB2 = #'IIOP_ProfileBody_1_1'{iiop_version=V, host=H0, port=P0, object_key=O2,
- components=[]},
- TP2 = #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP, profile_data=PB2},
- S2 = #'IOP_IOR'{type_id=T0, profiles=[TP2]},
- {'internal_registered', N0, _, _, M0} = iop_ior:get_key(S0),
- {'internal', K1, _, _, M0} = iop_ior:get_key(S1),
- {'external', {H0, P0, O2,_,_,
- #host_data{protocol = normal,
- ssl_data = undefined,
- version = {1,2},
- csiv2_mech = undefined,
- csiv2_statefull = false,
- charset = 65537,
- wcharset = 65801,
- ft_heartbeat = false,
- ft_primary = false,
- ft_group = undefined,
- csiv2_addresses = []}}}
- = iop_ior:get_key(S2),
- T0 = iop_ior:get_typeID(S0),
- O0 = iop_ior:get_objkey(S0),
- O1 = iop_ior:get_objkey(S1),
- O2 = iop_ior:get_objkey(S2),
- ok.
-
-%%-----------------------------------------------------------------
-%% Internal functions
-%%-----------------------------------------------------------------
-corba_fake_mk_objkey(Id, 'key', Pid) when is_pid(Pid) ->
- Key = make_objkey(),
- {Id, 'key', Key, term_to_binary(undefined), 0, 0};
-corba_fake_mk_objkey(Id, 'key', RegName) when is_atom(RegName) ->
- Key = term_to_binary(RegName),
- {Id, 'key', Key, term_to_binary(undefined), 0, 0};
-corba_fake_mk_objkey(Id, 'registered', RegName) when is_atom(RegName) ->
- {Id, 'registered', RegName, term_to_binary(undefined), 0, 0}.
-
-make_objkey() ->
- term_to_binary({{erlang:system_time(),
- erlang:unique_integer()},
- node()}).
diff --git a/lib/orber/test/ip_v4v6_interop_SUITE.erl b/lib/orber/test/ip_v4v6_interop_SUITE.erl
deleted file mode 100644
index 48cc77eca7..0000000000
--- a/lib/orber/test/ip_v4v6_interop_SUITE.erl
+++ /dev/null
@@ -1,199 +0,0 @@
-%%----------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%----------------------------------------------------------------------
-%% File : ip_v4v6_interop_SUITE.erl
-%% Description :
-%%
-%%----------------------------------------------------------------------
--module(ip_v4v6_interop_SUITE).
-
--compile(export_all).
-%%----------------------------------------------------------------------
-%% External exports
-%%----------------------------------------------------------------------
--export([
- all/0,
- init_per_suite/1,
- end_per_suite/1,
- init_per_testcase/2,
- end_per_testcase/2,
- groups/0,
- init_per_group/2,
- end_per_group/2
- ]).
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
-
-%%----------------------------------------------------------------------
-%% Include files
-%%----------------------------------------------------------------------
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/src/ifr_objects.hrl").
--include("idl_output/orber_test_server.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming_NamingContextExt.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming_NamingContext.hrl").
-
-%%----------------------------------------------------------------------
-%% Macros
-%%----------------------------------------------------------------------
--define(default_timeout, test_server:minutes(15)).
-
--define(match(ExpectedRes,Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~nRESULT: ~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-%%----------------------------------------------------------------------
-%% Records
-%%----------------------------------------------------------------------
-
-%%======================================================================
-%% Initialization functions.
-%%======================================================================
-
-init_per_testcase(_Case, Config) ->
- %% Starting dual configured ORB
- orber:jump_start([{iiop_port, 10001}, {flags, 16#1000}]),
- orber:info(),
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- orber:jump_stop(),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(Config) ->
- Config.
-
-%%====================================================================
-%% SUITE specification
-%%====================================================================
-all() ->
- [
- dual_ipv4v6
- ].
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-%%====================================================================
-%% Test Cases
-%%====================================================================
-%% ORB configured for supporting both IPv4 and IPv6
-dual_ipv4v6(_Config) ->
-
- %% Starting slave node with ipv4 configured ORB
- {ok, Ipv4Node, _Ipv4Host} =
- ?match({ok,_,_}, orber_test_lib:js_node([{iiop_port, 4001}])),
- Ipv4NS = orber_test_lib:remote_apply(Ipv4Node, corba, resolve_initial_references, ["NameService"]),
-
- %% Starting slave node with ipv6 configured ORB
- {ok, Ipv6Node, _Ipv6Host} =
- ?match({ok,_,_}, orber_test_lib:js_node([{iiop_port, 6001}, {flags, 16#0100}])),
- Ipv6NS = orber_test_lib:remote_apply(Ipv6Node, corba, resolve_initial_references, ["NameService"]),
-
- %% Add the ipv6 interface in the dual configured ORB
- ?match({ok, _}, orber:add_listen_interface("::1", normal,
- [{ip_family, inet6}, {iiop_port, 10002}])),
- DualNS = corba:resolve_initial_references("NameService"),
-
- %% Bind IPv4 NameServer to a name in the dual stack orbs NameServer
- NSDual4 = orber_test_lib:remote_apply(Ipv4Node, corba, resolve_initial_references_remote,
- ["NameService", ["iiop://127.0.0.1:10001"]]),
- ?match(ok, orber_test_lib:remote_apply(Ipv4Node, 'CosNaming_NamingContext', bind,
- [NSDual4, lname:new(["ns4"]), Ipv4NS])),
- 'CosNaming_NamingContext':resolve(DualNS, lname:new(["ns4"])),
-
- %% Bind IPv6 NameServer to a name in the dual stack orbs NameServer
- NSDual6 = orber_test_lib:remote_apply(Ipv6Node, corba, resolve_initial_references_remote,
- ["NameService", ["iiop://[::1]:10002"]]),
- ?match(ok, orber_test_lib:remote_apply(Ipv6Node, 'CosNaming_NamingContext', bind,
- [NSDual6, lname:new(["ns6"]), Ipv6NS])),
- 'CosNaming_NamingContext':resolve(DualNS, lname:new(["ns6"])),
-
- %% IPv4: Fetch IPv6 NS reference from dual stack orber and register own NameServer in that
- Ipv4NSO = orber_test_lib:remote_apply(Ipv4Node, 'CosNaming_NamingContext', resolve,
- [NSDual4, lname:new(["ns6"])]),
- ?match(ok, orber_test_lib:remote_apply(Ipv4Node, 'CosNaming_NamingContext', bind,
- [Ipv4NSO, lname:new(["nso"]), Ipv4NS])),
-
- %% IPv6: Fetch IPv4 NS reference from dual stack orber and register own NameServer in that
- Ipv6NSO = orber_test_lib:remote_apply(Ipv6Node, 'CosNaming_NamingContext', resolve,
- [NSDual6, lname:new(["ns4"])]),
- ?match(ok, orber_test_lib:remote_apply(Ipv6Node, 'CosNaming_NamingContext', bind,
- [Ipv6NSO, lname:new(["nso"]), Ipv6NS])),
-
-
- %% IPv4: Fetch own NS reference from IPv6 NameServer and add a context then check that everything went well
- Ipv4NSFromIpv6 = orber_test_lib:remote_apply(Ipv6Node, 'CosNaming_NamingContext', resolve,
- [Ipv6NS, lname:new(["nso"])]),
- _Ipv4NC = orber_test_lib:remote_apply(Ipv4Node, 'CosNaming_NamingContext', bind_new_context,
- [Ipv4NSFromIpv6, lname:new(["test_context4"])]),
-
- %% IPv6: Fetch own NS reference from IPv4 NameServer and add a context then check that everything went well
- Ipv6NSFromIpv4 = orber_test_lib:remote_apply(Ipv4Node, 'CosNaming_NamingContext', resolve,
- [Ipv4NS, lname:new(["nso"])]),
- _Ipv6NC = orber_test_lib:remote_apply(Ipv6Node, 'CosNaming_NamingContext', bind_new_context,
- [Ipv6NSFromIpv4, lname:new(["test_context6"])]),
-
- %% Check that all the names are register correctly
- {ok,DualNames,_} = 'CosNaming_NamingContext':list(DualNS, 100),
- {ok,Ipv4Names,_} = orber_test_lib:remote_apply(Ipv4Node, 'CosNaming_NamingContext', list, [Ipv4NS, 100]),
- {ok,Ipv6Names,_} = orber_test_lib:remote_apply(Ipv6Node, 'CosNaming_NamingContext', list, [Ipv6NS, 100]),
-
- io:format("\nNames in Dual NS: ~p\n", [DualNames]),
- ?match(2, length(DualNames)),
- io:format("\nNames in IPv4 NS: ~p\n", [Ipv4Names]),
- ?match(2, length(Ipv4Names)),
- io:format("\nNames in IPv6 NS: ~p\n", [Ipv6Names]),
- ?match(2, length(Ipv6Names)),
-
- ok.
-
diff --git a/lib/orber/test/lname_SUITE.erl b/lib/orber/test/lname_SUITE.erl
deleted file mode 100644
index cb67cd6136..0000000000
--- a/lib/orber/test/lname_SUITE.erl
+++ /dev/null
@@ -1,213 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%%
-%% Description:
-%% Test suite for the Names Library module
-%%
-%%-----------------------------------------------------------------
--module(lname_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming.hrl").
--include_lib("orber/COSS/CosNaming/lname.hrl").
-
--define(default_timeout, test_server:minutes(3)).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([]).
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [lname_component, lname].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: name component handling tests
-%% Description:
-%%-----------------------------------------------------------------
-lname_component(_) ->
- create_test(),
- get_tests(),
- set_tests().
-
-create_test() ->
- #'CosNaming_NameComponent'{} = lname_component:create(),
- ok.
-
-get_tests() ->
- NC = #'CosNaming_NameComponent'{id="first", kind="apple"},
- NC1 = #'CosNaming_NameComponent'{id="", kind="apple"},
- NC2 = #'CosNaming_NameComponent'{id="first", kind=""},
- "first" = lname_component:get_id(NC),
- "apple" = lname_component:get_kind(NC),
- {'EXCEPTION', #'LNameComponent_NotSet'{}} =
- (catch lname_component:get_id(NC1)),
- {'EXCEPTION', #'LNameComponent_NotSet'{}} =
- (catch lname_component:get_kind(NC2)),
- ok.
-
-set_tests() ->
- NC = #'CosNaming_NameComponent'{id="first", kind="apple"},
- #'CosNaming_NameComponent'{id="second", kind="apple"} =
- lname_component:set_id(NC, "second"),
- #'CosNaming_NameComponent'{id="first", kind="pear"} =
- lname_component:set_kind(NC, "pear"),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: name handling tests
-%% Description:
-%%-----------------------------------------------------------------
-lname(_) ->
- Name = [#'CosNaming_NameComponent'{id="first", kind="apple"},
- #'CosNaming_NameComponent'{id="last", kind="peach"},
- #'CosNaming_NameComponent'{id="and", kind="plum"},
- #'CosNaming_NameComponent'{id="always", kind="orange"}],
- insert_tests(Name),
- get_tests(Name),
- delete_tests(Name),
- comparision_tests(Name),
- convertion_tests(Name).
-
-insert_tests(Name) ->
- NC = #'CosNaming_NameComponent'{id="new", kind="pear"},
- [NC, #'CosNaming_NameComponent'{id="first", kind="apple"},
- #'CosNaming_NameComponent'{id="last", kind="peach"},
- #'CosNaming_NameComponent'{id="and", kind="plum"},
- #'CosNaming_NameComponent'{id="always", kind="orange"}] =
- lname:insert_component(Name, 1, NC),
- [#'CosNaming_NameComponent'{id="first", kind="apple"},
- #'CosNaming_NameComponent'{id="last", kind="peach"},
- #'CosNaming_NameComponent'{id="and", kind="plum"},
- #'CosNaming_NameComponent'{id="always", kind="orange"}, NC] =
- lname:insert_component(Name, 5, NC),
- [#'CosNaming_NameComponent'{id="first", kind="apple"},
- #'CosNaming_NameComponent'{id="last", kind="peach"},
- #'CosNaming_NameComponent'{id="and", kind="plum"}, NC,
- #'CosNaming_NameComponent'{id="always", kind="orange"}] =
- lname:insert_component(Name, 4, NC),
- [#'CosNaming_NameComponent'{id="first", kind="apple"},
- #'CosNaming_NameComponent'{id="last", kind="peach"}, NC,
- #'CosNaming_NameComponent'{id="and", kind="plum"},
- #'CosNaming_NameComponent'{id="always", kind="orange"}] =
- lname:insert_component(Name, 3, NC),
- {'EXCEPTION', #'LName_NoComponent'{}} =
- (catch lname:insert_component(Name, 6, NC)),
- {'EXCEPTION', #'LName_NoComponent'{}} =
- (catch lname:insert_component(Name, 0, NC)),
- {'EXCEPTION', #'LName_NoComponent'{}} =
- (catch lname:insert_component(Name, -2, NC)),
- ok.
-
-get_tests(Name) ->
- #'CosNaming_NameComponent'{id="first", kind="apple"} =
- lname:get_component(Name, 1),
- #'CosNaming_NameComponent'{id="always", kind="orange"} =
- lname:get_component(Name, 4),
- #'CosNaming_NameComponent'{id="and", kind="plum"} =
- lname:get_component(Name, 3),
- {'EXCEPTION', #'LName_NoComponent'{}} =
- (catch lname:get_component(Name, 5)),
- {'EXCEPTION', #'LName_NoComponent'{}} =
- (catch lname:get_component(Name, 0)),
- {'EXCEPTION', #'LName_NoComponent'{}} =
- (catch lname:get_component(Name, -2)),
- ok.
-
-delete_tests(Name) ->
- [#'CosNaming_NameComponent'{id="last", kind="peach"},
- #'CosNaming_NameComponent'{id="and", kind="plum"},
- #'CosNaming_NameComponent'{id="always", kind="orange"}] =
- lname:delete_component(Name, 1),
- [#'CosNaming_NameComponent'{id="first", kind="apple"},
- #'CosNaming_NameComponent'{id="last", kind="peach"},
- #'CosNaming_NameComponent'{id="and", kind="plum"}] =
- lname:delete_component(Name, 4),
- [#'CosNaming_NameComponent'{id="first", kind="apple"},
- #'CosNaming_NameComponent'{id="last", kind="peach"},
- #'CosNaming_NameComponent'{id="always", kind="orange"}] =
- lname:delete_component(Name, 3),
- {'EXCEPTION', #'LName_NoComponent'{}} =
- (catch lname:delete_component(Name, 6)),
- {'EXCEPTION', #'LName_NoComponent'{}} =
- (catch lname:delete_component(Name, 0)),
- {'EXCEPTION', #'LName_NoComponent'{}} =
- (catch lname:delete_component(Name, -2)),
- ok.
-
-comparision_tests(Name) ->
- true = lname:equal(Name, Name),
- false = lname:equal(Name, lname:delete_component(Name, 2)),
- true = lname:less_than(lname:delete_component(Name, 2), Name),
- false = lname:less_than(Name, Name),
- false = lname:less_than(Name, lname:delete_component(Name, 2)),
- ok.
-
-convertion_tests(Name) ->
- Name = lname:from_idl_form(Name),
- Name = lname:to_idl_form(Name),
- ok.
diff --git a/lib/orber/test/multi_ORB_SUITE.erl b/lib/orber/test/multi_ORB_SUITE.erl
deleted file mode 100644
index 3c5bb0b5e5..0000000000
--- a/lib/orber/test/multi_ORB_SUITE.erl
+++ /dev/null
@@ -1,2286 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(multi_ORB_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/src/ifr_objects.hrl").
--include("idl_output/orber_test_server.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming_NamingContextExt.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming_NamingContext.hrl").
-
-
--define(default_timeout, test_server:minutes(15)).
-
--define(match(ExpectedRes,Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~nRESULT: ~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, cases/0,
- init_per_suite/1, end_per_suite/1, basic_PI_api/1, multi_orber_api/1,
- init_per_testcase/2, end_per_testcase/2, multi_pseudo_orber_api/1,
- light_orber_api/1, light_orber2_api/1,
- ssl_1_multi_orber_api/1, ssl_2_multi_orber_api/1, ssl_reconfigure_api/1,
- iiop_timeout_api/1, iiop_timeout_added_api/1, setup_connection_timeout_api/1,
- setup_multi_connection_timeout_api/1, setup_multi_connection_timeout_random_api/1,
- setup_multi_connection_timeout_attempts_api/1,
- fragments_server_api/1, fragments_max_server_api/1,
- fragments_max_server_added_api/1, fragments_client_api/1,
- light_ifr_api/1, max_requests_api/1, max_requests_added_api/1,
- max_connections_api/1, max_packet_size_exceeded_api/1,
- max_packet_size_ok_api/1, proxy_interface_api/1, proxy_interface_ipv6_api/1,
- multiple_accept_api/1, implicit_context_api/1,
- pseudo_implicit_context_api/1, pseudo_two_implicit_context_api/1,
- oneway_implicit_context_api/1, implicit_context_roundtrip_api/1,
- oneway_pseudo_implicit_context_api/1, flags_added_api/1,
- oneway_pseudo_two_implicit_context_api/1,
- local_interface_api/1, local_interface_ctx_override_api/1,
- local_interface_acl_override_api/1, bad_giop_header_api/1,
- bad_fragment_id_client_api/1, bad_id_cancel_request_api/1,
- close_connections_api/1, close_connections_local_interface_api/1,
- close_connections_local_interface_ctx_override_api/1,
- ssl_1_multi_orber_generation_3_api/1, ssl_2_multi_orber_generation_3_api/1,
- ssl_reconfigure_generation_3_api/1,
- close_connections_alt_iiop_addr_api/1, close_connections_multiple_profiles_api/1]).
-
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--export([pseudo_calls/2, pseudo_casts/2, create_fake_server_ORB/5, do_connect/3]).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% NOTE - the fragment test cases must be first since we explicitly set a request
-%% id. Otherwise, the request-id counter would be increased and we cannot know
-%% what it is.
-cases() ->
- [fragments_server_api, fragments_max_server_api,
- fragments_max_server_added_api, fragments_client_api,
- flags_added_api, bad_fragment_id_client_api,
- bad_giop_header_api, bad_id_cancel_request_api,
- implicit_context_api, pseudo_implicit_context_api,
- pseudo_two_implicit_context_api,
- implicit_context_roundtrip_api,
- oneway_implicit_context_api,
- oneway_pseudo_implicit_context_api,
- oneway_pseudo_two_implicit_context_api,
- proxy_interface_api, proxy_interface_ipv6_api,
- local_interface_api, local_interface_ctx_override_api,
- local_interface_acl_override_api, close_connections_api,
- close_connections_local_interface_api,
- close_connections_local_interface_ctx_override_api,
- close_connections_alt_iiop_addr_api,
- close_connections_multiple_profiles_api,
- multiple_accept_api, max_requests_api,
- max_requests_added_api, max_connections_api,
- max_packet_size_exceeded_api, max_packet_size_ok_api,
- light_ifr_api, multi_pseudo_orber_api, multi_orber_api,
- light_orber_api, light_orber2_api, basic_PI_api,
- iiop_timeout_api, iiop_timeout_added_api,
- setup_connection_timeout_api,
- setup_multi_connection_timeout_api,
- setup_multi_connection_timeout_attempts_api,
- setup_multi_connection_timeout_random_api,
- ssl_1_multi_orber_generation_3_api,
- ssl_2_multi_orber_generation_3_api,
- ssl_reconfigure_generation_3_api].
-
-% ssl_1_multi_orber_api,ssl_2_multi_orber_api,ssl_reconfigure_api,
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_testcase(TC,Config)
- when TC =:= ssl_1_multi_orber_api;
- TC =:= ssl_2_multi_orber_api;
- TC =:= ssl_reconfigure_api ->
- init_ssl(Config);
-init_per_testcase(TC,Config)
- when TC =:= ssl_1_multi_orber_generation_3_api;
- TC =:= ssl_2_multi_orber_generation_3_api;
- TC =:= ssl_reconfigure_generation_3_api ->
- init_ssl_3(Config);
-init_per_testcase(_Case, Config) ->
- init_all(Config).
-
-init_ssl(Config) ->
- case proplists:get_value(crypto_started, Config) of
- true ->
- case orber_test_lib:ssl_version() of
- no_ssl ->
- {skip, "SSL is not installed!"};
- _ ->
- init_all(Config)
- end;
- false ->
- {skip, "Crypto did not start"}
- end.
-
-init_ssl_3(Config) ->
- case proplists:get_value(crypto_started, Config) of
- true ->
- case orber_test_lib:ssl_version() of
- 3 ->
- init_all(Config);
- 2 ->
- {skip, "Could not find the correct SSL version!"};
- no_ssl ->
- {skip, "SSL is not installed!"}
- end;
- false ->
- {skip, "Crypto did not start"}
- end.
-
-init_all(Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- Dog=test_server:timetrap(?default_timeout),
- orber:jump_start(0),
- oe_orber_test_server:oe_register(),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- oe_orber_test_server:oe_unregister(),
- orber:jump_stop(),
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) ->
- if
- is_list(Config) ->
- try crypto:start() of
- ok ->
- [{crypto_started, true} | Config]
- catch _:_ ->
- [{crypto_started, false} | Config]
- end;
- true ->
- exit("Config not a list")
- end.
-
-end_per_suite(Config) ->
- application:stop(crypto),
- Config.
-
-%%-----------------------------------------------------------------
-%% API tests for ORB to ORB, no security
-%%-----------------------------------------------------------------
-
-%% IIOP Implicit Contex tests
-implicit_context_api(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_LOCAL_INTERFACE},
- {ip_address, IP}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- %% Create a remote server
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
- [nameservice])),
- IOR = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaname::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService#mamba")),
-
- Relay = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([])),
- ?match(ok,
- orber_test_server:
- relay_call(Relay,
- [{context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface,
- Loopback}}]}],
- IOR)),
-
- ?match([_,_], orber:iiop_connections(out)),
- Conns = ?match([_,_],
- orber_test_lib:remote_apply(ServerNode, orber, iiop_connections, [in])),
- ?match(true, lists:keymember(Loopback, 1, Conns)),
- ok.
-
-%% IIOP Implicit Contex roundtrip tests
-implicit_context_roundtrip_api(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_LOCAL_INTERFACE},
- {ip_address, IP}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- %% Create a remote server
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
- [nameservice])),
- Relay = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaname::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService#mamba")),
-
- IOR = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([], [])),
- ?match(ok,
- orber_test_server:
- relay_call(Relay,
- [{context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface,
- Loopback}}]}],
- IOR)),
- ?match([_,_], orber:iiop_connections(out)),
- Conns = ?match([_,_],
- orber_test_lib:remote_apply(ServerNode, orber, iiop_connections, [in])),
- ?match(true, lists:keymember(Loopback, 1, Conns)),
- ok.
-
-%% IIOP Implicit Contex oneway tests
-oneway_implicit_context_api(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_LOCAL_INTERFACE},
- {ip_address, IP}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- %% Create a remote server
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
- [nameservice])),
- IOR = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaname::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService#mamba")),
-
- Relay = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([])),
- ?match(ok,
- orber_test_server:
- relay_cast(Relay,
- [{context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface,
- Loopback}}]}],
- IOR)),
-
- %% We must wait for a few seconds for the client to be able to set up the
- %% connection (since it's a oneway operation).
- timer:sleep(5000),
- ?match([_,_], orber:iiop_connections(out)),
- Conns = ?match([_,_],
- orber_test_lib:remote_apply(ServerNode, orber, iiop_connections, [in])),
- ?match(true, lists:keymember(Loopback, 1, Conns)),
- ok.
-
-%% IIOP Implicit Contex tests (via pseudo object)
-pseudo_implicit_context_api(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_LOCAL_INTERFACE},
- {ip_address, IP}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- %% Create a remote server
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
- [nameservice])),
- IOR = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaname::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService#mamba")),
-
- Relay = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([], [{pseudo,true}])),
- ?match(ok,
- orber_test_server:
- relay_call(Relay,
- [{context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface,
- Loopback}}]}],
- IOR)),
- ?match([_,_], orber:iiop_connections(out)),
- Conns = ?match([_,_],
- orber_test_lib:remote_apply(ServerNode, orber, iiop_connections, [in])),
- ?match(true, lists:keymember(Loopback, 1, Conns)),
- ok.
-
-%% IIOP two Implicit Contex tests (via pseudo object)
-pseudo_two_implicit_context_api(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_LOCAL_INTERFACE},
- {ip_address, IP}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- %% Create a remote server
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
- [nameservice])),
- IOR = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaname::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService#mamba")),
-
- Relay = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([], [{pseudo,true}])),
- put(oe_server_in_context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface,
- IP}}]),
- ?match(ok,
- orber_test_server:
- relay_call(Relay,
- [{context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface,
- Loopback}}]}],
- IOR)),
- ?match([_,_], orber:iiop_connections(out)),
- Conns = ?match([_,_],
- orber_test_lib:remote_apply(ServerNode, orber, iiop_connections, [in])),
- ?match(true, lists:keymember(Loopback, 1, Conns)),
- ok.
-
-%% IIOP Implicit Contex tests (via pseudo object oneway)
-oneway_pseudo_implicit_context_api(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_LOCAL_INTERFACE},
- {ip_address, IP}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- %% Create a remote server
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
- [nameservice])),
- IOR = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaname::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService#mamba")),
-
- Relay = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([], [{pseudo,true}])),
- ?match(ok,
- orber_test_server:
- relay_cast(Relay,
- [{context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface,
- Loopback}}]}],
- IOR)),
- ?match([_,_], orber:iiop_connections(out)),
- Conns = ?match([_,_],
- orber_test_lib:remote_apply(ServerNode, orber, iiop_connections, [in])),
- ?match(true, lists:keymember(Loopback, 1, Conns)),
- ok.
-
-%% IIOP two Implicit Contex tests (via pseudo object oneway)
-oneway_pseudo_two_implicit_context_api(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_LOCAL_INTERFACE},
- {ip_address, IP}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- %% Create a remote server
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
- [nameservice])),
- IOR = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaname::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService#mamba")),
-
- Relay = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([], [{pseudo,true}])),
- %% Add incoming implicit context which must be removed.
- put(oe_server_in_context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface,
- IP}}]),
- ?match(ok,
- orber_test_server:
- relay_cast(Relay,
- [{context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface,
- Loopback}}]}],
- IOR)),
- ?match([_,_], orber:iiop_connections(out)),
- Conns = ?match([_,_],
- orber_test_lib:remote_apply(ServerNode, orber, iiop_connections, [in])),
- ?match(true, lists:keymember(Loopback, 1, Conns)),
- ok.
-
-
-
-%% IIOP Multiple Accept tests
-multiple_accept_api(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_LOCAL_INTERFACE},
- {ip_address, IP}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- %% The server ORB doesn't listen to 127.0.0.1
- ?match({'EXCEPTION',_},
- corba:string_to_object("corbaloc::1.2@" ++Loopback++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match([], orber:iiop_connections(out)),
-
- IOR1 = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {IP, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
- iop_ior:get_key(IOR1)),
- ?match([_], orber:iiop_connections(out)),
-
- {ok, Ref1} = ?match({ok, _},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
- [Loopback, normal])),
-
- IOR2 = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaloc::1.2@"++Loopback++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {Loopback, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
- iop_ior:get_key(IOR2)),
- ?match([_,_], orber:iiop_connections(out)),
-
- {ok, Ref2} = ?match({ok, _},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
- [Loopback, normal, 9543])),
- ?match({error, eaddrinuse},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
- [Loopback, normal, 9543])),
-
- IOR3 = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaloc::1.2@"++Loopback++":9543/NameService")),
- ?match({'external', {Loopback, 9543, _ObjectKey, _Counter, _TP, _NewHD}},
- iop_ior:get_key(IOR3)),
- ?match([_,_,_], orber:iiop_connections(out)),
-
- ?match(ok,
- orber_test_lib:remote_apply(ServerNode, orber,
- remove_listen_interface, [Ref1])),
- %% Wait a few seconds to be sure that the connections really has been removed.
- timer:sleep(4000),
- ?match([_,_], orber:iiop_connections(out)),
-
- ?match(ok,
- orber_test_lib:remote_apply(ServerNode, orber,
- remove_listen_interface, [Ref2])),
- %% Wait a few seconds to be sure that the connections really has been removed.
- timer:sleep(4000),
- ?match([_], orber:iiop_connections(out)),
-
- ?match({'EXCEPTION',_},
- corba:string_to_object("corbaloc::1.2@"++Loopback++":9543/NameService")),
- ?match({'EXCEPTION',_},
- corba:string_to_object("corbaloc::1.2@"++Loopback++":"++integer_to_list(ServerPort)++"/NameService")),
-
- IOR4 = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {IP, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
- iop_ior:get_key(IOR4)),
-
- ok.
-
-
-%% IIOP Proxy Interface tests
-%% This case test if the server ORB use the correct
-%% interface when exporting IOR:s
-proxy_interface_api(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_LOCAL_INTERFACE}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- IOR1 = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {IP, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
- iop_ior:get_key(IOR1)),
- IOR2 = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaloc::1.2@"++Loopback++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {Loopback, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
- iop_ior:get_key(IOR2)),
- ok.
-
-%% IIOP Proxy Interface tests
-%% This case test if the server ORB use the correct
-%% IPv6 interface when exporting IOR:s
-proxy_interface_ipv6_api(_Config) ->
- case orber_test_lib:version_ok() of
- true ->
- proxy_interface_ipv6_api2();
- Reason ->
- Reason
- end.
-
-proxy_interface_ipv6_api2() ->
- Loopback = orber_test_lib:get_loopback_interface(inet6),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, (?ORB_ENV_USE_IPV6 bor
- ?ORB_ENV_LOCAL_INTERFACE)}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
-
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_USE_IPV6}])),
-
- IP = orber_test_lib:remote_apply(ClientNode, orber_test_lib, get_host, []),
-
- IOR1 = ?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
- ["corbaloc::1.2@["++IP++"]:"++integer_to_list(ServerPort)++"/NameService"])),
- ?match({'external', {IP, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
- orber_test_lib:remote_apply(ClientNode, iop_ior, get_key, [IOR1])),
- IOR2 = ?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
- ["corbaloc::1.2@["++Loopback++"]:"++integer_to_list(ServerPort)++"/NameService"])),
- ?match({'external', {Loopback, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
- orber_test_lib:remote_apply(ClientNode, iop_ior, get_key, [IOR2])),
- ok.
-
-%% IIOP Local Interface tests
-%% This case test if the server ORB use the correct
-%% local interface when connecting to another ORB
-local_interface_api(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{ip_address_local, Loopback}])),
- Port = orber:iiop_port(),
- ?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
- ["corbaloc::1.2@"++IP++":"++integer_to_list(Port)++"/NameService"])),
- [{Loopback, RemotePort}] =
- ?match([{Loopback,_RemotePort}], orber:iiop_connections(in)),
-
- ?match([{IP, Port}],
- orber_test_lib:remote_apply(ClientNode, orber,
- iiop_connections, [out])),
- ?match([{IP, Port}], orber:find_sockname_by_peername(Loopback,RemotePort)),
- ?match([{Loopback, RemotePort}], orber:find_peername_by_sockname(IP, Port)),
-
- ?match([{Loopback, RemotePort}],
- orber_test_lib:remote_apply(ClientNode, orber,
- find_sockname_by_peername,
- [IP, Port])),
- ?match([{IP, Port}],
- orber_test_lib:remote_apply(ClientNode, orber,
- find_peername_by_sockname,
- [Loopback,RemotePort])),
-
-
- ok.
-
-%% IIOP Local Interface tests
-%% This case test if the server ORB use the correct
-%% local interface when connecting to another ORB
-local_interface_ctx_override_api(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{ip_address_local, IP}])),
- Port = orber:iiop_port(),
- ?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
- ["corbaloc::1.2@"++IP++":"++integer_to_list(Port)++"/NameService",
- [#'IOP_ServiceContext'
- {context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface, Loopback}}]])),
- [{Loopback, RemotePort}] =
- ?match([{Loopback,_RemotePort}], orber:iiop_connections(in)),
-
- ?match([{IP, Port, Loopback}],
- orber_test_lib:remote_apply(ClientNode, orber,
- iiop_connections, [out])),
- ?match([{IP, Port}], orber:find_sockname_by_peername(Loopback,RemotePort)),
- ?match([{Loopback, RemotePort}], orber:find_peername_by_sockname(IP, Port)),
-
- ?match([{Loopback, RemotePort}],
- orber_test_lib:remote_apply(ClientNode, orber,
- find_sockname_by_peername,
- [IP, Port])),
- ?match([{IP, Port}],
- orber_test_lib:remote_apply(ClientNode, orber,
- find_peername_by_sockname,
- [Loopback,RemotePort])),
-
- ok.
-
-%% IIOP Local Interface tests
-%% This case test if the server ORB use the correct
-%% local interface when connecting to another ORB
-local_interface_acl_override_api(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- ACL = [{tcp_out, IP ++ "/18", [Loopback]}],
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{ip_address_local, IP},
- {iiop_acl, ACL},
- {flags, ?ORB_ENV_USE_ACL_OUTGOING}])),
- Port = orber:iiop_port(),
- ?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
- ["corbaloc::1.2@"++IP++":"++integer_to_list(Port)++"/NameService",
- [#'IOP_ServiceContext'
- {context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface, IP}}]])),
- ?match([{Loopback,_RemotePort}], orber:iiop_connections(in)),
- ?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
- ["corbaloc::1.2@"++IP++":"++integer_to_list(Port)++"/NameService"])),
-
- [{Loopback, RemotePort}] =
- ?match([{Loopback,_RemotePort}], orber:iiop_connections(in)),
- ?match([{IP, Port, IP}], orber_test_lib:remote_apply(ClientNode, orber,
- iiop_connections, [out])),
- ?match([{IP, Port}], orber:find_sockname_by_peername(Loopback,RemotePort)),
- ?match([{Loopback, RemotePort}], orber:find_peername_by_sockname(IP, Port)),
-
- ?match([{Loopback, RemotePort}],
- orber_test_lib:remote_apply(ClientNode, orber,
- find_sockname_by_peername,
- [IP, Port])),
- ?match([{IP, Port}],
- orber_test_lib:remote_apply(ClientNode, orber,
- find_peername_by_sockname,
- [Loopback,RemotePort])),
-
- ok.
-
-
-%% IIOP TIMEOUT API tests
-%% This case test if timeout configuration behaves correctly
-iiop_timeout_api(_Config) ->
-
- %% Install two secure orber.
- {ok, ClientNode, ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{iiop_timeout, 6},
- {iiop_connection_timeout, 3},
- {iiop_in_connection_timeout, 3}])),
- ClientPort = orber_test_lib:remote_apply(ClientNode, orber, iiop_port, []),
-
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{iiop_timeout, 6},
- {iiop_connection_timeout, 3},
- {iiop_in_connection_timeout, 12}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
-
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
- [timeout])),
-
- %% Tell client_orb to interoperate with server_orb.
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
- lookup,
- [ServerHost, ServerPort])),
- %% Interop worked fine, perform delay tests.
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
- timeouts,
- [ServerHost, ServerPort, 6000])),
-
- %% Create a connection to the "client_orb", which will now act as server.
- ?match({'IOP_IOR',_,_},
- corba:string_to_object("corbaloc::1.2@"++ClientHost++":"++integer_to_list(ClientPort)++"/NameService")),
- %% Check that the connection is established.
- ?match([{_, ClientPort}], orber:iiop_connections(out)),
- %% Wait >3 seconds (i.e. iiop_in_connection_timeout) and check if the connection
- %% have been closed.
- timer:sleep(8000),
- ?match([], orber:iiop_connections(out)),
-
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- uninstall_test_data,
- [timeout])),
- ok.
-
-%% IIOP TIMEOUT API tests
-%% This case test if timeout configuration behaves correctly
-iiop_timeout_added_api(_Config) ->
- IP = orber_test_lib:get_host(),
- {ok, Node, _Host} = ?match({ok,_,_}, orber_test_lib:js_node([])),
- Port = 1 + orber_test_lib:remote_apply(Node, orber, iiop_port, []),
- ?match({ok, _},
- orber_test_lib:remote_apply(Node, orber,
- add_listen_interface,
- [IP, normal,
- [{iiop_in_connection_timeout, 3},
- {flags, ?ORB_ENV_LOCAL_INTERFACE},
- {iiop_port, Port}]])),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- install_test_data,
- [timeout])),
-
- ?match({'IOP_IOR',_,_},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(Port)++"/NameService")),
- %% Check that the connection is established.
- ?match([{_, Port}], orber:iiop_connections(out)),
- %% Wait >3 seconds (i.e. iiop_in_connection_timeout) and check if the connection
- %% have been closed.
- timer:sleep(8000),
- ?match([], orber:iiop_connections(out)),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- uninstall_test_data,
- [timeout])),
- ok.
-
-%%-----------------------------------------------------------------
-%% API tests for ORB to ORB using pseudo call/cast, no security
-%%-----------------------------------------------------------------
-
-%% MULTI ORB PSEUDO API tests
-%% This case test if data encode/decode (IIOP) for pseudo objects
-%% produce the correct result, i.e., the test_server echos
-%% the input parameter or an exception is raised (MARSHAL)
-multi_pseudo_orber_api(_Config) ->
- %% --- Create a slave-node ---
- {ok, Node, Host} =
- ?match({ok,_,_}, orber_test_lib:js_node()),
- Port = orber_test_lib:remote_apply(Node, orber, iiop_port, []),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- install_test_data,
- [pseudo])),
-
- NSR = ?match({'IOP_IOR',"IDL:omg.org/CosNaming/NamingContextExt:1.0",_},
- corba:string_to_object("corbaloc::1.1@"++Host++":"++
- integer_to_list(Port)++"/NameService")),
- Obj =
- ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- 'CosNaming_NamingContext':resolve(NSR, lname:new(["mamba"]))),
- orber_test_lib:corba_object_tests(Obj, NSR),
-
- %% Can we even contact the object?
- ?match(ok, orber_test_server:print(Obj)),
-
- %% Invoke one blocking call followed by several invokations.
- spawn(?MODULE, pseudo_calls, [5, Obj]),
- ?match({ok, 10000}, orber_test_server:pseudo_call_delay(Obj, 10000)),
- spawn(?MODULE, pseudo_casts, [5, Obj]),
- ?match(ok, orber_test_server:pseudo_cast_delay(Obj, 10000)),
-
- %%--- Testing code and decode arguments ---
- orber_test_lib:test_coding(Obj),
-
- %% Test if exit is handled properly.
- ?match({'EXCEPTION',{'TRANSIENT',_,_,_}},
- orber_test_server:stop_brutal(Obj)),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- uninstall_test_data,
- [pseudo])),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% API tests for ORB to ORB with local flags definition set.
-%%-----------------------------------------------------------------
-%% MULTI ORB PSEUDO with local flags definition set
-flags_added_api(_Config) ->
- %% --- Create a slave-node ---
- IP = orber_test_lib:get_host(),
- {ok, Node, _Host} =
- ?match({ok,_,_}, orber_test_lib:js_node([])),
- Port = 1 + orber_test_lib:remote_apply(Node, orber, iiop_port, []),
- ?match({ok, _},
- orber_test_lib:remote_apply(Node, orber,
- add_listen_interface,
- [IP, normal,
- [{flags, (?ORB_ENV_LOCAL_INTERFACE bor
- ?ORB_ENV_EXCLUDE_CODESET_COMPONENT)},
- {iiop_port, Port}]])),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- install_test_data,
- [pseudo])),
- Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- corba:string_to_object("corbaname::1.1@"++IP++":"++
- integer_to_list(Port)++"/NameService#mamba")),
- ?match({'external', {IP, Port, _ObjectKey, _Counter,
- #'IOP_TaggedProfile'{tag=?TAG_INTERNET_IOP,
- profile_data=
- #'IIOP_ProfileBody_1_1'{components=[]}},
- _NewHD}},
- iop_ior:get_key(Obj)),
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- uninstall_test_data,
- [pseudo])),
-
- ok.
-
-
-
-%%-----------------------------------------------------------------
-%% API tests for ORB to ORB with limited concurrent requests
-%%-----------------------------------------------------------------
-%% MULTI ORB PSEUDO with limited concurrent requests tests
-max_requests_api(_Config) ->
- %% --- Create a slave-node ---
- {ok, Node, Host} =
- ?match({ok,_,_}, orber_test_lib:js_node([{iiop_max_in_requests, 1}])),
- Port = orber_test_lib:remote_apply(Node, orber, iiop_port, []),
- max_requests(Node, Host, Port).
-
-%% MULTI ORB PSEUDO with limited concurrent requests tests
-max_requests_added_api(_Config) ->
- %% --- Create a slave-node ---
- [IP] = ?match([_], orber:host()),
- {ok, Node, _Host} =
- ?match({ok,_,_}, orber_test_lib:js_node([])),
- Port = 1 + orber_test_lib:remote_apply(Node, orber, iiop_port, []),
- ?match({ok, _},
- orber_test_lib:remote_apply(Node, orber,
- add_listen_interface,
- [IP, normal,
- [{iiop_max_in_requests, 1},
- {flags, ?ORB_ENV_LOCAL_INTERFACE},
- {iiop_port, Port}]])),
- max_requests(Node, IP, Port).
-
-max_requests(Node, Host, Port) ->
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- install_test_data,
- [pseudo])),
- Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- corba:string_to_object("corbaname::1.1@"++Host++":"++
- integer_to_list(Port)++"/NameService#mamba")),
-
- %% Can we even contact the object?
- ?match(ok, orber_test_server:print(Obj)),
-
- %% Invoke one blocking call followed by several invokations.
- spawn(orber_test_server, pseudo_call_delay, [Obj, 15000]),
- %% Wait for a second to be sure that the previous request has been sent
- timer:sleep(1000),
- {MegaSecsB, Before, _} = erlang:timestamp(),
- pseudo_calls(5, Obj),
- {MegaSecsA, After, _} = erlang:timestamp(),
- %% Normally we we can perform hundreds of pseudo-calls per second. Hence,
- %% if we add 8 seconds to 'Before' it should still be less since we only
- %% allow one request at a time to the target ORB.
- ?match(true, (MegaSecsB + (Before+8)*1000000) < (MegaSecsA + After*1000000)),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- uninstall_test_data,
- [pseudo])),
-
- ok.
-
-%%-----------------------------------------------------------------
-%% API tests for ORB to ORB with limited concurrent connections
-%%-----------------------------------------------------------------
-%% MULTI ORB PSEUDO with limited concurrent connections tests
-max_connections_api(_Config) ->
- %% --- Create a slave-node ---
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{iiop_backlog, 0},
- {iiop_max_in_connections, 2}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
- [nameservice])),
-
- %% Claim connection 1 & 2
- Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- corba:string_to_object("corbaname::1.2@"++ServerHost++":"++
- integer_to_list(ServerPort)++"/NameService#mamba")),
- %% Claim backlog
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node()),
-
- spawn(ClientNode, orber_test_server, print, [Obj]),
- timer:sleep(5000),
- ?match([_], orber_test_lib:remote_apply(ClientNode, orber,
- iiop_connections, [])),
-
- %% Try to connect. Should fail. Due to the behavior of different TCP stacks, backlog 1
- %% might not be the precise value. Hence, we also need to define the iiop_timeout. Otherwise
- %% this test case will fail. For the same reason we must GC this connection.
- {ok, ClientNodeII, _ClientHostII} =
- ?match({ok,_,_}, orber_test_lib:js_node([{iiop_setup_connection_timeout, 5},
- {iiop_timeout, 5},
- {iiop_connection_timeout, 8}])),
-
- ?match({'EXCEPTION', _},
- orber_test_lib:remote_apply(ClientNodeII, orber_test_server,
- testing_iiop_string, [Obj, "Fail"])),
-
- %% Remove 2 connections. We need to wait a moment so that both sides has detected it.
- timer:sleep(5000),
- ?match([_,_], orber:iiop_connections()),
- ?match(ok, orber_iiop_pm:close_connection([{ServerHost, ServerPort}])),
- timer:sleep(5000),
- [{Host, Port}] = ?match([_], orber:iiop_connections()),
- ?match(ok, orber_iiop_pm:close_connection([{Host, Port}])),
- timer:sleep(5000),
- ?match([], orber:iiop_connections()),
-
- ?match([_], orber_test_lib:remote_apply(ClientNode, orber,
- iiop_connections, [])),
-
- ?match([], orber_test_lib:remote_apply(ClientNodeII, orber,
- iiop_connections, [])),
-
- ?match({ok, "OK"},
- orber_test_lib:remote_apply(ClientNodeII, orber_test_server,
- testing_iiop_string, [Obj, "OK"])),
-
- timer:sleep(4000),
- ?match([_], orber_test_lib:remote_apply(ClientNodeII, orber,
- iiop_connections, [])),
-
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- uninstall_test_data,
- [pseudo])),
-
- ok.
-
-
-%%-----------------------------------------------------------------
-%% API tests for terminating connection by using an IOR.
-%%-----------------------------------------------------------------
-%% Close outgoing connection
-close_connections_api(_Config) ->
- %% --- Create a slave-node ---
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{ip_address, IP}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
- [nameservice])),
- orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- IP = orber_test_lib:get_host(),
-
- %% Create a connection
- Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- corba:string_to_object("corbaname::1.2@"++IP++":"++
- integer_to_list(ServerPort)++"/NameService#mamba")),
- %% Check that it's up.
- ?match([{IP, ServerPort}], orber:iiop_connections(out)),
- %% Try to close using the wronge interface.
- ?match(ok, orber:close_connection(Obj, Loopback)),
- %% Should still be up.
- ?match([{IP, ServerPort}], orber:iiop_connections(out)),
- %% Try to close it properly
- ?match(ok, orber:close_connection(Obj)),
- %% Wait a moment so that both sides has detected it.
- timer:sleep(5000),
- %% Worked?
- ?match([], orber:iiop_connections(out)),
- ok.
-
-
-%% IIOP Local Interface disconnect tests
-%% This case test if the server ORB use the correct
-%% local interface when connecting to another ORB
-close_connections_local_interface_api(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{ip_address_local, Loopback}])),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{ip_address, IP}])),
- Port = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- IOR = ?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
- ["corbaloc::1.2@"++IP++":"++integer_to_list(Port)++"/NameService"])),
-
- %% Check that the connnection is up and running using the default interface
- ?match([{Loopback,_RemotePort}], orber_test_lib:remote_apply(ServerNode, orber,
- iiop_connections, [in])),
- ?match([{IP, Port}],
- orber_test_lib:remote_apply(ClientNode, orber,
- iiop_connections, [out])),
- %% Try to close the connection
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber,
- close_connection, [IOR])),
- %% Wait a moment so that both sides has detected it.
- timer:sleep(5000),
- %% Now the connection shall be gone.
- ?match([], orber_test_lib:remote_apply(ClientNode, orber,
- iiop_connections, [out])),
- ?match([], orber_test_lib:remote_apply(ServerNode, orber,
- iiop_connections, [in])),
-
- ok.
-
-%% IIOP Local Interface disconnect tests
-%% This case test if the server ORB use the correct
-%% local interface when connecting to another ORB
-close_connections_local_interface_ctx_override_api(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{ip_address_local, IP},
- {ip_address, IP}])),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{ip_address, IP}])),
- Port = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- IOR = ?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
- ["corbaloc::1.2@"++IP++":"++integer_to_list(Port)++"/NameService",
- [#'IOP_ServiceContext'
- {context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface, Loopback}}]])),
-
- timer:sleep(2000),
- %% Check that the connnection is up and running using the default interface
- ?match([{Loopback,_RemotePort}], orber_test_lib:remote_apply(ServerNode, orber,
- iiop_connections, [in])),
-
- ?match([{IP, Port, Loopback}],
- orber_test_lib:remote_apply(ClientNode, orber,
- iiop_connections, [out])),
- %% Try to close not supplying the interface.
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber,
- close_connection, [IOR])),
-
- timer:sleep(2000),
- %% The connection shall still be up and running
- ?match([{Loopback,_RemotePort}], orber_test_lib:remote_apply(ServerNode, orber,
- iiop_connections, [in])),
- ?match([{IP, Port, Loopback}],
- orber_test_lib:remote_apply(ClientNode, orber,
- iiop_connections, [out])),
- %% Try to close not supplying the interface.
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber,
- close_connection, [IOR, IP])),
-
- timer:sleep(2000),
- %% The connection shall still be up and running
- ?match([{Loopback,_RemotePort}], orber_test_lib:remote_apply(ServerNode, orber,
- iiop_connections, [in])),
- ?match([{IP, Port, Loopback}],
- orber_test_lib:remote_apply(ClientNode, orber,
- iiop_connections, [out])),
-
- %% Try to close supplying the correct interface.
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber,
- close_connection, [IOR, Loopback])),
- %% Wait a moment so that both sides has detected it.
- timer:sleep(5000),
- %% Now the connection shall be gone.
- ?match([], orber_test_lib:remote_apply(ServerNode, orber,
- iiop_connections, [in])),
- ?match([], orber_test_lib:remote_apply(ClientNode, orber,
- iiop_connections, [out])),
- ok.
-
-%% IIOP alternate address disconnect tests
-%% This case test if the server ORB use the correct
-%% local interface when connecting to another ORB
-close_connections_alt_iiop_addr_api(_Config) ->
- %% --- Create a slave-node ---
- Loopback = orber_test_lib:get_loopback_interface(),
- IP = orber_test_lib:get_host(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{giop_version, {1, 2}},
- {ip_address, {multiple, [IP, Loopback]}}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
- [{nameservice, Loopback, ServerPort}])),
- %% Create two connections
- Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- corba:string_to_object("corbaname::1.2@"++IP++":"++
- integer_to_list(ServerPort)++"/NameService#mamba")),
- ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- corba:string_to_object("corbaname::1.2@"++Loopback++":"++
- integer_to_list(ServerPort)++"/NameService#mamba")),
- timer:sleep(2000),
- %% The connection shall still be up and running
- ?match([{_,_}, {_,_}], orber:iiop_connections(out)),
- ?match([{_,_}, {_,_}],
- orber_test_lib:remote_apply(ServerNode, orber,
- iiop_connections, [in])),
-
- %% Try to close the connection
- ?match(ok, orber:close_connection(Obj)),
- %% Wait a moment so that both sides has detected it.
- timer:sleep(5000),
- %% Now the connections shall be gone.
- ?match([], orber:iiop_connections(out)),
- ?match([], orber_test_lib:remote_apply(ServerNode, orber,
- iiop_connections, [in])),
- ok.
-
-%% IIOP alternate address disconnect tests
-%% This case test if the server ORB use the correct
-%% local interface when connecting to another ORB
-close_connections_multiple_profiles_api(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- %% --- Create a slave-node ---
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{ip_address,
- {multiple, [Loopback, IP]}}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data, [nameservice])),
- %% Create two connections
- Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- corba:string_to_object("corbaname::1.2@"++IP++":"++
- integer_to_list(ServerPort)++"/NameService#mamba")),
- ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- corba:string_to_object("corbaname::1.2@"++Loopback++":"++
- integer_to_list(ServerPort)++"/NameService#mamba")),
- %% The connection shall still be up and running
- ?match([{_,_}, {_,_}], orber:iiop_connections(out)),
- ?match([{_,_}, {_,_}],
- orber_test_lib:remote_apply(ServerNode, orber,
- iiop_connections, [in])),
-
- %% Try to close the connection
- ?match(ok, orber:close_connection(Obj)),
- %% Wait a moment so that both sides has detected it.
- timer:sleep(5000),
- %% Now the connections shall be gone.
- ?match([], orber:iiop_connections(out)),
- ?match([], orber_test_lib:remote_apply(ServerNode, orber,
- iiop_connections, [in])),
- ok.
-
-%%-----------------------------------------------------------------
-%% API tests for ORB to ORB with iiop_packet_size set
-%%-----------------------------------------------------------------
-%% Exceed the maximum request size
-max_packet_size_exceeded_api(_Config) ->
- case catch gen_tcp:listen(0, [{packet,cdr}, {packet_size, 14}]) of
- {'EXIT',badarg} ->
- {skipped, "The inet option {packet_size, Max} not supported"};
- {ok, LS} ->
- (catch gen_tcp:close(LS)),
- %% --- Create a slave-node ---
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{iiop_packet_size, 1}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber,
- iiop_port, []),
- ?match({'EXCEPTION', #'CosNaming_NamingContextExt_InvalidAddress'{}},
- corba:string_to_object("corbaloc::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService")),
- ok
- end.
-
-%%-----------------------------------------------------------------
-%% API tests for ORB to ORB with iiop_packet_size set
-%%-----------------------------------------------------------------
-%% Not exceed the maximum request size
-max_packet_size_ok_api(_Config) ->
- case catch gen_tcp:listen(0, [{packet,cdr}, {packet_size, 14}]) of
- {'EXIT',badarg} ->
- {skipped, "The inet option {packet_size, Max} not supported"};
- {ok, LS} ->
- (catch gen_tcp:close(LS)),
- %% --- Create a slave-node ---
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{iiop_packet_size, 5000}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber,
- iiop_port, []),
- ?match({'IOP_IOR',_,_},
- corba:string_to_object("corbaloc::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService")),
- ok
- end.
-
-
-
-%%-----------------------------------------------------------------
-%% API tests for ORB to ORB, no security
-%%-----------------------------------------------------------------
-%% LIGHT IFR ORB API tests
-light_ifr_api(_Config) ->
-
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, 128}])),
-
- ?match([_,_,_,_], orber_test_lib:remote_apply(ClientNode, orber, get_tables, [])),
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
- install_test_data,
- [nameservice])),
-
-
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, 128}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
- [nameservice])),
- ?match([_,_,_,_], orber_test_lib:remote_apply(ServerNode, orber, get_tables, [])),
-
- Obj = ?match({'IOP_IOR',_,_},
- corba:string_to_object("corbaname::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService#mamba")),
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib, test_coding, [Obj])),
-
- ?match(0, orber_test_lib:remote_apply(ClientNode, orber_diagnostics, missing_modules, [])),
-
- ?match(ok, orber_test_lib:remote_apply(ClientNode, mnesia, dirty_write,
- [#orber_light_ifr{id = "FakeId1",
- module=non_existing,
- type=?IFR_StructDef}])),
- ?match(ok, orber_test_lib:remote_apply(ClientNode, mnesia, dirty_write,
- [#orber_light_ifr{id = "FakeId2",
- module=non_existing,
- type=?IFR_UnionDef}])),
- ?match(ok, orber_test_lib:remote_apply(ClientNode, mnesia, dirty_write,
- [#orber_light_ifr{id = "FakeId3",
- module=non_existing,
- type=?IFR_ExceptionDef}])),
- ?match(ok, orber_test_lib:remote_apply(ClientNode, mnesia, dirty_write,
- [#orber_light_ifr{id = "FakeId4",
- module=non_existing,
- type=?IFR_InterfaceDef}])),
- ?match(ok, orber_test_lib:remote_apply(ClientNode, mnesia, dirty_write,
- [#orber_light_ifr{id = "FakeId5",
- module=orber_test_lib,
- type=?IFR_InterfaceDef}])),
- ?match(5, orber_test_lib:remote_apply(ClientNode, orber_diagnostics, missing_modules, [])),
-
-
- ?match(ok, mnesia:dirty_write(#ir_UnionDef{ir_Internal_ID = "FakedIId1",
- absolute_name="::Module::NonExisting"})),
- ?match(ok, mnesia:dirty_write(#ir_StructDef{ir_Internal_ID = "FakedIId2",
- absolute_name="::Module::NonExisting"})),
- ?match(ok, mnesia:dirty_write(#ir_ExceptionDef{ir_Internal_ID = "FakedIId3",
- absolute_name="::Module::NonExisting"})),
- ?match(ok, mnesia:dirty_write(#ir_InterfaceDef{ir_Internal_ID = "FakedIId4",
- absolute_name="::Module::NonExisting"})),
- ?match(ok, mnesia:dirty_write(#ir_InterfaceDef{ir_Internal_ID = "FakedIId5",
- absolute_name="::orber::test::lib"})),
-
- ?match(5, orber_diagnostics:missing_modules()),
-
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- uninstall_test_data,
- [nameservice])),
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
- uninstall_test_data,
- [nameservice])),
- ok.
-
-%%-----------------------------------------------------------------
-%% API tests for ORB to ORB, no security
-%%-----------------------------------------------------------------
-%% LIGHT ORB API tests
-%% This case test if a light Orber can communicate correctly
-%% with an fully installed Orber.
-light_orber_api(_Config) ->
- %% --- Create a slave-node ---
- LocalHost = net_adm:localhost(),
- {ok, Node, _Host} =
- ?match({ok,_,_}, orber_test_lib:js_node([{lightweight, ["iiop://"++LocalHost++":"++integer_to_list(orber:iiop_port())]}],
- lightweight)),
- ?match(ok, orber:info(io)),
- ?match([_], orber_test_lib:remote_apply(Node, orber_env, get_lightweight_nodes,[])),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- install_test_data,
- [light])),
-
- Obj1=(catch orber_test_server:oe_create(state,[{pseudo,true}])),
- ?match({_,pseudo,orber_test_server_impl, _,_, _}, Obj1),
- Obj2=(catch orber_test_server:oe_create(state,[])),
- ?match({_,key,_, _,_, _}, Obj2),
-
- NS = corba:resolve_initial_references("NameService"),
- 'CosNaming_NamingContext':bind(NS, lname:new(["mamba"]), Obj1),
- 'CosNaming_NamingContext':bind(NS, lname:new(["viper"]), Obj2),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- light_tests,
- [LocalHost,
- orber:iiop_port(), "viper"])),
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- light_tests,
- [LocalHost,
- orber:iiop_port(), "mamba"])),
-
- %% Clean up.
-
- catch corba:dispose(Obj1),
- catch corba:dispose(Obj2),
- catch 'CosNaming_NamingContext':destroy(NS),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- uninstall_test_data,
- [light])),
- ok.
-%%-----------------------------------------------------------------
-%% API tests for ORB to ORB, no security
-%%-----------------------------------------------------------------
-%% LIGHT ORB API tests
-%% This case test if a light Orber can communicate correctly
-%% with an fully installed Orber. This case test if we can
-%% start as lightweight without first setting the environment
-%% variable
-light_orber2_api(_Config) ->
- %% --- Create a slave-node ---
- LocalHost = net_adm:localhost(),
- {ok, Node, _Host} =
- ?match({ok,_,_}, orber_test_lib:js_node([],
- {lightweight, ["iiop://"++LocalHost++":"++integer_to_list(orber:iiop_port())]})),
- ?match(ok, orber:info(io)),
- ?match([_], orber_test_lib:remote_apply(Node, orber_env, get_lightweight_nodes,[])),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- install_test_data,
- [light])),
-
- Obj1=(catch orber_test_server:oe_create(state,[{pseudo,true}])),
- ?match({_,pseudo,orber_test_server_impl, _,_, _}, Obj1),
- Obj2=(catch orber_test_server:oe_create(state,[])),
- ?match({_,key,_, _,_, _}, Obj2),
-
- NS = corba:resolve_initial_references("NameService"),
- 'CosNaming_NamingContext':bind(NS, lname:new(["mamba"]), Obj1),
- 'CosNaming_NamingContext':bind(NS, lname:new(["viper"]), Obj2),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- light_tests,
- [LocalHost,
- orber:iiop_port(), "viper"])),
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- light_tests,
- [LocalHost,
- orber:iiop_port(), "mamba"])),
-
- %% Clean up.
-
- catch corba:dispose(Obj1),
- catch corba:dispose(Obj2),
- catch 'CosNaming_NamingContext':destroy(NS),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- uninstall_test_data,
- [light])),
- ok.
-
-%%-----------------------------------------------------------------
-%% API tests for ORB to ORB, no security
-%%-----------------------------------------------------------------
-%% MULTI ORB API tests
-%% This case test if data encode/decode (IIOP)
-%% produce the correct result, i.e., the test_server echos
-%% the input parameter or an exception is raised (MARSHAL).
-multi_orber_api(_Config) ->
-
- NewICObj1 = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([])),
- NewICObj2 = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([], [{regname, {local, newic2}}])),
- NewICObj3 = ?match({_,_,_,_,_,_}, orber_test_server:oe_create([], [{regname, {global, newic3}}])),
- ?match(ok, orber_test_server:print(NewICObj1)),
- ?match(ok, orber_test_server:print(NewICObj2)),
- ?match(ok, orber_test_server:print(NewICObj3)),
- catch corba:dispose(NewICObj1),
- catch corba:dispose(NewICObj2),
- catch corba:dispose(NewICObj3),
-
- %% --- Create a slave-node ---
- {ok, Node, Host} =
- ?match({ok,_,_}, orber_test_lib:js_node()),
- Port = orber_test_lib:remote_apply(Node, orber, iiop_port, []),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- install_test_data,
- [nameservice])),
-
- NSR = ?match({'IOP_IOR',"IDL:omg.org/CosNaming/NamingContextExt:1.0",_},
- corba:string_to_object("corbaloc::1.2@"++Host++":"++
- integer_to_list(Port)++"/NameService")),
-
- ?match({'EXCEPTION',{'CosNaming_NamingContext_NotFound',_,_,_}},
- 'CosNaming_NamingContext':resolve(NSR, lname:new(["not_exist"]))),
-
- Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- 'CosNaming_NamingContext':resolve(NSR, lname:new(["mamba"]))),
- ?match(ok, orber_test_server:print(Obj)),
-
- Obj12B = ?match({'IOP_IOR',_,_},
- corba:string_to_object("corbaloc::1.2@"++Host++":"++integer_to_list(Port)++"/Mamba")),
-
- Obj11B = ?match({'IOP_IOR',_,_},
- corba:string_to_object("corbaloc::1.1@"++Host++":"++integer_to_list(Port)++"/Mamba")),
-
- Obj10B = ?match({'IOP_IOR',_,_},
- corba:string_to_object("corbaloc::1.0@"++Host++":"++integer_to_list(Port)++"/Mamba")),
-
- context_test(Obj12B),
- context_test(Obj11B),
-
- ?match(ok, orber_test_server:print(Obj12B)),
- ?match(ok, orber_test_server:print(Obj11B)),
- ?match(ok, orber_test_server:print(Obj10B)),
- ?match({'EXCEPTION',{'CosNaming_NamingContextExt_InvalidAddress',_}},
- corba:string_to_object("corbaloc::1.0@"++Host++":"++integer_to_list(Port)++"/Wrong")),
-
- ?match(ok, orber_test_lib:corba_object_tests(Obj12B, NSR)),
- ?match(ok, orber_test_lib:corba_object_tests(Obj11B, NSR)),
- ?match(ok, orber_test_lib:corba_object_tests(Obj10B, NSR)),
-
- %%--- Testing code and decode arguments ---
- orber_test_lib:test_coding(Obj),
-
- ?match({'EXCEPTION',#'BAD_CONTEXT'{}},
- orber_test_server:
- print(Obj12B,
- [{context,
- [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface,
- {127,0,0,1}}}]}])),
-
- ?match({'EXCEPTION',{'TRANSIENT',_,_,_}},
- orber_test_server:stop_brutal(Obj12B)),
- ?match({'EXCEPTION',{'TRANSIENT',_,_,_}},
- orber_test_server:print(Obj12B)),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- uninstall_test_data,
- [nameservice])),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% API tests for ORB to ORB, no security, using basic interceptors
-%%-----------------------------------------------------------------
-%% MULTI ORB API tests
-%% This case test if data encode/decode (IIOP)
-%% produce the correct result when using basic interceptors
-%% i.e., the test_server echos the input parameter or
-%% an exception is raised (MARSHAL).
-basic_PI_api(_Config) ->
- %% Change configuration to use Basic Interceptors.
- orber:configure_override(interceptors, {native, [orber_test_lib]}),
- %% --- Create a slave-node ---
- {ok, Node, Host} =
- ?match({ok,_,_}, orber_test_lib:js_node([{interceptors, {native, [orber_test_lib]}}])),
- Port = orber_test_lib:remote_apply(Node, orber, iiop_port, []),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- install_test_data,
- [nameservice])),
-
- Obj12 = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- corba:string_to_object("corbaname::1.2@"++Host++":"++integer_to_list(Port)++"/NameService#mamba")),
-
- Obj11 = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- corba:string_to_object("corbaname::1.1@"++Host++":"++integer_to_list(Port)++"/NameService#mamba")),
-
- Obj10 = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- corba:string_to_object("corbaname::1.0@"++Host++":"++integer_to_list(Port)++"/NameService#mamba")),
-
- ?match(ok, corba:print_object(Obj12)),
- ?match(ok, corba:print_object(Obj11, error_report)),
- ?match(ok, corba:print_object(Obj10, {error_report, "Reason"})),
-
- ?match(ok, orber_test_server:print(Obj12)),
- ?match(ok, orber_test_server:print(Obj11)),
- ?match(ok, orber_test_server:print(Obj10)),
-
-
- Obj12B = ?match({'IOP_IOR',_,_},
- corba:string_to_object("corbaloc::1.2@"++Host++":"++integer_to_list(Port)++"/Mamba")),
-
- Obj11B = ?match({'IOP_IOR',_,_},
- corba:string_to_object("corbaloc::1.1@"++Host++":"++integer_to_list(Port)++"/Mamba")),
-
- Obj10B = ?match({'IOP_IOR',_,_},
- corba:string_to_object("corbaloc::1.0@"++Host++":"++integer_to_list(Port)++"/Mamba")),
-
- ?match(ok, corba:print_object(Obj12B, info_msg)),
- ?match(ok, corba:print_object(Obj11B, {info_msg, "Comment"})),
- ?match([_|_], corba:print_object(Obj10B, string)),
-
- ?match(ok, orber_test_server:print(Obj12B)),
- ?match(ok, orber_test_server:print(Obj11B)),
- ?match(ok, orber_test_server:print(Obj10B)),
- ?match({'EXCEPTION',{'CosNaming_NamingContextExt_InvalidAddress',_}},
- corba:string_to_object("corbaloc::1.0@"++Host++":"++integer_to_list(Port)++"/Wrong")),
-
- ?match(ok, orber_test_lib:alternate_iiop_address(Host, Port)),
-
- context_test(Obj12B),
- context_test(Obj11B),
-
- %%--- Testing code and decode arguments ---
- orber_test_lib:test_coding(Obj12),
- orber_test_lib:test_coding(Obj11),
- orber_test_lib:test_coding(Obj10),
-
- application:set_env(orber, interceptors, false),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- uninstall_test_data,
- [nameservice])),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% API tests for ORB to ORB, ssl security depth 1
-%%-----------------------------------------------------------------
-
-%% SECURE MULTI ORB API tests (SSL depth 1)
-%% This case set up two secure orbs and test if they can
-%% communicate. The case also test to access one of the
-%% secure orbs which must raise a NO_PERMISSION exception.
-ssl_1_multi_orber_api(_Config) ->
- ServerOptions = orber_test_lib:get_options_old(iiop_ssl, server,
- 1, [{iiop_ssl_port, 0}]),
- ClientOptions = orber_test_lib:get_options_old(iiop_ssl, client,
- 1, [{iiop_ssl_port, 0}]),
- ssl_suite(ServerOptions, ClientOptions).
-
-
-%% SECURE MULTI ORB API tests (SSL depth 1)
-%% This case set up two secure orbs and test if they can
-%% communicate. The case also test to access one of the
-%% secure orbs which must raise a NO_PERMISSION exception.
-ssl_1_multi_orber_generation_3_api(_Config) ->
-
- ServerOptions = orber_test_lib:get_options(iiop_ssl, server,
- 1, [{ssl_generation, 3},
- {iiop_ssl_port, 0}]),
- ClientOptions = orber_test_lib:get_options(iiop_ssl, client,
- 1, [{ssl_generation, 3},
- {iiop_ssl_port, 0}]),
- ssl_suite(ServerOptions, ClientOptions).
-
-%%-----------------------------------------------------------------
-%% API tests for ORB to ORB, ssl security depth 2
-%%-----------------------------------------------------------------
-
-%% SECURE MULTI ORB API tests (SSL depth 2)
-%% These case set up two secure orbs and test if they can
-%% communicate. They also test to access one of the
-%% secure orbs which must raise a NO_PERMISSION exception.
-ssl_2_multi_orber_api(_Config) ->
-
- ServerOptions = orber_test_lib:get_options_old(iiop_ssl, server,
- 2, [{iiop_ssl_port, 0}]),
- ClientOptions = orber_test_lib:get_options_old(iiop_ssl, client,
- 2, [{iiop_ssl_port, 0}]),
- ssl_suite(ServerOptions, ClientOptions).
-
-ssl_2_multi_orber_generation_3_api(_Config) ->
-
- ServerOptions = orber_test_lib:get_options(iiop_ssl, server,
- 2, [{ssl_generation, 3},
- {iiop_ssl_port, 0}]),
- ClientOptions = orber_test_lib:get_options(iiop_ssl, client,
- 2, [{ssl_generation, 3},
- {iiop_ssl_port, 0}]),
- ssl_suite(ServerOptions, ClientOptions).
-%%-----------------------------------------------------------------
-%% API tests for ORB to ORB, ssl security depth 2
-%%-----------------------------------------------------------------
-
-%% SECURE MULTI ORB API tests (SSL depth 2)
-%% These case set up two secure orbs and test if they can
-%% communicate. They also test to access one of the
-%% secure orbs which must raise a NO_PERMISSION exception.
-ssl_reconfigure_api(_Config) ->
- ssl_reconfigure_old([]).
-
-
-% ssl_reconfigure_generation_3_api_old(_Config) ->
-% ssl_reconfigure_old([{ssl_generation, 3}]).
-
-ssl_reconfigure_old(ExtraSSLOptions) ->
-
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_},
- orber_test_lib:js_node([{iiop_port, 0},
- {flags, ?ORB_ENV_LOCAL_INTERFACE},
- {ip_address, IP}|ExtraSSLOptions])),
- orber_test_lib:remote_apply(ServerNode, ssl, start, []),
- orber_test_lib:remote_apply(ServerNode, crypto, start, []),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
- [ssl])),
- ?match({ok, _},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
- [Loopback, normal, [{iiop_port, 5648},
- {iiop_ssl_port, 5649},
- {interceptors, {native, [orber_iiop_tracer_silent]}}|ExtraSSLOptions]])),
- ServerOptions = orber_test_lib:get_options_old(iiop_ssl, server,
- 2, [{flags, ?ORB_ENV_LOCAL_INTERFACE},
- {iiop_port, 5648},
- {iiop_ssl_port, 5649},
- {interceptors, {native, [orber_iiop_tracer_silent]}}|ExtraSSLOptions]),
- ?match({ok, _},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
- [Loopback, ssl, ServerOptions])),
-
- ClientOptions = orber_test_lib:get_options_old(iiop_ssl, client,
- 2, [{iiop_ssl_port, 0}|ExtraSSLOptions]),
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node(ClientOptions)),
-
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
- install_test_data,
- [ssl])),
- orber_test_lib:remote_apply(ClientNode, ssl, start, []),
- orber_test_lib:remote_apply(ServerNode, crypto, start, []),
- Obj = ?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba,
- string_to_object, ["corbaname:iiop:1.1@"++Loopback++":5648/NameService#mamba",
- [{context, [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {configuration, ClientOptions}}]}]])),
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_server,
- print, [Obj])).
-
-
-ssl_reconfigure_generation_3_api(_Config) ->
- ssl_reconfigure([{ssl_generation, 3}]).
-
-
-ssl_reconfigure(ExtraSSLOptions) ->
-
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_},
- orber_test_lib:js_node([{iiop_port, 0},
- {flags, ?ORB_ENV_LOCAL_INTERFACE},
- {ip_address, IP}|ExtraSSLOptions])),
- orber_test_lib:remote_apply(ServerNode, ssl, start, []),
- orber_test_lib:remote_apply(ServerNode, crypto, start, []),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
- [ssl])),
- ?match({ok, _},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
- [Loopback, normal, [{iiop_port, 5648},
- {iiop_ssl_port, 5649},
- {interceptors, {native, [orber_iiop_tracer_silent]}}|ExtraSSLOptions]])),
- ServerOptions = orber_test_lib:get_options(iiop_ssl, server,
- 2, [{flags, ?ORB_ENV_LOCAL_INTERFACE},
- {iiop_port, 5648},
- {iiop_ssl_port, 5649},
- {interceptors, {native, [orber_iiop_tracer_silent]}}|ExtraSSLOptions]),
- ?match({ok, _},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
- [Loopback, ssl, ServerOptions])),
-
- ClientOptions = orber_test_lib:get_options(iiop_ssl, client,
- 2, [{iiop_ssl_port, 0}|ExtraSSLOptions]),
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node(ClientOptions)),
-
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
- install_test_data,
- [ssl])),
- orber_test_lib:remote_apply(ClientNode, ssl, start, []),
- orber_test_lib:remote_apply(ServerNode, crypto, start, []),
- Obj = ?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba,
- string_to_object, ["corbaname:iiop:1.1@"++Loopback++":5648/NameService#mamba",
- [{context, [#'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {configuration, ClientOptions}}]}]])),
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_server,
- print, [Obj])).
-
-
-%%------------------------------------------------------------
-%% function : ssl_suite
-%% Arguments: Config
-%% Depth
-%% Returns : ok
-%% Effect :
-%%------------------------------------------------------------
-ssl_suite(ServerOptions, ClientOptions) ->
-
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node(ServerOptions)),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- SSLServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_ssl_port, []),
-
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node(ClientOptions)),
-
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
- [ssl])),
- %% Tell the client to interoperate with the server. The purpose of this
- %% operation is to look up, using NameService, an object reference and
- %% use it to contact the object.
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
- lookup,
- [ServerHost, ServerPort])),
-
- ?match(ok, orber_test_lib:remote_apply(ClientNode, orber_test_lib,
- alternate_ssl_iiop_address,
- [ServerHost, ServerPort, SSLServerPort])),
-
- %% 'This' node is not secure. Contact the server. Must refuse connection.
- NSR = ?match({'IOP_IOR',"IDL:omg.org/CosNaming/NamingContextExt:1.0",_},
- corba:string_to_object("corbaloc::1.2@"++ServerHost++":"++
- integer_to_list(ServerPort)++"/NameService")),
-
- %% Should be 'NO_PERMISSION'??
- ?match({'EXCEPTION',{'COMM_FAILURE',_,_,_}},
- 'CosNaming_NamingContext':resolve(NSR, lname:new(["not_exist"]))),
-
- %% Should be 'NO_PERMISSION'??
- ?match({'EXCEPTION',{'COMM_FAILURE',_,_,_}},
- 'CosNaming_NamingContext':resolve(NSR, lname:new(["mamba"]))),
-
- %% Uninstall.
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- uninstall_test_data,
- [ssl])),
- ok.
-
-%%-----------------------------------------------------------------
-%% iiop_setup_connection_timeout API tests for ORB to ORB.
-%%-----------------------------------------------------------------
-setup_connection_timeout_api(_Config) ->
- ?match(ok, application:set_env(orber, iiop_backlog, 0)),
- %% Wait to be sure that the configuration has kicked in.
- timer:sleep(2000),
- {ok, Ref, Port} = create_fake_server_ORB(normal, 0, [], listen, []),
- ?match(ok, orber:configure(iiop_setup_connection_timeout, 5)),
- ?match(ok, orber:info(io)),
- IP = orber_test_lib:get_host(),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- timer:sleep(2000),
- Corbaloc = "corbaloc::1.2@"++IP++":"++integer_to_list(Port)++"/NameService",
- ?match({'EXCEPTION', _E}, corba:string_to_object(Corbaloc)),
- destroy_fake_ORB(Ref),
- ?match(ok, application:set_env(orber, iiop_backlog, 5)),
- ok.
-
-%%-----------------------------------------------------------------
-%% iiop_setup_connection_timeout API tests for ORB to ORB.
-%%-----------------------------------------------------------------
-setup_multi_connection_timeout_api(_Config) ->
- ?match(ok, application:set_env(orber, iiop_backlog, 0)),
- %% Wait to be sure that the configuration has kicked in.
- timer:sleep(2000),
- {ok, Ref, Port} = create_fake_server_ORB(normal, 0, [], listen, []),
- ?match(ok, application:set_env(orber, iiop_out_ports, {6042, 6234})),
- ?match(ok, orber:configure(iiop_setup_connection_timeout, 5)),
- ?match(ok, orber:info(io)),
- IP = orber_test_lib:get_host(),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- Corbaloc = "corbaloc::1.2@"++IP++":"++integer_to_list(Port)++"/NameService",
- timer:sleep(2000),
- ?match({'EXCEPTION', _E}, corba:string_to_object(Corbaloc)),
- destroy_fake_ORB(Ref),
- ?match(ok, application:set_env(orber, iiop_backlog, 5)),
- ?match(ok, application:set_env(orber, iiop_out_ports, undefined)),
- ok.
-
-setup_multi_connection_timeout_attempts_api(_Config) ->
- ?match(ok, application:set_env(orber, iiop_backlog, 0)),
- %% Wait to be sure that the configuration has kicked in.
- timer:sleep(2000),
- {ok, Ref, Port} = create_fake_server_ORB(normal, 0, [], listen, []),
- ?match(ok, application:set_env(orber, iiop_out_ports, {6042, 6234})),
- ?match(ok, application:set_env(orber, iiop_out_ports_attempts, 1)),
- ?match(ok, orber:configure(iiop_setup_connection_timeout, 5)),
- ?match(ok, orber:info(io)),
- IP = orber_test_lib:get_host(),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- Corbaloc = "corbaloc::1.2@"++IP++":"++integer_to_list(Port)++"/NameService",
- timer:sleep(2000),
- ?match({'EXCEPTION', _E}, corba:string_to_object(Corbaloc)),
- destroy_fake_ORB(Ref),
- ?match(ok, application:set_env(orber, iiop_backlog, 5)),
- ?match(ok, application:set_env(orber, iiop_out_ports, undefined)),
- ok.
-
-setup_multi_connection_timeout_random_api(_Config) ->
- ?match(ok, application:set_env(orber, iiop_backlog, 0)),
- %% Wait to be sure that the configuration has kicked in.
- timer:sleep(2000),
- {ok, Ref, Port} = create_fake_server_ORB(normal, 0, [], listen, []),
- ?match(ok, application:set_env(orber, iiop_out_ports, {6042, 6234})),
- ?match(ok, application:set_env(orber, iiop_out_ports_random, true)),
- ?match(ok, orber:configure(iiop_setup_connection_timeout, 5)),
- ?match(ok, orber:info(io)),
- IP = orber_test_lib:get_host(),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- spawn(?MODULE, do_connect, [IP, Port, [{active, false}]]),
- Corbaloc = "corbaloc::1.2@"++IP++":"++integer_to_list(Port)++"/NameService",
- timer:sleep(2000),
- ?match({'EXCEPTION', _E}, corba:string_to_object(Corbaloc)),
- destroy_fake_ORB(Ref),
- ?match(ok, application:set_env(orber, iiop_backlog, 5)),
- ?match(ok, application:set_env(orber, iiop_out_ports, undefined)),
- ok.
-
-%%-----------------------------------------------------------------
-%% Sending an incorrect header to the server-side ORB.
-%%-----------------------------------------------------------------
-bad_giop_header_api(_Config) ->
- orber:configure_override(interceptors, {native,[orber_iiop_tracer]}),
- orber:configure(orber_debug_level, 10),
- ?match(ok, orber:info(io)),
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node()),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- Req = <<"GIOP",1,2,0,100,0,0,0,5,0,0,0,10,50>> ,
- ?match(ok, fake_client_ORB(normal, ServerHost, ServerPort, [],
- message_error, [Req])),
-
- application:set_env(orber, interceptors, false),
- orber:configure(orber_debug_level, 0),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Fragmented IIOP tests (Server-side).
-%%-----------------------------------------------------------------
--define(REQUEST_ID, 0).
-
--define(REPLY_FRAG_1, <<71,73,79,80,1,2,2,1,0,0,0,41,0,0,0,?REQUEST_ID,0,0,0,0,0,0,0,1,78,69,79,0,0,0,0,2,0,10,0,0,0,0,0,0,0,0,0,18,0,0,0,0,0,0,0,4,49>>).
-%% The fragments are identical for requests and replies.
--define(FRAG_2, <<71,73,79,80,1,2,2,7,0,0,0,5,0,0,0,?REQUEST_ID,50>>).
--define(FRAG_3, <<71,73,79,80,1,2,2,7,0,0,0,5,0,0,0,?REQUEST_ID,51>>).
--define(FRAG_4, <<71,73,79,80,1,2,0,7,0,0,0,5,0,0,0,?REQUEST_ID,0>>).
-
-
-fragments_server_api(_Config) ->
- %% --- Create a slave-node ---
- {ok, Node, Host} =
- ?match({ok,_,_}, orber_test_lib:js_node()),
- Port = orber_test_lib:remote_apply(Node, orber, iiop_port, []),
-
- ?match(ok, orber_test_lib:remote_apply(Node, orber_test_lib,
- install_test_data,
- [nameservice])),
-
- NSR = ?match({'IOP_IOR',"IDL:omg.org/CosNaming/NamingContextExt:1.0",_},
- corba:string_to_object("corbaloc::1.2@"++Host++":"++
- integer_to_list(Port)++"/NameService")),
-
- Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- 'CosNaming_NamingContext':resolve(NSR, lname:new(["mamba"]))),
-
- Any = #any{typecode = {tk_string,0},
- value = "123"},
- Target = #'GIOP_TargetAddress'{label = ?GIOP_KeyAddr,
- value = iop_ior:get_objkey(Obj)},
- %% Fix a request header.
- {Hdr, Body, HdrLen, _What, _Flags} =
- cdr_encode:enc_request_split(
- #giop_env{version = {1,2}, objkey = Target,
- request_id = ?REQUEST_ID,
- response_expected = true,
- op = testing_iiop_any,
- parameters = [49], ctx = [],
- tc = {tk_void,[tk_char],[]},
- host = [orber_test_lib:get_host()],
- iiop_port = orber:iiop_port(),
- iiop_ssl_port = orber:iiop_ssl_port(),
- domain = orber:domain(),
- partial_security = orber:partial_security()}),
- NewBody =
- case size(Body) of
- 1 ->
- <<0,0,0,18,0,0,0,0,0,0,0,4,49>> ;
- Size ->
- Aligned = Size -1,
- <<AligmnetData:Aligned/binary,49>> = Body,
- list_to_binary([AligmnetData, <<0,0,0,18,0,0,0,0,0,0,0,4,49>> ])
- end,
-
- MessSize = HdrLen+size(NewBody),
- ReqFrag = list_to_binary([ <<"GIOP",1:8,2:8,2:8,0:8,
- MessSize:32/big-unsigned-integer>> , Hdr |NewBody]),
- ?match(Any, fake_client_ORB(normal, Host, Port, [], fragments,
- [ReqFrag, ?FRAG_2, ?FRAG_3, ?FRAG_4])),
-
- ok.
-
-%%-----------------------------------------------------------------
-%% Fragmented IIOP tests (Server-side). Exceeding Maximum.
-%%-----------------------------------------------------------------
-fragments_max_server_api(_Config) ->
- %% --- Create a slave-node ---
- IP = orber_test_lib:get_host(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{iiop_max_fragments, 2},
- {ip_address, IP}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- fragments_max_server(ServerNode, IP, ServerPort).
-
-fragments_max_server_added_api(_Config) ->
- %% --- Create a slave-node ---
- IP = orber_test_lib:get_host(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([])),
- ServerPort = 1 + orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match({ok, _},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
- [IP, normal,
- [{iiop_max_fragments, 2},
- {flags, ?ORB_ENV_LOCAL_INTERFACE},
- {iiop_port, ServerPort}]])),
- fragments_max_server(ServerNode, IP, ServerPort).
-
-fragments_max_server(ServerNode, ServerHost, ServerPort) ->
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
- [nameservice])),
- Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- corba:string_to_object("corbaname::1.2@"++ServerHost++":"++
- integer_to_list(ServerPort)++"/NameService#mamba")),
- Target = #'GIOP_TargetAddress'{label = ?GIOP_KeyAddr,
- value = iop_ior:get_objkey(Obj)},
- %% Fix a request header.
- {Hdr, Body, HdrLen, _What, _Flags} =
- cdr_encode:enc_request_split(
- #giop_env{version = {1,2},
- objkey = Target,
- request_id = ?REQUEST_ID,
- response_expected = true,
- op = testing_iiop_any,
- parameters = [49], ctx = [],
- tc = {tk_void,[tk_char],[]},
- host = [orber_test_lib:get_host()],
- iiop_port = orber:iiop_port(),
- iiop_ssl_port = orber:iiop_ssl_port(),
- domain = orber:domain(),
- partial_security = orber:partial_security()}),
- NewBody =
- case size(Body) of
- 1 ->
- <<0,0,0,18,0,0,0,0,0,0,0,4,49>> ;
- Size ->
- Aligned = Size -1,
- <<AligmnetData:Aligned/binary,49>> = Body,
- list_to_binary([AligmnetData, <<0,0,0,18,0,0,0,0,0,0,0,4,49>> ])
- end,
-
- MessSize = HdrLen+size(NewBody),
- ReqFrag = list_to_binary([ <<"GIOP",1:8,2:8,2:8,0:8,
- MessSize:32/big-unsigned-integer>> , Hdr |NewBody]),
- ?match(#'IMP_LIMIT'{},
- fake_client_ORB(normal, ServerHost, ServerPort, [], fragments_max,
- [ReqFrag, ?FRAG_2, ?FRAG_3, ?FRAG_4])),
-
- ok.
-
-%%-----------------------------------------------------------------
-%% Fragmented IIOP tests (Client-side).
-%%-----------------------------------------------------------------
-fragments_client_api(_Config) ->
- Any = #any{typecode = {tk_string,0},
- value = "123"},
- application:set_env(orber, interceptors, {native,[orber_iiop_tracer]}),
- orber:configure(orber_debug_level, 10),
- orber:info(),
- IOR = ?match({'IOP_IOR',_,_},
- iop_ior:create_external({1, 2}, "IDL:FAKE:1.0",
- "localhost", 6004, "FAKE", [])),
- spawn(?MODULE, create_fake_server_ORB, [normal, 6004, [], fragments,
- [?REPLY_FRAG_1, ?FRAG_2,
- ?FRAG_3, ?FRAG_4]]),
- ?match({ok, Any}, orber_test_server:testing_iiop_any(IOR, Any)),
- application:set_env(orber, interceptors, false),
- orber:configure(orber_debug_level, 0),
- ok.
-
-bad_fragment_id_client_api(_Config) ->
- application:set_env(orber, interceptors, {native,[orber_iiop_tracer]}),
- orber:configure(orber_debug_level, 10),
- orber:info(),
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node()),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- Req = <<71,73,79,80,1,2,2,7,0,0,0,5,0,0,0,100,50>> ,
- ?match(ok, fake_client_ORB(normal, ServerHost, ServerPort, [],
- message_error, [Req])),
-
- application:set_env(orber, interceptors, false),
- orber:configure(orber_debug_level, 0),
-
- ok.
-
-%%-----------------------------------------------------------------
-%% Non-existing request id
-%%-----------------------------------------------------------------
-bad_id_cancel_request_api(Config) when is_list(Config) ->
- Req10 = cdr_encode:enc_cancel_request(#giop_env{version = {1, 0},
- request_id = 556}),
- Req11 = cdr_encode:enc_cancel_request(#giop_env{version = {1, 1},
- request_id = 556}),
- Req12 = cdr_encode:enc_cancel_request(#giop_env{version = {1, 2},
- request_id = 556}),
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node()),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match(ok, fake_client_ORB(normal, ServerHost, ServerPort, [],
- message_error, [Req10])),
- ?match(ok, fake_client_ORB(normal, ServerHost, ServerPort, [],
- message_error, [Req11])),
- ?match(ok, fake_client_ORB(normal, ServerHost, ServerPort, [],
- message_error, [Req12])),
- ok.
-
-%%-----------------------------------------------------------------
-%% Local functions.
-%%-----------------------------------------------------------------
-
-do_connect(Host, Port, Options) ->
- gen_tcp:connect(Host, Port, Options),
- timer:sleep(20000).
-
-pseudo_calls(0, _) ->
- ok;
-pseudo_calls(Times, Obj) ->
- orber_test_server:pseudo_call(Obj),
- New = Times - 1,
- pseudo_calls(New, Obj).
-pseudo_casts(0, _) ->
- ok;
-pseudo_casts(Times, Obj) ->
- orber_test_server:pseudo_cast(Obj),
- New = Times - 1,
- pseudo_casts(New, Obj).
-
-context_test(Obj) ->
- CodeSetCtx = #'CONV_FRAME_CodeSetContext'{char_data = 65537,
- wchar_data = 65801},
- FTGrp = #'FT_FTGroupVersionServiceContext'{object_group_ref_version = ?ULONGMAX},
- FTReq = #'FT_FTRequestServiceContext'{client_id = "ClientId",
- retention_id = ?LONGMAX,
- expiration_time = ?ULONGLONGMAX},
-
- IDToken1 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTAbsent,
- value = true},
- IDToken2 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTAnonymous,
- value = false},
- IDToken3 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTPrincipalName,
- value = [0,255]},
- IDToken4 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTX509CertChain,
- value = [1,255]},
- IDToken5 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTDistinguishedName,
- value = [2,255]},
- IDToken6 = #'CSI_IdentityToken'{label = ?ULONGMAX,
- value = [3,255]},
-
- MTEstablishContext1 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
- [#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken1,
- client_authentication_token = [1, 255]}},
- MTEstablishContext2 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
- [#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken2,
- client_authentication_token = [1, 255]}},
- MTEstablishContext3 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
- [#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken3,
- client_authentication_token = [1, 255]}},
- MTEstablishContext4 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
- [#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken4,
- client_authentication_token = [1, 255]}},
- MTEstablishContext5 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
- [#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken5,
- client_authentication_token = [1, 255]}},
- MTEstablishContext6 = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTEstablishContext,
- value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX,
- authorization_token =
- [#'CSI_AuthorizationElement'
- {the_type = ?ULONGMAX,
- the_element = [0,255]}],
- identity_token = IDToken6,
- client_authentication_token = [1, 255]}},
- MTCompleteEstablishContext = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTCompleteEstablishContext,
- value = #'CSI_CompleteEstablishContext'{client_context_id = ?ULONGLONGMAX,
- context_stateful = false,
- final_context_token = [1, 255]}},
- MTContextError = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTContextError,
- value = #'CSI_ContextError'{client_context_id = ?ULONGLONGMAX,
- major_status = 1,
- minor_status = 2,
- error_token = [2,255]}},
- MTMessageInContext = #'CSI_SASContextBody'
- {label = ?CSI_MsgType_MTMessageInContext,
- value = #'CSI_MessageInContext'{client_context_id = ?ULONGLONGMAX,
- discard_context = true}},
- Ctx = [#'IOP_ServiceContext'{context_id=?IOP_CodeSets,
- context_data = CodeSetCtx},
- #'IOP_ServiceContext'{context_id=?IOP_FT_GROUP_VERSION,
- context_data = FTGrp},
- #'IOP_ServiceContext'{context_id=?IOP_FT_REQUEST,
- context_data = FTReq},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = MTEstablishContext1},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = MTEstablishContext2},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = MTEstablishContext3},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = MTEstablishContext4},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = MTEstablishContext5},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = MTEstablishContext6},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = MTCompleteEstablishContext},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = MTContextError},
- #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService,
- context_data = MTMessageInContext},
- #'IOP_ServiceContext'{context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {any_kind_of_data, {127,0,0,1}, 4001}}],
- ?match(ok, orber_test_server:testing_iiop_context(Obj, [{context, Ctx}])).
-
-
-create_fake_server_ORB(Type, Port, Options, listen, _Data) ->
- {ok, _ListenSocket, NewPort} =
- orber_socket:listen(Type, Port,
- [{backlog, 0}, {active, false}|Options]),
- Socket = orber_socket:connect(Type, 'localhost', NewPort, [{active, false}|Options]),
- {ok, {Type, Socket}, NewPort};
-create_fake_server_ORB(Type, Port, Options, Action, Data) ->
- {ok, ListenSocket, _NewPort} =
- orber_socket:listen(Type, Port, [{active, false}|Options]),
- Socket = orber_socket:accept(Type, ListenSocket),
- do_server_action(Type, Socket, Action, Data),
- orber_socket:close(Type, Socket),
- ok.
-
-destroy_fake_ORB({Type, Socket}) ->
- orber_socket:close(Type, Socket);
-destroy_fake_ORB(_) ->
- ok.
-
-fake_client_ORB(Type, Host, Port, Options, connect, _Data) ->
- Socket = orber_socket:connect(Type, Host, Port, [{active, false}|Options]),
- {Type, Socket};
-fake_client_ORB(Type, Host, Port, Options, Action, Data) ->
- Socket = orber_socket:connect(Type, Host, Port, [{active, false}|Options]),
- Result = do_client_action(Type, Socket, Action, Data),
- orber_socket:close(Type, Socket),
- Result.
-
-
-
-do_server_action(Type, Socket, fragments, FragList) ->
- timer:sleep(3000),
- {ok, _B} = gen_tcp:recv(Socket, 0),
- ok = send_data(Type, Socket, FragList);
-do_server_action(_Type, _Socket, _Action, _Data) ->
- ok.
-
-do_client_action(Type, Socket, fragments, FragList) ->
- ok = send_data(Type, Socket, FragList),
- timer:sleep(3000),
- {ok, Bytes} = gen_tcp:recv(Socket, 0),
- {#reply_header{request_id = ?REQUEST_ID, reply_status = no_exception}, ok, [Par]} =
- cdr_decode:dec_message({tk_void,[tk_any],[tk_any]}, Bytes),
- Par;
-do_client_action(Type, Socket, fragments_max, FragList) ->
- ok = send_data(Type, Socket, FragList),
- timer:sleep(3000),
- {ok, Bytes} = gen_tcp:recv(Socket, 0),
- {#reply_header{request_id = ?REQUEST_ID, reply_status = system_exception}, Exc, []} =
- cdr_decode:dec_message({tk_void,[tk_any],[tk_any]}, Bytes),
- Exc;
-do_client_action(Type, Socket, message_error, Data) ->
- ok = send_data(Type, Socket, Data),
- timer:sleep(3000),
- {ok,Bytes} = gen_tcp:recv(Socket, 0),
- 'message_error' = cdr_decode:dec_message({tk_void,[tk_any],[tk_any]}, Bytes),
- ok;
-do_client_action(_Type, _Socket, _Action, _Data) ->
- ok.
-
-send_data(_Type, _Socket, []) ->
- ok;
-send_data(Type, Socket, [H|T]) ->
- orber_socket:write(Type, Socket, H),
- send_data(Type, Socket, T).
-
diff --git a/lib/orber/test/naming_context_SUITE.erl b/lib/orber/test/naming_context_SUITE.erl
deleted file mode 100644
index 2afede287a..0000000000
--- a/lib/orber/test/naming_context_SUITE.erl
+++ /dev/null
@@ -1,390 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%%
-%% Description:
-%% Test suite for Name service
-%%
-%%-----------------------------------------------------------------
--module(naming_context_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/include/corba.hrl").
-
--define(default_timeout, test_server:minutes(5)).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
-
--export([name_context/1, check_list/1, name_context_ext/1]).
-
--export([init_per_suite/1, end_per_suite/1, init_per_testcase/2,
- end_per_testcase/2]).
-
-
-%%-----------------------------------------------------------------
-%% Macros
-%%-----------------------------------------------------------------
--define(REMAP_EXCEPT(F), case catch F of
- {'EXCEPTION', E} -> exit(E);
- {'EXIT', E} -> exit(E);
- R -> R
- end).
-
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-cases() ->
- [name_context, check_list, name_context_ext].
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-
-init_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- Dog=test_server:timetrap(?default_timeout),
- orber:jump_start(0),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- orber:jump_stop(),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(Config) ->
- Config.
-
-%%-----------------------------------------------------------------
-%% Test Case: name handling tests
-%% Description:
-%%-----------------------------------------------------------------
-name_context(_) ->
- ?REMAP_EXCEPT(name_context_run()).
-
-name_context_run() ->
- Ns = corba:resolve_initial_references("NameService"),
-
- ?match({'EXCEPTION', #'NO_PERMISSION'{}},
- 'CosNaming_NamingContextExt':destroy(Ns)),
-
- %% Create a test context.
- Tc = 'CosNaming_NamingContext':bind_new_context(Ns,
- [#'CosNaming_NameComponent'{id="testcontext",
- kind=""}]),
- %% Start testing
- 'CosNaming_NamingContext':bind(Tc, [#'CosNaming_NameComponent'
- {id="hej",
- kind=""}], Ns),
- Ns = 'CosNaming_NamingContext':resolve(Tc,
- [#'CosNaming_NameComponent'{id="hej",
- kind=""}]),
- Nc = 'CosNaming_NamingContext':new_context(Tc),
- 'CosNaming_NamingContext':bind(Tc, [#'CosNaming_NameComponent'
- {id="stop",
- kind=""}], Nc),
- Nc = 'CosNaming_NamingContext':resolve(Tc,
- [#'CosNaming_NameComponent'{id="stop",
- kind=""}]),
- {'EXCEPTION', E0} =
- (catch 'CosNaming_NamingContext':bind(Tc,
- [#'CosNaming_NameComponent'{id="stop",
- kind=""}], Ns)),
- ok = 'CosNaming_NamingContext':rebind(Tc,
- [#'CosNaming_NameComponent'{id="stop",
- kind=""}], Ns),
- {'CosNaming_NamingContext_AlreadyBound', _} = E0,
- 'CosNaming_NamingContext':bind_context(Tc,
- [#'CosNaming_NameComponent'{id="evaluate",
- kind=""}], Nc),
- Nc =
- 'CosNaming_NamingContext':resolve(Tc,
- [#'CosNaming_NameComponent'{id="evaluate",
- kind=""}]),
- 'CosNaming_NamingContext':bind(Tc,
- [#'CosNaming_NameComponent'{id="evaluate",
- kind=""},
- #'CosNaming_NameComponent'{id="hej",
- kind=""}], Ns),
- ok = 'CosNaming_NamingContext':rebind(Tc,
- [#'CosNaming_NameComponent'{id="evaluate",
- kind=""},
- #'CosNaming_NameComponent'{id="hej",
- kind=""}], Ns),
- Ns = 'CosNaming_NamingContext':resolve(Tc,
- [#'CosNaming_NameComponent'{id="evaluate",
- kind=""},
- #'CosNaming_NameComponent'{id="hej",
- kind=""}]),
- {'EXCEPTION', E1} =
- (catch 'CosNaming_NamingContext':resolve(Tc,
- [#'CosNaming_NameComponent'{id="stop",
- kind=""},
- #'CosNaming_NameComponent'{id="hej",
- kind=""}])),
- ?match(ok, orber_diagnostics:nameservice()),
-
- {'CosNaming_NamingContext_CannotProceed', _,_,_} = E1,
- {'EXCEPTION', E2} = (catch 'CosNaming_NamingContext':destroy(Nc)),
- {'CosNaming_NamingContext_NotEmpty', _} = E2,
- ok = 'CosNaming_NamingContext':unbind(Tc,
- [#'CosNaming_NameComponent'{id="evaluate",
- kind=""},
- #'CosNaming_NameComponent'{id="hej",
- kind=""}]),
- ok = 'CosNaming_NamingContext':destroy(Nc),
- ok = 'CosNaming_NamingContext':unbind(Tc,
- [#'CosNaming_NameComponent'{id="evaluate",
- kind=""}]),
- ok = 'CosNaming_NamingContext':unbind(Tc,
- [#'CosNaming_NameComponent'{id="stop",
- kind=""}]),
- ok = 'CosNaming_NamingContext':unbind(Tc,
- [#'CosNaming_NameComponent'{id="hej",
- kind=""}]),
- case 'CosNaming_NamingContext':list(Tc, 3) of
- {ok, [], ?ORBER_NIL_OBJREF} ->
- ok;
- _ ->
- exit(not_empty)
- end,
- ok = 'CosNaming_NamingContext':unbind(Ns,
- [#'CosNaming_NameComponent'{id="testcontext",
- kind=""}]),
- ok = 'CosNaming_NamingContext':destroy(Tc),
- ok.
-
-
-
-%% Check that the CosNaming::NamingContext::list() returns ok.
-%% Own Id: OTP-2023
-check_list(Config) when is_list(Config) ->
- ?REMAP_EXCEPT(check_list_run(Config)).
-
-check_list_run(_Config) ->
- create_default_contexts(),
- Ns = corba:resolve_initial_references("NameService"),
- {_, BL, _} = ?match({ok, _, ?ORBER_NIL_OBJREF},
- 'CosNaming_NamingContext':list(Ns, 256)),
-
- FF = fun(X) -> XX = hd(X#'CosNaming_Binding'.binding_name),
- XX#'CosNaming_NameComponent'.id end,
-
- L = lists:sort(lists:map(FF, BL)),
- ["host", "workgroup"] = L,
-
- %% Test next_n/2
- {_, _, BI} = ?match({ok, [], _BI}, 'CosNaming_NamingContext':list(Ns, 0)),
- ?match({true, []}, 'CosNaming_BindingIterator':next_n(BI, 0)),
- ?match({true, [_]}, 'CosNaming_BindingIterator':next_n(BI, 1)),
- ?match({false, [_]}, 'CosNaming_BindingIterator':next_n(BI, 1)),
- ?match({false, []}, 'CosNaming_BindingIterator':next_n(BI, 1)),
- ?match(ok, 'CosNaming_BindingIterator':destroy(BI)),
-
- {_, _, BI2} = ?match({ok, [], _BI2}, 'CosNaming_NamingContext':list(Ns, 0)),
- ?match({true, _}, 'CosNaming_BindingIterator':next_one(BI2)),
- ?match({true, _}, 'CosNaming_BindingIterator':next_one(BI2)),
- ?match({false, _}, 'CosNaming_BindingIterator':next_one(BI2)),
- ?match(ok, 'CosNaming_BindingIterator':destroy(BI2)),
- ?match(ok, orber_diagnostics:nameservice()),
- ok.
-
-create_default_contexts() ->
- HostComponent = lname_component:set_id(lname_component:create(),
- "host"),
- HostsComponent = lname_component:set_id(lname_component:create(),
- "hosts"),
- ResourcesComponent = lname_component:set_id(lname_component:create(),
- "resources"),
- DevelopmentComponent = lname_component:set_id(lname_component:create(),
- "development"),
- FactoriesComponent = lname_component:set_id(lname_component:create(),
- "factories"),
- WGComponent = lname_component:set_id(lname_component:create(),
- "workgroup"),
- %% Creation of Naming Context host and it's subcontexts
- NS = corba:resolve_initial_references("NameService"),
- H = 'CosNaming_NamingContext':bind_new_context(NS,
- lname:insert_component(lname:create(), 1, HostComponent)),
- HR = 'CosNaming_NamingContext':bind_new_context(H,
- lname:insert_component(lname:create(), 1, ResourcesComponent)),
- 'CosNaming_NamingContext':bind_new_context(HR,
- lname:insert_component(lname:create(), 1, FactoriesComponent)),
- HD = 'CosNaming_NamingContext':bind_new_context(H,
- lname:insert_component(lname:create(), 1, DevelopmentComponent)),
- HDR = 'CosNaming_NamingContext':bind_new_context(HD,
- lname:insert_component(lname:create(), 1, ResourcesComponent)),
- 'CosNaming_NamingContext':bind_new_context(HDR,
- lname:insert_component(lname:create(), 1, FactoriesComponent)),
- %% Creation of Naming Context workgroup and it's subcontexts
- W = 'CosNaming_NamingContext':bind_new_context(NS,
- lname:insert_component(lname:create(), 1, WGComponent)),
- 'CosNaming_NamingContext':bind_new_context(W,
- lname:insert_component(lname:create(), 1, HostsComponent)),
- WR = 'CosNaming_NamingContext':bind_new_context(W,
- lname:insert_component(lname:create(), 1, ResourcesComponent)),
- 'CosNaming_NamingContext':bind_new_context(WR,
- lname:insert_component(lname:create(), 1, FactoriesComponent)),
- WD = 'CosNaming_NamingContext':bind_new_context(W,
- lname:insert_component(lname:create(), 1, DevelopmentComponent)),
- WDR = 'CosNaming_NamingContext':bind_new_context(WD,
- lname:insert_component(lname:create(), 1, ResourcesComponent)),
- 'CosNaming_NamingContext':bind_new_context(WDR,
- lname:insert_component(lname:create(), 1, FactoriesComponent)),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case:
-%% Description:
-%%-----------------------------------------------------------------
-name_context_ext(_Config) ->
- ?REMAP_EXCEPT(name_context_ext_run()).
-
-name_context_ext_run() ->
- NS = ?match({_,pseudo,_, _,_, _},
- corba:resolve_initial_references("NameService")),
-
- Name1 = [#'CosNaming_NameComponent'{id="\\<id1\\>", kind="kind1"},
- #'CosNaming_NameComponent'{id="id2", kind="kind2"}],
- String1 = "\\<id1\\>.kind1/id2.kind2",
- Name2 = [#'CosNaming_NameComponent'{id="id1", kind=""},
- #'CosNaming_NameComponent'{id="id2", kind=""},
- #'CosNaming_NameComponent'{id="id3", kind=""}],
- String2 = "id1/id2/id3",
- Name3 = [#'CosNaming_NameComponent'{id="id1", kind="kind1"},
- #'CosNaming_NameComponent'{id="", kind=""},
- #'CosNaming_NameComponent'{id="id3", kind="kind3"}],
- String3 = "id1.kind1/./id3.kind3",
- Name4 = [#'CosNaming_NameComponent'{id="id1", kind="kind1"},
- #'CosNaming_NameComponent'{id="i.d.2", kind="kind2"},
- #'CosNaming_NameComponent'{id="id3", kind="kind3"}],
- String4 = "id1.kind1/i\\.d\\.2.kind2/id3.kind3",
- Name5 = [#'CosNaming_NameComponent'{id="id1", kind=""},
- #'CosNaming_NameComponent'{id="i/d/2", kind="kind2"},
- #'CosNaming_NameComponent'{id="id3", kind=""}],
- String5 = "id1/i\\/d\\/2.kind2/id3",
-
- BadString1 = "id1./id2/id3",
- BadString2 = "id1//id3",
-
- ?match(String1, 'CosNaming_NamingContextExt':to_string(NS, Name1)),
- ?match(String2, 'CosNaming_NamingContextExt':to_string(NS, Name2)),
- ?match(String3, 'CosNaming_NamingContextExt':to_string(NS, Name3)),
- ?match(String4, 'CosNaming_NamingContextExt':to_string(NS, Name4)),
- ?match(String5, 'CosNaming_NamingContextExt':to_string(NS, Name5)),
- ?match(Name1, 'CosNaming_NamingContextExt':to_name(NS, String1)),
- ?match(Name2, 'CosNaming_NamingContextExt':to_name(NS, String2)),
- ?match(Name3, 'CosNaming_NamingContextExt':to_name(NS, String3)),
- ?match(Name4, 'CosNaming_NamingContextExt':to_name(NS, String4)),
- ?match(Name5, 'CosNaming_NamingContextExt':to_name(NS, String5)),
-
- ?match({'EXCEPTION', {'CosNaming_NamingContext_InvalidName',_}},
- 'CosNaming_NamingContextExt':to_name(NS, BadString1)),
- ?match({'EXCEPTION', {'CosNaming_NamingContext_InvalidName',_}},
- 'CosNaming_NamingContextExt':to_name(NS, BadString2)),
-
- %% Create a test context.
- Tc = ?match({_,pseudo,_, _,_, _},
- 'CosNaming_NamingContext':bind_new_context(NS,
- [#'CosNaming_NameComponent'{id="testcontext",
- kind=""}])),
- ?match(ok, 'CosNaming_NamingContext':bind(Tc, [#'CosNaming_NameComponent'
- {id="hej",
- kind=""}], NS)),
-
- ?match(NS, 'CosNaming_NamingContextExt':resolve_str(Tc, "hej")),
-
- ?match("corbaloc:rir:", 'CosNaming_NamingContextExt':to_url(Tc, "rir:", "")),
- ?match("corbaname:rir:/NameService#org/erlang/",
- 'CosNaming_NamingContextExt':to_url(Tc, "rir:/NameService", "org/erlang/")),
- ?match("corbaloc::1.1@555%3cxyz.com:9999/Dev/NameService",
- 'CosNaming_NamingContextExt':to_url(Tc, ":1.1@555\\<xyz.com:9999/Dev/NameService", "")),
-
- %% Bad port
- ?match({'EXCEPTION', {'CosNaming_NamingContextExt_InvalidAddress',_}},
- 'CosNaming_NamingContextExt':to_url(Tc, ":[email protected]:99a9/", "")),
- %% BAd IIOP-version
- ?match({'EXCEPTION', {'CosNaming_NamingContextExt_InvalidAddress',_}},
- 'CosNaming_NamingContextExt':to_url(Tc, ":[email protected]:99a9/", "")),
- %% Bad IIOP-version
- ?match({'EXCEPTION', {'CosNaming_NamingContextExt_InvalidAddress',_}},
- 'CosNaming_NamingContextExt':to_url(Tc, ":@555xyz.com:99a9/", "")),
- %% Bad protocol
- ?match({'EXCEPTION', {'CosNaming_NamingContextExt_InvalidAddress',_}},
- 'CosNaming_NamingContextExt':to_url(Tc, "iop:@555xyz.com:99a9/", "")),
- %% Unsupported protocol
- ?match({'EXCEPTION', {'CosNaming_NamingContextExt_InvalidAddress',_}},
- 'CosNaming_NamingContextExt':to_url(Tc, "atm:@555xyz.com:9999/", "")),
- %% Bad Name
- ?match({'EXCEPTION', {'CosNaming_NamingContext_InvalidName',_}},
- 'CosNaming_NamingContextExt':to_url(Tc, ":555xyz.com:9999/", "id1./id2.kind2")),
-
- ok.
-
-
diff --git a/lib/orber/test/orber.cover b/lib/orber/test/orber.cover
deleted file mode 100644
index 807a7c2c6e..0000000000
--- a/lib/orber/test/orber.cover
+++ /dev/null
@@ -1,2 +0,0 @@
-{incl_app,orber,details}.
-
diff --git a/lib/orber/test/orber.spec b/lib/orber/test/orber.spec
deleted file mode 100644
index 0dd30deade..0000000000
--- a/lib/orber/test/orber.spec
+++ /dev/null
@@ -1 +0,0 @@
-{suites,"../orber_test",all}.
diff --git a/lib/orber/test/orber_SUITE.erl b/lib/orber/test/orber_SUITE.erl
deleted file mode 100644
index 75da31bc5f..0000000000
--- a/lib/orber/test/orber_SUITE.erl
+++ /dev/null
@@ -1,213 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(orber_SUITE).
--include_lib("common_test/include/ct.hrl").
-
--define(default_timeout, test_server:minutes(15)).
--define(application, orber).
-
-% Test server specific exports
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
--export([init_per_testcase/2, end_per_testcase/2]).
-
-% Test cases must be exported.
--export([app_test/1, undefined_functions/1, install_load_order/1,
- install_local_content/1,
- otp_9887/1]).
-
-%% Exporting error handler callbacks for use in otp_9887
--export([init/1, handle_event/2]).
-
-%%
-%% all/1
-%%
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [app_test, undefined_functions, install_load_order,
- install_local_content,
- otp_9887].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) ->
- Dog=proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-%
-% Test cases starts here.
-%
-app_test(_Config) ->
- ok=test_server:app_test(orber),
- ok.
-
-otp_9887(_Config) ->
- orber:jump_stop(),
- application:set_env(orber, orber_debug_level, 10),
- orber:jump_start([]),
-
- mnesia:create_table(orber_light_ifr, []),
-
- error_logger:add_report_handler(?MODULE,[self()]),
- catch orber_ifr:get_module(foo, bar),
-
- receive
- {stolen,Reason} ->
- {error,_Pid1, {_Pid2, _ErrorString, ArgumentList}} = Reason,
- 5 = length(ArgumentList)
- after 500 ->
- test_server:fail("OTP_9887 TIMED OUT")
- end,
-
- orber:jump_stop(),
- ok.
-
-%% Install Orber using the load_order option.
-install_load_order(_Config) ->
- orber:jump_stop(),
- case catch install_load_order2() of
- ok ->
- orber:jump_stop();
- What ->
- orber:jump_stop(),
- exit(What)
- end.
-
-install_load_order2() ->
- application:load(orber),
- mnesia:start(),
- corba:orb_init([{iiop_port, 0}]),
- orber:install([node()], [{ifr_storage_type, ram_copies},
- {load_order, 10}]),
- orber:start(),
- [H|_] = orber:get_tables(),
- 10 = mnesia:table_info(H, load_order),
- ok.
-
-%% Install Orber using the local_content option.
-install_local_content(_Config) ->
- orber:jump_stop(),
- case catch install_local_content2() of
- ok ->
- orber:jump_stop();
- What ->
- orber:jump_stop(),
- exit(What)
- end.
-
-install_local_content2() ->
- application:load(orber),
- mnesia:start(),
- corba:orb_init([{iiop_port, 0}]),
- orber:install([node()], [{ifr_storage_type, ram_copies},
- {local_content, true}]),
- orber:start(),
- [H|_] = orber:get_tables(),
- true = mnesia:table_info(H, local_content),
- ok.
-
-
-
-%% Check for undefined functions
-undefined_functions(_Config) ->
- App = orber,
- Root = code:root_dir(),
- LibDir = code:lib_dir(App),
- EbinDir = filename:join([LibDir,"ebin"]),
- AppFilePath = filename:join([LibDir,"ebin", "orber.app"]),
- {ok, [{application,orber,AppFile}]} = file:consult(AppFilePath),
- io:format("Using ~p~n~p~n", [AppFilePath, AppFile]),
- Mods = key1search(modules, AppFile),
- XRefTestName = undef_funcs_make_name(App, xref_test_name),
- {ok, XRef} = xref:start(XRefTestName),
- ok = xref:set_default(XRef,
- [{verbose,false},{warnings,false}]),
- XRefName = undef_funcs_make_name(App, xref_name),
- {ok, XRefName} = xref:add_release(XRef, Root, {name,XRefName}),
- {ok, App} = xref:replace_application(XRef, App, EbinDir),
- {ok, Undefs} = xref:analyze(XRef, undefined_function_calls),
- xref:stop(XRef),
- analyze_undefined_function_calls(Undefs, Mods, []).
-
-analyze_undefined_function_calls([], _, []) ->
- ok;
-analyze_undefined_function_calls([], _, AppUndefs) ->
- exit({suite_failed, {undefined_function_calls, AppUndefs}});
-analyze_undefined_function_calls([{{Mod, _F, _A}, _C} = AppUndef|Undefs],
- AppModules, AppUndefs) ->
- %% Check that this module is our's
- case lists:member(Mod,AppModules) of
- true ->
- {Calling,Called} = AppUndef,
- {Mod1,Func1,Ar1} = Calling,
- {Mod2,Func2,Ar2} = Called,
- io:format("undefined function call: "
- "~n ~w:~w/~w calls ~w:~w/~w~n",
- [Mod1,Func1,Ar1,Mod2,Func2,Ar2]),
- analyze_undefined_function_calls(Undefs, AppModules,
- [AppUndef|AppUndefs]);
- false ->
- io:format("dropping ~p~n", [Mod]),
- analyze_undefined_function_calls(Undefs, AppModules, AppUndefs)
- end.
-
-%% This function is used simply to avoid cut-and-paste errors later...
-undef_funcs_make_name(App, PostFix) ->
- list_to_atom(atom_to_list(App) ++ "_" ++ atom_to_list(PostFix)).
-
-key1search(Key, L) ->
- case lists:keysearch(Key, 1, L) of
- false ->
- fail({not_found, Key, L});
- {value, {Key, Value}} ->
- Value
- end.
-
-fail(Reason) ->
- exit({suite_failed, Reason}).
-
-%% Error handler
-
-init([Proc]) -> {ok,Proc}.
-
-handle_event(Event, Proc) ->
- Proc ! {stolen,Event},
- {ok,Proc}.
diff --git a/lib/orber/test/orber_acl_SUITE.erl b/lib/orber/test/orber_acl_SUITE.erl
deleted file mode 100644
index 2b0a48adc9..0000000000
--- a/lib/orber/test/orber_acl_SUITE.erl
+++ /dev/null
@@ -1,299 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%%
-%% Description:
-%% Test suite for the ACL functions
-%%
-%%-----------------------------------------------------------------
--module(orber_acl_SUITE).
-
--include_lib("common_test/include/ct.hrl").
-
--define(default_timeout, test_server:minutes(5)).
-
--define(match(ExpectedRes,Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~nRESULT: ~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [ipv4_verify, ipv4_range, ipv4_interfaces, ipv4_bm,
- ipv6_verify, ipv6_range, ipv6_interfaces, ipv6_bm].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_suite(Config) ->
- if
- is_list(Config) ->
- Config;
- true ->
- exit("Config not a list")
- end.
-
-end_per_suite(Config) ->
- Config.
-
-
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case
-%% Description: Testing IPv4 Verify Operation
-%%-----------------------------------------------------------------
-ipv4_verify(_) ->
- ?match(true, orber_acl:verify("192.168.64.148", "192.168.64.0/17", inet)),
- ?match({false,"192.168.128.0","192.168.255.255"},
- orber_acl:verify("192.168.64.148", "192.168.255.0/17", inet)),
- ?match(true, orber_acl:verify("192.168.255.148", "192.168.128.0/17", inet)),
- ?match(true, orber_acl:verify("192.168.128.148", "192.168.128.0/17", inet)),
- ?match(true, orber_acl:verify("192.168.255.255", "192.168.128.0/16", inet)),
- ?match({false,"192.168.0.0","192.168.255.255"},
- orber_acl:verify("192.169.255.255", "192.168.128.0/16", inet)),
- ?match(true, orber_acl:verify("192.168.128.255", "192.168.128.0/24", inet)),
- ?match({false,"192.168.128.0","192.168.128.255"},
- orber_acl:verify("192.168.255.255", "192.168.128.0/24", inet)),
- ?match({false,"192.168.128.0","192.168.128.127"},
- orber_acl:verify("192.168.128.255", "192.168.128.0/25", inet)),
- ?match(true, orber_acl:verify("192.168.128.255", "192.168.128.128/25", inet)),
- ?match(true, orber_acl:verify("192.168.128.128", "192.168.128.128/32", inet)),
- ?match({false,"192.168.128.128.","192.168.128.128."},
- orber_acl:verify("192.168.128.255", "192.168.128.128/32", inet)),
- ?match(true, orber_acl:verify("192.168.128.128", "192.168.128.128", inet)),
- ?match({false,"192.168.128.128.","192.168.128.128."},
- orber_acl:verify("192.168.128.255", "192.168.128.128", inet)),
- ?match(true, orber_acl:verify("192.168.128.255", "192.168.128.128/7", inet)),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case :
-%% Description: Testing IPv4 Range Operation
-%%-----------------------------------------------------------------
-ipv4_range(_) ->
- ?match({ok,"192.168.0.0", "192.168.127.255"},
- orber_acl:range("192.168.64.0/17")),
- ?match({ok, "192.168.128.0", "192.168.255.255"},
- orber_acl:range("192.168.255.0/17")),
- ?match({ok,"192.168.128.0","192.168.255.255"},
- orber_acl:range("192.168.128.0/17")),
- ?match({ok,"192.168.0.0","192.168.255.255"},
- orber_acl:range("192.168.128.0/16")),
- ?match({ok,"192.168.128.0","192.168.128.255"},
- orber_acl:range("192.168.128.0/24")),
- ?match({ok,"192.168.128.0","192.168.128.127"},
- orber_acl:range("192.168.128.0/25")),
- ?match({ok,"192.168.128.128","192.168.128.255"},
- orber_acl:range("192.168.128.128/25")),
- ?match({ok,"192.168.128.128.","192.168.128.128."},
- orber_acl:range("192.168.128.128/32")),
- ?match({ok,"192.168.128.128.","192.168.128.128."},
- orber_acl:range("192.168.128.128")),
- ?match({ok,"192.0.0.0","193.255.255.255"},
- orber_acl:range("192.168.128.128/7")),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case :
-%% Description: Testing IPv4 Interfaces Operation
-%%-----------------------------------------------------------------
-ipv4_interfaces(_) ->
- ?match({ok, _},
- orber_acl:init_acl([{tcp_in, "192.168.128.0/18", ["10.1.1.1"]},
- {tcp_in, "192.167.64.0/18#4001/5001", ["10.1.1.2"]},
- {tcp_in, "192.166.192.0/18"}], inet)),
- {ok, IPTuple1} = ?match({ok, _}, inet:getaddr("192.168.128.0", inet)),
- ?match({true, ["10.1.1.1"], 0}, orber_acl:match(IPTuple1, tcp_in, true)),
- ?match({false, [], 0}, orber_acl:match(IPTuple1, tcp_out, true)),
- {ok, IPTuple2} = ?match({ok, _}, inet:getaddr("192.167.64.0", inet)),
- ?match({true, ["10.1.1.2"], {4001,5001}}, orber_acl:match(IPTuple2, tcp_in, true)),
- ?match({false, [], 0}, orber_acl:match(IPTuple2, tcp_out, true)),
- {ok, IPTuple3} = ?match({ok, _}, inet:getaddr("192.166.192.0", inet)),
- ?match({true, [], 0}, orber_acl:match(IPTuple3, tcp_in, true)),
- ?match(false, orber_acl:match(IPTuple3, tcp_out)),
- ?match(ok, orber_acl:clear_acl()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case :
-%% Description: Benchmarking runtime critical IPv4 Operations
-%%-----------------------------------------------------------------
-ipv4_bm(_) ->
- ?match({ok, _, _, _}, bm2([{tcp_in, "192.168.64.0/17"}], inet, "192.168.64.148")),
- ok.
-%%-----------------------------------------------------------------
-%% Test Case :
-%% Description: Testing IPv6 Verify Operation
-%%-----------------------------------------------------------------
-ipv6_verify(_) ->
- case orber_test_lib:version_ok() of
- true ->
- ?match(true, orber_acl:verify("2002:C0A8:0:0:0:0:0:0", "2002:C0A8::/48", inet6)),
- ?match(true, orber_acl:verify("2002:C0A8:0:FFFF:FFFF:FFFF:FFFF:FFFF", "2002:C0A8::/48", inet6)),
- ?match({false,"2002:C0A8:0:0:0:0:0:0", "2002:C0A8:0:FFFF:FFFF:FFFF:FFFF:FFFF"},
- orber_acl:verify("2002:C0A8:1:FFFF:FFFF:FFFF:FFFF:FFFF", "2002:C0A8::/48", inet6)),
- ?match(true, orber_acl:verify("2002:C0A8:1:FFFF:FFFF:FFFF:FFFF:FFFF", "2002:C0A8::/47", inet6)),
- ?match({false,"2002:C0A8:0:0:0:0:0:0", "2002:C0A8:1:FFFF:FFFF:FFFF:FFFF:FFFF"},
- orber_acl:verify("2002:C0A8:2:FFFF:FFFF:FFFF:FFFF:FFFF", "2002:C0A8::/47", inet6)),
- ok;
- Reason ->
- Reason
- end.
-
-%%-----------------------------------------------------------------
-%% Test Case :
-%% Description: Testing IPv6 Range Operation
-%%-----------------------------------------------------------------
-ipv6_range(_) ->
- case orber_test_lib:version_ok() of
- true ->
- ?match({ok,"2002:C0A8:0:0:0:0:0:0", "2002:C0A8:0:FFFF:FFFF:FFFF:FFFF:FFFF"},
- orber_acl:range("2002:C0A8::/48", inet6)),
- ?match({ok,"2002:C0A8:0:0:0:0:0:0", "2002:C0A8:1:FFFF:FFFF:FFFF:FFFF:FFFF"},
- orber_acl:range("2002:C0A8::/47", inet6)),
- ok;
- Reason ->
- Reason
- end.
-
-%%-----------------------------------------------------------------
-%% Test Case :
-%% Description: Testing IPv6 Interfaces Operation
-%%-----------------------------------------------------------------
-ipv6_interfaces(_) ->
- case orber_test_lib:version_ok() of
- true ->
- ?match({ok, _}, orber_acl:init_acl([{tcp_in, "2002:C0A8::/49", ["0:0:0:0:0:0:10.1.1.1"]}], inet6)),
- {ok, IPTuple1} = ?match({ok, _}, inet:getaddr("2002:C0A8:0:7FFF:FFFF:FFFF:FFFF:FFFF", inet6)),
- ?match({true, ["0:0:0:0:0:0:10.1.1.1"], 0}, orber_acl:match(IPTuple1, tcp_in, true)),
- ?match(false, orber_acl:match(IPTuple1, tcp_out)),
- ?match(ok, orber_acl:clear_acl()),
- ok;
- Reason ->
- Reason
- end.
-
-%%-----------------------------------------------------------------
-%% Test Case :
-%% Description: Benchmarking runtime critical IPv6 Operations
-%%-----------------------------------------------------------------
-ipv6_bm(_) ->
- case orber_test_lib:version_ok() of
- true ->
- ?match({ok, _, _, _}, bm2([{tcp_in, "2002:C0A8::/48"}], inet6, "2002:C0A8:0:0:0:0:0:0")),
- ok;
- Reason ->
- Reason
- end.
-
-%%-----------------------------------------------------------------
-%% Local Functions
-%%-----------------------------------------------------------------
--define(NO_OF_TIMES, 1000).
-
-bm2(Filters, Family, Ip) ->
- {ok, IPTuple} = inet:getaddr(Ip, Family),
- orber_acl:init_acl(Filters, Family),
- TimeBefore1 = erlang:timestamp(),
- bm_loop(IPTuple, ?NO_OF_TIMES),
- TimeAfter1 = erlang:timestamp(),
- orber_acl:clear_acl(),
- Time1 = computeTime(TimeBefore1, TimeAfter1),
- orber_acl:init_acl(Filters, Family),
- TimeBefore2 = erlang:timestamp(),
- bm_loop2(Ip, ?NO_OF_TIMES, Family),
- TimeAfter2 = erlang:timestamp(),
- orber_acl:clear_acl(),
- Time2 = computeTime(TimeBefore2, TimeAfter2),
- orber_acl:init_acl(Filters, Family),
- TimeBefore3 = erlang:timestamp(),
- bm_loop2(IPTuple, ?NO_OF_TIMES, Family),
- TimeAfter3 = erlang:timestamp(),
- orber_acl:clear_acl(),
- Time3 = computeTime(TimeBefore3, TimeAfter3),
- {ok, round(?NO_OF_TIMES/Time1), round(?NO_OF_TIMES/Time2), round(?NO_OF_TIMES/Time3)}.
-
-
-bm_loop(_Ip, 0) ->
- ok;
-bm_loop(Ip, N) ->
- true = orber_acl:match(Ip, tcp_in),
- bm_loop(Ip, N-1).
-
-bm_loop2(_Ip, 0, _Family) ->
- ok;
-bm_loop2(Ip, N, Family) ->
- {ok, IPTuple} = inet:getaddr(Ip, Family),
- true = orber_acl:match(IPTuple, tcp_in),
- bm_loop2(Ip, N-1, Family).
-
-computeTime({_MegaSecb, Secb, MicroSecb}, {_MegaSeca, Seca, MicroSeca}) ->
- (Seca - Secb) + ((MicroSeca - MicroSecb) / 1000000).
-
-
-%%-----------------------------------------------------------------
-%% END OF MODULE
-%%-----------------------------------------------------------------
diff --git a/lib/orber/test/orber_firewall_ipv4_in_SUITE.erl b/lib/orber/test/orber_firewall_ipv4_in_SUITE.erl
deleted file mode 100644
index 6d085d3bf5..0000000000
--- a/lib/orber/test/orber_firewall_ipv4_in_SUITE.erl
+++ /dev/null
@@ -1,284 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(orber_firewall_ipv4_in_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/src/ifr_objects.hrl").
--include("idl_output/orber_test_server.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming_NamingContextExt.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming_NamingContext.hrl").
-
--define(default_timeout, test_server:minutes(15)).
-
--define(match(ExpectedRes,Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~nRESULT: ~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, cases/0,
- init_per_suite/1, end_per_suite/1,
- init_per_testcase/2, end_per_testcase/2,
- deny_port_api/1, deny_port_range_api/1, deny_host_api/1,
- deny_peerhost_api/1, allow_port_range_api/1,
- allow_host_api/1, allow_peerhost_api/1, check_address_api/1]).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% NOTE - the fragment test cases must bu first since we explicitly set a request
-%% id. Otherwise, the request-id counter would be increased and we cannot know
-%% what it is.
-cases() ->
- [deny_port_api, deny_port_range_api, deny_host_api,
- deny_peerhost_api, allow_port_range_api, allow_host_api,
- allow_peerhost_api, check_address_api].
-
-
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) ->
- if
- is_list(Config) ->
- orber:jump_start([{iiop_port, 0},
- {iiop_out_ports, {5980, 6000}}]),
- Config;
- true ->
- exit("Config not a list")
- end.
-
-end_per_suite(Config) ->
- orber:jump_stop(),
- Config.
-
-%%-----------------------------------------------------------------
-%% Incomming connections - Deny
-%%-----------------------------------------------------------------
-%% Deny Access due to invalid local port
-deny_port_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_USE_ACL_INCOMING},
- {iiop_acl, [{tcp_in, IP++"/32#7000"}]}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match({'EXCEPTION', #'CosNaming_NamingContextExt_InvalidAddress'{}},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-%% Deny Access due to invalid local port range
-deny_port_range_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_USE_ACL_INCOMING},
- {iiop_acl, [{tcp_in, IP++"/32#7000/8000"}]}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match({'EXCEPTION', #'CosNaming_NamingContextExt_InvalidAddress'{}},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-
-%% Deny Access due to invalid host
-deny_host_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_USE_ACL_INCOMING},
- {iiop_acl, [{tcp_in, "123.123.123.123/32"}]}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match({'EXCEPTION', #'CosNaming_NamingContextExt_InvalidAddress'{}},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-%% Deny Access due to invalid peerhost
-deny_peerhost_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_USE_ACL_INCOMING},
- {iiop_acl, [{tcp_in, IP++"/32", ["123.123.123.123"]}]}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match({'EXCEPTION', #'CosNaming_NamingContextExt_InvalidAddress'{}},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-%%-----------------------------------------------------------------
-%% Incomming connections - Allow
-%%-----------------------------------------------------------------
-%% Allow Access due to valid local port range
-allow_port_range_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_USE_ACL_INCOMING},
- {iiop_acl, [{tcp_in, IP++"/32#5980/6000"}]}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- IOR =
- ?match({'IOP_IOR',_,_},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match(false, corba_object:not_existent(IOR)),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-
-%% Allow Access due to valid host
-allow_host_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_USE_ACL_INCOMING},
- {iiop_acl, [{tcp_in, IP++"/32"}]}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- IOR =
- ?match({'IOP_IOR',_,_},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match(false, corba_object:not_existent(IOR)),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-%% Allow Access due to valid peerhost
-allow_peerhost_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_USE_ACL_INCOMING},
- {iiop_acl, [{tcp_in, IP++"/32", [IP]}]}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- IOR =
- ?match({'IOP_IOR',_,_},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService",
- [#'IOP_ServiceContext'
- {context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface, IP}}])),
- ?match(false, corba_object:not_existent(IOR,
- [#'IOP_ServiceContext'
- {context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface, IP}}])),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test corbaloc strings
-%%-----------------------------------------------------------------
-check_address_api(_Config) ->
- ?match({[[iiop,{1,0},"10.0.0.1",2809]],"NameService"},
- orber_cosnaming_utils:addresses(":10.0.0.1/NameService")),
- ?match({[[iiop,{1,0},"10.0.0.1",2809]],[]},
- orber_cosnaming_utils:addresses(":10.0.0.1")),
- ?match({[[iiop,{1,2},"10.0.0.1",2809]],"NameService"},
- orber_cosnaming_utils:addresses(":[email protected]/NameService")),
- ?match({[[iiop,{1,0},"10.0.0.1",4001]],"NameService"},
- orber_cosnaming_utils:addresses(":10.0.0.1:4001/NameService")),
- ?match({[[iiop,{1,1},"10.0.0.1",4001]],"NameService"},
- orber_cosnaming_utils:addresses(":[email protected]:4001/NameService")),
- ?match({[[iiop,{1,1},"10.0.0.1",4001]],[]},
- orber_cosnaming_utils:addresses(":[email protected]:4001")),
- ?match({[[iiop,{1,1},"10.0.0.1",4001]],[]},
- orber_cosnaming_utils:addresses("iiop:[email protected]:4001")),
- ?match({[[iiop,{1,1},"10.0.0.1",4001]],[]},
- orber_cosnaming_utils:addresses("iiop:[email protected]:4001/")),
-
- ?match({[[iiop,{1,1},"myhost",4001]],[]},
- orber_cosnaming_utils:addresses("iiop:1.1@myhost:4001")),
- ?match({[[iiop,{1,1},"myhost.full.name",4001]],"NameService"},
- orber_cosnaming_utils:addresses("iiop:[email protected]:4001/NameService")),
- ?match({[[iiop,{1,1},"myhost",4001],
- [iiop,{1,1},"myhost.full.name",2809]],"NameService"},
- orber_cosnaming_utils:addresses("iiop:1.1@myhost:4001,iiop:[email protected]/NameService")),
-
- ?match({[[iiop,{1,1},"123.12.23.2",4001],
- [iiop,{1,1},"10.0.0.1",4001]], "NameService"},
- orber_cosnaming_utils:addresses(":[email protected]:4001,:[email protected]:4001/NameService")),
- ?match({[[iiop,{1,1},"123.12.23.2",4001],
- [iiop,{1,1},"10.0.0.1",4001]], []},
- orber_cosnaming_utils:addresses(":[email protected]:4001,:[email protected]:4001")),
- ?match({[[iiop,{1,0},"123.12.23.2",4001],
- [iiop,{1,1},"10.0.0.1",4001]], "NameService"},
- orber_cosnaming_utils:addresses(":123.12.23.2:4001,:[email protected]:4001/NameService")),
- ?match({[[iiop,{1,1},"123.12.23.2",4001],
- [iiop,{1,0},"10.0.0.1",4001]], "NameService"},
- orber_cosnaming_utils:addresses(":[email protected]:4001,:10.0.0.1:4001/NameService")),
- ?match({[[iiop,{1,1},"123.12.23.2",2809],
- [iiop,{1,1},"10.0.0.1",4001]], "NameService"},
- orber_cosnaming_utils:addresses(":[email protected],:[email protected]:4001/NameService")),
- ?match({[[iiop,{1,1},"123.12.23.2",4001],
- [iiop,{1,1},"10.0.0.1",2809]], "NameService"},
- orber_cosnaming_utils:addresses(":[email protected]:4001,:[email protected]/NameService")),
- ?match({[[iiop,{1,0},"123.12.23.2",2809],
- [iiop,{1,0},"10.0.0.1",2809]], "NameService"},
- orber_cosnaming_utils:addresses(":123.12.23.2,:10.0.0.1/NameService")),
- ?match({[[iiop,{1,0},"123.12.23.2",2809],
- [iiop,{1,0},"10.0.0.1",2809]], []},
- orber_cosnaming_utils:addresses(":123.12.23.2,:10.0.0.1/")),
- ?match({[[iiop,{1,0},"123.12.23.2",2809],
- [iiop,{1,0},"10.0.0.1",2809]], []},
- orber_cosnaming_utils:addresses("iiop:123.12.23.2,:10.0.0.1/")),
-
- [IP] = ?match([_], orber:host()),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_USE_ACL_INCOMING},
- {iiop_acl, [{tcp_in, IP++"/32"}]}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match({'IOP_IOR',_,_},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
-
- ok.
-
diff --git a/lib/orber/test/orber_firewall_ipv4_out_SUITE.erl b/lib/orber/test/orber_firewall_ipv4_out_SUITE.erl
deleted file mode 100644
index e061d0410d..0000000000
--- a/lib/orber/test/orber_firewall_ipv4_out_SUITE.erl
+++ /dev/null
@@ -1,229 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(orber_firewall_ipv4_out_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/src/ifr_objects.hrl").
--include("idl_output/orber_test_server.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming_NamingContextExt.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming_NamingContext.hrl").
-
--define(default_timeout, test_server:minutes(15)).
-
--define(match(ExpectedRes,Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~nRESULT: ~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, cases/0,
- init_per_suite/1, end_per_suite/1,
- init_per_testcase/2, end_per_testcase/2,
- deny_port_api/1, deny_port_range_api/1, deny_host_api/1,
- allow_port_api/1, allow_port_range_api/1, allow_host_api/1,
- local_interface_api/1]).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% NOTE - the fragment test cases must bu first since we explicitly set a request
-%% id. Otherwise, the request-id counter would be increased and we cannot know
-%% what it is.
-cases() ->
- [deny_port_api, deny_port_range_api, deny_host_api,
- allow_port_api, allow_port_range_api, allow_host_api,
- local_interface_api].
-
-
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) ->
- if
- is_list(Config) ->
- orber:jump_start([{iiop_port, 0},
- {iiop_out_ports, {5980, 6000}}]),
- Config;
- true ->
- exit("Config not a list")
- end.
-
-end_per_suite(Config) ->
- orber:jump_stop(),
- Config.
-
-%%-----------------------------------------------------------------
-%% Incomming connections - Deny
-%%-----------------------------------------------------------------
-%% Deny Access due to invalid local port
-deny_port_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- ServerPort = orber:iiop_port(),
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_USE_ACL_OUTGOING},
- {iiop_acl, [{tcp_out, IP++"/32#" ++ integer_to_list(ServerPort+10)}]}])),
- ?match({'EXCEPTION', #'CosNaming_NamingContextExt_InvalidAddress'{}},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
- ["corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService"])),
-% catch orber_test_lib:destroy_node(ClientNode, timeout),
- ok.
-
-%% Deny Access due to invalid local port range
-deny_port_range_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- ServerPort = orber:iiop_port(),
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_USE_ACL_OUTGOING},
- {iiop_acl, [{tcp_out, IP++"/32#"++integer_to_list(ServerPort+100)++ "/" ++ integer_to_list(ServerPort+120)}]}])),
- ?match({'EXCEPTION', #'CosNaming_NamingContextExt_InvalidAddress'{}},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
- ["corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService"])),
-% catch orber_test_lib:destroy_node(ClientNode, timeout),
- ok.
-
-
-%% Deny Access due to invalid host
-deny_host_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_USE_ACL_OUTGOING},
- {iiop_acl, [{tcp_out, "123.123.123.123/32"}]}])),
- ServerPort = orber:iiop_port(),
- ?match({'EXCEPTION', #'CosNaming_NamingContextExt_InvalidAddress'{}},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
- ["corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService"])),
-% catch orber_test_lib:destroy_node(ClientNode, timeout),
- ok.
-
-%%-----------------------------------------------------------------
-%% Incomming connections - Allow
-%%-----------------------------------------------------------------
-%% Allow Access due to valid local port range
-allow_port_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- ServerPort = orber:iiop_port(),
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_USE_ACL_OUTGOING},
- {iiop_acl, [{tcp_out, IP++"/32#"++integer_to_list(ServerPort)}]}])),
- IOR =
- ?match({'IOP_IOR',_,_},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
- ["corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService"])),
- ?match(false,
- orber_test_lib:remote_apply(ClientNode, corba_object, not_existent, [IOR])),
-% catch orber_test_lib:destroy_node(ClientNode, timeout),
- ok.
-
-%% Allow Access due to valid local port range
-allow_port_range_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- ServerPort = orber:iiop_port(),
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_USE_ACL_OUTGOING},
- {iiop_acl, [{tcp_out, IP++"/32#" ++ integer_to_list(ServerPort-10) ++ "/" ++ integer_to_list(ServerPort+10)}]}])),
- IOR =
- ?match({'IOP_IOR',_,_},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
- ["corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService"])),
- ?match(false,
- orber_test_lib:remote_apply(ClientNode, corba_object, not_existent, [IOR])),
-% catch orber_test_lib:destroy_node(ClientNode, timeout),
- ok.
-
-
-%% Allow Access due to valid host
-allow_host_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_USE_ACL_OUTGOING},
- {iiop_acl, [{tcp_out, IP++"/32"}]}])),
- ServerPort = orber:iiop_port(),
- IOR =
- ?match({'IOP_IOR',_,_},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
- ["corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService"])),
- ?match(false,
- orber_test_lib:remote_apply(ClientNode, corba_object, not_existent, [IOR])),
-% catch orber_test_lib:destroy_node(ClientNode, timeout),
- ok.
-
-%% Allow Access due to valid host via a spcific interface
-local_interface_api(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{iiop_port, 0},
- {iiop_out_ports, {5980, 6000}},
- {ip_address, IP}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
-
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_USE_ACL_OUTGOING},
- {iiop_acl, [{tcp_out, IP, [Loopback]}]}])),
- IOR =
- ?match({'IOP_IOR',_,_},
- orber_test_lib:remote_apply(ClientNode, corba, string_to_object,
- ["corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService"])),
- ?match(false,
- orber_test_lib:remote_apply(ClientNode, corba_object, not_existent, [IOR])),
-% catch orber_test_lib:destroy_node(ClientNode, timeout),
- ok.
-
diff --git a/lib/orber/test/orber_firewall_ipv6_in_SUITE.erl b/lib/orber/test/orber_firewall_ipv6_in_SUITE.erl
deleted file mode 100644
index ee879f5ea8..0000000000
--- a/lib/orber/test/orber_firewall_ipv6_in_SUITE.erl
+++ /dev/null
@@ -1,315 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(orber_firewall_ipv6_in_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/src/ifr_objects.hrl").
--include("idl_output/orber_test_server.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming_NamingContextExt.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming_NamingContext.hrl").
-
--define(default_timeout, test_server:minutes(15)).
-
--define(match(ExpectedRes,Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~nRESULT: ~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, cases/0,
- init_per_suite/1, end_per_suite/1,
- init_per_testcase/2, end_per_testcase/2,
- deny_port_api/1, deny_port_range_api/1, deny_host_api/1,
- deny_peerhost_api/1, allow_port_range_api/1,
- allow_host_api/1, allow_peerhost_api/1, check_address_api/1]).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% NOTE - the fragment test cases must bu first since we explicitly set a request
-%% id. Otherwise, the request-id counter would be increased and we cannot know
-%% what it is.
-cases() ->
- [deny_port_api, deny_port_range_api, deny_host_api,
- deny_peerhost_api, allow_port_range_api, allow_host_api,
- allow_peerhost_api, check_address_api].
-
-
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- orber:jump_start([{iiop_port, 0},
- {iiop_out_ports, {5980, 6000}},
- {flags, ?ORB_ENV_USE_IPV6}]),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- orber:jump_stop(),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) ->
- case orber_test_lib:version_ok() of
- true ->
- if
- is_list(Config) ->
- Config;
- true ->
- exit("Config not a list")
- end;
- Reason ->
- Reason
- end.
-
-end_per_suite(Config) ->
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Incomming connections - Deny
-%%-----------------------------------------------------------------
-%% Deny Access due to invalid local port
-deny_port_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, (?ORB_ENV_USE_IPV6 bor
- ?ORB_ENV_USE_ACL_INCOMING)},
- {iiop_acl, [{tcp_in, IP++"/128#7000"}]}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match({'EXCEPTION', #'CosNaming_NamingContextExt_InvalidAddress'{}},
- corba:string_to_object("corbaloc::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService")),
- % catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-%% Deny Access due to invalid local port range
-deny_port_range_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, (?ORB_ENV_USE_IPV6 bor
- ?ORB_ENV_USE_ACL_INCOMING)},
- {iiop_acl, [{tcp_in, IP++"/128#7000/8000"}]}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match({'EXCEPTION', #'CosNaming_NamingContextExt_InvalidAddress'{}},
- corba:string_to_object("corbaloc::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService")),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-
-%% Deny Access due to invalid host
-deny_host_api(_Config) ->
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, (?ORB_ENV_USE_IPV6 bor
- ?ORB_ENV_USE_ACL_INCOMING)},
- {iiop_acl, [{tcp_in, "0:0:0:0:0:0:10.1.1.1/128"}]}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match({'EXCEPTION', #'CosNaming_NamingContextExt_InvalidAddress'{}},
- corba:string_to_object("corbaloc::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService")),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-%% Deny Access due to invalid peer host
-deny_peerhost_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_},
- orber_test_lib:js_node([{flags, (?ORB_ENV_USE_IPV6 bor
- ?ORB_ENV_USE_ACL_INCOMING)},
- {iiop_acl, [{tcp_in, IP++"/128", ["0:0:0:0:0:0:10.1.1.1"]}]}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match({'EXCEPTION', #'CosNaming_NamingContextExt_InvalidAddress'{}},
- corba:string_to_object("corbaloc::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService")),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-%%-----------------------------------------------------------------
-%% Incomming connections - Allow
-%%-----------------------------------------------------------------
-%% Allow Access due to valid local port range
-allow_port_range_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, (?ORB_ENV_USE_IPV6 bor
- ?ORB_ENV_USE_ACL_INCOMING)},
- {iiop_acl, [{tcp_in, IP++"/128#5980/6000"}]}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- io:format("ServerNode: ~p\nServerHost: ~p\n", [ServerNode, ServerHost]),
- IOR =
- ?match({'IOP_IOR',_,_},
- corba:string_to_object("corbaloc::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match(false, corba_object:not_existent(IOR)),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-
-%% Allow Access due to valid host
-allow_host_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, (?ORB_ENV_USE_IPV6 bor
- ?ORB_ENV_USE_ACL_INCOMING)},
- {iiop_acl, [{tcp_in, IP++"/128"}]}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- IOR =
- ?match({'IOP_IOR',_,_},
- corba:string_to_object("corbaloc::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match(false, corba_object:not_existent(IOR)),
-
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-%% Allow Access due to valid host
-allow_peerhost_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, (?ORB_ENV_USE_IPV6 bor
- ?ORB_ENV_USE_ACL_INCOMING)},
- {iiop_acl, [{tcp_in, IP++"/128", [IP]}]}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- IOR =
- ?match({'IOP_IOR',_,_},
- corba:string_to_object("corbaloc::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService",
- [#'IOP_ServiceContext'
- {context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface, IP}}])),
- ?match(false, corba_object:not_existent(IOR,
- [#'IOP_ServiceContext'
- {context_id=?ORBER_GENERIC_CTX_ID,
- context_data = {interface, IP}}])),
-
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test corbaloc strings
-%%-----------------------------------------------------------------
-check_address_api(_Config) ->
- ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:C02A:2A2A",2809]],"NameService"},
- orber_cosnaming_utils:addresses(":[0:0:0:0:0:FFFF:C02A:2A2A]/NameService")),
- ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:C02A:2A2A",2809]],[]},
- orber_cosnaming_utils:addresses(":[0:0:0:0:0:FFFF:C02A:2A2A]")),
- ?match({[[iiop,{1,2},"0:0:0:0:0:FFFF:C02A:2A2A",2809]],"NameService"},
- orber_cosnaming_utils:addresses(":1.2@[0:0:0:0:0:FFFF:C02A:2A2A]/NameService")),
- ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:C02A:2A2A",4001]],"NameService"},
- orber_cosnaming_utils:addresses(":[0:0:0:0:0:FFFF:C02A:2A2A]:4001/NameService")),
- ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:C02A:2A2A",4001]],"NameService"},
- orber_cosnaming_utils:addresses(":1.1@[0:0:0:0:0:FFFF:C02A:2A2A]:4001/NameService")),
- ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:C02A:2A2A",4001]],[]},
- orber_cosnaming_utils:addresses(":1.1@[0:0:0:0:0:FFFF:C02A:2A2A]:4001")),
- ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:C02A:2A2A",4001]],[]},
- orber_cosnaming_utils:addresses("iiop:1.1@[0:0:0:0:0:FFFF:C02A:2A2A]:4001")),
-
- ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:10.11.11.11",2809]],"NameService"},
- orber_cosnaming_utils:addresses(":[0:0:0:0:0:FFFF:10.11.11.11]/NameService")),
- ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:10.11.11.11",2809]],[]},
- orber_cosnaming_utils:addresses(":[0:0:0:0:0:FFFF:10.11.11.11]")),
- ?match({[[iiop,{1,2},"0:0:0:0:0:FFFF:10.11.11.11",2809]],"NameService"},
- orber_cosnaming_utils:addresses(":1.2@[0:0:0:0:0:FFFF:10.11.11.11]/NameService")),
- ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:10.11.11.11",4001]],"NameService"},
- orber_cosnaming_utils:addresses(":[0:0:0:0:0:FFFF:10.11.11.11]:4001/NameService")),
- ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:10.11.11.11",4001]],"NameService"},
- orber_cosnaming_utils:addresses(":1.1@[0:0:0:0:0:FFFF:10.11.11.11]:4001/NameService")),
- ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:10.11.11.11",4001]],[]},
- orber_cosnaming_utils:addresses(":1.1@[0:0:0:0:0:FFFF:10.11.11.11]:4001/")),
- ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:10.11.11.11",4001]],[]},
- orber_cosnaming_utils:addresses("iiop:1.1@[0:0:0:0:0:FFFF:10.11.11.11]:4001/")),
-
- ?match({[[iiop,{1,1},"myhost",4001]],[]},
- orber_cosnaming_utils:addresses("iiop:1.1@myhost:4001")),
- ?match({[[iiop,{1,1},"myhost.full.name",4001]],"NameService"},
- orber_cosnaming_utils:addresses("iiop:[email protected]:4001/NameService")),
- ?match({[[iiop,{1,1},"myhost",4001],
- [iiop,{1,1},"myhost.full.name",2809]],"NameService"},
- orber_cosnaming_utils:addresses("iiop:1.1@myhost:4001,iiop:[email protected]/NameService")),
-
- ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:10.11.11.11",4001],
- [iiop,{1,1},"0:0:0:0:0:FFFF:C02A:2A2A",4001]], "NameService"},
- orber_cosnaming_utils:addresses(":1.1@[0:0:0:0:0:FFFF:10.11.11.11]:4001,:1.1@[0:0:0:0:0:FFFF:C02A:2A2A]:4001/NameService")),
- ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:10.11.11.11",4001],
- [iiop,{1,1},"0:0:0:0:0:FFFF:C02A:2A2A",4001]], []},
- orber_cosnaming_utils:addresses(":1.1@[0:0:0:0:0:FFFF:10.11.11.11]:4001,:1.1@[0:0:0:0:0:FFFF:C02A:2A2A]:4001")),
- ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:10.11.11.11",4001],
- [iiop,{1,1},"0:0:0:0:0:FFFF:C02A:2A2A",4001]], "NameService"},
- orber_cosnaming_utils:addresses(":[0:0:0:0:0:FFFF:10.11.11.11]:4001,:1.1@[0:0:0:0:0:FFFF:C02A:2A2A]:4001/NameService")),
- ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:10.11.11.11",4001],
- [iiop,{1,0},"0:0:0:0:0:FFFF:C02A:2A2A",4001]], "NameService"},
- orber_cosnaming_utils:addresses(":1.1@[0:0:0:0:0:FFFF:10.11.11.11]:4001,:[0:0:0:0:0:FFFF:C02A:2A2A]:4001/NameService")),
- ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:10.11.11.11",2809],
- [iiop,{1,1},"0:0:0:0:0:FFFF:C02A:2A2A",4001]], "NameService"},
- orber_cosnaming_utils:addresses(":1.1@[0:0:0:0:0:FFFF:10.11.11.11],:1.1@[0:0:0:0:0:FFFF:C02A:2A2A]:4001/NameService")),
- ?match({[[iiop,{1,1},"0:0:0:0:0:FFFF:10.11.11.11",4001],
- [iiop,{1,1},"0:0:0:0:0:FFFF:C02A:2A2A",2809]], "NameService"},
- orber_cosnaming_utils:addresses(":1.1@[0:0:0:0:0:FFFF:10.11.11.11]:4001,:1.1@[0:0:0:0:0:FFFF:C02A:2A2A]/NameService")),
- ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:10.11.11.11",2809],
- [iiop,{1,0},"0:0:0:0:0:FFFF:C02A:2A2A",2809]], "NameService"},
- orber_cosnaming_utils:addresses(":[0:0:0:0:0:FFFF:10.11.11.11],:[0:0:0:0:0:FFFF:C02A:2A2A]/NameService")),
- ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:10.11.11.11",2809],
- [iiop,{1,0},"0:0:0:0:0:FFFF:C02A:2A2A",2809]], []},
- orber_cosnaming_utils:addresses(":[0:0:0:0:0:FFFF:10.11.11.11],:[0:0:0:0:0:FFFF:C02A:2A2A]/")),
- ?match({[[iiop,{1,0},"0:0:0:0:0:FFFF:10.11.11.11",2809],
- [iiop,{1,0},"0:0:0:0:0:FFFF:C02A:2A2A",2809]], []},
- orber_cosnaming_utils:addresses("iiop:[0:0:0:0:0:FFFF:10.11.11.11],:[0:0:0:0:0:FFFF:C02A:2A2A]/")),
-
- [IP] = ?match([_], orber:host()),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, (?ORB_ENV_USE_IPV6 bor
- ?ORB_ENV_USE_ACL_INCOMING)},
- {iiop_acl, [{tcp_in, IP++"/128"}]}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- ?match({'IOP_IOR',_,_},
- corba:string_to_object("corbaloc::1.2@["++IP++"]:"++integer_to_list(ServerPort)++"/NameService")),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-
diff --git a/lib/orber/test/orber_firewall_ipv6_out_SUITE.erl b/lib/orber/test/orber_firewall_ipv6_out_SUITE.erl
deleted file mode 100644
index 0fe305aeb5..0000000000
--- a/lib/orber/test/orber_firewall_ipv6_out_SUITE.erl
+++ /dev/null
@@ -1,236 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(orber_firewall_ipv6_out_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/src/ifr_objects.hrl").
--include("idl_output/orber_test_server.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming_NamingContextExt.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming_NamingContext.hrl").
-
--define(default_timeout, test_server:minutes(15)).
-
--define(match(ExpectedRes,Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~nRESULT: ~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, cases/0,
- init_per_suite/1, end_per_suite/1,
- init_per_testcase/2, end_per_testcase/2,
- deny_port_api/1, deny_port_range_api/1, deny_host_api/1,
- allow_port_api/1, allow_port_range_api/1, allow_host_api/1,
- local_interface_api/1]).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% NOTE - the fragment test cases must bu first since we explicitly set a request
-%% id. Otherwise, the request-id counter would be increased and we cannot know
-%% what it is.
-cases() ->
- [deny_port_api, deny_port_range_api, deny_host_api,
- allow_port_api, allow_port_range_api, allow_host_api,
- local_interface_api].
-
-
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- orber:jump_start([{iiop_port, 0},
- {iiop_out_ports, {5980, 6000}},
- {flags, ?ORB_ENV_USE_IPV6}]),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- orber:jump_stop(),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) ->
- case orber_test_lib:version_ok() of
- true ->
- if
- is_list(Config) ->
- Config;
- true ->
- exit("Config not a list")
- end;
- Reason ->
- Reason
- end.
-
-end_per_suite(Config) ->
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Incomming connections - Deny
-%%-----------------------------------------------------------------
-%% Deny Access due to invalid local port
-deny_port_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- ServerPort = orber:iiop_port(),
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, (?ORB_ENV_USE_IPV6 bor
- ?ORB_ENV_USE_ACL_OUTGOING)},
- {iiop_acl, [{tcp_out, IP++"/128#" ++ integer_to_list(ServerPort+10)}]}])),
- ?match({'EXCEPTION', #'CosNaming_NamingContextExt_InvalidAddress'{}},
- orber_test_lib:remote_apply(ServerNode, corba, string_to_object,
- ["corbaloc::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService"])),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-%% Deny Access due to invalid local port range
-deny_port_range_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- ServerPort = orber:iiop_port(),
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, (?ORB_ENV_USE_IPV6 bor
- ?ORB_ENV_USE_ACL_OUTGOING)},
- {iiop_acl, [{tcp_out, IP++"/128#"++integer_to_list(ServerPort+100)++ "/" ++ integer_to_list(ServerPort+120)}]}])),
- ?match({'EXCEPTION', #'CosNaming_NamingContextExt_InvalidAddress'{}},
- orber_test_lib:remote_apply(ServerNode, corba, string_to_object,
- ["corbaloc::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService"])),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-
-%% Deny Access due to invalid host
-deny_host_api(_Config) ->
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, (?ORB_ENV_USE_IPV6 bor
- ?ORB_ENV_USE_ACL_OUTGOING)},
- {iiop_acl, [{tcp_out, "0:0:0:0:0:0:10.1.1.1/128"}]}])),
- ServerPort = orber:iiop_port(),
- ?match({'EXCEPTION', #'CosNaming_NamingContextExt_InvalidAddress'{}},
- orber_test_lib:remote_apply(ServerNode, corba, string_to_object,
- ["corbaloc::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService"])),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-%%-----------------------------------------------------------------
-%% Incomming connections - Allow
-%%-----------------------------------------------------------------
-%% Allow Access due to valid local port
-allow_port_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- ServerPort = orber:iiop_port(),
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, (?ORB_ENV_USE_IPV6 bor
- ?ORB_ENV_USE_ACL_OUTGOING)},
- {iiop_acl, [{tcp_out, IP++"/128#" ++ integer_to_list(ServerPort)}]}])),
- IOR =
- ?match({'IOP_IOR',_,_},
- orber_test_lib:remote_apply(ServerNode, corba, string_to_object,
- ["corbaloc::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService"])),
- ?match(false,
- orber_test_lib:remote_apply(ServerNode, corba_object, not_existent, [IOR])),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-%% Allow Access due to valid local port range
-allow_port_range_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- ServerPort = orber:iiop_port(),
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, (?ORB_ENV_USE_IPV6 bor
- ?ORB_ENV_USE_ACL_OUTGOING)},
- {iiop_acl, [{tcp_out, IP++"/128#" ++ integer_to_list(ServerPort-10) ++ "/" ++ integer_to_list(ServerPort+10)}]}])),
- IOR =
- ?match({'IOP_IOR',_,_},
- orber_test_lib:remote_apply(ServerNode, corba, string_to_object,
- ["corbaloc::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService"])),
- ?match(false,
- orber_test_lib:remote_apply(ServerNode, corba_object, not_existent, [IOR])),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-
-%% Allow Access due to valid host
-allow_host_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, (?ORB_ENV_USE_IPV6 bor
- ?ORB_ENV_USE_ACL_OUTGOING)},
- {iiop_acl, [{tcp_out, IP}]}])),
- ServerPort = orber:iiop_port(),
- IOR =
- ?match({'IOP_IOR',_,_},
- orber_test_lib:remote_apply(ServerNode, corba, string_to_object,
- ["corbaloc::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService"])),
- ?match(false,
- orber_test_lib:remote_apply(ServerNode, corba_object, not_existent, [IOR])),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
-%% Allow Access due to valid host via a spcific interface
-local_interface_api(_Config) ->
- [IP] = ?match([_], orber:host()),
- {ok, ServerNode, ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, (?ORB_ENV_USE_IPV6 bor
- ?ORB_ENV_USE_ACL_OUTGOING)},
- {iiop_acl, [{tcp_out, IP, [IP]}]}])),
- ServerPort = orber:iiop_port(),
- IOR =
- ?match({'IOP_IOR',_,_},
- orber_test_lib:remote_apply(ServerNode, corba, string_to_object,
- ["corbaloc::1.2@"++ServerHost++":"++integer_to_list(ServerPort)++"/NameService"])),
- ?match(false,
- orber_test_lib:remote_apply(ServerNode, corba_object, not_existent, [IOR])),
-% catch orber_test_lib:destroy_node(ServerNode, timeout),
- ok.
-
diff --git a/lib/orber/test/orber_nat_SUITE.erl b/lib/orber/test/orber_nat_SUITE.erl
deleted file mode 100644
index 029a5e529b..0000000000
--- a/lib/orber/test/orber_nat_SUITE.erl
+++ /dev/null
@@ -1,364 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(orber_nat_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include_lib("orber/src/ifr_objects.hrl").
--include("idl_output/orber_test_server.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming_NamingContextExt.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming_NamingContext.hrl").
-
-
--define(default_timeout, test_server:minutes(15)).
-
--define(match(ExpectedRes,Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~nRESULT: ~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, cases/0,
- init_per_suite/1, end_per_suite/1,
- init_per_testcase/2, end_per_testcase/2,
- nat_ip_address/1, nat_ip_address_multiple/1,
- nat_ip_address_local/1, nat_ip_address_local_local/1,
- nat_iiop_port/1, nat_iiop_port_local/1,
- nat_iiop_port_local_local/1,
- nat_iiop_ssl_port/1, nat_iiop_ssl_port_local/1]).
-
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- cases().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-cases() ->
- [nat_ip_address,
- nat_ip_address_multiple,
- nat_ip_address_local,
- nat_iiop_port,
- nat_iiop_port_local,
- nat_ip_address_local_local,
- nat_iiop_port_local_local,
- nat_iiop_ssl_port,
- nat_iiop_ssl_port_local].
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_testcase(TC, Config)
- when TC =:= nat_iiop_ssl_port;
- TC =:= nat_iiop_ssl_port_local ->
- case proplists:get_value(crypto_started, Config) of
- true ->
- case orber_test_lib:ssl_version() of
- no_ssl ->
- {skip,"SSL not installed!"};
- _ ->
- init_per_testcase(dummy_tc, Config)
- end;
- false ->
- {skip, "Crypto did not start"}
- end;
-init_per_testcase(_Case, Config) ->
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- Dog=test_server:timetrap(?default_timeout),
- orber:jump_start([{iiop_port, 0},
- {flags, 0}]),
- oe_orber_test_server:oe_register(),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- oe_orber_test_server:oe_unregister(),
- orber:jump_stop(),
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-init_per_suite(Config) ->
- if
- is_list(Config) ->
- try crypto:start() of
- ok ->
- [{crypto_started, true} | Config]
- catch _:_ ->
- [{crypto_started, false} | Config]
- end;
- true ->
- exit("Config not a list")
- end.
-
-end_per_suite(Config) ->
- application:stop(crypto),
- Config.
-
-%%-----------------------------------------------------------------
-%% API tests for NAT
-%%-----------------------------------------------------------------
-%% These case test if the server ORB use the correct
-%% interface when exporting IOR:s
-nat_ip_address(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_ENABLE_NAT},
- {nat_ip_address, Loopback}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- IOR = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {Loopback, ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
- iop_ior:get_key(IOR)),
- ok.
-
-nat_ip_address_multiple(_Config) ->
- IP = orber_test_lib:get_host(),
-
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_ENABLE_NAT},
- {nat_ip_address, {multiple, ["10.0.0.1"]}}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- IOR = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {"10.0.0.1", ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
- iop_ior:get_key(IOR)),
- ok.
-
-nat_ip_address_local(_Config) ->
- IP = orber_test_lib:get_host(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_ENABLE_NAT},
- {nat_ip_address, {local, "10.0.0.1", [{IP, "127.0.0.1"}]}}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- IOR = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {"10.0.0.1", ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
- iop_ior:get_key(IOR)),
- ok.
-
-nat_ip_address_local_local(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags,
- (?ORB_ENV_LOCAL_INTERFACE bor
- ?ORB_ENV_ENABLE_NAT)},
- {nat_ip_address, {local, "10.0.0.1", [{IP, "10.0.0.2"}]}}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- IOR1 = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {"10.0.0.2", ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
- iop_ior:get_key(IOR1)),
- IOR2 = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaloc::1.2@"++Loopback++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {"10.0.0.1", ServerPort, _ObjectKey, _Counter, _TP, _NewHD}},
- iop_ior:get_key(IOR2)),
- ok.
-
-nat_iiop_port(_Config) ->
- IP = orber_test_lib:get_host(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_ENABLE_NAT},
- {nat_iiop_port, 42}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- IOR = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {_IP, 42, _ObjectKey, _Counter, _TP, _NewHD}},
- iop_ior:get_key(IOR)),
- ok.
-
-nat_iiop_port_local(_Config) ->
- IP = orber_test_lib:get_host(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags, ?ORB_ENV_ENABLE_NAT},
- {nat_iiop_port, {local, 42, [{4001, 43}]}}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- IOR = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {_IP, 42, _ObjectKey, _Counter, _TP, _NewHD}},
- iop_ior:get_key(IOR)),
- ok.
-
-nat_iiop_port_local_local(_Config) ->
- IP = orber_test_lib:get_host(),
- Loopback = orber_test_lib:get_loopback_interface(),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node([{flags,
- (?ORB_ENV_LOCAL_INTERFACE bor
- ?ORB_ENV_ENABLE_NAT)},
- {ip_address, IP}])),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- orber_test_lib:remote_apply(ServerNode, orber_env, configure_override, [nat_iiop_port, {local, 42, [{ServerPort, 43}]}]),
- IOR1 = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaloc::1.2@"++IP++":"++integer_to_list(ServerPort)++"/NameService")),
- ?match({'external', {IP, 43, _ObjectKey, _Counter, _TP, _NewHD}},
- iop_ior:get_key(IOR1)),
- {ok, Ref} = ?match({ok, _},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
- [Loopback, normal, 10088])),
- IOR2 = ?match(#'IOP_IOR'{},
- corba:string_to_object("corbaloc::1.2@"++Loopback++":10088/NameService")),
- ?match({'external', {IP, 42, _ObjectKey, _Counter, _TP, _NewHD}},
- iop_ior:get_key(IOR2)),
- ?match(ok,
- orber_test_lib:remote_apply(ServerNode, orber,
- remove_listen_interface, [Ref])),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% API tests for ORB to ORB, ssl security depth 1
-%%-----------------------------------------------------------------
-%% SECURE MULTI ORB API tests (SSL depth 1)
-%% Make sure NAT works for SSL
-nat_iiop_ssl_port(_Config) ->
-
- IP = orber_test_lib:get_host(),
- ServerOptions = orber_test_lib:get_options(iiop_ssl, server,
- 1, [{iiop_ssl_port, 0},
- {flags, ?ORB_ENV_ENABLE_NAT},
- {ip_address, IP}]),
- ClientOptions = orber_test_lib:get_options(iiop_ssl, client,
- 1, [{iiop_ssl_port, 0}]),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node(ServerOptions)),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- SSLServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_ssl_port, []),
- NATSSLServerPort = SSLServerPort+1,
- {ok, Ref} = ?match({ok, _},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
- [IP, ssl, NATSSLServerPort])),
- orber_test_lib:remote_apply(ServerNode, orber_env, configure_override,
- [nat_iiop_ssl_port,
- {local, NATSSLServerPort, [{4001, 43}]}]),
-
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node(ClientOptions)),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
- [ssl])),
-
- IOR1 = ?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba,
- string_to_object,
- ["corbaname::1.2@"++IP++":"++
- integer_to_list(ServerPort)++"/NameService#mamba"])),
-
- ?match({'external', {_IP, _Port, _ObjectKey, _Counter, _TP,
- #host_data{protocol = ssl,
- ssl_data = #'SSLIOP_SSL'{port = NATSSLServerPort}}}},
- iop_ior:get_key(IOR1)),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- uninstall_test_data,
- [ssl])),
- ?match(ok,
- orber_test_lib:remote_apply(ServerNode, orber,
- remove_listen_interface, [Ref])),
- ok.
-
-nat_iiop_ssl_port_local(_Config) ->
-
- IP = orber_test_lib:get_host(),
- ServerOptions = orber_test_lib:get_options(iiop_ssl, server,
- 1, [{iiop_ssl_port, 0},
- {flags,
- (?ORB_ENV_LOCAL_INTERFACE bor
- ?ORB_ENV_ENABLE_NAT)},
- {ip_address, IP}]),
- ClientOptions = orber_test_lib:get_options(iiop_ssl, client,
- 1, [{iiop_ssl_port, 0}]),
- {ok, ServerNode, _ServerHost} =
- ?match({ok,_,_}, orber_test_lib:js_node(ServerOptions)),
- ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_port, []),
- SSLServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_ssl_port, []),
- NATSSLServerPort = SSLServerPort+1,
- {ok, Ref} = ?match({ok, _},
- orber_test_lib:remote_apply(ServerNode, orber,
- add_listen_interface,
- [IP, ssl, NATSSLServerPort])),
- orber_test_lib:remote_apply(ServerNode, orber_env, configure_override,
- [nat_iiop_ssl_port,
- {local, NATSSLServerPort, [{NATSSLServerPort, NATSSLServerPort}]}]),
-
- {ok, ClientNode, _ClientHost} =
- ?match({ok,_,_}, orber_test_lib:js_node(ClientOptions)),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- install_test_data,
- [ssl])),
-
- IOR1 = ?match(#'IOP_IOR'{},
- orber_test_lib:remote_apply(ClientNode, corba,
- string_to_object,
- ["corbaname::1.2@"++IP++":"++
- integer_to_list(ServerPort)++"/NameService#mamba"])),
-
- ?match({'external', {_IP, _Port, _ObjectKey, _Counter, _TP,
- #host_data{protocol = ssl,
- ssl_data = #'SSLIOP_SSL'{port = NATSSLServerPort}}}},
- iop_ior:get_key(IOR1)),
- ?match(ok, orber_test_lib:remote_apply(ServerNode, orber_test_lib,
- uninstall_test_data,
- [ssl])),
- ?match(ok,
- orber_test_lib:remote_apply(ServerNode, orber,
- remove_listen_interface, [Ref])),
- ok.
-
diff --git a/lib/orber/test/orber_test.idl b/lib/orber/test/orber_test.idl
deleted file mode 100644
index 852daabedf..0000000000
--- a/lib/orber/test/orber_test.idl
+++ /dev/null
@@ -1,96 +0,0 @@
-//
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1997-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-//
-module Module
-{
-
- enum Enum {horse, pig, cow};
-
- struct Struct0 {
- long l;
- short s;
- char c;
- };
-
- struct Struct1 {
- string s;
- unsigned short us;
- unsigned long ul;
- };
-
- struct Struct2 {
- sequence <long> long_sequence;
- Enum e;
- octet o;
- };
-
- struct HEADER {
- short EID;
- short NDW;
- short SSID;
- };
-
- enum Enum1 {orange,banana, apple};
-
- union Union switch (short) {
- case 0: short First;
- case 1: string Second;
- case 2: char Third;
- };
-
- union Union1 switch (Enum){
- case horse: short horse;
- case pig: sequence <string> Second;
- case cow: Enum1 Third;
- };
-
- union Union2 switch (Enum){
- case horse: long a[10];
- case pig: Union u;
- case cow: Union1 u1;
- };
-
- exception Except1 {
- string why;
- sequence <string> rest_of_name;
- };
-
- exception Except2 {
- Enum1 e;
- Struct2 s;
- };
-
- exception Except3 {
- Union1 u;
- unsigned short s;
- Object o ;
- };
-
- exception Except4 {};
-
- interface I1 {
- void a();
- };
-
- interface I2 {
- void a();
- };
-
-};
-
diff --git a/lib/orber/test/orber_test_lib.erl b/lib/orber/test/orber_test_lib.erl
deleted file mode 100644
index 9b19c4bc4e..0000000000
--- a/lib/orber/test/orber_test_lib.erl
+++ /dev/null
@@ -1,1564 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(orber_test_lib).
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/include/ifr_types.hrl").
--include_lib("orber/src/orber_iiop.hrl").
--include("idl_output/orber_test_server.hrl").
--include_lib("orber/COSS/CosNaming/CosNaming.hrl").
-
--define(match(ExpectedRes,Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~nRESULT: ~p~n",
- [AcTuAlReS]),
- ?line exit(AcTuAlReS)
- end
- end()).
-
--export([js_node/2,
- js_node/1,
- js_node/0,
- slave_sup/0,
- remote_apply/4,
- install_test_data/1,
- light_tests/3,
- uninstall_test_data/1,
- destroy_node/2,
- lookup/2,
- alternate_iiop_address/2,
- create_alternate_iiop_address/2,
- alternate_ssl_iiop_address/3,
- create_alternate_ssl_iiop_address/3,
- test_coding/1,
- test_coding/2,
- corba_object_tests/2,
- timeouts/3,
- precond/3,
- postcond/4,
- oe_get_interface/0,
- create_components_IOR/1,
- get_options_old/2,
- get_options_old/3,
- get_options_old/4,
- get_options/2,
- get_options/3,
- get_options/4,
- version_ok/0,
- ssl_version/0,
- get_loopback_interface/0,
- get_loopback_interface/1,
- get_host/0,
- get_host/1]).
-
-%% Interceptor functions.
--export([new_out_connection/3,
- new_in_connection/3,
- closed_in_connection/1,
- closed_out_connection/1,
- in_request_encoded/6,
- in_reply_encoded/6,
- out_reply_encoded/6,
- out_request_encoded/6,
- in_request/6,
- in_reply/6,
- out_reply/6,
- out_request/6]).
-
-%%------------------------------------------------------------
-%% function : ssl_version
-%% Arguments:
-%% Returns : integer()
-%% Effect :
-%%
-%%------------------------------------------------------------
-ssl_version() ->
- try
- ssl:module_info(),
- case catch erlang:system_info(otp_release) of
- Version when is_list(Version) ->
- if
- "R12B" < Version ->
- 3;
- true ->
- 2
- end;
- _ ->
- 2
- end
- catch error:undef ->
- no_ssl
- end.
-
-%%------------------------------------------------------------
-%% function : version_ok
-%% Arguments:
-%% Returns : true | {skipped, Reason}
-%% Effect :
-%%
-%%------------------------------------------------------------
-version_ok() ->
- {ok, Hostname} = inet:gethostname(),
- case inet:getaddr(Hostname, inet6) of
- {error,nxdomain} ->
- {skipped, "Inet cannot handle IPv6"};
- _ ->
- case inet:getaddr("0:0:0:0:0:FFFF:127.0.0.1", inet6) of
- {error,nxdomain} ->
- {skipped, "Inet cannot handle IPv6"};
- _ ->
- case gen_tcp:listen(0, [{reuseaddr, true}, inet6]) of
- {ok, LSock} ->
- {ok, Port} = inet:port(LSock),
- case gen_tcp:connect(Hostname, Port, [inet6]) of
- {error, _} ->
- gen_tcp:close(LSock),
- {skipped, "Inet cannot handle IPv6"};
- {ok, Socket} ->
- gen_tcp:close(Socket),
- gen_tcp:close(LSock),
- true
- end;
- {error, _} ->
- {skipped, "Inet cannot handle IPv6"}
- end
- end
- end.
-
-%%------------------------------------------------------------
-%% function : get_host
-%% Arguments: Family - inet | inet6
-%% Returns : string()
-%% Effect :
-%%
-%%------------------------------------------------------------
-get_host() ->
- get_host(inet).
-get_host(Family) ->
- case os:type() of
- {win32, _} ->
- case os:version() of
- {6, _, _} when Family == inet ->
- "127.0.0.1";
- {6, _, _} ->
- "0:0:0:0:0:0:0:0001";
- _ ->
- [IP] = ?match([_], orber:host()),
- IP
- end;
- _ ->
- [IP] = ?match([_], orber:host()),
- IP
- end.
-
-%%------------------------------------------------------------
-%% function : get_loopback_interface
-%% Arguments: Family - inet | inet6
-%% Returns : string()
-%% Effect :
-%%
-%%------------------------------------------------------------
-get_loopback_interface() ->
- get_loopback_interface(inet).
-get_loopback_interface(Family) ->
- case os:type() of
- {win32, _} ->
- case os:version() of
- {6, _, _} when Family == inet ->
- "127.0.0.2";
- {6, _, _} ->
- "0:0:0:0:0:0:0:0002";
- _ when Family == inet ->
- "127.0.0.1";
- _ ->
- "0:0:0:0:0:0:0:0001"
- end;
- _ when Family == inet ->
- "127.0.0.1";
- _ ->
- "0:0:0:0:0:0:0:0001"
- end.
-
-%%------------------------------------------------------------
-%% function : js_node/4
-%% Arguments: Port - which iiop_port (integer())
-%% InitOptions - [{Key, Value}]
-%% {Type, StartOptions} - {lightweight, [{Key, Value}]}
-%% Returns : {ok, Node} | {error, _}
-%% Effect : Starts a new slave-node with given (optinally)
-%% extra arguments. If fails it retries 'Retries' times.
-%%------------------------------------------------------------
-js_node() ->
- js_node([], []).
-
-js_node(InitOptions) when is_list(InitOptions) ->
- js_node(InitOptions, []).
-
-js_node(InitOptions, StartOptions) when is_list(InitOptions) ->
- {A,B,C} = erlang:timestamp(),
- [_, Host] = string:tokens(atom_to_list(node()), [$@]),
- _NewInitOptions = check_options(InitOptions),
- js_node_helper(Host, 0, lists:concat([A,'_',B,'_',C]),
- InitOptions, 10, StartOptions).
-
-js_node_helper(Host, Port, Name, Options, Retries, StartOptions) ->
- case starter(Host, Name, create_paths()) of
- {ok, NewNode} ->
- case net_adm:ping(NewNode) of
- pong ->
- start_ssl(lists:member({secure, ssl}, Options), NewNode),
- {ok, Cwd} = file:get_cwd(),
- Path = code:get_path(),
- ok = rpc:call(NewNode, file, set_cwd, [Cwd]),
- true = rpc:call(NewNode, code, set_path, [Path]),
- rpc:call(NewNode, application, load, [orber]),
- ok = rpc:call(NewNode, corba, orb_init,
- [[{iiop_port, Port},
- {orber_debug_level, 10}|Options]]),
- start_orber(StartOptions, NewNode),
- spawn_link(NewNode, ?MODULE, slave_sup, []),
- rpc:multicall([node() | nodes()], global, sync, []),
- ok = rpc:call(NewNode, orber, info, [io]),
- {ok, NewNode, Host};
- _ ->
- {error, "net_adm:ping(Node) failed"}
- end;
- {error, Reason} when Retries == 0 ->
- {error, Reason};
- {error, Reason} ->
- io:format("Could not start slavenode ~p:~p due to: ~p~n",
- [Host, Port, Reason]),
- timer:sleep(500),
- js_node_helper(Host, Port, Name, Options, Retries-1, StartOptions)
- end.
-
-check_options(Options) ->
- case {os:type(), os:version()} of
- {{win32, _}, {6, _, _}} ->
- %% Vista, need to run additional checks.
- case {orber_tb:keysearch(ip_address, Options),
- orber_tb:keysearch(flags, Options, 0)} of
- {undefined, Flags} ->
- case ?ORB_FLAG_TEST(Flags, ?ORB_ENV_USE_IPV6) of
- true ->
- [{ip_address, get_host(inet6)}|Options];
- false ->
- [{ip_address, get_host(inet)}|Options]
- end;
- _ ->
- Options
- end;
- _ ->
- Options
- end.
-
-starter(Host, Name, Args) ->
- io:format("slave:start_link(~p,~p,~p).~n",[Host,Name,Args]),
- slave:start_link(Host, Name, Args).
-
-slave_sup() ->
- process_flag(trap_exit, true),
- receive
- {'EXIT', _, _} -> ignore
- end.
-
-start_ssl(true, Node) ->
- rpc:call(Node, ssl, start, []),
- rpc:call(Node, crypto, start, []);
-start_ssl(_, _) ->
- ok.
-
-start_orber({lightweight, Options}, Node) ->
- ok = rpc:call(Node, mnesia, start, []),
- ok = rpc:call(Node, orber, start_lightweight, [Options]);
-start_orber(lightweight, Node) ->
- ok = rpc:call(Node, mnesia, start, []),
- ok = rpc:call(Node, orber, start_lightweight, []);
-start_orber(_, Node) ->
- ok = rpc:call(Node, orber, jump_start, []).
-
-%%-----------------------------------------------------------------
-%% Type - ssl | iiop_ssl
-%% Role - 'server' | 'client'
-%% Options - [{Key, Value}]
-%%-----------------------------------------------------------------
-get_options_old(Type, Role) ->
- get_options_old(Type, Role, 2, []).
-
-get_options_old(ssl, Role, Level) ->
- get_options_old(ssl, Role, Level, []).
-
-get_options_old(ssl, Role, 2, Options) ->
- Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
- [{depth, 2},
- {verify, 2},
- {keyfile, filename:join([Dir, Role, "key.pem"])},
- {cacertfile, filename:join([Dir, Role, "cacerts.pem"])},
- {certfile, filename:join([Dir, Role, "cert.pem"])} |Options];
-get_options_old(iiop_ssl, _Role, 2, Options) ->
- Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
- [{ssl_server_depth, 2},
- {ssl_server_verify, 2},
- {ssl_server_certfile, filename:join([Dir, "server", "cert.pem"])},
- {ssl_server_cacertfile, filename:join([Dir, "server", "cacerts.pem"])},
- {ssl_server_keyfile, filename:join([Dir, "server", "key.pem"])},
- {ssl_client_depth, 2},
- {ssl_client_verify, 2},
- {ssl_client_certfile, filename:join([Dir, "client", "cert.pem"])},
- {ssl_client_cacertfile, filename:join([Dir, "client", "cacerts.pem"])},
- {ssl_client_keyfile, filename:join([Dir, "client", "key.pem"])},
- {secure, ssl} |Options];
-get_options_old(iiop_ssl, _Role, 1, Options) ->
- Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
- [{ssl_server_depth, 1},
- {ssl_server_verify, 0},
- {ssl_server_certfile, filename:join([Dir, "server", "cert.pem"])},
- {ssl_server_cacertfile, filename:join([Dir, "server", "cacerts.pem"])},
- {ssl_server_keyfile, filename:join([Dir, "server", "key.pem"])},
- {ssl_client_depth, 1},
- {ssl_client_verify, 0},
- {ssl_client_certfile, filename:join([Dir, "client", "cert.pem"])},
- {ssl_client_cacertfile, filename:join([Dir, "client", "cacerts.pem"])},
- {ssl_client_keyfile, filename:join([Dir, "client", "key.pem"])},
- {secure, ssl} |Options].
-
-get_options(Type, Role) ->
- get_options(Type, Role, 2, []).
-
-get_options(ssl, Role, Level) ->
- get_options(ssl, Role, Level, []).
-
-get_options(ssl, Role, 2, Options) ->
- Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
- Options1 = [{depth, 2},
- {verify, 2},
- {keyfile, filename:join([Dir, Role, "key.pem"])},
- {cacertfile, filename:join([Dir, Role, "cacerts.pem"])},
- {certfile, filename:join([Dir, Role, "cert.pem"])} |Options],
- case Role of
- client ->
- [{server_name_indication, disable} |Options1];
- server ->
- Options1
- end;
-get_options(iiop_ssl, _Role, 2, Options) ->
- Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
- [{ssl_server_options, [{depth, 2},
- {verify, 2},
- {certfile, filename:join([Dir, "server", "cert.pem"])},
- {cacertfile, filename:join([Dir, "server", "cacerts.pem"])},
- {keyfile, filename:join([Dir, "server", "key.pem"])}]},
- {ssl_client_options, [{depth, 2},
- {verify, 2},
- {server_name_indication, disable},
- {certfile, filename:join([Dir, "client", "cert.pem"])},
- {cacertfile, filename:join([Dir, "client", "cacerts.pem"])},
- {keyfile, filename:join([Dir, "client", "key.pem"])}]},
- {secure, ssl} |Options];
-get_options(iiop_ssl, _Role, 1, Options) ->
- Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
- [{ssl_server_options, [{depth, 1},
- {verify, 0},
- {certfile, filename:join([Dir, "server", "cert.pem"])},
- {cacertfile, filename:join([Dir, "server", "cacerts.pem"])},
- {keyfile, filename:join([Dir, "server", "key.pem"])}]},
- {ssl_client_options, [{depth, 1},
- {verify, 0},
- {server_name_indication, disable},
- {certfile, filename:join([Dir, "client", "cert.pem"])},
- {cacertfile, filename:join([Dir, "client", "cacerts.pem"])},
- {keyfile, filename:join([Dir, "client", "key.pem"])}]},
- {secure, ssl} |Options].
-
-create_paths() ->
- Path = filename:dirname(code:which(?MODULE)),
- " -pa " ++ Path ++ " -pa " ++
- filename:join(Path, "idl_output") ++
- " -pa " ++
- filename:join(Path, "all_SUITE_data") ++
- " -pa \"" ++
- filename:dirname(code:which(orber))++"\"".
-
-%%------------------------------------------------------------
-%% function : destroy_node
-%% Arguments: Node - which node to destroy.
-%% Type - normal | ssl
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-
-destroy_node(Node, Type) ->
- stopper(Node, Type).
-
-stopper(Node, _Type) ->
- slave:stop(Node).
-
-
-%%------------------------------------------------------------
-%% function : remote_apply
-%% Arguments: N - Node, M - Module,
-%% F - Function, A - Arguments (list)
-%% Returns :
-%% Effect :
-%%------------------------------------------------------------
-remote_apply(N, M,F,A) ->
- case rpc:call(N, M, F, A) of
- {badrpc, Reason} ->
- exit(Reason);
- Other ->
- Other
- end.
-
-
-
-%%------------------------------------------------------------
-%% function : install_test_data
-%% Arguments: WhichSuite
-%% Returns : ok
-%% Effect : Installs test data associated with 'WhichSuite'
-%%------------------------------------------------------------
-
-install_test_data(nameservice) ->
- oe_orber_test_server:oe_register(),
- Mamba = orber_test_server:oe_create([], [{regname, {local, mamba}}]),
- true = corba:add_initial_service("Mamba", Mamba),
- NS = corba:resolve_initial_references("NameService"),
- NC1 = lname_component:set_id(lname_component:create(), "mamba"),
- N = lname:insert_component(lname:create(), 1, NC1),
- 'CosNaming_NamingContext':bind(NS, N,Mamba);
-
-install_test_data({nameservice, AltAddr, AltPort}) ->
- oe_orber_test_server:oe_register(),
- Obj = orber_test_server:oe_create([], [{regname, {local, mamba}}]),
- Mamba = corba:add_alternate_iiop_address(Obj, AltAddr, AltPort),
- true = corba:add_initial_service("Mamba", Mamba),
- NS = corba:resolve_initial_references("NameService"),
- NC1 = lname_component:set_id(lname_component:create(), "mamba"),
- N = lname:insert_component(lname:create(), 1, NC1),
- 'CosNaming_NamingContext':bind(NS, N,Mamba);
-
-install_test_data(timeout) ->
- oe_orber_test_server:oe_register(),
- Mamba = orber_test_server:oe_create([], {local, mamba}),
- Viper = orber_test_timeout_server:oe_create([], {local, viper}),
- NS = corba:resolve_initial_references("NameService"),
- NC1 = lname_component:set_id(lname_component:create(), "mamba"),
- N1 = lname:insert_component(lname:create(), 1, NC1),
- NC2 = lname_component:set_id(lname_component:create(), "viper"),
- N2 = lname:insert_component(lname:create(), 1, NC2),
- 'CosNaming_NamingContext':bind(NS, N1, Mamba),
- 'CosNaming_NamingContext':bind(NS, N2, Viper);
-
-install_test_data(pseudo) ->
- oe_orber_test_server:oe_register(),
- Mamba = orber_test_server:oe_create([], [{pseudo,true}]),
- NS = corba:resolve_initial_references("NameService"),
- NC1 = lname_component:set_id(lname_component:create(), "mamba"),
- N = lname:insert_component(lname:create(), 1, NC1),
- 'CosNaming_NamingContext':bind(NS, N,Mamba);
-
-install_test_data(ssl) ->
- oe_orber_test_server:oe_register(),
- Mamba = orber_test_server:oe_create([], [{regname, {local, mamba}}]),
- NS = corba:resolve_initial_references("NameService"),
- NC1 = lname_component:set_id(lname_component:create(), "mamba"),
- N = lname:insert_component(lname:create(), 1, NC1),
- 'CosNaming_NamingContext':bind(NS, N,Mamba);
-
-install_test_data(ssl_simple) ->
- oe_orber_test_server:oe_register();
-
-install_test_data(light) ->
- %% Nothing to do at the moment but we might in the future
- ok;
-
-install_test_data(_) ->
- {error, "no_implement"}.
-
-
-%%------------------------------------------------------------
-%% function : uninstall_test_data
-%% Arguments: WhichSuite
-%% Returns : ok
-%% Effect : Uninstalls test data associated with 'WhichSuite'
-%%------------------------------------------------------------
-
-uninstall_test_data(pseudo) ->
- NS = corba:resolve_initial_references("NameService"),
- NC1 = lname_component:set_id(lname_component:create(), "mamba"),
- N = lname:insert_component(lname:create(), 1, NC1),
- _Obj = (catch 'CosNaming_NamingContext':resolve(NS, N)),
- catch 'CosNaming_NamingContext':destroy(NS),
- oe_orber_test_server:oe_unregister();
-
-uninstall_test_data(timeout) ->
- NS = corba:resolve_initial_references("NameService"),
- NC1 = lname_component:set_id(lname_component:create(), "mamba"),
- N1 = lname:insert_component(lname:create(), 1, NC1),
-
- NC2 = lname_component:set_id(lname_component:create(), "viper"),
- N2 = lname:insert_component(lname:create(), 1, NC2),
- Mamba = (catch 'CosNaming_NamingContext':resolve(NS, N1)),
- Viper = (catch 'CosNaming_NamingContext':resolve(NS, N2)),
- catch corba:dispose(Mamba),
- catch corba:dispose(Viper),
- catch 'CosNaming_NamingContext':destroy(NS),
- oe_orber_test_server:oe_unregister();
-
-uninstall_test_data(nameservice) ->
- true = corba:remove_initial_service("Mamba"),
- NS = corba:resolve_initial_references("NameService"),
- NC1 = lname_component:set_id(lname_component:create(), "mamba"),
- N = lname:insert_component(lname:create(), 1, NC1),
- Obj = (catch 'CosNaming_NamingContext':resolve(NS, N)),
- catch corba:dispose(Obj),
- catch 'CosNaming_NamingContext':destroy(NS),
- oe_orber_test_server:oe_unregister();
-
-uninstall_test_data(ssl) ->
- NS = corba:resolve_initial_references("NameService"),
- NC1 = lname_component:set_id(lname_component:create(), "mamba"),
- N = lname:insert_component(lname:create(), 1, NC1),
- Obj = (catch 'CosNaming_NamingContext':resolve(NS, N)),
- catch corba:dispose(Obj),
- catch 'CosNaming_NamingContext':destroy(NS),
- oe_orber_test_server:oe_unregister();
-
-uninstall_test_data(ssl_simple) ->
- oe_orber_test_server:oe_unregister();
-
-uninstall_test_data(light) ->
- %% Nothing to do at the moment but we might in the future
- ok;
-
-uninstall_test_data(_) ->
- {error, "no_implement"}.
-
-%%------------------------------------------------------------
-%% function : corba_object_tests
-%% Arguments: TestServerObj a orber_test_server ref
-%% OtherObj - any other Orber object.
-%% Returns : term()
-%% Effect :
-%%------------------------------------------------------------
-
-corba_object_tests(TestServerObj, OtherObj) ->
- ?match(false,
- corba_object:is_a(TestServerObj, "IDL:orber_parent/inherrit:1.0")),
- ?match(true,
- corba_object:is_a(TestServerObj, "IDL:omg.org/orber_parent/inherrit:1.0")),
- ?match(true,
- corba_object:is_a(TestServerObj, "IDL:omg.org/orber_test/server:1.0")),
- ?match(false,
- corba_object:is_a(TestServerObj, "IDL:orber_test/server:1.0")),
- ?match(false,
- corba_object:is_a(TestServerObj, "IDL:omg.org/orber_parent/inherrit:1.1")),
- ?match(false,
- corba_object:is_a(TestServerObj, "NotValidIFRID")),
- ?match(false,
- corba_object:is_nil(TestServerObj)),
- ?match(false,
- corba_object:is_equivalent(OtherObj,TestServerObj)),
- ?match(true,
- corba_object:is_equivalent(TestServerObj,TestServerObj)),
- ?match(false, corba_object:non_existent(TestServerObj)),
- ?match(false, corba_object:not_existent(TestServerObj)),
- ?match(#fullinterfacedescription{}, corba_object:get_interface(TestServerObj)),
-
- ok.
-
-%%------------------------------------------------------------
-%% function : lookup
-%% Arguments: Port - which port the other orb uses.
-%% Returns : term()
-%% Effect :
-%%------------------------------------------------------------
-
-lookup(Host, Port) ->
- Key = Host++":"++integer_to_list(Port),
- NSR = corba:resolve_initial_references_remote("NameService",
- ["iiop://"++Key]),
-
- NC1 = lname_component:set_id(lname_component:create(), "not_exist"),
- N1 = lname:insert_component(lname:create(), 1, NC1),
- ?match({'EXCEPTION',{'CosNaming_NamingContext_NotFound',_,_,_}},
- 'CosNaming_NamingContext':resolve(NSR, N1)),
-
- NC2 = lname_component:set_id(lname_component:create(), "mamba"),
- N2 = lname:insert_component(lname:create(), 1, NC2),
- Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- 'CosNaming_NamingContext':resolve(NSR, N2)),
- orber_test_server:print(Obj),
- Obj2 = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- corba:string_to_object("corbaname:iiop:1.1@"++Key++"/NameService#mamba")),
-
- orber_test_server:print(Obj2),
-
- NSR2 = ?match({'IOP_IOR',"IDL:omg.org/CosNaming/NamingContextExt:1.0",_},
- corba:string_to_object("corbaloc:iiop:1.1@"++Key++"/NameService")),
- Obj3 = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- 'CosNaming_NamingContext':resolve(NSR2, N2)),
- orber_test_server:print(Obj3).
-
-%%------------------------------------------------------------
-%% function : alternate_iiop_address
-%% Arguments: Port - which port the other orb uses.
-%% Returns : term()
-%% Effect :
-%%------------------------------------------------------------
-alternate_iiop_address(Host, Port) ->
- IOR = create_alternate_iiop_address(Host, Port),
-
- ?match(false, corba_object:non_existent(IOR)),
- ?match({'object_forward',_}, corba:locate(IOR)),
- ?match({'object_forward',_}, corba:locate(IOR, 10000)),
- ok.
-
-%%------------------------------------------------------------
-%% function : create_alternate_iiop_address
-%% Arguments: Port - which port the other orb uses.
-%% Returns : term()
-%% Effect :
-%%------------------------------------------------------------
-create_alternate_iiop_address(Host, Port) ->
- MC = [#'IOP_TaggedComponent'{tag = ?TAG_ORB_TYPE,
- component_data = ?ORBER_ORB_TYPE_1},
- #'IOP_TaggedComponent'{tag = ?TAG_CODE_SETS,
- component_data = ?DEFAULT_CODESETS},
- #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
- component_data = #'ALTERNATE_IIOP_ADDRESS'{
- 'HostID' = Host,
- 'Port' = Port}},
- #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
- component_data = #'ALTERNATE_IIOP_ADDRESS'{
- 'HostID' = Host,
- 'Port' = 8000}},
- #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
- component_data = #'ALTERNATE_IIOP_ADDRESS'{
- 'HostID' = Host,
- 'Port' = 8000}}],
- #'IOP_IOR'{type_id=TypeID,
- profiles=P1} = _IORA = iop_ior:create({1,2},
- "IDL:omg.org/CosNaming/NamingContextExt:1.0",
- [Host], 8000, -1,
- "NameService", MC, 0, 0),
- #'IOP_IOR'{profiles=P2} = _IORB = iop_ior:create({1,1},
- "IDL:omg.org/CosNaming/NamingContextExt:1.0",
- [Host], 8000, -1,
- "NameService", [], 0, 0),
- #'IOP_IOR'{type_id=TypeID, profiles=P2++P1}.
-
-
-%%------------------------------------------------------------
-%% function : create_components_IOR
-%% Arguments:
-%% Returns : term()
-%% Effect :
-%%------------------------------------------------------------
-create_components_IOR(Version) ->
- MC = [#'IOP_TaggedComponent'{tag = ?TAG_ORB_TYPE,
- component_data = ?ORBER_ORB_TYPE_1},
- #'IOP_TaggedComponent'{tag = ?TAG_CODE_SETS,
- component_data = ?DEFAULT_CODESETS},
- #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
- component_data = #'ALTERNATE_IIOP_ADDRESS'{
- 'HostID' = "127.0.0.1",
- 'Port' = 4001}},
- #'IOP_TaggedComponent'{tag = ?TAG_SSL_SEC_TRANS,
- component_data = #'SSLIOP_SSL'{target_supports = 0,
- target_requires = 1,
- port = 2}},
- #'IOP_TaggedComponent'{tag = ?TAG_FT_GROUP,
- component_data =
- #'FT_TagFTGroupTaggedComponent'
- {version = #'GIOP_Version'{major = 1,
- minor = 2},
- ft_domain_id = "FT_FTDomainId",
- object_group_id = ?ULONGLONGMAX,
- object_group_ref_version = ?LONGMAX}},
- #'IOP_TaggedComponent'{tag = ?TAG_FT_PRIMARY,
- component_data =
- #'FT_TagFTPrimaryTaggedComponent'{primary = true}},
- #'IOP_TaggedComponent'{tag = ?TAG_FT_HEARTBEAT_ENABLED,
- component_data =
- #'FT_TagFTHeartbeatEnabledTaggedComponent'{heartbeat_enabled = true}},
- #'IOP_TaggedComponent'{tag = ?TAG_CSI_SEC_MECH_LIST,
- component_data =
- #'CSIIOP_CompoundSecMechList'
- {stateful = false,
- mechanism_list =
- [#'CSIIOP_CompoundSecMech'
- {target_requires = 6,
- transport_mech =
- #'IOP_TaggedComponent'
- {tag=?TAG_TLS_SEC_TRANS,
- component_data=#'CSIIOP_TLS_SEC_TRANS'
- {target_supports = 7,
- target_requires = 8,
- addresses =
- [#'CSIIOP_TransportAddress'{host_name = "127.0.0.1",
- port = 6001}]}},
- as_context_mech =
- #'CSIIOP_AS_ContextSec'
- {target_supports = 9, target_requires = 10,
- client_authentication_mech = [1, 255],
- target_name = [2,255]},
- sas_context_mech =
- #'CSIIOP_SAS_ContextSec'
- {target_supports = 11, target_requires = 12,
- privilege_authorities =
- [#'CSIIOP_ServiceConfiguration'
- {syntax = ?ULONGMAX,
- name = [3,255]}],
- supported_naming_mechanisms = [[4,255],[5,255]],
- supported_identity_types = ?ULONGMAX}},
- #'CSIIOP_CompoundSecMech'
- {target_requires = 6,
- transport_mech =
- #'IOP_TaggedComponent'
- {tag=?TAG_NULL_TAG,
- component_data=[]},
- as_context_mech =
- #'CSIIOP_AS_ContextSec'
- {target_supports = 9, target_requires = 10,
- client_authentication_mech = [1, 255],
- target_name = [2,255]},
- sas_context_mech =
- #'CSIIOP_SAS_ContextSec'
- {target_supports = 11, target_requires = 12,
- privilege_authorities =
- [#'CSIIOP_ServiceConfiguration'
- {syntax = ?ULONGMAX,
- name = [3,255]}],
- supported_naming_mechanisms = [[4,255],[5,255]],
- supported_identity_types = ?ULONGMAX}},
- #'CSIIOP_CompoundSecMech'
- {target_requires = 6,
- transport_mech =
- #'IOP_TaggedComponent'
- {tag=?TAG_SECIOP_SEC_TRANS,
- component_data=#'CSIIOP_SECIOP_SEC_TRANS'
- {target_supports = 7,
- target_requires = 8,
- mech_oid = [0,255],
- target_name = [0,255],
- addresses =
- [#'CSIIOP_TransportAddress'{host_name = "127.0.0.1",
- port = 6001}]}},
- as_context_mech =
- #'CSIIOP_AS_ContextSec'
- {target_supports = 9, target_requires = 10,
- client_authentication_mech = [1, 255],
- target_name = [2,255]},
- sas_context_mech =
- #'CSIIOP_SAS_ContextSec'
- {target_supports = 11, target_requires = 12,
- privilege_authorities =
- [#'CSIIOP_ServiceConfiguration'
- {syntax = ?ULONGMAX,
- name = [3,255]}],
- supported_naming_mechanisms = [[4,255],[5,255]],
- supported_identity_types = ?ULONGMAX}}]}}],
- iop_ior:create(Version, "IDL:omg.org/CosNaming/NamingContextExt:1.0",
- ["127.0.0.1"], 5001, -1,
- "NameService", MC, 0, 0).
-
-
-%%------------------------------------------------------------
-%% function : alternate_ssl_iiop_address
-%% Arguments: Port - which port the other orb uses.
-%% Returns : term()
-%% Effect :
-%%------------------------------------------------------------
-alternate_ssl_iiop_address(Host, Port, SSLPort) ->
- IOR = create_alternate_ssl_iiop_address(Host, Port, SSLPort),
-
- ?match(false, corba_object:non_existent(IOR)),
- ?match({'object_forward',_}, corba:locate(IOR)),
- ?match({'object_forward',_}, corba:locate(IOR, 10000)),
- ok.
-
-
-%%------------------------------------------------------------
-%% function : create_alternate_ssl_iiop_address
-%% Arguments: Port - which port the other orb uses.
-%% Returns : term()
-%% Effect :
-%%------------------------------------------------------------
-create_alternate_ssl_iiop_address(Host, Port, SSLPort) ->
- MC = [#'IOP_TaggedComponent'{tag = ?TAG_ORB_TYPE,
- component_data = ?ORBER_ORB_TYPE_1},
- #'IOP_TaggedComponent'{tag = ?TAG_CODE_SETS,
- component_data = ?DEFAULT_CODESETS},
- #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
- component_data = #'ALTERNATE_IIOP_ADDRESS'{
- 'HostID' = Host,
- 'Port' = Port}},
- #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
- component_data = #'ALTERNATE_IIOP_ADDRESS'{
- 'HostID' = Host,
- 'Port' = 8000}},
- #'IOP_TaggedComponent'{tag = ?TAG_ALTERNATE_IIOP_ADDRESS,
- component_data = #'ALTERNATE_IIOP_ADDRESS'{
- 'HostID' = Host,
- 'Port' = 8000}},
- #'IOP_TaggedComponent'{tag=?TAG_SSL_SEC_TRANS,
- component_data=#'SSLIOP_SSL'{target_supports = 2,
- target_requires = 2,
- port = SSLPort}}],
- #'IOP_IOR'{type_id=TypeID,
- profiles=P1} = _IORA = iop_ior:create_external({1,2},
- "IDL:omg.org/CosNaming/NamingContextExt:1.0",
- Host, 8000,
- "NameService", MC),
- #'IOP_IOR'{profiles=P2} = _IORB = iop_ior:create_external({1,1},
- "IDL:omg.org/CosNaming/NamingContextExt:1.0",
- Host, 8000,
- "NameService", []),
- #'IOP_IOR'{type_id=TypeID, profiles=P2++P1}.
-
-
-%%------------------------------------------------------------
-%% function : timeouts
-%% Arguments: Port - which port the other orb uses.
-%% Returns : term()
-%% Effect :
-%%------------------------------------------------------------
-
-timeouts(Host, Port, ReqT) ->
- NSR = corba:resolve_initial_references_remote("NameService",
- ["iiop://"++Host++":"++integer_to_list(Port)]),
- NC1 = lname_component:set_id(lname_component:create(), "mamba"),
- N1 = lname:insert_component(lname:create(), 1, NC1),
- NC2 = lname_component:set_id(lname_component:create(), "viper"),
- N2 = lname:insert_component(lname:create(), 1, NC2),
- Mamba = 'CosNaming_NamingContext':resolve(NSR, N1),
- Viper = 'CosNaming_NamingContext':resolve(NSR, N2),
-
- ?match({'EXCEPTION',{'TIMEOUT',_,_,_}},
- orber_test_timeout_server:twoway_function(Viper, ReqT, ReqT*2)),
- ?match(ok, orber_test_timeout_server:oneway_function(Viper, ReqT*2)),
-
- ?match({'EXCEPTION',{'TIMEOUT',_,_,_}},
- orber_test_server:testing_iiop_twoway_delay(Mamba, ReqT)),
- ?match(ok, orber_test_server:testing_iiop_oneway_delay(Mamba, ReqT)),
-
- %% Since the objects are stalled we must wait until they are available again
- %% to be able to run any more tests and get the correct results.
- timer:sleep(ReqT*4),
-
- ?match(ok, orber_test_timeout_server:twoway_function(Viper, ReqT*2, ReqT)),
- ?match(ok, orber_test_timeout_server:oneway_function(Viper, ReqT*2)),
-
- ?match(ok, orber_test_server:testing_iiop_twoway_delay(Mamba, 0)),
- ?match(ok, orber_test_server:testing_iiop_oneway_delay(Mamba, 0)),
-
- timer:sleep(ReqT*4),
- ok.
-
-%%------------------------------------------------------------
-%% function : light_tests
-%% Arguments: Host - which node to contact.
-%% Port - which port the other orb uses.
-%% Returns : term()
-%% Effect :
-%%------------------------------------------------------------
-
-light_tests(Host, Port, ObjName) ->
- NSR = corba:resolve_initial_references_remote("NameService",
- ["iiop://"++Host++":"++integer_to_list(Port)]),
- NC1 = lname_component:set_id(lname_component:create(), "not_exist"),
- N1 = lname:insert_component(lname:create(), 1, NC1),
- %% We cannot handle any unknown replies (besides those found in stub).
- ?match({'EXCEPTION',
- {'CosNaming_NamingContext_NotFound',
- "IDL:omg.org/CosNaming/NamingContext/NotFound:1.0",_,_}},
- 'CosNaming_NamingContext':resolve(NSR, N1)),
- NC2 = lname_component:set_id(lname_component:create(), ObjName),
- N2 = lname:insert_component(lname:create(), 1, NC2),
- Obj = ?match({'IOP_IOR',"IDL:omg.org/orber_test/server:1.0",_},
- 'CosNaming_NamingContext':resolve(NSR, N2)),
- Nodes = orber:get_lightweight_nodes(),
- io:format("Light Nodes: ~p~n", [Nodes]),
- orber_test_server:print(Obj),
- test_coding(Obj),
- ok.
-
-
-%%------------------------------------------------------------
-%% function : test_coding_simple
-%% Arguments: ObjReference
-%% Returns : term()
-%% Effect : test encode/decode for all simple datatypes.
-%%------------------------------------------------------------
-
-test_coding(Obj) ->
- test_coding(Obj, false).
-
-test_coding(Obj, Local) ->
- %%--- Testing code and decode arguments ---
- ?match({ok, 1.5}, orber_test_server:testing_iiop_float(Obj, 1.5)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_float(Obj, atom)),
-
- ?match({ok,1.0}, orber_test_server:testing_iiop_double(Obj, 1.0)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_double(Obj, "wrong")),
-
- ?match({ok,0}, orber_test_server:testing_iiop_short(Obj, 0)),
- ?match({ok,?SHORTMAX}, orber_test_server:testing_iiop_short(Obj, ?SHORTMAX)),
- ?match({ok,?SHORTMIN}, orber_test_server:testing_iiop_short(Obj, ?SHORTMIN)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_short(Obj, atomic)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_short(Obj, ?SHORTMAX+1)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_short(Obj, ?SHORTMIN-1)),
-
- ?match({ok,0}, orber_test_server:testing_iiop_ushort(Obj, 0)),
- ?match({ok,?USHORTMAX}, orber_test_server:testing_iiop_ushort(Obj, ?USHORTMAX)),
- ?match({ok,?USHORTMIN}, orber_test_server:testing_iiop_ushort(Obj, ?USHORTMIN)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_ushort(Obj, ?USHORTMAX+1)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_ushort(Obj, ?USHORTMIN-1)),
-
- ?match({ok,0}, orber_test_server:testing_iiop_long(Obj, 0)),
- ?match({ok,?LONGMAX}, orber_test_server:testing_iiop_long(Obj, ?LONGMAX)),
- ?match({ok,?LONGMIN}, orber_test_server:testing_iiop_long(Obj, ?LONGMIN)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_long(Obj, "wrong")),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_long(Obj, ?LONGMAX+1)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_long(Obj, ?LONGMIN-1)),
-
- ?match({ok,0}, orber_test_server:testing_iiop_longlong(Obj, 0)),
- ?match({ok,?LONGLONGMAX}, orber_test_server:testing_iiop_longlong(Obj, ?LONGLONGMAX)),
- ?match({ok,?LONGLONGMIN}, orber_test_server:testing_iiop_longlong(Obj, ?LONGLONGMIN)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_longlong(Obj, "wrong")),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_longlong(Obj, ?LONGLONGMAX+1)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_longlong(Obj, ?LONGLONGMIN-1)),
-
- ?match({ok,0}, orber_test_server:testing_iiop_ulong(Obj, 0)),
- ?match({ok,?ULONGMAX}, orber_test_server:testing_iiop_ulong(Obj, ?ULONGMAX)),
- ?match({ok,?ULONGMIN}, orber_test_server:testing_iiop_ulong(Obj, ?ULONGMIN)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_ulong(Obj, ?ULONGMAX+1)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_ulong(Obj, ?ULONGMIN-1)),
-
- ?match({ok,0}, orber_test_server:testing_iiop_ulonglong(Obj, 0)),
- ?match({ok,?ULONGLONGMAX}, orber_test_server:testing_iiop_ulonglong(Obj, ?ULONGLONGMAX)),
- ?match({ok,?ULONGLONGMIN}, orber_test_server:testing_iiop_ulonglong(Obj, ?ULONGLONGMIN)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_ulonglong(Obj, ?ULONGLONGMAX+1)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_ulonglong(Obj, ?ULONGLONGMIN-1)),
-
- ?match({ok,98}, orber_test_server:testing_iiop_char(Obj, 98)),
- ?match({ok,$b}, orber_test_server:testing_iiop_char(Obj, $b)),
-
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_char(Obj, atomic)),
-
- ?match({ok,65535}, orber_test_server:testing_iiop_wchar(Obj, 65535)),
- ?match({ok,$b}, orber_test_server:testing_iiop_wchar(Obj, $b)),
-
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_wchar(Obj, atomic)),
-
- ?match({ok,true}, orber_test_server:testing_iiop_bool(Obj, true)),
- ?match({ok,false}, orber_test_server:testing_iiop_bool(Obj, false)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_bool(Obj, atom)),
-
- ?match({ok,1}, orber_test_server:testing_iiop_octet(Obj, 1)),
-% No real guards for this case.
-% ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
-% orber_test_server:testing_iiop_octet(Obj, 1.5)),
- IOR12 = create_components_IOR({1,2}),
- ?match({ok,Obj}, orber_test_server:testing_iiop_obj(Obj, Obj)),
- ?match({ok,IOR12}, orber_test_server:testing_iiop_obj(Obj, IOR12)),
- PObj = orber_test_server:oe_create([], [{pseudo,true}]),
- ?match({ok, _}, orber_test_server:testing_iiop_obj(Obj, PObj)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_obj(Obj, "no_object")),
- ?match({ok,"string"}, orber_test_server:testing_iiop_string(Obj, "string")),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_string(Obj, "ToLongString")),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_string(Obj, atomic)),
-
- ?match({ok,[65535]}, orber_test_server:testing_iiop_wstring(Obj, [65535])),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_wstring(Obj, "ToLongWstring")),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_wstring(Obj, atomic)),
-
- ?match({ok, one},
- orber_test_server:testing_iiop_enum(Obj, one)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_enum(Obj, three)),
- ?match({ok,[1,2,3]},
- orber_test_server:testing_iiop_seq(Obj, [1,2,3])),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_seq(Obj, [1,2,3,4])),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_seq(Obj, false)),
-
-
- ?match({ok,[#orber_test_server_struc{a=1, b=2}]},
- orber_test_server:testing_iiop_struc_seq(Obj,
- [#orber_test_server_struc{a=1, b=2}])),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_struc_seq(Obj, false)),
-
- ?match({ok,[#orber_test_server_uni{label=1, value=66}]},
- orber_test_server:testing_iiop_uni_seq(Obj,
- [#orber_test_server_uni{label=1, value=66}])),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_uni_seq(Obj, false)),
-
- ?match({ok,{"one", "two"}},
- orber_test_server:testing_iiop_array(Obj, {"one", "two"})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_array(Obj, {"one", "two", "three"})),
- ?match({ok,#orber_test_server_struc{a=1, b=2}},
- orber_test_server:testing_iiop_struct(Obj,
- #orber_test_server_struc{a=1, b=2})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_struct(Obj,
- #orber_test_server_struc{a="WRONG", b=2})),
- ?match({ok,#orber_test_server_uni{label=1, value=66}},
- orber_test_server:testing_iiop_union(Obj,
- #orber_test_server_uni{label=1, value=66})),
-
- ?match({ok,#orber_test_server_uni_d{label=1, value=66}},
- orber_test_server:testing_iiop_union_d(Obj,
- #orber_test_server_uni_d{label=1, value=66})),
-
- ?match({ok,#orber_test_server_uni_d{label=2, value=true}},
- orber_test_server:testing_iiop_union_d(Obj,
- #orber_test_server_uni_d{label=2, value=true})),
-
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_union_d(Obj,
- #orber_test_server_uni_d{label=2, value=66})),
-
- case Local of
- true ->
- ?match({ok,#orber_test_server_uni{label=2, value=66}},
- orber_test_server:testing_iiop_union(Obj,
- #orber_test_server_uni{label=2, value=66}));
- false ->
- ?match({ok,#orber_test_server_uni{label=2, value=undefined}},
- orber_test_server:testing_iiop_union(Obj,
- #orber_test_server_uni{label=2, value=66}))
- end,
-
- C1 = orber_test_server:fixed52const1(),
- C2 = orber_test_server:fixed52const2(),
- C3 = orber_test_server:fixed52const3(),
-
- C4 = orber_test_server:fixed52negconst1(),
- C5 = orber_test_server:fixed52negconst2(),
- C6 = orber_test_server:fixed52negconst3(),
-
- ?match({ok,C1}, orber_test_server:testing_iiop_fixed(Obj, C1)),
- ?match({ok,C2}, orber_test_server:testing_iiop_fixed(Obj, C2)),
- ?match({ok,C3}, orber_test_server:testing_iiop_fixed(Obj, C3)),
- ?match({ok,C4}, orber_test_server:testing_iiop_fixed(Obj, C4)),
- ?match({ok,C5}, orber_test_server:testing_iiop_fixed(Obj, C5)),
- ?match({ok,C6}, orber_test_server:testing_iiop_fixed(Obj, C6)),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_fixed(Obj, #fixed{digits = 5,
- scale = 2,
- value = 123450})),
-
- ?match(ok, orber_test_server:testing_iiop_void(Obj)),
-
- ?match({'EXCEPTION',{'BAD_QOS',_,_,_}},
- orber_test_server:pseudo_call_raise_exc(Obj, 1)),
- ?match({'EXCEPTION',{'BAD_QOS',_,_,_}},
- orber_test_server:pseudo_call_raise_exc(Obj, 2)),
- ?match({'EXCEPTION',{'orber_test_server_UserDefinedException',_}},
- orber_test_server:raise_local_exception(Obj)),
- ?match({'EXCEPTION',{'orber_test_server_ComplexUserDefinedException',_,
- [#orber_test_server_struc{a=1, b=2}]}},
- orber_test_server:raise_complex_local_exception(Obj)),
- %% Test all TypeCodes
- ?match({ok, #any{typecode = tk_long, value = 1}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_long,
- value = 1})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_long,
- value = "wrong"})),
- ?match({ok, #any{typecode = tk_float, value = 1.5}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_float,
- value = 1.5})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_long,
- value = "wrong"})),
- ?match({ok, #any{typecode = tk_double}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_double,
- value = 1.0})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_double,
- value = "wrong"})),
- ?match({ok, #any{typecode = tk_short, value = -1}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_short,
- value = -1})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_short,
- value = atomic})),
- ?match({ok, #any{typecode = tk_ushort, value = 1}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ushort,
- value = 1})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ushort,
- value = -1})),
- ?match({ok, #any{typecode = tk_long, value = 1}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_long,
- value = 1})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_long,
- value = "wrong"})),
- ?match({ok, #any{typecode = tk_longlong, value = 1}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_longlong,
- value = 1})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_longlong,
- value = "wrong"})),
- ?match({ok, #any{typecode = tk_ulong, value = 1}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ulong,
- value = 1})),
- ?match({ok, #any{typecode = tk_ulong, value = 4294967295}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ulong,
- value = 4294967295})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ulong,
- value = 4294967296})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ulong,
- value = -1})),
- ?match({ok, #any{typecode = tk_ulonglong, value = 1}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ulonglong,
- value = 1})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_ulonglong,
- value = -1})),
- ?match({ok, #any{typecode = tk_char, value = 98}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_char,
- value = 98})),
- ?match({ok, #any{typecode = tk_char, value = $b}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_char,
- value = $b})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_char,
- value = atomic})),
- ?match({ok, #any{typecode = tk_wchar, value = 65535}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_wchar,
- value = 65535})),
- ?match({ok, #any{typecode = tk_wchar, value = $b}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_wchar,
- value = $b})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_wchar,
- value = atomic})),
- ?match({ok, #any{typecode = tk_boolean, value = true}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_boolean,
- value = true})),
- ?match({ok, #any{typecode = tk_boolean, value = false}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_boolean,
- value = false})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_boolean,
- value = 1})),
- ?match({ok, #any{typecode = tk_octet, value = 1}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_octet,
- value = 1})),
- ?match({ok, #any{typecode = {tk_objref, "IDL:omg.org/orber_test/server:1.0", "server"}, value = Obj}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_objref, "IDL:omg.org/orber_test/server:1.0", "server"},
- value = Obj})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_objref, "IDL:omg.org/orber_test/server:1.0", "server"},
- value = "No Object"})),
- ?match({ok, #any{typecode = {tk_string, 6}, value = "string"}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_string, 6},
- value = "string"})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = tk_string,
- value = atomic})),
- ?match({ok, #any{typecode = {tk_wstring, 1}, value = [65535]}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_wstring, 1},
- value = [65535]})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_wstring, 1},
- value = atomic})),
- ?match({ok, #any{typecode = {tk_enum, "IDL:omg.org/orber_test/server/enumerant:1.0", "enumerant", ["one","two"]},
- value = two}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_enum, "IDL:omg.org/orber_test/server/enumerant:1.0", "enumerant", ["one","two"]},
- value = two})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_enum, "IDL:omg.org/orber_test/server/enumerant:1.0", "enumerant", ["one","two"]},
- value = three})),
-
-
- ?match({ok, #any{typecode = {tk_sequence, tk_long, 3},
- value = [1,2,3]}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_sequence, tk_long, 3},
- value = [1,2,3]})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_sequence, tk_long, 3},
- value = false})),
-
-
-
- ?match({ok, #any{typecode = {tk_array,{tk_string,0},2},
- value = {"one", "two"}}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_array,{tk_string,0},2},
- value = {"one", "two"}})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_array,{tk_string,0},2},
- value = {"one", "two", "three"}})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_array,{tk_string,0},2},
- value = {1, 2}})),
- ?match({ok, #any{typecode = {tk_struct,"IDL:omg.org/orber_test/server/struc:1.0",
- "struc",
- [{"a",tk_long},{"b",tk_short}]},
- value = #orber_test_server_struc{a=1, b=2}}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_struct,"IDL:omg.org/orber_test/server/struc:1.0",
- "struc",
- [{"a",tk_long},{"b",tk_short}]},
- value = #orber_test_server_struc{a=1, b=2}})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_struct,"IDL:omg.org/orber_test/server/struc:1.0",
- "struc",
- [{"a",tk_long},{"b",tk_short}]},
- value = #orber_test_server_struc{a=1, b="string"}})),
- ?match({ok, #any{typecode =
- {tk_union,"IDL:omg.org/orber_test/server/uni:1.0",
- "uni", tk_long, -1, [{1,"a",tk_long}]},
- value = #orber_test_server_uni{label=1, value=66}}},
- orber_test_server:
- testing_iiop_any(Obj,
- #any{typecode =
- {tk_union,"IDL:omg.org/orber_test/server/uni:1.0",
- "uni", tk_long, -1, [{1,"a",tk_long}]},
- value = #orber_test_server_uni{label=1, value=66}})),
- case Local of
- true ->
- ?match({ok, #any{typecode =
- {tk_union,"IDL:omg.org/orber_test/server/uni:1.0",
- "uni", tk_long, -1, [{1,"a",tk_long}]},
- value = #orber_test_server_uni{label=2, value=66}}},
- orber_test_server:
- testing_iiop_any(Obj,
- #any{typecode =
- {tk_union,"IDL:omg.org/orber_test/server/uni:1.0",
- "uni", tk_long, -1, [{1,"a",tk_long}]},
- value = #orber_test_server_uni{label=2, value=66}}));
- false ->
- ?match({ok, #any{typecode =
- {tk_union,"IDL:omg.org/orber_test/server/uni:1.0",
- "uni", tk_long, -1, [{1,"a",tk_long}]},
- value = #orber_test_server_uni{label=2, value=undefined}}},
- orber_test_server:
- testing_iiop_any(Obj,
- #any{typecode =
- {tk_union,"IDL:omg.org/orber_test/server/uni:1.0",
- "uni", tk_long, -1, [{1,"a",tk_long}]},
- value = #orber_test_server_uni{label=2, value=66}}))
- end,
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:
- testing_iiop_any(Obj,
- #any{typecode =
- {tk_union,"IDL:omg.org/orber_test/server/uni:1.0",
- "uni", tk_long, -1, [{1,"a",tk_long}]},
- value = #orber_test_server_uni{label=1, value="string"}})),
-
- ?match({ok, #any{typecode = {tk_fixed,5,2},
- value = #fixed{digits = 5, scale = 2, value = 12345}}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_fixed,5,2},
- value = #fixed{digits = 5,
- scale = 2,
- value = 12345}})),
- ?match({ok, #any{typecode = {tk_fixed,10,2},
- value = #fixed{digits = 10, scale = 2, value = 1234567890}}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_fixed,10,2},
- value = #fixed{digits = 10,
- scale = 2,
- value = 1234567890}})),
- ?match({ok, #any{typecode = {tk_fixed,6,2},
- value = #fixed{digits = 6, scale = 2, value = 300000}}},
- orber_test_server:testing_iiop_any(Obj, #any{typecode = {tk_fixed,6,2},
- value = #fixed{digits = 6,
- scale = 2,
- value = 300000}})),
- ?match({'EXCEPTION',{'MARSHAL',_,_,_}},
- orber_test_server:
- testing_iiop_server_marshal(Obj, "string")),
-
- RecS = #orber_test_server_rec_struct{chain = [#orber_test_server_rec_struct{chain = []}]},
- ?match(RecS, orber_test_server:testing_iiop_rec_struct(Obj, RecS)),
-
- RecU = #orber_test_server_rec_union{label = 'RecursiveType',
- value = [#orber_test_server_rec_union{label = 'RecursiveType',
- value = []}]},
- ?match(RecU, orber_test_server:testing_iiop_rec_union(Obj, RecU)),
-
-%% RecA1 = #any{typecode = unsupported, value = RecS},
-%% RecA2 = #any{typecode = unsupported, value = RecU},
-%% ?match(RecA1,
-%% orber_test_server:testing_iiop_rec_any(Obj, RecA1)),
-%% ?match(RecA2,
-%% orber_test_server:testing_iiop_rec_any(Obj, RecA2)),
-
- ok.
-
-%%--------------- Testing Post- & Pre-cond -------------------
-precond(Module, Function, Args) ->
- error_logger:info_msg("=============== pre-condition ============
-Module : ~p
-Function : ~p
-Arguments : ~p
-==========================================~n", [Module, Function, Args]),
- ok.
-
-postcond(Module, Function, Args, Result) ->
- error_logger:info_msg("=============== post-condition ===========
-Module : ~p
-Function : ~p
-Arguments : ~p
-Result : ~p
-==========================================~n", [Module, Function, Args, Result]),
- ok.
-
-%%--------------- Testing Missing Module ---------------------
-oe_get_interface() ->
- non_existing_module:tc(foo).
-
-%%--------------- INTERCEPTOR FUNCTIONS ----------------------
-%%------------------------------------------------------------
-%% function : new_in_connection
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-new_in_connection(Arg, CHost, Port) ->
- Host = node(),
- [{SHost, SPort}] = orber:find_sockname_by_peername(CHost, Port),
- Peers = orber:find_peername_by_sockname(SHost, SPort),
- error_logger:info_msg("=============== new_in_connection ========
-Node : ~p
-From Host : ~p
-From Port : ~p
-To Host : ~p
-To Port : ~p
-Peers : ~p
-Arg : ~p
-==========================================~n",
- [Host, CHost, Port, SHost, SPort, Peers, Arg]),
- {Host}.
-
-%%------------------------------------------------------------
-%% function : new_out_connection
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-new_out_connection(Arg, SHost, Port) ->
- Host = node(),
- error_logger:info_msg("=============== new_out_connection =======
-Node : ~p
-To Host : ~p
-To Port : ~p
-Arg : ~p
-==========================================~n",
- [Host, SHost, Port, Arg]),
- {Host}.
-
-%%------------------------------------------------------------
-%% function : closed_in_connection
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-closed_in_connection(Arg) ->
- error_logger:info_msg("=============== closed_in_connection =====
-Node : ~p
-Connection: ~p
-==========================================~n",
- [node(), Arg]),
- Arg.
-
-%%------------------------------------------------------------
-%% function : closed_out_connection
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-closed_out_connection(Arg) ->
- error_logger:info_msg("=============== closed_out_connection ====
-Node : ~p
-Connection: ~p
-==========================================~n",
- [node(), Arg]),
- Arg.
-
-%%------------------------------------------------------------
-%% function : in_request_encoded
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-in_request_encoded(Ref, _ObjKey, Ctx, Op,
- <<100:8,101:8,102:8,103:8,104:8,105:8,106:8,107:8,108:8,109:8,110:8,T/binary>>, _Args) ->
- error_logger:info_msg("=============== in_request_encoded =======
-Connection: ~p
-Operation : ~p
-Body : ~p
-Context : ~p
-==========================================~n",
- [Ref, Op, T, Ctx]),
- {T, "NewArgs"}.
-
-%%------------------------------------------------------------
-%% function : in_reply_encoded
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-in_reply_encoded(Ref, _ObjKey, Ctx, Op,
- <<100:8,101:8,102:8,103:8,104:8,105:8,106:8,107:8,108:8,109:8,110:8,T/binary>>,
- _Args) ->
- error_logger:info_msg("============== in_reply_encoded ==========
-Connection: ~p
-Operation : ~p
-Body : ~p
-Context : ~p
-==========================================~n",
- [Ref, Op, T, Ctx]),
- {T, "NewArgs"}.
-
-%%------------------------------------------------------------
-%% function : out_reply_encoded
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-out_reply_encoded(Ref, _ObjKey, Ctx, Op, List, _Args) ->
- error_logger:info_msg("============== out_reply_encoded =========
-Connection: ~p
-Operation : ~p
-Body : ~p
-Context : ~p
-==========================================~n",
- [Ref, Op, List, Ctx]),
- {list_to_binary([<<100:8,101:8,102:8,103:8,104:8,105:8,106:8,107:8,108:8,109:8,110:8>>|List]), "NewArgs"}.
-
-%%------------------------------------------------------------
-%% function : out_request_encoded
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-out_request_encoded(Ref, _ObjKey, Ctx, Op, List, _Args) ->
- error_logger:info_msg("============== out_request_encoded =======
-Connection: ~p
-Operation : ~p
-Body : ~p
-Context : ~p
-==========================================~n",
- [Ref, Op, List, Ctx]),
- {list_to_binary([<<100:8,101:8,102:8,103:8,104:8,105:8,106:8,107:8,108:8,109:8,110:8>>|List]), "NewArgs"}.
-
-%%------------------------------------------------------------
-%% function : in_request
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-in_request(Ref, _ObjKey, Ctx, Op, Params, _Args) ->
- error_logger:info_msg("=============== in_request ===============
-Connection: ~p
-Operation : ~p
-Parameters: ~p
-Context : ~p
-==========================================~n",
- [Ref, Op, Params, Ctx]),
- {Params, "NewArgs"}.
-
-%%------------------------------------------------------------
-%% function : in_reply
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-in_reply(Ref, _ObjKey, Ctx, Op, Reply, _Args) ->
- error_logger:info_msg("=============== in_reply =================
-Connection: ~p
-Operation : ~p
-Reply : ~p
-Context : ~p
-==========================================~n",
- [Ref, Op, Reply, Ctx]),
- {Reply, "NewArgs"}.
-
-%%------------------------------------------------------------
-%% function : postinvoke
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-out_reply(Ref, _ObjKey, Ctx, Op, Reply, _Args) ->
- error_logger:info_msg("=============== out_reply ================
-Connection: ~p
-Operation : ~p
-Reply : ~p
-Context : ~p
-==========================================~n",
- [Ref, Op, Reply, Ctx]),
- {Reply, "NewArgs"}.
-
-%%------------------------------------------------------------
-%% function : postinvoke
-%% Arguments:
-%% Returns :
-%%------------------------------------------------------------
-out_request(Ref, _ObjKey, Ctx, Op, Params, _Args) ->
- error_logger:info_msg("=============== out_request ==============
-Connection: ~p
-Operation : ~p
-Parameters: ~p
-Context : ~p
-==========================================~n",
- [Ref, Op, Params, Ctx]),
- {Params, "NewArgs"}.
-
-
-%%--------------- END OF MODULE ------------------------------
-
-
-
diff --git a/lib/orber/test/orber_test_server.cfg b/lib/orber/test/orber_test_server.cfg
deleted file mode 100644
index c6bbd99f17..0000000000
--- a/lib/orber/test/orber_test_server.cfg
+++ /dev/null
@@ -1,28 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-{timeout, "orber_test::timeout_server"}.
-{this, "orber_test::timeout_server"}.
-{{handle_info, "orber_test::timeout_server"}, true}.
-{this, "orber_test::server"}.
-{{handle_info, "orber_test::server"}, true}.
-{{postcond, "orber_test::server::testing_iiop_union_d"}, {orber_test_lib, postcond}}.
-{{postcond, "orber_test::server::testing_iiop_array"}, {orber_test_lib, postcond}}.
-{{precond, "orber_test::server::testing_iiop_array"}, {orber_test_lib, precond}}.
-{{precond, "orber_test::server::testing_iiop_enum"}, {orber_test_lib, precond}}.
diff --git a/lib/orber/test/orber_test_server.idl b/lib/orber/test/orber_test_server.idl
deleted file mode 100644
index f274baed24..0000000000
--- a/lib/orber/test/orber_test_server.idl
+++ /dev/null
@@ -1,177 +0,0 @@
-//
-// %CopyrightBegin%
-//
-// Copyright Ericsson AB 1999-2016. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// %CopyrightEnd%
-//
-
-#ifndef _ORBER_TEST_SERVER_IDL
-#define _ORBER_TEST_SERVER_IDL
-#pragma prefix "omg.org"
-
-module orber_parent {
- interface inherrit {
- void print();
- };
-};
-
-module orber_test {
-
- // interface server
- interface server : orber_parent::inherrit {
- typedef string array[2];
- typedef sequence <long, 3> seq;
- typedef wstring<6> WstrLength6;
- typedef string<6> StrLength6;
-
- struct struc {long a; short b;};
- union uni switch(long) {
- case 1: long a;};
-
- union uni_d switch(long) {
- case 1: long a;
- default: boolean b;
- };
- enum enumerant {one, two};
-
- exception UserDefinedException {};
-
- typedef sequence<struc> StrucSeq;
- typedef sequence<uni> UniSeq;
- exception ComplexUserDefinedException { StrucSeq strseq; };
-
- // Testing fixed
- const fixed val1 = 3.14D;
- const fixed val2 = 003.14D;
- const fixed val3 = 003.1400D;
- const fixed val4 = 3.1400D;
- const fixed val5 = .1400D;
- const fixed val6 = 3.D;
- const fixed val7 = -.1400D;
- const fixed val8 = -3.D;
- const fixed val9 = val4+val5;
- const fixed val10 = val4*val5;
- const fixed val11 = val4/val5;
- const fixed val12 = 123.140001D;
- const fixed val13 = 12314000.1D;
- const fixed val14 = val12-val13;
- const fixed val15 = val12+val13;
- const fixed val16 = val12*val13;
- const fixed val17 = 2.01D+2.01D;
- const fixed val18 = 2.01D*2.01D;
- const fixed val19 = 200D;
- const fixed val20 = 9999999999999999999999999999999D+9999999999999999999999999999999D;
- const fixed val21 = 9999999999999999999999999999999D-9999999999999999999999999999999D;
- const fixed val22 = 9999999999999999999999999999999D*9999999999999999999999999999999D;
- const fixed val23 = 9999999999999999999999999999999D/9999999999999999999999999999999D;
- const fixed val24 = 9999D+9999D;
- const fixed val25 = 400D/10D;
- const fixed val26 = 9999999999999999999999999999999D;
-
-
- typedef fixed<5,2> fixed52;
- const fixed52 fixed52const1 = 123.45d;
- const fixed52 fixed52const2 = 123.00d;
- const fixed52 fixed52const3 = 023.00d;
- const fixed52 fixed52negconst1 = -123.45d;
- const fixed52 fixed52negconst2 = -123.00d;
- const fixed52 fixed52negconst3 = -023.00d;
-
- struct rec_struct; // Forward declaration
- typedef sequence<rec_struct> rec_struct_seq;
- struct rec_struct {
- rec_struct_seq chain;
- };
-
-
- union rec_union; // Forward declaration
- typedef sequence<rec_union>rec_union_seq;
-
- enum MyEnum {RecursiveType, NameType};
-
- union rec_union switch (MyEnum) {
- case RecursiveType : rec_union_seq chain;
- case NameType : string aName;
- };
-
- void stop_normal();
-
- void stop_brutal();
-
- // Testing encode and decode
- void testing_iiop_float(inout float Fl);
- void testing_iiop_double(inout double Do);
- void testing_iiop_short(inout short Sh);
- void testing_iiop_ushort(inout unsigned short Us);
- void testing_iiop_long(inout long Lo);
- void testing_iiop_longlong(inout long long LLo);
- void testing_iiop_ulong(inout unsigned long Ulo);
- void testing_iiop_ulonglong(inout unsigned long long LLo);
- void testing_iiop_char(inout char Ch);
- void testing_iiop_wchar(inout wchar WCh);
- void testing_iiop_bool(inout boolean Bool);
- void testing_iiop_octet(inout octet Oct);
- void testing_iiop_any(inout any AnyType);
- void testing_iiop_obj(inout Object Obj);
- void testing_iiop_string(inout StrLength6 Str);
- void testing_iiop_wstring(inout WstrLength6 WStr);
- void testing_iiop_struct(inout struc Stru);
- void testing_iiop_union(inout uni Uni);
- void testing_iiop_union_d(inout uni_d Uni);
- void testing_iiop_enum(inout enumerant Enumerant);
- void testing_iiop_seq(inout seq Seq);
- void testing_iiop_uni_seq(inout UniSeq USeq);
- void testing_iiop_struc_seq(inout StrucSeq SSeq);
- void testing_iiop_array(inout array Arr);
- void testing_iiop_fixed(inout fixed52 MyFixed);
- void testing_iiop_void();
- void testing_iiop_context();
- void testing_iiop_server_marshal(inout StrLength6 Str);
-
- // Recursive types
- any testing_iiop_rec_any(in any RecType);
- rec_struct testing_iiop_rec_struct(in rec_struct RecS);
- rec_union testing_iiop_rec_union(in rec_union RecU);
-
-
- oneway void testing_iiop_oneway_delay(in long Time);
- void testing_iiop_twoway_delay(in long Time);
-
- // Testing relay calls/casts to, for example, test that sending implicit
- // Contexts works.
- void relay_call(in Object Target);
- oneway void relay_cast(in Object Target);
-
- // Testing pseudo calls/casts
- void pseudo_call();
- oneway void pseudo_cast();
- void pseudo_call_delay(inout long Lo);
- oneway void pseudo_cast_delay(in long Lo);
- void pseudo_call_raise_exc(in long Lo);
- void raise_local_exception()
- raises(UserDefinedException);
- void raise_complex_local_exception()
- raises(ComplexUserDefinedException);
- };
-
- interface timeout_server {
- oneway void oneway_function(in long time);
- void twoway_function(in long time);
- };
-
-};
-
-#endif
diff --git a/lib/orber/test/orber_test_server_impl.erl b/lib/orber/test/orber_test_server_impl.erl
deleted file mode 100644
index d9cef17d26..0000000000
--- a/lib/orber/test/orber_test_server_impl.erl
+++ /dev/null
@@ -1,276 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(orber_test_server_impl).
--include_lib("orber/include/corba.hrl").
--include("idl_output/orber_test_server.hrl").
-
-%%--------------- specified functions ------------------------
--export([stop_normal/2,
- stop_brutal/2,
- print/2,
- %% Testing code and decode arguments
- testing_iiop_float/3,
- testing_iiop_double/3,
- testing_iiop_short/3,
- testing_iiop_ushort/3,
- testing_iiop_long/3,
- testing_iiop_longlong/3,
- testing_iiop_ulong/3,
- testing_iiop_ulonglong/3,
- testing_iiop_char/3,
- testing_iiop_wchar/3,
- testing_iiop_bool/3,
- testing_iiop_octet/3,
- testing_iiop_any/3,
- testing_iiop_obj/3,
- testing_iiop_string/3,
- testing_iiop_wstring/3,
- testing_iiop_struct/3,
- testing_iiop_union/3,
- testing_iiop_union_d/3,
- testing_iiop_enum/3,
- testing_iiop_seq/3,
- testing_iiop_uni_seq/3,
- testing_iiop_struc_seq/3,
- testing_iiop_array/3,
- testing_iiop_fixed/3,
- testing_iiop_void/2,
- testing_iiop_context/2,
- testing_iiop_server_marshal/3,
- testing_iiop_rec_any/3,
- testing_iiop_rec_struct/3,
- testing_iiop_rec_union/3,
- relay_call/3,
- relay_cast/3,
- %% Testing pseudo calls.
- pseudo_call/2,
- pseudo_cast/2,
- pseudo_call_delay/3,
- pseudo_cast_delay/3,
- pseudo_call_raise_exc/3,
- %% Testing raise locally defined exception.
- raise_local_exception/2,
- raise_complex_local_exception/2,
- %% Test timeout functionality
- testing_iiop_oneway_delay/3,
- testing_iiop_twoway_delay/3]).
-
-
-%%--------------- gen_server specific ------------------------
--export([init/1, terminate/2]).
--export([handle_call/3, handle_cast/2, handle_info/2, code_change/3]).
-
-%%--------------- LOCAL DATA ---------------------------------
-
-%%------------------------------------------------------------
-%% function : init, terminate
-%%------------------------------------------------------------
-init(State) ->
- process_flag(trap_exit,true),
- {ok, State}.
-
-terminate(Reason, State) ->
- io:format("orber_test_server:terminate(~p ~p)~n",[Reason, State]),
- ok.
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-handle_call(_,_, State) ->
- {noreply, State}.
-handle_cast(_, State) ->
- {noreply, State}.
-handle_info(_Info, State) ->
- {noreply, State}.
-
-%%--------------- SERVER FUNCTIONS ---------------------------
-
-print(Self, State) ->
- io:format("orber_test_server:print(~p ~p)~n",[Self, State]),
- {reply, ok, State}.
-
-stop_normal(_Self, State) ->
- {stop, normal, ok, State}.
-
-stop_brutal(_Self, _State) ->
- exit("killed_brutal").
-
-
-%% Testing code and decode arguments
-testing_iiop_float(_Self, State, Float) ->
- {reply, {ok, Float}, State}.
-
-testing_iiop_double(_Self, State, Double) ->
- {reply, {ok, Double}, State}.
-
-testing_iiop_short(_Self, State, Short) ->
- {reply, {ok, Short}, State}.
-
-testing_iiop_ushort(_Self, State, Ushort) ->
- {reply, {ok, Ushort}, State}.
-
-testing_iiop_long(_Self, State, Long) ->
- {reply, {ok, Long}, State}.
-
-testing_iiop_longlong(_Self, State, LLong) ->
- {reply, {ok, LLong}, State}.
-
-testing_iiop_ulong(_Self, State, Ulong) ->
- {reply, {ok, Ulong}, State}.
-
-testing_iiop_ulonglong(_Self, State, ULlong) ->
- {reply, {ok, ULlong}, State}.
-
-testing_iiop_char(_Self, State, Char) ->
- {reply, {ok, Char}, State}.
-
-testing_iiop_wchar(_Self, State, WChar) ->
- {reply, {ok, WChar}, State}.
-
-testing_iiop_bool(_Self, State, Boolean) ->
- {reply, {ok, Boolean}, State}.
-
-testing_iiop_octet(_Self, State, Octet) ->
- {reply, {ok, Octet}, State}.
-
-testing_iiop_any(_Self, State, Any) ->
- {reply, {ok, Any}, State}.
-
-testing_iiop_obj(_Self, State, Obj) ->
- {reply, {ok, Obj}, State}.
-
-testing_iiop_string(_Self, State, String) ->
- {reply, {ok, String}, State}.
-
-testing_iiop_wstring(_Self, State, WString) ->
- {reply, {ok, WString}, State}.
-
-testing_iiop_struct(_Self, State, Struct) ->
- {reply, {ok, Struct}, State}.
-
-testing_iiop_union(_Self, State, Union) ->
- {reply, {ok, Union}, State}.
-
-testing_iiop_union_d(_Self, State, Union) ->
- {reply, {ok, Union}, State}.
-
-testing_iiop_enum(_Self, State, Enum) ->
- {reply, {ok, Enum}, State}.
-
-testing_iiop_seq(_Self, State, Sequence) ->
- {reply, {ok, Sequence}, State}.
-
-testing_iiop_uni_seq(_Self, State, Sequence) ->
- {reply, {ok, Sequence}, State}.
-
-testing_iiop_struc_seq(_Self, State, Sequence) ->
- {reply, {ok, Sequence}, State}.
-
-testing_iiop_array(_Self, State, Array) ->
- {reply, {ok, Array}, State}.
-
-testing_iiop_fixed(_Self, State, Fixed) ->
- {reply, {ok, Fixed}, State}.
-
-testing_iiop_void(_Self, State) ->
- {reply, ok, State}.
-
-testing_iiop_context(_Self, State) ->
- Ctx = get(oe_server_in_context),
- io:format("orber_test_server:testing_iiop_context( ~p )~n", [Ctx]),
- {reply, ok, State}.
-
-testing_iiop_server_marshal(_Self, State, _String) ->
- {reply, {ok, false}, State}.
-
-testing_iiop_rec_any(_Self, State, RAny) ->
- {reply, RAny, State}.
-
-testing_iiop_rec_struct(_Self, State, RecS) ->
- {reply, RecS, State}.
-
-testing_iiop_rec_union(_Self, State, RecU) ->
- {reply, RecU, State}.
-
-
-testing_iiop_oneway_delay(_Self, State, Time) ->
- timer:sleep(Time),
- {noreply, State}.
-
-testing_iiop_twoway_delay(_Self, State, Time) ->
- timer:sleep(Time),
- {reply, ok, State}.
-
-raise_local_exception(_Self, State) ->
- corba:raise(#'orber_test_server_UserDefinedException'{}),
- {reply, ok, State}.
-
-raise_complex_local_exception(_Self, State) ->
- corba:raise(#'orber_test_server_ComplexUserDefinedException'{strseq=
- [#orber_test_server_struc{a=1, b=2}]}),
- {reply, ok, State}.
-
-%% Testing relay calls/casts to, for example, test that sending implicit
-%% Contexts works.
-relay_call(_Self, State, Target) ->
- io:format("orber_test_server:relay_call( ~p ) Pre~n", [get(oe_server_in_context)]),
- orber_test_server:testing_iiop_context(Target),
- io:format("orber_test_server:relay_call( ~p ) Post~n", [get(oe_server_in_context)]),
- {reply, ok, State}.
-
-relay_cast(_Self, State, Target) ->
- io:format("orber_test_server:relay_cast( ~p ) Pre~n", [get(oe_server_in_context)]),
- orber_test_server:testing_iiop_context(Target),
- io:format("orber_test_server:relay_cast( ~p ) Post~n", [get(oe_server_in_context)]),
- {noreply, State}.
-
-%% Testing pseudo calls.
-pseudo_call(_Self, State) ->
- io:format("orber_test_server:pseudo_call( ~p )~n", [erlang:timestamp()]),
- {reply, ok, State}.
-
-pseudo_cast(_Self, State) ->
- io:format("orber_test_server:pseudo_cast( ~p )~n", [erlang:timestamp()]),
- {noreply, State}.
-pseudo_call_delay(_Self, State, Time) ->
- io:format("orber_test_server:pseudo_call_delay( ~p )~n", [erlang:timestamp()]),
- timer:sleep(Time),
- io:format("orber_test_server:pseudo_call_delay( ~p )~n", [erlang:timestamp()]),
- {reply, {ok, Time}, State}.
-
-pseudo_cast_delay(_Self, State, Time) ->
- io:format("orber_test_server:pseudo_cast_delay( ~p )~n", [erlang:timestamp()]),
- timer:sleep(Time),
- io:format("orber_test_server:pseudo_cast_delay( ~p )~n", [erlang:timestamp()]),
- {noreply, State}.
-
-pseudo_call_raise_exc(_Self, State, 1) ->
- io:format("orber_test_server:pseudo_call_raise_exc( ~p )~n",[1]),
- {reply, {'EXCEPTION', #'BAD_QOS'{completion_status=?COMPLETED_NO}}, State};
-pseudo_call_raise_exc(_Self, State, 2) ->
- io:format("orber_test_server:pseudo_call_raise_exc( ~p )~n",[2]),
- corba:raise(#'BAD_QOS'{completion_status=?COMPLETED_NO}),
- {reply, ok, State}.
-
-%%--------------- LOCAL FUNCTIONS ----------------------------
-
-%%--------------- END OF MODULE ------------------------------
-
diff --git a/lib/orber/test/orber_test_timeout_server_impl.erl b/lib/orber/test/orber_test_timeout_server_impl.erl
deleted file mode 100644
index de16877dde..0000000000
--- a/lib/orber/test/orber_test_timeout_server_impl.erl
+++ /dev/null
@@ -1,66 +0,0 @@
-%%--------------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%----------------------------------------------------------------------
-%% File : orber_test_timeout_server_impl.erl
-%% Purpose :
-%%----------------------------------------------------------------------
-
--module(orber_test_timeout_server_impl).
-
--export([oneway_function/3, twoway_function/3]).
-
-
-%%--------------- gen_server specific ------------------------
--export([init/1, terminate/2, code_change/3, handle_info/2]).
-
-%%------------------------------------------------------------
-%% function : server specific
-%%------------------------------------------------------------
-init(State) ->
- %% 'trap_exit' optional
- process_flag(trap_exit,true),
- {ok, State}.
-
-terminate(_Reason, _State) ->
- ok.
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%% If use IC option {{handle_info, "Module::Interface"}, true}
-handle_info(_Info, State) ->
- %% Await the next invocation.
- {noreply, State}.
-
-%%--- two-way ------------------------------------------------
-twoway_function(_OE_THIS, State, Time) ->
- timer:sleep(Time),
- {reply, ok, State}.
-
-
-%%--- one-way ------------------------------------------------
-oneway_function(_OE_THIS, State, Time) ->
- timer:sleep(Time),
- {noreply, State}.
-
-%%--------------- END OF MODULE ------------------------------
-
diff --git a/lib/orber/test/orber_web_SUITE.erl b/lib/orber/test/orber_web_SUITE.erl
deleted file mode 100644
index b272eb3fcf..0000000000
--- a/lib/orber/test/orber_web_SUITE.erl
+++ /dev/null
@@ -1,440 +0,0 @@
-%%-----------------------------------------------------------------
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-%%-----------------------------------------------------------------
-%% File : orber_web_SUITE.erl
-%% Purpose :
-%%-----------------------------------------------------------------
-
--module(orber_web_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/include/corba.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
--define(default_timeout, test_server:minutes(3)).
-
--define(match(ExpectedRes, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- ExpectedRes ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS;
- _ ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS)
- end
- end()).
-
--define(nomatch(Not, Expr),
- fun() ->
- AcTuAlReS = (catch (Expr)),
- case AcTuAlReS of
- Not ->
- io:format("###### ERROR ERROR ######~n~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS);
- _ ->
- io:format("------ CORRECT RESULT ------~n~p~n",
- [AcTuAlReS]),
- AcTuAlReS
- end
- end()).
-
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [menu, configure, info, nameservice, ifr_select,
- ifr_data, create, delete_ctx, add_ctx, delete_obj,
- server].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- Path = code:which(?MODULE),
- code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
- orber:jump_start(2875),
- oe_orber_test_server:oe_register(),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- oe_orber_test_server:oe_unregister(),
- orber:jump_stop(),
- Path = code:which(?MODULE),
- code:del_path(filename:join(filename:dirname(Path), "idl_output")),
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: menu
-%% Description:
-%%-----------------------------------------------------------------
-menu(_) ->
- Node = atom_to_list(node()),
- OK = orber_web:menu(env, [{"node", Node}]),
- ?match(OK, orber_web:menu(env, [])),
- ?match(OK, orber_web:menu(env, [42, {"node", Node}, "wrong"])),
- ?match({'EXIT', _E}, orber_web:menu(env, [{"node", localhost}])),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: configure
-%% Description:
-%%-----------------------------------------------------------------
-configure(_) ->
- Node = atom_to_list(node()),
- ?match({'EXIT', _}, orber_web:configure(env, [])),
- ?match({'EXIT', _}, orber_web:configure(env, [{"node", localhost},
- {"data", atom}])),
- ?match([_H|_T], orber_web:configure(env, [{"node", Node}, {"data", ""}])),
- ?match([_H|_T], orber_web:configure(env, [{"node", Node},
- {"data", "[{orber_debug_level, 9}]"}])),
- ?match({ok, 9}, application:get_env(orber, orber_debug_level)),
- ?match([_H|_T], orber_web:configure(env, [{"node", "bad_node"},
- {"data", "[{orber_debug_level, 9}]"}])),
- ?match({error, _}, orber_web:configure(env, [{"node", Node},
- {"data", "{orber_debug_level 9}"}])),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: info
-%% Description:
-%%-----------------------------------------------------------------
-info(_) ->
- ?match({'EXIT', _}, orber_web:info(env, [])),
- ?match({'EXIT', _}, orber_web:info(env, [{"node", localhost}])),
- ?match([_H|_T], orber_web:info(env, [{"node", atom_to_list(node())}])),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: nameservice
-%% Description:
-%%-----------------------------------------------------------------
-nameservice(_) ->
- NodeStr = atom_to_list(node()),
- ?match({'EXIT', _}, orber_web:nameservice(env, [{"node", localhost},
- {"context", "root"}])),
- ?match({'EXIT', _}, orber_web:nameservice(env, [{"node", localhost},
- {"context", "id1"}])),
- ?match([_H|_T], orber_web:nameservice(env, [{"node", "bad_node"},
- {"context", "root"}])),
- ?match([_,_,_,NodeStr|_], orber_web:nameservice(env, [{"node", NodeStr},
- {"context", "root"}])),
- ?match({ok,_}, orber_web:nameservice(env, [{"node", NodeStr},
- {"context", "id1"}])),
- ?match([_H|_T], orber_web:add_ctx(env, [{"node", NodeStr},
- {"context", "root"},
- {"id", "id1"}])),
- ?match([_H|_T], orber_web:add_ctx(env, [{"node", NodeStr},
- {"context", "id1"},
- {"id", "id2"}])),
- [_,_,_,IOR] =
- ?match([_,_,_,_], orber_web:create(env, [{"node", NodeStr},
- {"module", "orber_test_server"},
- {"arguments", "[]"},
- {"options", "[{pseudo, true}]"},
- {"namestr", "id1/id2/id3"},
- {"bind", "rebind"}])),
- ?match(#'IOP_IOR'{}, corba:string_to_object(IOR)),
-
- ?match([_,"id1"|_], orber_web:nameservice(env, [{"node", NodeStr},
- {"context", "id1"}])),
- ?nomatch({error, _}, orber_web:nameservice(env, [{"node", NodeStr},
- {"context", "id1/id2"},
- {"object", "id3"}])),
-
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: ifr_select
-%% Description:
-%%-----------------------------------------------------------------
-ifr_select(_) ->
- ?match({'EXIT', _}, orber_web:ifr_select(env, [])),
- ?match({'EXIT', _}, orber_web:ifr_select(env, [{"node", localhost}])),
- ?match([_H|_T], orber_web:ifr_select(env, [{"node", "bad_node"}])),
- ?match([_H|_T], orber_web:ifr_select(env, [{"node", atom_to_list(node())}])),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: ifr_data
-%% Description:
-%%-----------------------------------------------------------------
-ifr_data(_) ->
- ?match({'EXIT', _}, orber_web:ifr_data(env, [])),
- ?match({'EXIT', _}, orber_web:ifr_data(env, [{"node", localhost},
- {"table", "ir_ModuleDef"}])),
- ?match({error, _}, orber_web:ifr_data(env, [{"node", "bad_host"},
- {"table", "ir_ModuleDef"}])),
- ?match({'EXIT', _}, orber_web:ifr_data(env, [{"node", atom_to_list(node())},
- {"table", "bad_table"}])),
- ?match([_H|_T], orber_web:ifr_data(env, [{"node", atom_to_list(node())},
- {"table", "ir_ModuleDef"}])),
- ?match([_H|_T], orber_web:ifr_data(env, [{"node", atom_to_list(node())},
- {"table", "ir_InterfaceDef"}])),
- ?match([_H|_T], orber_web:ifr_data(env, [{"node", atom_to_list(node())},
- {"table", "ir_StructDef"}])),
- ?match([_H|_T], orber_web:ifr_data(env, [{"node", atom_to_list(node())},
- {"table", "ir_ExceptionDef"}])),
- ?match([_H|_T], orber_web:ifr_data(env, [{"node", atom_to_list(node())},
- {"table", "ir_ConstantDef"}])),
- ?match([_H|_T], orber_web:ifr_data(env, [{"node", atom_to_list(node())},
- {"table", "ir_EnumDef"}])),
- ?match([_H|_T], orber_web:ifr_data(env, [{"node", atom_to_list(node())},
- {"table", "ir_AliasDef"}])),
- ?match([_H|_T], orber_web:ifr_data(env, [{"node", atom_to_list(node())},
- {"table", "ir_AttributeDef"}])),
- ?match([_H|_T], orber_web:ifr_data(env, [{"node", atom_to_list(node())},
- {"table", "ir_OperationDef"}])),
- ?match([_H|_T], orber_web:ifr_data(env, [{"node", atom_to_list(node())},
- {"table", "ir_Contained"}])),
- ?match([_H|_T], orber_web:ifr_data(env, [{"node", atom_to_list(node())},
- {"table", "ir_TypedefDef"}])),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: create
-%% Description:
-%%-----------------------------------------------------------------
-create(_) ->
- NodeStr = atom_to_list(node()),
- ?match({'EXIT', _}, orber_web:create(env, [])),
- ?match({'EXIT', _}, orber_web:create(env, [{"node", localhost}])),
- ?match({error, _}, orber_web:create(env, [{"node", NodeStr},
- {"module", "orber_test_server"},
- {"arguments", "[]"},
- {"options", "[bad_option 42]"},
- {"namestr", "[]"},
- {"bind", "rebind"}])),
- ?match({error, _}, orber_web:create(env, [{"node", NodeStr},
- {"module", "orber_test_server"},
- {"arguments", "[bad_argument 42]"},
- {"options", "[]"},
- {"namestr", "[]"},
- {"bind", "rebind"}])),
-
- ?match([_, NodeStr|_T], orber_web:create(env, [{"node", NodeStr}])),
-
- [_,IOR] = ?match([_,_], orber_web:create(env, [{"node", NodeStr},
- {"module", "orber_test_server"},
- {"arguments", "[]"},
- {"options", "[]"},
- {"namestr", ""},
- {"bind", "rebind"}])),
- ?match(#'IOP_IOR'{}, corba:string_to_object(IOR)),
-
- [_,_,_,_,_,IOR2] =
- ?match([_,_,_,_,_,_], orber_web:create(env, [{"node", NodeStr},
- {"module", "orber_test_server"},
- {"arguments", "[]"},
- {"options", "[]"},
- {"namestr", "id1"},
- {"bind", "rebind"}])),
- ?match(#'IOP_IOR'{}, corba:string_to_object(IOR2)),
-
- [_,_,_,IOR3] =
- ?match([_,_,_,_], orber_web:create(env, [{"node", NodeStr},
- {"module", "orber_test_server"},
- {"arguments", "[]"},
- {"options", "[{pseudo, true}]"},
- {"namestr", "id2"},
- {"bind", "rebind"}])),
- ?match(#'IOP_IOR'{}, corba:string_to_object(IOR3)),
-
- [_,IOR4] =?match([_,_], orber_web:create(env, [{"node", NodeStr},
- {"module", "orber_test_server"},
- {"arguments", "[]"},
- {"options", "[{pseudo, true}]"},
- {"namestr", ""},
- {"bind", "rebind"}])),
- ?match(#'IOP_IOR'{}, corba:string_to_object(IOR4)),
-
- ?match([_], orber_web:create(env, [{"node", NodeStr},
- {"module", "orber_test_server"},
- {"arguments", "[]"},
- {"options", "[{unknown, option}]"},
- {"namestr", "id1"},
- {"bind", "rebind"}])),
-
- ?match([_, "id1"], orber_web:create(env, [{"node", NodeStr},
- {"module", "orber_test_server"},
- {"arguments", "[]"},
- {"options", "[]"},
- {"namestr", "id1"},
- {"bind", "bind"}])),
-
- ?match([_, "id2"], orber_web:create(env, [{"node", NodeStr},
- {"module", "orber_test_server"},
- {"arguments", "[]"},
- {"options", "[{pseudo, true}]"},
- {"namestr", "id2"},
- {"bind", "bind"}])),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: delete_ctx
-%% Description:
-%%-----------------------------------------------------------------
-delete_ctx(_) ->
- ?match({ok, _}, orber_web:delete_ctx(env, [{"node", atom_to_list(node())},
- {"context", "id1"}])),
- ?match([_H|_T], orber_web:add_ctx(env, [{"node", atom_to_list(node())},
- {"context", "root"},
- {"id", "id1"}])),
- ?match([_H|_T], orber_web:delete_ctx(env, [{"node", atom_to_list(node())},
- {"context", "id1"}])),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: add_ctx
-%% Description:
-%%-----------------------------------------------------------------
-add_ctx(_) ->
- ?match({error, _}, orber_web:add_ctx(env, [{"node", "bad_node"},
- {"context", "root"},
- {"id", "id1"}])),
- ?match([_H|_T], orber_web:add_ctx(env, [{"node", atom_to_list(node())},
- {"context", "root"},
- {"id", ""}])),
- ?match([_H|_T], orber_web:add_ctx(env, [{"node", atom_to_list(node())},
- {"context", "root"},
- {"id", "id1"}])),
- ?match([_H|_T], orber_web:add_ctx(env, [{"node", atom_to_list(node())},
- {"context", "id1"},
- {"id", "id2"}])),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: delete_obj
-%% Description:
-%%-----------------------------------------------------------------
-delete_obj(_) ->
- NodeStr = atom_to_list(node()),
- ?match({error, _}, orber_web:delete_obj(env, [{"node", "bad_node"},
- {"context", "id1"},
- {"action", "unbind"}])),
- ?match({error, _}, orber_web:delete_obj(env, [{"node", "bad_node"},
- {"context", "id1"},
- {"action", "both"}])),
- ?match({'EXIT', _}, orber_web:delete_obj(env, [{"node", bad_node},
- {"context", "id1"},
- {"action", "both"}])),
- ?match({error, _}, orber_web:delete_obj(env, [{"node", NodeStr},
- {"context", "non/existing"},
- {"action", "unbind"}])),
- [_,_,_,_,_,IOR2] =
- ?match([_,_,_,_,_,_], orber_web:create(env, [{"node", NodeStr},
- {"module", "orber_test_server"},
- {"arguments", "[]"},
- {"options", "[]"},
- {"namestr", "id1"},
- {"bind", "rebind"}])),
- ?match(#'IOP_IOR'{}, corba:string_to_object(IOR2)),
-
- ?match({error, _}, orber_web:delete_obj(env, [{"node", NodeStr},
- {"context", "bad/INS./id"},
- {"action", "unbind"}])),
-
- [_,_,_,IOR3] =
- ?match([_,_,_,_], orber_web:create(env, [{"node", NodeStr},
- {"module", "orber_test_server"},
- {"arguments", "[]"},
- {"options", "[{pseudo, true}]"},
- {"namestr", "id2"},
- {"bind", "rebind"}])),
- ?match(#'IOP_IOR'{}, corba:string_to_object(IOR3)),
-
- ?match([_, "id1"|_], orber_web:delete_obj(env, [{"node", NodeStr},
- {"context", "id1"},
- {"action", "unbind"}])),
- ?match([_, "id2"|_], orber_web:delete_obj(env, [{"node", NodeStr},
- {"context", "id2"},
- {"action", "unbind"}])),
-
-
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: server
-%% Description:
-%%-----------------------------------------------------------------
-server(_) ->
- NodeStr = "node=" ++ atom_to_list(node()),
- {ok, Pid} = ?match({ok,_}, orber_web_server:start()),
- ?match({error,{already_started, Pid}}, orber_web_server:start_link()),
- ?match({error,{already_started,Pid}}, orber_web_server:start()),
- ?match({orber, _}, orber_web_server:config_data()),
- ?match([_H|_T], orber_web_server:ifr_select(env, "node=badnode")),
- ?match([_H|_T], orber_web_server:ifr_select(env, "node=" ++ NodeStr)),
- ?match([_H|_T], orber_web_server:menu(env, NodeStr)),
- ?match([_H|_T], orber_web_server:configure(env, NodeStr ++ "&data=[{orber_debug_level, 9}]")),
- ?match([_H|_T], orber_web_server:nameservice(env, NodeStr ++ "&context=root")),
- ?match([_H|_T], orber_web_server:info(env, NodeStr)),
- ?match([_H|_T], orber_web_server:ifr_data(env, NodeStr ++ "&table=ir_ModuleDef")),
- ?match([_H|_T], orber_web_server:create(env, NodeStr)),
- ?match([_H|_T], orber_web_server:add_ctx(env, NodeStr ++ "&context=root&id=id1")),
- ?match([_H|_T], orber_web_server:delete_ctx(env, NodeStr++"&context=id1")),
- ?match([_H|_T], orber_web_server:delete_obj(env, NodeStr++"&context=id1&action=unbind")),
- ?match([_H|_T], orber_web_server:default_selection(env, NodeStr)),
- ?match(ok, orber_web_server:stop()),
- ok.
-
-
diff --git a/lib/orber/test/tc_SUITE.erl b/lib/orber/test/tc_SUITE.erl
deleted file mode 100644
index 4572057403..0000000000
--- a/lib/orber/test/tc_SUITE.erl
+++ /dev/null
@@ -1,605 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache Li2cense, 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%
-%%
-%%
-%%-----------------------------------------------------------------
-%%
-%% Description:
-%% Test suite for the basic typecode functions
-%%
-%%-----------------------------------------------------------------
--module(tc_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("orber/src/orber_iiop.hrl").
-
--define(default_timeout, test_server:minutes(3)).
-
--define(match(Expr),
- fun() ->
- case (catch (Expr)) of
- AcTuAlReS when is_binary(AcTuAlReS)->
- io:format("###### ERROR ERROR ######~nRESULT: ~p~n",
- [AcTuAlReS]),
- exit(AcTuAlReS);
- _ ->
- ok
- end
- end()).
--define(SUB_ELIST, [{"null", orber_tc:null()},
- {"void", orber_tc:void()},
- {"short", orber_tc:short()},
- {"unsigned_short", orber_tc:unsigned_short()},
- {"long", orber_tc:long()},
- {"unsigned_long", orber_tc:unsigned_long()},
- {"long_long", orber_tc:long_long()},
- {"unsigned_long_long", orber_tc:unsigned_long_long()},
- {"float", orber_tc:'float'()},
- {"double", orber_tc:double()},
- {"longdouble", orber_tc:longdouble()},
- {"boolean", orber_tc:boolean()},
- {"char", orber_tc:char()},
- {"wchar", orber_tc:wchar()},
- {"octet", orber_tc:octet()},
- {"any", orber_tc:any()},
- {"typecode", orber_tc:typecode()},
- {"principal", orber_tc:principal()},
- {"object_reference", orber_tc:object_reference("Id", "Name")}]).
-
--define(ELIST, [{"null", orber_tc:null()},
- {"void", orber_tc:void()},
- {"short", orber_tc:short()},
- {"unsigned_short", orber_tc:unsigned_short()},
- {"long", orber_tc:long()},
- {"unsigned_long", orber_tc:unsigned_long()},
- {"long_long", orber_tc:long_long()},
- {"unsigned_long_long", orber_tc:unsigned_long_long()},
- {"float", orber_tc:'float'()},
- {"double", orber_tc:double()},
- {"longdouble", orber_tc:longdouble()},
- {"boolean", orber_tc:boolean()},
- {"char", orber_tc:char()},
- {"wchar", orber_tc:wchar()},
- {"octet", orber_tc:octet()},
- {"any", orber_tc:any()},
- {"typecode", orber_tc:typecode()},
- {"principal", orber_tc:principal()},
- {"object_reference", orber_tc:object_reference("Id", "Name")},
- {"struct", orber_tc:struct("Id", "Name", ?SUB_ELIST)},
- {"enum", orber_tc:enum("Id", "Name", ["E1", "E2"])},
- {"string", orber_tc:string(1)},
- {"wstring", orber_tc:wstring(0)},
- {"sequence", orber_tc:sequence(orber_tc:enum("Id", "Name",
- ["E1", "E2"]), 0)},
- {"array", orber_tc:array(orber_tc:enum("Id", "Name",
- ["E1", "E2"]), 2)},
- {"alias", orber_tc:alias("id", "name",
- orber_tc:enum("Id", "Name",
- ["E1", "E2"]))},
- {"exception", orber_tc:exception("Id", "Name", ?SUB_ELIST)}]).
-
--define(VELIST, [{"null", orber_tc:null(), 42},
- {"void", orber_tc:void(), 42},
- {"short", orber_tc:short(), 42},
- {"unsigned_short", orber_tc:unsigned_short(), 42},
- {"long", orber_tc:long(), 42},
- {"unsigned_long", orber_tc:unsigned_long(), 42},
- {"long_long", orber_tc:long_long(), 42},
- {"unsigned_long_long", orber_tc:unsigned_long_long(), 42},
- {"float", orber_tc:'float'(), 42},
- {"double", orber_tc:double(), 42},
- {"longdouble", orber_tc:longdouble(), 42},
- {"boolean", orber_tc:boolean(), 42},
- {"char", orber_tc:char(), 42},
- {"wchar", orber_tc:wchar(), 42},
- {"octet", orber_tc:octet(), 42},
- {"any", orber_tc:any(), 42},
- {"typecode", orber_tc:typecode(), 42},
- {"principal", orber_tc:principal(), 42},
- {"object_reference", orber_tc:object_reference("Id", "Name"), 42},
- {"struct", orber_tc:struct("Id", "Name", ?SUB_ELIST), 42},
- {"enum", orber_tc:enum("Id", "Name", ["E1", "E2"]), 42},
- {"string", orber_tc:string(1), 42},
- {"wstring", orber_tc:wstring(0), 42},
- {"sequence", orber_tc:sequence(orber_tc:enum("Id", "Name",
- ["E1", "E2"]), 0), 42},
- {"array", orber_tc:array(orber_tc:enum("Id", "Name",
- ["E1", "E2"]), 2), 42},
- {"alias", orber_tc:alias("id", "name",
- orber_tc:enum("Id", "Name",
- ["E1", "E2"])), 42},
- {"exception", orber_tc:exception("Id", "Name", ?SUB_ELIST), 42}]).
-
-%%-----------------------------------------------------------------
-%% External exports
-%%-----------------------------------------------------------------
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
-%%-----------------------------------------------------------------
-%% Internal exports
-%%-----------------------------------------------------------------
--compile(export_all).
-
-%%-----------------------------------------------------------------
-%% Func: all/1
-%% Args:
-%% Returns:
-%%-----------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [null, void, short, ushort, long, ulong, longlong,
- ulonglong, boolean, char, wchar, octet, float, double,
- longdouble, any, typecode, principal, object_reference,
- struct, union, enum, string, wstring, sequence, array,
- alias, exception, fixed, value, value_box, native,
- abstract_interface, indirection, get_tc].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%-----------------------------------------------------------------
-%% Init and cleanup functions.
-%%-----------------------------------------------------------------
-
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-
-
-end_per_testcase(_Case, Config) ->
- Dog = proplists:get_value(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: null test
-%% Description:
-%%-----------------------------------------------------------------
-null(_) ->
- true = orber_tc:check_tc(orber_tc:null()),
- code(orber_tc:null()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: void test
-%% Description:
-%%-----------------------------------------------------------------
-void(_) ->
- true = orber_tc:check_tc(orber_tc:void()),
- code(orber_tc:void()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: short integer test
-%% Description:
-%%-----------------------------------------------------------------
-short(_) ->
- true = orber_tc:check_tc(orber_tc:short()),
- code(orber_tc:short()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: unsigned short integer test
-%% Description:
-%%-----------------------------------------------------------------
-ushort(_) ->
- true = orber_tc:check_tc(orber_tc:unsigned_short()),
- code(orber_tc:unsigned_short()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: long integer test
-%% Description:
-%%-----------------------------------------------------------------
-long(_) ->
- true = orber_tc:check_tc(orber_tc:long()),
- code(orber_tc:long()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: unsigned long integer test
-%% Description:
-%%-----------------------------------------------------------------
-ulong(_) ->
- true = orber_tc:check_tc(orber_tc:unsigned_long()),
- code(orber_tc:unsigned_long()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: long integer test
-%% Description:
-%%-----------------------------------------------------------------
-longlong(_) ->
- true = orber_tc:check_tc(orber_tc:long_long()),
- code(orber_tc:long_long()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: unsigned long integer test
-%% Description:
-%%-----------------------------------------------------------------
-ulonglong(_) ->
- true = orber_tc:check_tc(orber_tc:unsigned_long_long()),
- code(orber_tc:unsigned_long_long()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: float test
-%% Description:
-%%-----------------------------------------------------------------
-float(_) ->
- true = orber_tc:check_tc(orber_tc:'float'()),
- code(orber_tc:'float'()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: double test
-%% Description:
-%%-----------------------------------------------------------------
-double(_) ->
- true = orber_tc:check_tc(orber_tc:double()),
- code(orber_tc:double()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: longdouble test
-%% Description:
-%%-----------------------------------------------------------------
-longdouble(_) ->
- true = orber_tc:check_tc(orber_tc:longdouble()),
- code(orber_tc:longdouble()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: boolean test
-%% Description:
-%%-----------------------------------------------------------------
-boolean(_) ->
- true = orber_tc:check_tc(orber_tc:boolean()),
- code(orber_tc:boolean()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: character test
-%% Description:
-%%-----------------------------------------------------------------
-char(_) ->
- true = orber_tc:check_tc(orber_tc:char()),
- code(orber_tc:char()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: character test
-%% Description:
-%%-----------------------------------------------------------------
-wchar(_) ->
- true = orber_tc:check_tc(orber_tc:wchar()),
- code(orber_tc:wchar()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: octet test
-%% Description:
-%%-----------------------------------------------------------------
-octet(_) ->
- true = orber_tc:check_tc(orber_tc:octet()),
- code(orber_tc:octet()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: any test
-%% Description:
-%%-----------------------------------------------------------------
-any(_) ->
- true = orber_tc:check_tc(orber_tc:any()),
- code(orber_tc:any()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: typecode test
-%% Description:
-%%-----------------------------------------------------------------
-typecode(_) ->
- true = orber_tc:check_tc(orber_tc:typecode()),
- code(orber_tc:typecode()),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: principal test
-%% Description:
-%%-----------------------------------------------------------------
-principal(_) ->
- true = orber_tc:check_tc(orber_tc:principal()),
- code(orber_tc:principal()),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: object_reference test
-%% Description:
-%%-----------------------------------------------------------------
-object_reference(_) ->
- true = orber_tc:check_tc(orber_tc:object_reference("Id", "Name")),
- false = orber_tc:check_tc(orber_tc:object_reference(42, "Name")),
- false = orber_tc:check_tc(orber_tc:object_reference("Id", 42)),
- code(orber_tc:object_reference("Id", "Name")),
- ?match(code(orber_tc:object_reference(42, "Name"))),
- ?match(code(orber_tc:object_reference("Id", 42))),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: struct
-%% Description:
-%%-----------------------------------------------------------------
-struct(_) ->
- true = orber_tc:check_tc(orber_tc:struct("Id", "Name", ?ELIST)),
- false = orber_tc:check_tc(orber_tc:struct(42, "Name", ?ELIST)),
- false = orber_tc:check_tc(orber_tc:struct("Id", false, ?ELIST)),
- false = orber_tc:check_tc(orber_tc:struct("Id", "Name", ?VELIST)),
- false = orber_tc:check_tc(orber_tc:struct("Id", "Name", "wrong")),
- code(orber_tc:struct("Id", "Name", ?ELIST)),
- ?match(code(orber_tc:struct(42, "Name", ?ELIST))),
- ?match(code(orber_tc:struct("Id", false, ?ELIST))),
- ?match(code(orber_tc:struct("Id", "Name", ?VELIST))),
- ?match(code(orber_tc:struct("Id", "Name", "wrong"))),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: union
-%% Description:
-%%-----------------------------------------------------------------
-union(_) ->
- true = orber_tc:check_tc(orber_tc:union("Id", "Name", orber_tc:long(),
- -1, [{1, "long", orber_tc:long()},
- {2, "longlong", orber_tc:long()}])),
- false = orber_tc:check_tc(orber_tc:union("Id", "Name", orber_tc:long(),
- -1, ?ELIST)),
- false = orber_tc:check_tc(orber_tc:union(42, "Name", orber_tc:long(),
- -1, [{1, "long", orber_tc:long()},
- {2, "longlong", orber_tc:long()}])),
- false = orber_tc:check_tc(orber_tc:union("Id", false, orber_tc:long(),
- -1, [{1, "long", orber_tc:long()},
- {2, "longlong", orber_tc:long()}])),
- false = orber_tc:check_tc(orber_tc:union("Id", "Name", bad_tc,
- -1, [{1, "long", orber_tc:long()},
- {2, "longlong", orber_tc:long()}])),
- false = orber_tc:check_tc(orber_tc:union("Id", "Name", orber_tc:long(),
- "wrong", [{1, "long", orber_tc:long()},
- {2, "longlong", orber_tc:long()}])),
-
- code(orber_tc:union("Id", "Name", orber_tc:long(),
- -1, [{1, "long", orber_tc:long()},
- {2, "longlong", orber_tc:long()}])),
- ok.
-
-
-%%-----------------------------------------------------------------
-%% Test Case: enum test
-%% Description:
-%%-----------------------------------------------------------------
-enum(_) ->
- true = orber_tc:check_tc(orber_tc:enum("Id", "Name",
- ["E1", "E2", "E3"])),
- false = orber_tc:check_tc(orber_tc:enum(42, "Name",
- ["E1", "E2", "E3"])),
- false = orber_tc:check_tc(orber_tc:enum("Id", false,
- ["E1", "E2", "E3"])),
- false = orber_tc:check_tc(orber_tc:enum("Id", "Name",
- ["E1", false, "E3"])),
- code(orber_tc:enum("Id", "Name", ["E1", "E2", "E3"])),
- ?match(code(orber_tc:enum(false, "Name", ["E1", "E2", "E3"]))),
- ?match(code(orber_tc:enum("Id", 42, ["E1", "E2", "E3"]))),
- ?match(code(orber_tc:enum("Id", "Name", ["E1", false, "E3"]))),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: string
-%% Description:
-%%-----------------------------------------------------------------
-string(_) ->
- true = orber_tc:check_tc(orber_tc:string(0)),
- true = orber_tc:check_tc(orber_tc:string(1)),
- false = orber_tc:check_tc(orber_tc:string("wrong")),
- code(orber_tc:string(0)),
- code(orber_tc:string(1)),
- ?match(code(orber_tc:string(-1))),
- ?match(code(orber_tc:string(?ULONGMAX+1))),
- ?match(code(orber_tc:string("wrong"))),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: wstring
-%% Description:
-%%-----------------------------------------------------------------
-wstring(_) ->
- true = orber_tc:check_tc(orber_tc:wstring(0)),
- true = orber_tc:check_tc(orber_tc:wstring(1)),
- false = orber_tc:check_tc(orber_tc:wstring("wrong")),
- code(orber_tc:wstring(0)),
- code(orber_tc:wstring(1)),
- ?match(code(orber_tc:wstring(-1))),
- ?match(code(orber_tc:wstring(?ULONGMAX+1))),
- ?match(code(orber_tc:wstring(false))),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: sequence
-%% Description:
-%%-----------------------------------------------------------------
-sequence(_) ->
- true = orber_tc:check_tc(orber_tc:sequence(orber_tc:struct("Id", "Name", ?ELIST), 0)),
- code(orber_tc:sequence(orber_tc:struct("Id", "Name", ?ELIST), 0)),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: array
-%% Description:
-%%-----------------------------------------------------------------
-array(_) ->
- true = orber_tc:check_tc(orber_tc:array(orber_tc:struct("Id", "Name", ?ELIST), 1)),
- code(orber_tc:array(orber_tc:struct("Id", "Name", ?ELIST), 1)),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: alias
-%% Description:
-%%-----------------------------------------------------------------
-alias(_) ->
- true = orber_tc:check_tc(orber_tc:alias("Id", "Name", orber_tc:struct("Id", "Name", ?ELIST))),
- false = orber_tc:check_tc(orber_tc:alias(false, "Name", orber_tc:struct("Id", "Name", ?ELIST))),
- false = orber_tc:check_tc(orber_tc:alias("Id", 42, orber_tc:struct("Id", "Name", ?ELIST))),
- false = orber_tc:check_tc(orber_tc:alias("Id", "Name", "wrong")),
- code(orber_tc:alias("Id", "Name", orber_tc:struct("Id", "Name", ?ELIST))),
- ?match(code(orber_tc:alias("Id", "Name", orber_tc:struct("Id", "Name", ?VELIST)))),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: exception
-%% Description:
-%%-----------------------------------------------------------------
-exception(_) ->
- true = orber_tc:check_tc(orber_tc:exception("Id", "Name", ?ELIST)),
- false = orber_tc:check_tc(orber_tc:exception(42, "Name", ?ELIST)),
- false = orber_tc:check_tc(orber_tc:exception("Id", false, ?ELIST)),
- false = orber_tc:check_tc(orber_tc:exception("Id", "Name", "wrong")),
- code(orber_tc:exception("Id", "Name", ?ELIST)),
- ?match(code(orber_tc:exception(42, "Name", ?ELIST))),
- ?match(code(orber_tc:exception("Id", false, ?ELIST))),
- ?match(code(orber_tc:exception("Id", "Name", "wrong"))),
-
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: fixed
-%% Description:
-%%-----------------------------------------------------------------
-fixed(_) ->
- true = orber_tc:check_tc(orber_tc:fixed(25, 2)),
- code(orber_tc:fixed(25, 2)),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: value
-%% Description:
-%%-----------------------------------------------------------------
-value(_) ->
- true = orber_tc:check_tc(orber_tc:value("Id", "Name", 42,
- orber_tc:fixed(25, 2), ?VELIST)),
- false = orber_tc:check_tc(orber_tc:value(42, "Name", 42,
- orber_tc:fixed(25, 2), ?VELIST)),
- false = orber_tc:check_tc(orber_tc:value("Id", 42, 42,
- orber_tc:fixed(25, 2), ?VELIST)),
- false = orber_tc:check_tc(orber_tc:value("Id", "Name", "wrong",
- orber_tc:fixed(25, 2), ?VELIST)),
- false = orber_tc:check_tc(orber_tc:value("Id", "Name", "42",
- orber_tc:fixed(25, 2), ?VELIST)),
- false = orber_tc:check_tc(orber_tc:value("Id", "Name", "42",
- ?VELIST, ?VELIST)),
- false = orber_tc:check_tc(orber_tc:value("Id", "Name", "42",
- orber_tc:fixed(25, 2), false)),
-
- code(orber_tc:value("Id", "Name", 42, orber_tc:long(), ?VELIST)),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: value_box
-%% Description:
-%%-----------------------------------------------------------------
-value_box(_) ->
- true = orber_tc:check_tc(orber_tc:value_box("Id", "Name",
- orber_tc:fixed(25, 2))),
- false = orber_tc:check_tc(orber_tc:value_box(42, "Name",
- orber_tc:fixed(25, 2))),
- false = orber_tc:check_tc(orber_tc:value_box("Id", 42,
- orber_tc:fixed(25, 2))),
- false = orber_tc:check_tc(orber_tc:value_box("Id", "Name", "wrong")),
- code(orber_tc:value_box("Id", "Name", orber_tc:long())),
- ?match(code(orber_tc:value_box(42, "Name", orber_tc:short()))),
- ?match(code(orber_tc:value_box("Id", 42, orber_tc:char()))),
- ?match(code(orber_tc:value_box("Id", "Name", false))),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: native
-%% Description:
-%%-----------------------------------------------------------------
-native(_) ->
- true = orber_tc:check_tc(orber_tc:native("Id", "Name")),
- false = orber_tc:check_tc(orber_tc:native(42, "Name")),
- false = orber_tc:check_tc(orber_tc:native("Id", 42)),
- code(orber_tc:native("Id", "Name")),
- ?match(code(orber_tc:native(42, "Name"))),
- ?match(code(orber_tc:native("Id", 42))),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: abstract_interface
-%% Description:
-%%-----------------------------------------------------------------
-abstract_interface(_) ->
- true = orber_tc:check_tc(orber_tc:abstract_interface("RepId", "Name")),
- false = orber_tc:check_tc(orber_tc:abstract_interface(false, "Name")),
- false = orber_tc:check_tc(orber_tc:abstract_interface("RepId", 42)),
- code(orber_tc:abstract_interface("RepId", "Name")),
- ?match(code(orber_tc:abstract_interface(42, "Name"))),
- ?match(code(orber_tc:abstract_interface("Id", 42))),
- ok.
-
-
-
-%%-----------------------------------------------------------------
-%% Test Case: indirection
-%% Description:
-%%-----------------------------------------------------------------
-indirection(_) ->
- true = orber_tc:check_tc({'none', 42}),
- ok.
-
-%%-----------------------------------------------------------------
-%% Test Case: get_tc
-%% Description:
-%%-----------------------------------------------------------------
-get_tc(_) ->
- TC = 'CosNaming_Binding':tc(),
- TC = orber_tc:get_tc({'CosNaming_Binding', 42}),
- ?match(orber_tc:get_tc({'none', 42})),
- ok.
-
-%%-----------------------------------------------------------------
-%% MISC Operations
-%%-----------------------------------------------------------------
-code(Value) ->
- cdr_encode:enc_type({1,2}, tk_TypeCode, Value).
diff --git a/lib/orber/vsn.mk b/lib/orber/vsn.mk
deleted file mode 100644
index 595e686cb7..0000000000
--- a/lib/orber/vsn.mk
+++ /dev/null
@@ -1 +0,0 @@
-ORBER_VSN = 3.8.3
diff --git a/lib/os_mon/doc/src/Makefile b/lib/os_mon/doc/src/Makefile
index 91c7ae7bc3..354f8ed26b 100644
--- a/lib/os_mon/doc/src/Makefile
+++ b/lib/os_mon/doc/src/Makefile
@@ -1,8 +1,8 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 1997-2017. All Rights Reserved.
+#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -14,7 +14,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
+#
# %CopyrightEnd%
#
include $(ERL_TOP)/make/target.mk
@@ -43,16 +43,14 @@ XML_REF3_FILES = cpu_sup.xml \
os_sup.xml \
nteventlog.xml
-XML_REF6_FILES = os_mon_app.xml
+XML_REF6_FILES = os_mon_app.xml
-XML_PART_FILES = part_notes.xml
+XML_PART_FILES =
XML_CHAPTER_FILES = notes.xml
BOOK_FILES = book.xml
-GIF_FILES = \
- note.gif \
- warning.gif
+GIF_FILES =
XML_FILES = \
$(BOOK_FILES) $(XML_CHAPTER_FILES) \
@@ -74,9 +72,9 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
+XML_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -96,17 +94,18 @@ man: $(MAN3_FILES) $(MAN6_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-debug opt:
+debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
+ rm -f errs core *~
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
@@ -122,4 +121,3 @@ release_docs_spec: docs
$(INSTALL_DATA) $(MAN6DIR)/* "$(RELEASE_PATH)/man/man6"
release_spec:
-
diff --git a/lib/os_mon/doc/src/fascicules.xml b/lib/os_mon/doc/src/fascicules.xml
deleted file mode 100644
index fadd37eefb..0000000000
--- a/lib/os_mon/doc/src/fascicules.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/os_mon/doc/src/note.gif b/lib/os_mon/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/os_mon/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/os_mon/doc/src/notes.xml b/lib/os_mon/doc/src/notes.xml
index df4151147c..0910b3c0f3 100644
--- a/lib/os_mon/doc/src/notes.xml
+++ b/lib/os_mon/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2016</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,69 @@
</header>
<p>This document describes the changes made to the OS_Mon application.</p>
+<section><title>Os_Mon 2.4.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Os_Mon 2.4.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix <c>disksup</c> to handle mount paths with spaces in
+ them.</p>
+ <p>
+ Own Id: OTP-14513</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Os_Mon 2.4.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Os_Mon 2.4.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ On macOS 10.13 (High Sierra), disksup could not grab
+ information for any disks that used the new APFS file
+ system. That has been corrected.</p>
+ <p>
+ Own Id: OTP-14560 Aux Id: ERL-461 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Os_Mon 2.4.2</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/os_mon/doc/src/os_mon_mib.xml b/lib/os_mon/doc/src/os_mon_mib.xml
index dcf3649876..e995bf3de1 100644
--- a/lib/os_mon/doc/src/os_mon_mib.xml
+++ b/lib/os_mon/doc/src/os_mon_mib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2016</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -35,7 +35,10 @@
<p>Functions for loading and unloading the OTP-OS-MON-MIB into/from
an SNMP agent. The instrumentation of the OTP-OS-MON-MIB uses
Mnesia, hence Mnesia must be started prior to loading
- the OTP-OS-MON-MIB.</p>
+ the OTP-OS-MON-MIB.</p>
+ <warning>
+ <p>This module has been deprecated and will be removed in a furture release.</p>
+ </warning>
</description>
<funcs>
<func>
diff --git a/lib/os_mon/doc/src/part_notes.xml b/lib/os_mon/doc/src/part_notes.xml
deleted file mode 100644
index 364178acc3..0000000000
--- a/lib/os_mon/doc/src/part_notes.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>OS_Mon Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p>The operating system monitor, OS_Mon, provides services for
- monitoring CPU load, disk usage, memory usage and OS messages.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/os_mon/doc/src/user_guide.gif b/lib/os_mon/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/os_mon/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/os_mon/doc/src/warning.gif b/lib/os_mon/doc/src/warning.gif
deleted file mode 100644
index 96af52360e..0000000000
--- a/lib/os_mon/doc/src/warning.gif
+++ /dev/null
Binary files differ
diff --git a/lib/os_mon/src/cpu_sup.erl b/lib/os_mon/src/cpu_sup.erl
index e758b63d19..81e049ef22 100644
--- a/lib/os_mon/src/cpu_sup.erl
+++ b/lib/os_mon/src/cpu_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -244,7 +244,7 @@ get_uint32_measurement(Request, #internal{os_type = {unix, Sys}}) when Sys == ir
%% Get the load average using uptime.
%% "8:01pm up 2 days, 22:12, 4 users, load average: 0.70, 0.58, 0.43"
D = os:cmd("uptime") -- "\n",
- Avg = lists:reverse(hd(string:tokens(lists:reverse(D), ":"))),
+ Avg = lists:reverse(hd(string:lexemes(lists:reverse(D), ":"))),
{ok, [L1, L5, L15], _} = io_lib:fread("~f, ~f, ~f", Avg),
case Request of
?avg1 -> sunify(L1);
diff --git a/lib/os_mon/src/disksup.erl b/lib/os_mon/src/disksup.erl
index 492e4814da..5118d807e1 100644
--- a/lib/os_mon/src/disksup.erl
+++ b/lib/os_mon/src/disksup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,7 @@
terminate/2, code_change/3]).
%% Other exports
--export([format_status/2]).
+-export([format_status/2, parse_df/2]).
-record(state, {threshold, timeout, os, diskdata = [],port}).
@@ -285,7 +285,7 @@ check_disk_space({unix, sunos4}, Port, Threshold) ->
Result = my_cmd("df", Port),
check_disks_solaris(skip_to_eol(Result), Threshold);
check_disk_space({unix, darwin}, Port, Threshold) ->
- Result = my_cmd("/bin/df -i -k -t ufs,hfs", Port),
+ Result = my_cmd("/bin/df -i -k -t ufs,hfs,apfs", Port),
check_disks_susv3(skip_to_eol(Result), Threshold).
% This code works for Linux and FreeBSD as well
@@ -294,8 +294,8 @@ check_disks_solaris("", _Threshold) ->
check_disks_solaris("\n", _Threshold) ->
[];
check_disks_solaris(Str, Threshold) ->
- case io_lib:fread("~s~d~d~d~d%~s", Str) of
- {ok, [_FS, KB, _Used, _Avail, Cap, MntOn], RestStr} ->
+ case parse_df(Str, posix) of
+ {ok, {KB, Cap, MntOn}, RestStr} ->
if
Cap >= Threshold ->
set_alarm({disk_almost_full, MntOn}, []);
@@ -308,14 +308,102 @@ check_disks_solaris(Str, Threshold) ->
check_disks_solaris(skip_to_eol(Str),Threshold)
end.
+%% @private
+%% @doc Predicate to take a word from the input string until a space or
+%% a percent '%' sign (the Capacity field is followed by a %)
+parse_df_is_not_space($ ) -> false;
+parse_df_is_not_space($%) -> false;
+parse_df_is_not_space(_) -> true.
+
+%% @private
+%% @doc Predicate to take spaces away from string. Stops on a non-space
+parse_df_is_space($ ) -> true;
+parse_df_is_space(_) -> false.
+
+%% @private
+%% @doc Predicate to consume remaining characters until end of line.
+parse_df_is_not_eol($\r) -> false;
+parse_df_is_not_eol($\n) -> false;
+parse_df_is_not_eol(_) -> true.
+
+%% @private
+%% @doc Trims leading non-spaces (the word) from the string then trims spaces.
+parse_df_skip_word(Input) ->
+ Remaining = lists:dropwhile(fun parse_df_is_not_space/1, Input),
+ lists:dropwhile(fun parse_df_is_space/1, Remaining).
+
+%% @private
+%% @doc Takes all non-spaces and then drops following spaces.
+parse_df_take_word(Input) ->
+ {Word, Remaining0} = lists:splitwith(fun parse_df_is_not_space/1, Input),
+ Remaining1 = lists:dropwhile(fun parse_df_is_space/1, Remaining0),
+ {Word, Remaining1}.
+
+%% @private
+%% @doc Takes all non-spaces and then drops the % after it and the spaces.
+parse_df_take_word_percent(Input) ->
+ {Word, Remaining0} = lists:splitwith(fun parse_df_is_not_space/1, Input),
+ %% Drop the leading % or do nothing
+ Remaining1 = case Remaining0 of
+ [$% | R1] -> R1;
+ _ -> Remaining0 % Might be no % or empty list even
+ end,
+ Remaining2 = lists:dropwhile(fun parse_df_is_space/1, Remaining1),
+ {Word, Remaining2}.
+
+%% @private
+%% @doc Given a line of 'df' POSIX/SUSv3 output split it into fields:
+%% a string (mounted device), 4 integers (kilobytes, used, available
+%% and capacity), skip % sign, (optionally for susv3 can also skip IUsed, IFree
+%% and ICap% fields) then take remaining characters as the mount path
+-spec parse_df(string(), posix | susv3) ->
+ {error, parse_df} | {ok, {integer(), integer(), list()}, string()}.
+parse_df(Input0, Flavor) ->
+ %% Format of Posix/Linux df output looks like Header + Lines
+ %% Filesystem 1024-blocks Used Available Capacity Mounted on
+ %% udev 2467108 0 2467108 0% /dev
+ Input1 = parse_df_skip_word(Input0), % skip device path field
+ {KbStr, Input2} = parse_df_take_word(Input1), % take Kb field
+ Input3 = parse_df_skip_word(Input2), % skip Used field
+ Input4 = parse_df_skip_word(Input3), % skip Avail field
+
+ % take Capacity% field; drop a % sign following the capacity
+ {CapacityStr, Input5} = parse_df_take_word_percent(Input4),
+
+ %% Format of OS X/SUSv3 df looks similar to POSIX but has 3 extra columns
+ %% Filesystem 1024-blocks Used Available Capacity iused ifree %iused Mounted
+ %% /dev/disk1 243949060 2380 86690680 65% 2029724 37555 0% /
+ Input6 = case Flavor of
+ posix -> Input5;
+ susv3 -> % there are 3 extra integers we want to skip
+ Input5a = parse_df_skip_word(Input5), % skip IUsed field
+ Input5b = parse_df_skip_word(Input5a), % skip IFree field
+ %% skip the value of ICap + '%' field
+ {_, Input5c} = parse_df_take_word_percent(Input5b),
+ Input5c
+ end,
+
+ % path is the remaining string till end of line
+ {MountPath, Input7} = lists:splitwith(fun parse_df_is_not_eol/1, Input6),
+ % Trim the newlines
+ Remaining = lists:dropwhile(fun(X) -> not parse_df_is_not_eol(X) end,
+ Input7),
+ try
+ Kb = erlang:list_to_integer(KbStr),
+ Capacity = erlang:list_to_integer(CapacityStr),
+ {ok, {Kb, Capacity, MountPath}, Remaining}
+ catch error:badarg ->
+ {error, parse_df}
+ end.
+
% Parse per SUSv3 specification, notably recent OS X
check_disks_susv3("", _Threshold) ->
[];
check_disks_susv3("\n", _Threshold) ->
[];
check_disks_susv3(Str, Threshold) ->
- case io_lib:fread("~s~d~d~d~d%~d~d~d%~s", Str) of
- {ok, [_FS, KB, _Used, _Avail, Cap, _IUsed, _IFree, _ICap, MntOn], RestStr} ->
+ case parse_df(Str, susv3) of
+ {ok, {KB, Cap, MntOn}, RestStr} ->
if
Cap >= Threshold ->
set_alarm({disk_almost_full, MntOn}, []);
diff --git a/lib/os_mon/src/memsup.erl b/lib/os_mon/src/memsup.erl
index 0a9a883390..9d6447430d 100644
--- a/lib/os_mon/src/memsup.erl
+++ b/lib/os_mon/src/memsup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -705,7 +705,7 @@ get_os_wordsize_with_uname() ->
_ -> 32
end.
-clean_string(String) -> lists:flatten(string:tokens(String,"\r\n\t ")).
+clean_string(String) -> lists:flatten(string:lexemes(String,[[$\r,$\n]|"\n\t "])).
%%--Replying to pending clients-----------------------------------------
diff --git a/lib/os_mon/test/cpu_sup_SUITE.erl b/lib/os_mon/test/cpu_sup_SUITE.erl
index 7122d23503..ba28f31f26 100644
--- a/lib/os_mon/test/cpu_sup_SUITE.erl
+++ b/lib/os_mon/test/cpu_sup_SUITE.erl
@@ -122,19 +122,19 @@ util_api(Config) when is_list(Config) ->
%% util([])
{all, Busy1, NonBusy1, []} = cpu_sup:util([]),
- 100.00 = Busy1 + NonBusy1,
+ true = tiny_diff(100.00, Busy1 + NonBusy1),
%% util([detailed])
{Cpus2, Busy2, NonBusy2, []} = cpu_sup:util([detailed]),
true = lists:all(fun(X) -> is_integer(X) end, Cpus2),
true = lists:all(BusyP, Busy2),
true = lists:all(NonBusyP, NonBusy2),
- 100.00 = lists:foldl(Sum,0,Busy2)+lists:foldl(Sum,0,NonBusy2),
+ true = tiny_diff(100.00, lists:foldl(Sum,0,Busy2)+lists:foldl(Sum,0,NonBusy2)),
%% util([per_cpu])
[{Cpu3, Busy3, NonBusy3, []}|_] = cpu_sup:util([per_cpu]),
true = is_integer(Cpu3),
- 100.00 = Busy3 + NonBusy3,
+ true = tiny_diff(100.00, Busy3 + NonBusy3),
%% util([detailed, per_cpu])
[{Cpu4, Busy4, NonBusy4, []}|_] =
@@ -142,7 +142,7 @@ util_api(Config) when is_list(Config) ->
true = is_integer(Cpu4),
true = lists:all(BusyP, Busy2),
true = lists:all(NonBusyP, NonBusy2),
- 100.00 = lists:foldl(Sum,0,Busy4)+lists:foldl(Sum,0,NonBusy4),
+ true = tiny_diff(100.00, lists:foldl(Sum,0,Busy4)+lists:foldl(Sum,0,NonBusy4)),
%% bad util/1 calls
{'EXIT',{badarg,_}} = (catch cpu_sup:util(detailed)),
@@ -150,6 +150,9 @@ util_api(Config) when is_list(Config) ->
ok.
+tiny_diff(A, B) ->
+ (abs(A - B) < 1.0e-11).
+
-define(SPIN_TIME, 1000).
%% Test utilization values
diff --git a/lib/os_mon/test/disksup_SUITE.erl b/lib/os_mon/test/disksup_SUITE.erl
index ad61985014..fe27ea9046 100644
--- a/lib/os_mon/test/disksup_SUITE.erl
+++ b/lib/os_mon/test/disksup_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@
-export([port/1]).
-export([terminate/1, unavailable/1, restart/1]).
-export([otp_5910/1]).
--export([posix_only/1]).
+-export([posix_only/1, parse_df_output_posix/1, parse_df_output_susv3/1]).
init_per_suite(Config) when is_list(Config) ->
ok = application:start(os_mon),
@@ -59,7 +59,8 @@ suite() ->
all() ->
Bugs = [otp_5910],
- Always = [api, config, alarm, port, posix_only, unavailable] ++ Bugs,
+ Always = [api, config, alarm, port, posix_only, unavailable,
+ parse_df_output_posix, parse_df_output_susv3] ++ Bugs,
case test_server:os_type() of
{unix, _OSname} -> Always;
{win32, _OSname} -> Always;
@@ -413,3 +414,36 @@ get_disk_data([{"none",0,0}=E]) -> [E];
get_disk_data([{_,_,0}|Es]) -> get_disk_data(Es);
get_disk_data([E|Es]) -> [E|get_disk_data(Es)];
get_disk_data([]) -> [].
+
+%% @doc Test various expected inputs to 'df' command output (Linux/POSIX)
+parse_df_output_posix(Config) when is_list(Config) ->
+ PosixHdr = "Filesystem 1K-blocks Used Available Use% Mounted on\n",
+ {error, _} = disksup:parse_df(PosixHdr, posix),
+ {error, _} = disksup:parse_df("", posix),
+ {error, _} = disksup:parse_df("\n\n", posix),
+
+ %% Have a simple example with no funny spaces in mount path
+ Posix1 = "tmpfs 498048 7288 490760 2% /run\n",
+ {ok, {498048, 2, "/run"}, ""} = disksup:parse_df(Posix1, posix),
+
+ %% Have a mount path with some spaces in it
+ Posix2 = "tmpfs 498048 7288 490760 2% /spaces 1 2\n",
+ {ok, {498048, 2, "/spaces 1 2"}, ""} = disksup:parse_df(Posix2, posix).
+
+%% @doc Test various expected inputs to 'df' command output (Darwin/SUSv3)
+parse_df_output_susv3(Config) when is_list(Config) ->
+ DarwinHdr = "Filesystem 1024-blocks Used Available Capacity " ++
+ "iused ifree %iused Mounted on",
+ {error, _} = disksup:parse_df(DarwinHdr, susv3),
+ {error, _} = disksup:parse_df("", susv3),
+ {error, _} = disksup:parse_df("\n\n", susv3),
+
+ %% Have a simple example with no funny spaces in mount path
+ Darwin1 = "/dev/disk1 243949060 157002380 86690680 65% 2029724 " ++
+ "4292937555 0% /\n",
+ {ok, {243949060, 65, "/"}, ""} = disksup:parse_df(Darwin1, susv3),
+
+ %% Have a mount path with some spaces in it
+ Darwin2 = "/dev/disk1 243949060 157002380 86690680 65% 2029724 " ++
+ "4292937555 0% /spaces 1 2\n",
+ {ok, {243949060, 65, "/spaces 1 2"}, ""} = disksup:parse_df(Darwin2, susv3).
diff --git a/lib/os_mon/vsn.mk b/lib/os_mon/vsn.mk
index 59a3d9dee4..0c62c3db35 100644
--- a/lib/os_mon/vsn.mk
+++ b/lib/os_mon/vsn.mk
@@ -1 +1 @@
-OS_MON_VSN = 2.4.2
+OS_MON_VSN = 2.4.6
diff --git a/lib/otp_mibs/doc/src/Makefile b/lib/otp_mibs/doc/src/Makefile
index 62698b9300..22c3c127ac 100644
--- a/lib/otp_mibs/doc/src/Makefile
+++ b/lib/otp_mibs/doc/src/Makefile
@@ -1,8 +1,8 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2003-2016. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 2003-2018. All Rights Reserved.
+#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -14,7 +14,7 @@
# 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%
#
@@ -38,7 +38,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
XML_APPLICATION_FILES = ref_man.xml
XML_REF3_FILES = otp_mib.xml
-XML_PART_FILES = part.xml part_notes.xml
+XML_PART_FILES = part.xml
XML_CHAPTER_FILES = \
introduction.xml \
mibs.xml \
@@ -50,7 +50,7 @@ XML_FILES = \
$(BOOK_FILES) $(XML_CHAPTER_FILES) \
$(XML_PART_FILES) $(XML_REF3_FILES) $(XML_APPLICATION_FILES)
-GIF_FILES = note.gif
+GIF_FILES =
# ----------------------------------------------------
@@ -93,9 +93,10 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
+ rm -f errs core *~
# ----------------------------------------------------
# Release Target
@@ -113,4 +114,3 @@ release_docs_spec: docs
$(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
-
diff --git a/lib/otp_mibs/doc/src/fascicules.xml b/lib/otp_mibs/doc/src/fascicules.xml
deleted file mode 100644
index c075478967..0000000000
--- a/lib/otp_mibs/doc/src/fascicules.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
-
diff --git a/lib/otp_mibs/doc/src/note.gif b/lib/otp_mibs/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/otp_mibs/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/otp_mibs/doc/src/notes.xml b/lib/otp_mibs/doc/src/notes.xml
index dbd2f47ffb..443f08f1e1 100644
--- a/lib/otp_mibs/doc/src/notes.xml
+++ b/lib/otp_mibs/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2016</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,52 @@
<p>This document describes the changes made to the OTP_Mibs
application.</p>
+<section><title>Otp_Mibs 1.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Otp_Mibs 1.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The otp_mibs application has been deprecated and will be
+ removed in a future release.</p>
+ <p>
+ Own Id: OTP-15141</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Otp_Mibs 1.1.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Otp_Mibs 1.1.1</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/otp_mibs/doc/src/otp_mib.xml b/lib/otp_mibs/doc/src/otp_mib.xml
index 681ce9fa2d..530c529c69 100644
--- a/lib/otp_mibs/doc/src/otp_mib.xml
+++ b/lib/otp_mibs/doc/src/otp_mib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2003</year><year>2016</year>
+ <year>2003</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,7 +34,10 @@
<p>The SNMP application should be used to start an SNMP agent. Then
the API functions below can be used to load/unload the OTP-MIB
into/from the agent. The instrumentation of the OTP-MIB uses
- Mnesia, hence Mnesia must be started prior to loading the OTP-MIB.</p>
+ Mnesia, hence Mnesia must be started prior to loading the OTP-MIB.</p>
+ <warning>
+ <p>This application has been deprecated and will be removed in a furture release.</p>
+ </warning>
</description>
<funcs>
<func>
diff --git a/lib/otp_mibs/doc/src/part_notes.xml b/lib/otp_mibs/doc/src/part_notes.xml
deleted file mode 100644
index 5c03d28720..0000000000
--- a/lib/otp_mibs/doc/src/part_notes.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>OTP_Mibs Release Notes</title>
- <prepared>Ingela Anderton Andin</prepared>
- <docno></docno>
- <date>2004-09-07</date>
- <rev></rev>
- </header>
- <description>
- <p>The <em>OTP_Mibs</em> application provides an SNMP management
- information base for Erlang nodes.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
-
diff --git a/lib/otp_mibs/src/otp_mib.erl b/lib/otp_mibs/src/otp_mib.erl
index 1431818be4..ca868f2817 100644
--- a/lib/otp_mibs/src/otp_mib.erl
+++ b/lib/otp_mibs/src/otp_mib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,6 +36,9 @@
%% Exported for internal use via rpc
-export([get_erl_node/1, get_appls/1]).
+-deprecated([{load,1,eventually},
+ {unload,1,eventually}]).
+
%% Shadow tables
-record(erlNodeTable,
{erlNodeId, erlNodeName, erlNodeMachine, erlNodeVersion,
diff --git a/lib/otp_mibs/vsn.mk b/lib/otp_mibs/vsn.mk
index 7a793007ee..1b0444afcd 100644
--- a/lib/otp_mibs/vsn.mk
+++ b/lib/otp_mibs/vsn.mk
@@ -1,4 +1,4 @@
-OTP_MIBS_VSN = 1.1.1
+OTP_MIBS_VSN = 1.2.1
# Note: The branch 'otp_mibs' is defunct as of otp_mibs-1.0.4 and
# should NOT be used again.
diff --git a/lib/parsetools/doc/src/Makefile b/lib/parsetools/doc/src/Makefile
index 8b03ed0fc7..2e8b232902 100644
--- a/lib/parsetools/doc/src/Makefile
+++ b/lib/parsetools/doc/src/Makefile
@@ -1,8 +1,8 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
+#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -14,7 +14,7 @@
# 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%
#
@@ -39,7 +39,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
XML_APPLICATION_FILES = ref_man.xml
XML_REF3_FILES = yecc.xml leex.xml
-XML_PART_FILES = part_notes.xml
+XML_PART_FILES =
XML_CHAPTER_FILES = notes.xml
BOOK_FILES = book.xml
@@ -48,8 +48,7 @@ XML_FILES = \
$(BOOK_FILES) $(XML_CHAPTER_FILES) \
$(XML_PART_FILES) $(XML_REF3_FILES) $(XML_APPLICATION_FILES)
-GIF_FILES = \
- note.gif
+GIF_FILES =
XML_HTML_FILES = \
notes_history.xml
@@ -69,10 +68,10 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
+XML_FLAGS +=
+DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -90,6 +89,7 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
@@ -98,11 +98,11 @@ man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-debug opt:
+debug opt:
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
@@ -117,4 +117,3 @@ release_docs_spec: docs
release_spec:
-
diff --git a/lib/parsetools/doc/src/fascicules.xml b/lib/parsetools/doc/src/fascicules.xml
deleted file mode 100644
index fadd37eefb..0000000000
--- a/lib/parsetools/doc/src/fascicules.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/parsetools/doc/src/note.gif b/lib/parsetools/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/parsetools/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/parsetools/doc/src/notes.xml b/lib/parsetools/doc/src/notes.xml
index 3fa7169f50..f8cd9b972d 100644
--- a/lib/parsetools/doc/src/notes.xml
+++ b/lib/parsetools/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2017</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,51 @@
</header>
<p>This document describes the changes made to the Parsetools application.</p>
+<section><title>Parsetools 2.1.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Parsetools 2.1.7</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Calls to <c>erlang:get_stacktrace()</c> are removed.
+ </p>
+ <p>
+ Own Id: OTP-14861</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Parsetools 2.1.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Warnings about unused functions in <c>leexinc.hrl</c>
+ are suppressed. </p>
+ <p>
+ Own Id: OTP-14697</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Parsetools 2.1.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/parsetools/doc/src/part_notes.xml b/lib/parsetools/doc/src/part_notes.xml
deleted file mode 100644
index 5e0824e839..0000000000
--- a/lib/parsetools/doc/src/part_notes.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>PARSETOOLS Release Notes</title>
- <prepared>Carl Velin</prepared>
- <docno></docno>
- <date>1997-04-28</date>
- <rev>1.0</rev>
- <file>part_notes.sgml</file>
- </header>
- <description>
- <p>The <em>Parsetools</em> application contains utilities for
- parsing and scanning. Yecc is an <term id="LALR-1"></term>parser
- generator for Erlang, similar to yacc. Yecc takes a <term
- id="BNF"></term>grammar definition as input, and produces Erlang
- code for a parser as output. Leex is a regular expression based
- lexical analyzer generator for Erlang, similar to lex or flex.</p>
- <p>There are also release notes for
- <seealso marker="notes_history">older versions</seealso>.</p>
- </description>
- <xi:lude href="notes.xml"/>
-</part>
-
diff --git a/lib/parsetools/doc/src/user_guide.gif b/lib/parsetools/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/parsetools/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/parsetools/doc/src/warning.gif b/lib/parsetools/doc/src/warning.gif
deleted file mode 100644
index 96af52360e..0000000000
--- a/lib/parsetools/doc/src/warning.gif
+++ /dev/null
Binary files differ
diff --git a/lib/parsetools/include/leexinc.hrl b/lib/parsetools/include/leexinc.hrl
index b4449607cb..2a74c252ff 100644
--- a/lib/parsetools/include/leexinc.hrl
+++ b/lib/parsetools/include/leexinc.hrl
@@ -272,6 +272,8 @@ skip_cont(Rest, Line, {skip_token,Push}, Error) ->
skip_cont(Rest, Line, {error,_S}, Error) ->
skip_tokens(yystate(), Rest, Line, Rest, 0, Line, Error, reject, 0).
+-compile({nowarn_unused_function, [yyrev/1, yyrev/2, yypre/2, yysuf/2]}).
+
yyrev(List) -> lists:reverse(List).
yyrev(List, Tail) -> lists:reverse(List, Tail).
yypre(List, N) -> lists:sublist(List, N).
@@ -282,6 +284,8 @@ yysuf(List, N) -> lists:nthtail(N, List).
%% Line has been updated with respect to newlines in the prefix of
%% Chars consisting of (TokenLength - AcceptLength) characters.
+-compile({nowarn_unused_function, adjust_line/4}).
+
adjust_line(N, N, _Cs, L) -> L;
adjust_line(T, A, [$\n|Cs], L) ->
adjust_line(T-1, A, Cs, L-1);
diff --git a/lib/parsetools/include/yeccpre.hrl b/lib/parsetools/include/yeccpre.hrl
index 91d6cd49a6..562f17c19e 100644
--- a/lib/parsetools/include/yeccpre.hrl
+++ b/lib/parsetools/include/yeccpre.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -56,8 +56,7 @@ return_error(Line, Message) ->
yeccpars0(Tokens, Tzr, State, States, Vstack) ->
try yeccpars1(Tokens, Tzr, State, States, Vstack)
catch
- error: Error ->
- Stacktrace = erlang:get_stacktrace(),
+ error: Error: Stacktrace ->
try yecc_error_type(Error, Stacktrace) of
Desc ->
erlang:raise(error, {yecc_bug, ?CODE_VERSION, Desc},
diff --git a/lib/parsetools/src/leex.erl b/lib/parsetools/src/leex.erl
index e2e7d7359f..8a4a5e8d86 100644
--- a/lib/parsetools/src/leex.erl
+++ b/lib/parsetools/src/leex.erl
@@ -37,7 +37,6 @@
-import(lists, [member/2,reverse/1,sort/1,delete/2,
keysort/2,keydelete/3,
map/2,foldl/3,foreach/2,flatmap/2]).
--import(string, [substr/2,substr/3,span/2]).
-import(ordsets, [is_element/2,add_element/2,union/2]).
-import(orddict, [store/3]).
@@ -251,10 +250,10 @@ is_filename(T) ->
shorten_filename(Name0) ->
{ok,Cwd} = file:get_cwd(),
- case lists:prefix(Cwd, Name0) of
- false -> Name0;
- true ->
- case lists:nthtail(length(Cwd), Name0) of
+ case string:prefix(Name0, Cwd) of
+ nomatch -> Name0;
+ Rest ->
+ case unicode:characters_to_list(Rest) of
"/"++N -> N;
N -> N
end
@@ -490,12 +489,9 @@ parse_rules_end(_, NextLine, REAs, As, St) ->
%% action has been read. Keep track of line number.
collect_rule(Ifile, Chars, L0) ->
- %% Erlang strings are 1 based, but re 0 :-(
- {match,[{St0,Len}|_]} = re:run(Chars, "[^ \t\r\n]+", [unicode]),
- St = St0 + 1,
- %%io:fwrite("RE = ~p~n", [substr(Chars, St, Len)]),
- case collect_action(Ifile, substr(Chars, St+Len), L0, []) of
- {ok,[{':',_}|Toks],L1} -> {ok,substr(Chars, St, Len),Toks,L1};
+ {RegExp,Rest} = string:take(Chars, " \t\r\n", true),
+ case collect_action(Ifile, Rest, L0, []) of
+ {ok,[{':',_}|Toks],L1} -> {ok,RegExp,Toks,L1};
{ok,_,_} -> {error,{L0,leex,bad_rule}};
{eof,L1} -> {error,{L1,leex,bad_rule}};
{error,E,_} -> {error,E}
@@ -549,7 +545,7 @@ var_used(Name, Toks) ->
parse_rule_regexp(RE0, [{M,Exp}|Ms], St) ->
Split= re:split(RE0, "\\{" ++ M ++ "\\}", [{return,list},unicode]),
- RE1 = string:join(Split, Exp),
+ RE1 = lists:append(lists:join(Exp, Split)),
parse_rule_regexp(RE1, Ms, St);
parse_rule_regexp(RE, [], St) ->
%%io:fwrite("RE = ~p~n", [RE]),
@@ -589,9 +585,9 @@ nextline(Ifile, L, St) ->
eof -> {eof,L};
{error, _} -> add_error({L+1, leex, cannot_parse}, St);
Chars ->
- case substr(Chars, span(Chars, " \t\n")+1) of
- [$%|_Rest] -> nextline(Ifile, L+1, St);
- [] -> nextline(Ifile, L+1, St);
+ case string:take(Chars, " \t\n") of
+ {_, [$%|_Rest]} -> nextline(Ifile, L+1, St);
+ {_, []} -> nextline(Ifile, L+1, St);
_Other -> {ok,Chars,L+1}
end
end.
@@ -824,7 +820,7 @@ re_char_class(Cs, Cc, _) -> {reverse(Cc),Cs}. % Preserve order
%% posix_cc("space" ++ Cs) -> {space,Cs};
%% posix_cc("upper" ++ Cs) -> {upper,Cs};
%% posix_cc("xdigit" ++ Cs) -> {xdigit,Cs};
-%% posix_cc(Cs) -> parse_error({posix_cc,substr(Cs, 1, 5)}).
+%% posix_cc(Cs) -> parse_error({posix_cc,string:slice(Cs, 0, 5)}).
escape_char($n) -> $\n; % \n = LF
escape_char($r) -> $\r; % \r = CR
@@ -863,7 +859,7 @@ escape_char(C) -> C. % Pass it straight through
%% re_number(Cs, Acc) -> {Acc,Cs}.
string_between(Cs1, Cs2) ->
- substr(Cs1, 1, length(Cs1)-length(Cs2)).
+ string:slice(Cs1, 0, string:length(Cs1)-string:length(Cs2)).
%% We use standard methods, Thompson's construction and subset
%% construction, to create first an NFA and then a DFA from the
@@ -1343,7 +1339,7 @@ out_file(Ifile, Ofile, St, DFA, DF, Actions, Code, L) ->
eof -> output_file_directive(Ofile, St#leex.ifile, L);
{error, _} -> add_error(St#leex.ifile, {L, leex, cannot_parse}, St);
Line ->
- case substr(Line, 1, 5) of
+ case string:slice(Line, 0, 5) of
"##mod" -> out_module(Ofile, St);
"##cod" -> out_erlang_code(Ofile, St, Code, L);
"##dfa" -> out_dfa(Ofile, St, DFA, Code, DF, L);
@@ -1523,7 +1519,7 @@ prep_out_actions(As) ->
Name = list_to_atom(lists:concat([yyaction_,A])),
[Chars,Len,Line,_,_] = Vars,
Args = [V || V <- [Chars,Len,Line], V =/= "_"],
- ArgsChars = string:join(Args, ", "),
+ ArgsChars = lists:join(", ", Args),
{A,Code,Vars,Name,Args,ArgsChars}
end, As).
diff --git a/lib/parsetools/src/yecc.erl b/lib/parsetools/src/yecc.erl
index 36e33b52a4..3343a4282b 100644
--- a/lib/parsetools/src/yecc.erl
+++ b/lib/parsetools/src/yecc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -365,10 +365,10 @@ is_filename(T) ->
shorten_filename(Name0) ->
{ok,Cwd} = file:get_cwd(),
- case lists:prefix(Cwd, Name0) of
- false -> Name0;
- true ->
- case lists:nthtail(length(Cwd), Name0) of
+ case string:prefix(Name0, Cwd) of
+ nomatch -> Name0;
+ Rest ->
+ case unicode:characters_to_list(Rest) of
"/"++N -> N;
N -> N
end
@@ -455,10 +455,14 @@ os_process_size() ->
case os:type() of
{unix, sunos} ->
Size = os:cmd("ps -o vsz -p " ++ os:getpid() ++ " | tail -1"),
- list_to_integer(lib:nonl(Size));
+ list_to_integer(nonl(Size));
_ ->
0
- end.
+ end.
+
+nonl([$\n]) -> [];
+nonl([]) -> [];
+nonl([H|T]) -> [H|nonl(T)].
timeit(Name, Fun, St0) ->
Time = runtime,
@@ -2196,8 +2200,8 @@ output_reduce(St0, State, Terminal,
St20;
true ->
Ns = "Nss",
- Tmp = string:join(lists:duplicate(NmbrOfDaughters - 1, "_"),
- ","),
+ Tmp = lists:join(",",
+ lists:duplicate(NmbrOfDaughters - 1, "_")),
fwrite(St20, <<" [~s|Nss] = Ss,\n">>, [Tmp])
end,
St40 = case tokens(RuleNmbr, St30) of
diff --git a/lib/parsetools/src/yeccparser.erl b/lib/parsetools/src/yeccparser.erl
index 6f6f66d56c..0deecc7879 100644
--- a/lib/parsetools/src/yeccparser.erl
+++ b/lib/parsetools/src/yeccparser.erl
@@ -17,7 +17,7 @@ anno_of(Token) ->
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -72,8 +72,7 @@ return_error(Line, Message) ->
yeccpars0(Tokens, Tzr, State, States, Vstack) ->
try yeccpars1(Tokens, Tzr, State, States, Vstack)
catch
- error: Error ->
- Stacktrace = erlang:get_stacktrace(),
+ error: Error: Stacktrace ->
try yecc_error_type(Error, Stacktrace) of
Desc ->
erlang:raise(error, {yecc_bug, ?CODE_VERSION, Desc},
@@ -167,21 +166,20 @@ yecctoken_location(Token) ->
end.
-compile({nowarn_unused_function, yecctoken2string/1}).
-yecctoken2string({atom, _, A}) -> io_lib:write(A);
+yecctoken2string({atom, _, A}) -> io_lib:write_atom(A);
yecctoken2string({integer,_,N}) -> io_lib:write(N);
yecctoken2string({float,_,F}) -> io_lib:write(F);
yecctoken2string({char,_,C}) -> io_lib:write_char(C);
yecctoken2string({var,_,V}) -> io_lib:format("~s", [V]);
yecctoken2string({string,_,S}) -> io_lib:write_string(S);
yecctoken2string({reserved_symbol, _, A}) -> io_lib:write(A);
-yecctoken2string({_Cat, _, Val}) -> io_lib:format("~p",[Val]);
+yecctoken2string({_Cat, _, Val}) -> io_lib:format("~tp", [Val]);
yecctoken2string({dot, _}) -> "'.'";
-yecctoken2string({'$end', _}) ->
- [];
+yecctoken2string({'$end', _}) -> [];
yecctoken2string({Other, _}) when is_atom(Other) ->
- io_lib:write(Other);
+ io_lib:write_atom(Other);
yecctoken2string(Other) ->
- io_lib:write(Other).
+ io_lib:format("~tp", [Other]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/parsetools/test/yecc_SUITE.erl b/lib/parsetools/test/yecc_SUITE.erl
index a7166b91ed..715e50c301 100644
--- a/lib/parsetools/test/yecc_SUITE.erl
+++ b/lib/parsetools/test/yecc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1674,8 +1674,7 @@ format_error(Message) ->
yeccpars0(Tokens, MFA) ->
try yeccpars1(Tokens, MFA, 0, [], [])
catch
- error: Error ->
- Stacktrace = erlang:get_stacktrace(),
+ error: Error : Stacktrace ->
try yecc_error_type(Error, Stacktrace) of
{syntax_error, Token} ->
yeccerror(Token);
diff --git a/lib/parsetools/vsn.mk b/lib/parsetools/vsn.mk
index 502ca00a47..1a5201ce5d 100644
--- a/lib/parsetools/vsn.mk
+++ b/lib/parsetools/vsn.mk
@@ -1 +1 @@
-PARSETOOLS_VSN = 2.1.5
+PARSETOOLS_VSN = 2.1.8
diff --git a/lib/public_key/asn1/PKCS-7.asn1 b/lib/public_key/asn1/PKCS-7.asn1
index e76f928acb..e9c188be39 100644
--- a/lib/public_key/asn1/PKCS-7.asn1
+++ b/lib/public_key/asn1/PKCS-7.asn1
@@ -124,7 +124,7 @@ SignerInfoAuthenticatedAttributes ::= CHOICE {
-- Also defined in X.509
-- Redeclared here as a parameterized type
-AlgorithmIdentifierPKSC-7 {ALGORITHM:IOSet} ::= SEQUENCE {
+AlgorithmIdentifierPKCS-7 {ALGORITHM:IOSet} ::= SEQUENCE {
algorithm ALGORITHM.&id({IOSet}),
parameters ALGORITHM.&Type({IOSet}{@algorithm}) OPTIONAL
}
@@ -146,21 +146,21 @@ CRLSequence ::=
SEQUENCE OF CertificateList
ContentEncryptionAlgorithmIdentifier ::=
- AlgorithmIdentifierPKSC-7 {{ContentEncryptionAlgorithms}}
+ AlgorithmIdentifierPKCS-7 {{ContentEncryptionAlgorithms}}
ContentEncryptionAlgorithms ALGORITHM ::= {
... -- add any application-specific algorithms here
}
DigestAlgorithmIdentifier ::=
- AlgorithmIdentifierPKSC-7 {{DigestAlgorithms}}
+ AlgorithmIdentifierPKCS-7 {{DigestAlgorithms}}
DigestAlgorithms ALGORITHM ::= {
... -- add any application-specific algorithms here
}
DigestEncryptionAlgorithmIdentifier ::=
- AlgorithmIdentifierPKSC-7 {{DigestEncryptionAlgorithms}}
+ AlgorithmIdentifierPKCS-7 {{DigestEncryptionAlgorithms}}
DigestEncryptionAlgorithms ALGORITHM ::= {
... -- add any application-specific algorithms here
@@ -182,7 +182,7 @@ IssuerAndSerialNumber ::= SEQUENCE {
}
KeyEncryptionAlgorithmIdentifier ::=
- AlgorithmIdentifierPKSC-7 {{KeyEncryptionAlgorithms}}
+ AlgorithmIdentifierPKCS-7 {{KeyEncryptionAlgorithms}}
KeyEncryptionAlgorithms ALGORITHM ::= {
... -- add any application-specific algorithms here
diff --git a/lib/public_key/doc/specs/.gitignore b/lib/public_key/doc/specs/.gitignore
new file mode 100644
index 0000000000..322eebcb06
--- /dev/null
+++ b/lib/public_key/doc/specs/.gitignore
@@ -0,0 +1 @@
+specs_*.xml
diff --git a/lib/public_key/doc/src/Makefile b/lib/public_key/doc/src/Makefile
index 5bdc5d4159..c8647750af 100644
--- a/lib/public_key/doc/src/Makefile
+++ b/lib/public_key/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2016. All Rights Reserved.
+# Copyright Ericsson AB 2008-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -40,7 +40,7 @@ XML_APPLICATION_FILES = ref_man.xml
XML_REF3_FILES = public_key.xml
XML_REF6_FILES = public_key_app.xml
-XML_PART_FILES = part.xml part_notes.xml
+XML_PART_FILES = part.xml
XML_CHAPTER_FILES = \
introduction.xml \
public_key_records.xml \
@@ -50,9 +50,9 @@ XML_CHAPTER_FILES = \
BOOK_FILES = book.xml
XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) \
- $(XML_REF6_FILES) $(XML_PART_FILES) $(XML_CHAPTER_FILES)
+ $(XML_REF6_FILES) $(XML_PART_FILES) $(XML_CHAPTER_FILES)
-GIF_FILES = note.gif
+GIF_FILES =
# ----------------------------------------------------
@@ -77,12 +77,18 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
+
+TOP_SPECS_FILE = specs.xml
+
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
XML_FLAGS +=
DVIPS_FLAGS +=
+SPECS_FLAGS = -I../../include -I../../src -I../../..
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
@@ -99,9 +105,11 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+ rm -f $(SPECS_FILES)
rm -f errs core *~
man: $(MAN3_FILES) $(MAN6_FILES)
diff --git a/lib/public_key/doc/src/fascicules.xml b/lib/public_key/doc/src/fascicules.xml
deleted file mode 100644
index 25e7008537..0000000000
--- a/lib/public_key/doc/src/fascicules.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="usersguide" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="release_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
-
diff --git a/lib/public_key/doc/src/note.gif b/lib/public_key/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/public_key/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml
index 64592a6d87..62b4b4ca1b 100644
--- a/lib/public_key/doc/src/notes.xml
+++ b/lib/public_key/doc/src/notes.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2008</year>
- <year>2017</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -35,6 +35,237 @@
<file>notes.xml</file>
</header>
+<section><title>Public_Key 1.6.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Removed <c>#DSAPrivateKey{}</c> as acceptable input to
+ <c>public_key:verify/5</c>.</p>
+ <p>
+ Own Id: OTP-15284</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The typing in the CRYPTO and PUBLIC_KEY applications are
+ reworked and a few mistakes are corrected.</p>
+ <p>
+ The documentation is now generated from the typing and
+ some clarifications are made.</p>
+ <p>
+ A new chapter on Algorithm Details such as key sizes and
+ availability is added to the CRYPTO User's Guide.</p>
+ <p>
+ Own Id: OTP-15134</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Public_Key 1.6.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Some of the keylengths in the newly generated moduli file
+ in public_key are not universally supported. This could
+ cause the SSH key exchange
+ diffie-hellman-group-exchange-sha* to fail.</p>
+ <p>
+ Those keylengths are now removed.</p>
+ <p>
+ Own Id: OTP-15151 Aux Id: OTP-15113 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Public_Key 1.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Update calls to the base64 module to conform to that
+ module's type specifications.</p>
+ <p>
+ Own Id: OTP-14788 Aux Id: OTP-14624 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Use uri_string module instead of http_uri.</p>
+ <p>
+ Own Id: OTP-14902</p>
+ </item>
+ <item>
+ <p>
+ A new function -
+ <c>public_key:pkix_verify_hostname_match_fun/1</c> -
+ returns a fun to be given as option <c>match_fun</c> to
+ <c>public_key:pkix_verify_hostname/3</c> or via ssl.</p>
+ <p>
+ The fun makes the verify hostname matching according to
+ the specific rules for the protocol in the argument.
+ Presently only <c>https</c> is supported.</p>
+ <p>
+ Own Id: OTP-14962 Aux Id: ERL-542, OTP-15102 </p>
+ </item>
+ <item>
+ <p>
+ Compleate PKCS-8 encoding support and enhance the
+ decoding of 'PrivateKeyInfo' to conform to the rest of
+ Erlang public_key API.</p>
+ <p>
+ Own Id: OTP-15093</p>
+ </item>
+ <item>
+ <p>
+ A new moduli file is generated. This file is used for the
+ recommended <c>diffie-hellman-group-exchange-sha256</c>
+ key exchange algorithm in SSH.</p>
+ <p>
+ Own Id: OTP-15113</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Public_Key 1.5.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed a bug in <c>public_key:ssh_encode/2</c> that made
+ it possible to erroneously encode e.g. an RSA key with
+ another type e.g. ECDSA in the resulting binary.</p>
+ <p>
+ Own Id: OTP-14570 Aux Id: ERIERL-52, OTP-14676 </p>
+ </item>
+ <item>
+ <p>
+ Corrected handling of parameterized EC keys in
+ public_key:generate_key/1 so that it will work as
+ expected instead of causing a runtime error in crypto.</p>
+ <p>
+ Own Id: OTP-14620</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Public_Key 1.5.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Hostname verification: Add handling of the general name
+ <c>iPAddress</c> in certificate's subject alternative
+ name extension (<c>subjAltName</c>).</p>
+ <p>
+ Own Id: OTP-14653</p>
+ </item>
+ <item>
+ <p>
+ Correct key handling in pkix_test_data/1 and use a
+ generic example mail address instead of an existing one.</p>
+ <p>
+ Own Id: OTP-14766</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Public_Key 1.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ public_key now handles elliptic curve parameters in a
+ consistent way so that decoded ECDSA keys can be
+ correctly re-encoded.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-14621 Aux Id: ERL-480, ERL-481 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Extend crypto:sign, crypto:verify, public_key:sign and
+ public_key:verify with:</p>
+ <p>
+ * support for RSASSA-PS padding for signatures and for
+ saltlength setting<br/> * X9.31 RSA padding.<br/> * sha,
+ sha224, sha256, sha384, and sha512 for dss signatures as
+ mentioned in NIST SP 800-57 Part 1.<br/> * ripemd160 to
+ be used for rsa signatures.</p>
+ <p>
+ This is a manual merge of half of the pull request 838 by
+ potatosalad from Sept 2015.</p>
+ <p>
+ Own Id: OTP-13704 Aux Id: PR838 </p>
+ </item>
+ <item>
+ <p>
+ Add API function pkix_test_data/1 for facilitating
+ automated testing. This is useful for applications that
+ preform X509-certifcate path validation of so called
+ certificate chains, such as TLS.</p>
+ <p>
+ Own Id: OTP-14181</p>
+ </item>
+ <item>
+ <p>
+ Improved error propagation and reports</p>
+ <p>
+ Own Id: OTP-14236</p>
+ </item>
+ <item>
+ <p>
+ RSAPrivateKey version is set to 'two-prime' instead of
+ using the underlying enumeration value directly.</p>
+ <p>
+ Own Id: OTP-14534</p>
+ </item>
+ <item>
+ <p>
+ Deprecated function <c>crypto:rand_uniform/2</c> is
+ replaced by <c>rand:uniform/1</c>.</p>
+ <p>
+ Own Id: OTP-14608</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Public_Key 1.4.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/public_key/doc/src/part_notes.xml b/lib/public_key/doc/src/part_notes.xml
deleted file mode 100644
index 17f06d14f5..0000000000
--- a/lib/public_key/doc/src/part_notes.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2008</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>public_key Release Notes</title>
- <prepared>Ingela Anderton Andin</prepared>
- <docno></docno>
- <date>2008-01-22</date>
- <rev></rev>
- </header>
- <description>
- <p></p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
-
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index 04966ffb9c..a4d7e4a734 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2008</year>
- <year>2017</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -41,7 +41,7 @@
</description>
<section>
- <title>DATA TYPES</title>
+ <title>Common Records and ASN.1 Types</title>
<note><p>All records used in this Reference Manual
<!-- except #policy_tree_node{} -->
@@ -54,174 +54,132 @@
records and constant macros described here and in the User's Guide:</p>
<code> -include_lib("public_key/include/public_key.hrl").</code>
+ </section>
+
+ <datatypes>
+ <datatype>
+ <name name="oid"/>
+ <desc>
+ <p>Object identifier, a tuple of integers as generated by the <c>ASN.1</c> compiler.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="der_encoded"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="pki_asn1_type"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="asn1_type"/>
+ <desc>
+ <p>ASN.1 type present in the Public Key applications ASN.1 specifications.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="pem_entry"/>
+ <name name="der_or_encrypted_der"/>
+ <name name="cipher_info"/>
+ <name name="cipher"/>
+ <name name="salt"/>
+ <name name="cipher_info_params"/>
+ <desc>
+ <code>Cipher = "RC2-CBC" | "DES-CBC" | "DES-EDE3-CBC"</code>
+ <p><c>Salt</c> could be generated with
+ <seealso marker="crypto:crypto#strong_rand_bytes-1"><c>crypto:strong_rand_bytes(8)</c></seealso>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="public_key"/>
+ <name name="rsa_public_key"/>
+ <name name="dsa_public_key"/>
+ <name name="ec_public_key"/>
+ <name name="ecpk_parameters"/>
+ <name name="ecpk_parameters_api"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="private_key"/>
+ <name name="rsa_private_key"/>
+ <name name="dsa_private_key"/>
+ <name name="ec_private_key"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="key_params"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="digest_type"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="crl_reason"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="issuer_id"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="issuer_name"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="ssh_file"/>
+ <desc>
+ </desc>
+ </datatype>
+
+
+
+ </datatypes>
- <p>The following data types are used in the functions for <c>public_key</c>:</p>
-
- <taglist>
- <tag><c>oid()</c></tag>
- <item><p>Object identifier, a tuple of integers as generated by the <c>ASN.1</c> compiler.</p></item>
-
- <tag><c>boolean() =</c></tag>
- <item><p><c>true | false</c></p></item>
-
- <tag><c>string() =</c></tag>
- <item><p><c>[bytes()]</c></p></item>
-
- <tag><c>der_encoded() =</c></tag>
- <item><p><c>binary()</c></p></item>
-
- <tag><c>pki_asn1_type() =</c></tag>
- <item>
- <p><c>'Certificate'</c></p>
- <p><c>| 'RSAPrivateKey'</c></p>
- <p><c>| 'RSAPublicKey'</c></p>
- <p><c>| 'DSAPrivateKey'</c></p>
- <p><c>| 'DSAPublicKey'</c></p>
- <p><c>| 'DHParameter'</c></p>
- <p><c>| 'SubjectPublicKeyInfo'</c></p>
- <p><c>| 'PrivateKeyInfo'</c></p>
- <p><c>| 'CertificationRequest'</c></p>
- <p><c>| 'CertificateList'</c></p>
- <p><c>| 'ECPrivateKey'</c></p>
- <p><c>| 'EcpkParameters'</c></p>
- </item>
-
- <tag><c>pem_entry () =</c></tag>
- <item><p><c>{pki_asn1_type(), binary(), %% DER or encrypted DER</c></p>
- <p><c> not_encrypted | cipher_info()}</c></p></item>
-
- <tag><c>cipher_info() = </c></tag>
- <item><p><c>{"RC2-CBC" | "DES-CBC" | "DES-EDE3-CBC", crypto:strong_rand_bytes(8)</c></p>
- <p><c>| {#'PBEParameter{}, digest_type()} | #'PBES2-params'{}}</c></p>
- </item>
-
- <tag><c>public_key() =</c></tag>
- <item><p><c>rsa_public_key() | dsa_public_key() | ec_public_key()</c></p></item>
-
- <tag><c>private_key() =</c></tag>
- <item><p><c>rsa_private_key() | dsa_private_key() | ec_private_key()</c></p></item>
-
- <tag><c>rsa_public_key() =</c></tag>
- <item><p><c>#'RSAPublicKey'{}</c></p></item>
-
- <tag><c>rsa_private_key() =</c></tag>
- <item><p><c>#'RSAPrivateKey'{}</c></p></item>
-
- <tag><c>dsa_public_key() =</c></tag>
- <item><p><c>{integer(), #'Dss-Parms'{}}</c></p></item>
-
- <tag><c>dsa_private_key() =</c></tag>
- <item><p><c>#'DSAPrivateKey'{}</c></p></item>
-
- <tag><c>ec_public_key()</c></tag>
- <item><p>= <c>{#'ECPoint'{}, #'ECParameters'{} | {namedCurve, oid()}}</c></p></item>
-
- <tag><c>ec_private_key() =</c></tag>
- <item><p><c>#'ECPrivateKey'{}</c></p></item>
-
- <tag><c>public_crypt_options() =</c></tag>
- <item><p><c>[{rsa_pad, rsa_padding()}]</c></p></item>
-
- <tag><c>rsa_padding() =</c></tag>
- <item>
- <p><c>'rsa_pkcs1_padding'</c></p>
- <p><c>| 'rsa_pkcs1_oaep_padding'</c></p>
- <p><c>| 'rsa_no_padding'</c></p>
- </item>
-
- <tag><c>digest_type() = </c></tag>
- <item><p>Union of <c>rsa_digest_type()</c>, <c>dss_digest_type()</c>,
- and <c>ecdsa_digest_type()</c>.</p></item>
-
- <tag><c>rsa_digest_type() = </c></tag>
- <item><p><c>'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'</c></p></item>
-
- <tag><c>dss_digest_type() = </c></tag>
- <item><p><c>'sha'</c></p></item>
-
- <tag><c>ecdsa_digest_type() = </c></tag>
- <item><p><c>'sha'| 'sha224' | 'sha256' | 'sha384' | 'sha512'</c></p></item>
-
- <tag><c>crl_reason() = </c></tag>
- <item>
- <p><c>unspecified</c></p>
- <p><c>| keyCompromise</c></p>
- <p><c>| cACompromise</c></p>
- <p><c>| affiliationChanged</c></p>
- <p><c>| superseded</c></p>
- <p><c>| cessationOfOperation</c></p>
- <p><c>| certificateHold</c></p>
- <p><c>| privilegeWithdrawn</c></p>
- <p><c>| aACompromise</c></p>
- </item>
-
- <tag><c>issuer_name() =</c></tag>
- <item><p><c>{rdnSequence,[#'AttributeTypeAndValue'{}]}</c></p>
- </item>
-
- <tag><c>ssh_file() =</c></tag>
- <item>
- <p><c>openssh_public_key</c></p>
- <p><c>| rfc4716_public_key</c></p>
- <p><c>| known_hosts</c></p>
- <p><c>| auth_keys</c></p>
- </item>
- </taglist>
-
-
-<!-- <p><code>policy_tree() = [Root, Children]</code></p> -->
-
-<!-- <p><code>Root = #policy_tree_node{}</code></p> -->
-
-<!-- <p><code>Children = [] | policy_tree()</code></p> -->
-
-<!-- <p>The <c>policy_tree_node</c> record has the following fields:</p> -->
-
-<!-- <taglist> -->
-
-<!-- <tag>valid_policy</tag> -->
-<!-- <item>A single policy OID representing a -->
-<!-- valid policy for the path of length x.</item> -->
-
-<!-- <tag>qualifier_set</tag> -->
-<!-- <item>A set of policy qualifiers associated -->
-<!-- with the valid policy in certificate x.</item> -->
-
-<!-- <tag>critically_indicator</tag> -->
-<!-- <item>Indicates whether the -->
-<!-- certificate policy extension in certificate x was marked as -->
-<!-- critical.</item> -->
-
-<!-- <tag>expected_policy_set</tag> -->
-<!-- <item>Contains one or more policy OIDs -->
-<!-- that would satisfy this policy in the certificate x+1.</item> -->
-<!-- </taglist> -->
- </section>
<funcs>
<func>
- <name>compute_key(OthersKey, MyKey)-></name>
- <name>compute_key(OthersKey, MyKey, Params)-></name>
+ <name name="compute_key" arity="2"/>
+ <fsummary>Computes shared secret.</fsummary>
+ <desc>
+ <p>Computes shared secret.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="compute_key" arity="3"/>
<fsummary>Computes shared secret.</fsummary>
- <type>
- <v>OthersKey = #'ECPoint'{} | binary(), MyKey = #'ECPrivateKey'{} | binary()</v>
- <v>Params = #'DHParameter'{}</v>
- </type>
<desc>
<p>Computes shared secret.</p>
</desc>
</func>
<func>
- <name>decrypt_private(CipherText, Key) -> binary()</name>
- <name>decrypt_private(CipherText, Key, Options) -> binary()</name>
+ <name name="decrypt_private" arity="2"/>
+ <name name="decrypt_private" arity="3"/>
<fsummary>Public-key decryption.</fsummary>
- <type>
- <v>CipherText = binary()</v>
- <v>Key = rsa_private_key()</v>
- <v>Options = public_crypt_options()</v>
- </type>
<desc>
<p>Public-key decryption using the private key. See also <seealso
marker="crypto:crypto#private_decrypt/4">crypto:private_decrypt/4</seealso></p>
@@ -229,14 +187,9 @@
</func>
<func>
- <name>decrypt_public(CipherText, Key) - > binary()</name>
- <name>decrypt_public(CipherText, Key, Options) - > binary()</name>
+ <name name="decrypt_public" arity="2"/>
+ <name name="decrypt_public" arity="3"/>
<fsummary>Public-key decryption.</fsummary>
- <type>
- <v>CipherText = binary()</v>
- <v>Key = rsa_public_key()</v>
- <v>Options = public_crypt_options()</v>
- </type>
<desc>
<p>Public-key decryption using the public key. See also <seealso
marker="crypto:crypto#public_decrypt/4">crypto:public_decrypt/4</seealso></p>
@@ -244,47 +197,24 @@
</func>
<func>
- <name>der_decode(Asn1type, Der) -> term()</name>
+ <name name="der_decode" arity="2"/>
<fsummary>Decodes a public-key ASN.1 DER encoded entity.</fsummary>
- <type>
- <v>Asn1Type = atom()</v>
- <d>ASN.1 type present in the Public Key applications
- ASN.1 specifications.</d>
- <v>Der = der_encoded()</v>
- </type>
- <desc>
+ <desc>
<p>Decodes a public-key ASN.1 DER encoded entity.</p>
</desc>
</func>
-
+
<func>
- <name>der_encode(Asn1Type, Entity) -> der_encoded()</name>
+ <name name="der_encode" arity="2"/>
<fsummary>Encodes a public-key entity with ASN.1 DER encoding.</fsummary>
- <type>
- <v>Asn1Type = atom()</v>
- <d>ASN.1 type present in the Public Key applications
- ASN.1 specifications.</d>
- <v>Entity = term()</v>
- <d>Erlang representation of <c>Asn1Type</c></d>
- </type>
<desc>
<p>Encodes a public-key entity with ASN.1 DER encoding.</p>
</desc>
</func>
<func>
- <name>dh_gex_group(MinSize, SuggestedSize, MaxSize, Groups) -> {ok, {Size,Group}} | {error,Error}</name>
+ <name name="dh_gex_group" arity="4"/>
<fsummary>Selects a group for Diffie-Hellman key exchange</fsummary>
- <type>
- <v>MinSize = positive_integer()</v>
- <v>SuggestedSize = positive_integer()</v>
- <v>MaxSize = positive_integer()</v>
- <v>Groups = undefined | [{Size,[{G,P}]}]</v>
- <v>Size = positive_integer()</v>
- <v>Group = {G,P}</v>
- <v>G = positive_integer()</v>
- <v>P = positive_integer()</v>
- </type>
<desc>
<p>Selects a group for Diffie-Hellman key exchange with the key size in the range <c>MinSize...MaxSize</c>
and as close to <c>SuggestedSize</c> as possible. If <c>Groups == undefined</c> a default set will be
@@ -303,13 +233,10 @@
</desc>
</func>
- <func>
- <name>encrypt_private(PlainText, Key) -> binary()</name>
+ <func>
+ <name name="encrypt_private" arity="2"/>
+ <name name="encrypt_private" arity="3"/>
<fsummary>Public-key encryption using the private key.</fsummary>
- <type>
- <v>PlainText = binary()</v>
- <v>Key = rsa_private_key()</v>
- </type>
<desc>
<p>Public-key encryption using the private key.
See also <seealso
@@ -318,12 +245,9 @@
</func>
<func>
- <name>encrypt_public(PlainText, Key) -> binary()</name>
+ <name name="encrypt_public" arity="2"/>
+ <name name="encrypt_public" arity="3"/>
<fsummary>Public-key encryption using the public key.</fsummary>
- <type>
- <v>PlainText = binary()</v>
- <v>Key = rsa_public_key()</v>
- </type>
<desc>
<p>Public-key encryption using the public key. See also <seealso
marker="crypto:crypto#public_encrypt/4">crypto:public_encrypt/4</seealso>.</p>
@@ -331,12 +255,8 @@
</func>
<func>
- <name>generate_key(Params) -> {Public::binary(), Private::binary()} | #'ECPrivateKey'{} | #'RSAPrivateKey'{}</name>
+ <name name="generate_key" arity="1"/>
<fsummary>Generates a new keypair.</fsummary>
- <type>
- <v>Params = #'DHParameter'{} | {namedCurve, oid()} | #'ECParameters'{}
- | {rsa, Size::integer(), PubExp::integer} </v>
- </type>
<desc>
<p>Generates a new keypair. Note that except for Diffie-Hellman
the public key is included in the private key structure. See also
@@ -346,38 +266,27 @@
</func>
<func>
- <name>pem_decode(PemBin) -> [pem_entry()]</name>
+ <name name="pem_decode" arity="1"/>
<fsummary>Decodes PEM binary data and returns
entries as ASN.1 DER encoded entities.</fsummary>
- <type>
- <v>PemBin = binary()</v>
- <d>Example {ok, PemBin} = file:read_file("cert.pem").</d>
- </type>
<desc>
- <p>Decodes PEM binary data and returns
- entries as ASN.1 DER encoded entities.</p>
+ <p>Decodes PEM binary data and returns entries as ASN.1 DER encoded entities.</p>
+ <p>Example <c>{ok, PemBin} = file:read_file("cert.pem").</c></p>
</desc>
</func>
- <func>
- <name>pem_encode(PemEntries) -> binary()</name>
+ <func>
+ <name name="pem_encode" arity="1"/>
<fsummary>Creates a PEM binary.</fsummary>
- <type>
- <v> PemEntries = [pem_entry()] </v>
- </type>
- <desc>
- <p>Creates a PEM binary.</p>
- </desc>
+ <desc>
+ <p>Creates a PEM binary.</p>
+ </desc>
</func>
- <func>
- <name>pem_entry_decode(PemEntry) -> term()</name>
- <name>pem_entry_decode(PemEntry, Password) -> term()</name>
+ <func>
+ <name name="pem_entry_decode" arity="1"/>
+ <name name="pem_entry_decode" arity="2"/>
<fsummary>Decodes a PEM entry.</fsummary>
- <type>
- <v>PemEntry = pem_entry()</v>
- <v>Password = string()</v>
- </type>
<desc>
<p>Decodes a PEM entry. <c>pem_decode/1</c> returns a list of PEM
entries. Notice that if the PEM entry is of type
@@ -386,51 +295,36 @@
</desc>
</func>
- <func>
- <name>pem_entry_encode(Asn1Type, Entity) -> pem_entry()</name>
- <name>pem_entry_encode(Asn1Type, Entity, {CipherInfo, Password}) -> pem_entry()</name>
+ <func>
+ <name name="pem_entry_encode" arity="2"/>
+ <name name="pem_entry_encode" arity="3"/>
<fsummary>Creates a PEM entry that can be fed to <c>pem_encode/1</c>.</fsummary>
- <type>
- <v>Asn1Type = pki_asn1_type()</v>
- <v>Entity = term()</v>
- <d>Erlang representation of
- <c>Asn1Type</c>. If <c>Asn1Type</c> is 'SubjectPublicKeyInfo',
+ <desc>
+ <p>Creates a PEM entry that can be feed to <c>pem_encode/1</c>.</p>
+ <p>If <c>Asn1Type</c> is <c>'SubjectPublicKeyInfo'</c>,
<c>Entity</c> must be either an <c>rsa_public_key()</c>,
<c>dsa_public_key()</c> or an <c>ec_public_key()</c>
and this function creates the appropriate
- 'SubjectPublicKeyInfo' entry.
- </d>
- <v>CipherInfo = cipher_info()</v>
- <v>Password = string()</v>
- </type>
- <desc>
- <p>Creates a PEM entry that can be feed to <c>pem_encode/1</c>.</p>
- </desc>
+ <c>'SubjectPublicKeyInfo'</c> entry.
+ </p>
+ </desc>
</func>
-
+
<func>
- <name>pkix_decode_cert(Cert, otp|plain) -> #'Certificate'{} | #'OTPCertificate'{}</name>
+ <name name="pkix_decode_cert" arity="2"/>
<fsummary>Decodes an ASN.1 DER-encoded PKIX x509 certificate.</fsummary>
- <type>
- <v>Cert = der_encoded()</v>
- </type>
- <desc>
- <p>Decodes an ASN.1 DER-encoded PKIX certificate. Option <c>otp</c>
- uses the customized ASN.1 specification OTP-PKIX.asn1 for
- decoding and also recursively decode most of the standard
- parts.</p>
- </desc>
+ <desc>
+ <p>Decodes an ASN.1 DER-encoded PKIX certificate. Option <c>otp</c>
+ uses the customized ASN.1 specification OTP-PKIX.asn1 for
+ decoding and also recursively decode most of the standard
+ parts.</p>
+ </desc>
</func>
<func>
- <name>pkix_encode(Asn1Type, Entity, otp | plain) -> der_encoded()</name>
+ <name name="pkix_encode" arity="3"/>
<fsummary>DER encodes a PKIX x509 certificate or part of such a
certificate.</fsummary>
- <type>
- <v>Asn1Type = atom()</v>
- <d>The ASN.1 type can be 'Certificate', 'OTPCertificate' or a subtype of either.</d>
- <v>Entity = #'Certificate'{} | #'OTPCertificate'{} | a valid subtype</v>
- </type>
<desc>
<p>DER encodes a PKIX x509 certificate or part of such a
certificate. This function must be used for encoding certificates or parts of certificates
@@ -440,69 +334,47 @@
</func>
<func>
- <name>pkix_is_issuer(Cert, IssuerCert) -> boolean()</name>
- <fsummary>Checks if <c>IssuerCert</c> issued <c>Cert</c>.</fsummary>
- <type>
- <v>Cert = der_encoded() | #'OTPCertificate'{} | #'CertificateList'{}</v>
- <v>IssuerCert = der_encoded() | #'OTPCertificate'{}</v>
- </type>
- <desc>
- <p>Checks if <c>IssuerCert</c> issued <c>Cert</c>.</p>
- </desc>
- </func>
+ <name name="pkix_is_issuer" arity="2"/>
+ <fsummary>Checks if <c>IssuerCert</c> issued <c>Cert</c>.</fsummary>
+ <desc>
+ <p>Checks if <c>IssuerCert</c> issued <c>Cert</c>.</p>
+ </desc>
+ </func>
- <func>
- <name>pkix_is_fixed_dh_cert(Cert) -> boolean()</name>
- <fsummary>Checks if a certificate is a fixed Diffie-Hellman certificate.</fsummary>
- <type>
- <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
- </type>
- <desc>
- <p>Checks if a certificate is a fixed Diffie-Hellman certificate.</p>
- </desc>
- </func>
+ <func>
+ <name name="pkix_is_fixed_dh_cert" arity="1"/>
+ <fsummary>Checks if a certificate is a fixed Diffie-Hellman certificate.</fsummary>
+ <desc>
+ <p>Checks if a certificate is a fixed Diffie-Hellman certificate.</p>
+ </desc>
+ </func>
- <func>
- <name>pkix_is_self_signed(Cert) -> boolean()</name>
- <fsummary>Checks if a certificate is self-signed.</fsummary>
- <type>
- <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
- </type>
- <desc>
- <p>Checks if a certificate is self-signed.</p>
- </desc>
- </func>
+ <func>
+ <name name="pkix_is_self_signed" arity="1"/>
+ <fsummary>Checks if a certificate is self-signed.</fsummary>
+ <desc>
+ <p>Checks if a certificate is self-signed.</p>
+ </desc>
+ </func>
- <func>
- <name>pkix_issuer_id(Cert, IssuedBy) -> {ok, IssuerID} | {error, Reason}</name>
- <fsummary>Returns the issuer id.</fsummary>
- <type>
- <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
- <v>IssuedBy = self | other</v>
- <v>IssuerID = {integer(), issuer_name()}</v>
- <d>The issuer id consists of the serial number and the issuers name.</d>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Returns the issuer id.</p>
- </desc>
- </func>
-
+ <func>
+ <name name="pkix_issuer_id" arity="2"/>
+ <fsummary>Returns the issuer id.</fsummary>
+ <desc>
+ <p>Returns the issuer id.</p>
+ </desc>
+ </func>
- <func>
- <name>pkix_normalize_name(Issuer) -> Normalized</name>
- <fsummary>Normalizes an issuer name so that it can be easily
- compared to another issuer name.</fsummary>
- <type>
- <v>Issuer = issuer_name()</v>
- <v>Normalized = issuer_name()</v>
- </type>
- <desc>
- <p>Normalizes an issuer name so that it can be easily
- compared to another issuer name.</p>
- </desc>
- </func>
-
+ <func>
+ <name name="pkix_normalize_name" arity="1"/>
+ <fsummary>Normalizes an issuer name so that it can be easily
+ compared to another issuer name.</fsummary>
+ <desc>
+ <p>Normalizes an issuer name so that it can be easily
+ compared to another issuer name.</p>
+ </desc>
+ </func>
+
<func>
<name>pkix_path_validation(TrustedCert, CertChain, Options) -> {ok, {PublicKeyInfo, PolicyTree}} | {error, {bad_cert, Reason}} </name>
<fsummary>Performs a basic path validation according to RFC 5280.</fsummary>
@@ -604,26 +476,16 @@ fun(OtpCert :: #'OTPCertificate'{},
</func>
<func>
- <name>pkix_crl_issuer(CRL) -> issuer_name()</name>
+ <name name="pkix_crl_issuer" arity="1"/>
<fsummary>Returns the issuer of the <c>CRL</c>.</fsummary>
- <type>
- <v>CRL = der_encoded() | #'CertificateList'{} </v>
- </type>
<desc>
<p>Returns the issuer of the <c>CRL</c>.</p>
</desc>
</func>
<func>
- <name>pkix_crls_validate(OTPCertificate, DPAndCRLs, Options) -> CRLStatus()</name>
+ <name name="pkix_crls_validate" arity="3"/>
<fsummary>Performs CRL validation.</fsummary>
- <type>
- <v>OTPCertificate = #'OTPCertificate'{}</v>
- <v>DPAndCRLs = [{DP::#'DistributionPoint'{}, {DerCRL::der_encoded(), CRL::#'CertificateList'{}}}] </v>
- <v>Options = proplists:proplist()</v>
- <v>CRLStatus() = valid | {bad_cert, revocation_status_undetermined} |
- {bad_cert, {revoked, crl_reason()}}</v>
- </type>
<desc>
<p>Performs CRL validation. It is intended to be called from
the verify fun of <seealso marker="#pkix_path_validation-3"> pkix_path_validation/3
@@ -650,7 +512,7 @@ fun(OtpCert :: #'OTPCertificate'{},
<tag>{issuer_fun, fun()}</tag>
<item>
<p>The fun has the following type specification:</p>
-
+
<code>
fun(#'DistributionPoint'{}, #'CertificateList'{},
{rdnSequence,[#'AttributeTypeAndValue'{}]}, term()) ->
@@ -660,30 +522,30 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
that has signed the CRL.
</p>
<code> fun(DP, CRL, Issuer, UserState) -> {ok, RootCert, CertChain}</code>
- </item>
+ </item>
+
+ <tag>{undetermined_details, boolean()}</tag>
+ <item>
+ <p>Defaults to false. When revocation status can not be
+ determined, and this option is set to true, details of why no
+ CRLs where accepted are included in the return value.</p>
+ </item>
+
</taglist>
</desc>
</func>
<func>
- <name>pkix_crl_verify(CRL, Cert) -> boolean()</name>
+ <name name="pkix_crl_verify" arity="2"/>
<fsummary> Verify that <c>Cert</c> is the <c> CRL</c> signer. </fsummary>
- <type>
- <v>CRL = der_encoded() | #'CertificateList'{} </v>
- <v>Cert = der_encoded() | #'OTPCertificate'{} </v>
- </type>
<desc>
<p>Verify that <c>Cert</c> is the <c>CRL</c> signer.</p>
</desc>
</func>
<func>
- <name>pkix_dist_point(Cert) -> DistPoint</name>
+ <name name="pkix_dist_point" arity="1"/>
<fsummary>Creates a distribution point for CRLs issued by the same issuer as <c>Cert</c>.</fsummary>
- <type>
- <v> Cert = der_encoded() | #'OTPCertificate'{} </v>
- <v> DistPoint = #'DistributionPoint'{}</v>
- </type>
<desc>
<p>Creates a distribution point for CRLs issued by the same issuer as <c>Cert</c>.
Can be used as input to <seealso
@@ -693,26 +555,17 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
</func>
<func>
- <name>pkix_dist_points(Cert) -> DistPoints</name>
+ <name name="pkix_dist_points" arity="1"/>
<fsummary> Extracts distribution points from the certificates extensions.</fsummary>
- <type>
- <v> Cert = der_encoded() | #'OTPCertificate'{} </v>
- <v> DistPoints = [#'DistributionPoint'{}]</v>
- </type>
<desc>
<p> Extracts distribution points from the certificates extensions.</p>
</desc>
</func>
<func>
- <name>pkix_match_dist_point(CRL, DistPoint) -> boolean()</name>
+ <name name="pkix_match_dist_point" arity="2"/>
<fsummary>Checks whether the given distribution point matches the
Issuing Distribution Point of the CRL.</fsummary>
-
- <type>
- <v>CRL = der_encoded() | #'CertificateList'{} </v>
- <v>DistPoint = #'DistributionPoint'{}</v>
- </type>
<desc>
<p>Checks whether the given distribution point matches the
Issuing Distribution Point of the CRL, as described in RFC 5280.
@@ -722,11 +575,8 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
</func>
<func>
- <name>pkix_sign(#'OTPTBSCertificate'{}, Key) -> der_encoded()</name>
+ <name name="pkix_sign" arity="2"/>
<fsummary>Signs certificate.</fsummary>
- <type>
- <v>Key = rsa_private_key() | dsa_private_key()</v>
- </type>
<desc>
<p>Signs an 'OTPTBSCertificate'. Returns the corresponding
DER-encoded certificate.</p>
@@ -734,27 +584,181 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
</func>
<func>
- <name>pkix_sign_types(AlgorithmId) -> {DigestType, SignatureType}</name>
+ <name name="pkix_sign_types" arity="1"/>
<fsummary>Translates signature algorithm OID to Erlang digest and signature algorithm types.</fsummary>
+ <desc>
+ <p>Translates signature algorithm OID to Erlang digest and signature types.
+ </p>
+ <p>The <c>AlgorithmId</c> is the signature OID from a certificate or a certificate revocation list.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>pkix_test_data(Options) -> Config </name>
+ <name>pkix_test_data([chain_opts()]) -> [conf_opt()]</name>
+ <fsummary>Creates certificate test data.</fsummary>
<type>
- <v>AlgorithmId = oid()</v>
- <d>Signature OID from a certificate or a certificate revocation list.</d>
- <v>DigestType = rsa_digest_type() | dss_digest_type()</v>
- <v>SignatureType = rsa | dsa | ecdsa</v>
+ <v>Options = #{chain_type() := chain_opts()} </v>
+ <d>Options for ROOT, Intermediate and Peer certs</d>
+
+ <v>chain_type() = server_chain | client_chain </v>
+
+ <v>chain_opts() = #{root := [cert_opt()] | root_cert(),
+ peer := [cert_opt()],
+ intermediates => [[cert_opt()]]}</v>
+ <d>
+ A valid chain must have at least a ROOT and a peer cert.
+ The root cert can be given either as a cert pre-generated by
+ <seealso marker="#pkix_test_root_cert-2">
+ pkix_test_root_cert/2
+ </seealso>, or as root cert generation options.
+ </d>
+ <v>root_cert() = #{cert := der_encoded(), key := Key}</v>
+ <d>
+ A root certificate generated by
+ <seealso marker="#pkix_test_root_cert-2">
+ pkix_test_root_cert/2
+ </seealso>.
+ </d>
+ <v>cert_opt() = {Key, Value}</v>
+ <d>For available options see <seealso marker="#cert_opt"> cert_opt()</seealso> below.</d>
+
+ <v>Config = #{server_config := [conf_opt()],
+ client_config := [conf_opt()]}</v>
+
+ <v>conf_opt() = {cert, der_encoded()} | {key, PrivateKey} |{cacerts, [der_encoded()]}</v>
+ <d>
+ This is a subset of the type
+ <seealso marker="ssl:ssl#type-ssloption"> ssl:ssl_option()</seealso>.
+ <c>PrivateKey</c> is what
+ <seealso marker="#generate_key-1">generate_key/1</seealso>
+ returns.
+ </d>
</type>
+
<desc>
- <p>Translates signature algorithm OID to Erlang digest and signature types.
+ <p>
+ Creates certificate configuration(s) consisting of certificate
+ and its private key plus CA certificate bundle, for a client
+ and a server, intended to facilitate automated testing
+ of applications using X509-certificates,
+ often through SSL/TLS. The test data can be used
+ when you have control over both the client and the server
+ in a test scenario.
+ </p>
+ <p>
+ When this function is called with a map containing
+ client and server chain specifications;
+ it generates both a client and a server certificate chain
+ where the <c>cacerts</c>
+ returned for the server contains the root cert the server
+ should trust and the intermediate certificates the server
+ should present to connecting clients.
+ The root cert the server should trust is the one used
+ as root of the client certificate chain.
+ Vice versa applies to the <c>cacerts</c> returned for the client.
+ The root cert(s) can either be pre-generated with
+ <seealso marker="#pkix_test_root_cert-2">
+ pkix_test_root_cert/2
+ </seealso>, or if options are specified; it is (they are)
+ generated.
+ </p>
+ <p>
+ When this function is called with a list of certificate options;
+ it generates a configuration with just one node certificate
+ where <c>cacerts</c> contains the root cert
+ and the intermediate certs that should be presented to a peer.
+ In this case the same root cert must be used for all peers.
+ This is useful in for example an Erlang distributed cluster
+ where any node, towards another node, acts either
+ as a server or as a client depending on who connects to whom.
+ The generated certificate contains a subject altname,
+ which is not needed in a client certificate,
+ but makes the certificate useful for both roles.
+ </p>
+ <p>
+ The <marker id="cert_opt"/><c>cert_opt()</c>
+ type consists of the following options:
+ </p>
+ <taglist>
+ <tag> {digest, digest_type()}</tag>
+ <item><p>Hash algorithm to be used for
+ signing the certificate together with the key option. Defaults to sha that is sha1.
+ </p></item>
+ <tag> {key, key_params() | private_key()}</tag>
+ <item><p>Parameters to be used to call public_key:generate_key/1, to generate a key, or an existing
+ key. Defaults to generating an ECDSA key. Note this could fail if Erlang/OTP is compiled with a very old
+ cryptolib.</p></item>
+ <tag> {validity, {From::erlang:timestamp(), To::erlang:timestamp()}} </tag>
+ <item><p>The validity period of the certificate.</p></item>
+ <tag> {extensions, [#'Extension'{}]}</tag>
+ <item><p> Extensions to include in the certificate.</p>
+
+ <p>Default extensions included in CA certificates if not
+ otherwise specified are: </p>
+ <code>[#'Extension'{extnID = ?'id-ce-keyUsage',
+ extnValue = [keyCertSign, cRLSign],
+ critical = false},
+#'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue = #'BasicConstraints'{cA = true},
+ critical = true}]
+ </code>
+
+ <p>Default extensions included in the server peer cert if not
+ otherwise specified are: </p>
+ <code>[#'Extension'{extnID = ?'id-ce-keyUsage',
+ extnValue = [digitalSignature, keyAgreement],
+ critical = false},
+#'Extension'{extnID = ?'id-ce-subjectAltName',
+ extnValue = [{dNSName, Hostname}],
+ critical = false}]
+ </code>
+ <p>Hostname is the result of calling net_adm:localhost() in the Erlang node
+ where this funcion is called.
+ </p></item>
+
+ </taglist>
+
+ <note><p>
+ Note that the generated certificates and keys does not provide a formally correct PKIX-trust-chain
+ and they can not be used to achieve real security. This function is provided for testing purposes only.
+</p></note>
+ </desc>
+ </func>
+
+ <func>
+ <name>pkix_test_root_cert(Name, Options) -> RootCert</name>
+ <fsummary>Generates a test data root cert.</fsummary>
+ <type>
+ <v>Name = string()</v>
+ <d>The root certificate name.</d>
+ <v>Options = [cert_opt()]</v>
+ <d>
+ For available options see
+ <seealso marker="#cert_opt">cert_opt()</seealso>
+ under
+ <seealso marker="#pkix_test_data-1">pkix_test_data/1</seealso>.
+ </d>
+ <v>RootCert = #{cert := der_encoded(), key := Key}</v>
+ <d>
+ A root certificate and key. The <c>Key</c> is generated by
+ <seealso marker="#generate_key-1">generate_key/1</seealso>.
+ </d>
+ </type>
+ <desc>
+ <p>
+ Generates a root certificate that can be used
+ in multiple calls to
+ <seealso marker="#pkix_test_data-1">pkix_test_data/1</seealso>
+ when you want the same root certificate for
+ several generated certificates.
</p>
</desc>
</func>
<func>
- <name>pkix_verify(Cert, Key) -> boolean()</name>
+ <name name="pkix_verify" arity="2"/>
<fsummary>Verifies PKIX x.509 certificate signature.</fsummary>
- <type>
- <v>Cert = der_encoded()</v>
- <v>Key = rsa_public_key() | dsa_public_key() | ec_public_key()</v>
- </type>
<desc>
<p>Verifies PKIX x.509 certificate signature.</p>
</desc>
@@ -768,65 +772,132 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
<type>
<v>Cert = der_encoded() | #'OTPCertificate'{} </v>
<v>ReferenceIDs = [ RefID ]</v>
- <v>RefID = {IdType,string()}</v>
- <v>IdType = dns_id | srv_id | uri_id</v>
+ <v>RefID = {dns_id,string()} | {srv_id,string()} | {uri_id,string()} | {ip,inet:ip_address()|string()} | {OtherRefID,term()}}</v>
+ <v>OtherRefID = atom()</v>
<v>Opts = [ PvhOpt() ]</v>
<v>PvhOpt = [MatchOpt | FailCallBackOpt | FqdnExtractOpt]</v>
- <v>MatchOpt = {fun(RefId | FQDN::string(), PresentedID) -> boolean() | default}</v>
- <v>PresentedID = {dNSName,string()} | {uniformResourceIdentifier,string()}</v>
+ <v>MatchOpt = {match_fun, fun(RefId | FQDN::string(), PresentedID) -> boolean() | default}</v>
+ <v>PresentedID = {dNSName,string()} | {uniformResourceIdentifier,string() | {iPAddress,list(byte())} | {OtherPresId,term()}}</v>
+ <v>OtherPresID = atom()</v>
<v>FailCallBackOpt = {fail_callback, fun(#'OTPCertificate'{}) -> boolean()}</v>
<v>FqdnExtractOpt = {fqdn_fun, fun(RefID) -> FQDN::string() | default | undefined}</v>
</type>
<desc>
<p>This function checks that the <i>Presented Identifier</i> (e.g hostname) in a peer certificate
- conforms with the Expected Identifier that the client wants to connect to.
- This functions is intended to be added as an extra client check to the peer certificate when performing
+ is in agreement with at least one of the <i>Reference Identifier</i> that the client expects to be connected to.
+ The function is intended to be added as an extra client check of the peer certificate when performing
<seealso marker="public_key:public_key#pkix_path_validation-3">public_key:pkix_path_validation/3</seealso>
</p>
<p>See <url href="https://tools.ietf.org/html/rfc6125">RFC 6125</url>
for detailed information about hostname verification.
- The <seealso marker="using_public_key#verify_hostname">User's Manual</seealso>
+ The <seealso marker="using_public_key#verify_hostname">User's Guide</seealso>
and
<seealso marker="using_public_key#verify_hostname_examples">code examples</seealso>
describes this function more detailed.
</p>
+ <p>The <c>{OtherRefId,term()}</c> is defined by the user and is passed to the <c>match_fun</c>, if defined.
+ If the term in <c>OtherRefId</c> is a binary, it will be converted to a string.
+ </p>
+ <p>The <c>ip</c> Reference ID takes an <seealso marker="inet:inet#type-ip_address">inet:ip_address()</seealso>
+ or an ip address in string format (E.g "10.0.1.1" or "1234::5678:9012") as second element.
+ </p>
+ <p>The options are:</p>
+ <taglist>
+ <tag><c>match_fun</c></tag>
+ <item>
+ The <c>fun/2</c> in this option replaces the default host name matching rules. The fun should return a
+ boolean to tell if the Reference ID and Presented ID matches or not. The fun can also return a third
+ value, the atom <c>default</c>, if the default matching rules shall apply.
+ This makes it possible to augment the tests with a special case:
+ <code>
+fun(....) -> true; % My special case
+ (_, _) -> default % all others falls back to the inherit tests
+end
+ </code>
+ <br/>See <seealso marker="#pkix_verify_hostname_match_fun-1">pkix_verify_hostname_match_fun/1</seealso> for a
+ function that takes a protocol name as argument and returns a <c>fun/2</c> suitable for this option and
+ <seealso marker="using_public_key#redefining_match_op">Re-defining the match operation</seealso>
+ in the User's Guide for an example.
+ </item>
+
+ <tag><c>fail_callback</c></tag>
+ <item>If a matching fails, there could be circumstances when the certificate should be accepted anyway. Think for
+ example of a web browser where you choose to accept an outdated certificate. This option enables implementation
+ of such a function. This <c>fun/1</c> is called when no <c>ReferenceID</c> matches. The return value of the fun
+ (a <c>boolean()</c>) decides the outcome. If <c>true</c> the the certificate is accepted otherwise
+ it is rejected. See
+ <seealso marker="using_public_key#-pinning--a-certificate">"Pinning" a Certificate</seealso>
+ in the User's Guide.
+ </item>
+
+ <tag><c>fqdn_fun</c></tag>
+ <item>This option augments the host name extraction from URIs and other Reference IDs. It could for example be
+ a very special URI that is not standardised. The fun takes a Reference ID as argument and returns one of:
+ <list>
+ <item>the hostname</item>
+ <item>the atom <c>default</c>: the default host name extract function will be used</item>
+ <item>the atom <c>undefined</c>: a host name could not be extracted. The pkix_verify_hostname/3
+ will return <c>false</c>.</item>
+ </list>
+ <br/>For an example, see
+ <seealso marker="using_public_key#hostname_extraction">Hostname extraction</seealso>
+ in the User's Guide.
+ </item>
+ </taglist>
+
</desc>
</func>
<func>
- <name>sign(Msg, DigestType, Key) -> binary()</name>
- <fsummary>Creates a digital signature.</fsummary>
+ <name>pkix_verify_hostname_match_fun(Protcol) -> fun(RefId | FQDN::string(), PresentedID) -> boolean() | default</name>
+ <fsummary>Returns a fun that is intendended as argument to the match_fun option in pkix_verify_hostname/3.
+ </fsummary>
<type>
- <v>Msg = binary() | {digest,binary()}</v>
- <d>The <c>Msg</c> is either the binary "plain text" data to be
- signed or it is the hashed value of "plain text", that is, the
- digest.</d>
- <v>DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()</v>
- <v>Key = rsa_private_key() | dsa_private_key() | ec_private_key()</v>
- </type>
+ <v>Protocol = https</v>
+ <d>The algorithm for wich the fun should implement the special matching rules</d>
+ <v>RefId</v>
+ <d>See <seealso marker="#pkix_verify_hostname-3">pkix_verify_hostname/3</seealso>.</d>
+ <v>FQDN</v>
+ <d>See <seealso marker="#pkix_verify_hostname-3">pkix_verify_hostname/3</seealso>.</d>
+ <v>PresentedID</v>
+ <d>See <seealso marker="#pkix_verify_hostname-3">pkix_verify_hostname/3</seealso>.</d>
+ </type>
+ <desc>
+ <p>The return value of calling this function is intended to be used in the <c>match_fun</c> option in
+ <seealso marker="#pkix_verify_hostname-3">pkix_verify_hostname/3</seealso>.
+ </p>
+ <p>The returned fun augments the verify hostname matching according to the specific rules for
+ the protocol in the argument.
+ </p>
+ </desc>
+ </func>
+
+
+ <func>
+ <name name="sign" arity="3"/>
+ <name name="sign" arity="4"/>
+ <fsummary>Creates a digital signature.</fsummary>
<desc>
<p>Creates a digital signature.</p>
+ <p>The <c>Msg</c> is either the binary "plain text" data to be
+ signed or it is the hashed value of "plain text", that is, the
+ digest.</p>
</desc>
</func>
<func>
- <name>ssh_decode(SshBin, Type) -> [{public_key(), Attributes::list()}]</name>
+ <name name="ssh_decode" arity="2"/>
<fsummary>Decodes an SSH file-binary.</fsummary>
- <type>
- <v>SshBin = binary()</v>
- <d>Example <c>{ok, SshBin} = file:read_file("known_hosts")</c>.</d>
- <v>Type = public_key | ssh_file()</v>
- <d>If <c>Type</c> is <c>public_key</c> the binary can be either
- an RFC4716 public key or an OpenSSH public key.</d>
- </type>
- <desc>
- <p>Decodes an SSH file-binary. In the case of <c>known_hosts</c> or
- <c>auth_keys</c>, the binary can include one or more lines of the
- file. Returns a list of public keys and their attributes, possible
- attribute values depends on the file type represented by the
- binary.
- </p>
-
+ <desc>
+ <p>Decodes an SSH file-binary. In the case of <c>known_hosts</c> or
+ <c>auth_keys</c>, the binary can include one or more lines of the
+ file. Returns a list of public keys and their attributes, possible
+ attribute values depends on the file type represented by the
+ binary.
+ </p>
+ <p>If the <c>Type</c> is <c>ssh2_pubkey</c>, the result will be
+ <c>Decoded_ssh2_pubkey</c>. Otherwise it will be <c>Decoded_OtherType</c>.
+ </p>
<taglist>
<tag>RFC4716 attributes - see RFC 4716.</tag>
<item><p>{headers, [{string(), utf8_string()}]}</p></item>
@@ -839,23 +910,25 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
<item>{comment, string()}</item>
<item><p>{bits, integer()} - In SSH version 1 files.</p></item>
</taglist>
-
+ <p>Example: <c>{ok, SshBin} = file:read_file("known_hosts")</c>.
+ </p>
+ <p>If <c>Type</c> is <c>public_key</c> the binary can be either
+ an RFC4716 public key or an OpenSSH public key.</p>
</desc>
</func>
<func>
- <name>ssh_encode([{Key, Attributes}], Type) -> binary()</name>
+ <name name="ssh_encode" arity="2"/>
<fsummary>Encodes a list of SSH file entries to a binary.</fsummary>
- <type>
- <v>Key = public_key()</v>
- <v>Attributes = list()</v>
- <v>Type = ssh_file()</v>
- </type>
- <desc>
- <p>Encodes a list of SSH file entries (public keys and attributes) to a binary. Possible
- attributes depend on the file type, see <seealso
- marker="#ssh_decode-2"> ssh_decode/2 </seealso>.</p>
- </desc>
+ <desc>
+ <p>Encodes a list of SSH file entries (public keys and attributes) to a binary. Possible
+ attributes depend on the file type, see
+ <seealso marker="#ssh_decode-2"> ssh_decode/2 </seealso>.
+ </p>
+ <p>If the <c>Type</c> is <c>ssh2_pubkey</c>, the <c>InData</c> shall be
+ <c>InData_ssh2_pubkey</c>. Otherwise it shall be <c>OtherInData</c>.
+ </p>
+ </desc>
</func>
<func>
@@ -864,8 +937,8 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
<name>ssh_hostkey_fingerprint([DigestType], HostKey) -> [string()]</name>
<fsummary>Calculates a ssh fingerprint for a hostkey.</fsummary>
<type>
- <v>Key = public_key()</v>
- <v>DigestType = digest_type()</v>
+ <v>HostKey = <seealso marker="#type-public_key">public_key()</seealso></v>
+ <v>DigestType = <seealso marker="#type-digest_type">digest_type()</seealso></v>
</type>
<desc>
<p>Calculates a ssh fingerprint from a public host key as openssh does.</p>
@@ -894,27 +967,19 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
</func>
<func>
- <name>verify(Msg, DigestType, Signature, Key) -> boolean()</name>
+ <name name="verify" arity="4"/>
+ <name name="verify" arity="5"/>
<fsummary>Verifies a digital signature.</fsummary>
- <type>
- <v>Msg = binary() | {digest,binary()}</v>
- <d>The <c>Msg</c> is either the binary "plain text" data
- or it is the hashed value of "plain text", that is, the digest.</d>
- <v>DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()</v>
- <v>Signature = binary()</v>
- <v>Key = rsa_public_key() | dsa_public_key() | ec_public_key()</v>
- </type>
<desc>
<p>Verifies a digital signature.</p>
+ <p>The <c>Msg</c> is either the binary "plain text" data
+ or it is the hashed value of "plain text", that is, the digest.</p>
</desc>
</func>
<func>
- <name>short_name_hash(Name) -> string()</name>
+ <name name="short_name_hash" arity="1"/>
<fsummary>Generates a short hash of an issuer name.</fsummary>
- <type>
- <v>Name = issuer_name()</v>
- </type>
<desc>
<p>Generates a short hash of an issuer name. The hash is
returned as a string containing eight hexadecimal digits.</p>
diff --git a/lib/public_key/doc/src/public_key_records.xml b/lib/public_key/doc/src/public_key_records.xml
index d34f3ed9a3..d26867c12f 100644
--- a/lib/public_key/doc/src/public_key_records.xml
+++ b/lib/public_key/doc/src/public_key_records.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2008</year>
- <year>2015</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -70,10 +70,10 @@
<p><c>| {dNSName, string()}</c></p>
<p><c>| {x400Address, string()}</c></p>
<p><c>| {directoryName, {rdnSequence, [#AttributeTypeAndValue'{}]}}</c></p>
- <p><c>| {eidPartyName, special_string()}</c></p>
- <p><c>| {eidPartyName, special_string(), special_string()}</c></p>
+ <p><c>| {ediPartyName, special_string()}</c></p>
+ <p><c>| {ediPartyName, special_string(), special_string()}</c></p>
<p><c>| {uniformResourceIdentifier, string()}</c></p>
- <p><c>| {ipAddress, string()}</c></p>
+ <p><c>| {iPAddress, string()}</c></p>
<p><c>| {registeredId, oid()}</c></p>
<p><c>| {otherName, term()}</c></p>
</item>
@@ -171,9 +171,9 @@
#'ECPrivateKey'{
version, % integer()
privateKey, % binary()
- parameters, % der_encoded() - {'EcpkParameters', #'ECParameters'{}} |
- {'EcpkParameters', {namedCurve, oid()}} |
- {'EcpkParameters', 'NULL'} % Inherited by CA
+ parameters, % {ecParameters, #'ECParameters'{}} |
+ % {namedCurve, Oid::tuple()} |
+ % {implicitlyCA, 'NULL'}
publicKey % bitstring()
}.
diff --git a/lib/public_key/doc/src/specs.xml b/lib/public_key/doc/src/specs.xml
new file mode 100644
index 0000000000..e358ea1154
--- /dev/null
+++ b/lib/public_key/doc/src/specs.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<specs xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="../specs/specs_public_key.xml"/>
+</specs>
diff --git a/lib/public_key/doc/src/using_public_key.xml b/lib/public_key/doc/src/using_public_key.xml
index 417d479da3..de0a6596c3 100644
--- a/lib/public_key/doc/src/using_public_key.xml
+++ b/lib/public_key/doc/src/using_public_key.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2011</year><year>2016</year>
+ <year>2011</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -570,6 +570,7 @@ true = public_key:verify(Digest, none, Signature, PublicKey),</code>
<c>fqdn_fun</c> and <c>match_fun</c>.
</p>
<section>
+ <marker id="hostname_extraction"></marker>
<title>Hostname extraction</title>
<p>The <c>fqdn_fun</c> extracts hostnames (Fully Qualified Domain Names) from uri_id
or other ReferenceIDs that are not pre-defined in the public_key function.
@@ -595,7 +596,8 @@ true = public_key:verify(Digest, none, Signature, PublicKey),</code>
</code>
</section>
<section>
- <title>Re-defining the match operations</title>
+ <marker id="redefining_match_op"></marker>
+ <title>Re-defining the match operation</title>
<p>The default matching handles dns_id and uri_id. In an uri_id the value is tested for
equality with a value from the <c>Subject Alternate Name</c>. If som other kind of matching
is needed, use the <c>match_fun</c> option.
diff --git a/lib/public_key/include/public_key.hrl b/lib/public_key/include/public_key.hrl
index a1e7dd31bc..98d032bfdd 100644
--- a/lib/public_key/include/public_key.hrl
+++ b/lib/public_key/include/public_key.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -70,7 +70,8 @@
reasons_mask,
cert_status,
interim_reasons_mask,
- valid_ext
+ valid_ext,
+ details
}).
-record('ECPoint', {
diff --git a/lib/public_key/priv/moduli b/lib/public_key/priv/moduli
index 446f4b8bf4..83e8767a5e 100644
--- a/lib/public_key/priv/moduli
+++ b/lib/public_key/priv/moduli
@@ -1,193 +1,240 @@
-20151021104105 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D182EB7
-20151021104106 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D27F94F
-20151021104107 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D398EB7
-20151021104108 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D4B850F
-20151021104108 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D4BF35B
-20151021104108 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D5031DF
-20151021104109 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D5A4933
-20151021104110 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D6434BF
-20151021104111 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D70676B
-20151021104111 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D7235E3
-20151021104113 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9D963493
-20151021104114 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DAABAA7
-20151021104115 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DC2E333
-20151021104116 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DE16A7B
-20151021104117 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DE2C5D3
-20151021104118 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9DFF382F
-20151021104119 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E158F13
-20151021104122 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E4D9FEB
-20151021104123 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E5C1FDB
-20151021104126 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E9BB69B
-20151021104126 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9E9F62D3
-20151021104127 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EAA1C27
-20151021104128 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EBC3313
-20151021104129 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EC0733B
-20151021104130 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EDB7AD3
-20151021104132 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EF56457
-20151021104132 2 6 100 1023 5 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9EF5A9CF
-20151021104133 2 6 100 1023 2 CF973CD39DC7D62F2C45AAC5180491104C76E0FE5D80A10E6C06AE442F1F373167B0FCBC931F3C157B10A5557008FDE20D68051E6A4DB11CEE0B0749F76D7134B937A59DA998C42BC234A5C1A3CFCD70E624D253D7694076F7B1FD7B8D3427849C9377B3555796ACA58C69DFF542EEEC9859D3ADCE5CC88DF6F7817C9F13CBB3
-20151021104218 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BAAFFDF
-20151021104222 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BCB6D93
-20151021104225 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BE660BB
-20151021104226 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BE676C3
-20151021104229 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BF3E23B
-20151021104230 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17BF95757
-20151021104241 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17C59BEA7
-20151021104242 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17C6231B3
-20151021104244 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17C6879BF
-20151021104250 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17C9B678F
-20151021104252 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17CA66A4B
-20151021104253 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17CAB5543
-20151021104256 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17CB96933
-20151021104300 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17CDA8493
-20151021104308 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17D18C0C7
-20151021104310 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17D1DA5BF
-20151021104318 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17D4AB15F
-20151021104325 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17D7DE42F
-20151021104329 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17DA03D3B
-20151021104335 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17DD88BFF
-20151021104338 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17DE82B5F
-20151021104342 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17E07AF43
-20151021104343 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17E091E6F
-20151021104346 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17E28B90F
-20151021104347 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17E2A24F3
-20151021104401 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17EB074A7
-20151021104403 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17EC01B0F
-20151021104406 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17ED2186F
-20151021104407 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17ED55AAB
-20151021104411 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17EF58773
-20151021104414 2 6 100 1535 5 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17F0B3267
-20151021104423 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17F4DF61B
-20151021104434 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17F9BBB0B
-20151021104442 2 6 100 1535 2 CA8FA8EC4B042248C2F4430EE03A77F23899363D2D20972D2BA94033EF18619FD18260B0903BA8B8F385791338369E285FEF46A7FAFF6B02B6888E9810A9C02A3C6FF7F7F85C81205FBE5A387E8A8AA2F42782671F0F86E1C68D3718D03FD517AE44C99FDCD955EF4C762E6245FBA81A9AB492A107A1E72A0FE6A4FE179B00986C4614F66805F921AE05185D52679F3E262B2A0B41812638C7F0421AEDF59BED23860E3FB5A521A11EA2A1E4D483132C857ED7328B9852BB4437C0D17FDD6AFB
-20151021104350 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE5E381EF
-20151021104414 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE641C193
-20151021104422 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE659F523
-20151021104427 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE660E217
-20151021104438 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE6842F73
-20151021104441 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE689683B
-20151021104455 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE6C41E3B
-20151021104512 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE71E3BFF
-20151021104525 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE75C804F
-20151021104527 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE75DC48B
-20151021104535 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE7738983
-20151021104543 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE787027B
-20151021104610 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8075A1B
-20151021104625 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE84F79B3
-20151021104628 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE859F617
-20151021104641 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8948E2F
-20151021104646 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8A571B3
-20151021104659 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8CEA637
-20151021104705 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8E590FF
-20151021104707 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE8E7943F
-20151021104731 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE95A975F
-20151021104741 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE985F923
-20151021104745 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE996E20B
-20151021104806 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BE9FACFD7
-20151021104827 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEA562C43
-20151021104839 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEA8F25E3
-20151021104939 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEBB1DA0B
-20151021104941 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEBB86153
-20151021105002 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEC1B8883
-20151021105019 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BEC71316F
-20151021105035 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BECB1D113
-20151021105042 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BECC3F3AB
-20151021105045 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BECCC109B
-20151021105101 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BED16353B
-20151021105106 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BED24854F
-20151021105109 2 6 100 2047 2 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BED2AE4B3
-20151021105116 2 6 100 2047 5 F7693FC11FDDEAA493D3BA36F1FFF9264AA9952209203192A88A697BE9D0E306E306A27430BD87AB9EE9DB4BC78C41950C2EB0E5E4C686E8B1BA6D6A2B1FE91EF40C5EA32C51018323E1D305FE637F35ACABDBFC40AD683F779570A76869EB90015A342B2D1F7C81602688081FCAAA8D623090258D9C5C729C8CDDC0C12CA2D561DD987DB79B6AD7A2A509EBC383BF223FD95BC5A2FCC26FB3F3A0DD3FDC1228E338D3290235A596F9465F7BF490974847E616229A9E60B8F4AA161C52F655843CCCAE8821B40C426B535DE087964778652BBD4EC601C0456AE7128B593FCC64402C891227AE6EE88CC839416FBF462B4852999C646BE0BED7D8CF2BED472CF7
-20151021104612 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E360CD0C3
-20151021104628 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3620FBE7
-20151021104701 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E36490F57
-20151021105014 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E377ACADB
-20151021105125 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E37E6DE07
-20151021105320 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E38C2387F
-20151021105649 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3A61E46B
-20151021105815 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3B0A6A4B
-20151021105848 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3B47D2C3
-20151021105948 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3BBBB953
-20151021110011 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3BE3B83B
-20151021110036 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3C0A3F1B
-20151021110201 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3CB1970F
-20151021110208 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3CB70C2B
-20151021110235 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3CE4E4DF
-20151021110424 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3DB68CD7
-20151021110525 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3E290717
-20151021110655 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3ED6DA83
-20151021110731 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3F14C563
-20151021110831 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E3F85477F
-20151021111418 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E420DE56B
-20151021111430 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E421DBA2F
-20151021111624 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E42F39A93
-20151021111916 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E44302363
-20151021112222 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E4585795F
-20151021112245 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E45A1DAFF
-20151021112339 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E4601674F
-20151021112437 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E46691977
-20151021112521 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E46AF3AD3
-20151021112532 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E46BCAE97
-20151021112708 2 6 100 3071 2 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E476520D3
-20151021112724 2 6 100 3071 5 EF9230A29EC5925FD89310E8F3002A60977FBF02543B6BE08667D8E970AD2468FF1B0892B7310073860FA7145250E6FE7A3902CBE70CC7DB0776031A0868780D47644BD8CD714E41B2AC2D744A51ECA4877FE3D2F496D8E6FC03F2F05B29284DA8682F9BCC93CC16846DF724BFAB53FAAC8492CFBFDCBA92A2F12C221E7FAFC4D8AF54156F649C44869592721FDC2AA65BEDC19DCD2CDD9E14F147F18F900A90B48D6D83197BBFE501FC4F19AE7C16D70DDCE3C757970D1CAFB474A0EA215E747E45C05E90935B721058DDF1BFE23C603A367E66C7E096547952663AFFC9A2B8F6292E12E81A6A61A47D032F7EF62DF4A9998D7B21A7917CC89BA68EB1D40BD9625087754618DC06AA486258DBEAA4B177A82ED0D9E2D9442C89D5354B04712F5159CE4EC6EDD608A5BB25700D24EA16E49A20931891C796B53227698132B5E9321905B81BBB7303BAE12DAB4C864A7B305FE9D6B196921F4890229171DE6DF09FA4D1067255F9D0F05F72DDAA6EB55E73F93EEA17B31A46CB33662E477B3317
-20151021105143 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BA7321EB
-20151021105537 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BB3AF34B
-20151021105816 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BBC51883
-20151021110444 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BD1A86C7
-20151021111341 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BEDB7BBB
-20151021111438 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BF0297AB
-20151021111935 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156BFF381FF
-20151021113820 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C433A1BF
-20151021113833 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C43B426B
-20151021113900 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C45007D3
-20151021113921 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C45D8C3B
-20151021113941 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C4685D5F
-20151021114203 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C4F95D97
-20151021114417 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C57ED2FF
-20151021114645 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C612EC33
-20151021114825 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C67219F7
-20151021114922 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C6A942BB
-20151021115945 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156C91E14DB
-20151021120515 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CA5F5DB3
-20151021120715 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CAD0D497
-20151021121027 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CB8F9D6F
-20151021121241 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CC0F677F
-20151021121518 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CC9CC647
-20151021121600 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CCC0ADC3
-20151021121734 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CD1BC68B
-20151021121759 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CD2A7DBF
-20151021122003 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CDA3D323
-20151021122542 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CED8D107
-20151021122856 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156CF8DFEE7
-20151021123548 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D11CAC4F
-20151021123633 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D1426BBB
-20151021124201 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D2A62F0B
-20151021124454 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D353F0FB
-20151021124620 2 6 100 4095 5 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D3AE526F
-20151021125224 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D535C4CB
-20151021130254 2 6 100 4095 2 C8842271626E53546E0C712FA265713F2EE073C20A0723C96B6B182B1EAACC96233D4A199BD0E85F264078A513AD2454F284B8DF543D85019D1E70F2FF54BA43EFBC64AF465C170C3E376F5EC328F98E33E1ED8BED84FA097ABE584152B0E9827ED5CC2B1D4F5ECF2DC46F45C59816D02698EA26F319311E2B6973E83C37021CC8B416AEF653896A1764EE0CEE718A45E8B47CB960BD5907D0E843E8A8E7D4698363C3C3FB3ADC512368B72CAF16510C69052EA2AF51BE00BC8CA04DF1F00A00CC2CA4D74254A1E8738460FD244DDB446CB36554B0A24EEF3710E44DBCF39881E7D3F9AE223388084E7A49A3CB12612AE36416C0EB5628DF1477FEE4A5CF77CDC09AA0E2C989C0B7D1310AFA44B81DA79A65226C7EA510057991EABF9388DC5EA9F52FEA5D3B0872843F50878740794E523E9DC60E0EA1FC8746A7B2AA31FCA89AAA2FA907BED116C69D98F912DD5089BECF28577064225DE96FC214ED1794E7CCE8024F94036D915A123A464C951DA96A5ED7F286F205BEE71BDE2D133FD1891B31178FF25D31611A5B7839F0E68EAF0F8901A571E6917C580F31842A9F19C47E0638483B7947DDCD7864660AC2F8B2C430F1E7FC0F22FA51F96F0499332C5AD3FF9DC7F4332DD5BCCA820CC779B90C0F4C5F0CA52E96FAA187361753FBADC5C80D0492CD80A3EEA5D578772DA9FC1C0E10A0203098AF36D0ED2156D7B5CA43
-20151021111833 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B239959D5A7
-20151021112931 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B239A078C1B
-20151021123021 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B239EC676DF
-20151021131523 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23A2B9FC6B
-20151021141029 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23A7BD762B
-20151021143421 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23A9C3EFDF
-20151021144912 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AB1077AF
-20151021145200 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AB49943B
-20151021145825 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23ABE06353
-20151021150910 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23ACDA0223
-20151021153131 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AE91738F
-20151021154038 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AF40D013
-20151021154300 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23AF75AD97
-20151021155008 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B01C9553
-20151021162240 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B319431B
-20151021162649 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B35A3D2B
-20151021163640 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B439E263
-20151021171004 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B748B983
-20151021172144 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B8609B5B
-20151021173002 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23B9021E9F
-20151021182612 2 6 100 6143 2 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23BE0C1EDB
-20151021190053 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23C120FF97
-20151021192934 2 6 100 6143 5 FD9E6B52785CD7BE64D396A599DA4B97CD0BB49183F932A97694D80CA553354DBC26E77B8A0EC002257AADDF6AD27819CE64A06416E4A80B6EA92F28EA8D5B96C774109EEE5816B4B18F84368D1B41864C11AA73D6881675D779B174F6B4E344303F3EFD11BD7DE468467242372FD00908F296F5A2B20E2684F9122D08A46D647B05E298F0BCDAB60468349CCA6DA1B9FEBBC69D256FB9A3F1980F68466364FCEF1C98C1405191A6737A3627BA7F7313A8A18FC0B8521BF3430B1C6805CB44BCEB39904DD30130D24B225B598ED83C5FD757B80189FD9D5C2F9596687C40BAB1C6ED6244944629849D074A4C33FB15DDB3F9760FC59C44BEBB0EC032177147F61789769DAAAE2123CE488F7ECF19BDA051925BA9ED11EAA72DF70C9ECC8F714B4C35728E6679E66A1B56CCAE0FBBD3F9EBF950D4D623ED78E77CC3AD604E91F304EA78CE876F036214BD6F1977BD04C9ADD707D7A3BCCE87AD5D5A11C95E7025B0EA9C649DCB37942A3970A4FB04C284E4DDB4DC90163353B98B1C254FFD28443353F17A87C02E0BDB9F05424CC44C86309F1D73706F039CDAAC3EDC1A64F38FB42707D351DB5360C2680ADC1CC8D1C4AD312ACC904382C26BE33DA0E61429A5940820356ED28586BEB629ED1521D12D25B4DA01926295F3DA504DC9F431B719AC63277BE675E6F6DD4F7499CA11A23744577D653941963E8DAB610F7F226DB52CE5C683F72AEED2B6CE35ED07C29410397A6F7F606477CCC0EDE18CD0D96A7863BC4606193A8799B5AC1EEE6AC5EE36AC3077EC8DAB30EE94434B45B78BC13D96F74D6C4056EAA528CD3C68D308344808819B12F2BFB95A5C1A7DEEE188BF139216DDB7D757D7A50D3C46CE18881D776D617DCFFAA62276045373AA4D9446D7570338F99C0CA8A08851B4F9D388B4C275D3F9B7BA25F235D4329F63F7457C2EB5C68CE2A96D19766F0ED8E19F66DF3C5E29A38795B2F92291BB6EAB6F70A7E89DC9691F28486E9CF87FF11D5DF2E6B030A30B5D476AD59A34EE7262712ED96CEF4A5CAC3F08B3563D44683F746DA094C9CDB34427AF8D8CC2AE1B23C3BEB637
+20180605163926 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E3790983687163B
+20180605163926 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E379098369B52F3
+20180605163926 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E379098369DE513
+20180605163927 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E37909836B52273
+20180605163928 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E37909836C20313
+20180605163928 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E37909836C9430B
+20180605163929 2 6 100 1023 5 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E37909836DA8707
+20180605163929 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E37909836F54DB3
+20180605163930 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E3790983717A4D3
+20180605163931 2 6 100 1023 5 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E379098372B4C9F
+20180605163931 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E379098372F90F3
+20180605163932 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E3790983730E783
+20180605163932 2 6 100 1023 5 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E379098373292DF
+20180605163932 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E37909837356303
+20180605163933 2 6 100 1023 5 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E3790983743AE7F
+20180605163933 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E379098375E7EEB
+20180605163934 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E379098376750E3
+20180605163934 2 6 100 1023 5 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E379098376EC6E7
+20180605163936 2 6 100 1023 5 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E37909837A659EF
+20180605163936 2 6 100 1023 5 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E37909837AD4BE7
+20180605163937 2 6 100 1023 5 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E37909837B64E27
+20180605163937 2 6 100 1023 5 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E37909837CB4A7F
+20180605163938 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E37909837DDDCB3
+20180605163939 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E37909837FC35C3
+20180605163939 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E37909837FE3CDB
+20180605163939 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E379098380C0B83
+20180605163940 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E37909838128533
+20180605163941 2 6 100 1023 5 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E379098383338D7
+20180605163941 2 6 100 1023 5 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E37909838450DFF
+20180605163942 2 6 100 1023 5 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E37909838487D47
+20180605163942 2 6 100 1023 2 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E379098384CCA3B
+20180605163943 2 6 100 1023 5 C3B299C4B84296166548A199E1A643F5D00EC1A3E5DA6FE1B5A710220B66BF9D991130FE7A1060DA60127D185C4B301F3EFA5FAEC709DCFB84237488F5614314D426009C5A78A50E27B73DC5A642B0733CB216C91B3AD172E74D4F756CD11832F97866AA8E7A415D634A657E7433453DDAB0BC3A261CB7AA8E37909838664DEF
+20180605164241 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC0FCBFECB
+20180605164243 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC0FDD64C3
+20180605164247 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC100666A7
+20180605164250 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC1030926F
+20180605164251 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC1032D8C3
+20180605164256 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC1072924B
+20180605164259 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC1090839F
+20180605164301 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC10A234EB
+20180605164306 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC10DFDBF7
+20180605164309 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC10FA17CB
+20180605164310 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC10FE87E7
+20180605164315 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC11409597
+20180605164318 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC116159DF
+20180605164324 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC11AC1B33
+20180605164327 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC11CA3F3F
+20180605164329 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC11DC7E7B
+20180605164333 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC120452BB
+20180605164335 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC121AA82B
+20180605164336 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC12227373
+20180605164339 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC12408E5B
+20180605164343 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC126E985F
+20180605164343 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC1272F6F3
+20180605164345 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC1279FD67
+20180605164346 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC127EDDEB
+20180605164348 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC129DA56B
+20180605164351 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC12BB0F0B
+20180605164353 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC12CF73D7
+20180605164357 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC12FD603B
+20180605164359 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC13089AEF
+20180605164400 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC131627D3
+20180605164406 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC13547C4F
+20180605164412 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC139D9763
+20180605164412 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC13A041BF
+20180605164416 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC13CDD8EB
+20180605164419 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC13ED0BF3
+20180605164420 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC13EDD913
+20180605164421 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC13F9C1AF
+20180605164423 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC14000907
+20180605164424 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC14109807
+20180605164425 2 6 100 1535 2 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC141232B3
+20180605164426 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC14128AC7
+20180605164426 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC1413D4C7
+20180605164429 2 6 100 1535 5 E0EB69B054B239480F217B62FC7CB9CED55EE1B89CD9EBF68FF762B6FD8EE697715C55A255A32B3B41183E78AF4C28DE8614B1C5DF84C88829625BFEF77BA995868888DFD82E49A069338545170AFEC8D2AEFBBEEB4698BCE4E6D7725848B47661F37361EE3FD6FA8BF99E35E35C94729846E60582D00995663AE1C3666B0AB1AFC9316239DC33438FB72AAE7F760CA5D655706DEF44C2D594D01C9F6AB6F7D0F5EA974D6BE256E518A68A0C8902F10BAF2837E295BADC429BA190AC1427B407
+20180605162024 2 6 100 2047 5 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820A9B6DBF
+20180605162030 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820AB71C5B
+20180605162033 2 6 100 2047 5 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820ABF82EF
+20180605162036 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820AC82523
+20180605162048 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820B08B40B
+20180605162113 2 6 100 2047 5 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820B8A5FA7
+20180605162125 2 6 100 2047 5 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820BC6A33F
+20180605162128 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820BD10B4B
+20180605162138 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820C01495B
+20180605162215 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820CD1DE2B
+20180605162227 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820D0FD0D3
+20180605162248 2 6 100 2047 5 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820D7E119F
+20180605162307 2 6 100 2047 5 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820DE78837
+20180605162313 2 6 100 2047 5 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820E00124F
+20180605162328 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820E52028B
+20180605162338 2 6 100 2047 5 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820E83722F
+20180605162405 2 6 100 2047 5 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820F1A3AE7
+20180605162413 2 6 100 2047 5 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820F3F4EFF
+20180605162422 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820F6C4983
+20180605162445 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820FE667F3
+20180605162448 2 6 100 2047 5 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA820FF1635F
+20180605162455 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA8210101C4B
+20180605162459 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA82102130B3
+20180605162503 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA821032FD0B
+20180605162512 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA821061CB83
+20180605162520 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA8210880823
+20180605162522 2 6 100 2047 5 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA82108C26F7
+20180605162526 2 6 100 2047 5 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA82109CB12F
+20180605162533 2 6 100 2047 5 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA8210BB232F
+20180605162535 2 6 100 2047 5 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA8210BC312F
+20180605162559 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA82114266EB
+20180605162617 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA8211A7EF93
+20180605162620 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA8211B1F463
+20180605162622 2 6 100 2047 2 EF800DA0F9EB4469B688C23071C58D9878E1174F7E07324B0BEA4FB5AE0346081E6F11059BB476DC4AFA0DB79D5F32F4AEA65DA1C9EFA1D004FB6344054D51F8678127338384A32FA7599F49F761C676A2EC1D98632090FD549A088D67E855D40A0FD5611B97974951E78032484E335157CF6FD3AC75534B5C1C138CD2ADB4E3CDE2592FDA8C14A0518D0BD8D857A7B7E5117D84E5E95EEDD90C495461DE8BF7037A392136050EBC5675E407A54C68F4C2DC1DA6B66541B46A12E3AAC9E6F5CE5CCB18C7986B7D9C54B454627150734D15586B91665FF5268A27F6D5F8AA9353C203D76B419600E6F131159CFABF562B925160B8BD1E6C33CAEDDA8211B2B8CB
+20180605165041 2 6 100 3071 5 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A5935413C2A47
+20180605165123 2 6 100 3071 5 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A5935418152F7
+20180605165153 2 6 100 3071 5 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A593541B11757
+20180605165207 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A593541C320AB
+20180605165355 2 6 100 3071 5 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A5935428684D7
+20180605165613 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A5935437F2AFB
+20180605165641 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A593543A9D4DB
+20180605165800 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A5935442F850B
+20180605165954 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A593544F97433
+20180605170035 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A5935453BD0D3
+20180605170132 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A5935459D2583
+20180605170224 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A593545EFFA8B
+20180605170257 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A59354623E5C3
+20180605170321 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A5935464932C3
+20180605171004 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A5935492771BB
+20180605171050 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A593549763053
+20180605171111 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A59354994174B
+20180605171124 2 6 100 3071 5 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A593549A3E147
+20180605171332 2 6 100 3071 5 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A59354A88895F
+20180605171340 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A59354A8E5173
+20180605171346 2 6 100 3071 5 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A59354A903D4F
+20180605171418 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A59354AC3192B
+20180605171917 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A59354CE17653
+20180605172016 2 6 100 3071 5 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A59354D459DC7
+20180605172106 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A59354D9A8CE3
+20180605172258 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A59354E6015A3
+20180605172334 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A59354E99359B
+20180605172635 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A59354FDAF763
+20180605173053 2 6 100 3071 5 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A593551AB6C67
+20180605173245 2 6 100 3071 5 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A5935527032B7
+20180605173251 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A59355272787B
+20180605173312 2 6 100 3071 2 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A5935529301CB
+20180605173342 2 6 100 3071 5 EB5C4079829C2E1A39E88BFF48E2F94A4304E5198072CB97EACD9E3403E692767F80CC8DF04630FFC8B3DBC8521E6A8BC1E7A8FD54F3F28353F8353A6280C97DFBD87D3E8986FD077076C8CB440B2909EDC327470F92BD8BF35F90C0497C5392271CA0291C1F7E3636F5ED8034AC1CADFDE55B103A3B825A55EE452557FB712D34FB597A9D93DBB11FD12AFC1C2ADC95EC76D90AAC1795734C019804CE6F5922E6131CEEB4995C04277252F2D776AA185252A03451A99F2BE4E51ADC514BA754276FB6C3A9ACB9E2BB474D7F519B5BC56DC00D0D042DC066543F639569F00DD59FC1ADADCDD88FCFF0CDA84B8E7D8A58D77B9A22D2800A91EBE47B9B986AC9498A91E891A55CC17C6A398F04D2A14D30A205DAC8A41A7C33010298CF8FE53D9CC46F2AB136798C548ED9A503C132AD48DB1D038137636039BEB6983AC2EF3F2EF287CAB70F37455E206BF7684C8214191FBFFF447B587A3D94143336A22C1A83B6AB9A7DC2EB1099D04F7B9F4E134FB7A2329CCCE6E0FE73AB9A593552C1A7E7
+20180605174443 2 6 100 4095 5 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F71BB9EBA7
+20180605175218 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F71D2678A3
+20180605175425 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F71D861ED3
+20180605175901 2 6 100 4095 5 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F71E5FB7CF
+20180605180343 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F71F3B10EB
+20180605180359 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F71F3EFC3B
+20180605181956 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F7224AFBAB
+20180605182309 2 6 100 4095 5 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F722DFE397
+20180605182606 2 6 100 4095 5 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F723682E0F
+20180605183001 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F7241C6B53
+20180605183144 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F72468A833
+20180605183823 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F725A5A94B
+20180605184629 2 6 100 4095 5 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F7271E9047
+20180605184939 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F727B4FF23
+20180605190534 2 6 100 4095 5 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F72AAFF2BF
+20180605190753 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F72B14D523
+20180605191340 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F72C1ED923
+20180605191639 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F72CA9B123
+20180605193155 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F72F768B5B
+20180605193341 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F72FC32ECB
+20180605194146 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F73137091B
+20180605194618 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F7320594AB
+20180605194826 2 6 100 4095 5 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F7326065DF
+20180605194913 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F7327A7273
+20180605195719 2 6 100 4095 5 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F733F6EE4F
+20180605200053 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F7349A133B
+20180605200209 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F734CDA683
+20180605200404 2 6 100 4095 5 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F73524AC77
+20180605200812 2 6 100 4095 5 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F735E21A27
+20180605201507 2 6 100 4095 5 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F737264DFF
+20180605201935 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F737F47113
+20180605202538 2 6 100 4095 2 C99ACF60A371F11C9A02EA6920EA7F8F897742FD159713DE275C9C05059C86D7433F57043C70CC9D33F1E3CE222BB1991703F5F9688AAAF21305A0C263C82CAC5174B2621A318E14B1D7888B5F7ECDD4737101DCEC368A64AB38430AE56C3A6300E36FE8FB57C3619327C62ADC80671F67DC772A9C44EFB266D1120F9B9E7DEE5E3D092D6560D2794BFE19391FF4D11D5860DA7D110F3E13F6503765AA4060394E92F6E4301AEB248BFEA34182444B09732F95AA9B0FAAE1DC295022F1267099DE7E23B50D85585BED875C529FA59D642A09743222FDA04031281D729E9C2E9FC3E22FAE8C1AEA0A0F2FF7EC0C32E9B6B190B71917FFB8949A3ADB771843AE1DD39A3DAE9521CE2D10D2D12584E9289D849DBB9A52C7D990FA52EF786A0CA3D33EEDDD1F7350F501EC0ADAFBCA1B825FE995BF373853AC3FE33E48E728D918FA9A68B0E60F283EC8232B8F00984DB33C8800F9800183709C71F7CD5DF5837799837B473BFDB77E579DD76A2A239BFE09D0E32401B7D784391EEC064DF984E29F5C67F7F039BC8F156407AABD94879B4ABD773DA5506743A2E1AC7A5250ED51DD3D30E2CCC63971F1C72E7F424009884416F869A701C5257E9A6A1580324971575BF2999D37088AFB1B57B6F582007B7927CDE06166F2E500B5AC2C5143E6BE0C1A9AF4FEC2C9F688C86EB7DCB6A2C0F9CF6E4901361CAFC40EC640F7390F0743
+20180606081635 2 6 100 6143 5 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A3819B8FC5F
+20180606083850 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A381B1D13EB
+20180606084353 2 6 100 6143 5 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A381B65B5F7
+20180606090554 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A381CB9AFDB
+20180606092723 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A381E06BDBB
+20180606093241 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A381E51ADE3
+20180606101118 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A3820AE5D83
+20180606101425 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A3820D4A8DB
+20180606103024 2 6 100 6143 5 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A3821C99D9F
+20180606115838 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A3827308863
+20180606121641 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A38284780CB
+20180606121947 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A38286F57DB
+20180606131248 2 6 100 6143 5 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A382B9CA287
+20180606135001 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A382DD37563
+20180606140647 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A382ECDF72B
+20180606143527 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A383086B0F3
+20180606152011 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A38333510EB
+20180606153449 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A3834099ED3
+20180606154730 2 6 100 6143 5 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A3834C6C2F7
+20180606155117 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A3834F7FF83
+20180606191134 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A3840D756E3
+20180606201246 2 6 100 6143 5 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A38446BC09F
+20180606211911 2 6 100 6143 5 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A384849597F
+20180606223301 2 6 100 6143 5 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A384C9296DF
+20180606230821 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A384E995923
+20180607010019 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A38550B3B83
+20180607010449 2 6 100 6143 5 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A385542D20F
+20180607022006 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A3859892A7B
+20180607022905 2 6 100 6143 2 E52412D53049FA1E04E2773DFEC7889C30A4F3D4C3B3F7097EE2AF5389338B19F1A6F05E376AACA05A03716100BA338DA622A68FBE05566BBE6A32410BFAAF78177F712BEEE39DC8282F5E395907F7B7BB12E2A4C5C5E960E3C130C6F47F5A4D3E568D82E2D3A2BCB2BFDBDEA6739C8BB88F694A66EBF24F1AE57EB8C932B4DD9E83E0B400B70670CC4956B5B6E8F386D597FBDD1B7C7835024F002C2D3786B6BB82877959B16A78ED6192602832F6931E0A822D4ED88EB2BFA40234061518AC7E18EA0DF2398E27ECA306532B6155E18477E5A74B005A7A3903F762930F0EAA569B7C50B7502E3D4E4EDB115627DE49BBDED6528FFBBEEBF16D7D3EE29D61B0D5859ABDD8665345D05F7E5DD8FBB170203113333A87502E3E299E90F2D83AF447D67ADA23E77475E0E7416860385EDF12DD59F2576551D9E82457396064EDE8D13BDDF3F40AE591B4A0D3CB0527454EFABC40E629AF3B5A02BDCA06E194A195B13AD319E81915AB1375BB952A0B779040C46C23184962602D70BB0CBA2ED70AB24E2EB08B1BAEFE96D14154FCF1D00461A4D0B7291EC5010678482A136E4B3A4588C80C7AD89189FAA17F29FF4E5D318079EE5C181CC2CF586A6F73114BD85117EB97FE65CC2D2E3441B688C0DBDD11909783227150DF0FEE0946F39E6565285A62CCBF5464D5A518A7D217C6142A31134C0E8A8F401930F3A6979BC35C24275247444FBAAC542AB1280E7B455888F3AD8FE770FF3782DA1A5D76B3C633C40EC2E6A1B0615AF15931D3DD11F98907E0B836B16D5A2E450A97747509EFEB9963BC306A650B3215E1E0FCCEF9F323B56B75D579A8B280D757E2D28D7ABD079E2C0A7FAE800035BD7386E4EB901AA3BE80644720E625195CA36048A7C3514BD0247C37AD92AA3265B496C539B7DE84E39909E982A6D10D177803B0D38E2B80323C1DE7AD104FD5C1D1D631DA6309651C987255308DBE2DF7F4ED233BF6E6C07AD563E6F6FA23E3E9D248135EF83CBC35DB87F39E666F238B8DB06200DCF63EFA84117C2FDF365125604E09D972A32CA03490FD7D81C947C0B278BB2A385A0321EB
+20180607113212 2 6 100 8191 5 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD9285F38A617
+20180607125146 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928617A82F3
+20180607125328 2 6 100 8191 5 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928617CB5DF
+20180607151424 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD92865898703
+20180607154110 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928664CFCC3
+20180607160549 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD92866F6C0D3
+20180607170551 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD92868ADB733
+20180607185631 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD9286BD88C63
+20180607214035 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928707BBADB
+20180607235316 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928743304D3
+20180608011956 2 6 100 8191 5 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928769DD007
+20180608062301 2 6 100 8191 5 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD9287EFA162F
+20180608062621 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD9287F06E163
+20180608091419 2 6 100 8191 5 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD92883A67EDF
+20180608093938 2 6 100 8191 5 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD92884520EDF
+20180608122935 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD92888E78073
+20180608144406 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD9288C8EB5F3
+20180608204615 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928965840CB
+20180608213353 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928979C33F3
+20180608221715 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD92898C4F47B
+20180608230356 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD92899FB78E3
+20180609004940 2 6 100 8191 5 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD9289CC3013F
+20180609041610 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928A235CA2B
+20180609054840 2 6 100 8191 5 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928A49B8067
+20180609133521 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928B0B91E4B
+20180609143811 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928B24E1BF3
+20180609222946 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928BE4C0EC3
+20180610032425 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928C5BA8AFB
+20180610042318 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928C72C452B
+20180610043314 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928C762DC4B
+20180610072715 2 6 100 8191 5 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928CBBDB7BF
+20180610083654 2 6 100 8191 5 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928CD718587
+20180610085444 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928CDD91733
+20180610125906 2 6 100 8191 2 CEC852A0F60D2D7ECA1964A06B30C9C74CED6097183E357235647B360695981BFCA2F828FF22BB22CBCFF24E5B421D02E4169AA216FA977C33943011749067AF3996452BEB9C466CB71DB44802D60450F77A488C2C653115C2DD322D781CB1F4F70CBA60F5030B2569B1147F1EA25872E40326FF2F21D60DDBCC2350883EDF246F9F60D2BED0887D8CD9629A2317C4342785BED83D75765C8CCB9770B156256AB3A3D2F1E5C213BF51DA215802212A3EB18ECA6AFB944D26382E2F314FFB6F83AA2BB057E17BF7BE2604BEFF9BEAF8C72594B5097B97CDE8B4724B7A41816481154886EA99878F7D1570F1365971A237B18B0C048B4E0B550F0E4B84B0AEA8111991ADDB782A2585632E85100B8E6B04048565A70F699A04DF650C7FD138F489FC7B6D5D306FD86902666DA4C2F5259795BAEFA426F391265C2840232DC57DF50093EB6A6BDA2884BE777701953FBA502A233D811A49EBF59241B5931C6DAFC1CF3CFD688E182D8D27FF2CE1CA1D5AB06A44ACF0BAC4A35BF5212955D52AF7FE1F0EED58205C7A08EDF536AB22727C670B56D3F134485D4D4CE3D93883EA07AB900E4B9E1B39B6C19FFACFF664224038B5DE4C97DF0008282E6DDFCB9CAD35CD18FD9EE5EDCE40800E741F5CACAC25CEA9EF53C3B43008FF371EF9453A4E4AB69112C5761E903B5656D7FCA40090A1B26C8670217A2DF0AB05F4E530E1445FB243F2E8376BA169BD46A57EED72BE4395D77F5C595E422DECC125DC9ED0445CC15BC977F7DB6F683A419D862606E8EEC600CB206CDB958E9C98DC23E42BCDAE6560561177C4A119E0C65B22121B127B0A3E4A1D92CB42C297E59EDCD056F32DF3B8BF436785A842414BE3203395703B08EA6DCE4ECFE7831A882C0E0644C9D8C259CBFB3DB05AFCA2669D61D2E12EC3EB7BB105BC96627D239F3009F246CB5312C35420251A92F49C0B4C4B51B5526919C6767A13068A220497DFDEA49FC181F4EA2BAF496AE58E2A924F27F658FE6F7F7E21E26F5BCE5D469ABD9F3F19766051E9352CDB1324388C5DB78A6BD1DC861BE588FFDE7DDFE87F1CB0E9F422BD2B95A1EDC2D65EF9A88F36465053F4611E2B425CA697D4ACB99B5DE6B699495EA2F8F840D4720E40F475D3761432EBAAB46C15F2C251AB9C0AA4FAADEFD40B3C707F7B2A6729E55342F8728D21D263FF204B95407976147B9482170466B718232AA3E82A0C53049C6B2C0884830CEDCD8B9992309BB49BFD6BFD4695B0060540DE388DABC39D732B392F38D433EE0C02BE154DD8A48DB89BD98CB161A63AEEB0D25CC9A29D7C6F3780EA87808E8463E9EE46CBD669FAD39B6BDF75B054951784154BAB9C0BC554F30258AC6B39D72A492C027EE8955704E44414DF957398A9A0DA9005E6B152930F7A71AEEAAF2543947A773545E7A8B0B9C13F0CCAD928D3DBCC1B
20151021113847 2 6 100 8191 2 DC61EF13E4F3FC10CC946EEABC33F83EFCB35E0F47E4EC25C1CCBB2C7B502B2EFB0691AA231C8476DD51BA73204E6EA10B1A970FE2CF14AF01E72E1AEA87519A91D00D1499189F94A6CDA9E29C05F11F17FE74A4919A710A2787E180744465DF81C62AA65662FDA46FA6175E8A31E5B29E66DED6701C8FC4217E91D733FE94380F046680967D4CEA7BAC8F3916CDF96AA2C474FAD9650F48403FD0B5B756D34667D36A07767FA33027AE55484D0F701C3CA16632F413A14E4B8645AFAF15B78978C19A7661EDC569BEC72394B1204B166A48FCD5F56BE29840C7794CA6D3440356F15858CDCA9B429C7EA92E17242893FDC8C9C63841A382C32F20CFAB121B4BCAFD7BF9EF07FBF7CDFFECA0CEF3A49C3E2B24FA836F3318435255655E1B281071F62D5E4CD63361299B7828F72936E3FEA9E8044562A6F6ADD5321187C3101E4669C6271598FE1A866C93FE2870A4CEB9254BA32A4719E439317EA42200A335B5CFFA7946A7D0F1BD1A69AA11288B73C71C80B77FE3707CB077DDDEA5CA36A449FAB230C9625A0B12F8275D3FF82F5DA380E7A3F11B6F155FE7E91AC960BD95D9B13F7423AB9B15CC3C4DC34EF296033F009468EA16A721AD659F56C18516025050749ABF05E6D3EBD9778142A530979291F46DAA399A86B7BCDF09CC3E6EEF101419762A306DB45AEFC96C64E83F28338D55905F6A387E0F515E580C3A9B35330E21C32198CDEE3AFB355967A098F635FCA7C49CB4E1E82464B2B390EF1F259E40B9A06235C0273F76284FE6BD534EF3AF7CB01A4A5252B8B94CADC2850B2E56D53F9A31D7C029DF967D0A30C05BC64E119BED6076818FABC8CDD93F3255693E14EFC1A740A5D63A5E847FFE87BAB1DDE0506E1762EA61EFA9F9756151ECCCADD91B98A961A901A2D8B01ABDDD29EC804E8C8D28214BBA26048F924CA66316696E51A49D02FF034D20E44914B1115339CAD3819E0CB1640F0084886FEDDE5E28C29DC48ED30A8C3D789734338F5A9DF42584326E536FD1CF30BC85B8DCBD6120D127C98FE4B3614074F13C2CA4854E6D794156C185C40EB3DA7619CE96ADAF0941BD5499848B034C2B11DFECC0BDFA81C594241F759EF53FC7CDE7F2DE4F23CF81A5A0B7D62E31DABB9198D40307F7824DD130B7D1B80E9B6D322FEEDB5ACE34944F0BFB7D016762A9B2E173BFDD69303766AFBAB45FAB75D05430B4A3515858C4B7F04E23414E4AD03842CB0A20D8FF4B59B7C852BA9A5BE982A8ADA5CB70C36CE2A4D2C31A7015C9F3275E43D192C1B2924424088907A057DA7F2D32A2149922AB2E33F2147D637A3508911CB3FEA5E1AAB4525BACF27B6DD7A3E0AFA978FC3A39DE8882FB22688C3CCC92B6E69ACB0BBF575AB3368E51A2F6A20C414C6F146727CC0045F29061E695D29F7C030CE6929EB3AD11A5CBD0CDEE37347869A3
20151021133636 2 6 100 8191 2 DC61EF13E4F3FC10CC946EEABC33F83EFCB35E0F47E4EC25C1CCBB2C7B502B2EFB0691AA231C8476DD51BA73204E6EA10B1A970FE2CF14AF01E72E1AEA87519A91D00D1499189F94A6CDA9E29C05F11F17FE74A4919A710A2787E180744465DF81C62AA65662FDA46FA6175E8A31E5B29E66DED6701C8FC4217E91D733FE94380F046680967D4CEA7BAC8F3916CDF96AA2C474FAD9650F48403FD0B5B756D34667D36A07767FA33027AE55484D0F701C3CA16632F413A14E4B8645AFAF15B78978C19A7661EDC569BEC72394B1204B166A48FCD5F56BE29840C7794CA6D3440356F15858CDCA9B429C7EA92E17242893FDC8C9C63841A382C32F20CFAB121B4BCAFD7BF9EF07FBF7CDFFECA0CEF3A49C3E2B24FA836F3318435255655E1B281071F62D5E4CD63361299B7828F72936E3FEA9E8044562A6F6ADD5321187C3101E4669C6271598FE1A866C93FE2870A4CEB9254BA32A4719E439317EA42200A335B5CFFA7946A7D0F1BD1A69AA11288B73C71C80B77FE3707CB077DDDEA5CA36A449FAB230C9625A0B12F8275D3FF82F5DA380E7A3F11B6F155FE7E91AC960BD95D9B13F7423AB9B15CC3C4DC34EF296033F009468EA16A721AD659F56C18516025050749ABF05E6D3EBD9778142A530979291F46DAA399A86B7BCDF09CC3E6EEF101419762A306DB45AEFC96C64E83F28338D55905F6A387E0F515E580C3A9B35330E21C32198CDEE3AFB355967A098F635FCA7C49CB4E1E82464B2B390EF1F259E40B9A06235C0273F76284FE6BD534EF3AF7CB01A4A5252B8B94CADC2850B2E56D53F9A31D7C029DF967D0A30C05BC64E119BED6076818FABC8CDD93F3255693E14EFC1A740A5D63A5E847FFE87BAB1DDE0506E1762EA61EFA9F9756151ECCCADD91B98A961A901A2D8B01ABDDD29EC804E8C8D28214BBA26048F924CA66316696E51A49D02FF034D20E44914B1115339CAD3819E0CB1640F0084886FEDDE5E28C29DC48ED30A8C3D789734338F5A9DF42584326E536FD1CF30BC85B8DCBD6120D127C98FE4B3614074F13C2CA4854E6D794156C185C40EB3DA7619CE96ADAF0941BD5499848B034C2B11DFECC0BDFA81C594241F759EF53FC7CDE7F2DE4F23CF81A5A0B7D62E31DABB9198D40307F7824DD130B7D1B80E9B6D322FEEDB5ACE34944F0BFB7D016762A9B2E173BFDD69303766AFBAB45FAB75D05430B4A3515858C4B7F04E23414E4AD03842CB0A20D8FF4B59B7C852BA9A5BE982A8ADA5CB70C36CE2A4D2C31A7015C9F3275E43D192C1B2924424088907A057DA7F2D32A2149922AB2E33F2147D637A3508911CB3FEA5E1AAB4525BACF27B6DD7A3E0AFA978FC3A39DE8882FB22688C3CCC92B6E69ACB0BBF575AB3368E51A2F6A20C414C6F146727CC0045F29061E695D29F7C030CE6929EB3AD11A5CBD0CDEE373914ECA3
-20151021140108 2 6 100 8191 5 DC61EF13E4F3FC10CC946EEABC33F83EFCB35E0F47E4EC25C1CCBB2C7B502B2EFB0691AA231C8476DD51BA73204E6EA10B1A970FE2CF14AF01E72E1AEA87519A91D00D1499189F94A6CDA9E29C05F11F17FE74A4919A710A2787E180744465DF81C62AA65662FDA46FA6175E8A31E5B29E66DED6701C8FC4217E91D733FE94380F046680967D4CEA7BAC8F3916CDF96AA2C474FAD9650F48403FD0B5B756D34667D36A07767FA33027AE55484D0F701C3CA16632F413A14E4B8645AFAF15B78978C19A7661EDC569BEC72394B1204B166A48FCD5F56BE29840C7794CA6D3440356F15858CDCA9B429C7EA92E17242893FDC8C9C63841A382C32F20CFAB121B4BCAFD7BF9EF07FBF7CDFFECA0CEF3A49C3E2B24FA836F3318435255655E1B281071F62D5E4CD63361299B7828F72936E3FEA9E8044562A6F6ADD5321187C3101E4669C6271598FE1A866C93FE2870A4CEB9254BA32A4719E439317EA42200A335B5CFFA7946A7D0F1BD1A69AA11288B73C71C80B77FE3707CB077DDDEA5CA36A449FAB230C9625A0B12F8275D3FF82F5DA380E7A3F11B6F155FE7E91AC960BD95D9B13F7423AB9B15CC3C4DC34EF296033F009468EA16A721AD659F56C18516025050749ABF05E6D3EBD9778142A530979291F46DAA399A86B7BCDF09CC3E6EEF101419762A306DB45AEFC96C64E83F28338D55905F6A387E0F515E580C3A9B35330E21C32198CDEE3AFB355967A098F635FCA7C49CB4E1E82464B2B390EF1F259E40B9A06235C0273F76284FE6BD534EF3AF7CB01A4A5252B8B94CADC2850B2E56D53F9A31D7C029DF967D0A30C05BC64E119BED6076818FABC8CDD93F3255693E14EFC1A740A5D63A5E847FFE87BAB1DDE0506E1762EA61EFA9F9756151ECCCADD91B98A961A901A2D8B01ABDDD29EC804E8C8D28214BBA26048F924CA66316696E51A49D02FF034D20E44914B1115339CAD3819E0CB1640F0084886FEDDE5E28C29DC48ED30A8C3D789734338F5A9DF42584326E536FD1CF30BC85B8DCBD6120D127C98FE4B3614074F13C2CA4854E6D794156C185C40EB3DA7619CE96ADAF0941BD5499848B034C2B11DFECC0BDFA81C594241F759EF53FC7CDE7F2DE4F23CF81A5A0B7D62E31DABB9198D40307F7824DD130B7D1B80E9B6D322FEEDB5ACE34944F0BFB7D016762A9B2E173BFDD69303766AFBAB45FAB75D05430B4A3515858C4B7F04E23414E4AD03842CB0A20D8FF4B59B7C852BA9A5BE982A8ADA5CB70C36CE2A4D2C31A7015C9F3275E43D192C1B2924424088907A057DA7F2D32A2149922AB2E33F2147D637A3508911CB3FEA5E1AAB4525BACF27B6DD7A3E0AFA978FC3A39DE8882FB22688C3CCC92B6E69ACB0BBF575AB3368E51A2F6A20C414C6F146727CC0045F29061E695D29F7C030CE6929EB3AD11A5CBD0CDEE373A17959F
+b20151021140108 2 6 100 8191 5 DC61EF13E4F3FC10CC946EEABC33F83EFCB35E0F47E4EC25C1CCBB2C7B502B2EFB0691AA231C8476DD51BA73204E6EA10B1A970FE2CF14AF01E72E1AEA87519A91D00D1499189F94A6CDA9E29C05F11F17FE74A4919A710A2787E180744465DF81C62AA65662FDA46FA6175E8A31E5B29E66DED6701C8FC4217E91D733FE94380F046680967D4CEA7BAC8F3916CDF96AA2C474FAD9650F48403FD0B5B756D34667D36A07767FA33027AE55484D0F701C3CA16632F413A14E4B8645AFAF15B78978C19A7661EDC569BEC72394B1204B166A48FCD5F56BE29840C7794CA6D3440356F15858CDCA9B429C7EA92E17242893FDC8C9C63841A382C32F20CFAB121B4BCAFD7BF9EF07FBF7CDFFECA0CEF3A49C3E2B24FA836F3318435255655E1B281071F62D5E4CD63361299B7828F72936E3FEA9E8044562A6F6ADD5321187C3101E4669C6271598FE1A866C93FE2870A4CEB9254BA32A4719E439317EA42200A335B5CFFA7946A7D0F1BD1A69AA11288B73C71C80B77FE3707CB077DDDEA5CA36A449FAB230C9625A0B12F8275D3FF82F5DA380E7A3F11B6F155FE7E91AC960BD95D9B13F7423AB9B15CC3C4DC34EF296033F009468EA16A721AD659F56C18516025050749ABF05E6D3EBD9778142A530979291F46DAA399A86B7BCDF09CC3E6EEF101419762A306DB45AEFC96C64E83F28338D55905F6A387E0F515E580C3A9B35330E21C32198CDEE3AFB355967A098F635FCA7C49CB4E1E82464B2B390EF1F259E40B9A06235C0273F76284FE6BD534EF3AF7CB01A4A5252B8B94CADC2850B2E56D53F9A31D7C029DF967D0A30C05BC64E119BED6076818FABC8CDD93F3255693E14EFC1A740A5D63A5E847FFE87BAB1DDE0506E1762EA61EFA9F9756151ECCCADD91B98A961A901A2D8B01ABDDD29EC804E8C8D28214BBA26048F924CA66316696E51A49D02FF034D20E44914B1115339CAD3819E0CB1640F0084886FEDDE5E28C29DC48ED30A8C3D789734338F5A9DF42584326E536FD1CF30BC85B8DCBD6120D127C98FE4B3614074F13C2CA4854E6D794156C185C40EB3DA7619CE96ADAF0941BD5499848B034C2B11DFECC0BDFA81C594241F759EF53FC7CDE7F2DE4F23CF81A5A0B7D62E31DABB9198D40307F7824DD130B7D1B80E9B6D322FEEDB5ACE34944F0BFB7D016762A9B2E173BFDD69303766AFBAB45FAB75D05430B4A3515858C4B7F04E23414E4AD03842CB0A20D8FF4B59B7C852BA9A5BE982A8ADA5CB70C36CE2A4D2C31A7015C9F3275E43D192C1B2924424088907A057DA7F2D32A2149922AB2E33F2147D637A3508911CB3FEA5E1AAB4525BACF27B6DD7A3E0AFA978FC3A39DE8882FB22688C3CCC92B6E69ACB0BBF575AB3368E51A2F6A20C414C6F146727CC0045F29061E695D29F7C030CE6929EB3AD11A5CBD0CDEE373A17959F
diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl
index f45f2c2e9a..61a1239d26 100644
--- a/lib/public_key/src/pubkey_cert.erl
+++ b/lib/public_key/src/pubkey_cert.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,12 +32,29 @@
is_issuer/2, issuer_id/2, distribution_points/1,
is_fixed_dh_cert/1, verify_data/1, verify_fun/4,
select_extension/2, match_name/3,
- extensions_list/1, cert_auth_key_id/1, time_str_2_gregorian_sec/1]).
+ extensions_list/1, cert_auth_key_id/1, time_str_2_gregorian_sec/1,
+ gen_test_certs/1, root_cert/2]).
-define(NULL, 0).
-
+
+-export_type([cert_opt/0, chain_opts/0, conf_opt/0,
+ test_config/0, test_root_cert/0]).
+
+-type cert_opt() :: {digest, public_key:digest_type()} |
+ {key, public_key:key_params() | public_key:private_key()} |
+ {validity, {From::erlang:timestamp(), To::erlang:timestamp()}} |
+ {extensions, [#'Extension'{}]}.
+-type chain_end() :: root | peer.
+-type chain_opts() :: #{chain_end() := [cert_opt()], intermediates => [[cert_opt()]]}.
+-type conf_opt() :: {cert, public_key:der_encoded()} |
+ {key, public_key:private_key()} |
+ {cacerts, [public_key:der_encoded()]}.
+-type test_config() ::
+ #{server_config := [conf_opt()], client_config := [conf_opt()]}.
+-type test_root_cert() ::
+ #{cert := binary(), key := public_key:private_key()}.
%%====================================================================
-%% Internal application API
+%% Internal application APIu
%%====================================================================
%%--------------------------------------------------------------------
@@ -354,23 +371,23 @@ match_name(directoryName, DirName, [PermittedName | Rest]) ->
match_name(fun is_rdnSeq/2, DirName, PermittedName, Rest);
match_name(uniformResourceIdentifier, URI, [PermittedName | Rest]) ->
- case split_uri(URI) of
- incomplete ->
- false;
- {_, _, Host, _, _} ->
- PN = case split_uri(PermittedName) of
- {_, _, PNhost, _, _} -> PNhost;
+ case uri_string:normalize(URI, [return_map]) of
+ #{host := Host} ->
+ PN = case uri_string:normalize(PermittedName, [return_map]) of
+ #{host := PNhost} -> PNhost;
_X -> PermittedName
end,
- match_name(fun is_valid_host_or_domain/2, Host, PN, Rest)
+ match_name(fun is_valid_host_or_domain/2, Host, PN, Rest);
+ _ ->
+ false
end;
match_name(emailAddress, Name, [PermittedName | Rest]) ->
Fun = fun(Email, PermittedEmail) ->
- is_valid_email_address(Email, PermittedEmail,
- string:tokens(PermittedEmail,"@"))
- end,
- match_name(Fun, Name, PermittedName, Rest);
+ is_valid_email_address(Email, PermittedEmail,
+ string:tokens(PermittedEmail,"@"))
+ end,
+ match_name(Fun, Name, PermittedName, Rest);
match_name(dNSName, Name, [PermittedName | Rest]) ->
Fun = fun(Domain, [$.|Domain]) -> true;
@@ -418,6 +435,94 @@ match_name(Fun, Name, PermittedName, [Head | Tail]) ->
match_name(Fun, Name, Head, Tail)
end.
+%%%
+-spec gen_test_certs(#{server_chain:= chain_opts(),
+ client_chain:= chain_opts()} |
+ chain_opts()) ->
+ test_config() |
+ [conf_opt()].
+%%
+%% Generates server and and client configuration for testing
+%% purposes. All certificate options have default values
+gen_test_certs(
+ #{client_chain :=
+ #{root := ClientRoot,
+ intermediates := ClientCAs,
+ peer := ClientPeer},
+ server_chain :=
+ #{root := ServerRoot,
+ intermediates := ServerCAs,
+ peer := ServerPeer}}) ->
+ #{cert := ServerRootCert, key := ServerRootKey} =
+ case ServerRoot of
+ #{} ->
+ ServerRoot;
+ ServerRootConf when is_list(ServerRootConf) ->
+ root_cert("SERVER ROOT CA", ServerRootConf)
+ end,
+ #{cert := ClientRootCert, key := ClientRootKey} =
+ case ClientRoot of
+ #{} ->
+ ClientRoot;
+ ClientRootConf when is_list(ClientRootConf) ->
+ root_cert("CLIENT ROOT CA", ClientRootConf)
+ end,
+ [{ServerDERCert, ServerDERKey} | ServerCAsKeys] =
+ config(
+ server, ServerRootCert, ServerRootKey,
+ lists:reverse([ServerPeer | lists:reverse(ServerCAs)])),
+ [{ClientDERCert, ClientDERKey} | ClientCAsKeys] =
+ config(
+ client, ClientRootCert, ClientRootKey,
+ lists:reverse([ClientPeer | lists:reverse(ClientCAs)])),
+ ServerDERCA = ca_config(ClientRootCert, ServerCAsKeys),
+ ClientDERCA = ca_config(ServerRootCert, ClientCAsKeys),
+ #{server_config =>
+ [{cert, ServerDERCert}, {key, ServerDERKey},
+ {cacerts, ServerDERCA}],
+ client_config =>
+ [{cert, ClientDERCert}, {key, ClientDERKey},
+ {cacerts, ClientDERCA}]};
+%%
+%% Generates a node configuration for testing purposes,
+%% when using the node server cert also for the client.
+%% All certificate options have default values
+gen_test_certs(
+ #{root := Root, intermediates := CAs, peer := Peer}) ->
+ #{cert := RootCert, key := RootKey} =
+ case Root of
+ #{} ->
+ Root;
+ RootConf when is_list(RootConf) ->
+ root_cert("SERVER ROOT CA", RootConf)
+ end,
+ [{DERCert, DERKey} | CAsKeys] =
+ config(
+ server, RootCert, RootKey,
+ lists:reverse([Peer | lists:reverse(CAs)])),
+ DERCAs = ca_config(RootCert, CAsKeys),
+ [{cert, DERCert}, {key, DERKey}, {cacerts, DERCAs}].
+
+%%%
+-spec root_cert(string(), [cert_opt()]) -> test_root_cert().
+%%
+%% Generate a self-signed root cert
+root_cert(Name, Opts) ->
+ PrivKey = gen_key(proplists:get_value(key, Opts, default_key_gen())),
+ TBS = cert_template(),
+ Issuer = subject("root", Name),
+ OTPTBS =
+ TBS#'OTPTBSCertificate'{
+ signature = sign_algorithm(PrivKey, Opts),
+ issuer = Issuer,
+ validity = validity(Opts),
+ subject = Issuer,
+ subjectPublicKeyInfo = public_key(PrivKey),
+ extensions = extensions(undefined, ca, Opts)
+ },
+ #{cert => public_key:pkix_sign(OTPTBS, PrivKey),
+ key => PrivKey}.
+
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
@@ -763,75 +868,12 @@ is_valid_subject_alt_name({otherName, #'AnotherName'{}}) ->
is_valid_subject_alt_name({_, _}) ->
false.
-is_ip_address(Address) ->
- case inet_parse:address(Address) of
- {ok, _} ->
- true;
- _ ->
- false
- end.
-
-is_fully_qualified_name(_Name) ->
- true.
-
is_valid_uri(AbsURI) ->
- case split_uri(AbsURI) of
- incomplete ->
- false;
- {StrScheme, _, Host, _, _} ->
- case string:to_lower(StrScheme) of
- Scheme when Scheme =:= "http"; Scheme =:= "ftp" ->
- is_valid_host(Host);
- _ ->
- false
- end
- end.
-
-is_valid_host(Host) ->
- case is_ip_address(Host) of
- true ->
- true;
- false ->
- is_fully_qualified_name(Host)
- end.
-
-%% Could have a more general split URI in stdlib? Maybe when
-%% regexs are improved. Needed also in inets!
-split_uri(Uri) ->
- case split_uri(Uri, ":", {error, no_scheme}, 1, 1) of
- {error, no_scheme} ->
- incomplete;
- {StrScheme, "//" ++ URIPart} ->
- {Authority, PathQuery} =
- split_auth_path(URIPart),
- {UserInfo, HostPort} =
- split_uri(Authority, "@", {"", Authority}, 1, 1),
- {Host, Port} =
- split_uri(HostPort, ":", {HostPort, dummy_port}, 1, 1),
- {StrScheme, UserInfo, Host, Port, PathQuery}
- end.
-
-split_auth_path(URIPart) ->
- case split_uri(URIPart, "/", URIPart, 1, 0) of
- Split = {_, _} ->
- Split;
- URIPart ->
- case split_uri(URIPart, "\\?", URIPart, 1, 0) of
- Split = {_, _} ->
- Split;
- URIPart ->
- {URIPart,""}
- end
- end.
-
-split_uri(UriPart, SplitChar, NoMatchResult, SkipLeft, SkipRight) ->
- case re:run(UriPart, SplitChar) of
- {match,[{Start, _}]} ->
- StrPos = Start + 1,
- {string:substr(UriPart, 1, StrPos - SkipLeft),
- string:substr(UriPart, StrPos + SkipRight, length(UriPart))};
- nomatch ->
- NoMatchResult
+ case uri_string:normalize(AbsURI, [return_map]) of
+ #{scheme := _} ->
+ true;
+ _ ->
+ false
end.
is_rdnSeq({rdnSequence,[]}, {rdnSequence,[none]}) ->
@@ -1064,3 +1106,206 @@ missing_basic_constraints(OtpCert, SelfSigned, ValidationState, VerifyFun, UserS
Len - 1},
UserState}
end.
+
+gen_key(KeyGen) ->
+ case is_key(KeyGen) of
+ true ->
+ KeyGen;
+ false ->
+ public_key:generate_key(KeyGen)
+ end.
+
+is_key(#'DSAPrivateKey'{}) ->
+ true;
+is_key(#'RSAPrivateKey'{}) ->
+ true;
+is_key(#'ECPrivateKey'{}) ->
+ true;
+is_key(_) ->
+ false.
+
+
+cert_template() ->
+ #'OTPTBSCertificate'{
+ version = v3,
+ serialNumber = erlang:unique_integer([positive, monotonic]),
+ issuerUniqueID = asn1_NOVALUE,
+ subjectUniqueID = asn1_NOVALUE
+ }.
+
+subject(Contact, Name) ->
+ Opts = [{email, Contact ++ "@example.org"},
+ {name, Name},
+ {city, "Stockholm"},
+ {country, "SE"},
+ {org, "erlang"},
+ {org_unit, "automated testing"}],
+ subject(Opts).
+
+subject(SubjectOpts) when is_list(SubjectOpts) ->
+ Encode = fun(Opt) ->
+ {Type,Value} = subject_enc(Opt),
+ [#'AttributeTypeAndValue'{type=Type, value=Value}]
+ end,
+ {rdnSequence, [Encode(Opt) || Opt <- SubjectOpts]}.
+
+subject_enc({name, Name}) ->
+ {?'id-at-commonName', {printableString, Name}};
+subject_enc({email, Email}) ->
+ {?'id-emailAddress', Email};
+subject_enc({city, City}) ->
+ {?'id-at-localityName', {printableString, City}};
+subject_enc({org, Org}) ->
+ {?'id-at-organizationName', {printableString, Org}};
+subject_enc({org_unit, OrgUnit}) ->
+ {?'id-at-organizationalUnitName', {printableString, OrgUnit}};
+subject_enc({country, Country}) ->
+ {?'id-at-countryName', Country}.
+
+validity(Opts) ->
+ DefFrom0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())-1),
+ DefTo0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())+7),
+ {DefFrom, DefTo} = proplists:get_value(validity, Opts, {DefFrom0, DefTo0}),
+ Format =
+ fun({Y,M,D}) ->
+ lists:flatten(
+ io_lib:format("~4..0w~2..0w~2..0w000000Z",[Y,M,D]))
+ end,
+ #'Validity'{notBefore={generalTime, Format(DefFrom)},
+ notAfter ={generalTime, Format(DefTo)}}.
+
+sign_algorithm(#'RSAPrivateKey'{}, Opts) ->
+ Type = rsa_digest_oid(proplists:get_value(digest, Opts, sha1)),
+ #'SignatureAlgorithm'{algorithm = Type,
+ parameters = 'NULL'};
+sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) ->
+ #'SignatureAlgorithm'{algorithm = ?'id-dsa-with-sha1',
+ parameters = {params,#'Dss-Parms'{p=P, q=Q, g=G}}};
+sign_algorithm(#'ECPrivateKey'{parameters = Parms}, Opts) ->
+ Type = ecdsa_digest_oid(proplists:get_value(digest, Opts, sha1)),
+ #'SignatureAlgorithm'{algorithm = Type,
+ parameters = Parms}.
+rsa_digest_oid(sha1) ->
+ ?'sha1WithRSAEncryption';
+rsa_digest_oid(sha512) ->
+ ?'sha512WithRSAEncryption';
+rsa_digest_oid(sha384) ->
+ ?'sha384WithRSAEncryption';
+rsa_digest_oid(sha256) ->
+ ?'sha256WithRSAEncryption';
+rsa_digest_oid(md5) ->
+ ?'md5WithRSAEncryption'.
+
+ecdsa_digest_oid(sha1) ->
+ ?'ecdsa-with-SHA1';
+ecdsa_digest_oid(sha512) ->
+ ?'ecdsa-with-SHA512';
+ecdsa_digest_oid(sha384) ->
+ ?'ecdsa-with-SHA384';
+ecdsa_digest_oid(sha256) ->
+ ?'ecdsa-with-SHA256'.
+
+config(Role, Root, Key, Opts) ->
+ cert_chain(Role, Root, Key, Opts).
+
+cert_chain(Role, Root, RootKey, Opts) ->
+ cert_chain(Role, Root, RootKey, Opts, 0, []).
+
+cert_chain(Role, IssuerCert, IssuerKey, [PeerOpts], _, Acc) ->
+ Key = gen_key(proplists:get_value(key, PeerOpts, default_key_gen())),
+ Cert = cert(Role, public_key:pkix_decode_cert(IssuerCert, otp),
+ IssuerKey, Key, "admin", " Peer cert", PeerOpts, peer),
+ [{Cert, encode_key(Key)}, {IssuerCert, encode_key(IssuerKey)} | Acc];
+cert_chain(Role, IssuerCert, IssuerKey, [CAOpts | Rest], N, Acc) ->
+ Key = gen_key(proplists:get_value(key, CAOpts, default_key_gen())),
+ Cert = cert(Role, public_key:pkix_decode_cert(IssuerCert, otp), IssuerKey, Key, "webadmin",
+ " Intermidiate CA " ++ integer_to_list(N), CAOpts, ca),
+ cert_chain(Role, Cert, Key, Rest, N+1, [{IssuerCert, encode_key(IssuerKey)} | Acc]).
+
+cert(Role, #'OTPCertificate'{tbsCertificate = #'OTPTBSCertificate'{subject = Issuer}},
+ PrivKey, Key, Contact, Name, Opts, Type) ->
+ TBS = cert_template(),
+ OTPTBS = TBS#'OTPTBSCertificate'{
+ signature = sign_algorithm(PrivKey, Opts),
+ issuer = Issuer,
+ validity = validity(Opts),
+ subject = subject(Contact, atom_to_list(Role) ++ Name),
+ subjectPublicKeyInfo = public_key(Key),
+ extensions = extensions(Role, Type, Opts)
+ },
+ public_key:pkix_sign(OTPTBS, PrivKey).
+
+ca_config(Root, CAsKeys) ->
+ [Root | [CA || {CA, _} <- CAsKeys]].
+
+default_key_gen() ->
+ case crypto:ec_curves() of
+ [] ->
+ {rsa, 2048, 17};
+ [Curve |_] ->
+ Oid = pubkey_cert_records:namedCurves(Curve),
+ {namedCurve, Oid}
+ end.
+
+public_key(#'RSAPrivateKey'{modulus=N, publicExponent=E}) ->
+ Public = #'RSAPublicKey'{modulus=N, publicExponent=E},
+ Algo = #'PublicKeyAlgorithm'{algorithm= ?rsaEncryption, parameters='NULL'},
+ #'OTPSubjectPublicKeyInfo'{algorithm = Algo,
+ subjectPublicKey = Public};
+public_key(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) ->
+ Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa',
+ parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}},
+ #'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y};
+public_key(#'ECPrivateKey'{version = _Version,
+ privateKey = _PrivKey,
+ parameters = Params,
+ publicKey = PubKey}) ->
+ Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-ecPublicKey', parameters=Params},
+ #'OTPSubjectPublicKeyInfo'{algorithm = Algo,
+ subjectPublicKey = #'ECPoint'{point = PubKey}}.
+
+extensions(Role, Type, Opts) ->
+ Exts = proplists:get_value(extensions, Opts, []),
+ add_default_extensions(Role, Type, Exts).
+
+add_default_extensions(_, ca, Exts) ->
+ Default = [#'Extension'{extnID = ?'id-ce-keyUsage',
+ extnValue = [keyCertSign, cRLSign],
+ critical = false},
+ #'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue = #'BasicConstraints'{cA = true},
+ critical = true}],
+ add_default_extensions(Default, Exts);
+
+add_default_extensions(server, peer, Exts) ->
+ Hostname = net_adm:localhost(),
+ Default = [#'Extension'{extnID = ?'id-ce-keyUsage',
+ extnValue = [digitalSignature, keyAgreement],
+ critical = false},
+ #'Extension'{extnID = ?'id-ce-subjectAltName',
+ extnValue = [{dNSName, Hostname}],
+ critical = false}
+ ],
+ add_default_extensions(Default, Exts);
+
+add_default_extensions(client, peer, Exts) ->
+ Exts.
+
+add_default_extensions(Defaults0, Exts) ->
+ Defaults = lists:filtermap(fun(#'Extension'{extnID = ID} = Ext) ->
+ case lists:keymember(ID, 2, Exts) of
+ true ->
+ false;
+ false ->
+ {true, Ext}
+ end
+ end, Defaults0),
+ Exts ++ Defaults.
+
+encode_key(#'RSAPrivateKey'{} = Key) ->
+ {'RSAPrivateKey', public_key:der_encode('RSAPrivateKey', Key)};
+encode_key(#'ECPrivateKey'{} = Key) ->
+ {'ECPrivateKey', public_key:der_encode('ECPrivateKey', Key)};
+encode_key(#'DSAPrivateKey'{} = Key) ->
+ {'DSAPrivateKey', public_key:der_encode('DSAPrivateKey', Key)}.
+
diff --git a/lib/public_key/src/pubkey_crl.erl b/lib/public_key/src/pubkey_crl.erl
index 33bef91827..50abd704de 100644
--- a/lib/public_key/src/pubkey_crl.erl
+++ b/lib/public_key/src/pubkey_crl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -58,7 +58,8 @@ validate(OtpCert, OtherDPCRLs, DP, {DerCRL, CRL}, {DerDeltaCRL, DeltaCRL},
init_revokation_state() ->
#revoke_state{reasons_mask = sets:new(),
interim_reasons_mask = sets:new(),
- cert_status = unrevoked}.
+ cert_status = unrevoked,
+ details = []}.
fresh_crl(_, {undefined, undefined}, _) ->
%% Typically happens when there is no delta CRL that covers a CRL
@@ -152,9 +153,10 @@ verify_crl(OtpCert, DP, CRL, DerCRL, DeltaCRL, DerDeltaCRL, OtherDPCRLs,
RevokedState,
CRL, DerCRL, DeltaCRL, DerDeltaCRL,
IssuerFun, TrustedOtpCert, Path, OtherDPCRLs, IDP);
- _ ->
- {invalid, State0#revoke_state{valid_ext = ValidExt}}
- end;
+ _ ->
+ Details = RevokedState#revoke_state.details,
+ {invalid, RevokedState#revoke_state{valid_ext = ValidExt, details = [{{bad_crl, no_issuer_cert_chain}, CRL} | Details]}}
+ end;
{error, issuer_not_found} ->
case Fun(DP, CRL, issuer_not_found, AdditionalArgs) of
{ok, TrustedOtpCert, Path} ->
@@ -163,13 +165,16 @@ verify_crl(OtpCert, DP, CRL, DerCRL, DeltaCRL, DerDeltaCRL, OtherDPCRLs,
DerDeltaCRL, IssuerFun,
TrustedOtpCert, Path, OtherDPCRLs, IDP);
_ ->
- {invalid, {skip, State0}}
- end
+ Details = State0#revoke_state.details,
+ {invalid, {skip, State0#revoke_state{details = [{{bad_crl, no_issuer_cert_chain}, CRL} | Details] }}}
+ end
catch
- throw:{bad_crl, invalid_issuer} ->
- {invalid, {skip, State0}};
- throw:_ ->
- {invalid, State0#revoke_state{valid_ext = ValidExt}}
+ throw:{bad_crl, invalid_issuer} = Reason ->
+ Details = RevokedState#revoke_state.details,
+ {invalid, {skip, RevokedState#revoke_state{details = [{Reason, CRL} | Details]}}};
+ throw:Reason ->
+ Details = RevokedState#revoke_state.details,
+ {invalid, RevokedState#revoke_state{details = [{Reason, CRL} | Details]}}
end.
verify_mask_and_signatures(Revoked, DeltaRevoked, RevokedState, CRL, DerCRL, DeltaCRL, DerDeltaCRL,
@@ -183,10 +188,12 @@ verify_mask_and_signatures(Revoked, DeltaRevoked, RevokedState, CRL, DerCRL, Del
TrustedOtpCert, Path, IssuerFun, OtherDPCRLs, IDP),
{valid, Revoked, DeltaRevoked, RevokedState#revoke_state{reasons_mask = ReasonsMask}, IDP}
catch
- throw:_ ->
- {invalid, RevokedState};
+ throw:Reason ->
+ Details = RevokedState#revoke_state.details,
+ {invalid, RevokedState#revoke_state{details = [{Reason, CRL} | Details]}};
error:{badmatch, _} ->
- {invalid, RevokedState}
+ Details = RevokedState#revoke_state.details,
+ {invalid, RevokedState#revoke_state{details = [{{bad_crl, invalid_signature}, CRL} | Details]}}
end.
@@ -356,7 +363,7 @@ verify_scope(#'OTPCertificate'{tbsCertificate = TBSCert}, #'DistributionPoint'{c
verify_scope(DPName, IDPName, Names, TBSCert, IDP).
verify_scope(asn1_NOVALUE, _, asn1_NOVALUE, _, _) ->
- throw({bad_crl, scope_error1});
+ throw({bad_crl, scope_error});
verify_scope(asn1_NOVALUE, IDPName, DPIssuerNames, TBSCert, IDP) ->
verify_dp_name(IDPName, DPIssuerNames),
verify_dp_bools(TBSCert, IDP);
diff --git a/lib/public_key/src/pubkey_moduli.hrl b/lib/public_key/src/pubkey_moduli.hrl
index e4beecc12a..768db624c7 100644
--- a/lib/public_key/src/pubkey_moduli.hrl
+++ b/lib/public_key/src/pubkey_moduli.hrl
@@ -1,395 +1,489 @@
-define(dh_default_groups,
[{1023,
[{2,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840821904219},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016037066299},
{2,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840822843699},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016038392563},
{2,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840824293227},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016038561043},
{2,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840824411619},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016040084083},
{2,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840826770579},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016040928019},
{2,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840829698867},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016041403147},
{2,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840831699579},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016044289459},
{2,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840831788499},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016046539987},
{2,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840835116819},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016048107763},
{2,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840838791147},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016048195459},
{2,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840839741403},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016048489219},
{2,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840843908763},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016051183339},
{2,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840844149459},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016051761379},
{2,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840846037779},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016059530419},
{2,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840846316347},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016061519299},
{2,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840848087763},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016061652187},
{2,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840851778483},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016062557059},
+ {2,
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016062981427},
+ {2,
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016066800187},
+ {5,
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016042534663},
{5,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840818511543},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016047828127},
{5,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840819546447},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016048304863},
{5,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840820698807},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016049426047},
{5,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840821875983},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016052250343},
{5,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840822182367},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016055892463},
{5,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840823493823},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016056347623},
{5,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840828115623},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016056938023},
{5,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840833652783},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016058313343},
{5,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840844852263},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016065124567},
{5,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840849785943},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016066293247},
{5,
- 145775197456487668749161655795234893413202527697104473695831577761647854852108768430387864189919819365658842431613137268371680467610991509847733954019734973873643148023271112285230508466838215139872267855676600969961870846186166681894080056503367717025795010132090088184706677576861830882312093982840849803727}]},
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016066518343},
+ {5,
+ 137423569441246262992289626302405506810075372518201635033473127540045433614984773406065519964899878780586235832348933590594300290793347611716697640359482924853366011641117770719027755146909495326369377183195861495553717174988136205384838926110458474346294939275424613035724229598089601829380531182016068472303}]},
{1535,
[{2,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891121581459},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789627621067},
+ {2,
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789628761283},
+ {2,
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789634361539},
+ {2,
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789638537803},
+ {2,
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789641659627},
+ {2,
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789647419339},
+ {2,
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789659085619},
{2,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891123347643},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789662256763},
{2,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891123353283},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789664867003},
{2,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891124232763},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789666330667},
{2,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891131462067},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789666841459},
{2,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891135933003},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789668814427},
{2,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891136255299},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789672118003},
{2,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891137177907},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789672898027},
{2,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891139347603},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789674915179},
{2,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891152305467},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789676842763},
{2,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891159084867},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789681188923},
{2,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891161343219},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789682812883},
{2,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891172563627},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789691688803},
{2,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891174672243},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789694851307},
{2,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891180467739},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789696895987},
{2,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891185564427},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789696948499},
{2,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891189869307},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789699330739},
{5,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891119456223},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789631448743},
{5,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891124590423},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789634212463},
{5,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891130908327},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789640500127},
{5,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891131873727},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789645700087},
{5,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891135211407},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789647710183},
{5,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891143426247},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789652039063},
{5,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891143747007},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789654186463},
{5,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891146699103},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789661060927},
{5,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891150054447},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789671831647},
{5,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891155995647},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789672578407},
{5,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891157019487},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789678179287},
{5,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891159178863},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789681924847},
{5,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891161250063},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789686897743},
{5,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891170145447},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789691863487},
{5,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891171171087},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789697728943},
{5,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891172350063},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789698140423},
{5,
- 1907170736023124811736411458785042542925115668082539810200109305735683587893811083066646767750558659131374424885053147631157680241645866111036024727506041045267916677127337026486727329498794109266986160904622741269220273376068857149157352410555723198695322554668593076155279812272319710239217381596287633268687131658367273821116604691564975255858007378139664922713363377579390448226123206847441877045380881530736814422784905045609836858066127174749699891176092263}]},
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789699225607},
+ {5,
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789699353287},
+ {5,
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789699437767},
+ {5,
+ 2117681492913321569697017096248004964074655225855064803226626530973545674132063479305336653601343613581681296068799225967217443469822913599882869070603558288530230411228882956187328693299502078948089815664109460010482204163236896700745132726891852191217183972837285242539058483051590799983736242396087464474074677177065221920708495653383923226837547541111948031363494948381073214833218893715532814018571166368347836868668692007351599237524270407572667789700740103}]},
{2047,
[{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127673160083},
- {2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127674746147},
- {2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127677513587},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074755345499},
{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127677855803},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074756461859},
{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127681703483},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074760692747},
{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127691773067},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074773822283},
{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127693199747},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074776983899},
{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127694475899},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074790653483},
{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127702886939},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074794713299},
{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127707613619},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074815828619},
{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127713247667},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074834327939},
{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127727962403},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074842331123},
{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127729070603},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074845064267},
{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127741606979},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074846183603},
{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127745340899},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074847350027},
{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127764392459},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074850417539},
{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127764820307},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074852923427},
{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127771318403},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074865137387},
{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127781167379},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074871791507},
{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127782355883},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074872448099},
{2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127782887579},
- {2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127787746619},
- {2,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127789102259},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074872498379},
{5,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127666983407},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074753531327},
{5,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127675200023},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074755896047},
{5,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127687609343},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074769190823},
{5,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127691690063},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074773140287},
{5,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127708300823},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074801938847},
{5,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127712140847},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074808850487},
{5,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127715948087},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074810458703},
{5,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127717449983},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074819068463},
{5,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127717581887},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074828950247},
{5,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127725119327},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074831380223},
{5,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127735619543},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074843050847},
{5,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127776932207},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074853193463},
{5,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127788684623},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074854277423},
{5,
- 31232761562882516094884070611630050950237146275890833609093891047897843797997552232718257871173954549538774751038496595396925563385404720255716837933677220581287383288516914691172469244029925326629700819138694871356510866851914242889526314963319760427147424913618697965734069376105953045113129440174661252504850768513753786509136822851125652952326518541742866669959696723616260017966174003560432807987735744247115916855658422620715728754034819398357826714599804921184478793666674492366199879602022266103884178166633701002913239714329019644011011091883511432521179210877235289776043130356321939953141370575127790955767}]},
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074856272687},
+ {5,
+ 30234100291786660119150592253986164718868634461318049072554515332884967674928782249469681512369934810827458855581922926809556244370595605788701190647548919395621435148266404705314169286338735491330335839065308771794695863455361843400123918598469633373229888515556903041476081665517841329650690706907312078385023867825976012891153434200817912196296808624612663609473822637069014486910713969827270391274088701875401022668082592335250640966918882542262485103727016143768199802712794462461532704087012779665855118715263701391361266921229205676528586338993875313766674367990445223648968867957230166128407903969074856341807}]},
{3071,
[{2,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199506260163},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289461870763},
{2,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199530244827},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289490971387},
{2,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199578944619},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289493767387},
{2,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199589988939},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289502528779},
{2,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199594013379},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289515762739},
{2,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199601609043},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289520111827},
{2,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199604230203},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289526490499},
{2,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199606755099},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289531918987},
{2,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199618079787},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289535321539},
{2,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199653718659},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289537766083},
{2,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199657776483},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289585885627},
{2,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199707657579},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289591046227},
{2,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199722711699},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289593005899},
{2,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199743456099},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289609404787},
{2,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199785339603},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289612863787},
{2,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199797260499},
- {5,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199507581927},
- {5,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199510208343},
- {5,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199537327623},
- {5,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199551703167},
- {5,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199617722127},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289648408147},
+ {2,
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289660538083},
+ {2,
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289673483683},
+ {2,
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289677227419},
+ {2,
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289698314083},
+ {2,
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289741797499},
+ {2,
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289743929803},
{5,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199621084383},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289453025863},
{5,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199634824407},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289457558263},
{5,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199642326807},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289460688727},
{5,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199665149823},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289474675927},
{5,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199708695087},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289594040647},
{5,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199765825887},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289609025887},
{5,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199767685887},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289609530703},
{5,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199773947727},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289654971847},
{5,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199780743543},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289728752743},
{5,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199786221207},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289741648567},
{5,
- 5436771231278176260464207572014249237436628003751950430443256176419437109283409279325055179822137303309588375578210454771206339795059466564724705882357808020147943371370952376862400031959913112146741735409727429098983569717815170493079969998376532776669142518838712137720503257349411673630616846814922326748760377074686267404617800626017790893617723327526800481821613452766006640701474488365374399399907853664959711238779541522615905232982411502798277910194792404145749492189947629774082615011566526902465295439792626194825661087612449173617161800099003448528272624654517679417559537997833575275437573873218238645979906696208545848771753496507149936213366692226040978858284500769836334638725943292501159483097128028975365907974867494222456802766986272374880246378778326493320216426233834650917807239104899121676291950634433590565261175675893968032464664959347175273331523630462401583678513811133107339834284448366199798706967}]},
+ 5341214654634261952873757181561533451707821361473790513564315292835421225907290979705658514768610744229080270038566630873421837799494130654470818355524260427309266809137559455752156841542079285699912382198438256477191140483659741554623458276984132571490005422487391200312212866133415680909716507907845827994683552282075519283183306400978216170683966125586514167935144707307129515552296413428393454073134896115280919323970931969859738752463628375871247541392539129483603011834938988123237171126084442161006950491163910976429369302209546222425310901643650474858404742396613584660709357575219554168390865409561609082174871377547770444430973616557924010418332760953296455735166542214510320276939683699294586632574638203802976903133684878674504505778352407591179548498641812857848247717199756967280188814464938382873930435957699864919392905570032937866615892011156011915598355499435483769756567649481438043557349653592289746986983}]},
{4095,
[{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328641094123},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908261488803},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328654189387},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908267757267},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328663242883},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908296392939},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328715041723},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908296649787},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328717604779},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908347767723},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328805204587},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908378270547},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328806565843},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908383266867},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328807451707},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908404042059},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328836115507},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908438601507},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328845968059},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908495213859},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328887178459},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908512647459},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328908234163},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908521746723},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328948166083},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908568726363},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328954136203},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908573748939},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328963052323},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908598118683},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024329023777723},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908611654827},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024329047093003},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908619313779},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024329058480379},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908654940987},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024329090057419},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908658321027},
{2,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024329132001859},
- {5,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328685618887},
- {5,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328733393407},
- {5,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328804704703},
- {5,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328808160607},
- {5,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328817663383},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908711194899},
+ {2,
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908729714499},
{5,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328826409727},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908237597607},
{5,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328842353143},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908282017743},
{5,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328915670167},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908357526423},
{5,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328928173423},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908366458383},
{5,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328936548223},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908428742727},
{5,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328945813063},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908488602303},
{5,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328955100607},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908617606623},
{5,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328983302407},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908644249167},
{5,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024328995176167},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908664024183},
{5,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024329021303887},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908676438567},
{5,
- 818034524162384276004384029858643530286875094391273833506734966261806257117433972760379103507630310628953496150318170372254219924175532996281953750642804369831900894594960807970232131410638888573275563720690293481410915588408505771183615664441221559618326229227448328879290185035795866796496147000467456347856187771645103733376761936369144682074588463621004219054111244232031965820058057143484947957179035662640791007685559024477920075136419228662974090561346329074935312181886940693299380892129818458511403741106419480550004799657220331973244248753744516935739033770420884365608406478656143540532371463443324228730693491647103274058971797182813283112583029849186056551355376851686616057869624968077484471229044125401535456699914745876082047459812392122562460031611344154642406382436701361983114768023990405077450124649862159757605118611426368650203370143674925598905779061402007525955196464201496773278952462368223659263492419274489020447849336502432222101793313731259141617677580646998184158969477474527427664187763741360356528830301163614618231141541403007931347398186427059736520580903587497382362610721261644208653717495736748724114113311672504064943864203789205551568648546606356374830209356446449765364678719909024329064403567}]},
+ 822475527894530229285616572113840248471252289865654730245673569989009517195150670386319918731764341482939973599599030444586627098726805325532602670776492782830517765627499389443537251148551632924278584658894256392558800578282770783952781444172123021909239761249266774011128112210797775865561188225245937456884457382356013600801136212313898917668235824265001348217562305609115401999529744566651634335823205650035802368807460021617740974817291658859354863897470423588038163002057414285871641295222833687523714538475514552855242579151518676338365048493158502050812316214163484509139051517638342109175849018785568945149403656833584359154601084850728291664155244903363511084332084337961858034913924653425899617872300974717518876133738228463402736897605365573279650828581423928774933880146466418294504197525108110672457161289146815032997391965470390378909910135534473119298720916725046763262261767220808960157446815529871730997078479389353851235418277521225090118250855917746026804319123727978865815215602336860198597431012309304151978584224046103750860062629864591763945976315990671793648388266723695721279940197843205282458713913995036945430630152450677414407385229033726976302905725696701985169880658807635234608315361840320908697685503}]},
{6143,
[{2,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255204878912539},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066212697067},
+ {2,
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066239737819},
+ {2,
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066261564859},
+ {2,
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066266476003},
{2,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205024824427},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066306104707},
{2,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205108938283},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066308614363},
{2,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205168452667},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066415298659},
{2,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205178336083},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066433581259},
{2,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205194695203},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066436192219},
{2,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205234987027},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066526639459},
{2,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205249389907},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066543056683},
{2,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205299503899},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066571940083},
{2,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205303762219},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066616922347},
{2,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205318419043},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066630852307},
{2,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205369723267},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066646474627},
{2,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205388065627},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066845660899},
{2,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205483192027},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104067076479267},
+ {2,
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104067184606083},
+ {2,
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104067259968123},
+ {2,
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104067267961323},
{5,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255204867528103},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066189360223},
{5,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255204958533343},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066217457143},
{5,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205142917087},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066324667807},
{5,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205164709807},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066489492103},
{5,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205223494543},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066643247863},
{5,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205238451607},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066905718943},
{5,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205398650527},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104066970573183},
{5,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205534891927},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104067042481887},
{5,
- 33437583241773200736998306224385528803766612787425393970240448895665693432965804079937003812356294308539203151272072972277375104789647202046031197278230667153631409232762771720006125219920706956123725594446372009116332714804701277193618508630316668034287884909832516041233220775901611206642660372233947390606274902141826658826141733970432621047550484555565916575805826057191334266474445170275718783081560666447409216535181360674632456526571101451968821169633558969474691730611539132286052022835952896201555123627380799302110683026529909820807288537680562845821392314996440379370705723540964585839337801927778062852215686895319024767481042895138442976855163068747380166531199300232551267526017036164413600564815784019785977970949693984340717238729942561030179919817420833573731051545887599723662578148436252999801801184946912344055039296858955344284666098693644023712197329293309829111260795234865981993976990661827891668714260305572784933890804266304027991177237933956448650403587826112875783795940606993503972135788451776288043780405914188427059396997568948159052168252857826777287128664074216861215783789478700515409553239441062015685435438583826256963919799489374587339208720501219592669600392307850331252795823771544828155101319705650241344450112892458324477254048023146580514471110326358407290566960742849415447980366665653434043627949138890739742819993505594819520369919793246819138042045825632762369551350013672323292476735446079801969860131404566127284762569608997426987715169971180098109830736446816299192620247945607493820377482306775990092969824710142555863464957556013639252952281232650874597306442373552573476420189325342908686488322042941568296395918651660523487617863085692837653979094810691084612642444899086069505869007138363971482049103042831515780578797971864682660432869186605371682266108433970938695484953644215301255205578782263}]},
+ 30210369155779651888589832154992934074138507220822617750684652871127582962409899985645946445695043253195686248244998571402305199678770384280564307485035486218800068429843963439425551779021865465473175487387006425679517736862515996424867831461548685177440883895142510892080386024242790580351718476912346064665887342021801124592374644199240055614707801951400286738571835106941459565263538011604632591754698655670731747906958754306695890917250845082935314433013066321817795811216868330076422883334026288452966305998174700518168814979477732850177021088448137305837683404856702535774772361477172629825124721712806311678193131143271354379844514551970600366748790881625770009341628054007754553253798271412759265676226769394213651014204828629926952929904315923670432908575989917617637701451215022415020602741724294119817098286839062394376589141071497906909592069997336204239169602926838746847024777759842015748321319275357899423502183072151966760234482986263033779816032715802142058060420345923767082809675434739360245514122590144988299733345731573144371526046690587022732405227784184600940160738238518293781021765582962691631713434222022562950296250509633938674749281309291074381760671163336862668582157228513024763628253337784730104842959368278069041285218519766922739574404159050610285845118633942864745158438604557438873320358729699870593735296129291292133537433344339822168319576836729204869998368045864710009464349668393627057504172016907834801787571594303040666608785976162184230007930556331766254151014073812956419139773303370139752142739047952426344593274617190212675329544654619143794215577626176639637678757668518842586496846866347512471156638951909845841212416559374312458890749201523393740959899515314744619218832833815902335851353279396321673115498490049357132026679171719767095122045794337383943188601986364730890641872503895354104067188249103}]},
{8191,
[{2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645408345391859},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645408413484803},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645408426294467},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645408437420243},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645408466188083},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645408519326819},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645408597129947},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645408659473619},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645408841130339},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645409006846067},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645409068135923},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645409232339147},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645409253569523},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645409273017467},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645409293367523},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645409431407147},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645409674894923},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645409701436403},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645409902628547},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645410027309819},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645410051540267},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645410055117899},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645410163529523},
+ {2,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645410264370203},
+ {2,
938991641448887958659860711024139841840373070892857314837350127283993531354468803860225599873491818506054401963417489724433963777795696041544477412963807403300832656512849715212168703537706302853428971073305304224008208665300028518281475780493382070018498379488833882168221853720545474425047940975435356027594634176129712250061883354535324982741923143373986406603949677080360223989497048086447454366625852264609369284140522273595340921542019308988041920995057608746115976973659704188342646944998285431473302075966106608530908140377765357842459486869512398523240695806503711124427370056638597159539032058092571318621818616699716647464298881944582194013388150591419588422793657857267906072494480713650129757905856314362270238621284311461743652666256381611674809565144562467655186251867429369336740018623120262859220669942243740953355278814789244133782043857008487446798345197999966787658254507117076710455244182794239065255535191498857182705725985655379455993825553257619502588673174759329362518373537685585117537004065137523099625519490356398330532110250061129576411957409731201790054967354938147031111368166150009421041430118523249245874882140875551501824754839814848195806919150975076831338899823813371473496616326897054534509843640848822974414341233324307292275820287661792887177523563243279340678632061899626115667671047274195425889742755327012266774742591229119994211561599405909368902449776535330722644597809098307346948888547387746758109319767106289995123864514603259977184876246412673772519845777697496361969177346826245108557971745523905955370437517039028495325595180934057507336816903052766590118820327869839202378278312909402987412274414739124292902164277499512007446916921747463997761815820546816791093343347969046462095463611789365326128045878985464594892022442144072282717352526544915821855299863549245012366815543939396712522935345161074836470227392836664033041735035699615758782980717425699108612161567924880267630103820215946940542401779795959759774248414245436455737309858403883625882609790799283421857564831362243562647683958370353023343221966296655134926556805244483888769178095889844741765908328185625663202823312608064683035802724504683124396450612201783060593269112984065572954508643688374585823409316161924407053191442613988480926581084892323451281350937867676271858142177713557970909833234285545964647506859724327822527317869059455132036566677244407755994867168874825546516623190701762311472512591018622127119388239627852234680483324150442403},
{2,
938991641448887958659860711024139841840373070892857314837350127283993531354468803860225599873491818506054401963417489724433963777795696041544477412963807403300832656512849715212168703537706302853428971073305304224008208665300028518281475780493382070018498379488833882168221853720545474425047940975435356027594634176129712250061883354535324982741923143373986406603949677080360223989497048086447454366625852264609369284140522273595340921542019308988041920995057608746115976973659704188342646944998285431473302075966106608530908140377765357842459486869512398523240695806503711124427370056638597159539032058092571318621818616699716647464298881944582194013388150591419588422793657857267906072494480713650129757905856314362270238621284311461743652666256381611674809565144562467655186251867429369336740018623120262859220669942243740953355278814789244133782043857008487446798345197999966787658254507117076710455244182794239065255535191498857182705725985655379455993825553257619502588673174759329362518373537685585117537004065137523099625519490356398330532110250061129576411957409731201790054967354938147031111368166150009421041430118523249245874882140875551501824754839814848195806919150975076831338899823813371473496616326897054534509843640848822974414341233324307292275820287661792887177523563243279340678632061899626115667671047274195425889742755327012266774742591229119994211561599405909368902449776535330722644597809098307346948888547387746758109319767106289995123864514603259977184876246412673772519845777697496361969177346826245108557971745523905955370437517039028495325595180934057507336816903052766590118820327869839202378278312909402987412274414739124292902164277499512007446916921747463997761815820546816791093343347969046462095463611789365326128045878985464594892022442144072282717352526544915821855299863549245012366815543939396712522935345161074836470227392836664033041735035699615758782980717425699108612161567924880267630103820215946940542401779795959759774248414245436455737309858403883625882609790799283421857564831362243562647683958370353023343221966296655134926556805244483888769178095889844741765908328185625663202823312608064683035802724504683124396450612201783060593269112984065572954508643688374585823409316161924407053191442613988480926581084892323451281350937867676271858142177713557970909833234285545964647506859724327822527317869059455132036566677244407755994867168874825546516623190701762311472512591018622127119388239627852234680483324227808419},
{5,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645408307521047},
+ {5,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645408345535967},
+ {5,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645408700026887},
+ {5,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645408840291887},
+ {5,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645408918699743},
+ {5,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645408929943263},
+ {5,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645409339998527},
+ {5,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645409471627367},
+ {5,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645410128181183},
+ {5,
+ 881045461522943321086778073300940478556218355297969911976909161486894133662493726399243167458009140047097403832005558428608022057031977203602474613009545091720237343240266129021712322298408144531017770778248716957128799297677903712279084392023819163463966227515269649827380536523405101157732109499388260769586116300288304982677621782718749987230168262305655004727816729815800533511307474309647349575475321354016095742812539133151602748038504759763440423033004809780519532557484323246180020130950200646945418165013898390018998574383185461948128020544881733962825915669056546421700831605194278745248581382984298520377716141327298492058956203175900776169162131066555283318461828456520694888875026876615176999234594065729624240200260702661257238500249077130700729314922467706084046564196655345340394880604121971434682608173172839952354536660137326680056370043971462309932399249681084807535691908014774608948539576573091871838175518964071111240660427603031489552613754601246540211425394120613055590993731825013169587667380928210308207859749014992608494977324762902471764267795852486660601596648189999837075454896316687482540387017067211974603191279230953515521397067907513757763367315888101693042775385804066821260256218210264761730017655260313514255350592287156466544141273327424165523630928036465070504326759160965905472140206420733620859718350162744176336519051572708874620380237875083788097274492094030771087416734847686560630664937136197575123272360898853159596587429099207143246305845544244799356813180338388773189837194780822656452007718856513775556746086854637309945375913748887588098858159436611056484858182222940508156607890079350636796413492320863755066068420264176273501354701451580424930853731245191488999731887724342512885115174853872824237863191925018415676193712562003253140276927443202251707682541813796844055771821904734125528936278921457950566975054216078541402261766645717620168828928676184585062086661069943438428009453737016388913674954661321656899115360462958864817727116179756063838264308057333138934007726602464976584961039426342748390610135215206761067742896313902468085136725214515755654144065167649442144794757021442299332980346481411405659939120613041046295543064197536090990615733218132400037369470292737483454477799095857545361137577823887518193742510875707781884043932899326953370891554930847941892191784528780453236476476667586752290919919524010419077090794678643057876460306613406236250774207318712135446125272108408598954645410156742023},
+ {5,
938991641448887958659860711024139841840373070892857314837350127283993531354468803860225599873491818506054401963417489724433963777795696041544477412963807403300832656512849715212168703537706302853428971073305304224008208665300028518281475780493382070018498379488833882168221853720545474425047940975435356027594634176129712250061883354535324982741923143373986406603949677080360223989497048086447454366625852264609369284140522273595340921542019308988041920995057608746115976973659704188342646944998285431473302075966106608530908140377765357842459486869512398523240695806503711124427370056638597159539032058092571318621818616699716647464298881944582194013388150591419588422793657857267906072494480713650129757905856314362270238621284311461743652666256381611674809565144562467655186251867429369336740018623120262859220669942243740953355278814789244133782043857008487446798345197999966787658254507117076710455244182794239065255535191498857182705725985655379455993825553257619502588673174759329362518373537685585117537004065137523099625519490356398330532110250061129576411957409731201790054967354938147031111368166150009421041430118523249245874882140875551501824754839814848195806919150975076831338899823813371473496616326897054534509843640848822974414341233324307292275820287661792887177523563243279340678632061899626115667671047274195425889742755327012266774742591229119994211561599405909368902449776535330722644597809098307346948888547387746758109319767106289995123864514603259977184876246412673772519845777697496361969177346826245108557971745523905955370437517039028495325595180934057507336816903052766590118820327869839202378278312909402987412274414739124292902164277499512007446916921747463997761815820546816791093343347969046462095463611789365326128045878985464594892022442144072282717352526544915821855299863549245012366815543939396712522935345161074836470227392836664033041735035699615758782980717425699108612161567924880267630103820215946940542401779795959759774248414245436455737309858403883625882609790799283421857564831362243562647683958370353023343221966296655134926556805244483888769178095889844741765908328185625663202823312608064683035802724504683124396450612201783060593269112984065572954508643688374585823409316161924407053191442613988480926581084892323451281350937867676271858142177713557970909833234285545964647506859724327822527317869059455132036566677244407755994867168874825546516623190701762311472512591018622127119388239627852234680483324244759967}]}]
).
diff --git a/lib/public_key/src/pubkey_pbe.erl b/lib/public_key/src/pubkey_pbe.erl
index 0243bcaa82..806f7c5b0f 100644
--- a/lib/public_key/src/pubkey_pbe.erl
+++ b/lib/public_key/src/pubkey_pbe.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -222,7 +222,8 @@ pbe_pad(Data, {#'PBEParameter'{}, _}) ->
pbe_pad(Data, #'PBES2-params'{}) ->
pbe_pad(Data);
pbe_pad(Data, _) ->
- Data.
+pbe_pad(Data).%% Data.
+
pbe_pad(Data) ->
N = 8 - (erlang:byte_size(Data) rem 8),
diff --git a/lib/public_key/src/pubkey_pem.erl b/lib/public_key/src/pubkey_pem.erl
index 06a4455b3f..b92790554f 100644
--- a/lib/public_key/src/pubkey_pem.erl
+++ b/lib/public_key/src/pubkey_pem.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -209,6 +209,8 @@ pem_start('DSAPrivateKey') ->
<<"-----BEGIN DSA PRIVATE KEY-----">>;
pem_start('DHParameter') ->
<<"-----BEGIN DH PARAMETERS-----">>;
+pem_start('PrivateKeyInfo') ->
+ <<"-----BEGIN PRIVATE KEY-----">>;
pem_start('EncryptedPrivateKeyInfo') ->
<<"-----BEGIN ENCRYPTED PRIVATE KEY-----">>;
pem_start('CertificationRequest') ->
diff --git a/lib/public_key/src/pubkey_ssh.erl b/lib/public_key/src/pubkey_ssh.erl
index 9bda76d670..02c061efc9 100644
--- a/lib/public_key/src/pubkey_ssh.erl
+++ b/lib/public_key/src/pubkey_ssh.erl
@@ -29,7 +29,17 @@
]).
-define(UINT32(X), X:32/unsigned-big-integer).
--define(STRING(X), ?UINT32((size(X))), (X)/binary).
+-define(STRING(X), ?UINT32((byte_size(X))), (X)/binary).
+
+-define(DEC_BIN(X,Len), ?UINT32(Len), X:Len/binary ).
+-define(DEC_MPINT(I,Len), ?DEC_INT(I,Len) ).
+-define(DEC_INT(I,Len), ?UINT32(Len), I:Len/big-signed-integer-unit:8 ).
+
+-define(Empint(X), (mpint(X))/binary ).
+-define(Estring(X), (string(X))/binary ).
+
+-define(b64enc(X), base64:encode(iolist_to_binary(X)) ).
+-define(b64mime_dec(X), base64:mime_decode(iolist_to_binary(X)) ).
%% Max encoded line length is 72, but conformance examples use 68
%% Comment from rfc 4716: "The following are some examples of public
@@ -47,12 +57,12 @@
%% Description: Decodes a ssh file-binary.
%%--------------------------------------------------------------------
decode(Bin, public_key)->
- case binary:match(Bin, begin_marker()) of
- nomatch ->
- openssh_decode(Bin, openssh_public_key);
- _ ->
- rfc4716_decode(Bin)
- end;
+ PKtype =
+ case binary:match(Bin, begin_marker()) of
+ nomatch -> openssh_public_key;
+ _ -> rfc4716_public_key
+ end,
+ decode(Bin, PKtype);
decode(Bin, rfc4716_public_key) ->
rfc4716_decode(Bin);
decode(Bin, ssh2_pubkey) ->
@@ -79,7 +89,9 @@ dh_gex_group(Min, N, Max, undefined) ->
dh_gex_group(Min, N, Max, Groups) ->
case select_by_keylen(Min-10, N, Max+10, Groups) of
{ok,{Sz,GPs}} ->
- {ok, {Sz,lists:nth(crypto:rand_uniform(1, 1+length(GPs)), GPs)}};
+ Rnd = rand:uniform( length(GPs) ),
+ %% 1 =< Rnd =< length(GPs)
+ {ok, {Sz, lists:nth(Rnd,GPs)}};
Other ->
Other
end.
@@ -153,7 +165,7 @@ rfc4716_decode_line(Line, Lines, Acc) ->
rfc4716_decode_lines(Lines, [{string_decode(Tag), unicode_decode(Value)} | Acc]);
_ ->
{Body, Rest} = join_entry([Line | Lines], []),
- {lists:reverse(Acc), rfc4716_pubkey_decode(base64:mime_decode(Body)), Rest}
+ {lists:reverse(Acc), rfc4716_pubkey_decode(?b64mime_dec(Body)), Rest}
end.
join_entry([<<"---- END SSH2 PUBLIC KEY ----", _/binary>>| Lines], Entry) ->
@@ -162,26 +174,8 @@ join_entry([Line | Lines], Entry) ->
join_entry(Lines, [Line | Entry]).
-rfc4716_pubkey_decode(<<?UINT32(Len), Type:Len/binary,
- ?UINT32(SizeE), E:SizeE/binary,
- ?UINT32(SizeN), N:SizeN/binary>>) when Type == <<"ssh-rsa">> ->
- #'RSAPublicKey'{modulus = erlint(SizeN, N),
- publicExponent = erlint(SizeE, E)};
-
-rfc4716_pubkey_decode(<<?UINT32(Len), Type:Len/binary,
- ?UINT32(SizeP), P:SizeP/binary,
- ?UINT32(SizeQ), Q:SizeQ/binary,
- ?UINT32(SizeG), G:SizeG/binary,
- ?UINT32(SizeY), Y:SizeY/binary>>) when Type == <<"ssh-dss">> ->
- {erlint(SizeY, Y),
- #'Dss-Parms'{p = erlint(SizeP, P),
- q = erlint(SizeQ, Q),
- g = erlint(SizeG, G)}};
-rfc4716_pubkey_decode(<<?UINT32(Len), ECDSA_SHA2_etc:Len/binary,
- ?UINT32(SizeId), Id:SizeId/binary,
- ?UINT32(SizeQ), Q:SizeQ/binary>>) ->
- <<"ecdsa-sha2-", Id/binary>> = ECDSA_SHA2_etc,
- {#'ECPoint'{point = Q}, {namedCurve,public_key:ssh_curvename2oid(Id)}}.
+rfc4716_pubkey_decode(BinKey) -> ssh2_pubkey_decode(BinKey).
+
openssh_decode(Bin, FileType) ->
Lines = binary:split(Bin, <<"\n">>, [global]),
@@ -265,18 +259,14 @@ decode_comment(Comment) ->
openssh_pubkey_decode(Type, Base64Enc) ->
try
- ssh2_pubkey_decode(Type, base64:mime_decode(Base64Enc))
+ <<?DEC_BIN(Type,_TL), Bin/binary>> = ?b64mime_dec(Base64Enc),
+ ssh2_pubkey_decode(Type, Bin)
catch
_:_ ->
- {Type, base64:mime_decode(Base64Enc)}
+ {Type, ?b64mime_dec(Base64Enc)}
end.
-erlint(MPIntSize, MPIntValue) ->
- Bits= MPIntSize * 8,
- <<Integer:Bits/integer>> = MPIntValue,
- Integer.
-
ssh1_rsa_pubkey_decode(MBin, EBin) ->
#'RSAPublicKey'{modulus = integer_decode(MBin),
publicExponent = integer_decode(EBin)}.
@@ -304,12 +294,12 @@ do_encode(Type, Key, Attributes) ->
rfc4716_encode(Key, [],[]) ->
iolist_to_binary([begin_marker(),"\n",
- split_lines(base64:encode(ssh2_pubkey_encode(Key))),
+ split_lines(?b64enc(ssh2_pubkey_encode(Key))),
"\n", end_marker(), "\n"]);
rfc4716_encode(Key, [], [_|_] = Acc) ->
iolist_to_binary([begin_marker(), "\n",
lists:reverse(Acc),
- split_lines(base64:encode(ssh2_pubkey_encode(Key))),
+ split_lines(?b64enc(ssh2_pubkey_encode(Key))),
"\n", end_marker(), "\n"]);
rfc4716_encode(Key, [ Header | Headers], Acc) ->
LinesStr = rfc4716_encode_header(Header),
@@ -338,7 +328,7 @@ rfc4716_encode_value(Value) ->
openssh_encode(openssh_public_key, Key, Attributes) ->
Comment = proplists:get_value(comment, Attributes, ""),
- Enc = base64:encode(ssh2_pubkey_encode(Key)),
+ Enc = ?b64enc(ssh2_pubkey_encode(Key)),
iolist_to_binary([key_type(Key), " ", Enc, " ", Comment, "\n"]);
openssh_encode(auth_keys, Key, Attributes) ->
@@ -363,10 +353,10 @@ openssh_encode(known_hosts, Key, Attributes) ->
end.
openssh_ssh2_auth_keys_encode(undefined, Key, Comment) ->
- iolist_to_binary([key_type(Key)," ", base64:encode(ssh2_pubkey_encode(Key)), line_end(Comment)]);
+ iolist_to_binary([key_type(Key)," ", ?b64enc(ssh2_pubkey_encode(Key)), line_end(Comment)]);
openssh_ssh2_auth_keys_encode(Options, Key, Comment) ->
iolist_to_binary([comma_list_encode(Options, []), " ",
- key_type(Key)," ", base64:encode(ssh2_pubkey_encode(Key)), line_end(Comment)]).
+ key_type(Key)," ", ?b64enc(ssh2_pubkey_encode(Key)), line_end(Comment)]).
openssh_ssh1_auth_keys_encode(undefined, Bits,
#'RSAPublicKey'{modulus = N, publicExponent = E},
@@ -381,7 +371,7 @@ openssh_ssh1_auth_keys_encode(Options, Bits,
openssh_ssh2_know_hosts_encode(Hostnames, Key, Comment) ->
iolist_to_binary([comma_list_encode(Hostnames, []), " ",
- key_type(Key)," ", base64:encode(ssh2_pubkey_encode(Key)), line_end(Comment)]).
+ key_type(Key)," ", ?b64enc(ssh2_pubkey_encode(Key)), line_end(Comment)]).
openssh_ssh1_known_hosts_encode(Hostnames, Bits,
#'RSAPublicKey'{modulus = N, publicExponent = E},
@@ -409,71 +399,37 @@ comma_list_encode([Option | Rest], Acc) ->
ssh2_pubkey_encode(#'RSAPublicKey'{modulus = N, publicExponent = E}) ->
- ssh2_pubkey_encode({#'RSAPublicKey'{modulus = N, publicExponent = E}, 'ssh-rsa'});
-
-ssh2_pubkey_encode({Key, 'rsa-sha2-256'}) -> ssh2_pubkey_encode({Key, 'ssh-rsa'});
-ssh2_pubkey_encode({Key, 'rsa-sha2-512'}) -> ssh2_pubkey_encode({Key, 'ssh-rsa'});
-ssh2_pubkey_encode({#'RSAPublicKey'{modulus = N, publicExponent = E}, SignAlg}) ->
- SignAlgName = list_to_binary(atom_to_list(SignAlg)),
- StrLen = size(SignAlgName),
- EBin = mpint(E),
- NBin = mpint(N),
- <<?UINT32(StrLen), SignAlgName:StrLen/binary,
- EBin/binary,
- NBin/binary>>;
-ssh2_pubkey_encode({{_,#'Dss-Parms'{}}=Key, _}) ->
- ssh2_pubkey_encode(Key);
+ <<?STRING(<<"ssh-rsa">>), ?Empint(E), ?Empint(N)>>;
ssh2_pubkey_encode({Y, #'Dss-Parms'{p = P, q = Q, g = G}}) ->
- TypeStr = <<"ssh-dss">>,
- StrLen = size(TypeStr),
- PBin = mpint(P),
- QBin = mpint(Q),
- GBin = mpint(G),
- YBin = mpint(Y),
- <<?UINT32(StrLen), TypeStr:StrLen/binary,
- PBin/binary,
- QBin/binary,
- GBin/binary,
- YBin/binary>>;
-ssh2_pubkey_encode({{#'ECPoint'{},_}=Key, _}) ->
- ssh2_pubkey_encode(Key);
+ <<?STRING(<<"ssh-dss">>), ?Empint(P), ?Empint(Q), ?Empint(G), ?Empint(Y)>>;
ssh2_pubkey_encode(Key={#'ECPoint'{point = Q}, {namedCurve,OID}}) ->
- TypeStr = key_type(Key),
- StrLen = size(TypeStr),
- IdB = public_key:oid2ssh_curvename(OID),
- <<?UINT32(StrLen), TypeStr:StrLen/binary,
- (string(IdB))/binary,
- (string(Q))/binary>>.
+ Curve = public_key:oid2ssh_curvename(OID),
+ <<?STRING(key_type(Key)), ?Estring(Curve), ?Estring(Q)>>.
-ssh2_pubkey_decode(Bin = <<?UINT32(Len), Type:Len/binary, _/binary>>) ->
+ssh2_pubkey_decode(<<?DEC_BIN(Type,_TL), Bin/binary>>) ->
ssh2_pubkey_decode(Type, Bin).
-ssh2_pubkey_decode(<<"rsa-sha2-256">>, Bin) -> ssh2_pubkey_decode(<<"ssh-rsa">>, Bin);
-ssh2_pubkey_decode(<<"rsa-sha2-512">>, Bin) -> ssh2_pubkey_decode(<<"ssh-rsa">>, Bin);
+%% ssh2_pubkey_decode(<<"rsa-sha2-256">>, Bin) -> ssh2_pubkey_decode(<<"ssh-rsa">>, Bin);
+%% ssh2_pubkey_decode(<<"rsa-sha2-512">>, Bin) -> ssh2_pubkey_decode(<<"ssh-rsa">>, Bin);
ssh2_pubkey_decode(<<"ssh-rsa">>,
- <<?UINT32(Len), _:Len/binary,
- ?UINT32(SizeE), E:SizeE/binary,
- ?UINT32(SizeN), N:SizeN/binary>>) ->
- #'RSAPublicKey'{modulus = erlint(SizeN, N),
- publicExponent = erlint(SizeE, E)};
+ <<?DEC_INT(E, _EL),
+ ?DEC_INT(N, _NL)>>) ->
+ #'RSAPublicKey'{modulus = N,
+ publicExponent = E};
ssh2_pubkey_decode(<<"ssh-dss">>,
- <<?UINT32(Len), _:Len/binary,
- ?UINT32(SizeP), P:SizeP/binary,
- ?UINT32(SizeQ), Q:SizeQ/binary,
- ?UINT32(SizeG), G:SizeG/binary,
- ?UINT32(SizeY), Y:SizeY/binary>>) ->
- {erlint(SizeY, Y),
- #'Dss-Parms'{p = erlint(SizeP, P),
- q = erlint(SizeQ, Q),
- g = erlint(SizeG, G)}};
+ <<?DEC_INT(P, _PL),
+ ?DEC_INT(Q, _QL),
+ ?DEC_INT(G, _GL),
+ ?DEC_INT(Y, _YL)>>) ->
+ {Y, #'Dss-Parms'{p = P,
+ q = Q,
+ g = G}};
ssh2_pubkey_decode(<<"ecdsa-sha2-",Id/binary>>,
- <<?UINT32(Len), ECDSA_SHA2_etc:Len/binary,
- ?UINT32(SizeId), Id:SizeId/binary,
- ?UINT32(SizeQ), Q:SizeQ/binary>>) ->
- <<"ecdsa-sha2-", Id/binary>> = ECDSA_SHA2_etc,
+ <<?DEC_BIN(Id, _IL),
+ ?DEC_BIN(Q, _QL)>>) ->
{#'ECPoint'{point = Q}, {namedCurve,public_key:ssh_curvename2oid(Id)}}.
@@ -573,17 +529,16 @@ mpint(X) -> mpint_pos(X).
mpint_neg(X) ->
Bin = int_to_bin_neg(X, []),
- Sz = byte_size(Bin),
- <<?UINT32(Sz), Bin/binary>>.
+ <<?STRING(Bin)>>.
mpint_pos(X) ->
Bin = int_to_bin_pos(X, []),
<<MSB,_/binary>> = Bin,
- Sz = byte_size(Bin),
if MSB band 16#80 == 16#80 ->
- <<?UINT32((Sz+1)), 0, Bin/binary>>;
+ B = << 0, Bin/binary>>,
+ <<?STRING(B)>>;
true ->
- <<?UINT32(Sz), Bin/binary>>
+ <<?STRING(Bin)>>
end.
int_to_bin_pos(0,Ds=[_|_]) ->
@@ -600,7 +555,8 @@ int_to_bin_neg(X,Ds) ->
string(X) when is_binary(X) ->
<< ?STRING(X) >>;
string(X) ->
- << ?STRING(list_to_binary(X)) >>.
+ B = list_to_binary(X),
+ << ?STRING(B) >>.
is_ssh_curvename(Id) -> try public_key:ssh_curvename2oid(Id) of _ -> true
catch _:_ -> false
diff --git a/lib/public_key/src/public_key.app.src b/lib/public_key/src/public_key.app.src
index dbd732c384..5833141e87 100644
--- a/lib/public_key/src/public_key.app.src
+++ b/lib/public_key/src/public_key.app.src
@@ -14,7 +14,7 @@
{applications, [asn1, crypto, kernel, stdlib]},
{registered, []},
{env, []},
- {runtime_dependencies, ["stdlib-2.0","kernel-3.0","erts-6.0","crypto-3.8",
+ {runtime_dependencies, ["stdlib-3.5","kernel-3.0","erts-6.0","crypto-3.8",
"asn1-3.0"]}
]
}.
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 6651e9510e..3f609ce6c6 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@
decrypt_public/2, decrypt_public/3,
dh_gex_group/4,
dh_gex_group_sizes/0,
- sign/3, verify/4,
+ sign/3, sign/4, verify/4, verify/5,
generate_key/1,
compute_key/2, compute_key/3,
pkix_sign/2, pkix_verify/2,
@@ -49,6 +49,7 @@
pkix_normalize_name/1,
pkix_path_validation/3,
pkix_verify_hostname/2, pkix_verify_hostname/3,
+ pkix_verify_hostname_match_fun/1,
ssh_decode/2, ssh_encode/2,
ssh_hostkey_fingerprint/1, ssh_hostkey_fingerprint/2,
ssh_curvename2oid/1, oid2ssh_curvename/1,
@@ -58,11 +59,14 @@
pkix_match_dist_point/2,
pkix_crl_verify/2,
pkix_crl_issuer/1,
- short_name_hash/1
+ short_name_hash/1,
+ pkix_test_data/1,
+ pkix_test_root_cert/2
]).
-export_type([public_key/0, private_key/0, pem_entry/0,
- pki_asn1_type/0, asn1_type/0, ssh_file/0, der_encoded/0]).
+ pki_asn1_type/0, asn1_type/0, ssh_file/0, der_encoded/0,
+ key_params/0, digest_type/0]).
-type public_key() :: rsa_public_key() | dsa_public_key() | ec_public_key().
-type private_key() :: rsa_private_key() | dsa_private_key() | ec_private_key().
@@ -71,8 +75,12 @@
-type rsa_private_key() :: #'RSAPrivateKey'{}.
-type dsa_private_key() :: #'DSAPrivateKey'{}.
-type dsa_public_key() :: {integer(), #'Dss-Parms'{}}.
--type ec_public_key() :: {#'ECPoint'{},{namedCurve, Oid::tuple()} | #'ECParameters'{}}.
+-type ecpk_parameters() :: {ecParameters, #'ECParameters'{}} | {namedCurve, Oid::tuple()}.
+-type ecpk_parameters_api() :: ecpk_parameters() | #'ECParameters'{} | {namedCurve, Name::crypto:ec_named_curve()}.
+-type ec_public_key() :: {#'ECPoint'{}, ecpk_parameters_api()}.
-type ec_private_key() :: #'ECPrivateKey'{}.
+-type key_params() :: #'DHParameter'{} | {namedCurve, oid()} | #'ECParameters'{} |
+ {rsa, Size::integer(), PubExp::integer()}.
-type der_encoded() :: binary().
-type pki_asn1_type() :: 'Certificate' | 'RSAPrivateKey' | 'RSAPublicKey'
| 'DSAPrivateKey' | 'DSAPublicKey' | 'DHParameter'
@@ -80,24 +88,40 @@
'CertificationRequest' | 'CertificateList' |
'ECPrivateKey' | 'EcpkParameters'.
-type pem_entry() :: {pki_asn1_type(),
- binary(), %% DER or Encrypted DER
- not_encrypted | {Cipher :: string(), Salt :: binary()} |
- {Cipher :: string(), #'PBES2-params'{}} |
- {Cipher :: string(), {#'PBEParameter'{}, atom()}} %% hash type
+ der_or_encrypted_der(),
+ not_encrypted | cipher_info()
}.
+-type der_or_encrypted_der() :: binary().
+-type cipher_info() :: {cipher(),
+ cipher_info_params()} .
+-type cipher() :: string() . % "RC2-CBC" | "DES-CBC" | "DES-EDE3-CBC",
+-type cipher_info_params() :: salt()
+ | {#'PBEParameter'{}, digest_type()}
+ | #'PBES2-params'{} .
+
+-type salt() :: binary(). % crypto:strong_rand_bytes(8)
+%% -type cipher_info() :: {Cipher :: string(), Salt :: binary()} |
+%% {Cipher :: string(), #'PBES2-params'{}} |
+%% {Cipher :: string(), {#'PBEParameter'{}, atom()}} %% hash type
+%% .
+
-type asn1_type() :: atom(). %% see "OTP-PUB-KEY.hrl
-type ssh_file() :: openssh_public_key | rfc4716_public_key | known_hosts |
auth_keys.
--type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding'
- | 'rsa_no_padding'.
--type public_crypt_options() :: [{rsa_pad, rsa_padding()}].
--type rsa_digest_type() :: 'md5' | 'sha'| 'sha224' | 'sha256' | 'sha384' | 'sha512'.
--type dss_digest_type() :: 'none' | 'sha'. %% None is for backwards compatibility
--type ecdsa_digest_type() :: 'sha'| 'sha224' | 'sha256' | 'sha384' | 'sha512'.
--type digest_type() :: rsa_digest_type() | dss_digest_type() | ecdsa_digest_type().
+-type digest_type() :: none % None is for backwards compatibility
+ | crypto:rsa_digest_type()
+ | crypto:dss_digest_type()
+ | crypto:ecdsa_digest_type().
-type crl_reason() :: unspecified | keyCompromise | cACompromise | affiliationChanged | superseded
| cessationOfOperation | certificateHold | privilegeWithdrawn | aACompromise.
-type oid() :: tuple().
+-type chain_type() :: server_chain | client_chain.
+
+-type issuer_id() :: {SerialNr::integer(), issuer_name()} .
+
+-type issuer_name() :: {rdnSequence,[#'AttributeTypeAndValue'{}]} .
+
+
-define(UINT32(X), X:32/unsigned-big-integer).
-define(DER_NULL, <<5, 0>>).
@@ -123,11 +147,11 @@ pem_encode(PemEntries) when is_list(PemEntries) ->
iolist_to_binary(pubkey_pem:encode(PemEntries)).
%%--------------------------------------------------------------------
--spec pem_entry_decode(pem_entry(), string()) -> term().
-%
%% Description: Decodes a pem entry. pem_decode/1 returns a list of
%% pem entries.
%%--------------------------------------------------------------------
+-spec pem_entry_decode(PemEntry) -> term() when PemEntry :: pem_entry() .
+
pem_entry_decode({'SubjectPublicKeyInfo', Der, _}) ->
{_, {'AlgorithmIdentifier', AlgId, Params}, Key0}
= der_decode('SubjectPublicKeyInfo', Der),
@@ -145,6 +169,9 @@ pem_entry_decode({'SubjectPublicKeyInfo', Der, _}) ->
pem_entry_decode({Asn1Type, Der, not_encrypted}) when is_atom(Asn1Type),
is_binary(Der) ->
der_decode(Asn1Type, Der).
+
+-spec pem_entry_decode(PemEntry, Password) -> term() when PemEntry :: pem_entry(),
+ Password :: string() .
pem_entry_decode({Asn1Type, Der, not_encrypted}, _) when is_atom(Asn1Type),
is_binary(Der) ->
der_decode(Asn1Type, Der);
@@ -170,11 +197,12 @@ pem_entry_decode({Asn1Type, CryptDer, {Cipher, Salt}} = PemEntry,
%%--------------------------------------------------------------------
--spec pem_entry_encode(pki_asn1_type(), term()) -> pem_entry().
--spec pem_entry_encode(pki_asn1_type(), term(), term()) -> pem_entry().
%%
%% Description: Creates a pem entry that can be feed to pem_encode/1.
%%--------------------------------------------------------------------
+-spec pem_entry_encode(Asn1Type, Entity) -> pem_entry() when Asn1Type :: pki_asn1_type(),
+ Entity :: term() .
+
pem_entry_encode('SubjectPublicKeyInfo', Entity=#'RSAPublicKey'{}) ->
Der = der_encode('RSAPublicKey', Entity),
Spki = {'SubjectPublicKeyInfo',
@@ -197,6 +225,13 @@ pem_entry_encode('SubjectPublicKeyInfo',
pem_entry_encode(Asn1Type, Entity) when is_atom(Asn1Type) ->
Der = der_encode(Asn1Type, Entity),
{Asn1Type, Der, not_encrypted}.
+
+-spec pem_entry_encode(Asn1Type, Entity, InfoPwd) ->
+ pem_entry() when Asn1Type :: pki_asn1_type(),
+ Entity :: term(),
+ InfoPwd :: {CipherInfo,Password},
+ CipherInfo :: cipher_info(),
+ Password :: string() .
pem_entry_encode(Asn1Type, Entity, {{Cipher, #'PBES2-params'{}} = CipherInfo,
Password}) when is_atom(Asn1Type) andalso
is_list(Password) andalso
@@ -218,7 +253,9 @@ pem_entry_encode(Asn1Type, Entity, {{Cipher, Salt} = CipherInfo,
do_pem_entry_encode(Asn1Type, Entity, CipherInfo, Password).
%%--------------------------------------------------------------------
--spec der_decode(asn1_type(), Der::binary()) -> term().
+-spec der_decode(Asn1Type, Der) -> Entity when Asn1Type :: asn1_type(),
+ Der :: binary(),
+ Entity :: term().
%%
%% Description: Decodes a public key asn1 der encoded entity.
%%--------------------------------------------------------------------
@@ -227,7 +264,7 @@ der_decode(Asn1Type, Der) when (Asn1Type == 'PrivateKeyInfo') or
andalso is_binary(Der) ->
try
{ok, Decoded} = 'PKCS-FRAME':decode(Asn1Type, Der),
- Decoded
+ der_priv_key_decode(Decoded)
catch
error:{badmatch, {error, _}} = Error ->
erlang:error(Error)
@@ -242,12 +279,47 @@ der_decode(Asn1Type, Der) when is_atom(Asn1Type), is_binary(Der) ->
erlang:error(Error)
end.
-%%--------------------------------------------------------------------
--spec der_encode(asn1_type(), term()) -> Der::binary().
+der_priv_key_decode({'PrivateKeyInfo', v1,
+ {'PrivateKeyInfo_privateKeyAlgorithm', ?'id-ecPublicKey', {asn1_OPENTYPE, Parameters}}, PrivKey, _}) ->
+ EcPrivKey = der_decode('ECPrivateKey', PrivKey),
+ EcPrivKey#'ECPrivateKey'{parameters = der_decode('EcpkParameters', Parameters)};
+der_priv_key_decode({'PrivateKeyInfo', v1,
+ {'PrivateKeyInfo_privateKeyAlgorithm', ?'rsaEncryption', _}, PrivKey, _}) ->
+ der_decode('RSAPrivateKey', PrivKey);
+der_priv_key_decode({'PrivateKeyInfo', v1,
+ {'PrivateKeyInfo_privateKeyAlgorithm', ?'id-dsa', {asn1_OPENTYPE, Parameters}}, PrivKey, _}) ->
+ {params, #'Dss-Parms'{p=P, q=Q, g=G}} = der_decode('DSAParams', Parameters),
+ X = der_decode('Prime-p', PrivKey),
+ #'DSAPrivateKey'{p=P, q=Q, g=G, x=X};
+der_priv_key_decode(PKCS8Key) ->
+ PKCS8Key.
+
+%%--------------------------------------------------------------------
+-spec der_encode(Asn1Type, Entity) -> Der when Asn1Type :: asn1_type(),
+ Entity :: term(),
+ Der :: binary() .
%%
%% Description: Encodes a public key entity with asn1 DER encoding.
%%--------------------------------------------------------------------
-der_encode(Asn1Type, Entity) when (Asn1Type == 'PrivateKeyInfo') or
+
+der_encode('PrivateKeyInfo', #'DSAPrivateKey'{p=P, q=Q, g=G, x=X}) ->
+ der_encode('PrivateKeyInfo',
+ {'PrivateKeyInfo', v1,
+ {'PrivateKeyInfo_privateKeyAlgorithm', ?'id-dsa',
+ {asn1_OPENTYPE, der_encode('Dss-Parms', #'Dss-Parms'{p=P, q=Q, g=G})}},
+ der_encode('Prime-p', X), asn1_NOVALUE});
+der_encode('PrivateKeyInfo', #'RSAPrivateKey'{} = PrivKey) ->
+ der_encode('PrivateKeyInfo',
+ {'PrivateKeyInfo', v1,
+ {'PrivateKeyInfo_privateKeyAlgorithm', ?'rsaEncryption', {asn1_OPENTYPE, ?DER_NULL}},
+ der_encode('RSAPrivateKey', PrivKey), asn1_NOVALUE});
+der_encode('PrivateKeyInfo', #'ECPrivateKey'{parameters = Parameters} = PrivKey) ->
+ der_encode('PrivateKeyInfo',
+ {'PrivateKeyInfo', v1,
+ {'PrivateKeyInfo_privateKeyAlgorithm', ?'id-ecPublicKey',
+ {asn1_OPENTYPE, der_encode('EcpkParameters', Parameters)}},
+ der_encode('ECPrivateKey', PrivKey#'ECPrivateKey'{parameters = asn1_NOVALUE}), asn1_NOVALUE});
+der_encode(Asn1Type, Entity) when (Asn1Type == 'PrivateKeyInfo') or
(Asn1Type == 'EncryptedPrivateKeyInfo') ->
try
{ok, Encoded} = 'PKCS-FRAME':encode(Asn1Type, Entity),
@@ -267,8 +339,10 @@ der_encode(Asn1Type, Entity) when is_atom(Asn1Type) ->
end.
%%--------------------------------------------------------------------
--spec pkix_decode_cert(Cert::binary(), plain | otp) ->
- #'Certificate'{} | #'OTPCertificate'{}.
+-spec pkix_decode_cert(Cert, Type) ->
+ #'Certificate'{} | #'OTPCertificate'{}
+ when Cert :: der_encoded(),
+ Type :: plain | otp .
%%
%% Description: Decodes an asn1 der encoded pkix certificate. The otp
%% option will use the customized asn1 specification OTP-PKIX.asn1 for
@@ -288,7 +362,11 @@ pkix_decode_cert(DerCert, otp) when is_binary(DerCert) ->
end.
%%--------------------------------------------------------------------
--spec pkix_encode(asn1_type(), term(), otp | plain) -> Der::binary().
+-spec pkix_encode(Asn1Type, Entity, Type) -> Der
+ when Asn1Type :: asn1_type(),
+ Entity :: term(),
+ Type :: otp | plain,
+ Der :: der_encoded() .
%%
%% Description: Der encodes a certificate or part of a certificate.
%% This function must be used for encoding certificates or parts of certificates
@@ -303,16 +381,21 @@ pkix_encode(Asn1Type, Term0, otp) when is_atom(Asn1Type) ->
der_encode(Asn1Type, Term).
%%--------------------------------------------------------------------
--spec decrypt_private(CipherText :: binary(), rsa_private_key()) ->
- PlainText :: binary().
--spec decrypt_private(CipherText :: binary(), rsa_private_key(),
- public_crypt_options()) -> PlainText :: binary().
%%
%% Description: Public key decryption using the private key.
%%--------------------------------------------------------------------
+-spec decrypt_private(CipherText, Key) ->
+ PlainText when CipherText :: binary(),
+ Key :: rsa_private_key(),
+ PlainText :: binary() .
decrypt_private(CipherText, Key) ->
decrypt_private(CipherText, Key, []).
+-spec decrypt_private(CipherText, Key, Options) ->
+ PlainText when CipherText :: binary(),
+ Key :: rsa_private_key(),
+ Options :: crypto:pk_encrypt_decrypt_opts(),
+ PlainText :: binary() .
decrypt_private(CipherText,
#'RSAPrivateKey'{} = Key,
Options)
@@ -322,61 +405,69 @@ decrypt_private(CipherText,
crypto:private_decrypt(rsa, CipherText, format_rsa_private_key(Key), Padding).
%%--------------------------------------------------------------------
--spec decrypt_public(CipherText :: binary(), rsa_public_key() | rsa_private_key()) ->
- PlainText :: binary().
--spec decrypt_public(CipherText :: binary(), rsa_public_key() | rsa_private_key(),
- public_crypt_options()) -> PlainText :: binary().
-%% NOTE: The rsa_private_key() is not part of the documented API it is
-%% here for testing purposes, in a real situation this is not a relevant
-%% thing to do.
-%%
%% Description: Public key decryption using the public key.
%%--------------------------------------------------------------------
+-spec decrypt_public(CipherText, Key) ->
+ PlainText
+ when CipherText :: binary(),
+ Key :: rsa_public_key(),
+ PlainText :: binary() .
decrypt_public(CipherText, Key) ->
decrypt_public(CipherText, Key, []).
+-spec decrypt_public(CipherText, Key, Options) ->
+ PlainText
+ when CipherText :: binary(),
+ Key :: rsa_public_key(),
+ Options :: crypto:pk_encrypt_decrypt_opts(),
+ PlainText :: binary() .
decrypt_public(CipherText, #'RSAPublicKey'{modulus = N, publicExponent = E},
Options) when is_binary(CipherText), is_list(Options) ->
- decrypt_public(CipherText, N,E, Options);
-
-decrypt_public(CipherText,#'RSAPrivateKey'{modulus = N, publicExponent = E},
- Options) when is_binary(CipherText), is_list(Options) ->
- decrypt_public(CipherText, N,E, Options).
+ Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
+ crypto:public_decrypt(rsa, CipherText,[E, N], Padding).
%%--------------------------------------------------------------------
--spec encrypt_public(PlainText :: binary(), rsa_public_key() | rsa_private_key()) ->
- CipherText :: binary().
--spec encrypt_public(PlainText :: binary(), rsa_public_key() | rsa_private_key(),
- public_crypt_options()) -> CipherText :: binary().
-
-%% NOTE: The rsa_private_key() is not part of the documented API it is
-%% here for testing purposes, in a real situation this is not a relevant
-%% thing to do.
-%%
%% Description: Public key encryption using the public key.
%%--------------------------------------------------------------------
+-spec encrypt_public(PlainText, Key) ->
+ CipherText
+ when PlainText :: binary(),
+ Key :: rsa_public_key(),
+ CipherText :: binary() .
encrypt_public(PlainText, Key) ->
encrypt_public(PlainText, Key, []).
-encrypt_public(PlainText, #'RSAPublicKey'{modulus=N,publicExponent=E},
- Options) when is_binary(PlainText), is_list(Options) ->
- encrypt_public(PlainText, N,E, Options);
-encrypt_public(PlainText, #'RSAPrivateKey'{modulus=N,publicExponent=E},
+-spec encrypt_public(PlainText, Key, Options) ->
+ CipherText
+ when PlainText :: binary(),
+ Key :: rsa_public_key(),
+ Options :: crypto:pk_encrypt_decrypt_opts(),
+ CipherText :: binary() .
+encrypt_public(PlainText, #'RSAPublicKey'{modulus=N,publicExponent=E},
Options) when is_binary(PlainText), is_list(Options) ->
- encrypt_public(PlainText, N,E, Options).
+ Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
+ crypto:public_encrypt(rsa, PlainText, [E,N], Padding).
%%--------------------------------------------------------------------
--spec encrypt_private(PlainText :: binary(), rsa_private_key()) ->
- CipherText :: binary().
--spec encrypt_private(PlainText :: binary(), rsa_private_key(),
- public_crypt_options()) -> CipherText :: binary().
%%
%% Description: Public key encryption using the private key.
%%--------------------------------------------------------------------
+-spec encrypt_private(PlainText, Key) ->
+ CipherText
+ when PlainText :: binary(),
+ Key :: rsa_private_key(),
+ CipherText :: binary() .
encrypt_private(PlainText, Key) ->
encrypt_private(PlainText, Key, []).
+
+-spec encrypt_private(PlainText, Key, Options) ->
+ CipherText
+ when PlainText :: binary(),
+ Key :: rsa_private_key(),
+ Options :: crypto:pk_encrypt_decrypt_opts(),
+ CipherText :: binary() .
encrypt_private(PlainText,
#'RSAPrivateKey'{modulus = N, publicExponent = E,
privateExponent = D} = Key,
@@ -388,28 +479,48 @@ encrypt_private(PlainText,
crypto:private_encrypt(rsa, PlainText, format_rsa_private_key(Key), Padding).
%%--------------------------------------------------------------------
+%% Description: List available group sizes among the pre-computed dh groups
+%%--------------------------------------------------------------------
+-spec dh_gex_group_sizes() -> [pos_integer()].
dh_gex_group_sizes() ->
pubkey_ssh:dh_gex_group_sizes().
+%%--------------------------------------------------------------------
+%% Description: Select a precomputed group
+%%--------------------------------------------------------------------
+-spec dh_gex_group(MinSize, SuggestedSize, MaxSize, Groups) ->
+ {ok,{Size,Group}} | {error,term()}
+ when MinSize :: pos_integer(),
+ SuggestedSize :: pos_integer(),
+ MaxSize :: pos_integer(),
+ Groups :: undefined | [{Size,[Group]}],
+ Size :: pos_integer(),
+ Group :: {G,P},
+ G :: pos_integer(),
+ P :: pos_integer() .
dh_gex_group(Min, N, Max, Groups) ->
pubkey_ssh:dh_gex_group(Min, N, Max, Groups).
%%--------------------------------------------------------------------
--spec generate_key(#'DHParameter'{}) ->
- {Public::binary(), Private::binary()};
- ({namedCurve, Name ::oid()}) ->
- #'ECPrivateKey'{};
- (#'ECParameters'{}) ->
- #'ECPrivateKey'{};
- ({rsa, Size::pos_integer(), PubExp::pos_integer()}) ->
- #'RSAPrivateKey'{}.
-
-%% Description: Generates a new keypair
+%% Description: Generate a new key pair
%%--------------------------------------------------------------------
+-spec generate_key(DHparams | ECparams | RSAparams) ->
+ DHkeys | ECkey | RSAkey
+ when DHparams :: #'DHParameter'{},
+ DHkeys :: {PublicDH::binary(), PrivateDH::binary()},
+ ECparams :: ecpk_parameters_api(),
+ ECkey :: #'ECPrivateKey'{},
+ RSAparams :: {rsa, Size, PubExp},
+ Size::pos_integer(),
+ PubExp::pos_integer(),
+ RSAkey :: #'RSAPrivateKey'{} .
+
generate_key(#'DHParameter'{prime = P, base = G}) ->
crypto:generate_key(dh, [P, G]);
generate_key({namedCurve, _} = Params) ->
ec_generate_key(Params);
+generate_key({ecParameters, _} = Params) ->
+ ec_generate_key(Params);
generate_key(#'ECParameters'{} = Params) ->
ec_generate_key(Params);
generate_key({rsa, ModulusSize, PublicExponent}) ->
@@ -417,7 +528,7 @@ generate_key({rsa, ModulusSize, PublicExponent}) ->
{[E, N], [E, N, D, P, Q, D_mod_P_1, D_mod_Q_1, InvQ_mod_P]} ->
Nint = crypto:bytes_to_integer(N),
Eint = crypto:bytes_to_integer(E),
- #'RSAPrivateKey'{version = 0, % Two-factor (I guess since otherPrimeInfos is not given)
+ #'RSAPrivateKey'{version = 'two-prime', % Two-factor (I guess since otherPrimeInfos is not given)
modulus = Nint,
publicExponent = Eint,
privateExponent = crypto:bytes_to_integer(D),
@@ -435,7 +546,7 @@ generate_key({rsa, ModulusSize, PublicExponent}) ->
% 1976.
Nint = crypto:bytes_to_integer(N),
Eint = crypto:bytes_to_integer(E),
- #'RSAPrivateKey'{version = 0, % Two-factor (I guess since otherPrimeInfos is not given)
+ #'RSAPrivateKey'{version = 'two-prime', % Two-factor (I guess since otherPrimeInfos is not given)
modulus = Nint,
publicExponent = Eint,
privateExponent = crypto:bytes_to_integer(D),
@@ -450,24 +561,34 @@ generate_key({rsa, ModulusSize, PublicExponent}) ->
end.
%%--------------------------------------------------------------------
--spec compute_key(#'ECPoint'{} , #'ECPrivateKey'{}) -> binary().
--spec compute_key(OthersKey ::binary(), MyKey::binary(), #'DHParameter'{}) -> binary().
%% Description: Compute shared secret
%%--------------------------------------------------------------------
+-spec compute_key(OthersECDHkey, MyECDHkey) ->
+ SharedSecret
+ when OthersECDHkey :: #'ECPoint'{},
+ MyECDHkey :: #'ECPrivateKey'{},
+ SharedSecret :: binary().
compute_key(#'ECPoint'{point = Point}, #'ECPrivateKey'{privateKey = PrivKey,
parameters = Param}) ->
ECCurve = ec_curve_spec(Param),
crypto:compute_key(ecdh, Point, PrivKey, ECCurve).
+-spec compute_key(OthersDHkey, MyDHkey, DHparms) ->
+ SharedSecret
+ when OthersDHkey :: crypto:dh_public(), % Was: binary(),
+ MyDHkey :: crypto:dh_private(), % Was: binary(),
+ DHparms :: #'DHParameter'{},
+ SharedSecret :: binary().
compute_key(PubKey, PrivKey, #'DHParameter'{prime = P, base = G}) ->
crypto:compute_key(dh, PubKey, PrivKey, [P, G]).
%%--------------------------------------------------------------------
--spec pkix_sign_types(SignatureAlg::oid()) ->
- %% Relevant dsa digest type is subpart of rsa digest type
- { DigestType :: rsa_digest_type(),
- SignatureType :: rsa | dsa | ecdsa
- }.
+-spec pkix_sign_types(AlgorithmId) ->
+ {DigestType, SignatureType}
+ when AlgorithmId :: oid(),
+ %% Relevant dsa digest type is a subset of rsa_digest_type()
+ DigestType :: crypto:rsa_digest_type(),
+ SignatureType :: rsa | dsa | ecdsa .
%% Description:
%%--------------------------------------------------------------------
pkix_sign_types(?sha1WithRSAEncryption) ->
@@ -498,42 +619,70 @@ pkix_sign_types(?'ecdsa-with-SHA512') ->
{sha512, ecdsa}.
%%--------------------------------------------------------------------
--spec sign(binary() | {digest, binary()}, rsa_digest_type() | dss_digest_type() | ecdsa_digest_type(),
- rsa_private_key() |
- dsa_private_key() | ec_private_key()) -> Signature :: binary().
%% Description: Create digital signature.
%%--------------------------------------------------------------------
-sign(DigestOrPlainText, DigestType, Key = #'RSAPrivateKey'{}) ->
- crypto:sign(rsa, DigestType, DigestOrPlainText, format_rsa_private_key(Key));
-
-sign(DigestOrPlainText, sha, #'DSAPrivateKey'{p = P, q = Q, g = G, x = X}) ->
- crypto:sign(dss, sha, DigestOrPlainText, [P, Q, G, X]);
-
-sign(DigestOrPlainText, DigestType, #'ECPrivateKey'{privateKey = PrivKey,
- parameters = Param}) ->
- ECCurve = ec_curve_spec(Param),
- crypto:sign(ecdsa, DigestType, DigestOrPlainText, [PrivKey, ECCurve]);
-
-%% Backwards compatible
-sign(Digest, none, #'DSAPrivateKey'{} = Key) ->
- sign({digest,Digest}, sha, Key).
+-spec sign(Msg, DigestType, Key) ->
+ Signature when Msg :: binary() | {digest,binary()},
+ DigestType :: digest_type(),
+ Key :: private_key(),
+ Signature :: binary() .
+sign(DigestOrPlainText, DigestType, Key) ->
+ sign(DigestOrPlainText, DigestType, Key, []).
+
+-spec sign(Msg, DigestType, Key, Options) ->
+ Signature when Msg :: binary() | {digest,binary()},
+ DigestType :: digest_type(),
+ Key :: private_key(),
+ Options :: crypto:pk_sign_verify_opts(),
+ Signature :: binary() .
+sign(Digest, none, Key = #'DSAPrivateKey'{}, Options) when is_binary(Digest) ->
+ %% Backwards compatible
+ sign({digest, Digest}, sha, Key, Options);
+sign(DigestOrPlainText, DigestType, Key, Options) ->
+ case format_sign_key(Key) of
+ badarg ->
+ erlang:error(badarg, [DigestOrPlainText, DigestType, Key, Options]);
+ {Algorithm, CryptoKey} ->
+ crypto:sign(Algorithm, DigestType, DigestOrPlainText, CryptoKey, Options)
+ end.
%%--------------------------------------------------------------------
--spec verify(binary() | {digest, binary()}, rsa_digest_type() | dss_digest_type() | ecdsa_digest_type(),
- Signature :: binary(), rsa_public_key()
- | dsa_public_key() | ec_public_key()) -> boolean().
%% Description: Verifies a digital signature.
%%--------------------------------------------------------------------
-verify(DigestOrPlainText, DigestType, Signature, Key) when is_binary(Signature) ->
- do_verify(DigestOrPlainText, DigestType, Signature, Key);
-verify(_,_,_,_) ->
+-spec verify(Msg, DigestType, Signature, Key) ->
+ boolean() when Msg :: binary() | {digest, binary()},
+ DigestType :: digest_type(),
+ Signature :: binary(),
+ Key :: public_key() .
+
+verify(DigestOrPlainText, DigestType, Signature, Key) ->
+ verify(DigestOrPlainText, DigestType, Signature, Key, []).
+
+-spec verify(Msg, DigestType, Signature, Key, Options) ->
+ boolean() when Msg :: binary() | {digest, binary()},
+ DigestType :: digest_type(),
+ Signature :: binary(),
+ Key :: public_key(),
+ Options :: crypto:pk_sign_verify_opts().
+
+verify(Digest, none, Signature, Key = {_, #'Dss-Parms'{}}, Options) when is_binary(Digest) ->
+ %% Backwards compatible
+ verify({digest, Digest}, sha, Signature, Key, Options);
+verify(DigestOrPlainText, DigestType, Signature, Key, Options) when is_binary(Signature) ->
+ case format_verify_key(Key) of
+ badarg ->
+ erlang:error(badarg, [DigestOrPlainText, DigestType, Signature, Key, Options]);
+ {Algorithm, CryptoKey} ->
+ crypto:verify(Algorithm, DigestType, DigestOrPlainText, Signature, CryptoKey, Options)
+ end;
+verify(_,_,_,_,_) ->
%% If Signature is a bitstring and not a binary we know already at this
%% point that the signature is invalid.
false.
%%--------------------------------------------------------------------
--spec pkix_dist_point(der_encoded() | #'OTPCertificate'{}) ->
- #'DistributionPoint'{}.
+-spec pkix_dist_point(Cert) -> DistPoint when Cert :: der_encoded() | #'OTPCertificate'{},
+ DistPoint :: #'DistributionPoint'{}.
%% Description: Creates a distribution point for CRLs issued by the same issuer as <c>Cert</c>.
%%--------------------------------------------------------------------
pkix_dist_point(OtpCert) when is_binary(OtpCert) ->
@@ -556,8 +705,8 @@ pkix_dist_point(OtpCert) ->
reasons = asn1_NOVALUE,
distributionPoint = Point}.
%%--------------------------------------------------------------------
--spec pkix_dist_points(der_encoded() | #'OTPCertificate'{}) ->
- [#'DistributionPoint'{}].
+-spec pkix_dist_points(Cert) -> DistPoints when Cert :: der_encoded() | #'OTPCertificate'{},
+ DistPoints :: [ #'DistributionPoint'{} ].
%% Description: Extracts distributionpoints specified in the certificates extensions.
%%--------------------------------------------------------------------
pkix_dist_points(OtpCert) when is_binary(OtpCert) ->
@@ -571,8 +720,10 @@ pkix_dist_points(OtpCert) ->
[], Value).
%%--------------------------------------------------------------------
--spec pkix_match_dist_point(der_encoded() | #'CertificateList'{},
- #'DistributionPoint'{}) -> boolean().
+-spec pkix_match_dist_point(CRL, DistPoint) ->
+ boolean()
+ when CRL :: der_encoded() | #'CertificateList'{},
+ DistPoint :: #'DistributionPoint'{}.
%% Description: Check whether the given distribution point matches
%% the "issuing distribution point" of the CRL.
%%--------------------------------------------------------------------
@@ -603,8 +754,9 @@ pkix_match_dist_point(#'CertificateList'{
end.
%%--------------------------------------------------------------------
--spec pkix_sign(#'OTPTBSCertificate'{},
- rsa_private_key() | dsa_private_key() | ec_private_key()) -> Der::binary().
+-spec pkix_sign(Cert, Key) -> Der when Cert :: #'OTPTBSCertificate'{},
+ Key :: private_key(),
+ Der :: der_encoded() .
%%
%% Description: Sign a pkix x.509 certificate. Returns the corresponding
%% der encoded 'Certificate'{}
@@ -623,8 +775,8 @@ pkix_sign(#'OTPTBSCertificate'{signature =
pkix_encode('OTPCertificate', Cert, otp).
%%--------------------------------------------------------------------
--spec pkix_verify(Cert::binary(), rsa_public_key()|
- dsa_public_key() | ec_public_key()) -> boolean().
+-spec pkix_verify(Cert, Key) -> boolean() when Cert :: der_encoded(),
+ Key :: public_key() .
%%
%% Description: Verify pkix x.509 certificate signature.
%%--------------------------------------------------------------------
@@ -644,7 +796,9 @@ pkix_verify(DerCert, Key = {#'ECPoint'{}, _})
verify(PlainText, DigestType, Signature, Key).
%%--------------------------------------------------------------------
--spec pkix_crl_verify(CRL::binary() | #'CertificateList'{}, Cert::binary() | #'OTPCertificate'{}) -> boolean().
+-spec pkix_crl_verify(CRL, Cert) -> boolean()
+ when CRL :: der_encoded() | #'CertificateList'{},
+ Cert :: der_encoded() | #'OTPCertificate'{} .
%%
%% Description: Verify that Cert is the CRL signer.
%%--------------------------------------------------------------------
@@ -663,9 +817,12 @@ pkix_crl_verify(#'CertificateList'{} = CRL, #'OTPCertificate'{} = Cert) ->
PublicKey, PublicKeyParams).
%%--------------------------------------------------------------------
--spec pkix_is_issuer(Cert :: der_encoded()| #'OTPCertificate'{} | #'CertificateList'{},
- IssuerCert :: der_encoded()|
- #'OTPCertificate'{}) -> boolean().
+-spec pkix_is_issuer(Cert, IssuerCert) ->
+ boolean() when Cert :: der_encoded()
+ | #'OTPCertificate'{}
+ | #'CertificateList'{},
+ IssuerCert :: der_encoded()
+ | #'OTPCertificate'{} .
%%
%% Description: Checks if <IssuerCert> issued <Cert>.
%%--------------------------------------------------------------------
@@ -685,7 +842,7 @@ pkix_is_issuer(#'CertificateList'{tbsCertList = TBSCRL},
pubkey_cert_records:transform(TBSCRL#'TBSCertList'.issuer, decode)).
%%--------------------------------------------------------------------
--spec pkix_is_self_signed(Cert::binary()| #'OTPCertificate'{}) -> boolean().
+-spec pkix_is_self_signed(Cert) -> boolean() when Cert::der_encoded()| #'OTPCertificate'{}.
%%
%% Description: Checks if a Certificate is self signed.
%%--------------------------------------------------------------------
@@ -696,7 +853,7 @@ pkix_is_self_signed(Cert) when is_binary(Cert) ->
pkix_is_self_signed(OtpCert).
%%--------------------------------------------------------------------
--spec pkix_is_fixed_dh_cert(Cert::binary()| #'OTPCertificate'{}) -> boolean().
+-spec pkix_is_fixed_dh_cert(Cert) -> boolean() when Cert::der_encoded()| #'OTPCertificate'{}.
%%
%% Description: Checks if a Certificate is a fixed Diffie-Hellman Cert.
%%--------------------------------------------------------------------
@@ -707,13 +864,12 @@ pkix_is_fixed_dh_cert(Cert) when is_binary(Cert) ->
pkix_is_fixed_dh_cert(OtpCert).
%%--------------------------------------------------------------------
--spec pkix_issuer_id(Cert::binary()| #'OTPCertificate'{},
- IssuedBy :: self | other) ->
- {ok, {SerialNr :: integer(),
- Issuer :: {rdnSequence,
- [#'AttributeTypeAndValue'{}]}}}
- | {error, Reason :: term()}.
-%
+-spec pkix_issuer_id(Cert, IssuedBy) ->
+ {ok, issuer_id()} | {error, Reason}
+ when Cert::der_encoded()| #'OTPCertificate'{},
+ IssuedBy :: self | other,
+ Reason :: term() .
+
%% Description: Returns the issuer id.
%%--------------------------------------------------------------------
pkix_issuer_id(#'OTPCertificate'{} = OtpCert, Signed) when (Signed == self) or
@@ -724,9 +880,9 @@ pkix_issuer_id(Cert, Signed) when is_binary(Cert) ->
pkix_issuer_id(OtpCert, Signed).
%%--------------------------------------------------------------------
--spec pkix_crl_issuer(CRL::binary()| #'CertificateList'{}) ->
- {rdnSequence,
- [#'AttributeTypeAndValue'{}]}.
+-spec pkix_crl_issuer(CRL| #'CertificateList'{}) ->
+ Issuer when CRL :: der_encoded(),
+ Issuer :: issuer_name() .
%
%% Description: Returns the issuer.
%%--------------------------------------------------------------------
@@ -737,10 +893,9 @@ pkix_crl_issuer(#'CertificateList'{} = CRL) ->
CRL#'CertificateList'.tbsCertList#'TBSCertList'.issuer, decode).
%%--------------------------------------------------------------------
--spec pkix_normalize_name({rdnSequence,
- [#'AttributeTypeAndValue'{}]}) ->
- {rdnSequence,
- [#'AttributeTypeAndValue'{}]}.
+-spec pkix_normalize_name(Issuer) -> Normalized
+ when Issuer :: issuer_name(),
+ Normalized :: issuer_name() .
%%
%% Description: Normalizes a issuer name so that it can be easily
%% compared to another issuer name.
@@ -751,7 +906,7 @@ pkix_normalize_name(Issuer) ->
%%--------------------------------------------------------------------
-spec pkix_path_validation(Cert::binary()| #'OTPCertificate'{} | atom(),
CertChain :: [binary()] ,
- Options :: proplists:proplist()) ->
+ Options :: [{atom(),term()}]) ->
{ok, {PublicKeyInfo :: term(),
PolicyTree :: term()}} |
{error, {bad_cert, Reason :: term()}}.
@@ -787,10 +942,19 @@ pkix_path_validation(#'OTPCertificate'{} = TrustedCert, CertChain, Options)
path_validation(CertChain, ValidationState).
%--------------------------------------------------------------------
--spec pkix_crls_validate(#'OTPCertificate'{},
- [{DP::#'DistributionPoint'{}, {DerCRL::binary(), CRL::#'CertificateList'{}}}],
- Options :: proplists:proplist()) -> valid | {bad_cert, revocation_status_undetermined}
- | {bad_cert, {revoked, crl_reason()}}.
+-spec pkix_crls_validate(OTPcertificate, DPandCRLs, Options) ->
+ CRLstatus when OTPcertificate :: #'OTPCertificate'{},
+ DPandCRLs :: [DPandCRL],
+ DPandCRL :: {DP, {DerCRL, CRL}},
+ DP :: #'DistributionPoint'{},
+ DerCRL :: der_encoded(),
+ CRL :: #'CertificateList'{},
+ Options :: [{atom(),term()}],
+ CRLstatus :: valid
+ | {bad_cert, BadCertReason},
+ BadCertReason :: revocation_status_undetermined
+ | {revocation_status_undetermined, Reason::term()}
+ | {revoked, crl_reason()}.
%% Description: Performs a CRL validation according to RFC 5280.
%%--------------------------------------------------------------------
@@ -807,18 +971,31 @@ pkix_crls_validate(OtpCert, DPAndCRLs0, Options) ->
Options, pubkey_crl:init_revokation_state()).
%--------------------------------------------------------------------
--spec pkix_verify_hostname(Cert :: #'OTPCertificate'{} | binary(),
- ReferenceIDs :: [{uri_id | dns_id | oid(), string()}]) -> boolean().
+-type referenceIDs() :: [referenceID()] .
+-type referenceID() :: {uri_id | dns_id | ip | srv_id | oid(), string()}
+ | {ip, inet:ip_address()} .
--spec pkix_verify_hostname(Cert :: #'OTPCertificate'{} | binary(),
- ReferenceIDs :: [{uri_id | dns_id | oid(), string()}],
- Options :: proplists:proplist()) -> boolean().
+-type high_level_alg() :: https .
+-type match_fun() :: fun((ReferenceID::referenceID() | string(),
+ PresentedID::{atom()|oid(),string()}) -> match_fun_result() ) .
+-type match_fun_result() :: boolean() | default .
%% Description: Validates a hostname to RFC 6125
%%--------------------------------------------------------------------
+-spec pkix_verify_hostname(Cert, ReferenceIDs) -> boolean()
+ when Cert :: der_encoded()
+ | #'OTPCertificate'{},
+ ReferenceIDs :: referenceIDs() .
pkix_verify_hostname(Cert, ReferenceIDs) ->
pkix_verify_hostname(Cert, ReferenceIDs, []).
+-spec pkix_verify_hostname(Cert, ReferenceIDs, Options) ->
+ boolean()
+ when Cert :: der_encoded()
+ | #'OTPCertificate'{},
+ ReferenceIDs :: referenceIDs(),
+ Options :: [{atom(),term()}] .
+
pkix_verify_hostname(BinCert, ReferenceIDs, Options) when is_binary(BinCert) ->
pkix_verify_hostname(pkix_decode_cert(BinCert,otp), ReferenceIDs, Options);
@@ -877,10 +1054,25 @@ pkix_verify_hostname(Cert = #'OTPCertificate'{tbsCertificate = TbsCert}, Referen
end
end.
+
+-spec pkix_verify_hostname_match_fun(high_level_alg()) -> match_fun() .
+
+pkix_verify_hostname_match_fun(https) ->
+ fun({dns_id,FQDN=[_|_]}, {dNSName,Name=[_|_]}) -> verify_hostname_match_wildcard(FQDN, Name);
+ (_, _) -> default
+ end.
+
%%--------------------------------------------------------------------
--spec ssh_decode(binary(), public_key | ssh_file()) -> [{public_key(), Attributes::list()}]
- ; (binary(), ssh2_pubkey) -> public_key()
- .
+-spec ssh_decode(SshBin, Type) ->
+ Decoded
+ when SshBin :: binary(),
+ Type :: ssh2_pubkey | OtherType,
+ OtherType :: public_key | ssh_file(),
+ Decoded :: Decoded_ssh2_pubkey
+ | Decoded_OtherType,
+ Decoded_ssh2_pubkey :: public_key(),
+ Decoded_OtherType :: [{public_key(), Attributes}],
+ Attributes :: [{atom(),term()}] .
%%
%% Description: Decodes a ssh file-binary. In the case of know_hosts
%% or auth_keys the binary may include one or more lines of the
@@ -898,10 +1090,15 @@ ssh_decode(SshBin, Type) when is_binary(SshBin),
pubkey_ssh:decode(SshBin, Type).
%%--------------------------------------------------------------------
--spec ssh_encode([{public_key(), Attributes::list()}], ssh_file()) -> binary()
- ; (public_key(), ssh2_pubkey) -> binary()
- ; ({public_key(),atom()}, ssh2_pubkey) -> binary()
- .
+-spec ssh_encode(InData, Type) ->
+ binary()
+ when Type :: ssh2_pubkey | OtherType,
+ OtherType :: public_key | ssh_file(),
+ InData :: InData_ssh2_pubkey | OtherInData,
+ InData_ssh2_pubkey :: public_key(),
+ OtherInData :: [{Key,Attributes}],
+ Key :: public_key(),
+ Attributes :: [{atom(),term()}] .
%%
%% Description: Encodes a list of ssh file entries (public keys and
%% attributes) to a binary. Possible attributes depends on the file
@@ -936,13 +1133,14 @@ oid2ssh_curvename(?'secp521r1') -> <<"nistp521">>.
%%--------------------------------------------------------------------
-spec ssh_hostkey_fingerprint(public_key()) -> string().
--spec ssh_hostkey_fingerprint( digest_type(), public_key()) -> string()
- ; ([digest_type()], public_key()) -> [string()]
- .
ssh_hostkey_fingerprint(Key) ->
sshfp_string(md5, public_key:ssh_encode(Key,ssh2_pubkey) ).
+
+-spec ssh_hostkey_fingerprint( digest_type(), public_key()) -> string()
+ ; ([digest_type()], public_key()) -> [string()]
+ .
ssh_hostkey_fingerprint(HashAlgs, Key) when is_list(HashAlgs) ->
EncKey = public_key:ssh_encode(Key, ssh2_pubkey),
[sshfp_full_string(HashAlg,EncKey) || HashAlg <- HashAlgs];
@@ -980,8 +1178,7 @@ fp_fmt(b64, Bin) ->
[lists:nth(C+1,B64Chars) || <<C:6>> <= <<Bin/binary,0:Padding>> ].
%%--------------------------------------------------------------------
--spec short_name_hash({rdnSequence, [#'AttributeTypeAndValue'{}]}) ->
- string().
+-spec short_name_hash(Name) -> string() when Name :: issuer_name() .
%% Description: Generates OpenSSL-style hash of a name.
%%--------------------------------------------------------------------
@@ -990,25 +1187,68 @@ short_name_hash({rdnSequence, _Attributes} = Name) ->
<<HashValue:32/little, _/binary>> = crypto:hash(sha, HashThis),
string:to_lower(string:right(integer_to_list(HashValue, 16), 8, $0)).
+
%%--------------------------------------------------------------------
-%%% Internal functions
+-spec pkix_test_data(#{chain_type() := pubkey_cert:chain_opts()} |
+ pubkey_cert:chain_opts()) ->
+ pubkey_cert:test_config() |
+ [pubkey_cert:conf_opt()].
+
+%% Description: Generates cert(s) and ssl configuration
%%--------------------------------------------------------------------
-do_verify(DigestOrPlainText, DigestType, Signature,
- #'RSAPublicKey'{modulus = Mod, publicExponent = Exp}) ->
- crypto:verify(rsa, DigestType, DigestOrPlainText, Signature,
- [Exp, Mod]);
-do_verify(DigestOrPlaintext, DigestType, Signature, {#'ECPoint'{point = Point}, Param}) ->
- ECCurve = ec_curve_spec(Param),
- crypto:verify(ecdsa, DigestType, DigestOrPlaintext, Signature, [Point, ECCurve]);
+pkix_test_data(#{client_chain := ClientChain0,
+ server_chain := ServerChain0}) ->
+ Default = #{intermediates => []},
+ ClientChain = maps:merge(Default, ClientChain0),
+ ServerChain = maps:merge(Default, ServerChain0),
+ pubkey_cert:gen_test_certs(#{client_chain => ClientChain,
+ server_chain => ServerChain});
+pkix_test_data(#{} = Chain) ->
+ Default = #{intermediates => []},
+ pubkey_cert:gen_test_certs(maps:merge(Default, Chain)).
-%% Backwards compatibility
-do_verify(Digest, none, Signature, {_, #'Dss-Parms'{}} = Key ) ->
- verify({digest,Digest}, sha, Signature, Key);
+%%--------------------------------------------------------------------
+-spec pkix_test_root_cert(Name, Options) ->
+ RootCert
+ when Name :: string(),
+ Options :: [{atom(),term()}], %[cert_opt()],
+ RootCert :: pubkey_cert:test_root_cert().
+%% Description: Generates a root cert suitable for pkix_test_data/1
+%%--------------------------------------------------------------------
+
+pkix_test_root_cert(Name, Opts) ->
+ pubkey_cert:root_cert(Name, Opts).
-do_verify(DigestOrPlainText, sha = DigestType, Signature, {Key, #'Dss-Parms'{p = P, q = Q, g = G}})
- when is_integer(Key), is_binary(Signature) ->
- crypto:verify(dss, DigestType, DigestOrPlainText, Signature, [P, Q, G, Key]).
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+format_sign_key(Key = #'RSAPrivateKey'{}) ->
+ {rsa, format_rsa_private_key(Key)};
+format_sign_key(#'DSAPrivateKey'{p = P, q = Q, g = G, x = X}) ->
+ {dss, [P, Q, G, X]};
+format_sign_key(#'ECPrivateKey'{privateKey = PrivKey, parameters = Param}) ->
+ {ecdsa, [PrivKey, ec_curve_spec(Param)]};
+format_sign_key(_) ->
+ badarg.
+
+format_verify_key(#'RSAPublicKey'{modulus = Mod, publicExponent = Exp}) ->
+ {rsa, [Exp, Mod]};
+format_verify_key({#'ECPoint'{point = Point}, Param}) ->
+ {ecdsa, [Point, ec_curve_spec(Param)]};
+format_verify_key({Key, #'Dss-Parms'{p = P, q = Q, g = G}}) ->
+ {dss, [P, Q, G, Key]};
+%% Convert private keys to public keys
+format_verify_key(#'RSAPrivateKey'{modulus = Mod, publicExponent = Exp}) ->
+ format_verify_key(#'RSAPublicKey'{modulus = Mod, publicExponent = Exp});
+format_verify_key(#'ECPrivateKey'{parameters = Param, publicKey = {_, Point}}) ->
+ format_verify_key({#'ECPoint'{point = Point}, Param});
+format_verify_key(#'ECPrivateKey'{parameters = Param, publicKey = Point}) ->
+ format_verify_key({#'ECPoint'{point = Point}, Param});
+format_verify_key(#'DSAPrivateKey'{y=Y, p=P, q=Q, g=G}) ->
+ format_verify_key({Y, #'Dss-Parms'{p=P, q=Q, g=G}});
+format_verify_key(_) ->
+ badarg.
do_pem_entry_encode(Asn1Type, Entity, CipherInfo, Password) ->
Der = der_encode(Asn1Type, Entity),
@@ -1019,14 +1259,6 @@ do_pem_entry_decode({Asn1Type,_, _} = PemEntry, Password) ->
Der = pubkey_pem:decipher(PemEntry, Password),
der_decode(Asn1Type, Der).
-encrypt_public(PlainText, N, E, Options)->
- Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
- crypto:public_encrypt(rsa, PlainText, [E,N], Padding).
-
-decrypt_public(CipherText, N,E, Options) ->
- Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
- crypto:public_decrypt(rsa, CipherText,[E, N], Padding).
-
path_validation([], #path_validation_state{working_public_key_algorithm
= Algorithm,
working_public_key =
@@ -1121,8 +1353,13 @@ der_cert(#'OTPCertificate'{} = Cert) ->
der_cert(Der) when is_binary(Der) ->
Der.
-pkix_crls_validate(_, [],_, _, _) ->
- {bad_cert, revocation_status_undetermined};
+pkix_crls_validate(_, [],_, Options, #revoke_state{details = Details}) ->
+ case proplists:get_value(undetermined_details, Options, false) of
+ false ->
+ {bad_cert, revocation_status_undetermined};
+ true ->
+ {bad_cert, {revocation_status_undetermined, {bad_crls, format_details(Details)}}}
+ end;
pkix_crls_validate(OtpCert, [{DP, CRL, DeltaCRL} | Rest], All, Options, RevokedState0) ->
CallBack = proplists:get_value(update_crl, Options, fun(_, CurrCRL) ->
CurrCRL
@@ -1142,9 +1379,14 @@ pkix_crls_validate(OtpCert, [{DP, CRL, DeltaCRL} | Rest], All, Options, Revoked
do_pkix_crls_validate(OtpCert, [{DP, CRL, DeltaCRL} | Rest], All, Options, RevokedState0) ->
OtherDPCRLs = All -- [{DP, CRL, DeltaCRL}],
case pubkey_crl:validate(OtpCert, OtherDPCRLs, DP, CRL, DeltaCRL, Options, RevokedState0) of
- {undetermined, _, _} when Rest == []->
- {bad_cert, revocation_status_undetermined};
- {undetermined, _, RevokedState} when Rest =/= []->
+ {undetermined, unrevoked, #revoke_state{details = Details}} when Rest == []->
+ case proplists:get_value(undetermined_details, Options, false) of
+ false ->
+ {bad_cert, revocation_status_undetermined};
+ true ->
+ {bad_cert, {revocation_status_undetermined, {bad_crls, Details}}}
+ end;
+ {undetermined, unrevoked, RevokedState} when Rest =/= []->
pkix_crls_validate(OtpCert, Rest, All, Options, RevokedState);
{finished, unrevoked} ->
valid;
@@ -1231,22 +1473,54 @@ format_rsa_private_key(#'RSAPrivateKey'{modulus = N, publicExponent = E,
is_integer(D) ->
[E, N, D].
+-spec ec_generate_key(ecpk_parameters_api()) -> #'ECPrivateKey'{}.
ec_generate_key(Params) ->
Curve = ec_curve_spec(Params),
Term = crypto:generate_key(ecdh, Curve),
- ec_key(Term, Params).
-
-ec_curve_spec( #'ECParameters'{fieldID = FieldId, curve = PCurve, base = Base, order = Order, cofactor = CoFactor }) ->
- Field = {pubkey_cert_records:supportedCurvesTypes(FieldId#'FieldID'.fieldType),
- FieldId#'FieldID'.parameters},
+ NormParams = ec_normalize_params(Params),
+ ec_key(Term, NormParams).
+
+-spec ec_normalize_params(ecpk_parameters_api()) -> ecpk_parameters().
+ec_normalize_params({namedCurve, Name}) when is_atom(Name) ->
+ {namedCurve, pubkey_cert_records:namedCurves(Name)};
+ec_normalize_params(#'ECParameters'{} = ECParams) ->
+ {ecParameters, ECParams};
+ec_normalize_params(Other) -> Other.
+
+-spec ec_curve_spec(ecpk_parameters_api()) -> term().
+ec_curve_spec( #'ECParameters'{fieldID = #'FieldID'{fieldType = Type,
+ parameters = Params}, curve = PCurve, base = Base, order = Order, cofactor = CoFactor }) ->
+ Field = format_field(pubkey_cert_records:supportedCurvesTypes(Type), Params),
Curve = {PCurve#'Curve'.a, PCurve#'Curve'.b, none},
{Field, Curve, Base, Order, CoFactor};
+ec_curve_spec({ecParameters, ECParams}) ->
+ ec_curve_spec(ECParams);
ec_curve_spec({namedCurve, OID}) when is_tuple(OID), is_integer(element(1,OID)) ->
ec_curve_spec({namedCurve, pubkey_cert_records:namedCurves(OID)});
ec_curve_spec({namedCurve, Name}) when is_atom(Name) ->
crypto:ec_curve(Name).
-
+format_field(characteristic_two_field = Type, Params0) ->
+ #'Characteristic-two'{
+ m = M,
+ basis = BasisOid,
+ parameters = Params} = der_decode('Characteristic-two', Params0),
+ {Type, M, field_param_decode(BasisOid, Params)};
+format_field(prime_field, Params0) ->
+ Prime = der_decode('Prime-p', Params0),
+ {prime_field, Prime}.
+
+field_param_decode(?'ppBasis', Params) ->
+ #'Pentanomial'{k1 = K1, k2 = K2, k3 = K3} =
+ der_decode('Pentanomial', Params),
+ {ppbasis, K1, K2, K3};
+field_param_decode(?'tpBasis', Params) ->
+ K = der_decode('Trinomial', Params),
+ {tpbasis, K};
+field_param_decode(?'gnBasis', _) ->
+ onbasis.
+
+-spec ec_key({PubKey::term(), PrivateKey::term()}, Params::ecpk_parameters()) -> #'ECPrivateKey'{}.
ec_key({PubKey, PrivateKey}, Params) ->
#'ECPrivateKey'{version = 1,
privateKey = PrivateKey,
@@ -1330,7 +1604,7 @@ ascii_to_lower(String) ->
verify_hostname_extract_fqdn_default({dns_id,S}) ->
S;
verify_hostname_extract_fqdn_default({uri_id,URI}) ->
- {ok,{https,_,Host,_,_,_}} = http_uri:parse(URI),
+ #{scheme := "https", host := Host} = uri_string:normalize(URI, [return_map]),
Host.
@@ -1357,20 +1631,55 @@ verify_hostname_match_default(Ref, Pres) ->
verify_hostname_match_default0(FQDN=[_|_], {cn,FQDN}) ->
not lists:member($*, FQDN);
verify_hostname_match_default0(FQDN=[_|_], {cn,Name=[_|_]}) ->
- [F1|Fs] = string:tokens(FQDN, "."),
- [N1|Ns] = string:tokens(Name, "."),
- match_wild(F1,N1) andalso Fs==Ns;
+ verify_hostname_match_wildcard(FQDN, Name);
verify_hostname_match_default0({dns_id,R}, {dNSName,P}) ->
R==P;
verify_hostname_match_default0({uri_id,R}, {uniformResourceIdentifier,P}) ->
R==P;
-verify_hostname_match_default0({srv_id,R}, {T,P}) when T == srvName ;
- T == ?srvName_OID ->
+verify_hostname_match_default0({ip,R}, {iPAddress,P}) when length(P) == 4 ->
+ %% IPv4
+ try
+ list_to_tuple(P)
+ == if is_tuple(R), size(R)==4 -> R;
+ is_list(R) -> ok(inet:parse_ipv4strict_address(R))
+ end
+ catch
+ _:_ ->
+ false
+ end;
+
+verify_hostname_match_default0({ip,R}, {iPAddress,P}) when length(P) == 16 ->
+ %% IPv6. The length 16 is due to the certificate specification.
+ try
+ l16_to_tup(P)
+ == if is_tuple(R), size(R)==8 -> R;
+ is_list(R) -> ok(inet:parse_ipv6strict_address(R))
+ end
+ catch
+ _:_ ->
+ false
+ end;
+verify_hostname_match_default0({srv_id,R}, {srvName,P}) ->
+ R==P;
+verify_hostname_match_default0({srv_id,R}, {?srvName_OID,P}) ->
R==P;
verify_hostname_match_default0(_, _) ->
false.
+verify_hostname_match_wildcard(FQDN, Name) ->
+ [F1|Fs] = string:tokens(FQDN, "."),
+ [N1|Ns] = string:tokens(Name, "."),
+ match_wild(F1,N1) andalso Fs==Ns.
+
+
+ok({ok,X}) -> X.
+
+l16_to_tup(L) -> list_to_tuple(l16_to_tup(L, [])).
+%%
+l16_to_tup([A,B|T], Acc) -> l16_to_tup(T, [(A bsl 8) bor B | Acc]);
+l16_to_tup([], Acc) -> lists:reverse(Acc).
+
match_wild(A, [$*|B]) -> match_wild_suffixes(A, B);
match_wild([C|A], [ C|B]) -> match_wild(A, B);
match_wild([], []) -> true;
@@ -1409,11 +1718,18 @@ verify_hostname_match_loop(Refs, Pres, MatchFun, FailCB, Cert) ->
Refs).
+to_lower_ascii({ip,_}=X) -> X;
+to_lower_ascii({iPAddress,_}=X) -> X;
to_lower_ascii(S) when is_list(S) -> lists:map(fun to_lower_ascii/1, S);
to_lower_ascii({T,S}) -> {T, to_lower_ascii(S)};
to_lower_ascii(C) when $A =< C,C =< $Z -> C + ($a-$A);
to_lower_ascii(C) -> C.
to_string(S) when is_list(S) -> S;
-to_string(B) when is_binary(B) -> binary_to_list(B).
+to_string(B) when is_binary(B) -> binary_to_list(B);
+to_string(X) -> X.
+format_details([]) ->
+ no_relevant_crls;
+format_details(Details) ->
+ Details.
diff --git a/lib/public_key/test/erl_make_certs.erl b/lib/public_key/test/erl_make_certs.erl
index e4118bab0d..e772ea1734 100644
--- a/lib/public_key/test/erl_make_certs.erl
+++ b/lib/public_key/test/erl_make_certs.erl
@@ -178,8 +178,9 @@ make_tbs(SubjectKey, Opts) ->
_ ->
subject(proplists:get_value(subject, Opts),false)
end,
-
- {#'OTPTBSCertificate'{serialNumber = trunc(random:uniform()*100000000)*10000 + 1,
+ Rnd = rand:uniform( 1000000000000 ),
+ %% 1 =< Rnd < 1000000000001
+ {#'OTPTBSCertificate'{serialNumber = Rnd,
signature = SignAlgo,
issuer = Issuer,
validity = validity(Opts),
@@ -466,7 +467,8 @@ odd_rand(Size) ->
odd_rand(Min, Max).
odd_rand(Min,Max) ->
- Rand = crypto:rand_uniform(Min,Max),
+ %% Odd random number N such that Min =< N =< Max
+ Rand = (Min-1) + rand:uniform(Max-Min), % Min =< Rand < Max
case Rand rem 2 of
0 ->
Rand + 1;
diff --git a/lib/public_key/test/pbe_SUITE.erl b/lib/public_key/test/pbe_SUITE.erl
index 44caf479e5..523c9e2515 100644
--- a/lib/public_key/test/pbe_SUITE.erl
+++ b/lib/public_key/test/pbe_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -226,11 +226,6 @@ pbes2(Config) when is_list(Config) ->
ok
end.
-check_key_info(#'PrivateKeyInfo'{privateKeyAlgorithm =
- #'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?rsaEncryption},
- privateKey = Key}) ->
- #'RSAPrivateKey'{} = public_key:der_decode('RSAPrivateKey', iolist_to_binary(Key)).
-
decode_encode_key_file(File, Password, Cipher, Config) ->
Datadir = proplists:get_value(data_dir, Config),
{ok, PemKey} = file:read_file(filename:join(Datadir, File)),
@@ -238,11 +233,10 @@ decode_encode_key_file(File, Password, Cipher, Config) ->
PemEntry = public_key:pem_decode(PemKey),
ct:print("Pem entry: ~p" , [PemEntry]),
[{Asn1Type, _, {Cipher,_} = CipherInfo} = PubEntry] = PemEntry,
- KeyInfo = public_key:pem_entry_decode(PubEntry, Password),
+ #'RSAPrivateKey'{} = KeyInfo = public_key:pem_entry_decode(PubEntry, Password),
PemKey1 = public_key:pem_encode([public_key:pem_entry_encode(Asn1Type, KeyInfo, {CipherInfo, Password})]),
Pem = strip_ending_newlines(PemKey),
- Pem = strip_ending_newlines(PemKey1),
- check_key_info(KeyInfo).
+ Pem = strip_ending_newlines(PemKey1).
strip_ending_newlines(Bin) ->
string:strip(binary_to_list(Bin), right, 10).
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index 80895ce97c..1955e9e119 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -47,7 +47,10 @@ all() ->
pkix_iso_rsa_oid, pkix_iso_dsa_oid, pkix_crl, general_name,
pkix_verify_hostname_cn,
pkix_verify_hostname_subjAltName,
+ pkix_verify_hostname_subjAltName_IP,
pkix_verify_hostname_options,
+ pkix_test_data_all_default,
+ pkix_test_data,
short_cert_issuer_hash, short_crl_issuer_hash,
ssh_hostkey_fingerprint_md5_implicit,
ssh_hostkey_fingerprint_md5,
@@ -60,7 +63,11 @@ all() ->
groups() ->
[{pem_decode_encode, [], [dsa_pem, rsa_pem, ec_pem, encrypted_pem,
- dh_pem, cert_pem, pkcs7_pem, pkcs10_pem]},
+ dh_pem, cert_pem, pkcs7_pem, pkcs10_pem, ec_pem2,
+ rsa_priv_pkcs8, dsa_priv_pkcs8, ec_priv_pkcs8,
+ ec_pem_encode_generated,
+ gen_ec_param_prime_field, gen_ec_param_char_2_field
+ ]},
{ssh_public_key_decode_encode, [],
[ssh_rsa_public_key, ssh_dsa_public_key, ssh_ecdsa_public_key,
ssh_rfc4716_rsa_comment, ssh_rfc4716_dsa_comment,
@@ -92,6 +99,21 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
%%-------------------------------------------------------------------
+
+init_per_testcase(pkix_test_data_all_default, Config) ->
+ case crypto:ec_curves() of
+ [] ->
+ {skip, missing_ecc_support};
+ _ ->
+ init_common_per_testcase(Config)
+ end;
+
+init_per_testcase(gen_ec_param_prime_field=TC, Config) ->
+ init_per_testcase_gen_ec_param(TC, secp521r1, Config);
+
+init_per_testcase(gen_ec_param_char_2_field=TC, Config) ->
+ init_per_testcase_gen_ec_param(TC, sect571r1, Config);
+
init_per_testcase(TestCase, Config) ->
case TestCase of
ssh_hostkey_fingerprint_md5_implicit -> init_fingerprint_testcase([md5], Config);
@@ -101,6 +123,7 @@ init_per_testcase(TestCase, Config) ->
ssh_hostkey_fingerprint_sha384 -> init_fingerprint_testcase([sha384], Config);
ssh_hostkey_fingerprint_sha512 -> init_fingerprint_testcase([sha512], Config);
ssh_hostkey_fingerprint_list -> init_fingerprint_testcase([sha,md5], Config);
+ ec_pem_encode_generated -> init_ec_pem_encode_generated(Config);
_ -> init_common_per_testcase(Config)
end.
@@ -159,6 +182,19 @@ dsa_pem(Config) when is_list(Config) ->
DSAPubPemNoEndNewLines = strip_superfluous_newlines(DSAPubPem),
DSAPubPemNoEndNewLines = strip_superfluous_newlines(public_key:pem_encode([PubEntry0])).
+dsa_priv_pkcs8() ->
+ [{doc, "DSA PKCS8 private key decode/encode"}].
+dsa_priv_pkcs8(Config) when is_list(Config) ->
+ Datadir = proplists:get_value(data_dir, Config),
+ {ok, DsaPem} = file:read_file(filename:join(Datadir, "dsa_key_pkcs8.pem")),
+ [{'PrivateKeyInfo', DerDSAKey, not_encrypted} = Entry0 ] = public_key:pem_decode(DsaPem),
+ DSAKey = public_key:der_decode('PrivateKeyInfo', DerDSAKey),
+ DSAKey = public_key:pem_entry_decode(Entry0),
+ true = check_entry_type(DSAKey, 'DSAPrivateKey'),
+ PrivEntry0 = public_key:pem_entry_encode('PrivateKeyInfo', DSAKey),
+ DSAPemNoEndNewLines = strip_superfluous_newlines(DsaPem),
+ DSAPemNoEndNewLines = strip_superfluous_newlines(public_key:pem_encode([PrivEntry0])).
+
%%--------------------------------------------------------------------
rsa_pem() ->
@@ -194,6 +230,19 @@ rsa_pem(Config) when is_list(Config) ->
RSARawPemNoEndNewLines = strip_superfluous_newlines(RSARawPem),
RSARawPemNoEndNewLines = strip_superfluous_newlines(public_key:pem_encode([PubEntry1])).
+rsa_priv_pkcs8() ->
+ [{doc, "RSA PKCS8 private key decode/encode"}].
+rsa_priv_pkcs8(Config) when is_list(Config) ->
+ Datadir = proplists:get_value(data_dir, Config),
+ {ok, RsaPem} = file:read_file(filename:join(Datadir, "rsa_key_pkcs8.pem")),
+ [{'PrivateKeyInfo', DerRSAKey, not_encrypted} = Entry0 ] = public_key:pem_decode(RsaPem),
+ RSAKey = public_key:der_decode('PrivateKeyInfo', DerRSAKey),
+ RSAKey = public_key:pem_entry_decode(Entry0),
+ true = check_entry_type(RSAKey, 'RSAPrivateKey'),
+ PrivEntry0 = public_key:pem_entry_encode('PrivateKeyInfo', RSAKey),
+ RSAPemNoEndNewLines = strip_superfluous_newlines(RsaPem),
+ RSAPemNoEndNewLines = strip_superfluous_newlines(public_key:pem_encode([PrivEntry0])).
+
%%--------------------------------------------------------------------
ec_pem() ->
@@ -217,9 +266,59 @@ ec_pem(Config) when is_list(Config) ->
true = check_entry_type(ECParams, 'EcpkParameters'),
ECPrivKey = public_key:pem_entry_decode(Entry2),
true = check_entry_type(ECPrivKey, 'ECPrivateKey'),
+ true = check_entry_type(ECPrivKey#'ECPrivateKey'.parameters, 'EcpkParameters'),
ECPemNoEndNewLines = strip_superfluous_newlines(ECPrivPem),
ECPemNoEndNewLines = strip_superfluous_newlines(public_key:pem_encode([Entry1, Entry2])).
+ec_pem2() ->
+ [{doc, "EC key w/explicit params PEM-file decode/encode"}].
+ec_pem2(Config) when is_list(Config) ->
+ Datadir = proplists:get_value(data_dir, Config),
+
+ %% Load key with explicit curve parameters. Generated with...
+ %% openssl ecparam -name secp521r1 -genkey -param_enc explicit -out ec_key2.pem
+ {ok, ECPrivPem} = file:read_file(filename:join(Datadir, "ec_key2.pem")),
+ [{'EcpkParameters', _, not_encrypted} = Entry1,
+ {'ECPrivateKey', _, not_encrypted} = Entry2] = public_key:pem_decode(ECPrivPem),
+
+ ECParams = public_key:pem_entry_decode(Entry1),
+ true = check_entry_type(ECParams, 'EcpkParameters'),
+ ECPrivKey = public_key:pem_entry_decode(Entry2),
+ true = check_entry_type(ECPrivKey, 'ECPrivateKey'),
+ true = check_entry_type(ECPrivKey#'ECPrivateKey'.parameters, 'EcpkParameters'),
+ ECPemNoEndNewLines = strip_superfluous_newlines(ECPrivPem),
+ ECPemNoEndNewLines = strip_superfluous_newlines(public_key:pem_encode([Entry1, Entry2])).
+
+ec_priv_pkcs8() ->
+ [{doc, "EC PKCS8 private key decode/encode"}].
+ec_priv_pkcs8(Config) when is_list(Config) ->
+ Datadir = proplists:get_value(data_dir, Config),
+ {ok, ECPrivPem} = file:read_file(filename:join(Datadir, "ec_key_pkcs8.pem")),
+ [{'PrivateKeyInfo', _, not_encrypted} = PKCS8Key] = public_key:pem_decode(ECPrivPem),
+ ECPrivKey = public_key:pem_entry_decode(PKCS8Key),
+ true = check_entry_type(ECPrivKey, 'ECPrivateKey'),
+ true = check_entry_type(ECPrivKey#'ECPrivateKey'.parameters, 'EcpkParameters'),
+ PrivEntry0 = public_key:pem_entry_encode('PrivateKeyInfo', ECPrivKey),
+ ECPemNoEndNewLines = strip_superfluous_newlines(ECPrivPem),
+ ECPemNoEndNewLines = strip_superfluous_newlines(public_key:pem_encode([PrivEntry0])).
+
+init_ec_pem_encode_generated(Config) ->
+ case catch true = lists:member('secp384r1', crypto:ec_curves()) of
+ {'EXIT', _} -> {skip, {'secp384r1', not_supported}};
+ _ -> init_common_per_testcase(Config)
+ end.
+
+ec_pem_encode_generated() ->
+ [{doc, "PEM-encode generated EC key"}].
+ec_pem_encode_generated(_Config) ->
+
+ Key1 = public_key:generate_key({namedCurve, 'secp384r1'}),
+ public_key:pem_entry_encode('ECPrivateKey', Key1),
+
+ Key2 = public_key:generate_key({namedCurve, ?'secp384r1'}),
+ public_key:pem_entry_encode('ECPrivateKey', Key2).
+
+
%%--------------------------------------------------------------------
encrypted_pem() ->
@@ -619,12 +718,8 @@ encrypt_decrypt(Config) when is_list(Config) ->
Msg = list_to_binary(lists:duplicate(5, "Foo bar 100")),
RsaEncrypted = public_key:encrypt_private(Msg, PrivateKey),
Msg = public_key:decrypt_public(RsaEncrypted, PublicKey),
- Msg = public_key:decrypt_public(RsaEncrypted, PrivateKey),
RsaEncrypted2 = public_key:encrypt_public(Msg, PublicKey),
- RsaEncrypted3 = public_key:encrypt_public(Msg, PrivateKey),
Msg = public_key:decrypt_private(RsaEncrypted2, PrivateKey),
- Msg = public_key:decrypt_private(RsaEncrypted3, PrivateKey),
-
ok.
%%--------------------------------------------------------------------
@@ -866,7 +961,7 @@ pkix_verify_hostname_cn(Config) ->
%% openssl req -x509 -nodes -newkey rsa:1024 -keyout /dev/null -extensions SAN -config public_key_SUITE_data/verify_hostname.conf 2>/dev/null > public_key_SUITE_data/pkix_verify_hostname_subjAltName.pem
%%
%% Subject: C=SE, CN=example.com
-%% Subject Alternative Name: DNS:kb.example.org, URI:http://www.example.org, URI:https://wws.example.org
+%% Subject Alternative Name: DNS:kb.example.org, DNS:*.example.org, URI:http://www.example.org, URI:https://wws.example.org
pkix_verify_hostname_subjAltName(Config) ->
DataDir = proplists:get_value(data_dir, Config),
@@ -885,7 +980,25 @@ pkix_verify_hostname_subjAltName(Config) ->
{dns_id,"wws.example.org"}]),
%% Check that a dns_id matches a DNS subjAltName:
- true = public_key:pkix_verify_hostname(Cert, [{dns_id,"kb.example.org"}]).
+ true = public_key:pkix_verify_hostname(Cert, [{dns_id,"kb.example.org"}]),
+
+ %% Check that a dns_id does not match a DNS subjAltName wiht wildcard
+ false = public_key:pkix_verify_hostname(Cert, [{dns_id,"other.example.org"}]),
+
+ %% Check that a dns_id does match a DNS subjAltName wiht wildcard with matchfun
+ true = public_key:pkix_verify_hostname(Cert, [{dns_id,"other.example.org"}],
+ [{match_fun, public_key:pkix_verify_hostname_match_fun(https)}
+ ]
+ ),
+
+ %% Check that a uri_id does not match a DNS subjAltName wiht wildcard
+ false = public_key:pkix_verify_hostname(Cert, [{uri_id,"https://other.example.org"}]),
+
+ %% Check that a dns_id does match a DNS subjAltName wiht wildcard with matchfun
+ true = public_key:pkix_verify_hostname(Cert, [{uri_id,"https://other.example.org"}],
+ [{match_fun, public_key:pkix_verify_hostname_match_fun(https)}
+ ]
+ ).
%%--------------------------------------------------------------------
%% Uses the pem-file for pkix_verify_hostname_cn
@@ -932,9 +1045,51 @@ pkix_verify_hostname_options(Config) ->
end}]),
true = public_key:pkix_verify_hostname(Cert, [{uri_id,"https://example.com"}],
[{fqdn_fun, fun(_) -> default end}]),
- false = public_key:pkix_verify_hostname(Cert, [{uri_id,"some://very.wrong.domain"}]).
+ false = public_key:pkix_verify_hostname(Cert, [{uri_id,"some://very.wrong.domain"}]),
+
+ true = public_key:pkix_verify_hostname(Cert, [{dns_id,"example.com"}]),
+ true = public_key:pkix_verify_hostname(Cert, [{dns_id,"abb.bar.example.com"}]),
+ false = public_key:pkix_verify_hostname(Cert, [{dns_id,"example.com"},
+ {dns_id,"abb.bar.example.com"}],
+ [{fqdn_fun,fun(_)->undefined end}]).
+
%%--------------------------------------------------------------------
+%% To generate the PEM file contents:
+%%
+%% openssl req -x509 -nodes -newkey rsa:1024 -keyout /dev/null -extensions SAN -config public_key_SUITE_data/verify_hostname_ip.conf 2>/dev/null > public_key_SUITE_data/pkix_verify_hostname_subjAltName_IP.pem
+%%
+%% Subject: C=SE, CN=example.com
+%% Subject Alternative Name: DNS:1.2.3.4, DNS: abcd:ef::1, IP:10.67.16.75, URI:https://10.11.12.13
+
+pkix_verify_hostname_subjAltName_IP(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ {ok,Bin} = file:read_file(filename:join(DataDir,"pkix_verify_hostname_subjAltName_IP.pem")),
+ Cert = public_key:pkix_decode_cert(element(2,hd(public_key:pem_decode(Bin))), otp),
+
+ %% Print the tests that a matchfun has to handle
+ catch public_key:pkix_verify_hostname(Cert, [{some_tag,"some.domain"},
+ {ip, {10,67,16,75}}
+ ],
+ [{match_fun,
+ fun(Ref,Pres) ->
+ ct:pal("~p:~p:~nRef : ~p~nPres: ~p",[?MODULE,?LINE,Ref,Pres]),
+ false
+ end}]),
+
+ false = public_key:pkix_verify_hostname(Cert, [{uri_id,"https://1.2.3.4"}]),
+ true = public_key:pkix_verify_hostname(Cert, [{uri_id,"https://10.11.12.13"}]),
+ true = public_key:pkix_verify_hostname(Cert, [{dns_id,"1.2.3.4"}]),
+ true = public_key:pkix_verify_hostname(Cert, [{dns_id,<<"1.2.3.4">>}]),
+ false = public_key:pkix_verify_hostname(Cert, [{dns_id,"10.67.16.75"}]),
+ true = public_key:pkix_verify_hostname(Cert, [{ip, "aBcD:ef:0::0:1"}]),
+ true = public_key:pkix_verify_hostname(Cert, [{ip, {16#abcd,16#ef,0,0,0,0,0,1}}]),
+ true = public_key:pkix_verify_hostname(Cert, [{ip, "10.67.16.75"}]),
+ true = public_key:pkix_verify_hostname(Cert, [{ip, <<"10.67.16.75">>}]),
+ true = public_key:pkix_verify_hostname(Cert, [{ip, {10,67,16,75}}]),
+ false = public_key:pkix_verify_hostname(Cert, [{ip, {1,2,3,4}}]),
+ false = public_key:pkix_verify_hostname(Cert, [{ip, {10,11,12,13}}]).
+%%--------------------------------------------------------------------
pkix_iso_rsa_oid() ->
[{doc, "Test workaround for supporting certs that use ISO oids"
" 1.3.14.3.2.29 instead of PKIX/PKCS oid"}].
@@ -1007,6 +1162,84 @@ general_name(Config) when is_list(Config) ->
authorityCertSerialNumber =
1}).
%%--------------------------------------------------------------------
+
+pkix_test_data_all_default() ->
+ [{doc, "Test API function pkix_test_data/1"}].
+
+pkix_test_data_all_default(Config) when is_list(Config) ->
+ #{server_config := ServerConf0,
+ client_config := ClientConf0} = public_key:pkix_test_data(#{server_chain =>
+ #{root => [],
+ intermediates => [[]],
+ peer => []},
+ client_chain =>
+ #{root => [],
+ intermediates => [[]],
+ peer => []}}),
+ check_conf_member(ServerConf0, [key, cert, cacerts]),
+ check_conf_member(ClientConf0, [key, cert, cacerts]),
+
+ 3 = length(proplists:get_value(cacerts, ServerConf0)),
+ 3 = length(proplists:get_value(cacerts, ServerConf0)),
+
+ #{server_config := ServerConf1,
+ client_config := ClientConf1} = public_key:pkix_test_data(#{server_chain =>
+ #{root => [],
+ peer => []},
+ client_chain =>
+ #{root => [],
+ peer => []}}),
+ 2 = length(proplists:get_value(cacerts, ServerConf1)),
+ 2 = length(proplists:get_value(cacerts, ServerConf1)),
+
+ check_conf_member(ServerConf1, [key, cert, cacerts]),
+ check_conf_member(ClientConf1, [key, cert, cacerts]).
+
+
+pkix_test_data() ->
+ [{doc, "Test API function pkix_test_data/1"}].
+
+pkix_test_data(Config) when is_list(Config) ->
+ {Year, Month, Day} = date(),
+ Keygen =
+ case crypto:ec_curves() of
+ [] ->
+ {rsa, 2048, 17};
+ [Curve |_] ->
+ Oid = pubkey_cert_records:namedCurves(Curve),
+ {namedCurve, Oid}
+ end,
+ #{server_config := ServerConf0,
+ client_config := ClientConf0} =
+ public_key:pkix_test_data(#{server_chain =>
+ #{root => [],
+ intermediates => [],
+ peer => [{key, hardcode_rsa_key()}]},
+ client_chain =>
+ #{root => [{validity, {{Year-2, Month, Day},
+ {Year-1, Month, Day}}}],
+ intermediates =>
+ [[{extensions, [#'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue = #'BasicConstraints'{cA=true,
+ pathLenConstraint = 1},
+ critical = true}]}]],
+ peer => [{key, Keygen}, {digest, sha1}]}}),
+ check_conf_member(ServerConf0, [key, cert, cacerts]),
+ check_conf_member(ClientConf0, [key, cert, cacerts]).
+
+
+
+check_conf_member(_, []) ->
+ true;
+check_conf_member(Conf, [Member | Rest]) ->
+ case lists:keymember(Member, 1, Conf) of
+ true ->
+ check_conf_member(Conf, Rest);
+ false ->
+ ct:fail({misssing_conf, Member})
+ end.
+
+%%--------------------------------------------------------------------
short_cert_issuer_hash() ->
[{doc, "Test OpenSSL-style hash for certificate issuer"}].
@@ -1041,6 +1274,19 @@ short_crl_issuer_hash(Config) when is_list(Config) ->
CrlIssuerHash = public_key:short_name_hash(Issuer).
+%%--------------------------------------------------------------------
+gen_ec_param_prime_field() ->
+ [{doc, "Generate key with EC prime_field parameters"}].
+gen_ec_param_prime_field(Config) when is_list(Config) ->
+ Datadir = proplists:get_value(data_dir, Config),
+ do_gen_ec_param(filename:join(Datadir, "ec_key_param0.pem")).
+
+%%--------------------------------------------------------------------
+gen_ec_param_char_2_field() ->
+ [{doc, "Generate key with EC characteristic_two_field parameters"}].
+gen_ec_param_char_2_field(Config) when is_list(Config) ->
+ Datadir = proplists:get_value(data_dir, Config),
+ do_gen_ec_param(filename:join(Datadir, "ec_key_param1.pem")).
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
@@ -1095,7 +1341,7 @@ check_entry_type(#'ECPrivateKey'{}, 'ECPrivateKey') ->
true;
check_entry_type({namedCurve, _}, 'EcpkParameters') ->
true;
-check_entry_type(#'ECParameters'{}, 'EcpkParameters') ->
+check_entry_type({ecParameters, #'ECParameters'{}}, 'EcpkParameters') ->
true;
check_entry_type(_,_) ->
false.
@@ -1113,6 +1359,43 @@ strip_superfluous_newlines(Bin) ->
Str = string:strip(binary_to_list(Bin), right, 10),
re:replace(Str,"\n\n","\n", [{return,list}, global]).
+do_gen_ec_param(File) ->
+ {ok, KeyPem} = file:read_file(File),
+ Entries = public_key:pem_decode(KeyPem),
+ [ParamInfo] = [Entry || Entry={'EcpkParameters', _, not_encrypted} <- Entries],
+ {ecParameters, Params} = public_key:pem_entry_decode(ParamInfo),
+ Key = public_key:generate_key(Params),
+ case check_entry_type(Key, 'ECPrivateKey') of
+ true ->
+ ok;
+ false ->
+ ct:fail({key_gen_fail, File})
+ end.
+
+init_per_testcase_gen_ec_param(_TC, Curve, Config) ->
+ case crypto:ec_curves() of
+ [] ->
+ {skip, missing_ec_support};
+ Curves ->
+ case lists:member(Curve, Curves)
+ andalso crypto_supported_curve(Curve, Curves)
+ of
+ true ->
+ init_common_per_testcase(Config);
+ false ->
+ {skip, {missing_ec_support, Curve}}
+ end
+ end.
+
+
+crypto_supported_curve(Curve, _Curves) ->
+ try crypto:generate_key(ecdh, Curve) of
+ {error,_} -> false; % Just in case crypto is changed in the future...
+ _-> true
+ catch
+ _:_-> false
+ end.
+
incorrect_countryname_pkix_cert() ->
<<48,130,5,186,48,130,4,162,160,3,2,1,2,2,7,7,250,61,63,6,140,137,48,13,6,9,42, 134,72,134,247,13,1,1,5,5,0,48,129,220,49,11,48,9,6,3,85,4,6,19,2,85,83,49, 16,48,14,6,3,85,4,8,19,7,65,114,105,122,111,110,97,49,19,48,17,6,3,85,4,7,19, 10,83,99,111,116,116,115,100,97,108,101,49,37,48,35,6,3,85,4,10,19,28,83,116, 97,114,102,105,101,108,100,32,84,101,99,104,110,111,108,111,103,105,101,115, 44,32,73,110,99,46,49,57,48,55,6,3,85,4,11,19,48,104,116,116,112,58,47,47,99, 101,114,116,105,102,105,99,97,116,101,115,46,115,116,97,114,102,105,101,108, 100,116,101,99,104,46,99,111,109,47,114,101,112,111,115,105,116,111,114,121, 49,49,48,47,6,3,85,4,3,19,40,83,116,97,114,102,105,101,108,100,32,83,101,99, 117,114,101,32,67,101,114,116,105,102,105,99,97,116,105,111,110,32,65,117, 116,104,111,114,105,116,121,49,17,48,15,6,3,85,4,5,19,8,49,48,54,56,56,52,51, 53,48,30,23,13,49,48,49,48,50,51,48,49,51,50,48,53,90,23,13,49,50,49,48,50, 51,48,49,51,50,48,53,90,48,122,49,11,48,9,6,3,85,4,6,12,2,85,83,49,11,48,9,6, 3,85,4,8,12,2,65,90,49,19,48,17,6,3,85,4,7,12,10,83,99,111,116,116,115,100, 97,108,101,49,38,48,36,6,3,85,4,10,12,29,83,112,101,99,105,97,108,32,68,111, 109,97,105,110,32,83,101,114,118,105,99,101,115,44,32,73,110,99,46,49,33,48, 31,6,3,85,4,3,12,24,42,46,108,111,103,105,110,46,115,101,99,117,114,101,115, 101,114,118,101,114,46,110,101,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,185,136,240,80,141,36,124, 245,182,130,73,19,188,74,166,117,72,228,185,209,43,129,244,40,44,193,231,11, 209,12,234,88,43,142,1,162,48,122,17,95,230,105,171,131,12,147,46,204,36,80, 250,171,33,253,35,62,83,22,71,212,186,141,14,198,89,89,121,204,224,122,246, 127,110,188,229,162,67,95,6,74,231,127,99,131,7,240,85,102,203,251,50,58,58, 104,245,103,181,183,134,32,203,121,232,54,32,188,139,136,112,166,126,14,91, 223,153,172,164,14,61,38,163,208,215,186,210,136,213,143,70,147,173,109,217, 250,169,108,31,211,104,238,103,93,182,59,165,43,196,189,218,241,30,148,240, 109,90,69,176,194,52,116,173,151,135,239,10,209,179,129,192,102,75,11,25,168, 223,32,174,84,223,134,70,167,55,172,143,27,130,123,226,226,7,34,142,166,39, 48,246,96,231,150,84,220,106,133,193,55,95,159,227,24,249,64,36,1,142,171,16, 202,55,126,7,156,15,194,22,116,53,113,174,104,239,203,120,45,131,57,87,84, 163,184,27,83,57,199,91,200,34,43,98,61,180,144,76,65,170,177,2,3,1,0,1,163, 130,1,224,48,130,1,220,48,15,6,3,85,29,19,1,1,255,4,5,48,3,1,1,0,48,29,6,3, 85,29,37,4,22,48,20,6,8,43,6,1,5,5,7,3,1,6,8,43,6,1,5,5,7,3,2,48,14,6,3,85, 29,15,1,1,255,4,4,3,2,5,160,48,56,6,3,85,29,31,4,49,48,47,48,45,160,43,160, 41,134,39,104,116,116,112,58,47,47,99,114,108,46,115,116,97,114,102,105,101, 108,100,116,101,99,104,46,99,111,109,47,115,102,115,50,45,48,46,99,114,108, 48,83,6,3,85,29,32,4,76,48,74,48,72,6,11,96,134,72,1,134,253,110,1,7,23,2,48, 57,48,55,6,8,43,6,1,5,5,7,2,1,22,43,104,116,116,112,115,58,47,47,99,101,114, 116,115,46,115,116,97,114,102,105,101,108,100,116,101,99,104,46,99,111,109, 47,114,101,112,111,115,105,116,111,114,121,47,48,129,141,6,8,43,6,1,5,5,7,1, 1,4,129,128,48,126,48,42,6,8,43,6,1,5,5,7,48,1,134,30,104,116,116,112,58,47, 47,111,99,115,112,46,115,116,97,114,102,105,101,108,100,116,101,99,104,46,99, 111,109,47,48,80,6,8,43,6,1,5,5,7,48,2,134,68,104,116,116,112,58,47,47,99, 101,114,116,105,102,105,99,97,116,101,115,46,115,116,97,114,102,105,101,108, 100,116,101,99,104,46,99,111,109,47,114,101,112,111,115,105,116,111,114,121, 47,115,102,95,105,110,116,101,114,109,101,100,105,97,116,101,46,99,114,116, 48,31,6,3,85,29,35,4,24,48,22,128,20,73,75,82,39,209,27,188,242,161,33,106, 98,123,81,66,122,138,215,213,86,48,59,6,3,85,29,17,4,52,48,50,130,24,42,46, 108,111,103,105,110,46,115,101,99,117,114,101,115,101,114,118,101,114,46,110, 101,116,130,22,108,111,103,105,110,46,115,101,99,117,114,101,115,101,114,118, 101,114,46,110,101,116,48,29,6,3,85,29,14,4,22,4,20,138,233,191,208,157,203, 249,85,242,239,20,195,48,10,148,49,144,101,255,116,48,13,6,9,42,134,72,134, 247,13,1,1,5,5,0,3,130,1,1,0,82,31,121,162,49,50,143,26,167,202,143,61,71, 189,201,199,57,81,122,116,90,192,88,24,102,194,174,48,157,74,27,87,210,223, 253,93,3,91,150,109,120,1,110,27,11,200,198,141,222,246,14,200,71,105,41,138, 13,114,122,106,63,17,197,181,234,121,61,89,74,65,41,231,248,219,129,83,176, 219,55,107,55,211,112,98,38,49,69,77,96,221,108,123,152,12,210,159,157,141, 43,226,55,187,129,3,82,49,136,66,81,196,91,234,196,10,82,48,6,80,163,83,71, 127,102,177,93,209,129,26,104,2,84,24,255,248,161,3,244,169,234,92,122,110, 43,4,17,113,185,235,108,219,210,236,132,216,177,227,17,169,58,162,159,182, 162,93,160,229,200,9,163,229,110,121,240,168,232,14,91,214,188,196,109,210, 164,222,0,109,139,132,113,91,16,118,173,178,176,80,132,34,41,199,51,206,250, 224,132,60,115,192,94,107,163,219,212,226,225,65,169,148,108,213,46,174,173, 103,110,189,229,166,149,254,31,51,44,144,108,187,182,11,251,201,206,86,138, 208,59,51,86,132,235,81,225,88,34,190,8,184>>.
@@ -1128,3 +1411,15 @@ ssh_hostkey(rsa) ->
public_key),
PKdecoded.
+hardcode_rsa_key() ->
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus = 23995666614853919027835084074500048897452890537492185072956789802729257783422306095699263934587064480357348855732149402060270996295002843755712064937715826848741191927820899197493902093529581182351132392364214171173881547273475904587683433713767834856230531387991145055273426806331200574039205571401702219159773947658558490957010003143162250693492642996408861265758000254664396313741422909188635443907373976005987612936763564996605457102336549804831742940035613780926178523017685712710473543251580072875247250504243621640157403744718833162626193206685233710319205099867303242759099560438381385658382486042995679707669,
+ publicExponent = 17,
+ privateExponent = 11292078406990079542510627799764728892919007311761028269626724613049062486316379339152594792746853873109340637991599718616598115903530750002688030558925094987642913848386305504703012749896273497577003478759630198199473669305165131570674557041773098755873191241407597673069847908861741446606684974777271632545629600685952292605647052193819136445675100211504432575554351515262198132231537860917084269870590492135731720141577986787033006338680118008484613510063003323516659048210893001173583018220214626635609151105287049126443102976056146630518124476470236027123782297108342869049542023328584384300970694412006494684657,
+ prime1 = 169371138592582642967021557955633494538845517070305333860805485424261447791289944610138334410987654265476540480228705481960508520379619587635662291973699651583489223555422528867090299996446070521801757353675026048850480903160224210802452555900007597342687137394192939372218903554801584969667104937092080815197,
+ prime2 = 141675062317286527042995673340952251894209529891636708844197799307963834958115010129693036021381525952081167155681637592199810112261679449166276939178032066869788822014115556349519329537177920752776047051833616197615329017439297361972726138285974555338480581117881706656603857310337984049152655480389797687577,
+ exponent1 = 119556097830058336212015217380447172615655659108450823901745048534772786676204666783627059584226579481512852103690850928442711896738555003036938088452023283470698275450886490965004917644550167427154181661417665446247398284583687678213495921811770068712485038160606780733330990744565824684470897602653233516609,
+ exponent2 = 41669135975672507953822256864985956439473391144599032012999352737636422046504414744027363535700448809435637398729893409470532385959317485048904982111185902020526124121798693043976273393287623750816484427009887116945685005129205106462566511260580751570141347387612266663707016855981760014456663376585234613993,
+ coefficient = 76837684977089699359024365285678488693966186052769523357232308621548155587515525857011429902602352279058920284048929101483304120686557782043616693940283344235057989514310975192908256494992960578961614059245280827077951132083993754797053182279229469590276271658395444955906108899267024101096069475145863928441,
+ otherPrimeInfos = asn1_NOVALUE}.
diff --git a/lib/public_key/test/public_key_SUITE_data/dsa_key_pkcs8.pem b/lib/public_key/test/public_key_SUITE_data/dsa_key_pkcs8.pem
new file mode 100644
index 0000000000..86e38e2c76
--- /dev/null
+++ b/lib/public_key/test/public_key_SUITE_data/dsa_key_pkcs8.pem
@@ -0,0 +1,9 @@
+-----BEGIN PRIVATE KEY-----
+MIIBSwIBADCCASwGByqGSM44BAEwggEfAoGBALez5tklY5CdFeTMos899pA6i4u4
+uCtszgBzrdBk6cl5FVqzdzWMGTQiynnTpGsrOESinzP06Ip+pG15We2OORwgvCxD
+/W95aCiN0/+MdiXqlsmboBARMzsa+SmBENN3gF/+tuuEAFzOXU1q2cmEywRLyfbM
+2KIBVE/TChWYw2eRAhUA1R64VvcQ90XA8SOKVDmMA0dBzukCgYEAlLMYP0pbgBlg
+HQVO3/avAHlWNrIq52Lxk7SdPJWgMvPjTK9Z6sv88kxsCcydtjvO439j1yqcwk50
+GQc+86ktBWWz93/HkIdnFyqafef4mmWvm2Uq6ClQKS+A0Asfaj8Mys+HUMiI+qsf
+djRbyIpwb7MX1nsVdsKzALnZNMW27A0EFgIUWYCfDrv5tqwPWKJu00ez0R192SY=
+-----END PRIVATE KEY-----
diff --git a/lib/public_key/test/public_key_SUITE_data/ec_key2.pem b/lib/public_key/test/public_key_SUITE_data/ec_key2.pem
new file mode 100644
index 0000000000..56b8169e86
--- /dev/null
+++ b/lib/public_key/test/public_key_SUITE_data/ec_key2.pem
@@ -0,0 +1,29 @@
+-----BEGIN EC PARAMETERS-----
+MIIBwgIBATBNBgcqhkjOPQEBAkIB////////////////////////////////////
+//////////////////////////////////////////////////8wgZ4EQgH/////
+////////////////////////////////////////////////////////////////
+/////////////////ARBUZU+uWGOHJofkpohoLaFQO6i2nJbmbMV87i0iZGO8Qnh
+Vhk5Uex+k3sWUsC9O7G/BzVz34g9LDTx70Uf1GtQPwADFQDQnogAKRy4U5bMZxc5
+MoSqoNpkugSBhQQAxoWOBrcEBOnNnj7LZiOVtEKcZIE5BT+1Ifgor2BrTT26oUte
+d+/nWSj+HcEnov+o3jNIs8GFakKb+X5+McLlvWYBGDkpaniaO8AEXIpftCx9G9mY
+9URJV5tEaBevvRcnPmYsl+5ymV70JkDFULkBP60HYTU8cIaicsJAiL6Udp/RZlAC
+QgH///////////////////////////////////////////pRhoeDvy+Wa3/MAUj3
+CaXQO7XJuImcR667b7cekThkCQIBAQ==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MIICnQIBAQRCAVE6lUKRj5AE8Cw21A+iPWhXSg+XNuerrTyeFERY6AtOrRJ9mTQ3
+Av3xjiM3zhZy2KWnm62hvkvlGbZ7iDKcqg2GoIIBxjCCAcICAQEwTQYHKoZIzj0B
+AQJCAf//////////////////////////////////////////////////////////
+////////////////////////////MIGeBEIB////////////////////////////
+//////////////////////////////////////////////////////////wEQVGV
+PrlhjhyaH5KaIaC2hUDuotpyW5mzFfO4tImRjvEJ4VYZOVHsfpN7FlLAvTuxvwc1
+c9+IPSw08e9FH9RrUD8AAxUA0J6IACkcuFOWzGcXOTKEqqDaZLoEgYUEAMaFjga3
+BATpzZ4+y2YjlbRCnGSBOQU/tSH4KK9ga009uqFLXnfv51ko/h3BJ6L/qN4zSLPB
+hWpCm/l+fjHC5b1mARg5KWp4mjvABFyKX7QsfRvZmPVESVebRGgXr70XJz5mLJfu
+cple9CZAxVC5AT+tB2E1PHCGonLCQIi+lHaf0WZQAkIB////////////////////
+///////////////////////6UYaHg78vlmt/zAFI9wml0Du1ybiJnEeuu2+3HpE4
+ZAkCAQGhgYkDgYYABAFLBJzBphlIJmSPuXzTDTnZpL7A0fnyqit9V3TBvaOcL6Iw
+6m2TpXvNakxi8Flj0Ok4hdRt+YhawFs0bmzZCT8kfAFs7p55BPHk7FaMZaba77R8
+4V6MhUJSKLc0I/XQBtvoOgVlPJ0MPOndnIxPspCPll886yxG5kOMUAx3HjFg16RT
+eA==
+-----END EC PRIVATE KEY-----
diff --git a/lib/public_key/test/public_key_SUITE_data/ec_key_param0.pem b/lib/public_key/test/public_key_SUITE_data/ec_key_param0.pem
new file mode 100644
index 0000000000..679b08f1a2
--- /dev/null
+++ b/lib/public_key/test/public_key_SUITE_data/ec_key_param0.pem
@@ -0,0 +1,28 @@
+-----BEGIN EC PARAMETERS-----
+MIIBwgIBATBNBgcqhkjOPQEBAkIB////////////////////////////////////
+//////////////////////////////////////////////////8wgZ4EQgH/////
+////////////////////////////////////////////////////////////////
+/////////////////ARBUZU+uWGOHJofkpohoLaFQO6i2nJbmbMV87i0iZGO8Qnh
+Vhk5Uex+k3sWUsC9O7G/BzVz34g9LDTx70Uf1GtQPwADFQDQnogAKRy4U5bMZxc5
+MoSqoNpkugSBhQQAxoWOBrcEBOnNnj7LZiOVtEKcZIE5BT+1Ifgor2BrTT26oUte
+d+/nWSj+HcEnov+o3jNIs8GFakKb+X5+McLlvWYBGDkpaniaO8AEXIpftCx9G9mY
+9URJV5tEaBevvRcnPmYsl+5ymV70JkDFULkBP60HYTU8cIaicsJAiL6Udp/RZlAC
+QgH///////////////////////////////////////////pRhoeDvy+Wa3/MAUj3
+CaXQO7XJuImcR667b7cekThkCQIBAQ==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MIICnAIBAQRBP6XqBV/b2Q49a8RUvrJBwotzY+IErK5FkzgkExqJuyzXXMM3jMtd
+M1vlEF46OCjbldw7NaYITW1mpwz6z2xtqyagggHGMIIBwgIBATBNBgcqhkjOPQEB
+AkIB////////////////////////////////////////////////////////////
+//////////////////////////8wgZ4EQgH/////////////////////////////
+/////////////////////////////////////////////////////////ARBUZU+
+uWGOHJofkpohoLaFQO6i2nJbmbMV87i0iZGO8QnhVhk5Uex+k3sWUsC9O7G/BzVz
+34g9LDTx70Uf1GtQPwADFQDQnogAKRy4U5bMZxc5MoSqoNpkugSBhQQAxoWOBrcE
+BOnNnj7LZiOVtEKcZIE5BT+1Ifgor2BrTT26oUted+/nWSj+HcEnov+o3jNIs8GF
+akKb+X5+McLlvWYBGDkpaniaO8AEXIpftCx9G9mY9URJV5tEaBevvRcnPmYsl+5y
+mV70JkDFULkBP60HYTU8cIaicsJAiL6Udp/RZlACQgH/////////////////////
+//////////////////////pRhoeDvy+Wa3/MAUj3CaXQO7XJuImcR667b7cekThk
+CQIBAaGBiQOBhgAEAVtCjzs+HP67ZZheraLGJPY+iIJHwDYWeCyzn2J4/fOv5CTo
+x0+1QcjrECh4V4F6jfqwW/oQaG9KKyEWhvvWQ0yVAeBfE+89DhYB3h2kyelqRcwZ
+XUuB7n7TxijJiHJXq9b+u+sh0qH9ya6nbWjHk79V37pgQOegHjnRc1gIFz6IfRUa
+-----END EC PRIVATE KEY-----
diff --git a/lib/public_key/test/public_key_SUITE_data/ec_key_param1.pem b/lib/public_key/test/public_key_SUITE_data/ec_key_param1.pem
new file mode 100644
index 0000000000..67095d8dc5
--- /dev/null
+++ b/lib/public_key/test/public_key_SUITE_data/ec_key_param1.pem
@@ -0,0 +1,25 @@
+-----BEGIN EC PARAMETERS-----
+MIIBcQIBATAlBgcqhkjOPQECMBoCAgI7BgkqhkjOPQECAwMwCQIBAgIBBQIBCjBk
+BAEBBEgC9A5+IiHyld4pcRe389YvXGqX/8uM7/HNa6jOSpoYrYT/q72O+lkzK+et
+Z1ambilK/RhaeP8SqlIOTec5usoMf/7/fylVcnoDFQAqoFj3Og4zq0hrD2EEEMU6
+fxMjEASBkQQDAwAdNLhWKWwWwNQNPNd1CpPR0pVfqAql9A/I23sqvb3lOVD0wNKT
+zdcRo1tn+xSZrmADhhTxOUq/o7TIUNkn4ed2nI7sLRkDe/JzQtpjm23M//63PWnX
+jGwnpgCcu8oZgPhTOSHopoRCPkO6sIpXYpGvj0YbsqizUx0vBIXBmxbi8VFuI908
+GkgnrxuKwVsCSAP//////////////////////////////////////////////+Zh
+zhj/VZhzCAWbGGgjhR7H3ZyhFh3pPVF01m6Dgum7L+hORwIBAg==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MIICXgIBAQRIAwaM3VblR1nZJseRVx4qJBQLLulB7uMF9KE+hMPlzZjj/f3KbcK4
+dfhxYFf4gqWNJW3fzFMEYF7JpzDjuFTmfX5jjO5f8cw9oIIBdTCCAXECAQEwJQYH
+KoZIzj0BAjAaAgICOwYJKoZIzj0BAgMDMAkCAQICAQUCAQowZAQBAQRIAvQOfiIh
+8pXeKXEXt/PWL1xql//LjO/xzWuozkqaGK2E/6u9jvpZMyvnrWdWpm4pSv0YWnj/
+EqpSDk3nObrKDH/+/38pVXJ6AxUAKqBY9zoOM6tIaw9hBBDFOn8TIxAEgZEEAwMA
+HTS4VilsFsDUDTzXdQqT0dKVX6gKpfQPyNt7Kr295TlQ9MDSk83XEaNbZ/sUma5g
+A4YU8TlKv6O0yFDZJ+HndpyO7C0ZA3vyc0LaY5ttzP/+tz1p14xsJ6YAnLvKGYD4
+Uzkh6KaEQj5DurCKV2KRr49GG7Kos1MdLwSFwZsW4vFRbiPdPBpIJ68bisFbAkgD
+///////////////////////////////////////////////mYc4Y/1WYcwgFmxho
+I4Uex92coRYd6T1RdNZug4Lpuy/oTkcCAQKhgZUDgZIABALOIIukF443IxnNZx1Q
+4HKDifQ9Lj3Rh+inIKczXLLJNEGCJ0wwG3d4v/fOxzdepZcnYviFAijQQA/iYWsA
+/Zet+5B4yxKISQcHei+PXkqwAAwEqq6D4hO2orlNOO430rgLoA0MNFc7I1THanOp
+q4RhYp8qnCEjM7nfQ4R0F+hPgZK1VPojkrGolaY/cNT/oA==
+-----END EC PRIVATE KEY-----
diff --git a/lib/public_key/test/public_key_SUITE_data/ec_key_pkcs8.pem b/lib/public_key/test/public_key_SUITE_data/ec_key_pkcs8.pem
new file mode 100644
index 0000000000..8280a3671a
--- /dev/null
+++ b/lib/public_key/test/public_key_SUITE_data/ec_key_pkcs8.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgB349XXSmba5BbJT5UuCK
+OoyoPHsygy6n+WzP1J+8eYShRANCAATTJdDtiqV9Hs7q+Y/yak1z3uJpukFQGYmr
+lJ2iztxfv7bz10eJ5yM/GNqG8kK0w7SIzjedsIkfjRK7bX6mP7h4
+-----END PRIVATE KEY-----
diff --git a/lib/public_key/test/public_key_SUITE_data/pkix_verify_hostname_subjAltName.pem b/lib/public_key/test/public_key_SUITE_data/pkix_verify_hostname_subjAltName.pem
index 83e1ad37b3..7ab9ed7b96 100644
--- a/lib/public_key/test/public_key_SUITE_data/pkix_verify_hostname_subjAltName.pem
+++ b/lib/public_key/test/public_key_SUITE_data/pkix_verify_hostname_subjAltName.pem
@@ -1,14 +1,14 @@
-----BEGIN CERTIFICATE-----
-MIICEjCCAXugAwIBAgIJANwliLph5EiAMA0GCSqGSIb3DQEBCwUAMCMxCzAJBgNV
-BAYTAlNFMRQwEgYDVQQDEwtleGFtcGxlLmNvbTAeFw0xNjEyMjAxNTEyMjRaFw0x
-NzAxMTkxNTEyMjRaMCMxCzAJBgNVBAYTAlNFMRQwEgYDVQQDEwtleGFtcGxlLmNv
-bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAydstIN157w8QxkVaOl3wm81j
-fgZ8gqO3BXkECPF6bw5ewLlmePL6Qs4RypsaRe7cKJ9rHFlwhpdcYkxWSWEt2N7Z
-Ry3N4SjuU04ohWbYgy3ijTt7bJg7jOV1Dh56BnI4hwhQj0oNFizNZOeRRfEzdMnS
-+uk03t/Qre2NS7KbwnUCAwEAAaNOMEwwSgYDVR0RBEMwQYIOa2IuZXhhbXBsZS5v
-cmeGFmh0dHA6Ly93d3cuZXhhbXBsZS5vcmeGF2h0dHBzOi8vd3dzLmV4YW1wbGUu
-b3JnMA0GCSqGSIb3DQEBCwUAA4GBAKqFqW5gCso422bXriCBJoygokOTTOw1Rzpq
-K8Mm0B8W9rrW9OTkoLEcjekllZcUCZFin2HovHC5HlHZz+mQvBI1M6sN2HVQbSzS
-EgL66U9gwJVnn9/U1hXhJ0LO28aGbyE29DxnewNR741dWN3oFxCdlNaO6eMWaEsO
-gduJ5sDl
+MIICITCCAYqgAwIBAgIJAP31suf/Fi4oMA0GCSqGSIb3DQEBCwUAMCMxCzAJBgNV
+BAYTAlNFMRQwEgYDVQQDEwtleGFtcGxlLmNvbTAeFw0xODA1MTcxMDIzNDBaFw0x
+ODA2MTYxMDIzNDBaMCMxCzAJBgNVBAYTAlNFMRQwEgYDVQQDEwtleGFtcGxlLmNv
+bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsUVMXSM4Q6vYp7H4Svsfv4QQ
+dmUD3IdTbtumlyAqLZuc6Z0HU9IOE0wpF97+5AE3moHluwN/MtSX/fb9oxCjh3L6
+iDla770uUoIgiWkA9lyzuYXt7zGsqc0EmGMJRAHp4jOxI26U/C8wdXoyZsGD8GPr
+hYAI2Me4CkdDqCoRuUUCAwEAAaNdMFswWQYDVR0RBFIwUIIOa2IuZXhhbXBsZS5v
+cmeCDSouZXhhbXBsZS5vcmeGFmh0dHA6Ly93d3cuZXhhbXBsZS5vcmeGF2h0dHBz
+Oi8vd3dzLmV4YW1wbGUub3JnMA0GCSqGSIb3DQEBCwUAA4GBAKs8vWMqpXiuFhcq
+6W1dMrVB4tuDjt1Ctr3g2USXBLgm8NxsZzslFyDnrvtZY0hbjcAkGKMMhy8lFD5t
++GjBbyp7MKII6vJaVvc+wbrsbNdvioB1puGwbgVhgD3Kb79do9h6JrNncjMvBN7j
+VK6BUB8TUofFmztMjoPlxFOs/7qK
-----END CERTIFICATE-----
diff --git a/lib/public_key/test/public_key_SUITE_data/pkix_verify_hostname_subjAltName_IP.pem b/lib/public_key/test/public_key_SUITE_data/pkix_verify_hostname_subjAltName_IP.pem
new file mode 100644
index 0000000000..97d12cdadf
--- /dev/null
+++ b/lib/public_key/test/public_key_SUITE_data/pkix_verify_hostname_subjAltName_IP.pem
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIICBzCCAXCgAwIBAgIJAJgbo5FL73LuMA0GCSqGSIb3DQEBCwUAMCMxCzAJBgNV
+BAYTAlNFMRQwEgYDVQQDEwtleGFtcGxlLmNvbTAeFw0xNzEwMTExMDM0NDJaFw0x
+NzExMTAxMDM0NDJaMCMxCzAJBgNVBAYTAlNFMRQwEgYDVQQDEwtleGFtcGxlLmNv
+bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5muN8NIRHuqXgtAFpaJ4EPnd
+SD+hnzMiiWQ9qAsS8P4xFsl5aNH74BTgst6Rcq33qAw+4BtKFXMt7JbWMuZklFV3
+fzRSx099MVJSH3f2LDMNLfyDiSJnhBEv1rLPaosi91ZLvI5LiGTxzRLi3qftZBft
+Ryw1OempB4chLcBy2rsCAwEAAaNDMEEwPwYDVR0RBDgwNoIHMS4yLjMuNIcECkMQ
+S4cQq80A7wAAAAAAAAAAAAAAAYYTaHR0cHM6Ly8xMC4xMS4xMi4xMzANBgkqhkiG
+9w0BAQsFAAOBgQDMn8aqs/5FkkWhspvN2n+D2l87M+33a5My54ZVZhayZ/KRmhCN
+Gix/BiVYJ3UlmWmGcnQXb3MLt/LQHaD3S2whDaLN3xJ8BbnX7A4ZTybitdyeFhDw
+K3iDVUM3bSsBJ4EcBPWIMnow3ALP5HlGRMlH/87Qt+uVPXuwNh9pmyIhRQ==
+-----END CERTIFICATE-----
diff --git a/lib/public_key/test/public_key_SUITE_data/rsa_key_pkcs8.pem b/lib/public_key/test/public_key_SUITE_data/rsa_key_pkcs8.pem
new file mode 100644
index 0000000000..9ef5b3353f
--- /dev/null
+++ b/lib/public_key/test/public_key_SUITE_data/rsa_key_pkcs8.pem
@@ -0,0 +1,10 @@
+-----BEGIN PRIVATE KEY-----
+MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEA1GLJmDS5yLvg1zqa
+epnwCgOXzxpPvHokDQx+AcgfO14SPtCD6UTlDEwYBp+6tUTm+qgeQN/CTi7POwIA
+m7P3UwIDAQABAkALFiEJ1e7AwLXq5j88GR8Dls5s3CW/Y+zP1ZAaTbT7p0QUMxG+
+0ko7h8NoxcQJHZU27sZXCjog/IBqn577Xv4RAiEA8/aQ09kz0jxi4aNvlix4B+bW
+gX0sYtcCDkBzx8Y6iMkCIQDe3WCxV9PuiDjpuC8cAy3UMC5PBygZG4iK3arpgzxp
+OwIhAKxKJg+mpgVEJiTpsiVhNEeIS1bZWp5W75m3BM1B/haZAiBQOhEcxikcrR0P
+xaXvx5Uv1UhWWpUstKSqmLF17jBJEQIhAMx4HMLqwaGeYwOcxfzxz6Al8fnPmfAR
+hqFR28fVJrWX
+-----END PRIVATE KEY-----
diff --git a/lib/public_key/test/public_key_SUITE_data/verify_hostname.conf b/lib/public_key/test/public_key_SUITE_data/verify_hostname.conf
index a28864dc78..6b4e4f284e 100644
--- a/lib/public_key/test/public_key_SUITE_data/verify_hostname.conf
+++ b/lib/public_key/test/public_key_SUITE_data/verify_hostname.conf
@@ -10,7 +10,8 @@ CN=example.com
subjectAltName = @alt_names
[alt_names]
-DNS = kb.example.org
+DNS.1 = kb.example.org
+DNS.2 = *.example.org
URI.1 = http://www.example.org
URI.2 = https://wws.example.org
diff --git a/lib/public_key/test/public_key_SUITE_data/verify_hostname_ip.conf b/lib/public_key/test/public_key_SUITE_data/verify_hostname_ip.conf
new file mode 100644
index 0000000000..798592e4f6
--- /dev/null
+++ b/lib/public_key/test/public_key_SUITE_data/verify_hostname_ip.conf
@@ -0,0 +1,17 @@
+[req]
+prompt = no
+distinguished_name = DN
+
+[DN]
+C=SE
+CN=example.com
+
+[SAN]
+subjectAltName = @alt_names
+
+[alt_names]
+DNS = 1.2.3.4
+IP.1 = 10.67.16.75
+IP.2 = abcd:ef::1
+URI = https://10.11.12.13
+
diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk
index 83a77d2a28..4e52028c36 100644
--- a/lib/public_key/vsn.mk
+++ b/lib/public_key/vsn.mk
@@ -1 +1 @@
-PUBLIC_KEY_VSN = 1.4.1
+PUBLIC_KEY_VSN = 1.6.2
diff --git a/lib/reltool/doc/src/Makefile b/lib/reltool/doc/src/Makefile
index e378cdf980..dce8059616 100644
--- a/lib/reltool/doc/src/Makefile
+++ b/lib/reltool/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2016. All Rights Reserved.
+# Copyright Ericsson AB 2009-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -88,6 +88,7 @@ clean clean_docs:
fi \
done
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
diff --git a/lib/reltool/doc/src/notes.xml b/lib/reltool/doc/src/notes.xml
index 8593a1017f..e201ad4e23 100644
--- a/lib/reltool/doc/src/notes.xml
+++ b/lib/reltool/doc/src/notes.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2009</year>
- <year>2017</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -38,7 +38,56 @@
thus constitutes one section in this document. The title of each
section is the version number of Reltool.</p>
- <section><title>Reltool 0.7.4</title>
+ <section><title>Reltool 0.7.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Reltool 0.7.6</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Calls to <c>erlang:get_stacktrace()</c> are removed.
+ </p>
+ <p>
+ Own Id: OTP-14861</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Reltool 0.7.5</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Files generated by <c>release_handler</c> and
+ <c>reltool</c>, which might contain Unicode characters,
+ are now encoded as UTF-8 and written with format "~tp" or
+ "~ts". If the file is to be read by
+ <c>file:consult/1</c>, an encoding comment is added.</p>
+ <p>
+ Own Id: OTP-14463</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Reltool 0.7.4</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/reltool/doc/src/reltool.xml b/lib/reltool/doc/src/reltool.xml
index 5bfbee966b..874cda8369 100644
--- a/lib/reltool/doc/src/reltool.xml
+++ b/lib/reltool/doc/src/reltool.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2009</year>
- <year>2016</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -806,7 +806,7 @@ target_spec() = [target_spec()]
<name>stop(Pid) -> ok | {error, Reason}</name>
<fsummary>Stop a server or window process</fsummary>
<type>
- <v>Pid = server_pid() | window_pid()()</v>
+ <v>Pid = server_pid() | window_pid()</v>
<v>Reason = reason()</v>
</type>
<desc><p>Stop a server or window process</p></desc>
diff --git a/lib/reltool/doc/src/reltool_examples.xml b/lib/reltool/doc/src/reltool_examples.xml
index 30cb3c13b6..2a103119e6 100644
--- a/lib/reltool/doc/src/reltool_examples.xml
+++ b/lib/reltool/doc/src/reltool_examples.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2009</year>
- <year>2017</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -150,13 +150,13 @@ Eshell V9.0 (abort with ^G)
{mod_cond,all},
{incl_cond,derived},
{erts,[{app,erts,
- [{vsn,"9.0"},
- {lib_dir,"/usr/local/lib/erlang/lib/erts-9.0"},
+ [{vsn,"10.0"},
+ {lib_dir,"/usr/local/lib/erlang/lib/erts-10.0"},
{mod,erl_prim_loader,[]},
{mod,erl_tracer,[]},
{mod,erlang,[]},
{mod,erts_code_purger,[]},
- {mod,erts_dirty_process_code_checker,[]},
+ {mod,erts_dirty_process_signal_handler,[]},
{mod,erts_internal,[]},
{mod,erts_literal_area_collector,[]},
{mod,init,[]},
@@ -309,9 +309,9 @@ Eshell V9.0 (abort with ^G)
<section>
<title>Generate release and script files</title>
<pre>
-Erlang/OTP 20 [erts-9.0] [source-c13b302] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10]
+Erlang/OTP 20 [erts-10.0] [source-c13b302] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10]
[hipe] [kernel-poll:false]
-Eshell V9.0 (abort with ^G)
+Eshell V10.0 (abort with ^G)
1&gt;
1&gt; {ok, Server} = reltool:start_server([{config, {sys, [{boot_rel, "NAME"},
{rel, "NAME", "VSN",
@@ -324,13 +324,13 @@ Eshell V9.0 (abort with ^G)
3&gt;
3&gt; reltool:get_rel(Server, "NAME").
{ok,{release,{"NAME","VSN"},
- {erts,"9.0"},
+ {erts,"10.0"},
[{kernel,"5.2"},{stdlib,"3.3"},{sasl,"3.0.3"}]}}
4&gt;
4&gt; reltool:get_script(Server, "NAME").
{ok,{script,{"NAME","VSN"},
[{preLoaded,[erl_prim_loader,erl_tracer,erlang,
- erts_code_purger,erts_dirty_process_code_checker,
+ erts_code_purger,erts_dirty_process_signal_handler,
erts_internal,erts_literal_area_collector,init,otp_ring0,
prim_eval,prim_file,prim_inet,prim_zip,zlib]},
{progress,preloaded},
@@ -374,9 +374,9 @@ ok
<section>
<title>Create a target system</title>
<pre>
-Erlang/OTP 20 [erts-9.0] [source-c13b302] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10]
+Erlang/OTP 20 [erts-10.0] [source-c13b302] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10]
[hipe] [kernel-poll:false]
-Eshell V9.0 (abort with ^G)
+Eshell V10.0 (abort with ^G)
1&gt;
1&gt; Config = {sys, [{escript, "examples/display_args", [{incl_cond, include}]},
{app, inets, [{incl_cond, include}]},
@@ -393,7 +393,7 @@ Eshell V9.0 (abort with ^G)
2&gt;
2&gt; {ok, Spec} = reltool:get_target_spec([Config]).
{ok,[{create_dir,"releases",
- [{write_file,"start_erl.data","9.0 1.0\n"},
+ [{write_file,"start_erl.data","10.0 1.0\n"},
{create_dir,"1.0",
[{write_file,"start_clean.rel",
[37,37,32,114,101,108,32,103,101,110,101,114,97,116|...]},
@@ -410,17 +410,17 @@ Eshell V9.0 (abort with ^G)
{create_dir,"bin",
[{copy_file,"display_args.escript",
"/usr/local/lib/erlang/lib/reltool-0.7.3/examples/display_args"},
- {copy_file,"display_args","erts-9.0/bin/escript"},
- {copy_file,"start","erts-9.0/bin/start"},
- {copy_file,"ct_run","erts-9.0/bin/ct_run"},
- {copy_file,"dialyzer","erts-9.0/bin/dialyzer"},
- {copy_file,"run_erl","erts-9.0/bin/run_erl"},
- {copy_file,"erl","erts-9.0/bin/dyn_erl"},
- {copy_file,"to_erl","erts-9.0/bin/to_erl"},
- {copy_file,"epmd","erts-9.0/bin/epmd"},
- {copy_file,"erlc","erts-9.0/bin/erlc"},
- {copy_file,"typer","erts-9.0/bin/typer"},
- {copy_file,"escript","erts-9.0/bin/escript"},
+ {copy_file,"display_args","erts-10.0/bin/escript"},
+ {copy_file,"start","erts-10.0/bin/start"},
+ {copy_file,"ct_run","erts-10.0/bin/ct_run"},
+ {copy_file,"dialyzer","erts-10.0/bin/dialyzer"},
+ {copy_file,"run_erl","erts-10.0/bin/run_erl"},
+ {copy_file,"erl","erts-10.0/bin/dyn_erl"},
+ {copy_file,"to_erl","erts-10.0/bin/to_erl"},
+ {copy_file,"epmd","erts-10.0/bin/epmd"},
+ {copy_file,"erlc","erts-10.0/bin/erlc"},
+ {copy_file,"typer","erts-10.0/bin/typer"},
+ {copy_file,"escript","erts-10.0/bin/escript"},
{write_file,"start_clean.boot",&lt;&lt;131,104,3,119,6,115,...&gt;&gt;},
{write_file,"start_sasl.boot",&lt;&lt;131,104,3,119,6,...&gt;&gt;},
{write_file,"start.boot",&lt;&lt;131,104,3,119,...&gt;&gt;}]},
@@ -451,7 +451,7 @@ Eshell V9.0 (abort with ^G)
{copy_file,[...]},
{copy_file,...},
{...}]}]},
- {create_dir,"erts-9.0",
+ {create_dir,"erts-10.0",
[{create_dir,"bin",
[{copy_file,"start"},
{copy_file,"ct_run"},
@@ -459,7 +459,7 @@ Eshell V9.0 (abort with ^G)
{copy_file,"dialyzer"},
{copy_file,"beam.smp"},
{copy_file,"run_erl"},
- {copy_file,"erl","erts-9.0/bin/dyn_erl"},
+ {copy_file,"erl","erts-10.0/bin/dyn_erl"},
{copy_file,"to_erl"},
{copy_file,"epmd"},
{copy_file,"erl_child_setup"},
@@ -511,8 +511,8 @@ Eshell V9.0 (abort with ^G)
[{create_dir,"priv",
[{create_dir,"lib",[{copy_file,[...]},{copy_file,...}]},
{create_dir,"obj",[{copy_file,...},{...}|...]}]}]},
- {archive,"erts-9.0.ez",[],
- [{create_dir,"erts-9.0",
+ {archive,"erts-10.0.ez",[],
+ [{create_dir,"erts-10.0",
[{create_dir,"src",[{...}|...]},
{create_dir,"ebin",[...]}]}]},
{archive,"hipe-3.15.4.ez",[],
@@ -549,14 +549,14 @@ ok
ok
7&gt;
7&gt; file:list_dir(TargetDir).
-{ok,["bin","Install","lib","misc","usr","erts-9.0",
+{ok,["bin","Install","lib","misc","usr","erts-10.0",
"releases"]}
8&gt;
8&gt; file:list_dir(filename:join([TargetDir,"lib"])).
{ok,["tools-2.9.1.ez","kernel-5.2.ez","inets-6.3.9.ez",
"kernel-5.2","sasl-3.0.3.ez","hipe-3.15.4.ez","inets-6.3.9",
"crypto-3.7.4","crypto-3.7.4.ez","stdlib-3.3.ez",
- "erts-9.0.ez","stdlib-3.3","compiler-7.0.4.ez"]}
+ "erts-10.0.ez","stdlib-3.3","compiler-7.0.4.ez"]}
9&gt;
9&gt; file:make_dir("/tmp/yet_another_target_dir").
ok
@@ -565,7 +565,7 @@ ok
ok
11&gt;
11&gt; file:list_dir("/tmp/yet_another_target_dir").
-{ok,["bin","Install","lib","misc","usr","erts-9.0",
+{ok,["bin","Install","lib","misc","usr","erts-10.0",
"releases"]}
</pre>
diff --git a/lib/reltool/src/reltool.app.src b/lib/reltool/src/reltool.app.src
index 90f93d2901..dc85464750 100644
--- a/lib/reltool/src/reltool.app.src
+++ b/lib/reltool/src/reltool.app.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,6 +36,6 @@
{registered, []},
{applications, [stdlib, kernel]},
{env, []},
- {runtime_dependencies, ["wx-1.2","tools-2.6.14","stdlib-2.0","sasl-2.4",
+ {runtime_dependencies, ["wx-1.2","tools-2.6.14","stdlib-3.4","sasl-2.4",
"kernel-3.0","erts-7.0"]}
]}.
diff --git a/lib/reltool/src/reltool.erl b/lib/reltool/src/reltool.erl
index f6ce5578bc..2e1dbfd713 100644
--- a/lib/reltool/src/reltool.erl
+++ b/lib/reltool/src/reltool.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -80,7 +80,7 @@ get_server(WinPid) ->
{ok, _ServerPid} = OK ->
OK;
{error, Reason} ->
- {error, lists:flatten(io_lib:format("~p", [Reason]))}
+ {error, lists:flatten(io_lib:format("~tp", [Reason]))}
end.
%% Stop a server or window process
@@ -93,7 +93,7 @@ stop(Pid) when is_pid(Pid) ->
{'DOWN', Ref, _, _, shutdown} ->
ok;
{'DOWN', Ref, _, _, Reason} ->
- {error, lists:flatten(io_lib:format("~p", [Reason]))}
+ {error, lists:flatten(io_lib:format("~tp", [Reason]))}
end.
%% Internal library function
diff --git a/lib/reltool/src/reltool.hrl b/lib/reltool/src/reltool.hrl
index 8b4898570b..d133762818 100644
--- a/lib/reltool/src/reltool.hrl
+++ b/lib/reltool/src/reltool.hrl
@@ -119,7 +119,7 @@
| {archive, base_file(), [archive_opt()], [target_spec()]}
| {copy_file, base_file()}
| {copy_file, base_file(), top_file()}
- | {write_file, base_file(), iolist()}
+ | {write_file, base_file(), binary()}
| {strip_beam_file, base_file()}.
-type target_dir() :: dir().
-type incl_defaults() :: boolean().
@@ -220,7 +220,8 @@
{
name :: rel_name(),
vsn :: rel_vsn(),
- rel_apps :: [#rel_app{}]
+ rel_apps :: [#rel_app{}],
+ load_dot_erlang = true :: boolean()
}).
-record(sys,
@@ -300,6 +301,7 @@
-define(STANDALONE_INCL_SYS_FILTERS, ["^bin/(erl|epmd)(|\\.exe|\\.ini)\$",
"^bin/start(|_clean).boot\$",
+ "^bin/no_dot_erlang\\.boot\$",
"^erts.*/bin",
"^lib\$"]).
-define(STANDALONE_EXCL_SYS_FILTERS,
diff --git a/lib/reltool/src/reltool_app_win.erl b/lib/reltool/src/reltool_app_win.erl
index 468ba297bb..c84c1562ee 100644
--- a/lib/reltool/src/reltool_app_win.erl
+++ b/lib/reltool/src/reltool_app_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -102,8 +102,8 @@ init(Parent, WxEnv, Xref, C, AppName) ->
try
do_init(Parent, WxEnv, Xref, C, AppName)
catch
- error:Reason ->
- exit({Reason, erlang:get_stacktrace()})
+ error:Reason:Stacktrace ->
+ exit({Reason, Stacktrace})
end.
do_init(Parent, WxEnv, Xref, C, AppName) ->
@@ -174,7 +174,7 @@ loop(#state{xref_pid = Xref, common = C, app = App} = S) ->
S#state.mod_wins)},
?MODULE:loop(S2);
Msg ->
- error_logger:format("~w~w got unexpected message:\n\t~p\n",
+ error_logger:format("~w~w got unexpected message:\n\t~tp\n",
[?MODULE, self(), Msg]),
?MODULE:loop(S)
end.
@@ -182,7 +182,7 @@ loop(#state{xref_pid = Xref, common = C, app = App} = S) ->
exit_warning({'EXIT', _Pid, shutdown}) ->
ok;
exit_warning({'EXIT', _Pid, _Reason} = Msg) ->
- error_logger:format("~w~w got unexpected message:\n\t~p\n",
+ error_logger:format("~w~w got unexpected message:\n\t~tp\n",
[?MODULE, self(), Msg]).
create_window(#state{app = App} = S) ->
@@ -629,7 +629,7 @@ handle_event(#state{sys = Sys, app = App} = S, Wx) ->
handle_mod_button(S, Items, Action);
_ ->
error_logger:format("~w~w got unexpected app event from "
- "wx:\n\t~p\n",
+ "wx:\n\t~tp\n",
[?MODULE, self(), Wx]),
S
end.
@@ -676,7 +676,7 @@ move_mod(App, {_ItemNo, ModStr}, Action) ->
undefined;
_ ->
error_logger:format("~w~w got unexpected mod "
- "button event: ~w\n\t ~p\n",
+ "button event: ~w\n\t ~tp\n",
[?MODULE, self(), ModName, Action]),
M#mod.incl_cond
end,
diff --git a/lib/reltool/src/reltool_fgraph_win.erl b/lib/reltool/src/reltool_fgraph_win.erl
index 915330794c..0875d5dd7d 100644
--- a/lib/reltool/src/reltool_fgraph_win.erl
+++ b/lib/reltool/src/reltool_fgraph_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -526,7 +526,7 @@ loop(S, G) ->
exit(Reason);
Other ->
- error_logger:format("~w~w got unexpected message:\n\t~p\n",
+ error_logger:format("~w~w got unexpected message:\n\t~tp\n",
[?MODULE, self(), Other]),
loop(S, G)
end.
diff --git a/lib/reltool/src/reltool_mod_win.erl b/lib/reltool/src/reltool_mod_win.erl
index 8cd63bdda1..7df62b71be 100644
--- a/lib/reltool/src/reltool_mod_win.erl
+++ b/lib/reltool/src/reltool_mod_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -107,8 +107,8 @@ init(Parent, WxEnv, Xref, RelPid, C, ModName) ->
try
do_init(Parent, WxEnv, Xref, RelPid, C, ModName)
catch
- error:Reason ->
- exit({Reason, erlang:get_stacktrace()})
+ error:Reason:Stacktrace ->
+ exit({Reason, Stacktrace})
end.
do_init(Parent, WxEnv, Xref, RelPid, C, ModName) ->
@@ -171,7 +171,7 @@ loop(#state{xref_pid = Xref, common = C, mod = Mod} = S) ->
S2 = handle_event(S, Wx),
?MODULE:loop(S2);
_ ->
- error_logger:format("~w~w got unexpected message:\n\t~p\n",
+ error_logger:format("~w~w got unexpected message:\n\t~tp\n",
[?MODULE, self(), Msg]),
?MODULE:loop(S)
end
@@ -487,7 +487,7 @@ handle_event(#state{xref_pid = Xref} = S, Wx) ->
S;
_ ->
error_logger:format("~w~w got unexpected mod event from "
- "wx:\n\t~p\n",
+ "wx:\n\t~tp\n",
[?MODULE, self(), Wx]),
S
end.
@@ -667,7 +667,7 @@ goto_function(S, Editor) ->
wxStyledTextCtrl:setSelection(Editor, Left2, Right2),
Text = wxStyledTextCtrl:getSelectedText(Editor),
S2 = add_pos_to_history(S, CurrentPos),
- do_goto_function(S2, string:tokens(Text, ":"));
+ do_goto_function(S2, string:lexemes(Text, ":"));
_ ->
%% No function call
wxStyledTextCtrl:hideSelection(Editor, false),
@@ -833,7 +833,7 @@ load_code(Ed, Code) when is_binary(Code) ->
keyWords() ->
L = ["after","begin","case","try","cond","catch","andalso","orelse",
- "end","fun","if","let","of","query","receive","when","bnot","not",
+ "end","fun","if","let","of","receive","when","bnot","not",
"div","rem","band","and","bor","bxor","bsl","bsr","or","xor"],
lists:flatten([K ++ " " || K <- L] ++ [0]).
diff --git a/lib/reltool/src/reltool_server.erl b/lib/reltool/src/reltool_server.erl
index 89e90670cf..af71b0cf2a 100644
--- a/lib/reltool/src/reltool_server.erl
+++ b/lib/reltool/src/reltool_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -135,8 +135,8 @@ init([{parent,Parent}|_] = Options) ->
catch
throw:{error,Reason} ->
proc_lib:init_ack(Parent,{error,Reason});
- error:Reason ->
- exit({Reason, erlang:get_stacktrace()})
+ error:Reason:Stacktrace ->
+ exit({Reason, Stacktrace})
end.
do_init(Options) ->
@@ -225,12 +225,12 @@ parse_options([{Key, Val} | KeyVals], S, C, Sys) ->
Sys2 = read_config(Sys, {sys, Val}),
parse_options(KeyVals, S, C, Sys2);
_ ->
- reltool_utils:throw_error("Illegal option: ~p", [{Key, Val}])
+ reltool_utils:throw_error("Illegal option: ~tp", [{Key, Val}])
end;
parse_options([], S, C, Sys) ->
S#state{common = C, sys = Sys};
parse_options(KeyVals, _S, _C, _Sys) ->
- reltool_utils:throw_error("Illegal option: ~p", [KeyVals]).
+ reltool_utils:throw_error("Illegal option: ~tp", [KeyVals]).
loop(#state{sys = Sys} = S) ->
receive
@@ -400,12 +400,12 @@ loop(#state{sys = Sys} = S) ->
{'EXIT', Pid, Reason} when Pid =:= S#state.parent_pid ->
exit(Reason);
{call, ReplyTo, Ref, Msg} when is_pid(ReplyTo), is_reference(Ref) ->
- error_logger:format("~w~w got unexpected call:\n\t~p\n",
+ error_logger:format("~w~w got unexpected call:\n\t~tp\n",
[?MODULE, self(), Msg]),
reltool_utils:reply(ReplyTo, Ref, {error, {invalid_call, Msg}}),
?MODULE:loop(S);
Msg ->
- error_logger:format("~w~w got unexpected message:\n\t~p\n",
+ error_logger:format("~w~w got unexpected message:\n\t~tp\n",
[?MODULE, self(), Msg]),
?MODULE:loop(S)
end.
@@ -1232,7 +1232,7 @@ parse_app_info(File, [{Key, Val} | KeyVals], AI, Status) ->
Status);
_ ->
Status2 =
- reltool_utils:add_warning("Unexpected item ~p in app file ~tp.",
+ reltool_utils:add_warning("Unexpected item ~tp in app file ~tp.",
[Key,File],
Status),
parse_app_info(File, KeyVals, AI, Status2)
@@ -1417,9 +1417,12 @@ shrink_app(A) ->
do_save_config(S, Filename, InclDef, InclDeriv) ->
{ok, Config} = do_get_config(S, InclDef, InclDeriv),
- IoList = io_lib:format("%% config generated at ~w ~w\n~p.\n\n",
- [date(), time(), Config]),
- file:write_file(Filename, IoList).
+ IoList = io_lib:format("%% ~s\n"
+ "%% config generated at ~w ~w\n"
+ "~tp.\n\n",
+ [epp:encoding_to_string(utf8),date(), time(), Config]),
+ Bin = unicode:characters_to_binary(IoList),
+ file:write_file(Filename, Bin).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1455,7 +1458,7 @@ read_config(OldSys, {sys, KeyVals}) ->
[NewSys2#sys.boot_rel])
end;
read_config(_OldSys, BadConfig) ->
- reltool_utils:throw_error("Illegal content: ~p", [BadConfig]).
+ reltool_utils:throw_error("Illegal content: ~tp", [BadConfig]).
decode(#sys{apps = Apps} = Sys, [{erts = Name, AppKeyVals} | SysKeyVals])
when is_atom(Name), is_list(AppKeyVals) ->
@@ -1565,7 +1568,7 @@ decode(#sys{} = Sys, [{Key, Val} | KeyVals]) ->
debug_info when Val =:= keep; Val =:= strip ->
Sys#sys{debug_info = Val};
_ ->
- reltool_utils:throw_error("Illegal option: ~p", [{Key, Val}])
+ reltool_utils:throw_error("Illegal option: ~tp", [{Key, Val}])
end,
decode(Sys3, KeyVals);
decode(#app{} = App, [{Key, Val} | KeyVals]) ->
@@ -1620,14 +1623,14 @@ decode(#app{} = App, [{Key, Val} | KeyVals]) ->
active_dir = Dir,
sorted_dirs = [Dir]};
false ->
- reltool_utils:throw_error("Illegal lib dir for ~w: ~p",
+ reltool_utils:throw_error("Illegal lib dir for ~w: ~tp",
[App#app.name, Val])
end;
SelectVsn when SelectVsn=:=vsn; SelectVsn=:=lib_dir ->
reltool_utils:throw_error("Mutual exclusive options "
"'vsn' and 'lib_dir'",[]);
_ ->
- reltool_utils:throw_error("Illegal option: ~p", [{Key, Val}])
+ reltool_utils:throw_error("Illegal option: ~tp", [{Key, Val}])
end,
decode(App2, KeyVals);
decode(#app{mods = Mods} = App, [{mod, Name, ModKeyVals} | AppKeyVals]) ->
@@ -1641,7 +1644,7 @@ decode(#mod{} = Mod, [{Key, Val} | KeyVals]) ->
debug_info when Val =:= keep; Val =:= strip ->
Mod#mod{debug_info = Val};
_ ->
- reltool_utils:throw_error("Illegal option: ~p", [{Key, Val}])
+ reltool_utils:throw_error("Illegal option: ~tp", [{Key, Val}])
end,
decode(Mod2, KeyVals);
decode(#rel{rel_apps = RelApps} = Rel, [RelApp | KeyVals]) ->
@@ -1666,12 +1669,12 @@ decode(#rel{rel_apps = RelApps} = Rel, [RelApp | KeyVals]) ->
true ->
decode(Rel#rel{rel_apps = RelApps ++ [RA]}, KeyVals);
false ->
- reltool_utils:throw_error("Illegal option: ~p", [RelApp])
+ reltool_utils:throw_error("Illegal option: ~tp", [RelApp])
end;
decode(Acc, []) ->
Acc;
decode(_Acc, KeyVal) ->
- reltool_utils:throw_error("Illegal option: ~p", [KeyVal]).
+ reltool_utils:throw_error("Illegal option: ~tp", [KeyVal]).
is_type(Type) ->
case Type of
@@ -1866,7 +1869,7 @@ escripts_to_apps([Escript | Escripts], Apps, Status) ->
{ok, AF} ->
AF;
{error, Reason1} ->
- reltool_utils:throw_error("Illegal escript ~tp: ~p",
+ reltool_utils:throw_error("Illegal escript ~tp: ~tp",
[Escript,Reason1])
end,
@@ -1950,7 +1953,7 @@ escripts_to_apps([Escript | Escripts], Apps, Status) ->
Status2),
escripts_to_apps(Escripts, Apps2, Status3);
{error, Reason2} ->
- reltool_utils:throw_error("Illegal escript ~tp: ~p",
+ reltool_utils:throw_error("Illegal escript ~tp: ~tp",
[Escript,Reason2])
end;
escripts_to_apps([], Apps, Status) ->
@@ -2013,7 +2016,7 @@ init_escript_app(AppName, EscriptAppName, Dir, Info, Mods, Apps, Status) ->
case lists:keymember(AppName, #app.name, Apps) of
true ->
reltool_utils:throw_error(
- "~w: Application name clash. Escript ~tp contains application ~tp.",
+ "~w: Application name clash. Escript ~tp contains application ~w.",
[AppName,Dir,AppName]);
false ->
{App2, Status}
diff --git a/lib/reltool/src/reltool_sys_win.erl b/lib/reltool/src/reltool_sys_win.erl
index ba0d90ef5f..e24f468f67 100644
--- a/lib/reltool/src/reltool_sys_win.erl
+++ b/lib/reltool/src/reltool_sys_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -135,9 +135,9 @@ init(Options) ->
try
do_init(Options)
catch
- error:Reason ->
- io:format("~p: ~p~n",[Reason, erlang:get_stacktrace()]),
- exit({Reason, erlang:get_stacktrace()})
+ error:Reason:Stacktrace ->
+ io:format("~tp: ~tp~n",[Reason, Stacktrace]),
+ exit({Reason, Stacktrace})
end.
do_init([{safe_config, Safe}, {parent, Parent} | Options]) ->
@@ -182,7 +182,7 @@ do_init([{safe_config, Safe}, {parent, Parent} | Options]) ->
end.
restart_server_safe_config(true,Parent,Reason) ->
- io:format("~w(~w): <ERROR> ~p\n", [?MODULE, ?LINE, Reason]),
+ io:format("~w(~w): <ERROR> ~tp\n", [?MODULE, ?LINE, Reason]),
proc_lib:init_ack(Parent, {error,Reason});
restart_server_safe_config(false,Parent,Reason) ->
wx:new(),
@@ -199,7 +199,7 @@ restart_server_safe_config(false,Parent,Reason) ->
?wxID_OK ->
do_init([{safe_config,true},{parent,Parent},?safe_config]);
?wxID_CANCEL ->
- io:format("~w(~w): <ERROR> ~p\n", [?MODULE, ?LINE, Reason]),
+ io:format("~w(~w): <ERROR> ~tp\n", [?MODULE, ?LINE, Reason]),
proc_lib:init_ack(Parent,{error,Reason})
end.
@@ -251,7 +251,7 @@ loop(S) ->
?MODULE:loop(S#state{warning_wins = WWs2});
false ->
error_logger:format("~w~w got unexpected "
- "message:\n\t~p\n",
+ "message:\n\t~tp\n",
[?MODULE, self(), Msg]),
?MODULE:loop(S)
end
@@ -292,7 +292,7 @@ loop(S) ->
S#state.app_wins),
?MODULE:loop(S#state{fgraph_wins = FWs, app_wins = AWs});
Msg ->
- error_logger:format("~w~w got unexpected message:\n\t~p\n",
+ error_logger:format("~w~w got unexpected message:\n\t~tp\n",
[?MODULE, self(), Msg]),
?MODULE:loop(S)
end.
@@ -316,7 +316,7 @@ handle_child_exit({'EXIT', Pid, _Reason} = Exit, FWs, AWs) ->
msg_warning({'EXIT', _Pid, shutdown}, Type) when Type =/= unknown ->
ok;
msg_warning(Exit, Type) ->
- error_logger:format("~w~w got unexpected message (~w):\n\t~p\n",
+ error_logger:format("~w~w got unexpected message (~w):\n\t~tp\n",
[?MODULE, self(), Type, Exit]).
create_window(S) ->
@@ -1163,12 +1163,12 @@ handle_system_event(#state{sys = Sys} = S,
do_set_sys(S#state{sys = Sys2});
handle_system_event(S, Event, ObjRef, UserData) ->
error_logger:format("~w~w got unexpected wx sys event to ~p "
- "with user data: ~p\n\t ~p\n",
+ "with user data: ~tp\n\t ~tp\n",
[?MODULE, self(), ObjRef, UserData, Event]),
S.
handle_release_event(S, _Event, _ObjRef, UserData) ->
- io:format("Release data: ~p\n", [UserData]),
+ io:format("Release data: ~tp\n", [UserData]),
S.
handle_source_event(S,
@@ -1225,7 +1225,7 @@ handle_app_event(S,
handle_app_button(S, Items, Action);
handle_app_event(S, Event, ObjRef, UserData) ->
error_logger:format("~w~w got unexpected wx app event to "
- "~p with user data: ~p\n\t ~p\n",
+ "~p with user data: ~tp\n\t ~tp\n",
[?MODULE, self(), ObjRef, UserData, Event]),
S.
@@ -1269,7 +1269,7 @@ move_app(S, {_ItemNo, AppBase}, Action) ->
undefined;
_ ->
error_logger:format("~w~w got unexpected app "
- "button event: ~p ~p\n",
+ "button event: ~tp ~tp\n",
[?MODULE, self(), Action, AppBase]),
OldApp#app.incl_cond
end,
@@ -1543,7 +1543,7 @@ check_and_refresh(S, Status) ->
display_message(Reason, ?wxICON_ERROR),
false;
{error, Reason} ->
- Msg = lists:flatten(io_lib:format("Error:\n\n~p\n", [Reason])),
+ Msg = lists:flatten(io_lib:format("Error:\n\n~tp\n", [Reason])),
display_message(Msg, ?wxICON_ERROR),
false
end,
diff --git a/lib/reltool/src/reltool_target.erl b/lib/reltool/src/reltool_target.erl
index 1615a3e9b7..64834ecc1d 100644
--- a/lib/reltool/src/reltool_target.erl
+++ b/lib/reltool/src/reltool_target.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -55,7 +55,7 @@ mandatory_modules() ->
kernel_processes(KernelApp) ->
[
{kernelProcess, heart, {heart, start, []}},
- {kernelProcess, error_logger , {error_logger, start_link, []}},
+ {kernelProcess, logger , {logger_server, start_link, []}},
{kernelProcess,
application_controller,
{application_controller, start, [KernelApp]}}
@@ -424,7 +424,7 @@ gen_script(Rel, Sys, PathFlag, Variables) ->
{error, Text}
end.
-do_gen_script(#rel{name = RelName, vsn = RelVsn},
+do_gen_script(#rel{name = RelName, vsn = RelVsn, load_dot_erlang=LoadErlangRc},
#sys{apps = Apps},
MergedApps,
PathFlag,
@@ -474,9 +474,11 @@ do_gen_script(#rel{name = RelName, vsn = RelVsn},
Type =/= none,
Type =/= load,
not lists:member(Name, InclApps)],
-
%% Apply user specific customizations
- {apply, {c, erlangrc, []}},
+ case LoadErlangRc of
+ true -> {apply, {c, erlangrc, []}};
+ false -> []
+ end,
{progress, started}
],
{ok, {script, {RelName, RelVsn}, lists:flatten(DeepList)}}.
@@ -787,16 +789,20 @@ do_spec_rel_files(#rel{name = RelName} = Rel, Sys) ->
{ok, BootBin} = gen_boot(Script),
Date = date(),
Time = time(),
- RelIoList = io_lib:format("%% rel generated at ~w ~w\n~p.\n\n",
+ RelIoList = io_lib:format("%% rel generated at ~w ~w\n~tp.\n\n",
[Date, Time, GenRel]),
- ScriptIoList = io_lib:format("%% script generated at ~w ~w\n~p.\n\n",
+ ScriptIoList = io_lib:format("%% script generated at ~w ~w\n~tp.\n\n",
[Date, Time, Script]),
[
- {write_file, RelFile, RelIoList},
- {write_file, ScriptFile, ScriptIoList},
+ {write_file, RelFile, to_utf8_bin_with_enc_comment(RelIoList)},
+ {write_file, ScriptFile, to_utf8_bin_with_enc_comment(ScriptIoList)},
{write_file, BootFile, BootBin}
].
+to_utf8_bin_with_enc_comment(IoList) when is_list(IoList) ->
+ unicode:characters_to_binary("%% " ++ epp:encoding_to_string(utf8) ++ "\n"
+ ++ IoList).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Generate a complete target system
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1001,7 +1007,8 @@ spec_start_file(#sys{boot_rel = BootRelName,
{value, Erts} = lists:keysearch(erts, #app.name, Apps),
{value, BootRel} = lists:keysearch(BootRelName, #rel.name, Rels),
Data = Erts#app.vsn ++ " " ++ BootRel#rel.vsn ++ "\n",
- {BootRel#rel.vsn, {write_file, "start_erl.data", Data}}.
+ {BootRel#rel.vsn, {write_file, "start_erl.data",
+ unicode:characters_to_binary(Data)}}.
lookup_spec(Prefix, Specs) ->
lists:filter(fun(S) -> lists:prefix(Prefix, element(2, S)) end, Specs).
@@ -1183,18 +1190,18 @@ spec_app_file(#app{name = Name,
Info#app_info.modules)],
App2 = App#app{info = Info#app_info{modules = ModNames}},
Contents = gen_app(App2),
- AppIoList = io_lib:format("%% app generated at ~w ~w\n~p.\n\n",
+ AppIoList = io_lib:format("%% app generated at ~w ~w\n~tp.\n\n",
[date(), time(), Contents]),
- [{write_file, AppFilename, AppIoList}];
+ [{write_file, AppFilename, to_utf8_bin_with_enc_comment(AppIoList)}];
all ->
%% Include all included modules
%% Generate new file
ModNames = [M#mod.name || M <- Mods, M#mod.is_included],
App2 = App#app{info = Info#app_info{modules = ModNames}},
Contents = gen_app(App2),
- AppIoList = io_lib:format("%% app generated at ~w ~w\n~p.\n\n",
+ AppIoList = io_lib:format("%% app generated at ~w ~w\n~tp.\n\n",
[date(), time(), Contents]),
- [{write_file, AppFilename, AppIoList}]
+ [{write_file, AppFilename, to_utf8_bin_with_enc_comment(AppIoList)}]
end.
@@ -1285,7 +1292,7 @@ do_eval_spec({archive, Archive, Options, Files},
{ok, _} ->
ok;
{error, Reason} ->
- reltool_utils:throw_error("create archive ~ts failed: ~p",
+ reltool_utils:throw_error("create archive ~ts failed: ~tp",
[ArchiveFile, Reason])
end;
do_eval_spec({copy_file, File}, _OrigSourceDir, SourceDir, TargetDir) ->
@@ -1299,12 +1306,12 @@ do_eval_spec({copy_file, File, OldFile},
SourceFile = filename:join([OrigSourceDir, OldFile]),
TargetFile = filename:join([TargetDir, File]),
reltool_utils:copy_file(SourceFile, TargetFile);
-do_eval_spec({write_file, File, IoList},
+do_eval_spec({write_file, File, Bin},
_OrigSourceDir,
_SourceDir,
TargetDir) ->
TargetFile = filename:join([TargetDir, File]),
- reltool_utils:write_file(TargetFile, IoList);
+ reltool_utils:write_file(TargetFile, Bin);
do_eval_spec({strip_beam, File}, _OrigSourceDir, SourceDir, TargetDir) ->
SourceFile = filename:join([SourceDir, File]),
TargetFile = filename:join([TargetDir, File]),
@@ -1336,7 +1343,7 @@ cleanup_spec({copy_file, File}, TargetDir) ->
cleanup_spec({copy_file, NewFile, _OldFile}, TargetDir) ->
TargetFile = filename:join([TargetDir, NewFile]),
file:delete(TargetFile);
-cleanup_spec({write_file, File, _IoList}, TargetDir) ->
+cleanup_spec({write_file, File, _}, TargetDir) ->
TargetFile = filename:join([TargetDir, File]),
file:delete(TargetFile);
cleanup_spec({strip_beam, File}, TargetDir) ->
@@ -1406,7 +1413,7 @@ do_filter_spec(Path,
ExclRegexps) ->
Path2 = opt_join(Path, NewFile),
match(Path2, InclRegexps, ExclRegexps);
-do_filter_spec(Path, {write_file, File, _IoList}, InclRegexps, ExclRegexps) ->
+do_filter_spec(Path, {write_file, File, _}, InclRegexps, ExclRegexps) ->
Path2 = opt_join(Path, File),
match(Path2, InclRegexps, ExclRegexps);
do_filter_spec(Path, {strip_beam, File}, InclRegexps, ExclRegexps) ->
@@ -1448,7 +1455,7 @@ do_install(RelName, TargetDir) ->
RelDir = filename:join([TargetDir2, "releases"]),
DataFile = filename:join([RelDir, "start_erl.data"]),
Bin = reltool_utils:read_file(DataFile),
- case string:tokens(binary_to_list(Bin), " \n") of
+ case string:lexemes(unicode:characters_to_list(Bin), " \n") of
[ErlVsn, RelVsn | _] ->
ErtsBinDir = filename:join([TargetDir2, "erts-" ++ ErlVsn, "bin"]),
BinDir = filename:join([TargetDir2, "bin"]),
@@ -1501,8 +1508,8 @@ subst_src_script(Script, SrcDir, DestDir, Vars, Opts) ->
subst_file(Src, Dest, Vars, Opts) ->
Bin = reltool_utils:read_file(Src),
- Chars = subst(binary_to_list(Bin), Vars),
- reltool_utils:write_file(Dest, Chars),
+ Chars = subst(unicode:characters_to_list(Bin), Vars),
+ reltool_utils:write_file(Dest, unicode:characters_to_binary(Chars)),
case lists:member(preserve, Opts) of
true ->
FileInfo = reltool_utils:read_file_info(Src),
diff --git a/lib/reltool/src/reltool_utils.erl b/lib/reltool/src/reltool_utils.erl
index 60edc9f3ca..060a0912f9 100644
--- a/lib/reltool/src/reltool_utils.erl
+++ b/lib/reltool/src/reltool_utils.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -55,7 +55,7 @@ root_dir() ->
code:root_dir().
erl_libs() ->
- string:tokens(os:getenv("ERL_LIBS", ""), ":;").
+ string:lexemes(os:getenv("ERL_LIBS", ""), ":;").
lib_dirs(Dir) ->
case erl_prim_loader:list_dir(Dir) of
@@ -154,7 +154,12 @@ default_rels() ->
rel_apps = []},
#rel{name = "start_sasl",
vsn = "1.0",
- rel_apps = [#rel_app{name = sasl}]}
+ rel_apps = [#rel_app{name = sasl}]},
+ #rel{name = "no_dot_erlang", %% Needed by escript and erlc
+ vsn = "1.0",
+ rel_apps = [],
+ load_dot_erlang = false
+ }
].
choose_default(Tag, Profile, InclDefs)
@@ -286,7 +291,7 @@ split_app_dir(Dir) ->
{Name, Vsn} = split_app_name(Base),
Vsn2 =
try
- [list_to_integer(N) || N <- string:tokens(Vsn, ".")]
+ [list_to_integer(N) || N <- string:lexemes(Vsn, ".")]
catch
_:_ ->
Vsn
@@ -427,7 +432,7 @@ scroll_size(ObjRef) ->
safe_keysearch(Key, Pos, List, Mod, Line) ->
case lists:keysearch(Key, Pos, List) of
false ->
- io:format("~w(~w): lists:keysearch(~p, ~w, ~p) -> false\n",
+ io:format("~w(~w): lists:keysearch(~tp, ~w, ~tp) -> false\n",
[Mod, Line, Key, Pos, List]),
erlang:error({Mod, Line, lists, keysearch, [Key, Pos, List]});
{value, Val} ->
@@ -498,8 +503,8 @@ read_file(File) ->
throw_error("read file ~ts: ~ts", [File, Text])
end.
-write_file(File, IoList) ->
- case file:write_file(File, IoList) of
+write_file(File, Bin) ->
+ case file:write_file(File, Bin) of
ok ->
ok;
{error, Reason} ->
@@ -601,7 +606,7 @@ do_decode_regexps(Key, [Regexp | Regexps], Acc) ->
Regexps,
[#regexp{source = Regexp, compiled = MP} | Acc]);
_ ->
- Text = lists:flatten(io_lib:format("~p", [{Key, Regexp}])),
+ Text = lists:flatten(io_lib:format("~tp", [{Key, Regexp}])),
throw({error, "Illegal option: " ++ Text})
end;
do_decode_regexps(_Key, [], Acc) ->
diff --git a/lib/reltool/test/reltool_app_SUITE.erl b/lib/reltool/test/reltool_app_SUITE.erl
index 18c74bea6c..bd0ed5edca 100644
--- a/lib/reltool/test/reltool_app_SUITE.erl
+++ b/lib/reltool/test/reltool_app_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@
%%----------------------------------------------------------------------
-module(reltool_app_SUITE).
--compile(export_all).
+-compile([export_all, nowarn_export_all]).
-include("reltool_test_lib.hrl").
-include_lib("common_test/include/ct.hrl").
diff --git a/lib/reltool/test/reltool_manual_gui_SUITE.erl b/lib/reltool/test/reltool_manual_gui_SUITE.erl
index eebe2303fb..3a4b012d2e 100644
--- a/lib/reltool/test/reltool_manual_gui_SUITE.erl
+++ b/lib/reltool/test/reltool_manual_gui_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-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.
@@ -23,7 +23,7 @@
init_per_suite/1, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2]).
--compile(export_all).
+-export([config/1, depgraphs/1]).
-include_lib("common_test/include/ct.hrl").
-include("reltool_test_lib.hrl").
diff --git a/lib/reltool/test/reltool_server_SUITE.erl b/lib/reltool/test/reltool_server_SUITE.erl
index e8dfea94da..4e1937d479 100644
--- a/lib/reltool/test/reltool_server_SUITE.erl
+++ b/lib/reltool/test/reltool_server_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,11 +19,7 @@
-module(reltool_server_SUITE).
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
- init_per_suite/1, end_per_suite/1,
- init_per_testcase/2, end_per_testcase/2]).
-
--compile(export_all).
+-compile([export_all, nowarn_export_all]).
-include_lib("reltool/src/reltool.hrl").
-include("reltool_test_lib.hrl").
@@ -251,6 +247,7 @@ get_config(_Config) ->
{app,stdlib,[{incl_cond,include},{vsn,undefined},
{lib_dir,StdLibDir}]},
{boot_rel,"start_clean"},
+ {rel,"no_dot_erlang","1.0",[]},
{rel,"start_clean","1.0",[]},
{rel,"start_sasl","1.0",[sasl]},
{emu_name,"beam"},
@@ -281,6 +278,7 @@ get_config(_Config) ->
{app,stdlib,[{incl_cond,include},{vsn,StdVsn},
{lib_dir,StdLibDir},{mod,_,[]}|_]},
{boot_rel,"start_clean"},
+ {rel,"no_dot_erlang","1.0",[]},
{rel,"start_clean","1.0",[]},
{rel,"start_sasl","1.0",[sasl]},
{emu_name,"beam"},
@@ -2108,6 +2106,7 @@ save_config(Config) ->
{app,stdlib,[{incl_cond,include},{vsn,undefined},
{lib_dir,undefined}]},
{boot_rel,"start_clean"},
+ {rel,"no_dot_erlang","1.0",[]},
{rel,"start_clean","1.0",[]},
{rel,"start_sasl","1.0",[sasl]},
{emu_name,"beam"},
@@ -2148,6 +2147,7 @@ save_config(Config) ->
{app,stdlib,[{incl_cond,include},{vsn,StdVsn},
{lib_dir,StdLibDir},{mod,_,[]}|_]},
{boot_rel,"start_clean"},
+ {rel,"no_dot_erlang","1.0",[]},
{rel,"start_clean","1.0",[]},
{rel,"start_sasl","1.0",[sasl]},
{emu_name,"beam"},
@@ -2549,7 +2549,7 @@ undefined_regexp(_Config) ->
%% Library functions
erl_libs() ->
- string:tokens(os:getenv("ERL_LIBS", ""), ":;").
+ string:lexemes(os:getenv("ERL_LIBS", ""), ":;").
datadir(Config) ->
%% Removes the trailing slash...
@@ -2559,7 +2559,7 @@ latest(App) ->
AppStr = atom_to_list(App),
AppDirs = filelib:wildcard(filename:join(code:lib_dir(),AppStr++"-*")),
[LatestAppDir|_] = lists:reverse(AppDirs),
- [_,Vsn] = string:tokens(filename:basename(LatestAppDir),"-"),
+ [_,Vsn] = string:lexemes(filename:basename(LatestAppDir),"-"),
Vsn.
rm_missing_app(Apps) ->
@@ -2635,16 +2635,11 @@ os_cmd(Cmd) when is_list(Cmd) ->
Return->
%% Find the position of the status code wich is last in the string
%% prepended with #
- case string:rchr(Return, $#) of
-
- %% This happens only if the sh command pipe is somehow interrupted
- 0->
- {98, Return};
-
- Position->
- Result = string:left(Return,Position - 1),
- Status = string:substr(Return,Position + 1, length(Return) - Position - 1),
- {list_to_integer(Status), Result}
+ case string:split(Return, "$#", trailing) of
+ [_] -> %% This happens only if the sh command pipe is somehow interrupted
+ {98, Return};
+ [Result, Status0] ->
+ {list_to_integer(string:trim(Status0)), Result}
end
end.
diff --git a/lib/reltool/test/reltool_test_lib.erl b/lib/reltool/test/reltool_test_lib.erl
index 6cc2d259fb..be48ea4726 100644
--- a/lib/reltool/test/reltool_test_lib.erl
+++ b/lib/reltool/test/reltool_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
-module(reltool_test_lib).
--compile(export_all).
+-compile([export_all, nowarn_export_all]).
-include("reltool_test_lib.hrl").
-define(timeout, 20). % minutes
diff --git a/lib/reltool/test/reltool_wx_SUITE.erl b/lib/reltool/test/reltool_wx_SUITE.erl
index ac820db21c..f6f7721762 100644
--- a/lib/reltool/test/reltool_wx_SUITE.erl
+++ b/lib/reltool/test/reltool_wx_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
init_per_suite/1, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2]).
--compile(export_all).
+-export([start_all_windows/1, check_no_win_crash/0, wait_terminate/1]).
-include("reltool_test_lib.hrl").
diff --git a/lib/reltool/test/rtt.erl b/lib/reltool/test/rtt.erl
index 173ffc5166..479241d86b 100644
--- a/lib/reltool/test/rtt.erl
+++ b/lib/reltool/test/rtt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
-module(rtt).
--compile(export_all).
+-compile([export_all, nowarn_export_all]).
%% Modules or suites can be shortcuts, for example server expands to reltool_server_SUITE.
%%
diff --git a/lib/reltool/vsn.mk b/lib/reltool/vsn.mk
index 3617f6e0d9..6bfc8c60ea 100644
--- a/lib/reltool/vsn.mk
+++ b/lib/reltool/vsn.mk
@@ -1 +1 @@
-RELTOOL_VSN = 0.7.4
+RELTOOL_VSN = 0.7.7
diff --git a/lib/runtime_tools/doc/src/LTTng.xml b/lib/runtime_tools/doc/src/LTTng.xml
index 392d54857c..89cbc805d8 100644
--- a/lib/runtime_tools/doc/src/LTTng.xml
+++ b/lib/runtime_tools/doc/src/LTTng.xml
@@ -3,7 +3,7 @@
<chapter>
<header>
<copyright>
- <year>2016</year><year>2017</year>
+ <year>2016</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -111,7 +111,7 @@ $ make </code>
<p><em>process_register</em></p>
<list type="bulleted">
<item><c>pid : string</c> :: Process ID. Ex. <c>"&lt;0.131.0&gt;"</c></item>
- <item><c>name : string</c> :: Registered name. Ex. <c>"error_logger"</c></item>
+ <item><c>name : string</c> :: Registered name. Ex. <c>"logger"</c></item>
<item><c>type : string</c> :: <c>"register" | "unregister"</c></item>
</list>
<p>Example:</p>
@@ -134,7 +134,7 @@ $ make </code>
<p><em>port_open</em></p>
<list type="bulleted">
<item><c>pid : string</c> :: Process ID. Ex. <c>"&lt;0.131.0&gt;"</c></item>
- <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item>
+ <item><c>driver : string</c> :: Driver name. Ex. <c>"tcp_inet"</c></item>
<item><c>port : string</c> :: Port ID. Ex. <c>"#Port&lt;0.1031&gt;"</c></item>
</list>
<p>
@@ -323,7 +323,7 @@ $ make </code>
<p><em>driver_init</em></p>
<list type="bulleted">
- <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item>
+ <item><c>driver : string</c> :: Driver name. Ex. <c>"tcp_inet"</c></item>
<item><c>major : integer</c> :: Major version. Ex. <c>3</c></item>
<item><c>minor : integer</c> :: Minor version. Ex. <c>1</c></item>
<item><c>flags : integer</c> :: Flags. Ex. <c>1</c></item>
@@ -334,7 +334,7 @@ $ make </code>
<p><em>driver_start</em></p>
<list type="bulleted">
<item><c>pid : string</c> :: Process ID. Ex. <c>"&lt;0.131.0&gt;"</c></item>
- <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item>
+ <item><c>driver : string</c> :: Driver name. Ex. <c>"tcp_inet"</c></item>
<item><c>port : string</c> :: Port ID. Ex. <c>"#Port&lt;0.1031&gt;"</c></item>
</list>
<p>Example:</p>
@@ -344,7 +344,7 @@ $ make </code>
<list type="bulleted">
<item><c>pid : string</c> :: Process ID. Ex. <c>"&lt;0.131.0&gt;"</c></item>
<item><c>port : string</c> :: Port ID. Ex. <c>"#Port&lt;0.1031&gt;"</c></item>
- <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item>
+ <item><c>driver : string</c> :: Driver name. Ex. <c>"tcp_inet"</c></item>
<item><c>bytes : integer</c> :: Size of data returned. Ex. <c>82</c></item>
</list>
<p>Example:</p>
@@ -354,7 +354,7 @@ $ make </code>
<list type="bulleted">
<item><c>pid : string</c> :: Process ID. Ex. <c>"&lt;0.131.0&gt;"</c></item>
<item><c>port : string</c> :: Port ID. Ex. <c>"#Port&lt;0.1031&gt;"</c></item>
- <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item>
+ <item><c>driver : string</c> :: Driver name. Ex. <c>"tcp_inet"</c></item>
<item><c>bytes : integer</c> :: Size of data returned. Ex. <c>82</c></item>
</list>
<p>Example:</p>
@@ -364,7 +364,7 @@ $ make </code>
<list type="bulleted">
<item><c>pid : string</c> :: Process ID. Ex. <c>"&lt;0.131.0&gt;"</c></item>
<item><c>port : string</c> :: Port ID. Ex. <c>"#Port&lt;0.1031&gt;"</c></item>
- <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item>
+ <item><c>driver : string</c> :: Driver name. Ex. <c>"tcp_inet"</c></item>
</list>
<p>Example:</p>
<code type="none">driver_ready_input: { cpu_id = 5 }, { pid = "&lt;0.189.0&gt;", port = "#Port&lt;0.3637&gt;", driver = "inet_gethost 4 " }</code>
@@ -373,7 +373,7 @@ $ make </code>
<list type="bulleted">
<item><c>pid : string</c> :: Process ID. Ex. <c>"&lt;0.131.0&gt;"</c></item>
<item><c>port : string</c> :: Port ID. Ex. <c>"#Port&lt;0.1031&gt;"</c></item>
- <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item>
+ <item><c>driver : string</c> :: Driver name. Ex. <c>"tcp_inet"</c></item>
</list>
<p>Example:</p>
<code type="none">driver_ready_output: { cpu_id = 5 }, { pid = "&lt;0.194.0&gt;", port = "#Port&lt;0.3663&gt;", driver = "tcp_inet" }</code>
@@ -382,14 +382,14 @@ $ make </code>
<list type="bulleted">
<item><c>pid : string</c> :: Process ID. Ex. <c>"&lt;0.131.0&gt;"</c></item>
<item><c>port : string</c> :: Port ID. Ex. <c>"#Port&lt;0.1031&gt;"</c></item>
- <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item>
+ <item><c>driver : string</c> :: Driver name. Ex. <c>"tcp_inet"</c></item>
</list>
<p>Example:</p>
<code type="none">driver_timeout: { cpu_id = 5 }, { pid = "&lt;0.196.0&gt;", port = "#Port&lt;0.3664&gt;", driver = "tcp_inet" }</code>
<p><em>driver_stop_select</em></p>
<list type="bulleted">
- <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item>
+ <item><c>driver : string</c> :: Driver name. Ex. <c>"tcp_inet"</c></item>
</list>
<p>Example:</p>
<code type="none">driver_stop_select: { cpu_id = 5 }, { driver = "unknown" }</code>
@@ -398,7 +398,7 @@ $ make </code>
<list type="bulleted">
<item><c>pid : string</c> :: Process ID. Ex. <c>"&lt;0.131.0&gt;"</c></item>
<item><c>port : string</c> :: Port ID. Ex. <c>"#Port&lt;0.1031&gt;"</c></item>
- <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item>
+ <item><c>driver : string</c> :: Driver name. Ex. <c>"tcp_inet"</c></item>
</list>
<p>Example:</p>
<code type="none">driver_flush: { cpu_id = 7 }, { pid = "&lt;0.204.0&gt;", port = "#Port&lt;0.3686&gt;", driver = "tcp_inet" }</code>
@@ -407,32 +407,32 @@ $ make </code>
<list type="bulleted">
<item><c>pid : string</c> :: Process ID. Ex. <c>"&lt;0.131.0&gt;"</c></item>
<item><c>port : string</c> :: Port ID. Ex. <c>"#Port&lt;0.1031&gt;"</c></item>
- <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item>
+ <item><c>driver : string</c> :: Driver name. Ex. <c>"tcp_inet"</c></item>
</list>
<p>Example:</p>
- <code type="none">driver_stop: { cpu_id = 5 }, { pid = "[]", port = "#Port&lt;0.3673&gt;", driver = "efile" }</code>
+ <code type="none">driver_stop: { cpu_id = 5 }, { pid = "[]", port = "#Port&lt;0.3673&gt;", driver = "tcp_inet" }</code>
<p><em>driver_process_exit</em></p>
<list type="bulleted">
<item><c>pid : string</c> :: Process ID. Ex. <c>"&lt;0.131.0&gt;"</c></item>
<item><c>port : string</c> :: Port ID. Ex. <c>"#Port&lt;0.1031&gt;"</c></item>
- <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item>
+ <item><c>driver : string</c> :: Driver name. Ex. <c>"tcp_inet"</c></item>
</list>
<p><em>driver_ready_async</em></p>
<list type="bulleted">
<item><c>pid : string</c> :: Process ID. Ex. <c>"&lt;0.131.0&gt;"</c></item>
<item><c>port : string</c> :: Port ID. Ex. <c>"#Port&lt;0.1031&gt;"</c></item>
- <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item>
+ <item><c>driver : string</c> :: Driver name. Ex. <c>"tcp_inet"</c></item>
</list>
<p>Example:</p>
- <code type="none">driver_ready_async: { cpu_id = 3 }, { pid = "&lt;0.181.0&gt;", port = "#Port&lt;0.3622&gt;", driver = "efile" }</code>
+ <code type="none">driver_ready_async: { cpu_id = 3 }, { pid = "&lt;0.181.0&gt;", port = "#Port&lt;0.3622&gt;", driver = "tcp_inet" }</code>
<p><em>driver_call</em></p>
<list type="bulleted">
<item><c>pid : string</c> :: Process ID. Ex. <c>"&lt;0.131.0&gt;"</c></item>
<item><c>port : string</c> :: Port ID. Ex. <c>"#Port&lt;0.1031&gt;"</c></item>
- <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item>
+ <item><c>driver : string</c> :: Driver name. Ex. <c>"tcp_inet"</c></item>
<item><c>command : integer</c> :: Command integer. Ex. <c>1</c></item>
<item><c>bytes : integer</c> :: Size of data returned. Ex. <c>82</c></item>
</list>
@@ -443,7 +443,7 @@ $ make </code>
<list type="bulleted">
<item><c>pid : string</c> :: Process ID. Ex. <c>"&lt;0.131.0&gt;"</c></item>
<item><c>port : string</c> :: Port ID. Ex. <c>"#Port&lt;0.1031&gt;"</c></item>
- <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item>
+ <item><c>driver : string</c> :: Driver name. Ex. <c>"tcp_inet"</c></item>
<item><c>command : integer</c> :: Command integer. Ex. <c>1</c></item>
<item><c>bytes : integer</c> :: Size of data returned. Ex. <c>82</c></item>
</list>
diff --git a/lib/runtime_tools/doc/src/Makefile b/lib/runtime_tools/doc/src/Makefile
index 5ce40bb995..2399ed51e0 100644
--- a/lib/runtime_tools/doc/src/Makefile
+++ b/lib/runtime_tools/doc/src/Makefile
@@ -1,8 +1,8 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 1999-2018. All Rights Reserved.
+#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -14,7 +14,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
+#
# %CopyrightEnd%
#
include $(ERL_TOP)/make/target.mk
@@ -41,11 +41,17 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# Target Specs
# ----------------------------------------------------
XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = dbg.xml dyntrace.xml erts_alloc_config.xml system_information.xml msacc.xml
+XML_REF3_FILES = \
+ dbg.xml \
+ dyntrace.xml \
+ erts_alloc_config.xml \
+ system_information.xml \
+ msacc.xml \
+ scheduler.xml
XML_REF6_FILES = runtime_tools_app.xml
-XML_PART_FILES = part_notes.xml part_notes_history.xml part.xml
-XML_CHAPTER_FILES = notes.xml notes_history.xml LTTng.xml
+XML_PART_FILES = part.xml
+XML_CHAPTER_FILES = notes.xml LTTng.xml
GENERATED_XML_FILES = DTRACE.xml SYSTEMTAP.xml
@@ -56,6 +62,8 @@ XML_FILES = \
$(XML_PART_FILES) $(XML_REF3_FILES) \
$(XML_REF6_FILES) $(XML_APPLICATION_FILES)
+XML_GEN_FILES = $(GENERATED_XML_FILES:%=$(XMLDIR)/%)
+
GIF_FILES =
# ----------------------------------------------------
@@ -77,10 +85,10 @@ SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
TOP_SPECS_FILE = specs.xml
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
+XML_FLAGS +=
+DVIPS_FLAGS +=
SPECS_ESRC = ../../src
@@ -89,9 +97,8 @@ SPECS_FLAGS = -I../../include -I../../../kernel/src
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-$(XML_FILES): $(GENERATED_XML_FILES)
-%.xml: $(ERL_TOP)/HOWTO/%.md $(ERL_TOP)/make/emd2exml
+$(XMLDIR)/%.xml: $(ERL_TOP)/HOWTO/%.md $(ERL_TOP)/make/emd2exml
$(ERL_TOP)/make/emd2exml $< $@
$(HTMLDIR)/%.gif: %.gif
@@ -109,18 +116,19 @@ man: $(MAN3_FILES) $(MAN6_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-debug opt:
+debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
+ rm -f errs core *~
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
@@ -136,4 +144,3 @@ release_docs_spec: docs
$(INSTALL_DATA) $(MAN6_FILES) "$(RELEASE_PATH)/man/man6"
release_spec:
-
diff --git a/lib/runtime_tools/doc/src/dbg.xml b/lib/runtime_tools/doc/src/dbg.xml
index 95f74d4607..3262cafefc 100644
--- a/lib/runtime_tools/doc/src/dbg.xml
+++ b/lib/runtime_tools/doc/src/dbg.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -815,7 +815,7 @@ Error: fun containing local erlang function calls ('is_atomm' called in guard)\
<v>HandlerSpec = {HandlerFun, InitialData}</v>
<v>HandlerFun = fun() (two arguments)</v>
<v>ModuleSpec = fun() (no arguments) | {TracerModule, TracerState}</v>
- <v>ModuleModule = atom()</v>
+ <v>TracerModule = atom()</v>
<v>InitialData = TracerState = term()</v>
</type>
<desc>
diff --git a/lib/runtime_tools/doc/src/fascicules.xml b/lib/runtime_tools/doc/src/fascicules.xml
deleted file mode 100644
index 1a0bd6ec97..0000000000
--- a/lib/runtime_tools/doc/src/fascicules.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="refman" href="refman_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/runtime_tools/doc/src/note.gif b/lib/runtime_tools/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/runtime_tools/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml
index 2bfc174cae..810bb8207c 100644
--- a/lib/runtime_tools/doc/src/notes.xml
+++ b/lib/runtime_tools/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,117 @@
<p>This document describes the changes made to the Runtime_Tools
application.</p>
+<section><title>Runtime_Tools 1.13.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Optimize <c>observer</c> by using new
+ <c>system_info(ets_count)</c> instead of more expensive
+ <c>length(ets:all())</c>.</p>
+ <p>
+ Own Id: OTP-15163 Aux Id: PR-1844 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Runtime_Tools 1.13</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ New utility module <c>scheduler</c> which makes it easier
+ to measure scheduler utilization.</p>
+ <p>
+ Own Id: OTP-14904</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Runtime_Tools 1.12.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p><c>system_information:to_file/1</c> will now use
+ slightly less memory.</p>
+ <p>
+ Own Id: OTP-14816</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Runtime_Tools 1.12.4</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ New family of <c>erts_alloc</c> strategies: Age Order
+ First Fit. Similar to "address order", but instead the
+ oldest possible carrier is always chosen for allocation.</p>
+ <p>
+ Own Id: OTP-14917 Aux Id: ERIERL-88 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Runtime_Tools 1.12.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Runtime_Tools 1.12.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ General Unicode improvements.</p>
+ <p>
+ Own Id: OTP-14462</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Runtime_Tools 1.12.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A faulty encoding comment was added when saving trace
+ patterns to file. This is now corrected.</p>
+ <p>
+ Own Id: OTP-14479</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Runtime_Tools 1.12</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/runtime_tools/doc/src/part_notes.xml b/lib/runtime_tools/doc/src/part_notes.xml
deleted file mode 100644
index cabf3e39da..0000000000
--- a/lib/runtime_tools/doc/src/part_notes.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Runtime_Tools Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p><em>Runtime_Tools</em> provides low footprint tracing/debugging
- tools suitable for inclusion in a production system.</p>
- <p>For information about older versions, see
- <url href="part_notes_history_frame.html">Release Notes History</url>.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/runtime_tools/doc/src/part_notes_history.xml b/lib/runtime_tools/doc/src/part_notes_history.xml
deleted file mode 100644
index dd1991f23a..0000000000
--- a/lib/runtime_tools/doc/src/part_notes_history.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2006</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Runtime_Tools Release Notes History</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p><em>Runtime_Tools</em> provides low footprint tracing/debugging
- tools suitable for inclusion in a production system.</p>
- </description>
- <include file="notes_history"></include>
-</part>
-
diff --git a/lib/runtime_tools/doc/src/ref_man.xml b/lib/runtime_tools/doc/src/ref_man.xml
index d2fb7a29af..fdca65422d 100644
--- a/lib/runtime_tools/doc/src/ref_man.xml
+++ b/lib/runtime_tools/doc/src/ref_man.xml
@@ -4,7 +4,7 @@
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>1999</year><year>2016</year>
+ <year>1999</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -37,6 +37,7 @@
<xi:include href="dyntrace.xml"/>
<xi:include href="erts_alloc_config.xml"/>
<xi:include href="msacc.xml"/>
+ <xi:include href="scheduler.xml"/>
<xi:include href="system_information.xml"/>
</application>
diff --git a/lib/runtime_tools/doc/src/scheduler.xml b/lib/runtime_tools/doc/src/scheduler.xml
new file mode 100644
index 0000000000..dd8bf73bae
--- /dev/null
+++ b/lib/runtime_tools/doc/src/scheduler.xml
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title></title>
+ <prepared></prepared>
+ <responsible></responsible>
+ <docno>1</docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev></rev>
+ <file>scheduler.xml</file>
+ </header>
+ <module>scheduler</module>
+ <modulesummary>Measure scheduler utilization</modulesummary>
+ <description>
+ <p>This module contains utility functions for easier measurement and
+ calculation of scheduler utilization, otherwise obtained from calling the
+ more primitive <seealso marker="erts:erlang#statistics_scheduler_wall_time">
+ <c>statistics(scheduler_wall_time)</c></seealso>.</p>
+ <p>The simplest usage is to call <seealso marker="#utilization-1">
+ <c>scheduler:utilization(Seconds)</c></seealso>.</p>
+ </description>
+
+ <datatypes>
+ <datatype>
+ <name name="sched_sample"/>
+ </datatype>
+ <datatype>
+ <name name="sched_type"/>
+ </datatype>
+ <datatype>
+ <name name="sched_id"/>
+ </datatype>
+ <datatype>
+ <name name="sched_util_result"/>
+ <desc>
+ <p>A list of tuples containing results for individual schedulers
+ as well as aggregated averages. <c>Util</c> is the scheduler utilization
+ as a floating point value between 0.0 and 1.0. <c>Percent</c> is the
+ same utilization as a more human readable string expressed in percent.</p>
+ <taglist>
+ <tag><c>{normal, SchedulerId, Util, Percent}</c></tag>
+ <item>Scheduler utilization of a normal scheduler with number
+ <c>SchedulerId</c>.</item>
+ <tag><c>{cpu, SchedulerId, Util, Percent}</c></tag>
+ <item>Scheduler utilization of a dirty-cpu scheduler with number
+ <c>SchedulerId</c>.</item>
+ <tag><c>{io, SchedulerId, Util, Percent}</c></tag>
+ <item>Scheduler utilization of a dirty-io scheduler with number
+ <c>SchedulerId</c>. This tuple will only exist if both samples were
+ taken with <seealso marker="#sample_all-0"><c>sample_all/0</c></seealso>.</item>
+ <tag><c>{total, Util, Percent}</c></tag>
+ <item>Total utilization of all normal and dirty-cpu schedulers.</item>
+ <tag><c>{weighted, Util, Percent}</c></tag>
+ <item>Total utilization of all normal and dirty-cpu schedulers,
+ weighted against maximum amount of available CPU time.</item>
+ </taglist>
+ </desc>
+ </datatype>
+ </datatypes>
+
+ <funcs>
+
+ <func>
+ <name name="sample" arity="0"/>
+ <fsummary>Get scheduler utilization sample.</fsummary>
+ <desc>
+ <p>Return a scheduler utilization sample for normal and dirty-cpu
+ schedulers.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="sample_all" arity="0"/>
+ <fsummary>Get scheduler utilization sample.</fsummary>
+ <desc>
+ <p>Return a scheduler utilization sample for all schedulers,
+ including dirty-io schedulers.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="utilization" arity="1" clause_i="1"/>
+ <fsummary>Measure scheduler utilizations during a period of time.</fsummary>
+ <desc>
+ <p>Measure utilization for normal and dirty-cpu schedulers during
+ <c><anno>Seconds</anno></c> seconds, and then return the result.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="utilization" arity="1" clause_i="2"/>
+ <fsummary>Measure scheduler utilizations since sample.</fsummary>
+ <desc>
+ <p>Calculate scheduler utilizations for the time interval from when
+ <c><anno>Sample</anno></c> was taken and "now". The same as calling
+ <c>scheduler:utilization(Sample, scheduler:sample_all())</c>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="utilization" arity="2"/>
+ <fsummary>Measure scheduler utilizations between two samples.</fsummary>
+ <desc>
+ <p>Calculates scheduler utilizations for the time interval between
+ the two samples obtained from calling
+ <seealso marker="#sample-0"><c>sample/0</c></seealso> or
+ <seealso marker="#sample_all-0"><c>sample_all/0</c></seealso>.</p>
+ </desc>
+ </func>
+
+ </funcs>
+ </erlref>
diff --git a/lib/runtime_tools/doc/src/specs.xml b/lib/runtime_tools/doc/src/specs.xml
index 978bd39e55..33fe7fa370 100644
--- a/lib/runtime_tools/doc/src/specs.xml
+++ b/lib/runtime_tools/doc/src/specs.xml
@@ -2,4 +2,5 @@
<specs xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="../specs/specs_system_information.xml"/>
<xi:include href="../specs/specs_msacc.xml"/>
+ <xi:include href="../specs/specs_scheduler.xml"/>
</specs>
diff --git a/lib/runtime_tools/doc/src/warning.gif b/lib/runtime_tools/doc/src/warning.gif
deleted file mode 100644
index 96af52360e..0000000000
--- a/lib/runtime_tools/doc/src/warning.gif
+++ /dev/null
Binary files differ
diff --git a/lib/runtime_tools/examples/efile_drv.d b/lib/runtime_tools/examples/efile_drv.d
deleted file mode 100644
index a470518dd9..0000000000
--- a/lib/runtime_tools/examples/efile_drv.d
+++ /dev/null
@@ -1,105 +0,0 @@
-/* example usage: dtrace -q -s /path/to/efile_drv.d */
-/*
- * %CopyrightBegin%
- *
- * Copyright Scott Lystig Fritchie 2011-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- */
-
-BEGIN
-{
- op_map[1] = "OPEN";
- op_map[2] = "READ";
- op_map[3] = "LSEEK";
- op_map[4] = "WRITE";
- op_map[5] = "FSTAT";
- op_map[6] = "PWD";
- op_map[7] = "READDIR";
- op_map[8] = "CHDIR";
- op_map[9] = "FSYNC";
- op_map[10] = "MKDIR";
- op_map[11] = "DELETE";
- op_map[12] = "RENAME";
- op_map[13] = "RMDIR";
- op_map[14] = "TRUNCATE";
- op_map[15] = "READ_FILE";
- op_map[16] = "WRITE_INFO";
- op_map[19] = "LSTAT";
- op_map[20] = "READLINK";
- op_map[21] = "LINK";
- op_map[22] = "SYMLINK";
- op_map[23] = "CLOSE";
- op_map[24] = "PWRITEV";
- op_map[25] = "PREADV";
- op_map[26] = "SETOPT";
- op_map[27] = "IPREAD";
- op_map[28] = "ALTNAME";
- op_map[29] = "READ_LINE";
- op_map[30] = "FDATASYNC";
- op_map[31] = "FADVISE";
-}
-
-erlang*:::aio_pool-add
-{
- printf("async I/O pool port %s queue len %d\n", copyinstr(arg0), arg1);
-}
-
-erlang*:::aio_pool-get
-{
- printf("async I/O pool port %s queue len %d\n", copyinstr(arg0), arg1);
-}
-
-erlang*:::efile_drv-entry
-{
- printf("efile_drv enter tag={%d,%d} %s%s | %s (%d) | args: %s %s , %d %d (port %s)\n",
- arg0, arg1,
- arg2 == NULL ? "" : "user tag ",
- arg2 == NULL ? "" : copyinstr(arg2),
- op_map[arg3], arg3,
- arg4 == NULL ? "" : copyinstr(arg4),
- arg5 == NULL ? "" : copyinstr(arg5), arg6, arg7,
- /* NOTE: port name in args[10] is experimental */
- (args[10] == NULL) ?
- "?" : copyinstr((user_addr_t) args[10]));
-}
-
-erlang*:::efile_drv-int*
-{
- printf("async I/O worker tag={%d,%d} | %s (%d) | %s\n",
- arg0, arg1, op_map[arg2], arg2, probename);
-}
-
-/* efile_drv-return error case */
-erlang*:::efile_drv-return
-/arg4 == 0/
-{
- printf("efile_drv return tag={%d,%d} %s%s | %s (%d) | errno %d\n",
- arg0, arg1,
- arg2 == NULL ? "" : "user tag ",
- arg2 == NULL ? "" : copyinstr(arg2),
- op_map[arg3], arg3,
- arg5);
-}
-
-/* efile_drv-return success case */
-erlang*:::efile_drv-return
-/arg4 != 0/
-{
- printf("efile_drv return tag={%d,%d} %s | %s (%d) ok\n",
- arg0, arg1,
- arg2 == NULL ? "" : copyinstr(arg2),
- op_map[arg3], arg3);
-}
diff --git a/lib/runtime_tools/examples/efile_drv.systemtap b/lib/runtime_tools/examples/efile_drv.systemtap
deleted file mode 100644
index 29c3637e10..0000000000
--- a/lib/runtime_tools/examples/efile_drv.systemtap
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Scott Lystig Fritchie and Andreas Schultz, 2011-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- */
-/*
- * Note: This file assumes that you're using the non-SMP-enabled Erlang
- * virtual machine, "beam". The SMP-enabled VM is called "beam.smp".
- * Note that other variations of the virtual machine also have
- * different names, e.g. the debug build of the SMP-enabled VM
- * is "beam.debug.smp".
- *
- * To use a different virtual machine, replace each instance of
- * "beam" with "beam.smp" or the VM name appropriate to your
- * environment.
- */
-
-probe begin
-{
- op_map[1] = "OPEN";
- op_map[2] = "READ";
- op_map[3] = "LSEEK";
- op_map[4] = "WRITE";
- op_map[5] = "FSTAT";
- op_map[6] = "PWD";
- op_map[7] = "READDIR";
- op_map[8] = "CHDIR";
- op_map[9] = "FSYNC";
- op_map[10] = "MKDIR";
- op_map[11] = "DELETE";
- op_map[12] = "RENAME";
- op_map[13] = "RMDIR";
- op_map[14] = "TRUNCATE";
- op_map[15] = "READ_FILE";
- op_map[16] = "WRITE_INFO";
- op_map[19] = "LSTAT";
- op_map[20] = "READLINK";
- op_map[21] = "LINK";
- op_map[22] = "SYMLINK";
- op_map[23] = "CLOSE";
- op_map[24] = "PWRITEV";
- op_map[25] = "PREADV";
- op_map[26] = "SETOPT";
- op_map[27] = "IPREAD";
- op_map[28] = "ALTNAME";
- op_map[29] = "READ_LINE";
- op_map[30] = "FDATASYNC";
- op_map[31] = "FADVISE";
-}
-
-probe process("beam").mark("aio_pool-add")
-{
- printf("async I/O pool port %s queue len %d\n", user_string($arg1), $arg2);
-}
-
-probe process("beam").mark("aio_pool-get")
-{
- printf("async I/O pool port %s queue len %d\n", user_string($arg1), $arg2);
-}
-
-probe process("beam").mark("efile_drv-entry")
-{
- printf("efile_drv enter tag={%d,%d} %s%s | %s (%d) | args: %s %s , %d %d (port %s)\n",
- $arg1, $arg2,
- $arg3 == NULL ? "" : "user tag ",
- $arg3 == NULL ? "" : user_string($arg3),
- op_map[$arg4], $arg4,
- $arg5 == NULL ? "" : user_string($arg5),
- $arg6 == NULL ? "" : user_string($arg6), $arg7, $arg8,
- /* NOTE: port name in $arg[11] is experimental */
- user_string($arg11))
-}
-
-probe process("beam").mark("efile_drv-int*")
-{
- printf("async I/O worker tag={%d,%d} | %s (%d) | %s\n",
- $arg1, $arg2, op_map[$arg3], $arg3, probefunc());
-}
-
-probe process("beam").mark("efile_drv-return")
-{
- if ($arg5 == 0) {
- /* efile_drv-return error case */
- printf("efile_drv return tag={%d,%d} %s%s | %s (%d) | errno %d\n",
- $arg1, $arg2,
- $arg3 == NULL ? "" : "user tag ",
- $arg3 == NULL ? "" : user_string($arg3),
- op_map[$arg4], $arg4,
- $arg6);
- } else {
- /* efile_drv-return success case */
- printf("efile_drv return tag={%d,%d} %s | %s (%d) ok\n",
- $arg1, $arg2,
- $arg3 == NULL ? "" : user_string($arg3),
- op_map[$arg4], $arg4);
- }
-}
-
-global op_map;
diff --git a/lib/runtime_tools/src/Makefile b/lib/runtime_tools/src/Makefile
index 5a99c6e240..76286c5499 100644
--- a/lib/runtime_tools/src/Makefile
+++ b/lib/runtime_tools/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2017. All Rights Reserved.
+# Copyright Ericsson AB 1999-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -45,6 +45,7 @@ MODULES= \
system_information \
observer_backend \
ttb_autostart\
+ scheduler\
msacc
HRL_FILES= ../include/observer_backend.hrl
diff --git a/lib/runtime_tools/src/appmon_info.erl b/lib/runtime_tools/src/appmon_info.erl
index b5500085a3..d64206decf 100644
--- a/lib/runtime_tools/src/appmon_info.erl
+++ b/lib/runtime_tools/src/appmon_info.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -690,7 +690,7 @@ find_avoid() ->
[P|Accu];
_ -> Accu end end,
[undefined],
- [application_controller, init, error_logger, gs,
+ [application_controller, init, gs,
node_serv, appmon, appmon_a, appmon_info]).
diff --git a/lib/runtime_tools/src/dbg.erl b/lib/runtime_tools/src/dbg.erl
index e82f27896d..92938ed5c1 100644
--- a/lib/runtime_tools/src/dbg.erl
+++ b/lib/runtime_tools/src/dbg.erl
@@ -268,7 +268,7 @@ wtp(FileName) ->
{error, Reason} ->
{error, Reason};
{ok, File} ->
- io:put_chars(File, "%% coding: utf8\n"),
+ io:format(File, "%% ~s\n", [epp:encoding_to_string(utf8)]),
pt_doforall(fun ({_, Val}, _) when is_list(Val) ->
io:format(File, "~tp.~n", [Val]);
({_, _}, _) ->
diff --git a/lib/runtime_tools/src/erts_alloc_config.erl b/lib/runtime_tools/src/erts_alloc_config.erl
index 514530332c..845efaf9ef 100644
--- a/lib/runtime_tools/src/erts_alloc_config.erl
+++ b/lib/runtime_tools/src/erts_alloc_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -265,7 +265,13 @@ strategy_str(aoff) ->
strategy_str(aoffcbf) ->
"Address order first fit carrier best fit";
strategy_str(aoffcaobf) ->
- "Address order first fit carrier adress order best fit".
+ "Address order first fit carrier adress order best fit";
+strategy_str(ageffcaoff) ->
+ "Age order first fit carrier address order first fit";
+strategy_str(ageffcbf) ->
+ "Age order first fit carrier best fit";
+strategy_str(ageffcaobf) ->
+ "Age order first fit carrier adress order best fit".
default_acul(A, S) ->
case carrier_migration_support(S) of
@@ -621,7 +627,7 @@ format_header(FTO) ->
[Y, Mo, D, H, Mi, S]),
fcp(FTO,
"~s was used when generating the configuration.",
- [string:strip(erlang:system_info(system_version), both, $\n)]),
+ [string:trim(erlang:system_info(system_version), both, "$\n")]),
case erlang:system_info(schedulers) of
1 -> ok;
Schdlrs ->
@@ -698,28 +704,32 @@ fc(IODev, Frmt, Args) ->
fc(IODev, lists:flatten(io_lib:format(Frmt, Args))).
fc(IODev, String) ->
- fc_aux(IODev, string:tokens(String, " "), 0).
+ fc_aux(IODev, string:lexemes(String, " "), 0).
fc_aux(_IODev, [], 0) ->
ok;
fc_aux(IODev, [], _Len) ->
format(IODev, "~n");
fc_aux(IODev, [T|Ts], 0) ->
- Len = 2 + length(T),
+ Len = 2 + string:length(T),
format(IODev, "# ~s", [T]),
fc_aux(IODev, Ts, Len);
-fc_aux(IODev, [T|_Ts] = ATs, Len) when (length(T) + Len) >= ?PRINT_WITDH ->
- format(IODev, "~n"),
- fc_aux(IODev, ATs, 0);
-fc_aux(IODev, [T|Ts], Len) ->
- NewLen = Len + 1 + length(T),
- format(IODev, " ~s", [T]),
- fc_aux(IODev, Ts, NewLen).
+fc_aux(IODev, [T|Ts] = ATs, Len) ->
+ TLength = string:length(T),
+ case (TLength + Len) >= ?PRINT_WITDH of
+ true ->
+ format(IODev, "~n"),
+ fc_aux(IODev, ATs, 0);
+ false ->
+ NewLen = Len + 1 + TLength,
+ format(IODev, " ~s", [T]),
+ fc_aux(IODev, Ts, NewLen)
+ end.
%% fcl: format comment line
fcl(FTO) ->
EndStr = "# ",
- Precision = length(EndStr),
+ Precision = string:length(EndStr),
FieldWidth = -1*(?PRINT_WITDH),
format(FTO, "~*.*.*s~n", [FieldWidth, Precision, $-, EndStr]).
@@ -727,6 +737,6 @@ fcl(FTO, A) when is_atom(A) ->
fcl(FTO, atom_to_list(A));
fcl(FTO, Str) when is_list(Str) ->
Str2 = "# --- " ++ Str ++ " ",
- Precision = length(Str2),
+ Precision = string:length(Str2),
FieldWidth = -1*(?PRINT_WITDH),
format(FTO, "~*.*.*s~n", [FieldWidth, Precision, $-, Str2]).
diff --git a/lib/runtime_tools/src/msacc.erl b/lib/runtime_tools/src/msacc.erl
index 0d9b2690e5..7a3633be8e 100644
--- a/lib/runtime_tools/src/msacc.erl
+++ b/lib/runtime_tools/src/msacc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2014-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2014-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -46,7 +46,8 @@
system := float()}}.
--type msacc_type() :: scheduler | aux | async.
+-type msacc_type() :: aux | async | dirty_cpu_scheduler
+ | dirty_io_scheduler | poll | scheduler.
-type msacc_id() :: non_neg_integer().
-type msacc_state() :: alloc | aux | bif | busy_wait | check_io |
emulator | ets | gc | gc_fullsweep | nif |
diff --git a/lib/runtime_tools/src/observer_backend.erl b/lib/runtime_tools/src/observer_backend.erl
index d36af257ce..3a24986381 100644
--- a/lib/runtime_tools/src/observer_backend.erl
+++ b/lib/runtime_tools/src/observer_backend.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@
ttb_write_binary/2,
ttb_stop/1,
ttb_fetch/2,
+ ttb_fetch/3,
ttb_resume_trace/0,
ttb_get_filenames/1]).
-define(CHUNKSIZE,8191). % 8 kbytes - 1 byte
@@ -63,9 +64,7 @@ sys_info() ->
end,
{{_,Input},{_,Output}} = erlang:statistics(io),
- [{process_count, erlang:system_info(process_count)},
- {process_limit, erlang:system_info(process_limit)},
- {uptime, element(1, erlang:statistics(wall_clock))},
+ [{uptime, element(1, erlang:statistics(wall_clock))},
{run_queue, erlang:statistics(run_queue)},
{io_input, Input},
{io_output, Output},
@@ -86,7 +85,17 @@ sys_info() ->
{thread_pool_size, erlang:system_info(thread_pool_size)},
{wordsize_internal, erlang:system_info({wordsize, internal})},
{wordsize_external, erlang:system_info({wordsize, external})},
- {alloc_info, alloc_info()}
+ {alloc_info, alloc_info()},
+ {process_count, erlang:system_info(process_count)},
+ {atom_limit, erlang:system_info(atom_limit)},
+ {atom_count, erlang:system_info(atom_count)},
+ {process_limit, erlang:system_info(process_limit)},
+ {process_count, erlang:system_info(process_count)},
+ {port_limit, erlang:system_info(port_limit)},
+ {port_count, erlang:system_info(port_count)},
+ {ets_limit, erlang:system_info(ets_limit)},
+ {ets_count, erlang:system_info(ets_count)},
+ {dist_buf_busy_limit, erlang:system_info(dist_buf_busy_limit)}
| MemInfo].
alloc_info() ->
@@ -270,7 +279,7 @@ get_table_list(mnesia, Opts) ->
end,
[Tab|Acc]
catch _:_What ->
- %% io:format("Skipped ~p: ~p ~p ~n",[Id, _What, erlang:get_stacktrace()]),
+ %% io:format("Skipped ~p: ~p ~p ~n",[Id, _What, Stacktrace]),
Acc
end
end,
@@ -284,7 +293,7 @@ fetch_stats_loop(Parent, Time) ->
erlang:system_flag(scheduler_wall_time, true),
receive
_Msg ->
- %% erlang:system_flag(scheduler_wall_time, false)
+ erlang:system_flag(scheduler_wall_time, false),
ok
after Time ->
_M = Parent ! {stats, 1,
@@ -331,7 +340,6 @@ etop_collect(Collector) ->
case SchedulerWallTime of
undefined ->
- erlang:system_flag(scheduler_wall_time,true),
spawn(fun() -> flag_holder_proc(Collector) end),
ok;
_ ->
@@ -339,10 +347,11 @@ etop_collect(Collector) ->
end.
flag_holder_proc(Collector) ->
+ erlang:system_flag(scheduler_wall_time,true),
Ref = erlang:monitor(process,Collector),
receive
{'DOWN',Ref,_,_,_} ->
- %% erlang:system_flag(scheduler_wall_time,false)
+ erlang:system_flag(scheduler_wall_time,false),
ok
end.
@@ -650,22 +659,42 @@ stop_seq_trace() ->
%% Fetch ttb logs from remote node
ttb_fetch(MetaFile,{Port,Host}) ->
+ ttb_fetch(MetaFile,{Port,Host},undefined).
+ttb_fetch(MetaFile,{Port,Host},MasterEnc) ->
erlang:process_flag(priority,low),
Files = ttb_get_filenames(MetaFile),
{ok, Sock} = gen_tcp:connect(Host, Port, [binary, {packet, 2}]),
- send_files({Sock,Host},Files),
+ send_files({Sock,Host},Files,MasterEnc,file:native_name_encoding()),
ok = gen_tcp:close(Sock).
-send_files({Sock,Host},[File|Files]) ->
+send_files({Sock,Host},[File|Files],MasterEnc,MyEnc) ->
{ok,Fd} = file:open(File,[raw,read,binary]),
- ok = gen_tcp:send(Sock,<<1,(list_to_binary(filename:basename(File)))/binary>>),
+ Basename = filename:basename(File),
+ {Code,FilenameBin} = encode_filename(Basename,MasterEnc,MyEnc),
+ ok = gen_tcp:send(Sock,<<Code,FilenameBin/binary>>),
send_chunks(Sock,Fd),
ok = file:delete(File),
- send_files({Sock,Host},Files);
-send_files({_Sock,_Host},[]) ->
+ send_files({Sock,Host},Files,MasterEnc,MyEnc);
+send_files({_Sock,_Host},[],_MasterEnc,_MyEnc) ->
done.
+encode_filename(Basename,undefined,MyEnc) ->
+ %% Compatible with old version of ttb.erl, but no longer crashing
+ %% for code points > 255.
+ {1,unicode:characters_to_binary(Basename,MyEnc,MyEnc)};
+encode_filename(Basename,MasterEnc,MyEnc) ->
+ case unicode:characters_to_binary(Basename,MyEnc,MasterEnc) of
+ Bin when is_binary(Bin) ->
+ %% Encoding succeeded
+ {2,Bin};
+ _ ->
+ %% Can't convert Basename from my encoding to the master
+ %% node's encoding. Doing my best and hoping that master
+ %% node can fix it...
+ {3,unicode:characters_to_binary(Basename,MyEnc,MyEnc)}
+ end.
+
send_chunks(Sock,Fd) ->
case file:read(Fd,?CHUNKSIZE) of
{ok,Bin} ->
diff --git a/lib/runtime_tools/src/runtime_tools.app.src b/lib/runtime_tools/src/runtime_tools.app.src
index 449532e5c4..b026048b94 100644
--- a/lib/runtime_tools/src/runtime_tools.app.src
+++ b/lib/runtime_tools/src/runtime_tools.app.src
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
{modules, [appmon_info, dbg,observer_backend,runtime_tools,
runtime_tools_sup,erts_alloc_config,
ttb_autostart,dyntrace,system_information,
+ scheduler,
msacc]},
{registered, [runtime_tools_sup]},
{applications, [kernel, stdlib]},
diff --git a/lib/runtime_tools/src/scheduler.erl b/lib/runtime_tools/src/scheduler.erl
new file mode 100644
index 0000000000..c896b671ac
--- /dev/null
+++ b/lib/runtime_tools/src/scheduler.erl
@@ -0,0 +1,152 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%% @doc Utility functions for easier measurement of scheduler utilization
+%% using erlang:statistics(scheduler_wall_time).
+
+-module(scheduler).
+
+-export([sample/0,
+ sample_all/0,
+ utilization/1,
+ utilization/2]).
+
+-export_type([sched_sample/0]).
+
+
+-opaque sched_sample() ::
+ {scheduler_wall_time | scheduler_wall_time_all,
+ [{sched_type(), sched_id(), ActiveTime::integer(), TotalTime::integer()}]}.
+
+-type sched_type() :: normal | cpu | io.
+
+-type sched_id() :: integer().
+
+-spec sample() -> sched_sample().
+sample() ->
+ sample(scheduler_wall_time).
+
+-spec sample_all() -> sched_sample().
+sample_all() ->
+ sample(scheduler_wall_time_all).
+
+sample(Stats) ->
+ case erlang:statistics(Stats) of
+ undefined ->
+ erlang:system_flag(scheduler_wall_time, true),
+ sample(Stats);
+
+ List ->
+ Sorted = lists:sort(List),
+ Tagged = lists:map(fun({I, A, T}) -> {sched_tag(I), I, A, T} end,
+ Sorted),
+ {Stats, Tagged}
+ end.
+
+-type sched_util_result() ::
+ [{sched_type(), sched_id(), float(), string()} |
+ {total, float(), string()} |
+ {weighted, float(), string()}].
+
+-spec utilization(Seconds) -> sched_util_result() when
+ Seconds :: pos_integer();
+ (Sample) -> sched_util_result() when
+ Sample :: sched_sample().
+utilization(Seconds) when is_integer(Seconds), Seconds > 0 ->
+ OldFlag = erlang:system_flag(scheduler_wall_time, true),
+ T0 = sample(),
+ receive after Seconds*1000 -> ok end,
+ T1 = sample(),
+ case OldFlag of
+ false ->
+ erlang:system_flag(scheduler_wall_time, OldFlag);
+ true ->
+ ok
+ end,
+ utilization(T0,T1);
+
+utilization({Stats, _}=T0) when Stats =:= scheduler_wall_time;
+ Stats =:= scheduler_wall_time_all ->
+ utilization(T0, sample(Stats)).
+
+-spec utilization(Sample1, Sample2) -> sched_util_result() when
+ Sample1 :: sched_sample(),
+ Sample2 :: sched_sample().
+utilization({Stats, Ts0}, {Stats, Ts1}) ->
+ Diffs = lists:map(fun({{Tag, I, A0, T0}, {Tag, I, A1, T1}}) ->
+ {Tag, I, (A1 - A0), (T1 - T0)}
+ end,
+ lists:zip(Ts0,Ts1)),
+
+ {Lst0, {A, T, N}} = lists:foldl(fun({Tag, I, Adiff, Tdiff}, {Lst, Acc}) ->
+ R = safe_div(Adiff, Tdiff),
+ {[{Tag, I, R, percent(R)} | Lst],
+ acc(Tag, Adiff, Tdiff, Acc)}
+ end,
+ {[], {0, 0, 0}},
+ Diffs),
+
+ Total = safe_div(A, T),
+ Lst1 = lists:reverse(Lst0),
+ Lst2 = case erlang:system_info(logical_processors_available) of
+ unknown -> Lst1;
+ LPA ->
+ Weighted = Total * (N / LPA),
+ [{weighted, Weighted, percent(Weighted)} | Lst1]
+ end,
+ [{total, Total, percent(Total)} | Lst2];
+
+utilization({scheduler_wall_time, _}=T0,
+ {scheduler_wall_time_all, Ts1}) ->
+ utilization(T0, {scheduler_wall_time, remove_io(Ts1)});
+
+utilization({scheduler_wall_time_all, Ts0},
+ {scheduler_wall_time, _}=T1) ->
+ utilization({scheduler_wall_time, remove_io(Ts0)}, T1).
+
+%% Do not include dirty-io in totals
+acc(io, _, _, Acc) ->
+ Acc;
+acc(Tag, Adiff, Tdiff, {Asum, Tsum, N}) when Tag =:= normal; Tag =:= cpu ->
+ {Adiff+Asum, Tdiff+Tsum, N+1}.
+
+
+remove_io(Ts) ->
+ lists:filter(fun({io,_,_,_}) -> false;
+ (_) -> true end,
+ Ts).
+
+safe_div(A, B) ->
+ if B == 0.0 -> 0.0;
+ true -> A / B
+ end.
+
+sched_tag(Nr) ->
+ Normal = erlang:system_info(schedulers),
+ Cpu = Normal + erlang:system_info(dirty_cpu_schedulers),
+ case Nr of
+ _ when Nr =< Normal -> normal;
+ _ when Nr =< Cpu -> cpu;
+ _ -> io
+ end.
+
+
+percent(F) ->
+ float_to_list(F*100, [{decimals,1}]) ++ [$%].
diff --git a/lib/runtime_tools/src/system_information.erl b/lib/runtime_tools/src/system_information.erl
index df25297eb9..136ee55b54 100644
--- a/lib/runtime_tools/src/system_information.erl
+++ b/lib/runtime_tools/src/system_information.erl
@@ -75,43 +75,37 @@ load_report(file, File) -> load_report(data, from_file(File));
load_report(data, Report) ->
ok = start_internal(), gen_server:call(?SERVER, {load_report, Report}, infinity).
-report() -> [
- {init_arguments, init:get_arguments()},
- {code_paths, code:get_path()},
- {code, code()},
- {system_info, erlang_system_info()},
- {erts_compile_info, erlang:system_info(compile_info)},
- {beam_dynamic_libraries, get_dynamic_libraries()},
- {environment_erts, os_getenv_erts_specific()},
- {environment, [split_env(Env) || Env <- os:getenv()]},
- {sanity_check, sanity_check()}
- ].
+report() ->
+ %% This is ugly but beats having to maintain two distinct implementations,
+ %% and we don't really care about memory use since it's internal and
+ %% undocumented.
+ {ok, Fd} = file:open([], [ram, read, write]),
+ to_fd(Fd),
+ {ok, _} = file:position(Fd, bof),
+ from_fd(Fd).
-spec to_file(FileName) -> ok | {error, Reason} when
FileName :: file:name_all(),
Reason :: file:posix() | badarg | terminated | system_limit.
to_file(File) ->
- file:write_file(File, iolist_to_binary([
- io_lib:format("{system_information_version, ~p}.~n", [
- ?REPORT_FILE_VSN
- ]),
- io_lib:format("{system_information, ~p}.~n", [
- report()
- ])
- ])).
+ case file:open(File, [raw, write, binary, delayed_write]) of
+ {ok, Fd} ->
+ try
+ to_fd(Fd)
+ after
+ file:close(Fd)
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end.
from_file(File) ->
- case file:consult(File) of
- {ok, Data} ->
- case get_value([system_information_version], Data) of
- ?REPORT_FILE_VSN ->
- get_value([system_information], Data);
- Vsn ->
- erlang:error({unknown_version, Vsn})
- end;
- _ ->
- erlang:error(bad_report_file)
+ {ok, Fd} = file:open(File, [raw, read]),
+ try
+ from_fd(Fd)
+ after
+ file:close(Fd)
end.
applications() -> applications([]).
@@ -457,61 +451,151 @@ split_env([$=|Vs], Key) -> {lists:reverse(Key), Vs};
split_env([I|Vs], Key) -> split_env(Vs, [I|Key]);
split_env([], KV) -> lists:reverse(KV). % should not happen.
-%% get applications
+from_fd(Fd) ->
+ try
+ [{system_information_version, "1.0"},
+ {system_information, Data}] = consult_fd(Fd),
+ Data
+ catch
+ _:_ -> erlang:error(bad_report_file)
+ end.
-code() ->
- % order is important
- get_code_from_paths(code:get_path()).
+consult_fd(Fd) ->
+ consult_fd_1(Fd, [], {ok, []}).
+consult_fd_1(Fd, Cont0, ReadResult) ->
+ Data =
+ case ReadResult of
+ {ok, Characters} -> Characters;
+ eof -> eof
+ end,
+ case erl_scan:tokens(Cont0, Data, 1) of
+ {done, {ok, Tokens, _}, Next} ->
+ {ok, Term} = erl_parse:parse_term(Tokens),
+ [Term | consult_fd_1(Fd, [], {ok, Next})];
+ {more, Cont} ->
+ consult_fd_1(Fd, Cont, file:read(Fd, 1 bsl 20));
+ {done, {eof, _}, eof} -> []
+ end.
-get_code_from_paths([]) -> [];
-get_code_from_paths([Path|Paths]) ->
- case is_application_path(Path) of
- true ->
- [{application, get_application_from_path(Path)}|get_code_from_paths(Paths)];
- false ->
- [{code, [
- {path, Path},
- {modules, get_modules_from_path(Path)}
- ]}|get_code_from_paths(Paths)]
+%%
+%% Dumps a system_information tuple to the given Fd, writing the term in chunks
+%% to avoid eating too much memory on large systems.
+%%
+
+to_fd(Fd) ->
+ EmitChunk =
+ fun(Format, Args) ->
+ ok = file:write(Fd, io_lib:format(Format, Args))
+ end,
+
+ EmitChunk("{system_information_version, ~w}.~n"
+ "{system_information,["
+ "{init_arguments,~w},"
+ "{code_paths,~w},",
+ [?REPORT_FILE_VSN,
+ init:get_arguments(),
+ code:get_path()]),
+
+ emit_code_info(EmitChunk),
+
+ EmitChunk( "," %% Note the leading comma!
+ "{system_info,~w},"
+ "{erts_compile_info,~w},"
+ "{beam_dynamic_libraries,~w},"
+ "{environment_erts,~w},"
+ "{environment,~w},"
+ "{sanity_check,~w}"
+ "]}.~n",
+ [erlang_system_info(),
+ erlang:system_info(compile_info),
+ get_dynamic_libraries(),
+ os_getenv_erts_specific(),
+ [split_env(Env) || Env <- os:getenv()],
+ sanity_check()]).
+
+%% Emits all modules/applications in the *code path order*
+emit_code_info(EmitChunk) ->
+ EmitChunk("{code, [", []),
+ comma_separated_foreach(EmitChunk,
+ fun(Path) ->
+ case is_application_path(Path) of
+ true -> emit_application_info(EmitChunk, Path);
+ false -> emit_code_path_info(EmitChunk, Path)
+ end
+ end, code:get_path()),
+ EmitChunk("]}", []).
+
+emit_application_info(EmitChunk, Path) ->
+ [Appfile|_] = filelib:wildcard(filename:join(Path, "*.app")),
+ case file:consult(Appfile) of
+ {ok, [{application, App, Info}]} ->
+ RtDeps = proplists:get_value(runtime_dependencies, Info, []),
+ Description = proplists:get_value(description, Info, []),
+ Version = proplists:get_value(vsn, Info, []),
+
+ EmitChunk("{application, {~w,["
+ "{description,~w},"
+ "{vsn,~w},"
+ "{path,~w},"
+ "{runtime_dependencies,~w},",
+ [App, Description, Version, Path, RtDeps]),
+ emit_module_info_from_path(EmitChunk, Path),
+ EmitChunk("]}}", [])
end.
+emit_code_path_info(EmitChunk, Path) ->
+ EmitChunk("{code, ["
+ "{path, ~w},", [Path]),
+ emit_module_info_from_path(EmitChunk, Path),
+ EmitChunk("]}", []).
+
+emit_module_info_from_path(EmitChunk, Path) ->
+ BeamFiles = filelib:wildcard(filename:join(Path, "*.beam")),
+
+ EmitChunk("{modules, [", []),
+ comma_separated_foreach(EmitChunk,
+ fun(Beam) ->
+ emit_module_info(EmitChunk, Beam)
+ end, BeamFiles),
+ EmitChunk("]}", []).
+
+emit_module_info(EmitChunk, Beam) ->
+ %% FIXME: The next three calls load *all* significant chunks onto the heap,
+ %% which may cause us to run out of memory if there's a huge module in the
+ %% code path.
+ {ok,{Mod, Md5}} = beam_lib:md5(Beam),
+
+ CompilerVersion = get_compiler_version(Beam),
+ Native = beam_is_native_compiled(Beam),
+
+ Loaded = case code:is_loaded(Mod) of
+ false -> false;
+ _ -> true
+ end,
+
+ EmitChunk("{~w,["
+ "{loaded,~w},"
+ "{native,~w},"
+ "{compiler,~w},"
+ "{md5,~w}"
+ "]}",
+ [Mod, Loaded, Native, CompilerVersion, hexstring(Md5)]).
+
+comma_separated_foreach(_EmitChunk, _Fun, []) ->
+ ok;
+comma_separated_foreach(_EmitChunk, Fun, [H]) ->
+ Fun(H);
+comma_separated_foreach(EmitChunk, Fun, [H | T]) ->
+ Fun(H),
+ EmitChunk(",", []),
+ comma_separated_foreach(EmitChunk, Fun, T).
+
is_application_path(Path) ->
case filelib:wildcard(filename:join(Path, "*.app")) of
[] -> false;
_ -> true
end.
-get_application_from_path(Path) ->
- [Appfile|_] = filelib:wildcard(filename:join(Path, "*.app")),
- case file:consult(Appfile) of
- {ok, [{application, App, Info}]} ->
- {App, [
- {description, proplists:get_value(description, Info, [])},
- {vsn, proplists:get_value(vsn, Info, [])},
- {path, Path},
- {runtime_dependencies,
- proplists:get_value(runtime_dependencies, Info, [])},
- {modules, get_modules_from_path(Path)}
- ]}
- end.
-
-get_modules_from_path(Path) ->
- [
- begin
- {ok,{Mod, Md5}} = beam_lib:md5(Beam),
- Loaded = case code:is_loaded(Mod) of
- false -> false;
- _ -> true
- end,
- {Mod, [
- {loaded, Loaded},
- {native, beam_is_native_compiled(Beam)},
- {compiler, get_compiler_version(Beam)},
- {md5, hexstring(Md5)}
- ]}
- end || Beam <- filelib:wildcard(filename:join(Path, "*.beam"))
- ].
-
hexstring(Bin) when is_binary(Bin) ->
lists:flatten([io_lib:format("~2.16.0b", [V]) || <<V>> <= Bin]).
@@ -590,12 +674,12 @@ vsnstr2vsn(VsnStr) ->
list_to_tuple(lists:map(fun (Part) ->
list_to_integer(Part)
end,
- string:tokens(VsnStr, "."))).
+ string:lexemes(VsnStr, "."))).
rtdepstrs2rtdeps([]) ->
[];
rtdepstrs2rtdeps([RTDep | RTDeps]) ->
- [AppStr, VsnStr] = string:tokens(RTDep, "-"),
+ [AppStr, VsnStr] = string:lexemes(RTDep, "-"),
[{list_to_atom(AppStr), vsnstr2vsn(VsnStr)} | rtdepstrs2rtdeps(RTDeps)].
build_app_table([], AppTab) ->
diff --git a/lib/runtime_tools/test/Makefile b/lib/runtime_tools/test/Makefile
index 61377ea09e..29cf7545c9 100644
--- a/lib/runtime_tools/test/Makefile
+++ b/lib/runtime_tools/test/Makefile
@@ -9,7 +9,9 @@ MODULES = \
system_information_SUITE \
dbg_SUITE \
erts_alloc_config_SUITE \
- msacc_SUITE
+ scheduler_SUITE \
+ msacc_SUITE \
+ zzz_SUITE
ERL_FILES= $(MODULES:%=%.erl)
diff --git a/lib/runtime_tools/test/dbg_SUITE.erl b/lib/runtime_tools/test/dbg_SUITE.erl
index 4b0864858c..98cbc0360f 100644
--- a/lib/runtime_tools/test/dbg_SUITE.erl
+++ b/lib/runtime_tools/test/dbg_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
-export([all/0, suite/0,
big/1, tiny/1, simple/1, message/1, distributed/1, port/1,
send/1, recv/1,
- ip_port/1, file_port/1, file_port2/1, file_port_schedfix/1,
+ ip_port/1, file_port/1, file_port2/1,
ip_port_busy/1, wrap_port/1, wrap_port_time/1,
with_seq_trace/1, dead_suspend/1, local_trace/1,
saved_patterns/1, tracer_exit_on_stop/1,
@@ -41,7 +41,7 @@ suite() ->
all() ->
[big, tiny, simple, message, distributed, port, ip_port,
send, recv,
- file_port, file_port2, file_port_schedfix, ip_port_busy,
+ file_port, file_port2, ip_port_busy,
wrap_port, wrap_port_time, with_seq_trace, dead_suspend,
local_trace, saved_patterns, tracer_exit_on_stop,
erl_tracer, distributed_erl_tracer].
@@ -478,8 +478,7 @@ port(Config) when is_list(Config) ->
TraceFileDrv = list_to_atom(lists:flatten(["trace_file_drv n ",TestFile])),
[{trace,Port,open,S,TraceFileDrv},
{trace,Port,getting_linked,S},
- {trace,Port,closed,normal},
- {trace,Port,unlink,S}] = flush()
+ {trace,Port,closed,normal}] = flush()
after
dbg:stop()
end,
@@ -623,99 +622,6 @@ file_port2(Config) when is_list(Config) ->
end,
ok.
-%% Test that the scheduling timestamp fix for trace flag 'running' works.
-file_port_schedfix(Config) when is_list(Config) ->
- case (catch erlang:system_info(smp_support)) of
- true ->
- {skip, "No schedule fix on SMP"};
- _ ->
- try
- file_port_schedfix1(Config)
- after
- dbg:stop()
- end
- end.
-file_port_schedfix1(Config) when is_list(Config) ->
- stop(),
- {A,B,C} = erlang:now(),
- FTMP = atom_to_list(?MODULE) ++ integer_to_list(A) ++
- "-" ++ integer_to_list(B) ++ "-" ++ integer_to_list(C),
- FName = filename:join([proplists:get_value(data_dir, Config), FTMP]),
- %%
- Port = dbg:trace_port(file, {FName, wrap, ".wraplog", 8*1024, 4}),
- {ok, _} = dbg:tracer(port, Port),
- {ok,[{matched,_node,0}]} = dbg:p(new,[running,procs,send,timestamp]),
- %%
- %% Generate the trace data
- %%
- %% This starts 3 processes that sends a message to each other in a ring,
- %% 4 laps. Prior to sending the message to the next in the ring, each
- %% process send 8 messages to itself, just to generate some trace data,
- %% and to lower the possibility that the trace log wraps just after
- %% a schedule out message (which would not burden any process and hence
- %% not show up in the result)
- %%
- %% The wrap file trace is used because it burns a lot of time when the
- %% driver swaps files, a lot more than the regular file trace. The test
- %% case is dimensioned so that the log fills two files and just starts
- %% on the third (out of four wrap files). This gives two file swaps,
- %% and there are three processes, so one process will NOT be burdened.
- %% The criterion for trace success is then that the max process
- %% execution time must not be more than twice the min process
- %% execution time. Wallclock. A normal result is about 10 times more
- %% without schedule in - schedule out compensation (OTP-3938).
- %%
- ok = token_volleyball(3, 4, 8),
- %%
- {ok,[{matched,_,_}]} = dbg:p(all, [clear]),
- stop(),
- %%
- %% Get the trace result
- %%
- Tag = make_ref(),
- dbg:trace_client(file, {FName, wrap, ".wraplog"},
- {fun schedstat_handler/2, {self(), Tag, []}}),
- Result =
- receive
- {Tag, D} ->
- lists:map(
- fun({Pid, {A1, B1, C1}}) ->
- {Pid, C1/1000000 + B1 + A1*1000000}
- end,
- D)
- end,
- ok = io:format("Result=~p", [Result]),
- % erlang:display({?MODULE, ?LINE, Result}),
- %%
- %% Analyze the result
- %%
- {Min, Max} = lists:foldl(fun({_Pid, M}, {Mi, Ma}) ->
- {if M < Mi -> M; true -> Mi end,
- if M > Ma -> M; true -> Ma end}
- end,
- {void, 0},
- Result),
- % More PaN debug
- io:format("Min = ~f, Max = ~f~n",[Min,Max]),
- %%
- %% Cleanup
- %%
- ToBeDeleted = filelib:wildcard(FName++"*"++".wraplog"),
- lists:map(fun file:delete/1, ToBeDeleted),
- % io:format("ToBeDeleted=~p", [ToBeDeleted]),
- %%
- %% Present the result
- %%
- P = (Max / Min - 1) * 100,
- BottomLine = lists:flatten(io_lib:format("~.2f %", [P])),
- if P > 100 ->
- Reason = {BottomLine, '>', "100%"},
- erlang:display({file_port_schedfix, fail, Reason}),
- ct:fail(Reason);
- true ->
- {comment, BottomLine}
- end.
-
%% Test tracing to wrapping file port
wrap_port(Config) when is_list(Config) ->
Self = self(),
diff --git a/lib/runtime_tools/test/dyntrace_SUITE.erl b/lib/runtime_tools/test/dyntrace_SUITE.erl
index 7be2f49a8b..17bc104e9a 100644
--- a/lib/runtime_tools/test/dyntrace_SUITE.erl
+++ b/lib/runtime_tools/test/dyntrace_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-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.
@@ -51,11 +51,7 @@ init_per_suite(Config) ->
case erlang:system_info(debug_compiled) of
false -> "";
true -> ".debug"
- end ++
- case erlang:system_info(smp_support) of
- false -> "";
- true -> ".smp"
- end,
+ end ++ ".smp",
[{emu_name,N}|Config].
end_per_suite(_Config) ->
diff --git a/lib/runtime_tools/test/scheduler_SUITE.erl b/lib/runtime_tools/test/scheduler_SUITE.erl
new file mode 100644
index 0000000000..1c80253371
--- /dev/null
+++ b/lib/runtime_tools/test/scheduler_SUITE.erl
@@ -0,0 +1,104 @@
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+-module(scheduler_SUITE).
+
+-export([suite/0, all/0]).
+
+%% Test cases
+-export([basic/1]).
+
+all() -> [basic].
+
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+
+basic(_Config) ->
+ S1 = scheduler:sample(),
+ S2 = scheduler:sample_all(),
+
+ check(scheduler:utilization(1)),
+
+ check(scheduler:utilization(S1)),
+ check(scheduler:utilization(S2)),
+ check(scheduler:utilization(S1, scheduler:sample())),
+ check(scheduler:utilization(S2, scheduler:sample())),
+
+ S3 = scheduler:sample_all(),
+ U13 = scheduler:utilization(S1, S3),
+ U13 = scheduler:utilization(S1, remove_io(S3)),
+ check(U13),
+
+ U23all = scheduler:utilization(S2, S3),
+ check(U23all),
+ U23 = scheduler:utilization(S2, remove_io(S3)),
+ U23 = scheduler:utilization(remove_io(S2), S3),
+ U23 = remove_io(U23all),
+ check(U23),
+
+ ok.
+
+
+check([{total, Tf, Ts} | List]=U) ->
+ io:format("\nU = ~p\n", [U]),
+ check_values(Tf, Ts, true),
+
+ SchdList = case hd(List) of
+ {weighted, Wf, Ws} ->
+ check_values(Wf, Ws, false),
+ tl(List);
+ _ ->
+ unknown = erlang:system_info(logical_processors_available),
+ List
+ end,
+
+ lists:foreach(fun({Type, Id, F, S}) when ((Type =:= normal) or (Type =:= cpu) or (Type =:= io)),
+ is_integer(Id) ->
+ check_values(F, S, true)
+ end,
+ SchdList),
+ ok.
+
+check_values(F, S, Max100) ->
+ true = is_float(F),
+ true = F >= 0.0,
+
+ $% = lists:last(S),
+ Sf = list_to_float(lists:droplast(S)),
+ true = Sf >= 0.0,
+ true = case Max100 of
+ true ->
+ true = F =< 1.0,
+ true = Sf =< 100.0;
+ false ->
+ true
+ end,
+ MaxDiff = 0.055555555555555555, %% change to 0.05 when float_to_list/2 is fixed
+ true = abs(F*100 - Sf) =< MaxDiff,
+ ok.
+
+
+remove_io({scheduler_wall_time_all,Lst}) ->
+ {scheduler_wall_time, remove_io(Lst)};
+remove_io(Lst) ->
+ lists:filter(fun({io,_,_,_}) -> false;
+ (_) -> true end,
+ Lst).
diff --git a/lib/runtime_tools/test/zzz_SUITE.erl b/lib/runtime_tools/test/zzz_SUITE.erl
new file mode 100644
index 0000000000..59c7fd7404
--- /dev/null
+++ b/lib/runtime_tools/test/zzz_SUITE.erl
@@ -0,0 +1,37 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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(zzz_SUITE).
+
+%% The sole purpose of this test suite is for things we want to run last
+%% before the VM terminates.
+
+-export([all/0]).
+
+-export([lc_graph/1]).
+
+
+all() ->
+ [lc_graph].
+
+lc_graph(_Config) ->
+ %% Create "lc_graph" file in current working dir
+ %% if lock checker is enabled.
+ erts_debug:lc_graph(),
+ ok.
diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk
index 5ee39a25fe..aa3d702997 100644
--- a/lib/runtime_tools/vsn.mk
+++ b/lib/runtime_tools/vsn.mk
@@ -1 +1 @@
-RUNTIME_TOOLS_VSN = 1.12
+RUNTIME_TOOLS_VSN = 1.13.1
diff --git a/lib/sasl/doc/src/Makefile b/lib/sasl/doc/src/Makefile
index a66b1f8bcb..8e1e8b502c 100644
--- a/lib/sasl/doc/src/Makefile
+++ b/lib/sasl/doc/src/Makefile
@@ -9,11 +9,11 @@
# 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.
-#
+#
# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
# AB. All Rights Reserved.''
-#
+#
# $Id$
#
include $(ERL_TOP)/make/target.mk
@@ -44,17 +44,14 @@ XML_REF4_FILES = appup.xml rel.xml relup.xml script.xml
XML_REF6_FILES = sasl_app.xml
-XML_PART_FILES = part.xml part_notes.xml part_notes_history.xml
+XML_PART_FILES = part.xml
XML_CHAPTER_FILES = sasl_intro.xml \
error_logging.xml \
- notes.xml \
- notes_history.xml
+ notes.xml
BOOK_FILES = book.xml
-GIF_FILES = \
- note.gif \
- warning.gif
+GIF_FILES =
XML_FILES = \
$(BOOK_FILES) $(XML_CHAPTER_FILES) \
@@ -78,14 +75,14 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
+XML_FLAGS +=
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-$(HTMLDIR)/%.gif: %.gif
+$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
docs: pdf html man
@@ -100,19 +97,20 @@ man: $(MAN3_FILES) $(MAN4_FILES) $(MAN6_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%) # We depend just to copy them to ../html
-debug opt:
+debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN4DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
+ rm -f errs core *~
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
@@ -130,4 +128,3 @@ release_docs_spec: docs
$(INSTALL_DATA) $(MAN6_FILES) "$(RELEASE_PATH)/man/man6"
release_spec:
-
diff --git a/lib/sasl/doc/src/appup.xml b/lib/sasl/doc/src/appup.xml
index a43a966dcb..102ea9e5d7 100644
--- a/lib/sasl/doc/src/appup.xml
+++ b/lib/sasl/doc/src/appup.xml
@@ -4,7 +4,7 @@
<fileref>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -249,9 +249,17 @@
<pre>
{restart_application, Application}
Application = atom()</pre>
- <p>Restarting an application means that the application is
- stopped and then started again, similar to using the instructions
- <c>remove_application</c> and <c>add_application</c> in sequence.</p>
+ <p>Restarting an application means that the application is stopped
+ and then started again, similar to using the instructions
+ <c>remove_application</c> and <c>add_application</c> in sequence.
+ Note that, even if the application has been started before the
+ release upgrade is performed, <c>restart_application</c> may only
+ <c>load</c> it rather than <c>start</c> it, depending on the
+ application's <c>start type</c>:
+ If <c>Type = load</c>, the application is only loaded.
+ If <c>Type = none</c>, the application is not loaded and not
+ started, although the code for its modules is loaded.
+ </p>
</section>
<section>
diff --git a/lib/sasl/doc/src/error_logging.xml b/lib/sasl/doc/src/error_logging.xml
index 4b2c960bbb..e6c244c1b9 100644
--- a/lib/sasl/doc/src/error_logging.xml
+++ b/lib/sasl/doc/src/error_logging.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,22 +32,52 @@
<rev>B</rev>
<file>error_logging.xml</file>
</header>
+ <note>
+ <p>The SASL error logging concept described in this section is
+ deprecated since Erlang/OTP 21.0, when the
+ new <seealso marker="kernel:logger_chapter">logging
+ API</seealso> was introduced.</p>
+ <p>The new default behaviour is that the SASL application no
+ longer affects which log events that are logged.
+ <seealso marker="#supervisor_report">Supervisor
+ reports</seealso> and <seealso marker="#crash_report">crash
+ reports</seealso> are logged via the default logger handler
+ which is setup by
+ Kernel. <seealso marker="#progress_report">Progress
+ reports</seealso> are by default not logged, but can be enabled
+ by setting the primary log level to <c>info</c>, for example by
+ using the Kernel configuration
+ parameter <seealso marker="kernel:kernel_app#logger_level">
+ <c>logger_level</c></seealso>.</p>
+ <p>The old SASL error logging behaviour can be re-enabled by setting the
+ Kernel configuration
+ parameter <seealso marker="kernel:kernel_app#logger_sasl_compatible">
+ <c>logger_sasl_compatible</c></seealso> to <c>true</c>.</p>
+ <p>The mechanism
+ for <seealso marker="#multi_file_logging">multi-file error report
+ logging</seealso> as described in this section is also kept for
+ backwards compatibility. However, the new logging API also
+ introduces <seealso marker="kernel:logger_disk_log_h">
+ <c>logger_disk_log_h(3)</c></seealso>, which is a logger
+ handler that can print to multiple files
+ using <seealso marker="kernel:disk_log"><c>disk_log(3)</c></seealso>.</p>
+ </note>
+
+ <section>
+ <title>SASL reports</title>
<p>The SASL application introduces three types of reports:</p>
<list type="bulleted">
<item>Supervisor report</item>
<item>Progress report</item>
<item>Crash report</item>
</list>
- <p>When the SASL application is started, it adds a handler that
- formats and writes these reports, as specified in the configuration
- parameters for SASL, that is, the environment variables
- in the SASL application specification, which is found in the
- <c>.app</c> file of SASL. For details, see the
- <seealso marker="sasl_app"><c>sasl(6)</c></seealso> application in the
- Reference Manual and the <seealso marker="kernel:app"><c>app(4)</c></seealso>
- file in the Kernel Reference Manual.</p>
+ <p>When the SASL application is started, it adds a Logger handler
+ that formats and writes these reports, as specified in
+ the <seealso marker="sasl_app#deprecated_error_logger_config">configuration
+ parameters for SASL</seealso>.</p>
<section>
+ <marker id="supervisor_report"/>
<title>Supervisor Report</title>
<p>A supervisor report is issued when a supervised child terminates
unexpectedly. A supervisor report contains the following
@@ -68,6 +98,7 @@
</section>
<section>
+ <marker id="progress_report"/>
<title>Progress Report</title>
<p>A progress report is issued when a supervisor starts or
restarts a child. A progress report contains the following items:</p>
@@ -82,6 +113,7 @@
</section>
<section>
+ <marker id="crash_report"/>
<title>Crash Report</title>
<p>Processes started with functions
<seealso marker="stdlib:proc_lib#spawn/1"><c>proc_lib:spawn</c></seealso> or
@@ -105,6 +137,7 @@
crash. The information gathered is the same as the information
for Crasher, described in the previous item.</p></item>
</taglist>
+ </section>
<section>
<title>Example</title>
@@ -163,6 +196,7 @@
</section>
<section>
+ <marker id="multi_file_logging"/>
<title>Multi-File Error Report Logging</title>
<p>Multi-file error report logging is used to store error messages
received by <c>error_logger</c>. The error messages
@@ -171,7 +205,8 @@
of files exist at the same time. The logging is very fast, as
each error message is written as a binary term.</p>
<p>For more details, see the
- <seealso marker="sasl_app"><c>sasl(6)</c></seealso>
+ <seealso marker="sasl_app#deprecated_error_logger_config">
+ <c>sasl(6)</c></seealso>
application in the Reference Manual.</p>
</section>
diff --git a/lib/sasl/doc/src/fascicules.xml b/lib/sasl/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/sasl/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/sasl/doc/src/note.gif b/lib/sasl/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/sasl/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/sasl/doc/src/notes.xml b/lib/sasl/doc/src/notes.xml
index bc35939d7e..fce032136d 100644
--- a/lib/sasl/doc/src/notes.xml
+++ b/lib/sasl/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,178 @@
</header>
<p>This document describes the changes made to the SASL application.</p>
+<section><title>SASL 3.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SASL 3.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>A new logging API is added to Erlang/OTP, see the
+ <seealso
+ marker="kernel:logger"><c>logger(3)</c></seealso> manual
+ page, and section <seealso
+ marker="kernel:logger_chapter">Logging</seealso> in the
+ Kernel User's Guide.</p>
+ <p>Calls to <c>error_logger</c> are automatically
+ redirected to the new API, and legacy error logger event
+ handlers can still be used. It is, however, recommended
+ to use the Logger API directly when writing new code.</p>
+ <p>Notice the following potential incompatibilities:</p>
+ <list> <item><p>Kernel configuration parameters
+ <c>error_logger</c> still works, but is overruled if the
+ default handler's output destination is configured with
+ Kernel configuration parameter <c>logger</c>.</p> <p>In
+ general, parameters for configuring error logger are
+ overwritten by new parameters for configuring
+ Logger.</p></item> <item><p>The concept of SASL error
+ logging is deprecated, meaning that by default the SASL
+ application does not affect which log events are
+ logged.</p> <p>By default, supervisor reports and crash
+ reports are logged by the default Logger handler started
+ by Kernel, and end up at the same destination (terminal
+ or file) as other standard log event from Erlang/OTP.</p>
+ <p>Progress reports are not logged by default, but can be
+ enabled by setting the primary log level to info, for
+ example with the Kernel configuration parameter
+ <c>logger_level</c>.</p> <p>To obtain backwards
+ compatibility with the SASL error logging functionality
+ from earlier releases, set Kernel configuration parameter
+ <c>logger_sasl_compatible</c> to <c>true</c>. This
+ prevents the default Logger handler from logging any
+ supervisor-, crash-, or progress reports. Instead, SASL
+ adds a separate Logger handler during application start,
+ which takes care of these log events. The SASL
+ configuration parameters <c>sasl_error_logger</c> and
+ <c>sasl_errlog_type</c> specify the destination (terminal
+ or file) and severity level to log for these
+ events.</p></item></list>
+ <p>
+ Since Logger is new in Erlang/OTP 21.0, we do reserve the
+ right to introduce changes to the Logger API and
+ functionality in patches following this release. These
+ changes might or might not be backwards compatible with
+ the initial version.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-13295</p>
+ </item>
+ <item>
+ <p>
+ The old and outdated "Status Inspection" tool (modules
+ <c>si</c> and <c>si_sasl_sup</c>) is removed.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-14469</p>
+ </item>
+ <item>
+ <p>
+ When creating the release tar file, systools now includes
+ sys.config.src if it exists in the
+ $ROOT/releases/&lt;vsn&gt;/ directory. This is to allow
+ adjustments, e.g. resolving environment variables, after
+ unpacking the release, but before installing it. This
+ functionality requires a custom tool which uses
+ sys.config.src as input and creates a correct sys.config
+ file.</p>
+ <p>
+ Own Id: OTP-14950 Aux Id: PR-1560 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SASL 3.1.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ When upgrading with instruction 'restart_new_emulator',
+ the generated temporary boot file used 'kernelProcess'
+ statements from the old release instead of the new
+ release. This is now corrected.</p>
+ <p>
+ This correction is needed for upgrade to OTP-21.</p>
+ <p>
+ Own Id: OTP-15017</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SASL 3.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The Report Browser, rb, could earlier not handle reports
+ that were not lists, for example generated by
+ <c>error_logger:info_report({some, tuple})</c>. This term
+ is allowed as input to error_logger, but rb would state
+ that "A report on bad form was encountered". This is now
+ corrected.</p>
+ <p>
+ Own Id: OTP-13906 Aux Id: ERL-261 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SASL 3.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ General Unicode improvements.</p>
+ <p>
+ Own Id: OTP-14462</p>
+ </item>
+ <item>
+ <p>
+ Files generated by <c>release_handler</c> and
+ <c>reltool</c>, which might contain Unicode characters,
+ are now encoded as UTF-8 and written with format "~tp" or
+ "~ts". If the file is to be read by
+ <c>file:consult/1</c>, an encoding comment is added.</p>
+ <p>
+ Own Id: OTP-14463</p>
+ </item>
+ <item>
+ <p>
+ The SASL error logger event handler,
+ <c>sasl_report_file_h</c>, will now by default open its
+ log file with encoding UTF-8. This can be overridden when
+ configuring SASL, see configuration parameter
+ <c>sasl_error_logger</c> in the SASL reference manual.</p>
+ <p>
+ Own Id: OTP-14618</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SASL 3.0.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/sasl/doc/src/part_notes.xml b/lib/sasl/doc/src/part_notes.xml
deleted file mode 100644
index 8a32deefd9..0000000000
--- a/lib/sasl/doc/src/part_notes.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>SASL Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p>The System Architecture Support Libraries, <em>SASL</em>,
- provides support for alarm and release handling etc.</p>
- <p>For information about older versions, see
- <url href="part_notes_history_frame.html">Release Notes History</url>.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/sasl/doc/src/part_notes_history.xml b/lib/sasl/doc/src/part_notes_history.xml
deleted file mode 100644
index abdf09d845..0000000000
--- a/lib/sasl/doc/src/part_notes_history.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2006</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>SASL Release Notes History</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p>The System Architecture Support Libraries, <em>SASL</em>,
- provides support for alarm and release handling etc.</p>
- </description>
- <include file="notes_history"></include>
-</part>
-
diff --git a/lib/sasl/doc/src/release_handler.xml b/lib/sasl/doc/src/release_handler.xml
index 8f073807fb..9ba276aeac 100644
--- a/lib/sasl/doc/src/release_handler.xml
+++ b/lib/sasl/doc/src/release_handler.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -61,6 +61,7 @@
<list type="bulleted">
<item>A release upgrade file, <c>relup</c></item>
<item>A system configuration file, <c>sys.config</c></item>
+ <item>A system configuration source file, <c>sys.config.src</c></item>
</list>
<p>The <c>relup</c> file contains instructions for how to upgrade
to, or downgrade from, this version of the release.</p>
@@ -819,4 +820,3 @@ release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
<seealso marker="systools"><c>systools(3)</c></seealso></p>
</section>
</erlref>
-
diff --git a/lib/sasl/doc/src/sasl_app.xml b/lib/sasl/doc/src/sasl_app.xml
index 0576397f9b..fc83f63fe6 100644
--- a/lib/sasl/doc/src/sasl_app.xml
+++ b/lib/sasl/doc/src/sasl_app.xml
@@ -4,7 +4,7 @@
<appref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,12 +34,9 @@
<p>The SASL application provides the following services:</p>
<list type="bulleted">
<item><c>alarm_handler</c></item>
- <item><c>rb</c></item>
<item><c>release_handler</c></item>
<item><c>systools</c></item>
</list>
- <p>The SASL application also includes <c>error_logger</c> event
- handlers for formatting SASL error and crash reports.</p>
<note>
<p>The SASL application in OTP has nothing to do with
"Simple Authentication and Security Layer" (RFC 4422).</p>
@@ -47,51 +44,101 @@
</description>
<section>
- <title>Error Logger Event Handlers</title>
- <p>The following error logger event handlers are used by
- the SASL application.</p>
+ <title>Configuration</title>
+ <p>The following configuration parameters are defined for the SASL
+ application. For more information about configuration parameters, see
+ <seealso marker="kernel:app"><c>app(4)</c></seealso> in Kernel.</p>
+ <p>All configuration parameters are optional.</p>
+ <taglist>
+ <tag><c><![CDATA[start_prg = string() ]]></c></tag>
+ <item>
+ <p>Specifies the program to be used when restarting the system
+ during release installation. Default is
+ <c>$OTP_ROOT/bin/start</c>.</p>
+ </item>
+ <tag><c><![CDATA[masters = [atom()] ]]></c></tag>
+ <item>
+ <p>Specifies the nodes used by this node to read/write release
+ information. This parameter is ignored if parameter
+ <c>client_directory</c> is not set.</p>
+ </item>
+ <tag><c><![CDATA[client_directory = string() ]]></c></tag>
+ <item>
+ <p>This parameter specifies the client directory at the master
+ nodes. For details, see
+ <seealso marker="doc/design_principles:release_handling">Release Handling</seealso>
+ in <em>OTP Design Principles</em>. This parameter is
+ ignored if parameter <c>masters</c> is not set.</p>
+ </item>
+ <tag><c><![CDATA[static_emulator = true | false ]]></c></tag>
+ <item>
+ <p>Indicates if the Erlang emulator is statically installed. A
+ node with a static emulator cannot switch dynamically to a
+ new emulator, as the executable files are written into memory
+ statically. This parameter is ignored if parameters <c>masters</c>
+ and <c>client_directory</c> are not set.</p>
+ </item>
+ <tag><c><![CDATA[releases_dir = string() ]]></c></tag>
+ <item>
+ <p>Indicates where the <c>releases</c> directory is located.
+ The release handler writes all its files to this directory.
+ If this parameter is not set, the OS environment parameter
+ <c>RELDIR</c> is used. By default, this is
+ <c>$OTP_ROOT/releases</c>.</p>
+ </item>
+ </taglist>
+ </section>
+
+ <section>
+ <marker id="deprecated_error_logger_config"/>
+ <title>Deprecated Error Logger Event Handlers and Configuration</title>
+ <p>In Erlang/OTP 21.0, a new API for logging was added. The
+ old <c>error_logger</c> event manager, and event handlers
+ running on this manager, still work, but they are not used
+ by default.</p>
+ <p>The error logger event handlers <c>sasl_report_tty_h</c>
+ and <c>sasl_report_file_h</c>, were earlier used for printing
+ the so called SASL reports, i.e. <em>supervisor
+ reports</em>, <em>crash reports</em>, and <em>progress
+ reports</em>. These reports are now also printed by the default
+ logger handler started by the Kernel application. Progress
+ reports are by default stopped by the primary log level, but can
+ be enabled by setting this level to <c>info</c>, for example by
+ using the Kernel configuration
+ parameter <seealso marker="kernel:kernel_app#logger_level">
+ <c>logger_level</c></seealso>.</p>
+ <p>If the old error logger event handlers are still desired, they
+ must be added by
+ calling <c>error_logger:add_report_handler/1,2</c>.</p>
<taglist>
<tag><c>sasl_report_tty_h</c></tag>
<item>
<p>Formats and writes <em>supervisor reports</em>, <em>crash
reports</em>, and <em>progress reports</em> to <c>stdio</c>.
This error logger event handler uses
- <seealso marker="kernel:kernel_app#error_logger_format_depth">error_logger_format_depth</seealso>
- in the Kernel application to limit how much detail is
- printed in crash and supervisor reports.</p>
+ <seealso marker="kernel:kernel_app#deprecated-configuration-parameters"><c>error_logger_format_depth</c></seealso>
+ in the Kernel application to limit how much detail is printed
+ in crash and supervisor reports.</p>
</item>
<tag><c>sasl_report_file_h</c></tag>
<item>
<p>Formats and writes <em>supervisor reports</em>, <em>crash
report</em>, and <em>progress report</em> to a single file.
This error logger event handler uses
- <seealso marker="kernel:kernel_app#error_logger_format_depth">error_logger_format_depth</seealso>
- in the Kernel application to limit the details
- printed in crash and supervisor reports.</p>
- </item>
- <tag><c>log_mf_h</c></tag>
- <item>
- <p>This error logger writes <em>all</em> events sent to the
- error logger to disk. Multiple files and log rotation are
- used. For efficiency reasons, each event is written as a
- binary. For more information about this handler,
- see <seealso marker="stdlib:log_mf_h">the STDLIB Reference
- Manual</seealso>.</p>
- <p>To activate this event handler, three SASL
- configuration parameters must be set,
- <c>error_logger_mf_dir</c>, <c>error_logger_mf_maxbytes</c>,
- and <c>error_logger_mf_maxfiles</c>. The next section provides
- more information about the configuration parameters.</p>
+ <seealso marker="kernel:kernel_app#deprecated-configuration-parameters"><c>error_logger_format_depth</c></seealso>
+ in the Kernel application to limit the details printed in
+ crash and supervisor reports.</p>
</item>
</taglist>
- </section>
-
- <section>
- <title>Configuration</title>
- <p>The following configuration parameters are defined for the SASL
- application. For more information about configuration parameters, see
- <seealso marker="kernel:app"><c>app(4)</c></seealso> in Kernel.</p>
- <p>All configuration parameters are optional.</p>
+ <p>A similar behaviour, but still using the new logger API, can be
+ obtained by setting the Kernel application environment
+ variable <seealso marker="kernel:kernel_app#logger_sasl_compatible">
+ <c>logger_sasl_compatible</c></seealso> to <c>true</c>. This
+ adds a second instance of the standard Logger handler,
+ named <c>sasl</c>, which only prints the SASL reports. No SASL
+ reports are then printed by the Kernel logger handler.</p>
+ <p>The <c>sasl</c> handler is configured according to the values
+ of the following SASL application environment variables.</p>
<taglist>
<tag><c><![CDATA[sasl_error_logger = Value ]]></c></tag>
<item>
@@ -103,13 +150,16 @@
<tag><c>{file,FileName}</c></tag>
<item><p>Installs <c>sasl_report_file_h</c> in the error logger.
All reports go to file <c>FileName</c>, which is a
- string.</p></item>
+ string. The file is opened in <c>write</c> mode with encoding
+ <c>utf8</c>.</p></item>
<tag><c>{file,FileName,Modes}</c></tag>
<item><p>Same as <c>{file,FileName}</c>, except that <c>Modes</c>
allows you to specify the modes used for opening the <c>FileName</c>
given to the <seealso marker="kernel:file#open/2">file:open/2</seealso>
- call. When not specified, <c>Modes</c> defaults to <c>[write]</c>.
- Use <c>[append]</c> to have the <c>FileName</c> open in append mode.
+ call. By default, the file is opened in <c>write</c> mode
+ with encoding <c>utf8</c>. Use <c>[append]</c> to have
+ the <c>FileName</c> open in append mode. A different
+ encoding can also be specified.
<c>FileName</c> is a string.</p></item>
<tag><c>false</c></tag>
<item><p>No SASL error logger handler is installed.</p></item>
@@ -121,6 +171,25 @@
<c>sasl_error_logger</c> to error reports or progress reports,
or both. Default is <c>all</c>.</p>
</item>
+ <tag><marker id="utc_log"/><c><![CDATA[utc_log = true | false ]]></c></tag>
+ <item>
+ <p>If set to <c>true</c>, all dates in textual log outputs are
+ displayed in Universal Coordinated Time with the string
+ <c>UTC</c> appended.</p>
+ </item>
+ </taglist>
+
+ <p>The error logger event handler <c>log_mf_h</c> can also still
+ be used. This event handler writes <em>all</em> events sent to
+ the error logger to disk. Multiple files and log rotation are
+ used. For efficiency reasons, each event is written as a
+ binary. For more information about this handler,
+ see <seealso marker="stdlib:log_mf_h">the STDLIB Reference
+ Manual</seealso>.</p>
+ <p>To activate this event handler, three SASL configuration
+ parameters must be
+ set:</p>
+ <taglist>
<tag><c><![CDATA[error_logger_mf_dir = string() | false ]]></c></tag>
<item>
<p>Specifies in which directory <c>log_mf_h</c> is to store
@@ -139,55 +208,19 @@
this parameter is undefined, the <c>log_mf_h</c> handler is
not installed.</p>
</item>
- <tag><c><![CDATA[start_prg = string() ]]></c></tag>
- <item>
- <p>Specifies the program to be used when restarting the system
- during release installation. Default is
- <c>$OTP_ROOT/bin/start</c>.</p>
- </item>
- <tag><c><![CDATA[masters = [atom()] ]]></c></tag>
- <item>
- <p>Specifies the nodes used by this node to read/write release
- information. This parameter is ignored if parameter
- <c>client_directory</c> is not set.</p>
- </item>
- <tag><c><![CDATA[client_directory = string() ]]></c></tag>
- <item>
- <p>This parameter specifies the client directory at the master
- nodes. For details, see
- <seealso marker="doc/design_principles:release_handling">Release Handling</seealso>
- in <em>OTP Design Principles</em>. This parameter is
- ignored if parameter <c>masters</c> is not set.</p>
- </item>
- <tag><c><![CDATA[static_emulator = true | false ]]></c></tag>
- <item>
- <p>Indicates if the Erlang emulator is statically installed. A
- node with a static emulator cannot switch dynamically to a
- new emulator, as the executable files are written into memory
- statically. This parameter is ignored if parameters <c>masters</c>
- and <c>client_directory</c> are not set.</p>
- </item>
- <tag><c><![CDATA[releases_dir = string() ]]></c></tag>
- <item>
- <p>Indicates where the <c>releases</c> directory is located.
- The release handler writes all its files to this directory.
- If this parameter is not set, the OS environment parameter
- <c>RELDIR</c> is used. By default, this is
- <c>$OTP_ROOT/releases</c>.</p>
- </item>
- <tag><c><![CDATA[utc_log = true | false ]]></c></tag>
- <item>
- <p>If set to <c>true</c>, all dates in textual log outputs are
- displayed in Universal Coordinated Time with the string
- <c>UTC</c> appended.</p>
- </item>
</taglist>
+ <p>The new <seealso marker="kernel:logger_disk_log_h">
+ <c>logger_disk_log_h</c></seealso> might be an alternative
+ to <c>log_mf_h</c> if log rotation is desired. This does,
+ however, write the log events in clear text and not as binaries.</p>
+
</section>
<section>
<title>See Also</title>
<p><seealso marker="alarm_handler"><c>alarm_handler(3)</c></seealso>,
<seealso marker="kernel:error_logger"><c>error_logger(3)</c></seealso>,
+ <seealso marker="kernel:logger"><c>logger(3)</c></seealso>,
<seealso marker="stdlib:log_mf_h"><c>log_mf_h(3)</c></seealso>,
<seealso marker="rb"><c>rb(3)</c></seealso>,
<seealso marker="release_handler"><c>release_handler(3)</c></seealso>,
diff --git a/lib/sasl/doc/src/systools.xml b/lib/sasl/doc/src/systools.xml
index e7c3c499da..4842c732b1 100644
--- a/lib/sasl/doc/src/systools.xml
+++ b/lib/sasl/doc/src/systools.xml
@@ -349,10 +349,11 @@ myapp-1/ebin/myapp.app
the release version as specified in <c>Name.rel</c>.</p>
<p><c>releases/RelVsn</c> contains the boot script
<c>Name.boot</c> renamed to <c>start.boot</c> and, if found,
- the files <c>relup</c> and <c>sys.config</c>. These files
+ the files <c>relup</c> and <c>sys.config</c> or <c>sys.config.src</c>. These files
are searched for in the same directory as <c>Name.rel</c>,
in the current working directory, and in any directories
- specified using option <c>path</c>.</p>
+ specified using option <c>path</c>. In the case of <c>sys.config</c>
+ it is not included if <c>sys.config.src</c> is found.</p>
<p>If the release package is to contain a new Erlang runtime
system, the <c>bin</c> directory of the specified runtime
system <c>{erts,Dir}</c> is copied to <c>erts-ErtsVsn/bin</c>.</p>
@@ -397,4 +398,3 @@ myapp-1/ebin/myapp.app
<seealso marker="script"><c>script(4)</c></seealso></p>
</section>
</erlref>
-
diff --git a/lib/sasl/doc/src/warning.gif b/lib/sasl/doc/src/warning.gif
deleted file mode 100644
index 96af52360e..0000000000
--- a/lib/sasl/doc/src/warning.gif
+++ /dev/null
Binary files differ
diff --git a/lib/sasl/src/Makefile b/lib/sasl/src/Makefile
index ac7ee51100..7338bdf016 100644
--- a/lib/sasl/src/Makefile
+++ b/lib/sasl/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2016. All Rights Reserved.
+# Copyright Ericsson AB 1996-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/sasl-$(VSN)
MODULES= alarm_handler sasl sasl_report \
sasl_report_file_h sasl_report_tty_h format_lib_supp \
misc_supp rb rb_format_supp release_handler \
- release_handler_1 si si_sasl_supp systools \
+ release_handler_1 systools \
systools_make systools_rc systools_relup systools_lib \
erlsrv
diff --git a/lib/sasl/src/erlsrv.erl b/lib/sasl/src/erlsrv.erl
index 29d40d362f..e0bbd37ee3 100644
--- a/lib/sasl/src/erlsrv.erl
+++ b/lib/sasl/src/erlsrv.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@ erlsrv(EVer) ->
filename:join([Root, "erts-" ++ EVer, "bin", "erlsrv.exe"]).
current_version() ->
- hd(string:tokens(erlang:system_info(version),"_ ")).
+ hd(string:lexemes(erlang:system_info(version),"_ ")).
%%% Returns {ok, Output} | failed | {error, Reason}
run_erlsrv(Command) ->
@@ -107,7 +107,7 @@ get_all_services() ->
[];
{ok, [_H|T]} ->
F = fun(X) ->
- hd(string:tokens(X,"\t "))
+ hd(string:lexemes(X,"\t "))
end,
lists:map(F,T);
_ ->
@@ -191,8 +191,8 @@ get_service(EVer, ServiceName) ->
%%% have in the environment list...
EnvParts = lists:map(
fun(S) ->
- X = string:strip(S,left,$\t),
- case hd(string:tokens(X,"=")) of
+ X = string:trim(S, leading, "$\t"),
+ case hd(string:lexemes(X,"=")) of
X ->
%% Can this happen?
{X,""};
@@ -371,7 +371,7 @@ split_arglist([H|T]) ->
parse_arglist(Str) ->
lists:reverse(parse_arglist(Str,[])).
parse_arglist(Str,Accum) ->
- Stripped = string:strip(Str,left),
+ Stripped = string:trim(Str, leading),
case length(Stripped) of
0 ->
Accum;
@@ -432,14 +432,9 @@ split_by_env(Data) ->
splitline(Line) ->
- case string:chr(Line,$:) of
- 0 ->
+ case string:split(Line, ":") of
+ [_] ->
{Line, ""};
- N ->
- case length(string:substr(Line,N)) of
- 1 ->
- {string:substr(Line,1,N-1),""};
- _ ->
- {string:substr(Line,1,N-1),string:substr(Line,N+2)}
- end
+ [N, V] ->
+ {N, string:slice(V, 1)}
end.
diff --git a/lib/sasl/src/format_lib_supp.erl b/lib/sasl/src/format_lib_supp.erl
index 80dcdc91da..2d37dfe117 100644
--- a/lib/sasl/src/format_lib_supp.erl
+++ b/lib/sasl/src/format_lib_supp.erl
@@ -86,8 +86,10 @@ print_data(Device, Line, [{Key, Value}|T]) ->
print_data(Device, Line, [Value|T]) ->
Modifier = misc_supp:modifier(Device),
io:format(Device, "~"++Modifier++"p~n", [Value]),
- print_data(Device, Line, T).
-
+ print_data(Device, Line, T);
+print_data(Device, _Line, Value) ->
+ Modifier = misc_supp:modifier(Device),
+ io:format(Device, "~"++Modifier++"p~n", [Value]).
print_items(Device, Line, {Name, Items}) ->
print_items(Device, Line, Name, Items).
@@ -100,13 +102,13 @@ print_newlines(Device, N) when N > 0 ->
print_one_line(Device, Line, Key, Value) ->
Modifier = misc_supp:modifier(Device),
StrKey = term_to_string(Key,Modifier),
- KeyLen = lists:min([length(StrKey), Line]),
+ KeyLen = lists:min([string:length(StrKey), Line]),
ValueLen = Line - KeyLen,
Format1 = lists:concat(["~-", KeyLen, Modifier, "s"]),
Format2 = lists:concat(["~", ValueLen, Modifier, "s~n"]),
io:format(Device, Format1, [StrKey]),
Try = term_to_string(Value,Modifier),
- Length = length(Try),
+ Length = string:length(Try),
if
Length < ValueLen ->
io:format(Device, Format2, [Try]);
@@ -117,7 +119,7 @@ print_one_line(Device, Line, Key, Value) ->
end.
term_to_string(Value,Modifier) ->
- lists:flatten(io_lib:format(get_format(Value,Modifier), [Value])).
+ io_lib:format(get_format(Value,Modifier), [Value]).
get_format([],_) ->
"~p";
diff --git a/lib/sasl/src/rb.erl b/lib/sasl/src/rb.erl
index 6595d29a9c..28829132a1 100644
--- a/lib/sasl/src/rb.erl
+++ b/lib/sasl/src/rb.erl
@@ -586,14 +586,14 @@ find_widths([], _Modifier, DescrWidth, DateWidth, Data) ->
{DescrWidth+1, DateWidth+1, lists:reverse(Data)};
find_widths([H|T], Modifier, DescrWidth, DateWidth, Data) ->
DescrTerm = element(3,H),
- Descr = lists:flatten(io_lib:format("~"++Modifier++"w", [DescrTerm])),
- DescrTry = length(Descr),
+ Descr = io_lib:format("~"++Modifier++"w", [DescrTerm]),
+ DescrTry = string:length(Descr),
NewDescrWidth =
if
DescrTry > DescrWidth -> DescrTry;
true -> DescrWidth
end,
- DateTry = length(element(4, H)),
+ DateTry = string:length(element(4, H)),
NewDateWitdh =
if
DateTry > DateWidth -> DateTry;
diff --git a/lib/sasl/src/rb_format_supp.erl b/lib/sasl/src/rb_format_supp.erl
index 1eda43dae4..b5b7aba151 100644
--- a/lib/sasl/src/rb_format_supp.erl
+++ b/lib/sasl/src/rb_format_supp.erl
@@ -108,7 +108,7 @@ print(Date, Report, Device) ->
format_h(Line, Header, Pid, Date) ->
NHeader = lists:flatten(io_lib:format("~s ~w", [Header, Pid])),
- DateLen = length(Date),
+ DateLen = string:length(Date),
HeaderLen = Line - DateLen,
Format = lists:concat(["~-", HeaderLen, "s~", DateLen, "s"]),
io_lib:format(Format, [NHeader, Date]).
diff --git a/lib/sasl/src/release_handler.erl b/lib/sasl/src/release_handler.erl
index 1f3c6877d5..7570b74c1a 100644
--- a/lib/sasl/src/release_handler.erl
+++ b/lib/sasl/src/release_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -420,7 +420,7 @@ upgrade_app(App, NewDir) ->
%% located in the ebin dir of the _current_ version
%%-----------------------------------------------------------------
downgrade_app(App, OldDir) ->
- case string:tokens(filename:basename(OldDir), "-") of
+ case string:lexemes(filename:basename(OldDir), "-") of
[_AppS, OldVsn] ->
downgrade_app(App, OldVsn, OldDir);
_ ->
@@ -1052,8 +1052,8 @@ new_emulator_make_tmp_release(CurrentRelease,ToRelease,RelDir,Opts,Masters) ->
ToVsn = ToRelease#release.vsn,
TmpVsn = ?tmp_vsn(CurrentVsn),
case get_base_libs(ToRelease#release.libs) of
- {ok,{Kernel,Stdlib,Sasl}=BaseLibs,_} ->
- case get_base_libs(ToRelease#release.libs) of
+ {ok,{Kernel,Stdlib,Sasl},_} ->
+ case get_base_libs(CurrentRelease#release.libs) of
{ok,_,RestLibs} ->
TmpErtsVsn = ToRelease#release.erts_vsn,
TmpLibs = [Kernel,Stdlib,Sasl|RestLibs],
@@ -1062,7 +1062,7 @@ new_emulator_make_tmp_release(CurrentRelease,ToRelease,RelDir,Opts,Masters) ->
libs = TmpLibs,
status = unpacked},
new_emulator_make_hybrid_boot(CurrentVsn,ToVsn,TmpVsn,
- BaseLibs,RelDir,Opts,Masters),
+ RelDir,Opts,Masters),
new_emulator_make_hybrid_config(CurrentVsn,ToVsn,TmpVsn,
RelDir,Masters),
{TmpVsn,TmpRelease};
@@ -1095,7 +1095,7 @@ get_base_libs([],_Kernel,_Stdlib,undefined,_Rest) ->
get_base_libs([],Kernel,Stdlib,Sasl,Rest) ->
{ok,{Kernel,Stdlib,Sasl},lists:reverse(Rest)}.
-new_emulator_make_hybrid_boot(CurrentVsn,ToVsn,TmpVsn,BaseLibs,RelDir,Opts,Masters) ->
+new_emulator_make_hybrid_boot(CurrentVsn,ToVsn,TmpVsn,RelDir,Opts,Masters) ->
FromBootFile = filename:join([RelDir,CurrentVsn,"start.boot"]),
ToBootFile = filename:join([RelDir,ToVsn,"start.boot"]),
TmpBootFile = filename:join([RelDir,TmpVsn,"start.boot"]),
@@ -1103,11 +1103,7 @@ new_emulator_make_hybrid_boot(CurrentVsn,ToVsn,TmpVsn,BaseLibs,RelDir,Opts,Maste
Args = [ToVsn,Opts],
{ok,FromBoot} = read_file(FromBootFile,Masters),
{ok,ToBoot} = read_file(ToBootFile,Masters),
- {{_,_,KernelPath},{_,_,StdlibPath},{_,_,SaslPath}} = BaseLibs,
- Paths = {filename:join(KernelPath,"ebin"),
- filename:join(StdlibPath,"ebin"),
- filename:join(SaslPath,"ebin")},
- case systools_make:make_hybrid_boot(TmpVsn,FromBoot,ToBoot,Paths,Args) of
+ case systools_make:make_hybrid_boot(TmpVsn,FromBoot,ToBoot,Args) of
{ok,TmpBoot} ->
write_file(TmpBootFile,TmpBoot,Masters);
{error,Reason} ->
@@ -1143,8 +1139,9 @@ new_emulator_make_hybrid_config(CurrentVsn,ToVsn,TmpVsn,RelDir,Masters) ->
Config2 = replace_config(stdlib,Config1,Stdlib),
Config3 = replace_config(sasl,Config2,Sasl),
- ConfigStr = io_lib:format("~p.~n",[Config3]),
- write_file(TmpFile,ConfigStr,Masters).
+ ConfigStr = io_lib:format("%% ~s~n~tp.~n",
+ [epp:encoding_to_string(utf8),Config3]),
+ write_file(TmpFile,unicode:characters_to_binary(ConfigStr),Masters).
%% Take the configuration for application App from the new config and
%% insert in the old config.
@@ -1173,8 +1170,8 @@ new_emulator_rm_tmp_release(_,_,_,_,Releases,_) ->
%% Rename the tempoarary service (for erts ugprade) to the real ToVsn
rename_tmp_service(EVsn,TmpVsn,NewVsn) ->
- FromName = hd(string:tokens(atom_to_list(node()),"@")) ++ "_" ++ TmpVsn,
- ToName = hd(string:tokens(atom_to_list(node()),"@")) ++ "_" ++ NewVsn,
+ FromName = hd(string:lexemes(atom_to_list(node()),"@")) ++ "_" ++ TmpVsn,
+ ToName = hd(string:lexemes(atom_to_list(node()),"@")) ++ "_" ++ NewVsn,
case erlsrv:get_service(EVsn,ToName) of
{error, _Error} ->
ok;
@@ -1206,9 +1203,9 @@ rename_service(EVsn,FromName,ToName) ->
%%% in which case we try to rename the old service to the new name and try
%%% to update heart's view of what service we are really running.
do_make_services_permanent(PermanentVsn,Vsn, PermanentEVsn, EVsn) ->
- PermName = hd(string:tokens(atom_to_list(node()),"@"))
+ PermName = hd(string:lexemes(atom_to_list(node()),"@"))
++ "_" ++ PermanentVsn,
- Name = hd(string:tokens(atom_to_list(node()),"@"))
+ Name = hd(string:lexemes(atom_to_list(node()),"@"))
++ "_" ++ Vsn,
case erlsrv:get_service(EVsn,Name) of
{error, _Error} ->
@@ -1295,7 +1292,7 @@ do_make_permanent(#state{releases = Releases,
do_back_service(OldVersion, CurrentVersion,OldEVsn,CurrentEVsn) ->
- NN = hd(string:tokens(atom_to_list(node()),"@")),
+ NN = hd(string:lexemes(atom_to_list(node()),"@")),
OldName = NN ++ "_" ++ OldVersion,
CurrentName = NN ++ "_" ++ CurrentVersion,
UpdData = case erlsrv:get_service(CurrentEVsn,CurrentName) of
@@ -1384,7 +1381,7 @@ do_remove_service(Vsn) ->
%% Very unconditionally remove the service.
%% Note that the service could already have been removed when
%% making another release permanent.
- ServiceName = hd(string:tokens(atom_to_list(node()),"@"))
+ ServiceName = hd(string:lexemes(atom_to_list(node()),"@"))
++ "_" ++ Vsn,
case erlsrv:get_service(ServiceName) of
{error, _Error} ->
@@ -1669,9 +1666,9 @@ flush() ->
prepare_restart_nt(#release{erts_vsn = EVsn, vsn = Vsn},
#release{erts_vsn = PermEVsn, vsn = PermVsn},
DataFileName) ->
- CurrentServiceName = hd(string:tokens(atom_to_list(node()),"@"))
+ CurrentServiceName = hd(string:lexemes(atom_to_list(node()),"@"))
++ "_" ++ PermVsn,
- FutureServiceName = hd(string:tokens(atom_to_list(node()),"@"))
+ FutureServiceName = hd(string:lexemes(atom_to_list(node()),"@"))
++ "_" ++ Vsn,
CurrentService = case erlsrv:get_service(PermEVsn,CurrentServiceName) of
{error, _} = Error1 ->
@@ -1874,9 +1871,10 @@ write_releases_1(Dir, NewReleases, Masters) ->
write_releases_m(Dir, NewReleases, Masters).
do_write_release(Dir, RELEASES, NewReleases) ->
- case file:open(filename:join(Dir, RELEASES), [write]) of
+ case file:open(filename:join(Dir, RELEASES), [write,{encoding,utf8}]) of
{ok, Fd} ->
- ok = io:format(Fd, "~p.~n", [NewReleases]),
+ ok = io:format(Fd, "%% ~s~n~tp.~n",
+ [epp:encoding_to_string(utf8),NewReleases]),
ok = file:close(Fd);
{error, Reason} ->
{error, Reason}
diff --git a/lib/sasl/src/sasl.app.src b/lib/sasl/src/sasl.app.src
index 633cdfa070..688aff16f1 100644
--- a/lib/sasl/src/sasl.app.src
+++ b/lib/sasl/src/sasl.app.src
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,8 +32,6 @@
sasl_report,
sasl_report_tty_h,
sasl_report_file_h,
- si,
- si_sasl_supp,
systools,
systools_make,
systools_rc,
@@ -42,9 +40,8 @@
]},
{registered, [sasl_sup, alarm_handler, release_handler]},
{applications, [kernel, stdlib]},
- {env, [{sasl_error_logger, tty},
- {errlog_type, all}]},
+ {env, []},
{mod, {sasl, []}},
- {runtime_dependencies, ["tools-2.6.14","stdlib-3.0","kernel-5.0",
- "erts-8.1"]}]}.
+ {runtime_dependencies, ["tools-2.6.14","stdlib-3.4","kernel-5.3",
+ "erts-9.0"]}]}.
diff --git a/lib/sasl/src/sasl.appup.src b/lib/sasl/src/sasl.appup.src
index 7f866507a0..d37c5b3d95 100644
--- a/lib/sasl/src/sasl.appup.src
+++ b/lib/sasl/src/sasl.appup.src
@@ -1,7 +1,7 @@
%% -*- erlang -*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,7 +18,11 @@
%% %CopyrightEnd%
{"%VSN%",
%% Up from - max one major revision back
- [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-19.*
+ [{<<"3\\.0\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.0
+ {<<"3\\.1(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.1+
+ {<<"3\\.2(\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-21.*
%% Down to - max one major revision back
- [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-19.*
+ [{<<"3\\.0\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.*
+ {<<"3\\.1(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.1+
+ {<<"3\\.2(\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-21.*
}.
diff --git a/lib/sasl/src/sasl.erl b/lib/sasl/src/sasl.erl
index 24afaee183..0c68c93dc6 100644
--- a/lib/sasl/src/sasl.erl
+++ b/lib/sasl/src/sasl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,45 +31,52 @@
%%%-----------------------------------------------------------------
-behaviour(application).
--record(state, {sasl_error_logger, error_logger_mf}).
+-record(state, {sasl_logger, error_logger_mf}).
start(_, []) ->
- Handler = get_sasl_error_logger(),
- Type = get_sasl_error_logger_type(),
+ {Dest,Level} = get_logger_info(),
Mf = get_error_logger_mf(),
- add_sasl_error_logger(Handler, Type),
+ add_sasl_logger(Dest, Level),
add_error_logger_mf(Mf),
- State = #state{sasl_error_logger = Handler, error_logger_mf = Mf},
+ State = #state{sasl_logger = Dest, error_logger_mf = Mf},
case supervisor:start_link({local, sasl_sup}, sasl, []) of
{ok, Pid} -> {ok, Pid, State};
Error -> Error
end.
stop(State) ->
- delete_sasl_error_logger(State#state.sasl_error_logger),
+ delete_sasl_logger(State#state.sasl_logger),
delete_error_logger_mf(State#state.error_logger_mf).
%%-----------------------------------------------------------------
%% Internal functions
%%-----------------------------------------------------------------
-get_sasl_error_logger() ->
+get_logger_info() ->
+ case application:get_env(kernel, logger_sasl_compatible) of
+ {ok,true} ->
+ {get_logger_dest(),get_logger_level()};
+ _ ->
+ {std,undefined}
+ end.
+
+get_logger_dest() ->
case application:get_env(sasl, sasl_error_logger) of
- {ok, false} -> undefined;
- {ok, tty} -> tty;
- {ok, {file, File}} when is_list(File) -> {file, File, [write]};
- {ok, {file, File, Modes}} when is_list(File), is_list(Modes) ->
- {file, File, Modes};
- {ok, Bad} -> exit({bad_config, {sasl, {sasl_error_logger, Bad}}});
- _ -> undefined
+ {ok, false} -> undefined;
+ {ok, tty} -> standard_io;
+ {ok, {file, File}} when is_list(File) -> {file, File};
+ {ok, {file, File, Modes}} when is_list(File), is_list(Modes) ->
+ {file, File, Modes};
+ {ok, Bad} -> exit({bad_config, {sasl, {sasl_logger_dest, Bad}}});
+ undefined -> standard_io
end.
-get_sasl_error_logger_type() ->
+get_logger_level() ->
case application:get_env(sasl, errlog_type) of
- {ok, error} -> error;
- {ok, progress} -> progress;
- {ok, all} -> all;
- {ok, Bad} -> exit({bad_config, {sasl, {errlog_type, Bad}}});
- _ -> all
+ {ok, error} -> error;
+ {ok, progress} -> info;
+ {ok, all} -> info;
+ {ok, Bad} -> exit({bad_config, {sasl, {errlog_type, Bad}}});
+ _ -> info
end.
get_error_logger_mf() ->
@@ -119,26 +126,36 @@ get_mf_maxf() ->
{ok, Bad} -> exit({bad_config, {sasl, {error_logger_mf_maxfiles, Bad}}})
end.
-add_sasl_error_logger(undefined, _Type) -> ok;
-add_sasl_error_logger(Handler, Type) ->
- error_logger:add_report_handler(mod(Handler), args(Handler, Type)).
-
-delete_sasl_error_logger(undefined) -> ok;
-delete_sasl_error_logger(Type) ->
- error_logger:delete_report_handler(mod(Type)).
-
-mod(tty) -> sasl_report_tty_h;
-mod({file, _File, _Modes}) -> sasl_report_file_h.
-
-args({file, File, Modes}, Type) -> {File, Modes, type(Type)};
-args(_, Type) -> type(Type).
-
-type(error) -> error;
-type(progress) -> progress;
-type(_) -> all.
+add_sasl_logger(undefined, _Level) -> ok;
+add_sasl_logger(std, undefined) -> ok;
+add_sasl_logger(Dest, Level) ->
+ FC = #{legacy_header=>true,
+ single_line=>false},
+ case Level of
+ info -> allow_progress();
+ _ -> ok
+ end,
+ ok = logger:add_handler(sasl,logger_std_h,
+ #{level=>Level,
+ filter_default=>stop,
+ filters=>
+ [{remote_gl,
+ {fun logger_filters:remote_gl/2,stop}},
+ {sasl_domain,
+ {fun logger_filters:domain/2,
+ {log,equal,[otp,sasl]}}}],
+ config=>#{type=>Dest},
+ formatter=>{logger_formatter,FC}}).
+
+delete_sasl_logger(undefined) -> ok;
+delete_sasl_logger(std) -> ok;
+delete_sasl_logger(_Type) ->
+ _ = logger:remove_handler(sasl),
+ ok.
add_error_logger_mf(undefined) -> ok;
add_error_logger_mf({Dir, MaxB, MaxF}) ->
+ allow_progress(),
error_logger:add_report_handler(
log_mf_h, log_mf_h:init(Dir, MaxB, MaxF, fun pred/1)).
@@ -149,6 +166,13 @@ delete_error_logger_mf(_) ->
pred({_Type, GL, _Msg}) when node(GL) =/= node() -> false;
pred(_) -> true.
+allow_progress() ->
+ #{level:=PL} = logger:get_primary_config(),
+ case logger:compare_levels(info,PL) of
+ lt -> ok = logger:set_primary_config(level,info);
+ _ -> ok
+ end.
+
%%%-----------------------------------------------------------------
%%% supervisor functionality
%%%-----------------------------------------------------------------
diff --git a/lib/sasl/src/sasl_report.erl b/lib/sasl/src/sasl_report.erl
index eb454155d5..e6556ec6ce 100644
--- a/lib/sasl/src/sasl_report.erl
+++ b/lib/sasl/src/sasl_report.erl
@@ -47,6 +47,7 @@ io_report(_IO, _Fd, _, _) ->
is_my_error_report(all, Type) -> is_my_error_report(Type);
is_my_error_report(error, Type) -> is_my_error_report(Type);
is_my_error_report(_, _Type) -> false.
+
is_my_error_report(supervisor_report) -> true;
is_my_error_report(crash_report) -> true;
is_my_error_report(_) -> false.
@@ -54,6 +55,7 @@ is_my_error_report(_) -> false.
is_my_info_report(all, Type) -> is_my_info_report(Type);
is_my_info_report(progress, Type) -> is_my_info_report(Type);
is_my_info_report(_, _Type) -> false.
+
is_my_info_report(progress) -> true;
is_my_info_report(_) -> false.
@@ -62,46 +64,65 @@ write_report2(IO, Fd, Head, supervisor_report, Report) ->
Context = sup_get(errorContext, Report),
Reason = sup_get(reason, Report),
Offender = sup_get(offender, Report),
- {FmtString,Args} = supervisor_format([Name,Context,Reason,Offender]),
- write_report_action(IO, Fd, Head, FmtString, Args);
+ Enc = encoding(Fd),
+ {FmtString,Args} = supervisor_format([Name,Context,Reason,Offender], Enc),
+ String = io_lib:format(FmtString, Args),
+ write_report_action(IO, Fd, Head, String);
write_report2(IO, Fd, Head, progress, Report) ->
- Format = format_key_val(Report),
- write_report_action(IO, Fd, Head, "~s", [Format]);
+ Encoding = encoding(Fd),
+ Depth = error_logger:get_format_depth(),
+ String = format_key_val(Report, Encoding, Depth),
+ write_report_action(IO, Fd, Head, String);
write_report2(IO, Fd, Head, crash_report, Report) ->
+ Encoding = encoding(Fd),
Depth = error_logger:get_format_depth(),
- Format = proc_lib:format(Report, latin1, Depth),
- write_report_action(IO, Fd, Head, "~s", [Format]).
-
-supervisor_format(Args0) ->
- case error_logger:get_format_depth() of
- unlimited ->
- {" Supervisor: ~p~n"
- " Context: ~p~n"
- " Reason: ~80.18p~n"
- " Offender: ~80.18p~n~n",
- Args0};
- Depth ->
- [A,B,C,D] = Args0,
- Args = [A,Depth,B,Depth,C,Depth,D,Depth],
- {" Supervisor: ~P~n"
- " Context: ~P~n"
- " Reason: ~80.18P~n"
- " Offender: ~80.18P~n~n",
- Args}
- end.
-
-write_report_action(IO, Fd, Head, Format, Args) ->
- S = [Head|io_lib:format(Format, Args)],
+ String = proc_lib:format(Report, Encoding, Depth),
+ write_report_action(IO, Fd, Head, String).
+
+supervisor_format(Args0, Encoding) ->
+ {P, Tl} = p(Encoding, error_logger:get_format_depth()),
+ [A,B,C,D] = Args0,
+ Args = [A|Tl] ++ [B|Tl] ++ [C|Tl] ++ [D|Tl],
+ {" Supervisor: ~" ++ P ++ "\n"
+ " Context: ~" ++ P ++ "\n"
+ " Reason: ~80.18" ++ P ++ "\n"
+ " Offender: ~80.18" ++ P ++ "\n~n",
+ Args}.
+
+write_report_action(IO, Fd, Head, String) ->
+ S = [Head|String],
case IO of
io -> io:put_chars(Fd, S);
io_lib -> S
end.
-format_key_val([{Tag,Data}|Rep]) ->
- io_lib:format(" ~16w: ~p~n",[Tag,Data]) ++ format_key_val(Rep);
-format_key_val(_) ->
+format_key_val(Rep, Encoding, Depth) ->
+ {P, Tl} = p(Encoding, Depth),
+ format_key_val1(Rep, P, Tl).
+
+format_key_val1([{Tag,Data}|Rep], P, Tl) ->
+ (io_lib:format(" ~16w: ~" ++ P ++ "\n", [Tag, Data|Tl]) ++
+ format_key_val1(Rep, P, Tl));
+format_key_val1(_, _, _) ->
[].
+p(Encoding, Depth) ->
+ {Letter, Tl} = case Depth of
+ unlimited -> {"p", []};
+ _ -> {"P", [Depth]}
+ end,
+ P = modifier(Encoding) ++ Letter,
+ {P, Tl}.
+
+encoding(IO) ->
+ case lists:keyfind(encoding, 1, io:getopts(IO)) of
+ false -> latin1;
+ {encoding, Enc} -> Enc
+ end.
+
+modifier(latin1) -> "";
+modifier(_) -> "t".
+
sup_get(Tag, Report) ->
case lists:keysearch(Tag, 1, Report) of
{value, {_, Value}} ->
diff --git a/lib/sasl/src/sasl_report_file_h.erl b/lib/sasl/src/sasl_report_file_h.erl
index 21746839fa..05d6acd076 100644
--- a/lib/sasl/src/sasl_report_file_h.erl
+++ b/lib/sasl/src/sasl_report_file_h.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,15 +29,27 @@
handle_event/2, handle_call/2, handle_info/2,
terminate/2]).
-init({File, Modes, Type}) when is_list(Modes) ->
+init({File, Modes0, Type}) when is_list(Modes0) ->
process_flag(trap_exit, true),
+ Modes1 =
+ case lists:keymember(encoding,1,Modes0) of
+ true -> Modes0;
+ false -> [{encoding,utf8}|Modes0]
+ end,
+ Modes =
+ case [M || M <- Modes1, lists:member(M,[write,append,exclusive])] of
+ [] ->
+ [write|Modes1];
+ _ ->
+ Modes1
+ end,
case file:open(File, Modes) of
{ok,Fd} ->
{ok, {Fd, File, Type}};
What ->
What
end.
-
+
handle_event({_Type, GL, _Msg}, State) when node(GL) /= node() ->
{ok, State};
handle_event(Event, {Fd, File, Type}) ->
diff --git a/lib/sasl/src/si.erl b/lib/sasl/src/si.erl
deleted file mode 100644
index 275c6d508b..0000000000
--- a/lib/sasl/src/si.erl
+++ /dev/null
@@ -1,169 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%-----------------------------------------------------------------
-%% l(format_lib_supp), l(si_sasl_supp), l(si), l(si_ms_aos_supp), l(misc_supp).
-%% c(format_lib_supp), c(si_sasl_supp), c(si), c(si_ms_aos_supp), c(misc_supp).
-%%-----------------------------------------------------------------
-
-
-%%--------------------------------------------------
-%% Description:
-%% Status Inspection, main module.
-%%--------------------------------------------------
-
--module(si).
-
-
-%% External exports
--export([h/0, help/0, start/0, start/1, start_log/1, stop_log/0,
- abbrevs/0, pi/1, pi/2, pi/3, pi/4, ppi/1, ppi/3, stop/0]).
-
-%% Internal exports
--export([pi_impl/2, test/0]).
-
-
-%%--------------------------------------------------
-%% Table of contents
-%% 1. Interface
-%% 2. Implementation
-
-
--import(si_sasl_supp, [status_info/1, make_pid/1, p/1]).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% 1. Interface
-%%--------------------------------------------------
-
-h() -> print_help().
-help() -> print_help().
-
-start() -> si_sasl_supp:start().
-start(Options) -> si_sasl_supp:start(Options).
-
-stop() -> si_sasl_supp:stop().
-
-start_log(FileName) ->
- si_sasl_supp:start_log(FileName).
-
-stop_log() ->
- si_sasl_supp:stop_log().
-
-%%%-----------------------------------------------------------------
-%%% All functions can be called with an option 'normal' or 'all';
-%%% default is 'normal'.
-%%%-----------------------------------------------------------------
-
-abbrevs() ->
- io:format("~p", [lists:append(si_sasl_supp:process_abbrevs(),
- process_abbrevs())]).
-
-%%-----------------------------------------------------------------
-%% Process Info that tries to determine processtype (=Module), then
-%% it uses this Module:format_info to format data from status_info/1.
-%%-----------------------------------------------------------------
-pi(XPid) ->
- si_sasl_supp:si_exec({si, pi_impl}, [normal, XPid]).
-
-pi(Opt, XPid) ->
- si_sasl_supp:si_exec({si, pi_impl}, [si_sasl_supp:valid_opt(Opt), XPid]).
-
-pi(A, B, C) when is_integer(A), is_integer(B), is_integer(C) ->
- si_sasl_supp:si_exec({si, pi_impl}, [normal, {A, B, C}]).
-
-pi(Opt, A, B, C) when is_integer(A), is_integer(B), is_integer(C) ->
- si_sasl_supp:si_exec({si, pi_impl}, [si_sasl_supp:valid_opt(Opt), {A, B, C}]).
-
-%%-----------------------------------------------------------------
-%% Pretty print Process_Info.
-%%-----------------------------------------------------------------
-ppi(XPid) ->
- si_sasl_supp:ppi(XPid).
-ppi(A, B, C) ->
- si_sasl_supp:ppi(A, B, C).
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% 2. Implementation
-%%--------------------------------------------------
-
-print_help() ->
- p("~nStatus Inspection tool - usage"),
- p("=============================="),
- p(" For all these functions, Opt is an optional argument"),
- p(" which can be 'normal' or 'all'; default is 'normal'."),
- p(" If 'all', all information will be printed."),
- p(" A Pid can be: \"<A.B.C>\", {A, B, C}, B, a registered_name or an abbrev."),
- p("ANY PROCESS"),
- p("si:pi([Opt,] Pid) - Formatted information about any process that"),
- p(" SI recognises."),
- p("si:pi([Opt,] A,B,C) - Same as si:pi({A, B, C})."),
- p("si:ppi(Pid) - Pretty formating of process_info."),
- p(" Works for any process."),
- p("MISC"),
- p("si:abbrevs() - Lists valid abbreviations."),
- p("si:start_log(Filename) - Logging to file."),
- p("si:stop_log()"),
- p("si:start() - Starts Status Inspection (the si_server)."),
- p("si:start([{start_log, FileName}])"),
- p("si:stop() - Shut down SI.").
-
-
-%%--------------------------------------------------
-%% Copied (and modified) code from si_sasl_supp.
-%%--------------------------------------------------
-pi_impl(Opt, XPid) ->
- case make_pid(try_local_expand_abbrev(XPid)) of
- Pid when is_pid(Pid) ->
- case status_info(Pid) of
- {status_info, Pid, {module, Module}, Data} ->
- si_sasl_supp:do_best_printout(Opt, Pid, Module, Data);
- {error, Reason} ->
- _ = si_sasl_supp:ppi_impl(Pid),
- {error, {"can not get status info from process:",
- XPid,
- Reason}};
- Else ->
- {error, {"unknown status info", Else}}
- end;
- {error, Reason} ->
- {error, Reason}
- end.
-
-%%--------------------------------------------------
-%% Functions for handling of abbreviations
-%%--------------------------------------------------
-try_local_expand_abbrev(Abbrev) ->
- case si_sasl_supp:expand_abbrev(Abbrev, process_abbrevs()) of
- {value, {_, RealName}} -> RealName;
- _ -> Abbrev
- end.
-
-process_abbrevs() ->
- [].
-
-%% Test get_status_info/format_status_info for all implemented servers.
-test() ->
- lists:foreach(fun test_all_registered/1,
- lists:append(si_sasl_supp:process_abbrevs(),
- process_abbrevs())).
-
-test_all_registered({Al, _Ful}) ->
- si:pi(all, Al).
diff --git a/lib/sasl/src/si_sasl_supp.erl b/lib/sasl/src/si_sasl_supp.erl
deleted file mode 100644
index cce628f8c4..0000000000
--- a/lib/sasl/src/si_sasl_supp.erl
+++ /dev/null
@@ -1,380 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
--module(si_sasl_supp).
-
--behaviour(gen_server).
-
-%%%---------------------------------------------------------------------------
-%%% Description:
-%%% This module contains the BOS specific parts of the Status Inspection Tool.
-%%%---------------------------------------------------------------------------
-
-
-%% user interface
--export([h/0, help/0, start_log/1, stop_log/0, abbrevs/0, pi/1, pi/2, pi/3,
- pi/4, ppi/1, ppi/3, start/0, start/1, stop/0, start_link/1]).
-
-%% intermodule exports
--export([make_pid/1, make_pid/3, process_abbrevs/0, expand_abbrev/2,
- status_info/1, valid_opt/1, p/1, do_best_printout/4,
- si_exec/2, handle_call/3, terminate/2]).
-
-%% exports for use within module
--export([init/1, start_log_impl/1, pi_impl/2, ppi_impl/1]).
-
-%% other gen_server callbacks (not used)
--export([handle_cast/2, handle_info/2, code_change/3]).
-
-%%--------------------------------------------------
-%% Table of contents
-%% 1. Interface
-%% 2. SI - Server
-%% 3. Code
-%% 4. Selectors
-%%--------------------------------------------------
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% 1. Interface
-%% -----------------------------------------------------
-
-h() -> print_help().
-help() -> print_help().
-
-si_exec(Fun, Args) -> call({si_exec, Fun, Args}).
-
-start_log(FileName) ->
- call({start_log, FileName}).
-
-stop_log() ->
- call(stop_log).
-
-abbrevs() ->
- io:format("~p", [process_abbrevs()]).
-
-%%-----------------------------------------------------------------
-%% All functions can be called with an option 'normal' or 'all';
-%% default is 'normal'.
-%%-----------------------------------------------------------------
-%% Process Info that tries to determine processtype (=Module), then
-%% it uses this Module:format_info to format data from status_info/1.
-%%-----------------------------------------------------------------
-pi(XPid) ->
- si_exec({si_sasl_supp, pi_impl}, [normal, XPid]).
-
-pi(Opt, XPid) ->
- si_exec({si_sasl_supp, pi_impl}, [valid_opt(Opt), XPid]).
-
-pi(A, B, C) when is_integer(A), is_integer(B), is_integer(C) ->
- si_exec({si_sasl_supp, pi_impl}, [normal, {A, B, C}]).
-
-pi(Opt, A, B, C) when is_integer(A), is_integer(B), is_integer(C) ->
- si_exec({si_sasl_supp, pi_impl}, [valid_opt(Opt), {A, B, C}]).
-
-%%-----------------------------------------------------------------
-%% Pretty print Process_Info.
-%%-----------------------------------------------------------------
-ppi(XPid) ->
- case whereis(si_server) of
- undefined -> % You can always run ppi.
- ppi_impl(XPid); % if si_server is down, use standard_io
- _ ->
- si_exec({si_sasl_supp, ppi_impl}, [XPid])
- end.
-ppi(A, B, C) ->
- case whereis(si_server) of
- undefined -> % You can always run ppi.
- ppi_impl({A, B, C}); % if si_server is down, use standard_io
- _ ->
- si_exec({si_sasl_supp, ppi_impl}, [{A, B, C}])
- end.
-
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% 2. SI - Server
-%%--------------------------------------------------
--record(state, {}).
-
-start() -> start([]).
-start(Options) ->
- supervisor:start_child(sasl_sup,
- {si_server, {si_sasl_supp, start_link, [Options]},
- temporary, brutal_kill, worker, [si_sasl_supp]}).
-
-start_link(_Options) ->
- gen_server:start_link({local, si_server}, si_sasl_supp, [], []).
-
-stop() ->
- call(stop),
- supervisor:delete_child(sasl_sup, si_server).
-
-
-init(Options) ->
- process_flag(trap_exit, true),
- start_log_impl(get_option(Options, start_log, standard_io)),
- {ok, #state{}}.
-
-%%-----------------------------------------------------------------
-%% If an error occurs and we're logging to file: write the error
-%% to the file.
-%% Always return the error.
-%% The only data held by the si_server is the device in its process dictionary.
-%%-----------------------------------------------------------------
-handle_call({si_exec, Fun, Args}, _From, State) ->
- case catch apply(Fun, Args) of
- {'EXIT', Reason} ->
- print_error(get(device),
- "SI internal error. Reason: ~w~n",
- [Reason]),
- {stop, shutdown, {internal_error, Reason}, State};
- {error, Reason} ->
- print_error(get(device), "~nSI error: ~w~n", [Reason]),
- {reply, {error, Reason}, State};
- X ->
- {reply, X, State}
- end;
-handle_call({start_log, FileName}, _From, State) ->
- start_log_impl(FileName),
- {reply, ok, State};
-handle_call(stop_log, _From, State) ->
- start_log_impl(standard_io),
- {reply, ok, State};
-handle_call(stop, _From, State) ->
- start_log_impl(standard_io),
- {stop, normal, stopped, State}.
-
-terminate(_Reason, _State) ->
- _ = close_device(get(device)),
- ok.
-
-handle_cast(_Msg, State) ->
- {noreply, State}.
-handle_info(_Info, State) ->
- {noreply, State}.
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-close_device(standard_io) -> ok;
-close_device(Fd) -> file:close(Fd).
-
-print_error(standard_io, _, _) -> ok;
-print_error(Device, Format, Args) ->
- io:format(Device, Format, Args).
-
-get_option(Options, Key, Default) ->
- case lists:keysearch(Key, 1, Options) of
- {value, {_Key, Value}} -> Value;
- _ -> Default
- end.
-
-open_log_file(undefined, NewFile) ->
- open_log_file(NewFile);
-open_log_file(standard_io, NewFile) ->
- open_log_file(NewFile);
-open_log_file(OldFile, NewFile) ->
- _ = file:close(OldFile),
- open_log_file(NewFile).
-
-open_log_file(standard_io) -> standard_io;
-open_log_file(FileName) ->
- case file:open(FileName, [write]) of
- {ok, Fd} -> Fd;
- Error ->
- io:format("si_sasl_supp: Cannot open file '~s' (~w).~n",
- [FileName, Error]),
- io:format("si_sasl_supp: Using standard_io~n"),
- standard_io
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% 3. Code
-%%--------------------------------------------------
-
-%%-----------------------------------------------------------------
-%% call(Request) -> Term
-%%-----------------------------------------------------------------
-call(Req) ->
- gen_server:call(si_server, Req, infinity).
-
-%%--------------------------------------------------
-%% Makes a Pid of almost anything.
-%% Returns: Pid|{error, Reason}
-%% Fails: Never.
-%%--------------------------------------------------
-make_pid(A,B,C) when is_integer(A), is_integer(B), is_integer(C) ->
- list_to_pid(lists:concat(["<",A,".",B,".",C,">"])).
-make_pid(P) when is_pid(P) -> P;
-make_pid(undefined) -> undefined;
-make_pid(P) when is_atom(P) ->
- case whereis(P) of
- undefined ->
- case expand_abbrev(P, process_abbrevs()) of
- {error, Reason} -> {error, Reason};
- {value, {_Abbrev, FullName}} ->
- case whereis(FullName) of
- undefined ->
- {error, {'process not registered', P}};
- Pid -> Pid
- end
- end;
- Pid -> Pid
- end;
-make_pid(P) when is_list(P) -> list_to_pid(P);
-make_pid({A, B, C}) -> make_pid(A, B, C);
-make_pid(X) -> {error, {'can not make a pid of', X}}.
-
-process_abbrevs() ->
- [{init, init},
- {fs, file_server}].
-
-%%--------------------------------------------------
-%% Args: Abbrevs is an assoc-list of {Abbrev, RealName}
-%% Returns: {value, {Abbrev, FullName}}|{error, Reason}
-%%--------------------------------------------------
-expand_abbrev(ProcessName, Abbrevs) ->
- case lists:keysearch(ProcessName, 1, Abbrevs) of
- {value, {Abbrev, FullName}} ->
- {value, {Abbrev, FullName}};
- _ ->
- case lists:keysearch(ProcessName, 2, Abbrevs) of
- {value, {Abbrev, FullName}} ->
- {value, {Abbrev, FullName}};
- _ ->
- {error, {'invalid process name', ProcessName}}
- end
- end.
-
-%%-----------------------------------------------------------------
-%% This is the function that actually gets the information out
-%% of the agent/server/...
-%% Returns: {status_info, Pid, Type, Data}
-%% | {error, Reason}
-%%-----------------------------------------------------------------
-status_info(Pid) when is_pid(Pid) ->
- case catch sys:get_status(Pid, 5000) of
- {status, Pid, Type, Info} ->
- {status_info, Pid, Type, Info};
- _ ->
- {error, {'process does not respond', Pid}}
- end;
-
-status_info(X) ->
- {error, {'not a pid', X}}.
-
-%%--------------------------------------------------
-%% Implementation starts here.
-%%--------------------------------------------------
-start_log_impl(FileName) ->
- put(device, open_log_file(get(device), FileName)).
-
-valid_opt(all) -> all;
-valid_opt(_Opt) -> normal.
-
-
-print_help() ->
- p("- - - - - - - - PROCESSES - - - - - - - - - "),
- p("si_sasl_supp:pi([Opt,] Pid) - Formatted information about any process that"),
- p(" SI recognises."),
- p("si_sasl_supp:pi([Opt,] A,B,C) - Same as si_sasl_supp:pi({A, B, C})."),
- p("si_sasl_supp:ppi(Pid) - Pretty formating of process_info."),
- p(" Works for any process."),
- p("- - - - - - - - MISC - - - - - - - - - - - "),
- p("si_sasl_supp:abbrevs() - Lists valid abbreviations."),
- p("si_sasl_supp:start_log(FileNname)"),
- p("si_sasl_supp:stop_log()"),
- p("si_sasl_supp:start() - Starts Status Inspection (the si_server)."),
- p("si_sasl_supp:start([{start_log, FileName}])"),
- p("si_sasl_supp:stop() - Shut down SI.").
-
-
-
-%% Convenient shorthand
-p(X) ->
- io:format(lists:append(X, "~n")).
-
-pi_impl(Opt, XPid) ->
- case make_pid(XPid) of
- Pid when is_pid(Pid) ->
- case status_info(Pid) of
- {status_info, Pid, {module, Module}, Data} ->
- do_best_printout(Opt, Pid, Module, Data);
- {error, Reason} ->
- _ = ppi_impl(Pid),
- {error, {"can not get status info from process:",
- XPid,
- Reason}}
- end;
- {error, Reason} ->
- {error, Reason}
- end.
-
-%%--------------------------------------------------
-%% Is there a format_info for this process? In that case, run it!
-%% Return ok|{error, Reason}
-%% Fails: Never.
-%%--------------------------------------------------
-do_best_printout(Opt, Pid, Mod, Data) when is_pid(Pid) ->
- case print_info(get(device), Pid, {Mod, format_status}, Opt, Data) of
- ok -> ok;
- {error, Reason} ->
- _ = ppi_impl(Pid),
- {error, Reason}
- end.
-
-ppi_impl(XPid) ->
- case make_pid(XPid) of
- P when is_pid(P) ->
- case process_info(P) of
- undefined ->
- {error, {'dead process', P}};
- PI ->
- Device = case get(device) of
- undefined -> standard_io;
- X -> X
- end,
- io:format(Device, "~nPretty Process Info~n", []),
- io:format(Device, "-------------------~n", []),
- io:format(Device, "~p~n", [PI])
- end;
- _ -> {error, {no_pid, XPid}}
- end.
-
-print_info(Device, Pid, {Module, Func}, Opt, Data) ->
- case erlang:function_exported(Module, Func, 2) of
- true ->
- case catch apply(Module, Func, [Opt, Data]) of
- Format when is_list(Format) ->
- format_lib_supp:print_info(Device, 79,
- add_pid_to_format(Pid, Format)),
- ok;
- Other -> {error, {'invalid format', Other}}
- end;
- _ ->
- {error, {no_such_function, Module, Func}}
- end.
-
-add_pid_to_format(Pid, [{header, H} | T]) ->
- [{header, H}, {data, [{"Pid", Pid}]} | T];
-add_pid_to_format(Pid, List) ->
- [{data, [{"Pid", Pid}]} | List].
-
-
diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl
index b1523dcbb7..6916107623 100644
--- a/lib/sasl/src/systools_make.erl
+++ b/lib/sasl/src/systools_make.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,7 @@
-export([read_application/4]).
--export([make_hybrid_boot/5]).
+-export([make_hybrid_boot/4]).
-import(lists, [filter/2, keysort/2, keysearch/3, map/2, reverse/1,
append/1, foldl/3, member/2, foreach/2]).
@@ -178,94 +178,153 @@ return({error,Mod,Error},_,Flags) ->
%% and sasl.
%%
%% TmpVsn = string(),
-%% Paths = {KernelPath,StdlibPath,SaslPath}
%% Returns {ok,Boot} | {error,Reason}
%% Boot1 = Boot2 = Boot = binary()
%% Reason = {app_not_found,App} | {app_not_replaced,App}
-%% App = kernel | stdlib | sasl
-make_hybrid_boot(TmpVsn, Boot1, Boot2, Paths, Args) ->
- catch do_make_hybrid_boot(TmpVsn, Boot1, Boot2, Paths, Args).
-do_make_hybrid_boot(TmpVsn, Boot1, Boot2, Paths, Args) ->
- {script,{_RelName1,_RelVsn1},Script1} = binary_to_term(Boot1),
- {script,{RelName2,_RelVsn2},Script2} = binary_to_term(Boot2),
- MatchPaths = get_regexp_path(Paths),
- NewScript1 = replace_paths(Script1,MatchPaths),
- {Kernel,Stdlib,Sasl} = get_apps(Script2,undefined,undefined,undefined),
- NewScript2 = replace_apps(NewScript1,Kernel,Stdlib,Sasl),
- NewScript3 = add_apply_upgrade(NewScript2,Args),
- Boot = term_to_binary({script,{RelName2,TmpVsn},NewScript3}),
+%% App = stdlib | sasl
+make_hybrid_boot(TmpVsn, Boot1, Boot2, Args) ->
+ catch do_make_hybrid_boot(TmpVsn, Boot1, Boot2, Args).
+do_make_hybrid_boot(TmpVsn, OldBoot, NewBoot, Args) ->
+ {script,{_RelName1,_RelVsn1},OldScript} = binary_to_term(OldBoot),
+ {script,{NewRelName,_RelVsn2},NewScript} = binary_to_term(NewBoot),
+
+ %% Everyting upto kernel_load_completed must come from the new script
+ Fun1 = fun({progress,kernel_load_completed}) -> false;
+ (_) -> true
+ end,
+ {_OldKernelLoad,OldRest1} = lists:splitwith(Fun1,OldScript),
+ {NewKernelLoad,NewRest1} = lists:splitwith(Fun1,NewScript),
+
+ Fun2 = fun({progress,modules_loaded}) -> false;
+ (_) -> true
+ end,
+ {OldModLoad,OldRest2} = lists:splitwith(Fun2,OldRest1),
+ {NewModLoad,NewRest2} = lists:splitwith(Fun2,NewRest1),
+
+ Fun3 = fun({kernelProcess,_,_}) -> false;
+ (_) -> true
+ end,
+ {OldPaths,OldRest3} = lists:splitwith(Fun3,OldRest2),
+ {NewPaths,NewRest3} = lists:splitwith(Fun3,NewRest2),
+
+ Fun4 = fun({progress,init_kernel_started}) -> false;
+ (_) -> true
+ end,
+ {_OldKernelProcs,OldApps} = lists:splitwith(Fun4,OldRest3),
+ {NewKernelProcs,NewApps} = lists:splitwith(Fun4,NewRest3),
+
+ %% Then comes all module load, which for each app consist of:
+ %% {path,[AppPath]},
+ %% {primLoad,ModuleList}
+ %% Replace kernel, stdlib and sasl here
+ MatchPaths = get_regexp_path(),
+ ModLoad = replace_module_load(OldModLoad,NewModLoad,MatchPaths),
+ Paths = replace_paths(OldPaths,NewPaths,MatchPaths),
+
+ {Stdlib,Sasl} = get_apps(NewApps,undefined,undefined),
+ Apps0 = replace_apps(OldApps,Stdlib,Sasl),
+ Apps = add_apply_upgrade(Apps0,Args),
+
+ Script = NewKernelLoad++ModLoad++Paths++NewKernelProcs++Apps,
+ Boot = term_to_binary({script,{NewRelName,TmpVsn},Script}),
{ok,Boot}.
%% For each app, compile a regexp that can be used for finding its path
-get_regexp_path({KernelPath,StdlibPath,SaslPath}) ->
+get_regexp_path() ->
{ok,KernelMP} = re:compile("kernel-[0-9\.]+",[unicode]),
{ok,StdlibMP} = re:compile("stdlib-[0-9\.]+",[unicode]),
{ok,SaslMP} = re:compile("sasl-[0-9\.]+",[unicode]),
- [{KernelMP,KernelPath},{StdlibMP,StdlibPath},{SaslMP,SaslPath}].
-
-%% For each path in the script, check if it matches any of the MPs
-%% found above, and if so replace it with the correct new path.
-replace_paths([{path,Path}|Script],MatchPaths) ->
- [{path,replace_path(Path,MatchPaths)}|replace_paths(Script,MatchPaths)];
-replace_paths([Stuff|Script],MatchPaths) ->
- [Stuff|replace_paths(Script,MatchPaths)];
-replace_paths([],_) ->
+ [KernelMP,StdlibMP,SaslMP].
+
+replace_module_load(Old,New,[MP|MatchPaths]) ->
+ replace_module_load(do_replace_module_load(Old,New,MP),New,MatchPaths);
+replace_module_load(Script,_,[]) ->
+ Script.
+
+do_replace_module_load([{path,[OldAppPath]},{primLoad,OldMods}|OldRest],New,MP) ->
+ case re:run(OldAppPath,MP,[{capture,none}]) of
+ nomatch ->
+ [{path,[OldAppPath]},{primLoad,OldMods}|
+ do_replace_module_load(OldRest,New,MP)];
+ match ->
+ get_module_load(New,MP) ++ OldRest
+ end;
+do_replace_module_load([Other|Rest],New,MP) ->
+ [Other|do_replace_module_load(Rest,New,MP)];
+do_replace_module_load([],_,_) ->
+ [].
+
+get_module_load([{path,[AppPath]},{primLoad,Mods}|Rest],MP) ->
+ case re:run(AppPath,MP,[{capture,none}]) of
+ nomatch ->
+ get_module_load(Rest,MP);
+ match ->
+ [{path,[AppPath]},{primLoad,Mods}]
+ end;
+get_module_load([_|Rest],MP) ->
+ get_module_load(Rest,MP);
+get_module_load([],_) ->
[].
-replace_path([Path|Paths],MatchPaths) ->
- [do_replace_path(Path,MatchPaths)|replace_path(Paths,MatchPaths)];
-replace_path([],_) ->
+replace_paths([{path,OldPaths}|Old],New,MatchPaths) ->
+ {path,NewPath} = lists:keyfind(path,1,New),
+ [{path,do_replace_paths(OldPaths,NewPath,MatchPaths)}|Old];
+replace_paths([Other|Old],New,MatchPaths) ->
+ [Other|replace_paths(Old,New,MatchPaths)].
+
+do_replace_paths(Old,New,[MP|MatchPaths]) ->
+ do_replace_paths(do_replace_paths1(Old,New,MP),New,MatchPaths);
+do_replace_paths(Paths,_,[]) ->
+ Paths.
+
+do_replace_paths1([P|Ps],New,MP) ->
+ case re:run(P,MP,[{capture,none}]) of
+ nomatch ->
+ [P|do_replace_paths1(Ps,New,MP)];
+ match ->
+ get_path(New,MP) ++ Ps
+ end;
+do_replace_paths1([],_,_) ->
[].
-do_replace_path(Path,[{MP,ReplacePath}|MatchPaths]) ->
- case re:run(Path,MP,[{capture,none}]) of
- nomatch -> do_replace_path(Path,MatchPaths);
- match -> ReplacePath
+get_path([P|Ps],MP) ->
+ case re:run(P,MP,[{capture,none}]) of
+ nomatch ->
+ get_path(Ps,MP);
+ match ->
+ [P]
end;
-do_replace_path(Path,[]) ->
- Path.
-
-%% Return the entries for loading the three base applications
-get_apps([{kernelProcess,application_controller,
- {application_controller,start,[{application,kernel,_}]}}=Kernel|
- Script],_,Stdlib,Sasl) ->
- get_apps(Script,Kernel,Stdlib,Sasl);
+get_path([],_) ->
+ [].
+
+
+%% Return the entries for loading stdlib and sasl
get_apps([{apply,{application,load,[{application,stdlib,_}]}}=Stdlib|Script],
- Kernel,_,Sasl) ->
- get_apps(Script,Kernel,Stdlib,Sasl);
+ _,Sasl) ->
+ get_apps(Script,Stdlib,Sasl);
get_apps([{apply,{application,load,[{application,sasl,_}]}}=Sasl|_Script],
- Kernel,Stdlib,_) ->
- {Kernel,Stdlib,Sasl};
-get_apps([_|Script],Kernel,Stdlib,Sasl) ->
- get_apps(Script,Kernel,Stdlib,Sasl);
-get_apps([],undefined,_,_) ->
- throw({error,{app_not_found,kernel}});
-get_apps([],_,undefined,_) ->
+ Stdlib,_) ->
+ {Stdlib,Sasl};
+get_apps([_|Script],Stdlib,Sasl) ->
+ get_apps(Script,Stdlib,Sasl);
+get_apps([],undefined,_) ->
throw({error,{app_not_found,stdlib}});
-get_apps([],_,_,undefined) ->
+get_apps([],_,undefined) ->
throw({error,{app_not_found,sasl}}).
-
-%% Replace the entries for loading the base applications
-replace_apps([{kernelProcess,application_controller,
- {application_controller,start,[{application,kernel,_}]}}|
- Script],Kernel,Stdlib,Sasl) ->
- [Kernel|replace_apps(Script,undefined,Stdlib,Sasl)];
+%% Replace the entries for loading the stdlib and sasl
replace_apps([{apply,{application,load,[{application,stdlib,_}]}}|Script],
- Kernel,Stdlib,Sasl) ->
- [Stdlib|replace_apps(Script,Kernel,undefined,Sasl)];
+ Stdlib,Sasl) ->
+ [Stdlib|replace_apps(Script,undefined,Sasl)];
replace_apps([{apply,{application,load,[{application,sasl,_}]}}|Script],
- _Kernel,_Stdlib,Sasl) ->
+ _Stdlib,Sasl) ->
[Sasl|Script];
-replace_apps([Stuff|Script],Kernel,Stdlib,Sasl) ->
- [Stuff|replace_apps(Script,Kernel,Stdlib,Sasl)];
-replace_apps([],undefined,undefined,_) ->
+replace_apps([Stuff|Script],Stdlib,Sasl) ->
+ [Stuff|replace_apps(Script,Stdlib,Sasl)];
+replace_apps([],undefined,_) ->
throw({error,{app_not_replaced,sasl}});
-replace_apps([],undefined,_,_) ->
- throw({error,{app_not_replaced,stdlib}});
-replace_apps([],_,_,_) ->
- throw({error,{app_not_replaced,kernel}}).
-
+replace_apps([],_,_) ->
+ throw({error,{app_not_replaced,stdlib}}).
%% Finally add an apply of release_handler:new_emulator_upgrade - which will
%% complete the execution of the upgrade script (relup).
@@ -275,8 +334,6 @@ add_apply_upgrade(Script,Args) ->
{apply,{release_handler,new_emulator_upgrade,Args}} |
RevScript]).
-
-
%%-----------------------------------------------------------------
%% Create a release package from a release file.
%% Options is a list of {path, Path} | silent |
@@ -310,6 +367,7 @@ add_apply_upgrade(Script,Args) ->
%% RelVsn/start.boot
%% relup
%% sys.config
+%% sys.config.src
%% erts-EVsn[/bin]
%%-----------------------------------------------------------------
@@ -1152,10 +1210,10 @@ generate_script(Output, Release, Appls, Flags) ->
},
ScriptFile = Output ++ ".script",
- case file:open(ScriptFile, [write]) of
+ case file:open(ScriptFile, [write,{encoding,utf8}]) of
{ok, Fd} ->
- io:format(Fd, "%% script generated at ~w ~w\n~p.\n",
- [date(), time(), Script]),
+ io:format(Fd, "%% ~s\n%% script generated at ~w ~w\n~tp.\n",
+ [epp:encoding_to_string(utf8), date(), time(), Script]),
case file:close(Fd) of
ok ->
BootFile = Output ++ ".boot",
@@ -1488,6 +1546,12 @@ mandatory_modules() ->
gen_server,
heart,
kernel,
+ logger,
+ logger_filters,
+ logger_server,
+ logger_backend,
+ logger_config,
+ logger_simple_h,
lists,
proc_lib,
supervisor
@@ -1499,9 +1563,9 @@ mandatory_modules() ->
preloaded() ->
%% Sorted
[erl_prim_loader,erl_tracer,erlang,
- erts_code_purger,erts_dirty_process_code_checker,
+ erts_code_purger,erts_dirty_process_signal_handler,
erts_internal,erts_literal_area_collector,
- init,otp_ring0,prim_eval,prim_file,
+ init,otp_ring0,prim_buffer,prim_eval,prim_file,
prim_inet,prim_zip,zlib].
%%______________________________________________________________________
@@ -1512,7 +1576,7 @@ preloaded() ->
kernel_processes() ->
[{heart, heart, start, []},
- {error_logger, error_logger, start_link, []},
+ {logger, logger_server, start_link, []},
{application_controller, application_controller, start,
fun(Appls) ->
[{_,App}] = filter(fun({{kernel,_},_App}) -> true;
@@ -1552,6 +1616,7 @@ create_kernel_procs(Appls) ->
%% RelVsn/start.boot
%% relup
%% sys.config
+%% sys.config.src
%% erts-EVsn[/bin]
%%
%% The VariableN.tar.gz files can also be stored as own files not
@@ -1707,14 +1772,18 @@ add_system_files(Tar, RelName, Release, Path1) ->
add_to_tar(Tar, Relup, filename:join(RelVsnDir, "relup"))
end,
- case lookup_file("sys.config", Path) of
- false ->
- ignore;
- Sys ->
- check_sys_config(Sys),
- add_to_tar(Tar, Sys, filename:join(RelVsnDir, "sys.config"))
+ case lookup_file("sys.config.src", Path) of
+ false ->
+ case lookup_file("sys.config", Path) of
+ false ->
+ ignore;
+ Sys ->
+ check_sys_config(Sys),
+ add_to_tar(Tar, Sys, filename:join(RelVsnDir, "sys.config"))
+ end;
+ SysSrc ->
+ add_to_tar(Tar, SysSrc, filename:join(RelVsnDir, "sys.config.src"))
end,
-
ok.
lookup_file(Name, [Dir|Path]) ->
diff --git a/lib/sasl/src/systools_relup.erl b/lib/sasl/src/systools_relup.erl
index 706ae7d631..e836d57670 100644
--- a/lib/sasl/src/systools_relup.erl
+++ b/lib/sasl/src/systools_relup.erl
@@ -535,9 +535,9 @@ to_list(X) when is_list(X) -> X.
write_relup_file(Relup, Opts) ->
Filename = filename:join(filename:absname(get_opt(outdir,Opts)),
"relup"),
- case file:open(Filename, [write]) of
+ case file:open(Filename, [write,{encoding,utf8}]) of
{ok, Fd} ->
- io:format(Fd, "~p.~n", [Relup]),
+ io:format(Fd, "%% ~s~n~tp.~n", [epp:encoding_to_string(utf8),Relup]),
case file:close(Fd) of
ok -> ok;
{error,Reason} ->
diff --git a/lib/sasl/test/rb_SUITE.erl b/lib/sasl/test/rb_SUITE.erl
index 426dedbab5..2b6e452d14 100644
--- a/lib/sasl/test/rb_SUITE.erl
+++ b/lib/sasl/test/rb_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@ no_group_cases() ->
groups() ->
[{running_error_logger,[shuffle],[show,
+ show_other,
list,
rescan,
start_stop_log,
@@ -165,6 +166,23 @@ show(Config) ->
ok.
+show_other(Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ OutFile = filename:join(PrivDir,"rb_SUITE_log.txt"),
+
+ %% Insert some reports in the error log and start rb
+ error_logger:info_report([rb_test_term_in_list]),
+ error_logger:info_report(rb_test_term_no_list),
+ ok = start_rb(OutFile),
+
+ %% Show by type and check content
+ [{_,I1},{_,I2}] = check_report(fun() -> rb:show(info_report) end,OutFile),
+
+ true = contains(I1,"rb_test_term_no_list"),
+ true = contains(I2,"rb_test_term_in_list"),
+
+ ok.
+
list(Config) ->
PrivDir = ?config(priv_dir,Config),
OutFile = filename:join(PrivDir,"rb_SUITE_log.txt"),
diff --git a/lib/sasl/test/release_handler_SUITE.erl b/lib/sasl/test/release_handler_SUITE.erl
index 7093158502..2ff2f29591 100644
--- a/lib/sasl/test/release_handler_SUITE.erl
+++ b/lib/sasl/test/release_handler_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,7 +22,8 @@
-include_lib("common_test/include/ct.hrl").
-include("test_lib.hrl").
--compile(export_all).
+-compile([export_all, nowarn_export_all]).
+-export([scheduler_wall_time/0, garbage_collect/0]). %% rpc'ed
% Default timetrap timeout (set in init_per_testcase).
%-define(default_timeout, ?t:minutes(40)).
@@ -66,7 +67,7 @@ cases() ->
supervisor_which_children_timeout,
release_handler_which_releases, install_release_syntax_check,
upgrade_supervisor, upgrade_supervisor_fail, otp_9864,
- otp_10463_upgrade_script_regexp, no_dot_erlang].
+ otp_10463_upgrade_script_regexp, no_dot_erlang, unicode_upgrade].
groups() ->
[{release,[],
@@ -1085,8 +1086,9 @@ otp_9395_update_many_mods(Conf) when is_list(Conf) ->
Rel2Dir = filename:dirname(Rel2),
%% Start a slave node
+ PA = filename:dirname(code:which(?MODULE)),
{ok, Node} = t_start_node(otp_9395_update_many_mods, Rel1,
- filename:join(Rel1Dir,"sys.config")),
+ filename:join(Rel1Dir,"sys.config"), "-pa " ++ PA),
%% Start a lot of processes on the new node, all with refs to each
%% module that will be updated
@@ -1109,8 +1111,8 @@ otp_9395_update_many_mods(Conf) when is_list(Conf) ->
[RelVsn2, filename:join(Rel2Dir, "sys.config")]),
%% First, install release directly and check how much time it takes
- rpc:call(Node,erlang,garbage_collect,[]),
- rpc:call(Node,erlang,system_flag,[scheduler_wall_time,true]),
+ rpc:call(Node,?MODULE,garbage_collect,[]),
+ SWTFlag0 = spawn_link(Node, ?MODULE, scheduler_wall_time, []),
{TInst0,{ok, _, []}} =
timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn2]]),
SWT0 = rpc:call(Node,erlang,statistics,[scheduler_wall_time]),
@@ -1135,9 +1137,9 @@ otp_9395_update_many_mods(Conf) when is_list(Conf) ->
%% Finally install release after check and purge, and check that
%% this install was faster than the first.
- rpc:call(Node,erlang,system_flag,[scheduler_wall_time,false]),
- rpc:call(Node,erlang,garbage_collect,[]),
- rpc:call(Node,erlang,system_flag,[scheduler_wall_time,true]),
+ SWTFlag0 ! die,
+ rpc:call(Node,?MODULE,garbage_collect,[]),
+ _SWTFlag1 = spawn_link(Node, ?MODULE, scheduler_wall_time, []),
{TInst2,{ok, _RelVsn1, []}} =
timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn2]]),
SWT2 = rpc:call(Node,erlang,statistics,[scheduler_wall_time]),
@@ -1161,6 +1163,15 @@ otp_9395_update_many_mods(Conf) when is_list(Conf) ->
ok.
+scheduler_wall_time() ->
+ erlang:system_flag(scheduler_wall_time,true),
+ receive _Msg -> normal end.
+
+garbage_collect() ->
+ Pids = processes(),
+ [erlang:garbage_collect(Pid) || Pid <- Pids].
+
+
otp_9395_update_many_mods(cleanup,_Conf) ->
stop_node(node_name(otp_9395_update_many_mods)).
@@ -1190,8 +1201,9 @@ otp_9395_rm_many_mods(Conf) when is_list(Conf) ->
Rel2Dir = filename:dirname(Rel2),
%% Start a slave node
+ PA = filename:dirname(code:which(?MODULE)),
{ok, Node} = t_start_node(otp_9395_rm_many_mods, Rel1,
- filename:join(Rel1Dir,"sys.config")),
+ filename:join(Rel1Dir,"sys.config"), "-pa " ++ PA),
%% Start a lot of processes on the new node, all with refs to each
%% module that will be updated
@@ -1214,8 +1226,8 @@ otp_9395_rm_many_mods(Conf) when is_list(Conf) ->
[RelVsn2, filename:join(Rel2Dir, "sys.config")]),
%% First, install release directly and check how much time it takes
- rpc:call(Node,erlang,garbage_collect,[]),
- rpc:call(Node,erlang,system_flag,[scheduler_wall_time,true]),
+ rpc:call(Node,?MODULE,garbage_collect,[]),
+ SWTFlag0 = spawn_link(Node, ?MODULE, scheduler_wall_time, []),
{TInst0,{ok, _, []}} =
timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn2]]),
SWT0 = rpc:call(Node,erlang,statistics,[scheduler_wall_time]),
@@ -1240,9 +1252,9 @@ otp_9395_rm_many_mods(Conf) when is_list(Conf) ->
%% Finally install release after check and purge, and check that
%% this install was faster than the first.
- rpc:call(Node,erlang,system_flag,[scheduler_wall_time,false]),
- rpc:call(Node,erlang,garbage_collect,[]),
- rpc:call(Node,erlang,system_flag,[scheduler_wall_time,true]),
+ SWTFlag0 ! die,
+ rpc:call(Node,?MODULE,garbage_collect,[]),
+ _SWTFlag1 = spawn_link(Node, ?MODULE, scheduler_wall_time, []),
{TInst2,{ok, _RelVsn1, []}} =
timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn2]]),
SWT2 = rpc:call(Node,erlang,statistics,[scheduler_wall_time]),
@@ -1384,9 +1396,9 @@ upgrade_supervisor(Conf) when is_list(Conf) ->
%% Check that the restart strategy and child spec is updated
{status, _, {module, _}, [_, _, _, _, [_,_,{data,[{"State",State}]}|_]]} =
rpc:call(Node,sys,get_status,[a_sup]),
- {state,_,RestartStrategy,[Child],_,_,_,_,_,_,_} = State,
+ {state,_,RestartStrategy,{[a],Db},_,_,_,_,_,_,_} = State,
one_for_all = RestartStrategy, % changed from one_for_one
- {child,_,_,_,_,brutal_kill,_,_} = Child, % changed from timeout 2000
+ {child,_,_,_,_,brutal_kill,_,_} = maps:get(a,Db), % changed from timeout 2000
ok.
@@ -1835,24 +1847,32 @@ otp_10463_upgrade_script_regexp(cleanup,Config) ->
code:del_path(filename:join([DataDir,regexp_appup,app1,ebin])),
ok.
-no_dot_erlang(Conf) ->
- PrivDir = ?config(data_dir,Conf),
- {ok, OrigWd} = file:get_cwd(),
- try
- ok = file:set_cwd(PrivDir),
-
- {ok, Wd} = file:get_cwd(),
- io:format("Dir ~ts~n", [Wd]),
+no_dot_erlang(_Conf) ->
+ case init:get_argument(home) of
+ {ok,[[Home]]} when is_list(Home) ->
+ no_dot_erlang_1(Home);
+ _ -> ok
+ end.
+no_dot_erlang_1(Home) ->
+ DotErlang = filename:join(Home, ".erlang"),
+ BupErlang = filename:join(Home, ".erlang_testbup"),
+ try
+ {ok, Wd} = file:get_cwd(),
+ case filelib:is_file(DotErlang) of
+ true -> {ok, _} = file:copy(DotErlang, BupErlang);
+ false -> ok
+ end,
Erl0 = filename:join([code:root_dir(),"bin","erl"]),
Erl = filename:nativename(Erl0),
Quote = "\"",
Args = " -noinput -run c pwd -run erlang halt",
- ok = file:write_file(".erlang", <<"io:put_chars(\"DOT_ERLANG_READ\\n\").\n">>),
+ ok = file:write_file(DotErlang, <<"io:put_chars(\"DOT_ERLANG_READ\\n\").\n">>),
CMD1 = Quote ++ Erl ++ Quote ++ Args ,
case os:cmd(CMD1) of
- "DOT_ERLANG_READ" ++ _ -> ok;
+ "DOT_ERLANG_READ" ++ _ ->
+ io:format("~p: Success~n", [?LINE]);
Other1 ->
io:format("Failed: ~ts~n",[CMD1]),
io:format("Expected: ~s ++ _~n",["DOT_ERLANG_READ "]),
@@ -1862,7 +1882,7 @@ no_dot_erlang(Conf) ->
NO_DOT_ERL = " -boot no_dot_erlang",
CMD2 = Quote ++ Erl ++ Quote ++ NO_DOT_ERL ++ Args,
case lists:prefix(Wd, Other2 = os:cmd(CMD2)) of
- true -> ok;
+ true -> io:format("~p: Success~n", [?LINE]);
false ->
io:format("Failed: ~ts~n",[CMD2]),
io:format("Expected: ~s~n",["TESTOK"]),
@@ -1870,11 +1890,95 @@ no_dot_erlang(Conf) ->
exit({failed_to_start, no_dot_erlang})
end
after
- _ = file:delete(".erlang"),
- ok = file:set_cwd(OrigWd),
- ok
+ case filelib:is_file(BupErlang) of
+ true ->
+ {ok, _} = file:copy(BupErlang, DotErlang),
+ _ = file:delete(BupErlang);
+ false ->
+ _ = file:delete(DotErlang)
+ end
end.
+%%%-----------------------------------------------------------------
+%%% Test unicode handling. Make sure that release name, application
+%%% description, and application environment variables may contain
+%%% unicode characters.
+unicode_upgrade(Conf) ->
+ %% Set some paths
+ DataDir = ?config(data_dir, Conf),
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"unicode"),
+ LibDir0 = filename:join(DataDir, "unicode"),
+ LibDir =
+ case {file:native_name_encoding(),os:type()} of
+ {utf8,{Os,_}} when Os =/= win32 ->
+ LD = filename:join(DataDir,"unicode_αβ"),
+ file:make_symlink("unicode",LD),
+ LD;
+ _ ->
+ LibDir0
+ end,
+
+ %% Create the releases
+ RelName = "unicode_rel_αβ",
+ Rel1 = create_and_install_fake_first_release(Dir,{RelName,"1"},
+ [{u,"1.0",LibDir}]),
+ Rel2 = create_fake_upgrade_release(Dir,
+ {RelName,"2"},
+ [{u,"1.1",LibDir}],
+ {[Rel1],[Rel1],[LibDir]}),
+ Rel1Dir = filename:dirname(Rel1),
+ Rel2Dir = filename:dirname(Rel2),
+
+ %% Start a slave node
+ {ok, Node} = t_start_node(unicode_upgrade, Rel1,
+ filename:join(Rel1Dir,"sys.config"), "+pc unicode"),
+
+ %% Check
+ Dir1 = filename:join([LibDir, "u-1.0"]),
+ Dir1 = rpc:call(Node, code, lib_dir, [u]),
+ UBeam1 = filename:join([Dir1,"ebin","u.beam"]),
+ UBeam1 = rpc:call(Node,code,which,[u]),
+ {RelName,"1"} = rpc:call(Node,init,script_id,[]),
+ {Env,state} = rpc:call(Node,u,u,[]),
+ 'val_αβ' = proplists:get_value('key_αβ',Env),
+ [{RelName,"1",_,permanent}|_] =
+ rpc:call(Node,release_handler,which_releases,[]),
+ {ok,ReleasesDir} = rpc:call(Node,application,get_env,[sasl,releases_dir]),
+ {ok,[[{release,RelName,"1",_,_,permanent}|_]]} =
+ file:consult(filename:join(ReleasesDir,"RELEASES")),
+
+ %% Install second release
+ {ok, RelVsn2} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", [{u,"1.1",LibDir}]]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "relup")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "start.boot")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "sys.config")]),
+
+ {ok, _RelVsn1, []} =
+ rpc:call(Node, release_handler, install_release, [RelVsn2]),
+
+ %% And check
+ Dir2 = filename:join([LibDir, "u-1.1"]),
+ Dir2 = rpc:call(Node, code, lib_dir, [u]),
+ UBeam2 = filename:join([Dir2,"ebin","u.beam"]),
+ {file,UBeam2} = rpc:call(Node,code,is_loaded,[u]),
+ {RelName,"1"} = rpc:call(Node,init,script_id,[]),
+ {Env,{state,'αβ'}} = rpc:call(Node,u,u,[]),
+ [{RelName,"2",_,current}|_] =
+ rpc:call(Node,release_handler,which_releases,[]),
+ {ok,ReleasesDir2} = rpc:call(Node,application,get_env,[sasl,releases_dir]),
+ {ok,<<"%% coding: utf-8\n[{release,\"unicode_rel_αβ\",\"2\""/utf8,_/binary>>}=
+ file:read_file(filename:join(ReleasesDir2,"RELEASES")),
+ ok.
+
+unicode_upgrade(cleanup,_Conf) ->
+ stop_node(node_name(unicode_upgrade)).
+
%%%=================================================================
%%% Misceleaneous functions
@@ -2002,6 +2106,8 @@ are_names_reg_gg(Node, Names, N) ->
t_start_node(Name, Boot, SysConfig) ->
+ t_start_node(Name, Boot, SysConfig, "").
+t_start_node(Name, Boot, SysConfig, ArgStr) ->
Args =
case Boot of
[] -> [];
@@ -2010,8 +2116,9 @@ t_start_node(Name, Boot, SysConfig) ->
case SysConfig of
[] -> [];
_ -> " -config " ++ SysConfig
- end,
- test_server:start_node(Name, slave, [{args, Args}]).
+ end ++
+ " " ++ ArgStr,
+ test_server:start_node(Name, peer, [{args, Args}]).
stop_node(Node) ->
?t:stop_node(Node).
@@ -2460,7 +2567,9 @@ create_rel_file(RelFile,RelName,RelVsn,Erts,ExtraApps) ->
%% Insert a term in a file, which can be read with file:consult/1.
write_term_file(File,Term) ->
- ok = file:write_file(File,io_lib:format("~p.~n",[Term])).
+ Str = io_lib:format("%% ~s~n~tp.~n",[epp:encoding_to_string(utf8),Term]),
+ Bin = unicode:characters_to_binary(Str),
+ ok = file:write_file(File,Bin).
%% Check that global group info is correct - try again for a maximum of 5 sec
@@ -2471,15 +2580,15 @@ check_gg_info(Node,OtherAlive,OtherDead,Synced,N) ->
GGI = rpc:call(Node, global_group, info, []),
GI = rpc:call(Node, global, info,[]),
try do_check_gg_info(OtherAlive,OtherDead,Synced,GGI,GI)
- catch _:E when N==0 ->
+ catch _:E:Stacktrace when N==0 ->
?t:format("~nERROR: check_gg_info failed for ~p:~n~p~n"
"when GGI was: ~p~nand GI was: ~p~n",
- [Node,{E,erlang:get_stacktrace()},GGI,GI]),
+ [Node,{E,Stacktrace},GGI,GI]),
?t:fail("check_gg_info failed");
- _:E ->
+ _:E:Stacktrace ->
?t:format("~nWARNING: check_gg_info failed for ~p:~n~p~n"
"when GGI was: ~p~nand GI was: ~p~n",
- [Node,{E,erlang:get_stacktrace()},GGI,GI]),
+ [Node,{E,Stacktrace},GGI,GI]),
timer:sleep(1000),
check_gg_info(Node,OtherAlive,OtherDead,Synced,N-1)
end.
@@ -2719,8 +2828,8 @@ cover_fun(Node,Func) ->
%% and possibly other applications if they are listed in AppDirs =
%% [{App,Vsn,LibDir}]
create_and_install_fake_first_release(Dir,AppDirs) ->
- %% Create the first release
- {RelName,RelVsn} = init:script_id(),
+ create_and_install_fake_first_release(Dir,init:script_id(),AppDirs).
+create_and_install_fake_first_release(Dir,{RelName,RelVsn},AppDirs) ->
{Rel,_} = create_fake_release(Dir,RelName,RelVsn,AppDirs),
ReleasesDir = filename:join(Dir, "releases"),
RelDir = filename:dirname(Rel),
@@ -2744,9 +2853,11 @@ create_and_install_fake_first_release(Dir,AppDirs) ->
%% be upgraded to from the release created by
%% create_and_install_fake_first_release/2. Unpack first by calls to
%% release_handler:set_unpacked and release_handler:install_file.
-create_fake_upgrade_release(Dir,RelVsn,AppDirs,{UpFrom,DownTo,ExtraLibs}) ->
- %% Create a new release
+create_fake_upgrade_release(Dir,RelVsn,AppDirs,UpgrInstr) when not is_tuple(RelVsn) ->
{RelName,_} = init:script_id(),
+ create_fake_upgrade_release(Dir,{RelName,RelVsn},AppDirs,UpgrInstr);
+create_fake_upgrade_release(Dir,{RelName,RelVsn},AppDirs,{UpFrom,DownTo,ExtraLibs}) ->
+ %% Create a new release
{Rel,Paths} = create_fake_release(Dir,RelName,RelVsn,AppDirs),
RelDir = filename:dirname(Rel),
diff --git a/lib/sasl/test/release_handler_SUITE_data/Makefile.src b/lib/sasl/test/release_handler_SUITE_data/Makefile.src
index b794aa0e6f..113d3e2290 100644
--- a/lib/sasl/test/release_handler_SUITE_data/Makefile.src
+++ b/lib/sasl/test/release_handler_SUITE_data/Makefile.src
@@ -76,7 +76,13 @@ SUP= \
release_handler_timeouts/dummy-0.1/ebin/dummy_sup.@EMULATOR@ \
release_handler_timeouts/dummy-0.1/ebin/dummy_sup_2.@EMULATOR@
-all: $(LIB) $(APP) $(OTP2740) $(C) $(SUP)
+UNICODE= \
+ unicode/u-1.0/ebin/u.@EMULATOR@ \
+ unicode/u-1.0/ebin/u_sup.@EMULATOR@ \
+ unicode/u-1.1/ebin/u.@EMULATOR@ \
+ unicode/u-1.1/ebin/u_sup.@EMULATOR@
+
+all: $(LIB) $(APP) $(OTP2740) $(C) $(SUP) $(UNICODE)
lib/a-1.0/ebin/a.@EMULATOR@: lib/a-1.0/src/a.erl
erlc $(EFLAGS) -olib/a-1.0/ebin lib/a-1.0/src/a.erl
@@ -236,3 +242,13 @@ release_handler_timeouts/dummy-0.1/ebin/dummy_sup.@EMULATOR@: release_handler_ti
erlc $(EFLAGS) -orelease_handler_timeouts/dummy-0.1/ebin release_handler_timeouts/dummy-0.1/src/dummy_sup.erl
release_handler_timeouts/dummy-0.1/ebin/dummy_sup_2.@EMULATOR@: release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl
erlc $(EFLAGS) -orelease_handler_timeouts/dummy-0.1/ebin release_handler_timeouts/dummy-0.1/src/dummy_sup_2.erl
+
+unicode/u-1.0/ebin/u.@EMULATOR@: unicode/u-1.0/src/u.erl
+ erlc $(EFLAGS) -ounicode/u-1.0/ebin unicode/u-1.0/src/u.erl
+unicode/u-1.0/ebin/u_sup.@EMULATOR@: unicode/u-1.0/src/u_sup.erl
+ erlc $(EFLAGS) -ounicode/u-1.0/ebin unicode/u-1.0/src/u_sup.erl
+
+unicode/u-1.1/ebin/u.@EMULATOR@: unicode/u-1.1/src/u.erl
+ erlc $(EFLAGS) -ounicode/u-1.1/ebin unicode/u-1.1/src/u.erl
+unicode/u-1.1/ebin/u_sup.@EMULATOR@: unicode/u-1.1/src/u_sup.erl
+ erlc $(EFLAGS) -ounicode/u-1.1/ebin unicode/u-1.1/src/u_sup.erl
diff --git a/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/ebin/u.app b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/ebin/u.app
new file mode 100644
index 0000000000..fea4f9992e
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/ebin/u.app
@@ -0,0 +1,8 @@
+{application, u,
+ [{description, "This app shall test unicode handling αβ"},
+ {vsn, "1.0"},
+ {modules, [u, u_sup]},
+ {registered, [u_sup]},
+ {applications, [kernel, stdlib]},
+ {env, [{'key_αβ', 'val_αβ'}]},
+ {mod, {u_sup, []}}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/src/u.erl b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/src/u.erl
new file mode 100644
index 0000000000..45fe098c0e
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/src/u.erl
@@ -0,0 +1,50 @@
+%% ``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.
+%%
+%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% $Id$
+%%
+-module(u).
+
+
+-behaviour(gen_server).
+
+-vsn(1).
+
+%% External exports
+-export([start_link/0, u/0]).
+%% Internal exports
+-export([init/1, handle_call/3, handle_info/2, terminate/2]).
+
+start_link() -> gen_server:start_link({local, uu}, u, [], []).
+
+u() -> gen_server:call(uu, u).
+
+%%-----------------------------------------------------------------
+%% Callback functions from gen_server
+%%-----------------------------------------------------------------
+init([]) ->
+ process_flag(trap_exit, true),
+ {ok, state}.
+
+handle_call(u, _From, State) ->
+ X = application:get_all_env(u),
+ {reply, {X,State}, State}.
+
+handle_info(_, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/src/u_sup.erl b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/src/u_sup.erl
new file mode 100644
index 0000000000..b0d4a7b58f
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.0/src/u_sup.erl
@@ -0,0 +1,38 @@
+%% ``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.
+%%
+%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% $Id$
+%%
+-module(u_sup).
+
+
+-behaviour(supervisor).
+
+%% External exports
+-export([start/2]).
+
+%% Internal exports
+-export([init/1]).
+
+start(_, _) ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init([]) ->
+ SupFlags = {one_for_one, 4, 3600},
+ Config = {u,
+ {u, start_link, []},
+ permanent, 2000, worker, [u]},
+ {ok, {SupFlags, [Config]}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/ebin/u.app b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/ebin/u.app
new file mode 100644
index 0000000000..8fcc3bba42
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/ebin/u.app
@@ -0,0 +1,8 @@
+{application, u,
+ [{description, "This app shall test unicode handling αβ"},
+ {vsn, "1.1"},
+ {modules, [u, u_sup]},
+ {registered, [u_sup]},
+ {applications, [kernel, stdlib]},
+ {env, [{'key_αβ', 'val_αβ'}]},
+ {mod, {u_sup, []}}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/ebin/u.appup b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/ebin/u.appup
new file mode 100644
index 0000000000..0344ce92ab
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/ebin/u.appup
@@ -0,0 +1,3 @@
+{"1.1",
+ [{"1.0",[{update,u,{advanced,'αβ'}}]}],
+ [{"1.0",[{update,u,{advanced,'αβ'}}]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/src/u.erl b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/src/u.erl
new file mode 100644
index 0000000000..d2544d6fc1
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/src/u.erl
@@ -0,0 +1,55 @@
+%% ``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.
+%%
+%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% $Id$
+%%
+-module(u).
+
+
+-behaviour(gen_server).
+
+-vsn(1).
+
+%% External exports
+-export([start_link/0, u/0]).
+%% Internal exports
+-export([init/1, handle_call/3, handle_info/2, terminate/2, code_change/3]).
+
+start_link() -> gen_server:start_link({local, uu}, u, [], []).
+
+u() -> gen_server:call(uu, u).
+
+%%-----------------------------------------------------------------
+%% Callback functions from gen_server
+%%-----------------------------------------------------------------
+init([]) ->
+ process_flag(trap_exit, true),
+ {ok, {state,'αβ'}}.
+
+handle_call(u, _From, State) ->
+ X = application:get_all_env(u),
+ {reply, {X,State}, State}.
+
+handle_info(_, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change({down,_}, {State,_}, _Extra) ->
+ {ok, State};
+code_change(_, State, Extra) ->
+ {ok, {State, Extra}}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/src/u_sup.erl b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/src/u_sup.erl
new file mode 100644
index 0000000000..b0d4a7b58f
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/unicode/u-1.1/src/u_sup.erl
@@ -0,0 +1,38 @@
+%% ``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.
+%%
+%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% $Id$
+%%
+-module(u_sup).
+
+
+-behaviour(supervisor).
+
+%% External exports
+-export([start/2]).
+
+%% Internal exports
+-export([init/1]).
+
+start(_, _) ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init([]) ->
+ SupFlags = {one_for_one, 4, 3600},
+ Config = {u,
+ {u, start_link, []},
+ permanent, 2000, worker, [u]},
+ {ok, {SupFlags, [Config]}}.
diff --git a/lib/sasl/test/sasl_SUITE.erl b/lib/sasl/test/sasl_SUITE.erl
index f12bde9b3d..fc80e37210 100644
--- a/lib/sasl/test/sasl_SUITE.erl
+++ b/lib/sasl/test/sasl_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
-include_lib("common_test/include/ct.hrl").
%% Test server specific exports
+-export([init_per_suite/1,end_per_suite/1]).
-export([all/0,groups/0,init_per_group/2,end_per_group/2]).
-export([init_per_testcase/2, end_per_testcase/2]).
@@ -37,6 +38,19 @@ all() ->
groups() ->
[].
+init_per_suite(Config) ->
+ S = application:get_env(kernel,logger_sasl_compatible),
+ application:set_env(kernel,logger_sasl_compatible,true),
+ [{sasl_compatible,S}|Config].
+
+end_per_suite(Config) ->
+ case ?config(sasl_compatible,Config) of
+ {ok,X} ->
+ application:set_env(kernel,logger_sasl_compatible,X);
+ undefined ->
+ application:unset_env(kernel,logger_sasl_compatible)
+ end.
+
init_per_group(_GroupName, Config) ->
Config.
diff --git a/lib/sasl/test/sasl_report_SUITE.erl b/lib/sasl/test/sasl_report_SUITE.erl
index 53fb614921..e639b55cee 100644
--- a/lib/sasl/test/sasl_report_SUITE.erl
+++ b/lib/sasl/test/sasl_report_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,7 +20,8 @@
-module(sasl_report_SUITE).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
--export([gen_server_crash/1]).
+-export([gen_server_crash/1, gen_server_crash_unicode/1]).
+-export([legacy_gen_server_crash/1, legacy_gen_server_crash_unicode/1]).
-export([crash_me/0,start_link/0,init/1,handle_cast/2,terminate/2]).
@@ -29,7 +30,10 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [gen_server_crash].
+ [gen_server_crash,
+ gen_server_crash_unicode,
+ legacy_gen_server_crash,
+ legacy_gen_server_crash_unicode].
groups() ->
[].
@@ -47,47 +51,123 @@ end_per_group(_GroupName, Config) ->
Config.
gen_server_crash(Config) ->
+ gen_server_crash(Config, latin1).
+
+gen_server_crash_unicode(Config) ->
+ gen_server_crash(Config, unicode).
+
+legacy_gen_server_crash(Config) ->
+ legacy_gen_server_crash(Config,latin1).
+
+legacy_gen_server_crash_unicode(Config) ->
+ legacy_gen_server_crash(Config,unicode).
+
+gen_server_crash(Config, Encoding) ->
+ TC = list_to_atom(lists:concat([?FUNCTION_NAME,"_",Encoding])),
+ PrivDir = filename:join(?config(priv_dir,Config),?MODULE),
+ ConfigFileName = filename:join(PrivDir,TC),
+ KernelLog = filename:join(PrivDir,lists:concat([TC,"_kernel.log"])),
+ SaslLog = filename:join(PrivDir,lists:concat([TC,"_sasl.log"])),
+ KernelConfig = [{logger,[{handler,default,logger_std_h,
+ #{config=>#{type=>{file,KernelLog}}}}]},
+ {logger_sasl_compatible,true}],
+ Modes = [write, {encoding, Encoding}],
+ SaslConfig = [{sasl_error_logger,{file,SaslLog,Modes}}],
+ ok = filelib:ensure_dir(SaslLog),
+
+ ok = file:write_file(ConfigFileName ++ ".config",
+ io_lib:format("[{kernel, ~p},~n{sasl, ~p}].",
+ [KernelConfig,SaslConfig])),
+ {ok,Node} =
+ test_server:start_node(
+ TC, peer,
+ [{args, ["-pa ",filename:dirname(code:which(?MODULE)),
+ " -boot start_sasl -kernel start_timer true "
+ "-config ",ConfigFileName]}]),
+
+ %% Set depth
+ ok = rpc:call(Node,logger,update_formatter_config,[default,depth,30]),
+ ok = rpc:call(Node,logger,update_formatter_config,[sasl,depth,30]),
+
+ %% Make sure remote node logs it's own logs, and current node does
+ %% not log them.
+ ok = rpc:call(Node,logger,remove_handler_filter,[default,remote_gl]),
+ ok = rpc:call(Node,logger,remove_handler_filter,[sasl,remote_gl]),
+ ok = logger:add_primary_filter(no_remote,{fun(#{meta:=#{pid:=Pid}},_)
+ when node(Pid)=/=node() -> stop;
+ (_,_) -> ignore
+ end,[]}),
+ ct:log("Local node Logger config:~n~p",
+ [rpc:call(Node,logger,get_config,[])]),
+ ct:log("Remote node Logger config:~n~p",
+ [rpc:call(Node,logger,get_config,[])]),
+ ct:log("Remote node error_logger handlers: ~p",
+ [rpc:call(Node,error_logger,which_report_handlers,[])]),
+
+ ok = rpc:call(Node,?MODULE,crash_me,[]),
+
+ ok = rpc:call(Node,logger_std_h,filesync,[default]),
+ ok = rpc:call(Node,logger_std_h,filesync,[sasl]),
+
+ test_server:stop_node(Node),
+ ok = logger:remove_primary_filter(no_remote),
+
+ check_file(KernelLog, utf8, 70000, 150000),
+ check_file(SaslLog, Encoding, 70000, 150000),
+
+ ok = file:delete(KernelLog),
+ ok = file:delete(SaslLog),
+
+ ok.
+
+legacy_gen_server_crash(Config, Encoding) ->
+ StopFilter = {fun(_,_) -> stop end, ok},
+ logger:add_handler_filter(default,stop_all,StopFilter),
+ logger:add_handler_filter(sasl,stop_all,StopFilter),
+ logger:add_handler_filter(cth_log_redirect,stop_all,StopFilter),
try
- do_gen_server_crash(Config)
+ do_gen_server_crash(Config, Encoding)
after
- error_logger:tty(true),
- ok = application:unset_env(sasl, sasl_error_logger),
- ok = application:unset_env(kernel, error_logger_format_depth),
- error_logger:add_report_handler(cth_log_redirect)
+ logger:remove_handler_filter(default,stop_all),
+ logger:remove_handler_filter(sasl,stop_all),
+ logger:remove_handler_filter(cth_log_redirect,stop_all)
end,
ok.
-do_gen_server_crash(Config) ->
+do_gen_server_crash(Config, Encoding) ->
PrivDir = ?config(priv_dir, Config),
LogDir = filename:join(PrivDir, ?MODULE),
KernelLog = filename:join(LogDir, "kernel.log"),
SaslLog = filename:join(LogDir, "sasl.log"),
ok = filelib:ensure_dir(SaslLog),
- error_logger:delete_report_handler(cth_log_redirect),
- error_logger:tty(false),
- application:stop(sasl),
- ok = application:set_env(sasl, sasl_error_logger, {file,SaslLog},
- [{persistent,true}]),
+ Modes = [write, {encoding, Encoding}],
application:set_env(kernel, error_logger_format_depth, 30),
error_logger:logfile({open,KernelLog}),
- application:start(sasl),
- io:format("~p\n", [gen_event:which_handlers(error_logger)]),
+ error_logger:add_report_handler(sasl_report_file_h,{SaslLog,Modes,all}),
+ ct:log("Logger config:~n~p",[logger:get_config()]),
+ ct:log("error_logger handlers: ~p",[error_logger:which_report_handlers()]),
crash_me(),
error_logger:logfile(close),
+ error_logger:delete_report_handler(sasl_report_file_h),
- check_file(KernelLog, 70000, 150000),
- check_file(SaslLog, 100000, 150000),
+ check_file(KernelLog, utf8, 70000, 150000),
+ check_file(SaslLog, Encoding, 70000, 150000),
+ ok = file:delete(KernelLog),
+ ok = file:delete(SaslLog),
ok.
-check_file(File, Min, Max) ->
+check_file(File, Encoding, Min, Max) ->
{ok,Bin} = file:read_file(File),
Base = filename:basename(File),
io:format("*** Contents of ~s ***\n", [Base]),
- io:put_chars([Bin,"\n"]),
+ case Encoding of
+ latin1 -> io:format("~s\n", [Bin]);
+ _ -> io:format("~ts\n", [Bin])
+ end,
Sz = byte_size(Bin),
io:format("Size: ~p (allowed range is ~p..~p)\n",
[Sz,Min,Max]),
@@ -110,7 +190,9 @@ crash_me() ->
{ok,SuperPid} = supervisor:start_link(sasl_report_suite_supervisor, []),
[{Id,Pid,_,_}] = supervisor:which_children(SuperPid),
HugeData = gb_sets:from_list(lists:seq(1, 100000)),
- gen_server:cast(Pid, HugeData),
+ SomeData1 = list_to_atom([246]),
+ SomeData2 = list_to_atom([1024]),
+ gen_server:cast(Pid, {HugeData,SomeData1,SomeData2}),
Ref = monitor(process, Pid),
receive
{'DOWN',Ref,process,Pid,_} ->
@@ -129,6 +211,12 @@ init(_) ->
handle_cast(Big, St) ->
Seq = lists:seq(1, 10000),
+ Latin1Atom = list_to_atom([246]),
+ UnicodeAtom = list_to_atom([1024]),
+ put(Latin1Atom, Latin1Atom),
+ put(UnicodeAtom, UnicodeAtom),
+ self() ! Latin1Atom,
+ self() ! UnicodeAtom,
self() ! Seq,
self() ! Seq,
self() ! Seq,
diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl
index 07748d975f..1827974866 100644
--- a/lib/sasl/test/systools_SUITE.erl
+++ b/lib/sasl/test/systools_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2012-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.
@@ -67,7 +67,7 @@ groups() ->
otp_3065_circular_dependenies, included_and_used_sort_script]},
{tar, [],
[tar_options, normal_tar, no_mod_vsn_tar, system_files_tar,
- invalid_system_files_tar, variable_tar,
+ system_src_file_tar, invalid_system_files_tar, variable_tar,
src_tests_tar, var_tar, exref_tar, link_tar, no_sasl_tar,
otp_9507_path_ebin]},
{relup, [],
@@ -945,12 +945,47 @@ system_files_tar(Config) ->
ok.
+
system_files_tar(cleanup,Config) ->
Dir = ?privdir,
file:delete(filename:join(Dir,"sys.config")),
file:delete(filename:join(Dir,"relup")),
ok.
+%% make_tar: Check that sys.config.src and not sys.config is included
+system_src_file_tar(Config) ->
+ {ok, OldDir} = file:get_cwd(),
+
+ {LatestDir, LatestName} = create_script(latest,Config),
+
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_normal, lib]),
+ P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
+
+ ok = file:set_cwd(LatestDir),
+
+ %% Add dummy sys.config and sys.config.src
+ ok = file:write_file("sys.config.src","[${SOMETHING}].\n"),
+ ok = file:write_file("sys.config","[].\n"),
+
+ {ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
+ ok = systools:make_tar(LatestName, [{path, P}]),
+ ok = check_tar(fname(["releases","LATEST","sys.config.src"]), LatestName),
+ {error, _} = check_tar(fname(["releases","LATEST","sys.config"]), LatestName),
+ {ok, _, _} = systools:make_tar(LatestName, [{path, P}, silent]),
+ ok = check_tar(fname(["releases","LATEST","sys.config.src"]), LatestName),
+ {error, _} = check_tar(fname(["releases","LATEST","sys.config"]), LatestName),
+
+ ok = file:set_cwd(OldDir),
+
+ ok.
+
+system_src_file_tar(cleanup,Config) ->
+ Dir = ?privdir,
+ file:delete(filename:join(Dir,"sys.config")),
+ file:delete(filename:join(Dir,"sys.config.src")),
+ ok.
%% make_tar: Check that make_tar fails if relup or sys.config exist
%% but do not have valid content
@@ -1760,27 +1795,28 @@ normal_hybrid(Config) ->
ok = file:set_cwd(OldDir),
- BasePaths = {"testkernelpath","teststdlibpath","testsaslpath"},
{ok,Hybrid} = systools_make:make_hybrid_boot("tmp_vsn",Boot1,Boot2,
- BasePaths, [dummy,args]),
+ [dummy,args]),
{script,{"Test release","tmp_vsn"},Script} = binary_to_term(Hybrid),
ct:log("~p.~n",[Script]),
%% Check that all paths to base apps are replaced by paths from BaseLib
Boot1Str = io_lib:format("~p~n",[binary_to_term(Boot1)]),
+ Boot2Str = io_lib:format("~p~n",[binary_to_term(Boot2)]),
HybridStr = io_lib:format("~p~n",[binary_to_term(Hybrid)]),
ReOpts = [global,{capture,first,list},unicode],
{match,OldKernelMatch} = re:run(Boot1Str,"kernel-[0-9\.]+",ReOpts),
{match,OldStdlibMatch} = re:run(Boot1Str,"stdlib-[0-9\.]+",ReOpts),
{match,OldSaslMatch} = re:run(Boot1Str,"sasl-[0-9\.]+",ReOpts),
- nomatch = re:run(HybridStr,"kernel-[0-9\.]+",ReOpts),
- nomatch = re:run(HybridStr,"stdlib-[0-9\.]+",ReOpts),
- nomatch = re:run(HybridStr,"sasl-[0-9\.]+",ReOpts),
- {match,NewKernelMatch} = re:run(HybridStr,"testkernelpath",ReOpts),
- {match,NewStdlibMatch} = re:run(HybridStr,"teststdlibpath",ReOpts),
- {match,NewSaslMatch} = re:run(HybridStr,"testsaslpath",ReOpts),
+ {match,NewKernelMatch} = re:run(Boot2Str,"kernel-[0-9\.]+",ReOpts),
+ {match,NewStdlibMatch} = re:run(Boot2Str,"stdlib-[0-9\.]+",ReOpts),
+ {match,NewSaslMatch} = re:run(Boot2Str,"sasl-[0-9\.]+",ReOpts),
+
+ {match,NewKernelMatch} = re:run(HybridStr,"kernel-[0-9\.]+",ReOpts),
+ {match,NewStdlibMatch} = re:run(HybridStr,"stdlib-[0-9\.]+",ReOpts),
+ {match,NewSaslMatch} = re:run(HybridStr,"sasl-[0-9\.]+",ReOpts),
NewKernelN = length(NewKernelMatch),
NewKernelN = length(OldKernelMatch),
@@ -1789,6 +1825,11 @@ normal_hybrid(Config) ->
NewSaslN = length(NewSaslMatch),
NewSaslN = length(OldSaslMatch),
+ %% Check that kernelProcesses are taken from new boot script
+ {script,_,Script2} = binary_to_term(Boot2),
+ NewKernelProcs = [KP || KP={kernelProcess,_,_} <- Script2],
+ NewKernelProcs = [KP || KP={kernelProcess,_,_} <- Script],
+
%% Check that application load instruction has correct versions
Apps = application:loaded_applications(),
{_,_,KernelVsn} = lists:keyfind(kernel,1,Apps),
@@ -1859,10 +1900,8 @@ hybrid_no_old_sasl(Config) ->
{ok,Boot1} = file:read_file(Name1 ++ ".boot"),
{ok,Boot2} = file:read_file(Name2 ++ ".boot"),
- BasePaths = {"testkernelpath","teststdlibpath","testsaslpath"},
{error,{app_not_replaced,sasl}} =
- systools_make:make_hybrid_boot("tmp_vsn",Boot1,Boot2,
- BasePaths,[dummy,args]),
+ systools_make:make_hybrid_boot("tmp_vsn",Boot1,Boot2,[dummy,args]),
ok = file:set_cwd(OldDir),
ok.
@@ -1892,10 +1931,8 @@ hybrid_no_new_sasl(Config) ->
{ok,Boot1} = file:read_file(Name1 ++ ".boot"),
{ok,Boot2} = file:read_file(Name2 ++ ".boot"),
- BasePaths = {"testkernelpath","teststdlibpath","testsaslpath"},
{error,{app_not_found,sasl}} =
- systools_make:make_hybrid_boot("tmp_vsn",Boot1,Boot2,
- BasePaths,[dummy,args]),
+ systools_make:make_hybrid_boot("tmp_vsn",Boot1,Boot2,[dummy,args]),
ok = file:set_cwd(OldDir),
ok.
diff --git a/lib/sasl/test/test_lib.hrl b/lib/sasl/test/test_lib.hrl
index 9a54937f96..f5210d4f27 100644
--- a/lib/sasl/test/test_lib.hrl
+++ b/lib/sasl/test/test_lib.hrl
@@ -1,3 +1,3 @@
-define(ertsvsn,"4.4").
--define(kernelvsn,"5.0").
--define(stdlibvsn,"3.0").
+-define(kernelvsn,"5.3").
+-define(stdlibvsn,"3.4").
diff --git a/lib/sasl/vsn.mk b/lib/sasl/vsn.mk
index 2608ca5e00..94b7f9dc56 100644
--- a/lib/sasl/vsn.mk
+++ b/lib/sasl/vsn.mk
@@ -1 +1 @@
-SASL_VSN = 3.0.4
+SASL_VSN = 3.2.1
diff --git a/lib/snmp/doc/src/Makefile b/lib/snmp/doc/src/Makefile
index 9ea5dba0c5..e7ab491eef 100644
--- a/lib/snmp/doc/src/Makefile
+++ b/lib/snmp/doc/src/Makefile
@@ -1,9 +1,9 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
+#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -15,7 +15,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
+#
# %CopyrightEnd%
include $(ERL_TOP)/make/target.mk
@@ -66,7 +66,6 @@ HTML_REF6_FILES = $(XML_REF6_FILES:%.xml=$(HTMLDIR)/%.html)
HTML_CHAP_FILES = $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html)
EXTRA_FILES = \
- summary.html.src \
$(DEFAULT_HTML_FILES) \
$(HTML_REF1_FILES) \
$(HTML_REF3_FILES) \
@@ -85,18 +84,14 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
-INDEX_FILE = index.html
-INDEX_SRC = $(INDEX_FILE).src
-INDEX_TARGET = $(DOCDIR)/$(INDEX_FILE)
-
GIF_TARGETS = $(GIF_FILES:%=$(HTMLDIR)/%)
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
+XML_FLAGS +=
+DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -106,21 +101,17 @@ $(HTMLDIR)/%.gif: %.gif # Copy them to ../html
docs: pdf html man
-ldocs: local_docs $(INDEX_TARGET)
+ldocs: local_docs
$(TOP_PDF_FILE): $(XML_FILES)
pdf: $(TOP_PDF_FILE)
html: gifs $(HTML_REF_MAN_FILE)
-html2: html $(INDEX_TARGET)
clean clean_docs: clean_html clean_man clean_pdf
rm -f errs core *~
-$(INDEX_TARGET): $(INDEX_SRC) ../../vsn.mk # Create top make file
- $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ # inserting version number
-
man: man1 man3 man6 man7
man1: $(MAN1_FILES)
@@ -133,7 +124,7 @@ man7: $(MAN7_FILES)
gifs: $(GIF_TARGETS)
-debug opt:
+debug opt:
clean_pdf:
@echo "cleaning pdf:"
@@ -149,7 +140,7 @@ clean_man:
clean_html:
@echo "cleaning html:"
rm -rf $(HTMLDIR)/*
- rm -f $(INDEX_TARGET)
+ rm -rf $(XMLDIR)
$(MAN7DIR)/%.7: $(MIBSDIR)/%.mib
@echo "processing $*"
@@ -162,7 +153,7 @@ $(MAN7DIR)/%.7: $(MIBSDIR)/%.mib
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
$(MAN1DIR)/snmpc.1: snmpc_cmd.xml
date=`date +"%B %e %Y"`; \
@@ -194,7 +185,7 @@ info: info_xml info_man info_html
@echo "MAN6DIR: $(MAN6DIR)"
@echo "MAN7DIR: $(MAN7DIR)"
-info_man:
+info_man:
@echo "man files:"
@echo "MAN1_FILES = $(MAN1_FILES)"
@echo "MAN3_FILES = $(MAN3_FILES)"
@@ -203,7 +194,7 @@ info_man:
@echo ""
@echo "MIB_FILES = $(MIB_FILES)"
-info_xml:
+info_xml:
@echo "xml files:"
# @echo "XML_REF1_FILES = $(XML_REF1_FILES)"
@echo "XML_REF3_FILES = $(XML_REF3_FILES)"
@@ -221,9 +212,7 @@ info_xml:
info_html:
@echo "html files:"
@echo "DOCDIR = $(DOCDIR)"
- @echo "INDEX_FILE = $(INDEX_FILE)"
- @echo "INDEX_SRC = $(INDEX_SRC)"
- @echo "INDEX_TARGET = $(INDEX_TARGET)"
+ @echo "HTML_REF_MAN_FILE = $(HTML_REF_MAN_FILE)"
@echo ""
@echo "HTMLDIR = $(HTMLDIR)"
@echo "HTML_APP_FILES = $(HTML_APP_FILES)"
diff --git a/lib/snmp/doc/src/book.gif b/lib/snmp/doc/src/book.gif
deleted file mode 100644
index 94b3868792..0000000000
--- a/lib/snmp/doc/src/book.gif
+++ /dev/null
Binary files differ
diff --git a/lib/snmp/doc/src/fascicules.xml b/lib/snmp/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/snmp/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/snmp/doc/src/files.mk b/lib/snmp/doc/src/files.mk
index 5aeae19105..f364cb6fa5 100644
--- a/lib/snmp/doc/src/files.mk
+++ b/lib/snmp/doc/src/files.mk
@@ -1,9 +1,9 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2001-2016. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 2001-2017. All Rights Reserved.
+#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -15,7 +15,7 @@
# 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%
XML_APPLICATION_FILES = \
@@ -81,9 +81,7 @@ XML_REF3_FILES = \
XML_REF6_FILES = snmp_app.xml
XML_PART_FILES = \
- part.xml \
- part_notes.xml \
- part_notes_history.xml
+ part.xml
XML_CHAPTER_FILES = \
snmp_intro.xml \
@@ -115,23 +113,16 @@ XML_FILES = $(BOOK_FILES) \
$(XML_REF6_FILES) \
$(XML_APPLICATION_FILES)
-GIF_FILES = book.gif \
+GIF_FILES = \
getnext1.gif \
getnext2.gif \
getnext3.gif \
getnext4.gif \
snmp_agent_netif_1.gif \
snmp_manager_netif_1.gif \
- min_head.gif \
- note.gif \
- notes.gif \
- ref_man.gif \
snmp-um-1-image-1.gif \
snmp-um-1-image-2.gif \
snmp-um-1-image-3.gif \
- snmp.gif \
- user_guide.gif \
- warning.gif \
MIB_mechanism.gif
PS_FILES = getnext1.ps \
diff --git a/lib/snmp/doc/src/index.html.src b/lib/snmp/doc/src/index.html.src
deleted file mode 100644
index e1b6be4d1f..0000000000
--- a/lib/snmp/doc/src/index.html.src
+++ /dev/null
@@ -1,99 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<!-- This file is obsolete -->
-<HTML>
-<!--
- ``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.
-
- The Initial Developer of the Original Code is Ericsson Utvecklings AB.
- Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
- AB. All Rights Reserved.''
-
- $Id$
--->
-<HEAD>
-<TITLE>SNMP %VSN%</TITLE>
-</HEAD>
-
-<BODY BGCOLOR="#FFFFFF">
-
-<CENTER>
-<A HREF="http://www.erlang.se/"><IMG ALT="Erlang/OTP" BORDER=0 SRC="html/min_head.gif"></A><BR>
-
-<FONT SIZE="-1">
-[<A HREF="../../../doc/index.html">Up</A> |
-<A HREF="http://www.erlang.se/">Erlang/OTP</A>]
-</FONT><BR>
-
-<P><FONT SIZE="+3">
-SNMP
-</FONT><BR>
-Version %VSN%
-</CENTER>
-
-<P><TABLE>
-<TR>
-<TD>
-<IMG ALIGN=LEFT ALT="SNMP" SRC="html/snmp.gif">
-</TD>
-
-<TD>
-<P>A bilingual Simple Network Management Protocol application,
- featuring an Extensible Agent, a simple manager, a MIB compiler
- and facilities for implementing SNMP MIBs etc.
-</TD>
-</TR>
-</TABLE>
-
-<P><CENTER>
-<TABLE CELLPADDING=15>
-<TR>
-<TD ALIGN=CENTER>
-<A HREF="html/users_guide.html"><IMG ALT="User's Guide" BORDER=0 SRC="html/user_guide.gif"></A><BR>
-<FONT SIZE="-1">
-<A HREF="html/users_guide.html">User's Guide</A>
-</FONT>
-</TD>
-
-<TD ALIGN=CENTER>
-<A HREF="html/index.html"><IMG ALT="Reference Manual" BORDER=0 SRC="html/ref_man.gif"></A><BR>
-<FONT SIZE="-1">
-<A HREF="html/index.html">Reference Manual</A>
-</FONT>
-</TD>
-
-<TD ALIGN=CENTER>
-<A HREF="html/release_notes.html"><IMG ALT="Release Notes" BORDER=0 SRC="html/notes.gif"></A><BR>
-<FONT SIZE="-1">
-<A HREF="html/release_notes.html">Release Notes</A>
-</FONT>
-</TD>
-
-<TD ALIGN=CENTER>
-<A HREF="pdf/snmp-%VSN%.pdf"><IMG ALT="Off-Print" BORDER=0 SRC="html/book.gif"></A><BR>
-<FONT SIZE="-1">
-<A HREF="pdf/snmp-%VSN%.pdf">Off-Print</A>
-</FONT>
-</TD>
-</TR>
-</TABLE>
-</CENTER>
-
-<P><CENTER>
-<HR>
-<FONT SIZE="-1">
-Copyright &copy; 1991-2001
-<A HREF="http://www.erlang.se/">Ericsson Utvecklings AB</A>
-</FONT>
-</CENTER>
-</BODY>
-</HTML>
diff --git a/lib/snmp/doc/src/min_head.gif b/lib/snmp/doc/src/min_head.gif
deleted file mode 100644
index 67948a6378..0000000000
--- a/lib/snmp/doc/src/min_head.gif
+++ /dev/null
Binary files differ
diff --git a/lib/snmp/doc/src/note.gif b/lib/snmp/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/snmp/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/snmp/doc/src/notes.gif b/lib/snmp/doc/src/notes.gif
deleted file mode 100644
index e000cca26a..0000000000
--- a/lib/snmp/doc/src/notes.gif
+++ /dev/null
Binary files differ
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index b902e421ca..423d90fef6 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -4,14 +4,14 @@
<chapter>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
@@ -19,7 +19,7 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-
+
</legalnotice>
<title>SNMP Release Notes</title>
@@ -34,7 +34,126 @@
</header>
- <section><title>SNMP 5.2.6</title>
+ <section><title>SNMP 5.2.12</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Conversion of (agent) Audit Trail Log (ATL) failed due
+ to invalid log entries.</p> <p>The conversion aborted
+ completely midway because the ATL contained invalid
+ entries. The conversion has been improved so that it now
+ firstly handles encountered errors and write an
+ informative message (into the converted stream) and
+ secondly keeps count of the number of successful or
+ failed entry conversions. See <seealso
+ marker="snmpa#log_to_txt">log_to_txt</seealso> for more
+ info. </p> <p>The reason the ATL contained invalid
+ entries have also been fixed. The reason was that for
+ some outgoing messages (not response):</p> <list
+ type="bulleted"> <item> <p>encrypted (v3 messages)</p>
+ <p>Was logged "as is" (encrypted) without the info to
+ decrypt, making conversion impossible (which was the
+ reason the log contained bad entries).</p> </item> <item>
+ <p>un-encrypted</p> <p>Was not logged at all. </p>
+ </item> </list>
+ <p>
+ Own Id: OTP-15287 Aux Id: ERIERL-206 </p>
+ </item>
+ <item>
+ <p>
+ [compiler] Spurious version message removed. The snmp mib
+ compiler printed an spurious version message if the
+ 'version' option was provided.</p>
+ <p>
+ Own Id: OTP-15290</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SNMP 5.2.11</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The Snmp MIB compiler now allows using a
+ TEXTUAL-CONVENTION type before defining it.</p>
+ <p>
+ Own Id: OTP-14196 Aux Id: ERIERL-161 </p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+<section><title>SNMP 5.2.10</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The example MIB EX1-MIB in the SNMP application has been
+ corrected to match its example.</p>
+ <p>
+ Own Id: OTP-14204 Aux Id: PR-1726 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SNMP 5.2.9</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SNMP 5.2.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The <c>recbuf</c> configuration option was not propagated
+ correctly to the socket for the SNMP Manager.</p>
+ <p>
+ Own Id: OTP-13372 Aux Id: ERIERL-73 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SNMP 5.2.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A bug in the SNMP MIB compiler has been fixed. An
+ AUGMENTS referring to a table defined later in the MIB
+ did not work.</p>
+ <p>
+ Own Id: OTP-13014 Aux Id: ERL-375 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SNMP 5.2.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
@@ -220,8 +339,8 @@
<list type="bulleted">
<item>
<p>[compiler] Refinement of type Opaque was not allowed. </p>
- <p>MIB constructs such as '<c>SYNTAX Opaque (SIZE(0..65535))</c>'
- was previously not allowed,
+ <p>MIB constructs such as '<c>SYNTAX Opaque (SIZE(0..65535))</c>'
+ was previously not allowed,
see the standard <c>ALARM-MIB</c> for eaxmple. </p>
<p>Own Id: OTP-12066</p>
<p>Aux Id: Seq 12669</p>
@@ -238,8 +357,8 @@
<!--
<list type="bulleted">
<item>
- <p>[agent]
- see <seealso marker="snmpa#load_mibs">load_mibs</seealso> and
+ <p>[agent]
+ see <seealso marker="snmpa#load_mibs">load_mibs</seealso> and
<seealso marker="snmpa#unload_mibs">unload_mibs</seealso>. </p>
<p>Own Id: OTP-11216</p>
</item>
@@ -370,18 +489,18 @@
<!--
<list type="bulleted">
<item>
- <p>Wrong block cypher type used for AES ('aes_cbf128'
- instead of 'aes_cfb128') when performing AES block
- encrypt/decrypt which breaks SNMP usmAesCfb128Protocol
+ <p>Wrong block cypher type used for AES ('aes_cbf128'
+ instead of 'aes_cfb128') when performing AES block
+ encrypt/decrypt which breaks SNMP usmAesCfb128Protocol
in agent and manager. </p>
<p>Own Id: OTP-11412</p>
</item>
<item>
- <p>[manager] When performing the AES encryption, invalid values for
+ <p>[manager] When performing the AES encryption, invalid values for
the EngineBoots and EngineTime was used. </p>
- <p>The values of the local agent was used, which would have produced
- "some" values if an agent was actually running.
+ <p>The values of the local agent was used, which would have produced
+ "some" values if an agent was actually running.
If not it would have caused a crash. </p>
<p>Own Id: OTP-11413</p>
</item>
@@ -425,16 +544,16 @@
<list type="bulleted">
<item>
<p>[agent] Enable SNMP to create missing database directories. </p>
- <p>Add
+ <p>Add
<seealso marker="snmp_app#db_init_error">
- {db_init_error, create_db_and_dir}</seealso> option to SNMP
- <seealso marker="snmp_app#manager_opts_and_types">manager</seealso>
+ {db_init_error, create_db_and_dir}</seealso> option to SNMP
+ <seealso marker="snmp_app#manager_opts_and_types">manager</seealso>
and
- <seealso marker="snmp_app#agent_opts_and_types">agent</seealso>.
+ <seealso marker="snmp_app#agent_opts_and_types">agent</seealso>.
This allows them to create any missing parent directories for
- <c>db_dir</c>, rather than treating any missing directories
+ <c>db_dir</c>, rather than treating any missing directories
as a fatal error.
- The default for <c>db_init_error</c>, which is <c>terminate</c>,
+ The default for <c>db_init_error</c>, which is <c>terminate</c>,
is unchanged. </p>
<p>Steve Vinoski</p>
<p>Own Id: OTP-11352</p>
@@ -444,7 +563,7 @@
<p>[manager] Improved handling of unexpected return values from
<seealso marker="snmpm_user">snmpm_user</seealso>
callback functions. </p>
- <p>Violations of the documented API (crashes or invalid return
+ <p>Violations of the documented API (crashes or invalid return
values) will now result in an error message. </p>
<p>Own Id: OTP-11307</p>
</item>
@@ -452,16 +571,16 @@
<item>
<p>Add (atl) log conversion block option. </p>
<p>It is now possible to request that the Audit Trail Log should
- be blocked during conversion (<c>log_to_txt</c> or <c>log_to_io</c>).
- This could be usefull when coverting an entire large log (when
+ be blocked during conversion (<c>log_to_txt</c> or <c>log_to_io</c>).
+ This could be usefull when coverting an entire large log (when
there is a chance it may otherwise wrap during conversion). </p>
- <p>See
- agent
+ <p>See
+ agent
<seealso marker="snmpa#log_to_txt">log_to_txt</seealso> and
- <seealso marker="snmpa#log_to_io">log_to_io</seealso> and also
- manager
+ <seealso marker="snmpa#log_to_io">log_to_io</seealso> and also
+ manager
<seealso marker="snmpm#log_to_txt">log_to_txt</seealso> and
- <seealso marker="snmpm#log_to_io">log_to_io</seealso>
+ <seealso marker="snmpm#log_to_io">log_to_io</seealso>
for details. </p>
<p>Own Id: OTP-11396</p>
<p>Own Id: seq12433</p>
@@ -470,9 +589,9 @@
<item>
<p>When converting an Audit Trail Log to text, a corrupt
log entry could cause the entire conversion to fail. </p>
- <p>Also, for a log with sequence numbers, failing to
+ <p>Also, for a log with sequence numbers, failing to
decode a log entry would cause the conversion to fail
- (not because of the failed decode, but because of the
+ (not because of the failed decode, but because of the
failure to write the error message). </p>
<p>Own Id: OTP-111453</p>
<p>Aux Id: Seq 12459</p>
@@ -490,18 +609,18 @@
<list type="bulleted">
<item>
- <p>Wrong block cypher type used for AES ('aes_cbf128'
- instead of 'aes_cfb128') when performing AES block
- encrypt/decrypt which breaks SNMP usmAesCfb128Protocol
+ <p>Wrong block cypher type used for AES ('aes_cbf128'
+ instead of 'aes_cfb128') when performing AES block
+ encrypt/decrypt which breaks SNMP usmAesCfb128Protocol
in agent and manager. </p>
<p>Own Id: OTP-11412</p>
</item>
<item>
- <p>[manager] When performing the AES encryption, invalid values for
+ <p>[manager] When performing the AES encryption, invalid values for
the EngineBoots and EngineTime was used. </p>
- <p>The values of the local agent was used, which would have produced
- "some" values if an agent was actually running.
+ <p>The values of the local agent was used, which would have produced
+ "some" values if an agent was actually running.
If not it would have caused a crash. </p>
<p>Own Id: OTP-11413</p>
</item>
@@ -543,14 +662,14 @@
<list type="bulleted">
<item>
- <p>[agent] Improved documentation for the functions for
- loading and unloading mibs,
- see <seealso marker="snmpa#load_mibs">load_mibs</seealso> and
- <seealso marker="snmpa#unload_mibs">unload_mibs</seealso> for
+ <p>[agent] Improved documentation for the functions for
+ loading and unloading mibs,
+ see <seealso marker="snmpa#load_mibs">load_mibs</seealso> and
+ <seealso marker="snmpa#unload_mibs">unload_mibs</seealso> for
more info. </p>
- <p>Also added new functions for loading and unloading a single mib,
- see <seealso marker="snmpa#load_mib">load_mib</seealso> and
- <seealso marker="snmpa#unload_mib">unload_mib</seealso> for
+ <p>Also added new functions for loading and unloading a single mib,
+ see <seealso marker="snmpa#load_mib">load_mib</seealso> and
+ <seealso marker="snmpa#unload_mib">unload_mib</seealso> for
more info. </p>
<p>Own Id: OTP-11216</p>
</item>
@@ -566,8 +685,8 @@
<!--
<list type="bulleted">
<item>
- <p>[agent]
- see <seealso marker="snmpa#load_mibs">load_mibs</seealso> and
+ <p>[agent]
+ see <seealso marker="snmpa#load_mibs">load_mibs</seealso> and
<seealso marker="snmpa#unload_mibs">unload_mibs</seealso>. </p>
<p>Own Id: OTP-11216</p>
</item>
@@ -593,7 +712,7 @@
</list>
-->
</section>
-
+
</section> <!-- 4.24.2 -->
@@ -626,29 +745,29 @@
<list type="bulleted">
<item>
- <p>[agent] Reading the value of the vacmViewTreeFamilyMask returns
+ <p>[agent] Reading the value of the vacmViewTreeFamilyMask returns
it in the wrong (internal bitlist) format. </p>
<p>The vacmViewTreeFamilyMask is defined as a bit string in the MIB
- (OCTET STRING). Internally a bitlist (list of 1's and 0's,
+ (OCTET STRING). Internally a bitlist (list of 1's and 0's,
see <seealso marker="snmp_agent_config_files#vacm">vacm config file</seealso>
- for more info) is used.
+ for more info) is used.
However, the MIB implementation assumed the latter, effectively
rendering all attempts to read/set masks via SNMP unsuccessful. </p>
- <p>Since the mask is used in hot paths (e.g. access permission checks
- for each SNMP operation, the bitlist representation of the mask has
- benefits (e.g. faster processing). Reading/writing the view mask
- objects is less time-critical. Therefore, to fix the issue, convert
- between the bitlist (internal) representation and bitstring
+ <p>Since the mask is used in hot paths (e.g. access permission checks
+ for each SNMP operation, the bitlist representation of the mask has
+ benefits (e.g. faster processing). Reading/writing the view mask
+ objects is less time-critical. Therefore, to fix the issue, convert
+ between the bitlist (internal) representation and bitstring
(external) when the vacmViewTreeFamilyMask objects are accessed. </p>
- <p>Also, the check of the vacm config file was invalid with
- regard to the mask value. It was assumed to be a proper oid, which
+ <p>Also, the check of the vacm config file was invalid with
+ regard to the mask value. It was assumed to be a proper oid, which
is not strictly the case (see bitlist above). </p>
<p>Own Id: OTP-11177</p>
<p>Stefan Zegenhagen</p>
</item>
<item>
- <p>[agent] The counter increment function in the local-db was
+ <p>[agent] The counter increment function in the local-db was
incorrect. It did not handle counter wrap correctly. </p>
<p>Own Id: OTP-11192</p>
</item>
@@ -695,26 +814,26 @@
</item>
<item>
- <p>[agent] Introduced a documented behaviour for the mib-server
- <seealso marker="snmpa_mib_data">mib-data backend</seealso>.
+ <p>[agent] Introduced a documented behaviour for the mib-server
+ <seealso marker="snmpa_mib_data">mib-data backend</seealso>.
At present only the default module (<c>snmpa_mib_data_tttn</c>) is
provided. </p>
- <p>A config option for the (agent)
- <seealso marker="snmp_config#agent_mib_server">mib-servers</seealso>
- mib-data backend module has been added to the agent config options,
+ <p>A config option for the (agent)
+ <seealso marker="snmp_config#agent_mib_server">mib-servers</seealso>
+ mib-data backend module has been added to the agent config options,
<seealso marker="snmp_config#agent_ms_data_module">data_module</seealso>. </p>
<p>Own Id: OTP-11101</p>
</item>
<item>
- <p>[agent] Introduced a documented behaviour for the
- <seealso marker="snmpa_mib_storage">mib storage</seealso>.
- At present there are three simple modules
- (<c>snmpa_mib_storage_ets</c>, <c>snmpa_mib_storage_dets</c> and
+ <p>[agent] Introduced a documented behaviour for the
+ <seealso marker="snmpa_mib_storage">mib storage</seealso>.
+ At present there are three simple modules
+ (<c>snmpa_mib_storage_ets</c>, <c>snmpa_mib_storage_dets</c> and
<c>snmpa_mib_storage_mnesia</c>) implementing this behaviour,
provided with the app. </p>
- <p>A config option for the (agent)
- <seealso marker="snmp_config#agent_mib_storage">mib storage</seealso>
+ <p>A config option for the (agent)
+ <seealso marker="snmp_config#agent_mib_storage">mib storage</seealso>
has been added to the agent config options. </p>
<p>Own Id: OTP-11107</p>
</item>
@@ -772,14 +891,14 @@
<list type="bulleted">
<item>
<p>[agent] Errors in <c>vacmAccessTable</c> RowStatus handling.
- There are problems with the handling of vacmAccessTableStatus
+ There are problems with the handling of vacmAccessTableStatus
that cause some SNMP test suites to report errors.
- Most notably, erroneous set operations frequently cause "genErr"
- errors to be returned. These "genErr" errors are usually caused
- by badmatch exceptions coming from
- <c>{ok, Row} = snmpa_vacm:get_row(RowIndex)</c>
+ Most notably, erroneous set operations frequently cause "genErr"
+ errors to be returned. These "genErr" errors are usually caused
+ by badmatch exceptions coming from
+ <c>{ok, Row} = snmpa_vacm:get_row(RowIndex)</c>
if the row does not exist. </p>
- <p>The semantics of the RowStatus handling in that table has
+ <p>The semantics of the RowStatus handling in that table has
been adjusted to be compliant with the RowStatus
textual description of SNPMv2-TC MIB. </p>
<p>Stefan Zegenhagen</p>
@@ -803,7 +922,7 @@
</item>
<item>
- <p>[compiler] The MIB compiler could not handle a table index
+ <p>[compiler] The MIB compiler could not handle a table index
that was defined later in the MIB. </p>
<p>Own Id: OTP-10808</p>
</item>
@@ -836,7 +955,7 @@
<title>SNMP Development Toolkit 4.23</title>
<!--
<p>Version 4.23 supports code replacement in runtime from/to
- version 4.22.1,
+ version 4.22.1,
4.22, 4.21.7 4.21.6 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1 and 4.21. </p>
-->
@@ -848,14 +967,14 @@
<list type="bulleted">
<item>
- <p>[manager] Polish return values of snmpm_user_default according
+ <p>[manager] Polish return values of snmpm_user_default according
to snmpm_user doc.</p>
<p>Luca Favatella</p>
<p>Own Id: OTP-10671</p>
</item>
<item>
- <p>[agent] Remove runtime warning in snmpa_agent because of
+ <p>[agent] Remove runtime warning in snmpa_agent because of
tuple fun usage. </p>
<p>Luca Favatella</p>
<p>Own Id: OTP-10672</p>
@@ -877,10 +996,10 @@
<!--
<list type="bulleted">
<item>
- <p>[agent] Simultaneous
- <seealso marker="snmpa#backup">snmpa:backup/1,2</seealso>
+ <p>[agent] Simultaneous
+ <seealso marker="snmpa#backup">snmpa:backup/1,2</seealso>
calls can interfere.
- The master agent did not check if a backup was already in
+ The master agent did not check if a backup was already in
progress when a backup request was accepted. </p>
<p>Own Id: OTP-9884</p>
<p>Aux Id: Seq 11995</p>
@@ -913,7 +1032,7 @@
<section>
<title>SNMP Development Toolkit 4.22.1</title>
<p>Version 4.22.1 supports code replacement in runtime from/to
- version 4.22, 4.21.7 4.21.6 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1 and
+ version 4.22, 4.21.7 4.21.6 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1 and
4.21. </p>
<section>
@@ -925,15 +1044,15 @@
<list type="bulleted">
<item>
<p>[agent] Sematic fixes to SNMP-USER-BASED-SM-MIB.
- The semantics allow the <c>usmUserAuthKeyChange</c> and
- <c>usmUserPrivKeyChange</c> objects to be written to in the
- same set requests that also creates and clones the user.
- This was not possible beforehand, causing test tools checking
+ The semantics allow the <c>usmUserAuthKeyChange</c> and
+ <c>usmUserPrivKeyChange</c> objects to be written to in the
+ same set requests that also creates and clones the user.
+ This was not possible beforehand, causing test tools checking
semantic SNMPv3 behaviour to fail on a lot of test cases. </p>
- <p>Furthermore, once the user has been cloned by writing to an
- instance of <c>usmUserCloneFrom</c>, further set-operations to
- the same object will not return an error, but be no-ops.
- Especially, it must be avoided to copy security parameters
+ <p>Furthermore, once the user has been cloned by writing to an
+ instance of <c>usmUserCloneFrom</c>, further set-operations to
+ the same object will not return an error, but be no-ops.
+ Especially, it must be avoided to copy security parameters
again (possibly even from a different user). </p>
<p>Stefan Zegenhagen</p>
<p>Own Id: OTP-10166</p>
@@ -941,14 +1060,14 @@
<item>
<p>[agent] Errors in <c>vacmAccessTable</c> RowStatus handling.
- There are problems with the handling of vacmAccessTableStatus
+ There are problems with the handling of vacmAccessTableStatus
that cause some SNMP test suites to report errors.
- Most notably, erroneous set operations frequently cause "genErr"
- errors to be returned. These "genErr" errors are usually caused
- by badmatch exceptions coming from
- <c>{ok, Row} = snmpa_vacm:get_row(RowIndex)</c>
+ Most notably, erroneous set operations frequently cause "genErr"
+ errors to be returned. These "genErr" errors are usually caused
+ by badmatch exceptions coming from
+ <c>{ok, Row} = snmpa_vacm:get_row(RowIndex)</c>
if the row does not exist. </p>
- <p>The semantics of the RowStatus handling in that table has
+ <p>The semantics of the RowStatus handling in that table has
been adjusted to be compliant with the RowStatus
textual description of SNPMv2-TC MIB. </p>
<p>Stefan Zegenhagen</p>
@@ -967,24 +1086,24 @@
<list type="bulleted">
<item>
<p>[agent] Fix walk over vacmAccessTable.
- Fix the get_next implementation of vacmAccessTable to
+ Fix the get_next implementation of vacmAccessTable to
return all table entries. </p>
- <p>The get_next implementation of vacmAccessTable did not return
- all available table data. Instead, it only returned the first
+ <p>The get_next implementation of vacmAccessTable did not return
+ all available table data. Instead, it only returned the first
column for each row, and all columns for the last row available. </p>
<p>Stefan Zegenhagen</p>
<p>Own Id: OTP-10165</p>
</item>
<item>
- <p>[manager]
- <seealso marker="snmpm#log_to_io">snmpm:log_to_io/6</seealso>
+ <p>[manager]
+ <seealso marker="snmpm#log_to_io">snmpm:log_to_io/6</seealso>
did not use the LogName argument. </p>
<p>Own Id: OTP-10066</p>
</item>
<item>
- <p>Incorrect TimeTicks decode. Also bad handling of
+ <p>Incorrect TimeTicks decode. Also bad handling of
invalid encode (value outside of value range) for both
<c>TimeTicks</c> and <c>Unsigned32</c>. </p>
<p>Own Id: OTP-10132</p>
@@ -1015,38 +1134,38 @@
<list type="bulleted">
<item>
- <p>[compiler] The table information the MIB compiler provides with
- augmented tables has been extended with <c>nbr_of_cols</c>,
+ <p>[compiler] The table information the MIB compiler provides with
+ augmented tables has been extended with <c>nbr_of_cols</c>,
<c>first_accessible</c> and <c>not_accessible</c>. </p>
<p>Own Id: OTP-9969</p>
</item>
<item>
- <p>Added the <c>log_to_io</c> audit-trail-log converter function
- to the api modules of both the
- <seealso marker="snmpm#log_to_io">manager</seealso>
- and
+ <p>Added the <c>log_to_io</c> audit-trail-log converter function
+ to the api modules of both the
+ <seealso marker="snmpm#log_to_io">manager</seealso>
+ and
<seealso marker="snmpa#log_to_io">agent</seealso>. </p>
<p>Own Id: OTP-9940</p>
</item>
<item>
- <p>[manager] Introduced a new transport module,
- <c>snmpm_net_if_mt</c>,
- which handles all incomming and outgoing
+ <p>[manager] Introduced a new transport module,
+ <c>snmpm_net_if_mt</c>,
+ which handles all incomming and outgoing
traffic in newly created processes. The message/request is
processed and then the process exits. </p>
<p>Own Id: OTP-9876</p>
</item>
<item>
- <p>[agent] Documenting previously existing but undocumented function,
+ <p>[agent] Documenting previously existing but undocumented function,
<seealso marker="snmp_generic#get_table_info">snmp_generic:get_table_info/2</seealso>. </p>
<p>Own Id: OTP-9942</p>
</item>
<item>
- <p>[agent] Improve error handling while reading agent config files.
+ <p>[agent] Improve error handling while reading agent config files.
Some files contain mandatory information and is therefor themself
mandatory. </p>
<p>Own Id: OTP-9943</p>
@@ -1062,10 +1181,10 @@
<!--
<list type="bulleted">
<item>
- <p>[agent] Simultaneous
- <seealso marker="snmpa#backup">snmpa:backup/1,2</seealso>
+ <p>[agent] Simultaneous
+ <seealso marker="snmpa#backup">snmpa:backup/1,2</seealso>
calls can interfere.
- The master agent did not check if a backup was already in
+ The master agent did not check if a backup was already in
progress when a backup request was accepted. </p>
<p>Own Id: OTP-9884</p>
<p>Aux Id: Seq 11995</p>
@@ -1087,7 +1206,7 @@
<section>
<title>SNMP Development Toolkit 4.21.7</title>
<p>Version 4.21.7 supports code replacement in runtime from/to
- version 4.21.6, 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1, 4.21, 4.20.1 and
+ version 4.21.6, 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1, 4.21, 4.20.1 and
4.20. </p>
<section>
@@ -1097,13 +1216,13 @@
<!--
<list type="bulleted">
<item>
- <p>[agent] DoS attack using GET-BULK with large value of
+ <p>[agent] DoS attack using GET-BULK with large value of
MaxRepetitions.
- A preventive method has been implementing by simply
- limit the number of varbinds that can be included in
- a Get-BULK response message. This is specified by the
- new config option,
- <seealso marker="snmp_app#agent_gb_max_vbs">gb_max_vbs</seealso>.
+ A preventive method has been implementing by simply
+ limit the number of varbinds that can be included in
+ a Get-BULK response message. This is specified by the
+ new config option,
+ <seealso marker="snmp_app#agent_gb_max_vbs">gb_max_vbs</seealso>.
</p>
<p>Own Id: OTP-9700</p>
</item>
@@ -1121,10 +1240,10 @@
<list type="bulleted">
<item>
- <p>[agent] Simultaneous
- <seealso marker="snmpa#backup">snmpa:backup/1,2</seealso>
+ <p>[agent] Simultaneous
+ <seealso marker="snmpa#backup">snmpa:backup/1,2</seealso>
calls can interfere.
- The master agent did not check if a backup was already in
+ The master agent did not check if a backup was already in
progress when a backup request was accepted. </p>
<p>Own Id: OTP-9884</p>
<p>Aux Id: Seq 11995</p>
@@ -1145,7 +1264,7 @@
<section>
<title>SNMP Development Toolkit 4.21.6</title>
<p>Version 4.21.6 supports code replacement in runtime from/to
- version 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1, 4.21, 4.20.1 and
+ version 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1, 4.21, 4.20.1 and
4.20. </p>
<section>
@@ -1156,13 +1275,13 @@
<list type="bulleted">
<item>
- <p>[agent] DoS attack using GET-BULK with large value of
+ <p>[agent] DoS attack using GET-BULK with large value of
MaxRepetitions.
- A preventive method has been implementing by simply
- limit the number of varbinds that can be included in
- a Get-BULK response message. This is specified by the
- new config option,
- <seealso marker="snmp_app#agent_gb_max_vbs">gb_max_vbs</seealso>.
+ A preventive method has been implementing by simply
+ limit the number of varbinds that can be included in
+ a Get-BULK response message. This is specified by the
+ new config option,
+ <seealso marker="snmp_app#agent_gb_max_vbs">gb_max_vbs</seealso>.
</p>
<p>Own Id: OTP-9700</p>
</item>
@@ -1179,11 +1298,11 @@
<list type="bulleted">
<item>
- <p>[agent] Mib server cache gclimit update function incorrectly calls
- age update function.
- The gclimit update function,
- <seealso marker="snmpa#update_mibs_cache_gclimit">update_mibs_cache_gclimit/1</seealso>,
- <em>incorrectly</em> called the age update function,
+ <p>[agent] Mib server cache gclimit update function incorrectly calls
+ age update function.
+ The gclimit update function,
+ <seealso marker="snmpa#update_mibs_cache_gclimit">update_mibs_cache_gclimit/1</seealso>,
+ <em>incorrectly</em> called the age update function,
<seealso marker="snmpa#update_mibs_cache_age">update_mibs_cache_age/2</seealso>. </p>
<p>Johan Claesson</p>
<p>Own Id: OTP-9868</p>
@@ -1225,18 +1344,18 @@
<section>
<title>Fixed Bugs and Malfunctions</title>
<!--
- <p>-</p>
+ <p>-</p>
-->
<list type="bulleted">
<item>
- <p>[agent] Repeated vacm table dumping fails due to file name
- conflict. When dumping the vacm table to disk, a temoporary
- file with a fixed name was used. If the table dumping
- (snmpa_vacm:dump_table/0) was initiated from several different
- processes in rapid succesion, the dumping could fail because the
- different processes was simultaniously trying to write to the
- same file. This problem has been eliminated by creating a unique
+ <p>[agent] Repeated vacm table dumping fails due to file name
+ conflict. When dumping the vacm table to disk, a temoporary
+ file with a fixed name was used. If the table dumping
+ (snmpa_vacm:dump_table/0) was initiated from several different
+ processes in rapid succesion, the dumping could fail because the
+ different processes was simultaniously trying to write to the
+ same file. This problem has been eliminated by creating a unique
name for the temporary file. </p>
<p>Own Id: OTP-9851</p>
<p>Aux Id: Seq 11980</p>
@@ -1277,7 +1396,7 @@
<!--
<list type="bulleted">
<item>
- <p>[compiler] Improved version info printout from the
+ <p>[compiler] Improved version info printout from the
<seealso marker="snmpc(command)#">MIB compiler frontend escript</seealso>. </p>
<p>Own Id: OTP-9618</p>
</item>
@@ -1290,7 +1409,7 @@
<section>
<title>Fixed Bugs and Malfunctions</title>
<!--
- <p>-</p>
+ <p>-</p>
-->
<list type="bulleted">
@@ -1334,7 +1453,7 @@
<list type="bulleted">
<item>
- <p>[compiler] Improved version info printout from the
+ <p>[compiler] Improved version info printout from the
<seealso marker="snmpc(command)#">MIB compiler frontend escript</seealso>. </p>
<p>Own Id: OTP-9618</p>
</item>
@@ -1346,27 +1465,27 @@
<section>
<title>Fixed Bugs and Malfunctions</title>
<!--
- <p>-</p>
+ <p>-</p>
-->
<list type="bulleted">
<item>
- <p>[agent] Version 4.20 introduced a change that broke trap
- sending from subagents. Due to a bug in the test code,
+ <p>[agent] Version 4.20 introduced a change that broke trap
+ sending from subagents. Due to a bug in the test code,
this was not discovered, until that bug was fixed. </p>
<p>Own Id: OTP-9745</p>
</item>
<item>
- <p>[agent] When sending an error message (reply) regarding
+ <p>[agent] When sending an error message (reply) regarding
<c>snmpUnknownPDUHandlers</c>, the agent used the wrong OID. </p>
<p>Own Id: OTP-9747</p>
</item>
<item>
- <p>[compiler] Fix the <c>--warnings/--W</c> option parsing in the
+ <p>[compiler] Fix the <c>--warnings/--W</c> option parsing in the
<seealso marker="snmpc(command)#option_warnings">snmpc</seealso>
- wrapper (e)script.
+ wrapper (e)script.
The short warning option was incorrectly <c>--w</c>, instead
of as documented <c>--W</c>. This has now been corrected. </p>
<p>*** POTENTIAL INCOMPATIBILITY ***</p>
@@ -1386,7 +1505,7 @@
<list type="bulleted">
<item>
- <p>[compiler] The short warning option has been changed from
+ <p>[compiler] The short warning option has been changed from
<c>--w</c> to <c>--W</c> to comply with the documentation. </p>
<p>Tuncer Ayaz</p>
<p>Own Id: OTP-9718</p>
@@ -1410,7 +1529,7 @@
<!--
<list type="bulleted">
<item>
- <p>Bad note store GC timer deactivation.
+ <p>Bad note store GC timer deactivation.
Wrong field in the state record was set (timeout instead active). </p>
<p>Stefan Grundmann</p>
<p>Own Id: OTP-9690</p>
@@ -1424,12 +1543,12 @@
<section>
<title>Fixed Bugs and Malfunctions</title>
<!--
- <p>-</p>
+ <p>-</p>
-->
<list type="bulleted">
<item>
- <p>Bad note store GC timer deactivation.
+ <p>Bad note store GC timer deactivation.
Wrong field in the state record was set (timeout instead active). </p>
<p>Stefan Grundmann</p>
<p>Own Id: OTP-9690</p>
@@ -1459,13 +1578,13 @@
-->
<list type="bulleted">
<item>
- <p>[compiler] Used wrong variable name (for
- warnings-as-errors variable), which caused the
+ <p>[compiler] Used wrong variable name (for
+ warnings-as-errors variable), which caused the
compiler to crash when using the snmpc (e)script. </p>
- <p>Also added the option
+ <p>Also added the option
<seealso marker="snmpc(command)#option_werror">--Werror</seealso>
- for the SNMP MIB compiler (escript) frontend (to mimic
- <seealso marker="erts:erlc">erlc</seealso>),
+ for the SNMP MIB compiler (escript) frontend (to mimic
+ <seealso marker="erts:erlc">erlc</seealso>),
which specifies whether warnings should be treated as errors. </p>
<p>Own Id: OTP-9447</p>
</item>
@@ -1480,12 +1599,12 @@
<section>
<title>Fixed Bugs and Malfunctions</title>
- <p>-</p>
+ <p>-</p>
<!--
<list type="bulleted">
<item>
- <p>The snmp config tool could not handle (manager) audit trail config
+ <p>The snmp config tool could not handle (manager) audit trail config
because the option seqno was not handled. </p>
<p>Own Id: OTP-9354</p>
</item>
@@ -1515,15 +1634,15 @@
-->
<list type="bulleted">
<item>
- <p>[manager] There was no way to specify transport domain.
+ <p>[manager] There was no way to specify transport domain.
The transport domains was assumed to be IPv4 (transportDomainUdpIpv4).
- This has now been changed so that it can also be IPv6
- (transportDomainUdpIpv6).
- To facilitate this, the transport domain, <c>tdomain</c>,
- is now a (new) valid option when
+ This has now been changed so that it can also be IPv6
+ (transportDomainUdpIpv6).
+ To facilitate this, the transport domain, <c>tdomain</c>,
+ is now a (new) valid option when
<seealso marker="snmpm#register_agent">registering</seealso>
- a new agent (and
- <seealso marker="snmpm#update_agent_info">updating</seealso>
+ a new agent (and
+ <seealso marker="snmpm#update_agent_info">updating</seealso>
agent info). </p>
<p>This also mean that the transport behaviour has changed. </p>
<p>Own Id: OTP-9305</p>
@@ -1531,10 +1650,10 @@
</item>
<item>
- <p>[compiler] Added the option
- <seealso marker="snmpc#compile">warnings_as_errors</seealso>
- (for the SNMP MIB compiler (escript) frontend, the option
- <seealso marker="snmpc(command)#option_wae">--wae</seealso> is used)
+ <p>[compiler] Added the option
+ <seealso marker="snmpc#compile">warnings_as_errors</seealso>
+ (for the SNMP MIB compiler (escript) frontend, the option
+ <seealso marker="snmpc(command)#option_wae">--wae</seealso> is used)
which specifies whether warnings should be treated as errors. </p>
<p>Tuncer Ayaz</p>
<p>Own Id: OTP-9437</p>
@@ -1546,12 +1665,12 @@
<section>
<title>Fixed Bugs and Malfunctions</title>
<!--
- <p>-</p>
+ <p>-</p>
-->
<list type="bulleted">
<item>
- <p>The snmp config tool could not handle (manager) audit trail config
+ <p>The snmp config tool could not handle (manager) audit trail config
because the option seqno was not handled. </p>
<p>Own Id: OTP-9354</p>
</item>
@@ -1605,11 +1724,11 @@
<section>
<title>Fixed Bugs and Malfunctions</title>
<!--
- <p>-</p>
+ <p>-</p>
-->
<list type="bulleted">
<item>
- <p>[agent] Did not handle transport domains properly in some cases,
+ <p>[agent] Did not handle transport domains properly in some cases,
for instance trap sending. </p>
<p>Own Id: OTP-9400</p>
</item>
@@ -1646,9 +1765,9 @@
<list type="bulleted">
<item>
<p>[agent] Added support for sending traps to IPv6 targets. </p>
- <p>See the
- <seealso marker="snmp_agent_config_files#target_addr">target address config file</seealso>,
- the <seealso marker="snmpa_conf#target_addr_entry">target_addr_entry/11</seealso> function or
+ <p>See the
+ <seealso marker="snmp_agent_config_files#target_addr">target address config file</seealso>,
+ the <seealso marker="snmpa_conf#target_addr_entry">target_addr_entry/11</seealso> function or
<seealso marker="snmp_target_mib#add_addr">add_addr/11</seealso> for more info. </p>
<p>Own Id: OTP-9088</p>
<p>Aux Id: Seq 11790</p>
@@ -1657,7 +1776,7 @@
<item>
<p>[agent] To be able to handle multiple engine-id(s) when
- sending trap(s), the function
+ sending trap(s), the function
<seealso marker="snmp_community_mib#add_community">
add_community/6</seealso> has been added. </p>
<p>Own Id: OTP-9119</p>
@@ -1667,14 +1786,14 @@
<item>
<p>[manager] The API for snmp requests has been augmented to
allow the caller to override some configuration. </p>
- <p>This has been done by introducing a new set of API functions, see
- <seealso marker="snmpm#sync_get2">sync_get2/3,4</seealso>,
- <seealso marker="snmpm#async_get2">async_get2/3,4</seealso>,
- <seealso marker="snmpm#sync_get_next2">sync_get_next2/3,4</seealso>,
- <seealso marker="snmpm#async_get_next2">async_get_next2/3,4</seealso>,
- <seealso marker="snmpm#sync_get_bulk2">sync_get_bulk2/5,6</seealso>,
- <seealso marker="snmpm#async_get_bulk2">async_get_bulk2/5,6</seealso>,
- <seealso marker="snmpm#sync_set2">sync_set2/3,4</seealso> and
+ <p>This has been done by introducing a new set of API functions, see
+ <seealso marker="snmpm#sync_get2">sync_get2/3,4</seealso>,
+ <seealso marker="snmpm#async_get2">async_get2/3,4</seealso>,
+ <seealso marker="snmpm#sync_get_next2">sync_get_next2/3,4</seealso>,
+ <seealso marker="snmpm#async_get_next2">async_get_next2/3,4</seealso>,
+ <seealso marker="snmpm#sync_get_bulk2">sync_get_bulk2/5,6</seealso>,
+ <seealso marker="snmpm#async_get_bulk2">async_get_bulk2/5,6</seealso>,
+ <seealso marker="snmpm#sync_set2">sync_set2/3,4</seealso> and
<seealso marker="snmpm#async_set2">async_set2/3,4</seealso>
for more info. </p>
<p>Own Id: OTP-9162</p>
@@ -1682,8 +1801,8 @@
<item>
<p>[manager] The old API functions (for get and set
- requests:
- snmpm:g/3,4,5,6,7, snmpm:ag/3,4,5,6,7,
+ requests:
+ snmpm:g/3,4,5,6,7, snmpm:ag/3,4,5,6,7,
snmpm:gn/3,4,5,6,7, snmpm:agn/3,4,5,6,7,
snmpm:s/3,4,5,6,7, snmpm:s/3,4,5,6,7,
snmpm:gb/5,6,7,8,9 and snmpm:agb/5,6,7,8,9)
@@ -1695,12 +1814,12 @@
<item>
<p>[agent] Pass extra info through the agent to the net-if
process when sending notifications. </p>
- <p>See
+ <p>See
<seealso marker="snmpa#send_notification2">
- snmpa:send_notification2/3</seealso> for more info.
- See also the incomming net-if messages when sending a
- <seealso marker="snmp_agent_netif#im_send_pdu">trap</seealso>
- (send_pdu message) and
+ snmpa:send_notification2/3</seealso> for more info.
+ See also the incomming net-if messages when sending a
+ <seealso marker="snmp_agent_netif#im_send_pdu">trap</seealso>
+ (send_pdu message) and
<seealso marker="snmp_agent_netif#im_send_pdu_req">
notification</seealso> (send_pdu_req message). </p>
<p>Own Id: OTP-9183</p>
@@ -1718,15 +1837,15 @@
<section>
<title>Fixed Bugs and Malfunctions</title>
<!--
- <p>-</p>
+ <p>-</p>
-->
<list type="bulleted">
<item>
<p>Fixed endode/decode of values of type <c>Counter32</c>. </p>
- <p>This type (<c>Counter32</c>) is an unsigned integer 32,
- but is actually encoded as an signed integer 32.
- The encode/decode functions however, treated it as if it was
+ <p>This type (<c>Counter32</c>) is an unsigned integer 32,
+ but is actually encoded as an signed integer 32.
+ The encode/decode functions however, treated it as if it was
encodeded as an unsigned integer 32. </p>
<p>Own Id: OTP-9022</p>
</item>
@@ -1741,12 +1860,4 @@
</section>
</section> <!-- 4.20 -->
-
-
- <!-- section>
- <title>Release notes history</title>
- <p>For information about older versions see
- <url href="part_notes_history_frame.html">release notes history</url>.</p>
- </section -->
</chapter>
-
diff --git a/lib/snmp/doc/src/part_notes.xml b/lib/snmp/doc/src/part_notes.xml
deleted file mode 100644
index d149044169..0000000000
--- a/lib/snmp/doc/src/part_notes.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>1997</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>SNMP Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- <file>part_notes.xml</file>
- </header>
- <description>
- <p>A multilingual Simple Network Management Protocol application,
- featuring an Extensible Agent, a simple manager and a MIB
- compiler and facilities for implementing SNMP MIBs etc.</p>
- <p>For information about older versions see
- <url href="part_notes_history_frame.html">release notes history</url>.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/snmp/doc/src/part_notes_history.xml b/lib/snmp/doc/src/part_notes_history.xml
deleted file mode 100644
index aa5276dc94..0000000000
--- a/lib/snmp/doc/src/part_notes_history.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>SNMP Release Notes History</title>
- <prepared></prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date></date>
- <rev></rev>
- <file>part_notes_history.xml</file>
- </header>
- <description>
- <p>A multilingual Simple Network Management Protocol application,
- featuring an Extensible Agent, a simple manager and a MIB
- compiler and facilities for implementing SNMP MIBs etc.</p>
- </description>
- <include file="notes_history"></include>
-</part>
-
diff --git a/lib/snmp/doc/src/ref_man.gif b/lib/snmp/doc/src/ref_man.gif
deleted file mode 100644
index b13c4efd53..0000000000
--- a/lib/snmp/doc/src/ref_man.gif
+++ /dev/null
Binary files differ
diff --git a/lib/snmp/doc/src/snmp.gif b/lib/snmp/doc/src/snmp.gif
deleted file mode 100644
index d9985f990b..0000000000
--- a/lib/snmp/doc/src/snmp.gif
+++ /dev/null
Binary files differ
diff --git a/lib/snmp/doc/src/snmp.xml b/lib/snmp/doc/src/snmp.xml
index 801193675c..480ed2e825 100644
--- a/lib/snmp/doc/src/snmp.xml
+++ b/lib/snmp/doc/src/snmp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -341,10 +341,10 @@
</func>
<func>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block | Start) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Block | Stop) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop, Block) -> ok | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block | Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Block | Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop, Block) -> ok | {ok, Cnt} | {error, Reason}</name>
<fsummary>Convert an Audit Trail Log to text format</fsummary>
<type>
<v>LogDir = string()</v>
@@ -355,6 +355,9 @@
<v>LogFile = string()</v>
<v>Start = Stop = null | datetime() | {local_time,datetime()} | {universal_time,datetime()} </v>
<v>Block = boolean()</v>
+ <v>Cnt = {NumOK, NumERR}</v>
+ <v>NumOK = non_neg_integer()</v>
+ <v>NumERR = pos_integer()</v>
<v>Reason = term()</v>
</type>
<desc>
@@ -394,16 +397,25 @@
and <c>Vsn</c> is the SNMP version. <c>PDU</c> is a textual
version of the protocol data unit. There is a new line
between <c>Vsn</c> and <c>PDU</c>.</p>
+
+ <p>If the entire log is successfully converted, the function
+ will return <c>ok</c>.
+ If one of more entries fail to convert, the function will instead
+ return <c>{ok, {NumOK, NumERR}}</c>, where the counters indicate
+ how many valid and erroneous entries where found.
+ If instead <c>{error, Reason}</c> is returned, the conversion
+ encountered a fatal error and where either never done of aborted
+ midway. </p>
<marker id="log_to_io"></marker>
</desc>
</func>
<func>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block | Start) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Block | Stop) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop, Block) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block | Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Block | Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop, Block) -> ok | {ok, Cnt} | {error, Reason}</name>
<fsummary>Convert an Audit Trail Log to text format</fsummary>
<type>
<v>LogDir = string()</v>
@@ -412,6 +424,9 @@
<v>LogName = string()</v>
<v>LogFile = string()</v>
<v>Start = Stop = null | datetime() | {local_time,datetime()} | {universal_time,datetime()} </v>
+ <v>Cnt = {NumOK, NumERR}</v>
+ <v>NumOK = non_neg_integer()</v>
+ <v>NumERR = pos_integer()</v>
<v>Reason = term()</v>
</type>
<desc>
diff --git a/lib/snmp/doc/src/snmp_impl_example_agent.xml b/lib/snmp/doc/src/snmp_impl_example_agent.xml
index a86006a0a7..7dda3dd5cd 100644
--- a/lib/snmp/doc/src/snmp_impl_example_agent.xml
+++ b/lib/snmp/doc/src/snmp_impl_example_agent.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -47,6 +47,7 @@
EX1-MIB DEFINITIONS ::= BEGIN
IMPORTS
+ experimental FROM RFC1155-SMI
RowStatus FROM STANDARD-MIB
DisplayString FROM RFC1213-MIB
OBJECT-TYPE FROM RFC-1212
@@ -81,7 +82,7 @@ EX1-MIB DEFINITIONS ::= BEGIN
FriendsEntry ::=
SEQUENCE {
- fIndex
+ fIndex
INTEGER,
fName
DisplayString,
@@ -105,6 +106,7 @@ EX1-MIB DEFINITIONS ::= BEGIN
DESCRIPTION
"Name of friend"
::= { friendsEntry 2 }
+
fAddress OBJECT-TYPE
SYNTAX DisplayString (SIZE (0..255))
ACCESS read-write
@@ -112,6 +114,7 @@ EX1-MIB DEFINITIONS ::= BEGIN
DESCRIPTION
"Address of friend"
::= { friendsEntry 3 }
+
fStatus OBJECT-TYPE
SYNTAX RowStatus
ACCESS read-write
@@ -119,12 +122,13 @@ EX1-MIB DEFINITIONS ::= BEGIN
DESCRIPTION
"The status of this conceptual row."
::= { friendsEntry 4 }
+
fTrap TRAP-TYPE
ENTERPRISE example1
VARIABLES { myName, fIndex }
DESCRIPTION
- "This trap is sent when something happens to
- the friend specified by fIndex."
+ "This trap is sent when something happens to
+ the friend specified by fIndex."
::= 1
END
</code>
diff --git a/lib/snmp/doc/src/snmpa.xml b/lib/snmp/doc/src/snmpa.xml
index d756ff7a65..b78f14da01 100644
--- a/lib/snmp/doc/src/snmpa.xml
+++ b/lib/snmp/doc/src/snmpa.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2016</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -559,13 +559,13 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
<func>
<name>log_to_txt(LogDir)</name>
<name>log_to_txt(LogDir, Block | Mibs)</name>
- <name>log_to_txt(LogDir, Mibs, Block | OutFile) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, Block | LogName) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, Block | LogFile) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block | Start) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop) -> ok | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, Block | OutFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, Block | LogName) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, Block | LogFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block | Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
<fsummary>Convert an Audit Trail Log to text format</fsummary>
<type>
<v>LogDir = string()</v>
@@ -576,6 +576,9 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
<v>LogName = string()</v>
<v>LogFile = string()</v>
<v>Start = Stop = null | calendar:datetime() | {local_time, calendar:datetime()} | {universal_time, calendar:datetime()} </v>
+ <v>Cnt = {NumOK, NumERR}</v>
+ <v>NumOK = non_neg_integer()</v>
+ <v>NumERR = pos_integer()</v>
<v>Reason = disk_log_open_error() | file_open_error() | term()</v>
<v>disk_log_open_error() = {LogName, term()}</v>
<v>file_open_error() = {OutFile, term()}</v>
@@ -597,14 +600,14 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>log_to_io(LogDir) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Block | Mibs) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, Block | LogName) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, Block | LogFile) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block | Start) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Block | Mibs) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, Block | LogName) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, Block | LogFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block | Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
<fsummary>Convert an Audit Trail Log to text format</fsummary>
<type>
<v>LogDir = string()</v>
@@ -614,6 +617,9 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
<v>LogName = string()</v>
<v>LogFile = string()</v>
<v>Start = Stop = null | calendar:datetime() | {local_time, calendar:datetime()} | {universal_time, calendar:datetime()} </v>
+ <v>Cnt = {NumOK, NumERR}</v>
+ <v>NumOK = non_neg_integer()</v>
+ <v>NumERR = pos_integer()</v>
<v>Reason = disk_log_open_error() | file_open_error() | term()</v>
<v>disk_log_open_error() = {LogName, term()}</v>
<v>file_open_error() = {OutFile, term()}</v>
diff --git a/lib/snmp/doc/src/snmpm.xml b/lib/snmp/doc/src/snmpm.xml
index 4818aeb697..be4cd58a1a 100644
--- a/lib/snmp/doc/src/snmpm.xml
+++ b/lib/snmp/doc/src/snmpm.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2016</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -1216,13 +1216,13 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<func>
<name>log_to_txt(LogDir)</name>
<name>log_to_txt(LogDir, Block | Mibs)</name>
- <name>log_to_txt(LogDir, Mibs, Block | OutFile) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, Block | LogName) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, Block | LogFile) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block | Start) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop) -> ok | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, Block | OutFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, Block | LogName) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, Block | LogFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block | Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
<fsummary>Convert an Audit Trail Log to text format</fsummary>
<type>
<v>LogDir = string()</v>
@@ -1233,6 +1233,9 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<v>LogName = string()</v>
<v>LogFile = string()</v>
<v>Start = Stop = null | calendar:datetime() | {local_time, calendar:datetime()} | {universal_time, calendar:datetime()} </v>
+ <v>Cnt = {NumOK, NumERR}</v>
+ <v>NumOK = non_neg_integer()</v>
+ <v>NumERR = pos_integer()</v>
<v>Reason = disk_log_open_error() | file_open_error() | term()</v>
<v>disk_log_open_error() = {LogName, term()}</v>
<v>file_open_error() = {OutFile, term()}</v>
@@ -1254,15 +1257,15 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>log_to_io(LogDir) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Block | Mibs) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Block | Mibs) -> ok | {ok, Cnt} | {error, Reason}</name>
<name>log_to_io(LogDir, Mibs) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, Block | LogName) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, Block | LogFile) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block | Start) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, Block | LogName) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, Block | LogFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block | Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
<fsummary>Convert an Audit Trail Log to text format</fsummary>
<type>
<v>LogDir = string()</v>
@@ -1272,6 +1275,9 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<v>LogName = string()</v>
<v>LogFile = string()</v>
<v>Start = Stop = null | calendar:datetime() | {local_time, calendar:datetime()} | {universal_time, calendar:datetime()} </v>
+ <v>Cnt = {NumOK, NumERR}</v>
+ <v>NumOK = non_neg_integer()</v>
+ <v>NumERR = pos_integer()</v>
<v>Reason = disk_log_open_error() | file_open_error() | term()</v>
<v>disk_log_open_error() = {LogName, term()}</v>
<v>file_open_error() = {OutFile, term()}</v>
diff --git a/lib/snmp/doc/src/summary.html.src b/lib/snmp/doc/src/summary.html.src
deleted file mode 100644
index 9bad4adbeb..0000000000
--- a/lib/snmp/doc/src/summary.html.src
+++ /dev/null
@@ -1 +0,0 @@
-Simple Network Management Protocol (SNMP) support including a MIB compiler, a simple SNMP manager and tools for creating SNMP agents
diff --git a/lib/snmp/doc/src/user_guide.gif b/lib/snmp/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/snmp/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/snmp/doc/src/warning.gif b/lib/snmp/doc/src/warning.gif
deleted file mode 100644
index 96af52360e..0000000000
--- a/lib/snmp/doc/src/warning.gif
+++ /dev/null
Binary files differ
diff --git a/lib/snmp/src/agent/snmpa_net_if.erl b/lib/snmp/src/agent/snmpa_net_if.erl
index ecf9498ca9..afed4482d2 100644
--- a/lib/snmp/src/agent/snmpa_net_if.erl
+++ b/lib/snmp/src/agent/snmpa_net_if.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -137,11 +137,10 @@ init(Prio, NoteStore, MasterAgent, Parent, Opts) ->
proc_lib:init_ack({ok, self()}),
try loop(State)
catch
- C:E when C =/= exit, E =/= shutdown ->
+ C:E:S when C =/= exit, E =/= shutdown ->
Fmt =
"loop/1 EXCEPTION ~w:~w~n"
" ~p",
- S = erlang:get_stacktrace(),
case C of
exit ->
%% Externally killed, root cause is elsewhere
@@ -647,10 +646,10 @@ maybe_handle_recv(
case
try FilterMod:accept_recv(From_1, From_2)
catch
- Class:Exception ->
+ Class:Exception:StackTrace ->
error_msg(
"FilterMod:accept_recv(~p, ~p) crashed: ~w:~w~n ~p",
- [From_1,From_2,Class,Exception,erlang:get_stacktrace()]),
+ [From_1, From_2, Class, Exception, StackTrace]),
true
end
of
@@ -753,12 +752,11 @@ maybe_handle_recv_pdu(
case
try FilterMod:accept_recv_pdu(From_1, From_2, Type)
catch
- Class:Exception ->
+ Class:Exception:StackTrace ->
error_msg(
"FilterMod:accept_recv_pdu(~p, ~p, ~p) crashed: ~w:~w~n"
" ~p",
- [From_1,From_2,Type,Class,Exception,
- erlang:get_stacktrace()]),
+ [From_1, From_2, Type, Class, Exception, StackTrace]),
true
end
of
@@ -834,11 +832,10 @@ maybe_handle_reply_pdu(
try
FilterMod:accept_send_pdu(Addresses, Type)
catch
- Class:Exception ->
+ Class:Exception:StackTrace ->
error_msg(
"FilterMod:accept_send_pdu(~p, ~p) crashed: ~w:~w~n ~p",
- [Addresses, Type, Class, Exception,
- erlang:get_stacktrace()]),
+ [Addresses, Type, Class, Exception, StackTrace]),
true
end
of
@@ -872,7 +869,7 @@ handle_reply_pdu(
ACMData, LogF)) of
{ok, Packet} ->
?vinfo("time in agent: ~w mysec", [time_in_agent()]),
- try maybe_udp_send(S, Transport, To, Packet)
+ try maybe_udp_send_wo_log(S, Transport, To, Packet)
catch
{Reason, Sz} ->
error_msg("Cannot send message "
@@ -917,11 +914,10 @@ maybe_handle_send_pdu(
case
try FilterMod:accept_send_pdu(AddressesToFilter, Type)
catch
- Class:Exception ->
+ Class:Exception:StackTrace ->
error_msg(
"FilterMod:accept_send_pdu(~p, ~p) crashed: ~w:~w~n ~p",
- [AddressesToFilter,Type,
- Class,Exception,erlang:get_stacktrace()]),
+ [AddressesToFilter, Type, Class, Exception, StackTrace]),
true
end
of
@@ -1049,46 +1045,36 @@ do_handle_send_pdu(S, Type, Pdu, Addresses) ->
[Sz, Reason, Pdu])
end.
-do_handle_send_pdu1(
- #state{transports = Transports} = S,
- Type, Addresses) ->
+do_handle_send_pdu1(S, Type, Addresses) ->
lists:foreach(
- fun ({Domain, Address, Packet}) when is_binary(Packet) ->
- ?vdebug(
- "[~w] sending packet:~n"
- " size: ~p~n"
- " to: ~p", [Domain, sz(Packet), Address]),
- To = {Domain, Address},
- case select_transport_from_domain(Domain, Transports) of
- false ->
- error_msg(
- "Can not find transport~n"
- " size: ~p~n"
- " to: ~s",
- [sz(Packet), format_address(To)]);
- Transport ->
- maybe_udp_send(S, Transport, To, Packet)
- end;
- ({Domain, Address, {Packet, LogData}}) when is_binary(Packet) ->
- ?vdebug(
- "[~w] sending encrypted packet:~n"
- " size: ~p~n"
- " to: ~p", [Domain, sz(Packet), Address]),
- To = {Domain, Address},
- case select_transport_from_domain(Domain, Transports) of
- false ->
- error_msg(
- "Can not find transport~n"
- " size: ~p~n"
- " to: ~s",
- [sz(Packet), format_address(To)]);
- Transport ->
- maybe_udp_send(S, Transport, To, Packet, Type, LogData)
- end
+ fun ({Domain, Address, Pkg}) when is_binary(Pkg) ->
+ do_handle_send_pdu2(S, Type, Domain, Address,
+ Pkg, Pkg, "");
+ ({Domain, Address, {Pkg, LogPkg}}) when is_binary(Pkg) ->
+ do_handle_send_pdu2(S, Type, Domain, Address,
+ Pkg, LogPkg, " encrypted")
end,
Addresses).
-maybe_udp_send(
+do_handle_send_pdu2(#state{transports = Transports} = S,
+ Type, Domain, Address, Pkg, LogPkg, EncrStr) ->
+ ?vdebug("[~w] sending~s packet:"
+ "~n size: ~p"
+ "~n to: ~p", [Domain, EncrStr, sz(Pkg), Address]),
+ To = {Domain, Address},
+ case select_transport_from_domain(Domain, Transports) of
+ false ->
+ error_msg("Can not find transport: "
+ "~n size: ~p"
+ "~n to: ~s",
+ [sz(Pkg), format_address(To)]);
+ Transport ->
+ maybe_udp_send_w_log(S, Transport, To, Pkg, LogPkg, Type)
+ end.
+
+
+%% This function is used when logging has already been done!
+maybe_udp_send_wo_log(
#state{filter = FilterMod, transports = Transports},
#transport{socket = Socket},
To, Packet) ->
@@ -1096,10 +1082,10 @@ maybe_udp_send(
case
try FilterMod:accept_send(To_1, To_2)
catch
- Class:Exception ->
+ Class:Exception:StackTrace ->
error_msg(
"FilterMod:accept_send(~p, ~p) crashed: ~w:~w~n ~p",
- [To_1,To_2,Class,Exception,erlang:get_stacktrace()]),
+ [To_1, To_2, Class, Exception, StackTrace]),
true
end
of
@@ -1118,18 +1104,18 @@ maybe_udp_send(
udp_send(Socket, To, Packet)
end.
-maybe_udp_send(
+maybe_udp_send_w_log(
#state{log = Log, filter = FilterMod, transports = Transports},
#transport{socket = Socket},
- To, Packet, Type, _LogData) ->
+ To, Pkg, LogPkg, Type) ->
{To_1, To_2} = fix_filter_address(Transports, To),
case
try FilterMod:accept_send(To_1, To_2)
catch
- Class:Exception ->
+ Class:Exception:StackTrace ->
error_msg(
"FilterMod:accept_send(~p, ~p) crashed for: ~w:~w~n ~p",
- [To_1, To_2, Class, Exception, erlang:get_stacktrace()]),
+ [To_1, To_2, Class, Exception, StackTrace]),
true
end
of
@@ -1143,10 +1129,10 @@ maybe_udp_send(
_ ->
error_msg(
"FilterMod:accept_send(~p, ~p) returned: ~p",
- [To_1,To_2,Other])
+ [To_1, To_2, Other])
end,
- log(Log, Type, Packet, To),
- udp_send(Socket, To, Packet)
+ log(Log, Type, LogPkg, To),
+ udp_send(Socket, To, Pkg)
end.
udp_send(Socket, To, B) ->
@@ -1168,11 +1154,10 @@ udp_send(Socket, To, B) ->
ok ->
ok
catch
- error:ExitReason ->
+ error:ExitReason:StackTrace ->
error_msg("[exit] cannot send message "
"(destination: ~p:~p, size: ~p, reason: ~p, at: ~p)",
- [IpAddr, IpPort, sz(B), ExitReason,
- erlang:get_stacktrace()])
+ [IpAddr, IpPort, sz(B), ExitReason, StackTrace])
end.
sz(L) when is_list(L) -> length(L);
diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src
index db09ec3dc5..ca61782639 100644
--- a/lib/snmp/src/app/snmp.appup.src
+++ b/lib/snmp/src/app/snmp.appup.src
@@ -8,10 +8,6 @@
%% {update, snmpa_local_db, soft, soft_purge, soft_purge, []}
%% {add_module, snmpm_net_if_mt}
[
- {<<"5\\.2\\.4">>,
- [{load_module, snmp, soft_purge, soft_purge, []},
- {load_module, snmpc_lib, soft_purge, soft_purge, []},
- {load_module, snmpc_mib_gram, soft_purge, soft_purge, []}]},
{<<"5\\..*">>, [{restart_application, snmp}]},
{<<"4\\..*">>, [{restart_application, snmp}]}
],
@@ -21,10 +17,6 @@
%% {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
[
- {<<"5\\.2\\.4">>,
- [{load_module, snmp, soft_purge, soft_purge, []},
- {load_module, snmpc_lib, soft_purge, soft_purge, []},
- {load_module, snmpc_mib_gram, soft_purge, soft_purge, []}]},
{<<"5\\..*">>, [{restart_application, snmp}]},
{<<"4\\..*">>, [{restart_application, snmp}]}
]
diff --git a/lib/snmp/src/compile/snmpc.erl b/lib/snmp/src/compile/snmpc.erl
index 416353508e..c810bfcd41 100644
--- a/lib/snmp/src/compile/snmpc.erl
+++ b/lib/snmp/src/compile/snmpc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -169,11 +169,7 @@ get_version() ->
MI = ?MODULE:module_info(),
Attr = get_info(attributes, MI),
Vsn = get_info(app_vsn, Attr),
- Comp = get_info(compile, MI),
- Time = get_info(time, Comp),
- {Year, Month, Day, Hour, Min, Sec} = Time,
- io_lib:format("~s [~.4w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w]",
- [Vsn, Year, Month, Day, Hour, Min, Sec]).
+ Vsn.
maybe_display_options(Opts) ->
case lists:member(options, Opts) of
@@ -455,7 +451,9 @@ compile_parsed_data(#pdata{mib_name = MibName,
Deprecated = get_deprecated(Opts),
RelChk = get_relaxed_row_name_assign_check(Opts),
Data = #dldata{deprecated = Deprecated,
- relaxed_row_name_assign_check = RelChk},
+ relaxed_row_name_assign_check = RelChk},
+ mc_new_type_loop(Definitions),
+ put(augmentations, false),
definitions_loop(Definitions, Data),
MibName.
@@ -480,7 +478,40 @@ do_update_imports([{{Mib, ImportsFromMib0},_Line}|Imports], Acc) ->
update_status(Name, Status) ->
#cdata{status_ets = Ets} = get(cdata),
ets:insert(Ets, {Name, Status}).
-
+
+
+mc_new_type_loop(
+ [{#mc_new_type{
+ name = NewTypeName,
+ macro = Macro,
+ syntax = OldType,
+ display_hint = DisplayHint},Line}|T]) ->
+ ?vlog2("typeloop -> new_type:"
+ "~n Macro: ~p"
+ "~n NewTypeName: ~p"
+ "~n OldType: ~p"
+ "~n DisplayHint: ~p",
+ [Macro, NewTypeName, OldType, DisplayHint], Line),
+ ensure_macro_imported(Macro,Line),
+ Types = (get(cdata))#cdata.asn1_types,
+ case lists:keysearch(NewTypeName, #asn1_type.aliasname, Types) of
+ {value,_} ->
+ snmpc_lib:print_error("Type ~w already defined.",
+ [NewTypeName],Line);
+ false ->
+ %% NameOfOldType = element(2,OldType),
+ ASN1 = snmpc_lib:make_ASN1type(OldType),
+ snmpc_lib:add_cdata(#cdata.asn1_types,
+ [ASN1#asn1_type{aliasname = NewTypeName,
+ imported = false,
+ display_hint = DisplayHint}])
+ end,
+ mc_new_type_loop(T);
+mc_new_type_loop([_|T]) ->
+ mc_new_type_loop(T);
+mc_new_type_loop([]) ->
+ ok.
+
%% A deprecated object
definitions_loop([{#mc_object_type{name = ObjName, status = deprecated},
@@ -744,32 +775,8 @@ definitions_loop([{#mc_object_type{name = NameOfTable,
ColMEs]),
definitions_loop(RestObjs, Data);
-definitions_loop([{#mc_new_type{name = NewTypeName,
- macro = Macro,
- syntax = OldType,
- display_hint = DisplayHint},Line}|T],
- Data) ->
- ?vlog2("defloop -> new_type:"
- "~n Macro: ~p"
- "~n NewTypeName: ~p"
- "~n OldType: ~p"
- "~n DisplayHint: ~p",
- [Macro, NewTypeName, OldType, DisplayHint], Line),
- ensure_macro_imported(Macro,Line),
- Types = (get(cdata))#cdata.asn1_types,
- case lists:keysearch(NewTypeName, #asn1_type.aliasname, Types) of
- {value,_} ->
- snmpc_lib:print_error("Type ~w already defined.",
- [NewTypeName],Line);
- false ->
- %% NameOfOldType = element(2,OldType),
- ASN1 = snmpc_lib:make_ASN1type(OldType),
- snmpc_lib:add_cdata(#cdata.asn1_types,
- [ASN1#asn1_type{aliasname = NewTypeName,
- imported = false,
- display_hint = DisplayHint}])
- end,
- definitions_loop(T, Data);
+definitions_loop([{#mc_new_type{},_}|T], Data) ->
+ definitions_loop(T, Data);
%% Plain variable
definitions_loop([{#mc_object_type{name = NewVarName,
@@ -1211,7 +1218,39 @@ definitions_loop([{Obj,Line}|T], Data) ->
definitions_loop([], _Data) ->
?vlog("defloop -> done", []),
- ok.
+ case get(augmentations) of
+ true ->
+ CData = get(cdata),
+ put(cdata, CData#cdata{mes = augmentations(CData#cdata.mes)}),
+ ok;
+ false ->
+ ok
+ end.
+
+augmentations(
+ [#me{
+ aliasname = AliasName,
+ assocList =
+ [{table_info,
+ #table_info{
+ index_types =
+ {augments, SrcTableEntry, Line}} = TableInfo}|Ref]} = Me
+ |Mes]) ->
+ ?vlog("augmentations(~w) ->"
+ "~n NameOfTable: ~p"
+ "~n IndexingInfo: ~p"
+ "~n Sline: ~p",
+ [?LINE, AliasName, {augments, SrcTableEntry}, Line]),
+ NewTableInfo = snmpc_lib:fix_table_info_augmentation(TableInfo),
+ [Me#me{assocList = [{table_info,NewTableInfo}|Ref]}
+ |augmentations(Mes)];
+augmentations([Me | Mes]) ->
+ [Me|augmentations(Mes)];
+augmentations([]) ->
+ ?vlog("augmentations -> done", []),
+ [].
+
+
safe_elem(N,T) ->
case catch(element(N,T)) of
diff --git a/lib/snmp/src/compile/snmpc_lib.erl b/lib/snmp/src/compile/snmpc_lib.erl
index 33ddd78308..19a6bc8851 100644
--- a/lib/snmp/src/compile/snmpc_lib.erl
+++ b/lib/snmp/src/compile/snmpc_lib.erl
@@ -26,7 +26,7 @@
-export([test_father/4, make_ASN1type/1, import/1, makeInternalNode2/2,
is_consistent/1, resolve_defval/1, make_variable_info/1,
check_trap_name/3, make_table_info/5, get_final_mib/2, set_dir/2,
- look_at/1, add_cdata/2,
+ fix_table_info_augmentation/1, look_at/1, add_cdata/2,
check_object_group/4, check_notification_group/4,
check_notification/3,
register_oid/4,
@@ -710,25 +710,34 @@ check_trap_name(EnterpriseName, Line, MEs) ->
%% functions for tables.
%%----------------------------------------------------------------------
+fix_table_info_augmentation(
+ #table_info{index_types = {augments, SrcTableEntry, Line}} = TableInfo) ->
+ MEs = (get(cdata))#cdata.mes,
+ Aug =
+ case lookup(SrcTableEntry, MEs) of
+ false ->
+ print_error(
+ "Cannot AUGMENT the non-existing table entry ~p",
+ [SrcTableEntry], Line),
+ {augments, error};
+ {value, ME} ->
+ {augments,
+ {SrcTableEntry, translate_type(ME#me.asn1_type)}}
+ end,
+ TableInfo#table_info{index_types = Aug}.
+
+
make_table_info(Line, TableName, {augments, SrcTableEntry}, _, ColumnMEs) ->
ColMEs = lists:keysort(#me.oid, ColumnMEs),
- Nbr_of_Cols = length(ColMEs),
- MEs = ColMEs ++ (get(cdata))#cdata.mes,
- Aug = case lookup(SrcTableEntry, MEs) of
- false ->
- print_error("Cannot AUGMENT the non-existing table entry ~p",
- [SrcTableEntry], Line),
- {augments, error};
- {value, ME} ->
- {augments, {SrcTableEntry, translate_type(ME#me.asn1_type)}}
- end,
- FirstNonIdxCol = augments_first_non_index_column(ColMEs),
+ Nbr_of_Cols = length(ColMEs),
+ put(augmentations, true),
+ FirstNonIdxCol = augments_first_non_index_column(ColMEs),
NoAccs = list_not_accessible(FirstNonIdxCol, ColMEs),
FirstAcc = first_accessible(TableName, ColMEs),
#table_info{nbr_of_cols = Nbr_of_Cols,
- first_accessible = FirstAcc,
- not_accessible = NoAccs,
- index_types = Aug};
+ first_accessible = FirstAcc,
+ not_accessible = NoAccs,
+ index_types = {augments, SrcTableEntry, Line}};
make_table_info(Line, TableName, {indexes, []}, _, _ColumnMEs) ->
print_error("Table ~w lacks indexes.", [TableName],Line),
#table_info{};
diff --git a/lib/snmp/src/manager/snmpm_net_if.erl b/lib/snmp/src/manager/snmpm_net_if.erl
index 93c987eb0f..29216f9d6a 100644
--- a/lib/snmp/src/manager/snmpm_net_if.erl
+++ b/lib/snmp/src/manager/snmpm_net_if.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -367,7 +367,7 @@ common_socket_opts(Opts) ->
default ->
[];
Sz ->
- [{sndbuf, Sz}]
+ [{recbuf, Sz}]
end ++
case get_opt(Opts, no_reuse, false) of
false ->
diff --git a/lib/snmp/src/misc/snmp_log.erl b/lib/snmp/src/misc/snmp_log.erl
index 767d801eee..5713c14912 100644
--- a/lib/snmp/src/misc/snmp_log.erl
+++ b/lib/snmp/src/misc/snmp_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -649,13 +649,14 @@ do_log_to_file(Log, TextFile, Mibs, Start, Stop) ->
MiniMib = snmp_mini_mib:create(Mibs),
Write = fun(X) ->
case format_msg(X, MiniMib, Start, Stop) of
- {ok, S} ->
- io:format(Fd, "~s", [S]);
- _ ->
- ok
+ {Tag, S} when (Tag =:= ok) orelse (Tag =:= error) ->
+ io:format(Fd, "~s", [S]),
+ Tag;
+ Ignore ->
+ Ignore
end
end,
- Res = (catch loop(disk_log:chunk(Log, start), Log, Write)),
+ Res = (catch loop(Log, Write)),
snmp_mini_mib:delete(MiniMib),
file:close(Fd),
Res;
@@ -668,39 +669,63 @@ do_log_to_io(Log, Mibs, Start, Stop) ->
MiniMib = snmp_mini_mib:create(Mibs),
Write = fun(X) ->
case format_msg(X, MiniMib, Start, Stop) of
- {ok, S} ->
- io:format("~s", [S]);
- _ ->
- ok
+ {Tag, S} when (Tag =:= ok) orelse (Tag =:= error) ->
+ io:format("~s", [S]),
+ Tag;
+ X ->
+ X
end
end,
- (catch loop(disk_log:chunk(Log, start), Log, Write)),
+ Res = (catch loop(Log, Write)),
snmp_mini_mib:delete(MiniMib),
- ok.
+ Res.
+
+loop(Log, Write) ->
+ loop(disk_log:chunk(Log, start), Log, Write, 0, 0).
-loop(eof, _Log, _Write) ->
+loop(eof, _Log, _Write, _NumOK, 0 = _NumERR) ->
ok;
-loop({error, _} = Error, _Log, _Write) ->
+loop(eof, _Log, _Write, NumOK, NumERR) ->
+ {ok, {NumOK, NumERR}};
+loop({error, _} = Error, _Log, _Write, _NumOK, _NumERR) ->
Error;
-loop({Cont, Terms}, Log, Write) ->
- case (catch lists:foreach(Write, Terms)) of
- {'EXIT', Reason} ->
- {error, Reason};
- _ ->
- loop(disk_log:chunk(Log, Cont), Log, Write)
+loop({Cont, Terms}, Log, Write, NumOK, NumERR) ->
+ try loop_terms(Terms, Write) of
+ {ok, {AddedOK, AddedERR}} ->
+ loop(disk_log:chunk(Log, Cont), Log, Write,
+ NumOK+AddedOK, NumERR+AddedERR)
+ catch
+ C:E:S ->
+ {error, {C, E, S}}
end;
-loop({Cont, Terms, BadBytes}, Log, Write) ->
+loop({Cont, Terms, BadBytes}, Log, Write, NumOK, NumERR) ->
error_logger:error_msg("Skipping ~w bytes while converting ~p~n~n",
[BadBytes, Log]),
- case (catch lists:foreach(Write, Terms)) of
- {'EXIT', Reason} ->
- {error, Reason};
- _ ->
- loop(disk_log:chunk(Log, Cont), Log, Write)
- end;
-loop(Error, _Log, _Write) ->
- Error.
+ try loop_terms(Terms, Write) of
+ {ok, {AddedOK, AddedERR}} ->
+ loop(disk_log:chunk(Log, Cont), Log, Write,
+ NumOK+AddedOK, NumERR+AddedERR)
+ catch
+ C:E:S ->
+ {error, {C, E, S}}
+ end.
+
+
+loop_terms(Terms, Write) ->
+ loop_terms(Terms, Write, 0, 0).
+
+loop_terms([], _Write, NumOK, NumERR) ->
+ {ok, {NumOK, NumERR}};
+loop_terms([Term|Terms], Write, NumOK, NumERR) ->
+ case Write(Term) of
+ ok ->
+ loop_terms(Terms, Write, NumOK+1, NumERR);
+ error ->
+ loop_terms(Terms, Write, NumOK, NumERR+1);
+ _ ->
+ loop_terms(Terms, Write, NumOK, NumERR)
+ end.
format_msg(Entry, Mib, Start, Stop) ->
@@ -733,88 +758,149 @@ do_format_msg({Timestamp, SeqNo, Packet, Ip, Port}, Mib) ->
%% This is crap...
do_format_msg(_, _) ->
- format_tab("** unknown entry in log file\n\n", []).
+ {error, format_tab("** unknown entry in log file\n\n", [])}.
do_format_msg(TimeStamp, {V3Hdr, ScopedPdu}, AddrStr, Mib) ->
- case (catch snmp_pdus:dec_scoped_pdu(ScopedPdu)) of
+ try snmp_pdus:dec_scoped_pdu(ScopedPdu) of
ScopedPDU when is_record(ScopedPDU, scopedPdu) ->
Msg = #message{version = 'version-3',
vsn_hdr = V3Hdr,
data = ScopedPDU},
- f(ts2str(TimeStamp), "", Msg, AddrStr, Mib);
- {'EXIT', Reason} ->
- format_tab(
- "** error in log file at ~s from ~s ~p\n\n",
- [ts2str(TimeStamp), AddrStr, Reason])
+ try f(ts2str(TimeStamp), "", Msg, AddrStr, Mib) of
+ {ok, _} = OK ->
+ OK
+ catch
+ FormatT:FormatE ->
+ format_error("format scoped pdu",
+ TimeStamp, AddrStr, FormatT, FormatE)
+ end
+ catch
+ DecT:DecE ->
+ format_error("decode scoped pdu",
+ TimeStamp, AddrStr, DecT, DecE)
end;
do_format_msg(TimeStamp, Packet, AddrStr, Mib) ->
- case (catch snmp_pdus:dec_message(binary_to_list(Packet))) of
+ try snmp_pdus:dec_message(binary_to_list(Packet)) of
Msg when is_record(Msg, message) ->
- f(ts2str(TimeStamp), "", Msg, AddrStr, Mib);
- {'EXIT', Reason} ->
- format_tab("** error in log file ~p\n\n", [Reason])
+ try f(ts2str(TimeStamp), "", Msg, AddrStr, Mib) of
+ {ok, _} = OK ->
+ OK
+ catch
+ FormatT:FormatE ->
+ %% Provide info about the message
+ Extra =
+ case Msg#message.version of
+ 'version-3' ->
+ #v3_hdr{msgID = ID,
+ msgFlags = Flags,
+ msgSecurityModel = SecModel} =
+ Msg#message.vsn_hdr,
+ SecLevel = snmp_misc:get_sec_level(Flags),
+ f("msg-id: ~w, sec-level: ~w, sec-model: ~w",
+ [ID, SecLevel, sm2atom(SecModel)]);
+ _ -> %% Community
+ f("community: ~s", [Msg#message.vsn_hdr])
+ end,
+ format_error(f("format ~p message; ~s",
+ [Msg#message.version, Extra]),
+ TimeStamp, AddrStr, FormatT, FormatE)
+ end
+ catch
+ DecT:DecE ->
+ format_error("decode message",
+ TimeStamp, AddrStr, DecT, DecE)
+
end.
-
+
+sm2atom(?SEC_ANY) -> any;
+sm2atom(?SEC_V1) -> v1;
+sm2atom(?SEC_V2C) -> v2c;
+sm2atom(?SEC_USM) -> usm;
+sm2atom(_) -> unknown.
+
do_format_msg(TimeStamp, SeqNo, {V3Hdr, ScopedPdu}, AddrStr, Mib) ->
- case (catch snmp_pdus:dec_scoped_pdu(ScopedPdu)) of
+ try snmp_pdus:dec_scoped_pdu(ScopedPdu) of
ScopedPDU when is_record(ScopedPDU, scopedPdu) ->
Msg = #message{version = 'version-3',
vsn_hdr = V3Hdr,
data = ScopedPDU},
- f(ts2str(TimeStamp), sn2str(SeqNo), Msg, AddrStr, Mib);
- {'EXIT', Reason} ->
- format_tab(
- "** error in log file at ~s from ~s ~p\n\n",
- [ts2str(TimeStamp), sn2str(SeqNo), AddrStr, Reason])
+ try f(ts2str(TimeStamp), sn2str(SeqNo), Msg, AddrStr, Mib) of
+ {ok, _} = OK ->
+ OK
+ catch
+ FormatT:FormatE ->
+ format_error("format scoped pdu",
+ TimeStamp, SeqNo, AddrStr, FormatT, FormatE)
+ end
+ catch
+ DecT:DecE ->
+ format_error("decode scoped pdu",
+ TimeStamp, SeqNo, AddrStr, DecT, DecE)
end;
do_format_msg(TimeStamp, SeqNo, Packet, AddrStr, Mib) ->
- case (catch snmp_pdus:dec_message(binary_to_list(Packet))) of
+ try snmp_pdus:dec_message(binary_to_list(Packet)) of
Msg when is_record(Msg, message) ->
- f(ts2str(TimeStamp), sn2str(SeqNo), Msg, AddrStr, Mib);
- {'EXIT', Reason} ->
- format_tab(
- "** error in log file ~s from ~s ~p\n\n",
- [ts2str(TimeStamp), sn2str(SeqNo), AddrStr, Reason])
+ try f(ts2str(TimeStamp), sn2str(SeqNo), Msg, AddrStr, Mib) of
+ {ok, _} = OK ->
+ OK
+
+ catch
+ FormatT:FormatE ->
+ %% Provide info about the message
+ Extra =
+ case Msg#message.version of
+ 'version-3' ->
+ #v3_hdr{msgID = ID,
+ msgFlags = Flags,
+ msgSecurityModel = SecModel} =
+ Msg#message.vsn_hdr,
+ SecLevel = snmp_misc:get_sec_level(Flags),
+ f("msg-id: ~w, sec-level: ~w, sec-model: ~w",
+ [ID, SecLevel, sm2atom(SecModel)]);
+ _ -> %% Community
+ f("community: ~s", [Msg#message.vsn_hdr])
+ end,
+ format_error(f("format ~p message; ~s",
+ [Msg#message.version, Extra]),
+ TimeStamp, SeqNo, AddrStr, FormatT, FormatE)
+ end
+ catch
+ DecT:DecE ->
+ format_error("decode message",
+ TimeStamp, SeqNo, AddrStr, DecT, DecE)
end.
-
-
-%% format_msg({TimeStamp, {V3Hdr, ScopedPdu}, {Addr, Port}},
-%% Mib, Start, Stop) ->
-%% format_msg({TimeStamp, {V3Hdr, ScopedPdu}, Addr, Port},
-%% Mib, Start, Stop);
-%% format_msg({TimeStamp, {V3Hdr, ScopedPdu}, Addr, Port},
-%% Mib, Start, Stop) ->
-%% case timestamp_filter(TimeStamp, Start, Stop) of
-%% true ->
-%% case (catch snmp_pdus:dec_scoped_pdu(ScopedPdu)) of
-%% ScopedPDU when record(ScopedPDU, scopedPdu) ->
-%% Msg = #message{version = 'version-3',
-%% vsn_hdr = V3Hdr,
-%% data = ScopedPDU},
-%% f(ts2str(TimeStamp), Msg, Addr, Port, Mib);
-%% {'EXIT', Reason} ->
-%% format_tab("** error in log file at ~s from ~p:~w ~p\n\n",
-%% [ts2str(TimeStamp), ip(Addr), Port, Reason])
-%% end;
-%% false ->
-%% ignore
-%% end;
-%% format_msg({TimeStamp, Packet, {Addr, Port}}, Mib, Start, Stop) ->
-%% format_msg({TimeStamp, Packet, Addr, Port}, Mib, Start, Stop);
-%% format_msg({TimeStamp, Packet, Addr, Port}, Mib, Start, Stop) ->
-%% case timestamp_filter(TimeStamp, Start, Stop) of
-%% true ->
-%% case (catch snmp_pdus:dec_message(binary_to_list(Packet))) of
-%% Msg when record(Msg, message) ->
-%% f(ts2str(TimeStamp), Msg, Addr, Port, Mib);
-%% {'EXIT', Reason} ->
-%% format_tab("** error in log file ~p\n\n", [Reason])
-%% end;
-%% false ->
-%% ignore
-%% end;
-%% format_msg(_, _Mib, _Start, _Stop) ->
-%% format_tab("** unknown entry in log file\n\n", []).
+
+
+format_error(WhatStr, TimeStamp, AddrStr, throw, {error, Reason}) ->
+ {ok, Str} =
+ format_tab(
+ "** error (~s) in log file at ~s from ~s: "
+ "~n ~p\n\n",
+ [WhatStr, ts2str(TimeStamp), AddrStr, Reason]),
+ {error, Str};
+format_error(WhatStr, TimeStamp, AddrStr, T, E) ->
+ {ok, Str} =
+ format_tab(
+ "** error (~s) in log file at ~s from ~s: "
+ "~n ~w: ~p\n\n",
+ [WhatStr, ts2str(TimeStamp), AddrStr, T, E]),
+ {error, Str}.
+
+format_error(WhatStr, TimeStamp, SeqNo, AddrStr, throw, {error, Reason}) ->
+ {ok, Str} =
+ format_tab(
+ "** error (~s) in log file at ~s~s from ~s: "
+ "~n ~p\n\n",
+ [WhatStr, ts2str(TimeStamp), sn2str(SeqNo), AddrStr, Reason]),
+ {error, Str};
+format_error(WhatStr, TimeStamp, SeqNo, AddrStr, T, E) ->
+ {ok, Str} =
+ format_tab(
+ "** error (~s) in log file at ~s~s from ~s: "
+ "~n ~w, ~p\n\n",
+ [WhatStr, ts2str(TimeStamp), sn2str(SeqNo), AddrStr, T, E]),
+ {error, Str}.
+
f(TimeStamp, SeqNo,
#message{version = Vsn, vsn_hdr = VsnHdr, data = Data},
@@ -838,51 +924,21 @@ f(TimeStamp, SeqNo,
end,
format_tab(
"~w ~s - ~s [~s]~s ~w\n~s",
- [Class, AddrStr, HdrStr, TimeStamp, SeqNo, Vsn, Str]).
-
-%% f(TimeStamp, SeqNo,
-%% #message{version = Vsn, vsn_hdr = VsnHdr, data = Data},
-%% Addr, Port, Mib) ->
-%% Str = format_pdu(Data, Mib),
-%% HdrStr = format_header(Vsn, VsnHdr),
-%% case get_type(Data) of
-%% trappdu ->
-%% f_trap(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port);
-%% 'snmpv2-trap' ->
-%% f_trap(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port);
-%% 'inform-request' ->
-%% f_inform(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port);
-%% 'get-response' ->
-%% f_response(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port);
-%% report ->
-%% f_report(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port);
-%% _ ->
-%% f_request(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port)
-%% end.
-
-%% f_request(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) ->
-%% format_tab("request ~s:~w - ~s [~s]~s ~w\n~s",
-%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]).
-
-%% f_response(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) ->
-%% format_tab("response ~s:~w - ~s [~s]~s ~w\n~s",
-%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]).
-
-%% f_report(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) ->
-%% format_tab("report ~s:~w - ~s [~s]~s ~w\n~s",
-%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]).
+ [Class, AddrStr, HdrStr, TimeStamp, SeqNo, Vsn, Str]);
+f(TimeStamp, SeqNo, Msg, AddrStr, _Mib) ->
+ io:format("<ERROR> Unexpected data: "
+ "~n TimeStamp: ~s~s"
+ "~n Msg: ~p"
+ "~n AddrStr: ~p"
+ "~n", [TimeStamp, SeqNo, Msg, AddrStr]),
+ throw({error, 'invalid-message'}).
-%% f_trap(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) ->
-%% format_tab("trap ~s:~w - ~s [~s]~s ~w\n~s",
-%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]).
+f(F, A) ->
+ lists:flatten(io_lib:format(F, A)).
-%% f_inform(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) ->
-%% format_tab("inform ~s:~w - ~s [~s]~s ~w\n~s",
-%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]).
ipPort2Str(Ip, Port) ->
snmp_conf:mk_addr_string({Ip, Port}).
- %% io_lib:format("~s:~w", [ip(Ip), Port]).
%% Convert a timestamp 2-tupple to a printable string
%%
@@ -973,7 +1029,13 @@ format_pdu(#scopedPdu{contextName = Context, data = Pdu}, Mib) ->
io_lib:format("Context: \"~s\"\n~s",
[Context, snmp_misc:format_pdu(Pdu, Mib)]);
format_pdu(Pdu, Mib) ->
- snmp_misc:format_pdu(Pdu, Mib).
+ try snmp_misc:format_pdu(Pdu, Mib) of
+ Str ->
+ Str
+ catch
+ _:_ ->
+ throw({error, 'invalid-pdu'})
+ end.
get_type(#scopedPdu{data = Pdu}) ->
get_type(Pdu);
@@ -983,12 +1045,6 @@ get_type(#pdu{type = Type}) ->
Type.
-%% ip(Domain, Addr) ->
-%% snmp_conf:mk_addr_string(Domain, Addr).
-%% ip({A,B,C,D}) ->
-%% io_lib:format("~w.~w.~w.~w", [A,B,C,D]).
-
-
%% -------------------------------------------------------------------
%% Various utility functions
diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl
index 3c1a6f2afd..f9c18af6ea 100644
--- a/lib/snmp/test/snmp_agent_test.erl
+++ b/lib/snmp/test/snmp_agent_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -605,7 +605,12 @@ init_per_group(multiple_reqs_3 = GroupName, Config) ->
init_per_group(test_multi_threaded = GroupName, Config) ->
init_mt(snmp_test_lib:init_group_top_dir(GroupName, Config));
init_per_group(test_v3 = GroupName, Config) ->
- init_v3(snmp_test_lib:init_group_top_dir(GroupName, Config));
+ case snmp_test_lib:crypto_start() of
+ ok ->
+ init_v3(snmp_test_lib:init_group_top_dir(GroupName, Config));
+ _ ->
+ {skip, "Crypto did not start"}
+ end;
init_per_group(test_v1_v2 = GroupName, Config) ->
init_v1_v2(snmp_test_lib:init_group_top_dir(GroupName, Config));
init_per_group(test_v2 = GroupName, Config) ->
@@ -631,11 +636,26 @@ init_per_group(mib_storage_varm_dets = GroupName, Config) ->
init_varm_mib_storage_dets(
snmp_test_lib:init_group_top_dir(GroupName, Config));
init_per_group(mib_storage_size_check_mnesia = GroupName, Config) ->
- init_size_check_msm(snmp_test_lib:init_group_top_dir(GroupName, Config));
+ case snmp_test_lib:crypto_start() of
+ ok ->
+ init_size_check_msm(snmp_test_lib:init_group_top_dir(GroupName, Config));
+ _ ->
+ {skip, "Crypto did not start"}
+ end;
init_per_group(mib_storage_size_check_dets = GroupName, Config) ->
- init_size_check_msd(snmp_test_lib:init_group_top_dir(GroupName, Config));
+ case snmp_test_lib:crypto_start() of
+ ok ->
+ init_size_check_msm(snmp_test_lib:init_group_top_dir(GroupName, Config));
+ _ ->
+ {skip, "Crypto did not start"}
+ end;
init_per_group(mib_storage_size_check_ets = GroupName, Config) ->
- init_size_check_mse(snmp_test_lib:init_group_top_dir(GroupName, Config));
+ case snmp_test_lib:crypto_start() of
+ ok ->
+ init_size_check_msm(snmp_test_lib:init_group_top_dir(GroupName, Config));
+ _ ->
+ {skip, "Crypto did not start"}
+ end;
init_per_group(mib_storage_mnesia = GroupName, Config) ->
init_mib_storage_mnesia(snmp_test_lib:init_group_top_dir(GroupName,
Config));
diff --git a/lib/snmp/test/snmp_compiler_test.erl b/lib/snmp/test/snmp_compiler_test.erl
index 9b3c2bfd2c..0a7b729d1f 100644
--- a/lib/snmp/test/snmp_compiler_test.erl
+++ b/lib/snmp/test/snmp_compiler_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -57,8 +57,9 @@
otp_8595/1,
otp_10799/1,
otp_10808/1,
- otp_14145/1
-
+ otp_14145/1,
+ otp_13014/1,
+ otp_14196/1
]).
%%----------------------------------------------------------------------
@@ -137,7 +138,8 @@ all() ->
groups() ->
[{tickets, [],
- [otp_6150, otp_8574, otp_8595, otp_10799, otp_10808, otp_14145]}].
+ [otp_6150, otp_8574, otp_8595, otp_10799, otp_10808, otp_14145,
+ otp_13014, otp_14196]}].
init_per_group(_GroupName, Config) ->
Config.
@@ -436,7 +438,7 @@ otp_10808(Config) when is_list(Config) ->
otp_14145(suite) ->
[];
otp_14145(Config) when is_list(Config) ->
- put(tname, otp10808),
+ put(tname, otp14145),
p("starting with Config: ~p~n", [Config]),
Dir = ?config(case_top_dir, Config),
@@ -457,6 +459,56 @@ otp_14145(Config) when is_list(Config) ->
%%======================================================================
+otp_13014(suite) ->
+ [];
+otp_13014(Config) when is_list(Config) ->
+ put(tname, otp13014),
+ p("starting with Config: ~p~n", [Config]),
+
+ Dir = ?config(case_top_dir, Config),
+ MibDir = ?config(mib_dir, Config),
+ MibName = "Test-LLDP-MIB",
+ MibFile = join(MibDir, MibName++".mib"),
+ ?line {ok, MibBin} =
+ snmpc:compile(MibFile, [{outdir, Dir},
+ {verbosity, log},
+ {group_check, false},
+ module_compliance]),
+ p("Mib: ~n~p~n", [MibBin]),
+ #mib{mes = MEs} = read_mib(MibBin),
+ Oid = [1,0,8802,1,1,2,1,1,7],
+ #me{
+ entrytype = table,
+ aliasname = lldpConfigManAddrTable,
+ assocList = [{table_info,TableInfo}]} =
+ lists:keyfind(Oid, #me.oid, MEs),
+ #table_info{
+ nbr_of_cols = 1,
+ first_accessible = 1,
+ not_accessible = [],
+ index_types = {augments,{lldpLocManAddrEntry,undefined}}} =
+ TableInfo,
+ ok.
+
+%%======================================================================
+
+otp_14196(suite) ->
+ [];
+otp_14196(Config) when is_list(Config) ->
+ put(tname, otp14196),
+ p("starting with Config: ~p~n", [Config]),
+
+ Dir = ?config(case_top_dir, Config),
+ MibDir = ?config(mib_dir, Config),
+ MibFile = join(MibDir, "OTP14196-MIB.mib"),
+ ?line {ok, Mib} =
+ snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}]),
+ p("Mib: ~n~p~n", [Mib]),
+ ok.
+
+
+%%======================================================================
+
augments_extra_info(suite) ->
[];
augments_extra_info(Config) when is_list(Config) ->
diff --git a/lib/snmp/test/snmp_manager_test.erl b/lib/snmp/test/snmp_manager_test.erl
index 4bfeb0f8d1..6ced55f0cc 100644
--- a/lib/snmp/test/snmp_manager_test.erl
+++ b/lib/snmp/test/snmp_manager_test.erl
@@ -156,16 +156,25 @@ init_per_suite(Config0) when is_list(Config0) ->
?DBG("init_per_suite -> entry with"
"~n Config0: ~p", [Config0]),
- Config1 = snmp_test_lib:init_suite_top_dir(?MODULE, Config0),
- Config2 = snmp_test_lib:fix_data_dir(Config1),
-
- %% Mib-dirs
- %% data_dir is trashed by the test-server / common-test
- %% so there is no point in fixing it...
- MibDir = snmp_test_lib:lookup(data_dir, Config2),
- StdMibDir = filename:join([code:priv_dir(snmp), "mibs"]),
-
- [{mib_dir, MibDir}, {std_mib_dir, StdMibDir} | Config2].
+ %% Preferably this test SUITE should be divided into groups
+ %% so that if crypto does not work only v3 tests that
+ %% need crypto will be skipped, but as this is only a
+ %% problem with one legacy test machine, we will procrastinate
+ %% until we have a more important reason to fix this.
+ case snmp_test_lib:crypto_start() of
+ ok ->
+ Config1 = snmp_test_lib:init_suite_top_dir(?MODULE, Config0),
+ Config2 = snmp_test_lib:fix_data_dir(Config1),
+ %% Mib-dirs
+ %% data_dir is trashed by the test-server / common-test
+ %% so there is no point in fixing it...
+ MibDir = snmp_test_lib:lookup(data_dir, Config2),
+ StdMibDir = filename:join([code:priv_dir(snmp), "mibs"]),
+
+ [{mib_dir, MibDir}, {std_mib_dir, StdMibDir} | Config2];
+ _ ->
+ {skip, "Crypto did not start"}
+ end.
end_per_suite(Config) when is_list(Config) ->
diff --git a/lib/snmp/test/snmp_test_data/OTP14196-MIB.mib b/lib/snmp/test/snmp_test_data/OTP14196-MIB.mib
new file mode 100644
index 0000000000..0b3c718a02
--- /dev/null
+++ b/lib/snmp/test/snmp_test_data/OTP14196-MIB.mib
@@ -0,0 +1,47 @@
+OTP14196-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+ MODULE-IDENTITY, OBJECT-TYPE, snmpModules, mib-2
+ FROM SNMPv2-SMI
+ TEXTUAL-CONVENTION
+ FROM SNMPv2-TC
+ OBJECT-GROUP
+ FROM SNMPv2-CONF
+ ;
+
+otp14196MIB MODULE-IDENTITY
+ LAST-UPDATED "1004210000Z"
+ ORGANIZATION ""
+ CONTACT-INFO
+ ""
+ DESCRIPTION
+ "Test mib for OTP-14196"
+ ::= { snmpModules 1 }
+
+testCompliances OBJECT IDENTIFIER ::= { otp14196MIB 1 }
+test OBJECT IDENTIFIER ::= { mib-2 15 }
+
+typeA OBJECT-TYPE
+ SYNTAX TypeAType
+ MAX-ACCESS accessible-for-notify
+ STATUS current
+ DESCRIPTION
+ "Test type for OTP-14196"
+ ::= { test 4711 }
+
+TypeAType ::= TEXTUAL-CONVENTION
+ STATUS current
+ DESCRIPTION
+ ""
+ SYNTAX INTEGER
+
+testGroups OBJECT IDENTIFIER ::= { testCompliances 1 }
+
+testGroupA OBJECT-GROUP
+ OBJECTS { typeA }
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { testGroups 17 }
+
+END
diff --git a/lib/snmp/test/snmp_test_data/Test-LLDP-MIB.mib b/lib/snmp/test/snmp_test_data/Test-LLDP-MIB.mib
new file mode 100644
index 0000000000..40a9fc79e1
--- /dev/null
+++ b/lib/snmp/test/snmp_test_data/Test-LLDP-MIB.mib
@@ -0,0 +1,251 @@
+Test-LLDP-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+ MODULE-IDENTITY, OBJECT-TYPE, Integer32, Counter32, NOTIFICATION-TYPE
+ FROM SNMPv2-SMI
+ TEXTUAL-CONVENTION, TimeStamp, TruthValue
+ FROM SNMPv2-TC
+ SnmpAdminString
+ FROM SNMP-FRAMEWORK-MIB
+ MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP
+ FROM SNMPv2-CONF;
+
+t-lldpMIB MODULE-IDENTITY
+ LAST-UPDATED "200505060000Z" -- May 06, 2005
+ ORGANIZATION "IEEE 802.1 Working Group"
+ CONTACT-INFO
+ " Contact: The Erlang/OTP team at Ericsson AB, Sweden
+
+ WG-URL: http://grouper.ieee.org/groups/802/1/index.html
+ WG-EMail: [email protected]
+
+ Contact: Paul Congdon
+ Postal: Hewlett-Packard Company
+ 8000 Foothills Blvd.
+ Roseville, CA 95747
+ USA
+ Tel: +1-916-785-5753
+ DESCRIPTION
+ "This is the ripped out bits and pieces of LLDP-MIB
+ that triggered a compilation problem for Erlang/OTP's
+ MIB compiler due to an AUGMENTS in lldpConfigManAddrEntry
+ refering to a not yet defined OBJECT-TYPE lldpLocManAddrEntry.
+ Rip and rewrite done 2017.
+
+ Management Information Base module for LLDP configuration,
+ statistics, local system data and remote systems data
+ components.
+
+ Copyright (C) IEEE (2005). This version of this MIB module
+ is published as subclause 12.1 of IEEE Std 802.1AB-2005;
+ see the standard itself for full legal notices."
+ REVISION "200505060000Z" -- May 06, 2005
+ DESCRIPTION
+ "Published as part of IEEE Std 802.1AB-2005 initial version."
+ ::= { iso std(0) iso8802(8802) ieee802dot1(1) ieee802dot1mibs(1) 2 }
+
+--lldpNotifications OBJECT IDENTIFIER ::= { lldpMIB 0 }
+lldpObjects OBJECT IDENTIFIER ::= { t-lldpMIB 1 }
+lldpConformance OBJECT IDENTIFIER ::= { t-lldpMIB 2 }
+
+--
+-- LLDP MIB Objects
+--
+
+lldpConfiguration OBJECT IDENTIFIER ::= { lldpObjects 1 }
+--lldpStatistics OBJECT IDENTIFIER ::= { lldpObjects 2 }
+lldpLocalSystemData OBJECT IDENTIFIER ::= { lldpObjects 3 }
+--lldpRemoteSystemsData OBJECT IDENTIFIER ::= { lldpObjects 4 }
+--lldpExtensions OBJECT IDENTIFIER ::= { lldpObjects 5 }
+
+
+
+LldpPortList ::= TEXTUAL-CONVENTION
+ STATUS current
+ DESCRIPTION
+ "Each octet within this value specifies a set of eight ports,
+ with the first octet specifying ports 1 through 8, the second
+ octet specifying ports 9 through 16, etc. Within each octet,
+ the most significant bit represents the lowest numbered port,
+ and the least significant bit represents the highest numbered
+ port. Thus, each port of the system is represented by a
+ single bit within the value of this object. If that bit has
+ a value of '1' then that port is included in the set of ports;
+ the port is not included if its bit has a value of '0'."
+ REFERENCE
+ "IETF RFC 2674 section 5"
+ SYNTAX OCTET STRING(SIZE(0..512))
+
+
+
+--
+-- lldpManAddrConfigTxPortsTable : selection of management addresses
+-- to be transmitted on a specified set
+-- of ports.
+--
+
+lldpConfigManAddrTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF LldpConfigManAddrEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "The table that controls selection of LLDP management address
+ TLV instances to be transmitted on individual ports."
+ ::= { lldpConfiguration 7 }
+
+lldpConfigManAddrEntry OBJECT-TYPE
+ SYNTAX LldpConfigManAddrEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "LLDP configuration information that specifies the set
+ of ports (represented as a PortList) on which the local
+ system management address instance will be transmitted.
+
+ This configuration object augments the lldpLocManAddrEntry,
+ therefore it is only present along with the management
+ address instance contained in the associated
+ lldpLocManAddrEntry entry.
+
+ Each active lldpConfigManAddrEntry must be restored from
+ non-volatile and re-created (along with the corresponding
+ lldpLocManAddrEntry) after a re-initialization of the
+ management system."
+ AUGMENTS { lldpLocManAddrEntry }
+ ::= { lldpConfigManAddrTable 1 }
+
+LldpConfigManAddrEntry ::= SEQUENCE {
+ lldpConfigManAddrPortsTxEnable LldpPortList
+}
+
+lldpConfigManAddrPortsTxEnable OBJECT-TYPE
+ SYNTAX LldpPortList
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+ "A set of ports that are identified by a PortList, in which
+ each port is represented as a bit. The corresponding local
+ system management address instance will be transmitted on the
+ member ports of the lldpManAddrPortsTxEnable.
+
+ The default value for lldpConfigManAddrPortsTxEnable object
+ is empty binary string, which means no ports are specified
+ for advertising indicated management address instance."
+ REFERENCE
+ "IEEE 802.1AB-2005 10.2.1.1"
+ DEFVAL { ''H } -- empty binary string
+ ::= { lldpConfigManAddrEntry 1 }
+
+
+--
+-- lldpLocManAddrTable : Management addresses of the local system
+--
+
+lldpLocManAddrTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF LldpLocManAddrEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "This table contains management address information on the
+ local system known to this agent."
+ ::= { lldpLocalSystemData 8 }
+
+lldpLocManAddrEntry OBJECT-TYPE
+ SYNTAX LldpLocManAddrEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Management address information about a particular chassis
+ component. There may be multiple management addresses
+ configured on the system identified by a particular
+ lldpLocChassisId. Each management address should have
+ distinct 'management address type' (lldpLocManAddrSubtype) and
+ 'management address' (lldpLocManAddr.)
+
+ Entries may be created and deleted in this table by the
+ agent."
+ INDEX { lldpLocManAddrIfId,
+ lldpLocManAddrLen }
+ ::= { lldpLocManAddrTable 1 }
+
+LldpLocManAddrEntry ::= SEQUENCE {
+ lldpLocManAddrIfId Integer32,
+ lldpLocManAddrLen Integer32,
+ lldpLocManAddrOID OBJECT IDENTIFIER
+}
+
+lldpLocManAddrIfId OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The integer value used to identify the interface number
+ regarding the management address component associated with
+ the local system."
+ REFERENCE
+ "IEEE 802.1AB-2005 9.5.9.6"
+ ::= { lldpLocManAddrEntry 1 }
+
+lldpLocManAddrLen OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total length of the management address subtype and the
+ management address fields in LLDPDUs transmitted by the
+ local LLDP agent.
+
+ The management address length field is needed so that the
+ receiving systems that do not implement SNMP will not be
+ required to implement an iana family numbers/address length
+ equivalency table in order to decode the management adress."
+ REFERENCE
+ "IEEE 802.1AB-2005 9.5.9.2"
+ ::= { lldpLocManAddrEntry 2 }
+
+lldpLocManAddrOID OBJECT-TYPE
+ SYNTAX OBJECT IDENTIFIER
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The OID value used to identify the type of hardware component
+ or protocol entity associated with the management address
+ advertised by the local system agent."
+ REFERENCE
+ "IEEE 802.1AB-2005 9.5.9.8"
+ ::= { lldpLocManAddrEntry 3 }
+
+
+lldpGroups OBJECT IDENTIFIER ::= { lldpConformance 1 }
+
+lldpLocSysGroup OBJECT-GROUP
+ OBJECTS {
+ lldpLocManAddrIfId,
+ lldpLocManAddrLen,
+ lldpLocManAddrOID
+ }
+ STATUS current
+ DESCRIPTION
+ "The collection of objects which are used to represent LLDP
+ Local System Information.
+
+ This group is mandatory for agents which implement the LLDP
+ and have the capability of transmitting LLDP frames."
+ ::= { lldpGroups 6 }
+
+lldpConfigTxGroup OBJECT-GROUP
+ OBJECTS {
+ lldpConfigManAddrPortsTxEnable
+ }
+ STATUS current
+ DESCRIPTION
+ "The collection of objects which are used to configure the
+ LLDP implementation behavior.
+
+ This group is mandatory for agents which implement the LLDP
+ and have the capability of transmitting LLDP frames."
+ ::= { lldpGroups 3 }
+
+
+END
diff --git a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl
index 24c14d86ea..b83c7461d1 100644
--- a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl
+++ b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2014-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2014-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -88,8 +88,17 @@ groups() ->
].
init_per_suite(Config) ->
- [{agent_port, ?AGENT_PORT}, {manager_port, ?MANAGER_PORT} | Config].
-
+ case re:run(os:cmd("snmpd -v"),"NET-SNMP", [{capture, first}]) of
+ nomatch ->
+ {skip, "snmpd is NOT NET-SNMP"};
+ {match, _} ->
+ case re:run(os:cmd("snmpd -v"),"5.4|5.6.2.1", [{capture, first}]) of
+ nomatch ->
+ [{agent_port, ?AGENT_PORT}, {manager_port, ?MANAGER_PORT} | Config];
+ {match, _} ->
+ {skip, "buggy snmpd"}
+ end
+ end.
end_per_suite(_Config) ->
ok.
@@ -322,7 +331,7 @@ snmpget(Oid, Transport, Config) ->
Args =
["-c", "public", net_snmp_version(Versions),
- "-m", "",
+ "-m", ":",
"-Cf",
net_snmp_addr_str(Transport),
oid_str(Oid)],
@@ -353,11 +362,13 @@ start_snmpd(Community, SysDescr, Config) ->
["--rocommunity"++domain_suffix(Domain)++"="
++Community++" "++inet_parse:ntoa(Ip)
|| {Domain, {Ip, _}} <- Targets],
+
SnmpdArgs =
- ["-f", "-r", %"-Dverbose",
- "-c", filename:join(DataDir, "snmpd.conf"),
- "-C", "-Lo",
- "-m", "",
+ ["-f", "-r", %"-Dverbose",
+ "-c", filename:join(DataDir, "snmpd.conf"),
+ "-C",
+ "-Lo",
+ "-m", ":",
"--sysDescr="++SysDescr,
"--agentXSocket=tcp:localhost:"++integer_to_list(Port)]
++ CommunityArgs
diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk
index d41b1999cc..4d5a0fbce8 100644
--- a/lib/snmp/vsn.mk
+++ b/lib/snmp/vsn.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2017. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = snmp
-SNMP_VSN = 5.2.6
+SNMP_VSN = 5.2.12
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)"
diff --git a/lib/ssh/doc/specs/.gitignore b/lib/ssh/doc/specs/.gitignore
new file mode 100644
index 0000000000..322eebcb06
--- /dev/null
+++ b/lib/ssh/doc/specs/.gitignore
@@ -0,0 +1 @@
+specs_*.xml
diff --git a/lib/ssh/doc/src/Makefile b/lib/ssh/doc/src/Makefile
index a759854da4..77fa356092 100644
--- a/lib/ssh/doc/src/Makefile
+++ b/lib/ssh/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2016. All Rights Reserved.
+# Copyright Ericsson AB 2004-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -38,27 +38,31 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# Target Specs
# ----------------------------------------------------
XML_APPLICATION_FILES = ref_man.xml
-XML_REF3_FILES = ssh.xml \
- ssh_channel.xml \
- ssh_connection.xml \
+XML_REF3_FILES = \
+ ssh.xml \
+ ssh_client_channel.xml \
ssh_client_key_api.xml \
+ ssh_connection.xml \
+ ssh_server_channel.xml \
ssh_server_key_api.xml \
ssh_sftp.xml \
ssh_sftpd.xml \
XML_REF6_FILES = ssh_app.xml
-XML_PART_FILES = part_notes.xml \
- usersguide.xml
-XML_CHAPTER_FILES = notes.xml \
+XML_PART_FILES = usersguide.xml
+
+XML_CHAPTER_FILES = \
+ notes.xml \
introduction.xml \
- ssh_protocol.xml \
- using_ssh.xml
+ using_ssh.xml \
+ configure_algos.xml
+# ssh_protocol.xml \
BOOK_FILES = book.xml
XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) $(XML_REF6_FILES)\
- $(XML_PART_FILES) $(XML_CHAPTER_FILES)
+ $(XML_PART_FILES) $(XML_CHAPTER_FILES)
IMAGE_FILES = SSH_protocols.png
@@ -83,11 +87,18 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
+
+TOP_SPECS_FILE = specs.xml
+
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
+XML_FLAGS +=
+DVIPS_FLAGS +=
+
+#SPECS_FLAGS = -I../../include -I../../../kernel/include
+SPECS_FLAGS = -I../../../public_key/include -I../../../public_key/src -I../../..
# ----------------------------------------------------
# Targets
@@ -108,19 +119,21 @@ html: images $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+ rm -f $(SPECS_FILES)
rm -f errs core *~
man: $(MAN3_FILES) $(MAN6_FILES)
-debug opt:
+debug opt:
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
diff --git a/lib/ssh/doc/src/configure_algos.xml b/lib/ssh/doc/src/configure_algos.xml
new file mode 100644
index 0000000000..fa45b1cb4c
--- /dev/null
+++ b/lib/ssh/doc/src/configure_algos.xml
@@ -0,0 +1,429 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2017</year>
+ <year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>Configuring algorithms in SSH</title>
+ <prepared></prepared>
+ <docno></docno>
+ <approved></approved>
+ <date></date>
+ <rev></rev>
+ <file>configure_algos.xml</file>
+ </header>
+
+ <section>
+ <marker id="introduction"/>
+ <title>Introduction</title>
+ <p>To fully understand how to configure the algorithms, it is essential to have a basic understanding of the SSH protocol
+ and how OTP SSH app handles the corresponding items</p>
+
+ <p>The first subsection will give a short background of the SSH protocol while later sections describes
+ the implementation and provides some examples</p>
+
+ <section>
+ <title>Basics of the ssh protocol's algorithms handling</title>
+
+ <p>SSH uses different sets of algorithms in different phases of a session. Which
+ algorithms to use is negotiated by the client and the server at the beginning of a session.
+ See <url href="https://tools.ietf.org/html/rfc4253">RFC 4253</url>,
+ "The Secure Shell (SSH) Transport Layer Protocol" for details.
+ </p>
+
+ <p>The negotiation is simple: both peers sends their list of supported alghorithms to the other part.
+ The first algorithm on the client's list that also in on the server's list is selected. So it is the
+ client's orderering of the list that gives the priority for the algorithms.</p>
+
+ <p>There are five lists exchanged in the connection setup. Three of them are also divided in two
+ directions, to and from the server.</p>
+
+ <p>The lists are (named as in the SSH application's options):</p>
+ <taglist>
+ <tag><c>kex</c></tag>
+ <item>
+ <p>Key exchange.</p>
+ <p>An algorithm is selected for computing a secret encryption key. Among examples are:
+ the old nowadays week <c>'diffie-hellman-group-exchange-sha1'</c> and the very strong and modern
+ <c>'ecdh-sha2-nistp512'</c>.</p>
+ </item>
+
+ <tag><c>public_key</c></tag>
+ <item>
+ <p>Server host key</p>
+ <p>The asymetric encryption algorithm used in the server's private-public host key pair.
+ Examples include the well-known RSA <c>'ssh-rsa'</c> and elliptic curve <c>'ecdsa-sha2-nistp521'</c>.
+ </p>
+ </item>
+
+ <tag><c>cipher</c></tag>
+ <item>
+ <p>Symetric cipher algorithm used for the payload encryption. This algorithm will use the key calculated
+ in the kex phase (together with other info) to genereate the actual key used. Examples are
+ tripple-DES <c>'3des-cbc'</c> and one of many AES variants <c>'aes192-ctr'</c>.
+ </p>
+ <p>This list is actually two - one for each direction server-to-client and client-to-server. Therefore it
+ is possible but rare to have different algorithms in the two directions in one connection.</p>
+ </item>
+
+ <tag><c>mac</c></tag>
+ <item>
+ <p>Message authentication code</p>
+ <p>"Check sum" of each message sent between the peers. Examples are SHA <c>'hmac-sha1'</c> and
+ SHA2 <c>'hmac-sha2-512'</c>.</p>
+ <p>This list is also divided into two for the both directions</p>
+ </item>
+
+ <tag><c>compression</c></tag>
+ <item>
+ <p>If and how to compress the message. Examples are <c>none</c>, that is, no compression and
+ <c>zlib</c>.</p>
+ <p>This list is also divided into two for the both directions</p>
+ </item>
+
+ </taglist>
+ </section>
+
+ <section>
+ <title>The SSH app's mechanism</title>
+ <p>The set of algorithms that the SSH app uses by default depends on the algoritms supported by the:</p>
+ <list>
+ <item><p><seealso marker="crypto:crypto">crypto</seealso> app,</p>
+ </item>
+ <item><p>The cryptolib OTP is linked with, usally the one the OS uses, probably OpenSSL,</p>
+ </item>
+ <item><p>and finaly what the SSH app implements</p>
+ </item>
+ </list>
+ <p>Due to this, it impossible to list in documentation what algorithms that are available in a certain installation.</p>
+ <p>There is an important command to list the actual algorithms and their ordering:
+ <seealso marker="ssh#default_algorithms-0">ssh:default_algorithms/0</seealso>.</p>
+ <marker id="example_default_algorithms"/>
+ <code type="erl">
+0> ssh:default_algorithms().
+[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521',
+ 'ecdh-sha2-nistp256','diffie-hellman-group-exchange-sha256',
+ 'diffie-hellman-group16-sha512',
+ 'diffie-hellman-group18-sha512',
+ 'diffie-hellman-group14-sha256',
+ 'diffie-hellman-group14-sha1',
+ 'diffie-hellman-group-exchange-sha1']},
+ {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
+ 'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256',
+ 'rsa-sha2-512','ssh-dss']},
+ {cipher,[{client2server,['[email protected]',
+ 'aes256-ctr','aes192-ctr','[email protected]',
+ 'aes128-ctr','aes128-cbc','3des-cbc']},
+ {server2client,['[email protected]','aes256-ctr',
+ 'aes192-ctr','[email protected]','aes128-ctr',
+ 'aes128-cbc','3des-cbc']}]},
+ {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512',
+ 'hmac-sha1']},
+ {server2client,['hmac-sha2-256','hmac-sha2-512',
+ 'hmac-sha1']}]},
+ {compression,[{client2server,[none,'[email protected]',zlib]},
+ {server2client,[none,'[email protected]',zlib]}]}]
+
+ </code>
+ <p>To change the algorithm list, there are two options which can be used in
+ <seealso marker="ssh#connect-3">ssh:connect/2,3,4</seealso>
+ and
+ <seealso marker="ssh#daemon-2">ssh:daemon/2,3</seealso>. The options could of course
+ be used in all other functions that initiates connections.</p>
+
+ <p>The options are <c>preferred_algorithms</c> and <c>modify_algorithms</c>. The first one
+ replaces the default set, while the latter modifies the default set.</p>
+ </section>
+ </section>
+
+ <section>
+ <title>Replacing the default set: preferred_algorithms</title>
+ <p>See the <seealso marker="ssh#type-preferred_algorithms_common_option">Reference Manual</seealso> for details</p>
+
+ <p>Here follows a series of examples ranging from simple to more complex.</p>
+
+ <p>To forsee the effect of an option there is an experimental function <c>ssh:chk_algos_opts(Opts)</c>.
+ It mangles the options <c>preferred_algorithms</c>
+ and <c>modify_algorithms</c> in the same way as <c>ssh:dameon</c>, <c>ssh:connect</c> and their friends does.</p>
+
+ <section>
+ <title>Example 1</title>
+ <p>Replace the kex algorithms list with the single algorithm <c>'diffie-hellman-group14-sha256'</c>:</p>
+ <code>
+1> ssh:chk_algos_opts(
+ [{preferred_algorithms,
+ [{kex, ['diffie-hellman-group14-sha256']}
+ ]
+ }
+ ]).
+[{kex,['diffie-hellman-group14-sha256']},
+ {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
+ 'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256',
+ 'rsa-sha2-512','ssh-dss']},
+ {cipher,[{client2server,['[email protected]',
+ 'aes256-ctr','aes192-ctr','[email protected]',
+ 'aes128-ctr','aes128-cbc','3des-cbc']},
+ {server2client,['[email protected]','aes256-ctr',
+ 'aes192-ctr','[email protected]','aes128-ctr',
+ 'aes128-cbc','3des-cbc']}]},
+ {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512',
+ 'hmac-sha1']},
+ {server2client,['hmac-sha2-256','hmac-sha2-512',
+ 'hmac-sha1']}]},
+ {compression,[{client2server,[none,'[email protected]',zlib]},
+ {server2client,[none,'[email protected]',zlib]}]}]
+ </code>
+ <p>Note that the unmentioned lists (<c>public_key</c>, <c>cipher</c>, <c>mac</c> and <c>compression</c>)
+ are un-changed.</p>
+ </section>
+
+ <section>
+ <title>Example 2</title>
+ <p>In the lists that are divided in two for the two directions (c.f <c>cipher</c>) it is possible
+ to change both directions at once:</p>
+ <code>
+2> ssh:chk_algos_opts(
+ [{preferred_algorithms,
+ [{cipher,['aes128-ctr']}
+ ]
+ }
+ ]).
+[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521',
+ 'ecdh-sha2-nistp256','diffie-hellman-group-exchange-sha256',
+ 'diffie-hellman-group16-sha512',
+ 'diffie-hellman-group18-sha512',
+ 'diffie-hellman-group14-sha256',
+ 'diffie-hellman-group14-sha1',
+ 'diffie-hellman-group-exchange-sha1']},
+ {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
+ 'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256',
+ 'rsa-sha2-512','ssh-dss']},
+ {cipher,[{client2server,['aes128-ctr']},
+ {server2client,['aes128-ctr']}]},
+ {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512',
+ 'hmac-sha1']},
+ {server2client,['hmac-sha2-256','hmac-sha2-512',
+ 'hmac-sha1']}]},
+ {compression,[{client2server,[none,'[email protected]',zlib]},
+ {server2client,[none,'[email protected]',zlib]}]}]
+ </code>
+ <p>Note that both lists in <c>cipher</c> has been changed to the provided value (<c>'aes128-ctr'</c>).</p>
+ </section>
+
+ <section>
+ <title>Example 3</title>
+ <p>In the lists that are divided in two for the two directions (c.f <c>cipher</c>) it is possible
+ to change only one of the directions:</p>
+ <code>
+3> ssh:chk_algos_opts(
+ [{preferred_algorithms,
+ [{cipher,[{client2server,['aes128-ctr']}]}
+ ]
+ }
+ ]).
+[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521',
+ 'ecdh-sha2-nistp256','diffie-hellman-group-exchange-sha256',
+ 'diffie-hellman-group16-sha512',
+ 'diffie-hellman-group18-sha512',
+ 'diffie-hellman-group14-sha256',
+ 'diffie-hellman-group14-sha1',
+ 'diffie-hellman-group-exchange-sha1']},
+ {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
+ 'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256',
+ 'rsa-sha2-512','ssh-dss']},
+ {cipher,[{client2server,['aes128-ctr']},
+ {server2client,['[email protected]','aes256-ctr',
+ 'aes192-ctr','[email protected]','aes128-ctr',
+ 'aes128-cbc','3des-cbc']}]},
+ {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512',
+ 'hmac-sha1']},
+ {server2client,['hmac-sha2-256','hmac-sha2-512',
+ 'hmac-sha1']}]},
+ {compression,[{client2server,[none,'[email protected]',zlib]},
+ {server2client,[none,'[email protected]',zlib]}]}]
+ </code>
+ </section>
+
+ <section>
+ <title>Example 4</title>
+ <p>It is of course possible to change more than one list:</p>
+ <code>
+4> ssh:chk_algos_opts(
+ [{preferred_algorithms,
+ [{cipher,['aes128-ctr']},
+ {mac,['hmac-sha2-256']},
+ {kex,['ecdh-sha2-nistp384']},
+ {public_key,['ssh-rsa']},
+ {compression,[{server2client,[none]},
+ {client2server,[zlib]}]}
+ ]
+ }
+ ]).
+[{kex,['ecdh-sha2-nistp384']},
+ {public_key,['ssh-rsa']},
+ {cipher,[{client2server,['aes128-ctr']},
+ {server2client,['aes128-ctr']}]},
+ {mac,[{client2server,['hmac-sha2-256']},
+ {server2client,['hmac-sha2-256']}]},
+ {compression,[{client2server,[zlib]},
+ {server2client,[none]}]}]
+
+ </code>
+ <p>Note that the ordering of the tuples in the lists didn't matter.</p>
+ </section>
+ </section>
+
+ <section>
+ <title>Modifying the default set: modify_algorithms</title>
+ <p>A situation where it might be useful to add an algorithm is when one need to use a supported but disabled one.
+ An example is the <c>'diffie-hellman-group1-sha1'</c> which nowadays is very unsecure and therefore disabled. It is
+ however still supported and might be used.</p>
+
+ <p>The option <c>preferred_algorithms</c> may be complicated to use for adding or removing single algorithms.
+ First one has to list them with <c>ssh:default_algorithms()</c> and then do changes in the lists.</p>
+
+ <p>To facilitate addition or removal of algorithms the option <c>modify_algorithms</c> is available.
+ See the <seealso marker="ssh#type-modify_algorithms_common_option">Reference Manual</seealso> for details.</p>
+
+ <p>The option takes a list with instructions to append, prepend or remove algorithms:</p>
+ <code type="erl">
+{modify_algorithms, [{append, ...},
+ {prepend, ...},
+ {rm, ...}
+ ]}
+ </code>
+ <p>Each of the <c>...</c> can be a <c>algs_list()</c> as the argument to the <c>preferred_algorithms</c> option.</p>
+ <section>
+ <title>Example 5</title>
+ <p>As an example let's add the Diffie-Hellman Group1 first in the kex list. It is supported according to
+ <seealso marker="SSH_app#supported_algos">Supported algoritms</seealso>.</p>
+ <code type="erl">
+5> ssh:chk_algos_opts(
+ [{modify_algorithms,
+ [{prepend,
+ [{kex,['diffie-hellman-group1-sha1']}]
+ }
+ ]
+ }
+ ]).
+[{kex,['diffie-hellman-group1-sha1','ecdh-sha2-nistp384',
+ 'ecdh-sha2-nistp521','ecdh-sha2-nistp256',
+ 'diffie-hellman-group-exchange-sha256',
+ 'diffie-hellman-group16-sha512',
+ 'diffie-hellman-group18-sha512',
+ 'diffie-hellman-group14-sha256',
+ 'diffie-hellman-group14-sha1',
+ 'diffie-hellman-group-exchange-sha1']},
+ {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
+ 'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256',
+ 'rsa-sha2-512','ssh-dss']},
+ {cipher,[{client2server,['[email protected]',
+ 'aes256-ctr','aes192-ctr','[email protected]',
+ 'aes128-ctr','aes128-cbc','3des-cbc']},
+ {server2client,['[email protected]','aes256-ctr',
+ 'aes192-ctr','[email protected]','aes128-ctr',
+ 'aes128-cbc','3des-cbc']}]},
+ {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512',
+ 'hmac-sha1']},
+ {server2client,['hmac-sha2-256','hmac-sha2-512',
+ 'hmac-sha1']}]},
+ {compression,[{client2server,[none,'[email protected]',zlib]},
+ {server2client,[none,'[email protected]',zlib]}]}]
+
+ </code>
+ <p>And the result shows that the Diffie-Hellman Group1 is added at the head of the kex list</p>
+ </section>
+
+ <section>
+ <title>Example 6</title>
+ <p>In this example, we in put the 'diffie-hellman-group1-sha1' first and also move the
+ <c>'ecdh-sha2-nistp521'</c> to the end in the kex list, that is, <c>append</c> it.</p>
+ <code type="erl">
+6> ssh:chk_algos_opts(
+ [{modify_algorithms,
+ [{prepend,
+ [{kex, ['diffie-hellman-group1-sha1']}
+ ]},
+ {append,
+ [{kex, ['ecdh-sha2-nistp521']}
+ ]}
+ ]
+ }
+ ]).
+[{kex,['diffie-hellman-group1-sha1','ecdh-sha2-nistp384',
+ 'ecdh-sha2-nistp256','diffie-hellman-group-exchange-sha256',
+ 'diffie-hellman-group16-sha512',
+ 'diffie-hellman-group18-sha512',
+ 'diffie-hellman-group14-sha256',
+ 'diffie-hellman-group14-sha1',
+ 'diffie-hellman-group-exchange-sha1','ecdh-sha2-nistp521']},
+ {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
+ .....
+]
+ </code>
+ <p>Note that the appended algorithm is removed from its original place and then appended to the same list.</p>
+ </section>
+
+ <section>
+ <title>Example 7</title>
+ <p>In this example, we use both options (<c>preferred_algorithms</c> and <c>modify_algorithms</c>) and
+ also try to prepend an unsupported algorithm. Any unsupported algorithm is quietly removed.</p>
+ <code type="erl">
+7> ssh:chk_algos_opts(
+ [{preferred_algorithms,
+ [{cipher,['aes128-ctr']},
+ {mac,['hmac-sha2-256']},
+ {kex,['ecdh-sha2-nistp384']},
+ {public_key,['ssh-rsa']},
+ {compression,[{server2client,[none]},
+ {client2server,[zlib]}]}
+ ]
+ },
+ {modify_algorithms,
+ [{prepend,
+ [{kex, ['some unsupported algorithm']}
+ ]},
+ {append,
+ [{kex, ['diffie-hellman-group1-sha1']}
+ ]}
+ ]
+ }
+ ]).
+[{kex,['ecdh-sha2-nistp384','diffie-hellman-group1-sha1']},
+ {public_key,['ssh-rsa']},
+ {cipher,[{client2server,['aes128-ctr']},
+ {server2client,['aes128-ctr']}]},
+ {mac,[{client2server,['hmac-sha2-256']},
+ {server2client,['hmac-sha2-256']}]},
+ {compression,[{client2server,[zlib]},
+ {server2client,[none]}]}]
+
+ </code>
+ <p>It is of course questionable why anyone would like to use the both these options together,
+ but it is possible if an unforeseen need should arise.</p>
+ </section>
+
+
+
+ </section>
+
+</chapter>
diff --git a/lib/ssh/doc/src/fascicules.xml b/lib/ssh/doc/src/fascicules.xml
deleted file mode 100644
index 7e99398c16..0000000000
--- a/lib/ssh/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="usersguide" href="usersguide_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/ssh/doc/src/introduction.xml b/lib/ssh/doc/src/introduction.xml
index b7a73e2597..8444daf0cc 100644
--- a/lib/ssh/doc/src/introduction.xml
+++ b/lib/ssh/doc/src/introduction.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2012</year>
- <year>2016</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -145,7 +145,7 @@
data that can be sent to the channel peer without adjusting the
window. Typically, an SSH client opens a channel, sends data (commands),
receives data (control information), and then closes the channel.
- The <seealso marker="ssh_channel">ssh_channel</seealso> behaviour
+ The <seealso marker="ssh_client_channel">ssh_client_channel</seealso> behaviour
handles generic parts of SSH channel management. This makes it easy
to write your own SSH client/server processes that use flow-control
and thus opens for more focus on the application logic.
diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml
index f93753f1d2..7e77c6a457 100644
--- a/lib/ssh/doc/src/notes.xml
+++ b/lib/ssh/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,6 +30,543 @@
<file>notes.xml</file>
</header>
+<section><title>Ssh 4.7.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Extended the undocumented <c>ssh_dbg</c> debug module
+ with an api for a circular trace buffer. This makes it
+ easy to record the last low-level events before an error
+ is detected. It is intended for solving difficult errors.</p>
+ <p>
+ Own Id: OTP-15020</p>
+ </item>
+ <item>
+ <p>
+ The key exchange methods
+ <c>'[email protected]'</c>,
+ <c>'curve25519-sha256'</c> and <c>'curve448-sha512'</c>
+ are implemented. The last two are defined in
+ https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves</p>
+ <p>
+ They all depends on that OpenSSL 1.1.1 or higher is used
+ as cryptolib.</p>
+ <p>
+ Own Id: OTP-15133 Aux Id: OTP-15240 </p>
+ </item>
+ <item>
+ <p>
+ The cipher '<c>[email protected]</c>' is now
+ supported if OpenSSL 1.1.1 or higher is used as
+ cryptolib.</p>
+ <p>
+ Own Id: OTP-15209 Aux Id: OTP-15164 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.7</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ If the daemon port listener is restarted, it could
+ potentially fail with <c>eaddrinuse</c> if the timing is
+ unlucky. It will now retry and exponentially back off the
+ listener restart a few times before failing.</p>
+ <p>
+ Own Id: OTP-14955</p>
+ </item>
+ <item>
+ <p>
+ A channel callback module always got the module name as
+ reason in a call to terminate. Now it will get the proper
+ Reason, usually 'normal'.</p>
+ <p>
+ Own Id: OTP-15084</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The option <c>exec</c> has new option values defined to
+ make it much more easy to implement an own <c>exec</c>
+ server.</p>
+ <p>
+ An option called <c>exec</c> for daemons implementing the
+ handling of 'exec' requests has existed a long time but
+ has been undocumented. The old undocumented value - as
+ well as its behavior - is kept for compatibility EXCEPT
+ that error messages are changed and are sent as
+ "stderror" text.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-14851</p>
+ </item>
+ <item>
+ <p>
+ Updated ssh_connection:shell/2 documentation.</p>
+ <p>
+ Own Id: OTP-14880</p>
+ </item>
+ <item>
+ <p>
+ The experimental <c>ssh_dbg</c> module is completely
+ re-written. Its purpose is to make tracing and debugging
+ easier on deployed systems.</p>
+ <p>
+ Own Id: OTP-14896</p>
+ </item>
+ <item>
+ <p>
+ The SSH supervisor structure has been slightly changed.
+ This makes stopping the ssh application considerably
+ faster if there are open connections. This is important
+ in for example restarts.</p>
+ <p>
+ Own Id: OTP-14988</p>
+ </item>
+ <item>
+ <p>
+ The type specifications in SSH are completly reworked and
+ the following types are renamed:</p>
+ <p>
+ <c>ssh:ssh_connection_ref()</c> is changed to
+ <c>ssh:connection_ref()</c>, </p>
+ <p>
+ <c>ssh:ssh_daemon_ref()</c> is changed to
+ <c>ssh:daemon_ref()</c>,</p>
+ <p>
+ <c>ssh:ssh_channel_id()</c> is changed to
+ <c>ssh:channel_id()</c>.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15002 Aux Id: OTP-15030 </p>
+ </item>
+ <item>
+ <p>
+ The internal timer handling in SSH is now based on the
+ gen_statem timers.</p>
+ <p>
+ Own Id: OTP-15019</p>
+ </item>
+ <item>
+ <p>
+ Removed the undocumented and unused modules
+ <c>ssh_client_key.erl</c> and <c>ssh_server_key.erl</c>.</p>
+ <p>
+ Own Id: OTP-15028</p>
+ </item>
+ <item>
+ <p>
+ The Reference Manual pages are partly updated.</p>
+ <p>
+ The ssh page is now generated from specs and types, is
+ restructured and is partly rephrased.</p>
+ <p>
+ The ssh_channel, ssh_connection, ssh_client_key_api,
+ ssh_server_key_api and ssh_sftp pages are updated with
+ links, correct type names and some minor changes.</p>
+ <p>
+ Own Id: OTP-15030 Aux Id: OTP-15002 </p>
+ </item>
+ <item>
+ <p>
+ The behaviors <c>ssh_channel</c> and
+ <c>ssh_daemon_channel</c> are renamed to
+ <c>ssh_client_channel</c> and <c>ssh_server_channel</c>
+ respectively.</p>
+ <p>
+ The old modules are kept for compatibility but should
+ preferably be replaced when updating callback modules
+ referring them.</p>
+ <p>
+ Own Id: OTP-15041</p>
+ </item>
+ <item>
+ <p>
+ New test suite for channels.</p>
+ <p>
+ Own Id: OTP-15051</p>
+ </item>
+ <item>
+ <p>
+ The <c>rekey_limit</c> option could now set the max time
+ as well as the previously max data amount.</p>
+ <p>
+ Own Id: OTP-15069 Aux Id: ERL-617 </p>
+ </item>
+ <item>
+ <p>
+ Changed process exit supervision from links to monitors.</p>
+ <p>
+ Own Id: OTP-15082</p>
+ </item>
+ <item>
+ <p>
+ Better handling of misbehaving channel callback modules.</p>
+ <p>
+ Own Id: OTP-15083</p>
+ </item>
+ <item>
+ <p>
+ A new moduli file is generated. This file is used for the
+ recommended <c>diffie-hellman-group-exchange-sha256</c>
+ key exchange algorithm in SSH.</p>
+ <p>
+ Own Id: OTP-15113</p>
+ </item>
+ </list>
+ </section>
+</section>
+
+<section><title>Ssh 4.6.9.1</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ SFTP clients reported the error reason <c>""</c> if a
+ non-OTP sftp server was killed during a long file
+ transmission.</p>
+ <p>
+ Now the signal name (for example <c>"KILL"</c>) will be
+ the error reason if the server's reason is empty.</p>
+ <p>
+ The documentation also lacked type information about this
+ class of errors.</p>
+ <p>
+ Own Id: OTP-15148 Aux Id: ERIERL-194 </p>
+ </item>
+ <item>
+ <p>
+ Fix ssh_sftp decode error for sftp protocol version 4</p>
+ <p>
+ Own Id: OTP-15149 Aux Id: ERIERL-199 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.6.9</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Host key hash erroneously calculated for clients
+ following draft-00 of RFC 4419, for example PuTTY</p>
+ <p>
+ Own Id: OTP-15064</p>
+ </item>
+ <item>
+ <p>
+ Renegotiation could fail in some states</p>
+ <p>
+ Own Id: OTP-15066</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.6.8</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ An ssh_sftp server (running version 6) could fail if it
+ is told to remove a file which in fact is a directory.</p>
+ <p>
+ Own Id: OTP-15004</p>
+ </item>
+ <item>
+ <p>
+ Fix rare spurios shutdowns of ssh servers when receiveing
+ <c>{'EXIT',_,normal}</c> messages.</p>
+ <p>
+ Own Id: OTP-15018</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.6.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix bad spec in ssh.hrl: <c>double_algs()</c>.</p>
+ <p>
+ Own Id: OTP-14990</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.6.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Remove a blocking risk when a channel is closed and an
+ operation is tried on that channel after at least a
+ second's time gap.</p>
+ <p>
+ Own Id: OTP-14939</p>
+ </item>
+ </list>
+ </section>
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added ssh_compat_SUITE.</p>
+ <p>
+ This suite contains a number of interoperability tests
+ mainly with OpenSSH. The tests start docker containers
+ with different OpenSSH and OpenSSL/LibreSSLcryptolib
+ versions and performs a number of tests of supported
+ algorithms.</p>
+ <p>
+ All login methods and all user's public key types are
+ tested both for the client and the server.</p>
+ <p>
+ All algorithms for kex, cipher, host key, mac and
+ compressions are tested with a number of exec and sftp
+ tests, both for the client and the server.</p>
+ <p>
+ Own Id: OTP-14194 Aux Id: OTP-12487 </p>
+ </item>
+ <item>
+ <p>
+ Default exec is disabled when a user-defined shell is
+ enabled.</p>
+ <p>
+ Own Id: OTP-14881</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.6.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Adjusted supervisor timeouts</p>
+ <p>
+ Own Id: OTP-14907</p>
+ </item>
+ <item>
+ <p>
+ Remove ERROR messages for slow process exits</p>
+ <p>
+ Own Id: OTP-14930</p>
+ </item>
+ </list>
+ </section>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add option <c>save_accepted_host</c> to
+ <c>ssh:connection</c>. This option, if set to false,
+ inhibits saving host keys to e.g the file
+ <c>known_hosts</c>.</p>
+ <p>
+ Own Id: OTP-14935</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.6.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix problem with OpenSSH 7.2 (and later) clients that has
+ used sha1 instead of sha2 for rsa-sha-256/512 user's
+ public keys.</p>
+ <p>
+ Own Id: OTP-14827 Aux Id: ERL-531 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.6.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Passphrase option for ecdsa public keys was missing.</p>
+ <p>
+ Own Id: OTP-14602</p>
+ </item>
+ </list>
+ </section>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The host and user public key handling is hardened so that
+ a faulty plugin can't deliver a key of wrong type.</p>
+ <p>
+ Better checks in the server of the available hostkey's
+ types at start and at each accept.</p>
+ <p>
+ Better checks in the client of the available user public
+ key types at connect.</p>
+ <p>
+ Own Id: OTP-14676 Aux Id: ERIERL-52, OTP-14570 </p>
+ </item>
+ <item>
+ <p>
+ SSH can now fetch the host key from the private keys
+ stored in an Engine. See the crypto application for
+ details about Engines.</p>
+ <p>
+ Own Id: OTP-14757</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.6.2</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Trailing white space was removed at end of the
+ hello-string. This caused interoperability problems with
+ some other ssh-implementations (e.g OpenSSH 7.3p1 on
+ Solaris 11)</p>
+ <p>
+ Own Id: OTP-14763 Aux Id: ERIERL-74 </p>
+ </item>
+ <item>
+ <p>
+ Fixes that tcp connections that was immediately closed
+ (SYN, SYNACK, ACK, RST) by a client could be left in a
+ zombie state.</p>
+ <p>
+ Own Id: OTP-14778 Aux Id: ERIERL-104 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.6.1</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed broken printout</p>
+ <p>
+ Own Id: OTP-14645</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Disable aes_gcm ciphers if peer is OpenSSH 6.2 which is
+ known to have trouble with them in some cases.</p>
+ <p>
+ Own Id: OTP-14638</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Enables the <c>ssh_io module</c> to also accept binary
+ values when reading standard_io instead of getting stuck
+ in the receive clause.</p>
+ <p>
+ Own Id: OTP-14506 Aux Id: PR1503 </p>
+ </item>
+ <item>
+ <p>
+ Previously, the file owner access permission in response
+ to ssh_sftp:read_file_info/2 function was always
+ <c>read_write</c>. With this fix, the actual value of
+ file owner access permission is added to the returning
+ record. That value is calculated from file mode value.</p>
+ <p>
+ Own Id: OTP-14550 Aux Id: PR1533 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A new option <c>modify_algorithms</c> is implemented. It
+ enables specifying changes on the default algorithms
+ list. See the reference manual and the SSH User's Guide
+ chapter "Configuring algorithms in SSH".</p>
+ <p>
+ Own Id: OTP-14568</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.5.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ All unknown options are sent to the transport handler
+ regardless of type.</p>
+ <p>
+ Own Id: OTP-14541 Aux Id: EIRERL-63 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Ssh 4.5</title>
<section><title>Improvements and New Features</title>
@@ -200,6 +737,82 @@
</section>
+<section><title>Ssh 4.4.2.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix rare spurios shutdowns of ssh servers when receiveing
+ <c>{'EXIT',_,normal}</c> messages.</p>
+ <p>
+ Own Id: OTP-15018</p>
+ </item>
+ <item>
+ <p>
+ Host key hash erroneously calculated for clients
+ following draft-00 of RFC 4419, for example PuTTY</p>
+ <p>
+ Own Id: OTP-15064</p>
+ </item>
+ <item>
+ <p>
+ Renegotiation could fail in some states</p>
+ <p>
+ Own Id: OTP-15066</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.4.2.3</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ An ssh_sftp server (running version 6) could fail if it
+ is told to remove a file which in fact is a directory.</p>
+ <p>
+ Own Id: OTP-15004</p>
+ </item>
+ </list>
+ </section>
+</section>
+
+<section><title>Ssh 4.4.2.2</title>
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Default exec is disabled when a user-defined shell is
+ enabled.</p>
+ <p>
+ Own Id: OTP-14881</p>
+ </item>
+ </list>
+ </section>
+</section>
+
+
+<section><title>Ssh 4.4.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Trailing white space was removed at end of the
+ hello-string. This caused interoperability problems with
+ some other ssh-implementations (e.g OpenSSH 7.3p1 on
+ Solaris 11)</p>
+ <p>
+ Own Id: OTP-14763 Aux Id: ERIERL-74 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Ssh 4.4.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -570,6 +1183,108 @@
</section>
+<section><title>Ssh 4.2.2.6</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix rare spurios shutdowns of ssh servers when receiveing
+ <c>{'EXIT',_,normal}</c> messages.</p>
+ <p>
+ Own Id: OTP-15018</p>
+ </item>
+ </list>
+ </section>
+</section>
+
+
+<section><title>Ssh 4.2.2.5</title>
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Default exec is disabled when a user-defined shell is
+ enabled.</p>
+ <p>
+ Own Id: OTP-14881</p>
+ </item>
+ </list>
+ </section>
+</section>
+
+
+<section><title>Ssh 4.2.2.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Trailing white space was removed at end of the
+ hello-string. This caused interoperability problems with
+ some other ssh-implementations (e.g OpenSSH 7.3p1 on
+ Solaris 11)</p>
+ <p>
+ Own Id: OTP-14763 Aux Id: ERIERL-74 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.2.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The key exchange algorithm
+ diffie-hellman-group-exchange-sha* has a server-option
+ <c>{dh_gex_limits,{Min,Max}}</c>. There was a hostkey
+ signature validation error on the client side if the
+ option was used and the <c>Min</c> or the <c>Max</c>
+ differed from the corresponding values obtained from the
+ client.</p>
+ <p>
+ This bug is now corrected.</p>
+ <p>
+ Own Id: OTP-14166</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Key exchange algorithms
+ diffie-hellman-group-exchange-sha* optimized, up to a
+ factor of 11 for the slowest ( = biggest and safest) one.</p>
+ <p>
+ Own Id: OTP-14169 Aux Id: seq-13261 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.2.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Upgrade of an established client connection could crash
+ because the ssh client supervisors children had wrong
+ type. This is fixed now.</p>
+ <p>
+ Own Id: OTP-13782 Aux Id: seq13158 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Ssh 4.2.2.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/ssh/doc/src/part_notes.xml b/lib/ssh/doc/src/part_notes.xml
deleted file mode 100644
index aaca8ca9f2..0000000000
--- a/lib/ssh/doc/src/part_notes.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>SSH Release Notes</title>
- <prepared>Jakob Cederlund</prepared>
- <docno></docno>
- <date></date>
- <rev>%VSN%</rev>
- <file>part_notes.sgml</file>
- </header>
- <description>
- <p>This document describes the changes made to the SSH application.
- </p>
- </description>
- <xi:include file="notes.xml"/>
-</part>
-
diff --git a/lib/ssh/doc/src/ref_man.xml b/lib/ssh/doc/src/ref_man.xml
index 140ebd8c76..df37b0244f 100644
--- a/lib/ssh/doc/src/ref_man.xml
+++ b/lib/ssh/doc/src/ref_man.xml
@@ -4,7 +4,7 @@
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2004</year><year>2016</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -35,7 +35,8 @@
</description>
<xi:include href="ssh_app.xml"/>
<xi:include href="ssh.xml"/>
- <xi:include href="ssh_channel.xml"/>
+ <xi:include href="ssh_client_channel.xml"/>
+ <xi:include href="ssh_server_channel.xml"/>
<xi:include href="ssh_connection.xml"/>
<xi:include href="ssh_client_key_api.xml"/>
<xi:include href="ssh_server_key_api.xml"/>
diff --git a/lib/ssh/doc/src/specs.xml b/lib/ssh/doc/src/specs.xml
new file mode 100644
index 0000000000..acdbe2ddfd
--- /dev/null
+++ b/lib/ssh/doc/src/specs.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<specs xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="../specs/specs_ssh.xml"/>
+ <xi:include href="../specs/specs_ssh_client_channel.xml"/>
+ <xi:include href="../specs/specs_ssh_client_key_api.xml"/>
+ <xi:include href="../specs/specs_ssh_connection.xml"/>
+ <xi:include href="../specs/specs_ssh_server_channel.xml"/>
+ <xi:include href="../specs/specs_ssh_server_key_api.xml"/>
+ <xi:include href="../specs/specs_ssh_sftp.xml"/>
+ <xi:include href="../specs/specs_ssh_sftpd.xml"/>
+</specs>
+
+
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index ea7e975ef5..f238bf2ca8 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -4,15 +4,15 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
+
+ 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,
@@ -31,176 +31,211 @@
<module>ssh</module>
<modulesummary>Main API of the ssh application</modulesummary>
<description>
- <p>Interface module for the <c>ssh</c> application.</p>
- <p>See <seealso marker="ssh:SSH_app#supported">ssh(6)</seealso> for details of supported version,
- algorithms and unicode support.</p>
+ <p>This is the interface module for the <c>SSH</c> application.
+ The Secure Shell (SSH) Protocol is a protocol for secure remote login
+ and other secure network services over an insecure network.
+ See <seealso marker="ssh:SSH_app#supported">ssh(6)</seealso> for details of supported RFCs, versions,
+ algorithms and unicode handling.
+ </p>
+ <p>With the SSH application it is possible to start <i>clients</i> and to start <i>daemons</i> (servers).
+ </p>
+ <p>Clients are started with
+ <seealso marker="#connect/2">connect/2</seealso>,
+ <seealso marker="#connect/3">connect/3</seealso> or
+ <seealso marker="#connect/4">connect/4</seealso>. They open an encrypted connection on top of TCP/IP.
+ In that encrypted connection one or more channels could be opened with
+ <seealso marker="ssh_connection#session_channel/2">ssh_connection:session_channel/2,4</seealso>.
+ </p>
+ <p>Each channel is an isolated "pipe" between a client-side process and a server-side process. Thoose process
+ pairs could handle for example file transfers (sftp) or remote command execution (shell, exec and/or cli).
+ If a custom shell is implemented, the user of the client could execute the special commands remotely. Note that
+ the user is not necessarily a human but probably a system interfacing the SSH app.
+ </p>
+ <p>A server-side subssystem (channel) server is requested by the client with
+ <seealso marker="ssh_connection#subsystem/4">ssh_connection:subsystem/4</seealso>.
+ </p>
+ <p>A server (daemon) is started with
+ <seealso marker="#daemon/2">daemon/1</seealso>,
+ <seealso marker="#daemon/2">daemon/2</seealso> or
+ <seealso marker="#daemon/2">daemon/3</seealso>.
+ Possible channel handlers (subsystems) are declared with the
+ <seealso marker="#type-subsystem_daemon_option">subsystem</seealso> option when the daemon is started.
+ </p>
+ <p>To just run a shell on a remote machine, there are functions that bundles the needed
+ three steps needed into one:
+ <seealso marker="#shell/1">shell/1,2,3</seealso>.
+ Similarily, to just open an sftp (file transfer) connection to a remote machine, the simplest way is to use
+ <seealso marker="ssh_sftp#start_channel/1">ssh_sftp:start_channel/1,2,3</seealso>.
+ </p>
+ <p>To write your own client channel handler, use the behaviour
+ <seealso marker="ssh_client_channel">ssh_client_channel</seealso>. For server channel handlers use
+ <seealso marker="ssh_server_channel">ssh_server_channel</seealso> behaviour (replaces ssh_daemon_channel).
+ </p>
+ <p>Both clients and daemons accepts options that controls the exact behaviour. Some options are common to both.
+ The three sets are called
+ <seealso marker="#type-client_options">Client Options</seealso>,
+ <seealso marker="#type-daemon_options">Daemon Options</seealso> and
+ <seealso marker="#type-common_options">Common Options</seealso>.
+ </p>
+ <p>The descriptions of the options uses the
+ <seealso marker="doc/reference_manual:typespec">Erlang Type Language</seealso> with explaining text.
+ </p>
+ <note>
+ <p>The <seealso marker="users_guide">User's Guide</seealso> has examples and a
+ <seealso marker="using_ssh">Getting Started</seealso>
+ section.
+ </p>
+ </note>
</description>
<section>
- <title>OPTIONS</title>
- <p>The exact behaviour of some functions can be adjusted with the use of options which are documented together
- with the functions. Generally could each option be used at most one time in each function call. If given two or more
- times, the effect is not predictable unless explicitly documented.</p>
- <p>The options are of different kinds:</p>
- <taglist>
- <tag>Limits</tag>
- <item><p>which alters limits in the system, for example number of simultaneous login attempts.</p></item>
-
- <tag>Timeouts</tag>
- <item><p>which give some defined behaviour if too long time elapses before a given event or action,
- for example time to wait for an answer.</p></item>
-
- <tag>Callbacks</tag>
- <item><p>which gives the caller of the function the possibility to execute own code on some events,
- for example calling an own logging function or to perform an own login function</p></item>
-
- <tag>Behaviour</tag>
- <item><p>which changes the systems behaviour.</p></item>
- </taglist>
+ <title>Keys and files</title>
+ <p>A number of objects must be present for the SSH application to work.
+ Thoose objects are per default stored in files.
+ The default names, paths and file formats are the same as for
+ <url href="http://www.openssh.com">OpenSSH</url>. Keys could be generated with the <c>ssh-keygen</c>
+ program from OpenSSH. See the
+ <seealso marker="using_ssh#running-an-erlang-ssh-daemon">User's Guide</seealso>.
+ </p>
+
+ <p>The paths could easily be changed by options:
+ <seealso marker="#type-user_dir_common_option"><c>user_dir</c></seealso> and
+ <seealso marker="#type-system_dir_daemon_option"><c>system_dir</c></seealso>.
+ </p>
+ <p>A completly different storage could be interfaced by writing call-back modules
+ using the behaviours
+ <seealso marker="ssh_client_key_api">ssh_client_key_api</seealso> and/or
+ <seealso marker="ssh_server_key_api">ssh_server_key_api</seealso>.
+ A callback module is installed with the option
+ <seealso marker="#type-key_cb_common_option"><c>key_cb</c></seealso>
+ to the client and/or the daemon.
+ </p>
+
+ <section>
+ <title>Daemons</title>
+ <p>The keys are by default stored in files:</p>
+ <list>
+ <item>Mandatory: one or more <i>Host key(s)</i>, both private and public. Default is to
+ store them in the directory <c>/etc/ssh</c> in the files
+ <list>
+ <item><c>ssh_host_dsa_key</c> and <c>ssh_host_dsa_key.pub</c></item>
+ <item><c>ssh_host_rsa_key</c> and <c>ssh_host_rsa_key.pub</c></item>
+ <item><c>ssh_host_ecdsa_key</c> and <c>ssh_host_ecdsa_key.pub</c></item>
+ </list>
+ <p>The host keys directory could be changed with the option
+ <seealso marker="#type-system_dir_daemon_option"><c>system_dir</c></seealso>.</p>
+ </item>
+ <item>Optional: one or more <i>User's public key</i> in case of <c>publickey</c> authorization.
+ Default is to store them concatenated in the file <c>.ssh/authorized_keys</c> in the user's home directory.
+ <p>The user keys directory could be changed with the option
+ <seealso marker="#type-user_dir_common_option"><c>user_dir</c></seealso>.</p>
+ </item>
+ </list>
+ </section>
+
+ <section>
+ <title>Clients</title>
+ <p>The keys and some other data are by default stored in files in the directory <c>.ssh</c>
+ in the user's home directory.</p>
+ <p>The directory could be changed with the option
+ <seealso marker="#type-user_dir_common_option"><c>user_dir</c></seealso>.
+ </p>
+ <list>
+ <item>Optional: a list of <i>Host public key(s)</i> for previously connected hosts. This list
+ is handled by the SSH application without any need of user assistance. The default
+ is to store them in the file <c>known_hosts</c>.
+ <p>The
+ <seealso marker="#type-host_accepting_client_options">host_accepting_client_options()</seealso>
+ are associated with this list of keys.
+ </p>
+ </item>
+ <item>Optional: one or more <i>User's private key(s)</i> in case of <c>publickey</c> authorization.
+ The default files are
+ <list>
+ <item><c>id_dsa</c> and <c>id_dsa.pub</c></item>
+ <item><c>id_rsa</c> and <c>id_rsa.pub</c></item>
+ <item><c>id_ecdsa</c> and <c>id_ecdsa.pub</c></item>
+ </list>
+ </item>
+ </list>
+ </section>
+
</section>
- <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><c>[byte()]</c></p></item>
- <tag><c>ssh_daemon_ref() =</c></tag>
- <item><p>opaque() -
- as returned by <c>ssh:daemon/[1,2,3]</c></p></item>
- <tag><c>ssh_connection_ref() =</c></tag>
- <item><p>opaque() - as returned by <c>ssh:connect/3</c></p></item>
- <tag><c>ip_address() =</c></tag>
- <item><p><c>inet::ip_address</c></p></item>
- <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>string()</c></p></item>
- <tag><c>channel_callback() =</c></tag>
- <item><p><c>atom()</c> - Name of the Erlang module
- implementing the subsystem using the <c>ssh_channel</c> behavior, see
- <seealso marker="ssh_channel">ssh_channel(3)</seealso></p></item>
- <tag><c>key_cb() =</c></tag>
- <item>
- <p><c>atom() | {atom(), list()}</c></p>
- <p><c>atom()</c> - Name of the erlang module implementing the behaviours
- <seealso marker="ssh_client_key_api">ssh_client_key_api</seealso> or
- <seealso marker="ssh_client_key_api">ssh_client_key_api</seealso> as the
- case maybe.</p>
- <p><c>list()</c> - List of options that can be passed to the callback module.</p>
- </item>
- <tag><c>channel_init_args() =</c></tag>
- <item><p><c>list()</c></p></item>
-
- <tag><c>algs_list() =</c></tag>
- <item><p><c>list( alg_entry() )</c></p></item>
-
- <tag><c>alg_entry() =</c></tag>
- <item><p><c>{kex, simple_algs()} | {public_key, simple_algs()} | {cipher, double_algs()} | {mac, double_algs()} | {compression, double_algs()}</c></p></item>
-
- <tag><c>simple_algs() =</c></tag>
- <item><p><c>list( atom() )</c></p></item>
-
- <tag><c>double_algs() =</c></tag>
- <item><p><c>[{client2serverlist,simple_algs()},{server2client,simple_algs()}] | simple_algs()</c></p></item>
- </taglist>
-</section>
+ <!--
+ ================================================================
+ = Data types =
+ ================================================================
+ -->
- <funcs>
-
- <func>
- <name>close(ConnectionRef) -> ok </name>
- <fsummary>Closes an SSH connection.</fsummary>
- <type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- </type>
- <desc><p>Closes an SSH connection.</p>
+ <datatypes>
+
+ <datatype_title>Client Options</datatype_title>
+
+ <datatype>
+ <name name="client_options"/>
+ <name name="client_option"/>
+ <desc>
+ <p>Options for <seealso marker="#connect/3">clients</seealso>.
+ The individual options are further explained below or by following the hyperlinks.
+ </p>
</desc>
- </func>
-
- <func>
- <name>connect(Host, Port, Options) -> </name>
- <name>connect(Host, Port, Options, Timeout) -> </name>
- <name>connect(TcpSocket, Options) -> </name>
- <name>connect(TcpSocket, Options, Timeout) ->
- {ok, ssh_connection_ref()} | {error, Reason}</name>
- <fsummary>Connects to an SSH server.</fsummary>
- <type>
- <v>Host = string()</v>
- <v>Port = integer()</v>
- <d><c><![CDATA[22]]></c> is default, the assigned well-known port
- number for SSH.</d>
- <v>Options = [{Option, Value}]</v>
- <v>Timeout = infinity | integer()</v>
- <d>Negotiation time-out in milli-seconds. The default value is <c>infinity</c>.
- For connection time-out, use option <c>{connect_timeout, timeout()}</c>.</d>
- <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>
- </type>
+ </datatype>
+
+ <datatype>
+ <name name="pref_public_key_algs_client_option"/>
+ <desc>
+ <p>List of user (client) public key algorithms to try to use.</p>
+ <p>The default value is the <c>public_key</c> entry in the list returned by
+ <seealso marker="#default_algorithms/0">ssh:default_algorithms/0</seealso>.
+ </p>
+ <p>If there is no public key of a specified type available, the corresponding entry is ignored.
+ Note that the available set is dependent on the underlying cryptolib and current user's public keys.
+ </p>
+ <p>See also the option <seealso marker="#type-user_dir_common_option"><c>user_dir</c></seealso>
+ for specifying the path to the user's keys.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="pubkey_passphrase_client_options"/>
+ <desc>
+ <p>If the user's DSA, RSA or ECDSA key is protected by a passphrase, it can be
+ supplied with thoose options.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="host_accepting_client_options"/>
+ <name name="accept_hosts"/>
+ <name name="fp_digest_alg"/>
+ <name name="accept_callback"/>
+ <name name="fingerprint"/>
<desc>
- <p>Connects to an SSH server. No channel is started. This is done
- by calling
- <seealso marker="ssh_connection#session_channel/2">
- ssh_connection:session_channel/[2, 4]</seealso>.</p>
- <p>Options:</p>
<taglist>
- <tag><c><![CDATA[{inet, inet | inet6}]]></c></tag>
- <item>
- <p>IP version to use.</p>
- </item>
- <tag><marker id="opt_user_dir"></marker><c><![CDATA[{user_dir, string()}]]></c></tag>
- <item>
- <p>Sets the user directory, that is, the directory containing
- <c>ssh</c> configuration files for the user, such as
- <c><![CDATA[known_hosts]]></c>, <c><![CDATA[id_rsa,
- id_dsa]]></c>, and
- <c><![CDATA[authorized_key]]></c>. Defaults to the
- directory normally referred to as
- <c><![CDATA[~/.ssh]]></c>.</p>
- </item>
- <tag><c><![CDATA[{dsa_pass_phrase, string()}]]></c></tag>
- <item>
- <p>If the user DSA key is protected by a passphrase, it can be
- supplied with this option.
- </p>
- </item>
- <tag><c><![CDATA[{rsa_pass_phrase, string()}]]></c></tag>
+ <tag><c>silently_accept_hosts</c></tag>
<item>
- <p>If the user RSA key is protected by a passphrase, it can be
- supplied with this option.
- </p>
- </item>
- <tag>
- <c><![CDATA[{silently_accept_hosts, boolean()}]]></c> <br/>
- <c><![CDATA[{silently_accept_hosts, CallbackFun}]]></c> <br/>
- <c><![CDATA[{silently_accept_hosts, {HashAlgoSpec, CallbackFun} }]]></c> <br/>
- <br/>
- <c><![CDATA[HashAlgoSpec = crypto:digest_type() | [ crypto:digest_type() ] ]]></c><br/>
- <c><![CDATA[CallbackFun = fun(PeerName, FingerPrint) -> boolean()]]></c><br/>
- <c><![CDATA[PeerName = string()]]></c><br/>
- <c><![CDATA[FingerPrint = string() | [ string() ] ]]></c>
- </tag>
- <item>
- <p>This option guides the <c>connect</c> function how to act when the connected server presents a Host
+ <p>This option guides the <c>connect</c> function on how to act when the connected server presents a Host
Key that the client has not seen before. The default is to ask the user with a question on stdio of whether to
accept or reject the new Host Key.
- See also the option <seealso marker="#opt_user_dir"><c>user_dir</c></seealso>
- for the path to the file <c>known_hosts</c> where previously accepted Host Keys are recorded.
- </p>
+ See the option <seealso marker="#type-user_dir_common_option"><c>user_dir</c></seealso>
+ for specifying the path to the file <c>known_hosts</c> where previously accepted Host Keys are recorded.
+ See also the option
+ <seealso marker="#type-key_cb_common_option">key_cb</seealso>
+ for the general way to handle keys.
+ </p>
<p>The option can be given in three different forms as seen above:</p>
<list>
- <item>The value is a <c>boolean()</c>. The value <c>true</c> will make the client accept any unknown
- Host Key without any user interaction. The value <c>false</c> keeps the default behaviour of asking the
- the user on stdio.
+ <item>The value is a <c>boolean()</c>.
+ The value <c>true</c> will make the client accept any unknown Host Key without any user interaction.
+ The value <c>false</c> preserves the default behaviour of asking the user on stdio.
</item>
- <item>A <c>CallbackFun</c> will be called and the boolean return value <c>true</c> will make the client
- accept the Host Key. A return value of <c>false</c> will make the client to reject the Host Key and therefore
- also the connection will be closed. The arguments to the fun are:
+ <item>An <c>accept_callback()</c> will be called and the boolean return value <c>true</c>
+ will make the client
+ accept the Host Key. A return value of <c>false</c> will make the client to reject the Host Key and as a
+ result the connection will be closed. The arguments to the fun are:
<list type="bulleted">
<item><c>PeerName</c> - a string with the name or address of the remote host.</item>
<item><c>FingerPrint</c> - the fingerprint of the Host Key as
@@ -209,363 +244,335 @@
</item>
</list>
</item>
- <item>A tuple <c>{HashAlgoSpec, CallbackFun}</c>. The <c>HashAlgoSpec</c> specifies which hash algorithm
- shall be used to calculate the fingerprint used in the call of the <c>CallbackFun</c>. The <c>HashALgoSpec</c>
- is either an atom or a list of atoms as the first argument in
- <seealso marker="public_key:public_key#ssh_hostkey_fingerprint-2">public_key:ssh_hostkey_fingerprint/2</seealso>.
- If it is a list of hash algorithm names, the <c>FingerPrint</c> argument in the <c>CallbackFun</c> will be
- a list of fingerprints in the same order as the corresponding name in the <c>HashAlgoSpec</c> list.
+ <item>A tuple <c>{HashAlgoSpec, accept_callback}</c>. The <c>HashAlgoSpec</c>
+ specifies which hash algorithm
+ shall be used to calculate the fingerprint used in the call of the <c>accept_callback()</c>.
+ The <c>HashALgoSpec</c>
+ is either an atom or a list of atoms as the first argument in
+ <seealso marker="public_key:public_key#ssh_hostkey_fingerprint-2">public_key:ssh_hostkey_fingerprint/2</seealso>.
+ If it is a list of hash algorithm names, the <c>FingerPrint</c> argument in the
+ <c>accept_callback()</c> will be
+ a list of fingerprints in the same order as the corresponding name in the <c>HashAlgoSpec</c> list.
</item>
</list>
</item>
- <tag><c><![CDATA[{user_interaction, boolean()}]]></c></tag>
+
+ <tag><c>user_interaction</c></tag>
<item>
<p>If <c>false</c>, disables the client to connect to the server
if any user interaction is needed, such as accepting
the server to be added to the <c>known_hosts</c> file, or
- supplying a password. Defaults to <c>true</c>.
- Even if user interaction is allowed it can be
+ supplying a password.</p>
+ <p>Even if user interaction is allowed it can be
suppressed by other options, such as <c>silently_accept_hosts</c>
and <c>password</c>. However, those options are not always desirable
to use from a security point of view.</p>
+ <p>Defaults to <c>true</c>.</p>
</item>
- <tag><c><![CDATA[{disconnectfun, fun(Reason:term()) -> _}]]></c></tag>
+ <tag><c>save_accepted_host</c></tag>
<item>
- <p>Provides a fun to implement your own logging when a server disconnects the client.</p>
- </item>
-
- <tag><c><![CDATA[{unexpectedfun, fun(Message:term(), Peer) -> report | skip }]]></c></tag>
- <item>
- <p>Provides a fun to implement your own logging or other action when an unexpected message arrives.
- If the fun returns <c>report</c> the usual info report is issued but if <c>skip</c> is returned no
- report is generated.</p>
- <p><c>Peer</c> is in the format of <c>{Host,Port}</c>.</p>
- </item>
-
- <tag><c><![CDATA[{pref_public_key_algs, list()}]]></c></tag>
- <item>
- <p>List of user (client) public key algorithms to try to use.</p>
- <p>The default value is the <c>public_key</c> entry in
- <seealso marker="#default_algorithms/0">ssh:default_algorithms/0</seealso>.
+ <p>If <c>true</c>, the client saves an accepted host key to avoid the
+ accept question the next time the same host is connected. If the option
+ <seealso marker="#type-key_cb_common_option"><c>key_cb</c></seealso>
+ is not present, the key is saved in the file "known_hosts". See option
+ <seealso marker="#type-user_dir_common_option"><c>user_dir</c></seealso> for
+ the location of that file.
</p>
- <p>If there is no public key of a specified type available, the corresponding entry is ignored.
- Note that the available set is dependent on the underlying cryptolib and current user's public keys.
+ <p>If <c>false</c>, the key is not saved and the key will still be unknown
+ at the next access of the same host.
</p>
+ <p>Defaults to <c>true</c></p>
</item>
- <tag><c><![CDATA[{preferred_algorithms, algs_list()}]]></c></tag>
+ <tag><c>quiet_mode</c></tag>
<item>
- <p>List of algorithms to use in the algorithm negotiation. The default <c>algs_list()</c> can
- be obtained from <seealso marker="#default_algorithms/0">default_algorithms/0</seealso>.
- </p>
- <p>If an alg_entry() is missing in the algs_list(), the default value is used for that entry.</p>
- <p>Here is an example of this option:</p>
- <code>
-{preferred_algorithms,
- [{public_key,['ssh-rsa','ssh-dss']},
- {cipher,[{client2server,['aes128-ctr']},
- {server2client,['aes128-cbc','3des-cbc']}]},
- {mac,['hmac-sha2-256','hmac-sha1']},
- {compression,[none,zlib]}
- ]
-}
-</code>
- <p>The example specifies different algorithms in the two directions (client2server and server2client),
- for cipher but specifies the same algorithms for mac and compression in both directions.
- The kex (key exchange) is implicit but public_key is set explicitly.</p>
-
- <warning>
- <p>Changing the values can make a connection less secure. Do not change unless you
- know exactly what you are doing. If you do not understand the values then you
- are not supposed to change them.</p>
- </warning>
- </item>
-
- <tag><c><![CDATA[{dh_gex_limits,{Min=integer(),I=integer(),Max=integer()}}]]></c></tag>
- <item>
- <p>Sets the three diffie-hellman-group-exchange parameters that guides the connected server in choosing a group.
- See RFC 4419 for the function of thoose. The default value is <c>{1024, 6144, 8192}</c>.
- </p>
- </item>
-
- <tag><c><![CDATA[{connect_timeout, timeout()}]]></c></tag>
- <item>
- <p>Sets a time-out on the transport layer
- connection. For <c>gen_tcp</c> the time is in milli-seconds and the default value is
- <c>infinity</c>.</p>
+ <p>If <c>true</c>, the client does not print anything on authorization.</p>
+ <p>Defaults to <c>false</c></p>
</item>
+ </taglist>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{auth_methods, string()}]]></c></tag>
- <item>
- <p>Comma-separated string that determines which
- authentication methods that the client shall support and
- in which order they are tried. Defaults to
- <c><![CDATA["publickey,keyboard-interactive,password"]]></c></p>
- </item>
-
- <tag><c><![CDATA[{user, string()}]]></c></tag>
+ <datatype>
+ <name name="authentication_client_options"/>
+ <desc>
+ <taglist>
+ <tag><c>user</c></tag>
<item>
- <p>Provides a username. If this option is not given, <c>ssh</c>
+ <p>Provides the username. If this option is not given, <c>ssh</c>
reads from the environment (<c><![CDATA[LOGNAME]]></c> or
<c><![CDATA[USER]]></c> on UNIX,
<c><![CDATA[USERNAME]]></c> on Windows).</p>
</item>
- <tag><c><![CDATA[{password, string()}]]></c></tag>
+ <tag><c>password</c></tag>
<item>
<p>Provides a password for password authentication.
If this option is not given, the user is asked for a
password, if the password authentication method is
attempted.</p>
</item>
-
- <!--tag><c><![CDATA[{send_ext_info, boolean()}]]></c></tag>
- <item>
- <p>Send a list of extensions to the server if the server has asked for it. See
- <url href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-ext-info">Draft-ietf-curdle-ssh-ext-info (work in progress)</url> for details.
- </p>
- <p>Currently the client do not react on any extensions.
- </p>
- <p>Default value is <c>true</c>.
- </p>
- </item-->
-
- <tag><c><![CDATA[{recv_ext_info, boolean()}]]></c></tag>
- <item>
- <p>Tell the server that the client accepts extension negotiation. See
- <url href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-ext-info">Draft-ietf-curdle-ssh-ext-info (work in progress)</url> for details.
- </p>
- <p>Currently implemented extension is <c>server-sig-algs</c> which is the list of the server's preferred
- user's public key algorithms.
- </p>
- <p>Default value is <c>true</c>.
- </p>
- </item>
-
- <tag><c><![CDATA[{key_cb, key_cb()}]]></c></tag>
- <item>
- <p>Module implementing the behaviour <seealso
- marker="ssh_client_key_api">ssh_client_key_api</seealso>. Can be used to
- customize the handling of public keys. If callback options are provided
- along with the module name, they are made available to the callback
- module via the options passed to it under the key 'key_cb_private'.
- </p>
- </item>
-
- <tag><c><![CDATA[{quiet_mode, atom() = boolean()}]]></c></tag>
- <item>
- <p>If <c>true</c>, the client does not print anything on authorization.</p>
- </item>
-
- <tag><c><![CDATA[{id_string, random | string()}]]></c></tag>
- <item>
- <p>The string that the client presents to a connected server initially. The default value is "Erlang/VSN" where VSN is the ssh application version number.
- </p>
- <p>The value <c>random</c> will cause a random string to be created at each connection attempt. This is to make it a bit more difficult for a malicious peer to find the ssh software brand and version.
- </p>
- </item>
-
- <tag><c><![CDATA[{fd, file_descriptor()}]]></c></tag>
- <item>
- <p>Allows an existing file descriptor to be used
- (by passing it on to the transport protocol).</p></item>
- <tag><c><![CDATA[{rekey_limit, integer()}]]></c></tag>
- <item>
- <p>Provides, in bytes, when rekeying is to be initiated.
- Defaults to once per each GB and once per hour.</p>
- </item>
- <tag><c><![CDATA[{idle_time, integer()}]]></c></tag>
- <item>
- <p>Sets a time-out on a connection when no channels are active.
- Defaults to <c>infinity</c>.</p></item>
- <tag><c><![CDATA[{ssh_msg_debug_fun, fun(ConnectionRef::ssh_connection_ref(), AlwaysDisplay::boolean(), Msg::binary(), LanguageTag::binary()) -> _}]]></c></tag>
- <item>
- <p>Provide a fun to implement your own logging of the SSH message SSH_MSG_DEBUG. The last three parameters are from the message, see RFC4253, section 11.3. The <c>ConnectionRef</c> is the reference to the connection on which the message arrived. The return value from the fun is not checked.</p>
- <p>The default behaviour is ignore the message.
- To get a printout for each message with <c>AlwaysDisplay = true</c>, use for example <c>{ssh_msg_debug_fun, fun(_,true,M,_)-> io:format("DEBUG: ~p~n", [M]) end}</c></p>
- </item>
-
</taglist>
- </desc>
- </func>
+ </desc>
+ </datatype>
- <func>
- <name>connection_info(ConnectionRef, [Option]) ->[{Option,
- Value}]</name>
- <fsummary>Retrieves information about a connection.</fsummary>
- <type>
- <v>Option = client_version | server_version | user | peer | sockname </v>
- <v>Value = [option_value()] </v>
- <v>option_value() = {{Major::integer(), Minor::integer()}, VersionString::string()} |
- User::string() | Peer::{inet:hostname(), {inet::ip_adress(), inet::port_number()}} |
- Sockname::{inet::ip_adress(), inet::port_number()}</v>
- </type>
+ <datatype>
+ <name name="diffie_hellman_group_exchange_client_option"/>
<desc>
- <p>Retrieves information about a connection.</p>
+ <p>Sets the three diffie-hellman-group-exchange parameters that guides the connected server in choosing a group.
+ See
+ <url href="https://tools.ietf.org/html/rfc4419">RFC 4419</url>
+ for the details. The default value is <c>{1024, 6144, 8192}</c>.
+ </p>
</desc>
- </func>
-
- <func>
- <name>daemon(Port) -> </name>
- <name>daemon(Port, Options) -> </name>
- <name>daemon(HostAddress, Port, Options) -> </name>
- <name>daemon(TcpSocket) -> </name>
- <name>daemon(TcpSocket, Options) -> {ok, ssh_daemon_ref()} | {error, atom()}</name>
- <fsummary>Starts a server listening for SSH connections
- on the given port.</fsummary>
- <type>
- <v>Port = integer()</v>
- <v>HostAddress = ip_address() | any | loopback</v>
- <v>Options = [{Option, Value}]</v>
- <v>Option = atom()</v>
- <v>Value = term()</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>
- </type>
- <desc>
- <p>Starts a server listening for SSH connections on the given
- port. If the <c>Port</c> is 0, a random free port is selected. See
- <seealso marker="#daemon_info/1">daemon_info/1</seealso> about how to find the selected port number.</p>
+ </datatype>
- <p>Please note that by historical reasons both the <c>HostAddress</c> argument and the inet socket option
- <c>ip</c> set the listening address. This is a source of possible inconsistent settings.</p>
+ <datatype>
+ <name name="connect_timeout_client_option"/>
+ <desc>
+ <p>Sets a timeout on the transport layer connect time.
+ For <seealso marker="kernel:gen_tcp"><c>gen_tcp</c></seealso> the time is in milli-seconds and the default
+ value is <c>infinity</c>.
+ </p>
+ <p>See the parameter <c>Timeout</c> in <seealso marker="#connect/4">connect/4</seealso> for
+ a timeout of the negotiation phase.
+ </p>
+ </desc>
+ </datatype>
- <p>The rules for handling the two address passing options are:</p>
- <list>
- <item>if <c>HostAddress</c> is an IP-address, that IP-address is the listening address.
- An 'ip'-option will be discarded if present.</item>
+ <datatype>
+ <name name="recv_ext_info_client_option"/>
+ <desc>
+ <p>Make the client tell the server that the client accepts extension negotiation, that is,
+ include <c>ext-info-c</c> in the kexinit message sent. See
+ <url href="https://tools.ietf.org/html/rfc8308">RFC 8308</url>
+ for details and <seealso marker="SSH_app#supported-ext-info">ssh(6)</seealso>
+ for a list of currently implemented extensions.
+ </p>
+ <p>
+ Default value is <c>true</c> which is compatible with other implementations not supporting ext-info.
+ </p>
+ </desc>
+ </datatype>
- <item>if <c>HostAddress</c> is <c>loopback</c>, the listening address
- is <c>loopback</c> and an loopback address will be choosen by the underlying layers.
- An 'ip'-option will be discarded if present.</item>
+ <!--................................................................-->
+ <datatype_title>Daemon Options (Server Options)</datatype_title>
- <item>if <c>HostAddress</c> is <c>any</c> and no 'ip'-option is present, the listening address is
- <c>any</c> and the socket will listen to all addresses</item>
+ <datatype>
+ <name name="daemon_options"/>
+ <name name="daemon_option"/>
+ <desc>
+ <p>Options for <seealso marker="#daemon/1">daemons</seealso>.
+ The individual options are further explained below or by following the hyperlinks.
+ </p>
+ </desc>
+ </datatype>
- <item>if <c>HostAddress</c> is <c>any</c> and an 'ip'-option is present, the listening address is
- set to the value of the 'ip'-option</item>
- </list>
+
+ <datatype>
+ <name name="subsystem_daemon_option"/>
+ <name name="subsystem_spec"/>
+ <desc>
+ <p>Defines a subsystem in the daemon.</p>
+ <p>The <c>subsystem_name</c> is the name that a client requests to start with for example
+ <seealso marker="ssh_connection#subsystem/4">ssh_connection:subsystem/4</seealso>.
+ </p>
+ <p>The <c>channel_callback</c> is the module that implements the
+ <seealso marker="ssh_server_channel">ssh_server_channel</seealso> (replaces ssh_daemon_channel)
+ behaviour in the daemon. See the section
+ <seealso marker="using_ssh#usersguide_creating_a_subsystem">Creating a Subsystem</seealso>
+ in the User's Guide for more information and an example.
+ </p>
+ <p>If the subsystems option is not present, the value of <c>ssh_sftpd:subsystem_spec([])</c> is used.
+ This enables the sftp subsystem by default.
+ The option can be set to the empty list if you do not want the daemon to run any subsystems.</p>
+ </desc>
+ </datatype>
- <p>Options:</p>
- <taglist>
- <tag><c><![CDATA[{inet, inet | inet6}]]></c></tag>
- <item><p>IP version to use when the host address is specified as <c>any</c>.</p></item>
- <tag><c><![CDATA[{subsystems, [subsystem_spec()]}]]></c></tag>
+ <datatype>
+ <name name="shell_daemon_option"/>
+ <name name="'shell_fun/1'"/>
+ <name name="'shell_fun/2'"/>
+ <desc>
+ <p>Defines the read-eval-print loop used in a daemon when a shell is requested by the client.
+ The default is to use the Erlang shell: <c><![CDATA[{shell, start, []}]]></c>
+ </p>
+ <p>See the option <seealso marker="#type-exec_daemon_option"><c>exec</c></seealso>
+ for a description of how the daemon execute exec-requests depending on
+ the shell- and exec-options.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="exec_daemon_option"/>
+ <name name="'exec_fun/1'"/>
+ <name name="'exec_fun/2'"/>
+ <name name="'exec_fun/3'"/>
+ <name name="exec_result"/>
+ <desc>
+ <p>This option changes how the daemon execute exec-requests from clients. The term in the return value
+ is formatted to a string if it is a non-string type. No trailing newline is added in the ok-case but in the
+ error case.</p>
+ <p>Error texts are returned on channel-type 1 which usually is piped to <c>stderr</c> on e.g Linux systems.
+ Texts from a successful execution will in similar manner be piped to <c>stdout</c>. The exit-status code
+ is set to 0 for success and -1 for errors. The exact results presented on the client side depends on the
+ client and the client's operating system.
+ </p>
+ <p>The option cooperates with the daemon-option <seealso marker="#type-shell_daemon_option"><c>shell</c></seealso>
+ in the following way:</p>
+ <taglist>
+ <tag>1. If the exec-option is present (the shell-option may or may not be present):</tag>
<item>
- <p>Provides specifications for handling of subsystems. The
- "sftp" subsystem specification is retrieved by calling
- <c>ssh_sftpd:subsystem_spec/1</c>. If the subsystems option is
- not present, the value of
- <c>[ssh_sftpd:subsystem_spec([])]</c> is used.
- The option can be set to the empty list if
- you do not want the daemon to run any subsystems.</p>
+ <p>The exec-option fun is called with the same number of parameters as the arity of the fun,
+ and the result is returned to the client.
+ </p>
</item>
- <tag><c><![CDATA[{shell, {Module, Function, Args} |
- fun(string() = User) - > pid() | fun(string() = User,
- ip_address() = PeerAddr) -> pid()}]]></c></tag>
+
+ <tag>2. If the exec-option is absent, but a shell-option is present with the default Erlang shell:</tag>
<item>
- <p>Defines the read-eval-print loop used when a shell is
- requested by the client. The default is to use the Erlang shell:
- <c><![CDATA[{shell, start, []}]]></c></p>
+ <p>The default Erlang evaluator is used and the result is returned to the client.</p>
</item>
- <tag><c><![CDATA[{ssh_cli, {channel_callback(),
- channel_init_args()} | no_cli}]]></c></tag>
+
+ <tag>3. If the exec-option is absent, but a shell-option is present that is not the default Erlang shell:</tag>
<item>
- <p>Provides your own CLI implementation, that is, a channel callback
- module that implements a shell and command execution. The shell
- read-eval-print loop can be customized, using the
- option <c>shell</c>. This means less work than implementing
- an own CLI channel. If set to <c>no_cli</c>, the CLI channels
- are disabled and only subsystem channels are allowed.</p>
+ <p>The exec-request is not evaluated and an error message is returned to the client.</p>
</item>
- <tag><c><![CDATA[{user_dir, string()}]]></c></tag>
+
+ <tag>4. If neither the exec-option nor the shell-option is present:</tag>
<item>
- <p>Sets the user directory. That is, the directory containing
- <c>ssh</c> configuration files for the user, such as
- <c><![CDATA[known_hosts]]></c>, <c><![CDATA[id_rsa,
- id_dsa]]></c>, and
- <c><![CDATA[authorized_key]]></c>. Defaults to the
- directory normally referred to as
- <c><![CDATA[~/.ssh]]></c>.</p>
+ <p>The default Erlang evaluator is used and the result is returned to the client.</p>
</item>
- <tag><c><![CDATA[{system_dir, string()}]]></c></tag>
+ </taglist>
+ <p>If a custom CLI is installed (see the option <seealso marker="#type-ssh_cli_daemon_option"><c>ssh_cli</c></seealso>)
+ the rules above are replaced by thoose implied by the custom CLI.
+ </p>
+ <note>
+ <p>The exec-option has existed for a long time but has not previously been documented. The old
+ definition and behaviour are retained but obey the rules 1-4 above if conflicting.
+ The old and undocumented style should not be used in new programs.</p>
+ </note>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="ssh_cli_daemon_option"/>
+ <desc>
+ <p>Provides your own CLI implementation in a daemon.</p>
+ <p>It is a channel callback module that implements a shell
+ and command execution. The shell's read-eval-print loop can be customized, using the
+ option <seealso marker="#type-shell_daemon_option"><c>shell</c></seealso>. This means less work than implementing
+ an own CLI channel. If <c>ssh_cli</c> is set to <c>no_cli</c>, the CLI channels
+ like <seealso marker="#type-shell_daemon_option"><c>shell</c></seealso>
+ and <seealso marker="#type-exec_daemon_option"><c>exec</c></seealso>
+ are disabled and only subsystem channels are allowed.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="authentication_daemon_options"/>
+ <name name="prompt_texts"/>
+ <name name="kb_int_tuple"/>
+ <name name="kb_int_fun_3"/>
+ <name name="pwdfun_2"/>
+ <name name="pwdfun_4"/>
+ <desc>
+ <taglist>
+ <tag><marker id="type-system_dir_daemon_option"/><c>system_dir</c></tag>
<item>
<p>Sets the system directory, containing the host key files
that identify the host keys for <c>ssh</c>. Defaults to
- <c><![CDATA[/etc/ssh]]></c>. For security reasons,
- this directory is normally accessible only to the root user.</p>
+ <c>/etc/ssh</c>.</p>
+ <p>For security reasons, this directory is normally accessible only to the root user.</p>
+ <p>See also the option
+ <seealso marker="#type-key_cb_common_option">key_cb</seealso>
+ for the general way to handle keys.
+ </p>
</item>
- <tag><c><![CDATA[{auth_methods, string()}]]></c></tag>
+ <tag><c>auth_method_kb_interactive_data</c></tag>
<item>
- <p>Comma-separated string that determines which
- authentication methods that the server is to support and
- in what order they are tried. Defaults to
- <c><![CDATA["publickey,keyboard-interactive,password"]]></c></p>
- <p>Note that the client is free to use any order and to exclude methods.</p>
- </item>
-
- <tag><c><![CDATA[{auth_method_kb_interactive_data, PromptTexts}]]></c>
- <br/><c>where:</c>
- <br/><c>PromptTexts = kb_int_tuple() | fun(Peer::{IP::tuple(),Port::integer()}, User::string(), Service::string()) -> kb_int_tuple()</c>
- <br/><c>kb_int_tuple() = {Name::string(), Instruction::string(), Prompt::string(), Echo::boolean()}</c>
- </tag>
- <item>
- <p>Sets the text strings that the daemon sends to the client for presentation to the user when using <c>keyboar-interactive</c> authentication. If the fun/3 is used, it is called when the actual authentication occurs and may therefore return dynamic data like time, remote ip etc.</p>
+ <p>Sets the text strings that the daemon sends to the client for presentation to the user when
+ using <c>keyboard-interactive</c> authentication.</p>
+ <p>If the fun/3 is used, it is called when the actual authentication occurs and may therefore
+ return dynamic data like time, remote ip etc.</p>
<p>The parameter <c>Echo</c> guides the client about need to hide the password.</p>
<p>The default value is:
- <c>{auth_method_kb_interactive_data, {"SSH server", "Enter password for \""++User++"\"", "password: ", false}></c></p>
+ <c>{auth_method_kb_interactive_data, {"SSH server", "Enter password for \""++User++"\"", "password: ", false}></c>
+ </p>
</item>
- <tag><c><![CDATA[{user_passwords, [{string() = User,
- string() = Password}]}]]></c></tag>
+ <tag><c>user_passwords</c></tag>
<item>
- <p>Provides passwords for password authentication. The passwords
- are used when someone tries to connect to the server and
- public key user-authentication fails. The option provides
+ <p>Provides passwords for password authentication. The passwords are used when someone tries
+ to connect to the server and public key user-authentication fails. The option provides
a list of valid usernames and the corresponding passwords.
</p>
</item>
- <tag><c><![CDATA[{password, string()}]]></c></tag>
+
+ <tag><c>password</c></tag>
<item>
- <p>Provides a global password that authenticates any
- user. From a security perspective this option makes
- the server very vulnerable.</p>
+ <p>Provides a global password that authenticates any user.</p>
+ <warning>
+ <p>Intended to facilitate testing.</p>
+ <p>From a security perspective this option makes the server very vulnerable.</p>
+ </warning>
</item>
- <tag><c><![CDATA[{preferred_algorithms, algs_list()}]]></c></tag>
+ <tag><c>pwdfun</c> with <c>pwdfun_4()</c></tag>
<item>
- <p>List of algorithms to use in the algorithm negotiation. The default <c>algs_list()</c> can
- be obtained from <seealso marker="#default_algorithms/0">default_algorithms/0</seealso>.
+ <p>Provides a function for password validation. This could used for calling an external system or handeling
+ passwords stored as hash values.
</p>
- <p>If an alg_entry() is missing in the algs_list(), the default value is used for that entry.</p>
- <p>Here is an example of this option:</p>
- <code>
-{preferred_algorithms,
- [{public_key,['ssh-rsa','ssh-dss']},
- {cipher,[{client2server,['aes128-ctr']},
- {server2client,['aes128-cbc','3des-cbc']}]},
- {mac,['hmac-sha2-256','hmac-sha1']},
- {compression,[none,zlib]}
- ]
-}
-</code>
- <p>The example specifies different algorithms in the two directions (client2server and server2client),
- for cipher but specifies the same algorithms for mac and compression in both directions.
- The kex (key exchange) is implicit but public_key is set explicitly.</p>
+ <p>This fun can also be used to make delays in authentication tries for example by calling
+ <seealso marker="stdlib:timer#sleep/1">timer:sleep/1</seealso>.</p>
+ <p>To facilitate for instance counting of failed tries,
+ the <c>State</c> variable could be used. This state is per connection only. The first time the pwdfun
+ is called for a connection, the <c>State</c> variable has the value <c>undefined</c>.
+ </p>
+
+ <p>The fun should return:
+ </p>
+ <list type="bulleted">
+ <item><c>true</c> if the user and password is valid</item>
+ <item><c>false</c> if the user or password is invalid</item>
+ <item><c>disconnect</c> if a SSH_MSG_DISCONNECT message should be sent immediately. It will
+ be followed by a close of the underlying tcp connection.</item>
+ <item><c>{true, NewState:any()}</c> if the user and password is valid</item>
+ <item><c>{false, NewState:any()}</c> if the user or password is invalid</item>
+ </list>
- <warning>
- <p>Changing the values can make a connection less secure. Do not change unless you
- know exactly what you are doing. If you do not understand the values then you
- are not supposed to change them.</p>
- </warning>
+ <p>A third usage is to block login attempts from a missbehaving peer. The <c>State</c> described above
+ can be used for this. The return value <c>disconnect</c> is useful for this.</p>
</item>
- <tag><c><![CDATA[{dh_gex_groups, [{Size=integer(),G=integer(),P=integer()}] | {file,filename()} {ssh_moduli_file,filename()} }]]></c></tag>
+ <tag><c>pwdfun</c> with <c>pwdfun_2()</c></tag>
+ <item>
+ <p>Provides a function for password validation. This function is called with user and password
+ as strings, and returns:</p>
+ <list type="bulleted">
+ <item><c>true</c> if the user and password is valid</item>
+ <item><c>false</c> if the user or password is invalid</item>
+ </list>
+ <p>This variant is kept for compatibility.</p>
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="diffie_hellman_group_exchange_daemon_option"/>
+ <name name="explicit_group"/>
+ <name name="explicit_group_file"/>
+ <name name="ssh_moduli_file"/>
+ <desc>
+ <taglist>
+ <tag><c>dh_gex_groups</c></tag>
<item>
<p>Defines the groups the server may choose among when diffie-hellman-group-exchange is negotiated.
- See RFC 4419 for details. The three variants of this option are:
+ See
+ <url href="https://tools.ietf.org/html/rfc4419">RFC 4419</url>
+ for details. The three variants of this option are:
</p>
<taglist>
<tag><c>{Size=integer(),G=integer(),P=integer()}</c></tag>
@@ -587,7 +594,7 @@
</p>
</item>
- <tag><c><![CDATA[{dh_gex_limits,{Min=integer(),Max=integer()}}]]></c></tag>
+ <tag><c>dh_gex_limits</c></tag>
<item>
<p>Limits what a client can ask for in diffie-hellman-group-exchange.
The limits will be
@@ -598,57 +605,29 @@
</p>
<p>If <c>MaxUsed &lt; MinUsed</c> in a key exchange, it will fail with a disconnect.
</p>
- <p>See RFC 4419 for the function of the Max and Min values.</p>
- </item>
-
- <tag><c><![CDATA[{pwdfun, fun(User::string(), Password::string(), PeerAddress::{ip_adress(),port_number()}, State::any()) -> boolean() | disconnect | {boolean(),any()} }]]></c></tag>
- <item>
- <p>Provides a function for password validation. This could used for calling an external system or if
- passwords should be stored as a hash. The fun returns:
- </p>
- <list type="bulleted">
- <item><c>true</c> if the user and password is valid and</item>
- <item><c>false</c> otherwise.</item>
- </list>
- <p>This fun can also be used to make delays in authentication tries for example by calling
- <seealso marker="stdlib:timer#sleep/1">timer:sleep/1</seealso>. To facilitate counting of failed tries
- the <c>State</c> variable could be used. This state is per connection only. The first time the pwdfun
- is called for a connection, the <c>State</c> variable has the value <c>undefined</c>.
- The pwdfun can return - in addition to the values above - a new state
- as:
- </p>
- <list type="bulleted">
- <item><c>{true, NewState:any()}</c> if the user and password is valid or</item>
- <item><c>{false, NewState:any()}</c> if the user or password is invalid</item>
- </list>
- <p>A third usage is to block login attempts from a missbehaving peer. The <c>State</c> described above
- can be used for this. In addition to the responses above, the following return value is introduced:
- </p>
- <list type="bulleted">
- <item><c>disconnect</c> if the connection should be closed immediately after sending a SSH_MSG_DISCONNECT
- message.</item>
- </list>
- </item>
-
- <tag><c><![CDATA[{pwdfun, fun(User::string(), Password::string()) -> boolean()}]]></c></tag>
- <item>
- <p>Provides a function for password validation. This function is called
- with user and password as strings, and returns
- <c><![CDATA[true]]></c> if the password is valid and
- <c><![CDATA[false]]></c> otherwise.</p>
- <p>This option (<c>{pwdfun,fun/2}</c>) is the same as a subset of the previous
- (<c>{pwdfun,fun/4}</c>). It is kept for compatibility.</p>
+ <p>See
+ <url href="https://tools.ietf.org/html/rfc4419">RFC 4419</url>
+ for the function of the Max and Min values.</p>
</item>
+ </taglist>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{negotiation_timeout, integer()}]]></c></tag>
- <item>
- <p>Maximum time in milliseconds for the authentication negotiation.
- Defaults to 120000 (2 minutes). If the client fails to log in within this time,
- the connection is closed.
- </p>
- </item>
+ <datatype>
+ <name name="negotiation_timeout_daemon_option"/>
+ <desc>
+ <p>Maximum time in milliseconds for the authentication negotiation.
+ Defaults to 120000 ms (2 minutes). If the client fails to log in within this time,
+ the connection is closed.
+ </p>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{max_sessions, pos_integer()}]]></c></tag>
+ <datatype>
+ <name name="hardening_daemon_options"/>
+ <desc>
+ <taglist>
+ <tag><c>max_sessions</c></tag>
<item>
<p>The maximum number of simultaneous sessions that are accepted at any time
for this daemon. This includes sessions that are being authorized.
@@ -668,7 +647,7 @@
</p>
</item>
- <tag><c><![CDATA[{max_channels, pos_integer()}]]></c></tag>
+ <tag><c>max_channels</c></tag>
<item>
<p>The maximum number of channels with active remote subsystem that are accepted for
each connection to this daemon</p>
@@ -676,8 +655,7 @@
</p>
</item>
-
- <tag><c><![CDATA[{parallel_login, boolean()}]]></c></tag>
+ <tag><c>parallel_login</c></tag>
<item>
<p>If set to false (the default value), only one login is handled at a time.
If set to true, an unlimited number of login attempts are allowed simultaneously.
@@ -694,171 +672,557 @@
</warning>
</item>
- <tag><c><![CDATA[{minimal_remote_max_packet_size, non_negative_integer()}]]></c></tag>
+ <tag><c>minimal_remote_max_packet_size</c></tag>
<item>
- <p>The least maximum packet size that the daemon will accept in channel open requests from the client. The default value is 0.
+ <p>The least maximum packet size that the daemon will accept in channel open requests from the client.
+ The default value is 0.
</p>
</item>
+
+ </taglist>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="callbacks_daemon_options"/>
+ <desc>
+ <taglist>
+ <tag><c>connectfun</c></tag>
+ <item>
+ <p>Provides a fun to implement your own logging when a user authenticates to the server.</p>
+ </item>
- <tag><c><![CDATA[{id_string, random | string()}]]></c></tag>
+ <tag><c>failfun</c></tag>
<item>
- <p>The string the daemon will present to a connecting peer initially. The default value is "Erlang/VSN" where VSN is the ssh application version number.
- </p>
- <p>The value <c>random</c> will cause a random string to be created at each connection attempt. This is to make it a bit more difficult for a malicious peer to find the ssh software brand and version.
- </p>
+ <p>Provides a fun to implement your own logging when a user fails to authenticate.</p>
</item>
+ </taglist>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{send_ext_info, boolean()}]]></c></tag>
- <item>
- <p>Send a list of extensions to the client if the client has asked for it. See
- <url href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-ext-info">Draft-ietf-curdle-ssh-ext-info (work in progress)</url> for details.
- </p>
- <p>Currently implemented extension is sending <c>server-sig-algs</c> which is the list of the server's preferred
- user's public key algorithms.
- </p>
- <p>Default value is <c>true</c>.
- </p>
- </item>
+ <datatype>
+ <name name="send_ext_info_daemon_option"/>
+ <desc>
+ <p>Make the server (daemon) tell the client that the server accepts extension negotiation, that is,
+ include <c>ext-info-s</c> in the kexinit message sent. See
+ <url href="https://tools.ietf.org/html/rfc8308">RFC 8308</url>
+ for details and <seealso marker="SSH_app#supported-ext-info">ssh(6)</seealso>
+ for a list of currently implemented extensions.
+ </p>
+ <p>Default value is <c>true</c> which is compatible with other implementations not supporting ext-info.
+ </p>
+ </desc>
+ </datatype>
- <!--tag><c><![CDATA[{recv_ext_info, boolean()}]]></c></tag>
- <item>
- <p>Tell the client that the server accepts extension negotiation. See
- <url href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-ext-info">Draft-ietf-curdle-ssh-ext-info (work in progress)</url> for details.
- </p>
- <p>Default value is <c>true</c>.
- </p>
- </item-->
- <tag><c><![CDATA[{key_cb, key_cb()}]]></c></tag>
+ <!--................................................................-->
+ <datatype_title>Options common to clients and daemons</datatype_title>
+ <datatype>
+ <name name="common_options"/>
+ <name name="common_option"/>
+ <desc><p>The options above can be used both in clients and in daemons (servers). They are further explained below.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="user_dir_common_option"/>
+ <desc>
+ <p>Sets the user directory. That is, the directory containing <c>ssh</c> configuration
+ files for the user, such as
+ <c>known_hosts</c>, <c>id_rsa</c>, <c>id_dsa</c>>, <c>id_ecdsa</c> and <c>authorized_key</c>.
+ Defaults to the directory normally referred to as <c>~/.ssh</c>.
+ </p>
+ <p>See also the option
+ <seealso marker="#type-key_cb_common_option">key_cb</seealso>
+ for the general way to handle keys.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="profile_common_option"/>
+ <desc>
+ <p>Used together with <c>ip-address</c> and <c>port</c> to
+ uniquely identify a ssh daemon. This can be useful in a
+ virtualized environment, where there can be more that one
+ server that has the same <c>ip-address</c> and
+ <c>port</c>. If this property is not explicitly set, it is
+ assumed that the the <c>ip-address</c> and <c>port</c>
+ uniquely identifies the SSH daemon.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="max_idle_time_common_option"/>
+ <desc>
+ <p>Sets a time-out on a connection when no channels are active. Defaults to <c>infinity</c>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="rekey_limit_common_option"/>
+ <name name="limit_bytes"/>
+ <name name="limit_time"/>
+ <desc>
+ <p>Sets the limit when rekeying is to be initiated. Both the max time and max amount of data
+ could be configured:
+ </p>
+ <list>
+ <item><c>{Minutes, Bytes}</c> initiate rekeying when any of the limits are reached.</item>
+ <item><c>Bytes</c> initiate rekeying when <c>Bytes</c> number of bytes are transferred,
+ or at latest after one hour.</item>
+ </list>
+ <p>When a rekeying is done, both the timer and the byte counter are restarted.
+ Defaults to one hour and one GByte.</p>
+ <p>If <c>Minutes</c> is set to <c>infinity</c>, no rekeying will ever occur due to that max time has passed.
+ Setting <c>Bytes</c> to <c>infinity</c> will inhibit rekeying after a certain amount of data has been transferred.
+ If the option value is set to <c>{infinity, infinity}</c>, no rekeying will be initiated. Note that rekeying initiated
+ by the peer will still be performed.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="key_cb_common_option"/>
+ <desc>
+ <p>Module implementing the behaviour
+ <seealso marker="ssh_client_key_api">ssh_client_key_api</seealso> and/or
+ <seealso marker="ssh_server_key_api">ssh_server_key_api</seealso>.
+ Can be used to
+ customize the handling of public keys. If callback options are provided
+ along with the module name, they are made available to the callback
+ module via the options passed to it under the key 'key_cb_private'.
+ </p>
+ <p>The <c>Opts</c> defaults to <c>[]</c> when only the <c>Module</c> is specified.
+ </p>
+ <p>The default value of this option is <c>{ssh_file, []}</c>.
+ </p>
+ <p>A call to the call-back function <c>F</c> will be</p>
+ <code>
+ Module:F(..., [{key_cb_private,Opts}|UserOptions])
+ </code>
+ <p>where <c>...</c> are arguments to <c>F</c> as in
+ <seealso marker="ssh_client_key_api">ssh_client_key_api</seealso> and/or
+ <seealso marker="ssh_server_key_api">ssh_server_key_api</seealso>.
+ The <c>UserOptions</c> are the options given to <c>ssh:connect</c>, <c>ssh:shell</c> or <c>ssh:daemon</c>.
+ </p>
+
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="disconnectfun_common_option"/>
+ <desc>
+ <p>Provides a fun to implement your own logging when the peer disconnects.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="unexpectedfun_common_option"/>
+ <desc>
+ <p>Provides a fun to implement your own logging or other action when an unexpected message arrives.
+ If the fun returns <c>report</c> the usual info report is issued but if <c>skip</c> is returned no
+ report is generated.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="ssh_msg_debug_fun_common_option"/>
+ <desc>
+ <p>Provide a fun to implement your own logging of the SSH message SSH_MSG_DEBUG.
+ The last three parameters are from the message, see
+ <url href="https://tools.ietf.org/html/rfc4253#section-11.3">RFC 4253, section 11.3</url>.
+ The <seealso marker="#type-connection_ref"><c>connection_ref()</c></seealso> is the reference
+ to the connection on which the message arrived.
+ The return value from the fun is not checked.
+ </p>
+ <p>The default behaviour is ignore the message.
+ To get a printout for each message with <c>AlwaysDisplay = true</c>,
+ use for example <c>{ssh_msg_debug_fun, fun(_,true,M,_)-> io:format("DEBUG: ~p~n", [M]) end}</c></p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="id_string_common_option"/>
+ <desc>
+ <p>The string the daemon will present to a connecting peer initially.
+ The default value is "Erlang/VSN" where VSN is the ssh application version number.
+ </p>
+ <p>The value <c>random</c> will cause a random string to be created at each connection attempt.
+ This is to make it a bit more difficult for a malicious peer to find the ssh software brand and version.
+ </p>
+ <p>The value <c>{random, Nmin, Nmax}</c> will make a random string with at least <c>Nmin</c> characters and
+ at most <c>Nmax</c> characters.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="preferred_algorithms_common_option"/>
+ <name name="algs_list"/>
+ <name name="alg_entry"/>
+ <name name="kex_alg"/>
+ <name name="pubkey_alg"/>
+ <name name="cipher_alg"/>
+ <name name="mac_alg"/>
+ <name name="compression_alg"/>
+ <name name="double_algs"/>
+
+ <desc>
+ <p>List of algorithms to use in the algorithm negotiation. The default <c>algs_list()</c> can
+ be obtained from <seealso marker="#default_algorithms/0">default_algorithms/0</seealso>.
+ </p>
+ <p>If an alg_entry() is missing in the algs_list(), the default value is used for that entry.</p>
+ <p>Here is an example of this option:</p>
+ <code>
+ {preferred_algorithms,
+ [{public_key,['ssh-rsa','ssh-dss']},
+ {cipher,[{client2server,['aes128-ctr']},
+ {server2client,['aes128-cbc','3des-cbc']}]},
+ {mac,['hmac-sha2-256','hmac-sha1']},
+ {compression,[none,zlib]}
+ ]
+ }
+ </code>
+ <p>The example specifies different algorithms in the two directions (client2server and server2client),
+ for cipher but specifies the same algorithms for mac and compression in both directions.
+ The kex (key exchange) is implicit but public_key is set explicitly.</p>
+
+ <p>For background and more examples see the <seealso marker="configure_algos#introduction">User's Guide</seealso>.</p>
+
+ <p>If an algorithm name occurs more than once in a list, the behaviour is undefined. The tags in the property lists
+ are also assumed to occur at most one time.
+ </p>
+
+ <warning>
+ <p>Changing the values can make a connection less secure. Do not change unless you
+ know exactly what you are doing. If you do not understand the values then you
+ are not supposed to change them.</p>
+ </warning>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="modify_algorithms_common_option"/>
+ <name name="modify_algs_list"/>
+ <desc>
+ <p>Modifies the list of algorithms to use in the algorithm negotiation. The modifications are
+ applied after the option <c>preferred_algorithms</c> (if existing) is applied.</p>
+ <p>The algoritm for modifications works like this:</p>
+ <list>
<item>
- <p>Module implementing the behaviour <seealso
- marker="ssh_server_key_api">ssh_server_key_api</seealso>. Can be used to
- customize the handling of public keys. If callback options are provided
- along with the module name, they are made available to the callback
- module via the options passed to it under the key 'key_cb_private'.
+ <p>Input is the <c>modify_algs_list()</c> and a set of algorithms <c>A</c>
+ obtained from the <c>preferred_algorithms</c> option if existing, or else from the
+ <seealso marker="ssh#default_algorithms-0">ssh:default_algorithms/0</seealso>.
</p>
</item>
-
- <tag><c>{profile, atom()}</c></tag>
<item>
- <p>Used together with <c>ip-address</c> and <c>port</c> to
- uniquely identify a ssh daemon. This can be useful in a
- virtualized environment, where there can be more that one
- server that has the same <c>ip-address</c> and
- <c>port</c>. If this property is not explicitly set, it is
- assumed that the the <c>ip-address</c> and <c>port</c>
- uniquely identifies the SSH daemon.
- </p>
+ <p>The head of the <c>modify_algs_list()</c> modifies <c>A</c> giving the result <c>A'</c>.</p>
+ <p>The possible modifications are:</p>
+ <list>
+ <item>
+ <p>Append or prepend supported but not enabled algorithm(s) to the list of
+ algorithms. If the wanted algorithms already are in <c>A</c> they will first
+ be removed and then appended or prepended,
+ </p>
+ </item>
+ <item>
+ <p>Remove (rm) one or more algorithms from <c>A</c>.
+ </p>
+ </item>
+ </list>
</item>
-
- <tag><c><![CDATA[{fd, file_descriptor()}]]></c></tag>
- <item>
- <p>Allows an existing file-descriptor to be used
- (passed on to the transport protocol).</p></item>
- <tag><c><![CDATA[{failfun, fun(User::string(),
- PeerAddress::ip_address(), Reason::term()) -> _}]]></c></tag>
<item>
- <p>Provides a fun to implement your own logging when a user fails to authenticate.</p>
+ <p>Repeat the modification step with the tail of <c>modify_algs_list()</c> and the resulting
+ <c>A'</c>.
+ </p>
</item>
- <tag><c><![CDATA[{connectfun, fun(User::string(), PeerAddress::ip_address(),
- Method::string()) ->_}]]></c></tag>
- <item>
- <p>Provides a fun to implement your own logging when a user authenticates to the server.</p>
+ </list>
+ <p>If an unsupported algorithm is in the <c>modify_algs_list()</c>, it will be silently ignored</p>
+ <p>If there are more than one modify_algorithms options, the result is undefined.</p>
+ <p>Here is an example of this option:</p>
+ <code>
+ {modify_algorithms,
+ [{prepend, [{kex, ['diffie-hellman-group1-sha1']}],
+ {rm, [{compression, [none]}]}
+ ]
+ }
+ </code>
+ <p>The example specifies that:</p>
+ <list>
+ <item><p>the old key exchange algorithm 'diffie-hellman-group1-sha1' should be
+ the main alternative. It will be the main alternative since it is prepened to the list</p>
</item>
- <tag><c><![CDATA[{disconnectfun, fun(Reason:term()) -> _}]]></c></tag>
- <item>
- <p>Provides a fun to implement your own logging when a user disconnects from the server.</p>
+ <item><p>The compression algorithm none (= no compression) is removed so compression is enforced</p>
</item>
+ </list>
+ <p>For background and more examples see the <seealso marker="configure_algos#introduction">User's Guide</seealso>.</p>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{unexpectedfun, fun(Message:term(), Peer) -> report | skip }]]></c></tag>
- <item>
- <p>Provides a fun to implement your own logging or other action when an unexpected message arrives.
- If the fun returns <c>report</c> the usual info report is issued but if <c>skip</c> is returned no
- report is generated.</p>
- <p><c>Peer</c> is in the format of <c>{Host,Port}</c>.</p>
- </item>
- <tag><c><![CDATA[{idle_time, integer()}]]></c></tag>
- <item>
- <p>Sets a time-out on a connection when no channels are active.
- Defaults to <c>infinity</c>.</p>
- </item>
+ <datatype>
+ <name name="inet_common_option"/>
+ <desc>
+ <p>IP version to use when the host address is specified as <c>any</c>.</p>
+ </desc>
+ </datatype>
- <tag><c><![CDATA[{ssh_msg_debug_fun, fun(ConnectionRef::ssh_connection_ref(), AlwaysDisplay::boolean(), Msg::binary(), LanguageTag::binary()) -> _}]]></c></tag>
- <item>
- <p>Provide a fun to implement your own logging of the SSH message SSH_MSG_DEBUG. The last three parameters are from the message, see RFC4253, section 11.3. The <c>ConnectionRef</c> is the reference to the connection on which the message arrived. The return value from the fun is not checked.</p>
- <p>The default behaviour is ignore the message.
- To get a printout for each message with <c>AlwaysDisplay = true</c>, use for example <c>{ssh_msg_debug_fun, fun(_,true,M,_)-> io:format("DEBUG: ~p~n", [M]) end}</c></p>
- </item>
+ <datatype>
+ <name name="auth_methods_common_option"/>
+ <desc>
+ <p>Comma-separated string that determines which authentication methods that the client shall
+ support and in which order they are tried. Defaults to <c>"publickey,keyboard-interactive,password"</c>
+ </p>
+ <p>Note that the client is free to use any order and to exclude methods.
+ </p>
+ </desc>
+ </datatype>
- </taglist>
- </desc>
- </func>
+ <datatype>
+ <name name="fd_common_option"/>
+ <desc>
+ <p>Allows an existing file-descriptor to be used (passed on to the transport protocol).</p>
+ </desc>
+ </datatype>
- <func>
- <name>daemon_info(Daemon) -> {ok, [DaemonInfo]} | {error,Error}</name>
- <fsummary>Get info about a daemon</fsummary>
- <type>
- <v>DaemonInfo = {port,Port::pos_integer()} | {listen_address, any|ip_address()} | {profile,atom()}</v>
- <v>Port = integer()</v>
- <v>Error = bad_daemon_ref</v>
- </type>
+ <!--................................................................-->
+ <datatype_title>Other data types</datatype_title>
+
+ <datatype>
+ <name name="host"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="ip_port"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="mod_args"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="mod_fun_args"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="open_socket"/>
+ <desc>
+ <p>The socket is supposed to be result of a <seealso marker="kernel:gen_tcp#connect-3">gen_tcp:connect</seealso>
+ or a <seealso marker="kernel:gen_tcp#accept-1">gen_tcp:accept</seealso>. The socket must be in passive
+ mode (that is, opened with the option <c>{active,false})</c>.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="daemon_ref"/>
+ <desc>
+ <p>Opaque data type representing a daemon.</p>
+ <p>Returned by the functions <seealso marker="ssh#daemon-1"><c>daemon/1,2,3</c></seealso>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name>connection_ref()</name>
<desc>
- <p>Returns a key-value list with information about the daemon. For now, only the listening port is returned. This is intended for the case the daemon is started with the port set to 0.</p>
+ <p>Opaque data type representing a connection between a client and a server (daemon).</p>
+ <p>Returned by the functions
+ <seealso marker="ssh#connect-3"><c>connect/2,3,4</c></seealso> and
+ <seealso marker="ssh_sftp#start_channel-2"><c>ssh_sftp:start_channel/2,3</c></seealso>.
+ </p>
</desc>
+ </datatype>
+
+ <datatype>
+ <name name="channel_id"/>
+ <desc>
+ <p>Opaque data type representing a channel inside a connection.</p>
+ <p>Returned by the functions
+ <seealso marker="ssh_connection#session_channel/2">ssh_connection:session_channel/2,4</seealso>.
+ </p>
+ </desc>
+ </datatype>
+
+
+ <datatype>
+ <name>opaque_client_options</name>
+ <name>opaque_daemon_options</name>
+ <name>opaque_common_options</name>
+ <desc>
+ <marker id="type-opaque_client_options"/>
+ <marker id="type-opaque_daemon_options"/>
+ <marker id="type-opaque_common_options"/>
+ <p>Opaque types that define experimental options that are not to be used in products.</p>
+ </desc>
+ </datatype>
+ </datatypes>
+
+<!--
+ ================================================================
+ = Function definitions =
+ ================================================================
+-->
+
+ <funcs>
+
+<!-- CLOSE/1 -->
+ <func>
+ <name name="close" arity="1"/>
+ <fsummary>Closes an SSH connection.</fsummary>
+ <desc><p>Closes an SSH connection.</p></desc>
</func>
+
+<!-- CONNECT/2 etc -->
+ <func>
+ <name>connect(Host, Port, Options) -> Result </name>
+ <name>connect(Host, Port, Options, NegotiationTimeout) -> Result </name>
+ <name>connect(TcpSocket, Options) -> Result</name>
+ <name>connect(TcpSocket, Options, NegotiationTimeout) -> Result</name>
+ <fsummary>Connects to an SSH server.</fsummary>
+ <type>
+ <v>Host = <seealso marker="#type-host">host()</seealso></v>
+ <v>Port = <seealso marker="kernel:inet#type-port_number">inet:port_number()</seealso></v>
+ <v>Options = <seealso marker="#type-client_options">client_options()</seealso></v>
+ <v>TcpSocket = <seealso marker="#type-open_socket">open_socket()</seealso></v>
+ <v>NegotiationTimeout = timeout()</v>
+ <v>Result = {ok, <seealso marker="#type-connection_ref">connection_ref()</seealso>} | {error, term()}</v>
+ </type>
+ <desc>
+ <p>Connects to an SSH server at the <c>Host</c> on <c>Port</c>.
+ </p>
+ <p>As an alternative, an already open TCP socket could be passed to the function in <c>TcpSocket</c>.
+ The SSH initiation and negotiation will be initiated on that one with the SSH that should be at the
+ other end.
+ </p>
+ <p>No channel is started. This is done by calling <seealso marker="ssh_connection#session_channel/2">
+ ssh_connection:session_channel/[2, 4]</seealso>.
+ </p>
+ <p>The <c>NegotiationTimeout</c> is in milli-seconds. The default value is <c>infinity</c>.
+ For connection timeout, use the option
+ <seealso marker="#type-connect_timeout_client_option"><c>connect_timeout</c></seealso>.
+ </p>
+ </desc>
+ </func>
+
+<!-- CONNECTION_INFO/1, CONNECTION_INFO/2 -->
+ <func>
+ <name name="connection_info" arity="2"/>
+ <fsummary>Retrieves information about a connection.</fsummary>
+ <desc>
+ <p>Retrieves information about a connection. The list <c>Keys</c> defines which information that
+ is returned.</p>
+ </desc>
+ </func>
+
+<!-- DEAMON/1,2,3 -->
+ <func>
+ <name>daemon(Port | TcpSocket) -> Result</name>
+ <name>daemon(Port | TcpSocket, Options) -> Result</name>
+ <name>daemon(HostAddress, Port, Options) -> Result</name>
+ <fsummary>Starts a server listening for SSH connections.</fsummary>
+ <type>
+ <v>Port = integer()</v>
+ <v>TcpSocket = <seealso marker="#type-open_socket">open_socket()</seealso></v>
+ <v>Options = <seealso marker="#type-daemon_options">daemon_options()</seealso></v>
+ <v>HostAddress = <seealso marker="#type-host">host()</seealso> | any</v>
+ <v>Result = {ok, <seealso marker="#type-daemon_ref">daemon_ref()</seealso>} | {error, atom()}</v>
+ </type>
+ <desc>
+ <p>Starts a server listening for SSH connections on the given port. If the <c>Port</c> is 0,
+ a random free port is selected. See <seealso marker="#daemon_info/1">daemon_info/1</seealso>
+ about how to find the selected port number.
+ </p>
+ <p>As an alternative, an already open TCP socket could be passed to the function in <c>TcpSocket</c>.
+ The SSH initiation and negotiation will be initiated on that one when an SSH starts at the other end
+ of the TCP socket.
+ </p>
+ <p>For a description of the options, see <seealso marker="#type-daemon_options">Daemon Options</seealso>.
+ </p>
+ <p>Please note that by historical reasons both the <c>HostAddress</c> argument and the
+ <seealso marker="kernel:gen_tcp#type-connect_option">gen_tcp connect_option() <c>{ip,Address}</c></seealso>
+ set the listening address. This is a source of possible inconsistent settings.
+ </p>
+ <p>The rules for handling the two address passing options are:</p>
+ <list>
+ <item>if <c>HostAddress</c> is an IP-address, that IP-address is the listening address.
+ An 'ip'-option will be discarded if present.</item>
+
+ <item>if <c>HostAddress</c> is the atom <c>loopback</c>, the listening address
+ is <c>loopback</c> and an loopback address will be choosen by the underlying layers.
+ An 'ip'-option will be discarded if present.</item>
+
+ <item>if <c>HostAddress</c> is the atom <c>any</c> and no 'ip'-option is present, the listening address is
+ <c>any</c> and the socket will listen to all addresses</item>
+
+ <item>if <c>HostAddress</c> is <c>any</c> and an 'ip'-option is present, the listening address is
+ set to the value of the 'ip'-option</item>
+ </list>
+ </desc>
+ </func>
+
+<!-- DAEMON_INFO/1 -->
+ <func>
+ <name name="daemon_info" arity="1"/>
+ <fsummary>Get info about a daemon</fsummary>
+ <desc>
+ <p>Returns a key-value list with information about the daemon.</p>
+ </desc>
+ </func>
+
+<!-- DEFAULT_ALGORITHMS/0 -->
<func>
- <name>default_algorithms() -> algs_list()</name>
+ <name name="default_algorithms" arity="0"/>
<fsummary>Get a list declaring the supported algorithms</fsummary>
<desc>
<p>Returns a key-value list, where the keys are the different types of algorithms and the values are the
- algorithms themselves. An example:</p>
- <code>
-20> ssh:default_algorithms().
-[{kex,['diffie-hellman-group1-sha1']},
- {public_key,['ssh-rsa','ssh-dss']},
- {cipher,[{client2server,['aes128-ctr','aes128-cbc','3des-cbc']},
- {server2client,['aes128-ctr','aes128-cbc','3des-cbc']}]},
- {mac,[{client2server,['hmac-sha2-256','hmac-sha1']},
- {server2client,['hmac-sha2-256','hmac-sha1']}]},
- {compression,[{client2server,[none,zlib]},
- {server2client,[none,zlib]}]}]
-21>
-</code>
+ algorithms themselves.</p>
+ <p>See the <seealso marker="configure_algos#example_default_algorithms">User's Guide</seealso> for
+ an example.</p>
</desc>
</func>
+<!-- SHELL/1,2,3 -->
<func>
- <name>shell(Host) -> </name>
- <name>shell(Host, Option) -> </name>
- <name>shell(Host, Port, Option) -> </name>
- <name>shell(TcpSocket) -> _</name>
- <fsummary>Starts an interactive shell over an SSH server.</fsummary>
+ <name>shell(Host | TcpSocket) -> Result </name>
+ <name>shell(Host | TcpSocket, Options) -> Result </name>
+ <name>shell(Host, Port, Options) -> Result </name>
+ <fsummary>Starts an interactive shell on a remote SSH server.</fsummary>
<type>
- <v>Host = string()</v>
- <v>Port = integer()</v>
- <v>Options - see ssh:connect/3</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>Host = <seealso marker="#type-host">host()</seealso></v>
+ <v>TcpSocket = <seealso marker="#type-open_socket">open_socket()</seealso></v>
+ <v>Port = <seealso marker="kernel:inet#type-port_number">inet:port_number()</seealso></v>
+ <v>Options = <seealso marker="#type-client_options">client_options()</seealso></v>
+ <v>Result = ok | {error, Reason::term()}</v>
</type>
<desc>
- <p>Starts an interactive shell over an SSH server on the
- given <c>Host</c>. The function waits for user input,
- and does not return until the remote shell is ended (that is,
+ <p>Connects to an SSH server at <c>Host</c> and <c>Port</c> (defaults to 22) and starts an
+ interactive shell on that remote host.
+ </p>
+ <p>As an alternative, an already open TCP socket could be passed to the function in <c>TcpSocket</c>.
+ The SSH initiation and negotiation will be initiated on that one and finaly a shell will be started
+ on the host at the other end of the TCP socket.
+ </p>
+ <p>For a description of the options, see <seealso marker="#type-client_options">Client Options</seealso>.</p>
+ <p>The function waits for user input, and does not return until the remote shell is ended (that is,
exit from the shell).
</p>
</desc>
</func>
<func>
- <name>start() -> </name>
- <name>start(Type) -> ok | {error, Reason}</name>
+ <name name="start" arity="0"/>
+ <name name="start" arity="1"/>
<fsummary>Starts the SSH application.</fsummary>
- <type>
- <v>Type = permanent | transient | temporary</v>
- <v>Reason = term() </v>
- </type>
<desc>
<p>Utility function that starts the applications <c>crypto</c>, <c>public_key</c>,
and <c>ssh</c>. Default type is <c>temporary</c>.
@@ -868,11 +1232,8 @@
</func>
<func>
- <name>stop() -> ok | {error, Reason}</name>
+ <name name="stop" arity="0"/>
<fsummary>Stops the <c>ssh</c> application.</fsummary>
- <type>
- <v>Reason = term()</v>
- </type>
<desc>
<p>Stops the <c>ssh</c> application.
For more information, see the <seealso marker="kernel:application">application(3)</seealso>
@@ -881,34 +1242,22 @@
</func>
<func>
- <name>stop_daemon(DaemonRef) -> </name>
- <name>stop_daemon(Address, Port) -> ok </name>
- <fsummary>Stops the listener and all connections started by
- the listener.</fsummary>
- <type>
- <v>DaemonRef = ssh_daemon_ref()</v>
- <v>Address = ip_address()</v>
- <v>Port = integer()</v>
- </type>
+ <name name="stop_daemon" arity="1"/>
+ <name name="stop_daemon" arity="2"/>
+ <name name="stop_daemon" arity="3"/>
+ <fsummary>Stops the listener and all connections started by the listener.</fsummary>
<desc>
- <p>Stops the listener and all connections started by
- the listener.</p>
+ <p>Stops the listener and all connections started by the listener.</p>
</desc>
</func>
<func>
- <name>stop_listener(DaemonRef) -> </name>
- <name>stop_listener(Address, Port) -> ok </name>
- <fsummary>Stops the listener, but leaves existing connections started
- by the listener operational.</fsummary>
- <type>
- <v>DaemonRef = ssh_daemon_ref()</v>
- <v>Address = ip_address()</v>
- <v>Port = integer()</v>
- </type>
+ <name name="stop_listener" arity="1"/>
+ <name name="stop_listener" arity="2"/>
+ <name name="stop_listener" arity="3"/>
+ <fsummary>Stops the listener, but leaves existing connections started by the listener operational.</fsummary>
<desc>
- <p>Stops the listener, but leaves existing connections started
- by the listener operational.</p>
+ <p>Stops the listener, but leaves existing connections started by the listener operational.</p>
</desc>
</func>
diff --git a/lib/ssh/doc/src/ssh_app.xml b/lib/ssh/doc/src/ssh_app.xml
index 33ec7aaee0..e80bb1853d 100644
--- a/lib/ssh/doc/src/ssh_app.xml
+++ b/lib/ssh/doc/src/ssh_app.xml
@@ -4,7 +4,7 @@
<appref>
<header>
<copyright>
- <year>2012</year><year>2017</year>
+ <year>2012</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -97,7 +97,7 @@
<p>The <c>known_hosts</c> file contains a list of approved servers and
their public keys. Once a server is listed, it can be verified
without user interaction.
- </p>
+ </p>
</section>
<section>
<title>Authorized Keys</title>
@@ -130,39 +130,50 @@
For the list on a particular installation, use the command
<seealso marker="ssh:ssh#default_algorithms/0">ssh:default_algorithms/0</seealso>.
The user may override the default algorithm configuration both on the server side and the client side.
- See the option <c>preferred_algorithms</c> in the <seealso marker="ssh:ssh#daemon/1">ssh:daemon/1,2,3</seealso> and
+ See the options
+ <seealso marker="ssh:ssh#type-preferred_algorithms_common_option">preferred_algorithms</seealso>
+ and
+ <seealso marker="ssh:ssh#type-modify_algorithms_common_option">modify_algorithms</seealso>
+ in the <seealso marker="ssh:ssh#daemon/1">ssh:daemon/1,2,3</seealso> and
<seealso marker="ssh:ssh#connect/3">ssh:connect/3,4</seealso> functions.
</p>
- <p>Supported algorithms are:</p>
-
+ <p>Supported algorithms are (in the default order):</p>
+ <marker id="supported_algos"></marker>
<taglist>
<tag>Key exchange algorithms</tag>
<item>
<list type="bulleted">
- <item>ecdh-sha2-nistp256</item>
<item>ecdh-sha2-nistp384</item>
<item>ecdh-sha2-nistp521</item>
- <item>diffie-hellman-group-exchange-sha1</item>
+ <item>ecdh-sha2-nistp256</item>
<item>diffie-hellman-group-exchange-sha256</item>
- <item>diffie-hellman-group14-sha1</item>
- <item>diffie-hellman-group14-sha256</item>
<item>diffie-hellman-group16-sha512</item>
<item>diffie-hellman-group18-sha512</item>
- <item>(diffie-hellman-group1-sha1, retired: can be enabled with the <c>preferred_algorithms</c> option)</item>
+ <item>diffie-hellman-group14-sha256</item>
+ <item>curve25519-sha256</item>
+ <item>[email protected]</item>
+ <item>curve448-sha512</item>
+ <item>diffie-hellman-group14-sha1</item>
+ <item>diffie-hellman-group-exchange-sha1</item>
+ <item>(diffie-hellman-group1-sha1, retired: It can be enabled with the
+ <seealso marker="ssh:ssh#type-preferred_algorithms_common_option">preferred_algorithms</seealso>
+ or
+ <seealso marker="ssh:ssh#type-modify_algorithms_common_option">modify_algorithms</seealso>
+ options)</item>
</list>
</item>
<tag>Public key algorithms</tag>
<item>
<list type="bulleted">
- <item>ecdsa-sha2-nistp256</item>
<item>ecdsa-sha2-nistp384</item>
<item>ecdsa-sha2-nistp521</item>
+ <item>ecdsa-sha2-nistp256</item>
<item>ssh-rsa</item>
- <item>ssh-dss</item>
<item>rsa-sha2-256</item>
<item>rsa-sha2-512</item>
+ <item>ssh-dss</item>
</list>
</item>
@@ -178,11 +189,12 @@
<tag>Encryption algorithms (ciphers)</tag>
<item>
<list type="bulleted">
- <item>[email protected]</item>
+ <item>[email protected]</item>
<item>[email protected]</item>
- <item>aes128-ctr</item>
- <item>aes192-ctr</item>
<item>aes256-ctr</item>
+ <item>aes192-ctr</item>
+ <item>[email protected]</item>
+ <item>aes128-ctr</item>
<item>aes128-cbc</item>
<item>3des-cbc</item>
<item>(AEAD_AES_128_GCM, not enabled per default)</item>
@@ -241,7 +253,11 @@
<item><url href="https://tools.ietf.org/html/rfc4253">RFC 4253</url>, The Secure Shell (SSH) Transport Layer Protocol.
<p>Except</p>
<list type="bulleted">
- <item>8.1. diffie-hellman-group1-sha1. Disabled by default, can be enabled with the <c>preferred_algorithms</c> option.</item>
+ <item>8.1. diffie-hellman-group1-sha1. Disabled by default, can be enabled with the
+ <seealso marker="ssh:ssh#type-preferred_algorithms_common_option">preferred_algorithms</seealso>
+ or
+ <seealso marker="ssh:ssh#type-modify_algorithms_common_option">modify_algorithms</seealso>
+ options.</item>
</list>
<p/>
</item>
@@ -280,7 +296,10 @@
<p><marker id="rfc5647_note"/>There is an ambiguity in the synchronized selection of cipher and mac algorithm.
This is resolved by OpenSSH in the ciphers [email protected] and [email protected] which are implemented.
If the explicit ciphers and macs AEAD_AES_128_GCM or AEAD_AES_256_GCM are needed,
- they could be enabled with the option preferred_algorithms.
+ they could be enabled with the options
+ <seealso marker="ssh:ssh#type-preferred_algorithms_common_option">preferred_algorithms</seealso>
+ or
+ <seealso marker="ssh:ssh#type-modify_algorithms_common_option">modify_algorithms</seealso>.
</p>
<warning>
<p>
@@ -322,18 +341,27 @@
<p>Deviations:</p>
<list type="bulleted">
<item>The <c>diffie-hellman-group1-sha1</c> is not enabled by default, but is still supported and can be enabled
- with the option <c>preferred-algorithms</c></item>
+ with the options
+ <seealso marker="ssh:ssh#type-preferred_algorithms_common_option">preferred_algorithms</seealso>
+ or
+ <seealso marker="ssh:ssh#type-modify_algorithms_common_option">modify_algorithms</seealso>.
+ </item>
<item>The questionable sha1-based algorithms <c>diffie-hellman-group-exchange-sha1</c> and
<c>diffie-hellman-group14-sha1</c> are still enabled by default for compatibility with ancient clients and servers.
- They can be disabled with the option <c>preferred-algorithms</c></item>
+ They can be disabled with the options
+ <seealso marker="ssh:ssh#type-preferred_algorithms_common_option">preferred_algorithms</seealso>
+ or
+ <seealso marker="ssh:ssh#type-modify_algorithms_common_option">modify_algorithms</seealso>.
+ They will be disabled by default when the draft is turned into an RFC.</item>
</list>
<p/>
</item>
- <item><url href="https://tools.ietf.org/html/draft-ietf-curdle-rsa-sha2">Draft-ietf-curdle-rsa-sha2 (work in progress)</url>, Use of RSA Keys with SHA-2 256 and 512 in Secure Shell (SSH).
+ <item><url href="https://tools.ietf.org/html/rfc8332">RFC 8332</url>, Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell (SSH) Protocol.
</item>
- <item><url href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-ext-info">Draft-ietf-curdle-ssh-ext-info (work in progress)</url>, Extension Negotiation in Secure Shell (SSH).
+ <item><marker id="supported-ext-info"/>
+ <url href="https://tools.ietf.org/html/rfc8308">RFC 8308</url>, Extension Negotiation in the Secure Shell (SSH) Protocol.
<p>Implemented are:</p>
<list type="bulleted">
<item>The Extension Negotiation Mechanism</item>
@@ -341,6 +369,10 @@
</list>
<p/>
</item>
+
+ <item>
+ <url href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves">Secure Shell (SSH) Key Exchange Method using Curve25519 and Curve448 (work in progress)</url>
+ </item>
</list>
diff --git a/lib/ssh/doc/src/ssh_channel.xml b/lib/ssh/doc/src/ssh_channel.xml
deleted file mode 100644
index 7b598494f7..0000000000
--- a/lib/ssh/doc/src/ssh_channel.xml
+++ /dev/null
@@ -1,443 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>2009</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
- <title>ssh_channel</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <module>ssh_channel</module>
- <modulesummary>-behaviour(ssh_channel).
- </modulesummary>
- <description>
- <p>SSH services (clients and servers) are implemented as channels
- that are multiplexed over an SSH connection and communicates over
- the <url href="http://www.ietf.org/rfc/rfc4254.txt"> SSH
- Connection Protocol</url>. This module provides a callback API
- that takes care of generic channel aspects, such as flow control
- and close messages. It lets the callback functions take care of
- the service (application) specific parts. This behavior also ensures
- that the channel process honors the principal of an OTP-process so
- that it can be part of a supervisor tree. This is a requirement of
- channel processes implementing a subsystem that will be added to
- the <c>ssh</c> applications supervisor tree.
- </p>
-
- <note><p>When implementing an <c>ssh</c> subsystem, use
- <c>-behaviour(ssh_daemon_channel)</c> instead of <c>-behaviour(ssh_channel)</c>.
- The reason is that the only relevant callback functions for subsystems are
- <c>init/1</c>, <c>handle_ssh_msg/2</c>, <c>handle_msg/2</c>, and <c>terminate/2</c>.
- So, the <c>ssh_daemon_channel</c> behaviour is a limited version of the
- <c>ssh_channel</c> behaviour.
- </p></note>
- </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>ssh_connection_ref() =</c></tag>
- <item><p>opaque() -as returned by
- <c>ssh:connect/3</c> or sent to an SSH channel process</p></item>
- <tag><c>ssh_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
- the valid values,
- see <url href="http://www.ietf.org/rfc/rfc4254.txt">RFC 4254</url>
- Section 5.2</p></item>
- </taglist>
- </section>
-
- <funcs>
- <func>
- <name>call(ChannelRef, Msg) -></name>
- <name>call(ChannelRef, Msg, Timeout) -> Reply | {error, Reason}</name>
- <fsummary>Makes a synchronous call to a channel.</fsummary>
- <type>
- <v>ChannelRef = pid() </v>
- <d>As returned by <seealso marker = "#start_link-4">ssh_channel:start_link/4</seealso></d>
- <v>Msg = term()</v>
- <v>Timeout = timeout()</v>
- <v>Reply = term()</v>
- <v>Reason = closed | timeout</v>
-
- </type>
- <desc>
- <p>Makes a synchronous call to the channel process by sending
- a message and waiting until a reply arrives, or a time-out
- occurs. The channel calls <seealso marker =
- "#Module:handle_call-3">Module:handle_call/3</seealso>
- to handle the message. If the channel process does not exist,
- <c>{error, closed}</c> is returned.
- </p>
- </desc>
- </func>
-
- <func>
- <name>cast(ChannelRef, Msg) -> ok </name>
- <fsummary>Sends an asynchronous message to the channel
- ChannelRef and returns ok.</fsummary>
- <type>
- <v>ChannelRef = pid()</v>
- <d>As returned by <seealso marker = "#start_link-4">ssh_channel:start_link/4</seealso></d>
- <v>Msg = term()</v>
- </type>
- <desc>
- <p>Sends an asynchronous message to the channel process and
- returns ok immediately, ignoring if the destination node or
- channel process does not exist. The channel calls
- <seealso marker = "#Module:handle_cast-2">Module:handle_cast/2</seealso>
- to handle the message.
- </p>
- </desc>
- </func>
-
- <func>
- <name>enter_loop(State) -> _ </name>
- <fsummary>Makes an existing process an ssh_channel process.</fsummary>
- <type>
- <v>State = term()</v>
- <d>as returned by <seealso marker = "#init-1">ssh_channel:init/1</seealso></d>
- </type>
- <desc>
- <p>Makes an existing process an <c>ssh_channel</c>
- process. Does not return, instead the calling process
- enters the <c>ssh_channel</c> process receive loop and become an
- <c>ssh_channel process</c>. The process must have been started using
- one of the start functions in <c>proc_lib</c>, see the <seealso
- marker="stdlib:proc_lib">proc_lib(3)</seealso> manual page in STDLIB.
- The user is responsible for any initialization of the process
- and must call <seealso marker = "#init-1">ssh_channel:init/1</seealso>.
- </p>
- </desc>
- </func>
-
- <func>
- <name>init(Options) -> {ok, State} | {ok, State, Timeout} | {stop, Reason} </name>
- <fsummary>Initiates an <c>ssh_channel</c> process.</fsummary>
- <type>
- <v>Options = [{Option, Value}]</v>
- <v>State = term()</v>
- <v>Timeout = timeout()</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>
- The following options must be present:
- </p>
- <taglist>
- <tag><c><![CDATA[{channel_cb, atom()}]]></c></tag>
- <item><p>The module that implements the channel behaviour.</p></item>
-
- <tag><c><![CDATA[{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><![CDATA[{cm, connection_ref()}]]></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><![CDATA[{channel_id, channel_id()}]]></c></tag>
- <item><p>Id of the <c>ssh</c> channel.</p></item>
-
- </taglist>
-
- <note><p>This function is normally not called by the
- user. The user only needs to call if the
- channel process needs to be started with help of
- <c>proc_lib</c> instead of calling
- <c>ssh_channel:start/4</c> or
- <c>ssh_channel:start_link/4</c>.</p>
- </note>
- </desc>
- </func>
-
- <func>
- <name>reply(Client, Reply) -> _</name>
- <fsummary>Sends a reply to a client.</fsummary>
- <type>
- <v>Client = opaque()</v>
- <v>Reply = term()</v>
- </type>
- <desc>
- <p>This function can be used by a channel to send a
- reply to a client that called <c>call/[2,3]</c> when the reply
- cannot be defined in the return value of
- <seealso marker ="#Module:handle_call-3">Module:handle_call/3</seealso>.</p>
- <p><c>Client</c> must be the <c>From</c> argument provided to
- the callback function <c>handle_call/3</c>.
- <c>Reply</c> is an arbitrary term,
- which is given back to the client as the return value of
- <seealso marker="#call-2">ssh_channel:call/[2,3].</seealso></p>
- </desc>
- </func>
-
- <func>
- <name>start(SshConnection, ChannelId, ChannelCb, CbInitArgs) -> </name>
- <name>start_link(SshConnection, ChannelId, ChannelCb, CbInitArgs) ->
- {ok, ChannelRef} | {error, Reason}</name>
- <fsummary>Starts a process that handles an SSH channel.</fsummary>
- <type>
- <v>SshConnection = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
- <d>As returned by
- <seealso marker ="ssh_connection#session_channel/2">
- ssh_connection:session_channel/[2,4]</seealso>.</d>
- <v>ChannelCb = atom()</v>
- <d>Name of the module implementing the service-specific parts
- of the channel.</d>
- <v>CbInitArgs = [term()]</v>
- <d>Argument list for the <c>init</c> function in the callback module.</d>
- <v>ChannelRef = pid()</v>
- </type>
- <desc>
- <p>Starts a process that handles an SSH channel. It is
- called internally, by the <c>ssh</c> daemon, or explicitly by the <c>ssh</c>
- client implementations. The behavior sets the
- <c>trap_exit</c> flag to <c>true</c>.
- </p>
- </desc>
- </func>
-
- </funcs>
-
- <section>
- <marker id="cb_timeouts"></marker>
- <title>CALLBACK TIME-OUTS</title>
-
- <p>The time-out values that can be returned by the callback functions
- have the same semantics as in a <seealso marker="stdlib:gen_server">gen_server</seealso>.
- If the time-out occurs, <seealso marker="#Module:handle_msg-2">handle_msg/2</seealso>
- is called as <c>handle_msg(timeout, State)</c>.</p>
- </section>
-
- <funcs>
- <func>
- <name>Module:code_change(OldVsn, State, Extra) -> {ok,
- NewState}</name>
- <fsummary>Converts process state when code is changed.</fsummary>
- <type>
- <v>OldVsn = term()</v>
- <d>In the case of an upgrade, <c>OldVsn</c> is <c>Vsn</c>, and
- in the case of a downgrade, <c>OldVsn</c> is
- <c>{down,Vsn}</c>. <c>Vsn</c> is defined by the <c>vsn</c>
- attribute(s) of the old version of the callback module
- <c>Module</c>. If no such attribute is defined, the version is
- the checksum of the BEAM file.</d>
- <v>State = term()</v>
- <d>Internal state of the channel.</d>
- <v>Extra = term()</v>
- <d>Passed "as-is" from the <c>{advanced,Extra}</c>
- part of the update instruction.</d>
- </type>
- <desc>
- <p>Converts process state when code is changed.</p>
-
- <p>This function is called by a client-side channel when it
- is to update its internal state during a release
- upgrade or downgrade, that is, when the instruction
- <c>{update,Module,Change,...}</c>, where
- <c>Change={advanced,Extra}</c>, is given in the <c>appup</c>
- file. For more information, refer to Section 9.11.6
- Release Handling Instructions in the
- <seealso marker="doc/design_principles:release_handling#instr">System Documentation</seealso>.
- </p>
-
- <note><p>Soft upgrade according to the OTP release concept
- is not straight forward for the server side, as subsystem
- channel processes are spawned by the <c>ssh</c> application and
- hence added to its supervisor tree. The subsystem channels can
- be upgraded when upgrading the user application, if the callback
- functions can handle two versions of the state, but this function
- cannot be used in the normal way.</p>
- </note>
-
- </desc>
- </func>
-
- <func>
- <name>Module:init(Args) -> {ok, State} | {ok, State, timeout()} |
- {stop, Reason}</name>
- <fsummary>Makes necessary initializations and returns the
- initial channel state if the initializations succeed.</fsummary>
- <type>
- <v>Args = term()</v>
- <d>Last argument to <c>ssh_channel:start_link/4</c>.</d>
- <v>State = term()</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Makes necessary initializations and returns the initial channel
- state if the initializations succeed.
- </p>
- <p>For more detailed information on time-outs, see Section
- <seealso marker="#cb_timeouts">CALLBACK TIME-OUTS</seealso>. </p>
- </desc>
- </func>
-
- <func>
- <name>Module:handle_call(Msg, From, State) -> Result</name>
- <fsummary>Handles messages sent by calling
- <c>ssh_channel:call/[2,3]</c>.</fsummary>
- <type>
- <v>Msg = term()</v>
- <v>From = opaque()</v>
- <d>Is to be used as argument to
- <seealso marker="#reply-2">ssh_channel:reply/2</seealso></d>
- <v>State = term()</v>
- <v>Result = {reply, Reply, NewState} | {reply, Reply, NewState, timeout()}
- | {noreply, NewState} | {noreply , NewState, timeout()}
- | {stop, Reason, Reply, NewState} | {stop, Reason, NewState} </v>
- <v>Reply = term()</v>
- <d>Will be the return value of <seealso marker="#call-2">ssh_channel:call/[2,3]</seealso></d>
- <v>NewState = term()</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Handles messages sent by calling
- <seealso marker="#call-2">ssh_channel:call/[2,3]</seealso>
- </p>
- <p>For more detailed information on time-outs,, see Section
- <seealso marker="#cb_timeouts">CALLBACK TIME-OUTS</seealso>.</p>
- </desc>
- </func>
-
- <func>
- <name>Module:handle_cast(Msg, State) -> Result</name>
- <fsummary>Handles messages sent by calling
- <c>ssh_channel:cact/2</c>.</fsummary>
- <type>
- <v>Msg = term()</v>
- <v>State = term()</v>
- <v>Result = {noreply, NewState} | {noreply, NewState, timeout()}
- | {stop, Reason, NewState}</v>
- <v>NewState = term() </v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Handles messages sent by calling
- <c>ssh_channel:cast/2</c>.
- </p>
- <p>For more detailed information on time-outs, see Section
- <seealso marker="#cb_timeouts">CALLBACK TIME-OUTS</seealso>.</p>
- </desc>
- </func>
-
- <func>
- <name>Module:handle_msg(Msg, State) -> {ok, State} |
- {stop, ChannelId, State}</name>
-
- <fsummary>Handles other messages than SSH connection protocol,
- call, or cast messages sent to the channel.</fsummary>
- <type>
- <v>Msg = timeout | term()</v>
- <v>ChannelId = ssh_channel_id()</v>
- <v>State = term() </v>
- </type>
- <desc>
- <p>Handles other messages than SSH Connection Protocol, call, or
- cast messages sent to the channel.
- </p>
-
- <p>Possible Erlang 'EXIT' messages is to be handled by this
- function and all channels are to handle the following message.</p>
-
- <taglist>
- <tag><c><![CDATA[{ssh_channel_up, ssh_channel_id(),
- ssh_connection_ref()}]]></c></tag>
- <item><p>This is the first message that the channel receives.
- It is sent just before the <seealso
- marker="#init-1">ssh_channel:init/1</seealso> function
- returns successfully. This is especially useful if the
- server wants to send a message to the client without first
- receiving a message from it. If the message is not
- useful for your particular scenario, ignore it by
- immediately returning <c>{ok, State}</c>.
- </p></item>
- </taglist>
- </desc>
- </func>
-
- <func>
- <name>Module:handle_ssh_msg(Msg, State) -> {ok, State} | {stop,
- ChannelId, State}</name>
- <fsummary>Handles <c>ssh</c> connection protocol messages.</fsummary>
- <type>
- <v>Msg = ssh_connection:event()</v>
- <v>ChannelId = ssh_channel_id()</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>.
- </p>
-
- <p>The following message is taken care of by the
- <c>ssh_channel</c> behavior.</p>
-
- <taglist>
- <tag><c><![CDATA[{closed, ssh_channel_id()}]]></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>
- </taglist>
- </desc>
- </func>
-
- <func>
- <name>Module:terminate(Reason, State) -> _</name>
- <fsummary>Does cleaning up before channel process termination.
- </fsummary>
- <type>
- <v>Reason = term()</v>
- <v>State = term()</v>
- </type>
- <desc>
- <p>This function is called by a channel process when it is
- about to terminate. Before this function is called, <seealso
- marker="ssh_connection#close-2"> ssh_connection:close/2
- </seealso> is called, if it has not been called earlier.
- This function does any necessary cleaning
- up. When it returns, the channel process terminates with
- reason <c>Reason</c>. The return value is ignored.
- </p>
- </desc>
- </func>
-
- </funcs>
-
-</erlref>
diff --git a/lib/ssh/doc/src/ssh_client_channel.xml b/lib/ssh/doc/src/ssh_client_channel.xml
new file mode 100644
index 0000000000..9be4007c68
--- /dev/null
+++ b/lib/ssh/doc/src/ssh_client_channel.xml
@@ -0,0 +1,440 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2009</year>
+ <year>2018</year>
+ <holder>Ericsson AB, All Rights Reserved</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ The Initial Developer of the Original Code is Ericsson AB.
+ </legalnotice>
+ <title>ssh_client_channel</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ </header>
+ <module>ssh_client_channel</module>
+ <modulesummary>-behaviour(ssh_client_channel). (Replaces ssh_channel)
+ </modulesummary>
+ <description>
+ <note>
+ <p>This module replaces ssh_channel.</p>
+ <p>The old module is still available for compatibility, but should not be used for new programs.
+ The old module will not be maintained except for some error corrections
+ </p>
+ </note>
+ <p>SSH services (clients and servers) are implemented as channels
+ that are multiplexed over an SSH connection and communicates over
+ the <url href="http://www.ietf.org/rfc/rfc4254.txt"> SSH
+ Connection Protocol</url>. This module provides a callback API
+ that takes care of generic channel aspects for clients, such as flow control
+ and close messages. It lets the callback functions take care of
+ the service (application) specific parts. This behavior also ensures
+ that the channel process honors the principal of an OTP-process so
+ that it can be part of a supervisor tree. This is a requirement of
+ channel processes implementing a subsystem that will be added to
+ the <c>ssh</c> applications supervisor tree.
+ </p>
+
+ <note><p>When implementing a <c>ssh</c> subsystem for daemons, use
+ <seealso marker="ssh_server_channel">-behaviour(ssh_server_channel)</seealso> (Replaces ssh_daemon_channel)
+ instead.
+ </p>
+ </note>
+
+ <dont>
+ <p>Functions in this module are not supposed to be called outside a module implementing this
+ behaviour!
+ </p>
+ </dont>
+
+ </description>
+
+ <funcs>
+ <func>
+ <name>call(ChannelRef, Msg) -></name>
+ <name>call(ChannelRef, Msg, Timeout) -> Reply | {error, Reason}</name>
+ <fsummary>Makes a synchronous call to a channel.</fsummary>
+ <type>
+ <v>ChannelRef = pid() </v>
+ <d>As returned by <seealso marker = "#start_link-4">start_link/4</seealso></d>
+ <v>Msg = term()</v>
+ <v>Timeout = timeout()</v>
+ <v>Reply = term()</v>
+ <v>Reason = closed | timeout</v>
+
+ </type>
+ <desc>
+ <p>Makes a synchronous call to the channel process by sending
+ a message and waiting until a reply arrives, or a time-out
+ occurs. The channel calls <seealso marker =
+ "#Module:handle_call-3">Module:handle_call/3</seealso>
+ to handle the message. If the channel process does not exist,
+ <c>{error, closed}</c> is returned.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>cast(ChannelRef, Msg) -> ok </name>
+ <fsummary>Sends an asynchronous message to the channel
+ ChannelRef and returns ok.</fsummary>
+ <type>
+ <v>ChannelRef = pid()</v>
+ <d>As returned by <seealso marker = "#start_link-4">start_link/4</seealso></d>
+ <v>Msg = term()</v>
+ </type>
+ <desc>
+ <p>Sends an asynchronous message to the channel process and
+ returns ok immediately, ignoring if the destination node or
+ channel process does not exist. The channel calls
+ <seealso marker = "#Module:handle_cast-2">Module:handle_cast/2</seealso>
+ to handle the message.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>enter_loop(State) -> _ </name>
+ <fsummary>Makes an existing process an ssh_client_channel (replaces ssh_channel) process.</fsummary>
+ <type>
+ <v>State = term()</v>
+ <d>as returned by <seealso marker = "#init-1">init/1</seealso></d>
+ </type>
+ <desc>
+ <p>Makes an existing process an <c>ssh_client_channel</c> (replaces ssh_channel)
+ process. Does not return, instead the calling process
+ enters the <c>ssh_client_channel</c> (replaces ssh_channel) process receive loop and become an
+ <c>ssh_client_channel</c> process. The process must have been started using
+ one of the start functions in <c>proc_lib</c>, see the <seealso
+ marker="stdlib:proc_lib">proc_lib(3)</seealso> manual page in STDLIB.
+ The user is responsible for any initialization of the process
+ and must call <seealso marker = "#init-1">init/1</seealso>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>init(Options) -> {ok, State} | {ok, State, Timeout} | {stop, Reason} </name>
+ <fsummary>Initiates an <c>ssh_client_channel</c> process.</fsummary>
+ <type>
+ <v>Options = [{Option, Value}]</v>
+ <v>State = term()</v>
+ <v>Timeout = timeout()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>
+ The following options must be present:
+ </p>
+ <taglist>
+ <tag><c>{channel_cb, atom()}</c></tag>
+ <item><p>The module that implements the channel behaviour.</p></item>
+
+ <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>
+ <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>
+ <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>
+
+ </taglist>
+
+ <note><p>This function is normally not called by the
+ user. The user only needs to call if the
+ channel process needs to be started with help of
+ <c>proc_lib</c> instead of calling
+ <c>start/4</c> or
+ <c>start_link/4</c>.</p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
+ <name>reply(Client, Reply) -> _</name>
+ <fsummary>Sends a reply to a client.</fsummary>
+ <type>
+ <v>Client = opaque()</v>
+ <v>Reply = term()</v>
+ </type>
+ <desc>
+ <p>This function can be used by a channel to send a
+ reply to a client that called <c>call/[2,3]</c> when the reply
+ cannot be defined in the return value of
+ <seealso marker ="#Module:handle_call-3">Module:handle_call/3</seealso>.</p>
+ <p><c>Client</c> must be the <c>From</c> argument provided to
+ the callback function <c>handle_call/3</c>.
+ <c>Reply</c> is an arbitrary term,
+ which is given back to the client as the return value of
+ <seealso marker="#call-2">call/[2,3].</seealso></p>
+ </desc>
+ </func>
+
+ <func>
+ <name>start(SshConnection, ChannelId, ChannelCb, CbInitArgs) -> </name>
+ <name>start_link(SshConnection, ChannelId, ChannelCb, CbInitArgs) ->
+ {ok, ChannelRef} | {error, Reason}</name>
+ <fsummary>Starts a process that handles an SSH channel.</fsummary>
+ <type>
+ <v>SshConnection = ssh:connection_ref()</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>
+ <d>As returned by
+ <seealso marker ="ssh_connection#session_channel/2">
+ ssh_connection:session_channel/[2,4]</seealso>.</d>
+
+ <v>ChannelCb = atom()</v>
+ <d>Name of the module implementing the service-specific parts
+ of the channel.</d>
+
+ <v>CbInitArgs = [term()]</v>
+ <d>Argument list for the <c>init</c> function in the callback module.</d>
+
+ <v>ChannelRef = pid()</v>
+ </type>
+ <desc>
+ <p>Starts a process that handles an SSH channel. It is
+ called internally, by the <c>ssh</c> daemon, or explicitly by the <c>ssh</c>
+ client implementations. The behavior sets the
+ <c>trap_exit</c> flag to <c>true</c>.
+ </p>
+ </desc>
+ </func>
+
+ </funcs>
+
+ <section>
+ <title>Callback Functions</title>
+ <p>
+ The following functions are to be exported from a
+ <c>ssh_client_channel</c> callback module.
+ </p>
+ <marker id="cb_timeouts"></marker>
+ <section>
+ <title>Callback timeouts</title>
+ <p>The timeout values that can be returned by the callback functions
+ have the same semantics as in a <seealso marker="stdlib:gen_server">gen_server</seealso>.
+ If the time-out occurs, <seealso marker="#Module:handle_msg-2">handle_msg/2</seealso>
+ is called as <c>handle_msg(timeout, State)</c>.</p>
+ </section>
+ </section>
+
+ <funcs>
+ <func>
+ <name>Module:code_change(OldVsn, State, Extra) -> {ok,
+ NewState}</name>
+ <fsummary>Converts process state when code is changed.</fsummary>
+ <type>
+ <v>OldVsn = term()</v>
+ <d>In the case of an upgrade, <c>OldVsn</c> is <c>Vsn</c>, and
+ in the case of a downgrade, <c>OldVsn</c> is
+ <c>{down,Vsn}</c>. <c>Vsn</c> is defined by the <c>vsn</c>
+ attribute(s) of the old version of the callback module
+ <c>Module</c>. If no such attribute is defined, the version is
+ the checksum of the BEAM file.</d>
+ <v>State = term()</v>
+ <d>Internal state of the channel.</d>
+ <v>Extra = term()</v>
+ <d>Passed "as-is" from the <c>{advanced,Extra}</c>
+ part of the update instruction.</d>
+ </type>
+ <desc>
+ <p>Converts process state when code is changed.</p>
+
+ <p>This function is called by a client-side channel when it
+ is to update its internal state during a release
+ upgrade or downgrade, that is, when the instruction
+ <c>{update,Module,Change,...}</c>, where
+ <c>Change={advanced,Extra}</c>, is given in the <c>appup</c>
+ file. For more information, refer to Section 9.11.6
+ Release Handling Instructions in the
+ <seealso marker="doc/design_principles:release_handling#instr">System Documentation</seealso>.
+ </p>
+
+ <note><p>Soft upgrade according to the OTP release concept
+ is not straight forward for the server side, as subsystem
+ channel processes are spawned by the <c>ssh</c> application and
+ hence added to its supervisor tree. The subsystem channels can
+ be upgraded when upgrading the user application, if the callback
+ functions can handle two versions of the state, but this function
+ cannot be used in the normal way.</p>
+ </note>
+
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:init(Args) -> {ok, State} | {ok, State, timeout()} |
+ {stop, Reason}</name>
+ <fsummary>Makes necessary initializations and returns the
+ initial channel state if the initializations succeed.</fsummary>
+ <type>
+ <v>Args = term()</v>
+ <d>Last argument to <c>start_link/4</c>.</d>
+ <v>State = term()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Makes necessary initializations and returns the initial channel
+ state if the initializations succeed.
+ </p>
+ <p>For more detailed information on time-outs, see Section
+ <seealso marker="#cb_timeouts">Callback timeouts</seealso>. </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:handle_call(Msg, From, State) -> Result</name>
+ <fsummary>Handles messages sent by calling
+ <c>call/[2,3]</c>.</fsummary>
+ <type>
+ <v>Msg = term()</v>
+ <v>From = opaque()</v>
+ <d>Is to be used as argument to
+ <seealso marker="#reply-2">reply/2</seealso></d>
+ <v>State = term()</v>
+ <v>Result = {reply, Reply, NewState} | {reply, Reply, NewState, timeout()}
+ | {noreply, NewState} | {noreply , NewState, timeout()}
+ | {stop, Reason, Reply, NewState} | {stop, Reason, NewState} </v>
+ <v>Reply = term()</v>
+ <d>Will be the return value of <seealso marker="#call-2">call/[2,3]</seealso></d>
+ <v>NewState = term()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Handles messages sent by calling
+ <seealso marker="#call-2">call/[2,3]</seealso>
+ </p>
+ <p>For more detailed information on time-outs,, see Section
+ <seealso marker="#cb_timeouts">Callback timeouts</seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:handle_cast(Msg, State) -> Result</name>
+ <fsummary>Handles messages sent by calling
+ <c>cast/2</c>.</fsummary>
+ <type>
+ <v>Msg = term()</v>
+ <v>State = term()</v>
+ <v>Result = {noreply, NewState} | {noreply, NewState, timeout()}
+ | {stop, Reason, NewState}</v>
+ <v>NewState = term() </v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Handles messages sent by calling
+ <c>cast/2</c>.
+ </p>
+ <p>For more detailed information on time-outs, see Section
+ <seealso marker="#cb_timeouts">Callback timeouts</seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:handle_msg(Msg, State) -> {ok, State} |
+ {stop, ChannelId, State}</name>
+
+ <fsummary>Handles other messages than SSH connection protocol,
+ call, or cast messages sent to the channel.</fsummary>
+ <type>
+ <v>Msg = timeout | term()</v>
+ <v>ChannelId = <seealso marker="ssh#type-channel_id">ssh:channel_id()</seealso></v>
+ <v>State = term() </v>
+ </type>
+ <desc>
+ <p>Handles other messages than SSH Connection Protocol, call, or
+ cast messages sent to the channel.
+ </p>
+
+ <p>Possible Erlang 'EXIT' messages is to be handled by this
+ 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>
+ <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
+ returns successfully. This is especially useful if the
+ server wants to send a message to the client without first
+ receiving a message from it. If the message is not
+ useful for your particular scenario, ignore it by
+ immediately returning <c>{ok, State}</c>.
+ </p></item>
+ </taglist>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:handle_ssh_msg(Msg, State) -> {ok, State} | {stop,
+ ChannelId, State}</name>
+ <fsummary>Handles <c>ssh</c> connection protocol messages.</fsummary>
+ <type>
+ <v>Msg = ssh_connection:event()</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>.
+ </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>
+ <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>
+ </taglist>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:terminate(Reason, State) -> _</name>
+ <fsummary>Does cleaning up before channel process termination.
+ </fsummary>
+ <type>
+ <v>Reason = term()</v>
+ <v>State = term()</v>
+ </type>
+ <desc>
+ <p>This function is called by a channel process when it is
+ about to terminate. Before this function is called, <seealso
+ marker="ssh_connection#close-2"> ssh_connection:close/2
+ </seealso> is called, if it has not been called earlier.
+ This function does any necessary cleaning
+ up. When it returns, the channel process terminates with
+ reason <c>Reason</c>. The return value is ignored.
+ </p>
+ </desc>
+ </func>
+
+ </funcs>
+
+</erlref>
diff --git a/lib/ssh/doc/src/ssh_client_key_api.xml b/lib/ssh/doc/src/ssh_client_key_api.xml
index a1cd9d4b02..bc77756147 100644
--- a/lib/ssh/doc/src/ssh_client_key_api.xml
+++ b/lib/ssh/doc/src/ssh_client_key_api.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2012</year>
- <year>2016</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -41,7 +41,7 @@
see the <seealso marker="SSH_app"> ssh(6)</seealso> application manual.</p>
</description>
- <section>
+ <!-- section>
<title>DATA TYPES</title>
<p>Type definitions that are used more than once in this module,
@@ -56,28 +56,46 @@
<tag><c>string() =</c></tag>
<item><p><c>[byte()]</c></p></item>
<tag><c>public_key() =</c></tag>
- <item><p><c>#'RSAPublicKey'{}| {integer(), #'Dss-Parms'{}}| term()</c></p></item>
+ <item><p><c>#'RSAPublicKey'{}
+ | {integer(),#'Dss-Parms'{}}
+ | {#'ECPoint'{},{namedCurve,Curve::string()}}</c></p></item>
<tag><c>private_key() =</c></tag>
- <item><p><c>#'RSAPrivateKey'{} | #'DSAPrivateKey'{} | term()</c></p></item>
+ <item><p><c>#'RSAPrivateKey'{}
+ | #'DSAPrivateKey'{}
+ | #'ECPrivateKey'{}</c></p></item>
<tag><c>public_key_algorithm() =</c></tag>
- <item><p><c>'ssh-rsa'| 'ssh-dss' | atom()</c></p></item>
+ <item><p><c>'ssh-rsa' | 'ssh-dss'
+ | 'rsa-sha2-256' | 'rsa-sha2-384' | 'rsa-sha2-512'
+ | 'ecdsa-sha2-nistp256' | 'ecdsa-sha2-nistp384' | 'ecdsa-sha2-nistp521' </c></p></item>
</taglist>
- </section>
+ </section -->
+
+ <datatypes>
+ <datatype>
+ <name name="client_key_cb_options"/>
+ <desc>
+ <p>Options provided to <seealso marker="ssh#connect-3">ssh:connect/[3,4]</seealso>.
+ </p>
+ <p>The option list given in the
+ <seealso marker="ssh#type-key_cb_common_option"><c>key_cb</c></seealso>
+ option is available with the key <c>key_cb_private</c>.
+ </p>
+ </desc>
+ </datatype>
+ </datatypes>
<funcs>
<func>
- <name>Module:add_host_key(HostNames, Key, ConnectOptions) -> ok | {error, Reason}</name>
+ <name>Module:add_host_key(HostNames, PublicHostKey, ConnectOptions) -> ok | {error, Reason}</name>
<fsummary>Adds a host key to the set of trusted host keys.</fsummary>
<type>
- <v>HostNames = string()</v>
- <d>Description of the host that owns the <c>PublicKey</c>.</d>
+ <v>HostNames = string()</v>
+ <d>Description of the host that owns the <c>PublicHostKey</c>.</d>
- <v>Key = public_key()</v>
- <d>Normally an RSA or DSA public key, but handling of other public keys can be added.</d>
+ <v>PublicHostKey = <seealso marker="public_key:public_key#type-public_key">public_key:public_key()</seealso></v>
+ <d>Of ECDSA keys, only the Normally an RSA, DSA or ECDSA public key, but handling of other public keys can be added.</d>
- <v>ConnectOptions = proplists:proplist()</v>
- <d>Options provided to <seealso marker="ssh#connect-3">ssh:connect/[3,4]</seealso></d>
- <v>Reason = term().</v>
+ <v>ConnectOptions = <seealso marker="#type-client_key_cb_options">client_key_cb_options()</seealso></v>
</type>
<desc>
<p>Adds a host key to the set of trusted host keys.</p>
@@ -88,18 +106,16 @@
<name>Module:is_host_key(Key, Host, Algorithm, ConnectOptions) -> Result</name>
<fsummary>Checks if a host key is trusted.</fsummary>
<type>
- <v>Key = public_key() </v>
- <d>Normally an RSA or DSA public key, but handling of other public keys can be added.</d>
+ <v>Key = <seealso marker="public_key:public_key#type-public_key">public_key:public_key()</seealso></v>
+ <d>Normally an RSA, DSA or ECDSA public key, but handling of other public keys can be added.</d>
<v>Host = string()</v>
<d>Description of the host.</d>
- <v>Algorithm = public_key_algorithm()</v>
- <d>Host key algorithm. Is to support <c>'ssh-rsa'| 'ssh-dss'</c>, but more algorithms
- can be handled.</d>
+ <v>Algorithm = <seealso marker="ssh#type-pubkey_alg">ssh:pubkey_alg()</seealso></v>
+ <d>Host key algorithm.</d>
- <v>ConnectOptions = proplists:proplist() </v>
- <d>Options provided to <seealso marker="ssh#connect-3">ssh:connect/[3,4]</seealso>.</d>
+ <v>ConnectOptions = <seealso marker="#type-client_key_cb_options">client_key_cb_options()</seealso></v>
<v>Result = boolean()</v>
</type>
@@ -110,17 +126,15 @@
<func>
<name>Module:user_key(Algorithm, ConnectOptions) ->
- {ok, PrivateKey} | {error, Reason}</name>
+ {ok, PrivateKey} | {error, Reason}</name>
<fsummary>Fetches the users <em>public key</em> matching the <c>Algorithm</c>.</fsummary>
<type>
- <v>Algorithm = public_key_algorithm()</v>
- <d>Host key algorithm. Is to support <c>'ssh-rsa'| 'ssh-dss'</c> but more algorithms
- can be handled.</d>
+ <v>Algorithm = <seealso marker="ssh#type-pubkey_alg">ssh:pubkey_alg()</seealso></v>
+ <d>Host key algorithm.</d>
- <v>ConnectOptions = proplists:proplist()</v>
- <d>Options provided to <seealso marker="ssh#connect-3">ssh:connect/[3,4]</seealso></d>
+ <v>ConnectOptions = <seealso marker="#type-client_key_cb_options">client_key_cb_options()</seealso></v>
- <v>PrivateKey = private_key()</v>
+ <v>PrivateKey = <seealso marker="public_key:public_key#type-private_key">public_key:private_key()</seealso></v>
<d>Private key of the user matching the <c>Algorithm</c>.</d>
<v>Reason = term()</v>
diff --git a/lib/ssh/doc/src/ssh_connection.xml b/lib/ssh/doc/src/ssh_connection.xml
index 150d46a9a2..8e1cf156a8 100644
--- a/lib/ssh/doc/src/ssh_connection.xml
+++ b/lib/ssh/doc/src/ssh_connection.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2008</year>
- <year>2015</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -43,10 +43,10 @@
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, ssh_connection_ref(), ssh_event_msg()}]]></c>.
- If the <seealso marker="ssh_channel">ssh_channel</seealso> behavior is used to
+ <c><![CDATA[{ssh_cm, connection_ref(), ssh_event_msg()}]]></c>.
+ 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_channel#Module:handle_ssh_msg-2">handle_ssh_msg/2</seealso>.</p>
+ <seealso marker="ssh_client_channel#Module:handle_ssh_msg-2">handle_ssh_msg/2</seealso>.</p>
</description>
<section>
@@ -63,10 +63,10 @@
<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>ssh_connection_ref() =</c></tag>
+ <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>ssh_channel_id() =</c></tag>
+ <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
@@ -75,7 +75,7 @@
<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, ssh_connection_ref(), ssh_event_msg()}</c></p></item>
+ <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>
@@ -86,12 +86,12 @@
<tag><em>data_events()</em></tag>
<item>
<taglist>
- <tag><c><![CDATA[{data, ssh_channel_id(), ssh_data_type_code(), Data :: binary()}]]></c></tag>
+ <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, ssh_channel_id()}]]></c></tag>
+ <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>.
@@ -103,7 +103,7 @@
<item>
<taglist>
- <tag><c><![CDATA[{signal, ssh_channel_id(), ssh_signal()}]]></c></tag>
+ <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
@@ -111,7 +111,7 @@
referred to are on OS-level and not something generated by an
Erlang program.</p></item>
- <tag><c><![CDATA[{exit_signal, ssh_channel_id(), ExitSignal :: string(), ErrorMsg ::string(),
+ <tag><c><![CDATA[{exit_signal, channel_id(), ExitSignal :: string(), ErrorMsg ::string(),
LanguageString :: string()}]]></c></tag>
<item><p>A remote execution can terminate violently because of a signal.
@@ -119,7 +119,7 @@
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>
- <tag><c><![CDATA[{exit_status, ssh_channel_id(), ExitStatus :: integer()}]]></c></tag>
+ <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
@@ -127,11 +127,11 @@
<seealso marker="ssh_connection#exit_status-3">
ssh_connection:exit_status/3</seealso>.</p></item>
- <tag><c><![CDATA[{closed, ssh_channel_id()}]]></c></tag>
+ <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_channel">ssh_channel</seealso> behavior.</p></item>
+ <seealso marker="ssh_client_channel">ssh_client_channel</seealso> behavior.</p></item>
</taglist>
</item>
@@ -149,14 +149,14 @@
with the boolean value of <c>WantReply</c> as the second argument.</p>
<taglist>
- <tag><c><![CDATA[{env, ssh_channel_id(), WantReply :: boolean(),
+ <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, ssh_channel_id(),
+ <tag><c><![CDATA[{pty, channel_id(),
WantReply :: boolean(), {Terminal :: string(), CharWidth :: integer(),
RowHeight :: integer(), PixelWidth :: integer(), PixelHeight :: integer(),
TerminalModes :: [{Opcode :: atom() | integer(),
@@ -181,13 +181,13 @@
<seealso marker="ssh_connection#shell-2"> ssh_connection:shell/2</seealso>.
</p></item>
- <tag><c><![CDATA[{window_change, ssh_channel_id(), CharWidth() :: integer(),
+ <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
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>
- <tag><c><![CDATA[{exec, ssh_channel_id(),
+ <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
@@ -204,18 +204,18 @@
<name>adjust_window(ConnectionRef, ChannelId, NumOfBytes) -> ok</name>
<fsummary>Adjusts the SSH flow control window.</fsummary>
<type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
+ <v>ConnectionRef = connection_ref()</v>
+ <v>ChannelId = channel_id()</v>
<v>NumOfBytes = integer()</v>
</type>
<desc>
<p>Adjusts the SSH flow control window. This is to be done by both the
client- and server-side channel processes.</p>
- <note><p>Channels implemented with the <seealso marker="ssh_channel"> ssh_channel</seealso>
+ <note><p>Channels implemented with the <seealso marker="ssh_client_channel"> ssh_client_channel</seealso>
behavior do not normally need to call this function as flow control
is handled by the behavior. The behavior adjusts the window every time
- the callback <seealso marker="ssh_channel#Module:handle_ssh_msg-2">
+ the callback <seealso marker="ssh_client_channel#Module:handle_ssh_msg-2">
handle_ssh_msg/2</seealso> returns after processing channel data.</p></note>
</desc>
</func>
@@ -224,17 +224,17 @@
<name>close(ConnectionRef, ChannelId) -> ok</name>
<fsummary>Sends a close message on the channel <c>ChannelId</c>.</fsummary>
<type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
+ <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_channel</c>
+ <note><p>This function is called by the <c>ssh_client_channel</c>
behavior when the channel is terminated, see <seealso
- marker="ssh_channel"> ssh_channel(3)</seealso>. Thus, channels implemented
+ marker="ssh_client_channel"> ssh_client_channel(3)</seealso>. Thus, channels implemented
with the behavior are not to call this function explicitly.</p></note>
</desc>
</func>
@@ -244,8 +244,8 @@
{error, reason()}</name>
<fsummary>Requests that the server starts the execution of the given command.</fsummary>
<type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
+ <v>ConnectionRef = connection_ref()</v>
+ <v>ChannelId = channel_id()</v>
<v>Command = string()</v>
<v>Timeout = timeout()</v>
</type>
@@ -256,28 +256,28 @@
request is a one-time execution that closes the channel when it is done.</p>
<taglist>
- <tag><c>N x {ssh_cm, ssh_connection_ref(),
- {data, ssh_channel_id(), ssh_data_type_code(), Data :: binary()}}</c></tag>
+ <tag><c>N x {ssh_cm, connection_ref(),
+ {data, channel_id(), ssh_data_type_code(), 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, ssh_connection_ref(), {eof, ssh_channel_id()}}</c></tag>
+ <tag><c>0 or 1 x {ssh_cm, connection_ref(), {eof, channel_id()}}</c></tag>
<item><p>Indicates that no more data is to be sent.</p></item>
<tag><c>0 or 1 x {ssh_cm,
- ssh_connection_ref(), {exit_signal,
- ssh_channel_id(), ExitSignal :: string(), ErrorMsg :: string(), LanguageString :: string()}}</c></tag>
+ connection_ref(), {exit_signal,
+ channel_id(), 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, ssh_connection_ref(), {exit_status,
- ssh_channel_id(), ExitStatus :: integer()}}</c></tag>
+ <tag><c>0 or 1 x {ssh_cm, connection_ref(), {exit_status,
+ channel_id(), 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, ssh_connection_ref(),
- {closed, ssh_channel_id()}}</c></tag>
- <item><p>Indicates that the <c>ssh_channel</c> started for the
+ <tag><c>1 x {ssh_cm, connection_ref(),
+ {closed, channel_id()}}</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>
</desc>
@@ -287,8 +287,8 @@
<name>exit_status(ConnectionRef, ChannelId, Status) -> ok</name>
<fsummary>Sends the exit status of a command to the client.</fsummary>
<type>
- <v>ConnectionRef = ssh_connection_ref() </v>
- <v>ChannelId = ssh_channel_id()</v>
+ <v>ConnectionRef = connection_ref() </v>
+ <v>ChannelId = channel_id()</v>
<v>Status = integer()</v>
</type>
<desc>
@@ -304,8 +304,8 @@
<fsummary>Sends an SSH Connection Protocol <c>pty_req</c>,
to allocate a pseudo-terminal.</fsummary>
<type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
+ <v>ConnectionRef = connection_ref()</v>
+ <v>ChannelId = channel_id()</v>
<v>Options = proplists:proplist()</v>
</type>
<desc>
@@ -342,10 +342,10 @@
<name>reply_request(ConnectionRef, WantReply, Status, ChannelId) -> ok</name>
<fsummary>Sends status replies to requests that want such replies.</fsummary>
<type>
- <v>ConnectionRef = ssh_connection_ref()</v>
+ <v>ConnectionRef = connection_ref()</v>
<v>WantReply = boolean()</v>
<v>Status = ssh_request_status()</v>
- <v>ChannelId = ssh_channel_id()</v>
+ <v>ChannelId = channel_id()</v>
</type>
<desc>
<p>Sends status replies to requests where the requester has
@@ -364,8 +364,8 @@
ok | {error, timeout} | {error, closed}</name>
<fsummary>Sends channel data.</fsummary>
<type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
+ <v>ConnectionRef = connection_ref()</v>
+ <v>ChannelId = channel_id()</v>
<v>Data = binary()</v>
<v>Type = ssh_data_type_code()</v>
<v>Timeout = timeout()</v>
@@ -383,8 +383,8 @@
<name>send_eof(ConnectionRef, ChannelId) -> ok | {error, closed}</name>
<fsummary>Sends EOF on channel <c>ChannelId</c>.</fsummary>
<type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
+ <v>ConnectionRef = connection_ref()</v>
+ <v>ChannelId = channel_id()</v>
</type>
<desc>
<p>Sends EOF on channel <c>ChannelId</c>.</p>
@@ -394,10 +394,10 @@
<func>
<name>session_channel(ConnectionRef, Timeout) -></name>
<name>session_channel(ConnectionRef, InitialWindowSize,
- MaxPacketSize, Timeout) -> {ok, ssh_channel_id()} | {error, reason()}</name>
+ MaxPacketSize, Timeout) -> {ok, channel_id()} | {error, reason()}</name>
<fsummary>Opens a channel for an SSH session.</fsummary>
<type>
- <v>ConnectionRef = ssh_connection_ref()</v>
+ <v>ConnectionRef = connection_ref()</v>
<v>InitialWindowSize = integer()</v>
<v>MaxPacketSize = integer()</v>
<v>Timeout = timeout()</v>
@@ -415,8 +415,8 @@
<fsummary>Environment variables can be passed to the
shell/command to be started later.</fsummary>
<type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
+ <v>ConnectionRef = connection_ref()</v>
+ <v>ChannelId = channel_id()</v>
<v>Var = string()</v>
<v>Value = string()</v>
<v>Timeout = timeout()</v>
@@ -428,18 +428,22 @@
</func>
<func>
- <name>shell(ConnectionRef, ChannelId) -> ssh_request_status() | {error, closed}
+ <name>shell(ConnectionRef, ChannelId) -> ok | failure | {error, closed}
</name>
<fsummary>Requests that the user default shell (typically defined in
/etc/passwd in Unix systems) is to be executed at the server end.</fsummary>
<type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
+ <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
at the server end.</p>
+ <p>Note: the return value is <c>ok</c> instead of <c>success</c> unlike in other
+ functions in this module. This is a fault that was introduced so long ago that
+ any change would break a large number of existing software.
+ </p>
</desc>
</func>
@@ -448,8 +452,8 @@
{error, reason()}</name>
<fsummary>Requests to execute a predefined subsystem on the server.</fsummary>
<type>
- <v>ConnectionRef = ssh_connection_ref()</v>
- <v>ChannelId = ssh_channel_id()</v>
+ <v>ConnectionRef = connection_ref()</v>
+ <v>ChannelId = channel_id()</v>
<v>Subsystem = string()</v>
<v>Timeout = timeout()</v>
</type>
diff --git a/lib/ssh/doc/src/ssh_protocol.xml b/lib/ssh/doc/src/ssh_protocol.xml
index a0032ab449..0d99a96997 100644
--- a/lib/ssh/doc/src/ssh_protocol.xml
+++ b/lib/ssh/doc/src/ssh_protocol.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2013</year><year>2016</year>
+ <year>2013</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -87,8 +87,10 @@
connection, and all channels are flow-controlled. Typically an
SSH client will open a channel, send data/commands, receive
data/"control information" and when it is done close the
- channel. The <seealso
- marker="ssh_channel">ssh_channel</seealso> behaviour makes it easy to
+ channel. The
+ <seealso marker="ssh_client_channel">ssh_client_channel</seealso> /
+ <seealso marker="ssh_server_channel">ssh_server_channel</seealso> (Replaces ssh_daemon_channel)
+ behaviours makes it easy to
write your own SSH client/server processes that use flow
control. It handles generic parts of SSH channel management and
lets you focus on the application logic.
diff --git a/lib/ssh/doc/src/ssh_server_channel.xml b/lib/ssh/doc/src/ssh_server_channel.xml
new file mode 100644
index 0000000000..31ba9a3231
--- /dev/null
+++ b/lib/ssh/doc/src/ssh_server_channel.xml
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2009</year>
+ <year>2018</year>
+ <holder>Ericsson AB, All Rights Reserved</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ The Initial Developer of the Original Code is Ericsson AB.
+ </legalnotice>
+ <title>ssh_server_channel</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ </header>
+ <module>ssh_server_channel</module>
+ <modulesummary>-behaviour(ssh_server_channel). (Replaces ssh_daemon_channel)
+ </modulesummary>
+ <description>
+ <note>
+ <p>This module replaces ssh_daemon_channel.</p>
+ <p>The old module is still available for compatibility, but should not be used for new programs.
+ The old module will not be maintained except for some error corrections
+ </p>
+ </note>
+
+ <p>SSH services (clients and servers) are implemented as channels
+ that are multiplexed over an SSH connection and communicates over
+ the <url href="http://www.ietf.org/rfc/rfc4254.txt"> SSH
+ Connection Protocol</url>. This module provides a callback API
+ that takes care of generic channel aspects for daemons, such as flow control
+ and close messages. It lets the callback functions take care of
+ the service (application) specific parts. This behavior also ensures
+ that the channel process honors the principal of an OTP-process so
+ that it can be part of a supervisor tree. This is a requirement of
+ channel processes implementing a subsystem that will be added to
+ the <c>ssh</c> applications supervisor tree.
+ </p>
+
+ <note><p>When implementing a client subsystem handler, use
+ <seealso marker="ssh_client_channel">-behaviour(ssh_client_channel)</seealso> instead.
+ </p>
+ </note>
+
+ </description>
+
+ <section>
+ <title>Callback Functions</title>
+ <p>
+ The following functions are to be exported from a
+ <c>ssh_server_channel</c> callback module.
+ </p>
+ </section>
+
+ <funcs>
+ <func>
+ <name>Module:init(Args) -> {ok, State} | {ok, State, timeout()} |
+ {stop, Reason}</name>
+ <fsummary>Makes necessary initializations and returns the
+ initial channel state if the initializations succeed.</fsummary>
+ <type>
+ <v>Args = term()</v>
+ <d>Last argument to <c>start_link/4</c>.</d>
+ <v>State = term()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Makes necessary initializations and returns the initial channel
+ state if the initializations succeed.
+ </p>
+ <p>The time-out values that can be returned
+ have the same semantics as in a <seealso marker="stdlib:gen_server">gen_server</seealso>.
+ If the time-out occurs, <seealso marker="#Module:handle_msg-2">handle_msg/2</seealso>
+ is called as <c>handle_msg(timeout, State)</c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:handle_msg(Msg, State) -> {ok, State} |
+ {stop, ChannelId, State}</name>
+
+ <fsummary>Handles other messages than SSH connection protocol,
+ call, or cast messages sent to the channel.</fsummary>
+ <type>
+ <v>Msg = timeout | term()</v>
+ <v>ChannelId = <seealso marker="ssh#type-channel_id">ssh:channel_id()</seealso></v>
+ <v>State = term() </v>
+ </type>
+ <desc>
+ <p>Handles other messages than SSH Connection Protocol, call, or
+ cast messages sent to the channel.
+ </p>
+
+ <p>Possible Erlang 'EXIT' messages is to be handled by this
+ 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>
+ <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
+ receiving a message from it. If the message is not
+ useful for your particular scenario, ignore it by
+ immediately returning <c>{ok, State}</c>.
+ </p></item>
+ </taglist>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:handle_ssh_msg(Msg, State) -> {ok, State} | {stop,
+ ChannelId, State}</name>
+ <fsummary>Handles <c>ssh</c> connection protocol messages.</fsummary>
+ <type>
+ <v>Msg = ssh_connection:event()</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>.
+ </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>
+ <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>
+ </taglist>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:terminate(Reason, State) -> _</name>
+ <fsummary>Does cleaning up before channel process termination.
+ </fsummary>
+ <type>
+ <v>Reason = term()</v>
+ <v>State = term()</v>
+ </type>
+ <desc>
+ <p>This function is called by a channel process when it is
+ about to terminate. Before this function is called, <seealso
+ marker="ssh_connection#close-2"> ssh_connection:close/2
+ </seealso> is called, if it has not been called earlier.
+ This function does any necessary cleaning
+ up. When it returns, the channel process terminates with
+ reason <c>Reason</c>. The return value is ignored.
+ </p>
+ </desc>
+ </func>
+
+ </funcs>
+
+</erlref>
diff --git a/lib/ssh/doc/src/ssh_server_key_api.xml b/lib/ssh/doc/src/ssh_server_key_api.xml
index a0694ca8d9..e2a31bd5f5 100644
--- a/lib/ssh/doc/src/ssh_server_key_api.xml
+++ b/lib/ssh/doc/src/ssh_server_key_api.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2012</year>
- <year>2015</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -41,7 +41,7 @@
see the <seealso marker="SSH_app"> ssh(6)</seealso> application manual.</p>
</description>
- <section>
+ <!-- section>
<title>DATA TYPES</title>
<p>Type definitions that are used more than once in this module,
@@ -57,27 +57,52 @@
<tag><c>string() =</c></tag>
<item><p><c>[byte()]</c></p></item>
<tag><c>public_key() =</c></tag>
- <item><p><c>#'RSAPublicKey'{}| {integer(), #'Dss-Parms'{}}| term()</c></p></item>
+ <item><p><c>#'RSAPublicKey'{}
+ | {integer(),#'Dss-Parms'{}}
+ | {#'ECPoint'{},{namedCurve,Curve::string()}}</c></p></item>
<tag><c>private_key() =</c></tag>
- <item><p><c>#'RSAPrivateKey'{} | #'DSAPrivateKey'{} | term()</c></p></item>
+ <item><p><c>#'RSAPrivateKey'{}
+ | #'DSAPrivateKey'{}
+ | #'ECPrivateKey'{}</c></p></item>
<tag><c>public_key_algorithm() =</c></tag>
- <item><p><c>'ssh-rsa'| 'ssh-dss' | atom()</c></p></item>
+ <item><p><c>'ssh-rsa' | 'ssh-dss'
+ | 'rsa-sha2-256' | 'rsa-sha2-384' | 'rsa-sha2-512'
+ | 'ecdsa-sha2-nistp256' | 'ecdsa-sha2-nistp384' | 'ecdsa-sha2-nistp521' </c></p></item>
</taglist>
- </section>
+ </section -->
+ <datatypes>
+ <datatype>
+ <name name="daemon_key_cb_options"/>
+ <desc>
+ <p>Options provided to <seealso marker="ssh#daemon-2">ssh:daemon/2,3</seealso>.
+ </p>
+ <p>The option list given in the
+ <seealso marker="ssh#type-key_cb_common_option"><c>key_cb</c></seealso>
+ option is available with the key <c>key_cb_private</c>.
+ </p>
+ </desc>
+ </datatype>
+ </datatypes>
+
<funcs>
<func>
<name>Module:host_key(Algorithm, DaemonOptions) ->
{ok, Key} | {error, Reason}</name>
<fsummary>Fetches the host’s private key.</fsummary>
<type>
- <v>Algorithm = public_key_algorithm()</v>
- <d>Host key algorithm. Is to support <c>'ssh-rsa' | 'ssh-dss'</c>, but more algorithms
- can be handled.</d>
- <v>DaemonOptions = proplists:proplist()</v>
- <d>Options provided to <seealso marker="ssh#daemon-2">ssh:daemon/[2,3]</seealso>.</d>
- <v>Key = private_key()</v>
- <d>Private key of the host matching the <c>Algorithm</c>.</d>
+ <v>Algorithm = <seealso marker="ssh#type-pubkey_alg">ssh:pubkey_alg()</seealso></v>
+ <d>Host key algorithm.</d>
+
+ <v>DaemonOptions = <seealso marker="#type-daemon_key_cb_options">daemon_key_cb_options()</seealso></v>
+
+ <v>PrivateKey = <seealso marker="public_key:public_key#type-private_key">public_key:private_key()</seealso>
+ | <seealso marker="crypto:crypto#type-engine_key_ref">crypto:engine_key_ref()</seealso>
+ </v>
+
+ <d>Private key of the host matching the <c>Algorithm</c>.
+ It may be a reference to a 'ssh-rsa', rsa-sha2-* or 'ssh-dss' (NOT ecdsa) key stored in a loaded Engine.</d>
+
<v>Reason = term()</v>
</type>
<desc>
@@ -86,15 +111,17 @@
</func>
<func>
- <name>Module:is_auth_key(Key, User, DaemonOptions) -> Result</name>
+ <name>Module:is_auth_key(PublicUserKey, User, DaemonOptions) -> Result</name>
<fsummary>Checks if the user key is authorized.</fsummary>
<type>
- <v>Key = public_key()</v>
- <d>Normally an RSA or DSA public key, but handling of other public keys can be added</d>
+ <v>PublicUserKey = <seealso marker="public_key:public_key#type-public_key">public_key:public_key()</seealso></v>
+ <d>Normally an RSA, DSA or ECDSA public key, but handling of other public keys can be added</d>
+
<v>User = string()</v>
<d>User owning the public key.</d>
- <v>DaemonOptions = proplists:proplist()</v>
- <d>Options provided to <seealso marker="ssh#daemon-2">ssh:daemon/[2,3]</seealso>.</d>
+
+ <v>DaemonOptions = <seealso marker="#type-daemon_key_cb_options">daemon_key_cb_options()</seealso></v>
+
<v>Result = boolean()</v>
</type>
<desc>
diff --git a/lib/ssh/doc/src/ssh_sftp.xml b/lib/ssh/doc/src/ssh_sftp.xml
index ed7fbf9cf3..ea55126cb3 100644
--- a/lib/ssh/doc/src/ssh_sftp.xml
+++ b/lib/ssh/doc/src/ssh_sftp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2005</year><year>2017</year>
+ <year>2005</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -46,9 +46,9 @@
<taglist>
<tag><c>reason()</c></tag>
<item>
- <p>= <c>atom()</c> A description of the reason why an operation failed.</p>
+ <p>= <c>atom() | string() | tuple() </c>A description of the reason why an operation failed.</p>
<p>
- The value is formed from the sftp error codes in the protocol-level responses as defined in
+ The <c>atom()</c> value is formed from the sftp error codes in the protocol-level responses as defined in
<url href="https://tools.ietf.org/id/draft-ietf-secsh-filexfer-13.txt">draft-ietf-secsh-filexfer-13.txt</url>
section 9.1.
</p>
@@ -57,9 +57,13 @@
E.g. the error code <c>SSH_FX_NO_SUCH_FILE</c>
will cause the <c>reason()</c> to be <c>no_such_file</c>.
</p>
+ <p>The <c>string()</c> reason is the error information from the server in case of an exit-signal. If that information is empty, the reason is the exit signal name.
+ </p>
+ <p>The <c>tuple()</c> reason are other errors like the <c>{exit_status,integer()}</c> if the exit status is not 0.
+ </p>
</item>
- <tag><c>ssh_connection_ref() =</c></tag>
+ <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>
@@ -464,11 +468,16 @@
<v>FileInfo = record()</v>
</type>
<desc>
- <p>Returns a <c><![CDATA[file_info]]></c> record from the file specified by
+ <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
<seealso marker="kernel:file#read_file_info-2">file:read_file_info/2</seealso>
for information about the record.
</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>
+ on how to get information on links instead.
+ </p>
</desc>
</func>
@@ -541,7 +550,7 @@
<fsummary>Starts an SFTP client.</fsummary>
<type>
<v>Host = string()</v>
- <v>ConnectionRef = ssh_connection_ref()</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>
diff --git a/lib/ssh/doc/src/ssh_sftpd.xml b/lib/ssh/doc/src/ssh_sftpd.xml
index 1be29b3b29..3b34150e98 100644
--- a/lib/ssh/doc/src/ssh_sftpd.xml
+++ b/lib/ssh/doc/src/ssh_sftpd.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2005</year><year>2016</year>
+ <year>2005</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -44,8 +44,7 @@
<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
- <c>ssh_channel</c> behavior, see the
- <seealso marker="ssh_channel">ssh_channel(3)</seealso> manual page.</p></item>
+ <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>
diff --git a/lib/ssh/doc/src/usersguide.xml b/lib/ssh/doc/src/usersguide.xml
index 70051ba771..38ffa48cde 100644
--- a/lib/ssh/doc/src/usersguide.xml
+++ b/lib/ssh/doc/src/usersguide.xml
@@ -4,7 +4,7 @@
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2012</year><year>2016</year>
+ <year>2012</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -36,4 +36,5 @@
</description>
<xi:include href="introduction.xml"/>
<xi:include href="using_ssh.xml"/>
+ <xi:include href="configure_algos.xml"/>
</part>
diff --git a/lib/ssh/doc/src/using_ssh.xml b/lib/ssh/doc/src/using_ssh.xml
index ab307624e6..80662e9a70 100644
--- a/lib/ssh/doc/src/using_ssh.xml
+++ b/lib/ssh/doc/src/using_ssh.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2012</year>
- <year>2017</year>
+ <year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -298,6 +298,7 @@ ok = erl_tar:close(HandleRead),
</section>
<section>
+ <marker id="usersguide_creating_a_subsystem"/>
<title>Creating a Subsystem</title>
<p>A small <c>ssh</c> subsystem that echoes N bytes can be implemented as shown
@@ -305,7 +306,7 @@ ok = erl_tar:close(HandleRead),
<code type="erl" >
-module(ssh_echo_server).
--behaviour(ssh_daemon_channel).
+-behaviour(ssh_server_channel). % replaces ssh_daemon_channel
-record(state, {
n,
id,
@@ -383,7 +384,7 @@ terminate(_Reason, _State) ->
{ssh_msg, &lt;0.57.0>, {closed, 0}}
7> {error, closed} = ssh_connection:send(ConnectionRef, ChannelId, "10", infinity).
</code>
-<p>See also <seealso marker="ssh_channel"> ssh_channel(3)</seealso>.</p>
+<p>See also <seealso marker="ssh_client_channel">ssh_client_channel(3)</seealso> (replaces ssh_channel(3)).</p>
</section>
diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile
index 9e8d80c71f..6d64a45112 100644
--- a/lib/ssh/src/Makefile
+++ b/lib/ssh/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2017. All Rights Reserved.
+# Copyright Ericsson AB 2004-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -40,42 +40,44 @@ RELSYSDIR = $(RELEASE_PATH)/lib/ssh-$(VSN)
# Behaviour (api) modules are first so they are compiled when
# the compiler reaches a callback module using them.
BEHAVIOUR_MODULES= \
- ssh_sftpd_file_api \
- ssh_channel \
- ssh_daemon_channel \
ssh_client_key_api \
- ssh_server_key_api
+ ssh_daemon_channel \
+ ssh_server_channel \
+ ssh_server_key_api \
+ ssh_sftpd_file_api \
+ ssh_channel \
+ ssh_client_channel
MODULES= \
ssh \
- ssh_sup \
- sshc_sup \
- sshd_sup \
- ssh_options \
- ssh_connection_sup \
- ssh_connection \
- ssh_connection_handler \
- ssh_dbg \
- ssh_shell \
- ssh_system_sup \
- ssh_subsystem_sup \
- ssh_channel_sup \
- ssh_acceptor_sup \
ssh_acceptor \
+ ssh_acceptor_sup \
ssh_app \
ssh_auth\
ssh_bits \
ssh_cli \
+ ssh_connection \
+ ssh_connection_handler \
+ ssh_connection_sup \
+ ssh_dbg \
ssh_file \
- ssh_io \
ssh_info \
+ ssh_io \
ssh_message \
ssh_no_io \
+ ssh_options \
+ ssh_server_channel_sup \
ssh_sftp \
ssh_sftpd \
ssh_sftpd_file\
+ ssh_shell \
+ ssh_subsystem_sup \
+ ssh_sup \
+ ssh_system_sup \
ssh_transport \
- ssh_xfer
+ ssh_xfer \
+ sshc_sup \
+ sshd_sup
HRL_FILES =
@@ -97,7 +99,7 @@ APP_TARGET= $(EBIN)/$(APP_FILE)
APPUP_SRC= $(APPUP_FILE).src
APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
-INTERNAL_HRL_FILES = ssh_auth.hrl ssh_connect.hrl ssh_transport.hrl ssh.hrl ssh_userauth.hrl ssh_xfer.hrl ssh_dbg.hrl
+INTERNAL_HRL_FILES = ssh_auth.hrl ssh_connect.hrl ssh_transport.hrl ssh.hrl ssh_userauth.hrl ssh_xfer.hrl
# ----------------------------------------------------
# FLAGS
@@ -169,7 +171,7 @@ $(EBIN)/ssh_connection_handler.$(EMULATOR): ssh_connection_handler.erl ssh.hrl \
$(EBIN)/ssh_shell.$(EMULATOR): ssh_shell.erl ssh_connect.hrl
$(EBIN)/ssh_system_sup.$(EMULATOR): ssh_system_sup.erl ssh.hrl
$(EBIN)/ssh_subsystem_sup.$(EMULATOR): ssh_subsystem_sup.erl
-$(EBIN)/ssh_channel_sup.$(EMULATOR): ssh_channel_sup.erl
+$(EBIN)/ssh_server_channel_sup.$(EMULATOR): ssh_server_channel_sup.erl
$(EBIN)/ssh_acceptor_sup.$(EMULATOR): ssh_acceptor_sup.erl ssh.hrl
$(EBIN)/ssh_acceptor.$(EMULATOR): ssh_acceptor.erl ssh.hrl
$(EBIN)/ssh_app.$(EMULATOR): ssh_app.erl
@@ -208,8 +210,10 @@ $(EBIN)/ssh_transport.$(EMULATOR): ssh_transport.erl \
ssh_transport.hrl ssh.hrl
$(EBIN)/ssh_xfer.$(EMULATOR): ssh_xfer.erl ssh.hrl ssh_xfer.hrl
$(EBIN)/ssh_sftpd_file_api.$(EMULATOR): ssh_sftpd_file_api.erl
+$(EBIN)/ssh_client_channel.$(EMULATOR): ssh_client_channel.erl ssh_connect.hrl
$(EBIN)/ssh_channel.$(EMULATOR): ssh_channel.erl ssh_connect.hrl
$(EBIN)/ssh_daemon_channel.$(EMULATOR): ssh_daemon_channel.erl
+$(EBIN)/ssh_server_channel.$(EMULATOR): ssh_server_channel.erl
$(EBIN)/ssh_client_key_api.$(EMULATOR): ssh_client_key_api.erl \
../../public_key/include/public_key.hrl \
../../public_key/include/OTP-PUB-KEY.hrl \
diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src
index 974292fde1..410061cded 100644
--- a/lib/ssh/src/ssh.app.src
+++ b/lib/ssh/src/ssh.app.src
@@ -12,9 +12,9 @@
ssh_message,
ssh_bits,
ssh_cli,
+ ssh_client_channel,
ssh_client_key_api,
ssh_channel,
- ssh_channel_sup,
ssh_connection,
ssh_connection_handler,
ssh_connection_sup,
@@ -27,6 +27,8 @@
ssh_io,
ssh_info,
ssh_no_io,
+ ssh_server_channel,
+ ssh_server_channel_sup,
ssh_server_key_api,
ssh_sftp,
ssh_sftpd,
@@ -42,10 +44,10 @@
{env, []},
{mod, {ssh_app, []}},
{runtime_dependencies, [
- "crypto-3.7.3",
+ "crypto-4.2",
"erts-6.0",
"kernel-3.0",
- "public_key-1.4",
+ "public_key-1.5.2",
"stdlib-3.3"
]}]}.
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index 5ebab43c30..086fa6e5f8 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -1,7 +1,7 @@
%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,40 +35,57 @@
daemon/1, daemon/2, daemon/3,
daemon_info/1,
default_algorithms/0,
+ chk_algos_opts/1,
stop_listener/1, stop_listener/2, stop_listener/3,
stop_daemon/1, stop_daemon/2, stop_daemon/3,
shell/1, shell/2, shell/3
]).
+%%% "Deprecated" types export:
+-export_type([ssh_daemon_ref/0, ssh_connection_ref/0, ssh_channel_id/0]).
+-opaque ssh_daemon_ref() :: daemon_ref().
+-opaque ssh_connection_ref() :: connection_ref().
+-opaque ssh_channel_id() :: channel_id().
+
+
%%% Type exports
--export_type([ssh_daemon_ref/0,
- ssh_connection_ref/0,
- ssh_channel_id/0,
+-export_type([daemon_ref/0,
+ connection_ref/0,
+ channel_id/0,
+ client_options/0, client_option/0,
+ daemon_options/0, daemon_option/0,
+ common_options/0,
role/0,
subsystem_spec/0,
- subsystem_name/0,
- channel_callback/0,
- channel_init_args/0,
algs_list/0,
+ double_algs/1,
+ modify_algs_list/0,
alg_entry/0,
- simple_algs/0,
- double_algs/0
+ kex_alg/0,
+ pubkey_alg/0,
+ cipher_alg/0,
+ mac_alg/0,
+ compression_alg/0,
+ ip_port/0
]).
--opaque ssh_daemon_ref() :: daemon_ref() .
--opaque ssh_connection_ref() :: connection_ref() .
--opaque ssh_channel_id() :: channel_id().
+
+-opaque daemon_ref() :: pid() .
+-opaque channel_id() :: non_neg_integer().
+-type connection_ref() :: pid(). % should be -opaque, but that gives problems
%%--------------------------------------------------------------------
--spec start() -> ok | {error, term()}.
--spec start(permanent | transient | temporary) -> ok | {error, term()}.
-%%
%% Description: Starts the ssh application. Default type
%% is temporary. see application(3)
%%--------------------------------------------------------------------
+-spec start() -> ok | {error, term()}.
+
start() ->
start(temporary).
+-spec start(Type) -> ok | {error, term()} when
+ Type :: permanent | transient | temporary .
+
start(Type) ->
case application:ensure_all_started(ssh, Type) of
{ok, _} ->
@@ -78,30 +95,32 @@ start(Type) ->
end.
%%--------------------------------------------------------------------
--spec stop() -> ok | {error, term()}.
-%%
%% Description: Stops the ssh application.
%%--------------------------------------------------------------------
+-spec stop() -> ok | {error, term()}.
+
stop() ->
application:stop(ssh).
%%--------------------------------------------------------------------
--spec connect(inet:socket(), proplists:proplist()) -> ok_error(connection_ref()).
+%% Description: Starts an ssh connection.
+%%--------------------------------------------------------------------
+-spec connect(OpenTcpSocket, Options) -> {ok,connection_ref()} | {error,term()} when
+ OpenTcpSocket :: open_socket(),
+ Options :: client_options().
--spec connect(inet:socket(), proplists:proplist(), timeout()) -> ok_error(connection_ref())
- ; (string(), inet:port_number(), proplists:proplist()) -> ok_error(connection_ref()).
+connect(OpenTcpSocket, Options) when is_port(OpenTcpSocket),
+ is_list(Options) ->
+ connect(OpenTcpSocket, Options, infinity).
--spec connect(string(), inet:port_number(), proplists:proplist(), timeout()) -> ok_error(connection_ref()).
-%%
-%% Description: Starts an ssh connection.
-%%--------------------------------------------------------------------
-connect(Socket, UserOptions) when is_port(Socket),
- is_list(UserOptions) ->
- connect(Socket, UserOptions, infinity).
+-spec connect(open_socket(), client_options(), timeout()) ->
+ {ok,connection_ref()} | {error,term()}
+ ; (host(), inet:port_number(), client_options()) ->
+ {ok,connection_ref()} | {error,term()}.
-connect(Socket, UserOptions, Timeout) when is_port(Socket),
- is_list(UserOptions) ->
+connect(Socket, UserOptions, NegotiationTimeout) when is_port(Socket),
+ is_list(UserOptions) ->
case ssh_options:handle_options(client, UserOptions) of
{error, Error} ->
{error, Error};
@@ -110,16 +129,23 @@ connect(Socket, UserOptions, Timeout) when is_port(Socket),
ok ->
{ok, {Host,_Port}} = inet:sockname(Socket),
Opts = ?PUT_INTERNAL_OPT([{user_pid,self()}, {host,Host}], Options),
- ssh_connection_handler:start_connection(client, Socket, Opts, Timeout);
+ ssh_connection_handler:start_connection(client, Socket, Opts, NegotiationTimeout);
{error,SockError} ->
{error,SockError}
end
end;
-connect(Host, Port, UserOptions) when is_integer(Port),
- Port>0,
- is_list(UserOptions) ->
- connect(Host, Port, UserOptions, infinity).
+connect(Host, Port, Options) when is_integer(Port),
+ Port>0,
+ is_list(Options) ->
+ connect(Host, Port, Options, infinity).
+
+
+-spec connect(Host, Port, Options, NegotiationTimeout) -> {ok,connection_ref()} | {error,term()} when
+ Host :: host(),
+ Port :: inet:port_number(),
+ Options :: client_options(),
+ NegotiationTimeout :: timeout().
connect(Host0, Port, UserOptions, Timeout) when is_integer(Port),
Port>0,
@@ -147,7 +173,8 @@ connect(Host0, Port, UserOptions, Timeout) when is_integer(Port),
end.
%%--------------------------------------------------------------------
--spec close(pid()) -> ok.
+-spec close(ConnectionRef) -> ok | {error,term()} when
+ ConnectionRef :: connection_ref() .
%%
%% Description: Closes an ssh connection.
%%--------------------------------------------------------------------
@@ -155,15 +182,25 @@ close(ConnectionRef) ->
ssh_connection_handler:stop(ConnectionRef).
%%--------------------------------------------------------------------
--spec connection_info(pid(), [atom()]) -> [{atom(), term()}].
-%%
%% Description: Retrieves information about a connection.
%%--------------------------------------------------------------------
-connection_info(ConnectionRef, Options) ->
- ssh_connection_handler:connection_info(ConnectionRef, Options).
+-spec connection_info(ConnectionRef, Keys) -> ConnectionInfo when
+ ConnectionRef :: connection_ref(),
+ Keys :: [client_version | server_version | user | peer | sockname],
+ ConnectionInfo :: [{client_version, Version}
+ | {server_version, Version}
+ | {user,string()}
+ | {peer, {inet:hostname(), ip_port()}}
+ | {sockname, ip_port()}
+ ],
+ Version :: {ProtocolVersion, VersionString::string()},
+ ProtocolVersion :: {Major::pos_integer(), Minor::non_neg_integer()} .
+
+connection_info(Connection, Options) ->
+ ssh_connection_handler:connection_info(Connection, Options).
%%--------------------------------------------------------------------
--spec channel_info(pid(), channel_id(), [atom()]) -> [{atom(), term()}].
+-spec channel_info(connection_ref(), channel_id(), [atom()]) -> proplists:proplist().
%%
%% Description: Retrieves information about a connection.
%%--------------------------------------------------------------------
@@ -171,22 +208,21 @@ channel_info(ConnectionRef, ChannelId, Options) ->
ssh_connection_handler:channel_info(ConnectionRef, ChannelId, Options).
%%--------------------------------------------------------------------
--spec daemon(inet:port_number()) -> ok_error(daemon_ref()).
--spec daemon(inet:port_number()|inet:socket(), proplists:proplist()) -> ok_error(daemon_ref()).
--spec daemon(any | inet:ip_address(), inet:port_number(), proplists:proplist()) -> ok_error(daemon_ref())
- ;(socket, inet:socket(), proplists:proplist()) -> ok_error(daemon_ref())
- .
-
%% Description: Starts a server listening for SSH connections
%% on the given port.
%%--------------------------------------------------------------------
+-spec daemon(inet:port_number()) -> {ok,daemon_ref()} | {error,term()}.
+
daemon(Port) ->
daemon(Port, []).
+-spec daemon(inet:port_number()|open_socket(), daemon_options()) -> {ok,daemon_ref()} | {error,term()}.
+
daemon(Socket, UserOptions) when is_port(Socket) ->
try
#{} = Options = ssh_options:handle_options(server, UserOptions),
+
case valid_socket_to_use(Socket, ?GET_OPT(transport,Options)) of
ok ->
{ok, {IP,Port}} = inet:sockname(Socket),
@@ -225,6 +261,10 @@ daemon(Port, UserOptions) when 0 =< Port, Port =< 65535 ->
daemon(any, Port, UserOptions).
+-spec daemon(any | inet:ip_address(), inet:port_number(), daemon_options()) -> {ok,daemon_ref()} | {error,term()}
+ ;(socket, open_socket(), daemon_options()) -> {ok,daemon_ref()} | {error,term()}
+ .
+
daemon(Host0, Port0, UserOptions0) when 0 =< Port0, Port0 =< 65535,
Host0 == any ; Host0 == loopback ; is_tuple(Host0) ->
try
@@ -265,10 +305,13 @@ daemon(Host0, Port0, UserOptions0) when 0 =< Port0, Port0 =< 65535,
daemon(_, _, _) ->
{error, badarg}.
-
-
%%--------------------------------------------------------------------
--spec daemon_info(daemon_ref()) -> ok_error( [{atom(), term()}] ).
+-spec daemon_info(Daemon) -> {ok, DaemonInfo} | {error,term()} when
+ Daemon :: daemon_ref(),
+ DaemonInfo :: [ {ip, inet:ip_address()}
+ | {port, inet:port_number()}
+ | {profile, term()}
+ ].
daemon_info(Pid) ->
case catch ssh_system_sup:acceptor_supervisor(Pid) of
@@ -291,16 +334,23 @@ daemon_info(Pid) ->
end.
%%--------------------------------------------------------------------
--spec stop_listener(daemon_ref()) -> ok.
--spec stop_listener(inet:ip_address(), inet:port_number()) -> ok.
-%%
%% Description: Stops the listener, but leaves
%% existing connections started by the listener up and running.
%%--------------------------------------------------------------------
+-spec stop_listener(daemon_ref()) -> ok.
+
stop_listener(SysSup) ->
ssh_system_sup:stop_listener(SysSup).
+
+
+-spec stop_listener(inet:ip_address(), inet:port_number()) -> ok.
+
stop_listener(Address, Port) ->
stop_listener(Address, Port, ?DEFAULT_PROFILE).
+
+
+-spec stop_listener(any|inet:ip_address(), inet:port_number(), term()) -> ok.
+
stop_listener(any, Port, Profile) ->
map_ip(fun(IP) ->
ssh_system_sup:stop_listener(IP, Port, Profile)
@@ -311,17 +361,23 @@ stop_listener(Address, Port, Profile) ->
end, {address,Address}).
%%--------------------------------------------------------------------
--spec stop_daemon(daemon_ref()) -> ok.
--spec stop_daemon(inet:ip_address(), inet:port_number()) -> ok.
--spec stop_daemon(inet:ip_address(), inet:port_number(), atom()) -> ok.
-%%
%% Description: Stops the listener and all connections started by
%% the listener.
%%--------------------------------------------------------------------
+-spec stop_daemon(DaemonRef::daemon_ref()) -> ok.
+
stop_daemon(SysSup) ->
ssh_system_sup:stop_system(SysSup).
+
+
+-spec stop_daemon(inet:ip_address(), inet:port_number()) -> ok.
+
stop_daemon(Address, Port) ->
stop_daemon(Address, Port, ?DEFAULT_PROFILE).
+
+
+-spec stop_daemon(any|inet:ip_address(), inet:port_number(), atom()) -> ok.
+
stop_daemon(any, Port, Profile) ->
map_ip(fun(IP) ->
ssh_system_sup:stop_system(IP, Port, Profile)
@@ -332,33 +388,37 @@ stop_daemon(Address, Port, Profile) ->
end, {address,Address}).
%%--------------------------------------------------------------------
--spec shell(inet:socket() | string()) -> _.
--spec shell(inet:socket() | string(), proplists:proplist()) -> _.
--spec shell(string(), inet:port_number(), proplists:proplist()) -> _.
-
-%% Host = string()
-%% Port = integer()
-%% Options = [{Option, Value}]
-%%
%% Description: Starts an interactive shell to an SSH server on the
%% given <Host>. The function waits for user input,
%% and will not return until the remote shell is ended.(e.g. on
%% exit from the shell)
%%--------------------------------------------------------------------
+-spec shell(open_socket() | host()) -> _.
+
shell(Socket) when is_port(Socket) ->
shell(Socket, []);
shell(Host) ->
shell(Host, ?SSH_DEFAULT_PORT, []).
+
+-spec shell(open_socket() | host(), client_options()) -> _.
+
shell(Socket, Options) when is_port(Socket) ->
start_shell( connect(Socket, Options) );
shell(Host, Options) ->
shell(Host, ?SSH_DEFAULT_PORT, Options).
+
+-spec shell(Host, Port, Options) -> _ when
+ Host :: host(),
+ Port :: inet:port_number(),
+ Options :: client_options() .
+
shell(Host, Port, Options) ->
start_shell( connect(Host, Port, Options) ).
+
start_shell({ok, ConnectionRef}) ->
case ssh_connection:session_channel(ConnectionRef, infinity) of
{ok,ChannelId} ->
@@ -366,11 +426,17 @@ start_shell({ok, ConnectionRef}) ->
Args = [{channel_cb, ssh_shell},
{init_args,[ConnectionRef, ChannelId]},
{cm, ConnectionRef}, {channel_id, ChannelId}],
- {ok, State} = ssh_channel:init([Args]),
- ssh_channel:enter_loop(State);
+ {ok, State} = ssh_client_channel:init([Args]),
+ try
+ ssh_client_channel:enter_loop(State)
+ catch
+ exit:normal ->
+ ok
+ end;
Error ->
Error
end;
+
start_shell(Error) ->
Error.
@@ -381,6 +447,27 @@ default_algorithms() ->
ssh_transport:default_algorithms().
%%--------------------------------------------------------------------
+-spec chk_algos_opts(client_options()|daemon_options()) -> internal_options() | {error,term()}.
+%%--------------------------------------------------------------------
+chk_algos_opts(Opts) ->
+ case lists:foldl(
+ fun({preferred_algorithms,_}, Acc) -> Acc;
+ ({modify_algorithms,_}, Acc) -> Acc;
+ (KV, Acc) -> [KV|Acc]
+ end, [], Opts)
+ of
+ [] ->
+ case ssh_options:handle_options(client, Opts) of
+ M when is_map(M) ->
+ maps:get(preferred_algorithms, M);
+ Others ->
+ Others
+ end;
+ OtherOps ->
+ {error, {non_algo_opts_found,OtherOps}}
+ end.
+
+%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
%% The handle_daemon_args/2 function basically only sets the ip-option in Opts
@@ -439,6 +526,9 @@ open_listen_socket(_Host0, Port0, Options0) ->
%%%----------------------------------------------------------------
finalize_start(Host, Port, Profile, Options0, F) ->
try
+ %% throws error:Error if no usable hostkey is found
+ ssh_connection_handler:available_hkey_algorithms(server, Options0),
+
sshd_sup:start_child(Host, Port, Profile, Options0)
of
{error, {already_started, _}} ->
@@ -448,6 +538,8 @@ finalize_start(Host, Port, Profile, Options0, F) ->
Result = {ok,_} ->
F(Options0, Result)
catch
+ error:{shutdown,Err} ->
+ {error,Err};
exit:{noproc, _} ->
{error, ssh_not_started}
end.
diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl
index d6d412db43..94b9f3a196 100644
--- a/lib/ssh/src/ssh.hrl
+++ b/lib/ssh/src/ssh.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,12 +29,13 @@
-define(SSH_DEFAULT_PORT, 22).
-define(SSH_MAX_PACKET_SIZE, (256*1024)).
--define(REKEY_TIMOUT, 3600000).
-define(REKEY_DATA_TIMOUT, 60000).
-define(DEFAULT_PROFILE, default).
-define(DEFAULT_TRANSPORT, {tcp, gen_tcp, tcp_closed} ).
+-define(DEFAULT_SHELL, {shell, start, []} ).
+
-define(MAX_RND_PADDING_LEN, 15).
-define(SUPPORTED_AUTH_METHODS, "publickey,keyboard-interactive,password").
@@ -63,8 +64,8 @@
-define(uint16(X), << ?UINT16(X) >> ).
-define(uint32(X), << ?UINT32(X) >> ).
-define(uint64(X), << ?UINT64(X) >> ).
--define(string(X), << ?STRING(list_to_binary(X)) >> ).
-define(string_utf8(X), << ?STRING(unicode:characters_to_binary(X)) >> ).
+-define(string(X), ?string_utf8(X)).
-define(binary(X), << ?STRING(X) >>).
%% Cipher details
@@ -96,35 +97,270 @@
%% Types
--type role() :: client | server .
--type ok_error(SuccessType) :: {ok, SuccessType} | {error, any()} .
--type daemon_ref() :: pid() .
+-type role() :: client | server .
+
+-type host() :: string() | inet:ip_address() | loopback .
+-type open_socket() :: gen_tcp:socket().
+
+-type subsystem_spec() :: {Name::string(), mod_args()} .
+
+-type algs_list() :: list( alg_entry() ).
+-type alg_entry() :: {kex, [kex_alg()]}
+ | {public_key, [pubkey_alg()]}
+ | {cipher, double_algs(cipher_alg())}
+ | {mac, double_algs(mac_alg())}
+ | {compression, double_algs(compression_alg())} .
+
+-type kex_alg() :: 'diffie-hellman-group-exchange-sha1' |
+ 'diffie-hellman-group-exchange-sha256' |
+ 'diffie-hellman-group1-sha1' |
+ 'diffie-hellman-group14-sha1' |
+ 'diffie-hellman-group14-sha256' |
+ 'diffie-hellman-group16-sha512' |
+ 'diffie-hellman-group18-sha512' |
+ 'curve25519-sha256' |
+ 'curve448-sha512' |
+ 'ecdh-sha2-nistp256' |
+ 'ecdh-sha2-nistp384' |
+ 'ecdh-sha2-nistp521'
+ .
+
+-type pubkey_alg() :: 'ecdsa-sha2-nistp256' |
+ 'ecdsa-sha2-nistp384' |
+ 'ecdsa-sha2-nistp521' |
+ 'rsa-sha2-256' |
+ 'rsa-sha2-512' |
+ 'ssh-dss' |
+ 'ssh-rsa'
+ .
+
+-type cipher_alg() :: '3des-cbc' |
+ 'AEAD_AES_128_GCM' |
+ 'AEAD_AES_256_GCM' |
+ 'aes128-cbc' |
+ 'aes128-ctr' |
+ 'aes192-ctr' |
+ 'aes256-ctr' |
+ .
+
+-type mac_alg() :: 'AEAD_AES_128_GCM' |
+ 'AEAD_AES_256_GCM' |
+ 'hmac-sha1' |
+ 'hmac-sha2-256' |
+ 'hmac-sha2-512'
+ .
+
+-type compression_alg() :: 'none' |
+ 'zlib' |
+ .
+
+-type double_algs(AlgType) :: list( {client2server,[AlgType]} | {server2client,[AlgType]} )
+ | [AlgType].
+
+-type modify_algs_list() :: list( {append,algs_list()} | {prepend,algs_list()} | {rm,algs_list()} ) .
+
+-type internal_options() :: ssh_options:private_options().
+-type socket_options() :: [gen_tcp:connect_option() | gen_tcp:listen_option()].
+
+-type client_options() :: [ client_option() ] .
+-type daemon_options() :: [ daemon_option() ].
+
+
+-type common_options() :: [ common_option() ].
+-type common_option() ::
+ user_dir_common_option()
+ | profile_common_option()
+ | max_idle_time_common_option()
+ | key_cb_common_option()
+ | disconnectfun_common_option()
+ | unexpectedfun_common_option()
+ | ssh_msg_debug_fun_common_option()
+ | rekey_limit_common_option()
+ | id_string_common_option()
+ | preferred_algorithms_common_option()
+ | modify_algorithms_common_option()
+ | auth_methods_common_option()
+ | inet_common_option()
+ | fd_common_option()
+ .
+
+-define(COMMON_OPTION, common_option()).
+
+
+-type user_dir_common_option() :: {user_dir, false | string()}.
+-type profile_common_option() :: {profile, atom() }.
+-type max_idle_time_common_option() :: {idle_time, timeout()}.
+-type rekey_limit_common_option() :: {rekey_limit, Bytes::limit_bytes() |
+ {Minutes::limit_time(), Bytes::limit_bytes()}
+ }.
+
+-type limit_bytes() :: non_neg_integer() | infinity . % non_neg_integer due to compatibility
+-type limit_time() :: pos_integer() | infinity .
+
+-type key_cb_common_option() :: {key_cb, Module::atom() | {Module::atom(),Opts::[term()]} } .
+-type disconnectfun_common_option() ::
+ {disconnectfun, fun((Reason::term()) -> void | any()) }.
+-type unexpectedfun_common_option() ::
+ {unexpectedfun, fun((Message::term(),{Host::term(),Port::term()}) -> report | skip ) }.
+-type ssh_msg_debug_fun_common_option() ::
+ {ssh_msg_debug_fun, fun((ssh:connection_ref(),AlwaysDisplay::boolean(),Msg::binary(),LanguageTag::binary()) -> any()) } .
+
+-type id_string_common_option() :: {id_string, string() | random | {random,Nmin::pos_integer(),Nmax::pos_integer()} }.
+-type preferred_algorithms_common_option():: {preferred_algorithms, algs_list()}.
+-type modify_algorithms_common_option() :: {modify_algorithms, modify_algs_list()}.
+-type auth_methods_common_option() :: {auth_methods, string() }.
+
+-type inet_common_option() :: {inet, inet | inet6} .
+-type fd_common_option() :: {fd, gen_tcp:socket()} .
+
+
+-type opaque_common_options() ::
+ {transport, {atom(),atom(),atom()} }
+ | {vsn, {non_neg_integer(),non_neg_integer()} }
+ | {tstflg, list(term())}
+ | {user_dir_fun, fun()}
+ | {max_random_length_padding, non_neg_integer()} .
+
+
+
+-type client_option() ::
+ pref_public_key_algs_client_option()
+ | pubkey_passphrase_client_options()
+ | host_accepting_client_options()
+ | authentication_client_options()
+ | diffie_hellman_group_exchange_client_option()
+ | connect_timeout_client_option()
+ | recv_ext_info_client_option()
+ | opaque_client_options()
+ | gen_tcp:connect_option()
+ | ?COMMON_OPTION .
+
+-type opaque_client_options() ::
+ {keyboard_interact_fun, fun((term(),term(),term()) -> term())}
+ | opaque_common_options().
+
+-type pref_public_key_algs_client_option() :: {pref_public_key_algs, [pubkey_alg()] } .
+
+-type pubkey_passphrase_client_options() :: {dsa_pass_phrase, string()}
+ | {rsa_pass_phrase, string()}
+ | {ecdsa_pass_phrase, string()} .
+
+-type host_accepting_client_options() ::
+ {silently_accept_hosts, accept_hosts()}
+ | {user_interaction, boolean()}
+ | {save_accepted_host, boolean()}
+ | {quiet_mode, boolean()} .
+
+-type accept_hosts() :: boolean()
+ | accept_callback()
+ | {HashAlgoSpec::fp_digest_alg(), accept_callback()}.
+
+-type fp_digest_alg() :: 'md5' | crypto:sha1() | crypto:sha2() .
+
+-type accept_callback() :: fun((PeerName::string(), fingerprint() ) -> boolean()) .
+-type fingerprint() :: string() | [string()].
+
+-type authentication_client_options() ::
+ {user, string()}
+ | {password, string()} .
+
+-type diffie_hellman_group_exchange_client_option() ::
+ {dh_gex_limits, {Min::pos_integer(), I::pos_integer(), Max::pos_integer()} } .
+
+-type connect_timeout_client_option() :: {connect_timeout, timeout()} .
+
+-type recv_ext_info_client_option() :: {recv_ext_info, boolean()} .
+
+
+
+-type daemon_option() ::
+ subsystem_daemon_option()
+ | shell_daemon_option()
+ | exec_daemon_option()
+ | ssh_cli_daemon_option()
+ | authentication_daemon_options()
+ | diffie_hellman_group_exchange_daemon_option()
+ | negotiation_timeout_daemon_option()
+ | hardening_daemon_options()
+ | callbacks_daemon_options()
+ | send_ext_info_daemon_option()
+ | opaque_daemon_options()
+ | gen_tcp:listen_option()
+ | ?COMMON_OPTION .
+
+-type subsystem_daemon_option() :: {subsystems, subsystem_spec()}.
+
+-type shell_daemon_option() :: {shell, mod_fun_args() | 'shell_fun/1'() | 'shell_fun/2'() }.
+-type 'shell_fun/1'() :: fun((User::string()) -> pid()) .
+-type 'shell_fun/2'() :: fun((User::string(), PeerAddr::inet:ip_address()) -> pid()).
+
+-type exec_daemon_option() :: {exec, 'exec_fun/1'() | 'exec_fun/2'() | 'exec_fun/3'() }.
+
+-type 'exec_fun/1'() :: fun((Cmd::string()) -> exec_result()) .
+-type 'exec_fun/2'() :: fun((Cmd::string(), User::string()) -> exec_result()) .
+-type 'exec_fun/3'() :: fun((Cmd::string(), User::string(), ClientAddr::ip_port()) -> exec_result()) .
+-type exec_result() :: {ok,Result::term()} | {error,Reason::term()} .
+
+-type ssh_cli_daemon_option() :: {ssh_cli, mod_args() | no_cli }.
+
+-type send_ext_info_daemon_option() :: {send_ext_info, boolean()} .
+
+-type authentication_daemon_options() ::
+ {system_dir, string()}
+ | {auth_method_kb_interactive_data, prompt_texts() }
+ | {user_passwords, [{UserName::string(),Pwd::string()}]}
+ | {password, string()}
+ | {pwdfun, pwdfun_2() | pwdfun_4()} .
+
+-type prompt_texts() ::
+ kb_int_tuple()
+ | kb_int_fun_3()
+ .
+
+-type kb_int_fun_3() :: fun((Peer::ip_port(), User::string(), Service::string()) -> kb_int_tuple()).
+-type kb_int_tuple() :: {Name::string(), Instruction::string(), Prompt::string(), Echo::boolean()}.
--type subsystem_spec() :: {subsystem_name(), {channel_callback(), channel_init_args()}} .
--type subsystem_name() :: string() .
--type channel_callback() :: atom() .
--type channel_init_args() :: list() .
+-type pwdfun_2() :: fun((User::string(), Password::string()) -> boolean()) .
+-type pwdfun_4() :: fun((User::string(),
+ Password::string(),
+ PeerAddress::ip_port(),
+ State::any()) ->
+ boolean() | disconnect | {boolean(),NewState::any()}
+ ) .
--type algs_list() :: list( alg_entry() ).
--type alg_entry() :: {kex, simple_algs()}
- | {public_key, simple_algs()}
- | {cipher, double_algs()}
- | {mac, double_algs()}
- | {compression, double_algs()} .
--type simple_algs() :: list( atom() ) .
--type double_algs() :: list( {client2serverlist,simple_algs()} | {server2client,simple_algs()} )
- | simple_algs() .
+-type diffie_hellman_group_exchange_daemon_option() ::
+ {dh_gex_groups, [explicit_group()] | explicit_group_file() | ssh_moduli_file()}
+ | {dh_gex_limits, {Min::pos_integer(), Max::pos_integer()} } .
--type options() :: #{socket_options := socket_options(),
- internal_options := internal_options(),
- option_key() => any()
- }.
+-type explicit_group() :: {Size::pos_integer(),G::pos_integer(),P::pos_integer()} .
+-type explicit_group_file() :: {file,string()} .
+-type ssh_moduli_file() :: {ssh_moduli_file,string()}.
--type socket_options() :: proplists:proplist().
--type internal_options() :: #{option_key() => any()}.
+-type negotiation_timeout_daemon_option() :: {negotiation_timeout, timeout()} .
--type option_key() :: atom().
+-type hardening_daemon_options() ::
+ {max_sessions, pos_integer()}
+ | {max_channels, pos_integer()}
+ | {parallel_login, boolean()}
+ | {minimal_remote_max_packet_size, pos_integer()}.
+-type callbacks_daemon_options() ::
+ {failfun, fun((User::string(), PeerAddress::inet:ip_address(), Reason::term()) -> _)}
+ | {connectfun, fun((User::string(), PeerAddress::inet:ip_address(), Method::string()) ->_)} .
+
+-type opaque_daemon_options() ::
+ {infofun, fun()}
+ | opaque_common_options().
+
+-type ip_port() :: {inet:ip_address(), inet:port_number()} .
+
+-type mod_args() :: {Module::atom(), Args::list()} .
+-type mod_fun_args() :: {Module::atom(), Function::atom(), Args::list()} .
%% Records
@@ -132,8 +368,9 @@
{
role :: client | role(),
peer :: undefined |
- {inet:hostname(),
- {inet:ip_address(),inet:port_number()}}, %% string version of peer address
+ {inet:hostname(),ip_port()}, %% string version of peer address
+
+ local, %% Local sockname. Need this AFTER a socket is closed by i.e. a crash
c_vsn, %% client version {Major,Minor}
s_vsn, %% server version {Major,Minor}
@@ -149,8 +386,6 @@
algorithms, %% #alg{}
- kex, %% key exchange algorithm
- hkey, %% host key algorithm
key_cb, %% Private/Public key callback module
io_cb, %% Interaction callback module
@@ -246,4 +481,38 @@
_ -> exit(Reason)
end).
+
+%% dbg help macros
+-define(wr_record(N,BlackList),
+ wr_record(R=#N{}) -> ssh_dbg:wr_record(R, record_info(fields,N), BlackList)
+ ).
+
+-define(wr_record(N), ?wr_record(N, [])).
+
+
+%% Circular trace buffer macros
+
+-record(circ_buf_entry,
+ {
+ module,
+ line,
+ function,
+ pid = self(),
+ value
+ }).
+
+-define(CIRC_BUF_IN(VALUE),
+ ssh_dbg:cbuf_in(
+ #circ_buf_entry{module = ?MODULE,
+ line = ?LINE,
+ function = {?FUNCTION_NAME,?FUNCTION_ARITY},
+ pid = self(),
+ value = (VALUE)
+ })
+ ).
+
+-define(CIRC_BUF_IN_ONCE(VALUE),
+ ((fun(V) -> ?CIRC_BUF_IN(V), V end)(VALUE))
+ ).
+
-endif. % SSH_HRL defined
diff --git a/lib/ssh/src/ssh_acceptor.erl b/lib/ssh/src/ssh_acceptor.erl
index d66a34c58a..11ce80354e 100644
--- a/lib/ssh/src/ssh_acceptor.erl
+++ b/lib/ssh/src/ssh_acceptor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,6 +33,8 @@
%% spawn export
-export([acceptor_init/5, acceptor_loop/6]).
+-export([dbg_trace/3]).
+
-define(SLEEP_TIME, 200).
%%====================================================================
@@ -86,7 +88,8 @@ acceptor_init(Parent, Port, Address, Opts, AcceptTimeout) ->
acceptor_loop(Callback, Port, Address, Opts, LSock, AcceptTimeout);
{error,_} -> % Not open, a restart
- {ok,NewLSock} = listen(Port, Opts),
+ %% Allow gen_tcp:listen to fail 4 times if eaddrinuse:
+ {ok,NewLSock} = try_listen(Port, Opts, 4),
proc_lib:init_ack(Parent, {ok, self()}),
Opts1 = ?DELETE_INTERNAL_OPT(lsocket, Opts),
{_, Callback, _} = ?GET_OPT(transport, Opts1),
@@ -98,6 +101,19 @@ acceptor_init(Parent, Port, Address, Opts, AcceptTimeout) ->
end.
+try_listen(Port, Opts, NtriesLeft) ->
+ try_listen(Port, Opts, 1, NtriesLeft).
+
+try_listen(Port, Opts, N, Nmax) ->
+ case listen(Port, Opts) of
+ {error,eaddrinuse} when N<Nmax ->
+ timer:sleep(10*N), % Sleep 10, 20, 30,... ms
+ try_listen(Port, Opts, N+1, Nmax);
+ Other ->
+ Other
+ end.
+
+
request_ownership(LSock, SockOwner) ->
SockOwner ! {request_control,LSock,self()},
receive
@@ -181,3 +197,33 @@ handle_error(Reason) ->
error_logger:error_report(String),
exit({accept_failed, String}).
+%%%################################################################
+%%%#
+%%%# Tracing
+%%%#
+
+dbg_trace(points, _, _) -> [connections];
+
+dbg_trace(flags, connections, _) -> [c];
+dbg_trace(on, connections, _) -> dbg:tp(?MODULE, acceptor_init, 5, x),
+ dbg:tpl(?MODULE, handle_connection, 5, x);
+dbg_trace(off, connections, _) -> dbg:ctp(?MODULE, acceptor_init, 5),
+ dbg:ctp(?MODULE, handle_connection, 5);
+dbg_trace(format, connections, {call, {?MODULE,acceptor_init,
+ [_Parent, Port, Address, _Opts, _AcceptTimeout]}}) ->
+ [io_lib:format("Starting LISTENER on ~s:~p\n", [ntoa(Address),Port])
+ ];
+dbg_trace(format, connections, {return_from, {?MODULE,handle_connection,5}, {error,Error}}) ->
+ ["Starting connection to server failed:\n",
+ io_lib:format("Error = ~p", [Error])
+ ].
+
+
+
+ntoa(A) ->
+ try inet:ntoa(A)
+ catch
+ _:_ when is_list(A) -> A;
+ _:_ -> io_lib:format('~p',[A])
+ end.
+
diff --git a/lib/ssh/src/ssh_acceptor_sup.erl b/lib/ssh/src/ssh_acceptor_sup.erl
index a24664793b..15a2238dd3 100644
--- a/lib/ssh/src/ssh_acceptor_sup.erl
+++ b/lib/ssh/src/ssh_acceptor_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,8 +36,6 @@
-define(DEFAULT_TIMEOUT, 50000).
--spec init( [term()] ) -> {ok,{supervisor:sup_flags(),[supervisor:child_spec()]}} | ignore .
-
%%%=========================================================================
%%% API
%%%=========================================================================
@@ -86,10 +84,7 @@ child_spec(Address, Port, Profile, Options) ->
Timeout = ?GET_INTERNAL_OPT(timeout, Options, ?DEFAULT_TIMEOUT),
#{id => id(Address, Port, Profile),
start => {ssh_acceptor, start_link, [Port, Address, Options, Timeout]},
- restart => transient,
- shutdown => 5500, %brutal_kill,
- type => worker,
- modules => [ssh_acceptor]
+ restart => transient % because a crashed listener could be replaced by a new one
}.
id(Address, Port, Profile) ->
diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl
index ac64a7bf14..4e4aa440de 100644
--- a/lib/ssh/src/ssh_auth.erl
+++ b/lib/ssh/src/ssh_auth.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -40,15 +40,12 @@
%%--------------------------------------------------------------------
%%%----------------------------------------------------------------
userauth_request_msg(#ssh{userauth_methods = ServerMethods,
- userauth_supported_methods = UserPrefMethods, % Note: this is not documented as supported for clients
+ userauth_supported_methods = UserPrefMethods,
userauth_preference = ClientMethods0
} = Ssh0) ->
case sort_select_mthds(ClientMethods0, UserPrefMethods, ServerMethods) of
[] ->
- Msg = #ssh_msg_disconnect{code = ?SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE,
- description = "Unable to connect using the available authentication methods",
- language = "en"},
- {disconnect, Msg, ssh_transport:ssh_packet(Msg, Ssh0)};
+ {send_disconnect, ?SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, Ssh0};
[{Pref,Module,Function,Args} | Prefs] ->
Ssh = case Pref of
@@ -145,14 +142,17 @@ get_public_key(SigAlg, #ssh{opts = Opts}) ->
case KeyCb:user_key(KeyAlg, [{key_cb_private,KeyCbOpts}|UserOpts]) of
{ok, PrivKey} ->
try
+ %% Check the key - the KeyCb may be a buggy plugin
+ true = ssh_transport:valid_key_sha_alg(PrivKey, KeyAlg),
Key = ssh_transport:extract_public_key(PrivKey),
public_key:ssh_encode(Key, ssh2_pubkey)
of
PubKeyBlob -> {ok,{PrivKey,PubKeyBlob}}
catch
_:_ ->
- not_ok
+ not_ok
end;
+
_Error ->
not_ok
end.
@@ -193,11 +193,8 @@ init_userauth_request_msg(#ssh{opts = Opts} = Ssh) ->
%% Client side
case ?GET_OPT(user, Opts) of
undefined ->
- ErrStr = "Could not determine the users name",
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_ILLEGAL_USER_NAME,
- description = ErrStr});
-
+ ?DISCONNECT(?SSH_DISCONNECT_ILLEGAL_USER_NAME,
+ "Could not determine the users name");
User ->
ssh_transport:ssh_packet(
#ssh_msg_userauth_request{user = User,
@@ -301,11 +298,10 @@ handle_userauth_request(#ssh_msg_userauth_request{user = User,
SigWLen/binary>>
},
SessionId,
- #ssh{opts = Opts,
- userauth_supported_methods = Methods} = Ssh) ->
+ #ssh{userauth_supported_methods = Methods} = Ssh) ->
case verify_sig(SessionId, User, "ssh-connection",
- BAlg, KeyBlob, SigWLen, Opts) of
+ BAlg, KeyBlob, SigWLen, Ssh) of
true ->
{authorized, User,
ssh_transport:ssh_packet(
@@ -449,11 +445,8 @@ handle_userauth_info_response({extra,#ssh_msg_userauth_info_response{}},
handle_userauth_info_response(#ssh_msg_userauth_info_response{},
_Auth) ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
- description = "Server does not support keyboard-interactive"
- }).
-
+ ?DISCONNECT(?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
+ "Server does not support keyboard-interactive").
%%--------------------------------------------------------------------
%%% Internal functions
@@ -490,10 +483,8 @@ check_password(User, Password, Opts, Ssh) ->
{false,NewState} ->
{false, Ssh#ssh{pwdfun_user_state=NewState}};
disconnect ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
- description = "Unable to connect using the available authentication methods"
- })
+ ?DISCONNECT(?SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE,
+ "")
end
end.
@@ -515,7 +506,7 @@ pre_verify_sig(User, KeyBlob, Opts) ->
false
end.
-verify_sig(SessionId, User, Service, AlgBin, KeyBlob, SigWLen, Opts) ->
+verify_sig(SessionId, User, Service, AlgBin, KeyBlob, SigWLen, #ssh{opts = Opts} = Ssh) ->
try
Alg = binary_to_list(AlgBin),
{KeyCb,KeyCbOpts} = ?GET_OPT(key_cb, Opts),
@@ -526,7 +517,7 @@ verify_sig(SessionId, User, Service, AlgBin, KeyBlob, SigWLen, Opts) ->
<<?UINT32(AlgSigLen), AlgSig:AlgSigLen/binary>> = SigWLen,
<<?UINT32(AlgLen), _Alg:AlgLen/binary,
?UINT32(SigLen), Sig:SigLen/binary>> = AlgSig,
- ssh_transport:verify(PlainText, ssh_transport:sha(Alg), Sig, Key)
+ ssh_transport:verify(PlainText, ssh_transport:sha(Alg), Sig, Key, Ssh)
catch
_:_ ->
false
@@ -589,16 +580,12 @@ keyboard_interact_fun(KbdInteractFun, Name, Instr, PromptInfos, NumPrompts) ->
case KbdInteractFun(Name, Instr, Prompts) of
Rs when length(Rs) == NumPrompts ->
Rs;
- Rs ->
- throw({mismatching_number_of_responses,
- {got,Rs},
- {expected, NumPrompts},
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
- description = "User interaction failed",
- language = "en"}})
+ _Rs ->
+ nok
end.
key_alg('rsa-sha2-256') -> 'ssh-rsa';
key_alg('rsa-sha2-512') -> 'ssh-rsa';
key_alg(Alg) -> Alg.
+
diff --git a/lib/ssh/src/ssh_channel.erl b/lib/ssh/src/ssh_channel.erl
index 85b31f3669..443bd05086 100644
--- a/lib/ssh/src/ssh_channel.erl
+++ b/lib/ssh/src/ssh_channel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
-module(ssh_channel).
+-include("ssh.hrl").
-include("ssh_connect.hrl").
-callback init(Args :: term()) ->
@@ -49,331 +50,43 @@
{ok, NewState :: term()} | {error, Reason :: term()}.
-callback handle_msg(Msg ::term(), State :: term()) ->
- {ok, State::term()} | {stop, ChannelId::integer(), State::term()}.
+ {ok, State::term()} | {stop, ChannelId::ssh:channel_id(), State::term()}.
--callback handle_ssh_msg({ssh_cm, ConnectionRef::term(), SshMsg::term()},
+-callback handle_ssh_msg({ssh_cm, ConnectionRef::ssh:connection_ref(), SshMsg::term()},
State::term()) -> {ok, State::term()} |
- {stop, ChannelId::integer(),
+ {stop, ChannelId::ssh:channel_id(),
State::term()}.
--behaviour(gen_server).
-
%%% API
-export([start/4, start/5, start_link/4, start_link/5, call/2, call/3,
cast/2, reply/2, enter_loop/1]).
-%% gen_server callbacks
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- terminate/2, code_change/3]).
-
-%% Internal application API
--export([cache_create/0, cache_lookup/2, cache_update/2,
- cache_delete/1, cache_delete/2, cache_foldl/3,
- cache_info/2, cache_find/2,
- get_print_info/1]).
-
--record(state, {
- cm,
- channel_cb,
- channel_state,
- channel_id,
- close_sent = false
- }).
-
%%====================================================================
%% API
%%====================================================================
call(ChannelPid, Msg) ->
- call(ChannelPid, Msg, infinity).
+ ssh_client_channel:call(ChannelPid, Msg).
call(ChannelPid, Msg, TimeOute) ->
- try gen_server:call(ChannelPid, Msg, TimeOute) of
- Result ->
- Result
- catch
- exit:{noproc, _} ->
- {error, closed};
- exit:{normal, _} ->
- {error, closed};
- exit:{shutdown, _} ->
- {error, closed};
- exit:{{shutdown, _}, _} ->
- {error, closed};
- exit:{timeout, _} ->
- {error, timeout}
- end.
+ ssh_client_channel:call(ChannelPid, Msg, TimeOute).
cast(ChannelPid, Msg) ->
- gen_server:cast(ChannelPid, Msg).
-
+ ssh_client_channel:cast(ChannelPid, Msg).
reply(From, Msg) ->
- gen_server:reply(From, Msg).
+ ssh_client_channel:reply(From, Msg).
-%%====================================================================
-%% Internal application API
-%%====================================================================
-
-%%--------------------------------------------------------------------
-%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
-%% Description: Starts the server
-%%--------------------------------------------------------------------
start(ConnectionManager, ChannelId, CallBack, CbInitArgs) ->
- start(ConnectionManager, ChannelId, CallBack, CbInitArgs, undefined).
+ ssh_client_channel:start(ConnectionManager, ChannelId, CallBack, CbInitArgs).
start(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) ->
- Options = [{channel_cb, CallBack},
- {channel_id, ChannelId},
- {init_args, CbInitArgs},
- {cm, ConnectionManager},
- {exec, Exec}],
- gen_server:start(?MODULE, [Options], []).
+ ssh_client_channel:start(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec).
start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs) ->
- start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, undefined).
+ ssh_client_channel:start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs).
start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) ->
- Options = [{channel_cb, CallBack},
- {channel_id, ChannelId},
- {init_args, CbInitArgs},
- {cm, ConnectionManager},
- {exec, Exec}],
- gen_server:start_link(?MODULE, [Options], []).
+ ssh_client_channel:start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec).
enter_loop(State) ->
- gen_server:enter_loop(?MODULE, [], State).
-
-%%====================================================================
-%% gen_server callbacks
-%%====================================================================
-
-%%--------------------------------------------------------------------
-%% Function: init(Args) -> {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% Description: Initiates the server
-%%--------------------------------------------------------------------
-init([Options]) ->
- Cb = proplists:get_value(channel_cb, Options),
- ConnectionManager = proplists:get_value(cm, Options),
- ChannelId = proplists:get_value(channel_id, Options),
- process_flag(trap_exit, true),
- InitArgs =
- case proplists:get_value(exec, Options) of
- undefined ->
- proplists:get_value(init_args, Options);
- Exec ->
- proplists:get_value(init_args, Options) ++ [Exec]
- end,
- try Cb:init(InitArgs) of
- {ok, ChannelState} ->
- State = #state{cm = ConnectionManager,
- channel_cb = Cb,
- channel_id = ChannelId,
- channel_state = ChannelState},
- self() ! {ssh_channel_up, ChannelId, ConnectionManager},
- {ok, State};
- {ok, ChannelState, Timeout} ->
- State = #state{cm = ConnectionManager,
- channel_cb = Cb,
- channel_id = ChannelId,
- channel_state = ChannelState},
- self() ! {ssh_channel_up, ChannelId, ConnectionManager},
- {ok, State, Timeout};
- {stop, Why} ->
- {stop, Why}
- catch
- _:Reason ->
- {stop, Reason}
- end.
-
-%%--------------------------------------------------------------------
-%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
-%% {reply, Reply, State, Timeout} |
-%% {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, Reply, State} |
-%% {stop, Reason, State}
-%% Description: Handling call messages
-%%--------------------------------------------------------------------
-handle_call(get_print_info, _From, State) ->
- Reply =
- {{State#state.cm,
- State#state.channel_id},
- io_lib:format('CB=~p',[State#state.channel_cb])
- },
- {reply, Reply, State};
-
-handle_call(Request, From, #state{channel_cb = Module,
- channel_state = ChannelState} = State) ->
- try Module:handle_call(Request, From, ChannelState) of
- Result ->
- handle_cb_result(Result, State)
- catch
- error:{undef, _} ->
- {noreply, State}
- end.
-
-
-%%--------------------------------------------------------------------
-%% Function: handle_cast(Msg, State) -> {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State}
-%% Description: Handling cast messages
-%%--------------------------------------------------------------------
-handle_cast(Msg, #state{channel_cb = Module,
- channel_state = ChannelState} = State) ->
-
- try Module:handle_cast(Msg, ChannelState) of
- Result ->
- handle_cb_result(Result, State)
- catch
- error:{undef, _} ->
- {noreply, State}
- end.
-
-%%--------------------------------------------------------------------
-%% Function: handle_info(Info, State) -> {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State}
-%% Description: Handling all non call/cast messages
-%%--------------------------------------------------------------------
-handle_info({ssh_cm, ConnectionManager, {closed, _ChannelId}},
- #state{cm = ConnectionManager,
- close_sent = true} = State) ->
- {stop, normal, State};
-handle_info({ssh_cm, ConnectionManager, {closed, ChannelId}},
- #state{cm = ConnectionManager,
- close_sent = false} = State) ->
- %% To be on the safe side, i.e. the manager has already been terminated.
- (catch ssh_connection:close(ConnectionManager, ChannelId)),
- {stop, normal, State#state{close_sent = true}};
-
-handle_info({ssh_cm, _, _} = Msg, #state{cm = ConnectionManager,
- channel_cb = Module,
- channel_state = ChannelState0} = State) ->
- case Module:handle_ssh_msg(Msg, ChannelState0) of
- {ok, ChannelState} ->
- adjust_window(Msg),
- {noreply, State#state{channel_state = ChannelState}};
- {ok, ChannelState, Timeout} ->
- adjust_window(Msg),
- {noreply, State#state{channel_state = ChannelState}, Timeout};
- {stop, ChannelId, ChannelState} ->
- catch ssh_connection:close(ConnectionManager, ChannelId),
- {stop, normal, State#state{close_sent = true,
- channel_state = ChannelState}}
- end;
-
-handle_info(Msg, #state{cm = ConnectionManager, channel_cb = Module,
- channel_state = ChannelState0} = State) ->
- case Module:handle_msg(Msg, ChannelState0) of
- {ok, ChannelState} ->
- {noreply, State#state{channel_state = ChannelState}};
- {ok, ChannelState, Timeout} ->
- {noreply, State#state{channel_state = ChannelState}, Timeout};
- {stop, Reason, ChannelState} when is_atom(Reason)->
- {stop, Reason, State#state{close_sent = true,
- channel_state = ChannelState}};
- {stop, ChannelId, ChannelState} ->
- Reason =
- case Msg of
- {'EXIT', _Pid, shutdown} ->
- shutdown;
- _ ->
- normal
- end,
- (catch ssh_connection:close(ConnectionManager, ChannelId)),
- {stop, Reason, State#state{close_sent = true,
- channel_state = ChannelState}}
- end.
-
-%%--------------------------------------------------------------------
-%% Function: terminate(Reason, State) -> void()
-%% Description: This function is called by a gen_server when it is about to
-%% terminate. It should be the opposite of Module:init/1 and do any necessary
-%% cleaning up. When it returns, the gen_server terminates with Reason.
-%% The return value is ignored.
-%%--------------------------------------------------------------------
-terminate(Reason, #state{cm = ConnectionManager,
- channel_id = ChannelId,
- close_sent = false} = State) ->
- catch ssh_connection:close(ConnectionManager, ChannelId),
- terminate(Reason, State#state{close_sent = true});
-terminate(_, #state{channel_cb = Cb, channel_state = ChannelState}) ->
- catch Cb:terminate(Cb, ChannelState),
- ok.
-
-%%--------------------------------------------------------------------
-%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
-%% Description: Convert process state when code is changed
-%%--------------------------------------------------------------------
-code_change(OldVsn, #state{channel_cb = Module,
- channel_state = ChannelState0} = State, Extra) ->
- {ok, ChannelState} = Module:code_change(OldVsn, ChannelState0, Extra),
- {ok, State#state{channel_state = ChannelState}}.
-
-%%====================================================================
-%% Internal application API
-%%====================================================================
-cache_create() ->
- ets:new(cm_tab, [set,{keypos, #channel.local_id}]).
-
-cache_lookup(Cache, Key) ->
- case ets:lookup(Cache, Key) of
- [Channel] ->
- Channel;
- [] ->
- undefined
- end.
-
-cache_update(Cache, #channel{local_id = Id} = Entry) when Id =/= undefined ->
- ets:insert(Cache, Entry).
-
-cache_delete(Cache, Key) ->
- ets:delete(Cache, Key).
-
-cache_delete(Cache) ->
- ets:delete(Cache).
-
-cache_foldl(Fun, Acc, Cache) ->
- ets:foldl(Fun, Acc, Cache).
-
-cache_info(num_entries, Cache) ->
- proplists:get_value(size, ets:info(Cache)).
-
-cache_find(ChannelPid, Cache) ->
- case ets:match_object(Cache, #channel{user = ChannelPid}) of
- [] ->
- undefined;
- [Channel] ->
- Channel
- end.
-
-get_print_info(Pid) ->
- call(Pid, get_print_info, 1000).
-
-%%--------------------------------------------------------------------
-%%% Internal functions
-%%--------------------------------------------------------------------
-handle_cb_result({reply, Reply, ChannelState}, State) ->
- {reply, Reply, State#state{channel_state = ChannelState}};
-handle_cb_result({reply, Reply, ChannelState, Timeout}, State) ->
- {reply, Reply,State#state{channel_state = ChannelState}, Timeout};
-handle_cb_result({noreply, ChannelState}, State) ->
- {noreply, State#state{channel_state = ChannelState}};
-handle_cb_result({noreply, ChannelState, Timeout}, State) ->
- {noreply, State#state{channel_state = ChannelState}, Timeout};
-handle_cb_result({stop, Reason, Reply, ChannelState}, State) ->
- {stop, Reason, Reply, State#state{channel_state = ChannelState}};
-handle_cb_result({stop, Reason, ChannelState}, State) ->
- {stop, Reason, State#state{channel_state = ChannelState}}.
-
-adjust_window({ssh_cm, ConnectionManager,
- {data, ChannelId, _, Data}}) ->
- ssh_connection:adjust_window(ConnectionManager, ChannelId, size(Data));
-adjust_window(_) ->
- ok.
-
-
+ ssh_client_channel:enter_loop(State).
diff --git a/lib/ssh/src/ssh_channel_sup.erl b/lib/ssh/src/ssh_channel_sup.erl
deleted file mode 100644
index 6b01dc334d..0000000000
--- a/lib/ssh/src/ssh_channel_sup.erl
+++ /dev/null
@@ -1,57 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Ssh channel supervisor.
-%%----------------------------------------------------------------------
--module(ssh_channel_sup).
-
--behaviour(supervisor).
-
--export([start_link/1, start_child/2]).
-
-%% Supervisor callback
--export([init/1]).
-
-%%%=========================================================================
-%%% Internal API
-%%%=========================================================================
-start_link(Args) ->
- supervisor:start_link(?MODULE, [Args]).
-
-start_child(Sup, ChildSpec) ->
- supervisor:start_child(Sup, ChildSpec).
-
-%%%=========================================================================
-%%% Supervisor callback
-%%%=========================================================================
--spec init( [term()] ) -> {ok,{supervisor:sup_flags(),[supervisor:child_spec()]}} | ignore .
-
-init(_Args) ->
- RestartStrategy = one_for_one,
- MaxR = 10,
- MaxT = 3600,
- Children = [],
- {ok, {{RestartStrategy, MaxR, MaxT}, Children}}.
-
-%%%=========================================================================
-%%% Internal functions
-%%%=========================================================================
diff --git a/lib/ssh/src/ssh_cli.erl b/lib/ssh/src/ssh_cli.erl
index 62854346b0..af51356355 100644
--- a/lib/ssh/src/ssh_cli.erl
+++ b/lib/ssh/src/ssh_cli.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,14 +25,16 @@
-module(ssh_cli).
--behaviour(ssh_daemon_channel).
+-behaviour(ssh_server_channel).
-include("ssh.hrl").
-include("ssh_connect.hrl").
-%% ssh_channel callbacks
+%% ssh_server_channel callbacks
-export([init/1, handle_ssh_msg/2, handle_msg/2, terminate/2]).
+-export([dbg_trace/3]).
+
%% state
-record(state, {
cm,
@@ -45,23 +47,8 @@
}).
%%====================================================================
-%% ssh_channel callbacks
+%% ssh_server_channel callbacks
%%====================================================================
--spec init(Args :: term()) ->
- {ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} |
- {stop, Reason :: term()} | ignore.
-
--spec terminate(Reason :: (normal | shutdown | {shutdown, term()} |
- term()),
- State :: term()) ->
- term().
-
--spec handle_msg(Msg ::term(), State :: term()) ->
- {ok, State::term()} | {stop, ChannelId::integer(), State::term()}.
--spec handle_ssh_msg({ssh_cm, ConnectionRef::term(), SshMsg::term()},
- State::term()) -> {ok, State::term()} |
- {stop, ChannelId::integer(),
- State::term()}.
%%--------------------------------------------------------------------
%% Function: init(Args) -> {ok, State}
@@ -118,31 +105,52 @@ handle_ssh_msg({ssh_cm, ConnectionHandler,
write_chars(ConnectionHandler, ChannelId, Chars),
{ok, State#state{pty = Pty, buf = NewBuf}};
-handle_ssh_msg({ssh_cm, ConnectionHandler,
- {shell, ChannelId, WantReply}}, State) ->
+handle_ssh_msg({ssh_cm, ConnectionHandler, {shell, ChannelId, WantReply}}, State) ->
NewState = start_shell(ConnectionHandler, State),
- ssh_connection:reply_request(ConnectionHandler, WantReply,
- success, ChannelId),
+ ssh_connection:reply_request(ConnectionHandler, WantReply, success, ChannelId),
{ok, NewState#state{channel = ChannelId,
cm = ConnectionHandler}};
-handle_ssh_msg({ssh_cm, ConnectionHandler,
- {exec, ChannelId, WantReply, Cmd}}, #state{exec=undefined} = State) ->
- {Reply, Status} = exec(Cmd),
- write_chars(ConnectionHandler,
- ChannelId, io_lib:format("~p\n", [Reply])),
- ssh_connection:reply_request(ConnectionHandler, WantReply,
- success, ChannelId),
- ssh_connection:exit_status(ConnectionHandler, ChannelId, Status),
- ssh_connection:send_eof(ConnectionHandler, ChannelId),
- {stop, ChannelId, State#state{channel = ChannelId, cm = ConnectionHandler}};
-handle_ssh_msg({ssh_cm, ConnectionHandler,
- {exec, ChannelId, WantReply, Cmd}}, State) ->
- NewState = start_shell(ConnectionHandler, Cmd, State),
- ssh_connection:reply_request(ConnectionHandler, WantReply,
- success, ChannelId),
- {ok, NewState#state{channel = ChannelId,
- cm = ConnectionHandler}};
+handle_ssh_msg({ssh_cm, ConnectionHandler, {exec, ChannelId, WantReply, Cmd}}, S0) ->
+ case
+ case S0#state.exec of
+ {direct,F} ->
+ %% Exec called and a Fun or MFA is defined to use. The F returns the
+ %% value to return.
+ exec_direct(ConnectionHandler, F, Cmd);
+
+ undefined when S0#state.shell == ?DEFAULT_SHELL ->
+ %% Exec called and the shell is the default shell (= Erlang shell).
+ %% To be exact, eval the term as an Erlang term (but not using the
+ %% ?DEFAULT_SHELL directly). This disables banner, prompts and such.
+ exec_in_erlang_default_shell(Cmd);
+
+ undefined ->
+ %% Exec called, but the a shell other than the default shell is defined.
+ %% No new exec shell is defined, so don't execute!
+ %% We don't know if it is intended to use the new shell or not.
+ {"Prohibited.", 255, 1};
+
+ _ ->
+ %% Exec called and a Fun or MFA is defined to use. The F communicates via
+ %% standard io:write/read.
+ %% Kept for compatibility.
+ S1 = start_exec_shell(ConnectionHandler, Cmd, S0),
+ ssh_connection:reply_request(ConnectionHandler, WantReply, success, ChannelId),
+ {ok, S1}
+ end
+ of
+ {Reply, Status, Type} ->
+ write_chars(ConnectionHandler, ChannelId, Type, Reply),
+ ssh_connection:reply_request(ConnectionHandler, WantReply, success, ChannelId),
+ ssh_connection:exit_status(ConnectionHandler, ChannelId, Status),
+ ssh_connection:send_eof(ConnectionHandler, ChannelId),
+ {stop, ChannelId, S0#state{channel = ChannelId, cm = ConnectionHandler}};
+
+ {ok, S} ->
+ {ok, S#state{channel = ChannelId,
+ cm = ConnectionHandler}}
+ end;
handle_ssh_msg({ssh_cm, _ConnectionHandler, {eof, _ChannelId}}, State) ->
{ok, State};
@@ -249,35 +257,7 @@ to_group(Data, Group) ->
end,
to_group(Tail, Group).
-exec(Cmd) ->
- case eval(parse(scan(Cmd))) of
- {error, _} ->
- {Cmd, 0}; %% This should be an external call
- Term ->
- Term
- end.
-
-scan(Cmd) ->
- erl_scan:string(Cmd).
-
-parse({ok, Tokens, _}) ->
- erl_parse:parse_exprs(Tokens);
-parse(Error) ->
- Error.
-
-eval({ok, Expr_list}) ->
- case (catch erl_eval:exprs(Expr_list,
- erl_eval:new_bindings())) of
- {value, Value, _NewBindings} ->
- {Value, 0};
- {'EXIT', {Error, _}} ->
- {Error, -1};
- Error ->
- {Error, -1}
- end;
-eval(Error) ->
- {Error, -1}.
-
+%%--------------------------------------------------------------------
%%% io_request, handle io requests from the user process,
%%% Note, this is not the real I/O-protocol, but the mockup version
%%% used between edlin and a user_driver. The protocol tags are
@@ -453,11 +433,14 @@ move_cursor(From, To, #ssh_pty{width=Width, term=Type}) ->
%% %%% make sure that there is data to send
%% %%% before calling ssh_connection:send
write_chars(ConnectionHandler, ChannelId, Chars) ->
+ write_chars(ConnectionHandler, ChannelId, ?SSH_EXTENDED_DATA_DEFAULT, Chars).
+
+write_chars(ConnectionHandler, ChannelId, Type, Chars) ->
case has_chars(Chars) of
false -> ok;
true -> ssh_connection:send(ConnectionHandler,
ChannelId,
- ?SSH_EXTENDED_DATA_DEFAULT,
+ Type,
Chars)
end.
@@ -493,53 +476,130 @@ bin_to_list(L) when is_list(L) ->
bin_to_list(I) when is_integer(I) ->
I.
+
+%%--------------------------------------------------------------------
start_shell(ConnectionHandler, State) ->
- Shell = State#state.shell,
- ConnectionInfo = ssh_connection_handler:connection_info(ConnectionHandler,
- [peer, user]),
- ShellFun = case is_function(Shell) of
- true ->
- User = proplists:get_value(user, ConnectionInfo),
- case erlang:fun_info(Shell, arity) of
- {arity, 1} ->
- fun() -> Shell(User) end;
- {arity, 2} ->
- {_, PeerAddr} = proplists:get_value(peer, ConnectionInfo),
- fun() -> Shell(User, PeerAddr) end;
- _ ->
- Shell
- end;
- _ ->
- Shell
- end,
- Echo = get_echo(State#state.pty),
- Group = group:start(self(), ShellFun, [{echo, Echo}]),
- State#state{group = Group, buf = empty_buf()}.
-
-start_shell(_ConnectionHandler, Cmd, #state{exec={M, F, A}} = State) ->
- Group = group:start(self(), {M, F, A++[Cmd]}, [{echo, false}]),
- State#state{group = Group, buf = empty_buf()};
-start_shell(ConnectionHandler, Cmd, #state{exec=Shell} = State) when is_function(Shell) ->
-
- ConnectionInfo = ssh_connection_handler:connection_info(ConnectionHandler,
- [peer, user]),
- User = proplists:get_value(user, ConnectionInfo),
- ShellFun =
- case erlang:fun_info(Shell, arity) of
- {arity, 1} ->
- fun() -> Shell(Cmd) end;
- {arity, 2} ->
- fun() -> Shell(Cmd, User) end;
- {arity, 3} ->
- {_, PeerAddr} = proplists:get_value(peer, ConnectionInfo),
- fun() -> Shell(Cmd, User, PeerAddr) end;
- _ ->
- Shell
- end,
- Echo = get_echo(State#state.pty),
- Group = group:start(self(), ShellFun, [{echo,Echo}]),
- State#state{group = Group, buf = empty_buf()}.
+ ShellSpawner =
+ case State#state.shell of
+ Shell when is_function(Shell, 1) ->
+ [{user,User}] = ssh_connection_handler:connection_info(ConnectionHandler, [user]),
+ fun() -> Shell(User) end;
+ Shell when is_function(Shell, 2) ->
+ ConnectionInfo =
+ ssh_connection_handler:connection_info(ConnectionHandler, [peer, user]),
+ User = proplists:get_value(user, ConnectionInfo),
+ {_, PeerAddr} = proplists:get_value(peer, ConnectionInfo),
+ fun() -> Shell(User, PeerAddr) end;
+ {_,_,_} = Shell ->
+ Shell
+ end,
+ State#state{group = group:start(self(), ShellSpawner, [{echo, get_echo(State#state.pty)}]),
+ buf = empty_buf()}.
+
+%%--------------------------------------------------------------------
+start_exec_shell(ConnectionHandler, Cmd, State) ->
+ ExecShellSpawner =
+ case State#state.exec of
+ ExecShell when is_function(ExecShell, 1) ->
+ fun() -> ExecShell(Cmd) end;
+ ExecShell when is_function(ExecShell, 2) ->
+ [{user,User}] = ssh_connection_handler:connection_info(ConnectionHandler, [user]),
+ fun() -> ExecShell(Cmd, User) end;
+ ExecShell when is_function(ExecShell, 3) ->
+ ConnectionInfo =
+ ssh_connection_handler:connection_info(ConnectionHandler, [peer, user]),
+ User = proplists:get_value(user, ConnectionInfo),
+ {_, PeerAddr} = proplists:get_value(peer, ConnectionInfo),
+ fun() -> ExecShell(Cmd, User, PeerAddr) end;
+ {M,F,A} ->
+ {M, F, A++[Cmd]}
+ end,
+ State#state{group = group:start(self(), ExecShellSpawner, [{echo,false}]),
+ buf = empty_buf()}.
+
+%%--------------------------------------------------------------------
+exec_in_erlang_default_shell(Cmd) ->
+ case eval(parse(scan(Cmd))) of
+ {ok, Term} ->
+ {io_lib:format("~p\n", [Term]), 0, 0};
+ {error, Error} when is_atom(Error) ->
+ {io_lib:format("Error in ~p: ~p\n", [Cmd,Error]), -1, 1};
+ _ ->
+ {io_lib:format("Error: ~p\n", [Cmd]), -1, 1}
+ end.
+
+scan(Cmd) ->
+ erl_scan:string(Cmd).
+
+parse({ok, Tokens, _}) ->
+ erl_parse:parse_exprs(Tokens);
+parse(Error) ->
+ Error.
+
+eval({ok, Expr_list}) ->
+ case (catch erl_eval:exprs(Expr_list,
+ erl_eval:new_bindings())) of
+ {value, Value, _NewBindings} ->
+ {ok, Value};
+ {'EXIT', {Error, _}} ->
+ {error, Error};
+ {error, Error} ->
+ {error, Error};
+ Error ->
+ {error, Error}
+ end;
+eval({error,Error}) ->
+ {error, Error};
+eval(Error) ->
+ {error, Error}.
+
+%%--------------------------------------------------------------------
+exec_direct(ConnectionHandler, ExecSpec, Cmd) ->
+ try
+ case ExecSpec of
+ _ when is_function(ExecSpec, 1) ->
+ ExecSpec(Cmd);
+ _ when is_function(ExecSpec, 2) ->
+ [{user,User}] = ssh_connection_handler:connection_info(ConnectionHandler, [user]),
+ ExecSpec(Cmd, User);
+ _ when is_function(ExecSpec, 3) ->
+ ConnectionInfo =
+ ssh_connection_handler:connection_info(ConnectionHandler, [peer, user]),
+ User = proplists:get_value(user, ConnectionInfo),
+ {_, PeerAddr} = proplists:get_value(peer, ConnectionInfo),
+ ExecSpec(Cmd, User, PeerAddr)
+ end
+ of
+ Reply ->
+ return_direct_exec_reply(Reply, Cmd)
+ catch
+ C:Error ->
+ {io_lib:format("Error in \"~s\": ~p ~p~n", [Cmd,C,Error]), -1, 1}
+ end.
+
+
+return_direct_exec_reply(Reply, Cmd) ->
+ case fmt_exec_repl(Reply) of
+ {ok,S} ->
+ {S, 0, 0};
+ {error,S} ->
+ {io_lib:format("Error in \"~s\": ~s~n", [Cmd,S]), -1, 1}
+ end.
+
+fmt_exec_repl({T,A}) when T==ok ; T==error ->
+ try
+ {T, io_lib:format("~s",[A])}
+ catch
+ error:badarg ->
+ {T, io_lib:format("~p", [A])};
+ C:Err ->
+ {error, io_lib:format("~p:~p~n",[C,Err])}
+ end;
+fmt_exec_repl(Other) ->
+ {error, io_lib:format("Bad exec-plugin return: ~p",[Other])}.
+
+%%--------------------------------------------------------------------
% Pty can be undefined if the client never sets any pty options before
% starting the shell.
get_echo(undefined) ->
@@ -565,3 +625,19 @@ not_zero(0, B) ->
not_zero(A, _) ->
A.
+%%%################################################################
+%%%#
+%%%# Tracing
+%%%#
+
+dbg_trace(points, _, _) -> [terminate];
+
+dbg_trace(flags, terminate, _) -> [c];
+dbg_trace(on, terminate, _) -> dbg:tp(?MODULE, terminate, 2, x);
+dbg_trace(off, terminate, _) -> dbg:ctpg(?MODULE, terminate, 2);
+dbg_trace(format, terminate, {call, {?MODULE,terminate, [Reason, State]}}) ->
+ ["Cli Terminating:\n",
+ io_lib:format("Reason: ~p,~nState:~n~s", [Reason, wr_record(State)])
+ ].
+
+?wr_record(state).
diff --git a/lib/ssh/src/ssh_client_channel.erl b/lib/ssh/src/ssh_client_channel.erl
new file mode 100644
index 0000000000..f985d8e273
--- /dev/null
+++ b/lib/ssh/src/ssh_client_channel.erl
@@ -0,0 +1,458 @@
+%%
+%% %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(ssh_client_channel).
+
+-include("ssh.hrl").
+-include("ssh_connect.hrl").
+
+-callback init(Args :: term()) ->
+ {ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} |
+ {stop, Reason :: term()} | ignore.
+-callback handle_call(Request :: term(), From :: {pid(), Tag :: term()},
+ State :: term()) ->
+ {reply, Reply :: term(), NewState :: term()} |
+ {reply, Reply :: term(), NewState :: term(), timeout() | hibernate} |
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), timeout() | hibernate} |
+ {stop, Reason :: term(), Reply :: term(), NewState :: term()} |
+ {stop, Reason :: term(), NewState :: term()}.
+-callback handle_cast(Request :: term(), State :: term()) ->
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), timeout() | hibernate} |
+ {stop, Reason :: term(), NewState :: term()}.
+
+-callback terminate(Reason :: (normal | shutdown | {shutdown, term()} |
+ term()),
+ State :: term()) ->
+ term().
+-callback code_change(OldVsn :: (term() | {down, term()}), State :: term(),
+ Extra :: term()) ->
+ {ok, NewState :: term()} | {error, Reason :: term()}.
+
+-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()},
+ State::term()) -> {ok, State::term()} |
+ {stop, ChannelId::ssh:channel_id(),
+ State::term()}.
+-behaviour(gen_server).
+
+%%% API
+-export([start/4, start/5, start_link/4, start_link/5, call/2, call/3,
+ cast/2, reply/2, enter_loop/1]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+%% Internal application API
+-export([cache_create/0, cache_lookup/2, cache_update/2,
+ cache_delete/1, cache_delete/2, cache_foldl/3,
+ cache_info/2, cache_find/2,
+ get_print_info/1]).
+
+-export([dbg_trace/3]).
+
+-record(state, {
+ cm,
+ channel_cb,
+ channel_state,
+ channel_id,
+ close_sent = false
+ }).
+
+%%====================================================================
+%% API
+%%====================================================================
+
+call(ChannelPid, Msg) ->
+ call(ChannelPid, Msg, infinity).
+
+call(ChannelPid, Msg, TimeOute) ->
+ try gen_server:call(ChannelPid, Msg, TimeOute) of
+ Result ->
+ Result
+ catch
+ exit:{noproc, _} ->
+ {error, closed};
+ exit:{normal, _} ->
+ {error, closed};
+ exit:{shutdown, _} ->
+ {error, closed};
+ exit:{{shutdown, _}, _} ->
+ {error, closed};
+ exit:{timeout, _} ->
+ {error, timeout}
+ end.
+
+cast(ChannelPid, Msg) ->
+ gen_server:cast(ChannelPid, Msg).
+
+
+reply(From, Msg) ->
+ gen_server:reply(From, Msg).
+
+%%====================================================================
+%% Internal application API
+%%====================================================================
+
+%%--------------------------------------------------------------------
+%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
+%% Description: Starts the server
+%%--------------------------------------------------------------------
+start(ConnectionManager, ChannelId, CallBack, CbInitArgs) ->
+ start(ConnectionManager, ChannelId, CallBack, CbInitArgs, undefined).
+
+start(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) ->
+ Options = [{channel_cb, CallBack},
+ {channel_id, ChannelId},
+ {init_args, CbInitArgs},
+ {cm, ConnectionManager},
+ {exec, Exec}],
+ gen_server:start(?MODULE, [Options], []).
+
+start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs) ->
+ start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, undefined).
+
+start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) ->
+ Options = [{channel_cb, CallBack},
+ {channel_id, ChannelId},
+ {init_args, CbInitArgs},
+ {cm, ConnectionManager},
+ {exec, Exec}],
+ gen_server:start_link(?MODULE, [Options], []).
+
+enter_loop(State) ->
+ gen_server:enter_loop(?MODULE, [], State).
+
+%%====================================================================
+%% gen_server callbacks
+%%====================================================================
+
+%%--------------------------------------------------------------------
+%% Function: init(Args) -> {ok, State} |
+%% {ok, State, Timeout} |
+%% ignore |
+%% {stop, Reason}
+%% Description: Initiates the server
+%%--------------------------------------------------------------------
+init([Options]) ->
+ Cb = proplists:get_value(channel_cb, Options),
+ ConnectionManager = proplists:get_value(cm, Options),
+ ChannelId = proplists:get_value(channel_id, Options),
+ process_flag(trap_exit, true),
+ try Cb:init(channel_cb_init_args(Options)) of
+ {ok, ChannelState} ->
+ State = #state{cm = ConnectionManager,
+ channel_cb = Cb,
+ channel_id = ChannelId,
+ channel_state = ChannelState},
+ self() ! {ssh_channel_up, ChannelId, ConnectionManager},
+ {ok, State};
+ {ok, ChannelState, Timeout} ->
+ State = #state{cm = ConnectionManager,
+ channel_cb = Cb,
+ channel_id = ChannelId,
+ channel_state = ChannelState},
+ self() ! {ssh_channel_up, ChannelId, ConnectionManager},
+ {ok, State, Timeout};
+ {stop, Why} ->
+ {stop, Why}
+ catch
+ _:undef ->
+ {stop, {bad_channel_callback_module,Cb}};
+ _:Reason ->
+ {stop, Reason}
+ end.
+
+channel_cb_init_args(Options) ->
+ case proplists:get_value(exec, Options) of
+ undefined ->
+ proplists:get_value(init_args, Options);
+ Exec ->
+ proplists:get_value(init_args, Options) ++ [Exec]
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
+%% {reply, Reply, State, Timeout} |
+%% {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, Reply, State} |
+%% {stop, Reason, State}
+%% Description: Handling call messages
+%%--------------------------------------------------------------------
+handle_call(get_print_info, _From, State) ->
+ Reply =
+ {{State#state.cm,
+ State#state.channel_id},
+ io_lib:format('CB=~p',[State#state.channel_cb])
+ },
+ {reply, Reply, State};
+
+handle_call(Request, From, #state{channel_cb = Module,
+ channel_state = ChannelState} = State) ->
+ try Module:handle_call(Request, From, ChannelState) of
+ Result ->
+ handle_cb_result(Result, State)
+ catch
+ error:{undef, _} ->
+ {noreply, State}
+ end.
+
+
+%%--------------------------------------------------------------------
+%% Function: handle_cast(Msg, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% Description: Handling cast messages
+%%--------------------------------------------------------------------
+handle_cast(Msg, #state{channel_cb = Module,
+ channel_state = ChannelState} = State) ->
+
+ try Module:handle_cast(Msg, ChannelState) of
+ Result ->
+ handle_cb_result(Result, State)
+ catch
+ error:{undef, _} ->
+ {noreply, State}
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: handle_info(Info, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% Description: Handling all non call/cast messages
+%%--------------------------------------------------------------------
+handle_info({ssh_cm, ConnectionManager, {closed, _ChannelId}},
+ #state{cm = ConnectionManager,
+ close_sent = true} = State) ->
+ {stop, normal, State};
+handle_info({ssh_cm, ConnectionManager, {closed, ChannelId}},
+ #state{cm = ConnectionManager,
+ close_sent = false} = State) ->
+ %% To be on the safe side, i.e. the manager has already been terminated.
+ (catch ssh_connection:close(ConnectionManager, ChannelId)),
+ {stop, normal, State#state{close_sent = true}};
+
+handle_info({ssh_cm, _, _} = Msg, #state{cm = ConnectionManager,
+ channel_cb = Module,
+ channel_state = ChannelState0} = State) ->
+ case Module:handle_ssh_msg(Msg, ChannelState0) of
+ {ok, ChannelState} ->
+ adjust_window(Msg),
+ {noreply, State#state{channel_state = ChannelState}};
+ {ok, ChannelState, Timeout} ->
+ adjust_window(Msg),
+ {noreply, State#state{channel_state = ChannelState}, Timeout};
+ {stop, ChannelId, ChannelState} ->
+ catch ssh_connection:close(ConnectionManager, ChannelId),
+ {stop, normal, State#state{close_sent = true,
+ channel_state = ChannelState}}
+ end;
+
+handle_info(Msg, #state{cm = ConnectionManager, channel_cb = Module,
+ channel_state = ChannelState0} = State) ->
+ case Module:handle_msg(Msg, ChannelState0) of
+ {ok, ChannelState} ->
+ {noreply, State#state{channel_state = ChannelState}};
+ {ok, ChannelState, Timeout} ->
+ {noreply, State#state{channel_state = ChannelState}, Timeout};
+ {stop, Reason, ChannelState} when is_atom(Reason)->
+ {stop, Reason, State#state{close_sent = true,
+ channel_state = ChannelState}};
+ {stop, ChannelId, ChannelState} ->
+ Reason =
+ case Msg of
+ {'EXIT', _Pid, shutdown} ->
+ shutdown;
+ _ ->
+ normal
+ end,
+ (catch ssh_connection:close(ConnectionManager, ChannelId)),
+ {stop, Reason, State#state{close_sent = true,
+ channel_state = ChannelState}}
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: terminate(Reason, State) -> void()
+%% Description: This function is called by a gen_server when it is about to
+%% terminate. It should be the opposite of Module:init/1 and do any necessary
+%% cleaning up. When it returns, the gen_server terminates with Reason.
+%% The return value is ignored.
+%%--------------------------------------------------------------------
+terminate(Reason, #state{cm = ConnectionManager,
+ channel_id = ChannelId,
+ close_sent = false} = State) ->
+ catch ssh_connection:close(ConnectionManager, ChannelId),
+ terminate(Reason, State#state{close_sent = true});
+terminate(Reason, #state{channel_cb = Cb, channel_state = ChannelState}) ->
+ catch Cb:terminate(Reason, ChannelState),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% Description: Convert process state when code is changed
+%%--------------------------------------------------------------------
+code_change(OldVsn, #state{channel_cb = Module,
+ channel_state = ChannelState0} = State, Extra) ->
+ {ok, ChannelState} = Module:code_change(OldVsn, ChannelState0, Extra),
+ {ok, State#state{channel_state = ChannelState}}.
+
+%%====================================================================
+%% Internal application API
+%%====================================================================
+cache_create() ->
+ ets:new(cm_tab, [set,{keypos, #channel.local_id}]).
+
+cache_lookup(Cache, Key) ->
+ case ets:lookup(Cache, Key) of
+ [Channel] ->
+ Channel;
+ [] ->
+ undefined
+ end.
+
+cache_update(Cache, #channel{local_id = Id} = Entry) when Id =/= undefined ->
+ ets:insert(Cache, Entry).
+
+cache_delete(Cache, Key) ->
+ ets:delete(Cache, Key).
+
+cache_delete(Cache) ->
+ ets:delete(Cache).
+
+cache_foldl(Fun, Acc, Cache) ->
+ ets:foldl(Fun, Acc, Cache).
+
+cache_info(num_entries, Cache) ->
+ proplists:get_value(size, ets:info(Cache)).
+
+cache_find(ChannelPid, Cache) ->
+ case ets:match_object(Cache, #channel{user = ChannelPid}) of
+ [] ->
+ undefined;
+ [Channel] ->
+ Channel
+ end.
+
+get_print_info(Pid) ->
+ call(Pid, get_print_info, 1000).
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+handle_cb_result({reply, Reply, ChannelState}, State) ->
+ {reply, Reply, State#state{channel_state = ChannelState}};
+handle_cb_result({reply, Reply, ChannelState, Timeout}, State) ->
+ {reply, Reply,State#state{channel_state = ChannelState}, Timeout};
+handle_cb_result({noreply, ChannelState}, State) ->
+ {noreply, State#state{channel_state = ChannelState}};
+handle_cb_result({noreply, ChannelState, Timeout}, State) ->
+ {noreply, State#state{channel_state = ChannelState}, Timeout};
+handle_cb_result({stop, Reason, Reply, ChannelState}, State) ->
+ {stop, Reason, Reply, State#state{channel_state = ChannelState}};
+handle_cb_result({stop, Reason, ChannelState}, State) ->
+ {stop, Reason, State#state{channel_state = ChannelState}}.
+
+adjust_window({ssh_cm, ConnectionManager,
+ {data, ChannelId, _, Data}}) ->
+ ssh_connection:adjust_window(ConnectionManager, ChannelId, size(Data));
+adjust_window(_) ->
+ ok.
+
+
+%%%################################################################
+%%%#
+%%%# Tracing
+%%%#
+
+dbg_trace(points, _, _) -> [terminate, channels, channel_events];
+
+
+dbg_trace(flags, channels, A) -> [c] ++ dbg_trace(flags, terminate, A);
+dbg_trace(on, channels, A) -> dbg:tp(?MODULE, init, 1, x),
+ dbg_trace(on, terminate, A);
+dbg_trace(off, channels, A) -> dbg:ctpg(?MODULE, init, 1),
+ dbg_trace(off, terminate, A);
+dbg_trace(format, channels, {call, {?MODULE,init, [[KVs]]}}) ->
+ ["Server Channel Starting:\n",
+ io_lib:format("Connection: ~p, ChannelId: ~p, CallBack: ~p\nCallBack init args = ~p",
+ [proplists:get_value(K,KVs) || K <- [cm, channel_id, channel_cb]]
+ ++ [channel_cb_init_args(KVs)])
+ ];
+dbg_trace(format, channels, {return_from, {?MODULE,init,1}, {stop,Reason}}) ->
+ ["Server Channel Start FAILED!\n",
+ io_lib:format("Reason = ~p", [Reason])
+ ];
+dbg_trace(format, channels, F) ->
+ dbg_trace(format, terminate, F);
+
+
+dbg_trace(flags, terminate, _) -> [c];
+dbg_trace(on, terminate, _) -> dbg:tp(?MODULE, terminate, 2, x);
+dbg_trace(off, terminate, _) -> dbg:ctpg(?MODULE, terminate, 2);
+dbg_trace(format, terminate, {call, {?MODULE,terminate, [Reason, State]}}) ->
+ ["Server Channel Terminating:\n",
+ io_lib:format("Reason: ~p,~nState:~n~s", [Reason, wr_record(State)])
+ ];
+
+dbg_trace(flags, channel_events, _) -> [c];
+dbg_trace(on, channel_events, _) -> dbg:tp(?MODULE, handle_call, 3, x),
+ dbg:tp(?MODULE, handle_cast, 2, x),
+ dbg:tp(?MODULE, handle_info, 2, x);
+dbg_trace(off, channel_events, _) -> dbg:ctpg(?MODULE, handle_call, 3),
+ dbg:ctpg(?MODULE, handle_cast, 2),
+ dbg:ctpg(?MODULE, handle_info, 2);
+dbg_trace(format, channel_events, {call, {?MODULE,handle_call, [Call,From,State]}}) ->
+ [hdr("is called", State),
+ io_lib:format("From: ~p~nCall: ~p~n", [From, Call])
+ ];
+dbg_trace(format, channel_events, {return_from, {?MODULE,handle_call,3}, Ret}) ->
+ ["Server Channel call returned:\n",
+ io_lib:format("~p~n", [ssh_dbg:reduce_state(Ret)])
+ ];
+dbg_trace(format, channel_events, {call, {?MODULE,handle_cast, [Cast,State]}}) ->
+ [hdr("got cast", State),
+ io_lib:format("Cast: ~p~n", [Cast])
+ ];
+dbg_trace(format, channel_events, {return_from, {?MODULE,handle_cast,2}, Ret}) ->
+ ["Server Channel cast returned:\n",
+ io_lib:format("~p~n", [ssh_dbg:reduce_state(Ret)])
+ ];
+dbg_trace(format, channel_events, {call, {?MODULE,handle_info, [Info,State]}}) ->
+ [hdr("got info", State),
+ io_lib:format("Info: ~p~n", [Info])
+ ];
+dbg_trace(format, channel_events, {return_from, {?MODULE,handle_info,2}, Ret}) ->
+ ["Server Channel info returned:\n",
+ io_lib:format("~p~n", [ssh_dbg:reduce_state(Ret)])
+ ].
+
+hdr(Title, S) ->
+ io_lib:format("Server Channel (Id=~p, CB=~p) ~s:\n", [S#state.channel_id, S#state.channel_cb, Title]).
+
+?wr_record(state).
+
+
diff --git a/lib/ssh/src/ssh_client_key.erl b/lib/ssh/src/ssh_client_key.erl
deleted file mode 100644
index 5296ac2a02..0000000000
--- a/lib/ssh/src/ssh_client_key.erl
+++ /dev/null
@@ -1,35 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(ssh_client_key).
-
--include_lib("public_key/include/public_key.hrl").
--include("ssh.hrl").
-
--callback is_host_key(Key :: public_key(), Host :: string(),
- Algorithm :: 'ssh-rsa'| 'ssh-dsa'| atom(), Options :: proplists:proplist()) ->
- boolean().
-
--callback user_key(Algorithm :: 'ssh-rsa'| 'ssh-dsa'| atom(), Options :: list()) ->
- {ok, PrivateKey :: term()} | {error, string()}.
-
-
--callback add_host_key(Host :: string(), PublicKey :: term(), Options :: list()) ->
- ok | {error, Error::term()}.
diff --git a/lib/ssh/src/ssh_client_key_api.erl b/lib/ssh/src/ssh_client_key_api.erl
index 6e994ff292..384740b786 100644
--- a/lib/ssh/src/ssh_client_key_api.erl
+++ b/lib/ssh/src/ssh_client_key_api.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,26 +23,25 @@
-include_lib("public_key/include/public_key.hrl").
-include("ssh.hrl").
--export_type([algorithm/0]).
+-export_type([client_key_cb_options/0]).
--type algorithm() :: 'ssh-rsa'
- | 'ssh-dss'
- | 'ecdsa-sha2-nistp256'
- | 'ecdsa-sha2-nistp384'
- | 'ecdsa-sha2-nistp521'
- .
+-type client_key_cb_options() :: [{key_cb_private,term()} | ssh:client_option()].
--callback is_host_key(PublicKey :: public_key:public_key(),
- Host :: string(),
- Algorithm :: algorithm(),
- ConnectOptions :: proplists:proplist()) ->
+-callback is_host_key(Key :: public_key:public_key(),
+ Host :: string(),
+ Algorithm :: ssh:pubkey_alg(),
+ Options :: client_key_cb_options()
+ ) ->
boolean().
--callback user_key(Algorithm :: algorithm(),
- ConnectOptions :: proplists:proplist()) ->
- {ok, PrivateKey::public_key:private_key()} | {error, term()}.
+-callback user_key(Algorithm :: ssh:pubkey_alg(),
+ Options :: client_key_cb_options()
+ ) ->
+ {ok, PrivateKey :: public_key:private_key()} | {error, string()}.
--callback add_host_key(Host :: string(), PublicKey :: public_key:public_key(),
- Options :: proplists:proplist()) ->
+-callback add_host_key(Host :: string(),
+ PublicKey :: public_key:public_key(),
+ Options :: client_key_cb_options()
+ ) ->
ok | {error, Error::term()}.
diff --git a/lib/ssh/src/ssh_connect.hrl b/lib/ssh/src/ssh_connect.hrl
index a8de5f9a2f..9a060b8304 100644
--- a/lib/ssh/src/ssh_connect.hrl
+++ b/lib/ssh/src/ssh_connect.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,10 +22,6 @@
%%% Description : SSH connection protocol
--type channel_id() :: pos_integer().
--type connection_ref() :: pid().
-
-
-define(DEFAULT_PACKET_SIZE, 65536).
-define(DEFAULT_WINDOW_SIZE, 10*?DEFAULT_PACKET_SIZE).
diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl
index 7e9ee78fd2..83f85b1d8e 100644
--- a/lib/ssh/src/ssh_connection.erl
+++ b/lib/ssh/src/ssh_connection.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -40,40 +40,56 @@
-export([window_change/4, window_change/6,
signal/3, exit_status/3]).
-%% Internal application API
--export([channel_data/5, handle_msg/3, channel_eof_msg/1,
- channel_close_msg/1, channel_success_msg/1, channel_failure_msg/1,
+%% Internal SSH application API
+-export([channel_data/5,
+ handle_msg/3,
+ handle_stop/1,
+
+ channel_adjust_window_msg/2,
+ channel_close_msg/1,
+ channel_open_failure_msg/4,
+ channel_open_msg/5,
channel_status_msg/1,
- channel_adjust_window_msg/2, channel_data_msg/3,
- channel_open_msg/5, channel_open_confirmation_msg/4,
- channel_open_failure_msg/4, channel_request_msg/4,
+ channel_data_msg/3,
+ channel_eof_msg/1,
+ channel_failure_msg/1,
+ channel_open_confirmation_msg/4,
+ channel_request_msg/4,
+ channel_success_msg/1,
+
request_failure_msg/0,
- request_success_msg/1, bind/4, unbind/3, unbind_channel/2,
- bound_channel/3, encode_ip/1]).
+ request_success_msg/1,
+
+ bind/4, unbind/3, unbind_channel/2,
+ bound_channel/3, encode_ip/1
+ ]).
+
+-type connection_ref() :: ssh:connection_ref().
+-type channel_id() :: ssh:channel_id().
%%--------------------------------------------------------------------
%%% API
%%--------------------------------------------------------------------
%%--------------------------------------------------------------------
--spec session_channel(connection_ref(), timeout()) -> {ok, channel_id()} | {error, timeout | closed}.
--spec session_channel(connection_ref(), integer(), integer(), timeout()) -> {ok, channel_id()} | {error, timeout | closed}.
-
%% Description: Opens a channel for a ssh session. A session is a
%% remote execution of a program. The program may be a shell, an
%% application, a system command, or some built-in subsystem.
%% --------------------------------------------------------------------
+-spec session_channel(connection_ref(), timeout()) ->
+ {ok, channel_id()} | {error, timeout | closed}.
+
session_channel(ConnectionHandler, Timeout) ->
- session_channel(ConnectionHandler,
- ?DEFAULT_WINDOW_SIZE, ?DEFAULT_PACKET_SIZE,
- 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}.
-session_channel(ConnectionHandler, InitialWindowSize,
- MaxPacketSize, Timeout) ->
+session_channel(ConnectionHandler, InitialWindowSize, MaxPacketSize, Timeout) ->
case ssh_connection_handler:open_channel(ConnectionHandler, "session", <<>>,
- InitialWindowSize,
- MaxPacketSize, Timeout) of
+ InitialWindowSize,
+ MaxPacketSize, Timeout) of
{open, Channel} ->
{ok, Channel};
Error ->
@@ -81,55 +97,63 @@ session_channel(ConnectionHandler, InitialWindowSize,
end.
%%--------------------------------------------------------------------
--spec exec(connection_ref(), channel_id(), string(), timeout()) ->
- success | failure | {error, timeout | closed}.
-
%% 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}.
+
exec(ConnectionHandler, ChannelId, Command, TimeOut) ->
ssh_connection_handler:request(ConnectionHandler, self(), ChannelId, "exec",
true, [?string(Command)], TimeOut).
%%--------------------------------------------------------------------
--spec shell(connection_ref(), channel_id()) -> _.
-
%% Description: Will request that the user's default shell (typically
%% defined in /etc/passwd in UNIX systems) be started at the other
%% end.
%%--------------------------------------------------------------------
+-spec shell(connection_ref(), channel_id()) ->
+ ok | success | failure | {error, timeout}.
+
shell(ConnectionHandler, ChannelId) ->
ssh_connection_handler:request(ConnectionHandler, self(), ChannelId,
"shell", false, <<>>, 0).
%%--------------------------------------------------------------------
--spec subsystem(connection_ref(), channel_id(), string(), timeout()) ->
- success | failure | {error, timeout | closed}.
%%
%% Description: Executes a predefined subsystem.
%%--------------------------------------------------------------------
+-spec subsystem(connection_ref(), channel_id(), string(), timeout()) ->
+ success | failure | {error, timeout | closed}.
+
subsystem(ConnectionHandler, ChannelId, SubSystem, TimeOut) ->
ssh_connection_handler:request(ConnectionHandler, self(),
ChannelId, "subsystem",
true, [?string(SubSystem)], TimeOut).
%%--------------------------------------------------------------------
--spec send(connection_ref(), channel_id(), iodata()) ->
- ok | {error, closed}.
--spec send(connection_ref(), channel_id(), integer()| iodata(), timeout() | iodata()) ->
- ok | {error, timeout} | {error, closed}.
--spec send(connection_ref(), channel_id(), integer(), iodata(), timeout()) ->
- ok | {error, timeout} | {error, closed}.
-%%
-%%
%% Description: Sends channel data.
%%--------------------------------------------------------------------
+-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}.
+
send(ConnectionHandler, ChannelId, Data, TimeOut) when is_integer(TimeOut) ->
send(ConnectionHandler, ChannelId, 0, Data, TimeOut);
+
send(ConnectionHandler, ChannelId, Data, infinity) ->
send(ConnectionHandler, ChannelId, 0, Data, infinity);
+
send(ConnectionHandler, ChannelId, Type, Data) ->
send(ConnectionHandler, ChannelId, Type, Data, infinity).
+
+
+-spec send(connection_ref(), channel_id(), integer(), iodata(), timeout()) ->
+ ok | {error, timeout | closed}.
+
send(ConnectionHandler, ChannelId, Type, Data, TimeOut) ->
ssh_connection_handler:send(ConnectionHandler, ChannelId,
Type, Data, TimeOut).
@@ -143,7 +167,7 @@ send_eof(ConnectionHandler, Channel) ->
ssh_connection_handler:send_eof(ConnectionHandler, Channel).
%%--------------------------------------------------------------------
--spec adjust_window(connection_ref(), channel_id(), integer()) -> ok | {error, closed}.
+-spec adjust_window(connection_ref(), channel_id(), integer()) -> ok.
%%
%%
%% Description: Adjusts the ssh flowcontrol window.
@@ -185,17 +209,18 @@ reply_request(_,false, _, _) ->
ok.
%%--------------------------------------------------------------------
--spec ptty_alloc(connection_ref(), channel_id(), proplists:proplist()) ->
- success | failiure | {error, closed}.
--spec ptty_alloc(connection_ref(), channel_id(), proplists:proplist(), timeout()) ->
- success | failiure | {error, timeout} | {error, closed}.
-
-%%
-%%
%% Description: Sends a ssh connection protocol pty_req.
%%--------------------------------------------------------------------
+-spec ptty_alloc(connection_ref(), channel_id(), proplists:proplist()) ->
+ success | failure | {error, timeout}.
+
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}.
+
ptty_alloc(ConnectionHandler, Channel, Options0, TimeOut) ->
TermData = backwards_compatible(Options0, []), % FIXME
{Width, PixWidth} = pty_default_dimensions(width, TermData),
@@ -232,33 +257,21 @@ exit_status(ConnectionHandler, Channel, Status) ->
"exit-status", false, [?uint32(Status)], 0).
%%--------------------------------------------------------------------
-%%% Internal API
+%%% Internal, that is, ssh application internal API
%%--------------------------------------------------------------------
-l2b(L) when is_integer(hd(L)) ->
- try list_to_binary(L)
- of
- B -> B
- catch
- _:_ ->
- unicode:characters_to_binary(L)
- end;
-l2b([H|T]) ->
- << (l2b(H))/binary, (l2b(T))/binary >>;
-l2b(B) when is_binary(B) ->
- B;
-l2b([]) ->
- <<>>.
-
+%%%----------------------------------------------------------------
+%%% Send data on a channel/connection as result of for example
+%%% ssh_connection:send (executed in the ssh_connection_state machine)
+%%%
-channel_data(ChannelId, DataType, Data, Connection, From)
- when is_list(Data)->
+channel_data(ChannelId, DataType, Data, Connection, From) when is_list(Data)->
channel_data(ChannelId, DataType, l2b(Data), Connection, From);
channel_data(ChannelId, DataType, Data,
#connection{channel_cache = Cache} = Connection,
From) ->
- case ssh_channel:cache_lookup(Cache, ChannelId) of
+ case ssh_client_channel:cache_lookup(Cache, ChannelId) of
#channel{remote_id = Id, sent_close = false} = Channel0 ->
{SendList, Channel} =
update_send_window(Channel0#channel{flow_control = From}, DataType,
@@ -271,11 +284,18 @@ channel_data(ChannelId, DataType, Data,
SendData)}
end, SendList),
FlowCtrlMsgs = flow_control(Replies, Channel, Cache),
- {{replies, Replies ++ FlowCtrlMsgs}, Connection};
+ {Replies ++ FlowCtrlMsgs, Connection};
_ ->
- {{replies,[{channel_request_reply,From,{error,closed}}]}, Connection}
+ {[{channel_request_reply,From,{error,closed}}], Connection}
end.
+%%%----------------------------------------------------------------
+%%% Handle the channel messages on behalf of the ssh_connection_handler
+%%% state machine.
+%%%
+%%% Replies {Reply, UpdatedConnection}
+%%%
+
handle_msg(#ssh_msg_channel_open_confirmation{recipient_channel = ChannelId,
sender_channel = RemoteId,
initial_window_size = WindowSz,
@@ -283,63 +303,42 @@ handle_msg(#ssh_msg_channel_open_confirmation{recipient_channel = ChannelId,
#connection{channel_cache = Cache} = Connection0, _) ->
#channel{remote_id = undefined} = Channel =
- ssh_channel:cache_lookup(Cache, ChannelId),
+ ssh_client_channel:cache_lookup(Cache, ChannelId),
- ssh_channel:cache_update(Cache, Channel#channel{
+ ssh_client_channel:cache_update(Cache, Channel#channel{
remote_id = RemoteId,
recv_packet_size = max(32768, % rfc4254/5.2
min(PacketSz, Channel#channel.recv_packet_size)
),
send_window_size = WindowSz,
send_packet_size = PacketSz}),
- {Reply, Connection} = reply_msg(Channel, Connection0, {open, ChannelId}),
- {{replies, [Reply]}, Connection};
+ reply_msg(Channel, Connection0, {open, ChannelId});
handle_msg(#ssh_msg_channel_open_failure{recipient_channel = ChannelId,
reason = Reason,
description = Descr,
lang = Lang},
#connection{channel_cache = Cache} = Connection0, _) ->
- Channel = ssh_channel:cache_lookup(Cache, ChannelId),
- ssh_channel:cache_delete(Cache, ChannelId),
- {Reply, Connection} =
- reply_msg(Channel, Connection0, {open_error, Reason, Descr, Lang}),
- {{replies, [Reply]}, Connection};
-
-handle_msg(#ssh_msg_channel_success{recipient_channel = ChannelId},
- #connection{channel_cache = Cache} = Connection0, _) ->
- Channel = ssh_channel:cache_lookup(Cache, ChannelId),
- case reply_msg(Channel, Connection0, success) of
- {[], Connection} ->
- {noreply, Connection};
- {Reply, Connection} ->
- {{replies, [Reply]}, Connection}
- end;
+ Channel = ssh_client_channel:cache_lookup(Cache, ChannelId),
+ ssh_client_channel:cache_delete(Cache, ChannelId),
+ reply_msg(Channel, Connection0, {open_error, Reason, Descr, Lang});
-handle_msg(#ssh_msg_channel_failure{recipient_channel = ChannelId},
- #connection{channel_cache = Cache} = Connection0, _) ->
- Channel = ssh_channel:cache_lookup(Cache, ChannelId),
- case reply_msg(Channel, Connection0, failure) of
- {[], Connection} ->
- {noreply, Connection};
- {Reply, Connection} ->
- {{replies, [Reply]}, Connection}
- end;
+handle_msg(#ssh_msg_channel_success{recipient_channel = ChannelId}, Connection, _) ->
+ reply_msg(ChannelId, Connection, success);
+handle_msg(#ssh_msg_channel_failure{recipient_channel = ChannelId}, Connection, _) ->
+ reply_msg(ChannelId, Connection, failure);
-handle_msg(#ssh_msg_channel_eof{recipient_channel = ChannelId},
- #connection{channel_cache = Cache} = Connection0, _) ->
- Channel = ssh_channel:cache_lookup(Cache, ChannelId),
- {Reply, Connection} = reply_msg(Channel, Connection0, {eof, ChannelId}),
- {{replies, [Reply]}, Connection};
+handle_msg(#ssh_msg_channel_eof{recipient_channel = ChannelId}, Connection, _) ->
+ reply_msg(ChannelId, Connection, {eof, ChannelId});
handle_msg(#ssh_msg_channel_close{recipient_channel = ChannelId},
#connection{channel_cache = Cache} = Connection0, _) ->
- case ssh_channel:cache_lookup(Cache, ChannelId) of
+ case ssh_client_channel:cache_lookup(Cache, ChannelId) of
#channel{sent_close = Closed, remote_id = RemoteId,
flow_control = FlowControl} = Channel ->
- ssh_channel:cache_delete(Cache, ChannelId),
+ ssh_client_channel:cache_delete(Cache, ChannelId),
{CloseMsg, Connection} =
reply_msg(Channel, Connection0, {closed, ChannelId}),
ConnReplyMsgs =
@@ -358,48 +357,29 @@ handle_msg(#ssh_msg_channel_close{recipient_channel = ChannelId},
[{flow_control, From, {error, closed}}]
end,
- Replies = ConnReplyMsgs ++ [CloseMsg] ++ SendReplyMsgs,
- {{replies, Replies}, Connection};
+ Replies = ConnReplyMsgs ++ CloseMsg ++ SendReplyMsgs,
+ {Replies, Connection};
undefined ->
- {{replies, []}, Connection0}
+ {[], Connection0}
end;
handle_msg(#ssh_msg_channel_data{recipient_channel = ChannelId,
data = Data},
- #connection{channel_cache = Cache} = Connection0, _) ->
-
- case ssh_channel:cache_lookup(Cache, ChannelId) of
- #channel{recv_window_size = Size} = Channel ->
- WantedSize = Size - size(Data),
- ssh_channel:cache_update(Cache, Channel#channel{
- recv_window_size = WantedSize}),
- {Replies, Connection} =
- channel_data_reply(Cache, Channel, Connection0, 0, Data),
- {{replies, Replies}, Connection};
- undefined ->
- {noreply, Connection0}
- end;
+ Connection, _) ->
+ channel_data_reply_msg(ChannelId, Connection, 0, Data);
handle_msg(#ssh_msg_channel_extended_data{recipient_channel = ChannelId,
data_type_code = DataType,
data = Data},
- #connection{channel_cache = Cache} = Connection0, _) ->
-
- #channel{recv_window_size = Size} = Channel =
- ssh_channel:cache_lookup(Cache, ChannelId),
- WantedSize = Size - size(Data),
- ssh_channel:cache_update(Cache, Channel#channel{
- recv_window_size = WantedSize}),
- {Replies, Connection} =
- channel_data_reply(Cache, Channel, Connection0, DataType, Data),
- {{replies, Replies}, Connection};
+ Connection, _) ->
+ channel_data_reply_msg(ChannelId, Connection, DataType, Data);
handle_msg(#ssh_msg_channel_window_adjust{recipient_channel = ChannelId,
bytes_to_add = Add},
#connection{channel_cache = Cache} = Connection, _) ->
#channel{send_window_size = Size, remote_id = RemoteId} =
- Channel0 = ssh_channel:cache_lookup(Cache, ChannelId),
+ Channel0 = ssh_client_channel:cache_lookup(Cache, ChannelId),
{SendList, Channel} = %% TODO: Datatype 0 ?
update_send_window(Channel0#channel{send_window_size = Size + Add},
@@ -409,7 +389,7 @@ handle_msg(#ssh_msg_channel_window_adjust{recipient_channel = ChannelId,
{connection_reply, channel_data_msg(RemoteId, Type, Data)}
end, SendList),
FlowCtrlMsgs = flow_control(Channel, Cache),
- {{replies, Replies ++ FlowCtrlMsgs}, Connection};
+ {Replies ++ FlowCtrlMsgs, Connection};
handle_msg(#ssh_msg_channel_open{channel_type = "session" = Type,
sender_channel = RemoteId,
@@ -430,8 +410,7 @@ handle_msg(#ssh_msg_channel_open{channel_type = "session" = Type,
FailMsg = channel_open_failure_msg(RemoteId,
?SSH_OPEN_CONNECT_FAILED,
"Connection refused", "en"),
- {{replies, [{connection_reply, FailMsg}]},
- Connection0}
+ {[{connection_reply, FailMsg}], Connection0}
end;
MinAcceptedPackSz > PacketSz ->
@@ -439,7 +418,7 @@ handle_msg(#ssh_msg_channel_open{channel_type = "session" = Type,
?SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
lists:concat(["Maximum packet size below ",MinAcceptedPackSz,
" not supported"]), "en"),
- {{replies, [{connection_reply, FailMsg}]}, Connection0}
+ {[{connection_reply, FailMsg}], Connection0}
end;
handle_msg(#ssh_msg_channel_open{channel_type = "session",
@@ -452,35 +431,31 @@ handle_msg(#ssh_msg_channel_open{channel_type = "session",
FailMsg = channel_open_failure_msg(RemoteId,
?SSH_OPEN_CONNECT_FAILED,
"Connection refused", "en"),
- {{replies, [{connection_reply, FailMsg}]},
- Connection};
+ {[{connection_reply, FailMsg}], Connection};
handle_msg(#ssh_msg_channel_open{sender_channel = RemoteId}, Connection, _) ->
FailMsg = channel_open_failure_msg(RemoteId,
?SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
"Not allowed", "en"),
- {{replies, [{connection_reply, FailMsg}]}, Connection};
+ {[{connection_reply, FailMsg}], Connection};
handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = "exit-status",
data = Data},
- #connection{channel_cache = Cache} = Connection, _) ->
+ Connection, _) ->
<<?UINT32(Status)>> = Data,
- Channel = ssh_channel:cache_lookup(Cache, ChannelId),
- {Reply, Connection} =
- reply_msg(Channel, Connection, {exit_status, ChannelId, Status}),
- {{replies, [Reply]}, Connection};
+ reply_msg(ChannelId, Connection, {exit_status, ChannelId, Status});
handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = "exit-signal",
want_reply = false,
data = Data},
- #connection{channel_cache = Cache} = Connection0, _) ->
- <<?UINT32(SigLen), SigName:SigLen/binary,
- ?BOOLEAN(_Core),
- ?UINT32(ErrLen), Err:ErrLen/binary,
- ?UINT32(LangLen), Lang:LangLen/binary>> = Data,
- Channel = ssh_channel:cache_lookup(Cache, ChannelId),
+ #connection{channel_cache = Cache} = Connection0, _) ->
+ <<?DEC_BIN(SigName, _SigLen),
+ ?BOOLEAN(_Core),
+ ?DEC_BIN(Err, _ErrLen),
+ ?DEC_BIN(Lang, _LangLen)>> = Data,
+ Channel = ssh_client_channel:cache_lookup(Cache, ChannelId),
RemoteId = Channel#channel.remote_id,
{Reply, Connection} = reply_msg(Channel, Connection0,
{exit_signal, ChannelId,
@@ -488,167 +463,139 @@ handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
binary_to_list(Err),
binary_to_list(Lang)}),
CloseMsg = channel_close_msg(RemoteId),
- {{replies, [{connection_reply, CloseMsg}, Reply]},
- Connection};
+ {[{connection_reply, CloseMsg}|Reply], Connection};
handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = "xon-xoff",
want_reply = false,
data = Data},
- #connection{channel_cache = Cache} = Connection, _) ->
+ Connection, _) ->
<<?BOOLEAN(CDo)>> = Data,
- Channel = ssh_channel:cache_lookup(Cache, ChannelId),
- {Reply, Connection} =
- reply_msg(Channel, Connection, {xon_xoff, ChannelId, CDo=/= 0}),
- {{replies, [Reply]}, Connection};
+ reply_msg(ChannelId, Connection, {xon_xoff, ChannelId, CDo=/= 0});
handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = "window-change",
want_reply = false,
data = Data},
- #connection{channel_cache = Cache} = Connection0, _) ->
+ Connection0, _) ->
<<?UINT32(Width),?UINT32(Height),
- ?UINT32(PixWidth), ?UINT32(PixHeight)>> = Data,
- Channel = ssh_channel:cache_lookup(Cache, ChannelId),
- {Reply, Connection} =
- reply_msg(Channel, Connection0, {window_change, ChannelId,
- Width, Height,
- PixWidth, PixHeight}),
- {{replies, [Reply]}, Connection};
+ ?UINT32(PixWidth), ?UINT32(PixHeight)>> = Data,
+ reply_msg(ChannelId, Connection0, {window_change, ChannelId,
+ Width, Height,
+ PixWidth, PixHeight});
handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = "signal",
data = Data},
- #connection{channel_cache = Cache} = Connection0, _) ->
- <<?UINT32(SigLen), SigName:SigLen/binary>> = Data,
-
- Channel = ssh_channel:cache_lookup(Cache, ChannelId),
- {Reply, Connection} =
- reply_msg(Channel, Connection0, {signal, ChannelId,
- binary_to_list(SigName)}),
- {{replies, [Reply]}, Connection};
+ Connection0, _) ->
+ <<?DEC_BIN(SigName, _SigLen)>> = Data,
+ reply_msg(ChannelId, Connection0, {signal, ChannelId,
+ binary_to_list(SigName)});
handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = "subsystem",
want_reply = WantReply,
data = Data},
#connection{channel_cache = Cache} = Connection, server) ->
- <<?UINT32(SsLen), SsName:SsLen/binary>> = Data,
-
- #channel{remote_id = RemoteId} = Channel0 =
- ssh_channel:cache_lookup(Cache, ChannelId),
-
- ReplyMsg = {subsystem, ChannelId, WantReply, binary_to_list(SsName)},
-
- try
- {ok, Pid} = start_subsystem(SsName, Connection, Channel0, ReplyMsg),
- erlang:monitor(process, Pid),
- Channel = Channel0#channel{user = Pid},
- ssh_channel:cache_update(Cache, Channel),
- Reply = {connection_reply,
- channel_success_msg(RemoteId)},
- {{replies, [Reply]}, Connection}
- catch
- _:_ ->
- ErrorReply = {connection_reply,
- channel_failure_msg(RemoteId)},
- {{replies, [ErrorReply]}, Connection}
- end;
+ <<?DEC_BIN(SsName,_SsLen)>> = Data,
+ #channel{remote_id=RemoteId} = Channel =
+ ssh_client_channel:cache_lookup(Cache, ChannelId),
+ Reply =
+ try
+ start_subsystem(SsName, Connection, Channel,
+ {subsystem, ChannelId, WantReply, binary_to_list(SsName)})
+ of
+ {ok, Pid} ->
+ erlang:monitor(process, Pid),
+ ssh_client_channel:cache_update(Cache, Channel#channel{user=Pid}),
+ channel_success_msg(RemoteId);
+ {error,_Error} ->
+ channel_failure_msg(RemoteId)
+ catch
+ _:_ ->
+ channel_failure_msg(RemoteId)
+ end,
+ {[{connection_reply,Reply}], Connection};
handle_msg(#ssh_msg_channel_request{request_type = "subsystem"},
Connection, client) ->
%% The client SHOULD ignore subsystem requests. See RFC 4254 6.5.
- {{replies, []}, Connection};
+ {[], Connection};
handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = "pty-req",
want_reply = WantReply,
data = Data},
- #connection{channel_cache = Cache} = Connection, server) ->
- <<?UINT32(TermLen), BTermName:TermLen/binary,
- ?UINT32(Width),?UINT32(Height),
- ?UINT32(PixWidth), ?UINT32(PixHeight),
- Modes/binary>> = Data,
+ Connection, server) ->
+ <<?DEC_BIN(BTermName,_TermLen),
+ ?UINT32(Width),?UINT32(Height),
+ ?UINT32(PixWidth), ?UINT32(PixHeight),
+ Modes/binary>> = Data,
TermName = binary_to_list(BTermName),
-
PtyRequest = {TermName, Width, Height,
PixWidth, PixHeight, decode_pty_opts(Modes)},
-
- Channel = ssh_channel:cache_lookup(Cache, ChannelId),
- handle_cli_msg(Connection, Channel,
+ handle_cli_msg(Connection, ChannelId,
{pty, ChannelId, WantReply, PtyRequest});
handle_msg(#ssh_msg_channel_request{request_type = "pty-req"},
Connection, client) ->
%% The client SHOULD ignore pty requests. See RFC 4254 6.2.
- {{replies, []}, Connection};
+ {[], Connection};
handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = "shell",
want_reply = WantReply},
- #connection{channel_cache = Cache} = Connection, server) ->
-
- Channel = ssh_channel:cache_lookup(Cache, ChannelId),
-
- handle_cli_msg(Connection, Channel,
+ Connection, server) ->
+ handle_cli_msg(Connection, ChannelId,
{shell, ChannelId, WantReply});
handle_msg(#ssh_msg_channel_request{request_type = "shell"},
Connection, client) ->
%% The client SHOULD ignore shell requests. See RFC 4254 6.5.
- {{replies, []}, Connection};
+ {[], Connection};
handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = "exec",
want_reply = WantReply,
data = Data},
- #connection{channel_cache = Cache} = Connection, server) ->
- <<?UINT32(Len), Command:Len/binary>> = Data,
-
- Channel = ssh_channel:cache_lookup(Cache, ChannelId),
-
- handle_cli_msg(Connection, Channel,
+ Connection, server) ->
+ <<?DEC_BIN(Command, _Len)>> = Data,
+ handle_cli_msg(Connection, ChannelId,
{exec, ChannelId, WantReply, binary_to_list(Command)});
handle_msg(#ssh_msg_channel_request{request_type = "exec"},
Connection, client) ->
%% The client SHOULD ignore exec requests. See RFC 4254 6.5.
- {{replies, []}, Connection};
+ {[], Connection};
handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = "env",
want_reply = WantReply,
data = Data},
- #connection{channel_cache = Cache} = Connection, server) ->
-
- <<?UINT32(VarLen),
- Var:VarLen/binary, ?UINT32(ValueLen), Value:ValueLen/binary>> = Data,
-
- Channel = ssh_channel:cache_lookup(Cache, ChannelId),
-
- handle_cli_msg(Connection, Channel,
+ Connection, server) ->
+ <<?DEC_BIN(Var,_VarLen), ?DEC_BIN(Value,_ValLen)>> = Data,
+ handle_cli_msg(Connection, ChannelId,
{env, ChannelId, WantReply, Var, Value});
handle_msg(#ssh_msg_channel_request{request_type = "env"},
Connection, client) ->
%% The client SHOULD ignore env requests.
- {{replies, []}, Connection};
+ {[], Connection};
handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = _Other,
want_reply = WantReply},
#connection{channel_cache = Cache} = Connection, _) ->
if WantReply == true ->
- case ssh_channel:cache_lookup(Cache, ChannelId) of
+ case ssh_client_channel:cache_lookup(Cache, ChannelId) of
#channel{remote_id = RemoteId} ->
FailMsg = channel_failure_msg(RemoteId),
- {{replies, [{connection_reply, FailMsg}]},
- Connection};
+ {[{connection_reply, FailMsg}], Connection};
undefined -> %% Chanel has been closed
- {noreply, Connection}
+ {[], Connection}
end;
true ->
- {noreply, Connection}
+ {[], Connection}
end;
handle_msg(#ssh_msg_global_request{name = _Type,
@@ -656,79 +603,54 @@ handle_msg(#ssh_msg_global_request{name = _Type,
data = _Data}, Connection, _) ->
if WantReply == true ->
FailMsg = request_failure_msg(),
- {{replies, [{connection_reply, FailMsg}]},
- Connection};
+ {[{connection_reply, FailMsg}], Connection};
true ->
- {noreply, Connection}
+ {[], Connection}
end;
handle_msg(#ssh_msg_request_failure{},
#connection{requests = [{_, From} | Rest]} = Connection, _) ->
- {{replies, [{channel_request_reply, From, {failure, <<>>}}]},
+ {[{channel_request_reply, From, {failure, <<>>}}],
Connection#connection{requests = Rest}};
+
handle_msg(#ssh_msg_request_success{data = Data},
#connection{requests = [{_, From} | Rest]} = Connection, _) ->
- {{replies, [{channel_request_reply, From, {success, Data}}]},
+ {[{channel_request_reply, From, {success, Data}}],
Connection#connection{requests = Rest}};
handle_msg(#ssh_msg_disconnect{code = Code,
- description = Description,
- language = _Lang },
- #connection{channel_cache = Cache} = Connection0, _) ->
- {Connection, Replies} =
- ssh_channel:cache_foldl(fun(Channel, {Connection1, Acc}) ->
- {Reply, Connection2} =
- reply_msg(Channel,
- Connection1,
- {closed, Channel#channel.local_id}),
- {Connection2, [Reply | Acc]}
- end, {Connection0, []}, Cache),
-
- ssh_channel:cache_delete(Cache),
- {disconnect, {Code, Description}, {{replies, Replies}, Connection}}.
-
-handle_cli_msg(#connection{channel_cache = Cache} = Connection,
- #channel{user = undefined,
- remote_id = RemoteId,
- local_id = ChannelId} = Channel0, Reply0) ->
- case (catch start_cli(Connection, ChannelId)) of
- {ok, Pid} ->
- erlang:monitor(process, Pid),
- Channel = Channel0#channel{user = Pid},
- ssh_channel:cache_update(Cache, Channel),
- {Reply, Connection1} = reply_msg(Channel, Connection, Reply0),
- {{replies, [Reply]}, Connection1};
- _Other ->
- Reply = {connection_reply,
- channel_failure_msg(RemoteId)},
- {{replies, [Reply]}, Connection}
- end;
+ description = Description},
+ Connection, _) ->
+ {disconnect, {Code, Description}, handle_stop(Connection)}.
-handle_cli_msg(Connection0, Channel, Reply0) ->
- {Reply, Connection} = reply_msg(Channel, Connection0, Reply0),
- {{replies, [Reply]}, Connection}.
-
-channel_eof_msg(ChannelId) ->
- #ssh_msg_channel_eof{recipient_channel = ChannelId}.
-
-channel_close_msg(ChannelId) ->
- #ssh_msg_channel_close {recipient_channel = ChannelId}.
-
-channel_status_msg({success, ChannelId}) ->
- channel_success_msg(ChannelId);
-channel_status_msg({failure, ChannelId}) ->
- channel_failure_msg(ChannelId).
-
-channel_success_msg(ChannelId) ->
- #ssh_msg_channel_success{recipient_channel = ChannelId}.
-
-channel_failure_msg(ChannelId) ->
- #ssh_msg_channel_failure{recipient_channel = ChannelId}.
+%%%----------------------------------------------------------------
+%%% Returns pending responses to be delivered to the peer when a
+%%% Channel/Connection closes
+%%%
+handle_stop(#connection{channel_cache = Cache} = Connection0) ->
+ {Connection, Replies} =
+ ssh_client_channel:cache_foldl(
+ fun(Channel, {Connection1, Acc}) ->
+ {Reply, Connection2} =
+ reply_msg(Channel, Connection1,
+ {closed, Channel#channel.local_id}),
+ {Connection2, Reply ++ Acc}
+ end, {Connection0, []}, Cache),
+ ssh_client_channel:cache_delete(Cache),
+ {Replies, Connection}.
+
+%%%----------------------------------------------------------------
+%%% channel_*_msg(...)
+%%% Returns a #ssh_msg_....{} for channel operations.
+%%%
channel_adjust_window_msg(ChannelId, Bytes) ->
#ssh_msg_channel_window_adjust{recipient_channel = ChannelId,
bytes_to_add = Bytes}.
+channel_close_msg(ChannelId) ->
+ #ssh_msg_channel_close {recipient_channel = ChannelId}.
+
channel_data_msg(ChannelId, 0, Data) ->
#ssh_msg_channel_data{recipient_channel = ChannelId,
data = Data};
@@ -737,6 +659,12 @@ channel_data_msg(ChannelId, Type, Data) ->
data_type_code = Type,
data = Data}.
+channel_eof_msg(ChannelId) ->
+ #ssh_msg_channel_eof{recipient_channel = ChannelId}.
+
+channel_failure_msg(ChannelId) ->
+ #ssh_msg_channel_failure{recipient_channel = ChannelId}.
+
channel_open_msg(Type, ChannelId, WindowSize, MaxPacketSize, Data) ->
#ssh_msg_channel_open{channel_type = Type,
sender_channel = ChannelId,
@@ -757,18 +685,34 @@ channel_open_failure_msg(RemoteId, Reason, Description, Lang) ->
description = Description,
lang = Lang}.
+channel_status_msg({success, ChannelId}) ->
+ channel_success_msg(ChannelId);
+
+channel_status_msg({failure, ChannelId}) ->
+ channel_failure_msg(ChannelId).
+
channel_request_msg(ChannelId, Type, WantReply, Data) ->
#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = Type,
want_reply = WantReply,
data = Data}.
+channel_success_msg(ChannelId) ->
+ #ssh_msg_channel_success{recipient_channel = ChannelId}.
+
+%%%----------------------------------------------------------------
+%%% request_*_msg(...)
+%%% Returns a #ssh_msg_....{} for request responses.
+%%%
request_failure_msg() ->
#ssh_msg_request_failure{}.
request_success_msg(Data) ->
#ssh_msg_request_success{data = Data}.
+%%%----------------------------------------------------------------
+%%%
+%%%
bind(IP, Port, ChannelPid, Connection) ->
Binds = [{{IP, Port}, ChannelPid}
| lists:keydelete({IP, Port}, 1,
@@ -808,53 +752,91 @@ encode_ip(Addr) when is_list(Addr) ->
end
end.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%
+%%% Internal functions
+%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%----------------------------------------------------------------
+%%% Create the channel data when an ssh_msg_open_channel message
+%%% of "session" typ is handled
+%%%
+setup_session(#connection{channel_cache = Cache,
+ channel_id_seed = NewChannelID
+ } = C,
+ RemoteId, Type, WindowSize, PacketSize) ->
+ NextChannelID = NewChannelID + 1,
+ Channel =
+ #channel{type = Type,
+ sys = "ssh",
+ local_id = NewChannelID,
+ recv_window_size = ?DEFAULT_WINDOW_SIZE,
+ recv_packet_size = ?DEFAULT_PACKET_SIZE,
+ send_window_size = WindowSize,
+ send_packet_size = PacketSize,
+ send_buf = queue:new(),
+ remote_id = RemoteId
+ },
+ ssh_client_channel:cache_update(Cache, Channel),
+ OpenConfMsg = channel_open_confirmation_msg(RemoteId, NewChannelID,
+ ?DEFAULT_WINDOW_SIZE,
+ ?DEFAULT_PACKET_SIZE),
+ Reply = {connection_reply, OpenConfMsg},
+ {[Reply], C#connection{channel_id_seed = NextChannelID}}.
+
+
+%%%----------------------------------------------------------------
+%%% Start a cli or subsystem
+%%%
+start_cli(#connection{options = Options,
+ cli_spec = CliSpec,
+ exec = Exec,
+ sub_system_supervisor = SubSysSup}, ChannelId) ->
+ case CliSpec of
+ no_cli ->
+ {error, cli_disabled};
+ {CbModule, Args} ->
+ start_channel(CbModule, ChannelId, Args, SubSysSup, Exec, Options)
+ end.
+
+
+start_subsystem(BinName, #connection{options = Options,
+ sub_system_supervisor = SubSysSup},
+ #channel{local_id = ChannelId}, _ReplyMsg) ->
+ Name = binary_to_list(BinName),
+ case check_subsystem(Name, Options) of
+ {Callback, Opts} when is_atom(Callback), Callback =/= none ->
+ start_channel(Callback, ChannelId, Opts, SubSysSup, Options);
+ {Other, _} when Other =/= none ->
+ {error, legacy_option_not_supported}
+ end.
+
+
+%%% Helpers for starting cli/subsystems
start_channel(Cb, Id, Args, SubSysSup, Opts) ->
start_channel(Cb, Id, Args, SubSysSup, undefined, Opts).
start_channel(Cb, Id, Args, SubSysSup, Exec, Opts) ->
- ChildSpec = child_spec(Cb, Id, Args, Exec),
ChannelSup = ssh_subsystem_sup:channel_supervisor(SubSysSup),
- assert_limit_num_channels_not_exceeded(ChannelSup, Opts),
- ssh_channel_sup:start_child(ChannelSup, ChildSpec).
+ case max_num_channels_not_exceeded(ChannelSup, Opts) of
+ true ->
+ case ssh_server_channel_sup:start_child(ChannelSup, Cb, Id, Args, Exec) of
+ {error,{Error,_Info}} ->
+ throw(Error);
+ Others ->
+ Others
+ end;
+ false ->
+ throw(max_num_channels_exceeded)
+ end.
-assert_limit_num_channels_not_exceeded(ChannelSup, Opts) ->
+max_num_channels_not_exceeded(ChannelSup, Opts) ->
MaxNumChannels = ?GET_OPT(max_channels, Opts),
- NumChannels = length([x || {_,_,worker,[ssh_channel]} <-
+ NumChannels = length([x || {_,_,worker,[ssh_server_channel]} <-
supervisor:which_children(ChannelSup)]),
- if
- %% Note that NumChannels is BEFORE starting a new one
- NumChannels < MaxNumChannels ->
- ok;
- true ->
- throw(max_num_channels_exceeded)
- end.
-
-%%--------------------------------------------------------------------
-%%% Internal functions
-%%--------------------------------------------------------------------
-setup_session(#connection{channel_cache = Cache
- } = Connection0,
- RemoteId,
- Type, WindowSize, PacketSize) ->
- {ChannelId, Connection} = new_channel_id(Connection0),
-
- Channel = #channel{type = Type,
- sys = "ssh",
- local_id = ChannelId,
- recv_window_size = ?DEFAULT_WINDOW_SIZE,
- recv_packet_size = ?DEFAULT_PACKET_SIZE,
- send_window_size = WindowSize,
- send_packet_size = PacketSize,
- send_buf = queue:new(),
- remote_id = RemoteId
- },
- ssh_channel:cache_update(Cache, Channel),
- OpenConfMsg = channel_open_confirmation_msg(RemoteId, ChannelId,
- ?DEFAULT_WINDOW_SIZE,
- ?DEFAULT_PACKET_SIZE),
-
- {{replies, [{connection_reply, OpenConfMsg}]}, Connection}.
-
+ %% Note that NumChannels is BEFORE starting a new one
+ NumChannels < MaxNumChannels.
check_subsystem("sftp"= SsName, Options) ->
case ?GET_OPT(subsystems, Options) of
@@ -874,72 +856,10 @@ check_subsystem(SsName, Options) ->
Value
end.
-child_spec(Callback, Id, Args, Exec) ->
- Name = make_ref(),
- StartFunc = {ssh_channel, start_link, [self(), Id, Callback, Args, Exec]},
- Restart = temporary,
- Shutdown = 3600,
- Type = worker,
- {Name, StartFunc, Restart, Shutdown, Type, [ssh_channel]}.
-
-start_cli(#connection{cli_spec = no_cli}, _) ->
- {error, cli_disabled};
-start_cli(#connection{options = Options,
- cli_spec = {CbModule, Args},
- exec = Exec,
- sub_system_supervisor = SubSysSup}, ChannelId) ->
- start_channel(CbModule, ChannelId, Args, SubSysSup, Exec, Options).
-
-start_subsystem(BinName, #connection{options = Options,
- sub_system_supervisor = SubSysSup},
- #channel{local_id = ChannelId}, _ReplyMsg) ->
- Name = binary_to_list(BinName),
- case check_subsystem(Name, Options) of
- {Callback, Opts} when is_atom(Callback), Callback =/= none ->
- start_channel(Callback, ChannelId, Opts, SubSysSup, Options);
- {Other, _} when Other =/= none ->
- {error, legacy_option_not_supported}
- end.
-
-channel_data_reply(_, #channel{local_id = ChannelId} = Channel,
- Connection0, DataType, Data) ->
- {Reply, Connection} =
- reply_msg(Channel, Connection0, {data, ChannelId, DataType, Data}),
- {[Reply], Connection}.
-
-new_channel_id(Connection) ->
- ID = Connection#connection.channel_id_seed,
- {ID, Connection#connection{channel_id_seed = ID + 1}}.
-
-reply_msg(Channel, Connection, {open, _} = Reply) ->
- request_reply_or_data(Channel, Connection, Reply);
-reply_msg(Channel, Connection, {open_error, _, _, _} = Reply) ->
- request_reply_or_data(Channel, Connection, Reply);
-reply_msg(Channel, Connection, success = Reply) ->
- request_reply_or_data(Channel, Connection, Reply);
-reply_msg(Channel, Connection, failure = Reply) ->
- request_reply_or_data(Channel, Connection, Reply);
-reply_msg(Channel, Connection, {closed, _} = Reply) ->
- request_reply_or_data(Channel, Connection, Reply);
-reply_msg(undefined, Connection, _Reply) ->
- {noreply, Connection};
-reply_msg(#channel{user = ChannelPid}, Connection, Reply) ->
- {{channel_data, ChannelPid, Reply}, Connection}.
-
-
-request_reply_or_data(#channel{local_id = ChannelId, user = ChannelPid},
- #connection{requests = Requests} =
- Connection, Reply) ->
- case lists:keysearch(ChannelId, 1, Requests) of
- {value, {ChannelId, From}} ->
- {{channel_request_reply, From, Reply},
- Connection#connection{requests =
- lists:keydelete(ChannelId, 1, Requests)}};
- false when (Reply == success) or (Reply == failure) ->
- {[], Connection};
- false ->
- {{channel_data, ChannelPid, Reply}, Connection}
- end.
+%%%----------------------------------------------------------------
+%%%
+%%% Send-window handling
+%%%
update_send_window(Channel, _, undefined,
#connection{channel_cache = Cache}) ->
@@ -952,7 +872,7 @@ update_send_window(#channel{send_buf = SendBuffer} = Channel, DataType, Data,
do_update_send_window(Channel0, Cache) ->
{SendMsgs, Channel} = get_window(Channel0, []),
- ssh_channel:cache_update(Cache, Channel),
+ ssh_client_channel:cache_update(Cache, Channel),
{SendMsgs, Channel}.
get_window(#channel{send_window_size = 0
@@ -994,17 +914,22 @@ handle_send_window({Type, Data}, _, PacketSize, WindowSize, Acc) ->
<<Msg1:PacketSize/binary, Msg2/binary>> = Data,
{WindowSize - PacketSize, [{Type, Msg1} | Acc], {Type, Msg2}}.
+%%%----------------------------------------------------------------
+%%%
+%%% Flow control
+%%%
+
flow_control(Channel, Cache) ->
flow_control([window_adjusted], Channel, Cache).
flow_control([], Channel, Cache) ->
- ssh_channel:cache_update(Cache, Channel),
+ ssh_client_channel:cache_update(Cache, Channel),
[];
flow_control([_|_], #channel{flow_control = From,
send_buf = Buffer} = Channel, Cache) when From =/= undefined ->
case queue:is_empty(Buffer) of
true ->
- ssh_channel:cache_update(Cache, Channel#channel{flow_control = undefined}),
+ ssh_client_channel:cache_update(Cache, Channel#channel{flow_control = undefined}),
[{flow_control, Cache, Channel, From, ok}];
false ->
[]
@@ -1012,6 +937,11 @@ flow_control([_|_], #channel{flow_control = From,
flow_control(_,_,_) ->
[].
+%%%----------------------------------------------------------------
+%%%
+%%% Pseudo terminal stuff
+%%%
+
pty_req(ConnectionHandler, Channel, Term, Width, Height,
PixWidth, PixHeight, PtyOpts, TimeOut) ->
ssh_connection_handler:request(ConnectionHandler,
@@ -1037,8 +967,7 @@ pty_default_dimensions(Dimension, TermData) ->
encode_pty_opts(Opts) ->
Bin = list_to_binary(encode_pty_opts2(Opts)),
- Len = size(Bin),
- <<?UINT32(Len), Bin/binary>>.
+ <<?STRING(Bin)>>.
encode_pty_opts2([]) ->
[?TTY_OP_END];
@@ -1157,7 +1086,7 @@ decode_pty_opts(<<>>) ->
[];
decode_pty_opts(<<0, 0, 0, 0>>) ->
[];
-decode_pty_opts(<<?UINT32(Len), Modes:Len/binary>>) ->
+decode_pty_opts(<<?DEC_BIN(Modes,_Len)>>) ->
decode_pty_opts2(Modes);
decode_pty_opts(Binary) ->
decode_pty_opts2(Binary).
@@ -1234,3 +1163,104 @@ backwards_compatible([{pixel_hight, Value} | Rest], Acc) ->
backwards_compatible(Rest, [{height, Value} | Acc]);
backwards_compatible([Value| Rest], Acc) ->
backwards_compatible(Rest, [ Value | Acc]).
+
+
+%%%----------------------------------------------------------------
+%%%
+%%% Common part of handling channel messages meant for a cli (like "env", "exec" etc)
+%%% Called at the finnish of handle_msg(#ssh_msg_channel_request,...)
+%%%
+
+handle_cli_msg(C0, ChId, Reply0) ->
+ Cache = C0#connection.channel_cache,
+ Ch0 = ssh_client_channel:cache_lookup(Cache, ChId),
+ case Ch0#channel.user of
+ undefined ->
+ case (catch start_cli(C0, ChId)) of
+ {ok, Pid} ->
+ erlang:monitor(process, Pid),
+ Ch = Ch0#channel{user = Pid},
+ ssh_client_channel:cache_update(Cache, Ch),
+ reply_msg(Ch, C0, Reply0);
+ _Other ->
+ Reply = {connection_reply, channel_failure_msg(Ch0#channel.remote_id)},
+ {[Reply], C0}
+ end;
+
+ _ ->
+ reply_msg(Ch0, C0, Reply0)
+ end.
+
+%%%----------------------------------------------------------------
+%%%
+%%% Request response handling on return to the calling ssh_connection_handler
+%%% state machine.
+%%%
+
+channel_data_reply_msg(ChannelId, Connection, DataType, Data) ->
+ case ssh_client_channel:cache_lookup(Connection#connection.channel_cache, ChannelId) of
+ #channel{recv_window_size = Size} = Channel ->
+ WantedSize = Size - size(Data),
+ ssh_client_channel:cache_update(Connection#connection.channel_cache,
+ Channel#channel{recv_window_size = WantedSize}),
+ reply_msg(Channel, Connection, {data, ChannelId, DataType, Data});
+ undefined ->
+ {[], Connection}
+ end.
+
+
+reply_msg(ChId, C, Reply) when is_integer(ChId) ->
+ reply_msg(ssh_client_channel:cache_lookup(C#connection.channel_cache, ChId), C, Reply);
+
+reply_msg(Channel, Connection, {open, _} = Reply) ->
+ request_reply_or_data(Channel, Connection, Reply);
+reply_msg(Channel, Connection, {open_error, _, _, _} = Reply) ->
+ request_reply_or_data(Channel, Connection, Reply);
+reply_msg(Channel, Connection, success = Reply) ->
+ request_reply_or_data(Channel, Connection, Reply);
+reply_msg(Channel, Connection, failure = Reply) ->
+ request_reply_or_data(Channel, Connection, Reply);
+reply_msg(Channel, Connection, {closed, _} = Reply) ->
+ request_reply_or_data(Channel, Connection, Reply);
+reply_msg(undefined, Connection, _Reply) ->
+ {[], Connection};
+reply_msg(#channel{user = ChannelPid}, Connection, Reply) ->
+ {[{channel_data, ChannelPid, Reply}], Connection}.
+
+
+request_reply_or_data(#channel{local_id = ChannelId, user = ChannelPid},
+ #connection{requests = Requests} =
+ Connection, Reply) ->
+ case lists:keysearch(ChannelId, 1, Requests) of
+ {value, {ChannelId, From}} ->
+ {[{channel_request_reply, From, Reply}],
+ Connection#connection{requests =
+ lists:keydelete(ChannelId, 1, Requests)}};
+ false when (Reply == success) or (Reply == failure) ->
+ {[], Connection};
+ false ->
+ {[{channel_data, ChannelPid, Reply}], Connection}
+ end.
+
+
+
+%%%----------------------------------------------------------------
+%%% l(ist)2b(inary)
+%%%
+l2b(L) when is_integer(hd(L)) ->
+ try list_to_binary(L)
+ of
+ B -> B
+ catch
+ _:_ ->
+ unicode:characters_to_binary(L)
+ end;
+l2b([H|T]) ->
+ << (l2b(H))/binary, (l2b(T))/binary >>;
+l2b(B) when is_binary(B) ->
+ B;
+l2b([]) ->
+ <<>>.
+
+
+
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index 8d3ddb09a4..4b41c10cbb 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -46,6 +46,7 @@
%%% Internal application API
-export([start_connection/4,
+ available_hkey_algorithms/2,
open_channel/6,
request/6, request/7,
reply_request/3,
@@ -55,10 +56,13 @@
connection_info/2,
channel_info/3,
adjust_window/3, close/2,
- disconnect/1, disconnect/2,
+ disconnect/4,
get_print_info/1
]).
+-type connection_ref() :: ssh:connection_ref().
+-type channel_id() :: ssh:channel_id().
+
%%% Behaviour callbacks
-export([init/1, callback_mode/0, handle_event/4, terminate/3,
format_status/2, code_change/4]).
@@ -67,16 +71,28 @@
-export([init_connection_handler/3, % proc_lib:spawn needs this
init_ssh_record/3, % Export of this internal function
% intended for low-level protocol test suites
- renegotiate/1, renegotiate_data/1 % Export intended for test cases
+ renegotiate/1, alg/1 % Export intended for test cases
]).
+-export([dbg_trace/3]).
+
+
+-define(send_disconnect(Code, DetailedText, StateName, State),
+ send_disconnect(Code, DetailedText, ?MODULE, ?LINE, StateName, State)).
+
+-define(send_disconnect(Code, Reason, DetailedText, StateName, State),
+ send_disconnect(Code, Reason, DetailedText, ?MODULE, ?LINE, StateName, State)).
+
+-define(call_disconnectfun_and_log_cond(LogMsg, DetailedText, StateName, D),
+ call_disconnectfun_and_log_cond(LogMsg, DetailedText, ?MODULE, ?LINE, StateName, D)).
+
%%====================================================================
%% Start / stop
%%====================================================================
%%--------------------------------------------------------------------
-spec start_link(role(),
- inet:socket(),
- ssh_options:options()
+ gen_tcp:socket(),
+ internal_options()
) -> {ok, pid()}.
%% . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
start_link(Role, Socket, Options) ->
@@ -105,8 +121,8 @@ stop(ConnectionHandler)->
%%--------------------------------------------------------------------
-spec start_connection(role(),
- inet:socket(),
- ssh_options:options(),
+ gen_tcp:socket(),
+ internal_options(),
timeout()
) -> {ok, connection_ref()} | {error, term()}.
%% . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
@@ -148,17 +164,16 @@ start_connection(server = Role, Socket, Options, Timeout) ->
%%--------------------------------------------------------------------
%%% Some other module has decided to disconnect.
--spec disconnect(#ssh_msg_disconnect{}) -> no_return().
--spec disconnect(#ssh_msg_disconnect{}, iodata()) -> no_return().
+
+-spec disconnect(Code::integer(), Details::iodata(),
+ Module::atom(), Line::integer()) -> no_return().
%% . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-disconnect(Msg = #ssh_msg_disconnect{}) ->
- throw({keep_state_and_data,
- [{next_event, internal, {disconnect, Msg, Msg#ssh_msg_disconnect.description}}]}).
-disconnect(Msg = #ssh_msg_disconnect{}, ExtraInfo) ->
- throw({keep_state_and_data,
- [{next_event, internal, {disconnect, Msg, {Msg#ssh_msg_disconnect.description,ExtraInfo}}}]}).
+% Preferable called with the macro ?DISCONNECT
+disconnect(Code, DetailedText, Module, Line) ->
+ throw({keep_state_and_data,
+ [{next_event, internal, {send_disconnect, Code, DetailedText, Module, Line}}]}).
%%--------------------------------------------------------------------
-spec open_channel(connection_ref(),
@@ -310,43 +325,44 @@ close(ConnectionHandler, ChannelId) ->
) -> ok.
%% . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
renegotiate(ConnectionHandler) ->
- cast(ConnectionHandler, renegotiate).
+ cast(ConnectionHandler, force_renegotiate).
%%--------------------------------------------------------------------
--spec renegotiate_data(connection_ref()
- ) -> ok.
-%% . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-renegotiate_data(ConnectionHandler) ->
- cast(ConnectionHandler, data_size).
-
+alg(ConnectionHandler) ->
+ call(ConnectionHandler, get_alg).
%%====================================================================
%% Internal process state
%%====================================================================
-record(data, {
- starter :: pid(),
+ starter :: pid()
+ | undefined,
auth_user :: string()
| undefined,
connection_state :: #connection{},
- latest_channel_id = 0 :: non_neg_integer(),
- idle_timer_ref :: undefined
- | infinity
- | reference(),
- idle_timer_value = infinity :: infinity
- | pos_integer(),
- transport_protocol :: atom(), % ex: tcp
- transport_cb :: atom(), % ex: gen_tcp
- transport_close_tag :: atom(), % ex: tcp_closed
- ssh_params :: #ssh{},
- socket :: inet:socket(),
- decrypted_data_buffer = <<>> :: binary(),
- encrypted_data_buffer = <<>> :: binary(),
+ latest_channel_id = 0 :: non_neg_integer()
+ | undefined,
+ transport_protocol :: atom()
+ | undefined, % ex: tcp
+ transport_cb :: atom()
+ | undefined, % ex: gen_tcp
+ transport_close_tag :: atom()
+ | undefined, % ex: tcp_closed
+ ssh_params :: #ssh{}
+ | undefined,
+ socket :: gen_tcp:socket()
+ | undefined,
+ decrypted_data_buffer = <<>> :: binary()
+ | undefined,
+ encrypted_data_buffer = <<>> :: binary()
+ | undefined,
+ aead_data = <<>> :: binary()
+ | undefined,
undecrypted_packet_length :: undefined | non_neg_integer(),
key_exchange_init_msg :: #ssh_msg_kexinit{}
| undefined,
last_size_rekey = 0 :: non_neg_integer(),
event_queue = [] :: list(),
-% opts :: ssh_options:options(),
inet_initial_recbuf_size :: pos_integer()
| undefined
}).
@@ -356,8 +372,8 @@ renegotiate_data(ConnectionHandler) ->
%%====================================================================
%%--------------------------------------------------------------------
-spec init_connection_handler(role(),
- inet:socket(),
- ssh_options:options()
+ gen_tcp:socket(),
+ internal_options()
) -> no_return().
%% . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
init_connection_handler(Role, Socket, Opts) ->
@@ -369,16 +385,17 @@ init_connection_handler(Role, Socket, Opts) ->
StartState,
D);
- {stop, enotconn} ->
- %% Handles the abnormal sequence:
- %% SYN->
- %% <-SYNACK
- %% ACK->
- %% RST->
- exit({shutdown, "TCP connection to server was prematurely closed by the client"});
-
- {stop, OtherError} ->
- exit({shutdown, {init,OtherError}})
+ {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)
+ },
+ gen_statem:enter_loop(?MODULE,
+ [],
+ {init_error,Error},
+ #data{connection_state=C,
+ socket=Socket})
end.
@@ -387,7 +404,7 @@ init([Role,Socket,Opts]) ->
case inet:peername(Socket) of
{ok, PeerAddr} ->
{Protocol, Callback, CloseTag} = ?GET_OPT(transport, Opts),
- C = #connection{channel_cache = ssh_channel:cache_create(),
+ C = #connection{channel_cache = ssh_client_channel:cache_create(),
channel_id_seed = 0,
port_bindings = [],
requests = [],
@@ -402,20 +419,16 @@ init([Role,Socket,Opts]) ->
},
D = case Role of
client ->
- %% Start the renegotiation timers
- timer:apply_after(?REKEY_TIMOUT, gen_statem, cast, [self(), renegotiate]),
- timer:apply_after(?REKEY_DATA_TIMOUT, gen_statem, cast, [self(), data_size]),
- cache_init_idle_timer(D0);
+ D0;
server ->
Sups = ?GET_INTERNAL_OPT(supervisors, Opts),
- cache_init_idle_timer(
- D0#data{connection_state =
- C#connection{cli_spec = ?GET_OPT(ssh_cli, Opts, {ssh_cli,[?GET_OPT(shell, Opts)]}),
- exec = ?GET_OPT(exec, Opts),
- 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)
- }})
+ D0#data{connection_state =
+ C#connection{cli_spec = ?GET_OPT(ssh_cli, Opts, {ssh_cli,[?GET_OPT(shell, Opts)]}),
+ exec = ?GET_OPT(exec, Opts),
+ 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)
+ }}
end,
{ok, {hello,Role}, D};
@@ -431,18 +444,21 @@ init_ssh_record(Role, Socket, Opts) ->
{ok,PeerAddr} = inet:peername(Socket),
init_ssh_record(Role, Socket, PeerAddr, Opts).
-init_ssh_record(Role, _Socket, PeerAddr, Opts) ->
- KeyCb = ?GET_OPT(key_cb, Opts),
+init_ssh_record(Role, Socket, PeerAddr, Opts) ->
AuthMethods = ?GET_OPT(auth_methods, Opts),
S0 = #ssh{role = Role,
- key_cb = KeyCb,
+ key_cb = ?GET_OPT(key_cb, Opts),
opts = Opts,
userauth_supported_methods = AuthMethods,
- available_host_keys = supported_host_keys(Role, KeyCb, Opts),
+ available_host_keys = available_hkey_algorithms(Role, Opts),
random_length_padding = ?GET_OPT(max_random_length_padding, Opts)
},
{Vsn, Version} = ssh_transport:versions(Role, Opts),
+ LocalName = case inet:sockname(Socket) of
+ {ok,Local} -> Local;
+ _ -> undefined
+ end,
case Role of
client ->
PeerName = case ?GET_INTERNAL_OPT(host, Opts) of
@@ -461,7 +477,8 @@ init_ssh_record(Role, _Socket, PeerAddr, Opts) ->
false -> ssh_no_io
end,
userauth_quiet_mode = ?GET_OPT(quiet_mode, Opts),
- peer = {PeerName, PeerAddr}
+ peer = {PeerName, PeerAddr},
+ local = LocalName
},
S1#ssh{userauth_pubkeys = [K || K <- ?GET_OPT(pref_public_key_algs, Opts),
is_usable_user_pubkey(K, S1)
@@ -474,7 +491,8 @@ init_ssh_record(Role, _Socket, PeerAddr, Opts) ->
io_cb = ?GET_INTERNAL_OPT(io_cb, Opts, ssh_io),
userauth_methods = string:tokens(AuthMethods, ","),
kb_tries_left = 3,
- peer = {undefined, PeerAddr}
+ peer = {undefined, PeerAddr},
+ local = LocalName
}
end.
@@ -512,7 +530,7 @@ role({_,Role}) -> Role;
role({_,Role,_}) -> Role.
-spec renegotiation(state_name()) -> boolean().
-renegotiation({_,_,ReNeg}) -> ReNeg == renegotiation;
+renegotiation({_,_,ReNeg}) -> ReNeg == renegotiate;
renegotiation(_) -> false.
@@ -526,14 +544,37 @@ renegotiation(_) -> false.
#data{}
) -> gen_statem:event_handler_result(state_name()) .
+-define(CONNECTION_MSG(Msg),
+ [{next_event, internal, prepare_next_packet},
+ {next_event,internal,{conn_msg,Msg}}]).
+
%% . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
callback_mode() ->
- handle_event_function.
+ [handle_event_function,
+ state_enter].
+
+
+handle_event(_, _Event, {init_error,Error}=StateName, D) ->
+ case Error of
+ enotconn ->
+ %% Handles the abnormal sequence:
+ %% SYN->
+ %% <-SYNACK
+ %% ACK->
+ %% RST->
+ ?call_disconnectfun_and_log_cond("Protocol Error",
+ "TCP connenction to server was prematurely closed by the client",
+ StateName, D),
+ {stop, {shutdown,"TCP connenction to server was prematurely closed by the client"}};
+
+ OtherError ->
+ {stop, {shutdown,{init,OtherError}}}
+ end;
%%% ######## {hello, client|server} ####
%% The very first event that is sent when the we are set as controlling process of Socket
-handle_event(_, socket_control, {hello,_}, D) ->
+handle_event(_, socket_control, {hello,_}=StateName, D) ->
VsnMsg = ssh_transport:hello_version_msg(string_version(D#data.ssh_params)),
send_bytes(VsnMsg, D),
case inet:getopts(Socket=D#data.socket, [recbuf]) of
@@ -548,10 +589,13 @@ handle_event(_, socket_control, {hello,_}, D) ->
{keep_state, D#data{inet_initial_recbuf_size=Size}};
Other ->
+ ?call_disconnectfun_and_log_cond("Option return",
+ io_lib:format("Unexpected getopts return:~n ~p",[Other]),
+ StateName, D),
{stop, {shutdown,{unexpected_getopts_return, Other}}}
end;
-handle_event(_, {info_line,_Line}, {hello,Role}, D) ->
+handle_event(_, {info_line,_Line}, {hello,Role}=StateName, D) ->
case Role of
client ->
%% The server may send info lines to the client before the version_exchange
@@ -562,28 +606,33 @@ handle_event(_, {info_line,_Line}, {hello,Role}, D) ->
%% But the client may NOT send them to the server. Openssh answers with cleartext,
%% and so do we
send_bytes("Protocol mismatch.", D),
+ ?call_disconnectfun_and_log_cond("Protocol mismatch.",
+ "Protocol mismatch in version exchange. Client sent info lines.",
+ StateName, D),
{stop, {shutdown,"Protocol mismatch in version exchange. Client sent info lines."}}
end;
-handle_event(_, {version_exchange,Version}, {hello,Role}, D) ->
+handle_event(_, {version_exchange,Version}, {hello,Role}, D0) ->
{NumVsn, StrVsn} = ssh_transport:handle_hello_version(Version),
- case handle_version(NumVsn, StrVsn, D#data.ssh_params) of
+ case handle_version(NumVsn, StrVsn, D0#data.ssh_params) of
{ok, Ssh1} ->
%% Since the hello part is finnished correctly, we set the
%% socket to the packet handling mode (including recbuf size):
- inet:setopts(D#data.socket, [{packet,0},
+ inet:setopts(D0#data.socket, [{packet,0},
{mode,binary},
{active, once},
- {recbuf, D#data.inet_initial_recbuf_size}]),
+ {recbuf, D0#data.inet_initial_recbuf_size}]),
{KeyInitMsg, SshPacket, Ssh} = ssh_transport:key_exchange_init_msg(Ssh1),
- send_bytes(SshPacket, D),
- {next_state, {kexinit,Role,init}, D#data{ssh_params = Ssh,
+ send_bytes(SshPacket, D0),
+ {next_state, {kexinit,Role,init}, D0#data{ssh_params = Ssh,
key_exchange_init_msg = KeyInitMsg}};
not_supported ->
- disconnect(
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED,
- description = ["Protocol version ",StrVsn," not supported"]},
- {next_state, {hello,Role}, D})
+ {Shutdown, D} =
+ ?send_disconnect(?SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED,
+ io_lib:format("Offending version is ~p",[string:chomp(Version)]),
+ {hello,Role},
+ D0),
+ {stop, Shutdown, D}
end;
@@ -729,18 +778,20 @@ handle_event(internal, Msg, {ext_info,Role,_ReNegFlag}, D) when is_tuple(Msg) ->
%%% ######## {service_request, client|server} ####
-handle_event(_, Msg = #ssh_msg_service_request{name=ServiceName}, StateName = {service_request,server}, D) ->
+handle_event(_, Msg = #ssh_msg_service_request{name=ServiceName}, StateName = {service_request,server}, D0) ->
case ServiceName of
"ssh-userauth" ->
- Ssh0 = #ssh{session_id=SessionId} = D#data.ssh_params,
+ Ssh0 = #ssh{session_id=SessionId} = D0#data.ssh_params,
{ok, {Reply, Ssh}} = ssh_auth:handle_userauth_request(Msg, SessionId, Ssh0),
- send_bytes(Reply, D),
- {next_state, {userauth,server}, D#data{ssh_params = Ssh}};
+ send_bytes(Reply, D0),
+ {next_state, {userauth,server}, D0#data{ssh_params = Ssh}};
_ ->
- disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
- description = "Unknown service"},
- StateName, D)
+ {Shutdown, D} =
+ ?send_disconnect(?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
+ io_lib:format("Unknown service: ~p",[ServiceName]),
+ StateName, D0),
+ {stop, Shutdown, D}
end;
handle_event(_, #ssh_msg_service_accept{name = "ssh-userauth"}, {service_request,client},
@@ -756,15 +807,15 @@ handle_event(_, #ssh_msg_service_accept{name = "ssh-userauth"}, {service_request
handle_event(_,
Msg = #ssh_msg_userauth_request{service = ServiceName, method = Method},
StateName = {userauth,server},
- D = #data{ssh_params=Ssh0}) ->
+ D0 = #data{ssh_params=Ssh0}) ->
case {ServiceName, Ssh0#ssh.service, Method} of
{"ssh-connection", "ssh-connection", "none"} ->
%% Probably the very first userauth_request but we deny unauthorized login
{not_authorized, _, {Reply,Ssh}} =
ssh_auth:handle_userauth_request(Msg, Ssh0#ssh.session_id, Ssh0),
- send_bytes(Reply, D),
- {keep_state, D#data{ssh_params = Ssh}};
+ send_bytes(Reply, D0),
+ {keep_state, D0#data{ssh_params = Ssh}};
{"ssh-connection", "ssh-connection", Method} ->
%% Userauth request with a method like "password" or so
@@ -773,20 +824,20 @@ handle_event(_,
%% Yepp! we support this method
case ssh_auth:handle_userauth_request(Msg, Ssh0#ssh.session_id, Ssh0) of
{authorized, User, {Reply, Ssh}} ->
- send_bytes(Reply, D),
- D#data.starter ! ssh_connected,
- connected_fun(User, Method, D),
+ send_bytes(Reply, D0),
+ D0#data.starter ! ssh_connected,
+ connected_fun(User, Method, D0),
{next_state, {connected,server},
- D#data{auth_user = User,
+ D0#data{auth_user = User,
ssh_params = Ssh#ssh{authenticated = true}}};
{not_authorized, {User, Reason}, {Reply, Ssh}} when Method == "keyboard-interactive" ->
- retry_fun(User, Reason, D),
- send_bytes(Reply, D),
- {next_state, {userauth_keyboard_interactive,server}, D#data{ssh_params = Ssh}};
+ retry_fun(User, Reason, D0),
+ send_bytes(Reply, D0),
+ {next_state, {userauth_keyboard_interactive,server}, D0#data{ssh_params = Ssh}};
{not_authorized, {User, Reason}, {Reply, Ssh}} ->
- retry_fun(User, Reason, D),
- send_bytes(Reply, D),
- {keep_state, D#data{ssh_params = Ssh}}
+ retry_fun(User, Reason, D0),
+ send_bytes(Reply, D0),
+ {keep_state, D0#data{ssh_params = Ssh}}
end;
false ->
%% No we do not support this method (=/= none)
@@ -800,9 +851,11 @@ handle_event(_,
%% {ServiceName, Expected, Method} when Expected =/= ServiceName -> Do what?
{ServiceName, _, _} when ServiceName =/= "ssh-connection" ->
- disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
- description = "Unknown service"},
- StateName, D)
+ {Shutdown, D} =
+ ?send_disconnect(?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
+ io_lib:format("Unknown service: ~p",[ServiceName]),
+ StateName, D0),
+ {stop, Shutdown, D}
end;
%%---- userauth success to client
@@ -818,14 +871,14 @@ handle_event(_, #ssh_msg_userauth_success{}, {userauth,client}, D=#data{ssh_para
%%---- userauth failure response to client
handle_event(_, #ssh_msg_userauth_failure{}, {userauth,client}=StateName,
- D = #data{ssh_params = #ssh{userauth_methods = []}}) ->
- Msg = #ssh_msg_disconnect{code = ?SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE,
- description = "Unable to connect using the available"
- " authentication methods"},
- disconnect(Msg, StateName, D);
-
+ #data{ssh_params = #ssh{userauth_methods = []}} = D0) ->
+ {Shutdown, D} =
+ ?send_disconnect(?SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE,
+ io_lib:format("User auth failed for: ~p",[D0#data.auth_user]),
+ StateName, D0),
+ {stop, Shutdown, D};
handle_event(_, #ssh_msg_userauth_failure{authentications = Methods}, StateName={userauth,client},
- D = #data{ssh_params = Ssh0}) ->
+ D0 = #data{ssh_params = Ssh0}) ->
%% The prefered authentication method failed try next method
Ssh1 = case Ssh0#ssh.userauth_methods of
none ->
@@ -836,15 +889,18 @@ handle_event(_, #ssh_msg_userauth_failure{authentications = Methods}, StateName=
Ssh0
end,
case ssh_auth:userauth_request_msg(Ssh1) of
- {disconnect, DisconnectMsg, {Msg, Ssh}} ->
- send_bytes(Msg, D),
- disconnect(DisconnectMsg, StateName, D#data{ssh_params = Ssh});
+ {send_disconnect, Code, Ssh} ->
+ {Shutdown, D} =
+ ?send_disconnect(Code,
+ io_lib:format("User auth failed for: ~p",[D0#data.auth_user]),
+ StateName, D0#data{ssh_params = Ssh}),
+ {stop, Shutdown, D};
{"keyboard-interactive", {Msg, Ssh}} ->
- send_bytes(Msg, D),
- {next_state, {userauth_keyboard_interactive,client}, D#data{ssh_params = Ssh}};
+ send_bytes(Msg, D0),
+ {next_state, {userauth_keyboard_interactive,client}, D0#data{ssh_params = Ssh}};
{_Method, {Msg, Ssh}} ->
- send_bytes(Msg, D),
- {keep_state, D#data{ssh_params = Ssh}}
+ send_bytes(Msg, D0),
+ {keep_state, D0#data{ssh_params = Ssh}}
end;
%%---- banner to client
@@ -935,10 +991,10 @@ handle_event(_, {#ssh_msg_kexinit{},_}, {connected,Role}, D0) ->
{next_state, {kexinit,Role,renegotiate}, D, [postpone]};
handle_event(_, #ssh_msg_disconnect{description=Desc} = Msg, StateName, D0) ->
- {disconnect, _, {{replies,Replies}, _}} =
+ {disconnect, _, RepliesCon} =
ssh_connection:handle_msg(Msg, D0#data.connection_state, role(StateName)),
- {Actions,D} = send_replies(Replies, D0),
- disconnect_fun(Desc, D),
+ {Actions,D} = send_replies(RepliesCon, D0),
+ disconnect_fun("Received disconnect: "++Desc, D),
{stop_and_reply, {shutdown,Desc}, Actions, D};
handle_event(_, #ssh_msg_ignore{}, _, _) ->
@@ -951,102 +1007,103 @@ handle_event(_, #ssh_msg_debug{} = Msg, _, D) ->
debug_fun(Msg, D),
keep_state_and_data;
-handle_event(internal, Msg=#ssh_msg_global_request{}, StateName, D) ->
- handle_connection_msg(Msg, StateName, D);
-
-handle_event(internal, Msg=#ssh_msg_request_success{}, StateName, D) ->
- handle_connection_msg(Msg, StateName, D);
-
-handle_event(internal, Msg=#ssh_msg_request_failure{}, StateName, D) ->
- handle_connection_msg(Msg, StateName, D);
-
-handle_event(internal, Msg=#ssh_msg_channel_open{}, StateName, D) ->
- handle_connection_msg(Msg, StateName, D);
-
-handle_event(internal, Msg=#ssh_msg_channel_open_confirmation{}, StateName, D) ->
- handle_connection_msg(Msg, StateName, D);
-
-handle_event(internal, Msg=#ssh_msg_channel_open_failure{}, StateName, D) ->
- handle_connection_msg(Msg, StateName, D);
-
-handle_event(internal, Msg=#ssh_msg_channel_window_adjust{}, StateName, D) ->
- handle_connection_msg(Msg, StateName, D);
-
-handle_event(internal, Msg=#ssh_msg_channel_data{}, StateName, D) ->
- handle_connection_msg(Msg, StateName, D);
-
-handle_event(internal, Msg=#ssh_msg_channel_extended_data{}, StateName, D) ->
- handle_connection_msg(Msg, StateName, D);
-
-handle_event(internal, Msg=#ssh_msg_channel_eof{}, StateName, D) ->
- handle_connection_msg(Msg, StateName, D);
-
-handle_event(internal, Msg=#ssh_msg_channel_close{}, {connected,server} = StateName, D) ->
- handle_connection_msg(Msg, StateName, cache_request_idle_timer_check(D));
-
-handle_event(internal, Msg=#ssh_msg_channel_close{}, StateName, D) ->
- handle_connection_msg(Msg, StateName, D);
-
-handle_event(internal, Msg=#ssh_msg_channel_request{}, StateName, D) ->
- handle_connection_msg(Msg, StateName, D);
-
-handle_event(internal, Msg=#ssh_msg_channel_success{}, StateName, D) ->
- update_inet_buffers(D#data.socket),
- handle_connection_msg(Msg, StateName, D);
-
-handle_event(internal, Msg=#ssh_msg_channel_failure{}, StateName, D) ->
- handle_connection_msg(Msg, StateName, D);
-
+handle_event(internal, {conn_msg,Msg}, StateName, #data{starter = User,
+ connection_state = Connection0,
+ event_queue = Qev0} = D0) ->
+ Role = role(StateName),
+ Rengotation = renegotiation(StateName),
+ try ssh_connection:handle_msg(Msg, Connection0, Role) of
+ {disconnect, Reason0, RepliesConn} ->
+ {Repls, D} = send_replies(RepliesConn, D0),
+ case {Reason0,Role} of
+ {{_, Reason}, client} when ((StateName =/= {connected,client})
+ and (not Rengotation)) ->
+ User ! {self(), not_connected, Reason};
+ _ ->
+ ok
+ end,
+ {stop_and_reply, {shutdown,normal}, Repls, D};
-handle_event(cast, renegotiate, {connected,Role}, D) ->
- {KeyInitMsg, SshPacket, Ssh} = ssh_transport:key_exchange_init_msg(D#data.ssh_params),
- send_bytes(SshPacket, D),
- timer:apply_after(?REKEY_TIMOUT, gen_statem, cast, [self(), renegotiate]),
- {next_state, {kexinit,Role,renegotiate}, D#data{ssh_params = Ssh,
- key_exchange_init_msg = KeyInitMsg}};
+ {Replies, Connection} when is_list(Replies) ->
+ {Repls, D} =
+ case StateName of
+ {connected,_} ->
+ send_replies(Replies, D0#data{connection_state=Connection});
+ _ ->
+ {ConnReplies, NonConnReplies} = lists:splitwith(fun not_connected_filter/1, Replies),
+ send_replies(NonConnReplies, D0#data{event_queue = Qev0 ++ ConnReplies})
+ end,
+ case {Msg, StateName} of
+ {#ssh_msg_channel_close{}, {connected,_}} ->
+ {keep_state, D, [cond_set_idle_timer(D)|Repls]};
+ {#ssh_msg_channel_success{}, _} ->
+ update_inet_buffers(D#data.socket),
+ {keep_state, D, Repls};
+ _ ->
+ {keep_state, D, Repls}
+ end
-handle_event(cast, renegotiate, _, _) ->
- %% Already in key-exchange so safe to ignore
- timer:apply_after(?REKEY_TIMOUT, gen_statem, cast, [self(), renegotiate]), % FIXME: not here in original
- keep_state_and_data;
+ catch
+ Class:Error ->
+ {Repls, D1} = send_replies(ssh_connection:handle_stop(Connection0), D0),
+ {Shutdown, D} = ?send_disconnect(?SSH_DISCONNECT_BY_APPLICATION,
+ io_lib:format("Internal error: ~p:~p",[Class,Error]),
+ StateName, D1),
+ {stop_and_reply, Shutdown, Repls, D}
+ end;
-%% Rekey due to sent data limit reached?
-handle_event(cast, data_size, {connected,Role}, D) ->
- {ok, [{send_oct,Sent0}]} = inet:getstat(D#data.socket, [send_oct]),
- Sent = Sent0 - D#data.last_size_rekey,
- MaxSent = ?GET_OPT(rekey_limit, (D#data.ssh_params)#ssh.opts),
- timer:apply_after(?REKEY_DATA_TIMOUT, gen_statem, cast, [self(), data_size]),
- case Sent >= MaxSent of
- true ->
- {KeyInitMsg, SshPacket, Ssh} =
- ssh_transport:key_exchange_init_msg(D#data.ssh_params),
- send_bytes(SshPacket, D),
- {next_state, {kexinit,Role,renegotiate}, D#data{ssh_params = Ssh,
- key_exchange_init_msg = KeyInitMsg,
- last_size_rekey = Sent0}};
- _ ->
- keep_state_and_data
+handle_event(enter, _OldState, {connected,_}=State, D) ->
+ %% Entering the state where re-negotiation is possible
+ init_renegotiate_timers(State, D);
+
+handle_event(enter, _OldState, {ext_info,_,renegotiate}=State, D) ->
+ %% Could be hanging in exit_info state if nothing else arrives
+ init_renegotiate_timers(State, D);
+
+handle_event(enter, {connected,_}, State, D) ->
+ %% Exiting the state where re-negotiation is possible
+ pause_renegotiate_timers(State, D);
+
+handle_event(cast, force_renegotiate, StateName, D) ->
+ handle_event({timeout,renegotiate}, undefined, StateName, D);
+
+handle_event({timeout,renegotiate}, _, StateName, D0) ->
+ case StateName of
+ {connected,Role} ->
+ start_rekeying(Role, D0);
+ {ext_info,Role,renegotiate} ->
+ start_rekeying(Role, D0);
+ _ ->
+ %% Wrong state for starting a renegotiation, must be in re-negotiation
+ keep_state_and_data
end;
-handle_event(cast, data_size, _, _) ->
- %% Already in key-exchange so safe to ignore
- timer:apply_after(?REKEY_DATA_TIMOUT, gen_statem, cast, [self(), data_size]), % FIXME: not here in original
- keep_state_and_data;
-
+handle_event({timeout,check_data_size}, _, StateName, D0) ->
+ %% Rekey due to sent data limit reached? (Can't be in {ext_info,...} if data is sent)
+ case StateName of
+ {connected,Role} ->
+ check_data_rekeying(Role, D0);
+ _ ->
+ %% Wrong state for starting a renegotiation, must be in re-negotiation
+ keep_state_and_data
+ end;
+handle_event({call,From}, get_alg, _, D) ->
+ #ssh{algorithms=Algs} = D#data.ssh_params,
+ {keep_state_and_data, [{reply,From,Algs}]};
handle_event(cast, _, StateName, _) when not ?CONNECTED(StateName) ->
{keep_state_and_data, [postpone]};
handle_event(cast, {adjust_window,ChannelId,Bytes}, StateName, D) when ?CONNECTED(StateName) ->
- case ssh_channel:cache_lookup(cache(D), ChannelId) of
+ case ssh_client_channel:cache_lookup(cache(D), ChannelId) of
#channel{recv_window_size = WinSize,
recv_window_pending = Pending,
recv_packet_size = PktSize} = Channel
when (WinSize-Bytes) >= 2*PktSize ->
%% The peer can send at least two more *full* packet, no hurry.
- ssh_channel:cache_update(cache(D),
+ ssh_client_channel:cache_update(cache(D),
Channel#channel{recv_window_pending = Pending + Bytes}),
keep_state_and_data;
@@ -1054,7 +1111,7 @@ handle_event(cast, {adjust_window,ChannelId,Bytes}, StateName, D) when ?CONNECTE
recv_window_pending = Pending,
remote_id = Id} = Channel ->
%% Now we have to update the window - we can't receive so many more pkts
- ssh_channel:cache_update(cache(D),
+ ssh_client_channel:cache_update(cache(D),
Channel#channel{recv_window_size =
WinSize + Bytes + Pending,
recv_window_pending = 0}),
@@ -1066,7 +1123,7 @@ handle_event(cast, {adjust_window,ChannelId,Bytes}, StateName, D) when ?CONNECTE
end;
handle_event(cast, {reply_request,success,ChannelId}, StateName, D) when ?CONNECTED(StateName) ->
- case ssh_channel:cache_lookup(cache(D), ChannelId) of
+ case ssh_client_channel:cache_lookup(cache(D), ChannelId) of
#channel{remote_id = RemoteId} ->
Msg = ssh_connection:channel_success_msg(RemoteId),
update_inet_buffers(D#data.socket),
@@ -1109,7 +1166,7 @@ handle_event({call,From}, {connection_info, Options}, _, D) ->
{keep_state_and_data, [{reply,From,Info}]};
handle_event({call,From}, {channel_info,ChannelId,Options}, _, D) ->
- case ssh_channel:cache_lookup(cache(D), ChannelId) of
+ case ssh_client_channel:cache_lookup(cache(D), ChannelId) of
#channel{} = Channel ->
Info = fold_keys(Options, fun chann_info/2, Channel),
{keep_state_and_data, [{reply,From,Info}]};
@@ -1119,14 +1176,14 @@ handle_event({call,From}, {channel_info,ChannelId,Options}, _, D) ->
handle_event({call,From}, {info, all}, _, D) ->
- Result = ssh_channel:cache_foldl(fun(Channel, Acc) ->
+ Result = ssh_client_channel:cache_foldl(fun(Channel, Acc) ->
[Channel | Acc]
end,
[], cache(D)),
{keep_state_and_data, [{reply, From, {ok,Result}}]};
handle_event({call,From}, {info, ChannelPid}, _, D) ->
- Result = ssh_channel:cache_foldl(
+ Result = ssh_client_channel:cache_foldl(
fun(Channel, Acc) when Channel#channel.user == ChannelPid ->
[Channel | Acc];
(_, Acc) ->
@@ -1134,44 +1191,45 @@ handle_event({call,From}, {info, ChannelPid}, _, D) ->
end, [], cache(D)),
{keep_state_and_data, [{reply, From, {ok,Result}}]};
-handle_event({call,From}, stop, StateName, D0) ->
- {disconnect, _Reason, {{replies, Replies}, Connection}} =
- ssh_connection:handle_msg(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
- description = "User closed down connection"},
- D0#data.connection_state,
- role(StateName)),
- {Repls,D} = send_replies(Replies, D0),
- {stop_and_reply, normal, [{reply,From,ok}|Repls], D#data{connection_state=Connection}};
-
+handle_event({call,From}, stop, _StateName, D0) ->
+ {Repls,D} = send_replies(ssh_connection:handle_stop(D0#data.connection_state), D0),
+ {stop_and_reply, normal, [{reply,From,ok}|Repls], D};
handle_event({call,_}, _, StateName, _) when not ?CONNECTED(StateName) ->
{keep_state_and_data, [postpone]};
handle_event({call,From}, {request, ChannelPid, ChannelId, Type, Data, Timeout}, StateName, D0)
when ?CONNECTED(StateName) ->
- D = handle_request(ChannelPid, ChannelId, Type, Data, true, From, D0),
- %% Note reply to channel will happen later when reply is recived from peer on the socket
- start_channel_request_timer(ChannelId, From, Timeout),
- {keep_state, cache_request_idle_timer_check(D)};
+ case handle_request(ChannelPid, ChannelId, Type, Data, true, From, D0) of
+ {error,Error} ->
+ {keep_state, D0, {reply,From,{error,Error}}};
+ D ->
+ %% Note reply to channel will happen later when reply is recived from peer on the socket
+ start_channel_request_timer(ChannelId, From, Timeout),
+ {keep_state, D, cond_set_idle_timer(D)}
+ end;
handle_event({call,From}, {request, ChannelId, Type, Data, Timeout}, StateName, D0)
when ?CONNECTED(StateName) ->
- D = handle_request(ChannelId, Type, Data, true, From, D0),
- %% Note reply to channel will happen later when reply is recived from peer on the socket
- start_channel_request_timer(ChannelId, From, Timeout),
- {keep_state, cache_request_idle_timer_check(D)};
+ case handle_request(ChannelId, Type, Data, true, From, D0) of
+ {error,Error} ->
+ {keep_state, D0, {reply,From,{error,Error}}};
+ D ->
+ %% Note reply to channel will happen later when reply is recived from peer on the socket
+ start_channel_request_timer(ChannelId, From, Timeout),
+ {keep_state, D, cond_set_idle_timer(D)}
+ end;
handle_event({call,From}, {data, ChannelId, Type, Data, Timeout}, StateName, D0)
when ?CONNECTED(StateName) ->
- {{replies, Replies}, Connection} =
- ssh_connection:channel_data(ChannelId, Type, Data, D0#data.connection_state, From),
- {Repls,D} = send_replies(Replies, D0#data{connection_state = Connection}),
+ {Repls,D} = send_replies(ssh_connection:channel_data(ChannelId, Type, Data, D0#data.connection_state, From),
+ D0),
start_channel_request_timer(ChannelId, From, Timeout), % FIXME: No message exchange so why?
{keep_state, D, Repls};
handle_event({call,From}, {eof, ChannelId}, StateName, D0)
when ?CONNECTED(StateName) ->
- case ssh_channel:cache_lookup(cache(D0), ChannelId) of
+ case ssh_client_channel:cache_lookup(cache(D0), ChannelId) of
#channel{remote_id = Id, sent_close = false} ->
D = send_msg(ssh_connection:channel_eof_msg(Id), D0),
{keep_state, D, [{reply,From,ok}]};
@@ -1189,7 +1247,7 @@ handle_event({call,From},
InitialWindowSize,
MaxPacketSize, Data),
D1),
- ssh_channel:cache_update(cache(D2),
+ ssh_client_channel:cache_update(cache(D2),
#channel{type = Type,
sys = "none",
user = ChannelPid,
@@ -1200,11 +1258,11 @@ handle_event({call,From},
}),
D = add_request(true, ChannelId, From, D2),
start_channel_request_timer(ChannelId, From, Timeout),
- {keep_state, cache_cancel_idle_timer(D)};
+ {keep_state, D, cond_set_idle_timer(D)};
handle_event({call,From}, {send_window, ChannelId}, StateName, D)
when ?CONNECTED(StateName) ->
- Reply = case ssh_channel:cache_lookup(cache(D), ChannelId) of
+ Reply = case ssh_client_channel:cache_lookup(cache(D), ChannelId) of
#channel{send_window_size = WinSize,
send_packet_size = Packsize} ->
{ok, {WinSize, Packsize}};
@@ -1215,7 +1273,7 @@ handle_event({call,From}, {send_window, ChannelId}, StateName, D)
handle_event({call,From}, {recv_window, ChannelId}, StateName, D)
when ?CONNECTED(StateName) ->
- Reply = case ssh_channel:cache_lookup(cache(D), ChannelId) of
+ Reply = case ssh_client_channel:cache_lookup(cache(D), ChannelId) of
#channel{recv_window_size = WinSize,
recv_packet_size = Packsize} ->
{ok, {WinSize, Packsize}};
@@ -1226,11 +1284,11 @@ handle_event({call,From}, {recv_window, ChannelId}, StateName, D)
handle_event({call,From}, {close, ChannelId}, StateName, D0)
when ?CONNECTED(StateName) ->
- case ssh_channel:cache_lookup(cache(D0), ChannelId) of
+ case ssh_client_channel:cache_lookup(cache(D0), ChannelId) of
#channel{remote_id = Id} = Channel ->
D1 = send_msg(ssh_connection:channel_close_msg(Id), D0),
- ssh_channel:cache_update(cache(D1), Channel#channel{sent_close = true}),
- {keep_state, cache_request_idle_timer_check(D1), [{reply,From,ok}]};
+ ssh_client_channel:cache_update(cache(D1), Channel#channel{sent_close = true}),
+ {keep_state, D1, [cond_set_idle_timer(D1), {reply,From,ok}]};
undefined ->
{keep_state_and_data, [{reply,From,ok}]}
end;
@@ -1246,61 +1304,91 @@ handle_event(info, {Proto, Sock, Info}, {hello,_}, #data{socket = Sock,
{keep_state_and_data, [{next_event, internal, {info_line,Info}}]}
end;
+
handle_event(info, {Proto, Sock, NewData}, StateName, D0 = #data{socket = Sock,
transport_protocol = Proto}) ->
try ssh_transport:handle_packet_part(
D0#data.decrypted_data_buffer,
<<(D0#data.encrypted_data_buffer)/binary, NewData/binary>>,
- D0#data.undecrypted_packet_length,
+ D0#data.aead_data,
+ D0#data.undecrypted_packet_length,
D0#data.ssh_params)
of
{packet_decrypted, DecryptedBytes, EncryptedDataRest, Ssh1} ->
- D = D0#data{ssh_params =
+ D1 = D0#data{ssh_params =
Ssh1#ssh{recv_sequence = ssh_transport:next_seqnum(Ssh1#ssh.recv_sequence)},
decrypted_data_buffer = <<>>,
- undecrypted_packet_length = undefined,
+ undecrypted_packet_length = undefined,
+ aead_data = <<>>,
encrypted_data_buffer = EncryptedDataRest},
try
- ssh_message:decode(set_kex_overload_prefix(DecryptedBytes,D))
+ ssh_message:decode(set_kex_overload_prefix(DecryptedBytes,D1))
of
- Msg = #ssh_msg_kexinit{} ->
- {keep_state, D, [{next_event, internal, prepare_next_packet},
+ #ssh_msg_kexinit{} = Msg ->
+ {keep_state, D1, [{next_event, internal, prepare_next_packet},
{next_event, internal, {Msg,DecryptedBytes}}
]};
+
+ #ssh_msg_global_request{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
+ #ssh_msg_request_success{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
+ #ssh_msg_request_failure{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
+ #ssh_msg_channel_open{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
+ #ssh_msg_channel_open_confirmation{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
+ #ssh_msg_channel_open_failure{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
+ #ssh_msg_channel_window_adjust{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
+ #ssh_msg_channel_data{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
+ #ssh_msg_channel_extended_data{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
+ #ssh_msg_channel_eof{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
+ #ssh_msg_channel_close{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
+ #ssh_msg_channel_request{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
+ #ssh_msg_channel_failure{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
+ #ssh_msg_channel_success{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
+
Msg ->
- {keep_state, D, [{next_event, internal, prepare_next_packet},
- {next_event, internal, Msg}
+ {keep_state, D1, [{next_event, internal, prepare_next_packet},
+ {next_event, internal, Msg}
]}
catch
- _C:_E ->
- disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
- description = "Bad packet"},
- StateName, D)
+ C:E:ST ->
+ {Shutdown, D} =
+ ?send_disconnect(?SSH_DISCONNECT_PROTOCOL_ERROR,
+ io_lib:format("Bad packet: Decrypted, but can't decode~n~p:~p~n~p",
+ [C,E,ST]),
+ StateName, D1),
+ {stop, Shutdown, D}
end;
- {get_more, DecryptedBytes, EncryptedDataRest, RemainingSshPacketLen, Ssh1} ->
+ {get_more, DecryptedBytes, EncryptedDataRest, AeadData, RemainingSshPacketLen, Ssh1} ->
%% Here we know that there are not enough bytes in
%% EncryptedDataRest to use. We must wait for more.
inet:setopts(Sock, [{active, once}]),
{keep_state, D0#data{encrypted_data_buffer = EncryptedDataRest,
decrypted_data_buffer = DecryptedBytes,
- undecrypted_packet_length = RemainingSshPacketLen,
+ undecrypted_packet_length = RemainingSshPacketLen,
+ aead_data = AeadData,
ssh_params = Ssh1}};
{bad_mac, Ssh1} ->
- disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
- description = "Bad packet"},
- StateName, D0#data{ssh_params=Ssh1});
-
- {error, {exceeds_max_size,_PacketLen}} ->
- disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
- description = "Bad packet"},
- StateName, D0)
+ {Shutdown, D} =
+ ?send_disconnect(?SSH_DISCONNECT_PROTOCOL_ERROR,
+ "Bad packet: bad mac",
+ StateName, D0#data{ssh_params=Ssh1}),
+ {stop, Shutdown, D};
+
+ {error, {exceeds_max_size,PacketLen}} ->
+ {Shutdown, D} =
+ ?send_disconnect(?SSH_DISCONNECT_PROTOCOL_ERROR,
+ io_lib:format("Bad packet: Size (~p bytes) exceeds max size",
+ [PacketLen]),
+ StateName, D0),
+ {stop, Shutdown, D}
catch
- _C:_E ->
- disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
- description = "Bad packet"},
- StateName, D0)
+ C:E:ST ->
+ {Shutdown, D} =
+ ?send_disconnect(?SSH_DISCONNECT_PROTOCOL_ERROR,
+ io_lib:format("Bad packet: Couldn't decrypt~n~p:~p~n~p",[C,E,ST]),
+ StateName, D0),
+ {stop, Shutdown, D}
end;
@@ -1316,15 +1404,13 @@ handle_event(internal, prepare_next_packet, _, D) ->
inet:setopts(D#data.socket, [{active, once}]),
keep_state_and_data;
-handle_event(info, {CloseTag,Socket}, StateName,
- D = #data{socket = Socket,
- transport_close_tag = CloseTag}) ->
- %% Simulate a disconnect from the peer
- handle_event(info,
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
- description = "Connection closed"},
- StateName,
- D);
+handle_event(info, {CloseTag,Socket}, _StateName,
+ D0 = #data{socket = Socket,
+ transport_close_tag = CloseTag,
+ connection_state = C0}) ->
+ {Repls, D} = send_replies(ssh_connection:handle_stop(C0), D0),
+ disconnect_fun("Received a transport close", D),
+ {stop_and_reply, {shutdown,"Connection closed"}, Repls, D};
handle_event(info, {timeout, {_, From} = Request}, _,
#data{connection_state = #connection{requests = Requests} = C0} = D) ->
@@ -1340,23 +1426,47 @@ handle_event(info, {timeout, {_, From} = Request}, _,
end;
%%% Handle that ssh channels user process goes down
-handle_event(info, {'DOWN', _Ref, process, ChannelPid, _Reason}, _, D0) ->
- {{replies, Replies}, D1} = handle_channel_down(ChannelPid, D0),
- {Repls, D} = send_replies(Replies, D1),
- {keep_state, D, Repls};
+handle_event(info, {'DOWN', _Ref, process, ChannelPid, _Reason}, _, D) ->
+ Cache = cache(D),
+ ssh_client_channel:cache_foldl(
+ fun(#channel{user=U,
+ local_id=Id}, Acc) when U == ChannelPid ->
+ ssh_client_channel:cache_delete(Cache, Id),
+ Acc;
+ (_,Acc) ->
+ Acc
+ end, [], Cache),
+ {keep_state, D, cond_set_idle_timer(D)};
+
+handle_event({timeout,idle_time}, _Data, _StateName, _D) ->
+ {stop, {shutdown, "Timeout"}};
%%% So that terminate will be run when supervisor is shutdown
-handle_event(info, {'EXIT', _Sup, Reason}, _, _) ->
- {stop, {shutdown, Reason}};
+handle_event(info, {'EXIT', _Sup, Reason}, StateName, _) ->
+ Role = role(StateName),
+ if
+ Role == client ->
+ %% OTP-8111 tells this function clause fixes a problem in
+ %% clients, but there were no check for that role.
+ {stop, {shutdown, Reason}};
+
+ Reason == normal ->
+ %% An exit normal should not cause a server to crash. This has happend...
+ keep_state_and_data;
+
+ true ->
+ {stop, {shutdown, Reason}}
+ end;
handle_event(info, check_cache, _, D) ->
- {keep_state, cache_check_set_idle_timer(D)};
+ {keep_state, D, cond_set_idle_timer(D)};
handle_event(info, UnexpectedMessage, StateName, D = #data{ssh_params = Ssh}) ->
case unexpected_fun(UnexpectedMessage, D) of
report ->
Msg = lists:flatten(
io_lib:format(
+ "*** SSH: "
"Unexpected message '~p' received in state '~p'\n"
"Role: ~p\n"
"Peer: ~p\n"
@@ -1365,7 +1475,7 @@ handle_event(info, UnexpectedMessage, StateName, D = #data{ssh_params = Ssh}) ->
StateName,
Ssh#ssh.role,
Ssh#ssh.peer,
- ?GET_INTERNAL_OPT(address, Ssh#ssh.opts)])),
+ ?GET_INTERNAL_OPT(address, Ssh#ssh.opts, undefined)])),
error_logger:info_report(Msg),
keep_state_and_data;
@@ -1374,7 +1484,8 @@ handle_event(info, UnexpectedMessage, StateName, D = #data{ssh_params = Ssh}) ->
Other ->
Msg = lists:flatten(
- io_lib:format("Call to fun in 'unexpectedfun' failed:~n"
+ io_lib:format("*** SSH: "
+ "Call to fun in 'unexpectedfun' failed:~n"
"Return: ~p\n"
"Message: ~p\n"
"Role: ~p\n"
@@ -1383,70 +1494,90 @@ handle_event(info, UnexpectedMessage, StateName, D = #data{ssh_params = Ssh}) ->
[Other,
UnexpectedMessage,
Ssh#ssh.role,
- element(2,Ssh#ssh.peer),
- ?GET_INTERNAL_OPT(address, Ssh#ssh.opts)]
+ Ssh#ssh.peer,
+ ?GET_INTERNAL_OPT(address, Ssh#ssh.opts, undefined)]
)),
error_logger:error_report(Msg),
keep_state_and_data
end;
-handle_event(internal, {disconnect,Msg,_Reason}, StateName, D) ->
- disconnect(Msg, StateName, D);
+handle_event(internal, {send_disconnect,Code,DetailedText,Module,Line}, StateName, D0) ->
+ {Shutdown, D} =
+ send_disconnect(Code, DetailedText, Module, Line, StateName, D0),
+ {stop, Shutdown, D};
+
+
+handle_event(enter, _OldState, State, D) ->
+ %% Just skip
+ {next_state, State, D};
handle_event(_Type, _Msg, {ext_info,Role,_ReNegFlag}, D) ->
%% If something else arrives, goto next state and handle the event in that one
{next_state, {connected,Role}, D, [postpone]};
-handle_event(Type, Ev, StateName, D) ->
- Descr =
+handle_event(Type, Ev, StateName, D0) ->
+ Details =
case catch atom_to_list(element(1,Ev)) of
"ssh_msg_" ++_ when Type==internal ->
-%% "Message in wrong state";
lists:flatten(io_lib:format("Message ~p in wrong state (~p)", [element(1,Ev), StateName]));
_ ->
- "Internal error"
+ io_lib:format("Unhandled event in state ~p:~n~p", [StateName,Ev])
end,
- disconnect(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
- description = Descr},
- StateName, D).
+ {Shutdown, D} =
+ ?send_disconnect(?SSH_DISCONNECT_PROTOCOL_ERROR, Details, StateName, D0),
+ {stop, Shutdown, D}.
%%--------------------------------------------------------------------
-spec terminate(any(),
state_name(),
#data{}
- ) -> finalize_termination_result() .
+ ) -> term().
%% . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
-terminate(normal, StateName, State) ->
- finalize_termination(StateName, State);
+terminate(normal, _StateName, D) ->
+ stop_subsystem(D),
+ close_transport(D);
-terminate({shutdown,{init,Reason}}, StateName, State) ->
- error_logger:info_report(io_lib:format("Erlang ssh in connection handler init: ~p~n",[Reason])),
- finalize_termination(StateName, State);
+terminate({shutdown,"Connection closed"}, _StateName, D) ->
+ %% Normal: terminated by a sent by peer
+ stop_subsystem(D),
+ close_transport(D);
-terminate(shutdown, StateName, State0) ->
+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])),
+ stop_subsystem(D),
+ close_transport(D);
+
+terminate({shutdown,_R}, _StateName, D) ->
+ %% Internal termination, usually already reported via ?send_disconnect resulting in a log entry
+ stop_subsystem(D),
+ close_transport(D);
+
+terminate(shutdown, _StateName, D0) ->
%% Terminated by supervisor
- State = send_msg(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
- description = "Application shutdown"},
- State0),
- finalize_termination(StateName, State);
-
-%% terminate({shutdown,Msg}, StateName, State0) when is_record(Msg,ssh_msg_disconnect)->
-%% State = send_msg(Msg, State0),
-%% finalize_termination(StateName, Msg, State);
-
-terminate({shutdown,_R}, StateName, State) ->
- finalize_termination(StateName, State);
-
-terminate(Reason, StateName, State0) ->
- %% Others, e.g undef, {badmatch,_}
- log_error(Reason),
- State = send_msg(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
- description = "Internal error"},
- State0),
- finalize_termination(StateName, State).
+ %% Use send_msg directly instead of ?send_disconnect to avoid filling the log
+ D = send_msg(#ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
+ description = "Terminated (shutdown) by supervisor"},
+ D0),
+ close_transport(D);
+
+terminate(kill, _StateName, D) ->
+ %% Got a kill signal
+ stop_subsystem(D),
+ close_transport(D);
+
+terminate(Reason, StateName, D0) ->
+ %% Others, e.g undef, {badmatch,_}, ...
+ log(error, D0, Reason),
+ {_ShutdownReason, D} = ?send_disconnect(?SSH_DISCONNECT_BY_APPLICATION,
+ "Internal error",
+ io_lib:format("Reason: ~p",[Reason]),
+ StateName, D0),
+ stop_subsystem(D),
+ close_transport(D).
%%--------------------------------------------------------------------
@@ -1455,36 +1586,41 @@ terminate(Reason, StateName, State0) ->
format_status(normal, [_, _StateName, D]) ->
[{data, [{"State", D}]}];
format_status(terminate, [_, _StateName, D]) ->
- DataPropList0 = fmt_stat_rec(record_info(fields, data), D,
- [decrypted_data_buffer,
- encrypted_data_buffer,
- key_exchange_init_msg,
- user_passwords,
- opts,
- inet_initial_recbuf_size]),
- SshPropList = fmt_stat_rec(record_info(fields, ssh), D#data.ssh_params,
- [c_keyinit,
- s_keyinit,
- send_mac_key,
- send_mac_size,
- recv_mac_key,
- recv_mac_size,
- encrypt_keys,
- encrypt_ctx,
- decrypt_keys,
- decrypt_ctx,
- compress_ctx,
- decompress_ctx,
- shared_secret,
- exchanged_hash,
- session_id,
- keyex_key,
- keyex_info,
- available_host_keys]),
- DataPropList = lists:keyreplace(ssh_params, 1, DataPropList0,
- {ssh_params,SshPropList}),
- [{data, [{"State", DataPropList}]}].
-
+ [{data, [{"State", state_data2proplist(D)}]}].
+
+
+state_data2proplist(D) ->
+ DataPropList0 =
+ fmt_stat_rec(record_info(fields, data), D,
+ [decrypted_data_buffer,
+ encrypted_data_buffer,
+ key_exchange_init_msg,
+ user_passwords,
+ opts,
+ inet_initial_recbuf_size]),
+ SshPropList =
+ fmt_stat_rec(record_info(fields, ssh), D#data.ssh_params,
+ [c_keyinit,
+ s_keyinit,
+ send_mac_key,
+ send_mac_size,
+ recv_mac_key,
+ recv_mac_size,
+ encrypt_keys,
+ encrypt_ctx,
+ decrypt_keys,
+ decrypt_ctx,
+ compress_ctx,
+ decompress_ctx,
+ shared_secret,
+ exchanged_hash,
+ session_id,
+ keyex_key,
+ keyex_info,
+ available_host_keys]),
+ lists:keyreplace(ssh_params, 1, DataPropList0,
+ {ssh_params,SshPropList}).
+
fmt_stat_rec(FieldNames, Rec, Exclude) ->
Values = tl(tuple_to_list(Rec)),
@@ -1521,65 +1657,67 @@ start_the_connection_child(UserPid, Role, Socket, Options0) ->
%%--------------------------------------------------------------------
%% Stopping
--type finalize_termination_result() :: ok .
-
-finalize_termination(_StateName, #data{transport_cb = Transport,
- connection_state = Connection,
- socket = Socket}) ->
- case Connection of
- #connection{system_supervisor = SysSup,
- sub_system_supervisor = SubSysSup} when is_pid(SubSysSup) ->
- ssh_system_sup:stop_subsystem(SysSup, SubSysSup);
- _ ->
- do_nothing
- end,
- (catch Transport:close(Socket)),
+
+stop_subsystem(#data{connection_state =
+ #connection{system_supervisor = SysSup,
+ sub_system_supervisor = SubSysSup}}) when is_pid(SubSysSup) ->
+ ssh_system_sup:stop_subsystem(SysSup, SubSysSup);
+stop_subsystem(_) ->
ok.
+
+close_transport(#data{transport_cb = Transport,
+ socket = Socket}) ->
+ try
+ Transport:close(Socket)
+ of
+ _ -> ok
+ catch
+ _:_ -> ok
+ end.
+
%%--------------------------------------------------------------------
%% "Invert" the Role
peer_role(client) -> server;
peer_role(server) -> client.
%%--------------------------------------------------------------------
-supported_host_keys(client, _, Options) ->
- try
- find_sup_hkeys(Options)
- of
- [] ->
+available_hkey_algorithms(Role, Options) ->
+ KeyCb = ?GET_OPT(key_cb, Options),
+ case [A || A <- available_hkey_algos(Options),
+ (Role==client) orelse available_host_key(KeyCb, A, Options)
+ ] of
+
+ [] when Role==client ->
error({shutdown, "No public key algs"});
- Algs ->
- [atom_to_list(A) || A<-Algs]
- catch
- exit:Reason ->
- error({shutdown, Reason})
- end;
-supported_host_keys(server, KeyCb, Options) ->
- [atom_to_list(A) || A <- find_sup_hkeys(Options),
- available_host_key(KeyCb, A, Options)
- ].
+ [] when Role==server ->
+ error({shutdown, "No host key available"});
-find_sup_hkeys(Options) ->
- case proplists:get_value(public_key,
- ?GET_OPT(preferred_algorithms,Options)
- )
- of
- undefined ->
- ssh_transport:default_algorithms(public_key);
- L ->
- NonSupported = L--ssh_transport:supported_algorithms(public_key),
- L -- NonSupported
+ Algs ->
+ [atom_to_list(A) || A<-Algs]
end.
+available_hkey_algos(Options) ->
+ SupAlgos = ssh_transport:supported_algorithms(public_key),
+ HKeys = proplists:get_value(public_key,
+ ?GET_OPT(preferred_algorithms,Options)
+ ),
+ NonSupported = HKeys -- SupAlgos,
+ AvailableAndSupported = HKeys -- NonSupported,
+ AvailableAndSupported.
+
%% Alg :: atom()
available_host_key({KeyCb,KeyCbOpts}, Alg, Opts) ->
UserOpts = ?GET_OPT(user_options, Opts),
case KeyCb:host_key(Alg, [{key_cb_private,KeyCbOpts}|UserOpts]) of
- {ok,_} -> true;
- _ -> false
+ {ok,Key} ->
+ %% Check the key - the KeyCb may be a buggy plugin
+ ssh_transport:valid_key_sha_alg(Key, Alg);
+ _ ->
+ false
end.
@@ -1630,48 +1768,6 @@ call(FsmPid, Event, Timeout) ->
end.
-handle_connection_msg(Msg, StateName, D0 = #data{starter = User,
- connection_state = Connection0,
- event_queue = Qev0}) ->
- Renegotiation = renegotiation(StateName),
- Role = role(StateName),
- try ssh_connection:handle_msg(Msg, Connection0, Role) of
- {{replies, Replies}, Connection} ->
- {Repls, D} =
- case StateName of
- {connected,_} ->
- send_replies(Replies, D0#data{connection_state=Connection});
- _ ->
- {ConnReplies, NonConnReplies} = lists:splitwith(fun not_connected_filter/1, Replies),
- send_replies(NonConnReplies, D0#data{event_queue = Qev0 ++ ConnReplies})
- end,
- {keep_state, D, Repls};
-
- {noreply, Connection} ->
- {keep_state, D0#data{connection_state = Connection}};
-
- {disconnect, Reason0, {{replies, Replies}, Connection}} ->
- {Repls, D} = send_replies(Replies, D0#data{connection_state = Connection}),
- case {Reason0,Role} of
- {{_, Reason}, client} when ((StateName =/= {connected,client}) and (not Renegotiation)) ->
- User ! {self(), not_connected, Reason};
- _ ->
- ok
- end,
- {stop_and_reply, {shutdown,normal}, Repls, D#data{connection_state = Connection}}
-
- catch
- _:Error ->
- {disconnect, _Reason, {{replies, Replies}, Connection}} =
- ssh_connection:handle_msg(
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_BY_APPLICATION,
- description = "Internal error"},
- Connection0, Role),
- {Repls, D} = send_replies(Replies, D0#data{connection_state = Connection}),
- {stop_and_reply, {shutdown,Error}, Repls, D#data{connection_state = Connection}}
- end.
-
-
set_kex_overload_prefix(Msg = <<?BYTE(Op),_/binary>>, #data{ssh_params=SshParams})
when Op == 30;
Op == 31
@@ -1679,6 +1775,10 @@ set_kex_overload_prefix(Msg = <<?BYTE(Op),_/binary>>, #data{ssh_params=SshParams
case catch atom_to_list(kex(SshParams)) of
"ecdh-sha2-" ++ _ ->
<<"ecdh",Msg/binary>>;
+ "curve25519-" ++ _ ->
+ <<"ecdh",Msg/binary>>;
+ "curve448-" ++ _ ->
+ <<"ecdh",Msg/binary>>;
"diffie-hellman-group-exchange-" ++ _ ->
<<"dh_gex",Msg/binary>>;
"diffie-hellman-group" ++ _ ->
@@ -1748,39 +1848,37 @@ is_usable_user_pubkey(A, Ssh) ->
%%%----------------------------------------------------------------
handle_request(ChannelPid, ChannelId, Type, Data, WantReply, From, D) ->
- case ssh_channel:cache_lookup(cache(D), ChannelId) of
- #channel{remote_id = Id} = Channel ->
+ case ssh_client_channel:cache_lookup(cache(D), ChannelId) of
+ #channel{remote_id = Id,
+ sent_close = false} = Channel ->
update_sys(cache(D), Channel, Type, ChannelPid),
send_msg(ssh_connection:channel_request_msg(Id, Type, WantReply, Data),
add_request(WantReply, ChannelId, From, D));
- undefined ->
- D
+
+ _ when WantReply==true ->
+ {error,closed};
+
+ _ ->
+ D
end.
handle_request(ChannelId, Type, Data, WantReply, From, D) ->
- case ssh_channel:cache_lookup(cache(D), ChannelId) of
- #channel{remote_id = Id} ->
+ case ssh_client_channel:cache_lookup(cache(D), ChannelId) of
+ #channel{remote_id = Id,
+ sent_close = false} ->
send_msg(ssh_connection:channel_request_msg(Id, Type, WantReply, Data),
add_request(WantReply, ChannelId, From, D));
- undefined ->
- D
+
+ _ when WantReply==true ->
+ {error,closed};
+
+ _ ->
+ D
end.
%%%----------------------------------------------------------------
-handle_channel_down(ChannelPid, D) ->
- ssh_channel:cache_foldl(
- fun(Channel, Acc) when Channel#channel.user == ChannelPid ->
- ssh_channel:cache_delete(cache(D),
- Channel#channel.local_id),
- Acc;
- (_,Acc) ->
- Acc
- end, [], cache(D)),
- {{replies, []}, cache_check_set_idle_timer(D)}.
-
-
update_sys(Cache, Channel, Type, ChannelPid) ->
- ssh_channel:cache_update(Cache,
+ ssh_client_channel:cache_update(Cache,
Channel#channel{sys = Type, user = ChannelPid}).
add_request(false, _ChannelId, _From, State) ->
@@ -1797,12 +1895,86 @@ new_channel_id(#data{connection_state = #connection{channel_id_seed = Id} =
{Id, State#data{connection_state =
Connection#connection{channel_id_seed = Id + 1}}}.
+
%%%----------------------------------------------------------------
-%% %%% This server/client has decided to disconnect via the state machine:
-disconnect(Msg=#ssh_msg_disconnect{description=Description}, _StateName, State0) ->
- State = send_msg(Msg, State0),
- disconnect_fun(Description, State),
- {stop, {shutdown,Description}, State}.
+start_rekeying(Role, D0) ->
+ {KeyInitMsg, SshPacket, Ssh} = ssh_transport:key_exchange_init_msg(D0#data.ssh_params),
+ send_bytes(SshPacket, D0),
+ D = D0#data{ssh_params = Ssh,
+ key_exchange_init_msg = KeyInitMsg},
+ {next_state, {kexinit,Role,renegotiate}, D}.
+
+
+init_renegotiate_timers(State, D) ->
+ {RekeyTimeout,_MaxSent} = ?GET_OPT(rekey_limit, (D#data.ssh_params)#ssh.opts),
+ {next_state, State, D, [{{timeout,renegotiate}, RekeyTimeout, none},
+ {{timeout,check_data_size}, ?REKEY_DATA_TIMOUT, none} ]}.
+
+
+pause_renegotiate_timers(State, D) ->
+ {next_state, State, D, [{{timeout,renegotiate}, infinity, none},
+ {{timeout,check_data_size}, infinity, none} ]}.
+
+check_data_rekeying(Role, D) ->
+ {ok, [{send_oct,SocketSentTotal}]} = inet:getstat(D#data.socket, [send_oct]),
+ SentSinceRekey = SocketSentTotal - D#data.last_size_rekey,
+ {_RekeyTimeout,MaxSent} = ?GET_OPT(rekey_limit, (D#data.ssh_params)#ssh.opts),
+ case check_data_rekeying_dbg(SentSinceRekey, MaxSent) of
+ true ->
+ start_rekeying(Role, D#data{last_size_rekey = SocketSentTotal});
+ _ ->
+ %% Not enough data sent for a re-negotiation. Restart timer.
+ {keep_state, D, {{timeout,check_data_size}, ?REKEY_DATA_TIMOUT, none}}
+ end.
+
+check_data_rekeying_dbg(SentSinceRekey, MaxSent) ->
+ %% This function is for the ssh_dbg to trace on. See dbg_trace/3 at the end.
+ SentSinceRekey >= MaxSent.
+
+%%%----------------------------------------------------------------
+%%% This server/client has decided to disconnect via the state machine:
+%%% The unused arguments are for debugging.
+
+send_disconnect(Code, DetailedText, Module, Line, StateName, D) ->
+ send_disconnect(Code, default_text(Code), DetailedText, Module, Line, StateName, D).
+
+send_disconnect(Code, Reason, DetailedText, Module, Line, StateName, D0) ->
+ Msg = #ssh_msg_disconnect{code = Code,
+ description = Reason},
+ D = send_msg(Msg, D0),
+ LogMsg = io_lib:format("Disconnects with code = ~p [RFC4253 11.1]: ~s",[Code,Reason]),
+ call_disconnectfun_and_log_cond(LogMsg, DetailedText, Module, Line, StateName, D),
+ {{shutdown,Reason}, D}.
+
+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]));
+ _ ->
+ ok
+ end.
+
+
+default_text(?SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT) -> "Host not allowed to connect";
+default_text(?SSH_DISCONNECT_PROTOCOL_ERROR) -> "Protocol error";
+default_text(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED) -> "Key exchange failed";
+default_text(?SSH_DISCONNECT_RESERVED) -> "Reserved";
+default_text(?SSH_DISCONNECT_MAC_ERROR) -> "Mac error";
+default_text(?SSH_DISCONNECT_COMPRESSION_ERROR) -> "Compression error";
+default_text(?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE) -> "Service not available";
+default_text(?SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED) -> "Protocol version not supported";
+default_text(?SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE) -> "Host key not verifiable";
+default_text(?SSH_DISCONNECT_CONNECTION_LOST) -> "Connection lost";
+default_text(?SSH_DISCONNECT_BY_APPLICATION) -> "By application";
+default_text(?SSH_DISCONNECT_TOO_MANY_CONNECTIONS) -> "Too many connections";
+default_text(?SSH_DISCONNECT_AUTH_CANCELLED_BY_USER) -> "Auth cancelled by user";
+default_text(?SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE) -> "Unable to connect using the available authentication methods";
+default_text(?SSH_DISCONNECT_ILLEGAL_USER_NAME) -> "Illegal user name".
%%%----------------------------------------------------------------
counterpart_versions(NumVsn, StrVsn, #ssh{role = server} = Ssh) ->
@@ -1815,12 +1987,11 @@ conn_info(client_version, #data{ssh_params=S}) -> {S#ssh.c_vsn, S#ssh.c_version}
conn_info(server_version, #data{ssh_params=S}) -> {S#ssh.s_vsn, S#ssh.s_version};
conn_info(peer, #data{ssh_params=S}) -> S#ssh.peer;
conn_info(user, D) -> D#data.auth_user;
-conn_info(sockname, D) -> {ok, SockName} = inet:sockname(D#data.socket),
- SockName;
+conn_info(sockname, #data{ssh_params=S}) -> S#ssh.local;
%% dbg options ( = not documented):
conn_info(socket, D) -> D#data.socket;
conn_info(chan_ids, D) ->
- ssh_channel:cache_foldl(fun(#channel{local_id=Id}, Acc) ->
+ ssh_client_channel:cache_foldl(fun(#channel{local_id=Id}, Acc) ->
[Id | Acc]
end, [], cache(D)).
@@ -1847,23 +2018,54 @@ fold_keys(Keys, Fun, Extra) ->
end, [], Keys).
%%%----------------------------------------------------------------
-log_error(Reason) ->
- Report = io_lib:format("Erlang ssh connection handler failed with reason:~n"
- " ~p~n"
- "Stacktrace:~n"
- " ~p~n",
- [Reason, erlang:get_stacktrace()]),
- error_logger:error_report(Report).
+log(Tag, D, Reason) ->
+ case atom_to_list(Tag) of % Dialyzer-technical reasons...
+ "error" -> do_log(error_msg, Reason, D);
+ "warning" -> do_log(warning_msg, Reason, D);
+ "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,")">>
+ catch
+ _:_ -> ""
+ end,
+ Other =
+ case Role of
+ server -> "Client";
+ client -> "Server"
+ end,
+ error_logger:F("Erlang SSH ~p ~s ~s.~n"
+ "~s: ~p~n"
+ "~s~n",
+ [Role, VSN, CryptoInfo,
+ Other, PeerVersion,
+ Reason]).
%%%----------------------------------------------------------------
not_connected_filter({connection_reply, _Data}) -> true;
not_connected_filter(_) -> false.
%%%----------------------------------------------------------------
+
+send_replies({Repls,C = #connection{}}, D) when is_list(Repls) ->
+ send_replies(Repls, D#data{connection_state=C});
send_replies(Repls, State) ->
- lists:foldl(fun get_repl/2,
- {[],State},
- Repls).
+ lists:foldl(fun get_repl/2, {[],State}, Repls).
get_repl({connection_reply,Msg}, {CallRepls,S}) ->
if is_record(Msg, ssh_msg_channel_success) ->
@@ -1880,19 +2082,21 @@ get_repl({channel_data,Pid,Data}, Acc) ->
get_repl({channel_request_reply,From,Data}, {CallRepls,S}) ->
{[{reply,From,Data}|CallRepls], S};
get_repl({flow_control,Cache,Channel,From,Msg}, {CallRepls,S}) ->
- ssh_channel:cache_update(Cache, Channel#channel{flow_control = undefined}),
+ ssh_client_channel:cache_update(Cache, Channel#channel{flow_control = undefined}),
{[{reply,From,Msg}|CallRepls], S};
get_repl({flow_control,From,Msg}, {CallRepls,S}) ->
{[{reply,From,Msg}|CallRepls], S};
-get_repl(noreply, Acc) ->
- Acc;
+%% get_repl(noreply, Acc) ->
+%% Acc;
+%% get_repl([], Acc) ->
+%% Acc;
get_repl(X, Acc) ->
exit({get_repl,X,Acc}).
%%%----------------------------------------------------------------
-define(CALL_FUN(Key,D), catch (?GET_OPT(Key, (D#data.ssh_params)#ssh.opts)) ).
-disconnect_fun({disconnect,Msg}, D) -> ?CALL_FUN(disconnectfun,D)(Msg);
+%%disconnect_fun({disconnect,Msg}, D) -> ?CALL_FUN(disconnectfun,D)(Msg);
disconnect_fun(Reason, D) -> ?CALL_FUN(disconnectfun,D)(Reason).
unexpected_fun(UnexpectedMessage, #data{ssh_params = #ssh{peer = {_,Peer} }} = D) ->
@@ -1939,60 +2143,12 @@ retry_fun(User, Reason, #data{ssh_params = #ssh{opts = Opts,
%%% Cache idle timer that closes the connection if there are no
%%% channels open for a while.
-cache_init_idle_timer(D) ->
- case ?GET_OPT(idle_time, (D#data.ssh_params)#ssh.opts) of
- infinity ->
- D#data{idle_timer_value = infinity,
- idle_timer_ref = infinity % A flag used later...
- };
- IdleTime ->
- %% We dont want to set the timeout on first connect
- D#data{idle_timer_value = IdleTime}
+cond_set_idle_timer(D) ->
+ case ssh_client_channel:cache_info(num_entries, cache(D)) of
+ 0 -> {{timeout,idle_time}, ?GET_OPT(idle_time, (D#data.ssh_params)#ssh.opts), none};
+ _ -> {{timeout,idle_time}, infinity, none}
end.
-
-cache_check_set_idle_timer(D = #data{idle_timer_ref = undefined,
- idle_timer_value = IdleTime}) ->
- %% No timer set - shall we set one?
- case ssh_channel:cache_info(num_entries, cache(D)) of
- 0 when IdleTime == infinity ->
- %% No. Meaningless to set a timer that fires in an infinite time...
- D;
- 0 ->
- %% Yes, we'll set one since the cache is empty and it should not
- %% be that for a specified time
- D#data{idle_timer_ref =
- erlang:send_after(IdleTime, self(), {'EXIT',[],"Timeout"})};
- _ ->
- %% No - there are entries in the cache
- D
- end;
-cache_check_set_idle_timer(D) ->
- %% There is already a timer set or the timeout time is infinite
- D.
-
-
-cache_cancel_idle_timer(D) ->
- case D#data.idle_timer_ref of
- infinity ->
- %% The timer is not activated
- D;
- undefined ->
- %% The timer is already cancelled
- D;
- TimerRef ->
- %% The timer is active
- erlang:cancel_timer(TimerRef),
- D#data{idle_timer_ref = undefined}
- end.
-
-
-cache_request_idle_timer_check(D = #data{idle_timer_value = infinity}) ->
- D;
-cache_request_idle_timer_check(D = #data{idle_timer_value = IdleTime}) ->
- erlang:send_after(IdleTime, self(), check_cache),
- D.
-
%%%----------------------------------------------------------------
start_channel_request_timer(_,_, infinity) ->
ok;
@@ -2047,3 +2203,164 @@ update_inet_buffers(Socket) ->
catch
_:_ -> ok
end.
+
+%%%################################################################
+%%%#
+%%%# Tracing
+%%%#
+
+dbg_trace(points, _, _) -> [terminate, disconnect, connections, connection_events, renegotiation];
+
+dbg_trace(flags, connections, A) -> [c] ++ dbg_trace(flags, terminate, A);
+dbg_trace(on, connections, A) -> dbg:tp(?MODULE, init_connection_handler, 3, x),
+ dbg_trace(on, terminate, A);
+dbg_trace(off, connections, A) -> dbg:ctpg(?MODULE, init_connection_handler, 3),
+ dbg_trace(off, terminate, A);
+dbg_trace(format, connections, {call, {?MODULE,init_connection_handler, [Role, Sock, Opts]}}) ->
+ DefaultOpts = ssh_options:handle_options(Role,[]),
+ ExcludedKeys = [internal_options, user_options],
+ NonDefaultOpts =
+ maps:filter(fun(K,V) ->
+ case lists:member(K,ExcludedKeys) of
+ true ->
+ false;
+ false ->
+ V =/= (catch maps:get(K,DefaultOpts))
+ end
+ end,
+ Opts),
+ {ok, {IPp,Portp}} = inet:peername(Sock),
+ {ok, {IPs,Ports}} = inet:sockname(Sock),
+ [io_lib:format("Starting ~p connection:\n",[Role]),
+ io_lib:format("Socket = ~p, Peer = ~s:~p, Local = ~s:~p,~n"
+ "Non-default options:~n~p",
+ [Sock,inet:ntoa(IPp),Portp,inet:ntoa(IPs),Ports,
+ NonDefaultOpts])
+ ];
+dbg_trace(format, connections, F) ->
+ dbg_trace(format, terminate, F);
+
+dbg_trace(flags, connection_events, _) -> [c];
+dbg_trace(on, connection_events, _) -> dbg:tp(?MODULE, handle_event, 4, x);
+dbg_trace(off, connection_events, _) -> dbg:ctpg(?MODULE, handle_event, 4);
+dbg_trace(format, connection_events, {call, {?MODULE,handle_event, [EventType, EventContent, State, _Data]}}) ->
+ ["Connection event\n",
+ io_lib:format("EventType: ~p~nEventContent: ~p~nState: ~p~n", [EventType, EventContent, State])
+ ];
+dbg_trace(format, connection_events, {return_from, {?MODULE,handle_event,4}, Ret}) ->
+ ["Connection event result\n",
+ io_lib:format("~p~n", [event_handler_result(Ret)])
+ ];
+
+dbg_trace(flags, renegotiation, _) -> [c];
+dbg_trace(on, renegotiation, _) -> dbg:tpl(?MODULE, init_renegotiate_timers, 2, x),
+ dbg:tpl(?MODULE, pause_renegotiate_timers, 2, x),
+ dbg:tpl(?MODULE, check_data_rekeying_dbg, 2, x),
+ dbg:tpl(?MODULE, start_rekeying, 2, x);
+dbg_trace(off, renegotiation, _) -> dbg:ctpl(?MODULE, init_renegotiate_timers, 2),
+ dbg:ctpl(?MODULE, pause_renegotiate_timers, 2),
+ dbg:ctpl(?MODULE, check_data_rekeying_dbg, 2),
+ dbg:ctpl(?MODULE, start_rekeying, 2);
+dbg_trace(format, renegotiation, {call, {?MODULE,init_renegotiate_timers,[_State,D]}}) ->
+ ["Renegotiation init\n",
+ io_lib:format("rekey_limit: ~p ({ms,bytes})~ncheck_data_size: ~p (ms)~n",
+ [?GET_OPT(rekey_limit, (D#data.ssh_params)#ssh.opts),
+ ?REKEY_DATA_TIMOUT])
+ ];
+dbg_trace(format, renegotiation, {call, {?MODULE,pause_renegotiate_timers,[_State,_D]}}) ->
+ ["Renegotiation pause\n"];
+dbg_trace(format, renegotiation, {call, {?MODULE,start_rekeying,[_Role,_D]}}) ->
+ ["Renegotiation start rekeying\n"];
+dbg_trace(format, renegotiation, {call, {?MODULE,check_data_rekeying_dbg,[SentSinceRekey, MaxSent]}}) ->
+ ["Renegotiation check data sent\n",
+ io_lib:format("TotalSentSinceRekey: ~p~nMaxBeforeRekey: ~p~nStartRekey: ~p~n",
+ [SentSinceRekey, MaxSent, SentSinceRekey >= MaxSent])
+ ];
+
+
+
+dbg_trace(flags, terminate, _) -> [c];
+dbg_trace(on, terminate, _) -> dbg:tp(?MODULE, terminate, 3, x);
+dbg_trace(off, terminate, _) -> dbg:ctpg(?MODULE, terminate, 3);
+dbg_trace(format, terminate, {call, {?MODULE,terminate, [Reason, StateName, D]}}) ->
+ ExtraInfo =
+ try
+ {conn_info(peer,D),
+ conn_info(user,D),
+ conn_info(sockname,D)}
+ of
+ {{_,{IPp,Portp}}, Usr, {IPs,Ports}} when is_tuple(IPp), is_tuple(IPs),
+ is_integer(Portp), is_integer(Ports) ->
+ io_lib:format("Peer=~s:~p, Local=~s:~p, User=~p",
+ [inet:ntoa(IPp),Portp,inet:ntoa(IPs),Ports,Usr]);
+ {Peer,Usr,Sockname} ->
+ io_lib:format("Peer=~p, Local=~p, User=~p",[Peer,Sockname,Usr])
+ catch
+ _:_ ->
+ ""
+ end,
+ if
+ Reason == normal ;
+ Reason == shutdown ;
+ element(1,Reason) == shutdown
+ ->
+ ["Connection Terminating:\n",
+ io_lib:format("Reason: ~p, StateName: ~p~n~s", [Reason, StateName, ExtraInfo])
+ ];
+
+ true ->
+ ["Connection Terminating:\n",
+ io_lib:format("Reason: ~p, StateName: ~p~n~s~nStateData = ~p",
+ [Reason, StateName, ExtraInfo, state_data2proplist(D)])
+ ]
+ end;
+
+dbg_trace(flags, disconnect, _) -> [c];
+dbg_trace(on, disconnect, _) -> dbg:tpl(?MODULE, send_disconnect, 7, x);
+dbg_trace(off, disconnect, _) -> dbg:ctpl(?MODULE, send_disconnect, 7);
+dbg_trace(format, disconnect, {call,{?MODULE,send_disconnect,
+ [Code, Reason, DetailedText, Module, Line, StateName, _D]}}) ->
+ ["Disconnecting:\n",
+ io_lib:format(" Module = ~p, Line = ~p, StateName = ~p,~n"
+ " Code = ~p, Reason = ~p,~n"
+ " DetailedText =~n"
+ " ~p",
+ [Module, Line, StateName, Code, Reason, lists:flatten(DetailedText)])
+ ].
+
+
+event_handler_result({next_state, NextState, _NewData}) ->
+ {next_state, NextState, "#data{}"};
+event_handler_result({next_state, NextState, _NewData, Actions}) ->
+ {next_state, NextState, "#data{}", Actions};
+event_handler_result(R) ->
+ state_callback_result(R).
+
+state_callback_result({keep_state, _NewData}) ->
+ {keep_state, "#data{}"};
+state_callback_result({keep_state, _NewData, Actions}) ->
+ {keep_state, "#data{}", Actions};
+state_callback_result(keep_state_and_data) ->
+ keep_state_and_data;
+state_callback_result({keep_state_and_data, Actions}) ->
+ {keep_state_and_data, Actions};
+state_callback_result({repeat_state, _NewData}) ->
+ {repeat_state, "#data{}"};
+state_callback_result({repeat_state, _NewData, Actions}) ->
+ {repeat_state, "#data{}", Actions};
+state_callback_result(repeat_state_and_data) ->
+ repeat_state_and_data;
+state_callback_result({repeat_state_and_data, Actions}) ->
+ {repeat_state_and_data, Actions};
+state_callback_result(stop) ->
+ stop;
+state_callback_result({stop, Reason}) ->
+ {stop, Reason};
+state_callback_result({stop, Reason, _NewData}) ->
+ {stop, Reason, "#data{}"};
+state_callback_result({stop_and_reply, Reason, Replies}) ->
+ {stop_and_reply, Reason, Replies};
+state_callback_result({stop_and_reply, Reason, Replies, _NewData}) ->
+ {stop_and_reply, Reason, Replies, "#data{}"};
+state_callback_result(R) ->
+ R.
diff --git a/lib/ssh/src/ssh_connection_sup.erl b/lib/ssh/src/ssh_connection_sup.erl
index 60ee8b7c73..79804b8630 100644
--- a/lib/ssh/src/ssh_connection_sup.erl
+++ b/lib/ssh/src/ssh_connection_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -52,10 +52,7 @@ init(_) ->
},
ChildSpecs = [#{id => undefined, % As simple_one_for_one is used.
start => {ssh_connection_handler, start_link, []},
- restart => temporary,
- shutdown => 4000,
- type => worker,
- modules => [ssh_connection_handler]
+ restart => temporary % because there is no way to restart a crashed connection
}
],
{ok, {SupFlags,ChildSpecs}}.
diff --git a/lib/ssh/src/ssh_daemon_channel.erl b/lib/ssh/src/ssh_daemon_channel.erl
index 6ca93eff44..30c4773a7a 100644
--- a/lib/ssh/src/ssh_daemon_channel.erl
+++ b/lib/ssh/src/ssh_daemon_channel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
-module(ssh_daemon_channel).
-%% API to special server side channel that can be pluged into the erlang ssh daemeon
+%% API to server side channel that can be pluged into the erlang ssh daemeon
-callback init(Args :: term()) ->
{ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} |
{stop, Reason :: term()} | ignore.
@@ -36,34 +36,20 @@
term().
-callback handle_msg(Msg ::term(), State :: term()) ->
- {ok, State::term()} | {stop, ChannelId::integer(), State::term()}.
--callback handle_ssh_msg({ssh_cm, ConnectionRef::term(), SshMsg::term()},
+ {ok, State::term()} | {stop, ChannelId::ssh:channel_id(), State::term()}.
+-callback handle_ssh_msg({ssh_cm, ConnectionRef::ssh:connection_ref(), SshMsg::term()},
State::term()) -> {ok, State::term()} |
- {stop, ChannelId::integer(),
+ {stop, ChannelId::ssh:channel_id(),
State::term()}.
-%%% API
--export([start/4, start/5, start_link/4, start_link/5, enter_loop/1]).
-
-%% gen_server callbacks
--export([init/1, terminate/2]).
-
-start(ConnectionManager, ChannelId, CallBack, CbInitArgs) ->
- ssh_channel:start(ConnectionManager, ChannelId, CallBack, CbInitArgs, undefined).
-
-start(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) ->
- ssh_channel:start(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec).
-
-start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs) ->
- ssh_channel:start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, undefined).
+%%% Internal API
+-export([start_link/5,
+ get_print_info/1
+ ]).
start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) ->
- ssh_channel:start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec).
+ ssh_server_channel:start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec).
-enter_loop(State) ->
- ssh_channel:enter_loop(State).
-init(Args) ->
- ssh_channel:init(Args).
-terminate(Reason, State) ->
- ssh_channel:terminate(Reason, State).
+get_print_info(Pid) ->
+ ssh_server_channel:get_print_info(Pid).
diff --git a/lib/ssh/src/ssh_dbg.erl b/lib/ssh/src/ssh_dbg.erl
index 3f742ad9b6..4fe15b24d3 100644
--- a/lib/ssh/src/ssh_dbg.erl
+++ b/lib/ssh/src/ssh_dbg.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,285 +20,422 @@
%%
+%%% Purpose:
+%%% This module implements support for using the Erlang trace in a simple way for ssh
+%%% debugging.
+%%%
+%%% Begin the session with ssh_dbg:start(). This will do a dbg:start() if needed and
+%%% then dbg:p/2 to set some flags.
+%%%
+%%% Next select trace points to activate: for example plain text printouts of messages
+%%% sent or received. This is switched on and off with ssh_dbg:on(TracePoint(s)) and
+%%% ssh_dbg:off(TracePoint(s)). For example:
+%%%
+%%% ssh_dbg:on(messages) -- switch on printing plain text messages
+%%% ssh_dbg:on([alg,terminate]) -- switch on printing info about algorithm negotiation
+%%% ssh_dbg:on() -- switch on all ssh debugging
+%%%
+%%% To switch, use the off/0 or off/1 function in the same way, for example:
+%%%
+%%% ssh_dbg:off(alg) -- switch off algorithm negotiation tracing, but keep all other
+%%% ssh_dbg:off() -- switch off all ssh debugging
+%%%
+%%% Present the trace result with some other method than the default io:format/2:
+%%% ssh_dbg:start(fun(Format,Args) ->
+%%% my_special( io_lib:format(Format,Args) )
+%%% end)
+%%%
+
-module(ssh_dbg).
--export([messages/0, messages/1, messages/2, messages/3,
- auth/0, auth/1, auth/2, auth/3,
- stop/0
+-export([start/0, start/1,
+ stop/0,
+ start_server/0,
+ start_tracer/0, start_tracer/1,
+ on/1, on/0,
+ off/1, off/0,
+ go_on/0,
+ %% Circular buffer
+ cbuf_start/0, cbuf_start/1,
+ cbuf_stop_clear/0,
+ cbuf_in/1,
+ cbuf_list/0,
+ fmt_cbuf_items/0, fmt_cbuf_item/1
]).
-export([shrink_bin/1,
- wr_record/3]).
+ reduce_state/1,
+ wr_record/3]).
+
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
-include("ssh.hrl").
-include("ssh_transport.hrl").
-include("ssh_connect.hrl").
-include("ssh_auth.hrl").
-%%%================================================================
-messages() -> start(msg).
-messages(F) -> start(msg,F).
-messages(F,X) -> start(msg,F,X).
-messages(F,M,I) -> start(msg,F,M,I).
-
-auth() -> start(auth).
-auth(F) -> start(auth,F).
-auth(F,X) -> start(auth,F,X).
-auth(F,M,I) -> start(auth,F,M,I).
-
-stop() -> dbg:stop().
+-behaviour(gen_server).
+-define(SERVER, ?MODULE).
-%%%----------------------------------------------------------------
-start(Type) -> start(Type, fun io:format/2).
+-define(CALL_TIMEOUT, 15000). % 3x the default
-start(Type, F) when is_function(F,2) -> start(Type, fmt_fun(F));
-start(Type, F) when is_function(F,3) -> start(Type, F, id_fun()).
+%%%================================================================
-start(Type, WriteFun, MangleArgFun) when is_function(WriteFun, 3),
- is_function(MangleArgFun, 1) ->
- start(Type, WriteFun, MangleArgFun, []);
-start(Type, WriteFun, InitValue) ->
- start(Type, WriteFun, id_fun(), InitValue).
+-define(ALL_DBG_TYPES, get_all_dbg_types()).
-start(Type, WriteFun, MangleArgFun, InitValue) when is_function(WriteFun, 3),
- is_function(MangleArgFun, 1) ->
- cond_start(Type, WriteFun, MangleArgFun, InitValue),
- dbg_ssh(Type).
+start() -> start(fun io:format/2).
-%%%----------------------------------------------------------------
-fmt_fun(F) -> fun(Fmt,Args,Data) -> F(Fmt,Args), Data end.
+start(IoFmtFun) when is_function(IoFmtFun,2) ; is_function(IoFmtFun,3) ->
+ start_server(),
+ catch dbg:start(),
+ start_tracer(IoFmtFun),
+ dbg:p(all, get_all_trace_flags()),
+ ?ALL_DBG_TYPES.
-id_fun() -> fun(X) -> X end.
-
-%%%----------------------------------------------------------------
-dbg_ssh(msg) ->
- dbg_ssh(auth),
- dbg:tp(ssh_message,encode,1, x),
- dbg:tp(ssh_message,decode,1, x),
- dbg:tpl(ssh_transport,select_algorithm,4, x),
- dbg:tp(ssh_transport,hello_version_msg,1, x),
- dbg:tp(ssh_transport,handle_hello_version,1, x),
- dbg:tpl(ssh_connection_handler,ext_info,2, x);
-
-dbg_ssh(auth) ->
- dbg:tp(ssh_transport,hello_version_msg,1, x),
- dbg:tp(ssh_transport,handle_hello_version,1, x),
- dbg:tp(ssh_message,encode,1, x),
- dbg:tpl(ssh_transport,select_algorithm,4, x),
- dbg:tpl(ssh_connection_handler,ext_info,2, x),
- lists:foreach(fun(F) -> dbg:tp(ssh_auth, F, x) end,
- [publickey_msg, password_msg, keyboard_interactive_msg]).
-
-%%%================================================================
-cond_start(Type, WriteFun, MangleArgFun, Init) ->
+stop() ->
try
- dbg:start(),
- setup_tracer(Type, WriteFun, MangleArgFun, Init),
- dbg:p(new,[c,timestamp])
+ dbg:stop_clear(),
+ gen_server:stop(?SERVER)
catch
_:_ -> ok
end.
+start_server() ->
+ gen_server:start({local,?SERVER}, ?MODULE, [], []).
-msg_formater(msg, {trace_ts,Pid,call,{ssh_message,encode,[Msg]},TS}, D) ->
- fmt("~n~s SEND ~p ~s~n", [ts(TS),Pid,wr_record(shrink_bin(Msg))], D);
-msg_formater(msg, {trace_ts,_Pid,return_from,{ssh_message,encode,1},_Res,_TS}, D) ->
- D;
-
-msg_formater(msg, {trace_ts,_Pid,call,{ssh_message,decode,_},_TS}, D) ->
- D;
-msg_formater(msg, {trace_ts,Pid,return_from,{ssh_message,decode,1},Msg,TS}, D) ->
- fmt("~n~s ~p RECV ~s~n", [ts(TS),Pid,wr_record(shrink_bin(Msg))], D);
-
-msg_formater(auth, {trace_ts,Pid,return_from,{ssh_message,decode,1},#ssh_msg_userauth_failure{authentications=As},TS}, D) ->
- fmt("~n~s ~p Client login FAILURE. Try ~s~n", [ts(TS),Pid,As], D);
-
-msg_formater(auth, {trace_ts,Pid,return_from,{ssh_message,decode,1},#ssh_msg_userauth_success{},TS}, D) ->
- fmt("~n~s ~p Client login SUCCESS~n", [ts(TS),Pid], D);
-
-
-msg_formater(_, {trace_ts,_Pid,call,{ssh_transport,select_algorithm,_},_TS}, D) ->
- D;
-msg_formater(_, {trace_ts,Pid,return_from,{ssh_transport,select_algorithm,_},{ok,Alg},TS}, D) ->
- fmt("~n~s ~p ALGORITHMS~n~s~n", [ts(TS),Pid, wr_record(Alg)], D);
-
-msg_formater(_, {trace_ts,_Pid,call,{ssh_transport,hello_version_msg,_},_TS}, D) ->
- D;
-msg_formater(_, {trace_ts,Pid,return_from,{ssh_transport,hello_version_msg,1},Hello,TS}, D) ->
- fmt("~n~s ~p TCP SEND HELLO~n ~p~n", [ts(TS),Pid,lists:flatten(Hello)], D);
-
-msg_formater(_, {trace_ts,Pid,call,{ssh_transport,handle_hello_version,[Hello]},TS}, D) ->
- fmt("~n~s ~p RECV HELLO~n ~p~n", [ts(TS),Pid,lists:flatten(Hello)], D);
-msg_formater(_, {trace_ts,_Pid,return_from,{ssh_transport,handle_hello_version,1},_,_TS}, D) ->
- D;
-
-msg_formater(_, {trace_ts,Pid,call,{ssh_connection_handler,ext_info,[{"server-sig-algs",SigAlgs},State]},TS}, D) ->
- try lists:keyfind(ssh, 1, tuple_to_list(State)) of
- false ->
- D;
- #ssh{userauth_pubkeys = PKs} ->
- fmt("~n~s ~p Client got suggestion to use user public key sig-algs~n ~p~n and can use~n ~p~n",
- [ts(TS),Pid,string:tokens(SigAlgs,","),PKs], D)
- catch
- _:_ ->
- D
- end;
-
-msg_formater(_, {trace_ts,Pid,return_from,{ssh_connection_handler,ext_info,2},State,TS}, D) ->
- try lists:keyfind(ssh, 1, tuple_to_list(State)) of
- false ->
- D;
- #ssh{userauth_pubkeys = PKs} ->
- fmt("~n~s ~p Client will try user public key sig-algs~n ~p~n", [ts(TS),Pid,PKs], D)
- catch
- _:_ ->
- D
- end;
-msg_formater(_, {trace_ts,Pid,call,{ssh_auth,publickey_msg,[[SigAlg,#ssh{user=User}]]},TS}, D) ->
- fmt("~n~s ~p Client will try to login user ~p with public key algorithm ~p~n", [ts(TS),Pid,User,SigAlg], D);
-msg_formater(_, {trace_ts,Pid,return_from,{ssh_auth,publickey_msg,1},{not_ok,#ssh{user=User}},TS}, D) ->
- fmt("~s ~p User ~p can't login with that kind of public key~n", [ts(TS),Pid,User], D);
+start_tracer() -> start_tracer(fun io:format/2).
-msg_formater(_, {trace_ts,Pid,call,{ssh_auth,password_msg,[[#ssh{user=User}]]},TS}, D) ->
- fmt("~n~s ~p Client will try to login user ~p with password~n", [ts(TS),Pid,User], D);
-msg_formater(_, {trace_ts,Pid,return_from,{ssh_auth,password_msg,1},{not_ok,#ssh{user=User}},TS}, D) ->
- fmt("~s ~p User ~p can't login with password~n", [ts(TS),Pid,User], D);
+start_tracer(WriteFun) when is_function(WriteFun,2) ->
+ start_tracer(fun(F,A,S) -> WriteFun(F,A), S end);
+start_tracer(WriteFun) when is_function(WriteFun,3) ->
+ start_tracer(WriteFun, undefined).
-msg_formater(_, {trace_ts,Pid,call,{ssh_auth,keyboard_interactive_msg,[[#ssh{user=User}]]},TS}, D) ->
- fmt("~n~s ~p Client will try to login user ~p with password~n", [ts(TS),Pid,User], D);
-msg_formater(_, {trace_ts,Pid,return_from,{ssh_auth,keyboard_interactive_msg,1},{not_ok,#ssh{user=User}},TS}, D) ->
- fmt("~s ~p User ~p can't login with keyboard_interactive password~n", [ts(TS),Pid,User], D);
-msg_formater(msg, {trace_ts,Pid,send,{tcp,Sock,Bytes},Pid,TS}, D) ->
- fmt("~n~s ~p TCP SEND on ~p~n ~p~n", [ts(TS),Pid,Sock, shrink_bin(Bytes)], D);
+start_tracer(WriteFun, InitAcc) when is_function(WriteFun, 3) ->
+ Handler =
+ fun(Arg, Acc0) ->
+ try_all_types_in_all_modules(gen_server:call(?SERVER, get_on, ?CALL_TIMEOUT),
+ Arg, WriteFun,
+ Acc0)
+ end,
+ dbg:tracer(process, {Handler,InitAcc}).
-msg_formater(msg, {trace_ts,Pid,send,{tcp,Sock,Bytes},Dest,TS}, D) ->
- fmt("~n~s ~p TCP SEND from ~p TO ~p~n ~p~n", [ts(TS),Pid,Sock,Dest, shrink_bin(Bytes)], D);
+%%%----------------------------------------------------------------
+on() -> on(?ALL_DBG_TYPES).
+on(Type) -> switch(on, Type).
-msg_formater(msg, {trace_ts,Pid,send,ErlangMsg,Dest,TS}, D) ->
- fmt("~n~s ~p ERL MSG SEND TO ~p~n ~p~n", [ts(TS),Pid,Dest, shrink_bin(ErlangMsg)], D);
+off() -> off(?ALL_DBG_TYPES). % A bit overkill...
+off(Type) -> switch(off, Type).
+
+go_on() ->
+ IsOn = gen_server:call(?SERVER, get_on, ?CALL_TIMEOUT),
+ on(IsOn).
-msg_formater(msg, {trace_ts,Pid,'receive',{tcp,Sock,Bytes},TS}, D) ->
- fmt("~n~s ~p TCP RECEIVE on ~p~n ~p~n", [ts(TS),Pid,Sock,shrink_bin(Bytes)], D);
+%%%----------------------------------------------------------------
+shrink_bin(B) when is_binary(B), size(B)>256 -> {'*** SHRINKED BIN',
+ size(B),
+ element(1,split_binary(B,64)),
+ '...',
+ element(2,split_binary(B,size(B)-64))
+ };
+shrink_bin(L) when is_list(L) -> lists:map(fun shrink_bin/1, L);
+shrink_bin(T) when is_tuple(T) -> list_to_tuple(shrink_bin(tuple_to_list(T)));
+shrink_bin(X) -> X.
-msg_formater(msg, {trace_ts,Pid,'receive',ErlangMsg,TS}, D) ->
- fmt("~n~s ~p ERL MSG RECEIVE~n ~p~n", [ts(TS),Pid,shrink_bin(ErlangMsg)], D);
+%%%----------------------------------------------------------------
+%% Replace last element (the state) with "#<state-name>{}"
+reduce_state(T) ->
+ try
+ erlang:setelement(size(T),
+ T,
+ lists:concat(['#',element(1,element(size(T),T)),'{}'])
+ )
+ catch
+ _:_ ->
+ T
+ end.
+%%%================================================================
+-record(data, {
+ types_on = []
+ }).
-%% msg_formater(_, {trace_ts,_Pid,return_from,MFA,_Ret,_TS}=M, D) ->
-%% case lists:member(MFA, [{ssh_auth,keyboard_interactive_msg,1},
-%% {ssh_auth,password_msg,1},
-%% {ssh_auth,publickey_msg,1}]) of
-%% true ->
-%% D;
-%% false ->
-%% fmt("~nDBG ~n~p~n", [shrink_bin(M)], D)
-%% end;
+%%%----------------------------------------------------------------
+init(_) ->
+ {ok, #data{}}.
-%% msg_formater(_, M, D) ->
-%% fmt("~nDBG ~n~p~n", [shrink_bin(M)], D).
+%%%----------------------------------------------------------------
+handle_call({switch,on,Types}, _From, D) ->
+ NowOn = lists:usort(Types ++ D#data.types_on),
+ call_modules(on, Types, NowOn),
+ {reply, {ok,NowOn}, D#data{types_on = NowOn}};
+
+handle_call({switch,off,Types}, _From, D) ->
+ StillOn = D#data.types_on -- Types,
+ call_modules(off, Types, StillOn),
+ call_modules(on, StillOn, StillOn),
+ {reply, {ok,StillOn}, D#data{types_on = StillOn}};
+
+handle_call(get_on, _From, D) ->
+ {reply, D#data.types_on, D};
+
+handle_call(C, _From, D) ->
+ io:format('*** Unknown call: ~p~n',[C]),
+ {reply, {error,{unknown_call,C}}, D}.
+
+
+handle_cast(C, D) ->
+ io:format('*** Unknown cast: ~p~n',[C]),
+ {noreply, D}.
+
+handle_info(C, D) ->
+ io:format('*** Unknown info: ~p~n',[C]),
+ {noreply, D}.
-msg_formater(_, _, D) ->
- D.
+
+%%%================================================================
%%%----------------------------------------------------------------
--record(data, {writer,
- acc}).
+ssh_modules_with_trace() ->
+ {ok,AllSshModules} = application:get_key(ssh, modules),
+ [M || M <- AllSshModules,
+ lists:member({dbg_trace,3}, M:module_info(exports))].
-fmt(Fmt, Args, D=#data{writer=Write, acc=Acc}) ->
- D#data{acc = Write(Fmt,Args,Acc)}.
+%%%----------------------------------------------------------------
+get_all_trace_flags() ->
+ get_all_trace_flags(ssh_modules_with_trace()).
-ts({_,_,Usec}=Now) ->
- {_Date,{HH,MM,SS}} = calendar:now_to_local_time(Now),
- io_lib:format("~.2.0w:~.2.0w:~.2.0w.~.6.0w",[HH,MM,SS,Usec]);
-ts(_) ->
- "-".
+get_all_trace_flags(Modules) ->
+ lists:usort(
+ lists:flatten(
+ lists:foldl(
+ fun(Type, Acc) ->
+ call_modules(flags, Type, undefined, Acc, Modules)
+ end, [timestamp], ?ALL_DBG_TYPES))).
-setup_tracer(Type, WriteFun, MangleArgFun, Init) ->
- Handler = fun(Arg, D) ->
- msg_formater(Type, MangleArgFun(Arg), D)
- end,
- InitialData = #data{writer = WriteFun,
- acc = Init},
- {ok,_} = dbg:tracer(process, {Handler, InitialData}),
- ok.
+%%%----------------------------------------------------------------
+get_all_dbg_types() ->
+ lists:usort(
+ lists:flatten(
+ call_modules(points, undefined) )).
%%%----------------------------------------------------------------
-shrink_bin(B) when is_binary(B), size(B)>256 -> {'*** SHRINKED BIN',
- size(B),
- element(1,split_binary(B,64)),
- '...',
- element(2,split_binary(B,size(B)-64))
- };
-shrink_bin(L) when is_list(L) -> lists:map(fun shrink_bin/1, L);
-shrink_bin(T) when is_tuple(T) -> list_to_tuple(shrink_bin(tuple_to_list(T)));
-shrink_bin(X) -> X.
+call_modules(Cmnd, Type) ->
+ call_modules(Cmnd, Type, undefined).
+
+call_modules(Cmnd, Type, Arg) ->
+ call_modules(Cmnd, Type, Arg, []).
+
+call_modules(Cmnd, Type, Arg, Acc0) ->
+ call_modules(Cmnd, Type, Arg, Acc0, ssh_modules_with_trace()).
+
+call_modules(Cmnd, Types, Arg, Acc0, Modules) when is_list(Types) ->
+ lists:foldl(
+ fun(Type, Acc) ->
+ call_modules(Cmnd, Type, Arg, Acc, Modules)
+ end, Acc0, Types);
+
+call_modules(Cmnd, Type, Arg, Acc0, Modules) ->
+ lists:foldl(
+ fun(Mod, Acc) ->
+ try Mod:dbg_trace(Cmnd, Type, Arg)
+ of
+ Result -> [Result|Acc]
+ catch
+ _:_ -> Acc
+ end
+ end, Acc0, Modules).
%%%----------------------------------------------------------------
--define(wr_record(N,BlackList), wr_record(R=#N{}) -> wr_record(R, record_info(fields,N), BlackList)).
-
--define(wr_record(N), ?wr_record(N, [])).
-
-
-?wr_record(alg);
-
-?wr_record(ssh_msg_disconnect);
-?wr_record(ssh_msg_ignore);
-?wr_record(ssh_msg_unimplemented);
-?wr_record(ssh_msg_debug);
-?wr_record(ssh_msg_service_request);
-?wr_record(ssh_msg_service_accept);
-?wr_record(ssh_msg_kexinit);
-?wr_record(ssh_msg_kexdh_init);
-?wr_record(ssh_msg_kexdh_reply);
-?wr_record(ssh_msg_newkeys);
-?wr_record(ssh_msg_ext_info);
-?wr_record(ssh_msg_kex_dh_gex_request);
-?wr_record(ssh_msg_kex_dh_gex_request_old);
-?wr_record(ssh_msg_kex_dh_gex_group);
-?wr_record(ssh_msg_kex_dh_gex_init);
-?wr_record(ssh_msg_kex_dh_gex_reply);
-?wr_record(ssh_msg_kex_ecdh_init);
-?wr_record(ssh_msg_kex_ecdh_reply);
-
-?wr_record(ssh_msg_userauth_request);
-?wr_record(ssh_msg_userauth_failure);
-?wr_record(ssh_msg_userauth_success);
-?wr_record(ssh_msg_userauth_banner);
-?wr_record(ssh_msg_userauth_passwd_changereq);
-?wr_record(ssh_msg_userauth_pk_ok);
-?wr_record(ssh_msg_userauth_info_request);
-?wr_record(ssh_msg_userauth_info_response);
-
-?wr_record(ssh_msg_global_request);
-?wr_record(ssh_msg_request_success);
-?wr_record(ssh_msg_request_failure);
-?wr_record(ssh_msg_channel_open);
-?wr_record(ssh_msg_channel_open_confirmation);
-?wr_record(ssh_msg_channel_open_failure);
-?wr_record(ssh_msg_channel_window_adjust);
-?wr_record(ssh_msg_channel_data);
-?wr_record(ssh_msg_channel_extended_data);
-?wr_record(ssh_msg_channel_eof);
-?wr_record(ssh_msg_channel_close);
-?wr_record(ssh_msg_channel_request);
-?wr_record(ssh_msg_channel_success);
-?wr_record(ssh_msg_channel_failure);
-
-wr_record(R) -> io_lib:format('~p~n',[R]).
+switch(X, Type) when is_atom(Type) ->
+ switch(X, [Type]);
+
+switch(X, Types) when is_list(Types) ->
+ case whereis(?SERVER) of
+ undefined ->
+ start();
+ _ ->
+ ok
+ end,
+ case lists:usort(Types) -- ?ALL_DBG_TYPES of
+ [] ->
+ gen_server:call(?SERVER, {switch,X,Types}, ?CALL_TIMEOUT);
+ L ->
+ {error, {unknown, L}}
+ end.
+%%%----------------------------------------------------------------
+%%% Format of trace messages are described in reference manual for erlang:trace/4
+%%% {call,MFA}
+%%% {return_from,{M,F,N},Result}
+%%% {send,Msg,To}
+%%% {'receive',Msg}
+
+trace_pid({trace,Pid,_}) -> Pid;
+trace_pid({trace,Pid,_,_}) -> Pid;
+trace_pid({trace,Pid,_,_,_}) -> Pid;
+trace_pid({trace,Pid,_,_,_,_}) -> Pid;
+trace_pid({trace,Pid,_,_,_,_,_}) -> Pid;
+trace_pid({trace_ts,Pid,_,_TS}) -> Pid;
+trace_pid({trace_ts,Pid,_,_,_TS}) -> Pid;
+trace_pid({trace_ts,Pid,_,_,_,_TS}) -> Pid;
+trace_pid({trace_ts,Pid,_,_,_,_,_TS}) -> Pid;
+trace_pid({trace_ts,Pid,_,_,_,_,_,_TS}) -> Pid.
+
+trace_ts({trace_ts,_Pid,_,TS}) -> ts(TS);
+trace_ts({trace_ts,_Pid,_,_,TS}) -> ts(TS);
+trace_ts({trace_ts,_Pid,_,_,_,TS}) -> ts(TS);
+trace_ts({trace_ts,_Pid,_,_,_,_,TS}) -> ts(TS);
+trace_ts({trace_ts,_Pid,_,_,_,_,_,TS}) -> ts(TS);
+trace_ts(_) -> "-".
+
+trace_info({trace,_Pid,A}) -> A;
+trace_info({trace,_Pid,A,B}) -> {A,B};
+trace_info({trace,_Pid,A,B,C}) -> {A,B,C};
+trace_info({trace,_Pid,A,B,C,D}) -> {A,B,C,D};
+trace_info({trace,_Pid,A,B,C,D,E}) -> {A,B,C,D,E};
+trace_info({trace_ts,_Pid,A,_TS}) -> A;
+trace_info({trace_ts,_Pid,A,B,_TS}) -> {A,B};
+trace_info({trace_ts,_Pid,A,B,C,_TS}) -> {A,B,C};
+trace_info({trace_ts,_Pid,A,B,C,D,_TS}) -> {A,B,C,D};
+trace_info({trace_ts,_Pid,A,B,C,D,E,_TS}) -> {A,B,C,D,E}.
+
+
+try_all_types_in_all_modules(TypesOn, Arg, WriteFun, Acc0) ->
+ SshModules = ssh_modules_with_trace(),
+ TS = trace_ts(Arg),
+ PID = trace_pid(Arg),
+ INFO = trace_info(Arg),
+ lists:foldl(
+ fun(Type, Acc1) ->
+ lists:foldl(
+ fun(SshMod,Acc) ->
+ try WriteFun("~n~s ~p ~s~n",
+ [lists:flatten(TS), PID, lists:flatten(SshMod:dbg_trace(format,Type,INFO))],
+ Acc)
+ catch
+ _:_ -> Acc
+ end
+ end, Acc1, SshModules)
+ end, Acc0, TypesOn).
+%%%----------------------------------------------------------------
wr_record(T, Fs, BL) when is_tuple(T) ->
wr_record(tuple_to_list(T), Fs, BL);
-wr_record([Name|Values], Fields, BlackL) ->
+wr_record([_Name|Values], Fields, BlackL) ->
W = case Fields of
[] -> 0;
_ -> lists:max([length(atom_to_list(F)) || F<-Fields])
end,
- [io_lib:format("~p:~n",[string:to_upper(atom_to_list(Name))])
- | [io_lib:format(" ~*p: ~p~n",[W,Tag,Value]) || {Tag,Value} <- lists:zip(Fields,Values),
- not lists:member(Tag,BlackL)
- ]
+ [io_lib:format(" ~*p: ~p~n",[W,Tag,Value]) || {Tag,Value} <- lists:zip(Fields,Values),
+ not lists:member(Tag,BlackL)
].
+
+%%%----------------------------------------------------------------
+ts({_,_,Usec}=Now) when is_integer(Usec) ->
+ {_Date,{HH,MM,SS}} = calendar:now_to_local_time(Now),
+ io_lib:format("~.2.0w:~.2.0w:~.2.0w.~.6.0w",[HH,MM,SS,Usec]);
+ts(_) ->
+ "-".
+
+%%%================================================================
+-define(CIRC_BUF, circ_buf).
+
+cbuf_start() ->
+ cbuf_start(20).
+
+cbuf_start(CbufMaxLen) ->
+ put(?CIRC_BUF, {CbufMaxLen,queue:new()}),
+ ok.
+
+
+cbuf_stop_clear() ->
+ case erase(?CIRC_BUF) of
+ undefined ->
+ [];
+ {_CbufMaxLen,Queue} ->
+ queue:to_list(Queue)
+ end.
+
+
+cbuf_in(Value) ->
+ case get(?CIRC_BUF) of
+ undefined ->
+ disabled;
+ {CbufMaxLen,Queue} ->
+ UpdatedQueue =
+ try queue:head(Queue) of
+ {Value, TS0, Cnt0} ->
+ %% Same Value as last saved in the queue
+ queue:in_r({Value, TS0, Cnt0+1},
+ queue:drop(Queue)
+ );
+ _ ->
+ queue:in_r({Value, erlang:timestamp(), 1},
+ truncate_cbuf(Queue, CbufMaxLen)
+ )
+ catch
+ error:empty ->
+ queue:in_r({Value, erlang:timestamp(), 1}, Queue)
+ end,
+ put(?CIRC_BUF, {CbufMaxLen,UpdatedQueue}),
+ ok
+ end.
+
+
+cbuf_list() ->
+ case get(?CIRC_BUF) of
+ undefined ->
+ [];
+ {_CbufMaxLen,Queue} ->
+ queue:to_list(Queue)
+ end.
+
+
+truncate_cbuf(Q, CbufMaxLen) ->
+ case queue:len(Q) of
+ N when N>=CbufMaxLen ->
+ truncate_cbuf(element(2,queue:out_r(Q)), CbufMaxLen);
+ _ ->
+ Q
+ end.
+
+fmt_cbuf_items() ->
+ lists:flatten(
+ io_lib:format("Circular trace buffer. Latest item first.~n~s~n",
+ [case get(?CIRC_BUF) of
+ {Max,_} ->
+ L = cbuf_list(),
+ [io_lib:format("==== ~.*w: ~s~n",[num_digits(Max),N,fmt_cbuf_item(X)]) ||
+ {N,X} <- lists:zip(lists:seq(1,length(L)), L)
+ ];
+ _ ->
+ io_lib:format("Not started.~n",[])
+ end])).
+
+
+num_digits(0) -> 1;
+num_digits(N) when N>0 -> 1+trunc(math:log10(N)).
+
+
+fmt_cbuf_item({Value, TimeStamp, N}) ->
+ io_lib:format("~s~s~n~s~n",
+ [fmt_ts(TimeStamp),
+ [io_lib:format(" (Repeated ~p times)",[N]) || N>1],
+ fmt_value(Value)]).
+
+
+fmt_ts(TS = {_,_,Us}) ->
+ {{YY,MM,DD},{H,M,S}} = calendar:now_to_universal_time(TS),
+ io_lib:format("~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w.~.6.0w UTC",[YY,MM,DD,H,M,S,Us]).
+
+fmt_value(#circ_buf_entry{module = M,
+ line = L,
+ function = {F,A},
+ pid = Pid,
+ value = V}) ->
+ io_lib:format("~p:~p ~p/~p ~p~n~s",[M,L,F,A,Pid,fmt_value(V)]);
+fmt_value(Value) ->
+ io_lib:format("~p",[Value]).
diff --git a/lib/ssh/src/ssh_dbg.hrl b/lib/ssh/src/ssh_dbg.hrl
deleted file mode 100644
index e94664737b..0000000000
--- a/lib/ssh/src/ssh_dbg.hrl
+++ /dev/null
@@ -1,27 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--ifndef(SSH_DBG_HRL).
--define(SSH_DBG_HRL, 1).
-
--define(formatrec(RecName,R),
- ssh_dbg:wr_record(R, record_info(fields,RecName), [])).
-
--endif. % SSH_DBG_HRL defined
diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl
index 33792da38f..832952ed52 100644
--- a/lib/ssh/src/ssh_file.erl
+++ b/lib/ssh/src/ssh_file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -45,27 +45,6 @@
%%% API
-%%% client
--spec add_host_key(string(),
- public_key:public_key(),
- proplists:proplist()) -> ok | {error,term()}.
-
--spec is_host_key(public_key:public_key(),
- string(),
- ssh_client_key_api:algorithm(),
- proplists:proplist()) -> boolean().
-
--spec user_key(ssh_client_key_api:algorithm(),
- proplists:proplist()) -> {ok, public_key:private_key()} | {error,term()}.
-
-%%% server
--spec host_key(ssh_server_key_api:algorithm(),
- proplists:proplist()) -> {ok, public_key:private_key()} | {error,term()}.
-
--spec is_auth_key(public_key:public_key(),
- string(), proplists:proplist()) -> boolean().
-
-
%% Used by server
host_key(Algorithm, Opts) ->
File = file_name(system, file_base_name(Algorithm), Opts),
diff --git a/lib/ssh/src/ssh_info.erl b/lib/ssh/src/ssh_info.erl
index d464def6fa..79cd95e422 100644
--- a/lib/ssh/src/ssh_info.erl
+++ b/lib/ssh/src/ssh_info.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -140,15 +140,15 @@ print_system_sup({{ssh_acceptor_sup,_LocalHost,_LocalPort,_Profile}, Pid, superv
-print_channels({{server,ssh_channel_sup,_,_},Pid,supervisor,[ssh_channel_sup]}) when is_pid(Pid) ->
+print_channels({{server,ssh_server_channel_sup,_,_},Pid,supervisor,[ssh_server_channel_sup]}) when is_pid(Pid) ->
Children = supervisor:which_children(Pid),
- ChannelPids = [P || {R,P,worker,[ssh_channel]} <- Children,
+ ChannelPids = [P || {R,P,worker,[ssh_server_channel]} <- Children,
is_pid(P),
is_reference(R)],
case ChannelPids of
[] -> io_lib:format(?INDENT?INDENT"No channels~n",[]);
[Ch1Pid|_] ->
- {{ConnManager,_}, _Str} = ssh_channel:get_print_info(Ch1Pid),
+ {{ConnManager,_}, _Str} = ssh_server_channel:get_print_info(Ch1Pid),
{{_,Remote},_} = ssh_connection_handler:get_print_info(ConnManager),
[io_lib:format(?INDENT?INDENT"Remote: ~s ConnectionRef = ~p~n",[fmt_host_port(Remote),ConnManager]),
lists:map(fun print_ch/1, ChannelPids)
@@ -159,7 +159,7 @@ print_channels({{server,ssh_connection_sup,_,_},Pid,supervisor,[ssh_connection_s
print_ch(Pid) ->
try
- {{ConnManager,ChannelID}, Str} = ssh_channel:get_print_info(Pid),
+ {{ConnManager,ChannelID}, Str} = ssh_server_channel:get_print_info(Pid),
{_LocalRemote,StrM} = ssh_connection_handler:get_print_info(ConnManager),
io_lib:format(?INDENT?INDENT?INDENT"ch ~p ~p: ~s ~s~n",[ChannelID, Pid, StrM, Str])
catch
diff --git a/lib/ssh/src/ssh_io.erl b/lib/ssh/src/ssh_io.erl
index 8ba759ad60..a7cd1daeec 100644
--- a/lib/ssh/src/ssh_io.erl
+++ b/lib/ssh/src/ssh_io.erl
@@ -31,8 +31,8 @@ read_line(Prompt, Opts) ->
format("~s", [listify(Prompt)]),
?GET_INTERNAL_OPT(user_pid, Opts) ! {self(), question},
receive
- Answer when is_list(Answer) ->
- Answer
+ Answer when is_list(Answer) or is_binary(Answer) ->
+ unicode:characters_to_list(Answer)
end.
yes_no(Prompt, Opts) ->
@@ -44,7 +44,7 @@ yes_no(Prompt, Opts) ->
y -> yes;
n -> no;
- Answer when is_list(Answer) ->
+ Answer when is_list(Answer) or is_binary(Answer) ->
case trim(Answer) of
"y" -> yes;
"n" -> no;
@@ -60,7 +60,7 @@ read_password(Prompt, Opts) ->
format("~s", [listify(Prompt)]),
?GET_INTERNAL_OPT(user_pid, Opts) ! {self(), user_password},
receive
- Answer when is_list(Answer) ->
+ Answer when is_list(Answer) or is_binary(Answer) ->
case trim(Answer) of
"" ->
read_password(Prompt, Opts);
diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl
index b1fc05ae33..da4027a763 100644
--- a/lib/ssh/src/ssh_message.erl
+++ b/lib/ssh/src/ssh_message.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,6 +32,8 @@
-export([encode/1, decode/1, decode_keyboard_interactive_prompts/2]).
+-export([dbg_trace/3]).
+
-define('2bin'(X), (if is_binary(X) -> X;
is_list(X) -> list_to_binary(X);
X==undefined -> <<>>
@@ -252,12 +254,12 @@ encode(#ssh_msg_kexdh_init{e = E}) ->
<<?Ebyte(?SSH_MSG_KEXDH_INIT), ?Empint(E)>>;
encode(#ssh_msg_kexdh_reply{
- public_host_key = Key,
+ public_host_key = {Key,SigAlg},
f = F,
h_sig = Signature
}) ->
EncKey = public_key:ssh_encode(Key, ssh2_pubkey),
- EncSign = encode_signature(Key, Signature),
+ EncSign = encode_signature(Key, SigAlg, Signature),
<<?Ebyte(?SSH_MSG_KEXDH_REPLY), ?Ebinary(EncKey), ?Empint(F), ?Ebinary(EncSign)>>;
encode(#ssh_msg_kex_dh_gex_request{
@@ -278,21 +280,21 @@ encode(#ssh_msg_kex_dh_gex_init{e = Public}) ->
encode(#ssh_msg_kex_dh_gex_reply{
%% Will be private key encode_host_key extracts only the public part!
- public_host_key = Key,
+ public_host_key = {Key,SigAlg},
f = F,
h_sig = Signature
}) ->
EncKey = public_key:ssh_encode(Key, ssh2_pubkey),
- EncSign = encode_signature(Key, Signature),
+ EncSign = encode_signature(Key, SigAlg, Signature),
<<?Ebyte(?SSH_MSG_KEX_DH_GEX_REPLY), ?Ebinary(EncKey), ?Empint(F), ?Ebinary(EncSign)>>;
encode(#ssh_msg_kex_ecdh_init{q_c = Q_c}) ->
- <<?Ebyte(?SSH_MSG_KEX_ECDH_INIT), ?Empint(Q_c)>>;
+ <<?Ebyte(?SSH_MSG_KEX_ECDH_INIT), ?Ebinary(Q_c)>>;
-encode(#ssh_msg_kex_ecdh_reply{public_host_key = Key, q_s = Q_s, h_sig = Sign}) ->
+encode(#ssh_msg_kex_ecdh_reply{public_host_key = {Key,SigAlg}, q_s = Q_s, h_sig = Sign}) ->
EncKey = public_key:ssh_encode(Key, ssh2_pubkey),
- EncSign = encode_signature(Key, Sign),
- <<?Ebyte(?SSH_MSG_KEX_ECDH_REPLY), ?Ebinary(EncKey), ?Empint(Q_s), ?Ebinary(EncSign)>>;
+ EncSign = encode_signature(Key, SigAlg, Sign),
+ <<?Ebyte(?SSH_MSG_KEX_ECDH_REPLY), ?Ebinary(EncKey), ?Ebinary(Q_s), ?Ebinary(EncSign)>>;
encode(#ssh_msg_ignore{data = Data}) ->
<<?Ebyte(?SSH_MSG_IGNORE), ?Estring_utf8(Data)>>;
@@ -502,13 +504,13 @@ decode(<<?BYTE(?SSH_MSG_KEX_DH_GEX_REPLY), ?DEC_BIN(Key,__0), ?DEC_MPINT(F,__1),
h_sig = decode_signature(Hashsign)
};
-decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_INIT), ?DEC_MPINT(Q_c,__0)>>) ->
+decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_INIT), ?DEC_BIN(Q_c,__0)>>) ->
#ssh_msg_kex_ecdh_init{
q_c = Q_c
};
decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_REPLY),
- ?DEC_BIN(Key,__1), ?DEC_MPINT(Q_s,__2), ?DEC_BIN(Sig,__3)>>) ->
+ ?DEC_BIN(Key,__1), ?DEC_BIN(Q_s,__2), ?DEC_BIN(Sig,__3)>>) ->
#ssh_msg_kex_ecdh_reply{
public_host_key = public_key:ssh_decode(Key, ssh2_pubkey),
q_s = Q_s,
@@ -602,12 +604,95 @@ decode_signature(<<?DEC_BIN(Alg,__0), ?UINT32(_), Signature/binary>>) ->
{binary_to_list(Alg), Signature}.
-encode_signature({#'RSAPublicKey'{},Sign}, Signature) ->
- SignName = list_to_binary(atom_to_list(Sign)),
+encode_signature(#'RSAPublicKey'{}, SigAlg, Signature) ->
+ SignName = list_to_binary(atom_to_list(SigAlg)),
<<?Ebinary(SignName), ?Ebinary(Signature)>>;
-encode_signature({{_, #'Dss-Parms'{}},_}, Signature) ->
+encode_signature({_, #'Dss-Parms'{}}, _SigAlg, Signature) ->
<<?Ebinary(<<"ssh-dss">>), ?Ebinary(Signature)>>;
-encode_signature({{#'ECPoint'{}, {namedCurve,OID}},_}, Signature) ->
+encode_signature({#'ECPoint'{}, {namedCurve,OID}}, _SigAlg, Signature) ->
CurveName = public_key:oid2ssh_curvename(OID),
<<?Ebinary(<<"ecdsa-sha2-",CurveName/binary>>), ?Ebinary(Signature)>>.
+%%%################################################################
+%%%#
+%%%# Tracing
+%%%#
+
+dbg_trace(points, _, _) -> [ssh_messages, raw_messages];
+
+dbg_trace(flags, ssh_messages, _) -> [c];
+dbg_trace(on, ssh_messages, _) -> dbg:tp(?MODULE,encode,1,x),
+ dbg:tp(?MODULE,decode,1,x);
+dbg_trace(off, ssh_messages, _) -> dbg:ctpg(?MODULE,encode,1),
+ dbg:ctpg(?MODULE,decode,1);
+
+dbg_trace(flags, raw_messages, A) -> dbg_trace(flags, ssh_messages, A);
+dbg_trace(on, raw_messages, A) -> dbg_trace(on, ssh_messages, A);
+dbg_trace(off, raw_messages, A) -> dbg_trace(off, ssh_messages, A);
+
+dbg_trace(format, ssh_messages, {call,{?MODULE,encode,[Msg]}}) ->
+ Name = string:to_upper(atom_to_list(element(1,Msg))),
+ ["Going to send ",Name,":\n",
+ wr_record(ssh_dbg:shrink_bin(Msg))
+ ];
+dbg_trace(format, ssh_messages, {return_from,{?MODULE,decode,1},Msg}) ->
+ Name = string:to_upper(atom_to_list(element(1,Msg))),
+ ["Received ",Name,":\n",
+ wr_record(ssh_dbg:shrink_bin(Msg))
+ ];
+
+dbg_trace(format, raw_messages, {call,{?MODULE,decode,[BytesPT]}}) ->
+ ["Received plain text bytes (shown after decryption):\n",
+ io_lib:format("~p",[BytesPT])
+ ];
+dbg_trace(format, raw_messages, {return_from,{?MODULE,encode,1},BytesPT}) ->
+ ["Going to send plain text bytes (shown before encryption):\n",
+ io_lib:format("~p",[BytesPT])
+ ].
+
+
+?wr_record(ssh_msg_disconnect);
+?wr_record(ssh_msg_ignore);
+?wr_record(ssh_msg_unimplemented);
+?wr_record(ssh_msg_debug);
+?wr_record(ssh_msg_service_request);
+?wr_record(ssh_msg_service_accept);
+?wr_record(ssh_msg_kexinit);
+?wr_record(ssh_msg_kexdh_init);
+?wr_record(ssh_msg_kexdh_reply);
+?wr_record(ssh_msg_newkeys);
+?wr_record(ssh_msg_ext_info);
+?wr_record(ssh_msg_kex_dh_gex_request);
+?wr_record(ssh_msg_kex_dh_gex_request_old);
+?wr_record(ssh_msg_kex_dh_gex_group);
+?wr_record(ssh_msg_kex_dh_gex_init);
+?wr_record(ssh_msg_kex_dh_gex_reply);
+?wr_record(ssh_msg_kex_ecdh_init);
+?wr_record(ssh_msg_kex_ecdh_reply);
+
+?wr_record(ssh_msg_userauth_request);
+?wr_record(ssh_msg_userauth_failure);
+?wr_record(ssh_msg_userauth_success);
+?wr_record(ssh_msg_userauth_banner);
+?wr_record(ssh_msg_userauth_passwd_changereq);
+?wr_record(ssh_msg_userauth_pk_ok);
+?wr_record(ssh_msg_userauth_info_request);
+?wr_record(ssh_msg_userauth_info_response);
+
+?wr_record(ssh_msg_global_request);
+?wr_record(ssh_msg_request_success);
+?wr_record(ssh_msg_request_failure);
+?wr_record(ssh_msg_channel_open);
+?wr_record(ssh_msg_channel_open_confirmation);
+?wr_record(ssh_msg_channel_open_failure);
+?wr_record(ssh_msg_channel_window_adjust);
+?wr_record(ssh_msg_channel_data);
+?wr_record(ssh_msg_channel_extended_data);
+?wr_record(ssh_msg_channel_eof);
+?wr_record(ssh_msg_channel_close);
+?wr_record(ssh_msg_channel_request);
+?wr_record(ssh_msg_channel_success);
+?wr_record(ssh_msg_channel_failure);
+
+wr_record(R) -> io_lib:format('~p~n',[R]).
+
diff --git a/lib/ssh/src/ssh_no_io.erl b/lib/ssh/src/ssh_no_io.erl
index 1da257ed99..31963118cb 100644
--- a/lib/ssh/src/ssh_no_io.erl
+++ b/lib/ssh/src/ssh_no_io.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,35 +31,24 @@
-spec yes_no(any(), any()) -> no_return().
yes_no(_, _) ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
- description = "User interaction is not allowed"},
- {no_io_allowed, yes_no}).
+ ?DISCONNECT(?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
+ "User interaction is not allowed").
-spec read_password(any(), any()) -> no_return().
read_password(_, _) ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
- description = "User interaction is not allowed"},
- {no_io_allowed, read_password}).
-
+ ?DISCONNECT(?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
+ "User interaction is not allowed").
-spec read_line(any(), any()) -> no_return().
read_line(_, _) ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
- description = "User interaction is not allowed"},
- {no_io_allowed, read_line}).
-
+ ?DISCONNECT(?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
+ "User interaction is not allowed").
-spec format(any(), any()) -> no_return().
format(_, _) ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
- description = "User interaction is not allowed"},
- {no_io_allowed, format}).
-
+ ?DISCONNECT(?SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
+ "User interaction is not allowed").
diff --git a/lib/ssh/src/ssh_options.erl b/lib/ssh/src/ssh_options.erl
index 7eeed70739..bc9f2156bc 100644
--- a/lib/ssh/src/ssh_options.erl
+++ b/lib/ssh/src/ssh_options.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,7 @@
handle_options/2
]).
--export_type([options/0
+-export_type([private_options/0
]).
%%%================================================================
@@ -47,16 +47,23 @@
default => any()
}.
+-type option_key() :: atom().
+
-type option_declarations() :: #{ {option_key(),def} := option_declaration() }.
-type error() :: {error,{eoptions,any()}} .
+-type private_options() :: #{socket_options := socket_options(),
+ internal_options := internal_options(),
+ option_key() => any()
+ }.
+
%%%================================================================
%%%
%%% Get an option
%%%
--spec get_value(option_class(), option_key(), options(),
+-spec get_value(option_class(), option_key(), private_options(),
atom(), non_neg_integer()) -> any() | no_return().
get_value(Class, Key, Opts, _CallerMod, _CallerLine) when is_map(Opts) ->
@@ -69,7 +76,7 @@ get_value(Class, Key, Opts, _CallerMod, _CallerLine) ->
error({bad_options,Class, Key, Opts, _CallerMod, _CallerLine}).
--spec get_value(option_class(), option_key(), options(), fun(() -> any()),
+-spec get_value(option_class(), option_key(), private_options(), fun(() -> any()),
atom(), non_neg_integer()) -> any() | no_return().
get_value(socket_options, Key, Opts, DefFun, _CallerMod, _CallerLine) when is_map(Opts) ->
@@ -91,8 +98,8 @@ get_value(Class, Key, Opts, _DefFun, _CallerMod, _CallerLine) ->
%%% Put an option
%%%
--spec put_value(option_class(), option_in(), options(),
- atom(), non_neg_integer()) -> options().
+-spec put_value(option_class(), option_in(), private_options(),
+ atom(), non_neg_integer()) -> private_options().
put_value(user_options, KeyVal, Opts, _CallerMod, _CallerLine) when is_map(Opts) ->
put_user_value(KeyVal, Opts);
@@ -131,8 +138,8 @@ put_socket_value(A, SockOpts) when is_atom(A) ->
%%% Delete an option
%%%
--spec delete_key(option_class(), option_key(), options(),
- atom(), non_neg_integer()) -> options().
+-spec delete_key(option_class(), option_key(), private_options(),
+ atom(), non_neg_integer()) -> private_options().
delete_key(internal_options, Key, Opts, _CallerMod, _CallerLine) when is_map(Opts) ->
InternalOpts = maps:get(internal_options,Opts),
@@ -144,9 +151,7 @@ delete_key(internal_options, Key, Opts, _CallerMod, _CallerLine) when is_map(Opt
%%% Initialize the options
%%%
--spec handle_options(role(), proplists:proplist()) -> options() | error() .
-
--spec handle_options(role(), proplists:proplist(), options()) -> options() | error() .
+-spec handle_options(role(), client_options()|daemon_options()) -> private_options() | error() .
handle_options(Role, PropList0) ->
handle_options(Role, PropList0, #{socket_options => [],
@@ -155,7 +160,7 @@ handle_options(Role, PropList0) ->
}).
handle_options(Role, PropList0, Opts0) when is_map(Opts0),
- is_list(PropList0) ->
+ is_list(PropList0) ->
PropList1 = proplists:unfold(PropList0),
try
OptionDefinitions = default(Role),
@@ -170,9 +175,10 @@ handle_options(Role, PropList0, Opts0) when is_map(Opts0),
OptionDefinitions),
%% Enter the user's values into the map; unknown keys are
%% treated as socket options
- lists:foldl(fun(KV, Vals) ->
- save(KV, OptionDefinitions, Vals)
- end, InitialMap, PropList1)
+ final_preferred_algorithms(
+ lists:foldl(fun(KV, Vals) ->
+ save(KV, OptionDefinitions, Vals)
+ end, InitialMap, PropList1))
catch
error:{eoptions, KV, undefined} ->
{error, {eoptions,KV}};
@@ -236,7 +242,10 @@ save({Key,Value}, Defs, OptMap) when is_map(OptMap) ->
%% by the check fun will give an error exception:
error:{check,{BadValue,Extra}} ->
error({eoptions, {Key,BadValue}, Extra})
- end.
+ end;
+save(Opt, _Defs, OptMap) when is_map(OptMap) ->
+ OptMap#{socket_options := [Opt | maps:get(socket_options,OptMap)]}.
+
%%%================================================================
%%%
@@ -264,17 +273,19 @@ default(server) ->
},
{shell, def} =>
- #{default => {shell, start, []},
+ #{default => ?DEFAULT_SHELL,
chk => fun({M,F,A}) -> is_atom(M) andalso is_atom(F) andalso is_list(A);
(V) -> check_function1(V) orelse check_function2(V)
end,
class => user_options
},
- {exec, def} => % FIXME: need some archeology....
+ {exec, def} =>
#{default => undefined,
- chk => fun({M,F,_}) -> is_atom(M) andalso is_atom(F);
- (V) -> is_function(V)
+ chk => fun({direct, V}) -> check_function1(V) orelse check_function2(V) orelse check_function3(V);
+ %% Compatibility (undocumented):
+ ({M,F,A}) -> is_atom(M) andalso is_atom(F) andalso is_list(A);
+ (V) -> check_function1(V) orelse check_function2(V) orelse check_function3(V)
end,
class => user_options
},
@@ -417,6 +428,12 @@ default(client) ->
class => user_options
},
+ {ecdsa_pass_phrase, def} =>
+ #{default => undefined,
+ chk => fun check_string/1,
+ class => user_options
+ },
+
{silently_accept_hosts, def} =>
#{default => false,
chk => fun check_silently_accept_hosts/1,
@@ -429,6 +446,12 @@ default(client) ->
class => user_options
},
+ {save_accepted_host, def} =>
+ #{default => true,
+ chk => fun erlang:is_boolean/1,
+ class => user_options
+ },
+
{pref_public_key_algs, def} =>
#{default => ssh_transport:default_algorithms(public_key),
chk => fun check_pref_public_key_algs/1,
@@ -506,6 +529,15 @@ default(common) ->
class => user_options
},
+ %% NOTE: This option is supposed to be used only in this very module (?MODULE). There is
+ %% a final stage in handle_options that "merges" the preferred_algorithms option and this one.
+ %% The preferred_algorithms is the one to use in the rest of the ssh application!
+ {modify_algorithms, def} =>
+ #{default => undefined, % signals error if unsupported algo in preferred_algorithms :(
+ chk => fun check_modify_algorithms/1,
+ class => user_options
+ },
+
{id_string, def} =>
#{default => undefined, % FIXME: see ssh_transport:ssh_vsn/0
chk => fun(random) ->
@@ -567,9 +599,24 @@ default(common) ->
class => user_options
},
- {rekey_limit, def} => % FIXME: Why not common?
- #{default => 1024000000,
- chk => fun check_non_neg_integer/1,
+ {rekey_limit, def} =>
+ #{default => {3600000, 1024000000}, % {1 hour, 1 GB}
+ chk => fun({infinity, infinity}) ->
+ true;
+ ({Mins, infinity}) when is_integer(Mins), Mins>0 ->
+ {true, {Mins*60*1000, infinity}};
+ ({infinity, Bytes}) when is_integer(Bytes), Bytes>=0 ->
+ true;
+ ({Mins, Bytes}) when is_integer(Mins), Mins>0,
+ is_integer(Bytes), Bytes>=0 ->
+ {true, {Mins*60*1000, Bytes}};
+ (infinity) ->
+ {true, {3600000, infinity}};
+ (Bytes) when is_integer(Bytes), Bytes>=0 ->
+ {true, {3600000, Bytes}};
+ (_) ->
+ false
+ end,
class => user_options
},
@@ -817,83 +864,190 @@ valid_hash(L, Ss) when is_list(L) -> lists:all(fun(S) -> valid_hash(S,Ss) end, L
valid_hash(X, _) -> error_in_check(X, "Expect atom or list in fingerprint spec").
%%%----------------------------------------------------------------
-check_preferred_algorithms(Algs) ->
- [error_in_check(K,"Bad preferred_algorithms key")
- || {K,_} <- Algs,
- not lists:keymember(K,1,ssh:default_algorithms())],
+check_modify_algorithms(M) when is_list(M) ->
+ [error_in_check(Op_KVs, "Bad modify_algorithms")
+ || Op_KVs <- M,
+ not is_tuple(Op_KVs)
+ orelse (size(Op_KVs) =/= 2)
+ orelse (not lists:member(element(1,Op_KVs), [append,prepend,rm]))],
+ {true, [{Op,normalize_mod_algs(KVs,false)} || {Op,KVs} <- M]};
+check_modify_algorithms(_) ->
+ error_in_check(modify_algorithms, "Bad option value. List expected.").
+
+
+
+
+normalize_mod_algs(KVs, UseDefaultAlgs) ->
+ normalize_mod_algs(ssh_transport:algo_classes(), KVs, [], UseDefaultAlgs).
+
+normalize_mod_algs([K|Ks], KVs0, Acc, UseDefaultAlgs) ->
+ %% Pick the expected keys in order and check if they are in the user's list
+ {Vs1, KVs} =
+ case lists:keytake(K, 1, KVs0) of
+ {value, {K,Vs0}, KVs1} ->
+ {Vs0, KVs1};
+ false ->
+ {[], KVs0}
+ end,
+ Vs = normalize_mod_alg_list(K, Vs1, UseDefaultAlgs),
+ normalize_mod_algs(Ks, KVs, [{K,Vs} | Acc], UseDefaultAlgs);
+normalize_mod_algs([], [], Acc, _) ->
+ %% No values left in the key-value list after removing the expected entries
+ %% (thats good)
+ lists:reverse(Acc);
+normalize_mod_algs([], [{K,_}|_], _, _) ->
+ %% Some values left in the key-value list after removing the expected entries
+ %% (thats bad)
+ case ssh_transport:algo_class(K) of
+ true -> error_in_check(K, "Duplicate key");
+ false -> error_in_check(K, "Unknown key")
+ end;
+normalize_mod_algs([], [X|_], _, _) ->
+ error_in_check(X, "Bad list element").
- try alg_duplicates(Algs, [], [])
- of
- [] ->
- {true,
- [case proplists:get_value(Key, Algs) of
- undefined ->
- {Key,DefAlgs};
- Vals ->
- handle_pref_alg(Key,Vals,SupAlgs)
- end
- || {{Key,DefAlgs}, {Key,SupAlgs}} <- lists:zip(ssh:default_algorithms(),
- ssh_transport:supported_algorithms())
- ]
- };
-
- Dups ->
- error_in_check(Dups, "Duplicates")
- catch
- _:_ ->
- false
- end.
-alg_duplicates([{K,V}|KVs], Ks, Dups0) ->
- Dups =
- case lists:member(K,Ks) of
- true -> [K|Dups0];
- false -> Dups0
- end,
- case V--lists:usort(V) of
- [] -> alg_duplicates(KVs, [K|Ks], Dups);
- Ds -> alg_duplicates(KVs, [K|Ks], Dups++Ds)
+
+%%% Handle the algorithms list
+normalize_mod_alg_list(K, Vs, UseDefaultAlgs) ->
+ normalize_mod_alg_list(K,
+ ssh_transport:algo_two_spec_class(K),
+ Vs,
+ def_alg(K,UseDefaultAlgs)).
+
+
+normalize_mod_alg_list(_K, _, [], Default) ->
+ Default;
+
+normalize_mod_alg_list(K, true, [{client2server,L1}], [_,{server2client,L2}]) ->
+ [nml1(K,{client2server,L1}),
+ {server2client,L2}];
+
+normalize_mod_alg_list(K, true, [{server2client,L2}], [{client2server,L1},_]) ->
+ [{client2server,L1},
+ nml1(K,{server2client,L2})];
+
+normalize_mod_alg_list(K, true, [{server2client,L2},{client2server,L1}], _) ->
+ [nml1(K,{client2server,L1}),
+ nml1(K,{server2client,L2})];
+
+normalize_mod_alg_list(K, true, [{client2server,L1},{server2client,L2}], _) ->
+ [nml1(K,{client2server,L1}),
+ nml1(K,{server2client,L2})];
+
+normalize_mod_alg_list(K, true, L0, _) ->
+ L = nml(K,L0), % Throws errors
+ [{client2server,L},
+ {server2client,L}];
+
+normalize_mod_alg_list(K, false, L, _) ->
+ nml(K,L).
+
+
+nml1(K, {T,V}) when T==client2server ; T==server2client ->
+ {T, nml({K,T}, V)}.
+
+nml(K, L) ->
+ [error_in_check(K, "Bad value for this key") % This is a throw
+ || V <- L,
+ not is_atom(V)
+ ],
+ case L -- lists:usort(L) of
+ [] -> ok;
+ Dups -> error_in_check({K,Dups}, "Duplicates") % This is a throw
+ end,
+ L.
+
+
+def_alg(K, false) ->
+ case ssh_transport:algo_two_spec_class(K) of
+ false -> [];
+ true -> [{client2server,[]}, {server2client,[]}]
end;
-alg_duplicates([], _Ks, Dups) ->
- Dups.
-
-handle_pref_alg(Key,
- Vs=[{client2server,C2Ss=[_|_]},{server2client,S2Cs=[_|_]}],
- [{client2server,Sup_C2Ss},{server2client,Sup_S2Cs}]
- ) ->
- chk_alg_vs(Key, C2Ss, Sup_C2Ss),
- chk_alg_vs(Key, S2Cs, Sup_S2Cs),
- {Key, Vs};
-
-handle_pref_alg(Key,
- Vs=[{server2client,[_|_]},{client2server,[_|_]}],
- Sup=[{client2server,_},{server2client,_}]
- ) ->
- handle_pref_alg(Key, lists:reverse(Vs), Sup);
-
-handle_pref_alg(Key,
- Vs=[V|_],
- Sup=[{client2server,_},{server2client,_}]
- ) when is_atom(V) ->
- handle_pref_alg(Key, [{client2server,Vs},{server2client,Vs}], Sup);
-
-handle_pref_alg(Key,
- Vs=[V|_],
- Sup=[S|_]
- ) when is_atom(V), is_atom(S) ->
- chk_alg_vs(Key, Vs, Sup),
- {Key, Vs};
-
-handle_pref_alg(Key, Vs, _) ->
- error_in_check({Key,Vs}, "Badly formed list").
-
-chk_alg_vs(OptKey, Values, SupportedValues) ->
- case (Values -- SupportedValues) of
- [] -> Values;
- [none] -> [none]; % for testing only
- Bad -> error_in_check({OptKey,Bad}, "Unsupported value(s) found")
+def_alg(K, true) ->
+ ssh_transport:default_algorithms(K).
+
+
+
+check_preferred_algorithms(Algs) when is_list(Algs) ->
+ check_input_ok(Algs),
+ {true, normalize_mod_algs(Algs, true)};
+
+check_preferred_algorithms(_) ->
+ error_in_check(modify_algorithms, "Bad option value. List expected.").
+
+
+check_input_ok(Algs) ->
+ [error_in_check(KVs, "Bad preferred_algorithms")
+ || KVs <- Algs,
+ not is_tuple(KVs)
+ orelse (size(KVs) =/= 2)].
+
+%%%----------------------------------------------------------------
+final_preferred_algorithms(Options) ->
+ Result =
+ case ?GET_OPT(modify_algorithms, Options) of
+ undefined ->
+ rm_non_supported(true,
+ ?GET_OPT(preferred_algorithms, Options));
+ ModAlgs ->
+ rm_non_supported(false,
+ eval_ops(?GET_OPT(preferred_algorithms, Options),
+ ModAlgs))
+ end,
+ error_if_empty(Result), % Throws errors if any value list is empty
+ ?PUT_OPT({preferred_algorithms,Result}, Options).
+
+eval_ops(PrefAlgs, ModAlgs) ->
+ lists:foldl(fun eval_op/2, PrefAlgs, ModAlgs).
+
+eval_op({Op,AlgKVs}, PrefAlgs) ->
+ eval_op(Op, AlgKVs, PrefAlgs, []).
+
+eval_op(Op, [{C,L1}|T1], [{C,L2}|T2], Acc) ->
+ eval_op(Op, T1, T2, [{C,eval_op(Op,L1,L2,[])} | Acc]);
+
+eval_op(_, [], [], Acc) -> lists:reverse(Acc);
+eval_op(rm, Opt, Pref, []) when is_list(Opt), is_list(Pref) -> Pref -- Opt;
+eval_op(append, Opt, Pref, []) when is_list(Opt), is_list(Pref) -> (Pref--Opt) ++ Opt;
+eval_op(prepend, Opt, Pref, []) when is_list(Opt), is_list(Pref) -> Opt ++ (Pref--Opt).
+
+
+rm_non_supported(UnsupIsErrorFlg, KVs) ->
+ [{K,rmns(K,Vs, UnsupIsErrorFlg)} || {K,Vs} <- KVs].
+
+rmns(K, Vs, UnsupIsErrorFlg) ->
+ case ssh_transport:algo_two_spec_class(K) of
+ false ->
+ rm_unsup(Vs, ssh_transport:supported_algorithms(K), UnsupIsErrorFlg, K);
+ true ->
+ [{C, rm_unsup(Vsx, Sup, UnsupIsErrorFlg, {K,C})}
+ || {{C,Vsx},{C,Sup}} <- lists:zip(Vs,ssh_transport:supported_algorithms(K))
+ ]
end.
+rm_unsup(A, B, Flg, ErrInf) ->
+ case A--B of
+ Unsup=[_|_] when Flg==true -> error({eoptions,
+ {preferred_algorithms,{ErrInf,Unsup}},
+ "Unsupported value(s) found"
+ });
+ Unsup -> A -- Unsup
+ end.
+
+
+error_if_empty([{K,[]}|_]) ->
+ error({eoptions, K, "Empty resulting algorithm list"});
+error_if_empty([{K,[{client2server,[]}, {server2client,[]}]}]) ->
+ error({eoptions, K, "Empty resulting algorithm list"});
+error_if_empty([{K,[{client2server,[]}|_]} | _]) ->
+ error({eoptions, {K,client2server}, "Empty resulting algorithm list"});
+error_if_empty([{K,[_,{server2client,[]}|_]} | _]) ->
+ error({eoptions, {K,server2client}, "Empty resulting algorithm list"});
+error_if_empty([_|T]) ->
+ error_if_empty(T);
+error_if_empty([]) ->
+ ok.
+
%%%----------------------------------------------------------------
forbidden_option(K,V) ->
Txt = io_lib:format("The option '~s' is used internally. The "
diff --git a/lib/ssh/src/ssh_server_channel.erl b/lib/ssh/src/ssh_server_channel.erl
new file mode 100644
index 0000000000..555080e9ee
--- /dev/null
+++ b/lib/ssh/src/ssh_server_channel.erl
@@ -0,0 +1,55 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%
+
+%%
+%% Description: a gen_server implementing a simple
+%% terminal (using the group module) for a CLI
+%% over SSH
+
+-module(ssh_server_channel).
+
+%% API to server side channel that can be pluged into the erlang ssh daemeon
+-callback init(Args :: term()) ->
+ {ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} |
+ {stop, Reason :: term()} | ignore.
+
+-callback terminate(Reason :: (normal | shutdown | {shutdown, term()} |
+ term()),
+ State :: term()) ->
+ term().
+
+-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()},
+ State::term()) -> {ok, State::term()} |
+ {stop, ChannelId::ssh:channel_id(),
+ State::term()}.
+
+%%% Internal API
+-export([start_link/5,
+ get_print_info/1
+ ]).
+
+start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec) ->
+ ssh_client_channel:start_link(ConnectionManager, ChannelId, CallBack, CbInitArgs, Exec).
+
+
+get_print_info(Pid) ->
+ ssh_client_channel:get_print_info(Pid).
diff --git a/lib/ssh/src/ssh_server_channel_sup.erl b/lib/ssh/src/ssh_server_channel_sup.erl
new file mode 100644
index 0000000000..ff74061bb3
--- /dev/null
+++ b/lib/ssh/src/ssh_server_channel_sup.erl
@@ -0,0 +1,62 @@
+%%
+%% %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%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Ssh channel supervisor.
+%%----------------------------------------------------------------------
+-module(ssh_server_channel_sup).
+
+-behaviour(supervisor).
+
+-export([start_link/1, start_child/5]).
+
+%% Supervisor callback
+-export([init/1]).
+
+%%%=========================================================================
+%%% Internal API
+%%%=========================================================================
+start_link(Args) ->
+ supervisor:start_link(?MODULE, [Args]).
+
+start_child(Sup, Callback, Id, Args, Exec) ->
+ ChildSpec =
+ #{id => make_ref(),
+ start => {ssh_server_channel, start_link, [self(), Id, Callback, Args, Exec]},
+ restart => temporary,
+ type => worker,
+ modules => [ssh_server_channel]
+ },
+ supervisor:start_child(Sup, ChildSpec).
+
+%%%=========================================================================
+%%% Supervisor callback
+%%%=========================================================================
+init(_Args) ->
+ RestartStrategy = one_for_one,
+ MaxR = 10,
+ MaxT = 3600,
+ Children = [],
+ {ok, {{RestartStrategy, MaxR, MaxT}, Children}}.
+
+%%%=========================================================================
+%%% Internal functions
+%%%=========================================================================
diff --git a/lib/ssh/src/ssh_server_key.erl b/lib/ssh/src/ssh_server_key.erl
deleted file mode 100644
index 2ce0c7e3fe..0000000000
--- a/lib/ssh/src/ssh_server_key.erl
+++ /dev/null
@@ -1,34 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(ssh_server_key).
-
--include_lib("public_key/include/public_key.hrl").
--include("ssh.hrl").
-
--type ssh_algorithm() :: string().
-
--callback host_key(Algorithm :: ssh_algorithm(), Options :: list()) ->
- {ok, [{public_key(), Attributes::list()}]} | public_key()
- | {error, string()}.
-
--callback is_auth_key(Key :: public_key(), User :: string(),
- Algorithm :: ssh_algorithm(), Options :: list()) ->
- boolean().
diff --git a/lib/ssh/src/ssh_server_key_api.erl b/lib/ssh/src/ssh_server_key_api.erl
index 3f1b886fa7..ef1fe7d69c 100644
--- a/lib/ssh/src/ssh_server_key_api.erl
+++ b/lib/ssh/src/ssh_server_key_api.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,16 +23,18 @@
-include_lib("public_key/include/public_key.hrl").
-include("ssh.hrl").
--export_type([algorithm/0]).
+-export_type([daemon_key_cb_options/0]).
--type algorithm() :: ssh_client_key_api:algorithm().
+-type daemon_key_cb_options() :: [{key_cb_private,term()} | ssh:daemon_option()].
--callback host_key(Algorithm :: algorithm(),
- DaemonOptions :: proplists:proplist()) ->
+-callback host_key(Algorithm :: ssh:pubkey_alg(),
+ DaemonOptions :: daemon_key_cb_options()
+ ) ->
{ok, PrivateKey :: public_key:private_key()} | {error, term()}.
-callback is_auth_key(PublicKey :: public_key:public_key(),
User :: string(),
- DaemonOptions :: proplists:proplist()) ->
+ DaemonOptions :: daemon_key_cb_options()
+ ) ->
boolean().
diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl
index c1558a19b1..1b2ba5a50b 100644
--- a/lib/ssh/src/ssh_sftp.erl
+++ b/lib/ssh/src/ssh_sftp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@
-module(ssh_sftp).
--behaviour(ssh_channel).
+-behaviour(ssh_client_channel).
-include_lib("kernel/include/file.hrl").
-include("ssh.hrl").
@@ -47,11 +47,13 @@
recv_window/1, list_dir/2, read_file/2, write_file/3,
recv_window/2, list_dir/3, read_file/3, write_file/4]).
-%% ssh_channel callbacks
+%% ssh_client_channel callbacks
-export([init/1, handle_call/3, handle_cast/2, code_change/3, handle_msg/2, handle_ssh_msg/2, terminate/2]).
%% TODO: Should be placed elsewhere ssh_sftpd should not call functions in ssh_sftp!
-export([info_to_attr/1, attr_to_info/1]).
+-export([dbg_trace/3]).
+
-record(state,
{
xf,
@@ -121,7 +123,7 @@ start_channel(Cm, UserOptions) when is_pid(Cm) ->
{_SshOpts, ChanOpts, SftpOpts} = handle_options(UserOptions),
case ssh_xfer:attach(Cm, [], ChanOpts) of
{ok, ChannelId, Cm} ->
- case ssh_channel:start(Cm, ChannelId,
+ case ssh_client_channel:start(Cm, ChannelId,
?MODULE, [Cm, ChannelId, SftpOpts]) of
{ok, Pid} ->
case wait_for_version_negotiation(Pid, Timeout) of
@@ -149,7 +151,7 @@ start_channel(Host, Port, UserOptions) ->
proplists:get_value(timeout, SftpOpts, infinity)),
case ssh_xfer:connect(Host, Port, SshOpts, ChanOpts, Timeout) of
{ok, ChannelId, Cm} ->
- case ssh_channel:start(Cm, ChannelId, ?MODULE, [Cm,ChannelId,SftpOpts]) of
+ case ssh_client_channel:start(Cm, ChannelId, ?MODULE, [Cm,ChannelId,SftpOpts]) of
{ok, Pid} ->
case wait_for_version_negotiation(Pid, Timeout) of
ok ->
@@ -169,21 +171,16 @@ start_channel(Host, Port, UserOptions) ->
stop_channel(Pid) ->
case is_process_alive(Pid) of
true ->
- OldValue = process_flag(trap_exit, true),
- link(Pid),
- exit(Pid, ssh_sftp_stop_channel),
- receive
- {'EXIT', Pid, normal} ->
- ok
- after 5000 ->
- exit(Pid, kill),
- receive
- {'EXIT', Pid, killed} ->
- ok
- end
- end,
- process_flag(trap_exit, OldValue),
- ok;
+ MonRef = erlang:monitor(process, Pid),
+ unlink(Pid),
+ exit(Pid, ssh_sftp_stop_channel),
+ receive {'DOWN',MonRef,_,_,_} -> ok
+ after
+ 1000 ->
+ exit(Pid, kill),
+ erlang:demonitor(MonRef, [flush]),
+ ok
+ end;
false ->
ok
end.
@@ -801,13 +798,22 @@ handle_ssh_msg({ssh_cm, _, {signal, _, _}}, State) ->
%% Ignore signals according to RFC 4254 section 6.9.
{ok, State};
-handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, _, Error, _}},
+handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, Signal, Error0, _}},
State0) ->
+ Error =
+ case Error0 of
+ "" -> Signal;
+ _ -> Error0
+ end,
State = reply_all(State0, {error, Error}),
{stop, ChannelId, State};
handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, Status}}, State0) ->
- State = reply_all(State0, {error, {exit_status, Status}}),
+ State =
+ case State0 of
+ 0 -> State0;
+ _ -> reply_all(State0, {error, {exit_status, Status}})
+ end,
{stop, ChannelId, State}.
%%--------------------------------------------------------------------
@@ -823,7 +829,7 @@ handle_msg({ssh_channel_up, _, _}, #state{opts = Options, xf = Xf} = State) ->
%% Version negotiation timed out
handle_msg({timeout, undefined, From},
#state{xf = #ssh_xfer{channel = ChannelId}} = State) ->
- ssh_channel:reply(From, {error, timeout}),
+ ssh_client_channel:reply(From, {error, timeout}),
{stop, ChannelId, State};
handle_msg({timeout, Id, From}, #state{req_list = ReqList0} = State) ->
@@ -832,7 +838,7 @@ handle_msg({timeout, Id, From}, #state{req_list = ReqList0} = State) ->
{ok, State};
_ ->
ReqList = lists:keydelete(Id, 1, ReqList0),
- ssh_channel:reply(From, {error, timeout}),
+ ssh_client_channel:reply(From, {error, timeout}),
{ok, State#state{req_list = ReqList}}
end;
@@ -880,7 +886,7 @@ handle_options([Opt|Rest], Sftp, Chan, Ssh) ->
handle_options(Rest, Sftp, Chan, [Opt|Ssh]).
call(Pid, Msg, TimeOut) ->
- ssh_channel:call(Pid, {{timeout, TimeOut}, Msg}, infinity).
+ ssh_client_channel:call(Pid, {{timeout, TimeOut}, Msg}, infinity).
handle_reply(State, <<?UINT32(Len),Reply:Len/binary,Rest/binary>>) ->
do_handle_reply(State, Reply, Rest);
@@ -899,7 +905,7 @@ do_handle_reply(#state{xf = Xf} = State,
true ->
ok
end,
- ssh_channel:reply(From, ok)
+ ssh_client_channel:reply(From, ok)
end,
State#state{xf = Xf#ssh_xfer{vsn = Version, ext = Ext}, rep_buf = Rest};
@@ -947,7 +953,7 @@ async_reply(ReqID, Reply, _From={To,_}, State) ->
State.
sync_reply(Reply, From, State) ->
- catch (ssh_channel:reply(From, Reply)),
+ catch (ssh_client_channel:reply(From, Reply)),
State.
open2(OrigReqID,FileName,Handle,Mode,Async,From,State) ->
@@ -1050,7 +1056,7 @@ attr_to_info(A) when is_record(A, ssh_xfer_attr) ->
#file_info{
size = A#ssh_xfer_attr.size,
type = A#ssh_xfer_attr.type,
- access = read_write, %% FIXME: read/write/read_write/none
+ access = file_mode_to_owner_access(A#ssh_xfer_attr.permissions),
atime = unix_to_datetime(A#ssh_xfer_attr.atime),
mtime = unix_to_datetime(A#ssh_xfer_attr.mtime),
ctime = unix_to_datetime(A#ssh_xfer_attr.createtime),
@@ -1062,6 +1068,28 @@ attr_to_info(A) when is_record(A, ssh_xfer_attr) ->
uid = A#ssh_xfer_attr.owner,
gid = A#ssh_xfer_attr.group}.
+file_mode_to_owner_access(FileMode)
+ when is_integer(FileMode) ->
+ %% The file mode contains the access permissions.
+ %% The read and write access permission of file owner
+ %% are located in 8th and 7th bit of file mode respectively.
+
+ ReadPermission = ((FileMode bsr 8) band 1),
+ WritePermission = ((FileMode bsr 7) band 1),
+ case {ReadPermission, WritePermission} of
+ {1, 1} ->
+ read_write;
+ {1, 0} ->
+ read;
+ {0, 1} ->
+ write;
+ {0, 0} ->
+ none;
+ _ ->
+ undefined
+ end;
+file_mode_to_owner_access(_) ->
+ undefined.
unix_to_datetime(undefined) ->
undefined;
@@ -1438,3 +1466,21 @@ format_channel_start_error({shutdown, Reason}) ->
Reason;
format_channel_start_error(Reason) ->
Reason.
+
+%%%################################################################
+%%%#
+%%%# Tracing
+%%%#
+
+dbg_trace(points, _, _) -> [terminate];
+
+dbg_trace(flags, terminate, _) -> [c];
+dbg_trace(on, terminate, _) -> dbg:tp(?MODULE, terminate, 2, x);
+dbg_trace(off, terminate, _) -> dbg:ctpg(?MODULE, terminate, 2);
+dbg_trace(format, terminate, {call, {?MODULE,terminate, [Reason, State]}}) ->
+ ["Sftp Terminating:\n",
+ io_lib:format("Reason: ~p,~nState:~n~s", [Reason, wr_record(State)])
+ ].
+
+?wr_record(state).
+
diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl
index 427edf01ab..278f6a9780 100644
--- a/lib/ssh/src/ssh_sftpd.erl
+++ b/lib/ssh/src/ssh_sftpd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@
-module(ssh_sftpd).
--behaviour(ssh_daemon_channel).
+-behaviour(ssh_server_channel).
-include_lib("kernel/include/file.hrl").
@@ -38,6 +38,8 @@
-export([init/1, handle_ssh_msg/2, handle_msg/2, terminate/2]).
+-export([dbg_trace/3]).
+
-record(state, {
xf, % [{channel,ssh_xfer states}...]
cwd, % current dir (on first connect)
@@ -56,21 +58,7 @@
%%====================================================================
%% API
%%====================================================================
--spec init(Args :: term()) ->
- {ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} |
- {stop, Reason :: term()} | ignore.
-
--spec terminate(Reason :: (normal | shutdown | {shutdown, term()} |
- term()),
- State :: term()) ->
- term().
-
--spec handle_msg(Msg ::term(), State :: term()) ->
- {ok, State::term()} | {stop, ChannelId::integer(), State::term()}.
--spec handle_ssh_msg({ssh_cm, ConnectionRef::term(), SshMsg::term()},
- State::term()) -> {ok, State::term()} |
- {stop, ChannelId::integer(),
- State::term()}.
+-spec subsystem_spec(list()) -> subsystem_spec().
subsystem_spec(Options) ->
{"sftp", {?MODULE, Options}}.
@@ -137,9 +125,9 @@ handle_ssh_msg({ssh_cm, _, {signal, _, _}}, State) ->
%% Ignore signals according to RFC 4254 section 6.9.
{ok, State};
-handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, _, Error, _}}, State) ->
- Report = io_lib:format("Connection closed by peer ~n Error ~p~n",
- [Error]),
+handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, Signal, Error, _}}, State) ->
+ Report = io_lib:format("Connection closed by peer signal ~p~n Error ~p~n",
+ [Signal,Error]),
error_logger:error_report(Report),
{stop, ChannelId, State};
@@ -360,10 +348,12 @@ handle_op(?SSH_FXP_REMOVE, ReqId, <<?UINT32(PLen), BPath:PLen/binary>>,
case IsDir of %% This version 6 we still have ver 5
true when Vsn > 5 ->
ssh_xfer:xf_send_status(State0#state.xf, ReqId,
- ?SSH_FX_FILE_IS_A_DIRECTORY, "File is a directory");
+ ?SSH_FX_FILE_IS_A_DIRECTORY, "File is a directory"),
+ State0;
true ->
ssh_xfer:xf_send_status(State0#state.xf, ReqId,
- ?SSH_FX_FAILURE, "File is a directory");
+ ?SSH_FX_FAILURE, "File is a directory"),
+ State0;
false ->
{Status, FS1} = FileMod:delete(Path, FS0),
State1 = State0#state{file_state = FS1},
@@ -947,3 +937,20 @@ maybe_increase_recv_window(ConnectionManager, ChannelId, Options) ->
Increment =< 0 ->
do_nothing
end.
+
+%%%################################################################
+%%%#
+%%%# Tracing
+%%%#
+
+dbg_trace(points, _, _) -> [terminate];
+
+dbg_trace(flags, terminate, _) -> [c];
+dbg_trace(on, terminate, _) -> dbg:tp(?MODULE, terminate, 2, x);
+dbg_trace(off, terminate, _) -> dbg:ctpg(?MODULE, terminate, 2);
+dbg_trace(format, terminate, {call, {?MODULE,terminate, [Reason, State]}}) ->
+ ["SftpD Terminating:\n",
+ io_lib:format("Reason: ~p,~nState:~n~s", [Reason, wr_record(State)])
+ ].
+
+?wr_record(state).
diff --git a/lib/ssh/src/ssh_shell.erl b/lib/ssh/src/ssh_shell.erl
index 17224b6ef4..cdc9a6df5b 100644
--- a/lib/ssh/src/ssh_shell.erl
+++ b/lib/ssh/src/ssh_shell.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,18 +22,21 @@
-module(ssh_shell).
+-include("ssh.hrl").
-include("ssh_connect.hrl").
%%% As this is an user interactive client it behaves like a daemon
%%% channel inspite of it being a client.
--behaviour(ssh_daemon_channel).
+-behaviour(ssh_server_channel).
-%% ssh_channel callbacks
+%% ssh_server_channel callbacks
-export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]).
%% Spawn export
-export([input_loop/2]).
+-export([dbg_trace/3]).
+
-record(state,
{
io, %% Io process
@@ -43,23 +46,8 @@
).
%%====================================================================
-%% ssh_channel callbacks
+%% ssh_server_channel callbacks
%%====================================================================
--spec init(Args :: term()) ->
- {ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} |
- {stop, Reason :: term()} | ignore.
-
--spec terminate(Reason :: (normal | shutdown | {shutdown, term()} |
- term()),
- State :: term()) ->
- term().
-
--spec handle_msg(Msg ::term(), State :: term()) ->
- {ok, State::term()} | {stop, ChannelId::integer(), State::term()}.
--spec handle_ssh_msg({ssh_cm, ConnectionRef::term(), SshMsg::term()},
- State::term()) -> {ok, State::term()} |
- {stop, ChannelId::integer(),
- State::term()}.
%%--------------------------------------------------------------------
%% Function: init(Args) -> {ok, State}
@@ -194,3 +182,20 @@ get_ancestors() ->
A when is_list(A) -> A;
_ -> []
end.
+
+%%%################################################################
+%%%#
+%%%# Tracing
+%%%#
+
+dbg_trace(points, _, _) -> [terminate];
+
+dbg_trace(flags, terminate, _) -> [c];
+dbg_trace(on, terminate, _) -> dbg:tp(?MODULE, terminate, 2, x);
+dbg_trace(off, terminate, _) -> dbg:ctpg(?MODULE, terminate, 2);
+dbg_trace(format, terminate, {call, {?MODULE,terminate, [Reason, State]}}) ->
+ ["Shell Terminating:\n",
+ io_lib:format("Reason: ~p,~nState:~n~s", [Reason, wr_record(State)])
+ ].
+
+?wr_record(state).
diff --git a/lib/ssh/src/ssh_subsystem_sup.erl b/lib/ssh/src/ssh_subsystem_sup.erl
index 8db051095c..5fc8f7e764 100644
--- a/lib/ssh/src/ssh_subsystem_sup.erl
+++ b/lib/ssh/src/ssh_subsystem_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -48,7 +48,7 @@ connection_supervisor(SupPid) ->
channel_supervisor(SupPid) ->
Children = supervisor:which_children(SupPid),
- ssh_channel_sup(Children).
+ ssh_server_channel_sup(Children).
%%%=========================================================================
%%% Supervisor callback
@@ -74,18 +74,14 @@ ssh_connection_child_spec(Role, Address, Port, _Profile, Options) ->
#{id => id(Role, ssh_connection_sup, Address, Port),
start => {ssh_connection_sup, start_link, [Options]},
restart => temporary,
- shutdown => 5000,
- type => supervisor,
- modules => [ssh_connection_sup]
+ type => supervisor
}.
ssh_channel_child_spec(Role, Address, Port, _Profile, Options) ->
- #{id => id(Role, ssh_channel_sup, Address, Port),
- start => {ssh_channel_sup, start_link, [Options]},
+ #{id => id(Role, ssh_server_channel_sup, Address, Port),
+ start => {ssh_server_channel_sup, start_link, [Options]},
restart => temporary,
- shutdown => infinity,
- type => supervisor,
- modules => [ssh_channel_sup]
+ type => supervisor
}.
id(Role, Sup, Address, Port) ->
@@ -96,10 +92,10 @@ ssh_connection_sup([{_, Child, _, [ssh_connection_sup]} | _]) ->
ssh_connection_sup([_ | Rest]) ->
ssh_connection_sup(Rest).
-ssh_channel_sup([{_, Child, _, [ssh_channel_sup]} | _]) ->
+ssh_server_channel_sup([{_, Child, _, [ssh_server_channel_sup]} | _]) ->
Child;
-ssh_channel_sup([_ | Rest]) ->
- ssh_channel_sup(Rest).
+ssh_server_channel_sup([_ | Rest]) ->
+ ssh_server_channel_sup(Rest).
diff --git a/lib/ssh/src/ssh_sup.erl b/lib/ssh/src/ssh_sup.erl
index eaec7a54e4..61afbcd2ed 100644
--- a/lib/ssh/src/ssh_sup.erl
+++ b/lib/ssh/src/ssh_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,15 +36,14 @@ init(_) ->
intensity => 10,
period => 3600
},
- ChildSpecs = [#{id => Module,
- start => {Module, start_link, []},
- restart => permanent,
- shutdown => 4000, %brutal_kill,
- type => supervisor,
- modules => [Module]
+ ChildSpecs = [#{id => sshd_sup,
+ start => {sshd_sup, start_link, []},
+ type => supervisor
+ },
+ #{id => sshc_sup,
+ start => {sshc_sup, start_link, []},
+ type => supervisor
}
- || Module <- [sshd_sup,
- sshc_sup]
],
{ok, {SupFlags,ChildSpecs}}.
diff --git a/lib/ssh/src/ssh_system_sup.erl b/lib/ssh/src/ssh_system_sup.erl
index e70abf59c2..ed7c0c2bd5 100644
--- a/lib/ssh/src/ssh_system_sup.erl
+++ b/lib/ssh/src/ssh_system_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -63,9 +63,7 @@ init([Address, Port, Profile, Options]) ->
[#{id => id(ssh_acceptor_sup, Address, Port, Profile),
start => {ssh_acceptor_sup, start_link, [Address, Port, Profile, Options]},
restart => transient,
- shutdown => infinity,
- type => supervisor,
- modules => [ssh_acceptor_sup]
+ type => supervisor
}];
_ ->
[]
@@ -90,11 +88,11 @@ stop_listener(Address, Port, Profile) ->
stop_system(SysSup) ->
- spawn(fun() -> sshd_sup:stop_child(SysSup) end),
+ catch sshd_sup:stop_child(SysSup),
ok.
stop_system(Address, Port, Profile) ->
- spawn(fun() -> sshd_sup:stop_child(Address, Port, Profile) end),
+ catch sshd_sup:stop_child(Address, Port, Profile),
ok.
@@ -124,9 +122,8 @@ start_subsystem(SystemSup, Role, Address, Port, Profile, Options) ->
#{id => make_ref(),
start => {ssh_subsystem_sup, start_link, [Role, Address, Port, Profile, Options]},
restart => temporary,
- shutdown => infinity,
- type => supervisor,
- modules => [ssh_subsystem_sup]},
+ type => supervisor
+ },
supervisor:start_child(SystemSup, SubsystemSpec).
stop_subsystem(SystemSup, SubSys) ->
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index 412f5de9de..c5b0704925 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,7 +34,9 @@
-export([next_seqnum/1,
supported_algorithms/0, supported_algorithms/1,
default_algorithms/0, default_algorithms/1,
- handle_packet_part/4,
+ algo_classes/0, algo_class/1,
+ algo_two_spec_classes/0, algo_two_spec_class/1,
+ handle_packet_part/5,
handle_hello_version/1,
key_exchange_init_msg/1,
key_init/3, new_keys_message/1,
@@ -49,10 +51,12 @@
extract_public_key/1,
ssh_packet/2, pack/2,
valid_key_sha_alg/2,
- sha/1, sign/3, verify/4]).
+ sha/1, sign/3, verify/5]).
+
+-export([dbg_trace/3]).
%%% For test suites
--export([pack/3]).
+-export([pack/3, adjust_algs_for_peer_version/2]).
-export([decompress/2, decrypt_blocks/3, is_valid_mac/3 ]). % FIXME: remove
-define(Estring(X), ?STRING((if is_binary(X) -> X;
@@ -81,14 +85,33 @@ default_algorithms() -> [{K,default_algorithms(K)} || K <- algo_classes()].
algo_classes() -> [kex, public_key, cipher, mac, compression].
+algo_class(kex) -> true;
+algo_class(public_key) -> true;
+algo_class(cipher) -> true;
+algo_class(mac) -> true;
+algo_class(compression) -> true;
+algo_class(_) -> false.
+
+
+algo_two_spec_classes() -> [cipher, mac, compression].
+
+algo_two_spec_class(cipher) -> true;
+algo_two_spec_class(mac) -> true;
+algo_two_spec_class(compression) -> true;
+algo_two_spec_class(_) -> false.
+
+
+
default_algorithms(kex) ->
supported_algorithms(kex, [
- 'diffie-hellman-group1-sha1' % Gone in OpenSSH 7.3.p1
+ %% Gone in OpenSSH 7.3.p1:
+ 'diffie-hellman-group1-sha1'
]);
default_algorithms(cipher) ->
supported_algorithms(cipher, same(['AEAD_AES_128_GCM',
- 'AEAD_AES_256_GCM']));
+ 'AEAD_AES_256_GCM'
+ ]));
default_algorithms(mac) ->
supported_algorithms(mac, same(['AEAD_AES_128_GCM',
'AEAD_AES_256_GCM']));
@@ -102,13 +125,18 @@ supported_algorithms() -> [{K,supported_algorithms(K)} || K <- algo_classes()].
supported_algorithms(kex) ->
select_crypto_supported(
[
- {'ecdh-sha2-nistp384', [{public_keys,ecdh}, {ec_curve,secp384r1}, {hashs,sha384}]},
- {'ecdh-sha2-nistp521', [{public_keys,ecdh}, {ec_curve,secp521r1}, {hashs,sha512}]},
- {'ecdh-sha2-nistp256', [{public_keys,ecdh}, {ec_curve,secp256r1}, {hashs,sha256}]},
+ {'ecdh-sha2-nistp384', [{public_keys,ecdh}, {curves,secp384r1}, {hashs,sha384}]},
+ {'ecdh-sha2-nistp521', [{public_keys,ecdh}, {curves,secp521r1}, {hashs,sha512}]},
+ {'ecdh-sha2-nistp256', [{public_keys,ecdh}, {curves,secp256r1}, {hashs,sha256}]},
{'diffie-hellman-group-exchange-sha256', [{public_keys,dh}, {hashs,sha256}]},
{'diffie-hellman-group16-sha512', [{public_keys,dh}, {hashs,sha512}]}, % In OpenSSH 7.3.p1
{'diffie-hellman-group18-sha512', [{public_keys,dh}, {hashs,sha512}]}, % In OpenSSH 7.3.p1
{'diffie-hellman-group14-sha256', [{public_keys,dh}, {hashs,sha256}]}, % In OpenSSH 7.3.p1
+ %% https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves
+ %% Secure Shell (SSH) Key Exchange Method using Curve25519 and Curve448
+ {'curve25519-sha256', [{public_keys,ecdh}, {curves,x25519}, {hashs,sha256}]},
+ {'[email protected]', [{public_keys,ecdh}, {curves,x25519}, {hashs,sha256}]},
+ {'curve448-sha512', [{public_keys,ecdh}, {curves,x448}, {hashs,sha512}]},
{'diffie-hellman-group14-sha1', [{public_keys,dh}, {hashs,sha}]},
{'diffie-hellman-group-exchange-sha1', [{public_keys,dh}, {hashs,sha}]},
{'diffie-hellman-group1-sha1', [{public_keys,dh}, {hashs,sha}]}
@@ -116,9 +144,9 @@ supported_algorithms(kex) ->
supported_algorithms(public_key) ->
select_crypto_supported(
[
- {'ecdsa-sha2-nistp384', [{public_keys,ecdsa}, {hashs,sha384}, {ec_curve,secp384r1}]},
- {'ecdsa-sha2-nistp521', [{public_keys,ecdsa}, {hashs,sha512}, {ec_curve,secp521r1}]},
- {'ecdsa-sha2-nistp256', [{public_keys,ecdsa}, {hashs,sha256}, {ec_curve,secp256r1}]},
+ {'ecdsa-sha2-nistp384', [{public_keys,ecdsa}, {hashs,sha384}, {curves,secp384r1}]},
+ {'ecdsa-sha2-nistp521', [{public_keys,ecdsa}, {hashs,sha512}, {curves,secp521r1}]},
+ {'ecdsa-sha2-nistp256', [{public_keys,ecdsa}, {hashs,sha256}, {curves,secp256r1}]},
{'ssh-rsa', [{public_keys,rsa}, {hashs,sha} ]},
{'rsa-sha2-256', [{public_keys,rsa}, {hashs,sha256} ]},
{'rsa-sha2-512', [{public_keys,rsa}, {hashs,sha512} ]},
@@ -129,6 +157,7 @@ supported_algorithms(cipher) ->
same(
select_crypto_supported(
[
+ {'[email protected]', [{ciphers,chacha20}, {macs,poly1305}]},
{'[email protected]', [{ciphers,{aes_gcm,256}}]},
{'aes256-ctr', [{ciphers,{aes_ctr,256}}]},
{'aes192-ctr', [{ciphers,{aes_ctr,192}}]},
@@ -143,9 +172,9 @@ supported_algorithms(cipher) ->
supported_algorithms(mac) ->
same(
select_crypto_supported(
- [{'hmac-sha2-256', [{hashs,sha256}]},
- {'hmac-sha2-512', [{hashs,sha512}]},
- {'hmac-sha1', [{hashs,sha}]},
+ [{'hmac-sha2-256', [{macs,hmac}, {hashs,sha256}]},
+ {'hmac-sha2-512', [{macs,hmac}, {hashs,sha512}]},
+ {'hmac-sha1', [{macs,hmac}, {hashs,sha}]},
{'AEAD_AES_128_GCM', [{ciphers,{aes_gcm,128}}]},
{'AEAD_AES_256_GCM', [{ciphers,{aes_gcm,256}}]}
]
@@ -232,9 +261,9 @@ key_exchange_init_msg(Ssh0) ->
{SshPacket, Ssh} = ssh_packet(Msg, Ssh0),
{Msg, SshPacket, Ssh}.
-kex_init(#ssh{role = Role, opts = Opts, available_host_keys = HostKeyAlgs}) ->
+kex_init(#ssh{role = Role, opts = Opts, available_host_keys = HostKeyAlgs} = Ssh) ->
Random = ssh_bits:random(16),
- PrefAlgs = ?GET_OPT(preferred_algorithms, Opts),
+ PrefAlgs = adjust_algs_for_peer_version(Role, ?GET_OPT(preferred_algorithms, Opts), Ssh),
kexinit_message(Role, Random, PrefAlgs, HostKeyAlgs, Opts).
key_init(client, Ssh, Value) ->
@@ -242,7 +271,22 @@ key_init(client, Ssh, Value) ->
key_init(server, Ssh, Value) ->
Ssh#ssh{s_keyinit = Value}.
-
+adjust_algs_for_peer_version(client, PrefAlgs, #ssh{s_version=V}) ->
+ adjust_algs_for_peer_version(V, PrefAlgs);
+adjust_algs_for_peer_version(server, PrefAlgs, #ssh{c_version=V}) ->
+ adjust_algs_for_peer_version(V, PrefAlgs).
+%%
+adjust_algs_for_peer_version("SSH-2.0-OpenSSH_6.2"++_, PrefAlgs) ->
+ C0 = proplists:get_value(cipher, PrefAlgs, same([])),
+ C = [{D,L} || D <- [client2server, server2client],
+ L <- [[K || K <- proplists:get_value(D, C0, []),
+ K =/= '[email protected]']]
+ ],
+ lists:keyreplace(cipher, 1, PrefAlgs, {cipher,C});
+adjust_algs_for_peer_version(_, PrefAlgs) ->
+ PrefAlgs.
+
kexinit_message(Role, Random, Algs, HostKeyAlgs, Opts) ->
#ssh_msg_kexinit{
cookie = Random,
@@ -285,10 +329,11 @@ handle_kexinit_msg(#ssh_msg_kexinit{} = CounterPart, #ssh_msg_kexinit{} = Own,
key_exchange_first_msg(Algos#alg.kex,
Ssh#ssh{algorithms = Algos})
catch
- _:_ ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Selection of key exchange algorithm failed"})
+ Class:Error ->
+ ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ io_lib:format("Kexinit failed in client: ~p:~p",
+ [Class,Error])
+ )
end;
handle_kexinit_msg(#ssh_msg_kexinit{} = CounterPart, #ssh_msg_kexinit{} = Own,
@@ -301,10 +346,11 @@ handle_kexinit_msg(#ssh_msg_kexinit{} = CounterPart, #ssh_msg_kexinit{} = Own,
Algos ->
{ok, Ssh#ssh{algorithms = Algos}}
catch
- _:_ ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Selection of key exchange algorithm failed"})
+ Class:Error ->
+ ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ io_lib:format("Kexinit failed in server: ~p:~p",
+ [Class,Error])
+ )
end.
@@ -365,7 +411,10 @@ key_exchange_first_msg(Kex, Ssh0=#ssh{opts=Opts}) when Kex == 'diffie-hellman-gr
key_exchange_first_msg(Kex, Ssh0) when Kex == 'ecdh-sha2-nistp256' ;
Kex == 'ecdh-sha2-nistp384' ;
- Kex == 'ecdh-sha2-nistp521' ->
+ Kex == 'ecdh-sha2-nistp521' ;
+ Kex == 'curve25519-sha256' ;
+ Kex == '[email protected]';
+ Kex == 'curve448-sha512' ->
Curve = ecdh_curve(Kex),
{Public, Private} = generate_key(ecdh, Curve),
{SshPacket, Ssh1} = ssh_packet(#ssh_msg_kex_ecdh_init{q_c=Public}, Ssh0),
@@ -392,7 +441,7 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E},
K = compute_key(dh, E, Private, [P,G]),
MyPrivHostKey = get_host_key(Ssh0, SignAlg),
MyPubHostKey = extract_public_key(MyPrivHostKey),
- H = kex_hash(Ssh0, MyPubHostKey, SignAlg, sha(Kex), {E,Public,K}),
+ H = kex_hash(Ssh0, MyPubHostKey, sha(Kex), {E,Public,K}),
H_SIG = sign(H, sha(SignAlg), MyPrivHostKey),
{SshPacket, Ssh1} =
ssh_packet(#ssh_msg_kexdh_reply{public_host_key = {MyPubHostKey,SignAlg},
@@ -405,25 +454,22 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E},
session_id = sid(Ssh1, H)}};
true ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Key exchange failed, 'e' out of bounds"},
- {error,bad_e_from_peer}
- )
+ ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ io_lib:format("Kexdh init failed, received 'e' out of bounds~n E=~p~n P=~p",
+ [E,P])
+ )
end.
handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = PeerPubHostKey,
f = F,
h_sig = H_SIG},
#ssh{keyex_key = {{Private, Public}, {G, P}},
- algorithms = #alg{kex=Kex,
- hkey=SignAlg}} = Ssh0) ->
+ algorithms = #alg{kex=Kex}} = Ssh0) ->
%% client
if
1=<F, F=<(P-1)->
K = compute_key(dh, F, Private, [P,G]),
- H = kex_hash(Ssh0, PeerPubHostKey, SignAlg, sha(Kex), {Public,F,K}),
+ H = kex_hash(Ssh0, PeerPubHostKey, sha(Kex), {Public,F,K}),
case verify_host_key(Ssh0, PeerPubHostKey, H, H_SIG) of
ok ->
{SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0),
@@ -431,20 +477,16 @@ handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = PeerPubHostKey,
exchanged_hash = H,
session_id = sid(Ssh, H)})};
Error ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Key exchange failed"},
- Error)
+ ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ io_lib:format("Kexdh init failed. Verify host key: ~p",[Error])
+ )
end;
true ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Key exchange failed, 'f' out of bounds"},
- bad_f_from_peer
- )
+ ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ io_lib:format("Kexdh init failed, received 'f' out of bounds~n F=~p~n P=~p",
+ [F,P])
+ )
end.
@@ -468,11 +510,9 @@ handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request{min = Min0,
keyex_info = {Min0, Max0, NBits}
}};
{error,_} ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
- description = "No possible diffie-hellman-group-exchange group found"
- })
+ ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ io_lib:format("No possible diffie-hellman-group-exchange group found",[])
+ )
end;
handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request_old{n = NBits},
@@ -502,20 +542,14 @@ handle_kex_dh_gex_request(#ssh_msg_kex_dh_gex_request_old{n = NBits},
keyex_info = {-1, -1, NBits} % flag for kex_hash calc
}};
{error,_} ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
- description = "No possible diffie-hellman-group-exchange group found"
- })
+ ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ io_lib:format("No possible diffie-hellman-group-exchange group found",[])
+ )
end;
handle_kex_dh_gex_request(_, _) ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Key exchange failed, bad values in ssh_msg_kex_dh_gex_request"},
- bad_ssh_msg_kex_dh_gex_request).
-
+ ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ "Key exchange failed, bad values in ssh_msg_kex_dh_gex_request").
adjust_gex_min_max(Min0, Max0, Opts) ->
{Min1, Max1} = ?GET_OPT(dh_gex_limits, Opts),
@@ -525,11 +559,8 @@ adjust_gex_min_max(Min0, Max0, Opts) ->
Min2 =< Max2 ->
{Min2, Max2};
Max2 < Min2 ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
- description = "No possible diffie-hellman-group-exchange group possible"
- })
+ ?DISCONNECT(?SSH_DISCONNECT_PROTOCOL_ERROR,
+ "No possible diffie-hellman-group-exchange group possible")
end.
@@ -556,7 +587,7 @@ handle_kex_dh_gex_init(#ssh_msg_kex_dh_gex_init{e = E},
1<K, K<(P-1) ->
MyPrivHostKey = get_host_key(Ssh0, SignAlg),
MyPubHostKey = extract_public_key(MyPrivHostKey),
- H = kex_hash(Ssh0, MyPubHostKey, SignAlg, sha(Kex), {Min,NBits,Max,P,G,E,Public,K}),
+ H = kex_hash(Ssh0, MyPubHostKey, sha(Kex), {Min,NBits,Max,P,G,E,Public,K}),
H_SIG = sign(H, sha(SignAlg), MyPrivHostKey),
{SshPacket, Ssh} =
ssh_packet(#ssh_msg_kex_dh_gex_reply{public_host_key = {MyPubHostKey,SignAlg},
@@ -567,18 +598,15 @@ handle_kex_dh_gex_init(#ssh_msg_kex_dh_gex_init{e = E},
session_id = sid(Ssh, H)
}};
true ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Key exchange failed, 'K' out of bounds"},
- bad_K)
+ ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ "Kexdh init failed, received 'k' out of bounds"
+ )
end;
true ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Key exchange failed, 'e' out of bounds"},
- bad_e_from_peer)
+ ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ io_lib:format("Kexdh gex init failed, received 'e' out of bounds~n E=~p~n P=~p",
+ [E,P])
+ )
end.
handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = PeerPubHostKey,
@@ -586,8 +614,7 @@ handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = PeerPubHostK
h_sig = H_SIG},
#ssh{keyex_key = {{Private, Public}, {G, P}},
keyex_info = {Min, Max, NBits},
- algorithms = #alg{kex=Kex,
- hkey=SignAlg}} =
+ algorithms = #alg{kex=Kex}} =
Ssh0) ->
%% client
if
@@ -595,35 +622,29 @@ handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = PeerPubHostK
K = compute_key(dh, F, Private, [P,G]),
if
1<K, K<(P-1) ->
- H = kex_hash(Ssh0, PeerPubHostKey, SignAlg, sha(Kex), {Min,NBits,Max,P,G,Public,F,K}),
+ H = kex_hash(Ssh0, PeerPubHostKey, sha(Kex), {Min,NBits,Max,P,G,Public,F,K}),
case verify_host_key(Ssh0, PeerPubHostKey, H, H_SIG) of
ok ->
{SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0),
{ok, SshPacket, install_alg(snd, Ssh#ssh{shared_secret = ssh_bits:mpint(K),
exchanged_hash = H,
session_id = sid(Ssh, H)})};
- _Error ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Key exchange failed"
- })
+ Error ->
+ ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ io_lib:format("Kexdh gex reply failed. Verify host key: ~p",[Error])
+ )
end;
true ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Key exchange failed, 'K' out of bounds"},
- bad_K)
+ ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ "Kexdh gex init failed, 'K' out of bounds"
+ )
end;
true ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Key exchange failed, 'f' out of bounds"},
- bad_f_from_peer
- )
+ ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ io_lib:format("Kexdh gex init failed, received 'f' out of bounds~n F=~p~n P=~p",
+ [F,P])
+ )
end.
%%%----------------------------------------------------------------
@@ -642,7 +663,7 @@ handle_kex_ecdh_init(#ssh_msg_kex_ecdh_init{q_c = PeerPublic},
K ->
MyPrivHostKey = get_host_key(Ssh0, SignAlg),
MyPubHostKey = extract_public_key(MyPrivHostKey),
- H = kex_hash(Ssh0, MyPubHostKey, SignAlg, sha(Curve), {PeerPublic, MyPublic, K}),
+ H = kex_hash(Ssh0, MyPubHostKey, sha(Curve), {PeerPublic, MyPublic, K}),
H_SIG = sign(H, sha(SignAlg), MyPrivHostKey),
{SshPacket, Ssh1} =
ssh_packet(#ssh_msg_kex_ecdh_reply{public_host_key = {MyPubHostKey,SignAlg},
@@ -654,26 +675,27 @@ handle_kex_ecdh_init(#ssh_msg_kex_ecdh_init{q_c = PeerPublic},
exchanged_hash = H,
session_id = sid(Ssh1, H)}}
catch
- _:_ ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Peer ECDH public key is invalid"},
- invalid_peer_public_key)
+ Class:Error ->
+ ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ io_lib:format("ECDH compute key failed in server: ~p:~p~n"
+ "Kex: ~p, Curve: ~p~n"
+ "PeerPublic: ~p",
+ [Class,Error,Kex,Curve,PeerPublic])
+ )
end.
handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = PeerPubHostKey,
q_s = PeerPublic,
h_sig = H_SIG},
- #ssh{keyex_key = {{MyPublic,MyPrivate}, Curve},
- algorithms = #alg{hkey=SignAlg}} = Ssh0
+ #ssh{keyex_key = {{MyPublic,MyPrivate}, Curve}
+ } = Ssh0
) ->
%% at client
try
compute_key(ecdh, PeerPublic, MyPrivate, Curve)
of
K ->
- H = kex_hash(Ssh0, PeerPubHostKey, SignAlg, sha(Curve), {MyPublic,PeerPublic,K}),
+ H = kex_hash(Ssh0, PeerPubHostKey, sha(Curve), {MyPublic,PeerPublic,K}),
case verify_host_key(Ssh0, PeerPubHostKey, H, H_SIG) of
ok ->
{SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0),
@@ -681,19 +703,16 @@ handle_kex_ecdh_reply(#ssh_msg_kex_ecdh_reply{public_host_key = PeerPubHostKey,
exchanged_hash = H,
session_id = sid(Ssh, H)})};
Error ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Key exchange failed"},
- Error)
+ ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ io_lib:format("ECDH reply failed. Verify host key: ~p",[Error])
+ )
end
catch
- _:_ ->
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{
- code = ?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- description = "Peer ECDH public key is invalid"},
- invalid_peer_public_key)
+ Class:Error ->
+ ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
+ io_lib:format("Peer ECDH public key seem invalid: ~p:~p",
+ [Class,Error])
+ )
end.
@@ -703,11 +722,11 @@ handle_new_keys(#ssh_msg_newkeys{}, Ssh0) ->
#ssh{} = Ssh ->
{ok, Ssh}
catch
- _C:_Error -> %% TODO: Throw earlier ....
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
- description = "Install alg failed"
- })
+ Class:Error -> %% TODO: Throw earlier ...
+ ?DISCONNECT(?SSH_DISCONNECT_PROTOCOL_ERROR,
+ io_lib:format("Install alg failed: ~p:~p",
+ [Class,Error])
+ )
end.
@@ -763,8 +782,14 @@ get_host_key(SSH, SignAlg) ->
#ssh{key_cb = {KeyCb,KeyCbOpts}, opts = Opts} = SSH,
UserOpts = ?GET_OPT(user_options, Opts),
case KeyCb:host_key(SignAlg, [{key_cb_private,KeyCbOpts}|UserOpts]) of
- {ok, PrivHostKey} -> PrivHostKey;
- Result -> exit({error, {Result, unsupported_key_type}})
+ {ok, PrivHostKey} ->
+ %% Check the key - the KeyCb may be a buggy plugin
+ case valid_key_sha_alg(PrivHostKey, SignAlg) of
+ true -> PrivHostKey;
+ false -> exit({error, bad_hostkey})
+ end;
+ Result ->
+ exit({error, {Result, unsupported_key_type}})
end.
extract_public_key(#'RSAPrivateKey'{modulus = N, publicExponent = E}) ->
@@ -773,13 +798,21 @@ extract_public_key(#'DSAPrivateKey'{y = Y, p = P, q = Q, g = G}) ->
{Y, #'Dss-Parms'{p=P, q=Q, g=G}};
extract_public_key(#'ECPrivateKey'{parameters = {namedCurve,OID},
publicKey = Q}) ->
- {#'ECPoint'{point=Q}, {namedCurve,OID}}.
+ {#'ECPoint'{point=Q}, {namedCurve,OID}};
+extract_public_key(#{engine:=_, key_id:=_, algorithm:=Alg} = M) ->
+ case {Alg, crypto:privkey_to_pubkey(Alg, M)} of
+ {rsa, [E,N]} ->
+ #'RSAPublicKey'{modulus = N, publicExponent = E};
+ {dss, [P,Q,G,Y]} ->
+ {Y, #'Dss-Parms'{p=P, q=Q, g=G}}
+ end.
+
verify_host_key(#ssh{algorithms=Alg}=SSH, PublicKey, Digest, {AlgStr,Signature}) ->
case atom_to_list(Alg#alg.hkey) of
AlgStr ->
- case verify(Digest, sha(Alg#alg.hkey), Signature, PublicKey) of
+ case verify(Digest, sha(Alg#alg.hkey), Signature, PublicKey, SSH) of
false ->
{error, bad_signature};
true ->
@@ -790,6 +823,7 @@ verify_host_key(#ssh{algorithms=Alg}=SSH, PublicKey, Digest, {AlgStr,Signature})
end.
+%%% -> boolean() | {error,_}
accepted_host(Ssh, PeerName, Public, Opts) ->
case ?GET_OPT(silently_accept_hosts, Opts) of
@@ -811,11 +845,16 @@ accepted_host(Ssh, PeerName, Public, Opts) ->
%% Call-back alternatives: A user provided fun is called for the decision:
F when is_function(F,2) ->
- true == (catch F(PeerName, public_key:ssh_hostkey_fingerprint(Public)));
+ case catch F(PeerName, public_key:ssh_hostkey_fingerprint(Public)) of
+ true -> true;
+ _ -> {error, fingerprint_check_failed}
+ end;
{DigestAlg,F} when is_function(F,2) ->
- true == (catch F(PeerName, public_key:ssh_hostkey_fingerprint(DigestAlg,Public)))
-
+ case catch F(PeerName, public_key:ssh_hostkey_fingerprint(DigestAlg,Public)) of
+ true -> true;
+ _ -> {error, {fingerprint_check_failed,DigestAlg}}
+ end
end.
@@ -833,18 +872,30 @@ fmt_hostkey(X) -> X.
known_host_key(#ssh{opts = Opts, key_cb = {KeyCb,KeyCbOpts}, peer = {PeerName,_}} = Ssh,
Public, Alg) ->
UserOpts = ?GET_OPT(user_options, Opts),
- case KeyCb:is_host_key(Public, PeerName, Alg, [{key_cb_private,KeyCbOpts}|UserOpts]) of
- true ->
+ case is_host_key(KeyCb, Public, PeerName, Alg, [{key_cb_private,KeyCbOpts}|UserOpts]) of
+ {_,true} ->
ok;
- false ->
+ {_,false} ->
+ DoAdd = ?GET_OPT(save_accepted_host, Opts),
case accepted_host(Ssh, PeerName, Public, Opts) of
- true ->
- KeyCb:add_host_key(PeerName, Public, [{key_cb_private,KeyCbOpts}|UserOpts]);
+ true when DoAdd == true ->
+ {_,R} = add_host_key(KeyCb, PeerName, Public, [{key_cb_private,KeyCbOpts}|UserOpts]),
+ R;
+ true when DoAdd == false ->
+ ok;
false ->
- {error, rejected}
+ {error, rejected_by_user};
+ {error,E} ->
+ {error,E}
end
end.
+is_host_key(KeyCb, Public, PeerName, Alg, Data) ->
+ {KeyCb, KeyCb:is_host_key(Public, PeerName, Alg, Data)}.
+
+add_host_key(KeyCb, PeerName, Public, Data) ->
+ {KeyCb, KeyCb:add_host_key(PeerName, Public, Data)}.
+
%% Each of the algorithm strings MUST be a comma-separated list of
%% algorithm names (see ''Algorithm Naming'' in [SSH-ARCH]). Each
@@ -929,13 +980,14 @@ select_algorithm(Role, Client, Server, Opts) ->
%%% the exchanged MAC algorithms are ignored and there doesn't have to be
%%% a matching MAC.
-aead_gcm_simultan('[email protected]', _) -> {'AEAD_AES_128_GCM', 'AEAD_AES_128_GCM'};
-aead_gcm_simultan('[email protected]', _) -> {'AEAD_AES_256_GCM', 'AEAD_AES_256_GCM'};
-aead_gcm_simultan('AEAD_AES_128_GCM', _) -> {'AEAD_AES_128_GCM', 'AEAD_AES_128_GCM'};
-aead_gcm_simultan('AEAD_AES_256_GCM', _) -> {'AEAD_AES_256_GCM', 'AEAD_AES_256_GCM'};
-aead_gcm_simultan(_, 'AEAD_AES_128_GCM') -> {'AEAD_AES_128_GCM', 'AEAD_AES_128_GCM'};
-aead_gcm_simultan(_, 'AEAD_AES_256_GCM') -> {'AEAD_AES_256_GCM', 'AEAD_AES_256_GCM'};
-aead_gcm_simultan(Cipher, Mac) -> {Cipher,Mac}.
+aead_gcm_simultan('[email protected]', _) -> {'AEAD_AES_128_GCM', 'AEAD_AES_128_GCM'};
+aead_gcm_simultan('[email protected]', _) -> {'AEAD_AES_256_GCM', 'AEAD_AES_256_GCM'};
+aead_gcm_simultan('AEAD_AES_128_GCM'=C, _) -> {C, C};
+aead_gcm_simultan('AEAD_AES_256_GCM'=C, _) -> {C, C};
+aead_gcm_simultan(_, 'AEAD_AES_128_GCM'=C) -> {C, C};
+aead_gcm_simultan(_, 'AEAD_AES_256_GCM'=C) -> {C, C};
+aead_gcm_simultan('[email protected]'=C, _)-> {C, C};
+aead_gcm_simultan(Cipher, Mac) -> {Cipher,Mac}.
select_encrypt_decrypt(client, Client, Server) ->
@@ -993,9 +1045,7 @@ install_alg(Dir, SSH) ->
alg_setup(snd, SSH) ->
ALG = SSH#ssh.algorithms,
- SSH#ssh{kex = ALG#alg.kex,
- hkey = ALG#alg.hkey,
- encrypt = ALG#alg.encrypt,
+ SSH#ssh{encrypt = ALG#alg.encrypt,
send_mac = ALG#alg.send_mac,
send_mac_size = mac_digest_size(ALG#alg.send_mac),
compress = ALG#alg.compress,
@@ -1007,9 +1057,7 @@ alg_setup(snd, SSH) ->
alg_setup(rcv, SSH) ->
ALG = SSH#ssh.algorithms,
- SSH#ssh{kex = ALG#alg.kex,
- hkey = ALG#alg.hkey,
- decrypt = ALG#alg.decrypt,
+ SSH#ssh{decrypt = ALG#alg.decrypt,
recv_mac = ALG#alg.recv_mac,
recv_mac_size = mac_digest_size(ALG#alg.recv_mac),
decompress = ALG#alg.decompress,
@@ -1051,10 +1099,9 @@ select_all(CL, SL) when length(CL) + length(SL) < ?MAX_NUM_ALGORITHMS ->
%% algorithms used by client and server (client pref)
lists:map(fun(ALG) -> list_to_atom(ALG) end, (CL -- A));
select_all(CL, SL) ->
- Err = lists:concat(["Received too many algorithms (",length(CL),"+",length(SL)," >= ",?MAX_NUM_ALGORITHMS,")."]),
- ssh_connection_handler:disconnect(
- #ssh_msg_disconnect{code = ?SSH_DISCONNECT_PROTOCOL_ERROR,
- description = Err}).
+ Error = lists:concat(["Received too many algorithms (",length(CL),"+",length(SL)," >= ",?MAX_NUM_ALGORITHMS,")."]),
+ ?DISCONNECT(?SSH_DISCONNECT_PROTOCOL_ERROR,
+ Error).
select([], []) ->
@@ -1088,7 +1135,7 @@ pack(PlainText,
encrypt = CryptoAlg} = Ssh0, PacketLenDeviationForTests) when is_binary(PlainText) ->
{Ssh1, CompressedPlainText} = compress(Ssh0, PlainText),
- {EcryptedPacket, MAC, Ssh3} =
+ {FinalPacket, Ssh3} =
case pkt_type(CryptoAlg) of
common ->
PaddingLen = padding_length(4+1+size(CompressedPlainText), Ssh0),
@@ -1097,16 +1144,15 @@ pack(PlainText,
PlainPacketData = <<?UINT32(PlainPacketLen),?BYTE(PaddingLen), CompressedPlainText/binary, Padding/binary>>,
{Ssh2, EcryptedPacket0} = encrypt(Ssh1, PlainPacketData),
MAC0 = mac(MacAlg, MacKey, SeqNum, PlainPacketData),
- {EcryptedPacket0, MAC0, Ssh2};
+ {<<EcryptedPacket0/binary,MAC0/binary>>, Ssh2};
aead ->
PaddingLen = padding_length(1+size(CompressedPlainText), Ssh0),
Padding = ssh_bits:random(PaddingLen),
PlainPacketLen = 1 + PaddingLen + size(CompressedPlainText) + PacketLenDeviationForTests,
PlainPacketData = <<?BYTE(PaddingLen), CompressedPlainText/binary, Padding/binary>>,
- {Ssh2, {EcryptedPacket0,MAC0}} = encrypt(Ssh1, {<<?UINT32(PlainPacketLen)>>,PlainPacketData}),
- {<<?UINT32(PlainPacketLen),EcryptedPacket0/binary>>, MAC0, Ssh2}
+ {Ssh2, {EcryptedPacket0,MAC0}} = encrypt(Ssh1, <<?UINT32(PlainPacketLen),PlainPacketData/binary>>),
+ {<<EcryptedPacket0/binary,MAC0/binary>>, Ssh2}
end,
- FinalPacket = [EcryptedPacket, MAC],
Ssh = Ssh3#ssh{send_sequence = (SeqNum+1) band 16#ffffffff},
{FinalPacket, Ssh}.
@@ -1126,31 +1172,31 @@ padding_length(Size, #ssh{encrypt_block_size = BlockSize,
-handle_packet_part(<<>>, Encrypted0, undefined, #ssh{decrypt = CryptoAlg} = Ssh0) ->
+handle_packet_part(<<>>, Encrypted0, AEAD0, undefined, #ssh{decrypt = CryptoAlg} = Ssh0) ->
%% New ssh packet
case get_length(pkt_type(CryptoAlg), Encrypted0, Ssh0) of
get_more ->
%% too short to get the length
- {get_more, <<>>, Encrypted0, undefined, Ssh0};
+ {get_more, <<>>, Encrypted0, AEAD0, undefined, Ssh0};
- {ok, PacketLen, _, _, _} when PacketLen > ?SSH_MAX_PACKET_SIZE ->
+ {ok, PacketLen, _, _, _, _} when PacketLen > ?SSH_MAX_PACKET_SIZE ->
%% far too long message than expected
{error, {exceeds_max_size,PacketLen}};
- {ok, PacketLen, Decrypted, Encrypted1,
+ {ok, PacketLen, Decrypted, Encrypted1, AEAD,
#ssh{recv_mac_size = MacSize} = Ssh1} ->
%% enough bytes so we got the length and can calculate how many
%% more bytes to expect for a full packet
TotalNeeded = (4 + PacketLen + MacSize),
- handle_packet_part(Decrypted, Encrypted1, TotalNeeded, Ssh1)
+ handle_packet_part(Decrypted, Encrypted1, AEAD, TotalNeeded, Ssh1)
end;
-handle_packet_part(DecryptedPfx, EncryptedBuffer, TotalNeeded, Ssh0)
+handle_packet_part(DecryptedPfx, EncryptedBuffer, AEAD, TotalNeeded, Ssh0)
when (size(DecryptedPfx)+size(EncryptedBuffer)) < TotalNeeded ->
%% need more bytes to finalize the packet
- {get_more, DecryptedPfx, EncryptedBuffer, TotalNeeded, Ssh0};
+ {get_more, DecryptedPfx, EncryptedBuffer, AEAD, TotalNeeded, Ssh0};
-handle_packet_part(DecryptedPfx, EncryptedBuffer, TotalNeeded,
+handle_packet_part(DecryptedPfx, EncryptedBuffer, AEAD, TotalNeeded,
#ssh{recv_mac_size = MacSize,
decrypt = CryptoAlg} = Ssh0) ->
%% enough bytes to decode the packet.
@@ -1168,8 +1214,7 @@ handle_packet_part(DecryptedPfx, EncryptedBuffer, TotalNeeded,
{packet_decrypted, DecompressedPayload, NextPacketBytes, Ssh}
end;
aead ->
- PacketLenBin = DecryptedPfx,
- case decrypt(Ssh0, {PacketLenBin,EncryptedSfx,Mac}) of
+ case decrypt(Ssh0, {AEAD,EncryptedSfx,Mac}) of
{Ssh1, error} ->
{bad_mac, Ssh1};
{Ssh1, DecryptedSfx} ->
@@ -1186,21 +1231,29 @@ get_length(common, EncryptedBuffer, #ssh{decrypt_block_size = BlockSize} = Ssh0)
<<EncBlock:BlockSize/binary, EncryptedRest/binary>> = EncryptedBuffer,
{Ssh,
<<?UINT32(PacketLen),_/binary>> = Decrypted} = decrypt(Ssh0, EncBlock),
- {ok, PacketLen, Decrypted, EncryptedRest, Ssh};
+ {ok, PacketLen, Decrypted, EncryptedRest, <<>>, Ssh};
false ->
get_more
end;
+
get_length(aead, EncryptedBuffer, Ssh) ->
- case size(EncryptedBuffer) >= 4 of
- true ->
+ case {size(EncryptedBuffer) >= 4, Ssh#ssh.decrypt} of
+ {true, '[email protected]'} ->
+ <<EncryptedLen:4/binary, EncryptedRest/binary>> = EncryptedBuffer,
+ {Ssh1, PacketLenBin} = decrypt(Ssh, {length,EncryptedLen}),
+ <<?UINT32(PacketLen)>> = PacketLenBin,
+ {ok, PacketLen, PacketLenBin, EncryptedRest, EncryptedLen, Ssh1};
+ {true, _} ->
<<?UINT32(PacketLen), EncryptedRest/binary>> = EncryptedBuffer,
- {ok, PacketLen, <<?UINT32(PacketLen)>>, EncryptedRest, Ssh};
- false ->
+ {ok, PacketLen, <<?UINT32(PacketLen)>>, EncryptedRest, <<?UINT32(PacketLen)>>, Ssh};
+ {false, _} ->
get_more
end.
+
pkt_type('AEAD_AES_128_GCM') -> aead;
pkt_type('AEAD_AES_256_GCM') -> aead;
+pkt_type('[email protected]') -> aead;
pkt_type(_) -> common.
payload(<<PacketLen:32, PaddingLen:8, PayloadAndPadding/binary>>) ->
@@ -1208,10 +1261,12 @@ payload(<<PacketLen:32, PaddingLen:8, PayloadAndPadding/binary>>) ->
<<Payload:PayloadLen/binary, _/binary>> = PayloadAndPadding,
Payload.
+sign(SigData, HashAlg, #{algorithm:=dss} = Key) ->
+ mk_dss_sig(crypto:sign(dss, HashAlg, SigData, Key));
+sign(SigData, HashAlg, #{algorithm:=SigAlg} = Key) ->
+ crypto:sign(SigAlg, HashAlg, SigData, Key);
sign(SigData, HashAlg, #'DSAPrivateKey'{} = Key) ->
- DerSignature = public_key:sign(SigData, HashAlg, Key),
- #'Dss-Sig-Value'{r = R, s = S} = public_key:der_decode('Dss-Sig-Value', DerSignature),
- <<R:160/big-unsigned-integer, S:160/big-unsigned-integer>>;
+ mk_dss_sig(public_key:sign(SigData, HashAlg, Key));
sign(SigData, HashAlg, Key = #'ECPrivateKey'{}) ->
DerEncodedSign = public_key:sign(SigData, HashAlg, Key),
#'ECDSA-Sig-Value'{r=R, s=S} = public_key:der_decode('ECDSA-Sig-Value', DerEncodedSign),
@@ -1219,7 +1274,13 @@ sign(SigData, HashAlg, Key = #'ECPrivateKey'{}) ->
sign(SigData, HashAlg, Key) ->
public_key:sign(SigData, HashAlg, Key).
-verify(PlainText, HashAlg, Sig, {_, #'Dss-Parms'{}} = Key) ->
+
+mk_dss_sig(DerSignature) ->
+ #'Dss-Sig-Value'{r = R, s = S} = public_key:der_decode('Dss-Sig-Value', DerSignature),
+ <<R:160/big-unsigned-integer, S:160/big-unsigned-integer>>.
+
+
+verify(PlainText, HashAlg, Sig, {_, #'Dss-Parms'{}} = Key, _) ->
case Sig of
<<R:160/big-unsigned-integer, S:160/big-unsigned-integer>> ->
Signature = public_key:der_encode('Dss-Sig-Value', #'Dss-Sig-Value'{r = R, s = S}),
@@ -1227,7 +1288,7 @@ verify(PlainText, HashAlg, Sig, {_, #'Dss-Parms'{}} = Key) ->
_ ->
false
end;
-verify(PlainText, HashAlg, Sig, {#'ECPoint'{},_} = Key) ->
+verify(PlainText, HashAlg, Sig, {#'ECPoint'{},_} = Key, _) ->
case Sig of
<<?UINT32(Rlen),R:Rlen/big-signed-integer-unit:8,
?UINT32(Slen),S:Slen/big-signed-integer-unit:8>> ->
@@ -1237,7 +1298,15 @@ verify(PlainText, HashAlg, Sig, {#'ECPoint'{},_} = Key) ->
_ ->
false
end;
-verify(PlainText, HashAlg, Sig, Key) ->
+
+verify(PlainText, HashAlg, Sig, #'RSAPublicKey'{}=Key, #ssh{role = server,
+ c_version = "SSH-2.0-OpenSSH_7."++_})
+ when HashAlg == sha256; HashAlg == sha512 ->
+ %% Public key signing bug in in OpenSSH >= 7.2
+ public_key:verify(PlainText, HashAlg, Sig, Key)
+ orelse public_key:verify(PlainText, sha, Sig, Key);
+
+verify(PlainText, HashAlg, Sig, Key, _) ->
public_key:verify(PlainText, HashAlg, Sig, Key).
@@ -1289,11 +1358,32 @@ cipher('aes192-ctr') ->
cipher('aes256-ctr') ->
#cipher_data{key_bytes = 32,
iv_bytes = 16,
- block_bytes = 16}.
+ block_bytes = 16};
+
+cipher('[email protected]') -> % FIXME: Verify!!
+ #cipher_data{key_bytes = 32,
+ iv_bytes = 12,
+ block_bytes = 8}.
+
encrypt_init(#ssh{encrypt = none} = Ssh) ->
{ok, Ssh};
+encrypt_init(#ssh{encrypt = '[email protected]', role = client} = Ssh) ->
+ %% [email protected] uses two independent crypto streams, one (chacha20)
+ %% for the length used in stream mode, and the other (chacha20-poly1305) as AEAD for
+ %% the payload and to MAC the length||payload.
+ %% See draft-josefsson-ssh-chacha20-poly1305-openssh-00
+ <<K2:32/binary,K1:32/binary>> = hash(Ssh, "C", 512),
+ {ok, Ssh#ssh{encrypt_keys = {K1,K2}
+ % encrypt_block_size = 16, %default = 8. What to set it to? 64 (openssl chacha.h)
+ % ctx and iv is setup for each packet
+ }};
+encrypt_init(#ssh{encrypt = '[email protected]', role = server} = Ssh) ->
+ <<K2:32/binary,K1:32/binary>> = hash(Ssh, "D", 512),
+ {ok, Ssh#ssh{encrypt_keys = {K1,K2}
+ % encrypt_block_size = 16, %default = 8. What to set it to?
+ }};
encrypt_init(#ssh{encrypt = 'AEAD_AES_128_GCM', role = client} = Ssh) ->
IV = hash(Ssh, "A", 12*8),
<<K:16/binary>> = hash(Ssh, "C", 128),
@@ -1394,18 +1484,40 @@ encrypt_final(Ssh) ->
encrypt(#ssh{encrypt = none} = Ssh, Data) ->
{Ssh, Data};
+encrypt(#ssh{encrypt = '[email protected]',
+ encrypt_keys = {K1,K2},
+ send_sequence = Seq} = Ssh,
+ <<LenData:4/binary, PayloadData/binary>>) ->
+ %% Encrypt length
+ IV1 = <<0:8/unit:8, Seq:8/unit:8>>,
+ {_,EncLen} = crypto:stream_encrypt(crypto:stream_init(chacha20, K1, IV1),
+ LenData),
+ %% Encrypt payload
+ IV2 = <<1:8/little-unit:8, Seq:8/unit:8>>,
+ {_,EncPayloadData} = crypto:stream_encrypt(crypto:stream_init(chacha20, K2, IV2),
+ PayloadData),
+
+ %% MAC tag
+ {_,PolyKey} = crypto:stream_encrypt(crypto:stream_init(chacha20, K2, <<0:8/unit:8,Seq:8/unit:8>>),
+ <<0:32/unit:8>>),
+ EncBytes = <<EncLen/binary,EncPayloadData/binary>>,
+ Ctag = crypto:poly1305(PolyKey, EncBytes),
+ %% Result
+ {Ssh, {EncBytes,Ctag}};
encrypt(#ssh{encrypt = 'AEAD_AES_128_GCM',
encrypt_keys = K,
- encrypt_ctx = IV0} = Ssh, Data={_AAD,_Ptext}) ->
- Enc = {_Ctext,_Ctag} = crypto:block_encrypt(aes_gcm, K, IV0, Data),
+ encrypt_ctx = IV0} = Ssh,
+ <<LenData:4/binary, PayloadData/binary>>) ->
+ {Ctext,Ctag} = crypto:block_encrypt(aes_gcm, K, IV0, {LenData,PayloadData}),
IV = next_gcm_iv(IV0),
- {Ssh#ssh{encrypt_ctx = IV}, Enc};
+ {Ssh#ssh{encrypt_ctx = IV}, {<<LenData/binary,Ctext/binary>>,Ctag}};
encrypt(#ssh{encrypt = 'AEAD_AES_256_GCM',
encrypt_keys = K,
- encrypt_ctx = IV0} = Ssh, Data={_AAD,_Ptext}) ->
- Enc = {_Ctext,_Ctag} = crypto:block_encrypt(aes_gcm, K, IV0, Data),
+ encrypt_ctx = IV0} = Ssh,
+ <<LenData:4/binary, PayloadData/binary>>) ->
+ {Ctext,Ctag} = crypto:block_encrypt(aes_gcm, K, IV0, {LenData,PayloadData}),
IV = next_gcm_iv(IV0),
- {Ssh#ssh{encrypt_ctx = IV}, Enc};
+ {Ssh#ssh{encrypt_ctx = IV}, {<<LenData/binary,Ctext/binary>>,Ctag}};
encrypt(#ssh{encrypt = '3des-cbc',
encrypt_keys = {K1,K2,K3},
encrypt_ctx = IV0} = Ssh, Data) ->
@@ -1438,6 +1550,14 @@ encrypt(#ssh{encrypt = 'aes256-ctr',
decrypt_init(#ssh{decrypt = none} = Ssh) ->
{ok, Ssh};
+decrypt_init(#ssh{decrypt = '[email protected]', role = client} = Ssh) ->
+ <<K2:32/binary,K1:32/binary>> = hash(Ssh, "D", 512),
+ {ok, Ssh#ssh{decrypt_keys = {K1,K2}
+ }};
+decrypt_init(#ssh{decrypt = '[email protected]', role = server} = Ssh) ->
+ <<K2:32/binary,K1:32/binary>> = hash(Ssh, "C", 512),
+ {ok, Ssh#ssh{decrypt_keys = {K1,K2}
+ }};
decrypt_init(#ssh{decrypt = 'AEAD_AES_128_GCM', role = client} = Ssh) ->
IV = hash(Ssh, "B", 12*8),
<<K:16/binary>> = hash(Ssh, "D", 128),
@@ -1538,6 +1658,31 @@ decrypt_final(Ssh) ->
decrypt(Ssh, <<>>) ->
{Ssh, <<>>};
+decrypt(#ssh{decrypt = '[email protected]',
+ decrypt_keys = {K1,_K2},
+ recv_sequence = Seq} = Ssh, {length,EncryptedLen}) ->
+ {_State,PacketLenBin} =
+ crypto:stream_decrypt(crypto:stream_init(chacha20, K1, <<0:8/unit:8, Seq:8/unit:8>>),
+ EncryptedLen),
+ {Ssh, PacketLenBin};
+decrypt(#ssh{decrypt = '[email protected]',
+ decrypt_keys = {_K1,K2},
+ recv_sequence = Seq} = Ssh, {AAD,Ctext,Ctag}) ->
+ %% The length is already decoded and used to divide the input
+ %% Check the mac (important that it is timing-safe):
+ {_,PolyKey} =
+ crypto:stream_encrypt(crypto:stream_init(chacha20, K2, <<0:8/unit:8,Seq:8/unit:8>>),
+ <<0:32/unit:8>>),
+ case equal_const_time(Ctag, crypto:poly1305(PolyKey, <<AAD/binary,Ctext/binary>>)) of
+ true ->
+ %% MAC is ok, decode
+ IV2 = <<1:8/little-unit:8, Seq:8/unit:8>>,
+ {_,PlainText} =
+ crypto:stream_decrypt(crypto:stream_init(chacha20,K2,IV2), Ctext),
+ {Ssh, PlainText};
+ false ->
+ {Ssh,error}
+ end;
decrypt(#ssh{decrypt = none} = Ssh, Data) ->
{Ssh, Data};
decrypt(#ssh{decrypt = 'AEAD_AES_128_GCM',
@@ -1680,7 +1825,7 @@ send_mac_init(SSH) ->
Key = hash(SSH, "F", KeySize),
{ok, SSH#ssh { send_mac_key = Key }}
end;
- aead ->
+ _ ->
%% Not applicable
{ok, SSH}
end.
@@ -1701,7 +1846,7 @@ recv_mac_init(SSH) ->
Key = hash(SSH, "E", 8*mac_key_bytes(SSH#ssh.recv_mac)),
{ok, SSH#ssh { recv_mac_key = Key }}
end;
- aead ->
+ _ ->
%% Not applicable
{ok, SSH}
end.
@@ -1730,7 +1875,7 @@ mac('hmac-sha2-512', Key, SeqNum, Data) ->
hash(_SSH, _Char, 0) ->
<<>>;
hash(SSH, Char, N) ->
- HashAlg = sha(SSH#ssh.kex),
+ HashAlg = sha(SSH#ssh.algorithms#alg.kex),
K = SSH#ssh.shared_secret,
H = SSH#ssh.exchanged_hash,
K1 = crypto:hash(HashAlg, [K, H, Char, SSH#ssh.session_id]),
@@ -1745,23 +1890,30 @@ hash(K, H, Ki, N, HashAlg) ->
hash(K, H, <<Ki/binary, Kj/binary>>, N-128, HashAlg).
%%%----------------------------------------------------------------
-kex_hash(SSH, Key, SignAlg, HashAlg, Args) ->
- crypto:hash(HashAlg, kex_plaintext(SSH,Key,SignAlg,Args)).
+kex_hash(SSH, Key, HashAlg, Args) ->
+ crypto:hash(HashAlg, kex_plaintext(SSH,Key,Args)).
+
-kex_plaintext(SSH, Key, SignAlg, Args) ->
- EncodedKey = public_key:ssh_encode({Key,SignAlg}, ssh2_pubkey),
+kex_plaintext(SSH, Key, Args) ->
+ EncodedKey = public_key:ssh_encode(Key, ssh2_pubkey),
<<?Estring(SSH#ssh.c_version), ?Estring(SSH#ssh.s_version),
?Ebinary(SSH#ssh.c_keyinit), ?Ebinary(SSH#ssh.s_keyinit),
?Ebinary(EncodedKey),
(kex_alg_dependent(Args))/binary>>.
+
+kex_alg_dependent({Q_c, Q_s, K}) when is_binary(Q_c), is_binary(Q_s) ->
+ %% ecdh
+ <<?Ebinary(Q_c), ?Ebinary(Q_s), ?Empint(K)>>;
+
kex_alg_dependent({E, F, K}) ->
- %% diffie-hellman and ec diffie-hellman (with E = Q_c, F = Q_s)
+ %% diffie-hellman
<<?Empint(E), ?Empint(F), ?Empint(K)>>;
-kex_alg_dependent({-1, _, -1, _, _, E, F, K}) ->
+kex_alg_dependent({-1, NBits, -1, Prime, Gen, E, F, K}) ->
%% ssh_msg_kex_dh_gex_request_old
- <<?Empint(E), ?Empint(F), ?Empint(K)>>;
+ <<?Euint32(NBits),
+ ?Empint(Prime), ?Empint(Gen), ?Empint(E), ?Empint(F), ?Empint(K)>>;
kex_alg_dependent({Min, NBits, Max, Prime, Gen, E, F, K}) ->
%% diffie-hellman group exchange
@@ -1770,6 +1922,8 @@ kex_alg_dependent({Min, NBits, Max, Prime, Gen, E, F, K}) ->
%%%----------------------------------------------------------------
+valid_key_sha_alg(#{engine:=_, key_id:=_}, _Alg) -> true; % Engine key
+
valid_key_sha_alg(#'RSAPublicKey'{}, 'rsa-sha2-512') -> true;
valid_key_sha_alg(#'RSAPublicKey'{}, 'rsa-sha2-384') -> true;
valid_key_sha_alg(#'RSAPublicKey'{}, 'rsa-sha2-256') -> true;
@@ -1783,11 +1937,14 @@ valid_key_sha_alg(#'RSAPrivateKey'{}, 'ssh-rsa' ) -> true;
valid_key_sha_alg({_, #'Dss-Parms'{}}, 'ssh-dss') -> true;
valid_key_sha_alg(#'DSAPrivateKey'{}, 'ssh-dss') -> true;
-valid_key_sha_alg({#'ECPoint'{},{namedCurve,OID}}, Alg) -> sha(OID) == sha(Alg);
-valid_key_sha_alg(#'ECPrivateKey'{parameters = {namedCurve,OID}}, Alg) -> sha(OID) == sha(Alg);
+valid_key_sha_alg({#'ECPoint'{},{namedCurve,OID}}, Alg) -> valid_key_sha_alg_ec(OID, Alg);
+valid_key_sha_alg(#'ECPrivateKey'{parameters = {namedCurve,OID}}, Alg) -> valid_key_sha_alg_ec(OID, Alg);
valid_key_sha_alg(_, _) -> false.
-
+valid_key_sha_alg_ec(OID, Alg) ->
+ Curve = public_key:oid2ssh_curvename(OID),
+ Alg == list_to_atom("ecdsa-sha2-" ++ binary_to_list(Curve)).
+
public_algo(#'RSAPublicKey'{}) -> 'ssh-rsa'; % FIXME: Not right with draft-curdle-rsa-sha2
public_algo({_, #'Dss-Parms'{}}) -> 'ssh-dss';
@@ -1795,9 +1952,6 @@ public_algo({#'ECPoint'{},{namedCurve,OID}}) ->
Curve = public_key:oid2ssh_curvename(OID),
list_to_atom("ecdsa-sha2-" ++ binary_to_list(Curve)).
-
-
-
sha('ssh-rsa') -> sha;
sha('rsa-sha2-256') -> sha256;
sha('rsa-sha2-384') -> sha384;
@@ -1822,6 +1976,11 @@ sha(?'secp521r1') -> sha(secp521r1);
sha('ecdh-sha2-nistp256') -> sha(secp256r1);
sha('ecdh-sha2-nistp384') -> sha(secp384r1);
sha('ecdh-sha2-nistp521') -> sha(secp521r1);
+sha('curve25519-sha256' ) -> sha256;
+sha('[email protected]' ) -> sha256;
+sha('curve448-sha512') -> sha512;
+sha(x25519) -> sha256;
+sha(x448) -> sha512;
sha(Str) when is_list(Str), length(Str)<50 -> sha(list_to_atom(Str)).
@@ -1833,6 +1992,7 @@ mac_key_bytes('hmac-sha2-256')-> 32;
mac_key_bytes('hmac-sha2-512')-> 64;
mac_key_bytes('AEAD_AES_128_GCM') -> 0;
mac_key_bytes('AEAD_AES_256_GCM') -> 0;
+mac_key_bytes('[email protected]') -> 0;
mac_key_bytes(none) -> 0.
mac_digest_size('hmac-sha1') -> 20;
@@ -1843,6 +2003,7 @@ mac_digest_size('hmac-sha2-256') -> 32;
mac_digest_size('hmac-sha2-512') -> 64;
mac_digest_size('AEAD_AES_128_GCM') -> 16;
mac_digest_size('AEAD_AES_256_GCM') -> 16;
+mac_digest_size('[email protected]') -> 16;
mac_digest_size(none) -> 0.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1865,11 +2026,13 @@ parallell_gen_key(Ssh = #ssh{keyex_key = {x, {G, P}},
Ssh#ssh{keyex_key = {{Private, Public}, {G, P}}}.
+generate_key(ecdh = Algorithm, Args) ->
+ crypto:generate_key(Algorithm, Args);
generate_key(Algorithm, Args) ->
{Public,Private} = crypto:generate_key(Algorithm, Args),
{crypto:bytes_to_integer(Public), crypto:bytes_to_integer(Private)}.
-
+
compute_key(Algorithm, OthersPublic, MyPrivate, Args) ->
Shared = crypto:compute_key(Algorithm, OthersPublic, MyPrivate, Args),
crypto:bytes_to_integer(Shared).
@@ -1886,7 +2049,10 @@ dh_bits(#alg{encrypt = Encrypt,
ecdh_curve('ecdh-sha2-nistp256') -> secp256r1;
ecdh_curve('ecdh-sha2-nistp384') -> secp384r1;
-ecdh_curve('ecdh-sha2-nistp521') -> secp521r1.
+ecdh_curve('ecdh-sha2-nistp521') -> secp521r1;
+ecdh_curve('curve448-sha512' ) -> x448;
+ecdh_curve('curve25519-sha256' ) -> x25519;
+ecdh_curve('[email protected]' ) -> x25519.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1903,15 +2069,10 @@ supported_algorithms(Key, BlackList) ->
select_crypto_supported(L) ->
- Sup = [{ec_curve,crypto_supported_curves()} | crypto:supports()],
+ Sup = crypto:supports(),
[Name || {Name,CryptoRequires} <- L,
crypto_supported(CryptoRequires, Sup)].
-crypto_supported_curves() ->
- try crypto:ec_curves()
- catch _:_ -> []
- end.
-
crypto_supported(Conditions, Supported) ->
lists:all( fun({Tag,CryptoName}) when is_atom(CryptoName) ->
crypto_name_supported(Tag,CryptoName,Supported);
@@ -1921,7 +2082,11 @@ crypto_supported(Conditions, Supported) ->
end, Conditions).
crypto_name_supported(Tag, CryptoName, Supported) ->
- lists:member(CryptoName, proplists:get_value(Tag,Supported,[])).
+ Vs = case proplists:get_value(Tag,Supported,[]) of
+ [] when Tag == curves -> crypto:ec_curves();
+ L -> L
+ end,
+ lists:member(CryptoName, Vs).
len_supported(Name, Len) ->
try
@@ -1952,13 +2117,58 @@ same(Algs) -> [{client2server,Algs}, {server2client,Algs}].
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-trim_tail(Str) ->
- lists:reverse(trim_head(lists:reverse(Str))).
+%%% Compare two binaries in a timing safe maner.
+%%% The time spent in comparing should not be different depending on where in the binaries they differ.
+%%% This is to avoid a certain side-channel attac.
+equal_const_time(X1, X2) -> equal_const_time(X1, X2, true).
-trim_head([$\s|Cs]) -> trim_head(Cs);
-trim_head([$\t|Cs]) -> trim_head(Cs);
-trim_head([$\n|Cs]) -> trim_head(Cs);
-trim_head([$\r|Cs]) -> trim_head(Cs);
-trim_head(Cs) -> Cs.
+equal_const_time(<<B1,R1/binary>>, <<B2,R2/binary>>, Truth) ->
+ equal_const_time(R1, R2, Truth and (B1 == B2));
+equal_const_time(<<>>, <<>>, Truth) ->
+ Truth;
+equal_const_time(_, _, _) ->
+ false.
+%%%-------- Remove CR, LF and following characters from a line
+trim_tail(Str) ->
+ lists:takewhile(fun(C) ->
+ C=/=$\r andalso C=/=$\n
+ end, Str).
+
+%%%################################################################
+%%%#
+%%%# Tracing
+%%%#
+
+dbg_trace(points, _, _) -> [alg, ssh_messages, raw_messages, hello];
+
+dbg_trace(flags, hello, _) -> [c];
+dbg_trace(on, hello, _) -> dbg:tp(?MODULE,hello_version_msg,1,x),
+ dbg:tp(?MODULE,handle_hello_version,1,x);
+dbg_trace(off, hello, _) -> dbg:ctpg(?MODULE,hello_version_msg,1),
+ dbg:ctpg(?MODULE,handle_hello_version,1);
+
+dbg_trace(C, raw_messages, A) -> dbg_trace(C, hello, A);
+dbg_trace(C, ssh_messages, A) -> dbg_trace(C, hello, A);
+
+dbg_trace(flags, alg, _) -> [c];
+dbg_trace(on, alg, _) -> dbg:tpl(?MODULE,select_algorithm,4,x);
+dbg_trace(off, alg, _) -> dbg:ctpl(?MODULE,select_algorithm,4);
+
+
+dbg_trace(format, hello, {return_from,{?MODULE,hello_version_msg,1},Hello}) ->
+ ["Going to send hello message:\n",
+ Hello
+ ];
+dbg_trace(format, hello, {call,{?MODULE,handle_hello_version,[Hello]}}) ->
+ ["Received hello message:\n",
+ Hello
+ ];
+
+dbg_trace(format, alg, {return_from,{?MODULE,select_algorithm,4},{ok,Alg}}) ->
+ ["Negotiated algorithms:\n",
+ wr_record(Alg)
+ ].
+
+?wr_record(alg).
diff --git a/lib/ssh/src/ssh_transport.hrl b/lib/ssh/src/ssh_transport.hrl
index 87c3719514..f424a4ff63 100644
--- a/lib/ssh/src/ssh_transport.hrl
+++ b/lib/ssh/src/ssh_transport.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -220,6 +220,9 @@
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-define(DISCONNECT(Code, DetailedText),
+ ssh_connection_handler:disconnect(Code, DetailedText, ?MODULE, ?LINE)).
+
-define(SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT, 1).
-define(SSH_DISCONNECT_PROTOCOL_ERROR, 2).
-define(SSH_DISCONNECT_KEY_EXCHANGE_FAILED, 3).
diff --git a/lib/ssh/src/ssh_xfer.erl b/lib/ssh/src/ssh_xfer.erl
index e1680c120e..1d77ccb311 100644
--- a/lib/ssh/src/ssh_xfer.erl
+++ b/lib/ssh/src/ssh_xfer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -734,7 +734,7 @@ decode_ATTR(Vsn, <<?UINT32(Flags), Tail/binary>>) ->
{Type,Tail2} =
if Vsn =< 3 ->
{?SSH_FILEXFER_TYPE_UNKNOWN, Tail};
- Vsn >= 5 ->
+ true ->
<<?BYTE(T), TL/binary>> = Tail,
{T, TL}
end,
diff --git a/lib/ssh/src/sshc_sup.erl b/lib/ssh/src/sshc_sup.erl
index 133b2c6450..869de244ac 100644
--- a/lib/ssh/src/sshc_sup.erl
+++ b/lib/ssh/src/sshc_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@
-behaviour(supervisor).
--export([start_link/0, start_child/1, stop_child/1]).
+-export([start_link/0, start_child/1]).
%% Supervisor callback
-export([init/1]).
@@ -43,13 +43,6 @@ start_link() ->
start_child(Args) ->
supervisor:start_child(?MODULE, Args).
-stop_child(Client) ->
- spawn(fun() ->
- ClientSup = whereis(?SSHC_SUP),
- supervisor:terminate_child(ClientSup, Client)
- end),
- ok.
-
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
@@ -60,10 +53,7 @@ init(_) ->
},
ChildSpecs = [#{id => undefined, % As simple_one_for_one is used.
start => {ssh_connection_handler, start_link, []},
- restart => temporary,
- shutdown => 4000,
- type => worker,
- modules => [ssh_connection_handler]
+ restart => temporary % because there is no way to restart a crashed connection
}
],
{ok, {SupFlags,ChildSpecs}}.
diff --git a/lib/ssh/src/sshd_sup.erl b/lib/ssh/src/sshd_sup.erl
index c23e65d955..b5361abba5 100644
--- a/lib/ssh/src/sshd_sup.erl
+++ b/lib/ssh/src/sshd_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -90,10 +90,8 @@ init(_) ->
child_spec(Address, Port, Profile, Options) ->
#{id => id(Address, Port, Profile),
start => {ssh_system_sup, start_link, [Address, Port, Profile, Options]},
- restart => temporary,
- shutdown => infinity,
- type => supervisor,
- modules => [ssh_system_sup]
+ restart => temporary,
+ type => supervisor
}.
id(Address, Port, Profile) ->
diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile
index 32e76cf077..e221e94075 100644
--- a/lib/ssh/test/Makefile
+++ b/lib/ssh/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2017. All Rights Reserved.
+# Copyright Ericsson AB 2004-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -34,11 +34,15 @@ VSN=$(GS_VSN)
MODULES= \
ssh_algorithms_SUITE \
ssh_options_SUITE \
- ssh_renegotiate_SUITE \
ssh_basic_SUITE \
ssh_bench_SUITE \
+ ssh_chan_behaviours_SUITE \
+ ssh_compat_SUITE \
ssh_connection_SUITE \
+ ssh_dbg_SUITE \
+ ssh_engine_SUITE \
ssh_protocol_SUITE \
+ ssh_property_test_SUITE \
ssh_sftp_SUITE \
ssh_sftpd_SUITE \
ssh_sftpd_erlclient_SUITE \
@@ -48,7 +52,10 @@ MODULES= \
ssh_test_lib \
ssh_key_cb \
ssh_key_cb_options \
+ ssh_key_cb_engine_keys \
ssh_trpt_test_lib \
+ ssh_chan_behaviours_client \
+ ssh_chan_behaviours_server \
ssh_echo_server \
ssh_bench_dev_null \
ssh_peername_sockname_server \
@@ -132,6 +139,6 @@ release_tests_spec: opt
$(INSTALL_DATA) ssh.spec ssh_bench.spec ssh.cover "$(RELSYSDIR)"
$(INSTALL_DATA) $(HRL_FILES_NEEDED_IN_TEST) "$(RELSYSDIR)"
chmod -R u+w "$(RELSYSDIR)"
- @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
+ @tar cf - *_SUITE_data property_test | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/lib/ssh/test/property_test/ssh_eqc_client_info_timing.erl b/lib/ssh/test/property_test/ssh_eqc_client_info_timing.erl
index c07140dc43..6d0d8f5d99 100644
--- a/lib/ssh/test/property_test/ssh_eqc_client_info_timing.erl
+++ b/lib/ssh/test/property_test/ssh_eqc_client_info_timing.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -57,9 +57,9 @@
%%% Properties:
-prop_seq(_Config) ->
+prop_seq(Config) ->
{ok,Pid} = ssh_eqc_event_handler:add_report_handler(),
- {_, _, Port} = init_daemon(),
+ {_, _, Port} = init_daemon(Config),
numtests(1000,
?FORALL(Delay, choose(0,100),%% Micro seconds
try
@@ -86,7 +86,8 @@ any_relevant_error_report(Pid) ->
end, Reports).
%%%================================================================
-init_daemon() ->
+init_daemon(Config) ->
ok = begin ssh:stop(), ssh:start() end,
- ssh_test_lib:daemon([]).
+ DataDir = proplists:get_value(data_dir, Config),
+ ssh_test_lib:daemon([{system_dir,DataDir}]).
diff --git a/lib/ssh/test/property_test/ssh_eqc_subsys.erl b/lib/ssh/test/property_test/ssh_eqc_subsys.erl
index 30b254b9c0..087b3ebfa7 100644
--- a/lib/ssh/test/property_test/ssh_eqc_subsys.erl
+++ b/lib/ssh/test/property_test/ssh_eqc_subsys.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
-module(ssh_eqc_subsys).
--behaviour(ssh_daemon_channel).
+-behaviour(ssh_server_channel).
-export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]).
diff --git a/lib/ssh/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl
index 98964a2c8a..5e589e585f 100644
--- a/lib/ssh/test/ssh_algorithms_SUITE.erl
+++ b/lib/ssh/test/ssh_algorithms_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,15 +29,13 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
--define(TIMEOUT, 35000).
-
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
suite() ->
[{ct_hooks,[ts_install_cth]},
- {timetrap,{seconds,40}}].
+ {timetrap,{seconds,60}}].
all() ->
%% [{group,kex},{group,cipher}... etc
@@ -90,7 +88,7 @@ init_per_suite(Config) ->
" -- Max num algorithms: ~p~n"
,[os:getenv("HOME"),
init:get_argument(home),
- os:cmd("ssh -V"),
+ ssh_test_lib:installed_ssh_version("TIMEOUT"),
ssh:default_algorithms(),
crypto:info_lib(),
ssh_test_lib:default_algorithms(sshc),
@@ -102,7 +100,7 @@ init_per_suite(Config) ->
ct:log("all() ->~n ~p.~n~ngroups()->~n ~p.~n",[all(),groups()]),
ssh:start(),
[{std_simple_sftp_size,25000} % Sftp transferred data size
- | setup_pubkey(Config)]
+ | Config]
end
).
@@ -259,15 +257,14 @@ try_exec_simple_group(Group, Config) ->
of
_ -> ct:fail("Exec though no group available")
catch
- error:{badmatch,{error,"No possible diffie-hellman-group-exchange group found"}} -> ok;
- error:{badmatch,{error,"Connection closed"}} -> ok
+ error:{badmatch,{error,"Key exchange failed"}} -> ok
end.
%%--------------------------------------------------------------------
%% Testing all default groups
simple_exec_groups() ->
- [{timetrap,{seconds,120}}].
+ [{timetrap,{seconds,180}}].
simple_exec_groups(Config) ->
Sizes = interpolate( public_key:dh_gex_group_sizes() ),
@@ -318,10 +315,10 @@ sshc_simple_exec_os_cmd(Config) ->
ok;
false ->
ct:log("Bad result: ~p~nExpected: ~p~nMangled result: ~p", [RawResult,Expect,Lines]),
- {fail, "Bad result"}
+ {fail, "Bad result (see log in testcase)"}
end
after ?TIMEOUT ->
- ct:fail("Did not receive answer")
+ ct:fail("Did not receive answer (timeout)")
end.
%%--------------------------------------------------------------------
@@ -462,17 +459,6 @@ pubkey_opts(Config) ->
{system_dir, SystemDir}].
-setup_pubkey(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- UserDir = proplists:get_value(priv_dir, Config),
- Keys =
- [ssh_test_lib:setup_dsa(DataDir, UserDir),
- ssh_test_lib:setup_rsa(DataDir, UserDir),
- ssh_test_lib:setup_ecdsa("256", DataDir, UserDir)
- ],
- ssh_test_lib:write_auth_keys(Keys, UserDir), % 'authorized_keys' shall contain ALL pub keys
- Config.
-
setup_pubkey(Alg, Config) ->
DataDir = proplists:get_value(data_dir, Config),
UserDir = proplists:get_value(priv_dir, Config),
diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
index 62e2a585e4..778ae1e7b6 100644
--- a/lib/ssh/test/ssh_basic_SUITE.erl
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,59 +28,12 @@
-include("ssh_test_lib.hrl").
%% Note: This directive should only be used in test suites.
-%%-compile(export_all).
-
-%%% Test cases
--export([
- app_test/1,
- appup_test/1,
- cli/1,
- close/1,
- daemon_already_started/1,
- daemon_opt_fd/1,
- multi_daemon_opt_fd/1,
- double_close/1,
- exec/1,
- exec_compressed/1,
- exec_key_differs1/1,
- exec_key_differs2/1,
- exec_key_differs3/1,
- exec_key_differs_fail/1,
- idle_time_client/1,
- idle_time_server/1,
- inet6_option/1,
- inet_option/1,
- internal_error/1,
- known_hosts/1,
- login_bad_pwd_no_retry1/1,
- login_bad_pwd_no_retry2/1,
- login_bad_pwd_no_retry3/1,
- login_bad_pwd_no_retry4/1,
- login_bad_pwd_no_retry5/1,
- misc_ssh_options/1,
- openssh_zlib_basic_test/1,
- packet_size_zero/1,
- pass_phrase/1,
- peername_sockname/1,
- send/1,
- shell/1,
- shell_no_unicode/1,
- shell_unicode_string/1,
- ssh_info_print/1,
- key_callback/1,
- key_callback_options/1,
- shell_exit_status/1
- ]).
-
-%%% Common test callbacks
--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
- ]).
+-compile(export_all).
-define(NEWLINE, <<"\r\n">>).
+-define(REKEY_DATA_TMO, 1 * 60000). % Should be multiples of 60000
+
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
@@ -90,68 +43,105 @@ suite() ->
{timetrap,{seconds,40}}].
all() ->
- [app_test,
- appup_test,
- {group, dsa_key},
- {group, rsa_key},
- {group, ecdsa_sha2_nistp256_key},
- {group, ecdsa_sha2_nistp384_key},
- {group, ecdsa_sha2_nistp521_key},
- {group, dsa_pass_key},
- {group, rsa_pass_key},
- {group, host_user_key_differs},
- {group, key_cb},
- {group, internal_error},
- daemon_already_started,
- double_close,
- daemon_opt_fd,
- multi_daemon_opt_fd,
- packet_size_zero,
- ssh_info_print,
- {group, login_bad_pwd_no_retry},
- shell_exit_status
- ].
+ [{group, all_tests}].
groups() ->
- [{dsa_key, [], basic_tests()},
- {rsa_key, [], basic_tests()},
- {ecdsa_sha2_nistp256_key, [], basic_tests()},
- {ecdsa_sha2_nistp384_key, [], basic_tests()},
- {ecdsa_sha2_nistp521_key, [], basic_tests()},
- {host_user_key_differs, [], [exec_key_differs1,
- exec_key_differs2,
- exec_key_differs3,
- exec_key_differs_fail]},
+ [{all_tests, [parallel], [{group, ssh_renegotiate_SUITE},
+ {group, ssh_basic_SUITE}
+ ]},
+ {ssh_basic_SUITE, [], [app_test,
+ appup_test,
+ {group, dsa_key},
+ {group, rsa_key},
+ {group, ecdsa_sha2_nistp256_key},
+ {group, ecdsa_sha2_nistp384_key},
+ {group, ecdsa_sha2_nistp521_key},
+ {group, dsa_pass_key},
+ {group, rsa_pass_key},
+ {group, ecdsa_sha2_nistp256_pass_key},
+ {group, ecdsa_sha2_nistp384_pass_key},
+ {group, ecdsa_sha2_nistp521_pass_key},
+ {group, host_user_key_differs},
+ {group, key_cb},
+ {group, internal_error},
+ {group, rsa_host_key_is_actualy_ecdsa},
+ daemon_already_started,
+ double_close,
+ daemon_opt_fd,
+ multi_daemon_opt_fd,
+ packet_size,
+ ssh_info_print,
+ {group, login_bad_pwd_no_retry},
+ shell_exit_status
+ ]},
+
+ {ssh_renegotiate_SUITE, [parallel], [rekey0,
+ rekey1,
+ rekey2,
+ rekey3,
+ rekey4,
+ rekey_limit_client,
+ rekey_limit_daemon,
+ rekey_time_limit_client,
+ rekey_time_limit_daemon,
+ norekey_limit_client,
+ norekey_limit_daemon,
+ renegotiate1,
+ renegotiate2]},
+
+ {dsa_key, [], [{group, basic}]},
+ {rsa_key, [], [{group, basic}]},
+ {ecdsa_sha2_nistp256_key, [], [{group, basic}]},
+ {ecdsa_sha2_nistp384_key, [], [{group, basic}]},
+ {ecdsa_sha2_nistp521_key, [], [{group, basic}]},
+ {rsa_host_key_is_actualy_ecdsa, [], [fail_daemon_start]},
+ {host_user_key_differs, [parallel], [exec_key_differs1,
+ exec_key_differs2,
+ exec_key_differs3,
+ exec_key_differs_fail]},
{dsa_pass_key, [], [pass_phrase]},
{rsa_pass_key, [], [pass_phrase]},
- {key_cb, [], [key_callback, key_callback_options]},
+ {ecdsa_sha2_nistp256_pass_key, [], [pass_phrase]},
+ {ecdsa_sha2_nistp384_pass_key, [], [pass_phrase]},
+ {ecdsa_sha2_nistp521_pass_key, [], [pass_phrase]},
+ {key_cb, [parallel], [key_callback, key_callback_options]},
{internal_error, [], [internal_error]},
- {login_bad_pwd_no_retry, [], [login_bad_pwd_no_retry1,
- login_bad_pwd_no_retry2,
- login_bad_pwd_no_retry3,
- login_bad_pwd_no_retry4,
- login_bad_pwd_no_retry5
- ]}
+ {login_bad_pwd_no_retry, [parallel], [login_bad_pwd_no_retry1,
+ login_bad_pwd_no_retry2,
+ login_bad_pwd_no_retry3,
+ login_bad_pwd_no_retry4,
+ login_bad_pwd_no_retry5
+ ]},
+
+ {basic, [], [{group,p_basic},
+ shell, shell_no_unicode, shell_unicode_string,
+ close,
+ known_hosts
+ ]},
+ {p_basic, [parallel], [send, peername_sockname,
+ exec, exec_compressed,
+ cli,
+ idle_time_client, idle_time_server, openssh_zlib_basic_test,
+ misc_ssh_options, inet_option, inet6_option]}
].
-basic_tests() ->
- [send, close, peername_sockname,
- exec, exec_compressed,
- shell, shell_no_unicode, shell_unicode_string,
- cli, known_hosts,
- idle_time_client, idle_time_server, openssh_zlib_basic_test,
- misc_ssh_options, inet_option, inet6_option].
+
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- ?CHECK_CRYPTO(Config).
+ ?CHECK_CRYPTO(begin
+ ssh:start(),
+ Config
+ end).
end_per_suite(_Config) ->
ssh:stop().
%%--------------------------------------------------------------------
+init_per_group(ssh_renegotiate_SUITE, Config) ->
+ [{preferred_algorithms, ssh:default_algorithms()} | Config];
init_per_group(dsa_key, Config) ->
case lists:member('ssh-dss',
ssh_transport:default_algorithms(public_key)) of
@@ -174,6 +164,31 @@ init_per_group(rsa_key, Config) ->
false ->
{skip, unsupported_pub_key}
end;
+init_per_group(rsa_host_key_is_actualy_ecdsa, Config) ->
+ case
+ lists:member('ssh-rsa',
+ ssh_transport:default_algorithms(public_key)) and
+ lists:member('ecdsa-sha2-nistp256',
+ ssh_transport:default_algorithms(public_key))
+ of
+ true ->
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ ssh_test_lib:setup_ecdsa("256", DataDir, PrivDir),
+ %% The following sets up bad rsa keys:
+ begin
+ UserDir = PrivDir,
+ System = filename:join(UserDir, "system"),
+ file:copy(filename:join(DataDir, "id_rsa"), filename:join(UserDir, "id_rsa")),
+ file:rename(filename:join(System, "ssh_host_ecdsa_key"), filename:join(System, "ssh_host_rsa_key")),
+ file:rename(filename:join(System, "ssh_host_ecdsa_key.pub"), filename:join(System, "ssh_host_rsa_key.pub")),
+ ssh_test_lib:setup_rsa_known_host(DataDir, UserDir),
+ ssh_test_lib:setup_rsa_auth_keys(DataDir, UserDir)
+ end,
+ Config;
+ false ->
+ {skip, unsupported_pub_key}
+ end;
init_per_group(ecdsa_sha2_nistp256_key, Config) ->
case lists:member('ecdsa-sha2-nistp256',
ssh_transport:default_algorithms(public_key)) of
@@ -229,6 +244,45 @@ init_per_group(dsa_pass_key, Config) ->
false ->
{skip, unsupported_pub_key}
end;
+init_per_group(ecdsa_sha2_nistp256_pass_key, Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ case lists:member('ecdsa-sha2-nistp256',
+ ssh_transport:default_algorithms(public_key))
+ andalso
+ ssh_test_lib:setup_ecdsa_pass_phrase("256", DataDir, PrivDir, "Password")
+ of
+ true ->
+ [{pass_phrase, {ecdsa_pass_phrase, "Password"}}| Config];
+ false ->
+ {skip, unsupported_pub_key}
+ end;
+init_per_group(ecdsa_sha2_nistp384_pass_key, Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ case lists:member('ecdsa-sha2-nistp384',
+ ssh_transport:default_algorithms(public_key))
+ andalso
+ ssh_test_lib:setup_ecdsa_pass_phrase("384", DataDir, PrivDir, "Password")
+ of
+ true ->
+ [{pass_phrase, {ecdsa_pass_phrase, "Password"}}| Config];
+ false ->
+ {skip, unsupported_pub_key}
+ end;
+init_per_group(ecdsa_sha2_nistp521_pass_key, Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ case lists:member('ecdsa-sha2-nistp521',
+ ssh_transport:default_algorithms(public_key))
+ andalso
+ ssh_test_lib:setup_ecdsa_pass_phrase("521", DataDir, PrivDir, "Password")
+ of
+ true ->
+ [{pass_phrase, {ecdsa_pass_phrase, "Password"}}| Config];
+ false ->
+ {skip, unsupported_pub_key}
+ end;
init_per_group(host_user_key_differs, Config) ->
Data = proplists:get_value(data_dir, Config),
Sys = filename:join(proplists:get_value(priv_dir, Config), system_rsa),
@@ -241,7 +295,7 @@ init_per_group(host_user_key_differs, Config) ->
file:copy(filename:join(Data, "ssh_host_rsa_key.pub"), filename:join(Sys, "ssh_host_rsa_key.pub")),
file:copy(filename:join(Data, "id_ecdsa256"), filename:join(Usr, "id_ecdsa")),
file:copy(filename:join(Data, "id_ecdsa256.pub"), filename:join(Usr, "id_ecdsa.pub")),
- ssh_test_lib:setup_ecdsa_auth_keys("256", Usr, SysUsr),
+ ssh_test_lib:setup_ecdsa_auth_keys("256", Data, SysUsr),
ssh_test_lib:setup_rsa_known_host(Sys, Usr),
Config;
init_per_group(key_cb, Config) ->
@@ -259,7 +313,8 @@ init_per_group(internal_error, Config) ->
DataDir = proplists:get_value(data_dir, Config),
PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:setup_dsa(DataDir, PrivDir),
- file:delete(filename:join(PrivDir, "system/ssh_host_dsa_key")),
+ %% In the test case the key will be deleted after the daemon start:
+ %% ... file:delete(filename:join(PrivDir, "system/ssh_host_dsa_key")),
Config;
init_per_group(dir_options, Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
@@ -306,6 +361,7 @@ init_per_group(dir_options, Config) ->
init_per_group(_, Config) ->
Config.
+
end_per_group(dsa_key, Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
ssh_test_lib:clean_dsa(PrivDir),
@@ -339,7 +395,6 @@ init_per_testcase(TC, Config) when TC==shell_no_unicode ;
PrivDir = proplists:get_value(priv_dir, Config),
UserDir = proplists:get_value(priv_dir, Config),
SysDir = proplists:get_value(data_dir, Config),
- ssh:start(),
Sftpd = {_Pid, _Host, Port} =
ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, PrivDir},
@@ -362,7 +417,6 @@ init_per_testcase(inet6_option, Config) ->
{skip,"No ipv6 interface address"}
end;
init_per_testcase(_TestCase, Config) ->
- ssh:start(),
Config.
end_per_testcase(TestCase, Config) when TestCase == server_password_option;
@@ -383,7 +437,6 @@ end_per_testcase(_TestCase, Config) ->
end_per_testcase(Config).
end_per_testcase(_Config) ->
- ssh:stop(),
ok.
%%--------------------------------------------------------------------
@@ -405,8 +458,8 @@ misc_ssh_options(Config) when is_list(Config) ->
SystemDir = filename:join(proplists:get_value(priv_dir, Config), system),
UserDir = proplists:get_value(priv_dir, Config),
- CMiscOpt0 = [{connect_timeout, 1000}, {user_dir, UserDir}],
- CMiscOpt1 = [{connect_timeout, infinity}, {user_dir, UserDir}],
+ CMiscOpt0 = [{connect_timeout, 1000}, {user_dir, UserDir}, {silently_accept_hosts, true}],
+ CMiscOpt1 = [{connect_timeout, infinity}, {user_dir, UserDir}, {silently_accept_hosts, true}],
SMiscOpt0 = [{user_dir, UserDir}, {system_dir, SystemDir}],
SMiscOpt1 = [{user_dir, UserDir}, {system_dir, SystemDir}],
@@ -689,11 +742,11 @@ cli(Config) when is_list(Config) ->
{ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
ssh_connection:shell(ConnectionRef, ChannelId),
- ok = ssh_connection:send(ConnectionRef, ChannelId, <<"q">>),
+ ssh_connection:send(ConnectionRef, ChannelId, <<"q">>),
receive
{ssh_cm, ConnectionRef,
{data,0,0, <<"\r\nYou are accessing a dummy, type \"q\" to exit\r\n\n">>}} ->
- ok = ssh_connection:send(ConnectionRef, ChannelId, <<"q">>)
+ ssh_connection:send(ConnectionRef, ChannelId, <<"q">>)
after
30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE])
end,
@@ -822,12 +875,17 @@ key_callback_options(Config) when is_list(Config) ->
%%% Test that client does not hang if disconnects due to internal error
internal_error(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = filename:join(proplists:get_value(priv_dir, Config), system),
+ PrivDir = proplists:get_value(priv_dir, Config),
UserDir = proplists:get_value(priv_dir, Config),
+ SystemDir = filename:join(PrivDir, system),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{user_dir, UserDir},
{failfun, fun ssh_test_lib:failfun/2}]),
+
+ %% Now provoke an error in the following connect:
+ file:delete(filename:join(PrivDir, "system/ssh_host_dsa_key")),
+
{error, Error} =
ssh:connect(Host, Port, [{silently_accept_hosts, true},
{user_dir, UserDir},
@@ -856,6 +914,17 @@ send(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
+%%%
+fail_daemon_start(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ SystemDir = filename:join(proplists:get_value(priv_dir, Config), system),
+ UserDir = proplists:get_value(priv_dir, Config),
+
+ {error,_} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
+ {failfun, fun ssh_test_lib:failfun/2}]).
+
+%%--------------------------------------------------------------------
%%% Test ssh:connection_info([peername, sockname])
peername_sockname(Config) when is_list(Config) ->
process_flag(trap_exit, true),
@@ -1013,7 +1082,7 @@ multi_daemon_opt_fd(Config) ->
end || {S,Pid,C} <- Tests].
%%--------------------------------------------------------------------
-packet_size_zero(Config) ->
+packet_size(Config) ->
SystemDir = proplists:get_value(data_dir, Config),
PrivDir = proplists:get_value(priv_dir, Config),
UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
@@ -1028,21 +1097,36 @@ packet_size_zero(Config) ->
{user_interaction, false},
{user, "vego"},
{password, "morot"}]),
-
- {ok,Chan} = ssh_connection:session_channel(Conn, 1000, _MaxPacketSize=0, 60000),
- ok = ssh_connection:shell(Conn, Chan),
+ lists:foreach(
+ fun(MaxPacketSize) ->
+ ct:log("Try max_packet_size=~p",[MaxPacketSize]),
+ {ok,Ch} = ssh_connection:session_channel(Conn, 1000, MaxPacketSize, 60000),
+ ok = ssh_connection:shell(Conn, Ch),
+ rec(Server, Conn, Ch, MaxPacketSize),
+ ssh_connection:close(Conn, Ch)
+ end, [0, 1, 10, 25]),
ssh:close(Conn),
ssh:stop_daemon(Server),
+ ok.
+
+rec(Server, Conn, Ch, MaxSz) ->
receive
- {ssh_cm,Conn,{data,Chan,_Type,_Msg1}} = M ->
- ct:log("Got ~p",[M]),
- ct:fail(doesnt_obey_max_packet_size_0)
- after 5000 ->
- ok
- end.
-
+ {ssh_cm,Conn,{data,Ch,_,M}} when size(M) =< MaxSz ->
+ ct:log("~p: ~p",[MaxSz,M]),
+ rec(Server, Conn, Ch, MaxSz);
+ {ssh_cm,Conn,{data,Ch,_,_}} = M ->
+ ct:log("Max pkt size=~p. Got ~p",[MaxSz,M]),
+ ssh:close(Conn),
+ ssh:stop_daemon(Server),
+ ct:fail("Does not obey max_packet_size=~p",[MaxSz])
+ after
+ 2000 ->
+ ct:log("~p: ok!",[MaxSz]),
+ ok
+ end.
+
%%--------------------------------------------------------------------
shell_no_unicode(Config) ->
new_do_shell(proplists:get_value(io,Config),
@@ -1249,19 +1333,328 @@ shell_exit_status(Config) when is_list(Config) ->
ssh:stop_daemon(Pid).
+%%----------------------------------------------------------------------------
+%%% Idle timeout test
+rekey0() -> [{timetrap,{seconds,90}}].
+rekey1() -> [{timetrap,{seconds,90}}].
+rekey2() -> [{timetrap,{seconds,90}}].
+rekey3() -> [{timetrap,{seconds,90}}].
+rekey4() -> [{timetrap,{seconds,90}}].
+
+rekey0(Config) -> rekey_chk(Config, 0, 0).
+rekey1(Config) -> rekey_chk(Config, infinity, 0).
+rekey2(Config) -> rekey_chk(Config, {infinity,infinity}, 0).
+rekey3(Config) -> rekey_chk(Config, 0, infinity).
+rekey4(Config) -> rekey_chk(Config, 0, {infinity,infinity}).
+
+rekey_chk(Config, RLdaemon, RLclient) ->
+ {Pid, Host, Port} = ssh_test_lib:std_daemon(Config, [{rekey_limit, RLdaemon}]),
+ ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, RLclient}]),
+ Kex1 = ssh_test_lib:get_kex_init(ConnectionRef),
+
+ %% Make both sides send something:
+ {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef),
+
+ %% Check rekeying
+ timer:sleep(?REKEY_DATA_TMO),
+ ?wait_match(false, Kex1==ssh_test_lib:get_kex_init(ConnectionRef), [], 2000, 10),
+
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+%%% Test rekeying by data volume
+
+rekey_limit_client() -> [{timetrap,{seconds,400}}].
+rekey_limit_client(Config) ->
+ Limit = 6000,
+ UserDir = proplists:get_value(priv_dir, Config),
+ DataFile = filename:join(UserDir, "rekey.data"),
+ Data = lists:duplicate(Limit+10,1),
+ Algs = proplists:get_value(preferred_algorithms, Config),
+ {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0},
+ {preferred_algorithms,Algs}]),
+
+ ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, Limit},
+ {max_random_length_padding,0}]),
+ {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef),
+
+ %% Check that it doesn't rekey without data transfer
+ Kex1 = ssh_test_lib:get_kex_init(ConnectionRef),
+ timer:sleep(?REKEY_DATA_TMO),
+ true = (Kex1 == ssh_test_lib:get_kex_init(ConnectionRef)),
+
+ %% Check that datatransfer triggers rekeying
+ ok = ssh_sftp:write_file(SftpPid, DataFile, Data),
+ timer:sleep(?REKEY_DATA_TMO),
+ ?wait_match(false, Kex1==(Kex2=ssh_test_lib:get_kex_init(ConnectionRef)), Kex2, 2000, 10),
+
+ %% Check that datatransfer continues to trigger rekeying
+ ok = ssh_sftp:write_file(SftpPid, DataFile, Data),
+ timer:sleep(?REKEY_DATA_TMO),
+ ?wait_match(false, Kex2==(Kex3=ssh_test_lib:get_kex_init(ConnectionRef)), Kex3, 2000, 10),
+
+ %% Check that it doesn't rekey without data transfer
+ timer:sleep(?REKEY_DATA_TMO),
+ true = (Kex3 == ssh_test_lib:get_kex_init(ConnectionRef)),
+
+ %% Check that it doesn't rekey on a small datatransfer
+ ok = ssh_sftp:write_file(SftpPid, DataFile, "hi\n"),
+ timer:sleep(?REKEY_DATA_TMO),
+ true = (Kex3 == ssh_test_lib:get_kex_init(ConnectionRef)),
+
+ %% Check that it doesn't rekey without data transfer
+ timer:sleep(?REKEY_DATA_TMO),
+ true = (Kex3 == ssh_test_lib:get_kex_init(ConnectionRef)),
+
+ ssh_sftp:stop_channel(SftpPid),
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid).
+
+
+
+rekey_limit_daemon() -> [{timetrap,{seconds,400}}].
+rekey_limit_daemon(Config) ->
+ Limit = 6000,
+ UserDir = proplists:get_value(priv_dir, Config),
+ DataFile1 = filename:join(UserDir, "rekey1.data"),
+ DataFile2 = filename:join(UserDir, "rekey2.data"),
+ file:write_file(DataFile1, lists:duplicate(Limit+10,1)),
+ file:write_file(DataFile2, "hi\n"),
+
+ Algs = proplists:get_value(preferred_algorithms, Config),
+ {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{rekey_limit, Limit},
+ {max_random_length_padding,0},
+ {preferred_algorithms,Algs}]),
+ ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{max_random_length_padding,0}]),
+ {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef),
+
+ %% Check that it doesn't rekey without data transfer
+ Kex1 = ssh_test_lib:get_kex_init(ConnectionRef),
+ timer:sleep(?REKEY_DATA_TMO),
+ Kex1 = ssh_test_lib:get_kex_init(ConnectionRef),
+
+ %% Check that datatransfer triggers rekeying
+ {ok,_} = ssh_sftp:read_file(SftpPid, DataFile1),
+ timer:sleep(?REKEY_DATA_TMO),
+ ?wait_match(false, Kex1==(Kex2=ssh_test_lib:get_kex_init(ConnectionRef)), Kex2, 2000, 10),
+
+ %% Check that datatransfer continues to trigger rekeying
+ {ok,_} = ssh_sftp:read_file(SftpPid, DataFile1),
+ timer:sleep(?REKEY_DATA_TMO),
+ ?wait_match(false, Kex2==(Kex3=ssh_test_lib:get_kex_init(ConnectionRef)), Kex3, 2000, 10),
+
+ %% Check that it doesn't rekey without data transfer
+ timer:sleep(?REKEY_DATA_TMO),
+ true = (Kex3 == ssh_test_lib:get_kex_init(ConnectionRef)),
+
+ %% Check that it doesn't rekey on a small datatransfer
+ {ok,_} = ssh_sftp:read_file(SftpPid, DataFile2),
+ timer:sleep(?REKEY_DATA_TMO),
+ true = (Kex3 == ssh_test_lib:get_kex_init(ConnectionRef)),
+
+ %% Check that it doesn't rekey without data transfer
+ timer:sleep(?REKEY_DATA_TMO),
+ true = (Kex3 == ssh_test_lib:get_kex_init(ConnectionRef)),
+
+ ssh_sftp:stop_channel(SftpPid),
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid).
+
+
+%%--------------------------------------------------------------------
+%% Check that datatransfer in the other direction does not trigger re-keying
+norekey_limit_client() -> [{timetrap,{seconds,400}}].
+norekey_limit_client(Config) ->
+ Limit = 6000,
+ UserDir = proplists:get_value(priv_dir, Config),
+ DataFile = filename:join(UserDir, "rekey3.data"),
+ file:write_file(DataFile, lists:duplicate(Limit+10,1)),
+
+ Algs = proplists:get_value(preferred_algorithms, Config),
+ {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0},
+ {preferred_algorithms,Algs}]),
+
+ ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, Limit},
+ {max_random_length_padding,0}]),
+ {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef),
+
+ Kex1 = ssh_test_lib:get_kex_init(ConnectionRef),
+ timer:sleep(?REKEY_DATA_TMO),
+ true = (Kex1 == ssh_test_lib:get_kex_init(ConnectionRef)),
+
+ {ok,_} = ssh_sftp:read_file(SftpPid, DataFile),
+ timer:sleep(?REKEY_DATA_TMO),
+ true = (Kex1 == ssh_test_lib:get_kex_init(ConnectionRef)),
+
+ ssh_sftp:stop_channel(SftpPid),
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid).
+
+%% Check that datatransfer in the other direction does not trigger re-keying
+norekey_limit_daemon() -> [{timetrap,{seconds,400}}].
+norekey_limit_daemon(Config) ->
+ Limit = 6000,
+ UserDir = proplists:get_value(priv_dir, Config),
+ DataFile = filename:join(UserDir, "rekey4.data"),
+
+ Algs = proplists:get_value(preferred_algorithms, Config),
+ {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{rekey_limit, Limit},
+ {max_random_length_padding,0},
+ {preferred_algorithms,Algs}]),
+
+ ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{max_random_length_padding,0}]),
+ {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef),
+
+ Kex1 = ssh_test_lib:get_kex_init(ConnectionRef),
+ timer:sleep(?REKEY_DATA_TMO),
+ true = (Kex1 == ssh_test_lib:get_kex_init(ConnectionRef)),
+
+ ok = ssh_sftp:write_file(SftpPid, DataFile, lists:duplicate(Limit+10,1)),
+ timer:sleep(?REKEY_DATA_TMO),
+ true = (Kex1 == ssh_test_lib:get_kex_init(ConnectionRef)),
+
+ ssh_sftp:stop_channel(SftpPid),
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+%%% Test rekeying by time
+
+rekey_time_limit_client() -> [{timetrap,{seconds,400}}].
+rekey_time_limit_client(Config) ->
+ Minutes = ?REKEY_DATA_TMO div 60000,
+ GB = 1024*1000*1000,
+ Algs = proplists:get_value(preferred_algorithms, Config),
+ {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0},
+ {preferred_algorithms,Algs}]),
+ ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, {Minutes, GB}},
+ {max_random_length_padding,0}]),
+ rekey_time_limit(Pid, ConnectionRef).
+
+rekey_time_limit_daemon() -> [{timetrap,{seconds,400}}].
+rekey_time_limit_daemon(Config) ->
+ Minutes = ?REKEY_DATA_TMO div 60000,
+ GB = 1024*1000*1000,
+ Algs = proplists:get_value(preferred_algorithms, Config),
+ {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{rekey_limit, {Minutes, GB}},
+ {max_random_length_padding,0},
+ {preferred_algorithms,Algs}]),
+ ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{max_random_length_padding,0}]),
+ rekey_time_limit(Pid, ConnectionRef).
+
+
+rekey_time_limit(Pid, ConnectionRef) ->
+ {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef),
+ Kex1 = ssh_test_lib:get_kex_init(ConnectionRef),
+
+ timer:sleep(5000),
+ true = (Kex1 == ssh_test_lib:get_kex_init(ConnectionRef)),
+
+ %% Check that it rekeys when the max time + 30s has passed
+ timer:sleep(?REKEY_DATA_TMO + 30*1000),
+ ?wait_match(false, Kex1==(Kex2=ssh_test_lib:get_kex_init(ConnectionRef)), Kex2, 2000, 10),
+
+ %% Check that it does not rekey when nothing is transferred
+ timer:sleep(?REKEY_DATA_TMO + 30*1000),
+ ?wait_match(false, Kex2==ssh_test_lib:get_kex_init(ConnectionRef), [], 2000, 10),
+
+ ssh_sftp:stop_channel(SftpPid),
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+
+%%% Test rekeying with simultaneous send request
+
+renegotiate1(Config) ->
+ UserDir = proplists:get_value(priv_dir, Config),
+ DataFile = filename:join(UserDir, "renegotiate1.data"),
+
+ Algs = proplists:get_value(preferred_algorithms, Config),
+ {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0},
+ {preferred_algorithms,Algs}]),
+
+ RPort = ssh_test_lib:inet_port(),
+ {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort),
+
+
+ ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, [{max_random_length_padding,0}]),
+ {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef),
+
+ Kex1 = ssh_test_lib:get_kex_init(ConnectionRef),
+
+ {ok, Handle} = ssh_sftp:open(SftpPid, DataFile, [write]),
+
+ ok = ssh_sftp:write(SftpPid, Handle, "hi\n"),
+
+ ssh_relay:hold(RelayPid, rx, 20, 1000),
+ ssh_connection_handler:renegotiate(ConnectionRef),
+ spawn(fun() -> ok=ssh_sftp:write(SftpPid, Handle, "another hi\n") end),
+
+ timer:sleep(2000),
+
+ Kex2 = ssh_test_lib:get_kex_init(ConnectionRef),
+
+ false = (Kex2 == Kex1),
+
+ ssh_relay:stop(RelayPid),
+ ssh_sftp:stop_channel(SftpPid),
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
+
+%%% Test rekeying with inflight messages from peer
+
+renegotiate2(Config) ->
+ UserDir = proplists:get_value(priv_dir, Config),
+ DataFile = filename:join(UserDir, "renegotiate2.data"),
+
+ Algs = proplists:get_value(preferred_algorithms, Config),
+ {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0},
+ {preferred_algorithms,Algs}]),
+
+ RPort = ssh_test_lib:inet_port(),
+ {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort),
+
+ ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, [{max_random_length_padding,0}]),
+ {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef),
+
+ Kex1 = ssh_test_lib:get_kex_init(ConnectionRef),
+
+ {ok, Handle} = ssh_sftp:open(SftpPid, DataFile, [write]),
+
+ ok = ssh_sftp:write(SftpPid, Handle, "hi\n"),
+
+ ssh_relay:hold(RelayPid, rx, 20, infinity),
+ spawn(fun() -> ok=ssh_sftp:write(SftpPid, Handle, "another hi\n") end),
+ %% need a small pause here to ensure ssh_sftp:write is executed
+ ct:sleep(10),
+ ssh_connection_handler:renegotiate(ConnectionRef),
+ ssh_relay:release(RelayPid, rx),
+
+ timer:sleep(2000),
+
+ Kex2 = ssh_test_lib:get_kex_init(ConnectionRef),
+
+ false = (Kex2 == Kex1),
+
+ ssh_relay:stop(RelayPid),
+ ssh_sftp:stop_channel(SftpPid),
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid).
+
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
%% Due to timing the error message may or may not be delivered to
%% the "tcp-application" before the socket closed message is recived
-check_error("Invalid state") ->
- ok;
-check_error("Connection closed") ->
- ok;
-check_error("Selection of key exchange algorithm failed"++_) ->
- ok;
-check_error(Error) ->
- ct:fail(Error).
+check_error("Invalid state") -> ok;
+check_error("Connection closed") -> ok;
+check_error("Selection of key exchange algorithm failed"++_) -> ok;
+check_error("No host key available") -> ok;
+check_error(Error) -> ct:fail(Error).
basic_test(Config) ->
ClientOpts = proplists:get_value(client_opts, Config),
@@ -1403,7 +1796,7 @@ new_do_shell(IO, N, Ops=[{Order,Arg}|More]) ->
ct:fail("*** Expected ~p, but got ~p",[string:strip(ExpStr),RecStr])
end
after 30000 ->
- ct:log("Meassage queue of ~p:~n~p",
+ ct:log("Message queue of ~p:~n~p",
[self(), erlang:process_info(self(), messages)]),
case Order of
expect -> ct:fail("timeout, expected ~p",[string:strip(Arg)]);
diff --git a/lib/ssh/test/ssh_bench_SUITE.erl b/lib/ssh/test/ssh_bench_SUITE.erl
index 2c0cd8fc8e..764c52b624 100644
--- a/lib/ssh/test/ssh_bench_SUITE.erl
+++ b/lib/ssh/test/ssh_bench_SUITE.erl
@@ -1,7 +1,7 @@
%%%-------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -57,12 +57,19 @@ init_per_suite(Config) ->
ok ->
DataSize = 1000000,
SystemDir = proplists:get_value(data_dir, Config),
- Algs = insert_none(ssh:default_algorithms()),
+ Algs = ssh:default_algorithms(),
{_ServerPid, _Host, Port} =
ssh_test_lib:daemon([{system_dir, SystemDir},
{user_passwords, [{?UID,?PWD}]},
{failfun, fun ssh_test_lib:failfun/2},
{preferred_algorithms, Algs},
+ {modify_algorithms,[{prepend,[{cipher,[none]},
+ {mac,[none]}
+ ]}
+ %% ,{rm, [{cipher,['[email protected]',
+ %% ]}
+ ]},
{max_random_length_padding, 0},
{subsystems, [{"/dev/null", {ssh_bench_dev_null,[DataSize]}}]}
]),
@@ -145,7 +152,8 @@ transfer_text(Config) ->
|| {Crypto,Mac} <- [{ none, none},
{'aes128-ctr', 'hmac-sha1'},
{'aes256-ctr', 'hmac-sha1'},
-%% {'[email protected]', 'hmac-sha1'},
+{'[email protected]', 'hmac-sha1'},
+{'[email protected]', 'hmac-sha1'},
{'aes128-cbc', 'hmac-sha1'},
{'3des-cbc', 'hmac-sha1'},
{'aes128-ctr', 'hmac-sha2-256'},
@@ -175,11 +183,36 @@ gen_data(DataSz) ->
%% {suite, ?MODULE},
%% {name, mk_name(["Transfer 1M bytes ",Cipher,"/",Mac," [µs]"])}]);
connect_measure(Port, Cipher, Mac, Data, Options) ->
+ AES_GCM = {cipher,
+ []},
+
+ AlgOpt = case {Cipher,Mac} of
+ {none,none} ->
+ [{modify_algorithms,[{prepend, [{cipher,[Cipher]},
+ {mac,[Mac]}]}
+%%% ,{rm,[AES_GCM]}
+ ]}];
+ {none,_} ->
+ [{modify_algorithms,[{prepend, [{cipher,[Cipher]}]}
+%%% ,{rm,[AES_GCM]}
+ ]},
+ {preferred_algorithms, [{mac,[Mac]}]}];
+ {_,none} ->
+ [{modify_algorithms,[{prepend, [{mac,[Mac]}]}
+%%% ,{rm,[AES_GCM]}
+ ]},
+ {preferred_algorithms, [{cipher,[Cipher]}]}];
+ _ ->
+ [{preferred_algorithms, [{cipher,[Cipher]},
+ {mac,[Mac]}]}
+%%% ,{modify_algorithms, [{rm,[AES_GCM]}]}
+ ]
+ end,
Times =
[begin
- {ok,C} = ssh:connect("localhost", Port, [{preferred_algorithms, [{cipher,[Cipher]},
- {mac,[Mac]}]}
- |Options]),
+ {ok,C} = ssh:connect("localhost", Port, AlgOpt ++ Options),
{ok,Ch} = ssh_connection:session_channel(C, 10000),
success = ssh_connection:subsystem(C, Ch, "/dev/null", 10000),
{Time,ok} = timer:tc(?MODULE, send_wait_acc, [C, Ch, Data]),
@@ -205,16 +238,6 @@ send_wait_acc(C, Ch, Data) ->
%%%
%%%----------------------------------------------------------------
-insert_none(L) ->
- lists:foldl(fun insert_none/2, [], L).
-
-insert_none({T,L}, Acc) when T==cipher ;
- T==mac ->
- [{T, [{T1,L1++[none]} || {T1,L1} <- L]} | Acc];
-insert_none(_, Acc) ->
- Acc.
-
-%%%----------------------------------------------------------------
mk_name(Name) -> [char(C) || C <- lists:concat(Name)].
char($-) -> $_;
diff --git a/lib/ssh/test/ssh_bench_dev_null.erl b/lib/ssh/test/ssh_bench_dev_null.erl
index 5166247714..868eea5643 100644
--- a/lib/ssh/test/ssh_bench_dev_null.erl
+++ b/lib/ssh/test/ssh_bench_dev_null.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@
%%% Description: Example ssh server
-module(ssh_bench_dev_null).
--behaviour(ssh_daemon_channel).
+-behaviour(ssh_server_channel).
-record(state, {
cm,
diff --git a/lib/ssh/test/ssh_chan_behaviours_SUITE.erl b/lib/ssh/test/ssh_chan_behaviours_SUITE.erl
new file mode 100644
index 0000000000..16ed152bcd
--- /dev/null
+++ b/lib/ssh/test/ssh_chan_behaviours_SUITE.erl
@@ -0,0 +1,152 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssh_chan_behaviours_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("ssh/src/ssh.hrl").
+-include("ssh_test_lib.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{seconds,60}}].
+
+all() ->
+ [
+ noexist_subsystem,
+ undefined_subsystem,
+ defined_subsystem,
+ subsystem_client
+ ].
+
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ ?CHECK_CRYPTO(
+ begin
+ ssh:start(),
+ Config
+ end).
+
+end_per_suite(_Config) ->
+ {Time,R} = timer:tc(ssh, stop, []),
+ ct:log("Stop ssh: ~p ms",[(100*(Time div 1000)) / 100]),
+ R.
+
+init_per_testcase(_TC, Config) ->
+ SubSystems = [
+ {"bad_cb", {ssh_chan_behaviours_undefined, []}}, % A non-existing file
+ {"ch1", {ssh_chan_behaviours_server, [self(),true]}}
+ ],
+ {Pid, Host, Port} = ssh_test_lib:std_daemon(Config, [{subsystems,SubSystems}]),
+ C = ssh_test_lib:std_connect(Config, Host, Port, []),
+ [{connref,C}, {daemon_pid,Pid}| Config].
+
+end_per_testcase(_TC, Config) ->
+ {Time,_} = timer:tc(ssh, stop_daemon, [proplists:get_value(daemon_pid,Config)]),
+ ct:log("Stop daemon: ~p ms",[(100*(Time div 1000)) / 100]),
+ case flush() of
+ [] -> ok;
+ Msgs -> ct:pal("Unhandled messages:~n~p", [Msgs])
+ end.
+
+
+-define(EXPECT(What, Bind),
+ Bind =
+ (fun() ->
+ receive What ->
+ ct:log("~p:~p ~p got ~p",[?MODULE,?LINE,self(),What]),
+ Bind
+ after 5000 ->
+ ct:log("~p:~p ~p Flushed:~n~p",[?MODULE,?LINE,self(),flush()]),
+ ct:fail("Timeout!",[])
+ end
+ end)()
+ ).
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+%% Try start a subsystem whos name is not known by the server
+noexist_subsystem(Config) ->
+ C = proplists:get_value(connref, Config),
+ {ok, Ch} = ssh_connection:session_channel(C, infinity),
+ failure = ssh_connection:subsystem(C, Ch, "noexist", infinity),
+ ok = ssh_connection:close(C, Ch),
+ ?EXPECT({ssh_cm,C,{closed,Ch}},[]),
+ ok.
+
+%% Try to start a subsystem with a known name, but without any callback file
+undefined_subsystem(Config) ->
+ C = proplists:get_value(connref, Config),
+ {ok, Ch} = ssh_connection:session_channel(C, infinity),
+ failure = ssh_connection:subsystem(C, Ch, "bad_cb", infinity),
+ ok = ssh_connection:close(C, Ch),
+ ?EXPECT({ssh_cm,C,{closed,Ch}},[]), % self() is instead of a proper channel handler
+ ok.
+
+%% Try to start and stop a subsystem with known name and defined callback file
+defined_subsystem(Config) ->
+ C = proplists:get_value(connref, Config),
+ {ok, Ch1} = ssh_connection:session_channel(C, infinity),
+
+ success = ssh_connection:subsystem(C, Ch1, "ch1", infinity),
+ IDsrv = ?EXPECT({{_Csrv,_Ch1srv}, {ssh_channel_up,_Ch1srv,_Csrv}}, {_Csrv,_Ch1srv}),
+
+ ok = ssh_connection:close(C, Ch1),
+ ?EXPECT({IDsrv, {terminate,normal}}, []),
+ ?EXPECT({ssh_cm, C, {closed,Ch1}}, []), % self() is instead of a proper channel handler
+ ok.
+
+%% Try to start and stop a subsystem from a ssh_client_channel behviour
+subsystem_client(Config) ->
+ C = proplists:get_value(connref, Config),
+
+ {ok,ChRef} = ssh_chan_behaviours_client:start_link(C),
+ IDclt = ?EXPECT({{C,Ch1clt}, {ssh_channel_up,Ch1clt,C}}, {C,Ch1clt}),
+ IDsrv = ?EXPECT({{_Csrv,Ch1srv}, {ssh_channel_up,Ch1srv,_Csrv}}, {_Csrv,Ch1srv}),
+
+ ok = ssh_chan_behaviours_client:stop(ChRef),
+ ?EXPECT({IDclt, {terminate,normal}}, []), % From the proper channel handler
+ ?EXPECT({IDsrv, {terminate,normal}}, []),
+ ok.
+
+%%%================================================================
+%%%
+%%%
+
+flush() -> lists:reverse(flush([])).
+
+flush(Acc) ->
+ receive
+ M ->
+ flush([M|Acc])
+ after 0 ->
+ Acc
+ end.
+
diff --git a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_dsa_key
index 51ab6fbd88..51ab6fbd88 100644
--- a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_dsa_key
+++ b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_dsa_key
diff --git a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_dsa_key.pub
index 4dbb1305b0..4dbb1305b0 100644
--- a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_dsa_key.pub
+++ b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_dsa_key.pub
diff --git a/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_ecdsa_key b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_ecdsa_key
new file mode 100644
index 0000000000..fb1a862ded
--- /dev/null
+++ b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_ecdsa_key
@@ -0,0 +1,6 @@
+-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDArxbDfh3p1okrD9wQw6jJ4d4DdlBPD5GqXE8bIeRJiK41Sh40LgvPw
+mkqEDSXK++CgBwYFK4EEACKhZANiAAScl43Ih2lWTDKrSox5ve5uiTXil4smsup3
+CfS1XPjKxgBAmlfBim8izbdrT0BFdQzz2joduNMtpt61wO4rGs6jm0UP7Kim9PC7
+Hneb/99fIYopdMH5NMnk60zGO1uZ2vc=
+-----END EC PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_ecdsa_key.pub b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_ecdsa_key.pub
new file mode 100644
index 0000000000..428d5fb7d7
--- /dev/null
+++ b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_ecdsa_key.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBJyXjciHaVZMMqtKjHm97m6JNeKXiyay6ncJ9LVc+MrGAECaV8GKbyLNt2tPQEV1DPPaOh240y2m3rXA7isazqObRQ/sqKb08Lsed5v/318hiil0wfk0yeTrTMY7W5na9w== uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_rsa_key b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_rsa_key
index 79968bdd7d..79968bdd7d 100644
--- a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_rsa_key
+++ b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_rsa_key
diff --git a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_rsa_key.pub b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_rsa_key.pub
index 75d2025c71..75d2025c71 100644
--- a/lib/ssh/test/ssh_renegotiate_SUITE_data/ssh_host_rsa_key.pub
+++ b/lib/ssh/test/ssh_chan_behaviours_SUITE_data/ssh_host_rsa_key.pub
diff --git a/lib/ssh/test/ssh_chan_behaviours_client.erl b/lib/ssh/test/ssh_chan_behaviours_client.erl
new file mode 100644
index 0000000000..15f17733d6
--- /dev/null
+++ b/lib/ssh/test/ssh_chan_behaviours_client.erl
@@ -0,0 +1,143 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%
+
+%%
+
+%%% Description: Example ssh client
+-module(ssh_chan_behaviours_client).
+-behaviour(ssh_client_channel).
+-record(state, {
+ parent,
+ cm,
+ ch,
+ dbg
+ }).
+-export([start_link/1, start/1,
+ stop/1, send_eof/1,
+ init/1, handle_msg/2, handle_ssh_msg/2, terminate/2,
+ code_change/3, handle_call/3, handle_cast/2
+ ]).
+
+-define(DBG(State,Fmt,Args),
+ case State#state.dbg of
+ true -> ct:log("~p:~p ~p C=~p Ch=~p "++Fmt,
+ [?MODULE,?LINE,self(),State#state.cm,State#state.ch|Args]);
+ false -> ok
+ end).
+
+
+start_link(C) ->
+ {ok, Ch} = ssh_connection:session_channel(C, infinity),
+ ssh_client_channel:start_link(C, Ch, ssh_chan_behaviours_client, [C, Ch, self(), true]).
+
+start(C) ->
+ {ok, Ch} = ssh_connection:session_channel(C, infinity),
+ ssh_client_channel:start(C, Ch, ssh_chan_behaviours_client, [C, Ch, self(), true]).
+
+send_eof(ChRef) ->
+ ssh_client_channel:call(ChRef, send_eof).
+
+stop(ChRef) ->
+ ssh_client_channel:call(ChRef, stop).
+
+
+init([C, Ch, Parent, Dbg|_Exec]) ->
+ case ssh_connection:subsystem(C, Ch, "ch1", infinity) of
+ success ->
+ State = #state{cm = C,
+ ch = Ch,
+ parent=Parent,
+ dbg=Dbg},
+ ?DBG(State, "callback spawned, parent = ~p", [Parent]),
+ {ok, State};
+
+ Other ->
+ {stop, Other}
+ end.
+
+handle_msg({ssh_channel_up, ChannelId, ConnectionManager}=M, State0) ->
+ State = State0#state{cm = ConnectionManager,
+ ch = ChannelId},
+ tell_parent(M, State),
+ ?DBG(State, "ssh_channel_up",[]),
+ {ok, State}.
+
+handle_ssh_msg({ssh_cm, C, {data, Ch, 0, Data}}=M, #state{ch=Ch,cm=C} = State) ->
+ tell_parent(M, State),
+ ?DBG(State, "ssh_cm data size(Data)=~p",[size(Data)]),
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, C, {data, Ch, Type, Data}}=M, #state{ch=Ch,cm=C} = State) ->
+ tell_parent(M, State),
+ ?DBG(State, "ssh_cm data Type=~p : ~p",[Type,Data]),
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, C, {eof, Ch}}=M, #state{ch=Ch,cm=C} = State) ->
+ tell_parent(M, State),
+ ?DBG(State, "eof",[]),
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, C, {signal, _Ch, _SigNameStr}=Sig} = M, #state{ch=Ch,cm=C} = State) ->
+ %% Ignore signals according to RFC 4254 section 6.9.
+ tell_parent(M, State),
+ ?DBG(State, "~p",[Sig]),
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, C, {exit_signal, Ch, _, _Error, _}=Sig}=M, #state{ch=Ch,cm=C} = State) ->
+ tell_parent(M, State),
+ ?DBG(State, "~p",[Sig]),
+ {stop, Ch, State};
+
+handle_ssh_msg({ssh_cm, C, {exit_status, Ch, _Status}=Sig}=M, #state{ch=Ch,cm=C} = State) ->
+ tell_parent(M, State),
+ ?DBG(State, "~p",[Sig]),
+ {stop, Ch, State}.
+
+
+handle_call(send_eof, _From,#state{ch=Ch,cm=C} = State) ->
+ {reply, ssh_connection:send_eof(C,Ch), State};
+
+handle_call(stop, _From, State) ->
+ {stop, normal, ok, State};
+
+handle_call(Msg, _From, State) ->
+ ?DBG(State, "Unknown call ~p", [Msg]),
+ {reply, {unknown_call,Msg}, State}.
+
+
+terminate(Reason, State) ->
+ tell_parent({terminate,Reason}, State),
+ ?DBG(State, "terminate Reason = ~p",[Reason]).
+
+
+handle_cast(Msg, State) ->
+ ?DBG(State, "Unknown cast ~p", [Msg]),
+ {noreply, State}.
+
+code_change(_OldVsn, State, _Extra) -> {ok, State}.
+
+%%%================================================================
+%%%
+%%%
+
+tell_parent(Msg, #state{parent = Parent,
+ cm = C,
+ ch = Ch}) -> Parent ! {{C,Ch}, Msg}.
+
diff --git a/lib/ssh/test/ssh_chan_behaviours_server.erl b/lib/ssh/test/ssh_chan_behaviours_server.erl
new file mode 100644
index 0000000000..1408675a6e
--- /dev/null
+++ b/lib/ssh/test/ssh_chan_behaviours_server.erl
@@ -0,0 +1,96 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%
+
+%%
+
+%%% Description: Example ssh server
+-module(ssh_chan_behaviours_server).
+-behaviour(ssh_server_channel).
+-record(state, {
+ parent,
+ cm,
+ ch,
+ dbg
+ }).
+-export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]).
+
+-define(DBG(State,Fmt,Args),
+ case State#state.dbg of
+ true -> ct:log("~p:~p ~p C=~p Ch=~p "++Fmt,
+ [?MODULE,?LINE,self(),State#state.cm,State#state.ch|Args]);
+ false -> ok
+ end).
+
+
+init([Pid,Dbg|_Exec]) ->
+ {ok, #state{parent=Pid,
+ dbg=Dbg}}.
+
+handle_msg({ssh_channel_up, ChannelId, ConnectionManager}=M, State0) ->
+ State = State0#state{cm = ConnectionManager,
+ ch = ChannelId},
+ tell_parent(M, State),
+ ?DBG(State, "ssh_channel_up",[]),
+ {ok, State}.
+
+handle_ssh_msg({ssh_cm, C, {data, Ch, 0, Data}}=M, #state{ch=Ch,cm=C} = State) ->
+ tell_parent(M, State),
+ ?DBG(State, "ssh_cm data size(Data)=~p",[size(Data)]),
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, C, {data, Ch, Type, Data}}=M, #state{ch=Ch,cm=C} = State) ->
+ tell_parent(M, State),
+ ?DBG(State, "ssh_cm data Type=~p : ~p",[Type,Data]),
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, C, {eof, Ch}}=M, #state{ch=Ch,cm=C} = State) ->
+ tell_parent(M, State),
+ ?DBG(State, "eof",[]),
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, C, {signal, _Ch, _SigNameStr}=Sig} = M, #state{ch=Ch,cm=C} = State) ->
+ %% Ignore signals according to RFC 4254 section 6.9.
+ tell_parent(M, State),
+ ?DBG(State, "~p",[Sig]),
+ {ok, State};
+
+handle_ssh_msg({ssh_cm, C, {exit_signal, Ch, _, _Error, _}=Sig}=M, #state{ch=Ch,cm=C} = State) ->
+ tell_parent(M, State),
+ ?DBG(State, "~p",[Sig]),
+ {stop, Ch, State};
+
+handle_ssh_msg({ssh_cm, C, {exit_status, Ch, _Status}=Sig}=M, #state{ch=Ch,cm=C} = State) ->
+ tell_parent(M, State),
+ ?DBG(State, "~p",[Sig]),
+ {stop, Ch, State}.
+
+terminate(Reason, State) ->
+ tell_parent({terminate,Reason}, State),
+ ?DBG(State, "terminate Reason = ~p",[Reason]),
+ ok.
+
+%%%================================================================
+%%%
+%%%
+
+tell_parent(Msg, #state{parent = Parent,
+ cm = C,
+ ch = Ch}) -> Parent ! {{C,Ch}, Msg}.
+
diff --git a/lib/ssh/test/ssh_compat_SUITE.erl b/lib/ssh/test/ssh_compat_SUITE.erl
new file mode 100644
index 0000000000..1c607bebe8
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE.erl
@@ -0,0 +1,1398 @@
+%%
+%% %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(ssh_compat_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("ssh/src/ssh_transport.hrl"). % #ssh_msg_kexinit{}
+-include_lib("kernel/include/inet.hrl"). % #hostent{}
+-include_lib("kernel/include/file.hrl"). % #file_info{}
+-include("ssh_test_lib.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-define(USER,"sshtester").
+-define(PASSWD, "foobar").
+-define(BAD_PASSWD, "NOT-"?PASSWD).
+-define(DOCKER_PFX, "ssh_compat_suite-ssh").
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
+suite() ->
+ [{timetrap,{seconds,60}}].
+
+all() ->
+%% [check_docker_present] ++
+ [{group,G} || G <- ssh_image_versions()].
+
+groups() ->
+ [{otp_client, [], [login_otp_is_client,
+ all_algorithms_sftp_exec_reneg_otp_is_client,
+ send_recv_big_with_renegotiate_otp_is_client
+ ]},
+ {otp_server, [], [login_otp_is_server,
+ all_algorithms_sftp_exec_reneg_otp_is_server
+ ]} |
+ [{G, [], [{group,otp_client}, {group,otp_server}]} || G <- ssh_image_versions()]
+ ].
+
+
+ssh_image_versions() ->
+ try
+ %% Find all useful containers in such a way that undefined command, too low
+ %% priviliges, no containers and containers found give meaningful result:
+ L0 = ["REPOSITORY"++_|_] = string:tokens(os:cmd("docker images"), "\r\n"),
+ [["REPOSITORY","TAG"|_]|L1] = [string:tokens(E, " ") || E<-L0],
+ [list_to_atom(V) || [?DOCKER_PFX,V|_] <- L1]
+ of
+ Vs ->
+ lists:sort(Vs)
+ catch
+ error:{badmatch,_} ->
+ []
+ end.
+
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ ?CHECK_CRYPTO(
+ case os:find_executable("docker") of
+ false ->
+ {skip, "No docker"};
+ _ ->
+ ssh:start(),
+ ct:log("Crypto info: ~p",[crypto:info_lib()]),
+ Config
+ end).
+
+end_per_suite(Config) ->
+ %% Remove all containers that are not running:
+%%% os:cmd("docker rm $(docker ps -aq -f status=exited)"),
+ %% Remove dangling images:
+%%% os:cmd("docker rmi $(docker images -f dangling=true -q)"),
+ catch ssh:stop(),
+ Config.
+
+
+init_per_group(otp_server, Config) ->
+ case proplists:get_value(common_remote_client_algs, Config) of
+ undefined ->
+ SSHver = proplists:get_value(ssh_version, Config, ""),
+ {skip,"No "++SSHver++ " client found in docker"};
+ _ ->
+ Config
+ end;
+
+init_per_group(otp_client, Config) ->
+ Config;
+
+init_per_group(G, Config0) ->
+ case lists:member(G, ssh_image_versions()) of
+ true ->
+ %% This group is for one of the images
+ Vssh = atom_to_list(G),
+ Cmnt = io_lib:format("+++ ~s +++",[Vssh]),
+ ct:comment("~s",[Cmnt]),
+ try start_docker(G) of
+ {ok,ID} ->
+ ct:log("==> ~p started",[G]),
+ %% Find the algorithms that both client and server supports:
+ {IP,Port} = ip_port([{id,ID}]),
+ ct:log("Try contact ~p:~p",[IP,Port]),
+ Config1 = [{id,ID},
+ {ssh_version,Vssh}
+ | Config0],
+ try common_algs(Config1, IP, Port) of
+ {ok, ServerHello, RemoteServerCommon, ClientHello, RemoteClientCommon} ->
+ case chk_hellos([ServerHello,ClientHello], Cmnt) of
+ Cmnt ->
+ ok;
+ NewCmnt ->
+ ct:comment("~s",[NewCmnt])
+ end,
+ AuthMethods =
+ %% This should be obtained by quering the peer, but that
+ %% is a bit hard. It is possible with ssh_protocol_SUITE
+ %% techniques, but it can wait.
+ case Vssh of
+ "dropbear" ++ _ ->
+ [password, publickey];
+ _ ->
+ [password, 'keyboard-interactive', publickey]
+ end,
+ [{common_remote_server_algs,RemoteServerCommon},
+ {common_remote_client_algs,RemoteClientCommon},
+ {common_authmethods,AuthMethods}
+ |Config1];
+ Other ->
+ ct:log("Error in init_per_group: ~p",[Other]),
+ stop_docker(ID),
+ {fail, "Can't contact docker sshd"}
+ catch
+ Class:Exc ->
+ ST = erlang:get_stacktrace(),
+ ct:log("common_algs: ~p:~p~n~p",[Class,Exc,ST]),
+ stop_docker(ID),
+ {fail, "Failed during setup"}
+ end
+ catch
+ cant_start_docker ->
+ {skip, "Can't start docker"};
+
+ C:E ->
+ ST = erlang:get_stacktrace(),
+ ct:log("No ~p~n~p:~p~n~p",[G,C,E,ST]),
+ {skip, "Can't start docker"}
+ end;
+
+ false ->
+ Config0
+ end.
+
+end_per_group(G, Config) ->
+ case lists:member(G, ssh_image_versions()) of
+ true ->
+ catch stop_docker(proplists:get_value(id,Config));
+ false ->
+ ok
+ end.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+check_docker_present(_Config) ->
+ ct:log("This testcase is just to show in Monitor that we have a test host with docker installed",[]),
+ {fail, "Test is OK: just showing docker is available"}.
+
+%%--------------------------------------------------------------------
+login_otp_is_client(Config) ->
+ {IP,Port} = ip_port(Config),
+ PublicKeyAlgs = [A || {public_key,A} <- proplists:get_value(common_remote_server_algs, Config)],
+ CommonAuths =
+ [{AuthMethod,Alg} || AuthMethod <- proplists:get_value(common_authmethods, Config),
+ Alg <- case AuthMethod of
+ publickey ->
+ PublicKeyAlgs;
+ _ ->
+ [' ']
+ end
+ ],
+
+ chk_all_algos(?FUNCTION_NAME, CommonAuths, Config,
+ fun(AuthMethod,Alg) ->
+ {Opts,Dir} =
+ case AuthMethod of
+ publickey ->
+ {[], setup_remote_auth_keys_and_local_priv(Alg, Config)};
+ _ ->
+ {[{password,?PASSWD}], new_dir(Config)}
+ end,
+ ssh:connect(IP, Port, [{auth_methods, atom_to_list(AuthMethod)},
+ {user,?USER},
+ {user_dir, Dir},
+ {silently_accept_hosts,true},
+ {user_interaction,false}
+ | Opts
+ ])
+ end).
+
+
+%%--------------------------------------------------------------------
+login_otp_is_server(Config) ->
+ PublicKeyAlgs = [A || {public_key,A} <- proplists:get_value(common_remote_client_algs, Config)],
+ CommonAuths =
+ [{AuthMethod,Alg} || AuthMethod <- proplists:get_value(common_authmethods, Config),
+ Alg <- case AuthMethod of
+ publickey ->
+ PublicKeyAlgs;
+ _ ->
+ [' ']
+ end
+ ],
+ SysDir = setup_local_hostdir(hd(PublicKeyAlgs), Config),
+ chk_all_algos(?FUNCTION_NAME, CommonAuths, Config,
+ fun(AuthMethod,Alg) ->
+ {Opts,UsrDir} =
+ case AuthMethod of
+ publickey ->
+ {[{user_passwords, [{?USER,?BAD_PASSWD}]}],
+ setup_remote_priv_and_local_auth_keys(Alg, Config)
+ };
+ _ ->
+ {[{user_passwords, [{?USER,?PASSWD}]}],
+ new_dir(Config)
+ }
+ end,
+ {Server, Host, HostPort} =
+ ssh_test_lib:daemon(0,
+ [{auth_methods, atom_to_list(AuthMethod)},
+ {system_dir, SysDir},
+ {user_dir, UsrDir},
+ {failfun, fun ssh_test_lib:failfun/2}
+ | Opts
+ ]),
+ R = exec_from_docker(Config, Host, HostPort,
+ "'lists:concat([\"Answer=\",1+3]).\r\n'",
+ [<<"Answer=4">>],
+ ""),
+ ssh:stop_daemon(Server),
+ R
+ end).
+
+%%--------------------------------------------------------------------
+all_algorithms_sftp_exec_reneg_otp_is_client(Config) ->
+ CommonAlgs = proplists:get_value(common_remote_server_algs, Config),
+ {IP,Port} = ip_port(Config),
+ chk_all_algos(?FUNCTION_NAME, CommonAlgs, Config,
+ fun(Tag, Alg) ->
+ ConnRes =
+ ssh:connect(IP, Port,
+ [{user,?USER},
+ {password,?PASSWD},
+ {auth_methods, "password"},
+ {user_dir, new_dir(Config)},
+ {preferred_algorithms, [{Tag,[Alg]}]},
+ {silently_accept_hosts,true},
+ {user_interaction,false}
+ ]) ,
+ test_erl_client_reneg(ConnRes, % Seems that max 10 channels may be open in sshd
+ [{exec,1},
+ {sftp,5},
+ {no_subsyst,1},
+ {setenv, 1},
+ {sftp_async,1}
+ ])
+ end).
+
+%%--------------------------------------------------------------------
+all_algorithms_sftp_exec_reneg_otp_is_server(Config) ->
+ CommonAlgs = proplists:get_value(common_remote_client_algs, Config),
+ UserDir = setup_remote_priv_and_local_auth_keys('ssh-rsa', Config),
+ chk_all_algos(?FUNCTION_NAME, CommonAlgs, Config,
+ fun(Tag,Alg) ->
+ HostKeyAlg = case Tag of
+ public_key -> Alg;
+ _ -> 'ssh-rsa'
+ end,
+ SftpRootDir = new_dir(Config),
+ %% ct:log("Rootdir = ~p",[SftpRootDir]),
+ {Server, Host, HostPort} =
+ ssh_test_lib:daemon(0,
+ [{preferred_algorithms, [{Tag,[Alg]}]},
+ {system_dir, setup_local_hostdir(HostKeyAlg, Config)},
+ {user_dir, UserDir},
+ {user_passwords, [{?USER,?PASSWD}]},
+ {failfun, fun ssh_test_lib:failfun/2},
+ {subsystems,
+ [ssh_sftpd:subsystem_spec([{cwd,SftpRootDir},
+ {root,SftpRootDir}]),
+ {"echo_10",{ssh_echo_server,[10,[{dbg,true}]]}}
+ ]}
+ ]),
+ R = do([fun() ->
+ exec_from_docker(Config, Host, HostPort,
+ "hi_there.\r\n",
+ [<<"hi_there">>],
+ "")
+ end,
+ fun() ->
+ sftp_tests_erl_server(Config, Host, HostPort, SftpRootDir, UserDir)
+ end
+ ]),
+ ssh:stop_daemon(Server),
+ R
+ end).
+
+%%--------------------------------------------------------------------
+send_recv_big_with_renegotiate_otp_is_client(Config) ->
+ %% Connect to the remote openssh server:
+ {IP,Port} = ip_port(Config),
+ {ok,C} = ssh:connect(IP, Port, [{user,?USER},
+ {password,?PASSWD},
+ {user_dir, setup_remote_auth_keys_and_local_priv('ssh-rsa', Config)},
+ {silently_accept_hosts,true},
+ {user_interaction,false}
+ ]),
+
+ %% Open a channel and exec the Linux 'cat' command at the openssh side.
+ %% This 'cat' will read stdin and write to stdout until an eof is read from stdin.
+ {ok, Ch1} = ssh_connection:session_channel(C, infinity),
+ success = ssh_connection:exec(C, Ch1, "cat", infinity),
+
+ %% Build big binary
+ HalfSizeBytes = 100*1000*1000,
+ Data = << <<X:32>> || X <- lists:seq(1, HalfSizeBytes div 4)>>,
+
+ %% Send the data. Must spawn a process to avoid deadlock. The client will block
+ %% until all is sent through the send window. But the server will stop receiveing
+ %% when the servers send-window towards the client is full.
+ %% Since the client can't receive before the server has received all but 655k from the client
+ %% ssh_connection:send/4 is blocking...
+ spawn_link(
+ fun() ->
+ ct:comment("Sending ~p Mbytes with renegotiation in the middle",[2*byte_size(Data)/1000000]),
+ %% ct:log("sending first ~p bytes",[byte_size(Data)]),
+ ok = ssh_connection:send(C, Ch1, Data, 10000),
+ %% ct:log("Init renegotiation test",[]),
+ Kex1 = renegotiate_test(init, C),
+ %% ct:log("sending next ~p bytes",[byte_size(Data)]),
+ ok = ssh_connection:send(C, Ch1, Data, 10000),
+ %% ct:log("Finnish renegotiation test",[]),
+ renegotiate_test(Kex1, C),
+ %% ct:log("sending eof",[]),
+ ok = ssh_connection:send_eof(C, Ch1)
+ %%, ct:log("READY, sent ~p bytes",[2*byte_size(Data)])
+ end),
+
+ {eof,ReceivedData} =
+ loop_until(fun({eof,_}) -> true;
+ (_ ) -> false
+ end,
+ fun(Acc) ->
+ %%ct:log("Get more ~p",[ ExpectedSize-byte_size(Acc) ]),
+ receive
+ {ssh_cm, C, {eof,Ch}} when Ch==Ch1 ->
+ %% ct:log("eof received",[]),
+ {eof,Acc};
+
+ {ssh_cm, C, {data,Ch,0,B}} when Ch==Ch1,
+ is_binary(B) ->
+ %% ct:log("(1) Received ~p bytes (total ~p), missing ~p bytes",
+ %% [byte_size(B),
+ %% byte_size(B)+byte_size(Acc),
+ %% 2*byte_size(Data)-(byte_size(B)+byte_size(Acc))]),
+ ssh_connection:adjust_window(C, Ch1, byte_size(B)),
+ <<Acc/binary, B/binary>>
+ end
+ end,
+ <<>>),
+
+ ExpectedData = <<Data/binary, Data/binary>>,
+ case ReceivedData of
+ ExpectedData ->
+ %% ct:log("Correct data returned",[]),
+ %% receive close messages
+ loop_until(fun(Left) -> %% ct:log("Expect: ~p",[Left]),
+ Left == []
+ end,
+ fun([Next|Rest]) ->
+ receive
+ {ssh_cm,C,Next} -> Rest
+ end
+ end,
+ [%% Already received: {eof, Ch1},
+ {exit_status,Ch1,0},
+ {closed,Ch1}]
+ ),
+ ok;
+ _ when is_binary(ReceivedData) ->
+ ct:fail("~p bytes echoed but ~p expected", [byte_size(ReceivedData), 2*byte_size(Data)])
+ end.
+
+%%--------------------------------------------------------------------
+%% Utilities ---------------------------------------------------------
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%%
+%% A practical meta function
+%%
+loop_until(CondFun, DoFun, Acc) ->
+ case CondFun(Acc) of
+ true ->
+ Acc;
+ false ->
+ loop_until(CondFun, DoFun, DoFun(Acc))
+ end.
+
+%%--------------------------------------------------------------------
+%%
+%% Exec the Command in the docker. Add the arguments ExtraSshArg in the
+%% ssh command.
+%%
+%% If Expects is returned, then return 'ok', else return {fail,Msg}.
+%%
+exec_from_docker(Config, HostIP, HostPort, Command, Expects, ExtraSshArg) when is_binary(hd(Expects)),
+ is_list(Config) ->
+ {DockerIP,DockerPort} = ip_port(Config),
+ {ok,C} = ssh:connect(DockerIP, DockerPort,
+ [{user,?USER},
+ {password,?PASSWD},
+ {user_dir, new_dir(Config)},
+ {silently_accept_hosts,true},
+ {user_interaction,false}
+ ]),
+ R = exec_from_docker(C, HostIP, HostPort, Command, Expects, ExtraSshArg, Config),
+ ssh:close(C),
+ R.
+
+exec_from_docker(C, DestIP, DestPort, Command, Expects, ExtraSshArg, Config) when is_binary(hd(Expects)) ->
+ ExecCommand =
+ lists:concat(
+ ["sshpass -p ",?PASSWD," "
+ | case proplists:get_value(ssh_version,Config) of
+ "dropbear" ++ _ ->
+ ["dbclient -y -y -p ",DestPort," ",ExtraSshArg," ",iptoa(DestIP)," "];
+
+ _ -> %% OpenSSH or compatible
+ ["/buildroot/ssh/bin/ssh -o 'CheckHostIP=no' -o 'StrictHostKeyChecking=no' ",
+ ExtraSshArg," -p ",DestPort," ",iptoa(DestIP)," "]
+ end]) ++ Command,
+
+ case exec(C, ExecCommand) of
+ {ok,{ExitStatus,Result}} = R when ExitStatus == 0 ->
+ case binary:match(Result, Expects) of
+ nomatch ->
+ ct:log("Result of~n ~s~nis~n ~p",[ExecCommand,R]),
+ {fail, "Bad answer"};
+ _ ->
+ ok
+ end;
+ {ok,_} = R ->
+ ct:log("Result of~n ~s~nis~n ~p",[ExecCommand,R]),
+ {fail, "Exit status =/= 0"};
+ R ->
+ ct:log("Result of~n ~s~nis~n ~p",[ExecCommand,R]),
+ {fail, "Couldn't login to host"}
+ end.
+
+
+exec(C, Cmd) ->
+ %% ct:log("~s",[Cmd]),
+ {ok,Ch} = ssh_connection:session_channel(C, 10000),
+ success = ssh_connection:exec(C, Ch, Cmd, 10000),
+ result_of_exec(C, Ch).
+
+
+result_of_exec(C, Ch) ->
+ result_of_exec(C, Ch, undefined, <<>>).
+
+result_of_exec(C, Ch, ExitStatus, Acc) ->
+ receive
+ {ssh_cm,C,{closed,Ch}} ->
+ %%ct:log("CHAN ~p got *closed*",[Ch]),
+ {ok, {ExitStatus, Acc}};
+
+ {ssh_cm,C,{exit_status,Ch,ExStat}} when ExitStatus == undefined ->
+ %%ct:log("CHAN ~p got *exit status ~p*",[Ch,ExStat]),
+ result_of_exec(C, Ch, ExStat, Acc);
+
+ {ssh_cm,C,{data,Ch,_,Data}=_X} when ExitStatus == undefined ->
+ %%ct:log("CHAN ~p got ~p",[Ch,_X]),
+ result_of_exec(C, Ch, ExitStatus, <<Acc/binary, Data/binary>>);
+
+ _Other ->
+ %%ct:log("OTHER: ~p",[_Other]),
+ result_of_exec(C, Ch, ExitStatus, Acc)
+
+ after 5000 ->
+ ct:log("NO MORE, received so far:~n~s",[Acc]),
+ {error, timeout}
+ end.
+
+
+%%--------------------------------------------------------------------
+%%
+%% Loop through all {Tag,Alg} pairs in CommonAlgs, call DoTestFun(Tag,Alg) which
+%% returns one of {ok,C}, ok, or Other.
+%%
+%% The chk_all_algos returns 'ok' or {fail,FaledAlgosList}
+%%
+
+chk_all_algos(FunctionName, CommonAlgs, Config, DoTestFun) when is_function(DoTestFun,2) ->
+ ct:comment("~p algorithms",[length(CommonAlgs)]),
+ %% Check each algorithm
+ Failed =
+ lists:foldl(
+ fun({Tag,Alg}, FailedAlgos) ->
+ %% ct:log("Try ~p",[Alg]),
+ case DoTestFun(Tag,Alg) of
+ {ok,C} ->
+ ssh:close(C),
+ FailedAlgos;
+ ok ->
+ FailedAlgos;
+ Other ->
+ ct:log("FAILED! ~p ~p: ~p",[Tag,Alg,Other]),
+ [{Alg,Other}|FailedAlgos]
+ end
+ end, [], CommonAlgs),
+ ct:pal("~s", [format_result_table_use_all_algos(FunctionName, Config, CommonAlgs, Failed)]),
+ case Failed of
+ [] ->
+ ok;
+ _ ->
+ {fail, Failed}
+ end.
+
+
+
+%%%----------------------------------------------------------------
+%%%
+%%% Call all Funs as Fun() which returns 'ok', {ok,C} or Other.
+%%% do/1 returns 'ok' or the first encountered value that is not
+%%% successful.
+%%%
+
+do(Funs) ->
+ do(Funs, 1).
+
+do([Fun|Funs], N) ->
+ case Fun() of
+ ok ->
+ %% ct:log("Fun ~p ok",[N]),
+ do(Funs, N-1);
+ {ok,C} ->
+ %% ct:log("Fun ~p {ok,C}",[N]),
+ ssh:close(C),
+ do(Funs, N-1);
+ Other ->
+ ct:log("Fun ~p FAILED:~n~p",[N, Other]),
+ Other
+ end;
+
+do([], _) ->
+ %% ct:log("All Funs ok",[]),
+ ok.
+
+%%--------------------------------------------------------------------
+%%
+%% Functions to set up local and remote host's and user's keys and directories
+%%
+
+setup_local_hostdir(KeyAlg, Config) ->
+ setup_local_hostdir(KeyAlg, new_dir(Config), Config).
+setup_local_hostdir(KeyAlg, HostDir, Config) ->
+ {ok, {Priv,Publ}} = host_priv_pub_keys(Config, KeyAlg),
+ %% Local private and public key
+ DstFile = filename:join(HostDir, dst_filename(host,KeyAlg)),
+ ok = file:write_file(DstFile, Priv),
+ ok = file:write_file(DstFile++".pub", Publ),
+ HostDir.
+
+
+setup_remote_auth_keys_and_local_priv(KeyAlg, Config) ->
+ {IP,Port} = ip_port(Config),
+ setup_remote_auth_keys_and_local_priv(KeyAlg, IP, Port, new_dir(Config), Config).
+
+setup_remote_auth_keys_and_local_priv(KeyAlg, UserDir, Config) ->
+ {IP,Port} = ip_port(Config),
+ setup_remote_auth_keys_and_local_priv(KeyAlg, IP, Port, UserDir, Config).
+
+setup_remote_auth_keys_and_local_priv(KeyAlg, IP, Port, Config) ->
+ setup_remote_auth_keys_and_local_priv(KeyAlg, IP, Port, new_dir(Config), Config).
+
+setup_remote_auth_keys_and_local_priv(KeyAlg, IP, Port, UserDir, Config) ->
+ {ok, {Priv,Publ}} = user_priv_pub_keys(Config, KeyAlg),
+ %% Local private and public keys
+ DstFile = filename:join(UserDir, dst_filename(user,KeyAlg)),
+ ok = file:write_file(DstFile, Priv),
+ ok = file:write_file(DstFile++".pub", Publ),
+ %% Remote auth_methods with public key
+ {ok,Ch,Cc} = ssh_sftp:start_channel(IP, Port, [{user, ?USER },
+ {password, ?PASSWD },
+ {auth_methods, "password"},
+ {silently_accept_hosts,true},
+ {user_interaction,false}
+ ]),
+ _ = ssh_sftp:make_dir(Ch, ".ssh"),
+ ok = ssh_sftp:write_file(Ch, ".ssh/authorized_keys", Publ),
+ ok = ssh_sftp:write_file_info(Ch, ".ssh/authorized_keys", #file_info{mode=8#700}),
+ ok = ssh_sftp:write_file_info(Ch, ".ssh", #file_info{mode=8#700}),
+ ok = ssh_sftp:stop_channel(Ch),
+ ok = ssh:close(Cc),
+ UserDir.
+
+
+setup_remote_priv_and_local_auth_keys(KeyAlg, Config) ->
+ {IP,Port} = ip_port(Config),
+ setup_remote_priv_and_local_auth_keys(KeyAlg, IP, Port, new_dir(Config), Config).
+
+setup_remote_priv_and_local_auth_keys(KeyAlg, UserDir, Config) ->
+ {IP,Port} = ip_port(Config),
+ setup_remote_priv_and_local_auth_keys(KeyAlg, IP, Port, UserDir, Config).
+
+setup_remote_priv_and_local_auth_keys(KeyAlg, IP, Port, Config) ->
+ setup_remote_priv_and_local_auth_keys(KeyAlg, IP, Port, new_dir(Config), Config).
+
+setup_remote_priv_and_local_auth_keys(KeyAlg, IP, Port, UserDir, Config) ->
+ {ok, {Priv,Publ}} = user_priv_pub_keys(Config, KeyAlg),
+ %% Local auth_methods with public key
+ AuthKeyFile = filename:join(UserDir, "authorized_keys"),
+ ok = file:write_file(AuthKeyFile, Publ),
+ %% Remote private and public key
+ {ok,Ch,Cc} = ssh_sftp:start_channel(IP, Port, [{user, ?USER },
+ {password, ?PASSWD },
+ {auth_methods, "password"},
+ {silently_accept_hosts,true},
+ {user_interaction,false}
+ ]),
+ _ = ssh_sftp:make_dir(Ch, ".ssh"),
+ DstFile = filename:join(".ssh", dst_filename(user,KeyAlg)),
+ ok = ssh_sftp:write_file(Ch, DstFile, Priv),
+ ok = ssh_sftp:write_file_info(Ch, DstFile, #file_info{mode=8#700}),
+ ok = ssh_sftp:write_file(Ch, DstFile++".pub", Publ),
+ ok = ssh_sftp:write_file_info(Ch, ".ssh", #file_info{mode=8#700}),
+ ok = ssh_sftp:stop_channel(Ch),
+ ok = ssh:close(Cc),
+ UserDir.
+
+user_priv_pub_keys(Config, KeyAlg) -> priv_pub_keys("users_keys", user, Config, KeyAlg).
+host_priv_pub_keys(Config, KeyAlg) -> priv_pub_keys("host_keys", host, Config, KeyAlg).
+
+priv_pub_keys(KeySubDir, Type, Config, KeyAlg) ->
+ KeyDir = filename:join(proplists:get_value(data_dir,Config), KeySubDir),
+ {ok,Priv} = file:read_file(filename:join(KeyDir,src_filename(Type,KeyAlg))),
+ {ok,Publ} = file:read_file(filename:join(KeyDir,src_filename(Type,KeyAlg)++".pub")),
+ {ok, {Priv,Publ}}.
+
+
+%%%---------------- The default filenames
+src_filename(user, 'ssh-rsa' ) -> "id_rsa";
+src_filename(user, 'rsa-sha2-256' ) -> "id_rsa";
+src_filename(user, 'rsa-sha2-512' ) -> "id_rsa";
+src_filename(user, 'ssh-dss' ) -> "id_dsa";
+src_filename(user, 'ecdsa-sha2-nistp256') -> "id_ecdsa256";
+src_filename(user, 'ecdsa-sha2-nistp384') -> "id_ecdsa384";
+src_filename(user, 'ecdsa-sha2-nistp521') -> "id_ecdsa521";
+src_filename(host, 'ssh-rsa' ) -> "ssh_host_rsa_key";
+src_filename(host, 'rsa-sha2-256' ) -> "ssh_host_rsa_key";
+src_filename(host, 'rsa-sha2-512' ) -> "ssh_host_rsa_key";
+src_filename(host, 'ssh-dss' ) -> "ssh_host_dsa_key";
+src_filename(host, 'ecdsa-sha2-nistp256') -> "ssh_host_ecdsa_key256";
+src_filename(host, 'ecdsa-sha2-nistp384') -> "ssh_host_ecdsa_key384";
+src_filename(host, 'ecdsa-sha2-nistp521') -> "ssh_host_ecdsa_key521".
+
+dst_filename(user, 'ssh-rsa' ) -> "id_rsa";
+dst_filename(user, 'rsa-sha2-256' ) -> "id_rsa";
+dst_filename(user, 'rsa-sha2-512' ) -> "id_rsa";
+dst_filename(user, 'ssh-dss' ) -> "id_dsa";
+dst_filename(user, 'ecdsa-sha2-nistp256') -> "id_ecdsa";
+dst_filename(user, 'ecdsa-sha2-nistp384') -> "id_ecdsa";
+dst_filename(user, 'ecdsa-sha2-nistp521') -> "id_ecdsa";
+dst_filename(host, 'ssh-rsa' ) -> "ssh_host_rsa_key";
+dst_filename(host, 'rsa-sha2-256' ) -> "ssh_host_rsa_key";
+dst_filename(host, 'rsa-sha2-512' ) -> "ssh_host_rsa_key";
+dst_filename(host, 'ssh-dss' ) -> "ssh_host_dsa_key";
+dst_filename(host, 'ecdsa-sha2-nistp256') -> "ssh_host_ecdsa_key";
+dst_filename(host, 'ecdsa-sha2-nistp384') -> "ssh_host_ecdsa_key";
+dst_filename(host, 'ecdsa-sha2-nistp521') -> "ssh_host_ecdsa_key".
+
+
+%%--------------------------------------------------------------------
+%%
+%% Format the result table for chk_all_algos/4
+%%
+format_result_table_use_all_algos(FunctionName, Config, CommonAlgs, Failed) ->
+ %% Write a nice table with the result
+ AlgHead = 'Algorithm',
+ AlgWidth = lists:max([length(atom_to_list(A)) || {_,A} <- CommonAlgs]),
+ {ResultTable,_} =
+ lists:mapfoldl(
+ fun({T,A}, Tprev) ->
+ Tag = case T of
+ Tprev -> "";
+ _ -> io_lib:format('~s~n',[T])
+ end,
+ {io_lib:format('~s ~*s ~s~n',
+ [Tag, -AlgWidth, A,
+ case proplists:get_value(A,Failed) of
+ undefined -> "(ok)";
+ Err -> io_lib:format("<<<< FAIL <<<< ~p",[Err])
+ end]),
+ T}
+ end, undefined, CommonAlgs),
+
+ Vssh = proplists:get_value(ssh_version,Config,""),
+ io_lib:format("~nResults of ~p, Peer version: ~s~n~n"
+ "Tag ~*s Result~n"
+ "=====~*..=s=======~n~s"
+ ,[FunctionName, Vssh,
+ -AlgWidth, AlgHead,
+ AlgWidth, "", ResultTable]).
+
+%%--------------------------------------------------------------------
+%%
+%% Docker handling: start_docker/1 and stop_docker/1
+%%
+start_docker(Ver) ->
+ Cmnd = lists:concat(["docker run -itd --rm -p 1234 ",?DOCKER_PFX,":",Ver]),
+ Id0 = os:cmd(Cmnd),
+ ct:log("Ver = ~p, Cmnd ~p~n-> ~p",[Ver,Cmnd,Id0]),
+ case is_docker_sha(Id0) of
+ true ->
+ Id = hd(string:tokens(Id0, "\n")),
+ IP = ip(Id),
+ Port = 1234,
+ {ok, {Ver,{IP,Port},Id}};
+ false ->
+ throw(cant_start_docker)
+ end.
+
+
+stop_docker({_Ver,_,Id}) ->
+ Cmnd = lists:concat(["docker kill ",Id]),
+ os:cmd(Cmnd).
+
+is_docker_sha(L) ->
+ lists:all(fun(C) when $a =< C,C =< $z -> true;
+ (C) when $0 =< C,C =< $9 -> true;
+ ($\n) -> true;
+ (_) -> false
+ end, L).
+
+%%--------------------------------------------------------------------
+%%
+%% Misc docker info functions
+
+ip_port(Config) ->
+ {_Ver,{IP,Port},_} = proplists:get_value(id,Config),
+ {IP,Port}.
+
+port_mapped_to(Id) ->
+ Cmnd = lists:concat(["docker ps --format \"{{.Ports}}\" --filter id=",Id]),
+ [_, PortStr | _] = string:tokens(os:cmd(Cmnd), ":->/"),
+ list_to_integer(PortStr).
+
+ip(Id) ->
+ Cmnd = lists:concat(["docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ",
+ Id]),
+ IPstr0 = os:cmd(Cmnd),
+ ct:log("Cmnd ~p~n-> ~p",[Cmnd,IPstr0]),
+ IPstr = hd(string:tokens(IPstr0, "\n")),
+ {ok,IP} = inet:parse_address(IPstr),
+ IP.
+
+%%--------------------------------------------------------------------
+%%
+%% Normalize the host returned from ssh_test_lib
+
+iptoa({0,0,0,0}) -> inet_parse:ntoa(host_ip());
+iptoa(IP) -> inet_parse:ntoa(IP).
+
+host_ip() ->
+ {ok,Name} = inet:gethostname(),
+ {ok,#hostent{h_addr_list = [IP|_]}} = inet_res:gethostbyname(Name),
+ IP.
+
+%%--------------------------------------------------------------------
+%%
+%% Create a new fresh directory or clear an existing one
+%%
+
+new_dir(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ SubDirName = integer_to_list(erlang:system_time()),
+ Dir = filename:join(PrivDir, SubDirName),
+ case file:read_file_info(Dir) of
+ {error,enoent} ->
+ ok = file:make_dir(Dir),
+ Dir;
+ _ ->
+ timer:sleep(25),
+ new_dir(Config)
+ end.
+
+clear_dir(Dir) ->
+ delete_all_contents(Dir),
+ {ok,[]} = file:list_dir(Dir),
+ Dir.
+
+delete_all_contents(Dir) ->
+ {ok,Fs} = file:list_dir(Dir),
+ lists:map(fun(F0) ->
+ F = filename:join(Dir, F0),
+ case filelib:is_file(F) of
+ true ->
+ file:delete(F);
+ false ->
+ case filelib:is_dir(F) of
+ true ->
+ delete_all_contents(F),
+ file:del_dir(F);
+ false ->
+ ct:log("Neither file nor dir: ~p",[F])
+ end
+ end
+ end, Fs).
+
+%%--------------------------------------------------------------------
+%%
+%% Find the intersection of algoritms for otp ssh and the docker ssh.
+%% Returns {ok, ServerHello, Server, ClientHello, Client} where Server are the algorithms common
+%% with the docker server and analogous for Client.
+%%
+%% Client may be undefined if no usable client is found.
+%%
+%% Both Server and Client are lists of {Tag,AlgName}.
+%%
+
+common_algs(Config, IP, Port) ->
+ case remote_server_algs(IP, Port) of
+ {ok, {ServerHello, RemoteServerKexInit}} ->
+ RemoteServerAlgs = kexint_msg2default_algorithms(RemoteServerKexInit),
+ Server = find_common_algs(RemoteServerAlgs,
+ use_algorithms(ServerHello)),
+ ct:log("Remote server:~n~p~n~p",[ServerHello, RemoteServerAlgs]),
+ case remote_client_algs(Config) of
+ {ok,{ClientHello,RemoteClientKexInit}} ->
+ RemoteClientAlgs = kexint_msg2default_algorithms(RemoteClientKexInit),
+ Client = find_common_algs(RemoteClientAlgs,
+ use_algorithms(ClientHello)),
+ ct:log("Remote client:~n~p~n~p",[ClientHello, RemoteClientAlgs]),
+ {ok, ServerHello, Server, ClientHello, Client};
+ {error,_} =TO ->
+ ct:log("Remote client algs can't be found: ~p",[TO]),
+ {ok, ServerHello, Server, undefined, undefined};
+ Other ->
+ Other
+ end;
+ Other ->
+ Other
+ end.
+
+
+chk_hellos(Hs, Str) ->
+ lists:foldl(
+ fun(H, Acc) ->
+ try binary:split(H, <<"-">>, [global])
+ of
+ %% [<<"SSH">>,<<"2.0">>|_] ->
+ %% Acc;
+ [<<"SSH">>,OldVer = <<"1.",_/binary>>|_] ->
+ io_lib:format("~s, Old SSH ver ~s",[Acc,OldVer]);
+ _ ->
+ Acc
+ catch
+ _:_ ->
+ Acc
+ end
+ end, Str, Hs).
+
+
+find_common_algs(Remote, Local) ->
+ [{T,V} || {T,Vs} <- ssh_test_lib:extract_algos(
+ ssh_test_lib:intersection(Remote,
+ Local)),
+ V <- Vs].
+
+
+use_algorithms(RemoteHelloBin) ->
+ MyAlgos = ssh:chk_algos_opts(
+ [{modify_algorithms,
+ [{append,
+ [{kex,['diffie-hellman-group1-sha1']}
+ ]}
+ ]}
+ ]),
+ ssh_transport:adjust_algs_for_peer_version(binary_to_list(RemoteHelloBin)++"\r\n",
+ MyAlgos).
+
+kexint_msg2default_algorithms(#ssh_msg_kexinit{kex_algorithms = Kex,
+ server_host_key_algorithms = PubKey,
+ encryption_algorithms_client_to_server = CipherC2S,
+ encryption_algorithms_server_to_client = CipherS2C,
+ mac_algorithms_client_to_server = MacC2S,
+ mac_algorithms_server_to_client = MacS2C,
+ compression_algorithms_client_to_server = CompC2S,
+ compression_algorithms_server_to_client = CompS2C
+ }) ->
+ [{kex, ssh_test_lib:to_atoms(Kex)},
+ {public_key, ssh_test_lib:to_atoms(PubKey)},
+ {cipher, [{client2server,ssh_test_lib:to_atoms(CipherC2S)},
+ {server2client,ssh_test_lib:to_atoms(CipherS2C)}]},
+ {mac, [{client2server,ssh_test_lib:to_atoms(MacC2S)},
+ {server2client,ssh_test_lib:to_atoms(MacS2C)}]},
+ {compression, [{client2server,ssh_test_lib:to_atoms(CompC2S)},
+ {server2client,ssh_test_lib:to_atoms(CompS2C)}]}].
+
+
+%%--------------------------------------------------------------------
+%%
+%% Find the algorithms supported by the remote server
+%%
+%% Connect with tcp to the server, send a hello and read the returned
+%% server hello and kexinit message.
+%%
+remote_server_algs(IP, Port) ->
+ case try_gen_tcp_connect(IP, Port, 5) of
+ {ok,S} ->
+ ok = gen_tcp:send(S, "SSH-2.0-CheckAlgs\r\n"),
+ receive_hello(S);
+ {error,Error} ->
+ {error,Error}
+ end.
+
+try_gen_tcp_connect(IP, Port, N) when N>0 ->
+ case gen_tcp:connect(IP, Port, [binary]) of
+ {ok,S} ->
+ {ok,S};
+ {error,_Error} when N>1 ->
+ receive after 1000 -> ok end,
+ try_gen_tcp_connect(IP, Port, N-1);
+ {error,Error} ->
+ {error,Error}
+ end;
+try_gen_tcp_connect(_, _, _) ->
+ {error, "No contact"}.
+
+
+%%--------------------------------------------------------------------
+%%
+%% Find the algorithms supported by the remote client
+%%
+%% Set up a fake ssh server and make the remote client connect to it. Use
+%% hello message and the kexinit message.
+%%
+remote_client_algs(Config) ->
+ Parent = self(),
+ Ref = make_ref(),
+ spawn(
+ fun() ->
+ {ok,Sl} = gen_tcp:listen(0, [binary]),
+ {ok,{IP,Port}} = inet:sockname(Sl),
+ Parent ! {addr,Ref,IP,Port},
+ {ok,S} = gen_tcp:accept(Sl),
+ ok = gen_tcp:send(S, "SSH-2.0-CheckAlgs\r\n"),
+ Parent ! {Ref,receive_hello(S)}
+ end),
+ receive
+ {addr,Ref,IP,Port} ->
+ spawn(fun() ->
+ exec_from_docker(Config, IP, Port,
+ "howdy.\r\n",
+ [<<"howdy">>],
+ "")
+ end),
+ receive
+ {Ref, Result} ->
+ Result
+ after 5000 ->
+ {error, {timeout,2}}
+ end
+ after 5000 ->
+ {error, {timeout,1}}
+ end.
+
+
+%%% Receive a few packets from the remote server or client and find what is supported:
+
+receive_hello(S) ->
+ try
+ receive_hello(S, <<>>)
+ of
+ Result ->
+ Result
+ catch
+ Class:Error ->
+ ST = erlang:get_stacktrace(),
+ {error, {Class,Error,ST}}
+ end.
+
+
+receive_hello(S, Ack) ->
+ %% The Ack is to collect bytes until the full message is received
+ receive
+ {tcp, S, Bin0} when is_binary(Bin0) ->
+ case binary:split(<<Ack/binary, Bin0/binary>>, [<<"\r\n">>,<<"\r">>,<<"\n">>]) of
+ [Hello = <<"SSH-2.0-",_/binary>>, NextPacket] ->
+ %% ct:log("Got 2.0 hello (~p), ~p bytes to next msg",[Hello,size(NextPacket)]),
+ {ok, {Hello, receive_kexinit(S, NextPacket)}};
+
+ [Hello = <<"SSH-1.99-",_/binary>>, NextPacket] ->
+ %% ct:log("Got 1.99 hello (~p), ~p bytes to next msg",[Hello,size(NextPacket)]),
+ {ok, {Hello, receive_kexinit(S, NextPacket)}};
+
+ [Bin] when size(Bin) < 256 ->
+ %% ct:log("Got part of hello (~p chars):~n~s~n~s",[size(Bin),Bin,
+ %% [io_lib:format('~2.16.0b ',[C])
+ %% || C <- binary_to_list(Bin0)
+ %% ]
+ %% ]),
+ receive_hello(S, Bin0);
+
+ _ ->
+ ct:log("Bad hello string (line ~p, ~p chars):~n~s~n~s",[?LINE,size(Bin0),Bin0,
+ [io_lib:format('~2.16.0b ',[C])
+ || C <- binary_to_list(Bin0)
+ ]
+ ]),
+ ct:fail("Bad hello string received")
+ end;
+ Other ->
+ ct:log("Bad hello string (line ~p):~n~p",[?LINE,Other]),
+ ct:fail("Bad hello string received")
+
+ after 10000 ->
+ ct:log("Timeout waiting for hello!~n~s",[Ack]),
+ throw(timeout)
+ end.
+
+
+receive_kexinit(_S, <<PacketLen:32, PaddingLen:8, PayloadAndPadding/binary>>)
+ when PacketLen < 5000, % heuristic max len to stop huge attempts if packet decodeing get out of sync
+ size(PayloadAndPadding) >= (PacketLen-1) % Need more bytes?
+ ->
+ ct:log("Has all ~p packet bytes",[PacketLen]),
+ PayloadLen = PacketLen - PaddingLen - 1,
+ <<Payload:PayloadLen/binary, _Padding:PaddingLen/binary>> = PayloadAndPadding,
+ ssh_message:decode(Payload);
+
+receive_kexinit(S, Ack) ->
+ ct:log("Has ~p bytes, need more",[size(Ack)]),
+ receive
+ {tcp, S, Bin0} when is_binary(Bin0) ->
+ receive_kexinit(S, <<Ack/binary, Bin0/binary>>);
+ Other ->
+ ct:log("Bad hello string (line ~p):~n~p",[?LINE,Other]),
+ ct:fail("Bad hello string received")
+
+ after 10000 ->
+ ct:log("Timeout waiting for kexinit!~n~s",[Ack]),
+ throw(timeout)
+ end.
+
+%%%----------------------------------------------------------------
+%%% Test of sftp from the OpenSSH client side
+%%%
+
+sftp_tests_erl_server(Config, ServerIP, ServerPort, ServerRootDir, UserDir) ->
+ try
+ Cmnds = prepare_local_directory(ServerRootDir),
+ call_sftp_in_docker(Config, ServerIP, ServerPort, Cmnds, UserDir),
+ check_local_directory(ServerRootDir)
+ catch
+ Class:Error ->
+ ST = erlang:get_stacktrace(),
+ {error, {Class,Error,ST}}
+ end.
+
+
+prepare_local_directory(ServerRootDir) ->
+ file:write_file(filename:join(ServerRootDir,"tst1"),
+ <<"Some test text">>
+ ),
+ ["get tst1",
+ "put tst1 tst2",
+ "put tst1 tst3",
+ "rename tst1 ex_tst1",
+ "rm tst3",
+ "mkdir mydir",
+ "cd mydir",
+ "put tst1 file_1",
+ "put tst1 unreadable_file",
+ "chmod 222 unreadable_file",
+ "exit"].
+
+check_local_directory(ServerRootDir) ->
+ case lists:sort(ok(file:list_dir(ServerRootDir)) -- [".",".."]) of
+ ["ex_tst1","mydir","tst2"] ->
+ {ok,Expect} = file:read_file(filename:join(ServerRootDir,"ex_tst1")),
+ case file:read_file(filename:join(ServerRootDir,"tst2")) of
+ {ok,Expect} ->
+ case lists:sort(ok(file:list_dir(filename:join(ServerRootDir,"mydir"))) -- [".",".."]) of
+ ["file_1","unreadable_file"] ->
+ case file:read_file(filename:join([ServerRootDir,"mydir","file_1"])) of
+ {ok,Expect} ->
+ case file:read_file(filename:join([ServerRootDir,"mydir","unreadable_file"])) of
+ {error,_} ->
+ ok;
+ {ok,_} ->
+ {error, {could_read_unreadable,"mydir/unreadable_file"}}
+ end;
+ {ok,Other} ->
+ ct:log("file_1:~n~s~nExpected:~n~s",[Other,Expect]),
+ {error, {bad_contents_in_file,"mydir/file_1"}}
+ end;
+ Other ->
+ ct:log("Directory ~s~n~p",[filename:join(ServerRootDir,"mydir"),Other]),
+ {error,{bad_dir_contents,"mydir"}}
+ end;
+ {ok,Other} ->
+ ct:log("tst2:~n~s~nExpected:~n~s",[Other,Expect]),
+ {error, {bad_contents_in_file,"tst2"}}
+ end;
+ ["tst1"] ->
+ {error,{missing_file,"tst2"}};
+ Other ->
+ ct:log("Directory ~s~n~p",[ServerRootDir,Other]),
+ {error,{bad_dir_contents,"/"}}
+ end.
+
+call_sftp_in_docker(Config, ServerIP, ServerPort, Cmnds, UserDir) ->
+ {DockerIP,DockerPort} = ip_port(Config),
+ {ok,C} = ssh:connect(DockerIP, DockerPort,
+ [{user,?USER},
+ {password,?PASSWD},
+ {user_dir, UserDir},
+ {silently_accept_hosts,true},
+ {user_interaction,false}
+ ]),
+
+ %% Make commands for "expect" in the docker:
+ PreExpectCmnds = ["spawn /buildroot/ssh/bin/sftp -oPort="++integer_to_list(ServerPort)++
+ " -oCheckHostIP=no -oStrictHostKeyChecking=no " ++
+ iptoa(ServerIP)++"\n"
+ ],
+ PostExpectCmnds= [],
+ ExpectCmnds =
+ PreExpectCmnds ++
+ ["expect \"sftp>\" {send \""++Cmnd++"\n\"}\n" || Cmnd <- Cmnds] ++
+ PostExpectCmnds,
+
+ %% Make an commands file in the docker
+ {ok,Ch} = ssh_sftp:start_channel(C, [{timeout,10000}]),
+ ok = ssh_sftp:write_file(Ch, "commands", erlang:iolist_to_binary(ExpectCmnds)),
+ ok = ssh_sftp:stop_channel(Ch),
+
+ %% Call expect in the docker
+ {ok, Ch1} = ssh_connection:session_channel(C, infinity),
+ Kex1 = renegotiate_test(init, C),
+ success = ssh_connection:exec(C, Ch1, "expect commands", infinity),
+
+ renegotiate_test(Kex1, C),
+ recv_log_msgs(C, Ch1),
+
+ %% Done.
+ ssh:close(C).
+
+recv_log_msgs(C, Ch) ->
+ receive
+ {ssh_cm,C,{closed,Ch}} ->
+ %% ct:log("Channel closed ~p",[{closed,1}]),
+ ok;
+ {ssh_cm,C,{data,Ch,1,Msg}} ->
+ ct:log("*** ERROR from docker:~n~s",[Msg]),
+ recv_log_msgs(C, Ch);
+ {ssh_cm,C,_Msg} ->
+ %% ct:log("Got ~p",[_Msg]),
+ recv_log_msgs(C, Ch)
+ end.
+
+%%%----------------------------------------------------------------
+%%%----------------------------------------------------------------
+%%%
+%%% Tests from the Erlang client side
+%%%
+%%%----------------------------------------------------------------
+%%%----------------------------------------------------------------
+test_erl_client_reneg({ok,C}, Spec) ->
+ %% Start the test processes on the connection C:
+ Parent = self(),
+ Pids = [spawn(
+ fun() ->
+ Parent ! {self(), TestType, Id, one_test_erl_client(TestType,Id,C)}
+ end
+ )
+ || {TestType,N} <- Spec,
+ Id <- lists:seq(1,N)],
+
+ Kex1 = renegotiate_test(init, C),
+
+ %% Collect the results:
+ case lists:filter(
+ fun(R) -> R=/=ok end,
+ [receive
+ {Pid,_TestType,_Id,ok} ->
+ %% ct:log("Test ~p:~p passed!", [_TestType,_Id]),
+ ok;
+ {Pid,TestType,Id,OtherResult} ->
+ ct:log("~p:~p ~p ~p~n~p",[?MODULE,?LINE,TestType,Id,OtherResult]),
+ {error,TestType,Id}
+ end || Pid <- Pids])
+ of
+ [] ->
+ renegotiate_test(Kex1, C),
+ {ok,C};
+ Other ->
+ renegotiate_test(Kex1, C),
+ Other
+ end;
+
+test_erl_client_reneg(Error, _) ->
+ Error.
+
+
+one_test_erl_client(exec, Id, C) ->
+ {ok, Ch} = ssh_connection:session_channel(C, infinity),
+ success = ssh_connection:exec(C, Ch, "echo Hi there", 5000),
+ case loop_until(fun({eof,_}) -> true;
+ (_ ) -> false
+ end,
+ fun(Acc) ->
+ receive
+ {ssh_cm, C, {eof,Ch}} ->
+ {eof,Acc};
+ {ssh_cm, C, {data,Ch,0,B}} when is_binary(B) ->
+ <<Acc/binary, B/binary>>
+ end
+ end,
+ <<>>) of
+ {eof,<<"Hi there\n">>} ->
+ ok;
+ Other ->
+ ct:pal("exec Got other ~p", [Other]),
+ {error, {exec,Id,bad_msg,Other,undefined}}
+ end;
+
+one_test_erl_client(no_subsyst, Id, C) ->
+ {ok, Ch} = ssh_connection:session_channel(C, infinity),
+ case ssh_connection:subsystem(C, Ch, "foo", infinity) of
+ failure ->
+ ok;
+ Other ->
+ ct:pal("no_subsyst Got other ~p", [Other]),
+ {error, {no_subsyst,Id,bad_ret,Other,undefined}}
+ end;
+
+one_test_erl_client(setenv, Id, C) ->
+ {ok, Ch} = ssh_connection:session_channel(C, infinity),
+ Var = "ENV_TEST",
+ Value = lists:concat(["env_test_",Id,"_",erlang:system_time()]),
+ Env = case ssh_connection:setenv(C, Ch, Var, Value, infinity) of
+ success -> binary_to_list(Value++"\n");
+ failure -> <<"\n">>
+ end,
+ success = ssh_connection:exec(C, Ch, "echo $"++Var, 5000),
+ case loop_until(fun({eof,_}) -> true;
+ (_ ) -> false
+ end,
+ fun(Acc) ->
+ receive
+ {ssh_cm, C, {eof,Ch}} ->
+ {eof,Acc};
+ {ssh_cm, C, {data,Ch,0,B}} when is_binary(B) ->
+ <<Acc/binary, B/binary>>
+ end
+ end,
+ <<>>) of
+ {eof,Env} ->
+ ok;
+ Other ->
+ ct:pal("setenv Got other ~p", [Other]),
+ {error, {setenv,Id,bad_msg,Other,undefined}}
+ end;
+
+one_test_erl_client(SFTP, Id, C) when SFTP==sftp ; SFTP==sftp_async ->
+ try
+ {ok,Ch} = ssh_sftp:start_channel(C, [{timeout,10000}]),
+ %% A new fresh name of a new file tree:
+ RootDir = lists:concat(["r_",Id,"_",erlang:system_time()]),
+ %% Check that it does not exist:
+ false = lists:member(RootDir, ok(ssh_sftp:list_dir(Ch, "."))),
+ %% Create it:
+ ok = ssh_sftp:make_dir(Ch, RootDir),
+ {ok, #file_info{type=directory, access=read_write}} = ssh_sftp:read_file_info(Ch, RootDir),
+ R = do_sftp_tests_erl_client(SFTP, C, Ch, Id, RootDir),
+ catch ssh_sftp:stop_channel(Ch),
+ R
+ catch
+ Class:Error ->
+ ST = erlang:get_stacktrace(),
+ {error, {SFTP,Id,Class,Error,ST}}
+ end.
+
+
+
+do_sftp_tests_erl_client(sftp_async, _C, Ch, _Id, RootDir) ->
+ FileName1 = "boring_name",
+ F1 = filename:join(RootDir, FileName1),
+ %% Open a new handle and start writing:
+ {ok,Handle1} = ssh_sftp:open(Ch, F1, [write,binary]),
+ {async,Aref1} = ssh_sftp:awrite(Ch, Handle1, <<0:250000/unsigned-unit:8>>),
+ wait_for_async_result(Aref1);
+
+do_sftp_tests_erl_client(sftp, _C, Ch, _Id, RootDir) ->
+ FileName0 = "f0",
+ F0 = filename:join(RootDir, FileName0),
+
+ %% Create and write a file:
+ ok = ssh_sftp:write_file(Ch,
+ F0 = filename:join(RootDir, FileName0),
+ Data0 = mkbin(1234,240)),
+ {ok,Data0} = ssh_sftp:read_file(Ch, F0),
+ {ok, #file_info{type=regular, access=read_write, size=1234}} = ssh_sftp:read_file_info(Ch, F0),
+
+ %% Re-write:
+ {ok,Handle0} = ssh_sftp:open(Ch, F0, [write,read,binary]),
+ ok = ssh_sftp:pwrite(Ch, Handle0, 16, Data0_1=mkbin(10,255)),
+
+ <<B1:16/binary, _:10/binary, B2:(1234-26)/binary>> = Data0,
+ FileContents = <<B1:16/binary, Data0_1:10/binary, B2:(1234-26)/binary>>,
+
+ <<_:1/binary, Part:25/binary, _/binary>> = FileContents,
+ {ok, Part} = ssh_sftp:pread(Ch, Handle0, 1, 25),
+
+ %% Check:
+ {ok, FileContents} = ssh_sftp:pread(Ch, Handle0, 0, 1234),
+ ok = ssh_sftp:close(Ch, Handle0),
+
+ %% Check in another way:
+ {ok, FileContents} = ssh_sftp:read_file(Ch, F0),
+
+ %% Remove write access rights and check that it can't be written:
+ ok = ssh_sftp:write_file_info(Ch, F0, #file_info{mode=8#400}), %read}),
+ {ok, #file_info{type=regular, access=read}} = ssh_sftp:read_file_info(Ch, F0),
+ {error,permission_denied} = ssh_sftp:write_file(Ch, F0, mkbin(10,14)),
+
+ %% Test deletion of file and dir:
+ [FileName0] = ok(ssh_sftp:list_dir(Ch, RootDir)) -- [".", ".."],
+ ok = ssh_sftp:delete(Ch, F0),
+ [] = ok(ssh_sftp:list_dir(Ch, RootDir)) -- [".", ".."],
+ ok = ssh_sftp:del_dir(Ch, RootDir),
+ false = lists:member(RootDir, ok(ssh_sftp:list_dir(Ch, "."))),
+ ok.
+
+
+wait_for_async_result(Aref) ->
+ receive
+ {async_reply, Aref, Result} ->
+ Result
+ after
+ 60000 ->
+ timeout
+ end.
+
+
+mkbin(Size, Byte) ->
+ list_to_binary(lists:duplicate(Size,Byte)).
+
+ok({ok,X}) -> X.
+
+%%%----------------------------------------------------------------
+renegotiate_test(init, ConnectionRef) ->
+ Kex1 = ssh_test_lib:get_kex_init(ConnectionRef),
+ ssh_connection_handler:renegotiate(ConnectionRef),
+ %%ct:log("Renegotiate test initiated!",[]),
+ Kex1;
+
+renegotiate_test(Kex1, ConnectionRef) ->
+ case ssh_test_lib:get_kex_init(ConnectionRef) of
+ Kex1 ->
+ ct:log("Renegotiate test failed, Kex1 == Kex2!",[]),
+ error(renegotiate_failed);
+ _ ->
+ %% ct:log("Renegotiate test passed!",[]),
+ ok
+ end.
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-base-image b/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-base-image
new file mode 100755
index 0000000000..1cb7bf33e1
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-base-image
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+UBUNTU_VER=${1:-16.04}
+
+USER=sshtester
+PWD=foobar
+
+docker build \
+ -t ubuntubuildbase \
+ --build-arg https_proxy=$HTTPS_PROXY \
+ --build-arg http_proxy=$HTTP_PROXY \
+ - <<EOF
+
+ FROM ubuntu:$UBUNTU_VER
+ WORKDIR /buildroot
+
+ # Prepare for installing OpenSSH
+ RUN apt-get update
+ RUN apt-get upgrade -y
+ RUN apt-get -y install apt-utils
+ RUN apt-get -y install build-essential zlib1g-dev
+ RUN apt-get -y install sudo iputils-ping tcptraceroute net-tools
+ RUN apt-get -y install sshpass expect
+ RUN apt-get -y install libpam0g-dev
+
+ # A user for the tests
+ RUN (echo $PWD; echo $PWD; echo; echo; echo; echo; echo; echo ) | adduser $USER
+ RUN adduser $USER sudo
+
+ # Prepare the privsep preauth environment for openssh
+ RUN mkdir -p /var/empty
+ RUN chown root:sys /var/empty
+ RUN chmod 755 /var/empty
+ RUN groupadd -f sshd
+ RUN ls /bin/false
+ RUN id -u sshd 2> /dev/null || useradd -g sshd -c 'sshd privsep' -d /var/empty -s /bin/false sshd
+
+EOF
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-dropbear-ssh b/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-dropbear-ssh
new file mode 100755
index 0000000000..85973081d0
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-dropbear-ssh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+# ./create-dropbear-ssh
+
+# This way of fetching the tar-file separate from the docker commands makes
+# http-proxy handling way easier. The wget command handles the $https_proxy
+# variable while the docker command must have /etc/docker/something changed
+# and the docker server restarted. That is not possible without root access.
+
+# Make a Dockerfile. This method simplifies env variable handling considerably:
+cat - > TempDockerFile <<EOF
+
+ FROM ubuntubuildbase
+
+ WORKDIR /buildroot
+
+ RUN apt-get -y update
+ RUN apt-get -y upgrade
+ RUN apt-get -y install openssh-sftp-server
+%% RUN echo 81 | apt-get -y install dropbear
+
+EOF
+
+# Build the image:
+docker build -t ssh_compat_suite-ssh-dropbear -f ./TempDockerFile .
+
+# Cleaning
+rm -fr ./TempDockerFile $TMP
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-dropbear-ssh-run b/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-dropbear-ssh-run
new file mode 100755
index 0000000000..d98c0cfaa3
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-dropbear-ssh-run
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# ./create-dropbear-ssh-run
+
+VER=v2016.72
+
+# This way of fetching the tar-file separate from the docker commands makes
+# http-proxy handling way easier. The wget command handles the $https_proxy
+# variable while the docker command must have /etc/docker/something changed
+# and the docker server restarted. That is not possible without root access.
+
+# Make a Dockerfile. This method simplifies env variable handling considerably:
+cat - > TempDockerFile <<EOF
+
+ FROM ssh_compat_suite-ssh-dropbear-installed:${VER}
+
+ WORKDIR /buildroot
+
+ CMD dropbear -F -p 1234
+
+EOF
+
+# Build the image:
+docker build -t ssh_compat_suite-ssh:dropbear${VER} -f ./TempDockerFile .
+
+# Cleaning
+rm -fr ./TempDockerFile $TMP
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-ssh-image b/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-ssh-image
new file mode 100755
index 0000000000..2e08408841
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-ssh-image
@@ -0,0 +1,72 @@
+#!/bin/sh
+
+# ./create-image openssh 7.3p1 openssl 1.0.2m
+
+set -x
+
+case $1 in
+ openssh)
+ FAMssh=openssh
+ VERssh=$2
+ PFX=https://ftp.eu.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-
+ SFX=.tar.gz
+ TMP=tmp.tar.gz
+ ;;
+ *)
+ echo "Unsupported: $1"
+ exit
+esac
+
+FAMssl=$3
+VERssl=$4
+
+VER=${FAMssh}${VERssh}-${FAMssl}${VERssl}
+
+# This way of fetching the tar-file separate from the docker commands makes
+# http-proxy handling way easier. The wget command handles the $https_proxy
+# variable while the docker command must have /etc/docker/something changed
+# and the docker server restarted. That is not possible without root access.
+
+# Make a Dockerfile. This method simplifies env variable handling considerably:
+cat - > TempDockerFile <<EOF
+
+ FROM ssh_compat_suite-${FAMssl}:${VERssl}
+
+ LABEL openssh-version=${VER}
+
+ WORKDIR /buildroot
+
+ COPY ${TMP} .
+ RUN tar xf ${TMP}
+
+ # Build and install
+
+ WORKDIR ${FAMssh}-${VERssh}
+
+ # Probably VERY OpenSSH dependent...:
+ RUN ./configure --without-pie \
+ --prefix=/buildroot/ssh \
+ --with-ssl-dir=/buildroot/ssl \
+ --with-pam \
+ LDFLAGS=-Wl,-R/buildroot/ssl/lib
+ RUN make
+ RUN make install
+ RUN echo UsePAM yes >> /buildroot/ssh/etc/sshd_config
+
+ RUN echo Built ${VER}
+
+ # Start the daemon, but keep it in foreground to avoid killing the container
+ CMD /buildroot/ssh/sbin/sshd -D -p 1234
+
+EOF
+
+# Fetch the tar file. This could be done in an "ADD ..." in the Dockerfile,
+# but then we hit the proxy problem...
+wget -O $TMP $PFX$VERssh$SFX
+
+# Build the image:
+docker build -t ssh_compat_suite-ssh:$VER -f ./TempDockerFile .
+
+# Cleaning
+rm -fr ./TempDockerFile $TMP
+
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-ssl-image b/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-ssl-image
new file mode 100755
index 0000000000..4ab2a8bddc
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create-ssl-image
@@ -0,0 +1,71 @@
+#!/bin/sh
+
+# ./create-image openssl 1.0.2m
+
+case "$1" in
+ "openssl")
+ FAM=openssl
+ VER=$2
+ PFX=https://www.openssl.org/source/openssl-
+ SFX=.tar.gz
+ TMP=tmp.tar.gz
+ ;;
+ "libressl")
+ FAM=libressl
+ VER=$2
+ PFX=https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-
+ SFX=.tar.gz
+ TMP=tmp.tar.gz
+ ;;
+ *)
+ echo No lib type
+ exit
+ ;;
+esac
+
+case $1$2 in
+ openssl0.9.8[a-l])
+ CONFIG_FLAGS=no-asm
+ ;;
+ *)
+ CONFIG_FLAGS=
+ ;;
+esac
+
+
+# This way of fetching the tar-file separate from the docker commands makes
+# http-proxy handling way easier. The wget command handles the $https_proxy
+# variable while the docker command must have /etc/docker/something changed
+# and the docker server restarted. That is not possible without root access.
+
+# Make a Dockerfile. This method simplifies env variable handling considerably:
+cat - > TempDockerFile <<EOF
+
+ FROM ubuntubuildbase
+
+ LABEL version=$FAM-$VER
+
+ WORKDIR /buildroot
+
+ COPY ${TMP} .
+ RUN tar xf ${TMP}
+
+ WORKDIR ${FAM}-${VER}
+
+ RUN ./config --prefix=/buildroot/ssl ${CONFIG_FLAGS}
+
+ RUN make
+ RUN make install_sw
+
+ RUN echo Built ${FAM}-${VER}
+EOF
+
+# Fetch the tar file. This could be done in an "ADD ..." in the Dockerfile,
+# but then we hit the proxy problem...
+wget -O $TMP $PFX$VER$SFX
+
+# Build the image:
+docker build -t ssh_compat_suite-$FAM:$VER -f ./TempDockerFile .
+
+# Cleaning
+rm -fr ./TempDockerFile $TMP
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create_all b/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create_all
new file mode 100755
index 0000000000..0dcf8cb570
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/build_scripts/create_all
@@ -0,0 +1,89 @@
+#!/bin/bash
+
+UBUNTU_VERSION=16.04
+
+SSH_SSL_VERSIONS=(\
+ openssh 4.4p1 openssl 0.9.8c \
+ openssh 4.5p1 openssl 0.9.8m \
+ openssh 5.0p1 openssl 0.9.8za \
+ openssh 6.2p2 openssl 0.9.8c \
+ openssh 6.3p1 openssl 0.9.8zh \
+ \
+ openssh 7.1p1 openssl 1.0.0a \
+ \
+ openssh 7.1p1 openssl 1.0.1p \
+ \
+ openssh 6.6p1 openssl 1.0.2n \
+ openssh 7.1p1 openssl 1.0.2n \
+ openssh 7.6p1 openssl 1.0.2n \
+ \
+ openssh 7.6p1 libressl 2.6.4 \
+ )
+
+if [ "x$1" == "x-b" ]
+then
+ shift
+ SKIP_CREATE_BASE=true
+fi
+
+WHAT_TO_DO=$1
+
+function create_one_image ()
+{
+ SSH_FAM=$1
+ SSH_VER=$2
+ SSL_FAM=$3
+ SSL_VER=$4
+
+ [ "x$SKIP_CREATE_BASE" == "xtrue" ] || ./create-base-image || (echo "Create base failed." >&2; exit 1)
+ ./create-ssl-image $SSL_FAM $SSL_VER \
+ || (echo "Create $SSL_FAM $SSL_VER failed." >&2; exit 2)
+
+ ./create-ssh-image $SSH_FAM $SSH_VER $SSL_FAM $SSL_VER \
+ || (echo "Create $SSH_FAM $SSH_VER on $SSL_FAM $SSL_VER failed." >&2; exit 3)
+}
+
+
+case ${WHAT_TO_DO} in
+ list)
+ ;;
+ listatoms)
+ PRE="["
+ POST="]"
+ C=\'
+ COMMA=,
+ ;;
+ build_one)
+ if [ $# != 5 ]
+ then
+ echo "$0 build_one openssh SSH_ver openssl SSL_ver " && exit
+ else
+ create_one_image $2 $3 $4 $5
+ exit
+ fi
+ ;;
+ build_all)
+ ;;
+ *)
+ echo "$0 [-b] list | listatoms | build_one openssh SSH_ver openssl SSL_ver | build_all" && exit
+ ;;
+esac
+
+
+echo -n $PRE
+i=0
+while [ "x${SSH_SSL_VERSIONS[i]}" != "x" ]
+do
+ case ${WHAT_TO_DO} in
+ list*)
+ [ $i -eq 0 ] || echo $COMMA
+ echo -n $C${SSH_SSL_VERSIONS[$i]}${SSH_SSL_VERSIONS[$(( $i + 1 ))]}-${SSH_SSL_VERSIONS[$(( $i + 2 ))]}${SSH_SSL_VERSIONS[$(( $i + 3 ))]}$C
+ ;;
+ build_all)
+ create_one_image ${SSH_SSL_VERSIONS[$i]} ${SSH_SSL_VERSIONS[$(( $i + 1 ))]} ${SSH_SSL_VERSIONS[$(( $i + 2 ))]} ${SSH_SSL_VERSIONS[$(( $i + 3 ))]}
+ ;;
+ esac
+
+ i=$(( $i + 4 ))
+done
+echo $POST
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_dsa_key b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_dsa_key
new file mode 100644
index 0000000000..8b2354a7ea
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_dsa_key
@@ -0,0 +1,12 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBugIBAAKBgQDlXDEddxFbTtPsu2bRTbSONFVKMxe430iqBoXoKK2Gyhlqn7J8
+SRGlmvTN7T06+9iFqgJi+x+dlSJGlNEY/v67Z8C7rWfJynYuRier4TujLwP452RT
+YrsnCq47pGJXHb9xAWr7UGMv85uDrECUiIdK4xIrwpW/gMb5zPSThDGNiwIVANts
+B9nBX0NH/B0lXthVCg2jRSkpAoGAIS3vG8VmjQNYrGfdcdvQtGubFXs4jZJO6iDe
+9u9/O95dcnH4ZIL4y3ZPHbw73dCKXFe5NlqI/POmn3MyFdpyqH5FTHWB/aAFrma6
+qo00F1mv83DkQCEfg6fwE/SaaBjDecr5I14hWOtocpYqlY1/x1aspahwK6NLPp/D
+A4aAt78CgYAmNgr3dnHgMXrEsAeHswioAad3YLtnPvdFdHqd5j4oSbgKwFd7Xmyq
+blfeQ6rRo8dmUF0rkUU8cn71IqbhpsCJQEZPt9WBlhHiY95B1ELKYHoHCbZA8qrZ
+iEIcfwch85Da0/uzv4VE0UHTC0P3WRD3sZDfXd9dZLdc80n6ImYRpgIURgW8SZGj
+X0mMkMJv/Ltdt0gYx60=
+-----END DSA PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_dsa_key.pub
new file mode 100644
index 0000000000..9116493472
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_dsa_key.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAOVcMR13EVtO0+y7ZtFNtI40VUozF7jfSKoGhegorYbKGWqfsnxJEaWa9M3tPTr72IWqAmL7H52VIkaU0Rj+/rtnwLutZ8nKdi5GJ6vhO6MvA/jnZFNiuycKrjukYlcdv3EBavtQYy/zm4OsQJSIh0rjEivClb+AxvnM9JOEMY2LAAAAFQDbbAfZwV9DR/wdJV7YVQoNo0UpKQAAAIAhLe8bxWaNA1isZ91x29C0a5sVeziNkk7qIN7273873l1ycfhkgvjLdk8dvDvd0IpcV7k2Woj886afczIV2nKofkVMdYH9oAWuZrqqjTQXWa/zcORAIR+Dp/AT9JpoGMN5yvkjXiFY62hyliqVjX/HVqylqHAro0s+n8MDhoC3vwAAAIAmNgr3dnHgMXrEsAeHswioAad3YLtnPvdFdHqd5j4oSbgKwFd7XmyqblfeQ6rRo8dmUF0rkUU8cn71IqbhpsCJQEZPt9WBlhHiY95B1ELKYHoHCbZA8qrZiEIcfwch85Da0/uzv4VE0UHTC0P3WRD3sZDfXd9dZLdc80n6ImYRpg== uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key256 b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key256
new file mode 100644
index 0000000000..5ed2b361cc
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key256
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEILwQIf+Jul+oygeJn7cBSvn2LGqnW1ZfiHDQMDXZ96mooAoGCCqGSM49
+AwEHoUQDQgAEJUo0gCIhXEPJYvxec23IAjq7BjV1xw8deI8JV9vL5BMCZNhyj5Vt
+NbFPbKPuL/Sikn8p4YP/5y336ug7szvYrg==
+-----END EC PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key256.pub b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key256.pub
new file mode 100644
index 0000000000..240387d901
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key256.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCVKNIAiIVxDyWL8XnNtyAI6uwY1dccPHXiPCVfby+QTAmTYco+VbTWxT2yj7i/0opJ/KeGD/+ct9+roO7M72K4= uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key384 b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key384
new file mode 100644
index 0000000000..9d31d75cd5
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key384
@@ -0,0 +1,6 @@
+-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDBw+P1sic2i41wTGQgjyUlBtxQfnY77L8TFcDngoRiVrbCugnDrioNo
+JogqymWhSC+gBwYFK4EEACKhZANiAATwaqEp3vyLzfb08kqgIZLv/mAYJyGD+JMt
+f11OswGs3uFkbHZOErFCgeLuBvarSTAFkOlMR9GZGaDEfcrPBTtvKj+jEaAvh6yr
+JxS97rtwk2uadDMem2x4w9Ga4jw4S8E=
+-----END EC PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key384.pub b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key384.pub
new file mode 100644
index 0000000000..cca85bda72
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key384.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBPBqoSne/IvN9vTySqAhku/+YBgnIYP4ky1/XU6zAaze4WRsdk4SsUKB4u4G9qtJMAWQ6UxH0ZkZoMR9ys8FO28qP6MRoC+HrKsnFL3uu3CTa5p0Mx6bbHjD0ZriPDhLwQ== uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key521 b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key521
new file mode 100644
index 0000000000..b698be1ec9
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key521
@@ -0,0 +1,7 @@
+-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIBtGVvyn7kGX7BfWAYHK2ZXmhWscTOV0J0mAfab0u0ZMw0id2a3O9s
+sBjJoCqoAXTJ7d/OUw85qqQNDE5GDQpDFq6gBwYFK4EEACOhgYkDgYYABAHPWfUD
+tQ/JmfwmmSdWWjGm94hFqwaivI4H43acDdd71+vods4rN2Yh3X7fSUvJkeOhXFOJ
+yO9F+61ssKgS0a0nxQEvdXks3QyfKTPjYQuBUvY+AV/A4AskPBz731xCDmbYuWuh
+RPekZ7d5bF0U0pGlExbX+naQJMSbJSdZrPM9993EmA==
+-----END EC PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key521.pub b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key521.pub
new file mode 100644
index 0000000000..d181d30d69
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_ecdsa_key521.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAHPWfUDtQ/JmfwmmSdWWjGm94hFqwaivI4H43acDdd71+vods4rN2Yh3X7fSUvJkeOhXFOJyO9F+61ssKgS0a0nxQEvdXks3QyfKTPjYQuBUvY+AV/A4AskPBz731xCDmbYuWuhRPekZ7d5bF0U0pGlExbX+naQJMSbJSdZrPM9993EmA== uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_rsa_key b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_rsa_key
new file mode 100644
index 0000000000..84096298ca
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_rsa_key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAuC6uxC0P8voYQCrwJzczo9iSiwsovPv4etd2BLnu8cKWdnjR
+34tWvtguw2kO+iDyt4hFGGfDBQf2SXl+ZEsE2N1RlSp5A73me2byw/L4MreX2rbU
+TwyNXF3TBvKb3Gbpx7PoiB9frcb9RCMxtypBvGQD6bx6h5UWKuSkYzARaRLv3kbB
+swcqfrA3PfWybkIoaa2RO1Ca86u6K0v+a4r0OfRxTnghuakZkH6CD7+uU3irliPI
+UFt2wTI/qWmnDrMFh4RffToHK0QZHXdkq4ama5kRZdZ0svSorxqkl8EWGPhReoUj
+Yrz0bCNevSlDxHCxLi8epRxuv+AhZHW0YdMCCwIDAQABAoIBAHUyj1aZbfqolWHP
+cL0jbSKnHqiHU0bd9sED9T8QqTEBJwj/3Fwop+wMV8VURol3CbsrZPwgmoHLDTa3
+rmtXKSBtxAns2tA8uDpxyaxSIQj0thYgHHyoehL6SNu06OSYP84pdp+XhyRm6KXA
+11O7+dRMuAi1PCql/VMR5mCPJ6T5qWAVYHFyEBvMm4q5yYSRSPaAaZHC6WbEsxHN
+jGzcyl3tvmOyN0+M7v0U86lQ+H2tSXH+nQg/Ig6hWgFGg8AYoos/9yUGOY+e9bUE
+serYdsuiyxBfo4CgoSeDsjwNp1lAZ5UOrIDdRqK9C8jGVkHDzwfmmtczWXkVVzGZ
+Bd05izECgYEA31yHzSA/umamyZAQbi/5psk1Fc5m6MzsgmJmB6jm7hUZ0EbpSV4C
+6b1nOrk/IAtA12rvDHgWy0zpkJbC5b03C77RnBgTRgLQyolrcpLDJ47+Kxf/AHGk
+m63KaCpwZEQ4f9ARBXySD/jNoW9gz5S6Xa3RnHOC70DsIIk5VOCjWk0CgYEA0xiM
+Ay27PJcbAG/4tnjH8DZfHb8SULfnfUj8kMe3V2SDPDWbhY8zheo45wTBDRflFU5I
+XyGmfuZ7PTTnFVrJz8ua3mAMOzkFn4MmdaRCX9XtuE4YWq3lFvxlrJvfXSjEL0km
+8UwlhJMixaEPqFQjsKc9BHwWKRiKcF4zFQ1DybcCgYB46yfdhYLaj23lmqc6b6Bw
+iWbCql2N1DqJj2l65hY2d5fk6C6s+EcNcOrsoJKq70yoEgzdrDlyz+11yBg0tU2S
+fzgMkAAHG8kajHBts0QRK1kvzSrQe7VITjpQUAFOVpxbnTFJzhloqiHwLlKzremC
+g3IBh4svqO7r4j32VDI61QKBgQCQL4gS872cWSncVp7vI/iNHtZBHy2HbNX1QVEi
+Iwgb7U+mZIdh5roukhlj0l96bgPPVbUhJX7v1sX+vI/KikSmZk/V7IzuNrich5xR
+ZmzfwOOqq8z+wyBjXuqjx6P9oca+9Zxf3L8Tmtx5WNW1CCOImfKXiZopX9XPgsgp
+bPIMaQKBgQCql4uTSacSQ5s6rEEdvR+y6nTohF3zxhOQ+6xivm3Hf1mgTk40lQ+t
+sr6HsSTv8j/ZbhhtaUUb2efro3pDztjlxXFvITar9ZDB2B4QMlpSsDR9UNk8xKGY
+J9aYLr4fJC6J6VA7Wf0yq6LpjSXRH/2GeNtmMl5rFRsHt+VU7GZK9g==
+-----END RSA PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_rsa_key.pub b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_rsa_key.pub
new file mode 100644
index 0000000000..4ac6e7b124
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/host_keys/ssh_host_rsa_key.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4Lq7ELQ/y+hhAKvAnNzOj2JKLCyi8+/h613YEue7xwpZ2eNHfi1a+2C7DaQ76IPK3iEUYZ8MFB/ZJeX5kSwTY3VGVKnkDveZ7ZvLD8vgyt5fattRPDI1cXdMG8pvcZunHs+iIH1+txv1EIzG3KkG8ZAPpvHqHlRYq5KRjMBFpEu/eRsGzByp+sDc99bJuQihprZE7UJrzq7orS/5rivQ59HFOeCG5qRmQfoIPv65TeKuWI8hQW3bBMj+paacOswWHhF99OgcrRBkdd2SrhqZrmRFl1nSy9KivGqSXwRYY+FF6hSNivPRsI169KUPEcLEuLx6lHG6/4CFkdbRh0wIL uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_dsa b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_dsa
new file mode 100644
index 0000000000..01a88acea2
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_dsa
@@ -0,0 +1,12 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBvAIBAAKBgQC97XncQDaa9PQYEWK7llBxZQ2suVYTz1eadw2HtY+Y8ZKdUBLd
+9LUQ2lymUC9yq66rb5pBBR13k/9Zcbu8I0nafrZT4wJ4H0YGD6Ob5O4HR4EHjO5q
+hgnMJ17e1XnzI31MW5xAuAHTLLClNvnG05T1jaU+tRAsVSCHin3+sOenowIVAMSe
+ANBvw7fm5+Lw+ziOAHPjeYzRAoGBALkWCGpKmlJ65F3Y/RcownHQvsrDAllzKF/a
+cSfriCVVP5qVZ3Ach28ZZ9BFEnRE2SKqVsyBAiceb/+ISlu8CqKEvvoNIMJAu5rU
+MwZh+PeHN4ES6tWTwBGAwu84ke6N4BgV+6Q4qkcyywHsT5oU0EdVbn2zzAZw8c7v
+BpbsJ1KsAoGABraHWqSFhaX4+GHmtKwXZFVRKh/4R6GR2LpkFzGm3Ixv+eo9K5CI
+TjiBYiVMrWH23G1LiDuJyMGqHEnIef+sorNfNzdnwq+8qRCTS6mbpRXkUt9p1arJ
+MIKmosS+GFhTN6Z85gCwC51S2EDC4GW7J4ViHKacr1FwJSw9RC9F+WsCFQCRJayH
+P4vM1XUOVEeX7u04K1EAFg==
+-----END DSA PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_dsa.pub b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_dsa.pub
new file mode 100644
index 0000000000..30661d5adf
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_dsa.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAL3tedxANpr09BgRYruWUHFlDay5VhPPV5p3DYe1j5jxkp1QEt30tRDaXKZQL3KrrqtvmkEFHXeT/1lxu7wjSdp+tlPjAngfRgYPo5vk7gdHgQeM7mqGCcwnXt7VefMjfUxbnEC4AdMssKU2+cbTlPWNpT61ECxVIIeKff6w56ejAAAAFQDEngDQb8O35ufi8Ps4jgBz43mM0QAAAIEAuRYIakqaUnrkXdj9FyjCcdC+ysMCWXMoX9pxJ+uIJVU/mpVncByHbxln0EUSdETZIqpWzIECJx5v/4hKW7wKooS++g0gwkC7mtQzBmH494c3gRLq1ZPAEYDC7ziR7o3gGBX7pDiqRzLLAexPmhTQR1VufbPMBnDxzu8GluwnUqwAAACABraHWqSFhaX4+GHmtKwXZFVRKh/4R6GR2LpkFzGm3Ixv+eo9K5CITjiBYiVMrWH23G1LiDuJyMGqHEnIef+sorNfNzdnwq+8qRCTS6mbpRXkUt9p1arJMIKmosS+GFhTN6Z85gCwC51S2EDC4GW7J4ViHKacr1FwJSw9RC9F+Ws= uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa
new file mode 100644
index 0000000000..60e8f6eb6e
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIC557KPgmq+pWOAh1L8DV8GWW0u7W5vz6mim3FFB1l8koAoGCCqGSM49
+AwEHoUQDQgAEC3J5fQ8+8xQso0lhBdoLdvD14oSsQiMuweXq+Dy2+4Mjdw2/bbw0
+CvbE2+KWNcgwxRLycNGcMCBdf/cOgNyGkA==
+-----END EC PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa256 b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa256
new file mode 100644
index 0000000000..60e8f6eb6e
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa256
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIC557KPgmq+pWOAh1L8DV8GWW0u7W5vz6mim3FFB1l8koAoGCCqGSM49
+AwEHoUQDQgAEC3J5fQ8+8xQso0lhBdoLdvD14oSsQiMuweXq+Dy2+4Mjdw2/bbw0
+CvbE2+KWNcgwxRLycNGcMCBdf/cOgNyGkA==
+-----END EC PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa256.pub b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa256.pub
new file mode 100644
index 0000000000..b349d26da3
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa256.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAtyeX0PPvMULKNJYQXaC3bw9eKErEIjLsHl6vg8tvuDI3cNv228NAr2xNviljXIMMUS8nDRnDAgXX/3DoDchpA= sshtester@elxadlj3q32
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa384 b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa384
new file mode 100644
index 0000000000..ece6c8f284
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa384
@@ -0,0 +1,6 @@
+-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDBdgJs/xThHiy/aY1ymtQ4B0URNnRCm8l2WZMFjua57+nvq4Duf+igN
+pN/5p/+azLKgBwYFK4EEACKhZANiAATUw6pT/UW2HvTW6lL2BGY7NfUGEX285XVi
+9AcTXH1K+TOekbGmcpSirlGzSb15Wycajpmaae5vAzH1nnvcVd3FYODVdDXTHgV/
+FeXQ+vaw7CZnEAKZsr8mjXRX3fEyO1E=
+-----END EC PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa384.pub b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa384.pub
new file mode 100644
index 0000000000..fd81e220f7
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa384.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBNTDqlP9RbYe9NbqUvYEZjs19QYRfbzldWL0BxNcfUr5M56RsaZylKKuUbNJvXlbJxqOmZpp7m8DMfWee9xV3cVg4NV0NdMeBX8V5dD69rDsJmcQApmyvyaNdFfd8TI7UQ== uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa521 b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa521
new file mode 100644
index 0000000000..21c000ea03
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa521
@@ -0,0 +1,7 @@
+-----BEGIN EC PRIVATE KEY-----
+MIHbAgEBBEEhm0w3xcGILU8eP61mThVBwCJfyzrFktGf7cCa1ciL4YLsukd20Q3Z
+yp0YcEDLcEm36CZGabgkEvblJ1Rx2lPTu6AHBgUrgQQAI6GBiQOBhgAEAYep8cX2
+7wUPw5pNYwFkWQXrJ2GSkmO8iHwkWJ6srRay/sF3WoPF/dyDVymFgirtsSTJ+D0u
+ex4qphOOJxkd1Yf+ANHvDFN9LoBvbgtNLTRJlpuNLCdWQlt+mEnPMDGMV/HWHHiz
+7/mWE+XUVIcQjhm5uv0ObI/wroZEurXMGEhTis3L
+-----END EC PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa521.pub b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa521.pub
new file mode 100644
index 0000000000..d9830da5de
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_ecdsa521.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAGHqfHF9u8FD8OaTWMBZFkF6ydhkpJjvIh8JFierK0Wsv7Bd1qDxf3cg1cphYIq7bEkyfg9LnseKqYTjicZHdWH/gDR7wxTfS6Ab24LTS00SZabjSwnVkJbfphJzzAxjFfx1hx4s+/5lhPl1FSHEI4Zubr9DmyP8K6GRLq1zBhIU4rNyw== uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_rsa b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_rsa
new file mode 100644
index 0000000000..2e50ac2304
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_rsa
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEA7+C3gLoflKybq4I+clbg2SWf6cXyHpnLNDnZeMvIbOz2X/Ce
+XUm17DFeexTaVBs9Zq9WwDFOFkLQhbuXgpvB0shSY0nr+Em7InRM8AiRLxPe0txM
+mFFhL+v083dYwgaJOo1PthNM/tGRZJu+0sQDqrmN7CusFHdZg2NTzTzbwWqPiuP/
+mf3o7W4CWqDTBzbYTgpWlH7vRZf9FYwT4on5YWzLA8TvO2TwBGTfTMK5nswH++iO
+v4jKecoEwyBFMUSKqZ9UYHGw/kshHbltM65Ye/xjXEX0GxDdxu8ZyVKXd4acNbJJ
+P0tcxN4GzKJiR6zNYwCzDhjqDEbM5qCGhShhgQIDAQABAoIBAQCucdGBP9mvmUcs
+Fu+q3xttTztYGqfVMSrhtCA/BJOhA0K4ypegZ/Zw6gY3pBaSi6y/fEuuQSz0a2qR
+lra8OOFflGa15hBA4/2/NKyu8swCXITy+1qIesYev43HcMePcolhl1qcorSfq2/8
+pnbDd+Diy0Y2thvSVmk2b4mF+/gkUx3CHLhgRMcxCHLG1VeqIfLf+pa0jIw94tZ5
+CoIoI096pDTsneO9xhh1QxWQRRFVqdf3Q9zyiBgJCggpX+1fVsbQejuEK4hKRBKx
+SRPX/pX5aU+7+KSZ/DbtXGg1sCw9NUDFTIEV3UPmko4oWawNGv/CQAK80g3go28v
+UnVf11BBAoGBAP2amIFp+Ps33A5eesT7g/NNkGqBEi5W37K8qzYJxqXJvH0xmpFo
+8a3Je3PQRrzbTUJyISA6/XNnA62+bEvWiEXPiK3stQzNHoVz7ftCb19zgW4sLKRW
+Qhjq7QsGeRrdksJnZ7ekfzOv658vHJPElS1MdPu2WWhiNvAjtmdyFQulAoGBAPIk
+6831QAnCdp/ffH/K+cqV9vQYOFig8n4mQNNC+sLghrtZh9kbmTuuNKAhF56vdCCn
+ABD/+RiLXKVsF0PvQ5g9wRLKaiJubXI7XEBemCCLhjtESxGpWEV8GalslUgE1cKs
+d1pwSVjd0sYt0gOAf2VRhlbpSWhXA2xVll34xgetAoGAHaI089pYN7K9SgiMO/xP
+3NxRZcCTSUrpdM9LClN2HOVH2zEyqI8kvnPuswfBXEwb6QnBCS0bdKKy8Vhw+yOk
+ZNPtWrVwKoDFcj6rrlKDBRpQI3mR9doGezboYANvn04I2iKPIgxcuMNzuvQcWL/9
+1n86pDcYl3Pyi3kA1XGlN+kCgYEAz1boBxpqdDDsjGa8X1y5WUviAw8+KD3ghj5R
+IdTnjbjeBUxbc38bTawUac0MQZexE0iMWQImFGs4sHkGzufwdErkqSdjjAoMc1T6
+4C9fifaOwO7wbLYZ3J2wB4/vn5RsSV6OcIVXeN2wXnvbqZ38+A+/vWnSrqJbTwdW
+Uy7yup0CgYEA8M9vjpAoCr3XzNDwJyWRQcT7e+nRYUNDlXBl3jpQhHuJtnSnkoUv
+HXYXEwvp8peycNzeVz5OwFVMzCH8OG4WiGN4Pmo0rDWHED/W7eIRHIitHGTzZ+Qw
+gRxscoewblSLSkYMXidBLmQjr4U5bDBesRuGhm5NuLyMTa1f3Pc/90k=
+-----END RSA PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_rsa.pub b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_rsa.pub
new file mode 100644
index 0000000000..26e560d4f8
--- /dev/null
+++ b/lib/ssh/test/ssh_compat_SUITE_data/users_keys/id_rsa.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDv4LeAuh+UrJurgj5yVuDZJZ/pxfIemcs0Odl4y8hs7PZf8J5dSbXsMV57FNpUGz1mr1bAMU4WQtCFu5eCm8HSyFJjSev4SbsidEzwCJEvE97S3EyYUWEv6/Tzd1jCBok6jU+2E0z+0ZFkm77SxAOquY3sK6wUd1mDY1PNPNvBao+K4/+Z/ejtbgJaoNMHNthOClaUfu9Fl/0VjBPiiflhbMsDxO87ZPAEZN9MwrmezAf76I6/iMp5ygTDIEUxRIqpn1RgcbD+SyEduW0zrlh7/GNcRfQbEN3G7xnJUpd3hpw1skk/S1zE3gbMomJHrM1jALMOGOoMRszmoIaFKGGB uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_connection_SUITE.erl b/lib/ssh/test/ssh_connection_SUITE.erl
index 9bbd9da817..778e4a5fc8 100644
--- a/lib/ssh/test/ssh_connection_SUITE.erl
+++ b/lib/ssh/test/ssh_connection_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -45,9 +45,18 @@ all() ->
{group, openssh},
small_interrupted_send,
interrupted_send,
+ exec_erlang_term,
+ exec_erlang_term_non_default_shell,
start_shell,
start_shell_exec,
start_shell_exec_fun,
+ start_shell_exec_fun2,
+ start_shell_exec_fun3,
+ start_shell_exec_direct_fun,
+ start_shell_exec_direct_fun2,
+ start_shell_exec_direct_fun3,
+ start_shell_exec_direct_fun1_error,
+ start_shell_exec_direct_fun1_error_type,
start_shell_sock_exec_fun,
start_shell_sock_daemon_exec,
connect_sock_not_tcp,
@@ -85,13 +94,14 @@ init_per_suite(Config) ->
?CHECK_CRYPTO(Config).
end_per_suite(Config) ->
+ catch ssh:stop(),
Config.
%%--------------------------------------------------------------------
init_per_group(openssh, Config) ->
case ssh_test_lib:gen_tcp_connect("localhost", 22, []) of
{error,econnrefused} ->
- {skip,"No openssh deamon"};
+ {skip,"No openssh deamon (econnrefused)"};
{ok, Socket} ->
gen_tcp:close(Socket),
ssh_test_lib:openssh_sanity_check(Config)
@@ -519,7 +529,7 @@ start_shell_exec(Config) when is_list(Config) ->
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
{password, "morot"},
- {exec, {?MODULE,ssh_exec,[]}} ]),
+ {exec, {?MODULE,ssh_exec_echo,[]}} ]),
ConnectionRef = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
{user, "foo"},
@@ -532,7 +542,7 @@ start_shell_exec(Config) when is_list(Config) ->
success = ssh_connection:exec(ConnectionRef, ChannelId0,
"testing", infinity),
receive
- {ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"testing\r\n">>}} ->
+ {ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"echo testing\r\n">>}} ->
ok
after 5000 ->
ct:fail("Exec Timeout")
@@ -542,10 +552,42 @@ start_shell_exec(Config) when is_list(Config) ->
ssh:stop_daemon(Pid).
%%--------------------------------------------------------------------
-start_shell_exec_fun() ->
- [{doc, "start shell to exec command"}].
+exec_erlang_term(Config) when is_list(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
+ file:make_dir(UserDir),
+ SysDir = proplists:get_value(data_dir, Config),
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, UserDir},
+ {password, "morot"}
+ ]),
+
+ ConnectionRef = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "foo"},
+ {password, "morot"},
+ {user_interaction, true},
+ {user_dir, UserDir}]),
+
+ {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity),
+
+ success = ssh_connection:exec(ConnectionRef, ChannelId0,
+ "1+2.", infinity),
+ TestResult =
+ receive
+ {ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"3",_/binary>>}} = R ->
+ ct:log("Got expected ~p",[R]);
+ Other ->
+ ct:log("Got unexpected ~p",[Other])
+ after 5000 ->
+ {fail,"Exec Timeout"}
+ end,
+
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid),
+ TestResult.
-start_shell_exec_fun(Config) when is_list(Config) ->
+%%--------------------------------------------------------------------
+exec_erlang_term_non_default_shell(Config) when is_list(Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
file:make_dir(UserDir),
@@ -553,24 +595,109 @@ start_shell_exec_fun(Config) when is_list(Config) ->
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
{password, "morot"},
- {exec, fun ssh_exec/1}]),
+ {shell, fun(U, H) -> start_our_shell(U, H) end}
+ ]),
ConnectionRef = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
{user, "foo"},
{password, "morot"},
{user_interaction, true},
- {user_dir, UserDir}]),
+ {user_dir, UserDir}
+ ]),
{ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity),
success = ssh_connection:exec(ConnectionRef, ChannelId0,
- "testing", infinity),
+ "1+2.", infinity),
+ TestResult =
+ receive
+ {ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"3",_/binary>>}} = R ->
+ ct:log("Got unexpected ~p",[R]),
+ {fail,"Could exec erlang term although non-erlang shell"};
+ Other ->
+ ct:log("Got expected ~p",[Other])
+ after 5000 ->
+ {fail, "Exec Timeout"}
+ end,
+
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid),
+ TestResult.
+
+%%--------------------------------------------------------------------
+start_shell_exec_fun(Config) ->
+ do_start_shell_exec_fun(fun ssh_exec_echo/1,
+ "testing", <<"echo testing\r\n">>, 0,
+ Config).
+
+start_shell_exec_fun2(Config) ->
+ do_start_shell_exec_fun(fun ssh_exec_echo/2,
+ "testing", <<"echo foo testing\r\n">>, 0,
+ Config).
+
+start_shell_exec_fun3(Config) ->
+ do_start_shell_exec_fun(fun ssh_exec_echo/3,
+ "testing", <<"echo foo testing\r\n">>, 0,
+ Config).
+
+start_shell_exec_direct_fun(Config) ->
+ do_start_shell_exec_fun({direct, fun ssh_exec_direct_echo/1},
+ "testing", <<"echo testing\n">>, 0,
+ Config).
+
+start_shell_exec_direct_fun2(Config) ->
+ do_start_shell_exec_fun({direct, fun ssh_exec_direct_echo/2},
+ "testing", <<"echo foo testing">>, 0,
+ Config).
+
+start_shell_exec_direct_fun3(Config) ->
+ do_start_shell_exec_fun({direct, fun ssh_exec_direct_echo/3},
+ "testing", <<"echo foo testing">>, 0,
+ Config).
+
+start_shell_exec_direct_fun1_error(Config) ->
+ do_start_shell_exec_fun({direct, fun ssh_exec_direct_echo_error_return/1},
+ "testing", <<"Error in \"testing\": {bad}\n">>, 1,
+ Config).
+
+start_shell_exec_direct_fun1_error_type(Config) ->
+ do_start_shell_exec_fun({direct, fun ssh_exec_direct_echo_error_return_type/1},
+ "testing", <<"Error in \"testing\": Bad exec-plugin return: very_bad\n">>, 1,
+ Config).
+
+
+
+do_start_shell_exec_fun(Fun, Command, Expect, ExpectType, Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
+ file:make_dir(UserDir),
+ SysDir = proplists:get_value(data_dir, Config),
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, UserDir},
+ {password, "morot"},
+ {exec, Fun}]),
+
+ ConnectionRef = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "foo"},
+ {password, "morot"},
+ {user_interaction, true},
+ {user_dir, UserDir}]),
+
+ {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity),
+
+ success = ssh_connection:exec(ConnectionRef, ChannelId0, Command, infinity),
receive
- {ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"testing\r\n">>}} ->
+ {ssh_cm, ConnectionRef, {data, _ChannelId, ExpectType, Expect}} ->
ok
after 5000 ->
- ct:fail("Exec Timeout")
+ receive
+ Other ->
+ ct:pal("Received other:~n~p",[Other]),
+ ct:fail("Unexpected response")
+ after 0 ->
+ ct:fail("Exec Timeout")
+ end
end,
ssh:close(ConnectionRef),
@@ -588,7 +715,7 @@ start_shell_sock_exec_fun(Config) when is_list(Config) ->
{Pid, HostD, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
{password, "morot"},
- {exec, fun ssh_exec/1}]),
+ {exec, fun ssh_exec_echo/1}]),
Host = ssh_test_lib:ntoa(ssh_test_lib:mangle_connect_address(HostD)),
{ok, Sock} = ssh_test_lib:gen_tcp_connect(Host, Port, [{active,false}]),
@@ -604,7 +731,7 @@ start_shell_sock_exec_fun(Config) when is_list(Config) ->
"testing", infinity),
receive
- {ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"testing\r\n">>}} ->
+ {ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"echo testing\r\n">>}} ->
ok
after 5000 ->
ct:fail("Exec Timeout")
@@ -628,7 +755,7 @@ start_shell_sock_daemon_exec(Config) ->
{ok, _Pid} = ssh:daemon(Ss, [{system_dir, SysDir},
{user_dir, UserDir},
{password, "morot"},
- {exec, fun ssh_exec/1}])
+ {exec, fun ssh_exec_echo/1}])
end),
{ok,Sc} = gen_tcp:accept(Sl),
{ok,ConnectionRef} = ssh:connect(Sc, [{silently_accept_hosts, true},
@@ -643,7 +770,7 @@ start_shell_sock_daemon_exec(Config) ->
"testing", infinity),
receive
- {ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"testing\r\n">>}} ->
+ {ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"echo testing\r\n">>}} ->
ok
after 5000 ->
ct:fail("Exec Timeout")
@@ -754,7 +881,7 @@ stop_listener(Config) when is_list(Config) ->
{Pid0, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
{password, "morot"},
- {exec, fun ssh_exec/1}]),
+ {exec, fun ssh_exec_echo/1}]),
ConnectionRef0 = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
{user, "foo"},
@@ -774,7 +901,7 @@ stop_listener(Config) when is_list(Config) ->
success = ssh_connection:exec(ConnectionRef0, ChannelId0,
"testing", infinity),
receive
- {ssh_cm, ConnectionRef0, {data, ChannelId0, 0, <<"testing\r\n">>}} ->
+ {ssh_cm, ConnectionRef0, {data, ChannelId0, 0, <<"echo testing\r\n">>}} ->
ok
after 5000 ->
ct:fail("Exec Timeout")
@@ -783,7 +910,7 @@ stop_listener(Config) when is_list(Config) ->
case ssh_test_lib:daemon(Port, [{system_dir, SysDir},
{user_dir, UserDir},
{password, "potatis"},
- {exec, fun ssh_exec/1}]) of
+ {exec, fun ssh_exec_echo/1}]) of
{Pid1, Host, Port} ->
ConnectionRef1 = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
{user, "foo"},
@@ -800,6 +927,8 @@ stop_listener(Config) when is_list(Config) ->
ssh:stop_daemon(Pid0),
ssh:stop_daemon(Pid1);
Error ->
+ ssh:close(ConnectionRef0),
+ ssh:stop_daemon(Pid0),
ct:fail({unexpected, Error})
end.
@@ -819,11 +948,22 @@ start_subsystem_on_closed_channel(Config) ->
{user_interaction, false},
{user_dir, UserDir}]),
- {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
- ok = ssh_connection:close(ConnectionRef, ChannelId),
+ {ok, ChannelId1} = ssh_connection:session_channel(ConnectionRef, infinity),
+ ok = ssh_connection:close(ConnectionRef, ChannelId1),
+ {error, closed} = ssh_connection:ptty_alloc(ConnectionRef, ChannelId1, []),
+ {error, closed} = ssh_connection:subsystem(ConnectionRef, ChannelId1, "echo_n", 5000),
+ {error, closed} = ssh_connection:exec(ConnectionRef, ChannelId1, "testing1.\n", 5000),
+ {error, closed} = ssh_connection:send(ConnectionRef, ChannelId1, "exit().\n", 5000),
- {error, closed} = ssh_connection:subsystem(ConnectionRef, ChannelId, "echo_n", infinity),
+ %% Test that there could be a gap between close and an operation (Bugfix OTP-14939):
+ {ok, ChannelId2} = ssh_connection:session_channel(ConnectionRef, infinity),
+ ok = ssh_connection:close(ConnectionRef, ChannelId2),
+ timer:sleep(2000),
+ {error, closed} = ssh_connection:ptty_alloc(ConnectionRef, ChannelId2, []),
+ {error, closed} = ssh_connection:subsystem(ConnectionRef, ChannelId2, "echo_n", 5000),
+ {error, closed} = ssh_connection:exec(ConnectionRef, ChannelId2, "testing1.\n", 5000),
+ {error, closed} = ssh_connection:send(ConnectionRef, ChannelId2, "exit().\n", 5000),
ssh:close(ConnectionRef),
ssh:stop_daemon(Pid).
@@ -981,7 +1121,22 @@ start_our_shell(_User, _Peer) ->
%% Don't actually loop, just exit
end).
-ssh_exec(Cmd) ->
+
+ssh_exec_echo(Cmd) ->
+ spawn(fun() ->
+ io:format("echo "++Cmd ++ "\n")
+ end).
+
+ssh_exec_echo(Cmd, User) ->
spawn(fun() ->
- io:format(Cmd ++ "\n")
+ io:format(io_lib:format("echo ~s ~s\n",[User,Cmd]))
end).
+ssh_exec_echo(Cmd, User, _PeerAddr) ->
+ ssh_exec_echo(Cmd,User).
+
+ssh_exec_direct_echo(Cmd) -> {ok, io_lib:format("echo ~s~n",[Cmd])}.
+ssh_exec_direct_echo(Cmd, User) -> {ok, io_lib:format("echo ~s ~s",[User,Cmd])}.
+ssh_exec_direct_echo(Cmd, User, _PeerAddr) -> ssh_exec_direct_echo(Cmd,User).
+
+ssh_exec_direct_echo_error_return(_Cmd) -> {error, {bad}}.
+ssh_exec_direct_echo_error_return_type(_Cmd) -> very_bad.
diff --git a/lib/ssh/test/ssh_dbg_SUITE.erl b/lib/ssh/test/ssh_dbg_SUITE.erl
new file mode 100644
index 0000000000..ab7918fa90
--- /dev/null
+++ b/lib/ssh/test/ssh_dbg_SUITE.erl
@@ -0,0 +1,465 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssh_dbg_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("ssh/src/ssh.hrl").
+-include("ssh_test_lib.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{seconds,60}}].
+
+all() ->
+ [{group, dbg},
+ {group, circ_buf}
+ ].
+
+groups() ->
+ [{dbg, [], [dbg_basic,
+ dbg_alg_terminate,
+ dbg_ssh_messages,
+ dbg_connections,
+ dbg_channels]},
+ {circ_buf, [], [cb_basic,
+ cb_print,
+ cb_macros_print
+ ]}
+ ].
+
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ ?CHECK_CRYPTO(begin
+ ssh:start(),
+ Config
+ end).
+
+end_per_suite(_Config) ->
+ ssh:stop().
+
+%%--------------------------------------------------------------------
+init_per_testcase(_TC, Config) ->
+ Config.
+
+end_per_testcase(_TC, Config) ->
+ ssh_dbg:stop(),
+ Config.
+
+%%--------------------------------------------------------------------
+-define(USR, "foo").
+-define(PWD, "bar").
+
+-define(DBG_RECEIVE(ExpectPfx, Ref, C, Pid),
+ receive
+ {Ref, [_, C, ExpectPfx++_]} ->
+ ok
+
+ after 5000 ->
+ ssh_dbg:stop(),
+ ssh:stop_daemon(Pid),
+ ct:fail("No '~s' debug message",[ExpectPfx])
+ end
+ ).
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+dbg_basic(_Config) ->
+ L0 = ssh_dbg:start(),
+ true = is_pid(whereis(ssh_dbg)),
+ true = is_list(L0),
+
+ {ok,L0} = ssh_dbg:on(),
+ {ok,L0} = ssh_dbg:on(),
+
+ L1 = [hd(L0)],
+ {ok,L1} = ssh_dbg:off(tl(L0)),
+
+ {ok,L1} = ssh_dbg:go_on(),
+
+ {ok,[]} = ssh_dbg:off(),
+ {ok,[]} = ssh_dbg:off(),
+
+ ok = ssh_dbg:stop(),
+ undefined = whereis(ssh_dbg).
+
+
+%%--------------------------------------------------------------------
+dbg_alg_terminate(Config) ->
+ SystemDir = proplists:get_value(data_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
+
+ Ref = ssh_dbg_start(),
+ {ok,[alg,connections,terminate]} = ssh_dbg:on([alg,terminate,connections]),
+ {ok,[alg,terminate]} = ssh_dbg:off(connections), % just testing that terminate is not canceled
+
+ Parent = self(),
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
+ {user_passwords, [{?USR,?PWD}]},
+ {connectfun, fun(_,_,_) ->
+ Parent ! {daemon_c,Ref,self()}
+ end},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+ C = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user_dir, UserDir},
+ {user,?USR},
+ {password,?PWD},
+ {user_interaction, false}]),
+
+ %% Daemon connection ref (D):
+ D = receive
+ {daemon_c,Ref,D0} -> D0
+ end,
+ ct:log("~p:~p~nC = ~p, D=~p",[?MODULE,?LINE, C, D]),
+
+ ?DBG_RECEIVE("Negotiated algorithms:", Ref, C, Pid),
+ ?DBG_RECEIVE("Negotiated algorithms:", Ref, D, Pid),
+
+ ssh:close(C),
+ ?DBG_RECEIVE("Connection Terminating:", Ref, C, Pid),
+ ?DBG_RECEIVE("Connection Terminating:", Ref, D, Pid),
+
+ stop_and_fail_if_unhandled_dbg_msgs(Ref, [C,D], Pid).
+
+%%--------------------------------------------------------------------
+dbg_connections(Config) ->
+ SystemDir = proplists:get_value(data_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
+
+ Ref = ssh_dbg_start(),
+ {ok,[connections,terminate]} = ssh_dbg:on([connections, terminate]),
+ {ok,[connections]} = ssh_dbg:off(terminate), % Just testing that terminate doesn't cancel connections
+
+ Parent = self(),
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
+ {user_passwords, [{?USR,?PWD}]},
+ {connectfun, fun(_,_,_) ->
+ Parent ! {daemon_c,Ref,self()}
+ end},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+
+ ?DBG_RECEIVE("Starting LISTENER on ", Ref, _, Pid),
+
+ C = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user_dir, UserDir},
+ {user,?USR},
+ {password,?PWD},
+ {user_interaction, false}]),
+
+ %% Daemon connection ref (D):
+ D = receive
+ {daemon_c,Ref,D0} -> D0
+ end,
+ ct:log("~p:~p~nC = ~p, D=~p",[?MODULE,?LINE, C, D]),
+
+ ?DBG_RECEIVE("Starting server connection:", Ref, D, Pid),
+ ?DBG_RECEIVE("Starting client connection:", Ref, C, Pid),
+
+ ssh:close(C),
+ ?DBG_RECEIVE("Connection Terminating:", Ref, C, Pid),
+ ?DBG_RECEIVE("Connection Terminating:", Ref, D, Pid),
+
+ stop_and_fail_if_unhandled_dbg_msgs(Ref, [C,D], Pid).
+
+%%--------------------------------------------------------------------
+dbg_ssh_messages(Config) ->
+ SystemDir = proplists:get_value(data_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
+
+ Parent = self(),
+ Ref = make_ref(),
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
+ {user_passwords, [{?USR,?PWD}]},
+ {connectfun, fun(_,_,_) ->
+ Parent ! {daemon_c,Ref,self()}
+ end},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+
+ ssh_dbg_start(Ref),
+ {ok,[ssh_messages]} = ssh_dbg:on([ssh_messages]),
+
+ C = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user_dir, UserDir},
+ {user,?USR},
+ {password,?PWD},
+ {user_interaction, false}]),
+
+ %% Daemon connection ref (D):
+ D = receive
+ {daemon_c,Ref,D0} -> D0
+ end,
+ ct:log("~p:~p~nC = ~p, D=~p",[?MODULE,?LINE, C, D]),
+
+ ?DBG_RECEIVE("Going to send hello message:", Ref, C, Pid),
+ ?DBG_RECEIVE("Received hello message:", Ref, D, Pid),
+
+ ?DBG_RECEIVE("Going to send hello message:", Ref, D, Pid),
+ ?DBG_RECEIVE("Received hello message:", Ref, C, Pid),
+
+ ?DBG_RECEIVE("Going to send SSH_MSG_KEXINIT:", Ref, C, Pid),
+ ?DBG_RECEIVE("Received SSH_MSG_KEXINIT:", Ref, D, Pid),
+
+ ?DBG_RECEIVE("Going to send SSH_MSG_KEXINIT:", Ref, D, Pid),
+ ?DBG_RECEIVE("Received SSH_MSG_KEXINIT:", Ref, C, Pid),
+
+ case atom_to_list( (ssh_connection_handler:alg(C))#alg.kex ) of
+ "ecdh-"++_ ->
+ ?DBG_RECEIVE("Going to send SSH_MSG_KEX_ECDH_INIT:", Ref, C, Pid),
+ ?DBG_RECEIVE("Received SSH_MSG_KEX_ECDH_INIT:", Ref, D, Pid),
+ ?DBG_RECEIVE("Going to send SSH_MSG_KEX_ECDH_REPLY:", Ref, D, Pid),
+ ?DBG_RECEIVE("Received SSH_MSG_KEX_ECDH_REPLY:", Ref, C, Pid);
+
+ "diffie-hellman-group-exchange-"++_ ->
+ ?DBG_RECEIVE("Going to send SSH_MSG_KEX_DH_GEX_REQUEST:", Ref, C, Pid),
+ ?DBG_RECEIVE("Received SSH_MSG_KEX_DH_GEX_REQUEST:", Ref, D, Pid),
+ ?DBG_RECEIVE("Going to send SSH_MSG_KEX_DH_GEX_GROUP:", Ref, D, Pid),
+ ?DBG_RECEIVE("Received SSH_MSG_KEX_DH_GEX_GROUP:", Ref, C, Pid),
+ ?DBG_RECEIVE("Going to send SSH_MSG_KEX_DH_GEX_INIT:", Ref, C, Pid),
+ ?DBG_RECEIVE("Received SSH_MSG_KEX_DH_GEX_INIT:", Ref, D, Pid),
+ ?DBG_RECEIVE("Going to send SSH_MSG_KEX_DH_GEX_REPLY:", Ref, D, Pid),
+ ?DBG_RECEIVE("Received SSH_MSG_KEX_DH_GEX_REPLY:", Ref, C, Pid);
+
+ "diffie-hellman-group"++_ ->
+ ?DBG_RECEIVE("Going to send SSH_MSG_KEXDH_INIT:", Ref, C, Pid),
+ ?DBG_RECEIVE("Received SSH_MSG_KEXDH_INIT:", Ref, D, Pid),
+ ?DBG_RECEIVE("Going to send SSH_MSG_KEXDH_REPLY:", Ref, D, Pid),
+ ?DBG_RECEIVE("Received SSH_MSG_KEXDH_REPLY:", Ref, C, Pid)
+ end,
+
+
+ ?DBG_RECEIVE("Going to send SSH_MSG_NEWKEYS:", Ref, C, Pid),
+ ?DBG_RECEIVE("Received SSH_MSG_NEWKEYS:", Ref, D, Pid),
+
+ ?DBG_RECEIVE("Going to send SSH_MSG_NEWKEYS:", Ref, D, Pid),
+ ?DBG_RECEIVE("Received SSH_MSG_NEWKEYS:", Ref, C, Pid),
+
+ ?DBG_RECEIVE("Going to send SSH_MSG_SERVICE_REQUEST:", Ref, C, Pid),
+ ?DBG_RECEIVE("Received SSH_MSG_SERVICE_REQUEST:", Ref, D, Pid),
+
+ ?DBG_RECEIVE("Going to send SSH_MSG_SERVICE_ACCEPT:", Ref, D, Pid),
+ ?DBG_RECEIVE("Received SSH_MSG_SERVICE_ACCEPT:", Ref, C, Pid),
+
+ ?DBG_RECEIVE("Going to send SSH_MSG_USERAUTH_REQUEST:", Ref, C, Pid),
+ ?DBG_RECEIVE("Received SSH_MSG_USERAUTH_REQUEST:", Ref, D, Pid),
+
+ ?DBG_RECEIVE("Going to send SSH_MSG_USERAUTH_FAILURE:", Ref, D, Pid),
+ ?DBG_RECEIVE("Received SSH_MSG_USERAUTH_FAILURE:", Ref, C, Pid),
+
+ ?DBG_RECEIVE("Going to send SSH_MSG_USERAUTH_REQUEST:", Ref, C, Pid),
+ ?DBG_RECEIVE("Received SSH_MSG_USERAUTH_REQUEST:", Ref, D, Pid),
+
+ ?DBG_RECEIVE("Going to send SSH_MSG_USERAUTH_SUCCESS:", Ref, D, Pid),
+ ?DBG_RECEIVE("Received SSH_MSG_USERAUTH_SUCCESS:", Ref, C, Pid),
+
+
+ UnexpectedMsgs =
+ dbg_SKIP(Ref,
+ [S_R ++ P ++ ":" || P <- ["SSH_MSG_USERAUTH_REQUEST",
+ "SSH_MSG_USERAUTH_INFO_REQUEST",
+ "SSH_MSG_USERAUTH_INFO_RESPONSE",
+ "SSH_MSG_USERAUTH_FAILURE",
+ "SSH_MSG_EXT_INFO"
+ ],
+ S_R <- ["Going to send ",
+ "Received "
+ ]
+ ]),
+
+ ssh:close(C),
+ stop_and_fail_if_unhandled_dbg_msgs(UnexpectedMsgs, Ref, [C,D], Pid).
+
+%%--------------------------------------------------------------------
+dbg_channels(Config) ->
+ SystemDir = proplists:get_value(data_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
+
+ Ref = ssh_dbg_start(),
+ {ok,[channels,connections]} = ssh_dbg:on([connections, channels]),
+
+ Parent = self(),
+ TimeoutShell =
+ fun() ->
+ io:format("TimeoutShell started!~n",[]),
+ timer:sleep(1000),
+ Parent ! {daemon_channel,Ref,self()},
+ ct:log("~p TIMEOUT!",[self()])
+ end,
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
+ {user_passwords, [{?USR,?PWD}]},
+ {connectfun, fun(_,_,_) ->
+ Parent ! {daemon_c,Ref,self()}
+ end},
+ {shell, fun(_User) ->
+ spawn(TimeoutShell)
+ end
+ },
+ {failfun, fun ssh_test_lib:failfun/2}]),
+
+ ?DBG_RECEIVE("Starting LISTENER on ", Ref, _, Pid),
+
+ C = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user_dir, UserDir},
+ {user,?USR},
+ {password,?PWD},
+ {user_interaction, false}]),
+ {ok, Ch0} = ssh_connection:session_channel(C, infinity),
+ ok = ssh_connection:shell(C, Ch0),
+
+ %% Daemon connection ref (D):
+ D = receive {daemon_c,Ref,D0} -> D0 end,
+
+ %% Daemon channel (Dch):
+ Dch = receive {daemon_channel,Ref,Dch0} -> Dch0 end,
+ ct:log("~p:~p~nC = ~p, D=~p, Dch=~p~n~s",[?MODULE,?LINE, C, D, Dch, ssh_info:string()]),
+
+ ?DBG_RECEIVE("Starting server connection:", Ref, D, Pid),
+ ?DBG_RECEIVE("Starting client connection:", Ref, C, Pid),
+ ?DBG_RECEIVE("Server Channel Starting:", Ref, _, Pid),
+ ?DBG_RECEIVE("Server Channel Terminating:", Ref, _, Pid),
+
+ stop_and_fail_if_unhandled_dbg_msgs(Ref, [C,D], Pid).
+
+%%--------------------------------------------------------------------
+cb_basic(_Config) ->
+ %% Check that the circular buffer is disabled at start:
+ [] = ssh_dbg:cbuf_list(),
+ disabled = ssh_dbg:cbuf_in(anything),
+ [] = ssh_dbg:cbuf_list(),
+ %% Start it and enter three values, first is duplicated;
+ ok = ssh_dbg:cbuf_start(3),
+ ok = ssh_dbg:cbuf_in(v1),
+ ok = ssh_dbg:cbuf_in(v1),
+ ok = ssh_dbg:cbuf_in(v2),
+ ok = ssh_dbg:cbuf_in(v3),
+ [{v3,_,1}, {v2,_,1}, {v1,_,2}] = ssh_dbg:cbuf_list(),
+ %% Check that a fourth value erase the first entered:
+ ok = ssh_dbg:cbuf_in(v4),
+ [{v4,_,1}, {v3,_,1}, {v2,_,1}] = ssh_dbg:cbuf_list(),
+ %% Check that entering a value that is in the tail but not in the head is treated as a new value:
+ ok = ssh_dbg:cbuf_in(v2),
+ [{v2,_,1}, {v4,_,1}, {v3,_,1}] = ssh_dbg:cbuf_list(),
+ %% Stop and check that the buffer is returned:
+ [{v2,_,1}, {v4,_,1}, {v3,_,1}] = ssh_dbg:cbuf_stop_clear(),
+ %% Stopping a stopped buffer returns empty:
+ [] = ssh_dbg:cbuf_stop_clear(),
+ %% Check that a value can't be entered in a stopped buffer:
+ disabled = ssh_dbg:cbuf_in(v2).
+
+%%--------------------------------------------------------------------
+cb_print(_Config) ->
+ ssh_dbg:cbuf_start(),
+ [begin
+ ssh_dbg:cbuf_in(V),
+ ct:log("Enter ~p",[V])
+ end || V <- lists:seq(1,10)],
+ ct:log("~s",[ssh_dbg:fmt_cbuf_items()]),
+ ssh_dbg:cbuf_stop_clear().
+
+%%--------------------------------------------------------------------
+cb_macros_print(_Config) ->
+ ssh_dbg:cbuf_start(),
+ [begin
+ V = {test,V0},
+ ?CIRC_BUF_IN(V),
+ ct:log("Enter ~p",[V])
+ end || V0 <- lists:seq(1,5)],
+ ct:log("~s",[ssh_dbg:fmt_cbuf_items()]),
+ ssh_dbg:cbuf_stop_clear().
+
+%%--------------------------------------------------------------------
+%%--------------------------------------------------------------------
+%%--------------------------------------------------------------------
+
+ssh_dbg_start() ->
+ ssh_dbg_start(make_ref()).
+
+ssh_dbg_start(Ref) ->
+ Parent = self(),
+ [_|_] = ssh_dbg:start(fun(_F,A) ->
+ Parent ! {Ref,A}
+ end),
+ Ref.
+
+%%--------------------------------------------------------------------
+queued_msgs(Ref, Conns) ->
+ queued_msgs(Ref, Conns, []).
+
+queued_msgs(Ref, Conns, Acc) ->
+ receive
+ {Ref, [_, C, _]=Msg} ->
+ case is_list(Conns) andalso lists:member(C, Conns) of
+ true ->
+ queued_msgs(Ref, [Msg|Acc]);
+ false ->
+ queued_msgs(Ref, Conns, Acc)
+ end
+ after 0 ->
+ lists:reverse(Acc)
+ end.
+
+%%--------------------------------------------------------------------
+stop_and_fail_if_unhandled_dbg_msgs(Ref, Conns, DaemonPid) ->
+ stop_and_fail_if_unhandled_dbg_msgs(queued_msgs(Ref,Conns), Ref, Conns, DaemonPid).
+
+stop_and_fail_if_unhandled_dbg_msgs(Msgs, _Ref, _Conns, DaemonPid) ->
+ ssh:stop_daemon(DaemonPid),
+ case Msgs of
+ [] ->
+ ok;
+ _ ->
+ ct:log("Unexpected messages:~n~p",[Msgs]),
+ ct:fail("Unexpected messages")
+ end.
+
+%%--------------------------------------------------------------------
+dbg_SKIP(Ref, Prefixes) ->
+ dbg_SKIP(Ref, Prefixes, []).
+
+dbg_SKIP(Ref, Prefixes, UnexpectedAcc) ->
+ receive
+ {Ref, [_, _C, Msg]=M} ->
+ case lists:any(
+ fun(Pfx) ->
+ lists:prefix(Pfx, Msg)
+ end, Prefixes) of
+ true ->
+ ct:log("Skip:~n~p", [M]),
+ dbg_SKIP(Ref, Prefixes, UnexpectedAcc);
+ false ->
+ dbg_SKIP(Ref, Prefixes, [Msg|UnexpectedAcc])
+ end
+ after 0 ->
+ lists:reverse(UnexpectedAcc)
+ end.
+
diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_dsa_key
new file mode 100644
index 0000000000..51ab6fbd88
--- /dev/null
+++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_dsa_key
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK
+wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q
+diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA
+l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X
+skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF
+Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP
+ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah
+/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U
+ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W
+Lv62jKcdskxNyz2NQoBx
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_dsa_key.pub
new file mode 100644
index 0000000000..4dbb1305b0
--- /dev/null
+++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_dsa_key.pub
@@ -0,0 +1,11 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j
+YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2
+KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU
+aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI
+fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT
+MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh
+DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48
+wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2
+/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key256 b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key256
new file mode 100644
index 0000000000..2979ea88ed
--- /dev/null
+++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key256
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIMe4MDoit0t8RzSVPwkCBemQ9fhXL+xnTSAWISw8HNCioAoGCCqGSM49
+AwEHoUQDQgAEo2q7U3P6r0W5WGOLtM78UQtofM9UalEhiZeDdiyylsR/RR17Op0s
+VPGSADLmzzgcucLEKy17j2S+oz42VUJy5A==
+-----END EC PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key256.pub b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key256.pub
new file mode 100644
index 0000000000..85dc419345
--- /dev/null
+++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key256.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKNqu1Nz+q9FuVhji7TO/FELaHzPVGpRIYmXg3YsspbEf0UdezqdLFTxkgAy5s84HLnCxCste49kvqM+NlVCcuQ= uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key384 b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key384
new file mode 100644
index 0000000000..fb1a862ded
--- /dev/null
+++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key384
@@ -0,0 +1,6 @@
+-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDArxbDfh3p1okrD9wQw6jJ4d4DdlBPD5GqXE8bIeRJiK41Sh40LgvPw
+mkqEDSXK++CgBwYFK4EEACKhZANiAAScl43Ih2lWTDKrSox5ve5uiTXil4smsup3
+CfS1XPjKxgBAmlfBim8izbdrT0BFdQzz2joduNMtpt61wO4rGs6jm0UP7Kim9PC7
+Hneb/99fIYopdMH5NMnk60zGO1uZ2vc=
+-----END EC PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key384.pub b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key384.pub
new file mode 100644
index 0000000000..428d5fb7d7
--- /dev/null
+++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key384.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBJyXjciHaVZMMqtKjHm97m6JNeKXiyay6ncJ9LVc+MrGAECaV8GKbyLNt2tPQEV1DPPaOh240y2m3rXA7isazqObRQ/sqKb08Lsed5v/318hiil0wfk0yeTrTMY7W5na9w== uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key521 b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key521
new file mode 100644
index 0000000000..3e51ec2ecd
--- /dev/null
+++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key521
@@ -0,0 +1,7 @@
+-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIB8O1BFkl2HQjQLRLonEZ97da/h39DMa9/0/hvPZWAI8gUPEQcHxRx
+U7b09p3Zh+EBbMFq8+1ae9ds+ZTxE4WFSvKgBwYFK4EEACOhgYkDgYYABAAlWVjq
+Bzg7Wt4gE6UNb1lRE2cnlmH2L/A5uo6qZRx5lPnSKOxEhxSb/Oay1+9d6KRdrh6/
+vlhd9SHDBhLcAPDvWgBnJIEj92Q3pXX4JtoitL0yl+SvvU+vUh966mzHShHzj8p5
+ccOgPkPNoA70yrpGzkIhPezpZOQdCaOXj/jFqNCTDg==
+-----END EC PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key521.pub b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key521.pub
new file mode 100644
index 0000000000..017a29f4da
--- /dev/null
+++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_ecdsa_key521.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAAlWVjqBzg7Wt4gE6UNb1lRE2cnlmH2L/A5uo6qZRx5lPnSKOxEhxSb/Oay1+9d6KRdrh6/vlhd9SHDBhLcAPDvWgBnJIEj92Q3pXX4JtoitL0yl+SvvU+vUh966mzHShHzj8p5ccOgPkPNoA70yrpGzkIhPezpZOQdCaOXj/jFqNCTDg== uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_rsa_key b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_rsa_key
new file mode 100644
index 0000000000..79968bdd7d
--- /dev/null
+++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_rsa_key
@@ -0,0 +1,16 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8semM4q843337
+zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RWRWzjaxSB
+6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4QIDAQAB
+AoGANmvJzJO5hkLuvyDZHKfAnGTtpifcR1wtSa9DjdKUyn8vhKF0mIimnbnYQEmW
+NUUb3gXCZLi9PvkpRSVRrASDOZwcjoU/Kvww163vBUVb2cOZfFhyn6o2Sk88Tt++
+udH3hdjpf9i7jTtUkUe+QYPsia+wgvvrmn4QrahLAH86+kECQQDx5gFeXTME3cnW
+WMpFz3PPumduzjqgqMMWEccX4FtQkMX/gyGa5UC7OHFyh0N/gSWvPbRHa8A6YgIt
+n8DO+fh5AkEAzbqX4DOn8NY6xJIi42q7l/2jIA0RkB6P7YugW5NblhqBZ0XDnpA5
+sMt+rz+K07u9XZtxgh1xi7mNfwY6lEAMqQJBAJBEauCKmRj35Z6OyeQku59SPsnY
++SJEREVvSNw2lH9SOKQQ4wPsYlTGbvKtNVZgAcen91L5MmYfeckYE/fdIZECQQCt
+64zxsTnM1I8iFxj/gP/OYlJBikrKt8udWmjaghzvLMEw+T2DExJyb9ZNeT53+UMB
+m6O+B/4xzU/djvp+0hbhAkAemIt+rA5kTmYlFndhpvzkSSM8a2EXsO4XIPgGWCTT
+tQKS/tTly0ADMjN/TVy11+9d6zcqadNVuHXHGtR4W0GR
+-----END RSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_rsa_key.pub b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_rsa_key.pub
new file mode 100644
index 0000000000..75d2025c71
--- /dev/null
+++ b/lib/ssh/test/ssh_dbg_SUITE_data/ssh_host_rsa_key.pub
@@ -0,0 +1,5 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1yc2EAAAADAQABAAAAgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8
+semM4q843337zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RW
+RWzjaxSB6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4Q==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssh/test/ssh_echo_server.erl b/lib/ssh/test/ssh_echo_server.erl
index 5387d21efd..e039439f87 100644
--- a/lib/ssh/test/ssh_echo_server.erl
+++ b/lib/ssh/test/ssh_echo_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@
%%% Description: Example ssh server
-module(ssh_echo_server).
--behaviour(ssh_daemon_channel).
+-behaviour(ssh_server_channel).
-record(state, {
n,
id,
diff --git a/lib/ssh/test/ssh_engine_SUITE.erl b/lib/ssh/test/ssh_engine_SUITE.erl
new file mode 100644
index 0000000000..c2e6ac1fee
--- /dev/null
+++ b/lib/ssh/test/ssh_engine_SUITE.erl
@@ -0,0 +1,146 @@
+%%
+%% %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(ssh_engine_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-include("ssh_test_lib.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{seconds,40}}].
+
+all() ->
+ [{group, dsa_key},
+ {group, rsa_key}
+ ].
+
+groups() ->
+ [{dsa_key, [], basic_tests()},
+ {rsa_key, [], basic_tests()}
+ ].
+
+basic_tests() ->
+ [simple_connect
+ ].
+
+
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ ssh:start(),
+ ?CHECK_CRYPTO(
+ case crypto:info_lib() of
+ [{_,_, <<"OpenSSL 1.0.1s-freebsd 1 Mar 2016">>}] ->
+ {skip, "Strange Engine stuff"};
+
+ _ ->
+ case load_engine() of
+ {ok,E} ->
+ [{engine,E}|Config];
+ {error, notsup} ->
+ {skip, "Engine not supported on this OpenSSL version"};
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"};
+ Other ->
+ ct:log("Engine load failed: ~p",[Other]),
+ {fail, "Engine load failed"}
+ end
+ end
+ ).
+
+end_per_suite(Config) ->
+ catch crypto:engine_unload( proplists:get_value(engine,Config) ),
+ ssh:stop().
+
+%%--------------------------------------------------------------------
+init_per_group(dsa_key, Config) ->
+ case lists:member('ssh-dss',
+ ssh_transport:default_algorithms(public_key)) of
+ true ->
+ start_daemon(Config, 'ssh-dss', "dsa_private_key.pem");
+ false ->
+ {skip, unsupported_pub_key}
+ end;
+init_per_group(rsa_key, Config) ->
+ case lists:member('ssh-rsa',
+ ssh_transport:default_algorithms(public_key)) of
+ true ->
+ start_daemon(Config, 'ssh-rsa', "rsa_private_key.pem");
+ false ->
+ {skip, unsupported_pub_key}
+ end.
+
+start_daemon(Config, KeyType, KeyId) ->
+ SystemDir = proplists:get_value(data_dir, Config),
+ FullKeyId = filename:join(SystemDir, KeyId),
+ KeyCBOpts = [{engine, proplists:get_value(engine,Config)},
+ {KeyType, FullKeyId}
+ ],
+ Opts = [{key_cb, {ssh_key_cb_engine_keys, KeyCBOpts}}],
+ {Pid, Host, Port} = ssh_test_lib:std_daemon(Config, Opts),
+ [{host_port,{Host,Port}}, {daemon_pid,Pid}| Config].
+
+
+end_per_group(_, Config) ->
+ catch ssh:stop_daemon(proplists:get_value(daemon_pid,Config)),
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+%% A simple exec call
+simple_connect(Config) ->
+ {Host,Port} = proplists:get_value(host_port, Config),
+ CRef = ssh_test_lib:std_connect(Config, Host, Port, []),
+ ssh:close(CRef).
+
+%%--------------------------------------------------------------------
+%%--------------------------------------------------------------------
+load_engine() ->
+ case crypto:get_test_engine() of
+ {ok, Engine} ->
+ try crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ [])
+ catch
+ error:notsup ->
+ {error, notsup}
+ end;
+
+ {error, Error} ->
+ {error, Error}
+ end.
+
+start_std_daemon(Opts, Config) ->
+ ct:log("starting std_daemon",[]),
+ {Pid, Host, Port} = ssh_test_lib:std_daemon(Config, Opts),
+ ct:log("started ~p:~p ~p",[Host,Port,Opts]),
+ [{srvr_pid,Pid},{srvr_addr,{Host,Port}} | Config].
diff --git a/lib/ssh/test/ssh_engine_SUITE_data/dsa_private_key.pem b/lib/ssh/test/ssh_engine_SUITE_data/dsa_private_key.pem
new file mode 100644
index 0000000000..778ffac675
--- /dev/null
+++ b/lib/ssh/test/ssh_engine_SUITE_data/dsa_private_key.pem
@@ -0,0 +1,9 @@
+-----BEGIN PRIVATE KEY-----
+MIIBSwIBADCCASwGByqGSM44BAEwggEfAoGBAMyitTMR7vPbpqyAXJpqnB0AhFwQ
+F87IE+JKFl5bD/MSkhhRV5sM73HUU1ooXY0FjhZ+cdLUCATuZR5ta4ydANqWIcAB
+gX3IwF1B4zf5SXEKTWkUYneL9dOKtiZLtoG28swrk8xMxwX+0fLHkltCEj6FiTW9
+PFrv8GmIfV6DjcI9AhUAqXWbb3RtoN9Ld28fVMhGZrj3LJUCgYEAwnxGHGBMpJaF
+2w7zAw3jHjL8PMYlV6vnufGHQlwF0ZUXJxRsvagMb/X1qACTu2VPYEVoLQGM3cfH
+EhHoQmvSXGAyTfR7Bmn3gf1n/s/DcFbdZduUCZ/rAyIrfd0eSbc1I+kZk85UCsKK
+w/IYdlqcuYa4Cgm2TapT5uEMqH4jhzEEFgIULh8swEUWmU8aJNWsrWl4eCiuUUg=
+-----END PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_engine_SUITE_data/ecdsa_private_key.pem b/lib/ssh/test/ssh_engine_SUITE_data/ecdsa_private_key.pem
new file mode 100644
index 0000000000..a45522064f
--- /dev/null
+++ b/lib/ssh/test/ssh_engine_SUITE_data/ecdsa_private_key.pem
@@ -0,0 +1,8 @@
+-----BEGIN PRIVATE KEY-----
+MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIBparGjr0KcdNrVM2J
+G0mW5ltP1QyvxDqBMyWLWo3fruRZv6Qoohl5skd1u4O+KJoM/UrrSTOXI/MDR7NN
+i1yl7O+hgYkDgYYABAG8K2XVsK0ahG9+HIIPwCO0pJY8ulwSTXwIjkCGyB2lpglh
+8qJmRzuyGcfRTslv8wfv0sPlT9H9PKDvgrTUL7rvQQDdOODNgVPXSecUoXoPn+X+
+eqxs77bjx+A5x0t/i3m5PfkaNPh5MZ1H/bWuOOdj2ZXZw0R4rlVc0zVrgnPU8L8S
+BQ==
+-----END PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_engine_SUITE_data/rsa_private_key.pem b/lib/ssh/test/ssh_engine_SUITE_data/rsa_private_key.pem
new file mode 100644
index 0000000000..ea0e3d3958
--- /dev/null
+++ b/lib/ssh/test/ssh_engine_SUITE_data/rsa_private_key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCwwb0/ddXGXTFK
+4FLxXdV6a/WJMSoPPS55RvZIAHFsiTtvPLbJ8LxDsZ6wSVZLN0/UQ4wdWn9jftyj
+U5/IxBVG8XOtKimTMvm3/ZOzVLueGHBbrLYscRv9oL85ulTKHWgrZDu0lBX5JJTI
+v5UTCErzJRQbka9DG1GaBgDb1PlXfkzBWMwfsBZmwoC77KvCcIGCgbW/XCY03TP2
+3Tg8drvpByMStddP2FQ4fZ91qFUzPu8uhZEsqSQTFlmhgGEx7dLlky0xvu62RuAD
+RTpINpcWZtWDHTdssOqu653LwwqBY8lBopCZ/4Af8QR3ZYkQhen1YLEbVheXRuzI
+LSCZIiJNAgMBAAECggEBAJH4/fxpqQkvr2Shy33Pu1xlyhnpw01gfn/jrcKasxEq
+aC4eWup86E2TY3U8q4pkfIXU3uLi+O9HNpmflwargNLc1mY8uqb44ygiv5bLNEKE
+9k2PXcdoBfC4jxPyoNFl5cBn/7LK1TazEjiTl15na9ZPWcLG1pG5/vMPYCgsQ1sP
+8J3c4E3aaXIj9QceYxBprl490OCzieGyZlRipncz3g4UShRc/b4cycvDZOJpmAy4
+zbWTcBcSMPVPi5coF0K8UcimiqZkotfb/2RLc433i34IdsIXMM+brdq+g8rmjg5a
++oQPy02M6tFApBruEhAz8DGgaLtDY6MLtyZAt3SjXnUCgYEA1zLgamdTHOqrrmIi
+eIQBnAJiyIfcY8B9SX1OsLGYFCHiPVwgUY35B2c7MavMsGcExJhtE+uxU7o5djtM
+R6r9cRHOXJ6EQwa8OwzzPqbM17/YqNDeK39bc9WOFUqRWrhDhVMPy6z8rmZr73mG
+IUC7mBNx/1GBdVYXIlsXzC96dI8CgYEA0kUAhz6I5nyPa70NDEUYHLHf3IW1BCmE
+UoVbraSePJtIEY/IqFx7oDuFo30d4n5z+8ICCtyid1h/Cp3mf3akOiqltYUfgV1G
+JgcEjKKYWEnO7cfFyO7LB7Y3GYYDJNy6EzVWPiwTGk9ZTfFJEESmHC45Unxgd17m
+Dx/R58rFgWMCgYBQXQWFdtSI5fH7C1bIHrPjKNju/h2FeurOuObcAVZDnmu4cmD3
+U8d9xkVKxVeJQM99A1coq0nrdI3k4zwXP3mp8fZYjDHkPe2pN6rW6L9yiohEcsuk
+/siON1/5/4DMmidM8LnjW9R45HLGWWGHpX7oyco2iJ+Jy/6Tq+T1MX3PbQKBgQCm
+hdsbQJ0u3CrBSmFQ/E9SOlRt0r4+45pVuCOY6yweF2QF9HcXTtbhWQJHLclDHJ5C
+Ha18aKuKFN3XzKFFBPKe1jOSBDGlQ/dQGnKx5fr8wMdObM3oiaTlIJuWbRmEUgJT
+QARjDIi8Z2b0YUhZx+Q9oSXoe3PyVYehJrQX+/BavQKBgQCIr7Zp0rQPbfqcTL+M
+OYHUoNcb14f9f8hXeXHQOqVpsGwxGdRQAU9wbx/4+obKB5xIkzBsVNcJwavisNja
+hegnGjTB/9Hc4m+5bMGwH0bhS2eQO4o+YYM2ypDmFQqDLRfFUlZ5PVHffm/aA9+g
+GanNBCsmtoHtV6CJ1UZ7NmBuIA==
+-----END PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_engine_SUITE_data/rsa_private_key_pwd.pem b/lib/ssh/test/ssh_engine_SUITE_data/rsa_private_key_pwd.pem
new file mode 100644
index 0000000000..501662fc35
--- /dev/null
+++ b/lib/ssh/test/ssh_engine_SUITE_data/rsa_private_key_pwd.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIh888Iq6gxuMCAggA
+MBQGCCqGSIb3DQMHBAic/11YZ8Nt5gSCBMjG/Jb4qiMoBS50iQvHXqcETPE+0NBr
+jhsn9w94LkdRBstMPAsoKmY98Er96Rnde/NfmqlU9CupKTkd7Ce5poBf72Y6KMED
+cPURyjbGRFsu6x9skXB2obhyKYEqAEF2oQAg4Qbe5v1qXBIgDuC/NgiJnM+w2zCZ
+LkHSZB2/NmcnvDzcgPF7TM8pTO23xCJ33m37qjfWvHsgocVqZmL9wQ4+wr/NMYjJ
+pJvX1OHW1vBsZsXh40WchalYRSB1VeO368QfsE8coRJztqbMzdce9EQdMB6Q6jlO
+cetd3moLIoMP4I7HW0/SgokbycTbRiYSvRyU1TGc2WbW6BrFZV24IckcnnVUFatf
+6HKUcaYLG68dJcRgs5QMGkcmgVvlddENHFmHZlo0eym/xSiUl/AT8/5odscm6ML8
+wW5sneax+TF4J2eYmiN7yjAUCodXVTNYNDVKo6uUhntlymbM0o4UitVIbPIfTDHl
+sxJAEZ7vpuPqeNMxUk6G6zipuEjqsVbnuFSBSZmgKiGYcifRPUmqqINa3DdS4WVx
+xaPWdHbHVRD//ze3h/FsA+1lIE5q2kUE0xXseJA1ISog++kJp14XeaaL2j/tx3Ob
+OsbcaOAD/IUw/ItDt9kn0qzfnar7sS0Wov8AmJQxHmH7Lm93jHTLM05yE0AR/eBr
+Mig2ZdC+9OqVC+GPuBkRjSs8NpltQIDroz6EV9IMwPwXm0szSYoyoPLmlHJUdnLs
+ZUef+au6hYkEJBrvuisagnq5eT/fCV3hsjD7yODebNU2CmBTo6X2PRx/xsBHRMWl
+QkoM9PBdSCnKv6HpHl4pchuoqU2NpFjN0BCaad6aHfZSTnqgzK4bEh1oO6dI8/rB
+/eh71JyFFG5J4xbpaqz5Su01V1iwU5leK5bDwqals4M4+ZGHGciou7qnXUmX2fJl
+r6DlMUa/xy+A2ZG0NuZR05yk2oB3+KVNMgp6zFty3XaxwoNtc8GTLtLnBnIh2rlP
+mE1+I65LRWwrNQalPeOAUrYuEzhyp2Df7a8Ykas5PUH7MGR/S0Ge/dLxtE2bJuK4
+znbLAsGhvo/SbNxYqIp6D4iDtd3va6yUGncy41paA/vTKFVvXZDrXcwJQYYCVOGT
+OwdzNuozU8Dc7oxsd8oakfC46kvmVaOrGvZbm56PFfprcaL/Hslska5xxEni/eZe
+WRxZbCBhAVqS1pn5zkDQVUe9uFlR/x39Qi01HIlKLBsjpSs6qQsFArMe8hgXmXLG
+xP+dyVuOE18NzSewdEjeqSRKIM7Qi8EOjZsI4HdSRBY7bh9VhmaVXDZiCSf33TTE
+3y8nimzQAeuGoYg6WqHmWWC2Qnpki2HlaIH/ayXEyQWkP/qvg61e8ovdg9Fy8JOO
+0AacXVt5zj0q00AW5bKx7usi4NIjZedi86hUm6H19aBm7r86BKjwYTEI/GOcdrbV
+9HC/8ayOimgwiAG3gq+aLioWym+Z6KnsbVd7XReVbvM/InQx54WA2y5im0A+/c67
+oQFFPV84XGX9waeqv/K4Wzkm6HW+qVAEM67482VGOf0PVrlQMno6dOotT/Y7ljoZ
+2iz0LmN9yylJnLPDrr1i6gzbs5OhhUgbF5LI2YP2wWdCZTl/DrKSIvQZWl8U+tw3
+ciA=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_key_cb_engine_keys.erl b/lib/ssh/test/ssh_key_cb_engine_keys.erl
new file mode 100644
index 0000000000..fc9cbfd49b
--- /dev/null
+++ b/lib/ssh/test/ssh_key_cb_engine_keys.erl
@@ -0,0 +1,62 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2015-2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+
+%% Note: This module is used by ssh_basic_SUITE
+
+-module(ssh_key_cb_engine_keys).
+-behaviour(ssh_server_key_api).
+-compile(export_all).
+
+host_key(SshAlg, Options) ->
+ KBopts = proplists:get_value(key_cb_private, Options, []),
+ Engine = proplists:get_value(engine, KBopts),
+ case proplists:get_value(SshAlg, KBopts) of
+ undefined ->
+ {error, {unknown_alg,SshAlg}};
+ KeyId ->
+ case crypto_alg(SshAlg) of
+ undefined ->
+ {error, {unsupported_alg,SshAlg}};
+ CryptoAlg ->
+ PrivKey = #{engine => Engine,
+ key_id => KeyId,
+ algorithm => CryptoAlg},
+ %% Is there a key with this reference ?
+ case crypto:privkey_to_pubkey(CryptoAlg, PrivKey) of
+ [_|_] ->
+ {ok, PrivKey};
+ _ ->
+ {error, {no_hostkey,SshAlg}}
+ end
+ end
+ end.
+
+is_auth_key(_PublicUserKey, _User, _Options) ->
+ false.
+
+
+
+crypto_alg('ssh-rsa') -> rsa;
+crypto_alg('ssh-dss') -> dss;
+crypto_alg(_) -> undefined.
+
diff --git a/lib/ssh/test/ssh_options_SUITE.erl b/lib/ssh/test/ssh_options_SUITE.erl
index 8b454ffe5d..daf62483cd 100644
--- a/lib/ssh/test/ssh_options_SUITE.erl
+++ b/lib/ssh/test/ssh_options_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,7 +36,9 @@
id_string_no_opt_client/1,
id_string_no_opt_server/1,
id_string_own_string_client/1,
+ id_string_own_string_client_trail_space/1,
id_string_own_string_server/1,
+ id_string_own_string_server_trail_space/1,
id_string_random_client/1,
id_string_random_server/1,
max_sessions_sftp_start_channel_parallel/1,
@@ -68,7 +70,8 @@
hostkey_fingerprint_check_sha256/1,
hostkey_fingerprint_check_sha384/1,
hostkey_fingerprint_check_sha512/1,
- hostkey_fingerprint_check_list/1
+ hostkey_fingerprint_check_list/1,
+ save_accepted_host_option/1
]).
%%% Common test callbacks
@@ -116,10 +119,13 @@ all() ->
hostkey_fingerprint_check_list,
id_string_no_opt_client,
id_string_own_string_client,
+ id_string_own_string_client_trail_space,
id_string_random_client,
id_string_no_opt_server,
id_string_own_string_server,
+ id_string_own_string_server_trail_space,
id_string_random_server,
+ save_accepted_host_option,
{group, hardening_tests}
].
@@ -202,32 +208,23 @@ end_per_group(_, Config) ->
%%--------------------------------------------------------------------
init_per_testcase(_TestCase, Config) ->
ssh:start(),
- Config.
-
-end_per_testcase(TestCase, Config) when TestCase == server_password_option;
- TestCase == server_userpassword_option;
- TestCase == server_pwdfun_option;
- TestCase == server_pwdfun_4_option ->
+ %% Create a clean user_dir
UserDir = filename:join(proplists:get_value(priv_dir, Config), nopubkey),
ssh_test_lib:del_dirs(UserDir),
- end_per_testcase(Config);
-end_per_testcase(_TestCase, Config) ->
- end_per_testcase(Config).
+ file:make_dir(UserDir),
+ [{user_dir,UserDir}|Config].
-end_per_testcase(_Config) ->
+end_per_testcase(_TestCase, Config) ->
ssh:stop(),
ok.
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
-%%--------------------------------------------------------------------
%%% validate to server that uses the 'password' option
server_password_option(Config) when is_list(Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
+ UserDir = proplists:get_value(user_dir, Config),
SysDir = proplists:get_value(data_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
@@ -258,12 +255,10 @@ server_password_option(Config) when is_list(Config) ->
%%% validate to server that uses the 'password' option
server_userpassword_option(Config) when is_list(Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
+ UserDir = proplists:get_value(user_dir, Config),
SysDir = proplists:get_value(data_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
- {user_dir, PrivDir},
+ {user_dir, UserDir},
{user_passwords, [{"vego", "morot"}]}]),
ConnectionRef =
@@ -293,15 +288,13 @@ server_userpassword_option(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
%%% validate to server that uses the 'pwdfun' option
server_pwdfun_option(Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
+ UserDir = proplists:get_value(user_dir, Config),
SysDir = proplists:get_value(data_dir, Config),
CHKPWD = fun("foo",Pwd) -> Pwd=="bar";
(_,_) -> false
end,
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
- {user_dir, PrivDir},
+ {user_dir, UserDir},
{pwdfun,CHKPWD}]),
ConnectionRef =
ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
@@ -331,9 +324,7 @@ server_pwdfun_option(Config) ->
%%--------------------------------------------------------------------
%%% validate to server that uses the 'pwdfun/4' option
server_pwdfun_4_option(Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
+ UserDir = proplists:get_value(user_dir, Config),
SysDir = proplists:get_value(data_dir, Config),
PWDFUN = fun("foo",Pwd,{_,_},undefined) -> Pwd=="bar";
("fie",Pwd,{_,_},undefined) -> {Pwd=="bar",new_state};
@@ -341,7 +332,7 @@ server_pwdfun_4_option(Config) ->
(_,_,_,_) -> false
end,
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
- {user_dir, PrivDir},
+ {user_dir, UserDir},
{pwdfun,PWDFUN}]),
ConnectionRef1 =
ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
@@ -391,9 +382,7 @@ server_pwdfun_4_option(Config) ->
%%--------------------------------------------------------------------
server_pwdfun_4_option_repeat(Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
+ UserDir = proplists:get_value(user_dir, Config),
SysDir = proplists:get_value(data_dir, Config),
%% Test that the state works
Parent = self(),
@@ -402,7 +391,7 @@ server_pwdfun_4_option_repeat(Config) ->
(_,P,_,S) -> Parent!{P,S}, {false,S+1}
end,
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
- {user_dir, PrivDir},
+ {user_dir, UserDir},
{auth_methods,"keyboard-interactive"},
{pwdfun,PWDFUN}]),
@@ -486,9 +475,7 @@ user_dir_option(Config) ->
%%--------------------------------------------------------------------
%%% validate client that uses the 'ssh_msg_debug_fun' option
ssh_msg_debug_fun_option_client(Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
+ UserDir = proplists:get_value(user_dir, Config),
SysDir = proplists:get_value(data_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
@@ -526,9 +513,7 @@ ssh_msg_debug_fun_option_client(Config) ->
%%--------------------------------------------------------------------
connectfun_disconnectfun_server(Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
+ UserDir = proplists:get_value(user_dir, Config),
SysDir = proplists:get_value(data_dir, Config),
Parent = self(),
@@ -572,9 +557,7 @@ connectfun_disconnectfun_server(Config) ->
%%--------------------------------------------------------------------
connectfun_disconnectfun_client(Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
+ UserDir = proplists:get_value(user_dir, Config),
SysDir = proplists:get_value(data_dir, Config),
Parent = self(),
@@ -603,9 +586,7 @@ connectfun_disconnectfun_client(Config) ->
%%--------------------------------------------------------------------
%%% validate client that uses the 'ssh_msg_debug_fun' option
ssh_msg_debug_fun_option_server(Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
+ UserDir = proplists:get_value(user_dir, Config),
SysDir = proplists:get_value(data_dir, Config),
Parent = self(),
@@ -647,9 +628,7 @@ ssh_msg_debug_fun_option_server(Config) ->
%%--------------------------------------------------------------------
disconnectfun_option_server(Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
+ UserDir = proplists:get_value(user_dir, Config),
SysDir = proplists:get_value(data_dir, Config),
Parent = self(),
@@ -682,9 +661,7 @@ disconnectfun_option_server(Config) ->
%%--------------------------------------------------------------------
disconnectfun_option_client(Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
+ UserDir = proplists:get_value(user_dir, Config),
SysDir = proplists:get_value(data_dir, Config),
Parent = self(),
@@ -716,9 +693,7 @@ disconnectfun_option_client(Config) ->
%%--------------------------------------------------------------------
unexpectedfun_option_server(Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
+ UserDir = proplists:get_value(user_dir, Config),
SysDir = proplists:get_value(data_dir, Config),
Parent = self(),
@@ -759,9 +734,7 @@ unexpectedfun_option_server(Config) ->
%%--------------------------------------------------------------------
unexpectedfun_option_client(Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
+ UserDir = proplists:get_value(user_dir, Config),
SysDir = proplists:get_value(data_dir, Config),
Parent = self(),
@@ -836,14 +809,9 @@ supported_hash(HashAlg) ->
really_do_hostkey_fingerprint_check(Config, HashAlg) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- UserDirServer = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDirServer),
+ UserDir = proplists:get_value(user_dir, Config),
SysDir = proplists:get_value(data_dir, Config),
- UserDirClient =
- ssh_test_lib:create_random_dir(Config), % Ensure no 'known_hosts' disturbs
-
%% All host key fingerprints. Trust that public_key has checked the ssh_hostkey_fingerprint
%% function since that function is used by the ssh client...
FPs0 = [case HashAlg of
@@ -869,7 +837,7 @@ really_do_hostkey_fingerprint_check(Config, HashAlg) ->
%% Start daemon with the public keys that we got fingerprints from
{Pid, Host0, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
- {user_dir, UserDirServer},
+ {user_dir, UserDir},
{password, "morot"}]),
Host = ssh_test_lib:ntoa(Host0),
FP_check_fun = fun(PeerName, FP) ->
@@ -892,7 +860,8 @@ really_do_hostkey_fingerprint_check(Config, HashAlg) ->
end},
{user, "foo"},
{password, "morot"},
- {user_dir, UserDirClient},
+ {user_dir, UserDir},
+ {save_accepted_host, false}, % Ensure no 'known_hosts' disturbs
{user_interaction, false}]),
ssh:stop_daemon(Pid).
@@ -983,9 +952,7 @@ ms_passed(T0) ->
%%--------------------------------------------------------------------
ssh_daemon_minimal_remote_max_packet_size_option(Config) ->
SystemDir = proplists:get_value(data_dir, Config),
- PrivDir = proplists:get_value(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
+ UserDir = proplists:get_value(user_dir, Config),
{Server, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{user_dir, UserDir},
@@ -1035,6 +1002,19 @@ id_string_own_string_client(Config) ->
end.
%%--------------------------------------------------------------------
+id_string_own_string_client_trail_space(Config) ->
+ {Server, _Host, Port} = fake_daemon(Config),
+ {error,_} = ssh:connect("localhost", Port, [{id_string,"Pelle "}], 1000),
+ receive
+ {id,Server,"SSH-2.0-Pelle \r\n"} ->
+ ok;
+ {id,Server,Other} ->
+ ct:fail("Unexpected id: ~s.",[Other])
+ after 5000 ->
+ {fail,timeout}
+ end.
+
+%%--------------------------------------------------------------------
id_string_random_client(Config) ->
{Server, _Host, Port} = fake_daemon(Config),
{error,_} = ssh:connect("localhost", Port, [{id_string,random}], 1000),
@@ -1063,6 +1043,12 @@ id_string_own_string_server(Config) ->
{ok,"SSH-2.0-Olle\r\n"} = gen_tcp:recv(S1, 0, 2000).
%%--------------------------------------------------------------------
+id_string_own_string_server_trail_space(Config) ->
+ {_Server, Host, Port} = ssh_test_lib:std_daemon(Config, [{id_string,"Olle "}]),
+ {ok,S1}=ssh_test_lib:gen_tcp_connect(Host,Port,[{active,false},{packet,line}]),
+ {ok,"SSH-2.0-Olle \r\n"} = gen_tcp:recv(S1, 0, 2000).
+
+%%--------------------------------------------------------------------
id_string_random_server(Config) ->
{_Server, Host, Port} = ssh_test_lib:std_daemon(Config, [{id_string,random}]),
{ok,S1}=ssh_test_lib:gen_tcp_connect(Host,Port,[{active,false},{packet,line}]),
@@ -1241,7 +1227,7 @@ max_sessions(Config, ParallelLogin, Connect0) when is_function(Connect0,2) ->
[_|_] = Connections,
%% Now try one more than alowed:
- ct:log("Info Report might come here...",[]),
+ ct:pal("Info Report expected here (if not disabled) ...",[]),
try Connect(Host,Port)
of
_ConnectionRef1 ->
@@ -1249,8 +1235,7 @@ max_sessions(Config, ParallelLogin, Connect0) when is_function(Connect0,2) ->
{fail,"Too many connections accepted"}
catch
error:{badmatch,{error,"Connection closed"}} ->
- %% Step 2 ok: could not set up max_sessions+1 connections
- %% This is expected
+ ct:log("Step 2 ok: could not set up too many connections. Good.",[]),
%% Now stop one connection and try to open one more
ok = ssh:close(hd(Connections)),
try_to_connect(Connect, Host, Port, Pid)
@@ -1263,16 +1248,15 @@ max_sessions(Config, ParallelLogin, Connect0) when is_function(Connect0,2) ->
try_to_connect(Connect, Host, Port, Pid) ->
- {ok,Tref} = timer:send_after(3000, timeout_no_connection), % give the supervisors some time...
+ {ok,Tref} = timer:send_after(30000, timeout_no_connection), % give the supervisors some time...
try_to_connect(Connect, Host, Port, Pid, Tref, 1). % will take max 3300 ms after 11 tries
try_to_connect(Connect, Host, Port, Pid, Tref, N) ->
try Connect(Host,Port)
of
_ConnectionRef1 ->
- %% Step 3 ok: could set up one more connection after killing one
- %% Thats good.
timer:cancel(Tref),
+ ct:log("Step 3 ok: could set up one more connection after killing one. Thats good.",[]),
ssh:stop_daemon(Pid),
receive % flush.
timeout_no_connection -> ok
@@ -1291,6 +1275,33 @@ try_to_connect(Connect, Host, Port, Pid, Tref, N) ->
end.
%%--------------------------------------------------------------------
+save_accepted_host_option(Config) ->
+ UserDir = proplists:get_value(user_dir, Config),
+ KnownHosts = filename:join(UserDir, "known_hosts"),
+ SysDir = proplists:get_value(data_dir, Config),
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, UserDir},
+ {user_passwords, [{"vego", "morot"}]}
+ ]),
+ {error,enoent} = file:read_file(KnownHosts),
+
+ {ok,_C1} = ssh:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "vego"},
+ {password, "morot"},
+ {user_interaction, false},
+ {save_accepted_host, false},
+ {user_dir, UserDir}]),
+ {error,enoent} = file:read_file(KnownHosts),
+
+ {ok,_C2} = ssh:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "vego"},
+ {password, "morot"},
+ {user_interaction, false},
+ {user_dir, UserDir}]),
+ {ok,_} = file:read_file(KnownHosts),
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
diff --git a/lib/ssh/test/ssh_peername_sockname_server.erl b/lib/ssh/test/ssh_peername_sockname_server.erl
index 8731d80f62..1cc53edf6d 100644
--- a/lib/ssh/test/ssh_peername_sockname_server.erl
+++ b/lib/ssh/test/ssh_peername_sockname_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@
%% ssh connection.
--behaviour(ssh_daemon_channel).
+-behaviour(ssh_server_channel).
-record(state, {}).
-export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]).
diff --git a/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_dsa_key
new file mode 100644
index 0000000000..51ab6fbd88
--- /dev/null
+++ b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_dsa_key
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK
+wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q
+diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA
+l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X
+skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF
+Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP
+ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah
+/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U
+ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W
+Lv62jKcdskxNyz2NQoBx
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_dsa_key.pub
new file mode 100644
index 0000000000..4dbb1305b0
--- /dev/null
+++ b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_dsa_key.pub
@@ -0,0 +1,11 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j
+YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2
+KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU
+aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI
+fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT
+MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh
+DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48
+wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2
+/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_ecdsa_key b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_ecdsa_key
new file mode 100644
index 0000000000..2979ea88ed
--- /dev/null
+++ b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_ecdsa_key
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIMe4MDoit0t8RzSVPwkCBemQ9fhXL+xnTSAWISw8HNCioAoGCCqGSM49
+AwEHoUQDQgAEo2q7U3P6r0W5WGOLtM78UQtofM9UalEhiZeDdiyylsR/RR17Op0s
+VPGSADLmzzgcucLEKy17j2S+oz42VUJy5A==
+-----END EC PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_ecdsa_key.pub b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_ecdsa_key.pub
new file mode 100644
index 0000000000..85dc419345
--- /dev/null
+++ b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_ecdsa_key.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKNqu1Nz+q9FuVhji7TO/FELaHzPVGpRIYmXg3YsspbEf0UdezqdLFTxkgAy5s84HLnCxCste49kvqM+NlVCcuQ= uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_rsa_key b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_rsa_key
new file mode 100644
index 0000000000..79968bdd7d
--- /dev/null
+++ b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_rsa_key
@@ -0,0 +1,16 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8semM4q843337
+zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RWRWzjaxSB
+6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4QIDAQAB
+AoGANmvJzJO5hkLuvyDZHKfAnGTtpifcR1wtSa9DjdKUyn8vhKF0mIimnbnYQEmW
+NUUb3gXCZLi9PvkpRSVRrASDOZwcjoU/Kvww163vBUVb2cOZfFhyn6o2Sk88Tt++
+udH3hdjpf9i7jTtUkUe+QYPsia+wgvvrmn4QrahLAH86+kECQQDx5gFeXTME3cnW
+WMpFz3PPumduzjqgqMMWEccX4FtQkMX/gyGa5UC7OHFyh0N/gSWvPbRHa8A6YgIt
+n8DO+fh5AkEAzbqX4DOn8NY6xJIi42q7l/2jIA0RkB6P7YugW5NblhqBZ0XDnpA5
+sMt+rz+K07u9XZtxgh1xi7mNfwY6lEAMqQJBAJBEauCKmRj35Z6OyeQku59SPsnY
++SJEREVvSNw2lH9SOKQQ4wPsYlTGbvKtNVZgAcen91L5MmYfeckYE/fdIZECQQCt
+64zxsTnM1I8iFxj/gP/OYlJBikrKt8udWmjaghzvLMEw+T2DExJyb9ZNeT53+UMB
+m6O+B/4xzU/djvp+0hbhAkAemIt+rA5kTmYlFndhpvzkSSM8a2EXsO4XIPgGWCTT
+tQKS/tTly0ADMjN/TVy11+9d6zcqadNVuHXHGtR4W0GR
+-----END RSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_rsa_key.pub b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_rsa_key.pub
new file mode 100644
index 0000000000..75d2025c71
--- /dev/null
+++ b/lib/ssh/test/ssh_property_test_SUITE_data/ssh_host_rsa_key.pub
@@ -0,0 +1,5 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1yc2EAAAADAQABAAAAgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8
+semM4q843337zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RW
+RWzjaxSB6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4Q==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl
index 0837fe7eaf..3e3e151781 100644
--- a/lib/ssh/test/ssh_protocol_SUITE.erl
+++ b/lib/ssh/test/ssh_protocol_SUITE.erl
@@ -34,8 +34,8 @@
-define(NEWLINE, <<"\r\n">>).
-define(REKEY_DATA_TMO, 65000).
-%%-define(DEFAULT_KEX, 'diffie-hellman-group1-sha1').
-define(DEFAULT_KEX, 'diffie-hellman-group14-sha256').
+-define(EXTRA_KEX, 'diffie-hellman-group1-sha1').
-define(CIPHERS, ['aes256-ctr','aes192-ctr','aes128-ctr','aes128-cbc','3des-cbc']).
-define(DEFAULT_CIPHERS, [{client2server,?CIPHERS}, {server2client,?CIPHERS}]).
@@ -60,7 +60,8 @@ all() ->
{group,authentication},
{group,packet_size_error},
{group,field_size_error},
- {group,ext_info}
+ {group,ext_info},
+ {group,preferred_algorithms}
].
groups() ->
@@ -96,7 +97,13 @@ groups() ->
no_ext_info_s2,
ext_info_s,
ext_info_c
- ]}
+ ]},
+ {preferred_algorithms, [], [preferred_algorithms,
+ modify_append,
+ modify_prepend,
+ modify_rm,
+ modify_combo
+ ]}
].
@@ -623,11 +630,12 @@ client_handles_keyboard_interactive_0_pwds(Config) ->
%%%--------------------------------------------------------------------
-client_info_line(_Config) ->
+client_info_line(Config) ->
%% A client must not send an info-line. If it does, the server should handle
%% handle this gracefully
{ok,Pid} = ssh_eqc_event_handler:add_report_handler(),
- {_, _, Port} = ssh_test_lib:daemon([]),
+ DataDir = proplists:get_value(data_dir, Config),
+ {_, _, Port} = ssh_test_lib:daemon([{system_dir,DataDir}]),
%% Fake client:
{ok,S} = gen_tcp:connect("localhost",Port,[]),
@@ -701,8 +709,6 @@ ext_info_s(Config) ->
%%%--------------------------------------------------------------------
%%% The client sends the extension
ext_info_c(Config) ->
- {User,_Pwd} = server_user_password(Config),
-
%% Create a listening socket as server socket:
{ok,InitialState} = ssh_trpt_test_lib:exec(listen),
HostPort = ssh_trpt_test_lib:server_host_port(InitialState),
@@ -757,10 +763,135 @@ ext_info_c(Config) ->
{result, Pid, Error} -> ct:fail("Error: ~p",[Error])
end.
+
+%%%----------------------------------------------------------------
+%%%
+preferred_algorithms(Config) ->
+ Ciphers = filter_supported(cipher, ?CIPHERS),
+ {error,{eoptions,{{preferred_algorithms,{kex,[some_unknown_algo]}},
+ "Unsupported value(s) found"}}} =
+ chk_pref_algs(Config,
+ [?DEFAULT_KEX],
+ Ciphers,
+ [{preferred_algorithms, [{kex,[some_unknown_algo,?DEFAULT_KEX]},
+ {cipher,Ciphers}
+ ]}
+ ]).
+
+%%%----------------------------------------------------------------
+%%%
+modify_append(Config) ->
+ Ciphers = filter_supported(cipher, ?CIPHERS),
+ {ok,_} =
+ chk_pref_algs(Config,
+ [?DEFAULT_KEX, ?EXTRA_KEX],
+ Ciphers,
+ [{preferred_algorithms, [{kex,[?DEFAULT_KEX]},
+ {cipher,Ciphers}
+ ]},
+ {modify_algorithms, [{append,[{kex,[some_unknown_algo,?EXTRA_KEX]}]}]}
+ ]).
+
+%%%----------------------------------------------------------------
+%%%
+modify_prepend(Config) ->
+ Ciphers = filter_supported(cipher, ?CIPHERS),
+ {ok,_} =
+ chk_pref_algs(Config,
+ [?EXTRA_KEX, ?DEFAULT_KEX],
+ Ciphers,
+ [{preferred_algorithms, [{kex,[?DEFAULT_KEX]},
+ {cipher,Ciphers}
+ ]},
+ {modify_algorithms, [{prepend,[{kex,[some_unknown_algo,?EXTRA_KEX]}]}]}
+ ]).
+
+%%%----------------------------------------------------------------
+%%%
+modify_rm(Config) ->
+ Ciphers = filter_supported(cipher, ?CIPHERS),
+ {ok,_} =
+ chk_pref_algs(Config,
+ [?DEFAULT_KEX],
+ tl(Ciphers),
+ [{preferred_algorithms, [{kex,[?DEFAULT_KEX,?EXTRA_KEX]},
+ {cipher,Ciphers}
+ ]},
+ {modify_algorithms, [{rm,[{kex,[some_unknown_algo,?EXTRA_KEX]},
+ {cipher,[hd(Ciphers)]}
+ ]}
+ ]}
+ ]).
+
+
+%%%----------------------------------------------------------------
+%%%
+modify_combo(Config) ->
+ Ciphers = filter_supported(cipher, ?CIPHERS),
+ LastC = lists:last(Ciphers),
+ {ok,_} =
+ chk_pref_algs(Config,
+ [?DEFAULT_KEX],
+ [LastC] ++ (tl(Ciphers)--[LastC]) ++ [hd(Ciphers)],
+ [{preferred_algorithms, [{kex,[?DEFAULT_KEX,?EXTRA_KEX]},
+ {cipher,Ciphers}
+ ]},
+ {modify_algorithms, [{rm,[{kex,[some_unknown_algo,?EXTRA_KEX]}
+ ]},
+ {prepend,[{cipher,[{server2client,[LastC]}]}
+ ]},
+ {append,[{cipher,[a,hd(Ciphers),b]}
+ ]}
+ ]}
+ ]).
+
%%%================================================================
%%%==== Internal functions ========================================
%%%================================================================
+chk_pref_algs(Config,
+ ExpectedKex,
+ ExpectedCiphers,
+ ServerPrefOpts) ->
+ %% Start the dameon
+ case ssh_test_lib:daemon(
+ [{send_ext_info,false},
+ {recv_ext_info,false},
+ {system_dir, system_dir(Config)}
+ | ServerPrefOpts])
+ of
+ {_,Host,Port} ->
+ %% Check the Kex part
+ ssh_trpt_test_lib:exec(
+ [{set_options, [print_ops, {print_messages,detail}]},
+ {connect, Host, Port,
+ [{silently_accept_hosts, true},
+ {user_dir, user_dir(Config)},
+ {user_interaction, false}
+ ]},
+ {send, hello},
+ receive_hello,
+ {match,
+ #ssh_msg_kexinit{
+ kex_algorithms = to_lists(ExpectedKex),
+ encryption_algorithms_server_to_client = to_lists(ExpectedCiphers),
+ _ = '_'},
+ receive_msg}
+ ]);
+ Error ->
+ Error
+ end.
+
+
+filter_supported(K, Algs) -> Algs -- (Algs--supported(K)).
+
+supported(_K) -> proplists:get_value(
+ server2client,
+ ssh_transport:supported_algorithms(cipher)).
+
+to_lists(L) -> lists:map(fun erlang:atom_to_list/1, L).
+
+
%%%---- init_suite and end_suite ---------------------------------------
start_apps(Config) ->
catch ssh:stop(),
diff --git a/lib/ssh/test/ssh_renegotiate_SUITE.erl b/lib/ssh/test/ssh_renegotiate_SUITE.erl
deleted file mode 100644
index 74bbc291b2..0000000000
--- a/lib/ssh/test/ssh_renegotiate_SUITE.erl
+++ /dev/null
@@ -1,237 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(ssh_renegotiate_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include("ssh_test_lib.hrl").
-
-%% Note: This directive should only be used in test suites.
--compile(export_all).
-
--define(REKEY_DATA_TMO, 65000).
-%%--------------------------------------------------------------------
-%% Common Test interface functions -----------------------------------
-%%--------------------------------------------------------------------
-
-suite() -> [{ct_hooks,[ts_install_cth]},
- {timetrap,{seconds,40}}].
-
-all() -> [{group,default_algs},
- {group,aes_gcm}
- ].
-
-groups() -> [{default_algs, [], tests()},
- {aes_gcm, [], tests()}
- ].
-
-tests() -> [rekey, rekey_limit, renegotiate1, renegotiate2].
-
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- ?CHECK_CRYPTO(Config).
-
-end_per_suite(_Config) ->
- ssh:stop().
-
-%%--------------------------------------------------------------------
-init_per_group(aes_gcm, Config) ->
- case lists:member({client2server,['[email protected]']},
- ssh_transport:supported_algorithms(cipher)) of
- true ->
- [{preferred_algorithms, [{cipher,[{client2server,['[email protected]']},
- {server2client,['[email protected]']}]}]}
- | Config];
- false ->
- {skip, "aes_gcm not supported"}
- end;
-init_per_group(_, Config) ->
- [{preferred_algorithms, ssh:default_algorithms()} | Config].
-
-
-end_per_group(_, Config) ->
- Config.
-
-%%--------------------------------------------------------------------
-init_per_testcase(_TestCase, Config) ->
- ssh:start(),
- Config.
-
-end_per_testcase(_TestCase, _Config) ->
- ssh:stop(),
- ok.
-
-%%--------------------------------------------------------------------
-%% Test Cases --------------------------------------------------------
-%%--------------------------------------------------------------------
-
-%%% Idle timeout test
-rekey() -> [{timetrap,{seconds,90}}].
-
-rekey(Config) ->
- {Pid, Host, Port} =
- ssh_test_lib:std_daemon(Config,
- [{rekey_limit, 0}]),
- ConnectionRef =
- ssh_test_lib:std_connect(Config, Host, Port,
- [{rekey_limit, 0}]),
- Kex1 = ssh_test_lib:get_kex_init(ConnectionRef),
- receive
- after ?REKEY_DATA_TMO ->
- %%By this time rekeying would have been done
- Kex2 = ssh_test_lib:get_kex_init(ConnectionRef),
- false = (Kex2 == Kex1),
- ssh:close(ConnectionRef),
- ssh:stop_daemon(Pid)
- end.
-
-%%--------------------------------------------------------------------
-
-%%% Test rekeying by data volume
-
-rekey_limit() -> [{timetrap,{seconds,400}}].
-
-rekey_limit(Config) ->
- UserDir = proplists:get_value(priv_dir, Config),
- DataFile = filename:join(UserDir, "rekey.data"),
-
- Algs = proplists:get_value(preferred_algorithms, Config),
- {Pid, Host, Port} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0},
- {preferred_algorithms,Algs}]),
-
- ConnectionRef = ssh_test_lib:std_connect(Config, Host, Port, [{rekey_limit, 6000},
- {max_random_length_padding,0}]),
- {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef),
-
- Kex1 = ssh_test_lib:get_kex_init(ConnectionRef),
-
- timer:sleep(?REKEY_DATA_TMO),
- Kex1 = ssh_test_lib:get_kex_init(ConnectionRef),
-
- Data = lists:duplicate(159000,1),
- ok = ssh_sftp:write_file(SftpPid, DataFile, Data),
-
- timer:sleep(?REKEY_DATA_TMO),
- Kex2 = ssh_test_lib:get_kex_init(ConnectionRef),
-
- false = (Kex2 == Kex1),
-
- timer:sleep(?REKEY_DATA_TMO),
- Kex2 = ssh_test_lib:get_kex_init(ConnectionRef),
-
- ok = ssh_sftp:write_file(SftpPid, DataFile, "hi\n"),
-
- timer:sleep(?REKEY_DATA_TMO),
- Kex2 = ssh_test_lib:get_kex_init(ConnectionRef),
-
- false = (Kex2 == Kex1),
-
- timer:sleep(?REKEY_DATA_TMO),
- Kex2 = ssh_test_lib:get_kex_init(ConnectionRef),
-
- ssh_sftp:stop_channel(SftpPid),
- ssh:close(ConnectionRef),
- ssh:stop_daemon(Pid).
-
-%%--------------------------------------------------------------------
-
-%%% Test rekeying with simulataneous send request
-
-renegotiate1(Config) ->
- UserDir = proplists:get_value(priv_dir, Config),
- DataFile = filename:join(UserDir, "renegotiate1.data"),
-
- Algs = proplists:get_value(preferred_algorithms, Config),
- {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0},
- {preferred_algorithms,Algs}]),
-
- RPort = ssh_test_lib:inet_port(),
- {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort),
-
-
- ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, [{max_random_length_padding,0}]),
- {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef),
-
- Kex1 = ssh_test_lib:get_kex_init(ConnectionRef),
-
- {ok, Handle} = ssh_sftp:open(SftpPid, DataFile, [write]),
-
- ok = ssh_sftp:write(SftpPid, Handle, "hi\n"),
-
- ssh_relay:hold(RelayPid, rx, 20, 1000),
- ssh_connection_handler:renegotiate(ConnectionRef),
- spawn(fun() -> ok=ssh_sftp:write(SftpPid, Handle, "another hi\n") end),
-
- timer:sleep(2000),
-
- Kex2 = ssh_test_lib:get_kex_init(ConnectionRef),
-
- false = (Kex2 == Kex1),
-
- ssh_relay:stop(RelayPid),
- ssh_sftp:stop_channel(SftpPid),
- ssh:close(ConnectionRef),
- ssh:stop_daemon(Pid).
-
-%%--------------------------------------------------------------------
-
-%%% Test rekeying with inflight messages from peer
-
-renegotiate2(Config) ->
- UserDir = proplists:get_value(priv_dir, Config),
- DataFile = filename:join(UserDir, "renegotiate2.data"),
-
- Algs = proplists:get_value(preferred_algorithms, Config),
- {Pid, Host, DPort} = ssh_test_lib:std_daemon(Config,[{max_random_length_padding,0},
- {preferred_algorithms,Algs}]),
-
- RPort = ssh_test_lib:inet_port(),
- {ok,RelayPid} = ssh_relay:start_link({0,0,0,0}, RPort, Host, DPort),
-
- ConnectionRef = ssh_test_lib:std_connect(Config, Host, RPort, [{max_random_length_padding,0}]),
- {ok, SftpPid} = ssh_sftp:start_channel(ConnectionRef),
-
- Kex1 = ssh_test_lib:get_kex_init(ConnectionRef),
-
- {ok, Handle} = ssh_sftp:open(SftpPid, DataFile, [write]),
-
- ok = ssh_sftp:write(SftpPid, Handle, "hi\n"),
-
- ssh_relay:hold(RelayPid, rx, 20, infinity),
- spawn(fun() -> ok=ssh_sftp:write(SftpPid, Handle, "another hi\n") end),
- %% need a small pause here to ensure ssh_sftp:write is executed
- ct:sleep(10),
- ssh_connection_handler:renegotiate(ConnectionRef),
- ssh_relay:release(RelayPid, rx),
-
- timer:sleep(2000),
-
- Kex2 = ssh_test_lib:get_kex_init(ConnectionRef),
-
- false = (Kex2 == Kex1),
-
- ssh_relay:stop(RelayPid),
- ssh_sftp:stop_channel(SftpPid),
- ssh:close(ConnectionRef),
- ssh:stop_daemon(Pid).
-
-%%--------------------------------------------------------------------
-%% Internal functions ------------------------------------------------
-%%--------------------------------------------------------------------
diff --git a/lib/ssh/test/ssh_renegotiate_SUITE_data/id_dsa b/lib/ssh/test/ssh_renegotiate_SUITE_data/id_dsa
deleted file mode 100644
index d306f8b26e..0000000000
--- a/lib/ssh/test/ssh_renegotiate_SUITE_data/id_dsa
+++ /dev/null
@@ -1,13 +0,0 @@
------BEGIN DSA PRIVATE KEY-----
-MIIBvAIBAAKBgQDfi2flSTZZofwT4yQT0NikX/LGNT7UPeB/XEWe/xovEYCElfaQ
-APFixXvEgXwoojmZ5kiQRKzLM39wBP0jPERLbnZXfOOD0PDnw0haMh7dD7XKVMod
-/EigVgHf/qBdM2M8yz1s/rRF7n1UpLSypziKjkzCm7JoSQ2zbWIPdmBIXwIVAMgP
-kpr7Sq3O7sHdb8D601DRjoExAoGAMOQxDfB2Fd8ouz6G96f/UOzRMI/Kdv8kYYKW
-JIGY+pRYrLPyYzUeJznwZreOJgrczAX+luHnKFWJ2Dnk5CyeXk67Wsr7pJ/4MBMD
-OKeIS0S8qoSBN8+Krp79fgA+yS3IfqbkJLtLu4EBaCX4mKQIX4++k44d4U5lc8pt
-+9hlEI8CgYEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+e
-uEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AX
-Cy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34CFQC63czE
-ZU8w8Q+H7z0j+a+70x2iAw==
------END DSA PRIVATE KEY-----
-
diff --git a/lib/ssh/test/ssh_renegotiate_SUITE_data/id_rsa b/lib/ssh/test/ssh_renegotiate_SUITE_data/id_rsa
deleted file mode 100644
index 9d7e0dd5fb..0000000000
--- a/lib/ssh/test/ssh_renegotiate_SUITE_data/id_rsa
+++ /dev/null
@@ -1,15 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIICXAIBAAKBgQD1OET+3O/Bvj/dtjxDTXmj1oiJt4sIph5kGy0RfjoPrZfaS+CU
-DhakCmS6t2ivxWFgtpKWaoGMZMJqWj6F6ZsumyFl3FPBtujwY/35cgifrI9Ns4Tl
-zR1uuengNBmV+WRQ5cd9F2qS6Z8aDQihzt0r8JUqLcK+VQbrmNzboCCQQwIDAQAB
-AoGAPQEyqPTt8JUT7mRXuaacjFXiweAXhp9NEDpyi9eLOjtFe9lElZCrsUOkq47V
-TGUeRKEm9qSodfTbKPoqc8YaBJGJPhUaTAcha+7QcDdfHBvIsgxvU7ePVnlpXRp3
-CCUEMPhlnx6xBoTYP+fRU0e3+xJIPVyVCqX1jAdUMkzfRoECQQD6ux7B1QJAIWyK
-SGkbDUbBilNmzCFNgIpOP6PA+bwfi5d16diTpra5AX09keQABAo/KaP1PdV8Vg0p
-z4P3A7G3AkEA+l+AKG6m0kQTTBMJDqOdVPYwe+5GxunMaqmhokpEbuGsrZBl5Dvd
-WpcBjR7jmenrhKZRIuA+Fz5HPo/UQJPl1QJBAKxstDkeED8j/S2XoFhPKAJ+6t39
-sUVICVTIZQeXdmzHJXCcUSkw8+WEhakqw/3SyW0oaK2FSWQJFWJUZ+8eJj8CQEh3
-xeduB5kKnS9CvzdeghZqX6QvVosSdtlUmfUYW/BgH5PpHKTP8wTaeld3XldZTpMJ
-dKiMkUw2+XYROVUrubUCQD+Na1LhULlpn4ISEtIEfqpdlUhxDgO15Wg8USmsng+x
-ICliVOSQtwaZjm8kwaFt0W7XnpnDxbRs37vIEbIMWak=
------END RSA PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl
index 680a8ef52e..c2f9c0eba8 100644
--- a/lib/ssh/test/ssh_sftp_SUITE.erl
+++ b/lib/ssh/test/ssh_sftp_SUITE.erl
@@ -92,7 +92,7 @@ groups() ->
{write_read_tests, [], [open_close_file, open_close_dir, read_file, read_dir,
write_file, write_file_iolist, write_big_file, sftp_read_big_file,
rename_file, mk_rm_dir, remove_file, links,
- retrieve_attributes, set_attributes, async_read,
+ retrieve_attributes, set_attributes, file_owner_access, async_read,
async_write, position, pos_read, pos_write,
start_channel_sock
]}
@@ -181,8 +181,9 @@ init_per_group(openssh_server, Config) ->
[{peer, {fmt_host(IPx),Portx}}, {group, openssh_server} | Config];
{error,"Key exchange failed"} ->
{skip, "openssh server doesn't support the tested kex algorithm"};
- _ ->
- {skip, "No openssh server"}
+ Other ->
+ ct:log("No openssh server. Cause:~n~p~n",[Other]),
+ {skip, "No openssh daemon (see log in testcase)"}
end;
init_per_group(remote_tar, Config) ->
@@ -521,7 +522,36 @@ set_attributes(Config) when is_list(Config) ->
ok = file:write_file(FileName, "hello again").
%%--------------------------------------------------------------------
+file_owner_access() ->
+ [{doc,"Test file user access validity"}].
+file_owner_access(Config) when is_list(Config) ->
+ case os:type() of
+ {win32, _} ->
+ {skip, "Not a relevant test on Windows"};
+ _ ->
+ FileName = proplists:get_value(filename, Config),
+ {Sftp, _} = proplists:get_value(sftp, Config),
+
+ {ok, #file_info{mode = InitialMode}} = ssh_sftp:read_file_info(Sftp, FileName),
+
+ ok = ssh_sftp:write_file_info(Sftp, FileName, #file_info{mode=8#000}),
+ {ok, #file_info{access = none}} = ssh_sftp:read_file_info(Sftp, FileName),
+
+ ok = ssh_sftp:write_file_info(Sftp, FileName, #file_info{mode=8#400}),
+ {ok, #file_info{access = read}} = ssh_sftp:read_file_info(Sftp, FileName),
+
+ ok = ssh_sftp:write_file_info(Sftp, FileName, #file_info{mode=8#200}),
+ {ok, #file_info{access = write}} = ssh_sftp:read_file_info(Sftp, FileName),
+ ok = ssh_sftp:write_file_info(Sftp, FileName, #file_info{mode=8#600}),
+ {ok, #file_info{access = read_write}} = ssh_sftp:read_file_info(Sftp, FileName),
+
+ ok = ssh_sftp:write_file_info(Sftp, FileName, #file_info{mode=InitialMode}),
+
+ ok
+ end.
+
+%%--------------------------------------------------------------------
async_read() ->
[{doc,"Test API aread/3"}].
async_read(Config) when is_list(Config) ->
diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl
index 763649a12f..5fc948fbed 100644
--- a/lib/ssh/test/ssh_sftpd_SUITE.erl
+++ b/lib/ssh/test/ssh_sftpd_SUITE.erl
@@ -34,7 +34,7 @@
-define(PASSWD, "Sesame").
-define(XFER_PACKET_SIZE, 32768).
-define(XFER_WINDOW_SIZE, 4*?XFER_PACKET_SIZE).
--define(TIMEOUT, 10000).
+-define(SSH_TIMEOUT, 10000).
-define(REG_ATTERS, <<0,0,0,0,1>>).
-define(UNIX_EPOCH, 62167219200).
@@ -161,9 +161,9 @@ init_per_testcase(TestCase, Config) ->
{silently_accept_hosts, true}]),
{ok, Channel} =
ssh_connection:session_channel(Cm, ?XFER_WINDOW_SIZE,
- ?XFER_PACKET_SIZE, ?TIMEOUT),
+ ?XFER_PACKET_SIZE, ?SSH_TIMEOUT),
- success = ssh_connection:subsystem(Cm, Channel, "sftp", ?TIMEOUT),
+ success = ssh_connection:subsystem(Cm, Channel, "sftp", ?SSH_TIMEOUT),
ProtocolVer = case atom_to_list(TestCase) of
"ver3_" ++ _ ->
diff --git a/lib/ssh/test/ssh_sup_SUITE.erl b/lib/ssh/test/ssh_sup_SUITE.erl
index 3920a1c592..a0e3d809be 100644
--- a/lib/ssh/test/ssh_sup_SUITE.erl
+++ b/lib/ssh/test/ssh_sup_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,7 +42,9 @@ suite() ->
all() ->
[default_tree, sshc_subtree, sshd_subtree, sshd_subtree_profile,
- killed_acceptor_restarts].
+ killed_acceptor_restarts,
+ shell_channel_tree
+ ].
groups() ->
[].
@@ -199,8 +201,6 @@ killed_acceptor_restarts(Config) ->
Port2 = ssh_test_lib:daemon_port(DaemonPid2),
true = (Port /= Port2),
- ct:pal("~s",[lists:flatten(ssh_info:string())]),
-
{ok,[{AccPid,ListenAddr,Port}]} = acceptor_pid(DaemonPid),
{ok,[{AccPid2,ListenAddr,Port2}]} = acceptor_pid(DaemonPid2),
@@ -214,37 +214,143 @@ killed_acceptor_restarts(Config) ->
{user_dir, UserDir}]),
[{client_version,_}] = ssh:connection_info(C1,[client_version]),
+ ct:log("~s",[lists:flatten(ssh_info:string())]),
+
%% Make acceptor restart:
exit(AccPid, kill),
+ ?wait_match(undefined, process_info(AccPid)),
- %% Check it is a new acceptor:
- {ok,[{AccPid1,ListenAddr,Port}]} = acceptor_pid(DaemonPid),
- true = (AccPid /= AccPid1),
- true = (AccPid2 /= AccPid1),
+ %% Check it is a new acceptor and wait if it is not:
+ ?wait_match({ok,[{AccPid1,ListenAddr,Port}]}, AccPid1=/=AccPid,
+ acceptor_pid(DaemonPid),
+ AccPid1,
+ 500, 30),
+
+ true = (AccPid1 =/= AccPid2),
%% Connect second client and check it is alive:
- {ok,C2} = ssh:connect("localhost", Port, [{silently_accept_hosts, true},
- {user_interaction, false},
- {user, ?USER},
- {password, ?PASSWD},
- {user_dir, UserDir}]),
+ C2 =
+ case ssh:connect("localhost", Port, [{silently_accept_hosts, true},
+ {user_interaction, false},
+ {user, ?USER},
+ {password, ?PASSWD},
+ {user_dir, UserDir}]) of
+ {ok,_C2} ->
+ _C2;
+ _Other ->
+ ct:log("new connect failed: ~p~n~n~s",[_Other,lists:flatten(ssh_info:string())]),
+ ct:fail("Re-connect failed!", [])
+ end,
+
[{client_version,_}] = ssh:connection_info(C2,[client_version]),
- ct:pal("~s",[lists:flatten(ssh_info:string())]),
+ ct:log("~s",[lists:flatten(ssh_info:string())]),
%% Check first client is still alive:
[{client_version,_}] = ssh:connection_info(C1,[client_version]),
ok = ssh:stop_daemon(DaemonPid2),
- timer:sleep(15000),
+ ?wait_match(undefined, process_info(DaemonPid2), 1000, 30),
[{client_version,_}] = ssh:connection_info(C1,[client_version]),
[{client_version,_}] = ssh:connection_info(C2,[client_version]),
ok = ssh:stop_daemon(DaemonPid),
- timer:sleep(15000),
- {error,closed} = ssh:connection_info(C1,[client_version]),
- {error,closed} = ssh:connection_info(C2,[client_version]).
+ ?wait_match(undefined, process_info(DaemonPid), 1000, 30),
+ ?wait_match({error,closed}, ssh:connection_info(C1,[client_version]), 1000, 5),
+ ?wait_match({error,closed}, ssh:connection_info(C2,[client_version]), 1000, 5).
+
+%%-------------------------------------------------------------------------
+shell_channel_tree(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
+ file:make_dir(UserDir),
+ SysDir = proplists:get_value(data_dir, Config),
+ TimeoutShell =
+ fun() ->
+ io:format("TimeoutShell started!~n",[]),
+ timer:sleep(5000),
+ ct:log("~p TIMEOUT!",[self()])
+ end,
+ {Daemon, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, UserDir},
+ {password, "morot"},
+ {shell, fun(_User) ->
+ spawn(TimeoutShell)
+ end
+ }
+ ]),
+ ConnectionRef = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "foo"},
+ {password, "morot"},
+ {user_interaction, true},
+ {user_dir, UserDir}]),
+
+ [ChannelSup|_] = Sups0 = chk_empty_con_daemon(Daemon),
+ {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity),
+ ok = ssh_connection:shell(ConnectionRef,ChannelId0),
+
+ ?wait_match([{_, GroupPid,worker,[ssh_server_channel]}],
+ supervisor:which_children(ChannelSup),
+ [GroupPid]),
+ {links,GroupLinks} = erlang:process_info(GroupPid, links),
+ [ShellPid] = GroupLinks--[ChannelSup],
+ ct:log("GroupPid = ~p, ShellPid = ~p",[GroupPid,ShellPid]),
+
+ receive
+ {ssh_cm,ConnectionRef, {data, ChannelId0, 0, <<"TimeoutShell started!\r\n">>}} ->
+ receive
+ %%---- wait for the subsystem to terminate
+ {ssh_cm,ConnectionRef,{closed,ChannelId0}} ->
+ ct:log("Subsystem terminated",[]),
+ case {chk_empty_con_daemon(Daemon),
+ process_info(GroupPid),
+ process_info(ShellPid)} of
+ {Sups0, undefined, undefined} ->
+ %% SUCCESS
+ ssh:stop_daemon(Daemon);
+ {Sups0, _, undefined} ->
+ ssh:stop_daemon(Daemon),
+ ct:fail("Group proc lives!");
+ {Sups0, undefined, _} ->
+ ssh:stop_daemon(Daemon),
+ ct:fail("Shell proc lives!");
+ _ ->
+ ssh:stop_daemon(Daemon),
+ ct:fail("Sup tree changed!")
+ end
+ after 10000 ->
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Daemon),
+ ct:fail("CLI Timeout")
+ end
+ after 10000 ->
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Daemon),
+ ct:fail("CLI Timeout")
+ end.
+
+
+chk_empty_con_daemon(Daemon) ->
+ ?wait_match([{_,SubSysSup, supervisor,[ssh_subsystem_sup]},
+ {{ssh_acceptor_sup,_,_,_}, AccSup, supervisor,[ssh_acceptor_sup]}],
+ supervisor:which_children(Daemon),
+ [SubSysSup,AccSup]),
+ ?wait_match([{{server,ssh_connection_sup, _,_},
+ ConnectionSup, supervisor,
+ [ssh_connection_sup]},
+ {{server,ssh_server_channel_sup,_ ,_},
+ ChannelSup,supervisor,
+ [ssh_server_channel_sup]}],
+ supervisor:which_children(SubSysSup),
+ [ConnectionSup,ChannelSup]),
+ ?wait_match([{{ssh_acceptor_sup,_,_,_},_,worker,[ssh_acceptor]}],
+ supervisor:which_children(AccSup)),
+ ?wait_match([{_, _, worker,[ssh_connection_handler]}],
+ supervisor:which_children(ConnectionSup)),
+ ?wait_match([], supervisor:which_children(ChannelSup)),
+ [ChannelSup, ConnectionSup, SubSysSup, AccSup].
+
%%-------------------------------------------------------------------------
%% Help functions
%%-------------------------------------------------------------------------
@@ -266,9 +372,9 @@ check_sshd_system_tree(Daemon, Config) ->
?wait_match([{{server,ssh_connection_sup, _,_},
ConnectionSup, supervisor,
[ssh_connection_sup]},
- {{server,ssh_channel_sup,_ ,_},
+ {{server,ssh_server_channel_sup,_ ,_},
ChannelSup,supervisor,
- [ssh_channel_sup]}],
+ [ssh_server_channel_sup]}],
supervisor:which_children(SubSysSup),
[ConnectionSup,ChannelSup]),
@@ -282,7 +388,7 @@ check_sshd_system_tree(Daemon, Config) ->
ssh_sftp:start_channel(Client),
- ?wait_match([{_, _,worker,[ssh_channel]}],
+ ?wait_match([{_, _,worker,[ssh_server_channel]}],
supervisor:which_children(ChannelSup)),
ssh:close(Client).
diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl
index 7b273fecef..416cc301db 100644
--- a/lib/ssh/test/ssh_test_lib.erl
+++ b/lib/ssh/test/ssh_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,9 +28,7 @@
-include_lib("public_key/include/public_key.hrl").
-include_lib("common_test/include/ct.hrl").
-include_lib("ssh/src/ssh_transport.hrl").
-
-
--define(TIMEOUT, 50000).
+-include("ssh_test_lib.hrl").
%%%----------------------------------------------------------------
connect(Port, Options) when is_integer(Port) ->
@@ -58,7 +56,9 @@ daemon(Host, Port, Options) ->
ct:log("~p:~p Calling ssh:daemon(~p, ~p, ~p)",[?MODULE,?LINE,Host,Port,Options]),
case ssh:daemon(Host, Port, Options) of
{ok, Pid} ->
- {ok,L} = ssh:daemon_info(Pid),
+ R = ssh:daemon_info(Pid),
+ ct:log("~p:~p ssh:daemon_info(~p) ->~n ~p",[?MODULE,?LINE,Pid,R]),
+ {ok,L} = R,
ListenPort = proplists:get_value(port, L),
ListenIP = proplists:get_value(ip, L),
{Pid, ListenIP, ListenPort};
@@ -201,15 +201,17 @@ init_io_server(TestCase) ->
loop_io_server(TestCase, Buff0) ->
receive
- {input, TestCase, Line} ->
+ {input, TestCase, Line} = _INP ->
+ %%ct:log("io_server ~p:~p ~p got ~p",[?MODULE,?LINE,self(),_INP]),
loop_io_server(TestCase, Buff0 ++ [Line]);
- {io_request, From, ReplyAs, Request} ->
+ {io_request, From, ReplyAs, Request} = _REQ->
+ %%ct:log("io_server ~p:~p ~p got ~p",[?MODULE,?LINE,self(),_REQ]),
{ok, Reply, Buff} = io_request(Request, TestCase, From,
ReplyAs, Buff0),
io_reply(From, ReplyAs, Reply),
loop_io_server(TestCase, Buff);
{'EXIT',_, _} = _Exit ->
-%% ct:log("ssh_test_lib:loop_io_server/2 got ~p",[_Exit]),
+ ct:log("ssh_test_lib:loop_io_server/2 got ~p",[_Exit]),
ok
after
30000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE])
@@ -404,7 +406,7 @@ setup_ecdsa(Size, DataDir, UserDir) ->
file:copy(filename:join(DataDir, "ssh_host_ecdsa_key"++Size++".pub"), filename:join(System, "ssh_host_ecdsa_key.pub")),
ct:log("DataDir ~p:~n ~p~n~nSystDir ~p:~n ~p~n~nUserDir ~p:~n ~p",[DataDir, file:list_dir(DataDir), System, file:list_dir(System), UserDir, file:list_dir(UserDir)]),
setup_ecdsa_known_host(Size, System, UserDir),
- setup_ecdsa_auth_keys(Size, UserDir, UserDir).
+ setup_ecdsa_auth_keys(Size, DataDir, UserDir).
clean_dsa(UserDir) ->
del_dirs(filename:join(UserDir, "system")),
@@ -438,6 +440,29 @@ setup_rsa_pass_pharse(DataDir, UserDir, Phrase) ->
setup_rsa_known_host(DataDir, UserDir),
setup_rsa_auth_keys(DataDir, UserDir).
+setup_ecdsa_pass_phrase(Size, DataDir, UserDir, Phrase) ->
+ try
+ {ok, KeyBin} =
+ case file:read_file(F=filename:join(DataDir, "id_ecdsa"++Size)) of
+ {error,E} ->
+ ct:log("Failed (~p) to read ~p~nFiles: ~p", [E,F,file:list_dir(DataDir)]),
+ file:read_file(filename:join(DataDir, "id_ecdsa"));
+ Other ->
+ Other
+ end,
+ setup_pass_pharse(KeyBin, filename:join(UserDir, "id_ecdsa"), Phrase),
+ System = filename:join(UserDir, "system"),
+ file:make_dir(System),
+ file:copy(filename:join(DataDir, "ssh_host_ecdsa_key"++Size), filename:join(System, "ssh_host_ecdsa_key")),
+ file:copy(filename:join(DataDir, "ssh_host_ecdsa_key"++Size++".pub"), filename:join(System, "ssh_host_ecdsa_key.pub")),
+ setup_ecdsa_known_host(Size, System, UserDir),
+ setup_ecdsa_auth_keys(Size, DataDir, UserDir)
+ of
+ _ -> true
+ catch
+ _:_ -> false
+ end.
+
setup_pass_pharse(KeyBin, OutFile, Phrase) ->
[{KeyType, _,_} = Entry0] = public_key:pem_decode(KeyBin),
Key = public_key:pem_entry_decode(Entry0),
@@ -489,8 +514,15 @@ setup_rsa_auth_keys(Dir, UserDir) ->
PKey = #'RSAPublicKey'{publicExponent = E, modulus = N},
setup_auth_keys([{ PKey, [{comment, "Test"}]}], UserDir).
-setup_ecdsa_auth_keys(_Size, Dir, UserDir) ->
- {ok, Pem} = file:read_file(filename:join(Dir, "id_ecdsa")),
+setup_ecdsa_auth_keys(Size, Dir, UserDir) ->
+ {ok, Pem} =
+ case file:read_file(F=filename:join(Dir, "id_ecdsa"++Size)) of
+ {error,E} ->
+ ct:log("Failed (~p) to read ~p~nFiles: ~p", [E,F,file:list_dir(Dir)]),
+ file:read_file(filename:join(Dir, "id_ecdsa"));
+ Other ->
+ Other
+ end,
ECDSA = public_key:pem_entry_decode(hd(public_key:pem_decode(Pem))),
#'ECPrivateKey'{publicKey = Q,
parameters = Param = {namedCurve,_Id0}} = ECDSA,
@@ -570,9 +602,9 @@ check_ssh_client_support2(P) ->
{P, {data, _A}} ->
check_ssh_client_support2(P);
{P, {exit_status, E}} ->
+ ct:log("~p:~p exit_status:~n~p",[?MODULE,?LINE,E]),
E
after 5000 ->
-
ct:log("Openssh command timed out ~n"),
-1
end.
@@ -622,14 +654,14 @@ default_algorithms(sshc, DaemonOptions) ->
{hostport,Srvr,{_Host,Port}} ->
spawn(fun()-> os:cmd(lists:concat(["ssh -o \"StrictHostKeyChecking no\" -p ",Port," localhost"])) end)
after ?TIMEOUT ->
- ct:fail("No server respons 1")
+ ct:fail("No server respons (timeout) 1")
end,
receive
{result,Srvr,L} ->
L
after ?TIMEOUT ->
- ct:fail("No server respons 2")
+ ct:fail("No server respons (timeout) 2")
end.
run_fake_ssh({ok,InitialState}) ->
@@ -743,12 +775,12 @@ ssh_type1() ->
not_found;
Path ->
ct:log("~p:~p Found \"ssh\" at ~p",[?MODULE,?LINE,Path]),
- case os:cmd("ssh -V") of
+ case installed_ssh_version(timeout) of
Version = "OpenSSH" ++ _ ->
ct:log("~p:~p Found OpenSSH ~p",[?MODULE,?LINE,Version]),
openSSH;
- Str ->
- ct:log("ssh client ~p is unknown",[Str]),
+ Other ->
+ ct:log("ssh client ~p is unknown",[Other]),
unknown
end
end
@@ -758,6 +790,20 @@ ssh_type1() ->
not_found
end.
+installed_ssh_version(TimeoutReturn) ->
+ Parent = self(),
+ Pid = spawn(fun() ->
+ Parent ! {open_ssh_version, os:cmd("ssh -V")}
+ end),
+ receive
+ {open_ssh_version, V} ->
+ V
+ after ?TIMEOUT ->
+ exit(Pid, kill),
+ TimeoutReturn
+ end.
+
+
algo_intersection([], _) -> [];
@@ -880,7 +926,7 @@ get_kex_init(Conn, Ref, TRef) ->
end;
false ->
- ct:log("Not in 'connected' state: ~p",[State]),
+ ct:log("~p:~p Not in 'connected' state: ~p",[?MODULE,?LINE,State]),
receive
{reneg_timeout,Ref} ->
ct:log("S = ~p", [S]),
diff --git a/lib/ssh/test/ssh_test_lib.hrl b/lib/ssh/test/ssh_test_lib.hrl
index 54c93b7e87..4b6579bd71 100644
--- a/lib/ssh/test/ssh_test_lib.hrl
+++ b/lib/ssh/test/ssh_test_lib.hrl
@@ -1,4 +1,9 @@
%%-------------------------------------------------------------------------
+%% Timeout time in ms
+%%-------------------------------------------------------------------------
+-define(TIMEOUT, 27000).
+
+%%-------------------------------------------------------------------------
%% Check for usable crypt
%%-------------------------------------------------------------------------
-define(CHECK_CRYPTO(Available),
@@ -11,12 +16,12 @@
%%-------------------------------------------------------------------------
%% Help macro
%%-------------------------------------------------------------------------
--define(wait_match(Pattern, FunctionCall, Bind, Timeout, Ntries),
+-define(wait_match(Pattern, Guard, FunctionCall, Bind, Timeout, Ntries),
Bind =
(fun() ->
F = fun(N, F1) ->
case FunctionCall of
- Pattern -> Bind;
+ Pattern when Guard -> Bind;
_ when N>0 ->
ct:pal("Must sleep ~p ms at ~p:~p",[Timeout,?MODULE,?LINE]),
timer:sleep(Timeout),
@@ -29,6 +34,9 @@
end)()
).
+-define(wait_match(Pattern, FunctionCall, Bind, Timeout, Ntries),
+ ?wait_match(Pattern, true, FunctionCall, Bind, Timeout, Ntries)).
+
-define(wait_match(Pattern, FunctionCall, Timeout, Ntries), ?wait_match(Pattern, FunctionCall, ok, Timeout, Ntries)).
-define(wait_match(Pattern, FunctionCall, Bind), ?wait_match(Pattern, FunctionCall, Bind, 500, 10) ).
diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl
index 4d6aa93d4e..334281f53b 100644
--- a/lib/ssh/test/ssh_to_openssh_SUITE.erl
+++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,7 +27,6 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
--define(TIMEOUT, 50000).
-define(SSH_DEFAULT_PORT, 22).
-define(REKEY_DATA_TMO, 65000).
@@ -49,19 +48,9 @@ all() ->
end.
groups() ->
- [{erlang_client, [], [erlang_shell_client_openssh_server,
- erlang_client_openssh_server_exec_compressed,
- erlang_client_openssh_server_setenv,
- erlang_client_openssh_server_publickey_dsa,
- erlang_client_openssh_server_publickey_rsa,
- erlang_client_openssh_server_password,
- erlang_client_openssh_server_kexs,
- erlang_client_openssh_server_nonexistent_subsystem,
- erlang_client_openssh_server_renegotiate
+ [{erlang_client, [], [erlang_shell_client_openssh_server
]},
- {erlang_server, [], [erlang_server_openssh_client_public_key_dsa,
- erlang_server_openssh_client_public_key_rsa,
- erlang_server_openssh_client_renegotiate
+ {erlang_server, [], [erlang_server_openssh_client_renegotiate
]}
].
@@ -69,7 +58,7 @@ init_per_suite(Config) ->
?CHECK_CRYPTO(
case gen_tcp:connect("localhost", 22, []) of
{error,econnrefused} ->
- {skip,"No openssh deamon"};
+ {skip,"No openssh deamon (econnrefused)"};
_ ->
ssh_test_lib:openssh_sanity_check(Config)
end
@@ -101,15 +90,6 @@ end_per_group(_, Config) ->
Config.
-init_per_testcase(erlang_server_openssh_client_public_key_dsa, Config) ->
- chk_key(sshc, 'ssh-dss', ".ssh/id_dsa", Config);
-init_per_testcase(erlang_server_openssh_client_public_key_rsa, Config) ->
- chk_key(sshc, 'ssh-rsa', ".ssh/id_rsa", Config);
-init_per_testcase(erlang_client_openssh_server_publickey_dsa, Config) ->
- chk_key(sshd, 'ssh-dss', ".ssh/id_dsa", Config);
-init_per_testcase(erlang_client_openssh_server_publickey_rsa, Config) ->
- chk_key(sshd, 'ssh-rsa', ".ssh/id_rsa", Config);
-
init_per_testcase(erlang_server_openssh_client_renegotiate, Config) ->
case os:type() of
{unix,_} -> ssh:start(), Config;
@@ -123,27 +103,6 @@ end_per_testcase(_TestCase, _Config) ->
ssh:stop(),
ok.
-
-chk_key(Pgm, Name, File, Config) ->
- case ssh_test_lib:openssh_supports(Pgm, public_key, Name) of
- false ->
- {skip,lists:concat(["openssh client does not support ",Name])};
- true ->
- {ok,[[Home]]} = init:get_argument(home),
- KeyFile = filename:join(Home, File),
- case file:read_file(KeyFile) of
- {ok, Pem} ->
- case public_key:pem_decode(Pem) of
- [{_,_, not_encrypted}] ->
- init_per_testcase('__default__',Config);
- _ ->
- {skip, {error, "Has pass phrase can not be used by automated test case"}}
- end;
- _ ->
- {skip, lists:concat(["no ~/",File])}
- end
- end.
-
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
@@ -161,219 +120,6 @@ erlang_shell_client_openssh_server(Config) when is_list(Config) ->
receive_logout(),
receive_normal_exit(Shell).
-%--------------------------------------------------------------------
-erlang_client_openssh_server_exec() ->
- [{doc, "Test api function ssh_connection:exec"}].
-
-erlang_client_openssh_server_exec(Config) when is_list(Config) ->
- ConnectionRef = ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true},
- {user_interaction, false}]),
- {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity),
- success = ssh_connection:exec(ConnectionRef, ChannelId0,
- "echo testing", infinity),
- Data0 = {ssh_cm, ConnectionRef, {data, ChannelId0, 0, <<"testing\n">>}},
- case ssh_test_lib:receive_exec_result(Data0) of
- expected ->
- ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId0);
- {unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId0, 0}}
- = ExitStatus0} ->
- ct:log("0: Collected data ~p", [ExitStatus0]),
- ssh_test_lib:receive_exec_result(Data0,
- ConnectionRef, ChannelId0);
- Other0 ->
- ct:fail(Other0)
- end,
-
- {ok, ChannelId1} = ssh_connection:session_channel(ConnectionRef, infinity),
- success = ssh_connection:exec(ConnectionRef, ChannelId1,
- "echo testing1", infinity),
- Data1 = {ssh_cm, ConnectionRef, {data, ChannelId1, 0, <<"testing1\n">>}},
- case ssh_test_lib:receive_exec_result(Data1) of
- expected ->
- ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId1);
- {unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId1, 0}}
- = ExitStatus1} ->
- ct:log("0: Collected data ~p", [ExitStatus1]),
- ssh_test_lib:receive_exec_result(Data1,
- ConnectionRef, ChannelId1);
- Other1 ->
- ct:fail(Other1)
- end.
-
-%%--------------------------------------------------------------------
-erlang_client_openssh_server_exec_compressed() ->
- [{doc, "Test that compression option works"}].
-
-erlang_client_openssh_server_exec_compressed(Config) when is_list(Config) ->
- CompressAlgs = [zlib, '[email protected]',none],
- case ssh_test_lib:ssh_supports(CompressAlgs, compression) of
- {false,L} ->
- {skip, io_lib:format("~p compression is not supported",[L])};
-
- true ->
- ConnectionRef = ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true},
- {user_interaction, false},
- {preferred_algorithms,
- [{compression,CompressAlgs}]}]),
- {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
- success = ssh_connection:exec(ConnectionRef, ChannelId,
- "echo testing", infinity),
- Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"testing\n">>}},
- case ssh_test_lib:receive_exec_result(Data) of
- expected ->
- ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId);
- {unexpected_msg,{ssh_cm, ConnectionRef,
- {exit_status, ChannelId, 0}} = ExitStatus} ->
- ct:log("0: Collected data ~p", [ExitStatus]),
- ssh_test_lib:receive_exec_result(Data, ConnectionRef, ChannelId);
- Other ->
- ct:fail(Other)
- end
- end.
-
-%%--------------------------------------------------------------------
-erlang_client_openssh_server_kexs() ->
- [{doc, "Test that we can connect with different KEXs."}].
-
-erlang_client_openssh_server_kexs(Config) when is_list(Config) ->
- KexAlgos = try proplists:get_value(kex, proplists:get_value(common_algs,Config))
- catch _:_ -> []
- end,
- comment(KexAlgos),
- case KexAlgos of
- [] -> {skip, "No common kex algorithms"};
- _ ->
- Success =
- lists:foldl(
- fun(Kex, Acc) ->
- ConnectionRef =
- ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true},
- {user_interaction, false},
- {preferred_algorithms,
- [{kex,[Kex]}]}]),
-
- {ok, ChannelId} =
- ssh_connection:session_channel(ConnectionRef, infinity),
- success =
- ssh_connection:exec(ConnectionRef, ChannelId,
- "echo testing", infinity),
-
- ExpectedData = {ssh_cm, ConnectionRef, {data, ChannelId, 0, <<"testing\n">>}},
- case ssh_test_lib:receive_exec_result(ExpectedData) of
- expected ->
- ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId),
- Acc;
- {unexpected_msg,{ssh_cm, ConnectionRef,
- {exit_status, ChannelId, 0}} = ExitStatus} ->
- ct:log("0: Collected data ~p", [ExitStatus]),
- ssh_test_lib:receive_exec_result(ExpectedData, ConnectionRef, ChannelId),
- Acc;
- Other ->
- ct:log("~p failed: ~p",[Kex,Other]),
- false
- end
- end, true, KexAlgos),
- case Success of
- true ->
- ok;
- false ->
- {fail, "Kex failed for one or more algos"}
- end
- end.
-
-%%--------------------------------------------------------------------
-erlang_client_openssh_server_setenv() ->
- [{doc, "Test api function ssh_connection:setenv"}].
-
-erlang_client_openssh_server_setenv(Config) when is_list(Config) ->
- ConnectionRef =
- ssh_test_lib:connect(?SSH_DEFAULT_PORT, [{silently_accept_hosts, true},
- {user_interaction, false}]),
- {ok, ChannelId} =
- ssh_connection:session_channel(ConnectionRef, infinity),
- Env = case ssh_connection:setenv(ConnectionRef, ChannelId,
- "ENV_TEST", "testing_setenv",
- infinity) of
- success ->
- <<"tesing_setenv\n">>;
- failure ->
- <<"\n">>
- end,
- success = ssh_connection:exec(ConnectionRef, ChannelId,
- "echo $ENV_TEST", infinity),
- Data = {ssh_cm, ConnectionRef, {data, ChannelId, 0, Env}},
- case ssh_test_lib:receive_exec_result(Data) of
- expected ->
- ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId);
- {unexpected_msg,{ssh_cm, ConnectionRef,
- {data,0,1, UnxpectedData}}} ->
- %% Some os may return things as
- %% ENV_TEST: Undefined variable.\n"
- ct:log("UnxpectedData: ~p", [UnxpectedData]),
- ssh_test_lib:receive_exec_end(ConnectionRef, ChannelId);
- {unexpected_msg,{ssh_cm, ConnectionRef, {exit_status, ChannelId, 0}}
- = ExitStatus} ->
- ct:log("0: Collected data ~p", [ExitStatus]),
- ssh_test_lib:receive_exec_result(Data,
- ConnectionRef, ChannelId);
- Other ->
- ct:fail(Other)
- end.
-
-%%--------------------------------------------------------------------
-
-%% setenv not meaningfull on erlang ssh daemon!
-
-%%--------------------------------------------------------------------
-erlang_client_openssh_server_publickey_rsa(Config) ->
- erlang_client_openssh_server_publickey_X(Config, 'ssh-rsa').
-
-erlang_client_openssh_server_publickey_dsa(Config) ->
- erlang_client_openssh_server_publickey_X(Config, 'ssh-dss').
-
-
-erlang_client_openssh_server_publickey_X(Config, Alg) ->
- ConnectionRef =
- ssh_test_lib:connect(?SSH_DEFAULT_PORT,
- [{pref_public_key_algs, [Alg]},
- {user_interaction, false},
- {auth_methods, "publickey"},
- silently_accept_hosts]),
- {ok, Channel} =
- ssh_connection:session_channel(ConnectionRef, infinity),
- ok = ssh_connection:close(ConnectionRef, Channel),
- ok = ssh:close(ConnectionRef).
-
-%%--------------------------------------------------------------------
-erlang_server_openssh_client_public_key_dsa() ->
- [{timetrap, {seconds,(?TIMEOUT div 1000)+10}}].
-erlang_server_openssh_client_public_key_dsa(Config) when is_list(Config) ->
- erlang_server_openssh_client_public_key_X(Config, 'ssh-dss').
-
-erlang_server_openssh_client_public_key_rsa() ->
- [{timetrap, {seconds,(?TIMEOUT div 1000)+10}}].
-erlang_server_openssh_client_public_key_rsa(Config) when is_list(Config) ->
- erlang_server_openssh_client_public_key_X(Config, 'ssh-rsa').
-
-
-erlang_server_openssh_client_public_key_X(Config, Alg) ->
- SystemDir = proplists:get_value(data_dir, Config),
- PrivDir = proplists:get_value(priv_dir, Config),
- KnownHosts = filename:join(PrivDir, "known_hosts"),
- {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
- {preferred_algorithms,[{public_key, [Alg]}]},
- {auth_methods, "publickey"},
- {failfun, fun ssh_test_lib:failfun/2}]),
- ct:sleep(500),
-
- Cmd = ssh_test_lib:open_sshc_cmd(Host, Port,
- [" -o UserKnownHostsFile=", KnownHosts,
- " -o StrictHostKeyChecking=no"],
- "1+1."),
- OpenSsh = ssh_test_lib:open_port({spawn, Cmd}),
- ssh_test_lib:rcv_expected({data,<<"2\n">>}, OpenSsh, ?TIMEOUT),
- ssh:stop_daemon(Pid).
-
%%--------------------------------------------------------------------
%% Test that the Erlang/OTP server can renegotiate with openSSH
erlang_server_openssh_client_renegotiate(Config) ->
@@ -431,108 +177,6 @@ erlang_server_openssh_client_renegotiate(Config) ->
end.
%%--------------------------------------------------------------------
-erlang_client_openssh_server_renegotiate(_Config) ->
- process_flag(trap_exit, true),
- IO = ssh_test_lib:start_io_server(),
- Ref = make_ref(),
- Parent = self(),
-
- Shell =
- spawn_link(
- fun() ->
- Host = ssh_test_lib:hostname(),
- Options = [{user_interaction, false},
- {silently_accept_hosts,true}],
- group_leader(IO, self()),
- {ok, ConnRef} = ssh:connect(Host, ?SSH_DEFAULT_PORT, Options),
- ct:log("Parent = ~p, IO = ~p, Shell = ~p, ConnRef = ~p~n",[Parent, IO, self(), ConnRef]),
- case ssh_connection:session_channel(ConnRef, infinity) of
- {ok,ChannelId} ->
- success = ssh_connection:ptty_alloc(ConnRef, ChannelId, []),
- Args = [{channel_cb, ssh_shell},
- {init_args,[ConnRef, ChannelId]},
- {cm, ConnRef}, {channel_id, ChannelId}],
- {ok, State} = ssh_channel:init([Args]),
- Parent ! {ok, Ref, ConnRef},
- ssh_channel:enter_loop(State);
- Error ->
- Parent ! {error, Ref, Error}
- end,
- receive
- nothing -> ok
- end
- end),
-
- receive
- {error, Ref, Error} ->
- ct:fail("Error=~p",[Error]);
- {ok, Ref, ConnectionRef} ->
- IO ! {input, self(), "echo Hej1\n"},
- receive_data("Hej1", ConnectionRef),
- Kex1 = ssh_test_lib:get_kex_init(ConnectionRef),
- ssh_connection_handler:renegotiate(ConnectionRef),
- IO ! {input, self(), "echo Hej2\n"},
- receive_data("Hej2", ConnectionRef),
- Kex2 = ssh_test_lib:get_kex_init(ConnectionRef),
- IO ! {input, self(), "exit\n"},
- receive_logout(),
- receive_normal_exit(Shell),
- true = (Kex1 =/= Kex2)
- end.
-
-%%--------------------------------------------------------------------
-erlang_client_openssh_server_password() ->
- [{doc, "Test client password option"}].
-erlang_client_openssh_server_password(Config) when is_list(Config) ->
- %% to make sure we don't public-key-auth
- UserDir = proplists:get_value(data_dir, Config),
- {error, Reason0} =
- ssh:connect(any, ?SSH_DEFAULT_PORT, [{silently_accept_hosts, true},
- {user, "foo"},
- {password, "morot"},
- {user_interaction, false},
- {user_dir, UserDir}]),
-
- ct:log("Test of user foo that does not exist. "
- "Error msg: ~p~n", [Reason0]),
-
- User = string:strip(os:cmd("whoami"), right, $\n),
-
- case length(string:tokens(User, " ")) of
- 1 ->
- {error, Reason1} =
- ssh:connect(any, ?SSH_DEFAULT_PORT,
- [{silently_accept_hosts, true},
- {user, User},
- {password, "foo"},
- {user_interaction, false},
- {user_dir, UserDir}]),
- ct:log("Test of wrong Pasword. "
- "Error msg: ~p~n", [Reason1]);
- _ ->
- ct:log("Whoami failed reason: ~n", [])
- end.
-
-%%--------------------------------------------------------------------
-
-erlang_client_openssh_server_nonexistent_subsystem() ->
- [{doc, "Test client password option"}].
-erlang_client_openssh_server_nonexistent_subsystem(Config) when is_list(Config) ->
-
- ConnectionRef = ssh_test_lib:connect(?SSH_DEFAULT_PORT,
- [{user_interaction, false},
- silently_accept_hosts]),
-
- {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
-
- failure = ssh_connection:subsystem(ConnectionRef, ChannelId, "foo", infinity).
-
-%%--------------------------------------------------------------------
-%
-%% Not possible to send password with openssh without user interaction
-%%
-%%--------------------------------------------------------------------
-%%--------------------------------------------------------------------
%%% Internal functions -----------------------------------------------
%%--------------------------------------------------------------------
receive_data(Data, Conn) ->
diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk
index 7208baca6e..ae7b4cf3f2 100644
--- a/lib/ssh/vsn.mk
+++ b/lib/ssh/vsn.mk
@@ -1,5 +1,4 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
-SSH_VSN = 4.5
-
+SSH_VSN = 4.7.1
APP_VSN = "ssh-$(SSH_VSN)"
diff --git a/lib/ssl/doc/src/Makefile b/lib/ssl/doc/src/Makefile
index 669062779e..c72b6d6cc4 100644
--- a/lib/ssl/doc/src/Makefile
+++ b/lib/ssl/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2015. All Rights Reserved.
+# Copyright Ericsson AB 1999-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -38,25 +38,25 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
# Target Specs
# ----------------------------------------------------
XML_APPLICATION_FILES = refman.xml
-XML_REF3_FILES = ssl.xml ssl_crl_cache.xml ssl_crl_cache_api.xml ssl_session_cache_api.xml
+XML_REF3_FILES = ssl.xml ssl_crl_cache.xml ssl_crl_cache_api.xml ssl_session_cache_api.xml
XML_REF6_FILES = ssl_app.xml
-XML_PART_FILES = release_notes.xml usersguide.xml
+XML_PART_FILES = usersguide.xml
XML_CHAPTER_FILES = \
+ ssl_introduction.xml \
ssl_protocol.xml \
using_ssl.xml \
- pkix_certs.xml \
ssl_distribution.xml \
notes.xml
BOOK_FILES = book.xml
XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) $(XML_REF6_FILES) \
- $(XML_PART_FILES) $(XML_CHAPTER_FILES)
+ $(XML_PART_FILES) $(XML_CHAPTER_FILES)
-GIF_FILES = warning.gif
+GIF_FILES =
-PS_FILES =
+PS_FILES =
XML_FLAGS += -defs cite cite.defs -booksty otpA4
@@ -81,10 +81,10 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
+XML_FLAGS +=
+DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -102,6 +102,7 @@ html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f errs core *~
@@ -110,11 +111,11 @@ man: $(MAN3_FILES) $(MAN6_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-debug opt:
+debug opt:
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
diff --git a/lib/ssl/doc/src/fascicules.xml b/lib/ssl/doc/src/fascicules.xml
deleted file mode 100644
index 7a60e8dd1f..0000000000
--- a/lib/ssl/doc/src/fascicules.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="usersguide" href="usersguide_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="refman" href="refman_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="release_notes" href="release_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
-
diff --git a/lib/ssl/doc/src/note.gif b/lib/ssl/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/ssl/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 5a39cac9bc..5a2e394c72 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1999</year><year>2017</year>
+ <year>1999</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -27,6 +27,606 @@
</header>
<p>This document describes the changes made to the SSL application.</p>
+<section><title>SSL 9.0.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Use separate processes for sending and receiving
+ application data for TLS connections to avoid potential
+ deadlock that was most likely to occur when using TLS for
+ Erlang distribution. Note does not change the API.</p>
+ <p>
+ Own Id: OTP-15122</p>
+ </item>
+ <item>
+ <p>
+ Correct handling of empty server SNI extension</p>
+ <p>
+ Own Id: OTP-15168</p>
+ </item>
+ <item>
+ <p>
+ Correct PSK cipher suite handling and add
+ selected_cipher_suite to connection information</p>
+ <p>
+ Own Id: OTP-15172</p>
+ </item>
+ <item>
+ <p>
+ Adopt to the fact that cipher suite sign restriction are
+ relaxed in TLS-1.2</p>
+ <p>
+ Own Id: OTP-15173</p>
+ </item>
+ <item>
+ <p>
+ Enhance error handling of non existing PEM files</p>
+ <p>
+ Own Id: OTP-15174</p>
+ </item>
+ <item>
+ <p>
+ Correct close handling of transport accepted sockets in
+ the error state</p>
+ <p>
+ Own Id: OTP-15216</p>
+ </item>
+ <item>
+ <p>
+ Correct PEM cache to not add references to empty entries
+ when PEM file does not exist.</p>
+ <p>
+ Own Id: OTP-15224</p>
+ </item>
+ <item>
+ <p>
+ Correct handling of all PSK cipher suites</p>
+ <p>
+ Before only some PSK suites would be correctly negotiated
+ and most PSK ciphers suites would fail the connection.</p>
+ <p>
+ Own Id: OTP-15285</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ TLS will now try to order certificate chains if they
+ appear to be unordered. That is prior to TLS 1.3,
+ “certificate_list” ordering was required to be
+ strict, however some implementations already allowed for
+ some flexibility. For maximum compatibility, all
+ implementations SHOULD be prepared to handle potentially
+ extraneous certificates and arbitrary orderings from any
+ TLS version.</p>
+ <p>
+ Own Id: OTP-12983</p>
+ </item>
+ <item>
+ <p>
+ TLS will now try to reconstructed an incomplete
+ certificate chains from its local CA-database and use
+ that data for the certificate path validation. This
+ especially makes sense for partial chains as then the
+ peer might not send an intermediate CA as it is
+ considered the trusted root in that case.</p>
+ <p>
+ Own Id: OTP-15060</p>
+ </item>
+ <item>
+ <p>
+ Option keyfile defaults to certfile and should be trumped
+ with key. This failed for engine keys.</p>
+ <p>
+ Own Id: OTP-15193</p>
+ </item>
+ <item>
+ <p>
+ Error message improvement when own certificate has
+ decoding issues, see also issue ERL-668.</p>
+ <p>
+ Own Id: OTP-15234</p>
+ </item>
+ <item>
+ <p>
+ Correct dialyzer spec for key option</p>
+ <p>
+ Own Id: OTP-15281</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 9.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Correct cipher suite handling for ECDHE_*, the incorrect
+ handling could cause an incorrrect suite to be selected
+ and most likly fail the handshake.</p>
+ <p>
+ Own Id: OTP-15203</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 9.0</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Correct handling of ECDH suites.</p>
+ <p>
+ Own Id: OTP-14974</p>
+ </item>
+ <item>
+ <p>
+ Proper handling of clients that choose to send an empty
+ answer to a certificate request</p>
+ <p>
+ Own Id: OTP-15050</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Distribution over SSL (inet_tls) has, to improve
+ performance, been rewritten to not use intermediate
+ processes and ports.</p>
+ <p>
+ Own Id: OTP-14465</p>
+ </item>
+ <item>
+ <p>
+ Add suport for ECDHE_PSK cipher suites</p>
+ <p>
+ Own Id: OTP-14547</p>
+ </item>
+ <item>
+ <p>
+ For security reasons no longer support 3-DES cipher
+ suites by default</p>
+ <p>
+ *** INCOMPATIBILITY with possibly ***</p>
+ <p>
+ Own Id: OTP-14768</p>
+ </item>
+ <item>
+ <p>
+ For security reasons RSA-key exchange cipher suites are
+ no longer supported by default</p>
+ <p>
+ *** INCOMPATIBILITY with possible ***</p>
+ <p>
+ Own Id: OTP-14769</p>
+ </item>
+ <item>
+ <p>
+ The interoperability option to fallback to insecure
+ renegotiation now has to be explicitly turned on.</p>
+ <p>
+ *** INCOMPATIBILITY with possibly ***</p>
+ <p>
+ Own Id: OTP-14789</p>
+ </item>
+ <item>
+ <p>
+ Drop support for SSLv2 enabled clients. SSLv2 has been
+ broken for decades and never supported by the Erlang
+ SSL/TLS implementation. This option was by default
+ disabled and enabling it has proved to sometimes break
+ connections not using SSLv2 enabled clients.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-14824</p>
+ </item>
+ <item>
+ <p>
+ Remove CHACHA20_POLY1305 ciphers form default for now. We
+ have discovered interoperability problems, ERL-538, that
+ we believe needs to be solved in crypto.</p>
+ <p>
+ *** INCOMPATIBILITY with possibly ***</p>
+ <p>
+ Own Id: OTP-14882</p>
+ </item>
+ <item>
+ <p>
+ Generalize DTLS packet multiplexing to make it easier to
+ add future DTLS features and uses.</p>
+ <p>
+ Own Id: OTP-14888</p>
+ </item>
+ <item>
+ <p>
+ Use uri_string module instead of http_uri.</p>
+ <p>
+ Own Id: OTP-14902</p>
+ </item>
+ <item>
+ <p>
+ The SSL distribution protocol <c>-proto inet_tls</c> has
+ stopped setting the SSL option
+ <c>server_name_indication</c>. New verify funs for client
+ and server in <c>inet_tls_dist</c> has been added, not
+ documented yet, that checks node name if present in peer
+ certificate. Usage is still also yet to be documented.</p>
+ <p>
+ Own Id: OTP-14969 Aux Id: OTP-14465, ERL-598 </p>
+ </item>
+ <item>
+ <p>
+ Deprecate ssl:ssl_accept/[1,2,3] in favour of
+ ssl:handshake/[1,2,3]</p>
+ <p>
+ Own Id: OTP-15056</p>
+ </item>
+ <item>
+ <p>
+ Customizes the hostname verification of the peer
+ certificate, as different protocols that use TLS such as
+ HTTP or LDAP may want to do it differently</p>
+ <p>
+ Own Id: OTP-15102 Aux Id: ERL-542, OTP-14962 </p>
+ </item>
+ <item>
+ <p>
+ Add utility function for converting erlang cipher suites
+ to a string represenation (ERL-600).</p>
+ <p>
+ Own Id: OTP-15106</p>
+ </item>
+ <item>
+ <p>
+ First version with support for DTLS</p>
+ <p>
+ Own Id: OTP-15142</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 8.2.6.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Correct handling of empty server SNI extension</p>
+ <p>
+ Own Id: OTP-15168</p>
+ </item>
+ <item>
+ <p>
+ Correct cipher suite handling for ECDHE_*, the incorrect
+ handling could cause an incorrrect suite to be selected
+ and most likly fail the handshake.</p>
+ <p>
+ Own Id: OTP-15203</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 8.2.6.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improve cipher suite handling correcting ECC and TLS-1.2
+ requierments. Backport of solution for ERL-641</p>
+ <p>
+ Own Id: OTP-15178</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Option keyfile defaults to certfile and should be trumped
+ with key. This failed for engine keys.</p>
+ <p>
+ Own Id: OTP-15193</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 8.2.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Proper handling of clients that choose to send an empty
+ answer to a certificate request</p>
+ <p>
+ Own Id: OTP-15050</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 8.2.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix filter function to not incorrectly exclude AEAD
+ cipher suites</p>
+ <p>
+ Own Id: OTP-14981</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 8.2.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Optimization of bad merge conflict resolution causing
+ dubble decode</p>
+ <p>
+ Own Id: OTP-14843</p>
+ </item>
+ <item>
+ <p>
+ Restore error propagation to OTP-19.3 behaviour, in
+ OTP-20.2 implementation adjustments to gen_statem needed
+ some further adjustments to avoid a race condition. This
+ could cause a TLS server to not always report file path
+ errors correctly.</p>
+ <p>
+ Own Id: OTP-14852</p>
+ </item>
+ <item>
+ <p>
+ Corrected RC4 suites listing function to regard TLS
+ version</p>
+ <p>
+ Own Id: OTP-14871</p>
+ </item>
+ <item>
+ <p>
+ Fix alert handling so that unexpected messages are logged
+ and alerted correctly</p>
+ <p>
+ Own Id: OTP-14919</p>
+ </item>
+ <item>
+ <p>
+ Correct handling of anonymous cipher suites</p>
+ <p>
+ Own Id: OTP-14952</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added new API functions to facilitate cipher suite
+ handling</p>
+ <p>
+ Own Id: OTP-14760</p>
+ </item>
+ <item>
+ <p>
+ Correct TLS_FALLBACK_SCSV handling so that this special
+ flag suite is always placed last in the cipher suite list
+ in accordance with the specs. Also make sure this
+ functionality is used in DTLS.</p>
+ <p>
+ Own Id: OTP-14828</p>
+ </item>
+ <item>
+ <p>
+ Add TLS record version sanity check for early as possible
+ error detection and consistency in ALERT codes generated</p>
+ <p>
+ Own Id: OTP-14892</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 8.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Packet options cannot be supported for unreliable
+ transports, that is, packet option for DTLS over udp will
+ not be supported.</p>
+ <p>
+ Own Id: OTP-14664</p>
+ </item>
+ <item>
+ <p>
+ Ensure data delivery before close if possible. This fix
+ is related to fix in PR-1479.</p>
+ <p>
+ Own Id: OTP-14794</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The crypto API is extended to use private/public keys
+ stored in an Engine for sign/verify or encrypt/decrypt
+ operations.</p>
+ <p>
+ The ssl application provides an API to use this new
+ engine concept in TLS.</p>
+ <p>
+ Own Id: OTP-14448</p>
+ </item>
+ <item>
+ <p>
+ Implemented renegotiation for DTLS</p>
+ <p>
+ Own Id: OTP-14563</p>
+ </item>
+ <item>
+ <p>
+ A new command line option <c>-ssl_dist_optfile</c> has
+ been added to facilitate specifying the many options
+ needed when using SSL as the distribution protocol.</p>
+ <p>
+ Own Id: OTP-14657</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 8.2.2</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ TLS sessions must be registered with SNI if provided, so
+ that sessions where client hostname verification would
+ fail can not connect reusing a session created when the
+ server name verification succeeded.</p>
+ <p>
+ Own Id: OTP-14632</p>
+ </item>
+ <item>
+ <p> An erlang TLS server configured with cipher suites
+ using rsa key exchange, may be vulnerable to an Adaptive
+ Chosen Ciphertext attack (AKA Bleichenbacher attack)
+ against RSA, which when exploited, may result in
+ plaintext recovery of encrypted messages and/or a
+ Man-in-the-middle (MiTM) attack, despite the attacker not
+ having gained access to the server’s private key
+ itself. <url
+ href="https://nvd.nist.gov/vuln/detail/CVE-2017-1000385">CVE-2017-1000385</url>
+ </p> <p> Exploiting this vulnerability to perform
+ plaintext recovery of encrypted messages will, in most
+ practical cases, allow an attacker to read the plaintext
+ only after the session has completed. Only TLS sessions
+ established using RSA key exchange are vulnerable to this
+ attack. </p> <p> Exploiting this vulnerability to conduct
+ a MiTM attack requires the attacker to complete the
+ initial attack, which may require thousands of server
+ requests, during the handshake phase of the targeted
+ session within the window of the configured handshake
+ timeout. This attack may be conducted against any TLS
+ session using RSA signatures, but only if cipher suites
+ using RSA key exchange are also enabled on the server.
+ The limited window of opportunity, limitations in
+ bandwidth, and latency make this attack significantly
+ more difficult to execute. </p> <p> RSA key exchange is
+ enabled by default although least prioritized if server
+ order is honored. For such a cipher suite to be chosen it
+ must also be supported by the client and probably the
+ only shared cipher suite. </p> <p> Captured TLS sessions
+ encrypted with ephemeral cipher suites (DHE or ECDHE) are
+ not at risk for subsequent decryption due to this
+ vulnerability. </p> <p> As a workaround if default cipher
+ suite configuration was used you can configure the server
+ to not use vulnerable suites with the ciphers option like
+ this: </p> <c> {ciphers, [Suite || Suite &lt;-
+ ssl:cipher_suites(), element(1,Suite) =/= rsa]} </c> <p>
+ that is your code will look somethingh like this: </p>
+ <c> ssl:listen(Port, [{ciphers, [Suite || Suite &lt;-
+ ssl:cipher_suites(), element(1,S) =/= rsa]} | Options]).
+ </c> <p> Thanks to Hanno Böck, Juraj Somorovsky and
+ Craig Young for reporting this vulnerability. </p>
+ <p>
+ Own Id: OTP-14748</p>
+ </item>
+ </list>
+ </section>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ If no SNI is available and the hostname is an IP-address
+ also check for IP-address match. This check is not as
+ good as a DNS hostname check and certificates using
+ IP-address are not recommended.</p>
+ <p>
+ Own Id: OTP-14655</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 8.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Max session table works correctly again</p>
+ <p>
+ Own Id: OTP-14556</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Customize alert handling for DTLS over UDP to mitigate
+ DoS attacks</p>
+ <p>
+ Own Id: OTP-14078</p>
+ </item>
+ <item>
+ <p>
+ Improved error propagation and reports</p>
+ <p>
+ Own Id: OTP-14236</p>
+ </item>
+ </list>
+ </section>
+
+</section>
<section><title>SSL 8.2</title>
@@ -141,9 +741,74 @@
</item>
</list>
</section>
+</section>
+<section><title>SSL 8.1.3.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix alert handling so that unexpected messages are logged
+ and alerted correctly</p>
+ <p>
+ Own Id: OTP-14929</p>
+ </item>
+ </list>
+ </section>
</section>
+<section><title>SSL 8.1.3.1</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> An erlang TLS server configured with cipher suites
+ using rsa key exchange, may be vulnerable to an Adaptive
+ Chosen Ciphertext attack (AKA Bleichenbacher attack)
+ against RSA, which when exploited, may result in
+ plaintext recovery of encrypted messages and/or a
+ Man-in-the-middle (MiTM) attack, despite the attacker not
+ having gained access to the server’s private key
+ itself. <url
+ href="https://nvd.nist.gov/vuln/detail/CVE-2017-1000385">CVE-2017-1000385</url>
+ </p> <p> Exploiting this vulnerability to perform
+ plaintext recovery of encrypted messages will, in most
+ practical cases, allow an attacker to read the plaintext
+ only after the session has completed. Only TLS sessions
+ established using RSA key exchange are vulnerable to this
+ attack. </p> <p> Exploiting this vulnerability to conduct
+ a MiTM attack requires the attacker to complete the
+ initial attack, which may require thousands of server
+ requests, during the handshake phase of the targeted
+ session within the window of the configured handshake
+ timeout. This attack may be conducted against any TLS
+ session using RSA signatures, but only if cipher suites
+ using RSA key exchange are also enabled on the server.
+ The limited window of opportunity, limitations in
+ bandwidth, and latency make this attack significantly
+ more difficult to execute. </p> <p> RSA key exchange is
+ enabled by default although least prioritized if server
+ order is honored. For such a cipher suite to be chosen it
+ must also be supported by the client and probably the
+ only shared cipher suite. </p> <p> Captured TLS sessions
+ encrypted with ephemeral cipher suites (DHE or ECDHE) are
+ not at risk for subsequent decryption due to this
+ vulnerability. </p> <p> As a workaround if default cipher
+ suite configuration was used you can configure the server
+ to not use vulnerable suites with the ciphers option like
+ this: </p> <c> {ciphers, [Suite || Suite &lt;-
+ ssl:cipher_suites(), element(1,Suite) =/= rsa]} </c> <p>
+ that is your code will look somethingh like this: </p>
+ <c> ssl:listen(Port, [{ciphers, [Suite || Suite &lt;-
+ ssl:cipher_suites(), element(1,S) =/= rsa]} | Options]).
+ </c> <p> Thanks to Hanno Böck, Juraj Somorovsky and
+ Craig Young for reporting this vulnerability. </p>
+ <p>
+ Own Id: OTP-14748</p>
+ </item>
+ </list>
+ </section>
+</section>
<section><title>SSL 8.1.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -522,6 +1187,60 @@
</section>
+ <section><title>SSL 7.3.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> An erlang TLS server configured with cipher suites
+ using rsa key exchange, may be vulnerable to an Adaptive
+ Chosen Ciphertext attack (AKA Bleichenbacher attack)
+ against RSA, which when exploited, may result in
+ plaintext recovery of encrypted messages and/or a
+ Man-in-the-middle (MiTM) attack, despite the attacker not
+ having gained access to the server’s private key
+ itself. <url
+ href="https://nvd.nist.gov/vuln/detail/CVE-2017-1000385">CVE-2017-1000385</url>
+ </p> <p> Exploiting this vulnerability to perform
+ plaintext recovery of encrypted messages will, in most
+ practical cases, allow an attacker to read the plaintext
+ only after the session has completed. Only TLS sessions
+ established using RSA key exchange are vulnerable to this
+ attack. </p> <p> Exploiting this vulnerability to conduct
+ a MiTM attack requires the attacker to complete the
+ initial attack, which may require thousands of server
+ requests, during the handshake phase of the targeted
+ session within the window of the configured handshake
+ timeout. This attack may be conducted against any TLS
+ session using RSA signatures, but only if cipher suites
+ using RSA key exchange are also enabled on the server.
+ The limited window of opportunity, limitations in
+ bandwidth, and latency make this attack significantly
+ more difficult to execute. </p> <p> RSA key exchange is
+ enabled by default although least prioritized if server
+ order is honored. For such a cipher suite to be chosen it
+ must also be supported by the client and probably the
+ only shared cipher suite. </p> <p> Captured TLS sessions
+ encrypted with ephemeral cipher suites (DHE or ECDHE) are
+ not at risk for subsequent decryption due to this
+ vulnerability. </p> <p> As a workaround if default cipher
+ suite configuration was used you can configure the server
+ to not use vulnerable suites with the ciphers option like
+ this: </p> <c> {ciphers, [Suite || Suite &lt;-
+ ssl:cipher_suites(), element(1,Suite) =/= rsa]} </c> <p>
+ that is your code will look somethingh like this: </p>
+ <c> ssl:listen(Port, [{ciphers, [Suite || Suite &lt;-
+ ssl:cipher_suites(), element(1,S) =/= rsa]} | Options]).
+ </c> <p> Thanks to Hanno Böck, Juraj Somorovsky and
+ Craig Young for reporting this vulnerability. </p>
+ <p>
+ Own Id: OTP-14748</p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
<section><title>SSL 7.3.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -551,7 +1270,59 @@
</list>
</section>
+ <section><title>SSL 7.3.3.0.1</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> An erlang TLS server configured with cipher suites
+ using rsa key exchange, may be vulnerable to an Adaptive
+ Chosen Ciphertext attack (AKA Bleichenbacher attack)
+ against RSA, which when exploited, may result in
+ plaintext recovery of encrypted messages and/or a
+ Man-in-the-middle (MiTM) attack, despite the attacker not
+ having gained access to the server’s private key
+ itself. <url
+ href="https://nvd.nist.gov/vuln/detail/CVE-2017-1000385">CVE-2017-1000385</url>
+ </p> <p> Exploiting this vulnerability to perform
+ plaintext recovery of encrypted messages will, in most
+ practical cases, allow an attacker to read the plaintext
+ only after the session has completed. Only TLS sessions
+ established using RSA key exchange are vulnerable to this
+ attack. </p> <p> Exploiting this vulnerability to conduct
+ a MiTM attack requires the attacker to complete the
+ initial attack, which may require thousands of server
+ requests, during the handshake phase of the targeted
+ session within the window of the configured handshake
+ timeout. This attack may be conducted against any TLS
+ session using RSA signatures, but only if cipher suites
+ using RSA key exchange are also enabled on the server.
+ The limited window of opportunity, limitations in
+ bandwidth, and latency make this attack significantly
+ more difficult to execute. </p> <p> RSA key exchange is
+ enabled by default although least prioritized if server
+ order is honored. For such a cipher suite to be chosen it
+ must also be supported by the client and probably the
+ only shared cipher suite. </p> <p> Captured TLS sessions
+ encrypted with ephemeral cipher suites (DHE or ECDHE) are
+ not at risk for subsequent decryption due to this
+ vulnerability. </p> <p> As a workaround if default cipher
+ suite configuration was used you can configure the server
+ to not use vulnerable suites with the ciphers option like
+ this: </p> <c> {ciphers, [Suite || Suite &lt;-
+ ssl:cipher_suites(), element(1,Suite) =/= rsa]} </c> <p>
+ that is your code will look somethingh like this: </p>
+ <c> ssl:listen(Port, [{ciphers, [Suite || Suite &lt;-
+ ssl:cipher_suites(), element(1,S) =/= rsa]} | Options]).
+ </c> <p> Thanks to Hanno Böck, Juraj Somorovsky and
+ Craig Young for reporting this vulnerability. </p>
+ <p>
+ Own Id: OTP-14748</p>
+ </item>
+ </list>
+ </section>
+
+ </section>
<section><title>Improvements and New Features</title>
<list>
<item>
diff --git a/lib/ssl/doc/src/pkix_certs.xml b/lib/ssl/doc/src/pkix_certs.xml
deleted file mode 100644
index f365acef4d..0000000000
--- a/lib/ssl/doc/src/pkix_certs.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE chapter SYSTEM "chapter.dtd">
-
-<chapter>
- <header>
- <copyright>
- <year>2003</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>PKIX Certificates</title>
- <prepared>UAB/F/P Peter H&ouml;gfeldt</prepared>
- <docno></docno>
- <date>2003-06-09</date>
- <rev>A</rev>
- <file>pkix_certs.xml</file>
- </header>
-
- <section>
- <title>Introduction to Certificates</title>
- <p>Certificates were originally defined by ITU (CCITT) and the latest
- definitions are described in <cite id="X.509"></cite>, but those definitions
- are (as always) not working.
- </p>
- <p>Working certificate definitions for the Internet Community are found
- in the the PKIX RFCs <cite id="rfc3279"></cite> and <cite id="rfc3280"></cite>.
- The parsing of certificates in the Erlang/OTP SSL application is
- based on those RFCS.
- </p>
- <p>Certificates are defined in terms of ASN.1 (<cite id="X.680"></cite>).
- For an introduction to ASN.1 see <url href="http://asn1.elibel.tm.fr/">ASN.1 Information Site</url>.
- </p>
- </section>
-
- <section>
- <title>PKIX Certificates</title>
- <p>Certificate handling is now handled by the <c>public_key</c> application.</p>
- <p>
- DER encoded certificates returned by <c>ssl:peercert/1</c> can for example
- be decoded by the <c>public_key:pkix_decode_cert/2</c> function.
- </p>
- </section>
-</chapter>
-
-
diff --git a/lib/ssl/doc/src/release_notes.xml b/lib/ssl/doc/src/release_notes.xml
deleted file mode 100644
index 2e263c69a7..0000000000
--- a/lib/ssl/doc/src/release_notes.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>1999</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>SSL Release Notes</title>
- <prepared>Peter H&ouml;gfeldt</prepared>
- <docno></docno>
- <date>2003-05-26</date>
- <rev>A</rev>
- <file>release_notes.sgml</file>
- </header>
- <description>
- <p>The SSL application provides secure communication over sockets.
- </p>
- <p>This product includes software developed by the OpenSSL Project for
- use in the OpenSSL Toolkit (http://www.openssl.org/).
- </p>
- <p>This product includes cryptographic software written by Eric Young
- </p>
- <p>This product includes software written by Tim Hudson
- </p>
- <p>For full OpenSSL and SSLeay license texts, see <seealso marker="licenses#licenses">Licenses</seealso>.
- </p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
-
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index ca2dcbb761..3029977745 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1999</year><year>2017</year>
+ <year>1999</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,7 +32,7 @@
<modulesummary>Interface Functions for Secure Socket Layer</modulesummary>
<description>
<p>
- This module contains interface functions for the SSL/TLS protocol.
+ This module contains interface functions for the SSL/TLS/DTLS protocol.
For detailed information about the supported standards see
<seealso marker="ssl_app">ssl(6)</seealso>.
</p>
@@ -40,7 +40,7 @@
<section>
<title>DATA TYPES</title>
- <p>The following data types are used in the functions for SSL:</p>
+ <p>The following data types are used in the functions for SSL/TLS/DTLS:</p>
<taglist>
@@ -56,9 +56,11 @@
<p>The default socket options are
<c>[{mode,list},{packet, 0},{header, 0},{active, true}]</c>.</p>
<p>For valid options, see the
- <seealso marker="kernel:inet">inet(3)</seealso> and
- <seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso> manual pages
- in Kernel.</p></item>
+ <seealso marker="kernel:inet">inet(3)</seealso>,
+ <seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso> and
+ <seealso marker="kernel:gen_tcp">gen_udp(3)</seealso>
+ manual pages
+ in Kernel. Note that stream oriented options such as packet are only relevant for SSL/TLS and not DTLS</p></item>
<tag><marker id="type-ssloption"/><c>ssl_option() =</c></tag>
<item>
@@ -69,7 +71,9 @@
<p><c>| {cert, public_key:der_encoded()}</c></p>
<p><c>| {certfile, path()}</c></p>
<p><c>| {key, {'RSAPrivateKey'| 'DSAPrivateKey' | 'ECPrivateKey'
- | 'PrivateKeyInfo', public_key:der_encoded()}}</c></p>
+ | 'PrivateKeyInfo', public_key:der_encoded()} |
+ #{algorithm := rsa | dss | ecdsa,
+ engine := crypto:engine_ref(), key_id := crypto:key_id(), password => crypto:password()}</c></p>
<p><c>| {keyfile, path()}</c></p>
<p><c>| {password, string()}</c></p>
<p><c>| {cacerts, [public_key:der_encoded()]}</c></p>
@@ -85,6 +89,7 @@
[binary()]} | {client | server, [binary()], binary()}}</c></p>
<p><c>| {log_alert, boolean()}</c></p>
<p><c>| {server_name_indication, hostname() | disable}</c></p>
+ <p><c>| {customize_hostname_check, list()}</c></p>
<p><c>| {sni_hosts, [{hostname(), [ssl_option()]}]}</c></p>
<p><c>| {sni_fun, SNIfun::fun()}</c></p>
</item>
@@ -93,13 +98,14 @@
<item><p><c>{cb_info, {CallbackModule::atom(), DataTag::atom(),
ClosedTag::atom(), ErrTag:atom()}}</c></p>
- <p>Defaults to <c>{gen_tcp, tcp, tcp_closed, tcp_error}</c>. Can be used
- to customize the transport layer. The callback module must implement a
+ <p>Defaults to <c>{gen_tcp, tcp, tcp_closed, tcp_error}</c> for TLS
+ and <c>{gen_udp, udp, udp_closed, udp_error}</c> for DTLS. Can be used
+ to customize the transport layer. For TLS the callback module must implement a
reliable transport protocol, behave as <c>gen_tcp</c>, and have functions
corresponding to <c>inet:setopts/2</c>, <c>inet:getopts/2</c>,
<c>inet:peername/1</c>, <c>inet:sockname/1</c>, and <c>inet:port/1</c>.
The callback <c>gen_tcp</c> is treated specially and calls <c>inet</c>
- directly.</p>
+ directly. For DTLS this feature must be considered exprimental.</p>
<taglist>
<tag><c>CallbackModule =</c></tag>
<item><p><c>atom()</c></p></item>
@@ -135,18 +141,26 @@
<tag><c>sslsocket() =</c></tag>
<item><p>opaque()</p></item>
-
- <tag><marker id="type-protocol"/><c>protocol() =</c></tag>
+
+ <tag><marker id="type-protocol"/><c> protocol_version() =</c></tag>
+ <item><p><c> ssl_tls_protocol() | dtls_protocol() </c></p></item>
+
<item><p><c>sslv3 | tlsv1 | 'tlsv1.1' | 'tlsv1.2'</c></p></item>
+ <tag><marker id="type-protocol"/><c> dtls_protocol() =</c></tag>
+ <item><p><c>'dtlsv1' | 'dtlsv1.2'</c></p></item>
+
<tag><c>ciphers() =</c></tag>
- <item><p><c>= [ciphersuite()] | string()</c></p>
- <p>According to old API.</p></item>
+ <item><p><c>= [ciphersuite()]</c></p>
+ <p>Tuples and string formats accepted by versions
+ before ssl-8.2.4 will be converted for backwards compatibility</p></item>
<tag><c>ciphersuite() =</c></tag>
-
- <item><p><c>{key_exchange(), cipher(), MAC::hash()} |
- {key_exchange(), cipher(), MAC::hash(), PRF::hash()}</c></p></item>
+ <item><p><c>
+ #{key_exchange := key_exchange(),
+ cipher := cipher(),
+ mac := MAC::hash() | aead,
+ prf := PRF::hash() | default_prf} </c></p></item>
<tag><c>key_exchange()=</c></tag>
<item><p><c>rsa | dhe_dss | dhe_rsa | dh_anon | psk | dhe_psk
@@ -163,6 +177,12 @@
<tag><c>prf_random() =</c></tag>
<item><p><c>client_random | server_random</c></p></item>
+ <tag><c>cipher_filters() =</c></tag>
+ <item><p><c> [{key_exchange | cipher | mac | prf, algo_filter()}])</c></p></item>
+
+ <tag><c>algo_filter() =</c></tag>
+ <item><p>fun(key_exchange() | cipher() | hash() | aead | default_prf) -> true | false </p></item>
+
<tag><c>srp_param_type() =</c></tag>
<item><p><c>srp_1024 | srp_1536 | srp_2048 | srp_3072
| srp_4096 | srp_6144 | srp_8192</c></p></item>
@@ -178,11 +198,23 @@
| sect193r1 | sect193r2 | secp192k1 | secp192r1 | sect163k1
| sect163r1 | sect163r2 | secp160k1 | secp160r1 | secp160r2</c></p></item>
+ <tag><c>hello_extensions() =</c></tag>
+ <item><p><c>#{renegotiation_info => binary() | undefined,
+ signature_algs => [{hash(), ecsda| rsa| dsa}] | undefined
+ alpn => binary() | undefined,
+ next_protocol_negotiation => binary() | undefined,
+ srp => string() | undefined,
+ ec_point_formats => list() | undefined,
+ elliptic_curves => [oid] | undefined,
+ sni => string() | undefined}
+ }</c></p></item>
+
+
</taglist>
</section>
<section>
- <title>SSL OPTION DESCRIPTIONS - COMMON for SERVER and CLIENT</title>
+ <title>TLS/DTLS OPTION DESCRIPTIONS - COMMON for SERVER and CLIENT</title>
<p>The following options have the same meaning in the client and
the server:</p>
@@ -192,8 +224,16 @@
<tag><c>{protocol, tls | dtls}</c></tag>
<item><p>Choose TLS or DTLS protocol for the transport layer security.
Defaults to <c>tls</c> Introduced in OTP 20, DTLS support is considered
- experimental in this release. DTLS over other transports than UDP are not yet supported.</p></item>
-
+ experimental in this release. Other transports than UDP are not yet supported.</p></item>
+
+ <tag><c>{handshake, hello | full}</c></tag>
+ <item><p> Defaults to <c>full</c>. If hello is specified the handshake will
+ pause after the hello message and give the user a possibility make decisions
+ based on hello extensions before continuing or aborting the handshake by calling
+ <seealso marker="#handshake_continue-3"> handshake_continue/3</seealso> or
+ <seealso marker="#handshake_cancel-1"> handshake_cancel/1</seealso>
+ </p></item>
+
<tag><c>{cert, public_key:der_encoded()}</c></tag>
<item><p>The DER-encoded users certificate. If this option
is supplied, it overrides option <c>certfile</c>.</p></item>
@@ -201,9 +241,15 @@
<tag><c>{certfile, path()}</c></tag>
<item><p>Path to a file containing the user certificate.</p></item>
- <tag><c>{key, {'RSAPrivateKey'| 'DSAPrivateKey' | 'ECPrivateKey'
- |'PrivateKeyInfo', public_key:der_encoded()}}</c></tag>
- <item><p>The DER-encoded user's private key. If this option
+ <tag>
+ <marker id="key_option_def"/>
+ <c>{key, {'RSAPrivateKey'| 'DSAPrivateKey' | 'ECPrivateKey'
+ |'PrivateKeyInfo', public_key:der_encoded()} | #{algorithm := rsa | dss | ecdsa,
+ engine := crypto:engine_ref(), key_id := crypto:key_id(), password => crypto:password()}</c></tag>
+ <item><p>The DER-encoded user's private key or a map refering to a crypto
+ engine and its key reference that optionally can be password protected,
+ seealso <seealso marker="crypto:crypto#engine_load-4"> crypto:engine_load/4
+ </seealso> and <seealso marker="crypto:engine_load"> Crypto's Users Guide</seealso>. If this option
is supplied, it overrides option <c>keyfile</c>.</p></item>
<tag><c>{keyfile, path()}</c></tag>
@@ -239,8 +285,9 @@
<item><p>Specifies if to reject renegotiation attempt that does
not live up to
<url href="http://www.ietf.org/rfc/rfc5746.txt">RFC 5746</url>.
- By default <c>secure_renegotiate</c> is set to <c>false</c>,
- that is, secure renegotiation is used if possible,
+ By default <c>secure_renegotiate</c> is set to <c>true</c>,
+ that is, secure renegotiation is enforced. If set to <c>false</c> secure renegotiation
+ will still be used if possible,
but it falls back to insecure renegotiation if the peer
does not support
<url href="http://www.ietf.org/rfc/rfc5746.txt">RFC 5746</url>.</p>
@@ -281,11 +328,11 @@ atom()}} |
<list type="bulleted">
<item><p>If the verify callback fun returns <c>{fail, Reason}</c>,
the verification process is immediately stopped, an alert is
- sent to the peer, and the TLS/SSL handshake terminates.</p></item>
+ sent to the peer, and the TLS/DTLS handshake terminates.</p></item>
<item><p>If the verify callback fun returns <c>{valid, UserState}</c>,
the verification process continues.</p></item>
<item><p>If the verify callback fun always returns
- <c>{valid, UserState}</c>, the TLS/SSL handshake does not
+ <c>{valid, UserState}</c>, the TLS/DTLS handshake does not
terminate regarding verification failures and the connection is
established.</p></item>
<item><p>If called with an extension unknown to the user application,
@@ -448,15 +495,16 @@ marker="public_key:public_key#pkix_path_validation-3">public_key:pkix_path_valid
marker="public_key:public_key#pkix_path_validation-3">public_key:pkix_path_validation/3</seealso>
with the selected CA as trusted anchor and the rest of the chain.</p></item>
- <tag><c>{versions, [protocol()]}</c></tag>
+ <tag><c>{versions, [protocol_version()]}</c></tag>
+
<item><p>TLS protocol versions supported by started clients and servers.
This option overrides the application environment option
- <c>protocol_version</c>. If the environment option is not set, it defaults
+ <c>protocol_version</c> and <c>dtls_protocol_version</c>. If the environment option is not set, it defaults
to all versions, except SSL-3.0, supported by the SSL application.
See also <seealso marker="ssl:ssl_app">ssl(6).</seealso></p></item>
<tag><c>{hibernate_after, integer()|undefined}</c></tag>
- <item><p>When an integer-value is specified, <c>ssl_connection</c>
+ <item><p>When an integer-value is specified, <c>TLS/DTLS-connection</c>
goes into hibernation after the specified number of milliseconds
of inactivity, thus reducing its memory footprint. When
<c>undefined</c> is specified (this is the default), the process
@@ -516,7 +564,7 @@ fun(srp, Username :: string(), UserState :: term()) ->
</section>
<section>
- <title>SSL OPTION DESCRIPTIONS - CLIENT SIDE</title>
+ <title>TLS/DTLS OPTION DESCRIPTIONS - CLIENT SIDE</title>
<p>The following options are client-specific or have a slightly different
meaning in the client than in the server:</p>
@@ -589,22 +637,27 @@ fun(srp, Username :: string(), UserState :: term()) ->
<tag><c>{server_name_indication, HostName :: hostname()}</c></tag>
<item><p>Specify the hostname to be used in TLS Server Name Indication extension.
- Is usefull when upgrading a TCP socket to a TLS socket or if the hostname can not be
- derived from the Host argument to <seealso marker="ssl#connect-3">ssl:connect/3</seealso>.
- Will also cause the client to preform host name verification of the peer certificate
- <seealso marker="public_key:public_key#pkix_verify_hostname-2">public_key:pkix_verify_hostname(PeerCert, [{dns_id, HostName}])</seealso>
- </p> during the x509-path validation. If the check fails the error {bad_cert, hostname_check_failiure} will be
- propagated to the path validation fun <seealso marker="#verify_fun">verify_fun</seealso>
+ If not specified it will default to the <c>Host</c> argument of <seealso marker="#connect-3">connect/[3,4]</seealso>
+ unless it is of type inet:ipaddress().</p>
+ <p>
+ The <c>HostName</c> will also be used in the hostname verification of the peer certificate using
+ <seealso marker="public_key:public_key#pkix_verify_hostname-2">public_key:pkix_verify_hostname/2</seealso>.
+ </p>
</item>
+ <tag><c>{server_name_indication, disable}</c></tag>
+ <item>
+ <p> Prevents the Server Name Indication extension from being sent and
+ disables the hostname verification check
+ <seealso marker="public_key:public_key#pkix_verify_hostname-2">public_key:pkix_verify_hostname/2</seealso> </p>
+ </item>
+
+ <tag><c>{customize_hostname_check, Options::list()}</c></tag>
+ <item>
+ <p> Customizes the hostname verification of the peer certificate, as different protocols that use
+ TLS such as HTTP or LDAP may want to do it differently, for possible options see
+ <seealso marker="public_key:public_key#pkix_verify_hostname-3">public_key:pkix_verify_hostname/3</seealso> </p>
+ </item>
- <tag><c>{server_name_indication, disable}</c></tag>
- <item>
- <p>When starting a TLS connection without upgrade, the Server Name
- Indication extension is sent if possible that is can be derived from the Host argument
- to <seealso marker="ssl#connect-3">ssl:connect/3</seealso>.
- This option can be used to disable that behavior.</p>
- <note><p> Note that this also disables the default host name verification check of the peer certificate.</p></note>
- </item>
<tag><c>{fallback, boolean()}</c></tag>
<item>
<p> Send special cipher suite TLS_FALLBACK_SCSV to avoid undesired TLS version downgrade.
@@ -659,7 +712,7 @@ fun(srp, Username :: string(), UserState :: term()) ->
</section>
<section>
- <title>SSL OPTION DESCRIPTIONS - SERVER SIDE</title>
+ <title>TLS/DTLS OPTION DESCRIPTIONS - SERVER SIDE</title>
<p>The following options are server-specific or have a slightly different
meaning in the server than in the client:</p>
@@ -697,7 +750,7 @@ fun(srp, Username :: string(), UserState :: term()) ->
</p></item>
<tag><c>{fail_if_no_peer_cert, boolean()}</c></tag>
- <item><p>Used together with <c>{verify, verify_peer}</c> by an SSL server.
+ <item><p>Used together with <c>{verify, verify_peer}</c> by an TLS/DTLS server.
If set to <c>true</c>, the server fails if the client does not have
a certificate to send, that is, sends an empty certificate. If set to
<c>false</c>, it fails only if the client sends an invalid
@@ -711,7 +764,7 @@ fun(srp, Username :: string(), UserState :: term()) ->
<tag><c>{reuse_session, fun(SuggestedSessionId,
PeerCert, Compression, CipherSuite) -> boolean()}</c></tag>
- <item><p>Enables the SSL server to have a local policy
+ <item><p>Enables the TLS/DTLS server to have a local policy
for deciding if a session is to be reused or not.
Meaningful only if <c>reuse_sessions</c> is set to <c>true</c>.
<c>SuggestedSessionId</c> is a <c>binary()</c>, <c>PeerCert</c> is
@@ -797,19 +850,13 @@ fun(srp, Username :: string(), UserState :: term()) ->
client certificate is requested. For more details see the <seealso marker="#client_signature_algs">corresponding client option</seealso>.
</p> </item>
- <tag><c>{v2_hello_compatible, boolean()}</c></tag>
- <item>If true, the server accepts clients that send hello messages on SSL-2.0 format but offers
- supported SSL/TLS versions. Defaults to false, that is the server will not interoperate with clients that
- offers SSL-2.0.
- </item>
-
</taglist>
</section>
<section>
<title>General</title>
- <p>When an SSL socket is in active mode (the default), data from the
+ <p>When an TLS/DTLS socket is in active mode (the default), data from the
socket is delivered to the owner of the socket in the form of
messages:</p>
@@ -824,27 +871,52 @@ fun(srp, Username :: string(), UserState :: term()) ->
</section>
<funcs>
+
+ <func>
+ <name>append_cipher_suites(Deferred, Suites) -> ciphers() </name>
+ <fsummary></fsummary>
+ <type>
+ <v>Deferred = ciphers() | cipher_filters() </v>
+ <v>Suites = ciphers() </v>
+ </type>
+ <desc><p>Make <c>Deferred</c> suites become the least preferred
+ suites, that is put them at the end of the cipher suite list
+ <c>Suites</c> after removing them from <c>Suites</c> if
+ present. <c>Deferred</c> may be a list of cipher suits or a
+ list of filters in which case the filters are use on <c>Suites</c> to
+ extract the Deferred cipher list.</p>
+ </desc>
+ </func>
+
<func>
<name>cipher_suites() -></name>
- <name>cipher_suites(Type) -> ciphers()</name>
+ <name>cipher_suites(Type) -> old_ciphers()</name>
<fsummary>Returns a list of supported cipher suites.</fsummary>
<type>
<v>Type = erlang | openssl | all</v>
</type>
- <desc><p>Returns a list of supported cipher suites.
- <c>cipher_suites()</c> is equivalent to <c>cipher_suites(erlang).</c>
- Type <c>openssl</c> is provided for backwards compatibility with the
- old SSL, which used OpenSSL. <c>cipher_suites(all)</c> returns
- all available cipher suites. The cipher suites not present
- in <c>cipher_suites(erlang)</c> but included in
- <c>cipher_suites(all)</c> are not used unless explicitly configured
- by the user.</p>
+ <desc>
+ <p>Deprecated in OTP 21, use <seealso marker="#cipher_suites-2">cipher_suites/2</seealso> instead.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>cipher_suites(Supported, Version) -> ciphers()</name>
+ <fsummary>Returns a list of all default or
+ all supported cipher suites.</fsummary>
+ <type>
+ <v> Supported = default | all | anonymous </v>
+ <v> Version = protocol_version() </v>
+ </type>
+ <desc><p>Returns all default or all supported (except anonymous),
+ or all anonymous cipher suites for a
+ TLS version</p>
</desc>
</func>
<func>
<name>eccs() -></name>
- <name>eccs(protocol()) -> [named_curve()]</name>
+ <name>eccs(protocol_version()) -> [named_curve()]</name>
<fsummary>Returns a list of supported ECCs.</fsummary>
<desc><p>Returns a list of supported ECCs. <c>eccs()</c>
@@ -852,7 +924,7 @@ fun(srp, Username :: string(), UserState :: term()) ->
supported protocols and then deduplicating the output.</p>
</desc>
</func>
-
+
<func>
<name>clear_pem_cache() -> ok </name>
<fsummary> Clears the pem cache</fsummary>
@@ -867,28 +939,46 @@ fun(srp, Username :: string(), UserState :: term()) ->
<func>
<name>connect(Socket, SslOptions) -> </name>
- <name>connect(Socket, SslOptions, Timeout) -> {ok, SslSocket}
+ <name>connect(Socket, SslOptions, Timeout) -> {ok, SslSocket} | {ok, SslSocket, Ext}
| {error, Reason}</name>
<fsummary>Upgrades a <c>gen_tcp</c>, or
- equivalent, connected socket to an SSL socket.</fsummary>
+ equivalent, connected socket to an TLS socket.</fsummary>
<type>
<v>Socket = socket()</v>
- <v>SslOptions = [ssl_option()]</v>
+ <v>SslOptions = [{handshake, hello| full} | ssl_option()]</v>
<v>Timeout = integer() | infinity</v>
<v>SslSocket = sslsocket()</v>
+ <v>Ext = hello_extensions()</v>
<v>Reason = term()</v>
</type>
<desc><p>Upgrades a <c>gen_tcp</c>, or equivalent,
- connected socket to an SSL socket, that is, performs the
- client-side ssl handshake.</p>
+ connected socket to an TLS socket, that is, performs the
+ client-side TLS handshake.</p>
+
+ <note><p>If the option <c>verify</c> is set to <c>verify_peer</c>
+ the option <c>server_name_indication</c> shall also be specified,
+ if it is not no Server Name Indication extension will be sent,
+ and <seealso marker="public_key:public_key#pkix_verify_hostname-2">public_key:pkix_verify_hostname/2</seealso>
+ will be called with the IP-address of the connection as <c>ReferenceID</c>, which is proably not what you want.</p>
+ </note>
+
+ <p> If the option <c>{handshake, hello}</c> is used the
+ handshake is paused after receiving the server hello message
+ and the success response is <c>{ok, SslSocket, Ext}</c>
+ instead of <c>{ok, SslSocket}</c>. Thereafter the handshake is continued or
+ canceled by calling <seealso marker="#handshake_continue-3">
+ <c>handshake_continue/3</c></seealso> or <seealso
+ marker="#handshake_cancel-1"><c>handshake_cancel/1</c></seealso>.
+ </p>
+
</desc>
</func>
<func>
<name>connect(Host, Port, Options) -></name>
<name>connect(Host, Port, Options, Timeout) ->
- {ok, SslSocket} | {error, Reason}</name>
- <fsummary>Opens an SSL connection to <c>Host</c>, <c>Port</c>.</fsummary>
+ {ok, SslSocket}| {ok, SslSocket, Ext} | {error, Reason}</name>
+ <fsummary>Opens an TLS/DTLS connection to <c>Host</c>, <c>Port</c>.</fsummary>
<type>
<v>Host = host()</v>
<v>Port = integer()</v>
@@ -897,29 +987,56 @@ fun(srp, Username :: string(), UserState :: term()) ->
<v>SslSocket = sslsocket()</v>
<v>Reason = term()</v>
</type>
- <desc><p>Opens an SSL connection to <c>Host</c>, <c>Port</c>.</p></desc>
+ <desc><p>Opens an TLS/DTLS connection to <c>Host</c>, <c>Port</c>.</p>
+
+ <p> When the option <c>verify</c> is set to <c>verify_peer</c> the check
+ <seealso marker="public_key:public_key#pkix_verify_hostname-2">public_key:pkix_verify_hostname/2</seealso>
+ will be performed in addition to the usual x509-path validation checks. If the check fails the error {bad_cert, hostname_check_failed} will
+ be propagated to the path validation fun <seealso marker="#verify_fun">verify_fun</seealso>, where it is possible to do customized
+ checks by using the full possibilities of the <seealso marker="public_key:public_key#pkix_verify_hostname-3">public_key:pkix_verify_hostname/3</seealso> API.
+
+ When the option <c>server_name_indication</c> is provided, its value (the DNS name) will be used as <c>ReferenceID</c>
+ to <seealso marker="public_key:public_key#pkix_verify_hostname-2">public_key:pkix_verify_hostname/2</seealso>.
+ When no <c>server_name_indication</c> option is given, the <c>Host</c> argument will be used as
+ Server Name Indication extension. The <c>Host</c> argument will also be used for the
+ <seealso marker="public_key:public_key#pkix_verify_hostname-2">public_key:pkix_verify_hostname/2</seealso> check and if the <c>Host</c>
+ argument is an <c>inet:ip_address()</c> the <c>ReferenceID</c> used for the check will be <c>{ip, Host}</c> otherwise
+ <c>dns_id</c> will be assumed with a fallback to <c>ip</c> if that fails. </p>
+ <note><p>According to good practices certificates should not use IP-addresses as "server names". It would
+ be very surprising if this happen outside a closed network. </p></note>
+
+
+ <p> If the option <c>{handshake, hello}</c> is used the
+ handshake is paused after receiving the server hello message
+ and the success response is <c>{ok, SslSocket, Ext}</c>
+ instead of <c>{ok, SslSocket}</c>. Thereafter the handshake is continued or
+ canceled by calling <seealso marker="#handshake_continue-3">
+ <c>handshake_continue/3</c></seealso> or <seealso
+ marker="#handshake_cancel-1"><c>handshake_cancel/1</c></seealso>.
+ </p>
+ </desc>
</func>
<func>
<name>close(SslSocket) -> ok | {error, Reason}</name>
- <fsummary>Closes an SSL connection.</fsummary>
+ <fsummary>Closes an TLS/DTLS connection.</fsummary>
<type>
<v>SslSocket = sslsocket()</v>
<v>Reason = term()</v>
</type>
- <desc><p>Closes an SSL connection.</p>
+ <desc><p>Closes an TLS/DTLS connection.</p>
</desc>
</func>
<func>
<name>close(SslSocket, How) -> ok | {ok, port()} | {error, Reason}</name>
- <fsummary>Closes an SSL connection.</fsummary>
+ <fsummary>Closes an TLS connection.</fsummary>
<type>
<v>SslSocket = sslsocket()</v>
<v>How = timeout() | {NewController::pid(), timeout()} </v>
<v>Reason = term()</v>
</type>
- <desc><p>Closes or downgrades an SSL connection. In the latter case the transport
+ <desc><p>Closes or downgrades an TLS connection. In the latter case the transport
connection will be handed over to the <c>NewController</c> process after receiving
the TLS close alert from the peer. The returned transport socket will have
the following options set: <c>[{active, false}, {packet, 0}, {mode, binary}]</c></p>
@@ -930,7 +1047,7 @@ fun(srp, Username :: string(), UserState :: term()) ->
<name>controlling_process(SslSocket, NewOwner) ->
ok | {error, Reason}</name>
<fsummary>Assigns a new controlling process to the
- SSL socket.</fsummary>
+ TLS/DTLS socket.</fsummary>
<type>
<v>SslSocket = sslsocket()</v>
<v>NewOwner = pid()</v>
@@ -948,7 +1065,8 @@ fun(srp, Username :: string(), UserState :: term()) ->
<fsummary>Returns all the connection information.
</fsummary>
<type>
- <v>Item = protocol | cipher_suite | sni_hostname | ecc | session_id | atom()</v>
+ <v>SslSocket = sslsocket()</v>
+ <v>Item = protocol | selected_cipher_suite | sni_hostname | ecc | session_id | atom()</v>
<d>Meaningful atoms, not specified above, are the ssl option names.</d>
<v>Result = [{Item::atom(), Value::term()}]</v>
<v>Reason = term()</v>
@@ -956,6 +1074,9 @@ fun(srp, Username :: string(), UserState :: term()) ->
<desc><p>Returns the most relevant information about the connection, ssl options that
are undefined will be filtered out. Note that values that affect the security of the
connection will only be returned if explicitly requested by connection_information/2.</p>
+ <note><p>The legacy <c>Item = cipher_suite</c> is still supported
+ and returns the cipher suite on its (undocumented) legacy format.
+ It should be replaced by <c>selected_cipher_suite</c>.</p></note>
</desc>
</func>
@@ -965,6 +1086,7 @@ fun(srp, Username :: string(), UserState :: term()) ->
<fsummary>Returns the requested connection information.
</fsummary>
<type>
+ <v>SslSocket = sslsocket()</v>
<v>Items = [Item]</v>
<v>Item = protocol | cipher_suite | sni_hostname | ecc | session_id | client_random
| server_random | master_secret | atom()</v>
@@ -980,6 +1102,21 @@ fun(srp, Username :: string(), UserState :: term()) ->
</desc>
</func>
+ <func>
+ <name>filter_cipher_suites(Suites, Filters) -> ciphers()</name>
+ <fsummary></fsummary>
+ <type>
+ <v> Suites = ciphers()</v>
+ <v> Filters = cipher_filters()</v>
+ </type>
+ <desc><p>Removes cipher suites if any of the filter functions
+ returns false for any part of the cipher suite. This function
+ also calls default filter functions to make sure the cipher
+ suites are supported by crypto. If no filter function is supplied for some
+ part the default behaviour is fun(Algorithm) -> true.</p>
+ </desc>
+ </func>
+
<func>
<name>format_error(Reason) -> string()</name>
<fsummary>Returns an error string.</fsummary>
@@ -992,7 +1129,7 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>getopts(Socket, OptionNames) ->
+ <name>getopts(SslSocket, OptionNames) ->
{ok, [socketoption()]} | {error, Reason}</name>
<fsummary>Gets the values of the specified options.</fsummary>
<type>
@@ -1006,13 +1143,13 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>getstat(Socket) ->
+ <name>getstat(SslSocket) ->
{ok, OptionValues} | {error, inet:posix()}</name>
- <name>getstat(Socket, OptionNames) ->
+ <name>getstat(SslSocket, OptionNames) ->
{ok, OptionValues} | {error, inet:posix()}</name>
<fsummary>Get one or more statistic options for a socket</fsummary>
<type>
- <v>Socket = sslsocket()</v>
+ <v>SslSocket = sslsocket()</v>
<v>OptionNames = [atom()]</v>
<v>OptionValues = [{inet:stat_option(), integer()}]</v>
</type>
@@ -1023,6 +1160,86 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
+ <name>handshake(HsSocket) -> </name>
+ <name>handshake(HsSocket, Timeout) -> {ok, SslSocket} | {error, Reason}</name>
+ <fsummary>Performs server-side SSL/TLS handshake.</fsummary>
+ <type>
+ <v>HsSocket = SslSocket = sslsocket()</v>
+ <v>Timeout = integer()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Performs the SSL/TLS/DTLS server-side handshake.</p>
+ <p>Returns a new TLS/DTLS socket if the handshake is successful.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>handshake(Socket, SslOptions) -> </name>
+ <name>handshake(Socket, SslOptions, Timeout) -> {ok, SslSocket} | {ok, SslSocket, Ext} | {error, Reason}</name>
+ <fsummary>Performs server-side SSL/TLS/DTLS handshake.</fsummary>
+ <type>
+ <v>Socket = socket() | sslsocket() </v>
+ <v>SslSocket = sslsocket() </v>
+ <v>Ext = hello_extensions()</v>
+ <v>SslOptions = [{handshake, hello| full} | ssl_option()]</v>
+ <v>Timeout = integer()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>If <c>Socket</c> is a ordinary <c>socket()</c>: upgrades a <c>gen_tcp</c>,
+ or equivalent, socket to an SSL socket, that is, performs
+ the SSL/TLS server-side handshake and returns a TLS socket.</p>
+
+ <warning><p>The <c>Socket</c> shall be in passive mode ({active,
+ false}) before calling this function or else the behavior of this function
+ is undefined.
+ </p></warning>
+
+ <p>If <c>Socket</c> is an <c>sslsocket()</c>: provides extra SSL/TLS/DTLS
+ options to those specified in
+ <seealso marker="#listen-2">listen/2 </seealso> and then performs
+ the SSL/TLS/DTLS handshake. Returns a new TLS/DTLS socket if the handshake is successful.</p>
+
+ <p>
+ If option <c>{handshake, hello}</c> is specified the handshake is
+ paused after receiving the client hello message and the
+ success response is <c>{ok, SslSocket, Ext}</c> instead of <c>{ok,
+ SslSocket}</c>. Thereafter the handshake is continued or
+ canceled by calling <seealso marker="#handshake_continue-3">
+ <c>handshake_continue/3</c></seealso> or <seealso
+ marker="#handshake_cancel-1"><c>handshake_cancel/1</c></seealso>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>handshake_cancel(SslSocket) -> ok </name>
+ <fsummary>Cancel handshake with a fatal alert</fsummary>
+ <type>
+ <v>SslSocket = sslsocket()</v>
+ </type>
+ <desc>
+ <p>Cancel the handshake with a fatal <c>USER_CANCELED</c> alert.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>handshake_continue(HsSocket, SSLOptions) -> {ok, SslSocket} | {error, Reason}</name>
+ <name>handshake_continue(HsSocket, SSLOptions, Timeout) -> {ok, SslSocket} | {error, Reason}</name>
+ <fsummary>Continue the SSL/TLS handshake.</fsummary>
+ <type>
+ <v>HsSocket = SslSocket = sslsocket()</v>
+ <v>SslOptions = [ssl_option()]</v>
+ <v>Timeout = integer()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Continue the SSL/TLS handshake possiby with new, additional or changed options.</p>
+ </desc>
+ </func>
+
+ <func>
<name>listen(Port, Options) ->
{ok, ListenSocket} | {error, Reason}</name>
<fsummary>Creates an SSL listen socket.</fsummary>
@@ -1037,10 +1254,10 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>negotiated_protocol(Socket) -> {ok, Protocol} | {error, protocol_not_negotiated}</name>
+ <name>negotiated_protocol(SslSocket) -> {ok, Protocol} | {error, protocol_not_negotiated}</name>
<fsummary>Returns the protocol negotiated through ALPN or NPN extensions.</fsummary>
<type>
- <v>Socket = sslsocket()</v>
+ <v>SslSocket = sslsocket()</v>
<v>Protocol = binary()</v>
</type>
<desc>
@@ -1051,25 +1268,26 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>peercert(Socket) -> {ok, Cert} | {error, Reason}</name>
+ <name>peercert(SslSocket) -> {ok, Cert} | {error, Reason}</name>
<fsummary>Returns the peer certificate.</fsummary>
<type>
- <v>Socket = sslsocket()</v>
+ <v>SslSocket = sslsocket()</v>
<v>Cert = binary()</v>
</type>
<desc>
<p>The peer certificate is returned as a DER-encoded binary.
The certificate can be decoded with
- <c>public_key:pkix_decode_cert/2</c>.</p>
+ <seealso marker="public_key:public_key#pkix_decode_cert-2">public_key:pkix_decode_cert/2</seealso>
+ </p>
</desc>
</func>
<func>
- <name>peername(Socket) -> {ok, {Address, Port}} |
+ <name>peername(SslSocket) -> {ok, {Address, Port}} |
{error, Reason}</name>
<fsummary>Returns the peer address and port.</fsummary>
<type>
- <v>Socket = sslsocket()</v>
+ <v>SslSocket = sslsocket()</v>
<v>Address = ipaddress()</v>
<v>Port = integer()</v>
</type>
@@ -1077,6 +1295,22 @@ fun(srp, Username :: string(), UserState :: term()) ->
<p>Returns the address and port number of the peer.</p>
</desc>
</func>
+
+ <func>
+ <name>prepend_cipher_suites(Preferred, Suites) -> ciphers()</name>
+ <fsummary></fsummary>
+ <type>
+ <v>Preferred = ciphers() | cipher_filters() </v>
+ <v>Suites = ciphers() </v>
+ </type>
+ <desc><p>Make <c>Preferred</c> suites become the most preferred
+ suites that is put them at the head of the cipher suite list
+ <c>Suites</c> after removing them from <c>Suites</c> if
+ present. <c>Preferred</c> may be a list of cipher suits or a
+ list of filters in which case the filters are use on <c>Suites</c> to
+ extract the preferred cipher list. </p>
+ </desc>
+ </func>
<func>
<name>prf(Socket, Secret, Label, Seed, WantedLength) -> {ok, binary()} | {error, reason()}</name>
@@ -1093,18 +1327,18 @@ fun(srp, Username :: string(), UserState :: term()) ->
extra key material. It either takes user-generated values for
<c>Secret</c> and <c>Seed</c> or atoms directing it to use a specific
value from the session security parameters.</p>
- <p>Can only be used with TLS connections; <c>{error, undefined}</c>
+ <p>Can only be used with TLS/DTLS connections; <c>{error, undefined}</c>
is returned for SSLv3 connections.</p>
</desc>
</func>
<func>
- <name>recv(Socket, Length) -> </name>
- <name>recv(Socket, Length, Timeout) -> {ok, Data} | {error,
+ <name>recv(SslSocket, Length) -> </name>
+ <name>recv(SslSocket, Length, Timeout) -> {ok, Data} | {error,
Reason}</name>
<fsummary>Receives data on a socket.</fsummary>
<type>
- <v>Socket = sslsocket()</v>
+ <v>SslSocket = sslsocket()</v>
<v>Length = integer()</v>
<v>Timeout = integer()</v>
<v>Data = [char()] | binary()</v>
@@ -1126,10 +1360,10 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>renegotiate(Socket) -> ok | {error, Reason}</name>
+ <name>renegotiate(SslSocket) -> ok | {error, Reason}</name>
<fsummary>Initiates a new handshake.</fsummary>
<type>
- <v>Socket = sslsocket()</v>
+ <v>SslSocket = sslsocket()</v>
</type>
<desc><p>Initiates a new handshake. A notable return value is
<c>{error, renegotiation_rejected}</c> indicating that the peer
@@ -1139,10 +1373,10 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>send(Socket, Data) -> ok | {error, Reason}</name>
+ <name>send(SslSocket, Data) -> ok | {error, Reason}</name>
<fsummary>Writes data to a socket.</fsummary>
<type>
- <v>Socket = sslsocket()</v>
+ <v>SslSocket = sslsocket()</v>
<v>Data = iodata()</v>
</type>
<desc>
@@ -1153,10 +1387,10 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>setopts(Socket, Options) -> ok | {error, Reason}</name>
+ <name>setopts(SslSocket, Options) -> ok | {error, Reason}</name>
<fsummary>Sets socket options.</fsummary>
<type>
- <v>Socket = sslsocket()</v>
+ <v>SslSocket = sslsocket()</v>
<v>Options = [socketoption]()</v>
</type>
<desc>
@@ -1166,10 +1400,10 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>shutdown(Socket, How) -> ok | {error, Reason}</name>
+ <name>shutdown(SslSocket, How) -> ok | {error, Reason}</name>
<fsummary>Immediately closes a socket.</fsummary>
<type>
- <v>Socket = sslsocket()</v>
+ <v>SslSocket = sslsocket()</v>
<v>How = read | write | read_write</v>
<v>Reason = reason()</v>
</type>
@@ -1184,26 +1418,24 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
- <name>ssl_accept(Socket) -> </name>
- <name>ssl_accept(Socket, Timeout) -> ok | {error, Reason}</name>
+ <name>ssl_accept(SslSocket) -> </name>
+ <name>ssl_accept(SslSocket, Timeout) -> ok | {error, Reason}</name>
<fsummary>Performs server-side SSL/TLS handshake.</fsummary>
<type>
- <v>Socket = sslsocket()</v>
+ <v>SslSocket = sslsocket()</v>
<v>Timeout = integer()</v>
<v>Reason = term()</v>
</type>
<desc>
- <p>Performs the SSL/TLS server-side handshake.</p>
- <p><c>Socket</c> is a socket as returned by
- <seealso marker="#transport_accept-2">ssl:transport_accept/[1,2]</seealso>
- </p>
+ <p>Deprecated in OTP 21, use <seealso marker="#handshake-1">handshake/[1,2]</seealso> instead.</p>
+ <note><p>handshake/[1,2] always returns a new socket.</p></note>
</desc>
</func>
<func>
<name>ssl_accept(Socket, SslOptions) -> </name>
<name>ssl_accept(Socket, SslOptions, Timeout) -> {ok, Socket} | ok | {error, Reason}</name>
- <fsummary>Performs server-side SSL/TLS handshake.</fsummary>
+ <fsummary>Performs server-side SSL/TLS/DTLS handshake.</fsummary>
<type>
<v>Socket = socket() | sslsocket() </v>
<v>SslOptions = [ssl_option()]</v>
@@ -1211,29 +1443,17 @@ fun(srp, Username :: string(), UserState :: term()) ->
<v>Reason = term()</v>
</type>
<desc>
- <p>If <c>Socket</c> is a <c>socket()</c>: upgrades a <c>gen_tcp</c>,
- or equivalent, socket to an SSL socket, that is, performs
- the SSL/TLS server-side handshake and returns the SSL socket.</p>
-
- <warning><p>The listen socket is to be in mode <c>{active, false}</c>
- before telling the client that the server is ready to upgrade
- by calling this function, else the upgrade succeeds or does not
- succeed depending on timing.</p></warning>
-
- <p>If <c>Socket</c> is an <c>sslsocket()</c>: provides extra SSL/TLS
- options to those specified in
- <seealso marker="#listen-2">ssl:listen/2 </seealso> and then performs
- the SSL/TLS handshake.
- </p>
+ <p>Deprecated in OTP 21, use <seealso marker="#handshake-3">handshake/[2,3]</seealso> instead.</p>
+ <note><p>handshake/[2,3] always returns a new socket.</p></note>
</desc>
</func>
<func>
- <name>sockname(Socket) -> {ok, {Address, Port}} |
+ <name>sockname(SslSocket) -> {ok, {Address, Port}} |
{error, Reason}</name>
<fsummary>Returns the local address and port.</fsummary>
<type>
- <v>Socket = sslsocket()</v>
+ <v>SslSocket = sslsocket()</v>
<v>Address = ipaddress()</v>
<v>Port = integer()</v>
</type>
@@ -1265,32 +1485,44 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
+ <name>suite_to_str(CipherSuite) -> String</name>
+ <fsummary>Returns the string representation of a cipher suite.</fsummary>
+ <type>
+ <v>CipherSuite = erl_cipher_suite()</v>
+ <v>String = string()</v>
+ </type>
+ <desc>
+ <p>Returns the string representation of a cipher suite.</p>
+ </desc>
+ </func>
+
+ <func>
<name>transport_accept(ListenSocket) -></name>
<name>transport_accept(ListenSocket, Timeout) ->
- {ok, NewSocket} | {error, Reason}</name>
+ {ok, SslSocket} | {error, Reason}</name>
<fsummary>Accepts an incoming connection and
prepares for <c>ssl_accept</c>.</fsummary>
<type>
- <v>ListenSocket = NewSocket = sslsocket()</v>
+ <v>ListenSocket = SslSocket = sslsocket()</v>
<v>Timeout = integer()</v>
<v>Reason = reason()</v>
</type>
<desc>
<p>Accepts an incoming connection request on a listen socket.
<c>ListenSocket</c> must be a socket returned from
- <seealso marker="#listen-2"> ssl:listen/2</seealso>.
+ <seealso marker="#listen-2"> listen/2</seealso>.
The socket returned is to be passed to
- <seealso marker="#ssl_accept-2"> ssl:ssl_accept[2,3]</seealso>
+ <seealso marker="#handshake-2"> handshake/[2,3]</seealso>
to complete handshaking, that is,
- establishing the SSL/TLS connection.</p>
+ establishing the SSL/TLS/DTLS connection.</p>
<warning>
- <p>The socket returned can only be used with
- <seealso marker="#ssl_accept-2"> ssl:ssl_accept[2,3]</seealso>.
- No traffic can be sent or received before that call.</p>
+ <p>Most API functions require that the TLS/DTLS
+ connection is established to work as expected.
+ </p>
</warning>
<p>The accepted socket inherits the options set for
<c>ListenSocket</c> in
- <seealso marker="#listen-2"> ssl:listen/2</seealso>.</p>
+ <seealso marker="#listen-2"> listen/2</seealso>.</p>
<p>The default
value for <c>Timeout</c> is <c>infinity</c>. If
<c>Timeout</c> is specified and no connection is accepted
@@ -1304,7 +1536,8 @@ fun(srp, Username :: string(), UserState :: term()) ->
<fsummary>Returns version information relevant for the
SSL application.</fsummary>
<type>
- <v>versions_info() = {app_vsn, string()} | {supported | available, [protocol()] </v>
+ <v>versions_info() = {app_vsn, string()} | {supported | available, [ssl_tls_protocol()]} |
+ {supported_dtls | available_dtls, [dtls_protocol()]} </v>
</type>
<desc>
<p>Returns version information relevant for the SSL
@@ -1314,19 +1547,35 @@ fun(srp, Username :: string(), UserState :: term()) ->
<item>The application version of the SSL application.</item>
<tag><c>supported</c></tag>
- <item>TLS/SSL versions supported by default.
+ <item>SSL/TLS versions supported by default.
Overridden by a version option on
<seealso marker="#connect-2"> connect/[2,3,4]</seealso>,
<seealso marker="#listen-2"> listen/2</seealso>, and <seealso
marker="#ssl_accept-2">ssl_accept/[1,2,3]</seealso>.
- For the negotiated TLS/SSL version, see <seealso
- marker="#connection_information-1">ssl:connection_information/1
+ For the negotiated SSL/TLS version, see <seealso
+ marker="#connection_information-1">connection_information/1
</seealso>.</item>
-
+
+ <tag><c>supported_dtls</c></tag>
+ <item>DTLS versions supported by default.
+ Overridden by a version option on
+ <seealso marker="#connect-2"> connect/[2,3,4]</seealso>,
+ <seealso marker="#listen-2"> listen/2</seealso>, and <seealso
+ marker="#ssl_accept-2">ssl_accept/[1,2,3]</seealso>.
+ For the negotiated DTLS version, see <seealso
+ marker="#connection_information-1">connection_information/1
+ </seealso>.</item>
+
<tag><c>available</c></tag>
- <item>All TLS/SSL versions supported by the SSL application.
+ <item>All SSL/TLS versions supported by the SSL application.
TLS 1.2 requires sufficient support from the Crypto
application.</item>
+
+ <tag><c>available_dtls</c></tag>
+ <item>All DTLS versions supported by the SSL application.
+ DTLS 1.2 requires sufficient support from the Crypto
+ application.</item>
+
</taglist>
</desc>
</func>
@@ -1337,6 +1586,7 @@ fun(srp, Username :: string(), UserState :: term()) ->
<title>SEE ALSO</title>
<p><seealso marker="kernel:inet">inet(3)</seealso> and
<seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso>
+ <seealso marker="kernel:gen_udp">gen_udp(3)</seealso>
</p>
</section>
diff --git a/lib/ssl/doc/src/ssl_app.xml b/lib/ssl/doc/src/ssl_app.xml
index f317dfded4..f6d9021d4a 100644
--- a/lib/ssl/doc/src/ssl_app.xml
+++ b/lib/ssl/doc/src/ssl_app.xml
@@ -4,7 +4,7 @@
<appref>
<header>
<copyright>
- <year>1999</year><year>2016</year>
+ <year>1999</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -35,16 +35,21 @@
<description>
<p>
- The ssl application is an implementation of the SSL/TLS protocol in Erlang.
+ The ssl application is an implementation of the SSL/TLS/DTLS protocol in Erlang.
</p>
<list type="bulleted">
- <item>Supported SSL/TLS-versions are SSL-3.0, TLS-1.0,
- TLS-1.1, and TLS-1.2.</item>
- <item>For security reasons SSL-2.0 is not supported.</item>
+ <item>Supported SSL/TLS/DTLS-versions are SSL-3.0, TLS-1.0,
+ TLS-1.1, TLS-1.2, DTLS-1.0 (based on TLS-1.1), DTLS-1.2 (based on TLS-1.2)</item>
+ <item>For security reasons SSL-2.0 is not supported.
+ Interoperability with SSL-2.0 enabled clients dropped. (OTP 21) </item>
<item>For security reasons SSL-3.0 is no longer supported by default,
- but can be configured.</item>
+ but can be configured. (OTP 19) </item>
+ <item>For security reasons RSA key exchange cipher suites are no longer supported by default,
+ but can be configured. (OTP 21) </item>
<item>For security reasons DES cipher suites are no longer supported by default,
- but can be configured.</item>
+ but can be configured. (OTP 20) </item>
+ <item>For security reasons 3DES cipher suites are no longer supported by default,
+ but can be configured. (OTP 21) </item>
<item> Renegotiation Indication Extension <url href="http://www.ietf.org/rfc/rfc5746.txt">RFC 5746</url> is supported
</item>
<item>Ephemeral Diffie-Hellman cipher suites are supported,
@@ -72,7 +77,7 @@
<section>
<title>DEPENDENCIES</title>
- <p>The SSL application uses the <c>public_key</c> and
+ <p>The SSL application uses the <c>public_key</c>, <c>asn1</c> and
Crypto application to handle public keys and encryption, hence
these applications must be loaded for the SSL application to work.
In an embedded environment this means they must be started with
@@ -94,13 +99,20 @@
<p><c>erl -ssl protocol_version "['tlsv1.2', 'tlsv1.1']"</c></p>
<taglist>
- <tag><c>protocol_version = </c><seealso marker="ssl#type-protocol">ssl:protocol()</seealso><c><![CDATA[<optional>]]></c></tag>
+ <tag><c>protocol_version = </c><seealso marker="ssl#type-protocol">ssl:ssl_tls_protocol()</seealso><c><![CDATA[<optional>]]></c></tag>
<item><p>Protocol supported by started clients and
servers. If this option is not set, it defaults to all
- protocols currently supported by the SSL application.
+ TLS protocols currently supported by the SSL application.
This option can be overridden by the version option
to <c>ssl:connect/[2,3]</c> and <c>ssl:listen/2</c>.</p></item>
+ <tag><c>dtls_protocol_version = </c><seealso marker="ssl#type-protocol">ssl:dtls_protocol()</seealso><c><![CDATA[<optional>]]></c></tag>
+ <item><p>Protocol supported by started clients and
+ servers. If this option is not set, it defaults to all
+ DTLS protocols currently supported by the SSL application.
+ This option can be overridden by the version option
+ to <c>ssl:connect/[2,3]</c> and <c>ssl:listen/2</c>.</p></item>
+
<tag><c><![CDATA[session_lifetime = integer() <optional>]]></c></tag>
<item><p>Maximum lifetime of the session data in seconds. Defaults to 24 hours which is the maximum
recommended lifetime by <url href="http://www.ietf.org/rfc/5246rfc.txt">RFC 5246</url>. However
@@ -123,14 +135,14 @@
new client connections. If the maximum number of sessions is
reached, the current cache entries will be invalidated
regardless of their remaining lifetime. Defaults to
- 1000.</p></item>
+ 1000. Recommended ssl-8.2.1 or later for this option to work as intended.</p></item>
<tag> <c><![CDATA[session_cache_server_max = integer() <optional>]]></c></tag>
<item><p>Limits the growth of the servers session cache, that is
how many client sessions are cached by the server. If the
maximum number of sessions is reached, the current cache entries
will be invalidated regardless of their remaining
- lifetime. Defaults to 1000.</p></item>
+ lifetime. Defaults to 1000. Recommended ssl-8.2.1 or later for this option to work as intended.</p></item>
<tag><c><![CDATA[ssl_pem_cache_clean = integer() <optional>]]></c></tag>
<item>
@@ -145,9 +157,8 @@
<tag><c><![CDATA[bypass_pem_cache = boolean() <optional>]]></c></tag>
<item>
<p>Introduced in ssl-8.0.2. Disables the PEM-cache.
- The PEM cache has proven to be a bottleneck, until the
- implementation has been improved this can be used as
- a workaround. Defaults to false.
+ Can be used as a workaround for the PEM-cache bottleneck
+ before ssl-8.1.1. Defaults to false.
</p>
</item>
@@ -167,7 +178,7 @@
<title>ERROR LOGGER AND EVENT HANDLERS</title>
<p>The SSL application uses the default <seealso
marker="kernel:error_logger">OTP error logger</seealso> to log
- unexpected errors and TLS alerts. The logging of TLS alerts may be
+ unexpected errors and TLS/DTLS alerts. The logging of TLS/DTLS alerts may be
turned off with the <c>log_alert</c> option. </p>
</section>
diff --git a/lib/ssl/doc/src/ssl_crl_cache.xml b/lib/ssl/doc/src/ssl_crl_cache.xml
index 7a67de3971..71c6d5e49e 100644
--- a/lib/ssl/doc/src/ssl_crl_cache.xml
+++ b/lib/ssl/doc/src/ssl_crl_cache.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2015</year><year>2015</year>
+ <year>2015</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -40,7 +40,7 @@
<name>delete(Entries) -> ok | {error, Reason} </name>
<fsummary> </fsummary>
<type>
- <v> Entries = <seealso marker="inets:http_uri">http_uri:uri() </seealso> | {file, string()} | {der, [<seealso
+ <v> Entries = <seealso marker="stdlib:uri_string">uri_string:uri_string()</seealso> | {file, string()} | {der, [<seealso
marker="public_key:public_key"> public_key:der_encoded() </seealso>]}</v>
<v> Reason = term()</v>
</type>
@@ -55,7 +55,7 @@
<type>
<v> CRLSrc = {file, string()} | {der, [ <seealso
marker="public_key:public_key"> public_key:der_encoded() </seealso> ]}</v>
- <v> URI = <seealso marker="inets:http_uri">http_uri:uri() </seealso> </v>
+ <v> URI = <seealso marker="stdlib:uri_string">uri_string:uri_string() </seealso> </v>
<v> Reason = term()</v>
</type>
<desc>
@@ -63,4 +63,4 @@
</desc>
</func>
</funcs>
-</erlref> \ No newline at end of file
+</erlref>
diff --git a/lib/ssl/doc/src/ssl_distribution.xml b/lib/ssl/doc/src/ssl_distribution.xml
index 61f88e3860..e14f3f90dc 100644
--- a/lib/ssl/doc/src/ssl_distribution.xml
+++ b/lib/ssl/doc/src/ssl_distribution.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2016</year>
+ <year>2000</year><year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -22,7 +22,7 @@
</legalnotice>
- <title>Using SSL for Erlang Distribution</title>
+ <title>Using TLS for Erlang Distribution</title>
<prepared>P Nyblom</prepared>
<responsible></responsible>
<docno></docno>
@@ -33,7 +33,7 @@
<file>ssl_distribution.xml</file>
</header>
<p>This section describes how the Erlang distribution can use
- SSL to get extra verification and security.</p>
+ TLS to get extra verification and security.</p>
<p>The Erlang distribution can in theory use almost any
connection-based protocol as bearer. However, a module that
@@ -45,16 +45,16 @@
<p>In the SSL application, an extra distribution
module, <c>inet_tls_dist</c>, can be used as an
- alternative. All distribution connections will use SSL and
+ alternative. All distribution connections will use TLS and
all participating Erlang nodes in a distributed system must use
this distribution module.</p>
<p>The security level depends on the parameters provided to the
- SSL connection setup. Erlang node cookies are however always
+ TLS connection setup. Erlang node cookies are however always
used, as they can be used to differentiate between two different
Erlang networks.</p>
- <p>To set up Erlang distribution over SSL:</p>
+ <p>To set up Erlang distribution over TLS:</p>
<list type="bulleted">
<item><em>Step 1:</em> Build boot scripts including the
@@ -63,13 +63,13 @@
<c>net_kernel</c>.</item>
<item><em>Step 3:</em> Specify the security options and other
SSL options.</item>
- <item><em>Step 4:</em> Set up the environment to always use SSL.</item>
+ <item><em>Step 4:</em> Set up the environment to always use TLS.</item>
</list>
<p>The following sections describe these steps.</p>
<section>
- <title>Building Boot Scripts Including the ssl Application</title>
+ <title>Building Boot Scripts Including the SSL Application</title>
<p>Boot scripts are built using the <c>systools</c> utility in the
SASL application. For more information on <c>systools</c>,
see the SASL documentation. This is only an example of
@@ -90,7 +90,7 @@
STDLIB application.</p></item>
</list>
- <p>The following shows an example <c>.rel</c> file with SSL
+ <p>The following shows an example <c>.rel</c> file with TLS
added:</p>
<code type="none">
{release, {"OTP APN 181 01","R15A"}, {erts, "5.9"},
@@ -154,7 +154,7 @@ Eshell V5.0 (abort with ^G)
<section>
<title>Specifying Distribution Module for net_kernel</title>
- <p>The distribution module for SSL is named <c>inet_tls_dist</c>
+ <p>The distribution module for SSL/TLS is named <c>inet_tls_dist</c>
and is specified on the command line with option <c>-proto_dist</c>.
The argument to <c>-proto_dist</c> is to be the module
name without suffix <c>_dist</c>. So, this distribution
@@ -174,21 +174,107 @@ Eshell V5.0 (abort with ^G)
(ssl_test@myhost)1> </code>
<p>However, a node started in this way refuses to talk
- to other nodes, as no SSL parameters are supplied
+ to other nodes, as no TLS parameters are supplied
(see the next section).</p>
</section>
<section>
- <title>Specifying SSL Options</title>
- <p>For SSL to work, at least
- a public key and a certificate must be specified for the server
- side. In the following example, the PEM-files consist of two
- entries, the server certificate and its private key.</p>
+ <title>Specifying SSL/TLS Options</title>
+
+ <p>
+ The SSL/TLS distribution options can be written into a file
+ that is consulted when the node is started. This file name
+ is then specified with the command line argument
+ <c>-ssl_dist_optfile</c>.
+ </p>
+ <p>
+ Any available SSL/TLS option can be specified in an options file,
+ but note that options that take a <c>fun()</c> has to use
+ the syntax <c>fun Mod:Func/Arity</c> since a function
+ body can not be compiled when consulting a file.
+ </p>
+ <p>
+ Do not tamper with the socket options
+ <c>list</c>, <c>binary</c>, <c>active</c>, <c>packet</c>,
+ <c>nodelay</c> and <c>deliver</c> since they are used
+ by the distribution protocol handler itself.
+ Other raw socket options such as <c>packet_size</c> may
+ interfere severely, so beware!
+ </p>
+ <p>
+ For SSL/TLS to work, at least a public key and a certificate
+ must be specified for the server side.
+ In the following example, the PEM file
+ <c>"/home/me/ssl/erlserver.pem"</c> contains both
+ the server certificate and its private key.
+ </p>
+ <p>
+ Create a file named for example
+ <c>"/home/me/ssl/[email protected]"</c>:
+ </p>
+ <code type="none"><![CDATA[
+[{server,
+ [{certfile, "/home/me/ssl/erlserver.pem"},
+ {secure_renegotiate, true}]},
+ {client,
+ [{secure_renegotiate, true}]}].]]>
+ </code>
+ <p>
+ And then start the node like this
+ (line breaks in the command are for readability,
+ and shall not be there when typed):
+ </p>
+ <code type="none"><![CDATA[
+$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls
+ -ssl_dist_optfile "/home/me/ssl/[email protected]"
+ -sname ssl_test]]>
+ </code>
+ <p>
+ The options in the <c>{server, Opts}</c> tuple are used
+ when calling <c>ssl:ssl_accept/3</c>, and the options in the
+ <c>{client, Opts}</c> tuple are used when calling
+ <c>ssl:connect/4</c>.
+ </p>
+ <p>
+ For the client, the option
+ <c>{server_name_indication, atom_to_list(TargetNode)}</c>
+ is added when connecting.
+ This makes it possible to use the client option
+ <c>{verify, verify_peer}</c>,
+ and the client will verify that the certificate matches
+ the node name you are connecting to.
+ This only works if the the server certificate is issued
+ to the name <c>atom_to_list(TargetNode)</c>.
+ </p>
+ <p>
+ For the server it is also possible to use the option
+ <c>{verify, verify_peer}</c> and the server will only accept
+ client connections with certificates that are trusted by
+ a root certificate that the server knows.
+ A client that presents an untrusted certificate will be rejected.
+ This option is preferably combined with
+ <c>{fail_if_no_peer_cert, true}</c> or a client will
+ still be accepted if it does not present any certificate.
+ </p>
+ <p>
+ A node started in this way is fully functional, using TLS
+ as the distribution protocol.
+ </p>
+ </section>
+
+ <section>
+ <title>Specifying SSL/TLS Options (Legacy)</title>
+
+ <p>
+ As in the previous section the PEM file
+ <c>"/home/me/ssl/erlserver.pem"</c> contains both
+ the server certificate and its private key.
+ </p>
<p>On the <c>erl</c> command line you can specify options that the
- SSL distribution adds when creating a socket.</p>
+ SSL/TLS distribution adds when creating a socket.</p>
- <p>The simplest SSL options in the following list can be specified
+ <p>The simplest SSL/TLS options in the following list can be specified
by adding the
prefix <c>server_</c> or <c>client_</c> to the option name:</p>
<list type="bulleted">
@@ -208,7 +294,7 @@ Eshell V5.0 (abort with ^G)
</list>
<p>Note that <c>verify_fun</c> needs to be written in a different
- form than the corresponding SSL option, since funs are not
+ form than the corresponding SSL/TLS option, since funs are not
accepted on the command line.</p>
<p>The server can also take the options <c>dhfile</c> and
@@ -221,32 +307,34 @@ Eshell V5.0 (abort with ^G)
<p>Raw socket options, such as <c>packet</c> and <c>size</c> must not
be specified on the command line.</p>
- <p>The command-line argument for specifying the SSL options is named
+ <p>The command-line argument for specifying the SSL/TLS options is named
<c>-ssl_dist_opt</c> and is to be followed by pairs of
SSL options and their values. Argument <c>-ssl_dist_opt</c> can
be repeated any number of times.</p>
- <p>An example command line can now look as follows
+ <p>
+ An example command line doing the same as the example
+ in the previous section can now look as follows
(line breaks in the command are for readability,
- and are not be there when typed):</p>
- <code type="none">
+ and shall not be there when typed):
+ </p>
+ <code type="none"><![CDATA[
$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls
- -ssl_dist_opt server_certfile "/home/me/ssl/erlserver.pem"
+ -ssl_dist_opt server_certfile "/home/me/ssl/erlserver.pem"
-ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true
-sname ssl_test
Erlang (BEAM) emulator version 5.0 [source]
-
+
Eshell V5.0 (abort with ^G)
-(ssl_test@myhost)1> </code>
- <p>A node started in this way is fully functional, using SSL
- as the distribution protocol.</p>
+(ssl_test@myhost)1>]]>
+ </code>
</section>
<section>
- <title>Setting up Environment to Always Use SSL</title>
+ <title>Setting up Environment to Always Use SSL/TLS (Legacy)</title>
<p>A convenient way to specify arguments to Erlang is to use environment
variable <c>ERL_FLAGS</c>. All the flags needed to
- use the SSL distribution can be specified in that variable and are
+ use the SSL/TLS distribution can be specified in that variable and are
then interpreted as command-line arguments for all
subsequent invocations of Erlang.</p>
@@ -277,25 +365,21 @@ Eshell V5.0 (abort with ^G)
</section>
<section>
- <title>Using SSL distribution over IPv6</title>
- <p>It is possible to use SSL distribution over IPv6 instead of
+ <title>Using SSL/TLS distribution over IPv6</title>
+ <p>It is possible to use SSL/TLS distribution over IPv6 instead of
IPv4. To do this, pass the option <c>-proto_dist inet6_tls</c>
instead of <c>-proto_dist inet_tls</c> when starting Erlang,
either on the command line or in the <c>ERL_FLAGS</c> environment
variable.</p>
<p>An example command line with this option would look like this:</p>
- <code type="none">
+ <code type="none"><![CDATA[
$ erl -boot /home/me/ssl/start_ssl -proto_dist inet6_tls
- -ssl_dist_opt server_certfile "/home/me/ssl/erlserver.pem"
- -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true
- -sname ssl_test
-Erlang (BEAM) emulator version 5.0 [source]
-
-Eshell V5.0 (abort with ^G)
-(ssl_test@myhost)1> </code>
+ -ssl_dist_optfile "/home/me/ssl/[email protected]"
+ -sname ssl_test]]>
+ </code>
<p>A node started in this way will only be able to communicate with
- other nodes using SSL distribution over IPv6.</p>
+ other nodes using SSL/TLS distribution over IPv6.</p>
</section>
</chapter>
diff --git a/lib/ssl/doc/src/ssl_introduction.xml b/lib/ssl/doc/src/ssl_introduction.xml
index d3e39dbb01..adcfb091b7 100644
--- a/lib/ssl/doc/src/ssl_introduction.xml
+++ b/lib/ssl/doc/src/ssl_introduction.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2015</year>
- <year>2015</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -36,19 +36,20 @@
<title>Purpose</title>
<p>Transport Layer Security (TLS) and its predecessor, the Secure
Sockets Layer (SSL), are cryptographic protocols designed to
- provide communications security over a computer network. The protocols use
+ provide communications security over a computer network. The protocols
use X.509 certificates and hence public key (asymmetric) cryptography to
authenticate the counterpart with whom they communicate,
and to exchange a symmetric key for payload encryption. The protocol provides
data/message confidentiality (encryption), integrity (through message authentication code checks)
- and host verification (through certificate path validation).</p>
+ and host verification (through certificate path validation). DTLS (Datagram Transport Layer Security) that
+ is based on TLS but datagram oriented instead of stream oriented.</p>
</section>
<section>
<title>Prerequisites</title>
<p>It is assumed that the reader is familiar with the Erlang
programming language, the concepts of OTP, and has a basic
- understanding of SSL/TLS.</p>
+ understanding of SSL/TLS/DTLS.</p>
</section>
</chapter>
diff --git a/lib/ssl/doc/src/ssl_protocol.xml b/lib/ssl/doc/src/ssl_protocol.xml
index 31a22db58b..3ab836443f 100644
--- a/lib/ssl/doc/src/ssl_protocol.xml
+++ b/lib/ssl/doc/src/ssl_protocol.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2015</year>
+ <year>2003</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -22,7 +22,7 @@
</legalnotice>
- <title>TLS and its Predecessor, SSL</title>
+ <title>TLS/DTLS and TLS Predecessor, SSL</title>
<prepared></prepared>
<responsible></responsible>
<docno></docno>
@@ -33,7 +33,7 @@
<file>ssl_protocol.xml</file>
</header>
- <p>The Erlang SSL application implements the SSL/TLS protocol
+ <p>The Erlang SSL application implements the SSL/TLS/DTLS protocol
for the currently supported versions, see the
<seealso marker="ssl">ssl(3)</seealso> manual page.
</p>
@@ -41,20 +41,22 @@
<p>By default SSL/TLS is run over the TCP/IP protocol even
though you can plug in any other reliable transport protocol
with the same Application Programming Interface (API) as the
- <c>gen_tcp</c> module in Kernel.</p>
+ <c>gen_tcp</c> module in Kernel. DTLS is by default run over UDP/IP,
+ which means that application data has no delivery guarentees. Other
+ transports, such as SCTP, may be supported in future releases.</p>
<p>If a client and a server wants to use an upgrade mechanism, such as
- defined by RFC 2817, to upgrade a regular TCP/IP connection to an SSL
+ defined by RFC 2817, to upgrade a regular TCP/IP connection to an TLS
connection, this is supported by the Erlang SSL application API. This can be
useful for, for example, supporting HTTP and HTTPS on the same port and
- implementing virtual hosting.
+ implementing virtual hosting. Note this is a TLS feature only.
</p>
<section>
<title>Security Overview</title>
<p>To achieve authentication and privacy, the client and server
- perform a TLS handshake procedure before transmitting or receiving
+ perform a TLS/DTLS handshake procedure before transmitting or receiving
any data. During the handshake, they agree on a protocol version and
cryptographic algorithms, generate shared secrets using public
key cryptographies, and optionally authenticate each other with
@@ -73,10 +75,10 @@
<p>The keys for the symmetric encryption are generated uniquely
for each connection and are based on a secret negotiated
- in the TLS handshake.</p>
+ in the TLS/DTLS handshake.</p>
- <p>The TLS handshake protocol and data transfer is run on top of
- the TLS Record Protocol, which uses a keyed-hash Message
+ <p>The TLS/DTLS handshake protocol and data transfer is run on top of
+ the TLS/DTLS Record Protocol, which uses a keyed-hash Message
Authenticity Code (MAC), or a Hash-based MAC (HMAC),
to protect the message data
integrity. From the TLS RFC: "A Message Authentication Code is a
@@ -152,8 +154,8 @@
from it was saved, for security reasons. The amount of time the
session data is to be saved can be configured.</p>
- <p>By default the SSL clients try to reuse an available session and
- by default the SSL servers agree to reuse sessions when clients
+ <p>By default the TLS/DTLS clients try to reuse an available session and
+ by default the TLS/DTLS servers agree to reuse sessions when clients
ask for it.</p>
</section>
diff --git a/lib/ssl/doc/src/using_ssl.xml b/lib/ssl/doc/src/using_ssl.xml
index f84cd6e391..f2f9b66a31 100644
--- a/lib/ssl/doc/src/using_ssl.xml
+++ b/lib/ssl/doc/src/using_ssl.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2016</year>
+ <year>2003</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -22,7 +22,7 @@
</legalnotice>
- <title>Using SSL API</title>
+ <title>Using SSL application API</title>
<prepared></prepared>
<responsible></responsible>
<docno></docno>
@@ -51,7 +51,7 @@
<section>
<title>Minimal Example</title>
- <note><p> The minimal setup is not the most secure setup of SSL.</p>
+ <note><p> The minimal setup is not the most secure setup of SSL/TLS/DTLS.</p>
</note>
<p>To set up client/server connections:</p>
@@ -60,27 +60,27 @@
<code type="erl">1 server> ssl:start().
ok</code>
- <p><em>Step 2:</em> Create an SSL listen socket:</p>
+ <p><em>Step 2:</em> Create an TLS listen socket: (To run DTLS add the option {protocol, dtls})</p>
<code type="erl">2 server> {ok, ListenSocket} =
ssl:listen(9999, [{certfile, "cert.pem"}, {keyfile, "key.pem"},{reuseaddr, true}]).
{ok,{sslsocket, [...]}}</code>
- <p><em>Step 3:</em> Do a transport accept on the SSL listen socket:</p>
- <code type="erl">3 server> {ok, Socket} = ssl:transport_accept(ListenSocket).
+ <p><em>Step 3:</em> Do a transport accept on the TLS listen socket:</p>
+ <code type="erl">3 server> {ok, TLSTransportSocket} = ssl:transport_accept(ListenSocket).
{ok,{sslsocket, [...]}}</code>
- <p><em>Step 4:</em> Start the client side:</p>
+ <p><em>Step 4:</em> Start the client side: </p>
<code type="erl">1 client> ssl:start().
ok</code>
-
+ <p> To run DTLS add the option {protocol, dtls} to third argument.</p>
<code type="erl">2 client> {ok, Socket} = ssl:connect("localhost", 9999, [], infinity).
{ok,{sslsocket, [...]}}</code>
- <p><em>Step 5:</em> Do the SSL handshake:</p>
- <code type="erl">4 server> ok = ssl:ssl_accept(Socket).
+ <p><em>Step 5:</em> Do the TLS handshake:</p>
+ <code type="erl">4 server> {ok, Socket} = ssl:handshake(TLSTransportSocket).
ok</code>
- <p><em>Step 6:</em> Send a message over SSL:</p>
+ <p><em>Step 6:</em> Send a message over TLS:</p>
<code type="erl">5 server> ssl:send(Socket, "foo").
ok</code>
@@ -92,7 +92,7 @@ ok</code>
</section>
<section>
- <title>Upgrade Example</title>
+ <title>Upgrade Example - TLS only </title>
<note><p>To upgrade a TCP/IP connection to an SSL connection, the
client and server must agree to do so. The agreement
@@ -125,24 +125,24 @@ ok</code>
<code type="erl">4 server> inet:setopts(Socket, [{active, false}]).
ok</code>
- <p><em>Step 6:</em> Do the SSL handshake:</p>
- <code type="erl">5 server> {ok, SSLSocket} = ssl:ssl_accept(Socket, [{cacertfile, "cacerts.pem"},
+ <p><em>Step 6:</em> Do the TLS handshake:</p>
+ <code type="erl">5 server> {ok, TLSSocket} = ssl:handshake(Socket, [{cacertfile, "cacerts.pem"},
{certfile, "cert.pem"}, {keyfile, "key.pem"}]).
{ok,{sslsocket,[...]}}</code>
- <p><em>Step 7:</em> Upgrade to an SSL connection. The client and server
+ <p><em>Step 7:</em> Upgrade to an TLS connection. The client and server
must agree upon the upgrade. The server must call
- <c>ssl:accept/2</c> before the client calls <c>ssl:connect/3.</c></p>
- <code type="erl">3 client>{ok, SSLSocket} = ssl:connect(Socket, [{cacertfile, "cacerts.pem"},
+ <c>ssl:handshake/2</c> before the client calls <c>ssl:connect/3.</c></p>
+ <code type="erl">3 client>{ok, TLSSocket} = ssl:connect(Socket, [{cacertfile, "cacerts.pem"},
{certfile, "cert.pem"}, {keyfile, "key.pem"}], infinity).
{ok,{sslsocket,[...]}}</code>
- <p><em>Step 8:</em> Send a message over SSL:</p>
- <code type="erl">4 client> ssl:send(SSLSocket, "foo").
+ <p><em>Step 8:</em> Send a message over TLS:</p>
+ <code type="erl">4 client> ssl:send(TLSSocket, "foo").
ok</code>
- <p><em>Step 9:</em> Set <c>active true</c> on the SSL socket:</p>
- <code type="erl">4 server> ssl:setopts(SSLSocket, [{active, true}]).
+ <p><em>Step 9:</em> Set <c>active true</c> on the TLS socket:</p>
+ <code type="erl">4 server> ssl:setopts(TLSSocket, [{active, true}]).
ok</code>
<p><em>Step 10:</em> Flush the shell message queue to see that the message
@@ -152,4 +152,85 @@ Shell got {ssl,{sslsocket,[...]},"foo"}
ok</code>
</section>
</section>
+
+ <section>
+ <title>Customizing cipher suits</title>
+
+ <p>Fetch default cipher suite list for an TLS/DTLS version. Change default
+ to all to get all possible cipher suites.</p>
+ <code type="erl">1> Default = ssl:cipher_suites(default, 'tlsv1.2').
+ [#{cipher => aes_256_gcm,key_exchange => ecdhe_ecdsa,
+ mac => aead,prf => sha384}, ....]
+</code>
+
+ <p>In OTP 20 it is desirable to remove all cipher suites
+ that uses rsa kexchange (removed from default in 21) </p>
+ <code type="erl">2> NoRSA =
+ ssl:filter_cipher_suites(Default,
+ [{key_exchange, fun(rsa) -> false;
+ (_) -> true end}]).
+ [...]
+ </code>
+
+ <p> Pick just a few suites </p>
+ <code type="erl"> 3> Suites =
+ ssl:filter_cipher_suites(Default,
+ [{key_exchange, fun(ecdh_ecdsa) -> true;
+ (_) -> false end},
+ {cipher, fun(aes_128_cbc) ->true;
+ (_) ->false end}]).
+ [#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,
+ mac => sha256,prf => sha256},
+ #{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha,
+ prf => default_prf}]
+ </code>
+
+ <p> Make some particular suites the most preferred, or least
+ preferred by changing prepend to append.</p>
+ <code type="erl"> 4>ssl:prepend_cipher_suites(Suites, Default).
+ [#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,
+ mac => sha256,prf => sha256},
+ #{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha,
+ prf => default_prf},
+ #{cipher => aes_256_cbc,key_exchange => ecdhe_ecdsa,
+ mac => sha384,prf => sha384}, ...]
+ </code>
+ </section>
+
+ <section>
+ <title>Using an Engine Stored Key</title>
+
+ <p>Erlang ssl application is able to use private keys provided
+ by OpenSSL engines using the following mechanism:</p>
+
+ <code type="erl">1> ssl:start().
+ok</code>
+
+ <p>Load a crypto engine, should be done once per engine used. For example
+ dynamically load the engine called <c>MyEngine</c>:
+ </p>
+ <code type="erl">2> {ok, EngineRef} =
+crypto:engine_load(&lt;&lt;"dynamic">>,
+ [{&lt;&lt;"SO_PATH">>, "/tmp/user/engines/MyEngine"},&lt;&lt;"LOAD">>],[]).
+{ok,#Ref&lt;0.2399045421.3028942852.173962>}
+ </code>
+
+ <p>Create a map with the engine information and the algorithm used by the engine:</p>
+ <code type="erl">3> PrivKey =
+ #{algorithm => rsa,
+ engine => EngineRef,
+ key_id => "id of the private key in Engine"}.
+ </code>
+ <p>Use the map in the ssl key option:</p>
+ <code type="erl">4> {ok, SSLSocket} =
+ssl:connect("localhost", 9999,
+ [{cacertfile, "cacerts.pem"},
+ {certfile, "cert.pem"},
+ {key, PrivKey}], infinity).
+ </code>
+
+ <p>See also <seealso marker="crypto:engine_load#engine_load"> crypto documentation</seealso> </p>
+
+ </section>
+
</chapter>
diff --git a/lib/ssl/doc/src/warning.gif b/lib/ssl/doc/src/warning.gif
deleted file mode 100644
index 96af52360e..0000000000
--- a/lib/ssl/doc/src/warning.gif
+++ /dev/null
Binary files differ
diff --git a/lib/ssl/examples/src/client_server.erl b/lib/ssl/examples/src/client_server.erl
index c150f43bff..8d68da12d5 100644
--- a/lib/ssl/examples/src/client_server.erl
+++ b/lib/ssl/examples/src/client_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -39,15 +39,15 @@ start() ->
%% Accept
{ok, ASock} = ssl:transport_accept(LSock),
- ok = ssl:ssl_accept(ASock),
+ {ok, SslSocket} = ssl:handshake(ASock),
io:fwrite("Accept: accepted.~n"),
- {ok, Cert} = ssl:peercert(ASock),
+ {ok, Cert} = ssl:peercert(SslSocket),
io:fwrite("Accept: peer cert:~n~p~n", [public_key:pkix_decode_cert(Cert, otp)]),
io:fwrite("Accept: sending \"hello\".~n"),
- ssl:send(ASock, "hello"),
- {error, closed} = ssl:recv(ASock, 0),
+ ssl:send(SslSocket, "hello"),
+ {error, closed} = ssl:recv(SslSocket, 0),
io:fwrite("Accept: detected closed.~n"),
- ssl:close(ASock),
+ ssl:close(SslSocket),
io:fwrite("Listen: closing and terminating.~n"),
ssl:close(LSock),
@@ -75,7 +75,7 @@ mk_opts(Role) ->
[{active, false},
{verify, 2},
{depth, 2},
+ {server_name_indication, disable},
{cacertfile, filename:join([Dir, Role, "cacerts.pem"])},
{certfile, filename:join([Dir, Role, "cert.pem"])},
{keyfile, filename:join([Dir, Role, "key.pem"])}].
-
diff --git a/lib/ssl/src/Makefile b/lib/ssl/src/Makefile
index 2e7df9792e..8d1341f594 100644
--- a/lib/ssl/src/Makefile
+++ b/lib/ssl/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
+# Copyright Ericsson AB 1999-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -44,8 +44,6 @@ BEHAVIOUR_MODULES= \
MODULES= \
ssl \
- tls \
- dtls \
ssl_alert \
ssl_app \
ssl_sup \
@@ -54,8 +52,8 @@ MODULES= \
ssl_connection_sup \
ssl_listen_tracker_sup\
dtls_connection_sup \
- dtls_udp_listener\
- dtls_udp_sup \
+ dtls_packet_demux \
+ dtls_listener_sup \
ssl_dist_sup\
ssl_dist_admin_sup\
ssl_dist_connection_sup\
@@ -64,9 +62,11 @@ MODULES= \
ssl_certificate\
ssl_pkix_db\
ssl_cipher \
+ ssl_cipher_format \
ssl_srp_primes \
tls_connection \
dtls_connection \
+ tls_sender\
ssl_config \
ssl_connection \
tls_handshake \
@@ -84,11 +84,9 @@ MODULES= \
tls_record \
dtls_record \
ssl_record \
- ssl_v2 \
ssl_v3 \
tls_v1 \
- dtls_v1 \
- ssl_tls_dist_proxy
+ dtls_v1
INTERNAL_HRL_FILES = \
ssl_alert.hrl ssl_cipher.hrl \
diff --git a/lib/ssl/src/dtls.erl b/lib/ssl/src/dtls.erl
deleted file mode 100644
index cd705152a8..0000000000
--- a/lib/ssl/src/dtls.erl
+++ /dev/null
@@ -1,113 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
-%%% Purpose : Reflect DTLS specific API options (fairly simple wrapper at the moment)
-%% First implementation will support DTLS connections only in a "TLS/TCP like way"
-
--module(dtls).
-
--include("ssl_api.hrl").
--include("ssl_internal.hrl").
-
--export([connect/2, connect/3, listen/2, accept/1, accept/2,
- handshake/1, handshake/2, handshake/3]).
-
-%%--------------------------------------------------------------------
-%%
-%% Description: Connect to a DTLS server.
-%%--------------------------------------------------------------------
-
--spec connect(host() | port(), [connect_option()]) -> {ok, #sslsocket{}} |
- {error, reason()}.
-
-connect(Socket, Options) when is_port(Socket) ->
- connect(Socket, Options, infinity).
-
--spec connect(host() | port(), [connect_option()] | inet:port_number(),
- timeout() | list()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
-connect(Socket, SslOptions, Timeout) when is_port(Socket) ->
- DTLSOpts = [{protocol, dtls} | SslOptions],
- ssl:connect(Socket, DTLSOpts, Timeout);
-connect(Host, Port, Options) ->
- connect(Host, Port, Options, infinity).
-
--spec connect(host() | port(), inet:port_number(), list(), timeout()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
-connect(Host, Port, Options, Timeout) ->
- DTLSOpts = [{protocol, dtls} | Options],
- ssl:connect(Host, Port, DTLSOpts, Timeout).
-
-%%--------------------------------------------------------------------
--spec listen(inet:port_number(), [listen_option()]) ->{ok, #sslsocket{}} | {error, reason()}.
-
-%%
-%% Description: Creates an ssl listen socket.
-%%--------------------------------------------------------------------
-listen(Port, Options) ->
- DTLSOpts = [{protocol, dtls} | Options],
- ssl:listen(Port, DTLSOpts).
-
-%%--------------------------------------------------------------------
-%%
-%% Description: Performs transport accept on an ssl listen socket
-%%--------------------------------------------------------------------
--spec accept(#sslsocket{}) -> {ok, #sslsocket{}} |
- {error, reason()}.
-accept(ListenSocket) ->
- accept(ListenSocket, infinity).
-
--spec accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} |
- {error, reason()}.
-accept(Socket, Timeout) ->
- ssl:transport_accept(Socket, Timeout).
-
-%%--------------------------------------------------------------------
-%%
-%% Description: Performs accept on an ssl listen socket. e.i. performs
-%% ssl handshake.
-%%--------------------------------------------------------------------
-
--spec handshake(#sslsocket{}) -> ok | {error, reason()}.
-
-handshake(ListenSocket) ->
- handshake(ListenSocket, infinity).
-
-
--spec handshake(#sslsocket{} | port(), timeout()| [ssl_option()
- | transport_option()]) ->
- ok | {ok, #sslsocket{}} | {error, reason()}.
-
-handshake(#sslsocket{} = Socket, Timeout) ->
- ssl:ssl_accept(Socket, Timeout);
-
-handshake(ListenSocket, SslOptions) when is_port(ListenSocket) ->
- handshake(ListenSocket, SslOptions, infinity).
-
-
--spec handshake(port(), [ssl_option()| transport_option()], timeout()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
-handshake(Socket, SslOptions, Timeout) when is_port(Socket) ->
- ssl:ssl_accept(Socket, SslOptions, Timeout).
diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl
index e8cfbbe2e3..2a0b2b317d 100644
--- a/lib/ssl/src/dtls_connection.erl
+++ b/lib/ssl/src/dtls_connection.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,34 +36,35 @@
%% Internal application API
%% Setup
--export([start_fsm/8, start_link/7, init/1]).
+-export([start_fsm/8, start_link/7, init/1, pids/1]).
%% State transition handling
--export([next_record/1, next_event/3, next_event/4]).
+-export([next_record/1, next_event/3, next_event/4, handle_common_event/4]).
%% Handshake handling
--export([renegotiate/2,
- reinit_handshake_data/1,
- send_handshake/2, queue_handshake/2, queue_change_cipher/2,
- select_sni_extension/1]).
+-export([renegotiate/2, send_handshake/2,
+ queue_handshake/2, queue_change_cipher/2,
+ reinit/1, reinit_handshake_data/1, select_sni_extension/1, empty_connection_state/2]).
%% Alert and close handling
--export([encode_alert/3,send_alert/2, close/5]).
+-export([encode_alert/3, send_alert/2, send_alert_in_connection/2, close/5, protocol_name/0]).
%% Data handling
-
--export([encode_data/3, passive_receive/2, next_record_if_active/1, handle_common_event/4,
+-export([encode_data/3, passive_receive/2, next_record_if_active/1,
send/3, socket/5, setopts/3, getopts/3]).
%% gen_statem state functions
-export([init/3, error/3, downgrade/3, %% Initiation and take down states
- hello/3, certify/3, cipher/3, abbreviated/3, %% Handshake states
+ hello/3, user_hello/3, certify/3, cipher/3, abbreviated/3, %% Handshake states
connection/3]).
%% gen_statem callbacks
-export([callback_mode/0, terminate/3, code_change/4, format_status/2]).
%%====================================================================
%% Internal application API
+%%====================================================================
+%%====================================================================
+%% Setup
%%====================================================================
start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = false},_, Tracker} = Opts,
User, {CbModule, _,_, _} = CbInfo,
@@ -71,17 +72,238 @@ start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = false},_, Tracker}
try
{ok, Pid} = dtls_connection_sup:start_child([Role, Host, Port, Socket,
Opts, User, CbInfo]),
- {ok, SslSocket} = ssl_connection:socket_control(?MODULE, Socket, Pid, CbModule, Tracker),
- ok = ssl_connection:handshake(SslSocket, Timeout),
- {ok, SslSocket}
+ {ok, SslSocket} = ssl_connection:socket_control(?MODULE, Socket, [Pid], CbModule, Tracker),
+ ssl_connection:handshake(SslSocket, Timeout)
catch
error:{badmatch, {error, _} = Error} ->
Error
end.
-send_handshake(Handshake, #state{connection_states = ConnectionStates} = States) ->
+%%--------------------------------------------------------------------
+-spec start_link(atom(), host(), inet:port_number(), port(), list(), pid(), tuple()) ->
+ {ok, pid()} | ignore | {error, reason()}.
+%%
+%% Description: Creates a gen_statem process which calls Module:init/1 to
+%% initialize.
+%%--------------------------------------------------------------------
+start_link(Role, Host, Port, Socket, Options, User, CbInfo) ->
+ {ok, proc_lib:spawn_link(?MODULE, init, [[Role, Host, Port, Socket, Options, User, CbInfo]])}.
+
+init([Role, Host, Port, Socket, Options, User, CbInfo]) ->
+ process_flag(trap_exit, true),
+ State0 = #state{protocol_specific = Map} = initial_state(Role, Host, Port, Socket, Options, User, CbInfo),
+ try
+ State = ssl_connection:ssl_config(State0#state.ssl_options, Role, State0),
+ gen_statem:enter_loop(?MODULE, [], init, State)
+ catch
+ throw:Error ->
+ EState = State0#state{protocol_specific = Map#{error => Error}},
+ gen_statem:enter_loop(?MODULE, [], error, EState)
+ end.
+
+pids(_) ->
+ [self()].
+
+%%====================================================================
+%% State transition handling
+%%====================================================================
+next_record(#state{unprocessed_handshake_events = N} = State) when N > 0 ->
+ {no_record, State#state{unprocessed_handshake_events = N-1}};
+
+next_record(#state{protocol_buffers =
+ #protocol_buffers{dtls_cipher_texts = [#ssl_tls{epoch = Epoch} = CT | Rest]}
+ = Buffers,
+ connection_states = #{current_read := #{epoch := Epoch}} = ConnectionStates} = State) ->
+ CurrentRead = dtls_record:get_connection_state_by_epoch(Epoch, ConnectionStates, read),
+ case dtls_record:replay_detect(CT, CurrentRead) of
+ false ->
+ decode_cipher_text(State#state{connection_states = ConnectionStates}) ;
+ true ->
+ %% Ignore replayed record
+ next_record(State#state{protocol_buffers =
+ Buffers#protocol_buffers{dtls_cipher_texts = Rest},
+ connection_states = ConnectionStates})
+ end;
+next_record(#state{protocol_buffers =
+ #protocol_buffers{dtls_cipher_texts = [#ssl_tls{epoch = Epoch} | Rest]}
+ = Buffers,
+ connection_states = #{current_read := #{epoch := CurrentEpoch}} = ConnectionStates} = State)
+ when Epoch > CurrentEpoch ->
+ %% TODO Buffer later Epoch message, drop it for now
+ next_record(State#state{protocol_buffers =
+ Buffers#protocol_buffers{dtls_cipher_texts = Rest},
+ connection_states = ConnectionStates});
+next_record(#state{protocol_buffers =
+ #protocol_buffers{dtls_cipher_texts = [ _ | Rest]}
+ = Buffers,
+ connection_states = ConnectionStates} = State) ->
+ %% Drop old epoch message
+ next_record(State#state{protocol_buffers =
+ Buffers#protocol_buffers{dtls_cipher_texts = Rest},
+ connection_states = ConnectionStates});
+next_record(#state{role = server,
+ socket = {Listener, {Client, _}}} = State) ->
+ dtls_packet_demux:active_once(Listener, Client, self()),
+ {no_record, State};
+next_record(#state{role = client,
+ socket = {_Server, Socket} = DTLSSocket,
+ close_tag = CloseTag,
+ transport_cb = Transport} = State) ->
+ case dtls_socket:setopts(Transport, Socket, [{active,once}]) of
+ ok ->
+ {no_record, State};
+ _ ->
+ self() ! {CloseTag, DTLSSocket},
+ {no_record, State}
+ end;
+next_record(State) ->
+ {no_record, State}.
+
+next_event(StateName, Record, State) ->
+ next_event(StateName, Record, State, []).
+
+next_event(connection = StateName, no_record,
+ #state{connection_states = #{current_read := #{epoch := CurrentEpoch}}} = State0, Actions) ->
+ case next_record_if_active(State0) of
+ {no_record, State} ->
+ ssl_connection:hibernate_after(StateName, State, Actions);
+ {#ssl_tls{epoch = CurrentEpoch,
+ type = ?HANDSHAKE,
+ version = Version} = Record, State1} ->
+ State = dtls_version(StateName, Version, State1),
+ {next_state, StateName, State,
+ [{next_event, internal, {protocol_record, Record}} | Actions]};
+ {#ssl_tls{epoch = CurrentEpoch} = Record, State} ->
+ {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]};
+ {#ssl_tls{epoch = Epoch,
+ type = ?HANDSHAKE,
+ version = _Version}, State1} = _Record when Epoch == CurrentEpoch-1 ->
+ {State2, MoreActions} = send_handshake_flight(State1, CurrentEpoch),
+ {NextRecord, State} = next_record(State2),
+ next_event(StateName, NextRecord, State, Actions ++ MoreActions);
+ %% From FLIGHT perspective CHANGE_CIPHER_SPEC is treated as a handshake
+ {#ssl_tls{epoch = Epoch,
+ type = ?CHANGE_CIPHER_SPEC,
+ version = _Version}, State1} = _Record when Epoch == CurrentEpoch-1 ->
+ {State2, MoreActions} = send_handshake_flight(State1, CurrentEpoch),
+ {NextRecord, State} = next_record(State2),
+ next_event(StateName, NextRecord, State, Actions ++ MoreActions);
+ {#ssl_tls{epoch = _Epoch,
+ version = _Version}, State1} ->
+ %% TODO maybe buffer later epoch
+ {Record, State} = next_record(State1),
+ next_event(StateName, Record, State, Actions);
+ {#alert{} = Alert, State} ->
+ {next_state, StateName, State, [{next_event, internal, Alert} | Actions]}
+ end;
+next_event(connection = StateName, Record,
+ #state{connection_states = #{current_read := #{epoch := CurrentEpoch}}} = State0, Actions) ->
+ case Record of
+ #ssl_tls{epoch = CurrentEpoch,
+ type = ?HANDSHAKE,
+ version = Version} = Record ->
+ State = dtls_version(StateName, Version, State0),
+ {next_state, StateName, State,
+ [{next_event, internal, {protocol_record, Record}} | Actions]};
+ #ssl_tls{epoch = CurrentEpoch} ->
+ {next_state, StateName, State0, [{next_event, internal, {protocol_record, Record}} | Actions]};
+ #ssl_tls{epoch = Epoch,
+ type = ?HANDSHAKE,
+ version = _Version} when Epoch == CurrentEpoch-1 ->
+ {State1, MoreActions} = send_handshake_flight(State0, CurrentEpoch),
+ {NextRecord, State} = next_record(State1),
+ next_event(StateName, NextRecord, State, Actions ++ MoreActions);
+ %% From FLIGHT perspective CHANGE_CIPHER_SPEC is treated as a handshake
+ #ssl_tls{epoch = Epoch,
+ type = ?CHANGE_CIPHER_SPEC,
+ version = _Version} when Epoch == CurrentEpoch-1 ->
+ {State1, MoreActions} = send_handshake_flight(State0, CurrentEpoch),
+ {NextRecord, State} = next_record(State1),
+ next_event(StateName, NextRecord, State, Actions ++ MoreActions);
+ _ ->
+ next_event(StateName, no_record, State0, Actions)
+ end;
+next_event(StateName, Record,
+ #state{connection_states = #{current_read := #{epoch := CurrentEpoch}}} = State0, Actions) ->
+ case Record of
+ no_record ->
+ {next_state, StateName, State0, Actions};
+ #ssl_tls{epoch = CurrentEpoch,
+ version = Version} = Record ->
+ State = dtls_version(StateName, Version, State0),
+ {next_state, StateName, State,
+ [{next_event, internal, {protocol_record, Record}} | Actions]};
+ #ssl_tls{epoch = _Epoch,
+ version = _Version} = _Record ->
+ %% TODO maybe buffer later epoch
+ {Record, State} = next_record(State0),
+ next_event(StateName, Record, State, Actions);
+ #alert{} = Alert ->
+ {next_state, StateName, State0, [{next_event, internal, Alert} | Actions]}
+ end.
+
+handle_common_event(internal, #alert{} = Alert, StateName,
+ #state{negotiated_version = Version} = State) ->
+ handle_own_alert(Alert, Version, StateName, State);
+%%% DTLS record protocol level handshake messages
+handle_common_event(internal, #ssl_tls{type = ?HANDSHAKE,
+ fragment = Data},
+ StateName,
+ #state{protocol_buffers = Buffers0,
+ negotiated_version = Version} = State0) ->
+ try
+ case dtls_handshake:get_dtls_handshake(Version, Data, Buffers0) of
+ {[], Buffers} ->
+ {Record, State} = next_record(State0#state{protocol_buffers = Buffers}),
+ next_event(StateName, Record, State);
+ {Packets, Buffers} ->
+ State = State0#state{protocol_buffers = Buffers},
+ Events = dtls_handshake_events(Packets),
+ {next_state, StateName,
+ State#state{unprocessed_handshake_events = unprocessed_events(Events)}, Events}
+ end
+ catch throw:#alert{} = Alert ->
+ handle_own_alert(Alert, Version, StateName, State0)
+ end;
+%%% DTLS record protocol level application data messages
+handle_common_event(internal, #ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, StateName, State) ->
+ {next_state, StateName, State, [{next_event, internal, {application_data, Data}}]};
+%%% DTLS record protocol level change cipher messages
+handle_common_event(internal, #ssl_tls{type = ?CHANGE_CIPHER_SPEC, fragment = Data}, StateName, State) ->
+ {next_state, StateName, State, [{next_event, internal, #change_cipher_spec{type = Data}}]};
+%%% DTLS record protocol level Alert messages
+handle_common_event(internal, #ssl_tls{type = ?ALERT, fragment = EncAlerts}, StateName,
+ #state{negotiated_version = Version} = State) ->
+ case decode_alerts(EncAlerts) of
+ Alerts = [_|_] ->
+ handle_alerts(Alerts, {next_state, StateName, State});
+ #alert{} = Alert ->
+ handle_own_alert(Alert, Version, StateName, State)
+ end;
+%% Ignore unknown TLS record level protocol messages
+handle_common_event(internal, #ssl_tls{type = _Unknown}, StateName, State) ->
+ {next_state, StateName, State}.
+
+%%====================================================================
+%% Handshake handling
+%%====================================================================
+
+renegotiate(#state{role = client} = State, Actions) ->
+ %% Handle same way as if server requested
+ %% the renegotiation
+ {next_state, connection, State,
+ [{next_event, internal, #hello_request{}} | Actions]};
+
+renegotiate(#state{role = server} = State0, Actions) ->
+ HelloRequest = ssl_handshake:hello_request(),
+ State1 = prepare_flight(State0),
+ {State2, MoreActions} = send_handshake(HelloRequest, State1),
+ {Record, State} = next_record(State2),
+ next_event(hello, Record, State, Actions ++ MoreActions).
+
+send_handshake(Handshake, #state{connection_states = ConnectionStates} = State) ->
#{epoch := Epoch} = ssl_record:current_connection_state(ConnectionStates, write),
- send_handshake_flight(queue_handshake(Handshake, States), Epoch).
+ send_handshake_flight(queue_handshake(Handshake, State), Epoch).
queue_handshake(Handshake0, #state{tls_handshake_history = Hist0,
negotiated_version = Version,
@@ -104,63 +326,6 @@ queue_handshake(Handshake0, #state{tls_handshake_history = Hist0,
next_sequence => Seq +1},
tls_handshake_history = Hist}.
-
-send_handshake_flight(#state{socket = Socket,
- transport_cb = Transport,
- flight_buffer = #{handshakes := Flight,
- change_cipher_spec := undefined},
- negotiated_version = Version,
- connection_states = ConnectionStates0} = State0, Epoch) ->
- %% TODO remove hardcoded Max size
- {Encoded, ConnectionStates} =
- encode_handshake_flight(lists:reverse(Flight), Version, 1400, Epoch, ConnectionStates0),
- send(Transport, Socket, Encoded),
- {State0#state{connection_states = ConnectionStates}, []};
-
-send_handshake_flight(#state{socket = Socket,
- transport_cb = Transport,
- flight_buffer = #{handshakes := [_|_] = Flight0,
- change_cipher_spec := ChangeCipher,
- handshakes_after_change_cipher_spec := []},
- negotiated_version = Version,
- connection_states = ConnectionStates0} = State0, Epoch) ->
- {HsBefore, ConnectionStates1} =
- encode_handshake_flight(lists:reverse(Flight0), Version, 1400, Epoch, ConnectionStates0),
- {EncChangeCipher, ConnectionStates} = encode_change_cipher(ChangeCipher, Version, Epoch, ConnectionStates1),
-
- send(Transport, Socket, [HsBefore, EncChangeCipher]),
- {State0#state{connection_states = ConnectionStates}, []};
-
-send_handshake_flight(#state{socket = Socket,
- transport_cb = Transport,
- flight_buffer = #{handshakes := [_|_] = Flight0,
- change_cipher_spec := ChangeCipher,
- handshakes_after_change_cipher_spec := Flight1},
- negotiated_version = Version,
- connection_states = ConnectionStates0} = State0, Epoch) ->
- {HsBefore, ConnectionStates1} =
- encode_handshake_flight(lists:reverse(Flight0), Version, 1400, Epoch-1, ConnectionStates0),
- {EncChangeCipher, ConnectionStates2} =
- encode_change_cipher(ChangeCipher, Version, Epoch-1, ConnectionStates1),
- {HsAfter, ConnectionStates} =
- encode_handshake_flight(lists:reverse(Flight1), Version, 1400, Epoch, ConnectionStates2),
- send(Transport, Socket, [HsBefore, EncChangeCipher, HsAfter]),
- {State0#state{connection_states = ConnectionStates}, []};
-
-send_handshake_flight(#state{socket = Socket,
- transport_cb = Transport,
- flight_buffer = #{handshakes := [],
- change_cipher_spec := ChangeCipher,
- handshakes_after_change_cipher_spec := Flight1},
- negotiated_version = Version,
- connection_states = ConnectionStates0} = State0, Epoch) ->
- {EncChangeCipher, ConnectionStates1} =
- encode_change_cipher(ChangeCipher, Version, Epoch-1, ConnectionStates0),
- {HsAfter, ConnectionStates} =
- encode_handshake_flight(lists:reverse(Flight1), Version, 1400, Epoch, ConnectionStates1),
- send(Transport, Socket, [EncChangeCipher, HsAfter]),
- {State0#state{connection_states = ConnectionStates}, []}.
-
queue_change_cipher(ChangeCipher, #state{flight_buffer = Flight,
connection_states = ConnectionStates0} = State) ->
ConnectionStates =
@@ -168,6 +333,37 @@ queue_change_cipher(ChangeCipher, #state{flight_buffer = Flight,
State#state{flight_buffer = Flight#{change_cipher_spec => ChangeCipher},
connection_states = ConnectionStates}.
+reinit(State) ->
+ %% To be API compatible with TLS NOOP here
+ reinit_handshake_data(State).
+reinit_handshake_data(#state{protocol_buffers = Buffers} = State) ->
+ State#state{premaster_secret = undefined,
+ public_key_info = undefined,
+ tls_handshake_history = ssl_handshake:init_handshake_history(),
+ flight_state = {retransmit, ?INITIAL_RETRANSMIT_TIMEOUT},
+ flight_buffer = new_flight(),
+ protocol_buffers =
+ Buffers#protocol_buffers{
+ dtls_handshake_next_seq = 0,
+ dtls_handshake_next_fragments = [],
+ dtls_handshake_later_fragments = []
+ }}.
+
+select_sni_extension(#client_hello{extensions = HelloExtensions}) ->
+ HelloExtensions#hello_extensions.sni;
+select_sni_extension(_) ->
+ undefined.
+
+empty_connection_state(ConnectionEnd, BeastMitigation) ->
+ Empty = ssl_record:empty_connection_state(ConnectionEnd, BeastMitigation),
+ dtls_record:empty_connection_state(Empty).
+
+%%====================================================================
+%% Alert and close handling
+%%====================================================================
+encode_alert(#alert{} = Alert, Version, ConnectionStates) ->
+ dtls_record:encode_alert_record(Alert, Version, ConnectionStates).
+
send_alert(Alert, #state{negotiated_version = Version,
socket = Socket,
transport_cb = Transport,
@@ -177,70 +373,65 @@ send_alert(Alert, #state{negotiated_version = Version,
send(Transport, Socket, BinMsg),
State0#state{connection_states = ConnectionStates}.
+send_alert_in_connection(Alert, State) ->
+ _ = send_alert(Alert, State),
+ ok.
+
close(downgrade, _,_,_,_) ->
ok;
%% Other
close(_, Socket, Transport, _,_) ->
dtls_socket:close(Transport,Socket).
-reinit_handshake_data(#state{protocol_buffers = Buffers} = State) ->
- State#state{premaster_secret = undefined,
- public_key_info = undefined,
- tls_handshake_history = ssl_handshake:init_handshake_history(),
- flight_state = {retransmit, ?INITIAL_RETRANSMIT_TIMEOUT},
- protocol_buffers =
- Buffers#protocol_buffers{
- dtls_handshake_next_seq = 0,
- dtls_handshake_next_fragments = [],
- dtls_handshake_later_fragments = []
- }}.
+protocol_name() ->
+ "DTLS".
+
+%%====================================================================
+%% Data handling
+%%====================================================================
-select_sni_extension(#client_hello{extensions = HelloExtensions}) ->
- HelloExtensions#hello_extensions.sni;
-select_sni_extension(_) ->
- undefined.
+encode_data(Data, Version, ConnectionStates0)->
+ dtls_record:encode_data(Data, Version, ConnectionStates0).
+
+passive_receive(State0 = #state{user_data_buffer = Buffer}, StateName) ->
+ case Buffer of
+ <<>> ->
+ {Record, State} = next_record(State0),
+ next_event(StateName, Record, State);
+ _ ->
+ {Record, State} = ssl_connection:read_application_data(<<>>, State0),
+ next_event(StateName, Record, State)
+ end.
+next_record_if_active(State =
+ #state{socket_options =
+ #socket_options{active = false}}) ->
+ {no_record ,State};
+
+next_record_if_active(State) ->
+ next_record(State).
+
+send(Transport, {_, {{_,_}, _} = Socket}, Data) ->
+ send(Transport, Socket, Data);
+send(Transport, Socket, Data) ->
+ dtls_socket:send(Transport, Socket, Data).
socket(Pid, Transport, Socket, Connection, _) ->
dtls_socket:socket(Pid, Transport, Socket, Connection).
setopts(Transport, Socket, Other) ->
dtls_socket:setopts(Transport, Socket, Other).
+
getopts(Transport, Socket, Tag) ->
dtls_socket:getopts(Transport, Socket, Tag).
-%%====================================================================
-%% tls_connection_sup API
-%%====================================================================
-
%%--------------------------------------------------------------------
--spec start_link(atom(), host(), inet:port_number(), port(), list(), pid(), tuple()) ->
- {ok, pid()} | ignore | {error, reason()}.
-%%
-%% Description: Creates a gen_fsm process which calls Module:init/1 to
-%% initialize. To ensure a synchronized start-up procedure, this function
-%% does not return until Module:init/1 has returned.
+%% State functions
%%--------------------------------------------------------------------
-start_link(Role, Host, Port, Socket, Options, User, CbInfo) ->
- {ok, proc_lib:spawn_link(?MODULE, init, [[Role, Host, Port, Socket, Options, User, CbInfo]])}.
-
-init([Role, Host, Port, Socket, Options, User, CbInfo]) ->
- process_flag(trap_exit, true),
- State0 = initial_state(Role, Host, Port, Socket, Options, User, CbInfo),
- try
- State = ssl_connection:ssl_config(State0#state.ssl_options, Role, State0),
- gen_statem:enter_loop(?MODULE, [], init, State)
- catch
- throw:Error ->
- gen_statem:enter_loop(?MODULE, [], error, {Error,State0})
- end.
-
-callback_mode() ->
- [state_functions, state_enter].
-
%%--------------------------------------------------------------------
-%% State functions
+-spec init(gen_statem:event_type(),
+ {start, timeout()} | term(), #state{}) ->
+ gen_statem:state_function_result().
%%--------------------------------------------------------------------
-
init(enter, _, State) ->
{keep_state, State};
init({call, From}, {start, Timeout},
@@ -269,27 +460,35 @@ init({call, From}, {start, Timeout},
},
{Record, State} = next_record(State3),
next_event(hello, Record, State, Actions);
-init({call, _} = Type, Event, #state{role = server, transport_cb = gen_udp} = State) ->
- Result = ssl_connection:init(Type, Event,
- State#state{flight_state = {retransmit, ?INITIAL_RETRANSMIT_TIMEOUT},
- protocol_specific = #{current_cookie_secret => dtls_v1:cookie_secret(),
- previous_cookie_secret => <<>>}},
- ?MODULE),
+init({call, _} = Type, Event, #state{role = server, data_tag = udp} = State) ->
+ Result = gen_handshake(?FUNCTION_NAME, Type, Event,
+ State#state{flight_state = {retransmit, ?INITIAL_RETRANSMIT_TIMEOUT},
+ protocol_specific = #{current_cookie_secret => dtls_v1:cookie_secret(),
+ previous_cookie_secret => <<>>,
+ ignored_alerts => 0,
+ max_ignored_alerts => 10}}),
erlang:send_after(dtls_v1:cookie_timeout(), self(), new_cookie_secret),
Result;
-
+
init({call, _} = Type, Event, #state{role = server} = State) ->
%% I.E. DTLS over sctp
- ssl_connection:init(Type, Event, State#state{flight_state = reliable}, ?MODULE);
+ gen_handshake(?FUNCTION_NAME, Type, Event, State#state{flight_state = reliable});
init(Type, Event, State) ->
- ssl_connection:init(Type, Event, State, ?MODULE).
-
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
+
+%%--------------------------------------------------------------------
+-spec error(gen_statem:event_type(),
+ {start, timeout()} | term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
error(enter, _, State) ->
{keep_state, State};
-error({call, From}, {start, _Timeout}, {Error, State}) ->
- {stop_and_reply, normal, {reply, From, {error, Error}}, State};
-error({call, From}, Msg, State) ->
- handle_call(Msg, From, error, State);
+error({call, From}, {start, _Timeout},
+ #state{protocol_specific = #{error := Error}} = State) ->
+ ssl_connection:stop_and_reply(
+ normal, {reply, From, {error, Error}}, State);
+error({call, _} = Call, Msg, State) ->
+ gen_handshake(?FUNCTION_NAME, Call, Msg, State);
error(_, _, _) ->
{keep_state_and_data, [postpone]}.
@@ -305,10 +504,11 @@ hello(enter, _, #state{role = client} = State0) ->
{State, Actions} = handle_flight_timer(State0),
{keep_state, State, Actions};
hello(internal, #client_hello{cookie = <<>>,
- client_version = Version} = Hello, #state{role = server,
- transport_cb = Transport,
- socket = Socket,
- protocol_specific = #{current_cookie_secret := Secret}} = State0) ->
+ client_version = Version} = Hello,
+ #state{role = server,
+ transport_cb = Transport,
+ socket = Socket,
+ protocol_specific = #{current_cookie_secret := Secret}} = State0) ->
{ok, {IP, Port}} = dtls_socket:peername(Transport, Socket),
Cookie = dtls_handshake:cookie(Secret, IP, Port, Hello),
%% FROM RFC 6347 regarding HelloVerifyRequest message:
@@ -321,25 +521,7 @@ hello(internal, #client_hello{cookie = <<>>,
State1 = prepare_flight(State0#state{negotiated_version = Version}),
{State2, Actions} = send_handshake(VerifyRequest, State1),
{Record, State} = next_record(State2),
- next_event(hello, Record, State#state{tls_handshake_history = ssl_handshake:init_handshake_history()}, Actions);
-hello(internal, #client_hello{cookie = Cookie} = Hello, #state{role = server,
- transport_cb = Transport,
- socket = Socket,
- protocol_specific = #{current_cookie_secret := Secret,
- previous_cookie_secret := PSecret}} = State0) ->
- {ok, {IP, Port}} = dtls_socket:peername(Transport, Socket),
- case dtls_handshake:cookie(Secret, IP, Port, Hello) of
- Cookie ->
- handle_client_hello(Hello, State0);
- _ ->
- case dtls_handshake:cookie(PSecret, IP, Port, Hello) of
- Cookie ->
- handle_client_hello(Hello, State0);
- _ ->
- %% Handle bad cookie as new cookie request RFC 6347 4.1.2
- hello(internal, Hello#client_hello{cookie = <<>>}, State0)
- end
- end;
+ next_event(?FUNCTION_NAME, Record, State#state{tls_handshake_history = ssl_handshake:init_handshake_history()}, Actions);
hello(internal, #hello_verify_request{cookie = Cookie}, #state{role = client,
host = Host, port = Port,
ssl_options = SslOpts,
@@ -350,19 +532,48 @@ hello(internal, #hello_verify_request{cookie = Cookie}, #state{role = client,
session_cache = Cache,
session_cache_cb = CacheCb
} = State0) ->
- State1 = prepare_flight(State0#state{tls_handshake_history = ssl_handshake:init_handshake_history()}),
+
Hello = dtls_handshake:client_hello(Host, Port, Cookie, ConnectionStates0,
SslOpts,
Cache, CacheCb, Renegotiation, OwnCert),
Version = Hello#client_hello.client_version,
- HelloVersion = dtls_record:lowest_protocol_version(SslOpts#ssl_options.versions),
- {State2, Actions} = send_handshake(Hello, State1#state{negotiated_version = HelloVersion}),
+ State1 = prepare_flight(State0#state{tls_handshake_history = ssl_handshake:init_handshake_history()}),
+
+ {State2, Actions} = send_handshake(Hello, State1),
State3 = State2#state{negotiated_version = Version, %% Requested version
session =
Session0#session{session_id =
Hello#client_hello.session_id}},
{Record, State} = next_record(State3),
- next_event(hello, Record, State, Actions);
+ next_event(?FUNCTION_NAME, Record, State, Actions);
+hello(internal, #client_hello{extensions = Extensions} = Hello, #state{ssl_options = #ssl_options{handshake = hello},
+ start_or_recv_from = From} = State) ->
+ {next_state, user_hello, State#state{start_or_recv_from = undefined,
+ hello = Hello},
+ [{reply, From, {ok, ssl_connection:map_extensions(Extensions)}}]};
+hello(internal, #server_hello{extensions = Extensions} = Hello, #state{ssl_options = #ssl_options{handshake = hello},
+ start_or_recv_from = From} = State) ->
+ {next_state, user_hello, State#state{start_or_recv_from = undefined,
+ hello = Hello},
+ [{reply, From, {ok, ssl_connection:map_extensions(Extensions)}}]};
+hello(internal, #client_hello{cookie = Cookie} = Hello, #state{role = server,
+ transport_cb = Transport,
+ socket = Socket,
+ protocol_specific = #{current_cookie_secret := Secret,
+ previous_cookie_secret := PSecret}} = State0) ->
+ {ok, {IP, Port}} = dtls_socket:peername(Transport, Socket),
+ case dtls_handshake:cookie(Secret, IP, Port, Hello) of
+ Cookie ->
+ handle_client_hello(Hello, State0);
+ _ ->
+ case dtls_handshake:cookie(PSecret, IP, Port, Hello) of
+ Cookie ->
+ handle_client_hello(Hello, State0);
+ _ ->
+ %% Handle bad cookie as new cookie request RFC 6347 4.1.2
+ hello(internal, Hello#client_hello{cookie = <<>>}, State0)
+ end
+ end;
hello(internal, #server_hello{} = Hello,
#state{connection_states = ConnectionStates0,
negotiated_version = ReqVersion,
@@ -371,92 +582,130 @@ hello(internal, #server_hello{} = Hello,
ssl_options = SslOptions} = State) ->
case dtls_handshake:hello(Hello, SslOptions, ConnectionStates0, Renegotiation) of
#alert{} = Alert ->
- ssl_connection:handle_own_alert(Alert, ReqVersion, hello, State);
+ handle_own_alert(Alert, ReqVersion, ?FUNCTION_NAME, State);
{Version, NewId, ConnectionStates, ProtoExt, Protocol} ->
ssl_connection:handle_session(Hello,
Version, NewId, ConnectionStates, ProtoExt, Protocol, State)
end;
hello(internal, {handshake, {#client_hello{cookie = <<>>} = Handshake, _}}, State) ->
%% Initial hello should not be in handshake history
- {next_state, hello, State, [{next_event, internal, Handshake}]};
+ {next_state, ?FUNCTION_NAME, State, [{next_event, internal, Handshake}]};
hello(internal, {handshake, {#hello_verify_request{} = Handshake, _}}, State) ->
%% hello_verify should not be in handshake history
- {next_state, hello, State, [{next_event, internal, Handshake}]};
+ {next_state, ?FUNCTION_NAME, State, [{next_event, internal, Handshake}]};
+hello(internal, #change_cipher_spec{type = <<1>>}, State0) ->
+ {State1, Actions0} = send_handshake_flight(State0, retransmit_epoch(?FUNCTION_NAME, State0)),
+ {Record, State2} = next_record(State1),
+ {next_state, ?FUNCTION_NAME, State, Actions} = next_event(?FUNCTION_NAME, Record, State2, Actions0),
+ %% This will reset the retransmission timer by repeating the enter state event
+ {repeat_state, State, Actions};
hello(info, Event, State) ->
- handle_info(Event, hello, State);
+ gen_info(Event, ?FUNCTION_NAME, State);
hello(state_timeout, Event, State) ->
- handle_state_timeout(Event, hello, State);
+ handle_state_timeout(Event, ?FUNCTION_NAME, State);
hello(Type, Event, State) ->
- ssl_connection:hello(Type, Event, State, ?MODULE).
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
+user_hello(enter, _, State) ->
+ {keep_state, State};
+user_hello(Type, Event, State) ->
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
+
+%%--------------------------------------------------------------------
+-spec abbreviated(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
abbreviated(enter, _, State0) ->
{State, Actions} = handle_flight_timer(State0),
{keep_state, State, Actions};
abbreviated(info, Event, State) ->
- handle_info(Event, abbreviated, State);
+ gen_info(Event, ?FUNCTION_NAME, State);
abbreviated(internal = Type,
#change_cipher_spec{type = <<1>>} = Event,
#state{connection_states = ConnectionStates0} = State) ->
ConnectionStates1 = dtls_record:save_current_connection_state(ConnectionStates0, read),
ConnectionStates = dtls_record:next_epoch(ConnectionStates1, read),
- ssl_connection:abbreviated(Type, Event, State#state{connection_states = ConnectionStates}, ?MODULE);
+ gen_handshake(?FUNCTION_NAME, Type, Event, State#state{connection_states = ConnectionStates});
abbreviated(internal = Type, #finished{} = Event, #state{connection_states = ConnectionStates} = State) ->
- ssl_connection:abbreviated(Type, Event,
- prepare_flight(State#state{connection_states = ConnectionStates,
- flight_state = connection}), ?MODULE);
+ gen_handshake(?FUNCTION_NAME, Type, Event,
+ prepare_flight(State#state{connection_states = ConnectionStates,
+ flight_state = connection}));
abbreviated(state_timeout, Event, State) ->
- handle_state_timeout(Event, abbreviated, State);
+ handle_state_timeout(Event, ?FUNCTION_NAME, State);
abbreviated(Type, Event, State) ->
- ssl_connection:abbreviated(Type, Event, State, ?MODULE).
-
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
+%%--------------------------------------------------------------------
+-spec certify(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
certify(enter, _, State0) ->
{State, Actions} = handle_flight_timer(State0),
{keep_state, State, Actions};
certify(info, Event, State) ->
- handle_info(Event, certify, State);
+ gen_info(Event, ?FUNCTION_NAME, State);
certify(internal = Type, #server_hello_done{} = Event, State) ->
ssl_connection:certify(Type, Event, prepare_flight(State), ?MODULE);
+certify(internal, #change_cipher_spec{type = <<1>>}, State0) ->
+ {State1, Actions0} = send_handshake_flight(State0, retransmit_epoch(?FUNCTION_NAME, State0)),
+ {Record, State2} = next_record(State1),
+ {next_state, ?FUNCTION_NAME, State, Actions} = next_event(?FUNCTION_NAME, Record, State2, Actions0),
+ %% This will reset the retransmission timer by repeating the enter state event
+ {repeat_state, State, Actions};
certify(state_timeout, Event, State) ->
- handle_state_timeout(Event, certify, State);
+ handle_state_timeout(Event, ?FUNCTION_NAME, State);
certify(Type, Event, State) ->
- ssl_connection:certify(Type, Event, State, ?MODULE).
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
+%%--------------------------------------------------------------------
+-spec cipher(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
cipher(enter, _, State0) ->
{State, Actions} = handle_flight_timer(State0),
{keep_state, State, Actions};
cipher(info, Event, State) ->
- handle_info(Event, cipher, State);
+ gen_info(Event, ?FUNCTION_NAME, State);
cipher(internal = Type, #change_cipher_spec{type = <<1>>} = Event,
#state{connection_states = ConnectionStates0} = State) ->
ConnectionStates1 = dtls_record:save_current_connection_state(ConnectionStates0, read),
ConnectionStates = dtls_record:next_epoch(ConnectionStates1, read),
- ssl_connection:cipher(Type, Event, State#state{connection_states = ConnectionStates}, ?MODULE);
+ ssl_connection:?FUNCTION_NAME(Type, Event, State#state{connection_states = ConnectionStates}, ?MODULE);
cipher(internal = Type, #finished{} = Event, #state{connection_states = ConnectionStates} = State) ->
- ssl_connection:cipher(Type, Event,
- prepare_flight(State#state{connection_states = ConnectionStates,
- flight_state = connection}),
- ?MODULE);
+ ssl_connection:?FUNCTION_NAME(Type, Event,
+ prepare_flight(State#state{connection_states = ConnectionStates,
+ flight_state = connection}),
+ ?MODULE);
cipher(state_timeout, Event, State) ->
- handle_state_timeout(Event, cipher, State);
+ handle_state_timeout(Event, ?FUNCTION_NAME, State);
cipher(Type, Event, State) ->
- ssl_connection:cipher(Type, Event, State, ?MODULE).
+ ssl_connection:?FUNCTION_NAME(Type, Event, State, ?MODULE).
+%%--------------------------------------------------------------------
+-spec connection(gen_statem:event_type(),
+ #hello_request{} | #client_hello{}| term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
connection(enter, _, State) ->
{keep_state, State};
connection(info, Event, State) ->
- handle_info(Event, connection, State);
+ gen_info(Event, ?FUNCTION_NAME, State);
connection(internal, #hello_request{}, #state{host = Host, port = Port,
- session = #session{own_certificate = Cert} = Session0,
- session_cache = Cache, session_cache_cb = CacheCb,
- ssl_options = SslOpts,
- connection_states = ConnectionStates0,
- renegotiation = {Renegotiation, _}} = State0) ->
+ session = #session{own_certificate = Cert} = Session0,
+ session_cache = Cache, session_cache_cb = CacheCb,
+ ssl_options = SslOpts,
+ connection_states = ConnectionStates0,
+ renegotiation = {Renegotiation, _}} = State0) ->
+
Hello = dtls_handshake:client_hello(Host, Port, ConnectionStates0, SslOpts,
Cache, CacheCb, Renegotiation, Cert),
- {State1, Actions} = send_handshake(Hello, State0),
+ Version = Hello#client_hello.client_version,
+ HelloVersion = dtls_record:hello_version(Version, SslOpts#ssl_options.versions),
+ State1 = prepare_flight(State0),
+ {State2, Actions} = send_handshake(Hello, State1#state{negotiated_version = HelloVersion}),
{Record, State} =
next_record(
- State1#state{session = Session0#session{session_id
+ State2#state{flight_state = {retransmit, ?INITIAL_RETRANSMIT_TIMEOUT},
+ session = Session0#session{session_id
= Hello#client_hello.session_id}}),
next_event(hello, Record, State, Actions);
connection(internal, #client_hello{} = Hello, #state{role = server, allow_renegotiate = true} = State) ->
@@ -466,147 +715,41 @@ connection(internal, #client_hello{} = Hello, #state{role = server, allow_renego
%% initiated renegotiation we will disallow many client initiated
%% renegotiations immediately after each other.
erlang:send_after(?WAIT_TO_ALLOW_RENEGOTIATION, self(), allow_renegotiate),
- {next_state, hello, State#state{allow_renegotiate = false}, [{next_event, internal, Hello}]};
+ {next_state, hello, State#state{allow_renegotiate = false, renegotiation = {true, peer}},
+ [{next_event, internal, Hello}]};
connection(internal, #client_hello{}, #state{role = server, allow_renegotiate = false} = State0) ->
Alert = ?ALERT_REC(?WARNING, ?NO_RENEGOTIATION),
State1 = send_alert(Alert, State0),
{Record, State} = ssl_connection:prepare_connection(State1, ?MODULE),
- next_event(connection, Record, State);
+ next_event(?FUNCTION_NAME, Record, State);
+connection({call, From}, {application_data, Data}, State) ->
+ try
+ send_application_data(Data, From, ?FUNCTION_NAME, State)
+ catch throw:Error ->
+ ssl_connection:hibernate_after(?FUNCTION_NAME, State, [{reply, From, Error}])
+ end;
connection(Type, Event, State) ->
- ssl_connection:connection(Type, Event, State, ?MODULE).
+ ssl_connection:?FUNCTION_NAME(Type, Event, State, ?MODULE).
%%TODO does this make sense for DTLS ?
+%%--------------------------------------------------------------------
+-spec downgrade(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
downgrade(enter, _, State) ->
{keep_state, State};
downgrade(Type, Event, State) ->
- ssl_connection:downgrade(Type, Event, State, ?MODULE).
+ ssl_connection:?FUNCTION_NAME(Type, Event, State, ?MODULE).
%%--------------------------------------------------------------------
-%% Description: This function is called by a gen_fsm when it receives any
-%% other message than a synchronous or asynchronous event
-%% (or a system message).
+%% gen_statem callbacks
%%--------------------------------------------------------------------
+callback_mode() ->
+ [state_functions, state_enter].
-%% raw data from socket, unpack records
-handle_info({Protocol, _, _, _, Data}, StateName,
- #state{data_tag = Protocol} = State0) ->
- case next_dtls_record(Data, State0) of
- {Record, State} ->
- next_event(StateName, Record, State);
- #alert{} = Alert ->
- ssl_connection:handle_normal_shutdown(Alert, StateName, State0),
- {stop, {shutdown, own_alert}}
- end;
-handle_info({CloseTag, Socket}, StateName,
- #state{socket = Socket,
- socket_options = #socket_options{active = Active},
- protocol_buffers = #protocol_buffers{dtls_cipher_texts = CTs},
- close_tag = CloseTag,
- negotiated_version = Version} = State) ->
- %% Note that as of DTLS 1.2 (TLS 1.1),
- %% failure to properly close a connection no longer requires that a
- %% session not be resumed. This is a change from DTLS 1.0 to conform
- %% with widespread implementation practice.
- case (Active == false) andalso (CTs =/= []) of
- false ->
- case Version of
- {254, N} when N =< 253 ->
- ok;
- _ ->
- %% As invalidate_sessions here causes performance issues,
- %% we will conform to the widespread implementation
- %% practice and go aginst the spec
- %%invalidate_session(Role, Host, Port, Session)
- ok
- end,
- ssl_connection:handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
- {stop, {shutdown, transport_closed}};
- true ->
- %% Fixes non-delivery of final DTLS record in {active, once}.
- %% Basically allows the application the opportunity to set {active, once} again
- %% and then receive the final message.
- next_event(StateName, no_record, State)
- end;
-
-handle_info(new_cookie_secret, StateName,
- #state{protocol_specific = #{current_cookie_secret := Secret} = CookieInfo} = State) ->
- erlang:send_after(dtls_v1:cookie_timeout(), self(), new_cookie_secret),
- {next_state, StateName, State#state{protocol_specific =
- CookieInfo#{current_cookie_secret => dtls_v1:cookie_secret(),
- previous_cookie_secret => Secret}}};
-handle_info(Msg, StateName, State) ->
- ssl_connection:handle_info(Msg, StateName, State).
-
-
-handle_call(Event, From, StateName, State) ->
- ssl_connection:handle_call(Event, From, StateName, State, ?MODULE).
-
-handle_common_event(internal, #alert{} = Alert, StateName,
- #state{negotiated_version = Version} = State) ->
- ssl_connection:handle_own_alert(Alert, Version, StateName, State);
-%%% DTLS record protocol level handshake messages
-handle_common_event(internal, #ssl_tls{type = ?HANDSHAKE,
- fragment = Data},
- StateName,
- #state{protocol_buffers = Buffers0,
- negotiated_version = Version} = State0) ->
- try
- case dtls_handshake:get_dtls_handshake(Version, Data, Buffers0) of
- {[], Buffers} ->
- {Record, State} = next_record(State0#state{protocol_buffers = Buffers}),
- next_event(StateName, Record, State);
- {Packets, Buffers} ->
- State = State0#state{protocol_buffers = Buffers},
- Events = dtls_handshake_events(Packets),
- {next_state, StateName,
- State#state{unprocessed_handshake_events = unprocessed_events(Events)}, Events}
- end
- catch throw:#alert{} = Alert ->
- ssl_connection:handle_own_alert(Alert, Version, StateName, State0)
- end;
-%%% DTLS record protocol level application data messages
-handle_common_event(internal, #ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, StateName, State) ->
- {next_state, StateName, State, [{next_event, internal, {application_data, Data}}]};
-%%% DTLS record protocol level change cipher messages
-handle_common_event(internal, #ssl_tls{type = ?CHANGE_CIPHER_SPEC, fragment = Data}, StateName, State) ->
- {next_state, StateName, State, [{next_event, internal, #change_cipher_spec{type = Data}}]};
-%%% DTLS record protocol level Alert messages
-handle_common_event(internal, #ssl_tls{type = ?ALERT, fragment = EncAlerts}, StateName,
- #state{negotiated_version = Version} = State) ->
- case decode_alerts(EncAlerts) of
- Alerts = [_|_] ->
- handle_alerts(Alerts, {next_state, StateName, State});
- #alert{} = Alert ->
- ssl_connection:handle_own_alert(Alert, Version, StateName, State)
- end;
-%% Ignore unknown TLS record level protocol messages
-handle_common_event(internal, #ssl_tls{type = _Unknown}, StateName, State) ->
- {next_state, StateName, State}.
-
-handle_state_timeout(flight_retransmission_timeout, StateName,
- #state{flight_state = {retransmit, NextTimeout}} = State0) ->
- {State1, Actions} = send_handshake_flight(State0#state{flight_state = {retransmit, NextTimeout}},
- retransmit_epoch(StateName, State0)),
- {Record, State} = next_record(State1),
- next_event(StateName, Record, State, Actions).
-
-send(Transport, {_, {{_,_}, _} = Socket}, Data) ->
- send(Transport, Socket, Data);
-send(Transport, Socket, Data) ->
- dtls_socket:send(Transport, Socket, Data).
-%%--------------------------------------------------------------------
-%% Description:This function is called by a gen_fsm when it is about
-%% to terminate. It should be the opposite of Module:init/1 and do any
-%% necessary cleaning up. When it returns, the gen_fsm terminates with
-%% Reason. The return value is ignored.
-%%--------------------------------------------------------------------
terminate(Reason, StateName, State) ->
ssl_connection:terminate(Reason, StateName, State).
-%%--------------------------------------------------------------------
-%% code_change(OldVsn, StateName, State, Extra) -> {ok, StateName, NewState}
-%% Description: Convert process state when code is changed
-%%--------------------------------------------------------------------
code_change(_OldVsn, StateName, State, _Extra) ->
{ok, StateName, State}.
@@ -616,55 +759,6 @@ format_status(Type, Data) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-handle_client_hello(#client_hello{client_version = ClientVersion} = Hello,
- #state{connection_states = ConnectionStates0,
- port = Port, session = #session{own_certificate = Cert} = Session0,
- renegotiation = {Renegotiation, _},
- session_cache = Cache,
- session_cache_cb = CacheCb,
- negotiated_protocol = CurrentProtocol,
- key_algorithm = KeyExAlg,
- ssl_options = SslOpts} = State0) ->
-
- case dtls_handshake:hello(Hello, SslOpts, {Port, Session0, Cache, CacheCb,
- ConnectionStates0, Cert, KeyExAlg}, Renegotiation) of
- #alert{} = Alert ->
- ssl_connection:handle_own_alert(Alert, ClientVersion, hello, State0);
- {Version, {Type, Session},
- ConnectionStates, Protocol0, ServerHelloExt, HashSign} ->
- Protocol = case Protocol0 of
- undefined -> CurrentProtocol;
- _ -> Protocol0
- end,
-
- State = prepare_flight(State0#state{connection_states = ConnectionStates,
- negotiated_version = Version,
- hashsign_algorithm = HashSign,
- session = Session,
- negotiated_protocol = Protocol}),
-
- ssl_connection:hello(internal, {common_client_hello, Type, ServerHelloExt},
- State, ?MODULE)
- end.
-
-encode_handshake_flight(Flight, Version, MaxFragmentSize, Epoch, ConnectionStates) ->
- Fragments = lists:map(fun(Handshake) ->
- dtls_handshake:fragment_handshake(Handshake, MaxFragmentSize)
- end, Flight),
- dtls_record:encode_handshake(Fragments, Version, Epoch, ConnectionStates).
-
-encode_change_cipher(#change_cipher_spec{}, Version, Epoch, ConnectionStates) ->
- dtls_record:encode_change_cipher_spec(Version, Epoch, ConnectionStates).
-
-encode_data(Data, Version, ConnectionStates0)->
- dtls_record:encode_data(Data, Version, ConnectionStates0).
-
-encode_alert(#alert{} = Alert, Version, ConnectionStates) ->
- dtls_record:encode_alert_record(Alert, Version, ConnectionStates).
-
-decode_alerts(Bin) ->
- ssl_alert:decode(Bin).
-
initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, _}, User,
{CbModule, DataTag, CloseTag, ErrorTag}) ->
#ssl_options{beast_mitigation = BeastMitigation} = SSLOptions,
@@ -705,10 +799,12 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, _}, User,
flight_state = {retransmit, ?INITIAL_RETRANSMIT_TIMEOUT}
}.
-next_dtls_record(Data, #state{protocol_buffers = #protocol_buffers{
+next_dtls_record(Data, StateName, #state{protocol_buffers = #protocol_buffers{
dtls_record_buffer = Buf0,
dtls_cipher_texts = CT0} = Buffers} = State0) ->
- case dtls_record:get_dtls_records(Data, Buf0) of
+ case dtls_record:get_dtls_records(Data,
+ acceptable_record_versions(StateName, State0),
+ Buf0) of
{Records, Buf1} ->
CT1 = CT0 ++ Records,
next_record(State0#state{protocol_buffers =
@@ -718,141 +814,15 @@ next_dtls_record(Data, #state{protocol_buffers = #protocol_buffers{
Alert
end.
-next_record(#state{unprocessed_handshake_events = N} = State) when N > 0 ->
- {no_record, State#state{unprocessed_handshake_events = N-1}};
-
-next_record(#state{protocol_buffers =
- #protocol_buffers{dtls_cipher_texts = [#ssl_tls{epoch = Epoch} = CT | Rest]}
- = Buffers,
- connection_states = #{current_read := #{epoch := Epoch}} = ConnectionStates} = State) ->
- CurrentRead = dtls_record:get_connection_state_by_epoch(Epoch, ConnectionStates, read),
- case dtls_record:replay_detect(CT, CurrentRead) of
- false ->
- decode_cipher_text(State#state{connection_states = ConnectionStates}) ;
- true ->
- %% Ignore replayed record
- next_record(State#state{protocol_buffers =
- Buffers#protocol_buffers{dtls_cipher_texts = Rest},
- connection_states = ConnectionStates})
- end;
-next_record(#state{protocol_buffers =
- #protocol_buffers{dtls_cipher_texts = [#ssl_tls{epoch = Epoch} | Rest]}
- = Buffers,
- connection_states = #{current_read := #{epoch := CurrentEpoch}} = ConnectionStates} = State)
- when Epoch > CurrentEpoch ->
- %% TODO Buffer later Epoch message, drop it for now
- next_record(State#state{protocol_buffers =
- Buffers#protocol_buffers{dtls_cipher_texts = Rest},
- connection_states = ConnectionStates});
-next_record(#state{protocol_buffers =
- #protocol_buffers{dtls_cipher_texts = [ _ | Rest]}
- = Buffers,
- connection_states = ConnectionStates} = State) ->
- %% Drop old epoch message
- next_record(State#state{protocol_buffers =
- Buffers#protocol_buffers{dtls_cipher_texts = Rest},
- connection_states = ConnectionStates});
-next_record(#state{role = server,
- socket = {Listener, {Client, _}},
- transport_cb = gen_udp} = State) ->
- dtls_udp_listener:active_once(Listener, Client, self()),
- {no_record, State};
-next_record(#state{role = client,
- socket = {_Server, Socket},
- transport_cb = Transport} = State) ->
- dtls_socket:setopts(Transport, Socket, [{active,once}]),
- {no_record, State};
-next_record(State) ->
- {no_record, State}.
-
-next_record_if_active(State =
- #state{socket_options =
- #socket_options{active = false}}) ->
- {no_record ,State};
-
-next_record_if_active(State) ->
- next_record(State).
-
-passive_receive(State0 = #state{user_data_buffer = Buffer}, StateName) ->
- case Buffer of
- <<>> ->
- {Record, State} = next_record(State0),
- next_event(StateName, Record, State);
- _ ->
- {Record, State} = ssl_connection:read_application_data(<<>>, State0),
- next_event(StateName, Record, State)
- end.
-
-next_event(StateName, Record, State) ->
- next_event(StateName, Record, State, []).
+acceptable_record_versions(hello, _) ->
+ [dtls_record:protocol_version(Vsn) || Vsn <- ?ALL_DATAGRAM_SUPPORTED_VERSIONS];
+acceptable_record_versions(_, #state{negotiated_version = Version}) ->
+ [Version].
-next_event(connection = StateName, no_record,
- #state{connection_states = #{current_read := #{epoch := CurrentEpoch}}} = State0, Actions) ->
- case next_record_if_active(State0) of
- {no_record, State} ->
- ssl_connection:hibernate_after(StateName, State, Actions);
- {#ssl_tls{epoch = CurrentEpoch} = Record, State} ->
- {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]};
- {#ssl_tls{epoch = Epoch,
- type = ?HANDSHAKE,
- version = _Version}, State1} = _Record when Epoch == CurrentEpoch-1 ->
- {State2, MoreActions} = send_handshake_flight(State1, CurrentEpoch),
- {NextRecord, State} = next_record(State2),
- next_event(StateName, NextRecord, State, Actions ++ MoreActions);
- %% From FLIGHT perspective CHANGE_CIPHER_SPEC is treated as a handshake
- {#ssl_tls{epoch = Epoch,
- type = ?CHANGE_CIPHER_SPEC,
- version = _Version}, State1} = _Record when Epoch == CurrentEpoch-1 ->
- {State2, MoreActions} = send_handshake_flight(State1, CurrentEpoch),
- {NextRecord, State} = next_record(State2),
- next_event(StateName, NextRecord, State, Actions ++ MoreActions);
- {#ssl_tls{epoch = _Epoch,
- version = _Version}, State1} ->
- %% TODO maybe buffer later epoch
- {Record, State} = next_record(State1),
- next_event(StateName, Record, State, Actions);
- {#alert{} = Alert, State} ->
- {next_state, StateName, State, [{next_event, internal, Alert} | Actions]}
- end;
-next_event(connection = StateName, Record,
- #state{connection_states = #{current_read := #{epoch := CurrentEpoch}}} = State0, Actions) ->
- case Record of
- #ssl_tls{epoch = CurrentEpoch} ->
- {next_state, StateName, State0, [{next_event, internal, {protocol_record, Record}} | Actions]};
- #ssl_tls{epoch = Epoch,
- type = ?HANDSHAKE,
- version = _Version} when Epoch == CurrentEpoch-1 ->
- {State1, MoreActions} = send_handshake_flight(State0, CurrentEpoch),
- {NextRecord, State} = next_record(State1),
- next_event(StateName, NextRecord, State, Actions ++ MoreActions);
- %% From FLIGHT perspective CHANGE_CIPHER_SPEC is treated as a handshake
- #ssl_tls{epoch = Epoch,
- type = ?CHANGE_CIPHER_SPEC,
- version = _Version} when Epoch == CurrentEpoch-1 ->
- {State1, MoreActions} = send_handshake_flight(State0, CurrentEpoch),
- {NextRecord, State} = next_record(State1),
- next_event(StateName, NextRecord, State, Actions ++ MoreActions);
- _ ->
- next_event(StateName, no_record, State0, Actions)
- end;
-next_event(StateName, Record,
- #state{connection_states = #{current_read := #{epoch := CurrentEpoch}}} = State0, Actions) ->
- case Record of
- no_record ->
- {next_state, StateName, State0, Actions};
- #ssl_tls{epoch = CurrentEpoch,
- version = Version} = Record ->
- {next_state, StateName,
- dtls_version(StateName, Version, State0),
- [{next_event, internal, {protocol_record, Record}} | Actions]};
- #ssl_tls{epoch = _Epoch,
- version = _Version} = _Record ->
- %% TODO maybe buffer later epoch
- {Record, State} = next_record(State0),
- next_event(StateName, Record, State, Actions);
- #alert{} = Alert ->
- {next_state, StateName, State0, [{next_event, internal, Alert} | Actions]}
- end.
+dtls_handshake_events(Packets) ->
+ lists:map(fun(Packet) ->
+ {next_event, internal, {handshake, Packet}}
+ end, Packets).
decode_cipher_text(#state{protocol_buffers = #protocol_buffers{dtls_cipher_texts = [ CT | Rest]} = Buffers,
connection_states = ConnStates0} = State) ->
@@ -870,6 +840,177 @@ dtls_version(hello, Version, #state{role = server} = State) ->
dtls_version(_,_, State) ->
State.
+handle_client_hello(#client_hello{client_version = ClientVersion} = Hello,
+ #state{connection_states = ConnectionStates0,
+ port = Port, session = #session{own_certificate = Cert} = Session0,
+ renegotiation = {Renegotiation, _},
+ session_cache = Cache,
+ session_cache_cb = CacheCb,
+ negotiated_protocol = CurrentProtocol,
+ key_algorithm = KeyExAlg,
+ ssl_options = SslOpts} = State0) ->
+
+ case dtls_handshake:hello(Hello, SslOpts, {Port, Session0, Cache, CacheCb,
+ ConnectionStates0, Cert, KeyExAlg}, Renegotiation) of
+ #alert{} = Alert ->
+ handle_own_alert(Alert, ClientVersion, hello, State0);
+ {Version, {Type, Session},
+ ConnectionStates, Protocol0, ServerHelloExt, HashSign} ->
+ Protocol = case Protocol0 of
+ undefined -> CurrentProtocol;
+ _ -> Protocol0
+ end,
+
+ State = prepare_flight(State0#state{connection_states = ConnectionStates,
+ negotiated_version = Version,
+ hashsign_algorithm = HashSign,
+ client_hello_version = ClientVersion,
+ session = Session,
+ negotiated_protocol = Protocol}),
+
+ ssl_connection:hello(internal, {common_client_hello, Type, ServerHelloExt},
+ State, ?MODULE)
+ end.
+
+
+%% raw data from socket, unpack records
+handle_info({Protocol, _, _, _, Data}, StateName,
+ #state{data_tag = Protocol} = State0) ->
+ case next_dtls_record(Data, StateName, State0) of
+ {Record, State} ->
+ next_event(StateName, Record, State);
+ #alert{} = Alert ->
+ ssl_connection:handle_normal_shutdown(Alert, StateName, State0),
+ ssl_connection:stop({shutdown, own_alert}, State0)
+ end;
+handle_info({CloseTag, Socket}, StateName,
+ #state{socket = Socket,
+ socket_options = #socket_options{active = Active},
+ protocol_buffers = #protocol_buffers{dtls_cipher_texts = CTs},
+ close_tag = CloseTag,
+ negotiated_version = Version} = State) ->
+ %% Note that as of DTLS 1.2 (TLS 1.1),
+ %% failure to properly close a connection no longer requires that a
+ %% session not be resumed. This is a change from DTLS 1.0 to conform
+ %% with widespread implementation practice.
+ case (Active == false) andalso (CTs =/= []) of
+ false ->
+ case Version of
+ {254, N} when N =< 253 ->
+ ok;
+ _ ->
+ %% As invalidate_sessions here causes performance issues,
+ %% we will conform to the widespread implementation
+ %% practice and go aginst the spec
+ %%invalidate_session(Role, Host, Port, Session)
+ ok
+ end,
+ ssl_connection:handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
+ ssl_connection:stop({shutdown, transport_closed}, State);
+ true ->
+ %% Fixes non-delivery of final DTLS record in {active, once}.
+ %% Basically allows the application the opportunity to set {active, once} again
+ %% and then receive the final message.
+ next_event(StateName, no_record, State)
+ end;
+
+handle_info(new_cookie_secret, StateName,
+ #state{protocol_specific = #{current_cookie_secret := Secret} = CookieInfo} = State) ->
+ erlang:send_after(dtls_v1:cookie_timeout(), self(), new_cookie_secret),
+ {next_state, StateName, State#state{protocol_specific =
+ CookieInfo#{current_cookie_secret => dtls_v1:cookie_secret(),
+ previous_cookie_secret => Secret}}};
+handle_info(Msg, StateName, State) ->
+ ssl_connection:StateName(info, Msg, State, ?MODULE).
+
+handle_state_timeout(flight_retransmission_timeout, StateName,
+ #state{flight_state = {retransmit, NextTimeout}} = State0) ->
+ {State1, Actions0} = send_handshake_flight(State0#state{flight_state = {retransmit, NextTimeout}},
+ retransmit_epoch(StateName, State0)),
+ {Record, State2} = next_record(State1),
+ {next_state, StateName, State, Actions} = next_event(StateName, Record, State2, Actions0),
+ %% This will reset the retransmission timer by repeating the enter state event
+ {repeat_state, State, Actions}.
+
+handle_alerts([], Result) ->
+ Result;
+handle_alerts(_, {stop, _, _} = Stop) ->
+ Stop;
+handle_alerts([Alert | Alerts], {next_state, StateName, State}) ->
+ handle_alerts(Alerts, ssl_connection:handle_alert(Alert, StateName, State));
+handle_alerts([Alert | Alerts], {next_state, StateName, State, _Actions}) ->
+ handle_alerts(Alerts, ssl_connection:handle_alert(Alert, StateName, State)).
+
+handle_own_alert(Alert, Version, StateName, #state{data_tag = udp,
+ role = Role,
+ ssl_options = Options} = State0) ->
+ case ignore_alert(Alert, State0) of
+ {true, State} ->
+ log_ignore_alert(Options#ssl_options.log_alert, StateName, Alert, Role),
+ {next_state, StateName, State};
+ {false, State} ->
+ ssl_connection:handle_own_alert(Alert, Version, StateName, State)
+ end;
+handle_own_alert(Alert, Version, StateName, State) ->
+ ssl_connection:handle_own_alert(Alert, Version, StateName, State).
+
+encode_handshake_flight(Flight, Version, MaxFragmentSize, Epoch, ConnectionStates) ->
+ Fragments = lists:map(fun(Handshake) ->
+ dtls_handshake:fragment_handshake(Handshake, MaxFragmentSize)
+ end, Flight),
+ dtls_record:encode_handshake(Fragments, Version, Epoch, ConnectionStates).
+
+encode_change_cipher(#change_cipher_spec{}, Version, Epoch, ConnectionStates) ->
+ dtls_record:encode_change_cipher_spec(Version, Epoch, ConnectionStates).
+
+decode_alerts(Bin) ->
+ ssl_alert:decode(Bin).
+
+gen_handshake(StateName, Type, Event,
+ #state{negotiated_version = Version} = State) ->
+ try ssl_connection:StateName(Type, Event, State, ?MODULE) of
+ Result ->
+ Result
+ catch
+ _:_ ->
+ ssl_connection:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE,
+ malformed_handshake_data),
+ Version, StateName, State)
+ end.
+
+gen_info(Event, connection = StateName, #state{negotiated_version = Version} = State) ->
+ try handle_info(Event, StateName, State) of
+ Result ->
+ Result
+ catch
+ _:_ ->
+ ssl_connection:handle_own_alert(?ALERT_REC(?FATAL, ?INTERNAL_ERROR,
+ malformed_data),
+ Version, StateName, State)
+ end;
+
+gen_info(Event, StateName, #state{negotiated_version = Version} = State) ->
+ try handle_info(Event, StateName, State) of
+ Result ->
+ Result
+ catch
+ _:_ ->
+ ssl_connection:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE,
+ malformed_handshake_data),
+ Version, StateName, State)
+ end.
+unprocessed_events(Events) ->
+ %% The first handshake event will be processed immediately
+ %% as it is entered first in the event queue and
+ %% when it is processed there will be length(Events)-1
+ %% handshake events left to process before we should
+ %% process more TLS-records received on the socket.
+ erlang:length(Events)-1.
+
+update_handshake_history(#hello_verify_request{}, _, Hist) ->
+ Hist;
+update_handshake_history(_, Handshake, Hist) ->
+ ssl_handshake:update_handshake_history(Hist, iolist_to_binary(Handshake)).
prepare_flight(#state{flight_buffer = Flight,
connection_states = ConnectionStates0,
protocol_buffers =
@@ -890,11 +1031,11 @@ next_flight(Flight) ->
Flight#{handshakes => [],
change_cipher_spec => undefined,
handshakes_after_change_cipher_spec => []}.
-
-handle_flight_timer(#state{transport_cb = gen_udp,
+
+handle_flight_timer(#state{data_tag = udp,
flight_state = {retransmit, Timeout}} = State) ->
start_retransmision_timer(Timeout, State);
-handle_flight_timer(#state{transport_cb = gen_udp,
+handle_flight_timer(#state{data_tag = udp,
flight_state = connection} = State) ->
{State, []};
handle_flight_timer(State) ->
@@ -910,57 +1051,140 @@ new_timeout(N) when N =< 30 ->
new_timeout(_) ->
60.
-dtls_handshake_events(Packets) ->
- lists:map(fun(Packet) ->
- {next_event, internal, {handshake, Packet}}
- end, Packets).
+send_handshake_flight(#state{socket = Socket,
+ transport_cb = Transport,
+ flight_buffer = #{handshakes := Flight,
+ change_cipher_spec := undefined},
+ negotiated_version = Version,
+ connection_states = ConnectionStates0} = State0, Epoch) ->
+ %% TODO remove hardcoded Max size
+ {Encoded, ConnectionStates} =
+ encode_handshake_flight(lists:reverse(Flight), Version, 1400, Epoch, ConnectionStates0),
+ send(Transport, Socket, Encoded),
+ {State0#state{connection_states = ConnectionStates}, []};
-renegotiate(#state{role = client} = State, Actions) ->
- %% Handle same way as if server requested
- %% the renegotiation
- Hs0 = ssl_handshake:init_handshake_history(),
- {next_state, connection, State#state{tls_handshake_history = Hs0,
- protocol_buffers = #protocol_buffers{}},
- [{next_event, internal, #hello_request{}} | Actions]};
+send_handshake_flight(#state{socket = Socket,
+ transport_cb = Transport,
+ flight_buffer = #{handshakes := [_|_] = Flight0,
+ change_cipher_spec := ChangeCipher,
+ handshakes_after_change_cipher_spec := []},
+ negotiated_version = Version,
+ connection_states = ConnectionStates0} = State0, Epoch) ->
+ {HsBefore, ConnectionStates1} =
+ encode_handshake_flight(lists:reverse(Flight0), Version, 1400, Epoch, ConnectionStates0),
+ {EncChangeCipher, ConnectionStates} = encode_change_cipher(ChangeCipher, Version, Epoch, ConnectionStates1),
-renegotiate(#state{role = server,
- connection_states = CS0} = State0, Actions) ->
- HelloRequest = ssl_handshake:hello_request(),
- CS = CS0#{write_msg_seq => 0},
- {State1, MoreActions} = send_handshake(HelloRequest,
- State0#state{connection_states =
- CS}),
- Hs0 = ssl_handshake:init_handshake_history(),
- {Record, State} = next_record(State1#state{tls_handshake_history = Hs0,
- protocol_buffers = #protocol_buffers{}}),
- next_event(hello, Record, State, Actions ++ MoreActions).
+ send(Transport, Socket, [HsBefore, EncChangeCipher]),
+ {State0#state{connection_states = ConnectionStates}, []};
-handle_alerts([], Result) ->
- Result;
-handle_alerts(_, {stop,_} = Stop) ->
- Stop;
-handle_alerts([Alert | Alerts], {next_state, StateName, State}) ->
- handle_alerts(Alerts, ssl_connection:handle_alert(Alert, StateName, State));
-handle_alerts([Alert | Alerts], {next_state, StateName, State, _Actions}) ->
- handle_alerts(Alerts, ssl_connection:handle_alert(Alert, StateName, State)).
+send_handshake_flight(#state{socket = Socket,
+ transport_cb = Transport,
+ flight_buffer = #{handshakes := [_|_] = Flight0,
+ change_cipher_spec := ChangeCipher,
+ handshakes_after_change_cipher_spec := Flight1},
+ negotiated_version = Version,
+ connection_states = ConnectionStates0} = State0, Epoch) ->
+ {HsBefore, ConnectionStates1} =
+ encode_handshake_flight(lists:reverse(Flight0), Version, 1400, Epoch-1, ConnectionStates0),
+ {EncChangeCipher, ConnectionStates2} =
+ encode_change_cipher(ChangeCipher, Version, Epoch-1, ConnectionStates1),
+ {HsAfter, ConnectionStates} =
+ encode_handshake_flight(lists:reverse(Flight1), Version, 1400, Epoch, ConnectionStates2),
+ send(Transport, Socket, [HsBefore, EncChangeCipher, HsAfter]),
+ {State0#state{connection_states = ConnectionStates}, []};
+
+send_handshake_flight(#state{socket = Socket,
+ transport_cb = Transport,
+ flight_buffer = #{handshakes := [],
+ change_cipher_spec := ChangeCipher,
+ handshakes_after_change_cipher_spec := Flight1},
+ negotiated_version = Version,
+ connection_states = ConnectionStates0} = State0, Epoch) ->
+ {EncChangeCipher, ConnectionStates1} =
+ encode_change_cipher(ChangeCipher, Version, Epoch-1, ConnectionStates0),
+ {HsAfter, ConnectionStates} =
+ encode_handshake_flight(lists:reverse(Flight1), Version, 1400, Epoch, ConnectionStates1),
+ send(Transport, Socket, [EncChangeCipher, HsAfter]),
+ {State0#state{connection_states = ConnectionStates}, []}.
retransmit_epoch(_StateName, #state{connection_states = ConnectionStates}) ->
#{epoch := Epoch} =
ssl_record:current_connection_state(ConnectionStates, write),
Epoch.
-
-update_handshake_history(#hello_verify_request{}, _, Hist) ->
- Hist;
-update_handshake_history(_, Handshake, Hist) ->
- %% DTLS never needs option "v2_hello_compatible" to be true
- ssl_handshake:update_handshake_history(Hist, iolist_to_binary(Handshake), false).
-
-unprocessed_events(Events) ->
- %% The first handshake event will be processed immediately
- %% as it is entered first in the event queue and
- %% when it is processed there will be length(Events)-1
- %% handshake events left to process before we should
- %% process more TLS-records received on the socket.
- erlang:length(Events)-1.
+ignore_alert(#alert{level = ?FATAL}, #state{protocol_specific = #{ignored_alerts := N,
+ max_ignored_alerts := N}} = State) ->
+ {false, State};
+ignore_alert(#alert{level = ?FATAL} = Alert,
+ #state{protocol_specific = #{ignored_alerts := N} = PS} = State) ->
+ case is_ignore_alert(Alert) of
+ true ->
+ {true, State#state{protocol_specific = PS#{ignored_alerts => N+1}}};
+ false ->
+ {false, State}
+ end;
+ignore_alert(_, State) ->
+ {false, State}.
+
+%% RFC 6347 4.1.2.7. Handling Invalid Records
+%% recommends to silently ignore invalid DTLS records when
+%% upd is the transport. Note we do not support compression so no need
+%% include ?DECOMPRESSION_FAILURE
+is_ignore_alert(#alert{description = ?BAD_RECORD_MAC}) ->
+ true;
+is_ignore_alert(#alert{description = ?RECORD_OVERFLOW}) ->
+ true;
+is_ignore_alert(#alert{description = ?DECODE_ERROR}) ->
+ true;
+is_ignore_alert(#alert{description = ?DECRYPT_ERROR}) ->
+ true;
+is_ignore_alert(#alert{description = ?ILLEGAL_PARAMETER}) ->
+ true;
+is_ignore_alert(_) ->
+ false.
+
+log_ignore_alert(true, StateName, Alert, Role) ->
+ Txt = ssl_alert:alert_txt(Alert),
+ error_logger:format("DTLS over UDP ~p: In state ~p ignored to send ALERT ~s as DoS-attack mitigation \n",
+ [Role, StateName, Txt]);
+log_ignore_alert(false, _, _,_) ->
+ ok.
+
+send_application_data(Data, From, _StateName,
+ #state{socket = Socket,
+ negotiated_version = Version,
+ protocol_cb = Connection,
+ transport_cb = Transport,
+ connection_states = ConnectionStates0,
+ ssl_options = #ssl_options{renegotiate_at = RenegotiateAt}} = State0) ->
+
+ case time_to_renegotiate(Data, ConnectionStates0, RenegotiateAt) of
+ true ->
+ renegotiate(State0#state{renegotiation = {true, internal}},
+ [{next_event, {call, From}, {application_data, Data}}]);
+ false ->
+ {Msgs, ConnectionStates} =
+ Connection:encode_data(Data, Version, ConnectionStates0),
+ State = State0#state{connection_states = ConnectionStates},
+ case Connection:send(Transport, Socket, Msgs) of
+ ok ->
+ ssl_connection:hibernate_after(connection, State, [{reply, From, ok}]);
+ Result ->
+ ssl_connection:hibernate_after(connection, State, [{reply, From, Result}])
+ end
+ end.
+time_to_renegotiate(_Data,
+ #{current_write := #{sequence_number := Num}},
+ RenegotiateAt) ->
+
+ %% We could do test:
+ %% is_time_to_renegotiate((erlang:byte_size(_Data) div
+ %% ?MAX_PLAIN_TEXT_LENGTH) + 1, RenegotiateAt), but we chose to
+ %% have a some what lower renegotiateAt and a much cheaper test
+ is_time_to_renegotiate(Num, RenegotiateAt).
+
+is_time_to_renegotiate(N, M) when N < M->
+ false;
+is_time_to_renegotiate(_,_) ->
+ true.
diff --git a/lib/ssl/src/dtls_handshake.erl b/lib/ssl/src/dtls_handshake.erl
index 37a46b862e..3f70eaec8a 100644
--- a/lib/ssl/src/dtls_handshake.erl
+++ b/lib/ssl/src/dtls_handshake.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -16,6 +16,11 @@
%% limitations under the License.
%%
%% %CopyrightEnd%
+
+%%----------------------------------------------------------------------
+%% Purpose: Help funtions for handling the DTLS (specific parts of)
+%%% SSL/TLS/DTLS handshake protocol
+%%----------------------------------------------------------------------
-module(dtls_handshake).
-include("dtls_connection.hrl").
@@ -24,15 +29,21 @@
-include("ssl_internal.hrl").
-include("ssl_alert.hrl").
+%% Handshake handling
-export([client_hello/8, client_hello/9, cookie/4, hello/4,
- hello_verify_request/2, get_dtls_handshake/3, fragment_handshake/2,
- handshake_bin/2, encode_handshake/3]).
+ hello_verify_request/2]).
+
+%% Handshake encoding
+-export([fragment_handshake/2, encode_handshake/3]).
+
+%% Handshake decodeing
+-export([get_dtls_handshake/3]).
-type dtls_handshake() :: #client_hello{} | #hello_verify_request{} |
ssl_handshake:ssl_handshake().
%%====================================================================
-%% Internal application API
+%% Handshake handling
%%====================================================================
%%--------------------------------------------------------------------
-spec client_hello(host(), inet:port_number(), ssl_record:connection_states(),
@@ -56,7 +67,8 @@ client_hello(Host, Port, ConnectionStates, SslOpts,
%%--------------------------------------------------------------------
client_hello(Host, Port, Cookie, ConnectionStates,
#ssl_options{versions = Versions,
- ciphers = UserSuites
+ ciphers = UserSuites,
+ fallback = Fallback
} = SslOpts,
Cache, CacheCb, Renegotiation, OwnCert) ->
Version = dtls_record:highest_protocol_version(Versions),
@@ -66,12 +78,15 @@ client_hello(Host, Port, Cookie, ConnectionStates,
CipherSuites = ssl_handshake:available_suites(UserSuites, TLSVersion),
Extensions = ssl_handshake:client_hello_extensions(TLSVersion, CipherSuites,
- SslOpts, ConnectionStates, Renegotiation),
+ SslOpts, ConnectionStates,
+ Renegotiation),
Id = ssl_session:client_id({Host, Port, SslOpts}, Cache, CacheCb, OwnCert),
#client_hello{session_id = Id,
client_version = Version,
- cipher_suites = ssl_handshake:cipher_suites(CipherSuites, Renegotiation),
+ cipher_suites =
+ ssl_handshake:cipher_suites(CipherSuites,
+ Renegotiation, Fallback),
compression_methods = ssl_record:compressions(),
random = SecParams#security_parameters.client_random,
cookie = Cookie,
@@ -87,11 +102,11 @@ hello(#server_hello{server_version = Version, random = Random,
case dtls_record:is_acceptable_version(Version, SupportedVersions) of
true ->
handle_server_hello_extensions(Version, SessionId, Random, CipherSuite,
- Compression, HelloExt, SslOpt, ConnectionStates0, Renegotiation);
+ Compression, HelloExt, SslOpt,
+ ConnectionStates0, Renegotiation);
false ->
?ALERT_REC(?FATAL, ?PROTOCOL_VERSION)
end;
-
hello(#client_hello{client_version = ClientVersion} = Hello,
#ssl_options{versions = Versions} = SslOpts,
Info, Renegotiation) ->
@@ -107,7 +122,7 @@ cookie(Key, Address, Port, #client_hello{client_version = {Major, Minor},
<<?BYTE(Major), ?BYTE(Minor)>>,
Random, SessionId, CipherSuites, CompressionMethods],
crypto:hmac(sha, Key, CookieData).
-
+%%--------------------------------------------------------------------
-spec hello_verify_request(binary(), dtls_record:dtls_version()) -> #hello_verify_request{}.
%%
%% Description: Creates a hello verify request message sent by server to
@@ -117,11 +132,8 @@ hello_verify_request(Cookie, Version) ->
#hello_verify_request{protocol_version = Version, cookie = Cookie}.
%%--------------------------------------------------------------------
-
-encode_handshake(Handshake, Version, Seq) ->
- {MsgType, Bin} = enc_handshake(Handshake, Version),
- Len = byte_size(Bin),
- [MsgType, ?uint24(Len), ?uint16(Seq), ?uint24(0), ?uint24(Len), Bin].
+%%% Handshake encoding
+%%--------------------------------------------------------------------
fragment_handshake(Bin, _) when is_binary(Bin)->
%% This is the change_cipher_spec not a "real handshake" but part of the flight
@@ -129,10 +141,15 @@ fragment_handshake(Bin, _) when is_binary(Bin)->
fragment_handshake([MsgType, Len, Seq, _, Len, Bin], Size) ->
Bins = bin_fragments(Bin, Size),
handshake_fragments(MsgType, Seq, Len, Bins, []).
+encode_handshake(Handshake, Version, Seq) ->
+ {MsgType, Bin} = enc_handshake(Handshake, Version),
+ Len = byte_size(Bin),
+ [MsgType, ?uint24(Len), ?uint16(Seq), ?uint24(0), ?uint24(Len), Bin].
+
+%%--------------------------------------------------------------------
+%%% Handshake decodeing
+%%--------------------------------------------------------------------
-handshake_bin([Type, Length, Data], Seq) ->
- handshake_bin(Type, Length, Seq, Data).
-
%%--------------------------------------------------------------------
-spec get_dtls_handshake(dtls_record:dtls_version(), binary(), #protocol_buffers{}) ->
{[dtls_handshake()], #protocol_buffers{}}.
@@ -147,31 +164,37 @@ get_dtls_handshake(Version, Fragment, ProtocolBuffers) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-handle_client_hello(Version, #client_hello{session_id = SugesstedId,
- cipher_suites = CipherSuites,
- compression_methods = Compressions,
- random = Random,
- extensions =
- #hello_extensions{elliptic_curves = Curves,
- signature_algs = ClientHashSigns} = HelloExt},
+handle_client_hello(Version,
+ #client_hello{session_id = SugesstedId,
+ cipher_suites = CipherSuites,
+ compression_methods = Compressions,
+ random = Random,
+ extensions =
+ #hello_extensions{elliptic_curves = Curves,
+ signature_algs = ClientHashSigns}
+ = HelloExt},
#ssl_options{versions = Versions,
- signature_algs = SupportedHashSigns} = SslOpts,
- {Port, Session0, Cache, CacheCb, ConnectionStates0, Cert, _}, Renegotiation) ->
+ signature_algs = SupportedHashSigns,
+ eccs = SupportedECCs,
+ honor_ecc_order = ECCOrder} = SslOpts,
+ {Port, Session0, Cache, CacheCb, ConnectionStates0, Cert, _},
+ Renegotiation) ->
case dtls_record:is_acceptable_version(Version, Versions) of
true ->
TLSVersion = dtls_v1:corresponding_tls_version(Version),
AvailableHashSigns = ssl_handshake:available_signature_algs(
ClientHashSigns, SupportedHashSigns, Cert,TLSVersion),
- ECCCurve = ssl_handshake:select_curve(Curves, ssl_handshake:supported_ecc(TLSVersion)),
+ ECCCurve = ssl_handshake:select_curve(Curves, SupportedECCs, ECCOrder),
{Type, #session{cipher_suite = CipherSuite} = Session1}
- = ssl_handshake:select_session(SugesstedId, CipherSuites, AvailableHashSigns, Compressions,
+ = ssl_handshake:select_session(SugesstedId, CipherSuites,
+ AvailableHashSigns, Compressions,
Port, Session0#session{ecc = ECCCurve}, TLSVersion,
SslOpts, Cache, CacheCb, Cert),
case CipherSuite of
no_suite ->
?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY);
_ ->
- {KeyExAlg,_,_,_} = ssl_cipher:suite_definition(CipherSuite),
+ #{key_exchange := KeyExAlg} = ssl_cipher_format:suite_definition(CipherSuite),
case ssl_handshake:select_hashsign(ClientHashSigns, Cert, KeyExAlg,
SupportedHashSigns, TLSVersion) of
#alert{} = Alert ->
@@ -190,7 +213,8 @@ handle_client_hello_extensions(Version, Type, Random, CipherSuites,
HelloExt, SslOpts, Session0, ConnectionStates0, Renegotiation, HashSign) ->
try ssl_handshake:handle_client_hello_extensions(dtls_record, Random, CipherSuites,
HelloExt, dtls_v1:corresponding_tls_version(Version),
- SslOpts, Session0, ConnectionStates0, Renegotiation) of
+ SslOpts, Session0,
+ ConnectionStates0, Renegotiation) of
#alert{} = Alert ->
Alert;
{Session, ConnectionStates, Protocol, ServerHelloExt} ->
@@ -212,7 +236,7 @@ handle_server_hello_extensions(Version, SessionId, Random, CipherSuite,
end.
-%%%%%%% Encodeing %%%%%%%%%%%%%
+%%--------------------------------------------------------------------
enc_handshake(#hello_verify_request{protocol_version = {Major, Minor},
cookie = Cookie}, _Version) ->
@@ -220,7 +244,6 @@ enc_handshake(#hello_verify_request{protocol_version = {Major, Minor},
{?HELLO_VERIFY_REQUEST, <<?BYTE(Major), ?BYTE(Minor),
?BYTE(CookieLength),
Cookie:CookieLength/binary>>};
-
enc_handshake(#hello_request{}, _Version) ->
{?HELLO_REQUEST, <<>>};
enc_handshake(#client_hello{client_version = {Major, Minor},
@@ -243,19 +266,29 @@ enc_handshake(#client_hello{client_version = {Major, Minor},
?BYTE(CookieLength), Cookie/binary,
?UINT16(CsLength), BinCipherSuites/binary,
?BYTE(CmLength), BinCompMethods/binary, ExtensionsBin/binary>>};
-
enc_handshake(#server_hello{} = HandshakeMsg, Version) ->
{Type, <<?BYTE(Major), ?BYTE(Minor), Rest/binary>>} =
ssl_handshake:encode_handshake(HandshakeMsg, Version),
{DTLSMajor, DTLSMinor} = dtls_v1:corresponding_dtls_version({Major, Minor}),
{Type, <<?BYTE(DTLSMajor), ?BYTE(DTLSMinor), Rest/binary>>};
-
enc_handshake(HandshakeMsg, Version) ->
ssl_handshake:encode_handshake(HandshakeMsg, dtls_v1:corresponding_tls_version(Version)).
+handshake_bin(#handshake_fragment{
+ type = Type,
+ length = Len,
+ message_seq = Seq,
+ fragment_length = Len,
+ fragment_offset = 0,
+ fragment = Fragment}) ->
+ handshake_bin(Type, Len, Seq, Fragment).
+handshake_bin(Type, Length, Seq, FragmentData) ->
+ <<?BYTE(Type), ?UINT24(Length),
+ ?UINT16(Seq), ?UINT24(0), ?UINT24(Length),
+ FragmentData:Length/binary>>.
+
bin_fragments(Bin, Size) ->
bin_fragments(Bin, size(Bin), Size, 0, []).
-
bin_fragments(Bin, BinSize, FragSize, Offset, Fragments) ->
case (BinSize - Offset - FragSize) > 0 of
true ->
@@ -279,7 +312,7 @@ address_to_bin({A,B,C,D}, Port) ->
address_to_bin({A,B,C,D,E,F,G,H}, Port) ->
<<A:16,B:16,C:16,D:16,E:16,F:16,G:16,H:16,Port:16>>.
-%%%%%%% Decodeing %%%%%%%%%%%%%
+%%--------------------------------------------------------------------
handle_fragments(Version, FragmentData, Buffers0, Acc) ->
Fragments = decode_handshake_fragments(FragmentData),
@@ -322,7 +355,6 @@ decode_handshake(_Version, ?CLIENT_HELLO, <<?UINT24(_), ?UINT16(_),
compression_methods = Comp_methods,
extensions = DecodedExtensions
};
-
decode_handshake(_Version, ?HELLO_VERIFY_REQUEST, <<?UINT24(_), ?UINT16(_),
?UINT24(_), ?UINT24(_),
?BYTE(Major), ?BYTE(Minor),
@@ -330,7 +362,6 @@ decode_handshake(_Version, ?HELLO_VERIFY_REQUEST, <<?UINT24(_), ?UINT16(_),
Cookie:CookieLength/binary>>) ->
#hello_verify_request{protocol_version = {Major, Minor},
cookie = Cookie};
-
decode_handshake(Version, Tag, <<?UINT24(_), ?UINT16(_),
?UINT24(_), ?UINT24(_), Msg/binary>>) ->
%% DTLS specifics stripped
@@ -370,9 +401,10 @@ reassemble(Version, #handshake_fragment{message_seq = Seq} = Fragment,
end;
reassemble(_, #handshake_fragment{message_seq = FragSeq} = Fragment,
#protocol_buffers{dtls_handshake_next_seq = Seq,
- dtls_handshake_later_fragments = LaterFragments} = Buffers0) when FragSeq > Seq->
- {more_data,
- Buffers0#protocol_buffers{dtls_handshake_later_fragments = [Fragment | LaterFragments]}};
+ dtls_handshake_later_fragments = LaterFragments}
+ = Buffers0) when FragSeq > Seq->
+ {more_data,
+ Buffers0#protocol_buffers{dtls_handshake_later_fragments = [Fragment | LaterFragments]}};
reassemble(_, _, Buffers) ->
%% Disregard fragments FragSeq < Seq
{more_data, Buffers}.
@@ -396,26 +428,6 @@ merge_fragment(Frag0, [Frag1 | Rest]) ->
Frag ->
merge_fragment(Frag, Rest)
end.
-
-is_complete_handshake(#handshake_fragment{length = Length, fragment_length = Length}) ->
- true;
-is_complete_handshake(_) ->
- false.
-
-next_fragments(LaterFragments) ->
- case lists:keysort(#handshake_fragment.message_seq, LaterFragments) of
- [] ->
- {[], []};
- [#handshake_fragment{message_seq = Seq} | _] = Fragments ->
- split_frags(Fragments, Seq, [])
- end.
-
-split_frags([#handshake_fragment{message_seq = Seq} = Frag | Rest], Seq, Acc) ->
- split_frags(Rest, Seq, [Frag | Acc]);
-split_frags(Frags, _, Acc) ->
- {lists:reverse(Acc), Frags}.
-
-
%% Duplicate
merge_fragments(#handshake_fragment{
fragment_offset = PreviousOffSet,
@@ -486,17 +498,26 @@ merge_fragments(#handshake_fragment{
%% No merge there is a gap
merge_fragments(Previous, Current) ->
[Previous, Current].
-
-handshake_bin(#handshake_fragment{
- type = Type,
- length = Len,
- message_seq = Seq,
- fragment_length = Len,
- fragment_offset = 0,
- fragment = Fragment}) ->
- handshake_bin(Type, Len, Seq, Fragment).
-handshake_bin(Type, Length, Seq, FragmentData) ->
- <<?BYTE(Type), ?UINT24(Length),
- ?UINT16(Seq), ?UINT24(0), ?UINT24(Length),
- FragmentData:Length/binary>>.
+next_fragments(LaterFragments) ->
+ case lists:keysort(#handshake_fragment.message_seq, LaterFragments) of
+ [] ->
+ {[], []};
+ [#handshake_fragment{message_seq = Seq} | _] = Fragments ->
+ split_frags(Fragments, Seq, [])
+ end.
+
+split_frags([#handshake_fragment{message_seq = Seq} = Frag | Rest], Seq, Acc) ->
+ split_frags(Rest, Seq, [Frag | Acc]);
+split_frags(Frags, _, Acc) ->
+ {lists:reverse(Acc), Frags}.
+
+is_complete_handshake(#handshake_fragment{length = Length, fragment_length = Length}) ->
+ true;
+is_complete_handshake(_) ->
+ false.
+
+
+
+
+
diff --git a/lib/ssl/src/dtls_listener_sup.erl b/lib/ssl/src/dtls_listener_sup.erl
new file mode 100644
index 0000000000..dc30696a2c
--- /dev/null
+++ b/lib/ssl/src/dtls_listener_sup.erl
@@ -0,0 +1,62 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2016-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Supervisor for a procsses dispatching upd datagrams to
+%% correct DTLS handler
+%%----------------------------------------------------------------------
+-module(dtls_listener_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/0]).
+-export([start_child/1]).
+
+%% Supervisor callback
+-export([init/1]).
+
+%%%=========================================================================
+%%% API
+%%%=========================================================================
+start_link() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+start_child(Args) ->
+ supervisor:start_child(?MODULE, Args).
+
+%%%=========================================================================
+%%% Supervisor callback
+%%%=========================================================================
+init(_O) ->
+ RestartStrategy = simple_one_for_one,
+ MaxR = 0,
+ MaxT = 3600,
+
+ Name = undefined, % As simple_one_for_one is used.
+ StartFunc = {dtls_packet_demux, start_link, []},
+ Restart = temporary, % E.g. should not be restarted
+ Shutdown = 4000,
+ Modules = [dtls_packet_demux],
+ Type = worker,
+
+ ChildSpec = {Name, StartFunc, Restart, Shutdown, Type, Modules},
+ {ok, {{RestartStrategy, MaxR, MaxT}, [ChildSpec]}}.
diff --git a/lib/ssl/src/dtls_packet_demux.erl b/lib/ssl/src/dtls_packet_demux.erl
new file mode 100644
index 0000000000..1497c77cf3
--- /dev/null
+++ b/lib/ssl/src/dtls_packet_demux.erl
@@ -0,0 +1,309 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2016-2018. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(dtls_packet_demux).
+
+-behaviour(gen_server).
+
+-include("ssl_internal.hrl").
+
+%% API
+-export([start_link/5, active_once/3, accept/2, sockname/1, close/1,
+ get_all_opts/1, get_sock_opts/2, set_sock_opts/2]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-record(state,
+ {port,
+ listener,
+ transport,
+ dtls_options,
+ emulated_options,
+ dtls_msq_queues = kv_new(),
+ clients = set_new(),
+ dtls_processes = kv_new(),
+ accepters = queue:new(),
+ first,
+ close
+ }).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+start_link(Port, TransportInfo, EmOpts, InetOptions, DTLSOptions) ->
+ gen_server:start_link(?MODULE, [Port, TransportInfo, EmOpts, InetOptions, DTLSOptions], []).
+
+active_once(PacketSocket, Client, Pid) ->
+ gen_server:cast(PacketSocket, {active_once, Client, Pid}).
+
+accept(PacketSocket, Accepter) ->
+ call(PacketSocket, {accept, Accepter}).
+
+sockname(PacketSocket) ->
+ call(PacketSocket, sockname).
+close(PacketSocket) ->
+ call(PacketSocket, close).
+get_sock_opts(PacketSocket, SplitSockOpts) ->
+ call(PacketSocket, {get_sock_opts, SplitSockOpts}).
+get_all_opts(PacketSocket) ->
+ call(PacketSocket, get_all_opts).
+set_sock_opts(PacketSocket, Opts) ->
+ call(PacketSocket, {set_sock_opts, Opts}).
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+init([Port, {TransportModule, _,_,_} = TransportInfo, EmOpts, InetOptions, DTLSOptions]) ->
+ try
+ {ok, Socket} = TransportModule:open(Port, InetOptions),
+ {ok, #state{port = Port,
+ first = true,
+ transport = TransportInfo,
+ dtls_options = DTLSOptions,
+ emulated_options = EmOpts,
+ listener = Socket,
+ close = false}}
+ catch _:_ ->
+ {stop, {shutdown, {error, closed}}}
+ end.
+handle_call({accept, _}, _, #state{close = true} = State) ->
+ {reply, {error, closed}, State};
+
+handle_call({accept, Accepter}, From, #state{first = true,
+ accepters = Accepters,
+ listener = Socket} = State0) ->
+ next_datagram(Socket),
+ State = State0#state{first = false,
+ accepters = queue:in({Accepter, From}, Accepters)},
+ {noreply, State};
+
+handle_call({accept, Accepter}, From, #state{accepters = Accepters} = State0) ->
+ State = State0#state{accepters = queue:in({Accepter, From}, Accepters)},
+ {noreply, State};
+handle_call(sockname, _, #state{listener = Socket} = State) ->
+ Reply = inet:sockname(Socket),
+ {reply, Reply, State};
+handle_call(close, _, #state{dtls_processes = Processes,
+ accepters = Accepters} = State) ->
+ case kv_empty(Processes) of
+ true ->
+ {stop, normal, ok, State#state{close=true}};
+ false ->
+ lists:foreach(fun({_, From}) ->
+ gen_server:reply(From, {error, closed})
+ end, queue:to_list(Accepters)),
+ {reply, ok, State#state{close = true, accepters = queue:new()}}
+ end;
+handle_call({get_sock_opts, {SocketOptNames, EmOptNames}}, _, #state{listener = Socket,
+ emulated_options = EmOpts} = State) ->
+ case get_socket_opts(Socket, SocketOptNames) of
+ {ok, Opts} ->
+ {reply, {ok, emulated_opts_list(EmOpts, EmOptNames, []) ++ Opts}, State};
+ {error, Reason} ->
+ {reply, {error, Reason}, State}
+ end;
+handle_call(get_all_opts, _, #state{dtls_options = DTLSOptions,
+ emulated_options = EmOpts} = State) ->
+ {reply, {ok, EmOpts, DTLSOptions}, State};
+handle_call({set_sock_opts, {SocketOpts, NewEmOpts}}, _, #state{listener = Socket, emulated_options = EmOpts0} = State) ->
+ set_socket_opts(Socket, SocketOpts),
+ EmOpts = do_set_emulated_opts(NewEmOpts, EmOpts0),
+ {reply, ok, State#state{emulated_options = EmOpts}}.
+
+handle_cast({active_once, Client, Pid}, State0) ->
+ State = handle_active_once(Client, Pid, State0),
+ {noreply, State}.
+
+handle_info({Transport, Socket, IP, InPortNo, _} = Msg, #state{listener = Socket, transport = {_,Transport,_,_}} = State0) ->
+ State = handle_datagram({IP, InPortNo}, Msg, State0),
+ next_datagram(Socket),
+ {noreply, State};
+
+%% UDP socket does not have a connection and should not receive an econnreset
+%% This does however happens on some windows versions. Just ignoring it
+%% appears to make things work as expected!
+handle_info({Error, Socket, econnreset = Error}, #state{listener = Socket, transport = {_,_,_, udp_error}} = State) ->
+ Report = io_lib:format("Ignore SSL UDP Listener: Socket error: ~p ~n", [Error]),
+ error_logger:info_report(Report),
+ {noreply, State};
+handle_info({Error, Socket, Error}, #state{listener = Socket, transport = {_,_,_, Error}} = State) ->
+ Report = io_lib:format("SSL Packet muliplxer shutdown: Socket error: ~p ~n", [Error]),
+ error_logger:info_report(Report),
+ {noreply, State#state{close=true}};
+
+handle_info({'DOWN', _, process, Pid, _}, #state{clients = Clients,
+ dtls_processes = Processes0,
+ dtls_msq_queues = MsgQueues0,
+ close = ListenClosed} = State) ->
+ Client = kv_get(Pid, Processes0),
+ Processes = kv_delete(Pid, Processes0),
+ MsgQueues = kv_delete(Client, MsgQueues0),
+ case ListenClosed andalso kv_empty(Processes) of
+ true ->
+ {stop, normal, State};
+ false ->
+ {noreply, State#state{clients = set_delete(Client, Clients),
+ dtls_processes = Processes,
+ dtls_msq_queues = MsgQueues}}
+ end.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+handle_datagram(Client, Msg, #state{clients = Clients,
+ accepters = AcceptorsQueue0} = State) ->
+ case set_is_member(Client, Clients) of
+ false ->
+ case queue:out(AcceptorsQueue0) of
+ {{value, {UserPid, From}}, AcceptorsQueue} ->
+ setup_new_connection(UserPid, From, Client, Msg,
+ State#state{accepters = AcceptorsQueue});
+ {empty, _} ->
+ %% Drop packet client will resend
+ State
+ end;
+ true ->
+ dispatch(Client, Msg, State)
+ end.
+
+dispatch(Client, Msg, #state{dtls_msq_queues = MsgQueues} = State) ->
+ case kv_lookup(Client, MsgQueues) of
+ {value, Queue0} ->
+ case queue:out(Queue0) of
+ {{value, Pid}, Queue} when is_pid(Pid) ->
+ Pid ! Msg,
+ State#state{dtls_msq_queues =
+ kv_update(Client, Queue, MsgQueues)};
+ {{value, _}, Queue} ->
+ State#state{dtls_msq_queues =
+ kv_update(Client, queue:in(Msg, Queue), MsgQueues)};
+ {empty, Queue} ->
+ State#state{dtls_msq_queues =
+ kv_update(Client, queue:in(Msg, Queue), MsgQueues)}
+ end
+ end.
+next_datagram(Socket) ->
+ inet:setopts(Socket, [{active, once}]).
+
+handle_active_once(Client, Pid, #state{dtls_msq_queues = MsgQueues} = State0) ->
+ Queue0 = kv_get(Client, MsgQueues),
+ case queue:out(Queue0) of
+ {{value, Pid}, _} when is_pid(Pid) ->
+ State0;
+ {{value, Msg}, Queue} ->
+ Pid ! Msg,
+ State0#state{dtls_msq_queues = kv_update(Client, Queue, MsgQueues)};
+ {empty, Queue0} ->
+ State0#state{dtls_msq_queues = kv_update(Client, queue:in(Pid, Queue0), MsgQueues)}
+ end.
+
+setup_new_connection(User, From, Client, Msg, #state{dtls_processes = Processes,
+ clients = Clients,
+ dtls_msq_queues = MsgQueues,
+ dtls_options = DTLSOpts,
+ port = Port,
+ listener = Socket,
+ emulated_options = EmOpts} = State) ->
+ ConnArgs = [server, "localhost", Port, {self(), {Client, Socket}},
+ {DTLSOpts, EmOpts, dtls_listener}, User, dtls_socket:default_cb_info()],
+ case dtls_connection_sup:start_child(ConnArgs) of
+ {ok, Pid} ->
+ erlang:monitor(process, Pid),
+ gen_server:reply(From, {ok, Pid, {Client, Socket}}),
+ Pid ! Msg,
+ State#state{clients = set_insert(Client, Clients),
+ dtls_msq_queues = kv_insert(Client, queue:new(), MsgQueues),
+ dtls_processes = kv_insert(Pid, Client, Processes)};
+ {error, Reason} ->
+ gen_server:reply(From, {error, Reason}),
+ State
+ end.
+
+kv_update(Key, Value, Store) ->
+ gb_trees:update(Key, Value, Store).
+kv_lookup(Key, Store) ->
+ gb_trees:lookup(Key, Store).
+kv_insert(Key, Value, Store) ->
+ gb_trees:insert(Key, Value, Store).
+kv_get(Key, Store) ->
+ gb_trees:get(Key, Store).
+kv_delete(Key, Store) ->
+ gb_trees:delete(Key, Store).
+kv_new() ->
+ gb_trees:empty().
+kv_empty(Store) ->
+ gb_trees:is_empty(Store).
+
+set_new() ->
+ gb_sets:empty().
+set_insert(Item, Set) ->
+ gb_sets:insert(Item, Set).
+set_delete(Item, Set) ->
+ gb_sets:delete(Item, Set).
+set_is_member(Item, Set) ->
+ gb_sets:is_member(Item, Set).
+
+call(Server, Msg) ->
+ try
+ gen_server:call(Server, Msg, infinity)
+ catch
+ exit:{noproc, _} ->
+ {error, closed};
+ exit:{normal, _} ->
+ {error, closed};
+ exit:{{shutdown, _},_} ->
+ {error, closed}
+ end.
+
+set_socket_opts(_, []) ->
+ ok;
+set_socket_opts(Socket, SocketOpts) ->
+ inet:setopts(Socket, SocketOpts).
+
+get_socket_opts(_, []) ->
+ {ok, []};
+get_socket_opts(Socket, SocketOpts) ->
+ inet:getopts(Socket, SocketOpts).
+
+do_set_emulated_opts([], Opts) ->
+ Opts;
+do_set_emulated_opts([{mode, Value} | Rest], Opts) ->
+ do_set_emulated_opts(Rest, Opts#socket_options{mode = Value});
+do_set_emulated_opts([{active, Value} | Rest], Opts) ->
+ do_set_emulated_opts(Rest, Opts#socket_options{active = Value}).
+
+emulated_opts_list(_,[], Acc) ->
+ Acc;
+emulated_opts_list( Opts, [mode | Rest], Acc) ->
+ emulated_opts_list(Opts, Rest, [{mode, Opts#socket_options.mode} | Acc]);
+emulated_opts_list(Opts, [active | Rest], Acc) ->
+ emulated_opts_list(Opts, Rest, [{active, Opts#socket_options.active} | Acc]).
+
diff --git a/lib/ssl/src/dtls_record.erl b/lib/ssl/src/dtls_record.erl
index 8a7f8c1d0a..9eb0d8e2d7 100644
--- a/lib/ssl/src/dtls_record.erl
+++ b/lib/ssl/src/dtls_record.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,15 +30,17 @@
-include("ssl_cipher.hrl").
%% Handling of incoming data
--export([get_dtls_records/2, init_connection_states/2]).
+-export([get_dtls_records/3, init_connection_states/2, empty_connection_state/1]).
-%% Decoding
--export([decode_cipher_text/2]).
+-export([save_current_connection_state/2, next_epoch/2, get_connection_state_by_epoch/3, replay_detect/2,
+ init_connection_state_seq/2, current_connection_state_epoch/2]).
%% Encoding
-export([encode_handshake/4, encode_alert_record/3,
- encode_change_cipher_spec/3, encode_data/3]).
--export([encode_plain_text/5]).
+ encode_change_cipher_spec/3, encode_data/3, encode_plain_text/5]).
+
+%% Decoding
+-export([decode_cipher_text/2]).
%% Protocol version handling
-export([protocol_version/1, lowest_protocol_version/1, lowest_protocol_version/2,
@@ -46,9 +48,6 @@
is_higher/2, supported_protocol_versions/0,
is_acceptable_version/2, hello_version/2]).
--export([save_current_connection_state/2, next_epoch/2, get_connection_state_by_epoch/3, replay_detect/2]).
-
--export([init_connection_state_seq/2, current_connection_state_epoch/2]).
-export_type([dtls_version/0, dtls_atom_version/0]).
@@ -60,7 +59,7 @@
-compile(inline).
%%====================================================================
-%% Internal application API
+%% Handling of incoming data
%%====================================================================
%%--------------------------------------------------------------------
-spec init_connection_states(client | server, one_n_minus_one | zero_n | disabled) ->
@@ -75,7 +74,7 @@ init_connection_states(Role, BeastMitigation) ->
Initial = initial_connection_state(ConnectionEnd, BeastMitigation),
Current = Initial#{epoch := 0},
InitialPending = ssl_record:empty_connection_state(ConnectionEnd, BeastMitigation),
- Pending = InitialPending#{epoch => undefined, replay_window => init_replay_window(?REPLAY_WINDOW_SIZE)},
+ Pending = empty_connection_state(InitialPending),
#{saved_read => Current,
current_read => Current,
pending_read => Pending,
@@ -83,6 +82,9 @@ init_connection_states(Role, BeastMitigation) ->
current_write => Current,
pending_write => Pending}.
+empty_connection_state(Empty) ->
+ Empty#{epoch => undefined, replay_window => init_replay_window(?REPLAY_WINDOW_SIZE)}.
+
%%--------------------------------------------------------------------
-spec save_current_connection_state(ssl_record:connection_states(), read | write) ->
ssl_record:connection_states().
@@ -133,67 +135,58 @@ set_connection_state_by_epoch(ReadState, Epoch, #{saved_read := #{epoch := Epoch
States#{saved_read := ReadState}.
%%--------------------------------------------------------------------
--spec get_dtls_records(binary(), binary()) -> {[binary()], binary()} | #alert{}.
+-spec init_connection_state_seq(dtls_version(), ssl_record:connection_states()) ->
+ ssl_record:connection_state().
+%%
+%% Description: Copy the read sequence number to the write sequence number
+%% This is only valid for DTLS in the first client_hello
+%%--------------------------------------------------------------------
+init_connection_state_seq({254, _},
+ #{current_read := #{epoch := 0, sequence_number := Seq},
+ current_write := #{epoch := 0} = Write} = ConnnectionStates0) ->
+ ConnnectionStates0#{current_write => Write#{sequence_number => Seq}};
+init_connection_state_seq(_, ConnnectionStates) ->
+ ConnnectionStates.
+
+%%--------------------------------------------------------
+-spec current_connection_state_epoch(ssl_record:connection_states(), read | write) ->
+ integer().
+%%
+%% Description: Returns the epoch the connection_state record
+%% that is currently defined as the current connection state.
+%%--------------------------------------------------------------------
+current_connection_state_epoch(#{current_read := #{epoch := Epoch}},
+ read) ->
+ Epoch;
+current_connection_state_epoch(#{current_write := #{epoch := Epoch}},
+ write) ->
+ Epoch.
+
+%%--------------------------------------------------------------------
+-spec get_dtls_records(binary(), [dtls_version()], binary()) -> {[binary()], binary()} | #alert{}.
%%
%% Description: Given old buffer and new data from UDP/SCTP, packs up a records
%% and returns it as a list of tls_compressed binaries also returns leftover
%% data
%%--------------------------------------------------------------------
-get_dtls_records(Data, <<>>) ->
- get_dtls_records_aux(Data, []);
-get_dtls_records(Data, Buffer) ->
- get_dtls_records_aux(list_to_binary([Buffer, Data]), []).
-
-get_dtls_records_aux(<<?BYTE(?APPLICATION_DATA),?BYTE(MajVer),?BYTE(MinVer),
- ?UINT16(Epoch), ?UINT48(SequenceNumber),
- ?UINT16(Length), Data:Length/binary, Rest/binary>>,
- Acc) ->
- get_dtls_records_aux(Rest, [#ssl_tls{type = ?APPLICATION_DATA,
- version = {MajVer, MinVer},
- epoch = Epoch, sequence_number = SequenceNumber,
- fragment = Data} | Acc]);
-get_dtls_records_aux(<<?BYTE(?HANDSHAKE),?BYTE(MajVer),?BYTE(MinVer),
- ?UINT16(Epoch), ?UINT48(SequenceNumber),
- ?UINT16(Length),
- Data:Length/binary, Rest/binary>>, Acc) when MajVer >= 128 ->
- get_dtls_records_aux(Rest, [#ssl_tls{type = ?HANDSHAKE,
- version = {MajVer, MinVer},
- epoch = Epoch, sequence_number = SequenceNumber,
- fragment = Data} | Acc]);
-get_dtls_records_aux(<<?BYTE(?ALERT),?BYTE(MajVer),?BYTE(MinVer),
- ?UINT16(Epoch), ?UINT48(SequenceNumber),
- ?UINT16(Length), Data:Length/binary,
- Rest/binary>>, Acc) ->
- get_dtls_records_aux(Rest, [#ssl_tls{type = ?ALERT,
- version = {MajVer, MinVer},
- epoch = Epoch, sequence_number = SequenceNumber,
- fragment = Data} | Acc]);
-get_dtls_records_aux(<<?BYTE(?CHANGE_CIPHER_SPEC),?BYTE(MajVer),?BYTE(MinVer),
- ?UINT16(Epoch), ?UINT48(SequenceNumber),
- ?UINT16(Length), Data:Length/binary, Rest/binary>>,
- Acc) ->
- get_dtls_records_aux(Rest, [#ssl_tls{type = ?CHANGE_CIPHER_SPEC,
- version = {MajVer, MinVer},
- epoch = Epoch, sequence_number = SequenceNumber,
- fragment = Data} | Acc]);
-
-get_dtls_records_aux(<<0:1, _CT:7, ?BYTE(_MajVer), ?BYTE(_MinVer),
- ?UINT16(Length), _/binary>>,
- _Acc) when Length > ?MAX_CIPHER_TEXT_LENGTH ->
- ?ALERT_REC(?FATAL, ?RECORD_OVERFLOW);
-
-get_dtls_records_aux(<<1:1, Length0:15, _/binary>>,_Acc)
- when Length0 > ?MAX_CIPHER_TEXT_LENGTH ->
- ?ALERT_REC(?FATAL, ?RECORD_OVERFLOW);
-
-get_dtls_records_aux(Data, Acc) ->
- case size(Data) =< ?MAX_CIPHER_TEXT_LENGTH + ?INITIAL_BYTES of
- true ->
- {lists:reverse(Acc), Data};
- false ->
- ?ALERT_REC(?FATAL, ?UNEXPECTED_MESSAGE)
+get_dtls_records(Data, Versions, Buffer) ->
+ BinData = list_to_binary([Buffer, Data]),
+ case erlang:byte_size(BinData) of
+ N when N >= 3 ->
+ case assert_version(BinData, Versions) of
+ true ->
+ get_dtls_records_aux(BinData, []);
+ false ->
+ ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
+ end;
+ _ ->
+ get_dtls_records_aux(BinData, [])
end.
+%%====================================================================
+%% Encoding DTLS records
+%%====================================================================
+
%%--------------------------------------------------------------------
-spec encode_handshake(iolist(), dtls_version(), integer(), ssl_record:connection_states()) ->
{iolist(), ssl_record:connection_states()}.
@@ -241,11 +234,19 @@ encode_plain_text(Type, Version, Epoch, Data, ConnectionStates) ->
{CipherText, Write} = encode_dtls_cipher_text(Type, Version, CipherFragment, Write1),
{CipherText, set_connection_state_by_epoch(Write, Epoch, ConnectionStates, write)}.
+%%====================================================================
+%% Decoding
+%%====================================================================
decode_cipher_text(#ssl_tls{epoch = Epoch} = CipherText, ConnnectionStates0) ->
ReadState = get_connection_state_by_epoch(Epoch, ConnnectionStates0, read),
decode_cipher_text(CipherText, ReadState, ConnnectionStates0).
+
+%%====================================================================
+%% Protocol version handling
+%%====================================================================
+
%%--------------------------------------------------------------------
-spec protocol_version(dtls_atom_version() | dtls_version()) ->
dtls_version() | dtls_atom_version().
@@ -377,35 +378,6 @@ supported_protocol_versions([_|_] = Vsns) ->
is_acceptable_version(Version, Versions) ->
lists:member(Version, Versions).
-
-%%--------------------------------------------------------------------
--spec init_connection_state_seq(dtls_version(), ssl_record:connection_states()) ->
- ssl_record:connection_state().
-%%
-%% Description: Copy the read sequence number to the write sequence number
-%% This is only valid for DTLS in the first client_hello
-%%--------------------------------------------------------------------
-init_connection_state_seq({254, _},
- #{current_read := #{epoch := 0, sequence_number := Seq},
- current_write := #{epoch := 0} = Write} = ConnnectionStates0) ->
- ConnnectionStates0#{current_write => Write#{sequence_number => Seq}};
-init_connection_state_seq(_, ConnnectionStates) ->
- ConnnectionStates.
-
-%%--------------------------------------------------------
--spec current_connection_state_epoch(ssl_record:connection_states(), read | write) ->
- integer().
-%%
-%% Description: Returns the epoch the connection_state record
-%% that is currently defined as the current connection state.
-%%--------------------------------------------------------------------
-current_connection_state_epoch(#{current_read := #{epoch := Epoch}},
- read) ->
- Epoch;
-current_connection_state_epoch(#{current_write := #{epoch := Epoch}},
- write) ->
- Epoch.
-
-spec hello_version(dtls_version(), [dtls_version()]) -> dtls_version().
hello_version(Version, Versions) ->
case dtls_v1:corresponding_tls_version(Version) of
@@ -433,16 +405,91 @@ initial_connection_state(ConnectionEnd, BeastMitigation) ->
client_verify_data => undefined,
server_verify_data => undefined
}.
+assert_version(<<?BYTE(_), ?BYTE(MajVer), ?BYTE(MinVer), _/binary>>, Versions) ->
+ is_acceptable_version({MajVer, MinVer}, Versions).
-lowest_list_protocol_version(Ver, []) ->
- Ver;
-lowest_list_protocol_version(Ver1, [Ver2 | Rest]) ->
- lowest_list_protocol_version(lowest_protocol_version(Ver1, Ver2), Rest).
+get_dtls_records_aux(<<?BYTE(?APPLICATION_DATA),?BYTE(MajVer),?BYTE(MinVer),
+ ?UINT16(Epoch), ?UINT48(SequenceNumber),
+ ?UINT16(Length), Data:Length/binary, Rest/binary>>,
+ Acc) ->
+ get_dtls_records_aux(Rest, [#ssl_tls{type = ?APPLICATION_DATA,
+ version = {MajVer, MinVer},
+ epoch = Epoch, sequence_number = SequenceNumber,
+ fragment = Data} | Acc]);
+get_dtls_records_aux(<<?BYTE(?HANDSHAKE),?BYTE(MajVer),?BYTE(MinVer),
+ ?UINT16(Epoch), ?UINT48(SequenceNumber),
+ ?UINT16(Length),
+ Data:Length/binary, Rest/binary>>, Acc) when MajVer >= 128 ->
+ get_dtls_records_aux(Rest, [#ssl_tls{type = ?HANDSHAKE,
+ version = {MajVer, MinVer},
+ epoch = Epoch, sequence_number = SequenceNumber,
+ fragment = Data} | Acc]);
+get_dtls_records_aux(<<?BYTE(?ALERT),?BYTE(MajVer),?BYTE(MinVer),
+ ?UINT16(Epoch), ?UINT48(SequenceNumber),
+ ?UINT16(Length), Data:Length/binary,
+ Rest/binary>>, Acc) ->
+ get_dtls_records_aux(Rest, [#ssl_tls{type = ?ALERT,
+ version = {MajVer, MinVer},
+ epoch = Epoch, sequence_number = SequenceNumber,
+ fragment = Data} | Acc]);
+get_dtls_records_aux(<<?BYTE(?CHANGE_CIPHER_SPEC),?BYTE(MajVer),?BYTE(MinVer),
+ ?UINT16(Epoch), ?UINT48(SequenceNumber),
+ ?UINT16(Length), Data:Length/binary, Rest/binary>>,
+ Acc) ->
+ get_dtls_records_aux(Rest, [#ssl_tls{type = ?CHANGE_CIPHER_SPEC,
+ version = {MajVer, MinVer},
+ epoch = Epoch, sequence_number = SequenceNumber,
+ fragment = Data} | Acc]);
+get_dtls_records_aux(<<?BYTE(_), ?BYTE(_MajVer), ?BYTE(_MinVer),
+ ?UINT16(Length), _/binary>>,
+ _Acc) when Length > ?MAX_CIPHER_TEXT_LENGTH ->
+ ?ALERT_REC(?FATAL, ?RECORD_OVERFLOW);
-highest_list_protocol_version(Ver, []) ->
- Ver;
-highest_list_protocol_version(Ver1, [Ver2 | Rest]) ->
- highest_list_protocol_version(highest_protocol_version(Ver1, Ver2), Rest).
+get_dtls_records_aux(Data, Acc) ->
+ case size(Data) =< ?MAX_CIPHER_TEXT_LENGTH + ?INITIAL_BYTES of
+ true ->
+ {lists:reverse(Acc), Data};
+ false ->
+ ?ALERT_REC(?FATAL, ?UNEXPECTED_MESSAGE)
+ end.
+%%--------------------------------------------------------------------
+
+init_replay_window(Size) ->
+ #{size => Size,
+ top => Size,
+ bottom => 0,
+ mask => 0 bsl 64
+ }.
+
+replay_detect(#ssl_tls{sequence_number = SequenceNumber}, #{replay_window := Window}) ->
+ is_replay(SequenceNumber, Window).
+
+
+is_replay(SequenceNumber, #{bottom := Bottom}) when SequenceNumber < Bottom ->
+ true;
+is_replay(SequenceNumber, #{size := Size,
+ top := Top,
+ bottom := Bottom,
+ mask := Mask}) when (SequenceNumber >= Bottom) andalso (SequenceNumber =< Top) ->
+ Index = (SequenceNumber rem Size),
+ (Index band Mask) == 1;
+
+is_replay(_, _) ->
+ false.
+
+update_replay_window(SequenceNumber, #{replay_window := #{size := Size,
+ top := Top,
+ bottom := Bottom,
+ mask := Mask0} = Window0} = ConnectionStates) ->
+ NoNewBits = SequenceNumber - Top,
+ Index = SequenceNumber rem Size,
+ Mask = (Mask0 bsl NoNewBits) bor Index,
+ Window = Window0#{top => SequenceNumber,
+ bottom => Bottom + NoNewBits,
+ mask => Mask},
+ ConnectionStates#{replay_window := Window}.
+
+%%--------------------------------------------------------------------
encode_dtls_cipher_text(Type, {MajVer, MinVer}, Fragment,
#{epoch := Epoch, sequence_number := Seq} = WriteState) ->
@@ -486,6 +533,7 @@ encode_plain_text(Type, Version, Fragment, #{compression_state := CompS0,
ssl_cipher:cipher(BulkCipherAlgo, CipherS0, MAC, Fragment, TLSVersion),
{CipherFragment, WriteState0#{cipher_state => CipherS1}}.
+%%--------------------------------------------------------------------
decode_cipher_text(#ssl_tls{type = Type, version = Version,
epoch = Epoch,
sequence_number = Seq,
@@ -537,6 +585,7 @@ decode_cipher_text(#ssl_tls{type = Type, version = Version,
false ->
?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
end.
+%%--------------------------------------------------------------------
calc_mac_hash(Type, Version, #{mac_secret := MacSecret,
security_parameters := #security_parameters{mac_algorithm = MacAlg}},
@@ -545,16 +594,6 @@ calc_mac_hash(Type, Version, #{mac_secret := MacSecret,
mac_hash(Version, MacAlg, MacSecret, Epoch, SeqNo, Type,
Length, Fragment).
-highest_protocol_version() ->
- highest_protocol_version(supported_protocol_versions()).
-
-lowest_protocol_version() ->
- lowest_protocol_version(supported_protocol_versions()).
-
-sufficient_dtlsv1_2_crypto_support() ->
- CryptoSupport = crypto:supports(),
- proplists:get_bool(sha256, proplists:get_value(hashs, CryptoSupport)).
-
mac_hash({Major, Minor}, MacAlg, MacSecret, Epoch, SeqNo, Type, Length, Fragment) ->
Value = [<<?UINT16(Epoch), ?UINT48(SeqNo), ?BYTE(Type),
?BYTE(Major), ?BYTE(Minor), ?UINT16(Length)>>,
@@ -564,37 +603,25 @@ mac_hash({Major, Minor}, MacAlg, MacSecret, Epoch, SeqNo, Type, Length, Fragment
calc_aad(Type, {MajVer, MinVer}, Epoch, SeqNo) ->
<<?UINT16(Epoch), ?UINT48(SeqNo), ?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer)>>.
-init_replay_window(Size) ->
- #{size => Size,
- top => Size,
- bottom => 0,
- mask => 0 bsl 64
- }.
+%%--------------------------------------------------------------------
-replay_detect(#ssl_tls{sequence_number = SequenceNumber}, #{replay_window := Window}) ->
- is_replay(SequenceNumber, Window).
+lowest_list_protocol_version(Ver, []) ->
+ Ver;
+lowest_list_protocol_version(Ver1, [Ver2 | Rest]) ->
+ lowest_list_protocol_version(lowest_protocol_version(Ver1, Ver2), Rest).
+highest_list_protocol_version(Ver, []) ->
+ Ver;
+highest_list_protocol_version(Ver1, [Ver2 | Rest]) ->
+ highest_list_protocol_version(highest_protocol_version(Ver1, Ver2), Rest).
-is_replay(SequenceNumber, #{bottom := Bottom}) when SequenceNumber < Bottom ->
- true;
-is_replay(SequenceNumber, #{size := Size,
- top := Top,
- bottom := Bottom,
- mask := Mask}) when (SequenceNumber >= Bottom) andalso (SequenceNumber =< Top) ->
- Index = (SequenceNumber rem Size),
- (Index band Mask) == 1;
+highest_protocol_version() ->
+ highest_protocol_version(supported_protocol_versions()).
-is_replay(_, _) ->
- false.
+lowest_protocol_version() ->
+ lowest_protocol_version(supported_protocol_versions()).
+
+sufficient_dtlsv1_2_crypto_support() ->
+ CryptoSupport = crypto:supports(),
+ proplists:get_bool(sha256, proplists:get_value(hashs, CryptoSupport)).
-update_replay_window(SequenceNumber, #{replay_window := #{size := Size,
- top := Top,
- bottom := Bottom,
- mask := Mask0} = Window0} = ConnectionStates) ->
- NoNewBits = SequenceNumber - Top,
- Index = SequenceNumber rem Size,
- Mask = (Mask0 bsl NoNewBits) bor Index,
- Window = Window0#{top => SequenceNumber,
- bottom => Bottom + NoNewBits,
- mask => Mask},
- ConnectionStates#{replay_window := Window}.
diff --git a/lib/ssl/src/dtls_socket.erl b/lib/ssl/src/dtls_socket.erl
index fbbd479428..2001afd02f 100644
--- a/lib/ssl/src/dtls_socket.erl
+++ b/lib/ssl/src/dtls_socket.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2016-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2016-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,33 +22,33 @@
-include("ssl_internal.hrl").
-include("ssl_api.hrl").
--export([send/3, listen/3, accept/3, connect/4, socket/4, setopts/3, getopts/3, getstat/3,
+-export([send/3, listen/2, accept/3, connect/4, socket/4, setopts/3, getopts/3, getstat/3,
peername/2, sockname/2, port/2, close/2]).
--export([emulated_options/0, internal_inet_values/0, default_inet_values/0, default_cb_info/0]).
+-export([emulated_options/0, emulated_options/1, internal_inet_values/0, default_inet_values/0, default_cb_info/0]).
send(Transport, {{IP,Port},Socket}, Data) ->
Transport:send(Socket, IP, Port, Data).
-listen(gen_udp = Transport, Port, #config{transport_info = {Transport, _, _, _},
- ssl = SslOpts,
- emulated = EmOpts,
- inet_user = Options} = Config) ->
+listen(Port, #config{transport_info = TransportInfo,
+ ssl = SslOpts,
+ emulated = EmOpts,
+ inet_user = Options} = Config) ->
- case dtls_udp_sup:start_child([Port, emulated_socket_options(EmOpts, #socket_options{}),
+ case dtls_listener_sup:start_child([Port, TransportInfo, emulated_socket_options(EmOpts, #socket_options{}),
Options ++ internal_inet_values(), SslOpts]) of
{ok, Pid} ->
- {ok, #sslsocket{pid = {udp, Config#config{udp_handler = {Pid, Port}}}}};
+ {ok, #sslsocket{pid = {dtls, Config#config{dtls_handler = {Pid, Port}}}}};
Err = {error, _} ->
Err
end.
-accept(udp, #config{transport_info = {Transport = gen_udp,_,_,_},
+accept(dtls, #config{transport_info = {Transport,_,_,_},
connection_cb = ConnectionCb,
- udp_handler = {Listner, _}}, _Timeout) ->
- case dtls_udp_listener:accept(Listner, self()) of
+ dtls_handler = {Listner, _}}, _Timeout) ->
+ case dtls_packet_demux:accept(Listner, self()) of
{ok, Pid, Socket} ->
- {ok, socket(Pid, Transport, {Listner, Socket}, ConnectionCb)};
+ {ok, socket([Pid], Transport, {Listner, Socket}, ConnectionCb)};
{error, Reason} ->
{error, Reason}
end.
@@ -69,28 +69,30 @@ connect(Address, Port, #config{transport_info = {Transport, _, _, _} = CbInfo,
end.
close(gen_udp, {_Client, _Socket}) ->
- ok.
+ ok;
+close(Transport, {_Client, Socket}) ->
+ Transport:close(Socket).
-socket(Pid, gen_udp = Transport, {{_, _}, Socket}, ConnectionCb) ->
- #sslsocket{pid = Pid,
+socket(Pids, gen_udp = Transport, {{_, _}, Socket}, ConnectionCb) ->
+ #sslsocket{pid = Pids,
%% "The name "fd" is keept for backwards compatibility
fd = {Transport, Socket, ConnectionCb}};
-socket(Pid, Transport, Socket, ConnectionCb) ->
- #sslsocket{pid = Pid,
+socket(Pids, Transport, Socket, ConnectionCb) ->
+ #sslsocket{pid = Pids,
%% "The name "fd" is keept for backwards compatibility
fd = {Transport, Socket, ConnectionCb}}.
-setopts(_, #sslsocket{pid = {udp, #config{udp_handler = {ListenPid, _}}}}, Options) ->
+setopts(_, #sslsocket{pid = {dtls, #config{dtls_handler = {ListenPid, _}}}}, Options) ->
SplitOpts = tls_socket:split_options(Options),
- dtls_udp_listener:set_sock_opts(ListenPid, SplitOpts);
+ dtls_packet_demux:set_sock_opts(ListenPid, SplitOpts);
%%% Following clauses will not be called for emulated options, they are handled in the connection process
setopts(gen_udp, Socket, Options) ->
inet:setopts(Socket, Options);
setopts(Transport, Socket, Options) ->
Transport:setopts(Socket, Options).
-getopts(_, #sslsocket{pid = {udp, #config{udp_handler = {ListenPid, _}}}}, Options) ->
+getopts(_, #sslsocket{pid = {dtls, #config{dtls_handler = {ListenPid, _}}}}, Options) ->
SplitOpts = tls_socket:split_options(Options),
- dtls_udp_listener:get_sock_opts(ListenPid, SplitOpts);
+ dtls_packet_demux:get_sock_opts(ListenPid, SplitOpts);
getopts(gen_udp, #sslsocket{pid = {Socket, #config{emulated = EmOpts}}}, Options) ->
{SockOptNames, EmulatedOptNames} = tls_socket:split_options(Options),
EmulatedOpts = get_emulated_opts(EmOpts, EmulatedOptNames),
@@ -112,7 +114,7 @@ getstat(gen_udp, {_,Socket}, Options) ->
inet:getstat(Socket, Options);
getstat(Transport, Socket, Options) ->
Transport:getstat(Socket, Options).
-peername(udp, _) ->
+peername(_, undefined) ->
{error, enotconn};
peername(gen_udp, {_, {Client, _Socket}}) ->
{ok, Client};
@@ -133,11 +135,14 @@ port(Transport, Socket) ->
emulated_options() ->
[mode, active, packet, packet_size].
+emulated_options(Opts) ->
+ emulated_options(Opts, internal_inet_values(), default_inet_values()).
+
internal_inet_values() ->
[{active, false}, {mode,binary}].
default_inet_values() ->
- [{active, true}, {mode, list}].
+ [{active, true}, {mode, list}, {packet, 0}, {packet_size, 0}].
default_cb_info() ->
{gen_udp, udp, udp_closed, udp_error}.
@@ -149,8 +154,38 @@ get_emulated_opts(EmOpts, EmOptNames) ->
emulated_socket_options(InetValues, #socket_options{
mode = Mode,
+ packet = Packet,
+ packet_size = PacketSize,
active = Active}) ->
#socket_options{
mode = proplists:get_value(mode, InetValues, Mode),
+ packet = proplists:get_value(packet, InetValues, Packet),
+ packet_size = proplists:get_value(packet_size, InetValues, PacketSize),
active = proplists:get_value(active, InetValues, Active)
}.
+
+emulated_options([{mode, Value} = Opt |Opts], Inet, Emulated) ->
+ validate_inet_option(mode, Value),
+ emulated_options(Opts, Inet, [Opt | proplists:delete(mode, Emulated)]);
+emulated_options([{header, _} = Opt | _], _, _) ->
+ throw({error, {options, {not_supported, Opt}}});
+emulated_options([{active, Value} = Opt |Opts], Inet, Emulated) ->
+ validate_inet_option(active, Value),
+ emulated_options(Opts, Inet, [Opt | proplists:delete(active, Emulated)]);
+emulated_options([{packet, _} = Opt | _], _, _) ->
+ throw({error, {options, {not_supported, Opt}}});
+emulated_options([{packet_size, _} = Opt | _], _, _) ->
+ throw({error, {options, {not_supported, Opt}}});
+emulated_options([Opt|Opts], Inet, Emulated) ->
+ emulated_options(Opts, [Opt|Inet], Emulated);
+emulated_options([], Inet,Emulated) ->
+ {Inet, Emulated}.
+
+validate_inet_option(mode, Value)
+ when Value =/= list, Value =/= binary ->
+ throw({error, {options, {mode,Value}}});
+validate_inet_option(active, Value)
+ when Value =/= true, Value =/= false, Value =/= once ->
+ throw({error, {options, {active,Value}}});
+validate_inet_option(_, _) ->
+ ok.
diff --git a/lib/ssl/src/dtls_udp_listener.erl b/lib/ssl/src/dtls_udp_listener.erl
deleted file mode 100644
index c789a32087..0000000000
--- a/lib/ssl/src/dtls_udp_listener.erl
+++ /dev/null
@@ -1,304 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2016-2017. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
--module(dtls_udp_listener).
-
--behaviour(gen_server).
-
--include("ssl_internal.hrl").
-
-%% API
--export([start_link/4, active_once/3, accept/2, sockname/1, close/1,
- get_all_opts/1, get_sock_opts/2, set_sock_opts/2]).
-
-%% gen_server callbacks
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- terminate/2, code_change/3]).
-
--record(state,
- {port,
- listner,
- dtls_options,
- emulated_options,
- dtls_msq_queues = kv_new(),
- clients = set_new(),
- dtls_processes = kv_new(),
- accepters = queue:new(),
- first,
- close
- }).
-
-%%%===================================================================
-%%% API
-%%%===================================================================
-
-start_link(Port, EmOpts, InetOptions, DTLSOptions) ->
- gen_server:start_link(?MODULE, [Port, EmOpts, InetOptions, DTLSOptions], []).
-
-active_once(UDPConnection, Client, Pid) ->
- gen_server:cast(UDPConnection, {active_once, Client, Pid}).
-
-accept(UDPConnection, Accepter) ->
- call(UDPConnection, {accept, Accepter}).
-
-sockname(UDPConnection) ->
- call(UDPConnection, sockname).
-close(UDPConnection) ->
- call(UDPConnection, close).
-get_sock_opts(UDPConnection, SplitSockOpts) ->
- call(UDPConnection, {get_sock_opts, SplitSockOpts}).
-get_all_opts(UDPConnection) ->
- call(UDPConnection, get_all_opts).
-set_sock_opts(UDPConnection, Opts) ->
- call(UDPConnection, {set_sock_opts, Opts}).
-
-%%%===================================================================
-%%% gen_server callbacks
-%%%===================================================================
-
-init([Port, EmOpts, InetOptions, DTLSOptions]) ->
- try
- {ok, Socket} = gen_udp:open(Port, InetOptions),
- {ok, #state{port = Port,
- first = true,
- dtls_options = DTLSOptions,
- emulated_options = EmOpts,
- listner = Socket,
- close = false}}
- catch _:_ ->
- {error, closed}
- end.
-handle_call({accept, _}, _, #state{close = true} = State) ->
- {reply, {error, closed}, State};
-
-handle_call({accept, Accepter}, From, #state{first = true,
- accepters = Accepters,
- listner = Socket} = State0) ->
- next_datagram(Socket),
- State = State0#state{first = false,
- accepters = queue:in({Accepter, From}, Accepters)},
- {noreply, State};
-
-handle_call({accept, Accepter}, From, #state{accepters = Accepters} = State0) ->
- State = State0#state{accepters = queue:in({Accepter, From}, Accepters)},
- {noreply, State};
-handle_call(sockname, _, #state{listner = Socket} = State) ->
- Reply = inet:sockname(Socket),
- {reply, Reply, State};
-handle_call(close, _, #state{dtls_processes = Processes,
- accepters = Accepters} = State) ->
- case kv_empty(Processes) of
- true ->
- {stop, normal, ok, State#state{close=true}};
- false ->
- lists:foreach(fun({_, From}) ->
- gen_server:reply(From, {error, closed})
- end, queue:to_list(Accepters)),
- {reply, ok, State#state{close = true, accepters = queue:new()}}
- end;
-handle_call({get_sock_opts, {SocketOptNames, EmOptNames}}, _, #state{listner = Socket,
- emulated_options = EmOpts} = State) ->
- case get_socket_opts(Socket, SocketOptNames) of
- {ok, Opts} ->
- {reply, {ok, emulated_opts_list(EmOpts, EmOptNames, []) ++ Opts}, State};
- {error, Reason} ->
- {reply, {error, Reason}, State}
- end;
-handle_call(get_all_opts, _, #state{dtls_options = DTLSOptions,
- emulated_options = EmOpts} = State) ->
- {reply, {ok, EmOpts, DTLSOptions}, State};
-handle_call({set_sock_opts, {SocketOpts, NewEmOpts}}, _, #state{listner = Socket, emulated_options = EmOpts0} = State) ->
- set_socket_opts(Socket, SocketOpts),
- EmOpts = do_set_emulated_opts(NewEmOpts, EmOpts0),
- {reply, ok, State#state{emulated_options = EmOpts}}.
-
-handle_cast({active_once, Client, Pid}, State0) ->
- State = handle_active_once(Client, Pid, State0),
- {noreply, State}.
-
-handle_info({udp, Socket, IP, InPortNo, _} = Msg, #state{listner = Socket} = State0) ->
- State = handle_datagram({IP, InPortNo}, Msg, State0),
- next_datagram(Socket),
- {noreply, State};
-
-%% UDP socket does not have a connection and should not receive an econnreset
-%% This does however happens on on some windows versions. Just ignoring it
-%% appears to make things work as expected!
-handle_info({udp_error, Socket, econnreset = Error}, #state{listner = Socket} = State) ->
- Report = io_lib:format("Ignore SSL UDP Listener: Socket error: ~p ~n", [Error]),
- error_logger:info_report(Report),
- {noreply, State};
-handle_info({udp_error, Socket, Error}, #state{listner = Socket} = State) ->
- Report = io_lib:format("SSL UDP Listener shutdown: Socket error: ~p ~n", [Error]),
- error_logger:info_report(Report),
- {noreply, State#state{close=true}};
-
-handle_info({'DOWN', _, process, Pid, _}, #state{clients = Clients,
- dtls_processes = Processes0,
- close = ListenClosed} = State) ->
- Client = kv_get(Pid, Processes0),
- Processes = kv_delete(Pid, Processes0),
- case ListenClosed andalso kv_empty(Processes) of
- true ->
- {stop, normal, State};
- false ->
- {noreply, State#state{clients = set_delete(Client, Clients),
- dtls_processes = Processes}}
- end.
-
-terminate(_Reason, _State) ->
- ok.
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%%===================================================================
-%%% Internal functions
-%%%===================================================================
-handle_datagram(Client, Msg, #state{clients = Clients,
- accepters = AcceptorsQueue0} = State) ->
- case set_is_member(Client, Clients) of
- false ->
- case queue:out(AcceptorsQueue0) of
- {{value, {UserPid, From}}, AcceptorsQueue} ->
- setup_new_connection(UserPid, From, Client, Msg,
- State#state{accepters = AcceptorsQueue});
- {empty, _} ->
- %% Drop packet client will resend
- State
- end;
- true ->
- dispatch(Client, Msg, State)
- end.
-
-dispatch(Client, Msg, #state{dtls_msq_queues = MsgQueues} = State) ->
- case kv_lookup(Client, MsgQueues) of
- {value, Queue0} ->
- case queue:out(Queue0) of
- {{value, Pid}, Queue} when is_pid(Pid) ->
- Pid ! Msg,
- State#state{dtls_msq_queues =
- kv_update(Client, Queue, MsgQueues)};
- {{value, _}, Queue} ->
- State#state{dtls_msq_queues =
- kv_update(Client, queue:in(Msg, Queue), MsgQueues)};
- {empty, Queue} ->
- State#state{dtls_msq_queues =
- kv_update(Client, queue:in(Msg, Queue), MsgQueues)}
- end
- end.
-next_datagram(Socket) ->
- inet:setopts(Socket, [{active, once}]).
-
-handle_active_once(Client, Pid, #state{dtls_msq_queues = MsgQueues} = State0) ->
- Queue0 = kv_get(Client, MsgQueues),
- case queue:out(Queue0) of
- {{value, Pid}, _} when is_pid(Pid) ->
- State0;
- {{value, Msg}, Queue} ->
- Pid ! Msg,
- State0#state{dtls_msq_queues = kv_update(Client, Queue, MsgQueues)};
- {empty, Queue0} ->
- State0#state{dtls_msq_queues = kv_update(Client, queue:in(Pid, Queue0), MsgQueues)}
- end.
-
-setup_new_connection(User, From, Client, Msg, #state{dtls_processes = Processes,
- clients = Clients,
- dtls_msq_queues = MsgQueues,
- dtls_options = DTLSOpts,
- port = Port,
- listner = Socket,
- emulated_options = EmOpts} = State) ->
- ConnArgs = [server, "localhost", Port, {self(), {Client, Socket}},
- {DTLSOpts, EmOpts, udp_listner}, User, dtls_socket:default_cb_info()],
- case dtls_connection_sup:start_child(ConnArgs) of
- {ok, Pid} ->
- erlang:monitor(process, Pid),
- gen_server:reply(From, {ok, Pid, {Client, Socket}}),
- Pid ! Msg,
- State#state{clients = set_insert(Client, Clients),
- dtls_msq_queues = kv_insert(Client, queue:new(), MsgQueues),
- dtls_processes = kv_insert(Pid, Client, Processes)};
- {error, Reason} ->
- gen_server:reply(From, {error, Reason}),
- State
- end.
-
-kv_update(Key, Value, Store) ->
- gb_trees:update(Key, Value, Store).
-kv_lookup(Key, Store) ->
- gb_trees:lookup(Key, Store).
-kv_insert(Key, Value, Store) ->
- gb_trees:insert(Key, Value, Store).
-kv_get(Key, Store) ->
- gb_trees:get(Key, Store).
-kv_delete(Key, Store) ->
- gb_trees:delete(Key, Store).
-kv_new() ->
- gb_trees:empty().
-kv_empty(Store) ->
- gb_trees:is_empty(Store).
-
-set_new() ->
- gb_sets:empty().
-set_insert(Item, Set) ->
- gb_sets:insert(Item, Set).
-set_delete(Item, Set) ->
- gb_sets:delete(Item, Set).
-set_is_member(Item, Set) ->
- gb_sets:is_member(Item, Set).
-
-call(Server, Msg) ->
- try
- gen_server:call(Server, Msg, infinity)
- catch
- exit:{noproc, _} ->
- {error, closed};
- exit:{normal, _} ->
- {error, closed};
- exit:{{shutdown, _},_} ->
- {error, closed}
- end.
-
-set_socket_opts(_, []) ->
- ok;
-set_socket_opts(Socket, SocketOpts) ->
- inet:setopts(Socket, SocketOpts).
-
-get_socket_opts(_, []) ->
- {ok, []};
-get_socket_opts(Socket, SocketOpts) ->
- inet:getopts(Socket, SocketOpts).
-
-do_set_emulated_opts([], Opts) ->
- Opts;
-do_set_emulated_opts([{mode, Value} | Rest], Opts) ->
- do_set_emulated_opts(Rest, Opts#socket_options{mode = Value});
-do_set_emulated_opts([{active, Value} | Rest], Opts) ->
- do_set_emulated_opts(Rest, Opts#socket_options{active = Value}).
-
-emulated_opts_list(_,[], Acc) ->
- Acc;
-emulated_opts_list( Opts, [mode | Rest], Acc) ->
- emulated_opts_list(Opts, Rest, [{mode, Opts#socket_options.mode} | Acc]);
-emulated_opts_list(Opts, [active | Rest], Acc) ->
- emulated_opts_list(Opts, Rest, [{active, Opts#socket_options.active} | Acc]).
-
diff --git a/lib/ssl/src/dtls_udp_sup.erl b/lib/ssl/src/dtls_udp_sup.erl
deleted file mode 100644
index 197882e92f..0000000000
--- a/lib/ssl/src/dtls_udp_sup.erl
+++ /dev/null
@@ -1,62 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2016-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Supervisor for a procsses dispatching upd datagrams to
-%% correct DTLS handler
-%%----------------------------------------------------------------------
--module(dtls_udp_sup).
-
--behaviour(supervisor).
-
-%% API
--export([start_link/0]).
--export([start_child/1]).
-
-%% Supervisor callback
--export([init/1]).
-
-%%%=========================================================================
-%%% API
-%%%=========================================================================
-start_link() ->
- supervisor:start_link({local, ?MODULE}, ?MODULE, []).
-
-start_child(Args) ->
- supervisor:start_child(?MODULE, Args).
-
-%%%=========================================================================
-%%% Supervisor callback
-%%%=========================================================================
-init(_O) ->
- RestartStrategy = simple_one_for_one,
- MaxR = 0,
- MaxT = 3600,
-
- Name = undefined, % As simple_one_for_one is used.
- StartFunc = {dtls_udp_listener, start_link, []},
- Restart = temporary, % E.g. should not be restarted
- Shutdown = 4000,
- Modules = [dtls_udp_listener],
- Type = worker,
-
- ChildSpec = {Name, StartFunc, Restart, Shutdown, Type, Modules},
- {ok, {{RestartStrategy, MaxR, MaxT}, [ChildSpec]}}.
diff --git a/lib/ssl/src/dtls_v1.erl b/lib/ssl/src/dtls_v1.erl
index 51ee8ec047..b365961a6a 100644
--- a/lib/ssl/src/dtls_v1.erl
+++ b/lib/ssl/src/dtls_v1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,25 +21,31 @@
-include("ssl_cipher.hrl").
--export([suites/1, all_suites/1, hmac_hash/3, ecc_curves/1,
+-export([suites/1, all_suites/1, anonymous_suites/1,hmac_hash/3, ecc_curves/1,
corresponding_tls_version/1, corresponding_dtls_version/1,
cookie_secret/0, cookie_timeout/0]).
-define(COOKIE_BASE_TIMEOUT, 30000).
--spec suites(Minor:: 253|255) -> [ssl_cipher:cipher_suite()].
+-spec suites(Minor:: 253|255) -> [ssl_cipher_format:cipher_suite()].
suites(Minor) ->
lists:filter(fun(Cipher) ->
- is_acceptable_cipher(ssl_cipher:suite_definition(Cipher))
+ is_acceptable_cipher(ssl_cipher_format:suite_definition(Cipher))
end,
tls_v1:suites(corresponding_minor_tls_version(Minor))).
all_suites(Version) ->
lists:filter(fun(Cipher) ->
- is_acceptable_cipher(ssl_cipher:suite_definition(Cipher))
+ is_acceptable_cipher(ssl_cipher_format:suite_definition(Cipher))
end,
ssl_cipher:all_suites(corresponding_tls_version(Version))).
+anonymous_suites(Version) ->
+ lists:filter(fun(Cipher) ->
+ is_acceptable_cipher(ssl_cipher_format:suite_definition(Cipher))
+ end,
+ ssl_cipher:anonymous_suites(corresponding_tls_version(Version))).
+
hmac_hash(MacAlg, MacSecret, Value) ->
tls_v1:hmac_hash(MacAlg, MacSecret, Value).
diff --git a/lib/ssl/src/inet6_tls_dist.erl b/lib/ssl/src/inet6_tls_dist.erl
index ffd7296f93..96ce4d493a 100644
--- a/lib/ssl/src/inet6_tls_dist.erl
+++ b/lib/ssl/src/inet6_tls_dist.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,8 @@
%%
-module(inet6_tls_dist).
--export([childspecs/0, listen/1, accept/1, accept_connection/5,
+-export([childspecs/0]).
+-export([listen/1, accept/1, accept_connection/5,
setup/5, close/1, select/1]).
childspecs() ->
@@ -43,4 +44,4 @@ setup(Node, Type, MyNode, LongOrShortNames,SetupTime) ->
inet_tls_dist:gen_setup(inet6_tcp, Node, Type, MyNode, LongOrShortNames,SetupTime).
close(Socket) ->
- inet_tls_dist:close(Socket).
+ inet_tls_dist:gen_close(inet6_tcp, Socket).
diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl
index 0da4b3587f..ca059603ae 100644
--- a/lib/ssl/src/inet_tls_dist.erl
+++ b/lib/ssl/src/inet_tls_dist.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,16 +21,28 @@
%%
-module(inet_tls_dist).
--export([childspecs/0, listen/1, accept/1, accept_connection/5,
+-export([childspecs/0]).
+-export([listen/1, accept/1, accept_connection/5,
setup/5, close/1, select/1, is_node_name/1]).
%% Generalized dist API
-export([gen_listen/2, gen_accept/2, gen_accept_connection/6,
- gen_setup/6, gen_select/2]).
+ gen_setup/6, gen_close/2, gen_select/2]).
+
+-export([nodelay/0]).
+
+-export([verify_client/3, cert_nodes/1]).
+
+-export([dbg/0]). % Debug
-include_lib("kernel/include/net_address.hrl").
-include_lib("kernel/include/dist.hrl").
-include_lib("kernel/include/dist_util.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+-include("ssl_api.hrl").
+
+%% -------------------------------------------------------------------------
childspecs() ->
{ok, [{ssl_dist_sup,{ssl_dist_sup, start_link, []},
@@ -40,103 +52,524 @@ select(Node) ->
gen_select(inet_tcp, Node).
gen_select(Driver, Node) ->
- case split_node(atom_to_list(Node), $@, []) of
- [_, Host] ->
- case inet:getaddr(Host, Driver:family()) of
+ case dist_util:split_node(Node) of
+ {node,_,Host} ->
+ case Driver:getaddr(Host) of
{ok, _} -> true;
_ -> false
end;
- _ ->
- false
+ _ ->
+ false
+ end.
+
+%% -------------------------------------------------------------------------
+
+is_node_name(Node) ->
+ dist_util:is_node_name(Node).
+
+%% -------------------------------------------------------------------------
+
+hs_data_common(#sslsocket{pid = [_, DistCtrl|_]} = SslSocket) ->
+ #hs_data{
+ f_send =
+ fun (_Ctrl, Packet) ->
+ f_send(SslSocket, Packet)
+ end,
+ f_recv =
+ fun (_, Length, Timeout) ->
+ f_recv(SslSocket, Length, Timeout)
+ end,
+ f_setopts_pre_nodeup =
+ fun (Ctrl) when Ctrl == DistCtrl ->
+ f_setopts_pre_nodeup(SslSocket)
+ end,
+ f_setopts_post_nodeup =
+ fun (Ctrl) when Ctrl == DistCtrl ->
+%%% sys:trace(Ctrl, true),
+ f_setopts_post_nodeup(SslSocket)
+ end,
+ f_getll =
+ fun (Ctrl) when Ctrl == DistCtrl ->
+ f_getll(DistCtrl)
+ end,
+ f_address =
+ fun (Ctrl, Node) when Ctrl == DistCtrl ->
+ f_address(SslSocket, Node)
+ end,
+ mf_tick =
+ fun (Ctrl) when Ctrl == DistCtrl ->
+ mf_tick(DistCtrl)
+ end,
+ mf_getstat =
+ fun (Ctrl) when Ctrl == DistCtrl ->
+ mf_getstat(SslSocket)
+ end,
+ mf_setopts =
+ fun (Ctrl, Opts) when Ctrl == DistCtrl ->
+ mf_setopts(SslSocket, Opts)
+ end,
+ mf_getopts =
+ fun (Ctrl, Opts) when Ctrl == DistCtrl ->
+ mf_getopts(SslSocket, Opts)
+ end,
+ f_handshake_complete =
+ fun (Ctrl, Node, DHandle) when Ctrl == DistCtrl ->
+ f_handshake_complete(DistCtrl, Node, DHandle)
+ end}.
+
+f_send(SslSocket, Packet) ->
+ ssl:send(SslSocket, Packet).
+
+f_recv(SslSocket, Length, Timeout) ->
+ case ssl:recv(SslSocket, Length, Timeout) of
+ {ok, Bin} when is_binary(Bin) ->
+ {ok, binary_to_list(Bin)};
+ Other ->
+ Other
end.
-is_node_name(Node) when is_atom(Node) ->
- select(Node);
-is_node_name(_) ->
- false.
+f_setopts_pre_nodeup(_SslSocket) ->
+ ok.
+
+f_setopts_post_nodeup(_SslSocket) ->
+ ok.
+
+f_getll(DistCtrl) ->
+ {ok, DistCtrl}.
+
+f_address(SslSocket, Node) ->
+ case ssl:peername(SslSocket) of
+ {ok, Address} ->
+ case dist_util:split_node(Node) of
+ {node,_,Host} ->
+ #net_address{
+ address=Address, host=Host,
+ protocol=tls, family=inet};
+ _ ->
+ {error, no_node}
+ end
+ end.
+
+mf_tick(DistCtrl) ->
+ DistCtrl ! tick,
+ ok.
+
+mf_getstat(SslSocket) ->
+ case ssl:getstat(
+ SslSocket, [recv_cnt, send_cnt, send_pend]) of
+ {ok, Stat} ->
+ split_stat(Stat,0,0,0);
+ Error ->
+ Error
+ end.
+
+mf_setopts(SslSocket, Opts) ->
+ case setopts_filter(Opts) of
+ [] ->
+ ssl:setopts(SslSocket, Opts);
+ Opts1 ->
+ {error, {badopts,Opts1}}
+ end.
+
+mf_getopts(SslSocket, Opts) ->
+ ssl:getopts(SslSocket, Opts).
+
+f_handshake_complete(DistCtrl, Node, DHandle) ->
+ tls_sender:dist_handshake_complete(DistCtrl, Node, DHandle).
+
+setopts_filter(Opts) ->
+ [Opt || {K,_} = Opt <- Opts,
+ K =:= active orelse K =:= deliver orelse K =:= packet].
+
+split_stat([{recv_cnt, R}|Stat], _, W, P) ->
+ split_stat(Stat, R, W, P);
+split_stat([{send_cnt, W}|Stat], R, _, P) ->
+ split_stat(Stat, R, W, P);
+split_stat([{send_pend, P}|Stat], R, W, _) ->
+ split_stat(Stat, R, W, P);
+split_stat([], R, W, P) ->
+ {ok, R, W, P}.
+
+%% -------------------------------------------------------------------------
listen(Name) ->
gen_listen(inet_tcp, Name).
gen_listen(Driver, Name) ->
- ssl_tls_dist_proxy:listen(Driver, Name).
+ case inet_tcp_dist:gen_listen(Driver, Name) of
+ {ok, {Socket, Address, Creation}} ->
+ inet:setopts(Socket, [{packet, 4}]),
+ {ok, {Socket, Address#net_address{protocol=tls}, Creation}};
+ Other ->
+ Other
+ end.
+
+%% -------------------------------------------------------------------------
accept(Listen) ->
gen_accept(inet_tcp, Listen).
gen_accept(Driver, Listen) ->
- ssl_tls_dist_proxy:accept(Driver, Listen).
+ Kernel = self(),
+ monitor_pid(
+ spawn_opt(
+ fun () ->
+ accept_loop(Driver, Listen, Kernel)
+ end,
+ [link, {priority, max}])).
+
+accept_loop(Driver, Listen, Kernel) ->
+ case Driver:accept(Listen) of
+ {ok, Socket} ->
+ case check_ip(Driver, Socket) of
+ true ->
+ accept_loop(Driver, Listen, Kernel, Socket);
+ {false,IP} ->
+ error_logger:error_msg(
+ "** Connection attempt from "
+ "disallowed IP ~w ** ~n", [IP]),
+ ?shutdown2(no_node, trace({disallowed, IP}))
+ end;
+ Error ->
+ exit(trace(Error))
+ end.
+
+accept_loop(Driver, Listen, Kernel, Socket) ->
+ Opts = setup_verify_client(Socket, get_ssl_options(server)),
+ wait_for_code_server(),
+ case
+ ssl:handshake(
+ Socket,
+ trace([{active, false},{packet, 4}|Opts]),
+ net_kernel:connecttime())
+ of
+ {ok, #sslsocket{pid = [_, DistCtrl| _]} = SslSocket} ->
+ trace(
+ Kernel !
+ {accept, self(), DistCtrl,
+ Driver:family(), tls}),
+ receive
+ {Kernel, controller, Pid} ->
+ ok = ssl:controlling_process(SslSocket, Pid),
+ trace(
+ Pid ! {self(), controller});
+ {Kernel, unsupported_protocol} ->
+ exit(trace(unsupported_protocol))
+ end,
+ accept_loop(Driver, Listen, Kernel);
+ {error, {options, _}} = Error ->
+ %% Bad options: that's probably our fault.
+ %% Let's log that.
+ error_logger:error_msg(
+ "Cannot accept TLS distribution connection: ~s~n",
+ [ssl:format_error(Error)]),
+ gen_tcp:close(Socket),
+ exit(trace(Error));
+ Other ->
+ gen_tcp:close(Socket),
+ exit(trace(Other))
+ end.
+
+
+%% {verify_fun,{fun ?MODULE:verify_client/3,_}} is used
+%% as a configuration marker that verify_client/3 shall be used.
+%%
+%% Replace the State in the first occurence of
+%% {verify_fun,{fun ?MODULE:verify_client/3,State}}
+%% and remove the rest.
+%% The inserted state is not accesible from a configuration file
+%% since it is dynamic and connection dependent.
+%%
+setup_verify_client(Socket, Opts) ->
+ setup_verify_client(Socket, Opts, true, []).
+%%
+setup_verify_client(_Socket, [], _, OptsR) ->
+ lists:reverse(OptsR);
+setup_verify_client(Socket, [Opt|Opts], First, OptsR) ->
+ case Opt of
+ {verify_fun,{Fun,_}} ->
+ case Fun =:= fun ?MODULE:verify_client/3 of
+ true ->
+ if
+ First ->
+ case inet:peername(Socket) of
+ {ok,{PeerIP,_Port}} ->
+ {ok,Allowed} = net_kernel:allowed(),
+ AllowedHosts = allowed_hosts(Allowed),
+ setup_verify_client(
+ Socket, Opts, false,
+ [{verify_fun,
+ {Fun, {AllowedHosts,PeerIP}}}
+ |OptsR]);
+ {error,Reason} ->
+ exit(trace({no_peername,Reason}))
+ end;
+ true ->
+ setup_verify_client(
+ Socket, Opts, First, OptsR)
+ end;
+ false ->
+ setup_verify_client(
+ Socket, Opts, First, [Opt|OptsR])
+ end;
+ _ ->
+ setup_verify_client(Socket, Opts, First, [Opt|OptsR])
+ end.
+
+allowed_hosts(Allowed) ->
+ lists:usort(allowed_node_hosts(Allowed)).
+%%
+allowed_node_hosts([]) -> [];
+allowed_node_hosts([Node|Allowed]) ->
+ case dist_util:split_node(Node) of
+ {node,_,Host} ->
+ [Host|allowed_node_hosts(Allowed)];
+ {host,Host} ->
+ [Host|allowed_node_hosts(Allowed)];
+ _ ->
+ allowed_node_hosts(Allowed)
+ end.
-accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
- gen_accept_connection(inet_tcp, AcceptPid, Socket, MyNode, Allowed, SetupTime).
+%% Same as verify_peer but check cert host names for
+%% peer IP address
+verify_client(_, {bad_cert,_} = Reason, _) ->
+ {fail,Reason};
+verify_client(_, {extension,_}, S) ->
+ {unknown,S};
+verify_client(_, valid, S) ->
+ {valid,S};
+verify_client(_, valid_peer, {[],_} = S) ->
+ %% Allow all hosts
+ {valid,S};
+verify_client(PeerCert, valid_peer, {AllowedHosts,PeerIP} = S) ->
+ case
+ public_key:pkix_verify_hostname(
+ PeerCert,
+ [{ip,PeerIP}|[{dns_id,Host} || Host <- AllowedHosts]])
+ of
+ true ->
+ {valid,S};
+ false ->
+ {fail,cert_no_hostname_nor_ip_match}
+ end.
+
+
+wait_for_code_server() ->
+ %% This is an ugly hack. Upgrading a socket to TLS requires the
+ %% crypto module to be loaded. Loading the crypto module triggers
+ %% its on_load function, which calls code:priv_dir/1 to find the
+ %% directory where its NIF library is. However, distribution is
+ %% started earlier than the code server, so the code server is not
+ %% necessarily started yet, and code:priv_dir/1 might fail because
+ %% of that, if we receive an incoming connection on the
+ %% distribution port early enough.
+ %%
+ %% If the on_load function of a module fails, the module is
+ %% unloaded, and the function call that triggered loading it fails
+ %% with 'undef', which is rather confusing.
+ %%
+ %% Thus, the accept process will terminate, and be
+ %% restarted by ssl_dist_sup. However, it won't have any memory
+ %% of being asked by net_kernel to listen for incoming
+ %% connections. Hence, the node will believe that it's open for
+ %% distribution, but it actually isn't.
+ %%
+ %% So let's avoid that by waiting for the code server to start.
+ case whereis(code_server) of
+ undefined ->
+ timer:sleep(10),
+ wait_for_code_server();
+ Pid when is_pid(Pid) ->
+ ok
+ end.
-gen_accept_connection(Driver, AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
+%% -------------------------------------------------------------------------
+
+accept_connection(AcceptPid, DistCtrl, MyNode, Allowed, SetupTime) ->
+ gen_accept_connection(
+ inet_tcp, AcceptPid, DistCtrl, MyNode, Allowed, SetupTime).
+
+gen_accept_connection(
+ Driver, AcceptPid, DistCtrl, MyNode, Allowed, SetupTime) ->
Kernel = self(),
- spawn_link(fun() -> do_accept(Driver, Kernel, AcceptPid, Socket,
- MyNode, Allowed, SetupTime) end).
+ monitor_pid(
+ spawn_opt(
+ fun() ->
+ do_accept(
+ Driver, AcceptPid, DistCtrl,
+ MyNode, Allowed, SetupTime, Kernel)
+ end,
+ [link, {priority, max}])).
-setup(Node, Type, MyNode, LongOrShortNames,SetupTime) ->
- gen_setup(inet_tcp, Node, Type, MyNode, LongOrShortNames,SetupTime).
+do_accept(
+ _Driver, AcceptPid, DistCtrl, MyNode, Allowed, SetupTime, Kernel) ->
+ {ok, SslSocket} = tls_sender:dist_tls_socket(DistCtrl),
+ receive
+ {AcceptPid, controller} ->
+ Timer = dist_util:start_timer(SetupTime),
+ NewAllowed = allowed_nodes(SslSocket, Allowed),
+ HSData0 = hs_data_common(SslSocket),
+ HSData =
+ HSData0#hs_data{
+ kernel_pid = Kernel,
+ this_node = MyNode,
+ socket = DistCtrl,
+ timer = Timer,
+ this_flags = 0,
+ allowed = NewAllowed},
+ link(DistCtrl),
+ dist_util:handshake_other_started(trace(HSData))
+ end.
+
+allowed_nodes(_SslSocket, []) ->
+ %% Allow all
+ [];
+allowed_nodes(SslSocket, Allowed) ->
+ case ssl:peercert(SslSocket) of
+ {ok,PeerCertDER} ->
+ case ssl:peername(SslSocket) of
+ {ok,{PeerIP,_Port}} ->
+ PeerCert =
+ public_key:pkix_decode_cert(PeerCertDER, otp),
+ case
+ allowed_nodes(
+ PeerCert, allowed_hosts(Allowed), PeerIP)
+ of
+ [] ->
+ error_logger:error_msg(
+ "** Connection attempt from "
+ "disallowed node(s) ~p ** ~n", [PeerIP]),
+ ?shutdown2(
+ PeerIP, trace({is_allowed, not_allowed}));
+ AllowedNodes ->
+ AllowedNodes
+ end;
+ Error1 ->
+ ?shutdown2(no_peer_ip, trace(Error1))
+ end;
+ {error,no_peercert} ->
+ Allowed;
+ Error2 ->
+ ?shutdown2(no_peer_cert, trace(Error2))
+ end.
-gen_setup(Driver, Node, Type, MyNode, LongOrShortNames,SetupTime) ->
+allowed_nodes(PeerCert, [], PeerIP) ->
+ case public_key:pkix_verify_hostname(PeerCert, [{ip,PeerIP}]) of
+ true ->
+ Host = inet:ntoa(PeerIP),
+ true = is_list(Host),
+ [Host];
+ false ->
+ []
+ end;
+allowed_nodes(PeerCert, [Node|Allowed], PeerIP) ->
+ case dist_util:split_node(Node) of
+ {node,_,Host} ->
+ allowed_nodes(PeerCert, Allowed, PeerIP, Node, Host);
+ {host,Host} ->
+ allowed_nodes(PeerCert, Allowed, PeerIP, Node, Host);
+ _ ->
+ allowed_nodes(PeerCert, Allowed, PeerIP)
+ end.
+
+allowed_nodes(PeerCert, Allowed, PeerIP, Node, Host) ->
+ case public_key:pkix_verify_hostname(PeerCert, [{dns_id,Host}]) of
+ true ->
+ [Node|allowed_nodes(PeerCert, Allowed, PeerIP)];
+ false ->
+ allowed_nodes(PeerCert, Allowed, PeerIP)
+ end.
+
+
+
+setup(Node, Type, MyNode, LongOrShortNames, SetupTime) ->
+ gen_setup(inet_tcp, Node, Type, MyNode, LongOrShortNames, SetupTime).
+
+gen_setup(Driver, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
Kernel = self(),
- spawn_opt(fun() -> do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) end, [link, {priority, max}]).
-
+ monitor_pid(
+ spawn_opt(
+ fun() ->
+ do_setup(
+ Driver, Kernel, Node, Type,
+ MyNode, LongOrShortNames, SetupTime)
+ end,
+ [link, {priority, max}])).
+
do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
- [Name, Address] = splitnode(Driver, Node, LongOrShortNames),
- case inet:getaddr(Address, Driver:family()) of
+ {Name, Address} = split_node(Driver, Node, LongOrShortNames),
+ ErlEpmd = net_kernel:epmd_module(),
+ {ARMod, ARFun} = get_address_resolver(ErlEpmd, Driver),
+ Timer = trace(dist_util:start_timer(SetupTime)),
+ case ARMod:ARFun(Name,Address,Driver:family()) of
+ {ok, Ip, TcpPort, Version} ->
+ do_setup_connect(Driver, Kernel, Node, Address, Ip, TcpPort, Version, Type, MyNode, Timer);
{ok, Ip} ->
- Timer = dist_util:start_timer(SetupTime),
- ErlEpmd = net_kernel:epmd_module(),
case ErlEpmd:port_please(Name, Ip) of
{port, TcpPort, Version} ->
- ?trace("port_please(~p) -> version ~p~n",
- [Node,Version]),
- dist_util:reset_timer(Timer),
- case ssl_tls_dist_proxy:connect(Driver, Ip, TcpPort) of
- {ok, Socket} ->
- HSData = connect_hs_data(Kernel, Node, MyNode, Socket,
- Timer, Version, Ip, TcpPort, Address,
- Type),
- dist_util:handshake_we_started(HSData);
- Other ->
- %% Other Node may have closed since
- %% port_please !
- ?trace("other node (~p) "
- "closed since port_please.~n",
- [Node]),
- ?shutdown2(Node, {shutdown, {connect_failed, Other}})
- end;
+ do_setup_connect(Driver, Kernel, Node, Address, Ip, TcpPort, Version, Type, MyNode, Timer);
Other ->
- ?trace("port_please (~p) "
- "failed.~n", [Node]),
- ?shutdown2(Node, {shutdown, {port_please_failed, Other}})
+ ?shutdown2(
+ Node,
+ trace(
+ {port_please_failed, ErlEpmd, Name, Ip, Other}))
end;
Other ->
- ?trace("inet_getaddr(~p) "
- "failed (~p).~n", [Node,Other]),
- ?shutdown2(Node, {shutdown, {inet_getaddr_failed, Other}})
+ ?shutdown2(
+ Node,
+ trace({getaddr_failed, Driver, Address, Other}))
+ end.
+
+do_setup_connect(Driver, Kernel, Node, Address, Ip, TcpPort, Version, Type, MyNode, Timer) ->
+ Opts = trace(connect_options(get_ssl_options(client))),
+ dist_util:reset_timer(Timer),
+ case ssl:connect(
+ Address, TcpPort,
+ [binary, {active, false}, {packet, 4},
+ Driver:family(), nodelay()] ++ Opts,
+ net_kernel:connecttime()) of
+ {ok, #sslsocket{pid = [_, DistCtrl| _]} = SslSocket} ->
+ _ = monitor_pid(DistCtrl),
+ ok = ssl:controlling_process(SslSocket, self()),
+ HSData0 = hs_data_common(SslSocket),
+ HSData =
+ HSData0#hs_data{
+ kernel_pid = Kernel,
+ other_node = Node,
+ this_node = MyNode,
+ socket = DistCtrl,
+ timer = Timer,
+ this_flags = 0,
+ other_version = Version,
+ request_type = Type},
+ link(DistCtrl),
+ dist_util:handshake_we_started(trace(HSData));
+ Other ->
+ %% Other Node may have closed since
+ %% port_please !
+ ?shutdown2(
+ Node,
+ trace(
+ {ssl_connect_failed, Ip, TcpPort, Other}))
end.
close(Socket) ->
- gen_tcp:close(Socket),
- ok.
+ gen_close(inet, Socket).
-do_accept(Driver, Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
- process_flag(priority, max),
- receive
- {AcceptPid, controller} ->
- Timer = dist_util:start_timer(SetupTime),
- case check_ip(Driver, Socket) of
- true ->
- HSData = accept_hs_data(Kernel, MyNode, Socket, Timer, Allowed),
- dist_util:handshake_other_started(HSData);
- {false,IP} ->
- error_logger:error_msg("** Connection attempt from "
- "disallowed IP ~w ** ~n", [IP]),
- ?shutdown(no_node)
- end
+gen_close(Driver, Socket) ->
+ trace(Driver:close(Socket)).
+
+
+%% ------------------------------------------------------------
+%% Determine if EPMD module supports address resolving. Default
+%% is to use inet_tcp:getaddr/2.
+%% ------------------------------------------------------------
+get_address_resolver(EpmdModule, Driver) ->
+ case erlang:function_exported(EpmdModule, address_please, 3) of
+ true -> {EpmdModule, address_please};
+ _ -> {Driver, getaddr}
end.
+
%% ------------------------------------------------------------
%% Do only accept new connection attempts from nodes at our
%% own LAN, if the check_ip environment parameter is true.
@@ -147,16 +580,26 @@ check_ip(Driver, Socket) ->
case get_ifs(Socket) of
{ok, IFs, IP} ->
check_ip(Driver, IFs, IP);
- _ ->
- ?shutdown(no_node)
+ Other ->
+ ?shutdown2(
+ no_node, trace({check_ip_failed, Socket, Other}))
end;
_ ->
true
end.
+check_ip(Driver, [{OwnIP, _, Netmask}|IFs], PeerIP) ->
+ case {Driver:mask(Netmask, PeerIP), Driver:mask(Netmask, OwnIP)} of
+ {M, M} -> true;
+ _ -> check_ip(IFs, PeerIP)
+ end;
+check_ip(_Driver, [], PeerIP) ->
+ {false, PeerIP}.
+
get_ifs(Socket) ->
case inet:peername(Socket) of
{ok, {IP, _}} ->
+ %% XXX this is seriously broken for IPv6
case inet:getif(Socket) of
{ok, IFs} -> {ok, IFs, IP};
Error -> Error
@@ -165,125 +608,262 @@ get_ifs(Socket) ->
Error
end.
-check_ip(Driver, [{OwnIP, _, Netmask}|IFs], PeerIP) ->
- case {Driver:mask(Netmask, PeerIP), Driver:mask(Netmask, OwnIP)} of
- {M, M} -> true;
- _ -> check_ip(IFs, PeerIP)
+
+%% Look in Extensions, in all subjectAltName:s
+%% to find node names in this certificate.
+%% Host names are picked up as a subjectAltName containing
+%% a dNSName, and the first subjectAltName containing
+%% a commonName is the node name.
+%%
+cert_nodes(
+ #'OTPCertificate'{
+ tbsCertificate = #'OTPTBSCertificate'{extensions = Extensions}}) ->
+ parse_extensions(Extensions).
+
+
+parse_extensions(Extensions) when is_list(Extensions) ->
+ parse_extensions(Extensions, [], []);
+parse_extensions(asn1_NOVALUE) ->
+ undefined. % Allow all nodes
+%%
+parse_extensions([], [], []) ->
+ undefined; % Allow all nodes
+parse_extensions([], Hosts, []) ->
+ lists:reverse(Hosts);
+parse_extensions([], [], Names) ->
+ [Name ++ "@" || Name <- lists:reverse(Names)];
+parse_extensions([], Hosts, Names) ->
+ [Name ++ "@" ++ Host ||
+ Host <- lists:reverse(Hosts),
+ Name <- lists:reverse(Names)];
+parse_extensions(
+ [#'Extension'{
+ extnID = ?'id-ce-subjectAltName',
+ extnValue = AltNames}
+ |Extensions],
+ Hosts, Names) ->
+ case parse_subject_altname(AltNames) of
+ none ->
+ parse_extensions(Extensions, Hosts, Names);
+ {host,Host} ->
+ parse_extensions(Extensions, [Host|Hosts], Names);
+ {name,Name} ->
+ parse_extensions(Extensions, Hosts, [Name|Names])
end;
-check_ip(_Driver, [], PeerIP) ->
- {false, PeerIP}.
+parse_extensions([_|Extensions], Hosts, Names) ->
+ parse_extensions(Extensions, Hosts, Names).
+
+parse_subject_altname([]) ->
+ none;
+parse_subject_altname([{dNSName,Host}|_AltNames]) ->
+ {host,Host};
+parse_subject_altname(
+ [{directoryName,{rdnSequence,[Rdn|_]}}|AltNames]) ->
+ %%
+ %% XXX Why is rdnSequence a sequence?
+ %% Should we parse all members?
+ %%
+ case parse_rdn(Rdn) of
+ none ->
+ parse_subject_altname(AltNames);
+ Name ->
+ {name,Name}
+ end;
+parse_subject_altname([_|AltNames]) ->
+ parse_subject_altname(AltNames).
+
+
+parse_rdn([]) ->
+ none;
+parse_rdn(
+ [#'AttributeTypeAndValue'{
+ type = ?'id-at-commonName',
+ value = {utf8String,CommonName}}|_]) ->
+ unicode:characters_to_list(CommonName);
+parse_rdn([_|Rdn]) ->
+ parse_rdn(Rdn).
%% If Node is illegal terminate the connection setup!!
-splitnode(Driver, Node, LongOrShortNames) ->
- case split_node(atom_to_list(Node), $@, []) of
- [Name|Tail] when Tail =/= [] ->
- Host = lists:append(Tail),
- check_node(Driver, Name, Node, Host, LongOrShortNames);
- [_] ->
- error_logger:error_msg("** Nodename ~p illegal, no '@' character **~n",
- [Node]),
- ?shutdown(Node);
+split_node(Driver, Node, LongOrShortNames) ->
+ case dist_util:split_node(Node) of
+ {node, Name, Host} ->
+ check_node(Driver, Node, Name, Host, LongOrShortNames);
+ {host, _} ->
+ error_logger:error_msg(
+ "** Nodename ~p illegal, no '@' character **~n",
+ [Node]),
+ ?shutdown2(Node, trace({illegal_node_n@me, Node}));
_ ->
- error_logger:error_msg("** Nodename ~p illegal **~n", [Node]),
- ?shutdown(Node)
+ error_logger:error_msg(
+ "** Nodename ~p illegal **~n", [Node]),
+ ?shutdown2(Node, trace({illegal_node_name, Node}))
end.
-check_node(Driver, Name, Node, Host, LongOrShortNames) ->
- case split_node(Host, $., []) of
- [_] when LongOrShortNames == longnames ->
+check_node(Driver, Node, Name, Host, LongOrShortNames) ->
+ case string:split(Host, ".", all) of
+ [_] when LongOrShortNames =:= longnames ->
case Driver:parse_address(Host) of
{ok, _} ->
- [Name, Host];
+ {Name, Host};
_ ->
- error_logger:error_msg("** System running to use "
- "fully qualified "
- "hostnames **~n"
- "** Hostname ~s is illegal **~n",
- [Host]),
- ?shutdown(Node)
+ error_logger:error_msg(
+ "** System running to use "
+ "fully qualified hostnames **~n"
+ "** Hostname ~s is illegal **~n",
+ [Host]),
+ ?shutdown2(Node, trace({not_longnames, Host}))
end;
- [_, _ | _] when LongOrShortNames == shortnames ->
- error_logger:error_msg("** System NOT running to use fully qualified "
- "hostnames **~n"
- "** Hostname ~s is illegal **~n",
- [Host]),
- ?shutdown(Node);
+ [_,_|_] when LongOrShortNames =:= shortnames ->
+ error_logger:error_msg(
+ "** System NOT running to use "
+ "fully qualified hostnames **~n"
+ "** Hostname ~s is illegal **~n",
+ [Host]),
+ ?shutdown2(Node, trace({not_shortnames, Host}));
_ ->
- [Name, Host]
+ {Name, Host}
end.
-split_node([Chr|T], Chr, Ack) ->
- [lists:reverse(Ack)|split_node(T, Chr, [])];
-split_node([H|T], Chr, Ack) ->
- split_node(T, Chr, [H|Ack]);
-split_node([], _, Ack) ->
- [lists:reverse(Ack)].
-
-connect_hs_data(Kernel, Node, MyNode, Socket, Timer, Version, Ip, TcpPort, Address, Type) ->
- common_hs_data(Kernel, MyNode, Socket, Timer,
- #hs_data{other_node = Node,
- other_version = Version,
- f_address =
- fun(_,_) ->
- #net_address{address = {Ip,TcpPort},
- host = Address,
- protocol = proxy,
- family = inet}
- end,
- request_type = Type
- }).
-
-accept_hs_data(Kernel, MyNode, Socket, Timer, Allowed) ->
- common_hs_data(Kernel, MyNode, Socket, Timer, #hs_data{
- allowed = Allowed,
- f_address = fun get_remote_id/2
- }).
-
-common_hs_data(Kernel, MyNode, Socket, Timer, HsData) ->
- HsData#hs_data{
- kernel_pid = Kernel,
- this_node = MyNode,
- socket = Socket,
- timer = Timer,
- this_flags = 0,
- f_send =
- fun(S,D) ->
- gen_tcp:send(S,D)
- end,
- f_recv =
- fun(S,N,T) ->
- gen_tcp:recv(S,N,T)
- end,
- f_setopts_pre_nodeup =
- fun(S) ->
- inet:setopts(S, [{active, false}, {packet, 4}])
- end,
- f_setopts_post_nodeup =
- fun(S) ->
- inet:setopts(S, [{deliver, port},{active, true}])
- end,
- f_getll =
- fun(S) ->
- inet:getll(S)
- end,
- mf_tick =
- fun(S) ->
- gen_tcp:send(S, <<>>)
- end,
- mf_getstat =
- fun(S) ->
- {ok, Stats} = inet:getstat(S, [recv_cnt, send_cnt, send_pend]),
- R = proplists:get_value(recv_cnt, Stats, 0),
- W = proplists:get_value(send_cnt, Stats, 0),
- P = proplists:get_value(send_pend, Stats, 0),
- {ok, R,W,P}
- end}.
-
-get_remote_id(Socket, _Node) ->
- case ssl_tls_dist_proxy:get_tcp_address(Socket) of
- {ok, Address} ->
- Address;
- {error, _Reason} ->
- ?shutdown(no_node)
+%% -------------------------------------------------------------------------
+
+connect_options(Opts) ->
+ case application:get_env(kernel, inet_dist_connect_options) of
+ {ok,ConnectOpts} ->
+ lists:ukeysort(1, ConnectOpts ++ Opts);
+ _ ->
+ Opts
+ end.
+
+%% we may not always want the nodelay behaviour
+%% for performance reasons
+nodelay() ->
+ case application:get_env(kernel, dist_nodelay) of
+ undefined ->
+ {nodelay, true};
+ {ok, true} ->
+ {nodelay, true};
+ {ok, false} ->
+ {nodelay, false};
+ _ ->
+ {nodelay, true}
+ end.
+
+
+get_ssl_options(Type) ->
+ try ets:lookup(ssl_dist_opts, Type) of
+ [{Type, Opts}] ->
+ [{erl_dist, true} | Opts];
+ _ ->
+ get_ssl_dist_arguments(Type)
+ catch
+ error:badarg ->
+ get_ssl_dist_arguments(Type)
+ end.
+
+get_ssl_dist_arguments(Type) ->
+ case init:get_argument(ssl_dist_opt) of
+ {ok, Args} ->
+ [{erl_dist, true} | ssl_options(Type, lists:append(Args))];
+ _ ->
+ [{erl_dist, true}]
+ end.
+
+
+ssl_options(_Type, []) ->
+ [];
+ssl_options(client, ["client_" ++ Opt, Value | T] = Opts) ->
+ ssl_options(client, T, Opts, Opt, Value);
+ssl_options(server, ["server_" ++ Opt, Value | T] = Opts) ->
+ ssl_options(server, T, Opts, Opt, Value);
+ssl_options(Type, [_Opt, _Value | T]) ->
+ ssl_options(Type, T).
+%%
+ssl_options(Type, T, Opts, Opt, Value) ->
+ case ssl_option(Type, Opt) of
+ error ->
+ error(malformed_ssl_dist_opt, [Type, Opts]);
+ Fun ->
+ [{list_to_atom(Opt), Fun(Value)}|ssl_options(Type, T)]
end.
+
+ssl_option(server, Opt) ->
+ case Opt of
+ "dhfile" -> fun listify/1;
+ "fail_if_no_peer_cert" -> fun atomize/1;
+ _ -> ssl_option(client, Opt)
+ end;
+ssl_option(client, Opt) ->
+ case Opt of
+ "certfile" -> fun listify/1;
+ "cacertfile" -> fun listify/1;
+ "keyfile" -> fun listify/1;
+ "password" -> fun listify/1;
+ "verify" -> fun atomize/1;
+ "verify_fun" -> fun verify_fun/1;
+ "crl_check" -> fun atomize/1;
+ "crl_cache" -> fun termify/1;
+ "reuse_sessions" -> fun atomize/1;
+ "secure_renegotiate" -> fun atomize/1;
+ "depth" -> fun erlang:list_to_integer/1;
+ "hibernate_after" -> fun erlang:list_to_integer/1;
+ "ciphers" -> fun listify/1;
+ _ -> error
+ end.
+
+listify(List) when is_list(List) ->
+ List.
+
+atomize(List) when is_list(List) ->
+ list_to_atom(List);
+atomize(Atom) when is_atom(Atom) ->
+ Atom.
+
+termify(String) when is_list(String) ->
+ {ok, Tokens, _} = erl_scan:string(String ++ "."),
+ {ok, Term} = erl_parse:parse_term(Tokens),
+ Term.
+
+verify_fun(Value) ->
+ case termify(Value) of
+ {Mod, Func, State} when is_atom(Mod), is_atom(Func) ->
+ Fun = fun Mod:Func/3,
+ {Fun, State};
+ _ ->
+ error(malformed_ssl_dist_opt, [Value])
+ end.
+
+%% -------------------------------------------------------------------------
+
+%% Trace point
+trace(Term) -> Term.
+
+%% Keep an eye on distribution Pid:s we know of
+monitor_pid(Pid) ->
+ %%spawn(
+ %% fun () ->
+ %% MRef = erlang:monitor(process, Pid),
+ %% receive
+ %% {'DOWN', MRef, _, _, normal} ->
+ %% error_logger:error_report(
+ %% [dist_proc_died,
+ %% {reason, normal},
+ %% {pid, Pid}]);
+ %% {'DOWN', MRef, _, _, Reason} ->
+ %% error_logger:info_report(
+ %% [dist_proc_died,
+ %% {reason, Reason},
+ %% {pid, Pid}])
+ %% end
+ %% end),
+ Pid.
+
+dbg() ->
+ dbg:stop(),
+ dbg:tracer(),
+ dbg:p(all, c),
+ dbg:tpl(?MODULE, cx),
+ dbg:tpl(erlang, dist_ctrl_get_data_notification, cx),
+ dbg:tpl(erlang, dist_ctrl_get_data, cx),
+ dbg:tpl(erlang, dist_ctrl_put_data, cx),
+ ok.
diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src
index 064dcd6892..936df12e70 100644
--- a/lib/ssl/src/ssl.app.src
+++ b/lib/ssl/src/ssl.app.src
@@ -9,8 +9,8 @@
tls_socket,
tls_v1,
ssl_v3,
- ssl_v2,
tls_connection_sup,
+ tls_sender,
%% DTLS
dtls_connection,
dtls_handshake,
@@ -18,12 +18,10 @@
dtls_socket,
dtls_v1,
dtls_connection_sup,
- dtls_udp_listener,
- dtls_udp_sup,
+ dtls_packet_demux,
+ dtls_listener_sup,
%% API
ssl, %% Main API
- tls, %% TLS specific
- dtls, %% DTLS specific
ssl_session_cache_api,
%% Both TLS/SSL and DTLS
ssl_config,
@@ -31,13 +29,13 @@
ssl_handshake,
ssl_record,
ssl_cipher,
+ ssl_cipher_format,
ssl_srp_primes,
ssl_alert,
ssl_listen_tracker_sup, %% may be used by DTLS over SCTP
%% Erlang Distribution over SSL/TLS
inet_tls_dist,
inet6_tls_dist,
- ssl_tls_dist_proxy,
ssl_dist_sup,
ssl_dist_connection_sup,
ssl_dist_admin_sup,
@@ -63,7 +61,5 @@
{applications, [crypto, public_key, kernel, stdlib]},
{env, []},
{mod, {ssl_app, []}},
- {runtime_dependencies, ["stdlib-3.2","public_key-1.2","kernel-3.0",
- "erts-7.0","crypto-3.3", "inets-5.10.7"]}]}.
-
-
+ {runtime_dependencies, ["stdlib-3.5","public_key-1.5","kernel-6.0",
+ "erts-10.0","crypto-4.2", "inets-5.10.7"]}]}.
diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src
index bfdd0c205b..ae4d60b6ed 100644
--- a/lib/ssl/src/ssl.appup.src
+++ b/lib/ssl/src/ssl.appup.src
@@ -1,6 +1,7 @@
%% -*- erlang -*-
{"%VSN%",
- [
+[
+ {<<"9\\..*">>, [{restart_application, ssl}]},
{<<"8\\..*">>, [{restart_application, ssl}]},
{<<"7\\..*">>, [{restart_application, ssl}]},
{<<"6\\..*">>, [{restart_application, ssl}]},
@@ -9,6 +10,7 @@
{<<"3\\..*">>, [{restart_application, ssl}]}
],
[
+ {<<"9\\..*">>, [{restart_application, ssl}]},
{<<"8\\..*">>, [{restart_application, ssl}]},
{<<"7\\..*">>, [{restart_application, ssl}]},
{<<"6\\..*">>, [{restart_application, ssl}]},
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 75eb308ba5..4cf56035ba 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,36 +23,43 @@
%%% Purpose : Main API module for SSL see also tls.erl and dtls.erl
-module(ssl).
--include("ssl_internal.hrl").
+
-include_lib("public_key/include/public_key.hrl").
+-include("ssl_internal.hrl").
+-include("ssl_api.hrl").
+-include("ssl_internal.hrl").
+-include("ssl_record.hrl").
+-include("ssl_cipher.hrl").
+-include("ssl_handshake.hrl").
+-include("ssl_srp.hrl").
+
%% Application handling
-export([start/0, start/1, stop/0, clear_pem_cache/0]).
%% Socket handling
-export([connect/3, connect/2, connect/4,
listen/2, transport_accept/1, transport_accept/2,
- ssl_accept/1, ssl_accept/2, ssl_accept/3,
+ handshake/1, handshake/2, handshake/3, handshake_continue/2,
+ handshake_continue/3, handshake_cancel/1,
+ ssl_accept/1, ssl_accept/2, ssl_accept/3,
controlling_process/2, peername/1, peercert/1, sockname/1,
close/1, close/2, shutdown/2, recv/2, recv/3, send/2,
getopts/2, setopts/2, getstat/1, getstat/2
]).
-%% SSL/TLS protocol handling
--export([cipher_suites/0, cipher_suites/1, eccs/0, eccs/1, versions/0,
+%% SSL/TLS protocol handling
+-export([cipher_suites/0, cipher_suites/1, cipher_suites/2, filter_cipher_suites/2,
+ prepend_cipher_suites/2, append_cipher_suites/2,
+ eccs/0, eccs/1, versions/0,
format_error/1, renegotiate/1, prf/5, negotiated_protocol/1,
connection_information/1, connection_information/2]).
%% Misc
--export([handle_options/2, tls_version/1]).
+-export([handle_options/2, tls_version/1, new_ssl_options/3, suite_to_str/1]).
--include("ssl_api.hrl").
--include("ssl_internal.hrl").
--include("ssl_record.hrl").
--include("ssl_cipher.hrl").
--include("ssl_handshake.hrl").
--include("ssl_srp.hrl").
-
--include_lib("public_key/include/public_key.hrl").
+-deprecated({ssl_accept, 1, eventually}).
+-deprecated({ssl_accept, 2, eventually}).
+-deprecated({ssl_accept, 3, eventually}).
%%--------------------------------------------------------------------
-spec start() -> ok | {error, reason()}.
@@ -168,23 +175,54 @@ transport_accept(#sslsocket{pid = {ListenSocket,
ok | {ok, #sslsocket{}} | {error, reason()}.
-spec ssl_accept(#sslsocket{} | port(), [ssl_option()] | [ssl_option()| transport_option()], timeout()) ->
- {ok, #sslsocket{}} | {error, reason()}.
+ ok | {ok, #sslsocket{}} | {error, reason()}.
%%
%% Description: Performs accept on an ssl listen socket. e.i. performs
%% ssl handshake.
%%--------------------------------------------------------------------
ssl_accept(ListenSocket) ->
- ssl_accept(ListenSocket, infinity).
+ ssl_accept(ListenSocket, [], infinity).
+ssl_accept(Socket, Timeout) when (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
+ ssl_accept(Socket, [], Timeout);
+ssl_accept(ListenSocket, SslOptions) when is_port(ListenSocket) ->
+ ssl_accept(ListenSocket, SslOptions, infinity);
+ssl_accept(Socket, Timeout) ->
+ ssl_accept(Socket, [], Timeout).
+ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket) ->
+ handshake(Socket, SslOptions, Timeout);
+ssl_accept(Socket, SslOptions, Timeout) ->
+ case handshake(Socket, SslOptions, Timeout) of
+ {ok, _} ->
+ ok;
+ Error ->
+ Error
+ end.
+%%--------------------------------------------------------------------
+-spec handshake(#sslsocket{}) -> {ok, #sslsocket{}} | {error, reason()}.
+-spec handshake(#sslsocket{} | port(), timeout()| [ssl_option()
+ | transport_option()]) ->
+ {ok, #sslsocket{}} | {error, reason()}.
-ssl_accept(#sslsocket{} = Socket, Timeout) when (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
+-spec handshake(#sslsocket{} | port(), [ssl_option()] | [ssl_option()| transport_option()], timeout()) ->
+ {ok, #sslsocket{}} | {error, reason()}.
+%%
+%% Description: Performs accept on an ssl listen socket. e.i. performs
+%% ssl handshake.
+%%--------------------------------------------------------------------
+handshake(ListenSocket) ->
+ handshake(ListenSocket, infinity).
+
+handshake(#sslsocket{} = Socket, Timeout) when (is_integer(Timeout) andalso Timeout >= 0) or
+ (Timeout == infinity) ->
ssl_connection:handshake(Socket, Timeout);
-ssl_accept(ListenSocket, SslOptions) when is_port(ListenSocket) ->
- ssl_accept(ListenSocket, SslOptions, infinity).
+handshake(ListenSocket, SslOptions) when is_port(ListenSocket) ->
+ handshake(ListenSocket, SslOptions, infinity).
-ssl_accept(#sslsocket{} = Socket, [], Timeout) when (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity)->
- ssl_accept(Socket, Timeout);
-ssl_accept(#sslsocket{fd = {_, _, _, Tracker}} = Socket, SslOpts, Timeout) when
+handshake(#sslsocket{} = Socket, [], Timeout) when (is_integer(Timeout) andalso Timeout >= 0) or
+ (Timeout == infinity)->
+ handshake(Socket, Timeout);
+handshake(#sslsocket{fd = {_, _, _, Tracker}} = Socket, SslOpts, Timeout) when
(is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity)->
try
{ok, EmOpts, _} = tls_socket:get_all_opts(Tracker),
@@ -193,17 +231,17 @@ ssl_accept(#sslsocket{fd = {_, _, _, Tracker}} = Socket, SslOpts, Timeout) when
catch
Error = {error, _Reason} -> Error
end;
-ssl_accept(#sslsocket{pid = Pid, fd = {_, _, _}} = Socket, SslOpts, Timeout) when
+handshake(#sslsocket{pid = [Pid|_], fd = {_, _, _}} = Socket, SslOpts, Timeout) when
(is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity)->
try
- {ok, EmOpts, _} = dtls_udp_listener:get_all_opts(Pid),
+ {ok, EmOpts, _} = dtls_packet_demux:get_all_opts(Pid),
ssl_connection:handshake(Socket, {SslOpts,
tls_socket:emulated_socket_options(EmOpts, #socket_options{})}, Timeout)
catch
Error = {error, _Reason} -> Error
end;
-ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket),
- (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
+handshake(Socket, SslOptions, Timeout) when is_port(Socket),
+ (is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
{Transport,_,_,_} =
proplists:get_value(cb_info, SslOptions, {gen_tcp, tcp, tcp_closed, tcp_error}),
EmulatedOptions = tls_socket:emulated_options(),
@@ -213,22 +251,50 @@ ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket),
{ok, #config{transport_info = CbInfo, ssl = SslOpts, emulated = EmOpts}} ->
ok = tls_socket:setopts(Transport, Socket, tls_socket:internal_inet_values()),
{ok, Port} = tls_socket:port(Transport, Socket),
- ssl_connection:ssl_accept(ConnetionCb, Port, Socket,
- {SslOpts,
- tls_socket:emulated_socket_options(EmOpts, #socket_options{}), undefined},
- self(), CbInfo, Timeout)
+ ssl_connection:handshake(ConnetionCb, Port, Socket,
+ {SslOpts,
+ tls_socket:emulated_socket_options(EmOpts, #socket_options{}), undefined},
+ self(), CbInfo, Timeout)
catch
Error = {error, _Reason} -> Error
end.
+
+
+%%--------------------------------------------------------------------
+-spec handshake_continue(#sslsocket{}, [ssl_option()]) ->
+ {ok, #sslsocket{}} | {error, reason()}.
+%%
+%%
+%% Description: Continues the handshke possible with newly supplied options.
+%%--------------------------------------------------------------------
+handshake_continue(Socket, SSLOptions) ->
+ handshake_continue(Socket, SSLOptions, infinity).
+%%--------------------------------------------------------------------
+-spec handshake_continue(#sslsocket{}, [ssl_option()], timeout()) ->
+ {ok, #sslsocket{}} | {error, reason()}.
+%%
+%%
+%% Description: Continues the handshke possible with newly supplied options.
+%%--------------------------------------------------------------------
+handshake_continue(Socket, SSLOptions, Timeout) ->
+ ssl_connection:handshake_continue(Socket, SSLOptions, Timeout).
+%%--------------------------------------------------------------------
+-spec handshake_cancel(#sslsocket{}) -> term().
+%%
+%% Description: Cancels the handshakes sending a close alert.
+%%--------------------------------------------------------------------
+handshake_cancel(Socket) ->
+ ssl_connection:handshake_cancel(Socket).
+
%%--------------------------------------------------------------------
-spec close(#sslsocket{}) -> term().
%%
%% Description: Close an ssl connection
%%--------------------------------------------------------------------
-close(#sslsocket{pid = Pid}) when is_pid(Pid) ->
+close(#sslsocket{pid = [Pid|_]}) when is_pid(Pid) ->
ssl_connection:close(Pid, {close, ?DEFAULT_TIMEOUT});
-close(#sslsocket{pid = {udp, #config{udp_handler = {Pid, _}}}}) ->
- dtls_udp_listener:close(Pid);
+close(#sslsocket{pid = {dtls, #config{dtls_handler = {Pid, _}}}}) ->
+ dtls_packet_demux:close(Pid);
close(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport,_, _, _}}}}) ->
Transport:close(ListenSocket).
@@ -237,12 +303,12 @@ close(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport,_, _, _}
%%
%% Description: Close an ssl connection
%%--------------------------------------------------------------------
-close(#sslsocket{pid = TLSPid},
+close(#sslsocket{pid = [TLSPid|_]},
{Pid, Timeout} = DownGrade) when is_pid(TLSPid),
is_pid(Pid),
(is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
ssl_connection:close(TLSPid, {close, DownGrade});
-close(#sslsocket{pid = TLSPid}, Timeout) when is_pid(TLSPid),
+close(#sslsocket{pid = [TLSPid|_]}, Timeout) when is_pid(TLSPid),
(is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
ssl_connection:close(TLSPid, {close, Timeout});
close(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport,_, _, _}}}}, _) ->
@@ -253,12 +319,14 @@ close(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport,_, _, _}
%%
%% Description: Sends data over the ssl connection
%%--------------------------------------------------------------------
-send(#sslsocket{pid = Pid}, Data) when is_pid(Pid) ->
+send(#sslsocket{pid = [Pid]}, Data) when is_pid(Pid) ->
ssl_connection:send(Pid, Data);
-send(#sslsocket{pid = {_, #config{transport_info={gen_udp, _, _, _}}}}, _) ->
+send(#sslsocket{pid = [_, Pid]}, Data) when is_pid(Pid) ->
+ tls_sender:send_data(Pid, erlang:iolist_to_binary(Data));
+send(#sslsocket{pid = {_, #config{transport_info={_, udp, _, _}}}}, _) ->
{error,enotconn}; %% Emulate connection behaviour
-send(#sslsocket{pid = {udp,_}}, _) ->
- {error,enotconn};
+send(#sslsocket{pid = {dtls,_}}, _) ->
+ {error,enotconn}; %% Emulate connection behaviour
send(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport, _, _, _}}}}, Data) ->
Transport:send(ListenSocket, Data). %% {error,enotconn}
@@ -270,10 +338,10 @@ send(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport, _, _, _}
%%--------------------------------------------------------------------
recv(Socket, Length) ->
recv(Socket, Length, infinity).
-recv(#sslsocket{pid = Pid}, Length, Timeout) when is_pid(Pid),
+recv(#sslsocket{pid = [Pid|_]}, Length, Timeout) when is_pid(Pid),
(is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity)->
ssl_connection:recv(Pid, Length, Timeout);
-recv(#sslsocket{pid = {udp,_}}, _, _) ->
+recv(#sslsocket{pid = {dtls,_}}, _, _) ->
{error,enotconn};
recv(#sslsocket{pid = {Listen,
#config{transport_info = {Transport, _, _, _}}}}, _,_) when is_port(Listen)->
@@ -285,9 +353,9 @@ recv(#sslsocket{pid = {Listen,
%% Description: Changes process that receives the messages when active = true
%% or once.
%%--------------------------------------------------------------------
-controlling_process(#sslsocket{pid = Pid}, NewOwner) when is_pid(Pid), is_pid(NewOwner) ->
+controlling_process(#sslsocket{pid = [Pid|_]}, NewOwner) when is_pid(Pid), is_pid(NewOwner) ->
ssl_connection:new_user(Pid, NewOwner);
-controlling_process(#sslsocket{pid = {udp, _}},
+controlling_process(#sslsocket{pid = {dtls, _}},
NewOwner) when is_pid(NewOwner) ->
ok; %% Meaningless but let it be allowed to conform with TLS
controlling_process(#sslsocket{pid = {Listen,
@@ -303,7 +371,7 @@ controlling_process(#sslsocket{pid = {Listen,
%%
%% Description: Return SSL information for the connection
%%--------------------------------------------------------------------
-connection_information(#sslsocket{pid = Pid}) when is_pid(Pid) ->
+connection_information(#sslsocket{pid = [Pid|_]}) when is_pid(Pid) ->
case ssl_connection:connection_information(Pid, false) of
{ok, Info} ->
{ok, [Item || Item = {_Key, Value} <- Info, Value =/= undefined]};
@@ -312,7 +380,7 @@ connection_information(#sslsocket{pid = Pid}) when is_pid(Pid) ->
end;
connection_information(#sslsocket{pid = {Listen, _}}) when is_port(Listen) ->
{error, enotconn};
-connection_information(#sslsocket{pid = {udp,_}}) ->
+connection_information(#sslsocket{pid = {dtls,_}}) ->
{error,enotconn}.
%%--------------------------------------------------------------------
@@ -320,7 +388,7 @@ connection_information(#sslsocket{pid = {udp,_}}) ->
%%
%% Description: Return SSL information for the connection
%%--------------------------------------------------------------------
-connection_information(#sslsocket{pid = Pid}, Items) when is_pid(Pid) ->
+connection_information(#sslsocket{pid = [Pid|_]}, Items) when is_pid(Pid) ->
case ssl_connection:connection_information(Pid, include_security_info(Items)) of
{ok, Info} ->
{ok, [Item || Item = {Key, Value} <- Info, lists:member(Key, Items),
@@ -334,17 +402,15 @@ connection_information(#sslsocket{pid = Pid}, Items) when is_pid(Pid) ->
%%
%% Description: same as inet:peername/1.
%%--------------------------------------------------------------------
-peername(#sslsocket{pid = Pid, fd = {Transport, Socket, _}}) when is_pid(Pid)->
+peername(#sslsocket{pid = [Pid|_], fd = {Transport, Socket, _}}) when is_pid(Pid)->
dtls_socket:peername(Transport, Socket);
-peername(#sslsocket{pid = Pid, fd = {Transport, Socket, _, _}}) when is_pid(Pid)->
+peername(#sslsocket{pid = [Pid|_], fd = {Transport, Socket, _, _}}) when is_pid(Pid)->
tls_socket:peername(Transport, Socket);
-peername(#sslsocket{pid = {udp = Transport, #config{udp_handler = {_Pid, _}}}}) ->
- dtls_socket:peername(Transport, undefined);
-peername(#sslsocket{pid = Pid, fd = {gen_udp= Transport, Socket, _, _}}) when is_pid(Pid) ->
- dtls_socket:peername(Transport, Socket);
+peername(#sslsocket{pid = {dtls, #config{dtls_handler = {_Pid, _}}}}) ->
+ dtls_socket:peername(dtls, undefined);
peername(#sslsocket{pid = {ListenSocket, #config{transport_info = {Transport,_,_,_}}}}) ->
tls_socket:peername(Transport, ListenSocket); %% Will return {error, enotconn}
-peername(#sslsocket{pid = {udp,_}}) ->
+peername(#sslsocket{pid = {dtls,_}}) ->
{error,enotconn}.
%%--------------------------------------------------------------------
@@ -352,14 +418,14 @@ peername(#sslsocket{pid = {udp,_}}) ->
%%
%% Description: Returns the peercert.
%%--------------------------------------------------------------------
-peercert(#sslsocket{pid = Pid}) when is_pid(Pid) ->
+peercert(#sslsocket{pid = [Pid|_]}) when is_pid(Pid) ->
case ssl_connection:peer_certificate(Pid) of
{ok, undefined} ->
{error, no_peercert};
Result ->
Result
end;
-peercert(#sslsocket{pid = {udp, _}}) ->
+peercert(#sslsocket{pid = {dtls, _}}) ->
{error, enotconn};
peercert(#sslsocket{pid = {Listen, _}}) when is_port(Listen) ->
{error, enotconn}.
@@ -370,27 +436,100 @@ peercert(#sslsocket{pid = {Listen, _}}) when is_port(Listen) ->
%% Description: Returns the protocol that has been negotiated. If no
%% protocol has been negotiated will return {error, protocol_not_negotiated}
%%--------------------------------------------------------------------
-negotiated_protocol(#sslsocket{pid = Pid}) ->
+negotiated_protocol(#sslsocket{pid = [Pid|_]}) when is_pid(Pid) ->
ssl_connection:negotiated_protocol(Pid).
%%--------------------------------------------------------------------
--spec cipher_suites() -> [ssl_cipher:erl_cipher_suite()] | [string()].
+-spec cipher_suites() -> [ssl_cipher_format:old_erl_cipher_suite()] | [string()].
%%--------------------------------------------------------------------
cipher_suites() ->
cipher_suites(erlang).
%%--------------------------------------------------------------------
--spec cipher_suites(erlang | openssl | all) -> [ssl_cipher:erl_cipher_suite()] |
- [string()].
+-spec cipher_suites(erlang | openssl | all) ->
+ [ssl_cipher_format:old_erl_cipher_suite() | string()].
%% Description: Returns all supported cipher suites.
%%--------------------------------------------------------------------
cipher_suites(erlang) ->
- [ssl_cipher:erl_suite_definition(Suite) || Suite <- available_suites(default)];
+ [ssl_cipher_format:erl_suite_definition(Suite) || Suite <- available_suites(default)];
cipher_suites(openssl) ->
- [ssl_cipher:openssl_suite_name(Suite) || Suite <- available_suites(default)];
+ [ssl_cipher_format:openssl_suite_name(Suite) ||
+ Suite <- available_suites(default)];
cipher_suites(all) ->
- [ssl_cipher:erl_suite_definition(Suite) || Suite <- available_suites(all)].
+ [ssl_cipher_format:erl_suite_definition(Suite) || Suite <- available_suites(all)].
+
+%%--------------------------------------------------------------------
+-spec cipher_suites(default | all | anonymous, tls_record:tls_version() | dtls_record:dtls_version() |
+ tls_record:tls_atom_version() | dtls_record:dtls_atom_version()) ->
+ [ssl_cipher_format:erl_cipher_suite()].
+%% Description: Returns all default and all supported cipher suites for a
+%% TLS/DTLS version
+%%--------------------------------------------------------------------
+cipher_suites(Base, Version) when Version == 'tlsv1.2';
+ Version == 'tlsv1.1';
+ Version == tlsv1;
+ Version == sslv3 ->
+ cipher_suites(Base, tls_record:protocol_version(Version));
+cipher_suites(Base, Version) when Version == 'dtlsv1.2';
+ Version == 'dtlsv1'->
+ cipher_suites(Base, dtls_record:protocol_version(Version));
+cipher_suites(Base, Version) ->
+ [ssl_cipher_format:suite_definition(Suite) || Suite <- supported_suites(Base, Version)].
+
+%%--------------------------------------------------------------------
+-spec filter_cipher_suites([ssl_cipher_format:erl_cipher_suite()],
+ [{key_exchange | cipher | mac | prf, fun()}] | []) ->
+ [ssl_cipher_format:erl_cipher_suite()].
+%% Description: Removes cipher suites if any of the filter functions returns false
+%% for any part of the cipher suite. This function also calls default filter functions
+%% to make sure the cipher suite are supported by crypto.
+%%--------------------------------------------------------------------
+filter_cipher_suites(Suites, Filters0) ->
+ #{key_exchange_filters := KexF,
+ cipher_filters := CipherF,
+ mac_filters := MacF,
+ prf_filters := PrfF}
+ = ssl_cipher:crypto_support_filters(),
+ Filters = #{key_exchange_filters => add_filter(proplists:get_value(key_exchange, Filters0), KexF),
+ cipher_filters => add_filter(proplists:get_value(cipher, Filters0), CipherF),
+ mac_filters => add_filter(proplists:get_value(mac, Filters0), MacF),
+ prf_filters => add_filter(proplists:get_value(prf, Filters0), PrfF)},
+ ssl_cipher:filter_suites(Suites, Filters).
+%%--------------------------------------------------------------------
+-spec prepend_cipher_suites([ssl_cipher_format:erl_cipher_suite()] |
+ [{key_exchange | cipher | mac | prf, fun()}],
+ [ssl_cipher_format:erl_cipher_suite()]) ->
+ [ssl_cipher_format:erl_cipher_suite()].
+%% Description: Make <Preferred> suites become the most prefered
+%% suites that is put them at the head of the cipher suite list
+%% and remove them from <Suites> if present. <Preferred> may be a
+%% list of cipher suits or a list of filters in which case the
+%% filters are use on Suites to extract the the preferred
+%% cipher list.
+%% --------------------------------------------------------------------
+prepend_cipher_suites([First | _] = Preferred, Suites0) when is_map(First) ->
+ Suites = Preferred ++ (Suites0 -- Preferred),
+ Suites;
+prepend_cipher_suites(Filters, Suites) ->
+ Preferred = filter_cipher_suites(Suites, Filters),
+ Preferred ++ (Suites -- Preferred).
+%%--------------------------------------------------------------------
+-spec append_cipher_suites(Deferred :: [ssl_cipher_format:erl_cipher_suite()] |
+ [{key_exchange | cipher | mac | prf, fun()}],
+ [ssl_cipher_format:erl_cipher_suite()]) ->
+ [ssl_cipher_format:erl_cipher_suite()].
+%% Description: Make <Deferred> suites suites become the
+%% least prefered suites that is put them at the end of the cipher suite list
+%% and removed them from <Suites> if present.
+%%
+%%--------------------------------------------------------------------
+append_cipher_suites([First | _] = Deferred, Suites0) when is_map(First)->
+ Suites = (Suites0 -- Deferred) ++ Deferred,
+ Suites;
+append_cipher_suites(Filters, Suites) ->
+ Deferred = filter_cipher_suites(Suites, Filters),
+ (Suites -- Deferred) ++ Deferred.
%%--------------------------------------------------------------------
-spec eccs() -> tls_v1:curves().
@@ -401,8 +540,9 @@ eccs() ->
eccs_filter_supported(Curves).
%%--------------------------------------------------------------------
--spec eccs(tls_record:tls_version() | tls_record:tls_atom_version()) ->
- tls_v1:curves().
+-spec eccs(tls_record:tls_version() | tls_record:tls_atom_version() |
+ dtls_record:dtls_version() | dtls_record:dtls_atom_version()) ->
+ tls_v1:curves().
%% Description: returns the curves supported for a given version of
%% ssl/tls.
%%--------------------------------------------------------------------
@@ -411,8 +551,16 @@ eccs({3,0}) ->
eccs({3,_}) ->
Curves = tls_v1:ecc_curves(all),
eccs_filter_supported(Curves);
-eccs(AtomVersion) when is_atom(AtomVersion) ->
- eccs(tls_record:protocol_version(AtomVersion)).
+eccs({254,_} = Version) ->
+ eccs(dtls_v1:corresponding_tls_version(Version));
+eccs(Version) when Version == 'tlsv1.2';
+ Version == 'tlsv1.1';
+ Version == tlsv1;
+ Version == sslv3 ->
+ eccs(tls_record:protocol_version(Version));
+eccs(Version) when Version == 'dtlsv1.2';
+ Version == 'dtlsv1'->
+ eccs(dtls_v1:corresponding_tls_version(dtls_record:protocol_version(Version))).
eccs_filter_supported(Curves) ->
CryptoCurves = crypto:ec_curves(),
@@ -425,9 +573,9 @@ eccs_filter_supported(Curves) ->
%%
%% Description: Gets options
%%--------------------------------------------------------------------
-getopts(#sslsocket{pid = Pid}, OptionTags) when is_pid(Pid), is_list(OptionTags) ->
+getopts(#sslsocket{pid = [Pid|_]}, OptionTags) when is_pid(Pid), is_list(OptionTags) ->
ssl_connection:get_opts(Pid, OptionTags);
-getopts(#sslsocket{pid = {udp, #config{transport_info = {Transport,_,_,_}}}} = ListenSocket, OptionTags) when is_list(OptionTags) ->
+getopts(#sslsocket{pid = {dtls, #config{transport_info = {Transport,_,_,_}}}} = ListenSocket, OptionTags) when is_list(OptionTags) ->
try dtls_socket:getopts(Transport, ListenSocket, OptionTags) of
{ok, _} = Result ->
Result;
@@ -456,7 +604,7 @@ getopts(#sslsocket{}, OptionTags) ->
%%
%% Description: Sets options
%%--------------------------------------------------------------------
-setopts(#sslsocket{pid = Pid}, Options0) when is_pid(Pid), is_list(Options0) ->
+setopts(#sslsocket{pid = [Pid|_]}, Options0) when is_pid(Pid), is_list(Options0) ->
try proplists:expand([{binary, [{mode, binary}]},
{list, [{mode, list}]}], Options0) of
Options ->
@@ -465,7 +613,7 @@ setopts(#sslsocket{pid = Pid}, Options0) when is_pid(Pid), is_list(Options0) ->
_:_ ->
{error, {options, {not_a_proplist, Options0}}}
end;
-setopts(#sslsocket{pid = {udp, #config{transport_info = {Transport,_,_,_}}}} = ListenSocket, Options) when is_list(Options) ->
+setopts(#sslsocket{pid = {dtls, #config{transport_info = {Transport,_,_,_}}}} = ListenSocket, Options) when is_list(Options) ->
try dtls_socket:setopts(Transport, ListenSocket, Options) of
ok ->
ok;
@@ -511,7 +659,7 @@ getstat(Socket) ->
getstat(#sslsocket{pid = {Listen, #config{transport_info = {Transport, _, _, _}}}}, Options) when is_port(Listen), is_list(Options) ->
tls_socket:getstat(Transport, Listen, Options);
-getstat(#sslsocket{pid = Pid, fd = {Transport, Socket, _, _}}, Options) when is_pid(Pid), is_list(Options) ->
+getstat(#sslsocket{pid = [Pid|_], fd = {Transport, Socket, _, _}}, Options) when is_pid(Pid), is_list(Options) ->
tls_socket:getstat(Transport, Socket, Options).
%%---------------------------------------------------------------
@@ -522,9 +670,9 @@ getstat(#sslsocket{pid = Pid, fd = {Transport, Socket, _, _}}, Options) when is_
shutdown(#sslsocket{pid = {Listen, #config{transport_info = {Transport,_, _, _}}}},
How) when is_port(Listen) ->
Transport:shutdown(Listen, How);
-shutdown(#sslsocket{pid = {udp,_}},_) ->
+shutdown(#sslsocket{pid = {dtls,_}},_) ->
{error, enotconn};
-shutdown(#sslsocket{pid = Pid}, How) ->
+shutdown(#sslsocket{pid = [Pid|_]}, How) when is_pid(Pid) ->
ssl_connection:shutdown(Pid, How).
%%--------------------------------------------------------------------
@@ -534,25 +682,32 @@ shutdown(#sslsocket{pid = Pid}, How) ->
%%--------------------------------------------------------------------
sockname(#sslsocket{pid = {Listen, #config{transport_info = {Transport, _, _, _}}}}) when is_port(Listen) ->
tls_socket:sockname(Transport, Listen);
-sockname(#sslsocket{pid = {udp, #config{udp_handler = {Pid, _}}}}) ->
- dtls_udp_listener:sockname(Pid);
-sockname(#sslsocket{pid = Pid, fd = {Transport, Socket, _}}) when is_pid(Pid) ->
+sockname(#sslsocket{pid = {dtls, #config{dtls_handler = {Pid, _}}}}) ->
+ dtls_packet_demux:sockname(Pid);
+sockname(#sslsocket{pid = [Pid|_], fd = {Transport, Socket, _}}) when is_pid(Pid) ->
dtls_socket:sockname(Transport, Socket);
-sockname(#sslsocket{pid = Pid, fd = {Transport, Socket, _, _}}) when is_pid(Pid) ->
+sockname(#sslsocket{pid = [Pid| _], fd = {Transport, Socket, _, _}}) when is_pid(Pid) ->
tls_socket:sockname(Transport, Socket).
%%---------------------------------------------------------------
-spec versions() -> [{ssl_app, string()} | {supported, [tls_record:tls_atom_version()]} |
- {available, [tls_record:tls_atom_version()]}].
+ {supported_dtls, [dtls_record:dtls_atom_version()]} |
+ {available, [tls_record:tls_atom_version()]} |
+ {available_dtls, [dtls_record:dtls_atom_version()]}].
%%
%% Description: Returns a list of relevant versions.
%%--------------------------------------------------------------------
versions() ->
- Vsns = tls_record:supported_protocol_versions(),
- SupportedVsns = [tls_record:protocol_version(Vsn) || Vsn <- Vsns],
- AvailableVsns = ?ALL_AVAILABLE_VERSIONS,
- %% TODO Add DTLS versions when supported
- [{ssl_app, ?VSN}, {supported, SupportedVsns}, {available, AvailableVsns}].
+ TLSVsns = tls_record:supported_protocol_versions(),
+ DTLSVsns = dtls_record:supported_protocol_versions(),
+ SupportedTLSVsns = [tls_record:protocol_version(Vsn) || Vsn <- TLSVsns],
+ SupportedDTLSVsns = [dtls_record:protocol_version(Vsn) || Vsn <- DTLSVsns],
+ AvailableTLSVsns = ?ALL_AVAILABLE_VERSIONS,
+ AvailableDTLSVsns = ?ALL_AVAILABLE_DATAGRAM_VERSIONS,
+ [{ssl_app, ?VSN}, {supported, SupportedTLSVsns},
+ {supported_dtls, SupportedDTLSVsns},
+ {available, AvailableTLSVsns},
+ {available_dtls, AvailableDTLSVsns}].
%%---------------------------------------------------------------
@@ -560,24 +715,32 @@ versions() ->
%%
%% Description: Initiates a renegotiation.
%%--------------------------------------------------------------------
-renegotiate(#sslsocket{pid = Pid}) when is_pid(Pid) ->
+renegotiate(#sslsocket{pid = [Pid, Sender |_]}) when is_pid(Pid),
+ is_pid(Sender) ->
+ case tls_sender:renegotiate(Sender) of
+ {ok, Write} ->
+ tls_connection:renegotiation(Pid, Write);
+ Error ->
+ Error
+ end;
+renegotiate(#sslsocket{pid = [Pid |_]}) when is_pid(Pid) ->
ssl_connection:renegotiation(Pid);
-renegotiate(#sslsocket{pid = {udp,_}}) ->
+renegotiate(#sslsocket{pid = {dtls,_}}) ->
{error, enotconn};
renegotiate(#sslsocket{pid = {Listen,_}}) when is_port(Listen) ->
{error, enotconn}.
%%--------------------------------------------------------------------
-spec prf(#sslsocket{}, binary() | 'master_secret', binary(),
- binary() | prf_random(), non_neg_integer()) ->
+ [binary() | prf_random()], non_neg_integer()) ->
{ok, binary()} | {error, reason()}.
%%
%% Description: use a ssl sessions TLS PRF to generate key material
%%--------------------------------------------------------------------
-prf(#sslsocket{pid = Pid},
+prf(#sslsocket{pid = [Pid|_]},
Secret, Label, Seed, WantedLength) when is_pid(Pid) ->
ssl_connection:prf(Pid, Secret, Label, Seed, WantedLength);
-prf(#sslsocket{pid = {udp,_}}, _,_,_,_) ->
+prf(#sslsocket{pid = {dtls,_}}, _,_,_,_) ->
{error, enotconn};
prf(#sslsocket{pid = {Listen,_}}, _,_,_,_) when is_port(Listen) ->
{error, enotconn}.
@@ -629,24 +792,39 @@ tls_version({3, _} = Version) ->
tls_version({254, _} = Version) ->
dtls_v1:corresponding_tls_version(Version).
+
+%%--------------------------------------------------------------------
+-spec suite_to_str(ssl_cipher_format:erl_cipher_suite()) -> string().
+%%
+%% Description: Return the string representation of a cipher suite.
+%%--------------------------------------------------------------------
+suite_to_str(Cipher) ->
+ ssl_cipher_format:suite_to_str(Cipher).
+
+
%%%--------------------------------------------------------------
%%% Internal functions
%%%--------------------------------------------------------------------
-
%% Possible filters out suites not supported by crypto
available_suites(default) ->
Version = tls_record:highest_protocol_version([]),
ssl_cipher:filter_suites(ssl_cipher:suites(Version));
-
available_suites(all) ->
Version = tls_record:highest_protocol_version([]),
ssl_cipher:filter_suites(ssl_cipher:all_suites(Version)).
+supported_suites(default, Version) ->
+ ssl_cipher:suites(Version);
+supported_suites(all, Version) ->
+ ssl_cipher:all_suites(Version);
+supported_suites(anonymous, Version) ->
+ ssl_cipher:anonymous_suites(Version).
+
do_listen(Port, #config{transport_info = {Transport, _, _, _}} = Config, tls_connection) ->
tls_socket:listen(Transport, Port, Config);
-do_listen(Port, #config{transport_info = {Transport, _, _, _}} = Config, dtls_connection) ->
- dtls_socket:listen(Transport, Port, Config).
+do_listen(Port, Config, dtls_connection) ->
+ dtls_socket:listen(Port, Config).
%% Handle extra ssl options given to ssl_accept
-spec handle_options([any()], #ssl_options{}) -> #ssl_options{}
@@ -713,6 +891,13 @@ handle_options(Opts0, Role, Host) ->
Protocol = handle_option(protocol, Opts, tls),
+ case Versions of
+ [{3, 0}] ->
+ reject_alpn_next_prot_options(Opts);
+ _ ->
+ ok
+ end,
+
SSLOptions = #ssl_options{
versions = Versions,
verify = validate_option(verify, Verify),
@@ -744,7 +929,7 @@ handle_options(Opts0, Role, Host) ->
%% Server side option
reuse_session = handle_option(reuse_session, Opts, ReuseSessionFun),
reuse_sessions = handle_option(reuse_sessions, Opts, true),
- secure_renegotiate = handle_option(secure_renegotiate, Opts, false),
+ secure_renegotiate = handle_option(secure_renegotiate, Opts, true),
client_renegotiation = handle_option(client_renegotiation, Opts,
default_option_role(server, true, Role),
server, Role),
@@ -782,8 +967,9 @@ handle_options(Opts0, Role, Host) ->
client, Role),
crl_check = handle_option(crl_check, Opts, false),
crl_cache = handle_option(crl_cache, Opts, {ssl_crl_cache, {internal, []}}),
- v2_hello_compatible = handle_option(v2_hello_compatible, Opts, false),
- max_handshake_size = handle_option(max_handshake_size, Opts, ?DEFAULT_MAX_HANDSHAKE_SIZE)
+ max_handshake_size = handle_option(max_handshake_size, Opts, ?DEFAULT_MAX_HANDSHAKE_SIZE),
+ handshake = handle_option(handshake, Opts, full),
+ customize_hostname_check = handle_option(customize_hostname_check, Opts, [])
},
CbInfo = proplists:get_value(cb_info, Opts, default_cb_info(Protocol)),
@@ -798,9 +984,8 @@ handle_options(Opts0, Role, Host) ->
alpn_preferred_protocols, next_protocols_advertised,
client_preferred_next_protocols, log_alert,
server_name_indication, honor_cipher_order, padding_check, crl_check, crl_cache,
- fallback, signature_algs, eccs, honor_ecc_order, beast_mitigation, v2_hello_compatible,
- max_handshake_size],
-
+ fallback, signature_algs, eccs, honor_ecc_order, beast_mitigation,
+ max_handshake_size, handshake, customize_hostname_check],
SockOpts = lists:foldl(fun(Key, PropList) ->
proplists:delete(Key, PropList)
end, Opts, SslOptions),
@@ -809,11 +994,9 @@ handle_options(Opts0, Role, Host) ->
ConnetionCb = connection_cb(Opts),
{ok, #config{ssl = SSLOptions, emulated = Emulated, inet_ssl = Sock,
- inet_user = SockOpts, transport_info = CbInfo, connection_cb = ConnetionCb
+ inet_user = Sock, transport_info = CbInfo, connection_cb = ConnetionCb
}}.
-
-
handle_option(OptionName, Opts, Default, Role, Role) ->
handle_option(OptionName, Opts, Default);
handle_option(_, _, undefined = Value, _, _) ->
@@ -889,7 +1072,8 @@ validate_option(key, {KeyType, Value}) when is_binary(Value),
KeyType == 'ECPrivateKey';
KeyType == 'PrivateKeyInfo' ->
{KeyType, Value};
-
+validate_option(key, #{algorithm := _} = Value) ->
+ Value;
validate_option(keyfile, undefined) ->
<<>>;
validate_option(keyfile, Value) when is_binary(Value) ->
@@ -956,70 +1140,51 @@ validate_option(hibernate_after, Value) when is_integer(Value), Value >= 0 ->
validate_option(erl_dist,Value) when is_boolean(Value) ->
Value;
-validate_option(Opt, Value)
- when Opt =:= alpn_advertised_protocols orelse Opt =:= alpn_preferred_protocols,
- is_list(Value) ->
- case tls_record:highest_protocol_version([]) of
- {3,0} ->
- throw({error, {options, {not_supported_in_sslv3, {Opt, Value}}}});
- _ ->
- validate_binary_list(Opt, Value),
- Value
- end;
+validate_option(Opt, Value) when Opt =:= alpn_advertised_protocols orelse Opt =:= alpn_preferred_protocols,
+ is_list(Value) ->
+ validate_binary_list(Opt, Value),
+ Value;
validate_option(Opt, Value)
when Opt =:= alpn_advertised_protocols orelse Opt =:= alpn_preferred_protocols,
Value =:= undefined ->
undefined;
-validate_option(client_preferred_next_protocols = Opt, {Precedence, PreferredProtocols} = Value)
+validate_option(client_preferred_next_protocols, {Precedence, PreferredProtocols})
when is_list(PreferredProtocols) ->
- case tls_record:highest_protocol_version([]) of
- {3,0} ->
- throw({error, {options, {not_supported_in_sslv3, {Opt, Value}}}});
- _ ->
- validate_binary_list(client_preferred_next_protocols, PreferredProtocols),
- validate_npn_ordering(Precedence),
- {Precedence, PreferredProtocols, ?NO_PROTOCOL}
- end;
-validate_option(client_preferred_next_protocols = Opt, {Precedence, PreferredProtocols, Default} = Value)
- when is_list(PreferredProtocols), is_binary(Default),
- byte_size(Default) > 0, byte_size(Default) < 256 ->
- case tls_record:highest_protocol_version([]) of
- {3,0} ->
- throw({error, {options, {not_supported_in_sslv3, {Opt, Value}}}});
- _ ->
- validate_binary_list(client_preferred_next_protocols, PreferredProtocols),
- validate_npn_ordering(Precedence),
- Value
- end;
-
+ validate_binary_list(client_preferred_next_protocols, PreferredProtocols),
+ validate_npn_ordering(Precedence),
+ {Precedence, PreferredProtocols, ?NO_PROTOCOL};
+validate_option(client_preferred_next_protocols, {Precedence, PreferredProtocols, Default} = Value)
+ when is_list(PreferredProtocols), is_binary(Default),
+ byte_size(Default) > 0, byte_size(Default) < 256 ->
+ validate_binary_list(client_preferred_next_protocols, PreferredProtocols),
+ validate_npn_ordering(Precedence),
+ Value;
validate_option(client_preferred_next_protocols, undefined) ->
undefined;
validate_option(log_alert, Value) when is_boolean(Value) ->
Value;
-validate_option(next_protocols_advertised = Opt, Value) when is_list(Value) ->
- case tls_record:highest_protocol_version([]) of
- {3,0} ->
- throw({error, {options, {not_supported_in_sslv3, {Opt, Value}}}});
- _ ->
- validate_binary_list(next_protocols_advertised, Value),
- Value
- end;
-
+validate_option(next_protocols_advertised, Value) when is_list(Value) ->
+ validate_binary_list(next_protocols_advertised, Value),
+ Value;
validate_option(next_protocols_advertised, undefined) ->
undefined;
-validate_option(server_name_indication = Opt, Value) when is_list(Value) ->
+validate_option(server_name_indication, Value) when is_list(Value) ->
%% RFC 6066, Section 3: Currently, the only server names supported are
%% DNS hostnames
- case inet_parse:domain(Value) of
- false ->
- throw({error, {options, {{Opt, Value}}}});
- true ->
- Value
- end;
-validate_option(server_name_indication, undefined = Value) ->
+ %% case inet_parse:domain(Value) of
+ %% false ->
+ %% throw({error, {options, {{Opt, Value}}}});
+ %% true ->
+ %% Value
+ %% end;
+ %%
+ %% But the definition seems very diffuse, so let all strings through
+ %% and leave it up to public_key to decide...
Value;
-validate_option(server_name_indication, disable) ->
+validate_option(server_name_indication, undefined) ->
undefined;
+validate_option(server_name_indication, disable) ->
+ disable;
validate_option(sni_hosts, []) ->
[];
@@ -1053,14 +1218,18 @@ validate_option(beast_mitigation, Value) when Value == one_n_minus_one orelse
Value == zero_n orelse
Value == disabled ->
Value;
-validate_option(v2_hello_compatible, Value) when is_boolean(Value) ->
- Value;
validate_option(max_handshake_size, Value) when is_integer(Value) andalso Value =< ?MAX_UNIT24 ->
Value;
validate_option(protocol, Value = tls) ->
Value;
validate_option(protocol, Value = dtls) ->
Value;
+validate_option(handshake, hello = Value) ->
+ Value;
+validate_option(handshake, full = Value) ->
+ Value;
+validate_option(customize_hostname_check, Value) when is_list(Value) ->
+ Value;
validate_option(Opt, Value) ->
throw({error, {options, {Opt, Value}}}).
@@ -1129,24 +1298,6 @@ dtls_validate_versions([Version | Rest], Versions) when Version == 'dtlsv1';
dtls_validate_versions([Ver| _], Versions) ->
throw({error, {options, {Ver, {versions, Versions}}}}).
-validate_inet_option(mode, Value)
- when Value =/= list, Value =/= binary ->
- throw({error, {options, {mode,Value}}});
-validate_inet_option(packet, Value)
- when not (is_atom(Value) orelse is_integer(Value)) ->
- throw({error, {options, {packet,Value}}});
-validate_inet_option(packet_size, Value)
- when not is_integer(Value) ->
- throw({error, {options, {packet_size,Value}}});
-validate_inet_option(header, Value)
- when not is_integer(Value) ->
- throw({error, {options, {header,Value}}});
-validate_inet_option(active, Value)
- when Value =/= true, Value =/= false, Value =/= once ->
- throw({error, {options, {active,Value}}});
-validate_inet_option(_, _) ->
- ok.
-
%% The option cacerts overrides cacertsfile
ca_cert_default(_,_, [_|_]) ->
undefined;
@@ -1161,31 +1312,11 @@ ca_cert_default(verify_peer, undefined, _) ->
emulated_options(Protocol, Opts) ->
case Protocol of
tls ->
- emulated_options(Opts, tls_socket:internal_inet_values(), tls_socket:default_inet_values());
+ tls_socket:emulated_options(Opts);
dtls ->
- emulated_options(Opts, dtls_socket:internal_inet_values(), dtls_socket:default_inet_values())
+ dtls_socket:emulated_options(Opts)
end.
-emulated_options([{mode, Value} = Opt |Opts], Inet, Emulated) ->
- validate_inet_option(mode, Value),
- emulated_options(Opts, Inet, [Opt | proplists:delete(mode, Emulated)]);
-emulated_options([{header, Value} = Opt | Opts], Inet, Emulated) ->
- validate_inet_option(header, Value),
- emulated_options(Opts, Inet, [Opt | proplists:delete(header, Emulated)]);
-emulated_options([{active, Value} = Opt |Opts], Inet, Emulated) ->
- validate_inet_option(active, Value),
- emulated_options(Opts, Inet, [Opt | proplists:delete(active, Emulated)]);
-emulated_options([{packet, Value} = Opt |Opts], Inet, Emulated) ->
- validate_inet_option(packet, Value),
- emulated_options(Opts, Inet, [Opt | proplists:delete(packet, Emulated)]);
-emulated_options([{packet_size, Value} = Opt | Opts], Inet, Emulated) ->
- validate_inet_option(packet_size, Value),
- emulated_options(Opts, Inet, [Opt | proplists:delete(packet_size, Emulated)]);
-emulated_options([Opt|Opts], Inet, Emulated) ->
- emulated_options(Opts, [Opt|Inet], Emulated);
-emulated_options([], Inet,Emulated) ->
- {Inet, Emulated}.
-
handle_cipher_option(Value, Version) when is_list(Value) ->
try binary_cipher_suites(Version, Value) of
Suites ->
@@ -1200,30 +1331,57 @@ handle_cipher_option(Value, Version) when is_list(Value) ->
binary_cipher_suites(Version, []) ->
%% Defaults to all supported suites that does
%% not require explicit configuration
- ssl_cipher:filter_suites(ssl_cipher:suites(tls_version(Version)));
+ default_binary_suites(Version);
+binary_cipher_suites(Version, [Map|_] = Ciphers0) when is_map(Map) ->
+ Ciphers = [ssl_cipher_format:suite(C) || C <- Ciphers0],
+ binary_cipher_suites(Version, Ciphers);
binary_cipher_suites(Version, [Tuple|_] = Ciphers0) when is_tuple(Tuple) ->
- Ciphers = [ssl_cipher:suite(C) || C <- Ciphers0],
+ Ciphers = [ssl_cipher_format:suite(tuple_to_map(C)) || C <- Ciphers0],
binary_cipher_suites(Version, Ciphers);
-
binary_cipher_suites(Version, [Cipher0 | _] = Ciphers0) when is_binary(Cipher0) ->
- All = ssl_cipher:all_suites(tls_version(Version)),
+ All = ssl_cipher:all_suites(Version) ++
+ ssl_cipher:anonymous_suites(Version),
case [Cipher || Cipher <- Ciphers0, lists:member(Cipher, All)] of
[] ->
%% Defaults to all supported suites that does
%% not require explicit configuration
- ssl_cipher:filter_suites(ssl_cipher:suites(tls_version(Version)));
+ default_binary_suites(Version);
Ciphers ->
Ciphers
end;
binary_cipher_suites(Version, [Head | _] = Ciphers0) when is_list(Head) ->
%% Format: ["RC4-SHA","RC4-MD5"]
- Ciphers = [ssl_cipher:openssl_suite(C) || C <- Ciphers0],
+ Ciphers = [ssl_cipher_format:openssl_suite(C) || C <- Ciphers0],
binary_cipher_suites(Version, Ciphers);
binary_cipher_suites(Version, Ciphers0) ->
%% Format: "RC4-SHA:RC4-MD5"
- Ciphers = [ssl_cipher:openssl_suite(C) || C <- string:tokens(Ciphers0, ":")],
+ Ciphers = [ssl_cipher_format:openssl_suite(C) || C <- string:lexemes(Ciphers0, ":")],
binary_cipher_suites(Version, Ciphers).
+default_binary_suites(Version) ->
+ ssl_cipher:filter_suites(ssl_cipher:suites(Version)).
+
+tuple_to_map({Kex, Cipher, Mac}) ->
+ #{key_exchange => Kex,
+ cipher => Cipher,
+ mac => Mac,
+ prf => default_prf};
+tuple_to_map({Kex, Cipher, Mac, Prf}) ->
+ #{key_exchange => Kex,
+ cipher => Cipher,
+ mac => tuple_to_map_mac(Cipher, Mac),
+ prf => Prf}.
+
+%% Backwards compatible
+tuple_to_map_mac(aes_128_gcm, _) ->
+ aead;
+tuple_to_map_mac(aes_256_gcm, _) ->
+ aead;
+tuple_to_map_mac(chacha20_poly1305, _) ->
+ aead;
+tuple_to_map_mac(_, MAC) ->
+ MAC.
+
handle_eccs_option(Value, Version) when is_list(Value) ->
{_Major, Minor} = tls_version(Version),
try tls_v1:ecc_curves(Minor, Value) of
@@ -1483,3 +1641,27 @@ server_name_indication_default(Host) when is_list(Host) ->
Host;
server_name_indication_default(_) ->
undefined.
+
+
+reject_alpn_next_prot_options(Opts) ->
+ AlpnNextOpts = [alpn_advertised_protocols,
+ alpn_preferred_protocols,
+ next_protocols_advertised,
+ next_protocol_selector,
+ client_preferred_next_protocols],
+ reject_alpn_next_prot_options(AlpnNextOpts, Opts).
+
+reject_alpn_next_prot_options([], _) ->
+ ok;
+reject_alpn_next_prot_options([Opt| AlpnNextOpts], Opts) ->
+ case lists:keyfind(Opt, 1, Opts) of
+ {Opt, Value} ->
+ throw({error, {options, {not_supported_in_sslv3, {Opt, Value}}}});
+ false ->
+ reject_alpn_next_prot_options(AlpnNextOpts, Opts)
+ end.
+
+add_filter(undefined, Filters) ->
+ Filters;
+add_filter(Filter, Filters) ->
+ [Filter | Filters].
diff --git a/lib/ssl/src/ssl_alert.erl b/lib/ssl/src/ssl_alert.erl
index 696a55e4b9..34e9797f1f 100644
--- a/lib/ssl/src/ssl_alert.erl
+++ b/lib/ssl/src/ssl_alert.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,7 @@
-include("ssl_record.hrl").
-include("ssl_internal.hrl").
--export([decode/1, alert_txt/1, reason_code/2]).
+-export([decode/1, own_alert_txt/1, alert_txt/1, reason_code/2]).
%%====================================================================
%% Internal application API
@@ -48,7 +48,9 @@ decode(Bin) ->
decode(Bin, [], 0).
%%--------------------------------------------------------------------
--spec reason_code(#alert{}, client | server) -> closed | {essl, string()}.
+-spec reason_code(#alert{}, client | server) ->
+ closed | {tls_alert, unicode:chardata()}.
+%-spec reason_code(#alert{}, client | server) -> closed | {essl, string()}.
%%
%% Description: Returns the error reason that will be returned to the
%% user.
@@ -57,16 +59,32 @@ decode(Bin) ->
reason_code(#alert{description = ?CLOSE_NOTIFY}, _) ->
closed;
reason_code(#alert{description = Description}, _) ->
- {tls_alert, description_txt(Description)}.
+ {tls_alert, string:casefold(description_txt(Description))}.
+
+%%--------------------------------------------------------------------
+-spec own_alert_txt(#alert{}) -> string().
+%%
+%% Description: Returns the error string for given alert generated
+%% by the erlang implementation.
+%%--------------------------------------------------------------------
+own_alert_txt(#alert{level = Level, description = Description, where = {Mod,Line}, reason = undefined, role = Role}) ->
+ "at " ++ Mod ++ ":" ++ integer_to_list(Line) ++ " generated " ++ string:uppercase(atom_to_list(Role)) ++ " ALERT: " ++
+ level_txt(Level) ++ description_txt(Description);
+own_alert_txt(#alert{reason = Reason} = Alert) ->
+ BaseTxt = own_alert_txt(Alert#alert{reason = undefined}),
+ FormatDepth = 9, % Some limit on printed representation of an error
+ ReasonTxt = lists:flatten(io_lib:format("~P", [Reason, FormatDepth])),
+ BaseTxt ++ " - " ++ ReasonTxt.
%%--------------------------------------------------------------------
-spec alert_txt(#alert{}) -> string().
%%
-%% Description: Returns the error string for given alert.
+%% Description: Returns the error string for given alert received from
+%% the peer.
%%--------------------------------------------------------------------
-alert_txt(#alert{level = Level, description = Description, where = {Mod,Line}, reason = undefined}) ->
- Mod ++ ":" ++ integer_to_list(Line) ++ ":" ++
- level_txt(Level) ++" "++ description_txt(Description);
+alert_txt(#alert{level = Level, description = Description, reason = undefined, role = Role}) ->
+ "received " ++ string:uppercase(atom_to_list(Role)) ++ " ALERT: " ++
+ level_txt(Level) ++ description_txt(Description);
alert_txt(#alert{reason = Reason} = Alert) ->
BaseTxt = alert_txt(Alert#alert{reason = undefined}),
FormatDepth = 9, % Some limit on printed representation of an error
@@ -93,73 +111,73 @@ decode(<<>>, Acc, _) ->
lists:reverse(Acc, []).
level_txt(?WARNING) ->
- "Warning:";
+ "Warning - ";
level_txt(?FATAL) ->
- "Fatal error:".
+ "Fatal - ".
description_txt(?CLOSE_NOTIFY) ->
- "close notify";
+ "Close Notify";
description_txt(?UNEXPECTED_MESSAGE) ->
- "unexpected message";
+ "Unexpected Message";
description_txt(?BAD_RECORD_MAC) ->
- "bad record mac";
-description_txt(?DECRYPTION_FAILED) ->
- "decryption failed";
+ "Bad Record MAC";
+description_txt(?DECRYPTION_FAILED_RESERVED) ->
+ "Decryption Failed Reserved";
description_txt(?RECORD_OVERFLOW) ->
- "record overflow";
+ "Record Overflow";
description_txt(?DECOMPRESSION_FAILURE) ->
- "decompression failure";
+ "Decompression Failure";
description_txt(?HANDSHAKE_FAILURE) ->
- "handshake failure";
+ "Handshake Failure";
description_txt(?NO_CERTIFICATE_RESERVED) ->
- "No certificate reserved";
+ "No Certificate Reserved";
description_txt(?BAD_CERTIFICATE) ->
- "bad certificate";
+ "Bad Certificate";
description_txt(?UNSUPPORTED_CERTIFICATE) ->
- "unsupported certificate";
+ "Unsupported Certificate";
description_txt(?CERTIFICATE_REVOKED) ->
- "certificate revoked";
+ "Certificate Revoked";
description_txt(?CERTIFICATE_EXPIRED) ->
- "certificate expired";
+ "Certificate Expired";
description_txt(?CERTIFICATE_UNKNOWN) ->
- "certificate unknown";
+ "Certificate Unknown";
description_txt(?ILLEGAL_PARAMETER) ->
- "illegal parameter";
+ "Illegal Parameter";
description_txt(?UNKNOWN_CA) ->
- "unknown ca";
+ "Unknown CA";
description_txt(?ACCESS_DENIED) ->
- "access denied";
+ "Access Denied";
description_txt(?DECODE_ERROR) ->
- "decode error";
+ "Decode Error";
description_txt(?DECRYPT_ERROR) ->
- "decrypt error";
+ "Decrypt Error";
description_txt(?EXPORT_RESTRICTION) ->
- "export restriction";
+ "Export Restriction";
description_txt(?PROTOCOL_VERSION) ->
- "protocol version";
+ "Protocol Version";
description_txt(?INSUFFICIENT_SECURITY) ->
- "insufficient security";
+ "Insufficient Security";
description_txt(?INTERNAL_ERROR) ->
- "internal error";
+ "Internal Error";
description_txt(?USER_CANCELED) ->
- "user canceled";
+ "User Canceled";
description_txt(?NO_RENEGOTIATION) ->
- "no renegotiation";
+ "No Renegotiation";
description_txt(?UNSUPPORTED_EXTENSION) ->
- "unsupported extension";
+ "Unsupported Extension";
description_txt(?CERTIFICATE_UNOBTAINABLE) ->
- "certificate unobtainable";
+ "Certificate Unobtainable";
description_txt(?UNRECOGNISED_NAME) ->
- "unrecognised name";
+ "Unrecognised Name";
description_txt(?BAD_CERTIFICATE_STATUS_RESPONSE) ->
- "bad certificate status response";
+ "Bad Certificate Status Response";
description_txt(?BAD_CERTIFICATE_HASH_VALUE) ->
- "bad certificate hash value";
+ "Bad Certificate Hash Value";
description_txt(?UNKNOWN_PSK_IDENTITY) ->
- "unknown psk identity";
+ "Unknown Psk Identity";
description_txt(?INAPPROPRIATE_FALLBACK) ->
- "inappropriate fallback";
+ "Inappropriate Fallback";
description_txt(?NO_APPLICATION_PROTOCOL) ->
- "no application protocol";
+ "No application protocol";
description_txt(Enum) ->
lists:flatten(io_lib:format("unsupported/unknown alert: ~p", [Enum])).
diff --git a/lib/ssl/src/ssl_alert.hrl b/lib/ssl/src/ssl_alert.hrl
index f3743ba0f0..b23123905e 100644
--- a/lib/ssl/src/ssl_alert.hrl
+++ b/lib/ssl/src/ssl_alert.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -40,7 +40,7 @@
%% close_notify(0),
%% unexpected_message(10),
%% bad_record_mac(20),
-%% decryption_failed(21),
+%% decryption_failed_reserved(21),
%% record_overflow(22),
%% decompression_failure(30),
%% handshake_failure(40),
@@ -78,7 +78,7 @@
-define(CLOSE_NOTIFY, 0).
-define(UNEXPECTED_MESSAGE, 10).
-define(BAD_RECORD_MAC, 20).
--define(DECRYPTION_FAILED, 21).
+-define(DECRYPTION_FAILED_RESERVED, 21).
-define(RECORD_OVERFLOW, 22).
-define(DECOMPRESSION_FAILURE, 30).
-define(HANDSHAKE_FAILURE, 40).
@@ -118,6 +118,7 @@
level,
description,
where = {?FILE, ?LINE},
+ role,
reason
}).
-endif. % -ifdef(ssl_alert).
diff --git a/lib/ssl/src/ssl_api.hrl b/lib/ssl/src/ssl_api.hrl
index 2bd51cf91e..7b7b1cbcd9 100644
--- a/lib/ssl/src/ssl_api.hrl
+++ b/lib/ssl/src/ssl_api.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,7 +42,8 @@
{verify, verify_type()} |
{verify_fun, {fun(), InitialUserState::term()}} |
{fail_if_no_peer_cert, boolean()} | {depth, integer()} |
- {cert, Der::binary()} | {certfile, path()} | {key, Der::binary()} |
+ {cert, Der::binary()} | {certfile, path()} |
+ {key, {private_key_type(), Der::binary()}} |
{keyfile, path()} | {password, string()} | {cacerts, [Der::binary()]} |
{cacertfile, path()} | {dh, Der::binary()} | {dhfile, path()} |
{user_lookup_fun, {fun(), InitialUserState::term()}} |
@@ -57,7 +58,7 @@
-type verify_type() :: verify_none | verify_peer.
-type path() :: string().
--type ciphers() :: [ssl_cipher:erl_cipher_suite()] |
+-type ciphers() :: [ssl_cipher_format:erl_cipher_suite()] |
string(). % (according to old API)
-type ssl_imp() :: new | old.
@@ -65,4 +66,11 @@
ClosedTag::atom(), ErrTag::atom()}}.
-type prf_random() :: client_random | server_random.
+-type private_key_type() :: rsa | %% Backwards compatibility
+ dsa | %% Backwards compatibility
+ 'RSAPrivateKey' |
+ 'DSAPrivateKey' |
+ 'ECPrivateKey' |
+ 'PrivateKeyInfo'.
+
-endif. % -ifdef(ssl_api).
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index 0dd5e5c5cf..549e557beb 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017 All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018 All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
-export([trusted_cert_and_path/4,
certificate_chain/3,
+ certificate_chain/4,
file_to_certificats/2,
file_to_crls/2,
validate/3,
@@ -40,7 +41,8 @@
is_valid_key_usage/2,
select_extension/2,
extensions_list/1,
- public_key_type/1
+ public_key_type/1,
+ foldl_db/3
]).
%%====================================================================
@@ -79,7 +81,8 @@ trusted_cert_and_path(CertChain, CertDbHandle, CertDbRef, PartialChainHandler) -
%% Trusted must be selfsigned or it is an incomplete chain
handle_path(Trusted, Path, PartialChainHandler);
_ ->
- %% Root CA could not be verified
+ %% Root CA could not be verified, but partial
+ %% chain handler may trusted a cert that we got
handle_incomplete_chain(Path, PartialChainHandler)
end
end.
@@ -94,10 +97,23 @@ certificate_chain(undefined, _, _) ->
{error, no_cert};
certificate_chain(OwnCert, CertDbHandle, CertsDbRef) when is_binary(OwnCert) ->
ErlCert = public_key:pkix_decode_cert(OwnCert, otp),
- certificate_chain(ErlCert, OwnCert, CertDbHandle, CertsDbRef, [OwnCert]);
+ certificate_chain(ErlCert, OwnCert, CertDbHandle, CertsDbRef, [OwnCert], []);
certificate_chain(OwnCert, CertDbHandle, CertsDbRef) ->
DerCert = public_key:pkix_encode('OTPCertificate', OwnCert, otp),
- certificate_chain(OwnCert, DerCert, CertDbHandle, CertsDbRef, [DerCert]).
+ certificate_chain(OwnCert, DerCert, CertDbHandle, CertsDbRef, [DerCert], []).
+
+%%--------------------------------------------------------------------
+-spec certificate_chain(undefined | binary() | #'OTPCertificate'{} , db_handle(), certdb_ref(), [der_cert()]) ->
+ {error, no_cert} | {ok, #'OTPCertificate'{} | undefined, [der_cert()]}.
+%%
+%% Description: Create certificate chain with certs from
+%%--------------------------------------------------------------------
+certificate_chain(Cert, CertDbHandle, CertsDbRef, Candidates) when is_binary(Cert) ->
+ ErlCert = public_key:pkix_decode_cert(Cert, otp),
+ certificate_chain(ErlCert, Cert, CertDbHandle, CertsDbRef, [Cert], Candidates);
+certificate_chain(Cert, CertDbHandle, CertsDbRef, Candidates) ->
+ DerCert = public_key:pkix_encode('OTPCertificate', Cert, otp),
+ certificate_chain(Cert, DerCert, CertDbHandle, CertsDbRef, [DerCert], Candidates).
%%--------------------------------------------------------------------
-spec file_to_certificats(binary(), term()) -> [der_cert()].
%%
@@ -138,13 +154,8 @@ validate(_, {bad_cert, _} = Reason, _) ->
{fail, Reason};
validate(_, valid, UserState) ->
{valid, UserState};
-validate(Cert, valid_peer, UserState = {client, _,_, Hostname, _, _}) when Hostname =/= undefined ->
- case public_key:pkix_verify_hostname(Cert, [{dns_id, Hostname}]) of
- true ->
- {valid, UserState};
- false ->
- {fail, {bad_cert, hostname_check_failed}}
- end;
+validate(Cert, valid_peer, UserState = {client, _,_, {Hostname, Customize}, _, _}) when Hostname =/= disable ->
+ verify_hostname(Hostname, Customize, Cert, UserState);
validate(_, valid_peer, UserState) ->
{valid, UserState}.
@@ -192,9 +203,20 @@ public_key_type(?'id-ecPublicKey') ->
ec.
%%--------------------------------------------------------------------
+-spec foldl_db(fun(), db_handle() | {extracted, list()}, list()) ->
+ {ok, term()} | issuer_not_found.
+%%
+%% Description:
+%%--------------------------------------------------------------------
+foldl_db(IsIssuerFun, CertDbHandle, []) ->
+ ssl_pkix_db:foldl(IsIssuerFun, issuer_not_found, CertDbHandle);
+foldl_db(IsIssuerFun, _, [_|_] = ListDb) ->
+ lists:foldl(IsIssuerFun, issuer_not_found, ListDb).
+
+%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-certificate_chain(OtpCert, BinCert, CertDbHandle, CertsDbRef, Chain) ->
+certificate_chain(OtpCert, BinCert, CertDbHandle, CertsDbRef, Chain, ListDb) ->
IssuerAndSelfSigned =
case public_key:pkix_is_self_signed(OtpCert) of
true ->
@@ -205,12 +227,12 @@ certificate_chain(OtpCert, BinCert, CertDbHandle, CertsDbRef, Chain) ->
case IssuerAndSelfSigned of
{_, true = SelfSigned} ->
- certificate_chain(CertDbHandle, CertsDbRef, Chain, ignore, ignore, SelfSigned);
+ do_certificate_chain(CertDbHandle, CertsDbRef, Chain, ignore, ignore, SelfSigned, ListDb);
{{error, issuer_not_found}, SelfSigned} ->
- case find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef) of
+ case find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef, ListDb) of
{ok, {SerialNr, Issuer}} ->
- certificate_chain(CertDbHandle, CertsDbRef, Chain,
- SerialNr, Issuer, SelfSigned);
+ do_certificate_chain(CertDbHandle, CertsDbRef, Chain,
+ SerialNr, Issuer, SelfSigned, ListDb);
_ ->
%% Guess the the issuer must be the root
%% certificate. The verification of the
@@ -219,19 +241,19 @@ certificate_chain(OtpCert, BinCert, CertDbHandle, CertsDbRef, Chain) ->
{ok, undefined, lists:reverse(Chain)}
end;
{{ok, {SerialNr, Issuer}}, SelfSigned} ->
- certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, SelfSigned)
+ do_certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, SelfSigned, ListDb)
end.
-certificate_chain(_, _, [RootCert | _] = Chain, _, _, true) ->
+do_certificate_chain(_, _, [RootCert | _] = Chain, _, _, true, _) ->
{ok, RootCert, lists:reverse(Chain)};
-certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned) ->
+do_certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, _, ListDb) ->
case ssl_manager:lookup_trusted_cert(CertDbHandle, CertsDbRef,
SerialNr, Issuer) of
{ok, {IssuerCert, ErlCert}} ->
ErlCert = public_key:pkix_decode_cert(IssuerCert, otp),
certificate_chain(ErlCert, IssuerCert,
- CertDbHandle, CertsDbRef, [IssuerCert | Chain]);
+ CertDbHandle, CertsDbRef, [IssuerCert | Chain], ListDb);
_ ->
%% The trusted cert may be obmitted from the chain as the
%% counter part needs to have it anyway to be able to
@@ -239,7 +261,8 @@ certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned
{ok, undefined, lists:reverse(Chain)}
end.
-find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef) ->
+
+find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef, ListDb) ->
IsIssuerFun =
fun({_Key, {_Der, #'OTPCertificate'{} = ErlCertCandidate}}, Acc) ->
case public_key:pkix_is_issuer(OtpCert, ErlCertCandidate) of
@@ -257,26 +280,29 @@ find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef) ->
Acc
end,
- if is_reference(CertsDbRef) -> % actual DB exists
- try ssl_pkix_db:foldl(IsIssuerFun, issuer_not_found, CertDbHandle) of
- issuer_not_found ->
- {error, issuer_not_found}
- catch
- {ok, _IssuerId} = Return ->
- Return
- end;
- is_tuple(CertsDbRef), element(1,CertsDbRef) =:= extracted -> % cache bypass byproduct
- {extracted, CertsData} = CertsDbRef,
- DB = [Entry || {decoded, Entry} <- CertsData],
- try lists:foldl(IsIssuerFun, issuer_not_found, DB) of
- issuer_not_found ->
- {error, issuer_not_found}
- catch
- {ok, _IssuerId} = Return ->
- Return
- end
+ Result = case is_reference(CertsDbRef) of
+ true ->
+ do_find_issuer(IsIssuerFun, CertDbHandle, ListDb);
+ false ->
+ {extracted, CertsData} = CertsDbRef,
+ DB = [Entry || {decoded, Entry} <- CertsData],
+ do_find_issuer(IsIssuerFun, CertDbHandle, DB)
+ end,
+ case Result of
+ issuer_not_found ->
+ {error, issuer_not_found};
+ Result ->
+ Result
end.
+do_find_issuer(IssuerFun, CertDbHandle, CertDb) ->
+ try
+ foldl_db(IssuerFun, CertDbHandle, CertDb)
+ catch
+ throw:{ok, _} = Return ->
+ Return
+ end.
+
is_valid_extkey_usage(KeyUse, client) ->
%% Client wants to verify server
is_valid_key_usage(KeyUse,?'id-kp-serverAuth');
@@ -305,7 +331,7 @@ other_issuer(OtpCert, BinCert, CertDbHandle, CertDbRef) ->
{ok, IssuerId} ->
{other, IssuerId};
{error, issuer_not_found} ->
- case find_issuer(OtpCert, BinCert, CertDbHandle, CertDbRef) of
+ case find_issuer(OtpCert, BinCert, CertDbHandle, CertDbRef, []) of
{ok, IssuerId} ->
{other, IssuerId};
Other ->
@@ -337,3 +363,32 @@ new_trusteded_chain(DerCert, [_ | Rest]) ->
new_trusteded_chain(DerCert, Rest);
new_trusteded_chain(_, []) ->
unknown_ca.
+
+verify_hostname({fallback, Hostname}, Customize, Cert, UserState) when is_list(Hostname) ->
+ case public_key:pkix_verify_hostname(Cert, [{dns_id, Hostname}], Customize) of
+ true ->
+ {valid, UserState};
+ false ->
+ case public_key:pkix_verify_hostname(Cert, [{ip, Hostname}], Customize) of
+ true ->
+ {valid, UserState};
+ false ->
+ {fail, {bad_cert, hostname_check_failed}}
+ end
+ end;
+
+verify_hostname({fallback, Hostname}, Customize, Cert, UserState) ->
+ case public_key:pkix_verify_hostname(Cert, [{ip, Hostname}], Customize) of
+ true ->
+ {valid, UserState};
+ false ->
+ {fail, {bad_cert, hostname_check_failed}}
+ end;
+
+verify_hostname(Hostname, Customize, Cert, UserState) ->
+ case public_key:pkix_verify_hostname(Cert, [{dns_id, Hostname}], Customize) of
+ true ->
+ {valid, UserState};
+ false ->
+ {fail, {bad_cert, hostname_check_failed}}
+ end.
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index bd60197c88..b23129dcdd 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -1,7 +1,7 @@
%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,40 +33,23 @@
-include("ssl_alert.hrl").
-include_lib("public_key/include/public_key.hrl").
--export([security_parameters/2, security_parameters/3, suite_definition/1,
- erl_suite_definition/1,
+-export([security_parameters/2, security_parameters/3,
cipher_init/3, decipher/6, cipher/5, decipher_aead/6, cipher_aead/6,
- suite/1, suites/1, all_suites/1,
- ec_keyed_suites/0, anonymous_suites/1, psk_suites/1, srp_suites/0,
- rc4_suites/1, des_suites/1, openssl_suite/1, openssl_suite_name/1, filter/2, filter_suites/1,
+ suites/1, all_suites/1, crypto_support_filters/0,
+ chacha_suites/1, anonymous_suites/1, psk_suites/1, psk_suites_anon/1,
+ srp_suites/0, srp_suites_anon/0,
+ rc4_suites/1, des_suites/1, rsa_suites/1,
+ filter/3, filter_suites/1, filter_suites/2,
hash_algorithm/1, sign_algorithm/1, is_acceptable_hash/2, is_fallback/1,
random_bytes/1, calc_mac_hash/4,
is_stream_ciphersuite/1]).
--export_type([cipher_suite/0,
- erl_cipher_suite/0, openssl_cipher_suite/0,
- hash/0, key_algo/0, sign_algo/0]).
-
--type cipher() :: null |rc4_128 | des_cbc | '3des_ede_cbc'
- | aes_128_cbc | aes_256_cbc | aes_128_gcm | aes_256_gcm | chacha20_poly1305.
--type hash() :: null | md5 | sha | sha224 | sha256 | sha384 | sha512.
--type sign_algo() :: rsa | dsa | ecdsa.
--type key_algo() :: null | rsa | dhe_rsa | dhe_dss | ecdhe_ecdsa| ecdh_ecdsa | ecdh_rsa| srp_rsa| srp_dss |
- psk | dhe_psk | rsa_psk | dh_anon | ecdh_anon | srp_anon.
--type erl_cipher_suite() :: {key_algo(), cipher(), hash()} % Pre TLS 1.2
- %% TLS 1.2, internally PRE TLS 1.2 will use default_prf
- | {key_algo(), cipher(), hash(), hash() | default_prf}.
-
-
--type cipher_suite() :: binary().
--type cipher_enum() :: integer().
--type openssl_cipher_suite() :: string().
-
-
-compile(inline).
+-type cipher_enum() :: integer().
+
%%--------------------------------------------------------------------
--spec security_parameters(cipher_suite(), #security_parameters{}) ->
+-spec security_parameters(ssl_cipher_format:cipher_suite(), #security_parameters{}) ->
#security_parameters{}.
%% Only security_parameters/2 should call security_parameters/3 with undefined as
%% first argument.
@@ -76,14 +59,16 @@ security_parameters(?TLS_NULL_WITH_NULL_NULL = CipherSuite, SecParams) ->
security_parameters(undefined, CipherSuite, SecParams).
%%--------------------------------------------------------------------
--spec security_parameters(ssl_record:ssl_version() | undefined, cipher_suite(), #security_parameters{}) ->
+-spec security_parameters(ssl_record:ssl_version() | undefined,
+ ssl_cipher_format:cipher_suite(), #security_parameters{}) ->
#security_parameters{}.
%%
%% Description: Returns a security parameters record where the
%% cipher values has been updated according to <CipherSuite>
%%-------------------------------------------------------------------
security_parameters(Version, CipherSuite, SecParams) ->
- { _, Cipher, Hash, PrfHashAlg} = suite_definition(CipherSuite),
+ #{cipher := Cipher, mac := Hash,
+ prf := PrfHashAlg} = ssl_cipher_format:suite_definition(CipherSuite),
SecParams#security_parameters{
cipher_suite = CipherSuite,
bulk_cipher_algorithm = bulk_cipher_algorithm(Cipher),
@@ -92,7 +77,7 @@ security_parameters(Version, CipherSuite, SecParams) ->
expanded_key_material_length = expanded_key_material(Cipher),
key_material_length = key_material(Cipher),
iv_size = iv_size(Cipher),
- mac_algorithm = hash_algorithm(Hash),
+ mac_algorithm = mac_algorithm(Hash),
prf_algorithm = prf_algorithm(PrfHashAlg, Version),
hash_size = hash_size(Hash)}.
@@ -235,7 +220,7 @@ decipher(?AES_CBC, HashSz, CipherState, Fragment, Version, PaddingCheck) ->
%%--------------------------------------------------------------------
-spec decipher_aead(cipher_enum(), #cipher_state{}, integer(), binary(), binary(), ssl_record:ssl_version()) ->
- {binary(), binary(), #cipher_state{}} | #alert{}.
+ {binary(), #cipher_state{}} | #alert{}.
%%
%% Description: Decrypts the data and checks the associated data (AAD) MAC using
%% cipher described by cipher_enum() and updating the cipher state.
@@ -305,7 +290,7 @@ aead_decipher(Type, #cipher_state{key = Key, iv = IV} = CipherState,
end.
%%--------------------------------------------------------------------
--spec suites(ssl_record:ssl_version()) -> [cipher_suite()].
+-spec suites(ssl_record:ssl_version()) -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of supported cipher suites.
%%--------------------------------------------------------------------
@@ -318,26 +303,44 @@ suites({_, Minor}) ->
all_suites({3, _} = Version) ->
suites(Version)
- ++ anonymous_suites(Version)
+ ++ chacha_suites(Version)
++ psk_suites(Version)
++ srp_suites()
++ rc4_suites(Version)
- ++ des_suites(Version);
+ ++ des_suites(Version)
+ ++ rsa_suites(Version);
+
all_suites(Version) ->
dtls_v1:all_suites(Version).
+%%--------------------------------------------------------------------
+-spec chacha_suites(ssl_record:ssl_version() | integer()) ->
+ [ssl_cipher_format:cipher_suite()].
+%%
+%% Description: Returns list of the chacha cipher suites, only supported
+%% if explicitly set by user for now due to interop problems, proably need
+%% to be fixed in crypto.
+%%--------------------------------------------------------------------
+chacha_suites({3, _}) ->
+ [?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+ ?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ ?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256];
+chacha_suites(_) ->
+ [].
%%--------------------------------------------------------------------
--spec anonymous_suites(ssl_record:ssl_version() | integer()) -> [cipher_suite()].
+-spec anonymous_suites(ssl_record:ssl_version() | integer()) ->
+ [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the anonymous cipher suites, only supported
%% if explicitly set by user. Intended only for testing.
%%--------------------------------------------------------------------
-
anonymous_suites({3, N}) ->
- anonymous_suites(N);
-
+ srp_suites_anon() ++ anonymous_suites(N);
+anonymous_suites({254, _} = Version) ->
+ dtls_v1:anonymous_suites(Version);
anonymous_suites(N)
when N >= 3 ->
+ psk_suites_anon(N) ++
[?TLS_DH_anon_WITH_AES_128_GCM_SHA256,
?TLS_DH_anon_WITH_AES_256_GCM_SHA384,
?TLS_DH_anon_WITH_AES_128_CBC_SHA256,
@@ -346,79 +349,106 @@ anonymous_suites(N)
?TLS_ECDH_anon_WITH_AES_256_CBC_SHA,
?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,
?TLS_DH_anon_WITH_RC4_128_MD5];
-
-anonymous_suites(2) ->
+anonymous_suites(2 = N) ->
+ psk_suites_anon(N) ++
[?TLS_ECDH_anon_WITH_AES_128_CBC_SHA,
?TLS_ECDH_anon_WITH_AES_256_CBC_SHA,
?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,
?TLS_DH_anon_WITH_DES_CBC_SHA,
?TLS_DH_anon_WITH_RC4_128_MD5];
-
anonymous_suites(N) when N == 0;
N == 1 ->
- [?TLS_DH_anon_WITH_RC4_128_MD5,
- ?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
- ?TLS_DH_anon_WITH_DES_CBC_SHA
- ].
+ psk_suites_anon(N) ++
+ [?TLS_DH_anon_WITH_RC4_128_MD5,
+ ?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_DH_anon_WITH_DES_CBC_SHA
+ ].
%%--------------------------------------------------------------------
--spec psk_suites(ssl_record:ssl_version() | integer()) -> [cipher_suite()].
+-spec psk_suites(ssl_record:ssl_version() | integer()) -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the PSK cipher suites, only supported
%% if explicitly set by user.
%%--------------------------------------------------------------------
psk_suites({3, N}) ->
psk_suites(N);
-
psk_suites(N)
when N >= 3 ->
[
- ?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
+ ?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
+ ?TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
+ ?TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
+ ] ++ psk_suites(0);
+psk_suites(_) ->
+ [?TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
+ ?TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
+ ?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_RSA_PSK_WITH_RC4_128_SHA].
+
+%%--------------------------------------------------------------------
+-spec psk_suites_anon(ssl_record:ssl_version() | integer()) -> [ssl_cipher_format:cipher_suite()].
+%%
+%% Description: Returns a list of the anonymous PSK cipher suites, only supported
+%% if explicitly set by user.
+%%--------------------------------------------------------------------
+psk_suites_anon({3, N}) ->
+ psk_suites_anon(N);
+psk_suites_anon(N)
+ when N >= 3 ->
+ [
+ ?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
?TLS_PSK_WITH_AES_256_GCM_SHA384,
+ ?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
?TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
- ?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
?TLS_PSK_WITH_AES_256_CBC_SHA384,
+ ?TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256,
?TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
- ?TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
?TLS_PSK_WITH_AES_128_GCM_SHA256,
+ ?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
?TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
- ?TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
?TLS_PSK_WITH_AES_128_CBC_SHA256
- ] ++ psk_suites(0);
-
-psk_suites(_) ->
+ ] ++ psk_suites_anon(0);
+psk_suites_anon(_) ->
[?TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
- ?TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
?TLS_PSK_WITH_AES_256_CBC_SHA,
+ ?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
?TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
- ?TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
?TLS_PSK_WITH_AES_128_CBC_SHA,
+ ?TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
?TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
- ?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
?TLS_PSK_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_ECDHE_PSK_WITH_RC4_128_SHA,
?TLS_DHE_PSK_WITH_RC4_128_SHA,
- ?TLS_RSA_PSK_WITH_RC4_128_SHA,
?TLS_PSK_WITH_RC4_128_SHA].
-
%%--------------------------------------------------------------------
--spec srp_suites() -> [cipher_suite()].
+-spec srp_suites() -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the SRP cipher suites, only supported
%% if explicitly set by user.
%%--------------------------------------------------------------------
srp_suites() ->
- [?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
- ?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
+ [?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
- ?TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
- ?TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA].
+
%%--------------------------------------------------------------------
--spec rc4_suites(Version::ssl_record:ssl_version()) -> [cipher_suite()].
+-spec srp_suites_anon() -> [ssl_cipher_format:cipher_suite()].
+%%
+%% Description: Returns a list of the SRP anonymous cipher suites, only supported
+%% if explicitly set by user.
+%%--------------------------------------------------------------------
+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].
+
+%%--------------------------------------------------------------------
+-spec rc4_suites(Version::ssl_record:ssl_version() | integer()) ->
+ [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the RSA|(ECDH/RSA)| (ECDH/ECDSA)
%% with RC4 cipher suites, only supported if explicitly set by user.
@@ -426,17 +456,19 @@ srp_suites() ->
%% belonged to the user configured only category.
%%--------------------------------------------------------------------
rc4_suites({3, 0}) ->
+ rc4_suites(0);
+rc4_suites({3, Minor}) ->
+ rc4_suites(Minor) ++ rc4_suites(0);
+rc4_suites(0) ->
[?TLS_RSA_WITH_RC4_128_SHA,
?TLS_RSA_WITH_RC4_128_MD5];
-rc4_suites({3, N}) when N =< 3 ->
+rc4_suites(N) when N =< 3 ->
[?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
?TLS_ECDHE_RSA_WITH_RC4_128_SHA,
- ?TLS_RSA_WITH_RC4_128_SHA,
- ?TLS_RSA_WITH_RC4_128_MD5,
?TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
?TLS_ECDH_RSA_WITH_RC4_128_SHA].
%%--------------------------------------------------------------------
--spec des_suites(Version::ssl_record:ssl_version()) -> [cipher_suite()].
+-spec des_suites(Version::ssl_record:ssl_version()) -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the cipher suites
%% with DES cipher, only supported if explicitly set by user.
@@ -444,1014 +476,128 @@ rc4_suites({3, N}) when N =< 3 ->
%%--------------------------------------------------------------------
des_suites(_)->
[?TLS_DHE_RSA_WITH_DES_CBC_SHA,
- ?TLS_RSA_WITH_DES_CBC_SHA].
-
-%%--------------------------------------------------------------------
--spec suite_definition(cipher_suite()) -> erl_cipher_suite().
-%%
-%% Description: Return erlang cipher suite definition.
-%% Note: Currently not supported suites are commented away.
-%% They should be supported or removed in the future.
-%%-------------------------------------------------------------------
-%% TLS v1.1 suites
-suite_definition(?TLS_NULL_WITH_NULL_NULL) ->
- {null, null, null, null};
-%% RFC 5746 - Not a real cipher suite used to signal empty "renegotiation_info" extension
-%% to avoid handshake failure from old servers that do not ignore
-%% hello extension data as they should.
-suite_definition(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV) ->
- {null, null, null, null};
-%% suite_definition(?TLS_RSA_WITH_NULL_MD5) ->
-%% {rsa, null, md5, default_prf};
-%% suite_definition(?TLS_RSA_WITH_NULL_SHA) ->
-%% {rsa, null, sha, default_prf};
-suite_definition(?TLS_RSA_WITH_RC4_128_MD5) ->
- {rsa, rc4_128, md5, default_prf};
-suite_definition(?TLS_RSA_WITH_RC4_128_SHA) ->
- {rsa, rc4_128, sha, default_prf};
-suite_definition(?TLS_RSA_WITH_DES_CBC_SHA) ->
- {rsa, des_cbc, sha, default_prf};
-suite_definition(?TLS_RSA_WITH_3DES_EDE_CBC_SHA) ->
- {rsa, '3des_ede_cbc', sha, default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_DES_CBC_SHA) ->
- {dhe_dss, des_cbc, sha, default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) ->
- {dhe_dss, '3des_ede_cbc', sha, default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_DES_CBC_SHA) ->
- {dhe_rsa, des_cbc, sha, default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
- {dhe_rsa, '3des_ede_cbc', sha, default_prf};
-
-%%% TSL V1.1 AES suites
-suite_definition(?TLS_RSA_WITH_AES_128_CBC_SHA) ->
- {rsa, aes_128_cbc, sha, default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA) ->
- {dhe_dss, aes_128_cbc, sha, default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA) ->
- {dhe_rsa, aes_128_cbc, sha, default_prf};
-suite_definition(?TLS_RSA_WITH_AES_256_CBC_SHA) ->
- {rsa, aes_256_cbc, sha, default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA) ->
- {dhe_dss, aes_256_cbc, sha, default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA) ->
- {dhe_rsa, aes_256_cbc, sha, default_prf};
-
-%% TLS v1.2 suites
-
-%% suite_definition(?TLS_RSA_WITH_NULL_SHA) ->
-%% {rsa, null, sha, default_prf};
-suite_definition(?TLS_RSA_WITH_AES_128_CBC_SHA256) ->
- {rsa, aes_128_cbc, sha256, default_prf};
-suite_definition(?TLS_RSA_WITH_AES_256_CBC_SHA256) ->
- {rsa, aes_256_cbc, sha256, default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) ->
- {dhe_dss, aes_128_cbc, sha256, default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) ->
- {dhe_rsa, aes_128_cbc, sha256, default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) ->
- {dhe_dss, aes_256_cbc, sha256, default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) ->
- {dhe_rsa, aes_256_cbc, sha256, default_prf};
-
-%% not defined YET:
-%% TLS_DH_DSS_WITH_AES_128_CBC_SHA256 DH_DSS AES_128_CBC SHA256
-%% TLS_DH_RSA_WITH_AES_128_CBC_SHA256 DH_RSA AES_128_CBC SHA256
-%% TLS_DH_DSS_WITH_AES_256_CBC_SHA256 DH_DSS AES_256_CBC SHA256
-%% TLS_DH_RSA_WITH_AES_256_CBC_SHA256 DH_RSA AES_256_CBC SHA256
-
-%%% DH-ANON deprecated by TLS spec and not available
-%%% by default, but good for testing purposes.
-suite_definition(?TLS_DH_anon_WITH_RC4_128_MD5) ->
- {dh_anon, rc4_128, md5, default_prf};
-suite_definition(?TLS_DH_anon_WITH_DES_CBC_SHA) ->
- {dh_anon, des_cbc, sha, default_prf};
-suite_definition(?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA) ->
- {dh_anon, '3des_ede_cbc', sha, default_prf};
-suite_definition(?TLS_DH_anon_WITH_AES_128_CBC_SHA) ->
- {dh_anon, aes_128_cbc, sha, default_prf};
-suite_definition(?TLS_DH_anon_WITH_AES_256_CBC_SHA) ->
- {dh_anon, aes_256_cbc, sha, default_prf};
-suite_definition(?TLS_DH_anon_WITH_AES_128_CBC_SHA256) ->
- {dh_anon, aes_128_cbc, sha256, default_prf};
-suite_definition(?TLS_DH_anon_WITH_AES_256_CBC_SHA256) ->
- {dh_anon, aes_256_cbc, sha256, default_prf};
-
-%%% PSK Cipher Suites RFC 4279
-
-suite_definition(?TLS_PSK_WITH_RC4_128_SHA) ->
- {psk, rc4_128, sha, default_prf};
-suite_definition(?TLS_PSK_WITH_3DES_EDE_CBC_SHA) ->
- {psk, '3des_ede_cbc', sha, default_prf};
-suite_definition(?TLS_PSK_WITH_AES_128_CBC_SHA) ->
- {psk, aes_128_cbc, sha, default_prf};
-suite_definition(?TLS_PSK_WITH_AES_256_CBC_SHA) ->
- {psk, aes_256_cbc, sha, default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_RC4_128_SHA) ->
- {dhe_psk, rc4_128, sha, default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA) ->
- {dhe_psk, '3des_ede_cbc', sha, default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_AES_128_CBC_SHA) ->
- {dhe_psk, aes_128_cbc, sha, default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_AES_256_CBC_SHA) ->
- {dhe_psk, aes_256_cbc, sha, default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_RC4_128_SHA) ->
- {rsa_psk, rc4_128, sha, default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA) ->
- {rsa_psk, '3des_ede_cbc', sha, default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_AES_128_CBC_SHA) ->
- {rsa_psk, aes_128_cbc, sha, default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_AES_256_CBC_SHA) ->
- {rsa_psk, aes_256_cbc, sha, default_prf};
-
-%%% TLS 1.2 PSK Cipher Suites RFC 5487
-
-suite_definition(?TLS_PSK_WITH_AES_128_GCM_SHA256) ->
- {psk, aes_128_gcm, null, sha256};
-suite_definition(?TLS_PSK_WITH_AES_256_GCM_SHA384) ->
- {psk, aes_256_gcm, null, sha384};
-suite_definition(?TLS_DHE_PSK_WITH_AES_128_GCM_SHA256) ->
- {dhe_psk, aes_128_gcm, null, sha256};
-suite_definition(?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384) ->
- {dhe_psk, aes_256_gcm, null, sha384};
-suite_definition(?TLS_RSA_PSK_WITH_AES_128_GCM_SHA256) ->
- {rsa_psk, aes_128_gcm, null, sha256};
-suite_definition(?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384) ->
- {rsa_psk, aes_256_gcm, null, sha384};
-
-suite_definition(?TLS_PSK_WITH_AES_128_CBC_SHA256) ->
- {psk, aes_128_cbc, sha256, default_prf};
-suite_definition(?TLS_PSK_WITH_AES_256_CBC_SHA384) ->
- {psk, aes_256_cbc, sha384, default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_AES_128_CBC_SHA256) ->
- {dhe_psk, aes_128_cbc, sha256, default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_AES_256_CBC_SHA384) ->
- {dhe_psk, aes_256_cbc, sha384, default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_AES_128_CBC_SHA256) ->
- {rsa_psk, aes_128_cbc, sha256, default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384) ->
- {rsa_psk, aes_256_cbc, sha384, default_prf};
-
-suite_definition(?TLS_PSK_WITH_NULL_SHA256) ->
- {psk, null, sha256, default_prf};
-suite_definition(?TLS_PSK_WITH_NULL_SHA384) ->
- {psk, null, sha384, default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA256) ->
- {dhe_psk, null, sha256, default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA384) ->
- {dhe_psk, null, sha384, default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA256) ->
- {rsa_psk, null, sha256, default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA384) ->
- {rsa_psk, null, sha384, default_prf};
-
-%%% SRP Cipher Suites RFC 5054
-
-suite_definition(?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA) ->
- {srp_anon, '3des_ede_cbc', sha, default_prf};
-suite_definition(?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) ->
- {srp_rsa, '3des_ede_cbc', sha, default_prf};
-suite_definition(?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) ->
- {srp_dss, '3des_ede_cbc', sha, default_prf};
-suite_definition(?TLS_SRP_SHA_WITH_AES_128_CBC_SHA) ->
- {srp_anon, aes_128_cbc, sha, default_prf};
-suite_definition(?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) ->
- {srp_rsa, aes_128_cbc, sha, default_prf};
-suite_definition(?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA) ->
- {srp_dss, aes_128_cbc, sha, default_prf};
-suite_definition(?TLS_SRP_SHA_WITH_AES_256_CBC_SHA) ->
- {srp_anon, aes_256_cbc, sha, default_prf};
-suite_definition(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) ->
- {srp_rsa, aes_256_cbc, sha, default_prf};
-suite_definition(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) ->
- {srp_dss, aes_256_cbc, sha, default_prf};
-
-%% RFC 4492 EC TLS suites
-suite_definition(?TLS_ECDH_ECDSA_WITH_NULL_SHA) ->
- {ecdh_ecdsa, null, sha, default_prf};
-suite_definition(?TLS_ECDH_ECDSA_WITH_RC4_128_SHA) ->
- {ecdh_ecdsa, rc4_128, sha, default_prf};
-suite_definition(?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
- {ecdh_ecdsa, '3des_ede_cbc', sha, default_prf};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) ->
- {ecdh_ecdsa, aes_128_cbc, sha, default_prf};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) ->
- {ecdh_ecdsa, aes_256_cbc, sha, default_prf};
-
-suite_definition(?TLS_ECDHE_ECDSA_WITH_NULL_SHA) ->
- {ecdhe_ecdsa, null, sha, default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) ->
- {ecdhe_ecdsa, rc4_128, sha, default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
- {ecdhe_ecdsa, '3des_ede_cbc', sha, default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) ->
- {ecdhe_ecdsa, aes_128_cbc, sha, default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) ->
- {ecdhe_ecdsa, aes_256_cbc, sha, default_prf};
-
-suite_definition(?TLS_ECDH_RSA_WITH_NULL_SHA) ->
- {ecdh_rsa, null, sha, default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_RC4_128_SHA) ->
- {ecdh_rsa, rc4_128, sha, default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) ->
- {ecdh_rsa, '3des_ede_cbc', sha, default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) ->
- {ecdh_rsa, aes_128_cbc, sha, default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) ->
- {ecdh_rsa, aes_256_cbc, sha, default_prf};
-
-suite_definition(?TLS_ECDHE_RSA_WITH_NULL_SHA) ->
- {ecdhe_rsa, null, sha, default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_RC4_128_SHA) ->
- {ecdhe_rsa, rc4_128, sha, default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
- {ecdhe_rsa, '3des_ede_cbc', sha, default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) ->
- {ecdhe_rsa, aes_128_cbc, sha, default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) ->
- {ecdhe_rsa, aes_256_cbc, sha, default_prf};
-
-suite_definition(?TLS_ECDH_anon_WITH_NULL_SHA) ->
- {ecdh_anon, null, sha, default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_RC4_128_SHA) ->
- {ecdh_anon, rc4_128, sha, default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA) ->
- {ecdh_anon, '3des_ede_cbc', sha, default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_AES_128_CBC_SHA) ->
- {ecdh_anon, aes_128_cbc, sha, default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_AES_256_CBC_SHA) ->
- {ecdh_anon, aes_256_cbc, sha, default_prf};
-
-%% RFC 5289 EC TLS suites
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) ->
- {ecdhe_ecdsa, aes_128_cbc, sha256, sha256};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) ->
- {ecdhe_ecdsa, aes_256_cbc, sha384, sha384};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) ->
- {ecdh_ecdsa, aes_128_cbc, sha256, sha256};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) ->
- {ecdh_ecdsa, aes_256_cbc, sha384, sha384};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) ->
- {ecdhe_rsa, aes_128_cbc, sha256, sha256};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) ->
- {ecdhe_rsa, aes_256_cbc, sha384, sha384};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) ->
- {ecdh_rsa, aes_128_cbc, sha256, sha256};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) ->
- {ecdh_rsa, aes_256_cbc, sha384, sha384};
-
-%% RFC 5288 AES-GCM Cipher Suites
-suite_definition(?TLS_RSA_WITH_AES_128_GCM_SHA256) ->
- {rsa, aes_128_gcm, null, sha256};
-suite_definition(?TLS_RSA_WITH_AES_256_GCM_SHA384) ->
- {rsa, aes_256_gcm, null, sha384};
-suite_definition(?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) ->
- {dhe_rsa, aes_128_gcm, null, sha256};
-suite_definition(?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) ->
- {dhe_rsa, aes_256_gcm, null, sha384};
-suite_definition(?TLS_DH_RSA_WITH_AES_128_GCM_SHA256) ->
- {dh_rsa, aes_128_gcm, null, sha256};
-suite_definition(?TLS_DH_RSA_WITH_AES_256_GCM_SHA384) ->
- {dh_rsa, aes_256_gcm, null, sha384};
-suite_definition(?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256) ->
- {dhe_dss, aes_128_gcm, null, sha256};
-suite_definition(?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384) ->
- {dhe_dss, aes_256_gcm, null, sha384};
-suite_definition(?TLS_DH_DSS_WITH_AES_128_GCM_SHA256) ->
- {dh_dss, aes_128_gcm, null, sha256};
-suite_definition(?TLS_DH_DSS_WITH_AES_256_GCM_SHA384) ->
- {dh_dss, aes_256_gcm, null, sha384};
-suite_definition(?TLS_DH_anon_WITH_AES_128_GCM_SHA256) ->
- {dh_anon, aes_128_gcm, null, sha256};
-suite_definition(?TLS_DH_anon_WITH_AES_256_GCM_SHA384) ->
- {dh_anon, aes_256_gcm, null, sha384};
-
-%% RFC 5289 ECC AES-GCM Cipher Suites
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) ->
- {ecdhe_ecdsa, aes_128_gcm, null, sha256};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) ->
- {ecdhe_ecdsa, aes_256_gcm, null, sha384};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256) ->
- {ecdh_ecdsa, aes_128_gcm, null, sha256};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384) ->
- {ecdh_ecdsa, aes_256_gcm, null, sha384};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) ->
- {ecdhe_rsa, aes_128_gcm, null, sha256};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) ->
- {ecdhe_rsa, aes_256_gcm, null, sha384};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) ->
- {ecdh_rsa, aes_128_gcm, null, sha256};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) ->
- {ecdh_rsa, aes_256_gcm, null, sha384};
-
-%% draft-agl-tls-chacha20poly1305-04 Chacha20/Poly1305 Suites
-suite_definition(?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) ->
- {ecdhe_rsa, chacha20_poly1305, null, sha256};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) ->
- {ecdhe_ecdsa, chacha20_poly1305, null, sha256};
-suite_definition(?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256) ->
- {dhe_rsa, chacha20_poly1305, null, sha256}.
-
-%%--------------------------------------------------------------------
--spec erl_suite_definition(cipher_suite()) -> erl_cipher_suite().
-%%
-%% Description: Return erlang cipher suite definition. Filters last value
-%% for now (compatibility reasons).
-%%--------------------------------------------------------------------
-erl_suite_definition(S) ->
- case suite_definition(S) of
- {KeyExchange, Cipher, Hash, default_prf} ->
- {KeyExchange, Cipher, Hash};
- Suite ->
- Suite
- end.
-
-%%--------------------------------------------------------------------
--spec suite(erl_cipher_suite()) -> cipher_suite().
-%%
-%% Description: Return TLS cipher suite definition.
-%%--------------------------------------------------------------------
-
-%% TLS v1.1 suites
-%%suite({rsa, null, md5}) ->
-%% ?TLS_RSA_WITH_NULL_MD5;
-%%suite({rsa, null, sha}) ->
-%% ?TLS_RSA_WITH_NULL_SHA;
-suite({rsa, rc4_128, md5}) ->
- ?TLS_RSA_WITH_RC4_128_MD5;
-suite({rsa, rc4_128, sha}) ->
- ?TLS_RSA_WITH_RC4_128_SHA;
-suite({rsa, des_cbc, sha}) ->
- ?TLS_RSA_WITH_DES_CBC_SHA;
-suite({rsa, '3des_ede_cbc', sha}) ->
- ?TLS_RSA_WITH_3DES_EDE_CBC_SHA;
-suite({dhe_dss, des_cbc, sha}) ->
- ?TLS_DHE_DSS_WITH_DES_CBC_SHA;
-suite({dhe_dss, '3des_ede_cbc', sha}) ->
- ?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
-suite({dhe_rsa, des_cbc, sha}) ->
- ?TLS_DHE_RSA_WITH_DES_CBC_SHA;
-suite({dhe_rsa, '3des_ede_cbc', sha}) ->
- ?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
-suite({dh_anon, rc4_128, md5}) ->
- ?TLS_DH_anon_WITH_RC4_128_MD5;
-suite({dh_anon, des_cbc, sha}) ->
- ?TLS_DH_anon_WITH_DES_CBC_SHA;
-suite({dh_anon, '3des_ede_cbc', sha}) ->
- ?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA;
-
-%%% TSL V1.1 AES suites
-suite({rsa, aes_128_cbc, sha}) ->
- ?TLS_RSA_WITH_AES_128_CBC_SHA;
-suite({dhe_dss, aes_128_cbc, sha}) ->
- ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
-suite({dhe_rsa, aes_128_cbc, sha}) ->
- ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
-suite({dh_anon, aes_128_cbc, sha}) ->
- ?TLS_DH_anon_WITH_AES_128_CBC_SHA;
-suite({rsa, aes_256_cbc, sha}) ->
- ?TLS_RSA_WITH_AES_256_CBC_SHA;
-suite({dhe_dss, aes_256_cbc, sha}) ->
- ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
-suite({dhe_rsa, aes_256_cbc, sha}) ->
- ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
-suite({dh_anon, aes_256_cbc, sha}) ->
- ?TLS_DH_anon_WITH_AES_256_CBC_SHA;
-
-%% TLS v1.2 suites
-
-%% suite_definition(?TLS_RSA_WITH_NULL_SHA) ->
-%% {rsa, null, sha, sha256};
-suite({rsa, aes_128_cbc, sha256}) ->
- ?TLS_RSA_WITH_AES_128_CBC_SHA256;
-suite({rsa, aes_256_cbc, sha256}) ->
- ?TLS_RSA_WITH_AES_256_CBC_SHA256;
-suite({dhe_dss, aes_128_cbc, sha256}) ->
- ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256;
-suite({dhe_rsa, aes_128_cbc, sha256}) ->
- ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
-suite({dhe_dss, aes_256_cbc, sha256}) ->
- ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256;
-suite({dhe_rsa, aes_256_cbc, sha256}) ->
- ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
-suite({dh_anon, aes_128_cbc, sha256}) ->
- ?TLS_DH_anon_WITH_AES_128_CBC_SHA256;
-suite({dh_anon, aes_256_cbc, sha256}) ->
- ?TLS_DH_anon_WITH_AES_256_CBC_SHA256;
-
-%%% PSK Cipher Suites RFC 4279
-
-suite({psk, rc4_128,sha}) ->
- ?TLS_PSK_WITH_RC4_128_SHA;
-suite({psk, '3des_ede_cbc',sha}) ->
- ?TLS_PSK_WITH_3DES_EDE_CBC_SHA;
-suite({psk, aes_128_cbc,sha}) ->
- ?TLS_PSK_WITH_AES_128_CBC_SHA;
-suite({psk, aes_256_cbc,sha}) ->
- ?TLS_PSK_WITH_AES_256_CBC_SHA;
-suite({dhe_psk, rc4_128,sha}) ->
- ?TLS_DHE_PSK_WITH_RC4_128_SHA;
-suite({dhe_psk, '3des_ede_cbc',sha}) ->
- ?TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA;
-suite({dhe_psk, aes_128_cbc,sha}) ->
- ?TLS_DHE_PSK_WITH_AES_128_CBC_SHA;
-suite({dhe_psk, aes_256_cbc,sha}) ->
- ?TLS_DHE_PSK_WITH_AES_256_CBC_SHA;
-suite({rsa_psk, rc4_128,sha}) ->
- ?TLS_RSA_PSK_WITH_RC4_128_SHA;
-suite({rsa_psk, '3des_ede_cbc',sha}) ->
- ?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA;
-suite({rsa_psk, aes_128_cbc,sha}) ->
- ?TLS_RSA_PSK_WITH_AES_128_CBC_SHA;
-suite({rsa_psk, aes_256_cbc,sha}) ->
- ?TLS_RSA_PSK_WITH_AES_256_CBC_SHA;
-
-%%% TLS 1.2 PSK Cipher Suites RFC 5487
-
-suite({psk, aes_128_gcm, null, sha256}) ->
- ?TLS_PSK_WITH_AES_128_GCM_SHA256;
-suite({psk, aes_256_gcm, null, sha384}) ->
- ?TLS_PSK_WITH_AES_256_GCM_SHA384;
-suite({dhe_psk, aes_128_gcm, null, sha256}) ->
- ?TLS_DHE_PSK_WITH_AES_128_GCM_SHA256;
-suite({dhe_psk, aes_256_gcm, null, sha384}) ->
- ?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384;
-suite({rsa_psk, aes_128_gcm, null, sha256}) ->
- ?TLS_RSA_PSK_WITH_AES_128_GCM_SHA256;
-suite({rsa_psk, aes_256_gcm, null, sha384}) ->
- ?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384;
-
-suite({psk, aes_128_cbc, sha256}) ->
- ?TLS_PSK_WITH_AES_128_CBC_SHA256;
-suite({psk, aes_256_cbc, sha384}) ->
- ?TLS_PSK_WITH_AES_256_CBC_SHA384;
-suite({dhe_psk, aes_128_cbc, sha256}) ->
- ?TLS_DHE_PSK_WITH_AES_128_CBC_SHA256;
-suite({dhe_psk, aes_256_cbc, sha384}) ->
- ?TLS_DHE_PSK_WITH_AES_256_CBC_SHA384;
-suite({rsa_psk, aes_128_cbc, sha256}) ->
- ?TLS_RSA_PSK_WITH_AES_128_CBC_SHA256;
-suite({rsa_psk, aes_256_cbc, sha384}) ->
- ?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384;
-
-suite({psk, null, sha256}) ->
- ?TLS_PSK_WITH_NULL_SHA256;
-suite({psk, null, sha384}) ->
- ?TLS_PSK_WITH_NULL_SHA384;
-suite({dhe_psk, null, sha256}) ->
- ?TLS_DHE_PSK_WITH_NULL_SHA256;
-suite({dhe_psk, null, sha384}) ->
- ?TLS_DHE_PSK_WITH_NULL_SHA384;
-suite({rsa_psk, null, sha256}) ->
- ?TLS_RSA_PSK_WITH_NULL_SHA256;
-suite({rsa_psk, null, sha384}) ->
- ?TLS_RSA_PSK_WITH_NULL_SHA384;
-
-%%% SRP Cipher Suites RFC 5054
-
-suite({srp_anon, '3des_ede_cbc', sha}) ->
- ?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA;
-suite({srp_rsa, '3des_ede_cbc', sha}) ->
- ?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
-suite({srp_dss, '3des_ede_cbc', sha}) ->
- ?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
-suite({srp_anon, aes_128_cbc, sha}) ->
- ?TLS_SRP_SHA_WITH_AES_128_CBC_SHA;
-suite({srp_rsa, aes_128_cbc, sha}) ->
- ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA;
-suite({srp_dss, aes_128_cbc, sha}) ->
- ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
-suite({srp_anon, aes_256_cbc, sha}) ->
- ?TLS_SRP_SHA_WITH_AES_256_CBC_SHA;
-suite({srp_rsa, aes_256_cbc, sha}) ->
- ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
-suite({srp_dss, aes_256_cbc, sha}) ->
- ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA;
-
-%%% RFC 4492 EC TLS suites
-suite({ecdh_ecdsa, null, sha}) ->
- ?TLS_ECDH_ECDSA_WITH_NULL_SHA;
-suite({ecdh_ecdsa, rc4_128, sha}) ->
- ?TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
-suite({ecdh_ecdsa, '3des_ede_cbc', sha}) ->
- ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
-suite({ecdh_ecdsa, aes_128_cbc, sha}) ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
-suite({ecdh_ecdsa, aes_256_cbc, sha}) ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
-
-suite({ecdhe_ecdsa, null, sha}) ->
- ?TLS_ECDHE_ECDSA_WITH_NULL_SHA;
-suite({ecdhe_ecdsa, rc4_128, sha}) ->
- ?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
-suite({ecdhe_ecdsa, '3des_ede_cbc', sha}) ->
- ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
-suite({ecdhe_ecdsa, aes_128_cbc, sha}) ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
-suite({ecdhe_ecdsa, aes_256_cbc, sha}) ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
-
-suite({ecdh_rsa, null, sha}) ->
- ?TLS_ECDH_RSA_WITH_NULL_SHA;
-suite({ecdh_rsa, rc4_128, sha}) ->
- ?TLS_ECDH_RSA_WITH_RC4_128_SHA;
-suite({ecdh_rsa, '3des_ede_cbc', sha}) ->
- ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
-suite({ecdh_rsa, aes_128_cbc, sha}) ->
- ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
-suite({ecdh_rsa, aes_256_cbc, sha}) ->
- ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
-
-suite({ecdhe_rsa, null, sha}) ->
- ?TLS_ECDHE_RSA_WITH_NULL_SHA;
-suite({ecdhe_rsa, rc4_128, sha}) ->
- ?TLS_ECDHE_RSA_WITH_RC4_128_SHA;
-suite({ecdhe_rsa, '3des_ede_cbc', sha}) ->
- ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
-suite({ecdhe_rsa, aes_128_cbc, sha}) ->
- ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
-suite({ecdhe_rsa, aes_256_cbc, sha}) ->
- ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
-
-suite({ecdh_anon, null, sha}) ->
- ?TLS_ECDH_anon_WITH_NULL_SHA;
-suite({ecdh_anon, rc4_128, sha}) ->
- ?TLS_ECDH_anon_WITH_RC4_128_SHA;
-suite({ecdh_anon, '3des_ede_cbc', sha}) ->
- ?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA;
-suite({ecdh_anon, aes_128_cbc, sha}) ->
- ?TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
-suite({ecdh_anon, aes_256_cbc, sha}) ->
- ?TLS_ECDH_anon_WITH_AES_256_CBC_SHA;
-
-%%% RFC 5289 EC TLS suites
-suite({ecdhe_ecdsa, aes_128_cbc, sha256, sha256}) ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
-suite({ecdhe_ecdsa, aes_256_cbc, sha384, sha384}) ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
-suite({ecdh_ecdsa, aes_128_cbc, sha256, sha256}) ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
-suite({ecdh_ecdsa, aes_256_cbc, sha384, sha384}) ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
-suite({ecdhe_rsa, aes_128_cbc, sha256, sha256}) ->
- ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
-suite({ecdhe_rsa, aes_256_cbc, sha384, sha384}) ->
- ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
-suite({ecdh_rsa, aes_128_cbc, sha256, sha256}) ->
- ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
-suite({ecdh_rsa, aes_256_cbc, sha384, sha384}) ->
- ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384;
-
-%% RFC 5288 AES-GCM Cipher Suites
-suite({rsa, aes_128_gcm, null, sha256}) ->
- ?TLS_RSA_WITH_AES_128_GCM_SHA256;
-suite({rsa, aes_256_gcm, null, sha384}) ->
- ?TLS_RSA_WITH_AES_256_GCM_SHA384;
-suite({dhe_rsa, aes_128_gcm, null, sha256}) ->
- ?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
-suite({dhe_rsa, aes_256_gcm, null, sha384}) ->
- ?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
-suite({dh_rsa, aes_128_gcm, null, sha256}) ->
- ?TLS_DH_RSA_WITH_AES_128_GCM_SHA256;
-suite({dh_rsa, aes_256_gcm, null, sha384}) ->
- ?TLS_DH_RSA_WITH_AES_256_GCM_SHA384;
-suite({dhe_dss, aes_128_gcm, null, sha256}) ->
- ?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256;
-suite({dhe_dss, aes_256_gcm, null, sha384}) ->
- ?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384;
-suite({dh_dss, aes_128_gcm, null, sha256}) ->
- ?TLS_DH_DSS_WITH_AES_128_GCM_SHA256;
-suite({dh_dss, aes_256_gcm, null, sha384}) ->
- ?TLS_DH_DSS_WITH_AES_256_GCM_SHA384;
-suite({dh_anon, aes_128_gcm, null, sha256}) ->
- ?TLS_DH_anon_WITH_AES_128_GCM_SHA256;
-suite({dh_anon, aes_256_gcm, null, sha384}) ->
- ?TLS_DH_anon_WITH_AES_256_GCM_SHA384;
-
-%% RFC 5289 ECC AES-GCM Cipher Suites
-suite({ecdhe_ecdsa, aes_128_gcm, null, sha256}) ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
-suite({ecdhe_ecdsa, aes_256_gcm, null, sha384}) ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
-suite({ecdh_ecdsa, aes_128_gcm, null, sha256}) ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
-suite({ecdh_ecdsa, aes_256_gcm, null, sha384}) ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
-suite({ecdhe_rsa, aes_128_gcm, null, sha256}) ->
- ?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
-suite({ecdhe_rsa, aes_256_gcm, null, sha384}) ->
- ?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
-suite({ecdh_rsa, aes_128_gcm, null, sha256}) ->
- ?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
-suite({ecdh_rsa, aes_256_gcm, null, sha384}) ->
- ?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384;
-
-
-%% draft-agl-tls-chacha20poly1305-04 Chacha20/Poly1305 Suites
-suite({ecdhe_rsa, chacha20_poly1305, null, sha256}) ->
- ?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
-suite({ecdhe_ecdsa, chacha20_poly1305, null, sha256}) ->
- ?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256;
-suite({dhe_rsa, chacha20_poly1305, null, sha256}) ->
- ?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256.
+ ?TLS_RSA_WITH_DES_CBC_SHA,
+ ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+ ].
%%--------------------------------------------------------------------
--spec openssl_suite(openssl_cipher_suite()) -> cipher_suite().
+-spec rsa_suites(Version::ssl_record:ssl_version() | integer()) -> [ssl_cipher_format:cipher_suite()].
%%
-%% Description: Return TLS cipher suite definition.
-%%--------------------------------------------------------------------
-%% translate constants <-> openssl-strings
-openssl_suite("DHE-RSA-AES256-SHA256") ->
- ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
-openssl_suite("DHE-DSS-AES256-SHA256") ->
- ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256;
-openssl_suite("AES256-SHA256") ->
- ?TLS_RSA_WITH_AES_256_CBC_SHA256;
-openssl_suite("DHE-RSA-AES128-SHA256") ->
- ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("DHE-DSS-AES128-SHA256") ->
- ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256;
-openssl_suite("AES128-SHA256") ->
- ?TLS_RSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("DHE-RSA-AES256-SHA") ->
- ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
-openssl_suite("DHE-DSS-AES256-SHA") ->
- ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
-openssl_suite("AES256-SHA") ->
- ?TLS_RSA_WITH_AES_256_CBC_SHA;
-openssl_suite("EDH-RSA-DES-CBC3-SHA") ->
- ?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("EDH-DSS-DES-CBC3-SHA") ->
- ?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("DES-CBC3-SHA") ->
- ?TLS_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("DHE-RSA-AES128-SHA") ->
- ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
-openssl_suite("DHE-DSS-AES128-SHA") ->
- ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
-openssl_suite("AES128-SHA") ->
- ?TLS_RSA_WITH_AES_128_CBC_SHA;
-openssl_suite("RC4-SHA") ->
- ?TLS_RSA_WITH_RC4_128_SHA;
-openssl_suite("RC4-MD5") ->
- ?TLS_RSA_WITH_RC4_128_MD5;
-openssl_suite("EDH-RSA-DES-CBC-SHA") ->
- ?TLS_DHE_RSA_WITH_DES_CBC_SHA;
-openssl_suite("DES-CBC-SHA") ->
- ?TLS_RSA_WITH_DES_CBC_SHA;
-
-%%% SRP Cipher Suites RFC 5054
-
-openssl_suite("SRP-DSS-AES-256-CBC-SHA") ->
- ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA;
-openssl_suite("SRP-RSA-AES-256-CBC-SHA") ->
- ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
-openssl_suite("SRP-DSS-3DES-EDE-CBC-SHA") ->
- ?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("SRP-RSA-3DES-EDE-CBC-SHA") ->
- ?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("SRP-DSS-AES-128-CBC-SHA") ->
- ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
-openssl_suite("SRP-RSA-AES-128-CBC-SHA") ->
- ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA;
-
-%% RFC 4492 EC TLS suites
-openssl_suite("ECDH-ECDSA-RC4-SHA") ->
- ?TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
-openssl_suite("ECDH-ECDSA-DES-CBC3-SHA") ->
- ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("ECDH-ECDSA-AES128-SHA") ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
-openssl_suite("ECDH-ECDSA-AES256-SHA") ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
-
-openssl_suite("ECDHE-ECDSA-RC4-SHA") ->
- ?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
-openssl_suite("ECDHE-ECDSA-DES-CBC3-SHA") ->
- ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("ECDHE-ECDSA-AES128-SHA") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
-openssl_suite("ECDHE-ECDSA-AES256-SHA") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
-
-openssl_suite("ECDHE-RSA-RC4-SHA") ->
- ?TLS_ECDHE_RSA_WITH_RC4_128_SHA;
-openssl_suite("ECDHE-RSA-DES-CBC3-SHA") ->
- ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("ECDHE-RSA-AES128-SHA") ->
- ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
-openssl_suite("ECDHE-RSA-AES256-SHA") ->
- ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
-
-openssl_suite("ECDH-RSA-RC4-SHA") ->
- ?TLS_ECDH_RSA_WITH_RC4_128_SHA;
-openssl_suite("ECDH-RSA-DES-CBC3-SHA") ->
- ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("ECDH-RSA-AES128-SHA") ->
- ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
-openssl_suite("ECDH-RSA-AES256-SHA") ->
- ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
-
-%% RFC 5289 EC TLS suites
-openssl_suite("ECDHE-ECDSA-AES128-SHA256") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("ECDHE-ECDSA-AES256-SHA384") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
-openssl_suite("ECDH-ECDSA-AES128-SHA256") ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("ECDH-ECDSA-AES256-SHA384") ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
-openssl_suite("ECDHE-RSA-AES128-SHA256") ->
- ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("ECDHE-RSA-AES256-SHA384") ->
- ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
-openssl_suite("ECDH-RSA-AES128-SHA256") ->
- ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("ECDH-RSA-AES256-SHA384") ->
- ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384;
-
-%% RFC 5288 AES-GCM Cipher Suites
-openssl_suite("AES128-GCM-SHA256") ->
- ?TLS_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("AES256-GCM-SHA384") ->
- ?TLS_RSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("DHE-RSA-AES128-GCM-SHA256") ->
- ?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("DHE-RSA-AES256-GCM-SHA384") ->
- ?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("DH-RSA-AES128-GCM-SHA256") ->
- ?TLS_DH_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("DH-RSA-AES256-GCM-SHA384") ->
- ?TLS_DH_RSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("DHE-DSS-AES128-GCM-SHA256") ->
- ?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256;
-openssl_suite("DHE-DSS-AES256-GCM-SHA384") ->
- ?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384;
-openssl_suite("DH-DSS-AES128-GCM-SHA256") ->
- ?TLS_DH_DSS_WITH_AES_128_GCM_SHA256;
-openssl_suite("DH-DSS-AES256-GCM-SHA384") ->
- ?TLS_DH_DSS_WITH_AES_256_GCM_SHA384;
-
-%% RFC 5289 ECC AES-GCM Cipher Suites
-openssl_suite("ECDHE-ECDSA-AES128-GCM-SHA256") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("ECDHE-ECDSA-AES256-GCM-SHA384") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("ECDH-ECDSA-AES128-GCM-SHA256") ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("ECDH-ECDSA-AES256-GCM-SHA384") ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("ECDHE-RSA-AES128-GCM-SHA256") ->
- ?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("ECDHE-RSA-AES256-GCM-SHA384") ->
- ?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("ECDH-RSA-AES128-GCM-SHA256") ->
- ?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("ECDH-RSA-AES256-GCM-SHA384") ->
- ?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384.
-
+%% Description: Returns a list of the RSA key exchange
+%% cipher suites, only supported if explicitly set by user.
+%% Are not considered secure any more.
%%--------------------------------------------------------------------
--spec openssl_suite_name(cipher_suite()) -> openssl_cipher_suite().
-%%
-%% Description: Return openssl cipher suite name.
-%%-------------------------------------------------------------------
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA) ->
- "DHE-RSA-AES256-SHA";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA) ->
- "DHE-DSS-AES256-SHA";
-openssl_suite_name(?TLS_RSA_WITH_AES_256_CBC_SHA) ->
- "AES256-SHA";
-openssl_suite_name(?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "EDH-RSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) ->
- "EDH-DSS-DES-CBC3-SHA";
-openssl_suite_name(?TLS_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "DES-CBC3-SHA";
-openssl_suite_name( ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA) ->
- "DHE-RSA-AES128-SHA";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA) ->
- "DHE-DSS-AES128-SHA";
-openssl_suite_name(?TLS_RSA_WITH_AES_128_CBC_SHA) ->
- "AES128-SHA";
-openssl_suite_name(?TLS_RSA_WITH_RC4_128_SHA) ->
- "RC4-SHA";
-openssl_suite_name(?TLS_RSA_WITH_RC4_128_MD5) ->
- "RC4-MD5";
-openssl_suite_name(?TLS_DHE_RSA_WITH_DES_CBC_SHA) ->
- "EDH-RSA-DES-CBC-SHA";
-openssl_suite_name(?TLS_RSA_WITH_DES_CBC_SHA) ->
- "DES-CBC-SHA";
-openssl_suite_name(?TLS_RSA_WITH_NULL_SHA256) ->
- "NULL-SHA256";
-openssl_suite_name(?TLS_RSA_WITH_AES_128_CBC_SHA256) ->
- "AES128-SHA256";
-openssl_suite_name(?TLS_RSA_WITH_AES_256_CBC_SHA256) ->
- "AES256-SHA256";
-openssl_suite_name(?TLS_DH_DSS_WITH_AES_128_CBC_SHA256) ->
- "DH-DSS-AES128-SHA256";
-openssl_suite_name(?TLS_DH_RSA_WITH_AES_128_CBC_SHA256) ->
- "DH-RSA-AES128-SHA256";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) ->
- "DHE-DSS-AES128-SHA256";
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) ->
- "DHE-RSA-AES128-SHA256";
-openssl_suite_name(?TLS_DH_DSS_WITH_AES_256_CBC_SHA256) ->
- "DH-DSS-AES256-SHA256";
-openssl_suite_name(?TLS_DH_RSA_WITH_AES_256_CBC_SHA256) ->
- "DH-RSA-AES256-SHA256";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) ->
- "DHE-DSS-AES256-SHA256";
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) ->
- "DHE-RSA-AES256-SHA256";
-
-%%% PSK Cipher Suites RFC 4279
-
-openssl_suite_name(?TLS_PSK_WITH_AES_256_CBC_SHA) ->
- "PSK-AES256-CBC-SHA";
-openssl_suite_name(?TLS_PSK_WITH_3DES_EDE_CBC_SHA) ->
- "PSK-3DES-EDE-CBC-SHA";
-openssl_suite_name(?TLS_PSK_WITH_AES_128_CBC_SHA) ->
- "PSK-AES128-CBC-SHA";
-openssl_suite_name(?TLS_PSK_WITH_RC4_128_SHA) ->
- "PSK-RC4-SHA";
-
-%%% SRP Cipher Suites RFC 5054
-
-openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "SRP-RSA-3DES-EDE-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) ->
- "SRP-DSS-3DES-EDE-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) ->
- "SRP-RSA-AES-128-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA) ->
- "SRP-DSS-AES-128-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) ->
- "SRP-RSA-AES-256-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) ->
- "SRP-DSS-AES-256-CBC-SHA";
-
-%% RFC 4492 EC TLS suites
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_RC4_128_SHA) ->
- "ECDH-ECDSA-RC4-SHA";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
- "ECDH-ECDSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) ->
- "ECDH-ECDSA-AES128-SHA";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) ->
- "ECDH-ECDSA-AES256-SHA";
-
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) ->
- "ECDHE-ECDSA-RC4-SHA";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
- "ECDHE-ECDSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) ->
- "ECDHE-ECDSA-AES128-SHA";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) ->
- "ECDHE-ECDSA-AES256-SHA";
-
-openssl_suite_name(?TLS_ECDH_RSA_WITH_RC4_128_SHA) ->
- "ECDH-RSA-RC4-SHA";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "ECDH-RSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) ->
- "ECDH-RSA-AES128-SHA";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) ->
- "ECDH-RSA-AES256-SHA";
-
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_RC4_128_SHA) ->
- "ECDHE-RSA-RC4-SHA";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "ECDHE-RSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) ->
- "ECDHE-RSA-AES128-SHA";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) ->
- "ECDHE-RSA-AES256-SHA";
-
-%% RFC 5289 EC TLS suites
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) ->
- "ECDHE-ECDSA-AES128-SHA256";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) ->
- "ECDHE-ECDSA-AES256-SHA384";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) ->
- "ECDH-ECDSA-AES128-SHA256";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) ->
- "ECDH-ECDSA-AES256-SHA384";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) ->
- "ECDHE-RSA-AES128-SHA256";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) ->
- "ECDHE-RSA-AES256-SHA384";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) ->
- "ECDH-RSA-AES128-SHA256";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) ->
- "ECDH-RSA-AES256-SHA384";
-
-%% RFC 5288 AES-GCM Cipher Suites
-openssl_suite_name(?TLS_RSA_WITH_AES_128_GCM_SHA256) ->
- "AES128-GCM-SHA256";
-openssl_suite_name(?TLS_RSA_WITH_AES_256_GCM_SHA384) ->
- "AES256-GCM-SHA384";
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) ->
- "DHE-RSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) ->
- "DHE-RSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_DH_RSA_WITH_AES_128_GCM_SHA256) ->
- "DH-RSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_DH_RSA_WITH_AES_256_GCM_SHA384) ->
- "DH-RSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256) ->
- "DHE-DSS-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384) ->
- "DHE-DSS-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_DH_DSS_WITH_AES_128_GCM_SHA256) ->
- "DH-DSS-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_DH_DSS_WITH_AES_256_GCM_SHA384) ->
- "DH-DSS-AES256-GCM-SHA384";
-
-%% RFC 5289 ECC AES-GCM Cipher Suites
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) ->
- "ECDHE-ECDSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) ->
- "ECDHE-ECDSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256) ->
- "ECDH-ECDSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384) ->
- "ECDH-ECDSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) ->
- "ECDHE-RSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) ->
- "ECDHE-RSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) ->
- "ECDH-RSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) ->
- "ECDH-RSA-AES256-GCM-SHA384";
-
-%% No oppenssl name
-openssl_suite_name(Cipher) ->
- suite_definition(Cipher).
+rsa_suites({3, 0}) ->
+ rsa_suites(0);
+rsa_suites({3, Minor}) ->
+ rsa_suites(Minor) ++ rsa_suites(0);
+rsa_suites(0) ->
+ [?TLS_RSA_WITH_AES_256_CBC_SHA,
+ ?TLS_RSA_WITH_AES_128_CBC_SHA,
+ ?TLS_RSA_WITH_3DES_EDE_CBC_SHA
+ ];
+rsa_suites(N) when N =< 3 ->
+ [
+ ?TLS_RSA_WITH_AES_256_GCM_SHA384,
+ ?TLS_RSA_WITH_AES_256_CBC_SHA256,
+ ?TLS_RSA_WITH_AES_128_GCM_SHA256,
+ ?TLS_RSA_WITH_AES_128_CBC_SHA256
+ ].
%%--------------------------------------------------------------------
--spec filter(undefined | binary(), [cipher_suite()]) -> [cipher_suite()].
+-spec filter(undefined | binary(), [ssl_cipher_format:cipher_suite()],
+ ssl_record:ssl_version()) -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Select the cipher suites that can be used together with the
%% supplied certificate. (Server side functionality)
%%-------------------------------------------------------------------
-filter(undefined, Ciphers) ->
+filter(undefined, Ciphers, _) ->
Ciphers;
-filter(DerCert, Ciphers) ->
+filter(DerCert, Ciphers0, Version) ->
OtpCert = public_key:pkix_decode_cert(DerCert, otp),
SigAlg = OtpCert#'OTPCertificate'.signatureAlgorithm,
PubKeyInfo = OtpCert#'OTPCertificate'.tbsCertificate#'OTPTBSCertificate'.subjectPublicKeyInfo,
PubKeyAlg = PubKeyInfo#'OTPSubjectPublicKeyInfo'.algorithm,
- Ciphers1 =
- case ssl_certificate:public_key_type(PubKeyAlg#'PublicKeyAlgorithm'.algorithm) of
- rsa ->
- filter_keyuse(OtpCert, ((Ciphers -- dsa_signed_suites()) -- ec_keyed_suites()) -- ecdh_suites(),
- rsa_suites(), dhe_rsa_suites() ++ ecdhe_rsa_suites());
- dsa ->
- (Ciphers -- rsa_keyed_suites()) -- ec_keyed_suites();
- ec ->
- filter_keyuse(OtpCert, (Ciphers -- rsa_keyed_suites()) -- dsa_signed_suites(),
- [], ecdhe_ecdsa_suites())
- end,
-
- case public_key:pkix_sign_types(SigAlg#'SignatureAlgorithm'.algorithm) of
- {_, rsa} ->
- Ciphers1 -- ecdsa_signed_suites();
- {_, dsa} ->
- Ciphers1;
- {_, ecdsa} ->
- Ciphers1 -- rsa_signed_suites()
- end.
-
+ Ciphers = filter_suites_pubkey(
+ ssl_certificate:public_key_type(PubKeyAlg#'PublicKeyAlgorithm'.algorithm),
+ Ciphers0, Version, OtpCert),
+ {_, Sign} = public_key:pkix_sign_types(SigAlg#'SignatureAlgorithm'.algorithm),
+ filter_suites_signature(Sign, Ciphers, Version).
+
+%%--------------------------------------------------------------------
+-spec filter_suites([ssl_cipher_format:erl_cipher_suite()] | [ssl_cipher_format:cipher_suite()], map()) ->
+ [ssl_cipher_format:erl_cipher_suite()] | [ssl_cipher_format:cipher_suite()].
+%%
+%% Description: Filter suites using supplied filter funs
+%%-------------------------------------------------------------------
+filter_suites(Suites, Filters) ->
+ ApplyFilters = fun(Suite) ->
+ filter_suite(Suite, Filters)
+ end,
+ lists:filter(ApplyFilters, Suites).
+
+filter_suite(#{key_exchange := KeyExchange,
+ cipher := Cipher,
+ mac := Hash,
+ prf := Prf},
+ #{key_exchange_filters := KeyFilters,
+ cipher_filters := CipherFilters,
+ mac_filters := HashFilters,
+ prf_filters := PrfFilters}) ->
+ all_filters(KeyExchange, KeyFilters) andalso
+ all_filters(Cipher, CipherFilters) andalso
+ all_filters(Hash, HashFilters) andalso
+ all_filters(Prf, PrfFilters);
+filter_suite(Suite, Filters) ->
+ filter_suite(ssl_cipher_format:suite_definition(Suite), Filters).
+
%%--------------------------------------------------------------------
--spec filter_suites([cipher_suite()]) -> [cipher_suite()].
+-spec filter_suites([ssl_cipher_format:erl_cipher_suite()] | [ssl_cipher_format:cipher_suite()]) ->
+ [ssl_cipher_format:erl_cipher_suite()] | [ssl_cipher_format:cipher_suite()].
%%
%% Description: Filter suites for algorithms supported by crypto.
%%-------------------------------------------------------------------
-filter_suites(Suites = [Value|_]) when is_tuple(Value) ->
- Algos = crypto:supports(),
- Hashs = proplists:get_value(hashs, Algos),
- lists:filter(fun({KeyExchange, Cipher, Hash}) ->
- is_acceptable_keyexchange(KeyExchange, proplists:get_value(public_keys, Algos)) andalso
- is_acceptable_cipher(Cipher, proplists:get_value(ciphers, Algos)) andalso
- is_acceptable_hash(Hash, proplists:get_value(hashs, Algos));
- ({KeyExchange, Cipher, Hash, Prf}) ->
- is_acceptable_keyexchange(KeyExchange, proplists:get_value(public_keys, Algos)) andalso
- is_acceptable_cipher(Cipher, proplists:get_value(ciphers, Algos)) andalso
- is_acceptable_hash(Hash, Hashs) andalso
- is_acceptable_prf(Prf, Hashs)
- end, Suites);
-
filter_suites(Suites) ->
+ Filters = crypto_support_filters(),
+ filter_suites(Suites, Filters).
+
+all_filters(_, []) ->
+ true;
+all_filters(Value, [Filter| Rest]) ->
+ case Filter(Value) of
+ true ->
+ all_filters(Value, Rest);
+ false ->
+ false
+ end.
+crypto_support_filters() ->
Algos = crypto:supports(),
Hashs = proplists:get_value(hashs, Algos),
- lists:filter(fun(Suite) ->
- {KeyExchange, Cipher, Hash, Prf} = ssl_cipher:suite_definition(Suite),
- is_acceptable_keyexchange(KeyExchange, proplists:get_value(public_keys, Algos)) andalso
- is_acceptable_cipher(Cipher, proplists:get_value(ciphers, Algos)) andalso
- is_acceptable_hash(Hash, Hashs) andalso
- is_acceptable_prf(Prf, Hashs)
- end, Suites).
+ #{key_exchange_filters =>
+ [fun(KeyExchange) ->
+ is_acceptable_keyexchange(KeyExchange,
+ proplists:get_value(public_keys, Algos))
+ end],
+ cipher_filters =>
+ [fun(Cipher) ->
+ is_acceptable_cipher(Cipher,
+ proplists:get_value(ciphers, Algos))
+ end],
+ mac_filters =>
+ [fun(Hash) ->
+ is_acceptable_hash(Hash, Hashs)
+ end],
+ prf_filters =>
+ [fun(Prf) ->
+ is_acceptable_prf(Prf,
+ proplists:get_value(hashs, Algos))
+ end]}.
is_acceptable_keyexchange(KeyExchange, _Algos) when KeyExchange == psk;
KeyExchange == null ->
@@ -1465,7 +611,8 @@ is_acceptable_keyexchange(dhe_dss, Algos) ->
is_acceptable_keyexchange(dhe_rsa, Algos) ->
proplists:get_bool(dh, Algos) andalso
proplists:get_bool(rsa, Algos);
-is_acceptable_keyexchange(ecdh_anon, Algos) ->
+is_acceptable_keyexchange(KeyExchange, Algos) when KeyExchange == ecdh_anon;
+ KeyExchange == ecdhe_psk ->
proplists:get_bool(ecdh, Algos);
is_acceptable_keyexchange(KeyExchange, Algos) when KeyExchange == ecdh_ecdsa;
KeyExchange == ecdhe_ecdsa ->
@@ -1510,6 +657,8 @@ is_acceptable_cipher(Cipher, Algos) ->
is_acceptable_hash(null, _Algos) ->
true;
+is_acceptable_hash(aead, _Algos) ->
+ true;
is_acceptable_hash(Hash, Algos) ->
proplists:get_bool(Hash, Algos).
@@ -1541,7 +690,7 @@ calc_mac_hash(Type, Version,
MacSecret, SeqNo, Type,
Length, PlainFragment).
-is_stream_ciphersuite({_, rc4_128, _, _}) ->
+is_stream_ciphersuite(#{cipher := rc4_128}) ->
true;
is_stream_ciphersuite(_) ->
false.
@@ -1669,6 +818,11 @@ prf_algorithm(default_prf, {3, _}) ->
prf_algorithm(Algo, _) ->
hash_algorithm(Algo).
+mac_algorithm(aead) ->
+ aead;
+mac_algorithm(Algo) ->
+ hash_algorithm(Algo).
+
hash_algorithm(null) -> ?NULL;
hash_algorithm(md5) -> ?MD5;
hash_algorithm(sha) -> ?SHA; %% Only sha always refers to "SHA-1"
@@ -1699,6 +853,10 @@ sign_algorithm(Other) when is_integer(Other) andalso ((Other >= 224) and (Other
hash_size(null) ->
0;
+%% The AEAD MAC hash size is not used in the context
+%% of calculating the master secret. See RFC 5246 Section 6.2.3.3.
+hash_size(aead) ->
+ 0;
hash_size(md5) ->
16;
hash_size(sha) ->
@@ -1803,143 +961,214 @@ next_iv(Bin, IV) ->
<<_:FirstPart/binary, NextIV:IVSz/binary>> = Bin,
NextIV.
-rsa_signed_suites() ->
- dhe_rsa_suites() ++ rsa_suites() ++
- psk_rsa_suites() ++ srp_rsa_suites() ++
- ecdh_rsa_suites() ++ ecdhe_rsa_suites().
-
-rsa_keyed_suites() ->
- dhe_rsa_suites() ++ rsa_suites() ++
- psk_rsa_suites() ++ srp_rsa_suites() ++
- ecdhe_rsa_suites().
-
-dhe_rsa_suites() ->
- [?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
- ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
- ?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
- ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
- ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
- ?TLS_DHE_RSA_WITH_DES_CBC_SHA,
- ?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
- ?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
- ?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- ].
-
-psk_rsa_suites() ->
- [?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
- ?TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
- ?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
- ?TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
- ?TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
- ?TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
- ?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
- ?TLS_RSA_PSK_WITH_RC4_128_SHA].
-
-srp_rsa_suites() ->
- [?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
- ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
- ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA].
-
-rsa_suites() ->
- [?TLS_RSA_WITH_AES_256_CBC_SHA256,
- ?TLS_RSA_WITH_AES_256_CBC_SHA,
- ?TLS_RSA_WITH_3DES_EDE_CBC_SHA,
- ?TLS_RSA_WITH_AES_128_CBC_SHA256,
- ?TLS_RSA_WITH_AES_128_CBC_SHA,
- ?TLS_RSA_WITH_RC4_128_SHA,
- ?TLS_RSA_WITH_RC4_128_MD5,
- ?TLS_RSA_WITH_DES_CBC_SHA,
- ?TLS_RSA_WITH_AES_128_GCM_SHA256,
- ?TLS_RSA_WITH_AES_256_GCM_SHA384].
-
-ecdh_rsa_suites() ->
- [?TLS_ECDH_RSA_WITH_NULL_SHA,
- ?TLS_ECDH_RSA_WITH_RC4_128_SHA,
- ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
- ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
- ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
- ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
- ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
- ?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
- ?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384].
-
-ecdhe_rsa_suites() ->
- [?TLS_ECDHE_RSA_WITH_NULL_SHA,
- ?TLS_ECDHE_RSA_WITH_RC4_128_SHA,
- ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
- ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
- ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
- ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
- ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
- ?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- ?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
- ?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256].
-
-dsa_signed_suites() ->
- dhe_dss_suites() ++ srp_dss_suites().
-
-dhe_dss_suites() ->
- [?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
- ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
- ?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
- ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
- ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
- ?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
- ?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,
- ?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384].
-
-srp_dss_suites() ->
- [?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
- ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
- ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA].
+filter_suites_pubkey(rsa, CiphersSuites0, _Version, OtpCert) ->
+ KeyUses = key_uses(OtpCert),
+ NotECDSAKeyed = (CiphersSuites0 -- ec_keyed_suites(CiphersSuites0))
+ -- dss_keyed_suites(CiphersSuites0),
+ CiphersSuites = filter_keyuse_suites(keyEncipherment, KeyUses,
+ NotECDSAKeyed,
+ rsa_suites_encipher(CiphersSuites0)),
+ filter_keyuse_suites(digitalSignature, KeyUses, CiphersSuites,
+ rsa_ecdhe_dhe_suites(CiphersSuites));
+filter_suites_pubkey(dsa, Ciphers, _, OtpCert) ->
+ KeyUses = key_uses(OtpCert),
+ NotECRSAKeyed = (Ciphers -- rsa_keyed_suites(Ciphers)) -- ec_keyed_suites(Ciphers),
+ filter_keyuse_suites(digitalSignature, KeyUses, NotECRSAKeyed,
+ dss_dhe_suites(Ciphers));
+filter_suites_pubkey(ec, Ciphers, _, OtpCert) ->
+ Uses = key_uses(OtpCert),
+ NotRSADSAKeyed = (Ciphers -- rsa_keyed_suites(Ciphers)) -- dss_keyed_suites(Ciphers),
+ CiphersSuites = filter_keyuse_suites(digitalSignature, Uses, NotRSADSAKeyed,
+ ec_ecdhe_suites(Ciphers)),
+ filter_keyuse_suites(keyAgreement, Uses, CiphersSuites, ec_ecdh_suites(Ciphers)).
+
+filter_suites_signature(rsa, Ciphers, {3, N}) when N >= 3 ->
+ Ciphers;
+filter_suites_signature(rsa, Ciphers, Version) ->
+ (Ciphers -- ecdsa_signed_suites(Ciphers, Version)) -- dsa_signed_suites(Ciphers, Version);
+filter_suites_signature(dsa, Ciphers, Version) ->
+ (Ciphers -- ecdsa_signed_suites(Ciphers, Version)) -- rsa_signed_suites(Ciphers, Version);
+filter_suites_signature(ecdsa, Ciphers, Version) ->
+ (Ciphers -- rsa_signed_suites(Ciphers, Version)) -- dsa_signed_suites(Ciphers, Version).
+
+
+%% From RFC 5246 - Section 7.4.2. Server Certificate
+%% If the client provided a "signature_algorithms" extension, then all
+%% certificates provided by the server MUST be signed by a
+%% hash/signature algorithm pair that appears in that extension. Note
+%% that this implies that a certificate containing a key for one
+%% signature algorithm MAY be signed using a different signature
+%% algorithm (for instance, an RSA key signed with a DSA key). This is
+%% a departure from TLS 1.1, which required that the algorithms be the
+%% same.
+%% Note that this also implies that the DH_DSS, DH_RSA,
+%% ECDH_ECDSA, and ECDH_RSA key exchange algorithms do not restrict the
+%% algorithm used to sign the certificate. Fixed DH certificates MAY be
+%% signed with any hash/signature algorithm pair appearing in the
+%% extension. The names DH_DSS, DH_RSA, ECDH_ECDSA, and ECDH_RSA are
+%% historical.
+%% Note: DH_DSS and DH_RSA is not supported
+rsa_signed({3,N}) when N >= 3 ->
+ fun(rsa) -> true;
+ (dhe_rsa) -> true;
+ (ecdhe_rsa) -> true;
+ (rsa_psk) -> true;
+ (srp_rsa) -> true;
+ (_) -> false
+ end;
+rsa_signed(_) ->
+ fun(rsa) -> true;
+ (dhe_rsa) -> true;
+ (ecdhe_rsa) -> true;
+ (ecdh_rsa) -> true;
+ (rsa_psk) -> true;
+ (srp_rsa) -> true;
+ (_) -> false
+ end.
+%% Cert should be signed by RSA
+rsa_signed_suites(Ciphers, Version) ->
+ filter_suites(Ciphers, #{key_exchange_filters => [rsa_signed(Version)],
+ cipher_filters => [],
+ mac_filters => [],
+ prf_filters => []}).
+ecdsa_signed({3,N}) when N >= 3 ->
+ fun(ecdhe_ecdsa) -> true;
+ (_) -> false
+ end;
+ecdsa_signed(_) ->
+ fun(ecdhe_ecdsa) -> true;
+ (ecdh_ecdsa) -> true;
+ (_) -> false
+ end.
+
+%% Cert should be signed by ECDSA
+ecdsa_signed_suites(Ciphers, Version) ->
+ filter_suites(Ciphers, #{key_exchange_filters => [ecdsa_signed(Version)],
+ cipher_filters => [],
+ mac_filters => [],
+ prf_filters => []}).
+
+rsa_keyed(dhe_rsa) ->
+ true;
+rsa_keyed(ecdhe_rsa) ->
+ true;
+rsa_keyed(rsa) ->
+ true;
+rsa_keyed(rsa_psk) ->
+ true;
+rsa_keyed(srp_rsa) ->
+ true;
+rsa_keyed(_) ->
+ false.
-ec_keyed_suites() ->
- ecdh_ecdsa_suites() ++ ecdhe_ecdsa_suites()
- ++ ecdh_rsa_suites().
+%% Certs key is an RSA key
+rsa_keyed_suites(Ciphers) ->
+ filter_suites(Ciphers, #{key_exchange_filters => [fun(Kex) -> rsa_keyed(Kex) end],
+ cipher_filters => [],
+ mac_filters => [],
+ prf_filters => []}).
+
+%% RSA Certs key can be used for encipherment
+rsa_suites_encipher(Ciphers) ->
+ filter_suites(Ciphers, #{key_exchange_filters => [fun(rsa) -> true;
+ (rsa_psk) -> true;
+ (_) -> false
+ end],
+ cipher_filters => [],
+ mac_filters => [],
+ prf_filters => []}).
+
+dss_keyed(dhe_dss) ->
+ true;
+dss_keyed(spr_dss) ->
+ true;
+dss_keyed(_) ->
+ false.
+
+%% Cert should be have DSS key (DSA)
+dss_keyed_suites(Ciphers) ->
+ filter_suites(Ciphers, #{key_exchange_filters => [fun(Kex) -> dss_keyed(Kex) end],
+ cipher_filters => [],
+ mac_filters => [],
+ prf_filters => []}).
+
+%% Cert should be signed by DSS (DSA)
+dsa_signed_suites(Ciphers, Version) ->
+ filter_suites(Ciphers, #{key_exchange_filters => [dsa_signed(Version)],
+ cipher_filters => [],
+ mac_filters => [],
+ prf_filters => []}).
+dsa_signed(_) ->
+ fun(dhe_dss) -> true;
+ (_) -> false
+ end.
-ecdsa_signed_suites() ->
- ecdh_ecdsa_suites() ++ ecdhe_ecdsa_suites().
+dss_dhe_suites(Ciphers) ->
+ filter_suites(Ciphers, #{key_exchange_filters => [fun(dhe_dss) -> true;
+ (_) -> false
+ end],
+ cipher_filters => [],
+ mac_filters => [],
+ prf_filters => []}).
-ecdh_suites() ->
- ecdh_rsa_suites() ++ ecdh_ecdsa_suites().
+ec_keyed(ecdh_ecdsa) ->
+ true;
+ec_keyed(ecdh_rsa) ->
+ true;
+ec_keyed(ecdhe_ecdsa) ->
+ true;
+ec_keyed(_) ->
+ false.
-ecdh_ecdsa_suites() ->
- [?TLS_ECDH_ECDSA_WITH_NULL_SHA,
- ?TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
- ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
- ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
- ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
- ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
- ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
- ?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
- ?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384].
-
-ecdhe_ecdsa_suites() ->
- [?TLS_ECDHE_ECDSA_WITH_NULL_SHA,
- ?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
- ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
- ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
- ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
- ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
- ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
- ?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- ?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
- ?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256].
-
-filter_keyuse(OtpCert, Ciphers, Suites, SignSuites) ->
+%% Certs key is an ECC key
+ec_keyed_suites(Ciphers) ->
+ filter_suites(Ciphers, #{key_exchange_filters => [fun(Kex) -> ec_keyed(Kex) end],
+ cipher_filters => [],
+ mac_filters => [],
+ prf_filters => []}).
+
+%% EC Certs key usage keyAgreement
+ec_ecdh_suites(Ciphers)->
+ filter_suites(Ciphers, #{key_exchange_filters => [fun(ecdh_ecdsa) -> true;
+ (_) -> false
+ end],
+ cipher_filters => [],
+ mac_filters => [],
+ prf_filters => []}).
+
+%% EC Certs key usage digitalSignature
+ec_ecdhe_suites(Ciphers) ->
+ filter_suites(Ciphers, #{key_exchange_filters => [fun(ecdhe_ecdsa) -> true;
+ (ecdhe_rsa) -> true;
+ (_) -> false
+ end],
+ cipher_filters => [],
+ mac_filters => [],
+ prf_filters => []}).
+%% RSA Certs key usage digitalSignature
+rsa_ecdhe_dhe_suites(Ciphers) ->
+ filter_suites(Ciphers, #{key_exchange_filters => [fun(dhe_rsa) -> true;
+ (ecdhe_rsa) -> true;
+ (_) -> false
+ end],
+ cipher_filters => [],
+ mac_filters => [],
+ prf_filters => []}).
+
+key_uses(OtpCert) ->
TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
TBSExtensions = TBSCert#'OTPTBSCertificate'.extensions,
Extensions = ssl_certificate:extensions_list(TBSExtensions),
case ssl_certificate:select_extension(?'id-ce-keyUsage', Extensions) of
undefined ->
- Ciphers;
- #'Extension'{extnValue = KeyUse} ->
- Result = filter_keyuse_suites(keyEncipherment,
- KeyUse, Ciphers, Suites),
- filter_keyuse_suites(digitalSignature,
- KeyUse, Result, SignSuites)
+ [];
+ #'Extension'{extnValue = KeyUses} ->
+ KeyUses
end.
+%% If no key-usage extension is defined all key-usages are allowed
+filter_keyuse_suites(_, [], CiphersSuites, _) ->
+ CiphersSuites;
filter_keyuse_suites(Use, KeyUse, CipherSuits, Suites) ->
case ssl_certificate:is_valid_key_usage(KeyUse, Use) of
true ->
diff --git a/lib/ssl/src/ssl_cipher.hrl b/lib/ssl/src/ssl_cipher.hrl
index 8e8f3d9c67..ba6a98b92a 100644
--- a/lib/ssl/src/ssl_cipher.hrl
+++ b/lib/ssl/src/ssl_cipher.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -399,6 +399,17 @@
%% TLS_RSA_PSK_WITH_AES_256_CBC_SHA = { 0x00, 0x95 };
-define(TLS_RSA_PSK_WITH_AES_256_CBC_SHA, <<?BYTE(16#00), ?BYTE(16#95)>>).
+%%% PSK NULL Cipher Suites RFC 4785
+
+%% TLS_PSK_WITH_NULL_SHA = { 0x00, 0x2C };
+-define(TLS_PSK_WITH_NULL_SHA, <<?BYTE(16#00), ?BYTE(16#2C)>>).
+
+%% TLS_DHE_PSK_WITH_NULL_SHA = { 0x00, 0x2D };
+-define(TLS_DHE_PSK_WITH_NULL_SHA, <<?BYTE(16#00), ?BYTE(16#2D)>>).
+
+%% TLS_RSA_PSK_WITH_NULL_SHA = { 0x00, 0x2E };
+-define(TLS_RSA_PSK_WITH_NULL_SHA, <<?BYTE(16#00), ?BYTE(16#2E)>>).
+
%%% TLS 1.2 PSK Cipher Suites RFC 5487
%% TLS_PSK_WITH_AES_128_GCM_SHA256 = {0x00,0xA8};
@@ -455,6 +466,46 @@
%% TLS_RSA_PSK_WITH_NULL_SHA384 = {0x00,0xB9};
-define(TLS_RSA_PSK_WITH_NULL_SHA384, <<?BYTE(16#00), ?BYTE(16#B9)>>).
+%%% ECDHE PSK Cipher Suites RFC 5489
+
+%% TLS_ECDHE_PSK_WITH_RC4_128_SHA = {0xC0,0x33};
+-define(TLS_ECDHE_PSK_WITH_RC4_128_SHA, <<?BYTE(16#C0), ?BYTE(16#33)>>).
+
+%% TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA = {0xC0,0x34};
+-define(TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, <<?BYTE(16#C0), ?BYTE(16#34)>>).
+
+%% TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA = {0xC0,0x35};
+-define(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, <<?BYTE(16#C0), ?BYTE(16#35)>>).
+
+%% TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA = {0xC0,0x36};
+-define(TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, <<?BYTE(16#C0), ?BYTE(16#36)>>).
+
+%% TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 = {0xC0,0x37};
+-define(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, <<?BYTE(16#C0), ?BYTE(16#37)>>).
+
+%% TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 = {0xC0,0x38};
+-define(TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, <<?BYTE(16#C0), ?BYTE(16#38)>>).
+
+%% TLS_ECDHE_PSK_WITH_NULL_SHA256 = {0xC0,0x3A};
+-define(TLS_ECDHE_PSK_WITH_NULL_SHA256, <<?BYTE(16#C0), ?BYTE(16#3A)>>).
+
+%% TLS_ECDHE_PSK_WITH_NULL_SHA384 = {0xC0,0x3B};
+-define(TLS_ECDHE_PSK_WITH_NULL_SHA384, <<?BYTE(16#C0), ?BYTE(16#3B)>>).
+
+%%% ECDHE_PSK with AES-GCM and AES-CCM Cipher Suites, draft-ietf-tls-ecdhe-psk-aead-05
+
+%% TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 = {0xTBD; 0xTBD} {0xD0,0x01};
+-define(TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256, <<?BYTE(16#D0), ?BYTE(16#01)>>).
+
+%% TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384 = {0xTBD; 0xTBD} {0xD0,0x02};
+-define(TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384, <<?BYTE(16#D0), ?BYTE(16#02)>>).
+
+%% TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256 = {0xTBD; 0xTBD} {0xD0,0x03};
+-define(TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256, <<?BYTE(16#D0), ?BYTE(16#03)>>).
+
+%% TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256 = {0xTBD; 0xTBD} {0xD0,0x05};
+-define(TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256, <<?BYTE(16#D0), ?BYTE(16#05)>>).
+
%%% SRP Cipher Suites RFC 5054
%% TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = { 0xC0,0x1A };
diff --git a/lib/ssl/src/ssl_cipher_format.erl b/lib/ssl/src/ssl_cipher_format.erl
new file mode 100644
index 0000000000..c311c0d097
--- /dev/null
+++ b/lib/ssl/src/ssl_cipher_format.erl
@@ -0,0 +1,1764 @@
+%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Convert between diffrent cipher suite representations
+%%
+%%----------------------------------------------------------------------
+-module(ssl_cipher_format).
+
+-include("ssl_cipher.hrl").
+-include("ssl_internal.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+-export_type([cipher_suite/0,
+ erl_cipher_suite/0, old_erl_cipher_suite/0, openssl_cipher_suite/0,
+ hash/0, key_algo/0, sign_algo/0]).
+
+-type cipher() :: null |rc4_128 | des_cbc | '3des_ede_cbc' | aes_128_cbc | aes_256_cbc | aes_128_gcm | aes_256_gcm | chacha20_poly1305.
+-type hash() :: null | md5 | sha | sha224 | sha256 | sha384 | sha512.
+-type sign_algo() :: rsa | dsa | ecdsa.
+-type key_algo() :: null | rsa | dhe_rsa | dhe_dss | ecdhe_ecdsa| ecdh_ecdsa | ecdh_rsa| srp_rsa| srp_dss | psk | dhe_psk | rsa_psk | dh_anon | ecdh_anon | srp_anon.
+-type erl_cipher_suite() :: #{key_exchange := key_algo(),
+ cipher := cipher(),
+ mac := hash() | aead,
+ prf := hash() | default_prf %% Old cipher suites, version dependent
+ }.
+-type old_erl_cipher_suite() :: {key_algo(), cipher(), hash()} % Pre TLS 1.2
+ %% TLS 1.2, internally PRE TLS 1.2 will use default_prf
+ | {key_algo(), cipher(), hash(), hash() | default_prf}.
+-type cipher_suite() :: binary().
+-type openssl_cipher_suite() :: string().
+
+
+-export([suite_to_str/1, suite_definition/1, suite/1, erl_suite_definition/1,
+ openssl_suite/1, openssl_suite_name/1]).
+
+%%--------------------------------------------------------------------
+-spec suite_to_str(erl_cipher_suite()) -> string().
+%%
+%% Description: Return the string representation of a cipher suite.
+%%--------------------------------------------------------------------
+suite_to_str(#{key_exchange := null,
+ cipher := null,
+ mac := null,
+ prf := null}) ->
+ "TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
+suite_to_str(#{key_exchange := Kex,
+ cipher := Cipher,
+ mac := aead,
+ prf := PRF}) ->
+ "TLS_" ++ string:to_upper(atom_to_list(Kex)) ++
+ "_WITH_" ++ string:to_upper(atom_to_list(Cipher)) ++
+ "_" ++ string:to_upper(atom_to_list(PRF));
+suite_to_str(#{key_exchange := Kex,
+ cipher := Cipher,
+ mac := Mac}) ->
+ "TLS_" ++ string:to_upper(atom_to_list(Kex)) ++
+ "_WITH_" ++ string:to_upper(atom_to_list(Cipher)) ++
+ "_" ++ string:to_upper(atom_to_list(Mac)).
+
+%%--------------------------------------------------------------------
+-spec suite_definition(cipher_suite()) -> erl_cipher_suite().
+%%
+%% Description: Return erlang cipher suite definition.
+%% Note: Currently not supported suites are commented away.
+%% They should be supported or removed in the future.
+%%-------------------------------------------------------------------
+%% TLS v1.1 suites
+suite_definition(?TLS_NULL_WITH_NULL_NULL) ->
+ #{key_exchange => null,
+ cipher => null,
+ mac => null,
+ prf => null};
+%% RFC 5746 - Not a real cipher suite used to signal empty "renegotiation_info" extension
+%% to avoid handshake failure from old servers that do not ignore
+%% hello extension data as they should.
+suite_definition(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV) ->
+ #{key_exchange => null,
+ cipher => null,
+ mac => null,
+ prf => null};
+suite_definition(?TLS_RSA_WITH_RC4_128_MD5) ->
+ #{key_exchange => rsa,
+ cipher => rc4_128,
+ mac => md5,
+ prf => default_prf};
+suite_definition(?TLS_RSA_WITH_RC4_128_SHA) ->
+ #{key_exchange => rsa,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_WITH_DES_CBC_SHA) ->
+ #{key_exchange => rsa,
+ cipher => des_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => rsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_DES_CBC_SHA) ->
+ #{key_exchange => dhe_dss,
+ cipher => des_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => dhe_dss,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_DES_CBC_SHA) ->
+ #{key_exchange => dhe_rsa,
+ cipher => des_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => dhe_rsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+%%% TSL V1.1 AES suites
+suite_definition(?TLS_RSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => dhe_dss,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => dhe_dss,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+%% TLS v1.2 suites
+%% suite_definition(?TLS_RSA_WITH_NULL_SHA) ->
+%% {rsa, null, sha, default_prf};
+suite_definition(?TLS_RSA_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => rsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_RSA_WITH_AES_256_CBC_SHA256) ->
+ #{key_exchange => rsa,
+ cipher => aes_256_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => dhe_dss,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) ->
+ #{key_exchange => dhe_dss,
+ cipher => aes_256_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) ->
+ #{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha256,
+ prf => default_prf};
+%% not defined YET:
+%% TLS_DH_DSS_WITH_AES_128_CBC_SHA256 DH_DSS AES_128_CBC SHA256
+%% TLS_DH_RSA_WITH_AES_128_CBC_SHA256 DH_RSA AES_128_CBC SHA256
+%% TLS_DH_DSS_WITH_AES_256_CBC_SHA256 DH_DSS AES_256_CBC SHA256
+%% TLS_DH_RSA_WITH_AES_256_CBC_SHA256 DH_RSA AES_256_CBC SHA256
+%%% DH-ANON deprecated by TLS spec and not available
+%%% by default, but good for testing purposes.
+suite_definition(?TLS_DH_anon_WITH_RC4_128_MD5) ->
+ #{key_exchange => dh_anon,
+ cipher => rc4_128,
+ mac => md5,
+ prf => default_prf};
+suite_definition(?TLS_DH_anon_WITH_DES_CBC_SHA) ->
+ #{key_exchange => dh_anon,
+ cipher => des_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => dh_anon,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DH_anon_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => dh_anon,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DH_anon_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => dh_anon,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DH_anon_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => dh_anon,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DH_anon_WITH_AES_256_CBC_SHA256) ->
+ #{key_exchange => dh_anon,
+ cipher => aes_256_cbc,
+ mac => sha256,
+ prf => default_prf};
+%%% PSK Cipher Suites RFC 4279
+suite_definition(?TLS_PSK_WITH_RC4_128_SHA) ->
+ #{key_exchange => psk,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_PSK_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => psk,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_PSK_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => psk,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_PSK_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => psk,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_RC4_128_SHA) ->
+ #{key_exchange => dhe_psk,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => dhe_psk,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_RC4_128_SHA) ->
+ #{key_exchange => rsa_psk,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => rsa_psk,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => rsa_psk,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => rsa_psk,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+%%% PSK NULL Cipher Suites RFC 4785
+suite_definition(?TLS_PSK_WITH_NULL_SHA) ->
+ #{key_exchange => psk,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA) ->
+ #{key_exchange => dhe_psk,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA) ->
+ #{key_exchange => rsa_psk,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+%%% TLS 1.2 PSK Cipher Suites RFC 5487
+suite_definition(?TLS_PSK_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => psk,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_PSK_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => psk,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_DHE_PSK_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_RSA_PSK_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => rsa_psk,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => rsa_psk,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_PSK_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => psk,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_PSK_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => psk,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => rsa_psk,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => rsa_psk,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => default_prf};
+suite_definition(?TLS_PSK_WITH_NULL_SHA256) ->
+ #{key_exchange => psk,
+ cipher => null,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_PSK_WITH_NULL_SHA384) ->
+ #{key_exchange => psk,
+ cipher => null,
+ mac => sha384,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA256) ->
+ #{key_exchange => dhe_psk,
+ cipher => null,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA384) ->
+ #{key_exchange => dhe_psk,
+ cipher => null,
+ mac => sha384,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA256) ->
+ #{key_exchange => rsa_psk,
+ cipher => null,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA384) ->
+ #{key_exchange => rsa_psk,
+ cipher => null,
+ mac => sha384,
+ prf => default_prf};
+%%% ECDHE PSK Cipher Suites RFC 5489
+suite_definition(?TLS_ECDHE_PSK_WITH_RC4_128_SHA) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_NULL_SHA256) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => null,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_NULL_SHA384) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => null, mac => sha384,
+ prf => default_prf};
+%%% ECDHE_PSK with AES-GCM and AES-CCM Cipher Suites, draft-ietf-tls-ecdhe-psk-aead-05
+suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_128_gcm,
+ mac => null,
+ prf => sha256};
+suite_definition(?TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_256_gcm,
+ mac => null,
+ prf => sha384};
+%% suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256) ->
+%% #{key_exchange => ecdhe_psk,
+%% cipher => aes_128_ccm,
+%% mac => null,
+%% prf =>sha256};
+%% suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256) ->
+%% #{key_exchange => ecdhe_psk,
+%% cipher => aes_256_ccm,
+%% mac => null,
+%% prf => sha256};
+%%% SRP Cipher Suites RFC 5054
+suite_definition(?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => srp_anon,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => srp_rsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => srp_dss,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => srp_anon,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => srp_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => srp_dss,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => srp_anon,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => srp_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => srp_dss,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+%% RFC 4492 EC TLS suites
+suite_definition(?TLS_ECDH_ECDSA_WITH_NULL_SHA) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_ECDSA_WITH_RC4_128_SHA) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_NULL_SHA) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_RSA_WITH_NULL_SHA) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_RSA_WITH_RC4_128_SHA) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_RSA_WITH_NULL_SHA) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_RSA_WITH_RC4_128_SHA) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_anon_WITH_NULL_SHA) ->
+ #{key_exchange => ecdh_anon,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_anon_WITH_RC4_128_SHA) ->
+ #{key_exchange => ecdh_anon,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => ecdh_anon,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_anon_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => ecdh_anon,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_anon_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => ecdh_anon,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+%% RFC 5289 EC TLS suites
+suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => sha256};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => sha384};
+suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => sha256};
+suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => sha384};
+suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => sha256};
+suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => sha384};
+suite_definition(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => sha256};
+suite_definition(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => sha384};
+%% RFC 5288 AES-GCM Cipher Suites
+suite_definition(?TLS_RSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => rsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_RSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => rsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => dhe_rsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => dhe_rsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_DH_RSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => dh_rsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_DH_RSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => dh_rsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => dhe_dss,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => dhe_dss,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_DH_DSS_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => dh_dss,
+ cipher => aes_128_gcm,
+ mac => null,
+ prf => sha256};
+suite_definition(?TLS_DH_DSS_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => dh_dss,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_DH_anon_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => dh_anon,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_DH_anon_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => dh_anon,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+%% RFC 5289 ECC AES-GCM Cipher Suites
+suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+%% draft-agl-tls-chacha20poly1305-04 Chacha20/Poly1305 Suites
+suite_definition(?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => chacha20_poly1305,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => chacha20_poly1305,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256) ->
+ #{key_exchange => dhe_rsa,
+ cipher => chacha20_poly1305,
+ mac => aead,
+ prf => sha256}.
+
+%%--------------------------------------------------------------------
+-spec erl_suite_definition(cipher_suite() | erl_cipher_suite()) -> old_erl_cipher_suite().
+%%
+%% Description: Return erlang cipher suite definition. Filters last value
+%% for now (compatibility reasons).
+%%--------------------------------------------------------------------
+erl_suite_definition(Bin) when is_binary(Bin) ->
+ erl_suite_definition(suite_definition(Bin));
+erl_suite_definition(#{key_exchange := KeyExchange, cipher := Cipher,
+ mac := Hash, prf := Prf}) ->
+ case Prf of
+ default_prf ->
+ {KeyExchange, Cipher, Hash};
+ _ ->
+ {KeyExchange, Cipher, Hash, Prf}
+ end.
+
+%%--------------------------------------------------------------------
+-spec suite(erl_cipher_suite()) -> cipher_suite().
+%%
+%% Description: Return TLS cipher suite definition.
+%%--------------------------------------------------------------------
+%% TLS v1.1 suites
+suite(#{key_exchange := rsa,
+ cipher := rc4_128,
+ mac := md5}) ->
+ ?TLS_RSA_WITH_RC4_128_MD5;
+suite(#{key_exchange := rsa,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_RSA_WITH_RC4_128_SHA;
+suite(#{key_exchange := rsa,
+ cipher := des_cbc,
+ mac := sha}) ->
+ ?TLS_RSA_WITH_DES_CBC_SHA;
+suite(#{key_exchange := rsa,
+ cipher :='3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_RSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := dhe_dss,
+ cipher:= des_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_DSS_WITH_DES_CBC_SHA;
+suite(#{key_exchange := dhe_dss,
+ cipher:= '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := dhe_rsa,
+ cipher:= des_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_RSA_WITH_DES_CBC_SHA;
+suite(#{key_exchange := dhe_rsa,
+ cipher:= '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := dh_anon,
+ cipher:= rc4_128,
+ mac := md5}) ->
+ ?TLS_DH_anon_WITH_RC4_128_MD5;
+suite(#{key_exchange := dh_anon,
+ cipher:= des_cbc,
+ mac := sha}) ->
+ ?TLS_DH_anon_WITH_DES_CBC_SHA;
+suite(#{key_exchange := dh_anon,
+ cipher:= '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA;
+%%% TSL V1.1 AES suites
+suite(#{key_exchange := rsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_RSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := dhe_dss,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := dhe_rsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := dh_anon,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_DH_anon_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := rsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_RSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := dhe_dss,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := dhe_rsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := dh_anon,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_DH_anon_WITH_AES_256_CBC_SHA;
+%% TLS v1.2 suites
+suite(#{key_exchange := rsa,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_RSA_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := rsa,
+ cipher := aes_256_cbc,
+ mac := sha256}) ->
+ ?TLS_RSA_WITH_AES_256_CBC_SHA256;
+suite(#{key_exchange := dhe_dss,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := dhe_rsa,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := dhe_dss,
+ cipher := aes_256_cbc,
+ mac := sha256}) ->
+ ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256;
+suite(#{key_exchange := dhe_rsa,
+ cipher := aes_256_cbc,
+ mac := sha256}) ->
+ ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
+suite(#{key_exchange := dh_anon,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_DH_anon_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := dh_anon,
+ cipher := aes_256_cbc,
+ mac := sha256}) ->
+ ?TLS_DH_anon_WITH_AES_256_CBC_SHA256;
+%%% PSK Cipher Suites RFC 4279
+suite(#{key_exchange := psk,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_PSK_WITH_RC4_128_SHA;
+suite(#{key_exchange := psk,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_PSK_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := psk,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_PSK_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := psk,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_PSK_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := dhe_psk,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_DHE_PSK_WITH_RC4_128_SHA;
+suite(#{key_exchange := dhe_psk,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := dhe_psk,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_PSK_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := dhe_psk,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_PSK_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := rsa_psk,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_RSA_PSK_WITH_RC4_128_SHA;
+suite(#{key_exchange := rsa_psk,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := rsa_psk,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_RSA_PSK_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := rsa_psk,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_RSA_PSK_WITH_AES_256_CBC_SHA;
+%%% PSK NULL Cipher Suites RFC 4785
+suite(#{key_exchange := psk,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_PSK_WITH_NULL_SHA;
+suite(#{key_exchange := dhe_psk,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_DHE_PSK_WITH_NULL_SHA;
+suite(#{key_exchange := rsa_psk,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_RSA_PSK_WITH_NULL_SHA;
+%%% TLS 1.2 PSK Cipher Suites RFC 5487
+suite(#{key_exchange := psk,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_PSK_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := psk,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_PSK_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := dhe_psk,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DHE_PSK_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := dhe_psk,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := rsa_psk,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_RSA_PSK_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := rsa_psk,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := psk,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_PSK_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := psk,
+ cipher := aes_256_cbc,
+ mac := sha384}) ->
+ ?TLS_PSK_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := dhe_psk,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_DHE_PSK_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := dhe_psk,
+ cipher := aes_256_cbc,
+ mac := sha384}) ->
+ ?TLS_DHE_PSK_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := rsa_psk,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_RSA_PSK_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := rsa_psk,
+ cipher := aes_256_cbc,
+ mac := sha384}) ->
+ ?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := psk,
+ cipher := null,
+ mac := sha256}) ->
+ ?TLS_PSK_WITH_NULL_SHA256;
+suite(#{key_exchange := psk,
+ cipher := null,
+ mac := sha384}) ->
+ ?TLS_PSK_WITH_NULL_SHA384;
+suite(#{key_exchange := dhe_psk,
+ cipher := null,
+ mac := sha256}) ->
+ ?TLS_DHE_PSK_WITH_NULL_SHA256;
+suite(#{key_exchange := dhe_psk,
+ cipher := null,
+ mac := sha384}) ->
+ ?TLS_DHE_PSK_WITH_NULL_SHA384;
+suite(#{key_exchange := rsa_psk,
+ cipher := null,
+ mac := sha256}) ->
+ ?TLS_RSA_PSK_WITH_NULL_SHA256;
+suite(#{key_exchange := rsa_psk,
+ cipher := null,
+ mac := sha384}) ->
+ ?TLS_RSA_PSK_WITH_NULL_SHA384;
+%%% ECDHE PSK Cipher Suites RFC 5489
+suite(#{key_exchange := ecdhe_psk,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_ECDHE_PSK_WITH_RC4_128_SHA;
+suite(#{key_exchange := ecdhe_psk,
+ cipher :='3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := aes_256_cbc,
+ mac := sha384}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := null,
+ mac := sha256}) ->
+ ?TLS_ECDHE_PSK_WITH_NULL_SHA256;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := null,
+ mac := sha384}) ->
+ ?TLS_ECDHE_PSK_WITH_NULL_SHA384;
+%%% ECDHE_PSK with AES-GCM and AES-CCM Cipher Suites, draft-ietf-tls-ecdhe-psk-aead-05
+suite(#{key_exchange := ecdhe_psk,
+ cipher := aes_128_gcm,
+ mac := null,
+ prf := sha256}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := aes_256_gcm,
+ mac := null,
+ prf := sha384}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384;
+ %% suite(#{key_exchange := ecdhe_psk,
+ %% cipher := aes_128_ccm,
+ %% mac := null,
+ %% prf := sha256}) ->
+ %% ?TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256;
+ %% suite(#{key_exchange := ecdhe_psk,
+ %% cipher := aes_256_ccm,
+ %% mac := null,
+ %% prf := sha256}) ->
+ %% ?TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256;
+%%% SRP Cipher Suites RFC 5054
+suite(#{key_exchange := srp_anon,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := srp_rsa,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := srp_dss,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := srp_anon,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_SRP_SHA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := srp_rsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := srp_dss,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := srp_anon,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_SRP_SHA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := srp_rsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := srp_dss,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA;
+%%% RFC 4492 EC TLS suites
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_ECDH_ECDSA_WITH_NULL_SHA;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_ECDHE_ECDSA_WITH_NULL_SHA;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_ECDH_RSA_WITH_NULL_SHA;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_ECDH_RSA_WITH_RC4_128_SHA;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := '3des_ede_cbc', mac := sha}) ->
+ ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_ECDHE_RSA_WITH_NULL_SHA;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_ECDHE_RSA_WITH_RC4_128_SHA;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := ecdh_anon,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_ECDH_anon_WITH_NULL_SHA;
+suite(#{key_exchange := ecdh_anon,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_ECDH_anon_WITH_RC4_128_SHA;
+suite(#{key_exchange := ecdh_anon,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := ecdh_anon,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := ecdh_anon,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_ECDH_anon_WITH_AES_256_CBC_SHA;
+%%% RFC 5289 EC TLS suites
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := aes_128_cbc,
+ mac:= sha256,
+ prf := sha256}) ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := aes_256_cbc,
+ mac := sha384,
+ prf := sha384}) ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := aes_128_cbc,
+ mac := sha256,
+ prf := sha256}) ->
+ ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := aes_256_cbc,
+ mac := sha384,
+ prf := sha384}) ->
+ ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := aes_128_cbc,
+ mac := sha256,
+ prf := sha256}) ->
+ ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := aes_256_cbc,
+ mac := sha384,
+ prf := sha384}) ->
+ ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := aes_128_cbc,
+ mac := sha256,
+ prf := sha256}) ->
+ ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := aes_256_cbc,
+ mac := sha384,
+ prf := sha384}) ->
+ ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384;
+%% RFC 5288 AES-GCM Cipher Suites
+suite(#{key_exchange := rsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_RSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := rsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_RSA_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := dhe_rsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := dhe_rsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := dh_rsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DH_RSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := dh_rsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_DH_RSA_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := dhe_dss,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := dhe_dss,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := dh_dss,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DH_DSS_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := dh_dss,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_DH_DSS_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := dh_anon,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DH_anon_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := dh_anon,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_DH_anon_WITH_AES_256_GCM_SHA384;
+%% RFC 5289 ECC AES-GCM Cipher Suites
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384;
+%% draft-agl-tls-chacha20poly1305-04 Chacha20/Poly1305 Suites
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := chacha20_poly1305,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := chacha20_poly1305,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256;
+suite(#{key_exchange := dhe_rsa,
+ cipher := chacha20_poly1305,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256.
+
+%%--------------------------------------------------------------------
+-spec openssl_suite(openssl_cipher_suite()) -> cipher_suite().
+%%
+%% Description: Return TLS cipher suite definition.
+%%--------------------------------------------------------------------
+%% translate constants <-> openssl-strings
+openssl_suite("DHE-RSA-AES256-SHA256") ->
+ ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
+openssl_suite("DHE-DSS-AES256-SHA256") ->
+ ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256;
+openssl_suite("AES256-SHA256") ->
+ ?TLS_RSA_WITH_AES_256_CBC_SHA256;
+openssl_suite("DHE-RSA-AES128-SHA256") ->
+ ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("DHE-DSS-AES128-SHA256") ->
+ ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256;
+openssl_suite("AES128-SHA256") ->
+ ?TLS_RSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("DHE-RSA-AES256-SHA") ->
+ ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+openssl_suite("DHE-DSS-AES256-SHA") ->
+ ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
+openssl_suite("AES256-SHA") ->
+ ?TLS_RSA_WITH_AES_256_CBC_SHA;
+openssl_suite("EDH-RSA-DES-CBC3-SHA") ->
+ ?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("EDH-DSS-DES-CBC3-SHA") ->
+ ?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("DES-CBC3-SHA") ->
+ ?TLS_RSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("DHE-RSA-AES128-SHA") ->
+ ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
+openssl_suite("DHE-DSS-AES128-SHA") ->
+ ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
+openssl_suite("AES128-SHA") ->
+ ?TLS_RSA_WITH_AES_128_CBC_SHA;
+openssl_suite("RC4-SHA") ->
+ ?TLS_RSA_WITH_RC4_128_SHA;
+openssl_suite("RC4-MD5") ->
+ ?TLS_RSA_WITH_RC4_128_MD5;
+openssl_suite("EDH-RSA-DES-CBC-SHA") ->
+ ?TLS_DHE_RSA_WITH_DES_CBC_SHA;
+openssl_suite("DES-CBC-SHA") ->
+ ?TLS_RSA_WITH_DES_CBC_SHA;
+
+%%% SRP Cipher Suites RFC 5054
+
+openssl_suite("SRP-DSS-AES-256-CBC-SHA") ->
+ ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA;
+openssl_suite("SRP-RSA-AES-256-CBC-SHA") ->
+ ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
+openssl_suite("SRP-DSS-3DES-EDE-CBC-SHA") ->
+ ?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("SRP-RSA-3DES-EDE-CBC-SHA") ->
+ ?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("SRP-DSS-AES-128-CBC-SHA") ->
+ ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
+openssl_suite("SRP-RSA-AES-128-CBC-SHA") ->
+ ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA;
+
+%% RFC 4492 EC TLS suites
+openssl_suite("ECDH-ECDSA-RC4-SHA") ->
+ ?TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
+openssl_suite("ECDH-ECDSA-DES-CBC3-SHA") ->
+ ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("ECDH-ECDSA-AES128-SHA") ->
+ ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
+openssl_suite("ECDH-ECDSA-AES256-SHA") ->
+ ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
+
+openssl_suite("ECDHE-ECDSA-RC4-SHA") ->
+ ?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
+openssl_suite("ECDHE-ECDSA-DES-CBC3-SHA") ->
+ ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("ECDHE-ECDSA-AES128-SHA") ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
+openssl_suite("ECDHE-ECDSA-AES256-SHA") ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
+
+openssl_suite("ECDHE-RSA-RC4-SHA") ->
+ ?TLS_ECDHE_RSA_WITH_RC4_128_SHA;
+openssl_suite("ECDHE-RSA-DES-CBC3-SHA") ->
+ ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("ECDHE-RSA-AES128-SHA") ->
+ ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
+openssl_suite("ECDHE-RSA-AES256-SHA") ->
+ ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
+
+openssl_suite("ECDH-RSA-RC4-SHA") ->
+ ?TLS_ECDH_RSA_WITH_RC4_128_SHA;
+openssl_suite("ECDH-RSA-DES-CBC3-SHA") ->
+ ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("ECDH-RSA-AES128-SHA") ->
+ ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
+openssl_suite("ECDH-RSA-AES256-SHA") ->
+ ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
+
+%% RFC 5289 EC TLS suites
+openssl_suite("ECDHE-ECDSA-AES128-SHA256") ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("ECDHE-ECDSA-AES256-SHA384") ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
+openssl_suite("ECDH-ECDSA-AES128-SHA256") ->
+ ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("ECDH-ECDSA-AES256-SHA384") ->
+ ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
+openssl_suite("ECDHE-RSA-AES128-SHA256") ->
+ ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("ECDHE-RSA-AES256-SHA384") ->
+ ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
+openssl_suite("ECDH-RSA-AES128-SHA256") ->
+ ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("ECDH-RSA-AES256-SHA384") ->
+ ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384;
+
+%% RFC 5288 AES-GCM Cipher Suites
+openssl_suite("AES128-GCM-SHA256") ->
+ ?TLS_RSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("AES256-GCM-SHA384") ->
+ ?TLS_RSA_WITH_AES_256_GCM_SHA384;
+openssl_suite("DHE-RSA-AES128-GCM-SHA256") ->
+ ?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("DHE-RSA-AES256-GCM-SHA384") ->
+ ?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
+openssl_suite("DH-RSA-AES128-GCM-SHA256") ->
+ ?TLS_DH_RSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("DH-RSA-AES256-GCM-SHA384") ->
+ ?TLS_DH_RSA_WITH_AES_256_GCM_SHA384;
+openssl_suite("DHE-DSS-AES128-GCM-SHA256") ->
+ ?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256;
+openssl_suite("DHE-DSS-AES256-GCM-SHA384") ->
+ ?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384;
+openssl_suite("DH-DSS-AES128-GCM-SHA256") ->
+ ?TLS_DH_DSS_WITH_AES_128_GCM_SHA256;
+openssl_suite("DH-DSS-AES256-GCM-SHA384") ->
+ ?TLS_DH_DSS_WITH_AES_256_GCM_SHA384;
+
+%% RFC 5289 ECC AES-GCM Cipher Suites
+openssl_suite("ECDHE-ECDSA-AES128-GCM-SHA256") ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("ECDHE-ECDSA-AES256-GCM-SHA384") ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
+openssl_suite("ECDH-ECDSA-AES128-GCM-SHA256") ->
+ ?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("ECDH-ECDSA-AES256-GCM-SHA384") ->
+ ?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
+openssl_suite("ECDHE-RSA-AES128-GCM-SHA256") ->
+ ?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("ECDHE-RSA-AES256-GCM-SHA384") ->
+ ?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
+openssl_suite("ECDH-RSA-AES128-GCM-SHA256") ->
+ ?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("ECDH-RSA-AES256-GCM-SHA384") ->
+ ?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384.
+
+%%--------------------------------------------------------------------
+-spec openssl_suite_name(cipher_suite()) -> openssl_cipher_suite() | erl_cipher_suite().
+%%
+%% Description: Return openssl cipher suite name if possible
+%%-------------------------------------------------------------------
+openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA) ->
+ "DHE-RSA-AES256-SHA";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA) ->
+ "DHE-DSS-AES256-SHA";
+openssl_suite_name(?TLS_RSA_WITH_AES_256_CBC_SHA) ->
+ "AES256-SHA";
+openssl_suite_name(?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ "EDH-RSA-DES-CBC3-SHA";
+openssl_suite_name(?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) ->
+ "EDH-DSS-DES-CBC3-SHA";
+openssl_suite_name(?TLS_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ "DES-CBC3-SHA";
+openssl_suite_name( ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA) ->
+ "DHE-RSA-AES128-SHA";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA) ->
+ "DHE-DSS-AES128-SHA";
+openssl_suite_name(?TLS_RSA_WITH_AES_128_CBC_SHA) ->
+ "AES128-SHA";
+openssl_suite_name(?TLS_RSA_WITH_RC4_128_SHA) ->
+ "RC4-SHA";
+openssl_suite_name(?TLS_RSA_WITH_RC4_128_MD5) ->
+ "RC4-MD5";
+openssl_suite_name(?TLS_DHE_RSA_WITH_DES_CBC_SHA) ->
+ "EDH-RSA-DES-CBC-SHA";
+openssl_suite_name(?TLS_RSA_WITH_DES_CBC_SHA) ->
+ "DES-CBC-SHA";
+openssl_suite_name(?TLS_RSA_WITH_NULL_SHA256) ->
+ "NULL-SHA256";
+openssl_suite_name(?TLS_RSA_WITH_AES_128_CBC_SHA256) ->
+ "AES128-SHA256";
+openssl_suite_name(?TLS_RSA_WITH_AES_256_CBC_SHA256) ->
+ "AES256-SHA256";
+openssl_suite_name(?TLS_DH_DSS_WITH_AES_128_CBC_SHA256) ->
+ "DH-DSS-AES128-SHA256";
+openssl_suite_name(?TLS_DH_RSA_WITH_AES_128_CBC_SHA256) ->
+ "DH-RSA-AES128-SHA256";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) ->
+ "DHE-DSS-AES128-SHA256";
+openssl_suite_name(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) ->
+ "DHE-RSA-AES128-SHA256";
+openssl_suite_name(?TLS_DH_DSS_WITH_AES_256_CBC_SHA256) ->
+ "DH-DSS-AES256-SHA256";
+openssl_suite_name(?TLS_DH_RSA_WITH_AES_256_CBC_SHA256) ->
+ "DH-RSA-AES256-SHA256";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) ->
+ "DHE-DSS-AES256-SHA256";
+openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) ->
+ "DHE-RSA-AES256-SHA256";
+
+%%% PSK Cipher Suites RFC 4279
+
+openssl_suite_name(?TLS_PSK_WITH_AES_256_CBC_SHA) ->
+ "PSK-AES256-CBC-SHA";
+openssl_suite_name(?TLS_PSK_WITH_3DES_EDE_CBC_SHA) ->
+ "PSK-3DES-EDE-CBC-SHA";
+openssl_suite_name(?TLS_PSK_WITH_AES_128_CBC_SHA) ->
+ "PSK-AES128-CBC-SHA";
+openssl_suite_name(?TLS_PSK_WITH_RC4_128_SHA) ->
+ "PSK-RC4-SHA";
+
+%%% SRP Cipher Suites RFC 5054
+
+openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ "SRP-RSA-3DES-EDE-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) ->
+ "SRP-DSS-3DES-EDE-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) ->
+ "SRP-RSA-AES-128-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA) ->
+ "SRP-DSS-AES-128-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) ->
+ "SRP-RSA-AES-256-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) ->
+ "SRP-DSS-AES-256-CBC-SHA";
+
+%% RFC 4492 EC TLS suites
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_RC4_128_SHA) ->
+ "ECDH-ECDSA-RC4-SHA";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
+ "ECDH-ECDSA-DES-CBC3-SHA";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) ->
+ "ECDH-ECDSA-AES128-SHA";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) ->
+ "ECDH-ECDSA-AES256-SHA";
+
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) ->
+ "ECDHE-ECDSA-RC4-SHA";
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
+ "ECDHE-ECDSA-DES-CBC3-SHA";
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) ->
+ "ECDHE-ECDSA-AES128-SHA";
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) ->
+ "ECDHE-ECDSA-AES256-SHA";
+
+openssl_suite_name(?TLS_ECDH_RSA_WITH_RC4_128_SHA) ->
+ "ECDH-RSA-RC4-SHA";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ "ECDH-RSA-DES-CBC3-SHA";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) ->
+ "ECDH-RSA-AES128-SHA";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) ->
+ "ECDH-RSA-AES256-SHA";
+
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_RC4_128_SHA) ->
+ "ECDHE-RSA-RC4-SHA";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ "ECDHE-RSA-DES-CBC3-SHA";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) ->
+ "ECDHE-RSA-AES128-SHA";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) ->
+ "ECDHE-RSA-AES256-SHA";
+
+%% RFC 5289 EC TLS suites
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) ->
+ "ECDHE-ECDSA-AES128-SHA256";
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) ->
+ "ECDHE-ECDSA-AES256-SHA384";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) ->
+ "ECDH-ECDSA-AES128-SHA256";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) ->
+ "ECDH-ECDSA-AES256-SHA384";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) ->
+ "ECDHE-RSA-AES128-SHA256";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) ->
+ "ECDHE-RSA-AES256-SHA384";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) ->
+ "ECDH-RSA-AES128-SHA256";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) ->
+ "ECDH-RSA-AES256-SHA384";
+
+%% RFC 5288 AES-GCM Cipher Suites
+openssl_suite_name(?TLS_RSA_WITH_AES_128_GCM_SHA256) ->
+ "AES128-GCM-SHA256";
+openssl_suite_name(?TLS_RSA_WITH_AES_256_GCM_SHA384) ->
+ "AES256-GCM-SHA384";
+openssl_suite_name(?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) ->
+ "DHE-RSA-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) ->
+ "DHE-RSA-AES256-GCM-SHA384";
+openssl_suite_name(?TLS_DH_RSA_WITH_AES_128_GCM_SHA256) ->
+ "DH-RSA-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_DH_RSA_WITH_AES_256_GCM_SHA384) ->
+ "DH-RSA-AES256-GCM-SHA384";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256) ->
+ "DHE-DSS-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384) ->
+ "DHE-DSS-AES256-GCM-SHA384";
+openssl_suite_name(?TLS_DH_DSS_WITH_AES_128_GCM_SHA256) ->
+ "DH-DSS-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_DH_DSS_WITH_AES_256_GCM_SHA384) ->
+ "DH-DSS-AES256-GCM-SHA384";
+
+%% RFC 5289 ECC AES-GCM Cipher Suites
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) ->
+ "ECDHE-ECDSA-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) ->
+ "ECDHE-ECDSA-AES256-GCM-SHA384";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256) ->
+ "ECDH-ECDSA-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384) ->
+ "ECDH-ECDSA-AES256-GCM-SHA384";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) ->
+ "ECDHE-RSA-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) ->
+ "ECDHE-RSA-AES256-GCM-SHA384";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) ->
+ "ECDH-RSA-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) ->
+ "ECDH-RSA-AES256-GCM-SHA384";
+
+%% No oppenssl name
+openssl_suite_name(Cipher) ->
+ suite_definition(Cipher).
diff --git a/lib/ssl/src/ssl_config.erl b/lib/ssl/src/ssl_config.erl
index e4611995ec..1e6dab9276 100644
--- a/lib/ssl/src/ssl_config.erl
+++ b/lib/ssl/src/ssl_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -91,7 +91,15 @@ init_certificates(undefined, #{pem_cache := PemCache} = Config, CertFile, server
end;
init_certificates(Cert, Config, _, _) ->
{ok, Config#{own_certificate => Cert}}.
-
+init_private_key(_, #{algorithm := Alg} = Key, _, _Password, _Client) when Alg == ecdsa;
+ Alg == rsa;
+ Alg == dss ->
+ case maps:is_key(engine, Key) andalso maps:is_key(key_id, Key) of
+ true ->
+ Key;
+ false ->
+ throw({key, {invalid_key_id, Key}})
+ end;
init_private_key(_, undefined, <<>>, _Password, _Client) ->
undefined;
init_private_key(DbHandle, undefined, KeyFile, Password, _) ->
@@ -124,7 +132,13 @@ private_key(#'PrivateKeyInfo'{privateKeyAlgorithm =
#'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?'id-dsa'},
privateKey = Key}) ->
public_key:der_decode('DSAPrivateKey', iolist_to_binary(Key));
-
+private_key(#'PrivateKeyInfo'{privateKeyAlgorithm =
+ #'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?'id-ecPublicKey',
+ parameters = {asn1_OPENTYPE, Parameters}},
+ privateKey = Key}) ->
+ ECKey = public_key:der_decode('ECPrivateKey', iolist_to_binary(Key)),
+ ECParameters = public_key:der_decode('EcpkParameters', Parameters),
+ ECKey#'ECPrivateKey'{parameters = ECParameters};
private_key(Key) ->
Key.
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index fb87662c7b..9f876add6c 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -37,38 +37,44 @@
-include_lib("public_key/include/public_key.hrl").
%% Setup
--export([connect/8, ssl_accept/7, handshake/2, handshake/3,
+
+-export([connect/8, handshake/7, handshake/2, handshake/3,
+ handshake_continue/3, handshake_cancel/1,
socket_control/4, socket_control/5, start_or_recv_cancel_timer/2]).
%% User Events
-export([send/2, recv/3, close/2, shutdown/2,
new_user/2, get_opts/2, set_opts/2,
peer_certificate/1, renegotiation/1, negotiated_protocol/1, prf/5,
- connection_information/2, handle_common_event/5
+ connection_information/2
+ ]).
+
+%% Alert and close handling
+-export([handle_own_alert/4, handle_alert/3,
+ handle_normal_shutdown/3, stop/2, stop_and_reply/3
]).
+%% Data handling
+-export([read_application_data/2, internal_renegotiation/2]).
+
+%% Help functions for tls|dtls_connection.erl
+-export([handle_session/7, ssl_config/3,
+ prepare_connection/2, hibernate_after/3, map_extensions/1]).
+
%% General gen_statem state functions with extra callback argument
%% to determine if it is an SSL/TLS or DTLS gen_statem machine
--export([init/4, hello/4, abbreviated/4, certify/4, cipher/4, connection/4, downgrade/4]).
+-export([init/4, error/4, hello/4, user_hello/4, abbreviated/4, certify/4, cipher/4,
+ connection/4, downgrade/4]).
%% gen_statem callbacks
-export([terminate/3, format_status/2]).
-%%
--export([handle_info/3, handle_call/5, handle_session/7, ssl_config/3,
- prepare_connection/2, hibernate_after/3]).
-
-%% Alert and close handling
--export([handle_own_alert/4,handle_alert/3,
- handle_normal_shutdown/3
- ]).
-
-%% Data handling
--export([write_application_data/3, read_application_data/2]).
+%% Erlang Distribution export
+-export([get_sslsocket/1, dist_handshake_complete/2]).
%%====================================================================
-%% Internal application API
-%%====================================================================
+%% Setup
+%%====================================================================
%%--------------------------------------------------------------------
-spec connect(tls_connection | dtls_connection,
host(), inet:port_number(),
@@ -89,7 +95,7 @@ connect(Connection, Host, Port, Socket, Options, User, CbInfo, Timeout) ->
{error, ssl_not_started}
end.
%%--------------------------------------------------------------------
--spec ssl_accept(tls_connection | dtls_connection,
+-spec handshake(tls_connection | dtls_connection,
inet:port_number(), port(),
{#ssl_options{}, #socket_options{}, undefined | pid()},
pid(), tuple(), timeout()) ->
@@ -98,7 +104,7 @@ connect(Connection, Host, Port, Socket, Options, User, CbInfo, Timeout) ->
%% Description: Performs accept on an ssl listen socket. e.i. performs
%% ssl handshake.
%%--------------------------------------------------------------------
-ssl_accept(Connection, Port, Socket, Opts, User, CbInfo, Timeout) ->
+handshake(Connection, Port, Socket, Opts, User, CbInfo, Timeout) ->
try Connection:start_fsm(server, "localhost", Port, Socket, Opts, User,
CbInfo, Timeout)
catch
@@ -107,34 +113,62 @@ ssl_accept(Connection, Port, Socket, Opts, User, CbInfo, Timeout) ->
end.
%%--------------------------------------------------------------------
--spec handshake(#sslsocket{}, timeout()) -> ok | {error, reason()}.
+-spec handshake(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} |
+ {ok, #sslsocket{}, map()}| {error, reason()}.
%%
%% Description: Starts ssl handshake.
%%--------------------------------------------------------------------
-handshake(#sslsocket{pid = Pid}, Timeout) ->
+handshake(#sslsocket{pid = [Pid|_]} = Socket, Timeout) ->
case call(Pid, {start, Timeout}) of
connected ->
- ok;
+ {ok, Socket};
+ {ok, Ext} ->
+ {ok, Socket, Ext};
Error ->
Error
end.
%%--------------------------------------------------------------------
-spec handshake(#sslsocket{}, {#ssl_options{},#socket_options{}},
- timeout()) -> ok | {error, reason()}.
+ timeout()) -> {ok, #sslsocket{}} | {error, reason()}.
%%
%% Description: Starts ssl handshake with some new options
%%--------------------------------------------------------------------
-handshake(#sslsocket{pid = Pid}, SslOptions, Timeout) ->
+handshake(#sslsocket{pid = [Pid|_]} = Socket, SslOptions, Timeout) ->
case call(Pid, {start, SslOptions, Timeout}) of
connected ->
- ok;
+ {ok, Socket};
Error ->
Error
end.
+%%--------------------------------------------------------------------
+-spec handshake_continue(#sslsocket{}, [ssl_option()],
+ timeout()) -> {ok, #sslsocket{}}| {error, reason()}.
+%%
+%% Description: Continues handshake with new options
+%%--------------------------------------------------------------------
+handshake_continue(#sslsocket{pid = [Pid|_]} = Socket, SslOptions, Timeout) ->
+ case call(Pid, {handshake_continue, SslOptions, Timeout}) of
+ connected ->
+ {ok, Socket};
+ Error ->
+ Error
+ end.
+%%--------------------------------------------------------------------
+-spec handshake_cancel(#sslsocket{}) -> ok | {error, reason()}.
+%%
+%% Description: Cancels connection
+%%--------------------------------------------------------------------
+handshake_cancel(#sslsocket{pid = [Pid|_]}) ->
+ case call(Pid, cancel) of
+ closed ->
+ ok;
+ Error ->
+ Error
+ end.
%--------------------------------------------------------------------
--spec socket_control(tls_connection | dtls_connection, port(), pid(), atom()) ->
+-spec socket_control(tls_connection | dtls_connection, port(), [pid()], atom()) ->
{ok, #sslsocket{}} | {error, reason()}.
%%
%% Description: Set the ssl process to own the accept socket
@@ -143,27 +177,37 @@ socket_control(Connection, Socket, Pid, Transport) ->
socket_control(Connection, Socket, Pid, Transport, undefined).
%--------------------------------------------------------------------
--spec socket_control(tls_connection | dtls_connection, port(), pid(), atom(), pid()| undefined) ->
+-spec socket_control(tls_connection | dtls_connection, port(), [pid()], atom(), pid()| atom()) ->
{ok, #sslsocket{}} | {error, reason()}.
%%--------------------------------------------------------------------
-socket_control(Connection, Socket, Pid, Transport, udp_listner) ->
- %% dtls listner process must have the socket control
- {ok, Connection:socket(Pid, Transport, Socket, Connection, undefined)};
+socket_control(Connection, Socket, Pids, Transport, udp_listener) ->
+ %% dtls listener process must have the socket control
+ {ok, Connection:socket(Pids, Transport, Socket, Connection, undefined)};
-socket_control(tls_connection = Connection, Socket, Pid, Transport, ListenTracker) ->
+socket_control(tls_connection = Connection, Socket, [Pid|_] = Pids, Transport, ListenTracker) ->
case Transport:controlling_process(Socket, Pid) of
ok ->
- {ok, Connection:socket(Pid, Transport, Socket, Connection, ListenTracker)};
+ {ok, Connection:socket(Pids, Transport, Socket, Connection, ListenTracker)};
{error, Reason} ->
{error, Reason}
end;
-socket_control(dtls_connection = Connection, {_, Socket}, Pid, Transport, ListenTracker) ->
+socket_control(dtls_connection = Connection, {_, Socket}, [Pid|_] = Pids, Transport, ListenTracker) ->
case Transport:controlling_process(Socket, Pid) of
ok ->
- {ok, Connection:socket(Pid, Transport, Socket, Connection, ListenTracker)};
+ {ok, Connection:socket(Pids, Transport, Socket, Connection, ListenTracker)};
{error, Reason} ->
{error, Reason}
end.
+
+start_or_recv_cancel_timer(infinity, _RecvFrom) ->
+ undefined;
+start_or_recv_cancel_timer(Timeout, RecvFrom) ->
+ erlang:send_after(Timeout, self(), {cancel_start_or_recv, RecvFrom}).
+
+%%====================================================================
+%% User events
+%%====================================================================
+
%%--------------------------------------------------------------------
-spec send(pid(), iodata()) -> ok | {error, reason()}.
%%
@@ -263,8 +307,23 @@ renegotiation(ConnectionPid) ->
call(ConnectionPid, renegotiate).
%%--------------------------------------------------------------------
+-spec internal_renegotiation(pid(), ssl_record:connection_states()) ->
+ ok.
+%%
+%% Description: Starts a renegotiation of the ssl session.
+%%--------------------------------------------------------------------
+internal_renegotiation(ConnectionPid, #{current_write := WriteState}) ->
+ gen_statem:cast(ConnectionPid, {internal_renegotiate, WriteState}).
+
+get_sslsocket(ConnectionPid) ->
+ call(ConnectionPid, get_sslsocket).
+
+dist_handshake_complete(ConnectionPid, DHandle) ->
+ gen_statem:cast(ConnectionPid, {dist_handshake_complete, DHandle}).
+
+%%--------------------------------------------------------------------
-spec prf(pid(), binary() | 'master_secret', binary(),
- binary() | ssl:prf_random(), non_neg_integer()) ->
+ [binary() | ssl:prf_random()], non_neg_integer()) ->
{ok, binary()} | {error, reason()} | {'EXIT', term()}.
%%
%% Description: use a ssl sessions TLS PRF to generate key material
@@ -272,6 +331,193 @@ renegotiation(ConnectionPid) ->
prf(ConnectionPid, Secret, Label, Seed, WantedLength) ->
call(ConnectionPid, {prf, Secret, Label, Seed, WantedLength}).
+%%====================================================================
+%% Alert and close handling
+%%====================================================================
+handle_own_alert(Alert, _, StateName,
+ #state{role = Role,
+ protocol_cb = Connection,
+ ssl_options = SslOpts} = State) ->
+ try %% Try to tell the other side
+ send_alert(Alert, StateName, State)
+ catch _:_ -> %% Can crash if we are in a uninitialized state
+ ignore
+ end,
+ try %% Try to tell the local user
+ log_alert(SslOpts#ssl_options.log_alert, Role, Connection:protocol_name(), StateName, Alert#alert{role = Role}),
+ handle_normal_shutdown(Alert,StateName, State)
+ catch _:_ ->
+ ok
+ end,
+ stop({shutdown, own_alert}, State).
+
+handle_normal_shutdown(Alert, _, #state{socket = Socket,
+ transport_cb = Transport,
+ protocol_cb = Connection,
+ start_or_recv_from = StartFrom,
+ tracker = Tracker,
+ role = Role, renegotiation = {false, first}} = State) ->
+ Pids = Connection:pids(State),
+ alert_user(Pids, Transport, Tracker,Socket, StartFrom, Alert, Role, Connection);
+
+handle_normal_shutdown(Alert, StateName, #state{socket = Socket,
+ socket_options = Opts,
+ transport_cb = Transport,
+ protocol_cb = Connection,
+ user_application = {_Mon, Pid},
+ tracker = Tracker,
+ start_or_recv_from = RecvFrom, role = Role} = State) ->
+ Pids = Connection:pids(State),
+ alert_user(Pids, Transport, Tracker, Socket, StateName, Opts, Pid, RecvFrom, Alert, Role, Connection).
+
+handle_alert(#alert{level = ?FATAL} = Alert, StateName,
+ #state{socket = Socket, transport_cb = Transport,
+ protocol_cb = Connection,
+ ssl_options = SslOpts, start_or_recv_from = From, host = Host,
+ port = Port, session = Session, user_application = {_Mon, Pid},
+ role = Role, socket_options = Opts, tracker = Tracker} = State) ->
+ invalidate_session(Role, Host, Port, Session),
+ log_alert(SslOpts#ssl_options.log_alert, Role, Connection:protocol_name(),
+ StateName, Alert#alert{role = opposite_role(Role)}),
+ Pids = Connection:pids(State),
+ alert_user(Pids, Transport, Tracker, Socket, StateName, Opts, Pid, From, Alert, Role, Connection),
+ stop(normal, State);
+
+handle_alert(#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} = Alert,
+ StateName, State) ->
+ handle_normal_shutdown(Alert, StateName, State),
+ stop({shutdown, peer_close}, State);
+
+handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName,
+ #state{role = Role, ssl_options = SslOpts, protocol_cb = Connection,
+ renegotiation = {true, internal}} = State) ->
+ log_alert(SslOpts#ssl_options.log_alert, Role,
+ Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
+ handle_normal_shutdown(Alert, StateName, State),
+ stop({shutdown, peer_close}, State);
+
+handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, connection = StateName,
+ #state{role = Role,
+ ssl_options = SslOpts, renegotiation = {true, From},
+ protocol_cb = Connection} = State0) ->
+ log_alert(SslOpts#ssl_options.log_alert, Role,
+ Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
+ gen_statem:reply(From, {error, renegotiation_rejected}),
+ State1 = Connection:reinit_handshake_data(State0),
+ {Record, State} = Connection:next_record(State1#state{renegotiation = undefined}),
+ Connection:next_event(connection, Record, State);
+
+handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName,
+ #state{role = Role,
+ ssl_options = SslOpts, renegotiation = {true, From},
+ protocol_cb = Connection} = State0) ->
+ log_alert(SslOpts#ssl_options.log_alert, Role,
+ Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
+ gen_statem:reply(From, {error, renegotiation_rejected}),
+ {Record, State1} = Connection:next_record(State0),
+ %% Go back to connection!
+ State = Connection:reinit(State1#state{renegotiation = undefined}),
+ Connection:next_event(connection, Record, State);
+
+%% Gracefully log and ignore all other warning alerts
+handle_alert(#alert{level = ?WARNING} = Alert, StateName,
+ #state{ssl_options = SslOpts, protocol_cb = Connection, role = Role} = State0) ->
+ log_alert(SslOpts#ssl_options.log_alert, Role,
+ Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
+ {Record, State} = Connection:next_record(State0),
+ Connection:next_event(StateName, Record, State).
+
+%%====================================================================
+%% Data handling
+%%====================================================================
+read_application_data(Data, #state{user_application = {_Mon, Pid},
+ socket = Socket,
+ protocol_cb = Connection,
+ transport_cb = Transport,
+ socket_options = SOpts,
+ bytes_to_read = BytesToRead,
+ start_or_recv_from = RecvFrom,
+ timer = Timer,
+ user_data_buffer = Buffer0,
+ tracker = Tracker} = State0) ->
+ Buffer1 = if
+ Buffer0 =:= <<>> -> Data;
+ Data =:= <<>> -> Buffer0;
+ true -> <<Buffer0/binary, Data/binary>>
+ end,
+ case get_data(SOpts, BytesToRead, Buffer1) of
+ {ok, ClientData, Buffer} -> % Send data
+ #state{ssl_options = #ssl_options{erl_dist = Dist},
+ erl_dist_data = DistData} = State0,
+ case Dist andalso is_dist_up(DistData) of
+ true ->
+ dist_app_data(ClientData, State0#state{user_data_buffer = Buffer,
+ bytes_to_read = undefined});
+ _ ->
+ SocketOpt =
+ deliver_app_data(Connection:pids(State0),
+ Transport, Socket, SOpts,
+ ClientData, Pid, RecvFrom, Tracker, Connection),
+ cancel_timer(Timer),
+ State =
+ State0#state{
+ user_data_buffer = Buffer,
+ start_or_recv_from = undefined,
+ timer = undefined,
+ bytes_to_read = undefined,
+ socket_options = SocketOpt
+ },
+ if
+ SocketOpt#socket_options.active =:= false;
+ Buffer =:= <<>> ->
+ %% Passive mode, wait for active once or recv
+ %% Active and empty, get more data
+ Connection:next_record_if_active(State);
+ true -> %% We have more data
+ read_application_data(<<>>, State)
+ end
+ end;
+ {more, Buffer} -> % no reply, we need more data
+ Connection:next_record(State0#state{user_data_buffer = Buffer});
+ {passive, Buffer} ->
+ Connection:next_record_if_active(State0#state{user_data_buffer = Buffer});
+ {error,_Reason} -> %% Invalid packet in packet mode
+ deliver_packet_error(Connection:pids(State0),
+ Transport, Socket, SOpts, Buffer1, Pid, RecvFrom, Tracker, Connection),
+ stop(normal, State0)
+ end.
+
+dist_app_data(ClientData, #state{protocol_cb = Connection,
+ erl_dist_data = #{dist_handle := undefined,
+ dist_buffer := DistBuff} = DistData} = State) ->
+ Connection:next_record_if_active(State#state{erl_dist_data = DistData#{dist_buffer => [ClientData, DistBuff]}});
+dist_app_data(ClientData, #state{erl_dist_data = #{dist_handle := DHandle,
+ dist_buffer := DistBuff} = ErlDistData,
+ protocol_cb = Connection,
+ user_data_buffer = Buffer,
+ socket_options = SOpts} = State) ->
+ Data = merge_dist_data(DistBuff, ClientData),
+ try erlang:dist_ctrl_put_data(DHandle, Data) of
+ _ when SOpts#socket_options.active =:= false;
+ Buffer =:= <<>> ->
+ %% Passive mode, wait for active once or recv
+ %% Active and empty, get more data
+ Connection:next_record_if_active(State#state{erl_dist_data = ErlDistData#{dist_buffer => <<>>}});
+ _ -> %% We have more data
+ read_application_data(<<>>, State)
+ catch error:_ ->
+ stop(State, disconnect)
+ end.
+
+merge_dist_data(<<>>, ClientData) ->
+ ClientData;
+merge_dist_data(DistBuff, <<>>) ->
+ DistBuff;
+merge_dist_data(DistBuff, ClientData) ->
+ [DistBuff, ClientData].
+%%====================================================================
+%% Help functions for tls|dtls_connection.erl
+%%====================================================================
%%--------------------------------------------------------------------
-spec handle_session(#server_hello{}, ssl_record:ssl_version(),
binary(), ssl_record:connection_states(), _,_, #state{}) ->
@@ -283,8 +529,8 @@ handle_session(#server_hello{cipher_suite = CipherSuite,
#state{session = #session{session_id = OldId},
negotiated_version = ReqVersion,
negotiated_protocol = CurrentProtocol} = State0) ->
- {KeyAlgorithm, _, _, _} =
- ssl_cipher:suite_definition(CipherSuite),
+ #{key_exchange := KeyAlgorithm} =
+ ssl_cipher_format:suite_definition(CipherSuite),
PremasterSecret = make_premaster_secret(ReqVersion, KeyAlgorithm),
@@ -315,6 +561,9 @@ handle_session(#server_hello{cipher_suite = CipherSuite,
-spec ssl_config(#ssl_options{}, client | server, #state{}) -> #state{}.
%%--------------------------------------------------------------------
ssl_config(Opts, Role, State) ->
+ ssl_config(Opts, Role, State, new).
+
+ssl_config(Opts, Role, State0, Type) ->
{ok, #{cert_db_ref := Ref,
cert_db_handle := CertDbHandle,
fileref_db_handle := FileRefHandle,
@@ -324,23 +573,29 @@ ssl_config(Opts, Role, State) ->
dh_params := DHParams,
own_certificate := OwnCert}} =
ssl_config:init(Opts, Role),
- Handshake = ssl_handshake:init_handshake_history(),
TimeStamp = erlang:monotonic_time(),
- Session = State#state.session,
- State#state{tls_handshake_history = Handshake,
- session = Session#session{own_certificate = OwnCert,
- time_stamp = TimeStamp},
- file_ref_db = FileRefHandle,
- cert_db_ref = Ref,
- cert_db = CertDbHandle,
- crl_db = CRLDbHandle,
- session_cache = CacheHandle,
- private_key = Key,
- diffie_hellman_params = DHParams,
- ssl_options = Opts}.
+ Session = State0#state.session,
+ State = State0#state{session = Session#session{own_certificate = OwnCert,
+ time_stamp = TimeStamp},
+ file_ref_db = FileRefHandle,
+ cert_db_ref = Ref,
+ cert_db = CertDbHandle,
+ crl_db = CRLDbHandle,
+ session_cache = CacheHandle,
+ private_key = Key,
+ diffie_hellman_params = DHParams,
+ ssl_options = Opts},
+ case Type of
+ new ->
+ Handshake = ssl_handshake:init_handshake_history(),
+ State#state{tls_handshake_history = Handshake};
+ continue ->
+ State
+ end.
+
%%====================================================================
-%% gen_statem state functions
+%% gen_statem general state functions with connection cb argument
%%====================================================================
%%--------------------------------------------------------------------
-spec init(gen_statem:event_type(),
@@ -361,29 +616,58 @@ init({call, From}, {start, {Opts, EmOpts}, Timeout},
SslOpts = ssl:handle_options(Opts, OrigSSLOptions),
State = ssl_config(SslOpts, Role, State0),
init({call, From}, {start, Timeout},
- State#state{ssl_options = SslOpts, socket_options = new_emulated(EmOpts, SockOpts)}, Connection)
+ State#state{ssl_options = SslOpts,
+ socket_options = new_emulated(EmOpts, SockOpts)}, Connection)
catch throw:Error ->
- {stop_and_reply, normal, {reply, From, {error, Error}}}
+ stop_and_reply(normal, {reply, From, {error, Error}}, State0)
end;
init({call, From}, Msg, State, Connection) ->
- handle_call(Msg, From, init, State, Connection);
+ handle_call(Msg, From, ?FUNCTION_NAME, State, Connection);
init(_Type, _Event, _State, _Connection) ->
{keep_state_and_data, [postpone]}.
%%--------------------------------------------------------------------
+-spec error(gen_statem:event_type(),
+ {start, timeout()} | term(), #state{},
+ tls_connection | dtls_connection) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+error({call, From}, {close, _}, State, _Connection) ->
+ stop_and_reply(normal, {reply, From, ok}, State);
+error({call, From}, _Msg, State, _Connection) ->
+ {next_state, ?FUNCTION_NAME, State, [{reply, From, {error, closed}}]}.
+
+%%--------------------------------------------------------------------
-spec hello(gen_statem:event_type(),
#hello_request{} | #server_hello{} | term(),
#state{}, tls_connection | dtls_connection) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
hello({call, From}, Msg, State, Connection) ->
- handle_call(Msg, From, hello, State, Connection);
+ handle_call(Msg, From, ?FUNCTION_NAME, State, Connection);
hello(internal, {common_client_hello, Type, ServerHelloExt}, State, Connection) ->
do_server_hello(Type, ServerHelloExt, State, Connection);
hello(info, Msg, State, _) ->
- handle_info(Msg, hello, State);
+ handle_info(Msg, ?FUNCTION_NAME, State);
hello(Type, Msg, State, Connection) ->
- handle_common_event(Type, Msg, hello, State, Connection).
+ handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection).
+
+user_hello({call, From}, cancel, #state{negotiated_version = Version} = State, _) ->
+ gen_statem:reply(From, ok),
+ handle_own_alert(?ALERT_REC(?FATAL, ?USER_CANCELED, user_canceled),
+ Version, ?FUNCTION_NAME, State);
+user_hello({call, From}, {handshake_continue, NewOptions, Timeout}, #state{hello = Hello,
+ role = Role,
+ start_or_recv_from = RecvFrom,
+ ssl_options = Options0} = State0, _Connection) ->
+ Timer = start_or_recv_cancel_timer(Timeout, RecvFrom),
+ Options = ssl:handle_options(NewOptions, Options0#ssl_options{handshake = full}),
+ State = ssl_config(Options, Role, State0, continue),
+ {next_state, hello, State#state{start_or_recv_from = From,
+ timer = Timer},
+ [{next_event, internal, Hello}]};
+user_hello(_, _, _, _) ->
+ {keep_state_and_data, [postpone]}.
%%--------------------------------------------------------------------
-spec abbreviated(gen_statem:event_type(),
@@ -392,8 +676,7 @@ hello(Type, Msg, State, Connection) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
abbreviated({call, From}, Msg, State, Connection) ->
- handle_call(Msg, From, abbreviated, State, Connection);
-
+ handle_call(Msg, From, ?FUNCTION_NAME, State, Connection);
abbreviated(internal, #finished{verify_data = Data} = Finished,
#state{role = server,
negotiated_version = Version,
@@ -412,9 +695,8 @@ abbreviated(internal, #finished{verify_data = Data} = Finished,
expecting_finished = false}, Connection),
Connection:next_event(connection, Record, State);
#alert{} = Alert ->
- handle_own_alert(Alert, Version, abbreviated, State0)
+ handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0)
end;
-
abbreviated(internal, #finished{verify_data = Data} = Finished,
#state{role = client, tls_handshake_history = Handshake0,
session = #session{master_secret = MasterSecret},
@@ -428,13 +710,12 @@ abbreviated(internal, #finished{verify_data = Data} = Finished,
ssl_record:set_server_verify_data(current_read, Data, ConnectionStates0),
{State1, Actions} =
finalize_handshake(State0#state{connection_states = ConnectionStates1},
- abbreviated, Connection),
+ ?FUNCTION_NAME, Connection),
{Record, State} = prepare_connection(State1#state{expecting_finished = false}, Connection),
Connection:next_event(connection, Record, State, Actions);
#alert{} = Alert ->
- handle_own_alert(Alert, Version, abbreviated, State0)
+ handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0)
end;
-
%% only allowed to send next_protocol message after change cipher spec
%% & before finished message and it is not allowed during renegotiation
abbreviated(internal, #next_protocol{selected_protocol = SelectedProtocol},
@@ -442,20 +723,20 @@ abbreviated(internal, #next_protocol{selected_protocol = SelectedProtocol},
Connection) ->
{Record, State} =
Connection:next_record(State0#state{negotiated_protocol = SelectedProtocol}),
- Connection:next_event(abbreviated, Record,
+ Connection:next_event(?FUNCTION_NAME, Record,
State#state{expecting_next_protocol_negotiation = false});
abbreviated(internal,
- #change_cipher_spec{type = <<1>>}, #state{connection_states = ConnectionStates0} =
- State0, Connection) ->
+ #change_cipher_spec{type = <<1>>},
+ #state{connection_states = ConnectionStates0} = State0, Connection) ->
ConnectionStates1 =
- ssl_record:activate_pending_connection_state(ConnectionStates0, read),
+ ssl_record:activate_pending_connection_state(ConnectionStates0, read, Connection),
{Record, State} = Connection:next_record(State0#state{connection_states =
ConnectionStates1}),
- Connection:next_event(abbreviated, Record, State#state{expecting_finished = true});
+ Connection:next_event(?FUNCTION_NAME, Record, State#state{expecting_finished = true});
abbreviated(info, Msg, State, _) ->
- handle_info(Msg, abbreviated, State);
+ handle_info(Msg, ?FUNCTION_NAME, State);
abbreviated(Type, Msg, State, Connection) ->
- handle_common_event(Type, Msg, abbreviated, State, Connection).
+ handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection).
%%--------------------------------------------------------------------
-spec certify(gen_statem:event_type(),
@@ -465,17 +746,16 @@ abbreviated(Type, Msg, State, Connection) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
certify({call, From}, Msg, State, Connection) ->
- handle_call(Msg, From, certify, State, Connection);
+ handle_call(Msg, From, ?FUNCTION_NAME, State, Connection);
certify(info, Msg, State, _) ->
- handle_info(Msg, certify, State);
+ handle_info(Msg, ?FUNCTION_NAME, State);
certify(internal, #certificate{asn1_certificates = []},
#state{role = server, negotiated_version = Version,
ssl_options = #ssl_options{verify = verify_peer,
fail_if_no_peer_cert = true}} =
State, _) ->
Alert = ?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE),
- handle_own_alert(Alert, Version, certify, State);
-
+ handle_own_alert(Alert, Version, ?FUNCTION_NAME, State);
certify(internal, #certificate{asn1_certificates = []},
#state{role = server,
ssl_options = #ssl_options{verify = verify_peer,
@@ -483,41 +763,40 @@ certify(internal, #certificate{asn1_certificates = []},
State0, Connection) ->
{Record, State} =
Connection:next_record(State0#state{client_certificate_requested = false}),
- Connection:next_event(certify, Record, State);
-
+ Connection:next_event(?FUNCTION_NAME, Record, State);
certify(internal, #certificate{},
#state{role = server,
negotiated_version = Version,
ssl_options = #ssl_options{verify = verify_none}} =
State, _) ->
Alert = ?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE, unrequested_certificate),
- handle_own_alert(Alert, Version, certify, State);
-
+ handle_own_alert(Alert, Version, ?FUNCTION_NAME, State);
certify(internal, #certificate{} = Cert,
#state{negotiated_version = Version,
role = Role,
+ host = Host,
cert_db = CertDbHandle,
cert_db_ref = CertDbRef,
crl_db = CRLDbInfo,
ssl_options = Opts} = State, Connection) ->
case ssl_handshake:certify(Cert, CertDbHandle, CertDbRef,
- Opts, CRLDbInfo, Role) of
+ Opts, CRLDbInfo, Role, Host) of
{PeerCert, PublicKeyInfo} ->
handle_peer_cert(Role, PeerCert, PublicKeyInfo,
State#state{client_certificate_requested = false}, Connection);
#alert{} = Alert ->
- handle_own_alert(Alert, Version, certify, State)
+ handle_own_alert(Alert, Version, ?FUNCTION_NAME, State)
end;
-
certify(internal, #server_key_exchange{exchange_keys = Keys},
#state{role = client, negotiated_version = Version,
key_algorithm = Alg,
public_key_info = PubKeyInfo,
+ session = Session,
connection_states = ConnectionStates} = State, Connection)
when Alg == dhe_dss; Alg == dhe_rsa;
Alg == ecdhe_rsa; Alg == ecdhe_ecdsa;
Alg == dh_anon; Alg == ecdh_anon;
- Alg == psk; Alg == dhe_psk; Alg == rsa_psk;
+ Alg == psk; Alg == dhe_psk; Alg == ecdhe_psk; Alg == rsa_psk;
Alg == srp_dss; Alg == srp_rsa; Alg == srp_anon ->
Params = ssl_handshake:decode_server_key(Keys, Alg, ssl:tls_version(Version)),
@@ -534,14 +813,30 @@ certify(internal, #server_key_exchange{exchange_keys = Keys},
ConnectionStates, ssl:tls_version(Version), PubKeyInfo) of
true ->
calculate_secret(Params#server_key_params.params,
- State#state{hashsign_algorithm = HashSign},
+ State#state{hashsign_algorithm = HashSign,
+ session = session_handle_params(Params#server_key_params.params, Session)},
Connection);
false ->
handle_own_alert(?ALERT_REC(?FATAL, ?DECRYPT_ERROR),
- Version, certify, State)
+ Version, ?FUNCTION_NAME, State)
end
end;
-
+certify(internal, #certificate_request{},
+ #state{role = client, negotiated_version = Version,
+ key_algorithm = Alg} = State, _)
+ when Alg == dh_anon; Alg == ecdh_anon;
+ Alg == psk; Alg == dhe_psk; Alg == ecdhe_psk; Alg == rsa_psk;
+ Alg == srp_dss; Alg == srp_rsa; Alg == srp_anon ->
+ handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE),
+ Version, ?FUNCTION_NAME, State);
+certify(internal, #certificate_request{},
+ #state{session = #session{own_certificate = undefined},
+ role = client} = State0, Connection) ->
+ %% The client does not have a certificate and will send an empty reply, the server may fail
+ %% or accept the connection by its own preference. No signature algorihms needed as there is
+ %% no certificate to verify.
+ {Record, State} = Connection:next_record(State0),
+ Connection:next_event(?FUNCTION_NAME, Record, State#state{client_certificate_requested = true});
certify(internal, #certificate_request{} = CertRequest,
#state{session = #session{own_certificate = Cert},
role = client,
@@ -549,13 +844,12 @@ certify(internal, #certificate_request{} = CertRequest,
negotiated_version = Version} = State0, Connection) ->
case ssl_handshake:select_hashsign(CertRequest, Cert, SupportedHashSigns, ssl:tls_version(Version)) of
#alert {} = Alert ->
- handle_own_alert(Alert, Version, certify, State0);
+ handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0);
NegotiatedHashSign ->
{Record, State} = Connection:next_record(State0#state{client_certificate_requested = true}),
- Connection:next_event(certify, Record,
+ Connection:next_event(?FUNCTION_NAME, Record,
State#state{cert_hashsign_algorithm = NegotiatedHashSign})
end;
-
%% PSK and RSA_PSK might bypass the Server-Key-Exchange
certify(internal, #server_hello_done{},
#state{session = #session{master_secret = undefined},
@@ -568,13 +862,12 @@ certify(internal, #server_hello_done{},
when Alg == psk ->
case ssl_handshake:premaster_secret({Alg, PSKIdentity}, PSKLookup) of
#alert{} = Alert ->
- handle_own_alert(Alert, Version, certify, State0);
+ handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0);
PremasterSecret ->
State = master_secret(PremasterSecret,
State0#state{premaster_secret = PremasterSecret}),
client_certify_and_key_exchange(State, Connection)
end;
-
certify(internal, #server_hello_done{},
#state{session = #session{master_secret = undefined},
ssl_options = #ssl_options{user_lookup_fun = PSKLookup},
@@ -589,13 +882,12 @@ certify(internal, #server_hello_done{},
case ssl_handshake:premaster_secret({Alg, PSKIdentity}, PSKLookup,
RSAPremasterSecret) of
#alert{} = Alert ->
- handle_own_alert(Alert, Version, certify, State0);
+ handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0);
PremasterSecret ->
State = master_secret(PremasterSecret,
State0#state{premaster_secret = RSAPremasterSecret}),
client_certify_and_key_exchange(State, Connection)
end;
-
%% Master secret was determined with help of server-key exchange msg
certify(internal, #server_hello_done{},
#state{session = #session{master_secret = MasterSecret} = Session,
@@ -609,9 +901,8 @@ certify(internal, #server_hello_done{},
State = State0#state{connection_states = ConnectionStates},
client_certify_and_key_exchange(State, Connection);
#alert{} = Alert ->
- handle_own_alert(Alert, Version, certify, State0)
+ handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0)
end;
-
%% Master secret is calculated from premaster_secret
certify(internal, #server_hello_done{},
#state{session = Session0,
@@ -627,17 +918,15 @@ certify(internal, #server_hello_done{},
session = Session},
client_certify_and_key_exchange(State, Connection);
#alert{} = Alert ->
- handle_own_alert(Alert, Version, certify, State0)
+ handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0)
end;
-
certify(internal = Type, #client_key_exchange{} = Msg,
#state{role = server,
client_certificate_requested = true,
ssl_options = #ssl_options{fail_if_no_peer_cert = true}} = State,
Connection) ->
%% We expect a certificate here
- handle_common_event(Type, Msg, certify, State, Connection);
-
+ handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection);
certify(internal, #client_key_exchange{exchange_keys = Keys},
State = #state{key_algorithm = KeyAlg, negotiated_version = Version}, Connection) ->
try
@@ -645,11 +934,10 @@ certify(internal, #client_key_exchange{exchange_keys = Keys},
State, Connection)
catch
#alert{} = Alert ->
- handle_own_alert(Alert, Version, certify, State)
+ handle_own_alert(Alert, Version, ?FUNCTION_NAME, State)
end;
-
certify(Type, Msg, State, Connection) ->
- handle_common_event(Type, Msg, certify, State, Connection).
+ handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection).
%%--------------------------------------------------------------------
-spec cipher(gen_statem:event_type(),
@@ -658,11 +946,9 @@ certify(Type, Msg, State, Connection) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
cipher({call, From}, Msg, State, Connection) ->
- handle_call(Msg, From, cipher, State, Connection);
-
+ handle_call(Msg, From, ?FUNCTION_NAME, State, Connection);
cipher(info, Msg, State, _) ->
- handle_info(Msg, cipher, State);
-
+ handle_info(Msg, ?FUNCTION_NAME, State);
cipher(internal, #certificate_verify{signature = Signature,
hashsign_algorithm = CertHashSign},
#state{role = server,
@@ -673,25 +959,24 @@ cipher(internal, #certificate_verify{signature = Signature,
tls_handshake_history = Handshake
} = State0, Connection) ->
+ TLSVersion = ssl:tls_version(Version),
%% Use negotiated value if TLS-1.2 otherwhise return default
- HashSign = negotiated_hashsign(CertHashSign, KexAlg, PublicKeyInfo, Version),
+ HashSign = negotiated_hashsign(CertHashSign, KexAlg, PublicKeyInfo, TLSVersion),
case ssl_handshake:certificate_verify(Signature, PublicKeyInfo,
- ssl:tls_version(Version), HashSign, MasterSecret, Handshake) of
+ TLSVersion, HashSign, MasterSecret, Handshake) of
valid ->
{Record, State} = Connection:next_record(State0),
- Connection:next_event(cipher, Record,
+ Connection:next_event(?FUNCTION_NAME, Record,
State#state{cert_hashsign_algorithm = HashSign});
#alert{} = Alert ->
- handle_own_alert(Alert, Version, cipher, State0)
+ handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0)
end;
-
%% client must send a next protocol message if we are expecting it
cipher(internal, #finished{},
#state{role = server, expecting_next_protocol_negotiation = true,
negotiated_protocol = undefined, negotiated_version = Version} = State0,
_Connection) ->
- handle_own_alert(?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE), Version, cipher, State0);
-
+ handle_own_alert(?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE), Version, ?FUNCTION_NAME, State0);
cipher(internal, #finished{verify_data = Data} = Finished,
#state{negotiated_version = Version,
host = Host,
@@ -700,6 +985,7 @@ cipher(internal, #finished{verify_data = Data} = Finished,
expecting_finished = true,
session = #session{master_secret = MasterSecret}
= Session0,
+ ssl_options = SslOpts,
connection_states = ConnectionStates0,
tls_handshake_history = Handshake0} = State, Connection) ->
case ssl_handshake:verify_connection(ssl:tls_version(Version), Finished,
@@ -707,13 +993,12 @@ cipher(internal, #finished{verify_data = Data} = Finished,
get_current_prf(ConnectionStates0, read),
MasterSecret, Handshake0) of
verified ->
- Session = register_session(Role, Host, Port, Session0),
+ Session = register_session(Role, host_id(Role, Host, SslOpts), Port, Session0),
cipher_role(Role, Data, Session,
State#state{expecting_finished = false}, Connection);
#alert{} = Alert ->
- handle_own_alert(Alert, Version, cipher, State)
+ handle_own_alert(Alert, Version, ?FUNCTION_NAME, State)
end;
-
%% only allowed to send next_protocol message after change cipher spec
%% & before finished message and it is not allowed during renegotiation
cipher(internal, #next_protocol{selected_protocol = SelectedProtocol},
@@ -721,67 +1006,74 @@ cipher(internal, #next_protocol{selected_protocol = SelectedProtocol},
expecting_finished = true} = State0, Connection) ->
{Record, State} =
Connection:next_record(State0#state{negotiated_protocol = SelectedProtocol}),
- Connection:next_event(cipher, Record,
+ Connection:next_event(?FUNCTION_NAME, Record,
State#state{expecting_next_protocol_negotiation = false});
cipher(internal, #change_cipher_spec{type = <<1>>}, #state{connection_states = ConnectionStates0} =
State0, Connection) ->
ConnectionStates1 =
- ssl_record:activate_pending_connection_state(ConnectionStates0, read),
+ ssl_record:activate_pending_connection_state(ConnectionStates0, read, Connection),
{Record, State} = Connection:next_record(State0#state{connection_states =
ConnectionStates1}),
- Connection:next_event(cipher, Record, State#state{expecting_finished = true});
+ Connection:next_event(?FUNCTION_NAME, Record, State#state{expecting_finished = true});
cipher(Type, Msg, State, Connection) ->
- handle_common_event(Type, Msg, cipher, State, Connection).
+ handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection).
%%--------------------------------------------------------------------
-spec connection(gen_statem:event_type(), term(),
#state{}, tls_connection | dtls_connection) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-connection({call, From}, {application_data, Data},
- #state{protocol_cb = Connection} = State, Connection) ->
- %% We should look into having a worker process to do this to
- %% parallize send and receive decoding and not block the receiver
- %% if sending is overloading the socket.
- try
- write_application_data(Data, From, State)
- catch throw:Error ->
- hibernate_after(connection, State, [{reply, From, Error}])
- end;
connection({call, RecvFrom}, {recv, N, Timeout},
#state{protocol_cb = Connection, socket_options =
#socket_options{active = false}} = State0, Connection) ->
Timer = start_or_recv_cancel_timer(Timeout, RecvFrom),
Connection:passive_receive(State0#state{bytes_to_read = N,
start_or_recv_from = RecvFrom,
- timer = Timer}, connection);
+ timer = Timer}, ?FUNCTION_NAME);
connection({call, From}, renegotiate, #state{protocol_cb = Connection} = State,
Connection) ->
Connection:renegotiate(State#state{renegotiation = {true, From}}, []);
connection({call, From}, peer_certificate,
#state{session = #session{peer_certificate = Cert}} = State, _) ->
- hibernate_after(connection, State, [{reply, From, {ok, Cert}}]);
+ hibernate_after(?FUNCTION_NAME, State, [{reply, From, {ok, Cert}}]);
connection({call, From}, {connection_information, true}, State, _) ->
Info = connection_info(State) ++ security_info(State),
- hibernate_after(connection, State, [{reply, From, {ok, Info}}]);
+ hibernate_after(?FUNCTION_NAME, State, [{reply, From, {ok, Info}}]);
connection({call, From}, {connection_information, false}, State, _) ->
Info = connection_info(State),
- hibernate_after(connection, State, [{reply, From, {ok, Info}}]);
+ hibernate_after(?FUNCTION_NAME, State, [{reply, From, {ok, Info}}]);
connection({call, From}, negotiated_protocol,
#state{negotiated_protocol = undefined} = State, _) ->
- hibernate_after(connection, State, [{reply, From, {error, protocol_not_negotiated}}]);
+ hibernate_after(?FUNCTION_NAME, State, [{reply, From, {error, protocol_not_negotiated}}]);
connection({call, From}, negotiated_protocol,
#state{negotiated_protocol = SelectedProtocol} = State, _) ->
- hibernate_after(connection, State,
+ hibernate_after(?FUNCTION_NAME, State,
[{reply, From, {ok, SelectedProtocol}}]);
connection({call, From}, Msg, State, Connection) ->
- handle_call(Msg, From, connection, State, Connection);
+ handle_call(Msg, From, ?FUNCTION_NAME, State, Connection);
+connection(cast, {internal_renegotiate, WriteState}, #state{protocol_cb = Connection,
+ connection_states = ConnectionStates}
+ = State, Connection) ->
+ Connection:renegotiate(State#state{renegotiation = {true, internal},
+ connection_states = ConnectionStates#{current_write => WriteState}}, []);
+connection(cast, {dist_handshake_complete, DHandle},
+ #state{ssl_options = #ssl_options{erl_dist = true},
+ erl_dist_data = ErlDistData,
+ socket_options = SockOpts} = State0, Connection) ->
+ process_flag(priority, normal),
+ State1 =
+ State0#state{
+ socket_options =
+ SockOpts#socket_options{active = true},
+ erl_dist_data = ErlDistData#{dist_handle => DHandle}},
+ {Record, State} = dist_app_data(<<>>, State1),
+ Connection:next_event(connection, Record, State);
connection(info, Msg, State, _) ->
- handle_info(Msg, connection, State);
+ handle_info(Msg, ?FUNCTION_NAME, State);
connection(internal, {recv, _}, State, Connection) ->
- Connection:passive_receive(State, connection);
+ Connection:passive_receive(State, ?FUNCTION_NAME);
connection(Type, Msg, State, Connection) ->
- handle_common_event(Type, Msg, connection, State, Connection).
+ handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection).
%%--------------------------------------------------------------------
-spec downgrade(gen_statem:event_type(), term(),
@@ -794,12 +1086,12 @@ downgrade(internal, #alert{description = ?CLOSE_NOTIFY},
tls_socket:setopts(Transport, Socket, [{active, false}, {packet, 0}, {mode, binary}]),
Transport:controlling_process(Socket, Pid),
gen_statem:reply(From, {ok, Socket}),
- {stop, normal, State};
+ stop(normal, State);
downgrade(timeout, downgrade, #state{downgrade = {_, From}} = State, _) ->
gen_statem:reply(From, {error, timeout}),
- {stop, normal, State};
+ stop(normal, State);
downgrade(Type, Event, State, Connection) ->
- handle_common_event(Type, Event, downgrade, State, Connection).
+ handle_common_event(Type, Event, ?FUNCTION_NAME, State, Connection).
%%--------------------------------------------------------------------
%% Event handling functions called by state functions to handle
@@ -812,9 +1104,8 @@ handle_common_event(internal, {handshake, {#hello_request{} = Handshake, _}}, co
handle_common_event(internal, {handshake, {#hello_request{}, _}}, StateName, #state{role = client}, _)
when StateName =/= connection ->
{keep_state_and_data};
-handle_common_event(internal, {handshake, {Handshake, Raw}}, StateName,
- #state{tls_handshake_history = Hs0,
- ssl_options = #ssl_options{v2_hello_compatible = V2HComp}} = State0,
+handle_common_event(internal, {handshake, {Handshake, Raw}}, StateName,
+ #state{tls_handshake_history = Hs0} = State0,
Connection) ->
PossibleSNI = Connection:select_sni_extension(Handshake),
@@ -822,7 +1113,7 @@ handle_common_event(internal, {handshake, {Handshake, Raw}}, StateName,
%% a client_hello, which needs to be determined by the connection callback.
%% In other cases this is a noop
State = handle_sni_extension(PossibleSNI, State0),
- HsHist = ssl_handshake:update_handshake_history(Hs0, iolist_to_binary(Raw), V2HComp),
+ HsHist = ssl_handshake:update_handshake_history(Hs0, iolist_to_binary(Raw)),
{next_state, StateName, State#state{tls_handshake_history = HsHist},
[{next_event, internal, Handshake}]};
handle_common_event(internal, {protocol_record, TLSorDTLSRecord}, StateName, State, Connection) ->
@@ -831,10 +1122,17 @@ handle_common_event(timeout, hibernate, _, _, _) ->
{keep_state_and_data, [hibernate]};
handle_common_event(internal, {application_data, Data}, StateName, State0, Connection) ->
case read_application_data(Data, State0) of
- {stop, Reason, State} ->
- {stop, Reason, State};
+ {stop, _, _} = Stop->
+ Stop;
{Record, State} ->
- Connection:next_event(StateName, Record, State)
+ case Connection:next_event(StateName, Record, State) of
+ {next_state, StateName, State} ->
+ hibernate_after(StateName, State, []);
+ {next_state, StateName, State, Actions} ->
+ hibernate_after(StateName, State, Actions);
+ {stop, _, _} = Stop ->
+ Stop
+ end
end;
handle_common_event(internal, #change_cipher_spec{type = <<1>>}, StateName,
#state{negotiated_version = Version} = State, _) ->
@@ -842,8 +1140,8 @@ handle_common_event(internal, #change_cipher_spec{type = <<1>>}, StateName,
StateName, State);
handle_common_event(_Type, Msg, StateName, #state{negotiated_version = Version} = State,
_) ->
- Alert = ?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE),
- handle_own_alert(Alert, Version, {StateName, Msg}, State).
+ Alert = ?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE, {unexpected_msg, Msg}),
+ handle_own_alert(Alert, Version, StateName, State).
handle_call({application_data, _Data}, _, _, _, _) ->
%% In renegotiation priorities handshake, send data when handshake is finished
@@ -857,23 +1155,20 @@ handle_call({close, {Pid, Timeout}}, From, StateName, State0, Connection) when i
%% we must recive the close alert from the peer before releasing the
%% transport socket.
{next_state, downgrade, State#state{terminated = true}, [{timeout, Timeout, downgrade}]};
-handle_call({close, _} = Close, From, StateName, State, Connection) ->
+handle_call({close, _} = Close, From, StateName, State, _Connection) ->
%% Run terminate before returning so that the reuseaddr
%% inet-option works properly
- Result = Connection:terminate(Close, StateName, State#state{terminated = true}),
- {stop_and_reply, {shutdown, normal},
- {reply, From, Result}, State};
-handle_call({shutdown, How0}, From, _,
+ Result = terminate(Close, StateName, State),
+ stop_and_reply(
+ {shutdown, normal},
+ {reply, From, Result}, State#state{terminated = true});
+handle_call({shutdown, How0}, From, StateName,
#state{transport_cb = Transport,
- negotiated_version = Version,
- connection_states = ConnectionStates,
- socket = Socket}, Connection) ->
+ socket = Socket} = State, _) ->
case How0 of
How when How == write; How == both ->
- Alert = ?ALERT_REC(?WARNING, ?CLOSE_NOTIFY),
- {BinMsg, _} =
- Connection:encode_alert(Alert, Version, ConnectionStates),
- Connection:send(Transport, Socket, BinMsg);
+ send_alert(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY),
+ StateName, State);
_ ->
ok
end,
@@ -883,7 +1178,7 @@ handle_call({shutdown, How0}, From, _,
{keep_state_and_data, [{reply, From, ok}]};
Error ->
gen_statem:reply(From, {error, Error}),
- {stop, normal}
+ stop(normal, State)
end;
handle_call({recv, _N, _Timeout}, From, _,
#state{socket_options =
@@ -918,6 +1213,11 @@ handle_call({set_opts, Opts0}, From, StateName,
handle_call(renegotiate, From, StateName, _, _) when StateName =/= connection ->
{keep_state_and_data, [{reply, From, {error, already_renegotiating}}]};
+
+handle_call(get_sslsocket, From, _StateName, State, Connection) ->
+ SslSocket = Connection:socket(State),
+ {keep_state_and_data, [{reply, From, SslSocket}]};
+
handle_call({prf, Secret, Label, Seed, WantedLength}, From, _,
#state{connection_states = ConnectionStates,
negotiated_version = Version}, _) ->
@@ -952,42 +1252,53 @@ handle_info({ErrorTag, Socket, econnaborted}, StateName,
start_or_recv_from = StartFrom, role = Role,
error_tag = ErrorTag,
tracker = Tracker} = State) when StateName =/= connection ->
- alert_user(Transport, Tracker,Socket,
+ Pids = Connection:pids(State),
+ alert_user(Pids, Transport, Tracker,Socket,
StartFrom, ?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), Role, Connection),
- {stop, normal, State};
+ stop(normal, State);
handle_info({ErrorTag, Socket, Reason}, StateName, #state{socket = Socket,
error_tag = ErrorTag} = State) ->
Report = io_lib:format("SSL: Socket error: ~p ~n", [Reason]),
- error_logger:info_report(Report),
+ error_logger:error_report(Report),
handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
- {stop, normal, State};
-
-handle_info({'DOWN', MonitorRef, _, _, _}, _,
- State = #state{user_application={MonitorRef,_Pid}}) ->
- {stop, normal, State};
-
+ stop(normal, State);
+
+handle_info({'DOWN', MonitorRef, _, _, Reason}, _,
+ #state{user_application = {MonitorRef, _Pid},
+ ssl_options = #ssl_options{erl_dist = true}}) ->
+ {stop, {shutdown, Reason}};
+handle_info({'DOWN', MonitorRef, _, _, _}, _,
+ #state{user_application = {MonitorRef, _Pid}}) ->
+ {stop, normal};
+handle_info({'EXIT', Pid, _Reason}, StateName,
+ #state{user_application = {_MonitorRef, Pid}} = State) ->
+ %% It seems the user application has linked to us
+ %% - ignore that and let the monitor handle this
+ {next_state, StateName, State};
%%% So that terminate will be run when supervisor issues shutdown
handle_info({'EXIT', _Sup, shutdown}, _StateName, State) ->
- {stop, shutdown, State};
+ stop(shutdown, State);
handle_info({'EXIT', Socket, normal}, _StateName, #state{socket = Socket} = State) ->
%% Handle as transport close"
- {stop, {shutdown, transport_closed}, State};
+ stop({shutdown, transport_closed}, State);
+handle_info({'EXIT', Socket, Reason}, _StateName, #state{socket = Socket} = State) ->
+ stop({shutdown, Reason}, State);
handle_info(allow_renegotiate, StateName, State) ->
{next_state, StateName, State#state{allow_renegotiate = true}};
handle_info({cancel_start_or_recv, StartFrom}, StateName,
#state{renegotiation = {false, first}} = State) when StateName =/= connection ->
- {stop_and_reply, {shutdown, user_timeout},
- {reply, StartFrom, {error, timeout}}, State#state{timer = undefined}};
-
+ stop_and_reply(
+ {shutdown, user_timeout},
+ {reply, StartFrom, {error, timeout}},
+ State#state{timer = undefined});
handle_info({cancel_start_or_recv, RecvFrom}, StateName,
#state{start_or_recv_from = RecvFrom} = State) when RecvFrom =/= undefined ->
{next_state, StateName, State#state{start_or_recv_from = undefined,
bytes_to_read = undefined,
timer = undefined}, [{reply, RecvFrom, {error, timeout}}]};
-
handle_info({cancel_start_or_recv, _RecvFrom}, StateName, State) ->
{next_state, StateName, State#state{timer = undefined}};
@@ -996,9 +1307,9 @@ handle_info(Msg, StateName, #state{socket = Socket, error_tag = Tag} = State) ->
error_logger:info_report(Report),
{next_state, StateName, State}.
-%%--------------------------------------------------------------------
-%% gen_statem callbacks
-%%--------------------------------------------------------------------
+%%====================================================================
+%% general gen_statem callbacks
+%%====================================================================
terminate(_, _, #state{terminated = true}) ->
%% Happens when user closes the connection using ssl:close/1
%% we want to guarantee that Transport:close has been called
@@ -1007,13 +1318,12 @@ terminate(_, _, #state{terminated = true}) ->
%% returning. In both cases terminate has been run manually
%% before run by gen_statem which will end up here
ok;
-
terminate({shutdown, transport_closed} = Reason,
_StateName, #state{protocol_cb = Connection,
socket = Socket, transport_cb = Transport} = State) ->
handle_trusted_certs_db(State),
Connection:close(Reason, Socket, Transport, undefined, undefined);
-terminate({shutdown, own_alert}, _StateName, #state{%%send_queue = SendQueue,
+terminate({shutdown, own_alert}, _StateName, #state{
protocol_cb = Connection,
socket = Socket,
transport_cb = Transport} = State) ->
@@ -1024,17 +1334,21 @@ terminate({shutdown, own_alert}, _StateName, #state{%%send_queue = SendQueue,
_ ->
Connection:close({timeout, ?DEFAULT_TIMEOUT}, Socket, Transport, undefined, undefined)
end;
-terminate(Reason, connection, #state{negotiated_version = Version,
- protocol_cb = Connection,
- connection_states = ConnectionStates0,
- ssl_options = #ssl_options{padding_check = Check},
- transport_cb = Transport, socket = Socket
- } = State) ->
+terminate(downgrade = Reason, connection, #state{protocol_cb = Connection,
+ transport_cb = Transport, socket = Socket
+ } = State) ->
+ handle_trusted_certs_db(State),
+ Connection:close(Reason, Socket, Transport, undefined, undefined);
+terminate(Reason, connection, #state{protocol_cb = Connection,
+ connection_states = ConnectionStates,
+ ssl_options = #ssl_options{padding_check = Check},
+ transport_cb = Transport, socket = Socket
+ } = State) ->
handle_trusted_certs_db(State),
- {BinAlert, ConnectionStates} = terminate_alert(Reason, Version, ConnectionStates0, Connection),
- Connection:send(Transport, Socket, BinAlert),
+ Alert = terminate_alert(Reason),
+ %% Send the termination ALERT if possible
+ catch (ok = Connection:send_alert_in_connection(Alert, State)),
Connection:close(Reason, Socket, Transport, ConnectionStates, Check);
-
terminate(Reason, _StateName, #state{transport_cb = Transport, protocol_cb = Connection,
socket = Socket
} = State) ->
@@ -1068,115 +1382,13 @@ format_status(terminate, [_, StateName, State]) ->
}}]}].
%%--------------------------------------------------------------------
-%%%
-%%--------------------------------------------------------------------
-write_application_data(Data0, From,
- #state{socket = Socket,
- negotiated_version = Version,
- protocol_cb = Connection,
- transport_cb = Transport,
- connection_states = ConnectionStates0,
- socket_options = SockOpts,
- ssl_options = #ssl_options{renegotiate_at = RenegotiateAt}} = State) ->
- Data = encode_packet(Data0, SockOpts),
-
- case time_to_renegotiate(Data, ConnectionStates0, RenegotiateAt) of
- true ->
- Connection:renegotiate(State#state{renegotiation = {true, internal}},
- [{next_event, {call, From}, {application_data, Data0}}]);
- false ->
- {Msgs, ConnectionStates} = Connection:encode_data(Data, Version, ConnectionStates0),
- Result = Connection:send(Transport, Socket, Msgs),
- ssl_connection:hibernate_after(connection, State#state{connection_states = ConnectionStates},
- [{reply, From, Result}])
- end.
-
-read_application_data(Data, #state{user_application = {_Mon, Pid},
- socket = Socket,
- protocol_cb = Connection,
- transport_cb = Transport,
- socket_options = SOpts,
- bytes_to_read = BytesToRead,
- start_or_recv_from = RecvFrom,
- timer = Timer,
- user_data_buffer = Buffer0,
- tracker = Tracker} = State0) ->
- Buffer1 = if
- Buffer0 =:= <<>> -> Data;
- Data =:= <<>> -> Buffer0;
- true -> <<Buffer0/binary, Data/binary>>
- end,
- case get_data(SOpts, BytesToRead, Buffer1) of
- {ok, ClientData, Buffer} -> % Send data
- SocketOpt = deliver_app_data(Transport, Socket, SOpts,
- ClientData, Pid, RecvFrom, Tracker, Connection),
- cancel_timer(Timer),
- State = State0#state{user_data_buffer = Buffer,
- start_or_recv_from = undefined,
- timer = undefined,
- bytes_to_read = undefined,
- socket_options = SocketOpt
- },
- if
- SocketOpt#socket_options.active =:= false; Buffer =:= <<>> ->
- %% Passive mode, wait for active once or recv
- %% Active and empty, get more data
- Connection:next_record_if_active(State);
- true -> %% We have more data
- read_application_data(<<>>, State)
- end;
- {more, Buffer} -> % no reply, we need more data
- Connection:next_record(State0#state{user_data_buffer = Buffer});
- {passive, Buffer} ->
- Connection:next_record_if_active(State0#state{user_data_buffer = Buffer});
- {error,_Reason} -> %% Invalid packet in packet mode
- deliver_packet_error(Transport, Socket, SOpts, Buffer1, Pid, RecvFrom, Tracker, Connection),
- {stop, normal, State0}
- end.
-%%--------------------------------------------------------------------
-%%%
-%%--------------------------------------------------------------------
-handle_alert(#alert{level = ?FATAL} = Alert, StateName,
- #state{socket = Socket, transport_cb = Transport,
- protocol_cb = Connection,
- ssl_options = SslOpts, start_or_recv_from = From, host = Host,
- port = Port, session = Session, user_application = {_Mon, Pid},
- role = Role, socket_options = Opts, tracker = Tracker}) ->
- invalidate_session(Role, Host, Port, Session),
- log_alert(SslOpts#ssl_options.log_alert, StateName, Alert),
- alert_user(Transport, Tracker, Socket, StateName, Opts, Pid, From, Alert, Role, Connection),
- {stop, normal};
-
-handle_alert(#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} = Alert,
- StateName, State) ->
- handle_normal_shutdown(Alert, StateName, State),
- {stop, {shutdown, peer_close}};
-
-handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName,
- #state{ssl_options = SslOpts, renegotiation = {true, internal}} = State) ->
- log_alert(SslOpts#ssl_options.log_alert, StateName, Alert),
- handle_normal_shutdown(Alert, StateName, State),
- {stop, {shutdown, peer_close}};
-
-handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName,
- #state{ssl_options = SslOpts, renegotiation = {true, From},
- protocol_cb = Connection} = State0) ->
- log_alert(SslOpts#ssl_options.log_alert, StateName, Alert),
- gen_statem:reply(From, {error, renegotiation_rejected}),
- {Record, State} = Connection:next_record(State0),
- %% Go back to connection!
- Connection:next_event(connection, Record, State);
-
-%% Gracefully log and ignore all other warning alerts
-handle_alert(#alert{level = ?WARNING} = Alert, StateName,
- #state{ssl_options = SslOpts, protocol_cb = Connection} = State0) ->
- log_alert(SslOpts#ssl_options.log_alert, StateName, Alert),
- {Record, State} = Connection:next_record(State0),
- Connection:next_event(StateName, Record, State).
-
-%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+send_alert(Alert, connection, #state{protocol_cb = Connection} = State) ->
+ Connection:send_alert_in_connection(Alert, State);
+send_alert(Alert, _, #state{protocol_cb = Connection} = State) ->
+ Connection:send_alert(Alert, State).
+
connection_info(#state{sni_hostname = SNIHostname,
session = #session{session_id = SessionId,
cipher_suite = CipherSuite, ecc = ECCCurve},
@@ -1184,9 +1396,9 @@ connection_info(#state{sni_hostname = SNIHostname,
negotiated_version = {_,_} = Version,
ssl_options = Opts}) ->
RecordCB = record_cb(Connection),
- CipherSuiteDef = ssl_cipher:erl_suite_definition(CipherSuite),
- IsNamedCurveSuite = lists:member(element(1,CipherSuiteDef),
- [ecdh_ecdsa, ecdhe_ecdsa, ecdh_anon]),
+ CipherSuiteDef = #{key_exchange := KexAlg} = ssl_cipher_format:suite_definition(CipherSuite),
+ IsNamedCurveSuite = lists:member(KexAlg,
+ [ecdh_ecdsa, ecdhe_ecdsa, ecdh_rsa, ecdhe_rsa, ecdh_anon]),
CurveInfo = case ECCCurve of
{namedCurve, Curve} when IsNamedCurveSuite ->
[{ecc, {named_curve, pubkey_cert_records:namedCurves(Curve)}}];
@@ -1195,7 +1407,8 @@ connection_info(#state{sni_hostname = SNIHostname,
end,
[{protocol, RecordCB:protocol_version(Version)},
{session_id, SessionId},
- {cipher_suite, CipherSuiteDef},
+ {cipher_suite, ssl_cipher_format:erl_suite_definition(CipherSuiteDef)},
+ {selected_cipher_suite, CipherSuiteDef},
{sni_hostname, SNIHostname} | CurveInfo] ++ ssl_options_list(Opts).
security_info(#state{connection_states = ConnectionStates}) ->
@@ -1263,7 +1476,7 @@ resumed_server_hello(#state{session = Session,
server_hello(ServerHello, State0, Connection) ->
CipherSuite = ServerHello#server_hello.cipher_suite,
- {KeyAlgorithm, _, _, _} = ssl_cipher:suite_definition(CipherSuite),
+ #{key_exchange := KeyAlgorithm} = ssl_cipher_format:suite_definition(CipherSuite),
State = Connection:queue_handshake(ServerHello, State0),
State#state{key_algorithm = KeyAlgorithm}.
@@ -1277,8 +1490,8 @@ handle_peer_cert(Role, PeerCert, PublicKeyInfo,
State1 = State0#state{session =
Session#session{peer_certificate = PeerCert},
public_key_info = PublicKeyInfo},
- {KeyAlg,_,_,_} = ssl_cipher:suite_definition(CipherSuite),
- State2 = handle_peer_cert_key(Role, PeerCert, PublicKeyInfo, KeyAlg, State1),
+ #{key_exchange := KeyAlgorithm} = ssl_cipher_format:suite_definition(CipherSuite),
+ State2 = handle_peer_cert_key(Role, PeerCert, PublicKeyInfo, KeyAlgorithm, State1),
{Record, State} = Connection:next_record(State2),
Connection:next_event(certify, Record, State).
@@ -1286,12 +1499,12 @@ handle_peer_cert(Role, PeerCert, PublicKeyInfo,
handle_peer_cert_key(client, _,
{?'id-ecPublicKey', #'ECPoint'{point = _ECPoint} = PublicKey,
PublicKeyParams},
- KeyAlg, State) when KeyAlg == ecdh_rsa;
- KeyAlg == ecdh_ecdsa ->
+ KeyAlg, #state{session = Session} = State) when KeyAlg == ecdh_rsa;
+ KeyAlg == ecdh_ecdsa ->
ECDHKey = public_key:generate_key(PublicKeyParams),
PremasterSecret = ssl_handshake:premaster_secret(PublicKey, ECDHKey),
- master_secret(PremasterSecret, State#state{diffie_hellman_keys = ECDHKey});
-
+ master_secret(PremasterSecret, State#state{diffie_hellman_keys = ECDHKey,
+ session = Session#session{ecc = PublicKeyParams}});
%% We do currently not support cipher suites that use fixed DH.
%% If we want to implement that the following clause can be used
%% to extract DH parameters form cert.
@@ -1311,7 +1524,6 @@ certify_client(#state{client_certificate_requested = true, role = client,
= State, Connection) ->
Certificate = ssl_handshake:certificate(OwnCert, CertDbHandle, CertDbRef, client),
Connection:queue_handshake(Certificate, State);
-
certify_client(#state{client_certificate_requested = false} = State, _) ->
State.
@@ -1361,10 +1573,26 @@ server_certify_and_key_exchange(State0, Connection) ->
request_client_cert(State2, Connection).
certify_client_key_exchange(#encrypted_premaster_secret{premaster_secret= EncPMS},
- #state{private_key = Key} = State, Connection) ->
- PremasterSecret = ssl_handshake:premaster_secret(EncPMS, Key),
+ #state{private_key = Key, client_hello_version = {Major, Minor} = Version} = State, Connection) ->
+ FakeSecret = make_premaster_secret(Version, rsa),
+ %% Countermeasure for Bleichenbacher attack always provide some kind of premaster secret
+ %% and fail handshake later.RFC 5246 section 7.4.7.1.
+ PremasterSecret =
+ try ssl_handshake:premaster_secret(EncPMS, Key) of
+ Secret when erlang:byte_size(Secret) == ?NUM_OF_PREMASTERSECRET_BYTES ->
+ case Secret of
+ <<?BYTE(Major), ?BYTE(Minor), Rest/binary>> -> %% Correct
+ <<?BYTE(Major), ?BYTE(Minor), Rest/binary>>;
+ <<?BYTE(_), ?BYTE(_), Rest/binary>> -> %% Version mismatch
+ <<?BYTE(Major), ?BYTE(Minor), Rest/binary>>
+ end;
+ _ -> %% erlang:byte_size(Secret) =/= ?NUM_OF_PREMASTERSECRET_BYTES
+ FakeSecret
+ catch
+ #alert{description = ?DECRYPT_ERROR} ->
+ FakeSecret
+ end,
calculate_master_secret(PremasterSecret, State, Connection, certify, cipher);
-
certify_client_key_exchange(#client_diffie_hellman_public{dh_public = ClientPublicDhKey},
#state{diffie_hellman_params = #'DHParameter'{} = Params,
diffie_hellman_keys = {_, ServerDhPrivateKey}} = State,
@@ -1376,14 +1604,12 @@ certify_client_key_exchange(#client_ec_diffie_hellman_public{dh_public = ClientP
#state{diffie_hellman_keys = ECDHKey} = State, Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(#'ECPoint'{point = ClientPublicEcDhPoint}, ECDHKey),
calculate_master_secret(PremasterSecret, State, Connection, certify, cipher);
-
certify_client_key_exchange(#client_psk_identity{} = ClientKey,
#state{ssl_options =
#ssl_options{user_lookup_fun = PSKLookup}} = State0,
Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(ClientKey, PSKLookup),
calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher);
-
certify_client_key_exchange(#client_dhe_psk_identity{} = ClientKey,
#state{diffie_hellman_params = #'DHParameter'{} = Params,
diffie_hellman_keys = {_, ServerDhPrivateKey},
@@ -1393,6 +1619,14 @@ certify_client_key_exchange(#client_dhe_psk_identity{} = ClientKey,
PremasterSecret =
ssl_handshake:premaster_secret(ClientKey, ServerDhPrivateKey, Params, PSKLookup),
calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher);
+certify_client_key_exchange(#client_ecdhe_psk_identity{} = ClientKey,
+ #state{diffie_hellman_keys = ServerEcDhPrivateKey,
+ ssl_options =
+ #ssl_options{user_lookup_fun = PSKLookup}} = State,
+ Connection) ->
+ PremasterSecret =
+ ssl_handshake:premaster_secret(ClientKey, ServerEcDhPrivateKey, PSKLookup),
+ calculate_master_secret(PremasterSecret, State, Connection, certify, cipher);
certify_client_key_exchange(#client_rsa_psk_identity{} = ClientKey,
#state{private_key = Key,
ssl_options =
@@ -1400,7 +1634,6 @@ certify_client_key_exchange(#client_rsa_psk_identity{} = ClientKey,
Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(ClientKey, Key, PSKLookup),
calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher);
-
certify_client_key_exchange(#client_srp_public{} = ClientKey,
#state{srp_params = Params,
srp_keys = Key
@@ -1412,9 +1645,9 @@ certify_server(#state{key_algorithm = Algo} = State, _) when Algo == dh_anon;
Algo == ecdh_anon;
Algo == psk;
Algo == dhe_psk;
+ Algo == ecdhe_psk;
Algo == srp_anon ->
State;
-
certify_server(#state{cert_db = CertDbHandle,
cert_db_ref = CertDbRef,
session = #session{own_certificate = OwnCert}} = State, Connection) ->
@@ -1448,10 +1681,11 @@ key_exchange(#state{role = server, key_algorithm = Algo,
PrivateKey}),
State = Connection:queue_handshake(Msg, State0),
State#state{diffie_hellman_keys = DHKeys};
-
-key_exchange(#state{role = server, private_key = Key, key_algorithm = Algo} = State, _)
+key_exchange(#state{role = server, private_key = #'ECPrivateKey'{parameters = ECCurve} = Key, key_algorithm = Algo,
+ session = Session} = State, _)
when Algo == ecdh_ecdsa; Algo == ecdh_rsa ->
- State#state{diffie_hellman_keys = Key};
+ State#state{diffie_hellman_keys = Key,
+ session = Session#session{ecc = ECCurve}};
key_exchange(#state{role = server, key_algorithm = Algo,
hashsign_algorithm = HashSignAlgo,
private_key = PrivateKey,
@@ -1474,7 +1708,6 @@ key_exchange(#state{role = server, key_algorithm = Algo,
PrivateKey}),
State = Connection:queue_handshake(Msg, State0),
State#state{diffie_hellman_keys = ECDHKeys};
-
key_exchange(#state{role = server, key_algorithm = psk,
ssl_options = #ssl_options{psk_identity = undefined}} = State, _) ->
State;
@@ -1495,7 +1728,6 @@ key_exchange(#state{role = server, key_algorithm = psk,
ServerRandom,
PrivateKey}),
Connection:queue_handshake(Msg, State0);
-
key_exchange(#state{role = server, key_algorithm = dhe_psk,
ssl_options = #ssl_options{psk_identity = PskIdentityHint},
hashsign_algorithm = HashSignAlgo,
@@ -1517,7 +1749,27 @@ key_exchange(#state{role = server, key_algorithm = dhe_psk,
PrivateKey}),
State = Connection:queue_handshake(Msg, State0),
State#state{diffie_hellman_keys = DHKeys};
-
+key_exchange(#state{role = server, key_algorithm = ecdhe_psk,
+ ssl_options = #ssl_options{psk_identity = PskIdentityHint},
+ hashsign_algorithm = HashSignAlgo,
+ private_key = PrivateKey,
+ session = #session{ecc = ECCCurve},
+ connection_states = ConnectionStates0,
+ negotiated_version = Version
+ } = State0, Connection) ->
+ ECDHKeys = public_key:generate_key(ECCCurve),
+ #{security_parameters := SecParams} =
+ ssl_record:pending_connection_state(ConnectionStates0, read),
+ #security_parameters{client_random = ClientRandom,
+ server_random = ServerRandom} = SecParams,
+ Msg = ssl_handshake:key_exchange(server, ssl:tls_version(Version),
+ {ecdhe_psk,
+ PskIdentityHint, ECDHKeys,
+ HashSignAlgo, ClientRandom,
+ ServerRandom,
+ PrivateKey}),
+ State = Connection:queue_handshake(Msg, State0),
+ State#state{diffie_hellman_keys = ECDHKeys};
key_exchange(#state{role = server, key_algorithm = rsa_psk,
ssl_options = #ssl_options{psk_identity = undefined}} = State, _) ->
State;
@@ -1538,7 +1790,6 @@ key_exchange(#state{role = server, key_algorithm = rsa_psk,
ServerRandom,
PrivateKey}),
Connection:queue_handshake(Msg, State0);
-
key_exchange(#state{role = server, key_algorithm = Algo,
ssl_options = #ssl_options{user_lookup_fun = LookupFun},
hashsign_algorithm = HashSignAlgo,
@@ -1569,7 +1820,6 @@ key_exchange(#state{role = server, key_algorithm = Algo,
State = Connection:queue_handshake(Msg, State0),
State#state{srp_params = SrpParams,
srp_keys = Keys};
-
key_exchange(#state{role = client,
key_algorithm = rsa,
public_key_info = PublicKeyInfo,
@@ -1577,7 +1827,6 @@ key_exchange(#state{role = client,
premaster_secret = PremasterSecret} = State0, Connection) ->
Msg = rsa_key_exchange(ssl:tls_version(Version), PremasterSecret, PublicKeyInfo),
Connection:queue_handshake(Msg, State0);
-
key_exchange(#state{role = client,
key_algorithm = Algorithm,
negotiated_version = Version,
@@ -1592,13 +1841,13 @@ key_exchange(#state{role = client,
key_exchange(#state{role = client,
key_algorithm = Algorithm,
negotiated_version = Version,
- diffie_hellman_keys = Keys} = State0, Connection)
+ session = Session,
+ diffie_hellman_keys = #'ECPrivateKey'{parameters = ECCurve} = Key} = State0, Connection)
when Algorithm == ecdhe_ecdsa; Algorithm == ecdhe_rsa;
Algorithm == ecdh_ecdsa; Algorithm == ecdh_rsa;
Algorithm == ecdh_anon ->
- Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {ecdh, Keys}),
- Connection:queue_handshake(Msg, State0);
-
+ Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {ecdh, Key}),
+ Connection:queue_handshake(Msg, State0#state{session = Session#session{ecc = ECCurve}});
key_exchange(#state{role = client,
ssl_options = SslOpts,
key_algorithm = psk,
@@ -1606,7 +1855,6 @@ key_exchange(#state{role = client,
Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version),
{psk, SslOpts#ssl_options.psk_identity}),
Connection:queue_handshake(Msg, State0);
-
key_exchange(#state{role = client,
ssl_options = SslOpts,
key_algorithm = dhe_psk,
@@ -1616,6 +1864,17 @@ key_exchange(#state{role = client,
{dhe_psk,
SslOpts#ssl_options.psk_identity, DhPubKey}),
Connection:queue_handshake(Msg, State0);
+
+key_exchange(#state{role = client,
+ ssl_options = SslOpts,
+ key_algorithm = ecdhe_psk,
+ negotiated_version = Version,
+ diffie_hellman_keys = ECDHKeys} = State0, Connection) ->
+ Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version),
+ {ecdhe_psk,
+ SslOpts#ssl_options.psk_identity, ECDHKeys}),
+ Connection:queue_handshake(Msg, State0);
+
key_exchange(#state{role = client,
ssl_options = SslOpts,
key_algorithm = rsa_psk,
@@ -1626,7 +1885,6 @@ key_exchange(#state{role = client,
Msg = rsa_psk_key_exchange(ssl:tls_version(Version), SslOpts#ssl_options.psk_identity,
PremasterSecret, PublicKeyInfo),
Connection:queue_handshake(Msg, State0);
-
key_exchange(#state{role = client,
key_algorithm = Algorithm,
negotiated_version = Version,
@@ -1671,6 +1929,12 @@ rsa_psk_key_exchange(Version, PskIdentity, PremasterSecret,
rsa_psk_key_exchange(_, _, _, _) ->
throw (?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE, pub_key_is_not_rsa)).
+request_client_cert(#state{key_algorithm = Alg} = State, _)
+ when Alg == dh_anon; Alg == ecdh_anon;
+ Alg == psk; Alg == dhe_psk; Alg == ecdhe_psk; Alg == rsa_psk;
+ Alg == srp_dss; Alg == srp_rsa; Alg == srp_anon ->
+ State;
+
request_client_cert(#state{ssl_options = #ssl_options{verify = verify_peer,
signature_algs = SupportedHashSigns},
connection_states = ConnectionStates0,
@@ -1715,7 +1979,7 @@ finalize_handshake(State0, StateName, Connection) ->
ConnectionStates =
ssl_record:activate_pending_connection_state(ConnectionStates0,
- write),
+ write, Connection),
State2 = State1#state{connection_states = ConnectionStates},
State = next_protocol(State2, Connection),
@@ -1792,6 +2056,18 @@ calculate_secret(#server_dhe_psk_params{
calculate_master_secret(PremasterSecret, State#state{diffie_hellman_keys = Keys},
Connection, certify, certify);
+calculate_secret(#server_ecdhe_psk_params{
+ dh_params = #server_ecdh_params{curve = ECCurve}} = ServerKey,
+ #state{ssl_options = #ssl_options{user_lookup_fun = PSKLookup}} =
+ State=#state{session=Session}, Connection) ->
+ ECDHKeys = public_key:generate_key(ECCurve),
+
+ PremasterSecret = ssl_handshake:premaster_secret(ServerKey, ECDHKeys, PSKLookup),
+ calculate_master_secret(PremasterSecret,
+ State#state{diffie_hellman_keys = ECDHKeys,
+ session = Session#session{ecc = ECCurve}},
+ Connection, certify, certify);
+
calculate_secret(#server_srp_params{srp_n = Prime, srp_g = Generator} = ServerKey,
#state{ssl_options = #ssl_options{srp_identity = SRPId}} = State,
Connection) ->
@@ -1821,22 +2097,24 @@ generate_srp_server_keys(_SrpParams, 10) ->
generate_srp_server_keys(SrpParams =
#srp_user{generator = Generator, prime = Prime,
verifier = Verifier}, N) ->
- case crypto:generate_key(srp, {host, [Verifier, Generator, Prime, '6a']}) of
- error ->
- generate_srp_server_keys(SrpParams, N+1);
+ try crypto:generate_key(srp, {host, [Verifier, Generator, Prime, '6a']}) of
Keys ->
Keys
+ catch
+ error:_ ->
+ generate_srp_server_keys(SrpParams, N+1)
end.
generate_srp_client_keys(_Generator, _Prime, 10) ->
?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER);
generate_srp_client_keys(Generator, Prime, N) ->
- case crypto:generate_key(srp, {user, [Generator, Prime, '6a']}) of
- error ->
- generate_srp_client_keys(Generator, Prime, N+1);
+ try crypto:generate_key(srp, {user, [Generator, Prime, '6a']}) of
Keys ->
Keys
+ catch
+ error:_ ->
+ generate_srp_client_keys(Generator, Prime, N+1)
end.
handle_srp_identity(Username, {Fun, UserState}) ->
@@ -1876,6 +2154,7 @@ is_anonymous(Algo) when Algo == dh_anon;
Algo == ecdh_anon;
Algo == psk;
Algo == dhe_psk;
+ Algo == ecdhe_psk;
Algo == rsa_psk;
Algo == srp_anon ->
true;
@@ -1996,10 +2275,7 @@ set_socket_opts(_,_, _, [{active, _} = Opt| _], SockOpts, _) ->
set_socket_opts(ConnectionCb, Transport, Socket, [Opt | Opts], SockOpts, Other) ->
set_socket_opts(ConnectionCb, Transport, Socket, Opts, SockOpts, [Opt | Other]).
-start_or_recv_cancel_timer(infinity, _RecvFrom) ->
- undefined;
-start_or_recv_cancel_timer(Timeout, RecvFrom) ->
- erlang:send_after(Timeout, self(), {cancel_start_or_recv, RecvFrom}).
+
hibernate_after(connection = StateName,
#state{ssl_options=#ssl_options{hibernate_after = HibernateAfter}} = State,
@@ -2007,19 +2283,31 @@ hibernate_after(connection = StateName,
{next_state, StateName, State, [{timeout, HibernateAfter, hibernate} | Actions]};
hibernate_after(StateName, State, Actions) ->
{next_state, StateName, State, Actions}.
-
-terminate_alert(normal, Version, ConnectionStates, Connection) ->
- Connection:encode_alert(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY),
- Version, ConnectionStates);
-terminate_alert({Reason, _}, Version, ConnectionStates, Connection) when Reason == close;
- Reason == shutdown ->
- Connection:encode_alert(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY),
- Version, ConnectionStates);
-
-terminate_alert(_, Version, ConnectionStates, Connection) ->
- {BinAlert, _} = Connection:encode_alert(?ALERT_REC(?FATAL, ?INTERNAL_ERROR),
- Version, ConnectionStates),
- BinAlert.
+
+map_extensions(#hello_extensions{renegotiation_info = RenegotiationInfo,
+ signature_algs = SigAlg,
+ alpn = Alpn,
+ next_protocol_negotiation = Next,
+ srp = SRP,
+ ec_point_formats = ECPointFmt,
+ elliptic_curves = ECCCurves,
+ sni = SNI}) ->
+ #{renegotiation_info => ssl_handshake:extension_value(RenegotiationInfo),
+ signature_algs => ssl_handshake:extension_value(SigAlg),
+ alpn => ssl_handshake:extension_value(Alpn),
+ srp => ssl_handshake:extension_value(SRP),
+ next_protocol => ssl_handshake:extension_value(Next),
+ ec_point_formats => ssl_handshake:extension_value(ECPointFmt),
+ elliptic_curves => ssl_handshake:extension_value(ECCCurves),
+ sni => ssl_handshake:extension_value(SNI)}.
+
+terminate_alert(normal) ->
+ ?ALERT_REC(?WARNING, ?CLOSE_NOTIFY);
+terminate_alert({Reason, _}) when Reason == close;
+ Reason == shutdown ->
+ ?ALERT_REC(?WARNING, ?CLOSE_NOTIFY);
+terminate_alert(_) ->
+ ?ALERT_REC(?FATAL, ?INTERNAL_ERROR).
handle_trusted_certs_db(#state{ssl_options =
#ssl_options{cacertfile = <<>>, cacerts = []}}) ->
@@ -2049,16 +2337,15 @@ prepare_connection(#state{renegotiation = Renegotiate,
start_or_recv_from = RecvFrom} = State0, Connection)
when Renegotiate =/= {false, first},
RecvFrom =/= undefined ->
- State1 = Connection:reinit_handshake_data(State0),
+ State1 = Connection:reinit(State0),
{Record, State} = Connection:next_record(State1),
{Record, ack_connection(State)};
prepare_connection(State0, Connection) ->
- State = Connection:reinit_handshake_data(State0),
+ State = Connection:reinit(State0),
{no_record, ack_connection(State)}.
-ack_connection(#state{renegotiation = {true, Initiater}} = State)
- when Initiater == internal;
- Initiater == peer ->
+ack_connection(#state{renegotiation = {true, Initiater}} = State) when Initiater == peer;
+ Initiater == internal ->
State#state{renegotiation = undefined};
ack_connection(#state{renegotiation = {true, From}} = State) ->
gen_statem:reply(From, ok),
@@ -2079,6 +2366,11 @@ cancel_timer(Timer) ->
erlang:cancel_timer(Timer),
ok.
+session_handle_params(#server_ecdh_params{curve = ECCurve}, Session) ->
+ Session#session{ecc = ECCurve};
+session_handle_params(_, Session) ->
+ Session.
+
register_session(client, Host, Port, #session{is_resumable = new} = Session0) ->
Session = Session0#session{is_resumable = true},
ssl_manager:register_session(Host, Port, Session),
@@ -2090,6 +2382,11 @@ register_session(server, _, Port, #session{is_resumable = new} = Session0) ->
register_session(_, _, _, Session) ->
Session. %% Already registered
+host_id(client, _Host, #ssl_options{server_name_indication = Hostname}) when is_list(Hostname) ->
+ Hostname;
+host_id(_, Host, _) ->
+ Host.
+
handle_new_session(NewId, CipherSuite, Compression,
#state{session = Session0,
protocol_cb = Connection} = State0) ->
@@ -2154,7 +2451,7 @@ ssl_options_list([ciphers = Key | Keys], [Value | Values], Acc) ->
ssl_options_list(Keys, Values,
[{Key, lists:map(
fun(Suite) ->
- ssl_cipher:erl_suite_definition(Suite)
+ ssl_cipher_format:suite_definition(Suite)
end, Value)}
| Acc]);
ssl_options_list([Key | Keys], [Value | Values], Acc) ->
@@ -2173,8 +2470,8 @@ handle_active_option(_, connection = StateName0, To, Reply, #state{protocol_cb =
hibernate_after(StateName, State, [{reply, To, Reply}]);
{next_state, StateName, State, Actions} ->
hibernate_after(StateName, State, [{reply, To, Reply} | Actions]);
- {stop, Reason, State} ->
- {stop, Reason, State}
+ {stop, _, _} = Stop ->
+ Stop
end;
handle_active_option(_, StateName, To, Reply, #state{user_data_buffer = <<>>} = State) ->
%% Active once already set
@@ -2183,8 +2480,8 @@ handle_active_option(_, StateName, To, Reply, #state{user_data_buffer = <<>>} =
%% user_data_buffer =/= <<>>
handle_active_option(_, StateName0, To, Reply, #state{protocol_cb = Connection} = State0) ->
case read_application_data(<<>>, State0) of
- {stop, Reason, State} ->
- {stop, Reason, State};
+ {stop, _, _} = Stop ->
+ Stop;
{Record, State1} ->
%% Note: Renogotiation may cause StateName0 =/= StateName
case Connection:next_event(StateName0, Record, State1) of
@@ -2197,35 +2494,6 @@ handle_active_option(_, StateName0, To, Reply, #state{protocol_cb = Connection}
end
end.
-encode_packet(Data, #socket_options{packet=Packet}) ->
- case Packet of
- 1 -> encode_size_packet(Data, 8, (1 bsl 8) - 1);
- 2 -> encode_size_packet(Data, 16, (1 bsl 16) - 1);
- 4 -> encode_size_packet(Data, 32, (1 bsl 32) - 1);
- _ -> Data
- end.
-
-encode_size_packet(Bin, Size, Max) ->
- Len = erlang:byte_size(Bin),
- case Len > Max of
- true -> throw({error, {badarg, {packet_to_large, Len, Max}}});
- false -> <<Len:Size, Bin/binary>>
- end.
-
-time_to_renegotiate(_Data,
- #{current_write := #{sequence_number := Num}},
- RenegotiateAt) ->
-
- %% We could do test:
- %% is_time_to_renegotiate((erlang:byte_size(_Data) div ?MAX_PLAIN_TEXT_LENGTH) + 1, RenegotiateAt),
- %% but we chose to have a some what lower renegotiateAt and a much cheaper test
- is_time_to_renegotiate(Num, RenegotiateAt).
-
-is_time_to_renegotiate(N, M) when N < M->
- false;
-is_time_to_renegotiate(_,_) ->
- true.
-
%% Picks ClientData
get_data(_, _, <<>>) ->
@@ -2272,9 +2540,10 @@ decode_packet(Type, Buffer, PacketOpts) ->
%% Note that if the user has explicitly configured the socket to expect
%% HTTP headers using the {packet, httph} option, we don't do any automatic
%% switching of states.
-deliver_app_data(Transport, Socket, SOpts = #socket_options{active=Active, packet=Type},
+deliver_app_data(CPids, Transport, Socket, SOpts = #socket_options{active=Active, packet=Type},
Data, Pid, From, Tracker, Connection) ->
- send_or_reply(Active, Pid, From, format_reply(Transport, Socket, SOpts, Data, Tracker, Connection)),
+ send_or_reply(Active, Pid, From,
+ format_reply(CPids, Transport, Socket, SOpts, Data, Tracker, Connection)),
SO = case Data of
{P, _, _, _} when ((P =:= http_request) or (P =:= http_response)),
((Type =:= http) or (Type =:= http_bin)) ->
@@ -2293,21 +2562,24 @@ deliver_app_data(Transport, Socket, SOpts = #socket_options{active=Active, packe
SO
end.
-format_reply(_, _,#socket_options{active = false, mode = Mode, packet = Packet,
+format_reply(_, _, _,#socket_options{active = false, mode = Mode, packet = Packet,
header = Header}, Data, _, _) ->
{ok, do_format_reply(Mode, Packet, Header, Data)};
-format_reply(Transport, Socket, #socket_options{active = _, mode = Mode, packet = Packet,
+format_reply(CPids, Transport, Socket, #socket_options{active = _, mode = Mode, packet = Packet,
header = Header}, Data, Tracker, Connection) ->
- {ssl, Connection:socket(self(), Transport, Socket, Connection, Tracker),
+ {ssl, Connection:socket(CPids, Transport, Socket, Connection, Tracker),
do_format_reply(Mode, Packet, Header, Data)}.
-deliver_packet_error(Transport, Socket, SO= #socket_options{active = Active}, Data, Pid, From, Tracker, Connection) ->
- send_or_reply(Active, Pid, From, format_packet_error(Transport, Socket, SO, Data, Tracker, Connection)).
+deliver_packet_error(CPids, Transport, Socket,
+ SO= #socket_options{active = Active}, Data, Pid, From, Tracker, Connection) ->
+ send_or_reply(Active, Pid, From, format_packet_error(CPids,
+ Transport, Socket, SO, Data, Tracker, Connection)).
-format_packet_error(_, _,#socket_options{active = false, mode = Mode}, Data, _, _) ->
+format_packet_error(_, _, _,#socket_options{active = false, mode = Mode}, Data, _, _) ->
{error, {invalid_packet, do_format_reply(Mode, raw, 0, Data)}};
-format_packet_error(Transport, Socket, #socket_options{active = _, mode = Mode}, Data, Tracker, Connection) ->
- {ssl_error, Connection:socket(self(), Transport, Socket, Connection, Tracker),
+format_packet_error(CPids, Transport, Socket, #socket_options{active = _, mode = Mode},
+ Data, Tracker, Connection) ->
+ {ssl_error, Connection:socket(CPids, Transport, Socket, Connection, Tracker),
{invalid_packet, do_format_reply(Mode, raw, 0, Data)}}.
do_format_reply(binary, _, N, Data) when N > 0 -> % Header mode
@@ -2342,78 +2614,44 @@ send_or_reply(_, Pid, _From, Data) ->
send_user(Pid, Data).
send_user(Pid, Msg) ->
- Pid ! Msg.
+ Pid ! Msg,
+ ok.
-alert_user(Transport, Tracker, Socket, connection, Opts, Pid, From, Alert, Role, Connection) ->
- alert_user(Transport, Tracker, Socket, Opts#socket_options.active, Pid, From, Alert, Role, Connection);
-alert_user(Transport, Tracker, Socket,_, _, _, From, Alert, Role, Connection) ->
- alert_user(Transport, Tracker, Socket, From, Alert, Role, Connection).
+alert_user(Pids, Transport, Tracker, Socket, connection, Opts, Pid, From, Alert, Role, Connection) ->
+ alert_user(Pids, Transport, Tracker, Socket, Opts#socket_options.active, Pid, From, Alert, Role, Connection);
+alert_user(Pids, Transport, Tracker, Socket,_, _, _, From, Alert, Role, Connection) ->
+ alert_user(Pids, Transport, Tracker, Socket, From, Alert, Role, Connection).
-alert_user(Transport, Tracker, Socket, From, Alert, Role, Connection) ->
- alert_user(Transport, Tracker, Socket, false, no_pid, From, Alert, Role, Connection).
+alert_user(Pids, Transport, Tracker, Socket, From, Alert, Role, Connection) ->
+ alert_user(Pids, Transport, Tracker, Socket, false, no_pid, From, Alert, Role, Connection).
-alert_user(_, _, _, false = Active, Pid, From, Alert, Role, _) when From =/= undefined ->
+alert_user(_, _, _, _, false = Active, Pid, From, Alert, Role, _) when From =/= undefined ->
%% If there is an outstanding ssl_accept | recv
%% From will be defined and send_or_reply will
%% send the appropriate error message.
ReasonCode = ssl_alert:reason_code(Alert, Role),
send_or_reply(Active, Pid, From, {error, ReasonCode});
-alert_user(Transport, Tracker, Socket, Active, Pid, From, Alert, Role, Connection) ->
+alert_user(Pids, Transport, Tracker, Socket, Active, Pid, From, Alert, Role, Connection) ->
case ssl_alert:reason_code(Alert, Role) of
closed ->
send_or_reply(Active, Pid, From,
- {ssl_closed, Connection:socket(self(),
+ {ssl_closed, Connection:socket(Pids,
Transport, Socket, Connection, Tracker)});
ReasonCode ->
send_or_reply(Active, Pid, From,
- {ssl_error, Connection:socket(self(),
+ {ssl_error, Connection:socket(Pids,
Transport, Socket, Connection, Tracker), ReasonCode})
end.
-log_alert(true, Info, Alert) ->
+log_alert(true, Role, ProtocolName, StateName, #alert{role = Role} = Alert) ->
+ Txt = ssl_alert:own_alert_txt(Alert),
+ error_logger:info_report(io_lib:format("~s ~p: In state ~p ~s\n", [ProtocolName, Role, StateName, Txt]));
+log_alert(true, Role, ProtocolName, StateName, Alert) ->
Txt = ssl_alert:alert_txt(Alert),
- error_logger:format("SSL: ~p: ~s\n", [Info, Txt]);
-log_alert(false, _, _) ->
+ error_logger:info_report(io_lib:format("~s ~p: In state ~p ~s\n", [ProtocolName, Role, StateName, Txt]));
+log_alert(false, _, _, _, _) ->
ok.
-handle_own_alert(Alert, Version, StateName,
- #state{transport_cb = Transport,
- socket = Socket,
- protocol_cb = Connection,
- connection_states = ConnectionStates,
- ssl_options = SslOpts} = State) ->
- try %% Try to tell the other side
- {BinMsg, _} =
- Connection:encode_alert(Alert, Version, ConnectionStates),
- Connection:send(Transport, Socket, BinMsg)
- catch _:_ -> %% Can crash if we are in a uninitialized state
- ignore
- end,
- try %% Try to tell the local user
- log_alert(SslOpts#ssl_options.log_alert, StateName, Alert),
- handle_normal_shutdown(Alert,StateName, State)
- catch _:_ ->
- ok
- end,
- {stop, {shutdown, own_alert}}.
-
-handle_normal_shutdown(Alert, _, #state{socket = Socket,
- transport_cb = Transport,
- protocol_cb = Connection,
- start_or_recv_from = StartFrom,
- tracker = Tracker,
- role = Role, renegotiation = {false, first}}) ->
- alert_user(Transport, Tracker,Socket, StartFrom, Alert, Role, Connection);
-
-handle_normal_shutdown(Alert, StateName, #state{socket = Socket,
- socket_options = Opts,
- transport_cb = Transport,
- protocol_cb = Connection,
- user_application = {_Mon, Pid},
- tracker = Tracker,
- start_or_recv_from = RecvFrom, role = Role}) ->
- alert_user(Transport, Tracker, Socket, StateName, Opts, Pid, RecvFrom, Alert, Role, Connection).
-
invalidate_session(client, Host, Port, Session) ->
ssl_manager:invalidate_session(Host, Port, Session);
invalidate_session(server, _, Port, Session) ->
@@ -2470,3 +2708,14 @@ new_emulated([], EmOpts) ->
EmOpts;
new_emulated(NewEmOpts, _) ->
NewEmOpts.
+
+stop(Reason, State) ->
+ {stop, Reason, State}.
+
+stop_and_reply(Reason, Replies, State) ->
+ {stop_and_reply, Reason, Replies, State}.
+
+is_dist_up(#{dist_handle := Handle}) when Handle =/= undefined ->
+ true;
+is_dist_up(_) ->
+ false.
diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl
index 3e26f67de1..66e3182313 100644
--- a/lib/ssl/src/ssl_connection.hrl
+++ b/lib/ssl/src/ssl_connection.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -44,6 +44,7 @@
host :: string() | inet:ip_address(),
port :: integer(),
socket :: port() | tuple(), %% TODO: dtls socket
+ sender :: pid() | undefined,
ssl_options :: #ssl_options{},
socket_options :: #socket_options{},
connection_states :: ssl_record:connection_states() | secret_printout(),
@@ -57,10 +58,11 @@
session_cache_cb :: atom(),
crl_db :: term(),
negotiated_version :: ssl_record:ssl_version() | 'undefined',
+ client_hello_version :: ssl_record:ssl_version() | 'undefined',
client_certificate_requested = false :: boolean(),
- key_algorithm :: ssl_cipher:key_algo(),
+ key_algorithm :: ssl_cipher_format:key_algo(),
hashsign_algorithm = {undefined, undefined},
- cert_hashsign_algorithm,
+ cert_hashsign_algorithm = {undefined, undefined},
public_key_info :: ssl_handshake:public_key_info() | 'undefined',
private_key :: public_key:private_key() | secret_printout() | 'undefined',
diffie_hellman_params:: #'DHParameter'{} | undefined | secret_printout(),
@@ -73,10 +75,12 @@
cert_db_ref :: certdb_ref() | 'undefined',
bytes_to_read :: undefined | integer(), %% bytes to read in passive mode
user_data_buffer :: undefined | binary() | secret_printout(),
+ erl_dist_data = #{} :: map(),
renegotiation :: undefined | {boolean(), From::term() | internal | peer},
start_or_recv_from :: term(),
timer :: undefined | reference(), % start_or_recive_timer
- %%send_queue :: queue:queue(),
+ %%send_queue :: queue:queue(),
+ hello, %%:: #client_hello{} | #server_hello{},
terminated = false ::boolean(),
allow_renegotiate = true ::boolean(),
expecting_next_protocol_negotiation = false ::boolean(),
@@ -87,11 +91,11 @@
sni_hostname = undefined,
downgrade,
flight_buffer = [] :: list() | map(), %% Buffer of TLS/DTLS records, used during the TLS handshake
- %% to when possible pack more than on TLS record into the
- %% underlaying packet format. Introduced by DTLS - RFC 4347.
- %% The mecahnism is also usefull in TLS although we do not
- %% need to worry about packet loss in TLS. In DTLS we need to track DTLS handshake seqnr
- flight_state = reliable, %% reliable | {retransmit, integer()}| {waiting, ref(), integer()} - last two is used in DTLS over udp.
+ %% to when possible pack more than one TLS record into the
+ %% underlaying packet format. Introduced by DTLS - RFC 4347.
+ %% The mecahnism is also usefull in TLS although we do not
+ %% need to worry about packet loss in TLS. In DTLS we need to track DTLS handshake seqnr
+ flight_state = reliable, %% reliable | {retransmit, integer()}| {waiting, ref(), integer()} - last two is used in DTLS over udp.
protocol_specific = #{} :: map()
}).
-define(DEFAULT_DIFFIE_HELLMAN_PARAMS,
diff --git a/lib/ssl/src/ssl_connection_sup.erl b/lib/ssl/src/ssl_connection_sup.erl
index 1a1f43e683..934dd39df5 100644
--- a/lib/ssl/src/ssl_connection_sup.erl
+++ b/lib/ssl/src/ssl_connection_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -51,12 +51,12 @@ init([]) ->
ListenOptionsTracker = listen_options_tracker_child_spec(),
DTLSConnetionManager = dtls_connection_manager_child_spec(),
- DTLSUdpListeners = dtls_udp_listeners_spec(),
+ DTLSListeners = dtls_listeners_spec(),
{ok, {{one_for_one, 10, 3600}, [TLSConnetionManager,
ListenOptionsTracker,
DTLSConnetionManager,
- DTLSUdpListeners
+ DTLSListeners
]}}.
@@ -91,9 +91,9 @@ listen_options_tracker_child_spec() ->
Type = supervisor,
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
-dtls_udp_listeners_spec() ->
- Name = dtls_udp_listener,
- StartFunc = {dtls_udp_sup, start_link, []},
+dtls_listeners_spec() ->
+ Name = dtls_listener,
+ StartFunc = {dtls_listener_sup, start_link, []},
Restart = permanent,
Shutdown = 4000,
Modules = [],
diff --git a/lib/ssl/src/ssl_crl_cache.erl b/lib/ssl/src/ssl_crl_cache.erl
index 86c0207515..9c1af86eeb 100644
--- a/lib/ssl/src/ssl_crl_cache.erl
+++ b/lib/ssl/src/ssl_crl_cache.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -92,9 +92,9 @@ delete({der, CRLs}) ->
ssl_manager:delete_crls({?NO_DIST_POINT, CRLs});
delete(URI) ->
- case http_uri:parse(URI) of
- {ok, {http, _, _ , _, Path,_}} ->
- ssl_manager:delete_crls(string:strip(Path, left, $/));
+ case uri_string:normalize(URI, [return_map]) of
+ #{scheme := "http", path := Path} ->
+ ssl_manager:delete_crls(string:trim(Path, leading, "/"));
_ ->
{error, {only_http_distribution_points_supported, URI}}
end.
@@ -103,9 +103,9 @@ delete(URI) ->
%%% Internal functions
%%--------------------------------------------------------------------
do_insert(URI, CRLs) ->
- case http_uri:parse(URI) of
- {ok, {http, _, _ , _, Path,_}} ->
- ssl_manager:insert_crls(string:strip(Path, left, $/), CRLs);
+ case uri_string:normalize(URI, [return_map]) of
+ #{scheme := "http", path := Path} ->
+ ssl_manager:insert_crls(string:trim(Path, leading, "/"), CRLs);
_ ->
{error, {only_http_distribution_points_supported, URI}}
end.
@@ -161,8 +161,8 @@ http_get(URL, Rest, CRLDbInfo, Timeout) ->
cache_lookup(_, undefined) ->
[];
cache_lookup(URL, {{Cache, _}, _}) ->
- {ok, {_, _, _ , _, Path,_}} = http_uri:parse(URL),
- case ssl_pkix_db:lookup(string:strip(Path, left, $/), Cache) of
+ #{path := Path} = uri_string:normalize(URL, [return_map]),
+ case ssl_pkix_db:lookup(string:trim(Path, leading, "/"), Cache) of
undefined ->
[];
CRLs ->
diff --git a/lib/ssl/src/ssl_dist_sup.erl b/lib/ssl/src/ssl_dist_sup.erl
index 690b896919..bea67935d8 100644
--- a/lib/ssl/src/ssl_dist_sup.erl
+++ b/lib/ssl/src/ssl_dist_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,6 +30,9 @@
%% Supervisor callback
-export([init/1]).
+%% Debug
+-export([consult/1]).
+
%%%=========================================================================
%%% API
%%%=========================================================================
@@ -37,7 +40,18 @@
-spec start_link() -> {ok, pid()} | ignore | {error, term()}.
start_link() ->
- supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+ case init:get_argument(ssl_dist_optfile) of
+ {ok, [File]} ->
+ DistOpts = consult(File),
+ TabOpts = [set, protected, named_table],
+ Tab = ets:new(ssl_dist_opts, TabOpts),
+ true = ets:insert(Tab, DistOpts),
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []);
+ {ok, BadArg} ->
+ error({bad_ssl_dist_optfile, BadArg});
+ error ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, [])
+ end.
%%%=========================================================================
%%% Supervisor callback
@@ -46,8 +60,7 @@ start_link() ->
init([]) ->
AdminSup = ssl_admin_child_spec(),
ConnectionSup = ssl_connection_sup(),
- ProxyServer = proxy_server_child_spec(),
- {ok, {{one_for_all, 10, 3600}, [AdminSup, ProxyServer, ConnectionSup]}}.
+ {ok, {{one_for_all, 10, 3600}, [AdminSup, ConnectionSup]}}.
%%--------------------------------------------------------------------
%%% Internal functions
@@ -70,11 +83,51 @@ ssl_connection_sup() ->
Type = supervisor,
{Name, StartFunc, Restart, Shutdown, Type, Modules}.
-proxy_server_child_spec() ->
- Name = ssl_tls_dist_proxy,
- StartFunc = {ssl_tls_dist_proxy, start_link, []},
- Restart = permanent,
- Shutdown = 4000,
- Modules = [ssl_tls_dist_proxy],
- Type = worker,
- {Name, StartFunc, Restart, Shutdown, Type, Modules}.
+consult(File) ->
+ case erl_prim_loader:get_file(File) of
+ {ok, Binary, _FullName} ->
+ Encoding =
+ case epp:read_encoding_from_binary(Binary) of
+ none -> latin1;
+ Enc -> Enc
+ end,
+ case unicode:characters_to_list(Binary, Encoding) of
+ {error, _String, Rest} ->
+ error(
+ {bad_ssl_dist_optfile, {encoding_error, Rest}});
+ {incomplete, _String, Rest} ->
+ error(
+ {bad_ssl_dist_optfile, {encoding_incomplete, Rest}});
+ String when is_list(String) ->
+ consult_string(String)
+ end;
+ error ->
+ error({bad_ssl_dist_optfile, File})
+ end.
+
+consult_string(String) ->
+ case erl_scan:string(String) of
+ {error, Info, Location} ->
+ error({bad_ssl_dist_optfile, {scan_error, Info, Location}});
+ {ok, Tokens, _EndLocation} ->
+ consult_tokens(Tokens)
+ end.
+
+consult_tokens(Tokens) ->
+ case erl_parse:parse_exprs(Tokens) of
+ {error, Info} ->
+ error({bad_ssl_dist_optfile, {parse_error, Info}});
+ {ok, [Expr]} ->
+ consult_expr(Expr);
+ {ok, Other} ->
+ error({bad_ssl_dist_optfile, {parse_error, Other}})
+ end.
+
+consult_expr(Expr) ->
+ {value, Value, Bs} = erl_eval:expr(Expr, erl_eval:new_bindings()),
+ case erl_eval:bindings(Bs) of
+ [] ->
+ Value;
+ Other ->
+ error({bad_ssl_dist_optfile, {bindings, Other}})
+ end.
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 3cf466e78f..dc89fb0029 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -44,46 +44,44 @@
#client_key_exchange{} | #finished{} | #certificate_verify{} |
#hello_request{} | #next_protocol{}.
-%% Handshake messages
+%% Create handshake messages
-export([hello_request/0, server_hello/4, server_hello_done/0,
- certificate/4, certificate_request/5, key_exchange/3,
+ certificate/4, client_certificate_verify/6, certificate_request/5, key_exchange/3,
finished/5, next_protocol/1]).
%% Handle handshake messages
--export([certify/6, client_certificate_verify/6, certificate_verify/6, verify_signature/5,
+-export([certify/7, certificate_verify/6, verify_signature/5,
master_secret/4, server_key_exchange_hash/2, verify_connection/6,
- init_handshake_history/0, update_handshake_history/3, verify_server_key/5
+ init_handshake_history/0, update_handshake_history/2, verify_server_key/5,
+ select_version/3, extension_value/1
]).
-%% Encode/Decode
+%% Encode
-export([encode_handshake/2, encode_hello_extensions/1,
- encode_client_protocol_negotiation/2, encode_protocols_advertised_on_server/1,
- decode_handshake/3, decode_hello_extensions/1,
+ encode_client_protocol_negotiation/2, encode_protocols_advertised_on_server/1]).
+%% Decode
+-export([decode_handshake/3, decode_hello_extensions/1,
decode_server_key/3, decode_client_key/3,
decode_suites/2
]).
%% Cipher suites handling
--export([available_suites/2, available_signature_algs/2, cipher_suites/2,
- select_session/11, supported_ecc/1, available_signature_algs/4]).
+-export([available_suites/2, available_signature_algs/2, available_signature_algs/4,
+ cipher_suites/3, prf/6, select_session/11, supported_ecc/1,
+ premaster_secret/2, premaster_secret/3, premaster_secret/4]).
%% Extensions handling
-export([client_hello_extensions/5,
handle_client_hello_extensions/9, %% Returns server hello extensions
- handle_server_hello_extensions/9, select_curve/2, select_curve/3
+ handle_server_hello_extensions/9, select_curve/2, select_curve/3,
+ select_hashsign/4, select_hashsign/5,
+ select_hashsign_algs/3
]).
-%% MISC
--export([select_version/3, prf/6, select_hashsign/4, select_hashsign/5,
- select_hashsign_algs/3,
- premaster_secret/2, premaster_secret/3, premaster_secret/4]).
-
%%====================================================================
-%% Internal application API
+%% Create handshake messages
%%====================================================================
-%% ---------- Create handshake messages ----------
-
%%--------------------------------------------------------------------
-spec hello_request() -> #hello_request{}.
%%
@@ -119,31 +117,6 @@ server_hello(SessionId, Version, ConnectionStates, Extensions) ->
server_hello_done() ->
#server_hello_done{}.
-client_hello_extensions(Version, CipherSuites,
- #ssl_options{signature_algs = SupportedHashSigns,
- eccs = SupportedECCs} = SslOpts, ConnectionStates, Renegotiation) ->
- {EcPointFormats, EllipticCurves} =
- case advertises_ec_ciphers(lists:map(fun ssl_cipher:suite_definition/1, CipherSuites)) of
- true ->
- client_ecc_extensions(SupportedECCs);
- false ->
- {undefined, undefined}
- end,
- SRP = srp_user(SslOpts),
-
- #hello_extensions{
- renegotiation_info = renegotiation_info(tls_record, client,
- ConnectionStates, Renegotiation),
- srp = SRP,
- signature_algs = available_signature_algs(SupportedHashSigns, Version),
- ec_point_formats = EcPointFormats,
- elliptic_curves = EllipticCurves,
- alpn = encode_alpn(SslOpts#ssl_options.alpn_advertised_protocols, Renegotiation),
- next_protocol_negotiation =
- encode_client_protocol_negotiation(SslOpts#ssl_options.next_protocol_selector,
- Renegotiation),
- sni = sni(SslOpts#ssl_options.server_name_indication)}.
-
%%--------------------------------------------------------------------
-spec certificate(der_cert(), db_handle(), certdb_ref(), client | server) -> #certificate{} | #alert{}.
%%
@@ -166,19 +139,11 @@ certificate(OwnCert, CertDbHandle, CertDbRef, server) ->
case ssl_certificate:certificate_chain(OwnCert, CertDbHandle, CertDbRef) of
{ok, _, Chain} ->
#certificate{asn1_certificates = Chain};
- {error, _} ->
- ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, server_has_no_suitable_certificates)
+ {error, Error} ->
+ ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, {server_has_no_suitable_certificates, Error})
end.
%%--------------------------------------------------------------------
--spec next_protocol(binary()) -> #next_protocol{}.
-%%
-%% Description: Creates a next protocol message
-%%-------------------------------------------------------------------
-next_protocol(SelectedProtocol) ->
- #next_protocol{selected_protocol = SelectedProtocol}.
-
-%%--------------------------------------------------------------------
-spec client_certificate_verify(undefined | der_cert(), binary(),
ssl_record:ssl_version(), term(), public_key:private_key(),
ssl_handshake_history()) ->
@@ -204,14 +169,14 @@ client_certificate_verify(OwnCert, MasterSecret, Version,
end.
%%--------------------------------------------------------------------
--spec certificate_request(ssl_cipher:cipher_suite(), db_handle(),
+-spec certificate_request(ssl_cipher_format:cipher_suite(), db_handle(),
certdb_ref(), #hash_sign_algos{}, ssl_record:ssl_version()) ->
#certificate_request{}.
%%
%% Description: Creates a certificate_request message, called by the server.
%%--------------------------------------------------------------------
certificate_request(CipherSuite, CertDbHandle, CertDbRef, HashSigns, Version) ->
- Types = certificate_types(ssl_cipher:suite_definition(CipherSuite), Version),
+ Types = certificate_types(ssl_cipher_format:suite_definition(CipherSuite), Version),
Authorities = certificate_authorities(CertDbHandle, CertDbRef),
#certificate_request{
certificate_types = Types,
@@ -224,11 +189,18 @@ certificate_request(CipherSuite, CertDbHandle, CertDbRef, HashSigns, Version) ->
{dh, binary()} |
{dh, {binary(), binary()}, #'DHParameter'{}, {HashAlgo::atom(), SignAlgo::atom()},
binary(), binary(), public_key:private_key()} |
+ {ecdh, _, _, _, _, _} |
{ecdh, #'ECPrivateKey'{}} |
+ {psk, _, _, _, _, _} |
{psk, binary()} |
+ {dhe_psk, _, _, _, _, _, _, _} |
{dhe_psk, binary(), binary()} |
+ {ecdhe_psk, _, _, _, _, _, _} |
+ {ecdhe_psk, binary(), #'ECPrivateKey'{}} |
{srp, {binary(), binary()}, #srp_user{}, {HashAlgo::atom(), SignAlgo::atom()},
- binary(), binary(), public_key:private_key()}) ->
+ binary(), binary(), public_key:private_key()} |
+ {srp, _} |
+ {psk_premaster_secret, _, _, _}) ->
#client_key_exchange{} | #server_key_exchange{}.
%%
@@ -264,6 +236,13 @@ key_exchange(client, _Version, {dhe_psk, Identity, PublicKey}) ->
dh_public = PublicKey}
};
+key_exchange(client, _Version, {ecdhe_psk, Identity, #'ECPrivateKey'{publicKey = ECPublicKey}}) ->
+ #client_key_exchange{
+ exchange_keys = #client_ecdhe_psk_identity{
+ identity = Identity,
+ dh_public = ECPublicKey}
+ };
+
key_exchange(client, _Version, {psk_premaster_secret, PskIdentity, Secret, {_, PublicKey, _}}) ->
EncPremasterSecret =
encrypted_premaster_secret(Secret, PublicKey),
@@ -310,6 +289,16 @@ key_exchange(server, Version, {dhe_psk, PskIdentityHint, {PublicKey, _},
enc_server_key_exchange(Version, ServerEDHPSKParams,
HashSign, ClientRandom, ServerRandom, PrivateKey);
+key_exchange(server, Version, {ecdhe_psk, PskIdentityHint,
+ #'ECPrivateKey'{publicKey = ECPublicKey,
+ parameters = ECCurve},
+ HashSign, ClientRandom, ServerRandom, PrivateKey}) ->
+ ServerECDHEPSKParams = #server_ecdhe_psk_params{
+ hint = PskIdentityHint,
+ dh_params = #server_ecdh_params{curve = ECCurve, public = ECPublicKey}},
+ enc_server_key_exchange(Version, ServerECDHEPSKParams, HashSign,
+ ClientRandom, ServerRandom, PrivateKey);
+
key_exchange(server, Version, {srp, {PublicKey, _},
#srp_user{generator = Generator, prime = Prime,
salt = Salt},
@@ -328,23 +317,52 @@ key_exchange(server, Version, {srp, {PublicKey, _},
finished(Version, Role, PrfAlgo, MasterSecret, {Handshake, _}) -> % use the current handshake
#finished{verify_data =
calc_finished(Version, Role, PrfAlgo, MasterSecret, Handshake)}.
+%%--------------------------------------------------------------------
+-spec next_protocol(binary()) -> #next_protocol{}.
+%%
+%% Description: Creates a next protocol message
+%%-------------------------------------------------------------------
+next_protocol(SelectedProtocol) ->
+ #next_protocol{selected_protocol = SelectedProtocol}.
-%% ---------- Handle handshake messages ----------
-
-verify_server_key(#server_key_params{params_bin = EncParams,
- signature = Signature},
- HashSign = {HashAlgo, _},
- ConnectionStates, Version, PubKeyInfo) ->
- #{security_parameters := SecParams} =
- ssl_record:pending_connection_state(ConnectionStates, read),
- #security_parameters{client_random = ClientRandom,
- server_random = ServerRandom} = SecParams,
- Hash = server_key_exchange_hash(HashAlgo,
- <<ClientRandom/binary,
- ServerRandom/binary,
- EncParams/binary>>),
- verify_signature(Version, Hash, HashSign, Signature, PubKeyInfo).
+%%====================================================================
+%% Handle handshake messages
+%%====================================================================
+%%--------------------------------------------------------------------
+-spec certify(#certificate{}, db_handle(), certdb_ref(), #ssl_options{}, term(),
+ client | server, inet:hostname() | inet:ip_address()) -> {der_cert(), public_key_info()} | #alert{}.
+%%
+%% Description: Handles a certificate handshake message
+%%--------------------------------------------------------------------
+certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
+ Opts, CRLDbHandle, Role, Host) ->
+ ServerName = server_name(Opts#ssl_options.server_name_indication, Host, Role),
+ [PeerCert | ChainCerts ] = ASN1Certs,
+ try
+ {TrustedCert, CertPath} =
+ ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbHandle, CertDbRef,
+ Opts#ssl_options.partial_chain),
+ ValidationFunAndState = validation_fun_and_state(Opts#ssl_options.verify_fun, Role,
+ CertDbHandle, CertDbRef, ServerName,
+ Opts#ssl_options.customize_hostname_check,
+ Opts#ssl_options.crl_check, CRLDbHandle, CertPath),
+ Options = [{max_path_length, Opts#ssl_options.depth},
+ {verify_fun, ValidationFunAndState}],
+ case public_key:pkix_path_validation(TrustedCert, CertPath, Options) of
+ {ok, {PublicKeyInfo,_}} ->
+ {PeerCert, PublicKeyInfo};
+ {error, Reason} ->
+ handle_path_validation_error(Reason, PeerCert, ChainCerts, Opts, Options,
+ CertDbHandle, CertDbRef)
+ end
+ catch
+ error:{badmatch,{asn1, Asn1Reason}} ->
+ %% ASN-1 decode of certificate somehow failed
+ ?ALERT_REC(?FATAL, ?CERTIFICATE_UNKNOWN, {failed_to_decode_certificate, Asn1Reason});
+ error:OtherReason ->
+ ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, {unexpected_error, OtherReason})
+ end.
%%--------------------------------------------------------------------
-spec certificate_verify(binary(), public_key_info(), ssl_record:ssl_version(), term(),
binary(), ssl_handshake_history()) -> valid | #alert{}.
@@ -386,41 +404,55 @@ verify_signature(_, Hash, {HashAlgo, _SignAlg}, Signature,
{?'id-ecPublicKey', PublicKey, PublicKeyParams}) ->
public_key:verify({digest, Hash}, HashAlgo, Signature, {PublicKey, PublicKeyParams}).
-
%%--------------------------------------------------------------------
--spec certify(#certificate{}, db_handle(), certdb_ref(), #ssl_options{}, term(),
- client | server) -> {der_cert(), public_key_info()} | #alert{}.
+-spec master_secret(ssl_record:ssl_version(), #session{} | binary(), ssl_record:connection_states(),
+ client | server) -> {binary(), ssl_record:connection_states()} | #alert{}.
%%
-%% Description: Handles a certificate handshake message
-%%--------------------------------------------------------------------
-certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
- Opts, CRLDbHandle, Role) ->
+%% Description: Sets or calculates the master secret and calculate keys,
+%% updating the pending connection states. The Mastersecret and the update
+%% connection states are returned or an alert if the calculation fails.
+%%-------------------------------------------------------------------
+master_secret(Version, #session{master_secret = Mastersecret},
+ ConnectionStates, Role) ->
+ #{security_parameters := SecParams} =
+ ssl_record:pending_connection_state(ConnectionStates, read),
+ try master_secret(Version, Mastersecret, SecParams,
+ ConnectionStates, Role)
+ catch
+ exit:_ ->
+ ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, key_calculation_failure)
+ end;
- [PeerCert | _] = ASN1Certs,
- try
- {TrustedCert, CertPath} =
- ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbHandle, CertDbRef,
- Opts#ssl_options.partial_chain),
- ValidationFunAndState = validation_fun_and_state(Opts#ssl_options.verify_fun, Role,
- CertDbHandle, CertDbRef,
- Opts#ssl_options.server_name_indication,
- Opts#ssl_options.crl_check, CRLDbHandle, CertPath),
- case public_key:pkix_path_validation(TrustedCert,
- CertPath,
- [{max_path_length, Opts#ssl_options.depth},
- {verify_fun, ValidationFunAndState}]) of
- {ok, {PublicKeyInfo,_}} ->
- {PeerCert, PublicKeyInfo};
- {error, Reason} ->
- path_validation_alert(Reason)
- end
+master_secret(Version, PremasterSecret, ConnectionStates, Role) ->
+ #{security_parameters := SecParams} =
+ ssl_record:pending_connection_state(ConnectionStates, read),
+
+ #security_parameters{prf_algorithm = PrfAlgo,
+ client_random = ClientRandom,
+ server_random = ServerRandom} = SecParams,
+ try master_secret(Version,
+ calc_master_secret(Version,PrfAlgo,PremasterSecret,
+ ClientRandom, ServerRandom),
+ SecParams, ConnectionStates, Role)
catch
- error:_ ->
- %% ASN-1 decode of certificate somehow failed
- ?ALERT_REC(?FATAL, ?CERTIFICATE_UNKNOWN, failed_to_decode_certificate)
+ exit:_ ->
+ ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, master_secret_calculation_failure)
end.
%%--------------------------------------------------------------------
+-spec server_key_exchange_hash(md5sha | md5 | sha | sha224 |sha256 | sha384 | sha512, binary()) -> binary().
+%%
+%% Description: Calculate server key exchange hash
+%%--------------------------------------------------------------------
+server_key_exchange_hash(md5sha, Value) ->
+ MD5 = crypto:hash(md5, Value),
+ SHA = crypto:hash(sha, Value),
+ <<MD5/binary, SHA/binary>>;
+
+server_key_exchange_hash(Hash, Value) ->
+ crypto:hash(Hash, Value).
+
+%%--------------------------------------------------------------------
-spec verify_connection(ssl_record:ssl_version(), #finished{}, client | server, integer(), binary(),
ssl_handshake_history()) -> verified | #alert{}.
%%
@@ -447,295 +479,39 @@ init_handshake_history() ->
{[], []}.
%%--------------------------------------------------------------------
--spec update_handshake_history(ssl_handshake:ssl_handshake_history(), Data ::term(), boolean()) ->
+-spec update_handshake_history(ssl_handshake:ssl_handshake_history(), Data ::term()) ->
ssl_handshake:ssl_handshake_history().
%%
%% Description: Update the handshake history buffer with Data.
%%--------------------------------------------------------------------
-update_handshake_history(Handshake, % special-case SSL2 client hello
- <<?CLIENT_HELLO, ?UINT24(_), ?BYTE(Major), ?BYTE(Minor),
- ?UINT16(CSLength), ?UINT16(0),
- ?UINT16(CDLength),
- CipherSuites:CSLength/binary,
- ChallengeData:CDLength/binary>>, true) ->
- update_handshake_history(Handshake,
- <<?CLIENT_HELLO, ?BYTE(Major), ?BYTE(Minor),
- ?UINT16(CSLength), ?UINT16(0),
- ?UINT16(CDLength),
- CipherSuites:CSLength/binary,
- ChallengeData:CDLength/binary>>, true);
-update_handshake_history({Handshake0, _Prev}, Data, _) ->
+update_handshake_history({Handshake0, _Prev}, Data) ->
{[Data|Handshake0], Handshake0}.
-%% %%--------------------------------------------------------------------
-%% -spec decrypt_premaster_secret(binary(), #'RSAPrivateKey'{}) -> binary().
-
-%% %%
-%% %% Description: Public key decryption using the private key.
-%% %%--------------------------------------------------------------------
-%% decrypt_premaster_secret(Secret, RSAPrivateKey) ->
-%% try public_key:decrypt_private(Secret, RSAPrivateKey,
-%% [{rsa_pad, rsa_pkcs1_padding}])
-%% catch
-%% _:_ ->
-%% throw(?ALERT_REC(?FATAL, ?DECRYPT_ERROR))
-%% end.
-
-premaster_secret(OtherPublicDhKey, MyPrivateKey, #'DHParameter'{} = Params) ->
- try
- public_key:compute_key(OtherPublicDhKey, MyPrivateKey, Params)
- catch
- error:computation_failed ->
- throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
- end;
-premaster_secret(PublicDhKey, PrivateDhKey, #server_dh_params{dh_p = Prime, dh_g = Base}) ->
- try
- crypto:compute_key(dh, PublicDhKey, PrivateDhKey, [Prime, Base])
- catch
- error:computation_failed ->
- throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
- end;
-premaster_secret(#client_srp_public{srp_a = ClientPublicKey}, ServerKey, #srp_user{prime = Prime,
- verifier = Verifier}) ->
- case crypto:compute_key(srp, ClientPublicKey, ServerKey, {host, [Verifier, Prime, '6a']}) of
- error ->
- throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER));
- PremasterSecret ->
- PremasterSecret
- end;
-premaster_secret(#server_srp_params{srp_n = Prime, srp_g = Generator, srp_s = Salt, srp_b = Public},
- ClientKeys, {Username, Password}) ->
- case ssl_srp_primes:check_srp_params(Generator, Prime) of
- ok ->
- DerivedKey = crypto:hash(sha, [Salt, crypto:hash(sha, [Username, <<$:>>, Password])]),
- case crypto:compute_key(srp, Public, ClientKeys, {user, [DerivedKey, Prime, Generator, '6a']}) of
- error ->
- throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER));
- PremasterSecret ->
- PremasterSecret
- end;
- _ ->
- throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
- end;
-premaster_secret(#client_rsa_psk_identity{
- identity = PSKIdentity,
- exchange_keys = #encrypted_premaster_secret{premaster_secret = EncPMS}
- }, #'RSAPrivateKey'{} = Key, PSKLookup) ->
- PremasterSecret = premaster_secret(EncPMS, Key),
- psk_secret(PSKIdentity, PSKLookup, PremasterSecret);
-premaster_secret(#server_dhe_psk_params{
- hint = IdentityHint,
- dh_params = #server_dh_params{dh_y = PublicDhKey} = Params},
- PrivateDhKey,
- LookupFun) ->
- PremasterSecret = premaster_secret(PublicDhKey, PrivateDhKey, Params),
- psk_secret(IdentityHint, LookupFun, PremasterSecret);
-premaster_secret({rsa_psk, PSKIdentity}, PSKLookup, RSAPremasterSecret) ->
- psk_secret(PSKIdentity, PSKLookup, RSAPremasterSecret).
-
-premaster_secret(#client_dhe_psk_identity{
- identity = PSKIdentity,
- dh_public = PublicDhKey}, PrivateKey, #'DHParameter'{} = Params, PSKLookup) ->
- PremasterSecret = premaster_secret(PublicDhKey, PrivateKey, Params),
- psk_secret(PSKIdentity, PSKLookup, PremasterSecret).
-premaster_secret(#client_psk_identity{identity = PSKIdentity}, PSKLookup) ->
- psk_secret(PSKIdentity, PSKLookup);
-premaster_secret({psk, PSKIdentity}, PSKLookup) ->
- psk_secret(PSKIdentity, PSKLookup);
-premaster_secret(#'ECPoint'{} = ECPoint, #'ECPrivateKey'{} = ECDHKeys) ->
- public_key:compute_key(ECPoint, ECDHKeys);
-premaster_secret(EncSecret, #'RSAPrivateKey'{} = RSAPrivateKey) ->
- try public_key:decrypt_private(EncSecret, RSAPrivateKey,
- [{rsa_pad, rsa_pkcs1_padding}])
- catch
- _:_ ->
- throw(?ALERT_REC(?FATAL, ?DECRYPT_ERROR))
- end.
-%%--------------------------------------------------------------------
--spec server_key_exchange_hash(md5sha | md5 | sha | sha224 |sha256 | sha384 | sha512, binary()) -> binary().
-%%
-%% Description: Calculate server key exchange hash
-%%--------------------------------------------------------------------
-server_key_exchange_hash(md5sha, Value) ->
- MD5 = crypto:hash(md5, Value),
- SHA = crypto:hash(sha, Value),
- <<MD5/binary, SHA/binary>>;
-
-server_key_exchange_hash(Hash, Value) ->
- crypto:hash(Hash, Value).
-%%--------------------------------------------------------------------
--spec prf(ssl_record:ssl_version(), non_neg_integer(), binary(), binary(), [binary()], non_neg_integer()) ->
- {ok, binary()} | {error, undefined}.
-%%
-%% Description: use the TLS PRF to generate key material
-%%--------------------------------------------------------------------
-prf({3,0}, _, _, _, _, _) ->
- {error, undefined};
-prf({3,_N}, PRFAlgo, Secret, Label, Seed, WantedLength) ->
- {ok, tls_v1:prf(PRFAlgo, Secret, Label, Seed, WantedLength)}.
-
-
-%%--------------------------------------------------------------------
--spec select_hashsign(#hash_sign_algos{} | undefined, undefined | binary(),
- atom(), [atom()], ssl_record:ssl_version()) ->
- {atom(), atom()} | undefined | #alert{}.
-
-%%
-%% Description: Handles signature_algorithms hello extension (server)
-%%--------------------------------------------------------------------
-select_hashsign(_, undefined, _, _, _Version) ->
- {null, anon};
-%% The signature_algorithms extension was introduced with TLS 1.2. Ignore it if we have
-%% negotiated a lower version.
-select_hashsign(HashSigns, Cert, KeyExAlgo,
- undefined, {Major, Minor} = Version) when Major >= 3 andalso Minor >= 3->
- select_hashsign(HashSigns, Cert, KeyExAlgo, tls_v1:default_signature_algs(Version), Version);
-select_hashsign(#hash_sign_algos{hash_sign_algos = HashSigns}, Cert, KeyExAlgo, SupportedHashSigns,
- {Major, Minor}) when Major >= 3 andalso Minor >= 3 ->
- #'OTPCertificate'{tbsCertificate = TBSCert} = public_key:pkix_decode_cert(Cert, otp),
- #'OTPCertificate'{tbsCertificate = TBSCert,
- signatureAlgorithm = {_,SignAlgo, _}} = public_key:pkix_decode_cert(Cert, otp),
- #'OTPSubjectPublicKeyInfo'{algorithm = {_, SubjAlgo, _}} =
- TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo,
-
- Sign = sign_algo(SignAlgo),
- SubSing = sign_algo(SubjAlgo),
-
- case lists:filter(fun({_, S} = Algos) when S == Sign ->
- is_acceptable_hash_sign(Algos, Sign,
- SubSing, KeyExAlgo, SupportedHashSigns);
- (_) ->
- false
- end, HashSigns) of
- [] ->
- ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_signature_algorithm);
- [HashSign | _] ->
- HashSign
- end;
-select_hashsign(_, Cert, _, _, Version) ->
- #'OTPCertificate'{tbsCertificate = TBSCert} = public_key:pkix_decode_cert(Cert, otp),
- #'OTPSubjectPublicKeyInfo'{algorithm = {_,Algo, _}} = TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo,
- select_hashsign_algs(undefined, Algo, Version).
-%%--------------------------------------------------------------------
--spec select_hashsign(#certificate_request{}, binary(),
- [atom()], ssl_record:ssl_version()) ->
- {atom(), atom()} | #alert{}.
-
-%%
-%% Description: Handles signature algorithms selection for certificate requests (client)
-%%--------------------------------------------------------------------
-select_hashsign(#certificate_request{}, undefined, _, {Major, Minor}) when Major >= 3 andalso Minor >= 3->
- %% There client does not have a certificate and will send an empty reply, the server may fail
- %% or accept the connection by its own preference. No signature algorihms needed as there is
- %% no certificate to verify.
- {undefined, undefined};
-
-select_hashsign(#certificate_request{hashsign_algorithms = #hash_sign_algos{hash_sign_algos = HashSigns},
- certificate_types = Types}, Cert, SupportedHashSigns,
- {Major, Minor}) when Major >= 3 andalso Minor >= 3->
- #'OTPCertificate'{tbsCertificate = TBSCert} = public_key:pkix_decode_cert(Cert, otp),
- #'OTPCertificate'{tbsCertificate = TBSCert,
- signatureAlgorithm = {_,SignAlgo, _}} = public_key:pkix_decode_cert(Cert, otp),
- #'OTPSubjectPublicKeyInfo'{algorithm = {_, SubjAlgo, _}} =
- TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo,
-
- Sign = sign_algo(SignAlgo),
- SubSign = sign_algo(SubjAlgo),
-
- case is_acceptable_cert_type(SubSign, HashSigns, Types) andalso is_supported_sign(Sign, HashSigns) of
- true ->
- case lists:filter(fun({_, S} = Algos) when S == SubSign ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
- (_) ->
- false
- end, HashSigns) of
- [] ->
- ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_signature_algorithm);
- [HashSign | _] ->
- HashSign
- end;
- false ->
- ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_signature_algorithm)
- end;
-select_hashsign(#certificate_request{}, Cert, _, Version) ->
- select_hashsign(undefined, Cert, undefined, [], Version).
-
-%%--------------------------------------------------------------------
--spec select_hashsign_algs({atom(), atom()}| undefined, oid(), ssl_record:ssl_version()) ->
- {atom(), atom()}.
-
-%% Description: For TLS 1.2 hash function and signature algorithm pairs can be
-%% negotiated with the signature_algorithms extension,
-%% for previous versions always use appropriate defaults.
-%% RFC 5246, Sect. 7.4.1.4.1. Signature Algorithms
-%% If the client does not send the signature_algorithms extension, the
-%% server MUST do the following: (e.i defaults for TLS 1.2)
-%%
-%% - If the negotiated key exchange algorithm is one of (RSA, DHE_RSA,
-%% DH_RSA, RSA_PSK, ECDH_RSA, ECDHE_RSA), behave as if client had
-%% sent the value {sha1,rsa}.
-%%
-%% - If the negotiated key exchange algorithm is one of (DHE_DSS,
-%% DH_DSS), behave as if the client had sent the value {sha1,dsa}.
-%%
-%% - If the negotiated key exchange algorithm is one of (ECDH_ECDSA,
-%% ECDHE_ECDSA), behave as if the client had sent value {sha1,ecdsa}.
-
-%%--------------------------------------------------------------------
-select_hashsign_algs(HashSign, _, {Major, Minor}) when HashSign =/= undefined andalso
- Major >= 3 andalso Minor >= 3 ->
- HashSign;
-select_hashsign_algs(undefined, ?rsaEncryption, {Major, Minor}) when Major >= 3 andalso Minor >= 3 ->
- {sha, rsa};
-select_hashsign_algs(undefined,?'id-ecPublicKey', _) ->
- {sha, ecdsa};
-select_hashsign_algs(undefined, ?rsaEncryption, _) ->
- {md5sha, rsa};
-select_hashsign_algs(undefined, ?'id-dsa', _) ->
- {sha, dsa}.
-
-
-%%--------------------------------------------------------------------
--spec master_secret(ssl_record:ssl_version(), #session{} | binary(), ssl_record:connection_states(),
- client | server) -> {binary(), ssl_record:connection_states()} | #alert{}.
-%%
-%% Description: Sets or calculates the master secret and calculate keys,
-%% updating the pending connection states. The Mastersecret and the update
-%% connection states are returned or an alert if the calculation fails.
-%%-------------------------------------------------------------------
-master_secret(Version, #session{master_secret = Mastersecret},
- ConnectionStates, Role) ->
- #{security_parameters := SecParams} =
- ssl_record:pending_connection_state(ConnectionStates, read),
- try master_secret(Version, Mastersecret, SecParams,
- ConnectionStates, Role)
- catch
- exit:_ ->
- ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, key_calculation_failure)
- end;
-
-master_secret(Version, PremasterSecret, ConnectionStates, Role) ->
+verify_server_key(#server_key_params{params_bin = EncParams,
+ signature = Signature},
+ HashSign = {HashAlgo, _},
+ ConnectionStates, Version, PubKeyInfo) ->
#{security_parameters := SecParams} =
ssl_record:pending_connection_state(ConnectionStates, read),
-
- #security_parameters{prf_algorithm = PrfAlgo,
- client_random = ClientRandom,
+ #security_parameters{client_random = ClientRandom,
server_random = ServerRandom} = SecParams,
- try master_secret(Version,
- calc_master_secret(Version,PrfAlgo,PremasterSecret,
- ClientRandom, ServerRandom),
- SecParams, ConnectionStates, Role)
- catch
- exit:_ ->
- ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, master_secret_calculation_failure)
- end.
+ Hash = server_key_exchange_hash(HashAlgo,
+ <<ClientRandom/binary,
+ ServerRandom/binary,
+ EncParams/binary>>),
+ verify_signature(Version, Hash, HashSign, Signature, PubKeyInfo).
+
+select_version(RecordCB, ClientVersion, Versions) ->
+ do_select_version(RecordCB, ClientVersion, Versions).
+
+%%====================================================================
+%% Encode handshake
+%%====================================================================
-%%-------------Encode/Decode --------------------------------
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},
random = Random,
session_id = Session_ID,
@@ -857,70 +633,6 @@ encode_hello_extensions([#sni{hostname = Hostname} | Rest], Acc) ->
?UINT16(HostLen), HostnameBin/binary,
Acc/binary>>).
-enc_server_key_exchange(Version, Params, {HashAlgo, SignAlgo},
- ClientRandom, ServerRandom, PrivateKey) ->
- EncParams = encode_server_key(Params),
- case HashAlgo of
- null ->
- #server_key_params{params = Params,
- params_bin = EncParams,
- hashsign = {null, anon},
- signature = <<>>};
- _ ->
- Hash =
- server_key_exchange_hash(HashAlgo, <<ClientRandom/binary,
- ServerRandom/binary,
- EncParams/binary>>),
- Signature = digitally_signed(Version, Hash, HashAlgo, PrivateKey),
- #server_key_params{params = Params,
- params_bin = EncParams,
- hashsign = {HashAlgo, SignAlgo},
- signature = Signature}
- end.
-
-%%--------------------------------------------------------------------
--spec decode_client_key(binary(), ssl_cipher:key_algo(), ssl_record:ssl_version()) ->
- #encrypted_premaster_secret{}
- | #client_diffie_hellman_public{}
- | #client_ec_diffie_hellman_public{}
- | #client_psk_identity{}
- | #client_dhe_psk_identity{}
- | #client_rsa_psk_identity{}
- | #client_srp_public{}.
-%%
-%% Description: Decode client_key data and return appropriate type
-%%--------------------------------------------------------------------
-decode_client_key(ClientKey, Type, Version) ->
- dec_client_key(ClientKey, key_exchange_alg(Type), Version).
-
-%%--------------------------------------------------------------------
--spec decode_server_key(binary(), ssl_cipher:key_algo(), ssl_record:ssl_version()) ->
- #server_key_params{}.
-%%
-%% Description: Decode server_key data and return appropriate type
-%%--------------------------------------------------------------------
-decode_server_key(ServerKey, Type, Version) ->
- dec_server_key(ServerKey, key_exchange_alg(Type), Version).
-
-%%
-%% Description: Encode and decode functions for ALPN extension data.
-%%--------------------------------------------------------------------
-
-%% While the RFC opens the door to allow ALPN during renegotiation, in practice
-%% this does not work and it is recommended to ignore any ALPN extension during
-%% renegotiation, as done here.
-encode_alpn(_, true) ->
- undefined;
-encode_alpn(undefined, _) ->
- undefined;
-encode_alpn(Protocols, _) ->
- #alpn{extension_data = lists:foldl(fun encode_protocol/2, <<>>, Protocols)}.
-
-decode_alpn(undefined) ->
- undefined;
-decode_alpn(#alpn{extension_data=Data}) ->
- decode_protocols(Data, []).
-
encode_client_protocol_negotiation(undefined, _) ->
undefined;
encode_client_protocol_negotiation(_, false) ->
@@ -934,6 +646,10 @@ encode_protocols_advertised_on_server(undefined) ->
encode_protocols_advertised_on_server(Protocols) ->
#next_protocol_negotiation{extension_data = lists:foldl(fun encode_protocol/2, <<>>, Protocols)}.
+%%====================================================================
+%% Decode handshake
+%%====================================================================
+
decode_handshake(_, ?HELLO_REQUEST, <<>>) ->
#hello_request{};
decode_handshake(_, ?NEXT_PROTOCOL, <<?BYTE(SelectedProtocolLength),
@@ -966,7 +682,6 @@ decode_handshake(_Version, ?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:3
cipher_suite = Cipher_suite,
compression_method = Comp_method,
extensions = HelloExtensions};
-
decode_handshake(_Version, ?CERTIFICATE, <<?UINT24(ACLen), ASN1Certs:ACLen/binary>>) ->
#certificate{asn1_certificates = certs_to_list(ASN1Certs)};
decode_handshake(_Version, ?SERVER_KEY_EXCHANGE, Keys) ->
@@ -1013,66 +728,30 @@ decode_hello_extensions({client, <<?UINT16(ExtLen), Extensions:ExtLen/binary>>})
decode_hello_extensions(Extensions) ->
dec_hello_extensions(Extensions, #hello_extensions{}).
-dec_server_key(<<?UINT16(PLen), P:PLen/binary,
- ?UINT16(GLen), G:GLen/binary,
- ?UINT16(YLen), Y:YLen/binary, _/binary>> = KeyStruct,
- ?KEY_EXCHANGE_DIFFIE_HELLMAN, Version) ->
- Params = #server_dh_params{dh_p = P, dh_g = G, dh_y = Y},
- {BinMsg, HashSign, Signature} = dec_server_key_params(PLen + GLen + YLen + 6, KeyStruct, Version),
- #server_key_params{params = Params,
- params_bin = BinMsg,
- hashsign = HashSign,
- signature = Signature};
-%% ECParameters with named_curve
-%% TODO: explicit curve
-dec_server_key(<<?BYTE(?NAMED_CURVE), ?UINT16(CurveID),
- ?BYTE(PointLen), ECPoint:PointLen/binary,
- _/binary>> = KeyStruct,
- ?KEY_EXCHANGE_EC_DIFFIE_HELLMAN, Version) ->
- Params = #server_ecdh_params{curve = {namedCurve, tls_v1:enum_to_oid(CurveID)},
- public = ECPoint},
- {BinMsg, HashSign, Signature} = dec_server_key_params(PointLen + 4, KeyStruct, Version),
- #server_key_params{params = Params,
- params_bin = BinMsg,
- hashsign = HashSign,
- signature = Signature};
-dec_server_key(<<?UINT16(Len), PskIdentityHint:Len/binary, _/binary>> = KeyStruct,
- KeyExchange, Version)
- when KeyExchange == ?KEY_EXCHANGE_PSK; KeyExchange == ?KEY_EXCHANGE_RSA_PSK ->
- Params = #server_psk_params{
- hint = PskIdentityHint},
- {BinMsg, HashSign, Signature} = dec_server_key_params(Len + 2, KeyStruct, Version),
- #server_key_params{params = Params,
- params_bin = BinMsg,
- hashsign = HashSign,
- signature = Signature};
-dec_server_key(<<?UINT16(Len), IdentityHint:Len/binary,
- ?UINT16(PLen), P:PLen/binary,
- ?UINT16(GLen), G:GLen/binary,
- ?UINT16(YLen), Y:YLen/binary, _/binary>> = KeyStruct,
- ?KEY_EXCHANGE_DHE_PSK, Version) ->
- DHParams = #server_dh_params{dh_p = P, dh_g = G, dh_y = Y},
- Params = #server_dhe_psk_params{
- hint = IdentityHint,
- dh_params = DHParams},
- {BinMsg, HashSign, Signature} = dec_server_key_params(Len + PLen + GLen + YLen + 8, KeyStruct, Version),
- #server_key_params{params = Params,
- params_bin = BinMsg,
- hashsign = HashSign,
- signature = Signature};
-dec_server_key(<<?UINT16(NLen), N:NLen/binary,
- ?UINT16(GLen), G:GLen/binary,
- ?BYTE(SLen), S:SLen/binary,
- ?UINT16(BLen), B:BLen/binary, _/binary>> = KeyStruct,
- ?KEY_EXCHANGE_SRP, Version) ->
- Params = #server_srp_params{srp_n = N, srp_g = G, srp_s = S, srp_b = B},
- {BinMsg, HashSign, Signature} = dec_server_key_params(NLen + GLen + SLen + BLen + 7, KeyStruct, Version),
- #server_key_params{params = Params,
- params_bin = BinMsg,
- hashsign = HashSign,
- signature = Signature};
-dec_server_key(_, KeyExchange, _) ->
- throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, {unknown_or_malformed_key_exchange, KeyExchange})).
+%%--------------------------------------------------------------------
+-spec decode_server_key(binary(), ssl_cipher_format:key_algo(), ssl_record:ssl_version()) ->
+ #server_key_params{}.
+%%
+%% Description: Decode server_key data and return appropriate type
+%%--------------------------------------------------------------------
+decode_server_key(ServerKey, Type, Version) ->
+ dec_server_key(ServerKey, key_exchange_alg(Type), Version).
+
+%%--------------------------------------------------------------------
+-spec decode_client_key(binary(), ssl_cipher_format:key_algo(), ssl_record:ssl_version()) ->
+ #encrypted_premaster_secret{}
+ | #client_diffie_hellman_public{}
+ | #client_ec_diffie_hellman_public{}
+ | #client_psk_identity{}
+ | #client_dhe_psk_identity{}
+ | #client_ecdhe_psk_identity{}
+ | #client_rsa_psk_identity{}
+ | #client_srp_public{}.
+%%
+%% Description: Decode client_key data and return appropriate type
+%%--------------------------------------------------------------------
+decode_client_key(ClientKey, Type, Version) ->
+ dec_client_key(ClientKey, key_exchange_alg(Type), Version).
%%--------------------------------------------------------------------
-spec decode_suites('2_bytes'|'3_bytes', binary()) -> list().
@@ -1084,75 +763,59 @@ decode_suites('2_bytes', Dec) ->
decode_suites('3_bytes', Dec) ->
from_3bytes(Dec).
-%%-------------Cipeher suite handling --------------------------------
+%%====================================================================
+%% Cipher suite handling
+%%====================================================================
available_suites(UserSuites, Version) ->
- lists:filtermap(fun(Suite) ->
- lists:member(Suite, ssl_cipher:all_suites(Version))
- end, UserSuites).
+ VersionSuites = ssl_cipher:all_suites(Version) ++ ssl_cipher:anonymous_suites(Version),
+ lists:filtermap(fun(Suite) -> lists:member(Suite, VersionSuites) end, UserSuites).
available_suites(ServerCert, UserSuites, Version, undefined, Curve) ->
- ssl_cipher:filter(ServerCert, available_suites(UserSuites, Version))
- -- unavailable_ecc_suites(Curve);
+ Suites = ssl_cipher:filter(ServerCert, available_suites(UserSuites, Version), Version),
+ filter_unavailable_ecc_suites(Curve, Suites);
available_suites(ServerCert, UserSuites, Version, HashSigns, Curve) ->
Suites = available_suites(ServerCert, UserSuites, Version, undefined, Curve),
- filter_hashsigns(Suites, [ssl_cipher:suite_definition(Suite) || Suite <- Suites], HashSigns, []).
-filter_hashsigns([], [], _, Acc) ->
- lists:reverse(Acc);
-filter_hashsigns([Suite | Suites], [{KeyExchange,_,_,_} | Algos], HashSigns,
- Acc) when KeyExchange == dhe_ecdsa;
- KeyExchange == ecdhe_ecdsa ->
- do_filter_hashsigns(ecdsa, Suite, Suites, Algos, HashSigns, Acc);
+ filter_hashsigns(Suites, [ssl_cipher_format:suite_definition(Suite) || Suite <- Suites], HashSigns,
+ Version, []).
-filter_hashsigns([Suite | Suites], [{KeyExchange,_,_,_} | Algos], HashSigns,
- Acc) when KeyExchange == rsa;
- KeyExchange == dhe_rsa;
- KeyExchange == ecdhe_rsa;
- KeyExchange == srp_rsa;
- KeyExchange == rsa_psk ->
- do_filter_hashsigns(rsa, Suite, Suites, Algos, HashSigns, Acc);
-filter_hashsigns([Suite | Suites], [{KeyExchange,_,_,_} | Algos], HashSigns, Acc) when
- KeyExchange == dhe_dss;
- KeyExchange == srp_dss ->
- do_filter_hashsigns(dsa, Suite, Suites, Algos, HashSigns, Acc);
-filter_hashsigns([Suite | Suites], [{KeyExchange,_,_,_} | Algos], HashSigns, Acc) when
- KeyExchange == dh_dss;
- KeyExchange == dh_rsa;
- KeyExchange == dh_ecdsa;
- KeyExchange == ecdh_rsa;
- KeyExchange == ecdh_ecdsa ->
- %% Fixed DH certificates MAY be signed with any hash/signature
- %% algorithm pair appearing in the hash_sign extension. The names
- %% DH_DSS, DH_RSA, ECDH_ECDSA, and ECDH_RSA are historical.
- filter_hashsigns(Suites, Algos, HashSigns, [Suite| Acc]);
-filter_hashsigns([Suite | Suites], [{KeyExchange,_,_,_} | Algos], HashSigns, Acc) when
- KeyExchange == dh_anon;
- KeyExchange == ecdh_anon;
- KeyExchange == srp_anon;
- KeyExchange == psk;
- KeyExchange == dhe_psk ->
- %% In this case hashsigns is not used as the kexchange is anonaymous
- filter_hashsigns(Suites, Algos, HashSigns, [Suite| Acc]).
-
-do_filter_hashsigns(SignAlgo, Suite, Suites, Algos, HashSigns, Acc) ->
- case lists:keymember(SignAlgo, 2, HashSigns) of
- true ->
- filter_hashsigns(Suites, Algos, HashSigns, [Suite| Acc]);
- false ->
- filter_hashsigns(Suites, Algos, HashSigns, Acc)
- end.
-
-unavailable_ecc_suites(no_curve) ->
- ssl_cipher:ec_keyed_suites();
-unavailable_ecc_suites(_) ->
- [].
+available_signature_algs(undefined, _) ->
+ undefined;
+available_signature_algs(SupportedHashSigns, Version) when Version >= {3, 3} ->
+ #hash_sign_algos{hash_sign_algos = SupportedHashSigns};
+available_signature_algs(_, _) ->
+ undefined.
+available_signature_algs(undefined, SupportedHashSigns, _, Version) when
+ Version >= {3,3} ->
+ SupportedHashSigns;
+available_signature_algs(#hash_sign_algos{hash_sign_algos = ClientHashSigns}, SupportedHashSigns,
+ _, Version) when Version >= {3,3} ->
+ sets:to_list(sets:intersection(sets:from_list(ClientHashSigns),
+ sets:from_list(SupportedHashSigns)));
+available_signature_algs(_, _, _, _) ->
+ undefined.
+cipher_suites(Suites, Renegotiation, true) ->
+ %% TLS_FALLBACK_SCSV should be placed last -RFC7507
+ cipher_suites(Suites, Renegotiation) ++ [?TLS_FALLBACK_SCSV];
+cipher_suites(Suites, Renegotiation, false) ->
+ cipher_suites(Suites, Renegotiation).
cipher_suites(Suites, false) ->
[?TLS_EMPTY_RENEGOTIATION_INFO_SCSV | Suites];
cipher_suites(Suites, true) ->
Suites.
+%%--------------------------------------------------------------------
+-spec prf(ssl_record:ssl_version(), non_neg_integer(), binary(), binary(), [binary()], non_neg_integer()) ->
+ {ok, binary()} | {error, undefined}.
+%%
+%% Description: use the TLS PRF to generate key material
+%%--------------------------------------------------------------------
+prf({3,0}, _, _, _, _, _) ->
+ {error, undefined};
+prf({3,_N}, PRFAlgo, Secret, Label, Seed, WantedLength) ->
+ {ok, tls_v1:prf(PRFAlgo, Secret, Label, Seed, WantedLength)}.
-select_session(SuggestedSessionId, CipherSuites, HashSigns, Compressions, Port, #session{ecc = ECCCurve} =
+select_session(SuggestedSessionId, CipherSuites, HashSigns, Compressions, Port, #session{ecc = ECCCurve0} =
Session, Version,
#ssl_options{ciphers = UserSuites, honor_cipher_order = HonorCipherOrder} = SslOpts,
Cache, CacheCb, Cert) ->
@@ -1161,78 +824,135 @@ select_session(SuggestedSessionId, CipherSuites, HashSigns, Compressions, Port,
Cache, CacheCb),
case Resumed of
undefined ->
- Suites = available_suites(Cert, UserSuites, Version, HashSigns, ECCCurve),
- CipherSuite = select_cipher_suite(CipherSuites, Suites, HonorCipherOrder),
+ Suites = available_suites(Cert, UserSuites, Version, HashSigns, ECCCurve0),
+ CipherSuite0 = select_cipher_suite(CipherSuites, Suites, HonorCipherOrder),
+ {ECCCurve, CipherSuite} = cert_curve(Cert, ECCCurve0, CipherSuite0),
Compression = select_compression(Compressions),
{new, Session#session{session_id = SessionId,
+ ecc = ECCCurve,
cipher_suite = CipherSuite,
compression_method = Compression}};
_ ->
{resumed, Resumed}
end.
-%% Deprecated?
supported_ecc({Major, Minor}) when ((Major == 3) and (Minor >= 1)) orelse (Major > 3) ->
Curves = tls_v1:ecc_curves(Minor),
#elliptic_curves{elliptic_curve_list = Curves};
supported_ecc(_) ->
#elliptic_curves{elliptic_curve_list = []}.
-%%-------------certificate handling --------------------------------
-
-certificate_types(_, {N, M}) when N >= 3 andalso M >= 3 ->
- case proplists:get_bool(ecdsa,
- proplists:get_value(public_keys, crypto:supports())) of
- true ->
- <<?BYTE(?ECDSA_SIGN), ?BYTE(?RSA_SIGN), ?BYTE(?DSS_SIGN)>>;
- false ->
- <<?BYTE(?RSA_SIGN), ?BYTE(?DSS_SIGN)>>
+premaster_secret(OtherPublicDhKey, MyPrivateKey, #'DHParameter'{} = Params) ->
+ try
+ public_key:compute_key(OtherPublicDhKey, MyPrivateKey, Params)
+ catch
+ error:computation_failed ->
+ throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
+ end;
+premaster_secret(PublicDhKey, PrivateDhKey, #server_dh_params{dh_p = Prime, dh_g = Base}) ->
+ try
+ crypto:compute_key(dh, PublicDhKey, PrivateDhKey, [Prime, Base])
+ catch
+ error:computation_failed ->
+ throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
end;
+premaster_secret(#client_srp_public{srp_a = ClientPublicKey}, ServerKey, #srp_user{prime = Prime,
+ verifier = Verifier}) ->
+ try crypto:compute_key(srp, ClientPublicKey, ServerKey, {host, [Verifier, Prime, '6a']}) of
+ PremasterSecret ->
+ PremasterSecret
+ catch
+ error:_ ->
+ throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
+ end;
+premaster_secret(#server_srp_params{srp_n = Prime, srp_g = Generator, srp_s = Salt, srp_b = Public},
+ ClientKeys, {Username, Password}) ->
+ case ssl_srp_primes:check_srp_params(Generator, Prime) of
+ ok ->
+ DerivedKey = crypto:hash(sha, [Salt, crypto:hash(sha, [Username, <<$:>>, Password])]),
+ try crypto:compute_key(srp, Public, ClientKeys, {user, [DerivedKey, Prime, Generator, '6a']}) of
+ PremasterSecret ->
+ PremasterSecret
+ catch
+ error ->
+ throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
+ end;
+ _ ->
+ throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
+ end;
+premaster_secret(#client_rsa_psk_identity{
+ identity = PSKIdentity,
+ exchange_keys = #encrypted_premaster_secret{premaster_secret = EncPMS}
+ }, #'RSAPrivateKey'{} = Key, PSKLookup) ->
+ PremasterSecret = premaster_secret(EncPMS, Key),
+ psk_secret(PSKIdentity, PSKLookup, PremasterSecret);
+premaster_secret(#server_dhe_psk_params{
+ hint = IdentityHint,
+ dh_params = #server_dh_params{dh_y = PublicDhKey} = Params},
+ PrivateDhKey,
+ LookupFun) ->
+ PremasterSecret = premaster_secret(PublicDhKey, PrivateDhKey, Params),
+ psk_secret(IdentityHint, LookupFun, PremasterSecret);
+premaster_secret(#server_ecdhe_psk_params{
+ hint = IdentityHint,
+ dh_params = #server_ecdh_params{
+ public = ECServerPubKey}},
+ PrivateEcDhKey,
+ LookupFun) ->
+ PremasterSecret = premaster_secret(#'ECPoint'{point = ECServerPubKey}, PrivateEcDhKey),
+ psk_secret(IdentityHint, LookupFun, PremasterSecret);
+premaster_secret({rsa_psk, PSKIdentity}, PSKLookup, RSAPremasterSecret) ->
+ psk_secret(PSKIdentity, PSKLookup, RSAPremasterSecret);
+premaster_secret(#client_ecdhe_psk_identity{
+ identity = PSKIdentity,
+ dh_public = PublicEcDhPoint}, PrivateEcDhKey, PSKLookup) ->
+ PremasterSecret = premaster_secret(#'ECPoint'{point = PublicEcDhPoint}, PrivateEcDhKey),
+ psk_secret(PSKIdentity, PSKLookup, PremasterSecret).
+premaster_secret(#client_dhe_psk_identity{
+ identity = PSKIdentity,
+ dh_public = PublicDhKey}, PrivateKey, #'DHParameter'{} = Params, PSKLookup) ->
+ PremasterSecret = premaster_secret(PublicDhKey, PrivateKey, Params),
+ psk_secret(PSKIdentity, PSKLookup, PremasterSecret).
+premaster_secret(#client_psk_identity{identity = PSKIdentity}, PSKLookup) ->
+ psk_secret(PSKIdentity, PSKLookup);
+premaster_secret({psk, PSKIdentity}, PSKLookup) ->
+ psk_secret(PSKIdentity, PSKLookup);
+premaster_secret(#'ECPoint'{} = ECPoint, #'ECPrivateKey'{} = ECDHKeys) ->
+ public_key:compute_key(ECPoint, ECDHKeys);
+premaster_secret(EncSecret, #'RSAPrivateKey'{} = RSAPrivateKey) ->
+ try public_key:decrypt_private(EncSecret, RSAPrivateKey,
+ [{rsa_pad, rsa_pkcs1_padding}])
+ catch
+ _:_ ->
+ throw(?ALERT_REC(?FATAL, ?DECRYPT_ERROR))
+ end.
+%%====================================================================
+%% Extensions handling
+%%====================================================================
+client_hello_extensions(Version, CipherSuites,
+ #ssl_options{signature_algs = SupportedHashSigns,
+ eccs = SupportedECCs} = SslOpts, ConnectionStates, Renegotiation) ->
+ {EcPointFormats, EllipticCurves} =
+ case advertises_ec_ciphers(lists:map(fun ssl_cipher_format:suite_definition/1, CipherSuites)) of
+ true ->
+ client_ecc_extensions(SupportedECCs);
+ false ->
+ {undefined, undefined}
+ end,
+ SRP = srp_user(SslOpts),
-certificate_types({KeyExchange, _, _, _}, _) when KeyExchange == rsa;
- KeyExchange == dh_rsa;
- KeyExchange == dhe_rsa;
- KeyExchange == ecdhe_rsa ->
- <<?BYTE(?RSA_SIGN)>>;
-
-certificate_types({KeyExchange, _, _, _}, _) when KeyExchange == dh_dss;
- KeyExchange == dhe_dss;
- KeyExchange == srp_dss ->
- <<?BYTE(?DSS_SIGN)>>;
-
-certificate_types({KeyExchange, _, _, _}, _) when KeyExchange == dh_ecdsa;
- KeyExchange == dhe_ecdsa;
- KeyExchange == ecdh_ecdsa;
- KeyExchange == ecdhe_ecdsa ->
- <<?BYTE(?ECDSA_SIGN)>>;
-
-certificate_types(_, _) ->
- <<?BYTE(?RSA_SIGN)>>.
-
-certificate_authorities(CertDbHandle, CertDbRef) ->
- Authorities = certificate_authorities_from_db(CertDbHandle, CertDbRef),
- Enc = fun(#'OTPCertificate'{tbsCertificate=TBSCert}) ->
- OTPSubj = TBSCert#'OTPTBSCertificate'.subject,
- DNEncodedBin = public_key:pkix_encode('Name', OTPSubj, otp),
- DNEncodedLen = byte_size(DNEncodedBin),
- <<?UINT16(DNEncodedLen), DNEncodedBin/binary>>
- end,
- list_to_binary([Enc(Cert) || {_, Cert} <- Authorities]).
-
-certificate_authorities_from_db(CertDbHandle, CertDbRef) when is_reference(CertDbRef) ->
- ConnectionCerts = fun({{Ref, _, _}, Cert}, Acc) when Ref == CertDbRef ->
- [Cert | Acc];
- (_, Acc) ->
- Acc
- end,
- ssl_pkix_db:foldl(ConnectionCerts, [], CertDbHandle);
-certificate_authorities_from_db(_CertDbHandle, {extracted, CertDbData}) ->
- %% Cache disabled, Ref contains data
- lists:foldl(fun({decoded, {_Key,Cert}}, Acc) -> [Cert | Acc] end,
- [], CertDbData).
-
-
-%%-------------Extension handling --------------------------------
+ #hello_extensions{
+ renegotiation_info = renegotiation_info(tls_record, client,
+ ConnectionStates, Renegotiation),
+ srp = SRP,
+ signature_algs = available_signature_algs(SupportedHashSigns, Version),
+ ec_point_formats = EcPointFormats,
+ elliptic_curves = EllipticCurves,
+ alpn = encode_alpn(SslOpts#ssl_options.alpn_advertised_protocols, Renegotiation),
+ next_protocol_negotiation =
+ encode_client_protocol_negotiation(SslOpts#ssl_options.next_protocol_selector,
+ Renegotiation),
+ sni = sni(SslOpts#ssl_options.server_name_indication)}.
handle_client_hello_extensions(RecordCB, Random, ClientCipherSuites,
#hello_extensions{renegotiation_info = Info,
@@ -1309,231 +1029,223 @@ handle_server_hello_extensions(RecordCB, Random, CipherSuite, Compression,
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, too_many_protocols_in_server_hello)
end.
-select_version(RecordCB, ClientVersion, Versions) ->
- do_select_version(RecordCB, ClientVersion, Versions).
-
-do_select_version(_, ClientVersion, []) ->
- ClientVersion;
-do_select_version(RecordCB, ClientVersion, [Version | Versions]) ->
- case RecordCB:is_higher(Version, ClientVersion) of
- true ->
- %% Version too high for client - keep looking
- do_select_version(RecordCB, ClientVersion, Versions);
- false ->
- %% Version ok for client - look for a higher
- do_select_version(RecordCB, ClientVersion, Versions, Version)
- end.
-%%
-do_select_version(_, _, [], GoodVersion) ->
- GoodVersion;
-do_select_version(
- RecordCB, ClientVersion, [Version | Versions], GoodVersion) ->
- BetterVersion =
- case RecordCB:is_higher(Version, ClientVersion) of
- true ->
- %% Version too high for client
- GoodVersion;
- false ->
- %% Version ok for client
- case RecordCB:is_higher(Version, GoodVersion) of
- true ->
- %% Use higher version
- Version;
- false ->
- GoodVersion
- end
- end,
- do_select_version(RecordCB, ClientVersion, Versions, BetterVersion).
+select_curve(Client, Server) ->
+ select_curve(Client, Server, false).
-renegotiation_info(_, client, _, false) ->
- #renegotiation_info{renegotiated_connection = undefined};
-renegotiation_info(_RecordCB, server, ConnectionStates, false) ->
- ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
- case maps:get(secure_renegotiation, ConnectionState) of
- true ->
- #renegotiation_info{renegotiated_connection = ?byte(0)};
- false ->
- #renegotiation_info{renegotiated_connection = undefined}
- end;
-renegotiation_info(_RecordCB, client, ConnectionStates, true) ->
- ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
- case maps:get(secure_renegotiation, ConnectionState) of
- true ->
- Data = maps:get(client_verify_data, ConnectionState),
- #renegotiation_info{renegotiated_connection = Data};
- false ->
- #renegotiation_info{renegotiated_connection = undefined}
+select_curve(#elliptic_curves{elliptic_curve_list = ClientCurves},
+ #elliptic_curves{elliptic_curve_list = ServerCurves},
+ ServerOrder) ->
+ case ServerOrder of
+ false ->
+ select_shared_curve(ClientCurves, ServerCurves);
+ true ->
+ select_shared_curve(ServerCurves, ClientCurves)
end;
+select_curve(undefined, _, _) ->
+ %% Client did not send ECC extension use default curve if
+ %% ECC cipher is negotiated
+ {namedCurve, ?secp256r1}.
-renegotiation_info(_RecordCB, server, ConnectionStates, true) ->
- ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
- case maps:get(secure_renegotiation, ConnectionState) of
- true ->
- CData = maps:get(client_verify_data, ConnectionState),
- SData = maps:get(server_verify_data, ConnectionState),
- #renegotiation_info{renegotiated_connection = <<CData/binary, SData/binary>>};
- false ->
- #renegotiation_info{renegotiated_connection = undefined}
- end.
+%%--------------------------------------------------------------------
+-spec select_hashsign(#hash_sign_algos{} | undefined, undefined | binary(),
+ atom(), [atom()], ssl_record:ssl_version()) ->
+ {atom(), atom()} | undefined | #alert{}.
-handle_renegotiation_info(_RecordCB, _, #renegotiation_info{renegotiated_connection = ?byte(0)},
- ConnectionStates, false, _, _) ->
- {ok, ssl_record:set_renegotiation_flag(true, ConnectionStates)};
+%%
+%% Description: Handles signature_algorithms hello extension (server)
+%%--------------------------------------------------------------------
+select_hashsign(_, _, KeyExAlgo, _, _Version) when KeyExAlgo == dh_anon;
+ KeyExAlgo == ecdh_anon;
+ KeyExAlgo == srp_anon;
+ KeyExAlgo == psk;
+ KeyExAlgo == dhe_psk;
+ KeyExAlgo == ecdhe_psk ->
+ {null, anon};
+%% The signature_algorithms extension was introduced with TLS 1.2. Ignore it if we have
+%% negotiated a lower version.
+select_hashsign(HashSigns, Cert, KeyExAlgo,
+ undefined, {Major, Minor} = Version) when Major >= 3 andalso Minor >= 3->
+ select_hashsign(HashSigns, Cert, KeyExAlgo, tls_v1:default_signature_algs(Version), Version);
+select_hashsign(#hash_sign_algos{hash_sign_algos = HashSigns}, Cert, KeyExAlgo, SupportedHashSigns,
+ {Major, Minor}) when Major >= 3 andalso Minor >= 3 ->
+ #'OTPCertificate'{tbsCertificate = TBSCert} = public_key:pkix_decode_cert(Cert, otp),
+ #'OTPSubjectPublicKeyInfo'{algorithm = {_, SubjAlgo, _}} =
+ TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo,
-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)};
- false ->
- {ok, ssl_record:set_renegotiation_flag(false, ConnectionStates)}
+ SubSign = sign_algo(SubjAlgo),
+
+ case lists:filter(fun({_, S} = Algos) when S == SubSign ->
+ is_acceptable_hash_sign(Algos, KeyExAlgo, SupportedHashSigns);
+ (_) ->
+ false
+ end, HashSigns) of
+ [] ->
+ ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_signature_algorithm);
+ [HashSign | _] ->
+ HashSign
end;
+select_hashsign(_, Cert, _, _, Version) ->
+ #'OTPCertificate'{tbsCertificate = TBSCert} = public_key:pkix_decode_cert(Cert, otp),
+ #'OTPSubjectPublicKeyInfo'{algorithm = {_,Algo, _}} = TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo,
+ select_hashsign_algs(undefined, Algo, Version).
+%%--------------------------------------------------------------------
+-spec select_hashsign(#certificate_request{}, binary(),
+ [atom()], ssl_record:ssl_version()) ->
+ {atom(), atom()} | #alert{}.
-handle_renegotiation_info(_RecordCB, _, undefined, ConnectionStates, false, _, _) ->
- {ok, ssl_record:set_renegotiation_flag(false, ConnectionStates)};
+%%
+%% Description: Handles signature algorithms selection for certificate requests (client)
+%%--------------------------------------------------------------------
+select_hashsign(#certificate_request{hashsign_algorithms = #hash_sign_algos{hash_sign_algos = HashSigns},
+ certificate_types = Types}, Cert, SupportedHashSigns,
+ {Major, Minor}) when Major >= 3 andalso Minor >= 3->
+ #'OTPCertificate'{tbsCertificate = TBSCert} = public_key:pkix_decode_cert(Cert, otp),
+ #'OTPCertificate'{tbsCertificate = TBSCert,
+ signatureAlgorithm = {_,SignAlgo, _}} = public_key:pkix_decode_cert(Cert, otp),
+ #'OTPSubjectPublicKeyInfo'{algorithm = {_, SubjAlgo, _}} =
+ TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo,
-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),
- SData = maps:get(server_verify_data, ConnectionState),
- case <<CData/binary, SData/binary>> == ClientServerVerify of
+ Sign = sign_algo(SignAlgo),
+ SubSign = sign_algo(SubjAlgo),
+
+ case is_acceptable_cert_type(SubSign, HashSigns, Types) andalso is_supported_sign(Sign, HashSigns) of
true ->
- {ok, ConnectionStates};
+ case lists:filter(fun({_, S} = Algos) when S == SubSign ->
+ is_acceptable_hash_sign(Algos, SupportedHashSigns);
+ (_) ->
+ false
+ end, HashSigns) of
+ [] ->
+ ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_signature_algorithm);
+ [HashSign | _] ->
+ HashSign
+ end;
false ->
- ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, client_renegotiation)
+ ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_signature_algorithm)
end;
-handle_renegotiation_info(_RecordCB, server, #renegotiation_info{renegotiated_connection = ClientVerify},
- ConnectionStates, true, _, CipherSuites) ->
-
- case is_member(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV, CipherSuites) of
- true ->
- ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, {server_renegotiation, empty_renegotiation_info_scsv});
- false ->
- ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
- Data = maps:get(client_verify_data, ConnectionState),
- case Data == ClientVerify of
- true ->
- {ok, ConnectionStates};
- false ->
- ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, server_renegotiation)
- end
- end;
-
-handle_renegotiation_info(RecordCB, client, undefined, ConnectionStates, true, SecureRenegotation, _) ->
- handle_renegotiation_info(RecordCB, ConnectionStates, SecureRenegotation);
+select_hashsign(#certificate_request{}, Cert, _, Version) ->
+ select_hashsign(undefined, Cert, undefined, [], Version).
-handle_renegotiation_info(RecordCB, server, undefined, ConnectionStates, true, SecureRenegotation, CipherSuites) ->
- case is_member(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV, CipherSuites) of
- true ->
- ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, {server_renegotiation, empty_renegotiation_info_scsv});
- false ->
- handle_renegotiation_info(RecordCB, ConnectionStates, SecureRenegotation)
- end.
+%%--------------------------------------------------------------------
+-spec select_hashsign_algs({atom(), atom()}| undefined, oid(), ssl_record:ssl_version()) ->
+ {atom(), atom()}.
-handle_renegotiation_info(_RecordCB, ConnectionStates, SecureRenegotation) ->
- ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
- case {SecureRenegotation, maps:get(secure_renegotiation, ConnectionState)} of
- {_, true} ->
- ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, already_secure);
- {true, false} ->
- ?ALERT_REC(?FATAL, ?NO_RENEGOTIATION);
- {false, false} ->
- {ok, ConnectionStates}
- end.
+%% Description: For TLS 1.2 hash function and signature algorithm pairs can be
+%% negotiated with the signature_algorithms extension,
+%% for previous versions always use appropriate defaults.
+%% RFC 5246, Sect. 7.4.1.4.1. Signature Algorithms
+%% If the client does not send the signature_algorithms extension, the
+%% server MUST do the following: (e.i defaults for TLS 1.2)
+%%
+%% - If the negotiated key exchange algorithm is one of (RSA, DHE_RSA,
+%% DH_RSA, RSA_PSK, ECDH_RSA, ECDHE_RSA), behave as if client had
+%% sent the value {sha1,rsa}.
+%%
+%% - If the negotiated key exchange algorithm is one of (DHE_DSS,
+%% DH_DSS), behave as if the client had sent the value {sha1,dsa}.
+%%
+%% - If the negotiated key exchange algorithm is one of (ECDH_ECDSA,
+%% ECDHE_ECDSA), behave as if the client had sent value {sha1,ecdsa}.
-hello_extensions_list(#hello_extensions{renegotiation_info = RenegotiationInfo,
- srp = SRP,
- signature_algs = HashSigns,
- ec_point_formats = EcPointFormats,
- elliptic_curves = EllipticCurves,
- alpn = ALPN,
- next_protocol_negotiation = NextProtocolNegotiation,
- sni = Sni}) ->
- [Ext || Ext <- [RenegotiationInfo, SRP, HashSigns,
- EcPointFormats, EllipticCurves, ALPN, NextProtocolNegotiation, Sni], Ext =/= undefined].
+%%--------------------------------------------------------------------
+select_hashsign_algs(HashSign, _, {Major, Minor}) when HashSign =/= undefined andalso
+ Major >= 3 andalso Minor >= 3 ->
+ HashSign;
+select_hashsign_algs(undefined, ?rsaEncryption, {Major, Minor}) when Major >= 3 andalso Minor >= 3 ->
+ {sha, rsa};
+select_hashsign_algs(undefined,?'id-ecPublicKey', _) ->
+ {sha, ecdsa};
+select_hashsign_algs(undefined, ?rsaEncryption, _) ->
+ {md5sha, rsa};
+select_hashsign_algs(undefined, ?'id-dsa', _) ->
+ {sha, dsa}.
srp_user(#ssl_options{srp_identity = {UserName, _}}) ->
#srp{username = UserName};
srp_user(_) ->
undefined.
-client_ecc_extensions(SupportedECCs) ->
- CryptoSupport = proplists:get_value(public_keys, crypto:supports()),
- case proplists:get_bool(ecdh, CryptoSupport) of
- true ->
- EcPointFormats = #ec_point_formats{ec_point_format_list = [?ECPOINT_UNCOMPRESSED]},
- EllipticCurves = SupportedECCs,
- {EcPointFormats, EllipticCurves};
- _ ->
- {undefined, undefined}
- end.
+extension_value(undefined) ->
+ undefined;
+extension_value(#sni{hostname = HostName}) ->
+ HostName;
+extension_value(#ec_point_formats{ec_point_format_list = List}) ->
+ List;
+extension_value(#elliptic_curves{elliptic_curve_list = List}) ->
+ List;
+extension_value(#hash_sign_algos{hash_sign_algos = Algos}) ->
+ Algos;
+extension_value(#alpn{extension_data = Data}) ->
+ Data;
+extension_value(#next_protocol_negotiation{extension_data = Data}) ->
+ Data;
+extension_value(#srp{username = Name}) ->
+ Name;
+extension_value(#renegotiation_info{renegotiated_connection = Data}) ->
+ Data.
-server_ecc_extension(_Version, EcPointFormats) ->
- CryptoSupport = proplists:get_value(public_keys, crypto:supports()),
- case proplists:get_bool(ecdh, CryptoSupport) of
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+%%------------- Create handshake messages ----------------------------
+
+int_to_bin(I) ->
+ L = (length(integer_to_list(I, 16)) + 1) div 2,
+ <<I:(L*8)>>.
+
+certificate_types(_, {N, M}) when N >= 3 andalso M >= 3 ->
+ case proplists:get_bool(ecdsa,
+ proplists:get_value(public_keys, crypto:supports())) of
true ->
- handle_ecc_point_fmt_extension(EcPointFormats);
+ <<?BYTE(?ECDSA_SIGN), ?BYTE(?RSA_SIGN), ?BYTE(?DSS_SIGN)>>;
false ->
- undefined
- end.
-
-handle_ecc_point_fmt_extension(undefined) ->
- undefined;
-handle_ecc_point_fmt_extension(_) ->
- #ec_point_formats{ec_point_format_list = [?ECPOINT_UNCOMPRESSED]}.
+ <<?BYTE(?RSA_SIGN), ?BYTE(?DSS_SIGN)>>
+ end;
-advertises_ec_ciphers([]) ->
- false;
-advertises_ec_ciphers([{ecdh_ecdsa, _,_,_} | _]) ->
- true;
-advertises_ec_ciphers([{ecdhe_ecdsa, _,_,_} | _]) ->
- true;
-advertises_ec_ciphers([{ecdh_rsa, _,_,_} | _]) ->
- true;
-advertises_ec_ciphers([{ecdhe_rsa, _,_,_} | _]) ->
- true;
-advertises_ec_ciphers([{ecdh_anon, _,_,_} | _]) ->
- true;
-advertises_ec_ciphers([_| Rest]) ->
- advertises_ec_ciphers(Rest).
+certificate_types(#{key_exchange := KeyExchange}, _) when KeyExchange == rsa;
+ KeyExchange == dh_rsa;
+ KeyExchange == dhe_rsa;
+ KeyExchange == ecdhe_rsa ->
+ <<?BYTE(?RSA_SIGN)>>;
-select_curve(Client, Server) ->
- select_curve(Client, Server, false).
+certificate_types(#{key_exchange := KeyExchange}, _) when KeyExchange == dh_dss;
+ KeyExchange == dhe_dss;
+ KeyExchange == srp_dss ->
+ <<?BYTE(?DSS_SIGN)>>;
-select_curve(#elliptic_curves{elliptic_curve_list = ClientCurves},
- #elliptic_curves{elliptic_curve_list = ServerCurves},
- ServerOrder) ->
- case ServerOrder of
- false ->
- select_shared_curve(ClientCurves, ServerCurves);
- true ->
- select_shared_curve(ServerCurves, ClientCurves)
- end;
-select_curve(undefined, _, _) ->
- %% Client did not send ECC extension use default curve if
- %% ECC cipher is negotiated
- {namedCurve, ?secp256r1}.
+certificate_types(#{key_exchange := KeyExchange}, _) when KeyExchange == dh_ecdsa;
+ KeyExchange == dhe_ecdsa;
+ KeyExchange == ecdh_ecdsa;
+ KeyExchange == ecdhe_ecdsa ->
+ <<?BYTE(?ECDSA_SIGN)>>;
+certificate_types(_, _) ->
+ <<?BYTE(?RSA_SIGN)>>.
-select_shared_curve([], _) ->
- no_curve;
-select_shared_curve([Curve | Rest], Curves) ->
- case lists:member(Curve, Curves) of
- true ->
- {namedCurve, Curve};
- false ->
- select_shared_curve(Rest, Curves)
- end.
+certificate_authorities(CertDbHandle, CertDbRef) ->
+ Authorities = certificate_authorities_from_db(CertDbHandle, CertDbRef),
+ Enc = fun(#'OTPCertificate'{tbsCertificate=TBSCert}) ->
+ OTPSubj = TBSCert#'OTPTBSCertificate'.subject,
+ DNEncodedBin = public_key:pkix_encode('Name', OTPSubj, otp),
+ DNEncodedLen = byte_size(DNEncodedBin),
+ <<?UINT16(DNEncodedLen), DNEncodedBin/binary>>
+ end,
+ list_to_binary([Enc(Cert) || {_, Cert} <- Authorities]).
-sni(undefined) ->
- undefined;
-sni(Hostname) ->
- #sni{hostname = Hostname}.
+certificate_authorities_from_db(CertDbHandle, CertDbRef) when is_reference(CertDbRef) ->
+ ConnectionCerts = fun({{Ref, _, _}, Cert}, Acc) when Ref == CertDbRef ->
+ [Cert | Acc];
+ (_, Acc) ->
+ Acc
+ end,
+ ssl_pkix_db:foldl(ConnectionCerts, [], CertDbHandle);
+certificate_authorities_from_db(_CertDbHandle, {extracted, CertDbData}) ->
+ %% Cache disabled, Ref contains data
+ lists:foldl(fun({decoded, {_Key,Cert}}, Acc) -> [Cert | Acc] end,
+ [], CertDbData).
-%%--------------------------------------------------------------------
-%%% Internal functions
-%%--------------------------------------------------------------------
+%%-------------Handle handshake messages --------------------------------
validation_fun_and_state({Fun, UserState0}, Role, CertDbHandle, CertDbRef,
- ServerNameIndication, CRLCheck, CRLDbHandle, CertPath) ->
+ ServerNameIndication, CustomizeHostCheck, CRLCheck, CRLDbHandle, CertPath) ->
{fun(OtpCert, {extension, _} = Extension, {SslState, UserState}) ->
case ssl_certificate:validate(OtpCert,
Extension,
@@ -1550,9 +1262,9 @@ validation_fun_and_state({Fun, UserState0}, Role, CertDbHandle, CertDbRef,
(OtpCert, VerifyResult, {SslState, UserState}) ->
apply_user_fun(Fun, OtpCert, VerifyResult, UserState,
SslState, CertPath)
- end, {{Role, CertDbHandle, CertDbRef, ServerNameIndication, CRLCheck, CRLDbHandle}, UserState0}};
+ end, {{Role, CertDbHandle, CertDbRef, {ServerNameIndication, CustomizeHostCheck}, CRLCheck, CRLDbHandle}, UserState0}};
validation_fun_and_state(undefined, Role, CertDbHandle, CertDbRef,
- ServerNameIndication, CRLCheck, CRLDbHandle, CertPath) ->
+ ServerNameIndication, CustomizeHostCheck, CRLCheck, CRLDbHandle, CertPath) ->
{fun(OtpCert, {extension, _} = Extension, SslState) ->
ssl_certificate:validate(OtpCert,
Extension,
@@ -1572,7 +1284,7 @@ validation_fun_and_state(undefined, Role, CertDbHandle, CertDbRef,
ssl_certificate:validate(OtpCert,
VerifyResult,
SslState)
- end, {Role, CertDbHandle, CertDbRef, ServerNameIndication, CRLCheck, CRLDbHandle}}.
+ end, {Role, CertDbHandle, CertDbRef, {ServerNameIndication, CustomizeHostCheck}, CRLCheck, CRLDbHandle}}.
apply_user_fun(Fun, OtpCert, VerifyResult, UserState0,
{_, CertDbHandle, CertDbRef, _, CRLCheck, CRLDbHandle} = SslState, CertPath) when
@@ -1599,6 +1311,45 @@ apply_user_fun(Fun, OtpCert, ExtensionOrError, UserState0, SslState, _CertPath)
{unknown, {SslState, UserState}}
end.
+handle_path_validation_error({bad_cert, unknown_ca} = Reason, PeerCert, Chain,
+ Opts, Options, CertDbHandle, CertsDbRef) ->
+ handle_incomplete_chain(PeerCert, Chain, Opts, Options, CertDbHandle, CertsDbRef, Reason);
+handle_path_validation_error({bad_cert, invalid_issuer} = Reason, PeerCert, Chain0,
+ Opts, Options, CertDbHandle, CertsDbRef) ->
+ case ssl_certificate:certificate_chain(PeerCert, CertDbHandle, CertsDbRef, Chain0) of
+ {ok, _, [PeerCert | Chain] = OrdedChain} when Chain =/= Chain0 -> %% Chain appaears to be unorded
+ {Trusted, Path} = ssl_certificate:trusted_cert_and_path(OrdedChain,
+ CertDbHandle, CertsDbRef,
+ Opts#ssl_options.partial_chain),
+ case public_key:pkix_path_validation(Trusted, Path, Options) of
+ {ok, {PublicKeyInfo,_}} ->
+ {PeerCert, PublicKeyInfo};
+ {error, PathError} ->
+ handle_path_validation_error(PathError, PeerCert, Path,
+ Opts, Options, CertDbHandle, CertsDbRef)
+ end;
+ _ ->
+ path_validation_alert(Reason)
+ end;
+handle_path_validation_error(Reason, _, _, _, _,_, _) ->
+ path_validation_alert(Reason).
+
+handle_incomplete_chain(PeerCert, Chain0, Opts, Options, CertDbHandle, CertsDbRef, PathError0) ->
+ case ssl_certificate:certificate_chain(PeerCert, CertDbHandle, CertsDbRef) of
+ {ok, _, [PeerCert | _] = Chain} when Chain =/= Chain0 -> %% Chain candidate found
+ {Trusted, Path} = ssl_certificate:trusted_cert_and_path(Chain,
+ CertDbHandle, CertsDbRef,
+ Opts#ssl_options.partial_chain),
+ case public_key:pkix_path_validation(Trusted, Path, Options) of
+ {ok, {PublicKeyInfo,_}} ->
+ {PeerCert, PublicKeyInfo};
+ {error, PathError} ->
+ path_validation_alert(PathError)
+ end;
+ _ ->
+ path_validation_alert(PathError0)
+ end.
+
path_validation_alert({bad_cert, cert_expired}) ->
?ALERT_REC(?FATAL, ?CERTIFICATE_EXPIRED);
path_validation_alert({bad_cert, invalid_issuer}) ->
@@ -1611,8 +1362,9 @@ path_validation_alert({bad_cert, unknown_critical_extension}) ->
?ALERT_REC(?FATAL, ?UNSUPPORTED_CERTIFICATE);
path_validation_alert({bad_cert, {revoked, _}}) ->
?ALERT_REC(?FATAL, ?CERTIFICATE_REVOKED);
-path_validation_alert({bad_cert, revocation_status_undetermined}) ->
- ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE);
+path_validation_alert({bad_cert, {revocation_status_undetermined, Details}}) ->
+ Alert = ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE),
+ Alert#alert{reason = Details};
path_validation_alert({bad_cert, selfsigned_peer}) ->
?ALERT_REC(?FATAL, ?BAD_CERTIFICATE);
path_validation_alert({bad_cert, unknown_ca}) ->
@@ -1620,17 +1372,6 @@ path_validation_alert({bad_cert, unknown_ca}) ->
path_validation_alert(Reason) ->
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, Reason).
-encrypted_premaster_secret(Secret, RSAPublicKey) ->
- try
- PreMasterSecret = public_key:encrypt_public(Secret, RSAPublicKey,
- [{rsa_pad,
- rsa_pkcs1_padding}]),
- #encrypted_premaster_secret{premaster_secret = PreMasterSecret}
- catch
- _:_->
- throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, premaster_encryption_failed))
- end.
-
digitally_signed(Version, Hashes, HashAlgo, PrivateKey) ->
try do_digitally_signed(Version, Hashes, HashAlgo, PrivateKey) of
Signature ->
@@ -1639,17 +1380,123 @@ digitally_signed(Version, Hashes, HashAlgo, PrivateKey) ->
error:badkey->
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, bad_key(PrivateKey)))
end.
-
+do_digitally_signed({3, Minor}, Hash, HashAlgo, #{algorithm := Alg} = Engine)
+ when Minor >= 3 ->
+ crypto:sign(Alg, HashAlgo, {digest, Hash}, maps:remove(algorithm, Engine));
do_digitally_signed({3, Minor}, Hash, HashAlgo, Key) when Minor >= 3 ->
public_key:sign({digest, Hash}, HashAlgo, Key);
-do_digitally_signed(_Version, Hash, HashAlgo, #'DSAPrivateKey'{} = Key) ->
- public_key:sign({digest, Hash}, HashAlgo, Key);
do_digitally_signed(_Version, Hash, _HashAlgo, #'RSAPrivateKey'{} = Key) ->
public_key:encrypt_private(Hash, Key,
[{rsa_pad, rsa_pkcs1_padding}]);
+do_digitally_signed({3, _}, Hash, _,
+ #{algorithm := rsa} = Engine) ->
+ crypto:private_encrypt(rsa, Hash, maps:remove(algorithm, Engine),
+ rsa_pkcs1_padding);
+do_digitally_signed({3, _}, Hash, HashAlgo, #{algorithm := Alg} = Engine) ->
+ crypto:sign(Alg, HashAlgo, {digest, Hash}, maps:remove(algorithm, Engine));
do_digitally_signed(_Version, Hash, HashAlgo, Key) ->
public_key:sign({digest, Hash}, HashAlgo, Key).
+bad_key(#'DSAPrivateKey'{}) ->
+ unacceptable_dsa_key;
+bad_key(#'RSAPrivateKey'{}) ->
+ unacceptable_rsa_key;
+bad_key(#'ECPrivateKey'{}) ->
+ unacceptable_ecdsa_key.
+
+crl_check(_, false, _,_,_, _, _) ->
+ valid;
+crl_check(_, peer, _, _,_, valid, _) -> %% Do not check CAs with this option.
+ valid;
+crl_check(OtpCert, Check, CertDbHandle, CertDbRef, {Callback, CRLDbHandle}, _, CertPath) ->
+ Options = [{issuer_fun, {fun(_DP, CRL, Issuer, DBInfo) ->
+ ssl_crl:trusted_cert_and_path(CRL, Issuer, {CertPath,
+ DBInfo})
+ end, {CertDbHandle, CertDbRef}}},
+ {update_crl, fun(DP, CRL) -> Callback:fresh_crl(DP, CRL) end},
+ {undetermined_details, true}
+ ],
+ case dps_and_crls(OtpCert, Callback, CRLDbHandle, ext) of
+ no_dps ->
+ crl_check_same_issuer(OtpCert, Check,
+ dps_and_crls(OtpCert, Callback, CRLDbHandle, same_issuer),
+ Options);
+ DpsAndCRLs -> %% This DP list may be empty if relevant CRLs existed
+ %% but could not be retrived, will result in {bad_cert, revocation_status_undetermined}
+ case public_key:pkix_crls_validate(OtpCert, DpsAndCRLs, Options) of
+ {bad_cert, {revocation_status_undetermined, _}} ->
+ crl_check_same_issuer(OtpCert, Check, dps_and_crls(OtpCert, Callback,
+ CRLDbHandle, same_issuer), Options);
+ Other ->
+ Other
+ end
+ end.
+
+crl_check_same_issuer(OtpCert, best_effort, Dps, Options) ->
+ case public_key:pkix_crls_validate(OtpCert, Dps, Options) of
+ {bad_cert, {revocation_status_undetermined, _}} ->
+ valid;
+ Other ->
+ Other
+ end;
+crl_check_same_issuer(OtpCert, _, Dps, Options) ->
+ public_key:pkix_crls_validate(OtpCert, Dps, Options).
+
+dps_and_crls(OtpCert, Callback, CRLDbHandle, ext) ->
+ case public_key:pkix_dist_points(OtpCert) of
+ [] ->
+ no_dps;
+ DistPoints ->
+ Issuer = OtpCert#'OTPCertificate'.tbsCertificate#'OTPTBSCertificate'.issuer,
+ CRLs = distpoints_lookup(DistPoints, Issuer, Callback, CRLDbHandle),
+ dps_and_crls(DistPoints, CRLs, [])
+ end;
+
+dps_and_crls(OtpCert, Callback, CRLDbHandle, same_issuer) ->
+ DP = #'DistributionPoint'{distributionPoint = {fullName, GenNames}} =
+ public_key:pkix_dist_point(OtpCert),
+ CRLs = lists:flatmap(fun({directoryName, Issuer}) ->
+ Callback:select(Issuer, CRLDbHandle);
+ (_) ->
+ []
+ end, GenNames),
+ [{DP, {CRL, public_key:der_decode('CertificateList', CRL)}} || CRL <- CRLs].
+
+dps_and_crls([], _, Acc) ->
+ Acc;
+dps_and_crls([DP | Rest], CRLs, Acc) ->
+ DpCRL = [{DP, {CRL, public_key:der_decode('CertificateList', CRL)}} || CRL <- CRLs],
+ dps_and_crls(Rest, CRLs, DpCRL ++ Acc).
+
+distpoints_lookup([],_, _, _) ->
+ [];
+distpoints_lookup([DistPoint | Rest], Issuer, Callback, CRLDbHandle) ->
+ Result =
+ try Callback:lookup(DistPoint, Issuer, CRLDbHandle)
+ catch
+ error:undef ->
+ %% The callback module still uses the 2-argument
+ %% version of the lookup function.
+ Callback:lookup(DistPoint, CRLDbHandle)
+ end,
+ case Result of
+ not_available ->
+ distpoints_lookup(Rest, Issuer, Callback, CRLDbHandle);
+ CRLs ->
+ CRLs
+ end.
+
+encrypted_premaster_secret(Secret, RSAPublicKey) ->
+ try
+ PreMasterSecret = public_key:encrypt_public(Secret, RSAPublicKey,
+ [{rsa_pad,
+ rsa_pkcs1_padding}]),
+ #encrypted_premaster_secret{premaster_secret = PreMasterSecret}
+ catch
+ _:_->
+ throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, premaster_encryption_failed))
+ end.
+
calc_certificate_verify({3, 0}, HashAlgo, MasterSecret, Handshake) ->
ssl_v3:certificate_verify(HashAlgo, MasterSecret, lists:reverse(Handshake));
calc_certificate_verify({3, N}, HashAlgo, _MasterSecret, Handshake) ->
@@ -1702,24 +1549,7 @@ calc_master_secret({3,0}, _PrfAlgo, PremasterSecret, ClientRandom, ServerRandom)
calc_master_secret({3,_}, PrfAlgo, PremasterSecret, ClientRandom, ServerRandom) ->
tls_v1:master_secret(PrfAlgo, PremasterSecret, ClientRandom, ServerRandom).
-
-handle_renegotiation_extension(Role, RecordCB, Version, Info, Random, NegotiatedCipherSuite,
- ClientCipherSuites, Compression,
- ConnectionStates0, Renegotiation, SecureRenegotation) ->
- case handle_renegotiation_info(RecordCB, Role, Info, ConnectionStates0,
- Renegotiation, SecureRenegotation,
- ClientCipherSuites) of
- {ok, ConnectionStates} ->
- hello_pending_connection_states(RecordCB, Role,
- Version,
- NegotiatedCipherSuite,
- Random,
- Compression,
- ConnectionStates);
- #alert{} = Alert ->
- throw(Alert)
- end.
-
+
%% Update pending connection states with parameters exchanged via
%% hello messages
%% NOTE : Role is the role of the receiver of the hello message
@@ -1759,7 +1589,43 @@ hello_security_parameters(server, Version, #{security_parameters := SecParams},
compression_algorithm = Compression
}.
-%%-------------Encode/Decode --------------------------------
+select_compression(_CompressionMetodes) ->
+ ?NULL.
+
+do_select_version(_, ClientVersion, []) ->
+ ClientVersion;
+do_select_version(RecordCB, ClientVersion, [Version | Versions]) ->
+ case RecordCB:is_higher(Version, ClientVersion) of
+ true ->
+ %% Version too high for client - keep looking
+ do_select_version(RecordCB, ClientVersion, Versions);
+ false ->
+ %% Version ok for client - look for a higher
+ do_select_version(RecordCB, ClientVersion, Versions, Version)
+ end.
+%%
+do_select_version(_, _, [], GoodVersion) ->
+ GoodVersion;
+do_select_version(
+ RecordCB, ClientVersion, [Version | Versions], GoodVersion) ->
+ BetterVersion =
+ case RecordCB:is_higher(Version, ClientVersion) of
+ true ->
+ %% Version too high for client
+ GoodVersion;
+ false ->
+ %% Version ok for client
+ case RecordCB:is_higher(Version, GoodVersion) of
+ true ->
+ %% Use higher version
+ Version;
+ false ->
+ GoodVersion
+ end
+ end,
+ do_select_version(RecordCB, ClientVersion, Versions, BetterVersion).
+
+%%-------------Encode handshakes --------------------------------
encode_server_key(#server_dh_params{dh_p = P, dh_g = G, dh_y = Y}) ->
PLen = byte_size(P),
@@ -1785,6 +1651,18 @@ encode_server_key(#server_dhe_psk_params{
YLen = byte_size(Y),
<<?UINT16(Len), PskIdentityHint/binary,
?UINT16(PLen), P/binary, ?UINT16(GLen), G/binary, ?UINT16(YLen), Y/binary>>;
+encode_server_key(Params = #server_ecdhe_psk_params{hint = undefined}) ->
+ encode_server_key(Params#server_ecdhe_psk_params{hint = <<>>});
+encode_server_key(#server_ecdhe_psk_params{
+ hint = PskIdentityHint,
+ dh_params = #server_ecdh_params{
+ curve = {namedCurve, ECCurve}, public = ECPubKey}}) ->
+ %%TODO: support arbitrary keys
+ Len = byte_size(PskIdentityHint),
+ KLen = size(ECPubKey),
+ <<?UINT16(Len), PskIdentityHint/binary,
+ ?BYTE(?NAMED_CURVE), ?UINT16((tls_v1:oid_to_enum(ECCurve))),
+ ?BYTE(KLen), ECPubKey/binary>>;
encode_server_key(#server_srp_params{srp_n = N, srp_g = G, srp_s = S, srp_b = B}) ->
NLen = byte_size(N),
GLen = byte_size(G),
@@ -1817,6 +1695,12 @@ encode_client_key(#client_dhe_psk_identity{identity = Id, dh_public = DHPublic},
Len = byte_size(Id),
DHLen = byte_size(DHPublic),
<<?UINT16(Len), Id/binary, ?UINT16(DHLen), DHPublic/binary>>;
+encode_client_key(Identity = #client_ecdhe_psk_identity{identity = undefined}, Version) ->
+ encode_client_key(Identity#client_ecdhe_psk_identity{identity = <<"psk_identity">>}, Version);
+encode_client_key(#client_ecdhe_psk_identity{identity = Id, dh_public = DHPublic}, _) ->
+ Len = byte_size(Id),
+ DHLen = byte_size(DHPublic),
+ <<?UINT16(Len), Id/binary, ?BYTE(DHLen), DHPublic/binary>>;
encode_client_key(Identity = #client_rsa_psk_identity{identity = undefined}, Version) ->
encode_client_key(Identity#client_rsa_psk_identity{identity = <<"psk_identity">>}, Version);
encode_client_key(#client_rsa_psk_identity{identity = Id, exchange_keys = ExchangeKeys}, Version) ->
@@ -1847,6 +1731,126 @@ encode_protocol(Protocol, Acc) ->
Len = byte_size(Protocol),
<<Acc/binary, ?BYTE(Len), Protocol/binary>>.
+enc_server_key_exchange(Version, Params, {HashAlgo, SignAlgo},
+ ClientRandom, ServerRandom, PrivateKey) ->
+ EncParams = encode_server_key(Params),
+ case HashAlgo of
+ null ->
+ #server_key_params{params = Params,
+ params_bin = EncParams,
+ hashsign = {null, anon},
+ signature = <<>>};
+ _ ->
+ Hash =
+ server_key_exchange_hash(HashAlgo, <<ClientRandom/binary,
+ ServerRandom/binary,
+ EncParams/binary>>),
+ Signature = digitally_signed(Version, Hash, HashAlgo, PrivateKey),
+ #server_key_params{params = Params,
+ params_bin = EncParams,
+ hashsign = {HashAlgo, SignAlgo},
+ signature = Signature}
+ end.
+
+%% While the RFC opens the door to allow ALPN during renegotiation, in practice
+%% this does not work and it is recommended to ignore any ALPN extension during
+%% renegotiation, as done here.
+encode_alpn(_, true) ->
+ undefined;
+encode_alpn(undefined, _) ->
+ undefined;
+encode_alpn(Protocols, _) ->
+ #alpn{extension_data = lists:foldl(fun encode_protocol/2, <<>>, Protocols)}.
+
+hello_extensions_list(#hello_extensions{renegotiation_info = RenegotiationInfo,
+ srp = SRP,
+ signature_algs = HashSigns,
+ ec_point_formats = EcPointFormats,
+ elliptic_curves = EllipticCurves,
+ alpn = ALPN,
+ next_protocol_negotiation = NextProtocolNegotiation,
+ sni = Sni}) ->
+ [Ext || Ext <- [RenegotiationInfo, SRP, HashSigns,
+ EcPointFormats, EllipticCurves, ALPN, NextProtocolNegotiation, Sni], Ext =/= undefined].
+
+%%-------------Decode handshakes---------------------------------
+dec_server_key(<<?UINT16(PLen), P:PLen/binary,
+ ?UINT16(GLen), G:GLen/binary,
+ ?UINT16(YLen), Y:YLen/binary, _/binary>> = KeyStruct,
+ ?KEY_EXCHANGE_DIFFIE_HELLMAN, Version) ->
+ Params = #server_dh_params{dh_p = P, dh_g = G, dh_y = Y},
+ {BinMsg, HashSign, Signature} = dec_server_key_params(PLen + GLen + YLen + 6, KeyStruct, Version),
+ #server_key_params{params = Params,
+ params_bin = BinMsg,
+ hashsign = HashSign,
+ signature = Signature};
+%% ECParameters with named_curve
+%% TODO: explicit curve
+dec_server_key(<<?BYTE(?NAMED_CURVE), ?UINT16(CurveID),
+ ?BYTE(PointLen), ECPoint:PointLen/binary,
+ _/binary>> = KeyStruct,
+ ?KEY_EXCHANGE_EC_DIFFIE_HELLMAN, Version) ->
+ Params = #server_ecdh_params{curve = {namedCurve, tls_v1:enum_to_oid(CurveID)},
+ public = ECPoint},
+ {BinMsg, HashSign, Signature} = dec_server_key_params(PointLen + 4, KeyStruct, Version),
+ #server_key_params{params = Params,
+ params_bin = BinMsg,
+ hashsign = HashSign,
+ signature = Signature};
+dec_server_key(<<?UINT16(Len), PskIdentityHint:Len/binary, _/binary>> = KeyStruct,
+ KeyExchange, Version)
+ when KeyExchange == ?KEY_EXCHANGE_PSK; KeyExchange == ?KEY_EXCHANGE_RSA_PSK ->
+ Params = #server_psk_params{
+ hint = PskIdentityHint},
+ {BinMsg, HashSign, Signature} = dec_server_key_params(Len + 2, KeyStruct, Version),
+ #server_key_params{params = Params,
+ params_bin = BinMsg,
+ hashsign = HashSign,
+ signature = Signature};
+dec_server_key(<<?UINT16(Len), IdentityHint:Len/binary,
+ ?UINT16(PLen), P:PLen/binary,
+ ?UINT16(GLen), G:GLen/binary,
+ ?UINT16(YLen), Y:YLen/binary, _/binary>> = KeyStruct,
+ ?KEY_EXCHANGE_DHE_PSK, Version) ->
+ DHParams = #server_dh_params{dh_p = P, dh_g = G, dh_y = Y},
+ Params = #server_dhe_psk_params{
+ hint = IdentityHint,
+ dh_params = DHParams},
+ {BinMsg, HashSign, Signature} = dec_server_key_params(Len + PLen + GLen + YLen + 8, KeyStruct, Version),
+ #server_key_params{params = Params,
+ params_bin = BinMsg,
+ hashsign = HashSign,
+ signature = Signature};
+dec_server_key(<<?UINT16(Len), IdentityHint:Len/binary,
+ ?BYTE(?NAMED_CURVE), ?UINT16(CurveID),
+ ?BYTE(PointLen), ECPoint:PointLen/binary,
+ _/binary>> = KeyStruct,
+ ?KEY_EXCHANGE_EC_DIFFIE_HELLMAN_PSK, Version) ->
+ DHParams = #server_ecdh_params{
+ curve = {namedCurve, tls_v1:enum_to_oid(CurveID)},
+ public = ECPoint},
+ Params = #server_ecdhe_psk_params{
+ hint = IdentityHint,
+ dh_params = DHParams},
+ {BinMsg, HashSign, Signature} = dec_server_key_params(Len + 2 + PointLen + 4, KeyStruct, Version),
+ #server_key_params{params = Params,
+ params_bin = BinMsg,
+ hashsign = HashSign,
+ signature = Signature};
+dec_server_key(<<?UINT16(NLen), N:NLen/binary,
+ ?UINT16(GLen), G:GLen/binary,
+ ?BYTE(SLen), S:SLen/binary,
+ ?UINT16(BLen), B:BLen/binary, _/binary>> = KeyStruct,
+ ?KEY_EXCHANGE_SRP, Version) ->
+ Params = #server_srp_params{srp_n = N, srp_g = G, srp_s = S, srp_b = B},
+ {BinMsg, HashSign, Signature} = dec_server_key_params(NLen + GLen + SLen + BLen + 7, KeyStruct, Version),
+ #server_key_params{params = Params,
+ params_bin = BinMsg,
+ hashsign = HashSign,
+ signature = Signature};
+dec_server_key(_, KeyExchange, _) ->
+ throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, {unknown_or_malformed_key_exchange, KeyExchange})).
+
dec_client_key(PKEPMS, ?KEY_EXCHANGE_RSA, {3, 0}) ->
#encrypted_premaster_secret{premaster_secret = PKEPMS};
dec_client_key(<<?UINT16(_), PKEPMS/binary>>, ?KEY_EXCHANGE_RSA, _) ->
@@ -1868,6 +1872,10 @@ dec_client_key(<<?UINT16(Len), Id:Len/binary,
?UINT16(DH_YLen), DH_Y:DH_YLen/binary>>,
?KEY_EXCHANGE_DHE_PSK, _) ->
#client_dhe_psk_identity{identity = Id, dh_public = DH_Y};
+dec_client_key(<<?UINT16(Len), Id:Len/binary,
+ ?BYTE(DH_YLen), DH_Y:DH_YLen/binary>>,
+ ?KEY_EXCHANGE_EC_DIFFIE_HELLMAN_PSK, _) ->
+ #client_ecdhe_psk_identity{identity = Id, dh_public = DH_Y};
dec_client_key(<<?UINT16(Len), Id:Len/binary, PKEPMS/binary>>,
?KEY_EXCHANGE_RSA_PSK, {3, 0}) ->
#client_rsa_psk_identity{identity = Id,
@@ -1963,7 +1971,7 @@ dec_hello_extensions(<<?UINT16(?EC_POINT_FORMATS_EXT), ?UINT16(Len),
ECPointFormats}});
dec_hello_extensions(<<?UINT16(?SNI_EXT), ?UINT16(Len), Rest/binary>>, Acc) when Len == 0 ->
- dec_hello_extensions(Rest, Acc#hello_extensions{sni = ""}); %% Server may send an empy SNI
+ dec_hello_extensions(Rest, Acc#hello_extensions{sni = #sni{hostname = ""}}); %% Server may send an empy SNI
dec_hello_extensions(<<?UINT16(?SNI_EXT), ?UINT16(Len),
ExtData:Len/binary, Rest/binary>>, Acc) ->
@@ -1988,6 +1996,11 @@ dec_sni(<<?BYTE(?SNI_NAMETYPE_HOST_NAME), ?UINT16(Len),
dec_sni(<<?BYTE(_), ?UINT16(Len), _:Len, Rest/binary>>) -> dec_sni(Rest);
dec_sni(_) -> undefined.
+decode_alpn(undefined) ->
+ undefined;
+decode_alpn(#alpn{extension_data=Data}) ->
+ decode_protocols(Data, []).
+
decode_next_protocols({next_protocol_negotiation, Protocols}) ->
decode_protocols(Protocols, []).
@@ -2032,6 +2045,7 @@ from_2bytes(<<>>, Acc) ->
lists:reverse(Acc);
from_2bytes(<<?UINT16(N), Rest/binary>>, Acc) ->
from_2bytes(Rest, [?uint16(N) | Acc]).
+
key_exchange_alg(rsa) ->
?KEY_EXCHANGE_RSA;
key_exchange_alg(Alg) when Alg == dhe_rsa; Alg == dhe_dss;
@@ -2045,6 +2059,8 @@ key_exchange_alg(psk) ->
?KEY_EXCHANGE_PSK;
key_exchange_alg(dhe_psk) ->
?KEY_EXCHANGE_DHE_PSK;
+key_exchange_alg(ecdhe_psk) ->
+ ?KEY_EXCHANGE_EC_DIFFIE_HELLMAN_PSK;
key_exchange_alg(rsa_psk) ->
?KEY_EXCHANGE_RSA_PSK;
key_exchange_alg(Alg)
@@ -2053,8 +2069,133 @@ key_exchange_alg(Alg)
key_exchange_alg(_) ->
?NULL.
+%%-------------Cipher suite handling -----------------------------
+select_cipher_suite(CipherSuites, Suites, false) ->
+ select_cipher_suite(CipherSuites, Suites);
+select_cipher_suite(CipherSuites, Suites, true) ->
+ select_cipher_suite(Suites, CipherSuites).
+
+select_cipher_suite([], _) ->
+ no_suite;
+select_cipher_suite([Suite | ClientSuites], SupportedSuites) ->
+ case is_member(Suite, SupportedSuites) of
+ true ->
+ Suite;
+ false ->
+ select_cipher_suite(ClientSuites, SupportedSuites)
+ end.
+
+is_member(Suite, SupportedSuites) ->
+ lists:member(Suite, SupportedSuites).
+
+psk_secret(PSKIdentity, PSKLookup) ->
+ case handle_psk_identity(PSKIdentity, PSKLookup) of
+ {ok, PSK} when is_binary(PSK) ->
+ Len = erlang:byte_size(PSK),
+ <<?UINT16(Len), 0:(Len*8), ?UINT16(Len), PSK/binary>>;
+ #alert{} = Alert ->
+ Alert;
+ _ ->
+ throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
+ end.
+
+psk_secret(PSKIdentity, PSKLookup, PremasterSecret) ->
+ case handle_psk_identity(PSKIdentity, PSKLookup) of
+ {ok, PSK} when is_binary(PSK) ->
+ Len = erlang:byte_size(PremasterSecret),
+ PSKLen = erlang:byte_size(PSK),
+ <<?UINT16(Len), PremasterSecret/binary, ?UINT16(PSKLen), PSK/binary>>;
+ #alert{} = Alert ->
+ Alert;
+ _ ->
+ throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
+ end.
+
+handle_psk_identity(_PSKIdentity, LookupFun)
+ when LookupFun == undefined ->
+ error;
+handle_psk_identity(PSKIdentity, {Fun, UserState}) ->
+ Fun(psk, PSKIdentity, UserState).
+
+
+filter_hashsigns([], [], _, _, Acc) ->
+ lists:reverse(Acc);
+filter_hashsigns([Suite | Suites], [#{key_exchange := KeyExchange} | Algos], HashSigns, Version,
+ Acc) when KeyExchange == dhe_ecdsa;
+ KeyExchange == ecdhe_ecdsa ->
+ do_filter_hashsigns(ecdsa, Suite, Suites, Algos, HashSigns, Version, Acc);
+filter_hashsigns([Suite | Suites], [#{key_exchange := KeyExchange} | Algos], HashSigns, Version,
+ Acc) when KeyExchange == rsa;
+ KeyExchange == dhe_rsa;
+ KeyExchange == ecdhe_rsa;
+ KeyExchange == srp_rsa;
+ KeyExchange == rsa_psk ->
+ do_filter_hashsigns(rsa, Suite, Suites, Algos, HashSigns, Version, Acc);
+filter_hashsigns([Suite | Suites], [#{key_exchange := KeyExchange} | Algos], HashSigns, Version, Acc) when
+ KeyExchange == dhe_dss;
+ KeyExchange == srp_dss ->
+ do_filter_hashsigns(dsa, Suite, Suites, Algos, HashSigns, Version, Acc);
+filter_hashsigns([Suite | Suites], [#{key_exchange := KeyExchange} | Algos], HashSigns, Verion,
+ Acc) when
+ KeyExchange == dh_dss;
+ KeyExchange == dh_rsa;
+ KeyExchange == dh_ecdsa;
+ KeyExchange == ecdh_rsa;
+ KeyExchange == ecdh_ecdsa ->
+ %% Fixed DH certificates MAY be signed with any hash/signature
+ %% algorithm pair appearing in the hash_sign extension. The names
+ %% DH_DSS, DH_RSA, ECDH_ECDSA, and ECDH_RSA are historical.
+ filter_hashsigns(Suites, Algos, HashSigns, Verion, [Suite| Acc]);
+filter_hashsigns([Suite | Suites], [#{key_exchange := KeyExchange} | Algos], HashSigns, Version,
+ Acc) when
+ KeyExchange == dh_anon;
+ KeyExchange == ecdh_anon;
+ KeyExchange == srp_anon;
+ KeyExchange == psk;
+ KeyExchange == dhe_psk;
+ KeyExchange == ecdhe_psk ->
+ %% In this case hashsigns is not used as the kexchange is anonaymous
+ filter_hashsigns(Suites, Algos, HashSigns, Version, [Suite| Acc]).
+
+do_filter_hashsigns(SignAlgo, Suite, Suites, Algos, HashSigns, Version, Acc) ->
+ case lists:keymember(SignAlgo, 2, HashSigns) of
+ true ->
+ filter_hashsigns(Suites, Algos, HashSigns, Version, [Suite| Acc]);
+ false ->
+ filter_hashsigns(Suites, Algos, HashSigns, Version, Acc)
+ end.
+
+filter_unavailable_ecc_suites(no_curve, Suites) ->
+ ECCSuites = ssl_cipher:filter_suites(Suites, #{key_exchange_filters => [fun(ecdh_ecdsa) -> true;
+ (ecdhe_ecdsa) -> true;
+ (ecdh_rsa) -> true;
+ (_) -> false
+ end],
+ cipher_filters => [],
+ mac_filters => [],
+ prf_filters => []}),
+ Suites -- ECCSuites;
+filter_unavailable_ecc_suites(_, Suites) ->
+ Suites.
%%-------------Extension handling --------------------------------
+handle_renegotiation_extension(Role, RecordCB, Version, Info, Random, NegotiatedCipherSuite,
+ ClientCipherSuites, Compression,
+ ConnectionStates0, Renegotiation, SecureRenegotation) ->
+ case handle_renegotiation_info(RecordCB, Role, Info, ConnectionStates0,
+ Renegotiation, SecureRenegotation,
+ ClientCipherSuites) of
+ {ok, ConnectionStates} ->
+ hello_pending_connection_states(RecordCB, Role,
+ Version,
+ NegotiatedCipherSuite,
+ Random,
+ Compression,
+ ConnectionStates);
+ #alert{} = Alert ->
+ throw(Alert)
+ end.
+
%% Receive protocols, choose one from the list, return it.
handle_alpn_extension(_, {error, Reason}) ->
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, Reason);
@@ -2117,149 +2258,6 @@ handle_srp_extension(undefined, Session) ->
handle_srp_extension(#srp{username = Username}, Session) ->
Session#session{srp_username = Username}.
-%%-------------Misc --------------------------------
-
-select_cipher_suite(CipherSuites, Suites, false) ->
- select_cipher_suite(CipherSuites, Suites);
-select_cipher_suite(CipherSuites, Suites, true) ->
- select_cipher_suite(Suites, CipherSuites).
-
-select_cipher_suite([], _) ->
- no_suite;
-select_cipher_suite([Suite | ClientSuites], SupportedSuites) ->
- case is_member(Suite, SupportedSuites) of
- true ->
- Suite;
- false ->
- select_cipher_suite(ClientSuites, SupportedSuites)
- end.
-
-int_to_bin(I) ->
- L = (length(integer_to_list(I, 16)) + 1) div 2,
- <<I:(L*8)>>.
-
-is_member(Suite, SupportedSuites) ->
- lists:member(Suite, SupportedSuites).
-
-select_compression(_CompressionMetodes) ->
- ?NULL.
-
-available_signature_algs(undefined, _) ->
- undefined;
-available_signature_algs(SupportedHashSigns, Version) when Version >= {3, 3} ->
- #hash_sign_algos{hash_sign_algos = SupportedHashSigns};
-available_signature_algs(_, _) ->
- undefined.
-
-psk_secret(PSKIdentity, PSKLookup) ->
- case handle_psk_identity(PSKIdentity, PSKLookup) of
- {ok, PSK} when is_binary(PSK) ->
- Len = erlang:byte_size(PSK),
- <<?UINT16(Len), 0:(Len*8), ?UINT16(Len), PSK/binary>>;
- #alert{} = Alert ->
- Alert;
- _ ->
- throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
- end.
-
-psk_secret(PSKIdentity, PSKLookup, PremasterSecret) ->
- case handle_psk_identity(PSKIdentity, PSKLookup) of
- {ok, PSK} when is_binary(PSK) ->
- Len = erlang:byte_size(PremasterSecret),
- PSKLen = erlang:byte_size(PSK),
- <<?UINT16(Len), PremasterSecret/binary, ?UINT16(PSKLen), PSK/binary>>;
- #alert{} = Alert ->
- Alert;
- _ ->
- throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
- end.
-
-handle_psk_identity(_PSKIdentity, LookupFun)
- when LookupFun == undefined ->
- error;
-handle_psk_identity(PSKIdentity, {Fun, UserState}) ->
- Fun(psk, PSKIdentity, UserState).
-
-crl_check(_, false, _,_,_, _, _) ->
- valid;
-crl_check(_, peer, _, _,_, valid, _) -> %% Do not check CAs with this option.
- valid;
-crl_check(OtpCert, Check, CertDbHandle, CertDbRef, {Callback, CRLDbHandle}, _, CertPath) ->
- Options = [{issuer_fun, {fun(_DP, CRL, Issuer, DBInfo) ->
- ssl_crl:trusted_cert_and_path(CRL, Issuer, {CertPath,
- DBInfo})
- end, {CertDbHandle, CertDbRef}}},
- {update_crl, fun(DP, CRL) -> Callback:fresh_crl(DP, CRL) end}
- ],
- case dps_and_crls(OtpCert, Callback, CRLDbHandle, ext) of
- no_dps ->
- crl_check_same_issuer(OtpCert, Check,
- dps_and_crls(OtpCert, Callback, CRLDbHandle, same_issuer),
- Options);
- DpsAndCRLs -> %% This DP list may be empty if relevant CRLs existed
- %% but could not be retrived, will result in {bad_cert, revocation_status_undetermined}
- case public_key:pkix_crls_validate(OtpCert, DpsAndCRLs, Options) of
- {bad_cert, revocation_status_undetermined} ->
- crl_check_same_issuer(OtpCert, Check, dps_and_crls(OtpCert, Callback,
- CRLDbHandle, same_issuer), Options);
- Other ->
- Other
- end
- end.
-
-crl_check_same_issuer(OtpCert, best_effort, Dps, Options) ->
- case public_key:pkix_crls_validate(OtpCert, Dps, Options) of
- {bad_cert, revocation_status_undetermined} ->
- valid;
- Other ->
- Other
- end;
-crl_check_same_issuer(OtpCert, _, Dps, Options) ->
- public_key:pkix_crls_validate(OtpCert, Dps, Options).
-
-dps_and_crls(OtpCert, Callback, CRLDbHandle, ext) ->
- case public_key:pkix_dist_points(OtpCert) of
- [] ->
- no_dps;
- DistPoints ->
- Issuer = OtpCert#'OTPCertificate'.tbsCertificate#'OTPTBSCertificate'.issuer,
- CRLs = distpoints_lookup(DistPoints, Issuer, Callback, CRLDbHandle),
- dps_and_crls(DistPoints, CRLs, [])
- end;
-
-dps_and_crls(OtpCert, Callback, CRLDbHandle, same_issuer) ->
- DP = #'DistributionPoint'{distributionPoint = {fullName, GenNames}} =
- public_key:pkix_dist_point(OtpCert),
- CRLs = lists:flatmap(fun({directoryName, Issuer}) ->
- Callback:select(Issuer, CRLDbHandle);
- (_) ->
- []
- end, GenNames),
- [{DP, {CRL, public_key:der_decode('CertificateList', CRL)}} || CRL <- CRLs].
-
-dps_and_crls([], _, Acc) ->
- Acc;
-dps_and_crls([DP | Rest], CRLs, Acc) ->
- DpCRL = [{DP, {CRL, public_key:der_decode('CertificateList', CRL)}} || CRL <- CRLs],
- dps_and_crls(Rest, CRLs, DpCRL ++ Acc).
-
-distpoints_lookup([],_, _, _) ->
- [];
-distpoints_lookup([DistPoint | Rest], Issuer, Callback, CRLDbHandle) ->
- Result =
- try Callback:lookup(DistPoint, Issuer, CRLDbHandle)
- catch
- error:undef ->
- %% The callback module still uses the 2-argument
- %% version of the lookup function.
- Callback:lookup(DistPoint, CRLDbHandle)
- end,
- case Result of
- not_available ->
- distpoints_lookup(Rest, Issuer, Callback, CRLDbHandle);
- CRLs ->
- CRLs
- end.
sign_algo(?rsaEncryption) ->
rsa;
@@ -2271,44 +2269,17 @@ sign_algo(Alg) ->
{_, Sign} =public_key:pkix_sign_types(Alg),
Sign.
-is_acceptable_hash_sign(Algos, _, _, KeyExAlgo, SupportedHashSigns) when
- KeyExAlgo == dh_dss;
- KeyExAlgo == dh_rsa;
- KeyExAlgo == dh_ecdsa ->
- %% dh_* could be called only dh in TLS-1.2
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign(Algos, rsa, ecdsa, ecdh_rsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, rsa} = Algos, rsa, _, dhe_rsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, rsa} = Algos, rsa, rsa, ecdhe_rsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, rsa} = Algos, rsa, rsa, rsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, rsa} = Algos, rsa, _, srp_rsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, rsa} = Algos, rsa, _, rsa_psk, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, dsa} = Algos, dsa, _, dhe_dss, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, dsa} = Algos, dsa, _, srp_dss, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, ecdsa} = Algos, ecdsa, _, dhe_ecdsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, ecdsa} = Algos, ecdsa, ecdsa, ecdh_ecdsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign({_, ecdsa} = Algos, ecdsa, ecdsa, ecdhe_ecdsa, SupportedHashSigns) ->
- is_acceptable_hash_sign(Algos, SupportedHashSigns);
-is_acceptable_hash_sign(_, _, _, KeyExAlgo, _) when
+is_acceptable_hash_sign( _, KeyExAlgo, _) when
KeyExAlgo == psk;
KeyExAlgo == dhe_psk;
+ KeyExAlgo == ecdhe_psk;
KeyExAlgo == srp_anon;
KeyExAlgo == dh_anon;
KeyExAlgo == ecdhe_anon
->
true;
-is_acceptable_hash_sign(_,_, _,_,_) ->
- false.
+is_acceptable_hash_sign(Algos,_, SupportedHashSigns) ->
+ is_acceptable_hash_sign(Algos, SupportedHashSigns).
is_acceptable_hash_sign(Algos, SupportedHashSigns) ->
lists:member(Algos, SupportedHashSigns).
@@ -2329,21 +2300,182 @@ sign_type(dsa) ->
sign_type(ecdsa) ->
?ECDSA_SIGN.
+server_name(_, _, server) ->
+ undefined; %% Not interesting to check your own name.
+server_name(undefined, Host, client) ->
+ {fallback, Host}; %% Fallback to Host argument to connect
+server_name(SNI, _, client) ->
+ SNI. %% If Server Name Indication is available
-bad_key(#'DSAPrivateKey'{}) ->
- unacceptable_dsa_key;
-bad_key(#'RSAPrivateKey'{}) ->
- unacceptable_rsa_key;
-bad_key(#'ECPrivateKey'{}) ->
- unacceptable_ecdsa_key.
+client_ecc_extensions(SupportedECCs) ->
+ CryptoSupport = proplists:get_value(public_keys, crypto:supports()),
+ case proplists:get_bool(ecdh, CryptoSupport) of
+ true ->
+ EcPointFormats = #ec_point_formats{ec_point_format_list = [?ECPOINT_UNCOMPRESSED]},
+ EllipticCurves = SupportedECCs,
+ {EcPointFormats, EllipticCurves};
+ _ ->
+ {undefined, undefined}
+ end.
-available_signature_algs(undefined, SupportedHashSigns, _, Version) when
- Version >= {3,3} ->
- SupportedHashSigns;
-available_signature_algs(#hash_sign_algos{hash_sign_algos = ClientHashSigns}, SupportedHashSigns,
- _, Version) when Version >= {3,3} ->
- sets:to_list(sets:intersection(sets:from_list(ClientHashSigns),
- sets:from_list(SupportedHashSigns)));
-available_signature_algs(_, _, _, _) ->
- undefined.
+server_ecc_extension(_Version, EcPointFormats) ->
+ CryptoSupport = proplists:get_value(public_keys, crypto:supports()),
+ case proplists:get_bool(ecdh, CryptoSupport) of
+ true ->
+ handle_ecc_point_fmt_extension(EcPointFormats);
+ false ->
+ undefined
+ end.
+
+handle_ecc_point_fmt_extension(undefined) ->
+ undefined;
+handle_ecc_point_fmt_extension(_) ->
+ #ec_point_formats{ec_point_format_list = [?ECPOINT_UNCOMPRESSED]}.
+
+advertises_ec_ciphers([]) ->
+ false;
+advertises_ec_ciphers([#{key_exchange := ecdh_ecdsa} | _]) ->
+ true;
+advertises_ec_ciphers([#{key_exchange := ecdhe_ecdsa} | _]) ->
+ true;
+advertises_ec_ciphers([#{key_exchange := ecdh_rsa} | _]) ->
+ true;
+advertises_ec_ciphers([#{key_exchange := ecdhe_rsa} | _]) ->
+ true;
+advertises_ec_ciphers([#{key_exchange := ecdh_anon} | _]) ->
+ true;
+advertises_ec_ciphers([{ecdhe_psk, _,_,_} | _]) ->
+ true;
+advertises_ec_ciphers([_| Rest]) ->
+ advertises_ec_ciphers(Rest).
+
+select_shared_curve([], _) ->
+ no_curve;
+select_shared_curve([Curve | Rest], Curves) ->
+ case lists:member(Curve, Curves) of
+ true ->
+ {namedCurve, Curve};
+ false ->
+ select_shared_curve(Rest, Curves)
+ end.
+
+sni(undefined) ->
+ undefined;
+sni(disable) ->
+ undefined;
+sni(Hostname) ->
+ #sni{hostname = Hostname}.
+
+renegotiation_info(_, client, _, false) ->
+ #renegotiation_info{renegotiated_connection = undefined};
+renegotiation_info(_RecordCB, server, ConnectionStates, false) ->
+ ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
+ case maps:get(secure_renegotiation, ConnectionState) of
+ true ->
+ #renegotiation_info{renegotiated_connection = ?byte(0)};
+ false ->
+ #renegotiation_info{renegotiated_connection = undefined}
+ end;
+renegotiation_info(_RecordCB, client, ConnectionStates, true) ->
+ ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
+ case maps:get(secure_renegotiation, ConnectionState) of
+ true ->
+ Data = maps:get(client_verify_data, ConnectionState),
+ #renegotiation_info{renegotiated_connection = Data};
+ false ->
+ #renegotiation_info{renegotiated_connection = undefined}
+ end;
+
+renegotiation_info(_RecordCB, server, ConnectionStates, true) ->
+ ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
+ case maps:get(secure_renegotiation, ConnectionState) of
+ true ->
+ CData = maps:get(client_verify_data, ConnectionState),
+ SData = maps:get(server_verify_data, ConnectionState),
+ #renegotiation_info{renegotiated_connection = <<CData/binary, SData/binary>>};
+ false ->
+ #renegotiation_info{renegotiated_connection = undefined}
+ end.
+
+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) ->
+ case is_member(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV, CipherSuites) of
+ true ->
+ {ok, ssl_record:set_renegotiation_flag(true, ConnectionStates)};
+ false ->
+ {ok, ssl_record:set_renegotiation_flag(false, ConnectionStates)}
+ end;
+
+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},
+ ConnectionStates, true, _, _) ->
+ ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
+ CData = maps:get(client_verify_data, ConnectionState),
+ SData = maps:get(server_verify_data, ConnectionState),
+ case <<CData/binary, SData/binary>> == ClientServerVerify of
+ true ->
+ {ok, ConnectionStates};
+ false ->
+ ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, client_renegotiation)
+ end;
+handle_renegotiation_info(_RecordCB, server, #renegotiation_info{renegotiated_connection = ClientVerify},
+ ConnectionStates, true, _, CipherSuites) ->
+
+ case is_member(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV, CipherSuites) of
+ true ->
+ ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, {server_renegotiation, empty_renegotiation_info_scsv});
+ false ->
+ ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
+ Data = maps:get(client_verify_data, ConnectionState),
+ case Data == ClientVerify of
+ true ->
+ {ok, ConnectionStates};
+ false ->
+ ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, server_renegotiation)
+ end
+ end;
+
+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) ->
+ case is_member(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV, CipherSuites) of
+ true ->
+ ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, {server_renegotiation, empty_renegotiation_info_scsv});
+ false ->
+ handle_renegotiation_info(RecordCB, ConnectionStates, SecureRenegotation)
+ end.
+
+handle_renegotiation_info(_RecordCB, ConnectionStates, SecureRenegotation) ->
+ ConnectionState = ssl_record:current_connection_state(ConnectionStates, read),
+ case {SecureRenegotation, maps:get(secure_renegotiation, ConnectionState)} of
+ {_, true} ->
+ ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, already_secure);
+ {true, false} ->
+ ?ALERT_REC(?FATAL, ?NO_RENEGOTIATION);
+ {false, false} ->
+ {ok, ConnectionStates}
+ end.
+
+cert_curve(_, _, no_suite) ->
+ {no_curve, no_suite};
+cert_curve(Cert, ECCCurve0, CipherSuite) ->
+ case ssl_cipher_format:suite_definition(CipherSuite) of
+ #{key_exchange := Kex} when Kex == ecdh_ecdsa;
+ Kex == ecdh_rsa ->
+ OtpCert = public_key:pkix_decode_cert(Cert, otp),
+ TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
+ #'OTPSubjectPublicKeyInfo'{algorithm = AlgInfo}
+ = TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo,
+ {namedCurve, Oid} = AlgInfo#'PublicKeyAlgorithm'.parameters,
+ {{namedCurve, Oid}, CipherSuite};
+ _ ->
+ {ECCCurve0, CipherSuite}
+ end.
+
diff --git a/lib/ssl/src/ssl_handshake.hrl b/lib/ssl/src/ssl_handshake.hrl
index 324b7dbde3..a191fcf766 100644
--- a/lib/ssl/src/ssl_handshake.hrl
+++ b/lib/ssl/src/ssl_handshake.hrl
@@ -133,6 +133,7 @@
-define(KEY_EXCHANGE_DIFFIE_HELLMAN, 1).
-define(KEY_EXCHANGE_EC_DIFFIE_HELLMAN, 6).
-define(KEY_EXCHANGE_PSK, 2).
+-define(KEY_EXCHANGE_EC_DIFFIE_HELLMAN_PSK, 7).
-define(KEY_EXCHANGE_DHE_PSK, 3).
-define(KEY_EXCHANGE_RSA_PSK, 4).
-define(KEY_EXCHANGE_SRP, 5).
@@ -162,6 +163,11 @@
dh_params
}).
+-record(server_ecdhe_psk_params, {
+ hint,
+ dh_params
+ }).
+
-record(server_srp_params, {
srp_n, %% opaque srp_N<1..2^16-1>
srp_g, %% opaque srp_g<1..2^16-1>
@@ -254,6 +260,11 @@
dh_public
}).
+-record(client_ecdhe_psk_identity, {
+ identity,
+ dh_public
+ }).
+
-record(client_rsa_psk_identity, {
identity,
exchange_keys
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index 24ac34653e..fd246e2550 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -73,6 +73,7 @@
%% sslv3 is considered insecure due to lack of padding check (Poodle attack)
%% Keep as interop with legacy software but do not support as default
-define(ALL_AVAILABLE_VERSIONS, ['tlsv1.2', 'tlsv1.1', tlsv1, sslv3]).
+-define(ALL_AVAILABLE_DATAGRAM_VERSIONS, ['dtlsv1.2', dtlsv1]).
-define(ALL_SUPPORTED_VERSIONS, ['tlsv1.2', 'tlsv1.1', tlsv1]).
-define(MIN_SUPPORTED_VERSIONS, ['tlsv1.1', tlsv1]).
-define(ALL_DATAGRAM_SUPPORTED_VERSIONS, ['dtlsv1.2', dtlsv1]).
@@ -95,7 +96,8 @@
certfile :: binary(),
cert :: public_key:der_encoded() | secret_printout() | 'undefined',
keyfile :: binary(),
- key :: {'RSAPrivateKey' | 'DSAPrivateKey' | 'ECPrivateKey' | 'PrivateKeyInfo', public_key:der_encoded()} | secret_printout() | 'undefined',
+ key :: {'RSAPrivateKey' | 'DSAPrivateKey' | 'ECPrivateKey' | 'PrivateKeyInfo',
+ public_key:der_encoded()} | key_map() | secret_printout() | 'undefined',
password :: string() | secret_printout() | 'undefined',
cacerts :: [public_key:der_encoded()] | secret_printout() | 'undefined',
cacertfile :: binary(),
@@ -118,7 +120,7 @@
%% undefined if not hibernating, or number of ms of
%% inactivity after which ssl_connection will go into
%% hibernation
- hibernate_after :: timeout(),
+ hibernate_after :: timeout(),
%% This option should only be set to true by inet_tls_dist
erl_dist = false :: boolean(),
alpn_advertised_protocols = undefined :: [binary()] | undefined ,
@@ -142,8 +144,9 @@
signature_algs,
eccs,
honor_ecc_order :: boolean(),
- v2_hello_compatible :: boolean(),
- max_handshake_size :: integer()
+ max_handshake_size :: integer(),
+ handshake,
+ customize_hostname_check
}).
-record(socket_options,
@@ -158,13 +161,21 @@
-record(config, {ssl, %% SSL parameters
inet_user, %% User set inet options
emulated, %% Emulated option list or "inherit_tracker" pid
- udp_handler,
+ dtls_handler,
inet_ssl, %% inet options for internal ssl socket
transport_info, %% Callback info
connection_cb
}).
-
+-type key_map() :: #{algorithm := rsa | dss | ecdsa,
+ %% engine and key_id ought to
+ %% be :=, but putting it in
+ %% the spec gives dialyzer warning
+ %% of correct code!
+ engine => crypto:engine_ref(),
+ key_id => crypto:key_id(),
+ password => crypto:password()
+ }.
-type state_name() :: hello | abbreviated | certify | cipher | connection.
-type gen_fsm_state_return() :: {next_state, state_name(), term()} |
{next_state, state_name(), term(), timeout()} |
diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl
index ca9aaf4660..4b735b2400 100644
--- a/lib/ssl/src/ssl_manager.erl
+++ b/lib/ssl/src/ssl_manager.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -78,7 +78,7 @@
name(normal) ->
?MODULE;
name(dist) ->
- list_to_atom(atom_to_list(?MODULE) ++ "dist").
+ list_to_atom(atom_to_list(?MODULE) ++ "_dist").
%%--------------------------------------------------------------------
-spec start_link(list()) -> {ok, pid()} | ignore | {error, term()}.
@@ -127,7 +127,13 @@ cache_pem_file(File, DbHandle) ->
[Content] ->
{ok, Content};
undefined ->
- ssl_pem_cache:insert(File)
+ case ssl_pkix_db:decode_pem_file(File) of
+ {ok, Content} ->
+ ssl_pem_cache:insert(File, Content),
+ {ok, Content};
+ Error ->
+ Error
+ end
end.
%%--------------------------------------------------------------------
@@ -563,7 +569,7 @@ server_register_session(Port, Session, #state{session_cache_server_max = Max,
do_register_session(Key, Session, Max, Pid, Cache, CacheCb) ->
try CacheCb:size(Cache) of
- Max ->
+ Size when Size >= Max ->
invalidate_session_cache(Pid, CacheCb, Cache);
_ ->
CacheCb:update(Cache, Key, Session),
diff --git a/lib/ssl/src/ssl_pem_cache.erl b/lib/ssl/src/ssl_pem_cache.erl
index 6cc0729208..b7d23ef01e 100644
--- a/lib/ssl/src/ssl_pem_cache.erl
+++ b/lib/ssl/src/ssl_pem_cache.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 20016-2017. All Rights Reserved.
+%% Copyright Ericsson AB 20016-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,7 @@
-export([start_link/1,
start_link_dist/1,
name/1,
- insert/1,
+ insert/2,
clear/0]).
% Spawn export
@@ -65,7 +65,7 @@
name(normal) ->
?MODULE;
name(dist) ->
- list_to_atom(atom_to_list(?MODULE) ++ "dist").
+ list_to_atom(atom_to_list(?MODULE) ++ "_dist").
%%--------------------------------------------------------------------
-spec start_link(list()) -> {ok, pid()} | ignore | {error, term()}.
@@ -90,19 +90,17 @@ start_link_dist(_) ->
%%--------------------------------------------------------------------
--spec insert(binary()) -> {ok, term()} | {error, reason()}.
+-spec insert(binary(), term()) -> ok | {error, reason()}.
%%
%% Description: Cache a pem file and return its content.
%%--------------------------------------------------------------------
-insert(File) ->
- {ok, PemBin} = file:read_file(File),
- Content = public_key:pem_decode(PemBin),
+insert(File, Content) ->
case bypass_cache() of
true ->
- {ok, Content};
+ ok;
false ->
cast({cache_pem, File, Content}),
- {ok, Content}
+ ok
end.
%%--------------------------------------------------------------------
diff --git a/lib/ssl/src/ssl_pkix_db.erl b/lib/ssl/src/ssl_pkix_db.erl
index b28636569d..f7ddbd060e 100644
--- a/lib/ssl/src/ssl_pkix_db.erl
+++ b/lib/ssl/src/ssl_pkix_db.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -76,10 +76,17 @@ remove(Dbs) ->
true = ets:delete(Db1);
(undefined) ->
ok;
- (ssl_pem_cache) ->
- ok;
- (ssl_pem_cache_dist) ->
- ok;
+ (Name) when is_atom(Name) ->
+ NormalName = ssl_pem_cache:name(normal),
+ DistName = ssl_pem_cache:name(dist),
+ case Name of
+ NormalName ->
+ ok;
+ DistName ->
+ ok;
+ _ ->
+ true = ets:delete(Name)
+ end;
(Db) ->
true = ets:delete(Db)
end, Dbs).
@@ -150,7 +157,7 @@ extract_trusted_certs(File) ->
{error, {badmatch, Error}}
end.
--spec decode_pem_file(binary()) -> {ok, term()}.
+-spec decode_pem_file(binary()) -> {ok, term()} | {error, term()}.
decode_pem_file(File) ->
case file:read_file(File) of
{ok, PemBin} ->
@@ -309,11 +316,16 @@ decode_certs(Ref, Cert) ->
end.
new_trusted_cert_entry(File, [CertsDb, RefsDb, _ | _]) ->
- Ref = make_ref(),
- init_ref_db(Ref, File, RefsDb),
- {ok, Content} = ssl_pem_cache:insert(File),
- add_certs_from_pem(Content, Ref, CertsDb),
- {ok, Ref}.
+ case decode_pem_file(File) of
+ {ok, Content} ->
+ Ref = make_ref(),
+ init_ref_db(Ref, File, RefsDb),
+ ok = ssl_pem_cache:insert(File, Content),
+ add_certs_from_pem(Content, Ref, CertsDb),
+ {ok, Ref};
+ Error ->
+ Error
+ end.
add_crls([_,_,_, {_, Mapping} | _], ?NO_DIST_POINT, CRLs) ->
[add_crls(CRL, Mapping) || CRL <- CRLs];
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index 62c2ffce8b..659e1485ac 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@
%% Connection state handling
-export([initial_security_params/1, current_connection_state/2, pending_connection_state/2,
- activate_pending_connection_state/2,
+ activate_pending_connection_state/3,
set_security_params/3,
set_mac_secret/4,
set_master_secret/2,
@@ -53,11 +53,11 @@
-type ssl_atom_version() :: tls_record:tls_atom_version().
-type connection_states() :: term(). %% Map
-type connection_state() :: term(). %% Map
+
%%====================================================================
-%% Internal application API
+%% Connection state handling
%%====================================================================
-
%%--------------------------------------------------------------------
-spec current_connection_state(connection_states(), read | write) ->
connection_state().
@@ -83,7 +83,7 @@ pending_connection_state(ConnectionStates, write) ->
maps:get(pending_write, ConnectionStates).
%%--------------------------------------------------------------------
--spec activate_pending_connection_state(connection_states(), read | write) ->
+-spec activate_pending_connection_state(connection_states(), read | write, tls_connection | dtls_connection) ->
connection_states().
%%
%% Description: Creates a new instance of the connection_states record
@@ -91,13 +91,13 @@ pending_connection_state(ConnectionStates, write) ->
%%--------------------------------------------------------------------
activate_pending_connection_state(#{current_read := Current,
pending_read := Pending} = States,
- read) ->
+ read, Connection) ->
#{secure_renegotiation := SecureRenegotation} = Current,
#{beast_mitigation := BeastMitigation,
security_parameters := SecParams} = Pending,
NewCurrent = Pending#{sequence_number => 0},
ConnectionEnd = SecParams#security_parameters.connection_end,
- EmptyPending = empty_connection_state(ConnectionEnd, BeastMitigation),
+ EmptyPending = Connection:empty_connection_state(ConnectionEnd, BeastMitigation),
NewPending = EmptyPending#{secure_renegotiation => SecureRenegotation},
States#{current_read => NewCurrent,
pending_read => NewPending
@@ -105,13 +105,13 @@ activate_pending_connection_state(#{current_read := Current,
activate_pending_connection_state(#{current_write := Current,
pending_write := Pending} = States,
- write) ->
+ write, Connection) ->
NewCurrent = Pending#{sequence_number => 0},
#{secure_renegotiation := SecureRenegotation} = Current,
#{beast_mitigation := BeastMitigation,
security_parameters := SecParams} = Pending,
ConnectionEnd = SecParams#security_parameters.connection_end,
- EmptyPending = empty_connection_state(ConnectionEnd, BeastMitigation),
+ EmptyPending = Connection:empty_connection_state(ConnectionEnd, BeastMitigation),
NewPending = EmptyPending#{secure_renegotiation => SecureRenegotation},
States#{current_write => NewCurrent,
pending_write => NewPending
@@ -267,6 +267,9 @@ set_pending_cipher_state(#{pending_read := Read,
pending_read => Read#{cipher_state => ServerState},
pending_write => Write#{cipher_state => ClientState}}.
+%%====================================================================
+%% Compression
+%%====================================================================
uncompress(?NULL, Data, CS) ->
{Data, CS}.
@@ -282,6 +285,11 @@ compress(?NULL, Data, CS) ->
compressions() ->
[?byte(?NULL)].
+
+%%====================================================================
+%% Payload encryption/decryption
+%%====================================================================
+
%%--------------------------------------------------------------------
-spec cipher(ssl_version(), iodata(), connection_state(), MacHash::binary()) ->
{CipherFragment::binary(), connection_state()}.
@@ -318,7 +326,7 @@ cipher_aead(Version, Fragment,
%%--------------------------------------------------------------------
-spec decipher(ssl_version(), binary(), connection_state(), boolean()) ->
- {binary(), binary(), connection_state} | #alert{}.
+ {binary(), binary(), connection_state()} | #alert{}.
%%
%% Description: Payload decryption
%%--------------------------------------------------------------------
diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl
deleted file mode 100644
index 08947f24dd..0000000000
--- a/lib/ssl/src/ssl_tls_dist_proxy.erl
+++ /dev/null
@@ -1,479 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
--module(ssl_tls_dist_proxy).
-
-
--export([listen/2, accept/2, connect/3, get_tcp_address/1]).
--export([init/1, start_link/0, handle_call/3, handle_cast/2, handle_info/2,
- terminate/2, code_change/3, ssl_options/2]).
-
--include_lib("kernel/include/net_address.hrl").
-
--record(state,
- {listen,
- accept_loop
- }).
-
--define(PPRE, 4).
--define(PPOST, 4).
-
-
-%%====================================================================
-%% Internal application API
-%%====================================================================
-
-listen(Driver, Name) ->
- gen_server:call(?MODULE, {listen, Driver, Name}, infinity).
-
-accept(Driver, Listen) ->
- gen_server:call(?MODULE, {accept, Driver, Listen}, infinity).
-
-connect(Driver, Ip, Port) ->
- gen_server:call(?MODULE, {connect, Driver, Ip, Port}, infinity).
-
-
-do_listen(Options) ->
- {First,Last} = case application:get_env(kernel,inet_dist_listen_min) of
- {ok,N} when is_integer(N) ->
- case application:get_env(kernel,
- inet_dist_listen_max) of
- {ok,M} when is_integer(M) ->
- {N,M};
- _ ->
- {N,N}
- end;
- _ ->
- {0,0}
- end,
- do_listen(First, Last, listen_options([{backlog,128}|Options])).
-
-do_listen(First,Last,_) when First > Last ->
- {error,eaddrinuse};
-do_listen(First,Last,Options) ->
- case gen_tcp:listen(First, Options) of
- {error, eaddrinuse} ->
- do_listen(First+1,Last,Options);
- Other ->
- Other
- end.
-
-listen_options(Opts0) ->
- Opts1 =
- case application:get_env(kernel, inet_dist_use_interface) of
- {ok, Ip} ->
- [{ip, Ip} | Opts0];
- _ ->
- Opts0
- end,
- case application:get_env(kernel, inet_dist_listen_options) of
- {ok,ListenOpts} ->
- ListenOpts ++ Opts1;
- _ ->
- Opts1
- end.
-
-connect_options(Opts) ->
- case application:get_env(kernel, inet_dist_connect_options) of
- {ok,ConnectOpts} ->
- lists:ukeysort(1, ConnectOpts ++ Opts);
- _ ->
- Opts
- end.
-
-%%====================================================================
-%% gen_server callbacks
-%%====================================================================
-
-start_link() ->
- gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
-
-init([]) ->
- process_flag(priority, max),
- {ok, #state{}}.
-
-handle_call({listen, Driver, Name}, _From, State) ->
- case gen_tcp:listen(0, [{active, false}, {packet,?PPRE}, {ip, loopback}]) of
- {ok, Socket} ->
- {ok, World} = do_listen([{active, false}, binary, {packet,?PPRE}, {reuseaddr, true},
- Driver:family()]),
- {ok, TcpAddress} = get_tcp_address(Socket),
- {ok, WorldTcpAddress} = get_tcp_address(World),
- {_,Port} = WorldTcpAddress#net_address.address,
- ErlEpmd = net_kernel:epmd_module(),
- case ErlEpmd:register_node(Name, Port, Driver) of
- {ok, Creation} ->
- {reply, {ok, {Socket, TcpAddress, Creation}},
- State#state{listen={Socket, World}}};
- {error, _} = Error ->
- {reply, Error, State}
- end;
- Error ->
- {reply, Error, State}
- end;
-
-handle_call({accept, _Driver, Listen}, {From, _}, State = #state{listen={_, World}}) ->
- Self = self(),
- ErtsPid = spawn_link(fun() -> accept_loop(Self, erts, Listen, From) end),
- WorldPid = spawn_link(fun() -> accept_loop(Self, world, World, Listen) end),
- {reply, ErtsPid, State#state{accept_loop={ErtsPid, WorldPid}}};
-
-handle_call({connect, Driver, Ip, Port}, {From, _}, State) ->
- Me = self(),
- Pid = spawn_link(fun() -> setup_proxy(Driver, Ip, Port, Me) end),
- receive
- {Pid, go_ahead, LPort} ->
- Res = {ok, Socket} = try_connect(LPort),
- case gen_tcp:controlling_process(Socket, From) of
- {error, badarg} = Error -> {reply, Error, State}; % From is dead anyway.
- ok ->
- flush_old_controller(From, Socket),
- {reply, Res, State}
- end;
- {Pid, Error} ->
- {reply, Error, State}
- end;
-
-handle_call(_What, _From, State) ->
- {reply, ok, State}.
-
-handle_cast(_What, State) ->
- {noreply, State}.
-
-handle_info(_What, State) ->
- {noreply, State}.
-
-terminate(_Reason, _St) ->
- ok.
-
-code_change(_OldVsn, St, _Extra) ->
- {ok, St}.
-
-%%--------------------------------------------------------------------
-%%% Internal functions
-%%--------------------------------------------------------------------
-get_tcp_address(Socket) ->
- case inet:sockname(Socket) of
- {ok, Address} ->
- {ok, Host} = inet:gethostname(),
- NetAddress = #net_address{
- address = Address,
- host = Host,
- protocol = proxy,
- family = inet
- },
- {ok, NetAddress};
- {error, _} = Error -> Error
- end.
-
-accept_loop(Proxy, erts = Type, Listen, Extra) ->
- process_flag(priority, max),
- case gen_tcp:accept(Listen) of
- {ok, Socket} ->
- Extra ! {accept,self(),Socket,inet,proxy},
- receive
- {_Kernel, controller, Pid} ->
- inet:setopts(Socket, [nodelay()]),
- ok = gen_tcp:controlling_process(Socket, Pid),
- flush_old_controller(Pid, Socket),
- Pid ! {self(), controller};
- {_Kernel, unsupported_protocol} ->
- exit(unsupported_protocol)
- end;
- {error, closed} ->
- %% The listening socket is closed: the proxy process is
- %% shutting down. Exit normally, to avoid generating a
- %% spurious error report.
- exit(normal);
- Error ->
- exit(Error)
- end,
- accept_loop(Proxy, Type, Listen, Extra);
-
-accept_loop(Proxy, world = Type, Listen, Extra) ->
- process_flag(priority, max),
- case gen_tcp:accept(Listen) of
- {ok, Socket} ->
- Opts = get_ssl_options(server),
- wait_for_code_server(),
- case ssl:ssl_accept(Socket, Opts) of
- {ok, SslSocket} ->
- PairHandler =
- spawn_link(fun() ->
- setup_connection(SslSocket, Extra)
- end),
- ok = ssl:controlling_process(SslSocket, PairHandler),
- flush_old_controller(PairHandler, SslSocket);
- {error, {options, _}} = Error ->
- %% Bad options: that's probably our fault. Let's log that.
- error_logger:error_msg("Cannot accept TLS distribution connection: ~s~n",
- [ssl:format_error(Error)]),
- gen_tcp:close(Socket);
- _ ->
- gen_tcp:close(Socket)
- end;
- Error ->
- exit(Error)
- end,
- accept_loop(Proxy, Type, Listen, Extra).
-
-wait_for_code_server() ->
- %% This is an ugly hack. Upgrading a socket to TLS requires the
- %% crypto module to be loaded. Loading the crypto module triggers
- %% its on_load function, which calls code:priv_dir/1 to find the
- %% directory where its NIF library is. However, distribution is
- %% started earlier than the code server, so the code server is not
- %% necessarily started yet, and code:priv_dir/1 might fail because
- %% of that, if we receive an incoming connection on the
- %% distribution port early enough.
- %%
- %% If the on_load function of a module fails, the module is
- %% unloaded, and the function call that triggered loading it fails
- %% with 'undef', which is rather confusing.
- %%
- %% Thus, the ssl_tls_dist_proxy process will terminate, and be
- %% restarted by ssl_dist_sup. However, it won't have any memory
- %% of being asked by net_kernel to listen for incoming
- %% connections. Hence, the node will believe that it's open for
- %% distribution, but it actually isn't.
- %%
- %% So let's avoid that by waiting for the code server to start.
- case whereis(code_server) of
- undefined ->
- timer:sleep(10),
- wait_for_code_server();
- Pid when is_pid(Pid) ->
- ok
- end.
-
-try_connect(Port) ->
- case gen_tcp:connect({127,0,0,1}, Port, [{active, false}, {packet,?PPRE}, nodelay()]) of
- R = {ok, _S} ->
- R;
- {error, _R} ->
- try_connect(Port)
- end.
-
-setup_proxy(Driver, Ip, Port, Parent) ->
- process_flag(trap_exit, true),
- Opts = connect_options(get_ssl_options(client)),
- case ssl:connect(Ip, Port, [{active, true}, binary, {packet,?PPRE}, nodelay(),
- Driver:family()] ++ Opts) of
- {ok, World} ->
- {ok, ErtsL} = gen_tcp:listen(0, [{active, true}, {ip, loopback}, binary, {packet,?PPRE}]),
- {ok, #net_address{address={_,LPort}}} = get_tcp_address(ErtsL),
- Parent ! {self(), go_ahead, LPort},
- case gen_tcp:accept(ErtsL) of
- {ok, Erts} ->
- %% gen_tcp:close(ErtsL),
- loop_conn_setup(World, Erts);
- Err ->
- Parent ! {self(), Err}
- end;
- {error, {options, _}} = Err ->
- %% Bad options: that's probably our fault. Let's log that.
- error_logger:error_msg("Cannot open TLS distribution connection: ~s~n",
- [ssl:format_error(Err)]),
- Parent ! {self(), Err};
- Err ->
- Parent ! {self(), Err}
- end.
-
-
-%% we may not always want the nodelay behaviour
-%% %% for performance reasons
-
-nodelay() ->
- case application:get_env(kernel, dist_nodelay) of
- undefined ->
- {nodelay, true};
- {ok, true} ->
- {nodelay, true};
- {ok, false} ->
- {nodelay, false};
- _ ->
- {nodelay, true}
- end.
-
-setup_connection(World, ErtsListen) ->
- process_flag(trap_exit, true),
- {ok, TcpAddress} = get_tcp_address(ErtsListen),
- {_Addr,Port} = TcpAddress#net_address.address,
- {ok, Erts} = gen_tcp:connect({127,0,0,1}, Port, [{active, true}, binary, {packet,?PPRE}, nodelay()]),
- ssl:setopts(World, [{active,true}, {packet,?PPRE}, nodelay()]),
- loop_conn_setup(World, Erts).
-
-loop_conn_setup(World, Erts) ->
- receive
- {ssl, World, Data = <<$a, _/binary>>} ->
- gen_tcp:send(Erts, Data),
- ssl:setopts(World, [{packet,?PPOST}, nodelay()]),
- inet:setopts(Erts, [{packet,?PPOST}, nodelay()]),
- loop_conn(World, Erts);
- {tcp, Erts, Data = <<$a, _/binary>>} ->
- ssl:send(World, Data),
- ssl:setopts(World, [{packet,?PPOST}, nodelay()]),
- inet:setopts(Erts, [{packet,?PPOST}, nodelay()]),
- loop_conn(World, Erts);
- {ssl, World, Data = <<_, _/binary>>} ->
- gen_tcp:send(Erts, Data),
- loop_conn_setup(World, Erts);
- {tcp, Erts, Data = <<_, _/binary>>} ->
- ssl:send(World, Data),
- loop_conn_setup(World, Erts);
- {ssl, World, Data} ->
- gen_tcp:send(Erts, Data),
- loop_conn_setup(World, Erts);
- {tcp, Erts, Data} ->
- ssl:send(World, Data),
- loop_conn_setup(World, Erts);
- {tcp_closed, Erts} ->
- ssl:close(World);
- {ssl_closed, World} ->
- gen_tcp:close(Erts);
- {ssl_error, World, _} ->
-
- ssl:close(World)
- end.
-
-loop_conn(World, Erts) ->
- receive
- {ssl, World, Data} ->
- gen_tcp:send(Erts, Data),
- loop_conn(World, Erts);
- {tcp, Erts, Data} ->
- ssl:send(World, Data),
- loop_conn(World, Erts);
- {tcp_closed, Erts} ->
- ssl:close(World);
- {ssl_closed, World} ->
- gen_tcp:close(Erts);
- {ssl_error, World, _} ->
- ssl:close(World)
- end.
-
-get_ssl_options(Type) ->
- case init:get_argument(ssl_dist_opt) of
- {ok, Args} ->
- [{erl_dist, true} | ssl_options(Type, lists:append(Args))];
- _ ->
- [{erl_dist, true}]
- end.
-
-ssl_options(_,[]) ->
- [];
-ssl_options(server, ["client_" ++ _, _Value |T]) ->
- ssl_options(server,T);
-ssl_options(client, ["server_" ++ _, _Value|T]) ->
- ssl_options(client,T);
-ssl_options(server, ["server_certfile", Value|T]) ->
- [{certfile, Value} | ssl_options(server,T)];
-ssl_options(client, ["client_certfile", Value | T]) ->
- [{certfile, Value} | ssl_options(client,T)];
-ssl_options(server, ["server_cacertfile", Value|T]) ->
- [{cacertfile, Value} | ssl_options(server,T)];
-ssl_options(client, ["client_cacertfile", Value|T]) ->
- [{cacertfile, Value} | ssl_options(client,T)];
-ssl_options(server, ["server_keyfile", Value|T]) ->
- [{keyfile, Value} | ssl_options(server,T)];
-ssl_options(client, ["client_keyfile", Value|T]) ->
- [{keyfile, Value} | ssl_options(client,T)];
-ssl_options(server, ["server_password", Value|T]) ->
- [{password, Value} | ssl_options(server,T)];
-ssl_options(client, ["client_password", Value|T]) ->
- [{password, Value} | ssl_options(client,T)];
-ssl_options(server, ["server_verify", Value|T]) ->
- [{verify, atomize(Value)} | ssl_options(server,T)];
-ssl_options(client, ["client_verify", Value|T]) ->
- [{verify, atomize(Value)} | ssl_options(client,T)];
-ssl_options(server, ["server_verify_fun", Value|T]) ->
- [{verify_fun, verify_fun(Value)} | ssl_options(server,T)];
-ssl_options(client, ["client_verify_fun", Value|T]) ->
- [{verify_fun, verify_fun(Value)} | ssl_options(client,T)];
-ssl_options(server, ["server_crl_check", Value|T]) ->
- [{crl_check, atomize(Value)} | ssl_options(server,T)];
-ssl_options(client, ["client_crl_check", Value|T]) ->
- [{crl_check, atomize(Value)} | ssl_options(client,T)];
-ssl_options(server, ["server_crl_cache", Value|T]) ->
- [{crl_cache, termify(Value)} | ssl_options(server,T)];
-ssl_options(client, ["client_crl_cache", Value|T]) ->
- [{crl_cache, termify(Value)} | ssl_options(client,T)];
-ssl_options(server, ["server_reuse_sessions", Value|T]) ->
- [{reuse_sessions, atomize(Value)} | ssl_options(server,T)];
-ssl_options(client, ["client_reuse_sessions", Value|T]) ->
- [{reuse_sessions, atomize(Value)} | ssl_options(client,T)];
-ssl_options(server, ["server_secure_renegotiate", Value|T]) ->
- [{secure_renegotiate, atomize(Value)} | ssl_options(server,T)];
-ssl_options(client, ["client_secure_renegotiate", Value|T]) ->
- [{secure_renegotiate, atomize(Value)} | ssl_options(client,T)];
-ssl_options(server, ["server_depth", Value|T]) ->
- [{depth, list_to_integer(Value)} | ssl_options(server,T)];
-ssl_options(client, ["client_depth", Value|T]) ->
- [{depth, list_to_integer(Value)} | ssl_options(client,T)];
-ssl_options(server, ["server_hibernate_after", Value|T]) ->
- [{hibernate_after, list_to_integer(Value)} | ssl_options(server,T)];
-ssl_options(client, ["client_hibernate_after", Value|T]) ->
- [{hibernate_after, list_to_integer(Value)} | ssl_options(client,T)];
-ssl_options(server, ["server_ciphers", Value|T]) ->
- [{ciphers, Value} | ssl_options(server,T)];
-ssl_options(client, ["client_ciphers", Value|T]) ->
- [{ciphers, Value} | ssl_options(client,T)];
-ssl_options(server, ["server_dhfile", Value|T]) ->
- [{dhfile, Value} | ssl_options(server,T)];
-ssl_options(server, ["server_fail_if_no_peer_cert", Value|T]) ->
- [{fail_if_no_peer_cert, atomize(Value)} | ssl_options(server,T)];
-ssl_options(Type, Opts) ->
- error(malformed_ssl_dist_opt, [Type, Opts]).
-
-atomize(List) when is_list(List) ->
- list_to_atom(List);
-atomize(Atom) when is_atom(Atom) ->
- Atom.
-
-termify(String) when is_list(String) ->
- {ok, Tokens, _} = erl_scan:string(String ++ "."),
- {ok, Term} = erl_parse:parse_term(Tokens),
- Term.
-
-verify_fun(Value) ->
- case termify(Value) of
- {Mod, Func, State} when is_atom(Mod), is_atom(Func) ->
- Fun = fun Mod:Func/3,
- {Fun, State};
- _ ->
- error(malformed_ssl_dist_opt, [Value])
- end.
-
-flush_old_controller(Pid, Socket) ->
- receive
- {tcp, Socket, Data} ->
- Pid ! {tcp, Socket, Data},
- flush_old_controller(Pid, Socket);
- {tcp_closed, Socket} ->
- Pid ! {tcp_closed, Socket},
- flush_old_controller(Pid, Socket);
- {ssl, Socket, Data} ->
- Pid ! {ssl, Socket, Data},
- flush_old_controller(Pid, Socket);
- {ssl_closed, Socket} ->
- Pid ! {ssl_closed, Socket},
- flush_old_controller(Pid, Socket)
- after 0 ->
- ok
- end.
diff --git a/lib/ssl/src/ssl_v2.erl b/lib/ssl/src/ssl_v2.erl
deleted file mode 100644
index 37134cbe5d..0000000000
--- a/lib/ssl/src/ssl_v2.erl
+++ /dev/null
@@ -1,38 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-%%----------------------------------------------------------------------
-%% Purpose: Handles sslv2 hello as clients supporting sslv2 and higher
-%% will send an sslv2 hello.
-%%----------------------------------------------------------------------
-
--module(ssl_v2).
-
--export([client_random/2]).
-
-client_random(ChallengeData, 32) ->
- ChallengeData;
-client_random(ChallengeData, N) when N > 32 ->
- <<NewChallengeData:32/binary, _/binary>> = ChallengeData,
- NewChallengeData;
-client_random(ChallengeData, N) ->
- Pad = list_to_binary(lists:duplicate(N, 0)),
- <<Pad/binary, ChallengeData/binary>>.
diff --git a/lib/ssl/src/ssl_v3.erl b/lib/ssl/src/ssl_v3.erl
index 82d165f995..4eab60b440 100644
--- a/lib/ssl/src/ssl_v3.erl
+++ b/lib/ssl/src/ssl_v3.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -131,7 +131,7 @@ setup_keys(MasterSecret, ServerRandom, ClientRandom, HS, KML, _EKML, IVS) ->
{ClientWriteMacSecret, ServerWriteMacSecret, ClientWriteKey,
ServerWriteKey, ClientIV, ServerIV}.
--spec suites() -> [ssl_cipher:cipher_suite()].
+-spec suites() -> [ssl_cipher_format:cipher_suite()].
suites() ->
[
diff --git a/lib/ssl/src/tls.erl b/lib/ssl/src/tls.erl
deleted file mode 100644
index aa41cd1ba6..0000000000
--- a/lib/ssl/src/tls.erl
+++ /dev/null
@@ -1,112 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
-%%% Purpose : Reflect TLS specific API options (fairly simple wrapper at the moment)
-
--module(tls).
-
--include("ssl_api.hrl").
--include("ssl_internal.hrl").
-
--export([connect/2, connect/3, listen/2, accept/1, accept/2,
- handshake/1, handshake/2, handshake/3]).
-
-%%--------------------------------------------------------------------
-%%
-%% Description: Connect to an TLS server.
-%%--------------------------------------------------------------------
-
--spec connect(host() | port(), [connect_option()]) -> {ok, #sslsocket{}} |
- {error, reason()}.
-
-connect(Socket, Options) when is_port(Socket) ->
- connect(Socket, Options, infinity).
-
--spec connect(host() | port(), [connect_option()] | inet:port_number(),
- timeout() | list()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
-connect(Socket, SslOptions, Timeout) when is_port(Socket) ->
- TLSOpts = [{protocol, tls} | SslOptions],
- ssl:connect(Socket, TLSOpts, Timeout);
-connect(Host, Port, Options) ->
- connect(Host, Port, Options, infinity).
-
--spec connect(host() | port(), inet:port_number(), list(), timeout()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
-connect(Host, Port, Options, Timeout) ->
- TLSOpts = [{protocol, tls} | Options],
- ssl:connect(Host, Port, TLSOpts, Timeout).
-
-%%--------------------------------------------------------------------
--spec listen(inet:port_number(), [listen_option()]) ->{ok, #sslsocket{}} | {error, reason()}.
-
-%%
-%% Description: Creates an ssl listen socket.
-%%--------------------------------------------------------------------
-listen(Port, Options) ->
- TLSOpts = [{protocol, tls} | Options],
- ssl:listen(Port, TLSOpts).
-
-%%--------------------------------------------------------------------
-%%
-%% Description: Performs transport accept on an ssl listen socket
-%%--------------------------------------------------------------------
--spec accept(#sslsocket{}) -> {ok, #sslsocket{}} |
- {error, reason()}.
-accept(ListenSocket) ->
- accept(ListenSocket, infinity).
-
--spec accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} |
- {error, reason()}.
-accept(Socket, Timeout) ->
- ssl:transport_accept(Socket, Timeout).
-
-%%--------------------------------------------------------------------
-%%
-%% Description: Performs accept on an ssl listen socket. e.i. performs
-%% ssl handshake.
-%%--------------------------------------------------------------------
-
--spec handshake(#sslsocket{}) -> ok | {error, reason()}.
-
-handshake(ListenSocket) ->
- handshake(ListenSocket, infinity).
-
-
--spec handshake(#sslsocket{} | port(), timeout()| [ssl_option()
- | transport_option()]) ->
- ok | {ok, #sslsocket{}} | {error, reason()}.
-
-handshake(#sslsocket{} = Socket, Timeout) ->
- ssl:ssl_accept(Socket, Timeout);
-
-handshake(ListenSocket, SslOptions) when is_port(ListenSocket) ->
- handshake(ListenSocket, SslOptions, infinity).
-
-
--spec handshake(port(), [ssl_option()| transport_option()], timeout()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
-handshake(Socket, SslOptions, Timeout) when is_port(Socket) ->
- ssl:ssl_accept(Socket, SslOptions, Timeout).
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index 352874c77d..adb4f6d9ea 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -43,44 +43,52 @@
%% Internal application API
%% Setup
--export([start_fsm/8, start_link/7, init/1]).
-
--export([encode_data/3, encode_alert/3]).
+-export([start_fsm/8, start_link/8, init/1, pids/1]).
%% State transition handling
--export([next_record/1, next_event/3, next_event/4]).
+-export([next_record/1, next_event/3, next_event/4,
+ handle_common_event/4]).
%% Handshake handling
--export([renegotiate/2, send_handshake/2,
+-export([renegotiation/2, renegotiate/2, send_handshake/2,
queue_handshake/2, queue_change_cipher/2,
- reinit_handshake_data/1, select_sni_extension/1]).
+ reinit/1, reinit_handshake_data/1, select_sni_extension/1,
+ empty_connection_state/2]).
%% Alert and close handling
--export([send_alert/2, close/5]).
+-export([send_alert/2, send_alert_in_connection/2,
+ send_sync_alert/2,
+ encode_alert/3, close/5, protocol_name/0]).
%% Data handling
--export([passive_receive/2, next_record_if_active/1, handle_common_event/4, send/3,
- socket/5, setopts/3, getopts/3]).
+-export([encode_data/3, passive_receive/2, next_record_if_active/1,
+ send/3, socket/5, setopts/3, getopts/3]).
%% gen_statem state functions
-export([init/3, error/3, downgrade/3, %% Initiation and take down states
- hello/3, certify/3, cipher/3, abbreviated/3, %% Handshake states
- connection/3]).
+ hello/3, user_hello/3, certify/3, cipher/3, abbreviated/3, %% Handshake states
+ connection/3]).
%% gen_statem callbacks
-export([callback_mode/0, terminate/3, code_change/4, format_status/2]).
+
+-define(DIST_CNTRL_SPAWN_OPTS, [{priority, max}]).
+
%%====================================================================
%% Internal application API
%%====================================================================
+%%====================================================================
+%% Setup
+%%====================================================================
start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = false},_, Tracker} = Opts,
User, {CbModule, _,_, _} = CbInfo,
Timeout) ->
try
- {ok, Pid} = tls_connection_sup:start_child([Role, Host, Port, Socket,
+ {ok, Sender} = tls_sender:start(),
+ {ok, Pid} = tls_connection_sup:start_child([Role, Sender, Host, Port, Socket,
Opts, User, CbInfo]),
- {ok, SslSocket} = ssl_connection:socket_control(?MODULE, Socket, Pid, CbModule, Tracker),
- ok = ssl_connection:handshake(SslSocket, Timeout),
- {ok, SslSocket}
+ {ok, SslSocket} = ssl_connection:socket_control(?MODULE, Socket, [Pid, Sender], CbModule, Tracker),
+ ssl_connection:handshake(SslSocket, Timeout)
catch
error:{badmatch, {error, _} = Error} ->
Error
@@ -90,26 +98,200 @@ start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = true},_, Tracker} =
User, {CbModule, _,_, _} = CbInfo,
Timeout) ->
try
- {ok, Pid} = tls_connection_sup:start_child_dist([Role, Host, Port, Socket,
+ {ok, Sender} = tls_sender:start([{spawn_opt, ?DIST_CNTRL_SPAWN_OPTS}]),
+ {ok, Pid} = tls_connection_sup:start_child_dist([Role, Sender, Host, Port, Socket,
Opts, User, CbInfo]),
- {ok, SslSocket} = ssl_connection:socket_control(?MODULE, Socket, Pid, CbModule, Tracker),
- ok = ssl_connection:handshake(SslSocket, Timeout),
- {ok, SslSocket}
+ {ok, SslSocket} = ssl_connection:socket_control(?MODULE, Socket, [Pid, Sender], CbModule, Tracker),
+ ssl_connection:handshake(SslSocket, Timeout)
catch
error:{badmatch, {error, _} = Error} ->
Error
end.
+%%--------------------------------------------------------------------
+-spec start_link(atom(), pid(), host(), inet:port_number(), port(), list(), pid(), tuple()) ->
+ {ok, pid()} | ignore | {error, reason()}.
+%%
+%% Description: Creates a gen_statem process which calls Module:init/1 to
+%% initialize.
+%%--------------------------------------------------------------------
+start_link(Role, Sender, Host, Port, Socket, Options, User, CbInfo) ->
+ {ok, proc_lib:spawn_link(?MODULE, init, [[Role, Sender, Host, Port, Socket, Options, User, CbInfo]])}.
+
+init([Role, Sender, Host, Port, Socket, {SslOpts, _, _} = Options, User, CbInfo]) ->
+ process_flag(trap_exit, true),
+ link(Sender),
+ case SslOpts#ssl_options.erl_dist of
+ true ->
+ process_flag(priority, max);
+ _ ->
+ ok
+ end,
+ State0 = #state{protocol_specific = Map} = initial_state(Role, Sender,
+ Host, Port, Socket, Options, User, CbInfo),
+ try
+ State = ssl_connection:ssl_config(State0#state.ssl_options, Role, State0),
+ initialize_tls_sender(State),
+ gen_statem:enter_loop(?MODULE, [], init, State)
+ catch throw:Error ->
+ EState = State0#state{protocol_specific = Map#{error => Error}},
+ gen_statem:enter_loop(?MODULE, [], error, EState)
+ end.
+
+pids(#state{protocol_specific = #{sender := Sender}}) ->
+ [self(), Sender].
+
+%%====================================================================
+%% State transition handling
+%%====================================================================
+next_record(#state{unprocessed_handshake_events = N} = State) when N > 0 ->
+ {no_record, State#state{unprocessed_handshake_events = N-1}};
+
+next_record(#state{protocol_buffers =
+ #protocol_buffers{tls_packets = [], tls_cipher_texts = [CT | Rest]}
+ = Buffers,
+ connection_states = ConnStates0,
+ ssl_options = #ssl_options{padding_check = Check}} = State) ->
+ case tls_record:decode_cipher_text(CT, ConnStates0, Check) of
+ {Plain, ConnStates} ->
+ {Plain, State#state{protocol_buffers =
+ Buffers#protocol_buffers{tls_cipher_texts = Rest},
+ connection_states = ConnStates}};
+ #alert{} = Alert ->
+ {Alert, State}
+ end;
+next_record(#state{protocol_buffers = #protocol_buffers{tls_packets = [], tls_cipher_texts = []},
+ socket = Socket,
+ close_tag = CloseTag,
+ transport_cb = Transport} = State) ->
+ case tls_socket:setopts(Transport, Socket, [{active,once}]) of
+ ok ->
+ {no_record, State};
+ _ ->
+ self() ! {CloseTag, Socket},
+ {no_record, State}
+ end;
+next_record(State) ->
+ {no_record, State}.
+
+next_event(StateName, Record, State) ->
+ next_event(StateName, Record, State, []).
+
+next_event(connection = StateName, no_record, State0, Actions) ->
+ case next_record_if_active(State0) of
+ {no_record, State} ->
+ ssl_connection:hibernate_after(StateName, State, Actions);
+ {#ssl_tls{} = Record, State} ->
+ {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]};
+ {#alert{} = Alert, State} ->
+ {next_state, StateName, State, [{next_event, internal, Alert} | Actions]}
+ end;
+next_event(StateName, Record, State, Actions) ->
+ case Record of
+ no_record ->
+ {next_state, StateName, State, Actions};
+ #ssl_tls{} = Record ->
+ {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]};
+ #alert{} = Alert ->
+ {next_state, StateName, State, [{next_event, internal, Alert} | Actions]}
+ end.
+
+handle_common_event(internal, #alert{} = Alert, StateName,
+ #state{negotiated_version = Version} = State) ->
+ ssl_connection:handle_own_alert(Alert, Version, StateName, State);
+%%% TLS record protocol level handshake messages
+handle_common_event(internal, #ssl_tls{type = ?HANDSHAKE, fragment = Data},
+ StateName, #state{protocol_buffers =
+ #protocol_buffers{tls_handshake_buffer = Buf0} = Buffers,
+ negotiated_version = Version,
+ ssl_options = Options} = State0) ->
+ try
+ {Packets, Buf} = tls_handshake:get_tls_handshake(Version,Data,Buf0, Options),
+ State1 =
+ State0#state{protocol_buffers =
+ Buffers#protocol_buffers{tls_handshake_buffer = Buf}},
+ case Packets of
+ [] ->
+ assert_buffer_sanity(Buf, Options),
+ {Record, State} = next_record(State1),
+ next_event(StateName, Record, State);
+ _ ->
+ Events = tls_handshake_events(Packets),
+ case StateName of
+ connection ->
+ ssl_connection:hibernate_after(StateName, State1, Events);
+ _ ->
+ {next_state, StateName,
+ State1#state{unprocessed_handshake_events = unprocessed_events(Events)}, Events}
+ end
+ end
+ catch throw:#alert{} = Alert ->
+ ssl_connection:handle_own_alert(Alert, Version, StateName, State0)
+ end;
+%%% TLS record protocol level application data messages
+handle_common_event(internal, #ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, StateName, State) ->
+ {next_state, StateName, State, [{next_event, internal, {application_data, Data}}]};
+%%% TLS record protocol level change cipher messages
+handle_common_event(internal, #ssl_tls{type = ?CHANGE_CIPHER_SPEC, fragment = Data}, StateName, State) ->
+ {next_state, StateName, State, [{next_event, internal, #change_cipher_spec{type = Data}}]};
+%%% TLS record protocol level Alert messages
+handle_common_event(internal, #ssl_tls{type = ?ALERT, fragment = EncAlerts}, StateName,
+ #state{negotiated_version = Version} = State) ->
+ try decode_alerts(EncAlerts) of
+ Alerts = [_|_] ->
+ handle_alerts(Alerts, {next_state, StateName, State});
+ [] ->
+ ssl_connection:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, empty_alert),
+ Version, StateName, State);
+ #alert{} = Alert ->
+ ssl_connection:handle_own_alert(Alert, Version, StateName, State)
+ catch
+ _:_ ->
+ ssl_connection:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, alert_decode_error),
+ Version, StateName, State)
+
+ end;
+%% Ignore unknown TLS record level protocol messages
+handle_common_event(internal, #ssl_tls{type = _Unknown}, StateName, State) ->
+ {next_state, StateName, State}.
+%%====================================================================
+%% Handshake handling
+%%====================================================================
+renegotiation(Pid, WriteState) ->
+ gen_statem:call(Pid, {user_renegotiate, WriteState}).
+
+renegotiate(#state{role = client} = State, Actions) ->
+ %% Handle same way as if server requested
+ %% the renegotiation
+ Hs0 = ssl_handshake:init_handshake_history(),
+ {next_state, connection, State#state{tls_handshake_history = Hs0},
+ [{next_event, internal, #hello_request{}} | Actions]};
+renegotiate(#state{role = server,
+ socket = Socket,
+ transport_cb = Transport,
+ negotiated_version = Version,
+ connection_states = ConnectionStates0} = State0, Actions) ->
+ HelloRequest = ssl_handshake:hello_request(),
+ Frag = tls_handshake:encode_handshake(HelloRequest, Version),
+ Hs0 = ssl_handshake:init_handshake_history(),
+ {BinMsg, ConnectionStates} =
+ tls_record:encode_handshake(Frag, Version, ConnectionStates0),
+ send(Transport, Socket, BinMsg),
+ State1 = State0#state{connection_states =
+ ConnectionStates,
+ tls_handshake_history = Hs0},
+ {Record, State} = next_record(State1),
+ next_event(hello, Record, State, Actions).
+
send_handshake(Handshake, State) ->
send_handshake_flight(queue_handshake(Handshake, State)).
queue_handshake(Handshake, #state{negotiated_version = Version,
tls_handshake_history = Hist0,
flight_buffer = Flight0,
- ssl_options = #ssl_options{v2_hello_compatible = V2HComp},
connection_states = ConnectionStates0} = State0) ->
{BinHandshake, ConnectionStates, Hist} =
- encode_handshake(Handshake, Version, ConnectionStates0, Hist0, V2HComp),
+ encode_handshake(Handshake, Version, ConnectionStates0, Hist0),
State0#state{connection_states = ConnectionStates,
tls_handshake_history = Hist,
flight_buffer = Flight0 ++ [BinHandshake]}.
@@ -128,14 +310,11 @@ queue_change_cipher(Msg, #state{negotiated_version = Version,
State0#state{connection_states = ConnectionStates,
flight_buffer = Flight0 ++ [BinChangeCipher]}.
-send_alert(Alert, #state{negotiated_version = Version,
- socket = Socket,
- transport_cb = Transport,
- connection_states = ConnectionStates0} = State0) ->
- {BinMsg, ConnectionStates} =
- encode_alert(Alert, Version, ConnectionStates0),
- send(Transport, Socket, BinMsg),
- State0#state{connection_states = ConnectionStates}.
+reinit(#state{protocol_specific = #{sender := Sender},
+ negotiated_version = Version,
+ connection_states = #{current_write := Write}} = State) ->
+ tls_sender:update_connection_state(Sender, Write, Version),
+ reinit_handshake_data(State).
reinit_handshake_data(State) ->
%% premaster_secret, public_key_info and tls_handshake_info
@@ -152,9 +331,12 @@ select_sni_extension(#client_hello{extensions = HelloExtensions}) ->
select_sni_extension(_) ->
undefined.
-encode_data(Data, Version, ConnectionStates0)->
- tls_record:encode_data(Data, Version, ConnectionStates0).
+empty_connection_state(ConnectionEnd, BeastMitigation) ->
+ ssl_record:empty_connection_state(ConnectionEnd, BeastMitigation).
+%%====================================================================
+%% Alert and close handling
+%%====================================================================
%%--------------------------------------------------------------------
-spec encode_alert(#alert{}, ssl_record:ssl_version(), ssl_record:connection_states()) ->
{iolist(), ssl_record:connection_states()}.
@@ -164,39 +346,97 @@ encode_data(Data, Version, ConnectionStates0)->
encode_alert(#alert{} = Alert, Version, ConnectionStates) ->
tls_record:encode_alert_record(Alert, Version, ConnectionStates).
-%%====================================================================
-%% tls_connection_sup API
-%%====================================================================
+send_alert(Alert, #state{negotiated_version = Version,
+ socket = Socket,
+ transport_cb = Transport,
+ connection_states = ConnectionStates0} = StateData0) ->
+ {BinMsg, ConnectionStates} =
+ encode_alert(Alert, Version, ConnectionStates0),
+ send(Transport, Socket, BinMsg),
+ StateData0#state{connection_states = ConnectionStates}.
+
+%% If an ALERT sent in the connection state, should cause the TLS
+%% connection to end, we need to synchronize with the tls_sender
+%% process so that the ALERT if possible (that is the tls_sender process is
+%% not blocked) is sent before the connection process terminates and
+%% thereby closes the transport socket.
+send_alert_in_connection(#alert{level = ?FATAL} = Alert, State) ->
+ send_sync_alert(Alert, State);
+send_alert_in_connection(#alert{description = ?CLOSE_NOTIFY} = Alert, State) ->
+ send_sync_alert(Alert, State);
+send_alert_in_connection(Alert,
+ #state{protocol_specific = #{sender := Sender}}) ->
+ tls_sender:send_alert(Sender, Alert).
+send_sync_alert(Alert, #state{protocol_specific = #{sender := Sender}}= State) ->
+ tls_sender:send_and_ack_alert(Sender, Alert),
+ receive
+ {Sender, ack_alert} ->
+ ok
+ after ?DEFAULT_TIMEOUT ->
+ %% Sender is blocked terminate anyway
+ throw({stop, {shutdown, own_alert}, State})
+ end.
-%%--------------------------------------------------------------------
--spec start_link(atom(), host(), inet:port_number(), port(), list(), pid(), tuple()) ->
- {ok, pid()} | ignore | {error, reason()}.
-%%
-%% Description: Creates a gen_fsm process which calls Module:init/1 to
-%% initialize. To ensure a synchronized start-up procedure, this function
-%% does not return until Module:init/1 has returned.
-%%--------------------------------------------------------------------
-start_link(Role, Host, Port, Socket, Options, User, CbInfo) ->
- {ok, proc_lib:spawn_link(?MODULE, init, [[Role, Host, Port, Socket, Options, User, CbInfo]])}.
+%% User closes or recursive call!
+close({close, Timeout}, Socket, Transport = gen_tcp, _,_) ->
+ tls_socket:setopts(Transport, Socket, [{active, false}]),
+ Transport:shutdown(Socket, write),
+ _ = Transport:recv(Socket, 0, Timeout),
+ ok;
+%% Peer closed socket
+close({shutdown, transport_closed}, Socket, Transport = gen_tcp, ConnectionStates, Check) ->
+ close({close, 0}, Socket, Transport, ConnectionStates, Check);
+%% We generate fatal alert
+close({shutdown, own_alert}, Socket, Transport = gen_tcp, ConnectionStates, Check) ->
+ %% Standard trick to try to make sure all
+ %% data sent to the tcp port is really delivered to the
+ %% peer application before tcp port is closed so that the peer will
+ %% get the correct TLS alert message and not only a transport close.
+ %% Will return when other side has closed or after timout millisec
+ %% e.g. we do not want to hang if something goes wrong
+ %% with the network but we want to maximise the odds that
+ %% peer application gets all data sent on the tcp connection.
+ close({close, ?DEFAULT_TIMEOUT}, Socket, Transport, ConnectionStates, Check);
+close(downgrade, _,_,_,_) ->
+ ok;
+%% Other
+close(_, Socket, Transport, _,_) ->
+ Transport:close(Socket).
+protocol_name() ->
+ "TLS".
-init([Role, Host, Port, Socket, Options, User, CbInfo]) ->
- process_flag(trap_exit, true),
- State0 = initial_state(Role, Host, Port, Socket, Options, User, CbInfo),
- try
- State = ssl_connection:ssl_config(State0#state.ssl_options, Role, State0),
- gen_statem:enter_loop(?MODULE, [], init, State)
- catch throw:Error ->
- gen_statem:enter_loop(?MODULE, [], error, {Error, State0})
+%%====================================================================
+%% Data handling
+%%====================================================================
+encode_data(Data, Version, ConnectionStates0)->
+ tls_record:encode_data(Data, Version, ConnectionStates0).
+
+passive_receive(State0 = #state{user_data_buffer = Buffer}, StateName) ->
+ case Buffer of
+ <<>> ->
+ {Record, State} = next_record(State0),
+ next_event(StateName, Record, State);
+ _ ->
+ {Record, State} = ssl_connection:read_application_data(<<>>, State0),
+ next_event(StateName, Record, State)
end.
-callback_mode() ->
- state_functions.
+next_record_if_active(State =
+ #state{socket_options =
+ #socket_options{active = false}}) ->
+ {no_record ,State};
+next_record_if_active(State) ->
+ next_record(State).
-socket(Pid, Transport, Socket, Connection, Tracker) ->
- tls_socket:socket(Pid, Transport, Socket, Connection, Tracker).
+send(Transport, Socket, Data) ->
+ tls_socket:send(Transport, Socket, Data).
+
+socket(Pids, Transport, Socket, Connection, Tracker) ->
+ tls_socket:socket(Pids, Transport, Socket, Connection, Tracker).
setopts(Transport, Socket, Other) ->
tls_socket:setopts(Transport, Socket, Other).
+
getopts(Transport, Socket, Tag) ->
tls_socket:getopts(Transport, Socket, Tag).
@@ -211,7 +451,7 @@ getopts(Transport, Socket, Tag) ->
init({call, From}, {start, Timeout},
#state{host = Host, port = Port, role = client,
- ssl_options = #ssl_options{v2_hello_compatible = V2HComp} = SslOpts,
+ ssl_options = SslOpts,
session = #session{own_certificate = Cert} = Session0,
transport_cb = Transport, socket = Socket,
connection_states = ConnectionStates0,
@@ -227,7 +467,7 @@ init({call, From}, {start, Timeout},
HelloVersion = tls_record:hello_version(Version, SslOpts#ssl_options.versions),
Handshake0 = ssl_handshake:init_handshake_history(),
{BinMsg, ConnectionStates, Handshake} =
- encode_handshake(Hello, HelloVersion, ConnectionStates0, Handshake0, V2HComp),
+ encode_handshake(Hello, HelloVersion, ConnectionStates0, Handshake0),
send(Transport, Socket, BinMsg),
State1 = State0#state{connection_states = ConnectionStates,
negotiated_version = Version, %% Requested version
@@ -239,18 +479,19 @@ init({call, From}, {start, Timeout},
{Record, State} = next_record(State1),
next_event(hello, Record, State);
init(Type, Event, State) ->
- gen_handshake(ssl_connection, init, Type, Event, State).
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
%%--------------------------------------------------------------------
-spec error(gen_statem:event_type(),
{start, timeout()} | term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-
-error({call, From}, {start, _Timeout}, {Error, State}) ->
- {stop_and_reply, normal, {reply, From, {error, Error}}, State};
-error({call, From}, Msg, State) ->
- handle_call(Msg, From, error, State);
+error({call, From}, {start, _Timeout},
+ #state{protocol_specific = #{error := Error}} = State) ->
+ ssl_connection:stop_and_reply(
+ normal, {reply, From, {error, Error}}, State);
+error({call, _} = Call, Msg, State) ->
+ gen_handshake(?FUNCTION_NAME, Call, Msg, State);
error(_, _, _) ->
{keep_state_and_data, [postpone]}.
@@ -260,6 +501,18 @@ error(_, _, _) ->
#state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
+hello(internal, #client_hello{extensions = Extensions} = Hello,
+ #state{ssl_options = #ssl_options{handshake = hello},
+ start_or_recv_from = From} = State) ->
+ {next_state, user_hello, State#state{start_or_recv_from = undefined,
+ hello = Hello},
+ [{reply, From, {ok, ssl_connection:map_extensions(Extensions)}}]};
+hello(internal, #server_hello{extensions = Extensions} = Hello,
+ #state{ssl_options = #ssl_options{handshake = hello},
+ start_or_recv_from = From} = State) ->
+ {next_state, user_hello, State#state{start_or_recv_from = undefined,
+ hello = Hello},
+ [{reply, From, {ok, ssl_connection:map_extensions(Extensions)}}]};
hello(internal, #client_hello{client_version = ClientVersion} = Hello,
#state{connection_states = ConnectionStates0,
port = Port, session = #session{own_certificate = Cert} = Session0,
@@ -269,26 +522,27 @@ hello(internal, #client_hello{client_version = ClientVersion} = Hello,
negotiated_protocol = CurrentProtocol,
key_algorithm = KeyExAlg,
ssl_options = SslOpts} = State) ->
-
case tls_handshake:hello(Hello, SslOpts, {Port, Session0, Cache, CacheCb,
ConnectionStates0, Cert, KeyExAlg}, Renegotiation) of
#alert{} = Alert ->
- ssl_connection:handle_own_alert(Alert, ClientVersion, hello, State);
+ ssl_connection:handle_own_alert(Alert, ClientVersion, hello,
+ State#state{negotiated_version
+ = ClientVersion});
{Version, {Type, Session},
ConnectionStates, Protocol0, ServerHelloExt, HashSign} ->
Protocol = case Protocol0 of
undefined -> CurrentProtocol;
_ -> Protocol0
end,
-
- gen_handshake(ssl_connection, hello, internal, {common_client_hello, Type, ServerHelloExt},
- State#state{connection_states = ConnectionStates,
- negotiated_version = Version,
- hashsign_algorithm = HashSign,
- session = Session,
- negotiated_protocol = Protocol})
+ gen_handshake(?FUNCTION_NAME, internal, {common_client_hello, Type, ServerHelloExt},
+ State#state{connection_states = ConnectionStates,
+ negotiated_version = Version,
+ hashsign_algorithm = HashSign,
+ client_hello_version = ClientVersion,
+ session = Session,
+ negotiated_protocol = Protocol})
end;
-hello(internal, #server_hello{} = Hello,
+hello(internal, #server_hello{} = Hello,
#state{connection_states = ConnectionStates0,
negotiated_version = ReqVersion,
role = client,
@@ -296,42 +550,46 @@ hello(internal, #server_hello{} = Hello,
ssl_options = SslOptions} = State) ->
case tls_handshake:hello(Hello, SslOptions, ConnectionStates0, Renegotiation) of
#alert{} = Alert ->
- ssl_connection:handle_own_alert(Alert, ReqVersion, hello, State);
+ ssl_connection:handle_own_alert(Alert, ReqVersion, hello,
+ State#state{negotiated_version = ReqVersion});
{Version, NewId, ConnectionStates, ProtoExt, Protocol} ->
ssl_connection:handle_session(Hello,
Version, NewId, ConnectionStates, ProtoExt, Protocol, State)
end;
hello(info, Event, State) ->
- gen_info(Event, hello, State);
+ gen_info(Event, ?FUNCTION_NAME, State);
hello(Type, Event, State) ->
- gen_handshake(ssl_connection, hello, Type, Event, State).
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
+
+user_hello(Type, Event, State) ->
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
%%--------------------------------------------------------------------
-spec abbreviated(gen_statem:event_type(), term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
abbreviated(info, Event, State) ->
- gen_info(Event, abbreviated, State);
+ gen_info(Event, ?FUNCTION_NAME, State);
abbreviated(Type, Event, State) ->
- gen_handshake(ssl_connection, abbreviated, Type, Event, State).
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
%%--------------------------------------------------------------------
-spec certify(gen_statem:event_type(), term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
certify(info, Event, State) ->
- gen_info(Event, certify, State);
+ gen_info(Event, ?FUNCTION_NAME, State);
certify(Type, Event, State) ->
- gen_handshake(ssl_connection, certify, Type, Event, State).
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
%%--------------------------------------------------------------------
-spec cipher(gen_statem:event_type(), term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
cipher(info, Event, State) ->
- gen_info(Event, cipher, State);
+ gen_info(Event, ?FUNCTION_NAME, State);
cipher(Type, Event, State) ->
- gen_handshake(ssl_connection, cipher, Type, Event, State).
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
%%--------------------------------------------------------------------
-spec connection(gen_statem:event_type(),
@@ -339,15 +597,20 @@ cipher(Type, Event, State) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
connection(info, Event, State) ->
- gen_info(Event, connection, State);
+ gen_info(Event, ?FUNCTION_NAME, State);
+connection({call, From}, {user_renegotiate, WriteState},
+ #state{connection_states = ConnectionStates} = State) ->
+ {next_state, ?FUNCTION_NAME, State#state{connection_states = ConnectionStates#{current_write => WriteState}},
+ [{next_event,{call, From}, renegotiate}]};
connection(internal, #hello_request{},
- #state{role = client, host = Host, port = Port,
+ #state{role = client,
+ renegotiation = {Renegotiation, _},
+ host = Host, port = Port,
session = #session{own_certificate = Cert} = Session0,
session_cache = Cache, session_cache_cb = CacheCb,
- ssl_options = SslOpts,
- connection_states = ConnectionStates0,
- renegotiation = {Renegotiation, _}} = State0) ->
- Hello = tls_handshake:client_hello(Host, Port, ConnectionStates0, SslOpts,
+ ssl_options = SslOpts,
+ connection_states = ConnectionStates} = State0) ->
+ Hello = tls_handshake:client_hello(Host, Port, ConnectionStates, SslOpts,
Cache, CacheCb, Renegotiation, Cert),
{State1, Actions} = send_handshake(Hello, State0),
{Record, State} =
@@ -356,7 +619,10 @@ connection(internal, #hello_request{},
= Hello#client_hello.session_id}}),
next_event(hello, Record, State, Actions);
connection(internal, #client_hello{} = Hello,
- #state{role = server, allow_renegotiate = true} = State0) ->
+ #state{role = server, allow_renegotiate = true, connection_states = CS,
+ %%protocol_cb = Connection,
+ protocol_specific = #{sender := Sender}
+ } = State0) ->
%% Mitigate Computational DoS attack
%% http://www.educatedguesswork.org/2011/10/ssltls_and_computational_dos.html
%% http://www.thc.org/thc-ssl-dos/ Rather than disabling client
@@ -365,178 +631,53 @@ connection(internal, #client_hello{} = Hello,
erlang:send_after(?WAIT_TO_ALLOW_RENEGOTIATION, self(), allow_renegotiate),
{Record, State} = next_record(State0#state{allow_renegotiate = false,
renegotiation = {true, peer}}),
- next_event(hello, Record, State, [{next_event, internal, Hello}]);
+ {ok, Write} = tls_sender:renegotiate(Sender),
+ next_event(hello, Record, State#state{connection_states = CS#{current_write => Write}},
+ [{next_event, internal, Hello}]);
connection(internal, #client_hello{},
- #state{role = server, allow_renegotiate = false} = State0) ->
+ #state{role = server, allow_renegotiate = false,
+ protocol_cb = Connection} = State0) ->
Alert = ?ALERT_REC(?WARNING, ?NO_RENEGOTIATION),
- State1 = send_alert(Alert, State0),
- {Record, State} = ssl_connection:prepare_connection(State1, ?MODULE),
- next_event(connection, Record, State);
+ send_alert_in_connection(Alert, State0),
+ State1 = Connection:reinit_handshake_data(State0),
+ {Record, State} = next_record(State1),
+ next_event(?FUNCTION_NAME, Record, State);
connection(Type, Event, State) ->
- ssl_connection:connection(Type, Event, State, ?MODULE).
+ ssl_connection:?FUNCTION_NAME(Type, Event, State, ?MODULE).
%%--------------------------------------------------------------------
-spec downgrade(gen_statem:event_type(), term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
downgrade(Type, Event, State) ->
- ssl_connection:downgrade(Type, Event, State, ?MODULE).
-
-%%--------------------------------------------------------------------
-%% Event handling functions called by state functions to handle
-%% common or unexpected events for the state.
-%%--------------------------------------------------------------------
-handle_call(Event, From, StateName, State) ->
- ssl_connection:handle_call(Event, From, StateName, State, ?MODULE).
-
-%% raw data from socket, unpack records
-handle_info({Protocol, _, Data}, StateName,
- #state{data_tag = Protocol} = State0) ->
- case next_tls_record(Data, State0) of
- {Record, State} ->
- next_event(StateName, Record, State);
- #alert{} = Alert ->
- ssl_connection:handle_normal_shutdown(Alert, StateName, State0),
- {stop, {shutdown, own_alert}}
- end;
-handle_info({CloseTag, Socket}, StateName,
- #state{socket = Socket, close_tag = CloseTag,
- socket_options = #socket_options{active = Active},
- protocol_buffers = #protocol_buffers{tls_cipher_texts = CTs},
- negotiated_version = Version} = State) ->
-
- %% Note that as of TLS 1.1,
- %% failure to properly close a connection no longer requires that a
- %% session not be resumed. This is a change from TLS 1.0 to conform
- %% with widespread implementation practice.
+ ssl_connection:?FUNCTION_NAME(Type, Event, State, ?MODULE).
- case (Active == false) andalso (CTs =/= []) of
- false ->
- case Version of
- {1, N} when N >= 1 ->
- ok;
- _ ->
- %% As invalidate_sessions here causes performance issues,
- %% we will conform to the widespread implementation
- %% practice and go aginst the spec
- %%invalidate_session(Role, Host, Port, Session)
- ok
- end,
-
- ssl_connection:handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
- {stop, {shutdown, transport_closed}};
- true ->
- %% Fixes non-delivery of final TLS record in {active, once}.
- %% Basically allows the application the opportunity to set {active, once} again
- %% and then receive the final message.
- next_event(StateName, no_record, State)
- end;
-handle_info(Msg, StateName, State) ->
- ssl_connection:handle_info(Msg, StateName, State).
-
-handle_common_event(internal, #alert{} = Alert, StateName,
- #state{negotiated_version = Version} = State) ->
- ssl_connection:handle_own_alert(Alert, Version, StateName, State);
-
-%%% TLS record protocol level handshake messages
-handle_common_event(internal, #ssl_tls{type = ?HANDSHAKE, fragment = Data},
- StateName, #state{protocol_buffers =
- #protocol_buffers{tls_handshake_buffer = Buf0} = Buffers,
- negotiated_version = Version,
- ssl_options = Options} = State0) ->
- try
- {Packets, Buf} = tls_handshake:get_tls_handshake(Version,Data,Buf0, Options),
- State1 =
- State0#state{protocol_buffers =
- Buffers#protocol_buffers{tls_handshake_buffer = Buf}},
- case Packets of
- [] ->
- assert_buffer_sanity(Buf, Options),
- {Record, State} = next_record(State1),
- next_event(StateName, Record, State);
- _ ->
- Events = tls_handshake_events(Packets),
- case StateName of
- connection ->
- ssl_connection:hibernate_after(StateName, State1, Events);
- _ ->
- {next_state, StateName,
- State1#state{unprocessed_handshake_events = unprocessed_events(Events)}, Events}
- end
- end
- catch throw:#alert{} = Alert ->
- ssl_connection:handle_own_alert(Alert, Version, StateName, State0)
- end;
-%%% TLS record protocol level application data messages
-handle_common_event(internal, #ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, StateName, State) ->
- {next_state, StateName, State, [{next_event, internal, {application_data, Data}}]};
-%%% TLS record protocol level change cipher messages
-handle_common_event(internal, #ssl_tls{type = ?CHANGE_CIPHER_SPEC, fragment = Data}, StateName, State) ->
- {next_state, StateName, State, [{next_event, internal, #change_cipher_spec{type = Data}}]};
-%%% TLS record protocol level Alert messages
-handle_common_event(internal, #ssl_tls{type = ?ALERT, fragment = EncAlerts}, StateName,
- #state{negotiated_version = Version} = State) ->
- try decode_alerts(EncAlerts) of
- Alerts = [_|_] ->
- handle_alerts(Alerts, {next_state, StateName, State});
- [] ->
- ssl_connection:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, empty_alert),
- Version, StateName, State);
- #alert{} = Alert ->
- ssl_connection:handle_own_alert(Alert, Version, StateName, State)
- catch
- _:_ ->
- ssl_connection:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, alert_decode_error),
- Version, StateName, State)
-
- end;
-%% Ignore unknown TLS record level protocol messages
-handle_common_event(internal, #ssl_tls{type = _Unknown}, StateName, State) ->
- {next_state, StateName, State}.
-
-send(Transport, Socket, Data) ->
- tls_socket:send(Transport, Socket, Data).
-
-%%--------------------------------------------------------------------
+%--------------------------------------------------------------------
%% gen_statem callbacks
%%--------------------------------------------------------------------
+callback_mode() ->
+ state_functions.
+
terminate(Reason, StateName, State) ->
- catch ssl_connection:terminate(Reason, StateName, State).
+ catch ssl_connection:terminate(Reason, StateName, State),
+ ensure_sender_terminate(Reason, State).
format_status(Type, Data) ->
ssl_connection:format_status(Type, Data).
-%%--------------------------------------------------------------------
-%% code_change(OldVsn, StateName, State, Extra) -> {ok, StateName, NewState}
-%% Description: Convert process state when code is changed
-%%--------------------------------------------------------------------
-code_change(_OldVsn, StateName, State0, {Direction, From, To}) ->
- State = convert_state(State0, Direction, From, To),
- {ok, StateName, State};
code_change(_OldVsn, StateName, State, _) ->
{ok, StateName, State}.
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-encode_handshake(Handshake, Version, ConnectionStates0, Hist0, V2HComp) ->
- Frag = tls_handshake:encode_handshake(Handshake, Version),
- Hist = ssl_handshake:update_handshake_history(Hist0, Frag, V2HComp),
- {Encoded, ConnectionStates} =
- tls_record:encode_handshake(Frag, Version, ConnectionStates0),
- {Encoded, ConnectionStates, Hist}.
-
-encode_change_cipher(#change_cipher_spec{}, Version, ConnectionStates) ->
- tls_record:encode_change_cipher_spec(Version, ConnectionStates).
-
-decode_alerts(Bin) ->
- ssl_alert:decode(Bin).
-
-initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, Tracker}, User,
+initial_state(Role, Sender, Host, Port, Socket, {SSLOptions, SocketOptions, Tracker}, User,
{CbModule, DataTag, CloseTag, ErrorTag}) ->
- #ssl_options{beast_mitigation = BeastMitigation} = SSLOptions,
+ #ssl_options{beast_mitigation = BeastMitigation,
+ erl_dist = IsErlDist} = SSLOptions,
ConnectionStates = tls_record:init_connection_states(Role, BeastMitigation),
+ ErlDistData = erl_dist_data(IsErlDist),
SessionCacheCb = case application:get_env(ssl, session_cb) of
{ok, Cb} when is_atom(Cb) ->
Cb;
@@ -544,7 +685,7 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, Tracker}, Us
ssl_session_cache
end,
- Monitor = erlang:monitor(process, User),
+ UserMonitor = erlang:monitor(process, User),
#state{socket_options = SocketOptions,
ssl_options = SSLOptions,
@@ -557,9 +698,10 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, Tracker}, Us
host = Host,
port = Port,
socket = Socket,
+ erl_dist_data = ErlDistData,
connection_states = ConnectionStates,
protocol_buffers = #protocol_buffers{},
- user_application = {Monitor, User},
+ user_application = {UserMonitor, User},
user_data_buffer = <<>>,
session_cache_cb = SessionCacheCb,
renegotiation = {false, first},
@@ -567,173 +709,139 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, Tracker}, Us
start_or_recv_from = undefined,
protocol_cb = ?MODULE,
tracker = Tracker,
- flight_buffer = []
+ flight_buffer = [],
+ protocol_specific = #{sender => Sender}
}.
-next_tls_record(Data, #state{protocol_buffers = #protocol_buffers{tls_record_buffer = Buf0,
- tls_cipher_texts = CT0} = Buffers} = State0) ->
- case tls_record:get_tls_records(Data, Buf0) of
+erl_dist_data(true) ->
+ #{dist_handle => undefined,
+ dist_buffer => <<>>};
+erl_dist_data(false) ->
+ #{}.
+
+initialize_tls_sender(#state{role = Role,
+ socket = Socket,
+ socket_options = SockOpts,
+ tracker = Tracker,
+ protocol_cb = Connection,
+ transport_cb = Transport,
+ negotiated_version = Version,
+ ssl_options = #ssl_options{renegotiate_at = RenegotiateAt},
+ connection_states = #{current_write := ConnectionWriteState},
+ protocol_specific = #{sender := Sender}}) ->
+ Init = #{current_write => ConnectionWriteState,
+ role => Role,
+ socket => Socket,
+ socket_options => SockOpts,
+ tracker => Tracker,
+ protocol_cb => Connection,
+ transport_cb => Transport,
+ negotiated_version => Version,
+ renegotiate_at => RenegotiateAt},
+ tls_sender:initialize(Sender, Init).
+
+next_tls_record(Data, StateName, #state{protocol_buffers =
+ #protocol_buffers{tls_record_buffer = Buf0,
+ tls_cipher_texts = CT0} = Buffers}
+ = State0) ->
+ case tls_record:get_tls_records(Data,
+ acceptable_record_versions(StateName, State0),
+ Buf0) of
{Records, Buf1} ->
CT1 = CT0 ++ Records,
next_record(State0#state{protocol_buffers =
Buffers#protocol_buffers{tls_record_buffer = Buf1,
tls_cipher_texts = CT1}});
#alert{} = Alert ->
- Alert
+ handle_record_alert(Alert, State0)
end.
-next_record(#state{unprocessed_handshake_events = N} = State) when N > 0 ->
- {no_record, State#state{unprocessed_handshake_events = N-1}};
-
-next_record(#state{protocol_buffers =
- #protocol_buffers{tls_packets = [], tls_cipher_texts = [CT | Rest]}
- = Buffers,
- connection_states = ConnStates0,
- ssl_options = #ssl_options{padding_check = Check}} = State) ->
- case tls_record:decode_cipher_text(CT, ConnStates0, Check) of
- {Plain, ConnStates} ->
- {Plain, State#state{protocol_buffers =
- Buffers#protocol_buffers{tls_cipher_texts = Rest},
- connection_states = ConnStates}};
- #alert{} = Alert ->
- {Alert, State}
- end;
-next_record(#state{protocol_buffers = #protocol_buffers{tls_packets = [], tls_cipher_texts = []},
- socket = Socket,
- transport_cb = Transport} = State) ->
- case tls_socket:setopts(Transport, Socket, [{active,once}]) of
- ok ->
- {no_record, State};
- _ ->
- {socket_closed, State}
- end;
-next_record(State) ->
- {no_record, State}.
-next_record_if_active(State =
- #state{socket_options =
- #socket_options{active = false}}) ->
- {no_record ,State};
-next_record_if_active(State) ->
- next_record(State).
-
-passive_receive(State0 = #state{user_data_buffer = Buffer}, StateName) ->
- case Buffer of
- <<>> ->
- {Record, State} = next_record(State0),
- next_event(StateName, Record, State);
- _ ->
- {Record, State} = ssl_connection:read_application_data(<<>>, State0),
- next_event(StateName, Record, State)
- end.
-
-next_event(StateName, Record, State) ->
- next_event(StateName, Record, State, []).
-
-next_event(StateName, socket_closed, State, _) ->
- ssl_connection:handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
- {stop, {shutdown, transport_closed}, State};
-next_event(connection = StateName, no_record, State0, Actions) ->
- case next_record_if_active(State0) of
- {no_record, State} ->
- ssl_connection:hibernate_after(StateName, State, Actions);
- {socket_closed, State} ->
- next_event(StateName, socket_closed, State, Actions);
- {#ssl_tls{} = Record, State} ->
- {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]};
- {#alert{} = Alert, State} ->
- {next_state, StateName, State, [{next_event, internal, Alert} | Actions]}
- end;
-next_event(StateName, Record, State, Actions) ->
- case Record of
- no_record ->
- {next_state, StateName, State, Actions};
- #ssl_tls{} = Record ->
- {next_state, StateName, State, [{next_event, internal, {protocol_record, Record}} | Actions]};
- #alert{} = Alert ->
- {next_state, StateName, State, [{next_event, internal, Alert} | Actions]}
- end.
+acceptable_record_versions(hello, _) ->
+ [tls_record:protocol_version(Vsn) || Vsn <- ?ALL_AVAILABLE_VERSIONS];
+acceptable_record_versions(_, #state{negotiated_version = Version}) ->
+ [Version].
+handle_record_alert(Alert, _) ->
+ Alert.
tls_handshake_events(Packets) ->
lists:map(fun(Packet) ->
{next_event, internal, {handshake, Packet}}
end, Packets).
+%% raw data from socket, upack records
+handle_info({Protocol, _, Data}, StateName,
+ #state{data_tag = Protocol} = State0) ->
+ case next_tls_record(Data, StateName, State0) of
+ {Record, State} ->
+ next_event(StateName, Record, State);
+ #alert{} = Alert ->
+ ssl_connection:handle_normal_shutdown(Alert, StateName, State0),
+ ssl_connection:stop({shutdown, own_alert}, State0)
+ end;
+handle_info({CloseTag, Socket}, StateName,
+ #state{socket = Socket, close_tag = CloseTag,
+ socket_options = #socket_options{active = Active},
+ protocol_buffers = #protocol_buffers{tls_cipher_texts = CTs},
+ negotiated_version = Version} = State) ->
-renegotiate(#state{role = client} = State, Actions) ->
- %% Handle same way as if server requested
- %% the renegotiation
- Hs0 = ssl_handshake:init_handshake_history(),
- {next_state, connection, State#state{tls_handshake_history = Hs0},
- [{next_event, internal, #hello_request{}} | Actions]};
+ %% Note that as of TLS 1.1,
+ %% failure to properly close a connection no longer requires that a
+ %% session not be resumed. This is a change from TLS 1.0 to conform
+ %% with widespread implementation practice.
-renegotiate(#state{role = server,
- socket = Socket,
- transport_cb = Transport,
- negotiated_version = Version,
- connection_states = ConnectionStates0} = State0, Actions) ->
- HelloRequest = ssl_handshake:hello_request(),
- Frag = tls_handshake:encode_handshake(HelloRequest, Version),
- Hs0 = ssl_handshake:init_handshake_history(),
- {BinMsg, ConnectionStates} =
- tls_record:encode_handshake(Frag, Version, ConnectionStates0),
- send(Transport, Socket, BinMsg),
- State1 = State0#state{connection_states =
- ConnectionStates,
- tls_handshake_history = Hs0},
- {Record, State} = next_record(State1),
- next_event(hello, Record, State, Actions).
+ case (Active == false) andalso (CTs =/= []) of
+ false ->
+ case Version of
+ {1, N} when N >= 1 ->
+ ok;
+ _ ->
+ %% As invalidate_sessions here causes performance issues,
+ %% we will conform to the widespread implementation
+ %% practice and go aginst the spec
+ %%invalidate_session(Role, Host, Port, Session)
+ ok
+ end,
+
+ ssl_connection:handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
+ ssl_connection:stop({shutdown, transport_closed}, State);
+ true ->
+ %% Fixes non-delivery of final TLS record in {active, once}.
+ %% Basically allows the application the opportunity to set {active, once} again
+ %% and then receive the final message.
+ next_event(StateName, no_record, State)
+ end;
+handle_info({'EXIT', Sender, Reason}, _,
+ #state{protocol_specific = #{sender := Sender}} = State) ->
+ {stop, {shutdown, sender_died, Reason}, State};
+handle_info(Msg, StateName, State) ->
+ ssl_connection:StateName(info, Msg, State, ?MODULE).
handle_alerts([], Result) ->
Result;
-handle_alerts(_, {stop,_} = Stop) ->
+handle_alerts(_, {stop, _, _} = Stop) ->
Stop;
handle_alerts([Alert | Alerts], {next_state, StateName, State}) ->
handle_alerts(Alerts, ssl_connection:handle_alert(Alert, StateName, State));
handle_alerts([Alert | Alerts], {next_state, StateName, State, _Actions}) ->
handle_alerts(Alerts, ssl_connection:handle_alert(Alert, StateName, State)).
+encode_handshake(Handshake, Version, ConnectionStates0, Hist0) ->
+ Frag = tls_handshake:encode_handshake(Handshake, Version),
+ Hist = ssl_handshake:update_handshake_history(Hist0, Frag),
+ {Encoded, ConnectionStates} =
+ tls_record:encode_handshake(Frag, Version, ConnectionStates0),
+ {Encoded, ConnectionStates, Hist}.
-%% User closes or recursive call!
-close({close, Timeout}, Socket, Transport = gen_tcp, _,_) ->
- tls_socket:setopts(Transport, Socket, [{active, false}]),
- Transport:shutdown(Socket, write),
- _ = Transport:recv(Socket, 0, Timeout),
- ok;
-%% Peer closed socket
-close({shutdown, transport_closed}, Socket, Transport = gen_tcp, ConnectionStates, Check) ->
- close({close, 0}, Socket, Transport, ConnectionStates, Check);
-%% We generate fatal alert
-close({shutdown, own_alert}, Socket, Transport = gen_tcp, ConnectionStates, Check) ->
- %% Standard trick to try to make sure all
- %% data sent to the tcp port is really delivered to the
- %% peer application before tcp port is closed so that the peer will
- %% get the correct TLS alert message and not only a transport close.
- %% Will return when other side has closed or after timout millisec
- %% e.g. we do not want to hang if something goes wrong
- %% with the network but we want to maximise the odds that
- %% peer application gets all data sent on the tcp connection.
- close({close, ?DEFAULT_TIMEOUT}, Socket, Transport, ConnectionStates, Check);
-close(downgrade, _,_,_,_) ->
- ok;
-%% Other
-close(_, Socket, Transport, _,_) ->
- Transport:close(Socket).
-
-convert_state(#state{ssl_options = Options} = State, up, "5.3.5", "5.3.6") ->
- State#state{ssl_options = convert_options_partial_chain(Options, up)};
-convert_state(#state{ssl_options = Options} = State, down, "5.3.6", "5.3.5") ->
- State#state{ssl_options = convert_options_partial_chain(Options, down)}.
-
-convert_options_partial_chain(Options, up) ->
- {Head, Tail} = lists:split(5, tuple_to_list(Options)),
- list_to_tuple(Head ++ [{partial_chain, fun(_) -> unknown_ca end}] ++ Tail);
-convert_options_partial_chain(Options, down) ->
- list_to_tuple(proplists:delete(partial_chain, tuple_to_list(Options))).
-
-gen_handshake(GenConnection, StateName, Type, Event,
+encode_change_cipher(#change_cipher_spec{}, Version, ConnectionStates) ->
+ tls_record:encode_change_cipher_spec(Version, ConnectionStates).
+
+decode_alerts(Bin) ->
+ ssl_alert:decode(Bin).
+
+gen_handshake(StateName, Type, Event,
#state{negotiated_version = Version} = State) ->
- try GenConnection:StateName(Type, Event, State, ?MODULE) of
+ try ssl_connection:StateName(Type, Event, State, ?MODULE) of
Result ->
Result
catch
@@ -742,7 +850,7 @@ gen_handshake(GenConnection, StateName, Type, Event,
malformed_handshake_data),
Version, StateName, State)
end.
-
+
gen_info(Event, connection = StateName, #state{negotiated_version = Version} = State) ->
try handle_info(Event, StateName, State) of
Result ->
@@ -774,7 +882,8 @@ unprocessed_events(Events) ->
erlang:length(Events)-1.
-assert_buffer_sanity(<<?BYTE(_Type), ?UINT24(Length), Rest/binary>>, #ssl_options{max_handshake_size = Max}) when
+assert_buffer_sanity(<<?BYTE(_Type), ?UINT24(Length), Rest/binary>>,
+ #ssl_options{max_handshake_size = Max}) when
Length =< Max ->
case size(Rest) of
N when N < Length ->
@@ -794,3 +903,16 @@ assert_buffer_sanity(Bin, _) ->
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE,
malformed_handshake_data))
end.
+
+ensure_sender_terminate(downgrade, _) ->
+ ok; %% Do not terminate sender during downgrade phase
+ensure_sender_terminate(_, #state{protocol_specific = #{sender := Sender}}) ->
+ %% Make sure TLS sender dies when connection process is terminated normally
+ %% This is needed if the tls_sender is blocked in prim_inet:send
+ Kill = fun() ->
+ receive
+ after 5000 ->
+ catch (exit(Sender, kill))
+ end
+ end,
+ spawn(Kill).
diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl
index b54540393a..19a5eb0348 100644
--- a/lib/ssl/src/tls_handshake.erl
+++ b/lib/ssl/src/tls_handshake.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,13 +32,19 @@
-include("ssl_cipher.hrl").
-include_lib("public_key/include/public_key.hrl").
--export([client_hello/8, hello/4,
- get_tls_handshake/4, encode_handshake/2, decode_handshake/4]).
+%% Handshake handling
+-export([client_hello/8, hello/4]).
+
+%% Handshake encoding
+-export([encode_handshake/2]).
+
+%% Handshake decodeing
+-export([get_tls_handshake/4, decode_handshake/3]).
-type tls_handshake() :: #client_hello{} | ssl_handshake:ssl_handshake().
%%====================================================================
-%% Internal application API
+%% Handshake handling
%%====================================================================
%%--------------------------------------------------------------------
-spec client_hello(host(), inet:port_number(), ssl_record:connection_states(),
@@ -54,18 +60,14 @@ client_hello(Host, Port, ConnectionStates,
} = SslOpts,
Cache, CacheCb, Renegotiation, OwnCert) ->
Version = tls_record:highest_protocol_version(Versions),
- #{security_parameters := SecParams} = ssl_record:pending_connection_state(ConnectionStates, read),
+ #{security_parameters := SecParams} =
+ ssl_record:pending_connection_state(ConnectionStates, read),
AvailableCipherSuites = ssl_handshake:available_suites(UserSuites, Version),
Extensions = ssl_handshake:client_hello_extensions(Version,
AvailableCipherSuites,
- SslOpts, ConnectionStates, Renegotiation),
- CipherSuites =
- case Fallback of
- true ->
- [?TLS_FALLBACK_SCSV | ssl_handshake:cipher_suites(AvailableCipherSuites, Renegotiation)];
- false ->
- ssl_handshake:cipher_suites(AvailableCipherSuites, Renegotiation)
- end,
+ SslOpts, ConnectionStates,
+ Renegotiation),
+ CipherSuites = ssl_handshake:cipher_suites(AvailableCipherSuites, Renegotiation, Fallback),
Id = ssl_session:client_id({Host, Port, SslOpts}, Cache, CacheCb, OwnCert),
#client_hello{session_id = Id,
client_version = Version,
@@ -79,14 +81,14 @@ client_hello(Host, Port, ConnectionStates,
-spec hello(#server_hello{} | #client_hello{}, #ssl_options{},
ssl_record:connection_states() | {inet:port_number(), #session{}, db_handle(),
atom(), ssl_record:connection_states(),
- binary() | undefined, ssl_cipher:key_algo()},
+ binary() | undefined, ssl_cipher_format:key_algo()},
boolean()) ->
{tls_record:tls_version(), session_id(),
ssl_record:connection_states(), alpn | npn, binary() | undefined}|
{tls_record:tls_version(), {resumed | new, #session{}},
ssl_record:connection_states(), binary() | undefined,
- #hello_extensions{}, {ssl_cipher:hash(), ssl_cipher:sign_algo()} | undefined} |
- #alert{}.
+ #hello_extensions{}, {ssl_cipher_format:hash(), ssl_cipher_format:sign_algo()} |
+ undefined} | #alert{}.
%%
%% Description: Handles a received hello message
%%--------------------------------------------------------------------
@@ -99,7 +101,8 @@ hello(#server_hello{server_version = Version, random = Random,
case tls_record:is_acceptable_version(Version, SupportedVersions) of
true ->
handle_server_hello_extensions(Version, SessionId, Random, CipherSuite,
- Compression, HelloExt, SslOpt, ConnectionStates0, Renegotiation);
+ Compression, HelloExt, SslOpt,
+ ConnectionStates0, Renegotiation);
false ->
?ALERT_REC(?FATAL, ?PROTOCOL_VERSION)
end;
@@ -123,22 +126,36 @@ hello(#client_hello{client_version = ClientVersion,
handle_client_hello(Version, Hello, SslOpts, Info, Renegotiation)
end
catch
+ error:{case_clause,{asn1, Asn1Reason}} ->
+ %% ASN-1 decode of certificate somehow failed
+ ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, {failed_to_decode_own_certificate, Asn1Reason});
_:_ ->
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data)
end.
+
+%%--------------------------------------------------------------------
+%%% Handshake encodeing
+%%--------------------------------------------------------------------
+
%%--------------------------------------------------------------------
-spec encode_handshake(tls_handshake(), tls_record:tls_version()) -> iolist().
%%
%% Description: Encode a handshake packet
-%%--------------------------------------------------------------------x
+%%--------------------------------------------------------------------
encode_handshake(Package, Version) ->
{MsgType, Bin} = enc_handshake(Package, Version),
Len = byte_size(Bin),
[MsgType, ?uint24(Len), Bin].
+
%%--------------------------------------------------------------------
--spec get_tls_handshake(tls_record:tls_version(), binary(), binary() | iolist(), #ssl_options{}) ->
+%%% Handshake decodeing
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+-spec get_tls_handshake(tls_record:tls_version(), binary(), binary() | iolist(),
+ #ssl_options{}) ->
{[tls_handshake()], binary()}.
%%
%% Description: Given buffered and new data from ssl_record, collects
@@ -153,37 +170,45 @@ get_tls_handshake(Version, Data, Buffer, Options) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-handle_client_hello(Version, #client_hello{session_id = SugesstedId,
- cipher_suites = CipherSuites,
- compression_methods = Compressions,
- random = Random,
- extensions = #hello_extensions{elliptic_curves = Curves,
- signature_algs = ClientHashSigns} = HelloExt},
+handle_client_hello(Version,
+ #client_hello{session_id = SugesstedId,
+ cipher_suites = CipherSuites,
+ compression_methods = Compressions,
+ random = Random,
+ extensions =
+ #hello_extensions{elliptic_curves = Curves,
+ signature_algs = ClientHashSigns}
+ = HelloExt},
#ssl_options{versions = Versions,
signature_algs = SupportedHashSigns,
eccs = SupportedECCs,
honor_ecc_order = ECCOrder} = SslOpts,
- {Port, Session0, Cache, CacheCb, ConnectionStates0, Cert, _}, Renegotiation) ->
+ {Port, Session0, Cache, CacheCb, ConnectionStates0, Cert, _},
+ Renegotiation) ->
case tls_record:is_acceptable_version(Version, Versions) of
true ->
AvailableHashSigns = ssl_handshake:available_signature_algs(
ClientHashSigns, SupportedHashSigns, Cert, Version),
ECCCurve = ssl_handshake:select_curve(Curves, SupportedECCs, ECCOrder),
{Type, #session{cipher_suite = CipherSuite} = Session1}
- = ssl_handshake:select_session(SugesstedId, CipherSuites, AvailableHashSigns, Compressions,
- Port, Session0#session{ecc = ECCCurve}, Version,
- SslOpts, Cache, CacheCb, Cert),
+ = ssl_handshake:select_session(SugesstedId, CipherSuites,
+ AvailableHashSigns, Compressions,
+ Port, Session0#session{ecc = ECCCurve},
+ Version, SslOpts, Cache, CacheCb, Cert),
case CipherSuite of
no_suite ->
?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_ciphers);
_ ->
- {KeyExAlg,_,_,_} = ssl_cipher:suite_definition(CipherSuite),
- case ssl_handshake:select_hashsign(ClientHashSigns, Cert, KeyExAlg, SupportedHashSigns, Version) of
+ #{key_exchange := KeyExAlg} = ssl_cipher_format:suite_definition(CipherSuite),
+ case ssl_handshake:select_hashsign(ClientHashSigns, Cert, KeyExAlg,
+ SupportedHashSigns, Version) of
#alert{} = Alert ->
Alert;
HashSign ->
- handle_client_hello_extensions(Version, Type, Random, CipherSuites, HelloExt,
- SslOpts, Session1, ConnectionStates0,
+ handle_client_hello_extensions(Version, Type, Random,
+ CipherSuites, HelloExt,
+ SslOpts, Session1,
+ ConnectionStates0,
Renegotiation, HashSign)
end
end;
@@ -191,84 +216,35 @@ handle_client_hello(Version, #client_hello{session_id = SugesstedId,
?ALERT_REC(?FATAL, ?PROTOCOL_VERSION)
end.
-get_tls_handshake_aux(Version, <<?BYTE(Type), ?UINT24(Length),
- Body:Length/binary,Rest/binary>>,
- #ssl_options{v2_hello_compatible = V2Hello} = Opts, Acc) ->
- Raw = <<?BYTE(Type), ?UINT24(Length), Body/binary>>,
- try decode_handshake(Version, Type, Body, V2Hello) of
- Handshake ->
- get_tls_handshake_aux(Version, Rest, Opts, [{Handshake,Raw} | Acc])
- catch
- _:_ ->
- throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, handshake_decode_error))
- end;
-get_tls_handshake_aux(_Version, Data, _, Acc) ->
- {lists:reverse(Acc), Data}.
-
-decode_handshake(_, ?HELLO_REQUEST, <<>>, _) ->
- #hello_request{};
-
-decode_handshake(_Version, ?CLIENT_HELLO, Bin, true) ->
- try decode_hello(Bin) of
- Hello ->
- Hello
- catch
- _:_ ->
- decode_v2_hello(Bin)
- end;
-decode_handshake(_Version, ?CLIENT_HELLO, Bin, false) ->
- decode_hello(Bin);
-
-decode_handshake(_Version, ?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
- ?BYTE(SID_length), Session_ID:SID_length/binary,
- ?UINT16(Cs_length), CipherSuites:Cs_length/binary,
- ?BYTE(Cm_length), Comp_methods:Cm_length/binary,
- Extensions/binary>>, _) ->
-
- DecodedExtensions = ssl_handshake:decode_hello_extensions({client, Extensions}),
-
- #client_hello{
- client_version = {Major,Minor},
- random = Random,
- session_id = Session_ID,
- cipher_suites = ssl_handshake:decode_suites('2_bytes', CipherSuites),
- compression_methods = Comp_methods,
- extensions = DecodedExtensions
- };
-decode_handshake(Version, Tag, Msg, _) ->
- ssl_handshake:decode_handshake(Version, Tag, Msg).
+handle_client_hello_extensions(Version, Type, Random, CipherSuites,
+ HelloExt, SslOpts, Session0, ConnectionStates0,
+ Renegotiation, HashSign) ->
+ try ssl_handshake:handle_client_hello_extensions(tls_record, Random, CipherSuites,
+ HelloExt, Version, SslOpts,
+ Session0, ConnectionStates0,
+ Renegotiation) of
+ #alert{} = Alert ->
+ Alert;
+ {Session, ConnectionStates, Protocol, ServerHelloExt} ->
+ {Version, {Type, Session}, ConnectionStates, Protocol,
+ ServerHelloExt, HashSign}
+ catch throw:Alert ->
+ Alert
+ end.
-decode_hello(<<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
- ?BYTE(SID_length), Session_ID:SID_length/binary,
- ?UINT16(Cs_length), CipherSuites:Cs_length/binary,
- ?BYTE(Cm_length), Comp_methods:Cm_length/binary,
- Extensions/binary>>) ->
- DecodedExtensions = ssl_handshake:decode_hello_extensions({client, Extensions}),
-
- #client_hello{
- client_version = {Major,Minor},
- random = Random,
- session_id = Session_ID,
- cipher_suites = ssl_handshake:decode_suites('2_bytes', CipherSuites),
- compression_methods = Comp_methods,
- extensions = DecodedExtensions
- }.
-%% The server must be able to receive such messages, from clients that
-%% are willing to use ssl v3 or higher, but have ssl v2 compatibility.
-decode_v2_hello(<<?BYTE(Major), ?BYTE(Minor),
- ?UINT16(CSLength), ?UINT16(0),
- ?UINT16(CDLength),
- CipherSuites:CSLength/binary,
- ChallengeData:CDLength/binary>>) ->
- #client_hello{client_version = {Major, Minor},
- random = ssl_v2:client_random(ChallengeData, CDLength),
- session_id = 0,
- cipher_suites = ssl_handshake:decode_suites('3_bytes', CipherSuites),
- compression_methods = [?NULL],
- extensions = #hello_extensions{}
- }.
-
+handle_server_hello_extensions(Version, SessionId, Random, CipherSuite,
+ Compression, HelloExt, SslOpt, ConnectionStates0, Renegotiation) ->
+ case ssl_handshake:handle_server_hello_extensions(tls_record, Random, CipherSuite,
+ Compression, HelloExt, Version,
+ SslOpt, ConnectionStates0,
+ Renegotiation) of
+ #alert{} = Alert ->
+ Alert;
+ {ConnectionStates, ProtoExt, Protocol} ->
+ {Version, SessionId, ConnectionStates, ProtoExt, Protocol}
+ end.
+%%--------------------------------------------------------------------
enc_handshake(#hello_request{}, _Version) ->
{?HELLO_REQUEST, <<>>};
enc_handshake(#client_hello{client_version = {Major, Minor},
@@ -292,29 +268,39 @@ enc_handshake(#client_hello{client_version = {Major, Minor},
enc_handshake(HandshakeMsg, Version) ->
ssl_handshake:encode_handshake(HandshakeMsg, Version).
+%%--------------------------------------------------------------------
+get_tls_handshake_aux(Version, <<?BYTE(Type), ?UINT24(Length),
+ Body:Length/binary,Rest/binary>>,
+ Opts, Acc) ->
+ Raw = <<?BYTE(Type), ?UINT24(Length), Body/binary>>,
+ try decode_handshake(Version, Type, Body) of
+ Handshake ->
+ get_tls_handshake_aux(Version, Rest, Opts, [{Handshake,Raw} | Acc])
+ catch
+ _:_ ->
+ throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, handshake_decode_error))
+ end;
+get_tls_handshake_aux(_Version, Data, _, Acc) ->
+ {lists:reverse(Acc), Data}.
-handle_client_hello_extensions(Version, Type, Random, CipherSuites,
- HelloExt, SslOpts, Session0, ConnectionStates0, Renegotiation, HashSign) ->
- try ssl_handshake:handle_client_hello_extensions(tls_record, Random, CipherSuites,
- HelloExt, Version, SslOpts,
- Session0, ConnectionStates0, Renegotiation) of
- #alert{} = Alert ->
- Alert;
- {Session, ConnectionStates, Protocol, ServerHelloExt} ->
- {Version, {Type, Session}, ConnectionStates, Protocol, ServerHelloExt, HashSign}
- catch throw:Alert ->
- Alert
- end.
-
+decode_handshake(_, ?HELLO_REQUEST, <<>>) ->
+ #hello_request{};
+decode_handshake(_Version, ?CLIENT_HELLO,
+ <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
+ ?BYTE(SID_length), Session_ID:SID_length/binary,
+ ?UINT16(Cs_length), CipherSuites:Cs_length/binary,
+ ?BYTE(Cm_length), Comp_methods:Cm_length/binary,
+ Extensions/binary>>) ->
+ DecodedExtensions = ssl_handshake:decode_hello_extensions({client, Extensions}),
+ #client_hello{
+ client_version = {Major,Minor},
+ random = Random,
+ session_id = Session_ID,
+ cipher_suites = ssl_handshake:decode_suites('2_bytes', CipherSuites),
+ compression_methods = Comp_methods,
+ extensions = DecodedExtensions
+ };
+decode_handshake(Version, Tag, Msg) ->
+ ssl_handshake:decode_handshake(Version, Tag, Msg).
-handle_server_hello_extensions(Version, SessionId, Random, CipherSuite,
- Compression, HelloExt, SslOpt, ConnectionStates0, Renegotiation) ->
- case ssl_handshake:handle_server_hello_extensions(tls_record, Random, CipherSuite,
- Compression, HelloExt, Version,
- SslOpt, ConnectionStates0, Renegotiation) of
- #alert{} = Alert ->
- Alert;
- {ConnectionStates, ProtoExt, Protocol} ->
- {Version, SessionId, ConnectionStates, ProtoExt, Protocol}
- end.
diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
index 4ac6cdc6b5..f1aca8c801 100644
--- a/lib/ssl/src/tls_record.erl
+++ b/lib/ssl/src/tls_record.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,22 +32,22 @@
-include("ssl_cipher.hrl").
%% Handling of incoming data
--export([get_tls_records/2, init_connection_states/2]).
+-export([get_tls_records/3, init_connection_states/2]).
%% Encoding TLS records
-export([encode_handshake/3, encode_alert_record/3,
encode_change_cipher_spec/2, encode_data/3]).
-export([encode_plain_text/4]).
+%% Decoding
+-export([decode_cipher_text/3]).
+
%% Protocol version handling
-export([protocol_version/1, lowest_protocol_version/1, lowest_protocol_version/2,
highest_protocol_version/1, highest_protocol_version/2,
is_higher/2, supported_protocol_versions/0,
is_acceptable_version/1, is_acceptable_version/2, hello_version/2]).
-%% Decoding
--export([decode_cipher_text/3]).
-
-export_type([tls_version/0, tls_atom_version/0]).
-type tls_version() :: ssl_record:ssl_version().
@@ -56,13 +56,12 @@
-compile(inline).
%%====================================================================
-%% Internal application API
+%% Handling of incoming data
%%====================================================================
%%--------------------------------------------------------------------
-spec init_connection_states(client | server, one_n_minus_one | zero_n | disabled) ->
ssl_record:connection_states().
-%% %
- %
+%%
%% Description: Creates a connection_states record with appropriate
%% values for the initial SSL connection setup.
%%--------------------------------------------------------------------
@@ -76,16 +75,29 @@ init_connection_states(Role, BeastMitigation) ->
pending_write => Pending}.
%%--------------------------------------------------------------------
--spec get_tls_records(binary(), binary()) -> {[binary()], binary()} | #alert{}.
+-spec get_tls_records(binary(), [tls_version()], binary()) -> {[binary()], binary()} | #alert{}.
%%
%% and returns it as a list of tls_compressed binaries also returns leftover
%% Description: Given old buffer and new data from TCP, packs up a records
%% data
%%--------------------------------------------------------------------
-get_tls_records(Data, <<>>) ->
- get_tls_records_aux(Data, []);
-get_tls_records(Data, Buffer) ->
- get_tls_records_aux(list_to_binary([Buffer, Data]), []).
+get_tls_records(Data, Versions, Buffer) ->
+ BinData = list_to_binary([Buffer, Data]),
+ case erlang:byte_size(BinData) of
+ N when N >= 3 ->
+ case assert_version(BinData, Versions) of
+ true ->
+ get_tls_records_aux(BinData, []);
+ false ->
+ ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
+ end;
+ _ ->
+ get_tls_records_aux(BinData, [])
+ end.
+
+%%====================================================================
+%% Encoding
+%%====================================================================
%%--------------------------------------------------------------------
-spec encode_handshake(iolist(), tls_version(), ssl_record:connection_states()) ->
@@ -141,6 +153,74 @@ encode_data(Frag, Version,
Data = split_bin(Frag, ?MAX_PLAIN_TEXT_LENGTH, Version, BCA, BeastMitigation),
encode_iolist(?APPLICATION_DATA, Data, Version, ConnectionStates).
+%%====================================================================
+%% Decoding
+%%====================================================================
+
+%%--------------------------------------------------------------------
+-spec decode_cipher_text(#ssl_tls{}, ssl_record:connection_states(), boolean()) ->
+ {#ssl_tls{}, ssl_record:connection_states()}| #alert{}.
+%%
+%% Description: Decode cipher text
+%%--------------------------------------------------------------------
+decode_cipher_text(#ssl_tls{type = Type, version = Version,
+ fragment = CipherFragment} = CipherText,
+ #{current_read :=
+ #{compression_state := CompressionS0,
+ sequence_number := Seq,
+ cipher_state := CipherS0,
+ security_parameters :=
+ #security_parameters{
+ cipher_type = ?AEAD,
+ bulk_cipher_algorithm =
+ BulkCipherAlgo,
+ compression_algorithm = CompAlg}
+ } = ReadState0} = ConnnectionStates0, _) ->
+ AAD = calc_aad(Type, Version, ReadState0),
+ case ssl_cipher:decipher_aead(BulkCipherAlgo, CipherS0, Seq, AAD, CipherFragment, Version) of
+ {PlainFragment, CipherS1} ->
+ {Plain, CompressionS1} = ssl_record:uncompress(CompAlg,
+ PlainFragment, CompressionS0),
+ ConnnectionStates = ConnnectionStates0#{
+ current_read => ReadState0#{
+ cipher_state => CipherS1,
+ sequence_number => Seq + 1,
+ compression_state => CompressionS1}},
+ {CipherText#ssl_tls{fragment = Plain}, ConnnectionStates};
+ #alert{} = Alert ->
+ Alert
+ end;
+
+decode_cipher_text(#ssl_tls{type = Type, version = Version,
+ fragment = CipherFragment} = CipherText,
+ #{current_read :=
+ #{compression_state := CompressionS0,
+ sequence_number := Seq,
+ security_parameters :=
+ #security_parameters{compression_algorithm = CompAlg}
+ } = ReadState0} = ConnnectionStates0, PaddingCheck) ->
+ case ssl_record:decipher(Version, CipherFragment, ReadState0, PaddingCheck) of
+ {PlainFragment, Mac, ReadState1} ->
+ MacHash = ssl_cipher:calc_mac_hash(Type, Version, PlainFragment, ReadState1),
+ case ssl_record:is_correct_mac(Mac, MacHash) of
+ true ->
+ {Plain, CompressionS1} = ssl_record:uncompress(CompAlg,
+ PlainFragment, CompressionS0),
+ ConnnectionStates = ConnnectionStates0#{
+ current_read => ReadState1#{
+ sequence_number => Seq + 1,
+ compression_state => CompressionS1}},
+ {CipherText#ssl_tls{fragment = Plain}, ConnnectionStates};
+ false ->
+ ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
+ end;
+ #alert{} = Alert ->
+ Alert
+ end.
+
+%%====================================================================
+%% Protocol version handling
+%%====================================================================
%%--------------------------------------------------------------------
-spec protocol_version(tls_atom_version() | tls_version()) ->
@@ -278,11 +358,6 @@ supported_protocol_versions([_|_] = Vsns) ->
end
end.
-%%--------------------------------------------------------------------
-%%
-%% Description: ssl version 2 is not acceptable security risks are too big.
-%%
-%%--------------------------------------------------------------------
-spec is_acceptable_version(tls_version()) -> boolean().
is_acceptable_version({N,_})
when N >= ?LOWEST_MAJOR_SUPPORTED_VERSION ->
@@ -302,6 +377,7 @@ hello_version(Version, _) when Version >= {3, 3} ->
Version;
hello_version(_, Versions) ->
lowest_protocol_version(Versions).
+
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
@@ -318,6 +394,9 @@ initial_connection_state(ConnectionEnd, BeastMitigation) ->
server_verify_data => undefined
}.
+assert_version(<<?BYTE(_), ?BYTE(MajVer), ?BYTE(MinVer), _/binary>>, Versions) ->
+ is_acceptable_version({MajVer, MinVer}, Versions).
+
get_tls_records_aux(<<?BYTE(?APPLICATION_DATA),?BYTE(MajVer),?BYTE(MinVer),
?UINT16(Length), Data:Length/binary, Rest/binary>>,
Acc) ->
@@ -342,33 +421,10 @@ get_tls_records_aux(<<?BYTE(?CHANGE_CIPHER_SPEC),?BYTE(MajVer),?BYTE(MinVer),
get_tls_records_aux(Rest, [#ssl_tls{type = ?CHANGE_CIPHER_SPEC,
version = {MajVer, MinVer},
fragment = Data} | Acc]);
-%% Matches an ssl v2 client hello message.
-%% The server must be able to receive such messages, from clients that
-%% are willing to use ssl v3 or higher, but have ssl v2 compatibility.
-get_tls_records_aux(<<1:1, Length0:15, Data0:Length0/binary, Rest/binary>>,
- Acc) ->
- case Data0 of
- <<?BYTE(?CLIENT_HELLO), ?BYTE(MajVer), ?BYTE(MinVer), _/binary>> ->
- Length = Length0-1,
- <<?BYTE(_), Data1:Length/binary>> = Data0,
- Data = <<?BYTE(?CLIENT_HELLO), ?UINT24(Length), Data1/binary>>,
- get_tls_records_aux(Rest, [#ssl_tls{type = ?HANDSHAKE,
- version = {MajVer, MinVer},
- fragment = Data} | Acc]);
- _ ->
- ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE)
-
- end;
-
get_tls_records_aux(<<0:1, _CT:7, ?BYTE(_MajVer), ?BYTE(_MinVer),
- ?UINT16(Length), _/binary>>,
+ ?UINT16(Length), _/binary>>,
_Acc) when Length > ?MAX_CIPHER_TEXT_LENGTH ->
?ALERT_REC(?FATAL, ?RECORD_OVERFLOW);
-
-get_tls_records_aux(<<1:1, Length0:15, _/binary>>,_Acc)
- when Length0 > ?MAX_CIPHER_TEXT_LENGTH ->
- ?ALERT_REC(?FATAL, ?RECORD_OVERFLOW);
-
get_tls_records_aux(Data, Acc) ->
case size(Data) =< ?MAX_CIPHER_TEXT_LENGTH + ?INITIAL_BYTES of
true ->
@@ -376,37 +432,17 @@ get_tls_records_aux(Data, Acc) ->
false ->
?ALERT_REC(?FATAL, ?UNEXPECTED_MESSAGE)
end.
-
+%%--------------------------------------------------------------------
encode_plain_text(Type, Version, Data, #{current_write := Write0} = ConnectionStates) ->
{CipherFragment, Write1} = do_encode_plain_text(Type, Version, Data, Write0),
{CipherText, Write} = encode_tls_cipher_text(Type, Version, CipherFragment, Write1),
{CipherText, ConnectionStates#{current_write => Write}}.
-lowest_list_protocol_version(Ver, []) ->
- Ver;
-lowest_list_protocol_version(Ver1, [Ver2 | Rest]) ->
- lowest_list_protocol_version(lowest_protocol_version(Ver1, Ver2), Rest).
-
-highest_list_protocol_version(Ver, []) ->
- Ver;
-highest_list_protocol_version(Ver1, [Ver2 | Rest]) ->
- highest_list_protocol_version(highest_protocol_version(Ver1, Ver2), Rest).
-
encode_tls_cipher_text(Type, {MajVer, MinVer}, Fragment, #{sequence_number := Seq} = Write) ->
Length = erlang:iolist_size(Fragment),
{[<<?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer), ?UINT16(Length)>>, Fragment],
Write#{sequence_number => Seq +1}}.
-highest_protocol_version() ->
- highest_protocol_version(supported_protocol_versions()).
-
-lowest_protocol_version() ->
- lowest_protocol_version(supported_protocol_versions()).
-
-sufficient_tlsv1_2_crypto_support() ->
- CryptoSupport = crypto:supports(),
- proplists:get_bool(sha256, proplists:get_value(hashs, CryptoSupport)).
-
encode_iolist(Type, Data, Version, ConnectionStates0) ->
{ConnectionStates, EncodedMsg} =
lists:foldl(fun(Text, {CS0, Encoded}) ->
@@ -415,6 +451,31 @@ encode_iolist(Type, Data, Version, ConnectionStates0) ->
{CS1, [Enc | Encoded]}
end, {ConnectionStates0, []}, Data),
{lists:reverse(EncodedMsg), ConnectionStates}.
+%%--------------------------------------------------------------------
+do_encode_plain_text(Type, Version, Data, #{compression_state := CompS0,
+ security_parameters :=
+ #security_parameters{
+ cipher_type = ?AEAD,
+ compression_algorithm = CompAlg}
+ } = WriteState0) ->
+ {Comp, CompS1} = ssl_record:compress(CompAlg, Data, CompS0),
+ WriteState1 = WriteState0#{compression_state => CompS1},
+ AAD = calc_aad(Type, Version, WriteState1),
+ ssl_record:cipher_aead(Version, Comp, WriteState1, AAD);
+do_encode_plain_text(Type, Version, Data, #{compression_state := CompS0,
+ security_parameters :=
+ #security_parameters{compression_algorithm = CompAlg}
+ }= WriteState0) ->
+ {Comp, CompS1} = ssl_record:compress(CompAlg, Data, CompS0),
+ WriteState1 = WriteState0#{compression_state => CompS1},
+ MacHash = ssl_cipher:calc_mac_hash(Type, Version, Comp, WriteState1),
+ ssl_record:cipher(Version, Comp, WriteState1, MacHash);
+do_encode_plain_text(_,_,_,CS) ->
+ exit({cs, CS}).
+%%--------------------------------------------------------------------
+calc_aad(Type, {MajVer, MinVer},
+ #{sequence_number := SeqNo}) ->
+ <<?UINT64(SeqNo), ?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer)>>.
%% 1/n-1 splitting countermeasure Rizzo/Duong-Beast, RC4 chiphers are
%% not vulnerable to this attack.
@@ -440,89 +501,25 @@ do_split_bin(Bin, ChunkSize, Acc) ->
_ ->
lists:reverse(Acc, [Bin])
end.
-
%%--------------------------------------------------------------------
--spec decode_cipher_text(#ssl_tls{}, ssl_record:connection_states(), boolean()) ->
- {#ssl_tls{}, ssl_record:connection_states()}| #alert{}.
-%%
-%% Description: Decode cipher text
-%%--------------------------------------------------------------------
-decode_cipher_text(#ssl_tls{type = Type, version = Version,
- fragment = CipherFragment} = CipherText,
- #{current_read :=
- #{compression_state := CompressionS0,
- sequence_number := Seq,
- cipher_state := CipherS0,
- security_parameters :=
- #security_parameters{
- cipher_type = ?AEAD,
- bulk_cipher_algorithm =
- BulkCipherAlgo,
- compression_algorithm = CompAlg}
- } = ReadState0} = ConnnectionStates0, _) ->
- AAD = calc_aad(Type, Version, ReadState0),
- case ssl_cipher:decipher_aead(BulkCipherAlgo, CipherS0, Seq, AAD, CipherFragment, Version) of
- {PlainFragment, CipherS1} ->
- {Plain, CompressionS1} = ssl_record:uncompress(CompAlg,
- PlainFragment, CompressionS0),
- ConnnectionStates = ConnnectionStates0#{
- current_read => ReadState0#{
- cipher_state => CipherS1,
- sequence_number => Seq + 1,
- compression_state => CompressionS1}},
- {CipherText#ssl_tls{fragment = Plain}, ConnnectionStates};
- #alert{} = Alert ->
- Alert
- end;
+lowest_list_protocol_version(Ver, []) ->
+ Ver;
+lowest_list_protocol_version(Ver1, [Ver2 | Rest]) ->
+ lowest_list_protocol_version(lowest_protocol_version(Ver1, Ver2), Rest).
-decode_cipher_text(#ssl_tls{type = Type, version = Version,
- fragment = CipherFragment} = CipherText,
- #{current_read :=
- #{compression_state := CompressionS0,
- sequence_number := Seq,
- security_parameters :=
- #security_parameters{compression_algorithm = CompAlg}
- } = ReadState0} = ConnnectionStates0, PaddingCheck) ->
- case ssl_record:decipher(Version, CipherFragment, ReadState0, PaddingCheck) of
- {PlainFragment, Mac, ReadState1} ->
- MacHash = ssl_cipher:calc_mac_hash(Type, Version, PlainFragment, ReadState1),
- case ssl_record:is_correct_mac(Mac, MacHash) of
- true ->
- {Plain, CompressionS1} = ssl_record:uncompress(CompAlg,
- PlainFragment, CompressionS0),
- ConnnectionStates = ConnnectionStates0#{
- current_read => ReadState1#{
- sequence_number => Seq + 1,
- compression_state => CompressionS1}},
- {CipherText#ssl_tls{fragment = Plain}, ConnnectionStates};
- false ->
- ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
- end;
- #alert{} = Alert ->
- Alert
- end.
+highest_list_protocol_version(Ver, []) ->
+ Ver;
+highest_list_protocol_version(Ver1, [Ver2 | Rest]) ->
+ highest_list_protocol_version(highest_protocol_version(Ver1, Ver2), Rest).
+
+highest_protocol_version() ->
+ highest_protocol_version(supported_protocol_versions()).
+
+lowest_protocol_version() ->
+ lowest_protocol_version(supported_protocol_versions()).
+
+sufficient_tlsv1_2_crypto_support() ->
+ CryptoSupport = crypto:supports(),
+ proplists:get_bool(sha256, proplists:get_value(hashs, CryptoSupport)).
-do_encode_plain_text(Type, Version, Data, #{compression_state := CompS0,
- security_parameters :=
- #security_parameters{
- cipher_type = ?AEAD,
- compression_algorithm = CompAlg}
- } = WriteState0) ->
- {Comp, CompS1} = ssl_record:compress(CompAlg, Data, CompS0),
- WriteState1 = WriteState0#{compression_state => CompS1},
- AAD = calc_aad(Type, Version, WriteState1),
- ssl_record:cipher_aead(Version, Comp, WriteState1, AAD);
-do_encode_plain_text(Type, Version, Data, #{compression_state := CompS0,
- security_parameters :=
- #security_parameters{compression_algorithm = CompAlg}
- }= WriteState0) ->
- {Comp, CompS1} = ssl_record:compress(CompAlg, Data, CompS0),
- WriteState1 = WriteState0#{compression_state => CompS1},
- MacHash = ssl_cipher:calc_mac_hash(Type, Version, Comp, WriteState1),
- ssl_record:cipher(Version, Comp, WriteState1, MacHash);
-do_encode_plain_text(_,_,_,CS) ->
- exit({cs, CS}).
-calc_aad(Type, {MajVer, MinVer},
- #{sequence_number := SeqNo}) ->
- <<?UINT64(SeqNo), ?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer)>>.
diff --git a/lib/ssl/src/tls_sender.erl b/lib/ssl/src/tls_sender.erl
new file mode 100644
index 0000000000..ec03000b33
--- /dev/null
+++ b/lib/ssl/src/tls_sender.erl
@@ -0,0 +1,410 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(tls_sender).
+
+-behaviour(gen_statem).
+
+-include("ssl_internal.hrl").
+-include("ssl_alert.hrl").
+-include("ssl_handshake.hrl").
+-include("ssl_api.hrl").
+
+%% API
+-export([start/0, start/1, initialize/2, send_data/2, send_alert/2,
+ send_and_ack_alert/2, renegotiate/1,
+ update_connection_state/3, dist_tls_socket/1, dist_handshake_complete/3]).
+
+%% gen_statem callbacks
+-export([callback_mode/0, init/1, terminate/3, code_change/4]).
+-export([init/3, connection/3, handshake/3, death_row/3]).
+
+-define(SERVER, ?MODULE).
+
+-record(data, {connection_pid,
+ connection_states = #{},
+ role,
+ socket,
+ socket_options,
+ tracker,
+ protocol_cb,
+ transport_cb,
+ negotiated_version,
+ renegotiate_at,
+ connection_monitor,
+ dist_handle
+ }).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+%%--------------------------------------------------------------------
+-spec start() -> {ok, Pid :: pid()} |
+ ignore |
+ {error, Error :: term()}.
+-spec start(list()) -> {ok, Pid :: pid()} |
+ ignore |
+ {error, Error :: term()}.
+
+%% Description: Start sender process to avoid dead lock that
+%% may happen when a socket is busy (busy port) and the
+%% same process is sending and receiving
+%%--------------------------------------------------------------------
+start() ->
+ gen_statem:start(?MODULE, [], []).
+start(SpawnOpts) ->
+ gen_statem:start(?MODULE, [], SpawnOpts).
+
+%%--------------------------------------------------------------------
+-spec initialize(pid(), map()) -> ok.
+%% Description: So TLS connection process can initialize it sender
+%% process.
+%%--------------------------------------------------------------------
+initialize(Pid, InitMsg) ->
+ gen_statem:call(Pid, {self(), InitMsg}).
+
+%%--------------------------------------------------------------------
+-spec send_data(pid(), iodata()) -> ok.
+%% Description: Send application data
+%%--------------------------------------------------------------------
+send_data(Pid, AppData) ->
+ %% Needs error handling for external API
+ call(Pid, {application_data, AppData}).
+
+%%--------------------------------------------------------------------
+-spec send_alert(pid(), #alert{}) -> _.
+%% Description: TLS connection process wants to send an Alert
+%% in the connection state.
+%%--------------------------------------------------------------------
+send_alert(Pid, Alert) ->
+ gen_statem:cast(Pid, Alert).
+
+%%--------------------------------------------------------------------
+-spec send_and_ack_alert(pid(), #alert{}) -> ok.
+%% Description: TLS connection process wants to send an Alert
+%% in the connection state and recive an ack.
+%%--------------------------------------------------------------------
+send_and_ack_alert(Pid, Alert) ->
+ gen_statem:cast(Pid, {ack_alert, Alert}).
+
+%%--------------------------------------------------------------------
+-spec renegotiate(pid()) -> {ok, WriteState::map()} | {error, closed}.
+%% Description: So TLS connection process can synchronize the
+%% encryption state to be used when handshaking.
+%%--------------------------------------------------------------------
+renegotiate(Pid) ->
+ %% Needs error handling for external API
+ call(Pid, renegotiate).
+%%--------------------------------------------------------------------
+-spec update_connection_state(pid(), WriteState::map(), tls_record:tls_version()) -> ok.
+%% Description: So TLS connection process can synchronize the
+%% encryption state to be used when sending application data.
+%%--------------------------------------------------------------------
+update_connection_state(Pid, NewState, Version) ->
+ gen_statem:cast(Pid, {new_write, NewState, Version}).
+%%--------------------------------------------------------------------
+-spec dist_handshake_complete(pid(), node(), term()) -> ok.
+%% Description: Erlang distribution callback
+%%--------------------------------------------------------------------
+dist_handshake_complete(ConnectionPid, Node, DHandle) ->
+ gen_statem:call(ConnectionPid, {dist_handshake_complete, Node, DHandle}).
+%%--------------------------------------------------------------------
+-spec dist_tls_socket(pid()) -> {ok, #sslsocket{}}.
+%% Description: To enable distribution startup to get a proper "#sslsocket{}"
+%%--------------------------------------------------------------------
+dist_tls_socket(Pid) ->
+ gen_statem:call(Pid, dist_get_tls_socket).
+
+%%%===================================================================
+%%% gen_statem callbacks
+%%%===================================================================
+%%--------------------------------------------------------------------
+-spec callback_mode() -> gen_statem:callback_mode_result().
+%%--------------------------------------------------------------------
+callback_mode() ->
+ state_functions.
+
+%%--------------------------------------------------------------------
+-spec init(Args :: term()) ->
+ gen_statem:init_result(atom()).
+%%--------------------------------------------------------------------
+init(_) ->
+ %% Note: Should not trap exits so that this process
+ %% will be terminated if tls_connection process is
+ %% killed brutally
+ {ok, init, #data{}}.
+
+%%--------------------------------------------------------------------
+-spec init(gen_statem:event_type(),
+ Msg :: term(),
+ StateData :: term()) ->
+ gen_statem:event_handler_result(atom()).
+%%--------------------------------------------------------------------
+init({call, From}, {Pid, #{current_write := WriteState,
+ role := Role,
+ socket := Socket,
+ socket_options := SockOpts,
+ tracker := Tracker,
+ protocol_cb := Connection,
+ transport_cb := Transport,
+ negotiated_version := Version,
+ renegotiate_at := RenegotiateAt}},
+ #data{connection_states = ConnectionStates} = StateData0) ->
+ Monitor = erlang:monitor(process, Pid),
+ StateData =
+ StateData0#data{connection_pid = Pid,
+ connection_monitor = Monitor,
+ connection_states =
+ ConnectionStates#{current_write => WriteState},
+ role = Role,
+ socket = Socket,
+ socket_options = SockOpts,
+ tracker = Tracker,
+ protocol_cb = Connection,
+ transport_cb = Transport,
+ negotiated_version = Version,
+ renegotiate_at = RenegotiateAt},
+ {next_state, handshake, StateData, [{reply, From, ok}]};
+init(info, Msg, StateData) ->
+ handle_info(Msg, ?FUNCTION_NAME, StateData).
+%%--------------------------------------------------------------------
+-spec connection(gen_statem:event_type(),
+ Msg :: term(),
+ StateData :: term()) ->
+ gen_statem:event_handler_result(atom()).
+%%--------------------------------------------------------------------
+connection({call, From}, renegotiate,
+ #data{connection_states = #{current_write := Write}} = StateData) ->
+ {next_state, handshake, StateData, [{reply, From, {ok, Write}}]};
+connection({call, From}, {application_data, AppData},
+ #data{socket_options = SockOpts} = StateData) ->
+ case encode_packet(AppData, SockOpts) of
+ {error, _} = Error ->
+ {next_state, ?FUNCTION_NAME, StateData, [{reply, From, Error}]};
+ Data ->
+ send_application_data(Data, From, ?FUNCTION_NAME, StateData)
+ end;
+connection({call, From}, dist_get_tls_socket,
+ #data{protocol_cb = Connection,
+ transport_cb = Transport,
+ socket = Socket,
+ connection_pid = Pid,
+ tracker = Tracker} = StateData) ->
+ TLSSocket = Connection:socket([Pid, self()], Transport, Socket, Connection, Tracker),
+ {next_state, ?FUNCTION_NAME, StateData, [{reply, From, {ok, TLSSocket}}]};
+connection({call, From}, {dist_handshake_complete, _Node, DHandle}, #data{connection_pid = Pid} = StateData) ->
+ ok = erlang:dist_ctrl_input_handler(DHandle, Pid),
+ ok = ssl_connection:dist_handshake_complete(Pid, DHandle),
+ %% From now on we execute on normal priority
+ process_flag(priority, normal),
+ Events = dist_data_events(DHandle, []),
+ {next_state, ?FUNCTION_NAME, StateData#data{dist_handle = DHandle}, [{reply, From, ok} | Events]};
+connection(cast, {ack_alert, #alert{} = Alert}, #data{connection_pid = Pid} =StateData0) ->
+ StateData = send_tls_alert(Alert, StateData0),
+ Pid ! {self(), ack_alert},
+ {next_state, ?FUNCTION_NAME, StateData};
+connection(cast, #alert{} = Alert, StateData0) ->
+ StateData = send_tls_alert(Alert, StateData0),
+ {next_state, ?FUNCTION_NAME, StateData};
+connection(cast, {new_write, WritesState, Version},
+ #data{connection_states = ConnectionStates0} = StateData) ->
+ {next_state, connection,
+ StateData#data{connection_states =
+ ConnectionStates0#{current_write => WritesState},
+ negotiated_version = Version}};
+connection(info, dist_data, #data{dist_handle = DHandle} = StateData) ->
+ Events = dist_data_events(DHandle, []),
+ {next_state, ?FUNCTION_NAME, StateData, Events};
+connection(info, tick, StateData) ->
+ consume_ticks(),
+ {next_state, ?FUNCTION_NAME, StateData,
+ [{next_event, {call, {self(), undefined}},
+ {application_data, <<>>}}]};
+connection(info, {send, From, Ref, Data}, _StateData) ->
+ %% This is for testing only!
+ %%
+ %% Needed by some OTP distribution
+ %% test suites...
+ From ! {Ref, ok},
+ {keep_state_and_data,
+ [{next_event, {call, {self(), undefined}},
+ {application_data, iolist_to_binary(Data)}}]};
+connection(info, Msg, StateData) ->
+ handle_info(Msg, ?FUNCTION_NAME, StateData).
+%%--------------------------------------------------------------------
+-spec handshake(gen_statem:event_type(),
+ Msg :: term(),
+ StateData :: term()) ->
+ gen_statem:event_handler_result(atom()).
+%%--------------------------------------------------------------------
+handshake({call, _}, _, _) ->
+ {keep_state_and_data, [postpone]};
+handshake(cast, {new_write, WritesState, Version},
+ #data{connection_states = ConnectionStates0} = StateData) ->
+ {next_state, connection,
+ StateData#data{connection_states =
+ ConnectionStates0#{current_write => WritesState},
+ negotiated_version = Version}};
+handshake(info, Msg, StateData) ->
+ handle_info(Msg, ?FUNCTION_NAME, StateData).
+
+%%--------------------------------------------------------------------
+-spec death_row(gen_statem:event_type(),
+ Msg :: term(),
+ StateData :: term()) ->
+ gen_statem:event_handler_result(atom()).
+%%--------------------------------------------------------------------
+death_row(state_timeout, Reason, _State) ->
+ {stop, {shutdown, Reason}};
+death_row(_Type, _Msg, _State) ->
+ %% Waste all other events
+ keep_state_and_data.
+
+%%--------------------------------------------------------------------
+-spec terminate(Reason :: term(), State :: term(), Data :: term()) ->
+ any().
+%%--------------------------------------------------------------------
+terminate(_Reason, _State, _Data) ->
+ void.
+
+%%--------------------------------------------------------------------
+-spec code_change(
+ OldVsn :: term() | {down,term()},
+ State :: term(), Data :: term(), Extra :: term()) ->
+ {ok, NewState :: term(), NewData :: term()} |
+ (Reason :: term()).
+%% Convert process state when code is changed
+%%--------------------------------------------------------------------
+code_change(_OldVsn, State, Data, _Extra) ->
+ {ok, State, Data}.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+handle_info({'DOWN', Monitor, _, _, Reason}, _,
+ #data{connection_monitor = Monitor,
+ dist_handle = Handle} = StateData) when Handle =/= undefined->
+ {next_state, death_row, StateData, [{state_timeout, 5000, Reason}]};
+handle_info({'DOWN', Monitor, _, _, _}, _,
+ #data{connection_monitor = Monitor} = StateData) ->
+ {stop, normal, StateData};
+handle_info(_,_,_) ->
+ {keep_state_and_data}.
+
+send_tls_alert(Alert, #data{negotiated_version = Version,
+ socket = Socket,
+ protocol_cb = Connection,
+ transport_cb = Transport,
+ connection_states = ConnectionStates0} = StateData0) ->
+ {BinMsg, ConnectionStates} =
+ Connection:encode_alert(Alert, Version, ConnectionStates0),
+ Connection:send(Transport, Socket, BinMsg),
+ StateData0#data{connection_states = ConnectionStates}.
+
+send_application_data(Data, From, StateName,
+ #data{connection_pid = Pid,
+ socket = Socket,
+ dist_handle = DistHandle,
+ negotiated_version = Version,
+ protocol_cb = Connection,
+ transport_cb = Transport,
+ connection_states = ConnectionStates0,
+ renegotiate_at = RenegotiateAt} = StateData0) ->
+ case time_to_renegotiate(Data, ConnectionStates0, RenegotiateAt) of
+ true ->
+ ssl_connection:internal_renegotiation(Pid, ConnectionStates0),
+ {next_state, handshake, StateData0,
+ [{next_event, {call, From}, {application_data, Data}}]};
+ false ->
+ {Msgs, ConnectionStates} =
+ Connection:encode_data(Data, Version, ConnectionStates0),
+ StateData = StateData0#data{connection_states = ConnectionStates},
+ case Connection:send(Transport, Socket, Msgs) of
+ ok when DistHandle =/= undefined ->
+ {next_state, StateName, StateData, []};
+ Reason when DistHandle =/= undefined ->
+ {next_state, death_row, StateData, [{state_timeout, 5000, Reason}]};
+ ok ->
+ {next_state, StateName, StateData, [{reply, From, ok}]};
+ Result ->
+ {next_state, StateName, StateData, [{reply, From, Result}]}
+ end
+ end.
+
+encode_packet(Data, #socket_options{packet=Packet}) ->
+ case Packet of
+ 1 -> encode_size_packet(Data, 8, (1 bsl 8) - 1);
+ 2 -> encode_size_packet(Data, 16, (1 bsl 16) - 1);
+ 4 -> encode_size_packet(Data, 32, (1 bsl 32) - 1);
+ _ -> Data
+ end.
+
+encode_size_packet(Bin, Size, Max) ->
+ Len = erlang:byte_size(Bin),
+ case Len > Max of
+ true ->
+ {error, {badarg, {packet_to_large, Len, Max}}};
+ false ->
+ <<Len:Size, Bin/binary>>
+ end.
+time_to_renegotiate(_Data,
+ #{current_write := #{sequence_number := Num}},
+ RenegotiateAt) ->
+
+ %% We could do test:
+ %% is_time_to_renegotiate((erlang:byte_size(_Data) div
+ %% ?MAX_PLAIN_TEXT_LENGTH) + 1, RenegotiateAt), but we chose to
+ %% have a some what lower renegotiateAt and a much cheaper test
+ is_time_to_renegotiate(Num, RenegotiateAt).
+
+is_time_to_renegotiate(N, M) when N < M->
+ false;
+is_time_to_renegotiate(_,_) ->
+ true.
+
+call(FsmPid, Event) ->
+ try gen_statem:call(FsmPid, Event)
+ catch
+ exit:{noproc, _} ->
+ {error, closed};
+ exit:{normal, _} ->
+ {error, closed};
+ exit:{{shutdown, _},_} ->
+ {error, closed}
+ end.
+
+%%---------------Erlang distribution --------------------------------------
+
+dist_data_events(DHandle, Events) ->
+ case erlang:dist_ctrl_get_data(DHandle) of
+ none ->
+ erlang:dist_ctrl_get_data_notification(DHandle),
+ lists:reverse(Events);
+ Data ->
+ Event = {next_event, {call, {self(), undefined}}, {application_data, Data}},
+ dist_data_events(DHandle, [Event | Events])
+ end.
+
+consume_ticks() ->
+ receive tick ->
+ consume_ticks()
+ after 0 ->
+ ok
+ end.
diff --git a/lib/ssl/src/tls_socket.erl b/lib/ssl/src/tls_socket.erl
index e76d9c100a..a391bc53de 100644
--- a/lib/ssl/src/tls_socket.erl
+++ b/lib/ssl/src/tls_socket.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@
-export([send/3, listen/3, accept/3, socket/5, connect/4, upgrade/3,
setopts/3, getopts/3, getstat/3, peername/2, sockname/2, port/2]).
-export([split_options/1, get_socket_opts/3]).
--export([emulated_options/0, internal_inet_values/0, default_inet_values/0,
+-export([emulated_options/0, emulated_options/1, internal_inet_values/0, default_inet_values/0,
init/1, start_link/3, terminate/2, inherit_tracker/3,
emulated_socket_options/2, get_emulated_opts/1,
set_emulated_opts/2, get_all_opts/1, handle_call/3, handle_cast/2,
@@ -64,11 +64,12 @@ accept(ListenSocket, #config{transport_info = {Transport,_,_,_} = CbInfo,
{ok, Socket} ->
{ok, EmOpts} = get_emulated_opts(Tracker),
{ok, Port} = tls_socket:port(Transport, Socket),
- ConnArgs = [server, "localhost", Port, Socket,
+ {ok, Sender} = tls_sender:start(),
+ ConnArgs = [server, Sender, "localhost", Port, Socket,
{SslOpts, emulated_socket_options(EmOpts, #socket_options{}), Tracker}, self(), CbInfo],
case tls_connection_sup:start_child(ConnArgs) of
{ok, Pid} ->
- ssl_connection:socket_control(ConnectionCb, Socket, Pid, Transport, Tracker);
+ ssl_connection:socket_control(ConnectionCb, Socket, [Pid, Sender], Transport, Tracker);
{error, Reason} ->
{error, Reason}
end;
@@ -112,8 +113,8 @@ connect(Address, Port,
{error, {options, {socket_options, UserOpts}}}
end.
-socket(Pid, Transport, Socket, ConnectionCb, Tracker) ->
- #sslsocket{pid = Pid,
+socket(Pids, Transport, Socket, ConnectionCb, Tracker) ->
+ #sslsocket{pid = Pids,
%% "The name "fd" is keept for backwards compatibility
fd = {Transport, Socket, ConnectionCb, Tracker}}.
setopts(gen_tcp, #sslsocket{pid = {ListenSocket, #config{emulated = Tracker}}}, Options) ->
@@ -170,6 +171,9 @@ port(Transport, Socket) ->
emulated_options() ->
[mode, packet, active, header, packet_size].
+emulated_options(Opts) ->
+ emulated_options(Opts, internal_inet_values(), default_inet_values()).
+
internal_inet_values() ->
[{packet_size,0}, {packet, 0}, {header, 0}, {active, false}, {mode,binary}].
@@ -328,3 +332,41 @@ emulated_socket_options(InetValues, #socket_options{
packet = proplists:get_value(packet, InetValues, Packet),
packet_size = proplists:get_value(packet_size, InetValues, Size)
}.
+
+emulated_options([{mode, Value} = Opt |Opts], Inet, Emulated) ->
+ validate_inet_option(mode, Value),
+ emulated_options(Opts, Inet, [Opt | proplists:delete(mode, Emulated)]);
+emulated_options([{header, Value} = Opt | Opts], Inet, Emulated) ->
+ validate_inet_option(header, Value),
+ emulated_options(Opts, Inet, [Opt | proplists:delete(header, Emulated)]);
+emulated_options([{active, Value} = Opt |Opts], Inet, Emulated) ->
+ validate_inet_option(active, Value),
+ emulated_options(Opts, Inet, [Opt | proplists:delete(active, Emulated)]);
+emulated_options([{packet, Value} = Opt |Opts], Inet, Emulated) ->
+ validate_inet_option(packet, Value),
+ emulated_options(Opts, Inet, [Opt | proplists:delete(packet, Emulated)]);
+emulated_options([{packet_size, Value} = Opt | Opts], Inet, Emulated) ->
+ validate_inet_option(packet_size, Value),
+ emulated_options(Opts, Inet, [Opt | proplists:delete(packet_size, Emulated)]);
+emulated_options([Opt|Opts], Inet, Emulated) ->
+ emulated_options(Opts, [Opt|Inet], Emulated);
+emulated_options([], Inet,Emulated) ->
+ {Inet, Emulated}.
+
+validate_inet_option(mode, Value)
+ when Value =/= list, Value =/= binary ->
+ throw({error, {options, {mode,Value}}});
+validate_inet_option(packet, Value)
+ when not (is_atom(Value) orelse is_integer(Value)) ->
+ throw({error, {options, {packet,Value}}});
+validate_inet_option(packet_size, Value)
+ when not is_integer(Value) ->
+ throw({error, {options, {packet_size,Value}}});
+validate_inet_option(header, Value)
+ when not is_integer(Value) ->
+ throw({error, {options, {header,Value}}});
+validate_inet_option(active, Value)
+ when Value =/= true, Value =/= false, Value =/= once ->
+ throw({error, {options, {active,Value}}});
+validate_inet_option(_, _) ->
+ ok.
diff --git a/lib/ssl/src/tls_v1.erl b/lib/ssl/src/tls_v1.erl
index a8fe119bf8..1bfd9a8b6d 100644
--- a/lib/ssl/src/tls_v1.erl
+++ b/lib/ssl/src/tls_v1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -192,7 +192,7 @@ mac_hash(Method, Mac_write_secret, Seq_num, Type, {Major, Minor},
Fragment]),
Mac.
--spec suites(1|2|3) -> [ssl_cipher:cipher_suite()].
+-spec suites(1|2|3) -> [ssl_cipher_format:cipher_suite()].
suites(Minor) when Minor == 1; Minor == 2 ->
[
@@ -202,23 +202,13 @@ suites(Minor) when Minor == 1; Minor == 2 ->
?TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
- ?TLS_RSA_WITH_AES_256_CBC_SHA,
?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
?TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
?TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
- ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
- ?TLS_RSA_WITH_AES_128_CBC_SHA,
-
- ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
- ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
- ?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
- ?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
- ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
- ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
- ?TLS_RSA_WITH_3DES_EDE_CBC_SHA
+ ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
];
suites(3) ->
[?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
@@ -230,16 +220,10 @@ suites(3) ->
?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
- ?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
- ?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
- ?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-
?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384,
?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
- ?TLS_RSA_WITH_AES_256_GCM_SHA384,
- ?TLS_RSA_WITH_AES_256_CBC_SHA256,
?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
@@ -253,9 +237,7 @@ suites(3) ->
?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,
?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
- ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
- ?TLS_RSA_WITH_AES_128_GCM_SHA256,
- ?TLS_RSA_WITH_AES_128_CBC_SHA256
+ ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
%% not supported
%% ?TLS_DH_RSA_WITH_AES_256_GCM_SHA384,
@@ -264,8 +246,6 @@ suites(3) ->
%% ?TLS_DH_DSS_WITH_AES_128_GCM_SHA256
] ++ suites(2).
-
-
signature_algs({3, 3}, HashSigns) ->
CryptoSupports = crypto:supports(),
Hashes = proplists:get_value(hashs, CryptoSupports),
diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile
index 558be6d642..9dfb2eba53 100644
--- a/lib/ssl/test/Makefile
+++ b/lib/ssl/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2017. All Rights Reserved.
+# Copyright Ericsson AB 1999-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -37,6 +37,8 @@ VSN=$(GS_VSN)
MODULES = \
ssl_test_lib \
+ ssl_bench_test_lib \
+ ssl_dist_test_lib \
ssl_alpn_handshake_SUITE \
ssl_basic_SUITE \
ssl_bench_SUITE \
@@ -44,6 +46,8 @@ MODULES = \
ssl_certificate_verify_SUITE\
ssl_crl_SUITE\
ssl_dist_SUITE \
+ ssl_dist_bench_SUITE \
+ ssl_engine_SUITE\
ssl_handshake_SUITE \
ssl_npn_hello_SUITE \
ssl_npn_handshake_SUITE \
@@ -53,16 +57,18 @@ MODULES = \
ssl_session_cache_SUITE \
ssl_to_openssl_SUITE \
ssl_ECC_SUITE \
+ ssl_ECC_openssl_SUITE \
+ ssl_ECC\
ssl_upgrade_SUITE\
ssl_sni_SUITE \
make_certs\
- erl_make_certs\
x509_test
ERL_FILES = $(MODULES:%=%.erl)
-HRL_FILES =
+HRL_FILES = \
+ ssl_dist_test_lib.hrl
HRL_FILES_SRC = \
ssl_api.hrl\
diff --git a/lib/ssl/test/erl_make_certs.erl b/lib/ssl/test/erl_make_certs.erl
deleted file mode 100644
index 3ab6222780..0000000000
--- a/lib/ssl/test/erl_make_certs.erl
+++ /dev/null
@@ -1,477 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2011-2017. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%% Create test certificates
-
--module(erl_make_certs).
--include_lib("public_key/include/public_key.hrl").
-
--export([make_cert/1, gen_rsa/1, verify_signature/3, write_pem/3]).
--compile(export_all).
-
-%%--------------------------------------------------------------------
-%% @doc Create and return a der encoded certificate
-%% Option Default
-%% -------------------------------------------------------
-%% digest sha1
-%% validity {date(), date() + week()}
-%% version 3
-%% subject [] list of the following content
-%% {name, Name}
-%% {email, Email}
-%% {city, City}
-%% {state, State}
-%% {org, Org}
-%% {org_unit, OrgUnit}
-%% {country, Country}
-%% {serial, Serial}
-%% {title, Title}
-%% {dnQualifer, DnQ}
-%% issuer = {Issuer, IssuerKey} true (i.e. a ca cert is created)
-%% (obs IssuerKey migth be {Key, Password}
-%% key = KeyFile|KeyBin|rsa|dsa|ec Subject PublicKey rsa, dsa or ec generates key
-%%
-%%
-%% (OBS: The generated keys are for testing only)
-%% @spec ([{::atom(), ::term()}]) -> {Cert::binary(), Key::binary()}
-%% @end
-%%--------------------------------------------------------------------
-
-make_cert(Opts) ->
- SubjectPrivateKey = get_key(Opts),
- {TBSCert, IssuerKey} = make_tbs(SubjectPrivateKey, Opts),
- Cert = public_key:pkix_sign(TBSCert, IssuerKey),
- true = verify_signature(Cert, IssuerKey, undef), %% verify that the keys where ok
- {Cert, encode_key(SubjectPrivateKey)}.
-
-%%--------------------------------------------------------------------
-%% @doc Writes pem files in Dir with FileName ++ ".pem" and FileName ++ "_key.pem"
-%% @spec (::string(), ::string(), {Cert,Key}) -> ok
-%% @end
-%%--------------------------------------------------------------------
-write_pem(Dir, FileName, {Cert, Key = {_,_,not_encrypted}}) when is_binary(Cert) ->
- ok = der_to_pem(filename:join(Dir, FileName ++ ".pem"),
- [{'Certificate', Cert, not_encrypted}]),
- ok = der_to_pem(filename:join(Dir, FileName ++ "_key.pem"), [Key]).
-
-%%--------------------------------------------------------------------
-%% @doc Creates a rsa key (OBS: for testing only)
-%% the size are in bytes
-%% @spec (::integer()) -> {::atom(), ::binary(), ::opaque()}
-%% @end
-%%--------------------------------------------------------------------
-gen_rsa(Size) when is_integer(Size) ->
- Key = gen_rsa2(Size),
- {Key, encode_key(Key)}.
-
-%%--------------------------------------------------------------------
-%% @doc Creates a dsa key (OBS: for testing only)
-%% the sizes are in bytes
-%% @spec (::integer()) -> {::atom(), ::binary(), ::opaque()}
-%% @end
-%%--------------------------------------------------------------------
-gen_dsa(LSize,NSize) when is_integer(LSize), is_integer(NSize) ->
- Key = gen_dsa2(LSize, NSize),
- {Key, encode_key(Key)}.
-
-%%--------------------------------------------------------------------
-%% @doc Creates a ec key (OBS: for testing only)
-%% the sizes are in bytes
-%% @spec (::integer()) -> {::atom(), ::binary(), ::opaque()}
-%% @end
-%%--------------------------------------------------------------------
-gen_ec(Curve) when is_atom(Curve) ->
- Key = gen_ec2(Curve),
- {Key, encode_key(Key)}.
-
-%%--------------------------------------------------------------------
-%% @doc Verifies cert signatures
-%% @spec (::binary(), ::tuple()) -> ::boolean()
-%% @end
-%%--------------------------------------------------------------------
-verify_signature(DerEncodedCert, DerKey, _KeyParams) ->
- Key = decode_key(DerKey),
- case Key of
- #'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} ->
- public_key:pkix_verify(DerEncodedCert,
- #'RSAPublicKey'{modulus=Mod, publicExponent=Exp});
- #'DSAPrivateKey'{p=P, q=Q, g=G, y=Y} ->
- public_key:pkix_verify(DerEncodedCert, {Y, #'Dss-Parms'{p=P, q=Q, g=G}});
- #'ECPrivateKey'{version = _Version, privateKey = _PrivKey,
- parameters = Params, publicKey = PubKey} ->
- public_key:pkix_verify(DerEncodedCert, {#'ECPoint'{point = PubKey}, Params})
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%% Implementation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-get_key(Opts) ->
- case proplists:get_value(key, Opts) of
- undefined -> make_key(rsa, Opts);
- rsa -> make_key(rsa, Opts);
- dsa -> make_key(dsa, Opts);
- ec -> make_key(ec, Opts);
- Key ->
- Password = proplists:get_value(password, Opts, no_passwd),
- decode_key(Key, Password)
- end.
-
-decode_key({Key, Pw}) ->
- decode_key(Key, Pw);
-decode_key(Key) ->
- decode_key(Key, no_passwd).
-
-
-decode_key(#'RSAPublicKey'{} = Key,_) ->
- Key;
-decode_key(#'RSAPrivateKey'{} = Key,_) ->
- Key;
-decode_key(#'DSAPrivateKey'{} = Key,_) ->
- Key;
-decode_key(#'ECPrivateKey'{} = Key,_) ->
- Key;
-decode_key(PemEntry = {_,_,_}, Pw) ->
- public_key:pem_entry_decode(PemEntry, Pw);
-decode_key(PemBin, Pw) ->
- [KeyInfo] = public_key:pem_decode(PemBin),
- decode_key(KeyInfo, Pw).
-
-encode_key(Key = #'RSAPrivateKey'{}) ->
- {ok, Der} = 'OTP-PUB-KEY':encode('RSAPrivateKey', Key),
- {'RSAPrivateKey', Der, not_encrypted};
-encode_key(Key = #'DSAPrivateKey'{}) ->
- {ok, Der} = 'OTP-PUB-KEY':encode('DSAPrivateKey', Key),
- {'DSAPrivateKey', Der, not_encrypted};
-encode_key(Key = #'ECPrivateKey'{}) ->
- {ok, Der} = 'OTP-PUB-KEY':encode('ECPrivateKey', Key),
- {'ECPrivateKey', Der, not_encrypted}.
-
-make_tbs(SubjectKey, Opts) ->
- Version = list_to_atom("v"++integer_to_list(proplists:get_value(version, Opts, 3))),
-
- IssuerProp = proplists:get_value(issuer, Opts, true),
- {Issuer, IssuerKey} = issuer(IssuerProp, Opts, SubjectKey),
-
- {Algo, Parameters} = sign_algorithm(IssuerKey, Opts),
-
- SignAlgo = #'SignatureAlgorithm'{algorithm = Algo,
- parameters = Parameters},
- Subject = case IssuerProp of
- true -> %% Is a Root Ca
- Issuer;
- _ ->
- subject(proplists:get_value(subject, Opts),false)
- end,
-
- {#'OTPTBSCertificate'{serialNumber = trunc(rand:uniform()*100000000)*10000 + 1,
- signature = SignAlgo,
- issuer = Issuer,
- validity = validity(Opts),
- subject = Subject,
- subjectPublicKeyInfo = publickey(SubjectKey),
- version = Version,
- extensions = extensions(Opts)
- }, IssuerKey}.
-
-issuer(true, Opts, SubjectKey) ->
- %% Self signed
- {subject(proplists:get_value(subject, Opts), true), SubjectKey};
-issuer({Issuer, IssuerKey}, _Opts, _SubjectKey) when is_binary(Issuer) ->
- {issuer_der(Issuer), decode_key(IssuerKey)};
-issuer({File, IssuerKey}, _Opts, _SubjectKey) when is_list(File) ->
- {ok, [{cert, Cert, _}|_]} = pem_to_der(File),
- {issuer_der(Cert), decode_key(IssuerKey)}.
-
-issuer_der(Issuer) ->
- Decoded = public_key:pkix_decode_cert(Issuer, otp),
- #'OTPCertificate'{tbsCertificate=Tbs} = Decoded,
- #'OTPTBSCertificate'{subject=Subject} = Tbs,
- Subject.
-
-subject(undefined, IsRootCA) ->
- User = if IsRootCA -> "RootCA"; true -> os:getenv("USER", "test_user") end,
- Opts = [{email, User ++ "@erlang.org"},
- {name, User},
- {city, "Stockholm"},
- {country, "SE"},
- {org, "erlang"},
- {org_unit, "testing dep"}],
- subject(Opts);
-subject(Opts, _) ->
- subject(Opts).
-
-subject(SubjectOpts) when is_list(SubjectOpts) ->
- Encode = fun(Opt) ->
- {Type,Value} = subject_enc(Opt),
- [#'AttributeTypeAndValue'{type=Type, value=Value}]
- end,
- {rdnSequence, [Encode(Opt) || Opt <- SubjectOpts]}.
-
-%% Fill in the blanks
-subject_enc({name, Name}) -> {?'id-at-commonName', {printableString, Name}};
-subject_enc({email, Email}) -> {?'id-emailAddress', Email};
-subject_enc({city, City}) -> {?'id-at-localityName', {printableString, City}};
-subject_enc({state, State}) -> {?'id-at-stateOrProvinceName', {printableString, State}};
-subject_enc({org, Org}) -> {?'id-at-organizationName', {printableString, Org}};
-subject_enc({org_unit, OrgUnit}) -> {?'id-at-organizationalUnitName', {printableString, OrgUnit}};
-subject_enc({country, Country}) -> {?'id-at-countryName', Country};
-subject_enc({serial, Serial}) -> {?'id-at-serialNumber', Serial};
-subject_enc({title, Title}) -> {?'id-at-title', {printableString, Title}};
-subject_enc({dnQualifer, DnQ}) -> {?'id-at-dnQualifier', DnQ};
-subject_enc(Other) -> Other.
-
-
-extensions(Opts) ->
- case proplists:get_value(extensions, Opts, []) of
- false ->
- asn1_NOVALUE;
- Exts ->
- lists:flatten([extension(Ext) || Ext <- default_extensions(Exts)])
- end.
-
-default_extensions(Exts) ->
- Def = [{key_usage,undefined},
- {subject_altname, undefined},
- {issuer_altname, undefined},
- {basic_constraints, default},
- {name_constraints, undefined},
- {policy_constraints, undefined},
- {ext_key_usage, undefined},
- {inhibit_any, undefined},
- {auth_key_id, undefined},
- {subject_key_id, undefined},
- {policy_mapping, undefined}],
- Filter = fun({Key, _}, D) -> lists:keydelete(Key, 1, D) end,
- Exts ++ lists:foldl(Filter, Def, Exts).
-
-extension({_, undefined}) -> [];
-extension({basic_constraints, Data}) ->
- case Data of
- default ->
- #'Extension'{extnID = ?'id-ce-basicConstraints',
- extnValue = #'BasicConstraints'{cA=true},
- critical=true};
- false ->
- [];
- Len when is_integer(Len) ->
- #'Extension'{extnID = ?'id-ce-basicConstraints',
- extnValue = #'BasicConstraints'{cA=true, pathLenConstraint=Len},
- critical=true};
- _ ->
- #'Extension'{extnID = ?'id-ce-basicConstraints',
- extnValue = Data}
- end;
-extension({Id, Data, Critical}) ->
- #'Extension'{extnID = Id, extnValue = Data, critical = Critical}.
-
-
-publickey(#'RSAPrivateKey'{modulus=N, publicExponent=E}) ->
- Public = #'RSAPublicKey'{modulus=N, publicExponent=E},
- Algo = #'PublicKeyAlgorithm'{algorithm= ?rsaEncryption, parameters='NULL'},
- #'OTPSubjectPublicKeyInfo'{algorithm = Algo,
- subjectPublicKey = Public};
-publickey(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) ->
- Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa',
- parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}},
- #'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y};
-publickey(#'ECPrivateKey'{version = _Version,
- privateKey = _PrivKey,
- parameters = Params,
- publicKey = PubKey}) ->
- Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-ecPublicKey', parameters=Params},
- #'OTPSubjectPublicKeyInfo'{algorithm = Algo,
- subjectPublicKey = #'ECPoint'{point = PubKey}}.
-
-validity(Opts) ->
- DefFrom0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())-1),
- DefTo0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())+7),
- {DefFrom, DefTo} = proplists:get_value(validity, Opts, {DefFrom0, DefTo0}),
- Format = fun({Y,M,D}) -> lists:flatten(io_lib:format("~w~2..0w~2..0w000000Z",[Y,M,D])) end,
- #'Validity'{notBefore={generalTime, Format(DefFrom)},
- notAfter ={generalTime, Format(DefTo)}}.
-
-sign_algorithm(#'RSAPrivateKey'{}, Opts) ->
- Type = case proplists:get_value(digest, Opts, sha1) of
- sha1 -> ?'sha1WithRSAEncryption';
- sha512 -> ?'sha512WithRSAEncryption';
- sha384 -> ?'sha384WithRSAEncryption';
- sha256 -> ?'sha256WithRSAEncryption';
- md5 -> ?'md5WithRSAEncryption';
- md2 -> ?'md2WithRSAEncryption'
- end,
- {Type, 'NULL'};
-sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) ->
- {?'id-dsa-with-sha1', {params,#'Dss-Parms'{p=P, q=Q, g=G}}};
-sign_algorithm(#'ECPrivateKey'{parameters = Parms}, Opts) ->
- Type = case proplists:get_value(digest, Opts, sha1) of
- sha1 -> ?'ecdsa-with-SHA1';
- sha512 -> ?'ecdsa-with-SHA512';
- sha384 -> ?'ecdsa-with-SHA384';
- sha256 -> ?'ecdsa-with-SHA256'
- end,
- {Type, Parms}.
-
-make_key(rsa, _Opts) ->
- %% (OBS: for testing only)
- gen_rsa2(64);
-make_key(dsa, _Opts) ->
- gen_dsa2(128, 20); %% Bytes i.e. {1024, 160}
-make_key(ec, _Opts) ->
- %% (OBS: for testing only)
- CurveOid = hd(tls_v1:ecc_curves(0)),
- NamedCurve = pubkey_cert_records:namedCurves(CurveOid),
- gen_ec2(NamedCurve).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% RSA key generation (OBS: for testing only)
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
--define(SMALL_PRIMES, [65537,97,89,83,79,73,71,67,61,59,53,
- 47,43,41,37,31,29,23,19,17,13,11,7,5,3]).
-
-gen_rsa2(Size) ->
- P = prime(Size),
- Q = prime(Size),
- N = P*Q,
- Tot = (P - 1) * (Q - 1),
- [E|_] = lists:dropwhile(fun(Candidate) -> (Tot rem Candidate) == 0 end, ?SMALL_PRIMES),
- {D1,D2} = extended_gcd(E, Tot),
- D = erlang:max(D1,D2),
- case D < E of
- true ->
- gen_rsa2(Size);
- false ->
- {Co1,Co2} = extended_gcd(Q, P),
- Co = erlang:max(Co1,Co2),
- #'RSAPrivateKey'{version = 'two-prime',
- modulus = N,
- publicExponent = E,
- privateExponent = D,
- prime1 = P,
- prime2 = Q,
- exponent1 = D rem (P-1),
- exponent2 = D rem (Q-1),
- coefficient = Co
- }
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% DSA key generation (OBS: for testing only)
-%% See http://en.wikipedia.org/wiki/Digital_Signature_Algorithm
-%% and the fips_186-3.pdf
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-gen_dsa2(LSize, NSize) ->
- Q = prime(NSize), %% Choose N-bit prime Q
- X0 = prime(LSize),
- P0 = prime((LSize div 2) +1),
-
- %% Choose L-bit prime modulus P such that p-1 is a multiple of q.
- case dsa_search(X0 div (2*Q*P0), P0, Q, 1000) of
- error ->
- gen_dsa2(LSize, NSize);
- P ->
- G = crypto:mod_pow(2, (P-1) div Q, P), % Choose G a number whose multiplicative order modulo p is q.
- %% such that This may be done by setting g = h^(p-1)/q mod p, commonly h=2 is used.
-
- X = prime(20), %% Choose x by some random method, where 0 < x < q.
- Y = crypto:mod_pow(G, X, P), %% Calculate y = g^x mod p.
-
- #'DSAPrivateKey'{version=0, p = P, q = Q,
- g = crypto:bytes_to_integer(G), y = crypto:bytes_to_integer(Y), x = X}
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% EC key generation (OBS: for testing only)
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-gen_ec2(CurveId) ->
- {PubKey, PrivKey} = crypto:generate_key(ecdh, CurveId),
-
- #'ECPrivateKey'{version = 1,
- privateKey = PrivKey,
- parameters = {namedCurve, pubkey_cert_records:namedCurves(CurveId)},
- publicKey = PubKey}.
-
-%% See fips_186-3.pdf
-dsa_search(T, P0, Q, Iter) when Iter > 0 ->
- P = 2*T*Q*P0 + 1,
- case is_prime(P, 50) of
- true -> P;
- false -> dsa_search(T+1, P0, Q, Iter-1)
- end;
-dsa_search(_,_,_,_) ->
- error.
-
-
-%%%%%%% Crypto Math %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-prime(ByteSize) ->
- Rand = odd_rand(ByteSize),
- prime_odd(Rand, 0).
-
-prime_odd(Rand, N) ->
- case is_prime(Rand, 50) of
- true ->
- Rand;
- false ->
- prime_odd(Rand+2, N+1)
- end.
-
-%% see http://en.wikipedia.org/wiki/Fermat_primality_test
-is_prime(_, 0) -> true;
-is_prime(Candidate, Test) ->
- CoPrime = odd_rand(10000, Candidate),
- Result = crypto:mod_pow(CoPrime, Candidate, Candidate) ,
- is_prime(CoPrime, crypto:bytes_to_integer(Result), Candidate, Test).
-
-is_prime(CoPrime, CoPrime, Candidate, Test) ->
- is_prime(Candidate, Test-1);
-is_prime(_,_,_,_) ->
- false.
-
-odd_rand(Size) ->
- Min = 1 bsl (Size*8-1),
- Max = (1 bsl (Size*8))-1,
- odd_rand(Min, Max).
-
-odd_rand(Min,Max) ->
- Rand = crypto:rand_uniform(Min,Max),
- case Rand rem 2 of
- 0 ->
- Rand + 1;
- _ ->
- Rand
- end.
-
-extended_gcd(A, B) ->
- case A rem B of
- 0 ->
- {0, 1};
- N ->
- {X, Y} = extended_gcd(B, N),
- {Y, X-Y*(A div B)}
- end.
-
-pem_to_der(File) ->
- {ok, PemBin} = file:read_file(File),
- public_key:pem_decode(PemBin).
-
-der_to_pem(File, Entries) ->
- PemBin = public_key:pem_encode(Entries),
- file:write_file(File, PemBin).
-
diff --git a/lib/ssl/test/make_certs.erl b/lib/ssl/test/make_certs.erl
index ecbacc1590..8fe7c54549 100644
--- a/lib/ssl/test/make_certs.erl
+++ b/lib/ssl/test/make_certs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@
%%
-module(make_certs).
--compile([export_all]).
+-compile([export_all, nowarn_export_all]).
%-export([all/1, all/2, rootCA/2, intermediateCA/3, endusers/3, enduser/3, revoke/3, gencrl/2, verify/3]).
@@ -34,14 +34,15 @@
ecc_certs = false,
issuing_distribution_point = false,
crl_port = 8000,
- openssl_cmd = "openssl"}).
+ openssl_cmd = "openssl",
+ hostname = "host.example.com"}).
default_config() ->
- #config{}.
+ #config{hostname = net_adm:localhost()}.
make_config(Args) ->
- make_config(Args, #config{}).
+ make_config(Args, default_config()).
make_config([], C) ->
C;
@@ -66,7 +67,9 @@ make_config([{ecc_certs, Bool}|T], C) when is_boolean(Bool) ->
make_config([{issuing_distribution_point, Bool}|T], C) when is_boolean(Bool) ->
make_config(T, C#config{issuing_distribution_point = Bool});
make_config([{openssl_cmd, Cmd}|T], C) when is_list(Cmd) ->
- make_config(T, C#config{openssl_cmd = Cmd}).
+ make_config(T, C#config{openssl_cmd = Cmd});
+make_config([{hostname, Hostname}|T], C) when is_list(Hostname) ->
+ make_config(T, C#config{hostname = Hostname}).
all([DataDir, PrivDir]) ->
@@ -384,8 +387,11 @@ req_cnf(Root, C) ->
"subjectKeyIdentifier = hash\n"
"subjectAltName = email:copy\n"].
-ca_cnf(Root, C = #config{issuing_distribution_point = true}) ->
- Hostname = net_adm:localhost(),
+ca_cnf(
+ Root,
+ #config{
+ issuing_distribution_point = true,
+ hostname = Hostname} = C) ->
["# Purpose: Configuration for CAs.\n"
"\n"
"ROOTDIR = " ++ Root ++ "\n"
@@ -464,8 +470,12 @@ ca_cnf(Root, C = #config{issuing_distribution_point = true}) ->
"crlDistributionPoints=@crl_section\n"
];
-ca_cnf(Root, C = #config{issuing_distribution_point = false}) ->
- Hostname = net_adm:localhost(),
+ca_cnf(
+ Root,
+ #config{
+ issuing_distribution_point = false,
+ hostname = Hostname
+ } = C) ->
["# Purpose: Configuration for CAs.\n"
"\n"
"ROOTDIR = " ++ Root ++ "\n"
diff --git a/lib/ssl/test/ssl.spec b/lib/ssl/test/ssl.spec
index 0ad94e22bc..cb54168d36 100644
--- a/lib/ssl/test/ssl.spec
+++ b/lib/ssl/test/ssl.spec
@@ -1,5 +1,4 @@
{suites,"../ssl_test",all}.
-{skip_cases, "../ssl_test",
- ssl_bench_SUITE, [setup_sequential, setup_concurrent, payload_simple,
- use_pem_cache, bypass_pem_cache],
- "Benchmarks run separately"}.
+{skip_suites, "../ssl_test",
+ [ssl_bench_SUITE, ssl_dist_bench_SUITE],
+ "Benchmarks run separately"}.
diff --git a/lib/ssl/test/ssl_ECC.erl b/lib/ssl/test/ssl_ECC.erl
new file mode 100644
index 0000000000..36d949f74b
--- /dev/null
+++ b/lib/ssl/test/ssl_ECC.erl
@@ -0,0 +1,172 @@
+
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssl_ECC).
+
+%% 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").
+
+%% Test diffrent certificate chain types, note that it is the servers
+%% chain that affect what cipher suit that will be choosen
+
+%% ECDH_RSA
+client_ecdh_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [keyAgreement]}]),
+ Suites = all_rsa_suites(Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdh_rsa, ecdh_rsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdh_rsa}, {ciphers, Suites} | proplists:delete(check_keyex, Config)]).
+client_ecdhe_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [keyAgreement]}]),
+ Suites = all_rsa_suites(Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdhe_rsa, ecdh_rsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdh_rsa}, {ciphers, Suites} | proplists:delete(check_keyex, Config)]).
+client_ecdhe_ecdsa_server_ecdh_rsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [keyAgreement]}]),
+ Suites = all_rsa_suites(Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdh_rsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdh_rsa}, {ciphers, Suites} | proplists:delete(check_keyex, Config)]).
+
+%% ECDHE_RSA
+client_ecdh_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdh_rsa, ecdhe_rsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdhe_rsa} | proplists:delete(check_keyex, Config)]).
+client_ecdhe_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdhe_rsa, ecdhe_rsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdhe_rsa} | proplists:delete(check_keyex, Config)]).
+client_ecdhe_ecdsa_server_ecdhe_rsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdh_ecdsa, ecdhe_rsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdhe_rsa} | proplists:delete(check_keyex, Config)]).
+
+%% ECDH_ECDSA
+client_ecdh_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [keyAgreement]}]),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain,
+ ssl_test_lib:default_cert_chain_conf()}],
+ ecdh_ecdsa, ecdh_ecdsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdh_ecdsa} | proplists:delete(check_keyex, Config)]).
+client_ecdhe_rsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [keyAgreement]}]),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain,
+ ssl_test_lib:default_cert_chain_conf()}],
+ ecdhe_rsa, ecdh_ecdsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdh_ecdsa} | proplists:delete(check_keyex, Config)]).
+
+client_ecdhe_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [keyAgreement]}]),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain,
+ ssl_test_lib:default_cert_chain_conf()}],
+ ecdhe_ecdsa, ecdh_ecdsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdh_ecdsa} | proplists:delete(check_keyex, Config)]).
+
+%% ECDHE_ECDSA
+client_ecdh_rsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdh_rsa, ecdhe_ecdsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdhe_ecdsa} | proplists:delete(check_keyex, Config)]).
+client_ecdh_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdh_ecdsa, ecdhe_ecdsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdhe_ecdsa} | proplists:delete(check_keyex, Config)]).
+client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdhe_ecdsa} | proplists:delete(check_keyex, Config)]).
+
+all_rsa_suites(Config) ->
+ Version = proplists:get_value(tls_version, Config),
+ All = ssl:cipher_suites(all, Version),
+ Default = ssl:cipher_suites(default, Version),
+ RSASuites = ssl:filter_cipher_suites(All,[{key_exchange, fun(rsa) -> true;(_) -> false end}]),
+ ssl:append_cipher_suites(RSASuites, Default).
diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl
index 0fbb0bb79a..c93f066825 100644
--- a/lib/ssl/test/ssl_ECC_SUITE.erl
+++ b/lib/ssl/test/ssl_ECC_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,55 +36,24 @@ all() ->
[
{group, 'tlsv1.2'},
{group, 'tlsv1.1'},
- {group, 'tlsv1'}
+ {group, 'tlsv1'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
].
groups() ->
[
- {'tlsv1.2', [], all_versions_groups()},
- {'tlsv1.1', [], all_versions_groups()},
- {'tlsv1', [], all_versions_groups()},
- {'erlang_server', [], openssl_key_cert_combinations()},
- %%{'erlang_client', [], openssl_key_cert_combinations()},
- {'erlang', [], key_cert_combinations() ++ misc()
- ++ ecc_negotiation()}
+ {'tlsv1.2', [], [mix_sign | test_cases()]},
+ {'tlsv1.1', [], test_cases()},
+ {'tlsv1', [], test_cases()},
+ {'dtlsv1.2', [], [mix_sign | test_cases()]},
+ {'dtlsv1', [], test_cases()}
].
-all_versions_groups ()->
- [{group, 'erlang_server'},
- %%{group, 'erlang_client'},
- {group, 'erlang'}
- ].
-
-
-openssl_key_cert_combinations() ->
- ECDH_RSA = case ssl_test_lib:openssl_filter("ECDH-RSA") of
- [] ->
- [];
- _ ->
- server_ecdh_rsa()
- end,
-
- ECDHE_RSA = case ssl_test_lib:openssl_filter("ECDHE-RSA") of
- [] ->
- [];
- _ ->
- server_ecdhe_rsa()
- end,
- ECDH_ECDSA = case ssl_test_lib:openssl_filter("ECDH-ECDSA") of
- [] ->
- [];
- _ ->
- server_ecdhe_ecdsa()
- end,
-
- ECDHE_ECDSA = case ssl_test_lib:openssl_filter("ECDHE-ECDSA") of
- [] ->
- [];
- _ ->
- server_ecdhe_ecdsa()
- end,
- ECDH_RSA ++ ECDHE_RSA ++ ECDH_ECDSA ++ ECDHE_ECDSA.
+test_cases()->
+ key_cert_combinations()
+ ++ misc()
+ ++ ecc_negotiation().
key_cert_combinations() ->
server_ecdh_rsa() ++
@@ -112,7 +81,6 @@ server_ecdhe_ecdsa() ->
client_ecdh_ecdsa_server_ecdhe_ecdsa,
client_ecdhe_ecdsa_server_ecdhe_ecdsa].
-
misc()->
[client_ecdsa_server_ecdsa_with_raw_key].
@@ -138,9 +106,14 @@ init_per_suite(Config0) ->
end_per_suite(Config0),
try crypto:start() of
ok ->
- Config0
+ case ssl_test_lib:sufficient_crypto_support(cipher_ec) of
+ true ->
+ Config0;
+ false ->
+ {skip, "Crypto does not support ECC"}
+ end
catch _:_ ->
- {skip, "Crypto did not start"}
+ {skip, "Crypto did not start"}
end.
end_per_suite(_Config) ->
@@ -148,56 +121,24 @@ end_per_suite(_Config) ->
application:stop(crypto).
%%--------------------------------------------------------------------
-init_per_group(erlang_client = Group, Config) ->
- case ssl_test_lib:is_sane_ecc(openssl) of
- true ->
- common_init_per_group(Group, [{server_type, openssl},
- {client_type, erlang} | Config]);
- false ->
- {skip, "Known ECC bug in openssl"}
- end;
-
-init_per_group(erlang_server = Group, Config) ->
- case ssl_test_lib:is_sane_ecc(openssl) of
- true ->
- common_init_per_group(Group, [{server_type, erlang},
- {client_type, openssl} | Config]);
- false ->
- {skip, "Known ECC bug in openssl"}
- end;
-
-init_per_group(erlang = Group, Config) ->
- case ssl_test_lib:sufficient_crypto_support(Group) of
- true ->
- common_init_per_group(Group, [{server_type, erlang},
- {client_type, erlang} | Config]);
- false ->
- {skip, "Crypto does not support ECC"}
- end;
-
-init_per_group(openssl = Group, Config) ->
- case ssl_test_lib:sufficient_crypto_support(Group) of
- true ->
- common_init_per_group(Group, [{server_type, openssl},
- {client_type, openssl} | Config]);
- false ->
- {skip, "Crypto does not support ECC"}
- end;
-
-init_per_group(Group, Config) ->
- common_init_per_group(Group, Config).
-
-common_init_per_group(GroupName, Config) ->
+init_per_group(GroupName, Config) ->
case ssl_test_lib:is_tls_version(GroupName) of
true ->
- Config0 = ssl_test_lib:init_tls_version(GroupName, Config),
- [{tls_version, GroupName} | Config0];
- _ ->
- openssl_check(GroupName, Config)
+ [{tls_version, GroupName},
+ {server_type, erlang},
+ {client_type, erlang} | ssl_test_lib:init_tls_version(GroupName, Config)];
+ _ ->
+ Config
end.
-end_per_group(_GroupName, Config) ->
- Config.
+end_per_group(GroupName, Config0) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ Config = ssl_test_lib:clean_tls_version(Config0),
+ proplists:delete(tls_version, Config);
+ false ->
+ Config0
+ end.
%%--------------------------------------------------------------------
@@ -205,7 +146,7 @@ init_per_testcase(TestCase, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:log("Ciphers: ~p~n ", [ ssl:cipher_suites()]),
end_per_testcase(TestCase, Config),
- ssl_test_lib:clean_start(),
+ ssl:start(),
ct:timetrap({seconds, 15}),
Config.
@@ -216,360 +157,248 @@ end_per_testcase(_TestCase, Config) ->
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
-
%% Test diffrent certificate chain types, note that it is the servers
%% chain that affect what cipher suit that will be choosen
%% ECDH_RSA
client_ecdh_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],
- ecdh_rsa, ecdh_rsa, Config),
- basic_test(COpts, SOpts, [{check_keyex, ecdh_rsa} | proplists:delete(check_keyex, Config)]).
-client_ecdhe_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdhe_rsa, ecdh_rsa, Config),
- basic_test(COpts, SOpts, [{check_keyex, ecdh_rsa} | proplists:delete(check_keyex, Config)]).
-client_ecdhe_ecdsa_server_ecdh_rsa(Config) when is_list(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdh_rsa, Config),
- basic_test(COpts, SOpts, [{check_keyex, ecdh_rsa} | proplists:delete(check_keyex, Config)]).
-
+ ssl_ECC:client_ecdh_rsa_server_ecdh_rsa(Config).
+client_ecdhe_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_rsa_server_ecdh_rsa(Config).
+client_ecdhe_ecdsa_server_ecdh_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_ecdsa_server_ecdh_rsa(Config).
%% ECDHE_RSA
client_ecdh_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdh_rsa, ecdhe_rsa, Config),
- basic_test(COpts, SOpts, [{check_keyex, ecdhe_rsa} | proplists:delete(check_keyex, Config)]).
-client_ecdhe_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdhe_rsa, ecdhe_rsa, Config),
- basic_test(COpts, SOpts, [{check_keyex, ecdhe_rsa} | proplists:delete(check_keyex, Config)]).
-client_ecdhe_ecdsa_server_ecdhe_rsa(Config) when is_list(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdh_ecdsa, ecdhe_rsa, Config),
- basic_test(COpts, SOpts, [{check_keyex, ecdhe_rsa} | proplists:delete(check_keyex, Config)]).
-
+ ssl_ECC:client_ecdh_rsa_server_ecdhe_rsa(Config).
+client_ecdhe_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_rsa_server_ecdhe_rsa(Config).
+client_ecdhe_ecdsa_server_ecdhe_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_rsa(Config).
%% ECDH_ECDSA
-client_ecdh_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_peer_opts,
- [{extensions, [{key_usage, [keyEncipherment]
- }]}]}],
- ecdh_ecdsa, ecdh_ecdsa, Config),
- basic_test(COpts, SOpts,
- [{check_keyex, ecdh_ecdsa} | proplists:delete(check_keyex, Config)]).
-client_ecdhe_rsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_peer_opts,
- [{extensions, [{key_usage, [keyEncipherment]
- }]}]}],
- ecdhe_rsa, ecdh_ecdsa, Config),
- basic_test(COpts, SOpts, [{check_keyex, ecdh_ecdsa} | proplists:delete(check_keyex, Config)]).
-
-client_ecdhe_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_peer_opts,
- [{extensions, [{key_usage, [keyEncipherment]
- }]}]}],
- ecdhe_ecdsa, ecdh_ecdsa, Config),
- basic_test(COpts, SOpts,
- [{check_keyex, ecdh_ecdsa} | proplists:delete(check_keyex, Config)]).
-
+client_ecdh_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdh_ecdsa_server_ecdh_ecdsa(Config).
+client_ecdhe_rsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_rsa_server_ecdh_ecdsa(Config).
+client_ecdhe_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_ecdsa_server_ecdh_ecdsa(Config).
%% ECDHE_ECDSA
-client_ecdh_rsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdh_rsa, ecdhe_ecdsa, Config),
- basic_test(COpts, SOpts, [{check_keyex, ecdhe_ecdsa} | proplists:delete(check_keyex, Config)]).
-client_ecdh_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdh_ecdsa, ecdhe_ecdsa, Config),
- basic_test(COpts, SOpts, [{check_keyex, ecdhe_ecdsa} | proplists:delete(check_keyex, Config)]).
-client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdhe_ecdsa, ecdhe_ecdsa, Config),
- basic_test(COpts, SOpts, [{check_keyex, ecdhe_ecdsa} | proplists:delete(check_keyex, Config)]).
+client_ecdh_rsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdh_rsa_server_ecdhe_ecdsa(Config).
+client_ecdh_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdh_ecdsa_server_ecdhe_ecdsa(Config).
+client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config).
client_ecdsa_server_ecdsa_with_raw_key(Config) when is_list(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}]
+ , ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ServerKeyFile = proplists:get_value(keyfile, SOpts),
{ok, PemBin} = file:read_file(ServerKeyFile),
PemEntries = public_key:pem_decode(PemBin),
- {'ECPrivateKey', Key, not_encrypted} = proplists:lookup('ECPrivateKey', PemEntries),
+ {'ECPrivateKey', Key, not_encrypted} = proplists:lookup('ECPrivateKey', PemEntries),
ServerKey = {'ECPrivateKey', Key},
SType = proplists:get_value(server_type, Config),
CType = proplists:get_value(client_type, Config),
- {Server, Port} = start_server_with_raw_key(SType,
- [{key, ServerKey} | proplists:delete(keyfile, SOpts)],
- Config),
- Client = start_client(CType, Port, COpts, Config),
- check_result(Server, SType, Client, CType),
- close(Server, Client).
+ {Server, Port} = ssl_test_lib:start_server_with_raw_key(SType,
+ [{key, ServerKey} | proplists:delete(keyfile, SOpts)],
+ Config),
+ Client = ssl_test_lib:start_client(CType, Port, COpts, Config),
+ ssl_test_lib:gen_check_result(Server, SType, Client, CType),
+ ssl_test_lib:stop(Server, Client).
ecc_default_order(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [],
- case supported_eccs([{eccs, [sect571r1]}]) of
- true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
+ case ssl_test_lib:supported_eccs([{eccs, [sect571r1]}]) of
+ true -> ssl_test_lib:ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
- end.
+ end.
ecc_default_order_custom_curves(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{eccs, [secp256r1, sect571r1]}],
- case supported_eccs(ECCOpts) of
- true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
ecc_client_order(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, false}],
- case supported_eccs([{eccs, [sect571r1]}]) of
- true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
+ case ssl_test_lib:supported_eccs([{eccs, [sect571r1]}]) of
+ true -> ssl_test_lib:ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
ecc_client_order_custom_curves(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, false}, {eccs, [secp256r1, sect571r1]}],
- case supported_eccs(ECCOpts) of
- true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
ecc_unknown_curve(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{eccs, ['123_fake_curve']}],
- ecc_test_error(COpts, SOpts, [], ECCOpts, Config).
+ ssl_test_lib:ecc_test_error(COpts, SOpts, [], ECCOpts, Config).
client_ecdh_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdh_rsa, ecdhe_ecdsa, Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdh_rsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
- case supported_eccs(ECCOpts) of
- true -> ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
- false -> {skip, "unsupported named curves"}
- end.
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
client_ecdh_rsa_server_ecdhe_rsa_server_custom(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdh_rsa, ecdhe_rsa, Config),
- ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
- case supported_eccs(ECCOpts) of
- true -> ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config);
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdh_rsa, ecdhe_rsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
client_ecdhe_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_rsa, ecdhe_ecdsa, Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_rsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
- case supported_eccs(ECCOpts) of
- true -> ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
client_ecdhe_rsa_server_ecdhe_rsa_server_custom(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdhe_rsa, ecdhe_rsa, Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_rsa, ecdhe_rsa, Config),
+
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
- case supported_eccs(ECCOpts) of
- true -> ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config);
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
- end.
+ end.
client_ecdhe_rsa_server_ecdh_rsa_server_custom(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_peer_opts,
- [{extensions, [{key_usage, [keyEncipherment]
- }]}]}], ecdhe_rsa, ecdh_rsa, Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ Ext = x509_test:extensions([{key_usage, [keyEncipherment]}]),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdhe_rsa, ecdh_rsa, Config),
+
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
- case supported_eccs(ECCOpts) of
- true -> ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config);
+ Expected = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(0))), %% The certificate curve
+
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(Expected, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
- case supported_eccs(ECCOpts) of
- true -> ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
client_ecdhe_ecdsa_server_ecdhe_rsa_server_custom(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_rsa, Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_rsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
- case supported_eccs(ECCOpts) of
- true -> ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config);
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
end.
client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{eccs, [secp256r1, sect571r1]}],
- case supported_eccs(ECCOpts) of
- true -> ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config);
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config);
false -> {skip, "unsupported named curves"}
end.
client_ecdhe_rsa_server_ecdhe_ecdsa_client_custom(Config) ->
- {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_rsa, ecdhe_ecdsa, Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_rsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{eccs, [secp256r1, sect571r1]}],
- case supported_eccs(ECCOpts) of
- true -> ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config);
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config);
false -> {skip, "unsupported named curves"}
end.
-%%--------------------------------------------------------------------
-%% Internal functions ------------------------------------------------
-%%--------------------------------------------------------------------
-basic_test(COpts, SOpts, Config) ->
- SType = proplists:get_value(server_type, Config),
- CType = proplists:get_value(client_type, Config),
- {Server, Port} = start_server(SType, SOpts, Config),
- Client = start_client(CType, Port, COpts, Config),
- check_result(Server, SType, Client, CType),
- close(Server, Client).
-
-
-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),
- ssl_test_lib:check_result(Server, ok, Client, ok),
- close(Server, Client).
-
-ecc_test_error(COpts, SOpts, CECCOpts, SECCOpts, Config) ->
- {Server, Port} = start_server_ecc_error(erlang, SOpts, SECCOpts, Config),
- Client = start_client_ecc_error(erlang, Port, COpts, CECCOpts, Config),
- Error = {error, {tls_alert, "insufficient security"}},
- ssl_test_lib:check_result(Server, Error, Client, Error).
-
-
-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 = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Exe = "openssl",
- Args = ["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"],
-
- OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
- true = port_command(OpenSslPort, "Hello world"),
- OpenSslPort;
-
-start_client(erlang, Port, ClientOpts, Config) ->
- {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
- KeyEx = proplists:get_value(check_keyex, Config, false),
- ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, check_key_exchange_send_active, [KeyEx]}},
- {options, [{verify, verify_peer} | ClientOpts]}]).
-
-
-start_client_ecc(erlang, Port, ClientOpts, Expect, ECCOpts, Config) ->
- {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
- ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, check_ecc, [client, Expect]}},
- {options,
- ECCOpts ++
- [{verify, verify_peer} | ClientOpts]}]).
-
-start_client_ecc_error(erlang, Port, ClientOpts, ECCOpts, Config) ->
- {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
- ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {options,
- ECCOpts ++
- [{verify, verify_peer} | ClientOpts]}]).
-
-
-start_server(openssl, ServerOpts, _Config) ->
- Cert = proplists:get_value(certfile, ServerOpts),
- Key = proplists:get_value(keyfile, ServerOpts),
- CA = proplists:get_value(cacertfile, ServerOpts),
- Port = ssl_test_lib:inet_port(node()),
- Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Exe = "openssl",
- Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version),
- "-verify", "2", "-cert", Cert, "-CAfile", CA,
- "-key", Key, "-msg", "-debug"],
- OpenSslPort = ssl_test_lib: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),
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib,
- check_key_exchange_send_active,
- [KeyEx]}},
- {options, [{verify, verify_peer} | ServerOpts]}]),
- {Server, ssl_test_lib:inet_port(Server)}.
-
-start_server_with_raw_key(erlang, ServerOpts, Config) ->
- {_, ServerNode, _} = 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,
- [{verify, verify_peer} | ServerOpts]}]),
- {Server, ssl_test_lib:inet_port(Server)}.
-
-start_server_ecc(erlang, ServerOpts, Expect, ECCOpts, Config) ->
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, check_ecc, [server, Expect]}},
- {options,
- ECCOpts ++
- [{verify, verify_peer} | ServerOpts]}]),
- {Server, ssl_test_lib:inet_port(Server)}.
-
-start_server_ecc_error(erlang, ServerOpts, ECCOpts, Config) ->
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
- Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {options,
- ECCOpts ++
- [{verify, verify_peer} | ServerOpts]}]),
- {Server, ssl_test_lib:inet_port(Server)}.
-
-check_result(Server, erlang, Client, erlang) ->
- ssl_test_lib:check_result(Server, ok, Client, ok);
-check_result(Server, erlang, _, _) ->
- ssl_test_lib:check_result(Server, ok);
-check_result(_, _, Client, erlang) ->
- ssl_test_lib:check_result(Client, ok);
-check_result(_,openssl, _, openssl) ->
- ok.
-
-openssl_check(erlang, Config) ->
- Config;
-openssl_check(_, Config) ->
- TLSVersion = proplists:get_value(tls_version, Config),
- case ssl_test_lib:check_sane_openssl_version(TLSVersion) of
- true ->
- Config;
- false ->
- {skip, "TLS version not supported by openssl"}
- end.
-
-close(Port1, Port2) when is_port(Port1), is_port(Port2) ->
- ssl_test_lib:close_port(Port1),
- ssl_test_lib:close_port(Port2);
-close(Port, Pid) when is_port(Port) ->
- ssl_test_lib:close_port(Port),
- ssl_test_lib:close(Pid);
-close(Pid, Port) when is_port(Port) ->
- ssl_test_lib:close_port(Port),
- ssl_test_lib:close(Pid);
-close(Client, Server) ->
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-supported_eccs(Opts) ->
- ToCheck = proplists:get_value(eccs, Opts, []),
- Supported = ssl:eccs(),
- lists:all(fun(Curve) -> lists:member(Curve, Supported) end, ToCheck).
-
-check_ecc(SSL, Role, Expect) ->
- {ok, Data} = ssl:connection_information(SSL),
- case lists:keyfind(ecc, 1, Data) of
- {ecc, {named_curve, Expect}} -> ok;
- false when Expect =:= undefined -> ok;
- Other -> {error, Role, Expect, Other}
- end.
-
+mix_sign(Config) ->
+ {COpts0, SOpts0} = ssl_test_lib:make_mix_cert(Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECDHE_ECDSA =
+ ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'),
+ [{key_exchange, fun(ecdhe_ecdsa) -> true; (_) -> false end}]),
+ ssl_test_lib:basic_test(COpts, [{ciphers, ECDHE_ECDSA} | SOpts], Config).
diff --git a/lib/ssl/test/ssl_ECC_openssl_SUITE.erl b/lib/ssl/test/ssl_ECC_openssl_SUITE.erl
new file mode 100644
index 0000000000..81a7dfd2da
--- /dev/null
+++ b/lib/ssl/test/ssl_ECC_openssl_SUITE.erl
@@ -0,0 +1,218 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssl_ECC_openssl_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() ->
+ case test_cases() of
+ [_|_] ->
+ all_groups();
+ [] ->
+ [skip]
+ end.
+
+all_groups() ->
+ case ssl_test_lib:openssl_sane_dtls() of
+ true ->
+ [{group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}];
+ false ->
+ [{group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'}]
+ end.
+
+groups() ->
+ case ssl_test_lib:openssl_sane_dtls() of
+ true ->
+ [{'tlsv1.2', [], [mix_sign | test_cases()]},
+ {'tlsv1.1', [], test_cases()},
+ {'tlsv1', [], test_cases()},
+ {'dtlsv1.2', [], [mix_sign | test_cases()]},
+ {'dtlsv1', [], test_cases()}];
+ false ->
+ [{'tlsv1.2', [], [mix_sign | test_cases()]},
+ {'tlsv1.1', [], test_cases()},
+ {'tlsv1', [], test_cases()}]
+ end.
+
+test_cases()->
+ cert_combinations().
+
+cert_combinations() ->
+ lists:append(lists:map(fun({Name, Suites}) ->
+ case ssl_test_lib:openssl_filter(Name) of
+ [] ->
+ [];
+ [_|_] ->
+ Suites
+ end
+ end, [{"ECDH-ECDSA", server_ecdh_ecdsa()},
+ {"ECDH-RSA", server_ecdh_rsa()},
+ {"ECDHE-RSA", server_ecdhe_rsa()},
+ {"ECDHE-ECDSA", server_ecdhe_ecdsa()}
+ ])).
+server_ecdh_rsa() ->
+ [client_ecdh_rsa_server_ecdh_rsa,
+ client_ecdhe_rsa_server_ecdh_rsa,
+ client_ecdhe_ecdsa_server_ecdh_rsa].
+
+server_ecdhe_rsa() ->
+ [client_ecdh_rsa_server_ecdhe_rsa,
+ client_ecdhe_rsa_server_ecdhe_rsa,
+ client_ecdhe_ecdsa_server_ecdhe_rsa].
+
+server_ecdh_ecdsa() ->
+ [client_ecdh_ecdsa_server_ecdh_ecdsa,
+ client_ecdhe_rsa_server_ecdh_ecdsa,
+ client_ecdhe_ecdsa_server_ecdh_ecdsa].
+
+server_ecdhe_ecdsa() ->
+ [client_ecdh_rsa_server_ecdhe_ecdsa,
+ client_ecdh_ecdsa_server_ecdhe_ecdsa,
+ client_ecdhe_ecdsa_server_ecdhe_ecdsa].
+
+%%--------------------------------------------------------------------
+init_per_suite(Config0) ->
+ end_per_suite(Config0),
+ try crypto:start() of
+ ok ->
+ case ssl_test_lib:sufficient_crypto_support(cipher_ec) of
+ true ->
+ Config0;
+ false ->
+ {skip, "Openssl does not support ECC"}
+ end
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ application:stop(ssl),
+ application:stop(crypto).
+
+%%--------------------------------------------------------------------
+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 ->
+ [{tls_version, GroupName},
+ {server_type, erlang},
+ {client_type, openssl} | ssl_test_lib:init_tls_version(GroupName, Config)];
+ false ->
+ {skip, openssl_does_not_support_version}
+ end;
+ _ ->
+ Config
+ end.
+
+end_per_group(GroupName, Config0) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ Config = ssl_test_lib:clean_tls_version(Config0),
+ proplists:delete(tls_version, Config);
+ false ->
+ Config0
+ end.
+
+%%--------------------------------------------------------------------
+init_per_testcase(skip, Config) ->
+ Config;
+init_per_testcase(TestCase, Config) ->
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ Version = proplists:get_value(tls_version, Config),
+ ct:log("Ciphers: ~p~n ", [ssl:cipher_suites(default, Version)]),
+ end_per_testcase(TestCase, Config),
+ ssl:start(),
+ ct:timetrap({seconds, 30}),
+ Config.
+
+end_per_testcase(_TestCase, Config) ->
+ application:stop(ssl),
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+skip(Config) when is_list(Config) ->
+ {skip, openssl_does_not_support_ECC}.
+
+%% Test diffrent certificate chain types, note that it is the servers
+%% chain that affect what cipher suit that will be choosen
+
+%% ECDH_RSA
+client_ecdh_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdh_rsa_server_ecdh_rsa(Config).
+client_ecdhe_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_rsa_server_ecdh_rsa(Config).
+client_ecdhe_ecdsa_server_ecdh_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_ecdsa_server_ecdh_rsa(Config).
+%% ECDHE_RSA
+client_ecdh_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdh_rsa_server_ecdhe_rsa(Config).
+client_ecdhe_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_rsa_server_ecdhe_rsa(Config).
+client_ecdhe_ecdsa_server_ecdhe_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_rsa(Config).
+%% ECDH_ECDSA
+client_ecdh_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdh_ecdsa_server_ecdh_ecdsa(Config).
+client_ecdhe_rsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_rsa_server_ecdh_ecdsa(Config).
+client_ecdhe_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_ecdsa_server_ecdh_ecdsa(Config).
+%% ECDHE_ECDSA
+client_ecdh_rsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdh_rsa_server_ecdhe_ecdsa(Config).
+client_ecdh_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdh_ecdsa_server_ecdhe_ecdsa(Config).
+client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config).
+
+mix_sign(Config) ->
+ {COpts0, SOpts0} = ssl_test_lib:make_mix_cert(Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECDHE_ECDSA =
+ ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'),
+ [{key_exchange, fun(ecdhe_ecdsa) -> true; (_) -> false end}]),
+ ssl_test_lib:basic_test(COpts, [{ciphers, ECDHE_ECDSA} | SOpts], [{client_type, erlang},
+ {server_type, openssl} | Config]).
+
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_alpn_handshake_SUITE.erl b/lib/ssl/test/ssl_alpn_handshake_SUITE.erl
index 158b3524ac..04c4b257d9 100644
--- a/lib/ssl/test/ssl_alpn_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_alpn_handshake_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,14 +35,19 @@ all() ->
[{group, 'tlsv1.2'},
{group, 'tlsv1.1'},
{group, 'tlsv1'},
- {group, 'sslv3'}].
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
+ ].
groups() ->
[
{'tlsv1.2', [], alpn_tests()},
{'tlsv1.1', [], alpn_tests()},
{'tlsv1', [], alpn_tests()},
- {'sslv3', [], alpn_not_supported()}
+ {'sslv3', [], alpn_not_supported()},
+ {'dtlsv1.2', [], alpn_tests() -- [client_renegotiate]},
+ {'dtlsv1', [], alpn_tests() -- [client_renegotiate]}
].
alpn_tests() ->
@@ -67,13 +72,12 @@ alpn_not_supported() ->
alpn_not_supported_server
].
-init_per_suite(Config) ->
+init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
ssl_test_lib:clean_start(),
- {ok, _} = make_certs:all(proplists:get_value(data_dir, Config),
- proplists:get_value(priv_dir, Config)),
+ Config = ssl_test_lib:make_rsa_cert(Config0),
ssl_test_lib:cert_options(Config)
catch _:_ ->
{skip, "Crypto did not start"}
@@ -90,8 +94,7 @@ init_per_group(GroupName, Config) ->
true ->
case ssl_test_lib:sufficient_crypto_support(GroupName) of
true ->
- ssl_test_lib:init_tls_version(GroupName, Config),
- Config;
+ ssl_test_lib:init_tls_version(GroupName, Config);
false ->
{skip, "Missing crypto support"}
end;
@@ -100,8 +103,14 @@ init_per_group(GroupName, Config) ->
Config
end.
-end_per_group(_GroupName, Config) ->
- Config.
+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),
@@ -116,26 +125,29 @@ end_per_testcase(_TestCase, Config) ->
%%--------------------------------------------------------------------
empty_protocols_are_not_allowed(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
{error, {options, {alpn_preferred_protocols, {invalid_protocol, <<>>}}}}
= (catch ssl:listen(9443,
- [{alpn_preferred_protocols, [<<"foo/1">>, <<"">>]}])),
+ [{alpn_preferred_protocols, [<<"foo/1">>, <<"">>]}| ServerOpts])),
{error, {options, {alpn_advertised_protocols, {invalid_protocol, <<>>}}}}
= (catch ssl:connect({127,0,0,1}, 9443,
- [{alpn_advertised_protocols, [<<"foo/1">>, <<"">>]}])).
+ [{alpn_advertised_protocols, [<<"foo/1">>, <<"">>]} | ServerOpts])).
%--------------------------------------------------------------------------------
protocols_must_be_a_binary_list(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
Option1 = {alpn_preferred_protocols, hello},
- {error, {options, Option1}} = (catch ssl:listen(9443, [Option1])),
+ {error, {options, Option1}} = (catch ssl:listen(9443, [Option1 | ServerOpts])),
Option2 = {alpn_preferred_protocols, [<<"foo/1">>, hello]},
{error, {options, {alpn_preferred_protocols, {invalid_protocol, hello}}}}
- = (catch ssl:listen(9443, [Option2])),
+ = (catch ssl:listen(9443, [Option2 | ServerOpts])),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
Option3 = {alpn_advertised_protocols, hello},
- {error, {options, Option3}} = (catch ssl:connect({127,0,0,1}, 9443, [Option3])),
+ {error, {options, Option3}} = (catch ssl:connect({127,0,0,1}, 9443, [Option3 | ClientOpts])),
Option4 = {alpn_advertised_protocols, [<<"foo/1">>, hello]},
{error, {options, {alpn_advertised_protocols, {invalid_protocol, hello}}}}
- = (catch ssl:connect({127,0,0,1}, 9443, [Option4])).
+ = (catch ssl:connect({127,0,0,1}, 9443, [Option4 | ClientOpts])).
%--------------------------------------------------------------------------------
@@ -143,7 +155,7 @@ empty_client(Config) when is_list(Config) ->
run_failing_handshake(Config,
[{alpn_advertised_protocols, []}],
[{alpn_preferred_protocols, [<<"spdy/2">>, <<"spdy/3">>, <<"http/2">>]}],
- {connect_failed,{tls_alert,"no application protocol"}}).
+ {error,{tls_alert,"no application protocol"}}).
%--------------------------------------------------------------------------------
@@ -151,7 +163,7 @@ empty_server(Config) when is_list(Config) ->
run_failing_handshake(Config,
[{alpn_advertised_protocols, [<<"http/1.0">>, <<"http/1.1">>]}],
[{alpn_preferred_protocols, []}],
- {connect_failed,{tls_alert,"no application protocol"}}).
+ {error,{tls_alert,"no application protocol"}}).
%--------------------------------------------------------------------------------
@@ -159,7 +171,7 @@ empty_client_empty_server(Config) when is_list(Config) ->
run_failing_handshake(Config,
[{alpn_advertised_protocols, []}],
[{alpn_preferred_protocols, []}],
- {connect_failed,{tls_alert,"no application protocol"}}).
+ {error,{tls_alert,"no application protocol"}}).
%--------------------------------------------------------------------------------
@@ -167,7 +179,7 @@ no_matching_protocol(Config) when is_list(Config) ->
run_failing_handshake(Config,
[{alpn_advertised_protocols, [<<"http/1.0">>, <<"http/1.1">>]}],
[{alpn_preferred_protocols, [<<"spdy/2">>, <<"spdy/3">>, <<"http/2">>]}],
- {connect_failed,{tls_alert,"no application protocol"}}).
+ {error,{tls_alert,"no application protocol"}}).
%--------------------------------------------------------------------------------
@@ -226,9 +238,9 @@ client_alpn_and_server_alpn_npn(Config) when is_list(Config) ->
client_renegotiate(Config) when is_list(Config) ->
Data = "hello world",
- ClientOpts0 = proplists:get_value(client_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
ClientOpts = [{alpn_advertised_protocols, [<<"http/1.0">>]}] ++ ClientOpts0,
- ServerOpts0 = proplists:get_value(server_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
ServerOpts = [{alpn_preferred_protocols, [<<"spdy/2">>, <<"http/1.1">>, <<"http/1.0">>]}] ++ ServerOpts0,
ExpectedProtocol = {ok, <<"http/1.0">>},
@@ -250,9 +262,9 @@ client_renegotiate(Config) when is_list(Config) ->
%--------------------------------------------------------------------------------
session_reused(Config) when is_list(Config)->
- ClientOpts0 = proplists:get_value(client_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
ClientOpts = [{alpn_advertised_protocols, [<<"http/1.0">>]}] ++ ClientOpts0,
- ServerOpts0 = proplists:get_value(server_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
ServerOpts = [{alpn_preferred_protocols, [<<"spdy/2">>, <<"http/1.1">>, <<"http/1.0">>]}] ++ ServerOpts0,
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -299,7 +311,7 @@ session_reused(Config) when is_list(Config)->
%--------------------------------------------------------------------------------
alpn_not_supported_client(Config) when is_list(Config) ->
- ClientOpts0 = proplists:get_value(client_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
PrefProtocols = {client_preferred_next_protocols,
{client, [<<"http/1.0">>], <<"http/1.1">>}},
ClientOpts = [PrefProtocols] ++ ClientOpts0,
@@ -315,7 +327,7 @@ alpn_not_supported_client(Config) when is_list(Config) ->
%--------------------------------------------------------------------------------
alpn_not_supported_server(Config) when is_list(Config)->
- ServerOpts0 = proplists:get_value(server_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
AdvProtocols = {next_protocols_advertised, [<<"spdy/2">>, <<"http/1.1">>, <<"http/1.0">>]},
ServerOpts = [AdvProtocols] ++ ServerOpts0,
@@ -326,29 +338,30 @@ alpn_not_supported_server(Config) when is_list(Config)->
%%--------------------------------------------------------------------
run_failing_handshake(Config, ClientExtraOpts, ServerExtraOpts, ExpectedResult) ->
- ClientOpts = ClientExtraOpts ++ proplists:get_value(client_opts, Config),
- ServerOpts = ServerExtraOpts ++ proplists:get_value(server_opts, Config),
+ ClientOpts = ClientExtraOpts ++ ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ServerExtraOpts ++ ssl_test_lib:ssl_options(server_rsa_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {?MODULE, placeholder, []}},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
- ExpectedResult
- = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, placeholder, []}},
- {options, ClientOpts}]).
+ Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, placeholder, []}},
+ {options, ClientOpts}]),
+ ssl_test_lib:check_result(Server, ExpectedResult,
+ Client, ExpectedResult).
run_handshake(Config, ClientExtraOpts, ServerExtraOpts, ExpectedProtocol) ->
Data = "hello world",
- ClientOpts0 = proplists:get_value(client_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
ClientOpts = ClientExtraOpts ++ ClientOpts0,
- ServerOpts0 = proplists:get_value(server_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
ServerOpts = ServerExtraOpts ++ ServerOpts0,
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 407152aa75..4585ea7306 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -53,8 +53,7 @@ all() ->
{group, options_tls},
{group, session},
{group, 'dtlsv1.2'},
- %% {group, 'dtlsv1'}, Breaks dtls in cert_verify_SUITE enable later when
- %% problem is identified and fixed
+ {group, 'dtlsv1'},
{group, 'tlsv1.2'},
{group, 'tlsv1.1'},
{group, 'tlsv1'},
@@ -84,13 +83,14 @@ groups() ->
].
tls_versions_groups ()->
- [{group, renegotiate}, %% Should be in all_versions_groups not fixed for DTLS yet
+ [
{group, api_tls},
{group, tls_ciphers},
{group, error_handling_tests_tls}].
all_versions_groups ()->
[{group, api},
+ {group, renegotiate},
{group, ciphers},
{group, ciphers_ec},
{group, error_handling_tests}].
@@ -108,7 +108,8 @@ basic_tests() ->
clear_pem_cache,
defaults,
fallback,
- cipher_format
+ cipher_format,
+ suite_to_str
].
basic_tests_tls() ->
@@ -146,8 +147,7 @@ options_tests_tls() ->
tls_tcp_reuseaddr].
api_tests() ->
- [connection_info,
- secret_connection_info,
+ [secret_connection_info,
connection_information,
peercert,
peercert_with_client_cert,
@@ -163,7 +163,11 @@ api_tests() ->
server_name_indication_option,
accept_pool,
prf,
- socket_options
+ socket_options,
+ cipher_suites,
+ handshake_continue,
+ hello_client_cancel,
+ hello_server_cancel
].
api_tests_tls() ->
@@ -193,6 +197,7 @@ 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,
@@ -207,12 +212,14 @@ tls_cipher_tests() ->
rc4_ecdsa_cipher_suites].
cipher_tests() ->
- [cipher_suites,
+ [old_cipher_suites,
cipher_suites_mix,
ciphers_rsa_signed_certs,
ciphers_rsa_signed_certs_openssl_names,
ciphers_dsa_signed_certs,
ciphers_dsa_signed_certs_openssl_names,
+ chacha_rsa_cipher_suites,
+ chacha_ecdsa_cipher_suites,
anonymous_cipher_suites,
psk_cipher_suites,
psk_with_hint_cipher_suites,
@@ -235,7 +242,9 @@ error_handling_tests()->
[close_transport_accept,
recv_active,
recv_active_once,
- recv_error_handling
+ recv_error_handling,
+ call_in_error_state,
+ close_in_error_state
].
error_handling_tests_tls()->
@@ -266,7 +275,8 @@ init_per_suite(Config0) ->
proplists:get_value(priv_dir, Config0)),
Config1 = ssl_test_lib:make_dsa_cert(Config0),
Config2 = ssl_test_lib:make_ecdsa_cert(Config1),
- Config = ssl_test_lib:make_ecdh_rsa_cert(Config2),
+ Config3 = ssl_test_lib:make_rsa_cert(Config2),
+ Config = ssl_test_lib:make_ecdh_rsa_cert(Config3),
ssl_test_lib:cert_options(Config)
catch _:_ ->
{skip, "Crypto did not start"}
@@ -277,7 +287,17 @@ 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);
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);
@@ -291,8 +311,13 @@ init_per_group(GroupName, Config) ->
end
end.
-end_per_group(_GroupName, Config) ->
- Config.
+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;
@@ -360,6 +385,8 @@ init_per_testcase(TestCase, Config) when TestCase == psk_cipher_suites;
TestCase == psk_with_hint_cipher_suites;
TestCase == ciphers_rsa_signed_certs;
TestCase == ciphers_rsa_signed_certs_openssl_names;
+ TestCase == ciphers_ecdh_rsa_signed_certs_openssl_names;
+ TestCase == ciphers_ecdh_rsa_signed_certs;
TestCase == ciphers_dsa_signed_certs;
TestCase == ciphers_dsa_signed_certs_openssl_names;
TestCase == anonymous_cipher_suites;
@@ -368,7 +395,12 @@ init_per_testcase(TestCase, Config) when TestCase == psk_cipher_suites;
TestCase == anonymous_cipher_suites;
TestCase == psk_anon_cipher_suites;
TestCase == psk_anon_with_hint_cipher_suites;
- TestCase == versions_option,
+ TestCase == srp_cipher_suites;
+ TestCase == srp_anon_cipher_suites;
+ TestCase == srp_dsa_cipher_suites;
+ TestCase == des_rsa_cipher_suites;
+ TestCase == des_ecdh_rsa_cipher_suites;
+ TestCase == versions_option;
TestCase == tls_tcp_connect_big ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:timetrap({seconds, 60}),
@@ -386,24 +418,35 @@ init_per_testcase(reuse_session, Config) ->
init_per_testcase(rizzo, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
- ct:timetrap({seconds, 40}),
+ 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, 40}),
+ 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, 40}),
+ 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, 40}),
+ 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}),
@@ -434,6 +477,8 @@ init_per_testcase(TestCase, Config) when TestCase == tls_ssl_accept_timeout;
TestCase == tls_client_closes_socket;
TestCase == tls_closed_in_active_once;
TestCase == tls_downgrade ->
+ ssl:stop(),
+ ssl:start(),
ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:timetrap({seconds, 15}),
Config;
@@ -511,7 +556,7 @@ alerts() ->
[{doc, "Test ssl_alert:alert_txt/1"}].
alerts(Config) when is_list(Config) ->
Descriptions = [?CLOSE_NOTIFY, ?UNEXPECTED_MESSAGE, ?BAD_RECORD_MAC,
- ?DECRYPTION_FAILED, ?RECORD_OVERFLOW, ?DECOMPRESSION_FAILURE,
+ ?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,
@@ -568,7 +613,16 @@ new_options_in_accept(Config) when is_list(Config) ->
[_ , _ | ServerSslOpts] = ssl_test_lib:ssl_options(server_opts, Config), %% Remove non ssl opts
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Version = ssl_test_lib:protocol_options(Config, [{tls, sslv3}, {dtls, dtlsv1}]),
- Cipher = ssl_test_lib:protocol_options(Config, [{tls, {rsa,rc4_128,sha}}, {dtls, {rsa,aes_128_cbc,sha}}]),
+ Cipher = ssl_test_lib:protocol_options(Config, [{tls, #{key_exchange =>rsa,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf
+ }},
+ {dtls, #{key_exchange =>rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf
+ }}]),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{ssl_extra_opts, [{versions, [Version]},
@@ -593,6 +647,89 @@ new_options_in_accept(Config) when is_list(Config) ->
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_verification_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {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).
+
+%%--------------------------------------------------------------------
+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}]),
+ receive
+ {Server, {error, {tls_alert, "user canceled"}}} ->
+ ok;
+ {Server, {error, closed}} ->
+ ct:pal("Did not receive the ALERT"),
+ ok
+ end.
+
+%%--------------------------------------------------------------------
+hello_server_cancel() ->
+ [{doc, "Test API function ssl:handshake_cancel/1 on the server side"}].
+hello_server_cancel(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
+ {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."}].
@@ -614,41 +751,6 @@ prf(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
-connection_info() ->
- [{doc,"Test the API function ssl:connection_information/2"}].
-connection_info(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
- {options, ServerOpts}]),
-
- Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
- {options,
- [{ciphers,[{rsa, aes_128_cbc, sha}]} |
- ClientOpts]}]),
-
- ct:log("Testcase ~p, Client ~p Server ~p ~n",
- [self(), Client, Server]),
-
- Version = ssl_test_lib:protocol_version(Config),
-
- ServerMsg = ClientMsg = {ok, {Version, {rsa, aes_128_cbc, sha}}},
-
- ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-
secret_connection_info() ->
[{doc,"Test the API function ssl:connection_information/2"}].
secret_connection_info(Config) when is_list(Config) ->
@@ -670,8 +772,6 @@ secret_connection_info(Config) when is_list(Config) ->
ct:log("Testcase ~p, Client ~p Server ~p ~n",
[self(), Client, Server]),
-
- Version = ssl_test_lib:protocol_version(Config),
ssl_test_lib:check_result(Server, true, Client, true),
@@ -928,7 +1028,7 @@ controller_dies(Config) when is_list(Config) ->
{mfa, {?MODULE,
controller_dies_result, [self(),
ClientMsg]}},
- {options, [{reuseaddr,true}|ClientOpts]}]),
+ {options, ClientOpts}]),
ct:sleep(?SLEEP), %% so that they are connected
exit(Server, killed),
@@ -953,7 +1053,7 @@ tls_client_closes_socket(Config) when is_list(Config) ->
Connect = fun() ->
{ok, _Socket} = rpc:call(ClientNode, gen_tcp, connect,
- [Hostname, Port, TcpOpts]),
+ [Hostname, Port, [binary]]),
%% Make sure that ssl_accept is called before
%% client process ends and closes socket.
ct:sleep(?SLEEP)
@@ -1083,23 +1183,48 @@ fallback(Config) when is_list(Config) ->
Port = ssl_test_lib:inet_port(Server),
- Client =
- ssl_test_lib:start_client_error([{node, ClientNode},
- {port, Port}, {host, Hostname},
- {from, self()}, {options,
- [{fallback, true},
- {versions, ['tlsv1']}
- | ClientOpts]}]),
+ Client =
+ ssl_test_lib:start_client_error([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {from, self()}, {options,
+ [{fallback, true},
+ {versions, ['tlsv1']}
+ | ClientOpts]}]),
- ssl_test_lib:check_result(Server, {error,{tls_alert,"inappropriate fallback"}},
- Client, {error,{tls_alert,"inappropriate fallback"}}).
+ ssl_test_lib:check_result(Server, {error,{tls_alert,"inappropriate fallback"}},
+ Client, {error,{tls_alert,"inappropriate fallback"}}).
%%--------------------------------------------------------------------
cipher_format() ->
- [{doc, "Test that cipher conversion from tuples to binarys works"}].
+ [{doc, "Test that cipher conversion from maps | tuples | stings to binarys works"}].
cipher_format(Config) when is_list(Config) ->
- {ok, Socket} = ssl:listen(0, [{ciphers, ssl:cipher_suites()}]),
- ssl:close(Socket).
+ {ok, Socket0} = ssl:listen(0, [{ciphers, ssl:cipher_suites(default, 'tlsv1.2')}]),
+ ssl:close(Socket0),
+ %% Legacy
+ {ok, Socket1} = ssl:listen(0, [{ciphers, ssl:cipher_suites()}]),
+ ssl:close(Socket1),
+ {ok, Socket2} = ssl:listen(0, [{ciphers, ssl:cipher_suites(openssl)}]),
+ 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}).
%%--------------------------------------------------------------------
@@ -1251,22 +1376,83 @@ sockname_result(S) ->
ssl:sockname(S).
%%--------------------------------------------------------------------
+
cipher_suites() ->
- [{doc,"Test API function cipher_suites/0"}].
+ [{doc,"Test API function cipher_suites/2, filter_cipher_suites/2"
+ " and prepend|append_cipher_suites/2"}].
cipher_suites(Config) when is_list(Config) ->
- MandatoryCipherSuite = {rsa,'3des_ede_cbc',sha},
+ MandatoryCipherSuiteTLS1_0TLS1_1 = #{key_exchange => rsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf},
+ MandatoryCipherSuiteTLS1_0TLS1_2 = #{key_exchange =>rsa,
+ cipher => 'aes_128_cbc',
+ mac => sha,
+ prf => default_prf},
+ Version = ssl_test_lib:protocol_version(Config),
+ All = [_|_] = ssl:cipher_suites(all, Version),
+ Default = [_|_] = ssl:cipher_suites(default, Version),
+ Anonymous = [_|_] = ssl:cipher_suites(anonymous, Version),
+ true = length(Default) < length(All),
+ Filters = [{key_exchange,
+ fun(dhe_rsa) ->
+ true;
+ (_) ->
+ false
+ end
+ },
+ {cipher,
+ fun(aes_256_cbc) ->
+ true;
+ (_) ->
+ false
+ end
+ },
+ {mac,
+ fun(sha) ->
+ true;
+ (_) ->
+ false
+ end
+ }
+ ],
+ Cipher = #{cipher => aes_256_cbc,
+ key_exchange => dhe_rsa,
+ mac => sha,
+ prf => default_prf},
+ [Cipher] = ssl:filter_cipher_suites(All, Filters),
+ [Cipher | Rest0] = ssl:prepend_cipher_suites([Cipher], Default),
+ [Cipher | Rest0] = ssl:prepend_cipher_suites(Filters, Default),
+ true = lists:member(Cipher, Default),
+ false = lists:member(Cipher, Rest0),
+ [Cipher | Rest1] = lists:reverse(ssl:append_cipher_suites([Cipher], Default)),
+ [Cipher | Rest1] = lists:reverse(ssl:append_cipher_suites(Filters, Default)),
+ true = lists:member(Cipher, Default),
+ false = lists:member(Cipher, Rest1),
+ [] = lists:dropwhile(fun(X) -> not lists:member(X, Default) end, Anonymous),
+ [] = lists:dropwhile(fun(X) -> not lists:member(X, All) end, Anonymous),
+ true = lists:member(MandatoryCipherSuiteTLS1_0TLS1_1, All),
+ true = lists:member(MandatoryCipherSuiteTLS1_0TLS1_2, All).
+
+%%--------------------------------------------------------------------
+
+old_cipher_suites() ->
+ [{doc,"Test API function cipher_suites/0"}].
+
+old_cipher_suites(Config) when is_list(Config) ->
+ MandatoryCipherSuite = {rsa, '3des_ede_cbc', sha},
[_|_] = Suites = ssl:cipher_suites(),
- true = lists:member(MandatoryCipherSuite, Suites),
Suites = ssl:cipher_suites(erlang),
- [_|_] =ssl:cipher_suites(openssl).
+ [_|_] = ssl:cipher_suites(openssl),
+ true = lists:member(MandatoryCipherSuite, ssl:cipher_suites(all)).
%%--------------------------------------------------------------------
cipher_suites_mix() ->
[{doc,"Test to have old and new cipher suites at the same time"}].
cipher_suites_mix(Config) when is_list(Config) ->
- CipherSuites = [{ecdh_rsa,aes_128_cbc,sha256,sha256}, {rsa,aes_128_cbc,sha}],
+ CipherSuites = [{dhe_rsa,aes_128_cbc,sha256,sha256}, {dhe_rsa,aes_128_cbc,sha}],
ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
@@ -1711,7 +1897,7 @@ tls_send_close(Config) when is_list(Config) ->
{options, [{active, false} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
{ok, TcpS} = rpc:call(ClientNode, gen_tcp, connect,
- [Hostname,Port,[binary, {active, false}, {reuseaddr, true}]]),
+ [Hostname,Port,[binary, {active, false}]]),
{ok, SslS} = rpc:call(ClientNode, ssl, connect,
[TcpS,[{active, false}|ClientOpts]]),
@@ -1855,7 +2041,7 @@ tls_upgrade(Config) when is_list(Config) ->
{host, Hostname},
{from, self()},
{mfa, {?MODULE, upgrade_result, []}},
- {tcp_options, TcpOpts},
+ {tcp_options, [binary]},
{ssl_options, ClientOpts}]),
ct:log("Testcase ~p, Client ~p Server ~p ~n",
@@ -2308,20 +2494,16 @@ tls_shutdown_error(Config) when is_list(Config) ->
ciphers_rsa_signed_certs() ->
[{doc,"Test all rsa ssl cipher suites in highest support ssl/tls version"}].
-ciphers_rsa_signed_certs(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
+ciphers_rsa_signed_certs(Config) when is_list(Config) ->
Ciphers = ssl_test_lib:rsa_suites(crypto),
- ct:log("~p erlang cipher suites ~p~n", [Version, Ciphers]),
- run_suites(Ciphers, Version, Config, rsa).
+ run_suites(Ciphers, Config, rsa).
%%-------------------------------------------------------------------
ciphers_rsa_signed_certs_openssl_names() ->
[{doc,"Test all rsa ssl cipher suites in highest support ssl/tls version"}].
ciphers_rsa_signed_certs_openssl_names(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:openssl_rsa_suites(crypto),
- ct:log("tls1 openssl cipher suites ~p~n", [Ciphers]),
- run_suites(Ciphers, Version, Config, rsa).
+ Ciphers = ssl_test_lib:openssl_rsa_suites(),
+ run_suites(Ciphers, Config, rsa).
%%-------------------------------------------------------------------
ciphers_dsa_signed_certs() ->
@@ -2329,120 +2511,122 @@ ciphers_dsa_signed_certs() ->
ciphers_dsa_signed_certs(Config) when is_list(Config) ->
NVersion = ssl_test_lib:protocol_version(Config, tuple),
- Version = ssl_test_lib:protocol_version(Config),
Ciphers = ssl_test_lib:dsa_suites(NVersion),
- ct:log("~p erlang cipher suites ~p~n", [Version, Ciphers]),
- run_suites(Ciphers, Version, Config, dsa).
+ run_suites(Ciphers, Config, dsa).
%%-------------------------------------------------------------------
ciphers_dsa_signed_certs_openssl_names() ->
[{doc,"Test all dsa ssl cipher suites in highest support ssl/tls version"}].
ciphers_dsa_signed_certs_openssl_names(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
Ciphers = ssl_test_lib:openssl_dsa_suites(),
- ct:log("tls1 openssl cipher suites ~p~n", [Ciphers]),
- run_suites(Ciphers, Version, Config, dsa).
+ run_suites(Ciphers, Config, dsa).
+
%%-------------------------------------------------------------------
+chacha_rsa_cipher_suites()->
+ [{doc,"Test the cacha with ECDSA signed certs ciphersuites"}].
+chacha_rsa_cipher_suites(Config) when is_list(Config) ->
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = [S || {KeyEx,_,_} = S <- ssl_test_lib:chacha_suites(NVersion),
+ KeyEx == ecdhe_rsa, KeyEx == dhe_rsa],
+ run_suites(Ciphers, Config, chacha_ecdsa).
+
+%%-------------------------------------------------------------------
+chacha_ecdsa_cipher_suites()->
+ [{doc,"Test the cacha with ECDSA signed certs ciphersuites"}].
+chacha_ecdsa_cipher_suites(Config) when is_list(Config) ->
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = [S || {ecdhe_ecdsa,_,_} = S <- ssl_test_lib:chacha_suites(NVersion)],
+ run_suites(Ciphers, Config, chacha_rsa).
+%%-----------------------------------------------------------------
anonymous_cipher_suites()->
[{doc,"Test the anonymous ciphersuites"}].
anonymous_cipher_suites(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:anonymous_suites(Version),
- run_suites(Ciphers, Version, Config, anonymous).
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl_test_lib:ecdh_dh_anonymous_suites(NVersion),
+ run_suites(Ciphers, Config, anonymous).
%%-------------------------------------------------------------------
psk_cipher_suites() ->
[{doc, "Test the PSK ciphersuites WITHOUT server supplied identity hint"}].
psk_cipher_suites(Config) when is_list(Config) ->
- NVersion = tls_record:highest_protocol_version([]),
- Version = ssl_test_lib:protocol_version(Config),
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
Ciphers = ssl_test_lib:psk_suites(NVersion),
- run_suites(Ciphers, Version, Config, psk).
+ run_suites(Ciphers, Config, psk).
%%-------------------------------------------------------------------
psk_with_hint_cipher_suites()->
[{doc, "Test the PSK ciphersuites WITH server supplied identity hint"}].
psk_with_hint_cipher_suites(Config) when is_list(Config) ->
- NVersion = tls_record:highest_protocol_version([]),
- Version = ssl_test_lib:protocol_version(Config),
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
Ciphers = ssl_test_lib:psk_suites(NVersion),
- run_suites(Ciphers, Version, Config, psk_with_hint).
+ run_suites(Ciphers, Config, psk_with_hint).
%%-------------------------------------------------------------------
psk_anon_cipher_suites() ->
[{doc, "Test the anonymous PSK ciphersuites WITHOUT server supplied identity hint"}].
psk_anon_cipher_suites(Config) when is_list(Config) ->
- NVersion = tls_record:highest_protocol_version([]),
- Version = ssl_test_lib:protocol_version(Config),
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
Ciphers = ssl_test_lib:psk_anon_suites(NVersion),
- run_suites(Ciphers, Version, Config, psk_anon).
+ run_suites(Ciphers, Config, psk_anon).
%%-------------------------------------------------------------------
psk_anon_with_hint_cipher_suites()->
[{doc, "Test the anonymous PSK ciphersuites WITH server supplied identity hint"}].
psk_anon_with_hint_cipher_suites(Config) when is_list(Config) ->
- NVersion = tls_record:highest_protocol_version([]),
- Version = ssl_test_lib:protocol_version(Config),
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
Ciphers = ssl_test_lib:psk_anon_suites(NVersion),
- run_suites(Ciphers, Version, Config, psk_anon_with_hint).
+ run_suites(Ciphers, Config, psk_anon_with_hint).
%%-------------------------------------------------------------------
srp_cipher_suites()->
[{doc, "Test the SRP ciphersuites"}].
srp_cipher_suites(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
Ciphers = ssl_test_lib:srp_suites(),
- run_suites(Ciphers, Version, Config, srp).
+ run_suites(Ciphers, Config, srp).
%%-------------------------------------------------------------------
srp_anon_cipher_suites()->
[{doc, "Test the anonymous SRP ciphersuites"}].
srp_anon_cipher_suites(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
Ciphers = ssl_test_lib:srp_anon_suites(),
- run_suites(Ciphers, Version, Config, srp_anon).
+ run_suites(Ciphers, Config, srp_anon).
%%-------------------------------------------------------------------
srp_dsa_cipher_suites()->
[{doc, "Test the SRP DSA ciphersuites"}].
srp_dsa_cipher_suites(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
Ciphers = ssl_test_lib:srp_dss_suites(),
- run_suites(Ciphers, Version, Config, srp_dsa).
+ run_suites(Ciphers, Config, srp_dsa).
%%-------------------------------------------------------------------
rc4_rsa_cipher_suites()->
[{doc, "Test the RC4 ciphersuites"}].
rc4_rsa_cipher_suites(Config) when is_list(Config) ->
- NVersion = tls_record:highest_protocol_version([]),
- Version = tls_record:protocol_version(NVersion),
- Ciphers = ssl_test_lib:rc4_suites(NVersion),
- run_suites(Ciphers, Version, Config, rc4_rsa).
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = [S || {rsa,_,_} = S <- ssl_test_lib:rc4_suites(NVersion)],
+ run_suites(Ciphers, Config, rc4_rsa).
%-------------------------------------------------------------------
rc4_ecdh_rsa_cipher_suites()->
[{doc, "Test the RC4 ciphersuites"}].
rc4_ecdh_rsa_cipher_suites(Config) when is_list(Config) ->
- NVersion = tls_record:highest_protocol_version([]),
- Version = tls_record:protocol_version(NVersion),
- Ciphers = ssl_test_lib:rc4_suites(NVersion),
- run_suites(Ciphers, Version, Config, rc4_ecdh_rsa).
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = [S || {ecdh_rsa,_,_} = S <- ssl_test_lib:rc4_suites(NVersion)],
+ run_suites(Ciphers, Config, rc4_ecdh_rsa).
%%-------------------------------------------------------------------
rc4_ecdsa_cipher_suites()->
[{doc, "Test the RC4 ciphersuites"}].
rc4_ecdsa_cipher_suites(Config) when is_list(Config) ->
NVersion = tls_record:highest_protocol_version([]),
- Version = tls_record:protocol_version(NVersion),
- Ciphers = ssl_test_lib:rc4_suites(NVersion),
- run_suites(Ciphers, Version, Config, rc4_ecdsa).
+ Ciphers = [S || {ecdhe_ecdsa,_,_} = S <- ssl_test_lib:rc4_suites(NVersion)],
+ run_suites(Ciphers, Config, rc4_ecdsa).
%%-------------------------------------------------------------------
des_rsa_cipher_suites()->
[{doc, "Test the des_rsa ciphersuites"}].
des_rsa_cipher_suites(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:des_suites(Config),
- run_suites(Ciphers, Version, Config, des_rsa).
+ NVersion = tls_record:highest_protocol_version([]),
+ Ciphers = [S || {rsa,_,_} = S <- ssl_test_lib:des_suites(NVersion)],
+ run_suites(Ciphers, Config, des_rsa).
%-------------------------------------------------------------------
des_ecdh_rsa_cipher_suites()->
[{doc, "Test ECDH rsa signed ciphersuites"}].
des_ecdh_rsa_cipher_suites(Config) when is_list(Config) ->
NVersion = ssl_test_lib:protocol_version(Config, tuple),
- Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:des_suites(NVersion),
- run_suites(Ciphers, Version, Config, des_dhe_rsa).
+ Ciphers = [S || {dhe_rsa,_,_} = S <- ssl_test_lib:des_suites(NVersion)],
+ run_suites(Ciphers, Config, des_dhe_rsa).
%%--------------------------------------------------------------------
default_reject_anonymous()->
@@ -2454,21 +2638,21 @@ default_reject_anonymous(Config) when is_list(Config) ->
Version = ssl_test_lib:protocol_version(Config),
TLSVersion = ssl_test_lib:tls_version(Version),
- [CipherSuite | _] = ssl_test_lib:anonymous_suites(TLSVersion),
+ [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]}]),
+ {host, Hostname},
+ {from, self()},
+ {options,
+ [{ciphers,[CipherSuite]} |
+ ClientOpts]}]),
ssl_test_lib:check_result(Server, {error, {tls_alert, "insufficient security"}},
- Client, {error, {tls_alert, "insufficient security"}}).
+ Client, {error, {tls_alert, "insufficient security"}}).
%%--------------------------------------------------------------------
ciphers_ecdsa_signed_certs() ->
@@ -2476,38 +2660,30 @@ ciphers_ecdsa_signed_certs() ->
ciphers_ecdsa_signed_certs(Config) when is_list(Config) ->
NVersion = ssl_test_lib:protocol_version(Config, tuple),
- Version = ssl_test_lib:protocol_version(Config),
Ciphers = ssl_test_lib:ecdsa_suites(NVersion),
- ct:log("~p erlang cipher suites ~p~n", [Version, Ciphers]),
- run_suites(Ciphers, Version, Config, ecdsa).
+ run_suites(Ciphers, Config, ecdsa).
%%--------------------------------------------------------------------
ciphers_ecdsa_signed_certs_openssl_names() ->
[{doc, "Test all ecdsa ssl cipher suites in highest support ssl/tls version"}].
ciphers_ecdsa_signed_certs_openssl_names(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
Ciphers = ssl_test_lib:openssl_ecdsa_suites(),
- ct:log("tls1 openssl cipher suites ~p~n", [Ciphers]),
- run_suites(Ciphers, Version, Config, ecdsa).
+ run_suites(Ciphers, Config, ecdsa).
%%--------------------------------------------------------------------
ciphers_ecdh_rsa_signed_certs() ->
[{doc, "Test all ecdh_rsa ssl cipher suites in highest support ssl/tls version"}].
ciphers_ecdh_rsa_signed_certs(Config) when is_list(Config) ->
NVersion = ssl_test_lib:protocol_version(Config, tuple),
- Version = ssl_test_lib:protocol_version(Config),
Ciphers = ssl_test_lib:ecdh_rsa_suites(NVersion),
- ct:log("~p erlang cipher suites ~p~n", [Version, Ciphers]),
- run_suites(Ciphers, Version, Config, ecdh_rsa).
+ run_suites(Ciphers, Config, ecdh_rsa).
%%--------------------------------------------------------------------
ciphers_ecdh_rsa_signed_certs_openssl_names() ->
[{doc, "Test all ecdh_rsa ssl cipher suites in highest support ssl/tls version"}].
ciphers_ecdh_rsa_signed_certs_openssl_names(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
Ciphers = ssl_test_lib:openssl_ecdh_rsa_suites(),
- ct:log("tls1 openssl cipher suites ~p~n", [Ciphers]),
- run_suites(Ciphers, Version, Config, ecdh_rsa).
+ run_suites(Ciphers, Config, ecdh_rsa).
%%--------------------------------------------------------------------
reuse_session() ->
[{doc,"Test reuse of sessions (short handshake)"}].
@@ -2809,6 +2985,36 @@ client_secure_renegotiate(Config) when is_list(Config) ->
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),
+
+ 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() ->
@@ -2978,10 +3184,10 @@ der_input(Config) when is_list(Config) ->
Size = ets:info(CADb, size),
- SeverVerifyOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ 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_opts, Config),
+ 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},
@@ -3024,37 +3230,6 @@ der_input_opts(Opts) ->
{Cert, {Asn1Type, Key}, CaCerts, DHParams}.
%%--------------------------------------------------------------------
-%% different_ca_peer_sign() ->
-%% ["Check that a CA can have a different signature algorithm than the peer cert."];
-
-%% different_ca_peer_sign(Config) when is_list(Config) ->
-%% ClientOpts = ssl_test_lib:ssl_options(client_mix_opts, Config),
-%% ServerOpts = ssl_test_lib:ssl_options(server_mix_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_once, []}},
-%% {options, [{active, once},
-%% {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,
-%% send_recv_result_active_once,
-%% []}},
-%% {options, [{active, once},
-%% {verify, verify_peer}
-%% | ClientOpts]}]),
-
-%% ssl_test_lib:check_result(Server, ok, Client, ok),
-%% ssl_test_lib:close(Server),
-%% ssl_test_lib:close(Client).
-
-
-%%--------------------------------------------------------------------
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) ->
@@ -3095,7 +3270,7 @@ no_reuses_session_server_restart_new_cert(Config) when is_list(Config) ->
ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
{from, self()},
{mfa, {ssl_test_lib, no_result, []}},
- {options, DsaServerOpts}]),
+ {options, [{reuseaddr, true} | DsaServerOpts]}]),
Client1 =
ssl_test_lib:start_client([{node, ClientNode},
@@ -3122,14 +3297,14 @@ no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) ->
DsaServerOpts = ssl_test_lib:ssl_options(server_dsa_opts, Config),
PrivDir = proplists:get_value(priv_dir, Config),
- NewServerOpts = new_config(PrivDir, ServerOpts),
+ 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, NewServerOpts}]),
+ {options, NewServerOpts0}]),
Port = ssl_test_lib:inet_port(Server),
Client0 =
ssl_test_lib:start_client([{node, ClientNode},
@@ -3150,13 +3325,13 @@ no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) ->
ssl:clear_pem_cache(),
- NewServerOpts = new_config(PrivDir, DsaServerOpts),
+ NewServerOpts1 = new_config(PrivDir, DsaServerOpts),
Server1 =
ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
{from, self()},
{mfa, {ssl_test_lib, no_result, []}},
- {options, NewServerOpts}]),
+ {options, [{reuseaddr, true} | NewServerOpts1]}]),
Client1 =
ssl_test_lib:start_client([{node, ClientNode},
{port, Port}, {host, Hostname},
@@ -3173,18 +3348,25 @@ no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
defaults(Config) when is_list(Config)->
- [_,
- {supported, Supported},
- {available, Available}]
- = ssl:versions(),
- true = lists:member(sslv3, Available),
- false = lists:member(sslv3, Supported),
+ 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)),
+ true = lists:member('tlsv1', proplists:get_value(supported, Versions)),
+ true = lists:member('tlsv1.1', proplists:get_value(available, Versions)),
+ true = 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({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)),
+ true = lists:member('dtlsv1', proplists:get_value(supported_dtls, Versions)).
%%--------------------------------------------------------------------
reuseaddr() ->
@@ -3270,16 +3452,50 @@ tls_tcp_reuseaddr(Config) when is_list(Config) ->
honor_server_cipher_order() ->
[{doc,"Test API honor server cipher order."}].
honor_server_cipher_order(Config) when is_list(Config) ->
- ClientCiphers = [{rsa, aes_128_cbc, sha}, {rsa, aes_256_cbc, sha}],
- ServerCiphers = [{rsa, aes_256_cbc, sha}, {rsa, aes_128_cbc, sha}],
-honor_cipher_order(Config, true, ServerCiphers, ClientCiphers, {rsa, aes_256_cbc, sha}).
+ ClientCiphers = [#{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf},
+ #{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf}],
+ ServerCiphers = [#{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac =>sha,
+ prf => default_prf},
+ #{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf}],
+ honor_cipher_order(Config, true, ServerCiphers, ClientCiphers, #{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf}).
honor_client_cipher_order() ->
[{doc,"Test API honor server cipher order."}].
honor_client_cipher_order(Config) when is_list(Config) ->
- ClientCiphers = [{rsa, aes_128_cbc, sha}, {rsa, aes_256_cbc, sha}],
- ServerCiphers = [{rsa, aes_256_cbc, sha}, {rsa, aes_128_cbc, sha}],
-honor_cipher_order(Config, false, ServerCiphers, ClientCiphers, {rsa, aes_128_cbc, sha}).
+ ClientCiphers = [#{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf},
+ #{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf}],
+ ServerCiphers = [#{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac =>sha,
+ prf => default_prf},
+ #{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf}],
+honor_cipher_order(Config, false, ServerCiphers, ClientCiphers, #{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf}).
honor_cipher_order(Config, Honor, ServerCiphers, ClientCiphers, Expected) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
@@ -3335,7 +3551,7 @@ tls_ciphersuite_vs_version(Config) when is_list(Config) ->
>>),
{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, false),
+ ServerHello = tls_handshake:decode_handshake({RecMajor, RecMinor}, 2, HelloBin),
case ServerHello of
#server_hello{server_version = {3,0}, cipher_suite = <<0,57>>} ->
ok;
@@ -3389,14 +3605,14 @@ no_common_signature_algs(Config) when is_list(Config) ->
| ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {options, [{signature_algs, [{sha384, rsa}]}
- | ClientOpts]}]),
+ {host, Hostname},
+ {from, self()},
+ {options, [{signature_algs, [{sha384, rsa}]}
+ | ClientOpts]}]),
ssl_test_lib:check_result(Server, {error, {tls_alert, "insufficient security"}},
- Client, {error, {tls_alert, "insufficient security"}}).
-
+ Client, {error, {tls_alert, "insufficient security"}}).
+
%%--------------------------------------------------------------------
tls_dont_crash_on_handshake_garbage() ->
@@ -3458,7 +3674,7 @@ hibernate(Config) ->
{mfa, {ssl_test_lib, send_recv_result_active, []}},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
- {Client, #sslsocket{pid=Pid}} = ssl_test_lib:start_client([return_socket,
+ {Client, #sslsocket{pid=[Pid|_]}} = ssl_test_lib:start_client([return_socket,
{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
@@ -3501,7 +3717,7 @@ hibernate_right_away(Config) ->
Server1 = ssl_test_lib:start_server(StartServerOpts),
Port1 = ssl_test_lib:inet_port(Server1),
- {Client1, #sslsocket{pid = Pid1}} = ssl_test_lib:start_client(StartClientOpts ++
+ {Client1, #sslsocket{pid = [Pid1|_]}} = ssl_test_lib:start_client(StartClientOpts ++
[{port, Port1}, {options, [{hibernate_after, 0}|ClientOpts]}]),
ssl_test_lib:check_result(Server1, ok, Client1, ok),
@@ -3513,7 +3729,7 @@ hibernate_right_away(Config) ->
Server2 = ssl_test_lib:start_server(StartServerOpts),
Port2 = ssl_test_lib:inet_port(Server2),
- {Client2, #sslsocket{pid = Pid2}} = ssl_test_lib:start_client(StartClientOpts ++
+ {Client2, #sslsocket{pid = [Pid2|_]}} = ssl_test_lib:start_client(StartClientOpts ++
[{port, Port2}, {options, [{hibernate_after, 1}|ClientOpts]}]),
ssl_test_lib:check_result(Server2, ok, Client2, ok),
@@ -3749,13 +3965,13 @@ tls_tcp_error_propagation_in_active_mode(Config) when is_list(Config) ->
{mfa, {ssl_test_lib, no_result, []}},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
- {Client, #sslsocket{pid=Pid} = SslSocket} = ssl_test_lib:start_client([return_socket,
- {node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, receive_msg, []}},
- {options, ClientOpts}]),
-
+ {Client, #sslsocket{pid=[Pid|_]} = SslSocket} = ssl_test_lib:start_client([return_socket,
+ {node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, receive_msg, []}},
+ {options, ClientOpts}]),
+
{status, _, _, StatusInfo} = sys:get_status(Pid),
[_, _,_, _, Prop] = StatusInfo,
State = ssl_test_lib:state(Prop),
@@ -3788,6 +4004,64 @@ recv_error_handling(Config) when is_list(Config) ->
ssl:close(SslSocket),
ssl_test_lib:check_result(Server, ok).
+
+
+%%--------------------------------------------------------------------
+call_in_error_state() ->
+ [{doc,"Special case of call error handling"}].
+call_in_error_state(Config) when is_list(Config) ->
+ ServerOpts0 = ssl_test_lib:ssl_options(server_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = [{cacertfile, "foo.pem"} | proplists:delete(cacertfile, ServerOpts0)],
+ Pid = spawn_link(?MODULE, run_error_server, [[self() | ServerOpts]]),
+ receive
+ {Pid, Port} ->
+ spawn_link(?MODULE, run_client_error, [[Port, ClientOpts]])
+ end,
+ receive
+ {error, closed} ->
+ ok;
+ Other ->
+ ct:fail(Other)
+ end.
+
+run_client_error([Port, Opts]) ->
+ ssl:connect("localhost", Port, Opts).
+
+run_error_server([ Pid | Opts]) ->
+ {ok, Listen} = ssl:listen(0, Opts),
+ {ok,{_, Port}} = ssl:sockname(Listen),
+ Pid ! {self(), Port},
+ {ok, Socket} = ssl:transport_accept(Listen),
+ Pid ! ssl:controlling_process(Socket, self()).
+
+%%--------------------------------------------------------------------
+
+close_in_error_state() ->
+ [{doc,"Special case of closing socket in error state"}].
+close_in_error_state(Config) when is_list(Config) ->
+ ServerOpts0 = ssl_test_lib:ssl_options(server_opts, Config),
+ ServerOpts = [{cacertfile, "foo.pem"} | proplists:delete(cacertfile, ServerOpts0)],
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ _ = spawn_link(?MODULE, run_error_server_close, [[self() | ServerOpts]]),
+ receive
+ {_Pid, Port} ->
+ spawn_link(?MODULE, run_client_error, [[Port, ClientOpts]])
+ end,
+ receive
+ ok ->
+ ok;
+ Other ->
+ ct:fail(Other)
+ end.
+
+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() ->
@@ -3795,9 +4069,23 @@ rizzo() ->
vunrable to Rizzo/Dungon attack"}].
rizzo(Config) when is_list(Config) ->
- Ciphers = [X || X ={_,Y,_} <- ssl:cipher_suites(), Y =/= rc4_128],
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;
+ (_) ->
+ true
+ end}]),
+
run_send_recv_rizzo(Ciphers, Config, Version,
{?MODULE, send_recv_result_active_rizzo, []}).
%%--------------------------------------------------------------------
@@ -3807,8 +4095,15 @@ no_rizzo_rc4() ->
no_rizzo_rc4(Config) when is_list(Config) ->
Prop = proplists:get_value(tc_group_properties, Config),
Version = proplists:get_value(name, Prop),
- Ciphers = [ssl_cipher:erl_suite_definition(Suite) ||
- Suite <- ssl_test_lib:rc4_suites(tls_record:protocol_version(Version))],
+ 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, []}).
@@ -3818,10 +4113,22 @@ rizzo_one_n_minus_one() ->
rizzo_one_n_minus_one(Config) when is_list(Config) ->
Prop = proplists:get_value(tc_group_properties, Config),
Version = proplists:get_value(name, Prop),
- AllSuites = ssl_test_lib:available_suites(tls_record:protocol_version(Version)),
- Ciphers = [X || X ={_,Y,_} <- AllSuites, Y =/= rc4_128],
+ 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;
+ (_) ->
+ true
+ end}]),
run_send_recv_rizzo(Ciphers, Config, Version,
- {?MODULE, send_recv_result_active_rizzo, []}).
+ {?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"}].
@@ -3829,8 +4136,14 @@ rizzo_zero_n() ->
rizzo_zero_n(Config) when is_list(Config) ->
Prop = proplists:get_value(tc_group_properties, Config),
Version = proplists:get_value(name, Prop),
- AllSuites = ssl_test_lib:available_suites(tls_record:protocol_version(Version)),
- Ciphers = [X || X ={_,Y,_} <- AllSuites, Y =/= rc4_128],
+ 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, []}).
@@ -3838,9 +4151,16 @@ rizzo_disabled() ->
[{doc,"Test that the mitigation of Rizzo/Dungon attack can be explicitly disabled"}].
rizzo_disabled(Config) when is_list(Config) ->
- Ciphers = [X || X ={_,Y,_} <- ssl:cipher_suites(), Y =/= rc4_128],
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, []}).
@@ -3961,17 +4281,17 @@ unordered_protocol_versions_server(Config) when is_list(Config) ->
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
+ {mfa, {?MODULE, protocol_info_result, []}},
{options, [{versions, ['tlsv1.1', 'tlsv1.2']} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
+ {mfa, {?MODULE, protocol_info_result, []}},
{options, ClientOpts}]),
- CipherSuite = first_rsa_suite(ssl:cipher_suites()),
- ServerMsg = ClientMsg = {ok, {'tlsv1.2', CipherSuite}},
+
+ ServerMsg = ClientMsg = {ok,'tlsv1.2'},
ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg).
%%--------------------------------------------------------------------
@@ -3986,18 +4306,17 @@ unordered_protocol_versions_client(Config) when is_list(Config) ->
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
+ {mfa, {?MODULE, protocol_info_result, []}},
{options, ServerOpts }]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
+ {mfa, {?MODULE, protocol_info_result, []}},
{options, [{versions, ['tlsv1.1', 'tlsv1.2']} | ClientOpts]}]),
-
- CipherSuite = first_rsa_suite(ssl:cipher_suites()),
- ServerMsg = ClientMsg = {ok, {'tlsv1.2', CipherSuite}},
+
+ ServerMsg = ClientMsg = {ok, 'tlsv1.2'},
ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg).
%%--------------------------------------------------------------------
@@ -4326,6 +4645,7 @@ renegotiate_rejected(Socket) ->
ok;
%% Handle 1/n-1 splitting countermeasure Rizzo/Duong-Beast
{ssl, Socket, "H"} ->
+
receive
{ssl, Socket, "ello world"} ->
ok
@@ -4615,51 +4935,58 @@ rizzo_test(Cipher, Config, Version, Mfa) ->
[{Cipher, Error}]
end.
-client_server_opts({KeyAlgo,_,_}, Config)
+client_server_opts(#{key_exchange := KeyAlgo}, Config)
when KeyAlgo == rsa orelse
KeyAlgo == dhe_rsa orelse
- KeyAlgo == ecdhe_rsa ->
+ 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({KeyAlgo,_,_}, Config) when KeyAlgo == dss orelse KeyAlgo == dhe_dss ->
+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({KeyAlgo,_,_}, Config) when KeyAlgo == ecdh_ecdsa orelse KeyAlgo == ecdhe_ecdsa ->
+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({KeyAlgo,_,_}, Config) when KeyAlgo == ecdh_rsa ->
+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)}.
-run_suites(Ciphers, Version, Config, Type) ->
+run_suites(Ciphers, Config, Type) ->
+ Version = ssl_test_lib:protocol_version(Config),
+ ct:log("Running cipher suites ~p~n", [Ciphers]),
{ClientOpts, ServerOpts} =
case Type of
rsa ->
{ssl_test_lib:ssl_options(client_verification_opts, Config),
- ssl_test_lib:ssl_options(server_verification_opts, Config)};
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options(server_verification_opts, Config)]};
dsa ->
{ssl_test_lib:ssl_options(client_verification_opts, Config),
- ssl_test_lib:ssl_options(server_dsa_opts, Config)};
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options(server_dsa_opts, Config)]};
anonymous ->
%% No certs in opts!
{ssl_test_lib:ssl_options(client_verification_opts, Config),
- [{reuseaddr, true}, {ciphers, ssl_test_lib:anonymous_suites(Version)}]};
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options([], Config)]};
psk ->
{ssl_test_lib:ssl_options(client_psk, Config),
- [{ciphers, ssl_test_lib:psk_suites(Version)} |
+ [{ciphers, Ciphers} |
ssl_test_lib:ssl_options(server_psk, Config)]};
psk_with_hint ->
{ssl_test_lib:ssl_options(client_psk, Config),
- [{ciphers, ssl_test_lib:psk_suites(Version)} |
+ [{ciphers, Ciphers} |
ssl_test_lib:ssl_options(server_psk_hint, Config)
]};
psk_anon ->
{ssl_test_lib:ssl_options(client_psk, Config),
- [{ciphers, ssl_test_lib:psk_anon_suites(Version)} |
+ [{ciphers, Ciphers} |
ssl_test_lib:ssl_options(server_psk_anon, Config)]};
psk_anon_with_hint ->
{ssl_test_lib:ssl_options(client_psk, Config),
- [{ciphers, ssl_test_lib:psk_anon_suites(Version)} |
+ [{ciphers, Ciphers} |
ssl_test_lib:ssl_options(server_psk_anon_hint, Config)]};
srp ->
{ssl_test_lib:ssl_options(client_srp, Config),
@@ -4672,7 +4999,8 @@ run_suites(Ciphers, Version, Config, Type) ->
ssl_test_lib:ssl_options(server_srp_dsa, Config)};
ecdsa ->
{ssl_test_lib:ssl_options(client_verification_opts, Config),
- ssl_test_lib:ssl_options(server_ecdsa_opts, Config)};
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options(server_ecdsa_opts, Config)]};
ecdh_rsa ->
{ssl_test_lib:ssl_options(client_verification_opts, Config),
ssl_test_lib:ssl_options(server_ecdh_rsa_opts, Config)};
@@ -4695,22 +5023,34 @@ run_suites(Ciphers, Version, Config, Type) ->
des_rsa ->
{ssl_test_lib:ssl_options(client_verification_opts, Config),
[{ciphers, Ciphers} |
- ssl_test_lib:ssl_options(server_verification_opts, Config)]}
+ ssl_test_lib:ssl_options(server_verification_opts, Config)]};
+ chacha_rsa ->
+ {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options(server_verification_opts, Config)]};
+ chacha_ecdsa ->
+ {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options(server_ecdsa_opts, Config)]}
end,
-
- Result = lists:map(fun(Cipher) ->
- cipher(Cipher, Version, Config, ClientOpts, ServerOpts) end,
- ssl_test_lib:filter_suites(Ciphers, Version)),
- case lists:flatten(Result) of
- [] ->
- ok;
- Error ->
- ct:log("Cipher suite errors: ~p~n", [Error]),
- ct:fail(cipher_suite_failed_see_test_case_log)
- end.
-
+ Suites = ssl_test_lib:filter_suites(Ciphers, Version),
+ ct:pal("ssl_test_lib:filter_suites(~p ~p) -> ~p ", [Ciphers, Version, Suites]),
+ Results0 = lists:map(fun(Cipher) ->
+ cipher(Cipher, Version, Config, ClientOpts, ServerOpts) end,
+ ssl_test_lib:filter_suites(Ciphers, Version)),
+ Results = lists:flatten(Results0),
+ true = length(Results) == length(Suites),
+ check_cipher_result(Results).
+
+check_cipher_result([]) ->
+ ok;
+check_cipher_result([ok | Rest]) ->
+ check_cipher_result(Rest);
+check_cipher_result([_ |_] = Error) ->
+ ct:fail(Error).
+
erlang_cipher_suite(Suite) when is_list(Suite)->
- ssl_cipher:erl_suite_definition(ssl_cipher:openssl_suite(Suite));
+ ssl_cipher_format:suite_definition(ssl_cipher_format:openssl_suite(Suite));
erlang_cipher_suite(Suite) ->
Suite.
@@ -4745,7 +5085,7 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) ->
case Result of
ok ->
- [];
+ [ok];
Error ->
[{ErlangCipherSuite, Error}]
end.
@@ -4762,8 +5102,13 @@ connection_information_result(Socket) ->
end.
connection_info_result(Socket) ->
- {ok, Info} = ssl:connection_information(Socket, [protocol, cipher_suite]),
- {ok, {proplists:get_value(protocol, Info), proplists:get_value(cipher_suite, Info)}}.
+ {ok, Info} = ssl:connection_information(Socket, [protocol, selected_cipher_suite]),
+ {ok, {proplists:get_value(protocol, Info), proplists:get_value(selected_cipher_suite, Info)}}.
+
+protocol_info_result(Socket) ->
+ {ok, [{protocol, PVersion}]} = ssl:connection_information(Socket, [protocol]),
+ {ok, PVersion}.
+
version_info_result(Socket) ->
{ok, [{version, Version}]} = ssl:connection_information(Socket, [version]),
{ok, Version}.
@@ -4806,8 +5151,14 @@ tls_downgrade_result(Socket) ->
tls_close(Socket) ->
ok = ssl_test_lib:send_recv_result(Socket),
- ok = ssl:close(Socket, 5000).
-
+ 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}) ->
@@ -4886,20 +5237,6 @@ try_recv_active_once(Socket) ->
{error, einval} = ssl:recv(Socket, 11),
ok.
-first_rsa_suite([{ecdhe_rsa, _, _} = Suite | _]) ->
- Suite;
-first_rsa_suite([{dhe_rsa, _, _} = Suite| _]) ->
- Suite;
-first_rsa_suite([{rsa, _, _} = Suite| _]) ->
- Suite;
-first_rsa_suite([{ecdhe_rsa, _, _, _} = Suite | _]) ->
- Suite;
-first_rsa_suite([{dhe_rsa, _, _, _} = Suite| _]) ->
- Suite;
-first_rsa_suite([{rsa, _, _, _} = Suite| _]) ->
- Suite;
-first_rsa_suite([_ | Rest]) ->
- first_rsa_suite(Rest).
wait_for_send(Socket) ->
%% Make sure TLS process processed send message event
diff --git a/lib/ssl/test/ssl_bench.spec b/lib/ssl/test/ssl_bench.spec
index d2f75b4203..8b746c5ca9 100644
--- a/lib/ssl/test/ssl_bench.spec
+++ b/lib/ssl/test/ssl_bench.spec
@@ -1 +1 @@
-{suites,"../ssl_test",[ssl_bench_SUITE]}.
+{suites,"../ssl_test",[ssl_bench_SUITE, ssl_dist_bench_SUITE]}.
diff --git a/lib/ssl/test/ssl_bench_SUITE.erl b/lib/ssl/test/ssl_bench_SUITE.erl
index ae2928b1c3..3fe6338d69 100644
--- a/lib/ssl/test/ssl_bench_SUITE.erl
+++ b/lib/ssl/test/ssl_bench_SUITE.erl
@@ -40,11 +40,11 @@ end_per_group(_GroupName, _Config) ->
ok.
init_per_suite(Config) ->
- try
- Server = setup(ssl, node()),
- [{server_node, Server}|Config]
- catch _:_ ->
- {skipped, "Benchmark machines only"}
+ case node() of
+ nonode@nohost ->
+ {skipped, "Node not distributed"};
+ _ ->
+ [{server_node, ssl_bench_test_lib:setup(perf_server)}|Config]
end.
end_per_suite(_Config) ->
@@ -132,10 +132,10 @@ bypass_pem_cache(_Config) ->
ssl() ->
- test(ssl, ?COUNT, node()).
+ test(ssl, ?COUNT).
-test(Type, Count, Host) ->
- Server = setup(Type, Host),
+test(Type, Count) ->
+ Server = ssl_bench_test_lib:setup(perf_server),
(do_test(Type, setup_connection, Count * 20, 1, Server)),
(do_test(Type, setup_connection, Count, 100, Server)),
(do_test(Type, payload, Count*300, 10, Server)),
@@ -294,47 +294,6 @@ msg() ->
"asdlkjsafsdfoierwlejsdlkfjsdf">>.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-setup(_Type, nonode@nohost) ->
- exit(dist_not_enabled);
-setup(Type, _This) ->
- Host = case os:getenv(?remote_host) of
- false ->
- {ok, This} = inet:gethostname(),
- This;
- RemHost ->
- RemHost
- end,
- Node = list_to_atom("perf_server@" ++ Host),
- SlaveArgs = case init:get_argument(pa) of
- {ok, PaPaths} ->
- lists:append([" -pa " ++ P || [P] <- PaPaths]);
- _ -> []
- end,
- %% io:format("Slave args: ~p~n",[SlaveArgs]),
- Prog =
- case os:find_executable("erl") of
- false -> "erl";
- P -> P
- end,
- io:format("Prog = ~p~n", [Prog]),
-
- case net_adm:ping(Node) of
- pong -> ok;
- pang ->
- {ok, Node} = slave:start(Host, perf_server, SlaveArgs, no_link, Prog)
- end,
- Path = code:get_path(),
- true = rpc:call(Node, code, set_path, [Path]),
- ok = rpc:call(Node, ?MODULE, setup_server, [Type, node()]),
- io:format("Client (~p) using ~s~n",[node(), code:which(ssl)]),
- (Node =:= node()) andalso restrict_schedulers(client),
- Node.
-
-setup_server(_Type, ClientNode) ->
- (ClientNode =:= node()) andalso restrict_schedulers(server),
- io:format("Server (~p) using ~s~n",[node(), code:which(ssl)]),
- ok.
-
ensure_all_started(App, Ack) ->
case application:start(App) of
@@ -358,13 +317,6 @@ setup_server_init(Type, Tc, Loop, PC) ->
unlink(Pid),
Res.
-restrict_schedulers(Type) ->
- %% We expect this to run on 8 core machine
- Extra0 = 1,
- Extra = if (Type =:= server) -> -Extra0; true -> Extra0 end,
- Scheds = erlang:system_info(schedulers),
- erlang:system_flag(schedulers_online, (Scheds div 2) + Extra).
-
tc(Fun, Mod, Line) ->
case timer:tc(Fun) of
{_,{'EXIT',Reason}} ->
diff --git a/lib/ssl/test/ssl_bench_test_lib.erl b/lib/ssl/test/ssl_bench_test_lib.erl
new file mode 100644
index 0000000000..e5cbb911bd
--- /dev/null
+++ b/lib/ssl/test/ssl_bench_test_lib.erl
@@ -0,0 +1,75 @@
+%%%-------------------------------------------------------------------
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(ssl_bench_test_lib).
+
+%% API
+-export([setup/1]).
+
+%% Internal exports
+-export([setup_server/1]).
+
+-define(remote_host, "NETMARKS_REMOTE_HOST").
+
+setup(Name) ->
+ Host = case os:getenv(?remote_host) of
+ false ->
+ {ok, This} = inet:gethostname(),
+ This;
+ RemHost ->
+ RemHost
+ end,
+ Node = list_to_atom(atom_to_list(Name) ++ "@" ++ Host),
+ SlaveArgs = case init:get_argument(pa) of
+ {ok, PaPaths} ->
+ lists:append([" -pa " ++ P || [P] <- PaPaths]);
+ _ -> []
+ end,
+ %% io:format("Slave args: ~p~n",[SlaveArgs]),
+ Prog =
+ case os:find_executable("erl") of
+ false -> "erl";
+ P -> P
+ end,
+ io:format("Prog = ~p~n", [Prog]),
+
+ case net_adm:ping(Node) of
+ pong -> ok;
+ pang ->
+ {ok, Node} =
+ slave:start(Host, Name, SlaveArgs, no_link, Prog)
+ end,
+ Path = code:get_path(),
+ true = rpc:call(Node, code, set_path, [Path]),
+ ok = rpc:call(Node, ?MODULE, setup_server, [node()]),
+ io:format("Client (~p) using ~s~n",[node(), code:which(ssl)]),
+ (Node =:= node()) andalso restrict_schedulers(client),
+ Node.
+
+setup_server(ClientNode) ->
+ (ClientNode =:= node()) andalso restrict_schedulers(server),
+ io:format("Server (~p) using ~s~n",[node(), code:which(ssl)]),
+ ok.
+
+restrict_schedulers(Type) ->
+ %% We expect this to run on 8 core machine
+ Extra0 = 1,
+ Extra = if (Type =:= server) -> -Extra0; true -> Extra0 end,
+ Scheds = erlang:system_info(schedulers),
+ erlang:system_flag(schedulers_online, (Scheds div 2) + Extra).
diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
index 6221cffdc1..588ca153a9 100644
--- a/lib/ssl/test/ssl_certificate_verify_SUITE.erl
+++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2012-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.
@@ -40,14 +40,22 @@
%%--------------------------------------------------------------------
all() ->
[
- {group, tls},
- {group, dtls}
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
].
groups() ->
[
- {tls, [], all_protocol_groups()},
- {dtls, [], all_protocol_groups()},
+ {'tlsv1.2', [], all_protocol_groups()},
+ {'tlsv1.1', [], all_protocol_groups()},
+ {'tlsv1', [], all_protocol_groups()},
+ {'sslv3', [], all_protocol_groups()},
+ {'dtlsv1.2', [], all_protocol_groups()},
+ {'dtlsv1', [], all_protocol_groups()},
{active, [], tests()},
{active_once, [], tests()},
{passive, [], tests()},
@@ -65,6 +73,7 @@ tests() ->
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,
@@ -78,7 +87,10 @@ tests() ->
extended_key_usage_verify_server,
critical_extension_verify_client,
critical_extension_verify_server,
- critical_extension_verify_none].
+ critical_extension_verify_none,
+ customize_hostname_check,
+ incomplete_chain
+ ].
error_handling_tests()->
[client_with_cert_cipher_suites_handshake,
@@ -104,24 +116,6 @@ end_per_suite(_Config) ->
ssl:stop(),
application:stop(crypto).
-init_per_group(tls, Config0) ->
- Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- ssl:stop(),
- application:load(ssl),
- application:set_env(ssl, protocol_version, Version),
- ssl:start(),
- Config = proplists:delete(protocol, Config0),
- [{protocol, tls}, {version, tls_record:protocol_version(Version)} | Config];
-
-init_per_group(dtls, Config0) ->
- Version = dtls_record:protocol_version(dtls_record:highest_protocol_version([])),
- ssl:stop(),
- application:load(ssl),
- application:set_env(ssl, protocol_version, Version),
- ssl:start(),
- Config = proplists:delete(protocol_opts, proplists:delete(protocol, Config0)),
- [{protocol, dtls}, {protocol_opts, [{protocol, dtls}]}, {version, dtls_record:protocol_version(Version)} | Config];
-
init_per_group(active, Config) ->
[{active, true}, {receive_function, send_recv_result_active} | Config];
init_per_group(active_once, Config) ->
@@ -130,12 +124,24 @@ init_per_group(passive, Config) ->
[{active, false}, {receive_function, send_recv_result} | Config];
init_per_group(error_handling, Config) ->
[{active, false}, {receive_function, send_recv_result} | Config];
+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 ->
+ [{version, GroupName} | ssl_test_lib:init_tls_version(GroupName, Config)];
+ false ->
+ {skip, "Missing crypto support"}
+ end
+ end.
-init_per_group(_, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
+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:stop(),
@@ -303,6 +309,35 @@ server_require_peer_cert_fail(Config) when is_list(Config) ->
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."}].
@@ -436,7 +471,7 @@ server_require_peer_cert_partial_chain_fun_fail(Config) when is_list(Config) ->
[{_,_,_}, {_, IntermidiateCA, _} | _] = public_key:pem_decode(ServerCAs),
PartialChain = fun(_CertChain) ->
- ture = false %% crash on purpose
+ ture = false %% crash on purpose
end,
Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
@@ -564,9 +599,12 @@ cert_expired() ->
cert_expired(Config) when is_list(Config) ->
{Year, Month, Day} = date(),
Active = proplists:get_value(active, Config),
- {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_ca_0,
- [{validity, {{Year-2, Month, Day},
- {Year-1, Month, Day}}}]}],
+ {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_chain,
+ [[],
+ [{validity, {{Year-2, Month, Day},
+ {Year-1, Month, Day}}}],
+ []
+ ]}],
Config, "_expired"),
ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config),
@@ -582,8 +620,8 @@ cert_expired(Config) when is_list(Config) ->
{from, self()},
{options, [{verify, verify_peer}, {active, Active} | ClientOpts]}]),
- tcp_delivery_workaround(Server, {error, {tls_alert, "certificate expired"}},
- Client, {error, {tls_alert, "certificate expired"}}).
+ ssl_test_lib:check_result(Server, {error, {tls_alert, "certificate expired"}},
+ Client, {error, {tls_alert, "certificate expired"}}).
two_digits_str(N) when N < 10 ->
lists:flatten(io_lib:format("0~p", [N]));
@@ -595,11 +633,11 @@ extended_key_usage_verify_server() ->
[{doc,"Test cert that has a critical extended_key_usage extension in server cert"}].
extended_key_usage_verify_server(Config) when is_list(Config) ->
- {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_peer_opts,
- [{extensions,
- [{?'id-ce-extKeyUsage',
- [?'id-kp-serverAuth'], true}]
- }]}], Config, "_keyusage_server"),
+ Ext = x509_test:extensions([{?'id-ce-extKeyUsage',
+ [?'id-kp-serverAuth'], true}]),
+ {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_chain,
+ [[],[], [{extensions, Ext}]]}], Config,
+ "_keyusage_server"),
ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config),
Active = proplists:get_value(active, Config),
@@ -629,14 +667,13 @@ extended_key_usage_verify_both() ->
[{doc,"Test cert that has a critical extended_key_usage extension in client verify_peer mode"}].
extended_key_usage_verify_both(Config) when is_list(Config) ->
- {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_peer_opts,
- [{extensions, [{?'id-ce-extKeyUsage',
- [?'id-kp-serverAuth'], true}]
- }]},
- {client_peer_opts,
- [{extensions, [{?'id-ce-extKeyUsage',
- [?'id-kp-clientAuth'], true}]
- }]}], Config, "_keyusage_both"),
+ ServerExt = x509_test:extensions([{?'id-ce-extKeyUsage',
+ [?'id-kp-serverAuth'], true}]),
+ ClientExt = x509_test:extensions([{?'id-ce-extKeyUsage',
+ [?'id-kp-clientAuth'], true}]),
+ {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_chain, [[],[],[{extensions, ClientExt}]]},
+ {server_chain, [[],[],[{extensions, ServerExt}]]}],
+ Config, "_keyusage_both"),
ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config),
Active = proplists:get_value(active, Config),
@@ -665,10 +702,10 @@ critical_extension_verify_server() ->
[{doc,"Test cert that has a critical unknown extension in verify_peer mode"}].
critical_extension_verify_server(Config) when is_list(Config) ->
- {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_peer_opts,
- [{extensions, [{{2,16,840,1,113730,1,1},
- <<3,2,6,192>>, true}]
- }]}], Config, "_client_unknown_extension"),
+ Ext = x509_test:extensions([{{2,16,840,1,113730,1,1}, <<3,2,6,192>>, true}]),
+ {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_chain,
+ [[],[], [{extensions, Ext}]]}],
+ Config, "_client_unknown_extension"),
ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config),
Active = proplists:get_value(active, Config),
@@ -692,8 +729,8 @@ critical_extension_verify_server(Config) when is_list(Config) ->
%% This certificate has a critical extension that we don't
%% understand. Therefore, verification should fail.
- tcp_delivery_workaround(Server, {error, {tls_alert, "unsupported certificate"}},
- Client, {error, {tls_alert, "unsupported certificate"}}),
+ ssl_test_lib:check_result(Server, {error, {tls_alert, "unsupported certificate"}},
+ Client, {error, {tls_alert, "unsupported certificate"}}),
ssl_test_lib:close(Server).
%%--------------------------------------------------------------------
@@ -702,10 +739,10 @@ critical_extension_verify_client() ->
[{doc,"Test cert that has a critical unknown extension in verify_peer mode"}].
critical_extension_verify_client(Config) when is_list(Config) ->
- {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_peer_opts,
- [{extensions, [{{2,16,840,1,113730,1,1},
- <<3,2,6,192>>, true}]
- }]}], Config, "_server_unknown_extensions"),
+ Ext = x509_test:extensions([{{2,16,840,1,113730,1,1}, <<3,2,6,192>>, true}]),
+ {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_chain,
+ [[],[],[{extensions, Ext}]]}],
+ Config, "_server_unknown_extensions"),
ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config),
Active = proplists:get_value(active, Config),
@@ -738,11 +775,10 @@ critical_extension_verify_none() ->
[{doc,"Test cert that has a critical unknown extension in verify_none mode"}].
critical_extension_verify_none(Config) when is_list(Config) ->
- {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_peer_opts,
- [{extensions,
- [{{2,16,840,1,113730,1,1},
- <<3,2,6,192>>, true}]
- }]}], Config, "_unknown_extensions"),
+ Ext = x509_test:extensions([{{2,16,840,1,113730,1,1}, <<3,2,6,192>>, true}]),
+ {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_chain,
+ [[],[], [{extensions, Ext}]]}],
+ Config, "_unknown_extensions"),
ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config),
Active = proplists:get_value(active, Config),
@@ -777,12 +813,7 @@ no_authority_key_identifier() ->
" but are present in trusted certs db."}].
no_authority_key_identifier(Config) when is_list(Config) ->
- {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_peer_opts,
- [{extensions, [{auth_key_id, undefined}]
- }]},
- {client_peer_opts,
- [{extensions, [{auth_key_id, undefined}]
- }]}], Config, "_peer_no_auth_key_id"),
+ {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([], Config, "_peer_no_auth_key_id"),
ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config),
@@ -819,14 +850,10 @@ no_authority_key_identifier_keyEncipherment() ->
" authorityKeyIdentifier extension, but are present in trusted certs db."}].
no_authority_key_identifier_keyEncipherment(Config) when is_list(Config) ->
- {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_peer_opts,
- [{extensions, [{auth_key_id, undefined},
- {key_usage, [digitalSignature,
- keyEncipherment]}]
- }]},
- {client_peer_opts,
- [{extensions, [{auth_key_id, undefined}]
- }]}], Config, "_peer_keyEncipherment"),
+ ClientExt = x509_test:extensions([{key_usage, [digitalSignature, keyEncipherment]}]),
+ {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_chain,
+ [[],[],[{extensions, ClientExt}]]}],
+ Config, "_peer_keyEncipherment"),
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),
@@ -882,8 +909,8 @@ invalid_signature_server(Config) when is_list(Config) ->
{from, self()},
{options, [{verify, verify_peer} | ClientOpts]}]),
- tcp_delivery_workaround(Server, {error, {tls_alert, "unknown ca"}},
- Client, {error, {tls_alert, "unknown ca"}}).
+ ssl_test_lib:check_result(Server, {error, {tls_alert, "unknown ca"}},
+ Client, {error, {tls_alert, "unknown ca"}}).
%%--------------------------------------------------------------------
@@ -919,8 +946,8 @@ invalid_signature_client(Config) when is_list(Config) ->
{from, self()},
{options, NewClientOpts}]),
- tcp_delivery_workaround(Server, {error, {tls_alert, "unknown ca"}},
- Client, {error, {tls_alert, "unknown ca"}}).
+ ssl_test_lib:check_result(Server, {error, {tls_alert, "unknown ca"}},
+ Client, {error, {tls_alert, "unknown ca"}}).
%%--------------------------------------------------------------------
@@ -929,14 +956,13 @@ client_with_cert_cipher_suites_handshake() ->
[{doc, "Test that client with a certificate without keyEncipherment usage "
" extension can connect to a server with restricted cipher suites "}].
client_with_cert_cipher_suites_handshake(Config) when is_list(Config) ->
- {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_peer_opts,
- [{extensions,
- [{key_usage, [digitalSignature]}]
- }]}], Config, "_sign_only_extensions"),
-
-
+ Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
+ {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_chain,
+ [[], [], [{extensions, Ext}]]}],
+ Config, "_sign_only_extensions"),
ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config),
+ TLSVersion = ssl_test_lib:protocol_version(Config, tuple),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
@@ -945,7 +971,7 @@ client_with_cert_cipher_suites_handshake(Config) when is_list(Config) ->
send_recv_result_active, []}},
{options, [{active, true},
{ciphers,
- ssl_test_lib:rsa_non_signed_suites(proplists:get_value(version, Config))}
+ ssl_test_lib:rsa_non_signed_suites(TLSVersion)}
| ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
@@ -1122,44 +1148,91 @@ unknown_server_ca_accept_backwardscompatibility(Config) when is_list(Config) ->
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_result(Client1, {error, {tls_alert, "handshake failure"}},
+ Server, {error, {tls_alert, "handshake failure"}}),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+incomplete_chain() ->
+ [{doc,"Test option verify_peer"}].
+incomplete_chain(Config) when is_list(Config) ->
+ DefConf = ssl_test_lib:default_cert_chain_conf(),
+ CertChainConf = ssl_test_lib:gen_conf(rsa, rsa, DefConf, DefConf),
+ #{server_config := ServerConf,
+ client_config := ClientConf} = public_key:pkix_test_data(CertChainConf),
+ [ServerRoot| _] = ServerCas = proplists:get_value(cacerts, ServerConf),
+ ClientCas = proplists:get_value(cacerts, ClientConf),
+
+ Active = proplists:get_value(active, Config),
+ ReceiveFunction = proplists:get_value(receive_function, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, ReceiveFunction, []}},
+ {options, [{active, Active}, {verify, verify_peer},
+ {cacerts, [ServerRoot]} |
+ proplists:delete(cacerts, ServerConf)]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, ReceiveFunction, []}},
+ {options, [{active, Active},
+ {verify, verify_peer},
+ {cacerts, ServerCas ++ ClientCas} |
+ proplists:delete(cacerts, ClientConf)]}]),
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
-tcp_delivery_workaround(Server, ServerMsg, Client, ClientMsg) ->
- receive
- {Server, ServerMsg} ->
- client_msg(Client, ClientMsg);
- {Client, ClientMsg} ->
- server_msg(Server, ServerMsg);
- {Client, {error,closed}} ->
- server_msg(Server, ServerMsg);
- {Server, {error,closed}} ->
- client_msg(Client, ClientMsg)
- end.
-
-client_msg(Client, ClientMsg) ->
- receive
- {Client, ClientMsg} ->
- ok;
- {Client, {error,closed}} ->
- ct:log("client got close"),
- ok;
- {Client, {error, Reason}} ->
- ct:log("client got econnaborted: ~p", [Reason]),
- ok;
- Unexpected ->
- ct:fail(Unexpected)
- end.
-server_msg(Server, ServerMsg) ->
- receive
- {Server, ServerMsg} ->
- ok;
- {Server, {error,closed}} ->
- ct:log("server got close"),
- ok;
- {Server, {error, Reason}} ->
- ct:log("server got econnaborted: ~p", [Reason]),
- ok;
- Unexpected ->
- ct:fail(Unexpected)
- end.
diff --git a/lib/ssl/test/ssl_crl_SUITE.erl b/lib/ssl/test/ssl_crl_SUITE.erl
index e293d183f7..23c5eaf84d 100644
--- a/lib/ssl/test/ssl_crl_SUITE.erl
+++ b/lib/ssl/test/ssl_crl_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -155,9 +155,15 @@ init_per_testcase(Case, Config0) ->
DataDir = proplists:get_value(data_dir, Config),
CertDir = filename:join(proplists:get_value(priv_dir, Config0), idp_crl),
{CertOpts, Config} = init_certs(CertDir, idp_crl, Config),
- {ok, _} = make_certs:all(DataDir, CertDir, CertOpts),
- ct:timetrap({seconds, 6}),
- [{cert_dir, CertDir} | Config];
+ case make_certs:all(DataDir, CertDir, CertOpts) of
+ {ok, _} ->
+ ct:timetrap({seconds, 6}),
+ [{cert_dir, CertDir} | Config];
+ _ ->
+ end_per_testcase(Case, Config0),
+ ssl_test_lib:clean_start(),
+ {skip, "Unable to create IDP crls"}
+ end;
false ->
end_per_testcase(Case, Config0),
ssl_test_lib:clean_start(),
diff --git a/lib/ssl/test/ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl
index 8740e8c8f0..003e1fc448 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-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,20 +22,21 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("public_key/include/public_key.hrl").
+-include("ssl_dist_test_lib.hrl").
%% Note: This directive should only be used in test suites.
--compile(export_all).
+-compile([export_all, nowarn_export_all]).
-define(DEFAULT_TIMETRAP_SECS, 240).
-define(AWAIT_SSL_NODE_UP_TIMEOUT, 30000).
--record(node_handle,
- {connection_handler,
- socket,
- name,
- nodename}
- ).
+-import(ssl_dist_test_lib,
+ [tstsrvr_format/2, send_to_tstcntrl/1,
+ apply_on_ssl_node/4, apply_on_ssl_node/2,
+ stop_ssl_node/1]).
+start_ssl_node_name(Name, Args) ->
+ ssl_dist_test_lib:start_ssl_node(Name, Args).
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
@@ -140,11 +141,14 @@ basic_test(NH1, NH2, _) ->
apply_on_ssl_node(
NH1,
fun () ->
- tstsrvr_format("Hi from ~p!~n", [node()]),
- send_to_tstcntrl({Ref, self()}),
+ tstsrvr_format(
+ "Hi from ~p!~n", [node()]),
+ send_to_tstcntrl(
+ {Ref, self()}),
receive
{From, ping} ->
- tstsrvr_format("Received ping ~p!~n", [node()]),
+ tstsrvr_format(
+ "Received ping ~p!~n", [node()]),
From ! {self(), pong}
end
end)
@@ -154,7 +158,8 @@ basic_test(NH1, NH2, _) ->
ok = apply_on_ssl_node(
NH2,
fun () ->
- tstsrvr_format("Hi from ~p!~n", [node()]),
+ tstsrvr_format(
+ "Hi from ~p!~n", [node()]),
SslPid ! {self(), ping},
receive
{SslPid, pong} ->
@@ -183,7 +188,8 @@ payload_test(NH1, NH2, _) ->
apply_on_ssl_node(
NH1,
fun () ->
- send_to_tstcntrl({Ref, self()}),
+ send_to_tstcntrl(
+ {Ref, self()}),
receive
{From, Msg} ->
From ! {self(), Msg}
@@ -616,12 +622,6 @@ gen_dist_test(Test, Config) ->
%% ssl_node side api
%%
-tstsrvr_format(Fmt, ArgList) ->
- send_to_tstsrvr({format, Fmt, ArgList}).
-
-send_to_tstcntrl(Message) ->
- send_to_tstsrvr({message, Message}).
-
try_setting_priority(TestFun, Config) ->
Prio = 1,
case gen_udp:open(0, [{priority,Prio}]) of
@@ -653,44 +653,6 @@ inet_ports() ->
%% test_server side api
%%
-apply_on_ssl_node(Node, M, F, A) when is_atom(M), is_atom(F), is_list(A) ->
- Ref = make_ref(),
- send_to_ssl_node(Node, {apply, self(), Ref, M, F, A}),
- receive
- {Ref, Result} ->
- Result
- end.
-
-apply_on_ssl_node(Node, Fun) when is_function(Fun, 0) ->
- Ref = make_ref(),
- send_to_ssl_node(Node, {apply, self(), Ref, Fun}),
- receive
- {Ref, Result} ->
- Result
- end.
-
-stop_ssl_node(#node_handle{connection_handler = Handler,
- socket = Socket,
- name = Name}) ->
- ?t:format("Trying to stop ssl node ~s.~n", [Name]),
- Mon = erlang:monitor(process, Handler),
- unlink(Handler),
- case gen_tcp:send(Socket, term_to_binary(stop)) of
- ok ->
- receive
- {'DOWN', Mon, process, Handler, Reason} ->
- case Reason of
- normal ->
- ok;
- _ ->
- ct:pal("Down ~p ~n", [Reason])
- end
- end;
- Error ->
- erlang:demonitor(Mon, [flush]),
- ct:pal("Warning ~p ~n", [Error])
- end.
-
start_ssl_node(Config) ->
start_ssl_node(Config, "").
@@ -698,29 +660,8 @@ start_ssl_node(Config, XArgs) ->
Name = mk_node_name(Config),
SSL = proplists:get_value(ssl_opts, Config),
SSLDistOpts = setup_dist_opts(Config),
- start_ssl_node_raw(Name, SSL ++ " " ++ SSLDistOpts ++ XArgs).
-
-start_ssl_node_raw(Name, Args) ->
- {ok, LSock} = gen_tcp:listen(0,
- [binary, {packet, 4}, {active, false}]),
- {ok, ListenPort} = inet:port(LSock),
- CmdLine = mk_node_cmdline(ListenPort, Name, Args),
- ?t:format("Attempting to start ssl node ~ts: ~ts~n", [Name, CmdLine]),
- case open_port({spawn, CmdLine}, []) of
- Port when is_port(Port) ->
- unlink(Port),
- erlang:port_close(Port),
- case await_ssl_node_up(Name, LSock) of
- #node_handle{} = NodeHandle ->
- ?t:format("Ssl node ~s started.~n", [Name]),
- NodeName = list_to_atom(Name ++ "@" ++ host_name()),
- NodeHandle#node_handle{nodename = NodeName};
- Error ->
- exit({failed_to_start_node, Name, Error})
- end;
- Error ->
- exit({failed_to_start_node, Name, Error})
- end.
+ start_ssl_node_name(
+ Name, SSL ++ " " ++ SSLDistOpts ++ XArgs).
cache_crls_on_ssl_nodes(PrivDir, CANames, NHs) ->
[begin
@@ -739,11 +680,6 @@ cache_crls_on_ssl_nodes(PrivDir, CANames, NHs) ->
%% command line creation
%%
-host_name() ->
- [$@ | Host] = lists:dropwhile(fun ($@) -> false; (_) -> true end,
- atom_to_list(node())),
- Host.
-
mk_node_name(Config) ->
N = erlang:unique_integer([positive]),
Case = proplists:get_value(testcase, Config),
@@ -753,225 +689,6 @@ mk_node_name(Config) ->
++ "_"
++ integer_to_list(N).
-mk_node_cmdline(ListenPort, Name, Args) ->
- Static = "-detached -noinput",
- Pa = filename:dirname(code:which(?MODULE)),
- Prog = case catch init:get_argument(progname) of
- {ok,[[P]]} -> P;
- _ -> exit(no_progname_argument_found)
- end,
- NameSw = case net_kernel:longnames() of
- false -> "-sname ";
- _ -> "-name "
- end,
- {ok, Pwd} = file:get_cwd(),
- "\"" ++ Prog ++ "\" "
- ++ Static ++ " "
- ++ NameSw ++ " " ++ Name ++ " "
- ++ "-pa " ++ Pa ++ " "
- ++ "-run application start crypto -run application start public_key "
- ++ "-eval 'net_kernel:verbose(1)' "
- ++ "-run " ++ atom_to_list(?MODULE) ++ " cnct2tstsrvr "
- ++ host_name() ++ " "
- ++ integer_to_list(ListenPort) ++ " "
- ++ Args ++ " "
- ++ "-env ERL_CRASH_DUMP " ++ Pwd ++ "/erl_crash_dump." ++ Name ++ " "
- ++ "-kernel error_logger \"{file,\\\"" ++ Pwd ++ "/error_log." ++ Name ++ "\\\"}\" "
- ++ "-setcookie " ++ atom_to_list(erlang:get_cookie()).
-
-%%
-%% Connection handler test_server side
-%%
-
-await_ssl_node_up(Name, LSock) ->
- case gen_tcp:accept(LSock, ?AWAIT_SSL_NODE_UP_TIMEOUT) of
- timeout ->
- gen_tcp:close(LSock),
- ?t:format("Timeout waiting for ssl node ~s to come up~n",
- [Name]),
- timeout;
- {ok, Socket} ->
- gen_tcp:close(LSock),
- case gen_tcp:recv(Socket, 0) of
- {ok, Bin} ->
- check_ssl_node_up(Socket, Name, Bin);
- {error, closed} ->
- gen_tcp:close(Socket),
- exit({lost_connection_with_ssl_node_before_up, Name})
- end;
- {error, Error} ->
- gen_tcp:close(LSock),
- exit({accept_failed, Error})
- end.
-
-check_ssl_node_up(Socket, Name, Bin) ->
- case catch binary_to_term(Bin) of
- {'EXIT', _} ->
- gen_tcp:close(Socket),
- exit({bad_data_received_from_ssl_node, Name, Bin});
- {ssl_node_up, NodeName} ->
- case list_to_atom(Name++"@"++host_name()) of
- NodeName ->
- Parent = self(),
- Go = make_ref(),
- %% Spawn connection handler on test server side
- Pid = spawn_link(
- fun () ->
- receive Go -> ok end,
- tstsrvr_con_loop(Name, Socket, Parent)
- end),
- ok = gen_tcp:controlling_process(Socket, Pid),
- Pid ! Go,
- #node_handle{connection_handler = Pid,
- socket = Socket,
- name = Name};
- _ ->
- exit({unexpected_ssl_node_connected, NodeName})
- end;
- Msg ->
- exit({unexpected_msg_instead_of_ssl_node_up, Name, Msg})
- end.
-
-send_to_ssl_node(#node_handle{connection_handler = Hndlr}, Term) ->
- Hndlr ! {relay_to_ssl_node, term_to_binary(Term)},
- ok.
-
-tstsrvr_con_loop(Name, Socket, Parent) ->
- inet:setopts(Socket,[{active,once}]),
- receive
- {relay_to_ssl_node, Data} when is_binary(Data) ->
- case gen_tcp:send(Socket, Data) of
- ok ->
- ok;
- _Error ->
- gen_tcp:close(Socket),
- exit({failed_to_relay_data_to_ssl_node, Name, Data})
- end;
- {tcp, Socket, Bin} ->
- case catch binary_to_term(Bin) of
- {'EXIT', _} ->
- gen_tcp:close(Socket),
- exit({bad_data_received_from_ssl_node, Name, Bin});
- {format, FmtStr, ArgList} ->
- ?t:format(FmtStr, ArgList);
- {message, Msg} ->
- ?t:format("Got message ~p", [Msg]),
- Parent ! Msg;
- {apply_res, To, Ref, Res} ->
- To ! {Ref, Res};
- bye ->
- ?t:format("Ssl node ~s stopped.~n", [Name]),
- gen_tcp:close(Socket),
- exit(normal);
- Unknown ->
- exit({unexpected_message_from_ssl_node, Name, Unknown})
- end;
- {tcp_closed, Socket} ->
- gen_tcp:close(Socket),
- exit({lost_connection_with_ssl_node, Name})
- end,
- tstsrvr_con_loop(Name, Socket, Parent).
-
-%%
-%% Connection handler ssl_node side
-%%
-
-% cnct2tstsrvr() is called via command line arg -run ...
-cnct2tstsrvr([Host, Port]) when is_list(Host), is_list(Port) ->
- %% Spawn connection handler on ssl node side
- ConnHandler
- = spawn(fun () ->
- case catch gen_tcp:connect(Host,
- list_to_integer(Port),
- [binary,
- {packet, 4},
- {active, false}]) of
- {ok, Socket} ->
- notify_ssl_node_up(Socket),
- ets:new(test_server_info,
- [set,
- public,
- named_table,
- {keypos, 1}]),
- ets:insert(test_server_info,
- {test_server_handler, self()}),
- ssl_node_con_loop(Socket);
- Error ->
- halt("Failed to connect to test server " ++
- lists:flatten(io_lib:format("Host:~p ~n Port:~p~n Error:~p~n",
- [Host, Port, Error])))
- end
- end),
- spawn(fun () ->
- Mon = erlang:monitor(process, ConnHandler),
- receive
- {'DOWN', Mon, process, ConnHandler, Reason} ->
- receive after 1000 -> ok end,
- halt("test server connection handler terminated: " ++
- lists:flatten(io_lib:format("~p", [Reason])))
- end
- end).
-
-notify_ssl_node_up(Socket) ->
- case catch gen_tcp:send(Socket,
- term_to_binary({ssl_node_up, node()})) of
- ok -> ok;
- _ -> halt("Failed to notify test server that I'm up")
- end.
-
-send_to_tstsrvr(Term) ->
- case catch ets:lookup_element(test_server_info, test_server_handler, 2) of
- Hndlr when is_pid(Hndlr) ->
- Hndlr ! {relay_to_test_server, term_to_binary(Term)}, ok;
- _ ->
- receive after 200 -> ok end,
- send_to_tstsrvr(Term)
- end.
-
-ssl_node_con_loop(Socket) ->
- inet:setopts(Socket,[{active,once}]),
- receive
- {relay_to_test_server, Data} when is_binary(Data) ->
- case gen_tcp:send(Socket, Data) of
- ok ->
- ok;
- _Error ->
- gen_tcp:close(Socket),
- halt("Failed to relay data to test server")
- end;
- {tcp, Socket, Bin} ->
- case catch binary_to_term(Bin) of
- {'EXIT', _} ->
- gen_tcp:close(Socket),
- halt("test server sent me bad data");
- {apply, From, Ref, M, F, A} ->
- spawn_link(
- fun () ->
- send_to_tstsrvr({apply_res,
- From,
- Ref,
- (catch apply(M, F, A))})
- end);
- {apply, From, Ref, Fun} ->
- spawn_link(fun () ->
- send_to_tstsrvr({apply_res,
- From,
- Ref,
- (catch Fun())})
- end);
- stop ->
- gen_tcp:send(Socket, term_to_binary(bye)),
- gen_tcp:close(Socket),
- init:stop(),
- receive after infinity -> ok end;
- _Unknown ->
- halt("test server sent me an unexpected message")
- end;
- {tcp_closed, Socket} ->
- halt("Lost connection to test server")
- end,
- ssl_node_con_loop(Socket).
-
%%
%% Setup ssl dist info
%%
@@ -1007,7 +724,8 @@ setup_certs(Config) ->
ok = file:make_dir(NodeDir),
ok = file:make_dir(RGenDir),
make_randfile(RGenDir),
- {ok, _} = make_certs:all(RGenDir, NodeDir),
+ [Hostname|_] = string:split(net_adm:localhost(), ".", all),
+ {ok, _} = make_certs:all(RGenDir, NodeDir, [{hostname,Hostname}]),
SDir = filename:join([NodeDir, "server"]),
SC = filename:join([SDir, "cert.pem"]),
SK = filename:join([SDir, "key.pem"]),
diff --git a/lib/ssl/test/ssl_dist_bench_SUITE.erl b/lib/ssl/test/ssl_dist_bench_SUITE.erl
new file mode 100644
index 0000000000..3c7904cf24
--- /dev/null
+++ b/lib/ssl/test/ssl_dist_bench_SUITE.erl
@@ -0,0 +1,526 @@
+%%%-------------------------------------------------------------------
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(ssl_dist_bench_SUITE).
+
+-include_lib("common_test/include/ct_event.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+%% CT meta
+-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]).
+
+%% Test cases
+-export(
+ [setup/1,
+ roundtrip/1,
+ throughput_1024/1,
+ throughput_4096/1,
+ throughput_16384/1,
+ throughput_65536/1,
+ throughput_262144/1,
+ throughput_1048576/1]).
+
+%% Debug
+-export([payload/1]).
+
+%%%-------------------------------------------------------------------
+
+suite() -> [{ct_hooks, [{ts_install_cth, [{nodenames, 2}]}]}].
+
+all() -> [{group, ssl}, {group, plain}].
+
+groups() ->
+ [{ssl, all_groups()},
+ {plain, all_groups()},
+ %%
+ {setup, [{repeat, 1}], [setup]},
+ {roundtrip, [{repeat, 1}], [roundtrip]},
+ {throughput, [{repeat, 1}],
+ [throughput_1024,
+ throughput_4096,
+ throughput_16384,
+ throughput_65536,
+ throughput_262144,
+ throughput_1048576]}].
+
+all_groups() ->
+ [{group, setup},
+ {group, roundtrip},
+ {group, throughput}].
+
+init_per_suite(Config) ->
+ Digest = sha1,
+ ECCurve = secp521r1,
+ TLSVersion = 'tlsv1.2',
+ TLSCipher = {ecdhe_ecdsa,aes_128_cbc,sha256,sha256},
+ %%
+ Node = node(),
+ try
+ Node =/= nonode@nohost orelse
+ throw({skipped,"Node not distributed"}),
+ verify_node_src_addr(),
+ {supported, SSLVersions} =
+ lists:keyfind(supported, 1, ssl:versions()),
+ lists:member(TLSVersion, SSLVersions) orelse
+ throw(
+ {skipped,
+ "SSL does not support " ++ term_to_string(TLSVersion)}),
+ lists:member(ECCurve, ssl:eccs(TLSVersion)) orelse
+ throw(
+ {skipped,
+ "SSL does not support " ++ term_to_string(ECCurve)}),
+ lists:member(TLSCipher, ssl:cipher_suites()) orelse
+ throw(
+ {skipped,
+ "SSL does not support " ++ term_to_string(TLSCipher)})
+ of
+ _ ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ %%
+ [_, HostA] = split_node(Node),
+ NodeAName = ?MODULE_STRING ++ "_node_a",
+ NodeAString = NodeAName ++ "@" ++ HostA,
+ NodeAConfFile = filename:join(PrivDir, NodeAString ++ ".conf"),
+ NodeA = list_to_atom(NodeAString),
+ %%
+ ServerNode = ssl_bench_test_lib:setup(dist_server),
+ [_, HostB] = split_node(ServerNode),
+ NodeBName = ?MODULE_STRING ++ "_node_b",
+ NodeBString = NodeBName ++ "@" ++ HostB,
+ NodeBConfFile = filename:join(PrivDir, NodeBString ++ ".conf"),
+ NodeB = list_to_atom(NodeBString),
+ %%
+ CertOptions =
+ [{digest, Digest},
+ {key, {namedCurve, ECCurve}}],
+ RootCert =
+ public_key:pkix_test_root_cert(
+ ?MODULE_STRING ++ " ROOT CA", CertOptions),
+ SSLConf =
+ [{verify, verify_peer},
+ {versions, [TLSVersion]},
+ {ciphers, [TLSCipher]}],
+ ServerConf =
+ [{fail_if_no_peer_cert, true},
+ {verify_fun,
+ {fun inet_tls_dist:verify_client/3,[]}}
+ | SSLConf],
+ ClientConf = SSLConf,
+ %%
+ write_node_conf(
+ NodeAConfFile, NodeA, ServerConf, ClientConf,
+ CertOptions, RootCert),
+ write_node_conf(
+ NodeBConfFile, NodeB, ServerConf, ClientConf,
+ CertOptions, RootCert),
+ %%
+ [{node_a_name, NodeAName},
+ {node_a, NodeA},
+ {node_a_dist_args,
+ "-proto_dist inet_tls "
+ "-ssl_dist_optfile " ++ NodeAConfFile ++ " "},
+ {node_b_name, NodeBName},
+ {node_b, NodeB},
+ {node_b_dist_args,
+ "-proto_dist inet_tls "
+ "-ssl_dist_optfile " ++ NodeBConfFile ++ " "},
+ {server_node, ServerNode}
+ |Config]
+ catch
+ throw:Result ->
+ Result
+ end.
+
+end_per_suite(Config) ->
+ ServerNode = proplists:get_value(server_node, Config),
+ slave:stop(ServerNode).
+
+init_per_group(ssl, Config) ->
+ [{ssl_dist, true}, {ssl_dist_prefix, "SSL"}|Config];
+init_per_group(plain, Config) ->
+ [{ssl_dist, false}, {ssl_dist_prefix, "Plain"}|Config];
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+init_per_testcase(_Func, Conf) ->
+ Conf.
+
+end_per_testcase(_Func, _Conf) ->
+ ok.
+
+-define(COUNT, 400).
+
+%%%-------------------------------------------------------------------
+%%% CommonTest API helpers
+
+verify_node_src_addr() ->
+ Msg = "Hello, world!",
+ {ok,Host} = inet:gethostname(),
+ {ok,DstAddr} = inet:getaddr(Host, inet),
+ {ok,Socket} = gen_udp:open(0, [{active,false}]),
+ {ok,Port} = inet:port(Socket),
+ ok = gen_udp:send(Socket, DstAddr, Port, Msg),
+ case gen_udp:recv(Socket, length(Msg) + 1, 1000) of
+ {ok,{DstAddr,Port,Msg}} ->
+ ok;
+ {ok,{SrcAddr,Port,Msg}} ->
+ throw({skipped,
+ "Src and dst address mismatch: " ++
+ term_to_string(SrcAddr) ++ " =:= " ++
+ term_to_string(DstAddr)});
+ Weird ->
+ error(Weird)
+ end.
+
+write_node_conf(
+ ConfFile, Node, ServerConf, ClientConf, CertOptions, RootCert) ->
+ [Name,Host] = split_node(Node),
+ Conf =
+ public_key:pkix_test_data(
+ #{root => RootCert,
+ peer =>
+ [{extensions,
+ [
+ #'Extension'{
+ extnID = ?'id-ce-subjectAltName',
+ extnValue = [{dNSName, Host}],
+ critical = true},
+ #'Extension'{
+ extnID = ?'id-ce-subjectAltName',
+ extnValue =
+ [{directoryName,
+ {rdnSequence,
+ [[#'AttributeTypeAndValue'{
+ type = ?'id-at-commonName',
+ value =
+ {utf8String,
+ unicode:characters_to_binary(
+ Name, utf8)
+ }
+ }]]}}],
+ critical = true}
+ ]} | CertOptions]}),
+ NodeConf =
+ [{server, ServerConf ++ Conf}, {client, ClientConf ++ Conf}],
+ {ok, Fd} = file:open(ConfFile, [write]),
+ ok = file:change_mode(ConfFile, 8#400),
+ io:format(Fd, "~p.~n", [NodeConf]),
+ ok = file:close(Fd).
+
+split_node(Node) ->
+ string:split(atom_to_list(Node), "@").
+
+%%%-------------------------------------------------------------------
+%%% Test cases
+
+%%-----------------------
+%% Connection setup speed
+
+setup(Config) ->
+ run_nodepair_test(fun setup/5, Config).
+
+setup(A, B, Prefix, HA, HB) ->
+ Rounds = 50,
+ [] = ssl_apply(HA, erlang, nodes, []),
+ [] = ssl_apply(HB, erlang, nodes, []),
+ {SetupTime, CycleTime} =
+ ssl_apply(HA, fun () -> setup_runner(A, B, Rounds) end),
+ [] = ssl_apply(HA, erlang, nodes, []),
+ [] = ssl_apply(HB, erlang, nodes, []),
+ SetupSpeed = round((Rounds*1000000*1000) / SetupTime),
+ CycleSpeed = round((Rounds*1000000*1000) / CycleTime),
+ _ = report(Prefix++" Setup", SetupSpeed, "setups/1000s"),
+ report(Prefix++" Setup Cycle", CycleSpeed, "cycles/1000s").
+
+%% Runs on node A against rex in node B
+setup_runner(A, B, Rounds) ->
+ StartTime = start_time(),
+ SetupTime = setup_loop(A, B, 0, Rounds),
+ {microseconds(SetupTime), microseconds(elapsed_time(StartTime))}.
+
+setup_loop(_A, _B, T, 0) ->
+ T;
+setup_loop(A, B, T, N) ->
+ StartTime = start_time(),
+ [N,A] = [N|rpc:block_call(B, erlang, nodes, [])],
+ Time = elapsed_time(StartTime),
+ [N,B] = [N|erlang:nodes()],
+ Mref = erlang:monitor(process, {rex,B}),
+ true = net_kernel:disconnect(B),
+ receive
+ {'DOWN',Mref,process,_,_} ->
+ [] = erlang:nodes(),
+ setup_loop(A, B, Time + T, N - 1)
+ end.
+
+
+%%----------------
+%% Roundtrip speed
+
+roundtrip(Config) ->
+ run_nodepair_test(fun roundtrip/5, Config).
+
+roundtrip(A, B, Prefix, HA, HB) ->
+ Rounds = 40000,
+ [] = ssl_apply(HA, erlang, nodes, []),
+ [] = ssl_apply(HB, erlang, nodes, []),
+ ok = ssl_apply(HA, net_kernel, allow, [[B]]),
+ ok = ssl_apply(HB, net_kernel, allow, [[A]]),
+ Time = ssl_apply(HA, fun () -> roundtrip_runner(A, B, Rounds) end),
+ [B] = ssl_apply(HA, erlang, nodes, []),
+ [A] = ssl_apply(HB, erlang, nodes, []),
+ Speed = round((Rounds*1000000) / Time),
+ report(Prefix++" Roundtrip", Speed, "pings/s").
+
+%% Runs on node A and spawns a server on node B
+roundtrip_runner(A, B, Rounds) ->
+ ClientPid = self(),
+ [A] = rpc:call(B, erlang, nodes, []),
+ ServerPid =
+ erlang:spawn(
+ B,
+ fun () -> roundtrip_server(ClientPid, Rounds) end),
+ ServerMon = erlang:monitor(process, ServerPid),
+ microseconds(
+ roundtrip_client(ServerPid, ServerMon, start_time(), Rounds)).
+
+roundtrip_server(_Pid, 0) ->
+ ok;
+roundtrip_server(Pid, N) ->
+ receive
+ N ->
+ Pid ! N,
+ roundtrip_server(Pid, N-1)
+ end.
+
+roundtrip_client(_Pid, Mon, StartTime, 0) ->
+ Time = elapsed_time(StartTime),
+ receive
+ {'DOWN', Mon, _, _, normal} ->
+ Time;
+ {'DOWN', Mon, _, _, Other} ->
+ exit(Other)
+ end;
+roundtrip_client(Pid, Mon, StartTime, N) ->
+ Pid ! N,
+ receive
+ N ->
+ roundtrip_client(Pid, Mon, StartTime, N - 1)
+ end.
+
+
+%%-----------------
+%% Throughput speed
+
+throughput_1024(Config) ->
+ run_nodepair_test(
+ fun (A, B, Prefix, HA, HB) ->
+ throughput(A, B, Prefix, HA, HB, 100000, 1024)
+ end, Config).
+
+throughput_4096(Config) ->
+ run_nodepair_test(
+ fun (A, B, Prefix, HA, HB) ->
+ throughput(A, B, Prefix, HA, HB, 50000, 4096)
+ end, Config).
+
+throughput_16384(Config) ->
+ run_nodepair_test(
+ fun (A, B, Prefix, HA, HB) ->
+ throughput(A, B, Prefix, HA, HB, 10000, 16384)
+ end, Config).
+
+throughput_65536(Config) ->
+ run_nodepair_test(
+ fun (A, B, Prefix, HA, HB) ->
+ throughput(A, B, Prefix, HA, HB, 2000, 65536)
+ end, Config).
+
+throughput_262144(Config) ->
+ run_nodepair_test(
+ fun (A, B, Prefix, HA, HB) ->
+ throughput(A, B, Prefix, HA, HB, 500, 262144)
+ end, Config).
+
+throughput_1048576(Config) ->
+ run_nodepair_test(
+ fun (A, B, Prefix, HA, HB) ->
+ throughput(A, B, Prefix, HA, HB, 200, 1048576)
+ end, Config).
+
+throughput(A, B, Prefix, HA, HB, Packets, Size) ->
+ [] = ssl_apply(HA, erlang, nodes, []),
+ [] = ssl_apply(HB, erlang, nodes, []),
+ Time =
+ ssl_apply(HA, fun () -> throughput_runner(A, B, Packets, Size) end),
+ [B] = ssl_apply(HA, erlang, nodes, []),
+ [A] = ssl_apply(HB, erlang, nodes, []),
+ Speed = round((Packets*Size*1000000) / (1024*Time)),
+ report(Prefix++" Throughput_"++integer_to_list(Size), Speed, "kB/s").
+
+%% Runs on node A and spawns a server on node B
+throughput_runner(A, B, Rounds, Size) ->
+ Payload = payload(Size),
+ ClientPid = self(),
+ [A] = rpc:call(B, erlang, nodes, []),
+ ServerPid =
+ erlang:spawn(
+ B,
+ fun () -> throughput_server(ClientPid, Rounds) end),
+ ServerMon = erlang:monitor(process, ServerPid),
+ microseconds(
+ throughput_client(
+ ServerPid, ServerMon, Payload, start_time(), Rounds)).
+
+throughput_server(_Pid, 0) ->
+ ok;
+throughput_server(Pid, N) ->
+ receive
+ [N|_] ->
+ throughput_server(Pid, N-1)
+ end.
+
+throughput_client(_Pid, Mon, _Payload, StartTime, 0) ->
+ receive
+ {'DOWN', Mon, _, _, normal} ->
+ elapsed_time(StartTime);
+ {'DOWN', Mon, _, _, Other} ->
+ exit(Other)
+ end;
+throughput_client(Pid, Mon, Payload, StartTime, N) ->
+ Pid ! [N|Payload],
+ throughput_client(Pid, Mon, Payload, StartTime, N - 1).
+
+%%%-------------------------------------------------------------------
+%%% Test cases helpers
+
+run_nodepair_test(TestFun, Config) ->
+ A = proplists:get_value(node_a, Config),
+ B = proplists:get_value(node_b, Config),
+ Prefix = proplists:get_value(ssl_dist_prefix, Config),
+ HA = start_ssl_node_a(Config),
+ HB = start_ssl_node_b(Config),
+ try TestFun(A, B, Prefix, HA, HB)
+ after
+ stop_ssl_node_a(HA),
+ stop_ssl_node_b(HB, Config),
+ ok
+ end.
+
+ssl_apply(Handle, M, F, Args) ->
+ case ssl_dist_test_lib:apply_on_ssl_node(Handle, M, F, Args) of
+ {'EXIT',Reason} ->
+ error(Reason);
+ Result ->
+ Result
+ end.
+
+ssl_apply(Handle, Fun) ->
+ case ssl_dist_test_lib:apply_on_ssl_node(Handle, Fun) of
+ {'EXIT',Reason} ->
+ error(Reason);
+ Result ->
+ Result
+ end.
+
+start_ssl_node_a(Config) ->
+ Name = proplists:get_value(node_a_name, Config),
+ Args = get_node_args(node_a_dist_args, Config),
+ ssl_dist_test_lib:start_ssl_node(Name, Args).
+
+start_ssl_node_b(Config) ->
+ Name = proplists:get_value(node_b_name, Config),
+ Args = get_node_args(node_b_dist_args, Config),
+ ServerNode = proplists:get_value(server_node, Config),
+ rpc:call(
+ ServerNode, ssl_dist_test_lib, start_ssl_node, [Name, Args]).
+
+stop_ssl_node_a(HA) ->
+ ssl_dist_test_lib:stop_ssl_node(HA).
+
+stop_ssl_node_b(HB, Config) ->
+ ServerNode = proplists:get_value(server_node, Config),
+ rpc:call(ServerNode, ssl_dist_test_lib, stop_ssl_node, [HB]).
+
+get_node_args(Tag, Config) ->
+ case proplists:get_value(ssl_dist, Config) of
+ true ->
+ proplists:get_value(Tag, Config);
+ false ->
+ ""
+ end.
+
+
+
+payload(Size) ->
+ iolist_to_binary(
+ [case Size bsr 8 of
+ 0 ->
+ [];
+ Blocks ->
+ payload(Blocks, create_binary(256))
+ end | create_binary(Size band 255)]).
+%%
+payload(0, _) ->
+ [];
+payload(Blocks, Block) ->
+ Half = payload(Blocks bsr 1, Block),
+ [Half, Half |
+ if
+ Blocks band 1 =:= 1 ->
+ Block;
+ true ->
+ []
+ end].
+
+create_binary(Size) ->
+ create_binary(Size, <<>>).
+%%
+create_binary(0, Bin) ->
+ Bin;
+create_binary(Size, Bin) ->
+ NextSize = Size - 1,
+ create_binary(NextSize, <<Bin/binary, NextSize>>).
+
+start_time() ->
+ erlang:system_time().
+
+elapsed_time(StartTime) ->
+ erlang:system_time() - StartTime.
+
+microseconds(Time) ->
+ erlang:convert_time_unit(Time, native, microsecond).
+
+report(Name, Value, Unit) ->
+ ct:pal("~s: ~w ~s", [Name, Value, Unit]),
+ ct_event:notify(
+ #event{
+ name = benchmark_data,
+ data = [{value, Value}, {suite, "ssl_dist"}, {name, Name}]}),
+ {comment, term_to_string(Value) ++ " " ++ Unit}.
+
+term_to_string(Term) ->
+ unicode:characters_to_list(
+ io_lib:write(Term, [{encoding, unicode}])).
diff --git a/lib/ssl/test/ssl_dist_test_lib.erl b/lib/ssl/test/ssl_dist_test_lib.erl
new file mode 100644
index 0000000000..1b9c853fc4
--- /dev/null
+++ b/lib/ssl/test/ssl_dist_test_lib.erl
@@ -0,0 +1,343 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(ssl_dist_test_lib).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("public_key/include/public_key.hrl").
+-include("ssl_dist_test_lib.hrl").
+
+-export([tstsrvr_format/2, send_to_tstcntrl/1]).
+-export([apply_on_ssl_node/4, apply_on_ssl_node/2]).
+-export([stop_ssl_node/1, start_ssl_node/2]).
+%%
+-export([cnct2tstsrvr/1]).
+
+-define(AWAIT_SSL_NODE_UP_TIMEOUT, 30000).
+
+
+
+%% ssl_node side api
+%%
+
+tstsrvr_format(Fmt, ArgList) ->
+ send_to_tstsrvr({format, Fmt, ArgList}).
+
+send_to_tstcntrl(Message) ->
+ send_to_tstsrvr({message, Message}).
+
+
+%%
+%% test_server side api
+%%
+
+apply_on_ssl_node(
+ #node_handle{connection_handler = Hndlr} = Node,
+ M, F, A) when is_atom(M), is_atom(F), is_list(A) ->
+ Ref = erlang:monitor(process, Hndlr),
+ apply_on_ssl_node(Node, Ref, {apply, self(), Ref, M, F, A}).
+
+apply_on_ssl_node(
+ #node_handle{connection_handler = Hndlr} = Node,
+ Fun) when is_function(Fun, 0) ->
+ Ref = erlang:monitor(process, Hndlr),
+ apply_on_ssl_node(Node, Ref, {apply, self(), Ref, Fun}).
+
+apply_on_ssl_node(Node, Ref, Msg) ->
+ send_to_ssl_node(Node, Msg),
+ receive
+ {'DOWN', Ref, process, Hndlr, Reason} ->
+ exit({handler_died, Hndlr, Reason});
+ {Ref, Result} ->
+ Result
+ end.
+
+stop_ssl_node(#node_handle{connection_handler = Handler,
+ socket = Socket,
+ name = Name}) ->
+ ?t:format("Trying to stop ssl node ~s.~n", [Name]),
+ Mon = erlang:monitor(process, Handler),
+ unlink(Handler),
+ case gen_tcp:send(Socket, term_to_binary(stop)) of
+ ok ->
+ receive
+ {'DOWN', Mon, process, Handler, Reason} ->
+ case Reason of
+ normal ->
+ ok;
+ _ ->
+ ct:pal(
+ "stop_ssl_node/1 ~s Down ~p ~n",
+ [Name,Reason])
+ end
+ end;
+ Error ->
+ erlang:demonitor(Mon, [flush]),
+ ct:pal("stop_ssl_node/1 ~s Warning ~p ~n", [Name,Error])
+ end.
+
+start_ssl_node(Name, Args) ->
+ {ok, LSock} = gen_tcp:listen(0,
+ [binary, {packet, 4}, {active, false}]),
+ {ok, ListenPort} = inet:port(LSock),
+ CmdLine = mk_node_cmdline(ListenPort, Name, Args),
+ ?t:format("Attempting to start ssl node ~ts: ~ts~n", [Name, CmdLine]),
+ case open_port({spawn, CmdLine}, []) of
+ Port when is_port(Port) ->
+ unlink(Port),
+ erlang:port_close(Port),
+ case await_ssl_node_up(Name, LSock) of
+ #node_handle{} = NodeHandle ->
+ ?t:format("Ssl node ~s started.~n", [Name]),
+ NodeName = list_to_atom(Name ++ "@" ++ host_name()),
+ NodeHandle#node_handle{nodename = NodeName};
+ Error ->
+ exit({failed_to_start_node, Name, Error})
+ end;
+ Error ->
+ exit({failed_to_start_node, Name, Error})
+ end.
+
+host_name() ->
+ [_, Host] = string:split(atom_to_list(node()), "@"),
+ %% [$@ | Host] = lists:dropwhile(fun ($@) -> false; (_) -> true end,
+ %% atom_to_list(node())),
+ Host.
+
+mk_node_cmdline(ListenPort, Name, Args) ->
+ Static = "-detached -noinput",
+ Pa = filename:dirname(code:which(?MODULE)),
+ Prog = case catch init:get_argument(progname) of
+ {ok,[[P]]} -> P;
+ _ -> exit(no_progname_argument_found)
+ end,
+ NameSw = case net_kernel:longnames() of
+ false -> "-sname ";
+ _ -> "-name "
+ end,
+ {ok, Pwd} = file:get_cwd(),
+ "\"" ++ Prog ++ "\" "
+ ++ Static ++ " "
+ ++ NameSw ++ " " ++ Name ++ " "
+ ++ "-pa " ++ Pa ++ " "
+ ++ "-run application start crypto -run application start public_key "
+ ++ "-eval 'net_kernel:verbose(1)' "
+ ++ "-run " ++ atom_to_list(?MODULE) ++ " cnct2tstsrvr "
+ ++ host_name() ++ " "
+ ++ integer_to_list(ListenPort) ++ " "
+ ++ Args ++ " "
+ ++ "-env ERL_CRASH_DUMP " ++ Pwd ++ "/erl_crash_dump." ++ Name ++ " "
+ ++ "-kernel error_logger \"{file,\\\"" ++ Pwd ++ "/error_log." ++ Name ++ "\\\"}\" "
+ ++ "-setcookie " ++ atom_to_list(erlang:get_cookie()).
+
+%%
+%% Connection handler test_server side
+%%
+
+await_ssl_node_up(Name, LSock) ->
+ case gen_tcp:accept(LSock, ?AWAIT_SSL_NODE_UP_TIMEOUT) of
+ {ok, Socket} ->
+ gen_tcp:close(LSock),
+ case gen_tcp:recv(Socket, 0) of
+ {ok, Bin} ->
+ check_ssl_node_up(Socket, Name, Bin);
+ {error, closed} ->
+ gen_tcp:close(Socket),
+ exit({lost_connection_with_ssl_node_before_up, Name})
+ end;
+ {error, Error} ->
+ gen_tcp:close(LSock),
+ ?t:format("Accept failed for ssl node ~s: ~p~n", [Name,Error]),
+ exit({accept_failed, Error})
+ end.
+
+check_ssl_node_up(Socket, Name, Bin) ->
+ case catch binary_to_term(Bin) of
+ {'EXIT', _} ->
+ gen_tcp:close(Socket),
+ exit({bad_data_received_from_ssl_node, Name, Bin});
+ {ssl_node_up, NodeName} ->
+ case list_to_atom(Name++"@"++host_name()) of
+ NodeName ->
+ Parent = self(),
+ Go = make_ref(),
+ %% Spawn connection handler on test server side
+ Pid = spawn_link(
+ fun () ->
+ receive Go -> ok end,
+ process_flag(trap_exit, true),
+ tstsrvr_con_loop(Name, Socket, Parent)
+ end),
+ ok = gen_tcp:controlling_process(Socket, Pid),
+ Pid ! Go,
+ #node_handle{connection_handler = Pid,
+ socket = Socket,
+ name = Name};
+ _ ->
+ exit({unexpected_ssl_node_connected, NodeName})
+ end;
+ Msg ->
+ exit({unexpected_msg_instead_of_ssl_node_up, Name, Msg})
+ end.
+
+send_to_ssl_node(#node_handle{connection_handler = Hndlr}, Term) ->
+ Hndlr ! {relay_to_ssl_node, term_to_binary(Term)},
+ ok.
+
+tstsrvr_con_loop(Name, Socket, Parent) ->
+ ok = inet:setopts(Socket,[{active,once}]),
+ receive
+ {relay_to_ssl_node, Data} when is_binary(Data) ->
+ case gen_tcp:send(Socket, Data) of
+ ok ->
+ ok;
+ _Error ->
+ gen_tcp:close(Socket),
+ exit({failed_to_relay_data_to_ssl_node, Name, Data})
+ end;
+ {tcp, Socket, Bin} ->
+ try binary_to_term(Bin) of
+ {format, FmtStr, ArgList} ->
+ ?t:format(FmtStr, ArgList);
+ {message, Msg} ->
+ ?t:format("Got message ~p", [Msg]),
+ Parent ! Msg;
+ {apply_res, To, Ref, Res} ->
+ To ! {Ref, Res};
+ bye ->
+ {error, closed} = gen_tcp:recv(Socket, 0),
+ ?t:format("Ssl node ~s stopped.~n", [Name]),
+ gen_tcp:close(Socket),
+ exit(normal);
+ Unknown ->
+ exit({unexpected_message_from_ssl_node, Name, Unknown})
+ catch
+ error : _ ->
+ gen_tcp:close(Socket),
+ exit({bad_data_received_from_ssl_node, Name, Bin})
+ end;
+ {tcp_closed, Socket} ->
+ gen_tcp:close(Socket),
+ exit({lost_connection_with_ssl_node, Name});
+ {'EXIT', Parent, Reason} ->
+ exit({'EXIT', parent, Reason});
+ Unknown ->
+ exit({unknown, Unknown})
+ end,
+ tstsrvr_con_loop(Name, Socket, Parent).
+
+%%
+%% Connection handler ssl_node side
+%%
+
+% cnct2tstsrvr() is called via command line arg -run ...
+cnct2tstsrvr([Host, Port]) when is_list(Host), is_list(Port) ->
+ %% Spawn connection handler on ssl node side
+ ConnHandler
+ = spawn(fun () ->
+ case catch gen_tcp:connect(Host,
+ list_to_integer(Port),
+ [binary,
+ {packet, 4},
+ {active, false}]) of
+ {ok, Socket} ->
+ notify_ssl_node_up(Socket),
+ ets:new(test_server_info,
+ [set,
+ public,
+ named_table,
+ {keypos, 1}]),
+ ets:insert(test_server_info,
+ {test_server_handler, self()}),
+ ssl_node_con_loop(Socket);
+ Error ->
+ halt("Failed to connect to test server " ++
+ lists:flatten(io_lib:format("Host:~p ~n Port:~p~n Error:~p~n",
+ [Host, Port, Error])))
+ end
+ end),
+ spawn(fun () ->
+ Mon = erlang:monitor(process, ConnHandler),
+ receive
+ {'DOWN', Mon, process, ConnHandler, Reason} ->
+ receive after 1000 -> ok end,
+ halt("test server connection handler terminated: " ++
+ lists:flatten(io_lib:format("~p", [Reason])))
+ end
+ end).
+
+notify_ssl_node_up(Socket) ->
+ case catch gen_tcp:send(Socket,
+ term_to_binary({ssl_node_up, node()})) of
+ ok -> ok;
+ _ -> halt("Failed to notify test server that I'm up")
+ end.
+
+send_to_tstsrvr(Term) ->
+ case catch ets:lookup_element(test_server_info, test_server_handler, 2) of
+ Hndlr when is_pid(Hndlr) ->
+ Hndlr ! {relay_to_test_server, term_to_binary(Term)}, ok;
+ _ ->
+ receive after 200 -> ok end,
+ send_to_tstsrvr(Term)
+ end.
+
+ssl_node_con_loop(Socket) ->
+ inet:setopts(Socket,[{active,once}]),
+ receive
+ {relay_to_test_server, Data} when is_binary(Data) ->
+ case gen_tcp:send(Socket, Data) of
+ ok ->
+ ok;
+ _Error ->
+ gen_tcp:close(Socket),
+ halt("Failed to relay data to test server")
+ end;
+ {tcp, Socket, Bin} ->
+ case catch binary_to_term(Bin) of
+ {'EXIT', _} ->
+ gen_tcp:close(Socket),
+ halt("test server sent me bad data");
+ {apply, From, Ref, M, F, A} ->
+ spawn_link(
+ fun () ->
+ send_to_tstsrvr({apply_res,
+ From,
+ Ref,
+ (catch apply(M, F, A))})
+ end);
+ {apply, From, Ref, Fun} ->
+ spawn_link(fun () ->
+ send_to_tstsrvr({apply_res,
+ From,
+ Ref,
+ (catch Fun())})
+ end);
+ stop ->
+ gen_tcp:send(Socket, term_to_binary(bye)),
+ init:stop(),
+ receive after infinity -> ok end;
+ _Unknown ->
+ halt("test server sent me an unexpected message")
+ end;
+ {tcp_closed, Socket} ->
+ halt("Lost connection to test server")
+ end,
+ ssl_node_con_loop(Socket).
diff --git a/lib/ssl/test/ssl_dist_test_lib.hrl b/lib/ssl/test/ssl_dist_test_lib.hrl
new file mode 100644
index 0000000000..86b9b37026
--- /dev/null
+++ b/lib/ssl/test/ssl_dist_test_lib.hrl
@@ -0,0 +1,26 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-record(node_handle,
+ {connection_handler,
+ socket,
+ name,
+ nodename}
+ ).
diff --git a/lib/ssl/test/ssl_engine_SUITE.erl b/lib/ssl/test/ssl_engine_SUITE.erl
new file mode 100644
index 0000000000..1423c99dc2
--- /dev/null
+++ b/lib/ssl/test/ssl_engine_SUITE.erl
@@ -0,0 +1,162 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(ssl_engine_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() ->
+ [
+ private_key
+ ].
+
+init_per_suite(Config) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ case crypto:info_lib() of
+ [{_,_, <<"OpenSSL 1.0.1s-freebsd 1 Mar 2016">>}] ->
+ {skip, "Problem with engine on OpenSSL 1.0.1s-freebsd"};
+ _ ->
+ ssl_test_lib:clean_start(),
+ case crypto:get_test_engine() of
+ {ok, EngineName} ->
+ try crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, EngineName},
+ <<"LOAD">>],
+ []) of
+ {ok, Engine} ->
+ [{engine, Engine} |Config];
+ {error, Reason} ->
+ ct:pal("Reason ~p", [Reason]),
+ {skip, "No dynamic engine support"}
+ catch error:notsup ->
+ {skip, "No engine support in OpenSSL"}
+ end;
+ {error, notexist} ->
+ {skip, "Test engine not found"}
+ end
+ end
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(Config) ->
+ Engine = proplists:get_value(engine, Config),
+ crypto:engine_unload(Engine),
+ ssl:stop(),
+ application:stop(crypto).
+
+
+init_per_testcase(_TestCase, Config) ->
+ ssl:stop(),
+ ssl:start(),
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ ct:timetrap({seconds, 10}),
+ Config.
+
+end_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+private_key(Config) when is_list(Config) ->
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "client_engine"]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "server_engine"]),
+ #{server_config := ServerConf,
+ client_config := ClientConf} = GenCertData =
+ public_key:pkix_test_data(#{server_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
+ peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}
+ ]},
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(4)}],
+ intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)}]],
+ peer => [{key, ssl_test_lib:hardcode_rsa_key(6)}]}}),
+ [{server_config, FileServerConf},
+ {client_config, FileClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+
+ Engine = proplists:get_value(engine, Config),
+
+ ClientKey = engine_key(FileClientConf),
+ ServerKey = engine_key(FileServerConf),
+
+ EngineClientConf = [{key, #{algorithm => rsa,
+ engine => Engine,
+ key_id => ClientKey}} | proplists:delete(key, ClientConf)],
+
+ EngineServerConf = [{key, #{algorithm => rsa,
+ engine => Engine,
+ key_id => ServerKey}} | proplists:delete(key, ServerConf)],
+
+ EngineFileClientConf = [{key, #{algorithm => rsa,
+ engine => Engine,
+ key_id => ClientKey}} |
+ proplists:delete(keyfile, FileClientConf)],
+
+ EngineFileServerConf = [{key, #{algorithm => rsa,
+ engine => Engine,
+ key_id => ServerKey}} |
+ proplists:delete(keyfile, FileServerConf)],
+
+ %% Test with engine
+ test_tls_connection(EngineServerConf, EngineClientConf, Config),
+
+ %% Test with engine and present file arugments
+ test_tls_connection(EngineFileServerConf, EngineFileClientConf, Config),
+
+ %% Test that sofware fallback is available
+ test_tls_connection(ServerConf, [{reuse_sessions, false} |ClientConf], Config).
+
+engine_key(Conf) ->
+ FileStr = proplists:get_value(keyfile, Conf),
+ list_to_binary(FileStr).
+
+
+test_tls_connection(ServerConf, ClientConf, 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, [{verify, verify_peer}
+ | 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, send_recv_result_active, []}},
+ {options, [{verify, verify_peer} | ClientConf]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
diff --git a/lib/ssl/test/ssl_handshake_SUITE.erl b/lib/ssl/test/ssl_handshake_SUITE.erl
index 9658cb5f56..b8b9989d30 100644
--- a/lib/ssl/test/ssl_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_handshake_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,7 +33,6 @@
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
all() -> [decode_hello_handshake,
- decode_hello_handshake_version_confusion,
decode_single_hello_extension_correctly,
decode_supported_elliptic_curves_hello_extension_correctly,
decode_unknown_hello_extension_correctly,
@@ -41,7 +40,8 @@ all() -> [decode_hello_handshake,
decode_single_hello_sni_extension_correctly,
decode_empty_server_sni_correctly,
select_proper_tls_1_2_rsa_default_hashsign,
- ignore_hassign_extension_pre_tls_1_2].
+ ignore_hassign_extension_pre_tls_1_2,
+ unorded_chain].
%%--------------------------------------------------------------------
init_per_suite(Config) ->
@@ -101,20 +101,13 @@ decode_hello_handshake(_Config) ->
Version = {3, 0},
{Records, _Buffer} = tls_handshake:get_tls_handshake(Version, HelloPacket, <<>>,
- #ssl_options{v2_hello_compatible = false}),
+ #ssl_options{}),
{Hello, _Data} = hd(Records),
#renegotiation_info{renegotiated_connection = <<0>>}
= (Hello#server_hello.extensions)#hello_extensions.renegotiation_info.
-decode_hello_handshake_version_confusion(_) ->
- HelloPacket = <<3,3,0,0,0,0,0,63,210,235,149,6,244,140,108,13,177,74,16,218,33,108,219,41,73,228,3,82,132,123,73,144,118,100,0,0,32,192,4,0,10,192,45,192,38,0,47,192,18,0,163,0,22,0,165,192,29,192,18,192,30,0,103,0,57,192,48,0,47,1,0>>,
- Version = {3,3},
- ClientHello = 1,
- Hello = tls_handshake:decode_handshake({3,3}, ClientHello, HelloPacket, false),
- Hello = tls_handshake:decode_handshake({3,3}, ClientHello, HelloPacket, true).
-
decode_single_hello_extension_correctly(_Config) ->
Renegotiation = <<?UINT16(?RENEGOTIATION_EXT), ?UINT16(1), 0>>,
Extensions = ssl_handshake:decode_hello_extensions(Renegotiation),
@@ -157,7 +150,7 @@ decode_single_hello_sni_extension_correctly(_Config) ->
Exts = Decoded.
decode_empty_server_sni_correctly(_Config) ->
- Exts = #hello_extensions{sni = ""},
+ Exts = #hello_extensions{sni = #sni{hostname = ""}},
SNI = <<?UINT16(?SNI_EXT),?UINT16(0)>>,
Decoded = ssl_handshake:decode_hello_extensions(SNI),
Exts = Decoded.
@@ -181,6 +174,29 @@ ignore_hassign_extension_pre_tls_1_2(Config) ->
{md5sha, rsa} = ssl_handshake:select_hashsign(HashSigns, Cert, ecdhe_rsa, tls_v1:default_signature_algs({3,2}), {3,2}),
{md5sha, rsa} = ssl_handshake:select_hashsign(HashSigns, Cert, ecdhe_rsa, tls_v1:default_signature_algs({3,0}), {3,0}).
+unorded_chain(Config) when is_list(Config) ->
+ DefConf = ssl_test_lib:default_cert_chain_conf(),
+ CertChainConf = ssl_test_lib:gen_conf(rsa, rsa, DefConf, DefConf),
+ #{server_config := ServerConf,
+ client_config := _ClientConf} = public_key:pkix_test_data(CertChainConf),
+ PeerCert = proplists:get_value(cert, ServerConf),
+ CaCerts = [_, C1, C2] = proplists:get_value(cacerts, ServerConf),
+ {ok, ExtractedCerts} = ssl_pkix_db:extract_trusted_certs({der, CaCerts}),
+ UnordedChain = case public_key:pkix_is_self_signed(C1) of
+ true ->
+ [C1, C2];
+ false ->
+ [C2, C1]
+ end,
+ OrderedChain = [PeerCert | lists:reverse(UnordedChain)],
+ {ok, _, OrderedChain} =
+ ssl_certificate:certificate_chain(PeerCert, ets:new(foo, []), ExtractedCerts, UnordedChain).
+
+
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
+
is_supported(Hash) ->
Algos = crypto:supports(),
Hashs = proplists:get_value(hashs, Algos),
diff --git a/lib/ssl/test/ssl_npn_handshake_SUITE.erl b/lib/ssl/test/ssl_npn_handshake_SUITE.erl
index a02881f1ae..1c7d6b5f9f 100644
--- a/lib/ssl/test/ssl_npn_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_npn_handshake_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -95,8 +95,13 @@ init_per_group(GroupName, Config) ->
Config
end.
-end_per_group(_GroupName, Config) ->
- Config.
+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),
diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl
index 7281425461..3261244ace 100644
--- a/lib/ssl/test/ssl_packet_SUITE.erl
+++ b/lib/ssl/test/ssl_packet_SUITE.erl
@@ -53,28 +53,36 @@ all() ->
{group, 'tlsv1.2'},
{group, 'tlsv1.1'},
{group, 'tlsv1'},
- {group, 'sslv3'}
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
].
groups() ->
- [{'tlsv1.2', [], packet_tests()},
- {'tlsv1.1', [], packet_tests()},
- {'tlsv1', [], packet_tests()},
- {'sslv3', [], packet_tests()}
+ [{'tlsv1.2', [], socket_packet_tests() ++ protocol_packet_tests()},
+ {'tlsv1.1', [], socket_packet_tests() ++ protocol_packet_tests()},
+ {'tlsv1', [], socket_packet_tests() ++ protocol_packet_tests()},
+ {'sslv3', [], socket_packet_tests() ++ protocol_packet_tests()},
+ %% We will not support any packet types if the transport is
+ %% not reliable. We might support it for DTLS over SCTP in the future
+ {'dtlsv1.2', [], [reject_packet_opt]},
+ {'dtlsv1', [], [reject_packet_opt]}
].
-packet_tests() ->
- active_packet_tests() ++ active_once_packet_tests() ++ passive_packet_tests() ++
- [packet_send_to_large,
- packet_cdr_decode, packet_cdr_decode_list,
+socket_packet_tests() ->
+ socket_active_packet_tests() ++ socket_active_once_packet_tests() ++
+ socket_passive_packet_tests() ++ [packet_send_to_large, packet_tpkt_decode, packet_tpkt_decode_list].
+
+protocol_packet_tests() ->
+ protocol_active_packet_tests() ++ protocol_active_once_packet_tests() ++ protocol_passive_packet_tests() ++
+ [packet_cdr_decode, packet_cdr_decode_list,
packet_http_decode, packet_http_decode_list,
packet_http_bin_decode_multi,
packet_line_decode, packet_line_decode_list,
packet_asn1_decode, packet_asn1_decode_list,
- packet_tpkt_decode, packet_tpkt_decode_list,
packet_sunrm_decode, packet_sunrm_decode_list].
-passive_packet_tests() ->
+socket_passive_packet_tests() ->
[packet_raw_passive_many_small,
packet_0_passive_many_small,
packet_1_passive_many_small,
@@ -85,12 +93,8 @@ passive_packet_tests() ->
packet_1_passive_some_big,
packet_2_passive_some_big,
packet_4_passive_some_big,
- packet_httph_passive,
- packet_httph_bin_passive,
- packet_http_error_passive,
packet_wait_passive,
packet_size_passive,
- packet_baddata_passive,
%% inet header option should be deprecated!
header_decode_one_byte_passive,
header_decode_two_bytes_passive,
@@ -98,7 +102,14 @@ passive_packet_tests() ->
header_decode_two_bytes_one_sent_passive
].
-active_once_packet_tests() ->
+protocol_passive_packet_tests() ->
+ [packet_httph_passive,
+ packet_httph_bin_passive,
+ packet_http_error_passive,
+ packet_baddata_passive
+ ].
+
+socket_active_once_packet_tests() ->
[packet_raw_active_once_many_small,
packet_0_active_once_many_small,
packet_1_active_once_many_small,
@@ -108,12 +119,16 @@ active_once_packet_tests() ->
packet_0_active_once_some_big,
packet_1_active_once_some_big,
packet_2_active_once_some_big,
- packet_4_active_once_some_big,
+ packet_4_active_once_some_big
+ ].
+
+protocol_active_once_packet_tests() ->
+ [
packet_httph_active_once,
packet_httph_bin_active_once
].
-active_packet_tests() ->
+socket_active_packet_tests() ->
[packet_raw_active_many_small,
packet_0_active_many_small,
packet_1_active_many_small,
@@ -124,10 +139,7 @@ active_packet_tests() ->
packet_1_active_some_big,
packet_2_active_some_big,
packet_4_active_some_big,
- packet_httph_active,
- packet_httph_bin_active,
packet_wait_active,
- packet_baddata_active,
packet_size_active,
%% inet header option should be deprecated!
header_decode_one_byte_active,
@@ -136,6 +148,13 @@ active_packet_tests() ->
header_decode_two_bytes_one_sent_active
].
+
+protocol_active_packet_tests() ->
+ [packet_httph_active,
+ packet_httph_bin_active,
+ packet_baddata_active
+ ].
+
init_per_suite(Config) ->
catch crypto:stop(),
try crypto:start() of
@@ -168,8 +187,13 @@ init_per_group(GroupName, Config) ->
end.
-end_per_group(_GroupName, Config) ->
- Config.
+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, ?BASE_TIMEOUT_SECONDS}),
@@ -1902,6 +1926,25 @@ header_decode_two_bytes_one_sent_passive(Config) when is_list(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
+reject_packet_opt() ->
+ [{doc,"Test packet option is rejected for DTLS over udp"}].
+
+reject_packet_opt(Config) when is_list(Config) ->
+
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+
+ {error,{options,{not_supported,{packet,4}}}} =
+ ssl:listen(9999, [{packet, 4} | ServerOpts]),
+ {error,{options,{not_supported,{packet_size,1}}}} =
+ ssl:listen(9999, [{packet_size, 1} | ServerOpts]),
+ {error,{options,{not_supported,{header,1}}}} =
+ ssl:listen(9999, [{header, 1} | ServerOpts]),
+
+ client_reject_packet_opt(Config, {packet,4}),
+ client_reject_packet_opt(Config, {packet_size, 1}),
+ client_reject_packet_opt(Config, {header, 1}).
+
+%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
@@ -2223,3 +2266,23 @@ add_tpkt_header(IOList) when is_list(IOList) ->
Binary = list_to_binary(IOList),
L = size(Binary) + 4,
[3, 0, ((L) bsr 8) band 16#ff, (L) band 16#ff , Binary].
+
+
+client_reject_packet_opt(Config, PacketOpt) ->
+ 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, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result_msg ,[]}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client_error([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result_msg, []}},
+ {options, [PacketOpt |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Client, {error, {options, {not_supported, PacketOpt}}}).
diff --git a/lib/ssl/test/ssl_payload_SUITE.erl b/lib/ssl/test/ssl_payload_SUITE.erl
index cb1957327a..5939800001 100644
--- a/lib/ssl/test/ssl_payload_SUITE.erl
+++ b/lib/ssl/test/ssl_payload_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -95,8 +95,13 @@ init_per_group(GroupName, Config) ->
Config
end.
-end_per_group(_GroupName, Config) ->
- Config.
+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 == server_echos_passive_huge;
TestCase == server_echos_active_once_huge;
diff --git a/lib/ssl/test/ssl_pem_cache_SUITE.erl b/lib/ssl/test/ssl_pem_cache_SUITE.erl
index 96b15d9b51..25d2cb300d 100644
--- a/lib/ssl/test/ssl_pem_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_pem_cache_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
all() ->
- [pem_cleanup].
+ [pem_cleanup, invalid_insert].
groups() ->
[].
@@ -68,6 +68,10 @@ init_per_testcase(pem_cleanup = Case, Config) ->
application:set_env(ssl, ssl_pem_cache_clean, ?CLEANUP_INTERVAL),
ssl:start(),
ct:timetrap({minutes, 1}),
+ Config;
+init_per_testcase(_, Config) ->
+ ssl:start(),
+ ct:timetrap({seconds, 5}),
Config.
end_per_testcase(_TestCase, Config) ->
@@ -108,7 +112,34 @@ pem_cleanup(Config)when is_list(Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client),
false = Size == Size1.
-
+
+invalid_insert() ->
+ [{doc, "Test that insert of invalid pem does not cause empty cache entry"}].
+invalid_insert(Config)when is_list(Config) ->
+ process_flag(trap_exit, true),
+
+ ClientOpts = proplists:get_value(client_verification_opts, Config),
+ ServerOpts = proplists:get_value(server_verification_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ BadClientOpts = [{cacertfile, "tmp/does_not_exist.pem"} | proplists:delete(cacertfile, ClientOpts)],
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ ssl_test_lib:start_client_error([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {from, self()}, {options, BadClientOpts}]),
+ ssl_test_lib:close(Server),
+ 1 = ssl_pkix_db:db_size(get_fileref_db()).
+
+
+
+%%--------------------------------------------------------------------
+%% Internal funcations
+%%--------------------------------------------------------------------
+
get_pem_cache() ->
{status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
[_, _,_, _, Prop] = StatusInfo,
@@ -120,6 +151,16 @@ get_pem_cache() ->
undefined
end.
+get_fileref_db() ->
+ {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = ssl_test_lib:state(Prop),
+ case element(6, State) of
+ [_CertDb, {FileRefDb,_} | _] ->
+ FileRefDb;
+ _ ->
+ undefined
+ end.
later()->
DateTime = calendar:now_to_local_time(os:timestamp()),
Gregorian = calendar:datetime_to_gregorian_seconds(DateTime),
diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl
index 9862b3ce64..a0fab58b9d 100644
--- a/lib/ssl/test/ssl_session_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_session_cache_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -487,8 +487,8 @@ test_copts(_, 0, ClientOpts) ->
ClientOpts;
test_copts(max_table_size, N, ClientOpts) ->
Version = tls_record:highest_protocol_version([]),
- CipherSuites = %%lists:map(fun(X) -> ssl_cipher:suite_definition(X) end, ssl_cipher:filter_suites(ssl_cipher:suites(Version))),
-[ Y|| Y = {Alg,_, _, _} <- lists:map(fun(X) -> ssl_cipher:suite_definition(X) end, ssl_cipher:filter_suites(ssl_cipher:suites(Version))), Alg =/= ecdhe_ecdsa, Alg =/= ecdh_ecdsa, Alg =/= ecdh_rsa, Alg =/= ecdhe_rsa, Alg =/= dhe_dss, Alg =/= dss],
+ CipherSuites = %%lists:map(fun(X) -> ssl_cipher_format:suite_definition(X) end, ssl_cipher:filter_suites(ssl_cipher:suites(Version))),
+[ Y|| Y = {Alg,_, _, _} <- lists:map(fun(X) -> ssl_cipher_format:suite_definition(X) end, ssl_cipher:filter_suites(ssl_cipher:suites(Version))), Alg =/= ecdhe_ecdsa, Alg =/= ecdh_ecdsa, Alg =/= ecdh_rsa, Alg =/= ecdhe_rsa, Alg =/= dhe_dss, Alg =/= dss],
case length(CipherSuites) of
M when M >= N ->
Cipher = lists:nth(N, CipherSuites),
diff --git a/lib/ssl/test/ssl_sni_SUITE.erl b/lib/ssl/test/ssl_sni_SUITE.erl
index 4e916a7f03..251b6a2639 100644
--- a/lib/ssl/test/ssl_sni_SUITE.erl
+++ b/lib/ssl/test/ssl_sni_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,26 +25,61 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("public_key/include/public_key.hrl").
+-include_lib("kernel/include/inet.hrl").
+
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
-all() -> [no_sni_header,
- sni_match,
- sni_no_match,
- no_sni_header_fun,
- sni_match_fun,
- sni_no_match_fun].
+all() ->
+ [{group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
+ ].
+
+groups() ->
+ [
+ {'tlsv1.2', [], sni_tests()},
+ {'tlsv1.1', [], sni_tests()},
+ {'tlsv1', [], sni_tests()},
+ {'sslv3', [], sni_tests()},
+ {'dtlsv1.2', [], sni_tests()},
+ {'dtlsv1', [], sni_tests()}
+ ].
+
+sni_tests() ->
+ [no_sni_header,
+ sni_match,
+ sni_no_match,
+ no_sni_header_fun,
+ sni_match_fun,
+ sni_no_match_fun,
+ dns_name,
+ ip_fallback,
+ no_ip_fallback,
+ dns_name_reuse].
init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
ssl_test_lib:clean_start(),
- {ok, _} = make_certs:all(proplists:get_value(data_dir, Config0),
- proplists:get_value(priv_dir, Config0)),
- ssl_test_lib:cert_options(Config0)
+ 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.
@@ -53,6 +88,13 @@ 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 ->
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ ct:log("Ciphers: ~p~n ", [ ssl:cipher_suites()]),
+ ct:timetrap({seconds, 20}),
+ Config;
init_per_testcase(_TestCase, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:log("Ciphers: ~p~n ", [ ssl:cipher_suites()]),
@@ -66,24 +108,136 @@ end_per_testcase(_TestCase, Config) ->
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
no_sni_header(Config) ->
- run_handshake(Config, undefined, undefined, "server").
+ run_handshake(Config, undefined, undefined, "server Peer cert").
no_sni_header_fun(Config) ->
- run_sni_fun_handshake(Config, undefined, undefined, "server").
+ run_sni_fun_handshake(Config, undefined, undefined, "server Peer cert").
sni_match(Config) ->
- run_handshake(Config, "a.server", "a.server", "a.server").
+ run_handshake(Config, "a.server", "a.server", "server Peer cert").
sni_match_fun(Config) ->
- run_sni_fun_handshake(Config, "a.server", "a.server", "a.server").
+ run_sni_fun_handshake(Config, "a.server", "a.server", "server Peer cert").
sni_no_match(Config) ->
- run_handshake(Config, "c.server", undefined, "server").
+ run_handshake(Config, "c.server", undefined, "server Peer cert").
sni_no_match_fun(Config) ->
- run_sni_fun_handshake(Config, "c.server", undefined, "server").
+ run_sni_fun_handshake(Config, "c.server", undefined, "server Peer cert").
+
+dns_name(Config) ->
+ Hostname = "OTP.test.server",
+ #{server_config := ServerConf,
+ client_config := ClientConf} = public_key:pkix_test_data(#{server_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
+ peer => [{extensions, [#'Extension'{extnID =
+ ?'id-ce-subjectAltName',
+ extnValue = [{dNSName, Hostname}],
+ critical = false}]},
+ {key, ssl_test_lib:hardcode_rsa_key(3)}]},
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(4)}],
+ intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)}]],
+ peer => [{key, ssl_test_lib:hardcode_rsa_key(6)}]}}),
+ unsuccessfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], undefined, Config),
+ successfull_connect(ServerConf, [{verify, verify_peer}, {server_name_indication, Hostname} | ClientConf], undefined, Config),
+ unsuccessfull_connect(ServerConf, [{verify, verify_peer}, {server_name_indication, "foo"} | ClientConf], undefined, Config),
+ successfull_connect(ServerConf, [{verify, verify_peer}, {server_name_indication, disable} | ClientConf], undefined, Config).
+
+ip_fallback(Config) ->
+ Hostname = net_adm:localhost(),
+ {ok, #hostent{h_addr_list = [IP |_]}} = inet:gethostbyname(net_adm:localhost()),
+ IPStr = tuple_to_list(IP),
+ #{server_config := ServerConf,
+ client_config := ClientConf} = public_key:pkix_test_data(#{server_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
+ peer => [{extensions, [#'Extension'{extnID =
+ ?'id-ce-subjectAltName',
+ extnValue = [{dNSName, Hostname},
+ {iPAddress, IPStr}],
+ critical = false}]},
+ {key, ssl_test_lib:hardcode_rsa_key(3)}]},
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(4)}],
+ intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)}]],
+ peer => [{key, ssl_test_lib:hardcode_rsa_key(6)}]}}),
+ successfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], Hostname, Config),
+ successfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], IP, Config).
+no_ip_fallback(Config) ->
+ Hostname = net_adm:localhost(),
+ {ok, #hostent{h_addr_list = [IP |_]}} = inet:gethostbyname(net_adm:localhost()),
+ #{server_config := ServerConf,
+ client_config := ClientConf} = public_key:pkix_test_data(#{server_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
+ peer => [{extensions, [#'Extension'{extnID =
+ ?'id-ce-subjectAltName',
+ extnValue = [{dNSName, Hostname}],
+ critical = false}]},
+ {key, ssl_test_lib:hardcode_rsa_key(3)}
+ ]},
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(4)}],
+ intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)}]],
+ peer => [{key, ssl_test_lib:hardcode_rsa_key(6)}]}}),
+ successfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], Hostname, Config),
+ unsuccessfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], IP, Config).
+dns_name_reuse(Config) ->
+ SNIHostname = "OTP.test.server",
+ #{server_config := ServerConf,
+ client_config := ClientConf} = public_key:pkix_test_data(#{server_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
+ peer => [{extensions, [#'Extension'{extnID =
+ ?'id-ce-subjectAltName',
+ extnValue = [{dNSName, SNIHostname}],
+ critical = false}
+ ]},
+ {key, ssl_test_lib:hardcode_rsa_key(3)}
+ ]},
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(4)}],
+ intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)}]],
+ peer => [{key, ssl_test_lib:hardcode_rsa_key(6)}]}}),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ unsuccessfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], undefined, Config),
+
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, session_info_result, []}},
+ {options, ServerConf}]),
+ 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, [{verify, verify_peer},
+ {server_name_indication, SNIHostname} | ClientConf]}]),
+ receive
+ {Server, _} ->
+ ok
+ end,
+
+ Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}},
+
+ %% Make sure session is registered
+ ct:sleep(1000),
+
+ Client1 =
+ ssl_test_lib:start_client_error([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_info_result, []}},
+ {from, self()}, {options, [{verify, verify_peer} | ClientConf]}]),
+
+ ssl_test_lib:check_result(Client1, {error, {tls_alert, "handshake failure"}}),
+ ssl_test_lib:close(Client0).
%%--------------------------------------------------------------------
%% Internal Functions ------------------------------------------------
%%--------------------------------------------------------------------
@@ -141,13 +295,13 @@ run_sni_fun_handshake(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) ->
[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_opts, Config) ++ [{sni_fun, SNIFun}],
+ ServerOptions = ssl_test_lib:ssl_options(server_rsa_opts, Config) ++ [{sni_fun, SNIFun}],
ClientOptions =
case SNIHostname of
undefined ->
- proplists:get_value(client_opts, Config);
+ ssl_test_lib:ssl_options(client_rsa_opts, Config);
_ ->
- [{server_name_indication, SNIHostname}] ++ proplists:get_value(client_opts, Config)
+ [{server_name_indication, SNIHostname}] ++ ssl_test_lib:ssl_options(client_rsa_opts, Config)
end,
ct:log("Options: ~p", [[ServerOptions, ClientOptions]]),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -167,14 +321,14 @@ run_handshake(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) ->
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_opts, Config),
+ ServerOptions = proplists:get_value(sni_server_opts, Config) ++ ssl_test_lib:ssl_options(server_rsa_opts, Config),
ClientOptions =
- case SNIHostname of
- undefined ->
- proplists:get_value(client_opts, Config);
- _ ->
- [{server_name_indication, SNIHostname}] ++ proplists:get_value(client_opts, Config)
- end,
+ case SNIHostname of
+ undefined ->
+ ssl_test_lib:ssl_options(client_rsa_opts, Config);
+ _ ->
+ [{server_name_indication, SNIHostname}] ++ ssl_test_lib:ssl_options(client_rsa_opts, Config)
+ end,
ct:log("Options: ~p", [[ServerOptions, ClientOptions]]),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
@@ -188,3 +342,37 @@ run_handshake(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) ->
ssl_test_lib:check_result(Server, ExpectedSNIHostname, Client, ExpectedCN),
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+
+successfull_connect(ServerOptions, ClientOptions, Hostname0, Config) ->
+ {ClientNode, ServerNode, Hostname1} = ssl_test_lib:run_where(Config),
+ Hostname = host_name(Hostname0, Hostname1),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()}, {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, ServerOptions}]),
+ 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, ClientOptions}]),
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+unsuccessfull_connect(ServerOptions, ClientOptions, Hostname0, Config) ->
+ {ClientNode, ServerNode, Hostname1} = ssl_test_lib:run_where(Config),
+ Hostname = host_name(Hostname0, Hostname1),
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {options, ServerOptions}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {options, ClientOptions}]),
+
+ ssl_test_lib:check_result(Server, {error, {tls_alert, "handshake failure"}},
+ Client, {error, {tls_alert, "handshake failure"}}).
+host_name(undefined, Hostname) ->
+ Hostname;
+host_name(Hostname, _) ->
+ Hostname.
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index 77c21d9b57..39a5bcaad6 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -79,17 +79,21 @@ run_server(ListenSocket, Opts, N) ->
Pid ! {accepter, N, Server},
run_server(ListenSocket, Opts, N-1).
-do_run_server(_, {error, timeout} = Result, Opts) ->
+do_run_server(_, {error, _} = Result, Opts) ->
+ ct:log("Server error result ~p~n", [Result]),
+ Pid = proplists:get_value(from, Opts),
+ Pid ! {self(), Result};
+do_run_server(_, ok = Result, Opts) ->
+ ct:log("Server cancel result ~p~n", [Result]),
Pid = proplists:get_value(from, Opts),
Pid ! {self(), Result};
-
do_run_server(ListenSocket, AcceptSocket, Opts) ->
Node = proplists:get_value(node, Opts),
Pid = proplists:get_value(from, Opts),
Transport = proplists:get_value(transport, Opts, ssl),
{Module, Function, Args} = proplists:get_value(mfa, Opts),
ct:log("~p:~p~nServer: apply(~p,~p,~p)~n",
- [?MODULE,?LINE, Module, Function, [AcceptSocket | Args]]),
+ [?MODULE,?LINE, Module, Function, [AcceptSocket | Args]]),
case rpc:call(Node, Module, Function, [AcceptSocket | Args]) of
no_result_msg ->
ok;
@@ -117,7 +121,8 @@ connect(#sslsocket{} = ListenSocket, Opts) ->
ReconnectTimes = proplists:get_value(reconnect_times, Opts, 0),
Timeout = proplists:get_value(timeout, Opts, infinity),
SslOpts = proplists:get_value(ssl_extra_opts, Opts, []),
- AcceptSocket = connect(ListenSocket, Node, 1 + ReconnectTimes, dummy, Timeout, SslOpts),
+ ContOpts = proplists:get_value(continue_options, Opts, []),
+ AcceptSocket = connect(ListenSocket, Node, 1 + ReconnectTimes, dummy, Timeout, SslOpts, ContOpts),
case ReconnectTimes of
0 ->
AcceptSocket;
@@ -132,10 +137,45 @@ connect(ListenSocket, Opts) ->
[ListenSocket]),
AcceptSocket.
-connect(_, _, 0, AcceptSocket, _, _) ->
+connect(_, _, 0, AcceptSocket, _, _, _) ->
AcceptSocket;
-
-connect(ListenSocket, Node, N, _, Timeout, []) ->
+connect(ListenSocket, Node, _N, _, Timeout, SslOpts, cancel) ->
+ ct:log("ssl:transport_accept(~p)~n", [ListenSocket]),
+ {ok, AcceptSocket} = rpc:call(Node, ssl, transport_accept,
+ [ListenSocket]),
+ ct:log("~p:~p~nssl:handshake(~p,~p,~p)~n", [?MODULE,?LINE, AcceptSocket, SslOpts,Timeout]),
+
+ case rpc:call(Node, ssl, handshake, [AcceptSocket, SslOpts, Timeout]) of
+ {ok, Socket0, Ext} ->
+ ct:log("Ext ~p:~n", [Ext]),
+ ct:log("~p:~p~nssl:handshake_cancel(~p)~n", [?MODULE,?LINE, Socket0]),
+ rpc:call(Node, ssl, handshake_cancel, [Socket0]);
+ Result ->
+ ct:log("~p:~p~nssl:handshake@~p ret ~p",[?MODULE,?LINE, Node,Result]),
+ Result
+ end;
+connect(ListenSocket, Node, N, _, Timeout, SslOpts, [_|_] =ContOpts) ->
+ ct:log("ssl:transport_accept(~p)~n", [ListenSocket]),
+ {ok, AcceptSocket} = rpc:call(Node, ssl, transport_accept,
+ [ListenSocket]),
+ ct:log("~p:~p~nssl:handshake(~p,~p,~p)~n", [?MODULE,?LINE, AcceptSocket, SslOpts,Timeout]),
+
+ case rpc:call(Node, ssl, handshake, [AcceptSocket, SslOpts, Timeout]) of
+ {ok, Socket0, Ext} ->
+ ct:log("Ext ~p:~n", [Ext]),
+ ct:log("~p:~p~nssl:handshake_continue(~p,~p,~p)~n", [?MODULE,?LINE, Socket0, ContOpts,Timeout]),
+ case rpc:call(Node, ssl, handshake_continue, [Socket0, ContOpts, Timeout]) of
+ {ok, Socket} ->
+ connect(ListenSocket, Node, N-1, Socket, Timeout, SslOpts, ContOpts);
+ Error ->
+ ct:log("~p:~p~nssl:handshake_continue@~p ret ~p",[?MODULE,?LINE, Node,Error]),
+ Error
+ end;
+ Result ->
+ ct:log("~p:~p~nssl:handshake@~p ret ~p",[?MODULE,?LINE, Node,Result]),
+ Result
+ end;
+connect(ListenSocket, Node, N, _, Timeout, [], ContOpts) ->
ct:log("ssl:transport_accept(~p)~n", [ListenSocket]),
{ok, AcceptSocket} = rpc:call(Node, ssl, transport_accept,
[ListenSocket]),
@@ -143,12 +183,12 @@ connect(ListenSocket, Node, N, _, Timeout, []) ->
case rpc:call(Node, ssl, ssl_accept, [AcceptSocket, Timeout]) of
ok ->
- connect(ListenSocket, Node, N-1, AcceptSocket, Timeout, []);
+ connect(ListenSocket, Node, N-1, AcceptSocket, Timeout, [], ContOpts);
Result ->
ct:log("~p:~p~nssl:ssl_accept@~p ret ~p",[?MODULE,?LINE, Node,Result]),
Result
end;
-connect(ListenSocket, Node, _, _, Timeout, Opts) ->
+connect(ListenSocket, Node, _, _, Timeout, Opts, _) ->
ct:log("ssl:transport_accept(~p)~n", [ListenSocket]),
{ok, AcceptSocket} = rpc:call(Node, ssl, transport_accept,
[ListenSocket]),
@@ -187,8 +227,17 @@ run_client(Opts) ->
Pid = proplists:get_value(from, Opts),
Transport = proplists:get_value(transport, Opts, ssl),
Options = proplists:get_value(options, Opts),
+ ContOpts = proplists:get_value(continue_options, Opts, []),
ct:log("~p:~p~n~p:connect(~p, ~p)@~p~n", [?MODULE,?LINE, Transport, Host, Port, Node]),
ct:log("SSLOpts: ~p", [Options]),
+ case ContOpts of
+ [] ->
+ client_loop(Node, Host, Port, Pid, Transport, Options, Opts);
+ _ ->
+ client_cont_loop(Node, Host, Port, Pid, Transport, Options, ContOpts, Opts)
+ end.
+
+client_loop(Node, Host, Port, Pid, Transport, Options, Opts) ->
case rpc:call(Node, Transport, connect, [Host, Port, Options]) of
{ok, Socket} ->
Pid ! {connected, Socket},
@@ -245,6 +294,40 @@ run_client(Opts) ->
Pid ! {connect_failed, {badrpc,BadRPC}}
end.
+client_cont_loop(Node, Host, Port, Pid, Transport, Options, cancel, _Opts) ->
+ case rpc:call(Node, Transport, connect, [Host, Port, Options]) of
+ {ok, Socket, _} ->
+ Result = rpc:call(Node, Transport, handshake_cancel, [Socket]),
+ ct:log("~p:~p~nClient: Cancel: ~p ~n", [?MODULE,?LINE, Result]),
+ Pid ! {connect_failed, Result};
+ {error, Reason} ->
+ ct:log("~p:~p~nClient: connection failed: ~p ~n", [?MODULE,?LINE, Reason]),
+ Pid ! {connect_failed, Reason}
+ end;
+
+client_cont_loop(Node, Host, Port, Pid, Transport, Options, ContOpts, Opts) ->
+ case rpc:call(Node, Transport, connect, [Host, Port, Options]) of
+ {ok, Socket0, _} ->
+ ct:log("~p:~p~nClient: handshake_continue(~p, ~p, infinity) ~n", [?MODULE, ?LINE, Socket0, ContOpts]),
+ case rpc:call(Node, Transport, handshake_continue, [Socket0, ContOpts]) of
+ {ok, Socket} ->
+ Pid ! {connected, Socket},
+ {Module, Function, Args} = proplists:get_value(mfa, Opts),
+ ct:log("~p:~p~nClient: apply(~p,~p,~p)~n",
+ [?MODULE,?LINE, Module, Function, [Socket | Args]]),
+ case rpc:call(Node, Module, Function, [Socket | Args]) of
+ no_result_msg ->
+ ok;
+ Msg ->
+ ct:log("~p:~p~nClient Msg: ~p ~n", [?MODULE,?LINE, Msg]),
+ Pid ! {self(), Msg}
+ end
+ end;
+ {error, Reason} ->
+ ct:log("~p:~p~nClient: connection failed: ~p ~n", [?MODULE,?LINE, Reason]),
+ Pid ! {connect_failed, Reason}
+ end.
+
close(Pid) ->
ct:log("~p:~p~nClose ~p ~n", [?MODULE,?LINE, Pid]),
Monitor = erlang:monitor(process, Pid),
@@ -384,10 +467,6 @@ cert_options(Config) ->
"badkey.pem"]),
PskSharedSecret = <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
- SNIServerACertFile = filename:join([proplists:get_value(priv_dir, Config), "a.server", "cert.pem"]),
- SNIServerAKeyFile = filename:join([proplists:get_value(priv_dir, Config), "a.server", "key.pem"]),
- SNIServerBCertFile = filename:join([proplists:get_value(priv_dir, Config), "b.server", "cert.pem"]),
- SNIServerBKeyFile = filename:join([proplists:get_value(priv_dir, Config), "b.server", "key.pem"]),
[{client_opts, [{cacertfile, ClientCaCertFile},
{certfile, ClientCertFile},
{keyfile, ClientKeyFile}]},
@@ -445,52 +524,42 @@ cert_options(Config) ->
{server_bad_cert, [{ssl_imp, new},{cacertfile, ServerCaCertFile},
{certfile, BadCertFile}, {keyfile, ServerKeyFile}]},
{server_bad_key, [{ssl_imp, new},{cacertfile, ServerCaCertFile},
- {certfile, ServerCertFile}, {keyfile, BadKeyFile}]},
- {sni_server_opts, [{sni_hosts, [
- {"a.server", [
- {certfile, SNIServerACertFile},
- {keyfile, SNIServerAKeyFile}
- ]},
- {"b.server", [
- {certfile, SNIServerBCertFile},
- {keyfile, SNIServerBKeyFile}
- ]}
- ]}]}
+ {certfile, ServerCertFile}, {keyfile, BadKeyFile}]}
| Config].
-make_dsa_cert(Config) ->
- {ServerCaCertFile, ServerCertFile, ServerKeyFile} =
- make_cert_files("server", Config, dsa, dsa, "", []),
- {ClientCaCertFile, ClientCertFile, ClientKeyFile} =
- make_cert_files("client", Config, dsa, dsa, "", []),
- [{server_dsa_opts, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ServerCaCertFile},
- {certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
- {server_dsa_verify_opts, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ClientCaCertFile},
- {certfile, ServerCertFile}, {keyfile, ServerKeyFile},
- {verify, verify_peer}]},
- {client_dsa_opts, [{ssl_imp, new},
- {cacertfile, ClientCaCertFile},
- {certfile, ClientCertFile}, {keyfile, ClientKeyFile}]},
- {server_srp_dsa, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ServerCaCertFile},
- {certfile, ServerCertFile}, {keyfile, ServerKeyFile},
- {user_lookup_fun, {fun user_lookup/3, undefined}},
- {ciphers, srp_dss_suites()}]},
- {client_srp_dsa, [{ssl_imp, new},
- {srp_identity, {"Test-User", "secret"}},
- {cacertfile, ClientCaCertFile},
- {certfile, ClientCertFile}, {keyfile, ClientKeyFile}]}
- | Config].
-
-make_rsa_cert_chains(ChainConf, Config, Suffix) ->
- CryptoSupport = crypto:supports(),
- KeyGenSpec = key_gen_info(rsa, rsa),
+make_dsa_cert(Config) ->
+ CryptoSupport = crypto:supports(),
+ case proplists:get_bool(dss, proplists:get_value(public_keys, CryptoSupport)) of
+ true ->
+ ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()),
+ ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()),
+ CertChainConf = gen_conf(dsa, dsa, ClientChain, ServerChain),
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "dsa"]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "dsa"]),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
+ [{server_config, ServerConf},
+ {client_config, ClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+
+ [{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]}
+ | Config];
+ false ->
+ Config
+ end.
+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()),
+ CertChainConf = gen_conf(rsa, rsa, ClientChain, ServerChain),
ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa" ++ Suffix]),
ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa" ++ Suffix]),
- GenCertData = x509_test:gen_test_certs([{digest, appropriate_sha(CryptoSupport)} | KeyGenSpec] ++ ChainConf),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
[{server_config, ServerConf},
{client_config, ClientConf}] =
x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
@@ -498,12 +567,13 @@ make_rsa_cert_chains(ChainConf, Config, Suffix) ->
[{reuseaddr, true}, {verify, verify_peer} | ServerConf]
}.
-make_ec_cert_chains(ChainConf, ClientChainType, ServerChainType, Config) ->
- CryptoSupport = crypto:supports(),
- KeyGenSpec = key_gen_info(ClientChainType, ServerChainType),
+make_ec_cert_chains(UserConf, ClientChainType, ServerChainType, Config) ->
+ ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()),
+ ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()),
+ CertChainConf = gen_conf(ClientChainType, ServerChainType, ClientChain, ServerChain),
ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ClientChainType)]),
ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ServerChainType)]),
- GenCertData = x509_test:gen_test_certs([{digest, appropriate_sha(CryptoSupport)} | KeyGenSpec] ++ ChainConf),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
[{server_config, ServerConf},
{client_config, ClientConf}] =
x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
@@ -511,51 +581,150 @@ make_ec_cert_chains(ChainConf, ClientChainType, ServerChainType, Config) ->
[{reuseaddr, true}, {verify, verify_peer} | ServerConf]
}.
-key_gen_info(ClientChainType, ServerChainType) ->
- key_gen_spec("client", ClientChainType) ++ key_gen_spec("server", ServerChainType).
+default_cert_chain_conf() ->
+ %% Use only default options
+ [[],[],[]].
+
+gen_conf(mix, mix, UserClient, UserServer) ->
+ ClientTag = conf_tag("client"),
+ ServerTag = conf_tag("server"),
-key_gen_spec(Role, ecdh_rsa) ->
+ DefaultClient = default_cert_chain_conf(),
+ DefaultServer = default_cert_chain_conf(),
+
+ ClientConf = merge_chain_spec(UserClient, DefaultClient, []),
+ ServerConf = merge_chain_spec(UserServer, DefaultServer, []),
+
+ new_format([{ClientTag, ClientConf}, {ServerTag, ServerConf}]);
+gen_conf(ClientChainType, ServerChainType, UserClient, UserServer) ->
+ ClientTag = conf_tag("client"),
+ ServerTag = conf_tag("server"),
+
+ DefaultClient = chain_spec(client, ClientChainType),
+ DefaultServer = chain_spec(server, ServerChainType),
+
+ ClientConf = merge_chain_spec(UserClient, DefaultClient, []),
+ ServerConf = merge_chain_spec(UserServer, DefaultServer, []),
+
+ new_format([{ClientTag, ClientConf}, {ServerTag, ServerConf}]).
+
+new_format(Conf) ->
+ CConf = proplists:get_value(client_chain, Conf),
+ SConf = proplists:get_value(server_chain, Conf),
+ #{server_chain => proplist_to_map(SConf),
+ client_chain => proplist_to_map(CConf)}.
+
+proplist_to_map([Head | Rest]) ->
+ [Last | Tail] = lists:reverse(Rest),
+ #{root => Head,
+ intermediates => lists:reverse(Tail),
+ peer => Last}.
+
+conf_tag(Role) ->
+ list_to_atom(Role ++ "_chain").
+
+chain_spec(_Role, ecdh_rsa) ->
+ Digest = {digest, appropriate_sha(crypto:supports())},
CurveOid = hd(tls_v1:ecc_curves(0)),
- [{list_to_atom(Role ++ "_key_gen"), {namedCurve, CurveOid}},
- {list_to_atom(Role ++ "_key_gen_chain"), [hardcode_rsa_key(1),
- {namedCurve, CurveOid}]}
- ];
-key_gen_spec(Role, ecdhe_ecdsa) ->
+ [[Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, hardcode_rsa_key(1)}],
+ [Digest, {key, {namedCurve, CurveOid}}]];
+
+chain_spec(_Role, ecdhe_ecdsa) ->
+ Digest = {digest, appropriate_sha(crypto:supports())},
+ CurveOid = hd(tls_v1:ecc_curves(0)),
+ [[Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, {namedCurve, CurveOid}}]];
+
+chain_spec(_Role, ecdh_ecdsa) ->
+ Digest = {digest, appropriate_sha(crypto:supports())},
CurveOid = hd(tls_v1:ecc_curves(0)),
- [{list_to_atom(Role ++ "_key_gen"), {namedCurve, CurveOid}},
- {list_to_atom(Role ++ "_key_gen_chain"), [{namedCurve, CurveOid},
- {namedCurve, CurveOid}]}
- ];
-key_gen_spec(Role, ecdh_ecdsa) ->
+ [[Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, {namedCurve, CurveOid}}]];
+chain_spec(_Role, ecdhe_rsa) ->
+ Digest = {digest, appropriate_sha(crypto:supports())},
+ [[Digest, {key, hardcode_rsa_key(1)}],
+ [Digest, {key, hardcode_rsa_key(2)}],
+ [Digest, {key, hardcode_rsa_key(3)}]];
+chain_spec(_Role, ecdsa) ->
+ Digest = {digest, appropriate_sha(crypto:supports())},
CurveOid = hd(tls_v1:ecc_curves(0)),
- [{list_to_atom(Role ++ "_key_gen"), {namedCurve, CurveOid}},
- {list_to_atom(Role ++ "_key_gen_chain"), [{namedCurve, CurveOid},
- {namedCurve, CurveOid}]}
- ];
-key_gen_spec(Role, ecdhe_rsa) ->
- [{list_to_atom(Role ++ "_key_gen"), hardcode_rsa_key(1)},
- {list_to_atom(Role ++ "_key_gen_chain"), [hardcode_rsa_key(2),
- hardcode_rsa_key(3)]}
- ];
-key_gen_spec(Role, rsa) ->
- [{list_to_atom(Role ++ "_key_gen"), hardcode_rsa_key(1)},
- {list_to_atom(Role ++ "_key_gen_chain"), [hardcode_rsa_key(2),
- hardcode_rsa_key(3)]}
- ].
+ [[Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, {namedCurve, CurveOid}}]];
+chain_spec(_Role, rsa) ->
+ Digest = {digest, appropriate_sha(crypto:supports())},
+ [[Digest, {key, hardcode_rsa_key(1)}],
+ [Digest, {key, hardcode_rsa_key(2)}],
+ [Digest, {key, hardcode_rsa_key(3)}]];
+chain_spec(_Role, dsa) ->
+ Digest = {digest, appropriate_sha(crypto:supports())},
+ [[Digest, {key, hardcode_dsa_key(1)}],
+ [Digest, {key, hardcode_dsa_key(2)}],
+ [Digest, {key, hardcode_dsa_key(3)}]].
+
+merge_chain_spec([], [], Acc)->
+ lists:reverse(Acc);
+merge_chain_spec([User| UserRest], [Default | DefaultRest], Acc) ->
+ Merge = merge_spec(User, Default, confs(), []),
+ merge_chain_spec(UserRest, DefaultRest, [Merge | Acc]).
+
+confs() ->
+ [key, digest, validity, extensions].
+
+merge_spec(_, _, [], Acc) ->
+ Acc;
+merge_spec(User, Default, [Conf | Rest], Acc) ->
+ case proplists:get_value(Conf, User, undefined) of
+ undefined ->
+ case proplists:get_value(Conf, Default, undefined) of
+ undefined ->
+ merge_spec(User, Default, Rest, Acc);
+ Value ->
+ merge_spec(User, Default, Rest, [{Conf, Value} | Acc])
+ end;
+ Value ->
+ merge_spec(User, Default, Rest, [{Conf, Value} | Acc])
+ end.
+
+make_mix_cert(Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
+ Digest = {digest, appropriate_sha(crypto:supports())},
+ CurveOid = hd(tls_v1:ecc_curves(0)),
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "mix"]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "mix"]),
+ ClientChain = [[Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, hardcode_rsa_key(1)}],
+ [Digest, {key, {namedCurve, CurveOid}}, {extensions, Ext}]
+ ],
+ ServerChain = [[Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, hardcode_rsa_key(2)}],
+ [Digest, {key, {namedCurve, CurveOid}},{extensions, Ext}]
+ ],
+ ClientChainType =ServerChainType = mix,
+ CertChainConf = gen_conf(ClientChainType, ServerChainType, ClientChain, ServerChain),
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ClientChainType)]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ServerChainType)]),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
+ [{server_config, ServerConf},
+ {client_config, ClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+ {[{verify, verify_peer} | ClientConf],
+ [{reuseaddr, true}, {verify, verify_peer} | ServerConf]
+ }.
+
make_ecdsa_cert(Config) ->
CryptoSupport = crypto:supports(),
case proplists:get_bool(ecdsa, proplists:get_value(public_keys, CryptoSupport)) of
true ->
ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdsa"]),
ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdsa"]),
- CurveOid = hd(tls_v1:ecc_curves(0)),
- GenCertData = x509_test:gen_test_certs([{server_key_gen, {namedCurve, CurveOid}},
- {client_key_gen, {namedCurve, CurveOid}},
- {server_key_gen_chain, [{namedCurve, CurveOid},
- {namedCurve, CurveOid}]},
- {client_key_gen_chain, [{namedCurve, CurveOid},
- {namedCurve, CurveOid}]},
- {digest, appropriate_sha(CryptoSupport)}]),
+ ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()),
+ ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()),
+ CertChainConf = gen_conf(ecdsa, ecdsa, ClientChain, ServerChain),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
[{server_config, ServerConf},
{client_config, ClientConf}] =
x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
@@ -574,13 +743,10 @@ make_rsa_cert(Config) ->
true ->
ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa"]),
ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa"]),
- GenCertData = x509_test:gen_test_certs([{server_key_gen, hardcode_rsa_key(1)},
- {client_key_gen, hardcode_rsa_key(2)},
- {server_key_gen_chain, [hardcode_rsa_key(3),
- hardcode_rsa_key(4)]},
- {client_key_gen_chain, [hardcode_rsa_key(5),
- hardcode_rsa_key(6)]},
- {digest, appropriate_sha(CryptoSupport)}]),
+ ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()),
+ ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()),
+ CertChainConf = gen_conf(rsa, rsa, ClientChain, ServerChain),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
[{server_config, ServerConf},
{client_config, ClientConf}] =
x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
@@ -612,16 +778,10 @@ make_ecdh_rsa_cert(Config) ->
true ->
ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdh_rsa"]),
ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdh_rsa"]),
- CurveOid = hd(tls_v1:ecc_curves(0)),
- GenCertData = x509_test:gen_test_certs([{server_key_gen, {namedCurve, CurveOid}},
- {client_key_gen, {namedCurve, CurveOid}},
- {server_key_gen_chain, [hardcode_rsa_key(1),
- {namedCurve, CurveOid}
- ]},
- {client_key_gen_chain, [hardcode_rsa_key(2),
- {namedCurve, CurveOid}
- ]},
- {digest, appropriate_sha(CryptoSupport)}]),
+ ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()),
+ ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()),
+ CertChainConf = gen_conf(ecdh_rsa, ecdh_rsa, ClientChain, ServerChain),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
[{server_config, ServerConf},
{client_config, ClientConf}] =
x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
@@ -638,41 +798,6 @@ make_ecdh_rsa_cert(Config) ->
Config
end.
-make_mix_cert(Config) ->
- {ServerCaCertFile, ServerCertFile, ServerKeyFile} = make_cert_files("server", Config, dsa,
- rsa, "mix", []),
- {ClientCaCertFile, ClientCertFile, ClientKeyFile} = make_cert_files("client", Config, dsa,
- rsa, "mix", []),
- [{server_mix_opts, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ServerCaCertFile},
- {certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
- {server_mix_verify_opts, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ClientCaCertFile},
- {certfile, ServerCertFile}, {keyfile, ServerKeyFile},
- {verify, verify_peer}]},
- {client_mix_opts, [{ssl_imp, new},
- {cacertfile, ClientCaCertFile},
- {certfile, ClientCertFile}, {keyfile, ClientKeyFile}]}
- | Config].
-
-make_cert_files(RoleStr, Config, Alg1, Alg2, Prefix, Opts) ->
- Alg1Str = atom_to_list(Alg1),
- Alg2Str = atom_to_list(Alg2),
- CaInfo = {CaCert, _} = erl_make_certs:make_cert([{key, Alg1}| Opts]),
- {Cert, CertKey} = erl_make_certs:make_cert([{key, Alg2}, {issuer, CaInfo} | Opts]),
- CaCertFile = filename:join([proplists:get_value(priv_dir, Config),
- RoleStr, Prefix ++ Alg1Str ++ "_cacerts.pem"]),
- CertFile = filename:join([proplists:get_value(priv_dir, Config),
- RoleStr, Prefix ++ Alg2Str ++ "_cert.pem"]),
- KeyFile = filename:join([proplists:get_value(priv_dir, Config),
- RoleStr, Prefix ++ Alg2Str ++ "_key.pem"]),
-
- der_to_pem(CaCertFile, [{'Certificate', CaCert, not_encrypted}]),
- der_to_pem(CertFile, [{'Certificate', Cert, not_encrypted}]),
- der_to_pem(KeyFile, [CertKey]),
- {CaCertFile, CertFile, KeyFile}.
-
-
start_upgrade_server(Args) ->
Result = spawn_link(?MODULE, run_upgrade_server, [Args]),
receive
@@ -857,6 +982,160 @@ accepters(Acc, N) ->
accepters([Server| Acc], N-1)
end.
+
+basic_test(COpts, SOpts, Config) ->
+ SType = proplists:get_value(server_type, Config),
+ CType = proplists:get_value(client_type, Config),
+ {Server, Port} = start_server(SType, SOpts, Config),
+ Client = start_client(CType, Port, COpts, Config),
+ gen_check_result(Server, SType, Client, CType),
+ stop(Server, Client).
+
+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),
+ check_result(Server, ok, Client, ok),
+ stop(Server, Client).
+
+ecc_test_error(COpts, SOpts, CECCOpts, SECCOpts, Config) ->
+ {Server, Port} = start_server_ecc_error(erlang, SOpts, SECCOpts, Config),
+ Client = start_client_ecc_error(erlang, Port, COpts, CECCOpts, Config),
+ Error = {error, {tls_alert, "insufficient security"}},
+ check_result(Server, Error, Client, Error).
+
+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",
+ Args = ["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"],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+ true = port_command(OpenSslPort, "Hello world"),
+ OpenSslPort;
+
+start_client(erlang, Port, ClientOpts, Config) ->
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
+ KeyEx = proplists:get_value(check_keyex, Config, false),
+ ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, check_key_exchange_send_active, [KeyEx]}},
+ {options, [{verify, verify_peer} | ClientOpts]}]).
+
+
+start_client_ecc(erlang, Port, ClientOpts, Expect, ECCOpts, Config) ->
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
+ ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, check_ecc, [client, Expect]}},
+ {options,
+ ECCOpts ++
+ [{verify, verify_peer} | ClientOpts]}]).
+
+start_client_ecc_error(erlang, Port, ClientOpts, ECCOpts, Config) ->
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
+ ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {options,
+ ECCOpts ++
+ [{verify, verify_peer} | ClientOpts]}]).
+
+
+start_server(openssl, ServerOpts, Config) ->
+ Cert = proplists:get_value(certfile, ServerOpts),
+ Key = proplists:get_value(keyfile, ServerOpts),
+ CA = proplists:get_value(cacertfile, ServerOpts),
+ Port = inet_port(node()),
+ Version = protocol_version(Config),
+ Exe = "openssl",
+ Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version),
+ "-verify", "2", "-cert", Cert, "-CAfile", CA,
+ "-key", Key, "-msg", "-debug"],
+ 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),
+ Server = start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ check_key_exchange_send_active,
+ [KeyEx]}},
+ {options, [{verify, verify_peer} | ServerOpts]}]),
+ {Server, inet_port(Server)}.
+
+start_server_with_raw_key(erlang, ServerOpts, Config) ->
+ {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+ Server = start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ send_recv_result_active,
+ []}},
+ {options,
+ [{verify, verify_peer} | ServerOpts]}]),
+ {Server, inet_port(Server)}.
+
+start_server_ecc(erlang, ServerOpts, Expect, ECCOpts, Config) ->
+ {_, ServerNode, _} = run_where(Config),
+ Server = start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, check_ecc, [server, Expect]}},
+ {options,
+ ECCOpts ++
+ [{verify, verify_peer} | ServerOpts]}]),
+ {Server, inet_port(Server)}.
+
+start_server_ecc_error(erlang, ServerOpts, ECCOpts, Config) ->
+ {_, ServerNode, _} = run_where(Config),
+ Server = start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {options,
+ ECCOpts ++
+ [{verify, verify_peer} | ServerOpts]}]),
+ {Server, inet_port(Server)}.
+
+gen_check_result(Server, erlang, Client, erlang) ->
+ check_result(Server, ok, Client, ok);
+gen_check_result(Server, erlang, _, _) ->
+ check_result(Server, ok);
+gen_check_result(_, _, Client, erlang) ->
+ check_result(Client, ok);
+gen_check_result(_,openssl, _, openssl) ->
+ ok.
+
+stop(Port1, Port2) when is_port(Port1), is_port(Port2) ->
+ close_port(Port1),
+ close_port(Port2);
+stop(Port, Pid) when is_port(Port) ->
+ close_port(Port),
+ close(Pid);
+stop(Pid, Port) when is_port(Port) ->
+ close_port(Port),
+ close(Pid);
+stop(Client, Server) ->
+ close(Server),
+ close(Client).
+
+supported_eccs(Opts) ->
+ ToCheck = proplists:get_value(eccs, Opts, []),
+ Supported = ssl:eccs(),
+ lists:all(fun(Curve) -> lists:member(Curve, Supported) end, ToCheck).
+
+check_ecc(SSL, Role, Expect) ->
+ {ok, Data} = ssl:connection_information(SSL),
+ case lists:keyfind(ecc, 1, Data) of
+ {ecc, {named_curve, Expect}} -> ok;
+ Other -> {error, Role, Expect, Other}
+ end.
+
inet_port(Pid) when is_pid(Pid)->
receive
{Pid, {port, Port}} ->
@@ -925,13 +1204,13 @@ rsa_suites(CounterPart) ->
lists:member(cipher_atom(Cipher), Ciphers);
({ecdhe_rsa, Cipher, _}) when ECC == true ->
lists:member(cipher_atom(Cipher), Ciphers);
+ ({ecdhe_rsa, Cipher, _,_}) when ECC == true ->
+ lists:member(cipher_atom(Cipher), Ciphers);
({rsa, Cipher, _, _}) ->
lists:member(cipher_atom(Cipher), Ciphers);
({dhe_rsa, Cipher, _,_}) ->
lists:member(cipher_atom(Cipher), Ciphers);
- ({ecdhe_rsa, Cipher, _,_}) when ECC == true ->
- lists:member(cipher_atom(Cipher), Ciphers);
- (_) ->
+ (_) ->
false
end,
common_ciphers(CounterPart)).
@@ -941,13 +1220,13 @@ common_ciphers(crypto) ->
common_ciphers(openssl) ->
OpenSslSuites =
string:tokens(string:strip(os:cmd("openssl ciphers"), right, $\n), ":"),
- [ssl_cipher:erl_suite_definition(S)
+ [ssl_cipher_format:suite_definition(S)
|| S <- ssl_cipher:suites(tls_record:highest_protocol_version([])),
- lists:member(ssl_cipher:openssl_suite_name(S), OpenSslSuites)
+ lists:member(ssl_cipher_format:openssl_suite_name(S), OpenSslSuites)
].
available_suites(Version) ->
- [ssl_cipher:erl_suite_definition(Suite) ||
+ [ssl_cipher_format:suite_definition(Suite) ||
Suite <- ssl_cipher:filter_suites(ssl_cipher:suites(Version))].
@@ -983,16 +1262,10 @@ ecdh_rsa_suites(Version) ->
end,
available_suites(Version)).
-openssl_rsa_suites(CounterPart) ->
+openssl_rsa_suites() ->
Ciphers = ssl:cipher_suites(openssl),
- Names = case is_sane_ecc(CounterPart) of
- true ->
- "DSS | ECDSA";
- false ->
- "DSS | ECDHE | ECDH"
- end,
- lists:filter(fun(Str) -> string_regex_filter(Str, Names)
- end, Ciphers).
+ lists:filter(fun(Str) -> string_regex_filter(Str, "RSA")
+ end, Ciphers) -- openssl_ecdh_rsa_suites().
openssl_dsa_suites() ->
Ciphers = ssl:cipher_suites(openssl),
@@ -1025,49 +1298,89 @@ string_regex_filter(Str, Search) when is_list(Str) ->
string_regex_filter(_Str, _Search) ->
false.
-anonymous_suites(Version) ->
- Suites = ssl_cipher:anonymous_suites(Version),
- ssl_cipher:filter_suites(Suites).
-
+ecdh_dh_anonymous_suites(Version) ->
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:anonymous_suites(Version)],
+ [{key_exchange,
+ fun(dh_anon) ->
+ true;
+ (ecdh_anon) ->
+ true;
+ (_) ->
+ false
+ end}]).
+psk_suites({3,_} = Version) ->
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:psk_suites(Version)], []);
psk_suites(Version) ->
- Suites = ssl_cipher:psk_suites(Version),
- ssl_cipher:filter_suites(Suites).
+ ssl:filter_cipher_suites(psk_suites(dtls_v1:corresponding_tls_version(Version)),
+ [{cipher,
+ fun(rc4_128) ->
+ false;
+ (_) ->
+ true
+ end}]).
+
+psk_anon_suites({3,_} = Version) ->
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:psk_suites_anon(Version)],
+ [{key_exchange,
+ fun(psk) ->
+ true;
+ (dhe_psk) ->
+ true;
+ (ecdhe_psk) ->
+ true;
+ (_) ->
+ false
+ end}]);
psk_anon_suites(Version) ->
- Suites = [Suite || Suite <- psk_suites(Version), is_psk_anon_suite(Suite)],
- ssl_cipher:filter_suites(Suites).
+ ssl:filter_cipher_suites(psk_anon_suites(dtls_v1:corresponding_tls_version(Version)),
+ [{cipher,
+ fun(rc4_128) ->
+ false;
+ (_) ->
+ true
+ end}]).
-srp_suites() ->
- Suites =
- [{srp_anon, '3des_ede_cbc', sha},
- {srp_rsa, '3des_ede_cbc', sha},
- {srp_anon, aes_128_cbc, sha},
- {srp_rsa, aes_128_cbc, sha},
- {srp_anon, aes_256_cbc, sha},
- {srp_rsa, aes_256_cbc, sha}],
- ssl_cipher:filter_suites(Suites).
+srp_suites() ->
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:srp_suites()],
+ [{key_exchange,
+ fun(srp_rsa) ->
+ true;
+ (_) ->
+ false
+ end}]).
srp_anon_suites() ->
- Suites =
- [{srp_anon, '3des_ede_cbc', sha},
- {srp_anon, aes_128_cbc, sha},
- {srp_anon, aes_256_cbc, sha}],
- ssl_cipher:filter_suites(Suites).
-
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:srp_suites_anon()],
+ []).
srp_dss_suites() ->
- Suites =
- [{srp_dss, '3des_ede_cbc', sha},
- {srp_dss, aes_128_cbc, sha},
- {srp_dss, aes_256_cbc, sha}],
- ssl_cipher:filter_suites(Suites).
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:srp_suites()],
+ [{key_exchange,
+ fun(srp_dss) ->
+ true;
+ (_) ->
+ false
+ end}]).
+chacha_suites(Version) ->
+ [ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:filter_suites(ssl_cipher:chacha_suites(Version))].
+
rc4_suites(Version) ->
- Suites = ssl_cipher:rc4_suites(Version),
- ssl_cipher:filter_suites(Suites).
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <-ssl_cipher:rc4_suites(Version)], []).
des_suites(Version) ->
- Suites = ssl_cipher:des_suites(Version),
- ssl_cipher:filter_suites(Suites).
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <-ssl_cipher:des_suites(Version)], []).
+
+tuple_to_map({Kex, Cipher, Mac}) ->
+ #{key_exchange => Kex,
+ cipher => Cipher,
+ mac => Mac,
+ prf => default_prf};
+tuple_to_map({Kex, Cipher, Mac, Prf}) ->
+ #{key_exchange => Kex,
+ cipher => Cipher,
+ mac => Mac,
+ prf => Prf}.
pem_to_der(File) ->
{ok, PemBin} = file:read_file(File),
@@ -1079,7 +1392,7 @@ der_to_pem(File, Entries) ->
cipher_result(Socket, Result) ->
{ok, Info} = ssl:connection_information(Socket),
- Result = {ok, {proplists:get_value(protocol, Info), proplists:get_value(cipher_suite, Info)}},
+ Result = {ok, {proplists:get_value(protocol, Info), proplists:get_value(selected_cipher_suite, Info)}},
ct:log("~p:~p~nSuccessfull connect: ~p~n", [?MODULE,?LINE, Result]),
%% Importante to send two packets here
%% to properly test "cipher state" handling
@@ -1167,14 +1480,14 @@ init_tls_version(Version, Config) ->
NewConfig = proplists:delete(protocol_opts, proplists:delete(protocol, Config)),
[{protocol, tls} | NewConfig].
+clean_tls_version(Config) ->
+ proplists:delete(protocol_opts, proplists:delete(protocol, Config)).
+
sufficient_crypto_support(Version)
when Version == 'tlsv1.2'; Version == 'dtlsv1.2' ->
CryptoSupport = crypto:supports(),
proplists:get_bool(sha256, proplists:get_value(hashs, CryptoSupport));
-sufficient_crypto_support(Group) when Group == ciphers_ec; %% From ssl_basic_SUITE
- Group == erlang_server; %% From ssl_ECC_SUITE
- Group == erlang_client; %% From ssl_ECC_SUITE
- Group == erlang -> %% From ssl_ECC_SUITE
+sufficient_crypto_support(cipher_ec) ->
CryptoSupport = crypto:supports(),
proplists:get_bool(ecdh, proplists:get_value(public_keys, CryptoSupport));
sufficient_crypto_support(_) ->
@@ -1183,16 +1496,36 @@ sufficient_crypto_support(_) ->
check_key_exchange_send_active(Socket, false) ->
send_recv_result_active(Socket);
check_key_exchange_send_active(Socket, KeyEx) ->
- {ok, [{cipher_suite, Suite}]} = ssl:connection_information(Socket, [cipher_suite]),
- true = check_key_exchange(Suite, KeyEx),
+ {ok, Info} =
+ ssl:connection_information(Socket, [cipher_suite, protocol]),
+ Suite = proplists:get_value(cipher_suite, Info),
+ Version = proplists:get_value(protocol, Info),
+ true = check_key_exchange(Suite, KeyEx, Version),
send_recv_result_active(Socket).
-check_key_exchange({KeyEx,_, _}, KeyEx) ->
+check_key_exchange({KeyEx,_, _}, KeyEx, _) ->
+ ct:pal("Kex: ~p", [KeyEx]),
+ true;
+check_key_exchange({KeyEx,_,_,_}, KeyEx, _) ->
+ ct:pal("Kex: ~p", [KeyEx]),
+ true;
+check_key_exchange(KeyEx1, KeyEx2, Version) ->
+ ct:pal("Kex: ~p ~p", [KeyEx1, KeyEx2]),
+ case Version of
+ 'tlsv1.2' ->
+ v_1_2_check(element(1, KeyEx1), KeyEx2);
+ 'dtlsv1.2' ->
+ v_1_2_check(element(1, KeyEx1), KeyEx2);
+ _ ->
+ ct:pal("Negotiated ~p Expected ~p", [KeyEx1, KeyEx2]),
+ false
+ end.
+
+v_1_2_check(ecdh_ecdsa, ecdh_rsa) ->
true;
-check_key_exchange({KeyEx,_,_,_}, KeyEx) ->
+v_1_2_check(ecdh_rsa, ecdh_ecdsa) ->
true;
-check_key_exchange(KeyEx1, KeyEx2) ->
- ct:pal("Negotiated ~p Expected ~p", [KeyEx1, KeyEx2]),
+v_1_2_check(_, _) ->
false.
send_recv_result_active(Socket) ->
@@ -1254,7 +1587,7 @@ is_sane_ecc(crypto) ->
true
end;
is_sane_ecc(_) ->
- true.
+ sufficient_crypto_support(cipher_ec).
is_fips(openssl) ->
VersionStr = os:cmd("openssl version"),
@@ -1276,7 +1609,7 @@ is_fips(_) ->
false.
cipher_restriction(Config0) ->
- Version = tls_record:protocol_version(protocol_version(Config0)),
+ Version = protocol_version(Config0, tuple),
case is_sane_ecc(openssl) of
false ->
Opts = proplists:get_value(server_opts, Config0),
@@ -1290,17 +1623,97 @@ cipher_restriction(Config0) ->
Config0
end.
+openssl_dsa_support() ->
+ case os:cmd("openssl version") of
+ "LibreSSL 2.6.1" ++ _ ->
+ true;
+ "LibreSSL 2.6.2" ++ _ ->
+ true;
+ "LibreSSL 2.6" ++ _ ->
+ false;
+ "LibreSSL 2.4" ++ _ ->
+ true;
+ "LibreSSL 2.3" ++ _ ->
+ true;
+ "LibreSSL 2.2" ++ _ ->
+ true;
+ "LibreSSL 2.1" ++ _ ->
+ true;
+ "LibreSSL 2.0" ++ _ ->
+ true;
+ "LibreSSL" ++ _ ->
+ false;
+ "OpenSSL 1.1" ++ Rest ->
+ false;
+ "OpenSSL 1.0.1" ++ Rest ->
+ hd(Rest) >= s;
+ _ ->
+ true
+ end.
+
+%% Acctual support is tested elsewhere, this is to exclude some LibreSSL and OpenSSL versions
+openssl_sane_dtls() ->
+ case os:cmd("openssl version") of
+ "OpenSSL 0." ++ _ ->
+ false;
+ "OpenSSL 1.0.1s-freebsd" ++ _ ->
+ false;
+ "OpenSSL 1.0.2k-freebsd" ++ _ ->
+ false;
+ "OpenSSL 1.0.2" ++ _ ->
+ false;
+ "OpenSSL 1.0.0" ++ _ ->
+ false;
+ "OpenSSL" ++ _ ->
+ true;
+ "LibreSSL 2.7" ++ _ ->
+ true;
+ _ ->
+ false
+ end.
+openssl_sane_client_cert() ->
+ case os:cmd("openssl version") of
+ "LibreSSL 2.5.2" ++ _ ->
+ true;
+ "LibreSSL 2.4" ++ _ ->
+ false;
+ "LibreSSL 2.3" ++ _ ->
+ false;
+ "LibreSSL 2.1" ++ _ ->
+ false;
+ "LibreSSL 2.0" ++ _ ->
+ false;
+ "LibreSSL 2.0" ++ _ ->
+ false;
+ "OpenSSL 1.0.1s-freebsd" ->
+ false;
+ "OpenSSL 1.0.0" ++ _ ->
+ false;
+ _ ->
+ true
+ end.
+
check_sane_openssl_version(Version) ->
case supports_ssl_tls_version(Version) of
true ->
case {Version, os:cmd("openssl version")} of
+ {'sslv3', "OpenSSL 1.0.2" ++ _} ->
+ false;
+ {'dtlsv1', _} ->
+ not is_fips(openssl);
+ {'dtlsv1.2', _} ->
+ not is_fips(openssl);
{_, "OpenSSL 1.0.2" ++ _} ->
true;
{_, "OpenSSL 1.0.1" ++ _} ->
true;
- {'tlsv1.2', "OpenSSL 1.0" ++ _} ->
+ {'tlsv1.2', "OpenSSL 1.0.0" ++ _} ->
+ false;
+ {'tlsv1.1', "OpenSSL 1.0.0" ++ _} ->
false;
- {'tlsv1.1', "OpenSSL 1.0" ++ _} ->
+ {'dtlsv1.2', "OpenSSL 1.0.2" ++ _} ->
+ false;
+ {'dtlsv1', "OpenSSL 1.0.0" ++ _} ->
false;
{'tlsv1.2', "OpenSSL 0" ++ _} ->
false;
@@ -1321,8 +1734,9 @@ enough_openssl_crl_support(_) -> true.
wait_for_openssl_server(Port, tls) ->
do_wait_for_openssl_tls_server(Port, 10);
-wait_for_openssl_server(Port, dtls) ->
- do_wait_for_openssl_dtls_server(Port, 10).
+wait_for_openssl_server(_Port, dtls) ->
+ ok. %% No need to wait for DTLS over UDP server
+ %% client will retransmitt until it is up.
do_wait_for_openssl_tls_server(_, 0) ->
exit(failed_to_connect_to_openssl);
@@ -1335,21 +1749,6 @@ do_wait_for_openssl_tls_server(Port, N) ->
do_wait_for_openssl_tls_server(Port, N-1)
end.
-do_wait_for_openssl_dtls_server(_, 0) ->
- %%exit(failed_to_connect_to_openssl);
- ok;
-do_wait_for_openssl_dtls_server(Port, N) ->
- %% case gen_udp:open(0) of
- %% {ok, S} ->
- %% gen_udp:connect(S, "localhost", Port),
- %% gen_udp:close(S);
- %% _ ->
- %% ct:sleep(?SLEEP),
- %% do_wait_for_openssl_dtls_server(Port, N-1)
- %% end.
- ct:sleep(500),
- do_wait_for_openssl_dtls_server(Port, N-1).
-
version_flag(tlsv1) ->
"-tls1";
version_flag('tlsv1.1') ->
@@ -1365,15 +1764,23 @@ version_flag('dtlsv1.2') ->
version_flag('dtlsv1') ->
"-dtls1".
+filter_suites([Cipher | _] = Ciphers, AtomVersion) when is_list(Cipher)->
+ filter_suites([ssl_cipher_format:openssl_suite(S) || S <- Ciphers],
+ AtomVersion);
+filter_suites([Cipher | _] = Ciphers, AtomVersion) when is_binary(Cipher)->
+ filter_suites([ssl_cipher_format:suite_definition(S) || S <- Ciphers],
+ AtomVersion);
filter_suites(Ciphers0, AtomVersion) ->
Version = tls_version(AtomVersion),
Supported0 = ssl_cipher:suites(Version)
++ 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:rc4_suites(Version),
Supported1 = ssl_cipher:filter_suites(Supported0),
- Supported2 = [ssl_cipher:erl_suite_definition(S) || S <- Supported1],
+ Supported2 = [ssl_cipher_format:suite_definition(S) || S <- Supported1],
[Cipher || Cipher <- Ciphers0, lists:member(Cipher, Supported2)].
-define(OPENSSL_QUIT, "Q\n").
@@ -1419,12 +1826,20 @@ supports_ssl_tls_version(sslv2 = Version) ->
case os:cmd("openssl version") of
"OpenSSL 1" ++ _ ->
false;
+ %% Appears to be broken
+ "OpenSSL 0.9.8.o" ++ _ ->
+ false;
_ ->
VersionFlag = version_flag(Version),
Exe = "openssl",
Args = ["s_client", VersionFlag],
+ [{trap_exit, Trap}] = process_info(self(), [trap_exit]),
+ process_flag(trap_exit, true),
Port = ssl_test_lib:portable_open_port(Exe, Args),
- do_supports_ssl_tls_version(Port)
+ Bool = do_supports_ssl_tls_version(Port, ""),
+ consume_port_exit(Port),
+ process_flag(trap_exit, Trap),
+ Bool
end;
supports_ssl_tls_version(Version) ->
@@ -1432,23 +1847,24 @@ supports_ssl_tls_version(Version) ->
Exe = "openssl",
Args = ["s_client", VersionFlag],
Port = ssl_test_lib:portable_open_port(Exe, Args),
- do_supports_ssl_tls_version(Port).
+ do_supports_ssl_tls_version(Port, "").
-do_supports_ssl_tls_version(Port) ->
+do_supports_ssl_tls_version(Port, Acc) ->
receive
- {Port, {data, "u"}} ->
- false;
- {Port, {data, "unknown option" ++ _}} ->
- false;
- {Port, {data, Data}} ->
- case lists:member("error", string:tokens(Data, ":")) of
- true ->
- false;
- false ->
- do_supports_ssl_tls_version(Port)
- end
+ {Port, {data, Data}} ->
+ case Acc ++ Data of
+ "unknown option" ++ _ ->
+ false;
+ "s_client: Option unknown" ++ _->
+ false;
+ Info when length(Info) >= 24 ->
+ ct:pal("~p", [Info]),
+ true;
+ _ ->
+ do_supports_ssl_tls_version(Port, Acc ++ Data)
+ end
after 1000 ->
- true
+ true
end.
ssl_options(Option, Config) when is_atom(Option) ->
@@ -1493,6 +1909,7 @@ ct_log_supported_protocol_versions(Config) ->
clean_env() ->
application:unset_env(ssl, protocol_version),
+ application:unset_env(ssl, dtls_protocol_version),
application:unset_env(ssl, session_lifetime),
application:unset_env(ssl, session_cb),
application:unset_env(ssl, session_cb_init_args),
@@ -1512,10 +1929,14 @@ is_psk_anon_suite({psk, _,_}) ->
true;
is_psk_anon_suite({dhe_psk,_,_}) ->
true;
+is_psk_anon_suite({ecdhe_psk,_,_}) ->
+ true;
is_psk_anon_suite({psk, _,_,_}) ->
true;
is_psk_anon_suite({dhe_psk, _,_,_}) ->
true;
+is_psk_anon_suite({ecdhe_psk, _,_,_}) ->
+ true;
is_psk_anon_suite(_) ->
false.
@@ -1534,148 +1955,145 @@ tls_version('dtlsv1.2' = Atom) ->
tls_version(Atom) ->
tls_record:protocol_version(Atom).
+consume_port_exit(OpenSSLPort) ->
+ receive
+ {'EXIT', OpenSSLPort, _} ->
+ ok
+ end.
+
hardcode_rsa_key(1) ->
- {'RSAPrivateKey',0,
- 23995666614853919027835084074500048897452890537492185072956789802729257783422306095699263934587064480357348855732149402060270996295002843755712064937715826848741191927820899197493902093529581182351132392364214171173881547273475904587683433713767834856230531387991145055273426806331200574039205571401702219159773947658558490957010003143162250693492642996408861265758000254664396313741422909188635443907373976005987612936763564996605457102336549804831742940035613780926178523017685712710473543251580072875247250504243621640157403744718833162626193206685233710319205099867303242759099560438381385658382486042995679707669,
- 17,
- 11292078406990079542510627799764728892919007311761028269626724613049062486316379339152594792746853873109340637991599718616598115903530750002688030558925094987642913848386305504703012749896273497577003478759630198199473669305165131570674557041773098755873191241407597673069847908861741446606684974777271632545629600685952292605647052193819136445675100211504432575554351515262198132231537860917084269870590492135731720141577986787033006338680118008484613510063003323516659048210893001173583018220214626635609151105287049126443102976056146630518124476470236027123782297108342869049542023328584384300970694412006494684657,
- 169371138592582642967021557955633494538845517070305333860805485424261447791289944610138334410987654265476540480228705481960508520379619587635662291973699651583489223555422528867090299996446070521801757353675026048850480903160224210802452555900007597342687137394192939372218903554801584969667104937092080815197,
- 141675062317286527042995673340952251894209529891636708844197799307963834958115010129693036021381525952081167155681637592199810112261679449166276939178032066869788822014115556349519329537177920752776047051833616197615329017439297361972726138285974555338480581117881706656603857310337984049152655480389797687577,
- 119556097830058336212015217380447172615655659108450823901745048534772786676204666783627059584226579481512852103690850928442711896738555003036938088452023283470698275450886490965004917644550167427154181661417665446247398284583687678213495921811770068712485038160606780733330990744565824684470897602653233516609,
- 41669135975672507953822256864985956439473391144599032012999352737636422046504414744027363535700448809435637398729893409470532385959317485048904982111185902020526124121798693043976273393287623750816484427009887116945685005129205106462566511260580751570141347387612266663707016855981760014456663376585234613993,
- 76837684977089699359024365285678488693966186052769523357232308621548155587515525857011429902602352279058920284048929101483304120686557782043616693940283344235057989514310975192908256494992960578961614059245280827077951132083993754797053182279229469590276271658395444955906108899267024101096069475145863928441,
- asn1_NOVALUE};
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus = 23995666614853919027835084074500048897452890537492185072956789802729257783422306095699263934587064480357348855732149402060270996295002843755712064937715826848741191927820899197493902093529581182351132392364214171173881547273475904587683433713767834856230531387991145055273426806331200574039205571401702219159773947658558490957010003143162250693492642996408861265758000254664396313741422909188635443907373976005987612936763564996605457102336549804831742940035613780926178523017685712710473543251580072875247250504243621640157403744718833162626193206685233710319205099867303242759099560438381385658382486042995679707669,
+ publicExponent = 17,
+ privateExponent = 11292078406990079542510627799764728892919007311761028269626724613049062486316379339152594792746853873109340637991599718616598115903530750002688030558925094987642913848386305504703012749896273497577003478759630198199473669305165131570674557041773098755873191241407597673069847908861741446606684974777271632545629600685952292605647052193819136445675100211504432575554351515262198132231537860917084269870590492135731720141577986787033006338680118008484613510063003323516659048210893001173583018220214626635609151105287049126443102976056146630518124476470236027123782297108342869049542023328584384300970694412006494684657,
+ prime1 = 169371138592582642967021557955633494538845517070305333860805485424261447791289944610138334410987654265476540480228705481960508520379619587635662291973699651583489223555422528867090299996446070521801757353675026048850480903160224210802452555900007597342687137394192939372218903554801584969667104937092080815197,
+ prime2 = 141675062317286527042995673340952251894209529891636708844197799307963834958115010129693036021381525952081167155681637592199810112261679449166276939178032066869788822014115556349519329537177920752776047051833616197615329017439297361972726138285974555338480581117881706656603857310337984049152655480389797687577,
+ exponent1 = 119556097830058336212015217380447172615655659108450823901745048534772786676204666783627059584226579481512852103690850928442711896738555003036938088452023283470698275450886490965004917644550167427154181661417665446247398284583687678213495921811770068712485038160606780733330990744565824684470897602653233516609,
+ exponent2 = 41669135975672507953822256864985956439473391144599032012999352737636422046504414744027363535700448809435637398729893409470532385959317485048904982111185902020526124121798693043976273393287623750816484427009887116945685005129205106462566511260580751570141347387612266663707016855981760014456663376585234613993,
+ coefficient = 76837684977089699359024365285678488693966186052769523357232308621548155587515525857011429902602352279058920284048929101483304120686557782043616693940283344235057989514310975192908256494992960578961614059245280827077951132083993754797053182279229469590276271658395444955906108899267024101096069475145863928441,
+ otherPrimeInfos = asn1_NOVALUE};
hardcode_rsa_key(2) ->
-{'RSAPrivateKey',0,
- 21343679768589700771839799834197557895311746244621307033143551583788179817796325695589283169969489517156931770973490560582341832744966317712674900833543896521418422508485833901274928542544381247956820115082240721897193055368570146764204557110415281995205343662628196075590438954399631753508888358737971039058298703003743872818150364935790613286541190842600031570570099801682794056444451081563070538409720109449780410837763602317050353477918147758267825417201591905091231778937606362076129350476690460157227101296599527319242747999737801698427160817755293383890373574621116766934110792127739174475029121017282777887777,
- 17,
- 18832658619343853622211588088997845201745658451136447382185486691577805721584993260814073385267196632785528033211903435807948675951440868570007265441362261636545666919252206383477878125774454042314841278013741813438699754736973658909592256273895837054592950290554290654932740253882028017801960316533503857992358685308186680144968293076156011747178275038098868263178095174694099811498968993700538293188879611375604635940554394589807673542938082281934965292051746326331046224291377703201248790910007232374006151098976879987912446997911775904329728563222485791845480864283470332826504617837402078265424772379987120023773,
- 146807662748886761089048448970170315054939768171908279335181627815919052012991509112344782731265837727551849787333310044397991034789843793140419387740928103541736452627413492093463231242466386868459637115999163097726153692593711599245170083315894262154838974616739452594203727376460632750934355508361223110419,
- 145385325050081892763917667176962991350872697916072592966410309213561884732628046256782356731057378829876640317801978404203665761131810712267778698468684631707642938779964806354584156202882543264893826268426566901882487709510744074274965029453915224310656287149777603803201831202222853023280023478269485417083,
- 51814469205489445090252393754177758254684624060673510353593515699736136004585238510239335081623236845018299924941168250963996835808180162284853901555621683602965806809675350150634081614988136541809283687999704622726877773856604093851236499993845033701707873394143336209718962603456693912094478414715725803677,
- 51312467664734785681382706062457526359131540440966797517556579722433606376221663384746714140373192528191755406283051201483646739222992016094510128871300458249756331334105225772206172777487956446433115153562317730076172132768497908567634716277852432109643395464627389577600646306666889302334125933506877206029,
- 30504662229874176232343608562807118278893368758027179776313787938167236952567905398252901545019583024374163153775359371298239336609182249464886717948407152570850677549297935773605431024166978281486607154204888016179709037883348099374995148481968169438302456074511782717758301581202874062062542434218011141540,
- asn1_NOVALUE};
-
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus = 21343679768589700771839799834197557895311746244621307033143551583788179817796325695589283169969489517156931770973490560582341832744966317712674900833543896521418422508485833901274928542544381247956820115082240721897193055368570146764204557110415281995205343662628196075590438954399631753508888358737971039058298703003743872818150364935790613286541190842600031570570099801682794056444451081563070538409720109449780410837763602317050353477918147758267825417201591905091231778937606362076129350476690460157227101296599527319242747999737801698427160817755293383890373574621116766934110792127739174475029121017282777887777,
+ publicExponent = 17,
+ privateExponent = 18832658619343853622211588088997845201745658451136447382185486691577805721584993260814073385267196632785528033211903435807948675951440868570007265441362261636545666919252206383477878125774454042314841278013741813438699754736973658909592256273895837054592950290554290654932740253882028017801960316533503857992358685308186680144968293076156011747178275038098868263178095174694099811498968993700538293188879611375604635940554394589807673542938082281934965292051746326331046224291377703201248790910007232374006151098976879987912446997911775904329728563222485791845480864283470332826504617837402078265424772379987120023773,
+ prime1 = 146807662748886761089048448970170315054939768171908279335181627815919052012991509112344782731265837727551849787333310044397991034789843793140419387740928103541736452627413492093463231242466386868459637115999163097726153692593711599245170083315894262154838974616739452594203727376460632750934355508361223110419,
+ prime2 = 145385325050081892763917667176962991350872697916072592966410309213561884732628046256782356731057378829876640317801978404203665761131810712267778698468684631707642938779964806354584156202882543264893826268426566901882487709510744074274965029453915224310656287149777603803201831202222853023280023478269485417083,
+ exponent1 = 51814469205489445090252393754177758254684624060673510353593515699736136004585238510239335081623236845018299924941168250963996835808180162284853901555621683602965806809675350150634081614988136541809283687999704622726877773856604093851236499993845033701707873394143336209718962603456693912094478414715725803677,
+ exponent2 = 51312467664734785681382706062457526359131540440966797517556579722433606376221663384746714140373192528191755406283051201483646739222992016094510128871300458249756331334105225772206172777487956446433115153562317730076172132768497908567634716277852432109643395464627389577600646306666889302334125933506877206029,
+ coefficient = 30504662229874176232343608562807118278893368758027179776313787938167236952567905398252901545019583024374163153775359371298239336609182249464886717948407152570850677549297935773605431024166978281486607154204888016179709037883348099374995148481968169438302456074511782717758301581202874062062542434218011141540,
+ otherPrimeInfos = asn1_NOVALUE};
hardcode_rsa_key(3) ->
-{'RSAPrivateKey',0,
- 25089040456112869869472694987833070928503703615633809313972554887193090845137746668197820419383804666271752525807484521370419854590682661809972833718476098189250708650325307850184923546875260207894844301992963978994451844985784504212035958130279304082438876764367292331581532569155681984449177635856426023931875082020262146075451989132180409962870105455517050416234175675478291534563995772675388370042873175344937421148321291640477650173765084699931690748536036544188863178325887393475703801759010864779559318631816411493486934507417755306337476945299570726975433250753415110141783026008347194577506976486290259135429,
- 17,
- 8854955455098659953931539407470495621824836570223697404931489960185796768872145882893348383311931058684147950284994536954265831032005645344696294253579799360912014817761873358888796545955974191021709753644575521998041827642041589721895044045980930852625485916835514940558187965584358347452650930302268008446431977397918214293502821599497633970075862760001650736520566952260001423171553461362588848929781360590057040212831994258783694027013289053834376791974167294527043946669963760259975273650548116897900664646809242902841107022557239712438496384819445301703021164043324282687280801738470244471443835900160721870265,
- 171641816401041100605063917111691927706183918906535463031548413586331728772311589438043965564336865070070922328258143588739626712299625805650832695450270566547004154065267940032684307994238248203186986569945677705100224518137694769557564475390859269797990555863306972197736879644001860925483629009305104925823,
- 146170909759497809922264016492088453282310383272504533061020897155289106805616042710009332510822455269704884883705830985184223718261139908416790475825625309815234508695722132706422885088219618698987115562577878897003573425367881351537506046253616435685549396767356003663417208105346307649599145759863108910523,
- 60579464612132153154728441333538327425711971378777222246428851853999433684345266860486105493295364142377972586444050678378691780811632637288529186629507258781295583787741625893888579292084087601124818789392592131211843947578009918667375697196773859928702549128225990187436545756706539150170692591519448797349,
- 137572620950115585809189662580789132500998007785886619351549079675566218169991569609420548245479957900898715184664311515467504676010484619686391036071176762179044243478326713135456833024206699951987873470661533079532774988581535389682358631768109586527575902839864474036157372334443583670210960715165278974609,
- 15068630434698373319269196003209754243798959461311186548759287649485250508074064775263867418602372588394608558985183294561315208336731894947137343239541687540387209051236354318837334154993136528453613256169847839789803932725339395739618592522865156272771578671216082079933457043120923342632744996962853951612,
- asn1_NOVALUE};
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus = 25089040456112869869472694987833070928503703615633809313972554887193090845137746668197820419383804666271752525807484521370419854590682661809972833718476098189250708650325307850184923546875260207894844301992963978994451844985784504212035958130279304082438876764367292331581532569155681984449177635856426023931875082020262146075451989132180409962870105455517050416234175675478291534563995772675388370042873175344937421148321291640477650173765084699931690748536036544188863178325887393475703801759010864779559318631816411493486934507417755306337476945299570726975433250753415110141783026008347194577506976486290259135429,
+ publicExponent = 17,
+ privateExponent = 8854955455098659953931539407470495621824836570223697404931489960185796768872145882893348383311931058684147950284994536954265831032005645344696294253579799360912014817761873358888796545955974191021709753644575521998041827642041589721895044045980930852625485916835514940558187965584358347452650930302268008446431977397918214293502821599497633970075862760001650736520566952260001423171553461362588848929781360590057040212831994258783694027013289053834376791974167294527043946669963760259975273650548116897900664646809242902841107022557239712438496384819445301703021164043324282687280801738470244471443835900160721870265,
+ prime1 = 171641816401041100605063917111691927706183918906535463031548413586331728772311589438043965564336865070070922328258143588739626712299625805650832695450270566547004154065267940032684307994238248203186986569945677705100224518137694769557564475390859269797990555863306972197736879644001860925483629009305104925823,
+ prime2 =146170909759497809922264016492088453282310383272504533061020897155289106805616042710009332510822455269704884883705830985184223718261139908416790475825625309815234508695722132706422885088219618698987115562577878897003573425367881351537506046253616435685549396767356003663417208105346307649599145759863108910523,
+ exponent1 = 60579464612132153154728441333538327425711971378777222246428851853999433684345266860486105493295364142377972586444050678378691780811632637288529186629507258781295583787741625893888579292084087601124818789392592131211843947578009918667375697196773859928702549128225990187436545756706539150170692591519448797349,
+ exponent2 = 137572620950115585809189662580789132500998007785886619351549079675566218169991569609420548245479957900898715184664311515467504676010484619686391036071176762179044243478326713135456833024206699951987873470661533079532774988581535389682358631768109586527575902839864474036157372334443583670210960715165278974609,
+ coefficient = 15068630434698373319269196003209754243798959461311186548759287649485250508074064775263867418602372588394608558985183294561315208336731894947137343239541687540387209051236354318837334154993136528453613256169847839789803932725339395739618592522865156272771578671216082079933457043120923342632744996962853951612,
+ otherPrimeInfos = asn1_NOVALUE};
hardcode_rsa_key(4) ->
-{'RSAPrivateKey',0,
- 28617237755030755643854803617273584643843067580642149032833640135949799721163782522787597288521902619948688786051081993247908700824196122780349730169173433743054172191054872553484065655968335396052034378669869864779940355219732200954630251223541048434478476115391643898092650304645086338265930608997389611376417609043761464100338332976874588396803891301015812818307951159858145399281035705713082131199940309445719678087542976246147777388465712394062188801177717719764254900022006288880246925156931391594131839991579403409541227225173269459173129377291869028712271737734702830877034334838181789916127814298794576266389,
- 17,
- 26933870828264240605980991639786903194205240075898493207372837775011576208154148256741268036255908348187001210401018346586267012540419880263858569570986761169933338532757527109161473558558433313931326474042230460969355628442100895016122589386862163232450330461545076609969553227901257730132640573174013751883368376011370428995523268034111482031427024082719896108094847702954695363285832195666458915142143884210891427766607838346722974883433132513540317964796373298134261669479023445911856492129270184781873446960437310543998533283339488055776892320162032014809906169940882070478200435536171854883284366514852906334641,
- 177342190816702392178883147766999616783253285436834252111702533617098994535049411784501174309695427674025956656849179054202187436663487378682303508229883753383891163725167367039879190685255046547908384208614573353917213168937832054054779266431207529839577747601879940934691505396807977946728204814969824442867,
- 161367340863680900415977542864139121629424927689088951345472941851682581254789586032968359551717004797621579428672968948552429138154521719743297455351687337112710712475376510559020211584326773715482918387500187602625572442687231345855402020688502483137168684570635690059254866684191216155909970061793538842967,
- 62591361464718491357252875682470452982324688977706206627659717747211409835899792394529826226951327414362102349476180842659595565881230839534930649963488383547255704844176717778780890830090016428673547367746320007264898765507470136725216211681602657590439205035957626212244060728285168687080542875871702744541,
- 28476589564178982426348978152495139111074987239250991413906989738532220221433456358759122273832412611344984605059935696803369847909621479954699550944415412431654831613301737157474154985469430655673456186029444871051571607533040825739188591886206320553618003159523945304574388238386685203984112363845918619347,
- 34340318160575773065401929915821192439103777558577109939078671096408836197675640654693301707202885840826672396546056002756167635035389371579540325327619480512374920136684787633921441576901246290213545161954865184290700344352088099063404416346968182170720521708773285279884132629954461545103181082503707725012,
- asn1_NOVALUE};
+ #'RSAPrivateKey'{
+ version ='two-prime',
+ modulus = 28617237755030755643854803617273584643843067580642149032833640135949799721163782522787597288521902619948688786051081993247908700824196122780349730169173433743054172191054872553484065655968335396052034378669869864779940355219732200954630251223541048434478476115391643898092650304645086338265930608997389611376417609043761464100338332976874588396803891301015812818307951159858145399281035705713082131199940309445719678087542976246147777388465712394062188801177717719764254900022006288880246925156931391594131839991579403409541227225173269459173129377291869028712271737734702830877034334838181789916127814298794576266389,
+ publicExponent = 17,
+ privateExponent = 26933870828264240605980991639786903194205240075898493207372837775011576208154148256741268036255908348187001210401018346586267012540419880263858569570986761169933338532757527109161473558558433313931326474042230460969355628442100895016122589386862163232450330461545076609969553227901257730132640573174013751883368376011370428995523268034111482031427024082719896108094847702954695363285832195666458915142143884210891427766607838346722974883433132513540317964796373298134261669479023445911856492129270184781873446960437310543998533283339488055776892320162032014809906169940882070478200435536171854883284366514852906334641,
+ prime1 = 177342190816702392178883147766999616783253285436834252111702533617098994535049411784501174309695427674025956656849179054202187436663487378682303508229883753383891163725167367039879190685255046547908384208614573353917213168937832054054779266431207529839577747601879940934691505396807977946728204814969824442867,
+ prime2 = 161367340863680900415977542864139121629424927689088951345472941851682581254789586032968359551717004797621579428672968948552429138154521719743297455351687337112710712475376510559020211584326773715482918387500187602625572442687231345855402020688502483137168684570635690059254866684191216155909970061793538842967,
+ exponent1 = 62591361464718491357252875682470452982324688977706206627659717747211409835899792394529826226951327414362102349476180842659595565881230839534930649963488383547255704844176717778780890830090016428673547367746320007264898765507470136725216211681602657590439205035957626212244060728285168687080542875871702744541,
+ exponent2 = 28476589564178982426348978152495139111074987239250991413906989738532220221433456358759122273832412611344984605059935696803369847909621479954699550944415412431654831613301737157474154985469430655673456186029444871051571607533040825739188591886206320553618003159523945304574388238386685203984112363845918619347,
+ coefficient = 34340318160575773065401929915821192439103777558577109939078671096408836197675640654693301707202885840826672396546056002756167635035389371579540325327619480512374920136684787633921441576901246290213545161954865184290700344352088099063404416346968182170720521708773285279884132629954461545103181082503707725012,
+ otherPrimeInfos = asn1_NOVALUE};
+
hardcode_rsa_key(5) ->
-{'RSAPrivateKey',0,
- 26363170152814518327068346871197765236382539835597898797762992537312221863402655353436079974302838986536256364057947538018476963115004626096654613827403121905035011992899481598437933532388248462251770039307078647864188314916665766359828262009578648593031111569685489178543405615478739906285223620987558499488359880003693226535420421293716164794046859453204135383236667988765227190694994861629971618548127529849059769249520775574008363789050621665120207265361610436965088511042779948238320901918522125988916609088415989475825860046571847719492980547438560049874493788767083330042728150253120940100665370844282489982633,
- 17,
- 10855423004100095781734025182257903332628104638187370093196526338893267826106975733767797636477639582691399679317978398007608161282648963686857782164224814902073240232370374775827384395689278778574258251479385325591136364965685903795223402003944149420659869469870495544106108194608892902588033255700759382142132115013969680562678811046675523365751498355532768935784747314021422035957153013494814430893022253205880275287307995039363642554998244274484818208792520243113824379110193356010059999642946040953102866271737127640405568982049887176990990501963784502429481034227543991366980671390566584211881030995602076468001,
- 163564135568104310461344551909369650951960301778977149705601170951529791054750122905880591964737953456660497440730575925978769763154927541340839715938951226089095007207042122512586007411328664679011914120351043948122025612160733403945093961374276707993674792189646478659304624413958625254578122842556295400709,
- 161179405627326572739107057023381254841260287988433675196680483761672455172873134522398837271764104320975746111042211695289319249471386600030523328069395763313848583139553961129874895374324504709512019736703349829576024049432816885712623938437949550266365056310544300920756181033500610331519029869549723159637,
- 115457036871603042678596154288966812436677860079277988027483179495197499568058910286503947269226790675289762899339230065396778656344654735064122152427494983121714122734382674714766593466820233891067233496718383963380253373289929461608301619793607087995535147427985749641862087821617853120878674947686796753441,
- 142217122612346975946270932667689342506994371754500301644129838613240401623123353990351915239791856753802128921507833848784693455415929352968108818884760967629866396887841730408713142977345151214275311532385308673155315337734838428569962298621720191411498579097539089047726042088382891468987379296661520434973,
- 40624877259097915043489529504071755460170951428490878553842519165800720914888257733191322215286203357356050737713125202129282154441426952501134581314792133018830748896123382106683994268028624341502298766844710276939303555637478596035491641473828661569958212421472263269629366559343208764012473880251174832392,
- asn1_NOVALUE};
+ #'RSAPrivateKey'{
+ version= 'two-prime',
+ modulus = 26363170152814518327068346871197765236382539835597898797762992537312221863402655353436079974302838986536256364057947538018476963115004626096654613827403121905035011992899481598437933532388248462251770039307078647864188314916665766359828262009578648593031111569685489178543405615478739906285223620987558499488359880003693226535420421293716164794046859453204135383236667988765227190694994861629971618548127529849059769249520775574008363789050621665120207265361610436965088511042779948238320901918522125988916609088415989475825860046571847719492980547438560049874493788767083330042728150253120940100665370844282489982633,
+ publicExponent = 17,
+ privateExponent = 10855423004100095781734025182257903332628104638187370093196526338893267826106975733767797636477639582691399679317978398007608161282648963686857782164224814902073240232370374775827384395689278778574258251479385325591136364965685903795223402003944149420659869469870495544106108194608892902588033255700759382142132115013969680562678811046675523365751498355532768935784747314021422035957153013494814430893022253205880275287307995039363642554998244274484818208792520243113824379110193356010059999642946040953102866271737127640405568982049887176990990501963784502429481034227543991366980671390566584211881030995602076468001,
+ prime1 =163564135568104310461344551909369650951960301778977149705601170951529791054750122905880591964737953456660497440730575925978769763154927541340839715938951226089095007207042122512586007411328664679011914120351043948122025612160733403945093961374276707993674792189646478659304624413958625254578122842556295400709,
+ prime2 = 161179405627326572739107057023381254841260287988433675196680483761672455172873134522398837271764104320975746111042211695289319249471386600030523328069395763313848583139553961129874895374324504709512019736703349829576024049432816885712623938437949550266365056310544300920756181033500610331519029869549723159637,
+ exponent1 = 115457036871603042678596154288966812436677860079277988027483179495197499568058910286503947269226790675289762899339230065396778656344654735064122152427494983121714122734382674714766593466820233891067233496718383963380253373289929461608301619793607087995535147427985749641862087821617853120878674947686796753441,
+ exponent2 = 142217122612346975946270932667689342506994371754500301644129838613240401623123353990351915239791856753802128921507833848784693455415929352968108818884760967629866396887841730408713142977345151214275311532385308673155315337734838428569962298621720191411498579097539089047726042088382891468987379296661520434973,
+ coefficient = 40624877259097915043489529504071755460170951428490878553842519165800720914888257733191322215286203357356050737713125202129282154441426952501134581314792133018830748896123382106683994268028624341502298766844710276939303555637478596035491641473828661569958212421472263269629366559343208764012473880251174832392,
+ otherPrimeInfos = asn1_NOVALUE};
hardcode_rsa_key(6) ->
-{'RSAPrivateKey',0,
- 22748888494866396715768692484866595111939200209856056370972713870125588774286266397044592487895293134537316190976192161177144143633669641697309689280475257429554879273045671863645233402796222694405634510241820106743648116753479926387434021380537483429927516962909367257212902212159798399531316965145618774905828756510318897899298783143203190245236381440043169622358239226123652592179006905016804587837199618842875361941208299410035232803124113612082221121192550063791073372276763648926636149384299189072950588522522800393261949880796214514243704858378436010975184294077063518776479282353562934591448646412389762167039,
- 17,
- 6690849557313646092873144848490175032923294179369428344403739373566349639495960705013115437616262686628622409110644753287395336362844012263914614494257428655751435080307550548130951000822418439531068973600535325512837681398082331290421770994275730420566916753796872722709677121223470117509210872101652580854566448661533030419787125312956120661097410038933324613372774190658239039998357548275441758790939430824924502690997433186652165055694361752689819209062683281242276039100201318203707142383491769671330743466041394101421674581185260900666085723130684175548215193875544802254923825103844262661010117443222587769713,
- 164748737139489923768181260808494855987398781964531448608652166632780898215212977127034263859971474195908846263894581556691971503119888726148555271179103885786024920582830105413607436718060544856016793981261118694063993837665813285582095833772675610567592660039821387740255651489996976698808018635344299728063,
- 138082323967104548254375818343885141517788525705334488282154811252858957969378263753268344088034079842223206527922445018725900110643394926788280539200323021781309918753249061620424428562366627334409266756720941754364262467100514166396917565961434203543659974860389803369482625510495464845206228470088664021953,
- 19382204369351755737433089506881747763223386113474288071606137250915399790025056132592266336467232258342217207517009594904937823896457497193947678962247515974826461245038835931012639613889475865413740468383661022831058098548919210068481862796785365949128548239978986792971253116470232552800943368864035262125,
- 48734937870742781736838524121371226418043009072470995864289933383361985165662916618800592031070851709019955245149098241903258862580021738866451955011878713569874088971734962924855680669070574353320917678842685325069739694270769705787147376221682660074232932303666989424523279591939575827719845342384234360689,
- 81173034184183681160439870161505779100040258708276674532866007896310418779840630960490793104541748007902477778658270784073595697910785917474138815202903114440800310078464142273778315781957021015333260021813037604142367434117205299831740956310682461174553260184078272196958146289378701001596552915990080834227,
- asn1_NOVALUE}.
-
-
-dtls_hello() ->
- [1,
- <<0,1,4>>,
- <<0,0>>,
- <<0,0,0>>,
- <<0,1,4>>,
- <<254,253,88,
- 156,129,61,
- 131,216,15,
- 131,194,242,
- 46,154,190,
- 20,228,234,
- 234,150,44,
- 62,96,96,103,
- 127,95,103,
- 23,24,42,138,
- 13,142,32,57,
- 230,177,32,
- 210,154,152,
- 188,121,134,
- 136,53,105,
- 118,96,106,
- 103,231,223,
- 133,10,165,
- 50,32,211,
- 227,193,14,
- 181,143,48,
- 66,0,0,100,0,
- 255,192,44,
- 192,48,192,
- 36,192,40,
- 192,46,192,
- 50,192,38,
- 192,42,0,159,
- 0,163,0,107,
- 0,106,0,157,
- 0,61,192,43,
- 192,47,192,
- 35,192,39,
- 192,45,192,
- 49,192,37,
- 192,41,0,158,
- 0,162,0,103,
- 0,64,0,156,0,
- 60,192,10,
- 192,20,0,57,
- 0,56,192,5,
- 192,15,0,53,
- 192,8,192,18,
- 0,22,0,19,
- 192,3,192,13,
- 0,10,192,9,
- 192,19,0,51,
- 0,50,192,4,
- 192,14,0,47,
- 1,0,0,86,0,0,
- 0,14,0,12,0,
- 0,9,108,111,
- 99,97,108,
- 104,111,115,
- 116,0,10,0,
- 58,0,56,0,14,
- 0,13,0,25,0,
- 28,0,11,0,12,
- 0,27,0,24,0,
- 9,0,10,0,26,
- 0,22,0,23,0,
- 8,0,6,0,7,0,
- 20,0,21,0,4,
- 0,5,0,18,0,
- 19,0,1,0,2,0,
- 3,0,15,0,16,
- 0,17,0,11,0,
- 2,1,0>>].
-
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus = 22748888494866396715768692484866595111939200209856056370972713870125588774286266397044592487895293134537316190976192161177144143633669641697309689280475257429554879273045671863645233402796222694405634510241820106743648116753479926387434021380537483429927516962909367257212902212159798399531316965145618774905828756510318897899298783143203190245236381440043169622358239226123652592179006905016804587837199618842875361941208299410035232803124113612082221121192550063791073372276763648926636149384299189072950588522522800393261949880796214514243704858378436010975184294077063518776479282353562934591448646412389762167039,
+ publicExponent = 17,
+ privateExponent = 6690849557313646092873144848490175032923294179369428344403739373566349639495960705013115437616262686628622409110644753287395336362844012263914614494257428655751435080307550548130951000822418439531068973600535325512837681398082331290421770994275730420566916753796872722709677121223470117509210872101652580854566448661533030419787125312956120661097410038933324613372774190658239039998357548275441758790939430824924502690997433186652165055694361752689819209062683281242276039100201318203707142383491769671330743466041394101421674581185260900666085723130684175548215193875544802254923825103844262661010117443222587769713,
+ prime1 = 164748737139489923768181260808494855987398781964531448608652166632780898215212977127034263859971474195908846263894581556691971503119888726148555271179103885786024920582830105413607436718060544856016793981261118694063993837665813285582095833772675610567592660039821387740255651489996976698808018635344299728063,
+ prime2 = 138082323967104548254375818343885141517788525705334488282154811252858957969378263753268344088034079842223206527922445018725900110643394926788280539200323021781309918753249061620424428562366627334409266756720941754364262467100514166396917565961434203543659974860389803369482625510495464845206228470088664021953,
+ exponent1 = 19382204369351755737433089506881747763223386113474288071606137250915399790025056132592266336467232258342217207517009594904937823896457497193947678962247515974826461245038835931012639613889475865413740468383661022831058098548919210068481862796785365949128548239978986792971253116470232552800943368864035262125,
+ exponent2 = 48734937870742781736838524121371226418043009072470995864289933383361985165662916618800592031070851709019955245149098241903258862580021738866451955011878713569874088971734962924855680669070574353320917678842685325069739694270769705787147376221682660074232932303666989424523279591939575827719845342384234360689,
+ coefficient = 81173034184183681160439870161505779100040258708276674532866007896310418779840630960490793104541748007902477778658270784073595697910785917474138815202903114440800310078464142273778315781957021015333260021813037604142367434117205299831740956310682461174553260184078272196958146289378701001596552915990080834227,
+ otherPrimeInfos = asn1_NOVALUE}.
+
+hardcode_dsa_key(1) ->
+ {'DSAPrivateKey',0,
+ 99438313664986922963487511141216248076486724382260996073922424025828494981416579966171753999204426907349400798052572573634137057487829150578821328280864500098312146772602202702021153757550650696224643730869835650674962433068943942837519621267815961566259265204876799778977478160416743037274938277357237615491,
+ 1454908511695148818053325447108751926908854531909,
+ 20302424198893709525243209250470907105157816851043773596964076323184805650258390738340248469444700378962907756890306095615785481696522324901068493502141775433048117442554163252381401915027666416630898618301033737438756165023568220631119672502120011809327566543827706483229480417066316015458225612363927682579,
+ 48598545580251057979126570873881530215432219542526130654707948736559463436274835406081281466091739849794036308281564299754438126857606949027748889019480936572605967021944405048011118039171039273602705998112739400664375208228641666852589396502386172780433510070337359132965412405544709871654840859752776060358,
+ 1457508827177594730669011716588605181448418352823};
+hardcode_dsa_key(2) ->
+ #'DSAPrivateKey'{
+ version = 0,
+ p = 145447354557382582722944332987784622105075065624518040072393858097520305927329240484963764783346271194321683798321743658303478090647837211867389721684646254999291098347011037298359107547264573476540026676832159205689428125157386525591130716464335426605521884822982379206842523670736739023467072341958074788151,
+ q = 742801637799670234315651916144768554943688916729,
+ g = 79727684678125120155622004643594683941478642656111969487719464672433839064387954070113655822700268007902716505761008423792735229036965034283173483862273639257533568978482104785033927768441235063983341565088899599358397638308472931049309161811156189887217888328371767967629005149630676763492409067382020352505,
+ y = 35853727034965131665219275925554159789667905059030049940938124723126925435403746979702929280654735557166864135215989313820464108440192507913554896358611966877432546584986661291483639036057475682547385322659469460385785257933737832719745145778223672383438466035853830832837226950912832515496378486927322864228,
+ x = 801315110178350279541885862867982846569980443911};
+hardcode_dsa_key(3) ->
+ #'DSAPrivateKey'{
+ version = 0,
+ p = 99438313664986922963487511141216248076486724382260996073922424025828494981416579966171753999204426907349400798052572573634137057487829150578821328280864500098312146772602202702021153757550650696224643730869835650674962433068943942837519621267815961566259265204876799778977478160416743037274938277357237615491,
+ q = 1454908511695148818053325447108751926908854531909,
+ g = 20302424198893709525243209250470907105157816851043773596964076323184805650258390738340248469444700378962907756890306095615785481696522324901068493502141775433048117442554163252381401915027666416630898618301033737438756165023568220631119672502120011809327566543827706483229480417066316015458225612363927682579,
+ y = 48598545580251057979126570873881530215432219542526130654707948736559463436274835406081281466091739849794036308281564299754438126857606949027748889019480936572605967021944405048011118039171039273602705998112739400664375208228641666852589396502386172780433510070337359132965412405544709871654840859752776060358,
+ x = 1457508827177594730669011716588605181448418352823}.
+
+tcp_delivery_workaround(Server, ServerMsg, Client, ClientMsg) ->
+ receive
+ {Server, ServerMsg} ->
+ client_msg(Client, ClientMsg);
+ {Client, ClientMsg} ->
+ server_msg(Server, ServerMsg);
+ {Client, {error,closed}} ->
+ server_msg(Server, ServerMsg);
+ {Server, {error,closed}} ->
+ client_msg(Client, ClientMsg)
+ end.
+client_msg(Client, ClientMsg) ->
+ receive
+ {Client, ClientMsg} ->
+ ok;
+ {Client, {error,closed}} ->
+ ct:log("client got close"),
+ ok;
+ {Client, {error, Reason}} ->
+ ct:log("client got econnaborted: ~p", [Reason]),
+ ok;
+ Unexpected ->
+ ct:fail(Unexpected)
+ end.
+server_msg(Server, ServerMsg) ->
+ receive
+ {Server, ServerMsg} ->
+ ok;
+ {Server, {error,closed}} ->
+ ct:log("server got close"),
+ ok;
+ {Server, {error, Reason}} ->
+ ct:log("server got econnaborted: ~p", [Reason]),
+ ok;
+ Unexpected ->
+ ct:fail(Unexpected)
+ end.
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index 5093ef3728..5a38f5f9c1 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -37,31 +37,47 @@
%%--------------------------------------------------------------------
all() ->
- [
- {group, basic},
- {group, 'tlsv1.2'},
- {group, 'tlsv1.1'},
- {group, 'tlsv1'},
- {group, 'sslv3'},
- {group, 'dtlsv1.2'},
- {group, 'dtlsv1'}
- ].
+ case ssl_test_lib:openssl_sane_dtls() of
+ true ->
+ [{group, basic},
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}];
+ false ->
+ [{group, basic},
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'}]
+ end.
groups() ->
- [{basic, [], basic_tests()},
- {'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()}
- ].
-
+ case ssl_test_lib:openssl_sane_dtls() of
+ true ->
+ [{basic, [], basic_tests()},
+ {'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 ->
+ [{basic, [], basic_tests()},
+ {'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.
+
basic_tests() ->
[basic_erlang_client_openssl_server,
basic_erlang_server_openssl_client,
- expired_session,
- ssl2_erlang_server_openssl_client_comp
+ expired_session
].
all_versions_tests() ->
@@ -70,6 +86,9 @@ all_versions_tests() ->
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,
@@ -83,22 +102,32 @@ all_versions_tests() ->
expired_session,
ssl2_erlang_server_openssl_client
].
+
dtls_all_versions_tests() ->
- [
- %%erlang_client_openssl_server,
+ 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_client_openssl_server_dsa_cert,
erlang_server_openssl_client_dsa_cert,
- erlang_server_openssl_client_reuse_session
- %%erlang_client_openssl_server_renegotiate,
- %%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,
+ 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
].
@@ -135,56 +164,69 @@ sni_server_tests() ->
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(),
- {ok, _} = make_certs:all(proplists:get_value(data_dir, Config0),
- proplists:get_value(priv_dir, Config0)),
- Config1 = ssl_test_lib:make_dsa_cert(Config0),
- Config = ssl_test_lib:cert_options(Config1),
- ssl_test_lib:cipher_restriction(Config)
- catch _:_ ->
- {skip, "Crypto did not start"}
- end
+ 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).
-init_per_group(basic, Config) ->
- case ssl_test_lib:supports_ssl_tls_version(sslv2) of
- true ->
- [{v2_hello_compatible, true} | Config];
- false ->
- [{v2_hello_compatible, false} | Config]
+init_per_group(basic, Config0) ->
+ case ssl_test_lib:supports_ssl_tls_version('tlsv1.2')
+ orelse ssl_test_lib:supports_ssl_tls_version('tlsv1.1')
+ orelse ssl_test_lib:supports_ssl_tls_version('tlsv1')
+ of
+ true ->
+ ssl_test_lib:clean_tls_version(Config0);
+ false ->
+ {skip, "only sslv3 supported by OpenSSL"}
end;
+
init_per_group(GroupName, Config) ->
case ssl_test_lib:is_tls_version(GroupName) of
- true ->
+ true ->
case ssl_test_lib:supports_ssl_tls_version(GroupName) of
- true ->
+ true ->
case ssl_test_lib:check_sane_openssl_version(GroupName) of
- true ->
+ true ->
ssl_test_lib:init_tls_version(GroupName, Config);
- false ->
+ false ->
{skip, openssl_does_not_support_version}
end;
false ->
{skip, openssl_does_not_support_version}
end;
- _ ->
- ssl:start(),
- Config
+ _ ->
+ ssl:start(),
+ Config
end.
-end_per_group(_GroupName, Config) ->
- Config.
+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),
@@ -192,99 +234,121 @@ init_per_testcase(expired_session, Config) ->
application:load(ssl),
application:set_env(ssl, session_lifetime, ?EXPIRE),
ssl:start(),
- Config;
-
-init_per_testcase(TestCase, Config) when TestCase == ciphers_rsa_signed_certs;
- TestCase == ciphers_dsa_signed_certs ->
- ct:timetrap({seconds, 45}),
- special_init(TestCase, Config);
-
+ 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() of
+ true ->
+ special_init(TestCase, Config);
+ false ->
+ {skip, "DSA not supported by OpenSSL"}
+ end;
init_per_testcase(TestCase, Config) ->
- ct:timetrap({seconds, 20}),
+ 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_client_openssl_server_nowrap_seqnum;
TestCase == erlang_server_openssl_client_nowrap_seqnum
- ->
+ ->
{ok, Version} = application:get_env(ssl, protocol_version),
check_sane_openssl_renegotaite(Config, Version);
-special_init(Case, Config) when Case == ssl2_erlang_server_openssl_client;
- Case == ssl2_erlang_server_openssl_client_comp ->
+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;
+ 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 ->
+ 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;
+ 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 ->
+ 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)
+ 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 ->
+ 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, Config)
+ 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(_, Config) ->
- Config.
+ Config.
end_per_testcase(reuse_session_expired, Config) ->
application:unset_env(ssl, session_lifetime),
- Config;
+ Config;
end_per_testcase(_, Config) ->
Config.
@@ -295,8 +359,8 @@ basic_erlang_client_openssl_server() ->
[{doc,"Test erlang client with openssl server"}].
basic_erlang_client_openssl_server(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ 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),
@@ -307,8 +371,8 @@ basic_erlang_client_openssl_server(Config) when is_list(Config) ->
KeyFile = proplists:get_value(keyfile, ServerOpts),
Exe = "openssl",
- Args = ["s_server", "-accept", integer_to_list(Port),
- "-cert", CertFile, "-key", KeyFile],
+ Args = ["s_server", "-accept", integer_to_list(Port),
+ "-cert", CertFile, "-key", KeyFile],
OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
@@ -316,15 +380,15 @@ basic_erlang_client_openssl_server(Config) when is_list(Config) ->
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}]),
+ {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),
@@ -335,23 +399,29 @@ basic_erlang_server_openssl_client() ->
[{doc,"Test erlang server with openssl client"}].
basic_erlang_server_openssl_client(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- V2Compat = proplists:get_value(v2_hello_compatible, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Data = "From openssl to erlang",
- ct:pal("v2_hello_compatible: ~p", [V2Compat]),
-
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
- {options,[{v2_hello_compatible, V2Compat} | ServerOpts]}]),
+ {from, self()},
+ {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
+ {options,ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
Exe = "openssl",
- Args = ["s_client", "-connect", "localhost:" ++ integer_to_list(Port) | workaround_openssl_s_clinent()],
+ Args = case no_low_flag("-no_ssl2") of
+ [] ->
+ ["s_client", "-connect", hostname_format(Hostname) ++
+ ":" ++ integer_to_list(Port), no_low_flag("-no_ssl3")
+ | workaround_openssl_s_clinent()];
+ Flag ->
+ ["s_client", "-connect", hostname_format(Hostname) ++
+ ":" ++ integer_to_list(Port), no_low_flag("-no_ssl3"), Flag
+ | workaround_openssl_s_clinent()]
+ end,
OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
true = port_command(OpenSslPort, Data),
@@ -368,8 +438,8 @@ 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_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ 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),
@@ -381,19 +451,19 @@ erlang_client_openssl_server(Config) when is_list(Config) ->
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],
-
+ 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}]),
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE,
+ erlang_ssl_receive, [Data]}},
+ {options, ClientOpts}]),
true = port_command(OpensslPort, Data),
ssl_test_lib:check_result(Client, ok),
@@ -408,25 +478,25 @@ 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_opts, Config),
-
- {_, ServerNode, _} = ssl_test_lib:run_where(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, {?MODULE, erlang_ssl_receive, [Data]}},
- {options, ServerOpts}]),
+ {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", "localhost: " ++ integer_to_list(Port),
- ssl_test_lib:version_flag(Version)],
-
- OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+ 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),
@@ -441,10 +511,10 @@ erlang_client_openssl_server_dsa_cert() ->
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_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_dsa_verify_opts, Config),
+
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
- {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
-
Data = "From openssl to erlang",
Port = ssl_test_lib:inet_port(node()),
@@ -454,27 +524,27 @@ erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) ->
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"],
+ 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}]),
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE,
+ erlang_ssl_receive, [Data]}},
+ {options, ClientOpts}]),
true = port_command(OpensslPort, Data),
- ssl_test_lib:check_result(Client, ok),
-
+ 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_port(OpensslPort),
ssl_test_lib:close(Client),
process_flag(trap_exit, false),
ok.
@@ -486,7 +556,7 @@ erlang_server_openssl_client_dsa_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),
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Data = "From openssl to erlang",
CaCertFile = proplists:get_value(cacertfile, ClientOpts),
@@ -494,17 +564,17 @@ erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) ->
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}]),
+ {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", "localhost: " ++ integer_to_list(Port),
- ssl_test_lib:version_flag(Version),
- "-cert", CertFile,
- "-CAfile", CaCertFile,
- "-key", KeyFile, "-msg"],
+ 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),
@@ -516,31 +586,161 @@ erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) ->
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."}].
+ "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_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- {_, ServerNode, _} = ssl_test_lib:run_where(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}]),
+ {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", "localhost:" ++ integer_to_list(Port),
- ssl_test_lib:version_flag(Version),
- "-reconnect"],
+ 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),
@@ -551,7 +751,7 @@ erlang_server_openssl_client_reuse_session(Config) when is_list(Config) ->
%% 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),
+ process_flag(trap_exit, false),
ok.
%%--------------------------------------------------------------------
@@ -560,8 +760,8 @@ erlang_client_openssl_server_renegotiate() ->
[{doc,"Test erlang client when openssl server issuses a renegotiate"}].
erlang_client_openssl_server_renegotiate(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ 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),
@@ -575,46 +775,46 @@ erlang_client_openssl_server_renegotiate(Config) when is_list(Config) ->
Exe = "openssl",
Args = ["s_server", "-accept", integer_to_list(Port),
- ssl_test_lib:version_flag(Version),
- "-cert", CertFile, "-key", KeyFile, "-msg"],
+ 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,
- delayed_send, [[ErlData, OpenSslData]]}},
- {options, ClientOpts}]),
+ {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 !!
+
+ %% 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),
+ 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."}].
+ "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_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ 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),
-
+
ErlData = "From erlang to openssl\n",
N = 10,
@@ -624,21 +824,21 @@ erlang_client_openssl_server_nowrap_seqnum(Config) when is_list(Config) ->
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"],
-
+ 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, {ssl_test_lib,
- trigger_renegotiate, [[ErlData, N+2]]}},
- {options, [{reuse_sessions, false},
- {renegotiate_at, N} | ClientOpts]}]),
-
+ {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 !!
@@ -648,37 +848,37 @@ erlang_client_openssl_server_nowrap_seqnum(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
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."}].
+ "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_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- {_, ServerNode, _} = 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]}]),
+ {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", "localhost: " ++ integer_to_list(Port),
- ssl_test_lib:version_flag(Version),
- "-msg"],
-
+ 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),
@@ -688,15 +888,15 @@ erlang_server_openssl_client_nowrap_seqnum(Config) when is_list(Config) ->
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."}].
+ "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_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ 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()),
@@ -705,22 +905,22 @@ erlang_client_openssl_server_no_server_ca_cert(Config) when is_list(Config) ->
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"],
-
+ 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}]),
+ {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 !!
@@ -733,13 +933,13 @@ 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_verification_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
-
+
Data = "From openssl to erlang",
-
+
Port = ssl_test_lib:inet_port(node()),
CertFile = proplists:get_value(certfile, ServerOpts),
CaCertFile = proplists:get_value(cacertfile, ServerOpts),
@@ -747,104 +947,102 @@ erlang_client_openssl_server_client_cert(Config) when is_list(Config) ->
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"],
-
+ 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}]),
+ {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_verification_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
+ 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),
- {_, ServerNode, _} = 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]}]),
+ {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", "localhost:" ++ integer_to_list(Port),
- ssl_test_lib:version_flag(Version)],
+ "-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_verification_opts, Config),
- ClientOpts = proplists:get_value(client_verification_opts, Config),
+ 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]}]),
+ {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]}]),
-
+ {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).
@@ -863,7 +1061,8 @@ 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),
- Ciphers = ssl_test_lib:dsa_suites(tls_record:protocol_version(Version)),
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl_test_lib:dsa_suites(NVersion),
run_suites(Ciphers, Version, Config, dsa).
%%--------------------------------------------------------------------
@@ -871,47 +1070,47 @@ 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_verification_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
+ 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],
+ "-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]}]),
-
+ {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_msg, []}},
- {options,
- [{versions, [Version]} | ClientOpts]}]),
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result_msg, []}},
+ {options,
+ [{versions, [Version]} | ClientOpts]}]),
%% Clean close down! Server needs to be closed first !!
ssl_test_lib:close_port(OpensslPort),
@@ -926,8 +1125,8 @@ expired_session() ->
"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_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ 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()),
@@ -936,38 +1135,38 @@ expired_session(Config) when is_list(Config) ->
Exe = "openssl",
Args = ["s_server", "-accept", integer_to_list(Port),
- "-cert", CertFile,"-key", KeyFile],
-
+ "-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: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: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}]),
+ 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),
@@ -980,55 +1179,24 @@ ssl2_erlang_server_openssl_client() ->
ssl2_erlang_server_openssl_client(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
-
- {_, ServerNode, _} = 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", "localhost:" ++ 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()]]),
- consume_port_exit(OpenSslPort),
- ssl_test_lib:check_result(Server, {error, {tls_alert, "handshake failure"}}),
- process_flag(trap_exit, false).
-%%--------------------------------------------------------------------
-ssl2_erlang_server_openssl_client_comp() ->
- [{doc,"Test that ssl v2 clients are rejected"}].
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
-ssl2_erlang_server_openssl_client_comp(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- V2Compat = proplists:get_value(v2_hello_compatible, Config),
-
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
-
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
-
- Data = "From openssl to erlang",
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {options, [{v2_hello_compatible, V2Compat} | ServerOpts]}]),
+ {from, self()},
+ {options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
-
+
Exe = "openssl",
- Args = ["s_client", "-connect", "localhost:" ++ integer_to_list(Port),
- "-ssl2", "-msg"],
-
+ Args = ["s_client", "-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
+ "-ssl2", "-msg"],
+
OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
- true = port_command(OpenSslPort, Data),
-
+
ct:log("Ports ~p~n", [[erlang:port_info(P) || P <- erlang:ports()]]),
- consume_port_exit(OpenSslPort),
- ssl_test_lib:check_result(Server, {error, {tls_alert, "protocol version"}}),
+ ssl_test_lib:consume_port_exit(OpenSslPort),
+ ssl_test_lib:check_result(Server, {error, {tls_alert, "bad record mac"}}),
process_flag(trap_exit, false).
%%--------------------------------------------------------------------
@@ -1248,22 +1416,22 @@ erlang_server_openssl_client_npn_only_client(Config) when is_list(Config) ->
ok.
%--------------------------------------------------------------------------
erlang_server_openssl_client_sni_no_header(Config) when is_list(Config) ->
- erlang_server_openssl_client_sni_test(Config, undefined, undefined, "server").
+ 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").
+ 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", "a.server").
+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", "a.server").
+ 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").
+ 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").
+ erlang_server_openssl_client_sni_test_sni_fun(Config, "c.server", undefined, "server Peer cert").
%%--------------------------------------------------------------------
@@ -1273,11 +1441,11 @@ run_suites(Ciphers, Version, Config, Type) ->
{ClientOpts, ServerOpts} =
case Type of
rsa ->
- {ssl_test_lib:ssl_options(client_opts, Config),
- ssl_test_lib:ssl_options(server_opts, Config)};
+ {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_opts, Config),
- ssl_test_lib:ssl_options(server_dsa_opts, Config)}
+ {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) ->
@@ -1330,7 +1498,7 @@ send_and_hostname(SSLSocket) ->
erlang_server_openssl_client_sni_test(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) ->
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_opts, Config),
+ 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, []}},
@@ -1344,11 +1512,7 @@ erlang_server_openssl_client_sni_test(Config, SNIHostname, ExpectedSNIHostname,
openssl_client_args(ssl_test_lib:supports_ssl_tls_version(sslv2), Hostname, Port, SNIHostname)
end,
ClientPort = ssl_test_lib:portable_open_port(Exe, ClientArgs),
-
- %% Client check needs to be done befor server check,
- %% or server check might consume client messages
- ExpectedClientOutput = ["OK", "/CN=" ++ ExpectedCN ++ "/"],
- client_check_result(ClientPort, ExpectedClientOutput),
+
ssl_test_lib:check_result(Server, ExpectedSNIHostname),
ssl_test_lib:close_port(ClientPort),
ssl_test_lib:close(Server),
@@ -1359,7 +1523,7 @@ erlang_server_openssl_client_sni_test_sni_fun(Config, SNIHostname, ExpectedSNIHo
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_opts, Config) ++ [{sni_fun, SNIFun}],
+ 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, []}},
@@ -1375,10 +1539,6 @@ erlang_server_openssl_client_sni_test_sni_fun(Config, SNIHostname, ExpectedSNIHo
ClientPort = ssl_test_lib:portable_open_port(Exe, ClientArgs),
- %% Client check needs to be done befor server check,
- %% or server check might consume client messages
- ExpectedClientOutput = ["OK", "/CN=" ++ ExpectedCN ++ "/"],
- client_check_result(ClientPort, ExpectedClientOutput),
ssl_test_lib:check_result(Server, ExpectedSNIHostname),
ssl_test_lib:close_port(ClientPort),
ssl_test_lib:close(Server).
@@ -1442,8 +1602,8 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) ->
start_erlang_client_and_openssl_server_with_opts(Config, ErlangClientOpts, OpensslServerOpts, Data, Callback) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- ClientOpts0 = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
ClientOpts = ErlangClientOpts ++ ClientOpts0,
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -1488,8 +1648,8 @@ start_erlang_client_and_openssl_server_with_opts(Config, ErlangClientOpts, Opens
start_erlang_client_and_openssl_server_for_alpn_negotiation(Config, Data, Callback) ->
process_flag(trap_exit, true),
- ServerOpts = proplists:get_value(server_opts, Config),
- ClientOpts0 = proplists:get_value(client_opts, Config),
+ ServerOpts = proplists:get_value(server_rsa_opts, Config),
+ ClientOpts0 = proplists:get_value(client_rsa_opts, Config),
ClientOpts = [{alpn_advertised_protocols, [<<"spdy/2">>]} | ClientOpts0],
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -1524,7 +1684,7 @@ start_erlang_client_and_openssl_server_for_alpn_negotiation(Config, Data, Callba
start_erlang_server_and_openssl_client_for_alpn_negotiation(Config, Data, Callback) ->
process_flag(trap_exit, true),
- ServerOpts0 = proplists:get_value(server_opts, Config),
+ ServerOpts0 = proplists:get_value(server_rsa_opts, Config),
ServerOpts = [{alpn_preferred_protocols, [<<"spdy/2">>]} | ServerOpts0],
{_, ServerNode, _} = ssl_test_lib:run_where(Config),
@@ -1553,8 +1713,8 @@ start_erlang_server_and_openssl_client_for_alpn_negotiation(Config, Data, Callba
start_erlang_client_and_openssl_server_for_alpn_npn_negotiation(Config, Data, Callback) ->
process_flag(trap_exit, true),
- ServerOpts = proplists:get_value(server_opts, Config),
- ClientOpts0 = proplists:get_value(client_opts, Config),
+ 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],
@@ -1593,7 +1753,7 @@ start_erlang_client_and_openssl_server_for_alpn_npn_negotiation(Config, Data, Ca
start_erlang_server_and_openssl_client_for_alpn_npn_negotiation(Config, Data, Callback) ->
process_flag(trap_exit, true),
- ServerOpts0 = proplists:get_value(server_opts, Config),
+ ServerOpts0 = proplists:get_value(server_rsa_opts, Config),
ServerOpts = [{alpn_preferred_protocols, [<<"spdy/2">>]},
{next_protocols_advertised, [<<"spdy/3">>, <<"http/1.1">>]} | ServerOpts0],
@@ -1620,8 +1780,8 @@ start_erlang_server_and_openssl_client_for_alpn_npn_negotiation(Config, Data, Ca
start_erlang_client_and_openssl_server_for_npn_negotiation(Config, Data, Callback) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- ClientOpts0 = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
ClientOpts = [{client_preferred_next_protocols, {client, [<<"spdy/2">>], <<"http/1.1">>}} | ClientOpts0],
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -1658,10 +1818,10 @@ start_erlang_client_and_openssl_server_for_npn_negotiation(Config, Data, Callbac
start_erlang_server_and_openssl_client_for_npn_negotiation(Config, Data, Callback) ->
process_flag(trap_exit, true),
- ServerOpts0 = ssl_test_lib:ssl_options(server_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
ServerOpts = [{next_protocols_advertised, [<<"spdy/2">>]}, ServerOpts0],
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
@@ -1672,7 +1832,8 @@ start_erlang_server_and_openssl_client_for_npn_negotiation(Config, Data, Callbac
Version = ssl_test_lib:protocol_version(Config),
Exe = "openssl",
- Args = ["s_client", "-nextprotoneg", "http/1.0,spdy/2", "-msg", "-connect", "localhost:"
+ 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),
@@ -1687,10 +1848,10 @@ start_erlang_server_and_openssl_client_for_npn_negotiation(Config, Data, Callbac
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_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
ServerOpts = ErlangServerOpts ++ ServerOpts0,
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
@@ -1701,8 +1862,9 @@ start_erlang_server_and_openssl_client_with_opts(Config, ErlangServerOpts, OpenS
Version = ssl_test_lib:protocol_version(Config),
Exe = "openssl",
- Args = ["s_client"] ++ OpenSSLClientOpts ++ ["-msg", "-connect", "localhost:" ++ integer_to_list(Port),
- ssl_test_lib:version_flag(Version)],
+ 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),
@@ -1849,8 +2011,35 @@ openssl_client_args(true, Hostname, Port, ServerName) ->
["s_client", "-no_ssl2", "-connect", Hostname ++ ":" ++
integer_to_list(Port), "-servername", ServerName].
-consume_port_exit(OpenSSLPort) ->
- receive
- {'EXIT', OpenSSLPort, _} ->
- ok
+hostname_format(Hostname) ->
+ case lists:member($., Hostname) of
+ true ->
+ Hostname;
+ false ->
+ "localhost"
+ end.
+
+no_low_flag("-no_ssl2" = Flag) ->
+ case ssl_test_lib:supports_ssl_tls_version(sslv2) of
+ true ->
+ Flag;
+ false ->
+ ""
+ end;
+no_low_flag(Flag) ->
+ Flag.
+
+
+openssl_has_common_ciphers(Ciphers) ->
+ OCiphers = ssl_test_lib:common_ciphers(openssl),
+ has_common_ciphers(Ciphers, OCiphers).
+
+has_common_ciphers([], OCiphers) ->
+ false;
+has_common_ciphers([Cipher | Rest], OCiphers) ->
+ case lists:member(Cipher, OCiphers) of
+ true ->
+ true;
+ _ ->
+ has_common_ciphers(Rest, OCiphers)
end.
diff --git a/lib/ssl/test/x509_test.erl b/lib/ssl/test/x509_test.erl
index 4da1537ef6..fea01efdaf 100644
--- a/lib/ssl/test/x509_test.erl
+++ b/lib/ssl/test/x509_test.erl
@@ -24,23 +24,10 @@
-include_lib("public_key/include/public_key.hrl").
- -export([gen_test_certs/1, gen_pem_config_files/3]).
+-export([extensions/1, gen_pem_config_files/3]).
- gen_test_certs(Opts) ->
- SRootKey = gen_key(proplists:get_value(server_key_gen, Opts)),
- CRootKey = gen_key(proplists:get_value(client_key_gen, Opts)),
- ServerRoot = root_cert("server", SRootKey, Opts),
- ClientRoot = root_cert("client", CRootKey, Opts),
- [{ServerCert, ServerKey} | ServerCAsKeys] = config(server, ServerRoot, SRootKey, Opts),
- [{ClientCert, ClientKey} | ClientCAsKeys] = config(client, ClientRoot, CRootKey, Opts),
- ServerCAs = ca_config(ClientRoot, ServerCAsKeys),
- ClientCAs = ca_config(ServerRoot, ClientCAsKeys),
- [{server_config, [{cert, ServerCert}, {key, ServerKey}, {cacerts, ServerCAs}]},
- {client_config, [{cert, ClientCert}, {key, ClientKey}, {cacerts, ClientCAs}]}].
-
-gen_pem_config_files(GenCertData, ClientBase, ServerBase) ->
- ServerConf = proplists:get_value(server_config, GenCertData),
- ClientConf = proplists:get_value(client_config, GenCertData),
+gen_pem_config_files(#{server_config := ServerConf,
+ client_config := ClientConf}, ClientBase, ServerBase) ->
ServerCaCertFile = ServerBase ++ "_server_cacerts.pem",
ServerCertFile = ServerBase ++ "_server_cert.pem",
@@ -62,147 +49,30 @@ gen_pem_config_files(GenCertData, ClientBase, ServerBase) ->
{keyfile, ServerKeyFile}, {cacertfile, ServerCaCertFile}]},
{client_config, [{certfile, ClientCertFile},
{keyfile, ClientKeyFile}, {cacertfile, ClientCaCertFile}]}].
+extensions(Exts) ->
+ [extension(Ext) || Ext <- Exts].
- do_gen_pem_config_files(Config, CertFile, KeyFile, CAFile) ->
- CAs = proplists:get_value(cacerts, Config),
- Cert = proplists:get_value(cert, Config),
- Key = proplists:get_value(key, Config),
- der_to_pem(CertFile, [cert_entry(Cert)]),
- der_to_pem(KeyFile, [key_entry(Key)]),
- der_to_pem(CAFile, ca_entries(CAs)).
-
- cert_entry(Cert) ->
- {'Certificate', Cert, not_encrypted}.
-
- key_entry(Key = #'RSAPrivateKey'{}) ->
- Der = public_key:der_encode('RSAPrivateKey', Key),
- {'RSAPrivateKey', Der, not_encrypted};
- key_entry(Key = #'DSAPrivateKey'{}) ->
- Der = public_key:der_encode('DSAPrivateKey', Key),
- {'DSAPrivateKey', Der, not_encrypted};
- key_entry(Key = #'ECPrivateKey'{}) ->
- Der = public_key:der_encode('ECPrivateKey', Key),
- {'ECPrivateKey', Der, not_encrypted}.
-
- ca_entries(CAs) ->
- [{'Certificate', CACert, not_encrypted} || CACert <- CAs].
-
- gen_key(KeyGen) ->
- case is_key(KeyGen) of
- true ->
- KeyGen;
- false ->
- public_key:generate_key(KeyGen)
- end.
-
-root_cert(Role, PrivKey, Opts) ->
- TBS = cert_template(),
- Issuer = issuer("root", Role, " ROOT CA"),
- OTPTBS = TBS#'OTPTBSCertificate'{
- signature = sign_algorithm(PrivKey, Opts),
- issuer = Issuer,
- validity = validity(Opts),
- subject = Issuer,
- subjectPublicKeyInfo = public_key(PrivKey),
- extensions = extensions(Role, ca, Opts)
- },
- public_key:pkix_sign(OTPTBS, PrivKey).
-
-config(Role, Root, Key, Opts) ->
- KeyGenOpt = list_to_atom(atom_to_list(Role) ++ "_key_gen_chain"),
- KeyGens = proplists:get_value(KeyGenOpt, Opts, default_key_gen()),
- Keys = lists:map(fun gen_key/1, KeyGens),
- cert_chain(Role, Root, Key, Opts, Keys).
+do_gen_pem_config_files(Config, CertFile, KeyFile, CAFile) ->
+ CAs = proplists:get_value(cacerts, Config),
+ Cert = proplists:get_value(cert, Config),
+ Key = proplists:get_value(key, Config),
+ der_to_pem(CertFile, [cert_entry(Cert)]),
+ der_to_pem(KeyFile, [key_entry(Key)]),
+ der_to_pem(CAFile, ca_entries(CAs)).
-cert_template() ->
- #'OTPTBSCertificate'{
- version = v3,
- serialNumber = trunc(rand:uniform()*100000000)*10000 + 1,
- issuerUniqueID = asn1_NOVALUE,
- subjectUniqueID = asn1_NOVALUE
- }.
+cert_entry(Cert) ->
+ {'Certificate', Cert, not_encrypted}.
-issuer(Contact, Role, Name) ->
- subject(Contact, Role ++ Name).
+key_entry({'RSAPrivateKey', DERKey}) ->
+ {'RSAPrivateKey', DERKey, not_encrypted};
+key_entry({'DSAPrivateKey', DERKey}) ->
+ {'DSAPrivateKey', DERKey, not_encrypted};
+key_entry({'ECPrivateKey', DERKey}) ->
+ {'ECPrivateKey', DERKey, not_encrypted}.
-subject(Contact, Name) ->
- Opts = [{email, Contact ++ "@erlang.org"},
- {name, Name},
- {city, "Stockholm"},
- {country, "SE"},
- {org, "erlang"},
- {org_unit, "automated testing"}],
- subject(Opts).
-
-subject(SubjectOpts) when is_list(SubjectOpts) ->
- Encode = fun(Opt) ->
- {Type,Value} = subject_enc(Opt),
- [#'AttributeTypeAndValue'{type=Type, value=Value}]
- end,
- {rdnSequence, [Encode(Opt) || Opt <- SubjectOpts]}.
-
-subject_enc({name, Name}) ->
- {?'id-at-commonName', {printableString, Name}};
-subject_enc({email, Email}) ->
- {?'id-emailAddress', Email};
-subject_enc({city, City}) ->
- {?'id-at-localityName', {printableString, City}};
-subject_enc({state, State}) ->
- {?'id-at-stateOrProvinceName', {printableString, State}};
-subject_enc({org, Org}) ->
- {?'id-at-organizationName', {printableString, Org}};
-subject_enc({org_unit, OrgUnit}) ->
- {?'id-at-organizationalUnitName', {printableString, OrgUnit}};
-subject_enc({country, Country}) ->
- {?'id-at-countryName', Country};
-subject_enc({serial, Serial}) ->
- {?'id-at-serialNumber', Serial};
-subject_enc({title, Title}) ->
- {?'id-at-title', {printableString, Title}};
-subject_enc({dnQualifer, DnQ}) ->
- {?'id-at-dnQualifier', DnQ};
-subject_enc(Other) ->
- Other.
-
-validity(Opts) ->
- DefFrom0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())-1),
- DefTo0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())+7),
- {DefFrom, DefTo} = proplists:get_value(validity, Opts, {DefFrom0, DefTo0}),
- Format = fun({Y,M,D}) ->
- lists:flatten(io_lib:format("~w~2..0w~2..0w000000Z",[Y,M,D]))
- end,
- #'Validity'{notBefore={generalTime, Format(DefFrom)},
- notAfter ={generalTime, Format(DefTo)}}.
-
-extensions(Role, Type, Opts) ->
- Exts = proplists:get_value(extensions, Opts, []),
- lists:flatten([extension(Ext) || Ext <- default_extensions(Role, Type, Exts)]).
-
-%% Common extension: name_constraints, policy_constraints, ext_key_usage, inhibit_any,
-%% auth_key_id, subject_key_id, policy_mapping,
-
-default_extensions(_, ca, Exts) ->
- Def = [{key_usage, [keyCertSign, cRLSign]},
- {basic_constraints, default}],
- add_default_extensions(Def, Exts);
-
-default_extensions(server, peer, Exts) ->
- Hostname = net_adm:localhost(),
- Def = [{key_usage, [digitalSignature, keyAgreement]},
- {subject_alt, Hostname}],
- add_default_extensions(Def, Exts);
-
-default_extensions(_, peer, Exts) ->
- Exts.
-
-add_default_extensions(Def, Exts) ->
- Filter = fun({Key, _}, D) ->
- lists:keydelete(Key, 1, D);
- ({Key, _, _}, D) ->
- lists:keydelete(Key, 1, D)
- end,
- Exts ++ lists:foldl(Filter, Def, Exts).
+ca_entries(CAs) ->
+ [{'Certificate', CACert, not_encrypted} || CACert <- CAs].
extension({_, undefined}) ->
[];
@@ -222,13 +92,6 @@ extension({basic_constraints, Data}) ->
#'Extension'{extnID = ?'id-ce-basicConstraints',
extnValue = Data}
end;
-extension({auth_key_id, {Oid, Issuer, SNr}}) ->
- #'Extension'{extnID = ?'id-ce-authorityKeyIdentifier',
- extnValue = #'AuthorityKeyIdentifier'{
- keyIdentifier = Oid,
- authorityCertIssuer = Issuer,
- authorityCertSerialNumber = SNr},
- critical = false};
extension({key_usage, Value}) ->
#'Extension'{extnID = ?'id-ce-keyUsage',
extnValue = Value,
@@ -240,113 +103,6 @@ extension({subject_alt, Hostname}) ->
extension({Id, Data, Critical}) ->
#'Extension'{extnID = Id, extnValue = Data, critical = Critical}.
-public_key(#'RSAPrivateKey'{modulus=N, publicExponent=E}) ->
- Public = #'RSAPublicKey'{modulus=N, publicExponent=E},
- Algo = #'PublicKeyAlgorithm'{algorithm= ?rsaEncryption, parameters='NULL'},
- #'OTPSubjectPublicKeyInfo'{algorithm = Algo,
- subjectPublicKey = Public};
-public_key(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) ->
- Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa',
- parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}},
- #'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y};
-public_key(#'ECPrivateKey'{version = _Version,
- privateKey = _PrivKey,
- parameters = Params,
- publicKey = PubKey}) ->
- Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-ecPublicKey', parameters=Params},
- #'OTPSubjectPublicKeyInfo'{algorithm = Algo,
- subjectPublicKey = #'ECPoint'{point = PubKey}}.
-
-sign_algorithm(#'RSAPrivateKey'{}, Opts) ->
- Type = rsa_digest_oid(proplists:get_value(digest, Opts, sha1)),
- #'SignatureAlgorithm'{algorithm = Type,
- parameters = 'NULL'};
-sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) ->
- #'SignatureAlgorithm'{algorithm = ?'id-dsa-with-sha1',
- parameters = {params,#'Dss-Parms'{p=P, q=Q, g=G}}};
-sign_algorithm(#'ECPrivateKey'{parameters = Parms}, Opts) ->
- Type = ecdsa_digest_oid(proplists:get_value(digest, Opts, sha1)),
- #'SignatureAlgorithm'{algorithm = Type,
- parameters = Parms}.
-
-rsa_digest_oid(sha1) ->
- ?'sha1WithRSAEncryption';
-rsa_digest_oid(sha512) ->
- ?'sha512WithRSAEncryption';
-rsa_digest_oid(sha384) ->
- ?'sha384WithRSAEncryption';
-rsa_digest_oid(sha256) ->
- ?'sha256WithRSAEncryption';
-rsa_digest_oid(md5) ->
- ?'md5WithRSAEncryption'.
-
-ecdsa_digest_oid(sha1) ->
- ?'ecdsa-with-SHA1';
-ecdsa_digest_oid(sha512) ->
- ?'ecdsa-with-SHA512';
-ecdsa_digest_oid(sha384) ->
- ?'ecdsa-with-SHA384';
-ecdsa_digest_oid(sha256) ->
- ?'ecdsa-with-SHA256'.
-
-ca_config(Root, CAsKeys) ->
- [Root | [CA || {CA, _} <- CAsKeys]].
-
-cert_chain(Role, Root, RootKey, Opts, Keys) ->
- cert_chain(Role, Root, RootKey, Opts, Keys, 0, []).
-
-cert_chain(Role, IssuerCert, IssuerKey, Opts, [Key], _, Acc) ->
- PeerOpts = list_to_atom(atom_to_list(Role) ++ "_peer_opts"),
- Cert = cert(Role, public_key:pkix_decode_cert(IssuerCert, otp),
- IssuerKey, Key, "admin", " Peer cert", Opts, PeerOpts, peer),
- [{Cert, Key}, {IssuerCert, IssuerKey} | Acc];
-cert_chain(Role, IssuerCert, IssuerKey, Opts, [Key | Keys], N, Acc) ->
- CAOpts = list_to_atom(atom_to_list(Role) ++ "_ca_" ++ integer_to_list(N)),
- Cert = cert(Role, public_key:pkix_decode_cert(IssuerCert, otp), IssuerKey, Key, "webadmin",
- " Intermidiate CA " ++ integer_to_list(N), Opts, CAOpts, ca),
- cert_chain(Role, Cert, Key, Opts, Keys, N+1, [{IssuerCert, IssuerKey} | Acc]).
-
-cert(Role, #'OTPCertificate'{tbsCertificate = #'OTPTBSCertificate'{subject = Issuer,
- serialNumber = SNr
- }},
- PrivKey, Key, Contact, Name, Opts, CertOptsName, Type) ->
- CertOpts = proplists:get_value(CertOptsName, Opts, []),
- TBS = cert_template(),
- OTPTBS = TBS#'OTPTBSCertificate'{
- signature = sign_algorithm(PrivKey, Opts),
- issuer = Issuer,
- validity = validity(CertOpts),
- subject = subject(Contact, atom_to_list(Role) ++ Name),
- subjectPublicKeyInfo = public_key(Key),
- extensions = extensions(Role, Type,
- add_default_extensions([{auth_key_id, {auth_key_oid(Role), Issuer, SNr}}],
- CertOpts))
- },
- public_key:pkix_sign(OTPTBS, PrivKey).
-
-is_key(#'DSAPrivateKey'{}) ->
- true;
-is_key(#'RSAPrivateKey'{}) ->
- true;
-is_key(#'ECPrivateKey'{}) ->
- true;
-is_key(_) ->
- false.
-
der_to_pem(File, Entries) ->
PemBin = public_key:pem_encode(Entries),
file:write_file(File, PemBin).
-
-default_key_gen() ->
- case tls_v1:ecc_curves(0) of
- [] ->
- [{rsa, 2048, 17}, {rsa, 2048, 17}];
- [_|_] ->
- [{namedCurve, hd(tls_v1:ecc_curves(0))},
- {namedCurve, hd(tls_v1:ecc_curves(0))}]
- end.
-
-auth_key_oid(server) ->
- ?'id-kp-serverAuth';
-auth_key_oid(client) ->
- ?'id-kp-clientAuth'.
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index 25b2a2bec0..741bdb6df0 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1 @@
-SSL_VSN = 8.2
+SSL_VSN = 9.0.2
diff --git a/lib/stdlib/doc/src/Makefile b/lib/stdlib/doc/src/Makefile
index 26602764a6..4541b4a463 100644
--- a/lib/stdlib/doc/src/Makefile
+++ b/lib/stdlib/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -71,7 +71,6 @@ XML_REF3_FILES = \
gen_statem.xml \
io.xml \
io_lib.xml \
- lib.xml \
lists.xml \
log_mf_h.xml \
maps.xml \
@@ -98,13 +97,15 @@ XML_REF3_FILES = \
sys.xml \
timer.xml \
unicode.xml \
+ uri_string.xml \
win32reg.xml \
zip.xml
XML_REF6_FILES = stdlib_app.xml
-XML_PART_FILES = part.xml part_notes.xml part_notes_history.xml
-XML_CHAPTER_FILES = io_protocol.xml unicode_usage.xml notes.xml notes_history.xml assert_hrl.xml
+XML_PART_FILES = part.xml
+XML_CHAPTER_FILES = introduction.xml io_protocol.xml unicode_usage.xml \
+ notes.xml assert_hrl.xml
BOOK_FILES = book.xml
@@ -131,9 +132,9 @@ SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
TOP_SPECS_FILE = specs.xml
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
+XML_FLAGS +=
SPECS_FLAGS = -I../../include -I../../../kernel/include
@@ -150,23 +151,24 @@ html: $(HTML_REF_MAN_FILE)
man: $(MAN3_FILES) $(MAN6_FILES)
-debug opt:
+debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(SPECDIR)/*
- rm -f errs core *~
+ rm -f errs core *~
$(SPECDIR)/specs_erl_id_trans.xml:
- escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ $(gen_verbose)escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
-o$(dir $@) -module erl_id_trans
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
diff --git a/lib/stdlib/doc/src/assert_hrl.xml b/lib/stdlib/doc/src/assert_hrl.xml
index ea23cca2ee..4dc7299609 100644
--- a/lib/stdlib/doc/src/assert_hrl.xml
+++ b/lib/stdlib/doc/src/assert_hrl.xml
@@ -4,7 +4,7 @@
<fileref>
<header>
<copyright>
- <year>2012</year><year>2017</year>
+ <year>2012</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -93,7 +93,7 @@ erlc -DNOASSERT=true *.erl</code>
<taglist>
<tag><c>assert(BoolExpr)</c></tag>
<item></item>
- <tag><c>URKAassert(BoolExpr, Comment)</c></tag>
+ <tag><c>assert(BoolExpr, Comment)</c></tag>
<item>
<p>Tests that <c>BoolExpr</c> completes normally returning
<c>true</c>.</p>
diff --git a/lib/stdlib/doc/src/c.xml b/lib/stdlib/doc/src/c.xml
index 7666699183..b6cb6f5aae 100644
--- a/lib/stdlib/doc/src/c.xml
+++ b/lib/stdlib/doc/src/c.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -94,6 +94,15 @@
</func>
<func>
+ <name name="erlangrc" arity="1"/>
+ <fsummary>Load an erlang resource file.</fsummary>
+ <desc>
+ <p>Search <c>PathList</c> and load <c>.erlang</c> resource file if
+ found.</p>
+ </desc>
+ </func>
+
+ <func>
<name name="flush" arity="0"/>
<fsummary>Flush any messages sent to the shell.</fsummary>
<desc>
diff --git a/lib/stdlib/doc/src/calendar.xml b/lib/stdlib/doc/src/calendar.xml
index 65b3edcdf6..6b4fa7f98a 100644
--- a/lib/stdlib/doc/src/calendar.xml
+++ b/lib/stdlib/doc/src/calendar.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -317,6 +317,32 @@
</func>
<func>
+ <name name="rfc3339_to_system_time" arity="1"/>
+ <name name="rfc3339_to_system_time" arity="2"/>
+ <fsummary>Convert from RFC 3339 timestamp to system time.</fsummary>
+ <type name="rfc3339_string"/>
+ <type name="rfc3339_time_unit"/>
+ <desc>
+ <p>Converts an RFC 3339 timestamp into system time. The data format
+ of RFC 3339 timestamps is described by
+ <url href="https://www.ietf.org/rfc/rfc3339.txt">RFC 3339</url>.</p>
+ <p>Valid option:</p>
+ <taglist>
+ <tag><c>{unit, Unit}</c></tag>
+ <item><p>The time unit of the return value.
+ The default is <c>second</c>.</p>
+ </item>
+ </taglist>
+ <pre>
+1> <input>calendar:rfc3339_to_system_time("2018-02-01T16:17:58+01:00").</input>
+1517498278
+2> <input>calendar:rfc3339_to_system_time("2018-02-01 15:18:02.088Z",
+ [{unit, nanosecond}]).</input>
+1517498282088000000</pre>
+ </desc>
+ </func>
+
+ <func>
<name name="seconds_to_daystime" arity="1"/>
<fsummary>Compute days and time from seconds.</fsummary>
<desc>
@@ -339,6 +365,71 @@
</func>
<func>
+ <name name="system_time_to_local_time" arity="2"/>
+ <fsummary>Convert system time to local date and time.</fsummary>
+ <desc>
+ <p>Converts a specified system time into local date and time.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="system_time_to_rfc3339" arity="1"/>
+ <name name="system_time_to_rfc3339" arity="2"/>
+ <fsummary>Convert from system to RFC 3339 timestamp.</fsummary>
+ <type name="offset"/>
+ <type name="rfc3339_string"/>
+ <type name="rfc3339_time_unit"/>
+ <desc>
+ <p>Converts a system time into an RFC 3339 timestamp. The data format
+ of RFC 3339 timestamps is described by
+ <url href="https://www.ietf.org/rfc/rfc3339.txt">RFC 3339</url>.
+ The data format of offsets is also described by RFC 3339.</p>
+ <p>Valid options:</p>
+ <taglist>
+ <tag><c>{offset, Offset}</c></tag>
+ <item><p>The offset, either a string or an integer, to be
+ included in the formatted string.
+ An empty string, which is the default, is interpreted
+ as local time. A non-empty string is included as is.
+ The time unit of the integer is the same as the one
+ of <c><anno>Time</anno></c>.</p>
+ </item>
+ <tag><c>{time_designator, Character}</c></tag>
+ <item><p>The character used as time designator, that is,
+ the date and time separator. The default is <c>$T</c>.</p>
+ </item>
+ <tag><c>{unit, Unit}</c></tag>
+ <item><p>The time unit of <c><anno>Time</anno></c>. The
+ default is <c>second</c>. If some other unit is given
+ (<c>millisecond</c>, <c>microsecond</c>, or
+ <c>nanosecond</c>), the formatted string includes a
+ fraction of a second.</p>
+ </item>
+ </taglist>
+ <pre>
+1> <input>calendar:system_time_to_rfc3339(erlang:system_time(second)).</input>
+"2018-04-23T14:56:28+02:00"
+2> <input>calendar:system_time_to_rfc3339(erlang:system_time(second),
+ [{offset, "-02:00"}]).</input>
+"2018-04-23T10:56:52-02:00"
+3> <input>calendar:system_time_to_rfc3339(erlang:system_time(second),
+ [{offset, -7200}]).</input>
+"2018-04-23T10:57:05-02:00"
+4> <input>calendar:system_time_to_rfc3339(erlang:system_time(millisecond),
+ [{unit, millisecond}, {time_designator, $\s}, {offset, "Z"}]).</input>
+"2018-04-23 12:57:20.482Z"</pre>
+ </desc>
+ </func>
+
+ <func>
+ <name name="system_time_to_universal_time" arity="2"/>
+ <fsummary>Convert system time to universal date and time.</fsummary>
+ <desc>
+ <p>Converts a specified system time into universal date and time.</p>
+ </desc>
+ </func>
+
+ <func>
<name name="time_difference" arity="2"/>
<fsummary>Compute the difference between two times (deprecated).
</fsummary>
diff --git a/lib/stdlib/doc/src/digraph.xml b/lib/stdlib/doc/src/digraph.xml
index 5332d7aba5..a5252b443b 100644
--- a/lib/stdlib/doc/src/digraph.xml
+++ b/lib/stdlib/doc/src/digraph.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -170,6 +170,10 @@
<p>If the edge would create a cycle in
an <seealso marker="#acyclic_digraph">acyclic digraph</seealso>,
<c>{error,&nbsp;{bad_edge,&nbsp;<anno>Path</anno>}}</c> is returned.
+ If <c><anno>G</anno></c> already has an edge with value
+ <c><anno>E</anno></c> connecting a different pair of vertices,
+ <c>{error,&nbsp;{bad_edge,&nbsp;[<anno>V1</anno>,&nbsp;<anno>V2</anno>]}}</c>
+ is returned.
If either of <c><anno>V1</anno></c> or <c><anno>V2</anno></c> is not
a vertex of digraph <c><anno>G</anno></c>,
<c>{error,&nbsp;{bad_vertex,&nbsp;</c><anno>V</anno><c>}}</c> is
diff --git a/lib/stdlib/doc/src/epp.xml b/lib/stdlib/doc/src/epp.xml
index 1dc0161398..d803d259aa 100644
--- a/lib/stdlib/doc/src/epp.xml
+++ b/lib/stdlib/doc/src/epp.xml
@@ -124,6 +124,10 @@
<fsummary>Open a file for preprocessing.</fsummary>
<desc>
<p>Opens a file for preprocessing.</p>
+ <p>If you want to change the file name of the implicit -file()
+ attributes inserted during preprocessing, you can do with
+ <c>{source_name, <anno>SourceName</anno>}</c>. If unset it will
+ default to the name of the opened file.</p>
<p>If <c>extra</c> is specified in
<c><anno>Options</anno></c>, the return value is
<c>{ok, <anno>Epp</anno>, <anno>Extra</anno>}</c> instead
@@ -169,6 +173,10 @@
<p>Preprocesses and parses an Erlang source file.
Notice that tuple <c>{eof, <anno>Line</anno>}</c> returned at the
end of the file is included as a "form".</p>
+ <p>If you want to change the file name of the implicit -file()
+ attributes inserted during preprocessing, you can do with
+ <c>{source_name, <anno>SourceName</anno>}</c>. If unset it will
+ default to the name of the opened file.</p>
<p>If <c>extra</c> is specified in
<c><anno>Options</anno></c>, the return value is
<c>{ok, [<anno>Form</anno>], <anno>Extra</anno>}</c> instead
diff --git a/lib/stdlib/doc/src/erl_tar.xml b/lib/stdlib/doc/src/erl_tar.xml
index 337028568a..68fa071090 100644
--- a/lib/stdlib/doc/src/erl_tar.xml
+++ b/lib/stdlib/doc/src/erl_tar.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2003</year><year>2017</year>
+ <year>2003</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -90,8 +90,8 @@
<section>
<title>Other Storage Media</title>
- <p>The <seealso marker="inets:ftp"><c>ftp</c></seealso>
- module (Inets) normally accesses the tar file on disk using
+ <p>The <seealso marker="ftp:ftp"><c>ftp</c></seealso>
+ module normally accesses the tar file on disk using
the <seealso marker="kernel:file"><c>file</c></seealso> module.
When other needs arise, you can define your own low-level Erlang
functions to perform the writing and reading on the storage media;
@@ -136,6 +136,9 @@
<v>Filename = filename()|{NameInArchive,FilenameOrBin}</v>
<v>Options = [Option]</v>
<v>Option = dereference|verbose|{chunks,ChunkSize}</v>
+ <v>|{atime,non_neg_integer()}|{mtime,non_neg_integer()}</v>
+ <v>|{ctime,non_neg_integer()}|{uid,non_neg_integer()}</v>
+ <v>|{gid,non_neg_integer()}</v>
<v>ChunkSize = positive_integer()</v>
<v>RetValue = ok|{error,{Filename,Reason}}</v>
<v>Reason = term()</v>
@@ -167,6 +170,42 @@
<seealso marker="ssh:ssh_sftp#open_tar/3">
<c>ssh_sftp:open_tar/3</c></seealso>.</p>
</item>
+ <tag><c>{atime,non_neg_integer()}</c></tag>
+ <item>
+ <p>Sets the last time, as
+ <seealso marker="erts:time_correction#POSIX_Time">
+ POSIX time</seealso>, when the file was read. See also
+ <seealso marker="kernel:file#read_file_info/1">
+ <c>file:read_file_info/1</c></seealso>.</p>
+ </item>
+ <tag><c>{mtime,non_neg_integer()}</c></tag>
+ <item>
+ <p>Sets the last time, as
+ <seealso marker="erts:time_correction#POSIX_Time">
+ POSIX time</seealso>, when the file was written. See also
+ <seealso marker="kernel:file#read_file_info/1">
+ <c>file:read_file_info/1</c></seealso>.</p>
+ </item>
+ <tag><c>{ctime,non_neg_integer()}</c></tag>
+ <item>
+ <p>Sets the time, as
+ <seealso marker="erts:time_correction#POSIX_Time">
+ POSIX time</seealso>, when the file was created. See also
+ <seealso marker="kernel:file#read_file_info/1">
+ <c>file:read_file_info/1</c></seealso>.</p>
+ </item>
+ <tag><c>{uid,non_neg_integer()}</c></tag>
+ <item>
+ <p>Sets the file owner.
+ <seealso marker="kernel:file#read_file_info/1">
+ <c>file:read_file_info/1</c></seealso>.</p>
+ </item>
+ <tag><c>{gid,non_neg_integer()}</c></tag>
+ <item>
+ <p>Sets the group that the file owner belongs to.
+ <seealso marker="kernel:file#read_file_info/1">
+ <c>file:read_file_info/1</c></seealso>.</p>
+ </item>
</taglist>
</desc>
</func>
@@ -378,7 +417,7 @@
<v>Reason = term()</v>
</type>
<desc>
- <p>Cconverts an error reason term to a human-readable error message
+ <p>Converts an error reason term to a human-readable error message
string.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml
index f6f3d18d6a..ad006f9a2b 100644
--- a/lib/stdlib/doc/src/ets.xml
+++ b/lib/stdlib/doc/src/ets.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -49,14 +49,16 @@
associated with each key. A <c>bag</c> or <c>duplicate_bag</c> table can
have many objects associated with each key.</p>
+ <marker id="max_ets_tables"></marker>
<note>
<p>
The number of tables stored at one Erlang node <em>used</em> to
be limited. This is no longer the case (except by memory usage).
The previous default limit was about 1400 tables and
could be increased by setting the environment variable
- <c>ERL_MAX_ETS_TABLES</c> before starting the Erlang runtime
- system. This hard limit has been removed, but it is currently
+ <c>ERL_MAX_ETS_TABLES</c> or the command line option
+ <seealso marker="erts:erl#+e"><c>+e</c></seealso> before starting the
+ Erlang runtime system. This hard limit has been removed, but it is currently
useful to set the <c>ERL_MAX_ETS_TABLES</c> anyway. It should be
set to an approximate of the maximum amount of tables used. This since
an internal table for named tables is sized using this value. If
@@ -325,7 +327,7 @@
<p><c><anno>Acc0</anno></c> is returned if the table is empty.
This function is similar to
<seealso marker="lists#foldl/3"><c>lists:foldl/3</c></seealso>.
- The table elements are traversed is unspecified order, except for
+ The table elements are traversed in an unspecified order, except for
<c>ordered_set</c> tables, where they are traversed first to last.</p>
<p>If <c><anno>Function</anno></c> inserts objects into the table,
or another
@@ -341,7 +343,7 @@
<p><c><anno>Acc0</anno></c> is returned if the table is empty.
This function is similar to
<seealso marker="lists#foldr/3"><c>lists:foldr/3</c></seealso>.
- The table elements are traversed is unspecified order, except for
+ The table elements are traversed in an unspecified order, except for
<c>ordered_set</c> tables, where they are traversed last to first.</p>
<p>If <c><anno>Function</anno></c> inserts objects into the table,
or another
@@ -408,9 +410,9 @@
calls cannot be in the guard or body of the fun. Calls to built-in
match specification functions is of course allowed:</p>
<pre>
-4> <input>ets:fun2ms(fun({M,N}) when N > X, is_atomm(M) -> M end).</input>
+4> <input>ets:fun2ms(fun({M,N}) when N > X, my_fun(M) -> M end).</input>
Error: fun containing local Erlang function calls
-('is_atomm' called in guard) cannot be translated into match_spec
+('my_fun' called in guard) cannot be translated into match_spec
{error,transform_error}
5> <input>ets:fun2ms(fun({M,N}) when N > X, is_atom(M) -> M end).</input>
[{{'$1','$2'},[{'>','$2',{const,3}},{is_atom,'$1'}],['$1']}]</pre>
@@ -487,6 +489,11 @@ Error: fun containing local Erlang function calls
<p>The pid of the heir of the table, or <c>none</c> if no heir
is set.</p>
</item>
+ <tag><c>{id,</c><seealso marker="#type-tid">
+ <c>tid()</c></seealso><c>}</c></tag>
+ <item>
+ <p>The table identifier.</p>
+ </item>
<tag><c>{keypos, integer() >= 1}</c></tag>
<item>
<p>The key position.</p>
@@ -963,11 +970,11 @@ ets:is_compiled_ms(Broken).</code>
<func>
<name name="match_spec_run" arity="2"/>
<fsummary>Perform matching, using a compiled match specification on a
- list of tuples.</fsummary>
+ list of terms.</fsummary>
<desc>
<p>Executes the matching specified in a compiled
<seealso marker="#match_spec">match specification</seealso> on a list
- of tuples. Term <c><anno>CompiledMatchSpec</anno></c> is to be
+ of terms. Term <c><anno>CompiledMatchSpec</anno></c> is to be
the result of a call to <seealso marker="#match_spec_compile/1">
<c>match_spec_compile/1</c></seealso> and is hence the internal
representation of the match specification one wants to use.</p>
@@ -985,7 +992,7 @@ Table = ets:new...
MatchSpec = ...
% The following call...
ets:match_spec_run(ets:tab2list(Table),
-ets:match_spec_compile(MatchSpec)),
+ ets:match_spec_compile(MatchSpec)),
% ...gives the same result as the more common (and more efficient)
ets:select(Table, MatchSpec),</code>
<note>
@@ -1016,7 +1023,7 @@ ets:select(Table, MatchSpec),</code>
be used in subsequent operations. The table identifier can be
sent to other processes so that a table can be shared between
different processes within a node.</p>
- <p>Parameter <c><anno>Options</anno></c> is a list of atoms that
+ <p>Parameter <c><anno>Options</anno></c> is a list of options that
specifies table type, access rights, key position, and whether the
table is named. Default values are used for omitted options.
This means that not specifying any options (<c>[]</c>) is the same
@@ -1074,10 +1081,13 @@ ets:select(Table, MatchSpec),</code>
</item>
<tag><c>named_table</c></tag>
<item>
- <p>If this option is present, name <c><anno>Name</anno></c> is
- associated with the table identifier. The name can then
- be used instead of the table identifier in subsequent
- operations.</p>
+ <p>If this option is present, the table is registered under its
+ <c><anno>Name</anno></c> which can then be used instead of the
+ table identifier in subsequent operations.</p>
+ <p>The function will also return the <c><anno>Name</anno></c>
+ instead of the table identifier. To get the table identifier of a
+ named table, use
+ <seealso marker="#whereis/1"><c>whereis/1</c></seealso>.</p>
</item>
<tag><c>{keypos,<anno>Pos</anno>}</c></tag>
<item>
@@ -1961,7 +1971,7 @@ true</pre>
The return value is a list of the new counter values from each
update operation in the same order as in the operation list. If an
empty list is specified, nothing is updated and an empty list is
- returned. If the function fails, no updates is done.</p>
+ returned. If the function fails, no updates are done.</p>
<p>The specified <c><anno>Key</anno></c> is used to identify the object
by either <em>matching</em> the key of an object in a <c>set</c>
table, or <em>compare equal</em> to the key of an object in an
@@ -2037,6 +2047,21 @@ true</pre>
</list>
</desc>
</func>
+
+ <func>
+ <name name="whereis" arity="1"/>
+ <fsummary>Retrieves the tid() of a named table.</fsummary>
+ <desc>
+ <p>This function returns the
+ <seealso marker="#type-tid"><c>tid()</c></seealso> of the named table
+ identified by <c><anno>TableName</anno></c>, or <c>undefined</c> if
+ no such table exists. The <c>tid()</c> can be used in place of the
+ table name in all operations, which is slightly faster since the name
+ does not have to be resolved on each call.</p>
+ <p>If the table is deleted, the <c>tid()</c> will be invalid even if
+ another named table is created with the same name.</p>
+ </desc>
+ </func>
</funcs>
</erlref>
diff --git a/lib/stdlib/doc/src/fascicules.xml b/lib/stdlib/doc/src/fascicules.xml
deleted file mode 100644
index 0ded9007e0..0000000000
--- a/lib/stdlib/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- STDLIB User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/stdlib/doc/src/filelib.xml b/lib/stdlib/doc/src/filelib.xml
index 80c4acffdb..3b5be75bc0 100644
--- a/lib/stdlib/doc/src/filelib.xml
+++ b/lib/stdlib/doc/src/filelib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2003</year><year>2017</year>
+ <year>2003</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -45,6 +45,30 @@
<p>For more information about raw filenames, see the
<seealso marker="kernel:file"><c>file</c></seealso> module.</p>
+
+ <note>
+ <p>
+ Functionality in this module generally assumes valid input and
+ does not necessarily fail on input that does not use a valid
+ encoding, but may instead very likely produce invalid output.
+ </p>
+ <p>
+ File operations used to accept filenames containing
+ null characters (integer value zero). This caused
+ the name to be truncated and in some cases arguments
+ to primitive operations to be mixed up. Filenames
+ containing null characters inside the filename
+ are now <em>rejected</em> and will cause primitive
+ file operations to fail.
+ </p>
+ </note>
+ <warning><p>
+ Currently null characters at the end of the filename
+ will be accepted by primitive file operations. Such
+ filenames are however still documented as invalid. The
+ implementation will also change in the future and
+ reject such filenames.
+ </p></warning>
</description>
<datatypes>
@@ -193,6 +217,11 @@
<p>Other characters represent themselves. Only filenames that
have exactly the same character in the same position match.
Matching is case-sensitive, for example, "a" does not match "A".</p>
+ <p>Directory separators must always be written as <c>/</c>, even on
+ Windows.</p>
+ <p>A character preceded by <c>\</c> loses its special meaning. Note
+ that <c>\</c> must be written as <c>\\</c> in a string literal.
+ For example, "\\?*" will match any filename starting with <c>?</c>.</p>
<p>Notice that multiple "*" characters are allowed
(as in Unix wildcards, but opposed to Windows/DOS wildcards).</p>
<p><em>Examples:</em></p>
@@ -267,7 +296,7 @@ filelib:wildcard("lib/**/*.{erl,hrl}")</code>
for a file with the extension <c>.beam</c>, the default rule is to
look for a file with a corresponding extension <c>.erl</c> by
replacing the suffix <c>"ebin"</c> of the object directory path with
- <c>"src"</c>.
+ <c>"src"</c> or <c>"src/*"</c>.
The file search is done through <seealso
marker="#find_file/3"><c>find_file/3</c></seealso>. The directory of
the object file is always tried before any other directory specified
diff --git a/lib/stdlib/doc/src/filename.xml b/lib/stdlib/doc/src/filename.xml
index 14fd5ef787..36254c2d00 100644
--- a/lib/stdlib/doc/src/filename.xml
+++ b/lib/stdlib/doc/src/filename.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2017</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -46,7 +46,10 @@
filename by removing redundant directory separators, use
<seealso marker="#join/1"><c>join/1</c></seealso>.</p>
- <p>The module supports raw filenames in the way that if a binary is
+ <p>
+ The module supports
+ <seealso marker="unicode_usage#notes-about-raw-filenames">raw
+ filenames</seealso> in the way that if a binary is
present, or the filename cannot be interpreted according to the return
value of <seealso marker="kernel:file#native_name_encoding/0">
<c>file:native_name_encoding/0</c></seealso>, a raw filename is also
@@ -56,12 +59,31 @@
(the join operation is performed of course). For more information
about raw filenames, see the
<seealso marker="kernel:file"><c>file</c></seealso> module.</p>
+
+ <note>
+ <p>
+ Functionality in this module generally assumes valid input and
+ does not necessarily fail on input that does not use a valid
+ encoding, but may instead very likely produce invalid output.
+ </p>
+ <p>
+ File operations used to accept filenames containing
+ null characters (integer value zero). This caused
+ the name to be truncated and in some cases arguments
+ to primitive operations to be mixed up. Filenames
+ containing null characters inside the filename
+ are now <em>rejected</em> and will cause primitive
+ file operations to fail.
+ </p>
+ </note>
+ <warning><p>
+ Currently null characters at the end of the filename
+ will be accepted by primitive file operations. Such
+ filenames are however still documented as invalid. The
+ implementation will also change in the future and
+ reject such filenames.
+ </p></warning>
</description>
- <datatypes>
- <datatype>
- <name name="basedir_type"/>
- </datatype>
- </datatypes>
<funcs>
<func>
@@ -122,18 +144,37 @@
</func>
<func>
- <name name="basedir" arity="2"/>
- <fsummary>Equivalent to <c>basedir(<anno>Type</anno>,<anno>Application</anno>,#{})</c>.</fsummary>
+ <name name="basedir" arity="2" clause_i="1"/>
+ <name name="basedir" arity="2" clause_i="2"/>
+ <fsummary>Equivalent to <c>basedir(<anno>PathType</anno>,
+ <anno>Application</anno>,#{})</c> or
+ <c>basedir(<anno>PathsType</anno>, <anno>Application</anno>,#{})</c>.
+ </fsummary>
+ <type variable="PathType" name_i="1"/>
+ <type name="basedir_path_type"/>
+ <type variable="PathsType" name_i="2"/>
+ <type name="basedir_paths_type"/>
+ <type variable="Application"/>
<desc>
<p>
- Equivalent to <seealso marker="#basedir-3">
- basedir(<anno>Type</anno>, <anno>Application</anno>, #{})</seealso>.
+ Equivalent to <seealso marker="#basedir_3_1">
+ basedir(<anno>PathType</anno>, <anno>Application</anno>, #{})</seealso>
+ or <seealso marker="#basedir_3_2">
+basedir(<anno>PathsType</anno>, <anno>Application</anno>, #{})</seealso>.
</p>
</desc>
</func>
<func>
- <name name="basedir" arity="3"/>
+ <name name="basedir" arity="3" clause_i="1" anchor="basedir_3_1"/>
+ <name name="basedir" arity="3" clause_i="2" anchor="basedir_3_2"/>
<fsummary></fsummary>
+ <type variable="PathType" name_i="1"/>
+ <type name="basedir_path_type"/>
+ <type variable="PathsType" name_i="2"/>
+ <type name="basedir_paths_type"/>
+ <type variable="Application"/>
+ <type variable="Opts"/>
+ <type name="basedir_opts"/>
<desc><marker id="basedir-3"/>
<p>
Returns a suitable path, or paths, for a given type. If
@@ -372,15 +413,18 @@ true
tuples <c>{<anno>BinSuffix</anno>, <anno>SourceSuffix</anno>}</c> and
is interpreted as follows: if the end of the directory name where the
object is located matches <c><anno>BinSuffix</anno></c>, then the
- source code directory has the same name, but with
- <c><anno>BinSuffix</anno></c> replaced by
- <c><anno>SourceSuffix</anno></c>. <c><anno>Rules</anno></c> defaults
+ name created by replacing <c><anno>BinSuffix</anno></c> with
+ <c><anno>SourceSuffix</anno></c> is expanded by calling
+ <seealso marker="filelib#wildcard/1">
+ <c>filelib:wildcard/1</c></seealso>.
+ If a regular file is found among the matches, the function
+ returns that location together with <c><anno>Options</anno></c>.
+ Otherwise the next rule is tried, and so on.</p>
+ <p><c><anno>Rules</anno></c> defaults
to:</p>
<code type="none">
-[{"", ""}, {"ebin", "src"}, {"ebin", "esrc"}]</code>
- <p>If the source file is found in the resulting directory, the function
- returns that location together with <c><anno>Options</anno></c>.
- Otherwise the next rule is tried, and so on.</p>
+[{"", ""}, {"ebin", "src"}, {"ebin", "esrc"},
+ {"ebin", "src/*"}, {"ebin", "esrc/*"}]</code>
<p>The function returns <c>{<anno>SourceFile</anno>,
<anno>Options</anno>}</c> if it succeeds.
<c><anno>SourceFile</anno></c> is the absolute path to the source
@@ -555,6 +599,7 @@ unsafe</pre>
["a:/","msdev","include"]</pre>
</desc>
</func>
+
</funcs>
</erlref>
diff --git a/lib/stdlib/doc/src/gb_sets.xml b/lib/stdlib/doc/src/gb_sets.xml
index 7bfe477a11..03397b4503 100644
--- a/lib/stdlib/doc/src/gb_sets.xml
+++ b/lib/stdlib/doc/src/gb_sets.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2001</year><year>2016</year>
+ <year>2001</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -83,6 +83,8 @@
</item>
<item><seealso marker="#is_element/2"><c>is_element/2</c></seealso>
</item>
+ <item><seealso marker="#is_empty/1"><c>is_empty/1</c></seealso>
+ </item>
<item><seealso marker="#is_set/1"><c>is_set/1</c></seealso>
</item>
<item><seealso marker="#is_subset/2"><c>is_subset/2</c></seealso>
diff --git a/lib/stdlib/doc/src/gen_event.xml b/lib/stdlib/doc/src/gen_event.xml
index 012737c390..f793ec7fdf 100644
--- a/lib/stdlib/doc/src/gen_event.xml
+++ b/lib/stdlib/doc/src/gen_event.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -207,7 +207,7 @@ gen_event:stop -----> Module:terminate/2
</item>
<item>
<p>If the event handler is deleted later, the event manager
- sends a message<c>{gen_event_EXIT,Handler,Reason}</c> to
+ sends a message <c>{gen_event_EXIT,Handler,Reason}</c> to
the calling process. <c>Reason</c> is one of the following:</p>
<list type="bulleted">
<item>
@@ -458,8 +458,7 @@ gen_event:stop -----> Module:terminate/2
with the expected reason. Any other reason than <c>normal</c>,
<c>shutdown</c>, or <c>{shutdown,Term}</c> causes an
error report to be issued using
- <seealso marker="kernel:error_logger#format/2">
- <c>error_logger:format/2</c></seealso>.
+ <seealso marker="kernel:logger"><c>logger(3)</c></seealso>.
The default <c>Reason</c> is <c>normal</c>.</p>
<p><c>Timeout</c> is an integer greater than zero that
specifies how many milliseconds to wait for the event manager to
diff --git a/lib/stdlib/doc/src/gen_server.xml b/lib/stdlib/doc/src/gen_server.xml
index 7d137fc772..106bda85f5 100644
--- a/lib/stdlib/doc/src/gen_server.xml
+++ b/lib/stdlib/doc/src/gen_server.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -60,6 +60,8 @@ gen_server:abcast -----> Module:handle_cast/2
- -----> Module:handle_info/2
+- -----> Module:handle_continue/2
+
- -----> Module:terminate/2
- -----> Module:code_change/3</pre>
@@ -88,6 +90,13 @@ gen_server:abcast -----> Module:handle_cast/2
implies at least two garbage collections (when hibernating and
shortly after waking up) and is not something you want to do
between each call to a busy server.</p>
+
+ <p>If the <c>gen_server</c> process needs to perform an action
+ immediately after initialization or to break the execution of a
+ callback into multiple steps, it can return <c>{continue,Continue}</c>
+ in place of the time-out or hibernation value, which will immediately
+ invoke the <c>handle_continue/2</c> callback.</p>
+
</description>
<funcs>
@@ -477,8 +486,7 @@ gen_server:abcast -----> Module:handle_cast/2
with the expected reason. Any other reason than <c>normal</c>,
<c>shutdown</c>, or <c>{shutdown,Term}</c> causes an
error report to be issued using
- <seealso marker="kernel:error_logger#format/2">
- <c>error_logger:format/2</c></seealso>.
+ <seealso marker="kernel:logger"><c>logger(3)</c></seealso>.
The default <c>Reason</c> is <c>normal</c>.</p>
<p><c>Timeout</c> is an integer greater than zero that
specifies how many milliseconds to wait for the server to
@@ -610,12 +618,15 @@ gen_server:abcast -----> Module:handle_cast/2
<v>State = term()</v>
<v>Result = {reply,Reply,NewState} | {reply,Reply,NewState,Timeout}</v>
<v>&nbsp;&nbsp;| {reply,Reply,NewState,hibernate}</v>
+ <v>&nbsp;&nbsp;| {reply,Reply,NewState,{continue,Continue}}</v>
<v>&nbsp;&nbsp;| {noreply,NewState} | {noreply,NewState,Timeout}</v>
<v>&nbsp;&nbsp;| {noreply,NewState,hibernate}</v>
+ <v>&nbsp;&nbsp;| {noreply,NewState,{continue,Continue}}</v>
<v>&nbsp;&nbsp;| {stop,Reason,Reply,NewState} | {stop,Reason,NewState}</v>
<v>&nbsp;Reply = term()</v>
<v>&nbsp;NewState = term()</v>
<v>&nbsp;Timeout = int()>=0 | infinity</v>
+ <v>&nbsp;Continue = term()</v>
<v>&nbsp;Reason = term()</v>
</type>
<desc>
@@ -673,9 +684,11 @@ gen_server:abcast -----> Module:handle_cast/2
<v>State = term()</v>
<v>Result = {noreply,NewState} | {noreply,NewState,Timeout}</v>
<v>&nbsp;&nbsp;| {noreply,NewState,hibernate}</v>
+ <v>&nbsp;&nbsp;| {noreply,NewState,{continue,Continue}}</v>
<v>&nbsp;&nbsp;| {stop,Reason,NewState}</v>
<v>&nbsp;NewState = term()</v>
<v>&nbsp;Timeout = int()>=0 | infinity</v>
+ <v>&nbsp;Continue = term()</v>
<v>&nbsp;Reason = term()</v>
</type>
<desc>
@@ -690,6 +703,41 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
+ <name>Module:handle_continue(Continue, State) -> Result</name>
+ <fsummary>Handle a continue instruction.</fsummary>
+ <type>
+ <v>Continue = term()</v>
+ <v>State = term()</v>
+ <v>Result = {noreply,NewState} | {noreply,NewState,Timeout}</v>
+ <v>&nbsp;&nbsp;| {noreply,NewState,hibernate}</v>
+ <v>&nbsp;&nbsp;| {noreply,NewState,{continue,Continue}}</v>
+ <v>&nbsp;&nbsp;| {stop,Reason,NewState}</v>
+ <v>&nbsp;NewState = term()</v>
+ <v>&nbsp;Timeout = int()>=0 | infinity</v>
+ <v>&nbsp;Continue = term()</v>
+ <v>&nbsp;Reason = normal | term()</v>
+ </type>
+ <desc>
+ <note>
+ <p>This callback is optional, so callback modules need to
+ export it only if they return <c>{continue,Continue}</c>
+ from another callback. If continue is used and the callback
+ is not implemented, the process will exit with <c>undef</c>
+ error.</p>
+ </note>
+ <p>This function is called by a <c>gen_server</c> process whenever
+ a previous callback returns <c>{continue, Continue}</c>.
+ <c>handle_continue/2</c> is invoked immediately after the previous
+ callback, which makes it useful for performing work after
+ initialization or for splitting the work in a callback in
+ multiple steps, updating the process state along the way.</p>
+ <p>For a description of the other arguments and possible return values,
+ see <seealso marker="#Module:handle_call/3">
+ <c>Module:handle_call/3</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
<name>Module:handle_info(Info, State) -> Result</name>
<fsummary>Handle an incoming message.</fsummary>
<type>
@@ -697,6 +745,7 @@ gen_server:abcast -----> Module:handle_cast/2
<v>State = term()</v>
<v>Result = {noreply,NewState} | {noreply,NewState,Timeout}</v>
<v>&nbsp;&nbsp;| {noreply,NewState,hibernate}</v>
+ <v>&nbsp;&nbsp;| {noreply,NewState,{continue,Continue}}</v>
<v>&nbsp;&nbsp;| {stop,Reason,NewState}</v>
<v>&nbsp;NewState = term()</v>
<v>&nbsp;Timeout = int()>=0 | infinity</v>
@@ -726,7 +775,7 @@ gen_server:abcast -----> Module:handle_cast/2
<type>
<v>Args = term()</v>
<v>Result = {ok,State} | {ok,State,Timeout} | {ok,State,hibernate}</v>
- <v>&nbsp;| {stop,Reason} | ignore</v>
+ <v>&nbsp;| {ok,State,{continue,Continue}} | {stop,Reason} | ignore</v>
<v>&nbsp;State = term()</v>
<v>&nbsp;Timeout = int()>=0 | infinity</v>
<v>&nbsp;Reason = term()</v>
@@ -811,8 +860,7 @@ gen_server:abcast -----> Module:handle_cast/2
<c>shutdown</c>, or <c>{shutdown,Term}</c>, the <c>gen_server</c>
process is assumed to terminate because of an error and
an error report is issued using
- <seealso marker="kernel:error_logger#format/2">
- <c>error_logger:format/2</c></seealso>.</p>
+ <seealso marker="kernel:logger"><c>logger(3)</c></seealso>.</p>
</desc>
</func>
</funcs>
diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml
index a7caa71dcb..a808d3af55 100644
--- a/lib/stdlib/doc/src/gen_statem.xml
+++ b/lib/stdlib/doc/src/gen_statem.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2016</year><year>2017</year>
+ <year>2016</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,7 +32,68 @@
<modulesummary>Generic state machine behavior.</modulesummary>
<description>
<p>
- This behavior module provides a state machine. Two
+ <c>gen_statem</c> provides a generic state machine behaviour
+ and replaces its predecessor
+ <seealso marker="gen_fsm"><c>gen_fsm</c></seealso>
+ since Erlang/OTP 20.0.
+ </p>
+ <p>
+ This reference manual describes types generated from the types
+ in the <c>gen_statem</c> source code, so they are correct.
+ However, the generated descriptions also reflect the type hiearchy,
+ which makes them kind of hard to read.
+ </p>
+ <p>
+ To get an overview of the concepts and operation of <c>gen_statem</c>,
+ do read the
+ <seealso marker="doc/design_principles:statem">
+ <c>gen_statem</c>&nbsp;Behaviour
+ </seealso>
+ in
+ <seealso marker="doc/design_principles:users_guide">
+ OTP Design Principles
+ </seealso>
+ which frequently links back to this reference manual to avoid
+ containing detailed facts that may rot by age.
+ </p>
+ <note>
+ <p>
+ This behavior appeared in Erlang/OTP 19.0.
+ In OTP 19.1 a backwards incompatible change of
+ the return tuple from
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
+ was made and the mandatory callback function
+ <seealso marker="#Module:callback_mode/0">
+ <c>Module:callback_mode/0</c>
+ </seealso>
+ was introduced. In OTP 20.0 the
+ <seealso marker="#type-generic_timeout"><c>generic timeouts</c></seealso>
+ were added.
+ </p>
+ </note>
+ <p>
+ <c>gen_statem</c> has got the same features that
+ <seealso marker="gen_fsm"><c>gen_fsm</c></seealso>
+ had and adds some really useful:
+ </p>
+ <list type="bulleted">
+ <item>Co-located state code</item>
+ <item>Arbitrary term state</item>
+ <item>Event postponing</item>
+ <item>Self-generated events</item>
+ <item>State time-out</item>
+ <item>Multiple generic named time-outs</item>
+ <item>Absolute time-out time</item>
+ <item>Automatic state enter calls</item>
+ <item>
+ Reply from other state than the request, <c>sys</c> traceable
+ </item>
+ <item>Multiple <c>sys</c> traceable replies</item>
+ </list>
+
+
+ <p>
+ Two
<seealso marker="#type-callback_mode"><em>callback modes</em></seealso>
are supported:
</p>
@@ -50,34 +111,6 @@
</p>
</item>
</list>
- <note>
- <p>
- This is a new behavior in Erlang/OTP 19.0.
- It has been thoroughly reviewed, is stable enough
- to be used by at least two heavy OTP applications,
- and is here to stay.
- Depending on user feedback, we do not expect
- but can find it necessary to make minor
- not backward compatible changes into Erlang/OTP 20.0.
- </p>
- </note>
- <p>
- The <c>gen_statem</c> behavior replaces
- <seealso marker="gen_fsm"><c>gen_fsm</c> </seealso> in Erlang/OTP 20.0.
- It has the same features and adds some really useful:
- </p>
- <list type="bulleted">
- <item>Gathered state code.</item>
- <item>Arbitrary term state.</item>
- <item>Event postponing.</item>
- <item>Self-generated events.</item>
- <item>State time-out.</item>
- <item>Multiple generic named time-outs.</item>
- <item>Absolute time-out time.</item>
- <item>Automatic state enter calls.</item>
- <item>Reply from other state than the request.</item>
- <item>Multiple <c>sys</c> traceable replies.</item>
- </list>
<p>
The callback model(s) for <c>gen_statem</c> differs from
the one for <seealso marker="gen_fsm"><c>gen_fsm</c></seealso>,
@@ -148,7 +181,7 @@ erlang:'!' -----> Module:StateName/3
is <c>state_functions</c>, the state must be an atom and
is used as the state callback name; see
<seealso marker="#Module:StateName/3"><c>Module:StateName/3</c></seealso>.
- This gathers all code for a specific state
+ This co-locates all code for a specific state
in one function as the <c>gen_statem</c> engine
branches depending on state name.
Note the fact that the callback function
@@ -207,8 +240,10 @@ erlang:'!' -----> Module:StateName/3
whenever a new state is entered; see
<seealso marker="#type-state_enter"><c>state_enter()</c></seealso>.
This is for writing code common to all state entries.
- Another way to do it is to insert events at state transitions,
- but you have to do so everywhere it is needed.
+ Another way to do it is to insert an event at the state transition,
+ and/or to use a dedicated state transition function,
+ but that is something you will have to remember
+ at every state transition to the state(s) that need it.
</p>
<note>
<p>If you in <c>gen_statem</c>, for example, postpone
@@ -252,6 +287,16 @@ erlang:'!' -----> Module:StateName/3
to use after every event; see
<seealso marker="erts:erlang#hibernate/3"><c>erlang:hibernate/3</c></seealso>.
</p>
+ <p>
+ There is also a server start option
+ <seealso marker="#type-hibernate_after_opt">
+ <c>{hibernate_after, Timeout}</c>
+ </seealso>
+ for
+ <seealso marker="#start/3"><c>start/3,4</c></seealso> or
+ <seealso marker="#start_link/3"><c>start_link/3,4</c></seealso>
+ that may be used to automatically hibernate the server.
+ </p>
</description>
<section>
@@ -543,7 +588,23 @@ handle_event(_, _, State, Data) ->
<name name="event_type"/>
<desc>
<p>
- External events are of three types:
+ There are 3 categories of events:
+ <seealso marker="#type-external_event_type">external</seealso>,
+ <seealso marker="#type-timeout_event_type">timeout</seealso>,
+ and <c>internal</c>.
+ </p>
+ <p>
+ <c>internal</c> events can only be generated by the
+ state machine itself through the state transition action
+ <seealso marker="#type-action"><c>next_event</c></seealso>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="external_event_type"/>
+ <desc>
+ <p>
+ External events are of 3 types:
<c>{call,<anno>From</anno>}</c>, <c>cast</c>, or <c>info</c>.
<seealso marker="#call/2">Calls</seealso>
(synchronous) and
@@ -551,12 +612,17 @@ handle_event(_, _, State, Data) ->
originate from the corresponding API functions.
For calls, the event contains whom to reply to.
Type <c>info</c> originates from regular process messages sent
- to the <c>gen_statem</c>. The state machine
- implementation can, in addition to the above,
- generate
- <seealso marker="#type-event_type"><c>events of types</c></seealso>
- <c>timeout</c>, <c>{timeout,<anno>Name</anno>}</c>,
- <c>state_timeout</c>, and <c>internal</c> to itself.
+ to the <c>gen_statem</c>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="timeout_event_type"/>
+ <desc>
+ <p>
+ There are 3 types of timeout events that the state machine
+ can generate for itself with the corresponding
+ <seealso marker="#type-timeout_action">timeout_action()</seealso>s.
</p>
</desc>
</datatype>
@@ -647,9 +713,9 @@ handle_event(_, _, State, Data) ->
<p>
If
<seealso marker="#Module:code_change/4"><c>Module:code_change/4</c></seealso>
- should transform the state to a state with a different
- name it is still regarded as the same state so this
- does not cause a state enter call.
+ should transform the state,
+ it is regarded as a state rename and not a state change,
+ which will not cause a state enter call.
</p>
<p>
Note that a state enter call <em>will</em> be done
@@ -667,12 +733,19 @@ handle_event(_, _, State, Data) ->
<p>
Transition options can be set by
<seealso marker="#type-action">actions</seealso>
- and they modify how the state transition is done:
+ and modify the state transition.
+ Here are the sequence of steps for a state transition:
</p>
<list type="ordered">
<item>
<p>
- If the state changes, is the initial state,
+ If
+ <seealso marker="#type-state_enter">
+ <em>state enter calls</em>
+ </seealso>
+ are used, and either:
+ the state changes, it is the initial state,
+ or one of the callback results
<seealso marker="#type-state_callback_result">
<c>repeat_state</c>
</seealso>
@@ -680,16 +753,21 @@ handle_event(_, _, State, Data) ->
<seealso marker="#type-state_callback_result">
<c>repeat_state_and_data</c>
</seealso>
- is used, and also
- <seealso marker="#type-state_enter"><em>state enter calls</em></seealso>
- are used, the <c>gen_statem</c> calls
+ is used; the <c>gen_statem</c> calls
the new state callback with arguments
- <seealso marker="#type-state_enter">(enter, OldState, Data)</seealso>.
+ <seealso marker="#type-state_enter"><c>(enter, OldState, Data)</c></seealso>.
+ </p>
+ <p>
Any
- <seealso marker="#type-enter_action"><c>actions</c></seealso>
+ <seealso marker="#type-enter_action">actions</seealso>
returned from this call are handled as if they were
- appended to the actions
- returned by the state callback that changed states.
+ appended to the actions
+ returned by the state callback that caused the state entry.
+ </p>
+ <p>
+ Should this state enter call return any of
+ the mentioned <c>repeat_*</c> callback results
+ it is repeated again, with the updated <c>Data</c>.
</p>
</item>
<item>
@@ -718,7 +796,7 @@ handle_event(_, _, State, Data) ->
All events stored with
<seealso marker="#type-action"><c>action()</c></seealso>
<c>next_event</c>
- are inserted to be processed before the other queued events.
+ are inserted to be processed before previously queued events.
</p>
</item>
<item>
@@ -732,7 +810,9 @@ handle_event(_, _, State, Data) ->
delivered to the state machine before any external
not yet received event so if there is such a time-out requested,
the corresponding time-out zero event is enqueued as
- the newest event.
+ the newest received event;
+ that is after already queued events
+ such as inserted and postponed events.
</p>
<p>
Any event cancels an
@@ -770,7 +850,7 @@ handle_event(_, _, State, Data) ->
When a new message arrives the
<seealso marker="#state callback">state callback</seealso>
is called with the corresponding event,
- and we start again from the top of this list.
+ and we start again from the top of this sequence.
</p>
</item>
</list>
@@ -795,13 +875,19 @@ handle_event(_, _, State, Data) ->
<seealso marker="proc_lib#hibernate/3"><c>proc_lib:hibernate/3</c></seealso>
before going into <c>receive</c>
to wait for a new external event.
- If there are enqueued events,
- to prevent receiving any new event, an
- <seealso marker="erts:erlang#garbage_collect/0"><c>erlang:garbage_collect/0</c></seealso>
- is done instead to simulate
- that the <c>gen_statem</c> entered hibernation
- and immediately got awakened by the oldest enqueued event.
</p>
+ <note>
+ <p>
+ If there are enqueued events to process
+ when hibrnation is requested,
+ this is optimized by not hibernating but instead calling
+ <seealso marker="erts:erlang#garbage_collect/0">
+ <c>erlang:garbage_collect/0</c>
+ </seealso>
+ to simulate that the <c>gen_statem</c> entered hibernation
+ and immediately got awakened by an enqueued event.
+ </p>
+ </note>
</desc>
</datatype>
<datatype>
@@ -836,7 +922,7 @@ handle_event(_, _, State, Data) ->
no timer is actually started,
instead the the time-out event is enqueued to ensure
that it gets processed before any not yet
- received external event.
+ received external event, but after already queued events.
</p>
<p>
Note that it is not possible nor needed to cancel this time-out,
@@ -922,7 +1008,9 @@ handle_event(_, _, State, Data) ->
If <c>Abs</c> is <c>true</c> an absolute timer is started,
and if it is <c>false</c> a relative, which is the default.
See
- <seealso marker="erts:erlang#start_timer/4"><c>erlang:start_timer/4</c></seealso>
+ <seealso marker="erts:erlang#start_timer/4">
+ <c>erlang:start_timer/4</c>
+ </seealso>
for details.
</p>
<p>
@@ -948,7 +1036,9 @@ handle_event(_, _, State, Data) ->
</p>
<p>
Actions that set
- <seealso marker="#type-transition_option">transition options</seealso>
+ <seealso marker="#type-transition_option">
+ transition options
+ </seealso>
override any previous of the same type,
so the last in the containing list wins.
For example, the last
@@ -960,7 +1050,9 @@ handle_event(_, _, State, Data) ->
<item>
<p>
Sets the
- <seealso marker="#type-transition_option"><c>transition_option()</c></seealso>
+ <seealso marker="#type-transition_option">
+ <c>transition_option()</c>
+ </seealso>
<seealso marker="#type-postpone"><c>postpone()</c></seealso>
for this state transition.
This action is ignored when returned from
@@ -973,7 +1065,11 @@ handle_event(_, _, State, Data) ->
<tag><c>next_event</c></tag>
<item>
<p>
- Stores the specified <c><anno>EventType</anno></c>
+ This action does not set any
+ <seealso marker="#type-transition_option">
+ <c>transition_option()</c>
+ </seealso>
+ but instead stores the specified <c><anno>EventType</anno></c>
and <c><anno>EventContent</anno></c> for insertion after all
actions have been executed.
</p>
@@ -1026,15 +1122,34 @@ handle_event(_, _, State, Data) ->
for this state transition.
</p>
</item>
- <tag><c>Timeout</c></tag>
+ </taglist>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="timeout_action"/>
+ <desc>
+ <p>
+ These state transition actions can be invoked by
+ returning them from the
+ <seealso marker="#state callback">state callback</seealso>, from
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
+ or by giving them to
+ <seealso marker="#enter_loop/5"><c>enter_loop/5,6</c></seealso>.
+ </p>
+ <p>
+ These timeout actions sets timeout
+ <seealso marker="#type-transition_option">transition options</seealso>.
+ </p>
+ <taglist>
+ <tag><c>Time</c></tag>
<item>
<p>
- Short for <c>{timeout,Timeout,Timeout}</c>, that is,
+ Short for <c>{timeout,Time,Time}</c>, that is,
the time-out message is the time-out time.
This form exists to make the
<seealso marker="#state callback">state callback</seealso>
- return value <c>{next_state,NextState,NewData,Timeout}</c>
- allowed like for <c>gen_fsm</c>'s
+ return value <c>{next_state,NextState,NewData,Time}</c>
+ allowed like for <c>gen_fsm</c>.
</p>
</item>
<tag><c>timeout</c></tag>
@@ -1086,7 +1201,11 @@ handle_event(_, _, State, Data) ->
<seealso marker="#enter_loop/5"><c>enter_loop/5,6</c></seealso>.
</p>
<p>
- It replies to a caller waiting for a reply in
+ It does not set any
+ <seealso marker="#type-transition_option">
+ <c>transition_option()</c>
+ </seealso>
+ but instead replies to a caller waiting for a reply in
<seealso marker="#call/2"><c>call/2</c></seealso>.
<c><anno>From</anno></c> must be the term from argument
<seealso marker="#type-event_type"><c>{call,<anno>From</anno>}</c></seealso>
@@ -1329,7 +1448,7 @@ handle_event(_, _, State, Data) ->
<c><anno>T</anno></c> is the time-out time.
<c>{clean_timeout,<anno>T</anno>}</c> works like
just <c>T</c> described in the note above
- and uses a proxy process for <c>T &lt; infinity</c>,
+ and uses a proxy process
while <c>{dirty_timeout,<anno>T</anno>}</c>
bypasses the proxy process which is more lightweight.
</p>
@@ -1339,8 +1458,12 @@ handle_event(_, _, State, Data) ->
with <c>{dirty_timeout,<anno>T</anno>}</c>
to avoid that the calling process dies when the call
times out, you will have to be prepared to handle
- a late reply.
- So why not just let the calling process die?
+ a late reply. Note that there is an odd chance
+ to get a late reply even with
+ <c>{dirty_timeout,infinity}</c> or <c>infinity</c>
+ for example in the event of network problems.
+ So why not just let the calling process die
+ by not catching the exception?
</p>
</note>
<p>
@@ -1655,7 +1778,7 @@ handle_event(_, _, State, Data) ->
with the expected reason. Any other reason than <c>normal</c>,
<c>shutdown</c>, or <c>{shutdown,Term}</c> causes an
error report to be issued through
- <seealso marker="kernel:error_logger#format/2"><c>error_logger:format/2</c></seealso>.
+ <seealso marker="kernel:logger"><c>logger(3)</c></seealso>.
The default <c><anno>Reason</anno></c> is <c>normal</c>.
</p>
<p>
@@ -1851,7 +1974,7 @@ handle_event(_, _, State, Data) ->
</p>
<note>
<p>
- Note that if the <c>gen_statem</c> is started trough
+ Note that if the <c>gen_statem</c> is started through
<seealso marker="proc_lib"><c>proc_lib</c></seealso>
and
<seealso marker="#enter_loop/4"><c>enter_loop/4-6</c></seealso>,
@@ -2065,16 +2188,20 @@ init(Args) -> erlang:error(not_implemented, [Args]).</pre>
You may also not change states from this call.
Should you return <c>{next_state,NextState, ...}</c>
with <c>NextState =/= State</c> the <c>gen_statem</c> crashes.
- It is possible to use <c>{repeat_state, ...}</c>,
- <c>{repeat_state_and_data,_}</c> or
- <c>repeat_state_and_data</c> but all of them makes little
+ Note that it is actually allowed to use
+ <c>{repeat_state, NewData, ...}</c> although it makes little
sense since you immediately will be called again with a new
<em>state enter call</em> making this just a weird way
of looping, and there are better ways to loop in Erlang.
+ If you do not update <c>NewData</c> and have some
+ loop termination condition, or if you use
+ <c>{repeat_state_and_data, _}</c> or
+ <c>repeat_state_and_data</c> you have an infinite loop!
You are advised to use <c>{keep_state,...}</c>,
<c>{keep_state_and_data,_}</c> or
- <c>keep_state_and_data</c> since you can not change states
- from a <em>state enter call</em> anyway.
+ <c>keep_state_and_data</c>
+ since changing states from a <em>state enter call</em>
+ is not possible anyway.
</p>
<p>
Note the fact that you can use
@@ -2159,7 +2286,7 @@ init(Args) -> erlang:error(not_implemented, [Args]).</pre>
<c>shutdown</c>, or <c>{shutdown,Term}</c>,
the <c>gen_statem</c> is assumed to terminate because of an error
and an error report is issued using
- <seealso marker="kernel:error_logger#format/2"><c>error_logger:format/2</c></seealso>.
+ <seealso marker="kernel:logger"><c>logger(3)</c></seealso>.
</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/io.xml b/lib/stdlib/doc/src/io.xml
index 64fcf4379f..d4a2713840 100644
--- a/lib/stdlib/doc/src/io.xml
+++ b/lib/stdlib/doc/src/io.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -137,11 +137,11 @@
Hello world!
ok</pre>
<p>The general format of a control sequence is <c>~F.P.PadModC</c>.</p>
- <p>Character <c>C</c> determines the type of control sequence
- to be used, <c>F</c> and <c>P</c> are optional numeric
- arguments. If <c>F</c>, <c>P</c>, or <c>Pad</c> is <c>*</c>,
- the next argument in <c>Data</c> is used as the numeric value
- of <c>F</c> or <c>P</c>.</p>
+ <p>The character <c>C</c> determines the type of control sequence
+ to be used. It is the only required field. All of <c>F</c>,
+ <c>P</c>, <c>Pad</c>, and <c>Mod</c> are optional. For example,
+ to use a <c>#</c> for <c>Pad</c> but use the default values for
+ <c>F</c> and <c>P</c>, you can write <c>~..#C</c>.</p>
<list type="bulleted">
<item>
<p><c>F</c> is the <c>field width</c> of the printed argument. A
@@ -167,13 +167,26 @@ ok</pre>
The default padding character is <c>' '</c> (space).</p>
</item>
<item>
- <p><c>Mod</c> is the control sequence modifier. It is either a
- single character (<c>t</c>, for Unicode
- translation, and <c>l</c>, for stopping <c>p</c> and
- <c>P</c> from detecting printable characters)
- that changes the interpretation of <c>Data</c>.</p>
+ <p><c>Mod</c> is the control sequence modifier. This is
+ one or more characters that change the interpretation of
+ <c>Data</c>. The current modifiers are <c>t</c>, for Unicode
+ translation, and <c>l</c>, for stopping <c>p</c> and <c>P</c>
+ from detecting printable characters.</p>
</item>
</list>
+ <p>If <c>F</c>, <c>P</c>, or <c>Pad</c> is a <c>*</c> character,
+ the next argument in <c>Data</c> is used as the value.
+ For example:</p>
+ <pre>
+1> <input>io:fwrite("~*.*.0f~n",[9, 5, 3.14159265]).</input>
+003.14159
+ok</pre>
+ <p>To use a literal <c>*</c> character as <c>Pad</c>, it must be
+ passed as an argument:</p>
+ <pre>
+2> <input>io:fwrite("~*.*.*f~n",[9, 5, $*, 3.14159265]).</input>
+**3.14159
+ok</pre>
<p><em>Available control sequences:</em></p>
<taglist>
<tag><c>~</c></tag>
@@ -257,8 +270,9 @@ ok</pre>
\x{400}
ok
5> <input>io:fwrite("~s~n",[[1024]]).</input>
-** exception exit: {badarg,[{io,format,[&lt;0.26.0&gt;,"~s~n",[[1024]]]},
- ...</pre>
+** exception error: bad argument
+ in function io:format/3
+ called as io:format(&lt;0.53.0>,"~s~n",[[1024]])</pre>
</item>
<tag><c>w</c></tag>
<item>
@@ -276,10 +290,9 @@ ok
<c>~w</c>, but breaks terms whose printed representation
is longer than one line into many lines and indents each
line sensibly. Left-justification is not supported.
- It also tries to detect lists of
- printable characters and to output these as strings. The
- Unicode translation modifier is used for determining
- what characters are printable, for example:</p>
+ It also tries to detect flat lists of
+ printable characters and output these as strings.
+ For example:</p>
<pre>
1> <input>T = [{attributes,[[{id,age,1.50000},{mode,explicit},</input>
<input>{typename,"INTEGER"}], [{id,cho},{mode,explicit},{typename,'Cho'}]]},</input>
@@ -301,7 +314,7 @@ ok
{mode,implicit}]
ok</pre>
<p>The field width specifies the maximum line length.
- Defaults to 80. The precision specifies the initial
+ It defaults to 80. The precision specifies the initial
indentation of the term. It defaults to the number of
characters printed on this line in the <em>same</em> call to
<seealso marker="#write/1"><c>write/1</c></seealso> or
@@ -319,11 +332,22 @@ Here T = [{attributes,[[{id,age,1.5},
{tag,{'PRIVATE',3}},
{mode,implicit}]
ok</pre>
+
+ <p>As from Erlang/OTP 21.0, a field width of value
+ <c>0</c> can be used for specifying that a line is
+ infinitely long, which means that no line breaks
+ are inserted. For example:</p>
+
+ <pre>
+5> <input>io:fwrite("~0p~n", [lists:seq(1, 30)]).</input>
+[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
+ok</pre>
+
<p>When the modifier <c>l</c> is specified, no detection of
printable character lists takes place, for example:</p>
<pre>
-5> <input>S = [{a,"a"}, {b, "b"}].</input>
-6> <input>io:fwrite("~15p~n", [S]).</input>
+6> <input>S = [{a,"a"}, {b, "b"}],
+ io:fwrite("~15p~n", [S]).</input>
[{a,"a"},
{b,"b"}]
ok
@@ -331,18 +355,53 @@ ok
[{a,[97]},
{b,[98]}]
ok</pre>
- <p>Binaries that look like UTF-8 encoded strings are
- output with the string syntax if the Unicode translation
- modifier is specified:</p>
+ <p>The Unicode translation modifier <c>t</c> specifies how to treat
+ characters outside the Latin-1 range of codepoints, in
+ atoms, strings, and binaries. For example, printing an atom
+ containing a character &gt; 255:</p>
+ <pre>
+8> <input>io:fwrite("~p~n",[list_to_atom([1024])]).</input>
+'\x{400}'
+ok
+9> <input>io:fwrite("~tp~n",[list_to_atom([1024])]).</input>
+'Ѐ'
+ok</pre>
+ <p>By default, Erlang only detects lists of characters
+ in the Latin-1 range as strings, but the <c>+pc unicode</c>
+ flag can be used to change this (see <seealso
+ marker="#printable_range/0">
+ <c>printable_range/0</c></seealso> for details). For example:</p>
<pre>
-9> <input>io:fwrite("~p~n",[[1024]]).</input>
+10> <input>io:fwrite("~p~n",[[214]]).</input>
+"Ö"
+ok
+11> <input>io:fwrite("~p~n",[[1024]]).</input>
+[1024]
+ok
+12> <input>io:fwrite("~tp~n",[[1024]]).</input>
+[1024]
+ok
+</pre>
+ <p>but if Erlang was started with <c>+pc unicode</c>:</p>
+ <pre>
+13> <input>io:fwrite("~p~n",[[1024]]).</input>
[1024]
-10> <input>io:fwrite("~tp~n",[[1024]]).</input>
-"\x{400}"
-11> <input>io:fwrite("~tp~n", [&lt;&lt;128,128&gt;&gt;]).</input>
+ok
+14> <input>io:fwrite("~tp~n",[[1024]]).</input>
+"Ѐ"
+ok</pre>
+ <p>Similarly, binaries that look like UTF-8 encoded strings
+ are output with the binary string syntax if the <c>t</c>
+ modifier is specified:</p>
+ <pre>
+15> <input>io:fwrite("~p~n", [&lt;&lt;208,128&gt;&gt;]).</input>
+&lt;&lt;208,128&gt;&gt;
+ok
+16> <input>io:fwrite("~tp~n", [&lt;&lt;208,128&gt;&gt;]).</input>
+&lt;&lt;"Ѐ"/utf8&gt;&gt;
+ok
+17> <input>io:fwrite("~tp~n", [&lt;&lt;128,128&gt;&gt;]).</input>
&lt;&lt;128,128&gt;&gt;
-12> <input>io:fwrite("~tp~n", [&lt;&lt;208,128&gt;&gt;]).</input>
-&lt;&lt;"\x{400}"/utf8&gt;&gt;
ok</pre>
</item>
<tag><c>W</c></tag>
@@ -454,12 +513,9 @@ ok</pre>
abc def 'abc def' {foo,1} A
ok
2> <input>io:fwrite("~s", [65]).</input>
-** exception exit: {badarg,[{io,format,[&lt;0.22.0>,"~s","A"]},
- {erl_eval,do_apply,5},
- {shell,exprs,6},
- {shell,eval_exprs,6},
- {shell,eval_loop,3}]}
- in function io:o_request/2</pre>
+** exception error: bad argument
+ in function io:format/3
+ called as io:format(&lt;0.53.0>,"~s","A")</pre>
<p>In this example, an attempt was made to output the single
character 65 with the aid of the string formatting directive
<c>"~s"</c>.</p>
diff --git a/lib/stdlib/doc/src/io_lib.xml b/lib/stdlib/doc/src/io_lib.xml
index bc1d77ac83..a3df2897ac 100644
--- a/lib/stdlib/doc/src/io_lib.xml
+++ b/lib/stdlib/doc/src/io_lib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -52,6 +52,9 @@
</desc>
</datatype>
<datatype>
+ <name name="chars_limit"/>
+ </datatype>
+ <datatype>
<name name="depth"/>
</datatype>
<datatype>
@@ -153,6 +156,31 @@
</func>
<func>
+ <name name="format" arity="3"/>
+ <name name="fwrite" arity="3"/>
+ <fsummary>Write formatted output.</fsummary>
+ <desc>
+ <p>Returns a character list that represents <c><anno>Data</anno></c>
+ formatted in accordance with <c><anno>Format</anno></c> in
+ the same way as
+ <seealso marker="#fwrite/2"><c>fwrite/2</c></seealso> and
+ <seealso marker="#format/2"><c>format/2</c></seealso>,
+ but takes an extra argument, a list of options.</p>
+ <p>Valid option:</p>
+ <taglist>
+ <tag><c>{chars_limit, <anno>CharsLimit</anno>}</c></tag>
+ <item>
+ <p>A soft limit on the number of characters returned.
+ When the number of characters is reached, remaining
+ structures are replaced by "<c>...</c>".
+ <c><anno>CharsLimit</anno></c> defaults to -1, which
+ means no limit on the number of characters returned.</p>
+ </item>
+ </taglist>
+ </desc>
+ </func>
+
+ <func>
<name name="fread" arity="2"/>
<fsummary>Read formatted input.</fsummary>
<desc>
@@ -361,17 +389,24 @@
<fsummary>Write a term.</fsummary>
<desc>
<p>Returns a character list that represents <c><anno>Term</anno></c>.
- Argument <c><anno>Depth</anno></c> controls the depth of the
+ Option <c><anno>Depth</anno></c> controls the depth of the
structures written. When the specified depth is reached,
everything below this level is replaced by "<c>...</c>".
<c><anno>Depth</anno></c> defaults to -1, which means
- no limitation.</p>
+ no limitation. Option <c><anno>CharsLimit</anno></c> puts a
+ soft limit on the number of characters returned. When the
+ number of characters is reached, remaining structures are
+ replaced by "<c>...</c>". <c><anno>CharsLimit</anno></c>
+ defaults to -1, which means no limit on the number of
+ characters returned.</p>
<p><em>Example:</em></p>
<pre>
1> <input>lists:flatten(io_lib:write({1,[2],[3],[4,5],6,7,8,9})).</input>
"{1,[2],[3],[4,5],6,7,8,9}"
2> <input>lists:flatten(io_lib:write({1,[2],[3],[4,5],6,7,8,9}, 5)).</input>
-"{1,[2],[3],[...],...}"</pre>
+"{1,[2],[3],[...],...}"
+3> <input>lists:flatten(io_lib:write({[1,2,3],[4,5],6,7,8,9}, [{chars_limit,20}])).</input>
+"{[1,2|...],[4|...],...}"</pre>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/lib.xml b/lib/stdlib/doc/src/lib.xml
deleted file mode 100644
index 58dad7c9e0..0000000000
--- a/lib/stdlib/doc/src/lib.xml
+++ /dev/null
@@ -1,103 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE erlref SYSTEM "erlref.dtd">
-
-<erlref>
- <header>
- <copyright>
- <year>1996</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>lib</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <module>lib</module>
- <modulesummary>Useful library functions.</modulesummary>
- <description>
- <warning>
- <p>This module is retained for backward compatibility. It can disappear
- without warning in a future Erlang/OTP release.</p>
- </warning>
- </description>
-
- <funcs>
- <func>
- <name name="error_message" arity="2"/>
- <fsummary>Print error message.</fsummary>
- <desc>
- <p>Prints error message <c><anno>Args</anno></c> in accordance with
- <c><anno>Format</anno></c>. Similar to
- <seealso marker="io#format/1"><c>io:format/2</c></seealso>.</p>
- </desc>
- </func>
-
- <func>
- <name name="flush_receive" arity="0"/>
- <fsummary>Flush messages.</fsummary>
- <desc>
- <p>Flushes the message buffer of the current process.</p>
- </desc>
- </func>
-
- <func>
- <name name="nonl" arity="1"/>
- <fsummary>Remove last newline.</fsummary>
- <desc>
- <p>Removes the last newline character, if any, in
- <c><anno>String1</anno></c>.</p>
- </desc>
- </func>
-
- <func>
- <name name="progname" arity="0"/>
- <fsummary>Return name of Erlang start script.</fsummary>
- <desc>
- <p>Returns the name of the script that started the current
- Erlang session.</p>
- </desc>
- </func>
-
- <func>
- <name name="send" arity="2"/>
- <fsummary>Send a message.</fsummary>
- <desc>
- <p>Makes it possible to send a message using the <c>apply/3</c> BIF.</p>
- </desc>
- </func>
-
- <func>
- <name name="sendw" arity="2"/>
- <fsummary>Send a message and wait for an answer.</fsummary>
- <desc>
- <p>As <seealso marker="#send/2"><c>send/2</c></seealso>,
- but waits for an answer. It is implemented as follows:</p>
- <code type="none">
-sendw(To, Msg) ->
- To ! {self(),Msg},
- receive
- Reply -> Reply
- end.</code>
- <p>The returned message is not necessarily a reply to the sent
- message.</p>
- </desc>
- </func>
- </funcs>
-</erlref>
-
diff --git a/lib/stdlib/doc/src/lists.xml b/lib/stdlib/doc/src/lists.xml
index 60dbae70c2..c3d5d7e07a 100644
--- a/lib/stdlib/doc/src/lists.xml
+++ b/lib/stdlib/doc/src/lists.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -187,7 +187,7 @@
<desc>
<p>Calls <c><anno>Fun</anno>(<anno>Elem</anno>)</c> on successive
elements <c>Elem</c> of <c><anno>List1</anno></c>.
- <c><anno>Fun</anno>/2</c> must return either a Boolean or a tuple
+ <c><anno>Fun</anno>/1</c> must return either a Boolean or a tuple
<c>{true, <anno>Value</anno>}</c>. The function returns the list of
elements for which <c><anno>Fun</anno></c> returns a new value, where
a value of <c>true</c> is synonymous with
@@ -771,6 +771,18 @@ length(lists:seq(From, To, Incr)) =:= (To - From + Incr) div Incr</code>
</func>
<func>
+ <name name="search" arity="2"/>
+ <fsummary>Find the first element that satisfies a predicate.</fsummary>
+ <desc>
+ <p>If there is a <c><anno>Value</anno></c> in <c><anno>List</anno></c>
+ such that <c><anno>Pred</anno>(<anno>Value</anno>)</c> returns
+ <c>true</c>, returns <c>{value, <anno>Value</anno>}</c>
+ for the first such <c><anno>Value</anno></c>,
+ otherwise returns <c>false</c>.</p>
+ </desc>
+ </func>
+
+ <func>
<name name="splitwith" arity="2"/>
<fsummary>Split a list into two lists based on a predicate.</fsummary>
<desc>
diff --git a/lib/stdlib/doc/src/maps.xml b/lib/stdlib/doc/src/maps.xml
index 8c7270816b..a225dea3b5 100644
--- a/lib/stdlib/doc/src/maps.xml
+++ b/lib/stdlib/doc/src/maps.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2013</year><year>2016</year>
+ <year>2013</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,16 +33,31 @@
<p>This module contains functions for maps processing.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="iterator"/>
+ <desc>
+ <p>An iterator representing the key value associations in a map.</p>
+ <p>Created using <seealso marker="#iterator-1"><c>maps:iterator/1</c></seealso>.</p>
+ <p>Consumed by <seealso marker="#next-1"><c>maps:next/1</c></seealso>,
+ <seealso marker="#filter-2"><c>maps:filter/2</c></seealso>,
+ <seealso marker="#fold-3"><c>maps:fold/3</c></seealso> and
+ <seealso marker="#map-2"><c>maps:map/2</c></seealso>.</p>
+ </desc>
+ </datatype>
+ </datatypes>
+
<funcs>
<func>
<name name="filter" arity="2"/>
<fsummary>Select pairs that satisfy a predicate.</fsummary>
<desc>
- <p>Returns a map <c><anno>Map2</anno></c> for which predicate
- <c><anno>Pred</anno></c> holds true in <c><anno>Map1</anno></c>.</p>
+ <p>Returns a map <c><anno>Map</anno></c> for which predicate
+ <c><anno>Pred</anno></c> holds true in <c><anno>MapOrIter</anno></c>.</p>
<p>The call fails with a <c>{badmap,Map}</c> exception if
- <c><anno>Map1</anno></c> is not a map, or with <c>badarg</c> if
- <c><anno>Pred</anno></c> is not a function of arity 2.</p>
+ <c><anno>MapOrIter</anno></c> is not a map or valid iterator,
+ or with <c>badarg</c> if <c><anno>Pred</anno></c> is not a
+ function of arity 2.</p>
<p><em>Example:</em></p>
<code type="none">
> M = #{a => 2, b => 3, c=> 4, "a" => 1, "b" => 2, "c" => 4},
@@ -76,12 +91,16 @@
<fsummary></fsummary>
<desc>
<p>Calls <c>F(K, V, AccIn)</c> for every <c><anno>K</anno></c> to value
- <c><anno>V</anno></c> association in <c><anno>Map</anno></c> in
+ <c><anno>V</anno></c> association in <c><anno>MapOrIter</anno></c> in
any order. Function <c>fun F/3</c> must return a new
accumulator, which is passed to the next successive call.
This function returns the final value of the accumulator. The initial
accumulator value <c><anno>Init</anno></c> is returned if the map is
empty.</p>
+ <p>The call fails with a <c>{badmap,Map}</c> exception if
+ <c><anno>MapOrIter</anno></c> is not a map or valid iterator,
+ or with <c>badarg</c> if <c><anno>Fun</anno></c> is not a
+ function of arity 3.</p>
<p><em>Example:</em></p>
<code type="none">
> Fun = fun(K,V,AccIn) when is_list(K) -> AccIn + V end,
@@ -169,6 +188,32 @@ false</code>
</func>
<func>
+ <name name="iterator" arity="1"/>
+ <fsummary>Create a map iterator.</fsummary>
+ <desc>
+ <p>Returns a map iterator <c><anno>Iterator</anno></c> that can
+ be used by <seealso marker="#next-1"><c>maps:next/1</c></seealso>
+ to traverse the key-value associations in a map. When iterating
+ over a map, the memory usage is guaranteed to be bounded no matter
+ the size of the map.</p>
+ <p>The call fails with a <c>{badmap,Map}</c> exception if
+ <c><anno>Map</anno></c> is not a map.</p>
+ <p><em>Example:</em></p>
+ <code type="none">
+> M = #{ a => 1, b => 2 }.
+#{a => 1,b => 2}
+> I = maps:iterator(M).
+[{a,1},{b,2}]
+> {K1, V1, I2} = maps:next(I).
+{a,1,[{b,2}]}
+> {K2, V2, I3} = maps:next(I2).
+{b,2,[]}
+> maps:next(I3).
+none</code>
+ </desc>
+ </func>
+
+ <func>
<name name="keys" arity="1"/>
<fsummary></fsummary>
<desc>
@@ -188,12 +233,16 @@ false</code>
<name name="map" arity="2"/>
<fsummary></fsummary>
<desc>
- <p>Produces a new map <c><anno>Map2</anno></c> by calling function
+ <p>Produces a new map <c><anno>Map</anno></c> by calling function
<c>fun F(K, V1)</c> for every <c><anno>K</anno></c> to value
- <c><anno>V1</anno></c> association in <c><anno>Map1</anno></c> in
+ <c><anno>V1</anno></c> association in <c><anno>MapOrIter</anno></c> in
any order. Function <c>fun F/2</c> must return value
<c><anno>V2</anno></c> to be associated with key <c><anno>K</anno></c>
- for the new map <c><anno>Map2</anno></c>.</p>
+ for the new map <c><anno>Map</anno></c>.</p>
+ <p>The call fails with a <c>{badmap,Map}</c> exception if
+ <c><anno>MapOrIter</anno></c> is not a map or valid iterator,
+ or with <c>badarg</c> if <c><anno>Fun</anno></c> is not a
+ function of arity 2.</p>
<p><em>Example:</em></p>
<code type="none">
> Fun = fun(K,V1) when is_list(K) -> V1*2 end,
@@ -234,6 +283,35 @@ false</code>
</func>
<func>
+ <name name="next" arity="1"/>
+ <fsummary>Get the next key and value from an iterator.</fsummary>
+ <desc>
+ <p>Returns the next key-value association in
+ <c><anno>Iterator</anno></c> and a new iterator for the
+ remaining associations in the iterator.
+ </p>
+ <p>
+ If there are no more associations in the iterator,
+ <c>none</c> is returned.
+ </p>
+ <p><em>Example:</em></p>
+ <code type="none">
+> Map = #{a => 1, b => 2, c => 3}.
+#{a => 1,b => 2,c => 3}
+> Iter = maps:iterator(Map).
+[{a,1},{b,2},{c,3}]
+> {_, _, Iter1} = maps:next(Iter).
+{a,1,[{b,2},{c,3}]}
+> {_, _, Iter2} = maps:next(Iter1).
+{b,2,[{c,3}]}
+> {_, _, Iter3} = maps:next(Iter2).
+{c,3,[]}
+> maps:next(Iter3).
+none</code>
+ </desc>
+ </func>
+
+ <func>
<name name="put" arity="3"/>
<fsummary></fsummary>
<desc>
diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml
index 46454e9b80..d800885b16 100644
--- a/lib/stdlib/doc/src/notes.xml
+++ b/lib/stdlib/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,660 @@
</header>
<p>This document describes the changes made to the STDLIB application.</p>
+<section><title>STDLIB 3.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The specs of <c>filename:basedir/2,3</c> are
+ corrected.</p>
+ <p>
+ Own Id: OTP-15252 Aux Id: ERL-667 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Let <c>dets:open_file()</c> exit with a <c>badarg</c>
+ message if given a raw file name (a binary). </p>
+ <p>
+ Own Id: OTP-15253 Aux Id: OTP-13229, ERL-55 </p>
+ </item>
+ <item>
+ <p> The <c>Format</c> argument of the formatting
+ functions in modules <c>io</c> and <c>io_lib</c> is
+ accepted even if it is, for example, a list of binaries.
+ This is how it used to be before Erlang/OTP 21.0. </p>
+ <p>
+ Own Id: OTP-15304</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 3.5.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug that could cause a crash when formatting a
+ list of non-characters using the control sequences
+ <c>p</c> or <c>P</c> and limiting the output with the
+ option <c>chars_limit</c>. </p>
+ <p>
+ Own Id: OTP-15159</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 3.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p><c>gen_statem</c> improvements.</p> <p> When using an
+ exception that is valid but not allowed in a state enter
+ call, the reason has been changed from
+ <c>{bad_action_from_state_function,Action}</c> to
+ <c>{bad_state_enter_action_from_state_function,Action}</c>.
+ </p><p> Timer parsing has been improved. Many erroneous
+ timeout tuples was not handled correctly. </p><p> The
+ documentation has been updated, in particular the User's
+ Guide and the pointer to it from the Reference Manual is
+ much more obvious. </p>
+ <p>
+ Own Id: OTP-14015</p>
+ </item>
+ <item>
+ <p>
+ The type specifications for <c>file:posix/0</c> and
+ <c>inet:posix/0</c> have been updated according to which
+ errors file and socket operations should be able to
+ return.</p>
+ <p>
+ Own Id: OTP-14019 Aux Id: ERL-550 </p>
+ </item>
+ <item>
+ <p> File operations used to accept <seealso
+ marker="kernel:file#type-name_all">filenames</seealso>
+ containing null characters (integer value zero). This
+ caused the name to be truncated and in some cases
+ arguments to primitive operations to be mixed up.
+ Filenames containing null characters inside the filename
+ are now <em>rejected</em> and will cause primitive file
+ operations to fail. </p> <p> Also environment variable
+ operations used to accept <seealso
+ marker="kernel:os#type-env_var_name">names</seealso> and
+ <seealso
+ marker="kernel:os#type-env_var_value">values</seealso> of
+ environment variables containing null characters (integer
+ value zero). This caused operations to silently produce
+ erroneous results. Environment variable names and values
+ containing null characters inside the name or value are
+ now <em>rejected</em> and will cause environment variable
+ operations to fail. </p> <p>Primitive environment
+ variable operations also used to accept the <c>$=</c>
+ character in environment variable names causing various
+ problems. <c>$=</c> characters in environment variable
+ names are now also <em>rejected</em>. </p> <p>Also
+ <seealso
+ marker="kernel:os#cmd/1"><c>os:cmd/1</c></seealso> now
+ reject null characters inside its <seealso
+ marker="kernel:os#type-os_command">command</seealso>.
+ </p> <p><seealso
+ marker="erts:erlang#open_port/2"><c>erlang:open_port/2</c></seealso>
+ will also reject null characters inside the port name
+ from now on.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-14543 Aux Id: ERL-370 </p>
+ </item>
+ <item>
+ <p> Make <c>io_lib:unscan_format/1</c> work with pad char
+ and default precision. </p>
+ <p>
+ Own Id: OTP-14958 Aux Id: PR-1735 </p>
+ </item>
+ <item>
+ <p> The control sequence modifiers <c>t</c> and <c>l</c>
+ can be used together in the same control sequence which
+ makes it possible to have Unicode atoms and no detection
+ of printable character lists at the same time. </p>
+ <p>
+ Own Id: OTP-14971 Aux Id: PR-1743 </p>
+ </item>
+ <item>
+ <p> Fix a bug in the Erlang code linter: the check of
+ guard expressions no longer returns <c>false</c> if the
+ map syntax is used. The bug affected the Erlang shell,
+ the Debugger, and other modules evaluating abstract code.
+ </p>
+ <p>
+ Own Id: OTP-15035 Aux Id: ERL-613 </p>
+ </item>
+ <item>
+ <p>
+ A sys debug fun of type {Fun,State} should not be
+ possible to install twice. This was, however, possible if
+ the current State was 'undefined', which was mistaken for
+ non-existing fun. This has been corrected.</p>
+ <p>
+ Own Id: OTP-15049</p>
+ </item>
+ <item>
+ <p>
+ Fix <c>io:putchars/2</c> stacktrace rewriting at errors
+ to point to a valid function.</p>
+ <p>
+ Own Id: OTP-15101</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The <c>gen_server</c> has gotten a new callback
+ <c>handle_continue/2</c> for check pointing the state.
+ This is useful at least when implementing behaviours on
+ top of <c>gen_server</c> and for some start up scenarios.</p>
+ <p>
+ Own Id: OTP-13019 Aux Id: PR-1490 </p>
+ </item>
+ <item>
+ <p> The semantics of timeout parameter
+ <c>{clean_timeout,infinity}</c> to
+ <c>gen_statem:call/3</c> has been changed to use a proxy
+ process for the call. With this change
+ <c>clean_timeout</c> implicates a proxy process with no
+ exceptions. This may be a hard to observe
+ incompatibility: in the presence of network problems a
+ late reply could arrive in the caller's message queue
+ when catching errors. That will not happen after this
+ correction. </p><p> The semantics of timeout parameter
+ <c>infinity</c> has not been changed. </p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-13073 Aux Id: PR-1595 </p>
+ </item>
+ <item>
+ <p>A new logging API is added to Erlang/OTP, see the
+ <seealso
+ marker="kernel:logger"><c>logger(3)</c></seealso> manual
+ page, and section <seealso
+ marker="kernel:logger_chapter">Logging</seealso> in the
+ Kernel User's Guide.</p>
+ <p>Calls to <c>error_logger</c> are automatically
+ redirected to the new API, and legacy error logger event
+ handlers can still be used. It is, however, recommended
+ to use the Logger API directly when writing new code.</p>
+ <p>Notice the following potential incompatibilities:</p>
+ <list> <item><p>Kernel configuration parameters
+ <c>error_logger</c> still works, but is overruled if the
+ default handler's output destination is configured with
+ Kernel configuration parameter <c>logger</c>.</p> <p>In
+ general, parameters for configuring error logger are
+ overwritten by new parameters for configuring
+ Logger.</p></item> <item><p>The concept of SASL error
+ logging is deprecated, meaning that by default the SASL
+ application does not affect which log events are
+ logged.</p> <p>By default, supervisor reports and crash
+ reports are logged by the default Logger handler started
+ by Kernel, and end up at the same destination (terminal
+ or file) as other standard log event from Erlang/OTP.</p>
+ <p>Progress reports are not logged by default, but can be
+ enabled by setting the primary log level to info, for
+ example with the Kernel configuration parameter
+ <c>logger_level</c>.</p> <p>To obtain backwards
+ compatibility with the SASL error logging functionality
+ from earlier releases, set Kernel configuration parameter
+ <c>logger_sasl_compatible</c> to <c>true</c>. This
+ prevents the default Logger handler from logging any
+ supervisor-, crash-, or progress reports. Instead, SASL
+ adds a separate Logger handler during application start,
+ which takes care of these log events. The SASL
+ configuration parameters <c>sasl_error_logger</c> and
+ <c>sasl_errlog_type</c> specify the destination (terminal
+ or file) and severity level to log for these
+ events.</p></item></list>
+ <p>
+ Since Logger is new in Erlang/OTP 21.0, we do reserve the
+ right to introduce changes to the Logger API and
+ functionality in patches following this release. These
+ changes might or might not be backwards compatible with
+ the initial version.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-13295</p>
+ </item>
+ <item>
+ <p> Add functions
+ <c>calendar:system_time_to_local_time/2</c> and
+ <c>calendar:system_time_to_universal_time/2</c>. </p>
+ <p>
+ Own Id: OTP-13413</p>
+ </item>
+ <item>
+ <p> Functions <c>rand:uniform_real/0</c> and
+ <c>rand:uniform_real_s/1</c> have been added. They
+ produce uniformly distributed numbers in the range <c>0.0
+ =&lt; X &lt; 1.0</c> that are as close to random real
+ numbers as Normalized IEEE 754 Double Precision allows.
+ Because the random real number exactly <c>0.0</c> is
+ infinitely improbable they will never return exactly
+ <c>0.0</c>. </p><p> These properties are useful when you
+ need to call for example <c>math:log(X)</c> or <c>1 /
+ X</c> on a random value <c>X</c>, since that will never
+ fail with a number from these new functions. </p>
+ <p>
+ Own Id: OTP-13764 Aux Id: PR-1574 </p>
+ </item>
+ <item>
+ <p>
+ Added maps:iterator/0 and maps:next/1 to be used for
+ iterating over the key-value associations in a map.</p>
+ <p>
+ Own Id: OTP-14012</p>
+ </item>
+ <item>
+ <p>Changed the default behaviour of <c>.erlang</c>
+ loading: <c>.erlang</c> is no longer loaded from the
+ current directory. <c>c:erlangrc(PathList)</c> can be
+ used to search and load an <c>.erlang</c> file from user
+ specified directories.</p> <p><c>escript</c>,
+ <c>erlc</c>, <c>dialyzer</c> and <c>typer</c> no longer
+ load an <c>.erlang</c> at all.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-14439</p>
+ </item>
+ <item>
+ <p>
+ Added new uri_string module to stdlib for handling URIs
+ (RFC 3986).</p>
+ <p>
+ Own Id: OTP-14496</p>
+ </item>
+ <item>
+ <p>
+ Update Unicode specification to version 10.0.</p>
+ <p>
+ Own Id: OTP-14503</p>
+ </item>
+ <item>
+ <p><c>filelib:wildcard()</c> now allows characters with a
+ special meaning to be escaped using backslashes.</p>
+ <p>This is an incompatible change, but note that the use
+ of backslashes in wildcards would already work
+ differently on Windows and Unix. Existing calls to
+ <c>filelib:wildcard()</c> needs to be updated. On
+ Windows, directory separators must always be written as a
+ slash.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-14577</p>
+ </item>
+ <item>
+ <p>
+ The supervisor now stores its child specifications in a
+ map instead of a list. This causes a significant
+ improvement when starting many children under a
+ non-simple_one_for_one supervisor.</p>
+ <p>
+ Own Id: OTP-14586</p>
+ </item>
+ <item>
+ <p> The <c>base64</c> module is optimized. </p> <p> Note
+ that the functions <c>encode/1</c>, <c>decode/1</c>, and
+ <c>mime_decode/1</c> fail unless called with an argument
+ of the documented type. They used to accept any
+ <c>iodata()</c>. </p>
+ <p>
+ Own Id: OTP-14624 Aux Id: PR-1565 </p>
+ </item>
+ <item>
+ <p> Add function <c>lists:search/2</c>. </p>
+ <p>
+ Own Id: OTP-14675 Aux Id: PR-102 </p>
+ </item>
+ <item>
+ <p>
+ uri_string module extended with functions for handling
+ application/x-www-form-urlencoded query strings based on
+ the HTML5 specification.</p>
+ <p>
+ Own Id: OTP-14747</p>
+ </item>
+ <item>
+ <p> Add functions
+ <c>calendar:rfc3339_to_system_time/1,2</c> and
+ <c>calendar:system_time_to_rfc3339/1,2</c>. </p>
+ <p>
+ Own Id: OTP-14764</p>
+ </item>
+ <item>
+ <p> The stack traces returned by the functions of the
+ <c>erl_eval</c> module more accurately reflect where the
+ exception occurred. </p>
+ <p>
+ Own Id: OTP-14826 Aux Id: PR 1540 </p>
+ </item>
+ <item>
+ <p> Add options <c>atime</c>, <c>mtime</c>, <c>ctime</c>,
+ <c>uid</c>, and <c>gid</c> to the <c>erl_tar:add/3,4</c>
+ functions. </p>
+ <p>
+ Own Id: OTP-14834 Aux Id: PR 1608 </p>
+ </item>
+ <item>
+ <p>Added <c>ets:whereis/1</c> for retrieving the table
+ identifier of a named table.</p>
+ <p>
+ Own Id: OTP-14884</p>
+ </item>
+ <item>
+ <p>
+ Improved URI normalization functions in the uri_string
+ module.</p>
+ <p>
+ Own Id: OTP-14910</p>
+ </item>
+ <item>
+ <p> The new functions <c>io_lib:fwrite/3</c> and
+ <c>io_lib:format/3</c> take a third argument, an option
+ list. The only option is <c>chars_limit</c>, which is
+ used for limiting the number of returned characters. The
+ limit is soft, which means that the number of returned
+ characters exceeds the limit with at most a smallish
+ amount. If the limit is set, the functions
+ <c>format/3</c> and <c>fwrite/3</c> try to distribute the
+ number of characters evenly over the control sequences
+ <c>pPswW</c>. Furthermore, the control sequences
+ <c>pPwP</c> try to distribute the number of characters
+ evenly over substructures. </p> <p> A modification of the
+ control sequences <c>pPwW</c> is that even if there is no
+ limit on the number of returned characters, all
+ associations of a map are printed to the same depth. The
+ aim is to give a more consistent output as the order of
+ map keys is not defined. As before, if the depth is less
+ than the number of associations of a map, the selection
+ of associations to print is arbitrary. </p>
+ <p>
+ Own Id: OTP-14983</p>
+ </item>
+ <item>
+ <p> Add functions <c>ordsets:is_empty/1</c> and
+ <c>sets:is_empty/1</c>. </p>
+ <p>
+ Own Id: OTP-14996 Aux Id: ERL-557, PR-1703 </p>
+ </item>
+ <item>
+ <p>
+ Improve performance of <c>string:uppercase/1</c>,
+ <c>string:lowercase/1</c> and <c>string:casefold/1</c>
+ when handling ASCII characters.</p>
+ <p>
+ Own Id: OTP-14998</p>
+ </item>
+ <item>
+ <p>External funs with literal values for module, name,
+ and arity (e.g. <c>erlang:abs/1</c>) are now treated as
+ literals. That means more efficient code that produces
+ less garbage on the heap.</p>
+ <p>
+ Own Id: OTP-15003</p>
+ </item>
+ <item>
+ <p>
+ sys:statistics(Pid,get) did not report 'out' messages
+ from gen_server. This is now corrected.</p>
+ <p>
+ Own Id: OTP-15047</p>
+ </item>
+ <item>
+ <p>
+ A sys debug function can now have the format
+ {Id,Fun,State} in addition to the old {Fun,State}. This
+ allows installing multiple instances of a debug fun.</p>
+ <p>
+ Own Id: OTP-15048</p>
+ </item>
+ <item>
+ <p> The <c>lib</c> module is removed:</p> <list
+ type="bulleted"> <item><c>lib:error_message/2</c> is
+ removed.</item> <item><c>lib:flush_receive/0</c> is
+ removed.</item> <item><c>lib:nonl/1</c> is
+ removed.</item> <item><c>lib:progname/0</c> is replaced
+ by <c>ct:get_progname/0</c>.</item>
+ <item><c>lib:send/2</c> is removed.</item>
+ <item><c>lib:sendw/2</c> is removed.</item> </list>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15072 Aux Id: PR 1786, OTP-15114 </p>
+ </item>
+ <item>
+ <p>
+ Function <c>ets:delete_all_objects/1</c> now yields the
+ scheduler thread for large tables that take significant
+ time to clear. This to improve real time characteristics
+ of other runnable processes.</p>
+ <p>
+ Own Id: OTP-15078</p>
+ </item>
+ <item>
+ <p> In control sequences of the functions
+ <c>io:fwrite/2,3</c> and <c>io_lib:fwrite/2,3</c>
+ containing <c>p</c> or <c>P</c>, a field width of value
+ <c>0</c> means that no line breaks are inserted. This is
+ in contrast to the old behaviour, where <c>0</c> used to
+ insert line breaks after every subterm. To insert line
+ breaks after every subterm, a field width of value
+ <c>1</c> can be used. </p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15103 Aux Id: ERL-607 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 3.4.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The <c>Module:init/1</c> function in <c>gen_statem</c>
+ may return an actions list containing any action, but an
+ erroneous check only allowed state enter actions so e.g
+ <c>{next_event,internal,event}</c> caused a server crash.
+ This bug has been fixed.</p>
+ <p>
+ Own Id: OTP-13995</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 3.4.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Correct <c>filelib:find_source()</c> and
+ <c>filelib:find_file()</c> to by default also search one
+ level below <c>src</c>. This is in accordance with the
+ Design Principles which states that an application can
+ have Erlang source files one level below the <c>src</c>
+ directory. </p>
+ <p>
+ Own Id: OTP-14832 Aux Id: ERL-527 </p>
+ </item>
+ <item>
+ <p> The contract of <c>erl_tar:table/2</c> is corrected.
+ </p>
+ <p>
+ Own Id: OTP-14860 Aux Id: PR 1670 </p>
+ </item>
+ <item>
+ <p> Correct a few contracts. </p>
+ <p>
+ Own Id: OTP-14889</p>
+ </item>
+ <item>
+ <p>
+ Fix string:prefix/2 to handle an empty string as second
+ argument.</p>
+ <p>
+ Own Id: OTP-14942 Aux Id: PR-1702 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 3.4.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Make <c>ets:i/1</c> exit cleaner when ^D is input
+ while browsing a table. Only the old Erlang shell is
+ affected (<c>erl(1)</c> flag <c>-oldshell</c>). </p>
+ <p>
+ Own Id: OTP-14663</p>
+ </item>
+ <item>
+ <p>
+ Fixed handling of windows UNC paths in module
+ <c>filename</c>.</p>
+ <p>
+ Own Id: OTP-14693</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Improve performance of the new string functionality when
+ handling ASCII characters.</p>
+ <p>
+ Own Id: OTP-14670</p>
+ </item>
+ <item>
+ <p>
+ Added a clarification to the documentation of
+ <c>unicode:characters_to_list/2</c>.</p>
+ <p>
+ Own Id: OTP-14798</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 3.4.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug in the Erlang shell where recursively
+ defined records with typed fields could cause a loop.
+ </p>
+ <p>
+ Own Id: OTP-14488 Aux Id: PR-1489 </p>
+ </item>
+ <item>
+ <p>
+ Make edlin handle grapheme clusters instead of codepoints
+ to improve the handling multi-codepoints characters.</p>
+ <p>
+ Own Id: OTP-14542</p>
+ </item>
+ <item>
+ <p>There could be false warnings for
+ <c>erlang:get_stacktrace/0</c> being used outside of a
+ <c>try</c> block when using multiple <c>catch</c>
+ clauses.</p>
+ <p>
+ Own Id: OTP-14600 Aux Id: ERL-478 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> The Erlang code linter no longer checks that the
+ functions mentioned in <c>nowarn_deprecated_function</c>
+ options are declared in the module. </p>
+ <p>
+ Own Id: OTP-14378</p>
+ </item>
+ <item>
+ <p>
+ General Unicode improvements.</p>
+ <p>
+ Own Id: OTP-14462</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 3.4.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> A bug in <c>proc_lib:format()</c> introduced in
+ Erlang/OTP 20.0 is corrected. </p>
+ <p>
+ Own Id: OTP-14482 Aux Id: PR-1488 </p>
+ </item>
+ <item>
+ <p>
+ Fix string:len/1 to be compatible with previous versions.</p>
+ <p>
+ Own Id: OTP-14487 Aux Id: ERIERL-40 </p>
+ </item>
+ <item>
+ <p>
+ In OTP-20.0, the behavior of c, make, and ct_make was
+ changed so that in some cases the beam files by default
+ would be written to the directory where the source files
+ were found. This is now changed back to the old behavior
+ so beam files are by default written to current
+ directory.</p>
+ <p>
+ Own Id: OTP-14489 Aux Id: ERL-438 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>STDLIB 3.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -400,7 +1054,7 @@
marker="erts:erl"><c>erl</c></seealso> command.</p>
<p>
See <url
- href="http://pcre.org/original/changelog.txt"><c>http://pcre.org/original/changelog.txt</c></url>
+ href="http://pcre.org/original/changelog.txt">http://pcre.org/original/changelog.txt</url>
for information about changes made to PCRE between the
versions 8.33 and 8.40.</p>
<p>
diff --git a/lib/stdlib/doc/src/ordsets.xml b/lib/stdlib/doc/src/ordsets.xml
index 7b590932e4..11f98c8fb7 100644
--- a/lib/stdlib/doc/src/ordsets.xml
+++ b/lib/stdlib/doc/src/ordsets.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -142,6 +142,15 @@
</func>
<func>
+ <name name="is_empty" arity="1"/>
+ <fsummary>Test for empty set.</fsummary>
+ <desc>
+ <p>Returns <c>true</c> if <c><anno>Ordset</anno></c> is an empty set,
+ otherwise <c>false</c>.</p>
+ </desc>
+ </func>
+
+ <func>
<name name="is_set" arity="1"/>
<fsummary>Test for an <c>Ordset</c>.</fsummary>
<desc>
diff --git a/lib/stdlib/doc/src/part_notes.xml b/lib/stdlib/doc/src/part_notes.xml
deleted file mode 100644
index 461de749dd..0000000000
--- a/lib/stdlib/doc/src/part_notes.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>STDLIB Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p>The Standard Erlang Libraries application, <em>STDLIB</em>,
- contains modules for manipulating lists, strings and files etc.</p>
- <p>For information about older versions, see
- <url href="part_notes_history_frame.html">Release Notes History</url>.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/stdlib/doc/src/part_notes_history.xml b/lib/stdlib/doc/src/part_notes_history.xml
deleted file mode 100644
index 8fd048a41e..0000000000
--- a/lib/stdlib/doc/src/part_notes_history.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2006</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>STDLIB Release Notes History</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p>The Standard Erlang Libraries application, <em>STDLIB</em>,
- contains modules for manipulating lists, strings and files etc.</p>
- </description>
- <include file="notes_history"></include>
-</part>
-
diff --git a/lib/stdlib/doc/src/proc_lib.xml b/lib/stdlib/doc/src/proc_lib.xml
index cb152d1935..b85fab67d5 100644
--- a/lib/stdlib/doc/src/proc_lib.xml
+++ b/lib/stdlib/doc/src/proc_lib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -59,18 +59,17 @@
<p>When a process that is started using <c>proc_lib</c> terminates
abnormally (that is, with another exit reason than <c>normal</c>,
<c>shutdown</c>, or <c>{shutdown,Term}</c>), a <em>crash report</em>
- is generated, which is written to terminal by the default SASL
- event handler. That is, the crash report is normally only visible
- if the SASL application is started; see
- <seealso marker="sasl:sasl_app"><c>sasl(6)</c></seealso> and section
+ is generated, which is written to terminal by the default logger
+ handler setup by Kernel. For more information about how crash reports
+ were logged prior to Erlang/OTP 21.0, see
<seealso marker="sasl:error_logging">SASL Error Logging</seealso>
in the SASL User's Guide.</p>
<p>Unlike in "plain Erlang", <c>proc_lib</c> processes will not generate
<em>error reports</em>, which are written to the terminal by the
- emulator and do not require SASL to be started. All exceptions are
+ emulator. All exceptions are
converted to <em>exits</em> which are ignored by the default
- <c>error_logger</c> handler.</p>
+ <c>logger</c> handler.</p>
<p>The crash report contains the previously stored information, such
as ancestors and initial function, the termination reason, and
@@ -115,12 +114,22 @@
<name name="format" arity="2"/>
<fsummary>Format a crash report.</fsummary>
<desc>
- <p>This function can be used by a user-defined event handler to
+ <note>
+ <p>This function is deprecated in the sense that
+ the <c>error_logger</c> is no longer the preferred
+ interface for logging in Erlang/OTP. A
+ new <seealso marker="kernel:logger_chapter">logging
+ API</seealso> was added in Erlang/OTP 21.0, but
+ legacy <c>error_logger</c> handlers can still be used. New
+ Logger handlers do not need to use this function, since
+ the formatting callback (<c>report_cb</c>) is included as
+ metadata in the log event.</p>
+ </note>
+ <p>This function can be used by a user-defined legacy
+ <c>error_logger</c> event handler to
format a crash report. The crash report is sent using
- <seealso marker="kernel:error_logger#error_report/2">
- <c>error_logger:error_report(crash_report,
- <anno>CrashReport</anno>)</c></seealso>.
- That is, the event to be handled is of the format
+ <seealso marker="kernel:logger">
+ <c>logger(3)</c></seealso>, and the event to be handled is of the format
<c>{error_report, GL, {Pid, crash_report,
<anno>CrashReport</anno>}}</c>,
where <c>GL</c> is the group leader pid of process
@@ -132,7 +141,19 @@
<name name="format" arity="3"/>
<fsummary>Format a crash report.</fsummary>
<desc>
- <p>This function can be used by a user-defined event handler to
+ <note>
+ <p>This function is deprecated in the sense that
+ the <c>error_logger</c> is no longer the preferred
+ interface for logging in Erlang/OTP. A
+ new <seealso marker="kernel:logger_chapter">logging
+ API</seealso> was added in Erlang/OTP 21.0, but
+ legacy <c>error_logger</c> handlers can still be used. New
+ Logger handlers do not need to used this function, since
+ the formatting callback (<c>report_cb</c>) is included as
+ metadata in the log event.</p>
+ </note>
+ <p>This function can be used by a user-defined legacy
+ <c>error_logger</c> event handler to
format a crash report. When <anno>Depth</anno> is specified as a
positive integer, it is used in the format string to
limit the output as follows: <c>io_lib:format("~P",
@@ -395,6 +416,8 @@ init(Parent) ->
<title>See Also</title>
<p><seealso marker="kernel:error_logger">
<c>error_logger(3)</c></seealso></p>
+ <p><seealso marker="kernel:logger">
+ <c>logger(3)</c></seealso></p>
</section>
</erlref>
diff --git a/lib/stdlib/doc/src/rand.xml b/lib/stdlib/doc/src/rand.xml
index e06d7e467d..21f680a0ee 100644
--- a/lib/stdlib/doc/src/rand.xml
+++ b/lib/stdlib/doc/src/rand.xml
@@ -35,12 +35,19 @@
<module>rand</module>
<modulesummary>Pseudo random number generation.</modulesummary>
<description>
- <p>This module provides a random number generator. The module contains
- a number of algorithms. The uniform distribution algorithms use the
- <url href="http://xorshift.di.unimi.it">scrambled Xorshift algorithms by
- Sebastiano Vigna</url>. The normal distribution algorithm uses the
- <url href="http://www.jstatsoft.org/v05/i08">Ziggurat Method by Marsaglia
- and Tsang</url>.</p>
+ <p>
+ This module provides a pseudo random number generator.
+ The module contains a number of algorithms.
+ The uniform distribution algorithms use the
+ <url href="http://xorshift.di.unimi.it">
+ xoroshiro116+ and xorshift1024* algorithms by Sebastiano Vigna.
+ </url>
+ The normal distribution algorithm uses the
+ <url href="http://www.jstatsoft.org/v05/i08">
+ Ziggurat Method by Marsaglia and Tsang
+ </url>
+ on top of the uniform distribution algorithm.
+ </p>
<p>For some algorithms, jump functions are provided for generating
non-overlapping sequences for parallel computations.
The jump functions perform calculations
@@ -66,7 +73,7 @@
<p>Jump function: equivalent to 2^64 calls</p>
<p>
This is a corrected version of the previous default algorithm,
- that now has been superseeded by Xoroshiro116+ (<c>exrop</c>).
+ that now has been superseded by Xoroshiro116+ (<c>exrop</c>).
Since there is no native 58 bit rotate instruction this
algorithm executes a little (say &lt; 15%) faster than <c>exrop</c>.
See the
@@ -126,8 +133,9 @@
variable <c>rand_seed</c> to remember the current state.</p>
<p>If a process calls
- <seealso marker="#uniform-0"><c>uniform/0</c></seealso> or
- <seealso marker="#uniform-1"><c>uniform/1</c></seealso> without
+ <seealso marker="#uniform-0"><c>uniform/0</c></seealso>,
+ <seealso marker="#uniform-1"><c>uniform/1</c></seealso> or
+ <seealso marker="#uniform_real-0"><c>uniform_real/0</c></seealso> without
setting a seed first, <seealso marker="#seed-1"><c>seed/1</c></seealso>
is called automatically with the default algorithm and creates a
non-constant seed.</p>
@@ -161,10 +169,17 @@ R3 = rand:uniform(),</pre>
S0 = rand:seed_s(exrop),
{R4, S1} = rand:uniform_s(S0),</pre>
+ <p>Textbook basic form Box-Muller standard normal deviate</p>
+
+ <pre>
+R5 = rand:uniform_real(),
+R6 = rand:uniform(),
+SND0 = math:sqrt(-2 * math:log(R5)) * math:cos(math:pi() * R6)</pre>
+
<p>Create a standard normal deviate:</p>
<pre>
-{SND0, S2} = rand:normal_s(S1),</pre>
+{SND1, S2} = rand:normal_s(S1),</pre>
<p>Create a normal deviate with mean -3 and variance 0.5:</p>
@@ -393,9 +408,71 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
<name name="uniform" arity="0"/>
<fsummary>Return a random float.</fsummary>
<desc><marker id="uniform-0"/>
- <p>Returns a random float uniformly distributed in the value
+ <p>
+ Returns a random float uniformly distributed in the value
range <c>0.0 =&lt; <anno>X</anno> &lt; 1.0</c> and
- updates the state in the process dictionary.</p>
+ updates the state in the process dictionary.
+ </p>
+ <p>
+ The generated numbers are on the form N * 2.0^(-53),
+ that is; equally spaced in the interval.
+ </p>
+ <warning>
+ <p>
+ This function may return exactly <c>0.0</c> which can be
+ fatal for certain applications. If that is undesired
+ you can use <c>(1.0 - rand:uniform())</c> to get the
+ interval <c>0.0 &lt; <anno>X</anno> =&lt; 1.0</c>, or instead use
+ <seealso marker="#uniform_real-0"><c>uniform_real/0</c></seealso>.
+ </p>
+ <p>
+ If neither endpoint is desired you can test and re-try
+ like this:
+ </p>
+ <pre>
+my_uniform() ->
+ case rand:uniform() of
+ 0.0 -> my_uniform();
+ X -> X
+ end
+end.</pre>
+ </warning>
+ </desc>
+ </func>
+
+ <func>
+ <name name="uniform_real" arity="0"/>
+ <fsummary>Return a random float.</fsummary>
+ <desc><marker id="uniform_real-0"/>
+ <p>
+ Returns a random float
+ uniformly distributed in the value range
+ <c>DBL_MIN =&lt; <anno>X</anno> &lt; 1.0</c>
+ and updates the state in the process dictionary.
+ </p>
+ <p>
+ Conceptually, a random real number <c>R</c> is generated
+ from the interval <c>0 =&lt; R &lt; 1</c> and then the
+ closest rounded down normalized number
+ in the IEEE 754 Double precision format
+ is returned.
+ </p>
+ <note>
+ <p>
+ The generated numbers from this function has got better
+ granularity for small numbers than the regular
+ <seealso marker="#uniform-0"><c>uniform/0</c></seealso>
+ because all bits in the mantissa are random.
+ This property, in combination with the fact that exactly zero
+ is never returned is useful for algoritms doing for example
+ <c>1.0 / <anno>X</anno></c> or <c>math:log(<anno>X</anno>)</c>.
+ </p>
+ </note>
+ <p>
+ See
+ <seealso marker="#uniform_real_s-1"><c>uniform_real_s/1</c></seealso>
+ for more explanation.
+ </p>
</desc>
</func>
@@ -414,9 +491,97 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
<name name="uniform_s" arity="1"/>
<fsummary>Return a random float.</fsummary>
<desc>
- <p>Returns, for a specified state, random float
+ <p>
+ Returns, for a specified state, random float
uniformly distributed in the value range <c>0.0 =&lt;
- <anno>X</anno> &lt; 1.0</c> and a new state.</p>
+ <anno>X</anno> &lt; 1.0</c> and a new state.
+ </p>
+ <p>
+ The generated numbers are on the form N * 2.0^(-53),
+ that is; equally spaced in the interval.
+ </p>
+ <warning>
+ <p>
+ This function may return exactly <c>0.0</c> which can be
+ fatal for certain applications. If that is undesired
+ you can use <c>(1.0 - rand:uniform(State))</c> to get the
+ interval <c>0.0 &lt; <anno>X</anno> =&lt; 1.0</c>, or instead use
+ <seealso marker="#uniform_real_s-1"><c>uniform_real_s/1</c></seealso>.
+ </p>
+ <p>
+ If neither endpoint is desired you can test and re-try
+ like this:
+ </p>
+ <pre>
+my_uniform(State) ->
+ case rand:uniform(State) of
+ {0.0, NewState} -> my_uniform(NewState);
+ Result -> Result
+ end
+end.</pre>
+ </warning>
+ </desc>
+ </func>
+
+ <func>
+ <name name="uniform_real_s" arity="1"/>
+ <fsummary>Return a random float.</fsummary>
+ <desc>
+ <p>
+ Returns, for a specified state, a random float
+ uniformly distributed in the value range
+ <c>DBL_MIN =&lt; <anno>X</anno> &lt; 1.0</c>
+ and updates the state in the process dictionary.
+ </p>
+ <p>
+ Conceptually, a random real number <c>R</c> is generated
+ from the interval <c>0 =&lt; R &lt; 1</c> and then the
+ closest rounded down normalized number
+ in the IEEE 754 Double precision format
+ is returned.
+ </p>
+ <note>
+ <p>
+ The generated numbers from this function has got better
+ granularity for small numbers than the regular
+ <seealso marker="#uniform_s-1"><c>uniform_s/1</c></seealso>
+ because all bits in the mantissa are random.
+ This property, in combination with the fact that exactly zero
+ is never returned is useful for algoritms doing for example
+ <c>1.0 / <anno>X</anno></c> or <c>math:log(<anno>X</anno>)</c>.
+ </p>
+ </note>
+ <p>
+ The concept implicates that the probability to get
+ exactly zero is extremely low; so low that this function
+ is in fact guaranteed to never return zero. The smallest
+ number that it might return is <c>DBL_MIN</c>, which is
+ 2.0^(-1022).
+ </p>
+ <p>
+ The value range stated at the top of this function
+ description is technically correct, but
+ <c>0.0 =&lt; <anno>X</anno> &lt; 1.0</c>
+ is a better description of the generated numbers'
+ statistical distribution. Except that exactly 0.0
+ is never returned, which is not possible to observe
+ statistically.
+ </p>
+ <p>
+ For example; for all sub ranges
+ <c>N*2.0^(-53) =&lt; X &lt; (N+1)*2.0^(-53)</c>
+ where
+ <c>0 =&lt; integer(N) &lt; 2.0^53</c>
+ the probability is the same.
+ Compare that with the form of the numbers generated by
+ <seealso marker="#uniform_s-1"><c>uniform_s/1</c></seealso>.
+ </p>
+ <p>
+ Having to generate extra random bits for
+ small numbers costs a little performance.
+ This function is about 20% slower than the regular
+ <seealso marker="#uniform_s-1"><c>uniform_s/1</c></seealso>
+ </p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/ref_man.xml b/lib/stdlib/doc/src/ref_man.xml
index 878a3babc5..8d61833d1f 100644
--- a/lib/stdlib/doc/src/ref_man.xml
+++ b/lib/stdlib/doc/src/ref_man.xml
@@ -4,7 +4,7 @@
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -66,7 +66,6 @@
<xi:include href="gen_statem.xml"/>
<xi:include href="io.xml"/>
<xi:include href="io_lib.xml"/>
- <xi:include href="lib.xml"/>
<xi:include href="lists.xml"/>
<xi:include href="log_mf_h.xml"/>
<xi:include href="maps.xml"/>
@@ -93,6 +92,7 @@
<xi:include href="sys.xml"/>
<xi:include href="timer.xml"/>
<xi:include href="unicode.xml"/>
+ <xi:include href="uri_string.xml"/>
<xi:include href="win32reg.xml"/>
<xi:include href="zip.xml"/>
</application>
diff --git a/lib/stdlib/doc/src/sets.xml b/lib/stdlib/doc/src/sets.xml
index 4934bed365..8db3e1e623 100644
--- a/lib/stdlib/doc/src/sets.xml
+++ b/lib/stdlib/doc/src/sets.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2017</year>
+ <year>2000</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -140,6 +140,15 @@
</func>
<func>
+ <name name="is_empty" arity="1"/>
+ <fsummary>Test for empty set.</fsummary>
+ <desc>
+ <p>Returns <c>true</c> if <c><anno>Set</anno></c> is an empty set,
+ otherwise <c>false</c>.</p>
+ </desc>
+ </func>
+
+ <func>
<name name="is_set" arity="1"/>
<fsummary>Test for a <c>Set</c>.</fsummary>
<desc>
diff --git a/lib/stdlib/doc/src/specs.xml b/lib/stdlib/doc/src/specs.xml
index 45b207b13d..fd2d625685 100644
--- a/lib/stdlib/doc/src/specs.xml
+++ b/lib/stdlib/doc/src/specs.xml
@@ -33,7 +33,6 @@
<xi:include href="../specs/specs_gen_statem.xml"/>
<xi:include href="../specs/specs_io.xml"/>
<xi:include href="../specs/specs_io_lib.xml"/>
- <xi:include href="../specs/specs_lib.xml"/>
<xi:include href="../specs/specs_lists.xml"/>
<xi:include href="../specs/specs_log_mf_h.xml"/>
<xi:include href="../specs/specs_maps.xml"/>
@@ -60,6 +59,7 @@
<xi:include href="../specs/specs_sys.xml"/>
<xi:include href="../specs/specs_timer.xml"/>
<xi:include href="../specs/specs_unicode.xml"/>
+ <xi:include href="../specs/specs_uri_string.xml"/>
<xi:include href="../specs/specs_win32reg.xml"/>
<xi:include href="../specs/specs_zip.xml"/>
</specs>
diff --git a/lib/stdlib/doc/src/string.xml b/lib/stdlib/doc/src/string.xml
index 9d5edd9ecf..3348464eba 100644
--- a/lib/stdlib/doc/src/string.xml
+++ b/lib/stdlib/doc/src/string.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -111,8 +111,8 @@
<c>unicode:chardata()</c></seealso> and operate on grapheme
clusters. The <seealso marker="#oldapi"> <c>old
functions</c></seealso> that only work on Latin-1 lists as input
- are still available but should not be
- used. They will be deprecated in Erlang/OTP 21.
+ are still available but should not be used, they will be
+ deprecated in a future release.
</p>
</description>
@@ -594,7 +594,7 @@ ÖÄÅ</pre>
or <c>both</c>, indicates from which direction characters
are to be removed.
</p>
- <p> Default <c><anno>Characters</anno></c> are the set of
+ <p> Default <c><anno>Characters</anno></c> is the set of
nonbreakable whitespace codepoints, defined as
Pattern_White_Space in
<url href="http://unicode.org/reports/tr31/">Unicode Standard Annex #31</url>.
@@ -641,7 +641,7 @@ ÖÄÅ</pre>
<note><p>
The functions are kept for backward compatibility, but are
not recommended.
- They will be deprecated in Erlang/OTP 21.
+ They will be deprecated in a future release.
</p>
<p>Any undocumented functions in <c>string</c> are not to be used.</p>
</note>
diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml
index 6d5065ca02..5fd5760499 100644
--- a/lib/stdlib/doc/src/supervisor.xml
+++ b/lib/stdlib/doc/src/supervisor.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -208,8 +208,16 @@ child_spec() = #{id => child_id(), % mandatory
the child process is unconditionally terminated using
<c>exit(Child,kill)</c>.</p>
<p>If the child process is another supervisor, the shutdown time
- is to be set to <c>infinity</c> to give the subtree ample
- time to shut down. It is also allowed to set it to <c>infinity</c>,
+ must be set to <c>infinity</c> to give the subtree ample
+ time to shut down.</p>
+ <warning>
+ <p>Setting the shutdown time to anything other
+ than <c>infinity</c> for a child of type <c>supervisor</c>
+ can cause a race condition where the child in question
+ unlinks its own children, but fails to terminate them
+ before it is killed.</p>
+ </warning>
+ <p>It is also allowed to set it to <c>infinity</c>,
if the child process is a worker.</p>
<warning>
<p>Be careful when setting the shutdown time to
diff --git a/lib/stdlib/doc/src/sys.xml b/lib/stdlib/doc/src/sys.xml
index 64d8789016..9fe816e33a 100644
--- a/lib/stdlib/doc/src/sys.xml
+++ b/lib/stdlib/doc/src/sys.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -102,7 +102,7 @@
then treated in the debug function. For example, <c>trace</c>
formats the system events to the terminal.
</p>
- <p>Three predefined system events are used when a
+ <p>Four predefined system events are used when a
process receives or sends a message. The process can also define its
own system events. It is always up to the process itself
to format these events.</p>
@@ -276,7 +276,9 @@
<p><c><anno>Func</anno></c> is called whenever a system event is
generated. This function is to return <c>done</c>, or a new
<c>Func</c> state. In the first case, the function is removed. It is
- also removed if the function fails.</p>
+ also removed if the function fails. If one debug function should be
+ installed more times, a unique <c><anno>FuncId</anno></c> must be
+ specified for each installation.</p>
</desc>
</func>
@@ -330,8 +332,8 @@
<fsummary>Remove a debug function from the process.</fsummary>
<desc>
<p>Removes an installed debug function from the
- process. <c><anno>Func</anno></c> must be the same as previously
- installed.</p>
+ process. <c><anno>Func</anno></c> or <c><anno>FuncId</anno></c> must be
+ the same as previously installed.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/timer.xml b/lib/stdlib/doc/src/timer.xml
index fcaccdb2cb..e913e33589 100644
--- a/lib/stdlib/doc/src/timer.xml
+++ b/lib/stdlib/doc/src/timer.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -270,8 +270,8 @@
<item>
<p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>,
<anno>Arguments</anno>)</c> and measures the elapsed real time as
- reported by <seealso marker="os:timestamp/0">
- <c>os:timestamp/0</c></seealso>.</p>
+ reported by <seealso marker="erts:erlang#monotonic_time/0">
+ <c>erlang:monotonic_time/0</c></seealso>.</p>
<p>Returns <c>{<anno>Time</anno>, <anno>Value</anno>}</c>, where
<c><anno>Time</anno></c> is the elapsed real time in
<em>microseconds</em>, and <c><anno>Value</anno></c> is what is
diff --git a/lib/stdlib/doc/src/unicode.xml b/lib/stdlib/doc/src/unicode.xml
index e86f45431f..d822aca89c 100644
--- a/lib/stdlib/doc/src/unicode.xml
+++ b/lib/stdlib/doc/src/unicode.xml
@@ -239,8 +239,13 @@
<c><anno>InEncoding</anno></c>.</p>
</item>
</list>
- <p>Only when <c><anno>InEncoding</anno></c> is one of the UTF
- encodings, integers in the list are allowed to be &gt; 255.</p>
+ <p>
+ Note that integers in the list always represent code points
+ regardless of <c><anno>InEncoding</anno></c> passed. If
+ <c><anno>InEncoding</anno> latin1</c> is passed, only code
+ points &lt; 256 are allowed; otherwise, all valid unicode code
+ points are allowed.
+ </p>
<p>If <c><anno>InEncoding</anno></c> is <c>latin1</c>, parameter
<c><anno>Data</anno></c> corresponds to the <c>iodata()</c> type,
but for <c>unicode</c>, parameter <c><anno>Data</anno></c> can
diff --git a/lib/stdlib/doc/src/unicode_usage.xml b/lib/stdlib/doc/src/unicode_usage.xml
index 26dc46719e..789e063c12 100644
--- a/lib/stdlib/doc/src/unicode_usage.xml
+++ b/lib/stdlib/doc/src/unicode_usage.xml
@@ -719,8 +719,8 @@ Eshell V5.10.1 (abort with ^G)
</section>
<section>
- <title>Unicode Filenames</title>
<marker id="unicode_file_names"/>
+ <title>Unicode Filenames</title>
<p>Most modern operating systems support Unicode filenames in some way.
There are many different ways to do this and Erlang by default treats the
different approaches differently:</p>
@@ -855,8 +855,12 @@ Eshell V5.10.1 (abort with ^G)
</note>
<section>
- <title>Notes About Raw Filenames</title>
<marker id="notes-about-raw-filenames"/>
+ <title>Notes About Raw Filenames</title>
+ <note><p>
+ Note that raw filenames <em>not</em> necessarily are encoded the
+ same way as on the OS level.
+ </p></note>
<p>Raw filenames were introduced together with Unicode filename support
in ERTS 5.8.2 (Erlang/OTP R14B01). The reason &quot;raw
filenames&quot; were introduced in the system was
diff --git a/lib/stdlib/doc/src/uri_string.xml b/lib/stdlib/doc/src/uri_string.xml
new file mode 100644
index 0000000000..88d4600611
--- /dev/null
+++ b/lib/stdlib/doc/src/uri_string.xml
@@ -0,0 +1,359 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2017</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ </legalnotice>
+
+ <title>uri_string</title>
+ <prepared>Péter Dimitrov</prepared>
+ <docno>1</docno>
+ <date>2018-02-07</date>
+ <rev>A</rev>
+ </header>
+ <module>uri_string</module>
+ <modulesummary>URI processing functions.</modulesummary>
+ <description>
+ <p>This module contains functions for parsing and handling URIs
+ (<url href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986</url>) and
+ form-urlencoded query strings (<url href="https://www.w3.org/TR/html52/">HTML 5.2</url>).
+ </p>
+ <p>
+ Parsing and serializing non-UTF-8 form-urlencoded query strings are also supported
+ (<url href="https://www.w3.org/TR/html50/">HTML 5.0</url>).
+ </p>
+ <p>A URI is an identifier consisting of a sequence of characters matching the syntax
+ rule named <em>URI</em> in <url href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986</url>.
+ </p>
+ <p> The generic URI syntax consists of a hierarchical sequence of components referred
+ to as the scheme, authority, path, query, and fragment:</p>
+ <pre>
+ URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+ hier-part = "//" authority path-abempty
+ / path-absolute
+ / path-rootless
+ / path-empty
+ scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+ authority = [ userinfo "@" ] host [ ":" port ]
+ userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
+
+ reserved = gen-delims / sub-delims
+ gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+ sub-delims = "!" / "$" / "&amp;" / "'" / "(" / ")"
+ / "*" / "+" / "," / ";" / "="
+
+ unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ </pre><br></br>
+ <p>The interpretation of a URI depends only on the characters used and not on how those
+ characters are represented in a network protocol.</p>
+ <p>The functions implemented by this module cover the following use cases:</p>
+ <list type="bulleted">
+ <item>Parsing URIs into its components and returing a map<br></br>
+ <seealso marker="#parse/1"><c>parse/1</c></seealso>
+ </item>
+ <item>Recomposing a map of URI components into a URI string<br></br>
+ <seealso marker="#recompose/1"><c>recompose/1</c></seealso>
+ </item>
+ <item>Changing inbound binary and percent-encoding of URIs<br></br>
+ <seealso marker="#transcode/2"><c>transcode/2</c></seealso>
+ </item>
+ <item>Transforming URIs into a normalized form<br></br>
+ <seealso marker="#normalize/1"><c>normalize/1</c></seealso><br></br>
+ <seealso marker="#normalize/2"><c>normalize/2</c></seealso>
+ </item>
+ <item>Composing form-urlencoded query strings from a list of key-value pairs<br></br>
+ <seealso marker="#compose_query/1"><c>compose_query/1</c></seealso><br></br>
+ <seealso marker="#compose_query/2"><c>compose_query/2</c></seealso>
+ </item>
+ <item>Dissecting form-urlencoded query strings into a list of key-value pairs<br></br>
+ <seealso marker="#dissect_query/1"><c>dissect_query/1</c></seealso>
+ </item>
+ </list>
+ <p>There are four different encodings present during the handling of URIs:</p>
+ <list type="bulleted">
+ <item>Inbound binary encoding in binaries</item>
+ <item>Inbound percent-encoding in lists and binaries</item>
+ <item>Outbound binary encoding in binaries</item>
+ <item>Outbound percent-encoding in lists and binaries</item>
+ </list>
+ <p>Functions with <c>uri_string()</c> argument accept lists, binaries and
+ mixed lists (lists with binary elements) as input type. All of the functions but
+ <c>transcode/2</c> expects input as lists of unicode codepoints, UTF-8 encoded binaries
+ and UTF-8 percent-encoded URI parts ("%C3%B6" corresponds to the unicode character "ö").</p>
+ <p>Unless otherwise specified the return value type and encoding are the same as the input
+ type and encoding. That is, binary input returns binary output, list input returns a list
+ output but mixed input returns list output.</p>
+ <p>In case of lists there is only percent-encoding. In binaries, however, both binary encoding
+ and percent-encoding shall be considered. <c>transcode/2</c> provides the means to convert
+ between the supported encodings, it takes a <c>uri_string()</c> and a list of options
+ specifying inbound and outbound encodings.</p>
+ <p><url href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986</url> does not mandate any specific
+ character encoding and it is usually defined by the protocol or surrounding text. This library
+ takes the same assumption, binary and percent-encoding are handled as one configuration unit,
+ they cannot be set to different values.</p>
+ </description>
+
+ <datatypes>
+ <datatype>
+ <name name="error"/>
+ <desc>
+ <p>Error tuple indicating the type of error. Possible values of the second component:</p>
+ <list type="bulleted">
+ <item><c>invalid_character</c></item>
+ <item><c>invalid_encoding</c></item>
+ <item><c>invalid_input</c></item>
+ <item><c>invalid_map</c></item>
+ <item><c>invalid_percent_encoding</c></item>
+ <item><c>invalid_scheme</c></item>
+ <item><c>invalid_uri</c></item>
+ <item><c>invalid_utf8</c></item>
+ <item><c>missing_value</c></item>
+ </list>
+ <p>The third component is a term providing additional information about the
+ cause of the error.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="uri_map"/>
+ <desc>
+ <p>Map holding the main components of a URI.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="uri_string"/>
+ <desc>
+ <p>List of unicode codepoints, a UTF-8 encoded binary, or a mix of the two,
+ representing an <url href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986</url>
+ compliant URI (<em>percent-encoded form</em>).
+ A URI is a sequence of characters from a very limited set: the letters of
+ the basic Latin alphabet, digits, and a few special characters.</p>
+ </desc>
+ </datatype>
+ </datatypes>
+
+ <funcs>
+
+ <func>
+ <name name="compose_query" arity="1"/>
+ <fsummary>Compose urlencoded query string.</fsummary>
+ <desc>
+ <p>Composes a form-urlencoded <c><anno>QueryString</anno></c> based on a
+ <c><anno>QueryList</anno></c>, a list of non-percent-encoded key-value pairs.
+ Form-urlencoding is defined in section
+ 4.10.21.6 of the <url href="https://www.w3.org/TR/html52/">HTML 5.2</url>
+ specification and in section 4.10.22.6 of the
+ <url href="https://www.w3.org/TR/html50/">HTML 5.0</url> specification for
+ non-UTF-8 encodings.
+ </p>
+ <p>See also the opposite operation <seealso marker="#dissect_query/1">
+ <c>dissect_query/1</c></seealso>.
+ </p>
+ <p><em>Example:</em></p>
+ <pre>
+1> <input>uri_string:compose_query([{"foo bar","1"},{"city","örebro"}]).</input>
+<![CDATA["foo+bar=1&city=%C3%B6rebro"]]>
+2> <![CDATA[uri_string:compose_query([{<<"foo bar">>,<<"1">>},
+2> {<<"city">>,<<"örebro"/utf8>>}]).]]>
+<![CDATA[<<"foo+bar=1&city=%C3%B6rebro">>]]>
+ </pre>
+ </desc>
+ </func>
+
+ <func>
+ <name name="compose_query" arity="2"/>
+ <fsummary>Compose urlencoded query string.</fsummary>
+ <desc>
+ <p>Same as <c>compose_query/1</c> but with an additional
+ <c><anno>Options</anno></c> parameter, that controls the encoding ("charset")
+ used by the encoding algorithm. There are two supported encodings: <c>utf8</c>
+ (or <c>unicode</c>) and <c>latin1</c>.
+ </p>
+ <p>Each character in the entry's name and value that cannot be expressed using
+ the selected character encoding, is replaced by a string consisting of a U+0026
+ AMPERSAND character (<![CDATA[&]]>), a "#" (U+0023) character, one or more ASCII
+ digits representing the Unicode code point of the character in base ten, and
+ finally a ";" (U+003B) character.
+ </p>
+ <p>Bytes that are out of the range 0x2A, 0x2D, 0x2E, 0x30 to 0x39, 0x41 to 0x5A, 0x5F,
+ 0x61 to 0x7A, are percent-encoded (U+0025 PERCENT SIGN character (%) followed by
+ uppercase ASCII hex digits representing the hexadecimal value of the byte).
+ </p>
+ <p>See also the opposite operation <seealso marker="#dissect_query/1">
+ <c>dissect_query/1</c></seealso>.
+ </p>
+ <p><em>Example:</em></p>
+ <pre>
+1> <input>uri_string:compose_query([{"foo bar","1"},{"city","örebro"}],</input>
+1> [{encoding, latin1}]).
+<![CDATA["foo+bar=1&city=%F6rebro"
+2> uri_string:compose_query([{<<"foo bar">>,<<"1">>},
+2> {<<"city">>,<<"東京"/utf8>>}], [{encoding, latin1}]).]]>
+<![CDATA[<<"foo+bar=1&city=%26%2326481%3B%26%2320140%3B">>]]>
+ </pre>
+ </desc>
+ </func>
+
+ <func>
+ <name name="dissect_query" arity="1"/>
+ <fsummary>Dissect query string.</fsummary>
+ <desc>
+ <p>Dissects an urlencoded <c><anno>QueryString</anno></c> and returns a
+ <c><anno>QueryList</anno></c>, a list of non-percent-encoded key-value pairs.
+ Form-urlencoding is defined in section
+ 4.10.21.6 of the <url href="https://www.w3.org/TR/html52/">HTML 5.2</url>
+ specification and in section 4.10.22.6 of the
+ <url href="https://www.w3.org/TR/html50/">HTML 5.0</url> specification for
+ non-UTF-8 encodings.
+ </p>
+ <p>See also the opposite operation <seealso marker="#compose_query/1">
+ <c>compose_query/1</c></seealso>.
+ </p>
+ <p><em>Example:</em></p>
+ <pre>
+1> <input><![CDATA[uri_string:dissect_query("foo+bar=1&city=%C3%B6rebro").]]></input>
+[{"foo bar","1"},{"city","örebro"}]
+2> <![CDATA[uri_string:dissect_query(<<"foo+bar=1&city=%26%2326481%3B%26%2320140%3B">>).]]>
+<![CDATA[[{<<"foo bar">>,<<"1">>},
+ {<<"city">>,<<230,157,177,228,186,172>>}] ]]>
+ </pre>
+ </desc>
+ </func>
+
+ <func>
+ <name name="normalize" arity="1"/>
+ <fsummary>Syntax-based normalization.</fsummary>
+ <desc>
+ <p>Transforms an <c><anno>URI</anno></c> into a normalized form
+ using Syntax-Based Normalization as defined by
+ <url href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986</url>.</p>
+ <p>This function implements case normalization, percent-encoding
+ normalization, path segment normalization and scheme based normalization
+ for HTTP(S) with basic support for FTP, SSH, SFTP and TFTP.</p>
+ <p><em>Example:</em></p>
+ <pre>
+1> <input>uri_string:normalize("/a/b/c/./../../g").</input>
+"/a/g"
+2> <![CDATA[uri_string:normalize(<<"mid/content=5/../6">>).]]>
+<![CDATA[<<"mid/6">>]]>
+3> uri_string:normalize("http://localhost:80").
+"https://localhost/"
+4> <input>uri_string:normalize(#{scheme => "http",port => 80,path => "/a/b/c/./../../g",</input>
+4> host => "localhost-örebro"}).
+"http://localhost-%C3%B6rebro/a/g"
+ </pre>
+ </desc>
+ </func>
+
+ <func>
+ <name name="normalize" arity="2"/>
+ <fsummary>Syntax-based normalization.</fsummary>
+ <desc>
+ <p>Same as <c>normalize/1</c> but with an additional
+ <c><anno>Options</anno></c> parameter, that controls if the normalized URI
+ shall be returned as an uri_map().
+ There is one supported option: <c>return_map</c>.
+ </p>
+ <p><em>Example:</em></p>
+ <pre>
+1> <input>uri_string:normalize("/a/b/c/./../../g", [return_map]).</input>
+#{path => "/a/g"}
+2> <![CDATA[uri_string:normalize(<<"mid/content=5/../6">>, [return_map]).]]>
+<![CDATA[#{path => <<"mid/6">>}]]>
+3> uri_string:normalize("http://localhost:80", [return_map]).
+#{scheme => "http",path => "/",host => "localhost"}
+4> <input>uri_string:normalize(#{scheme => "http",port => 80,path => "/a/b/c/./../../g",</input>
+4> host => "localhost-örebro"}, [return_map]).
+#{scheme => "http",path => "/a/g",host => "localhost-örebro"}
+ </pre>
+ </desc>
+ </func>
+
+ <func>
+ <name name="parse" arity="1"/>
+ <fsummary>Parse URI into a map.</fsummary>
+ <desc>
+ <p>Parses an <url href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986</url>
+ compliant <c>uri_string()</c> into a <c>uri_map()</c>, that holds the parsed
+ components of the <c>URI</c>.
+ If parsing fails, an error tuple is returned.</p>
+ <p>See also the opposite operation <seealso marker="#recompose/1">
+ <c>recompose/1</c></seealso>.</p>
+ <p><em>Example:</em></p>
+ <pre>
+1> <input>uri_string:parse("foo://[email protected]:8042/over/there?name=ferret#nose").</input>
+#{fragment => "nose",host => "example.com",
+ path => "/over/there",port => 8042,query => "name=ferret",
+ scheme => foo,userinfo => "user"}
+2> <![CDATA[uri_string:parse(<<"foo://[email protected]:8042/over/there?name=ferret">>).]]>
+<![CDATA[#{host => <<"example.com">>,path => <<"/over/there">>,
+ port => 8042,query => <<"name=ferret">>,scheme => <<"foo">>,
+ userinfo => <<"user">>}]]>
+ </pre>
+ </desc>
+ </func>
+
+ <func>
+ <name name="recompose" arity="1"/>
+ <fsummary>Recompose URI.</fsummary>
+ <desc>
+ <p>Creates an <url href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986</url> compliant
+ <c><anno>URIString</anno></c> (percent-encoded), based on the components of
+ <c><anno>URIMap</anno></c>.
+ If the <c><anno>URIMap</anno></c> is invalid, an error tuple is returned.</p>
+ <p>See also the opposite operation <seealso marker="#parse/1">
+ <c>parse/1</c></seealso>.</p>
+ <p><em>Example:</em></p>
+ <pre>
+1> <input>URIMap = #{fragment => "nose", host => "example.com", path => "/over/there",</input>
+1> port => 8042, query => "name=ferret", scheme => "foo", userinfo => "user"}.
+#{fragment => "top",host => "example.com",
+ path => "/over/there",port => 8042,query => "?name=ferret",
+ scheme => foo,userinfo => "user"}
+
+2> <input>uri_string:recompose(URIMap).</input>
+"foo://example.com:8042/over/there?name=ferret#nose"</pre>
+ </desc>
+ </func>
+
+ <func>
+ <name name="transcode" arity="2"/>
+ <fsummary>Transcode URI.</fsummary>
+ <desc>
+ <p>Transcodes an <url href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986</url>
+ compliant <c><anno>URIString</anno></c>,
+ where <c><anno>Options</anno></c> is a list of tagged tuples, specifying the inbound
+ (<c>in_encoding</c>) and outbound (<c>out_encoding</c>) encodings. <c>in_encoding</c>
+ and <c>out_encoding</c> specifies both binary encoding and percent-encoding for the
+ input and output data. Mixed encoding, where binary encoding is not the same as
+ percent-encoding, is not supported.
+ If an argument is invalid, an error tuple is returned.</p>
+ <p><em>Example:</em></p>
+ <pre>
+1> <input><![CDATA[uri_string:transcode(<<"foo%00%00%00%F6bar"/utf32>>,]]></input>
+1> [{in_encoding, utf32},{out_encoding, utf8}]).
+<![CDATA[<<"foo%C3%B6bar"/utf8>>]]>
+2> uri_string:transcode("foo%F6bar", [{in_encoding, latin1},
+2> {out_encoding, utf8}]).
+"foo%C3%B6bar"
+ </pre>
+ </desc>
+ </func>
+
+ </funcs>
+</erlref>
diff --git a/lib/stdlib/doc/src/user_guide.gif b/lib/stdlib/doc/src/user_guide.gif
deleted file mode 100644
index e6275a803d..0000000000
--- a/lib/stdlib/doc/src/user_guide.gif
+++ /dev/null
Binary files differ
diff --git a/lib/stdlib/include/assert.hrl b/lib/stdlib/include/assert.hrl
index 2fbaeba0b2..2ec89e7d8a 100644
--- a/lib/stdlib/include/assert.hrl
+++ b/lib/stdlib/include/assert.hrl
@@ -309,7 +309,7 @@
{unexpected_success, __V}]})
catch
Class:Term -> ok;
- __C:__T ->
+ __C:__T:__S ->
erlang:error({assertException,
[{module, ?MODULE},
{line, ?LINE},
@@ -318,8 +318,7 @@
"{ "++(??Class)++" , "++(??Term)
++" , [...] }"},
{unexpected_exception,
- {__C, __T,
- erlang:get_stacktrace()}}]})
+ {__C, __T, __S}}]})
end
end)())
end).
@@ -338,7 +337,7 @@
{unexpected_success, __V}]})
catch
Class:Term -> ok;
- __C:__T ->
+ __C:__T:__S ->
erlang:error({assertException,
[{module, ?MODULE},
{line, ?LINE},
@@ -348,8 +347,7 @@
"{ "++(??Class)++" , "++(??Term)
++" , [...] }"},
{unexpected_exception,
- {__C, __T,
- erlang:get_stacktrace()}}]})
+ {__C, __T, __S}}]})
end
end)())
end).
@@ -378,7 +376,7 @@
try (Expr) of
_ -> ok
catch
- __C:__T ->
+ __C:__T:__S ->
case __C of
Class ->
case __T of
@@ -391,9 +389,7 @@
"{ "++(??Class)++" , "
++(??Term)++" , [...] }"},
{unexpected_exception,
- {__C, __T,
- erlang:get_stacktrace()
- }}]});
+ {__C, __T, __S}}]});
_ -> ok
end;
_ -> ok
@@ -407,7 +403,7 @@
try (Expr) of
_ -> ok
catch
- __C:__T ->
+ __C:__T:__S ->
case __C of
Class ->
case __T of
@@ -421,9 +417,7 @@
"{ "++(??Class)++" , "
++(??Term)++" , [...] }"},
{unexpected_exception,
- {__C, __T,
- erlang:get_stacktrace()
- }}]});
+ {__C, __T, __S}}]});
_ -> ok
end;
_ -> ok
diff --git a/lib/stdlib/src/Makefile b/lib/stdlib/src/Makefile
index bf836203ec..c95f7637f7 100644
--- a/lib/stdlib/src/Makefile
+++ b/lib/stdlib/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2017. All Rights Reserved.
+# Copyright Ericsson AB 1996-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -62,6 +62,7 @@ MODULES= \
erl_anno \
erl_bits \
erl_compile \
+ erl_error \
erl_eval \
erl_expand_records \
erl_internal \
@@ -91,7 +92,6 @@ MODULES= \
io_lib_format \
io_lib_fread \
io_lib_pretty \
- lib \
lists \
log_mf_h \
maps \
@@ -121,6 +121,7 @@ MODULES= \
timer \
unicode \
unicode_util \
+ uri_string \
win32reg \
zip
@@ -175,6 +176,7 @@ docs:
primary_bootstrap_compiler: \
$(BOOTSTRAP_COMPILER)/ebin/epp.beam \
$(BOOTSTRAP_COMPILER)/ebin/erl_anno.beam \
+ $(BOOTSTRAP_COMPILER)/ebin/erl_error.beam \
$(BOOTSTRAP_COMPILER)/ebin/erl_scan.beam \
$(BOOTSTRAP_COMPILER)/ebin/erl_parse.beam \
$(BOOTSTRAP_COMPILER)/ebin/erl_lint.beam \
@@ -237,6 +239,13 @@ $(EBIN)/erl_tar.beam: ../../kernel/include/file.hrl erl_tar.hrl
$(EBIN)/file_sorter.beam: ../../kernel/include/file.hrl
$(EBIN)/filelib.beam: ../../kernel/include/file.hrl
$(EBIN)/filename.beam: ../../kernel/include/file.hrl
+$(EBIN)/gen_event.beam: ../../kernel/include/logger.hrl
+$(EBIN)/gen_fsm.beam: ../../kernel/include/logger.hrl
+$(EBIN)/gen_server.beam: ../../kernel/include/logger.hrl
+$(EBIN)/gen_statem.beam: ../../kernel/include/logger.hrl
+$(EBIN)/proc_lib.beam: ../../kernel/include/logger.hrl
$(EBIN)/qlc_pt.beam: ../include/ms_transform.hrl
$(EBIN)/shell.beam: ../../kernel/include/file.hrl
+$(EBIN)/supervisor.beam: ../../kernel/include/logger.hrl
+$(EBIN)/supervisor_bridge.beam: ../../kernel/include/logger.hrl
$(EBIN)/zip.beam: ../include/zip.hrl ../../kernel/include/file.hrl
diff --git a/lib/stdlib/src/array.erl b/lib/stdlib/src/array.erl
index 079b761463..939b1fb488 100644
--- a/lib/stdlib/src/array.erl
+++ b/lib/stdlib/src/array.erl
@@ -290,7 +290,7 @@ new(Size, Fixed, Default) ->
end,
#array{size = Size, max = M, default = Default, elements = E}.
--spec find_max(integer(), integer()) -> integer().
+-spec find_max(integer(), non_neg_integer()) -> non_neg_integer().
find_max(I, M) when I >= M ->
find_max(I, ?extend(M));
@@ -1603,7 +1603,7 @@ foldl_2(I, E, A, Ix, F, D, N, R, S) ->
Ix + S, F, D, N, R, S).
-spec foldl_3(pos_integer(), _, A, array_indx(),
- fun((array_indx, _, A) -> B), integer()) -> B.
+ fun((array_indx(), _, A) -> B), integer()) -> B.
foldl_3(I, E, A, Ix, F, N) when I =< N ->
foldl_3(I+1, E, F(Ix, element(I, E), A), Ix+1, F, N);
diff --git a/lib/stdlib/src/base64.erl b/lib/stdlib/src/base64.erl
index 5885745fb1..6ea4147abf 100644
--- a/lib/stdlib/src/base64.erl
+++ b/lib/stdlib/src/base64.erl
@@ -24,22 +24,11 @@
-export([encode/1, decode/1, mime_decode/1,
encode_to_string/1, decode_to_string/1, mime_decode_to_string/1]).
-%%-------------------------------------------------------------------------
%% The following type is a subtype of string() for return values
%% of (some) functions of this module.
-%%-------------------------------------------------------------------------
-
-type ascii_string() :: [1..255].
-type ascii_binary() :: binary().
-%%-------------------------------------------------------------------------
-%% encode_to_string(ASCII) -> Base64String
-%% ASCII - string() | binary()
-%% Base64String - string()
-%%
-%% Description: Encodes a plain ASCII string (or binary) into base64.
-%%-------------------------------------------------------------------------
-
-spec encode_to_string(Data) -> Base64String when
Data :: ascii_string() | ascii_binary(),
Base64String :: ascii_string().
@@ -47,107 +36,89 @@
encode_to_string(Bin) when is_binary(Bin) ->
encode_to_string(binary_to_list(Bin));
encode_to_string(List) when is_list(List) ->
- encode_l(List).
-
-%%-------------------------------------------------------------------------
-%% encode(ASCII) -> Base64
-%% ASCII - string() | binary()
-%% Base64 - binary()
-%%
-%% Description: Encodes a plain ASCII string (or binary) into base64.
-%%-------------------------------------------------------------------------
+ encode_list_to_string(List).
-spec encode(Data) -> Base64 when
Data :: ascii_string() | ascii_binary(),
Base64 :: ascii_binary().
encode(Bin) when is_binary(Bin) ->
- encode_binary(Bin);
+ encode_binary(Bin, <<>>);
encode(List) when is_list(List) ->
- list_to_binary(encode_l(List)).
+ encode_list(List, <<>>).
--spec encode_l(ascii_string()) -> ascii_string().
-
-encode_l([]) ->
+encode_list_to_string([]) ->
[];
-encode_l([A]) ->
- [b64e(A bsr 2),
- b64e((A band 3) bsl 4), $=, $=];
-encode_l([A,B]) ->
- [b64e(A bsr 2),
- b64e(((A band 3) bsl 4) bor (B bsr 4)),
- b64e((B band 15) bsl 2), $=];
-encode_l([A,B,C|Ls]) ->
- BB = (A bsl 16) bor (B bsl 8) bor C,
+encode_list_to_string([B1]) ->
+ [b64e(B1 bsr 2),
+ b64e((B1 band 3) bsl 4), $=, $=];
+encode_list_to_string([B1,B2]) ->
+ [b64e(B1 bsr 2),
+ b64e(((B1 band 3) bsl 4) bor (B2 bsr 4)),
+ b64e((B2 band 15) bsl 2), $=];
+encode_list_to_string([B1,B2,B3|Ls]) ->
+ BB = (B1 bsl 16) bor (B2 bsl 8) bor B3,
[b64e(BB bsr 18),
b64e((BB bsr 12) band 63),
b64e((BB bsr 6) band 63),
- b64e(BB band 63) | encode_l(Ls)].
-
-encode_binary(Bin) ->
- Split = 3*(byte_size(Bin) div 3),
- <<Main0:Split/binary,Rest/binary>> = Bin,
- Main = << <<(b64e(C)):8>> || <<C:6>> <= Main0 >>,
- case Rest of
- <<A:6,B:6,C:4>> ->
- <<Main/binary,(b64e(A)):8,(b64e(B)):8,(b64e(C bsl 2)):8,$=:8>>;
- <<A:6,B:2>> ->
- <<Main/binary,(b64e(A)):8,(b64e(B bsl 4)):8,$=:8,$=:8>>;
- <<>> ->
- Main
- end.
+ b64e(BB band 63) | encode_list_to_string(Ls)].
-%%-------------------------------------------------------------------------
-%% mime_decode(Base64) -> ASCII
-%% decode(Base64) -> ASCII
-%% Base64 - string() | binary()
-%% ASCII - binary()
-%%
-%% Description: Decodes an base64 encoded string to plain ASCII.
-%% mime_decode strips away all characters not Base64 before converting,
-%% whereas decode crashes if an illegal character is found
-%%-------------------------------------------------------------------------
+encode_binary(<<>>, A) ->
+ A;
+encode_binary(<<B1:8>>, A) ->
+ <<A/bits,(b64e(B1 bsr 2)):8,(b64e((B1 band 3) bsl 4)):8,$=:8,$=:8>>;
+encode_binary(<<B1:8, B2:8>>, A) ->
+ <<A/bits,(b64e(B1 bsr 2)):8,
+ (b64e(((B1 band 3) bsl 4) bor (B2 bsr 4))):8,
+ (b64e((B2 band 15) bsl 2)):8, $=:8>>;
+encode_binary(<<B1:8, B2:8, B3:8, Ls/bits>>, A) ->
+ BB = (B1 bsl 16) bor (B2 bsl 8) bor B3,
+ encode_binary(Ls,
+ <<A/bits,(b64e(BB bsr 18)):8,
+ (b64e((BB bsr 12) band 63)):8,
+ (b64e((BB bsr 6) band 63)):8,
+ (b64e(BB band 63)):8>>).
+
+encode_list([], A) ->
+ A;
+encode_list([B1], A) ->
+ <<A/bits,(b64e(B1 bsr 2)):8,(b64e((B1 band 3) bsl 4)):8,$=:8,$=:8>>;
+encode_list([B1,B2], A) ->
+ <<A/bits,(b64e(B1 bsr 2)):8,
+ (b64e(((B1 band 3) bsl 4) bor (B2 bsr 4))):8,
+ (b64e((B2 band 15) bsl 2)):8, $=:8>>;
+encode_list([B1,B2,B3|Ls], A) ->
+ BB = (B1 bsl 16) bor (B2 bsl 8) bor B3,
+ encode_list(Ls,
+ <<A/bits,(b64e(BB bsr 18)):8,
+ (b64e((BB bsr 12) band 63)):8,
+ (b64e((BB bsr 6) band 63)):8,
+ (b64e(BB band 63)):8>>).
+
+%% mime_decode strips away all characters not Base64 before
+%% converting, whereas decode crashes if an illegal character is found
-spec decode(Base64) -> Data when
Base64 :: ascii_string() | ascii_binary(),
Data :: ascii_binary().
decode(Bin) when is_binary(Bin) ->
- decode_binary(<<>>, Bin);
+ decode_binary(Bin, <<>>);
decode(List) when is_list(List) ->
- list_to_binary(decode_l(List)).
+ decode_list(List, <<>>).
-spec mime_decode(Base64) -> Data when
Base64 :: ascii_string() | ascii_binary(),
Data :: ascii_binary().
mime_decode(Bin) when is_binary(Bin) ->
- mime_decode_binary(<<>>, Bin);
+ mime_decode_binary(Bin, <<>>);
mime_decode(List) when is_list(List) ->
- mime_decode(list_to_binary(List)).
-
--spec decode_l(ascii_string()) -> ascii_string().
-
-decode_l(List) ->
- L = strip_spaces(List, []),
- decode(L, []).
-
--spec mime_decode_l(ascii_string()) -> ascii_string().
+ mime_decode_list(List, <<>>).
-mime_decode_l(List) ->
- L = strip_illegal(List, [], 0),
- decode(L, []).
-
-%%-------------------------------------------------------------------------
-%% mime_decode_to_string(Base64) -> ASCII
-%% decode_to_string(Base64) -> ASCII
-%% Base64 - string() | binary()
-%% ASCII - binary()
-%%
-%% Description: Decodes an base64 encoded string to plain ASCII.
-%% mime_decode strips away all characters not Base64 before converting,
-%% whereas decode crashes if an illegal character is found
-%%-------------------------------------------------------------------------
+%% mime_decode_to_string strips away all characters not Base64 before
+%% converting, whereas decode_to_string crashes if an illegal
+%% character is found
-spec decode_to_string(Base64) -> DataString when
Base64 :: ascii_string() | ascii_binary(),
@@ -156,7 +127,7 @@ mime_decode_l(List) ->
decode_to_string(Bin) when is_binary(Bin) ->
decode_to_string(binary_to_list(Bin));
decode_to_string(List) when is_list(List) ->
- decode_l(List).
+ decode_list_to_string(List).
-spec mime_decode_to_string(Base64) -> DataString when
Base64 :: ascii_string() | ascii_binary(),
@@ -165,202 +136,326 @@ decode_to_string(List) when is_list(List) ->
mime_decode_to_string(Bin) when is_binary(Bin) ->
mime_decode_to_string(binary_to_list(Bin));
mime_decode_to_string(List) when is_list(List) ->
- mime_decode_l(List).
-
-%% One-based decode map.
--define(DECODE_MAP,
- {bad,bad,bad,bad,bad,bad,bad,bad,ws,ws,bad,bad,ws,bad,bad, %1-15
- bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, %16-31
- ws,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,62,bad,bad,bad,63, %32-47
- 52,53,54,55,56,57,58,59,60,61,bad,bad,bad,eq,bad,bad, %48-63
- bad,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
- 15,16,17,18,19,20,21,22,23,24,25,bad,bad,bad,bad,bad,
- bad,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
- 41,42,43,44,45,46,47,48,49,50,51,bad,bad,bad,bad,bad,
- bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
- bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
- bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
- bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
- bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
- bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
- bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
- bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad}).
-
-decode_binary(Result0, <<C:8,T0/bits>>) ->
- case element(C, ?DECODE_MAP) of
- bad ->
- erlang:error({badarg,C});
- ws ->
- decode_binary(Result0, T0);
- eq ->
- case strip_ws(T0) of
- <<$=:8,T/binary>> ->
- <<>> = strip_ws(T),
- Split = byte_size(Result0) - 1,
- <<Result:Split/bytes,_:4>> = Result0,
- Result;
- T ->
- <<>> = strip_ws(T),
- Split = byte_size(Result0) - 1,
- <<Result:Split/bytes,_:2>> = Result0,
- Result
- end;
- Bits ->
- decode_binary(<<Result0/bits,Bits:6>>, T0)
- end;
-decode_binary(Result, <<>>) ->
- true = is_binary(Result),
- Result.
+ mime_decode_list_to_string(List).
%% Skipping pad character if not at end of string. Also liberal about
%% excess padding and skipping of other illegal (non-base64 alphabet)
%% characters. See section 3.3 of RFC4648
-mime_decode_binary(Result, <<0:8,T/bits>>) ->
- mime_decode_binary(Result, T);
-mime_decode_binary(Result0, <<C:8,T/bits>>) ->
- case element(C, ?DECODE_MAP) of
- Bits when is_integer(Bits) ->
- mime_decode_binary(<<Result0/bits,Bits:6>>, T);
+mime_decode_list([0 | Cs], A) ->
+ mime_decode_list(Cs, A);
+mime_decode_list([C1 | Cs], A) ->
+ case b64d(C1) of
+ B1 when is_integer(B1) -> mime_decode_list(Cs, A, B1);
+ _ -> mime_decode_list(Cs, A) % eq is padding
+ end;
+mime_decode_list([], A) ->
+ A.
+
+mime_decode_list([0 | Cs], A, B1) ->
+ mime_decode_list(Cs, A, B1);
+mime_decode_list([C2 | Cs], A, B1) ->
+ case b64d(C2) of
+ B2 when is_integer(B2) ->
+ mime_decode_list(Cs, A, B1, B2);
+ _ -> mime_decode_list(Cs, A, B1) % eq is padding
+ end.
+
+mime_decode_list([0 | Cs], A, B1, B2) ->
+ mime_decode_list(Cs, A, B1, B2);
+mime_decode_list([C3 | Cs], A, B1, B2) ->
+ case b64d(C3) of
+ B3 when is_integer(B3) ->
+ mime_decode_list(Cs, A, B1, B2, B3);
+ eq=B3 ->
+ mime_decode_list_after_eq(Cs, A, B1, B2, B3);
+ _ -> mime_decode_list(Cs, A, B1, B2)
+ end.
+
+mime_decode_list([0 | Cs], A, B1, B2, B3) ->
+ mime_decode_list(Cs, A, B1, B2, B3);
+mime_decode_list([C4 | Cs], A, B1, B2, B3) ->
+ case b64d(C4) of
+ B4 when is_integer(B4) ->
+ mime_decode_list(Cs, <<A/bits,B1:6,B2:6,B3:6,B4:6>>);
eq ->
- mime_decode_binary_after_eq(Result0, T, false);
- _ ->
- mime_decode_binary(Result0, T)
+ mime_decode_list_after_eq(Cs, A, B1, B2, B3);
+ _ -> mime_decode_list(Cs, A, B1, B2, B3)
+ end.
+
+mime_decode_list_after_eq([0 | Cs], A, B1, B2, B3) ->
+ mime_decode_list_after_eq(Cs, A, B1, B2, B3);
+mime_decode_list_after_eq([C | Cs], A, B1, B2, B3) ->
+ case b64d(C) of
+ B when is_integer(B) ->
+ %% More valid data, skip the eq as invalid
+ case B3 of
+ eq -> mime_decode_list(Cs, A, B1, B2, B);
+ _ -> mime_decode_list(Cs, <<A/bits,B1:6,B2:6,B3:6,B:6>>)
+ end;
+ _ -> mime_decode_list_after_eq(Cs, A, B1, B2, B3)
end;
-mime_decode_binary(Result, _) ->
- true = is_binary(Result),
- Result.
-
-mime_decode_binary_after_eq(Result, <<0:8,T/bits>>, Eq) ->
- mime_decode_binary_after_eq(Result, T, Eq);
-mime_decode_binary_after_eq(Result0, <<C:8,T/bits>>, Eq) ->
- case element(C, ?DECODE_MAP) of
- bad ->
- mime_decode_binary_after_eq(Result0, T, Eq);
- ws ->
- mime_decode_binary_after_eq(Result0, T, Eq);
+mime_decode_list_after_eq([], A, B1, B2, eq) ->
+ <<A/bits,B1:6,(B2 bsr 4):2>>;
+mime_decode_list_after_eq([], A, B1, B2, B3) ->
+ <<A/bits,B1:6,B2:6,(B3 bsr 2):4>>.
+
+mime_decode_binary(<<0:8, Cs/bits>>, A) ->
+ mime_decode_binary(Cs, A);
+mime_decode_binary(<<C1:8, Cs/bits>>, A) ->
+ case b64d(C1) of
+ B1 when is_integer(B1) -> mime_decode_binary(Cs, A, B1);
+ _ -> mime_decode_binary(Cs, A) % eq is padding
+ end;
+mime_decode_binary(<<>>, A) ->
+ A.
+
+mime_decode_binary(<<0:8, Cs/bits>>, A, B1) ->
+ mime_decode_binary(Cs, A, B1);
+mime_decode_binary(<<C2:8, Cs/bits>>, A, B1) ->
+ case b64d(C2) of
+ B2 when is_integer(B2) ->
+ mime_decode_binary(Cs, A, B1, B2);
+ _ -> mime_decode_binary(Cs, A, B1) % eq is padding
+ end.
+
+mime_decode_binary(<<0:8, Cs/bits>>, A, B1, B2) ->
+ mime_decode_binary(Cs, A, B1, B2);
+mime_decode_binary(<<C3:8, Cs/bits>>, A, B1, B2) ->
+ case b64d(C3) of
+ B3 when is_integer(B3) ->
+ mime_decode_binary(Cs, A, B1, B2, B3);
+ eq=B3 ->
+ mime_decode_binary_after_eq(Cs, A, B1, B2, B3);
+ _ -> mime_decode_binary(Cs, A, B1, B2)
+ end.
+
+mime_decode_binary(<<0:8, Cs/bits>>, A, B1, B2, B3) ->
+ mime_decode_binary(Cs, A, B1, B2, B3);
+mime_decode_binary(<<C4:8, Cs/bits>>, A, B1, B2, B3) ->
+ case b64d(C4) of
+ B4 when is_integer(B4) ->
+ mime_decode_binary(Cs, <<A/bits,B1:6,B2:6,B3:6,B4:6>>);
eq ->
- mime_decode_binary_after_eq(Result0, T, true);
- Bits when is_integer(Bits) ->
+ mime_decode_binary_after_eq(Cs, A, B1, B2, B3);
+ _ -> mime_decode_binary(Cs, A, B1, B2, B3)
+ end.
+
+mime_decode_binary_after_eq(<<0:8, Cs/bits>>, A, B1, B2, B3) ->
+ mime_decode_binary_after_eq(Cs, A, B1, B2, B3);
+mime_decode_binary_after_eq(<<C:8, Cs/bits>>, A, B1, B2, B3) ->
+ case b64d(C) of
+ B when is_integer(B) ->
%% More valid data, skip the eq as invalid
- mime_decode_binary(<<Result0/bits,Bits:6>>, T)
+ case B3 of
+ eq -> mime_decode_binary(Cs, A, B1, B2, B);
+ _ -> mime_decode_binary(Cs, <<A/bits,B1:6,B2:6,B3:6,B:6>>)
+ end;
+ _ -> mime_decode_binary_after_eq(Cs, A, B1, B2, B3)
+ end;
+mime_decode_binary_after_eq(<<>>, A, B1, B2, eq) ->
+ <<A/bits,B1:6,(B2 bsr 4):2>>;
+mime_decode_binary_after_eq(<<>>, A, B1, B2, B3) ->
+ <<A/bits,B1:6,B2:6,(B3 bsr 2):4>>.
+
+mime_decode_list_to_string([0 | Cs]) ->
+ mime_decode_list_to_string(Cs);
+mime_decode_list_to_string([C1 | Cs]) ->
+ case b64d(C1) of
+ B1 when is_integer(B1) -> mime_decode_list_to_string(Cs, B1);
+ _ -> mime_decode_list_to_string(Cs) % eq is padding
end;
-mime_decode_binary_after_eq(Result0, <<>>, Eq) ->
- %% No more valid data.
- case bit_size(Result0) rem 8 of
- 0 ->
- %% '====' is not uncommon.
- Result0;
- 4 when Eq ->
- %% enforce at least one more '=' only ignoring illegals and spacing
- Split = byte_size(Result0) - 1,
- <<Result:Split/bytes,_:4>> = Result0,
- Result;
- 2 ->
- %% remove 2 bits
- Split = byte_size(Result0) - 1,
- <<Result:Split/bytes,_:2>> = Result0,
- Result
+mime_decode_list_to_string([]) ->
+ [].
+
+mime_decode_list_to_string([0 | Cs], B1) ->
+ mime_decode_list_to_string(Cs, B1);
+mime_decode_list_to_string([C2 | Cs], B1) ->
+ case b64d(C2) of
+ B2 when is_integer(B2) ->
+ mime_decode_list_to_string(Cs, B1, B2);
+ _ -> mime_decode_list_to_string(Cs, B1) % eq is padding
end.
-decode([], A) -> A;
-decode([$=,$=,C2,C1|Cs], A) ->
- Bits2x6 = (b64d(C1) bsl 18) bor (b64d(C2) bsl 12),
- Octet1 = Bits2x6 bsr 16,
- decode(Cs, [Octet1|A]);
-decode([$=,C3,C2,C1|Cs], A) ->
- Bits3x6 = (b64d(C1) bsl 18) bor (b64d(C2) bsl 12)
- bor (b64d(C3) bsl 6),
- Octet1 = Bits3x6 bsr 16,
- Octet2 = (Bits3x6 bsr 8) band 16#ff,
- decode(Cs, [Octet1,Octet2|A]);
-decode([C4,C3,C2,C1| Cs], A) ->
- Bits4x6 = (b64d(C1) bsl 18) bor (b64d(C2) bsl 12)
- bor (b64d(C3) bsl 6) bor b64d(C4),
- Octet1 = Bits4x6 bsr 16,
- Octet2 = (Bits4x6 bsr 8) band 16#ff,
- Octet3 = Bits4x6 band 16#ff,
- decode(Cs, [Octet1,Octet2,Octet3|A]).
+mime_decode_list_to_string([0 | Cs], B1, B2) ->
+ mime_decode_list_to_string(Cs, B1, B2);
+mime_decode_list_to_string([C3 | Cs], B1, B2) ->
+ case b64d(C3) of
+ B3 when is_integer(B3) ->
+ mime_decode_list_to_string(Cs, B1, B2, B3);
+ eq=B3 -> mime_decode_list_to_string_after_eq(Cs, B1, B2, B3);
+ _ -> mime_decode_list_to_string(Cs, B1, B2)
+ end.
-%%%========================================================================
-%%% Internal functions
-%%%========================================================================
+mime_decode_list_to_string([0 | Cs], B1, B2, B3) ->
+ mime_decode_list_to_string(Cs, B1, B2, B3);
+mime_decode_list_to_string([C4 | Cs], B1, B2, B3) ->
+ case b64d(C4) of
+ B4 when is_integer(B4) ->
+ Bits4x6 = (B1 bsl 18) bor (B2 bsl 12) bor (B3 bsl 6) bor B4,
+ Octet1 = Bits4x6 bsr 16,
+ Octet2 = (Bits4x6 bsr 8) band 16#ff,
+ Octet3 = Bits4x6 band 16#ff,
+ [Octet1, Octet2, Octet3 | mime_decode_list_to_string(Cs)];
+ eq ->
+ mime_decode_list_to_string_after_eq(Cs, B1, B2, B3);
+ _ -> mime_decode_list_to_string(Cs, B1, B2, B3)
+ end.
-strip_spaces([], A) -> A;
-strip_spaces([$\s|Cs], A) -> strip_spaces(Cs, A);
-strip_spaces([$\t|Cs], A) -> strip_spaces(Cs, A);
-strip_spaces([$\r|Cs], A) -> strip_spaces(Cs, A);
-strip_spaces([$\n|Cs], A) -> strip_spaces(Cs, A);
-strip_spaces([C|Cs], A) -> strip_spaces(Cs, [C | A]).
-
-strip_ws(<<$\t,T/binary>>) ->
- strip_ws(T);
-strip_ws(<<$\n,T/binary>>) ->
- strip_ws(T);
-strip_ws(<<$\r,T/binary>>) ->
- strip_ws(T);
-strip_ws(<<$\s,T/binary>>) ->
- strip_ws(T);
-strip_ws(T) -> T.
+mime_decode_list_to_string_after_eq([0 | Cs], B1, B2, B3) ->
+ mime_decode_list_to_string_after_eq(Cs, B1, B2, B3);
+mime_decode_list_to_string_after_eq([C | Cs], B1, B2, B3) ->
+ case b64d(C) of
+ B when is_integer(B) ->
+ %% More valid data, skip the eq as invalid
+ case B3 of
+ eq -> mime_decode_list_to_string(Cs, B1, B2, B);
+ _ ->
+ Bits4x6 = (B1 bsl 18) bor (B2 bsl 12) bor (B3 bsl 6) bor B,
+ Octet1 = Bits4x6 bsr 16,
+ Octet2 = (Bits4x6 bsr 8) band 16#ff,
+ Octet3 = Bits4x6 band 16#ff,
+ [Octet1, Octet2, Octet3 | mime_decode_list_to_string(Cs)]
+ end;
+ _ -> mime_decode_list_to_string_after_eq(Cs, B1, B2, B3)
+ end;
+mime_decode_list_to_string_after_eq([], B1, B2, eq) ->
+ binary_to_list(<<B1:6,(B2 bsr 4):2>>);
+mime_decode_list_to_string_after_eq([], B1, B2, B3) ->
+ binary_to_list(<<B1:6,B2:6,(B3 bsr 2):4>>).
+
+decode_list([C1 | Cs], A) ->
+ case b64d(C1) of
+ ws -> decode_list(Cs, A);
+ B1 -> decode_list(Cs, A, B1)
+ end;
+decode_list([], A) ->
+ A.
-%% Skipping pad character if not at end of string. Also liberal about
-%% excess padding and skipping of other illegal (non-base64 alphabet)
-%% characters. See section 3.3 of RFC4648
-strip_illegal([], A, _Cnt) ->
+decode_list([C2 | Cs], A, B1) ->
+ case b64d(C2) of
+ ws -> decode_list(Cs, A, B1);
+ B2 -> decode_list(Cs, A, B1, B2)
+ end.
+
+decode_list([C3 | Cs], A, B1, B2) ->
+ case b64d(C3) of
+ ws -> decode_list(Cs, A, B1, B2);
+ B3 -> decode_list(Cs, A, B1, B2, B3)
+ end.
+
+decode_list([C4 | Cs], A, B1, B2, B3) ->
+ case b64d(C4) of
+ ws -> decode_list(Cs, A, B1, B2, B3);
+ eq when B3 =:= eq -> only_ws(Cs, <<A/bits,B1:6,(B2 bsr 4):2>>);
+ eq -> only_ws(Cs, <<A/bits,B1:6,B2:6,(B3 bsr 2):4>>);
+ B4 -> decode_list(Cs, <<A/bits,B1:6,B2:6,B3:6,B4:6>>)
+ end.
+
+decode_binary(<<C1:8, Cs/bits>>, A) ->
+ case b64d(C1) of
+ ws -> decode_binary(Cs, A);
+ B1 -> decode_binary(Cs, A, B1)
+ end;
+decode_binary(<<>>, A) ->
+ A.
+
+decode_binary(<<C2:8, Cs/bits>>, A, B1) ->
+ case b64d(C2) of
+ ws -> decode_binary(Cs, A, B1);
+ B2 -> decode_binary(Cs, A, B1, B2)
+ end.
+
+decode_binary(<<C3:8, Cs/bits>>, A, B1, B2) ->
+ case b64d(C3) of
+ ws -> decode_binary(Cs, A, B1, B2);
+ B3 -> decode_binary(Cs, A, B1, B2, B3)
+ end.
+
+decode_binary(<<C4:8, Cs/bits>>, A, B1, B2, B3) ->
+ case b64d(C4) of
+ ws -> decode_binary(Cs, A, B1, B2, B3);
+ eq when B3 =:= eq -> only_ws_binary(Cs, <<A/bits,B1:6,(B2 bsr 4):2>>);
+ eq -> only_ws_binary(Cs, <<A/bits,B1:6,B2:6,(B3 bsr 2):4>>);
+ B4 -> decode_binary(Cs, <<A/bits,B1:6,B2:6,B3:6,B4:6>>)
+ end.
+
+only_ws_binary(<<>>, A) ->
A;
-strip_illegal([0|Cs], A, Cnt) ->
- strip_illegal(Cs, A, Cnt);
-strip_illegal([C|Cs], A, Cnt) ->
- case element(C, ?DECODE_MAP) of
- bad ->
- strip_illegal(Cs, A, Cnt);
- ws ->
- strip_illegal(Cs, A, Cnt);
- eq ->
- case {tail_contains_more(Cs, false), Cnt rem 4} of
- {{[], _}, 0} ->
- A; %% Ignore extra =
- {{[], true}, 2} ->
- [$=|[$=|A]]; %% 'XX=='
- {{[], _}, 3} ->
- [$=|A]; %% 'XXX='
- {{[H|T], _}, _} ->
- %% more data, skip equals
- strip_illegal(T, [H|A], Cnt+1)
- end;
- _ ->
- strip_illegal(Cs, [C|A], Cnt+1)
+only_ws_binary(<<C:8, Cs/bits>>, A) ->
+ case b64d(C) of
+ ws -> only_ws_binary(Cs, A)
end.
-%% Search the tail for more valid data and remember if we saw
-%% another equals along the way.
-tail_contains_more([], Eq) ->
- {[], Eq};
-tail_contains_more(<<>>, Eq) ->
- {<<>>, Eq};
-tail_contains_more([C|T]=More, Eq) ->
- case element(C, ?DECODE_MAP) of
- bad ->
- tail_contains_more(T, Eq);
- ws ->
- tail_contains_more(T, Eq);
- eq ->
- tail_contains_more(T, true);
- _ ->
- {More, Eq}
+decode_list_to_string([C1 | Cs]) ->
+ case b64d(C1) of
+ ws -> decode_list_to_string(Cs);
+ B1 -> decode_list_to_string(Cs, B1)
end;
-tail_contains_more(<<C:8,T/bits>> =More, Eq) ->
- case element(C, ?DECODE_MAP) of
- bad ->
- tail_contains_more(T, Eq);
- ws ->
- tail_contains_more(T, Eq);
- eq ->
- tail_contains_more(T, true);
- _ ->
- {More, Eq}
+decode_list_to_string([]) ->
+ [].
+
+decode_list_to_string([C2 | Cs], B1) ->
+ case b64d(C2) of
+ ws -> decode_list_to_string(Cs, B1);
+ B2 -> decode_list_to_string(Cs, B1, B2)
end.
-
+
+decode_list_to_string([C3 | Cs], B1, B2) ->
+ case b64d(C3) of
+ ws -> decode_list_to_string(Cs, B1, B2);
+ B3 -> decode_list_to_string(Cs, B1, B2, B3)
+ end.
+
+decode_list_to_string([C4 | Cs], B1, B2, B3) ->
+ case b64d(C4) of
+ ws ->
+ decode_list_to_string(Cs, B1, B2, B3);
+ eq when B3 =:= eq ->
+ only_ws(Cs, binary_to_list(<<B1:6,(B2 bsr 4):2>>));
+ eq ->
+ only_ws(Cs, binary_to_list(<<B1:6,B2:6,(B3 bsr 2):4>>));
+ B4 ->
+ Bits4x6 = (B1 bsl 18) bor (B2 bsl 12) bor (B3 bsl 6) bor B4,
+ Octet1 = Bits4x6 bsr 16,
+ Octet2 = (Bits4x6 bsr 8) band 16#ff,
+ Octet3 = Bits4x6 band 16#ff,
+ [Octet1, Octet2, Octet3 | decode_list_to_string(Cs)]
+ end.
+
+only_ws([], A) ->
+ A;
+only_ws([C | Cs], A) ->
+ case b64d(C) of
+ ws -> only_ws(Cs, A)
+ end.
+
+%%%========================================================================
+%%% Internal functions
+%%%========================================================================
+
%% accessors
+-compile({inline, [{b64d, 1}]}).
+%% One-based decode map.
+b64d(X) ->
+ element(X,
+ {bad,bad,bad,bad,bad,bad,bad,bad,ws,ws,bad,bad,ws,bad,bad, %1-15
+ bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, %16-31
+ ws,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,62,bad,bad,bad,63, %32-47
+ 52,53,54,55,56,57,58,59,60,61,bad,bad,bad,eq,bad,bad, %48-63
+ bad,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
+ 15,16,17,18,19,20,21,22,23,24,25,bad,bad,bad,bad,bad,
+ bad,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
+ 41,42,43,44,45,46,47,48,49,50,51,bad,bad,bad,bad,bad,
+ bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
+ bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
+ bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
+ bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
+ bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
+ bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
+ bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
+ bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad}).
+
+-compile({inline, [{b64e, 1}]}).
b64e(X) ->
element(X+1,
{$A, $B, $C, $D, $E, $F, $G, $H, $I, $J, $K, $L, $M, $N,
@@ -368,9 +463,3 @@ b64e(X) ->
$a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n,
$o, $p, $q, $r, $s, $t, $u, $v, $w, $x, $y, $z,
$0, $1, $2, $3, $4, $5, $6, $7, $8, $9, $+, $/}).
-
-
-b64d(X) ->
- b64d_ok(element(X, ?DECODE_MAP)).
-
-b64d_ok(I) when is_integer(I) -> I.
diff --git a/lib/stdlib/src/beam_lib.erl b/lib/stdlib/src/beam_lib.erl
index 06c15fceda..01181b1097 100644
--- a/lib/stdlib/src/beam_lib.erl
+++ b/lib/stdlib/src/beam_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -148,7 +148,8 @@ chunks(File, Chunks, Options) ->
try read_chunk_data(File, Chunks, Options)
catch Error -> Error end.
--spec all_chunks(beam()) -> {'ok', 'beam_lib', [{chunkid(), dataB()}]}.
+-spec all_chunks(beam()) ->
+ {'ok', 'beam_lib', [{chunkid(), dataB()}]} | {'error', 'beam_lib', info_rsn()}.
all_chunks(File) ->
read_all_chunks(File).
@@ -689,30 +690,31 @@ chunk_to_data(debug_info=Id, Chunk, File, _Cs, AtomTable, Mod) ->
<<0:8,N:8,Mode0:N/binary,Rest/binary>> ->
Mode = binary_to_atom(Mode0, utf8),
Term = decrypt_chunk(Mode, Mod, File, Id, Rest),
- {AtomTable, {Id, Term}};
+ {AtomTable, {Id, anno_from_term(Term)}};
_ ->
case catch binary_to_term(Chunk) of
{'EXIT', _} ->
error({invalid_chunk, File, chunk_name_to_id(Id, File)});
Term ->
- {AtomTable, {Id, Term}}
+ {AtomTable, {Id, anno_from_term(Term)}}
end
end;
chunk_to_data(abstract_code=Id, Chunk, File, _Cs, AtomTable, Mod) ->
+ %% Before Erlang/OTP 20.0.
case Chunk of
<<>> ->
{AtomTable, {Id, no_abstract_code}};
<<0:8,N:8,Mode0:N/binary,Rest/binary>> ->
Mode = binary_to_atom(Mode0, utf8),
Term = decrypt_chunk(Mode, Mod, File, Id, Rest),
- {AtomTable, {Id, anno_from_term(Term)}};
+ {AtomTable, {Id, old_anno_from_term(Term)}};
_ ->
case catch binary_to_term(Chunk) of
{'EXIT', _} ->
error({invalid_chunk, File, chunk_name_to_id(Id, File)});
Term ->
try
- {AtomTable, {Id, anno_from_term(Term)}}
+ {AtomTable, {Id, old_anno_from_term(Term)}}
catch
_:_ ->
error({invalid_chunk, File,
@@ -946,14 +948,24 @@ decrypt_chunk(Type, Module, File, Id, Bin) ->
error({key_missing_or_invalid, File, Id})
end.
-anno_from_term({raw_abstract_v1, Forms}) ->
+old_anno_from_term({raw_abstract_v1, Forms}) ->
{raw_abstract_v1, anno_from_forms(Forms)};
-anno_from_term({Tag, Forms}) when Tag =:= abstract_v1; Tag =:= abstract_v2 ->
+old_anno_from_term({Tag, Forms}) when Tag =:= abstract_v1;
+ Tag =:= abstract_v2 ->
try {Tag, anno_from_forms(Forms)}
catch
_:_ ->
{Tag, Forms}
end;
+old_anno_from_term(T) ->
+ T.
+
+anno_from_term({debug_info_v1=Tag1, erl_abstract_code=Tag2, {Forms, Opts}}) ->
+ try {Tag1, Tag2, {anno_from_forms(Forms), Opts}}
+ catch
+ _:_ ->
+ {Tag1, Tag2, {Forms, Opts}}
+ end;
anno_from_term(T) ->
T.
diff --git a/lib/stdlib/src/binary.erl b/lib/stdlib/src/binary.erl
index 6a64133b45..52b9fedc9c 100644
--- a/lib/stdlib/src/binary.erl
+++ b/lib/stdlib/src/binary.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -47,23 +47,39 @@ at(_, _) ->
-spec bin_to_list(Subject) -> [byte()] when
Subject :: binary().
-bin_to_list(_) ->
- erlang:nif_error(undef).
+bin_to_list(Subject) ->
+ binary_to_list(Subject).
-spec bin_to_list(Subject, PosLen) -> [byte()] when
Subject :: binary(),
PosLen :: part().
-bin_to_list(_, _) ->
- erlang:nif_error(undef).
+bin_to_list(Subject, {Pos, Len}) ->
+ bin_to_list(Subject, Pos, Len);
+bin_to_list(_Subject, _BadArg) ->
+ erlang:error(badarg).
-spec bin_to_list(Subject, Pos, Len) -> [byte()] when
Subject :: binary(),
Pos :: non_neg_integer(),
Len :: integer().
-bin_to_list(_, _, _) ->
- erlang:nif_error(undef).
+bin_to_list(Subject, Pos, Len) when not is_binary(Subject);
+ not is_integer(Pos);
+ not is_integer(Len) ->
+ %% binary_to_list/3 allows bitstrings as long as the slice fits, and we
+ %% want to badarg when Pos/Len aren't integers instead of raising badarith
+ %% when adjusting args for binary_to_list/3.
+ erlang:error(badarg);
+bin_to_list(Subject, Pos, 0) when Pos >= 0, Pos =< byte_size(Subject) ->
+ %% binary_to_list/3 doesn't handle this case.
+ [];
+bin_to_list(_Subject, _Pos, 0) ->
+ erlang:error(badarg);
+bin_to_list(Subject, Pos, Len) when Len < 0 ->
+ bin_to_list(Subject, Pos + Len, -Len);
+bin_to_list(Subject, Pos, Len) when Len > 0 ->
+ binary_to_list(Subject, Pos + 1, Pos + Len).
-spec compile_pattern(Pattern) -> cp() when
Pattern :: binary() | [binary()].
diff --git a/lib/stdlib/src/c.erl b/lib/stdlib/src/c.erl
index 4ab9234b81..0362b72536 100644
--- a/lib/stdlib/src/c.erl
+++ b/lib/stdlib/src/c.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -255,7 +255,7 @@ safe_recompile(File, Options, BeamFile) ->
compile_and_load(File, Opts0) when is_list(Opts0) ->
Opts = [report_errors, report_warnings
| ensure_from(filename:extension(File),
- ensure_outdir(filename:dirname(File), Opts0))],
+ ensure_outdir(".", Opts0))],
case compile:file(File, Opts) of
{ok,Mod} -> %Listing file.
purge_and_load(Mod, File, Opts);
@@ -564,7 +564,7 @@ display_info(Pid) ->
Other
end,
Reds = fetch(reductions, Info),
- LM = length(fetch(messages, Info)),
+ LM = fetch(message_queue_len, Info),
HS = fetch(heap_size, Info),
SS = fetch(stack_size, Info),
iformat(w(Pid), mfa_string(Call),
@@ -668,19 +668,23 @@ lm() ->
[l(M) || M <- mm()].
%% erlangrc(Home)
-%% Try to run a ".erlang" file, first in the current directory
-%% else in home directory.
+%% Try to run a ".erlang" file in home directory.
+
+-spec erlangrc() -> {ok, file:filename()} | {error, term()}.
erlangrc() ->
case init:get_argument(home) of
{ok,[[Home]]} ->
erlangrc([Home]);
_ ->
- f_p_e(["."], ".erlang")
+ {error, enoent}
end.
-erlangrc([Home]) ->
- f_p_e([".",Home], ".erlang").
+-spec erlangrc(PathList) -> {ok, file:filename()} | {error, term()}
+ when PathList :: [Dir :: file:name()].
+
+erlangrc([Home|_]=Paths) when is_list(Home) ->
+ f_p_e(Paths, ".erlang").
error(Fmt, Args) ->
error_logger:error_msg(Fmt, Args).
@@ -692,11 +696,11 @@ f_p_e(P, F) ->
{error, E={Line, _Mod, _Term}} ->
error("file:path_eval(~tp,~tp): error on line ~p: ~ts~n",
[P, F, Line, file:format_error(E)]),
- ok;
+ {error, E};
{error, E} ->
error("file:path_eval(~tp,~tp): ~ts~n",
[P, F, file:format_error(E)]),
- ok;
+ {error, E};
Other ->
Other
end.
@@ -882,7 +886,7 @@ portinfo(Id) ->
procline(Name, Info, Pid) ->
Call = initial_call(Info),
Reds = fetch(reductions, Info),
- LM = length(fetch(messages, Info)),
+ LM = fetch(message_queue_len, Info),
procformat(io_lib:format("~tw",[Name]),
io_lib:format("~w",[Pid]),
io_lib:format("~ts",[mfa_string(Call)]),
@@ -1030,8 +1034,8 @@ appcall(App, M, F, Args) ->
try
apply(M, F, Args)
catch
- error:undef ->
- case erlang:get_stacktrace() of
+ error:undef:S ->
+ case S of
[{M,F,Args,_}|_] ->
Arity = length(Args),
io:format("Call to ~w:~w/~w in application ~w failed.\n",
diff --git a/lib/stdlib/src/calendar.erl b/lib/stdlib/src/calendar.erl
index 55a0cfc9a1..9a600c1972 100644
--- a/lib/stdlib/src/calendar.erl
+++ b/lib/stdlib/src/calendar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -39,8 +39,14 @@
now_to_datetime/1, % = now_to_universal_time/1
now_to_local_time/1,
now_to_universal_time/1,
+ rfc3339_to_system_time/1,
+ rfc3339_to_system_time/2,
seconds_to_daystime/1,
seconds_to_time/1,
+ system_time_to_local_time/2,
+ system_time_to_universal_time/2,
+ system_time_to_rfc3339/1,
+ system_time_to_rfc3339/2,
time_difference/2,
time_to_seconds/1,
universal_time/0,
@@ -55,10 +61,13 @@
-define(SECONDS_PER_DAY, 86400).
-define(DAYS_PER_YEAR, 365).
-define(DAYS_PER_LEAP_YEAR, 366).
--define(DAYS_PER_4YEARS, 1461).
--define(DAYS_PER_100YEARS, 36524).
--define(DAYS_PER_400YEARS, 146097).
+%% -define(DAYS_PER_4YEARS, 1461).
+%% -define(DAYS_PER_100YEARS, 36524).
+%% -define(DAYS_PER_400YEARS, 146097).
-define(DAYS_FROM_0_TO_1970, 719528).
+-define(DAYS_FROM_0_TO_10000, 2932897).
+-define(SECONDS_FROM_0_TO_1970, (?DAYS_FROM_0_TO_1970*?SECONDS_PER_DAY)).
+-define(SECONDS_FROM_0_TO_10000, (?DAYS_FROM_0_TO_10000*?SECONDS_PER_DAY)).
%%----------------------------------------------------------------------
%% Types
@@ -83,6 +92,13 @@
-type datetime1970() :: {{year1970(),month(),day()},time()}.
-type yearweeknum() :: {year(),weeknum()}.
+-type rfc3339_string() :: [byte(), ...].
+%% By design 'native' is not supported:
+-type rfc3339_time_unit() :: 'microsecond'
+ | 'millisecond'
+ | 'nanosecond'
+ | 'second'.
+
%%----------------------------------------------------------------------
%% All dates are according the the Gregorian calendar. In this module
@@ -309,8 +325,7 @@ local_time_to_universal_time_dst(DateTime) ->
-spec now_to_datetime(Now) -> datetime1970() when
Now :: erlang:timestamp().
now_to_datetime({MSec, Sec, _uSec}) ->
- Sec0 = MSec*1000000 + Sec + ?DAYS_FROM_0_TO_1970*?SECONDS_PER_DAY,
- gregorian_seconds_to_datetime(Sec0).
+ system_time_to_datetime(MSec*1000000 + Sec).
-spec now_to_universal_time(Now) -> datetime1970() when
Now :: erlang:timestamp().
@@ -328,6 +343,33 @@ now_to_local_time({MSec, Sec, _uSec}) ->
erlang:universaltime_to_localtime(
now_to_universal_time({MSec, Sec, _uSec})).
+-spec rfc3339_to_system_time(DateTimeString) -> integer() when
+ DateTimeString :: rfc3339_string().
+
+rfc3339_to_system_time(DateTimeString) ->
+ rfc3339_to_system_time(DateTimeString, []).
+
+-spec rfc3339_to_system_time(DateTimeString, Options) -> integer() when
+ DateTimeString :: rfc3339_string(),
+ Options :: [Option],
+ Option :: {'unit', rfc3339_time_unit()}.
+
+rfc3339_to_system_time(DateTimeString, Options) ->
+ Unit = proplists:get_value(unit, Options, second),
+ %% _T is the character separating the date and the time:
+ {DateStr, [_T|TimeStr]} = lists:split(10, DateTimeString),
+ {TimeStr2, TimeStr3} = lists:split(8, TimeStr),
+ {ok, [Hour, Min, Sec], []} = io_lib:fread("~d:~d:~d", TimeStr2),
+ {ok, [Year, Month, Day], []} = io_lib:fread("~d-~d-~d", DateStr),
+ DateTime = {{Year, Month, Day}, {Hour, Min, Sec}},
+ IsFractionChar = fun(C) -> C >= $0 andalso C =< $9 orelse C =:= $. end,
+ {FractionStr, UtcOffset} = lists:splitwith(IsFractionChar, TimeStr3),
+ Time = datetime_to_system_time(DateTime),
+ Secs = Time - offset_adjustment(Time, second, UtcOffset),
+ check(DateTimeString, Options, Secs),
+ ScaledEpoch = erlang:convert_time_unit(Secs, second, Unit),
+ ScaledEpoch + copy_sign(fraction(Unit, FractionStr), ScaledEpoch).
+
%% seconds_to_daystime(Secs) = {Days, {Hour, Minute, Second}}
@@ -363,6 +405,55 @@ seconds_to_time(Secs) when Secs >= 0, Secs < ?SECONDS_PER_DAY ->
Second = Secs1 rem ?SECONDS_PER_MINUTE,
{Hour, Minute, Second}.
+-spec system_time_to_local_time(Time, TimeUnit) -> datetime() when
+ Time :: integer(),
+ TimeUnit :: erlang:time_unit().
+
+system_time_to_local_time(Time, TimeUnit) ->
+ UniversalDate = system_time_to_universal_time(Time, TimeUnit),
+ erlang:universaltime_to_localtime(UniversalDate).
+
+-spec system_time_to_universal_time(Time, TimeUnit) -> datetime() when
+ Time :: integer(),
+ TimeUnit :: erlang:time_unit().
+
+system_time_to_universal_time(Time, TimeUnit) ->
+ Secs = erlang:convert_time_unit(Time, TimeUnit, second),
+ system_time_to_datetime(Secs).
+
+-spec system_time_to_rfc3339(Time) -> DateTimeString when
+ Time :: integer(),
+ DateTimeString :: rfc3339_string().
+
+system_time_to_rfc3339(Time) ->
+ system_time_to_rfc3339(Time, []).
+
+-type offset() :: [byte()] | (Time :: integer()).
+-spec system_time_to_rfc3339(Time, Options) -> DateTimeString when
+ Time :: integer(), % Since Epoch
+ Options :: [Option],
+ Option :: {'offset', offset()}
+ | {'time_designator', byte()}
+ | {'unit', rfc3339_time_unit()},
+ DateTimeString :: rfc3339_string().
+
+system_time_to_rfc3339(Time, Options) ->
+ Unit = proplists:get_value(unit, Options, second),
+ OffsetOption = proplists:get_value(offset, Options, ""),
+ T = proplists:get_value(time_designator, Options, $T),
+ AdjustmentSecs = offset_adjustment(Time, Unit, OffsetOption),
+ Offset = offset(OffsetOption, AdjustmentSecs),
+ Adjustment = erlang:convert_time_unit(AdjustmentSecs, second, Unit),
+ AdjustedTime = Time + Adjustment,
+ Factor = factor(Unit),
+ Secs = AdjustedTime div Factor,
+ check(Time, Options, Secs),
+ DateTime = system_time_to_datetime(Secs),
+ {{Year, Month, Day}, {Hour, Min, Sec}} = DateTime,
+ FractionStr = fraction_str(Factor, AdjustedTime),
+ flat_fwrite("~4.10.0B-~2.10.0B-~2.10.0B~c~2.10.0B:~2.10.0B:~2.10.0B~s~s",
+ [Year, Month, Day, T, Hour, Min, Sec, FractionStr, Offset]).
+
%% time_difference(T1, T2) = Tdiff
%%
%% Returns the difference between two {Date, Time} structures.
@@ -550,3 +641,85 @@ df(Year, _) ->
true -> 1;
false -> 0
end.
+
+check(_Arg, _Options, Secs) when Secs >= - ?SECONDS_FROM_0_TO_1970,
+ Secs < ?SECONDS_FROM_0_TO_10000 ->
+ ok;
+check(Arg, Options, _Secs) ->
+ erlang:error({badarg, [Arg, Options]}).
+
+datetime_to_system_time(DateTime) ->
+ datetime_to_gregorian_seconds(DateTime) - ?SECONDS_FROM_0_TO_1970.
+
+system_time_to_datetime(Seconds) ->
+ gregorian_seconds_to_datetime(Seconds + ?SECONDS_FROM_0_TO_1970).
+
+offset(OffsetOption, Secs0) when OffsetOption =:= "";
+ is_integer(OffsetOption) ->
+ Sign = case Secs0 < 0 of
+ true -> $-;
+ false -> $+
+ end,
+ Secs = abs(Secs0),
+ Hour = Secs div 3600,
+ Min = (Secs rem 3600) div 60,
+ io_lib:fwrite("~c~2.10.0B:~2.10.0B", [Sign, Hour, Min]);
+offset(OffsetOption, _Secs) ->
+ OffsetOption.
+
+offset_adjustment(Time, Unit, OffsetString) when is_list(OffsetString) ->
+ offset_string_adjustment(Time, Unit, OffsetString);
+offset_adjustment(_Time, Unit, Offset) when is_integer(Offset) ->
+ erlang:convert_time_unit(Offset, Unit, second).
+
+offset_string_adjustment(Time, Unit, "") ->
+ local_offset(Time, Unit);
+offset_string_adjustment(_Time, _Unit, "Z") ->
+ 0;
+offset_string_adjustment(_Time, _Unit, "z") ->
+ 0;
+offset_string_adjustment(_Time, _Unit, [Sign|Tz]) ->
+ {ok, [Hour, Min], []} = io_lib:fread("~d:~d", Tz),
+ Adjustment = 3600 * Hour + 60 * Min,
+ case Sign of
+ $- -> -Adjustment;
+ $+ -> Adjustment
+ end.
+
+local_offset(SystemTime, Unit) ->
+ LocalTime = system_time_to_local_time(SystemTime, Unit),
+ UniversalTime = system_time_to_universal_time(SystemTime, Unit),
+ LocalSecs = datetime_to_gregorian_seconds(LocalTime),
+ UniversalSecs = datetime_to_gregorian_seconds(UniversalTime),
+ LocalSecs - UniversalSecs.
+
+fraction_str(Factor, Time) ->
+ case Time rem Factor of
+ 0 ->
+ "";
+ Fraction ->
+ FS = io_lib:fwrite(".~*..0B", [log10(Factor), abs(Fraction)]),
+ string:trim(FS, trailing, "0")
+ end.
+
+fraction(second, _) ->
+ 0;
+fraction(_, "") ->
+ 0;
+fraction(Unit, FractionStr) ->
+ round(factor(Unit) * list_to_float([$0|FractionStr])).
+
+copy_sign(N1, N2) when N2 < 0 -> -N1;
+copy_sign(N1, _N2) -> N1.
+
+factor(second) -> 1;
+factor(millisecond) -> 1000;
+factor(microsecond) -> 1000000;
+factor(nanosecond) -> 1000000000.
+
+log10(1000) -> 3;
+log10(1000000) -> 6;
+log10(1000000000) -> 9.
+
+flat_fwrite(F, S) ->
+ lists:flatten(io_lib:fwrite(F, S)).
diff --git a/lib/stdlib/src/dets.erl b/lib/stdlib/src/dets.erl
index 10e8c9c800..0488c2bef2 100644
--- a/lib/stdlib/src/dets.erl
+++ b/lib/stdlib/src/dets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -616,12 +616,18 @@ next(Tab, Key) ->
%% Assuming that a file already exists, open it with the
%% parameters as already specified in the file itself.
%% Return a ref leading to the file.
-open_file(File) ->
- case dets_server:open_file(to_list(File)) of
- badarg -> % Should not happen.
- erlang:error(dets_process_died, [File]);
- Reply ->
- einval(Reply, [File])
+open_file(File0) ->
+ File = to_list(File0),
+ case is_list(File) of
+ true ->
+ case dets_server:open_file(File) of
+ badarg -> % Should not happen.
+ erlang:error(dets_process_died, [File]);
+ Reply ->
+ einval(Reply, [File])
+ end;
+ false ->
+ erlang:error(badarg, [File0])
end.
-spec open_file(Name, Args) -> {'ok', Name} | {'error', Reason} when
@@ -1088,6 +1094,7 @@ defaults(Tab, Args) ->
debug = false},
Fun = fun repl/2,
Defaults = lists:foldl(Fun, Defaults0, Args),
+ true = is_list(Defaults#open_args.file),
is_comp_min_max(Defaults).
to_list(T) when is_atom(T) -> atom_to_list(T);
@@ -1112,9 +1119,7 @@ repl({delayed_write, {Delay,Size} = C}, Defs)
Defs#open_args{delayed_write = C};
repl({estimated_no_objects, I}, Defs) ->
repl({min_no_slots, I}, Defs);
-repl({file, File}, Defs) when is_list(File) ->
- Defs#open_args{file = File};
-repl({file, File}, Defs) when is_atom(File) ->
+repl({file, File}, Defs) ->
Defs#open_args{file = to_list(File)};
repl({keypos, P}, Defs) when is_integer(P), P > 0 ->
Defs#open_args{keypos =P};
@@ -1288,8 +1293,8 @@ init(Parent, Server) ->
catch
exit:normal ->
exit(normal);
- _:Bad ->
- bug_found(no_name, Op, Bad, From),
+ _:Bad:Stacktrace ->
+ bug_found(no_name, Op, Bad, Stacktrace, From),
exit(Bad) % give up
end
end.
@@ -1354,7 +1359,7 @@ open_file_loop2(Head, N) ->
?MODULE, [], Head);
Message ->
error_logger:format("** dets: unexpected message"
- "(ignored): ~w~n", [Message]),
+ "(ignored): ~tw~n", [Message]),
open_file_loop(Head, N)
end.
@@ -1371,8 +1376,8 @@ do_apply_op(Op, From, Head, N) ->
catch
exit:normal ->
exit(normal);
- _:Bad ->
- bug_found(Head#head.name, Op, Bad, From),
+ _:Bad:Stacktrace ->
+ bug_found(Head#head.name, Op, Bad, Stacktrace, From),
open_file_loop(Head, N)
end.
@@ -1403,7 +1408,7 @@ apply_op(Op, From, Head, N) ->
Head;
_Dirty when N =:= 0 -> % dirty or new_dirty
%% The updates seems to have declined
- dets_utils:vformat("** dets: Auto save of ~p\n",
+ dets_utils:vformat("** dets: Auto save of ~tp\n",
[Head#head.name]),
{NewHead, _Res} = perform_save(Head, true),
erlang:garbage_collect(),
@@ -1581,19 +1586,19 @@ apply_op(Op, From, Head, N) ->
ok
end.
-bug_found(Name, Op, Bad, From) ->
+bug_found(Name, Op, Bad, Stacktrace, From) ->
case dets_utils:debug_mode() of
true ->
%% If stream_op/5 found more requests, this is not
%% the last operation.
error_logger:format
- ("** dets: Bug was found when accessing table ~w,~n"
- "** dets: operation was ~p and reply was ~w.~n"
- "** dets: Stacktrace: ~w~n",
- [Name, Op, Bad, erlang:get_stacktrace()]);
+ ("** dets: Bug was found when accessing table ~tw,~n"
+ "** dets: operation was ~tp and reply was ~tw.~n"
+ "** dets: Stacktrace: ~tw~n",
+ [Name, Op, Bad, Stacktrace]);
false ->
error_logger:format
- ("** dets: Bug was found when accessing table ~w~n",
+ ("** dets: Bug was found when accessing table ~tw~n",
[Name])
end,
if
@@ -2117,7 +2122,7 @@ do_open_file([Fname, Verbose], Parent, Server, Ref) ->
Error;
Bad ->
error_logger:format
- ("** dets: Bug was found in open_file/1, reply was ~w.~n",
+ ("** dets: Bug was found in open_file/1, reply was ~tw.~n",
[Bad]),
{error, {dets_bug, Fname, Bad}}
end;
@@ -2135,7 +2140,7 @@ do_open_file([Tab, OpenArgs, Verb], Parent, Server, _Ref) ->
Bad ->
error_logger:format
("** dets: Bug was found in open_file/2, arguments were~n"
- "** dets: ~w and reply was ~w.~n",
+ "** dets: ~tw and reply was ~tw.~n",
[OpenArgs, Bad]),
{error, {dets_bug, Tab, {open_file, OpenArgs}, Bad}}
end.
@@ -3123,7 +3128,7 @@ check_safe_fixtable(Head) ->
((get(verbose) =:= yes) orelse dets_utils:debug_mode()) of
true ->
error_logger:format
- ("** dets: traversal of ~p needs safe_fixtable~n",
+ ("** dets: traversal of ~tp needs safe_fixtable~n",
[Head#head.name]);
false ->
ok
@@ -3189,7 +3194,7 @@ scan_read(H, From, _To, Min, _L, Ts, R, C) ->
err(Error) ->
case get(verbose) of
yes ->
- error_logger:format("** dets: failed with ~w~n", [Error]),
+ error_logger:format("** dets: failed with ~tw~n", [Error]),
Error;
undefined ->
Error
diff --git a/lib/stdlib/src/dets_utils.erl b/lib/stdlib/src/dets_utils.erl
index da6ebd18f2..12394bd1ad 100644
--- a/lib/stdlib/src/dets_utils.erl
+++ b/lib/stdlib/src/dets_utils.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -377,7 +377,8 @@ corrupt_reason(Head, Reason0) ->
no_disk_map ->
Reason0;
DM ->
- ST = erlang:get_stacktrace(),
+ {current_stacktrace, ST} =
+ erlang:process_info(self(), current_stacktrace),
PD = get(),
{Reason0, ST, PD, DM}
end,
@@ -387,7 +388,7 @@ corrupt_reason(Head, Reason0) ->
corrupt(Head, Error) ->
case get(verbose) of
yes ->
- error_logger:format("** dets: Corrupt table ~p: ~tp\n",
+ error_logger:format("** dets: Corrupt table ~tp: ~tp\n",
[Head#head.name, Error]);
_ -> ok
end,
diff --git a/lib/stdlib/src/edlin.erl b/lib/stdlib/src/edlin.erl
index 71e8471c45..f027d05f55 100644
--- a/lib/stdlib/src/edlin.erl
+++ b/lib/stdlib/src/edlin.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -83,7 +83,7 @@ edit_line(Cs, {line,P,L,M}) ->
edit_line1(Cs, {line,P,L,{blink,N}}) ->
edit(Cs, P, L, none, [{move_rel,N}]);
edit_line1(Cs, {line,P,{[],[]},none}) ->
- {more_chars, {line,P,{lists:reverse(Cs),[]},none},[{put_chars, unicode, Cs}]};
+ {more_chars, {line,P,{string:reverse(Cs),[]},none},[{put_chars, unicode, Cs}]};
edit_line1(Cs, {line,P,L,M}) ->
edit(Cs, P, L, M, []).
@@ -93,14 +93,14 @@ edit([C|Cs], P, {Bef,Aft}, Prefix, Rs0) ->
case key_map(C, Prefix) of
meta ->
edit(Cs, P, {Bef,Aft}, meta, Rs0);
- meta_o ->
- edit(Cs, P, {Bef,Aft}, meta_o, Rs0);
- meta_csi ->
- edit(Cs, P, {Bef,Aft}, meta_csi, Rs0);
- meta_meta ->
- edit(Cs, P, {Bef,Aft}, meta_meta, Rs0);
- {csi, _} = Csi ->
- edit(Cs, P, {Bef,Aft}, Csi, Rs0);
+ meta_o ->
+ edit(Cs, P, {Bef,Aft}, meta_o, Rs0);
+ meta_csi ->
+ edit(Cs, P, {Bef,Aft}, meta_csi, Rs0);
+ meta_meta ->
+ edit(Cs, P, {Bef,Aft}, meta_meta, Rs0);
+ {csi, _} = Csi ->
+ edit(Cs, P, {Bef,Aft}, Csi, Rs0);
meta_left_sq_bracket ->
edit(Cs, P, {Bef,Aft}, meta_left_sq_bracket, Rs0);
search_meta ->
@@ -110,8 +110,8 @@ edit([C|Cs], P, {Bef,Aft}, Prefix, Rs0) ->
ctlx ->
edit(Cs, P, {Bef,Aft}, ctlx, Rs0);
new_line ->
- {done, reverse(Bef, Aft ++ "\n"), Cs,
- reverse(Rs0, [{move_rel,length(Aft)},{put_chars,unicode,"\n"}])};
+ {done, get_line(Bef, Aft ++ "\n"), Cs,
+ reverse(Rs0, [{move_rel,cp_len(Aft)},{put_chars,unicode,"\n"}])};
redraw_line ->
Rs1 = erase(P, Bef, Aft, Rs0),
Rs = redraw(P, Bef, Aft, Rs1),
@@ -157,7 +157,7 @@ edit([], P, L, {blink,N}, Rs) ->
edit([], P, L, Prefix, Rs) ->
{more_chars,{line,P,L,Prefix},reverse(Rs)};
edit(eof, _, {Bef,Aft}, _, Rs) ->
- {done,reverse(Bef, Aft),[],reverse(Rs, [{move_rel,length(Aft)}])}.
+ {done,get_line(Bef, Aft),[],reverse(Rs, [{move_rel,cp_len(Aft)}])}.
%% %% Assumes that arg is a string
%% %% Horizontal whitespace only.
@@ -279,11 +279,21 @@ key_map(C, search) -> {insert_search,C};
key_map(C, _) -> {undefined,C}.
%% do_op(Action, Before, After, Requests)
-
-do_op({insert,C}, Bef, [], Rs) ->
- {{[C|Bef],[]},[{put_chars, unicode,[C]}|Rs]};
-do_op({insert,C}, Bef, Aft, Rs) ->
- {{[C|Bef],Aft},[{insert_chars, unicode, [C]}|Rs]};
+%% Before and After are of lists of type string:grapheme_cluster()
+do_op({insert,C}, [], [], Rs) ->
+ {{[C],[]},[{put_chars, unicode,[C]}|Rs]};
+do_op({insert,C}, [Bef|Bef0], [], Rs) ->
+ case string:to_graphemes([Bef,C]) of
+ [GC] -> {{[GC|Bef0],[]},[{put_chars, unicode,[C]}|Rs]};
+ _ -> {{[C,Bef|Bef0],[]},[{put_chars, unicode,[C]}|Rs]}
+ end;
+do_op({insert,C}, [], Aft, Rs) ->
+ {{[C],Aft},[{insert_chars, unicode,[C]}|Rs]};
+do_op({insert,C}, [Bef|Bef0], Aft, Rs) ->
+ case string:to_graphemes([Bef,C]) of
+ [GC] -> {{[GC|Bef0],Aft},[{insert_chars, unicode,[C]}|Rs]};
+ _ -> {{[C,Bef|Bef0],Aft},[{insert_chars, unicode,[C]}|Rs]}
+ end;
%% Search mode prompt always looks like (search)`$TERMS': $RESULT.
%% the {insert_search, _} handlings allow to share this implementation
%% correctly with group.erl. This module provides $TERMS, and group.erl
@@ -299,13 +309,13 @@ do_op({insert_search, C}, Bef, [], Rs) ->
[{insert_chars, unicode, [C]++Aft}, {delete_chars,-3} | Rs],
search};
do_op({insert_search, C}, Bef, Aft, Rs) ->
- Offset= length(Aft),
+ Offset= cp_len(Aft),
NAft = "': ",
{{[C|Bef],NAft},
[{insert_chars, unicode, [C]++NAft}, {delete_chars,-Offset} | Rs],
search};
do_op({search, backward_delete_char}, [_|Bef], Aft, Rs) ->
- Offset= length(Aft)+1,
+ Offset= cp_len(Aft)+1,
NAft = "': ",
{{Bef,NAft},
[{insert_chars, unicode, NAft}, {delete_chars,-Offset}|Rs],
@@ -314,13 +324,13 @@ do_op({search, backward_delete_char}, [], _Aft, Rs) ->
Aft="': ",
{{[],Aft}, Rs, search};
do_op({search, skip_up}, Bef, Aft, Rs) ->
- Offset= length(Aft),
+ Offset= cp_len(Aft),
NAft = "': ",
{{[$\^R|Bef],NAft}, % we insert ^R as a flag to whoever called us
[{insert_chars, unicode, NAft}, {delete_chars,-Offset}|Rs],
search};
do_op({search, skip_down}, Bef, Aft, Rs) ->
- Offset= length(Aft),
+ Offset= cp_len(Aft),
NAft = "': ",
{{[$\^S|Bef],NAft}, % we insert ^S as a flag to whoever called us
[{insert_chars, unicode, NAft}, {delete_chars,-Offset}|Rs],
@@ -328,12 +338,12 @@ do_op({search, skip_down}, Bef, Aft, Rs) ->
do_op({search, search_found}, _Bef, Aft, Rs) ->
"': "++NAft = Aft,
{{[],NAft},
- [{put_chars, unicode, "\n"}, {move_rel,-length(Aft)} | Rs],
+ [{put_chars, unicode, "\n"}, {move_rel,-cp_len(Aft)} | Rs],
search_found};
do_op({search, search_quit}, _Bef, Aft, Rs) ->
"': "++NAft = Aft,
{{[],NAft},
- [{put_chars, unicode, "\n"}, {move_rel,-length(Aft)} | Rs],
+ [{put_chars, unicode, "\n"}, {move_rel,-cp_len(Aft)} | Rs],
search_quit};
%% do blink after $$
do_op({blink,C,M}, Bef=[$$,$$|_], Aft, Rs) ->
@@ -361,14 +371,16 @@ do_op(auto_blink, Bef, Aft, Rs) ->
N -> {blink,N+1,{Bef,Aft},
[{move_rel,-(N+1)}|Rs]}
end;
-do_op(forward_delete_char, Bef, [_|Aft], Rs) ->
- {{Bef,Aft},[{delete_chars,1}|Rs]};
-do_op(backward_delete_char, [_|Bef], Aft, Rs) ->
- {{Bef,Aft},[{delete_chars,-1}|Rs]};
+do_op(forward_delete_char, Bef, [GC|Aft], Rs) ->
+ {{Bef,Aft},[{delete_chars,gc_len(GC)}|Rs]};
+do_op(backward_delete_char, [GC|Bef], Aft, Rs) ->
+ {{Bef,Aft},[{delete_chars,-gc_len(GC)}|Rs]};
do_op(transpose_char, [C1,C2|Bef], [], Rs) ->
- {{[C2,C1|Bef],[]},[{put_chars, unicode,[C1,C2]},{move_rel,-2}|Rs]};
+ Len = gc_len(C1)+gc_len(C2),
+ {{[C2,C1|Bef],[]},[{put_chars, unicode,[C1,C2]},{move_rel,-Len}|Rs]};
do_op(transpose_char, [C2|Bef], [C1|Aft], Rs) ->
- {{[C2,C1|Bef],Aft},[{put_chars, unicode,[C1,C2]},{move_rel,-1}|Rs]};
+ Len = gc_len(C2),
+ {{[C2,C1|Bef],Aft},[{put_chars, unicode,[C1,C2]},{move_rel,-Len}|Rs]};
do_op(kill_word, Bef, Aft0, Rs) ->
{Aft1,Kill0,N0} = over_non_word(Aft0, [], 0),
{Aft,Kill,N} = over_word(Aft1, Kill0, N0),
@@ -381,7 +393,7 @@ do_op(backward_kill_word, Bef0, Aft, Rs) ->
{{Bef,Aft},[{delete_chars,-N}|Rs]};
do_op(kill_line, Bef, Aft, Rs) ->
put(kill_buffer, Aft),
- {{Bef,[]},[{delete_chars,length(Aft)}|Rs]};
+ {{Bef,[]},[{delete_chars,cp_len(Aft)}|Rs]};
do_op(yank, Bef, [], Rs) ->
Kill = get(kill_buffer),
{{reverse(Kill, Bef),[]},[{put_chars, unicode,Kill}|Rs]};
@@ -389,9 +401,9 @@ do_op(yank, Bef, Aft, Rs) ->
Kill = get(kill_buffer),
{{reverse(Kill, Bef),Aft},[{insert_chars, unicode,Kill}|Rs]};
do_op(forward_char, Bef, [C|Aft], Rs) ->
- {{[C|Bef],Aft},[{move_rel,1}|Rs]};
+ {{[C|Bef],Aft},[{move_rel,gc_len(C)}|Rs]};
do_op(backward_char, [C|Bef], Aft, Rs) ->
- {{Bef,[C|Aft]},[{move_rel,-1}|Rs]};
+ {{Bef,[C|Aft]},[{move_rel,-gc_len(C)}|Rs]};
do_op(forward_word, Bef0, Aft0, Rs) ->
{Aft1,Bef1,N0} = over_non_word(Aft0, Bef0, 0),
{Aft,Bef,N} = over_word(Aft1, Bef1, N0),
@@ -400,17 +412,17 @@ do_op(backward_word, Bef0, Aft0, Rs) ->
{Bef1,Aft1,N0} = over_non_word(Bef0, Aft0, 0),
{Bef,Aft,N} = over_word(Bef1, Aft1, N0),
{{Bef,Aft},[{move_rel,-N}|Rs]};
-do_op(beginning_of_line, [C|Bef], Aft, Rs) ->
- {{[],reverse(Bef, [C|Aft])},[{move_rel,-(length(Bef)+1)}|Rs]};
+do_op(beginning_of_line, [_|_]=Bef, Aft, Rs) ->
+ {{[],reverse(Bef, Aft)},[{move_rel,-(cp_len(Bef))}|Rs]};
do_op(beginning_of_line, [], Aft, Rs) ->
{{[],Aft},Rs};
-do_op(end_of_line, Bef, [C|Aft], Rs) ->
- {{reverse(Aft, [C|Bef]),[]},[{move_rel,length(Aft)+1}|Rs]};
+do_op(end_of_line, Bef, [_|_]=Aft, Rs) ->
+ {{reverse(Aft, Bef),[]},[{move_rel,cp_len(Aft)}|Rs]};
do_op(end_of_line, Bef, [], Rs) ->
{{Bef,[]},Rs};
do_op(ctlu, Bef, Aft, Rs) ->
put(kill_buffer, reverse(Bef)),
- {{[], Aft}, [{delete_chars, -length(Bef)} | Rs]};
+ {{[], Aft}, [{delete_chars, -cp_len(Bef)} | Rs]};
do_op(beep, Bef, Aft, Rs) ->
{{Bef,Aft},[beep|Rs]};
do_op(_, Bef, Aft, Rs) ->
@@ -436,7 +448,7 @@ over_word(Cs, Stack, N) ->
until_quote([$\'|Cs], Stack, N) ->
{Cs, [$\'|Stack], N+1};
until_quote([C|Cs], Stack, N) ->
- until_quote(Cs, [C|Stack], N+1).
+ until_quote(Cs, [C|Stack], N+gc_len(C)).
over_word1([$\'=C|Cs], Stack, N) ->
until_quote(Cs, [C|Stack], N+1);
@@ -445,7 +457,7 @@ over_word1(Cs, Stack, N) ->
over_word2([C|Cs], Stack, N) ->
case word_char(C) of
- true -> over_word2(Cs, [C|Stack], N+1);
+ true -> over_word2(Cs, [C|Stack], N+gc_len(C));
false -> {[C|Cs],Stack,N}
end;
over_word2([], Stack, N) when is_integer(N) ->
@@ -454,7 +466,7 @@ over_word2([], Stack, N) when is_integer(N) ->
over_non_word([C|Cs], Stack, N) ->
case word_char(C) of
true -> {[C|Cs],Stack,N};
- false -> over_non_word(Cs, [C|Stack], N+1)
+ false -> over_non_word(Cs, [C|Stack], N+gc_len(C))
end;
over_non_word([], Stack, N) ->
{[],Stack,N}.
@@ -465,6 +477,7 @@ word_char(C) when C >= $a, C =< $z -> true;
word_char(C) when C >= $ß, C =< $ÿ, C =/= $÷ -> true;
word_char(C) when C >= $0, C =< $9 -> true;
word_char(C) when C =:= $_ -> true;
+word_char([_|_]) -> true; %% Is grapheme
word_char(_) -> false.
%% over_white(Chars, InitialStack, InitialCount) ->
@@ -488,8 +501,8 @@ over_paren(Chars, Paren, Match) ->
over_paren([C,$$,$$|Cs], Paren, Match, D, N, L) ->
over_paren([C|Cs], Paren, Match, D, N+2, L);
-over_paren([_,$$|Cs], Paren, Match, D, N, L) ->
- over_paren(Cs, Paren, Match, D, N+2, L);
+over_paren([GC,$$|Cs], Paren, Match, D, N, L) ->
+ over_paren(Cs, Paren, Match, D, N+1+gc_len(GC), L);
over_paren([Match|_], _Paren, Match, 1, N, _) ->
N;
over_paren([Match|Cs], Paren, Match, D, N, [Match|L]) ->
@@ -518,8 +531,8 @@ over_paren([$[|_], _, _, _, _, _) ->
over_paren([${|_], _, _, _, _, _) ->
beep;
-over_paren([_|Cs], Paren, Match, D, N, L) ->
- over_paren(Cs, Paren, Match, D, N+1, L);
+over_paren([GC|Cs], Paren, Match, D, N, L) ->
+ over_paren(Cs, Paren, Match, D, N+gc_len(GC), L);
over_paren([], _, _, _, _, _) ->
0.
@@ -529,8 +542,8 @@ over_paren_auto(Chars) ->
over_paren_auto([C,$$,$$|Cs], D, N, L) ->
over_paren_auto([C|Cs], D, N+2, L);
-over_paren_auto([_,$$|Cs], D, N, L) ->
- over_paren_auto(Cs, D, N+2, L);
+over_paren_auto([GC,$$|Cs], D, N, L) ->
+ over_paren_auto(Cs, D, N+1+gc_len(GC), L);
over_paren_auto([$(|_], _, N, []) ->
{N, $)};
@@ -553,8 +566,8 @@ over_paren_auto([$[|Cs], D, N, [$[|L]) ->
over_paren_auto([${|Cs], D, N, [${|L]) ->
over_paren_auto(Cs, D, N+1, L);
-over_paren_auto([_|Cs], D, N, L) ->
- over_paren_auto(Cs, D, N+1, L);
+over_paren_auto([GC|Cs], D, N, L) ->
+ over_paren_auto(Cs, D, N+gc_len(GC), L);
over_paren_auto([], _, _, _) ->
0.
@@ -574,28 +587,43 @@ erase_inp({line,_,{Bef,Aft},_}) ->
reverse(erase([], Bef, Aft, [])).
erase(Pbs, Bef, Aft, Rs) ->
- [{delete_chars,-length(Pbs)-length(Bef)},{delete_chars,length(Aft)}|Rs].
+ [{delete_chars,-cp_len(Pbs)-cp_len(Bef)},{delete_chars,cp_len(Aft)}|Rs].
redraw_line({line,Pbs,{Bef,Aft},_}) ->
reverse(redraw(Pbs, Bef, Aft, [])).
redraw(Pbs, Bef, Aft, Rs) ->
- [{move_rel,-length(Aft)},{put_chars, unicode,reverse(Bef, Aft)},{put_chars, unicode,Pbs}|Rs].
+ [{move_rel,-cp_len(Aft)},{put_chars, unicode,reverse(Bef, Aft)},{put_chars, unicode,Pbs}|Rs].
length_before({line,Pbs,{Bef,_Aft},_}) ->
- length(Pbs) + length(Bef).
+ cp_len(Pbs) + cp_len(Bef).
length_after({line,_,{_Bef,Aft},_}) ->
- length(Aft).
+ cp_len(Aft).
prompt({line,Pbs,_,_}) ->
Pbs.
current_line({line,_,{Bef, Aft},_}) ->
- reverse(Bef, Aft ++ "\n").
+ get_line(Bef, Aft ++ "\n").
current_chars({line,_,{Bef,Aft},_}) ->
- reverse(Bef, Aft).
+ get_line(Bef, Aft).
+
+get_line(Bef, Aft) ->
+ unicode:characters_to_list(reverse(Bef, Aft)).
+
+%% Grapheme length in codepoints
+gc_len(CP) when is_integer(CP) -> 1;
+gc_len(CPs) when is_list(CPs) -> length(CPs).
+
+%% String length in codepoints
+cp_len(Str) ->
+ cp_len(Str, 0).
+
+cp_len([GC|R], Len) ->
+ cp_len(R, Len + gc_len(GC));
+cp_len([], Len) -> Len.
%% %% expand(CurrentBefore) ->
%% %% {yes,Expansion} | no
diff --git a/lib/stdlib/src/edlin_expand.erl b/lib/stdlib/src/edlin_expand.erl
index a1a97af4c5..bdcefda6e5 100644
--- a/lib/stdlib/src/edlin_expand.erl
+++ b/lib/stdlib/src/edlin_expand.erl
@@ -23,7 +23,7 @@
-export([expand/1, format_matches/1]).
--import(lists, [reverse/1, nthtail/2, prefix/2]).
+-import(lists, [reverse/1, prefix/2]).
%% expand(CurrentBefore) ->
%% {yes, Expansion, Matches} | {no, Matches}
@@ -75,15 +75,15 @@ to_atom(Str) ->
end.
match(Prefix, Alts, Extra0) ->
- Len = length(Prefix),
+ Len = string:length(Prefix),
Matches = lists:sort(
[{S, A} || {H, A} <- Alts,
- prefix(Prefix, S=hd(io_lib:fwrite("~w",[H])))]),
+ prefix(Prefix, S=flat_write(H))]),
case longest_common_head([N || {N, _} <- Matches]) of
{partial, []} ->
{no, [], Matches}; % format_matches(Matches)};
{partial, Str} ->
- case nthtail(Len, Str) of
+ case string:slice(Str, Len) of
[] ->
{yes, [], Matches}; % format_matches(Matches)};
Remain ->
@@ -94,18 +94,21 @@ match(Prefix, Alts, Extra0) ->
{"(",[{Str,0}]} -> "()";
{_,_} -> Extra0
end,
- {yes, nthtail(Len, Str) ++ Extra, []};
+ {yes, string:slice(Str, Len) ++ Extra, []};
no ->
{no, [], []}
end.
+flat_write(T) ->
+ lists:flatten(io_lib:fwrite("~tw",[T])).
+
%% Return the list of names L in multiple columns.
format_matches(L) ->
{S1, Dots} = format_col(lists:sort(L), []),
S = case Dots of
true ->
{_, Prefix} = longest_common_head(vals(L)),
- PrefixLen = length(Prefix),
+ PrefixLen = string:length(Prefix),
case PrefixLen =< 3 of
true -> S1; % Do not replace the prefix with "...".
false ->
@@ -128,7 +131,7 @@ format_col([A|T], Width, Len, Acc0, LL, Dots) ->
{H0, R} = format_val(A),
Hmax = LL - length(R),
{H, NewDots} =
- case length(H0) > Hmax of
+ case string:length(H0) > Hmax of
true -> {io_lib:format("~-*ts", [Hmax - 3, H0]) ++ "...", true};
false -> {H0, Dots}
end,
@@ -149,12 +152,12 @@ format_val(H) ->
field_width(L, LL) -> field_width(L, 0, LL).
field_width([{H,_}|T], W, LL) ->
- case length(H) of
+ case string:length(H) of
L when L > W -> field_width(T, L, LL);
_ -> field_width(T, W, LL)
end;
field_width([H|T], W, LL) ->
- case length(H) of
+ case string:length(H) of
L when L > W -> field_width(T, L, LL);
_ -> field_width(T, W, LL)
end;
@@ -169,10 +172,11 @@ vals([S|L]) -> [S|vals(L)].
leading_dots([], _Len) -> [];
leading_dots([{H, I}|L], Len) ->
- [{"..." ++ nthtail(Len, H), I}|leading_dots(L, Len)];
+ [{"..." ++ string:slice(H, Len), I}|leading_dots(L, Len)];
leading_dots([H|L], Len) ->
- ["..." ++ nthtail(Len, H)|leading_dots(L, Len)].
+ ["..." ++ string:slice(H, Len)|leading_dots(L, Len)].
+%% Strings are handled naively, but it should be OK here.
longest_common_head([]) ->
no;
longest_common_head(LL) ->
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index 31d0d499e3..181a524db6 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@
-type epp_handle() :: pid().
-type source_encoding() :: latin1 | utf8.
--type ifdef() :: 'ifdef' | 'ifndef' | 'else'.
+-type ifdef() :: 'ifdef' | 'ifndef' | 'if' | 'else'.
-type name() :: atom().
-type argspec() :: 'none' %No arguments
@@ -117,6 +117,7 @@ open(Name, File, StartLocation, Path, Pdm) ->
{'ok', Epp} | {'ok', Epp, Extra} | {'error', ErrorDescriptor} when
Options :: [{'default_encoding', DefEncoding :: source_encoding()} |
{'includes', IncludePath :: [DirectoryName :: file:name()]} |
+ {'source_name', SourceName :: file:name()} |
{'macros', PredefMacros :: macros()} |
{'name',FileName :: file:name()} |
'extra'],
@@ -221,6 +222,8 @@ format_error({illegal_function,Macro}) ->
io_lib:format("?~s can only be used within a function", [Macro]);
format_error({illegal_function_usage,Macro}) ->
io_lib:format("?~s must not begin a form", [Macro]);
+format_error(elif_after_else) ->
+ "'elif' following 'else'";
format_error({'NYI',What}) ->
io_lib:format("not yet implemented '~s'", [What]);
format_error({error,Term}) ->
@@ -246,6 +249,7 @@ parse_file(Ifile, Path, Predefs) ->
{'ok', [Form]} | {'ok', [Form], Extra} | {error, OpenError} when
FileName :: file:name(),
Options :: [{'includes', IncludePath :: [DirectoryName :: file:name()]} |
+ {'source_name', SourceName :: file:name()} |
{'macros', PredefMacros :: macros()} |
{'default_encoding', DefEncoding :: source_encoding()} |
'extra'],
@@ -479,7 +483,7 @@ com_enc(_B, _Fun, _N, L, Ps) ->
com_enc_end([L | Ps]).
com_enc_end(Ps0) ->
- Ps = lists:reverse([lists:reverse(string:to_lower(P)) || P <- Ps0]),
+ Ps = lists:reverse([lists:reverse(lowercase(P)) || P <- Ps0]),
com_encoding(Ps).
com_encoding(["latin","1"|_]) ->
@@ -489,6 +493,9 @@ com_encoding(["utf","8"|_]) ->
com_encoding(_) ->
throw(no). % Don't try any further
+lowercase(S) ->
+ unicode:characters_to_list(string:lowercase(S)).
+
normalize_typed_record_fields([]) ->
{typed, []};
normalize_typed_record_fields(Fields) ->
@@ -535,9 +542,10 @@ server(Pid, Name, Options, #epp{pre_opened=PreOpened}=St) ->
init_server(Pid, Name, Options, St)
end.
-init_server(Pid, Name, Options, St0) ->
+init_server(Pid, FileName, Options, St0) ->
+ SourceName = proplists:get_value(source_name, Options, FileName),
Pdm = proplists:get_value(macros, Options, []),
- Ms0 = predef_macros(Name),
+ Ms0 = predef_macros(FileName),
case user_predef(Pdm, Ms0) of
{ok,Ms1} ->
#epp{file = File, location = AtLocation} = St0,
@@ -547,14 +555,14 @@ init_server(Pid, Name, Options, St0) ->
epp_reply(Pid, {ok,self(),Encoding}),
%% ensure directory of current source file is
%% first in path
- Path = [filename:dirname(Name) |
+ Path = [filename:dirname(FileName) |
proplists:get_value(includes, Options, [])],
- St = St0#epp{delta=0, name=Name, name2=Name,
+ St = St0#epp{delta=0, name=SourceName, name2=SourceName,
path=Path, macs=Ms1,
default_encoding=DefEncoding},
From = wait_request(St),
Anno = erl_anno:new(AtLocation),
- enter_file_reply(From, file_name(Name), Anno,
+ enter_file_reply(From, file_name(SourceName), Anno,
AtLocation, code),
wait_req_scan(St);
{error,E} ->
@@ -568,6 +576,7 @@ init_server(Pid, Name, Options, St0) ->
predef_macros(File) ->
Machine = list_to_atom(erlang:system_info(machine)),
Anno = line1(),
+ OtpVersion = list_to_integer(erlang:system_info(otp_release)),
Defs = [{'FILE', {none,[{string,Anno,File}]}},
{'FUNCTION_NAME', undefined},
{'FUNCTION_ARITY', undefined},
@@ -577,7 +586,8 @@ predef_macros(File) ->
{'BASE_MODULE', undefined},
{'BASE_MODULE_STRING', undefined},
{'MACHINE', {none,[{atom,Anno,Machine}]}},
- {Machine, {none,[{atom,Anno,true}]}}
+ {Machine, {none,[{atom,Anno,true}]}},
+ {'OTP_RELEASE', {none,[{integer,Anno,OtpVersion}]}}
],
maps:from_list(Defs).
@@ -1082,21 +1092,118 @@ scan_else(_Toks, Else, From, St) ->
epp_reply(From, {error,{loc(Else),epp,{bad,'else'}}}),
wait_req_scan(St).
-%% scan_if(Tokens, EndifToken, From, EppState)
+%% scan_if(Tokens, IfToken, From, EppState)
%% Handle the conditional parsing of a file.
-%% Report a badly formed if test and then treat as false macro.
+scan_if([{'(',_}|_]=Toks, If, From, St) ->
+ try eval_if(Toks, St) of
+ true ->
+ scan_toks(From, St#epp{istk=['if'|St#epp.istk]});
+ _ ->
+ skip_toks(From, St, ['if'])
+ catch
+ throw:Error0 ->
+ Error = case Error0 of
+ {_,erl_parse,_} ->
+ {error,Error0};
+ _ ->
+ {error,{loc(If),epp,Error0}}
+ end,
+ epp_reply(From, Error),
+ wait_req_skip(St, ['if'])
+ end;
scan_if(_Toks, If, From, St) ->
- epp_reply(From, {error,{loc(If),epp,{'NYI','if'}}}),
+ epp_reply(From, {error,{loc(If),epp,{bad,'if'}}}),
wait_req_skip(St, ['if']).
+eval_if(Toks0, St) ->
+ Toks = expand_macros(Toks0, St),
+ Es1 = case erl_parse:parse_exprs(Toks) of
+ {ok,Es0} -> Es0;
+ {error,E} -> throw(E)
+ end,
+ Es = rewrite_expr(Es1, St),
+ assert_guard_expr(Es),
+ Bs = erl_eval:new_bindings(),
+ LocalFun = fun(_Name, _Args) ->
+ error(badarg)
+ end,
+ try erl_eval:exprs(Es, Bs, {value,LocalFun}) of
+ {value,Res,_} ->
+ Res
+ catch
+ _:_ ->
+ false
+ end.
+
+assert_guard_expr([E0]) ->
+ E = rewrite_expr(E0, none),
+ case erl_lint:is_guard_expr(E) of
+ false ->
+ throw({bad,'if'});
+ true ->
+ ok
+ end;
+assert_guard_expr(_) ->
+ throw({bad,'if'}).
+
+%% Dual-purpose rewriting function. When the second argument is
+%% an #epp{} record, calls to defined(Symbol) will be evaluated.
+%% When the second argument is 'none', legal calls to our built-in
+%% functions are eliminated in order to turn the expression into
+%% a legal guard expression.
+
+rewrite_expr({call,_,{atom,_,defined},[N0]}, #epp{macs=Macs}) ->
+ %% Evaluate defined(Symbol).
+ N = case N0 of
+ {var,_,N1} -> N1;
+ {atom,_,N1} -> N1;
+ _ -> throw({bad,'if'})
+ end,
+ {atom,0,maps:is_key(N, Macs)};
+rewrite_expr({call,_,{atom,_,Name},As0}, none) ->
+ As = rewrite_expr(As0, none),
+ Arity = length(As),
+ case erl_internal:bif(Name, Arity) andalso
+ not erl_internal:guard_bif(Name, Arity) of
+ false ->
+ %% A guard BIF, an -if built-in, or an unknown function.
+ %% Eliminate the call so that erl_lint will not complain.
+ %% The call might fail later at evaluation time.
+ to_conses(As);
+ true ->
+ %% An auto-imported BIF (not guard BIF). Not allowed.
+ throw({bad,'if'})
+ end;
+rewrite_expr([H|T], St) ->
+ [rewrite_expr(H, St)|rewrite_expr(T, St)];
+rewrite_expr(Tuple, St) when is_tuple(Tuple) ->
+ list_to_tuple(rewrite_expr(tuple_to_list(Tuple), St));
+rewrite_expr(Other, _) ->
+ Other.
+
+to_conses([H|T]) ->
+ {cons,0,H,to_conses(T)};
+to_conses([]) ->
+ {nil,0}.
+
%% scan_elif(Tokens, EndifToken, From, EppState)
%% Handle the conditional parsing of a file.
%% Report a badly formed if test and then treat as false macro.
scan_elif(_Toks, Elif, From, St) ->
- epp_reply(From, {error,{loc(Elif),epp,{'NYI','elif'}}}),
- wait_req_scan(St).
+ case St#epp.istk of
+ ['else'|Cis] ->
+ epp_reply(From, {error,{loc(Elif),
+ epp,{illegal,"unbalanced",'elif'}}}),
+ wait_req_skip(St#epp{istk=Cis}, ['else']);
+ [_I|Cis] ->
+ skip_toks(From, St#epp{istk=Cis}, ['elif']);
+ [] ->
+ epp_reply(From, {error,{loc(Elif),epp,
+ {illegal,"unbalanced",elif}}}),
+ wait_req_scan(St)
+ end.
%% scan_endif(Tokens, EndifToken, From, EppState)
%% If we are in an if body then exit it, else report an error.
@@ -1155,6 +1262,8 @@ skip_toks(From, St, [I|Sis]) ->
skip_toks(From, St#epp{location=Cl}, ['if',I|Sis]);
{ok,[{'-',_Lh},{atom,_Le,'else'}=Else|_Toks],Cl}->
skip_else(Else, From, St#epp{location=Cl}, [I|Sis]);
+ {ok,[{'-',_Lh},{atom,_Le,'elif'}=Elif|Toks],Cl}->
+ skip_elif(Toks, Elif, From, St#epp{location=Cl}, [I|Sis]);
{ok,[{'-',_Lh},{atom,_Le,endif}|_Toks],Cl} ->
skip_toks(From, St#epp{location=Cl}, Sis);
{ok,_Toks,Cl} ->
@@ -1185,30 +1294,40 @@ skip_toks(From, St, []) ->
skip_else(Else, From, St, ['else'|Sis]) ->
epp_reply(From, {error,{loc(Else),epp,{illegal,"repeated",'else'}}}),
wait_req_skip(St, ['else'|Sis]);
+skip_else(_Else, From, St, ['elif'|Sis]) ->
+ skip_toks(From, St, ['else'|Sis]);
skip_else(_Else, From, St, [_I]) ->
scan_toks(From, St#epp{istk=['else'|St#epp.istk]});
skip_else(_Else, From, St, Sis) ->
skip_toks(From, St, Sis).
+skip_elif(_Toks, Elif, From, St, ['else'|_]=Sis) ->
+ epp_reply(From, {error,{loc(Elif),epp,elif_after_else}}),
+ wait_req_skip(St, Sis);
+skip_elif(Toks, Elif, From, St, [_I]) ->
+ scan_if(Toks, Elif, From, St);
+skip_elif(_Toks, _Elif, From, St, Sis) ->
+ skip_toks(From, St, Sis).
+
%% macro_pars(Tokens, ArgStack)
%% macro_expansion(Tokens, Anno)
%% Extract the macro parameters and the expansion from a macro definition.
-macro_pars([{')',_Lp}, {',',Ld}|Ex], Args) ->
- {ok, {lists:reverse(Args), macro_expansion(Ex, Ld)}};
-macro_pars([{var,_,Name}, {')',_Lp}, {',',Ld}|Ex], Args) ->
+macro_pars([{')',_Lp}, {',',_Ld}=Comma|Ex], Args) ->
+ {ok, {lists:reverse(Args), macro_expansion(Ex, Comma)}};
+macro_pars([{var,_,Name}, {')',_Lp}, {',',_Ld}=Comma|Ex], Args) ->
false = lists:member(Name, Args), %Prolog is nice
- {ok, {lists:reverse([Name|Args]), macro_expansion(Ex, Ld)}};
+ {ok, {lists:reverse([Name|Args]), macro_expansion(Ex, Comma)}};
macro_pars([{var,_L,Name}, {',',_}|Ts], Args) ->
false = lists:member(Name, Args),
macro_pars(Ts, [Name|Args]).
-macro_expansion([{')',_Lp},{dot,_Ld}], _Anno0) -> [];
-macro_expansion([{dot,_}=Dot], _Anno0) ->
+macro_expansion([{')',_Lp},{dot,_Ld}], _T0) -> [];
+macro_expansion([{dot,_}=Dot], _T0) ->
throw({error,loc(Dot),missing_parenthesis});
-macro_expansion([T|Ts], _Anno0) ->
+macro_expansion([T|Ts], _T0) ->
[T|macro_expansion(Ts, T)];
-macro_expansion([], Anno0) -> throw({error,loc(Anno0),premature_end}).
+macro_expansion([], T0) -> throw({error,loc(T0),premature_end}).
%% expand_macros(Tokens, St)
%% expand_macro(Tokens, MacroToken, RestTokens)
diff --git a/lib/stdlib/src/erl_compile.erl b/lib/stdlib/src/erl_compile.erl
index 18d7548fdc..f781312ca2 100644
--- a/lib/stdlib/src/erl_compile.erl
+++ b/lib/stdlib/src/erl_compile.erl
@@ -188,6 +188,8 @@ parse_dep_option("", T) ->
{[makedep,{makedep_output,standard_io}],T};
parse_dep_option("D", T) ->
{[makedep],T};
+parse_dep_option("MD", T) ->
+ {[makedep_side_effect],T};
parse_dep_option("F"++Opt, T0) ->
{File,T} = get_option("MF", Opt, T0),
{[makedep,{makedep_output,File}],T};
@@ -221,6 +223,7 @@ usage() ->
"the dependencies"},
{"-MP","add a phony target for each dependency"},
{"-MD","same as -M -MT file (with default 'file')"},
+ {"-MMD","generate dependencies as a side-effect"},
{"-o name","name output directory or file"},
{"-pa path","add path to the front of Erlang's code path"},
{"-pz path","add path to the end of Erlang's code path"},
diff --git a/lib/stdlib/src/erl_error.erl b/lib/stdlib/src/erl_error.erl
new file mode 100644
index 0000000000..fdcb9e824c
--- /dev/null
+++ b/lib/stdlib/src/erl_error.erl
@@ -0,0 +1,421 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(erl_error).
+
+-export([format_exception/6, format_exception/7,
+ format_stacktrace/4, format_stacktrace/5,
+ format_call/4, format_call/5, format_fun/1, format_fun/2]).
+
+%%% Formatting of exceptions, mfa:s and funs.
+
+%% -> iolist() (no \n at end)
+%% I is the current column, starting from 1 (it will be used
+%% as indentation whenever newline has been inserted);
+%% Class, Reason and StackTrace are the exception;
+%% FormatFun = fun(Term, I) -> iolist() formats terms;
+%% StackFun = fun(Mod, Fun, Arity) -> boolean() is used for trimming the
+%% end of the stack (typically calls to erl_eval are skipped).
+format_exception(I, Class, Reason, StackTrace, StackFun, FormatFun) ->
+ format_exception(I, Class, Reason, StackTrace, StackFun, FormatFun,
+ latin1).
+
+%% -> iolist() | unicode:charlist() (no \n at end)
+%% FormatFun = fun(Term, I) -> iolist() | unicode:charlist().
+format_exception(I, Class, Reason, StackTrace, StackFun, FormatFun, Encoding)
+ when is_integer(I), I >= 1, is_function(StackFun, 3),
+ is_function(FormatFun, 2) ->
+ S = n_spaces(I-1),
+ {Term,Trace1,Trace} = analyze_exception(Class, Reason, StackTrace),
+ Expl0 = explain_reason(Term, Class, Trace1, FormatFun, S, Encoding),
+ FormatString = case Encoding of
+ latin1 -> "~s~s";
+ _ -> "~s~ts"
+ end,
+ Expl = io_lib:fwrite(FormatString, [exited(Class), Expl0]),
+ case format_stacktrace1(S, Trace, FormatFun, StackFun, Encoding) of
+ [] -> Expl;
+ Stack -> [Expl, $\n, Stack]
+ end.
+
+%% -> iolist() (no \n at end)
+format_stacktrace(I, StackTrace, StackFun, FormatFun) ->
+ format_stacktrace(I, StackTrace, StackFun, FormatFun, latin1).
+
+%% -> iolist() | unicode:charlist() (no \n at end)
+format_stacktrace(I, StackTrace, StackFun, FormatFun, Encoding)
+ when is_integer(I), I >= 1, is_function(StackFun, 3),
+ is_function(FormatFun, 2) ->
+ S = n_spaces(I-1),
+ format_stacktrace1(S, StackTrace, FormatFun, StackFun, Encoding).
+
+%% -> iolist() (no \n at end)
+format_call(I, ForMForFun, As, FormatFun) ->
+ format_call(I, ForMForFun, As, FormatFun, latin1).
+
+%% -> iolist() | unicode:charlist() (no \n at end)
+format_call(I, ForMForFun, As, FormatFun, Enc)
+ when is_integer(I), I >= 1, is_list(As), is_function(FormatFun, 2) ->
+ format_call("", n_spaces(I-1), ForMForFun, As, FormatFun, Enc).
+
+%% -> iolist() (no \n at end)
+format_fun(Fun) ->
+ format_fun(Fun, latin1).
+
+%% -> iolist() (no \n at end)
+format_fun(Fun, Enc) when is_function(Fun) ->
+ {module, M} = erlang:fun_info(Fun, module),
+ {name, F} = erlang:fun_info(Fun, name),
+ {arity, A} = erlang:fun_info(Fun, arity),
+ case erlang:fun_info(Fun, type) of
+ {type, local} when F =:= "" ->
+ io_lib:fwrite(<<"~w">>, [Fun]);
+ {type, local} when M =:= erl_eval ->
+ io_lib:fwrite(<<"interpreted function with arity ~w">>, [A]);
+ {type, local} ->
+ mfa_to_string(M, F, A, Enc);
+ {type, external} ->
+ mfa_to_string(M, F, A, Enc)
+ end.
+
+analyze_exception(error, Term, Stack) ->
+ case {is_stacktrace(Stack), Stack, Term} of
+ {true, [{_,_,As,_}=MFAL|MFAs], function_clause} when is_list(As) ->
+ {Term,[MFAL],MFAs};
+ {true, [{shell,F,A,_}], function_clause} when is_integer(A) ->
+ {Term, [{F,A}], []};
+ {true, [{_,_,_,_}=MFAL|MFAs], undef} ->
+ {Term,[MFAL],MFAs};
+ {true, _, _} ->
+ {Term,[],Stack};
+ {false, _, _} ->
+ {{Term,Stack},[],[]}
+ end;
+analyze_exception(_Class, Term, Stack) ->
+ case is_stacktrace(Stack) of
+ true ->
+ {Term,[],Stack};
+ false ->
+ {{Term,Stack},[],[]}
+ end.
+
+is_stacktrace([]) ->
+ true;
+is_stacktrace([{M,F,A,I}|Fs])
+ when is_atom(M), is_atom(F), is_integer(A), is_list(I) ->
+ is_stacktrace(Fs);
+is_stacktrace([{M,F,As,I}|Fs])
+ when is_atom(M), is_atom(F), length(As) >= 0, is_list(I) ->
+ is_stacktrace(Fs);
+is_stacktrace(_) ->
+ false.
+
+%% ERTS exit codes (some of them are also returned by erl_eval):
+explain_reason(badarg, error, [], _PF, _S, _Enc) ->
+ <<"bad argument">>;
+explain_reason({badarg,V}, error=Cl, [], PF, S, _Enc) -> % orelse, andalso
+ format_value(V, <<"bad argument: ">>, Cl, PF, S);
+explain_reason(badarith, error, [], _PF, _S, _Enc) ->
+ <<"an error occurred when evaluating an arithmetic expression">>;
+explain_reason({badarity,{Fun,As}}, error, [], _PF, _S, Enc)
+ when is_function(Fun) ->
+ %% Only the arity is displayed, not the arguments As.
+ io_lib:fwrite(<<"~ts called with ~s">>,
+ [format_fun(Fun, Enc), argss(length(As))]);
+explain_reason({badfun,Term}, error=Cl, [], PF, S, _Enc) ->
+ format_value(Term, <<"bad function ">>, Cl, PF, S);
+explain_reason({badmatch,Term}, error=Cl, [], PF, S, _Enc) ->
+ Str = <<"no match of right hand side value ">>,
+ format_value(Term, Str, Cl, PF, S);
+explain_reason({case_clause,V}, error=Cl, [], PF, S, _Enc) ->
+ %% "there is no case clause with a true guard sequence and a
+ %% pattern matching..."
+ format_value(V, <<"no case clause matching ">>, Cl, PF, S);
+explain_reason(function_clause, error, [{F,A}], _PF, _S, _Enc) ->
+ %% Shell commands
+ FAs = io_lib:fwrite(<<"~w/~w">>, [F, A]),
+ [<<"no function clause matching call to ">> | FAs];
+explain_reason(function_clause, error=Cl, [{M,F,As,Loc}], PF, S, Enc) ->
+ Str = <<"no function clause matching ">>,
+ [format_errstr_call(Str, Cl, {M,F}, As, PF, S, Enc),$\s|location(Loc)];
+explain_reason(if_clause, error, [], _PF, _S, _Enc) ->
+ <<"no true branch found when evaluating an if expression">>;
+explain_reason(noproc, error, [], _PF, _S, _Enc) ->
+ <<"no such process or port">>;
+explain_reason(notalive, error, [], _PF, _S, _Enc) ->
+ <<"the node cannot be part of a distributed system">>;
+explain_reason(system_limit, error, [], _PF, _S, _Enc) ->
+ <<"a system limit has been reached">>;
+explain_reason(timeout_value, error, [], _PF, _S, _Enc) ->
+ <<"bad receive timeout value">>;
+explain_reason({try_clause,V}, error=Cl, [], PF, S, _Enc) ->
+ %% "there is no try clause with a true guard sequence and a
+ %% pattern matching..."
+ format_value(V, <<"no try clause matching ">>, Cl, PF, S);
+explain_reason(undef, error, [{M,F,A,_}], _PF, _S, Enc) ->
+ %% Only the arity is displayed, not the arguments, if there are any.
+ io_lib:fwrite(<<"undefined function ~ts">>,
+ [mfa_to_string(M, F, n_args(A), Enc)]);
+explain_reason({shell_undef,F,A,_}, error, [], _PF, _S, Enc) ->
+ %% Give nicer reports for undefined shell functions
+ %% (but not when the user actively calls shell_default:F(...)).
+ FS = to_string(F, Enc),
+ io_lib:fwrite(<<"undefined shell command ~ts/~w">>, [FS, n_args(A)]);
+%% Exit codes returned by erl_eval only:
+explain_reason({argument_limit,_Fun}, error, [], _PF, _S, _Enc) ->
+ io_lib:fwrite(<<"limit of number of arguments to interpreted function"
+ " exceeded">>, []);
+explain_reason({bad_filter,V}, error=Cl, [], PF, S, _Enc) ->
+ format_value(V, <<"bad filter ">>, Cl, PF, S);
+explain_reason({bad_generator,V}, error=Cl, [], PF, S, _Enc) ->
+ format_value(V, <<"bad generator ">>, Cl, PF, S);
+explain_reason({unbound,V}, error, [], _PF, _S, _Enc) ->
+ io_lib:fwrite(<<"variable ~w is unbound">>, [V]);
+%% Exit codes local to the shell module (restricted shell):
+explain_reason({restricted_shell_bad_return, V}, exit=Cl, [], PF, S, _Enc) ->
+ Str = <<"restricted shell module returned bad value ">>,
+ format_value(V, Str, Cl, PF, S);
+explain_reason({restricted_shell_disallowed,{ForMF,As}},
+ exit=Cl, [], PF, S, Enc) ->
+ %% ForMF can be a fun, but not a shell fun.
+ Str = <<"restricted shell does not allow ">>,
+ format_errstr_call(Str, Cl, ForMF, As, PF, S, Enc);
+explain_reason(restricted_shell_started, exit, [], _PF, _S, _Enc) ->
+ <<"restricted shell starts now">>;
+explain_reason(restricted_shell_stopped, exit, [], _PF, _S, _Enc) ->
+ <<"restricted shell stopped">>;
+%% Other exit code:
+explain_reason(Reason, Class, [], PF, S, _Enc) ->
+ PF(Reason, (iolist_size(S)+1) + exited_size(Class)).
+
+n_args(A) when is_integer(A) ->
+ A;
+n_args(As) when is_list(As) ->
+ length(As).
+
+argss(0) ->
+ <<"no arguments">>;
+argss(1) ->
+ <<"one argument">>;
+argss(2) ->
+ <<"two arguments">>;
+argss(I) ->
+ io_lib:fwrite(<<"~w arguments">>, [I]).
+
+format_stacktrace1(S0, Stack0, PF, SF, Enc) ->
+ Stack1 = lists:dropwhile(fun({M,F,A,_}) -> SF(M, F, A)
+ end, lists:reverse(Stack0)),
+ S = [" " | S0],
+ Stack = lists:reverse(Stack1),
+ format_stacktrace2(S, Stack, 1, PF, Enc).
+
+format_stacktrace2(S, [{M,F,A,L}|Fs], N, PF, Enc) when is_integer(A) ->
+ [io_lib:fwrite(<<"~s~s ~ts ~ts">>,
+ [sep(N, S), origin(N, M, F, A),
+ mfa_to_string(M, F, A, Enc),
+ location(L)])
+ | format_stacktrace2(S, Fs, N + 1, PF, Enc)];
+format_stacktrace2(S, [{M,F,As,_}|Fs], N, PF, Enc) when is_list(As) ->
+ A = length(As),
+ CalledAs = [S,<<" called as ">>],
+ C = format_call("", CalledAs, {M,F}, As, PF, Enc),
+ [io_lib:fwrite(<<"~s~s ~ts\n~s~ts">>,
+ [sep(N, S), origin(N, M, F, A),
+ mfa_to_string(M, F, A, Enc),
+ CalledAs, C])
+ | format_stacktrace2(S, Fs, N + 1, PF, Enc)];
+format_stacktrace2(_S, [], _N, _PF, _Enc) ->
+ "".
+
+location(L) ->
+ File = proplists:get_value(file, L),
+ Line = proplists:get_value(line, L),
+ if
+ File =/= undefined, Line =/= undefined ->
+ io_lib:format("(~ts, line ~w)", [File, Line]);
+ true ->
+ ""
+ end.
+
+sep(1, S) -> S;
+sep(_, S) -> [$\n | S].
+
+origin(1, M, F, A) ->
+ case is_op({M, F}, n_args(A)) of
+ {yes, F} -> <<"in operator ">>;
+ no -> <<"in function ">>
+ end;
+origin(_N, _M, _F, _A) ->
+ <<"in call from">>.
+
+format_errstr_call(ErrStr, Class, ForMForFun, As, PF, Pre0, Enc) ->
+ Pre1 = [Pre0 | n_spaces(exited_size(Class))],
+ format_call(ErrStr, Pre1, ForMForFun, As, PF, Enc).
+
+format_call(ErrStr, Pre1, ForMForFun, As, PF, Enc) ->
+ Arity = length(As),
+ [ErrStr |
+ case is_op(ForMForFun, Arity) of
+ {yes,Op} ->
+ format_op(ErrStr, Pre1, Op, As, PF, Enc);
+ no ->
+ MFs = mf_to_string(ForMForFun, Arity, Enc),
+ I1 = string:length([Pre1,ErrStr|MFs]),
+ S1 = pp_arguments(PF, As, I1, Enc),
+ S2 = pp_arguments(PF, As, string:length([Pre1|MFs]), Enc),
+ Long = count_nl(pp_arguments(PF, [a2345,b2345], I1, Enc)) > 0,
+ case Long or (count_nl(S2) < count_nl(S1)) of
+ true ->
+ [$\n, Pre1, MFs, S2];
+ false ->
+ [MFs, S1]
+ end
+ end].
+
+format_op(ErrStr, Pre, Op, [A1], PF, _Enc) ->
+ OpS = io_lib:fwrite(<<"~s ">>, [Op]),
+ I1 = iolist_size([ErrStr,Pre,OpS]),
+ [OpS | PF(A1, I1+1)];
+format_op(ErrStr, Pre, Op, [A1, A2], PF, Enc) ->
+ I1 = iolist_size([ErrStr,Pre]),
+ S1 = PF(A1, I1+1),
+ S2 = PF(A2, I1+1),
+ OpS = atom_to_list(Op),
+ Pre1 = [$\n | n_spaces(I1)],
+ case count_nl(S1) > 0 of
+ true ->
+ [S1,Pre1,OpS,Pre1|S2];
+ false ->
+ OpS2 = io_lib:fwrite(<<" ~s ">>, [Op]),
+ Size1 = iolist_size([ErrStr,Pre|OpS2]),
+ {Size2,S1_2} = size(Enc, S1),
+ S2_2 = PF(A2, Size1+Size2+1),
+ case count_nl(S2) < count_nl(S2_2) of
+ true ->
+ [S1_2,Pre1,OpS,Pre1|S2];
+ false ->
+ [S1_2,OpS2|S2_2]
+ end
+ end.
+
+pp_arguments(PF, As, I, Enc) ->
+ case {As, printable_list(Enc, As)} of
+ {[Int | T], true} ->
+ L = integer_to_list(Int),
+ Ll = length(L),
+ A = list_to_atom(lists:duplicate(Ll, $a)),
+ S0 = unicode:characters_to_list(PF([A | T], I+1), Enc),
+ brackets_to_parens([$[,L,string:slice(S0, 1+Ll)], Enc);
+ _ ->
+ brackets_to_parens(PF(As, I+1), Enc)
+ end.
+
+brackets_to_parens(S, Enc) ->
+ B = unicode:characters_to_binary(S, Enc),
+ Sz = byte_size(B) - 2,
+ <<$[,R:Sz/binary,$]>> = B,
+ [$(,R,$)].
+
+printable_list(latin1, As) ->
+ io_lib:printable_latin1_list(As);
+printable_list(_, As) ->
+ io_lib:printable_list(As).
+
+mfa_to_string(M, F, A, Enc) ->
+ io_lib:fwrite(<<"~ts/~w">>, [mf_to_string({M, F}, A, Enc), A]).
+
+mf_to_string({M, F}, A, Enc) ->
+ case erl_internal:bif(M, F, A) of
+ true ->
+ io_lib:fwrite(<<"~w">>, [F]);
+ false ->
+ case is_op({M, F}, A) of
+ {yes, '/'} ->
+ io_lib:fwrite(<<"~w">>, [F]);
+ {yes, F} ->
+ atom_to_list(F);
+ no ->
+ FS = to_string(F, Enc),
+ io_lib:fwrite(<<"~w:~ts">>, [M, FS])
+ end
+ end;
+mf_to_string(Fun, _A, Enc) when is_function(Fun) ->
+ format_fun(Fun, Enc);
+mf_to_string(F, _A, Enc) ->
+ FS = to_string(F, Enc),
+ io_lib:fwrite(<<"~ts">>, [FS]).
+
+format_value(V, ErrStr, Class, PF, S) ->
+ Pre1Sz = exited_size(Class),
+ S1 = PF(V, Pre1Sz + iolist_size([S, ErrStr])+1),
+ [ErrStr | case count_nl(S1) of
+ N1 when N1 > 1 ->
+ S2 = PF(V, iolist_size(S) + 1 + Pre1Sz),
+ case count_nl(S2) < N1 of
+ true ->
+ [$\n, S, n_spaces(Pre1Sz) | S2];
+ false ->
+ S1
+ end;
+ _ ->
+ S1
+ end].
+
+%% Handles deep lists, but not all iolists.
+count_nl([E | Es]) ->
+ count_nl(E) + count_nl(Es);
+count_nl($\n) ->
+ 1;
+count_nl(Bin) when is_binary(Bin) ->
+ count_nl(binary_to_list(Bin));
+count_nl(_) ->
+ 0.
+
+n_spaces(N) ->
+ lists:duplicate(N, $\s).
+
+is_op(ForMForFun, A) ->
+ try
+ {erlang,F} = ForMForFun,
+ _ = erl_internal:op_type(F, A),
+ {yes,F}
+ catch error:_ -> no
+ end.
+
+exited_size(Class) ->
+ iolist_size(exited(Class)).
+
+exited(error) ->
+ <<"exception error: ">>;
+exited(exit) ->
+ <<"exception exit: ">>;
+exited(throw) ->
+ <<"exception throw: ">>.
+
+to_string(A, latin1) ->
+ io_lib:write_atom_as_latin1(A);
+to_string(A, _) ->
+ io_lib:write_atom(A).
+
+size(latin1, S) ->
+ {iolist_size(S),S};
+size(_, S0) ->
+ S = unicode:characters_to_list(S0, unicode),
+ true = is_list(S),
+ {string:length(S),S}.
diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl
index eafee346eb..2066b2f60f 100644
--- a/lib/stdlib/src/erl_eval.erl
+++ b/lib/stdlib/src/erl_eval.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,8 +27,9 @@
-export([exprs/2,exprs/3,exprs/4,expr/2,expr/3,expr/4,expr/5,
expr_list/2,expr_list/3,expr_list/4]).
-export([new_bindings/0,bindings/1,binding/2,add_binding/3,del_binding/2]).
-
--export([is_constant_expr/1, partial_eval/1]).
+-export([extended_parse_exprs/1, extended_parse_term/1,
+ subst_values_for_vars/2]).
+-export([is_constant_expr/1, partial_eval/1, eval_str/1]).
%% Is used by standalone Erlang (escript).
%% Also used by shell.erl.
@@ -69,6 +70,9 @@
-type(non_local_function_handler() :: {value, nlfun_handler()}
| none).
+-define(STACKTRACE,
+ element(2, erlang:process_info(self(), current_stacktrace))).
+
%% exprs(ExpressionSeq, Bindings)
%% exprs(ExpressionSeq, Bindings, LocalFuncHandler)
%% exprs(ExpressionSeq, Bindings, LocalFuncHandler, ExternalFuncHandler)
@@ -90,7 +94,7 @@ exprs(Exprs, Bs) ->
ok ->
exprs(Exprs, Bs, none, none, none);
{error,{_Line,_Mod,Error}} ->
- erlang:raise(error, Error, [{?MODULE,exprs,2}])
+ erlang:raise(error, Error, ?STACKTRACE)
end.
-spec(exprs(Expressions, Bindings, LocalFunctionHandler) ->
@@ -141,7 +145,7 @@ expr(E, Bs) ->
ok ->
expr(E, Bs, none, none, none);
{error,{_Line,_Mod,Error}} ->
- erlang:raise(error, Error, [{?MODULE,expr,2}])
+ erlang:raise(error, Error, ?STACKTRACE)
end.
-spec(expr(Expression, Bindings, LocalFunctionHandler) ->
@@ -182,7 +186,7 @@ check_command(Es, Bs) ->
fun_data(F) when is_function(F) ->
case erlang:fun_info(F, module) of
- {module,erl_eval} ->
+ {module,?MODULE} ->
case erlang:fun_info(F, env) of
{env,[{FBs,_FLf,_FEf,FCs}]} ->
{fun_data,FBs,FCs};
@@ -209,8 +213,8 @@ expr({var,_,V}, Bs, _Lf, _Ef, RBs) ->
case binding(V, Bs) of
{value,Val} ->
ret_expr(Val, Bs, RBs);
- unbound -> % Should not happen.
- erlang:raise(error, {unbound,V}, stacktrace())
+ unbound -> % Cannot not happen if checked by erl_lint
+ erlang:raise(error, {unbound,V}, ?STACKTRACE)
end;
expr({char,_,C}, Bs, _Lf, _Ef, RBs) ->
ret_expr(C, Bs, RBs);
@@ -236,13 +240,13 @@ expr({tuple,_,Es}, Bs0, Lf, Ef, RBs) ->
{Vs,Bs} = expr_list(Es, Bs0, Lf, Ef),
ret_expr(list_to_tuple(Vs), Bs, RBs);
expr({record_field,_,_,Name,_}, _Bs, _Lf, _Ef, _RBs) ->
- erlang:raise(error, {undef_record,Name}, stacktrace());
+ erlang:raise(error, {undef_record,Name}, ?STACKTRACE);
expr({record_index,_,Name,_}, _Bs, _Lf, _Ef, _RBs) ->
- erlang:raise(error, {undef_record,Name}, stacktrace());
+ erlang:raise(error, {undef_record,Name}, ?STACKTRACE);
expr({record,_,Name,_}, _Bs, _Lf, _Ef, _RBs) ->
- erlang:raise(error, {undef_record,Name}, stacktrace());
+ erlang:raise(error, {undef_record,Name}, ?STACKTRACE);
expr({record,_,_,Name,_}, _Bs, _Lf, _Ef, _RBs) ->
- erlang:raise(error, {undef_record,Name}, stacktrace());
+ erlang:raise(error, {undef_record,Name}, ?STACKTRACE);
%% map
expr({map,_,Binding,Es}, Bs0, Lf, Ef, RBs) ->
@@ -281,7 +285,7 @@ expr({'fun',_Line,{function,Mod0,Name0,Arity0}}, Bs0, Lf, Ef, RBs) ->
ret_expr(F, Bs, RBs);
expr({'fun',_Line,{function,Name,Arity}}, _Bs0, _Lf, _Ef, _RBs) -> % R8
%% Don't know what to do...
- erlang:raise(error, undef, [{erl_eval,Name,Arity}|stacktrace()]);
+ erlang:raise(error, undef, [{?MODULE,Name,Arity}|?STACKTRACE]);
expr({'fun',Line,{clauses,Cs}} = Ex, Bs, Lf, Ef, RBs) ->
%% Save only used variables in the function environment.
%% {value,L,V} are hidden while lint finds used variables.
@@ -325,8 +329,9 @@ expr({'fun',Line,{clauses,Cs}} = Ex, Bs, Lf, Ef, RBs) ->
20 -> fun (A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T) ->
eval_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T], Info) end;
_Other ->
- erlang:raise(error, {'argument_limit',{'fun',Line,Cs}},
- stacktrace())
+ L = erl_anno:location(Line),
+ erlang:raise(error, {'argument_limit',{'fun',L,to_terms(Cs)}},
+ ?STACKTRACE)
end,
ret_expr(F, Bs, RBs);
expr({named_fun,Line,Name,Cs} = Ex, Bs, Lf, Ef, RBs) ->
@@ -377,8 +382,10 @@ expr({named_fun,Line,Name,Cs} = Ex, Bs, Lf, Ef, RBs) ->
eval_named_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T],
RF, Info) end;
_Other ->
- erlang:raise(error, {'argument_limit',{named_fun,Line,Name,Cs}},
- stacktrace())
+ L = erl_anno:location(Line),
+ erlang:raise(error, {'argument_limit',
+ {named_fun,L,Name,to_terms(Cs)}},
+ ?STACKTRACE)
end,
ret_expr(F, Bs, RBs);
expr({call,_,{remote,_,{atom,_,qlc},{atom,_,q}},[{lc,_,_E,_Qs}=LC | As0]},
@@ -422,25 +429,28 @@ expr({call,_,Func0,As0}, Bs0, Lf, Ef, RBs) -> % function or {Mod,Fun}
{As,Bs2} = expr_list(As0, Bs1, Lf, Ef),
case Func of
{M,F} when is_atom(M), is_atom(F) ->
- erlang:raise(error, {badfun,Func}, stacktrace());
+ erlang:raise(error, {badfun,Func}, ?STACKTRACE);
_ ->
do_apply(Func, As, Bs2, Ef, RBs)
end;
expr({'catch',_,Expr}, Bs0, Lf, Ef, RBs) ->
- Ref = make_ref(),
- case catch {Ref,expr(Expr, Bs0, Lf, Ef, none)} of
- {Ref,{value,V,Bs}} -> % Nothing was thrown (guaranteed).
- ret_expr(V, Bs, RBs);
- Other ->
- ret_expr(Other, Bs0, RBs)
+ try expr(Expr, Bs0, Lf, Ef, none) of
+ {value,V,Bs} ->
+ ret_expr(V, Bs, RBs)
+ catch
+ throw:Term ->
+ ret_expr(Term, Bs0, RBs);
+ exit:Reason ->
+ ret_expr({'EXIT',Reason}, Bs0, RBs);
+ error:Reason:Stacktrace ->
+ ret_expr({'EXIT',{Reason,Stacktrace}}, Bs0, RBs)
end;
expr({match,_,Lhs,Rhs0}, Bs0, Lf, Ef, RBs) ->
{value,Rhs,Bs1} = expr(Rhs0, Bs0, Lf, Ef, none),
case match(Lhs, Rhs, Bs1) of
{match,Bs} ->
ret_expr(Rhs, Bs, RBs);
- nomatch ->
- erlang:raise(error, {badmatch,Rhs}, stacktrace())
+ nomatch -> erlang:raise(error, {badmatch,Rhs}, ?STACKTRACE)
end;
expr({op,_,Op,A0}, Bs0, Lf, Ef, RBs) ->
{value,A,Bs} = expr(A0, Bs0, Lf, Ef, none),
@@ -452,7 +462,7 @@ expr({op,_,'andalso',L0,R0}, Bs0, Lf, Ef, RBs) ->
{value,R,_} = expr(R0, Bs1, Lf, Ef, none),
R;
false -> false;
- _ -> erlang:raise(error, {badarg,L}, stacktrace())
+ _ -> erlang:raise(error, {badarg,L}, ?STACKTRACE)
end,
ret_expr(V, Bs1, RBs);
expr({op,_,'orelse',L0,R0}, Bs0, Lf, Ef, RBs) ->
@@ -462,7 +472,7 @@ expr({op,_,'orelse',L0,R0}, Bs0, Lf, Ef, RBs) ->
false ->
{value,R,_} = expr(R0, Bs1, Lf, Ef, none),
R;
- _ -> erlang:raise(error, {badarg,L}, stacktrace())
+ _ -> erlang:raise(error, {badarg,L}, ?STACKTRACE)
end,
ret_expr(V, Bs1, RBs);
expr({op,_,Op,L0,R0}, Bs0, Lf, Ef, RBs) ->
@@ -474,7 +484,7 @@ expr({bin,_,Fs}, Bs0, Lf, Ef, RBs) ->
{value,V,Bs} = eval_bits:expr_grp(Fs, Bs0, EvalFun),
ret_expr(V, Bs, RBs);
expr({remote,_,_,_}, _Bs, _Lf, _Ef, _RBs) ->
- erlang:raise(error, {badexpr,':'}, stacktrace());
+ erlang:raise(error, {badexpr,':'}, ?STACKTRACE);
expr({value,_,Val}, Bs, _Lf, _Ef, RBs) -> % Special case straight values.
ret_expr(Val, Bs, RBs).
@@ -570,7 +580,7 @@ local_func(Func, As, _Bs, {M,F,Eas}, _Ef, RBs) ->
local_func2(apply(M, F, [Func,As|Eas]), RBs);
%% Default unknown function handler to undefined function.
local_func(Func, As0, _Bs0, none, _Ef, _RBs) ->
- erlang:raise(error, undef, [{erl_eval,Func,length(As0)}|stacktrace()]).
+ erlang:raise(error, undef, [{?MODULE,Func,length(As0)}|?STACKTRACE]).
local_func2({value,V,Bs}, RBs) ->
ret_expr(V, Bs, RBs);
@@ -637,7 +647,7 @@ do_apply(Func, As, Bs0, Ef, RBs) ->
{{arity, Arity}, Arity} ->
eval_fun(FCs, As, FBs, FLf, FEf, NRBs);
_ ->
- erlang:raise(error, {badarity,{Func,As}},stacktrace())
+ erlang:raise(error, {badarity,{Func,As}},?STACKTRACE)
end;
{{env,[{FBs,FLf,FEf,FCs,FName}]},_} ->
NRBs = if
@@ -648,7 +658,7 @@ do_apply(Func, As, Bs0, Ef, RBs) ->
{{arity, Arity}, Arity} ->
eval_named_fun(FCs, As, FBs, FLf, FEf, FName, Func, NRBs);
_ ->
- erlang:raise(error, {badarity,{Func,As}},stacktrace())
+ erlang:raise(error, {badarity,{Func,As}},?STACKTRACE)
end;
{no_env,none} when RBs =:= value ->
%% Make tail recursive calls when possible.
@@ -730,7 +740,7 @@ eval_generate([V|Rest], P, Bs0, Lf, Ef, CompFun, Acc) ->
eval_generate([], _P, _Bs0, _Lf, _Ef, _CompFun, Acc) ->
Acc;
eval_generate(Term, _P, _Bs0, _Lf, _Ef, _CompFun, _Acc) ->
- erlang:raise(error, {bad_generator,Term}, stacktrace()).
+ erlang:raise(error, {bad_generator,Term}, ?STACKTRACE).
eval_b_generate(<<_/bitstring>>=Bin, P, Bs0, Lf, Ef, CompFun, Acc) ->
Mfun = match_fun(Bs0),
@@ -746,7 +756,7 @@ eval_b_generate(<<_/bitstring>>=Bin, P, Bs0, Lf, Ef, CompFun, Acc) ->
Acc
end;
eval_b_generate(Term, _P, _Bs0, _Lf, _Ef, _CompFun, _Acc) ->
- erlang:raise(error, {bad_generator,Term}, stacktrace()).
+ erlang:raise(error, {bad_generator,Term}, ?STACKTRACE).
eval_filter(F, Bs0, Lf, Ef, CompFun, Acc) ->
case erl_lint:is_guard_test(F) of
@@ -760,7 +770,7 @@ eval_filter(F, Bs0, Lf, Ef, CompFun, Acc) ->
{value,true,Bs1} -> CompFun(Bs1);
{value,false,_} -> Acc;
{value,V,_} ->
- erlang:raise(error, {bad_filter,V}, stacktrace())
+ erlang:raise(error, {bad_filter,V}, ?STACKTRACE)
end
end.
@@ -816,7 +826,7 @@ eval_fun([{clause,_,H,G,B}|Cs], As, Bs0, Lf, Ef, RBs) ->
end;
eval_fun([], As, _Bs, _Lf, _Ef, _RBs) ->
erlang:raise(error, function_clause,
- [{?MODULE,'-inside-an-interpreted-fun-',As}|stacktrace()]).
+ [{?MODULE,'-inside-an-interpreted-fun-',As}|?STACKTRACE]).
eval_named_fun(As, Fun, {Bs0,Lf,Ef,Cs,Name}) ->
@@ -836,7 +846,7 @@ eval_named_fun([{clause,_,H,G,B}|Cs], As, Bs0, Lf, Ef, Name, Fun, RBs) ->
end;
eval_named_fun([], As, _Bs, _Lf, _Ef, _Name, _Fun, _RBs) ->
erlang:raise(error, function_clause,
- [{?MODULE,'-inside-an-interpreted-fun-',As}|stacktrace()]).
+ [{?MODULE,'-inside-an-interpreted-fun-',As}|?STACKTRACE]).
%% expr_list(ExpressionList, Bindings)
@@ -894,13 +904,13 @@ if_clauses([{clause,_,[],G,B}|Cs], Bs, Lf, Ef, RBs) ->
false -> if_clauses(Cs, Bs, Lf, Ef, RBs)
end;
if_clauses([], _Bs, _Lf, _Ef, _RBs) ->
- erlang:raise(error, if_clause, stacktrace()).
+ erlang:raise(error, if_clause, ?STACKTRACE).
%% try_clauses(Body, CaseClauses, CatchClauses, AfterBody, Bindings,
%% LocalFuncHandler, ExtFuncHandler, RBs)
-%% When/if variable bindings between the different parts of a
-%% try-catch expression are introduced this will have to be rewritten.
+
try_clauses(B, Cases, Catches, AB, Bs, Lf, Ef, RBs) ->
+ check_stacktrace_vars(Catches, Bs),
try exprs(B, Bs, Lf, Ef, none) of
{value,V,Bs1} when Cases =:= [] ->
ret_expr(V, Bs1, RBs);
@@ -909,23 +919,18 @@ try_clauses(B, Cases, Catches, AB, Bs, Lf, Ef, RBs) ->
{B2,Bs2} ->
exprs(B2, Bs2, Lf, Ef, RBs);
nomatch ->
- erlang:raise(error, {try_clause,V}, stacktrace())
+ erlang:raise(error, {try_clause,V}, ?STACKTRACE)
end
catch
- Class:Reason when Catches =:= [] ->
- %% Rethrow
- erlang:raise(Class, Reason, stacktrace());
- Class:Reason ->
-%%% %% Set stacktrace
-%%% try erlang:raise(Class, Reason, stacktrace())
-%%% catch _:_ -> ok
-%%% end,
- V = {Class,Reason,erlang:get_stacktrace()},
- case match_clause(Catches, [V],Bs, Lf, Ef) of
+ Class:Reason:Stacktrace when Catches =:= [] ->
+ erlang:raise(Class, Reason, Stacktrace);
+ Class:Reason:Stacktrace ->
+ V = {Class,Reason,Stacktrace},
+ case match_clause(Catches, [V], Bs, Lf, Ef) of
{B2,Bs2} ->
exprs(B2, Bs2, Lf, Ef, RBs);
nomatch ->
- erlang:raise(Class, Reason, stacktrace())
+ erlang:raise(Class, Reason, Stacktrace)
end
after
if AB =:= [] ->
@@ -935,6 +940,23 @@ try_clauses(B, Cases, Catches, AB, Bs, Lf, Ef, RBs) ->
end
end.
+check_stacktrace_vars([{clause,_,[{tuple,_,[_,_,STV]}],_,_}|Cs], Bs) ->
+ case STV of
+ {var,_,V} ->
+ case binding(V, Bs) of
+ {value, _} ->
+ erlang:raise(error, stacktrace_bound, ?STACKTRACE);
+ unbound ->
+ check_stacktrace_vars(Cs, Bs)
+ end;
+ _ ->
+ erlang:raise(error,
+ {illegal_stacktrace_variable,STV},
+ ?STACKTRACE)
+ end;
+check_stacktrace_vars([], _Bs) ->
+ ok.
+
%% case_clauses(Value, Clauses, Bindings, LocalFuncHandler, ExtFuncHandler,
%% RBs)
@@ -943,7 +965,7 @@ case_clauses(Val, Cs, Bs, Lf, Ef, RBs) ->
{B, Bs1} ->
exprs(B, Bs1, Lf, Ef, RBs);
nomatch ->
- erlang:raise(error, {case_clause,Val}, stacktrace())
+ erlang:raise(error, {case_clause,Val}, ?STACKTRACE)
end.
%%
@@ -1018,7 +1040,7 @@ guard0([G|Gs], Bs0, Lf, Ef) ->
{value,false,_} -> false
end;
false ->
- erlang:raise(error, guard_expr, stacktrace())
+ erlang:raise(error, guard_expr, ?STACKTRACE)
end;
guard0([], _Bs, _Lf, _Ef) -> true.
@@ -1073,7 +1095,7 @@ match(Pat, Term, Bs) ->
match(Pat, Term, Bs, BBs) ->
case catch match1(Pat, Term, Bs, BBs) of
invalid ->
- erlang:raise(error, {illegal_pattern,Pat}, stacktrace());
+ erlang:raise(error, {illegal_pattern,to_term(Pat)}, ?STACKTRACE);
Other ->
Other
end.
@@ -1254,7 +1276,7 @@ merge_bindings(Bs1, Bs2) ->
case orddict:find(Name, Bs) of
{ok,Val} -> Bs; %Already with SAME value
{ok,V1} ->
- erlang:raise(error, {badmatch,V1}, stacktrace());
+ erlang:raise(error, {badmatch,V1}, ?STACKTRACE);
error -> orddict:store(Name, Val, Bs)
end end,
Bs2, orddict:to_list(Bs1)).
@@ -1264,10 +1286,234 @@ merge_bindings(Bs1, Bs2) ->
%% fun (Name, Val, Bs) ->
%% case orddict:find(Name, Bs) of
%% {ok,Val} -> orddict:erase(Name, Bs);
-%% {ok,V1} -> erlang:raise(error,{badmatch,V1},stacktrace());
+%% {ok,V1} -> erlang:raise(error,{badmatch,V1},?STACKTRACE);
%% error -> Bs
%% end
%% end, Bs2, Bs1).
+
+to_terms(Abstrs) ->
+ [to_term(Abstr) || Abstr <- Abstrs].
+
+to_term(Abstr) ->
+ erl_parse:anno_to_term(Abstr).
+
+%% Substitute {value, A, Item} for {var, A, Var}, preserving A.
+%% {value, A, Item} is a shell/erl_eval convention, and for example
+%% the linter cannot handle it.
+
+-spec subst_values_for_vars(ExprList, Bindings) -> [term()] when
+ ExprList :: [erl_parse:abstract_expr()],
+ Bindings :: binding_struct().
+
+subst_values_for_vars({var, A, V}=Var, Bs) ->
+ case erl_eval:binding(V, Bs) of
+ {value, Value} ->
+ {value, A, Value};
+ unbound ->
+ Var
+ end;
+subst_values_for_vars(L, Bs) when is_list(L) ->
+ [subst_values_for_vars(E, Bs) || E <- L];
+subst_values_for_vars(T, Bs) when is_tuple(T) ->
+ list_to_tuple(subst_values_for_vars(tuple_to_list(T), Bs));
+subst_values_for_vars(T, _Bs) ->
+ T.
+
+%% `Tokens' is assumed to have been scanned with the 'text' option.
+%% The annotations of the returned expressions are locations.
+%%
+%% Can handle pids, ports, references, and external funs ("items").
+%% Known items are represented by variables in the erl_parse tree, and
+%% the items themselves are stored in the returned bindings.
+
+-spec extended_parse_exprs(Tokens) ->
+ {'ok', ExprList, Bindings} | {'error', ErrorInfo} when
+ Tokens :: [erl_scan:token()],
+ ExprList :: [erl_parse:abstract_expr()],
+ Bindings :: erl_eval:binding_struct(),
+ ErrorInfo :: erl_parse:error_info().
+
+extended_parse_exprs(Tokens) ->
+ Ts = tokens_fixup(Tokens),
+ case erl_parse:parse_exprs(Ts) of
+ {ok, Exprs0} ->
+ {Exprs, Bs} = expr_fixup(Exprs0),
+ {ok, reset_expr_anno(Exprs), Bs};
+ _ErrorInfo ->
+ erl_parse:parse_exprs(reset_token_anno(Ts))
+ end.
+
+tokens_fixup([]) -> [];
+tokens_fixup([T|Ts]=Ts0) ->
+ try token_fixup(Ts0) of
+ {NewT, NewTs} ->
+ [NewT|tokens_fixup(NewTs)]
+ catch
+ _:_ ->
+ [T|tokens_fixup(Ts)]
+ end.
+
+token_fixup(Ts) ->
+ {AnnoL, NewTs, FixupTag} = unscannable(Ts),
+ String = lists:append([erl_anno:text(A) || A <- AnnoL]),
+ _ = (fixup_fun(FixupTag))(String),
+ NewAnno = erl_anno:set_text(fixup_text(FixupTag), hd(AnnoL)),
+ {{string, NewAnno, String}, NewTs}.
+
+unscannable([{'#', A1}, {var, A2, 'Fun'}, {'<', A3}, {atom, A4, _},
+ {'.', A5}, {float, A6, _}, {'>', A7}|Ts]) ->
+ {[A1, A2, A3, A4, A5, A6, A7], Ts, function};
+unscannable([{'#', A1}, {var, A2, 'Fun'}, {'<', A3}, {atom, A4, _},
+ {'.', A5}, {atom, A6, _}, {'.', A7}, {integer, A8, _},
+ {'>', A9}|Ts]) ->
+ {[A1, A2, A3, A4, A5, A6, A7, A8, A9], Ts, function};
+unscannable([{'<', A1}, {float, A2, _}, {'.', A3}, {integer, A4, _},
+ {'>', A5}|Ts]) ->
+ {[A1, A2, A3, A4, A5], Ts, pid};
+unscannable([{'#', A1}, {var, A2, 'Port'}, {'<', A3}, {float, A4, _},
+ {'>', A5}|Ts]) ->
+ {[A1, A2, A3, A4, A5], Ts, port};
+unscannable([{'#', A1}, {var, A2, 'Ref'}, {'<', A3}, {float, A4, _},
+ {'.', A5}, {float, A6, _}, {'>', A7}|Ts]) ->
+ {[A1, A2, A3, A4, A5, A6, A7], Ts, reference}.
+
+expr_fixup(Expr0) ->
+ {Expr, Bs, _} = expr_fixup(Expr0, erl_eval:new_bindings(), 1),
+ {Expr, Bs}.
+
+expr_fixup({string,A,S}=T, Bs0, I) ->
+ try string_fixup(A, S) of
+ Value ->
+ Var = new_var(I),
+ Bs = erl_eval:add_binding(Var, Value, Bs0),
+ {{var, A, Var}, Bs, I+1}
+ catch
+ _:_ ->
+ {T, Bs0, I}
+ end;
+expr_fixup(Tuple, Bs0, I0) when is_tuple(Tuple) ->
+ {L, Bs, I} = expr_fixup(tuple_to_list(Tuple), Bs0, I0),
+ {list_to_tuple(L), Bs, I};
+expr_fixup([E0|Es0], Bs0, I0) ->
+ {E, Bs1, I1} = expr_fixup(E0, Bs0, I0),
+ {Es, Bs, I} = expr_fixup(Es0, Bs1, I1),
+ {[E|Es], Bs, I};
+expr_fixup(T, Bs, I) ->
+ {T, Bs, I}.
+
+string_fixup(A, S) ->
+ Text = erl_anno:text(A),
+ FixupTag = fixup_tag(Text, S),
+ (fixup_fun(FixupTag))(S).
+
+new_var(I) ->
+ list_to_atom(lists:concat(['__ExtendedParseExprs_', I, '__'])).
+
+reset_token_anno(Tokens) ->
+ [setelement(2, T, (reset_anno())(element(2, T))) || T <- Tokens].
+
+reset_expr_anno(Exprs) ->
+ [erl_parse:map_anno(reset_anno(), E) || E <- Exprs].
+
+reset_anno() ->
+ fun(A) -> erl_anno:new(erl_anno:location(A)) end.
+
+fixup_fun(function) -> fun function/1;
+fixup_fun(pid) -> fun erlang:list_to_pid/1;
+fixup_fun(port) -> fun erlang:list_to_port/1;
+fixup_fun(reference) -> fun erlang:list_to_ref/1.
+
+function(S) ->
+ %% External function.
+ {ok, [_, _, _,
+ {atom, _, Module}, _,
+ {atom, _, Function}, _,
+ {integer, _, Arity}|_], _} = erl_scan:string(S),
+ erlang:make_fun(Module, Function, Arity).
+
+fixup_text(function) -> "function";
+fixup_text(pid) -> "pid";
+fixup_text(port) -> "port";
+fixup_text(reference) -> "reference".
+
+fixup_tag("function", "#"++_) -> function;
+fixup_tag("pid", "<"++_) -> pid;
+fixup_tag("port", "#"++_) -> port;
+fixup_tag("reference", "#"++_) -> reference.
+
+%%% End of extended_parse_exprs.
+
+%% `Tokens' is assumed to have been scanned with the 'text' option.
+%%
+%% Can handle pids, ports, references, and external funs.
+
+-spec extended_parse_term(Tokens) ->
+ {'ok', Term} | {'error', ErrorInfo} when
+ Tokens :: [erl_scan:token()],
+ Term :: term(),
+ ErrorInfo :: erl_parse:error_info().
+
+extended_parse_term(Tokens) ->
+ case extended_parse_exprs(Tokens) of
+ {ok, [Expr], Bindings} ->
+ try normalise(Expr, Bindings) of
+ Term ->
+ {ok, Term}
+ catch
+ _:_ ->
+ Loc = erl_anno:location(element(2, Expr)),
+ {error,{Loc,?MODULE,"bad term"}}
+ end;
+ {ok, [_,Expr|_], _Bindings} ->
+ Loc = erl_anno:location(element(2, Expr)),
+ {error,{Loc,?MODULE,"bad term"}};
+ {error, _} = Error ->
+ Error
+ end.
+
+%% From erl_parse.
+normalise({var, _, V}, Bs) ->
+ {value, Value} = erl_eval:binding(V, Bs),
+ Value;
+normalise({char,_,C}, _Bs) -> C;
+normalise({integer,_,I}, _Bs) -> I;
+normalise({float,_,F}, _Bs) -> F;
+normalise({atom,_,A}, _Bs) -> A;
+normalise({string,_,S}, _Bs) -> S;
+normalise({nil,_}, _Bs) -> [];
+normalise({bin,_,Fs}, Bs) ->
+ {value, B, _} =
+ eval_bits:expr_grp(Fs, [],
+ fun(E, _) ->
+ {value, normalise(E, Bs), []}
+ end, [], true),
+ B;
+normalise({cons,_,Head,Tail}, Bs) ->
+ [normalise(Head, Bs)|normalise(Tail, Bs)];
+normalise({tuple,_,Args}, Bs) ->
+ list_to_tuple(normalise_list(Args, Bs));
+normalise({map,_,Pairs}, Bs) ->
+ maps:from_list(lists:map(fun
+ %% only allow '=>'
+ ({map_field_assoc,_,K,V}) ->
+ {normalise(K, Bs),normalise(V, Bs)}
+ end, Pairs));
+%% Special case for unary +/-.
+normalise({op,_,'+',{char,_,I}}, _Bs) -> I;
+normalise({op,_,'+',{integer,_,I}}, _Bs) -> I;
+normalise({op,_,'+',{float,_,F}}, _Bs) -> F;
+normalise({op,_,'-',{char,_,I}}, _Bs) -> -I; %Weird, but compatible!
+normalise({op,_,'-',{integer,_,I}}, _Bs) -> -I;
+normalise({op,_,'-',{float,_,F}}, _Bs) -> -F;
+normalise({'fun',_,{function,{atom,_,M},{atom,_,F},{integer,_,A}}}, _Bs) ->
+ %% Since "#Fun<M.F.A>" is recognized, "fun M:F/A" should be too.
+ fun M:F/A.
+
+normalise_list([H|T], Bs) ->
+ [normalise(H, Bs)|normalise_list(T, Bs)];
+normalise_list([], _Bs) ->
+ [].
+
%%----------------------------------------------------------------------------
%%
%% Evaluate expressions:
@@ -1320,13 +1566,53 @@ ev_expr({cons,_,H,T}) -> [ev_expr(H) | ev_expr(T)].
%% true = erl_internal:guard_bif(F, length(As)),
%% apply(erlang, F, [ev_expr(X) || X <- As]);
+%% eval_str(InStr) -> {ok, OutStr} | {error, ErrStr'}
+%% InStr must represent a body
+%% Note: If InStr is a binary it has to be a Latin-1 string.
+%% If you have a UTF-8 encoded binary you have to call
+%% unicode:characters_to_list/1 before the call to eval_str().
+
+-define(result(F,D), lists:flatten(io_lib:format(F, D))).
+
+-spec eval_str(string() | unicode:latin1_binary()) ->
+ {'ok', string()} | {'error', string()}.
+
+eval_str(Str) when is_list(Str) ->
+ case erl_scan:tokens([], Str, 0) of
+ {more, _} ->
+ {error, "Incomplete form (missing .<cr>)??"};
+ {done, {ok, Toks, _}, Rest} ->
+ case all_white(Rest) of
+ true ->
+ case erl_parse:parse_exprs(Toks) of
+ {ok, Exprs} ->
+ case catch erl_eval:exprs(Exprs, erl_eval:new_bindings()) of
+ {value, Val, _} ->
+ {ok, Val};
+ Other ->
+ {error, ?result("*** eval: ~p", [Other])}
+ end;
+ {error, {_Line, Mod, Args}} ->
+ Msg = ?result("*** ~ts",[Mod:format_error(Args)]),
+ {error, Msg}
+ end;
+ false ->
+ {error, ?result("Non-white space found after "
+ "end-of-form :~ts", [Rest])}
+ end
+ end;
+eval_str(Bin) when is_binary(Bin) ->
+ eval_str(binary_to_list(Bin)).
+
+all_white([$\s|T]) -> all_white(T);
+all_white([$\n|T]) -> all_white(T);
+all_white([$\t|T]) -> all_white(T);
+all_white([]) -> true;
+all_white(_) -> false.
+
ret_expr(_Old, New) ->
%% io:format("~w: reduced ~s => ~s~n",
%% [line(Old), erl_pp:expr(Old), erl_pp:expr(New)]),
New.
line(Expr) -> element(2, Expr).
-
-%% {?MODULE,expr,3} is still the stacktrace, despite the
-%% fact that expr() now takes two, three or four arguments...
-stacktrace() -> [{?MODULE,expr,3}].
diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl
index 89b97b901e..939abaff00 100644
--- a/lib/stdlib/src/erl_internal.erl
+++ b/lib/stdlib/src/erl_internal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -74,8 +74,10 @@ guard_bif(element, 2) -> true;
guard_bif(float, 1) -> true;
guard_bif(floor, 1) -> true;
guard_bif(hd, 1) -> true;
+guard_bif(is_map_key, 2) -> true;
guard_bif(length, 1) -> true;
guard_bif(map_size, 1) -> true;
+guard_bif(map_get, 2) -> true;
guard_bif(node, 0) -> true;
guard_bif(node, 1) -> true;
guard_bif(round, 1) -> true;
@@ -314,6 +316,7 @@ bif(is_function, 2) -> true;
bif(is_integer, 1) -> true;
bif(is_list, 1) -> true;
bif(is_map, 1) -> true;
+bif(is_map_key, 2) -> true;
bif(is_number, 1) -> true;
bif(is_pid, 1) -> true;
bif(is_port, 1) -> true;
@@ -337,6 +340,7 @@ bif(list_to_tuple, 1) -> true;
bif(load_module, 2) -> true;
bif(make_ref, 0) -> true;
bif(map_size,1) -> true;
+bif(map_get,2) -> true;
bif(max,2) -> true;
bif(min,2) -> true;
bif(module_loaded, 1) -> true;
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index fcfd0d8493..e9ac2fcdff 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -93,13 +93,6 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
}).
-%% Are we outside or inside a catch or try/catch?
--type catch_scope() :: 'none'
- | 'after_old_catch'
- | 'after_try'
- | 'wrong_part_of_try'
- | 'try_catch'.
-
%% Define the lint state record.
%% 'called' and 'exports' contain {Line, {Function, Arity}},
%% the other function collections contain {Function, Arity}.
@@ -144,8 +137,7 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
:: dict:dict(ta(), #typeinfo{}),
exp_types=gb_sets:empty() %Exported types
:: gb_sets:set(ta()),
- catch_scope = none %Inside/outside try or catch
- :: catch_scope()
+ in_try_head=false :: boolean() %In a try head.
}).
-type lint_state() :: #lint{}.
@@ -194,8 +186,6 @@ format_error({bad_nowarn_bif_clash,{F,A}}) ->
format_error(disallowed_nowarn_bif_clash) ->
io_lib:format("compile directive nowarn_bif_clash is no longer allowed,~n"
" - use explicit module names or -compile({no_auto_import, [F/A]})", []);
-format_error({bad_nowarn_deprecated_function,{M,F,A}}) ->
- io_lib:format("~tw:~tw/~w is not a deprecated function", [M,F,A]);
format_error({bad_on_load,Term}) ->
io_lib:format("badly formed on_load attribute: ~tw", [Term]);
format_error(multiple_on_loads) ->
@@ -234,15 +224,6 @@ format_error({redefine_old_bif_import,{F,A}}) ->
format_error({redefine_bif_import,{F,A}}) ->
io_lib:format("import directive overrides auto-imported BIF ~w/~w~n"
" - use \"-compile({no_auto_import,[~w/~w]}).\" to resolve name clash", [F,A,F,A]);
-format_error({get_stacktrace,wrong_part_of_try}) ->
- "erlang:get_stacktrace/0 used in the wrong part of 'try' expression. "
- "(Use it in the block between 'catch' and 'end'.)";
-format_error({get_stacktrace,after_old_catch}) ->
- "erlang:get_stacktrace/0 used following an old-style 'catch' "
- "may stop working in a future release. (Use it inside 'try'.)";
-format_error({get_stacktrace,after_try}) ->
- "erlang:get_stacktrace/0 used following a 'try' expression "
- "may stop working in a future release. (Use it inside 'try'.)";
format_error({deprecated, MFA, ReplacementMFA, Rel}) ->
io_lib:format("~s is deprecated and will be removed in ~s; use ~s",
[format_mfa(MFA), Rel, format_mfa(ReplacementMFA)]);
@@ -314,6 +295,10 @@ format_error({unused_var, V}) ->
io_lib:format("variable ~w is unused", [V]);
format_error({variable_in_record_def,V}) ->
io_lib:format("variable ~w in record definition", [V]);
+format_error({stacktrace_guard,V}) ->
+ io_lib:format("stacktrace variable ~w must not be used in a guard", [V]);
+format_error({stacktrace_bound,V}) ->
+ io_lib:format("stacktrace variable ~w must not be previously bound", [V]);
%% --- binaries ---
format_error({undefined_bittype,Type}) ->
io_lib:format("bit type ~tw undefined", [Type]);
@@ -588,10 +573,7 @@ start(File, Opts) ->
false, Opts)},
{missing_spec_all,
bool_option(warn_missing_spec_all, nowarn_missing_spec_all,
- false, Opts)},
- {get_stacktrace,
- bool_option(warn_get_stacktrace, nowarn_get_stacktrace,
- true, Opts)}
+ false, Opts)}
],
Enabled1 = [Category || {Category,true} <- Enabled0],
Enabled = ordsets:from_list(Enabled1),
@@ -856,14 +838,11 @@ not_deprecated(Forms, St0) ->
{nowarn_deprecated_function, MFAs0} <- lists:flatten([Args]),
MFA <- lists:flatten([MFAs0])],
Nowarn = [MFA || {MFA,_L} <- MFAsL],
- Bad = [MFAL || {{M,F,A},_L}=MFAL <- MFAsL,
- otp_internal:obsolete(M, F, A) =:= no],
- St1 = func_line_warning(bad_nowarn_deprecated_function, Bad, St0),
ML = [{M,L} || {{M,_F,_A},L} <- MFAsL, is_atom(M)],
- St3 = foldl(fun ({M,L}, St2) ->
+ St1 = foldl(fun ({M,L}, St2) ->
check_module_name(M, L, St2)
- end, St1, ML),
- St3#lint{not_deprecated = ordsets:from_list(Nowarn)}.
+ end, St0, ML),
+ St1#lint{not_deprecated = ordsets:from_list(Nowarn)}.
%% The nowarn_bif_clash directive is not only deprecated, it's actually an error from R14A
disallowed_compile_flags(Forms, St0) ->
@@ -1426,7 +1405,7 @@ call_function(Line, F, A, #lint{usage=Usage0,called=Cd,func=Func,file=File}=St)
%% function(Line, Name, Arity, Clauses, State) -> State.
function(Line, Name, Arity, Cs, St0) ->
- St1 = St0#lint{func={Name,Arity},catch_scope=none},
+ St1 = St0#lint{func={Name,Arity}},
St2 = define_function(Line, Name, Arity, St1),
clauses(Cs, St2).
@@ -2116,6 +2095,10 @@ is_gexpr({cons,_L,H,T}, Info) -> is_gexpr_list([H,T], Info);
is_gexpr({tuple,_L,Es}, Info) -> is_gexpr_list(Es, Info);
%%is_gexpr({struct,_L,_Tag,Es}, Info) ->
%% is_gexpr_list(Es, Info);
+is_gexpr({map,_L,Es}, Info) ->
+ is_map_fields(Es, Info);
+is_gexpr({map,_L,Src,Es}, Info) ->
+ is_gexpr(Src, Info) andalso is_map_fields(Es, Info);
is_gexpr({record_index,_L,_Name,Field}, Info) ->
is_gexpr(Field, Info);
is_gexpr({record_field,_L,Rec,_Name,Field}, Info) ->
@@ -2158,6 +2141,14 @@ is_gexpr_op(Op, A) ->
is_gexpr_list(Es, Info) -> all(fun (E) -> is_gexpr(E, Info) end, Es).
+is_map_fields([{Tag,_,K,V}|Fs], Info) when Tag =:= map_field_assoc;
+ Tag =:= map_field_exact ->
+ is_gexpr(K, Info) andalso
+ is_gexpr(V, Info) andalso
+ is_map_fields(Fs, Info);
+is_map_fields([], _Info) -> true;
+is_map_fields(_T, _Info) -> false.
+
is_gexpr_fields(Fs, L, Name, {RDs,_}=Info) ->
IFs = case dict:find(Name, RDs) of
{ok,{_Line,Fields}} -> Fs ++ init_fields(Fs, L, Fields);
@@ -2367,7 +2358,7 @@ expr({call,Line,F,As}, Vt, St0) ->
expr({'try',Line,Es,Scs,Ccs,As}, Vt, St0) ->
%% Currently, we don't allow any exports because later
%% passes cannot handle exports in combination with 'after'.
- {Evt0,St1} = exprs(Es, Vt, St0#lint{catch_scope=wrong_part_of_try}),
+ {Evt0,St1} = exprs(Es, Vt, St0),
TryLine = {'try',Line},
Uvt = vtunsafe(TryLine, Evt0, Vt),
Evt1 = vtupdate(Uvt, Evt0),
@@ -2379,12 +2370,11 @@ expr({'try',Line,Es,Scs,Ccs,As}, Vt, St0) ->
{Avt0,St} = exprs(As, vtupdate(Evt2, Vt), St2),
Avt1 = vtupdate(vtunsafe(TryLine, Avt0, Vt), Avt0),
Avt = vtmerge(Evt2, Avt1),
- {Avt,St#lint{catch_scope=after_try}};
+ {Avt,St};
expr({'catch',Line,E}, Vt, St0) ->
%% No new variables added, flag new variables as unsafe.
{Evt,St} = expr(E, Vt, St0),
- {vtupdate(vtunsafe({'catch',Line}, Evt, Vt), Evt),
- St#lint{catch_scope=after_old_catch}};
+ {vtupdate(vtunsafe({'catch',Line}, Evt, Vt), Evt),St};
expr({match,_Line,P,E}, Vt, St0) ->
{Evt,St1} = expr(E, Vt, St0),
{Pvt,Bvt,St2} = pattern(P, vtupdate(Evt, Vt), St1),
@@ -3223,11 +3213,11 @@ is_module_dialyzer_option(Option) ->
try_clauses(Scs, Ccs, In, Vt, St0) ->
{Csvt0,St1} = icrt_clauses(Scs, Vt, St0),
- St2 = St1#lint{catch_scope=try_catch},
+ St2 = St1#lint{in_try_head=true},
{Csvt1,St3} = icrt_clauses(Ccs, Vt, St2),
Csvt = Csvt0 ++ Csvt1,
UpdVt = icrt_export(Csvt, Vt, In, St3),
- {UpdVt,St3}.
+ {UpdVt,St3#lint{in_try_head=false}}.
%% icrt_clauses(Clauses, In, ImportVarTable, State) ->
%% {UpdVt,State}.
@@ -3244,12 +3234,29 @@ icrt_clauses(Cs, Vt, St) ->
mapfoldl(fun (C, St0) -> icrt_clause(C, Vt, St0) end, St, Cs).
icrt_clause({clause,_Line,H,G,B}, Vt0, St0) ->
- {Hvt,Binvt,St1} = head(H, Vt0, St0),
- Vt1 = vtupdate(Hvt, Binvt),
- {Gvt,St2} = guard(G, vtupdate(Vt1, Vt0), St1),
- Vt2 = vtupdate(Gvt, Vt1),
- {Bvt,St3} = exprs(B, vtupdate(Vt2, Vt0), St2),
- {vtupdate(Bvt, Vt2),St3}.
+ Vt1 = taint_stack_var(Vt0, H, St0),
+ {Hvt,Binvt,St1} = head(H, Vt1, St0),
+ Vt2 = vtupdate(Hvt, Binvt),
+ Vt3 = taint_stack_var(Vt2, H, St0),
+ {Gvt,St2} = guard(G, vtupdate(Vt3, Vt0), St1#lint{in_try_head=false}),
+ Vt4 = vtupdate(Gvt, Vt2),
+ {Bvt,St3} = exprs(B, vtupdate(Vt4, Vt0), St2),
+ {vtupdate(Bvt, Vt4),St3}.
+
+taint_stack_var(Vt, Pat, #lint{in_try_head=true}) ->
+ [{tuple,_,[_,_,{var,_,Stk}]}] = Pat,
+ case Stk of
+ '_' ->
+ Vt;
+ _ ->
+ lists:map(fun({V,{bound,Used,Lines}}) when V =:= Stk ->
+ {V,{stacktrace,Used,Lines}};
+ (B) ->
+ B
+ end, Vt)
+ end;
+taint_stack_var(Vt, _Pat, #lint{in_try_head=false}) ->
+ Vt.
icrt_export(Vts, Vt, {Tag,Attrs}, St) ->
{_File,Loc} = loc(Attrs, St),
@@ -3489,6 +3496,9 @@ pat_var(V, Line, Vt, Bvt, St) ->
{[{V,{bound,used,Ls}}],[],
%% As this is matching, exported vars are risky.
add_warning(Line, {exported_var,V,From}, St)};
+ {ok,{stacktrace,_Usage,Ls}} ->
+ {[{V,{bound,used,Ls}}],[],
+ add_error(Line, {stacktrace_bound,V}, St)};
error when St#lint.recdef_top ->
{[],[{V,{bound,unused,[Line]}}],
add_error(Line, {variable_in_record_def,V}, St)};
@@ -3546,6 +3556,9 @@ expr_var(V, Line, Vt, St) ->
false ->
{[{V,{{export,From},used,Ls}}],St}
end;
+ {ok,{stacktrace,_Usage,Ls}} ->
+ {[{V,{bound,used,Ls}}],
+ add_error(Line, {stacktrace_guard,V}, St)};
error ->
{[{V,{bound,used,[Line]}}],
add_error(Line, {unbound_var,V}, St)}
@@ -3713,8 +3726,7 @@ has_wildcard_field([]) -> false.
check_remote_function(Line, M, F, As, St0) ->
St1 = deprecated_function(Line, M, F, As, St0),
St2 = check_qlc_hrl(Line, M, F, As, St1),
- St3 = check_get_stacktrace(Line, M, F, As, St2),
- format_function(Line, M, F, As, St3).
+ format_function(Line, M, F, As, St2).
%% check_qlc_hrl(Line, ModName, FuncName, [Arg], State) -> State
%% Add warning if qlc:q/1,2 has been called but qlc.hrl has not
@@ -3763,23 +3775,6 @@ deprecated_function(Line, M, F, As, St) ->
St
end.
-check_get_stacktrace(Line, erlang, get_stacktrace, [], St) ->
- case St of
- #lint{catch_scope=none} ->
- St;
- #lint{catch_scope=try_catch} ->
- St;
- #lint{catch_scope=Scope} ->
- case is_warn_enabled(get_stacktrace, St) of
- false ->
- St;
- true ->
- add_warning(Line, {get_stacktrace,Scope}, St)
- end
- end;
-check_get_stacktrace(_, _, _, _, St) ->
- St.
-
-dialyzer({no_match, deprecated_type/5}).
deprecated_type(L, M, N, As, St) ->
@@ -3915,10 +3910,9 @@ check_format_string(Fmt) ->
extract_sequences(Fmt, []).
extract_sequences(Fmt, Need0) ->
- case string:chr(Fmt, $~) of
- 0 -> {ok,lists:reverse(Need0)}; %That's it
- Pos ->
- Fmt1 = string:substr(Fmt, Pos+1), %Skip ~
+ case string:find(Fmt, [$~]) of
+ nomatch -> {ok,lists:reverse(Need0)}; %That's it
+ [$~|Fmt1] ->
case extract_sequence(1, Fmt1, Need0) of
{ok,Need1,Rest} -> extract_sequences(Rest, Need1);
Error -> Error
@@ -3949,6 +3943,8 @@ extract_sequence(3, [$.,_|Fmt], Need) ->
extract_sequence(4, Fmt, Need);
extract_sequence(3, Fmt, Need) ->
extract_sequence(4, Fmt, Need);
+extract_sequence(4, [$t, $l | Fmt], Need) ->
+ extract_sequence(4, [$l, $t | Fmt], Need);
extract_sequence(4, [$t, $c | Fmt], Need) ->
extract_sequence(5, [$c|Fmt], Need);
extract_sequence(4, [$t, $s | Fmt], Need) ->
@@ -3965,8 +3961,14 @@ extract_sequence(4, [$t, C | _Fmt], _Need) ->
{error,"invalid control ~t" ++ [C]};
extract_sequence(4, [$l, $p | Fmt], Need) ->
extract_sequence(5, [$p|Fmt], Need);
+extract_sequence(4, [$l, $t, $p | Fmt], Need) ->
+ extract_sequence(5, [$p|Fmt], Need);
extract_sequence(4, [$l, $P | Fmt], Need) ->
extract_sequence(5, [$P|Fmt], Need);
+extract_sequence(4, [$l, $t, $P | Fmt], Need) ->
+ extract_sequence(5, [$P|Fmt], Need);
+extract_sequence(4, [$l, $t, C | _Fmt], _Need) ->
+ {error,"invalid control ~lt" ++ [C]};
extract_sequence(4, [$l, C | _Fmt], _Need) ->
{error,"invalid control ~l" ++ [C]};
extract_sequence(4, Fmt, Need) ->
diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl
index 6e72d64acc..9602f0bcd9 100644
--- a/lib/stdlib/src/erl_parse.yrl
+++ b/lib/stdlib/src/erl_parse.yrl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,6 +29,10 @@ clause_args clause_guard clause_body
expr expr_100 expr_150 expr_160 expr_200 expr_300 expr_400 expr_500
expr_600 expr_700 expr_800
expr_max
+pat_expr pat_expr_200 pat_expr_300 pat_expr_400 pat_expr_500
+pat_expr_600 pat_expr_700 pat_expr_800
+pat_expr_max map_pat_expr record_pat_expr
+pat_argument_list pat_exprs
list tail
list_comprehension lc_expr lc_exprs
binary_comprehension
@@ -37,7 +41,7 @@ record_expr record_tuple record_field record_fields
map_expr map_tuple map_field map_field_assoc map_field_exact map_fields map_key
if_expr if_clause if_clauses case_expr cr_clause cr_clauses receive_expr
fun_expr fun_clause fun_clauses atom_or_var integer_or_var
-try_expr try_catch try_clause try_clauses
+try_expr try_catch try_clause try_clauses try_opt_stacktrace
function_call argument_list
exprs guard
atomic strings
@@ -66,7 +70,7 @@ char integer float atom string var
'spec' 'callback' % helper
dot.
-Expect 2.
+Expect 0.
Rootsymbol form.
@@ -210,7 +214,7 @@ function_clause -> atom clause_args clause_guard clause_body :
{clause,?anno('$1'),element(3, '$1'),'$2','$3','$4'}.
-clause_args -> argument_list : element(1, '$1').
+clause_args -> pat_argument_list : element(1, '$1').
clause_guard -> 'when' guard : '$2'.
clause_guard -> '$empty' : [].
@@ -275,6 +279,53 @@ expr_max -> receive_expr : '$1'.
expr_max -> fun_expr : '$1'.
expr_max -> try_expr : '$1'.
+pat_expr -> pat_expr_200 '=' pat_expr : {match,?anno('$2'),'$1','$3'}.
+pat_expr -> pat_expr_200 : '$1'.
+
+pat_expr_200 -> pat_expr_300 comp_op pat_expr_300 :
+ ?mkop2('$1', '$2', '$3').
+pat_expr_200 -> pat_expr_300 : '$1'.
+
+pat_expr_300 -> pat_expr_400 list_op pat_expr_300 :
+ ?mkop2('$1', '$2', '$3').
+pat_expr_300 -> pat_expr_400 : '$1'.
+
+pat_expr_400 -> pat_expr_400 add_op pat_expr_500 :
+ ?mkop2('$1', '$2', '$3').
+pat_expr_400 -> pat_expr_500 : '$1'.
+
+pat_expr_500 -> pat_expr_500 mult_op pat_expr_600 :
+ ?mkop2('$1', '$2', '$3').
+pat_expr_500 -> pat_expr_600 : '$1'.
+
+pat_expr_600 -> prefix_op pat_expr_700 :
+ ?mkop1('$1', '$2').
+pat_expr_600 -> map_pat_expr : '$1'.
+pat_expr_600 -> pat_expr_700 : '$1'.
+
+pat_expr_700 -> record_pat_expr : '$1'.
+pat_expr_700 -> pat_expr_800 : '$1'.
+
+pat_expr_800 -> pat_expr_max : '$1'.
+
+pat_expr_max -> var : '$1'.
+pat_expr_max -> atomic : '$1'.
+pat_expr_max -> list : '$1'.
+pat_expr_max -> binary : '$1'.
+pat_expr_max -> tuple : '$1'.
+pat_expr_max -> '(' pat_expr ')' : '$2'.
+
+map_pat_expr -> '#' map_tuple :
+ {map, ?anno('$1'),'$2'}.
+map_pat_expr -> pat_expr_max '#' map_tuple :
+ {map, ?anno('$2'),'$1','$3'}.
+map_pat_expr -> map_pat_expr '#' map_tuple :
+ {map, ?anno('$2'),'$1','$3'}.
+
+record_pat_expr -> '#' atom '.' atom :
+ {record_index,?anno('$1'),element(3, '$2'),'$4'}.
+record_pat_expr -> '#' atom record_tuple :
+ {record,?anno('$1'),element(3, '$2'),'$3'}.
list -> '[' ']' : {nil,?anno('$1')}.
list -> '[' expr tail : {cons,?anno('$1'),'$2','$3'}.
@@ -397,6 +448,10 @@ case_expr -> 'case' expr 'of' cr_clauses 'end' :
cr_clauses -> cr_clause : ['$1'].
cr_clauses -> cr_clause ';' cr_clauses : ['$1' | '$3'].
+%% FIXME: merl in syntax_tools depends on patterns in a 'case' being
+%% full expressions. Therefore, we can't use pat_expr here. There
+%% should be a better way.
+
cr_clause -> expr clause_guard clause_body :
{clause,?anno('$1'),['$1'],'$2','$3'}.
@@ -424,11 +479,11 @@ integer_or_var -> var : '$1'.
fun_clauses -> fun_clause : ['$1'].
fun_clauses -> fun_clause ';' fun_clauses : ['$1' | '$3'].
-fun_clause -> argument_list clause_guard clause_body :
+fun_clause -> pat_argument_list clause_guard clause_body :
{Args,Anno} = '$1',
{clause,Anno,'fun',Args,'$2','$3'}.
-fun_clause -> var argument_list clause_guard clause_body :
+fun_clause -> var pat_argument_list clause_guard clause_body :
{clause,element(2, '$1'),element(3, '$1'),element(1, '$2'),'$3','$4'}.
try_expr -> 'try' exprs 'of' cr_clauses try_catch :
@@ -446,24 +501,31 @@ try_catch -> 'after' exprs 'end' :
try_clauses -> try_clause : ['$1'].
try_clauses -> try_clause ';' try_clauses : ['$1' | '$3'].
-try_clause -> expr clause_guard clause_body :
+try_clause -> pat_expr clause_guard clause_body :
A = ?anno('$1'),
{clause,A,[{tuple,A,[{atom,A,throw},'$1',{var,A,'_'}]}],'$2','$3'}.
-try_clause -> atom ':' expr clause_guard clause_body :
+try_clause -> atom ':' pat_expr try_opt_stacktrace clause_guard clause_body :
A = ?anno('$1'),
- {clause,A,[{tuple,A,['$1','$3',{var,A,'_'}]}],'$4','$5'}.
-try_clause -> var ':' expr clause_guard clause_body :
+ {clause,A,[{tuple,A,['$1','$3',{var,A,'$4'}]}],'$5','$6'}.
+try_clause -> var ':' pat_expr try_opt_stacktrace clause_guard clause_body :
A = ?anno('$1'),
- {clause,A,[{tuple,A,['$1','$3',{var,A,'_'}]}],'$4','$5'}.
+ {clause,A,[{tuple,A,['$1','$3',{var,A,'$4'}]}],'$5','$6'}.
+try_opt_stacktrace -> ':' var : element(3, '$2').
+try_opt_stacktrace -> '$empty' : '_'.
argument_list -> '(' ')' : {[],?anno('$1')}.
argument_list -> '(' exprs ')' : {'$2',?anno('$1')}.
+pat_argument_list -> '(' ')' : {[],?anno('$1')}.
+pat_argument_list -> '(' pat_exprs ')' : {'$2',?anno('$1')}.
exprs -> expr : ['$1'].
exprs -> expr ',' exprs : ['$1' | '$3'].
+pat_exprs -> pat_expr : ['$1'].
+pat_exprs -> pat_expr ',' pat_exprs : ['$1' | '$3'].
+
guard -> exprs : ['$1'].
guard -> exprs ';' guard : ['$1'|'$3'].
@@ -918,7 +980,7 @@ Erlang code.
-type af_unary_op(T) :: {'op', anno(), unary_op(), T}.
--type unary_op() :: '+' | '*' | 'bnot' | 'not'.
+-type unary_op() :: '+' | '-' | 'bnot' | 'not'.
%% See also lib/stdlib/{src/erl_bits.erl,include/erl_bits.hrl}.
-type type_specifier_list() :: 'default' | [type_specifier(), ...].
@@ -1315,6 +1377,8 @@ normalise({map,_,Pairs}=M) ->
({map_field_assoc,_,K,V}) -> {normalise(K),normalise(V)};
(_) -> erlang:error({badarg,M})
end, Pairs));
+normalise({'fun',_,{function,{atom,_,M},{atom,_,F},{integer,_,A}}}) ->
+ fun M:F/A;
%% Special case for unary +/-.
normalise({op,_,'+',{char,_,I}}) -> I;
normalise({op,_,'+',{integer,_,I}}) -> I;
diff --git a/lib/stdlib/src/erl_posix_msg.erl b/lib/stdlib/src/erl_posix_msg.erl
index bfafca1ff7..8959fea498 100644
--- a/lib/stdlib/src/erl_posix_msg.erl
+++ b/lib/stdlib/src/erl_posix_msg.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -64,6 +64,7 @@ message_1(eduppkg) -> <<"duplicate package name">>;
message_1(eexist) -> <<"file already exists">>;
message_1(efault) -> <<"bad address in system call argument">>;
message_1(efbig) -> <<"file too large">>;
+message_1(eftype) -> <<"EFTYPE">>;
message_1(ehostdown) -> <<"host is down">>;
message_1(ehostunreach) -> <<"host is unreachable">>;
message_1(eidrm) -> <<"identifier removed">>;
@@ -115,6 +116,7 @@ message_1(enopkg) -> <<"package not installed">>;
message_1(enoprotoopt) -> <<"bad proocol option">>;
message_1(enospc) -> <<"no space left on device">>;
message_1(enosr) -> <<"out of stream resources or not a stream device">>;
+message_1(enostr) -> <<"not a stream">>;
message_1(enosym) -> <<"unresolved symbol name">>;
message_1(enosys) -> <<"function not implemented">>;
message_1(enotblk) -> <<"block device required">>;
@@ -128,6 +130,7 @@ message_1(enotty) -> <<"inappropriate device for ioctl">>;
message_1(enotuniq) -> <<"name not unique on network">>;
message_1(enxio) -> <<"no such device or address">>;
message_1(eopnotsupp) -> <<"operation not supported on socket">>;
+message_1(eoverflow) -> <<"offset too large for file system">>;
message_1(eperm) -> <<"not owner">>;
message_1(epfnosupport) -> <<"protocol family not supported">>;
message_1(epipe) -> <<"broken pipe">>;
@@ -167,4 +170,6 @@ message_1(ewouldblock) -> <<"operation would block">>;
message_1(exdev) -> <<"cross-domain link">>;
message_1(exfull) -> <<"message tables full">>;
message_1(nxdomain) -> <<"non-existing domain">>;
+message_1(exbadport) -> <<"inet_drv bad port state">>;
+message_1(exbadseq) -> <<"inet_drv bad request sequence">>;
message_1(_) -> <<"unknown POSIX error">>.
diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl
index ee5e7a11bf..dd302a2880 100644
--- a/lib/stdlib/src/erl_pp.erl
+++ b/lib/stdlib/src/erl_pp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -59,7 +59,7 @@
_ -> ?TEST(T)
end).
-define(EXPRS_TEST(L),
- [?TEST(E) || E <- L]).
+ _ = [?TEST(E) || E <- L]).
-define(TEST(T),
%% Assumes that erl_anno has been compiled with DEBUG=true.
%% erl_pp does not use the annoations, but test it anyway.
@@ -237,13 +237,20 @@ lform({attribute,Line,Name,Arg}, Opts) ->
lform({function,Line,Name,Arity,Clauses}, Opts) ->
lfunction({function,Line,Name,Arity,Clauses}, Opts);
%% These are specials to make it easier for the compiler.
-lform({error,E}, _Opts) ->
- leaf(format("~p\n", [{error,E}]));
-lform({warning,W}, _Opts) ->
- leaf(format("~p\n", [{warning,W}]));
+lform({error,_}=E, Opts) ->
+ message(E, Opts);
+lform({warning,_}=W, Opts) ->
+ message(W, Opts);
lform({eof,_Line}, _Opts) ->
$\n.
+message(M, #options{encoding = Encoding}) ->
+ F = case Encoding of
+ latin1 -> "~p\n";
+ unicode -> "~tp\n"
+ end,
+ leaf(format(F, [M])).
+
lattribute({attribute,_Line,type,Type}, Opts) ->
[typeattr(type, Type, Opts),leaf(".\n")];
lattribute({attribute,_Line,opaque,Type}, Opts) ->
@@ -598,8 +605,6 @@ lexpr({'fun',_,{clauses,Cs},Extra}, _Prec, Opts) ->
lexpr({named_fun,_,Name,Cs,Extra}, _Prec, Opts) ->
{force_nl,fun_info(Extra),
{list,[{first,['fun', " "],fun_clauses(Cs, Opts, {named, Name})},'end']}};
-lexpr({'query',_,Lc}, _Prec, Opts) ->
- {list,[{step,leaf("query"),lexpr(Lc, 0, Opts)},'end']};
lexpr({call,_,{remote,_,{atom,_,M},{atom,_,F}=N}=Name,Args}, Prec, Opts) ->
case erl_internal:bif(M, F, length(Args)) of
true ->
@@ -904,7 +909,7 @@ maybe_paren(_P, _Prec, Expr) ->
Expr.
leaf(S) ->
- {leaf,chars_size(S),S}.
+ {leaf,string:length(S),S}.
%%% Do the formatting. Currently nothing fancy. Could probably have
%%% done it in one single pass.
@@ -964,7 +969,7 @@ f({seq,Before,After,Sep,LItems}, I0, ST, WT, PP) ->
Sizes = BSizeL ++ SizeL,
NSepChars = if
is_list(Sep), Sep =/= [] ->
- erlang:max(0, length(CharsL)-1);
+ erlang:max(0, length(CharsL)-1); % not string:length
true ->
0
end,
@@ -1120,7 +1125,7 @@ incr(I, Incr) ->
I+Incr.
indentation(E, I) when I < 0 ->
- chars_size(E);
+ string:length(E);
indentation(E, I0) ->
I = io_lib_format:indentation(E, I0),
case has_nl(E) of
@@ -1157,19 +1162,19 @@ write_a_string(S, I, PP) ->
write_a_string([], _N, _Len, _PP) ->
[];
write_a_string(S, N, Len, PP) ->
- SS = string:sub_string(S, 1, N),
+ SS = string:slice(S, 0, N),
Sl = write_string(SS, PP),
- case (chars_size(Sl) > Len) and (N > ?MIN_SUBSTRING) of
+ case (string:length(Sl) > Len) and (N > ?MIN_SUBSTRING) of
true ->
write_a_string(S, N-1, Len, PP);
false ->
[flat_leaf(Sl) |
- write_a_string(lists:nthtail(length(SS), S), Len, Len, PP)]
+ write_a_string(string:slice(S, string:length(SS)), Len, Len, PP)]
end.
flat_leaf(S) ->
L = lists:flatten(S),
- {leaf,length(L),L}.
+ {leaf,string:length(L),L}.
write_value(V, PP) ->
(PP#pp.value_fun)(V).
@@ -1190,15 +1195,6 @@ write_char(C, PP) ->
a0() ->
erl_anno:new(0).
-chars_size([C | Es]) when is_integer(C) ->
- 1 + chars_size(Es);
-chars_size([E | Es]) ->
- chars_size(E) + chars_size(Es);
-chars_size([]) ->
- 0;
-chars_size(B) when is_binary(B) ->
- byte_size(B).
-
-define(N_SPACES, 30).
spacetab() ->
diff --git a/lib/stdlib/src/erl_scan.erl b/lib/stdlib/src/erl_scan.erl
index 47223b129c..4774c4bf19 100644
--- a/lib/stdlib/src/erl_scan.erl
+++ b/lib/stdlib/src/erl_scan.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -752,7 +752,7 @@ scan_string(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0}) ->
{char_error,Ncs,Error,Nline,Ncol,EndCol} ->
scan_error(Error, Nline, Ncol, Nline, EndCol, Ncs);
{error,Nline,Ncol,Nwcs,Ncs} ->
- Estr = string:substr(Nwcs, 1, 16), % Expanded escape chars.
+ Estr = string:slice(Nwcs, 0, 16), % Expanded escape chars.
scan_error({string,$\",Estr}, Line0, Col0, Nline, Ncol, Ncs); %"
{Ncs,Nline,Ncol,Nstr,Nwcs} ->
Anno = anno(Line0, Col0, St, Nstr),
@@ -767,7 +767,7 @@ scan_qatom(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0}) ->
{char_error,Ncs,Error,Nline,Ncol,EndCol} ->
scan_error(Error, Nline, Ncol, Nline, EndCol, Ncs);
{error,Nline,Ncol,Nwcs,Ncs} ->
- Estr = string:substr(Nwcs, 1, 16), % Expanded escape chars.
+ Estr = string:slice(Nwcs, 0, 16), % Expanded escape chars.
scan_error({string,$\',Estr}, Line0, Col0, Nline, Ncol, Ncs); %'
{Ncs,Nline,Ncol,Nstr,Nwcs} ->
case catch list_to_atom(Nwcs) of
diff --git a/lib/stdlib/src/erl_tar.erl b/lib/stdlib/src/erl_tar.erl
index 76f0b38108..d8b8f466b1 100644
--- a/lib/stdlib/src/erl_tar.erl
+++ b/lib/stdlib/src/erl_tar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -189,7 +189,7 @@ table(Name) ->
%% Returns a list of names of the files in the tar file Name.
%% Options accepted: compressed, verbose, cooked.
-spec table(open_handle(), [compressed | verbose | cooked]) ->
- {ok, [tar_entry()]} | {error, term()}.
+ {ok, [string() | tar_entry()]} | {error, term()}.
table(Name, Opts) when is_list(Opts) ->
foldl_read(Name, fun table1/4, [], table_opts(Opts)).
@@ -457,26 +457,61 @@ add(Reader, NameOrBin, NameInArchive, Options)
do_add(#reader{access=write}=Reader, Name, NameInArchive, Options)
when is_list(NameInArchive), is_list(Options) ->
- RF = fun(F) -> file:read_link_info(F, [{time, posix}]) end,
+ RF = apply_file_info_opts_fun(Options, read_link_info),
Opts = #add_opts{read_info=RF},
- add1(Reader, Name, NameInArchive, add_opts(Options, Opts));
+ add1(Reader, Name, NameInArchive, add_opts(Options, Options, Opts));
do_add(#reader{access=read},_,_,_) ->
{error, eacces};
do_add(Reader,_,_,_) ->
{error, {badarg, Reader}}.
-add_opts([dereference|T], Opts) ->
- RF = fun(F) -> file:read_file_info(F, [{time, posix}]) end,
- add_opts(T, Opts#add_opts{read_info=RF});
-add_opts([verbose|T], Opts) ->
- add_opts(T, Opts#add_opts{verbose=true});
-add_opts([{chunks,N}|T], Opts) ->
- add_opts(T, Opts#add_opts{chunk_size=N});
-add_opts([_|T], Opts) ->
- add_opts(T, Opts);
-add_opts([], Opts) ->
+add_opts([dereference|T], AllOptions, Opts) ->
+ RF = apply_file_info_opts_fun(AllOptions, read_file_info),
+ add_opts(T, AllOptions, Opts#add_opts{read_info=RF});
+add_opts([verbose|T], AllOptions, Opts) ->
+ add_opts(T, AllOptions, Opts#add_opts{verbose=true});
+add_opts([{chunks,N}|T], AllOptions, Opts) ->
+ add_opts(T, AllOptions, Opts#add_opts{chunk_size=N});
+add_opts([{atime,Value}|T], AllOptions, Opts) ->
+ add_opts(T, AllOptions, Opts#add_opts{atime=Value});
+add_opts([{mtime,Value}|T], AllOptions, Opts) ->
+ add_opts(T, AllOptions, Opts#add_opts{mtime=Value});
+add_opts([{ctime,Value}|T], AllOptions, Opts) ->
+ add_opts(T, AllOptions, Opts#add_opts{ctime=Value});
+add_opts([{uid,Value}|T], AllOptions, Opts) ->
+ add_opts(T, AllOptions, Opts#add_opts{uid=Value});
+add_opts([{gid,Value}|T], AllOptions, Opts) ->
+ add_opts(T, AllOptions, Opts#add_opts{gid=Value});
+add_opts([_|T], AllOptions, Opts) ->
+ add_opts(T, AllOptions, Opts);
+add_opts([], _AllOptions, Opts) ->
Opts.
+apply_file_info_opts(Opts, {ok, FileInfo}) ->
+ {ok, do_apply_file_info_opts(Opts, FileInfo)};
+apply_file_info_opts(_Opts, Other) ->
+ Other.
+
+do_apply_file_info_opts([{atime,Value}|T], FileInfo) ->
+ do_apply_file_info_opts(T, FileInfo#file_info{atime=Value});
+do_apply_file_info_opts([{mtime,Value}|T], FileInfo) ->
+ do_apply_file_info_opts(T, FileInfo#file_info{mtime=Value});
+do_apply_file_info_opts([{ctime,Value}|T], FileInfo) ->
+ do_apply_file_info_opts(T, FileInfo#file_info{ctime=Value});
+do_apply_file_info_opts([{uid,Value}|T], FileInfo) ->
+ do_apply_file_info_opts(T, FileInfo#file_info{uid=Value});
+do_apply_file_info_opts([{gid,Value}|T], FileInfo) ->
+ do_apply_file_info_opts(T, FileInfo#file_info{gid=Value});
+do_apply_file_info_opts([_|T], FileInfo) ->
+ do_apply_file_info_opts(T, FileInfo);
+do_apply_file_info_opts([], FileInfo) ->
+ FileInfo.
+
+apply_file_info_opts_fun(Options, InfoFunction) ->
+ fun(F) ->
+ apply_file_info_opts(Options, file:InfoFunction(F, [{time, posix}]))
+ end.
+
add1(#reader{}=Reader, Name, NameInArchive, #add_opts{read_info=ReadInfo}=Opts)
when is_list(Name) ->
Res = case ReadInfo(Name) of
@@ -515,9 +550,11 @@ add1(Reader, Bin, NameInArchive, Opts) when is_binary(Bin) ->
name = NameInArchive,
size = byte_size(Bin),
typeflag = ?TYPE_REGULAR,
- atime = Now,
- mtime = Now,
- ctime = Now,
+ atime = add_opts_time(Opts#add_opts.atime, Now),
+ mtime = add_opts_time(Opts#add_opts.mtime, Now),
+ ctime = add_opts_time(Opts#add_opts.ctime, Now),
+ uid = Opts#add_opts.uid,
+ gid = Opts#add_opts.gid,
mode = 8#100644},
{ok, Reader2} = add_header(Reader, Header, Opts),
Padding = skip_padding(byte_size(Bin)),
@@ -527,6 +564,9 @@ add1(Reader, Bin, NameInArchive, Opts) when is_binary(Bin) ->
{error, Reason} -> {error, {NameInArchive, Reason}}
end.
+add_opts_time(undefined, Now) -> Now;
+add_opts_time(Time, _Now) -> Time.
+
add_directory(Reader, DirName, NameInArchive, Info, Opts) ->
case file:list_dir(DirName) of
{ok, []} ->
@@ -1650,8 +1690,12 @@ write_file(Name, Bin) ->
case file:write_file(Name, Bin) of
ok -> ok;
{error,enoent} ->
- ok = make_dirs(Name, file),
- write_file(Name, Bin);
+ case make_dirs(Name, file) of
+ ok ->
+ write_file(Name, Bin);
+ {error,Reason} ->
+ throw({error, Reason})
+ end;
{error,Reason} ->
throw({error, Reason})
end.
diff --git a/lib/stdlib/src/erl_tar.hrl b/lib/stdlib/src/erl_tar.hrl
index cff0c2f500..5d6cecbb66 100644
--- a/lib/stdlib/src/erl_tar.hrl
+++ b/lib/stdlib/src/erl_tar.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,12 @@
-record(add_opts, {
read_info, %% Fun to use for read file/link info.
chunk_size = 0, %% For file reading when sending to sftp. 0=do not chunk
- verbose = false}). %% Verbose on/off.
+ verbose = false, %% Verbose on/off.
+ atime = undefined,
+ mtime = undefined,
+ ctime = undefined,
+ uid = 0,
+ gid = 0}).
-type add_opts() :: #add_opts{}.
%% Options used when reading a tar archive.
@@ -36,7 +41,12 @@
-type add_opt() :: dereference |
verbose |
- {chunks, pos_integer()}.
+ {chunks, pos_integer()} |
+ {atime, non_neg_integer()} |
+ {mtime, non_neg_integer()} |
+ {ctime, non_neg_integer()} |
+ {uid, non_neg_integer()} |
+ {gid, non_neg_integer()}.
-type extract_opt() :: {cwd, string()} |
{files, [string()]} |
diff --git a/lib/stdlib/src/error_logger_file_h.erl b/lib/stdlib/src/error_logger_file_h.erl
index b7c193f965..58da0cbdd6 100644
--- a/lib/stdlib/src/error_logger_file_h.erl
+++ b/lib/stdlib/src/error_logger_file_h.erl
@@ -126,7 +126,7 @@ format_body(State, [{Format,Args}|T]) ->
S0
catch
_:_ ->
- format(State, "ERROR: ~p - ~p\n", [Format,Args])
+ format(State, "ERROR: ~tp - ~tp\n", [Format,Args])
end,
[S|format_body(State, T)];
format_body(_State, []) ->
@@ -165,44 +165,26 @@ parse_event({warning_report, _GL, {Pid, std_warning, Args}}) ->
parse_event(_) -> ignore.
format_term(Term) when is_list(Term) ->
- case string_p(Term) of
+ case string_p(lists:flatten(Term)) of
true ->
- [{"~s\n",[Term]}];
+ [{"~ts\n",[Term]}];
false ->
format_term_list(Term)
end;
format_term(Term) ->
- [{"~p\n",[Term]}].
+ [{"~tp\n",[Term]}].
format_term_list([{Tag,Data}|T]) ->
- [{" ~p: ~p\n",[Tag,Data]}|format_term_list(T)];
+ [{" ~tp: ~tp\n",[Tag,Data]}|format_term_list(T)];
format_term_list([Data|T]) ->
- [{" ~p\n",[Data]}|format_term_list(T)];
+ [{" ~tp\n",[Data]}|format_term_list(T)];
format_term_list([]) ->
- [];
-format_term_list(_) ->
- %% Continue to allow non-proper lists for now.
- %% FIXME: Remove this clause in OTP 19.
[].
string_p([]) ->
false;
-string_p(Term) ->
- string_p1(Term).
-
-string_p1([H|T]) when is_integer(H), H >= $\s, H < 255 ->
- string_p1(T);
-string_p1([$\n|T]) -> string_p1(T);
-string_p1([$\r|T]) -> string_p1(T);
-string_p1([$\t|T]) -> string_p1(T);
-string_p1([$\v|T]) -> string_p1(T);
-string_p1([$\b|T]) -> string_p1(T);
-string_p1([$\f|T]) -> string_p1(T);
-string_p1([$\e|T]) -> string_p1(T);
-string_p1([H|T]) when is_list(H) ->
- string_p1(H) andalso string_p1(T);
-string_p1([]) -> true;
-string_p1(_) -> false.
+string_p(FlatList) ->
+ io_lib:printable_list(FlatList).
get_utc_config() ->
%% SASL utc_log configuration overrides stdlib config
@@ -225,7 +207,7 @@ header(Time, Title) ->
end.
header({{Y,Mo,D},{H,Mi,S}}, Title, UTC) ->
- io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s ~s===~n",
+ io_lib:format("~n=~ts==== ~p-~s-~p::~s:~s:~s ~s===~n",
[Title,D,month(Mo),Y,t(H),t(Mi),t(S),UTC]).
t(X) when is_integer(X) ->
diff --git a/lib/stdlib/src/error_logger_tty_h.erl b/lib/stdlib/src/error_logger_tty_h.erl
index 8f0d7b0362..fa940b7264 100644
--- a/lib/stdlib/src/error_logger_tty_h.erl
+++ b/lib/stdlib/src/error_logger_tty_h.erl
@@ -39,13 +39,16 @@
{user,
prev_handler,
io_mod=io,
- depth=unlimited}).
+ depth=unlimited,
+ modifier=""}).
%% This one is used when we takeover from the simple error_logger.
init({[], {error_logger, Buf}}) ->
User = set_group_leader(),
Depth = error_logger:get_format_depth(),
- State = #st{user=User,prev_handler=error_logger,depth=Depth},
+ Modifier = modifier(),
+ State = #st{user=User,prev_handler=error_logger,
+ depth=Depth,modifier=Modifier},
write_events(State, Buf),
{ok, State};
%% This one is used if someone took over from us, and now wants to
@@ -57,7 +60,8 @@ init({[], {error_logger_tty_h, PrevHandler}}) ->
init([]) ->
User = set_group_leader(),
Depth = error_logger:get_format_depth(),
- {ok, #st{user=User,prev_handler=[],depth=Depth}}.
+ Modifier = modifier(),
+ {ok, #st{user=User,prev_handler=[],depth=Depth,modifier=Modifier}}.
handle_event({_Type, GL, _Msg}, State) when node(GL) =/= node() ->
{ok, State};
@@ -91,8 +95,9 @@ code_change(_OldVsn, State, _Extra) ->
write_event(Event, IoMod) ->
do_write_event(#st{io_mod=IoMod}, Event).
-write_event(Event, IoMod, Depth) ->
- do_write_event(#st{io_mod=IoMod,depth=Depth}, Event).
+write_event(Event, IoMod, {Depth, Enc}) ->
+ Modifier = modifier(Enc),
+ do_write_event(#st{io_mod=IoMod,depth=Depth,modifier=Modifier}, Event).
%%% ------------------------------------------------------
@@ -120,12 +125,12 @@ write_events(State, [Ev|Es]) ->
write_events(_State, []) ->
ok.
-do_write_event(State, {Time, Event}) ->
- case parse_event(Event) of
+do_write_event(#st{modifier=M}=State, {Time, Event}) ->
+ case parse_event(Event,M) of
ignore ->
ok;
{Title,Pid,FormatList} ->
- Header = header(Time, Title),
+ Header = header(Time, Title, M),
Body = format_body(State, FormatList),
AtNode = if
node(Pid) =/= node() ->
@@ -144,13 +149,13 @@ do_write_event(State, {Time, Event}) ->
do_write_event(_, _) ->
ok.
-format_body(State, [{Format,Args}|T]) ->
+format_body(#st{modifier=M}=State, [{Format,Args}|T]) ->
S = try format(State, Format, Args) of
S0 ->
S0
catch
_:_ ->
- format(State, "ERROR: ~p - ~p\n", [Format,Args])
+ format(State, "ERROR: ~"++M++"p - ~"++M++"p\n", [Format,Args])
end,
[S|format_body(State, T)];
format_body(_State, []) ->
@@ -174,62 +179,41 @@ limit_format([H|T], Depth) ->
limit_format([], _) ->
[].
-parse_event({error, _GL, {Pid, Format, Args}}) ->
+parse_event({error, _GL, {Pid, Format, Args}},_) ->
{"ERROR REPORT",Pid,[{Format,Args}]};
-parse_event({info_msg, _GL, {Pid, Format, Args}}) ->
+parse_event({info_msg, _GL, {Pid, Format, Args}},_) ->
{"INFO REPORT",Pid,[{Format, Args}]};
-parse_event({warning_msg, _GL, {Pid, Format, Args}}) ->
+parse_event({warning_msg, _GL, {Pid, Format, Args}},_) ->
{"WARNING REPORT",Pid,[{Format,Args}]};
-parse_event({error_report, _GL, {Pid, std_error, Args}}) ->
- {"ERROR REPORT",Pid,format_term(Args)};
-parse_event({info_report, _GL, {Pid, std_info, Args}}) ->
- {"INFO REPORT",Pid,format_term(Args)};
-parse_event({warning_report, _GL, {Pid, std_warning, Args}}) ->
- {"WARNING REPORT",Pid,format_term(Args)};
-parse_event(_) -> ignore.
-
-format_term(Term) when is_list(Term) ->
- case string_p(Term) of
+parse_event({error_report, _GL, {Pid, std_error, Args}},M) ->
+ {"ERROR REPORT",Pid,format_term(Args,M)};
+parse_event({info_report, _GL, {Pid, std_info, Args}},M) ->
+ {"INFO REPORT",Pid,format_term(Args,M)};
+parse_event({warning_report, _GL, {Pid, std_warning, Args}},M) ->
+ {"WARNING REPORT",Pid,format_term(Args,M)};
+parse_event(_,_) -> ignore.
+
+format_term(Term,M) when is_list(Term) ->
+ case string_p(lists:flatten(Term)) of
true ->
- [{"~s\n",[Term]}];
+ [{"~"++M++"s\n",[Term]}];
false ->
- format_term_list(Term)
+ format_term_list(Term,M)
end;
-format_term(Term) ->
- [{"~p\n",[Term]}].
-
-format_term_list([{Tag,Data}|T]) ->
- [{" ~p: ~p\n",[Tag,Data]}|format_term_list(T)];
-format_term_list([Data|T]) ->
- [{" ~p\n",[Data]}|format_term_list(T)];
-format_term_list([]) ->
- [];
-format_term_list(_) ->
- %% Continue to allow non-proper lists for now.
- %% FIXME: Remove this clause in OTP 19.
+format_term(Term,M) ->
+ [{"~"++M++"p\n",[Term]}].
+
+format_term_list([{Tag,Data}|T],M) ->
+ [{" ~"++M++"p: ~"++M++"p\n",[Tag,Data]}|format_term_list(T,M)];
+format_term_list([Data|T],M) ->
+ [{" ~"++M++"p\n",[Data]}|format_term_list(T,M)];
+format_term_list([],_) ->
[].
string_p([]) ->
false;
-string_p(Term) ->
- string_p1(Term).
-
-string_p1([H|T]) when is_integer(H), H >= $\s, H < 255 ->
- string_p1(T);
-string_p1([$\n|T]) -> string_p1(T);
-string_p1([$\r|T]) -> string_p1(T);
-string_p1([$\t|T]) -> string_p1(T);
-string_p1([$\v|T]) -> string_p1(T);
-string_p1([$\b|T]) -> string_p1(T);
-string_p1([$\f|T]) -> string_p1(T);
-string_p1([$\e|T]) -> string_p1(T);
-string_p1([H|T]) when is_list(H) ->
- case string_p1(H) of
- true -> string_p1(T);
- _ -> false
- end;
-string_p1([]) -> true;
-string_p1(_) -> false.
+string_p(FlatList) ->
+ io_lib:printable_list(FlatList).
get_utc_config() ->
%% SASL utc_log configuration overrides stdlib config
@@ -243,16 +227,16 @@ get_utc_config() ->
end
end.
-header(Time, Title) ->
+header(Time, Title, M) ->
case get_utc_config() of
true ->
- header(Time, Title, "UTC ");
+ header(Time, Title, "UTC ", M);
_ ->
- header(calendar:universal_time_to_local_time(Time), Title, "")
+ header(calendar:universal_time_to_local_time(Time), Title, "", M)
end.
-header({{Y,Mo,D},{H,Mi,S}}, Title, UTC) ->
- io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s ~s===~n",
+header({{Y,Mo,D},{H,Mi,S}}, Title, UTC, M) ->
+ io_lib:format("~n=~"++M++"s==== ~p-~s-~p::~s:~s:~s ~s===~n",
[Title,D,month(Mo),Y,t(H),t(Mi),t(S),UTC]).
t(X) when is_integer(X) ->
@@ -274,3 +258,13 @@ month(9) -> "Sep";
month(10) -> "Oct";
month(11) -> "Nov";
month(12) -> "Dec".
+
+modifier() ->
+ modifier(encoding()).
+modifier(latin1) ->
+ "";
+modifier(_) ->
+ "t".
+
+encoding() ->
+ proplists:get_value(encoding,io:getopts(),latin1).
diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl
index 2093916a7c..3f14894b55 100644
--- a/lib/stdlib/src/escript.erl
+++ b/lib/stdlib/src/escript.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -224,8 +224,8 @@ return_sections(S, Bin) ->
normalize_section(Name, undefined) ->
{Name, undefined};
normalize_section(shebang, "#!" ++ Chars) ->
- Chopped = string:strip(Chars, right, $\n),
- Stripped = string:strip(Chopped, both),
+ Chopped = string:trim(Chars, trailing, "$\n"),
+ Stripped = string:trim(Chopped, both),
if
Stripped =:= ?SHEBANG ->
{shebang, default};
@@ -233,8 +233,8 @@ normalize_section(shebang, "#!" ++ Chars) ->
{shebang, Stripped}
end;
normalize_section(comment, Chars) ->
- Chopped = string:strip(Chars, right, $\n),
- Stripped = string:strip(string:strip(Chopped, left, $%), both),
+ Chopped = string:trim(Chars, trailing, "$\n"),
+ Stripped = string:trim(string:trim(Chopped, leading, "$%"), both),
if
Stripped =:= ?COMMENT ->
{comment, default};
@@ -242,8 +242,8 @@ normalize_section(comment, Chars) ->
{comment, Stripped}
end;
normalize_section(emu_args, "%%!" ++ Chars) ->
- Chopped = string:strip(Chars, right, $\n),
- Stripped = string:strip(Chopped, both),
+ Chopped = string:trim(Chars, trailing, "$\n"),
+ Stripped = string:trim(Chopped, both),
{emu_args, Stripped};
normalize_section(Name, Chars) ->
{Name, Chars}.
@@ -283,8 +283,7 @@ start(EscriptOptions) ->
throw:Str ->
io:format("escript: ~ts\n", [Str]),
my_halt(127);
- _:Reason ->
- Stk = erlang:get_stacktrace(),
+ _:Reason:Stk ->
io:format("escript: Internal error: ~tp\n", [Reason]),
io:format("~tp\n", [Stk]),
my_halt(127)
@@ -759,8 +758,8 @@ run(Module, Args) ->
Module:main(Args),
my_halt(0)
catch
- Class:Reason ->
- fatal(format_exception(Class, Reason))
+ Class:Reason:StackTrace ->
+ fatal(format_exception(Class, Reason, StackTrace))
end.
-spec interpret(_, _, _, _) -> no_return().
@@ -793,8 +792,8 @@ interpret(Forms, HasRecs, File, Args) ->
end}),
my_halt(0)
catch
- Class:Reason ->
- fatal(format_exception(Class, Reason))
+ Class:Reason:StackTrace ->
+ fatal(format_exception(Class, Reason, StackTrace))
end.
report_errors(Errors) ->
@@ -860,7 +859,7 @@ code_handler(Name, Args, Dict, File) ->
%% io:format("Calling:~p~n",[{Mod,Name,Args}]),
apply(Mod, Name, Args);
error ->
- io:format("Script does not export ~w/~w\n", [Name,Arity]),
+ io:format("Script does not export ~tw/~w\n", [Name,Arity]),
my_halt(127)
end
end.
@@ -873,7 +872,7 @@ eval_exprs([E|Es], Bs0, Lf, Ef, RBs) ->
{value,_V,Bs} = erl_eval:expr(E, Bs0, Lf, Ef, RBs1),
eval_exprs(Es, Bs, Lf, Ef, RBs).
-format_exception(Class, Reason) ->
+format_exception(Class, Reason, StackTrace) ->
Enc = encoding(),
P = case Enc of
latin1 -> "P";
@@ -882,9 +881,8 @@ format_exception(Class, Reason) ->
PF = fun(Term, I) ->
io_lib:format("~." ++ integer_to_list(I) ++ P, [Term, 50])
end,
- StackTrace = erlang:get_stacktrace(),
StackFun = fun(M, _F, _A) -> (M =:= erl_eval) or (M =:= ?MODULE) end,
- lib:format_exception(1, Class, Reason, StackTrace, StackFun, PF, Enc).
+ erl_error:format_exception(1, Class, Reason, StackTrace, StackFun, PF, Enc).
encoding() ->
[{encoding, Encoding}] = enc(),
@@ -916,8 +914,8 @@ hidden_apply(App, M, F, Args) ->
try
apply(fun() -> M end(), F, Args)
catch
- error:undef ->
- case erlang:get_stacktrace() of
+ error:undef:StackTrace ->
+ case StackTrace of
[{M,F,Args,_} | _] ->
Arity = length(Args),
Text = io_lib:format("Call to ~w:~w/~w in application ~w failed.\n",
diff --git a/lib/stdlib/src/ets.erl b/lib/stdlib/src/ets.erl
index 898b2f5bba..29f907ad73 100644
--- a/lib/stdlib/src/ets.erl
+++ b/lib/stdlib/src/ets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -73,10 +73,13 @@
select_count/2, select_delete/2, select_replace/2, select_reverse/1,
select_reverse/2, select_reverse/3, setopts/2, slot/2,
take/2,
- update_counter/3, update_counter/4, update_element/3]).
+ update_counter/3, update_counter/4, update_element/3,
+ whereis/1]).
%% internal exports
--export([internal_request_all/0]).
+-export([internal_request_all/0,
+ internal_delete_all/2,
+ internal_select_delete/2]).
-spec all() -> [Tab] when
Tab :: tab().
@@ -115,7 +118,15 @@ delete(_, _) ->
-spec delete_all_objects(Tab) -> true when
Tab :: tab().
-delete_all_objects(_) ->
+delete_all_objects(Tab) ->
+ _ = ets:internal_delete_all(Tab, undefined),
+ true.
+
+-spec internal_delete_all(Tab, undefined) -> NumDeleted when
+ Tab :: tab(),
+ NumDeleted :: non_neg_integer().
+
+internal_delete_all(_, _) ->
erlang:nif_error(undef).
-spec delete_object(Tab, Object) -> true when
@@ -145,6 +156,7 @@ give_away(_, _, _) ->
InfoList :: [InfoTuple],
InfoTuple :: {compressed, boolean()}
| {heir, pid() | none}
+ | {id, tid()}
| {keypos, pos_integer()}
| {memory, non_neg_integer()}
| {name, atom()}
@@ -162,7 +174,7 @@ info(_) ->
-spec info(Tab, Item) -> Value | undefined when
Tab :: tab(),
- Item :: compressed | fixed | heir | keypos | memory
+ Item :: compressed | fixed | heir | id | keypos | memory
| name | named_table | node | owner | protection
| safe_fixed | safe_fixed_monotonic_time | size | stats | type
| write_concurrency | read_concurrency,
@@ -277,7 +289,7 @@ match_spec_compile(_) ->
erlang:nif_error(undef).
-spec match_spec_run_r(List, CompiledMatchSpec, list()) -> list() when
- List :: [tuple()],
+ List :: [term()],
CompiledMatchSpec :: comp_match_spec().
match_spec_run_r(_, _, _) ->
@@ -376,7 +388,17 @@ select_count(_, _) ->
MatchSpec :: match_spec(),
NumDeleted :: non_neg_integer().
-select_delete(_, _) ->
+select_delete(Tab, [{'_',[],[true]}]) ->
+ ets:internal_delete_all(Tab, undefined);
+select_delete(Tab, MatchSpec) ->
+ ets:internal_select_delete(Tab, MatchSpec).
+
+-spec internal_select_delete(Tab, MatchSpec) -> NumDeleted when
+ Tab :: tab(),
+ MatchSpec :: match_spec(),
+ NumDeleted :: non_neg_integer().
+
+internal_select_delete(_, _) ->
erlang:nif_error(undef).
-spec select_replace(Tab, MatchSpec) -> NumReplaced when
@@ -512,12 +534,17 @@ update_counter(_, _, _, _) ->
update_element(_, _, _) ->
erlang:nif_error(undef).
+-spec whereis(TableName) -> tid() | undefined when
+ TableName :: atom().
+whereis(_) ->
+ erlang:nif_error(undef).
+
%%% End of BIFs
-opaque comp_match_spec() :: reference().
-spec match_spec_run(List, CompiledMatchSpec) -> list() when
- List :: [tuple()],
+ List :: [term()],
CompiledMatchSpec :: comp_match_spec().
match_spec_run(List, CompiledMS) ->
@@ -882,10 +909,10 @@ tab2file(Tab, File, Options) ->
_ = disk_log:close(Name),
_ = file:delete(File),
exit(ExReason);
- error:ErReason ->
+ error:ErReason:StackTrace ->
_ = disk_log:close(Name),
_ = file:delete(File),
- erlang:raise(error,ErReason,erlang:get_stacktrace())
+ erlang:raise(error,ErReason,StackTrace)
end
catch
throw:TReason2 ->
@@ -1060,9 +1087,9 @@ file2tab(File, Opts) ->
exit:ExReason ->
ets:delete(Tab),
exit(ExReason);
- error:ErReason ->
+ error:ErReason:StackTrace ->
ets:delete(Tab),
- erlang:raise(error,ErReason,erlang:get_stacktrace())
+ erlang:raise(error,ErReason,StackTrace)
end
after
_ = disk_log:close(Name)
@@ -1693,13 +1720,15 @@ choice(Height, Width, P, Mode, Tab, Key, Turn, Opos) ->
end,
choice(Height, Width, P, Mode, Tab, Key, Turn, Opos);
[$/|Regexp] -> %% from regexp
- case re:compile(nonl(Regexp)) of
+ case re:compile(nonl(Regexp),[unicode]) of
{ok,Re} ->
re_search(Height, Width, Tab, ets:first(Tab), Re, 1, 1);
{error,{ErrorString,_Pos}} ->
io:format("~ts\n", [ErrorString]),
choice(Height, Width, P, Mode, Tab, Key, Turn, Opos)
end;
+ eof ->
+ ok;
_ ->
choice(Height, Width, P, Mode, Tab, Key, Turn, Opos)
end.
@@ -1717,7 +1746,7 @@ get_line(P, Default) ->
line_string(Binary) when is_binary(Binary) -> unicode:characters_to_list(Binary);
line_string(Other) -> Other.
-nonl(S) -> string:strip(S, right, $\n).
+nonl(S) -> string:trim(S, trailing, "$\n").
print_number(Tab, Key, Num) ->
Os = ets:lookup(Tab, Key),
@@ -1746,7 +1775,7 @@ do_display_item(_Height, Width, I, Opos) ->
L = to_string(I),
L2 = if
length(L) > Width - 8 ->
- string:substr(L, 1, Width-13) ++ " ...";
+ string:slice(L, 0, Width-13) ++ " ...";
true ->
L
end,
diff --git a/lib/stdlib/src/eval_bits.erl b/lib/stdlib/src/eval_bits.erl
index 631faa3be5..bb86a65c72 100644
--- a/lib/stdlib/src/eval_bits.erl
+++ b/lib/stdlib/src/eval_bits.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,9 @@
-export([expr_grp/3,expr_grp/5,match_bits/6,
match_bits/7,bin_gen/6]).
+-define(STACKTRACE,
+ element(2, erlang:process_info(self(), current_stacktrace))).
+
%% Types used in this module:
%% @type bindings(). An abstract structure for bindings between
%% variables and values (the environment)
@@ -93,9 +96,9 @@ eval_exp_field1(V, Size, Unit, Type, Endian, Sign) ->
eval_exp_field(V, Size, Unit, Type, Endian, Sign)
catch
error:system_limit ->
- error(system_limit);
+ erlang:raise(error, system_limit, ?STACKTRACE);
error:_ ->
- error(badarg)
+ erlang:raise(error, badarg, ?STACKTRACE)
end.
eval_exp_field(Val, Size, Unit, integer, little, signed) ->
@@ -131,7 +134,7 @@ eval_exp_field(Val, all, Unit, binary, _, _) ->
Size when Size rem Unit =:= 0 ->
<<Val:Size/binary-unit:1>>;
_ ->
- error(badarg)
+ erlang:raise(error, badarg, ?STACKTRACE)
end;
eval_exp_field(Val, Size, Unit, binary, _, _) ->
<<Val:(Size*Unit)/binary-unit:1>>.
@@ -377,12 +380,12 @@ make_bit_type(Line, default, Type0) ->
{ok,all,Bt} -> {{atom,Line,all},erl_bits:as_list(Bt)};
{ok,undefined,Bt} -> {{atom,Line,undefined},erl_bits:as_list(Bt)};
{ok,Size,Bt} -> {{integer,Line,Size},erl_bits:as_list(Bt)};
- {error,Reason} -> error(Reason)
+ {error,Reason} -> erlang:raise(error, Reason, ?STACKTRACE)
end;
make_bit_type(_Line, Size, Type0) -> %Size evaluates to an integer or 'all'
case erl_bits:set_bit_type(Size, Type0) of
{ok,Size,Bt} -> {Size,erl_bits:as_list(Bt)};
- {error,Reason} -> error(Reason)
+ {error,Reason} -> erlang:raise(error, Reason, ?STACKTRACE)
end.
match_check_size(Mfun, Size, Bs) ->
@@ -405,9 +408,3 @@ match_check_size(_, {value,_,_}, _Bs, _AllowAll) ->
ok; %From the debugger.
match_check_size(_, _, _Bs, _AllowAll) ->
throw(invalid).
-
-%% error(Reason) -> exception thrown
-%% Throw a nice-looking exception, similar to exceptions from erl_eval.
-error(Reason) ->
- erlang:raise(error, Reason, [{erl_eval,expr,3}]).
-
diff --git a/lib/stdlib/src/file_sorter.erl b/lib/stdlib/src/file_sorter.erl
index 3aeaff8dc4..191e050538 100644
--- a/lib/stdlib/src/file_sorter.erl
+++ b/lib/stdlib/src/file_sorter.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1314,9 +1314,9 @@ infun(W) ->
{cont, W#w{in = NFun}, Objs};
Error ->
error(Error, W1)
- catch Class:Reason ->
+ catch Class:Reason:Stacktrace ->
cleanup(W1),
- erlang:raise(Class, Reason, erlang:get_stacktrace())
+ erlang:raise(Class, Reason, Stacktrace)
end.
outfun(A, #w{inout_value = Val} = W) when Val =/= no_value ->
@@ -1336,9 +1336,9 @@ outfun(A, W) ->
W#w{out = NF};
Error ->
error(Error, W1)
- catch Class:Reason ->
+ catch Class:Reason:Stacktrace ->
cleanup(W1),
- erlang:raise(Class, Reason, erlang:get_stacktrace())
+ erlang:raise(Class, Reason, Stacktrace)
end.
is_keypos(Keypos) when is_integer(Keypos), Keypos > 0 ->
diff --git a/lib/stdlib/src/filelib.erl b/lib/stdlib/src/filelib.erl
index d7c313f214..de839be5cf 100644
--- a/lib/stdlib/src/filelib.erl
+++ b/lib/stdlib/src/filelib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -365,11 +365,18 @@ do_list_dir(Dir, Mod) -> eval_list_dir(Dir, Mod).
%%% Compiling a wildcard.
+
+%% Define characters used for escaping a \.
+-define(ESCAPE_PREFIX, $@).
+-define(ESCAPE_CHARACTER, [?ESCAPE_PREFIX,$e]).
+-define(ESCAPED_ESCAPE_PREFIX, [?ESCAPE_PREFIX,?ESCAPE_PREFIX]).
+
%% Only for debugging.
compile_wildcard(Pattern) when is_list(Pattern) ->
{compiled_wildcard,?HANDLE_ERROR(compile_wildcard(Pattern, "."))}.
-compile_wildcard(Pattern, Cwd0) ->
+compile_wildcard(Pattern0, Cwd0) ->
+ Pattern = convert_escapes(Pattern0),
[Root|Rest] = filename:split(Pattern),
case filename:pathtype(Root) of
relative ->
@@ -409,7 +416,8 @@ compile_join({cwd,Cwd}, File0) ->
compile_join({root,PrefixLen,Root}, File) ->
{root,PrefixLen,filename:join(Root, File)}.
-compile_part(Part) ->
+compile_part(Part0) ->
+ Part = wrap_escapes(Part0),
compile_part(Part, false, []).
compile_part_to_sep(Part) ->
@@ -445,6 +453,8 @@ compile_part([${|Rest], Upto, Result) ->
error ->
compile_part(Rest, Upto, [${|Result])
end;
+compile_part([{escaped,X}|Rest], Upto, Result) ->
+ compile_part(Rest, Upto, [X|Result]);
compile_part([X|Rest], Upto, Result) ->
compile_part(Rest, Upto, [X|Result]);
compile_part([], _Upto, Result) ->
@@ -461,6 +471,8 @@ compile_charset1([Lower, $-, Upper|Rest], Ordset) when Lower =< Upper ->
compile_charset1(Rest, compile_range(Lower, Upper, Ordset));
compile_charset1([$]|Rest], Ordset) ->
{ok, {one_of, gb_sets:from_ordset(Ordset)}, Rest};
+compile_charset1([{escaped,X}|Rest], Ordset) ->
+ compile_charset1(Rest, ordsets:add_element(X, Ordset));
compile_charset1([X|Rest], Ordset) ->
compile_charset1(Rest, ordsets:add_element(X, Ordset));
compile_charset1([], _Ordset) ->
@@ -486,6 +498,32 @@ compile_alt(Pattern, Result) ->
error
end.
+%% Convert backslashes to an illegal Unicode character to
+%% protect in from filename:split/1.
+
+convert_escapes([?ESCAPE_PREFIX|T]) ->
+ ?ESCAPED_ESCAPE_PREFIX ++ convert_escapes(T);
+convert_escapes([$\\|T]) ->
+ ?ESCAPE_CHARACTER ++ convert_escapes(T);
+convert_escapes([H|T]) ->
+ [H|convert_escapes(T)];
+convert_escapes([]) ->
+ [].
+
+%% Wrap each escape in a tuple to remove the special meaning for
+%% the character that follows.
+
+wrap_escapes(?ESCAPED_ESCAPE_PREFIX ++ T) ->
+ [?ESCAPE_PREFIX|wrap_escapes(T)];
+wrap_escapes(?ESCAPE_CHARACTER ++ [C|T]) ->
+ [{escaped,C}|wrap_escapes(T)];
+wrap_escapes(?ESCAPE_CHARACTER) ->
+ [];
+wrap_escapes([H|T]) ->
+ [H|wrap_escapes(T)];
+wrap_escapes([]) ->
+ [].
+
badpattern(Reason) ->
error({badpattern,Reason}).
@@ -544,17 +582,16 @@ default_search_rules() ->
{"", ".c", c_source_search_rules()},
{"", ".in", basic_source_search_rules()},
%% plain old directory rules, backwards compatible
- {"", ""},
- {"ebin","src"},
- {"ebin","esrc"}
- ].
+ {"", ""}] ++ erl_source_search_rules().
basic_source_search_rules() ->
(erl_source_search_rules()
++ c_source_search_rules()).
erl_source_search_rules() ->
- [{"ebin","src"}, {"ebin","esrc"}].
+ [{"ebin","src"}, {"ebin","esrc"},
+ {"ebin",filename:join("src", "*")},
+ {"ebin",filename:join("esrc", "*")}].
c_source_search_rules() ->
[{"priv","c_src"}, {"priv","src"}, {"bin","c_src"}, {"bin","src"}, {"", "src"}].
@@ -634,8 +671,16 @@ try_dir_rule(Dir, Filename, From, To) ->
Src = filename:join(NewDir, Filename),
case is_regular(Src) of
true -> {ok, Src};
- false -> error
+ false -> find_regular_file(wildcard(Src))
end;
false ->
error
end.
+
+find_regular_file([]) ->
+ error;
+find_regular_file([File|Files]) ->
+ case is_regular(File) of
+ true -> {ok, File};
+ false -> find_regular_file(Files)
+ end.
diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl
index 9bf4290916..b7b7b562ab 100644
--- a/lib/stdlib/src/filename.erl
+++ b/lib/stdlib/src/filename.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,6 +34,38 @@
%% we flatten the arguments immediately on function entry as that makes
%% it easier to ensure that the code works.
+%%
+%% *** Requirements on Raw Filename Format ***
+%%
+%% These requirements are due to the 'filename' module
+%% in stdlib. This since it is documented that it
+%% should be able to operate on raw filenames as well
+%% as ordinary filenames.
+%%
+%% A raw filename *must* be a byte sequence where:
+%% 1. Codepoints 0-127 (7-bit ascii) *must* be encoded
+%% as a byte with the corresponding value. That is,
+%% the most significant bit in the byte encoding the
+%% codepoint is never set.
+%% 2. Codepoints greater than 127 *must* be encoded
+%% with the most significant bit set in *every* byte
+%% encoding it.
+%%
+%% Latin1 and UTF-8 meet these requirements while
+%% UTF-16 and UTF-32 don't.
+%%
+%% On Windows filenames are natively stored as malformed
+%% UTF-16LE (lonely surrogates may appear). A more correct
+%% description than UTF-16 would be an array of 16-bit
+%% words... In order to meet the requirements of the
+%% raw file format we convert the malformed UTF-16LE to
+%% malformed UTF-8 which meet the requirements.
+%%
+%% Note that these requirements are today only OTP
+%% internal (erts-stdlib internal) requirements that
+%% could be changed.
+%%
+
-export([absname/1, absname/2, absname_join/2,
basename/1, basename/2, dirname/1,
extension/1, join/1, join/2, pathtype/1,
@@ -41,6 +73,7 @@
safe_relative_path/1]).
-export([find_src/1, find_src/2]). % deprecated
-export([basedir/2, basedir/3]).
+-export([validate/1]).
%% Undocumented and unsupported exports.
-export([append/2]).
@@ -439,6 +472,10 @@ join(Name1, Name2) when is_atom(Name2) ->
join1([UcLetter, $:|Rest], RelativeName, [], win32)
when is_integer(UcLetter), UcLetter >= $A, UcLetter =< $Z ->
join1(Rest, RelativeName, [$:, UcLetter+$a-$A], win32);
+join1([$\\,$\\|Rest], RelativeName, [], win32) ->
+ join1([$/,$/|Rest], RelativeName, [], win32);
+join1([$/,$/|Rest], RelativeName, [], win32) ->
+ join1(Rest, RelativeName, [$/,$/], win32);
join1([$\\|Rest], RelativeName, Result, win32) ->
join1([$/|Rest], RelativeName, Result, win32);
join1([$/|Rest], RelativeName, [$., $/|Result], OsType) ->
@@ -467,6 +504,10 @@ join1([Atom|Rest], RelativeName, Result, OsType) when is_atom(Atom) ->
join1b(<<UcLetter, $:, Rest/binary>>, RelativeName, [], win32)
when is_integer(UcLetter), UcLetter >= $A, UcLetter =< $Z ->
join1b(Rest, RelativeName, [$:, UcLetter+$a-$A], win32);
+join1b(<<$\\,$\\,Rest/binary>>, RelativeName, [], win32) ->
+ join1b(<<$/,$/,Rest/binary>>, RelativeName, [], win32);
+join1b(<<$/,$/,Rest/binary>>, RelativeName, [], win32) ->
+ join1b(Rest, RelativeName, [$/,$/], win32);
join1b(<<$\\,Rest/binary>>, RelativeName, Result, win32) ->
join1b(<<$/,Rest/binary>>, RelativeName, Result, win32);
join1b(<<$/,Rest/binary>>, RelativeName, [$., $/|Result], OsType) ->
@@ -477,6 +518,8 @@ join1b(<<>>, <<>>, Result, OsType) ->
list_to_binary(maybe_remove_dirsep(Result, OsType));
join1b(<<>>, RelativeName, [$:|Rest], win32) ->
join1b(RelativeName, <<>>, [$:|Rest], win32);
+join1b(<<>>, RelativeName, [$/,$/|Result], win32) ->
+ join1b(RelativeName, <<>>, [$/,$/|Result], win32);
join1b(<<>>, RelativeName, [$/|Result], OsType) ->
join1b(RelativeName, <<>>, [$/|Result], OsType);
join1b(<<>>, RelativeName, [$., $/|Result], OsType) ->
@@ -490,6 +533,8 @@ maybe_remove_dirsep([$/, $:, Letter], win32) ->
[Letter, $:, $/];
maybe_remove_dirsep([$/], _) ->
[$/];
+maybe_remove_dirsep([$/,$/], win32) ->
+ [$/,$/];
maybe_remove_dirsep([$/|Name], _) ->
lists:reverse(Name);
maybe_remove_dirsep(Name, _) ->
@@ -679,6 +724,9 @@ win32_splitb(<<Letter0,$:,Rest/binary>>) when ?IS_DRIVELETTER(Letter0) ->
Letter = fix_driveletter(Letter0),
L = binary:split(Rest,[<<"/">>,<<"\\">>],[global]),
[<<Letter,$:>> | [ X || X <- L, X =/= <<>> ]];
+win32_splitb(<<Slash,Slash,Rest/binary>>) when ((Slash =:= $\\) orelse (Slash =:= $/)) ->
+ L = binary:split(Rest,[<<"/">>,<<"\\">>],[global]),
+ [<<"//">> | [ X || X <- L, X =/= <<>> ]];
win32_splitb(<<Slash,Rest/binary>>) when ((Slash =:= $\\) orelse (Slash =:= $/)) ->
L = binary:split(Rest,[<<"/">>,<<"\\">>],[global]),
[<<$/>> | [ X || X <- L, X =/= <<>> ]];
@@ -690,6 +738,8 @@ win32_splitb(Name) ->
unix_split(Name) ->
split(Name, [], unix).
+win32_split([Slash,Slash|Rest]) when ((Slash =:= $\\) orelse (Slash =:= $/)) ->
+ split(Rest, [[$/,$/]], win32);
win32_split([$\\|Rest]) ->
win32_split([$/|Rest]);
win32_split([X, $\\|Rest]) when is_integer(X) ->
@@ -962,24 +1012,33 @@ filename_string_to_binary(List) ->
%% basedir
%% http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
--type basedir_type() :: 'user_cache' | 'user_config' | 'user_data'
- | 'user_log'
- | 'site_config' | 'site_data'.
+-type basedir_path_type() :: 'user_cache' | 'user_config' | 'user_data'
+ | 'user_log'.
+-type basedir_paths_type() :: 'site_config' | 'site_data'.
+
+-type basedir_opts() :: #{author => string() | binary(),
+ os => 'windows' | 'darwin' | 'linux',
+ version => string() | binary()}.
--spec basedir(Type,Application) -> file:filename_all() when
- Type :: basedir_type(),
+-spec basedir(PathType,Application) -> file:filename_all() when
+ PathType :: basedir_path_type(),
+ Application :: string() | binary();
+ (PathsType,Application) -> [file:filename_all()] when
+ PathsType :: basedir_paths_type(),
Application :: string() | binary().
basedir(Type,Application) when is_atom(Type), is_list(Application) orelse
is_binary(Application) ->
basedir(Type, Application, #{}).
--spec basedir(Type,Application,Opts) -> file:filename_all() when
- Type :: basedir_type(),
+-spec basedir(PathType,Application,Opts) -> file:filename_all() when
+ PathType :: basedir_path_type(),
Application :: string() | binary(),
- Opts :: #{author => string() | binary(),
- os => 'windows' | 'darwin' | 'linux',
- version => string() | binary()}.
+ Opts :: basedir_opts();
+ (PathsType,Application,Opts) -> [file:filename_all()] when
+ PathsType :: basedir_paths_type(),
+ Application :: string() | binary(),
+ Opts :: basedir_opts().
basedir(Type,Application,Opts) when is_atom(Type), is_map(Opts),
is_list(Application) orelse
@@ -1036,10 +1095,10 @@ basedir_linux(Type) ->
user_log -> getenv("XDG_CACHE_HOME", ?basedir_linux_user_log, true);
site_data ->
Base = getenv("XDG_DATA_DIRS",?basedir_linux_site_data,false),
- string:tokens(Base,":");
+ string:lexemes(Base, ":");
site_config ->
Base = getenv("XDG_CONFIG_DIRS",?basedir_linux_site_config,false),
- string:tokens(Base,":")
+ string:lexemes(Base, ":")
end.
-define(basedir_darwin_user_data, "Library/Application Support").
@@ -1135,3 +1194,72 @@ basedir_os_type() ->
{win32,_} -> windows;
_ -> linux
end.
+
+%%
+%% validate/1
+%%
+
+-spec validate(FileName) -> boolean() when
+ FileName :: file:name_all().
+
+validate(FileName) when is_binary(FileName) ->
+ %% Raw filename...
+ validate_bin(FileName);
+validate(FileName) when is_list(FileName);
+ is_atom(FileName) ->
+ validate_list(FileName,
+ file:native_name_encoding(),
+ os:type()).
+
+validate_list(FileName, Enc, Os) ->
+ try
+ true = validate_list(FileName, Enc, Os, 0) > 0
+ catch
+ _ : _ -> false
+ end.
+
+validate_list([], _Enc, _Os, Chars) ->
+ Chars;
+validate_list(C, Enc, Os, Chars) when is_integer(C) ->
+ validate_char(C, Enc, Os),
+ Chars+1;
+validate_list(A, Enc, Os, Chars) when is_atom(A) ->
+ validate_list(atom_to_list(A), Enc, Os, Chars);
+validate_list([H|T], Enc, Os, Chars) ->
+ NewChars = validate_list(H, Enc, Os, Chars),
+ validate_list(T, Enc, Os, NewChars).
+
+%% C is always an integer...
+% validate_char(C, _, _) when not is_integer(C) ->
+% throw(invalid);
+validate_char(C, _, _) when C < 1 ->
+ throw(invalid); %% No negative or null characters...
+validate_char(C, latin1, _) when C > 255 ->
+ throw(invalid);
+validate_char(C, utf8, _) when C >= 16#110000 ->
+ throw(invalid);
+validate_char(C, utf8, {win32, _}) when C > 16#ffff ->
+ throw(invalid); %% invalid win wchar...
+validate_char(_C, utf8, {win32, _}) ->
+ ok; %% Range below is accepted on windows...
+validate_char(C, utf8, _) when 16#D800 =< C, C =< 16#DFFF ->
+ throw(invalid); %% invalid unicode range...
+validate_char(_, _, _) ->
+ ok.
+
+validate_bin(Bin) ->
+ %% Raw filename. That is, we do not interpret
+ %% the encoding, but we still do not accept
+ %% null characters...
+ try
+ true = validate_bin(Bin, 0) > 0
+ catch
+ _ : _ -> false
+ end.
+
+validate_bin(<<>>, Bs) ->
+ Bs;
+validate_bin(<<0, _Rest/binary>>, _Bs) ->
+ throw(invalid); %% No null characters allowed...
+validate_bin(<<_B, Rest/binary>>, Bs) ->
+ validate_bin(Rest, Bs+1).
diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl
index 32f43fc706..a7f743bd4c 100644
--- a/lib/stdlib/src/gen.erl
+++ b/lib/stdlib/src/gen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -49,6 +49,7 @@
| {'logfile', string()}.
-type option() :: {'timeout', timeout()}
| {'debug', [debug_flag()]}
+ | {'hibernate_after', timeout()}
| {'spawn_opt', [proc_lib:spawn_option()]}.
-type options() :: [option()].
@@ -147,57 +148,36 @@ init_it2(GenMod, Starter, Parent, Name, Mod, Args, Options) ->
call(Process, Label, Request) ->
call(Process, Label, Request, ?default_timeout).
+%% Optimize a common case.
+call(Process, Label, Request, Timeout) when is_pid(Process),
+ Timeout =:= infinity orelse is_integer(Timeout) andalso Timeout >= 0 ->
+ do_call(Process, Label, Request, Timeout);
call(Process, Label, Request, Timeout)
when Timeout =:= infinity; is_integer(Timeout), Timeout >= 0 ->
Fun = fun(Pid) -> do_call(Pid, Label, Request, Timeout) end,
do_for_proc(Process, Fun).
-do_call(Process, Label, Request, Timeout) ->
- try erlang:monitor(process, Process) of
- Mref ->
- %% If the monitor/2 call failed to set up a connection to a
- %% remote node, we don't want the '!' operator to attempt
- %% to set up the connection again. (If the monitor/2 call
- %% failed due to an expired timeout, '!' too would probably
- %% have to wait for the timeout to expire.) Therefore,
- %% use erlang:send/3 with the 'noconnect' option so that it
- %% will fail immediately if there is no connection to the
- %% remote node.
-
- catch erlang:send(Process, {Label, {self(), Mref}, Request},
- [noconnect]),
- receive
- {Mref, Reply} ->
- erlang:demonitor(Mref, [flush]),
- {ok, Reply};
- {'DOWN', Mref, _, _, noconnection} ->
- Node = get_node(Process),
- exit({nodedown, Node});
- {'DOWN', Mref, _, _, Reason} ->
- exit(Reason)
- after Timeout ->
- erlang:demonitor(Mref, [flush]),
- exit(timeout)
- end
- catch
- error:_ ->
- %% Node (C/Java?) is not supporting the monitor.
- %% The other possible case -- this node is not distributed
- %% -- should have been handled earlier.
- %% Do the best possible with monitor_node/2.
- %% This code may hang indefinitely if the Process
- %% does not exist. It is only used for featureweak remote nodes.
- Node = get_node(Process),
- monitor_node(Node, true),
- receive
- {nodedown, Node} ->
- monitor_node(Node, false),
- exit({nodedown, Node})
- after 0 ->
- Tag = make_ref(),
- Process ! {Label, {self(), Tag}, Request},
- wait_resp(Node, Tag, Timeout)
- end
+do_call(Process, Label, Request, Timeout) when is_atom(Process) =:= false ->
+ Mref = erlang:monitor(process, Process),
+
+ %% OTP-21:
+ %% Auto-connect is asynchronous. But we still use 'noconnect' to make sure
+ %% we send on the monitored connection, and not trigger a new auto-connect.
+ %%
+ erlang:send(Process, {Label, {self(), Mref}, Request}, [noconnect]),
+
+ receive
+ {Mref, Reply} ->
+ erlang:demonitor(Mref, [flush]),
+ {ok, Reply};
+ {'DOWN', Mref, _, _, noconnection} ->
+ Node = get_node(Process),
+ exit({nodedown, Node});
+ {'DOWN', Mref, _, _, Reason} ->
+ exit(Reason)
+ after Timeout ->
+ erlang:demonitor(Mref, [flush]),
+ exit(timeout)
end.
get_node(Process) ->
@@ -212,19 +192,6 @@ get_node(Process) ->
node(Process)
end.
-wait_resp(Node, Tag, Timeout) ->
- receive
- {Tag, Reply} ->
- monitor_node(Node, false),
- {ok, Reply};
- {nodedown, Node} ->
- monitor_node(Node, false),
- exit({nodedown, Node})
- after Timeout ->
- monitor_node(Node, false),
- exit(timeout)
- end.
-
%%
%% Send a reply to the client.
%%
@@ -422,7 +389,7 @@ debug_options(Name, Opts) ->
try sys:debug_options(Options)
catch _:_ ->
error_logger:format(
- "~p: ignoring erroneous debug options - ~p~n",
+ "~tp: ignoring erroneous debug options - ~tp~n",
[Name,Options]),
[]
end;
diff --git a/lib/stdlib/src/gen_event.erl b/lib/stdlib/src/gen_event.erl
index da2b0da3ca..8213282867 100644
--- a/lib/stdlib/src/gen_event.erl
+++ b/lib/stdlib/src/gen_event.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -47,16 +47,19 @@
system_replace_state/2,
format_status/2]).
+%% logger callback
+-export([format_log/1]).
+
-export_type([handler/0, handler_args/0, add_handler_ret/0,
del_handler_ret/0]).
--import(error_logger, [error_msg/2]).
-
-record(handler, {module :: atom(),
id = false,
state,
supervised = false :: 'false' | pid()}).
+-include("logger.hrl").
+
%%%=========================================================================
%%% API
%%%=========================================================================
@@ -119,14 +122,15 @@
-type add_handler_ret() :: ok | term() | {'EXIT',term()}.
-type del_handler_ret() :: ok | term() | {'EXIT',term()}.
--type emgr_name() :: {'local', atom()} | {'global', atom()}
+-type emgr_name() :: {'local', atom()} | {'global', term()}
| {'via', atom(), term()}.
-type debug_flag() :: 'trace' | 'log' | 'statistics' | 'debug'
| {'logfile', string()}.
-type option() :: {'timeout', timeout()}
| {'debug', [debug_flag()]}
- | {'spawn_opt', [proc_lib:spawn_option()]}.
--type emgr_ref() :: atom() | {atom(), atom()} | {'global', atom()}
+ | {'spawn_opt', [proc_lib:spawn_option()]}
+ | {'hibernate_after', timeout()}.
+-type emgr_ref() :: atom() | {atom(), atom()} | {'global', term()}
| {'via', atom(), term()} | pid().
-type start_ret() :: {'ok', pid()} | {'error', term()}.
@@ -142,7 +146,7 @@
%% start_link()
%% start_link(MgrName | Options)
%% start_link(MgrName, Options)
-%% MgrName ::= {local, atom()} | {global, atom()} | {via, atom(), term()}
+%% MgrName ::= {local, atom()} | {global, term()} | {via, atom(), term()}
%% Options ::= [{timeout, Timeout} | {debug, [Flag]} | {spawn_opt,SOpts}]
%% Flag ::= trace | log | {logfile, File} | statistics | debug
%% (debug == log && statistics)
@@ -441,15 +445,15 @@ system_replace_state(StateFun, [ServerName, MSL, HibernateAfterTimeout, Hib]) ->
print_event(Dev, {in, Msg}, Name) ->
case Msg of
{notify, Event} ->
- io:format(Dev, "*DBG* ~p got event ~p~n", [Name, Event]);
+ io:format(Dev, "*DBG* ~tp got event ~tp~n", [Name, Event]);
{_,_,{call, Handler, Query}} ->
- io:format(Dev, "*DBG* ~p(~p) got call ~p~n",
+ io:format(Dev, "*DBG* ~tp(~tp) got call ~tp~n",
[Name, Handler, Query]);
_ ->
- io:format(Dev, "*DBG* ~p got ~p~n", [Name, Msg])
+ io:format(Dev, "*DBG* ~tp got ~tp~n", [Name, Msg])
end;
print_event(Dev, Dbg, Name) ->
- io:format(Dev, "*DBG* ~p : ~p~n", [Name, Dbg]).
+ io:format(Dev, "*DBG* ~tp : ~tp~n", [Name, Dbg]).
%% server_add_handler(Handler, Args, MSL) -> {Ret, MSL'}.
@@ -582,9 +586,13 @@ server_update(Handler1, Func, Event, SName) ->
remove, SName, normal),
no;
{'EXIT', {undef, [{Mod1, handle_info, [_,_], _}|_]}} ->
- error_logger:warning_msg("** Undefined handle_info in ~p~n"
- "** Unhandled message: ~p~n", [Mod1, Event]),
- {ok, Handler1};
+ ?LOG_WARNING(#{label=>{gen_event,no_handle_info},
+ module=>Mod1,
+ message=>Event},
+ #{domain=>[otp],
+ report_cb=>fun gen_event:format_log/1,
+ error_logger=>#{tag=>warning_msg}}), % warningmap??
+ {ok, Handler1};
Other ->
do_terminate(Mod1, Handler1, {error, Other}, State,
Event, SName, crash),
@@ -736,6 +744,23 @@ report_error(_Handler, normal, _, _, _) -> ok;
report_error(_Handler, shutdown, _, _, _) -> ok;
report_error(_Handler, {swapped,_,_}, _, _, _) -> ok;
report_error(Handler, Reason, State, LastIn, SName) ->
+ ?LOG_ERROR(#{label=>{gen_event,terminate},
+ handler=>handler(Handler),
+ name=>SName,
+ last_message=>LastIn,
+ state=>format_status(terminate,Handler#handler.module,
+ get(),State),
+ reason=>Reason},
+ #{domain=>[otp],
+ report_cb=>fun gen_event:format_log/1,
+ error_logger=>#{tag=>error}}).
+
+format_log(#{label:={gen_event,terminate},
+ handler:=Handler,
+ name:=SName,
+ last_message:=LastIn,
+ state:=State,
+ reason:=Reason}) ->
Reason1 =
case Reason of
{'EXIT',{undef,[{M,F,A,L}|MFAs]}} ->
@@ -755,23 +780,18 @@ report_error(Handler, Reason, State, LastIn, SName) ->
_ ->
Reason
end,
- Mod = Handler#handler.module,
- FmtState = case erlang:function_exported(Mod, format_status, 2) of
- true ->
- Args = [get(), State],
- case catch Mod:format_status(terminate, Args) of
- {'EXIT', _} -> State;
- Else -> Else
- end;
- _ ->
- State
- end,
- error_msg("** gen_event handler ~p crashed.~n"
- "** Was installed in ~p~n"
- "** Last event was: ~p~n"
- "** When handler state == ~p~n"
- "** Reason == ~p~n",
- [handler(Handler),SName,LastIn,FmtState,Reason1]).
+ {"** gen_event handler ~p crashed.~n"
+ "** Was installed in ~tp~n"
+ "** Last event was: ~tp~n"
+ "** When handler state == ~tp~n"
+ "** Reason == ~tp~n",
+ [Handler,SName,LastIn,State,Reason1]};
+format_log(#{label:={gen_event,no_handle_info},
+ module:=Mod,
+ message:=Msg}) ->
+ {"** Undefined handle_info in ~tp~n"
+ "** Unhandled message: ~tp~n",
+ [Mod, Msg]}.
handler(Handler) when not Handler#handler.id ->
Handler#handler.module;
@@ -804,17 +824,21 @@ format_status(Opt, StatusData) ->
[PDict, SysState, Parent, _Debug, [ServerName, MSL, _HibernateAfterTimeout, _Hib]] = StatusData,
Header = gen:format_status_header("Status for event handler",
ServerName),
- FmtMSL = [case erlang:function_exported(Mod, format_status, 2) of
- true ->
- Args = [PDict, State],
- case catch Mod:format_status(Opt, Args) of
- {'EXIT', _} -> MSL;
- Else -> MS#handler{state = Else}
- end;
- _ ->
- MS
- end || #handler{module = Mod, state = State} = MS <- MSL],
+ FmtMSL = [MS#handler{state=format_status(Opt, Mod, PDict, State)}
+ || #handler{module = Mod, state = State} = MS <- MSL],
[{header, Header},
{data, [{"Status", SysState},
{"Parent", Parent}]},
{items, {"Installed handlers", FmtMSL}}].
+
+format_status(Opt, Mod, PDict, State) ->
+ case erlang:function_exported(Mod, format_status, 2) of
+ true ->
+ Args = [PDict, State],
+ case catch Mod:format_status(Opt, Args) of
+ {'EXIT', _} -> State;
+ Else -> Else
+ end;
+ false ->
+ State
+ end.
diff --git a/lib/stdlib/src/gen_fsm.erl b/lib/stdlib/src/gen_fsm.erl
index 9ef0ca818c..caaaf8fa2e 100644
--- a/lib/stdlib/src/gen_fsm.erl
+++ b/lib/stdlib/src/gen_fsm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -105,6 +105,8 @@
%%%
%%% ---------------------------------------------------
+-include("logger.hrl").
+
-export([start/3, start/4,
start_link/3, start_link/4,
stop/1, stop/3,
@@ -124,27 +126,28 @@
system_replace_state/2,
format_status/2]).
--deprecated({start, 3, next_major_release}).
--deprecated({start, 4, next_major_release}).
--deprecated({start_link, 3, next_major_release}).
--deprecated({start_link, 4, next_major_release}).
--deprecated({stop, 1, next_major_release}).
--deprecated({stop, 3, next_major_release}).
--deprecated({send_event, 2, next_major_release}).
--deprecated({sync_send_event, 2, next_major_release}).
--deprecated({sync_send_event, 3, next_major_release}).
--deprecated({send_all_state_event, 2, next_major_release}).
--deprecated({sync_send_all_state_event, 2, next_major_release}).
--deprecated({sync_send_all_state_event, 3, next_major_release}).
--deprecated({reply, 2, next_major_release}).
--deprecated({start_timer, 2, next_major_release}).
--deprecated({send_event_after, 2, next_major_release}).
--deprecated({cancel_timer, 1, next_major_release}).
--deprecated({enter_loop, 4, next_major_release}).
--deprecated({enter_loop, 5, next_major_release}).
--deprecated({enter_loop, 6, next_major_release}).
-
--import(error_logger, [format/2]).
+%% logger callback
+-export([format_log/1]).
+
+-deprecated({start, 3, eventually}).
+-deprecated({start, 4, eventually}).
+-deprecated({start_link, 3, eventually}).
+-deprecated({start_link, 4, eventually}).
+-deprecated({stop, 1, eventually}).
+-deprecated({stop, 3, eventually}).
+-deprecated({send_event, 2, eventually}).
+-deprecated({sync_send_event, 2, eventually}).
+-deprecated({sync_send_event, 3, eventually}).
+-deprecated({send_all_state_event, 2, eventually}).
+-deprecated({sync_send_all_state_event, 2, eventually}).
+-deprecated({sync_send_all_state_event, 3, eventually}).
+-deprecated({reply, 2, eventually}).
+-deprecated({start_timer, 2, eventually}).
+-deprecated({send_event_after, 2, eventually}).
+-deprecated({cancel_timer, 1, eventually}).
+-deprecated({enter_loop, 4, eventually}).
+-deprecated({enter_loop, 5, eventually}).
+-deprecated({enter_loop, 6, eventually}).
%%% ---------------------------------------------------
%%% Interface functions.
@@ -198,7 +201,7 @@
%%% start(Name, Mod, Args, Options)
%%% start_link(Mod, Args, Options)
%%% start_link(Name, Mod, Args, Options) where:
-%%% Name ::= {local, atom()} | {global, atom()} | {via, atom(), term()}
+%%% Name ::= {local, atom()} | {global, term()} | {via, atom(), term()}
%%% Mod ::= atom(), callback module implementing the 'real' fsm
%%% Args ::= term(), init arguments (to Mod:init/1)
%%% Options ::= [{debug, [Flag]}]
@@ -452,30 +455,30 @@ system_replace_state(StateFun, [Name, StateName, StateData, Mod, Time, Hibernate
print_event(Dev, {in, Msg}, {Name, StateName}) ->
case Msg of
{'$gen_event', Event} ->
- io:format(Dev, "*DBG* ~p got event ~p in state ~w~n",
+ io:format(Dev, "*DBG* ~tp got event ~tp in state ~tw~n",
[Name, Event, StateName]);
{'$gen_all_state_event', Event} ->
io:format(Dev,
- "*DBG* ~p got all_state_event ~p in state ~w~n",
+ "*DBG* ~tp got all_state_event ~tp in state ~tw~n",
[Name, Event, StateName]);
{timeout, Ref, {'$gen_timer', Message}} ->
io:format(Dev,
- "*DBG* ~p got timer ~p in state ~w~n",
+ "*DBG* ~tp got timer ~tp in state ~tw~n",
[Name, {timeout, Ref, Message}, StateName]);
{timeout, _Ref, {'$gen_event', Event}} ->
io:format(Dev,
- "*DBG* ~p got timer ~p in state ~w~n",
+ "*DBG* ~tp got timer ~tp in state ~tw~n",
[Name, Event, StateName]);
_ ->
- io:format(Dev, "*DBG* ~p got ~p in state ~w~n",
+ io:format(Dev, "*DBG* ~tp got ~tp in state ~tw~n",
[Name, Msg, StateName])
end;
print_event(Dev, {out, Msg, To, StateName}, Name) ->
- io:format(Dev, "*DBG* ~p sent ~p to ~w~n"
- " and switched to state ~w~n",
+ io:format(Dev, "*DBG* ~tp sent ~tp to ~tw~n"
+ " and switched to state ~tw~n",
[Name, Msg, To, StateName]);
print_event(Dev, return, {Name, StateName}) ->
- io:format(Dev, "*DBG* ~p switched to state ~w~n",
+ io:format(Dev, "*DBG* ~tp switched to state ~tw~n",
[Name, StateName]).
handle_msg(Msg, Parent, Name, StateName, StateData, Mod, _Time, HibernateAfterTimeout) -> %No debug here
@@ -499,8 +502,12 @@ handle_msg(Msg, Parent, Name, StateName, StateData, Mod, _Time, HibernateAfterTi
reply(From, Reply),
exit(R);
{'EXIT', {undef, [{Mod, handle_info, [_,_,_], _}|_]}} ->
- error_logger:warning_msg("** Undefined handle_info in ~p~n"
- "** Unhandled message: ~p~n", [Mod, Msg]),
+ ?LOG_WARNING(#{label=>{gen_fsm,no_handle_info},
+ module=>Mod,
+ message=>Msg},
+ #{domain=>[otp],
+ report_cb=>fun gen_fsm:format_log/1,
+ error_logger=>#{tag=>warning_msg}}),
loop(Parent, Name, StateName, StateData, Mod, infinity, HibernateAfterTimeout, []);
{'EXIT', What} ->
terminate(What, Name, Msg, Mod, StateName, StateData, []);
@@ -603,6 +610,24 @@ terminate(Reason, Name, Msg, Mod, StateName, StateData, Debug) ->
end.
error_info(Reason, Name, Msg, StateName, StateData, Debug) ->
+ ?LOG_ERROR(#{label=>{gen_fsm,terminate},
+ name=>Name,
+ last_message=>Msg,
+ state_name=>StateName,
+ state_data=>StateData,
+ reason=>Reason},
+ #{domain=>[otp],
+ report_cb=>fun gen_fsm:format_log/1,
+ error_logger=>#{tag=>error}}),
+ sys:print_log(Debug),
+ ok.
+
+format_log(#{label:={gen_fsm,terminate},
+ name:=Name,
+ last_message:=Msg,
+ state_name:=StateName,
+ state_data:=StateData,
+ reason:=Reason}) ->
Reason1 =
case Reason of
{undef,[{M,F,A,L}|MFAs]} ->
@@ -620,29 +645,33 @@ error_info(Reason, Name, Msg, StateName, StateData, Debug) ->
_ ->
Reason
end,
- Str = "** State machine ~p terminating \n" ++
- get_msg_str(Msg) ++
- "** When State == ~p~n"
- "** Data == ~p~n"
- "** Reason for termination = ~n** ~p~n",
- format(Str, [Name, get_msg(Msg), StateName, StateData, Reason1]),
- sys:print_log(Debug),
- ok.
+ {"** State machine ~tp terminating \n" ++
+ get_msg_str(Msg) ++
+ "** When State == ~tp~n"
+ "** Data == ~tp~n"
+ "** Reason for termination = ~n** ~tp~n",
+ [Name, get_msg(Msg), StateName, StateData, Reason1]};
+format_log(#{label:={gen_fsm,no_handle_info},
+ module:=Mod,
+ message:=Msg}) ->
+ {"** Undefined handle_info in ~p~n"
+ "** Unhandled message: ~tp~n",
+ [Mod, Msg]}.
get_msg_str({'$gen_event', _Event}) ->
- "** Last event in was ~p~n";
+ "** Last event in was ~tp~n";
get_msg_str({'$gen_sync_event', _Event}) ->
- "** Last sync event in was ~p~n";
+ "** Last sync event in was ~tp~n";
get_msg_str({'$gen_all_state_event', _Event}) ->
- "** Last event in was ~p (for all states)~n";
+ "** Last event in was ~tp (for all states)~n";
get_msg_str({'$gen_sync_all_state_event', _Event}) ->
- "** Last sync event in was ~p (for all states)~n";
+ "** Last sync event in was ~tp (for all states)~n";
get_msg_str({timeout, _Ref, {'$gen_timer', _Msg}}) ->
- "** Last timer event in was ~p~n";
+ "** Last timer event in was ~tp~n";
get_msg_str({timeout, _Ref, {'$gen_event', _Msg}}) ->
- "** Last timer event in was ~p~n";
+ "** Last timer event in was ~tp~n";
get_msg_str(_Msg) ->
- "** Last message in was ~p~n".
+ "** Last message in was ~tp~n".
get_msg({'$gen_event', Event}) -> Event;
get_msg({'$gen_sync_event', Event}) -> Event;
diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl
index a3d53efd0d..44e9231ebe 100644
--- a/lib/stdlib/src/gen_server.erl
+++ b/lib/stdlib/src/gen_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -104,35 +104,44 @@
system_replace_state/2,
format_status/2]).
+%% logger callback
+-export([format_log/1]).
+
%% Internal exports
-export([init_it/6]).
+-include("logger.hrl").
+
-define(
STACKTRACE(),
- try throw(ok) catch _ -> erlang:get_stacktrace() end).
+ element(2, erlang:process_info(self(), current_stacktrace))).
%%%=========================================================================
%%% API
%%%=========================================================================
-callback init(Args :: term()) ->
- {ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} |
+ {ok, State :: term()} | {ok, State :: term(), timeout() | hibernate | {continue, term()}} |
{stop, Reason :: term()} | ignore.
-callback handle_call(Request :: term(), From :: {pid(), Tag :: term()},
State :: term()) ->
{reply, Reply :: term(), NewState :: term()} |
- {reply, Reply :: term(), NewState :: term(), timeout() | hibernate} |
+ {reply, Reply :: term(), NewState :: term(), timeout() | hibernate | {continue, term()}} |
{noreply, NewState :: term()} |
- {noreply, NewState :: term(), timeout() | hibernate} |
+ {noreply, NewState :: term(), timeout() | hibernate | {continue, term()}} |
{stop, Reason :: term(), Reply :: term(), NewState :: term()} |
{stop, Reason :: term(), NewState :: term()}.
-callback handle_cast(Request :: term(), State :: term()) ->
{noreply, NewState :: term()} |
- {noreply, NewState :: term(), timeout() | hibernate} |
+ {noreply, NewState :: term(), timeout() | hibernate | {continue, term()}} |
{stop, Reason :: term(), NewState :: term()}.
-callback handle_info(Info :: timeout | term(), State :: term()) ->
{noreply, NewState :: term()} |
- {noreply, NewState :: term(), timeout() | hibernate} |
+ {noreply, NewState :: term(), timeout() | hibernate | {continue, term()}} |
+ {stop, Reason :: term(), NewState :: term()}.
+-callback handle_continue(Info :: term(), State :: term()) ->
+ {noreply, NewState :: term()} |
+ {noreply, NewState :: term(), timeout() | hibernate | {continue, term()}} |
{stop, Reason :: term(), NewState :: term()}.
-callback terminate(Reason :: (normal | shutdown | {shutdown, term()} |
term()),
@@ -149,7 +158,7 @@
Status :: term().
-optional_callbacks(
- [handle_info/2, terminate/2, code_change/3, format_status/2]).
+ [handle_info/2, handle_continue/2, terminate/2, code_change/3, format_status/2]).
%%% -----------------------------------------------------------------
%%% Starts a generic server.
@@ -157,7 +166,7 @@
%%% start(Name, Mod, Args, Options)
%%% start_link(Mod, Args, Options)
%%% start_link(Name, Mod, Args, Options) where:
-%%% Name ::= {local, atom()} | {global, atom()} | {via, atom(), term()}
+%%% Name ::= {local, atom()} | {global, term()} | {via, atom(), term()}
%%% Mod ::= atom(), callback module implementing the 'real' server
%%% Args ::= term(), init arguments (to Mod:init/1)
%%% Options ::= [{timeout, Timeout} | {debug, [Flag]}]
@@ -309,7 +318,7 @@ enter_loop(Mod, Options, State, ServerName, Timeout) ->
Name = gen:get_proc_name(ServerName),
Parent = gen:get_parent(),
Debug = gen:debug_options(Name, Options),
- HibernateAfterTimeout = gen:hibernate_after(Options),
+ HibernateAfterTimeout = gen:hibernate_after(Options),
loop(Parent, Name, State, Mod, Timeout, HibernateAfterTimeout, Debug).
%%%========================================================================
@@ -365,7 +374,7 @@ init_it(Mod, Args) ->
{ok, Mod:init(Args)}
catch
throw:R -> {ok, R};
- Class:R -> {'EXIT', Class, R, erlang:get_stacktrace()}
+ Class:R:S -> {'EXIT', Class, R, S}
end.
%%%========================================================================
@@ -374,6 +383,19 @@ init_it(Mod, Args) ->
%%% ---------------------------------------------------
%%% The MAIN loop.
%%% ---------------------------------------------------
+
+loop(Parent, Name, State, Mod, {continue, Continue} = Msg, HibernateAfterTimeout, Debug) ->
+ Reply = try_dispatch(Mod, handle_continue, Continue, State),
+ case Debug of
+ [] ->
+ handle_common_reply(Reply, Parent, Name, undefined, Msg, Mod,
+ HibernateAfterTimeout, State);
+ _ ->
+ Debug1 = sys:handle_debug(Debug, fun print_event/3, Name, Msg),
+ handle_common_reply(Reply, Parent, Name, undefined, Msg, Mod,
+ HibernateAfterTimeout, State, Debug1)
+ end;
+
loop(Parent, Name, State, Mod, hibernate, HibernateAfterTimeout, Debug) ->
proc_lib:hibernate(?MODULE,wake_hib,[Parent, Name, State, Mod, HibernateAfterTimeout, Debug]);
@@ -420,12 +442,11 @@ decode_msg(Msg, Parent, Name, State, Mod, Time, HibernateAfterTimeout, Debug, Hi
%%% Send/receive functions
%%% ---------------------------------------------------
do_send(Dest, Msg) ->
- case catch erlang:send(Dest, Msg, [noconnect]) of
- noconnect ->
- spawn(erlang, send, [Dest,Msg]);
- Other ->
- Other
- end.
+ try erlang:send(Dest, Msg)
+ catch
+ error:_ -> ok
+ end,
+ ok.
do_multi_call(Nodes, Name, Req, infinity) ->
Tag = make_ref(),
@@ -617,18 +638,22 @@ try_dispatch(Mod, Func, Msg, State) ->
catch
throw:R ->
{ok, R};
- error:undef = R when Func == handle_info ->
+ error:undef = R:Stacktrace when Func == handle_info ->
case erlang:function_exported(Mod, handle_info, 2) of
false ->
- error_logger:warning_msg("** Undefined handle_info in ~p~n"
- "** Unhandled message: ~p~n",
- [Mod, Msg]),
+ ?LOG_WARNING(
+ #{label=>{gen_server,no_handle_info},
+ module=>Mod,
+ message=>Msg},
+ #{domain=>[otp],
+ report_cb=>fun gen_server:format_log/1,
+ error_logger=>#{tag=>warning_msg}}),
{ok, {noreply, State}};
true ->
- {'EXIT', error, R, erlang:get_stacktrace()}
+ {'EXIT', error, R, Stacktrace}
end;
- Class:R ->
- {'EXIT', Class, R, erlang:get_stacktrace()}
+ Class:R:Stacktrace ->
+ {'EXIT', Class, R, Stacktrace}
end.
try_handle_call(Mod, Msg, From, State) ->
@@ -637,8 +662,8 @@ try_handle_call(Mod, Msg, From, State) ->
catch
throw:R ->
{ok, R};
- Class:R ->
- {'EXIT', Class, R, erlang:get_stacktrace()}
+ Class:R:Stacktrace ->
+ {'EXIT', Class, R, Stacktrace}
end.
try_terminate(Mod, Reason, State) ->
@@ -649,8 +674,8 @@ try_terminate(Mod, Reason, State) ->
catch
throw:R ->
{ok, R};
- Class:R ->
- {'EXIT', Class, R, erlang:get_stacktrace()}
+ Class:R:Stacktrace ->
+ {'EXIT', Class, R, Stacktrace}
end;
false ->
{ok, ok}
@@ -785,21 +810,21 @@ system_replace_state(StateFun, [Name, State, Mod, Time, HibernateAfterTimeout])
print_event(Dev, {in, Msg}, Name) ->
case Msg of
{'$gen_call', {From, _Tag}, Call} ->
- io:format(Dev, "*DBG* ~p got call ~p from ~w~n",
+ io:format(Dev, "*DBG* ~tp got call ~tp from ~w~n",
[Name, Call, From]);
{'$gen_cast', Cast} ->
- io:format(Dev, "*DBG* ~p got cast ~p~n",
+ io:format(Dev, "*DBG* ~tp got cast ~tp~n",
[Name, Cast]);
_ ->
- io:format(Dev, "*DBG* ~p got ~p~n", [Name, Msg])
+ io:format(Dev, "*DBG* ~tp got ~tp~n", [Name, Msg])
end;
print_event(Dev, {out, Msg, To, State}, Name) ->
- io:format(Dev, "*DBG* ~p sent ~p to ~w, new state ~w~n",
+ io:format(Dev, "*DBG* ~tp sent ~tp to ~w, new state ~tp~n",
[Name, Msg, To, State]);
print_event(Dev, {noreply, State}, Name) ->
- io:format(Dev, "*DBG* ~p new state ~w~n", [Name, State]);
+ io:format(Dev, "*DBG* ~tp new state ~tp~n", [Name, State]);
print_event(Dev, Event, Name) ->
- io:format(Dev, "*DBG* ~p dbg ~p~n", [Name, Event]).
+ io:format(Dev, "*DBG* ~tp dbg ~tp~n", [Name, Event]).
%%% ---------------------------------------------------
@@ -833,8 +858,7 @@ terminate(Class, Reason, Stacktrace, ReportReason, Name, From, Msg, Mod, State,
Reply = try_terminate(Mod, terminate_reason(Class, Reason, Stacktrace), State),
case Reply of
{'EXIT', C, R, S} ->
- FmtState = format_status(terminate, Mod, get(), State),
- error_info({R, S}, Name, From, Msg, FmtState, Debug),
+ error_info({R, S}, Name, From, Msg, Mod, State, Debug),
erlang:raise(C, R, S);
_ ->
case {Class, Reason} of
@@ -842,8 +866,7 @@ terminate(Class, Reason, Stacktrace, ReportReason, Name, From, Msg, Mod, State,
{exit, shutdown} -> ok;
{exit, {shutdown,_}} -> ok;
_ ->
- FmtState = format_status(terminate, Mod, get(), State),
- error_info(ReportReason, Name, From, Msg, FmtState, Debug)
+ error_info(ReportReason, Name, From, Msg, Mod, State, Debug)
end
end,
case Stacktrace of
@@ -856,12 +879,46 @@ terminate(Class, Reason, Stacktrace, ReportReason, Name, From, Msg, Mod, State,
terminate_reason(error, Reason, Stacktrace) -> {Reason, Stacktrace};
terminate_reason(exit, Reason, _Stacktrace) -> Reason.
-error_info(_Reason, application_controller, _From, _Msg, _State, _Debug) ->
+error_info(_Reason, application_controller, _From, _Msg, _Mod, _State, _Debug) ->
%% OTP-5811 Don't send an error report if it's the system process
%% application_controller which is terminating - let init take care
%% of it instead
ok;
-error_info(Reason, Name, From, Msg, State, Debug) ->
+error_info(Reason, Name, From, Msg, Mod, State, Debug) ->
+ ?LOG_ERROR(#{label=>{gen_server,terminate},
+ name=>Name,
+ last_message=>Msg,
+ state=>format_status(terminate, Mod, get(), State),
+ reason=>Reason,
+ client_info=>client_stacktrace(From)},
+ #{domain=>[otp],
+ report_cb=>fun gen_server:format_log/1,
+ error_logger=>#{tag=>error}}),
+ sys:print_log(Debug),
+ ok.
+
+client_stacktrace(undefined) ->
+ undefined;
+client_stacktrace({From,_Tag}) ->
+ client_stacktrace(From);
+client_stacktrace(From) when is_pid(From), node(From) =:= node() ->
+ case process_info(From, [current_stacktrace, registered_name]) of
+ undefined ->
+ {From,dead};
+ [{current_stacktrace, Stacktrace}, {registered_name, []}] ->
+ {From,{From,Stacktrace}};
+ [{current_stacktrace, Stacktrace}, {registered_name, Name}] ->
+ {From,{Name,Stacktrace}}
+ end;
+client_stacktrace(From) when is_pid(From) ->
+ {From,remote}.
+
+format_log(#{label:={gen_server,terminate},
+ name:=Name,
+ last_message:=Msg,
+ state:=State,
+ reason:=Reason,
+ client_info:=Client}) ->
Reason1 =
case Reason of
{undef,[{M,F,A,L}|MFAs]} ->
@@ -879,34 +936,29 @@ error_info(Reason, Name, From, Msg, State, Debug) ->
_ ->
error_logger:limit_term(Reason)
end,
- {ClientFmt, ClientArgs} = client_stacktrace(From),
- LimitedState = error_logger:limit_term(State),
- error_logger:format("** Generic server ~p terminating \n"
- "** Last message in was ~p~n"
- "** When Server state == ~p~n"
- "** Reason for termination == ~n** ~p~n" ++ ClientFmt,
- [Name, Msg, LimitedState, Reason1] ++ ClientArgs),
- sys:print_log(Debug),
- ok.
-client_stacktrace(undefined) ->
+ {ClientFmt,ClientArgs} = format_client_log(Client),
+ {"** Generic server ~tp terminating \n"
+ "** Last message in was ~tp~n"
+ "** When Server state == ~tp~n"
+ "** Reason for termination == ~n** ~tp~n" ++ ClientFmt,
+ [Name, Msg, error_logger:limit_term(State), Reason1] ++ ClientArgs};
+format_log(#{label:={gen_server,no_handle_info},
+ module:=Mod,
+ message:=Msg}) ->
+ {"** Undefined handle_info in ~p~n"
+ "** Unhandled message: ~tp~n",
+ [Mod, Msg]}.
+
+format_client_log(undefined) ->
{"", []};
-client_stacktrace({From, _Tag}) ->
- client_stacktrace(From);
-client_stacktrace(From) when is_pid(From), node(From) =:= node() ->
- case process_info(From, [current_stacktrace, registered_name]) of
- undefined ->
- {"** Client ~p is dead~n", [From]};
- [{current_stacktrace, Stacktrace}, {registered_name, []}] ->
- {"** Client ~p stacktrace~n"
- "** ~p~n",
- [From, Stacktrace]};
- [{current_stacktrace, Stacktrace}, {registered_name, Name}] ->
- {"** Client ~p stacktrace~n"
- "** ~p~n",
- [Name, Stacktrace]}
- end;
-client_stacktrace(From) when is_pid(From) ->
- {"** Client ~p is remote on node ~p~n", [From, node(From)]}.
+format_client_log({From,dead}) ->
+ {"** Client ~p is dead~n", [From]};
+format_client_log({From,remote}) ->
+ {"** Client ~p is remote on node ~p~n", [From, node(From)]};
+format_client_log({_From,{Name,Stacktrace}}) ->
+ {"** Client ~tp stacktrace~n"
+ "** ~tp~n",
+ [Name, Stacktrace]}.
%%-----------------------------------------------------------------
%% Status information
diff --git a/lib/stdlib/src/gen_statem.erl b/lib/stdlib/src/gen_statem.erl
index b5e9da1e66..faa43fbc1e 100644
--- a/lib/stdlib/src/gen_statem.erl
+++ b/lib/stdlib/src/gen_statem.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2016-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2016-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,6 +19,8 @@
%%
-module(gen_statem).
+-include("logger.hrl").
+
%% API
-export(
[start/3,start/4,start_link/3,start_link/4,
@@ -44,6 +46,9 @@
-export(
[wakeup_from_hibernate/3]).
+%% logger callback
+-export([format_log/1]).
+
%% Type exports for templates and callback modules
-export_type(
[event_type/0,
@@ -78,9 +83,11 @@
-type data() :: term().
-type event_type() ::
- {'call',From :: from()} | 'cast' | 'info' |
- 'timeout' | {'timeout', Name :: term()} | 'state_timeout' |
- 'internal'.
+ external_event_type() | timeout_event_type() | 'internal'.
+-type external_event_type() ::
+ {'call',From :: from()} | 'cast' | 'info'.
+-type timeout_event_type() ::
+ 'timeout' | {'timeout', Name :: term()} | 'state_timeout'.
-type callback_mode_result() ::
callback_mode() | [callback_mode() | state_enter()].
@@ -138,8 +145,10 @@
-type enter_action() ::
'hibernate' | % Set the hibernate option
{'hibernate', Hibernate :: hibernate()} |
- %%
- (Timeout :: event_timeout()) | % {timeout,Timeout}
+ timeout_action() |
+ reply_action().
+-type timeout_action() ::
+ (Time :: event_timeout()) | % {timeout,Time,Time}
{'timeout', % Set the event_timeout option
Time :: event_timeout(), EventContent :: term()} |
{'timeout', % Set the event_timeout option
@@ -159,9 +168,7 @@
{'state_timeout', % Set the state_timeout option
Time :: state_timeout(),
EventContent :: term(),
- Options :: (timeout_option() | [timeout_option()])} |
- %%
- reply_action().
+ Options :: (timeout_option() | [timeout_option()])}.
-type reply_action() ::
{'reply', % Reply to a caller
From :: from(), Reply :: term()}.
@@ -296,7 +303,7 @@
(Reason :: term()).
%% Format the callback module state in some sensible that is
-%% often condensed way. For StatusOption =:= 'normal' the perferred
+%% often condensed way. For StatusOption =:= 'normal' the preferred
%% return term is [{data,[{"State",FormattedState}]}], and for
%% StatusOption =:= 'terminate' it is just FormattedState.
-callback format_status(
@@ -320,7 +327,14 @@
handle_event/4 % For callback_mode() =:= handle_event_function
]).
+
+
%% Type validation functions
+-compile(
+ {inline,
+ [callback_mode/1, state_enter/1,
+ event_type/1, from/1, timeout_event_type/1]}).
+%%
callback_mode(CallbackMode) ->
case CallbackMode of
state_functions -> true;
@@ -328,28 +342,81 @@ callback_mode(CallbackMode) ->
_ -> false
end.
%%
-from({Pid,_}) when is_pid(Pid) -> true;
-from(_) -> false.
+state_enter(StateEnter) ->
+ case StateEnter of
+ state_enter ->
+ true;
+ _ ->
+ false
+ end.
%%
-event_type({call,From}) ->
- from(From);
event_type(Type) ->
case Type of
{call,From} -> from(From);
+ %%
cast -> true;
info -> true;
- timeout -> true;
- state_timeout -> true;
internal -> true;
- {timeout,_} -> true;
- _ -> false
+ _ -> timeout_event_type(Type)
+ end.
+%%
+from({Pid,_}) when is_pid(Pid) -> true;
+from(_) -> false.
+%%
+timeout_event_type(Type) ->
+ case Type of
+ timeout -> true;
+ state_timeout -> true;
+ {timeout,_Name} -> true;
+ _ -> false
end.
-
-define(
STACKTRACE(),
- try throw(ok) catch _ -> erlang:get_stacktrace() end).
+ element(2, erlang:process_info(self(), current_stacktrace))).
+
+-define(not_sys_debug, []).
+%%
+%% This is a macro to only evaluate arguments if Debug =/= [].
+%% Debug is evaluated multiple times.
+-define(
+ sys_debug(Debug, NameState, Entry),
+ case begin Debug end of
+ ?not_sys_debug ->
+ begin Debug end;
+ _ ->
+ sys_debug(begin Debug end, begin NameState end, begin Entry end)
+ end).
+
+-record(state,
+ {callback_mode = undefined :: callback_mode() | undefined,
+ state_enter = false :: boolean(),
+ module :: atom(),
+ name :: atom(),
+ state :: term(),
+ data :: term(),
+ postponed = [] :: [{event_type(),term()}],
+ %%
+ timer_refs = #{} :: % timer ref => the timer's event type
+ #{reference() => timeout_event_type()},
+ timer_types = #{} :: % timer's event type => timer ref
+ #{timeout_event_type() => reference()},
+ cancel_timers = 0 :: non_neg_integer(),
+ %% We add a timer to both timer_refs and timer_types
+ %% when we start it. When we request an asynchronous
+ %% timer cancel we remove it from timer_types. When
+ %% the timer cancel message arrives we remove it from
+ %% timer_refs.
+ %%
+ hibernate = false :: boolean(),
+ hibernate_after = infinity :: timeout()}).
+
+-record(trans_opts,
+ {hibernate = false,
+ postpone = false,
+ timeouts_r = [],
+ next_events_r = []}).
%%%==========================================================================
%%% API
@@ -422,6 +489,10 @@ stop(ServerRef, Reason, Timeout) ->
%% Send an event to a state machine that arrives with type 'event'
-spec cast(ServerRef :: server_ref(), Msg :: term()) -> ok.
+cast(ServerRef, Msg) when is_pid(ServerRef) ->
+ send(ServerRef, wrap_cast(Msg));
+cast(ServerRef, Msg) when is_atom(ServerRef) ->
+ send(ServerRef, wrap_cast(Msg));
cast({global,Name}, Msg) ->
try global:send(Name, wrap_cast(Msg)) of
_ -> ok
@@ -435,10 +506,6 @@ cast({via,RegMod,Name}, Msg) ->
_:_ -> ok
end;
cast({Name,Node} = ServerRef, Msg) when is_atom(Name), is_atom(Node) ->
- send(ServerRef, wrap_cast(Msg));
-cast(ServerRef, Msg) when is_atom(ServerRef) ->
- send(ServerRef, wrap_cast(Msg));
-cast(ServerRef, Msg) when is_pid(ServerRef) ->
send(ServerRef, wrap_cast(Msg)).
%% Call a state machine (synchronous; a reply is expected) that
@@ -455,75 +522,16 @@ call(ServerRef, Request) ->
{'clean_timeout',T :: timeout()} |
{'dirty_timeout',T :: timeout()}) ->
Reply :: term().
+call(ServerRef, Request, infinity = T = Timeout) ->
+ call_dirty(ServerRef, Request, Timeout, T);
+call(ServerRef, Request, {dirty_timeout, T} = Timeout) ->
+ call_dirty(ServerRef, Request, Timeout, T);
+call(ServerRef, Request, {clean_timeout, T} = Timeout) ->
+ call_clean(ServerRef, Request, Timeout, T);
+call(ServerRef, Request, {_, _} = Timeout) ->
+ erlang:error(badarg, [ServerRef,Request,Timeout]);
call(ServerRef, Request, Timeout) ->
- case parse_timeout(Timeout) of
- {dirty_timeout,T} ->
- try gen:call(ServerRef, '$gen_call', Request, T) of
- {ok,Reply} ->
- Reply
- catch
- Class:Reason ->
- erlang:raise(
- Class,
- {Reason,{?MODULE,call,[ServerRef,Request,Timeout]}},
- erlang:get_stacktrace())
- end;
- {clean_timeout,T} ->
- %% Call server through proxy process to dodge any late reply
- Ref = make_ref(),
- Self = self(),
- Pid = spawn(
- fun () ->
- Self !
- try gen:call(
- ServerRef, '$gen_call', Request, T) of
- Result ->
- {Ref,Result}
- catch Class:Reason ->
- {Ref,Class,Reason,
- erlang:get_stacktrace()}
- end
- end),
- Mref = monitor(process, Pid),
- receive
- {Ref,Result} ->
- demonitor(Mref, [flush]),
- case Result of
- {ok,Reply} ->
- Reply
- end;
- {Ref,Class,Reason,Stacktrace} ->
- demonitor(Mref, [flush]),
- erlang:raise(
- Class,
- {Reason,{?MODULE,call,[ServerRef,Request,Timeout]}},
- Stacktrace);
- {'DOWN',Mref,_,_,Reason} ->
- %% There is a theoretical possibility that the
- %% proxy process gets killed between try--of and !
- %% so this clause is in case of that
- exit(Reason)
- end;
- Error when is_atom(Error) ->
- erlang:error(Error, [ServerRef,Request,Timeout])
- end.
-
-parse_timeout(Timeout) ->
- case Timeout of
- {clean_timeout,infinity} ->
- {dirty_timeout,infinity};
- {clean_timeout,_} ->
- Timeout;
- {dirty_timeout,_} ->
- Timeout;
- {_,_} ->
- %% Be nice and throw a badarg for speling errors
- badarg;
- infinity ->
- {dirty_timeout,infinity};
- T ->
- {clean_timeout,T}
- end.
+ call_clean(ServerRef, Request, Timeout, Timeout).
%% Reply from a state machine callback to whom awaits in call/2
-spec reply([reply_action()] | reply_action()) -> ok.
@@ -532,6 +540,7 @@ reply({reply,From,Reply}) ->
reply(Replies) when is_list(Replies) ->
replies(Replies).
%%
+-compile({inline, [reply/2]}).
-spec reply(From :: from(), Reply :: term()) -> ok.
reply({To,Tag}, Reply) when is_pid(To) ->
Msg = {Tag,Reply},
@@ -581,9 +590,58 @@ enter_loop(Module, Opts, State, Data, Server, Actions) ->
%%---------------------------------------------------------------------------
%% API helpers
+-compile({inline, [wrap_cast/1]}).
wrap_cast(Event) ->
{'$gen_cast',Event}.
+call_dirty(ServerRef, Request, Timeout, T) ->
+ try gen:call(ServerRef, '$gen_call', Request, T) of
+ {ok,Reply} ->
+ Reply
+ catch
+ Class:Reason:Stacktrace ->
+ erlang:raise(
+ Class,
+ {Reason,{?MODULE,call,[ServerRef,Request,Timeout]}},
+ Stacktrace)
+ end.
+
+call_clean(ServerRef, Request, Timeout, T) ->
+ %% Call server through proxy process to dodge any late reply
+ Ref = make_ref(),
+ Self = self(),
+ Pid = spawn(
+ fun () ->
+ Self !
+ try gen:call(
+ ServerRef, '$gen_call', Request, T) of
+ Result ->
+ {Ref,Result}
+ catch Class:Reason:Stacktrace ->
+ {Ref,Class,Reason,Stacktrace}
+ end
+ end),
+ Mref = monitor(process, Pid),
+ receive
+ {Ref,Result} ->
+ demonitor(Mref, [flush]),
+ case Result of
+ {ok,Reply} ->
+ Reply
+ end;
+ {Ref,Class,Reason,Stacktrace} ->
+ demonitor(Mref, [flush]),
+ erlang:raise(
+ Class,
+ {Reason,{?MODULE,call,[ServerRef,Request,Timeout]}},
+ Stacktrace);
+ {'DOWN',Mref,_,_,Reason} ->
+ %% There is a theoretical possibility that the
+ %% proxy process gets killed between try--of and !
+ %% so this clause is in case of that
+ exit(Reason)
+ end.
+
replies([{reply,From,Reply}|Replies]) ->
reply(From, Reply),
replies(Replies);
@@ -592,76 +650,39 @@ replies([]) ->
%% Might actually not send the message in case of caught exception
send(Proc, Msg) ->
- try erlang:send(Proc, Msg, [noconnect]) of
- noconnect ->
- _ = spawn(erlang, send, [Proc,Msg]),
- ok;
- ok ->
- ok
+ try erlang:send(Proc, Msg)
catch
- _:_ ->
- ok
- end.
+ error:_ -> ok
+ end,
+ ok.
%% Here the init_it/6 and enter_loop/5,6,7 functions converge
enter(Module, Opts, State, Data, Server, Actions, Parent) ->
%% The values should already have been type checked
Name = gen:get_proc_name(Server),
Debug = gen:debug_options(Name, Opts),
- HibernateAfterTimeout = gen:hibernate_after(Opts),
- Events = [],
- P = [],
+ HibernateAfterTimeout = gen:hibernate_after(Opts),
+ Events = [],
Event = {internal,init_state},
%% We enforce {postpone,false} to ensure that
%% our fake Event gets discarded, thought it might get logged
- NewActions =
- if
- is_list(Actions) ->
- Actions ++ [{postpone,false}];
- true ->
- [Actions,{postpone,false}]
- end,
- TimerRefs = #{},
- %% Key: timer ref
- %% Value: the timer type i.e the timer's event type
- %%
- TimerTypes = #{},
- %% Key: timer type i.e the timer's event type
- %% Value: timer ref
- %%
- %% We add a timer to both timer_refs and timer_types
- %% when we start it. When we request an asynchronous
- %% timer cancel we remove it from timer_types. When
- %% the timer cancel message arrives we remove it from
- %% timer_refs.
- %%
- Hibernate = false,
- CancelTimers = 0,
- S = #{
- callback_mode => undefined,
- state_enter => false,
- module => Module,
- name => Name,
- state => State,
- data => Data,
- postponed => P,
- %%
- %% The following fields are finally set from to the arguments to
- %% loop_event_actions/9 when it finally loops back to loop/3
- %% in loop_event_result/11
- timer_refs => TimerRefs,
- timer_types => TimerTypes,
- hibernate => Hibernate,
- hibernate_after => HibernateAfterTimeout,
- cancel_timers => CancelTimers
- },
- NewDebug = sys_debug(Debug, S, State, {enter,Event,State}),
+ NewActions = listify(Actions) ++ [{postpone,false}],
+ S =
+ #state{
+ module = Module,
+ name = Name,
+ state = State,
+ data = Data,
+ hibernate_after = HibernateAfterTimeout},
+ CallEnter = true,
+ NewDebug = ?sys_debug(Debug, {Name,State}, {enter,Event,State}),
case call_callback_mode(S) of
- {ok,NewS} ->
- loop_event_actions(
+ #state{} = NewS ->
+ loop_event_actions_list(
Parent, NewDebug, NewS,
- Events, Event, State, Data, NewActions, true);
- {Class,Reason,Stacktrace} ->
+ Events, Event, State, Data, false,
+ NewActions, CallEnter);
+ [Class,Reason,Stacktrace] ->
terminate(
Class, Reason, Stacktrace, NewDebug,
S, [Event|Events])
@@ -679,17 +700,14 @@ init_it(Starter, Parent, ServerRef, Module, Args, Opts) ->
catch
Result ->
init_result(Starter, Parent, ServerRef, Module, Result, Opts);
- Class:Reason ->
- Stacktrace = erlang:get_stacktrace(),
+ Class:Reason:Stacktrace ->
Name = gen:get_proc_name(ServerRef),
gen:unregister_name(ServerRef),
proc_lib:init_ack(Starter, {error,Reason}),
error_info(
Class, Reason, Stacktrace,
- #{name => Name,
- callback_mode => undefined,
- state_enter => false},
- [], [], undefined),
+ #state{name = Name},
+ []),
erlang:raise(Class, Reason, Stacktrace)
end.
@@ -719,10 +737,8 @@ init_result(Starter, Parent, ServerRef, Module, Result, Opts) ->
proc_lib:init_ack(Starter, {error,Error}),
error_info(
error, Error, ?STACKTRACE(),
- #{name => Name,
- callback_mode => undefined,
- state_enter => false},
- [], [], undefined),
+ #state{name = Name},
+ []),
exit(Error)
end.
@@ -736,9 +752,10 @@ system_terminate(Reason, _Parent, Debug, S) ->
terminate(exit, Reason, ?STACKTRACE(), Debug, S, []).
system_code_change(
- #{module := Module,
- state := State,
- data := Data} = S,
+ #state{
+ module = Module,
+ state = State,
+ data = Data} = S,
_Mod, OldVsn, Extra) ->
case
try Module:code_change(OldVsn, State, Data, Extra)
@@ -748,29 +765,31 @@ system_code_change(
of
{ok,NewState,NewData} ->
{ok,
- S#{callback_mode := undefined,
- state := NewState,
- data := NewData}};
+ S#state{
+ callback_mode = undefined,
+ state = NewState,
+ data = NewData}};
{ok,_} = Error ->
error({case_clause,Error});
Error ->
Error
end.
-system_get_state(#{state := State, data := Data}) ->
+system_get_state(#state{state = State, data = Data}) ->
{ok,{State,Data}}.
system_replace_state(
StateFun,
- #{state := State,
- data := Data} = S) ->
+ #state{
+ state = State,
+ data = Data} = S) ->
{NewState,NewData} = Result = StateFun({State,Data}),
- {ok,Result,S#{state := NewState, data := NewData}}.
+ {ok,Result,S#state{state = NewState, data = NewData}}.
format_status(
Opt,
[PDict,SysState,Parent,Debug,
- #{name := Name, postponed := P} = S]) ->
+ #state{name = Name, postponed = P} = S]) ->
Header = gen:format_status_header("Status for state machine", Name),
Log = sys:get_debug(log, Debug, []),
[{header,Header},
@@ -789,45 +808,39 @@ format_status(
%% them, not as the real erlang messages. Use trace for that.
%%---------------------------------------------------------------------------
+sys_debug(Debug, NameState, Entry) ->
+ sys:handle_debug(Debug, fun print_event/3, NameState, Entry).
+
print_event(Dev, {in,Event}, {Name,State}) ->
io:format(
- Dev, "*DBG* ~p receive ~s in state ~p~n",
+ Dev, "*DBG* ~tp receive ~ts in state ~tp~n",
[Name,event_string(Event),State]);
print_event(Dev, {out,Reply,{To,_Tag}}, {Name,State}) ->
io:format(
- Dev, "*DBG* ~p send ~p to ~p from state ~p~n",
+ Dev, "*DBG* ~tp send ~tp to ~p from state ~tp~n",
[Name,Reply,To,State]);
print_event(Dev, {terminate,Reason}, {Name,State}) ->
io:format(
- Dev, "*DBG* ~p terminate ~p in state ~p~n",
+ Dev, "*DBG* ~tp terminate ~tp in state ~tp~n",
[Name,Reason,State]);
print_event(Dev, {Tag,Event,NextState}, {Name,State}) ->
StateString =
case NextState of
State ->
- io_lib:format("~p", [State]);
+ io_lib:format("~tp", [State]);
_ ->
- io_lib:format("~p => ~p", [State,NextState])
+ io_lib:format("~tp => ~tp", [State,NextState])
end,
io:format(
- Dev, "*DBG* ~p ~w ~s in state ~s~n",
+ Dev, "*DBG* ~tp ~tw ~ts in state ~ts~n",
[Name,Tag,event_string(Event),StateString]).
event_string(Event) ->
case Event of
{{call,{Pid,_Tag}},Request} ->
- io_lib:format("call ~p from ~w", [Request,Pid]);
+ io_lib:format("call ~tp from ~w", [Request,Pid]);
{EventType,EventContent} ->
- io_lib:format("~w ~p", [EventType,EventContent])
- end.
-
-sys_debug(Debug, #{name := Name}, State, Entry) ->
- case Debug of
- [] ->
- Debug;
- _ ->
- sys:handle_debug(
- Debug, fun print_event/3, {Name,State}, Entry)
+ io_lib:format("~tw ~tp", [EventType,EventContent])
end.
%%%==========================================================================
@@ -844,14 +857,16 @@ wakeup_from_hibernate(Parent, Debug, S) ->
%% and detours through sys:handle_system_message/7 and proc_lib:hibernate/3
%% Entry point for system_continue/3
-loop(Parent, Debug, #{hibernate := true, cancel_timers := 0} = S) ->
+loop(Parent, Debug, #state{hibernate = true, cancel_timers = 0} = S) ->
loop_hibernate(Parent, Debug, S);
loop(Parent, Debug, S) ->
loop_receive(Parent, Debug, S).
loop_hibernate(Parent, Debug, S) ->
+ %%
%% Does not return but restarts process at
%% wakeup_from_hibernate/3 that jumps to loop_receive/3
+ %%
proc_lib:hibernate(
?MODULE, wakeup_from_hibernate, [Parent,Debug,S]),
error(
@@ -859,17 +874,18 @@ loop_hibernate(Parent, Debug, S) ->
{wakeup_from_hibernate,3}}).
%% Entry point for wakeup_from_hibernate/3
-loop_receive(Parent, Debug, #{hibernate_after := HibernateAfterTimeout} = S) ->
+loop_receive(
+ Parent, Debug, #state{hibernate_after = HibernateAfterTimeout} = S) ->
+ %%
receive
Msg ->
case Msg of
{system,Pid,Req} ->
- #{hibernate := Hibernate} = S,
%% Does not return but tail recursively calls
%% system_continue/3 that jumps to loop/3
sys:handle_system_msg(
Req, Pid, Parent, ?MODULE, Debug, S,
- Hibernate);
+ S#state.hibernate);
{'EXIT',Parent,Reason} = EXIT ->
%% EXIT is not a 2-tuple therefore
%% not an event but this will stand out
@@ -877,9 +893,9 @@ loop_receive(Parent, Debug, #{hibernate_after := HibernateAfterTimeout} = S) ->
Q = [EXIT],
terminate(exit, Reason, ?STACKTRACE(), Debug, S, Q);
{timeout,TimerRef,TimerMsg} ->
- #{timer_refs := TimerRefs,
- timer_types := TimerTypes,
- hibernate := Hibernate} = S,
+ #state{
+ timer_refs = TimerRefs,
+ timer_types = TimerTypes} = S,
case TimerRefs of
#{TimerRef := TimerType} ->
%% We know of this timer; is it a running
@@ -889,7 +905,6 @@ loop_receive(Parent, Debug, #{hibernate_after := HibernateAfterTimeout} = S) ->
#{TimerType := TimerRef} ->
%% The timer type maps back to this
%% timer ref, so it was a running timer
- Event = {TimerType,TimerMsg},
%% Unregister the triggered timeout
NewTimerRefs =
maps:remove(TimerRef, TimerRefs),
@@ -897,11 +912,10 @@ loop_receive(Parent, Debug, #{hibernate_after := HibernateAfterTimeout} = S) ->
maps:remove(TimerType, TimerTypes),
loop_receive_result(
Parent, Debug,
- S#{
- timer_refs := NewTimerRefs,
- timer_types := NewTimerTypes},
- Hibernate,
- Event);
+ S#state{
+ timer_refs = NewTimerRefs,
+ timer_types = NewTimerTypes},
+ TimerType, TimerMsg);
_ ->
%% This was a late timeout message
%% from timer being cancelled, so
@@ -911,14 +925,13 @@ loop_receive(Parent, Debug, #{hibernate_after := HibernateAfterTimeout} = S) ->
end;
_ ->
%% Not our timer; present it as an event
- Event = {info,Msg},
- loop_receive_result(
- Parent, Debug, S, Hibernate, Event)
+ loop_receive_result(Parent, Debug, S, info, Msg)
end;
{cancel_timer,TimerRef,_} ->
- #{timer_refs := TimerRefs,
- cancel_timers := CancelTimers,
- hibernate := Hibernate} = S,
+ #state{
+ timer_refs = TimerRefs,
+ cancel_timers = CancelTimers,
+ hibernate = Hibernate} = S,
case TimerRefs of
#{TimerRef := _} ->
%% We must have requested a cancel
@@ -928,9 +941,9 @@ loop_receive(Parent, Debug, #{hibernate_after := HibernateAfterTimeout} = S) ->
maps:remove(TimerRef, TimerRefs),
NewCancelTimers = CancelTimers - 1,
NewS =
- S#{
- timer_refs := NewTimerRefs,
- cancel_timers := NewCancelTimers},
+ S#state{
+ timer_refs = NewTimerRefs,
+ cancel_timers = NewCancelTimers},
if
Hibernate =:= true, NewCancelTimers =:= 0 ->
%% No more cancel_timer msgs to expect;
@@ -942,297 +955,704 @@ loop_receive(Parent, Debug, #{hibernate_after := HibernateAfterTimeout} = S) ->
_ ->
%% Not our cancel_timer msg;
%% present it as an event
- Event = {info,Msg},
- loop_receive_result(
- Parent, Debug, S, Hibernate, Event)
+ loop_receive_result(Parent, Debug, S, info, Msg)
end;
_ ->
%% External msg
- #{hibernate := Hibernate} = S,
- Event =
- case Msg of
- {'$gen_call',From,Request} ->
- {{call,From},Request};
- {'$gen_cast',E} ->
- {cast,E};
- _ ->
- {info,Msg}
- end,
- loop_receive_result(
- Parent, Debug, S, Hibernate, Event)
+ case Msg of
+ {'$gen_call',From,Request} ->
+ loop_receive_result(
+ Parent, Debug, S, {call,From}, Request);
+ {'$gen_cast',Cast} ->
+ loop_receive_result(Parent, Debug, S, cast, Cast);
+ _ ->
+ loop_receive_result(Parent, Debug, S, info, Msg)
+ end
end
after
HibernateAfterTimeout ->
loop_hibernate(Parent, Debug, S)
end.
+loop_receive_result(Parent, ?not_sys_debug, S, Type, Content) ->
+ %% Here is the queue of not yet handled events created
+ Events = [],
+ loop_event(Parent, ?not_sys_debug, S, Events, Type, Content);
loop_receive_result(
- Parent, Debug,
- #{state := State,
- timer_types := TimerTypes, cancel_timers := CancelTimers} = S,
- Hibernate, Event) ->
- %% From now the 'hibernate' field in S is invalid
- %% and will be restored when looping back
- %% in loop_event_result/11
- NewDebug = sys_debug(Debug, S, State, {in,Event}),
+ Parent, Debug, #state{name = Name, state = State} = S, Type, Content) ->
+ NewDebug = sys_debug(Debug, {Name,State}, {in,{Type,Content}}),
%% Here is the queue of not yet handled events created
Events = [],
- %% Cancel any running event timer
- case
- cancel_timer_by_type(timeout, TimerTypes, CancelTimers)
- of
- {_,CancelTimers} ->
- %% No timer cancelled
- loop_event(Parent, NewDebug, S, Events, Event, Hibernate);
- {NewTimerTypes,NewCancelTimers} ->
- %% The timer is removed from NewTimerTypes but
- %% remains in TimerRefs until we get
- %% the cancel_timer msg
- NewS =
- S#{
- timer_types := NewTimerTypes,
- cancel_timers := NewCancelTimers},
- loop_event(Parent, NewDebug, NewS, Events, Event, Hibernate)
- end.
+ loop_event(Parent, NewDebug, S, Events, Type, Content).
%% Entry point for handling an event, received or enqueued
loop_event(
+ Parent, Debug, #state{hibernate = Hibernate} = S,
+ Events, Type, Content) ->
+ %%
+ case Hibernate of
+ true ->
+ %%
+ %% If (this old) Hibernate is true here it can only be
+ %% because it was set from an event action
+ %% and we did not go into hibernation since there were
+ %% events in queue, so we do what the user
+ %% might rely on i.e collect garbage which
+ %% would have happened if we actually hibernated
+ %% and immediately was awakened.
+ %%
+ _ = garbage_collect(),
+ loop_event_state_function(
+ Parent, Debug, S, Events, Type, Content);
+ false ->
+ loop_event_state_function(
+ Parent, Debug, S, Events, Type, Content)
+ end.
+
+%% Call the state function
+loop_event_state_function(
Parent, Debug,
- #{state := State, data := Data} = S,
- Events, {Type,Content} = Event, Hibernate) ->
+ #state{state = State, data = Data} = S,
+ Events, Type, Content) ->
%%
- %% If (this old) Hibernate is true here it can only be
- %% because it was set from an event action
- %% and we did not go into hibernation since there were
- %% events in queue, so we do what the user
- %% might rely on i.e collect garbage which
- %% would have happened if we actually hibernated
- %% and immediately was awakened
- Hibernate andalso garbage_collect(),
+ %% The field 'hibernate' in S is now invalid and will be
+ %% restored when looping back to loop/3 or loop_event/6.
+ %%
+ Event = {Type,Content},
+ TransOpts = false,
case call_state_function(S, Type, Content, State, Data) of
- {ok,Result,NewS} ->
- {NextState,NewData,Actions,EnterCall} =
- parse_event_result(
- true, Debug, NewS,
- Events, Event, State, Data, Result),
- loop_event_actions(
- Parent, Debug, NewS,
- Events, Event, NextState, NewData, Actions, EnterCall);
- {Class,Reason,Stacktrace} ->
+ {Result, NewS} ->
+ loop_event_result(
+ Parent, Debug, NewS,
+ Events, Event, State, Data, TransOpts, Result);
+ [Class,Reason,Stacktrace] ->
terminate(
- Class, Reason, Stacktrace, Debug, S,
- [Event|Events])
+ Class, Reason, Stacktrace, Debug, S, [Event|Events])
end.
-loop_event_actions(
- Parent, Debug,
- #{state := State, state_enter := StateEnter} = S,
- Events, Event, NextState, NewData,
- Actions, EnterCall) ->
- %% Hibernate is reborn here as false being
- %% the default value from parse_actions/4
- case parse_actions(Debug, S, State, Actions) of
- {ok,NewDebug,Hibernate,TimeoutsR,Postpone,NextEventsR} ->
- if
- StateEnter, EnterCall ->
- loop_event_enter(
- Parent, NewDebug, S,
- Events, Event, NextState, NewData,
- Hibernate, TimeoutsR, Postpone, NextEventsR);
- true ->
- loop_event_result(
- Parent, NewDebug, S,
- Events, Event, NextState, NewData,
- Hibernate, TimeoutsR, Postpone, NextEventsR)
- end;
- {Class,Reason,Stacktrace} ->
+%% Make a state enter call to the state function
+loop_event_state_enter(
+ Parent, Debug, #state{state = PrevState} = S,
+ Events, Event, NextState, NewData, TransOpts) ->
+ %%
+ case call_state_function(S, enter, PrevState, NextState, NewData) of
+ {Result, NewS} ->
+ loop_event_result(
+ Parent, Debug, NewS,
+ Events, Event, NextState, NewData, TransOpts, Result);
+ [Class,Reason,Stacktrace] ->
terminate(
- Class, Reason, Stacktrace, Debug, S,
- [Event|Events])
+ Class, Reason, Stacktrace, Debug, S, [Event|Events])
end.
-loop_event_enter(
- Parent, Debug, #{state := State} = S,
- Events, Event, NextState, NewData,
- Hibernate, TimeoutsR, Postpone, NextEventsR) ->
- case call_state_function(S, enter, State, NextState, NewData) of
- {ok,Result,NewS} ->
- case parse_event_result(
- false, Debug, NewS,
- Events, Event, NextState, NewData, Result) of
- {_,NewerData,Actions,EnterCall} ->
- loop_event_enter_actions(
- Parent, Debug, NewS,
- Events, Event, NextState, NewerData,
- Hibernate, TimeoutsR, Postpone, NextEventsR,
- Actions, EnterCall)
- end;
- {Class,Reason,Stacktrace} ->
- terminate(
- Class, Reason, Stacktrace, Debug,
- S#{
- state := NextState,
- data := NewData,
- hibernate := Hibernate},
- [Event|Events])
+%% Process the result from the state function.
+%% When TransOpts =:= false it was a state function call,
+%% otherwise it is an option tuple and it was a state enter call.
+%%
+loop_event_result(
+ Parent, Debug, S,
+ Events, Event, State, Data, TransOpts, Result) ->
+ %%
+ case Result of
+ {next_state,State,NewData} ->
+ loop_event_actions(
+ Parent, Debug, S,
+ Events, Event, State, NewData, TransOpts,
+ [], false);
+ {next_state,NextState,NewData}
+ when TransOpts =:= false ->
+ loop_event_actions(
+ Parent, Debug, S,
+ Events, Event, NextState, NewData, TransOpts,
+ [], true);
+ {next_state,_NextState,_NewData} ->
+ terminate(
+ error,
+ {bad_state_enter_return_from_state_function,Result},
+ ?STACKTRACE(), Debug,
+ S#state{
+ state = State, data = Data,
+ hibernate = hibernate_in_trans_opts(TransOpts)},
+ [Event|Events]);
+ {next_state,State,NewData,Actions} ->
+ loop_event_actions(
+ Parent, Debug, S,
+ Events, Event, State, NewData, TransOpts,
+ Actions, false);
+ {next_state,NextState,NewData,Actions}
+ when TransOpts =:= false ->
+ loop_event_actions(
+ Parent, Debug, S,
+ Events, Event, NextState, NewData, TransOpts,
+ Actions, true);
+ {next_state,_NextState,_NewData,_Actions} ->
+ terminate(
+ error,
+ {bad_state_enter_return_from_state_function,Result},
+ ?STACKTRACE(), Debug,
+ S#state{
+ state = State, data = Data,
+ hibernate = hibernate_in_trans_opts(TransOpts)},
+ [Event|Events]);
+ %%
+ {keep_state,NewData} ->
+ loop_event_actions(
+ Parent, Debug, S,
+ Events, Event, State, NewData, TransOpts,
+ [], false);
+ {keep_state,NewData,Actions} ->
+ loop_event_actions(
+ Parent, Debug, S,
+ Events, Event, State, NewData, TransOpts,
+ Actions, false);
+ %%
+ keep_state_and_data ->
+ loop_event_actions(
+ Parent, Debug, S,
+ Events, Event, State, Data, TransOpts,
+ [], false);
+ {keep_state_and_data,Actions} ->
+ loop_event_actions(
+ Parent, Debug, S,
+ Events, Event, State, Data, TransOpts,
+ Actions, false);
+ %%
+ {repeat_state,NewData} ->
+ loop_event_actions(
+ Parent, Debug, S,
+ Events, Event, State, NewData, TransOpts,
+ [], true);
+ {repeat_state,NewData,Actions} ->
+ loop_event_actions(
+ Parent, Debug, S,
+ Events, Event, State, NewData, TransOpts,
+ Actions, true);
+ %%
+ repeat_state_and_data ->
+ loop_event_actions(
+ Parent, Debug, S,
+ Events, Event, State, Data, TransOpts,
+ [], true);
+ {repeat_state_and_data,Actions} ->
+ loop_event_actions(
+ Parent, Debug, S,
+ Events, Event, State, Data, TransOpts,
+ Actions, true);
+ %%
+ stop ->
+ terminate(
+ exit, normal, ?STACKTRACE(), Debug,
+ S#state{
+ state = State, data = Data,
+ hibernate = hibernate_in_trans_opts(TransOpts)},
+ [Event|Events]);
+ {stop,Reason} ->
+ terminate(
+ exit, Reason, ?STACKTRACE(), Debug,
+ S#state{
+ state = State, data = Data,
+ hibernate = hibernate_in_trans_opts(TransOpts)},
+ [Event|Events]);
+ {stop,Reason,NewData} ->
+ terminate(
+ exit, Reason, ?STACKTRACE(), Debug,
+ S#state{
+ state = State, data = NewData,
+ hibernate = hibernate_in_trans_opts(TransOpts)},
+ [Event|Events]);
+ %%
+ {stop_and_reply,Reason,Replies} ->
+ reply_then_terminate(
+ exit, Reason, ?STACKTRACE(), Debug,
+ S#state{
+ state = State, data = Data,
+ hibernate = hibernate_in_trans_opts(TransOpts)},
+ [Event|Events], Replies);
+ {stop_and_reply,Reason,Replies,NewData} ->
+ reply_then_terminate(
+ exit, Reason, ?STACKTRACE(), Debug,
+ S#state{
+ state = State, data = NewData,
+ hibernate = hibernate_in_trans_opts(TransOpts)},
+ [Event|Events], Replies);
+ %%
+ _ ->
+ terminate(
+ error,
+ {bad_return_from_state_function,Result},
+ ?STACKTRACE(), Debug,
+ S#state{
+ state = State, data = Data,
+ hibernate = hibernate_in_trans_opts(TransOpts)},
+ [Event|Events])
end.
-loop_event_enter_actions(
- Parent, Debug, #{state_enter := StateEnter} = S,
- Events, Event, NextState, NewData,
- Hibernate, TimeoutsR, Postpone, NextEventsR,
- Actions, EnterCall) ->
- case
- parse_enter_actions(
- Debug, S, NextState, Actions, Hibernate, TimeoutsR)
- of
- {ok,NewDebug,NewHibernate,NewTimeoutsR,_,_} ->
- if
- StateEnter, EnterCall ->
- loop_event_enter(
- Parent, NewDebug, S,
- Events, Event, NextState, NewData,
- NewHibernate, NewTimeoutsR, Postpone, NextEventsR);
- true ->
- loop_event_result(
- Parent, NewDebug, S,
- Events, Event, NextState, NewData,
- NewHibernate, NewTimeoutsR, Postpone, NextEventsR)
- end;
- {Class,Reason,Stacktrace} ->
- terminate(
- Class, Reason, Stacktrace, Debug,
- S#{
- state := NextState,
- data := NewData,
- hibernate := Hibernate},
- [Event|Events])
+%% Ensure that Actions are a list
+loop_event_actions(
+ Parent, Debug, S,
+ Events, Event, NextState, NewerData, TransOpts,
+ Actions, CallEnter) ->
+ loop_event_actions_list(
+ Parent, Debug, S,
+ Events, Event, NextState, NewerData, TransOpts,
+ listify(Actions), CallEnter).
+
+%% Process actions from the state function
+loop_event_actions_list(
+ Parent, Debug, #state{state_enter = StateEnter} = S,
+ Events, Event, NextState, NewerData, TransOpts,
+ Actions, CallEnter) ->
+ %%
+ case parse_actions(TransOpts, Debug, S, Actions) of
+ {NewDebug,NewTransOpts}
+ when StateEnter, CallEnter ->
+ loop_event_state_enter(
+ Parent, NewDebug, S,
+ Events, Event, NextState, NewerData, NewTransOpts);
+ {NewDebug,NewTransOpts} ->
+ loop_event_done(
+ Parent, NewDebug, S,
+ Events, Event, NextState, NewerData, NewTransOpts);
+ [Class,Reason,Stacktrace,NewDebug] ->
+ terminate(
+ Class, Reason, Stacktrace, NewDebug,
+ S#state{
+ state = NextState,
+ data = NewerData,
+ hibernate = hibernate_in_trans_opts(TransOpts)},
+ [Event|Events])
end.
-loop_event_result(
+-compile({inline, [hibernate_in_trans_opts/1]}).
+hibernate_in_trans_opts(false) ->
+ (#trans_opts{})#trans_opts.hibernate;
+hibernate_in_trans_opts(#trans_opts{hibernate = Hibernate}) ->
+ Hibernate.
+
+parse_actions(false, Debug, S, Actions) ->
+ parse_actions(true, Debug, S, Actions, #trans_opts{});
+parse_actions(TransOpts, Debug, S, Actions) ->
+ parse_actions(false, Debug, S, Actions, TransOpts).
+%%
+parse_actions(_StateCall, Debug, _S, [], TransOpts) ->
+ {Debug,TransOpts};
+parse_actions(StateCall, Debug, S, [Action|Actions], TransOpts) ->
+ case Action of
+ %% Actual actions
+ {reply,From,Reply} ->
+ parse_actions_reply(
+ StateCall, Debug, S, Actions, TransOpts, From, Reply);
+ %%
+ %% Actions that set options
+ {hibernate,NewHibernate} when is_boolean(NewHibernate) ->
+ parse_actions(
+ StateCall, Debug, S, Actions,
+ TransOpts#trans_opts{hibernate = NewHibernate});
+ hibernate ->
+ parse_actions(
+ StateCall, Debug, S, Actions,
+ TransOpts#trans_opts{hibernate = true});
+ %%
+ {postpone,NewPostpone} when not NewPostpone orelse StateCall ->
+ parse_actions(
+ StateCall, Debug, S, Actions,
+ TransOpts#trans_opts{postpone = NewPostpone});
+ postpone when StateCall ->
+ parse_actions(
+ StateCall, Debug, S, Actions,
+ TransOpts#trans_opts{postpone = true});
+ postpone ->
+ [error,
+ {bad_state_enter_action_from_state_function,Action},
+ ?STACKTRACE(),
+ Debug];
+ %%
+ {next_event,Type,Content} ->
+ parse_actions_next_event(
+ StateCall, Debug, S, Actions, TransOpts, Type, Content);
+ %%
+ _ ->
+ parse_actions_timeout(
+ StateCall, Debug, S, Actions, TransOpts, Action)
+ end.
+
+parse_actions_reply(
+ StateCall, ?not_sys_debug, S, Actions, TransOpts,
+ From, Reply) ->
+ %%
+ case from(From) of
+ true ->
+ reply(From, Reply),
+ parse_actions(StateCall, ?not_sys_debug, S, Actions, TransOpts);
+ false ->
+ [error,
+ {bad_action_from_state_function,{reply,From,Reply}},
+ ?STACKTRACE(),
+ ?not_sys_debug]
+ end;
+parse_actions_reply(
+ StateCall, Debug, #state{name = Name, state = State} = S,
+ Actions, TransOpts, From, Reply) ->
+ %%
+ case from(From) of
+ true ->
+ reply(From, Reply),
+ NewDebug = sys_debug(Debug, {Name,State}, {out,Reply,From}),
+ parse_actions(StateCall, NewDebug, S, Actions, TransOpts);
+ false ->
+ [error,
+ {bad_action_from_state_function,{reply,From,Reply}},
+ ?STACKTRACE(),
+ Debug]
+ end.
+
+parse_actions_next_event(
+ StateCall, ?not_sys_debug, S,
+ Actions, TransOpts, Type, Content) ->
+ case event_type(Type) of
+ true when StateCall ->
+ NextEventsR = TransOpts#trans_opts.next_events_r,
+ parse_actions(
+ StateCall, ?not_sys_debug, S, Actions,
+ TransOpts#trans_opts{
+ next_events_r = [{Type,Content}|NextEventsR]});
+ _ ->
+ [error,
+ {bad_state_enter_action_from_state_function,
+ {next_event,Type,Content}},
+ ?STACKTRACE(),
+ ?not_sys_debug]
+ end;
+parse_actions_next_event(
+ StateCall, Debug, #state{name = Name, state = State} = S,
+ Actions, TransOpts, Type, Content) ->
+ case event_type(Type) of
+ true when StateCall ->
+ NewDebug = sys_debug(Debug, {Name,State}, {in,{Type,Content}}),
+ NextEventsR = TransOpts#trans_opts.next_events_r,
+ parse_actions(
+ StateCall, NewDebug, S, Actions,
+ TransOpts#trans_opts{
+ next_events_r = [{Type,Content}|NextEventsR]});
+ _ ->
+ [error,
+ {bad_state_enter_action_from_state_function,
+ {next_event,Type,Content}},
+ ?STACKTRACE(),
+ Debug]
+ end.
+
+parse_actions_timeout(
+ StateCall, Debug, S, Actions, TransOpts,
+ {TimeoutType,Time,TimerMsg,TimerOpts} = AbsoluteTimeout) ->
+ %%
+ case classify_timeout(TimeoutType, Time, listify(TimerOpts)) of
+ absolute ->
+ parse_actions_timeout_add(
+ StateCall, Debug, S, Actions,
+ TransOpts, AbsoluteTimeout);
+ relative ->
+ RelativeTimeout = {TimeoutType,Time,TimerMsg},
+ parse_actions_timeout_add(
+ StateCall, Debug, S, Actions,
+ TransOpts, RelativeTimeout);
+ badarg ->
+ [error,
+ {bad_action_from_state_function,AbsoluteTimeout},
+ ?STACKTRACE(),
+ Debug]
+ end;
+parse_actions_timeout(
+ StateCall, Debug, S, Actions, TransOpts,
+ {TimeoutType,Time,_} = RelativeTimeout) ->
+ case classify_timeout(TimeoutType, Time, []) of
+ relative ->
+ parse_actions_timeout_add(
+ StateCall, Debug, S, Actions,
+ TransOpts, RelativeTimeout);
+ badarg ->
+ [error,
+ {bad_action_from_state_function,RelativeTimeout},
+ ?STACKTRACE(),
+ Debug]
+ end;
+parse_actions_timeout(
+ StateCall, Debug, S, Actions, TransOpts,
+ Time) ->
+ case classify_timeout(timeout, Time, []) of
+ relative ->
+ RelativeTimeout = {timeout,Time,Time},
+ parse_actions_timeout_add(
+ StateCall, Debug, S, Actions,
+ TransOpts, RelativeTimeout);
+ badarg ->
+ [error,
+ {bad_action_from_state_function,Time},
+ ?STACKTRACE(),
+ Debug]
+ end.
+
+parse_actions_timeout_add(
+ StateCall, Debug, S, Actions,
+ #trans_opts{timeouts_r = TimeoutsR} = TransOpts, Timeout) ->
+ parse_actions(
+ StateCall, Debug, S, Actions,
+ TransOpts#trans_opts{timeouts_r = [Timeout|TimeoutsR]}).
+
+%% Do the state transition
+loop_event_done(
+ Parent, ?not_sys_debug,
+ #state{postponed = P} = S,
+ Events, Event, NextState, NewData,
+ #trans_opts{
+ postpone = Postpone, hibernate = Hibernate,
+ timeouts_r = [], next_events_r = []}) ->
+ %%
+ %% Optimize the simple cases
+ %% i.e no timer changes, no inserted events and no debug,
+ %% by duplicate stripped down code
+ %%
+ %% Fast path
+ %%
+ case Postpone of
+ true ->
+ loop_event_done_fast(
+ Parent, Hibernate,
+ S,
+ Events, [Event|P], NextState, NewData);
+ false ->
+ loop_event_done_fast(
+ Parent, Hibernate,
+ S,
+ Events, P, NextState, NewData)
+ end;
+loop_event_done(
Parent, Debug_0,
- #{state := State, postponed := P_0,
- timer_refs := TimerRefs_0, timer_types := TimerTypes_0,
- cancel_timers := CancelTimers_0} = S_0,
+ #state{
+ state = State, postponed = P_0,
+ timer_refs = TimerRefs_0, timer_types = TimerTypes_0,
+ cancel_timers = CancelTimers_0} = S,
Events_0, Event_0, NextState, NewData,
- Hibernate, TimeoutsR, Postpone, NextEventsR) ->
+ #trans_opts{
+ hibernate = Hibernate, timeouts_r = TimeoutsR,
+ postpone = Postpone, next_events_r = NextEventsR}) ->
%%
%% All options have been collected and next_events are buffered.
%% Do the actual state transition.
%%
- {Debug_1,P_1} = % Move current event to postponed if Postpone
+ %% Full feature path
+ %%
+ [Debug_1|P_1] = % Move current event to postponed if Postpone
case Postpone of
true ->
- {sys_debug(Debug_0, S_0, State, {postpone,Event_0,State}),
- [Event_0|P_0]};
+ [?sys_debug(
+ Debug_0,
+ {S#state.name,State},
+ {postpone,Event_0,NextState}),
+ Event_0|P_0];
false ->
- {sys_debug(Debug_0, S_0, State, {consume,Event_0,State}),
- P_0}
+ [?sys_debug(
+ Debug_0,
+ {S#state.name,State},
+ {consume,Event_0,NextState})|P_0]
end,
- {Events_1,P_2,{TimerTypes_1,CancelTimers_1}} =
- %% Move all postponed events to queue and cancel the
- %% state timeout if the state changes
+ {Events_2,P_2,Timers_2} =
+ %% Move all postponed events to queue,
+ %% cancel the event timer,
+ %% and cancel the state timeout if the state changes
if
NextState =:= State ->
- {Events_0,P_1,{TimerTypes_0,CancelTimers_0}};
+ {Events_0,P_1,
+ cancel_timer_by_type(
+ timeout, {TimerTypes_0,CancelTimers_0})};
true ->
{lists:reverse(P_1, Events_0),
[],
cancel_timer_by_type(
- state_timeout, TimerTypes_0, CancelTimers_0)}
- %% The state timer is removed from TimerTypes_1
- %% but remains in TimerRefs_0 until we get
+ state_timeout,
+ cancel_timer_by_type(
+ timeout, {TimerTypes_0,CancelTimers_0}))}
+ %% The state timer is removed from TimerTypes
+ %% but remains in TimerRefs until we get
%% the cancel_timer msg
end,
- {TimerRefs_2,TimerTypes_2,CancelTimers_2,TimeoutEvents} =
- %% Stop and start non-event timers
- parse_timers(TimerRefs_0, TimerTypes_1, CancelTimers_1, TimeoutsR),
+ {TimerRefs_3,{TimerTypes_3,CancelTimers_3},TimeoutEvents} =
+ %% Stop and start timers
+ parse_timers(TimerRefs_0, Timers_2, TimeoutsR),
%% Place next events last in reversed queue
- Events_2R = lists:reverse(Events_1, NextEventsR),
- %% Enqueue immediate timeout events and start event timer
- Events_3R = prepend_timeout_events(TimeoutEvents, Events_2R),
- S_1 =
- S_0#{
- state := NextState,
- data := NewData,
- postponed := P_2,
- timer_refs := TimerRefs_2,
- timer_types := TimerTypes_2,
- cancel_timers := CancelTimers_2,
- hibernate := Hibernate},
- case lists:reverse(Events_3R) of
- [] ->
- %% Get a new event
- loop(Parent, Debug_1, S_1);
- [Event|Events] ->
+ Events_3R = lists:reverse(Events_2, NextEventsR),
+ %% Enqueue immediate timeout events
+ Events_4R = prepend_timeout_events(TimeoutEvents, Events_3R),
+ loop_event_done(
+ Parent, Debug_1,
+ S#state{
+ state = NextState,
+ data = NewData,
+ postponed = P_2,
+ timer_refs = TimerRefs_3,
+ timer_types = TimerTypes_3,
+ cancel_timers = CancelTimers_3,
+ hibernate = Hibernate},
+ lists:reverse(Events_4R)).
+
+%% Fast path
+%%
+loop_event_done_fast(
+ Parent, Hibernate,
+ #state{
+ state = NextState,
+ timer_types = #{timeout := _} = TimerTypes,
+ cancel_timers = CancelTimers} = S,
+ Events, P, NextState, NewData) ->
+ %%
+ %% Same state, event timeout active
+ %%
+ loop_event_done_fast(
+ Parent, Hibernate, S,
+ Events, P, NextState, NewData,
+ cancel_timer_by_type(
+ timeout, {TimerTypes,CancelTimers}));
+loop_event_done_fast(
+ Parent, Hibernate,
+ #state{state = NextState} = S,
+ Events, P, NextState, NewData) ->
+ %%
+ %% Same state
+ %%
+ loop_event_done(
+ Parent, ?not_sys_debug,
+ S#state{
+ data = NewData,
+ postponed = P,
+ hibernate = Hibernate},
+ Events);
+loop_event_done_fast(
+ Parent, Hibernate,
+ #state{
+ timer_types = #{timeout := _} = TimerTypes,
+ cancel_timers = CancelTimers} = S,
+ Events, P, NextState, NewData) ->
+ %%
+ %% State change, event timeout active
+ %%
+ loop_event_done_fast(
+ Parent, Hibernate, S,
+ lists:reverse(P, Events), [], NextState, NewData,
+ cancel_timer_by_type(
+ state_timeout,
+ cancel_timer_by_type(
+ timeout, {TimerTypes,CancelTimers})));
+loop_event_done_fast(
+ Parent, Hibernate,
+ #state{
+ timer_types = #{state_timeout := _} = TimerTypes,
+ cancel_timers = CancelTimers} = S,
+ Events, P, NextState, NewData) ->
+ %%
+ %% State change, state timeout active
+ %%
+ loop_event_done_fast(
+ Parent, Hibernate, S,
+ lists:reverse(P, Events), [], NextState, NewData,
+ cancel_timer_by_type(
+ state_timeout,
+ cancel_timer_by_type(
+ timeout, {TimerTypes,CancelTimers})));
+loop_event_done_fast(
+ Parent, Hibernate,
+ #state{} = S,
+ Events, P, NextState, NewData) ->
+ %%
+ %% State change, no timeout to automatically cancel
+ %%
+ loop_event_done(
+ Parent, ?not_sys_debug,
+ S#state{
+ state = NextState,
+ data = NewData,
+ postponed = [],
+ hibernate = Hibernate},
+ lists:reverse(P, Events)).
+%%
+%% Fast path
+%%
+loop_event_done_fast(
+ Parent, Hibernate, S,
+ Events, P, NextState, NewData,
+ {TimerTypes,CancelTimers}) ->
+ %%
+ loop_event_done(
+ Parent, ?not_sys_debug,
+ S#state{
+ state = NextState,
+ data = NewData,
+ postponed = P,
+ timer_types = TimerTypes,
+ cancel_timers = CancelTimers,
+ hibernate = Hibernate},
+ Events).
+
+loop_event_done(Parent, Debug, S, Q) ->
+ case Q of
+ [] ->
+ %% Get a new event
+ loop(Parent, Debug, S);
+ [{Type,Content}|Events] ->
%% Loop until out of enqueued events
- loop_event(Parent, Debug_1, S_1, Events, Event, Hibernate)
+ loop_event(Parent, Debug, S, Events, Type, Content)
end.
%%---------------------------------------------------------------------------
%% Server loop helpers
-call_callback_mode(#{module := Module} = S) ->
+call_callback_mode(#state{module = Module} = S) ->
try Module:callback_mode() of
CallbackMode ->
callback_mode_result(S, CallbackMode)
catch
CallbackMode ->
callback_mode_result(S, CallbackMode);
- Class:Reason ->
- {Class,Reason,erlang:get_stacktrace()}
+ Class:Reason:Stacktrace ->
+ [Class,Reason,Stacktrace]
end.
callback_mode_result(S, CallbackMode) ->
- case
- parse_callback_mode(
- if
- is_atom(CallbackMode) ->
- [CallbackMode];
- true ->
- CallbackMode
- end, undefined, false)
- of
- {undefined,_} ->
- {error,
- {bad_return_from_callback_mode,CallbackMode},
- ?STACKTRACE()};
- {CBMode,StateEnter} ->
- {ok,
- S#{
- callback_mode := CBMode,
- state_enter := StateEnter}}
- end.
-
-parse_callback_mode([], CBMode, StateEnter) ->
- {CBMode,StateEnter};
-parse_callback_mode([H|T], CBMode, StateEnter) ->
+ callback_mode_result(
+ S, CallbackMode, listify(CallbackMode), undefined, false).
+%%
+callback_mode_result(_S, CallbackMode, [], undefined, _StateEnter) ->
+ [error,
+ {bad_return_from_callback_mode,CallbackMode},
+ ?STACKTRACE()];
+callback_mode_result(S, _CallbackMode, [], CBMode, StateEnter) ->
+ S#state{callback_mode = CBMode, state_enter = StateEnter};
+callback_mode_result(S, CallbackMode, [H|T], CBMode, StateEnter) ->
case callback_mode(H) of
true ->
- parse_callback_mode(T, H, StateEnter);
+ callback_mode_result(S, CallbackMode, T, H, StateEnter);
false ->
- case H of
- state_enter ->
- parse_callback_mode(T, CBMode, true);
- _ ->
- {undefined,StateEnter}
+ case state_enter(H) of
+ true ->
+ callback_mode_result(S, CallbackMode, T, CBMode, true);
+ false ->
+ [error,
+ {bad_return_from_callback_mode,CallbackMode},
+ ?STACKTRACE()]
end
- end;
-parse_callback_mode(_, _CBMode, StateEnter) ->
- {undefined,StateEnter}.
+ end.
call_state_function(
- #{callback_mode := undefined} = S, Type, Content, State, Data) ->
+ #state{callback_mode = undefined} = S, Type, Content, State, Data) ->
case call_callback_mode(S) of
- {ok,NewS} ->
+ #state{} = NewS ->
call_state_function(NewS, Type, Content, State, Data);
Error ->
Error
end;
call_state_function(
- #{callback_mode := CallbackMode, module := Module} = S,
+ #state{callback_mode = CallbackMode, module = Module} = S,
Type, Content, State, Data) ->
try
case CallbackMode of
@@ -1243,333 +1663,105 @@ call_state_function(
end
of
Result ->
- {ok,Result,S}
+ {Result,S}
catch
Result ->
- {ok,Result,S};
- Class:Reason ->
- {Class,Reason,erlang:get_stacktrace()}
- end.
-
-
-%% Interpret all callback return variants
-parse_event_result(
- AllowStateChange, Debug, S,
- Events, Event, State, Data, Result) ->
- case Result of
- stop ->
- terminate(
- exit, normal, ?STACKTRACE(), Debug,
- S#{state := State, data := Data},
- [Event|Events]);
- {stop,Reason} ->
- terminate(
- exit, Reason, ?STACKTRACE(), Debug,
- S#{state := State, data := Data},
- [Event|Events]);
- {stop,Reason,NewData} ->
- terminate(
- exit, Reason, ?STACKTRACE(), Debug,
- S#{state := State, data := NewData},
- [Event|Events]);
- %%
- {stop_and_reply,Reason,Replies} ->
- reply_then_terminate(
- exit, Reason, ?STACKTRACE(), Debug,
- S#{state := State, data := Data},
- [Event|Events], Replies);
- {stop_and_reply,Reason,Replies,NewData} ->
- reply_then_terminate(
- exit, Reason, ?STACKTRACE(), Debug,
- S#{state := State, data := NewData},
- [Event|Events], Replies);
- %%
- {next_state,State,NewData} ->
- {State,NewData,[],false};
- {next_state,NextState,NewData} when AllowStateChange ->
- {NextState,NewData,[],true};
- {next_state,State,NewData,Actions} ->
- {State,NewData,Actions,false};
- {next_state,NextState,NewData,Actions} when AllowStateChange ->
- {NextState,NewData,Actions,true};
- %%
- {keep_state,NewData} ->
- {State,NewData,[],false};
- {keep_state,NewData,Actions} ->
- {State,NewData,Actions,false};
- keep_state_and_data ->
- {State,Data,[],false};
- {keep_state_and_data,Actions} ->
- {State,Data,Actions,false};
- %%
- {repeat_state,NewData} ->
- {State,NewData,[],true};
- {repeat_state,NewData,Actions} ->
- {State,NewData,Actions,true};
- repeat_state_and_data ->
- {State,Data,[],true};
- {repeat_state_and_data,Actions} ->
- {State,Data,Actions,true};
- %%
- _ ->
- terminate(
- error,
- {bad_return_from_state_function,Result},
- ?STACKTRACE(), Debug,
- S#{state := State, data := Data},
- [Event|Events])
+ {Result,S};
+ Class:Reason:Stacktrace ->
+ [Class,Reason,Stacktrace]
end.
-parse_enter_actions(Debug, S, State, Actions, Hibernate, TimeoutsR) ->
- Postpone = forbidden,
- NextEventsR = forbidden,
- parse_actions(
- Debug, S, State, listify(Actions),
- Hibernate, TimeoutsR, Postpone, NextEventsR).
-
-parse_actions(Debug, S, State, Actions) ->
- Hibernate = false,
- TimeoutsR = [infinity], %% Will cancel event timer
- Postpone = false,
- NextEventsR = [],
- parse_actions(
- Debug, S, State, listify(Actions),
- Hibernate, TimeoutsR, Postpone, NextEventsR).
-%%
-parse_actions(
- Debug, _S, _State, [],
- Hibernate, TimeoutsR, Postpone, NextEventsR) ->
- {ok,Debug,Hibernate,TimeoutsR,Postpone,NextEventsR};
-parse_actions(
- Debug, S, State, [Action|Actions],
- Hibernate, TimeoutsR, Postpone, NextEventsR) ->
- case Action of
- %% Actual actions
- {reply,From,Reply} ->
- case from(From) of
- true ->
- NewDebug = do_reply(Debug, S, State, From, Reply),
- parse_actions(
- NewDebug, S, State, Actions,
- Hibernate, TimeoutsR, Postpone, NextEventsR);
- false ->
- {error,
- {bad_action_from_state_function,Action},
- ?STACKTRACE()}
- end;
- %%
- %% Actions that set options
- {hibernate,NewHibernate} when is_boolean(NewHibernate) ->
- parse_actions(
- Debug, S, State, Actions,
- NewHibernate, TimeoutsR, Postpone, NextEventsR);
- hibernate ->
- NewHibernate = true,
- parse_actions(
- Debug, S, State, Actions,
- NewHibernate, TimeoutsR, Postpone, NextEventsR);
- %%
- {postpone,NewPostpone}
- when is_boolean(NewPostpone), Postpone =/= forbidden ->
- parse_actions(
- Debug, S, State, Actions,
- Hibernate, TimeoutsR, NewPostpone, NextEventsR);
- postpone when Postpone =/= forbidden ->
- NewPostpone = true,
- parse_actions(
- Debug, S, State, Actions,
- Hibernate, TimeoutsR, NewPostpone, NextEventsR);
- %%
- {next_event,Type,Content} ->
- case event_type(Type) of
- true when NextEventsR =/= forbidden ->
- NewDebug =
- sys_debug(Debug, S, State, {in,{Type,Content}}),
- parse_actions(
- NewDebug, S, State, Actions,
- Hibernate, TimeoutsR, Postpone,
- [{Type,Content}|NextEventsR]);
- _ ->
- {error,
- {bad_action_from_state_function,Action},
- ?STACKTRACE()}
- end;
- %%
- {{timeout,_},_,_} = Timeout ->
- parse_actions_timeout(
- Debug, S, State, Actions,
- Hibernate, TimeoutsR, Postpone, NextEventsR, Timeout);
- {{timeout,_},_,_,_} = Timeout ->
- parse_actions_timeout(
- Debug, S, State, Actions,
- Hibernate, TimeoutsR, Postpone, NextEventsR, Timeout);
- {timeout,_,_} = Timeout ->
- parse_actions_timeout(
- Debug, S, State, Actions,
- Hibernate, TimeoutsR, Postpone, NextEventsR, Timeout);
- {timeout,_,_,_} = Timeout ->
- parse_actions_timeout(
- Debug, S, State, Actions,
- Hibernate, TimeoutsR, Postpone, NextEventsR, Timeout);
- {state_timeout,_,_} = Timeout ->
- parse_actions_timeout(
- Debug, S, State, Actions,
- Hibernate, TimeoutsR, Postpone, NextEventsR, Timeout);
- {state_timeout,_,_,_} = Timeout ->
- parse_actions_timeout(
- Debug, S, State, Actions,
- Hibernate, TimeoutsR, Postpone, NextEventsR, Timeout);
- Time ->
- parse_actions_timeout(
- Debug, S, State, Actions,
- Hibernate, TimeoutsR, Postpone, NextEventsR, Time)
- end.
-
-parse_actions_timeout(
- Debug, S, State, Actions,
- Hibernate, TimeoutsR, Postpone, NextEventsR, Timeout) ->
- case Timeout of
- {TimerType,Time,TimerMsg,TimerOpts} ->
- case validate_timer_args(Time, listify(TimerOpts)) of
- true ->
- parse_actions(
- Debug, S, State, Actions,
- Hibernate, [Timeout|TimeoutsR],
- Postpone, NextEventsR);
- false ->
- NewTimeout = {TimerType,Time,TimerMsg},
- parse_actions(
- Debug, S, State, Actions,
- Hibernate, [NewTimeout|TimeoutsR],
- Postpone, NextEventsR);
- error ->
- {error,
- {bad_action_from_state_function,Timeout},
- ?STACKTRACE()}
- end;
- {_,Time,_} ->
- case validate_timer_args(Time, []) of
- false ->
- parse_actions(
- Debug, S, State, Actions,
- Hibernate, [Timeout|TimeoutsR],
- Postpone, NextEventsR);
- error ->
- {error,
- {bad_action_from_state_function,Timeout},
- ?STACKTRACE()}
- end;
- Time ->
- case validate_timer_args(Time, []) of
- false ->
- parse_actions(
- Debug, S, State, Actions,
- Hibernate, [Timeout|TimeoutsR],
- Postpone, NextEventsR);
- error ->
- {error,
- {bad_action_from_state_function,Timeout},
- ?STACKTRACE()}
- end
+%% -> absolute | relative | badarg
+classify_timeout(TimeoutType, Time, Opts) ->
+ case timeout_event_type(TimeoutType) of
+ true ->
+ classify_time(false, Time, Opts);
+ false ->
+ badarg
end.
-validate_timer_args(Time, Opts) ->
- validate_timer_args(Time, Opts, false).
-%%
-validate_timer_args(Time, [], true) when is_integer(Time) ->
- true;
-validate_timer_args(Time, [], false) when is_integer(Time), Time >= 0 ->
- false;
-validate_timer_args(infinity, [], Abs) ->
- Abs;
-validate_timer_args(Time, [{abs,Abs}|Opts], _) when is_boolean(Abs) ->
- validate_timer_args(Time, Opts, Abs);
-validate_timer_args(_, [_|_], _) ->
- error.
+classify_time(Abs, Time, []) ->
+ case Abs of
+ true when
+ is_integer(Time);
+ Time =:= infinity ->
+ absolute;
+ false when
+ is_integer(Time), 0 =< Time;
+ Time =:= infinity ->
+ relative;
+ _ ->
+ badarg
+ end;
+classify_time(_, Time, [{abs,Abs}|Opts]) when is_boolean(Abs) ->
+ classify_time(Abs, Time, Opts);
+classify_time(_, _, Opts) when is_list(Opts) ->
+ badarg.
%% Stop and start timers as well as create timeout zero events
%% and pending event timer
%%
%% Stop and start timers non-event timers
-parse_timers(TimerRefs, TimerTypes, CancelTimers, TimeoutsR) ->
- parse_timers(TimerRefs, TimerTypes, CancelTimers, TimeoutsR, #{}, []).
+parse_timers(TimerRefs, Timers, TimeoutsR) ->
+ parse_timers(TimerRefs, Timers, TimeoutsR, #{}, []).
%%
parse_timers(
- TimerRefs, TimerTypes, CancelTimers, [], _Seen, TimeoutEvents) ->
- {TimerRefs,TimerTypes,CancelTimers,TimeoutEvents};
+ TimerRefs, Timers, [], _Seen, TimeoutEvents) ->
+ %%
+ {TimerRefs,Timers,TimeoutEvents};
parse_timers(
- TimerRefs, TimerTypes, CancelTimers, [Timeout|TimeoutsR],
- Seen, TimeoutEvents) ->
+ TimerRefs, Timers, [Timeout|TimeoutsR], Seen, TimeoutEvents) ->
+ %%
case Timeout of
{TimerType,Time,TimerMsg,TimerOpts} ->
%% Absolute timer
parse_timers(
- TimerRefs, TimerTypes, CancelTimers, TimeoutsR,
- Seen, TimeoutEvents,
+ TimerRefs, Timers, TimeoutsR, Seen, TimeoutEvents,
TimerType, Time, TimerMsg, listify(TimerOpts));
%% Relative timers below
{TimerType,0,TimerMsg} ->
parse_timers(
- TimerRefs, TimerTypes, CancelTimers, TimeoutsR,
- Seen, TimeoutEvents,
+ TimerRefs, Timers, TimeoutsR, Seen, TimeoutEvents,
TimerType, zero, TimerMsg, []);
{TimerType,Time,TimerMsg} ->
parse_timers(
- TimerRefs, TimerTypes, CancelTimers, TimeoutsR,
- Seen, TimeoutEvents,
- TimerType, Time, TimerMsg, []);
- 0 ->
- parse_timers(
- TimerRefs, TimerTypes, CancelTimers, TimeoutsR,
- Seen, TimeoutEvents,
- timeout, zero, 0, []);
- Time ->
- parse_timers(
- TimerRefs, TimerTypes, CancelTimers, TimeoutsR,
- Seen, TimeoutEvents,
- timeout, Time, Time, [])
+ TimerRefs, Timers, TimeoutsR, Seen, TimeoutEvents,
+ TimerType, Time, TimerMsg, [])
end.
parse_timers(
- TimerRefs, TimerTypes, CancelTimers, TimeoutsR,
- Seen, TimeoutEvents,
+ TimerRefs, Timers, TimeoutsR, Seen, TimeoutEvents,
TimerType, Time, TimerMsg, TimerOpts) ->
case Seen of
#{TimerType := _} ->
%% Type seen before - ignore
parse_timers(
- TimerRefs, TimerTypes, CancelTimers, TimeoutsR,
- Seen, TimeoutEvents);
+ TimerRefs, Timers, TimeoutsR, Seen, TimeoutEvents);
#{} ->
%% Unseen type - handle
NewSeen = Seen#{TimerType => true},
case Time of
infinity ->
%% Cancel any running timer
- {NewTimerTypes,NewCancelTimers} =
- cancel_timer_by_type(
- TimerType, TimerTypes, CancelTimers),
parse_timers(
- TimerRefs, NewTimerTypes, NewCancelTimers, TimeoutsR,
- NewSeen, TimeoutEvents);
+ TimerRefs, cancel_timer_by_type(TimerType, Timers),
+ TimeoutsR, NewSeen, TimeoutEvents);
zero ->
%% Cancel any running timer
- {NewTimerTypes,NewCancelTimers} =
- cancel_timer_by_type(
- TimerType, TimerTypes, CancelTimers),
%% Handle zero time timeouts later
- TimeoutEvent = {TimerType,TimerMsg},
parse_timers(
- TimerRefs, NewTimerTypes, NewCancelTimers, TimeoutsR,
- NewSeen, [TimeoutEvent|TimeoutEvents]);
+ TimerRefs, cancel_timer_by_type(TimerType, Timers),
+ TimeoutsR, NewSeen,
+ [{TimerType,TimerMsg}|TimeoutEvents]);
_ ->
%% (Re)start the timer
TimerRef =
erlang:start_timer(
Time, self(), TimerMsg, TimerOpts),
- case TimerTypes of
- #{TimerType := OldTimerRef} ->
+ case Timers of
+ {#{TimerType := OldTimerRef} = TimerTypes,
+ CancelTimers} ->
%% Cancel the running timer
cancel_timer(OldTimerRef),
NewCancelTimers = CancelTimers + 1,
@@ -1577,17 +1769,17 @@ parse_timers(
%% both TimerRefs and TimerTypes
parse_timers(
TimerRefs#{TimerRef => TimerType},
- TimerTypes#{TimerType => TimerRef},
- NewCancelTimers, TimeoutsR,
- NewSeen, TimeoutEvents);
- #{} ->
+ {TimerTypes#{TimerType => TimerRef},
+ NewCancelTimers},
+ TimeoutsR, NewSeen, TimeoutEvents);
+ {#{} = TimerTypes,CancelTimers} ->
%% Insert the new timer into
%% both TimerRefs and TimerTypes
parse_timers(
TimerRefs#{TimerRef => TimerType},
- TimerTypes#{TimerType => TimerRef},
- CancelTimers, TimeoutsR,
- NewSeen, TimeoutEvents)
+ {TimerTypes#{TimerType => TimerRef},
+ CancelTimers},
+ TimeoutsR, NewSeen, TimeoutEvents)
end
end
end.
@@ -1609,6 +1801,8 @@ prepend_timeout_events([], EventsR) ->
prepend_timeout_events([{timeout,_} = TimeoutEvent|TimeoutEvents], []) ->
prepend_timeout_events(TimeoutEvents, [TimeoutEvent]);
prepend_timeout_events([{timeout,_}|TimeoutEvents], EventsR) ->
+ %% Ignore since there are other events in queue
+ %% so they have cancelled the event timeout 0.
prepend_timeout_events(TimeoutEvents, EventsR);
prepend_timeout_events([TimeoutEvent|TimeoutEvents], EventsR) ->
%% Just prepend all others
@@ -1619,23 +1813,28 @@ prepend_timeout_events([TimeoutEvent|TimeoutEvents], EventsR) ->
%%---------------------------------------------------------------------------
%% Server helpers
-reply_then_terminate(
- Class, Reason, Stacktrace, Debug,
- #{state := State} = S, Q, Replies) ->
+reply_then_terminate(Class, Reason, Stacktrace, Debug, S, Q, Replies) ->
do_reply_then_terminate(
- Class, Reason, Stacktrace, Debug,
- S, Q, listify(Replies), State).
+ Class, Reason, Stacktrace, Debug, S, Q, listify(Replies)).
%%
do_reply_then_terminate(
- Class, Reason, Stacktrace, Debug, S, Q, [], _State) ->
+ Class, Reason, Stacktrace, Debug, S, Q, []) ->
terminate(Class, Reason, Stacktrace, Debug, S, Q);
do_reply_then_terminate(
- Class, Reason, Stacktrace, Debug, S, Q, [R|Rs], State) ->
+ Class, Reason, Stacktrace, Debug, S, Q, [R|Rs]) ->
case R of
{reply,{_To,_Tag}=From,Reply} ->
- NewDebug = do_reply(Debug, S, State, From, Reply),
+ reply(From, Reply),
+ NewDebug =
+ ?sys_debug(
+ Debug,
+ begin
+ #state{name = Name, state = State} = S,
+ {Name,State}
+ end,
+ {out,Reply,From}),
do_reply_then_terminate(
- Class, Reason, Stacktrace, NewDebug, S, Q, Rs, State);
+ Class, Reason, Stacktrace, NewDebug, S, Q, Rs);
_ ->
terminate(
error,
@@ -1644,14 +1843,9 @@ do_reply_then_terminate(
Debug, S, Q)
end.
-do_reply(Debug, S, State, From, Reply) ->
- reply(From, Reply),
- sys_debug(Debug, S, State, {out,Reply,From}).
-
-
terminate(
Class, Reason, Stacktrace, Debug,
- #{module := Module, state := State, data := Data, postponed := P} = S,
+ #state{module = Module, state = State, data = Data} = S,
Q) ->
case erlang:function_exported(Module, terminate, 3) of
true ->
@@ -1659,11 +1853,8 @@ terminate(
_ -> ok
catch
_ -> ok;
- C:R ->
- ST = erlang:get_stacktrace(),
- error_info(
- C, R, ST, S, Q, P,
- format_status(terminate, get(), S)),
+ C:R:ST ->
+ error_info(C, R, ST, S, Q),
sys:print_log(Debug),
erlang:raise(C, R, ST)
end;
@@ -1673,15 +1864,13 @@ terminate(
_ =
case Reason of
normal ->
- sys_debug(Debug, S, State, {terminate,Reason});
+ terminate_sys_debug(Debug, S, State, Reason);
shutdown ->
- sys_debug(Debug, S, State, {terminate,Reason});
+ terminate_sys_debug(Debug, S, State, Reason);
{shutdown,_} ->
- sys_debug(Debug, S, State, {terminate,Reason});
+ terminate_sys_debug(Debug, S, State, Reason);
_ ->
- error_info(
- Class, Reason, Stacktrace, S, Q, P,
- format_status(terminate, get(), S)),
+ error_info(Class, Reason, Stacktrace, S, Q),
sys:print_log(Debug)
end,
case Stacktrace of
@@ -1691,12 +1880,38 @@ terminate(
erlang:raise(Class, Reason, Stacktrace)
end.
+terminate_sys_debug(Debug, S, State, Reason) ->
+ ?sys_debug(Debug, {S#state.name,State}, {terminate,Reason}).
+
+
error_info(
Class, Reason, Stacktrace,
- #{name := Name,
- callback_mode := CallbackMode,
- state_enter := StateEnter},
- Q, P, FmtData) ->
+ #state{
+ name = Name,
+ callback_mode = CallbackMode,
+ state_enter = StateEnter,
+ postponed = P} = S,
+ Q) ->
+ ?LOG_ERROR(#{label=>{gen_statem,terminate},
+ name=>Name,
+ queue=>Q,
+ postponed=>P,
+ callback_mode=>CallbackMode,
+ state_enter=>StateEnter,
+ state=>format_status(terminate, get(), S),
+ reason=>{Class,Reason,Stacktrace}},
+ #{domain=>[otp],
+ report_cb=>fun gen_statem:format_log/1,
+ error_logger=>#{tag=>error}}).
+
+format_log(#{label:={gen_statem,terminate},
+ name:=Name,
+ queue:=Q,
+ postponed:=P,
+ callback_mode:=CallbackMode,
+ state_enter:=StateEnter,
+ state:=FmtData,
+ reason:={Class,Reason,Stacktrace}}) ->
{FixedReason,FixedStacktrace} =
case Stacktrace of
[{M,F,Args,_}|ST]
@@ -1731,53 +1946,51 @@ error_info(
false ->
CallbackMode
end,
- error_logger:format(
- "** State machine ~p terminating~n" ++
- case Q of
- [] -> "";
- _ -> "** Last event = ~p~n"
- end ++
- "** When server state = ~p~n" ++
- "** Reason for termination = ~w:~p~n" ++
- "** Callback mode = ~p~n" ++
- case Q of
- [_,_|_] -> "** Queued = ~p~n";
- _ -> ""
- end ++
- case P of
- [] -> "";
- _ -> "** Postponed = ~p~n"
- end ++
- case FixedStacktrace of
- [] -> "";
- _ -> "** Stacktrace =~n** ~p~n"
- end,
- [Name |
- case Q of
- [] -> [];
- [Event|_] -> [Event]
- end] ++
- [LimitedFmtData,
- Class,LimitedFixedReason,
- CBMode] ++
- case Q of
- [_|[_|_] = Events] -> [Events];
- _ -> []
- end ++
- case P of
- [] -> [];
- _ -> [LimitedP]
- end ++
- case FixedStacktrace of
- [] -> [];
- _ -> [FixedStacktrace]
- end).
-
+ {"** State machine ~tp terminating~n" ++
+ case Q of
+ [] -> "";
+ _ -> "** Last event = ~tp~n"
+ end ++
+ "** When server state = ~tp~n" ++
+ "** Reason for termination = ~w:~tp~n" ++
+ "** Callback mode = ~p~n" ++
+ case Q of
+ [_,_|_] -> "** Queued = ~tp~n";
+ _ -> ""
+ end ++
+ case P of
+ [] -> "";
+ _ -> "** Postponed = ~tp~n"
+ end ++
+ case FixedStacktrace of
+ [] -> "";
+ _ -> "** Stacktrace =~n** ~tp~n"
+ end,
+ [Name |
+ case Q of
+ [] -> [];
+ [Event|_] -> [Event]
+ end] ++
+ [LimitedFmtData,
+ Class,LimitedFixedReason,
+ CBMode] ++
+ case Q of
+ [_|[_|_] = Events] -> [Events];
+ _ -> []
+ end ++
+ case P of
+ [] -> [];
+ _ -> [LimitedP]
+ end ++
+ case FixedStacktrace of
+ [] -> [];
+ _ -> [FixedStacktrace]
+ end}.
%% Call Module:format_status/2 or return a default value
format_status(
Opt, PDict,
- #{module := Module, state := State, data := Data}) ->
+ #state{module = Module, state = State, data = Data}) ->
case erlang:function_exported(Module, format_status, 2) of
true ->
try Module:format_status(Opt, [PDict,State,Data])
@@ -1802,6 +2015,7 @@ format_status_default(Opt, State, Data) ->
[{data,[{"State",StateData}]}]
end.
+-compile({inline, [listify/1]}).
listify(Item) when is_list(Item) ->
Item;
listify(Item) ->
@@ -1815,14 +2029,16 @@ listify(Item) ->
%%
%% Remove the timer from TimerTypes.
%% When we get the cancel_timer msg we remove it from TimerRefs.
-cancel_timer_by_type(TimerType, TimerTypes, CancelTimers) ->
+-compile({inline, [cancel_timer_by_type/2]}).
+cancel_timer_by_type(TimerType, {TimerTypes,CancelTimers} = TT_CT) ->
case TimerTypes of
#{TimerType := TimerRef} ->
- cancel_timer(TimerRef),
+ ok = erlang:cancel_timer(TimerRef, [{async,true}]),
{maps:remove(TimerType, TimerTypes),CancelTimers + 1};
#{} ->
- {TimerTypes,CancelTimers}
+ TT_CT
end.
+-compile({inline, [cancel_timer/1]}).
cancel_timer(TimerRef) ->
ok = erlang:cancel_timer(TimerRef, [{async,true}]).
diff --git a/lib/stdlib/src/io.erl b/lib/stdlib/src/io.erl
index f510f61e9f..63c9a6bddf 100644
--- a/lib/stdlib/src/io.erl
+++ b/lib/stdlib/src/io.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -86,7 +86,16 @@ put_chars(Chars) ->
CharData :: unicode:chardata().
put_chars(Io, Chars) ->
- o_request(Io, {put_chars,unicode,Chars}, put_chars).
+ put_chars(Io, unicode, Chars).
+
+%% This function is here to make the erlang:raise in o_request actually raise to
+%% a valid function.
+-spec put_chars(IoDevice, Encoding, CharData) -> 'ok' when
+ IoDevice :: device(),
+ Encoding :: unicode,
+ CharData :: unicode:chardata().
+put_chars(Io, Encoding, Chars) ->
+ o_request(Io, {put_chars,Encoding,Chars}, put_chars).
-spec nl() -> 'ok'.
diff --git a/lib/stdlib/src/io_lib.erl b/lib/stdlib/src/io_lib.erl
index 9d447418f8..8223a52873 100644
--- a/lib/stdlib/src/io_lib.erl
+++ b/lib/stdlib/src/io_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -60,11 +60,12 @@
-module(io_lib).
--export([fwrite/2,fread/2,fread/3,format/2]).
--export([scan_format/2,unscan_format/1,build_text/1]).
+-export([fwrite/2,fwrite/3,fread/2,fread/3,format/2,format/3]).
+-export([scan_format/2,unscan_format/1,build_text/1,build_text/2]).
-export([print/1,print/4,indentation/2]).
-export([write/1,write/2,write/3,nl/0,format_prompt/1,format_prompt/2]).
+-export([write_binary/3]).
-export([write_atom/1,write_string/1,write_string/2,write_latin1_string/1,
write_latin1_string/2, write_char/1, write_latin1_char/1]).
@@ -87,7 +88,7 @@
-export([limit_term/2]).
-export_type([chars/0, latin1_string/0, continuation/0,
- fread_error/0, fread_item/0, format_spec/0]).
+ fread_error/0, fread_item/0, format_spec/0, chars_limit/0]).
%%----------------------------------------------------------------------
@@ -135,6 +136,18 @@
fwrite(Format, Args) ->
format(Format, Args).
+-type chars_limit() :: integer().
+
+-spec fwrite(Format, Data, Options) -> chars() when
+ Format :: io:format(),
+ Data :: [term()],
+ Options :: [Option],
+ Option :: {'chars_limit', CharsLimit},
+ CharsLimit :: chars_limit().
+
+fwrite(Format, Args, Options) ->
+ format(Format, Args, Options).
+
-spec fread(Format, String) -> Result when
Format :: string(),
String :: string(),
@@ -149,7 +162,7 @@ fread(Chars, Format) ->
-spec fread(Continuation, CharSpec, Format) -> Return when
Continuation :: continuation() | [],
- CharSpec :: string() | eof,
+ CharSpec :: string() | 'eof',
Format :: string(),
Return :: {'more', Continuation1 :: continuation()}
| {'done', Result, LeftOverChars :: string()},
@@ -165,11 +178,26 @@ fread(Cont, Chars, Format) ->
Data :: [term()].
format(Format, Args) ->
- case catch io_lib_format:fwrite(Format, Args) of
- {'EXIT',_} ->
- erlang:error(badarg, [Format, Args]);
- Other ->
- Other
+ try io_lib_format:fwrite(Format, Args)
+ catch
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [Format, Args])
+ end.
+
+-spec format(Format, Data, Options) -> chars() when
+ Format :: io:format(),
+ Data :: [term()],
+ Options :: [Option],
+ Option :: {'chars_limit', CharsLimit},
+ CharsLimit :: chars_limit().
+
+format(Format, Args, Options) ->
+ try io_lib_format:fwrite(Format, Args, Options)
+ catch
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [Format, Args])
end.
-spec scan_format(Format, Data) -> FormatList when
@@ -180,7 +208,9 @@ format(Format, Args) ->
scan_format(Format, Args) ->
try io_lib_format:scan(Format, Args)
catch
- _:_ -> erlang:error(badarg, [Format, Args])
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [Format, Args])
end.
-spec unscan_format(FormatList) -> {Format, Data} when
@@ -195,7 +225,37 @@ unscan_format(FormatList) ->
FormatList :: [char() | format_spec()].
build_text(FormatList) ->
- io_lib_format:build(FormatList).
+ try io_lib_format:build(FormatList)
+ catch
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [FormatList])
+ end.
+
+-spec build_text(FormatList, Options) -> chars() when
+ FormatList :: [char() | format_spec()],
+ Options :: [Option],
+ Option :: {'chars_limit', CharsLimit},
+ CharsLimit :: chars_limit().
+
+build_text(FormatList, Options) ->
+ try io_lib_format:build(FormatList, Options)
+ catch
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [FormatList, Options])
+ end.
+
+%% Failure to load a module must not be labeled as badarg.
+%% C, R, and S are included so that the original error, which could be
+%% a bug in io_lib_format, can be found by tracing on
+%% test_modules_loaded/3.
+test_modules_loaded(_C, _R, _S) ->
+ Modules = [io_lib_format, io_lib_pretty, string, unicode],
+ case code:ensure_modules_loaded(Modules) of
+ ok -> ok;
+ Error -> erlang:error(Error)
+ end.
-spec print(Term) -> chars() when
Term :: term().
@@ -240,7 +300,7 @@ format_prompt(Prompt, Encoding) ->
do_format_prompt(add_modifier(Encoding, "p"), [Prompt]).
do_format_prompt(Format, Args) ->
- case catch io_lib:format(Format, Args) of
+ case catch format(Format, Args) of
{'EXIT',_} -> "???";
List -> List
end.
@@ -259,7 +319,8 @@ add_modifier(_, C) ->
-spec write(Term) -> chars() when
Term :: term().
-write(Term) -> write(Term, -1).
+write(Term) ->
+ write1(Term, -1, latin1).
-spec write(term(), depth(), boolean()) -> chars().
@@ -274,16 +335,29 @@ write(Term, D, false) ->
(Term, Options) -> chars() when
Term :: term(),
Options :: [Option],
- Option :: {'depth', Depth}
+ Option :: {'chars_limit', CharsLimit}
+ | {'depth', Depth}
| {'encoding', 'latin1' | 'utf8' | 'unicode'},
+ CharsLimit :: chars_limit(),
Depth :: depth().
write(Term, Options) when is_list(Options) ->
Depth = get_option(depth, Options, -1),
Encoding = get_option(encoding, Options, epp:default_encoding()),
- write1(Term, Depth, Encoding);
+ CharsLimit = get_option(chars_limit, Options, -1),
+ if
+ Depth =:= 0; CharsLimit =:= 0 ->
+ "...";
+ CharsLimit < 0 ->
+ write1(Term, Depth, Encoding);
+ CharsLimit > 0 ->
+ RecDefFun = fun(_, _) -> no end,
+ If = io_lib_pretty:intermediate
+ (Term, Depth, CharsLimit, RecDefFun, Encoding, _Str=false),
+ io_lib_pretty:write(If)
+ end;
write(Term, Depth) ->
- write1(Term, Depth, latin1).
+ write(Term, [{depth, Depth}, {encoding, latin1}]).
write1(_Term, 0, _E) -> "...";
write1(Term, _D, _E) when is_integer(Term) -> integer_to_list(Term);
@@ -300,7 +374,7 @@ write1([H|T], D, E) ->
if
D =:= 1 -> "[...]";
true ->
- [$[,[write1(H, D-1, E)|write_tail(T, D-1, E, $|)],$]]
+ [$[,[write1(H, D-1, E)|write_tail(T, D-1, E)],$]]
end;
write1(F, _D, _E) when is_function(F) ->
erlang:fun_to_list(F);
@@ -311,20 +385,24 @@ write1(T, D, E) when is_tuple(T) ->
D =:= 1 -> "{...}";
true ->
[${,
- [write1(element(1, T), D-1, E)|
- write_tail(tl(tuple_to_list(T)), D-1, E, $,)],
+ [write1(element(1, T), D-1, E)|write_tuple(T, 2, D-1, E)],
$}]
end.
-%% write_tail(List, Depth, CharacterBeforeDots)
+%% write_tail(List, Depth, Encoding)
%% Test the terminating case first as this looks better with depth.
-write_tail([], _D, _E, _S) -> "";
-write_tail(_, 1, _E, S) -> [S | "..."];
-write_tail([H|T], D, E, S) ->
- [$,,write1(H, D-1, E)|write_tail(T, D-1, E, S)];
-write_tail(Other, D, E, S) ->
- [S,write1(Other, D-1, E)].
+write_tail([], _D, _E) -> "";
+write_tail(_, 1, _E) -> [$| | "..."];
+write_tail([H|T], D, E) ->
+ [$,,write1(H, D-1, E)|write_tail(T, D-1, E)];
+write_tail(Other, D, E) ->
+ [$|,write1(Other, D-1, E)].
+
+write_tuple(T, I, _D, _E) when I > tuple_size(T) -> "";
+write_tuple(_, _I, 1, _E) -> [$, | "..."];
+write_tuple(T, I, D, E) ->
+ [$,,write1(element(I, T), D-1, E)|write_tuple(T, I+1, D-1, E)].
write_port(Port) ->
erlang:port_to_list(Port).
@@ -333,32 +411,43 @@ write_ref(Ref) ->
erlang:ref_to_list(Ref).
write_map(Map, D, E) when is_integer(D) ->
- [$#,${,write_map_body(maps:to_list(Map), D, E),$}].
+ [$#,${,write_map_body(maps:to_list(Map), D, D - 1, E),$}].
-write_map_body(_, 0, _E) -> "...";
-write_map_body([], _, _E) -> [];
-write_map_body([{K,V}], D, E) -> write_map_assoc(K, V, D, E);
-write_map_body([{K,V}|KVs], D, E) ->
- [write_map_assoc(K, V, D, E),$, | write_map_body(KVs, D-1, E)].
+write_map_body(_, 1, _D0, _E) -> "...";
+write_map_body([], _, _D0, _E) -> [];
+write_map_body([{K,V}], _D, D0, E) -> write_map_assoc(K, V, D0, E);
+write_map_body([{K,V}|KVs], D, D0, E) ->
+ [write_map_assoc(K, V, D0, E),$, | write_map_body(KVs, D - 1, D0, E)].
write_map_assoc(K, V, D, E) ->
- [write1(K, D - 1, E),"=>",write1(V, D-1, E)].
+ [write1(K, D, E)," => ",write1(V, D, E)].
write_binary(B, D) when is_integer(D) ->
- [$<,$<,write_binary_body(B, D),$>,$>].
-
-write_binary_body(<<>>, _D) ->
- "";
-write_binary_body(_B, 1) ->
- "...";
-write_binary_body(<<X:8>>, _D) ->
- [integer_to_list(X)];
-write_binary_body(<<X:8,Rest/bitstring>>, D) ->
- [integer_to_list(X),$,|write_binary_body(Rest, D-1)];
-write_binary_body(B, _D) ->
+ {S, _} = write_binary(B, D, -1),
+ S.
+
+write_binary(B, D, T) ->
+ {S, Rest} = write_binary_body(B, D, tsub(T, 4), []),
+ {[$<,$<,lists:reverse(S),$>,$>], Rest}.
+
+write_binary_body(<<>> = B, _D, _T, Acc) ->
+ {Acc, B};
+write_binary_body(B, D, T, Acc) when D =:= 1; T =:= 0->
+ {["..."|Acc], B};
+write_binary_body(<<X:8>>, _D, _T, Acc) ->
+ {[integer_to_list(X)|Acc], <<>>};
+write_binary_body(<<X:8,Rest/bitstring>>, D, T, Acc) ->
+ S = integer_to_list(X),
+ write_binary_body(Rest, D-1, tsub(T, length(S) + 1), [$,,S|Acc]);
+write_binary_body(B, _D, _T, Acc) ->
L = bit_size(B),
<<X:L>> = B,
- [integer_to_list(X),$:,integer_to_list(L)].
+ {[integer_to_list(L),$:,integer_to_list(X)|Acc], <<>>}.
+
+%% Make sure T does not change sign.
+tsub(T, _) when T < 0 -> T;
+tsub(T, E) when T >= E -> T - E;
+tsub(_, _) -> 0.
get_option(Key, TupleList, Default) ->
case lists:keyfind(Key, 1, TupleList) of
@@ -931,7 +1020,7 @@ limit_term(Term, Depth) ->
limit(_, 0) -> '...';
limit([H|T]=L, D) ->
if
- D =:= 1 -> '...';
+ D =:= 1 -> ['...'];
true ->
case printable_list(L) of
true -> L;
@@ -944,10 +1033,10 @@ limit(Term, D) when is_map(Term) ->
limit({}=T, _D) -> T;
limit(T, D) when is_tuple(T) ->
if
- D =:= 1 -> '...';
+ D =:= 1 -> {'...'};
true ->
list_to_tuple([limit(element(1, T), D-1)|
- limit_tail(tl(tuple_to_list(T)), D-1)])
+ limit_tuple(T, 2, D-1)])
end;
limit(<<_/bitstring>>=Term, D) -> limit_bitstring(Term, D);
limit(Term, _D) -> Term.
@@ -959,23 +1048,36 @@ limit_tail([H|T], D) ->
limit_tail(Other, D) ->
limit(Other, D-1).
+limit_tuple(T, I, _D) when I > tuple_size(T) -> [];
+limit_tuple(_, _I, 1) -> ['...'];
+limit_tuple(T, I, D) ->
+ [limit(element(I, T), D-1)|limit_tuple(T, I+1, D-1)].
+
%% Cannot limit maps properly since there is no guarantee that
%% maps:from_list() creates a map with the same internal ordering of
-%% the selected associations as in Map.
+%% the selected associations as in Map. Instead of subtracting one
+%% from the depth as the map associations are traversed (as is done
+%% for tuples and lists), the same depth is applied to each and every
+%% (returned) association.
limit_map(Map, D) ->
- maps:from_list(erts_internal:maps_to_list(Map, D)).
-%% maps:from_list(limit_map_body(erts_internal:maps_to_list(Map, D), D)).
-
-%% limit_map_body(_, 0) -> [{'...', '...'}];
-%% limit_map_body([], _) -> [];
-%% limit_map_body([{K,V}], D) -> [limit_map_assoc(K, V, D)];
-%% limit_map_body([{K,V}|KVs], D) ->
-%% [limit_map_assoc(K, V, D) | limit_map_body(KVs, D-1)].
+ %% Keep one extra association to make sure the final ',...' is included.
+ limit_map_body(maps:iterator(Map), D + 1, D, []).
+
+limit_map_body(_I, 0, _D0, Acc) ->
+ maps:from_list(Acc);
+limit_map_body(I, D, D0, Acc) ->
+ case maps:next(I) of
+ {K, V, NextI} ->
+ limit_map_body(NextI, D-1, D0, [limit_map_assoc(K, V, D0) | Acc]);
+ none ->
+ maps:from_list(Acc)
+ end.
-%% limit_map_assoc(K, V, D) ->
-%% {limit(K, D-1), limit(V, D-1)}.
+limit_map_assoc(K, V, D) ->
+ %% Keep keys as are to avoid creating duplicated keys.
+ {K, limit(V, D - 1)}.
-limit_bitstring(B, _D) -> B. %% Keeps all printable binaries.
+limit_bitstring(B, _D) -> B. % Keeps all printable binaries.
test_limit(_, 0) -> throw(limit);
test_limit([H|T]=L, D) when is_integer(D) ->
@@ -1011,18 +1113,21 @@ test_limit_tuple(T, I, Sz, D) ->
test_limit(element(I, T), D-1),
test_limit_tuple(T, I+1, Sz, D-1).
-test_limit_map(_Map, _D) -> ok.
-%% test_limit_map_body(erts_internal:maps_to_list(Map, D), D).
-
-%% test_limit_map_body(_, 0) -> throw(limit);
-%% test_limit_map_body([], _) -> ok;
-%% test_limit_map_body([{K,V}], D) -> test_limit_map_assoc(K, V, D);
-%% test_limit_map_body([{K,V}|KVs], D) ->
-%% test_limit_map_assoc(K, V, D),
-%% test_limit_map_body(KVs, D-1).
+test_limit_map(Map, D) ->
+ test_limit_map_body(maps:iterator(Map), D).
+
+test_limit_map_body(_I, 0) -> throw(limit); % cannot happen
+test_limit_map_body(I, D) ->
+ case maps:next(I) of
+ {K, V, NextI} ->
+ test_limit_map_assoc(K, V, D),
+ test_limit_map_body(NextI, D-1);
+ none ->
+ ok
+ end.
-%% test_limit_map_assoc(K, V, D) ->
-%% test_limit(K, D-1),
-%% test_limit(V, D-1).
+test_limit_map_assoc(K, V, D) ->
+ test_limit(K, D - 1),
+ test_limit(V, D - 1).
test_limit_bitstring(_, _) -> ok.
diff --git a/lib/stdlib/src/io_lib_format.erl b/lib/stdlib/src/io_lib_format.erl
index 4b2d15c8b3..ab9031573b 100644
--- a/lib/stdlib/src/io_lib_format.erl
+++ b/lib/stdlib/src/io_lib_format.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,8 @@
%% Formatting functions of io library.
--export([fwrite/2,fwrite_g/1,indentation/2,scan/2,unscan/1,build/1]).
+-export([fwrite/2,fwrite/3,fwrite_g/1,indentation/2,scan/2,unscan/1,
+ build/1, build/2]).
%% Format the arguments in Args after string Format. Just generate
%% an error if there is an error in the arguments.
@@ -37,22 +38,48 @@
%% and it also splits the handling of the control characters into two
%% parts.
--spec fwrite(Format, Data) -> FormatList when
+-spec fwrite(Format, Data) -> io_lib:chars() when
Format :: io:format(),
- Data :: [term()],
- FormatList :: [char() | io_lib:format_spec()].
+ Data :: [term()].
fwrite(Format, Args) ->
build(scan(Format, Args)).
+-spec fwrite(Format, Data, Options) -> io_lib:chars() when
+ Format :: io:format(),
+ Data :: [term()],
+ Options :: [Option],
+ Option :: {'chars_limit', CharsLimit},
+ CharsLimit :: io_lib:chars_limit().
+
+fwrite(Format, Args, Options) ->
+ build(scan(Format, Args), Options).
+
%% Build the output text for a pre-parsed format list.
-spec build(FormatList) -> io_lib:chars() when
FormatList :: [char() | io_lib:format_spec()].
build(Cs) ->
- Pc = pcount(Cs),
- build(Cs, Pc, 0).
+ build(Cs, []).
+
+-spec build(FormatList, Options) -> io_lib:chars() when
+ FormatList :: [char() | io_lib:format_spec()],
+ Options :: [Option],
+ Option :: {'chars_limit', CharsLimit},
+ CharsLimit :: io_lib:chars_limit().
+
+build(Cs, Options) ->
+ CharsLimit = get_option(chars_limit, Options, -1),
+ Res1 = build_small(Cs),
+ {P, S, W, Other} = count_small(Res1),
+ case P + S + W of
+ 0 ->
+ Res1;
+ NumOfLimited ->
+ RemainingChars = sub(CharsLimit, Other),
+ build_limited(Res1, P, NumOfLimited, RemainingChars, 0)
+ end.
%% Parse all control sequences in the format string.
@@ -95,7 +122,7 @@ print([]) ->
[].
print(C, F, Ad, P, Pad, Encoding, Strings) ->
- [$~] ++ print_field_width(F, Ad) ++ print_precision(P) ++
+ [$~] ++ print_field_width(F, Ad) ++ print_precision(P, Pad) ++
print_pad_char(Pad) ++ print_encoding(Encoding) ++
print_strings(Strings) ++ [C].
@@ -103,8 +130,9 @@ print_field_width(none, _Ad) -> "";
print_field_width(F, left) -> integer_to_list(-F);
print_field_width(F, right) -> integer_to_list(F).
-print_precision(none) -> "";
-print_precision(P) -> [$. | integer_to_list(P)].
+print_precision(none, $\s) -> "";
+print_precision(none, _Pad) -> "."; % pad must be second dot
+print_precision(P, _Pad) -> [$. | integer_to_list(P)].
print_pad_char($\s) -> ""; % default, no need to make explicit
print_pad_char(Pad) -> [$., Pad].
@@ -126,25 +154,23 @@ collect_cseq(Fmt0, Args0) ->
{F,Ad,Fmt1,Args1} = field_width(Fmt0, Args0),
{P,Fmt2,Args2} = precision(Fmt1, Args1),
{Pad,Fmt3,Args3} = pad_char(Fmt2, Args2),
- {Encoding,Fmt4,Args4} = encoding(Fmt3, Args3),
- {Strings,Fmt5,Args5} = strings(Fmt4, Args4),
- {C,As,Fmt6,Args6} = collect_cc(Fmt5, Args5),
- FormatSpec = #{control_char => C, args => As, width => F, adjust => Ad,
- precision => P, pad_char => Pad, encoding => Encoding,
- strings => Strings},
- {FormatSpec,Fmt6,Args6}.
-
-encoding([$t|Fmt],Args) ->
- true = hd(Fmt) =/= $l,
- {unicode,Fmt,Args};
-encoding(Fmt,Args) ->
- {latin1,Fmt,Args}.
-
-strings([$l|Fmt],Args) ->
- true = hd(Fmt) =/= $t,
- {false,Fmt,Args};
-strings(Fmt,Args) ->
- {true,Fmt,Args}.
+ Spec0 = #{width => F,
+ adjust => Ad,
+ precision => P,
+ pad_char => Pad,
+ encoding => latin1,
+ strings => true},
+ {Spec1,Fmt4} = modifiers(Fmt3, Spec0),
+ {C,As,Fmt5,Args4} = collect_cc(Fmt4, Args3),
+ Spec2 = Spec1#{control_char => C, args => As},
+ {Spec2,Fmt5,Args4}.
+
+modifiers([$t|Fmt], Spec) ->
+ modifiers(Fmt, Spec#{encoding => unicode});
+modifiers([$l|Fmt], Spec) ->
+ modifiers(Fmt, Spec#{strings => false});
+modifiers(Fmt, Spec) ->
+ {Spec, Fmt}.
field_width([$-|Fmt0], Args0) ->
{F,Fmt,Args} = field_value(Fmt0, Args0),
@@ -203,40 +229,78 @@ collect_cc([$~|Fmt], Args) when is_list(Args) -> {$~,[],Fmt,Args};
collect_cc([$n|Fmt], Args) when is_list(Args) -> {$n,[],Fmt,Args};
collect_cc([$i|Fmt], [A|Args]) -> {$i,[A],Fmt,Args}.
-%% pcount([ControlC]) -> Count.
-%% Count the number of print requests.
-
-pcount(Cs) -> pcount(Cs, 0).
-
-pcount([#{control_char := $p}|Cs], Acc) -> pcount(Cs, Acc+1);
-pcount([#{control_char := $P}|Cs], Acc) -> pcount(Cs, Acc+1);
-pcount([_|Cs], Acc) -> pcount(Cs, Acc);
-pcount([], Acc) -> Acc.
-
-%% build([Control], Pc, Indentation) -> io_lib:chars().
+%% count_small([ControlC]) -> Count.
+%% Count the number of big (pPwWsS) print requests and
+%% number of characters of other print (small) requests.
+
+count_small(Cs) ->
+ count_small(Cs, #{p => 0, s => 0, w => 0, other => 0}).
+
+count_small([#{control_char := $p}|Cs], #{p := P} = Cnts) ->
+ count_small(Cs, Cnts#{p := P + 1});
+count_small([#{control_char := $P}|Cs], #{p := P} = Cnts) ->
+ count_small(Cs, Cnts#{p := P + 1});
+count_small([#{control_char := $w}|Cs], #{w := W} = Cnts) ->
+ count_small(Cs, Cnts#{w := W + 1});
+count_small([#{control_char := $W}|Cs], #{w := W} = Cnts) ->
+ count_small(Cs, Cnts#{w := W + 1});
+count_small([#{control_char := $s}|Cs], #{w := W} = Cnts) ->
+ count_small(Cs, Cnts#{w := W + 1});
+count_small([S|Cs], #{other := Other} = Cnts) when is_list(S);
+ is_binary(S) ->
+ count_small(Cs, Cnts#{other := Other + string:length(S)});
+count_small([C|Cs], #{other := Other} = Cnts) when is_integer(C) ->
+ count_small(Cs, Cnts#{other := Other + 1});
+count_small([], #{p := P, s := S, w := W, other := Other}) ->
+ {P, S, W, Other}.
+
+%% build_small([Control]) -> io_lib:chars().
+%% Interpret the control structures, but only the small ones.
+%% The big ones are saved for later.
+%% build_limited([Control], NumberOfPps, NumberOfLimited,
+%% CharsLimit, Indentation)
%% Interpret the control structures. Count the number of print
%% remaining and only calculate indentation when necessary. Must also
%% be smart when calculating indentation for characters in format.
-build([#{control_char := C, args := As, width := F, adjust := Ad,
- precision := P, pad_char := Pad, encoding := Enc,
- strings := Str} | Cs], Pc0, I) ->
- S = control(C, As, F, Ad, P, Pad, Enc, Str, I),
- Pc1 = decr_pc(C, Pc0),
+build_small([#{control_char := C, args := As, width := F, adjust := Ad,
+ precision := P, pad_char := Pad, encoding := Enc}=CC | Cs]) ->
+ case control_small(C, As, F, Ad, P, Pad, Enc) of
+ not_small -> [CC | build_small(Cs)];
+ S -> lists:flatten(S) ++ build_small(Cs)
+ end;
+build_small([C|Cs]) -> [C|build_small(Cs)];
+build_small([]) -> [].
+
+build_limited([#{control_char := C, args := As, width := F, adjust := Ad,
+ precision := P, pad_char := Pad, encoding := Enc,
+ strings := Str} | Cs], NumOfPs0, Count0, MaxLen0, I) ->
+ MaxChars = if
+ MaxLen0 < 0 -> MaxLen0;
+ true -> MaxLen0 div Count0
+ end,
+ S = control_limited(C, As, F, Ad, P, Pad, Enc, Str, MaxChars, I),
+ Len = string:length(S),
+ NumOfPs = decr_pc(C, NumOfPs0),
+ Count = Count0 - 1,
+ MaxLen = sub(MaxLen0, Len),
if
- Pc1 > 0 -> [S|build(Cs, Pc1, indentation(S, I))];
- true -> [S|build(Cs, Pc1, I)]
+ NumOfPs > 0 -> [S|build_limited(Cs, NumOfPs, Count,
+ MaxLen, indentation(S, I))];
+ true -> [S|build_limited(Cs, NumOfPs, Count, MaxLen, I)]
end;
-build([$\n|Cs], Pc, _I) -> [$\n|build(Cs, Pc, 0)];
-build([$\t|Cs], Pc, I) -> [$\t|build(Cs, Pc, ((I + 8) div 8) * 8)];
-build([C|Cs], Pc, I) -> [C|build(Cs, Pc, I+1)];
-build([], _Pc, _I) -> [].
+build_limited([$\n|Cs], NumOfPs, Count, MaxLen, _I) ->
+ [$\n|build_limited(Cs, NumOfPs, Count, MaxLen, 0)];
+build_limited([$\t|Cs], NumOfPs, Count, MaxLen, I) ->
+ [$\t|build_limited(Cs, NumOfPs, Count, MaxLen, ((I + 8) div 8) * 8)];
+build_limited([C|Cs], NumOfPs, Count, MaxLen, I) ->
+ [C|build_limited(Cs, NumOfPs, Count, MaxLen, I+1)];
+build_limited([], _, _, _, _) -> [].
decr_pc($p, Pc) -> Pc - 1;
decr_pc($P, Pc) -> Pc - 1;
decr_pc(_, Pc) -> Pc.
-
%% Calculate the indentation of the end of a string given its start
%% indentation. We assume tabs at 8 cols.
@@ -252,67 +316,74 @@ indentation([C|Cs], I) ->
indentation(Cs, indentation(C, I));
indentation([], I) -> I.
-%% control(FormatChar, [Argument], FieldWidth, Adjust, Precision, PadChar,
-%% Encoding, Indentation) -> String
-%% This is the main dispatch function for the various formatting commands.
-%% Field widths and precisions have already been calculated.
-
-control($w, [A], F, Adj, P, Pad, Enc, _Str, _I) ->
- term(io_lib:write(A, [{depth,-1}, {encoding, Enc}]), F, Adj, P, Pad);
-control($p, [A], F, Adj, P, Pad, Enc, Str, I) ->
- print(A, -1, F, Adj, P, Pad, Enc, Str, I);
-control($W, [A,Depth], F, Adj, P, Pad, Enc, _Str, _I) when is_integer(Depth) ->
- term(io_lib:write(A, [{depth,Depth}, {encoding, Enc}]), F, Adj, P, Pad);
-control($P, [A,Depth], F, Adj, P, Pad, Enc, Str, I) when is_integer(Depth) ->
- print(A, Depth, F, Adj, P, Pad, Enc, Str, I);
-control($s, [A], F, Adj, P, Pad, latin1, _Str, _I) when is_atom(A) ->
+%% control_small(FormatChar, [Argument], FieldWidth, Adjust, Precision,
+%% PadChar, Encoding) -> String
+%% control_limited(FormatChar, [Argument], FieldWidth, Adjust, Precision,
+%% PadChar, Encoding, StringP, ChrsLim, Indentation) -> String
+%% These are the dispatch functions for the various formatting controls.
+
+control_small($s, [A], F, Adj, P, Pad, latin1) when is_atom(A) ->
L = iolist_to_chars(atom_to_list(A)),
string(L, F, Adj, P, Pad);
-control($s, [A], F, Adj, P, Pad, unicode, _Str, _I) when is_atom(A) ->
+control_small($s, [A], F, Adj, P, Pad, unicode) when is_atom(A) ->
string(atom_to_list(A), F, Adj, P, Pad);
-control($s, [L0], F, Adj, P, Pad, latin1, _Str, _I) ->
- L = iolist_to_chars(L0),
- string(L, F, Adj, P, Pad);
-control($s, [L0], F, Adj, P, Pad, unicode, _Str, _I) ->
- L = cdata_to_chars(L0),
- uniconv(string(L, F, Adj, P, Pad));
-control($e, [A], F, Adj, P, Pad, _Enc, _Str, _I) when is_float(A) ->
+control_small($e, [A], F, Adj, P, Pad, _Enc) when is_float(A) ->
fwrite_e(A, F, Adj, P, Pad);
-control($f, [A], F, Adj, P, Pad, _Enc, _Str, _I) when is_float(A) ->
+control_small($f, [A], F, Adj, P, Pad, _Enc) when is_float(A) ->
fwrite_f(A, F, Adj, P, Pad);
-control($g, [A], F, Adj, P, Pad, _Enc, _Str, _I) when is_float(A) ->
+control_small($g, [A], F, Adj, P, Pad, _Enc) when is_float(A) ->
fwrite_g(A, F, Adj, P, Pad);
-control($b, [A], F, Adj, P, Pad, _Enc, _Str, _I) when is_integer(A) ->
+control_small($b, [A], F, Adj, P, Pad, _Enc) when is_integer(A) ->
unprefixed_integer(A, F, Adj, base(P), Pad, true);
-control($B, [A], F, Adj, P, Pad, _Enc, _Str, _I) when is_integer(A) ->
+control_small($B, [A], F, Adj, P, Pad, _Enc) when is_integer(A) ->
unprefixed_integer(A, F, Adj, base(P), Pad, false);
-control($x, [A,Prefix], F, Adj, P, Pad, _Enc, _Str, _I) when is_integer(A),
- is_atom(Prefix) ->
+control_small($x, [A,Prefix], F, Adj, P, Pad, _Enc) when is_integer(A),
+ is_atom(Prefix) ->
prefixed_integer(A, F, Adj, base(P), Pad, atom_to_list(Prefix), true);
-control($x, [A,Prefix], F, Adj, P, Pad, _Enc, _Str, _I) when is_integer(A) ->
+control_small($x, [A,Prefix], F, Adj, P, Pad, _Enc) when is_integer(A) ->
true = io_lib:deep_char_list(Prefix), %Check if Prefix a character list
prefixed_integer(A, F, Adj, base(P), Pad, Prefix, true);
-control($X, [A,Prefix], F, Adj, P, Pad, _Enc, _Str, _I) when is_integer(A),
- is_atom(Prefix) ->
+control_small($X, [A,Prefix], F, Adj, P, Pad, _Enc) when is_integer(A),
+ is_atom(Prefix) ->
prefixed_integer(A, F, Adj, base(P), Pad, atom_to_list(Prefix), false);
-control($X, [A,Prefix], F, Adj, P, Pad, _Enc, _Str, _I) when is_integer(A) ->
+control_small($X, [A,Prefix], F, Adj, P, Pad, _Enc) when is_integer(A) ->
true = io_lib:deep_char_list(Prefix), %Check if Prefix a character list
prefixed_integer(A, F, Adj, base(P), Pad, Prefix, false);
-control($+, [A], F, Adj, P, Pad, _Enc, _Str, _I) when is_integer(A) ->
+control_small($+, [A], F, Adj, P, Pad, _Enc) when is_integer(A) ->
Base = base(P),
Prefix = [integer_to_list(Base), $#],
prefixed_integer(A, F, Adj, Base, Pad, Prefix, true);
-control($#, [A], F, Adj, P, Pad, _Enc, _Str, _I) when is_integer(A) ->
+control_small($#, [A], F, Adj, P, Pad, _Enc) when is_integer(A) ->
Base = base(P),
Prefix = [integer_to_list(Base), $#],
prefixed_integer(A, F, Adj, Base, Pad, Prefix, false);
-control($c, [A], F, Adj, P, Pad, unicode, _Str, _I) when is_integer(A) ->
+control_small($c, [A], F, Adj, P, Pad, unicode) when is_integer(A) ->
char(A, F, Adj, P, Pad);
-control($c, [A], F, Adj, P, Pad, _Enc, _Str, _I) when is_integer(A) ->
+control_small($c, [A], F, Adj, P, Pad, _Enc) when is_integer(A) ->
char(A band 255, F, Adj, P, Pad);
-control($~, [], F, Adj, P, Pad, _Enc, _Str, _I) -> char($~, F, Adj, P, Pad);
-control($n, [], F, Adj, P, Pad, _Enc, _Str, _I) -> newline(F, Adj, P, Pad);
-control($i, [_A], _F, _Adj, _P, _Pad, _Enc, _Str, _I) -> [].
+control_small($~, [], F, Adj, P, Pad, _Enc) -> char($~, F, Adj, P, Pad);
+control_small($n, [], F, Adj, P, Pad, _Enc) -> newline(F, Adj, P, Pad);
+control_small($i, [_A], _F, _Adj, _P, _Pad, _Enc) -> [];
+control_small(_C, _As, _F, _Adj, _P, _Pad, _Enc) -> not_small.
+
+control_limited($s, [L0], F, Adj, P, Pad, latin1, _Str, CL, _I) ->
+ L = iolist_to_chars(L0),
+ string(limit_string(L, F, CL), limit_field(F, CL), Adj, P, Pad);
+control_limited($s, [L0], F, Adj, P, Pad, unicode, _Str, CL, _I) ->
+ L = cdata_to_chars(L0),
+ uniconv(string(limit_string(L, F, CL), limit_field(F, CL), Adj, P, Pad));
+control_limited($w, [A], F, Adj, P, Pad, Enc, _Str, CL, _I) ->
+ Chars = io_lib:write(A, [{depth, -1}, {encoding, Enc}, {chars_limit, CL}]),
+ term(Chars, F, Adj, P, Pad);
+control_limited($p, [A], F, Adj, P, Pad, Enc, Str, CL, I) ->
+ print(A, -1, F, Adj, P, Pad, Enc, Str, CL, I);
+control_limited($W, [A,Depth], F, Adj, P, Pad, Enc, _Str, CL, _I)
+ when is_integer(Depth) ->
+ Chars = io_lib:write(A, [{depth, Depth}, {encoding, Enc}, {chars_limit, CL}]),
+ term(Chars, F, Adj, P, Pad);
+control_limited($P, [A,Depth], F, Adj, P, Pad, Enc, Str, CL, I)
+ when is_integer(Depth) ->
+ print(A, Depth, F, Adj, P, Pad, Enc, Str, CL, I).
-ifdef(UNICODE_AS_BINARIES).
uniconv(C) ->
@@ -349,12 +420,13 @@ term(T, F, Adj, P0, Pad) ->
%% Print a term. Field width sets maximum line length, Precision sets
%% initial indentation.
-print(T, D, none, Adj, P, Pad, E, Str, I) ->
- print(T, D, 80, Adj, P, Pad, E, Str, I);
-print(T, D, F, Adj, none, Pad, E, Str, I) ->
- print(T, D, F, Adj, I+1, Pad, E, Str, I);
-print(T, D, F, right, P, _Pad, Enc, Str, _I) ->
- Options = [{column, P},
+print(T, D, none, Adj, P, Pad, E, Str, ChLim, I) ->
+ print(T, D, 80, Adj, P, Pad, E, Str, ChLim, I);
+print(T, D, F, Adj, none, Pad, E, Str, ChLim, I) ->
+ print(T, D, F, Adj, I+1, Pad, E, Str, ChLim, I);
+print(T, D, F, right, P, _Pad, Enc, Str, ChLim, _I) ->
+ Options = [{chars_limit, ChLim},
+ {column, P},
{line_length, F},
{depth, D},
{encoding, Enc},
@@ -380,7 +452,7 @@ float_e(_Fl, {Ds,E}, P) ->
{Fs,false} -> [Fs|float_exp(E-1)]
end.
-%% float_man([Digit], Icount, Dcount) -> {[Chars],CarryFlag}.
+%% float_man([Digit], Icount, Dcount) -> {[Char],CarryFlag}.
%% Generate the characters in the mantissa from the digits with Icount
%% characters before the '.' and Dcount decimals. Handle carry and let
%% caller decide what to do at top.
@@ -395,7 +467,7 @@ float_man([D|Ds], I, Dc) ->
{Cs,false} -> {[D|Cs],false}
end;
float_man([], I, Dc) -> %Pad with 0's
- {string:chars($0, I, [$.|string:chars($0, Dc)]),false}.
+ {lists:duplicate(I, $0) ++ [$.|lists:duplicate(Dc, $0)],false}.
float_man([D|_], 0) when D >= $5 -> {[],true};
float_man([_|_], 0) -> {[],false};
@@ -405,7 +477,7 @@ float_man([D|Ds], Dc) ->
{Cs,true} -> {[D+1|Cs],false};
{Cs,false} -> {[D|Cs],false}
end;
-float_man([], Dc) -> {string:chars($0, Dc),false}. %Pad with 0's
+float_man([], Dc) -> {lists:duplicate(Dc, $0),false}. %Pad with 0's
%% float_exp(Exponent) -> [Char].
%% Generate the exponent of a floating point number. Always include sign.
@@ -429,7 +501,7 @@ fwrite_f(Fl, F, Adj, P, Pad) when P >= 1 ->
float_f(Fl, Fd, P) when Fl < 0.0 ->
[$-|float_f(-Fl, Fd, P)];
float_f(Fl, {Ds,E}, P) when E =< 0 ->
- float_f(Fl, {string:chars($0, -E+1, Ds),1}, P); %Prepend enough 0's
+ float_f(Fl, {lists:duplicate(-E+1, $0)++Ds,1}, P); %Prepend enough 0's
float_f(_Fl, {Ds,E}, P) ->
case float_man(Ds, E, P) of
{Fs,true} -> "1" ++ Fs; %Handle carry
@@ -671,6 +743,18 @@ cdata_to_chars(B) when is_binary(B) ->
_ -> binary_to_list(B)
end.
+limit_string(S, F, CharsLimit) when CharsLimit < 0; CharsLimit >= F -> S;
+limit_string(S, _F, CharsLimit) ->
+ case string:length(S) =< CharsLimit of
+ true -> S;
+ false -> [string:slice(S, 0, sub(CharsLimit, 3)), "..."]
+ end.
+
+limit_field(F, CharsLimit) when CharsLimit < 0; F =:= none ->
+ F;
+limit_field(F, CharsLimit) ->
+ max(3, min(F, CharsLimit)).
+
%% string(String, Field, Adjust, Precision, PadChar)
string(S, none, _Adj, none, _Pad) -> S;
@@ -751,7 +835,7 @@ adjust(Data, Pad, right) -> [Pad|Data].
flat_trunc(List, N) when is_integer(N), N >= 0 ->
string:slice(List, 0, N).
-%% A deep version of string:chars/2,3
+%% A deep version of lists:duplicate/2
chars(_C, 0) ->
[];
@@ -784,3 +868,15 @@ lowercase([H|T]) ->
[H|lowercase(T)];
lowercase([]) ->
[].
+
+%% Make sure T does change sign.
+sub(T, _) when T < 0 -> T;
+sub(T, E) when T >= E -> T - E;
+sub(_, _) -> 0.
+
+get_option(Key, TupleList, Default) ->
+ case lists:keyfind(Key, 1, TupleList) of
+ false -> Default;
+ {Key, Value} -> Value;
+ _ -> Default
+ end.
diff --git a/lib/stdlib/src/io_lib_fread.erl b/lib/stdlib/src/io_lib_fread.erl
index 983e8d4566..319bff484e 100644
--- a/lib/stdlib/src/io_lib_fread.erl
+++ b/lib/stdlib/src/io_lib_fread.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@
-spec fread(Continuation, String, Format) -> Return when
Continuation :: io_lib:continuation() | [],
- String :: string(),
+ String :: string() | 'eof',
Format :: string(),
Return :: {'more', Continuation1 :: io_lib:continuation()}
| {'done', Result, LeftOverChars :: string()},
diff --git a/lib/stdlib/src/io_lib_pretty.erl b/lib/stdlib/src/io_lib_pretty.erl
index 505613b80e..ba9d9e8434 100644
--- a/lib/stdlib/src/io_lib_pretty.erl
+++ b/lib/stdlib/src/io_lib_pretty.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,6 +26,9 @@
-export([print/1,print/2,print/3,print/4,print/5,print/6]).
+%% To be used by io_lib only.
+-export([intermediate/6, write/1]).
+
%%%
%%% Exported functions
%%%
@@ -45,20 +48,23 @@ print(Term) ->
%% Used by the shell for printing records and for Unicode.
-type rec_print_fun() :: fun((Tag :: atom(), NFields :: non_neg_integer()) ->
- no | [FieldName :: atom()]).
+ 'no' | [FieldName :: atom()]).
-type column() :: integer().
+-type encoding() :: epp:source_encoding() | 'unicode'.
-type line_length() :: pos_integer().
-type depth() :: integer().
--type max_chars() :: integer().
+-type line_max_chars() :: integer().
+-type chars_limit() :: integer().
-type chars() :: io_lib:chars().
--type option() :: {column, column()}
- | {line_length, line_length()}
- | {depth, depth()}
- | {max_chars, max_chars()}
- | {record_print_fun, rec_print_fun()}
- | {strings, boolean()}
- | {encoding, latin1 | utf8 | unicode}.
+-type option() :: {'chars_limit', chars_limit()}
+ | {'column', column()}
+ | {'depth', depth()}
+ | {'encoding', encoding()}
+ | {'line_length', line_length()}
+ | {'line_max_chars', line_max_chars()}
+ | {'record_print_fun', rec_print_fun()}
+ | {'strings', boolean()}.
-type options() :: [option()].
-spec print(term(), rec_print_fun()) -> chars();
@@ -68,11 +74,12 @@ print(Term, Options) when is_list(Options) ->
Col = get_option(column, Options, 1),
Ll = get_option(line_length, Options, 80),
D = get_option(depth, Options, -1),
- M = get_option(max_chars, Options, -1),
+ M = get_option(line_max_chars, Options, -1),
+ T = get_option(chars_limit, Options, -1),
RecDefFun = get_option(record_print_fun, Options, no_fun),
Encoding = get_option(encoding, Options, epp:default_encoding()),
Strings = get_option(strings, Options, true),
- print(Term, Col, Ll, D, M, RecDefFun, Encoding, Strings);
+ print(Term, Col, Ll, D, M, T, RecDefFun, Encoding, Strings);
print(Term, RecDefFun) ->
print(Term, -1, RecDefFun).
@@ -84,38 +91,48 @@ print(Term, Depth, RecDefFun) ->
-spec print(term(), column(), line_length(), depth()) -> chars().
print(Term, Col, Ll, D) ->
- print(Term, Col, Ll, D, _M=-1, no_fun, latin1, true).
+ print(Term, Col, Ll, D, _M=-1, _T=-1, no_fun, latin1, true).
-spec print(term(), column(), line_length(), depth(), rec_print_fun()) ->
chars().
print(Term, Col, Ll, D, RecDefFun) ->
print(Term, Col, Ll, D, _M=-1, RecDefFun).
--spec print(term(), column(), line_length(), depth(), max_chars(),
+-spec print(term(), column(), line_length(), depth(), line_max_chars(),
rec_print_fun()) -> chars().
print(Term, Col, Ll, D, M, RecDefFun) ->
- print(Term, Col, Ll, D, M, RecDefFun, latin1, true).
+ print(Term, Col, Ll, D, M, _T=-1, RecDefFun, latin1, true).
%% D = Depth, default -1 (infinite), or LINEMAX=30 when printing from shell
+%% T = chars_limit, that is, maximal number of characters, default -1
+%% Used together with D to limit the output. It is possible that
+%% more than T characters are returned.
%% Col = current column, default 1
%% Ll = line length/~p field width, default 80
%% M = CHAR_MAX (-1 if no max, 60 when printing from shell)
-print(_, _, _, 0, _M, _RF, _Enc, _Str) -> "...";
-print(Term, Col, Ll, D, M, RecDefFun, Enc, Str) when Col =< 0 ->
+print(_, _, _, 0, _M, _T, _RF, _Enc, _Str) -> "...";
+print(_, _, _, _D, _M, 0, _RF, _Enc, _Str) -> "...";
+print(Term, Col, Ll, D, M, T, RecDefFun, Enc, Str) when Col =< 0 ->
%% ensure Col is at least 1
- print(Term, 1, Ll, D, M, RecDefFun, Enc, Str);
-print(Atom, _Col, _Ll, _D, _M, _RF, Enc, _Str) when is_atom(Atom) ->
+ print(Term, 1, Ll, D, M, T, RecDefFun, Enc, Str);
+print(Atom, _Col, _Ll, _D, _M, _T, _RF, Enc, _Str) when is_atom(Atom) ->
write_atom(Atom, Enc);
-print(Term, Col, Ll, D, M0, RecDefFun, Enc, Str) when is_tuple(Term);
- is_list(Term);
- is_map(Term);
- is_bitstring(Term) ->
+print(Term, Col, Ll, D, M0, T, RecDefFun, Enc, Str) when is_tuple(Term);
+ is_list(Term);
+ is_map(Term);
+ is_bitstring(Term) ->
%% preprocess and compute total number of chars
- If = {_S, Len} = print_length(Term, D, RecDefFun, Enc, Str),
+ {_, Len, _Dots, _} = If =
+ case T < 0 of
+ true -> print_length(Term, D, T, RecDefFun, Enc, Str);
+ false -> intermediate(Term, D, T, RecDefFun, Enc, Str)
+ end,
%% use Len as CHAR_MAX if M0 = -1
M = max_cs(M0, Len),
if
+ Ll =:= 0 ->
+ write(If);
Len < Ll - Col, Len =< M ->
%% write the whole thing on a single line when there is room
write(If);
@@ -126,7 +143,7 @@ print(Term, Col, Ll, D, M0, RecDefFun, Enc, Str) when is_tuple(Term);
1),
pp(If, Col, Ll, M, TInd, indent(Col), 0, 0)
end;
-print(Term, _Col, _Ll, _D, _M, _RF, _Enc, _Str) ->
+print(Term, _Col, _Ll, _D, _M, _T, _RF, _Enc, _Str) ->
%% atomic data types (bignums, atoms, ...) are never truncated
io_lib:write(Term).
@@ -147,28 +164,28 @@ max_cs(M, _Len) ->
?ATM(element(3, element(1, Pair)))). % Value
-define(ATM_FLD(Field), ?ATM(element(4, element(1, Field)))).
-pp({_S, Len} = If, Col, Ll, M, _TInd, _Ind, LD, W)
+pp({_S,Len,_,_} = If, Col, Ll, M, _TInd, _Ind, LD, W)
when Len < Ll - Col - LD, Len + W + LD =< M ->
write(If);
-pp({{list,L}, _Len}, Col, Ll, M, TInd, Ind, LD, W) ->
+pp({{list,L}, _Len, _, _}, Col, Ll, M, TInd, Ind, LD, W) ->
[$[, pp_list(L, Col + 1, Ll, M, TInd, indent(1, Ind), LD, $|, W + 1), $]];
-pp({{tuple,true,L}, _Len}, Col, Ll, M, TInd, Ind, LD, W) ->
+pp({{tuple,true,L}, _Len, _, _}, Col, Ll, M, TInd, Ind, LD, W) ->
[${, pp_tag_tuple(L, Col, Ll, M, TInd, Ind, LD, W + 1), $}];
-pp({{tuple,false,L}, _Len}, Col, Ll, M, TInd, Ind, LD, W) ->
+pp({{tuple,false,L}, _Len, _, _}, Col, Ll, M, TInd, Ind, LD, W) ->
[${, pp_list(L, Col + 1, Ll, M, TInd, indent(1, Ind), LD, $,, W + 1), $}];
-pp({{map,Pairs},_Len}, Col, Ll, M, TInd, Ind, LD, W) ->
+pp({{map,Pairs}, _Len, _, _}, Col, Ll, M, TInd, Ind, LD, W) ->
[$#, ${, pp_map(Pairs, Col + 2, Ll, M, TInd, indent(2, Ind), LD, W + 1),
$}];
-pp({{record,[{Name,NLen} | L]}, _Len}, Col, Ll, M, TInd, Ind, LD, W) ->
+pp({{record,[{Name,NLen} | L]}, _Len, _, _}, Col, Ll, M, TInd, Ind, LD, W) ->
[Name, ${, pp_record(L, NLen, Col, Ll, M, TInd, Ind, LD, W + NLen+1), $}];
-pp({{bin,S}, _Len}, Col, Ll, M, _TInd, Ind, LD, W) ->
+pp({{bin,S}, _Len, _, _}, Col, Ll, M, _TInd, Ind, LD, W) ->
pp_binary(S, Col + 2, Ll, M, indent(2, Ind), LD, W);
-pp({S, _Len}, _Col, _Ll, _M, _TInd, _Ind, _LD, _W) ->
+pp({S,_Len,_,_}, _Col, _Ll, _M, _TInd, _Ind, _LD, _W) ->
S.
%% Print a tagged tuple by indenting the rest of the elements
%% differently to the tag. Tuple has size >= 2.
-pp_tag_tuple([{Tag,Tlen} | L], Col, Ll, M, TInd, Ind, LD, W) ->
+pp_tag_tuple([{Tag,Tlen,_,_} | L], Col, Ll, M, TInd, Ind, LD, W) ->
%% this uses TInd
TagInd = Tlen + 2,
Tcol = Col + TagInd,
@@ -184,18 +201,18 @@ pp_tag_tuple([{Tag,Tlen} | L], Col, Ll, M, TInd, Ind, LD, W) ->
end.
pp_map([], _Col, _Ll, _M, _TInd, _Ind, _LD, _W) ->
- "";
-pp_map({dots, _}, _Col, _Ll, _M, _TInd, _Ind, _LD, _W) ->
- "...";
+ ""; % cannot happen
+pp_map({dots, _, _, _}, _Col, _Ll, _M, _TInd, _Ind, _LD, _W) ->
+ "..."; % cannot happen
pp_map([P | Ps], Col, Ll, M, TInd, Ind, LD, W) ->
{PS, PW} = pp_pair(P, Col, Ll, M, TInd, Ind, last_depth(Ps, LD), W),
[PS | pp_pairs_tail(Ps, Col, Col + PW, Ll, M, TInd, Ind, LD, PW)].
pp_pairs_tail([], _Col0, _Col, _Ll, _M, _TInd, _Ind, _LD, _W) ->
"";
-pp_pairs_tail({dots, _}, _Col0, _Col, _M, _Ll, _TInd, _Ind, _LD, _W) ->
+pp_pairs_tail({dots, _, _, _}, _Col0, _Col, _M, _Ll, _TInd, _Ind, _LD, _W) ->
",...";
-pp_pairs_tail([{_, Len}=P | Ps], Col0, Col, Ll, M, TInd, Ind, LD, W) ->
+pp_pairs_tail([{_, Len, _, _}=P | Ps], Col0, Col, Ll, M, TInd, Ind, LD, W) ->
LD1 = last_depth(Ps, LD),
ELen = 1 + Len,
if
@@ -209,7 +226,7 @@ pp_pairs_tail([{_, Len}=P | Ps], Col0, Col, Ll, M, TInd, Ind, LD, W) ->
pp_pairs_tail(Ps, Col0, Col0 + PW, Ll, M, TInd, Ind, LD, PW)]
end.
-pp_pair({_, Len}=Pair, Col, Ll, M, _TInd, _Ind, LD, W)
+pp_pair({_, Len, _, _}=Pair, Col, Ll, M, _TInd, _Ind, LD, W)
when Len < Ll - Col - LD, Len + W + LD =< M ->
{write_pair(Pair), if
?ATM_PAIR(Pair) ->
@@ -217,7 +234,7 @@ pp_pair({_, Len}=Pair, Col, Ll, M, _TInd, _Ind, LD, W)
true ->
Ll % force nl
end};
-pp_pair({{map_pair, K, V}, _Len}, Col0, Ll, M, TInd, Ind0, LD, W) ->
+pp_pair({{map_pair, K, V}, _Len, _, _}, Col0, Ll, M, TInd, Ind0, LD, W) ->
I = map_value_indent(TInd),
Ind = indent(I, Ind0),
{[pp(K, Col0, Ll, M, TInd, Ind0, LD, W), " =>\n",
@@ -225,7 +242,7 @@ pp_pair({{map_pair, K, V}, _Len}, Col0, Ll, M, TInd, Ind0, LD, W) ->
pp_record([], _Nlen, _Col, _Ll, _M, _TInd, _Ind, _LD, _W) ->
"";
-pp_record({dots, _}, _Nlen, _Col, _Ll, _M, _TInd, _Ind, _LD, _W) ->
+pp_record({dots, _, _, _}, _Nlen, _Col, _Ll, _M, _TInd, _Ind, _LD, _W) ->
"...";
pp_record([F | Fs], Nlen, Col0, Ll, M, TInd, Ind0, LD, W0) ->
Nind = Nlen + 1,
@@ -235,9 +252,9 @@ pp_record([F | Fs], Nlen, Col0, Ll, M, TInd, Ind0, LD, W0) ->
pp_fields_tail([], _Col0, _Col, _Ll, _M, _TInd, _Ind, _LD, _W) ->
"";
-pp_fields_tail({dots, _}, _Col0, _Col, _M, _Ll, _TInd, _Ind, _LD, _W) ->
+pp_fields_tail({dots, _, _ ,_}, _Col0, _Col, _M, _Ll, _TInd, _Ind, _LD, _W) ->
",...";
-pp_fields_tail([{_, Len}=F | Fs], Col0, Col, Ll, M, TInd, Ind, LD, W) ->
+pp_fields_tail([{_, Len, _, _}=F | Fs], Col0, Col, Ll, M, TInd, Ind, LD, W) ->
LD1 = last_depth(Fs, LD),
ELen = 1 + Len,
if
@@ -251,7 +268,7 @@ pp_fields_tail([{_, Len}=F | Fs], Col0, Col, Ll, M, TInd, Ind, LD, W) ->
pp_fields_tail(Fs, Col0, Col0 + FW, Ll, M, TInd, Ind, LD, FW)]
end.
-pp_field({_, Len}=Fl, Col, Ll, M, _TInd, _Ind, LD, W)
+pp_field({_, Len, _, _}=Fl, Col, Ll, M, _TInd, _Ind, LD, W)
when Len < Ll - Col - LD, Len + W + LD =< M ->
{write_field(Fl), if
?ATM_FLD(Fl) ->
@@ -259,7 +276,7 @@ pp_field({_, Len}=Fl, Col, Ll, M, _TInd, _Ind, LD, W)
true ->
Ll % force nl
end};
-pp_field({{field, Name, NameL, F}, _Len}, Col0, Ll, M, TInd, Ind0, LD, W0) ->
+pp_field({{field, Name, NameL, F},_,_, _}, Col0, Ll, M, TInd, Ind0, LD, W0) ->
{Col, Ind, S, W} = rec_indent(NameL, TInd, Col0, Ind0, W0 + NameL),
Sep = case S of
[$\n | _] -> " =";
@@ -286,15 +303,15 @@ rec_indent(RInd, TInd, Col0, Ind0, W0) ->
end,
{Col, Ind, S, W}.
-pp_list({dots, _}, _Col0, _Ll, _M, _TInd, _Ind, _LD, _S, _W) ->
+pp_list({dots, _, _, _}, _Col0, _Ll, _M, _TInd, _Ind, _LD, _S, _W) ->
"...";
pp_list([E | Es], Col0, Ll, M, TInd, Ind, LD, S, W) ->
{ES, WE} = pp_element(E, Col0, Ll, M, TInd, Ind, last_depth(Es, LD), W),
[ES | pp_tail(Es, Col0, Col0 + WE, Ll, M, TInd, Ind, LD, S, W + WE)].
pp_tail([], _Col0, _Col, _Ll, _M, _TInd, _Ind, _LD, _S, _W) ->
- "";
-pp_tail([{_, Len}=E | Es], Col0, Col, Ll, M, TInd, Ind, LD, S, W) ->
+ [];
+pp_tail([{_, Len, _, _}=E | Es], Col0, Col, Ll, M, TInd, Ind, LD, S, W) ->
LD1 = last_depth(Es, LD),
ELen = 1 + Len,
if
@@ -307,9 +324,9 @@ pp_tail([{_, Len}=E | Es], Col0, Col, Ll, M, TInd, Ind, LD, S, W) ->
[$,, $\n, Ind, ES |
pp_tail(Es, Col0, Col0 + WE, Ll, M, TInd, Ind, LD, S, WE)]
end;
-pp_tail({dots, _}, _Col0, _Col, _Ll, _M, _TInd, _Ind, _LD, S, _W) ->
+pp_tail({dots, _, _, _}, _Col0, _Col, _Ll, _M, _TInd, _Ind, _LD, S, _W) ->
[S | "..."];
-pp_tail({_, Len}=E, _Col0, Col, Ll, M, _TInd, _Ind, LD, S, W)
+pp_tail({_, Len, _, _}=E, _Col0, Col, Ll, M, _TInd, _Ind, LD, S, W)
when Len + 1 < Ll - Col - (LD + 1),
Len + 1 + W + (LD + 1) =< M,
?ATM(E) ->
@@ -317,7 +334,7 @@ pp_tail({_, Len}=E, _Col0, Col, Ll, M, _TInd, _Ind, LD, S, W)
pp_tail(E, Col0, _Col, Ll, M, TInd, Ind, LD, S, _W) ->
[S, $\n, Ind | pp(E, Col0, Ll, M, TInd, Ind, LD + 1, 0)].
-pp_element({_, Len}=E, Col, Ll, M, _TInd, _Ind, LD, W)
+pp_element({_, Len, _, _}=E, Col, Ll, M, _TInd, _Ind, LD, W)
when Len < Ll - Col - LD, Len + W + LD =< M, ?ATM(E) ->
{write(E), Len};
pp_element(E, Col, Ll, M, TInd, Ind, LD, W) ->
@@ -348,42 +365,42 @@ pp_binary(S, N, _N0, Ind) ->
end.
%% write the whole thing on a single line
-write({{tuple, _IsTagged, L}, _}) ->
+write({{tuple, _IsTagged, L}, _, _, _}) ->
[${, write_list(L, $,), $}];
-write({{list, L}, _}) ->
+write({{list, L}, _, _, _}) ->
[$[, write_list(L, $|), $]];
-write({{map, Pairs}, _}) ->
+write({{map, Pairs}, _, _, _}) ->
[$#,${, write_list(Pairs, $,), $}];
-write({{map_pair, _K, _V}, _}=Pair) ->
+write({{map_pair, _K, _V}, _, _, _}=Pair) ->
write_pair(Pair);
-write({{record, [{Name,_} | L]}, _}) ->
+write({{record, [{Name,_} | L]}, _, _, _}) ->
[Name, ${, write_fields(L), $}];
-write({{bin, S}, _}) ->
+write({{bin, S}, _, _, _}) ->
S;
-write({S, _}) ->
+write({S, _, _, _}) ->
S.
-write_pair({{map_pair, K, V}, _}) ->
+write_pair({{map_pair, K, V}, _, _, _}) ->
[write(K), " => ", write(V)].
write_fields([]) ->
"";
-write_fields({dots, _}) ->
+write_fields({dots, _, _, _}) ->
"...";
write_fields([F | Fs]) ->
[write_field(F) | write_fields_tail(Fs)].
write_fields_tail([]) ->
"";
-write_fields_tail({dots, _}) ->
+write_fields_tail({dots, _, _, _}) ->
",...";
write_fields_tail([F | Fs]) ->
[$,, write_field(F) | write_fields_tail(Fs)].
-write_field({{field, Name, _NameL, F}, _}) ->
+write_field({{field, Name, _NameL, F}, _, _, _}) ->
[Name, " = " | write(F)].
-write_list({dots, _}, _S) ->
+write_list({dots, _, _, _}, _S) ->
"...";
write_list([E | Es], S) ->
[write(E) | write_tail(Es, S)].
@@ -392,182 +409,365 @@ write_tail([], _S) ->
[];
write_tail([E | Es], S) ->
[$,, write(E) | write_tail(Es, S)];
-write_tail({dots, _}, S) ->
+write_tail({dots, _, _, _}, S) ->
[S | "..."];
write_tail(E, S) ->
[S | write(E)].
+-type more() :: fun((chars_limit(), DeltaDepth :: non_neg_integer()) ->
+ intermediate_format()).
+
+-type if_list() :: maybe_improper_list(intermediate_format(),
+ {'dots', non_neg_integer(),
+ non_neg_integer(), more()}).
+
+-type intermediate_format() ::
+ {chars()
+ | {'bin', chars()}
+ | 'dots'
+ | {'field', Name :: chars(), NameLen :: non_neg_integer(),
+ intermediate_format()}
+ | {'list', if_list()}
+ | {'map', if_list()}
+ | {'map_pair', K :: intermediate_format(),
+ V :: intermediate_format()}
+ | {'record', [{Name :: chars(), NameLen :: non_neg_integer()}
+ | if_list()]}
+ | {'tuple', IsTagged :: boolean(), if_list()},
+ Len :: non_neg_integer(),
+ NumOfDots :: non_neg_integer(),
+ More :: more() | 'no_more'
+ }.
+
+-spec intermediate(term(), depth(), pos_integer(), rec_print_fun(),
+ encoding(), boolean()) -> intermediate_format().
+
+intermediate(Term, D, T, RF, Enc, Str) when T > 0 ->
+ D0 = 1,
+ If = print_length(Term, D0, T, RF, Enc, Str),
+ case If of
+ {_, Len, Dots, _} when Dots =:= 0; Len > T; D =:= 1 ->
+ If;
+ _ ->
+ find_upper(If, Term, T, D0, 2, D, RF, Enc, Str)
+ end.
+
+find_upper(Lower, Term, T, Dl, Dd, D, RF, Enc, Str) ->
+ Dd2 = Dd * 2,
+ D1 = case D < 0 of
+ true -> Dl + Dd2;
+ false -> min(Dl + Dd2, D)
+ end,
+ If = expand(Lower, T, D1 - Dl),
+ case If of
+ {_, _, _Dots=0, _} -> % even if Len > T
+ If;
+ {_, Len, _, _} when Len =< T, D1 < D orelse D < 0 ->
+ find_upper(If, Term, T, D1, Dd2, D, RF, Enc, Str);
+ _ ->
+ search_depth(Lower, If, Term, T, Dl, D1, RF, Enc, Str)
+ end.
+
+%% Lower has NumOfDots > 0 and Len =< T.
+%% Upper has NumOfDots > 0 and Len > T.
+search_depth(Lower, Upper, _Term, T, Dl, Du, _RF, _Enc, _Str)
+ when Du - Dl =:= 1 ->
+ %% The returned intermediate format has Len >= T.
+ case Lower of
+ {_, T, _, _} ->
+ Lower;
+ _ ->
+ Upper
+ end;
+search_depth(Lower, Upper, Term, T, Dl, Du, RF, Enc, Str) ->
+ D1 = (Dl + Du) div 2,
+ If = expand(Lower, T, D1 - Dl),
+ case If of
+ {_, Len, _, _} when Len > T ->
+ %% Len can be greater than Upper's length.
+ %% This is a bit expensive since the work to
+ %% crate Upper is wasted. It is the price
+ %% to pay to get a more balanced output.
+ search_depth(Lower, If, Term, T, Dl, D1, RF, Enc, Str);
+ _ ->
+ search_depth(If, Upper, Term, T, D1, Du, RF, Enc, Str)
+ end.
+
%% The depth (D) is used for extracting and counting the characters to
%% print. The structure is kept so that the returned intermediate
%% format can be formatted. The separators (list, tuple, record, map) are
%% counted but need to be added later.
%% D =/= 0
-print_length([], _D, _RF, _Enc, _Str) ->
- {"[]", 2};
-print_length({}, _D, _RF, _Enc, _Str) ->
- {"{}", 2};
-print_length(#{}=M, _D, _RF, _Enc, _Str) when map_size(M) =:= 0 ->
- {"#{}", 3};
-print_length(Atom, _D, _RF, Enc, _Str) when is_atom(Atom) ->
+print_length([], _D, _T, _RF, _Enc, _Str) ->
+ {"[]", 2, 0, no_more};
+print_length({}, _D, _T, _RF, _Enc, _Str) ->
+ {"{}", 2, 0, no_more};
+print_length(#{}=M, _D, _T, _RF, _Enc, _Str) when map_size(M) =:= 0 ->
+ {"#{}", 3, 0, no_more};
+print_length(Atom, _D, _T, _RF, Enc, _Str) when is_atom(Atom) ->
S = write_atom(Atom, Enc),
- {S, lists:flatlength(S)};
-print_length(List, D, RF, Enc, Str) when is_list(List) ->
+ {S, string:length(S), 0, no_more};
+print_length(List, D, T, RF, Enc, Str) when is_list(List) ->
%% only flat lists are "printable"
- case Str andalso printable_list(List, D, Enc) of
+ case Str andalso printable_list(List, D, T, Enc) of
true ->
%% print as string, escaping double-quotes in the list
S = write_string(List, Enc),
- {S, length(S)};
- %% Truncated lists could break some existing code.
- % {true, Prefix} ->
- % S = write_string(Prefix, Enc),
- % {[S | "..."], 3 + length(S)};
+ {S, string:length(S), 0, no_more};
+ {true, Prefix} ->
+ %% Truncated lists when T < 0 could break some existing code.
+ S = write_string(Prefix, Enc),
+ %% NumOfDots = 0 to avoid looping--increasing the depth
+ %% does not make Prefix longer.
+ {[S | "..."], 3 + string:length(S), 0, no_more};
false ->
- print_length_list(List, D, RF, Enc, Str)
+ case print_length_list(List, D, T, RF, Enc, Str) of
+ {What, Len, Dots, _More} when Dots > 0 ->
+ More = fun(T1, Dd) ->
+ ?FUNCTION_NAME(List, D+Dd, T1, RF, Enc, Str)
+ end,
+ {What, Len, Dots, More};
+ If ->
+ If
+ end
end;
-print_length(Fun, _D, _RF, _Enc, _Str) when is_function(Fun) ->
+print_length(Fun, _D, _T, _RF, _Enc, _Str) when is_function(Fun) ->
S = io_lib:write(Fun),
- {S, iolist_size(S)};
-print_length(R, D, RF, Enc, Str) when is_atom(element(1, R)),
- is_function(RF) ->
+ {S, iolist_size(S), 0, no_more};
+print_length(R, D, T, RF, Enc, Str) when is_atom(element(1, R)),
+ is_function(RF) ->
case RF(element(1, R), tuple_size(R) - 1) of
no ->
- print_length_tuple(R, D, RF, Enc, Str);
+ print_length_tuple(R, D, T, RF, Enc, Str);
RDefs ->
- print_length_record(R, D, RF, RDefs, Enc, Str)
+ print_length_record(R, D, T, RF, RDefs, Enc, Str)
end;
-print_length(Tuple, D, RF, Enc, Str) when is_tuple(Tuple) ->
- print_length_tuple(Tuple, D, RF, Enc, Str);
-print_length(Map, D, RF, Enc, Str) when is_map(Map) ->
- print_length_map(Map, D, RF, Enc, Str);
-print_length(<<>>, _D, _RF, _Enc, _Str) ->
- {"<<>>", 4};
-print_length(<<_/bitstring>>, 1, _RF, _Enc, _Str) ->
- {"<<...>>", 7};
-print_length(<<_/bitstring>>=Bin, D, _RF, Enc, Str) ->
- case bit_size(Bin) rem 8 of
- 0 ->
- D1 = D - 1,
- case Str andalso printable_bin(Bin, D1, Enc) of
- {true, List} when is_list(List) ->
- S = io_lib:write_string(List, $"), %"
- {[$<,$<,S,$>,$>], 4 + length(S)};
- {false, List} when is_list(List) ->
- S = io_lib:write_string(List, $"), %"
- {[$<,$<,S,"/utf8>>"], 9 + length(S)};
- {true, true, Prefix} ->
- S = io_lib:write_string(Prefix, $"), %"
- {[$<,$<, S | "...>>"], 7 + length(S)};
- {false, true, Prefix} ->
- S = io_lib:write_string(Prefix, $"), %"
- {[$<,$<, S | "/utf8...>>"], 12 + length(S)};
- false ->
- S = io_lib:write(Bin, D),
- {{bin,S}, iolist_size(S)}
- end;
- _ ->
- S = io_lib:write(Bin, D),
- {{bin,S}, iolist_size(S)}
+print_length(Tuple, D, T, RF, Enc, Str) when is_tuple(Tuple) ->
+ print_length_tuple(Tuple, D, T, RF, Enc, Str);
+print_length(Map, D, T, RF, Enc, Str) when is_map(Map) ->
+ print_length_map(Map, D, T, RF, Enc, Str);
+print_length(<<>>, _D, _T, _RF, _Enc, _Str) ->
+ {"<<>>", 4, 0, no_more};
+print_length(<<_/bitstring>> = Bin, 1, _T, RF, Enc, Str) ->
+ More = fun(T1, Dd) -> ?FUNCTION_NAME(Bin, 1+Dd, T1, RF, Enc, Str) end,
+ {"<<...>>", 7, 3, More};
+print_length(<<_/bitstring>> = Bin, D, T, RF, Enc, Str) ->
+ D1 = D - 1,
+ case
+ Str andalso
+ (bit_size(Bin) rem 8) =:= 0 andalso
+ printable_bin0(Bin, D1, tsub(T, 6), Enc)
+ of
+ {true, List} when is_list(List) ->
+ S = io_lib:write_string(List, $"), %"
+ {[$<,$<,S,$>,$>], 4 + length(S), 0, no_more};
+ {false, List} when is_list(List) ->
+ S = io_lib:write_string(List, $"), %"
+ {[$<,$<,S,"/utf8>>"], 9 + string:length(S), 0, no_more};
+ {true, true, Prefix} ->
+ S = io_lib:write_string(Prefix, $"), %"
+ More = fun(T1, Dd) ->
+ ?FUNCTION_NAME(Bin, D+Dd, T1, RF, Enc, Str)
+ end,
+ {[$<,$<,S|"...>>"], 7 + length(S), 3, More};
+ {false, true, Prefix} ->
+ S = io_lib:write_string(Prefix, $"), %"
+ More = fun(T1, Dd) ->
+ ?FUNCTION_NAME(Bin, D+Dd, T1, RF, Enc, Str)
+ end,
+ {[$<,$<,S|"/utf8...>>"], 12 + string:length(S), 3, More};
+ false ->
+ case io_lib:write_binary(Bin, D, T) of
+ {S, <<>>} ->
+ {{bin, S}, iolist_size(S), 0, no_more};
+ {S, _Rest} ->
+ More = fun(T1, Dd) ->
+ ?FUNCTION_NAME(Bin, D+Dd, T1, RF, Enc, Str)
+ end,
+ {{bin, S}, iolist_size(S), 3, More}
+ end
end;
-print_length(Term, _D, _RF, _Enc, _Str) ->
+print_length(Term, _D, _T, _RF, _Enc, _Str) ->
S = io_lib:write(Term),
%% S can contain unicode, so iolist_size(S) cannot be used here
- {S, string:length(S)}.
-
-print_length_map(_Map, 1, _RF, _Enc, _Str) ->
- {"#{...}", 6};
-print_length_map(Map, D, RF, Enc, Str) when is_map(Map) ->
- Pairs = print_length_map_pairs(erts_internal:maps_to_list(Map, D), D, RF, Enc, Str),
- {{map, Pairs}, list_length(Pairs, 3)}.
-
-print_length_map_pairs([], _D, _RF, _Enc, _Str) ->
+ {S, string:length(S), 0, no_more}.
+
+print_length_map(Map, 1, _T, RF, Enc, Str) ->
+ More = fun(T1, Dd) -> ?FUNCTION_NAME(Map, 1+Dd, T1, RF, Enc, Str) end,
+ {"#{...}", 6, 3, More};
+print_length_map(Map, D, T, RF, Enc, Str) when is_map(Map) ->
+ Next = maps:next(maps:iterator(Map)),
+ PairsS = print_length_map_pairs(Next, D, D - 1, tsub(T, 3), RF, Enc, Str),
+ {Len, Dots} = list_length(PairsS, 3, 0),
+ {{map, PairsS}, Len, Dots, no_more}.
+
+print_length_map_pairs(none, _D, _D0, _T, _RF, _Enc, _Str) ->
[];
-print_length_map_pairs(_Pairs, 1, _RF, _Enc, _Str) ->
- {dots, 3};
-print_length_map_pairs([{K, V} | Pairs], D, RF, Enc, Str) ->
- [print_length_map_pair(K, V, D - 1, RF, Enc, Str) |
- print_length_map_pairs(Pairs, D - 1, RF, Enc, Str)].
-
-print_length_map_pair(K, V, D, RF, Enc, Str) ->
- {KS, KL} = print_length(K, D, RF, Enc, Str),
- {VS, VL} = print_length(V, D, RF, Enc, Str),
+print_length_map_pairs(Term, D, D0, T, RF, Enc, Str) when D =:= 1; T =:= 0->
+ More = fun(T1, Dd) ->
+ ?FUNCTION_NAME(Term, D+Dd, D0, T1, RF, Enc, Str)
+ end,
+ {dots, 3, 3, More};
+print_length_map_pairs({K, V, Iter}, D, D0, T, RF, Enc, Str) ->
+ Pair1 = print_length_map_pair(K, V, D0, tsub(T, 1), RF, Enc, Str),
+ {_, Len1, _, _} = Pair1,
+ Next = maps:next(Iter),
+ [Pair1 |
+ print_length_map_pairs(Next, D - 1, D0, tsub(T, Len1+1), RF, Enc, Str)].
+
+print_length_map_pair(K, V, D, T, RF, Enc, Str) ->
+ {_, KL, KD, _} = P1 = print_length(K, D, T, RF, Enc, Str),
KL1 = KL + 4,
- {{map_pair, {KS, KL1}, {VS, VL}}, KL1 + VL}.
-
-print_length_tuple(_Tuple, 1, _RF, _Enc, _Str) ->
- {"{...}", 5};
-print_length_tuple(Tuple, D, RF, Enc, Str) ->
- L = print_length_list1(tuple_to_list(Tuple), D, RF, Enc, Str),
+ {_, VL, VD, _} = P2 = print_length(V, D, tsub(T, KL1), RF, Enc, Str),
+ {{map_pair, P1, P2}, KL1 + VL, KD + VD, no_more}.
+
+print_length_tuple(Tuple, 1, _T, RF, Enc, Str) ->
+ More = fun(T1, Dd) -> ?FUNCTION_NAME(Tuple, 1+Dd, T1, RF, Enc, Str) end,
+ {"{...}", 5, 3, More};
+print_length_tuple(Tuple, D, T, RF, Enc, Str) ->
+ L = print_length_tuple1(Tuple, 1, D, tsub(T, 2), RF, Enc, Str),
IsTagged = is_atom(element(1, Tuple)) and (tuple_size(Tuple) > 1),
- {{tuple,IsTagged,L}, list_length(L, 2)}.
+ {Len, Dots} = list_length(L, 2, 0),
+ {{tuple,IsTagged,L}, Len, Dots, no_more}.
-print_length_record(_Tuple, 1, _RF, _RDefs, _Enc, _Str) ->
- {"{...}", 5};
-print_length_record(Tuple, D, RF, RDefs, Enc, Str) ->
+print_length_tuple1(Tuple, I, _D, _T, _RF, _Enc, _Str)
+ when I > tuple_size(Tuple) ->
+ [];
+print_length_tuple1(Tuple, I, D, T, RF, Enc, Str) when D =:= 1; T =:= 0->
+ More = fun(T1, Dd) -> ?FUNCTION_NAME(Tuple, I, D+Dd, T1, RF, Enc, Str) end,
+ {dots, 3, 3, More};
+print_length_tuple1(Tuple, I, D, T, RF, Enc, Str) ->
+ E = element(I, Tuple),
+ T1 = tsub(T, 1),
+ {_, Len1, _, _} = Elem1 = print_length(E, D - 1, T1, RF, Enc, Str),
+ T2 = tsub(T1, Len1),
+ [Elem1 | print_length_tuple1(Tuple, I + 1, D - 1, T2, RF, Enc, Str)].
+
+print_length_record(Tuple, 1, _T, RF, RDefs, Enc, Str) ->
+ More = fun(T1, Dd) ->
+ ?FUNCTION_NAME(Tuple, 1+Dd, T1, RF, RDefs, Enc, Str)
+ end,
+ {"{...}", 5, 3, More};
+print_length_record(Tuple, D, T, RF, RDefs, Enc, Str) ->
Name = [$# | write_atom(element(1, Tuple), Enc)],
- NameL = length(Name),
- Elements = tl(tuple_to_list(Tuple)),
- L = print_length_fields(RDefs, D - 1, Elements, RF, Enc, Str),
- {{record, [{Name,NameL} | L]}, list_length(L, NameL + 2)}.
-
-print_length_fields([], _D, [], _RF, _Enc, _Str) ->
+ NameL = string:length(Name),
+ T1 = tsub(T, NameL+2),
+ L = print_length_fields(RDefs, D - 1, T1, Tuple, 2, RF, Enc, Str),
+ {Len, Dots} = list_length(L, NameL + 2, 0),
+ {{record, [{Name,NameL} | L]}, Len, Dots, no_more}.
+
+print_length_fields([], _D, _T, Tuple, I, _RF, _Enc, _Str)
+ when I > tuple_size(Tuple) ->
[];
-print_length_fields(_, 1, _, _RF, _Enc, _Str) ->
- {dots, 3};
-print_length_fields([Def | Defs], D, [E | Es], RF, Enc, Str) ->
- [print_length_field(Def, D - 1, E, RF, Enc, Str) |
- print_length_fields(Defs, D - 1, Es, RF, Enc, Str)].
-
-print_length_field(Def, D, E, RF, Enc, Str) ->
+print_length_fields(Term, D, T, Tuple, I, RF, Enc, Str)
+ when D =:= 1; T =:= 0 ->
+ More = fun(T1, Dd) ->
+ ?FUNCTION_NAME(Term, D+Dd, T1, Tuple, I, RF, Enc, Str)
+ end,
+ {dots, 3, 3, More};
+print_length_fields([Def | Defs], D, T, Tuple, I, RF, Enc, Str) ->
+ E = element(I, Tuple),
+ T1 = tsub(T, 1),
+ Field1 = print_length_field(Def, D - 1, T1, E, RF, Enc, Str),
+ {_, Len1, _, _} = Field1,
+ T2 = tsub(T1, Len1),
+ [Field1 |
+ print_length_fields(Defs, D - 1, T2, Tuple, I + 1, RF, Enc, Str)].
+
+print_length_field(Def, D, T, E, RF, Enc, Str) ->
Name = write_atom(Def, Enc),
- {S, L} = print_length(E, D, RF, Enc, Str),
- NameL = length(Name) + 3,
- {{field, Name, NameL, {S, L}}, NameL + L}.
+ NameL = string:length(Name) + 3,
+ {_, Len, Dots, _} =
+ Field = print_length(E, D, tsub(T, NameL), RF, Enc, Str),
+ {{field, Name, NameL, Field}, NameL + Len, Dots, no_more}.
-print_length_list(List, D, RF, Enc, Str) ->
- L = print_length_list1(List, D, RF, Enc, Str),
- {{list, L}, list_length(L, 2)}.
+print_length_list(List, D, T, RF, Enc, Str) ->
+ L = print_length_list1(List, D, tsub(T, 2), RF, Enc, Str),
+ {Len, Dots} = list_length(L, 2, 0),
+ {{list, L}, Len, Dots, no_more}.
-print_length_list1([], _D, _RF, _Enc, _Str) ->
+print_length_list1([], _D, _T, _RF, _Enc, _Str) ->
[];
-print_length_list1(_, 1, _RF, _Enc, _Str) ->
- {dots, 3};
-print_length_list1([E | Es], D, RF, Enc, Str) ->
- [print_length(E, D - 1, RF, Enc, Str) |
- print_length_list1(Es, D - 1, RF, Enc, Str)];
-print_length_list1(E, D, RF, Enc, Str) ->
- print_length(E, D - 1, RF, Enc, Str).
-
-list_length([], Acc) ->
- Acc;
-list_length([{_, Len} | Es], Acc) ->
- list_length_tail(Es, Acc + Len);
-list_length({_, Len}, Acc) ->
- Acc + Len.
-
-list_length_tail([], Acc) ->
- Acc;
-list_length_tail([{_,Len} | Es], Acc) ->
- list_length_tail(Es, Acc + 1 + Len);
-list_length_tail({_, Len}, Acc) ->
- Acc + 1 + Len.
+print_length_list1(Term, D, T, RF, Enc, Str) when D =:= 1; T =:= 0->
+ More = fun(T1, Dd) -> ?FUNCTION_NAME(Term, D+Dd, T1, RF, Enc, Str) end,
+ {dots, 3, 3, More};
+print_length_list1([E | Es], D, T, RF, Enc, Str) ->
+ {_, Len1, _, _} = Elem1 = print_length(E, D - 1, tsub(T, 1), RF, Enc, Str),
+ [Elem1 | print_length_list1(Es, D - 1, tsub(T, Len1 + 1), RF, Enc, Str)];
+print_length_list1(E, D, T, RF, Enc, Str) ->
+ print_length(E, D - 1, T, RF, Enc, Str).
+
+list_length([], Acc, DotsAcc) ->
+ {Acc, DotsAcc};
+list_length([{_, Len, Dots, _} | Es], Acc, DotsAcc) ->
+ list_length_tail(Es, Acc + Len, DotsAcc + Dots);
+list_length({_, Len, Dots, _}, Acc, DotsAcc) ->
+ {Acc + Len, DotsAcc + Dots}.
+
+list_length_tail([], Acc, DotsAcc) ->
+ {Acc, DotsAcc};
+list_length_tail([{_, Len, Dots, _} | Es], Acc, DotsAcc) ->
+ list_length_tail(Es, Acc + 1 + Len, DotsAcc + Dots);
+list_length_tail({_, Len, Dots, _}, Acc, DotsAcc) ->
+ {Acc + 1 + Len, DotsAcc + Dots}.
%% ?CHARS printable characters has depth 1.
-define(CHARS, 4).
%% only flat lists are "printable"
-printable_list(_L, 1, _Enc) ->
+printable_list(_L, 1, _T, _Enc) ->
false;
-printable_list(L, _D, latin1) ->
+printable_list(L, _D, T, latin1) when T < 0 ->
io_lib:printable_latin1_list(L);
-printable_list(L, _D, _Uni) ->
+printable_list(L, _D, T, Enc) when T >= 0 ->
+ case slice(L, tsub(T, 2)) of
+ false ->
+ false;
+ {prefix, Prefix} when Enc =:= latin1 ->
+ io_lib:printable_latin1_list(Prefix) andalso {true, Prefix};
+ {prefix, Prefix} ->
+ %% Probably an overestimation.
+ io_lib:printable_list(Prefix) andalso {true, Prefix};
+ all when Enc =:= latin1 ->
+ io_lib:printable_latin1_list(L);
+ all ->
+ io_lib:printable_list(L)
+ end;
+printable_list(L, _D, T, _Uni) when T < 0->
io_lib:printable_list(L).
-printable_bin(Bin, D, Enc) when D >= 0, ?CHARS * D =< byte_size(Bin) ->
- printable_bin(Bin, erlang:min(?CHARS * D, byte_size(Bin)), D, Enc);
-printable_bin(Bin, D, Enc) ->
- printable_bin(Bin, byte_size(Bin), D, Enc).
+slice(L, N) ->
+ try string:length(L) =< N of
+ true ->
+ all;
+ false ->
+ case string:slice(L, 0, N) of
+ "" ->
+ false;
+ Prefix ->
+ {prefix, Prefix}
+ end
+ catch _:_ -> false
+ end.
+
+printable_bin0(Bin, D, T, Enc) ->
+ Len = case D >= 0 of
+ true ->
+ %% Use byte_size() also if Enc =/= latin1.
+ DChars = erlang:min(?CHARS * D, byte_size(Bin)),
+ case T >= 0 of
+ true ->
+ erlang:min(T, DChars);
+ false ->
+ DChars
+ end;
+ false when T < 0 ->
+ byte_size(Bin);
+ false when T >= 0 -> % cannot happen
+ T
+ end,
+ printable_bin(Bin, Len, D, Enc).
printable_bin(Bin, Len, D, latin1) ->
N = erlang:min(20, Len),
@@ -679,28 +879,70 @@ write_string(S, latin1) ->
write_string(S, _Uni) ->
io_lib:write_string(S, $"). %"
+expand({_, _, _Dots=0, no_more} = If, _T, _Dd) -> If;
+%% expand({{list,L}, _Len, _, no_more}, T, Dd) ->
+%% {NL, NLen, NDots} = expand_list(L, T, Dd, 2),
+%% {{list,NL}, NLen, NDots, no_more};
+expand({{tuple,IsTagged,L}, _Len, _, no_more}, T, Dd) ->
+ {NL, NLen, NDots} = expand_list(L, T, Dd, 2),
+ {{tuple,IsTagged,NL}, NLen, NDots, no_more};
+expand({{map, Pairs}, _Len, _, no_more}, T, Dd) ->
+ {NPairs, NLen, NDots} = expand_list(Pairs, T, Dd, 3),
+ {{map, NPairs}, NLen, NDots, no_more};
+expand({{map_pair, K, V}, _Len, _, no_more}, T, Dd) ->
+ {_, KL, KD, _} = P1 = expand(K, tsub(T, 1), Dd),
+ KL1 = KL + 4,
+ {_, VL, VD, _} = P2 = expand(V, tsub(T, KL1), Dd),
+ {{map_pair, P1, P2}, KL1 + VL, KD + VD, no_more};
+expand({{record, [{Name,NameL} | L]}, _Len, _, no_more}, T, Dd) ->
+ {NL, NLen, NDots} = expand_list(L, T, Dd, NameL + 2),
+ {{record, [{Name,NameL} | NL]}, NLen, NDots, no_more};
+expand({{field, Name, NameL, Field}, _Len, _, no_more}, T, Dd) ->
+ F = {_S, L, Dots, _} = expand(Field, tsub(T, NameL), Dd),
+ {{field, Name, NameL, F}, NameL + L, Dots, no_more};
+expand({_, _, _, More}, T, Dd) ->
+ More(T, Dd).
+
+expand_list(Ifs, T, Dd, L0) ->
+ L = expand_list(Ifs, tsub(T, L0), Dd),
+ {Len, Dots} = list_length(L, L0, 0),
+ {L, Len, Dots}.
+
+expand_list([], _T, _Dd) ->
+ [];
+expand_list([If | Ifs], T, Dd) ->
+ {_, Len1, _, _} = Elem1 = expand(If, tsub(T, 1), Dd),
+ [Elem1 | expand_list(Ifs, tsub(T, Len1 + 1), Dd)];
+expand_list({_, _, _, More}, T, Dd) ->
+ More(T, Dd).
+
+%% Make sure T does not change sign.
+tsub(T, _) when T < 0 -> T;
+tsub(T, E) when T >= E -> T - E;
+tsub(_, _) -> 0.
+
%% Throw 'no_good' if the indentation exceeds half the line length
%% unless there is room for M characters on the line.
-cind({_S, Len}, Col, Ll, M, Ind, LD, W) when Len < Ll - Col - LD,
- Len + W + LD =< M ->
+cind({_S, Len, _, _}, Col, Ll, M, Ind, LD, W) when Len < Ll - Col - LD,
+ Len + W + LD =< M ->
Ind;
-cind({{list,L}, _Len}, Col, Ll, M, Ind, LD, W) ->
+cind({{list,L}, _Len, _, _}, Col, Ll, M, Ind, LD, W) ->
cind_list(L, Col + 1, Ll, M, Ind, LD, W + 1);
-cind({{tuple,true,L}, _Len}, Col, Ll, M, Ind, LD, W) ->
+cind({{tuple,true,L}, _Len, _ ,_}, Col, Ll, M, Ind, LD, W) ->
cind_tag_tuple(L, Col, Ll, M, Ind, LD, W + 1);
-cind({{tuple,false,L}, _Len}, Col, Ll, M, Ind, LD, W) ->
+cind({{tuple,false,L}, _Len, _, _}, Col, Ll, M, Ind, LD, W) ->
cind_list(L, Col + 1, Ll, M, Ind, LD, W + 1);
-cind({{map,Pairs},_Len}, Col, Ll, M, Ind, LD, W) ->
+cind({{map,Pairs}, _Len, _, _}, Col, Ll, M, Ind, LD, W) ->
cind_map(Pairs, Col + 2, Ll, M, Ind, LD, W + 2);
-cind({{record,[{_Name,NLen} | L]}, _Len}, Col, Ll, M, Ind, LD, W) ->
+cind({{record,[{_Name,NLen} | L]}, _Len, _, _}, Col, Ll, M, Ind, LD, W) ->
cind_record(L, NLen, Col, Ll, M, Ind, LD, W + NLen + 1);
-cind({{bin,_S}, _Len}, _Col, _Ll, _M, Ind, _LD, _W) ->
+cind({{bin,_S}, _Len, _, _}, _Col, _Ll, _M, Ind, _LD, _W) ->
Ind;
-cind({_S, _Len}, _Col, _Ll, _M, Ind, _LD, _W) ->
+cind({_S,_Len,_,_}, _Col, _Ll, _M, Ind, _LD, _W) ->
Ind.
-cind_tag_tuple([{_Tag,Tlen} | L], Col, Ll, M, Ind, LD, W) ->
+cind_tag_tuple([{_Tag,Tlen,_,_} | L], Col, Ll, M, Ind, LD, W) ->
TagInd = Tlen + 2,
Tcol = Col + TagInd,
if
@@ -722,9 +964,9 @@ cind_map([P | Ps], Col, Ll, M, Ind, LD, W) ->
PW = cind_pair(P, Col, Ll, M, Ind, last_depth(Ps, LD), W),
cind_pairs_tail(Ps, Col, Col + PW, Ll, M, Ind, LD, W + PW);
cind_map(_, _Col, _Ll, _M, Ind, _LD, _W) ->
- Ind.
+ Ind. % cannot happen
-cind_pairs_tail([{_, Len}=P | Ps], Col0, Col, Ll, M, Ind, LD, W) ->
+cind_pairs_tail([{_, Len, _, _} = P | Ps], Col0, Col, Ll, M, Ind, LD, W) ->
LD1 = last_depth(Ps, LD),
ELen = 1 + Len,
if
@@ -738,7 +980,7 @@ cind_pairs_tail([{_, Len}=P | Ps], Col0, Col, Ll, M, Ind, LD, W) ->
cind_pairs_tail(_, _Col0, _Col, _Ll, _M, Ind, _LD, _W) ->
Ind.
-cind_pair({{map_pair, _Key, _Value}, Len}=Pair, Col, Ll, M, _Ind, LD, W)
+cind_pair({{map_pair, _Key, _Value}, Len, _, _}=Pair, Col, Ll, M, _Ind, LD, W)
when Len < Ll - Col - LD, Len + W + LD =< M ->
if
?ATM_PAIR(Pair) ->
@@ -746,7 +988,7 @@ cind_pair({{map_pair, _Key, _Value}, Len}=Pair, Col, Ll, M, _Ind, LD, W)
true ->
Ll
end;
-cind_pair({{map_pair, K, V}, _Len}, Col0, Ll, M, Ind, LD, W0) ->
+cind_pair({{map_pair, K, V}, _Len, _, _}, Col0, Ll, M, Ind, LD, W0) ->
cind(K, Col0, Ll, M, Ind, LD, W0),
I = map_value_indent(Ind),
cind(V, Col0 + I, Ll, M, Ind, LD, 0),
@@ -768,7 +1010,7 @@ cind_record([F | Fs], Nlen, Col0, Ll, M, Ind, LD, W0) ->
cind_record(_, _Nlen, _Col, _Ll, _M, Ind, _LD, _W) ->
Ind.
-cind_fields_tail([{_, Len}=F | Fs], Col0, Col, Ll, M, Ind, LD, W) ->
+cind_fields_tail([{_, Len, _, _} = F | Fs], Col0, Col, Ll, M, Ind, LD, W) ->
LD1 = last_depth(Fs, LD),
ELen = 1 + Len,
if
@@ -782,7 +1024,7 @@ cind_fields_tail([{_, Len}=F | Fs], Col0, Col, Ll, M, Ind, LD, W) ->
cind_fields_tail(_, _Col0, _Col, _Ll, _M, Ind, _LD, _W) ->
Ind.
-cind_field({{field, _N, _NL, _F}, Len}=Fl, Col, Ll, M, _Ind, LD, W)
+cind_field({{field, _N, _NL, _F}, Len, _, _}=Fl, Col, Ll, M, _Ind, LD, W)
when Len < Ll - Col - LD, Len + W + LD =< M ->
if
?ATM_FLD(Fl) ->
@@ -790,7 +1032,7 @@ cind_field({{field, _N, _NL, _F}, Len}=Fl, Col, Ll, M, _Ind, LD, W)
true ->
Ll
end;
-cind_field({{field, _Name, NameL, F}, _Len}, Col0, Ll, M, Ind, LD, W0) ->
+cind_field({{field, _Name, NameL, F},_Len,_,_}, Col0, Ll, M, Ind, LD, W0) ->
{Col, W} = cind_rec(NameL, Col0, Ll, M, Ind, W0 + NameL),
cind(F, Col, Ll, M, Ind, LD, W),
Ll.
@@ -813,7 +1055,7 @@ cind_rec(RInd, Col0, Ll, M, Ind, W0) ->
throw(no_good)
end.
-cind_list({dots, _}, _Col0, _Ll, _M, Ind, _LD, _W) ->
+cind_list({dots, _, _, _}, _Col0, _Ll, _M, Ind, _LD, _W) ->
Ind;
cind_list([E | Es], Col0, Ll, M, Ind, LD, W) ->
WE = cind_element(E, Col0, Ll, M, Ind, last_depth(Es, LD), W),
@@ -821,7 +1063,7 @@ cind_list([E | Es], Col0, Ll, M, Ind, LD, W) ->
cind_tail([], _Col0, _Col, _Ll, _M, Ind, _LD, _W) ->
Ind;
-cind_tail([{_, Len}=E | Es], Col0, Col, Ll, M, Ind, LD, W) ->
+cind_tail([{_, Len, _, _} = E | Es], Col0, Col, Ll, M, Ind, LD, W) ->
LD1 = last_depth(Es, LD),
ELen = 1 + Len,
if
@@ -832,9 +1074,9 @@ cind_tail([{_, Len}=E | Es], Col0, Col, Ll, M, Ind, LD, W) ->
WE = cind_element(E, Col0, Ll, M, Ind, LD1, 0),
cind_tail(Es, Col0, Col0 + WE, Ll, M, Ind, LD, WE)
end;
-cind_tail({dots, _}, _Col0, _Col, _Ll, _M, Ind, _LD, _W) ->
+cind_tail({dots, _, _, _}, _Col0, _Col, _Ll, _M, Ind, _LD, _W) ->
Ind;
-cind_tail({_, Len}=E, _Col0, Col, Ll, M, Ind, LD, W)
+cind_tail({_, Len, _, _}=E, _Col0, Col, Ll, M, Ind, LD, W)
when Len + 1 < Ll - Col - (LD + 1),
Len + 1 + W + (LD + 1) =< M,
?ATM(E) ->
@@ -842,7 +1084,7 @@ cind_tail({_, Len}=E, _Col0, Col, Ll, M, Ind, LD, W)
cind_tail(E, _Col0, Col, Ll, M, Ind, LD, _W) ->
cind(E, Col, Ll, M, Ind, LD + 1, 0).
-cind_element({_, Len}=E, Col, Ll, M, _Ind, LD, W)
+cind_element({_, Len, _, _}=E, Col, Ll, M, _Ind, LD, W)
when Len < Ll - Col - LD, Len + W + LD =< M, ?ATM(E) ->
Len;
cind_element(E, Col, Ll, M, Ind, LD, W) ->
diff --git a/lib/stdlib/src/lib.erl b/lib/stdlib/src/lib.erl
deleted file mode 100644
index c6eb0d7915..0000000000
--- a/lib/stdlib/src/lib.erl
+++ /dev/null
@@ -1,746 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
--module(lib).
-
--export([flush_receive/0, error_message/2, progname/0, nonl/1, send/2,
- sendw/2, eval_str/1]).
-
--export([extended_parse_exprs/1, extended_parse_term/1,
- subst_values_for_vars/2]).
-
--export([format_exception/6, format_exception/7,
- format_stacktrace/4, format_stacktrace/5,
- format_call/4, format_call/5, format_fun/1, format_fun/2]).
-
--spec flush_receive() -> 'ok'.
-
-flush_receive() ->
- receive
- _Any ->
- flush_receive()
- after
- 0 ->
- ok
- end.
-
-%%
-%% Functions for doing standard system format i/o.
-%%
--spec error_message(Format, Args) -> 'ok' when
- Format :: io:format(),
- Args :: [term()].
-
-error_message(Format, Args) ->
- io:format(<<"** ~ts **\n">>, [io_lib:format(Format, Args)]).
-
-%% Return the name of the script that starts (this) erlang
-%%
--spec progname() -> atom().
-
-progname() ->
- case init:get_argument(progname) of
- {ok, [[Prog]]} ->
- list_to_atom(Prog);
- _Other ->
- no_prog_name
- end.
-
--spec nonl(String1) -> String2 when
- String1 :: string(),
- String2 :: string().
-
-nonl([10]) -> [];
-nonl([]) -> [];
-nonl([H|T]) -> [H|nonl(T)].
-
--spec send(To, Msg) -> Msg when
- To :: pid() | atom() | {atom(), node()},
- Msg :: term().
-
-send(To, Msg) -> To ! Msg.
-
--spec sendw(To, Msg) -> term() when
- To :: pid() | atom() | {atom(), node()},
- Msg :: term().
-
-sendw(To, Msg) ->
- To ! {self(), Msg},
- receive
- Reply -> Reply
- end.
-
-%% eval_str(InStr) -> {ok, OutStr} | {error, ErrStr'}
-%% InStr must represent a body
-%% Note: If InStr is a binary it has to be a Latin-1 string.
-%% If you have a UTF-8 encoded binary you have to call
-%% unicode:characters_to_list/1 before the call to eval_str().
-
--define(result(F,D), lists:flatten(io_lib:format(F, D))).
-
--spec eval_str(string() | unicode:latin1_binary()) ->
- {'ok', string()} | {'error', string()}.
-
-eval_str(Str) when is_list(Str) ->
- case erl_scan:tokens([], Str, 0) of
- {more, _} ->
- {error, "Incomplete form (missing .<cr>)??"};
- {done, {ok, Toks, _}, Rest} ->
- case all_white(Rest) of
- true ->
- case erl_parse:parse_exprs(Toks) of
- {ok, Exprs} ->
- case catch erl_eval:exprs(Exprs, erl_eval:new_bindings()) of
- {value, Val, _} ->
- {ok, Val};
- Other ->
- {error, ?result("*** eval: ~p", [Other])}
- end;
- {error, {_Line, Mod, Args}} ->
- Msg = ?result("*** ~ts",[Mod:format_error(Args)]),
- {error, Msg}
- end;
- false ->
- {error, ?result("Non-white space found after "
- "end-of-form :~ts", [Rest])}
- end
- end;
-eval_str(Bin) when is_binary(Bin) ->
- eval_str(binary_to_list(Bin)).
-
-all_white([$\s|T]) -> all_white(T);
-all_white([$\n|T]) -> all_white(T);
-all_white([$\t|T]) -> all_white(T);
-all_white([]) -> true;
-all_white(_) -> false.
-
-%% `Tokens' is assumed to have been scanned with the 'text' option.
-%% The annotations of the returned expressions are locations.
-%%
-%% Can handle pids, ports, references, and external funs ("items").
-%% Known items are represented by variables in the erl_parse tree, and
-%% the items themselves are stored in the returned bindings.
-
--spec extended_parse_exprs(Tokens) ->
- {'ok', ExprList, Bindings} | {'error', ErrorInfo} when
- Tokens :: [erl_scan:token()],
- ExprList :: [erl_parse:abstract_expr()],
- Bindings :: erl_eval:binding_struct(),
- ErrorInfo :: erl_parse:error_info().
-
-extended_parse_exprs(Tokens) ->
- Ts = tokens_fixup(Tokens),
- case erl_parse:parse_exprs(Ts) of
- {ok, Exprs0} ->
- {Exprs, Bs} = expr_fixup(Exprs0),
- {ok, reset_expr_anno(Exprs), Bs};
- _ErrorInfo ->
- erl_parse:parse_exprs(reset_token_anno(Ts))
- end.
-
-tokens_fixup([]) -> [];
-tokens_fixup([T|Ts]=Ts0) ->
- try token_fixup(Ts0) of
- {NewT, NewTs} ->
- [NewT|tokens_fixup(NewTs)]
- catch
- _:_ ->
- [T|tokens_fixup(Ts)]
- end.
-
-token_fixup(Ts) ->
- {AnnoL, NewTs, FixupTag} = unscannable(Ts),
- String = lists:append([erl_anno:text(A) || A <- AnnoL]),
- _ = (fixup_fun(FixupTag))(String),
- NewAnno = erl_anno:set_text(fixup_text(FixupTag), hd(AnnoL)),
- {{string, NewAnno, String}, NewTs}.
-
-unscannable([{'#', A1}, {var, A2, 'Fun'}, {'<', A3}, {atom, A4, _},
- {'.', A5}, {float, A6, _}, {'>', A7}|Ts]) ->
- {[A1, A2, A3, A4, A5, A6, A7], Ts, function};
-unscannable([{'#', A1}, {var, A2, 'Fun'}, {'<', A3}, {atom, A4, _},
- {'.', A5}, {atom, A6, _}, {'.', A7}, {integer, A8, _},
- {'>', A9}|Ts]) ->
- {[A1, A2, A3, A4, A5, A6, A7, A8, A9], Ts, function};
-unscannable([{'<', A1}, {float, A2, _}, {'.', A3}, {integer, A4, _},
- {'>', A5}|Ts]) ->
- {[A1, A2, A3, A4, A5], Ts, pid};
-unscannable([{'#', A1}, {var, A2, 'Port'}, {'<', A3}, {float, A4, _},
- {'>', A5}|Ts]) ->
- {[A1, A2, A3, A4, A5], Ts, port};
-unscannable([{'#', A1}, {var, A2, 'Ref'}, {'<', A3}, {float, A4, _},
- {'.', A5}, {float, A6, _}, {'>', A7}|Ts]) ->
- {[A1, A2, A3, A4, A5, A6, A7], Ts, reference}.
-
-expr_fixup(Expr0) ->
- {Expr, Bs, _} = expr_fixup(Expr0, erl_eval:new_bindings(), 1),
- {Expr, Bs}.
-
-expr_fixup({string,A,S}=T, Bs0, I) ->
- try string_fixup(A, S) of
- Value ->
- Var = new_var(I),
- Bs = erl_eval:add_binding(Var, Value, Bs0),
- {{var, A, Var}, Bs, I+1}
- catch
- _:_ ->
- {T, Bs0, I}
- end;
-expr_fixup(Tuple, Bs0, I0) when is_tuple(Tuple) ->
- {L, Bs, I} = expr_fixup(tuple_to_list(Tuple), Bs0, I0),
- {list_to_tuple(L), Bs, I};
-expr_fixup([E0|Es0], Bs0, I0) ->
- {E, Bs1, I1} = expr_fixup(E0, Bs0, I0),
- {Es, Bs, I} = expr_fixup(Es0, Bs1, I1),
- {[E|Es], Bs, I};
-expr_fixup(T, Bs, I) ->
- {T, Bs, I}.
-
-string_fixup(A, S) ->
- Text = erl_anno:text(A),
- FixupTag = fixup_tag(Text, S),
- (fixup_fun(FixupTag))(S).
-
-new_var(I) ->
- list_to_atom(lists:concat(['__ExtendedParseExprs_', I, '__'])).
-
-reset_token_anno(Tokens) ->
- [setelement(2, T, (reset_anno())(element(2, T))) || T <- Tokens].
-
-reset_expr_anno(Exprs) ->
- [erl_parse:map_anno(reset_anno(), E) || E <- Exprs].
-
-reset_anno() ->
- fun(A) -> erl_anno:new(erl_anno:location(A)) end.
-
-fixup_fun(function) -> fun function/1;
-fixup_fun(pid) -> fun erlang:list_to_pid/1;
-fixup_fun(port) -> fun erlang:list_to_port/1;
-fixup_fun(reference) -> fun erlang:list_to_ref/1.
-
-function(S) ->
- %% External function.
- {ok, [_, _, _,
- {atom, _, Module}, _,
- {atom, _, Function}, _,
- {integer, _, Arity}|_], _} = erl_scan:string(S),
- erlang:make_fun(Module, Function, Arity).
-
-fixup_text(function) -> "function";
-fixup_text(pid) -> "pid";
-fixup_text(port) -> "port";
-fixup_text(reference) -> "reference".
-
-fixup_tag("function", "#"++_) -> function;
-fixup_tag("pid", "<"++_) -> pid;
-fixup_tag("port", "#"++_) -> port;
-fixup_tag("reference", "#"++_) -> reference.
-
-%%% End of extended_parse_exprs.
-
-%% `Tokens' is assumed to have been scanned with the 'text' option.
-%%
-%% Can handle pids, ports, references, and external funs.
-
--spec extended_parse_term(Tokens) ->
- {'ok', Term} | {'error', ErrorInfo} when
- Tokens :: [erl_scan:token()],
- Term :: term(),
- ErrorInfo :: erl_parse:error_info().
-
-extended_parse_term(Tokens) ->
- case extended_parse_exprs(Tokens) of
- {ok, [Expr], Bindings} ->
- try normalise(Expr, Bindings) of
- Term ->
- {ok, Term}
- catch
- _:_ ->
- Loc = erl_anno:location(element(2, Expr)),
- {error,{Loc,?MODULE,"bad term"}}
- end;
- {ok, [_,Expr|_], _Bindings} ->
- Loc = erl_anno:location(element(2, Expr)),
- {error,{Loc,?MODULE,"bad term"}};
- {error, _} = Error ->
- Error
- end.
-
-%% From erl_parse.
-normalise({var, _, V}, Bs) ->
- {value, Value} = erl_eval:binding(V, Bs),
- Value;
-normalise({char,_,C}, _Bs) -> C;
-normalise({integer,_,I}, _Bs) -> I;
-normalise({float,_,F}, _Bs) -> F;
-normalise({atom,_,A}, _Bs) -> A;
-normalise({string,_,S}, _Bs) -> S;
-normalise({nil,_}, _Bs) -> [];
-normalise({bin,_,Fs}, Bs) ->
- {value, B, _} =
- eval_bits:expr_grp(Fs, [],
- fun(E, _) ->
- {value, normalise(E, Bs), []}
- end, [], true),
- B;
-normalise({cons,_,Head,Tail}, Bs) ->
- [normalise(Head, Bs)|normalise(Tail, Bs)];
-normalise({tuple,_,Args}, Bs) ->
- list_to_tuple(normalise_list(Args, Bs));
-normalise({map,_,Pairs}, Bs) ->
- maps:from_list(lists:map(fun
- %% only allow '=>'
- ({map_field_assoc,_,K,V}) ->
- {normalise(K, Bs),normalise(V, Bs)}
- end, Pairs));
-%% Special case for unary +/-.
-normalise({op,_,'+',{char,_,I}}, _Bs) -> I;
-normalise({op,_,'+',{integer,_,I}}, _Bs) -> I;
-normalise({op,_,'+',{float,_,F}}, _Bs) -> F;
-normalise({op,_,'-',{char,_,I}}, _Bs) -> -I; %Weird, but compatible!
-normalise({op,_,'-',{integer,_,I}}, _Bs) -> -I;
-normalise({op,_,'-',{float,_,F}}, _Bs) -> -F;
-normalise({'fun',_,{function,{atom,_,M},{atom,_,F},{integer,_,A}}}, _Bs) ->
- %% Since "#Fun<M.F.A>" is recognized, "fun M:F/A" should be too.
- fun M:F/A.
-
-normalise_list([H|T], Bs) ->
- [normalise(H, Bs)|normalise_list(T, Bs)];
-normalise_list([], _Bs) ->
- [].
-
-%% To be used on ExprList and Bindings returned from extended_parse_exprs().
-%% Substitute {value, A, Item} for {var, A, ExtendedParseVar}.
-%% {value, A, Item} is a shell/erl_eval convention, and for example
-%% the linter cannot handle it.
-
--spec subst_values_for_vars(ExprList, Bindings) -> [term()] when
- ExprList :: [erl_parse:abstract_expr()],
- Bindings :: erl_eval:binding_struct().
-
-subst_values_for_vars({var, A, V}=Var, Bs) ->
- case erl_eval:binding(V, Bs) of
- {value, Value} ->
- {value, A, Value};
- unbound ->
- Var
- end;
-subst_values_for_vars(L, Bs) when is_list(L) ->
- [subst_values_for_vars(E, Bs) || E <- L];
-subst_values_for_vars(T, Bs) when is_tuple(T) ->
- list_to_tuple(subst_values_for_vars(tuple_to_list(T), Bs));
-subst_values_for_vars(T, _Bs) ->
- T.
-
-%%% Formatting of exceptions, mfa:s and funs.
-
-%% -> iolist() (no \n at end)
-%% I is the current column, starting from 1 (it will be used
-%% as indentation whenever newline has been inserted);
-%% Class, Reason and StackTrace are the exception;
-%% FormatFun = fun(Term, I) -> iolist() formats terms;
-%% StackFun = fun(Mod, Fun, Arity) -> boolean() is used for trimming the
-%% end of the stack (typically calls to erl_eval are skipped).
-format_exception(I, Class, Reason, StackTrace, StackFun, FormatFun) ->
- format_exception(I, Class, Reason, StackTrace, StackFun, FormatFun,
- latin1).
-
-%% -> iolist() | unicode:charlist() (no \n at end)
-%% FormatFun = fun(Term, I) -> iolist() | unicode:charlist().
-format_exception(I, Class, Reason, StackTrace, StackFun, FormatFun, Encoding)
- when is_integer(I), I >= 1, is_function(StackFun, 3),
- is_function(FormatFun, 2) ->
- S = n_spaces(I-1),
- {Term,Trace1,Trace} = analyze_exception(Class, Reason, StackTrace),
- Expl0 = explain_reason(Term, Class, Trace1, FormatFun, S, Encoding),
- FormatString = case Encoding of
- latin1 -> "~s~s";
- _ -> "~s~ts"
- end,
- Expl = io_lib:fwrite(FormatString, [exited(Class), Expl0]),
- case format_stacktrace1(S, Trace, FormatFun, StackFun, Encoding) of
- [] -> Expl;
- Stack -> [Expl, $\n, Stack]
- end.
-
-%% -> iolist() (no \n at end)
-format_stacktrace(I, StackTrace, StackFun, FormatFun) ->
- format_stacktrace(I, StackTrace, StackFun, FormatFun, latin1).
-
-%% -> iolist() | unicode:charlist() (no \n at end)
-format_stacktrace(I, StackTrace, StackFun, FormatFun, Encoding)
- when is_integer(I), I >= 1, is_function(StackFun, 3),
- is_function(FormatFun, 2) ->
- S = n_spaces(I-1),
- format_stacktrace1(S, StackTrace, FormatFun, StackFun, Encoding).
-
-%% -> iolist() (no \n at end)
-format_call(I, ForMForFun, As, FormatFun) ->
- format_call(I, ForMForFun, As, FormatFun, latin1).
-
-%% -> iolist() | unicode:charlist() (no \n at end)
-format_call(I, ForMForFun, As, FormatFun, Enc)
- when is_integer(I), I >= 1, is_list(As), is_function(FormatFun, 2) ->
- format_call("", n_spaces(I-1), ForMForFun, As, FormatFun, Enc).
-
-%% -> iolist() (no \n at end)
-format_fun(Fun) ->
- format_fun(Fun, latin1).
-
-%% -> iolist() (no \n at end)
-format_fun(Fun, Enc) when is_function(Fun) ->
- {module, M} = erlang:fun_info(Fun, module),
- {name, F} = erlang:fun_info(Fun, name),
- {arity, A} = erlang:fun_info(Fun, arity),
- case erlang:fun_info(Fun, type) of
- {type, local} when F =:= "" ->
- io_lib:fwrite(<<"~w">>, [Fun]);
- {type, local} when M =:= erl_eval ->
- io_lib:fwrite(<<"interpreted function with arity ~w">>, [A]);
- {type, local} ->
- mfa_to_string(M, F, A, Enc);
- {type, external} ->
- mfa_to_string(M, F, A, Enc)
- end.
-
-analyze_exception(error, Term, Stack) ->
- case {is_stacktrace(Stack), Stack, Term} of
- {true, [{_,_,As,_}=MFAL|MFAs], function_clause} when is_list(As) ->
- {Term,[MFAL],MFAs};
- {true, [{shell,F,A,_}], function_clause} when is_integer(A) ->
- {Term, [{F,A}], []};
- {true, [{_,_,_,_}=MFAL|MFAs], undef} ->
- {Term,[MFAL],MFAs};
- {true, _, _} ->
- {Term,[],Stack};
- {false, _, _} ->
- {{Term,Stack},[],[]}
- end;
-analyze_exception(_Class, Term, Stack) ->
- case is_stacktrace(Stack) of
- true ->
- {Term,[],Stack};
- false ->
- {{Term,Stack},[],[]}
- end.
-
-is_stacktrace([]) ->
- true;
-is_stacktrace([{M,F,A,I}|Fs])
- when is_atom(M), is_atom(F), is_integer(A), is_list(I) ->
- is_stacktrace(Fs);
-is_stacktrace([{M,F,As,I}|Fs])
- when is_atom(M), is_atom(F), length(As) >= 0, is_list(I) ->
- is_stacktrace(Fs);
-is_stacktrace(_) ->
- false.
-
-%% ERTS exit codes (some of them are also returned by erl_eval):
-explain_reason(badarg, error, [], _PF, _S, _Enc) ->
- <<"bad argument">>;
-explain_reason({badarg,V}, error=Cl, [], PF, S, _Enc) -> % orelse, andalso
- format_value(V, <<"bad argument: ">>, Cl, PF, S);
-explain_reason(badarith, error, [], _PF, _S, _Enc) ->
- <<"an error occurred when evaluating an arithmetic expression">>;
-explain_reason({badarity,{Fun,As}}, error, [], _PF, _S, Enc)
- when is_function(Fun) ->
- %% Only the arity is displayed, not the arguments As.
- io_lib:fwrite(<<"~ts called with ~s">>,
- [format_fun(Fun, Enc), argss(length(As))]);
-explain_reason({badfun,Term}, error=Cl, [], PF, S, _Enc) ->
- format_value(Term, <<"bad function ">>, Cl, PF, S);
-explain_reason({badmatch,Term}, error=Cl, [], PF, S, _Enc) ->
- Str = <<"no match of right hand side value ">>,
- format_value(Term, Str, Cl, PF, S);
-explain_reason({case_clause,V}, error=Cl, [], PF, S, _Enc) ->
- %% "there is no case clause with a true guard sequence and a
- %% pattern matching..."
- format_value(V, <<"no case clause matching ">>, Cl, PF, S);
-explain_reason(function_clause, error, [{F,A}], _PF, _S, _Enc) ->
- %% Shell commands
- FAs = io_lib:fwrite(<<"~w/~w">>, [F, A]),
- [<<"no function clause matching call to ">> | FAs];
-explain_reason(function_clause, error=Cl, [{M,F,As,Loc}], PF, S, Enc) ->
- Str = <<"no function clause matching ">>,
- [format_errstr_call(Str, Cl, {M,F}, As, PF, S, Enc),$\s|location(Loc)];
-explain_reason(if_clause, error, [], _PF, _S, _Enc) ->
- <<"no true branch found when evaluating an if expression">>;
-explain_reason(noproc, error, [], _PF, _S, _Enc) ->
- <<"no such process or port">>;
-explain_reason(notalive, error, [], _PF, _S, _Enc) ->
- <<"the node cannot be part of a distributed system">>;
-explain_reason(system_limit, error, [], _PF, _S, _Enc) ->
- <<"a system limit has been reached">>;
-explain_reason(timeout_value, error, [], _PF, _S, _Enc) ->
- <<"bad receive timeout value">>;
-explain_reason({try_clause,V}, error=Cl, [], PF, S, _Enc) ->
- %% "there is no try clause with a true guard sequence and a
- %% pattern matching..."
- format_value(V, <<"no try clause matching ">>, Cl, PF, S);
-explain_reason(undef, error, [{M,F,A,_}], _PF, _S, Enc) ->
- %% Only the arity is displayed, not the arguments, if there are any.
- io_lib:fwrite(<<"undefined function ~ts">>,
- [mfa_to_string(M, F, n_args(A), Enc)]);
-explain_reason({shell_undef,F,A,_}, error, [], _PF, _S, Enc) ->
- %% Give nicer reports for undefined shell functions
- %% (but not when the user actively calls shell_default:F(...)).
- FS = to_string(F, Enc),
- io_lib:fwrite(<<"undefined shell command ~ts/~w">>, [FS, n_args(A)]);
-%% Exit codes returned by erl_eval only:
-explain_reason({argument_limit,_Fun}, error, [], _PF, _S, _Enc) ->
- io_lib:fwrite(<<"limit of number of arguments to interpreted function"
- " exceeded">>, []);
-explain_reason({bad_filter,V}, error=Cl, [], PF, S, _Enc) ->
- format_value(V, <<"bad filter ">>, Cl, PF, S);
-explain_reason({bad_generator,V}, error=Cl, [], PF, S, _Enc) ->
- format_value(V, <<"bad generator ">>, Cl, PF, S);
-explain_reason({unbound,V}, error, [], _PF, _S, _Enc) ->
- io_lib:fwrite(<<"variable ~w is unbound">>, [V]);
-%% Exit codes local to the shell module (restricted shell):
-explain_reason({restricted_shell_bad_return, V}, exit=Cl, [], PF, S, _Enc) ->
- Str = <<"restricted shell module returned bad value ">>,
- format_value(V, Str, Cl, PF, S);
-explain_reason({restricted_shell_disallowed,{ForMF,As}},
- exit=Cl, [], PF, S, Enc) ->
- %% ForMF can be a fun, but not a shell fun.
- Str = <<"restricted shell does not allow ">>,
- format_errstr_call(Str, Cl, ForMF, As, PF, S, Enc);
-explain_reason(restricted_shell_started, exit, [], _PF, _S, _Enc) ->
- <<"restricted shell starts now">>;
-explain_reason(restricted_shell_stopped, exit, [], _PF, _S, _Enc) ->
- <<"restricted shell stopped">>;
-%% Other exit code:
-explain_reason(Reason, Class, [], PF, S, _Enc) ->
- PF(Reason, (iolist_size(S)+1) + exited_size(Class)).
-
-n_args(A) when is_integer(A) ->
- A;
-n_args(As) when is_list(As) ->
- length(As).
-
-argss(0) ->
- <<"no arguments">>;
-argss(1) ->
- <<"one argument">>;
-argss(2) ->
- <<"two arguments">>;
-argss(I) ->
- io_lib:fwrite(<<"~w arguments">>, [I]).
-
-format_stacktrace1(S0, Stack0, PF, SF, Enc) ->
- Stack1 = lists:dropwhile(fun({M,F,A,_}) -> SF(M, F, A)
- end, lists:reverse(Stack0)),
- S = [" " | S0],
- Stack = lists:reverse(Stack1),
- format_stacktrace2(S, Stack, 1, PF, Enc).
-
-format_stacktrace2(S, [{M,F,A,L}|Fs], N, PF, Enc) when is_integer(A) ->
- [io_lib:fwrite(<<"~s~s ~ts ~s">>,
- [sep(N, S), origin(N, M, F, A),
- mfa_to_string(M, F, A, Enc),
- location(L)])
- | format_stacktrace2(S, Fs, N + 1, PF, Enc)];
-format_stacktrace2(S, [{M,F,As,_}|Fs], N, PF, Enc) when is_list(As) ->
- A = length(As),
- CalledAs = [S,<<" called as ">>],
- C = format_call("", CalledAs, {M,F}, As, PF, Enc),
- [io_lib:fwrite(<<"~s~s ~ts\n~s~ts">>,
- [sep(N, S), origin(N, M, F, A),
- mfa_to_string(M, F, A, Enc),
- CalledAs, C])
- | format_stacktrace2(S, Fs, N + 1, PF, Enc)];
-format_stacktrace2(_S, [], _N, _PF, _Enc) ->
- "".
-
-location(L) ->
- File = proplists:get_value(file, L),
- Line = proplists:get_value(line, L),
- if
- File =/= undefined, Line =/= undefined ->
- io_lib:format("(~s, line ~w)", [File, Line]);
- true ->
- ""
- end.
-
-sep(1, S) -> S;
-sep(_, S) -> [$\n | S].
-
-origin(1, M, F, A) ->
- case is_op({M, F}, n_args(A)) of
- {yes, F} -> <<"in operator ">>;
- no -> <<"in function ">>
- end;
-origin(_N, _M, _F, _A) ->
- <<"in call from">>.
-
-format_errstr_call(ErrStr, Class, ForMForFun, As, PF, Pre0, Enc) ->
- Pre1 = [Pre0 | n_spaces(exited_size(Class))],
- format_call(ErrStr, Pre1, ForMForFun, As, PF, Enc).
-
-format_call(ErrStr, Pre1, ForMForFun, As, PF, Enc) ->
- Arity = length(As),
- [ErrStr |
- case is_op(ForMForFun, Arity) of
- {yes,Op} ->
- format_op(ErrStr, Pre1, Op, As, PF, Enc);
- no ->
- MFs = mf_to_string(ForMForFun, Arity, Enc),
- I1 = string:length([Pre1,ErrStr|MFs]),
- S1 = pp_arguments(PF, As, I1, Enc),
- S2 = pp_arguments(PF, As, string:length([Pre1|MFs]), Enc),
- Long = count_nl(pp_arguments(PF, [a2345,b2345], I1, Enc)) > 0,
- case Long or (count_nl(S2) < count_nl(S1)) of
- true ->
- [$\n, Pre1, MFs, S2];
- false ->
- [MFs, S1]
- end
- end].
-
-format_op(ErrStr, Pre, Op, [A1], PF, _Enc) ->
- OpS = io_lib:fwrite(<<"~s ">>, [Op]),
- I1 = iolist_size([ErrStr,Pre,OpS]),
- [OpS | PF(A1, I1+1)];
-format_op(ErrStr, Pre, Op, [A1, A2], PF, Enc) ->
- I1 = iolist_size([ErrStr,Pre]),
- S1 = PF(A1, I1+1),
- S2 = PF(A2, I1+1),
- OpS = atom_to_list(Op),
- Pre1 = [$\n | n_spaces(I1)],
- case count_nl(S1) > 0 of
- true ->
- [S1,Pre1,OpS,Pre1|S2];
- false ->
- OpS2 = io_lib:fwrite(<<" ~s ">>, [Op]),
- Size1 = iolist_size([ErrStr,Pre|OpS2]),
- {Size2,S1_2} = size(Enc, S1),
- S2_2 = PF(A2, Size1+Size2+1),
- case count_nl(S2) < count_nl(S2_2) of
- true ->
- [S1_2,Pre1,OpS,Pre1|S2];
- false ->
- [S1_2,OpS2|S2_2]
- end
- end.
-
-pp_arguments(PF, As, I, Enc) ->
- case {As, printable_list(Enc, As)} of
- {[Int | T], true} ->
- L = integer_to_list(Int),
- Ll = length(L),
- A = list_to_atom(lists:duplicate(Ll, $a)),
- S0 = unicode:characters_to_list(PF([A | T], I+1), Enc),
- brackets_to_parens([$[,L,string:sub_string(S0, 2+Ll)], Enc);
- _ ->
- brackets_to_parens(PF(As, I+1), Enc)
- end.
-
-brackets_to_parens(S, Enc) ->
- B = unicode:characters_to_binary(S, Enc),
- Sz = byte_size(B) - 2,
- <<$[,R:Sz/binary,$]>> = B,
- [$(,R,$)].
-
-printable_list(latin1, As) ->
- io_lib:printable_latin1_list(As);
-printable_list(_, As) ->
- io_lib:printable_list(As).
-
-mfa_to_string(M, F, A, Enc) ->
- io_lib:fwrite(<<"~ts/~w">>, [mf_to_string({M, F}, A, Enc), A]).
-
-mf_to_string({M, F}, A, Enc) ->
- case erl_internal:bif(M, F, A) of
- true ->
- io_lib:fwrite(<<"~w">>, [F]);
- false ->
- case is_op({M, F}, A) of
- {yes, '/'} ->
- io_lib:fwrite(<<"~w">>, [F]);
- {yes, F} ->
- atom_to_list(F);
- no ->
- FS = to_string(F, Enc),
- io_lib:fwrite(<<"~w:~ts">>, [M, FS])
- end
- end;
-mf_to_string(Fun, _A, Enc) when is_function(Fun) ->
- format_fun(Fun, Enc);
-mf_to_string(F, _A, Enc) ->
- FS = to_string(F, Enc),
- io_lib:fwrite(<<"~ts">>, [FS]).
-
-format_value(V, ErrStr, Class, PF, S) ->
- Pre1Sz = exited_size(Class),
- S1 = PF(V, Pre1Sz + iolist_size([S, ErrStr])+1),
- [ErrStr | case count_nl(S1) of
- N1 when N1 > 1 ->
- S2 = PF(V, iolist_size(S) + 1 + Pre1Sz),
- case count_nl(S2) < N1 of
- true ->
- [$\n, S, n_spaces(Pre1Sz) | S2];
- false ->
- S1
- end;
- _ ->
- S1
- end].
-
-%% Handles deep lists, but not all iolists.
-count_nl([E | Es]) ->
- count_nl(E) + count_nl(Es);
-count_nl($\n) ->
- 1;
-count_nl(Bin) when is_binary(Bin) ->
- count_nl(binary_to_list(Bin));
-count_nl(_) ->
- 0.
-
-n_spaces(N) ->
- lists:duplicate(N, $\s).
-
-is_op(ForMForFun, A) ->
- try
- {erlang,F} = ForMForFun,
- _ = erl_internal:op_type(F, A),
- {yes,F}
- catch error:_ -> no
- end.
-
-exited_size(Class) ->
- iolist_size(exited(Class)).
-
-exited(error) ->
- <<"exception error: ">>;
-exited(exit) ->
- <<"exception exit: ">>;
-exited(throw) ->
- <<"exception throw: ">>.
-
-to_string(A, latin1) ->
- io_lib:write_atom_as_latin1(A);
-to_string(A, _) ->
- io_lib:write_atom(A).
-
-size(latin1, S) ->
- {iolist_size(S),S};
-size(_, S0) ->
- S = unicode:characters_to_list(S0, unicode),
- true = is_list(S),
- {string:length(S),S}.
diff --git a/lib/stdlib/src/lists.erl b/lib/stdlib/src/lists.erl
index af9d63ddd6..06c90c0280 100644
--- a/lib/stdlib/src/lists.erl
+++ b/lib/stdlib/src/lists.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -38,8 +38,8 @@
-export([all/2,any/2,map/2,flatmap/2,foldl/3,foldr/3,filter/2,
partition/2,zf/2,filtermap/2,
- mapfoldl/3,mapfoldr/3,foreach/2,takewhile/2,dropwhile/2,splitwith/2,
- split/2,
+ mapfoldl/3,mapfoldr/3,foreach/2,takewhile/2,dropwhile/2,
+ search/2, splitwith/2,split/2,
join/2]).
%%% BIFs
@@ -1399,6 +1399,19 @@ dropwhile(Pred, [Hd|Tail]=Rest) ->
end;
dropwhile(Pred, []) when is_function(Pred, 1) -> [].
+-spec search(Pred, List) -> {value, Value} | false when
+ Pred :: fun((T) -> boolean()),
+ List :: [T],
+ Value :: T.
+
+search(Pred, [Hd|Tail]) ->
+ case Pred(Hd) of
+ true -> {value, Hd};
+ false -> search(Pred, Tail)
+ end;
+search(Pred, []) when is_function(Pred, 1) ->
+ false.
+
-spec splitwith(Pred, List) -> {List1, List2} when
Pred :: fun((T) -> boolean()),
List :: [T],
diff --git a/lib/stdlib/src/maps.erl b/lib/stdlib/src/maps.erl
index 5dafdb282a..60463feec2 100644
--- a/lib/stdlib/src/maps.erl
+++ b/lib/stdlib/src/maps.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,7 +23,8 @@
-export([get/3, filter/2,fold/3,
map/2, size/1,
update_with/3, update_with/4,
- without/2, with/2]).
+ without/2, with/2,
+ iterator/1, next/1]).
%% BIFs
-export([get/2, find/2, from_list/1,
@@ -31,6 +32,15 @@
new/0, put/3, remove/2, take/2,
to_list/1, update/3, values/1]).
+-opaque iterator() :: {term(), term(), iterator()}
+ | none | nonempty_improper_list(integer(),map()).
+
+-export_type([iterator/0]).
+
+-dialyzer({no_improper_lists, iterator/1}).
+
+-define(IS_ITERATOR(I), is_tuple(I) andalso tuple_size(I) == 3; I == none; is_integer(hd(I)) andalso is_map(tl(I))).
+
%% Shadowed by erl_bif_types: maps:get/2
-spec get(Key,Map) -> Value when
Key :: term(),
@@ -39,7 +49,6 @@
get(_,_) -> erlang:nif_error(undef).
-
-spec find(Key,Map) -> {ok, Value} | error when
Key :: term(),
Map :: map(),
@@ -114,14 +123,20 @@ remove(_,_) -> erlang:nif_error(undef).
take(_,_) -> erlang:nif_error(undef).
-%% Shadowed by erl_bif_types: maps:to_list/1
-spec to_list(Map) -> [{Key,Value}] when
Map :: map(),
Key :: term(),
Value :: term().
-to_list(_) -> erlang:nif_error(undef).
+to_list(Map) when is_map(Map) ->
+ to_list_internal(erts_internal:map_next(0, Map, []));
+to_list(Map) ->
+ erlang:error({badmap,Map},[Map]).
+to_list_internal([Iter, Map | Acc]) when is_integer(Iter) ->
+ to_list_internal(erts_internal:map_next(Iter, Map, Acc));
+to_list_internal(Acc) ->
+ Acc.
%% Shadowed by erl_bif_types: maps:update/3
-spec update(Key,Value,Map1) -> Map2 when
@@ -192,47 +207,80 @@ get(Key,Map,Default) ->
erlang:error({badmap,Map},[Key,Map,Default]).
--spec filter(Pred,Map1) -> Map2 when
+-spec filter(Pred,MapOrIter) -> Map when
Pred :: fun((Key, Value) -> boolean()),
Key :: term(),
Value :: term(),
- Map1 :: map(),
- Map2 :: map().
+ MapOrIter :: map() | iterator(),
+ Map :: map().
filter(Pred,Map) when is_function(Pred,2), is_map(Map) ->
- maps:from_list([{K,V}||{K,V}<-maps:to_list(Map),Pred(K,V)]);
+ maps:from_list(filter_1(Pred, iterator(Map)));
+filter(Pred,Iterator) when is_function(Pred,2), ?IS_ITERATOR(Iterator) ->
+ maps:from_list(filter_1(Pred, Iterator));
filter(Pred,Map) ->
erlang:error(error_type(Map),[Pred,Map]).
-
--spec fold(Fun,Init,Map) -> Acc when
+filter_1(Pred, Iter) ->
+ case next(Iter) of
+ {K, V, NextIter} ->
+ case Pred(K,V) of
+ true ->
+ [{K,V} | filter_1(Pred, NextIter)];
+ false ->
+ filter_1(Pred, NextIter)
+ end;
+ none ->
+ []
+ end.
+
+-spec fold(Fun,Init,MapOrIter) -> Acc when
Fun :: fun((K, V, AccIn) -> AccOut),
Init :: term(),
Acc :: term(),
AccIn :: term(),
AccOut :: term(),
- Map :: map(),
+ MapOrIter :: map() | iterator(),
K :: term(),
V :: term().
fold(Fun,Init,Map) when is_function(Fun,3), is_map(Map) ->
- lists:foldl(fun({K,V},A) -> Fun(K,V,A) end,Init,maps:to_list(Map));
+ fold_1(Fun,Init,iterator(Map));
+fold(Fun,Init,Iterator) when is_function(Fun,3), ?IS_ITERATOR(Iterator) ->
+ fold_1(Fun,Init,Iterator);
fold(Fun,Init,Map) ->
- erlang:error(error_type(Map),[Fun,Init,Map]).
+ erlang:error(error_type_iter(Map),[Fun,Init,Map]).
+
+fold_1(Fun, Acc, Iter) ->
+ case next(Iter) of
+ {K, V, NextIter} ->
+ fold_1(Fun, Fun(K,V,Acc), NextIter);
+ none ->
+ Acc
+ end.
--spec map(Fun,Map1) -> Map2 when
+-spec map(Fun,MapOrIter) -> Map when
Fun :: fun((K, V1) -> V2),
- Map1 :: map(),
- Map2 :: map(),
+ MapOrIter :: map() | iterator(),
+ Map :: map(),
K :: term(),
V1 :: term(),
V2 :: term().
map(Fun,Map) when is_function(Fun, 2), is_map(Map) ->
- maps:from_list([{K,Fun(K,V)}||{K,V}<-maps:to_list(Map)]);
+ maps:from_list(map_1(Fun, iterator(Map)));
+map(Fun,Iterator) when is_function(Fun, 2), ?IS_ITERATOR(Iterator) ->
+ maps:from_list(map_1(Fun, Iterator));
map(Fun,Map) ->
- erlang:error(error_type(Map),[Fun,Map]).
+ erlang:error(error_type_iter(Map),[Fun,Map]).
+map_1(Fun, Iter) ->
+ case next(Iter) of
+ {K, V, NextIter} ->
+ [{K, Fun(K, V)} | map_1(Fun, NextIter)];
+ none ->
+ []
+ end.
-spec size(Map) -> non_neg_integer() when
Map :: map().
@@ -242,6 +290,26 @@ size(Map) when is_map(Map) ->
size(Val) ->
erlang:error({badmap,Val},[Val]).
+-spec iterator(Map) -> Iterator when
+ Map :: map(),
+ Iterator :: iterator().
+
+iterator(M) when is_map(M) -> [0 | M];
+iterator(M) -> erlang:error({badmap, M}, [M]).
+
+-spec next(Iterator) -> {Key, Value, NextIterator} | 'none' when
+ Iterator :: iterator(),
+ Key :: term(),
+ Value :: term(),
+ NextIterator :: iterator().
+next({K, V, I}) ->
+ {K, V, I};
+next([Path | Map]) when is_integer(Path), is_map(Map) ->
+ erts_internal:map_next(Path, Map, iterator);
+next(none) ->
+ none;
+next(Iter) ->
+ erlang:error(badarg, [Iter]).
-spec without(Ks,Map1) -> Map2 when
Ks :: [K],
@@ -250,11 +318,10 @@ size(Val) ->
K :: term().
without(Ks,M) when is_list(Ks), is_map(M) ->
- lists:foldl(fun(K, M1) -> ?MODULE:remove(K, M1) end, M, Ks);
+ lists:foldl(fun(K, M1) -> maps:remove(K, M1) end, M, Ks);
without(Ks,M) ->
erlang:error(error_type(M),[Ks,M]).
-
-spec with(Ks, Map1) -> Map2 when
Ks :: [K],
Map1 :: map(),
@@ -263,17 +330,20 @@ without(Ks,M) ->
with(Ks,Map1) when is_list(Ks), is_map(Map1) ->
Fun = fun(K, List) ->
- case ?MODULE:find(K, Map1) of
- {ok, V} ->
- [{K, V} | List];
- error ->
- List
- end
- end,
- ?MODULE:from_list(lists:foldl(Fun, [], Ks));
+ case maps:find(K, Map1) of
+ {ok, V} ->
+ [{K, V} | List];
+ error ->
+ List
+ end
+ end,
+ maps:from_list(lists:foldl(Fun, [], Ks));
with(Ks,M) ->
erlang:error(error_type(M),[Ks,M]).
error_type(M) when is_map(M) -> badarg;
error_type(V) -> {badmap, V}.
+
+error_type_iter(M) when is_map(M); ?IS_ITERATOR(M) -> badarg;
+error_type_iter(V) -> {badmap, V}.
diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl
index 6616e957c0..6d243e1bec 100644
--- a/lib/stdlib/src/ms_transform.erl
+++ b/lib/stdlib/src/ms_transform.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -224,10 +224,12 @@ transform_from_shell(Dialect, Clauses, BoundEnvironment) ->
%% Called when translating during compiling
%%
--spec parse_transform(Forms, Options) -> Forms2 when
+-spec parse_transform(Forms, Options) -> Forms2 | Errors | Warnings when
Forms :: [erl_parse:abstract_form() | erl_parse:form_info()],
Forms2 :: [erl_parse:abstract_form() | erl_parse:form_info()],
- Options :: term().
+ Options :: term(),
+ Errors :: {error, ErrInfo :: [tuple()], WarnInfo :: []},
+ Warnings :: {warning, Forms2, WarnInfo :: [tuple()]}.
parse_transform(Forms, _Options) ->
SaveFilename = setup_filename(),
@@ -929,6 +931,7 @@ bool_test(is_port,1) -> true;
bool_test(is_reference,1) -> true;
bool_test(is_tuple,1) -> true;
bool_test(is_map,1) -> true;
+bool_test(is_map_key, 2) -> true;
bool_test(is_binary,1) -> true;
bool_test(is_function,1) -> true;
bool_test(is_record,2) -> true;
@@ -943,7 +946,9 @@ real_guard_function(node,0) -> true;
real_guard_function(node,1) -> true;
real_guard_function(round,1) -> true;
real_guard_function(size,1) -> true;
+real_guard_function(bit_size,1) -> true;
real_guard_function(map_size,1) -> true;
+real_guard_function(map_get,2) -> true;
real_guard_function(tl,1) -> true;
real_guard_function(trunc,1) -> true;
real_guard_function(self,0) -> true;
@@ -1115,5 +1120,3 @@ normalise_list([H|T]) ->
[normalise(H)|normalise_list(T)];
normalise_list([]) ->
[].
-
-
diff --git a/lib/stdlib/src/ordsets.erl b/lib/stdlib/src/ordsets.erl
index 569407f5ef..176047079b 100644
--- a/lib/stdlib/src/ordsets.erl
+++ b/lib/stdlib/src/ordsets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@
-module(ordsets).
--export([new/0,is_set/1,size/1,to_list/1,from_list/1]).
+-export([new/0,is_set/1,size/1,is_empty/1,to_list/1,from_list/1]).
-export([is_element/2,add_element/2,del_element/2]).
-export([union/2,union/1,intersection/2,intersection/1]).
-export([is_disjoint/2]).
@@ -60,6 +60,13 @@ is_set([], _) -> true.
size(S) -> length(S).
+%% is_empty(OrdSet) -> boolean().
+%% Return 'true' if OrdSet is an empty set, otherwise 'false'.
+-spec is_empty(Ordset) -> boolean() when
+ Ordset :: ordset(_).
+
+is_empty(S) -> S=:=[].
+
%% to_list(OrdSet) -> [Elem].
%% Return the elements in OrdSet as a list.
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index 9e9c0dc413..aaed13ba3a 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -63,9 +63,9 @@ obsolete_1(gen_fsm, start, 4) ->
{deprecated, {gen_statem, start, 4}};
obsolete_1(gen_fsm, start_link, 3) ->
- {deprecated, {gen_statem, start, 3}};
+ {deprecated, {gen_statem, start_link, 3}};
obsolete_1(gen_fsm, start_link, 4) ->
- {deprecated, {gen_statem, start, 4}};
+ {deprecated, {gen_statem, start_link, 4}};
obsolete_1(gen_fsm, stop, 1) ->
{deprecated, {gen_statem, stop, 1}};
@@ -83,9 +83,9 @@ obsolete_1(gen_fsm, reply, 2) ->
{deprecated, {gen_statem, reply, 2}};
obsolete_1(gen_fsm, send_event, 2) ->
- {deprecated, {gen_statem, cast, 1}};
+ {deprecated, {gen_statem, cast, 2}};
obsolete_1(gen_fsm, send_all_state_event, 2) ->
- {deprecated, {gen_statem, cast, 1}};
+ {deprecated, {gen_statem, cast, 2}};
obsolete_1(gen_fsm, sync_send_event, 2) ->
{deprecated, {gen_statem, call, 2}};
@@ -98,11 +98,11 @@ obsolete_1(gen_fsm, sync_send_all_state_event, 3) ->
{deprecated, {gen_statem, call, 3}};
obsolete_1(gen_fsm, start_timer, 2) ->
- {deprecated, {erlang, start_timer, 2}};
+ {deprecated, {erlang, start_timer, 3}};
obsolete_1(gen_fsm, cancel_timer, 1) ->
{deprecated, {erlang, cancel_timer, 1}};
obsolete_1(gen_fsm, send_event_after, 2) ->
- {deprecated, {erlang, send_after, 2}};
+ {deprecated, {erlang, send_after, 3}};
%% *** CRYPTO added in OTP 20 ***
@@ -112,7 +112,7 @@ obsolete_1(crypto, rand_uniform, 2) ->
%% *** CRYPTO added in OTP 19 ***
obsolete_1(crypto, rand_bytes, 1) ->
- {deprecated, {crypto, strong_rand_bytes, 1}};
+ {removed, {crypto, strong_rand_bytes, 1}, "20.0"};
%% *** CRYPTO added in R16B01 ***
@@ -466,8 +466,6 @@ obsolete_1(inviso, _, _) ->
{removed,"the inviso application was removed in R16"};
%% Added in R15B01.
-obsolete_1(gs, _, _) ->
- {removed,"the gs application has been removed; use the wx application instead"};
obsolete_1(ssh, sign_data, 2) ->
{removed,"removed in R16A; use public_key:pem_decode/1, public_key:pem_entry_decode/1 "
"and public_key:sign/3 instead"};
@@ -485,10 +483,6 @@ obsolete_1(wxPaintDC, new, 0) ->
{deprecated,"deprecated function not available in wxWidgets-2.9 and later"};
obsolete_1(wxWindowDC, new, 0) ->
{deprecated,"deprecated function not available in wxWidgets-2.9 and later"};
-obsolete_1(wxGraphicsContext, createLinearGradientBrush, 7) ->
- {deprecated,"deprecated function not available in wxWidgets-2.9 and later"};
-obsolete_1(wxGraphicsContext, createRadialGradientBrush, 8) ->
- {deprecated,"deprecated function not available in wxWidgets-2.9 and later"};
obsolete_1(wxGraphicsRenderer, createLinearGradientBrush, 7) ->
{deprecated,"deprecated function not available in wxWidgets-2.9 and later"};
obsolete_1(wxGraphicsRenderer, createRadialGradientBrush, 8) ->
@@ -610,11 +604,25 @@ obsolete_1(filename, find_src, 1) ->
obsolete_1(filename, find_src, 2) ->
{deprecated, "deprecated; use filelib:find_source/3 instead"};
+obsolete_1(erlang, get_stacktrace, 0) ->
+ {deprecated, "deprecated; use the new try/catch syntax for retrieving the stack backtrace"};
+
%% Removed in OTP 20.
obsolete_1(erlang, hash, 2) ->
{removed, {erlang, phash2, 2}, "20.0"};
+%% Add in OTP 21.
+
+obsolete_1(ssl, ssl_accept, 1) ->
+ {deprecated, "deprecated; use ssl:handshake/1 instead"};
+obsolete_1(ssl, ssl_accept, 2) ->
+ {deprecated, "deprecated; use ssl:handshake/2 instead"};
+obsolete_1(ssl, ssl_accept, 3) ->
+ {deprecated, "deprecated; use ssl:handshake/3 instead"};
+obsolete_1(otp_mib, F, _) when F =:= load; F =:= unload ->
+ {deprecated, "deprecated; functionality will be removed in a future release"};
+
%% not obsolete
obsolete_1(_, _, _) ->
diff --git a/lib/stdlib/src/pool.erl b/lib/stdlib/src/pool.erl
index 05950a1d7c..599be55607 100644
--- a/lib/stdlib/src/pool.erl
+++ b/lib/stdlib/src/pool.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
%% with the least load !!!!
%% This function is callable from any node including the master
%% That is part of the pool
-%% nodes are scheduled on a per usgae basis and per load basis,
+%% nodes are scheduled on a per usage basis and per load basis,
%% Whenever we use a node, we put at the end of the queue, and whenever
%% a node report a change in load, we insert it accordingly
@@ -197,7 +197,7 @@ pure_insert({Load,Node},[{L,N}|Tail]) when Load < L ->
pure_insert(L,[H|T]) -> [H|pure_insert(L,T)].
%% Really should not measure the contributions from
-%% the back ground processes here .... which we do :-(
+%% the background processes here .... which we do :-(
%% We don't have to monitor the master, since we're slaves anyway
statistic_collector() ->
@@ -213,7 +213,7 @@ statistic_collector(I) ->
stat_loop(M, 999999)
end.
-%% Do not tell the master about our load if it has not changed
+%% Do not tell the master about our load if it has not changed
stat_loop(M, Old) ->
sleep(2000),
diff --git a/lib/stdlib/src/proc_lib.erl b/lib/stdlib/src/proc_lib.erl
index 9ce8e7d60e..cfbaf8b242 100644
--- a/lib/stdlib/src/proc_lib.erl
+++ b/lib/stdlib/src/proc_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@
start/3, start/4, start/5, start_link/3, start_link/4, start_link/5,
hibernate/3,
init_ack/1, init_ack/2,
- init_p/3,init_p/5,format/1,format/2,format/3,
+ init_p/3,init_p/5,format/1,format/2,format/3,report_cb/2,
initial_call/1,
translate_initial_call/1,
stop/1, stop/3]).
@@ -40,6 +40,8 @@
-export_type([spawn_option/0]).
+-include("logger.hrl").
+
%%-----------------------------------------------------------------------------
-type priority_level() :: 'high' | 'low' | 'max' | 'normal'.
@@ -231,8 +233,8 @@ init_p(Parent, Ancestors, Fun) when is_function(Fun) ->
try
Fun()
catch
- Class:Reason ->
- exit_p(Class, Reason, erlang:get_stacktrace())
+ Class:Reason:Stacktrace ->
+ exit_p(Class, Reason, Stacktrace)
end.
-spec init_p(pid(), [pid()], atom(), atom(), [term()]) -> term().
@@ -246,8 +248,8 @@ init_p_do_apply(M, F, A) ->
try
apply(M, F, A)
catch
- Class:Reason ->
- exit_p(Class, Reason, erlang:get_stacktrace())
+ Class:Reason:Stacktrace ->
+ exit_p(Class, Reason, Stacktrace)
end.
-spec wake_up(atom(), atom(), [term()]) -> term().
@@ -256,8 +258,8 @@ wake_up(M, F, A) when is_atom(M), is_atom(F), is_list(A) ->
try
apply(M, F, A)
catch
- Class:Reason ->
- exit_p(Class, Reason, erlang:get_stacktrace())
+ Class:Reason:Stacktrace ->
+ exit_p(Class, Reason, Stacktrace)
end.
exit_p(Class, Reason, Stacktrace) ->
@@ -503,10 +505,13 @@ crash_report(exit, normal, _, _) -> ok;
crash_report(exit, shutdown, _, _) -> ok;
crash_report(exit, {shutdown,_}, _, _) -> ok;
crash_report(Class, Reason, StartF, Stacktrace) ->
- OwnReport = my_info(Class, Reason, StartF, Stacktrace),
- LinkReport = linked_info(self()),
- Rep = [OwnReport,LinkReport],
- error_logger:error_report(crash_report, Rep).
+ ?LOG_ERROR(#{label=>{proc_lib,crash},
+ report=>[my_info(Class, Reason, StartF, Stacktrace),
+ linked_info(self())]},
+ #{domain=>[otp,sasl],
+ report_cb=>fun proc_lib:report_cb/2,
+ logger_formatter=>#{title=>"CRASH REPORT"},
+ error_logger=>#{tag=>error_report,type=>crash_report}}).
my_info(Class, Reason, [], Stacktrace) ->
my_info_1(Class, Reason, Stacktrace);
@@ -742,9 +747,20 @@ check({badrpc,Error}) -> Error;
check(Res) -> Res.
%%% -----------------------------------------------------------
-%%% Format (and write) a generated crash info structure.
+%%% Format a generated crash info structure.
%%% -----------------------------------------------------------
+-spec report_cb(CrashReport,FormatOpts) -> unicode:chardata() when
+ CrashReport :: #{label => {proc_lib,crash},
+ report => [term()]},
+ FormatOpts :: logger:report_cb_config().
+report_cb(#{label:={proc_lib,crash}, report:=CrashReport}, Extra) ->
+ Default = #{chars_limit => unlimited,
+ depth => unlimited,
+ single_line => false,
+ encoding => utf8},
+ do_format(CrashReport, maps:merge(Default,Extra)).
+
-spec format(CrashReport) -> string() when
CrashReport :: [term()].
format(CrashReport) ->
@@ -762,30 +778,51 @@ format(CrashReport, Encoding) ->
Encoding :: latin1 | unicode | utf8,
Depth :: unlimited | pos_integer().
-format([OwnReport,LinkReport], Encoding, Depth) ->
- Extra = {Encoding,Depth},
- MyIndent = " ",
+format(CrashReport, Encoding, Depth) ->
+ do_format(CrashReport, #{chars_limit => unlimited,
+ depth => Depth,
+ encoding => Encoding,
+ single_line => false}).
+
+do_format([OwnReport,LinkReport], #{single_line:=Single}=Extra) ->
+ Indent = if Single -> "";
+ true -> " "
+ end,
+ MyIndent = Indent ++ Indent,
+ Sep = nl(Single,"; "),
OwnFormat = format_report(OwnReport, MyIndent, Extra),
- LinkFormat = format_link_report(LinkReport, MyIndent, Extra),
- Str = io_lib:format(" crasher:~n~ts neighbours:~n~ts",
- [OwnFormat, LinkFormat]),
+ LinkFormat = lists:join(Sep,format_link_report(LinkReport, MyIndent, Extra)),
+ Nl = nl(Single," "),
+ Str = io_lib:format("~scrasher:"++Nl++"~ts"++Sep++"~sneighbours:"++Nl++"~ts",
+ [Indent,OwnFormat,Indent,LinkFormat]),
lists:flatten(Str).
-format_link_report([Link|Reps], Indent, Extra) ->
+format_link_report([Link|Reps], Indent0, #{single_line:=Single}=Extra) ->
Rep = case Link of
{neighbour,Rep0} -> Rep0;
_ -> Link
end,
+ Indent = if Single -> "";
+ true -> Indent0
+ end,
LinkIndent = [" ",Indent],
- [Indent,"neighbour:\n",format_report(Rep, LinkIndent, Extra)|
+ [[Indent,"neighbour:",nl(Single," "),format_report(Rep, LinkIndent, Extra)]|
format_link_report(Reps, Indent, Extra)];
-format_link_report([], _, _) ->
- [].
-
-format_report(Rep, Indent, Extra) when is_list(Rep) ->
- format_rep(Rep, Indent, Extra);
-format_report(Rep, Indent, {Enc,Depth}) ->
- io_lib:format("~s~"++modifier(Enc)++"P~n", [Indent, Rep, Depth]).
+format_link_report(Rep, Indent, Extra) ->
+ format_report(Rep, Indent, Extra).
+
+format_report(Rep, Indent, #{single_line:=Single}=Extra) when is_list(Rep) ->
+ lists:join(nl(Single,", "),format_rep(Rep, Indent, Extra));
+format_report(Rep, Indent0, #{encoding:=Enc,depth:=Depth,
+ chars_limit:=Limit,single_line:=Single}) ->
+ {P,Tl} = p(Enc,Depth),
+ {Indent,Width} = if Single -> {"","0"};
+ true -> {Indent0,""}
+ end,
+ Opts = if is_integer(Limit) -> [{chars_limit,Limit}];
+ true -> []
+ end,
+ io_lib:format("~s~"++Width++P, [Indent, Rep | Tl], Opts).
format_rep([{initial_call,InitialCall}|Rep], Indent, Extra) ->
[format_mfa(Indent, InitialCall, Extra)|format_rep(Rep, Indent, Extra)];
@@ -797,19 +834,32 @@ format_rep([{Tag,Data}|Rep], Indent, Extra) ->
format_rep(_, _, _Extra) ->
[].
-format_exception(Class, Reason, StackTrace, {Enc,_}=Extra) ->
+format_exception(Class, Reason, StackTrace,
+ #{encoding:=Enc,depth:=Depth,chars_limit:=Limit,
+ single_line:=Single}=Extra) ->
PF = pp_fun(Extra),
StackFun = fun(M, _F, _A) -> (M =:= erl_eval) or (M =:= ?MODULE) end,
- %% EI = " exception: ",
- EI = " ",
- [EI, lib:format_exception(1+length(EI), Class, Reason,
- StackTrace, StackFun, PF, Enc), "\n"].
+ if Single ->
+ {P,Tl} = p(Enc,Depth),
+ Opts = if is_integer(Limit) -> [{chars_limit,Limit}];
+ true -> []
+ end,
+ [atom_to_list(Class), ": ",
+ io_lib:format("~0"++P,[{Reason,StackTrace}|Tl],Opts)];
+ true ->
+ EI = " ",
+ [EI, erl_error:format_exception(1+length(EI), Class, Reason,
+ StackTrace, StackFun, PF, Enc)]
+ end.
-format_mfa(Indent, {M,F,Args}=StartF, {Enc,_}=Extra) ->
+format_mfa(Indent0, {M,F,Args}=StartF, #{encoding:=Enc,single_line:=Single}=Extra) ->
+ Indent = if Single -> "";
+ true -> Indent0
+ end,
try
A = length(Args),
[Indent,"initial call: ",atom_to_list(M),$:,to_string(F, Enc),$/,
- integer_to_list(A),"\n"]
+ integer_to_list(A)]
catch
error:_ ->
format_tag(Indent, initial_call, StartF, Extra)
@@ -820,27 +870,43 @@ to_string(A, latin1) ->
to_string(A, _) ->
io_lib:write_atom(A).
-pp_fun({Enc,Depth}) ->
- {Letter,Tl} = case Depth of
- unlimited -> {"p",[]};
- _ -> {"P",[Depth]}
- end,
- P = modifier(Enc) ++ Letter,
+pp_fun(#{encoding:=Enc,depth:=Depth,chars_limit:=Limit,single_line:=Single}) ->
+ {P,Tl} = p(Enc, Depth),
+ Width = if Single -> "0";
+ true -> ""
+ end,
+ Opts = if is_integer(Limit) -> [{chars_limit,Limit}];
+ true -> []
+ end,
fun(Term, I) ->
- io_lib:format("~." ++ integer_to_list(I) ++ P, [Term|Tl])
+ io_lib:format("~" ++ Width ++ "." ++ integer_to_list(I) ++ P,
+ [Term|Tl], Opts)
end.
-format_tag(Indent, Tag, Data, {_Enc,Depth}) ->
- case Depth of
- unlimited ->
- io_lib:format("~s~p: ~80.18p~n", [Indent, Tag, Data]);
- _ ->
- io_lib:format("~s~p: ~80.18P~n", [Indent, Tag, Data, Depth])
- end.
+format_tag(Indent0, Tag, Data, #{encoding:=Enc,depth:=Depth,chars_limit:=Limit,single_line:=Single}) ->
+ {P,Tl} = p(Enc, Depth),
+ {Indent,Width} = if Single -> {"","0"};
+ true -> {Indent0,""}
+ end,
+ Opts = if is_integer(Limit) -> [{chars_limit,Limit}];
+ true -> []
+ end,
+ io_lib:format("~s~" ++ Width ++ "p: ~" ++ Width ++ ".18" ++ P,
+ [Indent, Tag, Data|Tl], Opts).
+
+p(Encoding, Depth) ->
+ {Letter, Tl} = case Depth of
+ unlimited -> {"p", []};
+ _ -> {"P", [Depth]}
+ end,
+ P = modifier(Encoding) ++ Letter,
+ {P, Tl}.
modifier(latin1) -> "";
modifier(_) -> "t".
+nl(true,Else) -> Else;
+nl(false,_) -> "\n".
%%% -----------------------------------------------------------
%%% Stop a process and wait for it to terminate
diff --git a/lib/stdlib/src/qlc.erl b/lib/stdlib/src/qlc.erl
index 535ca57a6b..a1c1117e31 100644
--- a/lib/stdlib/src/qlc.erl
+++ b/lib/stdlib/src/qlc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -301,11 +301,11 @@ eval(QH, Options) ->
post_funs(Post)
end
end
- catch Term ->
- case erlang:get_stacktrace() of
+ catch throw:Term:Stacktrace ->
+ case Stacktrace of
[?THROWN_ERROR | _] ->
Term;
- Stacktrace ->
+ _ ->
erlang:raise(throw, Term, Stacktrace)
end
end
@@ -359,11 +359,11 @@ fold(Fun, Acc0, QH, Options) ->
post_funs(Post)
end
end
- catch Term ->
- case erlang:get_stacktrace() of
+ catch throw:Term:Stacktrace ->
+ case Stacktrace of
[?THROWN_ERROR | _] ->
Term;
- Stacktrace ->
+ _ ->
erlang:raise(throw, Term, Stacktrace)
end
end
@@ -457,11 +457,11 @@ info(QH, Options) ->
debug -> % Not documented. Intended for testing only.
Info
end
- catch Term ->
- case erlang:get_stacktrace() of
+ catch throw:Term:Stacktrace ->
+ case Stacktrace of
[?THROWN_ERROR | _] ->
Term;
- Stacktrace ->
+ _ ->
erlang:raise(throw, Term, Stacktrace)
end
end
@@ -638,7 +638,7 @@ string_to_handle(Str, Options, Bindings) when is_list(Str) ->
case erl_scan:string(Str, 1, [text]) of
{ok, Tokens, _} ->
ScanRes =
- case lib:extended_parse_exprs(Tokens) of
+ case erl_eval:extended_parse_exprs(Tokens) of
{ok, [Expr0], SBs} ->
{ok, Expr0, SBs};
{ok, _ExprList, _SBs} ->
@@ -1056,9 +1056,9 @@ cursor_process(H, GUnique, GCache, TmpDir, SpawnOptions, MaxList, TmpUsage) ->
Prep = prepare_qlc(H, not_a_list, GUnique, GCache,
TmpDir, MaxList, TmpUsage),
setup_qlc(Prep, Setup)
- catch Class:Reason ->
- Parent ! {self(), {caught, Class, Reason,
- erlang:get_stacktrace()}},
+ catch Class:Reason:Stacktrace ->
+ Parent ! {self(),
+ {caught, Class, Reason, Stacktrace}},
exit(normal)
end,
Parent ! {self(), ok},
@@ -1075,8 +1075,8 @@ parent_fun(Pid, Parent) ->
{TPid, {parent_fun, Fun}} ->
V = try
{value, Fun()}
- catch Class:Reason ->
- {parent_fun_caught, Class, Reason, erlang:get_stacktrace()}
+ catch Class:Reason:Stacktrace ->
+ {parent_fun_caught, Class, Reason, Stacktrace}
end,
TPid ! {Parent, V},
parent_fun(Pid, Parent);
@@ -1101,9 +1101,9 @@ reply(Parent, MonRef, Post, Cont) ->
throw_error(Cont)
end
catch
- Class:Reason ->
+ Class:Reason:Stacktrace ->
post_funs(Post),
- Message = {caught, Class, Reason, erlang:get_stacktrace()},
+ Message = {caught, Class, Reason, Stacktrace},
Parent ! {self(), Message},
exit(normal)
end,
@@ -1132,7 +1132,7 @@ wait_for_request(Parent, MonRef, Post) ->
wait_for_request(Parent, MonRef, Post);
Other ->
error_logger:error_msg(
- "The qlc cursor ~w received an unexpected message:\n~p\n",
+ "The qlc cursor ~w received an unexpected message:\n~tp\n",
[self(), Other]),
wait_for_request(Parent, MonRef, Post)
end.
@@ -1196,8 +1196,8 @@ abstract1({table, TableDesc}, _NElements, _Depth, _A) ->
{ok, Tokens, _} =
erl_scan:string(lists:flatten(TableDesc++"."), 1, [text]),
{ok, Es, Bs} =
- lib:extended_parse_exprs(Tokens),
- [Expr] = lib:subst_values_for_vars(Es, Bs),
+ erl_eval:extended_parse_exprs(Tokens),
+ [Expr] = erl_eval:subst_values_for_vars(Es, Bs),
special(Expr);
false -> % abstract expression
TableDesc
@@ -1392,9 +1392,8 @@ next_loop(Pid, L, N) when N =/= 0 ->
{caught, throw, Error, [?THROWN_ERROR | _]} ->
Error;
{caught, Class, Reason, Stacktrace} ->
- CurrentStacktrace = try erlang:error(foo)
- catch error:_ -> erlang:get_stacktrace()
- end,
+ {current_stacktrace, CurrentStacktrace} =
+ erlang:process_info(self(), current_stacktrace),
erlang:raise(Class, Reason, Stacktrace ++ CurrentStacktrace);
error ->
erlang:error({qlc_cursor_pid_no_longer_exists, Pid})
@@ -2627,9 +2626,9 @@ table_handle(#qlc_table{trav_fun = TraverseFun, trav_MS = TravMS,
Parent =:= self() ->
try
ParentFun()
- catch Class:Reason ->
+ catch Class:Reason:Stacktrace ->
post_funs(Post),
- erlang:raise(Class, Reason, erlang:get_stacktrace())
+ erlang:raise(Class, Reason, Stacktrace)
end;
true ->
case monitor_request(Parent, {parent_fun, ParentFun}) of
@@ -3033,9 +3032,9 @@ file_sort_handle(H, Kp, SortOptions, TmpDir, Compressed, Post, LocalPost) ->
{terms, BTerms} ->
try
{[binary_to_term(B) || B <- BTerms], Post, LocalPost}
- catch Class:Reason ->
+ catch Class:Reason:Stacktrace ->
post_funs(Post),
- erlang:raise(Class, Reason, erlang:get_stacktrace())
+ erlang:raise(Class, Reason, Stacktrace)
end
end.
@@ -3045,9 +3044,9 @@ do_sort(In, Out, Sort, SortOptions, Post) ->
{error, Reason} -> throw_reason(Reason);
Reply -> Reply
end
- catch Class:Term ->
+ catch Class:Term:Stacktrace ->
post_funs(Post),
- erlang:raise(Class, Term, erlang:get_stacktrace())
+ erlang:raise(Class, Term, Stacktrace)
end.
do_sort(In, Out, sort, SortOptions) ->
@@ -3750,7 +3749,7 @@ maybe_error_logger(Name, Why) ->
expand_stacktrace(),
Trimmer = fun(M, _F, _A) -> M =:= erl_eval end,
Formater = fun(Term, I) -> io_lib:print(Term, I, 80, -1) end,
- X = lib:format_stacktrace(1, Stacktrace, Trimmer, Formater),
+ X = erl_error:format_stacktrace(1, Stacktrace, Trimmer, Formater),
error_logger:Name("qlc: temporary file was needed for ~w\n~ts\n",
[Why, lists:flatten(X)]).
@@ -3797,9 +3796,9 @@ call(undefined, _Arg, Default, _Post) ->
call(Fun, Arg, _Default, Post) ->
try
Fun(Arg)
- catch Class:Reason ->
+ catch Class:Reason:Stacktrace ->
post_funs(Post),
- erlang:raise(Class, Reason, erlang:get_stacktrace())
+ erlang:raise(Class, Reason, Stacktrace)
end.
grd(undefined, _Arg) ->
diff --git a/lib/stdlib/src/rand.erl b/lib/stdlib/src/rand.erl
index 7a8a5e6d4a..362e98006e 100644
--- a/lib/stdlib/src/rand.erl
+++ b/lib/stdlib/src/rand.erl
@@ -21,8 +21,8 @@
%% Multiple PRNG module for Erlang/OTP
%% Copyright (c) 2015-2016 Kenji Rikitake
%%
-%% exrop (xoroshiro116+) added and statistical distribution
-%% improvements by the Erlang/OTP team 2017
+%% exrop (xoroshiro116+) added, statistical distribution
+%% improvements and uniform_real added by the Erlang/OTP team 2017
%% =====================================================================
-module(rand).
@@ -30,10 +30,14 @@
-export([seed_s/1, seed_s/2, seed/1, seed/2,
export_seed/0, export_seed_s/1,
uniform/0, uniform/1, uniform_s/1, uniform_s/2,
+ uniform_real/0, uniform_real_s/1,
jump/0, jump/1,
normal/0, normal/2, normal_s/1, normal_s/3
]).
+%% Debug
+-export([make_float/3, float2str/1, bc64/1]).
+
-compile({inline, [exs64_next/1, exsplus_next/1,
exs1024_next/1, exs1024_calc/2,
exrop_next/1, exrop_next_s/2,
@@ -60,6 +64,10 @@
%% N i evaluated 3 times
(?BSL((Bits), (X), (N)) bor ((X) bsr ((Bits)-(N))))).
+-define(
+ BC(V, N),
+ bc((V), ?BIT((N) - 1), N)).
+
%%-define(TWO_POW_MINUS53, (math:pow(2, -53))).
-define(TWO_POW_MINUS53, 1.11022302462515657e-16).
@@ -84,14 +92,21 @@
%% The 'bits' field indicates how many bits the integer
%% returned from 'next' has got, i.e 'next' shall return
%% an random integer in the range 0..(2^Bits - 1).
-%% At least 53 bits is required for the floating point
-%% producing fallbacks. This field is only used when
-%% the 'uniform' or 'uniform_n' fields are not defined.
+%% At least 55 bits is required for the floating point
+%% producing fallbacks, but 56 bits would be more future proof.
%%
%% The fields 'next', 'uniform' and 'uniform_n'
-%% implement the algorithm. If 'uniform' or 'uinform_n'
+%% implement the algorithm. If 'uniform' or 'uniform_n'
%% is not present there is a fallback using 'next' and either
-%% 'bits' or the deprecated 'max'.
+%% 'bits' or the deprecated 'max'. The 'next' function
+%% must generate a word with at least 56 good random bits.
+%%
+%% The 'weak_low_bits' field indicate how many bits are of
+%% lesser quality and they will not be used by the floating point
+%% producing functions, nor by the range producing functions
+%% when more bits are needed, to avoid weak bits in the middle
+%% of the generated bits. The lowest bits from the range
+%% functions still have the generator's quality.
%%
-type alg_handler() ::
#{type := alg(),
@@ -148,11 +163,7 @@
%% For ranges larger than the algorithm bit size
uniform_range(Range, #{next:=Next, bits:=Bits} = Alg, R, V) ->
- WeakLowBits =
- case Alg of
- #{weak_low_bits:=WLB} -> WLB;
- #{} -> 0
- end,
+ WeakLowBits = maps:get(weak_low_bits, Alg, 0),
%% Maybe waste the lowest bit(s) when shifting in new bits
Shift = Bits - WeakLowBits,
ShiftMask = bnot ?MASK(WeakLowBits),
@@ -297,7 +308,7 @@ uniform_s({#{bits:=Bits, next:=Next} = Alg, R0}) ->
{(V bsr (Bits - 53)) * ?TWO_POW_MINUS53, {Alg, R1}};
uniform_s({#{max:=Max, next:=Next} = Alg, R0}) ->
{V, R1} = Next(R0),
- %% Old broken algorithm with non-uniform density
+ %% Old algorithm with non-uniform density
{V / (Max + 1), {Alg, R1}}.
@@ -317,7 +328,7 @@ uniform_s(N, {#{bits:=Bits, next:=Next} = Alg, R0})
?uniform_range(N, Alg, R1, V, MaxMinusN, I);
uniform_s(N, {#{max:=Max, next:=Next} = Alg, R0})
when is_integer(N), 1 =< N ->
- %% Old broken algorithm with skewed probability
+ %% Old algorithm with skewed probability
%% and gap in ranges > Max
{V, R1} = Next(R0),
if
@@ -328,6 +339,189 @@ uniform_s(N, {#{max:=Max, next:=Next} = Alg, R0})
{trunc(F * N) + 1, {Alg, R1}}
end.
+%% uniform_real/0: returns a random float X where 0.0 < X =< 1.0,
+%% updating the state in the process dictionary.
+
+-spec uniform_real() -> X :: float().
+uniform_real() ->
+ {X, Seed} = uniform_real_s(seed_get()),
+ _ = seed_put(Seed),
+ X.
+
+%% uniform_real_s/1: given a state, uniform_s/1
+%% returns a random float X where 0.0 < X =< 1.0,
+%% and a new state.
+%%
+%% This function does not use the same form of uniformity
+%% as the uniform_s/1 function.
+%%
+%% Instead, this function does not generate numbers with equal
+%% distance in the interval, but rather tries to keep all mantissa
+%% bits random also for small numbers, meaning that the distance
+%% between possible numbers decreases when the numbers
+%% approaches 0.0, as does the possibility for a particular
+%% number. Hence uniformity is preserved.
+%%
+%% To generate 56 bits at the time instead of 53 is actually
+%% a speed optimization since the probability to have to
+%% generate a second word decreases by 1/2 for every extra bit.
+%%
+%% This function generates normalized numbers, so the smallest number
+%% that can be generated is 2^-1022 with the distance 2^-1074
+%% to the next to smallest number, compared to 2^-53 for uniform_s/1.
+%%
+%% This concept of uniformity should work better for applications
+%% where you need to calculate 1.0/X or math:log(X) since those
+%% operations benefits from larger precision approaching 0.0,
+%% and that this function does not return 0.0 nor denormalized
+%% numbers very close to 0.0. The log() operation in The Box-Muller
+%% transformation for normal distribution is an example of this.
+%%
+%%-define(TWO_POW_MINUS55, (math:pow(2, -55))).
+%%-define(TWO_POW_MINUS110, (math:pow(2, -110))).
+%%-define(TWO_POW_MINUS55, 2.7755575615628914e-17).
+%%-define(TWO_POW_MINUS110, 7.7037197775489436e-34).
+%%
+-spec uniform_real_s(State :: state()) -> {X :: float(), NewState :: state()}.
+uniform_real_s({#{bits:=Bits, next:=Next} = Alg, R0}) ->
+ %% Generate a 56 bit number without using the weak low bits.
+ %%
+ %% Be sure to use only 53 bits when multiplying with
+ %% math:pow(2.0, -N) to avoid rounding which would make
+ %% "even" floats more probable than "odd".
+ %%
+ {V1, R1} = Next(R0),
+ M1 = V1 bsr (Bits - 56),
+ if
+ ?BIT(55) =< M1 ->
+ %% We have 56 bits - waste 3
+ {(M1 bsr 3) * math:pow(2.0, -53), {Alg, R1}};
+ ?BIT(54) =< M1 ->
+ %% We have 55 bits - waste 2
+ {(M1 bsr 2) * math:pow(2.0, -54), {Alg, R1}};
+ ?BIT(53) =< M1 ->
+ %% We have 54 bits - waste 1
+ {(M1 bsr 1) * math:pow(2.0, -55), {Alg, R1}};
+ ?BIT(52) =< M1 ->
+ %% We have 53 bits - use all
+ {M1 * math:pow(2.0, -56), {Alg, R1}};
+ true ->
+ %% Need more bits
+ {V2, R2} = Next(R1),
+ uniform_real_s(Alg, Next, M1, -56, R2, V2, Bits)
+ end;
+uniform_real_s({#{max:=_, next:=Next} = Alg, R0}) ->
+ %% Generate a 56 bit number.
+ %% Ignore the weak low bits for these old algorithms,
+ %% just produce something reasonable.
+ %%
+ %% Be sure to use only 53 bits when multiplying with
+ %% math:pow(2.0, -N) to avoid rounding which would make
+ %% "even" floats more probable than "odd".
+ %%
+ {V1, R1} = Next(R0),
+ M1 = ?MASK(56, V1),
+ if
+ ?BIT(55) =< M1 ->
+ %% We have 56 bits - waste 3
+ {(M1 bsr 3) * math:pow(2.0, -53), {Alg, R1}};
+ ?BIT(54) =< M1 ->
+ %% We have 55 bits - waste 2
+ {(M1 bsr 2) * math:pow(2.0, -54), {Alg, R1}};
+ ?BIT(53) =< M1 ->
+ %% We have 54 bits - waste 1
+ {(M1 bsr 1) * math:pow(2.0, -55), {Alg, R1}};
+ ?BIT(52) =< M1 ->
+ %% We have 53 bits - use all
+ {M1 * math:pow(2.0, -56), {Alg, R1}};
+ true ->
+ %% Need more bits
+ {V2, R2} = Next(R1),
+ uniform_real_s(Alg, Next, M1, -56, R2, V2, 56)
+ end.
+
+uniform_real_s(Alg, _Next, M0, -1064, R1, V1, Bits) -> % 19*56
+ %% This is a very theoretical bottom case.
+ %% The odds of getting here is about 2^-1008,
+ %% through a white box test case, or thanks to
+ %% a malfunctioning PRNG producing 18 56-bit zeros in a row.
+ %%
+ %% Fill up to 53 bits, we have at most 52
+ B0 = (53 - ?BC(M0, 52)), % Missing bits
+ {(((M0 bsl B0) bor (V1 bsr (Bits - B0))) * math:pow(2.0, -1064 - B0)),
+ {Alg, R1}};
+uniform_real_s(Alg, Next, M0, BitNo, R1, V1, Bits) ->
+ if
+ %% Optimize the most probable.
+ %% Fill up to 53 bits.
+ ?BIT(51) =< M0 ->
+ %% We have 52 bits in M0 - need 1
+ {(((M0 bsl 1) bor (V1 bsr (Bits - 1)))
+ * math:pow(2.0, BitNo - 1)),
+ {Alg, R1}};
+ ?BIT(50) =< M0 ->
+ %% We have 51 bits in M0 - need 2
+ {(((M0 bsl 2) bor (V1 bsr (Bits - 2)))
+ * math:pow(2.0, BitNo - 2)),
+ {Alg, R1}};
+ ?BIT(49) =< M0 ->
+ %% We have 50 bits in M0 - need 3
+ {(((M0 bsl 3) bor (V1 bsr (Bits - 3)))
+ * math:pow(2.0, BitNo - 3)),
+ {Alg, R1}};
+ M0 == 0 ->
+ M1 = V1 bsr (Bits - 56),
+ if
+ ?BIT(55) =< M1 ->
+ %% We have 56 bits - waste 3
+ {(M1 bsr 3) * math:pow(2.0, BitNo - 53), {Alg, R1}};
+ ?BIT(54) =< M1 ->
+ %% We have 55 bits - waste 2
+ {(M1 bsr 2) * math:pow(2.0, BitNo - 54), {Alg, R1}};
+ ?BIT(53) =< M1 ->
+ %% We have 54 bits - waste 1
+ {(M1 bsr 1) * math:pow(2.0, BitNo - 55), {Alg, R1}};
+ ?BIT(52) =< M1 ->
+ %% We have 53 bits - use all
+ {M1 * math:pow(2.0, BitNo - 56), {Alg, R1}};
+ BitNo =:= -1008 ->
+ %% Endgame
+ %% For the last round we can not have 14 zeros or more
+ %% at the top of M1 because then we will underflow,
+ %% so we need at least 43 bits
+ if
+ ?BIT(42) =< M1 ->
+ %% We have 43 bits - get the last bits
+ uniform_real_s(Alg, Next, M1, BitNo - 56, R1);
+ true ->
+ %% Would underflow 2^-1022 - start all over
+ %%
+ %% We could just crash here since the odds for
+ %% the PRNG being broken is much higher than
+ %% for a good PRNG generating this many zeros
+ %% in a row. Maybe we should write an error
+ %% report or call this a system limit...?
+ uniform_real_s({Alg, R1})
+ end;
+ true ->
+ %% Need more bits
+ uniform_real_s(Alg, Next, M1, BitNo - 56, R1)
+ end;
+ true ->
+ %% Fill up to 53 bits
+ B0 = 53 - ?BC(M0, 49), % Number of bits we need to append
+ {(((M0 bsl B0) bor (V1 bsr (Bits - B0)))
+ * math:pow(2.0, BitNo - B0)),
+ {Alg, R1}}
+ end.
+%%
+uniform_real_s(#{bits:=Bits} = Alg, Next, M0, BitNo, R0) ->
+ {V1, R1} = Next(R0),
+ uniform_real_s(Alg, Next, M0, BitNo, R1, V1, Bits);
+uniform_real_s(#{max:=_} = Alg, Next, M0, BitNo, R0) ->
+ {V1, R1} = Next(R0),
+ uniform_real_s(Alg, Next, M0, BitNo, R1, ?MASK(56, V1), 56).
+
%% jump/1: given a state, jump/1
%% returns a new state which is equivalent to that
%% after a large number of call defined for each algorithm.
@@ -1025,3 +1219,42 @@ normal_fi(Indx) ->
1.0214971439701471e-02,8.6165827693987316e-03,7.0508754713732268e-03,
5.5224032992509968e-03,4.0379725933630305e-03,2.6090727461021627e-03,
1.2602859304985975e-03}).
+
+%%%bitcount64(0) -> 0;
+%%%bitcount64(V) -> 1 + bitcount(V, 64).
+%%%
+%%%-define(
+%%% BITCOUNT(V, N),
+%%% bitcount(V, N) ->
+%%% if
+%%% (1 bsl ((N) bsr 1)) =< (V) ->
+%%% ((N) bsr 1) + bitcount((V) bsr ((N) bsr 1), ((N) bsr 1));
+%%% true ->
+%%% bitcount((V), ((N) bsr 1))
+%%% end).
+%%%?BITCOUNT(V, 64);
+%%%?BITCOUNT(V, 32);
+%%%?BITCOUNT(V, 16);
+%%%?BITCOUNT(V, 8);
+%%%?BITCOUNT(V, 4);
+%%%?BITCOUNT(V, 2);
+%%%bitcount(_, 1) -> 0.
+
+bc64(V) -> ?BC(V, 64).
+
+%% Linear from high bit - higher probability first gives faster execution
+bc(V, B, N) when B =< V -> N;
+bc(V, B, N) -> bc(V, B bsr 1, N - 1).
+
+make_float(S, E, M) ->
+ <<F/float>> = <<S:1, E:11, M:52>>,
+ F.
+
+float2str(N) ->
+ <<S:1, E:11, M:52>> = <<(float(N))/float>>,
+ lists:flatten(
+ io_lib:format(
+ "~c~c.~13.16.0bE~b",
+ [case S of 1 -> $-; 0 -> $+ end,
+ case E of 0 -> $0; _ -> $1 end,
+ M, E - 16#3ff])).
diff --git a/lib/stdlib/src/sets.erl b/lib/stdlib/src/sets.erl
index c65a13b22e..8adb9016e2 100644
--- a/lib/stdlib/src/sets.erl
+++ b/lib/stdlib/src/sets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@
-module(sets).
%% Standard interface.
--export([new/0,is_set/1,size/1,to_list/1,from_list/1]).
+-export([new/0,is_set/1,size/1,is_empty/1,to_list/1,from_list/1]).
-export([is_element/2,add_element/2,del_element/2]).
-export([union/2,union/1,intersection/2,intersection/1]).
-export([is_disjoint/2]).
@@ -96,6 +96,12 @@ is_set(_) -> false.
Set :: set().
size(S) -> S#set.size.
+%% is_empty(Set) -> boolean().
+%% Return 'true' if Set is an empty set, otherwise 'false'.
+-spec is_empty(Set) -> boolean() when
+ Set :: set().
+is_empty(S) -> S#set.size=:=0.
+
%% to_list(Set) -> [Elem].
%% Return the elements in Set as a list.
-spec to_list(Set) -> List when
diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl
index 6eafc7b209..c73cf22943 100644
--- a/lib/stdlib/src/shell.erl
+++ b/lib/stdlib/src/shell.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -230,7 +230,7 @@ server_loop(N0, Eval_0, Bs00, RT, Ds00, History0, Results0) ->
{Res,Eval0} = get_command(Prompt, Eval_1, Bs0, RT, Ds0),
case Res of
{ok,Es0,XBs} ->
- Es1 = lib:subst_values_for_vars(Es0, XBs),
+ Es1 = erl_eval:subst_values_for_vars(Es0, XBs),
case expand_hist(Es1, N) of
{ok,Es} ->
{V,Eval,Bs,Ds} = shell_cmd(Es, Eval0, Bs0, RT, Ds0, cmd),
@@ -280,7 +280,7 @@ get_command(Prompt, Eval, Bs, RT, Ds) ->
io:scan_erl_exprs(group_leader(), Prompt, 1, [text])
of
{ok,Toks,_EndPos} ->
- lib:extended_parse_exprs(Toks);
+ erl_eval:extended_parse_exprs(Toks);
{eof,_EndPos} ->
eof;
{error,ErrorInfo,_EndPos} ->
@@ -589,7 +589,7 @@ report_exception(Class, Severity, {Reason,Stacktrace}, RT) ->
PF = fun(Term, I1) -> pp(Term, I1, RT) end,
SF = fun(M, _F, _A) -> (M =:= erl_eval) or (M =:= ?MODULE) end,
Enc = encoding(),
- Str = lib:format_exception(I, Class, Reason, Stacktrace, SF, PF, Enc),
+ Str = erl_error:format_exception(I, Class, Reason, Stacktrace, SF, PF, Enc),
io:requests([{put_chars, latin1, Tag},
{put_chars, unicode, Str},
nl]).
@@ -645,8 +645,7 @@ eval_exprs(Es, Shell, Bs0, RT, Lf, Ef, W) ->
catch
exit:normal ->
exit(normal);
- Class:Reason ->
- Stacktrace = erlang:get_stacktrace(),
+ Class:Reason:Stacktrace ->
M = {self(),Class,{Reason,Stacktrace}},
case do_catch(Class, Reason) of
true ->
@@ -701,7 +700,9 @@ exprs([E0|Es], Bs1, RT, Lf, Ef, Bs0, W) ->
{W,V0};
true -> case result_will_be_saved() of
true -> V0;
- false -> ignored
+ false ->
+ erlang:garbage_collect(),
+ ignored
end
end,
{{value,V,Bs,get()},Bs};
@@ -727,7 +728,7 @@ result_will_be_saved() ->
used_record_defs(E, RT) ->
%% Be careful to return a list where used records come before
%% records that use them. The linter wants them ordered that way.
- UR = case used_records(E, [], RT) of
+ UR = case used_records(E, [], RT, []) of
[] ->
[];
L0 ->
@@ -737,13 +738,19 @@ used_record_defs(E, RT) ->
end,
record_defs(RT, UR).
-used_records(E, U0, RT) ->
+used_records(E, U0, RT, Skip) ->
case used_records(E) of
{name,Name,E1} ->
- U = used_records(ets:lookup(RT, Name), [Name | U0], RT),
- used_records(E1, U, RT);
+ U = case lists:member(Name, Skip) of
+ true ->
+ U0;
+ false ->
+ R = ets:lookup(RT, Name),
+ used_records(R, [Name | U0], RT, [Name | Skip])
+ end,
+ used_records(E1, U, RT, Skip);
{expr,[E1 | Es]} ->
- used_records(Es, used_records(E1, U0, RT), RT);
+ used_records(Es, used_records(E1, U0, RT, Skip), RT, Skip);
_ ->
U0
end.
@@ -799,8 +806,8 @@ restrict_handlers(RShMod, Shell, RT) ->
-define(BAD_RETURN(M, F, V),
try erlang:error(reason)
- catch _:_ -> erlang:raise(exit, {restricted_shell_bad_return,V},
- [{M,F,3} | erlang:get_stacktrace()])
+ catch _:_:S -> erlang:raise(exit, {restricted_shell_bad_return,V},
+ [{M,F,3} | S])
end).
local_allowed(F, As, RShMod, Bs, Shell, RT) when is_atom(F) ->
@@ -1409,7 +1416,7 @@ pp(V, I, D, RT) ->
true
end,
io_lib_pretty:print(V, ([{column, I}, {line_length, columns()},
- {depth, D}, {max_chars, ?CHAR_MAX},
+ {depth, D}, {line_max_chars, ?CHAR_MAX},
{strings, Strings},
{record_print_fun, record_print_fun(RT)}]
++ enc())).
@@ -1453,7 +1460,7 @@ check_env(V) ->
{ok, Val} ->
Txt = io_lib:fwrite
("Invalid value of STDLIB configuration parameter"
- "~w: ~tp\n", [V, Val]),
+ "~tw: ~tp\n", [V, Val]),
error_logger:info_report(lists:flatten(Txt))
end.
diff --git a/lib/stdlib/src/slave.erl b/lib/stdlib/src/slave.erl
index 5b5c328c0c..5e8c1a43ea 100644
--- a/lib/stdlib/src/slave.erl
+++ b/lib/stdlib/src/slave.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -77,7 +77,7 @@ start_pseudo(_,_,_) -> ok. %% It's already there
Pid :: pid().
relay({badrpc,Reason}) ->
- error_msg(" ** exiting relay server ~w :~w **~n", [self(),Reason]),
+ error_msg(" ** exiting relay server ~w :~tw **~n", [self(),Reason]),
exit(Reason);
relay(undefined) ->
error_msg(" ** exiting relay server ~w **~n", [self()]),
@@ -187,7 +187,7 @@ start_link(Host, Name, Args) ->
start(Host, Name, Args, self()).
start(Host0, Name, Args, LinkTo) ->
- Prog = lib:progname(),
+ Prog = progname(),
start(Host0, Name, Args, LinkTo, Prog).
start(Host0, Name, Args, LinkTo, Prog) ->
@@ -296,7 +296,6 @@ mk_cmd(Host, Name, Args, Waiter, Prog0) ->
" -s slave slave_start ", node(),
" ", Waiter,
" ", Args]),
-
case after_char($@, atom_to_list(node())) of
Host ->
{ok, BasicCmd};
@@ -309,6 +308,15 @@ mk_cmd(Host, Name, Args, Waiter, Prog0) ->
end
end.
+%% Return the name of the script that starts (this) erlang
+progname() ->
+ case init:get_argument(progname) of
+ {ok, [[Prog]]} ->
+ Prog;
+ _Other ->
+ "no_prog_name"
+ end.
+
%% This is an attempt to distinguish between spaces in the program
%% path and spaces that separate arguments. The program is quoted to
%% allow spaces in the path.
@@ -317,10 +325,10 @@ mk_cmd(Host, Name, Args, Waiter, Prog0) ->
%% (through start/5) or if the -program switch to beam is used and
%% includes arguments (typically done by cerl in OTP test environment
%% in order to ensure that slave/peer nodes are started with the same
-%% emulator and flags as the test node. The return from lib:progname()
+%% emulator and flags as the test node. The result from progname()
%% could then typically be '/<full_path_to>/cerl -gcov').
quote_progname(Progname) ->
- do_quote_progname(string:tokens(to_list(Progname)," ")).
+ do_quote_progname(string:lexemes(to_list(Progname)," ")).
do_quote_progname([Prog]) ->
"\""++Prog++"\"";
diff --git a/lib/stdlib/src/stdlib.app.src b/lib/stdlib/src/stdlib.app.src
index 3c449d3cb9..cd09872b87 100644
--- a/lib/stdlib/src/stdlib.app.src
+++ b/lib/stdlib/src/stdlib.app.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -43,6 +43,7 @@
erl_anno,
erl_bits,
erl_compile,
+ erl_error,
erl_eval,
erl_expand_records,
erl_internal,
@@ -71,7 +72,6 @@
io_lib_format,
io_lib_fread,
io_lib_pretty,
- lib,
lists,
log_mf_h,
maps,
@@ -101,13 +101,14 @@
timer,
unicode,
unicode_util,
+ uri_string,
win32reg,
zip]},
{registered,[timer_server,rsh_starter,take_over_monitor,pool_master,
dets]},
{applications, [kernel]},
{env, []},
- {runtime_dependencies, ["sasl-3.0","kernel-5.0","erts-9.0","crypto-3.3",
+ {runtime_dependencies, ["sasl-3.0","kernel-6.0","erts-10.0","crypto-3.3",
"compiler-5.0"]}
]}.
diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src
index 3100504a80..8c0b186288 100644
--- a/lib/stdlib/src/stdlib.appup.src
+++ b/lib/stdlib/src/stdlib.appup.src
@@ -18,7 +18,11 @@
%% %CopyrightEnd%
{"%VSN%",
%% Up from - max one major revision back
- [{<<"3\\.[0-3](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-19.*
+ [{<<"3\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.*
+ {<<"3\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-21.0
+ {<<"3\\.6(\\.[0-9]+)*">>,[restart_new_emulator]}],% OTP-21.1
%% Down to - max one major revision back
- [{<<"3\\.[0-3](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-19.*
+ [{<<"3\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-20.*
+ {<<"3\\.5(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-21.0
+ {<<"3\\.6(\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-21.1
}.
diff --git a/lib/stdlib/src/string.erl b/lib/stdlib/src/string.erl
index 6f7009b5d9..2939e78d9d 100644
--- a/lib/stdlib/src/string.erl
+++ b/lib/stdlib/src/string.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -74,15 +74,16 @@
-export([to_upper/1, to_lower/1]).
%%
-import(lists,[member/2]).
-
-compile({no_auto_import,[length/1]}).
+-compile({inline, [btoken/2, rev/1, append/2, stack/2, search_compile/1]}).
+-define(ASCII_LIST(CP1,CP2), CP1 < 256, CP2 < 256, CP1 =/= $\r).
-export_type([grapheme_cluster/0]).
-type grapheme_cluster() :: char() | [char()].
-type direction() :: 'leading' | 'trailing'.
--dialyzer({no_improper_lists, stack/2}).
+-dialyzer({no_improper_lists, [stack/2, length_b/3]}).
%%% BIFs internal (not documented) should not to be used outside of this module
%%% May be removed
-export([list_to_float/1, list_to_integer/1]).
@@ -117,8 +118,10 @@ is_empty(_) -> false.
%% Count the number of grapheme clusters in chardata
-spec length(String::unicode:chardata()) -> non_neg_integer().
+length(<<CP1/utf8, Bin/binary>>) ->
+ length_b(Bin, CP1, 0);
length(CD) ->
- length_1(unicode_util:gc(CD), 0).
+ length_1(CD, 0).
%% Convert a string to a list of grapheme clusters
-spec to_graphemes(String::unicode:chardata()) -> [grapheme_cluster()].
@@ -166,6 +169,8 @@ equal(A, B, true, Norm) ->
%% Reverse grapheme clusters
-spec reverse(String::unicode:chardata()) -> [grapheme_cluster()].
+reverse(<<CP1/utf8, Rest/binary>>) ->
+ reverse_b(Rest, CP1, []);
reverse(CD) ->
reverse_1(CD, []).
@@ -176,7 +181,10 @@ reverse(CD) ->
Start :: non_neg_integer(),
Slice :: unicode:chardata().
slice(CD, N) when is_integer(N), N >= 0 ->
- slice_l(CD, N, is_binary(CD)).
+ case slice_l0(CD, N) of
+ [] when is_binary(CD) -> <<>>;
+ Res -> Res
+ end.
-spec slice(String, Start, Length) -> Slice when
String::unicode:chardata(),
@@ -185,9 +193,15 @@ slice(CD, N) when is_integer(N), N >= 0 ->
Slice :: unicode:chardata().
slice(CD, N, Length)
when is_integer(N), N >= 0, is_integer(Length), Length > 0 ->
- slice_trail(slice_l(CD, N, is_binary(CD)), Length);
+ case slice_l0(CD, N) of
+ [] when is_binary(CD) -> <<>>;
+ L -> slice_trail(L, Length)
+ end;
slice(CD, N, infinity) ->
- slice_l(CD, N, is_binary(CD));
+ case slice_l0(CD, N) of
+ [] when is_binary(CD) -> <<>>;
+ Res -> Res
+ end;
slice(CD, _, 0) ->
case is_binary(CD) of
true -> <<>>;
@@ -246,18 +260,22 @@ trim(Str, Dir) ->
Dir :: direction() | 'both',
Characters :: [grapheme_cluster()].
trim(Str, _, []) -> Str;
+trim(Str, leading, [Sep]) when is_list(Str), Sep < 256 ->
+ trim_ls(Str, Sep);
trim(Str, leading, Sep) when is_list(Sep) ->
- trim_l(Str, search_pattern(Sep));
-trim(Str, trailing, Sep) when is_list(Sep) ->
- trim_t(Str, 0, search_pattern(Sep));
-trim(Str, both, Sep0) when is_list(Sep0) ->
- Sep = search_pattern(Sep0),
- trim_t(trim_l(Str,Sep), 0, Sep).
+ trim_l(Str, Sep);
+trim(Str, trailing, [Sep]) when is_list(Str), Sep < 256 ->
+ trim_ts(Str, Sep);
+trim(Str, trailing, Seps0) when is_list(Seps0) ->
+ Seps = search_pattern(Seps0),
+ trim_t(Str, 0, Seps);
+trim(Str, both, Sep) when is_list(Sep) ->
+ trim(trim(Str,leading,Sep), trailing, Sep).
%% Delete trailing newlines or \r\n
-spec chomp(String::unicode:chardata()) -> unicode:chardata().
chomp(Str) ->
- trim_t(Str,0, {[[$\r,$\n],$\n], [$\r,$\n], [<<$\r>>,<<$\n>>]}).
+ trim(Str, trailing, [[$\r,$\n],$\n]).
%% Split String into two parts where the leading part consists of Characters
-spec take(String, Characters) -> {Leading, Trailing} when
@@ -290,8 +308,7 @@ take(Str, [], Complement, Dir) ->
{true, leading} -> {Str, Empty};
{true, trailing} -> {Empty, Str}
end;
-take(Str, Sep0, false, leading) ->
- Sep = search_pattern(Sep0),
+take(Str, Sep, false, leading) ->
take_l(Str, Sep, []);
take(Str, Sep0, true, leading) ->
Sep = search_pattern(Sep0),
@@ -306,16 +323,30 @@ take(Str, Sep0, true, trailing) ->
%% Uppercase all chars in Str
-spec uppercase(String::unicode:chardata()) -> unicode:chardata().
uppercase(CD) when is_list(CD) ->
- uppercase_list(CD);
-uppercase(CD) when is_binary(CD) ->
- uppercase_bin(CD,<<>>).
+ try uppercase_list(CD, false)
+ catch unchanged -> CD
+ end;
+uppercase(<<CP1/utf8, Rest/binary>>=Orig) ->
+ try uppercase_bin(CP1, Rest, false) of
+ List -> unicode:characters_to_binary(List)
+ catch unchanged -> Orig
+ end;
+uppercase(<<>>) ->
+ <<>>.
%% Lowercase all chars in Str
-spec lowercase(String::unicode:chardata()) -> unicode:chardata().
lowercase(CD) when is_list(CD) ->
- lowercase_list(CD);
-lowercase(CD) when is_binary(CD) ->
- lowercase_bin(CD,<<>>).
+ try lowercase_list(CD, false)
+ catch unchanged -> CD
+ end;
+lowercase(<<CP1/utf8, Rest/binary>>=Orig) ->
+ try lowercase_bin(CP1, Rest, false) of
+ List -> unicode:characters_to_binary(List)
+ catch unchanged -> Orig
+ end;
+lowercase(<<>>) ->
+ <<>>.
%% Make a titlecase of the first char in Str
-spec titlecase(String::unicode:chardata()) -> unicode:chardata().
@@ -335,9 +366,16 @@ titlecase(CD) when is_binary(CD) ->
%% Make a comparable string of the Str should be used for equality tests only
-spec casefold(String::unicode:chardata()) -> unicode:chardata().
casefold(CD) when is_list(CD) ->
- casefold_list(CD);
-casefold(CD) when is_binary(CD) ->
- casefold_bin(CD,<<>>).
+ try casefold_list(CD, false)
+ catch unchanged -> CD
+ end;
+casefold(<<CP1/utf8, Rest/binary>>=Orig) ->
+ try casefold_bin(CP1, Rest, false) of
+ List -> unicode:characters_to_binary(List)
+ catch unchanged -> Orig
+ end;
+casefold(<<>>) ->
+ <<>>.
-spec to_integer(String) -> {Int, Rest} | {'error', Reason} when
String :: unicode:chardata(),
@@ -384,7 +422,7 @@ to_float(String) ->
end.
to_number(String, Number, Rest, List, _Tail) when is_binary(String) ->
- BSz = length(List)-length(Rest),
+ BSz = erlang:length(List)-erlang:length(Rest),
<<_:BSz/binary, Cont/binary>> = String,
{Number, Cont};
to_number(_, Number, Rest, _, Tail) ->
@@ -393,10 +431,12 @@ to_number(_, Number, Rest, _, Tail) ->
%% Return the remaining string with prefix removed or else nomatch
-spec prefix(String::unicode:chardata(), Prefix::unicode:chardata()) ->
'nomatch' | unicode:chardata().
-prefix(Str, []) -> Str;
prefix(Str, Prefix0) ->
- Prefix = unicode:characters_to_list(Prefix0),
- case prefix_1(Str, Prefix) of
+ Result = case unicode:characters_to_list(Prefix0) of
+ [] -> Str;
+ Prefix -> prefix_1(Str, Prefix)
+ end,
+ case Result of
[] when is_binary(Str) -> <<>>;
Res -> Res
end.
@@ -451,6 +491,7 @@ replace(String, SearchPattern, Replacement, Where) ->
SeparatorList::[grapheme_cluster()]) ->
[unicode:chardata()].
lexemes([], _) -> [];
+lexemes(Str, []) -> [Str];
lexemes(Str, Seps0) when is_list(Seps0) ->
Seps = search_pattern(Seps0),
lexemes_m(Str, Seps, []).
@@ -484,13 +525,13 @@ find(String, SearchPattern, leading) ->
find(String, SearchPattern, trailing) ->
find_r(String, unicode:characters_to_list(SearchPattern), nomatch).
-%% Fetch first codepoint and return rest in tail
+%% Fetch first grapheme cluster and return rest in tail
-spec next_grapheme(String::unicode:chardata()) ->
maybe_improper_list(grapheme_cluster(),unicode:chardata()) |
{error,unicode:chardata()}.
next_grapheme(CD) -> unicode_util:gc(CD).
-%% Fetch first grapheme cluster and return rest in tail
+%% Fetch first codepoint and return rest in tail
-spec next_codepoint(String::unicode:chardata()) ->
maybe_improper_list(char(),unicode:chardata()) |
{error,unicode:chardata()}.
@@ -498,10 +539,23 @@ next_codepoint(CD) -> unicode_util:cp(CD).
%% Internals
-length_1([_|Rest], N) ->
- length_1(unicode_util:gc(Rest), N+1);
-length_1([], N) ->
- N.
+length_1([CP1|[CP2|_]=Cont], N) when ?ASCII_LIST(CP1,CP2) ->
+ length_1(Cont, N+1);
+length_1(Str, N) ->
+ case unicode_util:gc(Str) of
+ [] -> N;
+ [_|Rest] -> length_1(Rest, N+1)
+ end.
+
+length_b(<<CP2/utf8, Rest/binary>>, CP1, N)
+ when ?ASCII_LIST(CP1,CP2) ->
+ length_b(Rest, CP2, N+1);
+length_b(Bin0, CP1, N) ->
+ [_|Bin1] = unicode_util:gc([CP1|Bin0]),
+ case unicode_util:cp(Bin1) of
+ [] -> N+1;
+ [CP3|Bin] -> length_b(Bin, CP3, N+1)
+ end.
equal_1([A|AR], [B|BR]) when is_integer(A), is_integer(B) ->
A =:= B andalso equal_1(AR, BR);
@@ -540,29 +594,66 @@ equal_norm_nocase(A0, B0, Norm) ->
{L1,L2} when is_list(L1), is_list(L2) -> false
end.
+reverse_1([CP1|[CP2|_]=Cont], Acc) when ?ASCII_LIST(CP1,CP2) ->
+ reverse_1(Cont, [CP1|Acc]);
reverse_1(CD, Acc) ->
case unicode_util:gc(CD) of
[GC|Rest] -> reverse_1(Rest, [GC|Acc]);
[] -> Acc
end.
-slice_l(CD, N, Binary) when N > 0 ->
+reverse_b(<<CP2/utf8, Rest/binary>>, CP1, Acc)
+ when ?ASCII_LIST(CP1,CP2) ->
+ reverse_b(Rest, CP2, [CP1|Acc]);
+reverse_b(Bin0, CP1, Acc) ->
+ [GC|Bin1] = unicode_util:gc([CP1|Bin0]),
+ case unicode_util:cp(Bin1) of
+ [] -> [GC|Acc];
+ [CP3|Bin] -> reverse_b(Bin, CP3, [GC|Acc])
+ end.
+
+slice_l0(<<CP1/utf8, Bin/binary>>, N) when N > 0 ->
+ slice_lb(Bin, CP1, N);
+slice_l0(L, N) ->
+ slice_l(L, N).
+
+slice_l([CP1|[CP2|_]=Cont], N) when ?ASCII_LIST(CP1,CP2),N > 0 ->
+ slice_l(Cont, N-1);
+slice_l(CD, N) when N > 0 ->
case unicode_util:gc(CD) of
- [_|Cont] -> slice_l(Cont, N-1, Binary);
- [] when Binary -> <<>>;
+ [_|Cont] -> slice_l(Cont, N-1);
[] -> []
end;
-slice_l(Cont, 0, Binary) ->
- case is_empty(Cont) of
- true when Binary -> <<>>;
- _ -> Cont
+slice_l(Cont, 0) ->
+ Cont.
+
+slice_lb(<<CP2/utf8, Bin/binary>>, CP1, N) when ?ASCII_LIST(CP1,CP2), N > 1 ->
+ slice_lb(Bin, CP2, N-1);
+slice_lb(Bin, CP1, N) ->
+ [_|Rest] = unicode_util:gc([CP1|Bin]),
+ if N > 1 ->
+ case unicode_util:cp(Rest) of
+ [CP2|Cont] -> slice_lb(Cont, CP2, N-1);
+ [] -> <<>>
+ end;
+ N =:= 1 ->
+ Rest
end.
+slice_trail(Orig, N) when is_binary(Orig) ->
+ case Orig of
+ <<CP1/utf8, Bin/binary>> when N > 0 ->
+ Length = slice_bin(Bin, CP1, N),
+ Sz = byte_size(Orig) - Length,
+ <<Keep:Sz/binary, _/binary>> = Orig,
+ Keep;
+ _ -> <<>>
+ end;
slice_trail(CD, N) when is_list(CD) ->
- slice_list(CD, N);
-slice_trail(CD, N) when is_binary(CD) ->
- slice_bin(CD, N, CD).
+ slice_list(CD, N).
+slice_list([CP1|[CP2|_]=Cont], N) when ?ASCII_LIST(CP1,CP2),N > 0 ->
+ [CP1|slice_list(Cont, N-1)];
slice_list(CD, N) when N > 0 ->
case unicode_util:gc(CD) of
[GC|Cont] -> append(GC, slice_list(Cont, N-1));
@@ -571,76 +662,165 @@ slice_list(CD, N) when N > 0 ->
slice_list(_, 0) ->
[].
-slice_bin(CD, N, Orig) when N > 0 ->
- case unicode_util:gc(CD) of
- [_|Cont] -> slice_bin(Cont, N-1, Orig);
- [] -> Orig
+slice_bin(<<CP2/utf8, Bin/binary>>, CP1, N) when ?ASCII_LIST(CP1,CP2), N > 0 ->
+ slice_bin(Bin, CP2, N-1);
+slice_bin(CD, CP1, N) when N > 0 ->
+ [_|Bin] = unicode_util:gc([CP1|CD]),
+ case unicode_util:cp(Bin) of
+ [CP2|Cont] -> slice_bin(Cont, CP2, N-1);
+ [] -> 0
end;
-slice_bin([], 0, Orig) ->
- Orig;
-slice_bin(CD, 0, Orig) ->
- Sz = byte_size(Orig) - byte_size(CD),
- <<Keep:Sz/binary, _/binary>> = Orig,
- Keep.
-
-uppercase_list(CPs0) ->
+slice_bin(CD, CP1, 0) ->
+ byte_size(CD)+byte_size(<<CP1/utf8>>).
+
+uppercase_list([CP1|[CP2|_]=Cont], _Changed) when $a =< CP1, CP1 =< $z, CP2 < 256 ->
+ [CP1-32|uppercase_list(Cont, true)];
+uppercase_list([CP1|[CP2|_]=Cont], Changed) when CP1 < 128, CP2 < 256 ->
+ [CP1|uppercase_list(Cont, Changed)];
+uppercase_list([], true) ->
+ [];
+uppercase_list([], false) ->
+ throw(unchanged);
+uppercase_list(CPs0, Changed) ->
case unicode_util:uppercase(CPs0) of
- [Char|CPs] -> append(Char,uppercase_list(CPs));
- [] -> []
+ [Char|CPs] when Char =:= hd(CPs0) -> [Char|uppercase_list(CPs, Changed)];
+ [Char|CPs] -> append(Char,uppercase_list(CPs, true));
+ [] -> uppercase_list([], Changed)
end.
-uppercase_bin(CPs0, Acc) ->
- case unicode_util:uppercase(CPs0) of
- [Char|CPs] when is_integer(Char) ->
- uppercase_bin(CPs, <<Acc/binary, Char/utf8>>);
- [Chars|CPs] ->
- uppercase_bin(CPs, <<Acc/binary,
- << <<CP/utf8>> || CP <- Chars>>/binary >>);
- [] -> Acc
+uppercase_bin(CP1, <<CP2/utf8, Bin/binary>>, _Changed)
+ when $a =< CP1, CP1 =< $z, CP2 < 256 ->
+ [CP1-32|uppercase_bin(CP2, Bin, true)];
+uppercase_bin(CP1, <<CP2/utf8, Bin/binary>>, Changed)
+ when CP1 < 128, CP2 < 256 ->
+ [CP1|uppercase_bin(CP2, Bin, Changed)];
+uppercase_bin(CP1, Bin, Changed) ->
+ case unicode_util:uppercase([CP1|Bin]) of
+ [CP1|CPs] ->
+ case unicode_util:cp(CPs) of
+ [Next|Rest] ->
+ [CP1|uppercase_bin(Next, Rest, Changed)];
+ [] when Changed ->
+ [CP1];
+ [] ->
+ throw(unchanged)
+ end;
+ [Char|CPs] ->
+ case unicode_util:cp(CPs) of
+ [Next|Rest] ->
+ [Char|uppercase_bin(Next, Rest, true)];
+ [] ->
+ [Char]
+ end
end.
-lowercase_list(CPs0) ->
+lowercase_list([CP1|[CP2|_]=Cont], _Changed) when $A =< CP1, CP1 =< $Z, CP2 < 256 ->
+ [CP1+32|lowercase_list(Cont, true)];
+lowercase_list([CP1|[CP2|_]=Cont], Changed) when CP1 < 128, CP2 < 256 ->
+ [CP1|lowercase_list(Cont, Changed)];
+lowercase_list([], true) ->
+ [];
+lowercase_list([], false) ->
+ throw(unchanged);
+lowercase_list(CPs0, Changed) ->
case unicode_util:lowercase(CPs0) of
- [Char|CPs] -> append(Char,lowercase_list(CPs));
- [] -> []
+ [Char|CPs] when Char =:= hd(CPs0) -> [Char|lowercase_list(CPs, Changed)];
+ [Char|CPs] -> append(Char,lowercase_list(CPs, true));
+ [] -> lowercase_list([], Changed)
end.
-lowercase_bin(CPs0, Acc) ->
- case unicode_util:lowercase(CPs0) of
- [Char|CPs] when is_integer(Char) ->
- lowercase_bin(CPs, <<Acc/binary, Char/utf8>>);
- [Chars|CPs] ->
- lowercase_bin(CPs, <<Acc/binary,
- << <<CP/utf8>> || CP <- Chars>>/binary >>);
- [] -> Acc
+lowercase_bin(CP1, <<CP2/utf8, Bin/binary>>, _Changed)
+ when $A =< CP1, CP1 =< $Z, CP2 < 256 ->
+ [CP1+32|lowercase_bin(CP2, Bin, true)];
+lowercase_bin(CP1, <<CP2/utf8, Bin/binary>>, Changed)
+ when CP1 < 128, CP2 < 256 ->
+ [CP1|lowercase_bin(CP2, Bin, Changed)];
+lowercase_bin(CP1, Bin, Changed) ->
+ case unicode_util:lowercase([CP1|Bin]) of
+ [CP1|CPs] ->
+ case unicode_util:cp(CPs) of
+ [Next|Rest] ->
+ [CP1|lowercase_bin(Next, Rest, Changed)];
+ [] when Changed ->
+ [CP1];
+ [] ->
+ throw(unchanged)
+ end;
+ [Char|CPs] ->
+ case unicode_util:cp(CPs) of
+ [Next|Rest] ->
+ [Char|lowercase_bin(Next, Rest, true)];
+ [] ->
+ [Char]
+ end
end.
-casefold_list(CPs0) ->
+casefold_list([CP1|[CP2|_]=Cont], _Changed) when $A =< CP1, CP1 =< $Z, CP2 < 256 ->
+ [CP1+32|casefold_list(Cont, true)];
+casefold_list([CP1|[CP2|_]=Cont], Changed) when CP1 < 128, CP2 < 256 ->
+ [CP1|casefold_list(Cont, Changed)];
+casefold_list([], true) ->
+ [];
+casefold_list([], false) ->
+ throw(unchanged);
+casefold_list(CPs0, Changed) ->
case unicode_util:casefold(CPs0) of
- [Char|CPs] -> append(Char, casefold_list(CPs));
- [] -> []
+ [Char|CPs] when Char =:= hd(CPs0) -> [Char|casefold_list(CPs, Changed)];
+ [Char|CPs] -> append(Char,casefold_list(CPs, true));
+ [] -> casefold_list([], Changed)
end.
-casefold_bin(CPs0, Acc) ->
- case unicode_util:casefold(CPs0) of
- [Char|CPs] when is_integer(Char) ->
- casefold_bin(CPs, <<Acc/binary, Char/utf8>>);
- [Chars|CPs] ->
- casefold_bin(CPs, <<Acc/binary,
- << <<CP/utf8>> || CP <- Chars>>/binary >>);
- [] -> Acc
+casefold_bin(CP1, <<CP2/utf8, Bin/binary>>, _Changed)
+ when $A =< CP1, CP1 =< $Z, CP2 < 256 ->
+ [CP1+32|casefold_bin(CP2, Bin, true)];
+casefold_bin(CP1, <<CP2/utf8, Bin/binary>>, Changed)
+ when CP1 < 128, CP2 < 256 ->
+ [CP1|casefold_bin(CP2, Bin, Changed)];
+casefold_bin(CP1, Bin, Changed) ->
+ case unicode_util:casefold([CP1|Bin]) of
+ [CP1|CPs] ->
+ case unicode_util:cp(CPs) of
+ [Next|Rest] ->
+ [CP1|casefold_bin(Next, Rest, Changed)];
+ [] when Changed ->
+ [CP1];
+ [] ->
+ throw(unchanged)
+ end;
+ [Char|CPs] ->
+ case unicode_util:cp(CPs) of
+ [Next|Rest] ->
+ [Char|casefold_bin(Next, Rest, true)];
+ [] ->
+ [Char]
+ end
end.
-
+%% Fast path for ascii searching for one character in lists
+trim_ls([CP1|[CP2|_]=Cont]=Str, Sep)
+ when ?ASCII_LIST(CP1,CP2) ->
+ case Sep of
+ CP1 -> trim_ls(Cont, Sep);
+ _ -> Str
+ end;
+trim_ls(Str, Sep) ->
+ trim_l(Str, [Sep]).
+
+trim_l([CP1|[CP2|_]=Cont]=Str, Sep)
+ when ?ASCII_LIST(CP1,CP2) ->
+ case lists:member(CP1, Sep) of
+ true -> trim_l(Cont, Sep);
+ false -> Str
+ end;
trim_l([Bin|Cont0], Sep) when is_binary(Bin) ->
case bin_search_inv(Bin, Cont0, Sep) of
{nomatch, Cont} -> trim_l(Cont, Sep);
Keep -> Keep
end;
-trim_l(Str, {GCs, _, _}=Sep) when is_list(Str) ->
+trim_l(Str, Sep) when is_list(Str) ->
case unicode_util:gc(Str) of
[C|Cs] ->
- case lists:member(C, GCs) of
+ case lists:member(C, Sep) of
true -> trim_l(Cs, Sep);
false -> Str
end;
@@ -652,15 +832,51 @@ trim_l(Bin, Sep) when is_binary(Bin) ->
[Keep] -> Keep
end.
-trim_t([Bin|Cont0], N, Sep) when is_binary(Bin) ->
+%% Fast path for ascii searching for one character in lists
+trim_ts([Sep|Cs1]=Str, Sep) ->
+ case Cs1 of
+ [] -> [];
+ [CP2|_] when ?ASCII_LIST(Sep,CP2) ->
+ Tail = trim_ts(Cs1, Sep),
+ case is_empty(Tail) of
+ true -> [];
+ false -> [Sep|Tail]
+ end;
+ _ ->
+ trim_t(Str, 0, search_pattern([Sep]))
+ end;
+trim_ts([CP|Cont],Sep) when is_integer(CP) ->
+ [CP|trim_ts(Cont, Sep)];
+trim_ts(Str, Sep) ->
+ trim_t(Str, 0, search_pattern([Sep])).
+
+trim_t([CP1|Cont]=Cs0, _, {GCs,CPs,_}=Seps) when is_integer(CP1) ->
+ case lists:member(CP1, CPs) of
+ true ->
+ [GC|Cs1] = unicode_util:gc(Cs0),
+ case lists:member(GC, GCs) of
+ true ->
+ Tail = trim_t(Cs1, 0, Seps),
+ case is_empty(Tail) of
+ true -> [];
+ false -> append(GC,Tail)
+ end;
+ false ->
+ append(GC,trim_t(Cs1, 0, Seps))
+ end;
+ false ->
+ [CP1|trim_t(Cont, 0, Seps)]
+ end;
+trim_t([Bin|Cont0], N, {GCs,_,_}=Seps0) when is_binary(Bin) ->
<<_:N/binary, Rest/binary>> = Bin,
- case bin_search(Rest, Cont0, Sep) of
+ Seps = search_compile(Seps0),
+ case bin_search(Rest, Cont0, Seps) of
{nomatch,_} ->
- stack(Bin, trim_t(Cont0, 0, Sep));
+ stack(Bin, trim_t(Cont0, 0, Seps));
[SepStart|Cont1] ->
- case bin_search_inv(SepStart, Cont1, Sep) of
+ case bin_search_inv(SepStart, Cont1, GCs) of
{nomatch, Cont} ->
- Tail = trim_t(Cont, 0, Sep),
+ Tail = trim_t(Cont, 0, Seps),
case is_empty(Tail) of
true ->
KeepSz = byte_size(Bin) - byte_size(SepStart),
@@ -672,67 +888,69 @@ trim_t([Bin|Cont0], N, Sep) when is_binary(Bin) ->
end;
[NonSep|Cont] when is_binary(NonSep) ->
KeepSz = byte_size(Bin) - byte_size(NonSep),
- trim_t([Bin|Cont], KeepSz, Sep)
+ trim_t([Bin|Cont], KeepSz, Seps)
end
end;
-trim_t(Str, 0, {GCs,CPs,_}=Sep) when is_list(Str) ->
- case unicode_util:cp(Str) of
- [CP|Cs] ->
- case lists:member(CP, CPs) of
+trim_t(Str, 0, {GCs,_,_}=Seps) when is_list(Str) ->
+ case unicode_util:gc(Str) of
+ [GC|Cs1] ->
+ case lists:member(GC, GCs) of
true ->
- [GC|Cs1] = unicode_util:gc(Str),
- case lists:member(GC, GCs) of
- true ->
- Tail = trim_t(Cs1, 0, Sep),
- case is_empty(Tail) of
- true -> [];
- false -> append(GC,Tail)
- end;
- false ->
- append(GC,trim_t(Cs1, 0, Sep))
+ Tail = trim_t(Cs1, 0, Seps),
+ case is_empty(Tail) of
+ true -> [];
+ false -> append(GC,Tail)
end;
false ->
- append(CP,trim_t(Cs, 0, Sep))
+ append(GC,trim_t(Cs1, 0, Seps))
end;
[] -> []
end;
-trim_t(Bin, N, Sep) when is_binary(Bin) ->
+trim_t(Bin, N, {GCs,_,_}=Seps0) when is_binary(Bin) ->
<<_:N/binary, Rest/binary>> = Bin,
- case bin_search(Rest, Sep) of
+ Seps = search_compile(Seps0),
+ case bin_search(Rest, [], Seps) of
{nomatch,_} -> Bin;
[SepStart] ->
- case bin_search_inv(SepStart, [], Sep) of
+ case bin_search_inv(SepStart, [], GCs) of
{nomatch,_} ->
KeepSz = byte_size(Bin) - byte_size(SepStart),
<<Keep:KeepSz/binary, _/binary>> = Bin,
Keep;
[NonSep] ->
KeepSz = byte_size(Bin) - byte_size(NonSep),
- trim_t(Bin, KeepSz, Sep)
+ trim_t(Bin, KeepSz, Seps)
end
end.
-take_l([Bin|Cont0], Sep, Acc) when is_binary(Bin) ->
- case bin_search_inv(Bin, Cont0, Sep) of
+
+take_l([CP1|[CP2|_]=Cont]=Str, Seps, Acc)
+ when ?ASCII_LIST(CP1,CP2) ->
+ case lists:member(CP1, Seps) of
+ true -> take_l(Cont, Seps, [CP1|Acc]);
+ false -> {rev(Acc), Str}
+ end;
+take_l([Bin|Cont0], Seps, Acc) when is_binary(Bin) ->
+ case bin_search_inv(Bin, Cont0, Seps) of
{nomatch, Cont} ->
Used = cp_prefix(Cont0, Cont),
- take_l(Cont, Sep, [unicode:characters_to_binary([Bin|Used])|Acc]);
+ take_l(Cont, Seps, [unicode:characters_to_binary([Bin|Used])|Acc]);
[Bin1|_]=After when is_binary(Bin1) ->
First = byte_size(Bin) - byte_size(Bin1),
<<Keep:First/binary, _/binary>> = Bin,
{btoken(Keep,Acc), After}
end;
-take_l(Str, {GCs, _, _}=Sep, Acc) when is_list(Str) ->
+take_l(Str, Seps, Acc) when is_list(Str) ->
case unicode_util:gc(Str) of
[C|Cs] ->
- case lists:member(C, GCs) of
- true -> take_l(Cs, Sep, append(rev(C),Acc));
+ case lists:member(C, Seps) of
+ true -> take_l(Cs, Seps, append(rev(C),Acc));
false -> {rev(Acc), Str}
end;
[] -> {rev(Acc), []}
end;
-take_l(Bin, Sep, Acc) when is_binary(Bin) ->
- case bin_search_inv(Bin, [], Sep) of
+take_l(Bin, Seps, Acc) when is_binary(Bin) ->
+ case bin_search_inv(Bin, [], Seps) of
{nomatch,_} ->
{btoken(Bin, Acc), <<>>};
[After] ->
@@ -741,27 +959,41 @@ take_l(Bin, Sep, Acc) when is_binary(Bin) ->
{btoken(Keep, Acc), After}
end.
-take_lc([Bin|Cont0], Sep, Acc) when is_binary(Bin) ->
- case bin_search(Bin, Cont0, Sep) of
+
+take_lc([CP1|Cont]=Str0, {GCs,CPs,_}=Seps, Acc) when is_integer(CP1) ->
+ case lists:member(CP1, CPs) of
+ true ->
+ [GC|Str] = unicode_util:gc(Str0),
+ case lists:member(GC, GCs) of
+ false -> take_lc(Str, Seps, append(rev(GC),Acc));
+ true -> {rev(Acc), Str0}
+ end;
+ false ->
+ take_lc(Cont, Seps, append(CP1,Acc))
+ end;
+take_lc([Bin|Cont0], Seps0, Acc) when is_binary(Bin) ->
+ Seps = search_compile(Seps0),
+ case bin_search(Bin, Cont0, Seps) of
{nomatch, Cont} ->
Used = cp_prefix(Cont0, Cont),
- take_lc(Cont, Sep, [unicode:characters_to_binary([Bin|Used])|Acc]);
+ take_lc(Cont, Seps, [unicode:characters_to_binary([Bin|Used])|Acc]);
[Bin1|_]=After when is_binary(Bin1) ->
First = byte_size(Bin) - byte_size(Bin1),
<<Keep:First/binary, _/binary>> = Bin,
{btoken(Keep,Acc), After}
end;
-take_lc(Str, {GCs, _, _}=Sep, Acc) when is_list(Str) ->
+take_lc(Str, {GCs,_,_}=Seps, Acc) when is_list(Str) ->
case unicode_util:gc(Str) of
[C|Cs] ->
case lists:member(C, GCs) of
- false -> take_lc(Cs, Sep, append(rev(C),Acc));
+ false -> take_lc(Cs, Seps, append(rev(C),Acc));
true -> {rev(Acc), Str}
end;
[] -> {rev(Acc), []}
end;
-take_lc(Bin, Sep, Acc) when is_binary(Bin) ->
- case bin_search(Bin, [], Sep) of
+take_lc(Bin, Seps0, Acc) when is_binary(Bin) ->
+ Seps = search_compile(Seps0),
+ case bin_search(Bin, [], Seps) of
{nomatch,_} ->
{btoken(Bin, Acc), <<>>};
[After] ->
@@ -770,148 +1002,192 @@ take_lc(Bin, Sep, Acc) when is_binary(Bin) ->
{btoken(Keep, Acc), After}
end.
-take_t([Bin|Cont0], N, Sep) when is_binary(Bin) ->
+
+take_t([CP1|Cont]=Str0, _, {GCs,CPs,_}=Seps) when is_integer(CP1) ->
+ case lists:member(CP1, CPs) of
+ true ->
+ [GC|Str] = unicode_util:gc(Str0),
+ case lists:member(GC, GCs) of
+ true ->
+ {Head, Tail} = take_t(Str, 0, Seps),
+ case is_empty(Head) of
+ true -> {Head, append(GC,Tail)};
+ false -> {append(GC,Head), Tail}
+ end;
+ false ->
+ {Head, Tail} = take_t(Str, 0, Seps),
+ {append(GC,Head), Tail}
+ end;
+ false ->
+ {Head, Tail} = take_t(Cont, 0, Seps),
+ {[CP1|Head], Tail}
+ end;
+take_t([Bin|Cont0], N, {GCs,_,_}=Seps0) when is_binary(Bin) ->
<<_:N/binary, Rest/binary>> = Bin,
- case bin_search(Rest, Cont0, Sep) of
+ Seps = search_compile(Seps0),
+ case bin_search(Rest, Cont0, Seps) of
{nomatch,Cont} ->
Used = cp_prefix(Cont0, Cont),
- {Head, Tail} = take_t(Cont, 0, Sep),
+ {Head, Tail} = take_t(Cont, 0, Seps),
{stack(unicode:characters_to_binary([Bin|Used]), Head), Tail};
[SepStart|Cont1] ->
- case bin_search_inv(SepStart, Cont1, Sep) of
+ case bin_search_inv(SepStart, Cont1, GCs) of
{nomatch, Cont} ->
- {Head, Tail} = take_t(Cont, 0, Sep),
+ {Head, Tail} = take_t(Cont, 0, Seps),
Used = cp_prefix(Cont0, Cont),
- case equal(Tail, Cont) of
+ case is_empty(Head) of
true ->
KeepSz = byte_size(Bin) - byte_size(SepStart),
<<Keep:KeepSz/binary, End/binary>> = Bin,
- {stack(Keep,Head), stack(stack(End,Used),Tail)};
+ {Keep, stack(stack(End,Used),Tail)};
false ->
{stack(unicode:characters_to_binary([Bin|Used]),Head), Tail}
end;
[NonSep|Cont] when is_binary(NonSep) ->
KeepSz = byte_size(Bin) - byte_size(NonSep),
- take_t([Bin|Cont], KeepSz, Sep)
+ take_t([Bin|Cont], KeepSz, Seps)
end
end;
-take_t(Str, 0, {GCs,CPs,_}=Sep) when is_list(Str) ->
- case unicode_util:cp(Str) of
- [CP|Cs] ->
- case lists:member(CP, CPs) of
+take_t(Str, 0, {GCs,_,_}=Seps) when is_list(Str) ->
+ case unicode_util:gc(Str) of
+ [GC|Cs1] ->
+ case lists:member(GC, GCs) of
true ->
- [GC|Cs1] = unicode_util:gc(Str),
- case lists:member(GC, GCs) of
- true ->
- {Head, Tail} = take_t(Cs1, 0, Sep),
- case equal(Tail, Cs1) of
- true -> {Head, append(GC,Tail)};
- false -> {append(GC,Head), Tail}
- end;
- false ->
- {Head, Tail} = take_t(Cs, 0, Sep),
- {append(CP,Head), Tail}
+ {Head, Tail} = take_t(Cs1, 0, Seps),
+ case is_empty(Head) of
+ true -> {Head, append(GC,Tail)};
+ false -> {append(GC,Head), Tail}
end;
false ->
- {Head, Tail} = take_t(Cs, 0, Sep),
- {append(CP,Head), Tail}
+ {Head, Tail} = take_t(Cs1, 0, Seps),
+ {append(GC,Head), Tail}
end;
[] -> {[],[]}
end;
-take_t(Bin, N, Sep) when is_binary(Bin) ->
+take_t(Bin, N, {GCs,_,_}=Seps0) when is_binary(Bin) ->
<<_:N/binary, Rest/binary>> = Bin,
- case bin_search(Rest, Sep) of
+ Seps = search_compile(Seps0),
+ case bin_search(Rest, [], Seps) of
{nomatch,_} -> {Bin, <<>>};
[SepStart] ->
- case bin_search_inv(SepStart, [], Sep) of
+ case bin_search_inv(SepStart, [], GCs) of
{nomatch,_} ->
KeepSz = byte_size(Bin) - byte_size(SepStart),
<<Before:KeepSz/binary, End/binary>> = Bin,
{Before, End};
[NonSep] ->
KeepSz = byte_size(Bin) - byte_size(NonSep),
- take_t(Bin, KeepSz, Sep)
+ take_t(Bin, KeepSz, Seps)
end
end.
-take_tc([Bin|Cont0], N, Sep) when is_binary(Bin) ->
+take_tc([CP1|[CP2|_]=Cont], _, {GCs,_,_}=Seps) when ?ASCII_LIST(CP1,CP2) ->
+ case lists:member(CP1, GCs) of
+ false ->
+ {Head, Tail} = take_tc(Cont, 0, Seps),
+ case is_empty(Head) of
+ true -> {Head, append(CP1,Tail)};
+ false -> {append(CP1,Head), Tail}
+ end;
+ true ->
+ {Head, Tail} = take_tc(Cont, 0, Seps),
+ {append(CP1,Head), Tail}
+ end;
+take_tc([Bin|Cont0], N, {GCs,_,_}=Seps0) when is_binary(Bin) ->
<<_:N/binary, Rest/binary>> = Bin,
- case bin_search_inv(Rest, Cont0, Sep) of
+ case bin_search_inv(Rest, Cont0, GCs) of
{nomatch,Cont} ->
Used = cp_prefix(Cont0, Cont),
- {Head, Tail} = take_tc(Cont, 0, Sep),
+ {Head, Tail} = take_tc(Cont, 0, Seps0),
{stack(unicode:characters_to_binary([Bin|Used]), Head), Tail};
[SepStart|Cont1] ->
- case bin_search(SepStart, Cont1, Sep) of
+ Seps = search_compile(Seps0),
+ case bin_search(SepStart, Cont1, Seps) of
{nomatch, Cont} ->
- {Head, Tail} = take_tc(Cont, 0, Sep),
+ {Head, Tail} = take_tc(Cont, 0, Seps),
Used = cp_prefix(Cont0, Cont),
- case equal(Tail, Cont) of
+ case is_empty(Head) of
true ->
KeepSz = byte_size(Bin) - byte_size(SepStart),
<<Keep:KeepSz/binary, End/binary>> = Bin,
- {stack(Keep,Head), stack(stack(End,Used),Tail)};
+ {Keep, stack(stack(End,Used),Tail)};
false ->
{stack(unicode:characters_to_binary([Bin|Used]),Head), Tail}
end;
[NonSep|Cont] when is_binary(NonSep) ->
KeepSz = byte_size(Bin) - byte_size(NonSep),
- take_tc([Bin|Cont], KeepSz, Sep)
+ take_tc([Bin|Cont], KeepSz, Seps)
end
end;
-take_tc(Str, 0, {GCs,CPs,_}=Sep) when is_list(Str) ->
- case unicode_util:cp(Str) of
- [CP|Cs] ->
- case lists:member(CP, CPs) of
- true ->
- [GC|Cs1] = unicode_util:gc(Str),
- case lists:member(GC, GCs) of
- false ->
- {Head, Tail} = take_tc(Cs1, 0, Sep),
- case equal(Tail, Cs1) of
- true -> {Head, append(GC,Tail)};
- false -> {append(GC,Head), Tail}
- end;
- true ->
- {Head, Tail} = take_tc(Cs1, 0, Sep),
- {append(GC,Head), Tail}
- end;
+take_tc(Str, 0, {GCs,_,_}=Seps) when is_list(Str) ->
+ case unicode_util:gc(Str) of
+ [GC|Cs1] ->
+ case lists:member(GC, GCs) of
false ->
- {Head, Tail} = take_tc(Cs, 0, Sep),
- case equal(Tail, Cs) of
- true -> {Head, append(CP,Tail)};
- false -> {append(CP,Head), Tail}
- end
+ {Head, Tail} = take_tc(Cs1, 0, Seps),
+ case is_empty(Head) of
+ true -> {Head, append(GC,Tail)};
+ false -> {append(GC,Head), Tail}
+ end;
+ true ->
+ {Head, Tail} = take_tc(Cs1, 0, Seps),
+ {append(GC,Head), Tail}
end;
[] -> {[],[]}
end;
-take_tc(Bin, N, Sep) when is_binary(Bin) ->
+take_tc(Bin, N, {GCs,_,_}=Seps0) when is_binary(Bin) ->
<<_:N/binary, Rest/binary>> = Bin,
- case bin_search_inv(Rest, [], Sep) of
+ case bin_search_inv(Rest, [], GCs) of
{nomatch,_} -> {Bin, <<>>};
[SepStart] ->
- case bin_search(SepStart, [], Sep) of
+ Seps = search_compile(Seps0),
+ case bin_search(SepStart, [], Seps) of
{nomatch,_} ->
KeepSz = byte_size(Bin) - byte_size(SepStart),
<<Before:KeepSz/binary, End/binary>> = Bin,
{Before, End};
[NonSep] ->
KeepSz = byte_size(Bin) - byte_size(NonSep),
- take_tc(Bin, KeepSz, Sep)
+ take_tc(Bin, KeepSz, Seps)
end
end.
-prefix_1(Cs, []) -> Cs;
-prefix_1(Cs, [_]=Pre) ->
- prefix_2(unicode_util:gc(Cs), Pre);
-prefix_1(Cs, Pre) ->
- prefix_2(unicode_util:cp(Cs), Pre).
-
-prefix_2([C|Cs], [C|Pre]) ->
- prefix_1(Cs, Pre);
-prefix_2(_, _) ->
- nomatch.
+prefix_1(Cs0, [GC]) ->
+ case unicode_util:gc(Cs0) of
+ [GC|Cs] -> Cs;
+ _ -> nomatch
+ end;
+prefix_1([CP|Cs], [Pre|PreR]) when is_integer(CP) ->
+ case CP =:= Pre of
+ true -> prefix_1(Cs,PreR);
+ false -> nomatch
+ end;
+prefix_1(<<CP/utf8, Cs/binary>>, [Pre|PreR]) ->
+ case CP =:= Pre of
+ true -> prefix_1(Cs,PreR);
+ false -> nomatch
+ end;
+prefix_1(Cs0, [Pre|PreR]) ->
+ case unicode_util:cp(Cs0) of
+ [Pre|Cs] -> prefix_1(Cs,PreR);
+ _ -> nomatch
+ end.
+split_1([CP1|Cs]=Cs0, [C|_]=Needle, _, Where, Curr, Acc) when is_integer(CP1) ->
+ case CP1=:=C of
+ true ->
+ case prefix_1(Cs0, Needle) of
+ nomatch -> split_1(Cs, Needle, 0, Where, append(C,Curr), Acc);
+ Rest when Where =:= leading ->
+ [rev(Curr), Rest];
+ Rest when Where =:= trailing ->
+ split_1(Cs, Needle, 0, Where, [C|Curr], [rev(Curr), Rest]);
+ Rest when Where =:= all ->
+ split_1(Rest, Needle, 0, Where, [], [rev(Curr)|Acc])
+ end;
+ false ->
+ split_1(Cs, Needle, 0, Where, append(CP1,Curr), Acc)
+ end;
split_1([Bin|Cont0], Needle, Start, Where, Curr0, Acc)
when is_binary(Bin) ->
case bin_search_str(Bin, Start, Cont0, Needle) of
@@ -971,32 +1247,50 @@ split_1(Bin, [_C|_]=Needle, Start, Where, Curr0, Acc) ->
end
end.
-lexemes_m([Bin|Cont0], Seps, Ts) when is_binary(Bin) ->
- case bin_search_inv(Bin, Cont0, Seps) of
+lexemes_m([CP|_]=Cs0, {GCs,CPs,_}=Seps, Ts) when is_integer(CP) ->
+ case lists:member(CP, CPs) of
+ true ->
+ [GC|Cs2] = unicode_util:gc(Cs0),
+ case lists:member(GC, GCs) of
+ true ->
+ lexemes_m(Cs2, Seps, Ts);
+ false ->
+ {Lexeme,Rest} = lexeme_pick(Cs0, Seps, []),
+ lexemes_m(Rest, Seps, [Lexeme|Ts])
+ end;
+ false ->
+ {Lexeme,Rest} = lexeme_pick(Cs0, Seps, []),
+ lexemes_m(Rest, Seps, [Lexeme|Ts])
+ end;
+lexemes_m([Bin|Cont0], {GCs,_,_}=Seps0, Ts) when is_binary(Bin) ->
+ case bin_search_inv(Bin, Cont0, GCs) of
{nomatch,Cont} ->
- lexemes_m(Cont, Seps, Ts);
+ lexemes_m(Cont, Seps0, Ts);
Cs ->
+ Seps = search_compile(Seps0),
{Lexeme,Rest} = lexeme_pick(Cs, Seps, []),
lexemes_m(Rest, Seps, [Lexeme|Ts])
end;
-lexemes_m(Cs0, {GCs, _, _}=Seps, Ts) when is_list(Cs0) ->
+lexemes_m(Cs0, {GCs, _, _}=Seps0, Ts) when is_list(Cs0) ->
case unicode_util:gc(Cs0) of
[C|Cs] ->
case lists:member(C, GCs) of
true ->
- lexemes_m(Cs, Seps, Ts);
+ lexemes_m(Cs, Seps0, Ts);
false ->
+ Seps = search_compile(Seps0),
{Lexeme,Rest} = lexeme_pick(Cs0, Seps, []),
lexemes_m(Rest, Seps, [Lexeme|Ts])
end;
[] ->
lists:reverse(Ts)
end;
-lexemes_m(Bin, Seps, Ts) when is_binary(Bin) ->
- case bin_search_inv(Bin, [], Seps) of
+lexemes_m(Bin, {GCs,_,_}=Seps0, Ts) when is_binary(Bin) ->
+ case bin_search_inv(Bin, [], GCs) of
{nomatch,_} ->
lists:reverse(Ts);
[Cs] ->
+ Seps = search_compile(Seps0),
{Lexeme,Rest} = lexeme_pick(Cs, Seps, []),
lexemes_m(Rest, Seps, add_non_empty(Lexeme,Ts))
end.
@@ -1027,7 +1321,7 @@ lexeme_pick(Cs0, {GCs, CPs, _} = Seps, Tkn) when is_list(Cs0) ->
true ->
[GC|Cs2] = unicode_util:gc(Cs0),
case lists:member(GC, GCs) of
- true -> {rev(Tkn), Cs0};
+ true -> {rev(Tkn), Cs2};
false -> lexeme_pick(Cs2, Seps, append(rev(GC),Tkn))
end;
false ->
@@ -1037,7 +1331,7 @@ lexeme_pick(Cs0, {GCs, CPs, _} = Seps, Tkn) when is_list(Cs0) ->
{rev(Tkn), []}
end;
lexeme_pick(Bin, Seps, Tkn) when is_binary(Bin) ->
- case bin_search(Bin, Seps) of
+ case bin_search(Bin, [], Seps) of
{nomatch,_} ->
{btoken(Bin,Tkn), []};
[Left] ->
@@ -1046,35 +1340,38 @@ lexeme_pick(Bin, Seps, Tkn) when is_binary(Bin) ->
{btoken(Lexeme, Tkn), Left}
end.
-nth_lexeme_m([Bin|Cont0], Seps, N) when is_binary(Bin) ->
- case bin_search_inv(Bin, Cont0, Seps) of
+nth_lexeme_m([Bin|Cont0], {GCs,_,_}=Seps0, N) when is_binary(Bin) ->
+ case bin_search_inv(Bin, Cont0, GCs) of
{nomatch,Cont} ->
- nth_lexeme_m(Cont, Seps, N);
+ nth_lexeme_m(Cont, Seps0, N);
Cs when N > 1 ->
- Rest = lexeme_skip(Cs, Seps),
- nth_lexeme_m(Rest, Seps, N-1);
+ Rest = lexeme_skip(Cs, Seps0),
+ nth_lexeme_m(Rest, Seps0, N-1);
Cs ->
+ Seps = search_compile(Seps0),
{Lexeme,_} = lexeme_pick(Cs, Seps, []),
Lexeme
end;
-nth_lexeme_m(Cs0, {GCs, _, _}=Seps, N) when is_list(Cs0) ->
+nth_lexeme_m(Cs0, {GCs, _, _}=Seps0, N) when is_list(Cs0) ->
case unicode_util:gc(Cs0) of
[C|Cs] ->
case lists:member(C, GCs) of
true ->
- nth_lexeme_m(Cs, Seps, N);
+ nth_lexeme_m(Cs, Seps0, N);
false when N > 1 ->
- Cs1 = lexeme_skip(Cs, Seps),
- nth_lexeme_m(Cs1, Seps, N-1);
+ Cs1 = lexeme_skip(Cs, Seps0),
+ nth_lexeme_m(Cs1, Seps0, N-1);
false ->
+ Seps = search_compile(Seps0),
{Lexeme,_} = lexeme_pick(Cs0, Seps, []),
Lexeme
end;
[] ->
[]
end;
-nth_lexeme_m(Bin, Seps, N) when is_binary(Bin) ->
- case bin_search_inv(Bin, [], Seps) of
+nth_lexeme_m(Bin, {GCs,_,_}=Seps0, N) when is_binary(Bin) ->
+ Seps = search_compile(Seps0),
+ case bin_search_inv(Bin, [], GCs) of
[Cs] when N > 1 ->
Cs1 = lexeme_skip(Cs, Seps),
nth_lexeme_m(Cs1, Seps, N-1);
@@ -1090,16 +1387,17 @@ lexeme_skip([CP|Cs1]=Cs0, {GCs,CPs,_}=Seps) when is_integer(CP) ->
true ->
[GC|Cs2] = unicode_util:gc(Cs0),
case lists:member(GC, GCs) of
- true -> Cs0;
+ true -> Cs2;
false -> lexeme_skip(Cs2, Seps)
end;
false ->
lexeme_skip(Cs1, Seps)
end;
-lexeme_skip([Bin|Cont0], Seps) when is_binary(Bin) ->
+lexeme_skip([Bin|Cont0], Seps0) when is_binary(Bin) ->
+ Seps = search_compile(Seps0),
case bin_search(Bin, Cont0, Seps) of
{nomatch,_} -> lexeme_skip(Cont0, Seps);
- Cs -> Cs
+ Cs -> tl(unicode_util:gc(Cs))
end;
lexeme_skip(Cs0, {GCs, CPs, _} = Seps) when is_list(Cs0) ->
case unicode_util:cp(Cs0) of
@@ -1108,7 +1406,7 @@ lexeme_skip(Cs0, {GCs, CPs, _} = Seps) when is_list(Cs0) ->
true ->
[GC|Cs2] = unicode_util:gc(Cs0),
case lists:member(GC, GCs) of
- true -> Cs0;
+ true -> Cs2;
false -> lexeme_skip(Cs2, Seps)
end;
false ->
@@ -1117,12 +1415,23 @@ lexeme_skip(Cs0, {GCs, CPs, _} = Seps) when is_list(Cs0) ->
[] ->
[]
end;
-lexeme_skip(Bin, Seps) when is_binary(Bin) ->
- case bin_search(Bin, Seps) of
+lexeme_skip(Bin, Seps0) when is_binary(Bin) ->
+ Seps = search_compile(Seps0),
+ case bin_search(Bin, [], Seps) of
{nomatch,_} -> <<>>;
- [Left] -> Left
+ [Left] -> tl(unicode_util:gc(Left))
end.
+find_l([C1|Cs]=Cs0, [C|_]=Needle) when is_integer(C1) ->
+ case C1 of
+ C ->
+ case prefix_1(Cs0, Needle) of
+ nomatch -> find_l(Cs, Needle);
+ _ -> Cs0
+ end;
+ _ ->
+ find_l(Cs, Needle)
+ end;
find_l([Bin|Cont0], Needle) when is_binary(Bin) ->
case bin_search_str(Bin, 0, Cont0, Needle) of
{nomatch, _, Cont} ->
@@ -1147,6 +1456,16 @@ find_l(Bin, Needle) ->
{_Before, [Cs], _After} -> Cs
end.
+find_r([Cp|Cs]=Cs0, [C|_]=Needle, Res) when is_integer(Cp) ->
+ case Cp of
+ C ->
+ case prefix_1(Cs0, Needle) of
+ nomatch -> find_r(Cs, Needle, Res);
+ _ -> find_r(Cs, Needle, Cs0)
+ end;
+ _ ->
+ find_r(Cs, Needle, Res)
+ end;
find_r([Bin|Cont0], Needle, Res) when is_binary(Bin) ->
case bin_search_str(Bin, 0, Cont0, Needle) of
{nomatch,_,Cont} ->
@@ -1217,11 +1536,6 @@ cp_prefix_1(Orig, Until, Cont) ->
%% Binary special
-bin_search(Bin, Seps) ->
- bin_search(Bin, [], Seps).
-
-bin_search(_Bin, Cont, {[],_,_}) ->
- {nomatch, Cont};
bin_search(Bin, Cont, {Seps,_,BP}) ->
bin_search_loop(Bin, 0, BP, Cont, Seps).
@@ -1229,10 +1543,14 @@ bin_search(Bin, Cont, {Seps,_,BP}) ->
%% i.e. å in nfd form $a "COMBINING RING ABOVE"
%% and PREPEND characters like "ARABIC NUMBER SIGN" 1536 <<216,128>>
%% combined with other characters are currently ignored.
+search_pattern({_,_,_}=P) -> P;
search_pattern(Seps) ->
CPs = search_cp(Seps),
- Bin = bin_pattern(CPs),
- {Seps, CPs, Bin}.
+ {Seps, CPs, undefined}.
+
+search_compile({Sep, CPs, undefined}) ->
+ {Sep, CPs, binary:compile_pattern(bin_pattern(CPs))};
+search_compile({_,_,_}=Compiled) -> Compiled.
search_cp([CP|Seps]) when is_integer(CP) ->
[CP|search_cp(Seps)];
@@ -1253,9 +1571,21 @@ bin_search_loop(Bin0, Start, BinSeps, Cont, Seps) ->
case binary:match(Bin, BinSeps) of
nomatch ->
{nomatch,Cont};
+ {Where, _CL} when Cont =:= [] ->
+ <<_:Where/binary, Cont1/binary>> = Bin,
+ [GC|Cont2] = unicode_util:gc(Cont1),
+ case lists:member(GC, Seps) of
+ false when Cont2 =:= [] ->
+ {nomatch, []};
+ false ->
+ Next = byte_size(Bin0) - byte_size(Cont2),
+ bin_search_loop(Bin0, Next, BinSeps, Cont, Seps);
+ true ->
+ [Cont1]
+ end;
{Where, _CL} ->
<<_:Where/binary, Cont0/binary>> = Bin,
- Cont1 = stack(Cont0, Cont),
+ Cont1 = [Cont0|Cont],
[GC|Cont2] = unicode_util:gc(Cont1),
case lists:member(GC, Seps) of
false ->
@@ -1263,55 +1593,108 @@ bin_search_loop(Bin0, Start, BinSeps, Cont, Seps) ->
[BinR|Cont] when is_binary(BinR) ->
Next = byte_size(Bin0) - byte_size(BinR),
bin_search_loop(Bin0, Next, BinSeps, Cont, Seps);
- BinR when is_binary(BinR), Cont =:= [] ->
- Next = byte_size(Bin0) - byte_size(BinR),
- bin_search_loop(Bin0, Next, BinSeps, Cont, Seps);
_ ->
{nomatch, Cont2}
end;
- true when is_list(Cont1) ->
- Cont1;
true ->
- [Cont1]
+ Cont1
end
end.
-bin_search_inv(Bin, Cont, {[], _, _}) ->
- [Bin|Cont];
-bin_search_inv(Bin, Cont, {[Sep], _, _}) ->
- bin_search_inv_1([Bin|Cont], Sep);
-bin_search_inv(Bin, Cont, {Seps, _, _}) ->
- bin_search_inv_n([Bin|Cont], Seps).
-
-bin_search_inv_1([<<>>|CPs], _) ->
- {nomatch, CPs};
-bin_search_inv_1(CPs = [Bin0|Cont], Sep) when is_binary(Bin0) ->
- case unicode_util:gc(CPs) of
- [Sep|Bin] when is_binary(Bin), Cont =:= [] ->
- bin_search_inv_1([Bin], Sep);
- [Sep|[Bin|Cont]=Cs] when is_binary(Bin) ->
- bin_search_inv_1(Cs, Sep);
- [Sep|Cs] ->
- {nomatch, Cs};
- _ -> CPs
- end.
+bin_search_inv(<<>>, Cont, _) ->
+ {nomatch, Cont};
+bin_search_inv(Bin, Cont, [Sep]) ->
+ bin_search_inv_1(Bin, Cont, Sep);
+bin_search_inv(Bin, Cont, Seps) ->
+ bin_search_inv_n(Bin, Cont, Seps).
+
+bin_search_inv_1(<<CP1/utf8, BinRest/binary>>=Bin0, Cont, Sep) ->
+ case BinRest of
+ <<CP2/utf8, _/binary>> when ?ASCII_LIST(CP1, CP2) ->
+ case CP1 of
+ Sep -> bin_search_inv_1(BinRest, Cont, Sep);
+ _ -> [Bin0|Cont]
+ end;
+ _ when Cont =:= [] ->
+ case unicode_util:gc(Bin0) of
+ [Sep|Bin] -> bin_search_inv_1(Bin, Cont, Sep);
+ _ -> [Bin0|Cont]
+ end;
+ _ ->
+ case unicode_util:gc([Bin0|Cont]) of
+ [Sep|[Bin|Cont]] when is_binary(Bin) ->
+ bin_search_inv_1(Bin, Cont, Sep);
+ [Sep|Cs] ->
+ {nomatch, Cs};
+ _ -> [Bin0|Cont]
+ end
+ end;
+bin_search_inv_1(<<>>, Cont, _Sep) ->
+ {nomatch, Cont};
+bin_search_inv_1([], Cont, _Sep) ->
+ {nomatch, Cont}.
-bin_search_inv_n([<<>>|CPs], _) ->
- {nomatch, CPs};
-bin_search_inv_n([Bin0|Cont]=CPs, Seps) when is_binary(Bin0) ->
- [C|Cs0] = unicode_util:gc(CPs),
- case {lists:member(C, Seps), Cs0} of
- {true, Cs} when is_binary(Cs), Cont =:= [] ->
- bin_search_inv_n([Cs], Seps);
- {true, [Bin|Cont]=Cs} when is_binary(Bin) ->
- bin_search_inv_n(Cs, Seps);
- {true, Cs} -> {nomatch, Cs};
- {false, _} -> CPs
- end.
+bin_search_inv_n(<<CP1/utf8, BinRest/binary>>=Bin0, Cont, Seps) ->
+ case BinRest of
+ <<CP2/utf8, _/binary>> when ?ASCII_LIST(CP1, CP2) ->
+ case lists:member(CP1,Seps) of
+ true -> bin_search_inv_n(BinRest, Cont, Seps);
+ false -> [Bin0|Cont]
+ end;
+ _ when Cont =:= [] ->
+ [GC|Bin] = unicode_util:gc(Bin0),
+ case lists:member(GC, Seps) of
+ true -> bin_search_inv_n(Bin, Cont, Seps);
+ false -> [Bin0|Cont]
+ end;
+ _ ->
+ [GC|Cs0] = unicode_util:gc([Bin0|Cont]),
+ case lists:member(GC, Seps) of
+ false -> [Bin0|Cont];
+ true ->
+ case Cs0 of
+ [Bin|Cont] when is_binary(Bin) ->
+ bin_search_inv_n(Bin, Cont, Seps);
+ _ ->
+ {nomatch, Cs0}
+ end
+ end
+ end;
+bin_search_inv_n(<<>>, Cont, _Sep) ->
+ {nomatch, Cont};
+bin_search_inv_n([], Cont, _Sep) ->
+ {nomatch, Cont}.
+
+bin_search_str(Bin0, Start, [], SearchCPs) ->
+ Compiled = binary:compile_pattern(unicode:characters_to_binary(SearchCPs)),
+ bin_search_str_1(Bin0, Start, Compiled, SearchCPs);
bin_search_str(Bin0, Start, Cont, [CP|_]=SearchCPs) ->
+ First = binary:compile_pattern(<<CP/utf8>>),
+ bin_search_str_2(Bin0, Start, Cont, First, SearchCPs).
+
+bin_search_str_1(Bin0, Start, First, SearchCPs) ->
+ <<_:Start/binary, Bin/binary>> = Bin0,
+ case binary:match(Bin, First) of
+ nomatch -> {nomatch, byte_size(Bin0), []};
+ {Where0, _} ->
+ Where = Start+Where0,
+ <<Keep:Where/binary, Cs0/binary>> = Bin0,
+ case prefix_1(Cs0, SearchCPs) of
+ nomatch ->
+ <<_/utf8, Cs/binary>> = Cs0,
+ KeepSz = byte_size(Bin0) - byte_size(Cs),
+ bin_search_str_1(Bin0, KeepSz, First, SearchCPs);
+ [] ->
+ {Keep, [Cs0], <<>>};
+ Rest ->
+ {Keep, [Cs0], Rest}
+ end
+ end.
+
+bin_search_str_2(Bin0, Start, Cont, First, SearchCPs) ->
<<_:Start/binary, Bin/binary>> = Bin0,
- case binary:match(Bin, <<CP/utf8>>) of
+ case binary:match(Bin, First) of
nomatch -> {nomatch, byte_size(Bin0), Cont};
{Where0, _} ->
Where = Start+Where0,
@@ -1320,7 +1703,7 @@ bin_search_str(Bin0, Start, Cont, [CP|_]=SearchCPs) ->
case prefix_1(stack(Cs0,Cont), SearchCPs) of
nomatch when is_binary(Cs) ->
KeepSz = byte_size(Bin0) - byte_size(Cs),
- bin_search_str(Bin0, KeepSz, Cont, SearchCPs);
+ bin_search_str_2(Bin0, KeepSz, Cont, First, SearchCPs);
nomatch ->
{nomatch, Where, stack([GC|Cs],Cont)};
[] ->
@@ -1344,7 +1727,7 @@ bin_search_str(Bin0, Start, Cont, [CP|_]=SearchCPs) ->
String :: string(),
Length :: non_neg_integer().
-len(S) -> length(S).
+len(S) -> erlang:length(S).
%% equal(String1, String2)
%% Test if 2 strings are equal.
@@ -1689,7 +2072,7 @@ left(String, Len) when is_integer(Len) -> left(String, Len, $\s).
Character :: char().
left(String, Len, Char) when is_integer(Char) ->
- Slen = length(String),
+ Slen = erlang:length(String),
if
Slen > Len -> substr(String, 1, Len);
Slen < Len -> l_pad(String, Len-Slen, Char);
@@ -1714,7 +2097,7 @@ right(String, Len) when is_integer(Len) -> right(String, Len, $\s).
Character :: char().
right(String, Len, Char) when is_integer(Char) ->
- Slen = length(String),
+ Slen = erlang:length(String),
if
Slen > Len -> substr(String, Slen-Len+1);
Slen < Len -> r_pad(String, Len-Slen, Char);
@@ -1741,7 +2124,7 @@ centre(String, Len) when is_integer(Len) -> centre(String, Len, $\s).
centre(String, 0, Char) when is_list(String), is_integer(Char) ->
[]; % Strange cases to centre string
centre(String, Len, Char) when is_integer(Char) ->
- Slen = length(String),
+ Slen = erlang:length(String),
if
Slen > Len -> substr(String, (Slen-Len) div 2 + 1, Len);
Slen < Len ->
diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl
index 1cd65fbf18..1ac7334830 100644
--- a/lib/stdlib/src/supervisor.erl
+++ b/lib/stdlib/src/supervisor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,11 +31,24 @@
%% Internal exports
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3, format_status/2]).
--export([try_again_restart/2]).
%% For release_handler only
-export([get_callback_module/1]).
+-include("logger.hrl").
+
+-define(report_error(Error, Reason, Child, SupName),
+ ?LOG_ERROR(#{label=>{supervisor,Error},
+ report=>[{supervisor,SupName},
+ {errorContext,Error},
+ {reason,Reason},
+ {offender,extract_child(Child)}]},
+ #{domain=>[otp,sasl],
+ report_cb=>fun logger:format_otp_report/1,
+ logger_formatter=>#{title=>"SUPERVISOR REPORT"},
+ error_logger=>#{tag=>error_report,
+ type=>supervisor_report}})).
+
%%--------------------------------------------------------------------------
-export_type([sup_flags/0, child_spec/0, startchild_ret/0, strategy/0]).
@@ -79,6 +92,7 @@
| {RestartStrategy :: strategy(),
Intensity :: non_neg_integer(),
Period :: pos_integer()}.
+-type children() :: {Ids :: [child_id()], Db :: #{child_id() => child_rec()}}.
%%--------------------------------------------------------------------------
%% Defaults
@@ -96,7 +110,7 @@
pid = undefined :: child()
| {restarting, pid() | undefined}
| [pid()],
- name :: child_id(),
+ id :: child_id(),
mfargs :: mfargs(),
restart_type :: restart(),
shutdown :: shutdown(),
@@ -104,16 +118,11 @@
modules = [] :: modules()}).
-type child_rec() :: #child{}.
--define(DICTS, dict).
--define(DICT, dict:dict).
--define(SETS, sets).
--define(SET, sets:set).
-
-record(state, {name,
strategy :: strategy() | 'undefined',
- children = [] :: [child_rec()],
- dynamics :: {'dict', ?DICT(pid(), list())}
- | {'set', ?SET(pid())}
+ children = {[],#{}} :: children(), % Ids in start order
+ dynamics :: {'maps', #{pid() => list()}}
+ | {'sets', sets:set(pid())}
| 'undefined',
intensity :: non_neg_integer() | 'undefined',
period :: pos_integer() | 'undefined',
@@ -124,6 +133,9 @@
-type state() :: #state{}.
-define(is_simple(State), State#state.strategy =:= simple_one_for_one).
+-define(is_temporary(_Child_), _Child_#child.restart_type=:=temporary).
+-define(is_transient(_Child_), _Child_#child.restart_type=:=transient).
+-define(is_permanent(_Child_), _Child_#child.restart_type=:=permanent).
-callback init(Args :: term()) ->
{ok, {SupFlags :: sup_flags(), [ChildSpec :: child_spec()]}}
@@ -179,16 +191,16 @@ start_child(Supervisor, ChildSpec) ->
| {'error', Error},
Error :: 'running' | 'restarting' | 'not_found' | 'simple_one_for_one' |
term().
-restart_child(Supervisor, Name) ->
- call(Supervisor, {restart_child, Name}).
+restart_child(Supervisor, Id) ->
+ call(Supervisor, {restart_child, Id}).
-spec delete_child(SupRef, Id) -> Result when
SupRef :: sup_ref(),
Id :: child_id(),
Result :: 'ok' | {'error', Error},
Error :: 'running' | 'restarting' | 'not_found' | 'simple_one_for_one'.
-delete_child(Supervisor, Name) ->
- call(Supervisor, {delete_child, Name}).
+delete_child(Supervisor, Id) ->
+ call(Supervisor, {delete_child, Id}).
%%-----------------------------------------------------------------
%% Func: terminate_child/2
@@ -202,16 +214,16 @@ delete_child(Supervisor, Name) ->
Id :: pid() | child_id(),
Result :: 'ok' | {'error', Error},
Error :: 'not_found' | 'simple_one_for_one'.
-terminate_child(Supervisor, Name) ->
- call(Supervisor, {terminate_child, Name}).
+terminate_child(Supervisor, Id) ->
+ call(Supervisor, {terminate_child, Id}).
-spec get_childspec(SupRef, Id) -> Result when
SupRef :: sup_ref(),
Id :: pid() | child_id(),
Result :: {'ok', child_spec()} | {'error', Error},
Error :: 'not_found'.
-get_childspec(Supervisor, Name) ->
- call(Supervisor, {get_childspec, Name}).
+get_childspec(Supervisor, Id) ->
+ call(Supervisor, {get_childspec, Id}).
-spec which_children(SupRef) -> [{Id,Child,Type,Modules}] when
SupRef :: sup_ref(),
@@ -246,17 +258,6 @@ check_childspecs(ChildSpecs) when is_list(ChildSpecs) ->
check_childspecs(X) -> {error, {badarg, X}}.
%%%-----------------------------------------------------------------
-%%% Called by restart/2
--spec try_again_restart(SupRef, Child) -> ok when
- SupRef :: sup_ref(),
- Child :: child_id() | pid().
-try_again_restart(Supervisor, Child) ->
- cast(Supervisor, {try_again_restart, Child}).
-
-cast(Supervisor, Req) ->
- gen_server:cast(Supervisor, Req).
-
-%%%-----------------------------------------------------------------
%%% Called by release_handler during upgrade
-spec get_callback_module(Pid) -> Module when
Pid :: pid(),
@@ -325,7 +326,7 @@ init_children(State, StartSpec) ->
init_dynamic(State, [StartSpec]) ->
case check_startspec([StartSpec]) of
{ok, Children} ->
- {ok, State#state{children = Children}};
+ {ok, dyn_init(State#state{children = Children})};
Error ->
{stop, {start_spec, Error}}
end;
@@ -334,35 +335,34 @@ init_dynamic(_State, StartSpec) ->
%%-----------------------------------------------------------------
%% Func: start_children/2
-%% Args: Children = [child_rec()] in start order
+%% Args: Children = children() % Ids in start order
%% SupName = {local, atom()} | {global, atom()} | {pid(), Mod}
-%% Purpose: Start all children. The new list contains #child's
+%% Purpose: Start all children. The new map contains #child's
%% with pids.
%% Returns: {ok, NChildren} | {error, NChildren, Reason}
-%% NChildren = [child_rec()] in termination order (reversed
-%% start order)
+%% NChildren = children() % Ids in termination order
+%% (reversed start order)
%%-----------------------------------------------------------------
-start_children(Children, SupName) -> start_children(Children, [], SupName).
-
-start_children([Child|Chs], NChildren, SupName) ->
- case do_start_child(SupName, Child) of
- {ok, undefined} when Child#child.restart_type =:= temporary ->
- start_children(Chs, NChildren, SupName);
- {ok, Pid} ->
- start_children(Chs, [Child#child{pid = Pid}|NChildren], SupName);
- {ok, Pid, _Extra} ->
- start_children(Chs, [Child#child{pid = Pid}|NChildren], SupName);
- {error, Reason} ->
- report_error(start_error, Reason, Child, SupName),
- {error, lists:reverse(Chs) ++ [Child | NChildren],
- {failed_to_start_child,Child#child.name,Reason}}
- end;
-start_children([], NChildren, _SupName) ->
- {ok, NChildren}.
+start_children(Children, SupName) ->
+ Start =
+ fun(Id,Child) ->
+ case do_start_child(SupName, Child) of
+ {ok, undefined} when ?is_temporary(Child) ->
+ remove;
+ {ok, Pid} ->
+ {update,Child#child{pid = Pid}};
+ {ok, Pid, _Extra} ->
+ {update,Child#child{pid = Pid}};
+ {error, Reason} ->
+ ?report_error(start_error, Reason, Child, SupName),
+ {abort,{failed_to_start_child,Id,Reason}}
+ end
+ end,
+ children_map(Start,Children).
do_start_child(SupName, Child) ->
#child{mfargs = {M, F, Args}} = Child,
- case catch apply(M, F, Args) of
+ case do_start_child_i(M, F, Args) of
{ok, Pid} when is_pid(Pid) ->
NChild = Child#child{pid = Pid},
report_progress(NChild, SupName),
@@ -371,10 +371,8 @@ do_start_child(SupName, Child) ->
NChild = Child#child{pid = Pid},
report_progress(NChild, SupName),
{ok, Pid, Extra};
- ignore ->
- {ok, undefined};
- {error, What} -> {error, What};
- What -> {error, What}
+ Other ->
+ Other
end.
do_start_child_i(M, F, A) ->
@@ -400,17 +398,17 @@ do_start_child_i(M, F, A) ->
-spec handle_call(call(), term(), state()) -> {'reply', term(), state()}.
handle_call({start_child, EArgs}, _From, State) when ?is_simple(State) ->
- Child = hd(State#state.children),
+ Child = get_dynamic_child(State),
#child{mfargs = {M, F, A}} = Child,
Args = A ++ EArgs,
case do_start_child_i(M, F, Args) of
{ok, undefined} ->
{reply, {ok, undefined}, State};
{ok, Pid} ->
- NState = save_dynamic_child(Child#child.restart_type, Pid, Args, State),
+ NState = dyn_store(Pid, Args, State),
{reply, {ok, Pid}, NState};
{ok, Pid, Extra} ->
- NState = save_dynamic_child(Child#child.restart_type, Pid, Args, State),
+ NState = dyn_store(Pid, Args, State),
{reply, {ok, Pid, Extra}, NState};
What ->
{reply, What, State}
@@ -426,121 +424,94 @@ handle_call({start_child, ChildSpec}, _From, State) ->
end;
%% terminate_child for simple_one_for_one can only be done with pid
-handle_call({terminate_child, Name}, _From, State) when not is_pid(Name),
- ?is_simple(State) ->
+handle_call({terminate_child, Id}, _From, State) when not is_pid(Id),
+ ?is_simple(State) ->
{reply, {error, simple_one_for_one}, State};
-handle_call({terminate_child, Name}, _From, State) ->
- case get_child(Name, State, ?is_simple(State)) of
- {value, Child} ->
- case do_terminate(Child, State#state.name) of
- #child{restart_type=RT} when RT=:=temporary; ?is_simple(State) ->
- {reply, ok, state_del_child(Child, State)};
- NChild ->
- {reply, ok, replace_child(NChild, State)}
- end;
- false ->
+handle_call({terminate_child, Id}, _From, State) ->
+ case find_child(Id, State) of
+ {ok, Child} ->
+ do_terminate(Child, State#state.name),
+ {reply, ok, del_child(Child, State)};
+ error ->
{reply, {error, not_found}, State}
end;
%% restart_child request is invalid for simple_one_for_one supervisors
-handle_call({restart_child, _Name}, _From, State) when ?is_simple(State) ->
+handle_call({restart_child, _Id}, _From, State) when ?is_simple(State) ->
{reply, {error, simple_one_for_one}, State};
-handle_call({restart_child, Name}, _From, State) ->
- case get_child(Name, State) of
- {value, Child} when Child#child.pid =:= undefined ->
+handle_call({restart_child, Id}, _From, State) ->
+ case find_child(Id, State) of
+ {ok, Child} when Child#child.pid =:= undefined ->
case do_start_child(State#state.name, Child) of
{ok, Pid} ->
- NState = replace_child(Child#child{pid = Pid}, State),
+ NState = set_pid(Pid, Id, State),
{reply, {ok, Pid}, NState};
{ok, Pid, Extra} ->
- NState = replace_child(Child#child{pid = Pid}, State),
+ NState = set_pid(Pid, Id, State),
{reply, {ok, Pid, Extra}, NState};
Error ->
{reply, Error, State}
end;
- {value, #child{pid=?restarting(_)}} ->
+ {ok, #child{pid=?restarting(_)}} ->
{reply, {error, restarting}, State};
- {value, _} ->
+ {ok, _} ->
{reply, {error, running}, State};
_ ->
{reply, {error, not_found}, State}
end;
%% delete_child request is invalid for simple_one_for_one supervisors
-handle_call({delete_child, _Name}, _From, State) when ?is_simple(State) ->
+handle_call({delete_child, _Id}, _From, State) when ?is_simple(State) ->
{reply, {error, simple_one_for_one}, State};
-handle_call({delete_child, Name}, _From, State) ->
- case get_child(Name, State) of
- {value, Child} when Child#child.pid =:= undefined ->
- NState = remove_child(Child, State),
+handle_call({delete_child, Id}, _From, State) ->
+ case find_child(Id, State) of
+ {ok, Child} when Child#child.pid =:= undefined ->
+ NState = remove_child(Id, State),
{reply, ok, NState};
- {value, #child{pid=?restarting(_)}} ->
+ {ok, #child{pid=?restarting(_)}} ->
{reply, {error, restarting}, State};
- {value, _} ->
+ {ok, _} ->
{reply, {error, running}, State};
_ ->
{reply, {error, not_found}, State}
end;
-handle_call({get_childspec, Name}, _From, State) ->
- case get_child(Name, State, ?is_simple(State)) of
- {value, Child} ->
+handle_call({get_childspec, Id}, _From, State) ->
+ case find_child(Id, State) of
+ {ok, Child} ->
{reply, {ok, child_to_spec(Child)}, State};
- false ->
+ error ->
{reply, {error, not_found}, State}
end;
-handle_call(which_children, _From, #state{children = [#child{restart_type = temporary,
- child_type = CT,
- modules = Mods}]} =
- State) when ?is_simple(State) ->
- Reply = lists:map(fun(Pid) -> {undefined, Pid, CT, Mods} end,
- ?SETS:to_list(dynamics_db(temporary, State#state.dynamics))),
- {reply, Reply, State};
-
-handle_call(which_children, _From, #state{children = [#child{restart_type = RType,
- child_type = CT,
- modules = Mods}]} =
- State) when ?is_simple(State) ->
- Reply = lists:map(fun({?restarting(_),_}) -> {undefined,restarting,CT,Mods};
- ({Pid, _}) -> {undefined, Pid, CT, Mods} end,
- ?DICTS:to_list(dynamics_db(RType, State#state.dynamics))),
+handle_call(which_children, _From, State) when ?is_simple(State) ->
+ #child{child_type = CT,modules = Mods} = get_dynamic_child(State),
+ Reply = dyn_map(fun(?restarting(_)) -> {undefined, restarting, CT, Mods};
+ (Pid) -> {undefined, Pid, CT, Mods}
+ end, State),
{reply, Reply, State};
handle_call(which_children, _From, State) ->
Resp =
- lists:map(fun(#child{pid = ?restarting(_), name = Name,
- child_type = ChildType, modules = Mods}) ->
- {Name, restarting, ChildType, Mods};
- (#child{pid = Pid, name = Name,
- child_type = ChildType, modules = Mods}) ->
- {Name, Pid, ChildType, Mods}
- end,
- State#state.children),
+ children_to_list(
+ fun(Id,#child{pid = ?restarting(_),
+ child_type = ChildType, modules = Mods}) ->
+ {Id, restarting, ChildType, Mods};
+ (Id,#child{pid = Pid,
+ child_type = ChildType, modules = Mods}) ->
+ {Id, Pid, ChildType, Mods}
+ end,
+ State#state.children),
{reply, Resp, State};
-
-handle_call(count_children, _From, #state{children = [#child{restart_type = temporary,
- child_type = CT}]} = State)
+handle_call(count_children, _From, #state{dynamic_restarts = Restarts} = State)
when ?is_simple(State) ->
- Sz = ?SETS:size(dynamics_db(temporary, State#state.dynamics)),
- Reply = case CT of
- supervisor -> [{specs, 1}, {active, Sz},
- {supervisors, Sz}, {workers, 0}];
- worker -> [{specs, 1}, {active, Sz},
- {supervisors, 0}, {workers, Sz}]
- end,
- {reply, Reply, State};
-
-handle_call(count_children, _From, #state{dynamic_restarts = Restarts,
- children = [#child{restart_type = RType,
- child_type = CT}]} = State)
- when ?is_simple(State) ->
- Sz = ?DICTS:size(dynamics_db(RType, State#state.dynamics)),
- Active = Sz - Restarts,
+ #child{child_type = CT} = get_dynamic_child(State),
+ Sz = dyn_size(State),
+ Active = Sz - Restarts, % Restarts is always 0 for temporary children
Reply = case CT of
supervisor -> [{specs, 1}, {active, Active},
{supervisors, Sz}, {workers, 0}];
@@ -552,16 +523,15 @@ handle_call(count_children, _From, #state{dynamic_restarts = Restarts,
handle_call(count_children, _From, State) ->
%% Specs and children are together on the children list...
{Specs, Active, Supers, Workers} =
- lists:foldl(fun(Child, Counts) ->
- count_child(Child, Counts)
- end, {0,0,0,0}, State#state.children),
+ children_fold(fun(_Id, Child, Counts) ->
+ count_child(Child, Counts)
+ end, {0,0,0,0}, State#state.children),
%% Reformat counts to a property list.
Reply = [{specs, Specs}, {active, Active},
{supervisors, Supers}, {workers, Workers}],
{reply, Reply, State}.
-
count_child(#child{pid = Pid, child_type = worker},
{Specs, Active, Supers, Workers}) ->
case is_pid(Pid) andalso is_process_alive(Pid) of
@@ -575,34 +545,15 @@ count_child(#child{pid = Pid, child_type = supervisor},
false -> {Specs+1, Active, Supers+1, Workers}
end.
-
%%% If a restart attempt failed, this message is cast
%%% from restart/2 in order to give gen_server the chance to
%%% check it's inbox before trying again.
--spec handle_cast({try_again_restart, child_id() | pid()}, state()) ->
+-spec handle_cast({try_again_restart, child_id() | {'restarting',pid()}}, state()) ->
{'noreply', state()} | {stop, shutdown, state()}.
-handle_cast({try_again_restart,Pid}, #state{children=[Child]}=State)
- when ?is_simple(State) ->
- RT = Child#child.restart_type,
- RPid = restarting(Pid),
- case dynamic_child_args(RPid, RT, State#state.dynamics) of
- {ok, Args} ->
- {M, F, _} = Child#child.mfargs,
- NChild = Child#child{pid = RPid, mfargs = {M, F, Args}},
- case restart(NChild,State) of
- {ok, State1} ->
- {noreply, State1};
- {shutdown, State1} ->
- {stop, shutdown, State1}
- end;
- error ->
- {noreply, State}
- end;
-
-handle_cast({try_again_restart,Name}, State) ->
- case lists:keyfind(Name,#child.name,State#state.children) of
- Child = #child{pid=?restarting(_)} ->
+handle_cast({try_again_restart,TryAgainId}, State) ->
+ case find_child_and_args(TryAgainId, State) of
+ {ok, Child = #child{pid=?restarting(_)}} ->
case restart(Child,State) of
{ok, State1} ->
{noreply, State1};
@@ -628,8 +579,9 @@ handle_info({'EXIT', Pid, Reason}, State) ->
end;
handle_info(Msg, State) ->
- error_logger:error_msg("Supervisor received unexpected message: ~p~n",
- [Msg]),
+ ?LOG_ERROR("Supervisor received unexpected message: ~tp~n",[Msg],
+ #{domain=>[otp],
+ error_logger=>#{tag=>error}}),
{noreply, State}.
%%
@@ -637,10 +589,8 @@ handle_info(Msg, State) ->
%%
-spec terminate(term(), state()) -> 'ok'.
-terminate(_Reason, #state{children=[Child]} = State) when ?is_simple(State) ->
- terminate_dynamic_children(Child, dynamics_db(Child#child.restart_type,
- State#state.dynamics),
- State#state.name);
+terminate(_Reason, State) when ?is_simple(State) ->
+ terminate_dynamic_children(State);
terminate(_Reason, State) ->
terminate_children(State#state.children, State#state.name).
@@ -675,8 +625,8 @@ code_change(_, State, _) ->
update_childspec(State, StartSpec) when ?is_simple(State) ->
case check_startspec(StartSpec) of
- {ok, [Child]} ->
- {ok, State#state{children = [Child]}};
+ {ok, {[_],_}=Children} ->
+ {ok, State#state{children = Children}};
Error ->
{error, Error}
end;
@@ -690,39 +640,36 @@ update_childspec(State, StartSpec) ->
{error, Error}
end.
-update_childspec1([Child|OldC], Children, KeepOld) ->
- case update_chsp(Child, Children) of
- {ok,NewChildren} ->
- update_childspec1(OldC, NewChildren, KeepOld);
+update_childspec1({[Id|OldIds], OldDb}, {Ids,Db}, KeepOld) ->
+ case update_chsp(maps:get(Id,OldDb), Db) of
+ {ok,NewDb} ->
+ update_childspec1({OldIds,OldDb}, {Ids,NewDb}, KeepOld);
false ->
- update_childspec1(OldC, Children, [Child|KeepOld])
+ update_childspec1({OldIds,OldDb}, {Ids,Db}, [Id|KeepOld])
end;
-update_childspec1([], Children, KeepOld) ->
+update_childspec1({[],OldDb}, {Ids,Db}, KeepOld) ->
+ KeepOldDb = maps:with(KeepOld,OldDb),
%% Return them in (kept) reverse start order.
- lists:reverse(Children ++ KeepOld).
-
-update_chsp(OldCh, Children) ->
- case lists:map(fun(Ch) when OldCh#child.name =:= Ch#child.name ->
- Ch#child{pid = OldCh#child.pid};
- (Ch) ->
- Ch
- end,
- Children) of
- Children ->
- false; % OldCh not found in new spec.
- NewC ->
- {ok, NewC}
+ {lists:reverse(Ids ++ KeepOld),maps:merge(KeepOldDb,Db)}.
+
+update_chsp(#child{id=Id}=OldChild, NewDb) ->
+ case maps:find(Id, NewDb) of
+ {ok,Child} ->
+ {ok,NewDb#{Id => Child#child{pid = OldChild#child.pid}}};
+ error -> % Id not found in new spec.
+ false
end.
+
%%% ---------------------------------------------------
%%% Start a new child.
%%% ---------------------------------------------------
handle_start_child(Child, State) ->
- case get_child(Child#child.name, State) of
- false ->
+ case find_child(Child#child.id, State) of
+ error ->
case do_start_child(State#state.name, Child) of
- {ok, undefined} when Child#child.restart_type =:= temporary ->
+ {ok, undefined} when ?is_temporary(Child) ->
{{ok, undefined}, State};
{ok, Pid} ->
{{ok, Pid}, save_child(Child#child{pid = Pid}, State)};
@@ -731,9 +678,9 @@ handle_start_child(Child, State) ->
{error, What} ->
{{error, {What, Child}}, State}
end;
- {value, OldChild} when is_pid(OldChild#child.pid) ->
+ {ok, OldChild} when is_pid(OldChild#child.pid) ->
{{error, {already_started, OldChild#child.pid}}, State};
- {value, _OldChild} ->
+ {ok, _OldChild} ->
{{error, already_present}, State}
end.
@@ -742,188 +689,157 @@ handle_start_child(Child, State) ->
%%% Returns: {ok, state()} | {shutdown, state()}
%%% ---------------------------------------------------
-restart_child(Pid, Reason, #state{children = [Child]} = State) when ?is_simple(State) ->
- RestartType = Child#child.restart_type,
- case dynamic_child_args(Pid, RestartType, State#state.dynamics) of
- {ok, Args} ->
- {M, F, _} = Child#child.mfargs,
- NChild = Child#child{pid = Pid, mfargs = {M, F, Args}},
- do_restart(RestartType, Reason, NChild, State);
- error ->
- {ok, State}
- end;
-
restart_child(Pid, Reason, State) ->
- Children = State#state.children,
- case lists:keyfind(Pid, #child.pid, Children) of
- #child{restart_type = RestartType} = Child ->
- do_restart(RestartType, Reason, Child, State);
- false ->
+ case find_child_and_args(Pid, State) of
+ {ok, Child} ->
+ do_restart(Reason, Child, State);
+ error ->
{ok, State}
end.
-do_restart(permanent, Reason, Child, State) ->
- report_error(child_terminated, Reason, Child, State#state.name),
+do_restart(Reason, Child, State) when ?is_permanent(Child) ->
+ ?report_error(child_terminated, Reason, Child, State#state.name),
restart(Child, State);
-do_restart(_, normal, Child, State) ->
- NState = state_del_child(Child, State),
+do_restart(normal, Child, State) ->
+ NState = del_child(Child, State),
{ok, NState};
-do_restart(_, shutdown, Child, State) ->
- NState = state_del_child(Child, State),
+do_restart(shutdown, Child, State) ->
+ NState = del_child(Child, State),
{ok, NState};
-do_restart(_, {shutdown, _Term}, Child, State) ->
- NState = state_del_child(Child, State),
+do_restart({shutdown, _Term}, Child, State) ->
+ NState = del_child(Child, State),
{ok, NState};
-do_restart(transient, Reason, Child, State) ->
- report_error(child_terminated, Reason, Child, State#state.name),
+do_restart(Reason, Child, State) when ?is_transient(Child) ->
+ ?report_error(child_terminated, Reason, Child, State#state.name),
restart(Child, State);
-do_restart(temporary, Reason, Child, State) ->
- report_error(child_terminated, Reason, Child, State#state.name),
- NState = state_del_child(Child, State),
+do_restart(Reason, Child, State) when ?is_temporary(Child) ->
+ ?report_error(child_terminated, Reason, Child, State#state.name),
+ NState = del_child(Child, State),
{ok, NState}.
restart(Child, State) ->
case add_restart(State) of
{ok, NState} ->
case restart(NState#state.strategy, Child, NState) of
- {try_again,NState2} ->
+ {{try_again, TryAgainId}, NState2} ->
%% Leaving control back to gen_server before
%% trying again. This way other incoming requsts
%% for the supervisor can be handled - e.g. a
%% shutdown request for the supervisor or the
%% child.
- Id = if ?is_simple(State) -> Child#child.pid;
- true -> Child#child.name
- end,
- ok = try_again_restart(self(), Id),
- {ok,NState2};
- {try_again, NState2, #child{name=ChName}} ->
- ok = try_again_restart(self(), ChName),
+ try_again_restart(TryAgainId),
{ok,NState2};
Other ->
Other
end;
{terminate, NState} ->
- report_error(shutdown, reached_max_restart_intensity,
+ ?report_error(shutdown, reached_max_restart_intensity,
Child, State#state.name),
- {shutdown, remove_child(Child, NState)}
+ {shutdown, del_child(Child, NState)}
end.
restart(simple_one_for_one, Child, State0) ->
#child{pid = OldPid, mfargs = {M, F, A}} = Child,
- State = case OldPid of
+ State1 = case OldPid of
?restarting(_) ->
NRes = State0#state.dynamic_restarts - 1,
State0#state{dynamic_restarts = NRes};
_ ->
State0
end,
- Dynamics = ?DICTS:erase(OldPid, dynamics_db(Child#child.restart_type,
- State#state.dynamics)),
+ State2 = dyn_erase(OldPid, State1),
case do_start_child_i(M, F, A) of
{ok, Pid} ->
- DynamicsDb = {dict, ?DICTS:store(Pid, A, Dynamics)},
- NState = State#state{dynamics = DynamicsDb},
+ NState = dyn_store(Pid, A, State2),
{ok, NState};
{ok, Pid, _Extra} ->
- DynamicsDb = {dict, ?DICTS:store(Pid, A, Dynamics)},
- NState = State#state{dynamics = DynamicsDb},
+ NState = dyn_store(Pid, A, State2),
{ok, NState};
{error, Error} ->
- NRestarts = State#state.dynamic_restarts + 1,
- DynamicsDb = {dict, ?DICTS:store(restarting(OldPid), A, Dynamics)},
- NState = State#state{dynamic_restarts = NRestarts,
- dynamics = DynamicsDb},
- report_error(start_error, Error, Child, State#state.name),
- {try_again, NState}
+ ROldPid = restarting(OldPid),
+ NRestarts = State2#state.dynamic_restarts + 1,
+ State3 = State2#state{dynamic_restarts = NRestarts},
+ NState = dyn_store(ROldPid, A, State3),
+ ?report_error(start_error, Error, Child, NState#state.name),
+ {{try_again, ROldPid}, NState}
end;
-restart(one_for_one, Child, State) ->
+restart(one_for_one, #child{id=Id} = Child, State) ->
OldPid = Child#child.pid,
case do_start_child(State#state.name, Child) of
{ok, Pid} ->
- NState = replace_child(Child#child{pid = Pid}, State),
+ NState = set_pid(Pid, Id, State),
{ok, NState};
{ok, Pid, _Extra} ->
- NState = replace_child(Child#child{pid = Pid}, State),
+ NState = set_pid(Pid, Id, State),
{ok, NState};
{error, Reason} ->
- NState = replace_child(Child#child{pid = restarting(OldPid)}, State),
- report_error(start_error, Reason, Child, State#state.name),
- {try_again, NState}
+ NState = set_pid(restarting(OldPid), Id, State),
+ ?report_error(start_error, Reason, Child, State#state.name),
+ {{try_again,Id}, NState}
end;
-restart(rest_for_one, Child, State) ->
- {ChAfter, ChBefore} = split_child(Child#child.pid, State#state.children),
- ChAfter2 = terminate_children(ChAfter, State#state.name),
- case start_children(ChAfter2, State#state.name) of
- {ok, ChAfter3} ->
- {ok, State#state{children = ChAfter3 ++ ChBefore}};
- {error, ChAfter3, {failed_to_start_child, ChName, _Reason}}
- when ChName =:= Child#child.name ->
- NChild = Child#child{pid=restarting(Child#child.pid)},
- NState = State#state{children = ChAfter3 ++ ChBefore},
- {try_again, replace_child(NChild,NState)};
- {error, ChAfter3, {failed_to_start_child, ChName, _Reason}} ->
- NChild = lists:keyfind(ChName, #child.name, ChAfter3),
- NChild2 = NChild#child{pid=?restarting(undefined)},
- NState = State#state{children = ChAfter3 ++ ChBefore},
- {try_again, replace_child(NChild2,NState), NChild2}
- end;
-restart(one_for_all, Child, State) ->
- Children1 = del_child(Child#child.pid, State#state.children),
- Children2 = terminate_children(Children1, State#state.name),
- case start_children(Children2, State#state.name) of
- {ok, NChs} ->
- {ok, State#state{children = NChs}};
- {error, NChs, {failed_to_start_child, ChName, _Reason}}
- when ChName =:= Child#child.name ->
- NChild = Child#child{pid=restarting(Child#child.pid)},
- NState = State#state{children = NChs},
- {try_again, replace_child(NChild,NState)};
- {error, NChs, {failed_to_start_child, ChName, _Reason}} ->
- NChild = lists:keyfind(ChName, #child.name, NChs),
- NChild2 = NChild#child{pid=?restarting(undefined)},
- NState = State#state{children = NChs},
- {try_again, replace_child(NChild2,NState), NChild2}
+restart(rest_for_one, #child{id=Id} = Child, #state{name=SupName} = State) ->
+ {ChAfter, ChBefore} = split_child(Id, State#state.children),
+ {Return, ChAfter2} = restart_multiple_children(Child, ChAfter, SupName),
+ {Return, State#state{children = append(ChAfter2,ChBefore)}};
+restart(one_for_all, Child, #state{name=SupName} = State) ->
+ Children1 = del_child(Child#child.id, State#state.children),
+ {Return, NChildren} = restart_multiple_children(Child, Children1, SupName),
+ {Return, State#state{children = NChildren}}.
+
+restart_multiple_children(Child, Children, SupName) ->
+ Children1 = terminate_children(Children, SupName),
+ case start_children(Children1, SupName) of
+ {ok, NChildren} ->
+ {ok, NChildren};
+ {error, NChildren, {failed_to_start_child, FailedId, _Reason}} ->
+ NewPid = if FailedId =:= Child#child.id ->
+ restarting(Child#child.pid);
+ true ->
+ ?restarting(undefined)
+ end,
+ {{try_again, FailedId}, set_pid(NewPid,FailedId,NChildren)}
end.
restarting(Pid) when is_pid(Pid) -> ?restarting(Pid);
restarting(RPid) -> RPid.
+-spec try_again_restart(child_id() | {'restarting',pid()}) -> 'ok'.
+try_again_restart(TryAgainId) ->
+ gen_server:cast(self(), {try_again_restart, TryAgainId}).
+
%%-----------------------------------------------------------------
%% Func: terminate_children/2
-%% Args: Children = [child_rec()] in termination order
+%% Args: Children = children() % Ids in termination order
%% SupName = {local, atom()} | {global, atom()} | {pid(),Mod}
-%% Returns: NChildren = [child_rec()] in
-%% startup order (reversed termination order)
+%% Returns: NChildren = children() % Ids in startup order
+%% % (reversed termination order)
%%-----------------------------------------------------------------
terminate_children(Children, SupName) ->
- terminate_children(Children, SupName, []).
-
-%% Temporary children should not be restarted and thus should
-%% be skipped when building the list of terminated children, although
-%% we do want them to be shut down as many functions from this module
-%% use this function to just clear everything.
-terminate_children([Child = #child{restart_type=temporary} | Children], SupName, Res) ->
- _ = do_terminate(Child, SupName),
- terminate_children(Children, SupName, Res);
-terminate_children([Child | Children], SupName, Res) ->
- NChild = do_terminate(Child, SupName),
- terminate_children(Children, SupName, [NChild | Res]);
-terminate_children([], _SupName, Res) ->
- Res.
+ Terminate =
+ fun(_Id,Child) when ?is_temporary(Child) ->
+ %% Temporary children should not be restarted and thus should
+ %% be skipped when building the list of terminated children.
+ do_terminate(Child, SupName),
+ remove;
+ (_Id,Child) ->
+ do_terminate(Child, SupName),
+ {update,Child#child{pid=undefined}}
+ end,
+ {ok,NChildren} = children_map(Terminate, Children),
+ NChildren.
do_terminate(Child, SupName) when is_pid(Child#child.pid) ->
case shutdown(Child#child.pid, Child#child.shutdown) of
ok ->
ok;
- {error, normal} when Child#child.restart_type =/= permanent ->
+ {error, normal} when not (?is_permanent(Child)) ->
ok;
{error, OtherReason} ->
- report_error(shutdown_error, OtherReason, Child, SupName)
+ ?report_error(shutdown_error, OtherReason, Child, SupName)
end,
- Child#child{pid = undefined};
-do_terminate(Child, _SupName) ->
- Child#child{pid = undefined}.
+ ok;
+do_terminate(_Child, _SupName) ->
+ ok.
%%-----------------------------------------------------------------
%% Shutdowns a child. We must check the EXIT value
@@ -996,66 +912,50 @@ monitor_child(Pid) ->
ok
end.
-
%%-----------------------------------------------------------------
-%% Func: terminate_dynamic_children/3
-%% Args: Child = child_rec()
-%% Dynamics = ?DICT() | ?SET()
-%% SupName = {local, atom()} | {global, atom()} | {pid(),Mod}
+%% Func: terminate_dynamic_children/1
+%% Args: State
%% Returns: ok
%%
-%%
%% Shutdown all dynamic children. This happens when the supervisor is
%% stopped. Because the supervisor can have millions of dynamic children, we
-%% can have an significative overhead here.
+%% can have a significative overhead here.
%%-----------------------------------------------------------------
-terminate_dynamic_children(Child, Dynamics, SupName) ->
- {Pids, EStack0} = monitor_dynamic_children(Child, Dynamics),
- Sz = ?SETS:size(Pids),
+terminate_dynamic_children(State) ->
+ Child = get_dynamic_child(State),
+ {Pids, EStack0} = monitor_dynamic_children(Child,State),
+ Sz = sets:size(Pids),
EStack = case Child#child.shutdown of
brutal_kill ->
- ?SETS:fold(fun(P, _) -> exit(P, kill) end, ok, Pids),
+ sets:fold(fun(P, _) -> exit(P, kill) end, ok, Pids),
wait_dynamic_children(Child, Pids, Sz, undefined, EStack0);
infinity ->
- ?SETS:fold(fun(P, _) -> exit(P, shutdown) end, ok, Pids),
+ sets:fold(fun(P, _) -> exit(P, shutdown) end, ok, Pids),
wait_dynamic_children(Child, Pids, Sz, undefined, EStack0);
Time ->
- ?SETS:fold(fun(P, _) -> exit(P, shutdown) end, ok, Pids),
+ sets:fold(fun(P, _) -> exit(P, shutdown) end, ok, Pids),
TRef = erlang:start_timer(Time, self(), kill),
wait_dynamic_children(Child, Pids, Sz, TRef, EStack0)
end,
%% Unroll stacked errors and report them
- ?DICTS:fold(fun(Reason, Ls, _) ->
- report_error(shutdown_error, Reason,
- Child#child{pid=Ls}, SupName)
- end, ok, EStack).
-
-
-monitor_dynamic_children(#child{restart_type=temporary}, Dynamics) ->
- ?SETS:fold(fun(P, {Pids, EStack}) ->
- case monitor_child(P) of
- ok ->
- {?SETS:add_element(P, Pids), EStack};
- {error, normal} ->
- {Pids, EStack};
- {error, Reason} ->
- {Pids, ?DICTS:append(Reason, P, EStack)}
- end
- end, {?SETS:new(), ?DICTS:new()}, Dynamics);
-monitor_dynamic_children(#child{restart_type=RType}, Dynamics) ->
- ?DICTS:fold(fun(P, _, {Pids, EStack}) when is_pid(P) ->
- case monitor_child(P) of
- ok ->
- {?SETS:add_element(P, Pids), EStack};
- {error, normal} when RType =/= permanent ->
- {Pids, EStack};
- {error, Reason} ->
- {Pids, ?DICTS:append(Reason, P, EStack)}
- end;
- (?restarting(_), _, {Pids, EStack}) ->
- {Pids, EStack}
- end, {?SETS:new(), ?DICTS:new()}, Dynamics).
-
+ dict:fold(fun(Reason, Ls, _) ->
+ ?report_error(shutdown_error, Reason,
+ Child#child{pid=Ls}, State#state.name)
+ end, ok, EStack).
+
+monitor_dynamic_children(Child,State) ->
+ dyn_fold(fun(P,{Pids, EStack}) when is_pid(P) ->
+ case monitor_child(P) of
+ ok ->
+ {sets:add_element(P, Pids), EStack};
+ {error, normal} when not (?is_permanent(Child)) ->
+ {Pids, EStack};
+ {error, Reason} ->
+ {Pids, dict:append(Reason, P, EStack)}
+ end;
+ (?restarting(_), {Pids, EStack}) ->
+ {Pids, EStack}
+ end, {sets:new(), dict:new()}, State).
wait_dynamic_children(_Child, _Pids, 0, undefined, EStack) ->
EStack;
@@ -1073,39 +973,38 @@ wait_dynamic_children(#child{shutdown=brutal_kill} = Child, Pids, Sz,
TRef, EStack) ->
receive
{'DOWN', _MRef, process, Pid, killed} ->
- wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
+ wait_dynamic_children(Child, sets:del_element(Pid, Pids), Sz-1,
TRef, EStack);
{'DOWN', _MRef, process, Pid, Reason} ->
- wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
- TRef, ?DICTS:append(Reason, Pid, EStack))
+ wait_dynamic_children(Child, sets:del_element(Pid, Pids), Sz-1,
+ TRef, dict:append(Reason, Pid, EStack))
end;
-wait_dynamic_children(#child{restart_type=RType} = Child, Pids, Sz,
- TRef, EStack) ->
+wait_dynamic_children(Child, Pids, Sz, TRef, EStack) ->
receive
{'DOWN', _MRef, process, Pid, shutdown} ->
- wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
+ wait_dynamic_children(Child, sets:del_element(Pid, Pids), Sz-1,
TRef, EStack);
{'DOWN', _MRef, process, Pid, {shutdown, _}} ->
- wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
+ wait_dynamic_children(Child, sets:del_element(Pid, Pids), Sz-1,
TRef, EStack);
- {'DOWN', _MRef, process, Pid, normal} when RType =/= permanent ->
- wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
+ {'DOWN', _MRef, process, Pid, normal} when not (?is_permanent(Child)) ->
+ wait_dynamic_children(Child, sets:del_element(Pid, Pids), Sz-1,
TRef, EStack);
{'DOWN', _MRef, process, Pid, Reason} ->
- wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1,
- TRef, ?DICTS:append(Reason, Pid, EStack));
+ wait_dynamic_children(Child, sets:del_element(Pid, Pids), Sz-1,
+ TRef, dict:append(Reason, Pid, EStack));
{timeout, TRef, kill} ->
- ?SETS:fold(fun(P, _) -> exit(P, kill) end, ok, Pids),
+ sets:fold(fun(P, _) -> exit(P, kill) end, ok, Pids),
wait_dynamic_children(Child, Pids, Sz, undefined, EStack)
end.
%%-----------------------------------------------------------------
-%% Child/State manipulating functions.
+%% Access #state.children
%%-----------------------------------------------------------------
%% Note we do not want to save the parameter list for temporary processes as
@@ -1113,114 +1012,184 @@ wait_dynamic_children(#child{restart_type=RType} = Child, Pids, Sz,
%% Especially for dynamic children to simple_one_for_one supervisors
%% it could become very costly as it is not uncommon to spawn
%% very many such processes.
-save_child(#child{restart_type = temporary,
- mfargs = {M, F, _}} = Child, #state{children = Children} = State) ->
- State#state{children = [Child#child{mfargs = {M, F, undefined}} |Children]};
-save_child(Child, #state{children = Children} = State) ->
- State#state{children = [Child |Children]}.
-
-save_dynamic_child(temporary, Pid, _, #state{dynamics = Dynamics} = State) ->
- DynamicsDb = dynamics_db(temporary, Dynamics),
- State#state{dynamics = {set, ?SETS:add_element(Pid, DynamicsDb)}};
-save_dynamic_child(RestartType, Pid, Args, #state{dynamics = Dynamics} = State) ->
- DynamicsDb = dynamics_db(RestartType, Dynamics),
- State#state{dynamics = {dict, ?DICTS:store(Pid, Args, DynamicsDb)}}.
-
-dynamics_db(temporary, undefined) ->
- ?SETS:new();
-dynamics_db(_, undefined) ->
- ?DICTS:new();
-dynamics_db(_, {_Tag, DynamicsDb}) ->
- DynamicsDb.
-
-dynamic_child_args(_Pid, temporary, _DynamicsDb) ->
- {ok, undefined};
-dynamic_child_args(Pid, _RT, {dict, DynamicsDb}) ->
- ?DICTS:find(Pid, DynamicsDb);
-dynamic_child_args(_Pid, _RT, undefined) ->
- error.
-
-state_del_child(#child{pid = Pid, restart_type = temporary}, State) when ?is_simple(State) ->
- NDynamics = ?SETS:del_element(Pid, dynamics_db(temporary, State#state.dynamics)),
- State#state{dynamics = {set, NDynamics}};
-state_del_child(#child{pid = Pid, restart_type = RType}, State) when ?is_simple(State) ->
- NDynamics = ?DICTS:erase(Pid, dynamics_db(RType, State#state.dynamics)),
- State#state{dynamics = {dict, NDynamics}};
-state_del_child(Child, State) ->
- NChildren = del_child(Child#child.name, State#state.children),
- State#state{children = NChildren}.
-
-del_child(Name, [Ch|Chs]) when Ch#child.name =:= Name, Ch#child.restart_type =:= temporary ->
- Chs;
-del_child(Name, [Ch|Chs]) when Ch#child.name =:= Name ->
- [Ch#child{pid = undefined} | Chs];
-del_child(Pid, [Ch|Chs]) when Ch#child.pid =:= Pid, Ch#child.restart_type =:= temporary ->
- Chs;
-del_child(Pid, [Ch|Chs]) when Ch#child.pid =:= Pid ->
- [Ch#child{pid = undefined} | Chs];
-del_child(Name, [Ch|Chs]) ->
- [Ch|del_child(Name, Chs)];
-del_child(_, []) ->
- [].
+-spec save_child(child_rec(), state()) -> state().
+save_child(#child{mfargs = {M, F, _}} = Child, State) when ?is_temporary(Child) ->
+ do_save_child(Child#child{mfargs = {M, F, undefined}}, State);
+save_child(Child, State) ->
+ do_save_child(Child, State).
+
+-spec do_save_child(child_rec(), state()) -> state().
+do_save_child(#child{id = Id} = Child, #state{children = {Ids,Db}} = State) ->
+ State#state{children = {[Id|Ids],Db#{Id => Child}}}.
+
+-spec del_child(child_rec(), state()) -> state();
+ (child_id(), children()) -> children().
+del_child(#child{pid = Pid}, State) when ?is_simple(State) ->
+ dyn_erase(Pid,State);
+del_child(Child, State) when is_record(Child,child), is_record(State,state) ->
+ NChildren = del_child(Child#child.id, State#state.children),
+ State#state{children = NChildren};
+del_child(Id, {Ids,Db}) ->
+ case maps:get(Id, Db) of
+ Child when Child#child.restart_type =:= temporary ->
+ {lists:delete(Id, Ids), maps:remove(Id, Db)};
+ Child ->
+ {Ids, Db#{Id=>Child#child{pid=undefined}}}
+ end.
-%% Chs = [S4, S3, Ch, S1, S0]
-%% Ret: {[S4, S3, Ch], [S1, S0]}
-split_child(Name, Chs) ->
- split_child(Name, Chs, []).
-
-split_child(Name, [Ch|Chs], After) when Ch#child.name =:= Name ->
- {lists:reverse([Ch#child{pid = undefined} | After]), Chs};
-split_child(Pid, [Ch|Chs], After) when Ch#child.pid =:= Pid ->
- {lists:reverse([Ch#child{pid = undefined} | After]), Chs};
-split_child(Name, [Ch|Chs], After) ->
- split_child(Name, Chs, [Ch | After]);
-split_child(_, [], After) ->
- {lists:reverse(After), []}.
-
-get_child(Name, State) ->
- get_child(Name, State, false).
-
-get_child(Pid, State, AllowPid) when AllowPid, is_pid(Pid) ->
- get_dynamic_child(Pid, State);
-get_child(Name, State, _) ->
- lists:keysearch(Name, #child.name, State#state.children).
-
-get_dynamic_child(Pid, #state{children=[Child], dynamics=Dynamics}) ->
- case is_dynamic_pid(Pid, Dynamics) of
- true ->
- {value, Child#child{pid=Pid}};
- false ->
- RPid = restarting(Pid),
- case is_dynamic_pid(RPid, Dynamics) of
- true ->
- {value, Child#child{pid=RPid}};
- false ->
+%% In: {[S4, S3, Ch, S1, S0],Db}
+%% Ret: {{[S4, S3, Ch],Db1}, {[S1, S0],Db2}}
+%% Db1 and Db2 contain the keys in the lists they are associated with.
+-spec split_child(child_id(), children()) -> {children(), children()}.
+split_child(Id, {Ids,Db}) ->
+ {IdsAfter,IdsBefore} = split_ids(Id, Ids, []),
+ DbBefore = maps:with(IdsBefore,Db),
+ #{Id:=Ch} = DbAfter = maps:with(IdsAfter,Db),
+ {{IdsAfter,DbAfter#{Id=>Ch#child{pid=undefined}}},{IdsBefore,DbBefore}}.
+
+split_ids(Id, [Id|Ids], After) ->
+ {lists:reverse([Id|After]), Ids};
+split_ids(Id, [Other|Ids], After) ->
+ split_ids(Id, Ids, [Other | After]).
+
+%% Find the child record for a given Pid (dynamic child) or Id
+%% (non-dynamic child). This is called from the API functions.
+-spec find_child(pid() | child_id(), state()) -> {ok,child_rec()} | error.
+find_child(Pid, State) when is_pid(Pid), ?is_simple(State) ->
+ case find_dynamic_child(Pid, State) of
+ error ->
+ case find_dynamic_child(restarting(Pid), State) of
+ error ->
case erlang:is_process_alive(Pid) of
- true -> false;
- false -> {value, Child}
- end
- end
+ true -> error;
+ false -> {ok, get_dynamic_child(State)}
+ end;
+ Other ->
+ Other
+ end;
+ Other ->
+ Other
+ end;
+find_child(Id, #state{children = {_Ids,Db}}) ->
+ maps:find(Id, Db).
+
+%% Get the child record - either by child id or by pid. If
+%% simple_one_for_one, then insert the pid and args into the returned
+%% child record. This is called when trying to restart the child.
+-spec find_child_and_args(IdOrPid, state()) -> {ok, child_rec()} | error when
+ IdOrPid :: pid() | {restarting,pid()} | child_id().
+find_child_and_args(Pid, State) when ?is_simple(State) ->
+ case find_dynamic_child(Pid, State) of
+ {ok,#child{mfargs={M,F,_}} = Child} ->
+ {ok, Args} = dyn_args(Pid, State),
+ {ok, Child#child{mfargs = {M, F, Args}}};
+ error ->
+ error
+ end;
+find_child_and_args(Pid, State) when is_pid(Pid) ->
+ find_child_by_pid(Pid, State);
+find_child_and_args(Id, #state{children={_Ids,Db}}) ->
+ maps:find(Id, Db).
+
+%% Given the pid, find the child record for a dynamic child, and
+%% include the pid in the returned record.
+-spec find_dynamic_child(IdOrPid, state()) -> {ok, child_rec()} | error when
+ IdOrPid :: pid() | {restarting,pid()} | child_id().
+find_dynamic_child(Pid, State) ->
+ case dyn_exists(Pid, State) of
+ true ->
+ Child = get_dynamic_child(State),
+ {ok, Child#child{pid=Pid}};
+ false ->
+ error
end.
-is_dynamic_pid(Pid, {dict, Dynamics}) ->
- ?DICTS:is_key(Pid, Dynamics);
-is_dynamic_pid(Pid, {set, Dynamics}) ->
- ?SETS:is_element(Pid, Dynamics);
-is_dynamic_pid(_Pid, undefined) ->
- false.
-
-replace_child(Child, State) ->
- Chs = do_replace_child(Child, State#state.children),
- State#state{children = Chs}.
-
-do_replace_child(Child, [Ch|Chs]) when Ch#child.name =:= Child#child.name ->
- [Child | Chs];
-do_replace_child(Child, [Ch|Chs]) ->
- [Ch|do_replace_child(Child, Chs)].
+%% Given the pid, find the child record for a non-dyanamic child.
+-spec find_child_by_pid(IdOrPid, state()) -> {ok,child_rec()} | error when
+ IdOrPid :: pid() | {restarting,pid()}.
+find_child_by_pid(Pid,#state{children={_Ids,Db}}) ->
+ Fun = fun(_Id,#child{pid=P}=Ch,_) when P =:= Pid ->
+ throw(Ch);
+ (_,_,error) ->
+ error
+ end,
+ try maps:fold(Fun,error,Db)
+ catch throw:Child -> {ok,Child}
+ end.
-remove_child(Child, State) ->
- Chs = lists:keydelete(Child#child.name, #child.name, State#state.children),
- State#state{children = Chs}.
+%% Get the child record from a simple_one_for_one supervisor - no pid
+%% It is assumed that the child can always be found
+-spec get_dynamic_child(state()) -> child_rec().
+get_dynamic_child(#state{children={[Id],Db}}) ->
+ #{Id := Child} = Db,
+ Child.
+
+%% Update pid in the given child record and store it in the process state
+-spec set_pid(term(), child_id(), state()) -> state();
+ (term(), child_id(), children()) -> children().
+set_pid(Pid, Id, #state{children=Children} = State) ->
+ State#state{children = set_pid(Pid, Id, Children)};
+set_pid(Pid, Id, {Ids, Db}) ->
+ NewDb = maps:update_with(Id, fun(Child) -> Child#child{pid=Pid} end, Db),
+ {Ids,NewDb}.
+
+%% Remove the Id and the child record from the process state
+-spec remove_child(child_id(), state()) -> state().
+remove_child(Id, #state{children={Ids,Db}} = State) ->
+ NewIds = lists:delete(Id,Ids),
+ NewDb = maps:remove(Id,Db),
+ State#state{children = {NewIds,NewDb}}.
+
+%% In the order of Ids, traverse the children and update each child
+%% according to the return value of the Fun.
+%% On error, abort and return the merge of the old and the updated map.
+%% NOTE: The returned list of Ids is reverted compared to the input.
+-spec children_map(Fun, children()) -> {ok, children()} |
+ {error,children(),Reason} when
+ Fun :: fun((child_id(),child_rec()) -> {update,child_rec()} |
+ remove |
+ {abort, Reason}),
+ Reason :: term().
+children_map(Fun,{Ids,Db}) ->
+ children_map(Fun, Ids, Db, []).
+
+children_map(Fun,[Id|Ids],Db,Acc) ->
+ case Fun(Id,maps:get(Id,Db)) of
+ {update,Child} ->
+ children_map(Fun,Ids,Db#{Id => Child},[Id|Acc]);
+ remove ->
+ children_map(Fun,Ids,maps:remove(Id,Db),Acc);
+ {abort,Reason} ->
+ {error,{lists:reverse(Ids)++[Id|Acc],Db},Reason}
+ end;
+children_map(_Fun,[],Db,Acc) ->
+ {ok,{Acc,Db}}.
+
+%% In the order of Ids, map over all children and return the list
+-spec children_to_list(Fun, children()) -> List when
+ Fun :: fun((child_id(), child_rec()) -> Elem),
+ List :: list(Elem),
+ Elem :: term().
+children_to_list(Fun,{Ids,Db}) ->
+ children_to_list(Fun, Ids, Db, []).
+children_to_list(Fun,[Id|Ids],Db,Acc) ->
+ children_to_list(Fun,Ids,Db,[Fun(Id,maps:get(Id,Db))|Acc]);
+children_to_list(_Fun,[],_Db,Acc) ->
+ lists:reverse(Acc).
+
+%% The order is not important - so ignore Ids
+-spec children_fold(Fun, Acc0, children()) -> Acc1 when
+ Fun :: fun((child_id(), child_rec(), AccIn) -> AccOut),
+ Acc0 :: term(),
+ Acc1 :: term(),
+ AccIn :: term(),
+ AccOut :: term().
+children_fold(Fun,Init,{_Ids,Db}) ->
+ maps:fold(Fun, Init, Db).
+
+-spec append(children(), children()) -> children().
+append({Ids1,Db1},{Ids2,Db2}) ->
+ {Ids1++Ids2,maps:merge(Db1,Db2)}.
%%-----------------------------------------------------------------
%% Func: init_state/4
@@ -1290,27 +1259,27 @@ supname(N, _) -> N.
%%% Returns: {ok, [child_rec()]} | Error
%%% ------------------------------------------------------
-check_startspec(Children) -> check_startspec(Children, []).
+check_startspec(Children) -> check_startspec(Children, [], #{}).
-check_startspec([ChildSpec|T], Res) ->
+check_startspec([ChildSpec|T], Ids, Db) ->
case check_childspec(ChildSpec) of
- {ok, Child} ->
- case lists:keymember(Child#child.name, #child.name, Res) of
+ {ok, #child{id=Id}=Child} ->
+ case maps:is_key(Id, Db) of
%% The error message duplicate_child_name is kept for
%% backwards compatibility, although
%% duplicate_child_id would be more correct.
- true -> {duplicate_child_name, Child#child.name};
- false -> check_startspec(T, [Child | Res])
+ true -> {duplicate_child_name, Id};
+ false -> check_startspec(T, [Id | Ids], Db#{Id=>Child})
end;
Error -> Error
end;
-check_startspec([], Res) ->
- {ok, lists:reverse(Res)}.
+check_startspec([], Ids, Db) ->
+ {ok, {lists:reverse(Ids),Db}}.
check_childspec(ChildSpec) when is_map(ChildSpec) ->
catch do_check_childspec(maps:merge(?default_child_spec,ChildSpec));
-check_childspec({Name, Func, RestartType, Shutdown, ChildType, Mods}) ->
- check_childspec(#{id => Name,
+check_childspec({Id, Func, RestartType, Shutdown, ChildType, Mods}) ->
+ check_childspec(#{id => Id,
start => Func,
restart => RestartType,
shutdown => Shutdown,
@@ -1320,15 +1289,15 @@ check_childspec(X) -> {invalid_child_spec, X}.
do_check_childspec(#{restart := RestartType,
type := ChildType} = ChildSpec)->
- Name = case ChildSpec of
- #{id := N} -> N;
+ Id = case ChildSpec of
+ #{id := I} -> I;
_ -> throw(missing_id)
end,
Func = case ChildSpec of
#{start := F} -> F;
_ -> throw(missing_start)
end,
- validName(Name),
+ validId(Id),
validFunc(Func),
validRestartType(RestartType),
validChildType(ChildType),
@@ -1343,14 +1312,14 @@ do_check_childspec(#{restart := RestartType,
_ -> {M,_,_} = Func, [M]
end,
validMods(Mods),
- {ok, #child{name = Name, mfargs = Func, restart_type = RestartType,
+ {ok, #child{id = Id, mfargs = Func, restart_type = RestartType,
shutdown = Shutdown, child_type = ChildType, modules = Mods}}.
validChildType(supervisor) -> true;
validChildType(worker) -> true;
validChildType(What) -> throw({invalid_child_type, What}).
-validName(_Name) -> true.
+validId(_Id) -> true.
validFunc({M, F, A}) when is_atom(M),
is_atom(F),
@@ -1379,13 +1348,13 @@ validMods(Mods) when is_list(Mods) ->
Mods);
validMods(Mods) -> throw({invalid_modules, Mods}).
-child_to_spec(#child{name = Name,
+child_to_spec(#child{id = Id,
mfargs = Func,
restart_type = RestartType,
shutdown = Shutdown,
child_type = ChildType,
modules = Mods}) ->
- #{id => Name,
+ #{id => Id,
start => Func,
restart => RestartType,
shutdown => Shutdown,
@@ -1431,37 +1400,75 @@ inPeriod(Then, Now, Period) ->
%%% ------------------------------------------------------
%%% Error and progress reporting.
%%% ------------------------------------------------------
-
-report_error(Error, Reason, Child, SupName) ->
- ErrorMsg = [{supervisor, SupName},
- {errorContext, Error},
- {reason, Reason},
- {offender, extract_child(Child)}],
- error_logger:error_report(supervisor_report, ErrorMsg).
-
-
extract_child(Child) when is_list(Child#child.pid) ->
[{nb_children, length(Child#child.pid)},
- {id, Child#child.name},
+ {id, Child#child.id},
{mfargs, Child#child.mfargs},
{restart_type, Child#child.restart_type},
{shutdown, Child#child.shutdown},
{child_type, Child#child.child_type}];
extract_child(Child) ->
[{pid, Child#child.pid},
- {id, Child#child.name},
+ {id, Child#child.id},
{mfargs, Child#child.mfargs},
{restart_type, Child#child.restart_type},
{shutdown, Child#child.shutdown},
{child_type, Child#child.child_type}].
report_progress(Child, SupName) ->
- Progress = [{supervisor, SupName},
- {started, extract_child(Child)}],
- error_logger:info_report(progress, Progress).
+ ?LOG_INFO(#{label=>{supervisor,progress},
+ report=>[{supervisor,SupName},
+ {started,extract_child(Child)}]},
+ #{domain=>[otp,sasl],
+ report_cb=>fun logger:format_otp_report/1,
+ logger_formatter=>#{title=>"PROGRESS REPORT"},
+ error_logger=>#{tag=>info_report,type=>progress}}).
format_status(terminate, [_PDict, State]) ->
State;
format_status(_, [_PDict, State]) ->
[{data, [{"State", State}]},
{supervisor, [{"Callback", State#state.module}]}].
+
+%%%-----------------------------------------------------------------
+%%% Dynamics database access
+dyn_size(#state{dynamics = {Mod,Db}}) ->
+ Mod:size(Db).
+
+dyn_erase(Pid,#state{dynamics={sets,Db}}=State) ->
+ State#state{dynamics={sets,sets:del_element(Pid,Db)}};
+dyn_erase(Pid,#state{dynamics={maps,Db}}=State) ->
+ State#state{dynamics={maps,maps:remove(Pid,Db)}}.
+
+dyn_store(Pid,_,#state{dynamics={sets,Db}}=State) ->
+ State#state{dynamics={sets,sets:add_element(Pid,Db)}};
+dyn_store(Pid,Args,#state{dynamics={maps,Db}}=State) ->
+ State#state{dynamics={maps,Db#{Pid => Args}}}.
+
+dyn_fold(Fun,Init,#state{dynamics={sets,Db}}) ->
+ sets:fold(Fun,Init,Db);
+dyn_fold(Fun,Init,#state{dynamics={maps,Db}}) ->
+ maps:fold(fun(Pid,_,Acc) -> Fun(Pid,Acc) end, Init, Db).
+
+dyn_map(Fun, #state{dynamics={sets,Db}}) ->
+ lists:map(Fun, sets:to_list(Db));
+dyn_map(Fun, #state{dynamics={maps,Db}}) ->
+ lists:map(Fun, maps:keys(Db)).
+
+dyn_exists(Pid, #state{dynamics={sets, Db}}) ->
+ sets:is_element(Pid, Db);
+dyn_exists(Pid, #state{dynamics={maps, Db}}) ->
+ maps:is_key(Pid, Db).
+
+dyn_args(_Pid, #state{dynamics={sets, _Db}}) ->
+ {ok,undefined};
+dyn_args(Pid, #state{dynamics={maps, Db}}) ->
+ maps:find(Pid, Db).
+
+dyn_init(State) ->
+ dyn_init(get_dynamic_child(State),State).
+
+dyn_init(Child,State) when ?is_temporary(Child) ->
+ State#state{dynamics={sets,sets:new()}};
+dyn_init(_Child,State) ->
+ State#state{dynamics={maps,maps:new()}}.
diff --git a/lib/stdlib/src/supervisor_bridge.erl b/lib/stdlib/src/supervisor_bridge.erl
index af1e046d30..21ba6f53af 100644
--- a/lib/stdlib/src/supervisor_bridge.erl
+++ b/lib/stdlib/src/supervisor_bridge.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,6 +21,8 @@
-behaviour(gen_server).
+-include("logger.hrl").
+
%% External exports
-export([start_link/2, start_link/3]).
%% Internal exports
@@ -129,13 +131,22 @@ terminate_pid(Reason, #state{mod = Mod, child_state = ChildState}) ->
Mod:terminate(Reason, ChildState).
report_progress(Pid, Mod, StartArgs, SupName) ->
- Progress = [{supervisor, SupName},
- {started, [{pid, Pid}, {mfa, {Mod, init, [StartArgs]}}]}],
- error_logger:info_report(progress, Progress).
+ ?LOG_INFO(#{label=>{supervisor,progress},
+ report=>[{supervisor, SupName},
+ {started, [{pid, Pid},
+ {mfa, {Mod, init, [StartArgs]}}]}]},
+ #{domain=>[otp,sasl],
+ report_cb=>fun logger:format_otp_report/1,
+ logger_formatter=>#{title=>"PROGRESS REPORT"},
+ error_logger=>#{tag=>info_report,type=>progress}}).
report_error(Error, Reason, #state{name = Name, pid = Pid, mod = Mod}) ->
- ErrorMsg = [{supervisor, Name},
- {errorContext, Error},
- {reason, Reason},
- {offender, [{pid, Pid}, {mod, Mod}]}],
- error_logger:error_report(supervisor_report, ErrorMsg).
+ ?LOG_ERROR(#{label=>{supervisor,error},
+ report=>[{supervisor, Name},
+ {errorContext, Error},
+ {reason, Reason},
+ {offender, [{pid, Pid}, {mod, Mod}]}]},
+ #{domain=>[otp,sasl],
+ report_cb=>fun logger:format_otp_report/1,
+ logger_formatter=>#{title=>"SUPERVISOR REPORT"},
+ error_logger=>#{tag=>error_report,type=>supervisor_report}}).
diff --git a/lib/stdlib/src/sys.erl b/lib/stdlib/src/sys.erl
index 1f966411c5..0064414d6f 100644
--- a/lib/stdlib/src/sys.erl
+++ b/lib/stdlib/src/sys.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -38,10 +38,13 @@
-export_type([dbg_opt/0]).
--type name() :: pid() | atom() | {'global', atom()}.
+-type name() :: pid() | atom()
+ | {'global', term()}
+ | {'via', module(), term()}.
-type system_event() :: {'in', Msg :: _}
| {'in', Msg :: _, From :: _}
| {'out', Msg :: _, To :: _}
+ | {'out', Msg :: _, To :: _, State :: _}
| term().
-opaque dbg_opt() :: {'trace', 'true'}
| {'log',
@@ -54,7 +57,8 @@
MessagesIn :: non_neg_integer(),
MessagesOut :: non_neg_integer()}}
| {'log_to_file', file:io_device()}
- | {Func :: dbg_fun(), FuncState :: term()}.
+ | {Func :: dbg_fun(), FuncState :: term()}
+ | {FuncId :: term(), Func :: dbg_fun(), FuncState :: term()}.
-type dbg_fun() :: fun((FuncState :: _,
Event :: system_event(),
ProcState :: _) -> 'done' | (NewFuncState :: _)).
@@ -265,33 +269,41 @@ no_debug(Name, Timeout) -> send_system_msg(Name, {debug, no_debug}, Timeout).
-spec install(Name, FuncSpec) -> 'ok' when
Name :: name(),
- FuncSpec :: {Func, FuncState},
+ FuncSpec :: {Func, FuncState} | {FuncId, Func, FuncState},
+ FuncId :: term(),
Func :: dbg_fun(),
FuncState :: term().
install(Name, {Func, FuncState}) ->
- send_system_msg(Name, {debug, {install, {Func, FuncState}}}).
+ send_system_msg(Name, {debug, {install, {Func, FuncState}}});
+install(Name, {FuncId, Func, FuncState}) ->
+ send_system_msg(Name, {debug, {install, {FuncId, Func, FuncState}}}).
-spec install(Name, FuncSpec, Timeout) -> 'ok' when
Name :: name(),
- FuncSpec :: {Func, FuncState},
+ FuncSpec :: {Func, FuncState} | {FuncId, Func, FuncState},
+ FuncId :: term(),
Func :: dbg_fun(),
FuncState :: term(),
Timeout :: timeout().
install(Name, {Func, FuncState}, Timeout) ->
- send_system_msg(Name, {debug, {install, {Func, FuncState}}}, Timeout).
+ send_system_msg(Name, {debug, {install, {Func, FuncState}}}, Timeout);
+install(Name, {FuncId, Func, FuncState}, Timeout) ->
+ send_system_msg(Name, {debug, {install, {FuncId, Func, FuncState}}}, Timeout).
--spec remove(Name, Func) -> 'ok' when
+-spec remove(Name, Func | FuncId) -> 'ok' when
Name :: name(),
- Func :: dbg_fun().
-remove(Name, Func) ->
- send_system_msg(Name, {debug, {remove, Func}}).
+ Func :: dbg_fun(),
+ FuncId :: term().
+remove(Name, FuncOrFuncId) ->
+ send_system_msg(Name, {debug, {remove, FuncOrFuncId}}).
--spec remove(Name, Func, Timeout) -> 'ok' when
+-spec remove(Name, Func | FuncId, Timeout) -> 'ok' when
Name :: name(),
Func :: dbg_fun(),
+ FuncId :: term(),
Timeout :: timeout().
-remove(Name, Func, Timeout) ->
- send_system_msg(Name, {debug, {remove, Func}}, Timeout).
+remove(Name, FuncOrFuncId, Timeout) ->
+ send_system_msg(Name, {debug, {remove, FuncOrFuncId}}, Timeout).
%%-----------------------------------------------------------------
%% All system messages sent are on the form {system, From, Msg}
@@ -385,6 +397,13 @@ handle_debug([{log_to_file, Fd} | T], FormFunc, State, Event) ->
handle_debug([{statistics, StatData} | T], FormFunc, State, Event) ->
NStatData = stat(Event, StatData),
[{statistics, NStatData} | handle_debug(T, FormFunc, State, Event)];
+handle_debug([{FuncId, {Func, FuncState}} | T], FormFunc, State, Event) ->
+ case catch Func(FuncState, Event, State) of
+ done -> handle_debug(T, FormFunc, State, Event);
+ {'EXIT', _} -> handle_debug(T, FormFunc, State, Event);
+ NFuncState ->
+ [{FuncId, {Func, NFuncState}} | handle_debug(T, FormFunc, State, Event)]
+ end;
handle_debug([{Func, FuncState} | T], FormFunc, State, Event) ->
case catch Func(FuncState, Event, State) of
done -> handle_debug(T, FormFunc, State, Event);
@@ -542,8 +561,10 @@ debug_cmd(no_debug, Debug) ->
{ok, []};
debug_cmd({install, {Func, FuncState}}, Debug) ->
{ok, install_debug(Func, FuncState, Debug)};
-debug_cmd({remove, Func}, Debug) ->
- {ok, remove_debug(Func, Debug)};
+debug_cmd({install, {FuncId, Func, FuncState}}, Debug) ->
+ {ok, install_debug(FuncId, {Func, FuncState}, Debug)};
+debug_cmd({remove, FuncOrFuncId}, Debug) ->
+ {ok, remove_debug(FuncOrFuncId, Debug)};
debug_cmd(_Unknown, Debug) ->
{unknown_debug, Debug}.
@@ -571,6 +592,7 @@ get_stat(_) ->
stat({in, _Msg}, {Time, Reds, In, Out}) -> {Time, Reds, In+1, Out};
stat({in, _Msg, _From}, {Time, Reds, In, Out}) -> {Time, Reds, In+1, Out};
stat({out, _Msg, _To}, {Time, Reds, In, Out}) -> {Time, Reds, In, Out+1};
+stat({out, _Msg, _To, _State}, {Time, Reds, In, Out}) -> {Time, Reds, In, Out+1};
stat(_, StatData) -> StatData.
trim(N, LogData) ->
@@ -580,9 +602,9 @@ trim(N, LogData) ->
%% Debug structure manipulating functions
%%-----------------------------------------------------------------
install_debug(Item, Data, Debug) ->
- case get_debug2(Item, Debug, undefined) of
- undefined -> [{Item, Data} | Debug];
- _ -> Debug
+ case lists:keysearch(Item, 1, Debug) of
+ false -> [{Item, Data} | Debug];
+ _ -> Debug
end.
remove_debug(Item, Debug) -> lists:keydelete(Item, 1, Debug).
@@ -633,7 +655,8 @@ close_log_file(Debug) ->
| {'log_to_file', FileName}
| {'install', FuncSpec},
FileName :: file:name(),
- FuncSpec :: {Func, FuncState},
+ FuncSpec :: {Func, FuncState} | {FuncId, Func, FuncState},
+ FuncId :: term(),
Func :: dbg_fun(),
FuncState :: term().
debug_options(Options) ->
@@ -656,6 +679,8 @@ debug_options([{log_to_file, FileName} | T], Debug) ->
end;
debug_options([{install, {Func, FuncState}} | T], Debug) ->
debug_options(T, install_debug(Func, FuncState, Debug));
+debug_options([{install, {FuncId, Func, FuncState}} | T], Debug) ->
+ debug_options(T, install_debug(FuncId, {Func, FuncState}, Debug));
debug_options([_ | T], Debug) ->
debug_options(T, Debug);
debug_options([], Debug) ->
diff --git a/lib/stdlib/src/uri_string.erl b/lib/stdlib/src/uri_string.erl
new file mode 100644
index 0000000000..f07307c039
--- /dev/null
+++ b/lib/stdlib/src/uri_string.erl
@@ -0,0 +1,2148 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+%% [RFC 3986, Chapter 2.2. Reserved Characters]
+%%
+%% reserved = gen-delims / sub-delims
+%%
+%% gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+%%
+%% sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+%% / "*" / "+" / "," / ";" / "="
+%%
+%%
+%% [RFC 3986, Chapter 2.3. Unreserved Characters]
+%%
+%% unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+%%
+%%
+%% [RFC 3986, Chapter 3. Syntax Components]
+%%
+%% The generic URI syntax consists of a hierarchical sequence of
+%% components referred to as the scheme, authority, path, query, and
+%% fragment.
+%%
+%% URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+%%
+%% hier-part = "//" authority path-abempty
+%% / path-absolute
+%% / path-rootless
+%% / path-empty
+%%
+%% The scheme and path components are required, though the path may be
+%% empty (no characters). When authority is present, the path must
+%% either be empty or begin with a slash ("/") character. When
+%% authority is not present, the path cannot begin with two slash
+%% characters ("//"). These restrictions result in five different ABNF
+%% rules for a path (Section 3.3), only one of which will match any
+%% given URI reference.
+%%
+%% The following are two example URIs and their component parts:
+%%
+%% foo://example.com:8042/over/there?name=ferret#nose
+%% \_/ \______________/\_________/ \_________/ \__/
+%% | | | | |
+%% scheme authority path query fragment
+%% | _____________________|__
+%% / \ / \
+%% urn:example:animal:ferret:nose
+%%
+%%
+%% [RFC 3986, Chapter 3.1. Scheme]
+%%
+%% Each URI begins with a scheme name that refers to a specification for
+%% assigning identifiers within that scheme.
+%%
+%% scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+%%
+%%
+%% [RFC 3986, Chapter 3.2. Authority]
+%%
+%% Many URI schemes include a hierarchical element for a naming
+%% authority so that governance of the name space defined by the
+%% remainder of the URI is delegated to that authority (which may, in
+%% turn, delegate it further).
+%%
+%% authority = [ userinfo "@" ] host [ ":" port ]
+%%
+%%
+%% [RFC 3986, Chapter 3.2.1. User Information]
+%%
+%% The userinfo subcomponent may consist of a user name and, optionally,
+%% scheme-specific information about how to gain authorization to access
+%% the resource. The user information, if present, is followed by a
+%% commercial at-sign ("@") that delimits it from the host.
+%%
+%% userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
+%%
+%%
+%% [RFC 3986, Chapter 3.2.2. Host]
+%%
+%% The host subcomponent of authority is identified by an IP literal
+%% encapsulated within square brackets, an IPv4 address in dotted-
+%% decimal form, or a registered name.
+%%
+%% host = IP-literal / IPv4address / reg-name
+%%
+%% IP-literal = "[" ( IPv6address / IPvFuture ) "]"
+%%
+%% IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+%%
+%% IPv6address = 6( h16 ":" ) ls32
+%% / "::" 5( h16 ":" ) ls32
+%% / [ h16 ] "::" 4( h16 ":" ) ls32
+%% / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+%% / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+%% / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
+%% / [ *4( h16 ":" ) h16 ] "::" ls32
+%% / [ *5( h16 ":" ) h16 ] "::" h16
+%% / [ *6( h16 ":" ) h16 ] "::"
+%%
+%% ls32 = ( h16 ":" h16 ) / IPv4address
+%% ; least-significant 32 bits of address
+%%
+%% h16 = 1*4HEXDIG
+%% ; 16 bits of address represented in hexadecimal
+%%
+%% IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
+%%
+%% dec-octet = DIGIT ; 0-9
+%% / %x31-39 DIGIT ; 10-99
+%% / "1" 2DIGIT ; 100-199
+%% / "2" %x30-34 DIGIT ; 200-249
+%% / "25" %x30-35 ; 250-255
+%%
+%% reg-name = *( unreserved / pct-encoded / sub-delims )
+%%
+%%
+%% [RFC 3986, Chapter 3.2.2. Port]
+%%
+%% The port subcomponent of authority is designated by an optional port
+%% number in decimal following the host and delimited from it by a
+%% single colon (":") character.
+%%
+%% port = *DIGIT
+%%
+%%
+%% [RFC 3986, Chapter 3.3. Path]
+%%
+%% The path component contains data, usually organized in hierarchical
+%% form, that, along with data in the non-hierarchical query component
+%% (Section 3.4), serves to identify a resource within the scope of the
+%% URI's scheme and naming authority (if any). The path is terminated
+%% by the first question mark ("?") or number sign ("#") character, or
+%% by the end of the URI.
+%%
+%% path = path-abempty ; begins with "/" or is empty
+%% / path-absolute ; begins with "/" but not "//"
+%% / path-noscheme ; begins with a non-colon segment
+%% / path-rootless ; begins with a segment
+%% / path-empty ; zero characters
+%%
+%% path-abempty = *( "/" segment )
+%% path-absolute = "/" [ segment-nz *( "/" segment ) ]
+%% path-noscheme = segment-nz-nc *( "/" segment )
+%% path-rootless = segment-nz *( "/" segment )
+%% path-empty = 0<pchar>
+%% segment = *pchar
+%% segment-nz = 1*pchar
+%% segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
+%% ; non-zero-length segment without any colon ":"
+%%
+%% pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+%%
+%%
+%% [RFC 3986, Chapter 3.4. Query]
+%%
+%% The query component contains non-hierarchical data that, along with
+%% data in the path component (Section 3.3), serves to identify a
+%% resource within the scope of the URI's scheme and naming authority
+%% (if any). The query component is indicated by the first question
+%% mark ("?") character and terminated by a number sign ("#") character
+%% or by the end of the URI.
+%%
+%% query = *( pchar / "/" / "?" )
+%%
+%%
+%% [RFC 3986, Chapter 3.5. Fragment]
+%%
+%% The fragment identifier component of a URI allows indirect
+%% identification of a secondary resource by reference to a primary
+%% resource and additional identifying information.
+%%
+%% fragment = *( pchar / "/" / "?" )
+%%
+%%
+%% [RFC 3986, Chapter 4.1. URI Reference]
+%%
+%% URI-reference is used to denote the most common usage of a resource
+%% identifier.
+%%
+%% URI-reference = URI / relative-ref
+%%
+%%
+%% [RFC 3986, Chapter 4.2. Relative Reference]
+%%
+%% A relative reference takes advantage of the hierarchical syntax
+%% (Section 1.2.3) to express a URI reference relative to the name space
+%% of another hierarchical URI.
+%%
+%% relative-ref = relative-part [ "?" query ] [ "#" fragment ]
+%%
+%% relative-part = "//" authority path-abempty
+%% / path-absolute
+%% / path-noscheme
+%% / path-empty
+%%
+%%
+%% [RFC 3986, Chapter 4.3. Absolute URI]
+%%
+%% Some protocol elements allow only the absolute form of a URI without
+%% a fragment identifier. For example, defining a base URI for later
+%% use by relative references calls for an absolute-URI syntax rule that
+%% does not allow a fragment.
+%%
+%% absolute-URI = scheme ":" hier-part [ "?" query ]
+%%
+-module(uri_string).
+
+%%-------------------------------------------------------------------------
+%% External API
+%%-------------------------------------------------------------------------
+-export([compose_query/1, compose_query/2,
+ dissect_query/1, normalize/1, normalize/2, parse/1,
+ recompose/1, transcode/2]).
+-export_type([error/0, uri_map/0, uri_string/0]).
+
+
+%%-------------------------------------------------------------------------
+%% Internal API
+%%-------------------------------------------------------------------------
+-export([is_host/1, is_path/1]). % suppress warnings
+
+
+%%-------------------------------------------------------------------------
+%% Macros
+%%-------------------------------------------------------------------------
+-define(CHAR(Char), <<Char/utf8>>).
+-define(STRING_EMPTY, <<>>).
+-define(STRING(MatchStr), <<MatchStr/binary>>).
+-define(STRING_REST(MatchStr, Rest), <<MatchStr/utf8, Rest/binary>>).
+
+-define(DEC2HEX(X),
+ if ((X) >= 0) andalso ((X) =< 9) -> (X) + $0;
+ ((X) >= 10) andalso ((X) =< 15) -> (X) + $A - 10
+ end).
+
+-define(HEX2DEC(X),
+ if ((X) >= $0) andalso ((X) =< $9) -> (X) - $0;
+ ((X) >= $A) andalso ((X) =< $F) -> (X) - $A + 10;
+ ((X) >= $a) andalso ((X) =< $f) -> (X) - $a + 10
+ end).
+
+
+%%%=========================================================================
+%%% API
+%%%=========================================================================
+
+%%-------------------------------------------------------------------------
+%% URI compliant with RFC 3986
+%% ASCII %x21 - %x7A ("!" - "z") except
+%% %x34 " double quote
+%% %x60 < less than
+%% %x62 > greater than
+%% %x92 \ backslash
+%% %x94 ^ caret / circumflex
+%% %x96 ` grave / accent
+%%-------------------------------------------------------------------------
+-type uri_string() :: iodata().
+-type error() :: {error, atom(), term()}.
+
+
+%%-------------------------------------------------------------------------
+%% RFC 3986, Chapter 3. Syntax Components
+%%-------------------------------------------------------------------------
+-type uri_map() ::
+ #{fragment => unicode:chardata(),
+ host => unicode:chardata(),
+ path => unicode:chardata(),
+ port => non_neg_integer() | undefined,
+ query => unicode:chardata(),
+ scheme => unicode:chardata(),
+ userinfo => unicode:chardata()} | #{}.
+
+
+%%-------------------------------------------------------------------------
+%% Normalize URIs
+%%-------------------------------------------------------------------------
+-spec normalize(URI) -> NormalizedURI when
+ URI :: uri_string() | uri_map(),
+ NormalizedURI :: uri_string()
+ | error().
+normalize(URIMap) ->
+ try normalize(URIMap, [])
+ catch
+ throw:{error, Atom, RestData} -> {error, Atom, RestData}
+ end.
+
+
+-spec normalize(URI, Options) -> NormalizedURI when
+ URI :: uri_string() | uri_map(),
+ Options :: [return_map],
+ NormalizedURI :: uri_string() | uri_map().
+normalize(URIMap, []) when is_map(URIMap) ->
+ recompose(normalize_map(URIMap));
+normalize(URIMap, [return_map]) when is_map(URIMap) ->
+ normalize_map(URIMap);
+normalize(URIString, []) ->
+ case parse(URIString) of
+ Value when is_map(Value) ->
+ recompose(normalize_map(Value));
+ Error ->
+ Error
+ end;
+normalize(URIString, [return_map]) ->
+ case parse(URIString) of
+ Value when is_map(Value) ->
+ normalize_map(Value);
+ Error ->
+ Error
+ end.
+
+
+%%-------------------------------------------------------------------------
+%% Parse URIs
+%%-------------------------------------------------------------------------
+-spec parse(URIString) -> URIMap when
+ URIString :: uri_string(),
+ URIMap :: uri_map()
+ | error().
+parse(URIString) when is_binary(URIString) ->
+ try parse_uri_reference(URIString, #{})
+ catch
+ throw:{error, Atom, RestData} -> {error, Atom, RestData}
+ end;
+parse(URIString) when is_list(URIString) ->
+ try
+ Binary = unicode:characters_to_binary(URIString),
+ Map = parse_uri_reference(Binary, #{}),
+ convert_mapfields_to_list(Map)
+ catch
+ throw:{error, Atom, RestData} -> {error, Atom, RestData}
+ end.
+
+
+%%-------------------------------------------------------------------------
+%% Recompose URIs
+%%-------------------------------------------------------------------------
+-spec recompose(URIMap) -> URIString when
+ URIMap :: uri_map(),
+ URIString :: uri_string()
+ | error().
+recompose(Map) ->
+ case is_valid_map(Map) of
+ false ->
+ {error, invalid_map, Map};
+ true ->
+ try
+ T0 = update_scheme(Map, empty),
+ T1 = update_userinfo(Map, T0),
+ T2 = update_host(Map, T1),
+ T3 = update_port(Map, T2),
+ T4 = update_path(Map, T3),
+ T5 = update_query(Map, T4),
+ update_fragment(Map, T5)
+ catch
+ throw:{error, Atom, RestData} -> {error, Atom, RestData}
+ end
+ end.
+
+
+%%-------------------------------------------------------------------------
+%% Transcode URIs
+%%-------------------------------------------------------------------------
+-spec transcode(URIString, Options) -> Result when
+ URIString :: uri_string(),
+ Options :: [{in_encoding, unicode:encoding()}|{out_encoding, unicode:encoding()}],
+ Result :: uri_string()
+ | error().
+transcode(URIString, Options) when is_binary(URIString) ->
+ try
+ InEnc = proplists:get_value(in_encoding, Options, utf8),
+ OutEnc = proplists:get_value(out_encoding, Options, utf8),
+ List = convert_to_list(URIString, InEnc),
+ Output = transcode(List, [], InEnc, OutEnc),
+ convert_to_binary(Output, utf8, OutEnc)
+ catch
+ throw:{error, Atom, RestData} -> {error, Atom, RestData}
+ end;
+transcode(URIString, Options) when is_list(URIString) ->
+ InEnc = proplists:get_value(in_encoding, Options, utf8),
+ OutEnc = proplists:get_value(out_encoding, Options, utf8),
+ Flattened = flatten_list(URIString, InEnc),
+ try transcode(Flattened, [], InEnc, OutEnc)
+ catch
+ throw:{error, Atom, RestData} -> {error, Atom, RestData}
+ end.
+
+
+%%-------------------------------------------------------------------------
+%% Functions for working with the query part of a URI as a list
+%% of key/value pairs.
+%% HTML 5.2 - 4.10.21.6 URL-encoded form data - WHATWG URL (10 Jan 2018) - UTF-8
+%% HTML 5.0 - 4.10.22.6 URL-encoded form data - non UTF-8
+%%-------------------------------------------------------------------------
+
+%%-------------------------------------------------------------------------
+%% Compose urlencoded query string from a list of unescaped key/value pairs.
+%% (application/x-www-form-urlencoded encoding algorithm)
+%%-------------------------------------------------------------------------
+-spec compose_query(QueryList) -> QueryString when
+ QueryList :: [{unicode:chardata(), unicode:chardata()}],
+ QueryString :: uri_string()
+ | error().
+compose_query(List) ->
+ compose_query(List, [{encoding, utf8}]).
+
+
+-spec compose_query(QueryList, Options) -> QueryString when
+ QueryList :: [{unicode:chardata(), unicode:chardata()}],
+ Options :: [{encoding, atom()}],
+ QueryString :: uri_string()
+ | error().
+compose_query([],_Options) ->
+ [];
+compose_query(List, Options) ->
+ try compose_query(List, Options, false, <<>>)
+ catch
+ throw:{error, Atom, RestData} -> {error, Atom, RestData}
+ end.
+%%
+compose_query([{Key,Value}|Rest], Options, IsList, Acc) ->
+ Separator = get_separator(Rest),
+ K = form_urlencode(Key, Options),
+ V = form_urlencode(Value, Options),
+ IsListNew = IsList orelse is_list(Key) orelse is_list(Value),
+ compose_query(Rest, Options, IsListNew, <<Acc/binary,K/binary,"=",V/binary,Separator/binary>>);
+compose_query([], _Options, IsList, Acc) ->
+ case IsList of
+ true -> convert_to_list(Acc, utf8);
+ false -> Acc
+ end.
+
+
+%%-------------------------------------------------------------------------
+%% Dissect a query string into a list of unescaped key/value pairs.
+%% (application/x-www-form-urlencoded decoding algorithm)
+%%-------------------------------------------------------------------------
+-spec dissect_query(QueryString) -> QueryList when
+ QueryString :: uri_string(),
+ QueryList :: [{unicode:chardata(), unicode:chardata()}]
+ | error().
+dissect_query(<<>>) ->
+ [];
+dissect_query([]) ->
+ [];
+dissect_query(QueryString) when is_list(QueryString) ->
+ try
+ B = convert_to_binary(QueryString, utf8, utf8),
+ dissect_query_key(B, true, [], <<>>, <<>>)
+ catch
+ throw:{error, Atom, RestData} -> {error, Atom, RestData}
+ end;
+dissect_query(QueryString) ->
+ try dissect_query_key(QueryString, false, [], <<>>, <<>>)
+ catch
+ throw:{error, Atom, RestData} -> {error, Atom, RestData}
+ end.
+
+
+%%%========================================================================
+%%% Internal functions
+%%%========================================================================
+
+%%-------------------------------------------------------------------------
+%% Converts Map fields to lists
+%%-------------------------------------------------------------------------
+convert_mapfields_to_list(Map) ->
+ Fun = fun (_, V) when is_binary(V) -> unicode:characters_to_list(V);
+ (_, V) -> V end,
+ maps:map(Fun, Map).
+
+
+%%-------------------------------------------------------------------------
+%% [RFC 3986, Chapter 4.1. URI Reference]
+%%
+%% URI-reference is used to denote the most common usage of a resource
+%% identifier.
+%%
+%% URI-reference = URI / relative-ref
+%%-------------------------------------------------------------------------
+-spec parse_uri_reference(binary(), uri_map()) -> uri_map().
+parse_uri_reference(<<>>, _) -> #{path => <<>>};
+parse_uri_reference(URIString, URI) ->
+ try parse_scheme_start(URIString, URI)
+ catch
+ throw:{_,_,_} ->
+ parse_relative_part(URIString, URI)
+ end.
+
+
+%%-------------------------------------------------------------------------
+%% [RFC 3986, Chapter 4.2. Relative Reference]
+%%
+%% A relative reference takes advantage of the hierarchical syntax
+%% (Section 1.2.3) to express a URI reference relative to the name space
+%% of another hierarchical URI.
+%%
+%% relative-ref = relative-part [ "?" query ] [ "#" fragment ]
+%%
+%% relative-part = "//" authority path-abempty
+%% / path-absolute
+%% / path-noscheme
+%% / path-empty
+%%-------------------------------------------------------------------------
+-spec parse_relative_part(binary(), uri_map()) -> uri_map().
+parse_relative_part(?STRING_REST("//", Rest), URI) ->
+ %% Parse userinfo - "//" is NOT part of authority
+ try parse_userinfo(Rest, URI) of
+ {T, URI1} ->
+ Userinfo = calculate_parsed_userinfo(Rest, T),
+ URI2 = maybe_add_path(URI1),
+ URI2#{userinfo => Userinfo}
+ catch
+ throw:{_,_,_} ->
+ {T, URI1} = parse_host(Rest, URI),
+ Host = calculate_parsed_host_port(Rest, T),
+ URI2 = maybe_add_path(URI1),
+ URI2#{host => remove_brackets(Host)}
+ end;
+parse_relative_part(?STRING_REST($/, Rest), URI) ->
+ {T, URI1} = parse_segment(Rest, URI), % path-absolute
+ Path = calculate_parsed_part(Rest, T),
+ URI1#{path => ?STRING_REST($/, Path)};
+parse_relative_part(?STRING_REST($?, Rest), URI) ->
+ {T, URI1} = parse_query(Rest, URI), % path-empty ?query
+ Query = calculate_parsed_query_fragment(Rest, T),
+ URI2 = maybe_add_path(URI1),
+ URI2#{query => Query};
+parse_relative_part(?STRING_REST($#, Rest), URI) ->
+ {T, URI1} = parse_fragment(Rest, URI), % path-empty
+ Fragment = calculate_parsed_query_fragment(Rest, T),
+ URI2 = maybe_add_path(URI1),
+ URI2#{fragment => Fragment};
+parse_relative_part(?STRING_REST(Char, Rest), URI) ->
+ case is_segment_nz_nc(Char) of
+ true ->
+ {T, URI1} = parse_segment_nz_nc(Rest, URI), % path-noscheme
+ Path = calculate_parsed_part(Rest, T),
+ URI1#{path => ?STRING_REST(Char, Path)};
+ false -> throw({error,invalid_uri,[Char]})
+ end.
+
+
+%%-------------------------------------------------------------------------
+%% [RFC 3986, Chapter 3.3. Path]
+%%
+%% The path component contains data, usually organized in hierarchical
+%% form, that, along with data in the non-hierarchical query component
+%% (Section 3.4), serves to identify a resource within the scope of the
+%% URI's scheme and naming authority (if any). The path is terminated
+%% by the first question mark ("?") or number sign ("#") character, or
+%% by the end of the URI.
+%%
+%% path = path-abempty ; begins with "/" or is empty
+%% / path-absolute ; begins with "/" but not "//"
+%% / path-noscheme ; begins with a non-colon segment
+%% / path-rootless ; begins with a segment
+%% / path-empty ; zero characters
+%%
+%% path-abempty = *( "/" segment )
+%% path-absolute = "/" [ segment-nz *( "/" segment ) ]
+%% path-noscheme = segment-nz-nc *( "/" segment )
+%% path-rootless = segment-nz *( "/" segment )
+%% path-empty = 0<pchar>
+%% segment = *pchar
+%% segment-nz = 1*pchar
+%% segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
+%% ; non-zero-length segment without any colon ":"
+%%
+%% pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+%%-------------------------------------------------------------------------
+
+%%-------------------------------------------------------------------------
+%% path-abempty
+%%-------------------------------------------------------------------------
+-spec parse_segment(binary(), uri_map()) -> {binary(), uri_map()}.
+parse_segment(?STRING_REST($/, Rest), URI) ->
+ parse_segment(Rest, URI); % segment
+parse_segment(?STRING_REST($?, Rest), URI) ->
+ {T, URI1} = parse_query(Rest, URI), % ?query
+ Query = calculate_parsed_query_fragment(Rest, T),
+ {Rest, URI1#{query => Query}};
+parse_segment(?STRING_REST($#, Rest), URI) ->
+ {T, URI1} = parse_fragment(Rest, URI),
+ Fragment = calculate_parsed_query_fragment(Rest, T),
+ {Rest, URI1#{fragment => Fragment}};
+parse_segment(?STRING_REST(Char, Rest), URI) ->
+ case is_pchar(Char) of
+ true -> parse_segment(Rest, URI);
+ false -> throw({error,invalid_uri,[Char]})
+ end;
+parse_segment(?STRING_EMPTY, URI) ->
+ {?STRING_EMPTY, URI}.
+
+
+%%-------------------------------------------------------------------------
+%% path-noscheme
+%%-------------------------------------------------------------------------
+-spec parse_segment_nz_nc(binary(), uri_map()) -> {binary(), uri_map()}.
+parse_segment_nz_nc(?STRING_REST($/, Rest), URI) ->
+ parse_segment(Rest, URI); % segment
+parse_segment_nz_nc(?STRING_REST($?, Rest), URI) ->
+ {T, URI1} = parse_query(Rest, URI), % ?query
+ Query = calculate_parsed_query_fragment(Rest, T),
+ {Rest, URI1#{query => Query}};
+parse_segment_nz_nc(?STRING_REST($#, Rest), URI) ->
+ {T, URI1} = parse_fragment(Rest, URI),
+ Fragment = calculate_parsed_query_fragment(Rest, T),
+ {Rest, URI1#{fragment => Fragment}};
+parse_segment_nz_nc(?STRING_REST(Char, Rest), URI) ->
+ case is_segment_nz_nc(Char) of
+ true -> parse_segment_nz_nc(Rest, URI);
+ false -> throw({error,invalid_uri,[Char]})
+ end;
+parse_segment_nz_nc(?STRING_EMPTY, URI) ->
+ {?STRING_EMPTY, URI}.
+
+
+%% Check if char is pchar.
+-spec is_pchar(char()) -> boolean().
+is_pchar($%) -> true; % pct-encoded
+is_pchar($:) -> true;
+is_pchar($@) -> true;
+is_pchar(Char) -> is_unreserved(Char) orelse is_sub_delim(Char).
+
+%% Check if char is segment_nz_nc.
+-spec is_segment_nz_nc(char()) -> boolean().
+is_segment_nz_nc($%) -> true; % pct-encoded
+is_segment_nz_nc($@) -> true;
+is_segment_nz_nc(Char) -> is_unreserved(Char) orelse is_sub_delim(Char).
+
+
+%%-------------------------------------------------------------------------
+%% [RFC 3986, Chapter 3.1. Scheme]
+%%
+%% Each URI begins with a scheme name that refers to a specification for
+%% assigning identifiers within that scheme.
+%%
+%% scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+%%-------------------------------------------------------------------------
+-spec parse_scheme_start(binary(), uri_map()) -> uri_map().
+parse_scheme_start(?STRING_REST(Char, Rest), URI) ->
+ case is_alpha(Char) of
+ true -> {T, URI1} = parse_scheme(Rest, URI),
+ Scheme = calculate_parsed_scheme(Rest, T),
+ URI2 = maybe_add_path(URI1),
+ URI2#{scheme => ?STRING_REST(Char, Scheme)};
+ false -> throw({error,invalid_uri,[Char]})
+ end.
+
+%% Add path component if it missing after parsing the URI.
+%% According to the URI specification there is always a
+%% path component in every URI-reference and it can be
+%% empty.
+maybe_add_path(Map) ->
+ case maps:is_key(path, Map) of
+ false ->
+ Map#{path => <<>>};
+ _Else ->
+ Map
+ end.
+
+
+
+-spec parse_scheme(binary(), uri_map()) -> {binary(), uri_map()}.
+parse_scheme(?STRING_REST($:, Rest), URI) ->
+ {_, URI1} = parse_hier(Rest, URI),
+ {Rest, URI1};
+parse_scheme(?STRING_REST(Char, Rest), URI) ->
+ case is_scheme(Char) of
+ true -> parse_scheme(Rest, URI);
+ false -> throw({error,invalid_uri,[Char]})
+ end;
+parse_scheme(?STRING_EMPTY, _URI) ->
+ throw({error,invalid_uri,<<>>}).
+
+
+%% Check if char is allowed in scheme
+-spec is_scheme(char()) -> boolean().
+is_scheme($+) -> true;
+is_scheme($-) -> true;
+is_scheme($.) -> true;
+is_scheme(Char) -> is_alpha(Char) orelse is_digit(Char).
+
+
+%%-------------------------------------------------------------------------
+%% hier-part = "//" authority path-abempty
+%% / path-absolute
+%% / path-rootless
+%% / path-empty
+%%-------------------------------------------------------------------------
+-spec parse_hier(binary(), uri_map()) -> {binary(), uri_map()}.
+parse_hier(?STRING_REST("//", Rest), URI) ->
+ % Parse userinfo - "//" is NOT part of authority
+ try parse_userinfo(Rest, URI) of
+ {T, URI1} ->
+ Userinfo = calculate_parsed_userinfo(Rest, T),
+ {Rest, URI1#{userinfo => Userinfo}}
+ catch
+ throw:{_,_,_} ->
+ {T, URI1} = parse_host(Rest, URI),
+ Host = calculate_parsed_host_port(Rest, T),
+ {Rest, URI1#{host => remove_brackets(Host)}}
+ end;
+parse_hier(?STRING_REST($/, Rest), URI) ->
+ {T, URI1} = parse_segment(Rest, URI), % path-absolute
+ Path = calculate_parsed_part(Rest, T),
+ {Rest, URI1#{path => ?STRING_REST($/, Path)}};
+parse_hier(?STRING_REST($?, Rest), URI) ->
+ {T, URI1} = parse_query(Rest, URI), % path-empty ?query
+ Query = calculate_parsed_query_fragment(Rest, T),
+ {Rest, URI1#{query => Query}};
+parse_hier(?STRING_REST($#, Rest), URI) ->
+ {T, URI1} = parse_fragment(Rest, URI), % path-empty
+ Fragment = calculate_parsed_query_fragment(Rest, T),
+ {Rest, URI1#{fragment => Fragment}};
+parse_hier(?STRING_REST(Char, Rest), URI) -> % path-rootless
+ case is_pchar(Char) of
+ true -> % segment_nz
+ {T, URI1} = parse_segment(Rest, URI),
+ Path = calculate_parsed_part(Rest, T),
+ {Rest, URI1#{path => ?STRING_REST(Char, Path)}};
+ false -> throw({error,invalid_uri,[Char]})
+ end;
+parse_hier(?STRING_EMPTY, URI) ->
+ {<<>>, URI}.
+
+
+%%-------------------------------------------------------------------------
+%% [RFC 3986, Chapter 3.2. Authority]
+%%
+%% Many URI schemes include a hierarchical element for a naming
+%% authority so that governance of the name space defined by the
+%% remainder of the URI is delegated to that authority (which may, in
+%% turn, delegate it further).
+%%
+%% The authority component is preceded by a double slash ("//") and is
+%% terminated by the next slash ("/"), question mark ("?"), or number
+%% sign ("#") character, or by the end of the URI.
+%%
+%% authority = [ userinfo "@" ] host [ ":" port ]
+%%
+%%
+%% [RFC 3986, Chapter 3.2.1. User Information]
+%%
+%% The userinfo subcomponent may consist of a user name and, optionally,
+%% scheme-specific information about how to gain authorization to access
+%% the resource. The user information, if present, is followed by a
+%% commercial at-sign ("@") that delimits it from the host.
+%%
+%% userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
+%%-------------------------------------------------------------------------
+-spec parse_userinfo(binary(), uri_map()) -> {binary(), uri_map()}.
+parse_userinfo(?CHAR($@), URI) ->
+ {?STRING_EMPTY, URI#{host => <<>>}};
+parse_userinfo(?STRING_REST($@, Rest), URI) ->
+ {T, URI1} = parse_host(Rest, URI),
+ Host = calculate_parsed_host_port(Rest, T),
+ {Rest, URI1#{host => remove_brackets(Host)}};
+parse_userinfo(?STRING_REST(Char, Rest), URI) ->
+ case is_userinfo(Char) of
+ true -> parse_userinfo(Rest, URI);
+ false -> throw({error,invalid_uri,[Char]})
+ end;
+parse_userinfo(?STRING_EMPTY, _URI) ->
+ %% URI cannot end in userinfo state
+ throw({error,invalid_uri,<<>>}).
+
+
+%% Check if char is allowed in userinfo
+-spec is_userinfo(char()) -> boolean().
+is_userinfo($%) -> true; % pct-encoded
+is_userinfo($:) -> true;
+is_userinfo(Char) -> is_unreserved(Char) orelse is_sub_delim(Char).
+
+
+%%-------------------------------------------------------------------------
+%% [RFC 3986, Chapter 3.2.2. Host]
+%%
+%% The host subcomponent of authority is identified by an IP literal
+%% encapsulated within square brackets, an IPv4 address in dotted-
+%% decimal form, or a registered name.
+%%
+%% host = IP-literal / IPv4address / reg-name
+%%
+%% IP-literal = "[" ( IPv6address / IPvFuture ) "]"
+%%
+%% IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+%%
+%% IPv6address = 6( h16 ":" ) ls32
+%% / "::" 5( h16 ":" ) ls32
+%% / [ h16 ] "::" 4( h16 ":" ) ls32
+%% / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+%% / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+%% / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
+%% / [ *4( h16 ":" ) h16 ] "::" ls32
+%% / [ *5( h16 ":" ) h16 ] "::" h16
+%% / [ *6( h16 ":" ) h16 ] "::"
+%%
+%% ls32 = ( h16 ":" h16 ) / IPv4address
+%% ; least-significant 32 bits of address
+%%
+%% h16 = 1*4HEXDIG
+%% ; 16 bits of address represented in hexadecimal
+%%
+%% IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
+%%
+%% dec-octet = DIGIT ; 0-9
+%% / %x31-39 DIGIT ; 10-99
+%% / "1" 2DIGIT ; 100-199
+%% / "2" %x30-34 DIGIT ; 200-249
+%% / "25" %x30-35 ; 250-255
+%%
+%% reg-name = *( unreserved / pct-encoded / sub-delims )
+%%-------------------------------------------------------------------------
+-spec parse_host(binary(), uri_map()) -> {binary(), uri_map()}.
+parse_host(?STRING_REST($:, Rest), URI) ->
+ {T, URI1} = parse_port(Rest, URI),
+ H = calculate_parsed_host_port(Rest, T),
+ Port = get_port(H),
+ {Rest, URI1#{port => Port}};
+parse_host(?STRING_REST($/, Rest), URI) ->
+ {T, URI1} = parse_segment(Rest, URI), % path-abempty
+ Path = calculate_parsed_part(Rest, T),
+ {Rest, URI1#{path => ?STRING_REST($/, Path)}};
+parse_host(?STRING_REST($?, Rest), URI) ->
+ {T, URI1} = parse_query(Rest, URI), % path-empty ?query
+ Query = calculate_parsed_query_fragment(Rest, T),
+ {Rest, URI1#{query => Query}};
+parse_host(?STRING_REST($[, Rest), URI) ->
+ parse_ipv6_bin(Rest, [], URI);
+parse_host(?STRING_REST($#, Rest), URI) ->
+ {T, URI1} = parse_fragment(Rest, URI), % path-empty
+ Fragment = calculate_parsed_query_fragment(Rest, T),
+ {Rest, URI1#{fragment => Fragment}};
+parse_host(?STRING_REST(Char, Rest), URI) ->
+ case is_digit(Char) of
+ true ->
+ try parse_ipv4_bin(Rest, [Char], URI)
+ catch
+ throw:{_,_,_} ->
+ parse_reg_name(?STRING_REST(Char, Rest), URI)
+ end;
+ false -> parse_reg_name(?STRING_REST(Char, Rest), URI)
+ end;
+parse_host(?STRING_EMPTY, URI) ->
+ {?STRING_EMPTY, URI}.
+
+
+-spec parse_reg_name(binary(), uri_map()) -> {binary(), uri_map()}.
+parse_reg_name(?STRING_REST($:, Rest), URI) ->
+ {T, URI1} = parse_port(Rest, URI),
+ H = calculate_parsed_host_port(Rest, T),
+ Port = get_port(H),
+ {Rest, URI1#{port => Port}};
+parse_reg_name(?STRING_REST($/, Rest), URI) ->
+ {T, URI1} = parse_segment(Rest, URI), % path-abempty
+ Path = calculate_parsed_part(Rest, T),
+ {Rest, URI1#{path => ?STRING_REST($/, Path)}};
+parse_reg_name(?STRING_REST($?, Rest), URI) ->
+ {T, URI1} = parse_query(Rest, URI), % path-empty ?query
+ Query = calculate_parsed_query_fragment(Rest, T),
+ {Rest, URI1#{query => Query}};
+parse_reg_name(?STRING_REST($#, Rest), URI) ->
+ {T, URI1} = parse_fragment(Rest, URI), % path-empty
+ Fragment = calculate_parsed_query_fragment(Rest, T),
+ {Rest, URI1#{fragment => Fragment}};
+parse_reg_name(?STRING_REST(Char, Rest), URI) ->
+ case is_reg_name(Char) of
+ true -> parse_reg_name(Rest, URI);
+ false -> throw({error,invalid_uri,[Char]})
+ end;
+parse_reg_name(?STRING_EMPTY, URI) ->
+ {?STRING_EMPTY, URI}.
+
+%% Check if char is allowed in reg-name
+-spec is_reg_name(char()) -> boolean().
+is_reg_name($%) -> true;
+is_reg_name(Char) -> is_unreserved(Char) orelse is_sub_delim(Char).
+
+
+-spec parse_ipv4_bin(binary(), list(), uri_map()) -> {binary(), uri_map()}.
+parse_ipv4_bin(?STRING_REST($:, Rest), Acc, URI) ->
+ _ = validate_ipv4_address(lists:reverse(Acc)),
+ {T, URI1} = parse_port(Rest, URI),
+ H = calculate_parsed_host_port(Rest, T),
+ Port = get_port(H),
+ {Rest, URI1#{port => Port}};
+parse_ipv4_bin(?STRING_REST($/, Rest), Acc, URI) ->
+ _ = validate_ipv4_address(lists:reverse(Acc)),
+ {T, URI1} = parse_segment(Rest, URI), % path-abempty
+ Path = calculate_parsed_part(Rest, T),
+ {Rest, URI1#{path => ?STRING_REST($/, Path)}};
+parse_ipv4_bin(?STRING_REST($?, Rest), Acc, URI) ->
+ _ = validate_ipv4_address(lists:reverse(Acc)),
+ {T, URI1} = parse_query(Rest, URI), % path-empty ?query
+ Query = calculate_parsed_query_fragment(Rest, T),
+ {Rest, URI1#{query => Query}};
+parse_ipv4_bin(?STRING_REST($#, Rest), Acc, URI) ->
+ _ = validate_ipv4_address(lists:reverse(Acc)),
+ {T, URI1} = parse_fragment(Rest, URI), % path-empty
+ Fragment = calculate_parsed_query_fragment(Rest, T),
+ {Rest, URI1#{fragment => Fragment}};
+parse_ipv4_bin(?STRING_REST(Char, Rest), Acc, URI) ->
+ case is_ipv4(Char) of
+ true -> parse_ipv4_bin(Rest, [Char|Acc], URI);
+ false -> throw({error,invalid_uri,[Char]})
+ end;
+parse_ipv4_bin(?STRING_EMPTY, Acc, URI) ->
+ _ = validate_ipv4_address(lists:reverse(Acc)),
+ {?STRING_EMPTY, URI}.
+
+
+%% Check if char is allowed in IPv4 addresses
+-spec is_ipv4(char()) -> boolean().
+is_ipv4($.) -> true;
+is_ipv4(Char) -> is_digit(Char).
+
+-spec validate_ipv4_address(list()) -> list().
+validate_ipv4_address(Addr) ->
+ case inet:parse_ipv4strict_address(Addr) of
+ {ok, _} -> Addr;
+ {error, _} -> throw({error,invalid_uri,Addr})
+ end.
+
+
+-spec parse_ipv6_bin(binary(), list(), uri_map()) -> {binary(), uri_map()}.
+parse_ipv6_bin(?STRING_REST($], Rest), Acc, URI) ->
+ _ = validate_ipv6_address(lists:reverse(Acc)),
+ parse_ipv6_bin_end(Rest, URI);
+parse_ipv6_bin(?STRING_REST(Char, Rest), Acc, URI) ->
+ case is_ipv6(Char) of
+ true -> parse_ipv6_bin(Rest, [Char|Acc], URI);
+ false -> throw({error,invalid_uri,[Char]})
+ end;
+parse_ipv6_bin(?STRING_EMPTY, _Acc, _URI) ->
+ throw({error,invalid_uri,<<>>}).
+
+%% Check if char is allowed in IPv6 addresses
+-spec is_ipv6(char()) -> boolean().
+is_ipv6($:) -> true;
+is_ipv6($.) -> true;
+is_ipv6(Char) -> is_hex_digit(Char).
+
+
+-spec parse_ipv6_bin_end(binary(), uri_map()) -> {binary(), uri_map()}.
+parse_ipv6_bin_end(?STRING_REST($:, Rest), URI) ->
+ {T, URI1} = parse_port(Rest, URI),
+ H = calculate_parsed_host_port(Rest, T),
+ Port = get_port(H),
+ {Rest, URI1#{port => Port}};
+parse_ipv6_bin_end(?STRING_REST($/, Rest), URI) ->
+ {T, URI1} = parse_segment(Rest, URI), % path-abempty
+ Path = calculate_parsed_part(Rest, T),
+ {Rest, URI1#{path => ?STRING_REST($/, Path)}};
+parse_ipv6_bin_end(?STRING_REST($?, Rest), URI) ->
+ {T, URI1} = parse_query(Rest, URI), % path-empty ?query
+ Query = calculate_parsed_query_fragment(Rest, T),
+ {Rest, URI1#{query => Query}};
+parse_ipv6_bin_end(?STRING_REST($#, Rest), URI) ->
+ {T, URI1} = parse_fragment(Rest, URI), % path-empty
+ Fragment = calculate_parsed_query_fragment(Rest, T),
+ {Rest, URI1#{fragment => Fragment}};
+parse_ipv6_bin_end(?STRING_REST(Char, Rest), URI) ->
+ case is_ipv6(Char) of
+ true -> parse_ipv6_bin_end(Rest, URI);
+ false -> throw({error,invalid_uri,[Char]})
+ end;
+parse_ipv6_bin_end(?STRING_EMPTY, URI) ->
+ {?STRING_EMPTY, URI}.
+
+-spec validate_ipv6_address(list()) -> list().
+validate_ipv6_address(Addr) ->
+ case inet:parse_ipv6strict_address(Addr) of
+ {ok, _} -> Addr;
+ {error, _} -> throw({error,invalid_uri,Addr})
+ end.
+
+
+%%-------------------------------------------------------------------------
+%% [RFC 3986, Chapter 3.2.2. Port]
+%%
+%% The port subcomponent of authority is designated by an optional port
+%% number in decimal following the host and delimited from it by a
+%% single colon (":") character.
+%%
+%% port = *DIGIT
+%%-------------------------------------------------------------------------
+-spec parse_port(binary(), uri_map()) -> {binary(), uri_map()}.
+parse_port(?STRING_REST($/, Rest), URI) ->
+ {T, URI1} = parse_segment(Rest, URI), % path-abempty
+ Path = calculate_parsed_part(Rest, T),
+ {Rest, URI1#{path => ?STRING_REST($/, Path)}};
+parse_port(?STRING_REST($?, Rest), URI) ->
+ {T, URI1} = parse_query(Rest, URI), % path-empty ?query
+ Query = calculate_parsed_query_fragment(Rest, T),
+ {Rest, URI1#{query => Query}};
+parse_port(?STRING_REST($#, Rest), URI) ->
+ {T, URI1} = parse_fragment(Rest, URI), % path-empty
+ Fragment = calculate_parsed_query_fragment(Rest, T),
+ {Rest, URI1#{fragment => Fragment}};
+parse_port(?STRING_REST(Char, Rest), URI) ->
+ case is_digit(Char) of
+ true -> parse_port(Rest, URI);
+ false -> throw({error,invalid_uri,[Char]})
+ end;
+parse_port(?STRING_EMPTY, URI) ->
+ {?STRING_EMPTY, URI}.
+
+
+%%-------------------------------------------------------------------------
+%% [RFC 3986, Chapter 3.4. Query]
+%%
+%% The query component contains non-hierarchical data that, along with
+%% data in the path component (Section 3.3), serves to identify a
+%% resource within the scope of the URI's scheme and naming authority
+%% (if any). The query component is indicated by the first question
+%% mark ("?") character and terminated by a number sign ("#") character
+%% or by the end of the URI.
+%%
+%% query = *( pchar / "/" / "?" )
+%%-------------------------------------------------------------------------
+-spec parse_query(binary(), uri_map()) -> {binary(), uri_map()}.
+parse_query(?STRING_REST($#, Rest), URI) ->
+ {T, URI1} = parse_fragment(Rest, URI),
+ Fragment = calculate_parsed_query_fragment(Rest, T),
+ {Rest, URI1#{fragment => Fragment}};
+parse_query(?STRING_REST(Char, Rest), URI) ->
+ case is_query(Char) of
+ true -> parse_query(Rest, URI);
+ false -> throw({error,invalid_uri,[Char]})
+ end;
+parse_query(?STRING_EMPTY, URI) ->
+ {?STRING_EMPTY, URI}.
+
+
+%% Check if char is allowed in query
+-spec is_query(char()) -> boolean().
+is_query($/) -> true;
+is_query($?) -> true;
+is_query(Char) -> is_pchar(Char).
+
+
+%%-------------------------------------------------------------------------
+%% [RFC 3986, Chapter 3.5. Fragment]
+%%
+%% The fragment identifier component of a URI allows indirect
+%% identification of a secondary resource by reference to a primary
+%% resource and additional identifying information.
+%%
+%% fragment = *( pchar / "/" / "?" )
+%%-------------------------------------------------------------------------
+-spec parse_fragment(binary(), uri_map()) -> {binary(), uri_map()}.
+parse_fragment(?STRING_REST(Char, Rest), URI) ->
+ case is_fragment(Char) of
+ true -> parse_fragment(Rest, URI);
+ false -> throw({error,invalid_uri,[Char]})
+ end;
+parse_fragment(?STRING_EMPTY, URI) ->
+ {?STRING_EMPTY, URI}.
+
+
+%% Check if char is allowed in fragment
+-spec is_fragment(char()) -> boolean().
+is_fragment($/) -> true;
+is_fragment($?) -> true;
+is_fragment(Char) -> is_pchar(Char).
+
+
+%%-------------------------------------------------------------------------
+%% [RFC 3986, Chapter 2.2. Reserved Characters]
+%%
+%% reserved = gen-delims / sub-delims
+%%
+%% gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+%%
+%% sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+%% / "*" / "+" / "," / ";" / "="
+%%
+%%-------------------------------------------------------------------------
+
+%% Return true if input char is reserved.
+-spec is_reserved(char()) -> boolean().
+is_reserved($:) -> true;
+is_reserved($/) -> true;
+is_reserved($?) -> true;
+is_reserved($#) -> true;
+is_reserved($[) -> true;
+is_reserved($]) -> true;
+is_reserved($@) -> true;
+
+is_reserved($!) -> true;
+is_reserved($$) -> true;
+is_reserved($&) -> true;
+is_reserved($') -> true;
+is_reserved($() -> true;
+is_reserved($)) -> true;
+
+is_reserved($*) -> true;
+is_reserved($+) -> true;
+is_reserved($,) -> true;
+is_reserved($;) -> true;
+is_reserved($=) -> true;
+is_reserved(_) -> false.
+
+
+%% Check if char is sub-delim.
+-spec is_sub_delim(char()) -> boolean().
+is_sub_delim($!) -> true;
+is_sub_delim($$) -> true;
+is_sub_delim($&) -> true;
+is_sub_delim($') -> true;
+is_sub_delim($() -> true;
+is_sub_delim($)) -> true;
+
+is_sub_delim($*) -> true;
+is_sub_delim($+) -> true;
+is_sub_delim($,) -> true;
+is_sub_delim($;) -> true;
+is_sub_delim($=) -> true;
+is_sub_delim(_) -> false.
+
+
+%%-------------------------------------------------------------------------
+%% [RFC 3986, Chapter 2.3. Unreserved Characters]
+%%
+%% unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+%%
+%%-------------------------------------------------------------------------
+-spec is_unreserved(char()) -> boolean().
+is_unreserved($-) -> true;
+is_unreserved($.) -> true;
+is_unreserved($_) -> true;
+is_unreserved($~) -> true;
+is_unreserved(Char) -> is_alpha(Char) orelse is_digit(Char).
+
+-spec is_alpha(char()) -> boolean().
+is_alpha(C)
+ when $A =< C, C =< $Z;
+ $a =< C, C =< $z -> true;
+is_alpha(_) -> false.
+
+-spec is_digit(char()) -> boolean().
+is_digit(C)
+ when $0 =< C, C =< $9 -> true;
+is_digit(_) -> false.
+
+-spec is_hex_digit(char()) -> boolean().
+is_hex_digit(C)
+ when $0 =< C, C =< $9;$a =< C, C =< $f;$A =< C, C =< $F -> true;
+is_hex_digit(_) -> false.
+
+
+%% Remove enclosing brackets from binary
+-spec remove_brackets(binary()) -> binary().
+remove_brackets(<<$[/utf8, Rest/binary>>) ->
+ {H,T} = split_binary(Rest, byte_size(Rest) - 1),
+ case T =:= <<$]/utf8>> of
+ true -> H;
+ false -> Rest
+ end;
+remove_brackets(Addr) -> Addr.
+
+
+%%-------------------------------------------------------------------------
+%% Helper functions for calculating the parsed binary.
+%%-------------------------------------------------------------------------
+-spec calculate_parsed_scheme(binary(), binary()) -> binary().
+calculate_parsed_scheme(Input, <<>>) ->
+ strip_last_char(Input, [$:]);
+calculate_parsed_scheme(Input, Unparsed) ->
+ get_parsed_binary(Input, Unparsed).
+
+
+-spec calculate_parsed_part(binary(), binary()) -> binary().
+calculate_parsed_part(Input, <<>>) ->
+ strip_last_char(Input, [$?,$#]);
+calculate_parsed_part(Input, Unparsed) ->
+ get_parsed_binary(Input, Unparsed).
+
+
+-spec calculate_parsed_userinfo(binary(), binary()) -> binary().
+calculate_parsed_userinfo(Input, <<>>) ->
+ strip_last_char(Input, [$?,$#,$@]);
+calculate_parsed_userinfo(Input, Unparsed) ->
+ get_parsed_binary(Input, Unparsed).
+
+
+-spec calculate_parsed_host_port(binary(), binary()) -> binary().
+calculate_parsed_host_port(Input, <<>>) ->
+ strip_last_char(Input, [$:,$?,$#,$/]);
+calculate_parsed_host_port(Input, Unparsed) ->
+ get_parsed_binary(Input, Unparsed).
+
+
+calculate_parsed_query_fragment(Input, <<>>) ->
+ strip_last_char(Input, [$#]);
+calculate_parsed_query_fragment(Input, Unparsed) ->
+ get_parsed_binary(Input, Unparsed).
+
+
+get_port(<<>>) ->
+ undefined;
+get_port(B) ->
+ try binary_to_integer(B)
+ catch
+ error:badarg ->
+ throw({error, invalid_uri, B})
+ end.
+
+
+%% Strip last char if it is in list
+%%
+%% This function is optimized for speed: parse/1 is about 10% faster than
+%% with an alternative implementation based on lists and sets.
+strip_last_char(<<>>, _) -> <<>>;
+strip_last_char(Input, [C0]) ->
+ case binary:last(Input) of
+ C0 ->
+ init_binary(Input);
+ _Else ->
+ Input
+ end;
+strip_last_char(Input, [C0,C1]) ->
+ case binary:last(Input) of
+ C0 ->
+ init_binary(Input);
+ C1 ->
+ init_binary(Input);
+ _Else ->
+ Input
+ end;
+strip_last_char(Input, [C0,C1,C2]) ->
+ case binary:last(Input) of
+ C0 ->
+ init_binary(Input);
+ C1 ->
+ init_binary(Input);
+ C2 ->
+ init_binary(Input);
+ _Else ->
+ Input
+ end;
+strip_last_char(Input, [C0,C1,C2,C3]) ->
+ case binary:last(Input) of
+ C0 ->
+ init_binary(Input);
+ C1 ->
+ init_binary(Input);
+ C2 ->
+ init_binary(Input);
+ C3 ->
+ init_binary(Input);
+ _Else ->
+ Input
+ end.
+
+
+%% Get parsed binary
+get_parsed_binary(Input, Unparsed) ->
+ {First, _} = split_binary(Input, byte_size(Input) - byte_size_exl_head(Unparsed)),
+ First.
+
+
+%% Return all bytes of the binary except the last one. The binary must be non-empty.
+init_binary(B) ->
+ {Init, _} =
+ split_binary(B, byte_size(B) - 1),
+ Init.
+
+
+%% Returns the size of a binary exluding the first element.
+%% Used in calls to split_binary().
+-spec byte_size_exl_head(binary()) -> number().
+byte_size_exl_head(<<>>) -> 0;
+byte_size_exl_head(Binary) -> byte_size(Binary) + 1.
+
+
+%%-------------------------------------------------------------------------
+%% [RFC 3986, Chapter 2.1. Percent-Encoding]
+%%
+%% A percent-encoding mechanism is used to represent a data octet in a
+%% component when that octet's corresponding character is outside the
+%% allowed set or is being used as a delimiter of, or within, the
+%% component. A percent-encoded octet is encoded as a character
+%% triplet, consisting of the percent character "%" followed by the two
+%% hexadecimal digits representing that octet's numeric value. For
+%% example, "%20" is the percent-encoding for the binary octet
+%% "00100000" (ABNF: %x20), which in US-ASCII corresponds to the space
+%% character (SP). Section 2.4 describes when percent-encoding and
+%% decoding is applied.
+%%
+%% pct-encoded = "%" HEXDIG HEXDIG
+%%-------------------------------------------------------------------------
+
+%%-------------------------------------------------------------------------
+%% Percent-encode
+%%-------------------------------------------------------------------------
+
+%% Only validates as scheme cannot have percent-encoded characters
+-spec encode_scheme(list()|binary()) -> list() | binary().
+encode_scheme([]) ->
+ throw({error,invalid_scheme,""});
+encode_scheme(<<>>) ->
+ throw({error,invalid_scheme,<<>>});
+encode_scheme(Scheme) ->
+ case validate_scheme(Scheme) of
+ true -> Scheme;
+ false -> throw({error,invalid_scheme,Scheme})
+ end.
+
+-spec encode_userinfo(list()|binary()) -> list() | binary().
+encode_userinfo(Cs) ->
+ encode(Cs, fun is_userinfo/1).
+
+-spec encode_host(list()|binary()) -> list() | binary().
+encode_host(Cs) ->
+ case classify_host(Cs) of
+ regname -> Cs;
+ ipv4 -> Cs;
+ ipv6 -> bracket_ipv6(Cs);
+ other -> encode(Cs, fun is_reg_name/1)
+ end.
+
+-spec encode_path(list()|binary()) -> list() | binary().
+encode_path(Cs) ->
+ encode(Cs, fun is_path/1).
+
+-spec encode_query(list()|binary()) -> list() | binary().
+encode_query(Cs) ->
+ encode(Cs, fun is_query/1).
+
+-spec encode_fragment(list()|binary()) -> list() | binary().
+encode_fragment(Cs) ->
+ encode(Cs, fun is_fragment/1).
+
+%%-------------------------------------------------------------------------
+%% Helper funtions for percent-decode
+%%-------------------------------------------------------------------------
+
+-spec decode(list()|binary()) -> list() | binary().
+decode(Cs) ->
+ decode(Cs, <<>>).
+%%
+decode(L, Acc) when is_list(L) ->
+ B0 = unicode:characters_to_binary(L),
+ B1 = decode(B0, Acc),
+ unicode:characters_to_list(B1);
+decode(<<$%,C0,C1,Cs/binary>>, Acc) ->
+ case is_hex_digit(C0) andalso is_hex_digit(C1) of
+ true ->
+ B = ?HEX2DEC(C0)*16+?HEX2DEC(C1),
+ case is_reserved(B) of
+ true ->
+ %% [2.2] Characters in the reserved set are protected from
+ %% normalization.
+ %% [2.1] For consistency, URI producers and normalizers should
+ %% use uppercase hexadecimal digits for all percent-
+ %% encodings.
+ H0 = hex_to_upper(C0),
+ H1 = hex_to_upper(C1),
+ decode(Cs, <<Acc/binary,$%,H0,H1>>);
+ false ->
+ decode(Cs, <<Acc/binary, B>>)
+ end;
+ false -> throw({error,invalid_percent_encoding,<<$%,C0,C1>>})
+ end;
+decode(<<C,Cs/binary>>, Acc) ->
+ decode(Cs, <<Acc/binary, C>>);
+decode(<<>>, Acc) ->
+ check_utf8(Acc).
+
+%% Returns Cs if it is utf8 encoded.
+check_utf8(Cs) ->
+ case unicode:characters_to_list(Cs) of
+ {incomplete,_,_} ->
+ throw({error,invalid_utf8,Cs});
+ {error,_,_} ->
+ throw({error,invalid_utf8,Cs});
+ _ -> Cs
+ end.
+
+%% Convert hex digit to uppercase form
+hex_to_upper(H) when $a =< H, H =< $f ->
+ H - 32;
+hex_to_upper(H) when $0 =< H, H =< $9;$A =< H, H =< $F->
+ H;
+hex_to_upper(H) ->
+ throw({error,invalid_input, H}).
+
+%% Check if char is allowed in host
+-spec is_host(char()) -> boolean().
+is_host($:) -> true;
+is_host(Char) -> is_unreserved(Char) orelse is_sub_delim(Char).
+
+%% Check if char is allowed in path
+-spec is_path(char()) -> boolean().
+is_path($/) -> true;
+is_path(Char) -> is_pchar(Char).
+
+
+%%-------------------------------------------------------------------------
+%% Helper functions for percent-encode
+%%-------------------------------------------------------------------------
+-spec encode(list()|binary(), fun()) -> list() | binary().
+encode(Component, Fun) when is_list(Component) ->
+ B = unicode:characters_to_binary(Component),
+ unicode:characters_to_list(encode(B, Fun, <<>>));
+encode(Component, Fun) when is_binary(Component) ->
+ encode(Component, Fun, <<>>).
+%%
+encode(<<Char/utf8, Rest/binary>>, Fun, Acc) ->
+ C = encode_codepoint_binary(Char, Fun),
+ encode(Rest, Fun, <<Acc/binary,C/binary>>);
+encode(<<Char, Rest/binary>>, _Fun, _Acc) ->
+ throw({error,invalid_input,<<Char,Rest/binary>>});
+encode(<<>>, _Fun, Acc) ->
+ Acc.
+
+
+-spec encode_codepoint_binary(integer(), fun()) -> binary().
+encode_codepoint_binary(C, Fun) ->
+ case Fun(C) of
+ false -> percent_encode_binary(C);
+ true -> <<C>>
+ end.
+
+
+-spec percent_encode_binary(integer()) -> binary().
+percent_encode_binary(Code) ->
+ percent_encode_binary(<<Code/utf8>>, <<>>).
+
+
+percent_encode_binary(<<A:4,B:4,Rest/binary>>, Acc) ->
+ percent_encode_binary(Rest, <<Acc/binary,$%,(?DEC2HEX(A)),(?DEC2HEX(B))>>);
+percent_encode_binary(<<>>, Acc) ->
+ Acc.
+
+
+%%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
+validate_scheme([]) -> true;
+validate_scheme([H|T]) ->
+ case is_scheme(H) of
+ true -> validate_scheme(T);
+ false -> false
+ end;
+validate_scheme(<<>>) -> true;
+validate_scheme(<<H, Rest/binary>>) ->
+ case is_scheme(H) of
+ true -> validate_scheme(Rest);
+ false -> false
+ end.
+
+
+%%-------------------------------------------------------------------------
+%% Classifies hostname into the following categories:
+%% regname, ipv4 - address does not contain reserved characters to be
+%% percent-encoded
+%% ipv6 - address does not contain reserved characters but it shall be
+%% encolsed in brackets
+%% other - address shall be percent-encoded
+%%-------------------------------------------------------------------------
+classify_host([]) -> other;
+classify_host(Addr) when is_binary(Addr) ->
+ A = unicode:characters_to_list(Addr),
+ classify_host_ipv6(A);
+classify_host(Addr) ->
+ classify_host_ipv6(Addr).
+
+classify_host_ipv6(Addr) ->
+ case is_ipv6_address(Addr) of
+ true -> ipv6;
+ false -> classify_host_ipv4(Addr)
+ end.
+
+classify_host_ipv4(Addr) ->
+ case is_ipv4_address(Addr) of
+ true -> ipv4;
+ false -> classify_host_regname(Addr)
+ end.
+
+classify_host_regname([]) -> regname;
+classify_host_regname([H|T]) ->
+ case is_reg_name(H) of
+ true -> classify_host_regname(T);
+ false -> other
+ end.
+
+is_ipv4_address(Addr) ->
+ case inet:parse_ipv4strict_address(Addr) of
+ {ok, _} -> true;
+ {error, _} -> false
+ end.
+
+is_ipv6_address(Addr) ->
+ case inet:parse_ipv6strict_address(Addr) of
+ {ok, _} -> true;
+ {error, _} -> false
+ end.
+
+bracket_ipv6(Addr) when is_binary(Addr) ->
+ concat(<<$[,Addr/binary>>,<<$]>>);
+bracket_ipv6(Addr) when is_list(Addr) ->
+ [$[|Addr] ++ "]".
+
+
+%%-------------------------------------------------------------------------
+%% Helper funtions for recompose
+%%-------------------------------------------------------------------------
+
+%%-------------------------------------------------------------------------
+%% Checks if input Map has valid combination of fields that can be
+%% recomposed into a URI.
+%%
+%% The implementation is based on a decision tree that fulfills the
+%% following rules:
+%% - 'path' shall always be present in the input map
+%% URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+%% hier-part = "//" authority path-abempty
+%% / path-absolute
+%% / path-rootless
+%% / path-empty
+%% - 'host' shall be present in the input map when 'path' starts with
+%% two slashes ("//")
+%% path = path-abempty ; begins with "/" or is empty
+%% / path-absolute ; begins with "/" but not "//"
+%% / path-noscheme ; begins with a non-colon segment
+%% / path-rootless ; begins with a segment
+%% / path-empty ; zero characters
+%% path-abempty = *( "/" segment )
+%% segment = *pchar
+%% - 'host' shall be present if userinfo or port is present in input map
+%% authority = [ userinfo "@" ] host [ ":" port ]
+%% - All fields shall be valid (scheme, userinfo, host, port, path, query
+%% or fragment).
+%%-------------------------------------------------------------------------
+is_valid_map(#{path := Path} = Map) ->
+ ((starts_with_two_slash(Path) andalso is_valid_map_host(Map))
+ orelse
+ (maps:is_key(userinfo, Map) andalso is_valid_map_host(Map))
+ orelse
+ (maps:is_key(port, Map) andalso is_valid_map_host(Map))
+ orelse
+ all_fields_valid(Map));
+is_valid_map(#{}) ->
+ false.
+
+
+is_valid_map_host(Map) ->
+ maps:is_key(host, Map) andalso all_fields_valid(Map).
+
+
+all_fields_valid(Map) ->
+ Fun = fun(scheme, _, Acc) -> Acc;
+ (userinfo, _, Acc) -> Acc;
+ (host, _, Acc) -> Acc;
+ (port, _, Acc) -> Acc;
+ (path, _, Acc) -> Acc;
+ (query, _, Acc) -> Acc;
+ (fragment, _, Acc) -> Acc;
+ (_, _, _) -> false
+ end,
+ maps:fold(Fun, true, Map).
+
+
+starts_with_two_slash([$/,$/|_]) ->
+ true;
+starts_with_two_slash(?STRING_REST("//", _)) ->
+ true;
+starts_with_two_slash(_) -> false.
+
+
+update_scheme(#{scheme := Scheme}, _) ->
+ add_colon_postfix(encode_scheme(Scheme));
+update_scheme(#{}, _) ->
+ empty.
+
+
+update_userinfo(#{userinfo := Userinfo}, empty) ->
+ add_auth_prefix(encode_userinfo(Userinfo));
+update_userinfo(#{userinfo := Userinfo}, URI) ->
+ concat(URI,add_auth_prefix(encode_userinfo(Userinfo)));
+update_userinfo(#{}, empty) ->
+ empty;
+update_userinfo(#{}, URI) ->
+ URI.
+
+
+update_host(#{host := Host}, empty) ->
+ add_auth_prefix(encode_host(Host));
+update_host(#{host := Host} = Map, URI) ->
+ concat(URI,add_host_prefix(Map, encode_host(Host)));
+update_host(#{}, empty) ->
+ empty;
+update_host(#{}, URI) ->
+ URI.
+
+
+%% URI cannot be empty for ports. E.g. ":8080" is not a valid URI
+update_port(#{port := undefined}, URI) ->
+ concat(URI, <<":">>);
+update_port(#{port := Port}, URI) ->
+ concat(URI,add_colon(encode_port(Port)));
+update_port(#{}, URI) ->
+ URI.
+
+
+update_path(#{path := Path}, empty) ->
+ encode_path(Path);
+update_path(#{path := Path}, URI) ->
+ concat(URI,encode_path(Path));
+update_path(#{}, empty) ->
+ empty;
+update_path(#{}, URI) ->
+ URI.
+
+
+update_query(#{query := Query}, empty) ->
+ encode_query(Query);
+update_query(#{query := Query}, URI) ->
+ concat(URI,add_question_mark(encode_query(Query)));
+update_query(#{}, empty) ->
+ empty;
+update_query(#{}, URI) ->
+ URI.
+
+
+update_fragment(#{fragment := Fragment}, empty) ->
+ add_hashmark(encode_fragment(Fragment));
+update_fragment(#{fragment := Fragment}, URI) ->
+ concat(URI,add_hashmark(encode_fragment(Fragment)));
+update_fragment(#{}, empty) ->
+ "";
+update_fragment(#{}, URI) ->
+ URI.
+
+%%-------------------------------------------------------------------------
+%% Concatenates its arguments that can be lists and binaries.
+%% The result is a list if at least one of its argument is a list and
+%% binary otherwise.
+%%-------------------------------------------------------------------------
+concat(A, B) when is_binary(A), is_binary(B) ->
+ <<A/binary, B/binary>>;
+concat(A, B) when is_binary(A), is_list(B) ->
+ unicode:characters_to_list(A) ++ B;
+concat(A, B) when is_list(A) ->
+ A ++ maybe_to_list(B).
+
+add_hashmark(Comp) when is_binary(Comp) ->
+ <<$#, Comp/binary>>;
+add_hashmark(Comp) when is_list(Comp) ->
+ [$#|Comp].
+
+add_question_mark(Comp) when is_binary(Comp) ->
+ <<$?, Comp/binary>>;
+add_question_mark(Comp) when is_list(Comp) ->
+ [$?|Comp].
+
+add_colon(Comp) when is_binary(Comp) ->
+ <<$:, Comp/binary>>.
+
+add_colon_postfix(Comp) when is_binary(Comp) ->
+ <<Comp/binary,$:>>;
+add_colon_postfix(Comp) when is_list(Comp) ->
+ Comp ++ ":".
+
+add_auth_prefix(Comp) when is_binary(Comp) ->
+ <<"//", Comp/binary>>;
+add_auth_prefix(Comp) when is_list(Comp) ->
+ [$/,$/|Comp].
+
+add_host_prefix(#{userinfo := _}, Host) when is_binary(Host) ->
+ <<$@,Host/binary>>;
+add_host_prefix(#{}, Host) when is_binary(Host) ->
+ <<"//",Host/binary>>;
+add_host_prefix(#{userinfo := _}, Host) when is_list(Host) ->
+ [$@|Host];
+add_host_prefix(#{}, Host) when is_list(Host) ->
+ [$/,$/|Host].
+
+maybe_to_list(Comp) when is_binary(Comp) -> unicode:characters_to_list(Comp);
+maybe_to_list(Comp) -> Comp.
+
+encode_port(Port) ->
+ integer_to_binary(Port).
+
+%%-------------------------------------------------------------------------
+%% Helper functions for transcode
+%%-------------------------------------------------------------------------
+
+%%-------------------------------------------------------------------------
+%% uri_string:transcode(<<"x%00%00%00%F6"/utf32>>).
+%% 1. Convert (transcode/2) input to list form (list of unicode codepoints)
+%% "x%00%00%00%F6"
+%% 2. Accumulate characters until percent-encoded segment (transcode/4).
+%% Acc = "x"
+%% 3. Convert percent-encoded triplets to binary form (transcode_pct/4)
+%% <<0,0,0,246>>
+%% 4. Transcode in-encoded binary to out-encoding (utf32 -> utf8):
+%% <<195,182>>
+%% 5. Percent-encode out-encoded binary:
+%% <<"%C3%B6"/utf8>> = <<37,67,51,37,66,54>>
+%% 6. Convert binary to list form, reverse it and append the accumulator
+%% "6B%3C%" + "x"
+%% 7. Reverse Acc and return it
+%%-------------------------------------------------------------------------
+transcode([$%,_C0,_C1|_Rest] = L, Acc, InEnc, OutEnc) ->
+ transcode_pct(L, Acc, <<>>, InEnc, OutEnc);
+transcode([_C|_Rest] = L, Acc, InEnc, OutEnc) ->
+ transcode(L, Acc, [], InEnc, OutEnc).
+%%
+transcode([$%,_C0,_C1|_Rest] = L, Acc, List, InEncoding, OutEncoding) ->
+ transcode_pct(L, List ++ Acc, <<>>, InEncoding, OutEncoding);
+transcode([C|Rest], Acc, List, InEncoding, OutEncoding) ->
+ transcode(Rest, Acc, [C|List], InEncoding, OutEncoding);
+transcode([], Acc, List, _InEncoding, _OutEncoding) ->
+ lists:reverse(List ++ Acc).
+
+
+%% Transcode percent-encoded segment
+transcode_pct([$%,C0,C1|Rest] = L, Acc, B, InEncoding, OutEncoding) ->
+ case is_hex_digit(C0) andalso is_hex_digit(C1) of
+ true ->
+ Int = ?HEX2DEC(C0)*16+?HEX2DEC(C1),
+ transcode_pct(Rest, Acc, <<B/binary, Int>>, InEncoding, OutEncoding);
+ false -> throw({error, invalid_percent_encoding,L})
+ end;
+transcode_pct([_C|_Rest] = L, Acc, B, InEncoding, OutEncoding) ->
+ OutBinary = convert_to_binary(B, InEncoding, OutEncoding),
+ PctEncUtf8 = percent_encode_segment(OutBinary),
+ Out = lists:reverse(convert_to_list(PctEncUtf8, utf8)),
+ transcode(L, Out ++ Acc, [], InEncoding, OutEncoding);
+transcode_pct([], Acc, B, InEncoding, OutEncoding) ->
+ OutBinary = convert_to_binary(B, InEncoding, OutEncoding),
+ PctEncUtf8 = percent_encode_segment(OutBinary),
+ Out = convert_to_list(PctEncUtf8, utf8),
+ lists:reverse(Acc) ++ Out.
+
+
+%% Convert to binary
+convert_to_binary(Binary, InEncoding, OutEncoding) ->
+ case unicode:characters_to_binary(Binary, InEncoding, OutEncoding) of
+ {error, _List, RestData} ->
+ throw({error, invalid_input, RestData});
+ {incomplete, _List, RestData} ->
+ throw({error, invalid_input, RestData});
+ Result ->
+ Result
+ end.
+
+
+%% Convert to list
+convert_to_list(Binary, InEncoding) ->
+ case unicode:characters_to_list(Binary, InEncoding) of
+ {error, _List, RestData} ->
+ throw({error, invalid_input, RestData});
+ {incomplete, _List, RestData} ->
+ throw({error, invalid_input, RestData});
+ Result ->
+ Result
+ end.
+
+
+%% Flatten input list
+flatten_list([], _) ->
+ [];
+flatten_list(L, InEnc) ->
+ flatten_list(L, InEnc, []).
+%%
+flatten_list([H|T], InEnc, Acc) when is_binary(H) ->
+ L = convert_to_list(H, InEnc),
+ flatten_list(T, InEnc, lists:reverse(L) ++ Acc);
+flatten_list([H|T], InEnc, Acc) when is_list(H) ->
+ flatten_list(H ++ T, InEnc, Acc);
+flatten_list([H|T], InEnc, Acc) ->
+ flatten_list(T, InEnc, [H|Acc]);
+flatten_list([], _InEnc, Acc) ->
+ lists:reverse(Acc);
+flatten_list(Arg, _, _) ->
+ throw({error, invalid_input, Arg}).
+
+
+percent_encode_segment(Segment) ->
+ percent_encode_binary(Segment, <<>>).
+
+
+%%-------------------------------------------------------------------------
+%% Helper functions for compose_query
+%%-------------------------------------------------------------------------
+
+%% Returns separator to be used between key-value pairs
+get_separator(L) when length(L) =:= 0 ->
+ <<>>;
+get_separator(_L) ->
+ <<"&">>.
+
+
+%% HTML 5.2 - 4.10.21.6 URL-encoded form data - WHATWG URL (10 Jan 2018) - UTF-8
+%% HTML 5.0 - 4.10.22.6 URL-encoded form data - encoding (non UTF-8)
+form_urlencode(Cs, [{encoding, latin1}]) when is_list(Cs) ->
+ B = convert_to_binary(Cs, utf8, utf8),
+ html5_byte_encode(base10_encode(B));
+form_urlencode(Cs, [{encoding, latin1}]) when is_binary(Cs) ->
+ html5_byte_encode(base10_encode(Cs));
+form_urlencode(Cs, [{encoding, Encoding}])
+ when is_list(Cs), Encoding =:= utf8; Encoding =:= unicode ->
+ B = convert_to_binary(Cs, utf8, Encoding),
+ html5_byte_encode(B);
+form_urlencode(Cs, [{encoding, Encoding}])
+ when is_binary(Cs), Encoding =:= utf8; Encoding =:= unicode ->
+ html5_byte_encode(Cs);
+form_urlencode(Cs, [{encoding, Encoding}]) when is_list(Cs); is_binary(Cs) ->
+ throw({error,invalid_encoding, Encoding});
+form_urlencode(Cs, _) ->
+ throw({error,invalid_input, Cs}).
+
+
+%% For each character in the entry's name and value that cannot be expressed using
+%% the selected character encoding, replace the character by a string consisting of
+%% a U+0026 AMPERSAND character (&), a "#" (U+0023) character, one or more ASCII
+%% digits representing the Unicode code point of the character in base ten, and
+%% finally a ";" (U+003B) character.
+base10_encode(Cs) ->
+ base10_encode(Cs, <<>>).
+%%
+base10_encode(<<>>, Acc) ->
+ Acc;
+base10_encode(<<H/utf8,T/binary>>, Acc) when H > 255 ->
+ Base10 = convert_to_binary(integer_to_list(H,10), utf8, utf8),
+ base10_encode(T, <<Acc/binary,"&#",Base10/binary,$;>>);
+base10_encode(<<H/utf8,T/binary>>, Acc) ->
+ base10_encode(T, <<Acc/binary,H>>).
+
+
+html5_byte_encode(B) ->
+ html5_byte_encode(B, <<>>).
+%%
+html5_byte_encode(<<>>, Acc) ->
+ Acc;
+html5_byte_encode(<<$ ,T/binary>>, Acc) ->
+ html5_byte_encode(T, <<Acc/binary,$+>>);
+html5_byte_encode(<<H,T/binary>>, Acc) ->
+ case is_url_char(H) of
+ true ->
+ html5_byte_encode(T, <<Acc/binary,H>>);
+ false ->
+ <<A:4,B:4>> = <<H>>,
+ html5_byte_encode(T, <<Acc/binary,$%,(?DEC2HEX(A)),(?DEC2HEX(B))>>)
+ end;
+html5_byte_encode(H, _Acc) ->
+ throw({error,invalid_input, H}).
+
+
+%% Return true if input char can appear in form-urlencoded string
+%% Allowed chararacters:
+%% 0x2A, 0x2D, 0x2E, 0x30 to 0x39, 0x41 to 0x5A,
+%% 0x5F, 0x61 to 0x7A
+is_url_char(C)
+ when C =:= 16#2A; C =:= 16#2D;
+ C =:= 16#2E; C =:= 16#5F;
+ 16#30 =< C, C =< 16#39;
+ 16#41 =< C, C =< 16#5A;
+ 16#61 =< C, C =< 16#7A -> true;
+is_url_char(_) -> false.
+
+
+%%-------------------------------------------------------------------------
+%% Helper functions for dissect_query
+%%-------------------------------------------------------------------------
+dissect_query_key(<<$=,T/binary>>, IsList, Acc, Key, Value) ->
+ dissect_query_value(T, IsList, Acc, Key, Value);
+dissect_query_key(<<"&#",T/binary>>, IsList, Acc, Key, Value) ->
+ dissect_query_key(T, IsList, Acc, <<Key/binary,"&#">>, Value);
+dissect_query_key(<<$&,_T/binary>>, _IsList, _Acc, _Key, _Value) ->
+ throw({error, missing_value, "&"});
+dissect_query_key(<<H,T/binary>>, IsList, Acc, Key, Value) ->
+ dissect_query_key(T, IsList, Acc, <<Key/binary,H>>, Value);
+dissect_query_key(B, _, _, _, _) ->
+ throw({error, missing_value, B}).
+
+
+dissect_query_value(<<$&,T/binary>>, IsList, Acc, Key, Value) ->
+ K = form_urldecode(IsList, Key),
+ V = form_urldecode(IsList, Value),
+ dissect_query_key(T, IsList, [{K,V}|Acc], <<>>, <<>>);
+dissect_query_value(<<H,T/binary>>, IsList, Acc, Key, Value) ->
+ dissect_query_value(T, IsList, Acc, Key, <<Value/binary,H>>);
+dissect_query_value(<<>>, IsList, Acc, Key, Value) ->
+ K = form_urldecode(IsList, Key),
+ V = form_urldecode(IsList, Value),
+ lists:reverse([{K,V}|Acc]).
+
+
+%% HTML 5.2 - 4.10.21.6 URL-encoded form data - WHATWG URL (10 Jan 2018) - UTF-8
+%% HTML 5.0 - 4.10.22.6 URL-encoded form data - decoding (non UTF-8)
+form_urldecode(true, B) ->
+ Result = base10_decode(form_urldecode(B, <<>>)),
+ convert_to_list(Result, utf8);
+form_urldecode(false, B) ->
+ base10_decode(form_urldecode(B, <<>>));
+form_urldecode(<<>>, Acc) ->
+ Acc;
+form_urldecode(<<$+,T/binary>>, Acc) ->
+ form_urldecode(T, <<Acc/binary,$ >>);
+form_urldecode(<<$%,C0,C1,T/binary>>, Acc) ->
+ case is_hex_digit(C0) andalso is_hex_digit(C1) of
+ true ->
+ V = ?HEX2DEC(C0)*16+?HEX2DEC(C1),
+ form_urldecode(T, <<Acc/binary, V>>);
+ false ->
+ L = convert_to_list(<<$%,C0,C1,T/binary>>, utf8),
+ throw({error, invalid_percent_encoding, L})
+ end;
+form_urldecode(<<H/utf8,T/binary>>, Acc) ->
+ form_urldecode(T, <<Acc/binary,H/utf8>>);
+form_urldecode(<<H,_/binary>>, _Acc) ->
+ throw({error, invalid_character, [H]}).
+
+base10_decode(Cs) ->
+ base10_decode(Cs, <<>>).
+%
+base10_decode(<<>>, Acc) ->
+ Acc;
+base10_decode(<<"&#",T/binary>>, Acc) ->
+ base10_decode_unicode(T, Acc);
+base10_decode(<<H/utf8,T/binary>>, Acc) ->
+ base10_decode(T,<<Acc/binary,H/utf8>>);
+base10_decode(<<H,_/binary>>, _) ->
+ throw({error, invalid_input, [H]}).
+
+
+base10_decode_unicode(B, Acc) ->
+ base10_decode_unicode(B, 0, Acc).
+%%
+base10_decode_unicode(<<H/utf8,T/binary>>, Codepoint, Acc) when $0 =< H, H =< $9 ->
+ Res = Codepoint * 10 + (H - $0),
+ base10_decode_unicode(T, Res, Acc);
+base10_decode_unicode(<<$;,T/binary>>, Codepoint, Acc) ->
+ base10_decode(T, <<Acc/binary,Codepoint/utf8>>);
+base10_decode_unicode(<<H,_/binary>>, _, _) ->
+ throw({error, invalid_input, [H]}).
+
+
+%%-------------------------------------------------------------------------
+%% Helper functions for normalize
+%%-------------------------------------------------------------------------
+
+normalize_map(URIMap) ->
+ normalize_path_segment(
+ normalize_scheme_based(
+ normalize_percent_encoding(
+ normalize_case(URIMap)))).
+
+
+%% 6.2.2.1. Case Normalization
+normalize_case(#{scheme := Scheme, host := Host} = Map) ->
+ Map#{scheme => to_lower(Scheme),
+ host => to_lower(Host)};
+normalize_case(#{host := Host} = Map) ->
+ Map#{host => to_lower(Host)};
+normalize_case(#{scheme := Scheme} = Map) ->
+ Map#{scheme => to_lower(Scheme)};
+normalize_case(#{} = Map) ->
+ Map.
+
+
+%% 6.2.2.2. Percent-Encoding Normalization
+normalize_percent_encoding(Map) ->
+ Fun = fun (K,V) when K =:= userinfo; K =:= host; K =:= path;
+ K =:= query; K =:= fragment ->
+ decode(V);
+ %% Handle port and scheme
+ (_,V) ->
+ V
+ end,
+ maps:map(Fun, Map).
+
+
+to_lower(Cs) when is_list(Cs) ->
+ B = convert_to_binary(Cs, utf8, utf8),
+ convert_to_list(to_lower(B), utf8);
+to_lower(Cs) when is_binary(Cs) ->
+ to_lower(Cs, <<>>).
+%%
+to_lower(<<C,Cs/binary>>, Acc) when $A =< C, C =< $Z ->
+ to_lower(Cs, <<Acc/binary,(C + 32)>>);
+to_lower(<<C,Cs/binary>>, Acc) ->
+ to_lower(Cs, <<Acc/binary,C>>);
+to_lower(<<>>, Acc) ->
+ Acc.
+
+
+%% 6.2.2.3. Path Segment Normalization
+%% 5.2.4. Remove Dot Segments
+normalize_path_segment(Map) ->
+ Path = maps:get(path, Map, undefined),
+ Map#{path => remove_dot_segments(Path)}.
+
+
+remove_dot_segments(Path) when is_binary(Path) ->
+ remove_dot_segments(Path, <<>>);
+remove_dot_segments(Path) when is_list(Path) ->
+ B = convert_to_binary(Path, utf8, utf8),
+ B1 = remove_dot_segments(B, <<>>),
+ convert_to_list(B1, utf8).
+%%
+remove_dot_segments(<<>>, Output) ->
+ Output;
+remove_dot_segments(<<"../",T/binary>>, Output) ->
+ remove_dot_segments(T, Output);
+remove_dot_segments(<<"./",T/binary>>, Output) ->
+ remove_dot_segments(T, Output);
+remove_dot_segments(<<"/./",T/binary>>, Output) ->
+ remove_dot_segments(<<$/,T/binary>>, Output);
+remove_dot_segments(<<"/.">>, Output) ->
+ remove_dot_segments(<<$/>>, Output);
+remove_dot_segments(<<"/../",T/binary>>, Output) ->
+ Out1 = remove_last_segment(Output),
+ remove_dot_segments(<<$/,T/binary>>, Out1);
+remove_dot_segments(<<"/..">>, Output) ->
+ Out1 = remove_last_segment(Output),
+ remove_dot_segments(<<$/>>, Out1);
+remove_dot_segments(<<$.>>, Output) ->
+ remove_dot_segments(<<>>, Output);
+remove_dot_segments(<<"..">>, Output) ->
+ remove_dot_segments(<<>>, Output);
+remove_dot_segments(Input, Output) ->
+ {First, Rest} = first_path_segment(Input),
+ remove_dot_segments(Rest, <<Output/binary,First/binary>>).
+
+
+first_path_segment(Input) ->
+ F = first_path_segment(Input, <<>>),
+ split_binary(Input, byte_size(F)).
+%%
+first_path_segment(<<$/,T/binary>>, Acc) ->
+ first_path_segment_end(<<T/binary>>, <<Acc/binary,$/>>);
+first_path_segment(<<C,T/binary>>, Acc) ->
+ first_path_segment_end(<<T/binary>>, <<Acc/binary,C>>).
+
+
+first_path_segment_end(<<>>, Acc) ->
+ Acc;
+first_path_segment_end(<<$/,_/binary>>, Acc) ->
+ Acc;
+first_path_segment_end(<<C,T/binary>>, Acc) ->
+ first_path_segment_end(<<T/binary>>, <<Acc/binary,C>>).
+
+
+remove_last_segment(<<>>) ->
+ <<>>;
+remove_last_segment(B) ->
+ {Init, Last} = split_binary(B, byte_size(B) - 1),
+ case Last of
+ <<$/>> ->
+ Init;
+ _Char ->
+ remove_last_segment(Init)
+ end.
+
+
+%% RFC 3986, 6.2.3. Scheme-Based Normalization
+normalize_scheme_based(Map) ->
+ Scheme = maps:get(scheme, Map, undefined),
+ Port = maps:get(port, Map, undefined),
+ Path= maps:get(path, Map, undefined),
+ normalize_scheme_based(Map, Scheme, Port, Path).
+%%
+normalize_scheme_based(Map, Scheme, Port, Path)
+ when Scheme =:= "http"; Scheme =:= <<"http">> ->
+ normalize_http(Map, Port, Path);
+normalize_scheme_based(Map, Scheme, Port, Path)
+ when Scheme =:= "https"; Scheme =:= <<"https">> ->
+ normalize_https(Map, Port, Path);
+normalize_scheme_based(Map, Scheme, Port, _Path)
+ when Scheme =:= "ftp"; Scheme =:= <<"ftp">> ->
+ normalize_ftp(Map, Port);
+normalize_scheme_based(Map, Scheme, Port, _Path)
+ when Scheme =:= "ssh"; Scheme =:= <<"ssh">> ->
+ normalize_ssh_sftp(Map, Port);
+normalize_scheme_based(Map, Scheme, Port, _Path)
+ when Scheme =:= "sftp"; Scheme =:= <<"sftp">> ->
+ normalize_ssh_sftp(Map, Port);
+normalize_scheme_based(Map, Scheme, Port, _Path)
+ when Scheme =:= "tftp"; Scheme =:= <<"tftp">> ->
+ normalize_tftp(Map, Port);
+normalize_scheme_based(Map, _, _, _) ->
+ Map.
+
+
+normalize_http(Map, Port, Path) ->
+ M1 = normalize_port(Map, Port, 80),
+ normalize_http_path(M1, Path).
+
+
+normalize_https(Map, Port, Path) ->
+ M1 = normalize_port(Map, Port, 443),
+ normalize_http_path(M1, Path).
+
+
+normalize_ftp(Map, Port) ->
+ normalize_port(Map, Port, 21).
+
+
+normalize_ssh_sftp(Map, Port) ->
+ normalize_port(Map, Port, 22).
+
+
+normalize_tftp(Map, Port) ->
+ normalize_port(Map, Port, 69).
+
+
+normalize_port(Map, Port, Default) ->
+ case Port of
+ Default ->
+ maps:remove(port, Map);
+ _Else ->
+ Map
+ end.
+
+
+normalize_http_path(Map, Path) ->
+ case Path of
+ "" ->
+ Map#{path => "/"};
+ <<>> ->
+ Map#{path => <<"/">>};
+ _Else ->
+ Map
+ end.
diff --git a/lib/stdlib/src/zip.erl b/lib/stdlib/src/zip.erl
index 81f927f399..a922bf3fbe 100644
--- a/lib/stdlib/src/zip.erl
+++ b/lib/stdlib/src/zip.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -457,8 +457,7 @@ do_zip(F, Files, Options) ->
Out3 = Output({close, F}, Out2),
{ok, Out3}
catch
- C:R ->
- Stk = erlang:get_stacktrace(),
+ C:R:Stk ->
zlib:close(Z),
Output({close, F}, Out0),
erlang:raise(C, R, Stk)
diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile
index 72211332e9..bbe3cefa42 100644
--- a/lib/stdlib/test/Makefile
+++ b/lib/stdlib/test/Makefile
@@ -36,6 +36,7 @@ MODULES= \
ets_tough_SUITE \
expand_test \
expand_test1 \
+ unicode_expand \
ExpandTestCaps \
ExpandTestCaps1 \
filelib_SUITE \
@@ -68,6 +69,7 @@ MODULES= \
sets_test_lib \
sofs_SUITE \
stdlib_SUITE \
+ stdlib_bench_SUITE \
string_SUITE \
supervisor_1 \
supervisor_2 \
@@ -85,6 +87,8 @@ MODULES= \
timer_simple_SUITE \
unicode_SUITE \
unicode_util_SUITE \
+ uri_string_SUITE \
+ uri_string_property_test_SUITE \
win32reg_SUITE \
y2k_SUITE \
select_SUITE \
@@ -92,7 +96,8 @@ MODULES= \
random_unicode_list \
random_iolist \
error_logger_forwarder \
- maps_SUITE
+ maps_SUITE \
+ zzz_SUITE
ERL_FILES= $(MODULES:%=%.erl)
@@ -145,9 +150,9 @@ release_spec: opt
release_tests_spec: make_emakefile
$(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DATA) stdlib.spec $(EMAKEFILE) \
+ $(INSTALL_DATA) stdlib.spec stdlib_bench.spec $(EMAKEFILE) \
$(ERL_FILES) $(COVERFILE) "$(RELSYSDIR)"
chmod -R u+w "$(RELSYSDIR)"
- @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
+ @tar cf - *_SUITE_data property_test | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/lib/stdlib/test/array_SUITE.erl b/lib/stdlib/test/array_SUITE.erl
index 5836f275ba..df520ebb54 100644
--- a/lib/stdlib/test/array_SUITE.erl
+++ b/lib/stdlib/test/array_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -141,10 +141,10 @@ t(What) ->
io:format("Test ~p ~n",[T]),
try
?MODULE:T([])
- catch _E:_R ->
+ catch _E:_R:_S ->
Line = get(test_server_loc),
io:format("Failed ~p:~p ~p ~p~n ~p~n",
- [T,Line,_E,_R, erlang:get_stacktrace()])
+ [T,Line,_E,_R,_S])
end
end, What).
@@ -161,8 +161,8 @@ extract_tests() ->
end,
[Call(Test) || Test <- Tests],
io:format("Tests ~p~n", [Tests])
- catch _:Err ->
- io:format("Error: ~p ~p~n", [Err, erlang:get_stacktrace()])
+ catch _:Err:Stacktrace ->
+ io:format("Error: ~p ~p~n", [Err, Stacktrace])
end,
file:close(In),
file:close(Out).
diff --git a/lib/stdlib/test/base64_SUITE.erl b/lib/stdlib/test/base64_SUITE.erl
index 48b3f5f959..1fc4c3fc0e 100644
--- a/lib/stdlib/test/base64_SUITE.erl
+++ b/lib/stdlib/test/base64_SUITE.erl
@@ -97,10 +97,9 @@ base64_otp_5635(Config) when is_list(Config) ->
<<"===">> = base64:decode(base64:encode("===")),
ok.
%%-------------------------------------------------------------------------
-%% OTP-6279: Guard needed so that function fails in a correct
-%% way for faulty input, i.e. function_clause.
+%% OTP-6279: Make sure illegal characters are rejected when decoding.
base64_otp_6279(Config) when is_list(Config) ->
- {'EXIT',{function_clause, _}} = (catch base64:decode("dGVzda==a")),
+ {'EXIT',_} = (catch base64:decode("dGVzda==a")),
ok.
%%-------------------------------------------------------------------------
%% Encode and decode big binaries.
@@ -115,48 +114,61 @@ big(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
%% Make sure illegal characters are rejected when decoding.
illegal(Config) when is_list(Config) ->
- {'EXIT',{function_clause, _}} = (catch base64:decode("()")),
+ %% A few samples with different error reasons. Nothing can be
+ %% assumed about the reason for the crash.
+ {'EXIT',_} = (catch base64:decode("()")),
+ {'EXIT',_} = (catch base64:decode(<<19:8,20:8,21:8,22:8>>)),
+ {'EXIT',_} = (catch base64:decode([19,20,21,22])),
+ {'EXIT',_} = (catch base64:decode_to_string(<<19:8,20:8,21:8,22:8>>)),
+ {'EXIT',_} = (catch base64:decode_to_string([19,20,21,22])),
ok.
%%-------------------------------------------------------------------------
%% mime_decode and mime_decode_to_string have different implementations
-%% so test both with the same input separately. Both functions have
-%% the same implementation for binary/string arguments.
+%% so test both with the same input separately.
%%
%% Test base64:mime_decode/1.
mime_decode(Config) when is_list(Config) ->
+ MimeDecode = fun(In) ->
+ Out = base64:mime_decode(In),
+ Out = base64:mime_decode(binary_to_list(In))
+ end,
%% Test correct padding
- <<"one">> = base64:mime_decode(<<"b25l">>),
- <<"on">> = base64:mime_decode(<<"b24=">>),
- <<"o">> = base64:mime_decode(<<"bw==">>),
+ <<"one">> = MimeDecode(<<"b25l">>),
+ <<"on">> = MimeDecode(<<"b24=">>),
+ <<"o">> = MimeDecode(<<"bw==">>),
%% Test 1 extra padding
- <<"one">> = base64:mime_decode(<<"b25l= =">>),
- <<"on">> = base64:mime_decode(<<"b24== =">>),
- <<"o">> = base64:mime_decode(<<"bw=== =">>),
+ <<"one">> = MimeDecode(<<"b25l= =">>),
+ <<"on">> = MimeDecode(<<"b24== =">>),
+ <<"o">> = MimeDecode(<<"bw=== =">>),
%% Test 2 extra padding
- <<"one">> = base64:mime_decode(<<"b25l===">>),
- <<"on">> = base64:mime_decode(<<"b24====">>),
- <<"o">> = base64:mime_decode(<<"bw=====">>),
+ <<"one">> = MimeDecode(<<"b25l===">>),
+ <<"on">> = MimeDecode(<<"b24====">>),
+ <<"o">> = MimeDecode(<<"bw=====">>),
%% Test misc embedded padding
- <<"one">> = base64:mime_decode(<<"b2=5l===">>),
- <<"on">> = base64:mime_decode(<<"b=24====">>),
- <<"o">> = base64:mime_decode(<<"b=w=====">>),
+ <<"one">> = MimeDecode(<<"b2=5l===">>),
+ <<"on">> = MimeDecode(<<"b=24====">>),
+ <<"o">> = MimeDecode(<<"b=w=====">>),
%% Test misc white space and illegals with embedded padding
- <<"one">> = base64:mime_decode(<<" b~2=\r\n5()l===">>),
- <<"on">> = base64:mime_decode(<<"\tb =2\"¤4=¤= ==">>),
- <<"o">> = base64:mime_decode(<<"\nb=w=====">>),
+ <<"one">> = MimeDecode(<<" b~2=\r\n5()l===">>),
+ <<"on">> = MimeDecode(<<"\tb =2\"¤4=¤= ==">>),
+ <<"o">> = MimeDecode(<<"\nb=w=====">>),
%% Two pads
<<"Aladdin:open sesame">> =
- base64:mime_decode("QWxhZGRpbjpvc()GVuIHNlc2FtZQ=="),
+ MimeDecode(<<"QWxhZGRpbjpvc()GVuIHNlc2FtZQ==">>),
%% One pad to ignore, followed by more text
- <<"Hello World!!">> = base64:mime_decode(<<"SGVsb)(G8gV29ybGQ=h IQ= =">>),
+ <<"Hello World!!">> = MimeDecode(<<"SGVsb)(G8gV29ybGQ=h IQ= =">>),
%% No pad
<<"Aladdin:open sesam">> =
- base64:mime_decode("QWxhZGRpbjpvcG¤\")(VuIHNlc2Ft"),
+ MimeDecode(<<"QWxhZGRpbjpvcG¤\")(VuIHNlc2Ft">>),
%% Encoded base 64 strings may be divided by non base 64 chars.
%% In this cases whitespaces.
<<"0123456789!@#0^&*();:<>,. []{}">> =
- base64:mime_decode(
+ MimeDecode(
<<"MDEy MzQ1Njc4 \tOSFAIzBeJ \nio)(oKTs6 PD4sLi \r\nBbXXt9">>),
+ %% Zeroes
+ <<"012">> = MimeDecode(<<"\000M\000D\000E\000y=\000">>),
+ <<"o">> = MimeDecode(<<"bw==\000">>),
+ <<"o">> = MimeDecode(<<"bw=\000=">>),
ok.
%%-------------------------------------------------------------------------
@@ -165,39 +177,48 @@ mime_decode(Config) when is_list(Config) ->
%% Test base64:mime_decode_to_string/1.
mime_decode_to_string(Config) when is_list(Config) ->
+ MimeDecodeToString =
+ fun(In) ->
+ Out = base64:mime_decode_to_string(In),
+ Out = base64:mime_decode_to_string(binary_to_list(In))
+ end,
%% Test correct padding
- "one" = base64:mime_decode_to_string(<<"b25l">>),
- "on" = base64:mime_decode_to_string(<<"b24=">>),
- "o" = base64:mime_decode_to_string(<<"bw==">>),
+ "one" = MimeDecodeToString(<<"b25l">>),
+ "on" = MimeDecodeToString(<<"b24=">>),
+ "o" = MimeDecodeToString(<<"bw==">>),
%% Test 1 extra padding
- "one" = base64:mime_decode_to_string(<<"b25l= =">>),
- "on" = base64:mime_decode_to_string(<<"b24== =">>),
- "o" = base64:mime_decode_to_string(<<"bw=== =">>),
+ "one" = MimeDecodeToString(<<"b25l= =">>),
+ "on" = MimeDecodeToString(<<"b24== =">>),
+ "o" = MimeDecodeToString(<<"bw=== =">>),
%% Test 2 extra padding
- "one" = base64:mime_decode_to_string(<<"b25l===">>),
- "on" = base64:mime_decode_to_string(<<"b24====">>),
- "o" = base64:mime_decode_to_string(<<"bw=====">>),
+ "one" = MimeDecodeToString(<<"b25l===">>),
+ "on" = MimeDecodeToString(<<"b24====">>),
+ "o" = MimeDecodeToString(<<"bw=====">>),
%% Test misc embedded padding
- "one" = base64:mime_decode_to_string(<<"b2=5l===">>),
- "on" = base64:mime_decode_to_string(<<"b=24====">>),
- "o" = base64:mime_decode_to_string(<<"b=w=====">>),
+ "one" = MimeDecodeToString(<<"b2=5l===">>),
+ "on" = MimeDecodeToString(<<"b=24====">>),
+ "o" = MimeDecodeToString(<<"b=w=====">>),
%% Test misc white space and illegals with embedded padding
- "one" = base64:mime_decode_to_string(<<" b~2=\r\n5()l===">>),
- "on" = base64:mime_decode_to_string(<<"\tb =2\"¤4=¤= ==">>),
- "o" = base64:mime_decode_to_string(<<"\nb=w=====">>),
+ "one" = MimeDecodeToString(<<" b~2=\r\n5()l===">>),
+ "on" = MimeDecodeToString(<<"\tb =2\"¤4=¤= ==">>),
+ "o" = MimeDecodeToString(<<"\nb=w=====">>),
%% Two pads
"Aladdin:open sesame" =
- base64:mime_decode_to_string("QWxhZGRpbjpvc()GVuIHNlc2FtZQ=="),
+ MimeDecodeToString(<<"QWxhZGRpbjpvc()GVuIHNlc2FtZQ==">>),
%% One pad to ignore, followed by more text
- "Hello World!!" = base64:mime_decode_to_string(<<"SGVsb)(G8gV29ybGQ=h IQ= =">>),
+ "Hello World!!" = MimeDecodeToString(<<"SGVsb)(G8gV29ybGQ=h IQ= =">>),
%% No pad
"Aladdin:open sesam" =
- base64:mime_decode_to_string("QWxhZGRpbjpvcG¤\")(VuIHNlc2Ft"),
+ MimeDecodeToString(<<"QWxhZGRpbjpvcG¤\")(VuIHNlc2Ft">>),
%% Encoded base 64 strings may be divided by non base 64 chars.
%% In this cases whitespaces.
"0123456789!@#0^&*();:<>,. []{}" =
- base64:mime_decode_to_string(
+ MimeDecodeToString(
<<"MDEy MzQ1Njc4 \tOSFAIzBeJ \nio)(oKTs6 PD4sLi \r\nBbXXt9">>),
+ %% Zeroes
+ "012" = MimeDecodeToString(<<"\000M\000D\000E\000y=\000">>),
+ "o" = MimeDecodeToString(<<"bw==\000">>),
+ "o" = MimeDecodeToString(<<"bw=\000=">>),
ok.
%%-------------------------------------------------------------------------
diff --git a/lib/stdlib/test/beam_lib_SUITE.erl b/lib/stdlib/test/beam_lib_SUITE.erl
index 73219f8fd8..6418dc7eb6 100644
--- a/lib/stdlib/test/beam_lib_SUITE.erl
+++ b/lib/stdlib/test/beam_lib_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -78,7 +78,7 @@ normal(Conf) when is_list(Conf) ->
BeamFile = Simple ++ ".beam",
simple_file(Source),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
do_normal(Source, PrivDir, BeamFile, []),
@@ -95,7 +95,7 @@ normal(Conf) when is_list(Conf) ->
file:delete(BeamFile),
file:delete(Source),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
true = (P0 == pps()),
ok.
@@ -173,7 +173,7 @@ error(Conf) when is_list(Conf) ->
WrongFile = Simple ++ "foo.beam",
simple_file(Source),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
{ok,_} = compile:file(Source, [{outdir,PrivDir},debug_info]),
ACopy = filename:join(PrivDir, "a_copy.beam"),
@@ -213,7 +213,7 @@ error(Conf) when is_list(Conf) ->
%% we have eliminated them.
ok = file:write_file(BeamFile, <<"FOR1",5:32,"BEAMfel">>),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
true = (P0 == pps()),
file:delete(Source),
file:delete(WrongFile),
@@ -273,7 +273,7 @@ cmp(Conf) when is_list(Conf) ->
{Source2D1, BeamFile2D1} = make_beam(Dir1, simple2, concat),
{SourceD2, BeamFileD2} = make_beam(Dir2, simple, concat),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
%% cmp
@@ -300,7 +300,7 @@ cmp(Conf) when is_list(Conf) ->
ver(not_a_directory, beam_lib:diff_dirs(foo, bar)),
true = (P0 == pps()),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
delete_files([SourceD1, BeamFileD1, Source2D1,
BeamFile2D1, SourceD2, BeamFileD2]),
@@ -321,7 +321,7 @@ cmp_literals(Conf) when is_list(Conf) ->
{SourceD1, BeamFileD1} = make_beam(Dir1, simple, constant),
{SourceD2, BeamFileD2} = make_beam(Dir2, simple, constant2),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
%% cmp
@@ -334,7 +334,7 @@ cmp_literals(Conf) when is_list(Conf) ->
ver(chunks_different, beam_lib:cmp(B1, B2)),
true = (P0 == pps()),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
delete_files([SourceD1, BeamFileD1, SourceD2, BeamFileD2]),
@@ -351,7 +351,7 @@ strip(Conf) when is_list(Conf) ->
{Source4D1, BeamFile4D1} = make_beam(PrivDir, constant, constant),
{Source5D1, BeamFile5D1} = make_beam(PrivDir, lines, lines),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
%% strip binary
@@ -392,7 +392,7 @@ strip(Conf) when is_list(Conf) ->
(catch lines:t(atom)),
true = (P0 == pps()),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
delete_files([SourceD1, BeamFileD1,
Source2D1, BeamFile2D1,
@@ -457,7 +457,7 @@ building(Conf) when is_list(Conf) ->
{SourceD1, BeamFileD1} = make_beam(Dir1, building, member),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
%% read all chunks
@@ -487,7 +487,7 @@ building(Conf) when is_list(Conf) ->
end, ChunkIds),
true = (P0 == pps()),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
delete_files([SourceD1, BeamFileD1, BeamFileD2]),
file:del_dir(Dir1),
@@ -535,7 +535,7 @@ encrypted_abstr_1(Conf) ->
%% Avoid getting an extra port when crypto starts erl_ddll.
erl_ddll:start(),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
Key = "#a_crypto_key",
@@ -549,7 +549,7 @@ encrypted_abstr_1(Conf) ->
ok = crypto:stop(), %To get rid of extra ets tables.
file:delete(BeamFile),
file:delete(Source),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
true = (P0 == pps()),
ok.
@@ -658,7 +658,7 @@ encrypted_abstr_file_1(Conf) ->
%% Avoid getting an extra port when crypto starts erl_ddll.
erl_ddll:start(),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
P0 = pps(),
Key = "Long And niCe 99Krypto Key",
@@ -676,7 +676,7 @@ encrypted_abstr_file_1(Conf) ->
file:delete(filename:join(PrivDir, ".erlang.crypt")),
file:delete(BeamFile),
file:delete(Source),
- NoOfTables = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
true = (P0 == pps()),
ok.
diff --git a/lib/stdlib/test/c_SUITE.erl b/lib/stdlib/test/c_SUITE.erl
index 4bd32a30f8..bd84cdd228 100644
--- a/lib/stdlib/test/c_SUITE.erl
+++ b/lib/stdlib/test/c_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,9 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
-export([c_1/1, c_2/1, c_3/1, c_4/1, nc_1/1, nc_2/1, nc_3/1, nc_4/1,
- ls/1, memory/1]).
+ c_default_outdir_1/1, c_default_outdir_2/1,
+ nc_default_outdir_1/1, nc_default_outdir_2/1,
+ ls/1, memory/1]).
-include_lib("common_test/include/ct.hrl").
@@ -30,7 +32,10 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [c_1, c_2, c_3, c_4, nc_1, nc_2, nc_3, nc_4, ls, memory].
+ [c_1, c_2, c_3, c_4, nc_1, nc_2, nc_3, nc_4,
+ c_default_outdir_1, c_default_outdir_2,
+ nc_default_outdir_1, nc_default_outdir_2,
+ ls, memory].
groups() ->
[].
@@ -124,6 +129,50 @@ nc_4(Config) when is_list(Config) ->
Result = nc(R,[{outdir,W}]),
{ok, m} = Result.
+c_default_outdir_1(Config) ->
+ R = filename:join(proplists:get_value(data_dir, Config), "m.erl"),
+ W = proplists:get_value(priv_dir, Config),
+ file:set_cwd(W),
+ Obj = "m" ++ code:objfile_extension(),
+ _ = file:delete(Obj),
+ false = filelib:is_file(Obj),
+ Result = c:c(R),
+ {ok, m} = Result,
+ true = filelib:is_file(Obj).
+
+c_default_outdir_2(Config) ->
+ R = filename:join(proplists:get_value(data_dir, Config), "m"),
+ W = proplists:get_value(priv_dir, Config),
+ file:set_cwd(W),
+ Obj = "m" ++ code:objfile_extension(),
+ _ = file:delete(Obj),
+ false = filelib:is_file(Obj),
+ Result = c:c(R),
+ {ok, m} = Result,
+ true = filelib:is_file(Obj).
+
+nc_default_outdir_1(Config) ->
+ R = filename:join(proplists:get_value(data_dir, Config), "m.erl"),
+ W = proplists:get_value(priv_dir, Config),
+ file:set_cwd(W),
+ Obj = "m" ++ code:objfile_extension(),
+ _ = file:delete(Obj),
+ false = filelib:is_file(Obj),
+ Result = c:nc(R),
+ {ok, m} = Result,
+ true = filelib:is_file(Obj).
+
+nc_default_outdir_2(Config) ->
+ R = filename:join(proplists:get_value(data_dir, Config), "m"),
+ W = proplists:get_value(priv_dir, Config),
+ file:set_cwd(W),
+ Obj = "m" ++ code:objfile_extension(),
+ _ = file:delete(Obj),
+ false = filelib:is_file(Obj),
+ Result = c:nc(R),
+ {ok, m} = Result,
+ true = filelib:is_file(Obj).
+
ls(Config) when is_list(Config) ->
Directory = proplists:get_value(data_dir, Config),
ok = c:ls(Directory),
diff --git a/lib/stdlib/test/calendar_SUITE.erl b/lib/stdlib/test/calendar_SUITE.erl
index 20053dfe54..55118e251c 100644
--- a/lib/stdlib/test/calendar_SUITE.erl
+++ b/lib/stdlib/test/calendar_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,7 +30,8 @@
leap_years/1,
last_day_of_the_month/1,
local_time_to_universal_time_dst/1,
- iso_week_number/1]).
+ iso_week_number/1,
+ system_time/1, rfc3339/1]).
-define(START_YEAR, 1947).
-define(END_YEAR, 2012).
@@ -40,7 +41,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[gregorian_days, gregorian_seconds, day_of_the_week,
day_of_the_week_calibrate, leap_years,
- last_day_of_the_month, local_time_to_universal_time_dst, iso_week_number].
+ last_day_of_the_month, local_time_to_universal_time_dst,
+ iso_week_number, system_time, rfc3339].
groups() ->
[].
@@ -157,10 +159,163 @@ local_time_to_universal_time_dst_x(Config) when is_list(Config) ->
iso_week_number(Config) when is_list(Config) ->
check_iso_week_number().
+system_time(Config) when is_list(Config) ->
+ EpochDate = {{1970,1,1}, {0,0,0}},
+ Epoch = calendar:datetime_to_gregorian_seconds(EpochDate),
+ Y0 = {{0,1,1},{0,0,0}},
+
+ EpochDate = calendar:system_time_to_universal_time(0, second),
+ 0 = calendar:datetime_to_gregorian_seconds(Y0),
+ Y0 = calendar:system_time_to_universal_time(-Epoch, second),
+
+ T = erlang:system_time(second),
+ UDate = calendar:system_time_to_universal_time(T, second),
+ LDate = erlang:universaltime_to_localtime(UDate),
+ LDate = calendar:system_time_to_local_time(T, second),
+
+ ok.
+
+rfc3339(Config) when is_list(Config) ->
+ Ms = [{unit, millisecond}],
+ Mys = [{unit, microsecond}],
+ Ns = [{unit, nanosecond}],
+ S = [{unit, second}],
+ D = [{time_designator, $\s}],
+ Z = [{offset, "Z"}],
+
+ "1985-04-12T23:20:50.52Z" = test_parse("1985-04-12T23:20:50.52Z", Ms),
+ "1985-04-12T23:20:50.52Z" = test_parse("1985-04-12t23:20:50.52z", Ms),
+ "1985-04-12T21:20:50.52Z" =
+ test_parse("1985-04-12T23:20:50.52+02:00", Ms),
+ "1985-04-12T23:20:50Z" = test_parse("1985-04-12T23:20:50.52Z", S),
+ "1985-04-12T23:20:50.52Z" = test_parse("1985-04-12T23:20:50.52Z", Ms),
+ "1985-04-12T23:20:50.52Z" = test_parse("1985-04-12t23:20:50.52z", Mys),
+ "1985-04-12 21:20:50.52Z" =
+ test_parse("1985-04-12 23:20:50.52+02:00", Ns++D),
+ "1985-04-12T23:20:50Z" = test_parse("1985-04-12T23:20:50.52Z"),
+ "1996-12-20T00:39:57Z" = test_parse("1996-12-19T16:39:57-08:00"),
+ "1991-01-01T00:00:00Z" = test_parse("1990-12-31T23:59:60Z"),
+ "1991-01-01T08:00:00Z" = test_parse("1990-12-31T23:59:60-08:00"),
+
+ "1996-12-20T00:39:57Z" = test_parse("1996-12-19T16:39:57-08:00"),
+ %% The leap second is not handled:
+ "1991-01-01T00:00:00Z" = test_parse("1990-12-31T23:59:60Z"),
+
+ "9999-12-31T23:59:59Z" = do_format_z(253402300799, []),
+ "9999-12-31T23:59:59.999Z" = do_format_z(253402300799*1000+999, Ms),
+ "9999-12-31T23:59:59.999999Z" =
+ do_format_z(253402300799*1000000+999999, Mys),
+ "9999-12-31T23:59:59.999999999Z" =
+ do_format_z(253402300799*1000000000+999999999, Ns),
+ {'EXIT', _} = (catch do_format_z(253402300799+1, [])),
+ {'EXIT', _} = (catch do_parse("9999-12-31T23:59:60Z", [])),
+ {'EXIT', _} = (catch do_format_z(253402300799*1000000000+999999999+1, Ns)),
+ 253402300799 = do_parse("9999-12-31T23:59:59Z", []),
+
+ "0000-01-01T00:00:00Z" = test_parse("0000-01-01T00:00:00.0+00:00"),
+ "9999-12-31T00:00:00Z" = test_parse("9999-12-31T00:00:00.0+00:00"),
+ "1584-03-04T00:00:00Z" = test_parse("1584-03-04T00:00:00.0+00:00"),
+ "1900-01-01T00:00:00Z" = test_parse("1900-01-01T00:00:00.0+00:00"),
+ "2016-01-24T00:00:00Z" = test_parse("2016-01-24T00:00:00.0+00:00"),
+ "1970-01-01T00:00:00Z" = test_parse("1970-01-01T00:00:00Z"),
+ "1970-01-02T00:00:00Z" = test_parse("1970-01-01T23:59:60Z"),
+ "1970-01-02T00:00:00Z" = test_parse("1970-01-01T23:59:60.5Z"),
+ "1970-01-02T00:00:00Z" = test_parse("1970-01-01T23:59:60.55Z"),
+ "1970-01-02T00:00:00.55Z" = test_parse("1970-01-01T23:59:60.55Z", Ms),
+ "1970-01-02T00:00:00.55Z" = test_parse("1970-01-01T23:59:60.55Z", Mys),
+ "1970-01-02T00:00:00.55Z" = test_parse("1970-01-01T23:59:60.55Z", Ns),
+ "1970-01-02T00:00:00.999999Z" =
+ test_parse("1970-01-01T23:59:60.999999Z", Mys),
+ "1970-01-02T00:00:01Z" =
+ test_parse("1970-01-01T23:59:60.999999Z", Ms),
+ "1970-01-01T00:00:00Z" = test_parse("1970-01-01T00:00:00+00:00"),
+ "1970-01-01T00:00:00Z" = test_parse("1970-01-01T00:00:00-00:00"),
+ "1969-12-31T00:01:00Z" = test_parse("1970-01-01T00:00:00+23:59"),
+ "1918-11-11T09:00:00Z" = test_parse("1918-11-11T11:00:00+02:00", Mys),
+ "1970-01-01T00:00:00.000001Z" =
+ test_parse("1970-01-01T00:00:00.000001Z", Mys),
+
+ test_time(erlang:system_time(second), []),
+ test_time(erlang:system_time(second), Z),
+ test_time(erlang:system_time(second), Z ++ S),
+ test_time(erlang:system_time(second), [{offset, "+02:20"}]),
+ test_time(erlang:system_time(millisecond), Ms),
+ test_time(erlang:system_time(microsecond), Mys++[{offset, "-02:20"}]),
+
+ T = erlang:system_time(second),
+ TS = do_format(T, []),
+ TS = do_format(T * 1000, Ms),
+ TS = do_format(T * 1000 * 1000, Mys),
+ TS = do_format(T * 1000 * 1000 * 1000, Ns),
+
+ 946720800 = TO = do_parse("2000-01-01 10:00:00Z", []),
+ Str = "2000-01-01T10:02:00+00:02",
+ Str = do_format(TO, [{offset, 120}]),
+ Str = do_format(TO * 1000, [{offset, 120 * 1000}]++Ms),
+ Str = do_format(TO * 1000 * 1000, [{offset, 120 * 1000 * 1000}]++Mys),
+ Str = do_format(TO * 1000 * 1000 * 1000,
+ [{offset, 120 * 1000 * 1000 * 1000}]++Ns),
+
+ NStr = "2000-01-01T09:58:00-00:02",
+ NStr = do_format(TO, [{offset, -120}]),
+ NStr = do_format(TO * 1000, [{offset, -120 * 1000}]++Ms),
+ NStr = do_format(TO * 1000 * 1000, [{offset, -120 * 1000 * 1000}]++Mys),
+ NStr = do_format(TO * 1000 * 1000 * 1000,
+ [{offset, -120 * 1000 * 1000 * 1000}]++Ns),
+
+ 543210000 = do_parse("1970-01-01T00:00:00.54321Z", Ns),
+ 54321000 = do_parse("1970-01-01T00:00:00.054321Z", Ns),
+ 543210 = do_parse("1970-01-01T00:00:00.54321Z", Mys),
+ 543 = do_parse("1970-01-01T00:00:00.54321Z", Ms),
+ 0 = do_parse("1970-01-01T00:00:00.000001Z", Ms),
+ 1 = do_parse("1970-01-01T00:00:00.000001Z", Mys),
+ 1000 = do_parse("1970-01-01T00:00:00.000001Z", Ns),
+ 0 = do_parse("1970-01-01Q00:00:00.00049Z", Ms),
+ 1 = do_parse("1970-01-01Q00:00:00.0005Z", Ms),
+ 6543210 = do_parse("1970-01-01T00:00:06.54321Z", Mys),
+ 298815132000000 = do_parse("1979-06-21T12:12:12Z", Mys),
+ -1613826000000000 = do_parse("1918-11-11T11:00:00Z", Mys),
+ -1613833200000000 = do_parse("1918-11-11T11:00:00+02:00", Mys),
+ -1613833200000000 = do_parse("1918-11-11T09:00:00Z", Mys),
+
+ "1970-01-01T00:00:00Z" = do_format_z(0, Mys),
+ "1970-01-01T00:00:01Z" = do_format_z(1, S),
+ "1970-01-01T00:00:00.001Z" = do_format_z(1, Ms),
+ "1970-01-01T00:00:00.000001Z" = do_format_z(1, Mys),
+ "1970-01-01T00:00:00.000000001Z" = do_format_z(1, Ns),
+ "1970-01-01T00:00:01Z" = do_format_z(1000000, Mys),
+ "1970-01-01T00:00:00.54321Z" = do_format_z(543210, Mys),
+ "1970-01-01T00:00:00.543Z" = do_format_z(543, Ms),
+ "1970-01-01T00:00:00.54321Z" = do_format_z(543210000, Ns),
+ "1970-01-01T00:00:06.54321Z" = do_format_z(6543210, Mys),
+ "1979-06-21T12:12:12Z" = do_format_z(298815132000000, Mys),
+ "1918-11-11T13:00:00Z" = do_format_z(-1613818800000000, Mys),
+ ok.
+
%%
%% LOCAL FUNCTIONS
%%
+test_parse(String) ->
+ test_parse(String, []).
+
+test_parse(String, Options) ->
+ T = do_parse(String, Options),
+ calendar:system_time_to_rfc3339(T, [{offset, "Z"} | Options]).
+
+do_parse(String, Options) ->
+ calendar:rfc3339_to_system_time(String, Options).
+
+test_time(Time, Options) ->
+ F = calendar:system_time_to_rfc3339(Time, Options),
+ Time = calendar:rfc3339_to_system_time(F, Options).
+
+do_format_z(Time, Options) ->
+ do_format(Time, [{offset, "Z"}|Options]).
+
+do_format(Time, Options) ->
+ calendar:system_time_to_rfc3339(Time, Options).
+
%% check_gregorian_days
%%
check_gregorian_days(Days, MaxDays) when Days < MaxDays ->
diff --git a/lib/stdlib/test/dets_SUITE.erl b/lib/stdlib/test/dets_SUITE.erl
index d667bd82a2..65977a764a 100644
--- a/lib/stdlib/test/dets_SUITE.erl
+++ b/lib/stdlib/test/dets_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -3275,16 +3275,16 @@ otp_8856(Config) when is_list(Config) ->
{ok, _} = dets:open_file(Tab, [{type, bag}, {file, File}]),
spawn(fun()-> Me ! {1, dets:insert(Tab, [])} end),
spawn(fun()-> Me ! {2, dets:insert_new(Tab, [])} end),
- ok = dets:close(Tab),
receive {1, ok} -> ok end,
receive {2, true} -> ok end,
+ ok = dets:close(Tab),
file:delete(File),
{ok, _} = dets:open_file(Tab, [{type, set}, {file, File}]),
spawn(fun() -> dets:delete(Tab, 0) end),
spawn(fun() -> Me ! {3, dets:insert_new(Tab, {0,0})} end),
- ok = dets:close(Tab),
receive {3, true} -> ok end,
+ ok = dets:close(Tab),
file:delete(File),
ok.
@@ -3417,6 +3417,7 @@ otp_11709(Config) when is_list(Config) ->
ok.
%% OTP-13229. open_file() exits with badarg when given binary file name.
+%% Also OTP-15253.
otp_13229(_Config) ->
F = <<"binfile.tab">>,
try dets:open_file(name, [{file, F}]) of
@@ -3425,6 +3426,20 @@ otp_13229(_Config) ->
catch
error:badarg ->
ok
+ end,
+ try dets:open_file(F, []) of % OTP-15253
+ R2 ->
+ exit({open_succeeded, R2})
+ catch
+ error:badarg ->
+ ok
+ end,
+ try dets:open_file(F) of
+ R3 ->
+ exit({open_succeeded, R3})
+ catch
+ error:badarg ->
+ ok
end.
%% OTP-13260. Race when opening a table.
diff --git a/lib/stdlib/test/edlin_expand_SUITE.erl b/lib/stdlib/test/edlin_expand_SUITE.erl
index 1f694ea549..5c2b1965ba 100644
--- a/lib/stdlib/test/edlin_expand_SUITE.erl
+++ b/lib/stdlib/test/edlin_expand_SUITE.erl
@@ -22,7 +22,7 @@
init_per_testcase/2, end_per_testcase/2,
init_per_group/2,end_per_group/2]).
-export([normal/1, quoted_fun/1, quoted_module/1, quoted_both/1, erl_1152/1,
- erl_352/1]).
+ erl_352/1, unicode/1]).
-include_lib("common_test/include/ct.hrl").
@@ -37,7 +37,8 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- [normal, quoted_fun, quoted_module, quoted_both, erl_1152, erl_352].
+ [normal, quoted_fun, quoted_module, quoted_both, erl_1152, erl_352,
+ unicode].
groups() ->
[].
@@ -150,6 +151,7 @@ quoted_both(Config) when is_list(Config) ->
{yes,"weird-fun-name'()",[]} = do_expand("'ExpandTestCaps1':'#"),
ok.
+%% Note: pull request #1152.
erl_1152(Config) when is_list(Config) ->
"\n"++"foo"++" "++[1089]++_ = do_format(["foo",[1089]]),
ok.
@@ -226,6 +228,26 @@ check_trailing([I|Str], ArityStr, Suffix, Dots) ->
Rest =:= Suffix
end.
+unicode(Config) when is_list(Config) ->
+ {module,unicode_expand} = c:l('unicode_expand'),
+ {no,[],[{"'кlирилли́ческий атом'",0},
+ {"'кlирилли́ческий атом'",1},
+ {"'кlирилли́ческий атомB'",1},
+ {"module_info",0},
+ {"module_info",1}]} = do_expand("unicode_expand:"),
+ {yes,"рилли́ческий атом", []} = do_expand("unicode_expand:'кlи"),
+ {yes,"еский атом", []} = do_expand("unicode_expand:'кlирилли́ч"),
+ {yes,"(",[]} = do_expand("unicode_expand:'кlирилли́ческий атомB'"),
+ "\n'кlирилли́ческий атом'/0 'кlирилли́ческий атом'/1 "
+ "'кlирилли́ческий атомB'/1 \nmodule_info/0 "
+ "module_info/1 \n" =
+ do_format([{"'кlирилли́ческий атом'",0},
+ {"'кlирилли́ческий атом'",1},
+ {"'кlирилли́ческий атомB'",1},
+ {"module_info",0},
+ {"module_info",1}]),
+ ok.
+
do_expand(String) ->
edlin_expand:expand(lists:reverse(String)).
diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl
index 915f478dfa..0ac99ad03a 100644
--- a/lib/stdlib/test/epp_SUITE.erl
+++ b/lib/stdlib/test/epp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,7 +28,8 @@
otp_8130/1, overload_mac/1, otp_8388/1, otp_8470/1,
otp_8562/1, otp_8665/1, otp_8911/1, otp_10302/1, otp_10820/1,
otp_11728/1, encoding/1, extends/1, function_macro/1,
- test_error/1, test_warning/1, otp_14285/1]).
+ test_error/1, test_warning/1, otp_14285/1,
+ test_if/1,source_name/1]).
-export([epp_parse_erl_form/2]).
@@ -69,7 +70,7 @@ all() ->
overload_mac, otp_8388, otp_8470, otp_8562,
otp_8665, otp_8911, otp_10302, otp_10820, otp_11728,
encoding, extends, function_macro, test_error, test_warning,
- otp_14285].
+ otp_14285, test_if, source_name].
groups() ->
[{upcase_mac, [], [upcase_mac_1, upcase_mac_2]},
@@ -551,8 +552,8 @@ otp_8130(Config) when is_list(Config) ->
"t() -> "
" L = \"{ 34 , \\\"1\\\\x{AAA}\\\" , \\\"34\\\" , X . a , $\\\\x{AAA} }\", "
" R = ?M({34,\"1\\x{aaa}\",\"34\",X.a,$\\x{aaa}}),"
- " Lt = erl_scan:string(L, 1, [unicode]),"
- " Rt = erl_scan:string(R, 1, [unicode]),"
+ " Lt = erl_scan:string(L, 1),"
+ " Rt = erl_scan:string(R, 1),"
" Lt = Rt, ok. ">>,
ok},
@@ -799,7 +800,8 @@ otp_8130(Config) when is_list(Config) ->
PreDefMacs = macs(Epp),
['BASE_MODULE','BASE_MODULE_STRING','BEAM','FILE',
'FUNCTION_ARITY','FUNCTION_NAME',
- 'LINE','MACHINE','MODULE','MODULE_STRING'] = PreDefMacs,
+ 'LINE','MACHINE','MODULE','MODULE_STRING',
+ 'OTP_RELEASE'] = PreDefMacs,
{ok,[{'-',_},{atom,_,file}|_]} = epp:scan_erl_form(Epp),
{ok,[{'-',_},{atom,_,module}|_]} = epp:scan_erl_form(Epp),
{ok,[{atom,_,t}|_]} = epp:scan_erl_form(Epp),
@@ -952,27 +954,7 @@ ifdef(Config) ->
{define_c5,
<<"-\ndefine a.\n">>,
- {errors,[{{2,1},epp,{bad,define}}],[]}},
-
- {define_c6,
- <<"\n-if.\n"
- "-endif.\n">>,
- {errors,[{{2,2},epp,{'NYI','if'}}],[]}},
-
- {define_c7,
- <<"-ifndef(a).\n"
- "-elif.\n"
- "-endif.\n">>,
- {errors,[{{2,2},epp,{'NYI',elif}}],[]}},
-
- {define_c7,
- <<"-ifndef(a).\n"
- "-if.\n"
- "-elif.\n"
- "-endif.\n"
- "-endif.\n"
- "t() -> a.\n">>,
- {errors,[{{2,2},epp,{'NYI','if'}}],[]}}
+ {errors,[{{2,1},epp,{bad,define}}],[]}}
],
[] = compile(Config, Cs),
@@ -1117,6 +1099,147 @@ test_warning(Config) ->
[] = compile(Config, Cs),
ok.
+%% OTP-12847: Test the -if and -elif directives and the built-in
+%% function defined(Symbol).
+test_if(Config) ->
+ Cs = [{if_1c,
+ <<"-if.\n"
+ "-endif.\n"
+ "-if no_parentheses.\n"
+ "-endif.\n"
+ "-if(syntax error.\n"
+ "-endif.\n"
+ "-if(true).\n"
+ "-if(a+3).\n"
+ "syntax error not triggered here.\n"
+ "-endif.\n">>,
+ {errors,[{1,epp,{bad,'if'}},
+ {3,epp,{bad,'if'}},
+ {5,erl_parse,["syntax error before: ","error"]},
+ {11,epp,{illegal,"unterminated",'if'}}],
+ []}},
+
+ {if_2c, %Bad guard expressions.
+ <<"-if(is_list(integer_to_list(42))).\n" %Not guard BIF.
+ "-endif.\n"
+ "-if(begin true end).\n"
+ "-endif.\n">>,
+ {errors,[{1,epp,{bad,'if'}},
+ {3,epp,{bad,'if'}}],
+ []}},
+
+ {if_3c, %Invalid use of defined/1.
+ <<"-if defined(42).\n"
+ "-endif.\n">>,
+ {errors,[{1,epp,{bad,'if'}}],[]}},
+
+ {if_4c,
+ <<"-elif OTP_RELEASE > 18.\n">>,
+ {errors,[{1,epp,{illegal,"unbalanced",'elif'}}],[]}},
+
+ {if_5c,
+ <<"-ifdef(not_defined_today).\n"
+ "-else.\n"
+ "-elif OTP_RELEASE > 18.\n"
+ "-endif.\n">>,
+ {errors,[{3,epp,{illegal,"unbalanced",'elif'}}],[]}},
+
+ {if_6c,
+ <<"-if(defined(OTP_RELEASE)).\n"
+ "-else.\n"
+ "-elif(true).\n"
+ "-endif.\n">>,
+ {errors,[{3,epp,elif_after_else}],[]}},
+
+ {if_7c,
+ <<"-if(begin true end).\n" %Not a guard expression.
+ "-endif.\n">>,
+ {errors,[{1,epp,{bad,'if'}}],[]}}
+
+ ],
+ [] = compile(Config, Cs),
+
+ Ts = [{if_1,
+ <<"-if(?OTP_RELEASE > 18).\n"
+ "t() -> ok.\n"
+ "-else.\n"
+ "a bug.\n"
+ "-endif.\n">>,
+ ok},
+
+ {if_2,
+ <<"-if(false).\n"
+ "a bug.\n"
+ "-elif(?OTP_RELEASE > 18).\n"
+ "t() -> ok.\n"
+ "-else.\n"
+ "a bug.\n"
+ "-endif.\n">>,
+ ok},
+
+ {if_3,
+ <<"-if(true).\n"
+ "t() -> ok.\n"
+ "-elif(?OTP_RELEASE > 18).\n"
+ "a bug.\n"
+ "-else.\n"
+ "a bug.\n"
+ "-endif.\n">>,
+ ok},
+
+ {if_4,
+ <<"-define(a, 1).\n"
+ "-if(defined(a) andalso defined(OTP_RELEASE)).\n"
+ "t() -> ok.\n"
+ "-else.\n"
+ "a bug.\n"
+ "-endif.\n">>,
+ ok},
+
+ {if_5,
+ <<"-if(defined(a)).\n"
+ "a bug.\n"
+ "-else.\n"
+ "t() -> ok.\n"
+ "-endif.\n">>,
+ ok},
+
+ {if_6,
+ <<"-if(defined(not_defined_today)).\n"
+ " -if(true).\n"
+ " bug1.\n"
+ " -elif(true).\n"
+ " bug2.\n"
+ " -elif(true).\n"
+ " bug3.\n"
+ " -else.\n"
+ " bug4.\n"
+ " -endif.\n"
+ "-else.\n"
+ "t() -> ok.\n"
+ "-endif.\n">>,
+ ok},
+
+ {if_7,
+ <<"-if(not_builtin()).\n"
+ "a bug.\n"
+ "-else.\n"
+ "t() -> ok.\n"
+ "-endif.\n">>,
+ ok},
+
+ {if_8,
+ <<"-if(42).\n" %Not boolean.
+ "a bug.\n"
+ "-else.\n"
+ "t() -> ok.\n"
+ "-endif.\n">>,
+ ok}
+ ],
+ [] = run(Config, Ts),
+
+ ok.
+
%% Advanced test on overloading macros.
overload_mac(Config) when is_list(Config) ->
Cs = [
@@ -1579,6 +1702,18 @@ function_macro(Config) ->
ok.
+source_name(Config) when is_list(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ File = filename:join(DataDir, "source_name.erl"),
+
+ source_name_1(File, "/test/gurka.erl"),
+ source_name_1(File, "gaffel.erl"),
+
+ ok.
+
+source_name_1(File, Expected) ->
+ Res = epp:parse_file(File, [{source_name, Expected}]),
+ {ok, [{attribute,_,file,{Expected,_}} | _Forms]} = Res.
check(Config, Tests) ->
eval_tests(Config, fun check_test/2, Tests).
diff --git a/lib/stdlib/test/epp_SUITE_data/source_name.erl b/lib/stdlib/test/epp_SUITE_data/source_name.erl
new file mode 100644
index 0000000000..71ad2dddb9
--- /dev/null
+++ b/lib/stdlib/test/epp_SUITE_data/source_name.erl
@@ -0,0 +1,27 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(source_name).
+-export([ok/0]).
+
+%% Changing source name should not affect headers
+-include("bar.hrl").
+
+ok() -> ok.
diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl
index c3ef4eb051..f4019d477b 100644
--- a/lib/stdlib/test/erl_eval_SUITE.erl
+++ b/lib/stdlib/test/erl_eval_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -41,12 +41,14 @@
otp_8133/1,
otp_10622/1,
otp_13228/1,
+ otp_14826/1,
funs/1,
try_catch/1,
eval_expr_5/1,
zero_width/1,
eep37/1,
- eep43/1]).
+ eep43/1,
+ otp_15035/1]).
%%
%% Define to run outside of test server
@@ -57,6 +59,7 @@
-export([count_down/2, count_down_fun/0, do_apply/2,
local_func/3, local_func_value/2]).
+-export([simple/0]).
-ifdef(STANDALONE).
-define(config(A,B),config(A,B)).
@@ -83,9 +86,9 @@ all() ->
pattern_expr, match_bin, guard_3, guard_4, guard_5, lc,
simple_cases, unary_plus, apply_atom, otp_5269,
otp_6539, otp_6543, otp_6787, otp_6977, otp_7550,
- otp_8133, otp_10622, otp_13228,
+ otp_8133, otp_10622, otp_13228, otp_14826,
funs, try_catch, eval_expr_5, zero_width,
- eep37, eep43].
+ eep37, eep43, otp_15035].
groups() ->
[].
@@ -988,6 +991,173 @@ otp_13228(_Config) ->
EFH = {value, fun({io, fwrite}, [atom]) -> io_fwrite end},
{value, worked, []} = parse_and_run("foo(io:fwrite(atom)).", LFH, EFH).
+%% OTP-14826: more accurate stacktrace.
+otp_14826(_Config) ->
+ backtrace_check("fun(P) when is_pid(P) -> true end(a).",
+ function_clause,
+ [{erl_eval,'-inside-an-interpreted-fun-',[a],[]},
+ {erl_eval,eval_fun,6},
+ ?MODULE]),
+ backtrace_check("B.",
+ {unbound_var, 'B'},
+ [{erl_eval,expr,2}, ?MODULE]),
+ backtrace_check("B.",
+ {unbound, 'B'},
+ [{erl_eval,expr,5}, ?MODULE],
+ none, none),
+ backtrace_check("1/0.",
+ badarith,
+ [{erlang,'/',[1,0],[]},
+ {erl_eval,do_apply,6}]),
+ backtrace_catch("catch 1/0.",
+ badarith,
+ [{erlang,'/',[1,0],[]},
+ {erl_eval,do_apply,6}]),
+ check(fun() -> catch exit(foo) end,
+ "catch exit(foo).",
+ {'EXIT', foo}),
+ check(fun() -> catch throw(foo) end,
+ "catch throw(foo).",
+ foo),
+ backtrace_check("try 1/0 after foo end.",
+ badarith,
+ [{erlang,'/',[1,0],[]},
+ {erl_eval,do_apply,6}]),
+ backtrace_catch("catch (try 1/0 after foo end).",
+ badarith,
+ [{erlang,'/',[1,0],[]},
+ {erl_eval,do_apply,6}]),
+ backtrace_catch("try catch 1/0 after foo end.",
+ badarith,
+ [{erlang,'/',[1,0],[]},
+ {erl_eval,do_apply,6}]),
+ backtrace_check("try a of b -> bar after foo end.",
+ {try_clause,a},
+ [{erl_eval,try_clauses,8}]),
+ check(fun() -> X = try foo:bar() catch A:B:C -> {A,B} end, X end,
+ "try foo:bar() catch A:B:C -> {A,B} end.",
+ {error, undef}),
+ backtrace_check("C = 4, try foo:bar() catch A:B:C -> {A,B,C} end.",
+ stacktrace_bound,
+ [{erl_eval,check_stacktrace_vars,2},
+ {erl_eval,try_clauses,8}],
+ none, none),
+ backtrace_catch("catch (try a of b -> bar after foo end).",
+ {try_clause,a},
+ [{erl_eval,try_clauses,8}]),
+ backtrace_check("try 1/0 catch exit:a -> foo end.",
+ badarith,
+ [{erlang,'/',[1,0],[]},
+ {erl_eval,do_apply,6}]),
+ Es = [{'try',1,[{call,1,{remote,1,{atom,1,foo},{atom,1,bar}},[]}],
+ [],
+ [{clause,1,[{tuple,1,[{var,1,'A'},{var,1,'B'},{atom,1,'C'}]}],
+ [],[{tuple,1,[{var,1,'A'},{var,1,'B'},{atom,1,'C'}]}]}],[]}],
+ try
+ erl_eval:exprs(Es, [], none, none),
+ ct:fail(stacktrace_variable)
+ catch
+ error:{illegal_stacktrace_variable,{atom,1,'C'}}:S ->
+ [{erl_eval,check_stacktrace_vars,2,_},
+ {erl_eval,try_clauses,8,_}|_] = S
+ end,
+ backtrace_check("{1,1} = {A = 1, A = 2}.",
+ {badmatch, 1},
+ [erl_eval, {lists,foldl,3}]),
+ backtrace_check("case a of a when foo:bar() -> x end.",
+ guard_expr,
+ [{erl_eval,guard0,4}], none, none),
+ backtrace_check("case a of foo() -> ok end.",
+ {illegal_pattern,{call,1,{atom,1,foo},[]}},
+ [{erl_eval,match,4}], none, none),
+ backtrace_check("case a of b -> ok end.",
+ {case_clause,a},
+ [{erl_eval,case_clauses,6}, ?MODULE]),
+ backtrace_check("if a =:= b -> ok end.",
+ if_clause,
+ [{erl_eval,if_clauses,5}, ?MODULE]),
+ backtrace_check("fun A(b) -> ok end(a).",
+ function_clause,
+ [{erl_eval,'-inside-an-interpreted-fun-',[a],[]},
+ {erl_eval,eval_named_fun,8},
+ ?MODULE]),
+ backtrace_check("[A || A <- a].",
+ {bad_generator, a},
+ [{erl_eval,eval_generate,7}, {erl_eval, eval_lc, 6}]),
+ backtrace_check("<< <<A>> || <<A>> <= a>>.",
+ {bad_generator, a},
+ [{erl_eval,eval_b_generate,7}, {erl_eval, eval_bc, 6}]),
+ backtrace_check("[A || A <- [1], begin a end].",
+ {bad_filter, a},
+ [{erl_eval,eval_filter,6}, {erl_eval, eval_generate, 7}]),
+ fun() ->
+ {'EXIT', {{badarity, {_Fun, []}}, BT}} =
+ (catch parse_and_run("fun(A) -> A end().")),
+ check_backtrace([{erl_eval,do_apply,5}, ?MODULE], BT)
+ end(),
+ fun() ->
+ {'EXIT', {{badarity, {_Fun, []}}, BT}} =
+ (catch parse_and_run("fun F(A) -> A end().")),
+ check_backtrace([{erl_eval,do_apply,5}, ?MODULE], BT)
+ end(),
+ backtrace_check("foo().",
+ undef,
+ [{erl_eval,foo,0},{erl_eval,local_func,6}],
+ none, none),
+ backtrace_check("a orelse false.",
+ {badarg, a},
+ [{erl_eval,expr,5}, ?MODULE]),
+ backtrace_check("a andalso false.",
+ {badarg, a},
+ [{erl_eval,expr,5}, ?MODULE]),
+ backtrace_check("t = u.",
+ {badmatch, u},
+ [{erl_eval,expr,5}, ?MODULE]),
+ backtrace_check("{math,sqrt}(2).",
+ {badfun, {math,sqrt}},
+ [{erl_eval,expr,5}, ?MODULE]),
+ backtrace_check("erl_eval_SUITE:simple().",
+ simple,
+ [{?MODULE,simple1,0},{?MODULE,simple,0},erl_eval]),
+ Args = [{integer,1,I} || I <- lists:seq(1, 30)],
+ backtrace_check("fun(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,"
+ "19,20,21,22,23,24,25,26,27,28,29,30) -> a end.",
+ {argument_limit,
+ {'fun',1,[{clause,1,Args,[],[{atom,1,a}]}]}},
+ [{erl_eval,expr,5}, ?MODULE]),
+ backtrace_check("fun F(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,"
+ "19,20,21,22,23,24,25,26,27,28,29,30) -> a end.",
+ {argument_limit,
+ {named_fun,1,'F',[{clause,1,Args,[],[{atom,1,a}]}]}},
+ [{erl_eval,expr,5}, ?MODULE]),
+ backtrace_check("#r{}.",
+ {undef_record,r},
+ [{erl_eval,expr,5}, ?MODULE],
+ none, none),
+ %% eval_bits
+ backtrace_check("<<100:8/bitstring>>.",
+ badarg,
+ [{eval_bits,eval_exp_field1,6},
+ eval_bits,eval_bits,erl_eval]),
+ backtrace_check("<<100:8/foo>>.",
+ {undefined_bittype,foo},
+ [{eval_bits,make_bit_type,3},eval_bits,
+ eval_bits,erl_eval],
+ none, none),
+ backtrace_check("B = <<\"foo\">>, <<B/binary-unit:7>>.",
+ badarg,
+ [{eval_bits,eval_exp_field1,6},
+ eval_bits,eval_bits,erl_eval],
+ none, none),
+ ok.
+
+simple() ->
+ A = simple1(),
+ {A}.
+
+simple1() ->
+ erlang:error(simple).
+
%% Simple cases, just to cover some code.
funs(Config) when is_list(Config) ->
do_funs(none, none),
@@ -1437,6 +1607,55 @@ eep43(Config) when is_list(Config) ->
error_check("(#{})#{nonexisting:=value}.", {badkey,nonexisting}),
ok.
+otp_15035(Config) when is_list(Config) ->
+ check(fun() ->
+ fun() when #{} ->
+ a;
+ () when #{a => b} ->
+ b;
+ () when #{a => b} =:= #{a => b} ->
+ c
+ end()
+ end,
+ "fun() when #{} ->
+ a;
+ () when #{a => b} ->
+ b;
+ () when #{a => b} =:= #{a => b} ->
+ c
+ end().",
+ c),
+ check(fun() ->
+ F = fun(M) when M#{} ->
+ a;
+ (M) when M#{a => b} ->
+ b;
+ (M) when M#{a := b} ->
+ c;
+ (M) when M#{a := b} =:= M#{a := b} ->
+ d;
+ (M) when M#{a => b} =:= M#{a => b} ->
+ e
+ end,
+ {F(#{}), F(#{a => b})}
+ end,
+ "fun() ->
+ F = fun(M) when M#{} ->
+ a;
+ (M) when M#{a => b} ->
+ b;
+ (M) when M#{a := b} ->
+ c;
+ (M) when M#{a := b} =:= M#{a := b} ->
+ d;
+ (M) when M#{a => b} =:= M#{a => b} ->
+ e
+ end,
+ {F(#{}), F(#{a => b})}
+ end().",
+ {e, d}),
+ ok.
+
%% Check the string in different contexts: as is; in fun; from compiled code.
check(F, String, Result) ->
check1(F, String, Result),
@@ -1488,6 +1707,43 @@ error_check(String, Result, LFH, EFH) ->
ct:fail({eval, Other, Result})
end.
+backtrace_check(String, Result, Backtrace) ->
+ case catch parse_and_run(String) of
+ {'EXIT', {Result, BT}} ->
+ check_backtrace(Backtrace, BT);
+ Other ->
+ ct:fail({eval, Other, Result})
+ end.
+
+backtrace_check(String, Result, Backtrace, LFH, EFH) ->
+ case catch parse_and_run(String, LFH, EFH) of
+ {'EXIT', {Result, BT}} ->
+ check_backtrace(Backtrace, BT);
+ Other ->
+ ct:fail({eval, Other, Result})
+ end.
+
+backtrace_catch(String, Result, Backtrace) ->
+ case parse_and_run(String) of
+ {value, {'EXIT', {Result, BT}}, _Bindings} ->
+ check_backtrace(Backtrace, BT);
+ Other ->
+ ct:fail({eval, Other, Result})
+ end.
+
+check_backtrace([B1|Backtrace], [B2|BT]) ->
+ case {B1, B2} of
+ {M, {M,_,_,_}} ->
+ ok;
+ {{M,F,A}, {M,F,A,_}} ->
+ ok;
+ {B, B} ->
+ ok
+ end,
+ check_backtrace(Backtrace, BT);
+check_backtrace([], _) ->
+ ok.
+
eval_string(String) ->
{value, Result, _} = parse_and_run(String),
Result.
@@ -1499,8 +1755,8 @@ parse_and_run(String) ->
parse_and_run(String, LFH, EFH) ->
{ok,Tokens,_} = erl_scan:string(String),
- {ok, [Expr]} = erl_parse:parse_exprs(Tokens),
- erl_eval:expr(Expr, [], LFH, EFH).
+ {ok, Exprs} = erl_parse:parse_exprs(Tokens),
+ erl_eval:exprs(Exprs, [], LFH, EFH).
no_final_dot(S) ->
case lists:reverse(S) of
diff --git a/lib/stdlib/test/erl_internal_SUITE.erl b/lib/stdlib/test/erl_internal_SUITE.erl
index 789a9d4363..7d9df1f989 100644
--- a/lib/stdlib/test/erl_internal_SUITE.erl
+++ b/lib/stdlib/test/erl_internal_SUITE.erl
@@ -80,7 +80,7 @@ callbacks(application) ->
callbacks(gen_server) ->
[{init,1}, {handle_call,3}, {handle_cast,2},
{handle_info,2}, {terminate,2}, {code_change,3},
- {format_status,2}];
+ {format_status,2}, {handle_continue, 2}];
callbacks(gen_fsm) ->
[{init,1}, {handle_event,3}, {handle_sync_event,4},
{handle_info,3}, {terminate,3}, {code_change,4},
@@ -101,7 +101,7 @@ callbacks(supervisor) ->
optional_callbacks(application) ->
[];
optional_callbacks(gen_server) ->
- [{handle_info, 2}, {terminate, 2}, {code_change, 3}, {format_status, 2}];
+ [{handle_info, 2}, {handle_continue, 2}, {terminate, 2}, {code_change, 3}, {format_status, 2}];
optional_callbacks(gen_fsm) ->
[{handle_info, 3}, {terminate, 3}, {code_change, 4}, {format_status, 2}];
optional_callbacks(gen_event) ->
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index 6a75eaa737..f9ab83a120 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -66,7 +66,8 @@
otp_11851/1,otp_11879/1,otp_13230/1,
record_errors/1, otp_11879_cont/1,
non_latin1_module/1, otp_14323/1,
- get_stacktrace/1, otp_14285/1]).
+ stacktrace_syntax/1,
+ otp_14285/1, otp_14378/1]).
suite() ->
[{ct_hooks,[ts_install_cth]},
@@ -87,7 +88,7 @@ all() ->
maps, maps_type, maps_parallel_match,
otp_11851, otp_11879, otp_13230,
record_errors, otp_11879_cont, non_latin1_module, otp_14323,
- get_stacktrace, otp_14285].
+ stacktrace_syntax, otp_14285, otp_14378].
groups() ->
[{unused_vars_warn, [],
@@ -2054,12 +2055,10 @@ otp_5362(Config) when is_list(Config) ->
spawn(A).
">>,
{[nowarn_unused_function]},
- {error,[{3,erl_lint,disallowed_nowarn_bif_clash},
- {4,erl_lint,disallowed_nowarn_bif_clash},
- {4,erl_lint,{bad_nowarn_bif_clash,{spawn,2}}}],
- [{5,erl_lint,{bad_nowarn_deprecated_function,{3,now,-1}}},
- {5,erl_lint,{bad_nowarn_deprecated_function,{erlang,now,-1}}},
- {5,erl_lint,{bad_nowarn_deprecated_function,{{a,b,c},now,-1}}}]}
+ {errors,[{3,erl_lint,disallowed_nowarn_bif_clash},
+ {4,erl_lint,disallowed_nowarn_bif_clash},
+ {4,erl_lint,{bad_nowarn_bif_clash,{spawn,2}}}],
+ []}
},
{otp_5362_8,
@@ -3937,10 +3936,6 @@ non_latin1_module(Config) ->
UndefBehav = {undefined_behaviour,'кирилли́ческий атом'},
"behaviour 'кирилли́ческий атом' undefined" =
format_error(UndefBehav),
- BadDepr = {bad_nowarn_deprecated_function,
- {'кирилли́ческий атом','кирилли́ческий атом',18}},
- "'кирилли́ческий атом':'кирилли́ческий атом'/18 is not a deprecated "
- "function" = format_error(BadDepr),
Ts = [{non_latin1_module,
<<"
%% Report uses of module names with non-Latin-1 characters.
@@ -3951,9 +3946,6 @@ non_latin1_module(Config) ->
-callback 'кирилли́ческий атом':'кирилли́ческий атом'() -> a.
- -compile([{nowarn_deprecated_function,
- [{'кирилли́ческий атом','кирилли́ческий атом',18}]}]).
-
%% erl_lint:gexpr/3 is not extended to check module name here:
t1() when 'кирилли́ческий атом':'кирилли́ческий атом'(1) ->
b.
@@ -3977,29 +3969,44 @@ non_latin1_module(Config) ->
{6,erl_lint,non_latin1_module_unsupported},
{8,erl_lint,non_latin1_module_unsupported},
{8,erl_lint,BadCallback},
- {10,erl_lint,non_latin1_module_unsupported},
- {14,erl_lint,illegal_guard_expr},
- {18,erl_lint,non_latin1_module_unsupported},
+ {11,erl_lint,illegal_guard_expr},
+ {15,erl_lint,non_latin1_module_unsupported},
+ {17,erl_lint,non_latin1_module_unsupported},
{20,erl_lint,non_latin1_module_unsupported},
{23,erl_lint,non_latin1_module_unsupported},
- {26,erl_lint,non_latin1_module_unsupported},
- {28,erl_lint,non_latin1_module_unsupported}],
+ {25,erl_lint,non_latin1_module_unsupported}],
[{5,erl_lint,UndefBehav},
- {6,erl_lint,UndefBehav},
- {10,erl_lint,BadDepr}]}}],
+ {6,erl_lint,UndefBehav}]}}],
run(Config, Ts),
ok.
do_non_latin1_module(Mod) ->
File = atom_to_list(Mod) ++ ".erl",
- Forms = [{attribute,1,file,{File,1}},
- {attribute,1,module,Mod},
+ L1 = erl_anno:new(1),
+ Forms = [{attribute,L1,file,{File,1}},
+ {attribute,L1,module,Mod},
{eof,2}],
error = compile:forms(Forms),
{error,_,[]} = compile:forms(Forms, [return]),
ok.
+otp_14378(Config) ->
+ Ts = [
+ {otp_14378_1,
+ <<"-export([t/0]).
+ -compile({nowarn_deprecated_function,{erlang,now,1}}).
+ t() ->
+ erlang:now().">>,
+ [],
+ {warnings,[{4,erl_lint,
+ {deprecated,{erlang,now,0},
+ "Deprecated BIF. See the \"Time and Time Correction"
+ " in Erlang\" chapter of the ERTS User's Guide"
+ " for more information."}}]}}],
+ [] = run(Config, Ts),
+ ok.
+
%% OTP-14323: Check the dialyzer attribute.
otp_14323(Config) ->
Ts = [
@@ -4048,62 +4055,40 @@ otp_14323(Config) ->
[] = run(Config, Ts),
ok.
-get_stacktrace(Config) ->
- Ts = [{old_catch,
+stacktrace_syntax(Config) ->
+ Ts = [{guard,
<<"t1() ->
- catch error(foo),
- erlang:get_stacktrace().
+ try error(foo)
+ catch _:_:Stk when is_number(Stk) -> ok
+ end.
">>,
[],
- {warnings,[{3,erl_lint,{get_stacktrace,after_old_catch}}]}},
- {nowarn_get_stacktrace,
+ {errors,[{3,erl_lint,{stacktrace_guard,'Stk'}}],[]}},
+ {bound,
<<"t1() ->
- catch error(foo),
- erlang:get_stacktrace().
- ">>,
- [nowarn_get_stacktrace],
- []},
- {try_catch,
- <<"t1(X) ->
- try abs(X) of
- _ ->
- erlang:get_stacktrace()
- catch
- _:_ -> ok
- end.
-
- t2() ->
- try error(foo)
- catch _:_ -> ok
- end,
- erlang:get_stacktrace().
-
- t3() ->
+ Stk = [],
try error(foo)
- catch _:_ ->
- try error(bar)
- catch _:_ ->
- ok
- end,
- erlang:get_stacktrace()
+ catch _:_:Stk -> ok
end.
-
- no_warning(X) ->
- try
- abs(X)
- catch
- _:_ ->
- erlang:get_stacktrace()
+ ">>,
+ [],
+ {errors,[{4,erl_lint,{stacktrace_bound,'Stk'}}],[]}},
+ {guard_and_bound,
+ <<"t1() ->
+ Stk = [],
+ try error(foo)
+ catch _:_:Stk when is_integer(Stk) -> ok
end.
">>,
[],
- {warnings,[{4,erl_lint,{get_stacktrace,wrong_part_of_try}},
- {13,erl_lint,{get_stacktrace,after_try}},
- {22,erl_lint,{get_stacktrace,after_try}}]}}],
+ {errors,[{4,erl_lint,{stacktrace_bound,'Stk'}},
+ {4,erl_lint,{stacktrace_guard,'Stk'}}],[]}}
+ ],
run(Config, Ts),
ok.
+
%% Unicode atoms.
otp_14285(Config) ->
%% A small sample of all the errors and warnings in module erl_lint.
diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl
index 808ba9b4c1..dda8d0a12e 100644
--- a/lib/stdlib/test/erl_pp_SUITE.erl
+++ b/lib/stdlib/test/erl_pp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1262,7 +1262,7 @@ parse_forms(Chars) ->
parse_forms2([], _Cont, _Line, Forms) ->
lists:reverse(Forms);
parse_forms2(String, Cont0, Line, Forms) ->
- case erl_scan:tokens(Cont0, String, Line, [unicode]) of
+ case erl_scan:tokens(Cont0, String, Line) of
{done, {ok, Tokens, EndLine}, Chars} ->
{ok, Form} = erl_parse:parse_form(Tokens),
parse_forms2(Chars, [], EndLine, [Form | Forms]);
@@ -1303,7 +1303,7 @@ parse_and_pp_expr(String, Indent, Options) ->
erl_pp:expr(parse_expr(StringDot), Indent, Options).
parse_expr(Chars) ->
- {ok, Tokens, _} = erl_scan:string(Chars, 1, [unicode]),
+ {ok, Tokens, _} = erl_scan:string(Chars, 1),
{ok, [Expr]} = erl_parse:parse_exprs(Tokens),
Expr.
diff --git a/lib/stdlib/test/error_logger_h_SUITE.erl b/lib/stdlib/test/error_logger_h_SUITE.erl
index 30f96e0522..bf9b6d9ad6 100644
--- a/lib/stdlib/test/error_logger_h_SUITE.erl
+++ b/lib/stdlib/test/error_logger_h_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -62,6 +62,7 @@ logfile(Config) ->
error_logger:logfile({open,Log}),
ok = rpc:call(Node, erlang, apply, [fun gen_events/1,[Ev]]),
AtNode = iolist_to_binary(["** at node ",atom_to_list(Node)," **"]),
+ timer:sleep(1000), % some time get all log events in the log
error_logger:logfile(close),
analyse_events(Log, Ev, [AtNode], unlimited),
@@ -124,6 +125,7 @@ tty(Config) ->
ok = rpc:call(Node, erlang, apply, [fun gen_events/1,[Ev]]),
tty_log_close(),
AtNode = iolist_to_binary(["** at node ",atom_to_list(Node)," **"]),
+ timer:sleep(1000), % some time get all log events in the log
analyse_events(Log, Ev, [AtNode], unlimited),
test_server:stop_node(Node),
@@ -162,7 +164,7 @@ tty_log_open(Log) ->
{ok,D} -> D;
_ -> unlimited
end,
- error_logger:add_report_handler(?MODULE, {Fd,Depth}),
+ error_logger:add_report_handler(?MODULE, {Fd,Depth,latin1}),
Fd.
tty_log_close() ->
@@ -207,7 +209,7 @@ event_templates() ->
gen_events(Ev) ->
io:format("node = ~p\n", [node()]),
io:format("group leader = ~p\n", [group_leader()]),
- io:format("~p\n", [gen_event:which_handlers(error_logger)]),
+ io:format("~p\n", [error_logger:which_report_handlers()]),
call_error_logger(Ev),
{Pid,Ref} = spawn_monitor(fun() -> error(ouch) end),
@@ -240,6 +242,7 @@ analyse_events(Log, Ev, AtNode, Depth) ->
call_error_logger([{F,Args}|T]) ->
apply(error_logger, F, Args),
+ timer:sleep(10),
call_error_logger(T);
call_error_logger([]) -> ok.
@@ -257,8 +260,7 @@ match_output([Item|T], Lines0, AtNode, Depth) ->
Lines ->
match_output(T, Lines, AtNode, Depth)
catch
- C:E ->
- Stk = erlang:get_stacktrace(),
+ C:E:Stk ->
io:format("ITEM: ~p", [Item]),
io:format("LINES: ~p", [Lines0]),
erlang:raise(C, E, Stk)
@@ -393,11 +395,11 @@ dl_format_1([], [], _, Facc, Aacc) ->
%%% calling error_logger_tty_h:write_event/2.
%%%
-init({_,_}=St) ->
+init({_,_,_}=St) ->
{ok,St}.
-handle_event(Event, {Fd,Depth}=St) ->
- case error_logger_tty_h:write_event(tag_event(Event), io_lib, Depth) of
+handle_event(Event, {Fd,Depth,Enc}=St) ->
+ case error_logger_tty_h:write_event(tag_event(Event), io_lib, {Depth,Enc}) of
ok ->
ok;
Str when is_list(Str) ->
@@ -405,7 +407,7 @@ handle_event(Event, {Fd,Depth}=St) ->
end,
{ok,St}.
-terminate(_Reason, {Fd,_}) ->
+terminate(_Reason, {Fd,_,_}) ->
ok = file:close(Fd),
[].
diff --git a/lib/stdlib/test/escript_SUITE_data/unicode1 b/lib/stdlib/test/escript_SUITE_data/unicode1
index 351bb785e5..8dc9d450b8 100755
--- a/lib/stdlib/test/escript_SUITE_data/unicode1
+++ b/lib/stdlib/test/escript_SUITE_data/unicode1
@@ -8,7 +8,7 @@ main(_) ->
_D = erlang:system_flag(backtrace_depth, 0),
A = <<"\x{aaa}"/utf8>>,
S = lists:flatten(io_lib:format("~p/~p.", [A, A])),
- {ok, Ts, _} = erl_scan:string(S, 1, [unicode]),
+ {ok, Ts, _} = erl_scan:string(S, 1),
{ok, Es} = erl_parse:parse_exprs(Ts),
B = erl_eval:new_bindings(),
erl_eval:exprs(Es, B).
diff --git a/lib/stdlib/test/escript_SUITE_data/unicode2 b/lib/stdlib/test/escript_SUITE_data/unicode2
index 495188f6f0..d0195b036c 100755
--- a/lib/stdlib/test/escript_SUITE_data/unicode2
+++ b/lib/stdlib/test/escript_SUITE_data/unicode2
@@ -8,7 +8,7 @@ main(_) ->
_D = erlang:system_flag(backtrace_depth, 0),
A = <<"\x{aa}">>,
S = lists:flatten(io_lib:format("~p/~p.", [A, A])),
- {ok, Ts, _} = erl_scan:string(S, 1, [unicode]),
+ {ok, Ts, _} = erl_scan:string(S, 1),
{ok, Es} = erl_parse:parse_exprs(Ts),
B = erl_eval:new_bindings(),
erl_eval:exprs(Es, B).
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index 257a718404..aa2e352c29 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -55,6 +55,7 @@
-export([t_repair_continuation/1]).
-export([t_match_spec_run/1]).
-export([t_bucket_disappears/1]).
+-export([t_named_select/1]).
-export([otp_5340/1]).
-export([otp_6338/1]).
-export([otp_6842_select_1000/1]).
@@ -65,7 +66,7 @@
meta_lookup_named_read/1, meta_lookup_named_write/1,
meta_newdel_unnamed/1, meta_newdel_named/1]).
-export([smp_insert/1, smp_fixed_delete/1, smp_unfix_fix/1, smp_select_delete/1,
- smp_select_replace/1, otp_8166/1, otp_8732/1]).
+ smp_select_replace/1, otp_8166/1, otp_8732/1, delete_unfix_race/1]).
-export([exit_large_table_owner/1,
exit_many_large_table_owner/1,
exit_many_tables_owner/1,
@@ -78,6 +79,7 @@
-export([ets_all/1]).
-export([massive_ets_all/1]).
-export([take/1]).
+-export([whereis_table/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
%% Convenience for manual testing
@@ -85,6 +87,7 @@
-export([t_select_reverse/1]).
+-include_lib("stdlib/include/ms_transform.hrl"). % ets:fun2ms
-include_lib("common_test/include/ct.hrl").
-define(m(A,B), assert_eq(A,B)).
@@ -124,6 +127,7 @@ all() ->
t_insert_list, t_test_ms, t_select_delete, t_select_replace,
t_select_replace_next_bug,
t_ets_dets, memory, t_select_reverse, t_bucket_disappears,
+ t_named_select,
select_fail, t_insert_new, t_repair_continuation,
otp_5340, otp_6338, otp_6842_select_1000, otp_7665,
otp_8732, meta_wb, grow_shrink, grow_pseudo_deleted,
@@ -138,7 +142,9 @@ all() ->
otp_9423,
ets_all,
massive_ets_all,
- take].
+ take,
+ whereis_table,
+ delete_unfix_race].
groups() ->
[{new, [],
@@ -170,10 +176,12 @@ groups() ->
init_per_suite(Config) ->
erts_debug:set_internal_state(available_internal_state, true),
+ erts_debug:set_internal_state(ets_force_trap, true),
Config.
end_per_suite(_Config) ->
stop_spawn_logger(),
+ erts_debug:set_internal_state(ets_force_trap, false),
catch erts_debug:set_internal_state(available_internal_state, false),
ok.
@@ -204,6 +212,38 @@ t_bucket_disappears_do(Opts) ->
true = ets:delete(abcd),
verify_etsmem(EtsMem).
+%% OTP-21: Test that select/1 fails if named table was deleted and recreated
+%% and succeeds if table was renamed.
+t_named_select(_Config) ->
+ repeat_for_opts(fun t_named_select_do/1).
+
+t_named_select_do(Opts) ->
+ EtsMem = etsmem(),
+ T = t_name_tid_select,
+ ets_new(T, [named_table | Opts]),
+ ets:insert(T, {1,11}),
+ ets:insert(T, {2,22}),
+ ets:insert(T, {3,33}),
+ MS = [{{'$1', 22}, [], ['$1']}],
+ {[2], Cont1} = ets:select(T, MS, 1),
+ ets:delete(T),
+ {'EXIT',{badarg,_}} = (catch ets:select(Cont1)),
+ ets_new(T, [named_table | Opts]),
+ {'EXIT',{badarg,_}} = (catch ets:select(Cont1)),
+
+ true = ets:insert_new(T, {1,22}),
+ true = ets:insert_new(T, {2,22}),
+ true = ets:insert_new(T, {4,22}),
+ {[A,B], Cont2} = ets:select(T, MS, 2),
+ ets:rename(T, abcd),
+ {[C], '$end_of_table'} = ets:select(Cont2),
+ 7 = A + B + C,
+
+ true = ets:delete(abcd),
+ verify_etsmem(EtsMem).
+
+
+
%% Check ets:match_spec_run/2.
t_match_spec_run(Config) when is_list(Config) ->
@@ -699,7 +739,7 @@ whitebox_2(Opts) ->
ets:delete(T2),
ok.
-select_bound_chunk(Config) ->
+select_bound_chunk(_Config) ->
repeat_for_opts(fun select_bound_chunk_do/1, [all_types]).
select_bound_chunk_do(Opts) ->
@@ -777,7 +817,60 @@ t_delete_all_objects_do(Opts) ->
4000 = ets:info(T,size),
true = ets:delete_all_objects(T),
0 = ets:info(T,size),
- ets:delete(T).
+ ets:delete(T),
+
+ %% Test delete_all_objects is atomic
+ T2 = ets:new(t_delete_all_objects, [public | Opts]),
+ Self = self(),
+ Inserters = [spawn_link(fun() -> inserter(T2, 100*1000, 1, Self) end) || _ <- [1,2,3,4]],
+ [receive {Ipid, running} -> ok end || Ipid <- Inserters],
+
+ ets:delete_all_objects(T2),
+ erlang:yield(),
+ [Ipid ! stop || Ipid <- Inserters],
+ Result = [receive {Ipid, stopped, Highest} -> {Ipid,Highest} end || Ipid <- Inserters],
+
+ %% Verify unbroken sequences of objects inserted _after_ ets:delete_all_objects.
+ Sum = lists:foldl(fun({Ipid, Highest}, AccSum) ->
+ %% ets:fun2ms(fun({{K,Ipid}}) when K =< Highest -> true end),
+ AliveMS = [{{{'$1',Ipid}},[{'=<','$1',{const,Highest}}],[true]}],
+ Alive = ets:select_count(T2, AliveMS),
+ Lowest = Highest - (Alive-1),
+
+ %% ets:fun2ms(fun({{K,Ipid}}) when K < Lowest -> true end)
+ DeletedMS = [{{{'$1',Ipid}},[{'<','$1',{const,Lowest}}],[true]}],
+ 0 = ets:select_count(T2, DeletedMS),
+ AccSum + Alive
+ end,
+ 0,
+ Result),
+ ok = case ets:info(T2, size) of
+ Sum -> ok;
+ Size ->
+ io:format("Sum = ~p\nSize = ~p\n", [Sum, Size]),
+ {Sum,Size}
+ end,
+
+ ets:delete(T2).
+
+inserter(_, 0, _, _) ->
+ ok;
+inserter(T, N, Next, Papa) ->
+ case Next of
+ 10*1000 ->
+ Papa ! {self(), running};
+ _ ->
+ ok
+ end,
+
+ ets:insert(T, {{Next, self()}}),
+ receive
+ stop ->
+ Papa ! {self(), stopped, Next},
+ ok
+ after 0 ->
+ inserter(T, N-1, Next+1, Papa)
+ end.
%% Test ets:delete_object/2.
@@ -1702,7 +1795,7 @@ do_random_test() ->
ets:delete(Set),
verify_etsmem(EtsMem).
-%% Ttest various variants of update_element.
+%% Test various variants of update_element.
update_element(Config) when is_list(Config) ->
EtsMem = etsmem(),
repeat_for_opts(fun update_element_opts/1),
@@ -2303,13 +2396,8 @@ write_concurrency(Config) when is_list(Config) ->
NoHashMem = ets:info(No7,memory),
NoHashMem = ets:info(No8,memory),
- case erlang:system_info(smp_support) of
- true ->
- true = YesMem > NoHashMem,
- true = YesMem > NoTreeMem;
- false ->
- true = YesMem =:= NoHashMem
- end,
+ true = YesMem > NoHashMem,
+ true = YesMem > NoTreeMem,
{'EXIT',{badarg,_}} = (catch ets_new(foo,[public,{write_concurrency,foo}])),
{'EXIT',{badarg,_}} = (catch ets_new(foo,[public,{write_concurrency}])),
@@ -3672,7 +3760,7 @@ verify_rescheduling_exit(Config, ForEachData, Flags, Fix, NOTabs, NOProcs) ->
XScheds = count_exit_sched(TP),
io:format("~p XScheds=~p~n",
[TP, XScheds]),
- true = XScheds >= 5
+ true = XScheds >= 3
end,
TPs),
stop_loopers(LPs),
@@ -4124,6 +4212,7 @@ info_do(Opts) ->
{value, {keypos, 2}} = lists:keysearch(keypos, 1, Res),
{value, {protection, protected}} =
lists:keysearch(protection, 1, Res),
+ {value, {id, Tab}} = lists:keysearch(id, 1, Res),
true = ets:delete(Tab),
undefined = ets:info(non_existing_table_xxyy),
undefined = ets:info(non_existing_table_xxyy,type),
@@ -5421,6 +5510,46 @@ smp_fixed_delete_do() ->
%%verify_table_load(T),
ets:delete(T).
+%% ERL-720
+%% Provoke race between ets:delete and table unfix (by select_count)
+%% that caused ets_misc memory counter to indicate false leak.
+delete_unfix_race(Config) when is_list(Config) ->
+ EtsMem = etsmem(),
+ Table = ets:new(t,[set,public,{write_concurrency,true}]),
+ InsertOp =
+ fun() ->
+ receive stop ->
+ false
+ after 0 ->
+ ets:insert(Table, {rand:uniform(10)}),
+ true
+ end
+ end,
+ DeleteOp =
+ fun() ->
+ receive stop ->
+ false
+ after 0 ->
+ ets:delete(Table, rand:uniform(10)),
+ true
+ end
+ end,
+ SelectOp =
+ fun() ->
+ ets:select_count(Table, ets:fun2ms(fun(X) -> true end))
+ end,
+ Main = self(),
+ Ins = spawn(fun()-> repeat_while(InsertOp), Main ! self() end),
+ Del = spawn(fun()-> repeat_while(DeleteOp), Main ! self() end),
+ spawn(fun()->
+ repeat(SelectOp, 10000),
+ Del ! stop,
+ Ins ! stop
+ end),
+ [receive Pid -> ok end || Pid <- [Ins,Del]],
+ ets:delete(Table),
+ verify_etsmem(EtsMem).
+
num_of_buckets(T) ->
element(1,ets:info(T,stats)).
@@ -5917,6 +6046,36 @@ take(Config) when is_list(Config) ->
ets:delete(T3),
ok.
+whereis_table(Config) when is_list(Config) ->
+ %% Do we return 'undefined' when the named table doesn't exist?
+ undefined = ets:whereis(whereis_test),
+
+ %% Does the tid() refer to the same table as the name?
+ whereis_test = ets:new(whereis_test, [named_table]),
+ Tid = ets:whereis(whereis_test),
+
+ ets:insert(whereis_test, [{hello}, {there}]),
+
+ [[{hello}],[{there}]] = ets:match(whereis_test, '$1'),
+ [[{hello}],[{there}]] = ets:match(Tid, '$1'),
+
+ true = ets:delete_all_objects(Tid),
+
+ [] = ets:match(whereis_test, '$1'),
+ [] = ets:match(Tid, '$1'),
+
+ %% Does the name disappear when deleted through the tid()?
+ true = ets:delete(Tid),
+ undefined = ets:info(whereis_test),
+ {'EXIT',{badarg, _}} = (catch ets:match(whereis_test, '$1')),
+
+ %% Is the old tid() broken when the table is re-created with the same
+ %% name?
+ whereis_test = ets:new(whereis_test, [named_table]),
+ [] = ets:match(whereis_test, '$1'),
+ {'EXIT',{badarg, _}} = (catch ets:match(Tid, '$1')),
+
+ ok.
%%
%% Utility functions:
@@ -5932,16 +6091,11 @@ add_lists([E1|T1], [E2|T2], Acc) ->
run_smp_workers(InitF,ExecF,FiniF,Laps) ->
run_smp_workers(InitF,ExecF,FiniF,Laps, 0).
run_smp_workers(InitF,ExecF,FiniF,Laps, Exclude) ->
- case erlang:system_info(smp_support) of
- true ->
- case erlang:system_info(schedulers_online) of
- N when N > Exclude ->
- run_workers_do(InitF,ExecF,FiniF,Laps, N - Exclude);
- _ ->
- {skipped, "Too few schedulers online"}
- end;
- false ->
- {skipped,"No smp support"}
+ case erlang:system_info(schedulers_online) of
+ N when N > Exclude ->
+ run_workers_do(InitF,ExecF,FiniF,Laps, N - Exclude);
+ _ ->
+ {skipped, "Too few schedulers online"}
end.
run_sched_workers(InitF,ExecF,FiniF,Laps) ->
@@ -6053,17 +6207,23 @@ etsmem() ->
end},
{Mem,AllTabs}.
-verify_etsmem({MemInfo,AllTabs}) ->
+
+verify_etsmem(MI) ->
wait_for_test_procs(),
+ verify_etsmem(MI, 1).
+
+verify_etsmem({MemInfo,AllTabs}, Try) ->
case etsmem() of
{MemInfo,_} ->
io:format("Ets mem info: ~p", [MemInfo]),
- case MemInfo of
- {ErlMem,EtsAlloc} when ErlMem == notsup; EtsAlloc == undefined ->
+ case {MemInfo, Try} of
+ {{ErlMem,EtsAlloc},_} when ErlMem == notsup; EtsAlloc == undefined ->
%% Use 'erl +Mea max' to do more complete memory leak testing.
{comment,"Incomplete or no mem leak testing"};
- _ ->
- ok
+ {_, 1} ->
+ ok;
+ _ ->
+ {comment, "Transient memory discrepancy"}
end;
{MemInfo2, AllTabs2} ->
@@ -6071,7 +6231,15 @@ verify_etsmem({MemInfo,AllTabs}) ->
io:format("Actual: ~p", [MemInfo2]),
io:format("Changed tables before: ~p\n",[AllTabs -- AllTabs2]),
io:format("Changed tables after: ~p\n", [AllTabs2 -- AllTabs]),
- ct:fail("Failed memory check")
+ case Try < 2 of
+ true ->
+ io:format("\nThis discrepancy could be caused by an "
+ "inconsistent memory \"snapshot\""
+ "\nTry again...\n", []),
+ verify_etsmem({MemInfo, AllTabs}, Try+1);
+ false ->
+ ct:fail("Failed memory check")
+ end
end.
@@ -6102,20 +6270,23 @@ spawn_logger(Procs) ->
ok;
(Proc) ->
Mon = erlang:monitor(process, Proc),
- receive
+ ok = receive
{'DOWN', Mon, _, _, _} ->
ok
after 0 ->
case Kill of
true -> exit(Proc, kill);
- _ ->
- erlang:display({"Waiting for 'DOWN' from", Proc,
- process_info(Proc),
- pid_status(Proc)})
+ _ -> ok
end,
receive
{'DOWN', Mon, _, _, _} ->
ok
+ after 5000 ->
+ io:format("Waiting for 'DOWN' from ~w, status=~w\n"
+ "info = ~p\n", [Proc,
+ pid_status(Proc),
+ process_info(Proc)]),
+ timeout
end
end
end, Procs),
@@ -6251,11 +6422,9 @@ spawn_monitor_with_pid(Pid, Fun, N) ->
only_if_smp(Func) ->
only_if_smp(2, Func).
only_if_smp(Schedulers, Func) ->
- case {erlang:system_info(smp_support),
- erlang:system_info(schedulers_online)} of
- {false,_} -> {skip,"No smp support"};
- {true,N} when N < Schedulers -> {skip,"Too few schedulers online"};
- {true,_} -> Func()
+ case erlang:system_info(schedulers_online) of
+ N when N < Schedulers -> {skip,"Too few schedulers online"};
+ _ -> Func()
end.
%% Copy-paste from emulator/test/binary_SUITE.erl
@@ -6401,7 +6570,7 @@ very_big_num(0, Result) ->
Result.
make_port() ->
- open_port({spawn, "efile"}, [eof]).
+ hd(erlang:ports()).
make_pid() ->
spawn_link(fun sleeper/0).
diff --git a/lib/stdlib/test/filelib_SUITE.erl b/lib/stdlib/test/filelib_SUITE.erl
index c94821bc75..7403d52881 100644
--- a/lib/stdlib/test/filelib_SUITE.erl
+++ b/lib/stdlib/test/filelib_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,13 +26,15 @@
wildcard_one/1,wildcard_two/1,wildcard_errors/1,
fold_files/1,otp_5960/1,ensure_dir_eexist/1,ensure_dir_symlink/1,
wildcard_symlink/1, is_file_symlink/1, file_props_symlink/1,
- find_source/1]).
+ find_source/1, find_source_subdir/1]).
-import(lists, [foreach/2]).
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
+-define(PRIM_FILE, prim_file).
+
init_per_testcase(_Case, Config) ->
Config.
@@ -47,7 +49,7 @@ all() ->
[wildcard_one, wildcard_two, wildcard_errors,
fold_files, otp_5960, ensure_dir_eexist, ensure_dir_symlink,
wildcard_symlink, is_file_symlink, file_props_symlink,
- find_source].
+ find_source, find_source_subdir].
groups() ->
[].
@@ -120,7 +122,7 @@ wcc(Wc, Error) ->
do_wildcard_1(Dir, Wcf0) ->
do_wildcard_2(Dir, Wcf0),
Wcf = fun(Wc0) ->
- Wc = filename:join(Dir, Wc0),
+ Wc = Dir ++ "/" ++ Wc0,
L = Wcf0(Wc),
[subtract_dir(N, Dir) || N <- L]
end,
@@ -268,8 +270,37 @@ do_wildcard_9(Dir, Wcf) ->
%% Cleanup.
del(Files),
[ok = file:del_dir(D) || D <- lists:reverse(Dirs)],
- ok.
+ do_wildcard_10(Dir, Wcf).
+
+%% ERL-451/OTP-14577: Escape characters using \\.
+do_wildcard_10(Dir, Wcf) ->
+ All0 = ["{abc}","abc","def","---","z--","@a,b","@c"],
+ All = case os:type() of
+ {unix,_} ->
+ %% '?' is allowed in file names on Unix, but
+ %% not on Windows.
+ ["?q"|All0];
+ _ ->
+ All0
+ end,
+ Files = mkfiles(lists:reverse(All), Dir),
+
+ ["{abc}"] = Wcf("\\{a*"),
+ ["{abc}"] = Wcf("\\{abc}"),
+ ["abc","def","z--"] = Wcf("[a-z]*"),
+ ["---","abc","z--"] = Wcf("[a\\-z]*"),
+ ["@a,b","@c"] = Wcf("@{a\\,b,c}"),
+ ["@c"] = Wcf("@{a,b,c}"),
+
+ case os:type() of
+ {unix,_} ->
+ ["?q"] = Wcf("\\?q");
+ _ ->
+ [] = Wcf("\\?q")
+ end,
+ del(Files),
+ ok.
fold_files(Config) when is_list(Config) ->
Dir = filename:join(proplists:get_value(priv_dir, Config), "fold_files"),
@@ -417,10 +448,10 @@ wildcard_symlink(Config) when is_list(Config) ->
erl_prim_loader)),
["sub","symlink"] =
basenames(Dir, filelib:wildcard(filename:join(Dir, "*"),
- prim_file)),
+ ?PRIM_FILE)),
["symlink"] =
basenames(Dir, filelib:wildcard(filename:join(Dir, "symlink"),
- prim_file)),
+ ?PRIM_FILE)),
ok = file:delete(AFile),
%% The symlink should still be visible even when its target
%% has been deleted.
@@ -436,10 +467,10 @@ wildcard_symlink(Config) when is_list(Config) ->
erl_prim_loader)),
["sub","symlink"] =
basenames(Dir, filelib:wildcard(filename:join(Dir, "*"),
- prim_file)),
+ ?PRIM_FILE)),
["symlink"] =
basenames(Dir, filelib:wildcard(filename:join(Dir, "symlink"),
- prim_file)),
+ ?PRIM_FILE)),
ok
end.
@@ -468,17 +499,17 @@ is_file_symlink(Config) ->
ok ->
true = filelib:is_dir(DirAlias),
true = filelib:is_dir(DirAlias, erl_prim_loader),
- true = filelib:is_dir(DirAlias, prim_file),
+ true = filelib:is_dir(DirAlias, ?PRIM_FILE),
true = filelib:is_file(DirAlias),
true = filelib:is_file(DirAlias, erl_prim_loader),
- true = filelib:is_file(DirAlias, prim_file),
+ true = filelib:is_file(DirAlias, ?PRIM_FILE),
ok = file:make_symlink(AFile,FileAlias),
true = filelib:is_file(FileAlias),
true = filelib:is_file(FileAlias, erl_prim_loader),
- true = filelib:is_file(FileAlias, prim_file),
+ true = filelib:is_file(FileAlias, ?PRIM_FILE),
true = filelib:is_regular(FileAlias),
true = filelib:is_regular(FileAlias, erl_prim_loader),
- true = filelib:is_regular(FileAlias, prim_file),
+ true = filelib:is_regular(FileAlias, ?PRIM_FILE),
ok
end.
@@ -499,11 +530,11 @@ file_props_symlink(Config) ->
{_,_} = LastMod = filelib:last_modified(AFile),
LastMod = filelib:last_modified(Alias),
LastMod = filelib:last_modified(Alias, erl_prim_loader),
- LastMod = filelib:last_modified(Alias, prim_file),
+ LastMod = filelib:last_modified(Alias, ?PRIM_FILE),
FileSize = filelib:file_size(AFile),
FileSize = filelib:file_size(Alias),
FileSize = filelib:file_size(Alias, erl_prim_loader),
- FileSize = filelib:file_size(Alias, prim_file)
+ FileSize = filelib:file_size(Alias, ?PRIM_FILE)
end.
find_source(Config) when is_list(Config) ->
@@ -536,16 +567,18 @@ find_source(Config) when is_list(Config) ->
[{".erl",".yrl",[{"",""}]}]),
{ok, ParserErl} = filelib:find_source(code:which(core_parse)),
+ ParserErlName = filename:basename(ParserErl),
+ ParserErlDir = filename:dirname(ParserErl),
{ok, ParserYrl} = filelib:find_source(ParserErl),
"lry." ++ _ = lists:reverse(ParserYrl),
- {ok, ParserYrl} = filelib:find_source(ParserErl,
+ {ok, ParserYrl} = filelib:find_source(ParserErlName, ParserErlDir,
[{".beam",".erl",[{"ebin","src"}]},
{".erl",".yrl",[{"",""}]}]),
%% find_source automatically checks the local directory regardless of rules
{ok, ParserYrl} = filelib:find_source(ParserErl),
- {ok, ParserYrl} = filelib:find_source(ParserErl,
- [{".beam",".erl",[{"ebin","src"}]}]),
+ {ok, ParserYrl} = filelib:find_source(ParserErlName, ParserErlDir,
+ [{".erl",".yrl",[{"ebin","src"}]}]),
%% find_file does not check the local directory unless in the rules
ParserYrlName = filename:basename(ParserYrl),
@@ -559,3 +592,24 @@ find_source(Config) when is_list(Config) ->
{ok, ParserYrl} = filelib:find_file(ParserYrlName, ParserYrlDir),
{ok, ParserYrl} = filelib:find_file(ParserYrlName, ParserYrlDir, []),
ok.
+
+find_source_subdir(Config) when is_list(Config) ->
+ BeamFile = code:which(inets), % Located in lib/inets/src/inets_app/
+ BeamName = filename:basename(BeamFile),
+ BeamDir = filename:dirname(BeamFile),
+ SrcName = filename:basename(BeamFile, ".beam") ++ ".erl",
+
+ {ok, SrcFile} = filelib:find_source(BeamName, BeamDir),
+ SrcName = filename:basename(SrcFile),
+
+ {error, not_found} =
+ filelib:find_source(BeamName, BeamDir,
+ [{".beam",".erl",[{"ebin","src"}]}]),
+ {ok, SrcFile} =
+ filelib:find_source(BeamName, BeamDir,
+ [{".beam",".erl",
+ [{"ebin",filename:join("src", "*")}]}]),
+
+ {ok, SrcFile} = filelib:find_file(SrcName, BeamDir),
+
+ ok.
diff --git a/lib/stdlib/test/filename_SUITE.erl b/lib/stdlib/test/filename_SUITE.erl
index fc77593bb8..f284eb1ed6 100644
--- a/lib/stdlib/test/filename_SUITE.erl
+++ b/lib/stdlib/test/filename_SUITE.erl
@@ -107,6 +107,17 @@ absname(Config) when is_list(Config) ->
[Drive|":/erlang/src"] = filename:absname([Drive|":erlang/src"]),
"a:/erlang" = filename:absname("a:erlang"),
+ "//foo" = filename:absname("//foo"),
+ "//foo/bar" = filename:absname("//foo/bar"),
+ "//foo/\bar" = filename:absname("//foo/\bar"),
+ "//foo/bar/baz" = filename:absname("//foo/bar\\baz"),
+ "//foo/bar/baz" = filename:absname("//foo\\bar/baz"),
+ "//foo" = filename:absname("\\\\foo"),
+ "//foo/bar" = filename:absname("\\\\foo/bar"),
+ "//foo/\bar" = filename:absname("\\\\foo/\bar"),
+ "//foo/bar/baz" = filename:absname("\\\\foo/bar\\baz"),
+ "//foo/bar/baz" = filename:absname("\\\\foo\\bar/baz"),
+
file:set_cwd(Cwd),
ok;
{unix, _} ->
@@ -167,6 +178,23 @@ absname_2(Config) when is_list(Config) ->
[Drive|":/"]),
"a:/erlang" = filename:absname("a:erlang", [Drive|":/"]),
+ "//foo" = filename:absname("foo","//"),
+ "//foo/bar" = filename:absname("foo/bar", "//"),
+ "//foo/bar" = filename:absname("bar", "//foo"),
+ "//bar" = filename:absname("/bar", "//foo"),
+ "//foo/bar/baz" = filename:absname("bar/baz", "//foo"),
+ "//bar/baz" = filename:absname("//bar/baz", "//foo"),
+ "//\bar" = filename:absname("/\bar", "//foo"),
+ "//foo" = filename:absname("foo","\\\\"),
+ "//foo/bar" = filename:absname("foo/bar", "\\\\"),
+ "//foo/bar" = filename:absname("bar", "\\\\foo"),
+ "//bar" = filename:absname("/bar", "\\\\foo"),
+ "//foo/bar/baz" = filename:absname("bar/baz", "\\\\foo"),
+ "//bar/baz" = filename:absname("\\\\bar/baz", "\\\\foo"),
+ "//\bar" = filename:absname("/\bar", "\\\\foo"),
+ "//bar/baz" = filename:absname("\\\\bar/baz", "//foo"),
+ "//bar/baz" = filename:absname("//bar/baz", "\\\\foo"),
+
ok;
_ ->
"/usr/foo" = filename:absname(foo, "/usr"),
@@ -244,6 +272,18 @@ dirname(Config) when is_list(Config) ->
"A:usr" = filename:dirname("A:usr/foo.erl"),
"/usr" = filename:dirname("\\usr\\foo.erl"),
"/" = filename:dirname("\\usr"),
+ "//foo/bar" = filename:dirname("//foo/bar/baz.erl"),
+ "//foo/\bar" = filename:dirname("//foo/\bar/baz.erl"),
+ "//foo/bar" = filename:dirname("//foo\\bar/baz.erl"),
+ "//foo/bar" = filename:dirname("\\\\foo/bar/baz.erl"),
+ "//foo/\bar" = filename:dirname("\\\\foo/\bar/baz.erl"),
+ "//foo/bar" = filename:dirname("\\\\foo\\bar/baz.erl"),
+ "//foo" = filename:dirname("//foo/baz.erl"),
+ "//foo" = filename:dirname("//foo/\baz.erl"),
+ "//foo" = filename:dirname("//foo\\baz.erl"),
+ "//foo" = filename:dirname("\\\\foo/baz.erl"),
+ "//foo" = filename:dirname("\\\\foo/\baz.erl"),
+ "//foo" = filename:dirname("\\\\foo\\baz.erl"),
"A:" = filename:dirname("A:");
_ -> true
end,
@@ -289,7 +329,6 @@ join(Config) when is_list(Config) ->
%% join/1 and join/2 (OTP-12158) by using help function
%% filename_join/2.
"/" = filename:join(["/"]),
- "/" = filename:join(["//"]),
"usr/foo.erl" = filename_join("usr","foo.erl"),
"/src/foo.erl" = filename_join(usr, "/src/foo.erl"),
"/src/foo.erl" = filename_join("/src/",'foo.erl'),
@@ -301,7 +340,6 @@ join(Config) when is_list(Config) ->
"a/b/c/d/e/f/g" = filename_join("a//b/c/", "d//e/f/g"),
"a/b/c/d/e/f/g" = filename_join("a//b/c", "d//e/f/g"),
"/d/e/f/g" = filename_join("a//b/c", "/d//e/f/g"),
- "/d/e/f/g" = filename:join("a//b/c", "//d//e/f/g"),
"foo/bar" = filename_join([$f,$o,$o,$/,[]], "bar"),
@@ -332,6 +370,7 @@ join(Config) when is_list(Config) ->
case os:type() of
{win32, _} ->
+ "//" = filename:join(["//"]),
"d:/" = filename:join(["D:/"]),
"d:/" = filename:join(["D:\\"]),
"d:/abc" = filename_join("D:/", "abc"),
@@ -345,8 +384,35 @@ join(Config) when is_list(Config) ->
"c:/usr/foo.erl" = filename:join(["A:","C:/usr","foo.erl"]),
"c:usr/foo.erl" = filename:join(["A:","C:usr","foo.erl"]),
"d:/foo" = filename:join([$D, $:, $/, []], "foo"),
+ "//" = filename:join("\\\\", ""),
+ "//foo" = filename:join("\\\\", "foo"),
+ "//foo/bar" = filename:join("\\\\", "foo\\\\bar"),
+ "//foo/bar/baz" = filename:join("\\\\foo", "bar\\\\baz"),
+ "//foo/bar/baz" = filename:join("\\\\foo", "bar\\baz"),
+ "//foo/bar/baz" = filename:join("\\\\foo\\bar", baz),
+ "//foo/\bar/baz" = filename:join("\\\\foo/\bar", baz),
+ "//foo/bar/baz" = filename:join("\\\\foo/bar", baz),
+ "//bar/baz" = filename:join("\\\\foo", "\\\\bar\\baz"),
+ "//bar/baz" = filename:join("\\\\foo", "//bar\\baz"),
+ "//bar/baz" = filename:join("\\\\foo", "//bar/baz"),
+ "//bar/baz" = filename:join("\\\\foo", "\\\\bar/baz"),
+ "//d/e/f/g" = filename:join("a//b/c", "//d//e/f/g"),
+ "//" = filename:join("//", ""),
+ "//foo" = filename:join("//", "foo"),
+ "//foo/bar" = filename:join("//", "foo\\\\bar"),
+ "//foo/bar/baz" = filename:join("//foo", "bar\\\\baz"),
+ "//foo/bar/baz" = filename:join("//foo", "bar\\baz"),
+ "//foo/bar/baz" = filename:join("//foo\\bar", baz),
+ "//foo/\bar/baz" = filename:join("//foo/\bar", baz),
+ "//foo/bar/baz" = filename:join("//foo/bar", baz),
+ "//bar/baz" = filename:join("//foo", "\\\\bar\\baz"),
+ "//bar/baz" = filename:join("//foo", "//bar\\baz"),
+ "//bar/baz" = filename:join("//foo", "//bar/baz"),
+ "//bar/baz" = filename:join("//foo", "\\\\bar/baz"),
ok;
_ ->
+ "/" = filename:join(["//"]),
+ "/d/e/f/g" = filename:join("a//b/c", "//d//e/f/g"),
ok
end.
@@ -402,6 +468,16 @@ split(Config) when is_list(Config) ->
filename:split("a:\\msdev\\include"),
["a:","msdev","include"] =
filename:split("a:msdev\\include"),
+ ["//","foo"] =
+ filename:split("\\\\foo"),
+ ["//","foo"] =
+ filename:split("//foo"),
+ ["//","foo","bar"] =
+ filename:split("\\\\foo\\\\bar"),
+ ["//","foo","baz"] =
+ filename:split("\\\\foo\\baz"),
+ ["//","foo","baz"] =
+ filename:split("//foo\\baz"),
ok;
_ ->
ok
@@ -630,7 +706,6 @@ extension_bin(Config) when is_list(Config) ->
join_bin(Config) when is_list(Config) ->
<<"/">> = filename:join([<<"/">>]),
- <<"/">> = filename:join([<<"//">>]),
<<"usr/foo.erl">> = filename:join(<<"usr">>,<<"foo.erl">>),
<<"/src/foo.erl">> = filename:join(usr, <<"/src/foo.erl">>),
<<"/src/foo.erl">> = filename:join([<<"/src/">>,'foo.erl']),
@@ -642,7 +717,6 @@ join_bin(Config) when is_list(Config) ->
<<"a/b/c/d/e/f/g">> = filename:join([<<"a//b/c/">>, <<"d//e/f/g">>]),
<<"a/b/c/d/e/f/g">> = filename:join([<<"a//b/c">>, <<"d//e/f/g">>]),
<<"/d/e/f/g">> = filename:join([<<"a//b/c">>, <<"/d//e/f/g">>]),
- <<"/d/e/f/g">> = filename:join([<<"a//b/c">>, <<"//d//e/f/g">>]),
<<"foo/bar">> = filename:join([$f,$o,$o,$/,[]], <<"bar">>),
@@ -695,6 +769,7 @@ join_bin(Config) when is_list(Config) ->
case os:type() of
{win32, _} ->
+ <<"//">> = filename:join([<<"//">>]),
<<"d:/">> = filename:join([<<"D:/">>]),
<<"d:/">> = filename:join([<<"D:\\">>]),
<<"d:/abc">> = filename:join([<<"D:/">>, <<"abc">>]),
@@ -708,8 +783,35 @@ join_bin(Config) when is_list(Config) ->
<<"c:/usr/foo.erl">> = filename:join([<<"A:">>,<<"C:/usr">>,<<"foo.erl">>]),
<<"c:usr/foo.erl">> = filename:join([<<"A:">>,<<"C:usr">>,<<"foo.erl">>]),
<<"d:/foo">> = filename:join([$D, $:, $/, []], <<"foo">>),
+ <<"//">> = filename:join(<<"\\\\">>, <<"">>),
+ <<"//foo">> = filename:join(<<"\\\\">>, <<"foo">>),
+ <<"//foo/bar">> = filename:join(<<"\\\\">>, <<"foo\\\\bar">>),
+ <<"//foo/bar/baz">> = filename:join(<<"\\\\foo">>, <<"bar\\\\baz">>),
+ <<"//bar/baz">> = filename:join(<<"\\\\foo">>, <<"\\\\bar\\baz">>),
+ <<"//foo/bar/baz">> = filename:join(<<"\\\\foo\\bar">>, baz),
+ <<"//foo/\bar/baz">> = filename:join(<<"\\\\foo/\bar">>, baz),
+ <<"//foo/bar/baz">> = filename:join(<<"\\\\foo/bar">>, baz),
+ <<"//bar/baz">> = filename:join(<<"\\\\foo">>, <<"\\\\bar\\baz">>),
+ <<"//bar/baz">> = filename:join(<<"\\\\foo">>, <<"//bar\\baz">>),
+ <<"//bar/baz">> = filename:join(<<"\\\\foo">>, <<"//bar/baz">>),
+ <<"//bar/baz">> = filename:join(<<"\\\\foo">>, <<"\\\\bar/baz">>),
+ <<"//d/e/f/g">> = filename:join([<<"a//b/c">>, <<"//d//e/f/g">>]),
+ <<"//">> = filename:join(<<"//">>, <<"">>),
+ <<"//foo">> = filename:join(<<"//">>, <<"foo">>),
+ <<"//foo/bar">> = filename:join(<<"//">>, <<"foo\\\\bar">>),
+ <<"//foo/bar/baz">> = filename:join(<<"//foo">>, <<"bar\\\\baz">>),
+ <<"//bar/baz">> = filename:join(<<"//foo">>, <<"\\\\bar\\baz">>),
+ <<"//foo/bar/baz">> = filename:join(<<"//foo\\bar">>, baz),
+ <<"//foo/\bar/baz">> = filename:join(<<"//foo/\bar">>, baz),
+ <<"//foo/bar/baz">> = filename:join(<<"//foo/bar">>, baz),
+ <<"//bar/baz">> = filename:join(<<"//foo">>, <<"\\\\bar\\baz">>),
+ <<"//bar/baz">> = filename:join(<<"//foo">>, <<"//bar\\baz">>),
+ <<"//bar/baz">> = filename:join(<<"//foo">>, <<"//bar/baz">>),
+ <<"//bar/baz">> = filename:join(<<"//foo">>, <<"\\\\bar/baz">>),
ok;
_ ->
+ <<"/">> = filename:join([<<"//">>]),
+ <<"/d/e/f/g">> = filename:join([<<"a//b/c">>, <<"//d//e/f/g">>]),
ok
end.
@@ -756,6 +858,16 @@ split_bin(Config) when is_list(Config) ->
filename:split(<<"a:\\msdev\\include">>),
[<<"a:">>,<<"msdev">>,<<"include">>] =
filename:split(<<"a:msdev\\include">>),
+ [<<"//">>,<<"foo">>] =
+ filename:split(<<"\\\\foo">>),
+ [<<"//">>,<<"foo">>] =
+ filename:split(<<"//foo">>),
+ [<<"//">>,<<"foo">>,<<"bar">>] =
+ filename:split(<<"\\\\foo\\\\bar">>),
+ [<<"//">>,<<"foo">>,<<"baz">>] =
+ filename:split(<<"\\\\foo\\baz">>),
+ [<<"//">>,<<"foo">>,<<"baz">>] =
+ filename:split(<<"//foo\\baz">>),
ok;
_ ->
ok
diff --git a/lib/stdlib/test/gen_fsm_SUITE.erl b/lib/stdlib/test/gen_fsm_SUITE.erl
index 86cf58566b..41ee3246f5 100644
--- a/lib/stdlib/test/gen_fsm_SUITE.erl
+++ b/lib/stdlib/test/gen_fsm_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -389,7 +389,7 @@ stop10(_Config) ->
Dir = filename:dirname(code:which(?MODULE)),
rpc:call(Node,code,add_path,[Dir]),
{ok, Pid} = rpc:call(Node,gen_fsm,start,[{global,to_stop},?MODULE,[],[]]),
- global:sync(),
+ ok = global:sync(),
ok = gen_fsm:stop({global,to_stop}),
false = rpc:call(Node,erlang,is_process_alive,[Pid]),
{'EXIT',noproc} = (catch gen_fsm:stop({global,to_stop})),
@@ -1005,7 +1005,7 @@ undef_in_terminate(Config) when is_list(Config) ->
State = {undef_in_terminate, {?MODULE, terminate}},
{ok, FSM} = gen_fsm:start(?MODULE, {state_data, State}, []),
try
- gen_fsm:stop(FSM),
+ ok = gen_fsm:stop(FSM),
ct:fail(failed)
catch
exit:{undef, [{?MODULE, terminate, _, _}|_]} ->
@@ -1201,7 +1201,7 @@ timeout({timeout,Ref,{timeout,Time}}, {From,Ref}) ->
Cref = gen_fsm:start_timer(Time, cancel),
Time4 = Time*4,
receive after Time4 -> ok end,
- gen_fsm:cancel_timer(Cref),
+ _= gen_fsm:cancel_timer(Cref),
{next_state, timeout, {From,Ref2}};
timeout({timeout,Ref2,ok},{From,Ref2}) ->
gen_fsm:reply(From, ok),
diff --git a/lib/stdlib/test/gen_server_SUITE.erl b/lib/stdlib/test/gen_server_SUITE.erl
index 2e9dc4d4fb..e29195e895 100644
--- a/lib/stdlib/test/gen_server_SUITE.erl
+++ b/lib/stdlib/test/gen_server_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
-export([start/1, crash/1, call/1, cast/1, cast_fast/1,
- info/1, abcast/1, multicall/1, multicall_down/1,
+ continue/1, info/1, abcast/1, multicall/1, multicall_down/1,
call_remote1/1, call_remote2/1, call_remote3/1,
call_remote_n1/1, call_remote_n2/1, call_remote_n3/1, spec_init/1,
spec_init_local_registered_parent/1,
@@ -37,7 +37,8 @@
get_state/1, replace_state/1, call_with_huge_message_queue/1,
undef_handle_call/1, undef_handle_cast/1, undef_handle_info/1,
undef_init/1, undef_code_change/1, undef_terminate1/1,
- undef_terminate2/1, undef_in_terminate/1, undef_in_handle_info/1
+ undef_terminate2/1, undef_in_terminate/1, undef_in_handle_info/1,
+ undef_handle_continue/1
]).
-export([stop1/1, stop2/1, stop3/1, stop4/1, stop5/1, stop6/1, stop7/1,
@@ -52,7 +53,7 @@
%% The gen_server behaviour
--export([init/1, handle_call/3, handle_cast/2,
+-export([init/1, handle_call/3, handle_cast/2, handle_continue/2,
handle_info/2, code_change/3, terminate/2, format_status/2]).
suite() ->
@@ -61,7 +62,7 @@ suite() ->
all() ->
[start, {group,stop}, crash, call, cast, cast_fast, info, abcast,
- multicall, multicall_down, call_remote1, call_remote2,
+ continue, multicall, multicall_down, call_remote1, call_remote2,
call_remote3, call_remote_n1, call_remote_n2,
call_remote_n3, spec_init,
spec_init_local_registered_parent,
@@ -76,7 +77,7 @@ groups() ->
[{stop, [],
[stop1, stop2, stop3, stop4, stop5, stop6, stop7, stop8, stop9, stop10]},
{undef_callbacks, [],
- [undef_handle_call, undef_handle_cast, undef_handle_info,
+ [undef_handle_call, undef_handle_cast, undef_handle_info, undef_handle_continue,
undef_init, undef_code_change, undef_terminate1, undef_terminate2]}].
@@ -346,7 +347,7 @@ stop10(_Config) ->
Dir = filename:dirname(code:which(?MODULE)),
rpc:call(Node,code,add_path,[Dir]),
{ok, Pid} = rpc:call(Node,gen_server,start,[{global,to_stop},?MODULE,[],[]]),
- global:sync(),
+ ok = global:sync(),
ok = gen_server:stop({global,to_stop}),
false = rpc:call(Node,erlang,is_process_alive,[Pid]),
{'EXIT',noproc} = (catch gen_server:stop({global,to_stop})),
@@ -458,6 +459,47 @@ call(Config) when is_list(Config) ->
ok.
%% --------------------------------------
+%% Test handle_continue.
+%% --------------------------------------
+
+continue(Config) when is_list(Config) ->
+ {ok, Pid} = gen_server:start_link(gen_server_SUITE, {continue, self()}, []),
+ [{Pid, continue}, {Pid, after_continue}] = read_replies(Pid),
+
+ gen_server:call(Pid, {continue_reply, self()}),
+ [{Pid, continue}, {Pid, after_continue}] = read_replies(Pid),
+
+ gen_server:call(Pid, {continue_noreply, self()}),
+ [{Pid, continue}, {Pid, after_continue}] = read_replies(Pid),
+
+ gen_server:cast(Pid, {continue_noreply, self()}),
+ [{Pid, continue}, {Pid, after_continue}] = read_replies(Pid),
+
+ Pid ! {continue_noreply, self()},
+ [{Pid, continue}, {Pid, after_continue}] = read_replies(Pid),
+
+ Pid ! {continue_continue, self()},
+ [{Pid, before_continue}, {Pid, continue}, {Pid, after_continue}] = read_replies(Pid),
+
+ Ref = monitor(process, Pid),
+ Pid ! continue_stop,
+ verify_down_reason(Ref, Pid, normal).
+
+read_replies(Pid) ->
+ receive
+ {Pid, ack} -> read_replies()
+ after
+ 1000 -> ct:fail({continue, ack})
+ end.
+
+read_replies() ->
+ receive
+ Msg -> [Msg | read_replies()]
+ after
+ 0 -> []
+ end.
+
+%% --------------------------------------
%% Test call to nonexisting processes on remote nodes
%% --------------------------------------
@@ -467,7 +509,7 @@ start_node(Name) ->
%% After starting a slave, it takes a little while until global knows
%% about it, even if nodes() includes it, so we make sure that global
%% knows about it before registering something on all nodes.
- global:sync(),
+ ok = global:sync(),
N.
call_remote1(Config) when is_list(Config) ->
@@ -605,7 +647,7 @@ cast_fast(Config) when is_list(Config) ->
cast_fast_messup() ->
%% Register a false node: hopp@hostname
unregister(erl_epmd),
- erl_epmd:start_link(),
+ {ok, _} = erl_epmd:start_link(),
{ok,S} = gen_tcp:listen(0, []),
{ok,P} = inet:port(S),
{ok,_Creation} = erl_epmd:register_node(hopp, P),
@@ -1309,7 +1351,7 @@ do_call_with_huge_message_queue() ->
{Time,ok} = tc(fun() -> calls(10000, Pid) end),
- [self() ! {msg,N} || N <- lists:seq(1, 500000)],
+ _ = [self() ! {msg,N} || N <- lists:seq(1, 500000)],
erlang:garbage_collect(),
{NewTime,ok} = tc(fun() -> calls(10000, Pid) end),
io:format("Time for empty message queue: ~p", [Time]),
@@ -1346,7 +1388,7 @@ echo_loop() ->
%% Test the default implementation of terminate if the callback module
%% does not export it
undef_terminate1(Config) when is_list(Config) ->
- {ok, Server} = gen_server:start(oc_server, [], []),
+ {ok, Server} = oc_server:start(),
MRef = monitor(process, Server),
ok = gen_server:stop(Server),
ok = verify_down_reason(MRef, Server, normal).
@@ -1354,7 +1396,7 @@ undef_terminate1(Config) when is_list(Config) ->
%% Test the default implementation of terminate if the callback module
%% does not export it
undef_terminate2(Config) when is_list(Config) ->
- {ok, Server} = gen_server:start(oc_server, [], []),
+ {ok, Server} = oc_server:start(),
MRef = monitor(process, Server),
ok = gen_server:stop(Server, {error, test}, infinity),
ok = verify_down_reason(MRef, Server, {error, test}).
@@ -1377,7 +1419,7 @@ undef_init(_Config) ->
%% The upgrade should fail if code_change is expected in the callback module
%% but not exported, but the server should continue with the old code
undef_code_change(Config) when is_list(Config) ->
- {ok, Server} = gen_server:start(oc_server, [], []),
+ {ok, Server} = oc_server:start(),
{error, {'EXIT', {undef, [{oc_server, code_change, [_, _, _], _}|_]}}}
= fake_upgrade(Server, ?MODULE),
true = is_process_alive(Server).
@@ -1385,7 +1427,7 @@ undef_code_change(Config) when is_list(Config) ->
%% The server should crash if the handle_call callback is
%% not exported in the callback module
undef_handle_call(_Config) ->
- {ok, Server} = gen_server:start(oc_server, [], []),
+ {ok, Server} = oc_server:start(),
try
gen_server:call(Server, call_msg),
ct:fail(should_crash)
@@ -1397,17 +1439,25 @@ undef_handle_call(_Config) ->
%% The server should crash if the handle_cast callback is
%% not exported in the callback module
undef_handle_cast(_Config) ->
- {ok, Server} = gen_server:start(oc_server, [], []),
+ {ok, Server} = oc_server:start(),
MRef = monitor(process, Server),
gen_server:cast(Server, cast_msg),
verify_undef_down(MRef, Server, oc_server, handle_cast),
ok.
+%% The server should crash if the handle_continue callback is
+%% not exported in the callback module
+undef_handle_continue(_Config) ->
+ {ok, Server} = oc_server:start(continue),
+ MRef = monitor(process, Server),
+ verify_undef_down(MRef, Server, oc_server, handle_continue),
+ ok.
+
%% The server should log but not crash if the handle_info callback is
%% calling an undefined function
undef_handle_info(Config) when is_list(Config) ->
error_logger_forwarder:register(),
- {ok, Server} = gen_server:start(oc_server, [], []),
+ {ok, Server} = oc_server:start(),
Server ! hej,
wait_until_processed(Server, hej, 10),
true = is_process_alive(Server),
@@ -1426,7 +1476,7 @@ undef_in_terminate(Config) when is_list(Config) ->
State = {undef_in_terminate, {oc_server, terminate}},
{ok, Server} = gen_server:start(?MODULE, {state, State}, []),
try
- gen_server:stop(Server),
+ ok = gen_server:stop(Server),
ct:fail(failed)
catch
exit:{undef, [{oc_server, terminate, [], _}|_]} ->
@@ -1570,8 +1620,11 @@ init(hibernate) ->
init(sleep) ->
ct:sleep(1000),
{ok, []};
+init({continue, Pid}) ->
+ self() ! {after_continue, Pid},
+ {ok, [], {continue, {message, Pid}}};
init({state,State}) ->
- {ok, State}.
+ {ok,State}.
handle_call(started_p, _From, State) ->
io:format("FROZ"),
@@ -1604,6 +1657,12 @@ handle_call(shutdown_reason, _From, _State) ->
handle_call({call_undef_fun, Mod, Fun}, _From, State) ->
Mod:Fun(),
{reply, ok, State};
+handle_call({continue_reply, Pid}, _From, State) ->
+ self() ! {after_continue, Pid},
+ {reply, ok, State, {continue, {message, Pid}}};
+handle_call({continue_noreply, Pid}, From, State) ->
+ self() ! {after_continue, Pid},
+ {noreply, State, {continue, {message, Pid, From}}};
handle_call(stop_shutdown_reason, _From, State) ->
{stop,{shutdown,stop_reason},State}.
@@ -1615,11 +1674,14 @@ handle_cast({From,delayed_cast,T}, _State) ->
handle_cast(hibernate_now, _State) ->
{noreply, [], hibernate};
handle_cast(hibernate_later, _State) ->
- timer:send_after(1000,self(),hibernate_now),
+ {ok, _} = timer:send_after(1000,self(),hibernate_now),
{noreply, []};
handle_cast({call_undef_fun, Mod, Fun}, State) ->
Mod:Fun(),
{noreply, State};
+handle_cast({continue_noreply, Pid}, State) ->
+ self() ! {after_continue, Pid},
+ {noreply, State, {continue, {message, Pid}}};
handle_cast({From, stop}, State) ->
io:format("BAZ"),
{stop, {From,stopped}, State}.
@@ -1657,9 +1719,34 @@ handle_info(continue, From) ->
{noreply, []};
handle_info({From, stop}, State) ->
{stop, {From,stopped_info}, State};
+handle_info({after_continue, Pid}, State) ->
+ Pid ! {self(), after_continue},
+ Pid ! {self(), ack},
+ {noreply, State};
+handle_info({continue_noreply, Pid}, State) ->
+ self() ! {after_continue, Pid},
+ {noreply, State, {continue, {message, Pid}}};
+handle_info({continue_continue, Pid}, State) ->
+ {noreply, State, {continue, {continue, Pid}}};
+handle_info(continue_stop, State) ->
+ {noreply, State, {continue, stop}};
handle_info(_Info, State) ->
{noreply, State}.
+handle_continue({continue, Pid}, State) ->
+ Pid ! {self(), before_continue},
+ self() ! {after_continue, Pid},
+ {noreply, State, {continue, {message, Pid}}};
+handle_continue(stop, State) ->
+ {stop, normal, State};
+handle_continue({message, Pid}, State) ->
+ Pid ! {self(), continue},
+ {noreply, State};
+handle_continue({message, Pid, From}, State) ->
+ Pid ! {self(), continue},
+ gen_server:reply(From, ok),
+ {noreply, State}.
+
code_change(_OldVsn,
{new, {undef_in_code_change, {Mod, Fun}}} = State,
_Extra) ->
diff --git a/lib/stdlib/test/gen_server_SUITE_data/oc_server.erl b/lib/stdlib/test/gen_server_SUITE_data/oc_server.erl
index 4ba37987f3..7b92a49bf6 100644
--- a/lib/stdlib/test/gen_server_SUITE_data/oc_server.erl
+++ b/lib/stdlib/test/gen_server_SUITE_data/oc_server.erl
@@ -22,7 +22,7 @@
-behaviour(gen_server).
%% API
--export([start/0]).
+-export([start/0, start/1]).
%% gen_server callbacks
-export([init/1]).
@@ -30,8 +30,12 @@
-record(state, {}).
start() ->
- gen_server:start({local, ?MODULE}, ?MODULE, [], []).
+ gen_server:start(?MODULE, ok, []).
-init([]) ->
- {ok, #state{}}.
+start(continue) ->
+ gen_server:start(?MODULE, continue, []).
+init(ok) ->
+ {ok, #state{}};
+init(continue) ->
+ {ok, #state{}, {continue, continue}}.
diff --git a/lib/stdlib/test/gen_statem_SUITE.erl b/lib/stdlib/test/gen_statem_SUITE.erl
index 5b9daecfd3..053233df9b 100644
--- a/lib/stdlib/test/gen_statem_SUITE.erl
+++ b/lib/stdlib/test/gen_statem_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2016-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2016-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
-include_lib("common_test/include/ct.hrl").
--compile(export_all).
+-compile([export_all, nowarn_export_all]).
-behaviour(gen_statem).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -60,7 +60,8 @@ tcs(start) ->
tcs(stop) ->
[stop1, stop2, stop3, stop4, stop5, stop6, stop7, stop8, stop9, stop10];
tcs(abnormal) ->
- [abnormal1, abnormal1clean, abnormal1dirty, abnormal2];
+ [abnormal1, abnormal1clean, abnormal1dirty,
+ abnormal2, abnormal3, abnormal4];
tcs(sys) ->
[sys1, call_format_status,
error_format_status, terminate_crash_format,
@@ -524,6 +525,43 @@ abnormal2(Config) ->
process_flag(trap_exit, OldFl),
ok = verify_empty_msgq().
+%% Check that bad return actions makes the stm crash. Note that we must
+%% trap exit since we must link to get the real bad_return_ error
+abnormal3(Config) ->
+ OldFl = process_flag(trap_exit, true),
+ {ok,Pid} = gen_statem:start_link(?MODULE, start_arg(Config, []), []),
+
+ %% bad return value in the gen_statem loop
+ {{{bad_action_from_state_function,badaction},_},_} =
+ ?EXPECT_FAILURE(gen_statem:call(Pid, badaction), Reason),
+ receive
+ {'EXIT',Pid,{{bad_action_from_state_function,badaction},_}} -> ok
+ after 5000 ->
+ ct:fail(gen_statem_did_not_die)
+ end,
+
+ process_flag(trap_exit, OldFl),
+ ok = verify_empty_msgq().
+
+%% Check that bad timeout actions makes the stm crash. Note that we must
+%% trap exit since we must link to get the real bad_return_ error
+abnormal4(Config) ->
+ OldFl = process_flag(trap_exit, true),
+ {ok,Pid} = gen_statem:start_link(?MODULE, start_arg(Config, []), []),
+
+ %% bad return value in the gen_statem loop
+ BadTimeout = {badtimeout,4711,ouch},
+ {{{bad_action_from_state_function,BadTimeout},_},_} =
+ ?EXPECT_FAILURE(gen_statem:call(Pid, BadTimeout), Reason),
+ receive
+ {'EXIT',Pid,{{bad_action_from_state_function,BadTimeout},_}} -> ok
+ after 5000 ->
+ ct:fail(gen_statem_did_not_die)
+ end,
+
+ process_flag(trap_exit, OldFl),
+ ok = verify_empty_msgq().
+
shutdown(Config) ->
process_flag(trap_exit, true),
@@ -832,9 +870,14 @@ event_types(_Config) ->
%% Abusing the internal format of From...
#{init =>
fun () ->
- {ok, start, undefined}
+ {ok, start1, undefined,
+ [{next_event,internal,0}]}
end,
- start =>
+ start1 =>
+ fun (internal, 0, undefined) ->
+ {next_state, start2, undefined}
+ end,
+ start2 =>
fun ({call,_} = Call, Req, undefined) ->
{next_state, state1, undefined,
[{next_event,internal,1},
@@ -1801,10 +1844,12 @@ idle(cast, {connect,Pid}, Data) ->
idle({call,From}, connect, Data) ->
gen_statem:reply(From, accept),
{next_state,wfor_conf,Data,infinity}; % NoOp timeout just to test API
-idle(cast, badreturn, _Data) ->
- badreturn;
idle({call,_From}, badreturn, _Data) ->
badreturn;
+idle({call,_From}, badaction, Data) ->
+ {keep_state, Data, [badaction]};
+idle({call,_From}, {badtimeout,_,_} = BadTimeout, Data) ->
+ {keep_state, Data, BadTimeout};
idle({call,From}, {delayed_answer,T}, Data) ->
receive
after T ->
@@ -2040,9 +2085,9 @@ handle_event(Type, Event, State, Data) ->
Result ->
wrap_result(Result)
catch
- throw:Result ->
+ throw:Result:Stacktrace ->
erlang:raise(
- throw, wrap_result(Result), erlang:get_stacktrace())
+ throw, wrap_result(Result), Stacktrace)
end.
unwrap_state([State]) ->
diff --git a/lib/stdlib/test/id_transform_SUITE.erl b/lib/stdlib/test/id_transform_SUITE.erl
index 3d4ae1a189..0addf09461 100644
--- a/lib/stdlib/test/id_transform_SUITE.erl
+++ b/lib/stdlib/test/id_transform_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -61,8 +61,13 @@ id_transform(Config) when is_list(Config) ->
"erl_id_trans.erl"]),
{ok,erl_id_trans,Bin} = compile:file(File,[binary]),
{module,erl_id_trans} = code:load_binary(erl_id_trans, File, Bin),
- ct:timetrap({hours,1}),
- run_in_test_suite().
+ case test_server:is_valgrind() of
+ false ->
+ ct:timetrap({hours,1}),
+ run_in_test_suite();
+ true ->
+ {skip,"Valgrind (too slow)"}
+ end.
run_in_test_suite() ->
SuperDir = filename:dirname(filename:dirname(code:which(?MODULE))),
diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl
index e2c73371cd..f097552e8c 100644
--- a/lib/stdlib/test/io_SUITE.erl
+++ b/lib/stdlib/test/io_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,9 +31,10 @@
otp_10836/1, io_lib_width_too_small/1,
io_with_huge_message_queue/1, format_string/1,
maps/1, coverage/1, otp_14178_unicode_atoms/1, otp_14175/1,
- otp_14285/1, limit_term/1]).
+ otp_14285/1, limit_term/1, otp_14983/1, otp_15103/1, otp_15076/1,
+ otp_15159/1]).
--export([pretty/2]).
+-export([pretty/2, trf/3]).
%%-define(debug, true).
@@ -63,7 +64,7 @@ all() ->
io_lib_print_binary_depth_one, otp_10302, otp_10755, otp_10836,
io_lib_width_too_small, io_with_huge_message_queue,
format_string, maps, coverage, otp_14178_unicode_atoms, otp_14175,
- otp_14285, limit_term].
+ otp_14285, limit_term, otp_14983, otp_15103, otp_15076, otp_15159].
%% Error cases for output.
error_1(Config) when is_list(Config) ->
@@ -714,7 +715,7 @@ p(Term, D) ->
rp(Term, 1, 80, D).
p(Term, Col, Ll, D) ->
- rp(Term, Col, Ll, D, no_fun).
+ rp(Term, Col, Ll, D, none).
rp(Term, Col, Ll, D) ->
rp(Term, Col, Ll, D, fun rfd/2).
@@ -724,6 +725,8 @@ rp(Term, Col, Ll, D) ->
rp(Term, Col, Ll, D, RF) ->
rp(Term, Col, Ll, D, ?MAXCS, RF).
+rp(Term, Col, Ll, D, M, none) ->
+ rp(Term, Col, Ll, D, M, fun(_, _) -> no end);
rp(Term, Col, Ll, D, M, RF) ->
%% io:format("~n~n*** Col = ~p Ll = ~p D = ~p~n~p~n-->~n",
%% [Col, Ll, D, Term]),
@@ -1748,7 +1751,7 @@ printable_range(Suite) when is_list(Suite) ->
PrettyOptions = [{column,1},
{line_length,109},
{depth,30},
- {max_chars,60},
+ {line_max_chars,60},
{record_print_fun,
fun(_,_) -> no end},
{encoding,unicode}],
@@ -1806,7 +1809,7 @@ rpc_call_max(Node, M, F, Args) ->
%% Make sure that a bad specification for a printable range is rejected.
bad_printable_range(Config) when is_list(Config) ->
- Cmd = lists:concat([lib:progname()," +pcunnnnnicode -run erlang halt"]),
+ Cmd = ct:get_progname() ++ " +pcunnnnnicode -run erlang halt",
P = open_port({spawn, Cmd}, [stderr_to_stdout, {line, 200}]),
ok = receive
{P, {data, {eol , "bad range of printable characters" ++ _}}} ->
@@ -1884,7 +1887,7 @@ otp_10302(Suite) when is_list(Suite) ->
pretty(Term, Depth) when is_integer(Depth) ->
Opts = [{column, 1}, {line_length, 20},
- {depth, Depth}, {max_chars, 60},
+ {depth, Depth}, {line_max_chars, 60},
{record_print_fun, fun rfd/2},
{encoding, unicode}],
pretty(Term, Opts);
@@ -1903,29 +1906,61 @@ otp_10836(Suite) when is_list(Suite) ->
%% OTP-10755. The 'l' modifier
otp_10755(Suite) when is_list(Suite) ->
+ %% printing plain ascii characters
S = "string",
"\"string\"" = fmt("~p", [S]),
"[115,116,114,105,110,103]" = fmt("~lp", [S]),
"\"string\"" = fmt("~P", [S, 2]),
"[115|...]" = fmt("~lP", [S, 2]),
- {'EXIT',{badarg,_}} = (catch fmt("~ltp", [S])),
- {'EXIT',{badarg,_}} = (catch fmt("~tlp", [S])),
- {'EXIT',{badarg,_}} = (catch fmt("~ltP", [S])),
- {'EXIT',{badarg,_}} = (catch fmt("~tlP", [S])),
+ %% printing latin1 chars, with and without modifiers
+ T = {[255],list_to_atom([255]),[a,b,c]},
+ "{\"ÿ\",ÿ,[a,b,c]}" = fmt("~p", [T]),
+ "{\"ÿ\",ÿ,[a,b,c]}" = fmt("~tp", [T]),
+ "{[255],ÿ,[a,b,c]}" = fmt("~lp", [T]),
+ "{[255],ÿ,[a,b,c]}" = fmt("~ltp", [T]),
+ "{[255],ÿ,[a,b,c]}" = fmt("~tlp", [T]),
+ "{\"ÿ\",ÿ,...}" = fmt("~P", [T,3]),
+ "{\"ÿ\",ÿ,...}" = fmt("~tP", [T,3]),
+ "{[255],ÿ,...}" = fmt("~lP", [T,3]),
+ "{[255],ÿ,...}" = fmt("~ltP", [T,3]),
+ "{[255],ÿ,...}" = fmt("~tlP", [T,3]),
+ %% printing unicode chars, with and without modifiers
+ U = {[666],list_to_atom([666]),[a,b,c]},
+ "{[666],'\\x{29A}',[a,b,c]}" = fmt("~p", [U]),
+ case io:printable_range() of
+ unicode ->
+ "{\"ʚ\",'ʚ',[a,b,c]}" = fmt("~tp", [U]),
+ "{\"ʚ\",'ʚ',...}" = fmt("~tP", [U,3]);
+ latin1 ->
+ "{[666],'ʚ',[a,b,c]}" = fmt("~tp", [U]),
+ "{[666],'ʚ',...}" = fmt("~tP", [U,3])
+ end,
+ "{[666],'\\x{29A}',[a,b,c]}" = fmt("~lp", [U]),
+ "{[666],'ʚ',[a,b,c]}" = fmt("~ltp", [U]),
+ "{[666],'ʚ',[a,b,c]}" = fmt("~tlp", [U]),
+ "{[666],'\\x{29A}',...}" = fmt("~P", [U,3]),
+ "{[666],'\\x{29A}',...}" = fmt("~lP", [U,3]),
+ "{[666],'ʚ',...}" = fmt("~ltP", [U,3]),
+ "{[666],'ʚ',...}" = fmt("~tlP", [U,3]),
+ %% the compiler should catch uses of ~l with other than pP
Text =
"-module(l_mod).\n"
"-export([t/0]).\n"
"t() ->\n"
" S = \"string\",\n"
- " io:format(\"~ltp\", [S]),\n"
- " io:format(\"~tlp\", [S]),\n"
- " io:format(\"~ltP\", [S, 1]),\n"
- " io:format(\"~tlP\", [S, 1]).\n",
+ " io:format(\"~lw\", [S]),\n"
+ " io:format(\"~lW\", [S, 1]),\n"
+ " io:format(\"~ltw\", [S]),\n"
+ " io:format(\"~tlw\", [S]),\n"
+ " io:format(\"~ltW\", [S, 1]),\n"
+ " io:format(\"~tlW\", [S, 1]).\n",
{ok,l_mod,[{_File,Ws}]} = compile_file("l_mod.erl", Text, Suite),
- ["format string invalid (invalid control ~lt)",
- "format string invalid (invalid control ~tl)",
- "format string invalid (invalid control ~lt)",
- "format string invalid (invalid control ~tl)"] =
+ ["format string invalid (invalid control ~lw)",
+ "format string invalid (invalid control ~lW)",
+ "format string invalid (invalid control ~ltw)",
+ "format string invalid (invalid control ~ltw)",
+ "format string invalid (invalid control ~ltW)",
+ "format string invalid (invalid control ~ltW)"] =
[lists:flatten(M:format_error(E)) || {_L,M,E} <- Ws],
ok.
@@ -2003,6 +2038,7 @@ writes(N, F1) ->
format_string(_Config) ->
%% All but padding is tested by fmt/2.
+ "xxxxxxxsss" = fmt("~10..xs", ["sss"]),
"xxxxxxsssx" = fmt("~10.4.xs", ["sss"]),
"xxxxxxsssx" = fmt("~10.4.*s", [$x, "sss"]),
ok.
@@ -2018,19 +2054,19 @@ maps(_Config) ->
%% in a map with more than one element.
"#{}" = fmt("~w", [#{}]),
- "#{a=>b}" = fmt("~w", [#{a=>b}]),
- re_fmt(<<"#\\{(a=>b|c=>d),[.][.][.]=>[.][.][.]\\}">>,
- "~W", [#{a=>b,c=>d},2]),
- re_fmt(<<"#\\{(a=>b|c=>d|e=>f),[.][.][.]=>[.][.][.],[.][.][.]\\}">>,
- "~W", [#{a=>b,c=>d,e=>f},2]),
+ "#{a => b}" = fmt("~w", [#{a=>b}]),
+ re_fmt(<<"#\\{(a => b),[.][.][.]\\}">>,
+ "~W", [#{a => b,c => d},2]),
+ re_fmt(<<"#\\{(a => b),[.][.][.]\\}">>,
+ "~W", [#{a => b,c => d,e => f},2]),
"#{}" = fmt("~p", [#{}]),
- "#{a => b}" = fmt("~p", [#{a=>b}]),
- "#{...}" = fmt("~P", [#{a=>b},1]),
+ "#{a => b}" = fmt("~p", [#{a => b}]),
+ "#{...}" = fmt("~P", [#{a => b},1]),
re_fmt(<<"#\\{(a => b|c => d),[.][.][.]\\}">>,
- "~P", [#{a=>b,c=>d},2]),
+ "~P", [#{a => b,c => d},2]),
re_fmt(<<"#\\{(a => b|c => d|e => f),[.][.][.]\\}">>,
- "~P", [#{a=>b,c=>d,e=>f},2]),
+ "~P", [#{a => b,c => d,e => f},2]),
List = [{I,I*I} || I <- lists:seq(1, 20)],
Map = maps:from_list(List),
@@ -2138,8 +2174,8 @@ otp_14175(_Config) ->
"#{}" = p(#{}, 1),
"#{...}" = p(#{a => 1}, 1),
"#{#{} => a}" = p(#{#{} => a}, 2),
- "#{a => 1,...}" = p(#{a => 1, b => 2}, 2),
- "#{a => 1,b => 2}" = p(#{a => 1, b => 2}, -1),
+ mt("#{a => 1,...}", p(#{a => 1, b => 2}, 2)),
+ mt("#{a => 1,b => 2}", p(#{a => 1, b => 2}, -1)),
M = #{kaaaaaaaaaaaaaaaaaaa => v1,kbbbbbbbbbbbbbbbbbbb => v2,
kccccccccccccccccccc => v3,kddddddddddddddddddd => v4,
@@ -2382,19 +2418,36 @@ limit_term(_Config) ->
{_, 2} = limt({a,b,c,[d,e]}, 2),
{_, 2} = limt({a,b,c,[d,e]}, 3),
{_, 2} = limt({a,b,c,[d,e]}, 4),
+ T0 = [1|{a,b,c}],
+ {_, 2} = limt(T0, 2),
+ {_, 2} = limt(T0, 3),
+ {_, 2} = limt(T0, 4),
{_, 1} = limt(<<"foo">>, 18),
+ {_, 2} = limt({"",[1,2]}, 3),
+ {_, 2} = limt({"",{1,2}}, 3),
+ true = limt_pp({"123456789012345678901234567890",{1,2}}, 3),
ok = blimt(<<"123456789012345678901234567890">>),
+ true = limt_pp(<<"123456789012345678901234567890">>, 3),
+ {_, 2} = limt({<<"kljlkjsl">>,[1,2,3,4]}, 4),
{_, 1} = limt(<<7:3>>, 2),
{_, 1} = limt(<<7:21>>, 2),
{_, 1} = limt([], 2),
{_, 1} = limt({}, 2),
+ {_, 1} = limt({"", ""}, 4),
{_, 1} = limt(#{}, 2),
- {_, 1} = limt(#{[] => {}}, 2),
+ {_, 2} = limt(#{[] => {}}, 1),
+ {_, 2} = limt(#{[] => {}}, 2),
{_, 1} = limt(#{[] => {}}, 3),
T = #{[] => {},[a] => [b]},
- {_, 1} = limt(T, 2),
- {_, 1} = limt(T, 3),
+ {_, 1} = limt(T, 0),
+ {_, 2} = limt(T, 1),
+ {_, 2} = limt(T, 2),
+ {_, 2} = limt(T, 3),
{_, 1} = limt(T, 4),
+ T2 = #{[] => {},{} => []},
+ {_, 2} = limt(T2, 1),
+ {_, 2} = limt(T2, 2),
+ {_, 1} = limt(T2, 3),
ok.
blimt(Binary) ->
@@ -2428,3 +2481,169 @@ limt(Term, Depth) when is_integer(Depth) ->
form(Term, Depth) ->
lists:flatten(io_lib:format("~W", [Term, Depth])).
+
+limt_pp(Term, Depth) when is_integer(Depth) ->
+ T1 = io_lib:limit_term(Term, Depth),
+ S = pp(Term, Depth),
+ S1 = pp(T1, Depth),
+ S1 =:= S.
+
+pp(Term, Depth) ->
+ lists:flatten(io_lib:format("~P", [Term, Depth])).
+
+otp_14983(_Config) ->
+ trunc_depth(-1, fun trp/3),
+ trunc_depth(10, fun trp/3),
+ trunc_depth(-1, fun trw/3),
+ trunc_depth(10, fun trw/3),
+ trunc_depth_p(-1),
+ trunc_depth_p(10),
+ trunc_string(),
+ ok.
+
+trunc_string() ->
+ "str " = trf("str ", [], 10),
+ "str ..." = trf("str ~s", ["str"], 6),
+ "str str" = trf("str ~s", ["str"], 7),
+ "str ..." = trf("str ~8s", ["str"], 6),
+ Pa = filename:dirname(code:which(?MODULE)),
+ {ok, UNode} = test_server:start_node(printable_range_unicode, slave,
+ [{args, " +pc unicode -pa " ++ Pa}]),
+ U = "кирилли́ческий атом",
+ UFun = fun(Format, Args, CharsLimit) ->
+ rpc:call(UNode,
+ ?MODULE, trf, [Format, Args, CharsLimit])
+ end,
+ "str кир" = UFun("str ~3ts", [U], 7),
+ "str ..." = UFun("str ~3ts", [U], 6),
+ "str ..." = UFun("str ~30ts", [U], 6),
+ "str кир..." = UFun("str ~30ts", [U], 10),
+ "str кирилл..." = UFun("str ~30ts", [U], 13),
+ "str кирилли́..." = UFun("str ~30ts", [U], 14),
+ "str кирилли́ч..." = UFun("str ~30ts", [U], 15),
+ "\"кирилли́ческ\"..." = UFun("~tp", [U], 13),
+ BU = <<"кирилли́ческий атом"/utf8>>,
+ "<<\"кирилли́\"/utf8...>>" = UFun("~tp", [BU], 20),
+ "<<\"кирилли́\"/utf8...>>" = UFun("~tp", [BU], 21),
+ "<<\"кирилли́ческ\"/utf8...>>" = UFun("~tp", [BU], 22),
+ test_server:stop_node(UNode).
+
+trunc_depth(D, Fun) ->
+ "..." = Fun("", D, 0),
+ "[]" = Fun("", D, 1),
+
+ "#{}" = Fun(#{}, D, 1),
+ "#{a => 1}" = Fun(#{a => 1}, D, 7),
+ "#{...}" = Fun(#{a => 1}, D, 5),
+ "#{a => 1}" = Fun(#{a => 1}, D, 6),
+ A = lists:seq(1, 1000),
+ M = #{A => A, {A,A} => {A,A}},
+ "#{...}" = Fun(M, D, 6),
+ "#{{...} => {...},...}" = Fun(M, D, 7),
+ "#{{[...],...} => {[...],...},...}" = Fun(M, D, 22),
+ "#{{[...],...} => {[...],...},[...] => [...]}" = Fun(M, D, 31),
+ "#{{[...],...} => {[...],...},[...] => [...]}" = Fun(M, D, 33),
+ "#{{[1|...],[...]} => {[1|...],[...]},[1,2|...] => [...]}" =
+ Fun(M, D, 50),
+
+ "..." = Fun({c, 1, 2}, D, 0),
+ "{...}" = Fun({c, 1, 2}, D, 1),
+
+ "..." = Fun({}, D, 0),
+ "{}" = Fun({}, D, 1),
+ T = {A, A, A},
+ "{...}" = Fun(T, D, 5),
+ "{[...],...}" = Fun(T, D, 6),
+ "{[1|...],[...],...}" = Fun(T, D, 12),
+ "{[1,2|...],[1|...],...}" = Fun(T, D, 20),
+ "{[1,2|...],[1|...],[...]}" = Fun(T, D, 21),
+ "{[1,2,3|...],[1,2|...],[1|...]}" = Fun(T, D, 28),
+
+ "{[1],[1,2|...]}" = Fun({[1],[1,2,3,4]}, D, 14).
+
+trunc_depth_p(D) ->
+ UOpts = [{record_print_fun, fun rfd/2},
+ {encoding, unicode}],
+ LOpts = [{record_print_fun, fun rfd/2},
+ {encoding, latin1}],
+ trunc_depth_p(D, UOpts),
+ trunc_depth_p(D, LOpts).
+
+trunc_depth_p(D, Opts) ->
+ "[...]" = trp("abcdefg", D, 4, Opts),
+ "\"abc\"..." = trp("abcdefg", D, 5, Opts),
+ "\"abcdef\"..." = trp("abcdefg", D, 8, Opts),
+ "\"abcdefg\"" = trp("abcdefg", D, 9, Opts),
+ "\"abcdefghijkl\"" = trp("abcdefghijkl", D, -1, Opts),
+ AZ = lists:seq($A, $Z),
+ AZb = list_to_binary(AZ),
+ AZbS = "<<\"" ++ AZ ++ "\">>",
+ AZbS = trp(AZb, D, -1),
+ "<<\"ABCDEFGH\"...>>" = trp(AZb, D, 17, Opts), % 4 chars even if D = -1...
+ "<<\"ABCDEFGHIJKL\"...>>" = trp(AZb, D, 18, Opts),
+ B1 = <<"abcdef",0:8>>,
+ "<<\"ab\"...>>" = trp(B1, D, 8, Opts),
+ "<<\"abcdef\"...>>" = trp(B1, D, 14, Opts),
+ "<<97,98,99,100,...>>" = trp(B1, D, 16, Opts),
+ "<<97,98,99,100,101,102,0>>" = trp(B1, D, -1, Opts),
+ B2 = <<AZb/binary,0:8>>,
+ "<<\"AB\"...>>" = trp(B2, D, 8, Opts),
+ "<<\"ABCDEFGH\"...>>" = trp(B2, D, 14, Opts),
+ "<<65,66,67,68,69,70,71,72,0>>" = trp(<<"ABCDEFGH",0:8>>, D, -1, Opts),
+ "<<97,0,107,108,...>>" = trp(<<"a",0:8,"kllkjlksdjfsj">>, D, 20, Opts),
+
+ A = lists:seq(1, 1000),
+ "#c{...}" = trp({c, 1, 2}, D, 6),
+ "#c{...}" = trp({c, 1, 2}, D, 7),
+ "#c{f1 = [...],...}" = trp({c, A, A}, D, 18),
+ "#c{f1 = [1|...],f2 = [...]}" = trp({c, A, A}, D, 19),
+ "#c{f1 = [1,2|...],f2 = [1|...]}" = trp({c, A, A}, D, 31),
+ "#c{f1 = [1,2,3|...],f2 = [1,2|...]}" = trp({c, A, A}, D, 32).
+
+trp(Term, D, T) ->
+ trp(Term, D, T, [{record_print_fun, fun rfd/2}]).
+
+trp(Term, D, T, Opts) ->
+ R = io_lib_pretty:print(Term, [{depth, D},
+ {chars_limit, T}|Opts]),
+ lists:flatten(io_lib:format("~s", [R])).
+
+trw(Term, D, T) ->
+ lists:flatten(io_lib:format("~W", [Term, D], [{chars_limit, T}])).
+
+trf(Format, Args, T) ->
+ trf(Format, Args, T, [{record_print_fun, fun rfd/2}]).
+
+trf(Format, Args, T, Opts) ->
+ lists:flatten(io_lib:format(Format, Args, [{chars_limit, T}|Opts])).
+
+otp_15103(_Config) ->
+ T = lists:duplicate(5, {a,b,c}),
+
+ S1 = io_lib:format("~0p", [T]),
+ "[{a,b,c},{a,b,c},{a,b,c},{a,b,c},{a,b,c}]" = lists:flatten(S1),
+ S2 = io_lib:format("~-0p", [T]),
+ "[{a,b,c},{a,b,c},{a,b,c},{a,b,c},{a,b,c}]" = lists:flatten(S2),
+ S3 = io_lib:format("~1p", [T]),
+ "[{a,\n b,\n c},\n {a,\n b,\n c},\n {a,\n b,\n c},\n {a,\n b,\n"
+ " c},\n {a,\n b,\n c}]" = lists:flatten(S3),
+
+ S4 = io_lib:format("~0P", [T, 5]),
+ "[{a,b,c},{a,b,...},{a,...},{...}|...]" = lists:flatten(S4),
+ S5 = io_lib:format("~1P", [T, 5]),
+ "[{a,\n b,\n c},\n {a,\n b,...},\n {a,...},\n {...}|...]" =
+ lists:flatten(S5),
+ ok.
+
+otp_15159(_Config) ->
+ "[atom]" =
+ lists:flatten(io_lib:format("~p", [[atom]], [{chars_limit,5}])),
+ ok.
+
+otp_15076(_Config) ->
+ {'EXIT', {badarg, _}} = (catch io_lib:format("~c", [a])),
+ L = io_lib:scan_format("~c", [a]),
+ {"~c", [a]} = io_lib:unscan_format(L),
+ {'EXIT', {badarg, _}} = (catch io_lib:build_text(L)),
+ {'EXIT', {badarg, _}} = (catch io_lib:build_text(L, [])),
+ ok.
diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl
index 7c99244b36..837ab4e97e 100644
--- a/lib/stdlib/test/lists_SUITE.erl
+++ b/lib/stdlib/test/lists_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -57,7 +57,7 @@
filter_partition/1,
join/1,
otp_5939/1, otp_6023/1, otp_6606/1, otp_7230/1,
- suffix/1, subtract/1, droplast/1, hof/1]).
+ suffix/1, subtract/1, droplast/1, search/1, hof/1]).
%% Sort randomized lists until stopped.
%%
@@ -121,7 +121,7 @@ groups() ->
{zip, [parallel], [zip_unzip, zip_unzip3, zipwith, zipwith3]},
{misc, [parallel], [reverse, member, dropwhile, takewhile,
filter_partition, suffix, subtract, join,
- hof, droplast]}
+ hof, droplast, search]}
].
init_per_suite(Config) ->
@@ -2615,6 +2615,20 @@ droplast(Config) when is_list(Config) ->
ok.
+%% Test lists:search/2
+search(Config) when is_list(Config) ->
+ F = fun(I) -> I rem 2 =:= 0 end,
+ F2 = fun(A, B) -> A > B end,
+
+ {value, 2} = lists:search(F, [1,2,3,4]),
+ false = lists:search(F, [1,3,5,7]),
+ false = lists:search(F, []),
+
+ %% Error cases.
+ {'EXIT',{function_clause,_}} = (catch lists:search(badfun, [])),
+ {'EXIT',{function_clause,_}} = (catch lists:search(F2, [])),
+ ok.
+
%% Briefly test the common high-order functions to ensure they
%% are covered.
hof(Config) when is_list(Config) ->
diff --git a/lib/stdlib/test/maps_SUITE.erl b/lib/stdlib/test/maps_SUITE.erl
index 42e669a799..6f3cd8bf1b 100644
--- a/lib/stdlib/test/maps_SUITE.erl
+++ b/lib/stdlib/test/maps_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@
-export([t_update_with_3/1, t_update_with_4/1,
t_get_3/1, t_filter_2/1,
t_fold_3/1,t_map_2/1,t_size_1/1,
+ t_iterator_1/1,
t_with_2/1,t_without_2/1]).
%%-define(badmap(V,F,Args), {'EXIT', {{badmap,V}, [{maps,F,Args,_}|_]}}).
@@ -47,6 +48,7 @@ all() ->
[t_update_with_3,t_update_with_4,
t_get_3,t_filter_2,
t_fold_3,t_map_2,t_size_1,
+ t_iterator_1,
t_with_2,t_without_2].
t_update_with_3(Config) when is_list(Config) ->
@@ -106,6 +108,8 @@ t_without_2(_Config) ->
%% error case
?badmap(a,without,[[a,b],a]) = (catch maps:without([a,b],id(a))),
?badmap(a,without,[{a,b},a]) = (catch maps:without({a,b},id(a))),
+ ?badmap({0,<<>>,97},without,[[],{0,<<>>,97}]) = (catch maps:without([], {0,<<>>,97})),
+ ?badmap({0,<<>>,97},without,[[false, -20, -8],{0,<<>>,97}]) = (catch maps:without([false, -20, -8], {0, <<>>, 97})),
?badarg(without,[a,#{}]) = (catch maps:without(a,#{})),
ok.
@@ -118,6 +122,8 @@ t_with_2(_Config) ->
%% error case
?badmap(a,with,[[a,b],a]) = (catch maps:with([a,b],id(a))),
?badmap(a,with,[{a,b},a]) = (catch maps:with({a,b},id(a))),
+ ?badmap({0,<<>>,97},with,[[],{0,<<>>,97}]) = (catch maps:with([], {0,<<>>,97})),
+ ?badmap({0,<<>>,97},with,[[false, -20, -8],{0,<<>>,97}]) = (catch maps:with([false, -20, -8], {0, <<>>, 97})),
?badarg(with,[a,#{}]) = (catch maps:with(a,#{})),
ok.
@@ -127,6 +133,8 @@ t_filter_2(Config) when is_list(Config) ->
Pred2 = fun(K,V) -> is_list(K) andalso (V rem 2) =:= 0 end,
#{a := 2,c := 4} = maps:filter(Pred1,M),
#{"b" := 2,"c" := 4} = maps:filter(Pred2,M),
+ #{a := 2,c := 4} = maps:filter(Pred1,maps:iterator(M)),
+ #{"b" := 2,"c" := 4} = maps:filter(Pred2,maps:iterator(M)),
%% error case
?badmap(a,filter,[_,a]) = (catch maps:filter(fun(_,_) -> ok end,id(a))),
?badarg(filter,[<<>>,#{}]) = (catch maps:filter(id(<<>>),#{})),
@@ -139,6 +147,8 @@ t_fold_3(Config) when is_list(Config) ->
Tot0 = lists:sum(Vs),
Tot1 = maps:fold(fun({k,_},V,A) -> A + V end, 0, M0),
true = Tot0 =:= Tot1,
+ Tot2 = maps:fold(fun({k,_},V,A) -> A + V end, 0, maps:iterator(M0)),
+ true = Tot0 =:= Tot2,
%% error case
?badmap(a,fold,[_,0,a]) = (catch maps:fold(fun(_,_,_) -> ok end,0,id(a))),
@@ -151,12 +161,48 @@ t_map_2(Config) when is_list(Config) ->
#{ {k,1} := 1, {k,200} := 200} = M0,
M1 = maps:map(fun({k,_},V) -> V + 42 end, M0),
#{ {k,1} := 43, {k,200} := 242} = M1,
+ M2 = maps:map(fun({k,_},V) -> V + 42 end, maps:iterator(M0)),
+ #{ {k,1} := 43, {k,200} := 242} = M2,
%% error case
?badmap(a,map,[_,a]) = (catch maps:map(fun(_,_) -> ok end, id(a))),
?badarg(map,[<<>>,#{}]) = (catch maps:map(id(<<>>),#{})),
ok.
+t_iterator_1(Config) when is_list(Config) ->
+
+ %% Small map test
+ M0 = #{ a => 1, b => 2 },
+ I0 = maps:iterator(M0),
+ {K1,V1,I1} = maps:next(I0),
+ {K2,V2,I2} = maps:next(I1),
+ none = maps:next(I2),
+
+ KVList = lists:sort([{K1,V1},{K2,V2}]),
+ KVList = lists:sort(maps:to_list(M0)),
+
+ %% Large map test
+
+ Vs2 = lists:seq(1,200),
+ M2 = maps:from_list([{{k,I},I}||I<-Vs2]),
+ KVList2 = lists:sort(iter_kv(maps:iterator(M2))),
+ KVList2 = lists:sort(maps:to_list(M2)),
+
+ %% Larger map test
+
+ Vs3 = lists:seq(1,10000),
+ M3 = maps:from_list([{{k,I},I}||I<-Vs3]),
+ KVList3 = lists:sort(iter_kv(maps:iterator(M3))),
+ KVList3 = lists:sort(maps:to_list(M3)),
+ ok.
+
+iter_kv(I) ->
+ case maps:next(I) of
+ none ->
+ [];
+ {K,V,NI} ->
+ [{K,V} | iter_kv(NI)]
+ end.
t_size_1(Config) when is_list(Config) ->
0 = maps:size(#{}),
diff --git a/lib/stdlib/test/proc_lib_SUITE.erl b/lib/stdlib/test/proc_lib_SUITE.erl
index 029e6286e4..127b1317e4 100644
--- a/lib/stdlib/test/proc_lib_SUITE.erl
+++ b/lib/stdlib/test/proc_lib_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@
init_per_group/2,end_per_group/2,
crash/1, stacktrace/1, sync_start_nolink/1, sync_start_link/1,
spawn_opt/1, sp1/0, sp2/0, sp3/1, sp4/2, sp5/1, '\x{447}'/0,
- hibernate/1, stop/1, t_format/1]).
+ hibernate/1, stop/1, t_format/1, t_format_arbitrary/1]).
-export([ otp_6345/1, init_dont_hang/1]).
-export([hib_loop/1, awaken/1]).
@@ -51,7 +51,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[crash, stacktrace, {group, sync_start}, spawn_opt, hibernate,
- {group, tickets}, stop, t_format].
+ {group, tickets}, stop, t_format, t_format_arbitrary].
groups() ->
[{tickets, [], [otp_6345, init_dont_hang]},
@@ -78,6 +78,14 @@ end_per_group(_GroupName, Config) ->
%% synchronous, and we want to test that the crash report is ok.
%%-----------------------------------------------------------------
crash(Config) when is_list(Config) ->
+ ok = application:unset_env(kernel, error_logger_format_depth),
+ crash_1(Config),
+ ok = application:set_env(kernel, error_logger_format_depth, 30),
+ crash_1(Config),
+ ok = application:unset_env(kernel, error_logger_format_depth),
+ ok.
+
+crash_1(_Config) ->
error_logger:add_report_handler(?MODULE, self()),
%% Make sure that we don't get a crash report if a process
@@ -438,8 +446,8 @@ init_dont_hang(Config) when is_list(Config) ->
StartLinkRes = proc_lib:start(?MODULE, init_dont_hang_init, [self()], 1000),
StartLinkRes = proc_lib:start(?MODULE, init_dont_hang_init, [self()], 1000, []),
ok
- catch _:Error ->
- io:format("Error ~p /= ~p ~n",[erlang:get_stacktrace(), StartLinkRes]),
+ catch _:Error:Stacktrace ->
+ io:format("Error ~p /= ~p ~n",[Stacktrace, StartLinkRes]),
exit(Error)
end.
@@ -534,24 +542,29 @@ system_terminate(Reason,_Parent,_Deb,_State) ->
t_format(_Config) ->
- error_logger:tty(false),
+ {ok,#{level:=Level}} = logger:get_handler_config(default),
+ logger:set_handler_config(default,level,none),
+ error_logger:add_report_handler(?MODULE, self()),
try
t_format()
after
- error_logger:tty(true)
+ error_logger:delete_report_handler(?MODULE),
+ logger:set_handler_config(default,level,Level)
end,
ok.
t_format() ->
- error_logger:add_report_handler(?MODULE, self()),
- Pid = proc_lib:spawn(fun t_format_looper/0),
+ Pid = proc_lib:spawn(fun '\x{aaa}t_format_looper'/0),
HugeData = gb_sets:from_list(lists:seq(1, 100)),
- Pid ! {die,HugeData},
+ SomeData1 = list_to_atom([246]),
+ SomeData2 = list_to_atom([1024]),
+ Pid ! {SomeData1,SomeData2},
+ Pid ! {die,{HugeData,SomeData1,SomeData2}},
Report = receive
{crash_report, Pid, Report0} -> Report0
end,
- Usz = do_test_format(Report, unlimited),
- Tsz = do_test_format(Report, 20),
+ Usz = do_test_format(Report, latin1, unlimited),
+ Tsz = do_test_format(Report, latin1, 20),
if
Tsz >= Usz ->
@@ -560,21 +573,59 @@ t_format() ->
ok
end,
+ UszU = do_test_format(Report, unicode, unlimited),
+ TszU = do_test_format(Report, unicode, 20),
+
+ if
+ TszU >= UszU ->
+ ct:fail(failed);
+ true ->
+ ok
+ end,
+
+ ok.
+
+t_format_arbitrary(_Config) ->
+ {ok,#{level:=Level}} = logger:get_handler_config(default),
+ logger:set_handler_config(default,level,none),
+ try
+ t_format_arbitrary()
+ after
+ logger:set_handler_config(default,level,Level)
+ end,
ok.
+t_format_arbitrary() ->
+ A = list_to_atom([1024]),
+ do_test_format([fake_report, A], unlimited),
+ do_test_format([fake_report, A], 20),
+
+ do_test_format([fake_report, foo], unlimited),
+ do_test_format([fake_report, foo], 20),
+ do_test_format([fake_report, []], unlimited),
+ do_test_format([fake_report, []], 20).
+
do_test_format(Report, Depth) ->
- io:format("*** Depth = ~p", [Depth]),
- S0 = proc_lib:format(Report, latin1, Depth),
+ do_test_format(Report, latin1, Depth),
+ do_test_format(Report, unicode, Depth).
+
+do_test_format(Report, Encoding, Depth) ->
+ io:format("*** Depth = ~p, Encoding = ~p", [Depth, Encoding]),
+ S0 = proc_lib:format(Report, Encoding, Depth),
S = lists:flatten(S0),
- io:put_chars(S),
+ case Encoding of
+ latin1 -> io:format("~s\n", [S]);
+ _ -> io:format("~ts\n", [S])
+ end,
length(S).
-t_format_looper() ->
+'\x{aaa}t_format_looper'() ->
receive
{die,Data} ->
exit(Data);
- _ ->
- t_format_looper()
+ M ->
+ put(M, M),
+ '\x{aaa}t_format_looper'()
end.
%%-----------------------------------------------------------------
@@ -584,7 +635,7 @@ init(Tester) ->
{ok, Tester}.
handle_event({error_report, _GL, {Pid, crash_report, Report}}, Tester) ->
- io:format("~s\n", [proc_lib:format(Report)]),
+ io:format("~ts\n", [proc_lib:format(Report)]),
Tester ! {crash_report, Pid, Report},
{ok, Tester};
handle_event(_Event, State) ->
diff --git a/lib/stdlib/test/property_test/README b/lib/stdlib/test/property_test/README
new file mode 100644
index 0000000000..57602bf719
--- /dev/null
+++ b/lib/stdlib/test/property_test/README
@@ -0,0 +1,12 @@
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% %%%
+%%% WARNING %%%
+%%% %%%
+%%% This is experimental code which may be changed or removed %%%
+%%% anytime without any warning. %%%
+%%% %%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+The test in this directory are written assuming that the user has a QuickCheck license. They are to be run manually. Some may be possible to be run with other tools, e.g. PropEr.
+
diff --git a/lib/stdlib/test/property_test/uri_string_recompose.erl b/lib/stdlib/test/property_test/uri_string_recompose.erl
new file mode 100644
index 0000000000..39fadf23c2
--- /dev/null
+++ b/lib/stdlib/test/property_test/uri_string_recompose.erl
@@ -0,0 +1,571 @@
+%%
+%% %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(uri_string_recompose).
+
+-compile(export_all).
+
+-proptest(eqc).
+-proptest([triq,proper]).
+
+-ifndef(EQC).
+-ifndef(PROPER).
+-ifndef(TRIQ).
+-define(EQC,true).
+-endif.
+-endif.
+-endif.
+
+-ifdef(EQC).
+-include_lib("eqc/include/eqc.hrl").
+-define(MOD_eqc,eqc).
+
+-else.
+-ifdef(PROPER).
+-include_lib("proper/include/proper.hrl").
+-define(MOD_eqc,proper).
+
+-else.
+-ifdef(TRIQ).
+-define(MOD_eqc,triq).
+-include_lib("triq/include/triq.hrl").
+
+-endif.
+-endif.
+-endif.
+
+
+-define(STRING_REST(MatchStr, Rest), <<MatchStr/utf8, Rest/binary>>).
+
+-define(SCHEME, {scheme, scheme()}).
+-define(USER, {userinfo, unicode()}).
+-define(HOST, {host, host_map()}).
+-define(PORT, {port, port()}).
+-define(PATH_ABE, {path, path_abempty_map()}).
+-define(PATH_ABS, {path, path_absolute_map()}).
+-define(PATH_NOS, {path, path_noscheme_map()}).
+-define(PATH_ROO, {path, path_rootless_map()}).
+-define(PATH_EMP, {path, path_empty_map()}).
+-define(QUERY, {query, query_map()}).
+-define(FRAGMENT, {fragment, fragment_map()}).
+
+%% Non-unicode
+-define(USER_NU, {userinfo, non_unicode()}).
+-define(HOST_NU, {host, host_map_nu()}).
+-define(PATH_ABE_NU, {path, path_abempty_map_nu()}).
+-define(PATH_ABS_NU, {path, path_absolute_map_nu()}).
+-define(PATH_NOS_NU, {path, path_noscheme_map_nu()}).
+-define(PATH_ROO_NU, {path, path_rootless_map_nu()}).
+-define(QUERY_NU, {query, query_map_nu()}).
+-define(FRAGMENT_NU, {fragment, fragment_map_nu()}).
+
+%%%========================================================================
+%%% Properties
+%%%========================================================================
+
+prop_recompose() ->
+ ?FORALL(Map, map_no_unicode(),
+ Map =:= uri_string:parse(uri_string:recompose(Map))).
+
+prop_normalize() ->
+ ?FORALL(Map, map(),
+ uri_string:normalize(Map, [return_map]) =:=
+ uri_string:normalize(uri_string:parse(uri_string:recompose(Map)),
+ [return_map])).
+
+%% Stats
+prop_map_key_length_collect() ->
+ ?FORALL(List, map(),
+ collect(length(maps:keys(List)), true)).
+
+prop_map_collect() ->
+ ?FORALL(List, map(),
+ collect(lists:sort(maps:keys(List)), true)).
+
+prop_scheme_collect() ->
+ ?FORALL(List, scheme(),
+ collect(length(List), true)).
+
+
+%%%========================================================================
+%%% Generators
+%%%========================================================================
+
+map() ->
+ ?LET(Gen, comp_proplist(), proplist_to_map(Gen)).
+
+map_no_unicode() ->
+ ?LET(Gen, comp_proplist_nu(), proplist_to_map(Gen)).
+
+comp_proplist() ->
+ frequency([
+ {2, [?SCHEME,?PATH_ABS]},
+ {2, [?SCHEME,?PATH_ROO]},
+ {2, [?SCHEME,?PATH_EMP]},
+ {2, [?SCHEME,?HOST,?PATH_ABE]},
+ {2, [?SCHEME,?USER,?HOST,?PATH_ABE]},
+ {2, [?SCHEME,?HOST,?PORT,?PATH_ABE]},
+ {2, [?SCHEME,?USER,?HOST,?PORT,?PATH_ABE]},
+
+ {2, [?PATH_ABS]},
+ {2, [?PATH_NOS]},
+ {2, [?PATH_EMP]},
+ {2, [?HOST,?PATH_ABE]},
+ {2, [?USER,?HOST,?PATH_ABE]},
+ {2, [?HOST,?PORT,?PATH_ABE]},
+ {2, [?USER,?HOST,?PORT,?PATH_ABE]},
+
+
+ {2, [?SCHEME,?PATH_ABS,?QUERY]},
+ {2, [?SCHEME,?PATH_ROO,?QUERY]},
+ {2, [?SCHEME,?PATH_EMP,?QUERY]},
+ {2, [?SCHEME,?HOST,?PATH_ABE,?QUERY]},
+ {2, [?SCHEME,?USER,?HOST,?PATH_ABE,?QUERY]},
+ {2, [?SCHEME,?HOST,?PORT,?PATH_ABE,?QUERY]},
+ {2, [?SCHEME,?USER,?HOST,?PORT,?PATH_ABE,?QUERY]},
+
+ {2, [?PATH_ABS,?QUERY]},
+ {2, [?PATH_NOS,?QUERY]},
+ {2, [?PATH_EMP,?QUERY]},
+ {2, [?HOST,?PATH_ABE,?QUERY]},
+ {2, [?USER,?HOST,?PATH_ABE,?QUERY]},
+ {2, [?HOST,?PORT,?PATH_ABE,?QUERY]},
+ {2, [?USER,?HOST,?PORT,?PATH_ABE,?QUERY]},
+
+
+ {2, [?SCHEME,?PATH_ABS,?FRAGMENT]},
+ {2, [?SCHEME,?PATH_ROO,?FRAGMENT]},
+ {2, [?SCHEME,?PATH_EMP,?FRAGMENT]},
+ {2, [?SCHEME,?HOST,?PATH_ABE,?FRAGMENT]},
+ {2, [?SCHEME,?USER,?HOST,?PATH_ABE,?FRAGMENT]},
+ {2, [?SCHEME,?HOST,?PORT,?PATH_ABE,?FRAGMENT]},
+ {2, [?SCHEME,?USER,?HOST,?PORT,?PATH_ABE,?FRAGMENT]},
+
+ {2, [?PATH_ABS,?FRAGMENT]},
+ {2, [?PATH_NOS,?FRAGMENT]},
+ {2, [?PATH_EMP,?FRAGMENT]},
+ {2, [?HOST,?PATH_ABE,?FRAGMENT]},
+ {2, [?USER,?HOST,?PATH_ABE,?FRAGMENT]},
+ {2, [?HOST,?PORT,?PATH_ABE,?FRAGMENT]},
+ {2, [?USER,?HOST,?PORT,?PATH_ABE,?FRAGMENT]},
+
+
+ {2, [?SCHEME,?PATH_ABS,?QUERY,?FRAGMENT]},
+ {2, [?SCHEME,?PATH_ROO,?QUERY,?FRAGMENT]},
+ {2, [?SCHEME,?PATH_EMP,?QUERY,?FRAGMENT]},
+ {2, [?SCHEME,?HOST,?PATH_ABE,?QUERY,?FRAGMENT]},
+ {2, [?SCHEME,?USER,?HOST,?PATH_ABE,?QUERY,?FRAGMENT]},
+ {2, [?SCHEME,?HOST,?PORT,?PATH_ABE,?QUERY,?FRAGMENT]},
+ {2, [?SCHEME,?USER,?HOST,?PORT,?PATH_ABE,?QUERY,?FRAGMENT]},
+
+ {2, [?PATH_ABS,?QUERY,?FRAGMENT]},
+ {2, [?PATH_NOS,?QUERY,?FRAGMENT]},
+ {2, [?PATH_EMP,?QUERY,?FRAGMENT]},
+ {2, [?HOST,?PATH_ABE,?QUERY,?FRAGMENT]},
+ {2, [?USER,?HOST,?PATH_ABE,?QUERY,?FRAGMENT]},
+ {2, [?HOST,?PORT,?PATH_ABE,?QUERY,?FRAGMENT]},
+ {2, [?USER,?HOST,?PORT,?PATH_ABE,?QUERY,?FRAGMENT]}
+ ]).
+
+comp_proplist_nu() ->
+ frequency([
+ {2, [?SCHEME,?PATH_ABS_NU]},
+ {2, [?SCHEME,?PATH_ROO_NU]},
+ {2, [?SCHEME,?PATH_EMP]},
+ {2, [?SCHEME,?HOST_NU,?PATH_ABE_NU]},
+ {2, [?SCHEME,?USER_NU,?HOST_NU,?PATH_ABE_NU]},
+ {2, [?SCHEME,?HOST_NU,?PORT,?PATH_ABE_NU]},
+ {2, [?SCHEME,?USER_NU,?HOST_NU,?PORT,?PATH_ABE_NU]},
+
+ {2, [?PATH_ABS_NU]},
+ {2, [?PATH_NOS_NU]},
+ {2, [?PATH_EMP]},
+ {2, [?HOST_NU,?PATH_ABE_NU]},
+ {2, [?USER_NU,?HOST_NU,?PATH_ABE_NU]},
+ {2, [?HOST_NU,?PORT,?PATH_ABE_NU]},
+ {2, [?USER_NU,?HOST_NU,?PORT,?PATH_ABE_NU]},
+
+
+ {2, [?SCHEME,?PATH_ABS_NU,?QUERY_NU]},
+ {2, [?SCHEME,?PATH_ROO_NU,?QUERY_NU]},
+ {2, [?SCHEME,?PATH_EMP,?QUERY_NU]},
+ {2, [?SCHEME,?HOST_NU,?PATH_ABE_NU,?QUERY_NU]},
+ {2, [?SCHEME,?USER_NU,?HOST_NU,?PATH_ABE_NU,?QUERY_NU]},
+ {2, [?SCHEME,?HOST_NU,?PORT,?PATH_ABE_NU,?QUERY_NU]},
+ {2, [?SCHEME,?USER_NU,?HOST_NU,?PORT,?PATH_ABE_NU,?QUERY_NU]},
+
+ {2, [?PATH_ABS_NU,?QUERY_NU]},
+ {2, [?PATH_NOS_NU,?QUERY_NU]},
+ {2, [?PATH_EMP,?QUERY_NU]},
+ {2, [?HOST_NU,?PATH_ABE_NU,?QUERY_NU]},
+ {2, [?USER_NU,?HOST_NU,?PATH_ABE_NU,?QUERY_NU]},
+ {2, [?HOST_NU,?PORT,?PATH_ABE_NU,?QUERY_NU]},
+ {2, [?USER_NU,?HOST_NU,?PORT,?PATH_ABE_NU,?QUERY_NU]},
+
+
+ {2, [?SCHEME,?PATH_ABS_NU,?FRAGMENT_NU]},
+ {2, [?SCHEME,?PATH_ROO_NU,?FRAGMENT_NU]},
+ {2, [?SCHEME,?PATH_EMP,?FRAGMENT_NU]},
+ {2, [?SCHEME,?HOST_NU,?PATH_ABE_NU,?FRAGMENT_NU]},
+ {2, [?SCHEME,?USER_NU,?HOST_NU,?PATH_ABE_NU,?FRAGMENT_NU]},
+ {2, [?SCHEME,?HOST_NU,?PORT,?PATH_ABE_NU,?FRAGMENT_NU]},
+ {2, [?SCHEME,?USER_NU,?HOST_NU,?PORT,?PATH_ABE_NU,?FRAGMENT_NU]},
+
+ {2, [?PATH_ABS_NU,?FRAGMENT_NU]},
+ {2, [?PATH_NOS_NU,?FRAGMENT_NU]},
+ {2, [?PATH_EMP,?FRAGMENT_NU]},
+ {2, [?HOST_NU,?PATH_ABE_NU,?FRAGMENT_NU]},
+ {2, [?USER_NU,?HOST_NU,?PATH_ABE_NU,?FRAGMENT_NU]},
+ {2, [?HOST_NU,?PORT,?PATH_ABE_NU,?FRAGMENT_NU]},
+ {2, [?USER_NU,?HOST_NU,?PORT,?PATH_ABE_NU,?FRAGMENT_NU]},
+
+
+ {2, [?SCHEME,?PATH_ABS_NU,?QUERY_NU,?FRAGMENT_NU]},
+ {2, [?SCHEME,?PATH_ROO_NU,?QUERY_NU,?FRAGMENT_NU]},
+ {2, [?SCHEME,?PATH_EMP,?QUERY_NU,?FRAGMENT_NU]},
+ {2, [?SCHEME,?HOST_NU,?PATH_ABE_NU,?QUERY_NU,?FRAGMENT_NU]},
+ {2, [?SCHEME,?USER_NU,?HOST_NU,?PATH_ABE_NU,?QUERY_NU,?FRAGMENT_NU]},
+ {2, [?SCHEME,?HOST_NU,?PORT,?PATH_ABE_NU,?QUERY_NU,?FRAGMENT_NU]},
+ {2, [?SCHEME,?USER_NU,?HOST_NU,?PORT,?PATH_ABE_NU,?QUERY_NU,?FRAGMENT_NU]},
+
+ {2, [?PATH_ABS_NU,?QUERY_NU,?FRAGMENT_NU]},
+ {2, [?PATH_NOS_NU,?QUERY_NU,?FRAGMENT_NU]},
+ {2, [?PATH_EMP,?QUERY_NU,?FRAGMENT_NU]},
+ {2, [?HOST_NU,?PATH_ABE_NU,?QUERY_NU,?FRAGMENT_NU]},
+ {2, [?USER_NU,?HOST_NU,?PATH_ABE_NU,?QUERY_NU,?FRAGMENT_NU]},
+ {2, [?HOST_NU,?PORT,?PATH_ABE_NU,?QUERY_NU,?FRAGMENT_NU]},
+ {2, [?USER_NU,?HOST_NU,?PORT,?PATH_ABE_NU,?QUERY_NU,?FRAGMENT_NU]}
+ ]).
+
+
+%%-------------------------------------------------------------------------
+%% Path
+%%-------------------------------------------------------------------------
+path_abempty_map() ->
+ frequency([{90, path_abe_map()},
+ {10, path_empty_map()}]).
+
+path_abempty_map_nu() ->
+ frequency([{90, path_abe_map_nu()},
+ {10, path_empty_map()}]).
+
+
+path_abe_map() ->
+ ?SIZED(Length, path_abe_map(Length, [])).
+%%
+path_abe_map(0, Segments) ->
+ ?LET(Gen, Segments, lists:append(Gen));
+path_abe_map(N, Segments) ->
+ path_abe_map(N-1, [slash(),segment()|Segments]).
+
+path_abe_map_nu() ->
+ ?SIZED(Length, path_abe_map_nu(Length, [])).
+%%
+path_abe_map_nu(0, Segments) ->
+ ?LET(Gen, Segments, lists:append(Gen));
+path_abe_map_nu(N, Segments) ->
+ path_abe_map_nu(N-1, [slash(),segment_nu()|Segments]).
+
+
+path_absolute_map() ->
+ ?SIZED(Length, path_absolute_map(Length, [])).
+%%
+path_absolute_map(0, Segments) ->
+ ?LET(Gen, [slash(),segment_nz()|Segments], lists:append(Gen));
+path_absolute_map(N, Segments) ->
+ path_absolute_map(N-1, [slash(),segment()|Segments]).
+
+path_absolute_map_nu() ->
+ ?SIZED(Length, path_absolute_map_nu(Length, [])).
+%%
+path_absolute_map_nu(0, Segments) ->
+ ?LET(Gen, [slash(),segment_nz_nu()|Segments], lists:append(Gen));
+path_absolute_map_nu(N, Segments) ->
+ path_absolute_map_nu(N-1, [slash(),segment_nu()|Segments]).
+
+
+path_noscheme_map() ->
+ ?SIZED(Length, path_noscheme_map(Length, [])).
+%%
+path_noscheme_map(0, Segments) ->
+ ?LET(Gen, [segment_nz_nc()|Segments], lists:append(Gen));
+path_noscheme_map(N, Segments) ->
+ path_noscheme_map(N-1, [slash(),segment()|Segments]).
+
+path_noscheme_map_nu() ->
+ ?SIZED(Length, path_noscheme_map_nu(Length, [])).
+%%
+path_noscheme_map_nu(0, Segments) ->
+ ?LET(Gen, [segment_nz_nc_nu()|Segments], lists:append(Gen));
+path_noscheme_map_nu(N, Segments) ->
+ path_noscheme_map_nu(N-1, [slash(),segment_nu()|Segments]).
+
+
+path_rootless_map() ->
+ ?SIZED(Length, path_rootless_map(Length, [])).
+%%
+path_rootless_map(0, Segments) ->
+ ?LET(Gen, [segment_nz()|Segments], lists:append(Gen));
+path_rootless_map(N, Segments) ->
+ path_rootless_map(N-1, [slash(),segment()|Segments]).
+
+path_rootless_map_nu() ->
+ ?SIZED(Length, path_rootless_map_nu(Length, [])).
+%%
+path_rootless_map_nu(0, Segments) ->
+ ?LET(Gen, [segment_nz_nu()|Segments], lists:append(Gen));
+path_rootless_map_nu(N, Segments) ->
+ path_rootless_map_nu(N-1, [slash(),segment_nu()|Segments]).
+
+
+segment_nz() ->
+ non_empty(segment()).
+
+segment_nz_nu() ->
+ non_empty(segment_nu()).
+
+
+segment_nz_nc() ->
+ ?LET(Gen,
+ non_empty(list(frequency([{30, unreserved()},
+ {10, ptc_encoded_reserved()},
+ {10, sub_delims()},
+ {10, unicode_char()},
+ {5, oneof([$@])}
+ ]))),
+ lists:flatten(Gen)).
+
+segment_nz_nc_nu() ->
+ ?LET(Gen,
+ non_empty(list(frequency([{30, unreserved()},
+ {10, ptc_encoded_reserved()},
+ {10, sub_delims()},
+ {5, oneof([$@])}
+ ]))),
+ lists:flatten(Gen)).
+
+segment() ->
+ ?LET(Gen,
+ list(frequency([{30, unreserved()},
+ {10, ptc_encoded_reserved()},
+ {10, sub_delims()},
+ {10, unicode_char()},
+ {5, oneof([$:, $@])}
+ ])),
+ lists:flatten(Gen)).
+
+segment_nu() ->
+ ?LET(Gen,
+ list(frequency([{30, unreserved()},
+ {10, ptc_encoded_reserved()},
+ {10, sub_delims()},
+ {5, oneof([$:, $@])}
+ ])),
+ lists:flatten(Gen)).
+
+slash() ->
+ "/".
+
+path_empty_map() ->
+ "".
+
+
+%%-------------------------------------------------------------------------
+%% Host
+%%-------------------------------------------------------------------------
+host_map() ->
+ frequency([{30, reg_name()},
+ {30, ip_address()}
+ ]).
+
+host_map_nu() ->
+ frequency([{30, reg_name_nu()},
+ {30, ip_address()}
+ ]).
+
+reg_name() ->
+ ?LET(Gen,
+ list(frequency([{30, alpha()},
+ {10, sub_delims()},
+ {10, ptc_encoded_reserved()},
+ {10, unicode_char()}
+ ])),
+ lists:flatten(Gen)).
+
+reg_name_nu() ->
+ ?LET(Gen,
+ list(frequency([{30, alpha()},
+ {10, sub_delims()},
+ {10, ptc_encoded_reserved()}
+ ])),
+ lists:flatten(Gen)).
+
+
+ip_address() ->
+ oneof(["127.0.0.1", "::127.0.0.1",
+ "2001:0db8:0000:0000:0000:0000:1428:07ab",
+ "2001:0db8:0000:0000:0000::1428:07ab",
+ "2001:0db8:0:0:0:0:1428:07ab",
+ "2001:0db8:0::0:1428:07ab"]).
+
+%% Generating only reg-names
+host_uri() ->
+ ?LET(Gen,
+ non_empty(list(frequency([{30, unreserved()},
+ {10, sub_delims()},
+ {10, ptc_encoded_reserved()},
+ {10, pct_encoded()}
+ ]))),
+ lists:flatten(Gen)).
+
+%%-------------------------------------------------------------------------
+%% Port, Query, Fragment
+%%-------------------------------------------------------------------------
+port() ->
+ frequency([{10, undefined},
+ {10, range(1,65535)}
+ ]).
+
+query_map() ->
+ unicode().
+
+query_map_nu() ->
+ non_unicode().
+
+
+query_uri() ->
+ [$?| non_empty(list(frequency([{20, pchar()},
+ {5, oneof([$/, $?])} % punctuation
+ ])))].
+
+fragment_map() ->
+ unicode().
+
+fragment_map_nu() ->
+ non_unicode().
+
+
+fragment_uri() ->
+ [$?| non_empty(list(frequency([{20, pchar()},
+ {5, oneof([$/, $?])} % punctuation
+ ])))].
+
+
+%%-------------------------------------------------------------------------
+%% Scheme
+%%-------------------------------------------------------------------------
+scheme() ->
+ ?SIZED(Length, scheme_start(Length, [])).
+%%
+scheme_start(0, L) ->
+ ?LET(Gen, L, lists:reverse(Gen));
+scheme_start(N, L) ->
+ scheme(N-1,[alpha()|L]).
+
+scheme(0, L) ->
+ ?LET(Gen, L, lists:reverse(Gen));
+scheme(N, L) ->
+ scheme(N-1, [scheme_char()|L]).
+
+
+%%-------------------------------------------------------------------------
+%% Misc
+%%-------------------------------------------------------------------------
+unicode() ->
+ list(frequency([{20, alpha()}, % alpha
+ {10, digit()}, % digit
+ {10, unicode_char()} % unicode
+ ])).
+
+non_unicode() ->
+ list(frequency([{20, alpha()}, % alpha
+ {10, digit()} % digit
+ ])).
+
+scheme_char() ->
+ frequency([{20, alpha()}, % alpha
+ {20, digit()}, % digit
+ {5, oneof([$+, $-, $.])} % punctuation
+ ]).
+
+sub_delims() ->
+ oneof([$!, $$, $&, $', $(, $),
+ $*, $+, $,,$;, $=]).
+
+pchar() ->
+ frequency([{20, unreserved()},
+ {5, ptc_encoded_reserved()},
+ {5, pct_encoded()},
+ {5, sub_delims()},
+ {1, oneof([$:, $@])} % punctuation
+ ]).
+
+unreserved() ->
+ frequency([{20, alpha()},
+ {5, digit()},
+ {1, oneof([$-, $., $_, $~])} % punctuation
+ ]).
+
+unicode_char() ->
+ range(913, 1023).
+
+alpha() ->
+ frequency([{20, range($a, $z)}, % letters
+ {20, range($A, $Z)}]). % letters
+
+digit() ->
+ range($0, $9). % numbers
+
+pct_encoded() ->
+ oneof(["%C3%A4", "%C3%A5", "%C3%B6"]).
+
+%%-------------------------------------------------------------------------
+%% [RFC 3986, Chapter 2.2. Reserved Characters]
+%%
+%% reserved = gen-delims / sub-delims
+%%
+%% gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+%% 3A 2F 3F 23 5B 5D 40
+%% sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+%% 21 24 26 27 28 29
+%% / "*" / "+" / "," / ";" / "="
+%% 2A 2B 2C 3B 3D
+%%-------------------------------------------------------------------------
+ptc_encoded_reserved() ->
+ oneof(["%3A","%2F","%3F","%23","%5B","%5D","%40",
+ "%21","%24","%26","%27","%28","%29",
+ "%2A","%2B","%2C","%3B","3D"]).
+
+%%%========================================================================
+%%% Helpers
+%%%========================================================================
+proplist_to_map(L) ->
+ lists:foldl(fun({K,V},M) -> M#{K => V};
+ (_,M) -> M
+ end, #{}, L).
+
+map_scheme_host_to_lower(Map) ->
+ Fun = fun (scheme,V) ->
+ string:to_lower(V);
+ (host,V) ->
+ string:to_lower(V);
+ (_,V) ->
+ V
+ end,
+ maps:map(Fun, Map).
diff --git a/lib/stdlib/test/qlc_SUITE.erl b/lib/stdlib/test/qlc_SUITE.erl
index 5e9e03e410..d7354438f9 100644
--- a/lib/stdlib/test/qlc_SUITE.erl
+++ b/lib/stdlib/test/qlc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1695,28 +1695,7 @@ sort(Config) when is_list(Config) ->
[true || I <- lists:seq(1, 50000), not ets:insert(E, {I, I})],
H = qlc:q([{X,Y} || X <- [a,b], Y <- qlc:sort(ets:table(E))]),
100000 = length(qlc:e(H)),
- ets:delete(E)">>,
-
- begin
- TmpDir = ?privdir,
- [<<"TE = process_flag(trap_exit, true),
- E = ets:new(foo, []),
- [true || I <- lists:seq(1, 50000), not ets:insert(E, {I, I})],
- Ports = erlang:ports(),
- H = qlc:q([{X,Y} || X <- [a,b],
- begin
- [P] = erlang:ports() -- Ports,
- exit(P, port_exit),
- true
- end,
- Y <- qlc:sort(ets:table(E),
- [{tmpdir,\"">>,
- TmpDir, <<"\"}])]),
- {error, qlc, {file_error, _, _}} = (catch qlc:e(H)),
- receive {'EXIT', _, port_exit} -> ok end,
- ets:delete(E),
- process_flag(trap_exit, TE)">>]
- end
+ ets:delete(E)">>
],
run(Config, Ts),
@@ -7489,7 +7468,7 @@ strip_qlc_call(H) ->
strip_qlc_call2(H) ->
S = qlc:info(H, {flat, false}),
{ok, Tokens, _EndLine} = erl_scan:string(S++".", 1, [text]),
- {ok, [Expr], Bs} = lib:extended_parse_exprs(Tokens),
+ {ok, [Expr], Bs} = erl_eval:extended_parse_exprs(Tokens),
{case Expr of
{call,_,{remote,_,{atom,_,qlc},{atom,_,q}},[LC]} ->
{qlc, lists:flatten([erl_pp:expr(LC), "."]), []};
@@ -7510,7 +7489,7 @@ strip_qlc_call2(H) ->
join_info_count(H) ->
S = qlc:info(H, {flat, false}),
{ok, Tokens, _EndLine} = erl_scan:string(S++".", 1, [text]),
- {ok, [Expr], _Bs} = lib:extended_parse_exprs(Tokens),
+ {ok, [Expr], _Bs} = erl_eval:extended_parse_exprs(Tokens),
#ji{nmerge = Nmerge, nlookup = Nlookup,
nkeysort = NKeysort, nnested_loop = Nnested_loop} =
ji(Expr, #ji{}),
@@ -7554,7 +7533,7 @@ lookup_keys({generate,_,Q}, L) ->
lookup_keys(Q, L);
lookup_keys({table,Chars}, L) when is_list(Chars) ->
{ok, Tokens, _} = erl_scan:string(lists:flatten(Chars++"."), 1, [text]),
- {ok, [Expr], _Bs} = lib:extended_parse_exprs(Tokens),
+ {ok, [Expr], _Bs} = erl_eval:extended_parse_exprs(Tokens),
case Expr of
{call,_,_,[_fun,AKs]} ->
case erl_parse:normalise(AKs) of
@@ -7871,7 +7850,7 @@ run_test(Config, Extra, {cres, Body, Opts, ExpectedCompileReturn}) ->
{module, _} = code:load_abs(AbsFile, Mod),
Ms0 = erlang:process_info(self(),messages),
- Before = {{get(), lists:sort(ets:all()), Ms0}, pps()},
+ Before = {{lget(), lists:sort(ets:all()), Ms0}, pps()},
%% Prepare the check that the qlc module does not call qlc_pt.
_ = [unload_pt() || {file, Name} <- [code:is_loaded(qlc_pt)],
@@ -7903,7 +7882,7 @@ run_test(Config, Extra, Body) ->
wait_for_expected(R, {Strict0,PPS0}=Before, SourceFile, Wait) ->
Ms = erlang:process_info(self(),messages),
- After = {_,PPS1} = {{get(), lists:sort(ets:all()), Ms}, pps()},
+ After = {_,PPS1} = {{lget(), lists:sort(ets:all()), Ms}, pps()},
case {R, After} of
{ok, Before} ->
ok;
@@ -7931,6 +7910,18 @@ wait_for_expected(R, {Strict0,PPS0}=Before, SourceFile, Wait) ->
expected({ok,Before}, {R,After}, SourceFile)
end.
+%% The qlc modules uses the process dictionary for storing names of files.
+lget() ->
+ lists:sort([T || {K, _} = T <- get(), is_qlc_key(K)]).
+
+%% Copied from the qlc module.
+-define(LCACHE_FILE(Ref), {Ref, '$_qlc_cache_tmpfiles_'}).
+-define(MERGE_JOIN_FILE, '$_qlc_merge_join_tmpfiles_').
+
+is_qlc_key(?LCACHE_FILE(_)) -> true;
+is_qlc_key(?MERGE_JOIN_FILE) -> true;
+is_qlc_key(_) -> false.
+
unload_pt() ->
erlang:garbage_collect(), % get rid of references to qlc_pt...
_ = code:purge(qlc_pt),
diff --git a/lib/stdlib/test/rand_SUITE.erl b/lib/stdlib/test/rand_SUITE.erl
index 432293b656..b76c9f5341 100644
--- a/lib/stdlib/test/rand_SUITE.erl
+++ b/lib/stdlib/test/rand_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,11 +29,17 @@
basic_stats_uniform_1/1, basic_stats_uniform_2/1,
basic_stats_standard_normal/1,
basic_stats_normal/1,
+ stats_standard_normal_box_muller/1,
+ stats_standard_normal_box_muller_2/1,
+ stats_standard_normal/1,
+ uniform_real_conv/1,
plugin/1, measure/1,
reference_jump_state/1, reference_jump_procdict/1]).
-export([test/0, gen/1]).
+-export([uniform_real_gen/1, uniform_gen/2]).
+
-include_lib("common_test/include/ct.hrl").
-define(LOOP, 1000000).
@@ -47,6 +53,8 @@ all() ->
api_eq,
reference,
{group, basic_stats},
+ {group, distr_stats},
+ uniform_real_conv,
plugin, measure,
{group, reference_jump}
].
@@ -55,12 +63,19 @@ groups() ->
[{basic_stats, [parallel],
[basic_stats_uniform_1, basic_stats_uniform_2,
basic_stats_standard_normal]},
+ {distr_stats, [parallel],
+ [stats_standard_normal_box_muller,
+ stats_standard_normal_box_muller_2,
+ stats_standard_normal]},
{reference_jump, [parallel],
[reference_jump_state, reference_jump_procdict]}].
group(basic_stats) ->
%% valgrind needs a lot of time
[{timetrap,{minutes,10}}];
+group(distr_stats) ->
+ %% valgrind needs a lot of time
+ [{timetrap,{minutes,10}}];
group(reference_jump) ->
%% valgrind needs a lot of time
[{timetrap,{minutes,10}}].
@@ -73,14 +88,14 @@ test() ->
try
ok = ?MODULE:Test([]),
io:format("~p: ok~n", [Test])
- catch _:Reason ->
+ catch _:Reason:Stacktrace ->
io:format("Failed: ~p: ~p ~p~n",
- [Test, Reason, erlang:get_stacktrace()])
+ [Test, Reason, Stacktrace])
end
end, Tests).
algs() ->
- [exs64, exsplus, exsp, exrop, exs1024, exs1024s].
+ [exrop, exsp, exs1024s, exs64, exsplus, exs1024].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -89,8 +104,8 @@ seed(Config) when is_list(Config) ->
Algs = algs(),
Test = fun(Alg) ->
try seed_1(Alg)
- catch _:Reason ->
- ct:fail({Alg, Reason, erlang:get_stacktrace()})
+ catch _:Reason:Stacktrace ->
+ ct:fail({Alg, Reason, Stacktrace})
end
end,
[Test(Alg) || Alg <- Algs],
@@ -101,7 +116,7 @@ seed_1(Alg) ->
_ = rand:uniform(),
S00 = get(rand_seed),
erase(),
- _ = rand:uniform(),
+ _ = rand:uniform_real(),
false = S00 =:= get(rand_seed), %% hopefully
%% Choosing algo and seed
@@ -228,11 +243,13 @@ interval_float(Config) when is_list(Config) ->
interval_float_1(0) -> ok;
interval_float_1(N) ->
X = rand:uniform(),
+ Y = rand:uniform_real(),
if
- 0.0 =< X, X < 1.0 ->
+ 0.0 =< X, X < 1.0, 0.0 < Y, Y < 1.0 ->
ok;
true ->
- io:format("X=~p 0=<~p<1.0~n", [X,X]),
+ io:format("X=~p 0.0=<~p<1.0~n", [X,X]),
+ io:format("Y=~p 0.0<~p<1.0~n", [Y,Y]),
exit({X, rand:export_seed()})
end,
interval_float_1(N-1).
@@ -334,7 +351,13 @@ basic_stats_normal(Config) when is_list(Config) ->
IntendedMeanVariancePairs).
basic_uniform_1(N, S0, Sum, A0) when N > 0 ->
- {X,S} = rand:uniform_s(S0),
+ {X,S} =
+ case N band 1 of
+ 0 ->
+ rand:uniform_s(S0);
+ 1 ->
+ rand:uniform_real_s(S0)
+ end,
I = trunc(X*100),
A = array:set(I, 1+array:get(I,A0), A0),
basic_uniform_1(N-1, S, Sum+X, A);
@@ -399,6 +422,352 @@ normal_s(Mean, Variance, State0) when Mean == 0, Variance == 1 ->
normal_s(Mean, Variance, State0) ->
rand:normal_s(Mean, Variance, State0).
+
+
+-dialyzer({no_improper_lists, stats_standard_normal_box_muller/1}).
+stats_standard_normal_box_muller(Config) when is_list(Config) ->
+ try math:erfc(1.0) of
+ _ ->
+ TwoPi = 2.0 * math:pi(),
+ NormalS =
+ fun
+ ([S0]) ->
+ {U1, S1} = rand:uniform_real_s(S0),
+ R = math:sqrt(-2.0 * math:log(U1)),
+ {U2, S2} = rand:uniform_s(S1),
+ T = TwoPi * U2,
+ Z0 = R * math:cos(T),
+ Z1 = R * math:sin(T),
+ {Z0, [S2|Z1]};
+ ([S|Z]) ->
+ {Z, [S]}
+ end,
+ State = [rand:seed(exrop)],
+ stats_standard_normal(NormalS, State, 3)
+ catch error:_ ->
+ {skip, "math:erfc/1 not supported"}
+ end.
+
+-dialyzer({no_improper_lists, stats_standard_normal_box_muller_2/1}).
+stats_standard_normal_box_muller_2(Config) when is_list(Config) ->
+ try math:erfc(1.0) of
+ _ ->
+ TwoPi = 2.0 * math:pi(),
+ NormalS =
+ fun
+ ([S0]) ->
+ {U0, S1} = rand:uniform_s(S0),
+ U1 = 1.0 - U0,
+ R = math:sqrt(-2.0 * math:log(U1)),
+ {U2, S2} = rand:uniform_s(S1),
+ T = TwoPi * U2,
+ Z0 = R * math:cos(T),
+ Z1 = R * math:sin(T),
+ {Z0, [S2|Z1]};
+ ([S|Z]) ->
+ {Z, [S]}
+ end,
+ State = [rand:seed(exrop)],
+ stats_standard_normal(NormalS, State, 3)
+ catch error:_ ->
+ {skip, "math:erfc/1 not supported"}
+ end.
+
+
+stats_standard_normal(Config) when is_list(Config) ->
+ Retries = 7,
+ try math:erfc(1.0) of
+ _ ->
+ stats_standard_normal(
+ fun rand:normal_s/1, rand:seed_s(exrop), Retries)
+ catch error:_ ->
+ {skip, "math:erfc/1 not supported"}
+ end.
+%%
+stats_standard_normal(Fun, S, Retries) ->
+%%%
+%%% ct config:
+%%% {rand_SUITE, [{stats_standard_normal,[{seconds, 8}, {std_devs, 4.0}]}]}.
+%%%
+ Seconds = ct:get_config({?MODULE, ?FUNCTION_NAME, seconds}, 8),
+ StdDevs =
+ ct:get_config(
+ {?MODULE, ?FUNCTION_NAME, std_devs},
+ 4.0), % probability erfc(4.0/sqrt(2)) (1/15787) to fail a bucket
+%%%
+ ct:timetrap({seconds, Seconds + 120}),
+ %% Buckets is chosen to get a range where the the probability to land
+ %% in the top catch-all bucket is not vanishingly low, but with
+ %% these values it is about 1/25 of the probability for the low bucket
+ %% (closest to 0).
+ %%
+ %% Rounds is calculated so the expected value for the low
+ %% bucket will be at least TargetHits.
+ %%
+ InvDelta = 512,
+ Buckets = 4 * InvDelta, % 4 std devs range
+ TargetHits = 1024,
+ Sqrt2 = math:sqrt(2.0),
+ W = InvDelta * Sqrt2,
+ P0 = math:erf(1 / W),
+ Rounds = TargetHits * ceil(1.0 / P0),
+ Histogram = array:new({default, 0}),
+ ct:pal(
+ "Running standard normal test against ~w std devs for ~w seconds...",
+ [StdDevs, Seconds]),
+ StopTime = erlang:monotonic_time(second) + Seconds,
+ {PositiveHistogram, NegativeHistogram, Outlier, TotalRounds, NewS} =
+ stats_standard_normal(
+ InvDelta, Buckets, Histogram, Histogram, 0.0,
+ Fun, S, Rounds, StopTime, Rounds, 0),
+ Precision = math:sqrt(TotalRounds * P0) / StdDevs,
+ TopP = math:erfc(Buckets / W),
+ TopPrecision = math:sqrt(TotalRounds * TopP) / StdDevs,
+ OutlierProbability = math:erfc(Outlier / Sqrt2) * TotalRounds,
+ InvOP = 1.0 / OutlierProbability,
+ ct:pal(
+ "Total rounds: ~w, tolerance: 1/~.2f..1/~.2f, "
+ "outlier: ~.2f, probability 1/~.2f.",
+ [TotalRounds, Precision, TopPrecision, Outlier, InvOP]),
+ case
+ {bucket_error, TotalRounds,
+ check_histogram(
+ W, TotalRounds, StdDevs, PositiveHistogram, Buckets),
+ check_histogram(
+ W, TotalRounds, StdDevs, NegativeHistogram, Buckets)}
+ of
+ {_, _, [], []} when InvOP < 100 ->
+ {comment, {tp, TopPrecision, op, InvOP}};
+ {_, _, [], []} ->
+ %% If the probability for getting this Outlier is lower than
+ %% 1/100, then this is fishy!
+ stats_standard_normal(
+ Fun, NewS, Retries, {outlier_fishy, InvOP});
+ BucketErrors ->
+ stats_standard_normal(
+ Fun, NewS, Retries, BucketErrors)
+ end.
+%%
+stats_standard_normal(Fun, S, Retries, Failure) ->
+ case Retries - 1 of
+ 0 ->
+ ct:fail(Failure);
+ NewRetries ->
+ ct:pal("Retry due to TC glitch: ~p", [Failure]),
+ stats_standard_normal(Fun, S, NewRetries)
+ end.
+%%
+stats_standard_normal(
+ InvDelta, Buckets, PositiveHistogram, NegativeHistogram, Outlier,
+ Fun, S, 0, StopTime, Rounds, TotalRounds) ->
+ case erlang:monotonic_time(second) of
+ Now when Now < StopTime ->
+ stats_standard_normal(
+ InvDelta, Buckets,
+ PositiveHistogram, NegativeHistogram, Outlier,
+ Fun, S, Rounds, StopTime, Rounds, TotalRounds + Rounds);
+ _ ->
+ {PositiveHistogram, NegativeHistogram,
+ Outlier, TotalRounds + Rounds, S}
+ end;
+stats_standard_normal(
+ InvDelta, Buckets, PositiveHistogram, NegativeHistogram, Outlier,
+ Fun, S, Count, StopTime, Rounds, TotalRounds) ->
+ case Fun(S) of
+ {X, NewS} when 0.0 =< X ->
+ Bucket = min(Buckets, floor(X * InvDelta)),
+ stats_standard_normal(
+ InvDelta, Buckets,
+ increment_bucket(Bucket, PositiveHistogram),
+ NegativeHistogram, max(Outlier, X),
+ Fun, NewS, Count - 1, StopTime, Rounds, TotalRounds);
+ {MinusX, NewS} ->
+ X = -MinusX,
+ Bucket = min(Buckets, floor(X * InvDelta)),
+ stats_standard_normal(
+ InvDelta, Buckets,
+ PositiveHistogram,
+ increment_bucket(Bucket, NegativeHistogram), max(Outlier, X),
+ Fun, NewS, Count - 1, StopTime, Rounds, TotalRounds)
+ end.
+
+increment_bucket(Bucket, Array) ->
+ array:set(Bucket, array:get(Bucket, Array) + 1, Array).
+
+check_histogram(W, Rounds, StdDevs, Histogram, Buckets) ->
+ TargetP = 0.5 * math:erfc(Buckets / W),
+ P = 0.0,
+ N = 0,
+ check_histogram(
+ W, Rounds, StdDevs, Histogram, TargetP,
+ Buckets, Buckets, P, N).
+%%
+check_histogram(
+ _W, _Rounds, _StdDevs, _Histogram, _TargetP,
+ 0, _PrevBucket, _PrevP, _PrevN) ->
+ [];
+check_histogram(
+ W, Rounds, StdDevs, Histogram, TargetP,
+ Bucket, PrevBucket, PrevP, PrevN) ->
+ N = PrevN + array:get(Bucket, Histogram),
+ P = 0.5 * math:erfc(Bucket / W),
+ BucketP = P - PrevP,
+ if
+ BucketP < TargetP ->
+ check_histogram(
+ W, Rounds, StdDevs, Histogram, TargetP,
+ Bucket - 1, PrevBucket, PrevP, N);
+ true ->
+ Exp = BucketP * Rounds,
+ Var = Rounds * BucketP*(1.0 - BucketP),
+ Threshold = StdDevs * math:sqrt(Var),
+ LowerLimit = floor(Exp - Threshold),
+ UpperLimit = ceil(Exp + Threshold),
+ if
+ N < LowerLimit; UpperLimit < N ->
+ [#{bucket => {Bucket, PrevBucket}, n => N,
+ lower => LowerLimit, upper => UpperLimit} |
+ check_histogram(
+ W, Rounds, StdDevs, Histogram, TargetP,
+ Bucket - 1, Bucket, P, 0)];
+ true ->
+ check_histogram(
+ W, Rounds, StdDevs, Histogram, TargetP,
+ Bucket - 1, Bucket, P, 0)
+ end
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% White box test of the conversion to float
+
+uniform_real_conv(Config) when is_list(Config) ->
+ [begin
+%% ct:pal("~13.16.0bx~3.16.0b: ~p~n", [M,E,Gen]),
+ uniform_real_conv_check(M, E, Gen)
+ end || {M, E, Gen} <- uniform_real_conv_data()],
+ uniform_real_scan(0),
+ uniform_real_scan(3).
+
+uniform_real_conv_data() ->
+ [{16#fffffffffffff, -1, [16#3ffffffffffffff]},
+ {16#fffffffffffff, -1, [16#3ffffffffffffe0]},
+ {16#ffffffffffffe, -1, [16#3ffffffffffffdf]},
+ %%
+ {16#0000000000000, -1, [16#200000000000000]},
+ {16#fffffffffffff, -2, [16#1ffffffffffffff]},
+ {16#fffffffffffff, -2, [16#1fffffffffffff0]},
+ {16#ffffffffffffe, -2, [16#1ffffffffffffef]},
+ %%
+ {16#0000000000000, -2, [16#100000000000000]},
+ {16#fffffffffffff, -3, [16#0ffffffffffffff]},
+ {16#fffffffffffff, -3, [16#0fffffffffffff8]},
+ {16#ffffffffffffe, -3, [16#0fffffffffffff7]},
+ %%
+ {16#0000000000000, -3, [16#080000000000000]},
+ {16#fffffffffffff, -4, [16#07fffffffffffff]},
+ {16#fffffffffffff, -4, [16#07ffffffffffffc]},
+ {16#ffffffffffffe, -4, [16#07ffffffffffffb]},
+ %%
+ {16#0000000000000, -4, [16#040000000000000]},
+ {16#fffffffffffff, -5, [16#03fffffffffffff,16#3ffffffffffffff]},
+ {16#fffffffffffff, -5, [16#03ffffffffffffe,16#200000000000000]},
+ {16#ffffffffffffe, -5, [16#03fffffffffffff,16#1ffffffffffffff]},
+ {16#ffffffffffffe, -5, [16#03fffffffffffff,16#100000000000000]},
+ %%
+ {16#0000000000001, -56, [16#000000000000007,16#00000000000007f]},
+ {16#0000000000001, -56, [16#000000000000004,16#000000000000040]},
+ {16#0000000000000, -57, [16#000000000000003,16#20000000000001f]},
+ {16#0000000000000, -57, [16#000000000000000,16#200000000000000]},
+ {16#fffffffffffff, -58, [16#000000000000003,16#1ffffffffffffff]},
+ {16#fffffffffffff, -58, [16#000000000000000,16#1fffffffffffff0]},
+ {16#ffffffffffffe, -58, [16#000000000000000,16#1ffffffffffffef]},
+ {16#ffffffffffffe, -58, [16#000000000000000,16#1ffffffffffffe0]},
+ %%
+ {16#0000000000000, -58, [16#000000000000000,16#10000000000000f]},
+ {16#0000000000000, -58, [16#000000000000000,16#100000000000000]},
+ {2#11001100000000000000000000000000000000000011000000011, % 53 bits
+ -1022,
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, % 18 zeros
+ 2#1100110000000000000000000000000000000000001 bsl 2, % 43 bits
+ 2#1000000011 bsl (56-10+2)]}, % 10 bits
+ {0, -1, % 0.5 after retry
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, % 18 zeros
+ 2#111111111111111111111111111111111111111111 bsl 2, % 42 bits - retry
+ 16#200000000000003]}]. % 0.5
+
+-define(UNIFORM_REAL_SCAN_PATTERN, (16#19000000000009)). % 53 bits
+-define(UNIFORM_REAL_SCAN_NUMBER, (1021)).
+
+uniform_real_scan_template(K) ->
+ <<0:?UNIFORM_REAL_SCAN_NUMBER,
+ ?UNIFORM_REAL_SCAN_PATTERN:53,K:2,0:1>>.
+
+uniform_real_scan(K) ->
+ Templ = uniform_real_scan_template(K),
+ N = ?UNIFORM_REAL_SCAN_NUMBER,
+ uniform_real_scan(Templ, N, K).
+
+uniform_real_scan(Templ, N, K) when 0 =< N ->
+ <<_:N/bits,T/bits>> = Templ,
+ Data = uniform_real_scan_data(T, K),
+ uniform_real_conv_check(
+ ?UNIFORM_REAL_SCAN_PATTERN, N - 1 - ?UNIFORM_REAL_SCAN_NUMBER, Data),
+ uniform_real_scan(Templ, N - 1, K);
+uniform_real_scan(_, _, _) ->
+ ok.
+
+uniform_real_scan_data(Templ, K) ->
+ case Templ of
+ <<X:56, T/bits>> ->
+ B = rand:bc64(X),
+ [(X bsl 2) bor K |
+ if
+ 53 =< B ->
+ [];
+ true ->
+ uniform_real_scan_data(T, K)
+ end];
+ _ ->
+ <<X:56, _/bits>> = <<Templ/bits, 0:56>>,
+ [(X bsl 2) bor K]
+ end.
+
+uniform_real_conv_check(M, E, Gen) ->
+ <<F/float>> = <<0:1, (E + 16#3ff):11, M:52>>,
+ try uniform_real_gen(Gen) of
+ F -> F;
+ FF ->
+ ct:pal(
+ "~s =/= ~s: ~s~n",
+ [rand:float2str(FF), rand:float2str(F),
+ [["16#",integer_to_list(G,16),$\s]||G<-Gen]]),
+ ct:fail({neq, FF, F})
+ catch
+ Error:Reason:Stacktrace ->
+ ct:pal(
+ "~w:~p ~s: ~s~n",
+ [Error, Reason, rand:float2str(F),
+ [["16#",integer_to_list(G,16),$\s]||G<-Gen]]),
+ ct:fail({Error, Reason, F, Stacktrace})
+ end.
+
+
+uniform_real_gen(Gen) ->
+ State = rand_state(Gen),
+ {F, {#{type := rand_SUITE_list},[]}} = rand:uniform_real_s(State),
+ F.
+
+uniform_gen(Range, Gen) ->
+ State = rand_state(Gen),
+ {N, {#{type := rand_SUITE_list},[]}} = rand:uniform_s(Range, State),
+ N.
+
+%% Loaded dice for white box tests
+rand_state(Gen) ->
+ {#{type => rand_SUITE_list, bits => 58, weak_low_bits => 1,
+ next => fun ([H|T]) -> {H, T} end},
+ Gen}.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Test that the user can write algorithms.
@@ -459,213 +828,289 @@ measure(Config) ->
{skip,{will_not_run_in_scaled_time,Scale}}
end.
+-define(CHECK_UNIFORM_RANGE(Gen, Range, X, St),
+ case (Gen) of
+ {(X), (St)} when is_integer(X), 1 =< (X), (X) =< (Range) ->
+ St
+ end).
+-define(CHECK_UNIFORM(Gen, X, St),
+ case (Gen) of
+ {(X), (St)} when is_float(X), 0.0 =< (X), (X) < 1.0 ->
+ St
+ end).
+-define(CHECK_UNIFORM_NZ(Gen, X, St),
+ case (Gen) of
+ {(X), (St)} when is_float(X), 0.0 < (X), (X) =< 1.0 ->
+ St
+ end).
+-define(CHECK_NORMAL(Gen, X, St),
+ case (Gen) of
+ {(X), (St)} when is_float(X) ->
+ St
+ end).
+
do_measure(_Config) ->
- Algos =
+ Algs =
+ algs() ++
try crypto:strong_rand_bytes(1) of
- <<_>> -> [crypto64, crypto]
+ <<_>> -> [crypto64, crypto_cache, crypto]
catch
error:low_entropy -> [];
error:undef -> []
- end ++ algs(),
+ end,
%%
- ct:pal("RNG uniform integer performance~n",[]),
- TMark1 =
+ ct:pal("~nRNG uniform integer range 10000 performance~n",[]),
+ _ =
measure_1(
- random,
fun (_) -> 10000 end,
- undefined,
- fun (Range, State) ->
- {int, random:uniform_s(Range, State)}
- end),
+ fun (State, Range, Mod) ->
+ measure_loop(
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Mod:uniform_s(Range, St0), Range,
+ X, St1)
+ end,
+ State)
+ end,
+ Algs),
+ %%
+ ct:pal("~nRNG uniform integer 32 bit performance~n",[]),
_ =
- [measure_1(
- Algo,
- fun (_) -> 10000 end,
- TMark1,
- fun (Range, State) ->
- {int, rand:uniform_s(Range, State)}
- end) || Algo <- Algos],
+ measure_1(
+ fun (_) -> 1 bsl 32 end,
+ fun (State, Range, Mod) ->
+ measure_loop(
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Mod:uniform_s(Range, St0), Range,
+ X, St1)
+ end,
+ State)
+ end,
+ Algs),
%%
ct:pal("~nRNG uniform integer half range performance~n",[]),
- HalfRangeFun = fun (State) -> half_range(State) end,
- TMark2 =
- measure_1(
- random,
- HalfRangeFun,
- undefined,
- fun (Range, State) ->
- {int, random:uniform_s(Range, State)}
- end),
_ =
- [measure_1(
- Algo,
- HalfRangeFun,
- TMark2,
- fun (Range, State) ->
- {int, rand:uniform_s(Range, State)}
- end) || Algo <- Algos],
- %%
- ct:pal("~nRNG uniform integer half range + 1 performance~n",[]),
- HalfRangePlus1Fun = fun (State) -> half_range(State) + 1 end,
- TMark3 =
measure_1(
- random,
- HalfRangePlus1Fun,
- undefined,
- fun (Range, State) ->
- {int, random:uniform_s(Range, State)}
- end),
+ fun (State) -> half_range(State) end,
+ fun (State, Range, Mod) ->
+ measure_loop(
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Mod:uniform_s(Range, St0), Range,
+ X, St1)
+ end,
+ State)
+ end,
+ Algs),
+ %%
+ ct:pal("~nRNG uniform integer half range + 1 performance~n",[]),
_ =
- [measure_1(
- Algo,
- HalfRangePlus1Fun,
- TMark3,
- fun (Range, State) ->
- {int, rand:uniform_s(Range, State)}
- end) || Algo <- Algos],
+ measure_1(
+ fun (State) -> half_range(State) + 1 end,
+ fun (State, Range, Mod) ->
+ measure_loop(
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Mod:uniform_s(Range, St0), Range,
+ X, St1)
+ end,
+ State)
+ end,
+ Algs),
%%
ct:pal("~nRNG uniform integer full range - 1 performance~n",[]),
- FullRangeMinus1Fun = fun (State) -> (half_range(State) bsl 1) - 1 end,
- TMark4 =
- measure_1(
- random,
- FullRangeMinus1Fun,
- undefined,
- fun (Range, State) ->
- {int, random:uniform_s(Range, State)}
- end),
_ =
- [measure_1(
- Algo,
- FullRangeMinus1Fun,
- TMark4,
- fun (Range, State) ->
- {int, rand:uniform_s(Range, State)}
- end) || Algo <- Algos],
+ measure_1(
+ fun (State) -> (half_range(State) bsl 1) - 1 end,
+ fun (State, Range, Mod) ->
+ measure_loop(
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Mod:uniform_s(Range, St0), Range,
+ X, St1)
+ end,
+ State)
+ end,
+ Algs),
%%
ct:pal("~nRNG uniform integer full range performance~n",[]),
- FullRangeFun = fun (State) -> half_range(State) bsl 1 end,
- TMark5 =
- measure_1(
- random,
- FullRangeFun,
- undefined,
- fun (Range, State) ->
- {int, random:uniform_s(Range, State)}
- end),
_ =
- [measure_1(
- Algo,
- FullRangeFun,
- TMark5,
- fun (Range, State) ->
- {int, rand:uniform_s(Range, State)}
- end) || Algo <- Algos],
+ measure_1(
+ fun (State) -> half_range(State) bsl 1 end,
+ fun (State, Range, Mod) ->
+ measure_loop(
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Mod:uniform_s(Range, St0), Range,
+ X, St1)
+ end,
+ State)
+ end,
+ Algs),
%%
ct:pal("~nRNG uniform integer full range + 1 performance~n",[]),
- FullRangePlus1Fun = fun (State) -> (half_range(State) bsl 1) + 1 end,
- TMark6 =
- measure_1(
- random,
- FullRangePlus1Fun,
- undefined,
- fun (Range, State) ->
- {int, random:uniform_s(Range, State)}
- end),
_ =
- [measure_1(
- Algo,
- FullRangePlus1Fun,
- TMark6,
- fun (Range, State) ->
- {int, rand:uniform_s(Range, State)}
- end) || Algo <- Algos],
+ measure_1(
+ fun (State) -> (half_range(State) bsl 1) + 1 end,
+ fun (State, Range, Mod) ->
+ measure_loop(
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Mod:uniform_s(Range, St0), Range,
+ X, St1)
+ end,
+ State)
+ end,
+ Algs),
%%
ct:pal("~nRNG uniform integer double range performance~n",[]),
- DoubleRangeFun = fun (State) -> half_range(State) bsl 2 end,
- TMark7 =
- measure_1(
- random,
- DoubleRangeFun,
- undefined,
- fun (Range, State) ->
- {int, random:uniform_s(Range, State)}
- end),
_ =
- [measure_1(
- Algo,
- DoubleRangeFun,
- TMark7,
- fun (Range, State) ->
- {int, rand:uniform_s(Range, State)}
- end) || Algo <- Algos],
+ measure_1(
+ fun (State) ->
+ half_range(State) bsl 2
+ end,
+ fun (State, Range, Mod) ->
+ measure_loop(
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Mod:uniform_s(Range, St0), Range,
+ X, St1)
+ end,
+ State)
+ end,
+ Algs),
%%
ct:pal("~nRNG uniform integer double range + 1 performance~n",[]),
- DoubleRangePlus1Fun = fun (State) -> (half_range(State) bsl 2) + 1 end,
- TMark8 =
+ _ =
measure_1(
- random,
- DoubleRangePlus1Fun,
- undefined,
- fun (Range, State) ->
- {int, random:uniform_s(Range, State)}
- end),
+ fun (State) ->
+ (half_range(State) bsl 2) + 1
+ end,
+ fun (State, Range, Mod) ->
+ measure_loop(
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Mod:uniform_s(Range, St0), Range,
+ X, St1)
+ end,
+ State)
+ end,
+ Algs),
+ %%
+ ct:pal("~nRNG uniform integer 64 bit performance~n",[]),
_ =
- [measure_1(
- Algo,
- DoubleRangePlus1Fun,
- TMark8,
- fun (Range, State) ->
- {int, rand:uniform_s(Range, State)}
- end) || Algo <- Algos],
+ measure_1(
+ fun (_) -> 1 bsl 64 end,
+ fun (State, Range, Mod) ->
+ measure_loop(
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Mod:uniform_s(Range, St0), Range,
+ X, St1)
+ end,
+ State)
+ end,
+ Algs),
%%
ct:pal("~nRNG uniform float performance~n",[]),
- TMark9 =
+ _ =
measure_1(
- random,
fun (_) -> 0 end,
- undefined,
- fun (_, State) ->
- {uniform, random:uniform_s(State)}
- end),
+ fun (State, _, Mod) ->
+ measure_loop(
+ fun (St0) ->
+ ?CHECK_UNIFORM(Mod:uniform_s(St0), X, St)
+ end,
+ State)
+ end,
+ Algs),
+ %%
+ ct:pal("~nRNG uniform_real float performance~n",[]),
_ =
- [measure_1(
- Algo,
- fun (_) -> 0 end,
- TMark9,
- fun (_, State) ->
- {uniform, rand:uniform_s(State)}
- end) || Algo <- Algos],
+ measure_1(
+ fun (_) -> 0 end,
+ fun (State, _, Mod) ->
+ measure_loop(
+ fun (St0) ->
+ ?CHECK_UNIFORM(Mod:uniform_real_s(St0), X, St)
+ end,
+ State)
+ end,
+ Algs),
%%
ct:pal("~nRNG normal float performance~n",[]),
- io:format("~.12w: not implemented (too few bits)~n", [random]),
- _ = [measure_1(
- Algo,
- fun (_) -> 0 end,
- TMark9,
- fun (_, State) ->
- {normal, rand:normal_s(State)}
- end) || Algo <- Algos],
+ [TMarkNormalFloat|_] =
+ measure_1(
+ fun (_) -> 0 end,
+ fun (State, _, Mod) ->
+ measure_loop(
+ fun (St0) ->
+ ?CHECK_NORMAL(Mod:normal_s(St0), X, St1)
+ end,
+ State)
+ end,
+ Algs),
+ %% Just for fun try an implementation of the Box-Muller
+ %% transformation for creating normal distribution floats
+ %% to compare with our Ziggurat implementation.
+ %% Generates two numbers per call that we add so they
+ %% will not be optimized away. Hence the benchmark time
+ %% is twice what it should be.
+ TwoPi = 2 * math:pi(),
+ _ =
+ measure_1(
+ fun (_) -> 0 end,
+ fun (State, _, Mod) ->
+ measure_loop(
+ fun (State0) ->
+ {U1, State1} = Mod:uniform_real_s(State0),
+ {U2, State2} = Mod:uniform_s(State1),
+ R = math:sqrt(-2.0 * math:log(U1)),
+ T = TwoPi * U2,
+ Z0 = R * math:cos(T),
+ Z1 = R * math:sin(T),
+ ?CHECK_NORMAL({Z0 + Z1, State2}, X, State3)
+ end,
+ State)
+ end,
+ exrop, TMarkNormalFloat),
ok.
-measure_1(Algo, RangeFun, TMark, Gen) ->
+-define(LOOP_MEASURE, (?LOOP div 5)).
+
+measure_loop(Fun, State) ->
+ measure_loop(Fun, State, ?LOOP_MEASURE).
+%%
+measure_loop(Fun, State, N) when 0 < N ->
+ measure_loop(Fun, Fun(State), N-1);
+measure_loop(_, _, _) ->
+ ok.
+
+measure_1(RangeFun, Fun, Algs) ->
+ TMark = measure_1(RangeFun, Fun, hd(Algs), undefined),
+ [TMark] ++
+ [measure_1(RangeFun, Fun, Alg, TMark) || Alg <- tl(Algs)].
+
+measure_1(RangeFun, Fun, Alg, TMark) ->
Parent = self(),
- Seed =
- case Algo of
+ {Mod, State} =
+ case Alg of
crypto64 ->
- crypto64_seed();
+ {rand, crypto64_seed()};
+ crypto_cache ->
+ {rand, crypto:rand_seed_alg(crypto_cache)};
crypto ->
- crypto:rand_seed_s();
+ {rand, crypto:rand_seed_s()};
random ->
- random:seed(os:timestamp()), get(random_seed);
+ {random, random:seed(os:timestamp()), get(random_seed)};
_ ->
- rand:seed_s(Algo)
+ {rand, rand:seed_s(Alg)}
end,
- Range = RangeFun(Seed),
+ Range = RangeFun(State),
Pid = spawn_link(
fun() ->
- Fun = fun() -> measure_2(?LOOP, Range, Seed, Gen) end,
- {Time, ok} = timer:tc(Fun),
+ {Time, ok} = timer:tc(fun () -> Fun(State, Range, Mod) end),
Percent =
case TMark of
undefined -> 100;
@@ -673,7 +1118,8 @@ measure_1(Algo, RangeFun, TMark, Gen) ->
end,
io:format(
"~.12w: ~p ns ~p% [16#~.16b]~n",
- [Algo, (Time * 1000 + 500) div ?LOOP, Percent, Range]),
+ [Alg, (Time * 1000 + 500) div ?LOOP_MEASURE,
+ Percent, Range]),
Parent ! {self(), Time},
normal
end),
@@ -681,21 +1127,6 @@ measure_1(Algo, RangeFun, TMark, Gen) ->
{Pid, Msg} -> Msg
end.
-measure_2(N, Range, State0, Fun) when N > 0 ->
- case Fun(Range, State0) of
- {int, {Random, State}}
- when is_integer(Random), Random >= 1, Random =< Range ->
- measure_2(N-1, Range, State, Fun);
- {uniform, {Random, State}}
- when is_float(Random), 0.0 =< Random, Random < 1.0 ->
- measure_2(N-1, Range, State, Fun);
- {normal, {Random, State}} when is_float(Random) ->
- measure_2(N-1, Range, State, Fun);
- Res ->
- exit({error, Res, State0})
- end;
-measure_2(0, _, _, _) -> ok.
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% The jump sequence tests has two parts
%% for those with the functional API (jump/1)
diff --git a/lib/stdlib/test/re_SUITE.erl b/lib/stdlib/test/re_SUITE.erl
index 71f86e32e5..c9ef9da990 100644
--- a/lib/stdlib/test/re_SUITE.erl
+++ b/lib/stdlib/test/re_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -894,10 +894,13 @@ match_limit(Config) when is_list(Config) ->
%% Test that we get sub-binaries if subject is a binary and we capture
%% binaries.
sub_binaries(Config) when is_list(Config) ->
- Bin = list_to_binary(lists:seq(1,255)),
- {match,[B,C]}=re:run(Bin,"(a)",[{capture,all,binary}]),
- 255 = binary:referenced_byte_size(B),
- 255 = binary:referenced_byte_size(C),
- {match,[D]}=re:run(Bin,"(a)",[{capture,[1],binary}]),
- 255 = binary:referenced_byte_size(D),
+ %% The GC can auto-convert tiny sub-binaries to heap binaries, so we
+ %% extract large sequences to make the test more stable.
+ Bin = << <<I>> || I <- lists:seq(1, 4096) >>,
+ {match,[B,C]}=re:run(Bin,"a(.+)$",[{capture,all,binary}]),
+ true = byte_size(B) =/= byte_size(C),
+ 4096 = binary:referenced_byte_size(B),
+ 4096 = binary:referenced_byte_size(C),
+ {match,[D]}=re:run(Bin,"a(.+)$",[{capture,[1],binary}]),
+ 4096 = binary:referenced_byte_size(D),
ok.
diff --git a/lib/stdlib/test/re_SUITE_data/testoutput1 b/lib/stdlib/test/re_SUITE_data/testoutput1
index a2b3cffe9d..eff8ecc948 100644
--- a/lib/stdlib/test/re_SUITE_data/testoutput1
+++ b/lib/stdlib/test/re_SUITE_data/testoutput1
@@ -9442,4 +9442,8 @@ No match
\ X
0: X
+/X+(?#comment)?/
+ >XXX<
+ 0: X
+
/-- End of testinput1 --/
diff --git a/lib/stdlib/test/re_SUITE_data/testoutput2 b/lib/stdlib/test/re_SUITE_data/testoutput2
index 811bbefc84..61ed8d9d4e 100644
--- a/lib/stdlib/test/re_SUITE_data/testoutput2
+++ b/lib/stdlib/test/re_SUITE_data/testoutput2
@@ -14705,4 +14705,20 @@ No options
No first char
No need char
+"(?<=(a))\1?b"
+ ab
+ 0: b
+ 1: a
+ aaab
+ 0: ab
+ 1: a
+
+"(?=(a))\1?b"
+ ab
+ 0: ab
+ 1: a
+ aaab
+ 0: ab
+ 1: a
+
/-- End of testinput2 --/
diff --git a/lib/stdlib/test/re_SUITE_data/testoutput5 b/lib/stdlib/test/re_SUITE_data/testoutput5
index bab989ca7e..090e1e1c85 100644
--- a/lib/stdlib/test/re_SUITE_data/testoutput5
+++ b/lib/stdlib/test/re_SUITE_data/testoutput5
@@ -1942,4 +1942,12 @@ Need char = 'z'
0: \x{17f}
0+
+/\C[^\v]+\x80/8
+ [AΏBŀC]
+No match
+
+/\C[^\d]+\x80/8
+ [AΏBŀC]
+No match
+
/-- End of testinput5 --/
diff --git a/lib/stdlib/test/re_SUITE_data/testoutput8 b/lib/stdlib/test/re_SUITE_data/testoutput8
index 17b667a980..4984376d3c 100644
--- a/lib/stdlib/test/re_SUITE_data/testoutput8
+++ b/lib/stdlib/test/re_SUITE_data/testoutput8
@@ -7801,4 +7801,8 @@ No match
** Show all captures ignored after DFA matching
0: a
+/(02-)?[0-9]{3}-[0-9]{3}/
+ 02-123-123
+ 0: 02-123-123
+
/-- End of testinput8 --/
diff --git a/lib/stdlib/test/sets_SUITE.erl b/lib/stdlib/test/sets_SUITE.erl
index bec38000b2..2c1b388d52 100644
--- a/lib/stdlib/test/sets_SUITE.erl
+++ b/lib/stdlib/test/sets_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@
init_per_testcase/2,end_per_testcase/2,
create/1,add_element/1,del_element/1,
subtract/1,intersection/1,union/1,is_subset/1,
- is_set/1,fold/1,filter/1,
+ is_set/1,is_empty/1,fold/1,filter/1,
take_smallest/1,take_largest/1, iterate/1]).
-include_lib("common_test/include/ct.hrl").
@@ -48,7 +48,7 @@ suite() ->
all() ->
[create, add_element, del_element, subtract,
intersection, union, is_subset, is_set, fold, filter,
- take_smallest, take_largest, iterate].
+ take_smallest, take_largest, iterate, is_empty].
groups() ->
[].
@@ -345,6 +345,17 @@ is_set_1(M) ->
false = M(is_set, {}),
M(empty, []).
+is_empty(Config) when is_list(Config) ->
+ test_all(fun is_empty_1/1).
+
+is_empty_1(M) ->
+ S = M(from_list, [blurf]),
+ Empty = M(empty, []),
+
+ true = M(is_empty, Empty),
+ false = M(is_empty, S),
+ M(empty, []).
+
fold(Config) when is_list(Config) ->
test_all([{0,71},{125,129},{254,259},{510,513},{1023,1025},{9999,10001}],
fun fold_1/2).
diff --git a/lib/stdlib/test/sets_test_lib.erl b/lib/stdlib/test/sets_test_lib.erl
index 9f153822a2..e4d476ba54 100644
--- a/lib/stdlib/test/sets_test_lib.erl
+++ b/lib/stdlib/test/sets_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,7 @@ new(Mod, Eq) ->
(from_list, L) -> Mod:from_list(L);
(intersection, {S1,S2}) -> intersection(Mod, Eq, S1, S2);
(intersection, Ss) -> intersection(Mod, Eq, Ss);
- (is_empty, S) -> is_empty(Mod, S);
+ (is_empty, S) -> Mod:is_empty(S);
(is_set, S) -> Mod:is_set(S);
(is_subset, {S,Set}) -> is_subset(Mod, Eq, S, Set);
(iterator, S) -> Mod:iterator(S);
@@ -56,7 +56,7 @@ singleton(Mod, E) ->
add_element(Mod, El, S0) ->
S = Mod:add_element(El, S0),
true = Mod:is_element(El, S),
- false = is_empty(Mod, S),
+ false = Mod:is_empty(S),
true = Mod:is_set(S),
S.
@@ -66,17 +66,10 @@ del_element(Mod, El, S0) ->
true = Mod:is_set(S),
S.
-is_empty(Mod, S) ->
- true = Mod:is_set(S),
- case erlang:function_exported(Mod, is_empty, 1) of
- true -> Mod:is_empty(S);
- false -> Mod:size(S) == 0
- end.
-
intersection(Mod, Equal, S1, S2) ->
S = Mod:intersection(S1, S2),
true = Equal(S, Mod:intersection(S2, S1)),
- Disjoint = is_empty(Mod, S),
+ Disjoint = Mod:is_empty(S),
Disjoint = Mod:is_disjoint(S1, S2),
Disjoint = Mod:is_disjoint(S2, S1),
S.
diff --git a/lib/stdlib/test/shell_SUITE.erl b/lib/stdlib/test/shell_SUITE.erl
index 4f0fdc4c6a..22136d687c 100644
--- a/lib/stdlib/test/shell_SUITE.erl
+++ b/lib/stdlib/test/shell_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@
progex_lc/1, progex_funs/1,
otp_5990/1, otp_6166/1, otp_6554/1,
otp_7184/1, otp_7232/1, otp_8393/1, otp_10302/1, otp_13719/1,
- otp_14285/1, otp_14296/1]).
+ otp_14285/1, otp_14296/1, typed_records/1]).
-export([ start_restricted_from_shell/1,
start_restricted_on_command_line/1,restricted_local/1]).
@@ -74,10 +74,10 @@ suite() ->
{timetrap,{minutes,10}}].
all() ->
- [forget, records, known_bugs, otp_5226, otp_5327,
+ [forget, known_bugs, otp_5226, otp_5327,
otp_5435, otp_5195, otp_5915, otp_5916, {group, bits},
{group, refman}, {group, progex}, {group, tickets},
- {group, restricted}].
+ {group, restricted}, {group, records}].
groups() ->
[{restricted, [],
@@ -86,6 +86,8 @@ groups() ->
{bits, [],
[bs_match_misc_SUITE, bs_match_tail_SUITE,
bs_match_bin_SUITE, bs_construct_SUITE]},
+ {records, [],
+ [records, typed_records]},
{refman, [], [refman_bit_syntax]},
{progex, [],
[progex_bit_syntax, progex_records, progex_lc,
@@ -486,6 +488,48 @@ records(Config) when is_list(Config) ->
ok.
+%% Test of typed record support.
+typed_records(Config) when is_list(Config) ->
+ Test = filename:join(proplists:get_value(priv_dir, Config), "test.hrl"),
+ Contents = <<"-module(test).
+ -record(r0,{f :: any()}).
+ -record(r1,{f1 :: #r1{} | undefined, f2 :: #r0{} | atom()}).
+ -record(r2,{f :: #r2{} | undefined}).
+ ">>,
+ ok = file:write_file(Test, Contents),
+
+ RR1 = "rr(\"" ++ Test ++ "\"),
+ #r1{} = (#r1{f1=#r1{f1=undefined, f2=x}, f2 = #r0{}})#r1.f1,
+ ok.",
+ RR2 = "rr(\"" ++ Test ++ "\"),
+ #r0{} = (#r1{f1=#r1{f1=undefined, f2=x}, f2 = #r0{}})#r1.f2,
+ ok. ",
+ RR3 = "rr(\"" ++ Test ++ "\"),
+ #r1{f2=#r0{}} = (#r1{f1=#r1{f1=undefined, f2=#r0{}}, f2 = x})#r1.f1,
+ ok.",
+ RR4 = "rr(\"" ++ Test ++ "\"),
+ (#r1{f2 = #r0{}})#r1{f2 = x},
+ ok. ",
+ RR5 = "rr(\"" ++ Test ++ "\"),
+ (#r1{f2 = #r0{}})#r1{f1 = #r1{}},
+ ok. ",
+ RR6 = "rr(\"" ++ Test ++ "\"),
+ (#r2{f=#r2{f=undefined}})#r2.f,
+ ok.",
+ RR7 = "rr(\"" ++ Test ++ "\"),
+ #r2{} = (#r2{f=#r2{f=undefined}})#r2.f,
+ ok.",
+ [ok] = scan(RR1),
+ [ok] = scan(RR2),
+ [ok] = scan(RR3),
+ [ok] = scan(RR4),
+ [ok] = scan(RR5),
+ [ok] = scan(RR6),
+ [ok] = scan(RR7),
+
+ file:delete(Test),
+ ok.
+
%% Known bugs.
known_bugs(Config) when is_list(Config) ->
%% erl_eval:merge_bindings/2 cannot handle _removal_ of bindings.
@@ -517,9 +561,10 @@ otp_5226(Config) when is_list(Config) ->
otp_5327(Config) when is_list(Config) ->
"exception error: bad argument" =
comm_err(<<"<<\"hej\":default>>.">>),
+ L1 = erl_anno:new(1),
<<"abc">> =
- erl_parse:normalise({bin,1,[{bin_element,1,{string,1,"abc"},
- default,default}]}),
+ erl_parse:normalise({bin,L1,[{bin_element,L1,{string,L1,"abc"},
+ default,default}]}),
[<<"abc">>] = scan(<<"<<(<<\"abc\">>):3/binary>>.">>),
[<<"abc">>] = scan(<<"<<(<<\"abc\">>)/binary>>.">>),
"exception error: bad argument" =
@@ -532,9 +577,9 @@ otp_5327(Config) when is_list(Config) ->
comm_err(<<"<<10:default>>.">>),
[<<98,1:1>>] = scan(<<"<<3:3,5:6>>.">>),
{'EXIT',{badarg,_}} =
- (catch erl_parse:normalise({bin,1,[{bin_element,1,{integer,1,17},
- {atom,1,all},
- default}]})),
+ (catch erl_parse:normalise({bin,L1,[{bin_element,L1,{integer,L1,17},
+ {atom,L1,all},
+ default}]})),
[<<-20/signed>>] = scan(<<"<<-20/signed>> = <<-20>>.">>),
[<<-300:16/signed>>] =
scan(<<"<<-300:16/signed>> = <<-300:16>>.">>),
@@ -2735,12 +2780,12 @@ otp_10302(Config) when is_list(Config) ->
rpc:call(Node,shell, prompt_func, [default]),
_ = shell:prompt_func(default),
- %% Test lib:format_exception() (cf. OTP-6554)
+ %% Test erl_error:format_exception() (cf. OTP-6554)
Test6 =
<<"begin
A = <<\"\\xaa\">>,
S = lists:flatten(io_lib:format(\"~p/~p.\", [A, A])),
- {ok, Ts, _} = erl_scan:string(S, 1, [unicode]),
+ {ok, Ts, _} = erl_scan:string(S, 1),
{ok, Es} = erl_parse:parse_exprs(Ts),
B = erl_eval:new_bindings(),
erl_eval:exprs(Es, B)
@@ -2753,7 +2798,7 @@ otp_10302(Config) when is_list(Config) ->
<<"io:setopts([{encoding,utf8}]).
A = <<\"\\xaa\">>,
S = lists:flatten(io_lib:format(\"~p/~p.\", [A, A])),
- {ok, Ts, _} = erl_scan:string(S, 1, [unicode]),
+ {ok, Ts, _} = erl_scan:string(S, 1),
{ok, Es} = erl_parse:parse_exprs(Ts),
B = erl_eval:new_bindings(),
erl_eval:exprs(Es, B).">>,
@@ -2765,7 +2810,7 @@ otp_10302(Config) when is_list(Config) ->
<<"begin
A = [1089],
S = lists:flatten(io_lib:format(\"~tp/~tp.\", [A, A])),
- {ok, Ts, _} = erl_scan:string(S, 1, [unicode]),
+ {ok, Ts, _} = erl_scan:string(S, 1),
{ok, Es} = erl_parse:parse_exprs(Ts),
B = erl_eval:new_bindings(),
erl_eval:exprs(Es, B)
@@ -2777,7 +2822,7 @@ otp_10302(Config) when is_list(Config) ->
<<"io:setopts([{encoding,utf8}]).
A = [1089],
S = lists:flatten(io_lib:format(\"~tp/~tp.\", [A, A])),
- {ok, Ts, _} = erl_scan:string(S, 1, [unicode]),
+ {ok, Ts, _} = erl_scan:string(S, 1),
{ok, Es} = erl_parse:parse_exprs(Ts),
B = erl_eval:new_bindings(),
erl_eval:exprs(Es, B).">>,
@@ -2896,7 +2941,7 @@ otp_14296(Config) when is_list(Config) ->
end(),
fun() ->
- Port = open_port({spawn, "ls"}, [line]),
+ Port = open_port({spawn, "ls"}, [{line,1}]),
KnownPort = erlang:port_to_list(Port),
S = KnownPort ++ ".",
R = KnownPort ++ ".\n",
@@ -2922,10 +2967,10 @@ otp_14296(Config) when is_list(Config) ->
R = t(S)
end(),
- %% Test lib:extended_parse_term/1
+ %% Test erl_eval:extended_parse_term/1
TF = fun(S) ->
{ok, Ts, _} = erl_scan:string(S++".", 1, [text]),
- case lib:extended_parse_term(Ts) of
+ case erl_eval:extended_parse_term(Ts) of
{ok, Term} -> Term;
{error, _}=Error -> Error
end
@@ -2968,7 +3013,7 @@ scan(B) ->
scan(t(B), F).
scan(S0, F) ->
- case erl_scan:tokens([], S0, 1, [unicode]) of
+ case erl_scan:tokens([], S0, 1) of
{done,{ok,Ts,_},S} ->
[F(Ts) | scan(S, F)];
_Else ->
diff --git a/lib/stdlib/test/stdlib.spec b/lib/stdlib/test/stdlib.spec
index 3768e494b2..9c625091a8 100644
--- a/lib/stdlib/test/stdlib.spec
+++ b/lib/stdlib/test/stdlib.spec
@@ -1 +1,4 @@
{suites,"../stdlib_test",all}.
+{skip_groups,"../stdlib_test",stdlib_bench_SUITE,
+ [base64,gen_server,gen_statem,unicode],
+ "Benchmark only"}.
diff --git a/lib/stdlib/test/stdlib_bench.spec b/lib/stdlib/test/stdlib_bench.spec
new file mode 100644
index 0000000000..7a0da811a0
--- /dev/null
+++ b/lib/stdlib/test/stdlib_bench.spec
@@ -0,0 +1,10 @@
+%% Needed to compile ,unicode_util_SUITE and string_SUITE...
+{cases,"../stdlib_test",unicode_util_SUITE, []}.
+{cases,"../stdlib_test",string_SUITE, []}.
+{skip_suites,"../stdlib_test",unicode_util_SUITE, "bench only"}.
+{skip_suites,"../stdlib_test",string_SUITE, "bench only"}.
+
+{suites,"../stdlib_test",[stdlib_bench_SUITE]}.
+{skip_groups,"../stdlib_test",stdlib_bench_SUITE,
+ [gen_server_comparison,gen_statem_comparison],
+ "Not a benchmark"}.
diff --git a/lib/stdlib/test/stdlib_bench_SUITE.erl b/lib/stdlib/test/stdlib_bench_SUITE.erl
new file mode 100644
index 0000000000..2364e8376f
--- /dev/null
+++ b/lib/stdlib/test/stdlib_bench_SUITE.erl
@@ -0,0 +1,546 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012-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(stdlib_bench_SUITE).
+-compile([export_all, nowarn_export_all]).
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+suite() -> [{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]}].
+
+
+all() ->
+ [{group,unicode},{group,base64},
+ {group,gen_server},{group,gen_statem},
+ {group,gen_server_comparison},{group,gen_statem_comparison}].
+
+groups() ->
+ [{unicode,[{repeat,5}],
+ [norm_nfc_list, norm_nfc_deep_l, norm_nfc_binary,
+ string_lexemes_list, string_lexemes_binary
+ ]},
+ {base64,[{repeat,5}],
+ [decode_binary, decode_binary_to_string,
+ decode_list, decode_list_to_string,
+ encode_binary, encode_binary_to_string,
+ encode_list, encode_list_to_string,
+ mime_binary_decode, mime_binary_decode_to_string,
+ mime_list_decode, mime_list_decode_to_string]},
+ {gen_server, [{repeat,5}], cases(gen_server)},
+ {gen_statem, [{repeat,3}], cases(gen_statem)},
+ {gen_server_comparison, [],
+ [single_small, single_medium, single_big,
+ sched_small, sched_medium, sched_big,
+ multi_small, multi_medium, multi_big]},
+ {gen_statem_comparison, [],
+ [single_small, single_big,
+ sched_small, sched_big,
+ multi_small, multi_big]}].
+
+cases(gen_server) ->
+ [simple, simple_timer, simple_mon, simple_timer_mon,
+ generic, generic_timer];
+cases(gen_statem) ->
+ [generic, generic_fsm, generic_fsm_transit,
+ generic_statem, generic_statem_transit,
+ generic_statem_complex].
+
+init_per_group(gen_server, Config) ->
+ compile_servers(Config),
+ [{benchmark_suite,"stdlib_gen_server"}|Config];
+init_per_group(gen_statem, Config) ->
+ compile_servers(Config),
+ [{benchmark_suite,"stdlib_gen_statem"}|Config];
+init_per_group(gen_server_comparison, Config) ->
+ compile_servers(Config),
+ [{cases,cases(gen_server)},
+ {benchmark_suite,"stdlib_gen_server"}|Config];
+init_per_group(gen_statem_comparison, Config) ->
+ compile_servers(Config),
+ [{cases,cases(gen_statem)},
+ {benchmark_suite,"stdlib_gen_statem"}|Config];
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(Config) ->
+ Config.
+
+init_per_testcase(_Func, Conf) ->
+ Conf.
+
+end_per_testcase(_Func, _Conf) ->
+ ok.
+
+
+compile_servers(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Files = filelib:wildcard(filename:join(DataDir, "{simple,generic}*.erl")),
+ _ = [{ok, _} = compile:file(File) || File <- Files],
+ ok.
+
+comment(Value) ->
+ C = lists:flatten(io_lib:format("~p", [Value])),
+ {comment, C}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-define(REPEAT_NORM, 5).
+
+norm_nfc_list(Config) ->
+ Bin = norm_data(Config),
+ {_N, Mean, _Stddev, Res} = unicode_util_SUITE:time_count(nfc, list, Bin, ?REPEAT_NORM),
+ comment(report(1000.0*Res / Mean)).
+
+norm_nfc_deep_l(Config) ->
+ Bin = norm_data(Config),
+ {_N, Mean, _Stddev, Res} = unicode_util_SUITE:time_count(nfc, deep_l, Bin, ?REPEAT_NORM),
+ comment(report(1000.0*Res / Mean)).
+
+norm_nfc_binary(Config) ->
+ Bin = norm_data(Config),
+ {_N, Mean, _Stddev, Res} = unicode_util_SUITE:time_count(nfc, binary, Bin, ?REPEAT_NORM),
+ comment(report(1000.0*Res / Mean)).
+
+
+string_lexemes_list(Config) ->
+ %% Use nth_lexeme instead of lexemes to avoid building a result of
+ %% large lists which causes large differences between test runs, gc?
+ Bin = norm_data(Config),
+ Fun = fun(Str) -> string:nth_lexeme(Str, 200000, [$;,$\n,$\r]), 200000 end,
+ {_N, Mean, _Stddev, Res} = string_SUITE:time_func(Fun, list, Bin, 15),
+ comment(report(1000.0*Res / Mean)).
+
+string_lexemes_binary(Config) ->
+ %% Use nth_lexeme instead of lexemes to avoid building a result of
+ %% large lists which causes large differences between test runs, gc?
+ Bin = norm_data(Config),
+ Fun = fun(Str) -> string:nth_lexeme(Str, 200000, [$;,$\n,$\r]), 200000 end,
+ {_N, Mean, _Stddev, Res} = string_SUITE:time_func(Fun, binary, Bin, ?REPEAT_NORM),
+ comment(report(1000.0*Res / Mean)).
+
+%%%
+report(Tps) ->
+ ct_event:notify(#event{name = benchmark_data,
+ data = [{suite,"stdlib_unicode"},{value,round(Tps)}]}),
+ Tps.
+
+norm_data(Config) ->
+ DataDir0 = proplists:get_value(data_dir, Config),
+ DataDir = filename:join(lists:droplast(filename:split(DataDir0))),
+ File = filename:join([DataDir,"unicode_util_SUITE_data","NormalizationTest.txt"]),
+ {ok, Bin} = file:read_file(File),
+ Bin.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+decode_binary(_Config) ->
+ comment(test(decode, encoded_binary())).
+
+decode_binary_to_string(_Config) ->
+ comment(test(decode_to_string, encoded_binary())).
+
+decode_list(_Config) ->
+ comment(test(decode, encoded_list())).
+
+decode_list_to_string(_Config) ->
+ comment(test(decode_to_string, encoded_list())).
+
+encode_binary(_Config) ->
+ comment(test(encode, binary())).
+
+encode_binary_to_string(_Config) ->
+ comment(test(encode_to_string, binary())).
+
+encode_list(_Config) ->
+ comment(test(encode, list())).
+
+encode_list_to_string(_Config) ->
+ comment(test(encode_to_string, list())).
+
+mime_binary_decode(_Config) ->
+ comment(test(mime_decode, encoded_binary())).
+
+mime_binary_decode_to_string(_Config) ->
+ comment(test(mime_decode_to_string, encoded_binary())).
+
+mime_list_decode(_Config) ->
+ comment(test(mime_decode, encoded_list())).
+
+mime_list_decode_to_string(_Config) ->
+ comment(test(mime_decode_to_string, encoded_list())).
+
+-define(SIZE, 10000).
+-define(N, 1000).
+
+encoded_binary() ->
+ list_to_binary(encoded_list()).
+
+encoded_list() ->
+ L = random_byte_list(round(?SIZE*0.75)),
+ base64:encode_to_string(L).
+
+binary() ->
+ list_to_binary(list()).
+
+list() ->
+ random_byte_list(?SIZE).
+
+test(Func, Data) ->
+ F = fun() -> loop(?N, Func, Data) end,
+ {Time, ok} = timer:tc(fun() -> lspawn(F) end),
+ report_base64(Time).
+
+loop(0, _F, _D) -> garbage_collect(), ok;
+loop(N, F, D) ->
+ _ = base64:F(D),
+ loop(N - 1, F, D).
+
+lspawn(Fun) ->
+ {Pid, Ref} = spawn_monitor(fun() -> exit(Fun()) end),
+ receive
+ {'DOWN', Ref, process, Pid, Rep} -> Rep
+ end.
+
+report_base64(Time) ->
+ Tps = round((?N*1000000)/Time),
+ ct_event:notify(#event{name = benchmark_data,
+ data = [{suite, "stdlib_base64"},
+ {value, Tps}]}),
+ Tps.
+
+%% Copied from base64_SUITE.erl.
+
+random_byte_list(N) ->
+ random_byte_list(N, []).
+
+random_byte_list(0, Acc) ->
+ Acc;
+random_byte_list(N, Acc) ->
+ random_byte_list(N-1, [rand:uniform(255)|Acc]).
+
+make_big_binary(N) ->
+ list_to_binary(mbb(N, [])).
+
+mbb(N, Acc) when N > 256 ->
+ B = list_to_binary(lists:seq(0, 255)),
+ mbb(N - 256, [B | Acc]);
+mbb(N, Acc) ->
+ B = list_to_binary(lists:seq(0, N-1)),
+ lists:reverse(Acc, B).
+
+simple(Config) when is_list(Config) ->
+ comment(do_tests(simple, single_small, Config)).
+
+simple_timer(Config) when is_list(Config) ->
+ comment(do_tests(simple_timer, single_small, Config)).
+
+simple_mon(Config) when is_list(Config) ->
+ comment(do_tests(simple_mon, single_small, Config)).
+
+simple_timer_mon(Config) when is_list(Config) ->
+ comment(do_tests(simple_timer_mon, single_small, Config)).
+
+generic(Config) when is_list(Config) ->
+ comment(do_tests(generic, single_small, Config)).
+
+generic_timer(Config) when is_list(Config) ->
+ comment(do_tests(generic_timer, single_small, Config)).
+
+generic_statem(Config) when is_list(Config) ->
+ comment(do_tests(generic_statem, single_small, Config)).
+
+generic_statem_transit(Config) when is_list(Config) ->
+ comment(do_tests(generic_statem_transit, single_small, Config)).
+
+generic_statem_complex(Config) when is_list(Config) ->
+ comment(do_tests(generic_statem_complex, single_small, Config)).
+
+generic_fsm(Config) when is_list(Config) ->
+ comment(do_tests(generic_fsm, single_small, Config)).
+
+generic_fsm_transit(Config) when is_list(Config) ->
+ comment(do_tests(generic_fsm_transit, single_small, Config)).
+
+single_small(Config) when is_list(Config) ->
+ comparison(?config(cases, Config), single_small, Config).
+
+single_medium(Config) when is_list(Config) ->
+ comparison(?config(cases, Config), single_medium, Config).
+
+single_big(Config) when is_list(Config) ->
+ comparison(?config(cases, Config), single_big, Config).
+
+sched_small(Config) when is_list(Config) ->
+ comparison(?config(cases, Config), sched_small, Config).
+
+sched_medium(Config) when is_list(Config) ->
+ comparison(?config(cases, Config), sched_medium, Config).
+
+sched_big(Config) when is_list(Config) ->
+ comparison(?config(cases, Config), sched_big, Config).
+
+multi_small(Config) when is_list(Config) ->
+ comparison(?config(cases, Config), multi_small, Config).
+
+multi_medium(Config) when is_list(Config) ->
+ comparison(?config(cases, Config), multi_medium, Config).
+
+multi_big(Config) when is_list(Config) ->
+ comparison(?config(cases, Config), multi_big, Config).
+
+comparison(Cases, Kind, Config) ->
+ Cases = ?config(cases, Config),
+ [RefResult|_] = Results =
+ [do_tests(Case, Kind, Config) || Case <- Cases],
+ Normalized = [norm(Result, RefResult) || Result <- Results],
+ {Parallelism, Message} = bench_params(Kind),
+ Wordsize = erlang:system_info(wordsize),
+ MSize = Wordsize * erts_debug:flat_size(Message),
+ What = io_lib:format("#parallel gen_server instances: ~.4w, "
+ "message flat size: ~.5w bytes",
+ [Parallelism, MSize]),
+ Format =
+ lists:flatten(
+ ["~s: "] ++
+ [[atom_to_list(Case),": ~s "] || Case <- Cases]),
+ C = lists:flatten(io_lib:format(Format, [What] ++ Normalized)),
+ {comment, C}.
+
+norm(T, Ref) ->
+ try Ref / T of
+ Norm ->
+ io_lib:format("~.2f", [Norm])
+ catch error:badarith ->
+ "---"
+ end.
+
+-define(MAX_TIME_SECS, 3). % s
+-define(MAX_TIME, 1000 * ?MAX_TIME_SECS). % ms
+-define(CALLS_PER_LOOP, 5).
+
+do_tests(Test, ParamSet, Config) ->
+ BenchmarkSuite = ?config(benchmark_suite, Config),
+ {Client, ServerMod} = bench(Test),
+ {Parallelism, Message} = bench_params(ParamSet),
+ Fun = create_clients(Message, ServerMod, Client, Parallelism),
+ {TotalLoops, AllPidTime} = run_test(Fun),
+ try ?CALLS_PER_LOOP * round((1000 * TotalLoops) / AllPidTime) of
+ PerSecond ->
+ ct_event:notify(
+ #event{
+ name = benchmark_data,
+ data = [{suite,BenchmarkSuite},{value,PerSecond}]}),
+ PerSecond
+ catch error:badarith ->
+ "Time measurement is not working"
+ end.
+
+-define(COUNTER, n).
+
+simple_client(N, M, P) ->
+ put(?COUNTER, N),
+ _ = simple_server:reply(P, M),
+ _ = simple_server:reply(P, M),
+ _ = simple_server:reply(P, M),
+ _ = simple_server:reply(P, M),
+ _ = simple_server:reply(P, M),
+ simple_client(N+1, M, P).
+
+simple_client_timer(N, M, P) ->
+ put(?COUNTER, N),
+ _ = simple_server_timer:reply(P, M),
+ _ = simple_server_timer:reply(P, M),
+ _ = simple_server_timer:reply(P, M),
+ _ = simple_server_timer:reply(P, M),
+ _ = simple_server_timer:reply(P, M),
+ simple_client_timer(N+1, M, P).
+
+simple_client_mon(N, M, P) ->
+ put(?COUNTER, N),
+ _ = simple_server_mon:reply(P, M),
+ _ = simple_server_mon:reply(P, M),
+ _ = simple_server_mon:reply(P, M),
+ _ = simple_server_mon:reply(P, M),
+ _ = simple_server_mon:reply(P, M),
+ simple_client_mon(N+1, M, P).
+
+simple_client_timer_mon(N, M, P) ->
+ put(?COUNTER, N),
+ _ = simple_server_timer_mon:reply(P, M),
+ _ = simple_server_timer_mon:reply(P, M),
+ _ = simple_server_timer_mon:reply(P, M),
+ _ = simple_server_timer_mon:reply(P, M),
+ _ = simple_server_timer_mon:reply(P, M),
+ simple_client_timer_mon(N+1, M, P).
+
+generic_client(N, M, P) ->
+ put(?COUNTER, N),
+ _ = generic_server:reply(P, M),
+ _ = generic_server:reply(P, M),
+ _ = generic_server:reply(P, M),
+ _ = generic_server:reply(P, M),
+ _ = generic_server:reply(P, M),
+ generic_client(N+1, M, P).
+
+generic_timer_client(N, M, P) ->
+ put(?COUNTER, N),
+ _ = generic_server_timer:reply(P, M),
+ _ = generic_server_timer:reply(P, M),
+ _ = generic_server_timer:reply(P, M),
+ _ = generic_server_timer:reply(P, M),
+ _ = generic_server_timer:reply(P, M),
+ generic_timer_client(N+1, M, P).
+
+generic_statem_client(N, M, P) ->
+ put(?COUNTER, N),
+ _ = generic_statem:reply(P, M),
+ _ = generic_statem:reply(P, M),
+ _ = generic_statem:reply(P, M),
+ _ = generic_statem:reply(P, M),
+ _ = generic_statem:reply(P, M),
+ generic_statem_client(N+1, M, P).
+
+generic_statem_transit_client(N, M, P) ->
+ put(?COUNTER, N),
+ _ = generic_statem:transit(P, M),
+ _ = generic_statem:transit(P, M),
+ _ = generic_statem:transit(P, M),
+ _ = generic_statem:transit(P, M),
+ _ = generic_statem:transit(P, M),
+ generic_statem_transit_client(N+1, M, P).
+
+generic_statem_complex_client(N, M, P) ->
+ put(?COUNTER, N),
+ _ = generic_statem:reply(P, M),
+ _ = generic_statem:reply(P, M),
+ _ = generic_statem:reply(P, M),
+ _ = generic_statem:reply(P, M),
+ _ = generic_statem:reply(P, M),
+ generic_statem_complex_client(N+1, M, P).
+
+generic_fsm_client(N, M, P) ->
+ put(?COUNTER, N),
+ _ = generic_fsm:reply(P, M),
+ _ = generic_fsm:reply(P, M),
+ _ = generic_fsm:reply(P, M),
+ _ = generic_fsm:reply(P, M),
+ _ = generic_fsm:reply(P, M),
+ generic_fsm_client(N+1, M, P).
+
+generic_fsm_transit_client(N, M, P) ->
+ put(?COUNTER, N),
+ _ = generic_fsm:transit(P, M),
+ _ = generic_fsm:transit(P, M),
+ _ = generic_fsm:transit(P, M),
+ _ = generic_fsm:transit(P, M),
+ _ = generic_fsm:transit(P, M),
+ generic_fsm_transit_client(N+1, M, P).
+
+bench(simple) ->
+ {fun simple_client/3, simple_server};
+bench(simple_timer) ->
+ {fun simple_client_timer/3, simple_server_timer};
+bench(simple_mon) ->
+ {fun simple_client_mon/3, simple_server_mon};
+bench(simple_timer_mon) ->
+ {fun simple_client_timer_mon/3, simple_server_timer_mon};
+bench(generic) ->
+ {fun generic_client/3, generic_server};
+bench(generic_timer) ->
+ {fun generic_timer_client/3, generic_server_timer};
+bench(generic_statem) ->
+ {fun generic_statem_client/3, generic_statem};
+bench(generic_statem_transit) ->
+ {fun generic_statem_transit_client/3, generic_statem};
+bench(generic_statem_complex) ->
+ {fun generic_statem_complex_client/3, generic_statem_complex};
+bench(generic_fsm) ->
+ {fun generic_fsm_client/3, generic_fsm};
+bench(generic_fsm_transit) ->
+ {fun generic_fsm_transit_client/3, generic_fsm}.
+
+%% -> {Parallelism, MessageTerm}
+bench_params(single_small) -> {1, small()};
+bench_params(single_medium) -> {1, medium()};
+bench_params(single_big) -> {1, big()};
+bench_params(sched_small) -> {parallelism(), small()};
+bench_params(sched_medium) -> {parallelism(), medium()};
+bench_params(sched_big) -> {parallelism(), big()};
+bench_params(multi_small) -> {400, small()};
+bench_params(multi_medium) -> {400, medium()};
+bench_params(multi_big) -> {400, big()}.
+
+small() ->
+ small.
+
+medium() ->
+ lists:seq(1, 50).
+
+big() ->
+ lists:seq(1, 1000).
+
+parallelism() ->
+ case erlang:system_info(multi_scheduling) of
+ enabled -> erlang:system_info(schedulers_online);
+ _ -> 1
+ end.
+
+create_clients(M, ServerMod, Client, Parallel) ->
+ fun() ->
+ State = term,
+ ServerPid = ServerMod:start(State),
+ PidRefs = [spawn_monitor(fun() -> Client(0, M, ServerPid) end) ||
+ _ <- lists:seq(1, Parallel)],
+ timer:sleep(?MAX_TIME),
+ try
+ AllPidsN = collect(PidRefs, []),
+ TotalLoops = lists:sum(AllPidsN),
+ TotalLoops
+ after
+ ok = ServerMod:stop(ServerPid)
+ end
+ end.
+
+collect([], Result) ->
+ Result;
+collect([{Pid, Ref}|PidRefs], Result) ->
+ N = case erlang:process_info(Pid, dictionary) of
+ {dictionary, Dict} ->
+ {?COUNTER, N0} = lists:keyfind(?COUNTER, 1, Dict),
+ N0;
+ undefined -> % Process did not start in ?MAX_TIME_SECS.
+ 0
+ end,
+ exit(Pid, kill),
+ receive {'DOWN', Ref, _, _, _} -> ok end,
+ collect(PidRefs, [N|Result]).
+
+run_test(Test) ->
+ {T1, _} = statistics(runtime),
+ Result = Test(),
+ {T2, _} = statistics(runtime),
+ {Result, T2 - T1}.
diff --git a/lib/stdlib/test/stdlib_bench_SUITE_data/generic_fsm.erl b/lib/stdlib/test/stdlib_bench_SUITE_data/generic_fsm.erl
new file mode 100644
index 0000000000..50f7df7a2a
--- /dev/null
+++ b/lib/stdlib/test/stdlib_bench_SUITE_data/generic_fsm.erl
@@ -0,0 +1,59 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(generic_fsm).
+
+-export([start/1, reply/2, transit/2, stop/1]).
+
+-export([init/1, terminate/3]).
+-export([state1/3, state2/3]).
+
+-behaivour(gen_fsm).
+
+
+%% API
+
+start(Data) ->
+ {ok, Pid} = gen_fsm:start(?MODULE, Data, []),
+ Pid.
+
+stop(P) ->
+ ok = gen_fsm:stop(P).
+
+reply(S, M) ->
+ gen_fsm:sync_send_event(S, {reply, M}, infinity).
+
+transit(S, M) ->
+ gen_fsm:sync_send_event(S, {transit, M}, infinity).
+
+%% Implementation
+
+init(Data) ->
+ {ok, state1, Data}.
+
+terminate(_Reason, _State, _Data) ->
+ ok.
+
+state1({reply, M}, _From, Data) ->
+ {reply, M, ?FUNCTION_NAME, Data};
+state1({transit, M}, _From, Data) ->
+ {reply, M, state2, Data}.
+
+state2({transit, M}, _From, Data) ->
+ {reply, M, state1, Data}.
diff --git a/lib/stdlib/test/stdlib_bench_SUITE_data/generic_server.erl b/lib/stdlib/test/stdlib_bench_SUITE_data/generic_server.erl
new file mode 100644
index 0000000000..abd61dcdef
--- /dev/null
+++ b/lib/stdlib/test/stdlib_bench_SUITE_data/generic_server.erl
@@ -0,0 +1,31 @@
+-module(generic_server).
+
+-export([start/1, reply/2, stop/1]).
+
+-export([handle_call/3, handle_cast/2, init/1, terminate/2]).
+
+-behaviour(gen_server).
+
+-define(GEN_SERVER, gen_server).
+
+start(State) ->
+ {ok, Pid} = ?GEN_SERVER:start(?MODULE, State, []),
+ Pid.
+
+init(State) ->
+ {ok, State}.
+
+stop(P) ->
+ ok = ?GEN_SERVER:stop(P).
+
+reply(S, M) ->
+ _M = ?GEN_SERVER:call(S, {reply, M}, infinity).
+
+handle_call({reply, M}, _From, State) ->
+ {reply, M, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
diff --git a/lib/stdlib/test/stdlib_bench_SUITE_data/generic_server_timer.erl b/lib/stdlib/test/stdlib_bench_SUITE_data/generic_server_timer.erl
new file mode 100644
index 0000000000..0faa30207d
--- /dev/null
+++ b/lib/stdlib/test/stdlib_bench_SUITE_data/generic_server_timer.erl
@@ -0,0 +1,31 @@
+-module(generic_server_timer).
+
+-export([start/1, reply/2, stop/1]).
+
+-export([handle_call/3, handle_cast/2, init/1, terminate/2]).
+
+-behaviour(gen_server).
+
+-define(GEN_SERVER, gen_server).
+
+start(State) ->
+ {ok, Pid} = ?GEN_SERVER:start(?MODULE, State, []),
+ Pid.
+
+init(State) ->
+ {ok, State}.
+
+stop(P) ->
+ ok = ?GEN_SERVER:stop(P).
+
+reply(S, M) ->
+ ?GEN_SERVER:call(S, {reply, M}).
+
+handle_call({reply, M}, _From, State) ->
+ {reply, M, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
diff --git a/lib/stdlib/test/stdlib_bench_SUITE_data/generic_statem.erl b/lib/stdlib/test/stdlib_bench_SUITE_data/generic_statem.erl
new file mode 100644
index 0000000000..2e0491f060
--- /dev/null
+++ b/lib/stdlib/test/stdlib_bench_SUITE_data/generic_statem.erl
@@ -0,0 +1,58 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(generic_statem).
+
+-export([start/1, reply/2, transit/2, stop/1]).
+
+-export([callback_mode/0, init/1]).
+-export([state1/3, state2/3]).
+
+-behaviour(gen_statem).
+
+%% API
+
+start(Data) ->
+ {ok, Pid} = gen_statem:start(?MODULE, Data, []),
+ Pid.
+
+stop(P) ->
+ ok = gen_statem:stop(P).
+
+reply(S, M) ->
+ gen_statem:call(S, {reply, M}, infinity).
+
+transit(S, M) ->
+ gen_statem:call(S, {transit, M}, infinity).
+
+%% Implementation
+
+callback_mode() ->
+ state_functions.
+
+init(Data) ->
+ {ok, state1, Data}.
+
+state1({call, From}, {reply, M}, Data) ->
+ {keep_state, Data, {reply, From, M}};
+state1({call, From}, {transit, M}, Data) ->
+ {next_state, state2, Data, {reply, From, M}}.
+
+state2({call, From}, {transit, M}, Data) ->
+ {next_state, state1, Data, {reply, From, M}}.
diff --git a/lib/stdlib/test/stdlib_bench_SUITE_data/generic_statem_complex.erl b/lib/stdlib/test/stdlib_bench_SUITE_data/generic_statem_complex.erl
new file mode 100644
index 0000000000..983227d281
--- /dev/null
+++ b/lib/stdlib/test/stdlib_bench_SUITE_data/generic_statem_complex.erl
@@ -0,0 +1,66 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(generic_statem_complex).
+
+-export([start/1, reply/2, stop/1]).
+
+-export([callback_mode/0, init/1]).
+-export([state1/3, state2/3, state3/3]).
+
+-behaviour(gen_statem).
+
+%% API
+
+start(Data) ->
+ {ok, Pid} = gen_statem:start(?MODULE, Data, []),
+ Pid.
+
+stop(P) ->
+ ok = gen_statem:stop(P).
+
+reply(S, M) ->
+ gen_statem:call(S, {reply, M}, infinity).
+
+%% Implementation
+
+callback_mode() ->
+ [state_functions,state_enter].
+
+init(Data) ->
+ {ok, state1, Data}.
+
+state1(enter, _, Data) ->
+ {keep_state, Data,
+ {state_timeout, 5000, t1}};
+state1({call, _From}, {reply, _M}, Data) ->
+ {next_state, state2, Data,
+ [postpone,{next_event,internal,e}]}.
+
+state2(enter, _, _Data) ->
+ keep_state_and_data;
+state2(internal, e, Data) ->
+ {next_state, state3, Data}.
+
+state3(enter, _, Data) ->
+ {keep_state, Data,
+ {state_timeout, 5000, t3}};
+state3({call, From}, {reply, M}, Data) ->
+ {next_state, state1, Data,
+ {reply, From, M}}.
diff --git a/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server.erl b/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server.erl
new file mode 100644
index 0000000000..bd43f686e8
--- /dev/null
+++ b/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server.erl
@@ -0,0 +1,31 @@
+-module(simple_server).
+
+%% Local process. No timer. No monitor.
+
+-export([start/1, reply/2, stop/1]).
+
+start(State) ->
+ spawn(fun() -> loop(State) end).
+
+stop(P) ->
+ P ! {stop, self()},
+ receive
+ ok ->
+ ok
+ end.
+
+loop(S) ->
+ receive
+ {reply, P, M} ->
+ P ! M,
+ loop(S);
+ {stop, P} ->
+ P ! ok
+ end.
+
+reply(P, M) ->
+ P ! {reply, self(), M},
+ receive
+ M ->
+ M
+ end.
diff --git a/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_mon.erl b/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_mon.erl
new file mode 100644
index 0000000000..9b5ace5586
--- /dev/null
+++ b/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_mon.erl
@@ -0,0 +1,33 @@
+-module(simple_server_mon).
+
+%% Local process. No timer. Monitor.
+
+-export([start/1, reply/2, stop/1]).
+
+start(State) ->
+ spawn(fun() -> loop(State) end).
+
+stop(P) ->
+ P ! {stop, self()},
+ receive
+ ok ->
+ ok
+ end.
+
+loop(S) ->
+ receive
+ {reply, P, Mref, M} ->
+ P ! {ok, Mref, M},
+ loop(S);
+ {stop, P} ->
+ P ! ok
+ end.
+
+reply(P, M) ->
+ Mref = erlang:monitor(process, P),
+ P ! {reply, self(), Mref, M},
+ receive
+ {ok, Mref, M} ->
+ erlang:demonitor(Mref, [flush]),
+ ok
+ end.
diff --git a/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_timer.erl b/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_timer.erl
new file mode 100644
index 0000000000..82381e1fdf
--- /dev/null
+++ b/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_timer.erl
@@ -0,0 +1,33 @@
+-module(simple_server_timer).
+
+%% Local process. Timer. No monitor.
+
+-export([start/1, reply/2, stop/1]).
+
+start(State) ->
+ spawn(fun() -> loop(State) end).
+
+stop(P) ->
+ P ! {stop, self()},
+ receive
+ ok ->
+ ok
+ end.
+
+loop(S) ->
+ receive
+ {reply, P, M} ->
+ P ! M,
+ loop(S);
+ {stop, P} ->
+ P ! ok
+ end.
+
+reply(P, M) ->
+ P ! {reply, self(), M},
+ receive
+ M ->
+ M
+ after 100 ->
+ exit(fel)
+ end.
diff --git a/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_timer_mon.erl b/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_timer_mon.erl
new file mode 100644
index 0000000000..6124ca29c2
--- /dev/null
+++ b/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_timer_mon.erl
@@ -0,0 +1,35 @@
+-module(simple_server_timer_mon).
+
+%% Local process. Timer. Monitor.
+
+-export([start/1, reply/2, stop/1]).
+
+start(State) ->
+ spawn(fun() -> loop(State) end).
+
+stop(P) ->
+ P ! {stop, self()},
+ receive
+ ok ->
+ ok
+ end.
+
+loop(S) ->
+ receive
+ {reply, P, Mref, M} ->
+ P ! {ok, Mref, M},
+ loop(S);
+ {stop, P} ->
+ P ! ok
+ end.
+
+reply(P, M) ->
+ Mref = erlang:monitor(process, P),
+ P ! {reply, self(), Mref, M},
+ receive
+ {ok, Mref, M} ->
+ erlang:demonitor(Mref, [flush]),
+ ok
+ after 100 ->
+ exit(fel)
+ end.
diff --git a/lib/stdlib/test/string_SUITE.erl b/lib/stdlib/test/string_SUITE.erl
index 90f980c0e5..251e09121c 100644
--- a/lib/stdlib/test/string_SUITE.erl
+++ b/lib/stdlib/test/string_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -47,7 +47,8 @@
-export([to_upper_to_lower/1]).
%% Run tests when debugging them
--export([debug/0]).
+-export([debug/0, time_func/4]).
+-compile([nowarn_deprecated_function]).
suite() ->
[{ct_hooks,[ts_install_cth]},
@@ -92,14 +93,11 @@ end_per_testcase(_Case, _Config) ->
ok.
debug() ->
- Config = [{data_dir, ?MODULE_STRING++"_data"}],
+ Config = [{data_dir, "./" ++ ?MODULE_STRING++"_data"}],
[io:format("~p:~p~n",[Test,?MODULE:Test(Config)]) ||
{_,Tests} <- groups(), Test <- Tests].
-define(TEST(B,C,D), test(?LINE,?FUNCTION_NAME,B,C,D, true)).
--define(TEST_EQ(B,C,D),
- test(?LINE,?FUNCTION_NAME,B,C,D, true),
- test(?LINE,?FUNCTION_NAME,hd(C),[B|tl(C),D, true)).
-define(TEST_NN(B,C,D),
test(?LINE,?FUNCTION_NAME,B,C,D, false),
@@ -294,6 +292,7 @@ trim(_) ->
?TEST(["..h", ".e", <<"j..">>], [both, ". "], "h.ej"),
?TEST(["..h", <<".ejsa"/utf8>>, "n.."], [both, ". "], "h.ejsan"),
%% Test that it behaves with graphemes (i.e. nfd tests are the hard part)
+ ?TEST([1013,101,778,101,101], [trailing, [101]], [1013,101,778]),
?TEST("aaåaa", [both, "a"], "å"),
?TEST(["aaa",778,"äöoo"], [both, "ao"], "åäö"),
?TEST([<<"aaa">>,778,"äöoo"], [both, "ao"], "åäö"),
@@ -353,6 +352,7 @@ take(_) ->
?TEST([<<>>,<<"..">>, " h.ej", <<" ..">>], [Chars, true, leading], {".. ", "h.ej .."}),
?TEST(["..h", <<".ejsa"/utf8>>, "n.."], [Chars, true, leading], {"..", "h.ejsan.."}),
%% Test that it behaves with graphemes (i.e. nfd tests are the hard part)
+ ?TEST([101,778], [[[101, 779]], true], {[101,778], []}),
?TEST(["aaee",778,"äöoo"], [[[$e,778]], true, leading], {"aae", [$e,778|"äöoo"]}),
?TEST([<<"aae">>,778,"äöoo"], [[[$e,778]],true,leading], {"aa", [$e,778|"äöoo"]}),
?TEST([<<"e">>,778,"åäöe", <<778/utf8>>], [[[$e,778]], true, leading], {[], [$e,778]++"åäöe"++[778]}),
@@ -409,8 +409,8 @@ uppercase(_) ->
?TEST("abc", [], "ABC"),
?TEST("ABC", [], "ABC"),
?TEST("abcdefghiljklmnopqrstvxyzåäö",[], "ABCDEFGHILJKLMNOPQRSTVXYZÅÄÖ"),
- ?TEST("åäö", [], "ÅÄÖ"),
- ?TEST("ÅÄÖ", [], "ÅÄÖ"),
+ ?TEST("åäö ", [], "ÅÄÖ "),
+ ?TEST("ÅÄÖ ", [], "ÅÄÖ "),
?TEST("Michał", [], "MICHAŁ"),
?TEST(["Mic",<<"hał"/utf8>>], [], "MICHAŁ"),
?TEST("ljLJ", [], "LJLJ"),
@@ -423,8 +423,8 @@ lowercase(_) ->
?TEST("123", [], "123"),
?TEST("abc", [], "abc"),
?TEST("ABC", [], "abc"),
- ?TEST("åäö", [], "åäö"),
- ?TEST("ÅÄÖ", [], "åäö"),
+ ?TEST("åäö ", [], "åäö "),
+ ?TEST("ÅÄÖ ", [], "åäö "),
?TEST("MICHAŁ", [], "michał"),
?TEST(["Mic",<<"HAŁ"/utf8>>], [], "michał"),
?TEST("ß SHARP S", [], "ß sharp s"),
@@ -449,8 +449,8 @@ casefold(_) ->
?TEST("123", [], "123"),
?TEST("abc", [], "abc"),
?TEST("ABC", [], "abc"),
- ?TEST("åäö", [], "åäö"),
- ?TEST("ÅÄÖ", [], "åäö"),
+ ?TEST("åäö ", [], "åäö "),
+ ?TEST("ÅÄÖ ", [], "åäö "),
?TEST("MICHAŁ", [], "michał"),
?TEST(["Mic",<<"HAŁ"/utf8>>], [], "michał"),
?TEST("ß SHARP S", [], "ss sharp s"),
@@ -486,6 +486,10 @@ to_float(_) ->
prefix(_) ->
?TEST("", ["a"], nomatch),
?TEST("a", [""], "a"),
+ ?TEST("a", [[[]]], "a"),
+ ?TEST("a", [<<>>], "a"),
+ ?TEST("a", [[<<>>]], "a"),
+ ?TEST("a", [[[<<>>]]], "a"),
?TEST("b", ["a"], nomatch),
?TEST("a", ["a"], ""),
?TEST("å", ["a"], nomatch),
@@ -713,29 +717,135 @@ nth_lexeme(_) ->
meas(Config) ->
+ Parent = self(),
+ Exec = fun() ->
+ DataDir0 = proplists:get_value(data_dir, Config),
+ DataDir = filename:join(lists:droplast(filename:split(DataDir0))),
+ case proplists:get_value(profile, Config, false) of
+ false ->
+ do_measure(DataDir);
+ eprof ->
+ eprof:profile(fun() -> do_measure(DataDir) end, [set_on_spawn]),
+ eprof:stop_profiling(),
+ eprof:analyze(),
+ eprof:stop()
+ end,
+ Parent ! {test_done, self()},
+ normal
+ end,
+ ct:timetrap({minutes,2}),
case ct:get_timetrap_info() of
{_,{_,Scale}} when Scale > 1 ->
{skip,{will_not_run_in_debug,Scale}};
- _ -> % No scaling
- DataDir = proplists:get_value(data_dir, Config),
- TestDir = filename:dirname(string:trim(DataDir, trailing, "/")),
- do_measure(TestDir)
+ _ -> % No scaling, run at most 1.5 min
+ Tester = spawn(Exec),
+ receive {test_done, Tester} -> ok
+ after 90000 ->
+ io:format("Timelimit reached stopping~n",[]),
+ exit(Tester, die)
+ end,
+ ok
end.
-do_measure(TestDir) ->
- File = filename:join(TestDir, ?MODULE_STRING ++ ".erl"),
+do_measure(DataDir) ->
+ File = filename:join([DataDir,"unicode_util_SUITE_data","NormalizationTest.txt"]),
io:format("File ~s ",[File]),
{ok, Bin} = file:read_file(File),
io:format("~p~n",[byte_size(Bin)]),
Do = fun(Name, Func, Mode) ->
- {N, Mean, Stddev, _} = time_func(Func, Mode, Bin),
- io:format("~10w ~6w ~6.2fms ±~4.2fms #~.2w gc included~n",
+ {N, Mean, Stddev, _} = time_func(Func, Mode, Bin, 20),
+ io:format("~15w ~6w ~6.2fms ±~5.2fms #~.2w gc included~n",
[Name, Mode, Mean/1000, Stddev/1000, N])
end,
+ Do2 = fun(Name, Func, Mode) ->
+ {N, Mean, Stddev, _} = time_func(Func, binary, <<>>, 20),
+ io:format("~15w ~6w ~6.2fms ±~5.2fms #~.2w gc included~n",
+ [Name, Mode, Mean/1000, Stddev/1000, N])
+ end,
io:format("----------------------~n"),
- Do(tokens, fun(Str) -> string:tokens(Str, [$\n,$\r]) end, list),
+
+ Do(old_tokens, fun(Str) -> string:tokens(Str, [$\n,$\r]) end, list),
Tokens = {lexemes, fun(Str) -> string:lexemes(Str, [$\n,$\r]) end},
[Do(Name,Fun,Mode) || {Name,Fun} <- [Tokens], Mode <- [list, binary]],
+
+ S0 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxy.....",
+ S0B = <<"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxy.....">>,
+ Do2(old_strip_l, repeat(fun() -> string:strip(S0, left, $x) end), list),
+ Do2(trim_l, repeat(fun() -> string:trim(S0, leading, [$x]) end), list),
+ Do2(trim_l, repeat(fun() -> string:trim(S0B, leading, [$x]) end), binary),
+ Do2(old_strip_r, repeat(fun() -> string:strip(S0, right, $.) end), list),
+ Do2(trim_t, repeat(fun() -> string:trim(S0, trailing, [$.]) end), list),
+ Do2(trim_t, repeat(fun() -> string:trim(S0B, trailing, [$.]) end), binary),
+
+ Do2(old_chr_sub, repeat(fun() -> string:sub_string(S0, string:chr(S0, $.)) end), list),
+ Do2(old_str_sub, repeat(fun() -> string:sub_string(S0, string:str(S0, [$.])) end), list),
+ Do2(find, repeat(fun() -> string:find(S0, [$.]) end), list),
+ Do2(find, repeat(fun() -> string:find(S0B, [$.]) end), binary),
+ Do2(old_str_sub2, repeat(fun() -> N = string:str(S0, "xy.."),
+ {string:sub_string(S0,1,N), string:sub_string(S0,N+4)} end), list),
+ Do2(split, repeat(fun() -> string:split(S0, "xy..") end), list),
+ Do2(split, repeat(fun() -> string:split(S0B, "xy..") end), binary),
+
+ Do2(old_rstr_sub, repeat(fun() -> string:sub_string(S0, string:rstr(S0, [$y])) end), list),
+ Do2(find_t, repeat(fun() -> string:find(S0, [$y], trailing) end), list),
+ Do2(find_t, repeat(fun() -> string:find(S0B, [$y], trailing) end), binary),
+ Do2(old_rstr_sub2, repeat(fun() -> N = string:rstr(S0, "y.."),
+ {string:sub_string(S0,1,N), string:sub_string(S0,N+3)} end), list),
+ Do2(split_t, repeat(fun() -> string:split(S0, "y..", trailing) end), list),
+ Do2(split_t, repeat(fun() -> string:split(S0B, "y..", trailing) end), binary),
+
+ Do2(old_span, repeat(fun() -> N=string:span(S0, [$x, $y]),
+ {string:sub_string(S0,1,N),string:sub_string(S0,N+1)}
+ end), list),
+ Do2(take, repeat(fun() -> string:take(S0, [$x, $y]) end), list),
+ Do2(take, repeat(fun() -> string:take(S0B, [$x, $y]) end), binary),
+
+ Do2(old_cspan, repeat(fun() -> N=string:cspan(S0, [$.,$y]),
+ {string:sub_string(S0,1,N),string:sub_string(S0,N+1)}
+ end), list),
+ Do2(take_c, repeat(fun() -> string:take(S0, [$.,$y], true) end), list),
+ Do2(take_c, repeat(fun() -> string:take(S0B, [$.,$y], true) end), binary),
+
+ Do2(old_substr, repeat(fun() -> string:substr(S0, 21, 15) end), list),
+ Do2(slice, repeat(fun() -> string:slice(S0, 20, 15) end), list),
+ Do2(slice, repeat(fun() -> string:slice(S0B, 20, 15) end), binary),
+
+ LCase = "areaa reare rerar earea reare reare",
+ LCaseB = unicode:characters_to_binary(LCase),
+ UCase = string:uppercase(LCase),
+ UCaseB = unicode:characters_to_binary(UCase),
+
+ Do2(to_upper_0, repeat(fun() -> string:to_upper(UCase) end), list),
+ Do2(uppercase_0, repeat(fun() -> string:uppercase(UCase) end), list),
+ Do2(uppercase_0, repeat(fun() -> string:uppercase(UCaseB) end), binary),
+ Do2(to_upper_a, repeat(fun() -> string:to_upper(LCase) end), list),
+ Do2(uppercase_a, repeat(fun() -> string:uppercase(LCase) end), list),
+ Do2(uppercase_a, repeat(fun() -> string:uppercase(LCaseB) end), binary),
+
+ io:format("--~n",[]),
+ NthTokens = {nth_lexemes, fun(Str) -> string:nth_lexeme(Str, 18000, [$\n,$\r]) end},
+ [Do(Name,Fun,Mode) || {Name,Fun} <- [NthTokens], Mode <- [list, binary]],
+ Do2(take_t, repeat(fun() -> string:take(S0, [$.,$y], false, trailing) end), list),
+ Do2(take_t, repeat(fun() -> string:take(S0B, [$.,$y], false, trailing) end), binary),
+ Do2(take_tc, repeat(fun() -> string:take(S0, [$x], true, trailing) end), list),
+ Do2(take_tc, repeat(fun() -> string:take(S0B, [$x], true, trailing) end), binary),
+
+ Length = {length, fun(Str) -> string:length(Str) end},
+ [Do(Name,Fun,Mode) || {Name,Fun} <- [Length], Mode <- [list, binary]],
+
+ Reverse = {reverse, fun(Str) -> string:reverse(Str) end},
+ [Do(Name,Fun,Mode) || {Name,Fun} <- [Reverse], Mode <- [list, binary]],
+
+ ok.
+
+repeat(F) ->
+ fun(_) -> repeat_1(F,20000) end.
+
+repeat_1(F, N) when N > 0 ->
+ F(),
+ repeat_1(F, N-1);
+repeat_1(_, _) ->
+ erlang:garbage_collect(),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -783,9 +893,9 @@ test_1(Line, Func, Str, Args, Exp) ->
catch
error:Exp ->
ok;
- error:Reason ->
+ error:Reason:Stacktrace ->
io:format("~p:~p: Crash ~p ~p~n",
- [?MODULE,Line, Reason, erlang:get_stacktrace()]),
+ [?MODULE,Line, Reason, Stacktrace]),
exit({error, Func})
end.
@@ -850,10 +960,10 @@ check_types(Line, Func, [Str|_], Res) ->
io:format("Failed: ~p ~p: ~p ~p~n",[Line, Func, T1, T2]),
io:format(" ~p => ~p~n", [Str, Res]),
error;
- _:Reason ->
- io:format("Crash: ~p in~n ~p~n",[Reason, erlang:get_stacktrace()]),
+ _:Reason:Stacktrace ->
+ io:format("Crash: ~p in~n ~p~n",[Reason, Stacktrace]),
io:format("Failed: ~p ~p: ~p => ~p~n", [Line, Func, Str, Res]),
- exit({Reason, erlang:get_stacktrace()})
+ exit({Reason, Stacktrace})
end.
check_types_1(T, T) ->
@@ -865,8 +975,6 @@ check_types_1({list, _},{list, undefined}) ->
ok;
check_types_1({list, _},{list, codepoints}) ->
ok;
-check_types_1({list, _},{list, {list, codepoints}}) ->
- ok;
check_types_1({list, {list, _}},{list, {list, codepoints}}) ->
ok;
check_types_1(mixed,_) ->
@@ -938,19 +1046,19 @@ needs_check(_) -> true.
%%%% Timer stuff
-time_func(Fun, Mode, Bin) ->
+time_func(Fun, Mode, Bin, Repeat) ->
timer:sleep(100), %% Let emulator catch up and clean things before test runs
Self = self(),
Pid = spawn_link(fun() ->
Str = mode(Mode, Bin),
- Self ! {self(),time_func(0,0,0, Fun, Str, undefined)}
+ Self ! {self(),time_func(0,0,0, Fun, Str, undefined, Repeat)}
end),
receive {Pid,Msg} -> Msg end.
-time_func(N,Sum,SumSq, Fun, Str, _) when N < 50 ->
+time_func(N,Sum,SumSq, Fun, Str, _, Repeat) when N < Repeat ->
{Time, Res} = timer:tc(fun() -> Fun(Str) end),
- time_func(N+1,Sum+Time,SumSq+Time*Time, Fun, Str, Res);
-time_func(N,Sum,SumSq, _, _, Res) ->
+ time_func(N+1,Sum+Time,SumSq+Time*Time, Fun, Str, Res, Repeat);
+time_func(N,Sum,SumSq, _, _, Res, _) ->
Mean = round(Sum / N),
Stdev = round(math:sqrt((SumSq - (Sum*Sum/N))/(N - 1))),
{N, Mean, Stdev, Res}.
diff --git a/lib/stdlib/test/supervisor_1.erl b/lib/stdlib/test/supervisor_1.erl
index 419026749b..0d3dc67d3b 100644
--- a/lib/stdlib/test/supervisor_1.erl
+++ b/lib/stdlib/test/supervisor_1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,6 +42,8 @@ start_child(error) ->
set -> gen_server:start_link(?MODULE, error, [])
end;
+start_child({return, Term}) ->
+ Term;
start_child(Extra) ->
{ok, Pid} = gen_server:start_link(?MODULE, normal, []),
diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl
index cd2c6b0cbb..9370067910 100644
--- a/lib/stdlib/test/supervisor_SUITE.erl
+++ b/lib/stdlib/test/supervisor_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -39,6 +39,9 @@
sup_start_ignore_temporary_child_start_child_simple/1,
sup_start_ignore_permanent_child_start_child_simple/1,
sup_start_error_return/1, sup_start_fail/1,
+ sup_start_child_returns_error/1,
+ sup_start_restart_child_returns_error/1,
+ sup_start_child_returns_error_simple/1,
sup_start_map/1, sup_start_map_simple/1,
sup_start_map_faulty_specs/1,
sup_stop_infinity/1, sup_stop_timeout/1, sup_stop_brutal_kill/1,
@@ -65,14 +68,16 @@
simple_one_for_one_extra/1, simple_one_for_one_shutdown/1]).
%% Misc tests
--export([child_unlink/1, tree/1, count_children/1,
+-export([child_unlink/1, tree/1, count_children/1, count_children_supervisor/1,
count_restarting_children/1, get_callback_module/1,
do_not_save_start_parameters_for_temporary_children/1,
do_not_save_child_specs_for_temporary_children/1,
simple_one_for_one_scale_many_temporary_children/1,
simple_global_supervisor/1, hanging_restart_loop/1,
+ hanging_restart_loop_rest_for_one/1,
hanging_restart_loop_simple/1, code_change/1, code_change_map/1,
- code_change_simple/1, code_change_simple_map/1]).
+ code_change_simple/1, code_change_simple_map/1,
+ order_of_children/1, scale_start_stop_many_children/1]).
%%-------------------------------------------------------------------------
@@ -91,12 +96,15 @@ all() ->
{group, normal_termination},
{group, shutdown_termination},
{group, abnormal_termination}, child_unlink, tree,
- count_children, count_restarting_children, get_callback_module,
+ count_children, count_children_supervisor, count_restarting_children,
+ get_callback_module,
do_not_save_start_parameters_for_temporary_children,
do_not_save_child_specs_for_temporary_children,
simple_one_for_one_scale_many_temporary_children, temporary_bystander,
- simple_global_supervisor, hanging_restart_loop, hanging_restart_loop_simple,
- code_change, code_change_map, code_change_simple, code_change_simple_map].
+ simple_global_supervisor, hanging_restart_loop,
+ hanging_restart_loop_rest_for_one, hanging_restart_loop_simple,
+ code_change, code_change_map, code_change_simple, code_change_simple_map,
+ order_of_children, scale_start_stop_many_children].
groups() ->
[{sup_start, [],
@@ -105,7 +113,10 @@ groups() ->
sup_start_ignore_temporary_child_start_child,
sup_start_ignore_temporary_child_start_child_simple,
sup_start_ignore_permanent_child_start_child_simple,
- sup_start_error_return, sup_start_fail]},
+ sup_start_error_return, sup_start_fail,
+ sup_start_child_returns_error, sup_start_restart_child_returns_error,
+ sup_start_child_returns_error_simple
+ ]},
{sup_start_map, [],
[sup_start_map, sup_start_map_simple, sup_start_map_faulty_specs]},
{sup_stop, [],
@@ -147,6 +158,15 @@ init_per_testcase(_Case, Config) ->
Config.
end_per_testcase(_Case, _Config) ->
+ %% Clean up to avoid unnecessary error reports in the shell
+ case whereis(sup_test) of
+ SupPid when is_pid(SupPid) ->
+ unlink(SupPid),
+ exit(SupPid,shutdown),
+ ok;
+ _ ->
+ error
+ end,
ok.
start_link(InitResult) ->
@@ -274,6 +294,7 @@ sup_start_ignore_permanent_child_start_child_simple(Config)
%% Regression test: check that the supervisor terminates without error.
exit(Pid, shutdown),
check_exit_reason(Pid, shutdown).
+
%%-------------------------------------------------------------------------
%% Tests what happens if init-callback returns a invalid value.
sup_start_error_return(Config) when is_list(Config) ->
@@ -289,6 +310,53 @@ sup_start_fail(Config) when is_list(Config) ->
check_exit_reason(Term).
%%-------------------------------------------------------------------------
+%% Test what happens when the start function for a child returns
+%% {error,Reason} or some other term().
+sup_start_restart_child_returns_error(_Config) ->
+ process_flag(trap_exit, true),
+ Child = {child1, {supervisor_1, start_child, [error]},
+ permanent, 1000, worker, []},
+ {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, [Child]}}),
+
+ ok = supervisor:terminate_child(sup_test, child1),
+ {error,{function_clause,_}} = supervisor:restart_child(sup_test,child1),
+
+ [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test),
+ ok.
+
+%%-------------------------------------------------------------------------
+%% Test what happens when the start function for a child returns
+%% {error,Reason} or some other term().
+sup_start_child_returns_error(_Config) ->
+ process_flag(trap_exit, true),
+ Child1 = {child1, {supervisor_1, start_child, [{return,{error,reason}}]},
+ permanent, 1000, worker, []},
+ Child2 = {child2, {supervisor_1, start_child, [{return,error_reason}]},
+ permanent, 1000, worker, []},
+ {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
+
+ {error,{reason,_}} = supervisor:start_child(sup_test,Child1),
+ {error,{error_reason,_}} = supervisor:start_child(sup_test,Child2),
+
+ [] = supervisor:which_children(sup_test),
+ ok.
+
+%%-------------------------------------------------------------------------
+%% Test what happens when the start function for a child returns
+%% {error,Reason} - simple_one_for_one
+sup_start_child_returns_error_simple(_Config) ->
+ process_flag(trap_exit, true),
+ Child = {child1, {supervisor_1, start_child, []},
+ permanent, 1000, worker, []},
+ {ok, _Pid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child]}}),
+
+ {error,reason} = supervisor:start_child(sup_test,[{return,{error,reason}}]),
+ {error,error_reason} = supervisor:start_child(sup_test,[{return,error_reason}]),
+
+ [] = supervisor:which_children(sup_test),
+ ok.
+
+%%-------------------------------------------------------------------------
%% Tests that the supervisor process starts correctly with map
%% startspec, and that the full childspec can be read.
sup_start_map(Config) when is_list(Config) ->
@@ -468,7 +536,16 @@ extra_return(Config) when is_list(Config) ->
[{child1, CPid3, worker, []}] = supervisor:which_children(sup_test),
[1,1,0,1] = get_child_counts(sup_test),
- ok.
+ %% Check that it can be automatically restarted
+ terminate(CPid3, abnormal),
+ [{child1, CPid4, worker, []}] = supervisor:which_children(sup_test),
+ [1,1,0,1] = get_child_counts(sup_test),
+ if (not is_pid(CPid4)) orelse CPid4=:=CPid3 ->
+ ct:fail({not_restarted,CPid3,CPid4});
+ true ->
+ ok
+ end.
+
%%-------------------------------------------------------------------------
%% Test API functions start_child/2, terminate_child/2, delete_child/2
%% restart_child/2, which_children/1, count_children/1. Only correct
@@ -1140,7 +1217,7 @@ simple_one_for_one(Config) when is_list(Config) ->
[{Id4, Pid4, _, _}|_] = supervisor:which_children(sup_test),
terminate(SupPid, Pid4, Id4, abnormal),
- check_exit([SupPid]).
+ check_exit_reason(SupPid,shutdown).
%%-------------------------------------------------------------------------
@@ -1378,6 +1455,11 @@ tree(Config) when is_list(Config) ->
[?MODULE, {ok, {{one_for_one, 4, 3600}, []}}]},
permanent, infinity,
supervisor, []},
+ ChildSup3 = {supchild3,
+ {supervisor, start_link,
+ [?MODULE, {ok, {{one_for_one, 4, 3600}, []}}]},
+ transient, infinity,
+ supervisor, []},
%% Top supervisor
{ok, SupPid} = start_link({ok, {{one_for_all, 4, 3600}, []}}),
@@ -1385,7 +1467,9 @@ tree(Config) when is_list(Config) ->
%% Child supervisors
{ok, Sup1} = supervisor:start_child(SupPid, ChildSup1),
{ok, Sup2} = supervisor:start_child(SupPid, ChildSup2),
- [2,2,2,0] = get_child_counts(SupPid),
+ {ok, _Sup3} = supervisor:start_child(SupPid, ChildSup3),
+ ok = supervisor:terminate_child(SupPid, supchild3),
+ [3,2,3,0] = get_child_counts(SupPid),
%% Workers
[{_, CPid2, _, _},{_, CPid1, _, _}] =
@@ -1417,16 +1501,21 @@ tree(Config) when is_list(Config) ->
timer:sleep(1000),
- [{supchild2, NewSup2, _, _},{supchild1, NewSup1, _, _}] =
+ [{supchild3, NewSup3, _, _},
+ {supchild2, NewSup2, _, _},
+ {supchild1, NewSup1, _, _}] =
supervisor:which_children(SupPid),
- [2,2,2,0] = get_child_counts(SupPid),
+ [3,3,3,0] = get_child_counts(SupPid),
[{child2, _, _, _},{child1, _, _, _}] =
supervisor:which_children(NewSup1),
[2,2,0,2] = get_child_counts(NewSup1),
[] = supervisor:which_children(NewSup2),
- [0,0,0,0] = get_child_counts(NewSup2).
+ [0,0,0,0] = get_child_counts(NewSup2),
+
+ [] = supervisor:which_children(NewSup3),
+ [0,0,0,0] = get_child_counts(NewSup3).
%%-------------------------------------------------------------------------
%% Test count_children
@@ -1459,6 +1548,36 @@ count_children(Config) when is_list(Config) ->
[1,0,0,0] = get_child_counts(sup_test).
%%-------------------------------------------------------------------------
+%% Test count_children for simple_one_for_one, when children are supervisors
+count_children_supervisor(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ Child = {child, {supervisor_1, start_child, []}, temporary, infinity,
+ supervisor, []},
+ {ok, SupPid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child]}}),
+ [supervisor:start_child(sup_test, []) || _Ignore <- lists:seq(1,1000)],
+
+ Children = supervisor:which_children(sup_test),
+ ChildCount = get_child_counts(sup_test),
+
+ [supervisor:start_child(sup_test, []) || _Ignore2 <- lists:seq(1,1000)],
+
+ ChildCount2 = get_child_counts(sup_test),
+ Children2 = supervisor:which_children(sup_test),
+
+ ChildCount3 = get_child_counts(sup_test),
+ Children3 = supervisor:which_children(sup_test),
+
+ 1000 = length(Children),
+ [1,1000,1000,0] = ChildCount,
+ 2000 = length(Children2),
+ [1,2000,2000,0] = ChildCount2,
+ Children3 = Children2,
+ ChildCount3 = ChildCount2,
+
+ [terminate(SupPid, Pid, child, kill) || {undefined, Pid, supervisor, _Modules} <- Children3],
+ [1,0,0,0] = get_child_counts(sup_test).
+
+%%-------------------------------------------------------------------------
%% Test count_children when some children are restarting
count_restarting_children(Config) when is_list(Config) ->
process_flag(trap_exit, true),
@@ -1577,11 +1696,11 @@ dont_save_start_parameters_for_temporary_children(simple_one_for_one = Type) ->
start_children(Sup2, [LargeList], 100),
start_children(Sup3, [LargeList], 100),
- [{memory,Mem1}] = process_info(Sup1, [memory]),
- [{memory,Mem2}] = process_info(Sup2, [memory]),
- [{memory,Mem3}] = process_info(Sup3, [memory]),
+ Size1 = erts_debug:flat_size(sys:get_status(Sup1)),
+ Size2 = erts_debug:flat_size(sys:get_status(Sup2)),
+ Size3 = erts_debug:flat_size(sys:get_status(Sup3)),
- true = (Mem3 < Mem1) and (Mem3 < Mem2),
+ true = (Size3 < Size1) and (Size3 < Size2),
terminate(Sup1, shutdown),
terminate(Sup2, shutdown),
@@ -1605,11 +1724,11 @@ dont_save_start_parameters_for_temporary_children(Type) ->
start_children(Sup2, Transient, 100),
start_children(Sup3, Temporary, 100),
- [{memory,Mem1}] = process_info(Sup1, [memory]),
- [{memory,Mem2}] = process_info(Sup2, [memory]),
- [{memory,Mem3}] = process_info(Sup3, [memory]),
+ Size1 = erts_debug:flat_size(sys:get_status(Sup1)),
+ Size2 = erts_debug:flat_size(sys:get_status(Sup2)),
+ Size3 = erts_debug:flat_size(sys:get_status(Sup3)),
- true = (Mem3 < Mem1) and (Mem3 < Mem2),
+ true = (Size3 < Size1) and (Size3 < Size2),
terminate(Sup1, shutdown),
terminate(Sup2, shutdown),
@@ -1847,6 +1966,61 @@ hanging_restart_loop(Config) when is_list(Config) ->
undefined = whereis(sup_test),
ok.
+hanging_restart_loop_rest_for_one(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ {ok, Pid} = start_link({ok, {{rest_for_one, 8, 10}, []}}),
+ Child1 = {child1, {supervisor_1, start_child, []},
+ permanent, brutal_kill, worker, []},
+ Child2 = {child2, {supervisor_deadlock, start_child, []},
+ permanent, brutal_kill, worker, []},
+ Child3 = {child3, {supervisor_1, start_child, []},
+ permanent, brutal_kill, worker, []},
+
+ %% Ets table with state read by supervisor_deadlock.erl
+ ets:new(supervisor_deadlock,[set,named_table,public]),
+ ets:insert(supervisor_deadlock,{fail_start,false}),
+
+ {ok, CPid1} = supervisor:start_child(sup_test, Child1),
+ {ok, CPid2} = supervisor:start_child(sup_test, Child2),
+ link(CPid2),
+ {ok, _CPid3} = supervisor:start_child(sup_test, Child3),
+
+ ets:insert(supervisor_deadlock,{fail_start,true}),
+ supervisor_deadlock:restart_child(),
+ timer:sleep(2000), % allow restart to happen before proceeding
+
+ {error, already_present} = supervisor:start_child(sup_test, Child2),
+ {error, restarting} = supervisor:restart_child(sup_test, child2),
+ {error, restarting} = supervisor:delete_child(sup_test, child2),
+ [{child3,undefined,worker,[]},
+ {child2,restarting,worker,[]},
+ {child1,CPid1,worker,[]}] = supervisor:which_children(sup_test),
+ [3,1,0,3] = get_child_counts(sup_test),
+
+ ok = supervisor:terminate_child(sup_test, child2),
+ check_exit_reason(CPid2, error),
+ [{child3,undefined,worker,[]},
+ {child2,undefined,worker,[]},
+ {child1,CPid1,worker,[]}] = supervisor:which_children(sup_test),
+
+ ets:insert(supervisor_deadlock,{fail_start,false}),
+ {ok, CPid22} = supervisor:restart_child(sup_test, child2),
+ link(CPid22),
+
+ ets:insert(supervisor_deadlock,{fail_start,true}),
+ supervisor_deadlock:restart_child(),
+ timer:sleep(2000), % allow restart to happen before proceeding
+
+ %% Terminating supervisor.
+ %% OTP-9549 fixes so this does not give a timetrap timeout -
+ %% i.e. that supervisor does not hang in restart loop.
+ terminate(Pid,shutdown),
+
+ %% Check that child died with reason from 'restart' request above
+ check_exit_reason(CPid22, error),
+ undefined = whereis(sup_test),
+ ok.
+
%%-------------------------------------------------------------------------
%% Test that child and supervisor can be shutdown while hanging in
%% restart loop, simple_one_for_one.
@@ -2022,11 +2196,11 @@ code_change_simple(_Config) ->
SimpleChild2 = {child2,{supervisor_1, start_child, []}, permanent,
brutal_kill, worker, []},
- {error, {error, {ok,[_,_]}}} =
+ {error, {error, {ok,{[_,_],_}}}} =
fake_upgrade(SimplePid,{ok,{SimpleFlags,[SimpleChild1,SimpleChild2]}}),
%% Attempt to remove child
- {error, {error, {ok,[]}}} = fake_upgrade(SimplePid,{ok,{SimpleFlags,[]}}),
+ {error, {error, {ok,{[],_}}}} = fake_upgrade(SimplePid,{ok,{SimpleFlags,[]}}),
terminate(SimplePid,shutdown),
ok.
@@ -2047,11 +2221,11 @@ code_change_simple_map(_Config) ->
%% Attempt to add child
SimpleChild2 = #{id=>child2,
start=>{supervisor_1, start_child, []}},
- {error, {error, {ok, [_,_]}}} =
+ {error, {error, {ok, {[_,_],_}}}} =
fake_upgrade(SimplePid,{ok,{SimpleFlags,[SimpleChild1,SimpleChild2]}}),
%% Attempt to remove child
- {error, {error, {ok, []}}} =
+ {error, {error, {ok, {[],_}}}} =
fake_upgrade(SimplePid,{ok,{SimpleFlags,[]}}),
terminate(SimplePid,shutdown),
@@ -2075,6 +2249,155 @@ fake_upgrade(Pid,NewInitReturn) ->
ok = sys:resume(Pid),
R.
+%% Test that children are started in the order they are given, and
+%% terminated in the opposite order
+order_of_children(_Config) ->
+ process_flag(trap_exit, true),
+ %% Use child ids that are not alphabetically storted
+ Id1 = ch7,
+ Id2 = ch3,
+ Id3 = ch10,
+ Id4 = ch2,
+ Id5 = ch5,
+ Children =
+ [{Id, {supervisor_1, start_child, []}, permanent, 1000, worker, []} ||
+ Id <- [Id1,Id2,Id3,Id4,Id5]],
+
+ {ok, SupPid} = start_link({ok, {{rest_for_one, 2, 3600}, Children}}),
+
+
+ %% Check start order (pids are growing)
+ Which1 = supervisor:which_children(sup_test),
+ IsPid = fun({_,P,_,_}) when is_pid(P) -> true; (_) -> false end,
+ true = lists:all(IsPid,Which1),
+ SortedOnPid1 = lists:keysort(2,Which1),
+ [{Id1,Pid1,_,_},
+ {Id2,Pid2,_,_},
+ {Id3,Pid3,_,_},
+ {Id4,Pid4,_,_},
+ {Id5,Pid5,_,_}] = SortedOnPid1,
+
+ TPid = self(),
+ TraceHandler = fun({trace,P,exit,_},{Last,Ps}) when P=:=Last ->
+ TPid ! {exited,lists:reverse([P|Ps])},
+ {Last,Ps};
+ ({trace,P,exit,_},{Last,Ps}) ->
+ {Last,[P|Ps]};
+ (_T,Acc) ->
+ Acc
+ end,
+
+ %% Terminate Pid3 and check that Pid4 and Pid5 are terminated in
+ %% expected order.
+ Expected1 = [Pid5,Pid4],
+ {ok,_} = dbg:tracer(process,{TraceHandler,{Pid4,[]}}),
+ [{ok,[_]} = dbg:p(P,procs) || P <- Expected1],
+ terminate(Pid3, abnormal),
+ receive {exited,ExitedPids1} ->
+ dbg:stop_clear(),
+ case ExitedPids1 of
+ Expected1 -> ok;
+ _ -> ct:fail({faulty_termination_order,
+ {expected,Expected1},
+ {got,ExitedPids1}})
+ end
+ after 3000 ->
+ dbg:stop_clear(),
+ ct:fail({shutdown_fail,timeout})
+ end,
+
+ %% Then check that Id3-5 are started again in correct order
+ Which2 = supervisor:which_children(sup_test),
+ true = lists:all(IsPid,Which2),
+ SortedOnPid2 = lists:keysort(2,Which2),
+ [{Id1,Pid1,_,_},
+ {Id2,Pid2,_,_},
+ {Id3,Pid32,_,_},
+ {Id4,Pid42,_,_},
+ {Id5,Pid52,_,_}] = SortedOnPid2,
+
+ %% Terminate supervisor and check that all children are terminated
+ %% in opposite start order
+ Expected2 = [Pid52,Pid42,Pid32,Pid2,Pid1],
+ {ok,_} = dbg:tracer(process,{TraceHandler,{Pid1,[]}}),
+ [{ok,[_]} = dbg:p(P,procs) || P <- Expected2],
+ exit(SupPid,shutdown),
+ receive {exited,ExitedPids2} ->
+ dbg:stop_clear(),
+ case ExitedPids2 of
+ Expected2 -> ok;
+ _ -> ct:fail({faulty_termination_order,
+ {expected,Expected2},
+ {got,ExitedPids2}})
+ end
+ after 3000 ->
+ dbg:stop_clear(),
+ ct:fail({shutdown_fail,timeout})
+ end,
+ ok.
+
+%% Test that a non-simple supervisor scales well for starting and
+%% stopping many children.
+scale_start_stop_many_children(_Config) ->
+ case erlang:system_info(build_type) of
+ opt -> scale_start_stop_many_children();
+ Other -> {skip,"Run on build type 'opt' only (current: '" ++
+ atom_to_list(Other)++"')"}
+ end.
+
+scale_start_stop_many_children() ->
+ process_flag(trap_exit, true),
+ {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
+ N1 = 1000,
+ N2 = 100000,
+ Ids1 = lists:seq(1,N1),
+ Ids2 = lists:seq(1,N2),
+ Children1 = [{Id,{supervisor_1,start_child,[]},permanent,1000,worker,[]} ||
+ Id <- Ids1],
+ Children2 = [{Id,{supervisor_1,start_child,[]},permanent,1000,worker,[]} ||
+ Id <- Ids2],
+
+ {StartT1,_} =
+ timer:tc(fun() ->
+ [supervisor:start_child(sup_test,C) || C <- Children1]
+ end),
+ {StopT1,_} =
+ timer:tc(fun() ->
+ [supervisor:terminate_child(sup_test,I) || I <- Ids1]
+ end),
+ ct:log("~w children, start time: ~w ms, stop time: ~w ms",
+ [N1, StartT1 div 1000, StopT1 div 1000]),
+
+ {StartT2,_} =
+ timer:tc(fun() ->
+ [supervisor:start_child(sup_test,C) || C <- Children2]
+ end),
+ {StopT2,_} =
+ timer:tc(fun() ->
+ [supervisor:terminate_child(sup_test,I) || I <- Ids2]
+ end),
+ ct:log("~w children, start time: ~w ms, stop time: ~w ms",
+ [N2, StartT2 div 1000, StopT2 div 1000]),
+
+ %% Scaling should be more or less linear, but allowing a bit more
+ %% to avoid false alarms
+ ScaleLimit = (N2 div N1) * 10,
+ StartScale = StartT2 div StartT1,
+ StopScale = StopT2 div StopT1,
+
+ ct:log("Scale limit: ~w~nStart scale: ~w~nStop scale: ~w",
+ [ScaleLimit, StartScale, StopScale]),
+
+ if StartScale > ScaleLimit ->
+ ct:fail({bad_start_scale,StartScale});
+ StopScale > ScaleLimit ->
+ ct:fail({bad_stop_scale,StopScale});
+ true ->
+ ok
+ end,
+
+ ok.
+
%%-------------------------------------------------------------------------
terminate(Pid, Reason) when Reason =/= supervisor ->
terminate(dummy, Pid, dummy, Reason).
diff --git a/lib/stdlib/test/supervisor_deadlock.erl b/lib/stdlib/test/supervisor_deadlock.erl
index 8d3d1c6f30..f51aecccb2 100644
--- a/lib/stdlib/test/supervisor_deadlock.erl
+++ b/lib/stdlib/test/supervisor_deadlock.erl
@@ -1,5 +1,5 @@
-module(supervisor_deadlock).
--compile(export_all).
+-compile([export_all,nowarn_export_all]).
%%%-----------------------------------------------------------------
diff --git a/lib/stdlib/test/sys_SUITE.erl b/lib/stdlib/test/sys_SUITE.erl
index b44df0fbda..3278eb0eb0 100644
--- a/lib/stdlib/test/sys_SUITE.erl
+++ b/lib/stdlib/test/sys_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -84,7 +84,7 @@ stats(Config) when is_list(Config) ->
{ok,-44} = public_call(44),
{ok,Stats} = sys:statistics(?server,get),
true = lists:member({messages_in,1}, Stats),
- true = lists:member({messages_out,0}, Stats),
+ true = lists:member({messages_out,1}, Stats),
ok = sys:statistics(?server,false),
{status,_Pid,{module,_Mod},[_PDict,running,Self,_,_]} =
sys:get_status(?server),
@@ -133,7 +133,8 @@ install(Config) when is_list(Config) ->
Master ! {spy_got,{request,Arg},ProcState};
Other ->
io:format("Trigged other=~p\n",[Other])
- end
+ end,
+ func_state
end,
sys:install(?server,{SpyFun,func_state}),
{ok,-1} = (catch public_call(1)),
@@ -142,10 +143,27 @@ install(Config) when is_list(Config) ->
sys:install(?server,{SpyFun,func_state}),
sys:install(?server,{SpyFun,func_state}),
{ok,-3} = (catch public_call(3)),
- sys:remove(?server,SpyFun),
{ok,-4} = (catch public_call(4)),
+ sys:remove(?server,SpyFun),
+ {ok,-5} = (catch public_call(5)),
+ [{spy_got,{request,1},sys_SUITE_server},
+ {spy_got,{request,3},sys_SUITE_server},
+ {spy_got,{request,4},sys_SUITE_server}] = get_messages(),
+
+ sys:install(?server,{id1, SpyFun, func_state}),
+ sys:install(?server,{id1, SpyFun, func_state}), %% should not be installed
+ sys:install(?server,{id2, SpyFun, func_state}),
+ {ok,-1} = (catch public_call(1)),
+ %% We have two SpyFun installed:
[{spy_got,{request,1},sys_SUITE_server},
- {spy_got,{request,3},sys_SUITE_server}] = get_messages(),
+ {spy_got,{request,1},sys_SUITE_server}] = get_messages(),
+ sys:remove(?server, id1),
+ {ok,-1} = (catch public_call(1)),
+ %% We have one SpyFun installed:
+ [{spy_got,{request,1},sys_SUITE_server}] = get_messages(),
+ sys:no_debug(?server),
+ {ok,-1} = (catch public_call(1)),
+ [] = get_messages(),
stop(),
ok.
diff --git a/lib/stdlib/test/tar_SUITE.erl b/lib/stdlib/test/tar_SUITE.erl
index 4061008812..32a33283d1 100644
--- a/lib/stdlib/test/tar_SUITE.erl
+++ b/lib/stdlib/test/tar_SUITE.erl
@@ -28,7 +28,7 @@
extract_from_open_file/1, symlinks/1, open_add_close/1, cooked_compressed/1,
memory/1,unicode/1,read_other_implementations/1,
sparse/1, init/1, leading_slash/1, dotdot/1,
- roundtrip_metadata/1]).
+ roundtrip_metadata/1, apply_file_info_opts/1]).
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
@@ -42,7 +42,8 @@ all() ->
extract_filtered,
symlinks, open_add_close, cooked_compressed, memory, unicode,
read_other_implementations,
- sparse,init,leading_slash,dotdot,roundtrip_metadata].
+ sparse,init,leading_slash,dotdot,roundtrip_metadata,
+ apply_file_info_opts].
groups() ->
[].
@@ -989,6 +990,31 @@ do_roundtrip_metadata(Dir, File) ->
ok
end.
+apply_file_info_opts(Config) when is_list(Config) ->
+ ok = file:set_cwd(proplists:get_value(priv_dir, Config)),
+
+ ok = file:make_dir("empty_directory"),
+ ok = file:write_file("file", "contents"),
+
+ Opts = [{atime, 0}, {mtime, 0}, {ctime, 0}, {uid, 0}, {gid, 0}],
+ TarFile = "reproducible.tar",
+ {ok, Tar} = erl_tar:open(TarFile, [write]),
+ ok = erl_tar:add(Tar, "file", Opts),
+ ok = erl_tar:add(Tar, "empty_directory", Opts),
+ ok = erl_tar:add(Tar, <<"contents">>, "memory_file", Opts),
+ erl_tar:close(Tar),
+
+ ok = file:make_dir("extracted"),
+ erl_tar:extract(TarFile, [{cwd, "extracted"}]),
+
+ {ok, #file_info{mtime=0}} =
+ file:read_file_info("extracted/empty_directory", [{time, posix}]),
+ {ok, #file_info{mtime=0}} =
+ file:read_file_info("extracted/file", [{time, posix}]),
+ {ok, #file_info{mtime=0}} =
+ file:read_file_info("extracted/memory_file", [{time, posix}]),
+
+ ok.
%% Delete the given list of files.
delete_files([]) -> ok;
diff --git a/lib/stdlib/test/unicode_expand.erl b/lib/stdlib/test/unicode_expand.erl
new file mode 100644
index 0000000000..41f741fa84
--- /dev/null
+++ b/lib/stdlib/test/unicode_expand.erl
@@ -0,0 +1,36 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(unicode_expand).
+
+-export(['кlирилли́ческий атом'/0, 'кlирилли́ческий атом'/1,
+ 'кlирилли́ческий атомB'/1]).
+
+-export_type(['кlирилли́ческий атом'/0]).
+
+-type 'кlирилли́ческий атом'() :: integer().
+
+'кlирилли́ческий атом'() ->
+ 'кlирилли́ческий атом'('кlирилли́ческий атом').
+
+'кlирилли́ческий атом'(_Atom) ->
+ ok.
+
+'кlирилли́ческий атомB'(_B) ->
+ true.
diff --git a/lib/stdlib/test/unicode_util_SUITE.erl b/lib/stdlib/test/unicode_util_SUITE.erl
index 03c24c7027..962b307b07 100644
--- a/lib/stdlib/test/unicode_util_SUITE.erl
+++ b/lib/stdlib/test/unicode_util_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,9 @@
get/1,
count/1]).
--export([debug/0, id/1, bin_split/1, uc_loaded_size/0]).
+-export([debug/0, id/1, bin_split/1, uc_loaded_size/0,
+ time_count/4 %% Used by stdlib_bench_SUITE
+ ]).
suite() ->
[{ct_hooks,[ts_install_cth]},
@@ -134,10 +136,10 @@ verify_gc(Line0, N, Acc) ->
io:format("Expected: ~p~n", [Res]),
io:format("Got: ~w~n", [Other]),
Acc+1;
- Cl:R ->
+ Cl:R:Stacktrace ->
io:format("~p: ~ts => |~tp|~n",[N, Line, Str]),
io:format("Expected: ~p~n", [Res]),
- erlang:raise(Cl,R,erlang:get_stacktrace())
+ erlang:raise(Cl,R,Stacktrace)
end.
gc_test_data([[247]|Rest], Str, [First|GCs]) ->
@@ -173,29 +175,29 @@ verify_nfd(Data0, LineNo, _Acc) ->
C3GC = fetch(C1, fun unicode_util:nfd/1),
C3GC = fetch(C2, fun unicode_util:nfd/1),
C3GC = fetch(C3, fun unicode_util:nfd/1)
- catch _Cl:{badmatch, Other} = _R->
+ catch _Cl:{badmatch, Other} = _R: Stacktrace ->
io:format("Failed: ~p~nInput: ~ts~n\t=> ~w |~ts|~n",[LineNo, Data1, C1, C1]),
io:format("Expected: ~ts ~w~n", [C3GC, C3GC]),
io:format("Got: ~ts ~w~n", [Other, Other]),
- erlang:raise(_Cl,_R,erlang:get_stacktrace());
- Cl:R ->
+ erlang:raise(_Cl,_R,Stacktrace);
+ Cl:R:Stacktrace ->
io:format("~p: ~ts => |~tp|~n",[LineNo, Data1, C1]),
io:format("Expected: ~p~n", [C3]),
- erlang:raise(Cl,R,erlang:get_stacktrace())
+ erlang:raise(Cl,R,Stacktrace)
end,
C5GC = fetch(C5, fun unicode_util:gc/1),
try
C5GC = fetch(C4, fun unicode_util:nfd/1),
C5GC = fetch(C5, fun unicode_util:nfd/1)
- catch _Cl2:{badmatch, Other2} = _R2->
+ catch _Cl2:{badmatch, Other2} = _R2:Stacktrace2 ->
io:format("Failed: ~p~nInput: ~ts~n\t=> ~w |~ts|~n",[LineNo, Data1, C1, C1]),
io:format("Expected: ~ts ~w~n", [C5GC, C5GC]),
io:format("Got: ~ts ~w~n", [Other2, Other2]),
- erlang:raise(_Cl2,_R2,erlang:get_stacktrace());
- Cl2:R2 ->
+ erlang:raise(_Cl2,_R2,Stacktrace2);
+ Cl2:R2:Stacktrace2 ->
io:format("~p: ~ts => |~tp|~n",[LineNo, Data1, C1]),
io:format("Expected: ~p~n", [C5]),
- erlang:raise(Cl2,R2,erlang:get_stacktrace())
+ erlang:raise(Cl2,R2,Stacktrace2)
end,
ok.
@@ -216,29 +218,29 @@ verify_nfc(Data0, LineNo, _Acc) ->
C2GC = fetch(C1, fun unicode_util:nfc/1),
C2GC = fetch(C2, fun unicode_util:nfc/1),
C2GC = fetch(C3, fun unicode_util:nfc/1)
- catch _Cl:{badmatch, Other} = _R->
+ catch _Cl:{badmatch, Other} = _R:Stacktrace ->
io:format("Failed: ~p~nInput: ~ts~n\t=> ~w |~ts|~n",[LineNo, Data1, C1, C1]),
io:format("Expected: ~ts ~w~n", [C2GC, C2GC]),
io:format("Got: ~ts ~w~n", [Other, Other]),
- erlang:raise(_Cl,_R,erlang:get_stacktrace());
- Cl:R ->
+ erlang:raise(_Cl,_R,Stacktrace);
+ Cl:R:Stacktrace ->
io:format("~p: ~ts => |~tp|~n",[LineNo, Data1, C1]),
io:format("Expected: ~p~n", [C3]),
- erlang:raise(Cl,R,erlang:get_stacktrace())
+ erlang:raise(Cl,R,Stacktrace)
end,
C4GC = fetch(C4, fun unicode_util:gc/1),
try
C4GC = fetch(C4, fun unicode_util:nfc/1),
C4GC = fetch(C5, fun unicode_util:nfc/1)
- catch _Cl2:{badmatch, Other2} = _R2->
+ catch _Cl2:{badmatch, Other2} = _R2:Stacktrace2 ->
io:format("Failed: ~p~nInput: ~ts~n\t=> ~w |~ts|~n",[LineNo, Data1, C1, C1]),
io:format("Expected: ~ts ~w~n", [C4GC, C4GC]),
io:format("Got: ~ts ~w~n", [Other2, Other2]),
- erlang:raise(_Cl2,_R2,erlang:get_stacktrace());
- Cl2:R2 ->
+ erlang:raise(_Cl2,_R2,Stacktrace2);
+ Cl2:R2:Stacktrace2 ->
io:format("~p: ~ts => |~tp|~n",[LineNo, Data1, C1]),
io:format("Expected: ~p~n", [C5]),
- erlang:raise(Cl2,R2,erlang:get_stacktrace())
+ erlang:raise(Cl2,R2,Stacktrace2)
end,
ok.
@@ -261,15 +263,15 @@ verify_nfkd(Data0, LineNo, _Acc) ->
C5GC = lists:flatten(fetch(C3, fun unicode_util:nfkd/1)),
C5GC = lists:flatten(fetch(C4, fun unicode_util:nfkd/1)),
C5GC = lists:flatten(fetch(C5, fun unicode_util:nfkd/1))
- catch _Cl:{badmatch, Other} = _R->
+ catch _Cl:{badmatch, Other} = _R:Stacktrace ->
io:format("Failed: ~p~nInput: ~ts~n\t=> ~w |~ts|~n",[LineNo, Data1, C5, C5]),
io:format("Expected: ~ts ~w~n", [C5GC, C5GC]),
io:format("Got: ~ts ~w~n", [Other, Other]),
- erlang:raise(_Cl,_R,erlang:get_stacktrace());
- Cl:R ->
+ erlang:raise(_Cl,_R,Stacktrace);
+ Cl:R:Stacktrace ->
io:format("~p: ~ts => |~tp|~n",[LineNo, Data1, C1]),
io:format("Expected: ~p~n", [C3]),
- erlang:raise(Cl,R,erlang:get_stacktrace())
+ erlang:raise(Cl,R,Stacktrace)
end,
ok.
@@ -294,15 +296,15 @@ verify_nfkc(Data0, LineNo, _Acc) ->
C4GC = lists:flatten(fetch(C4, fun unicode_util:nfkc/1)),
C4GC = lists:flatten(fetch(C5, fun unicode_util:nfkc/1))
- catch _Cl:{badmatch, Other} = _R->
+ catch _Cl:{badmatch, Other} = _R:Stacktrace ->
io:format("Failed: ~p~nInput: ~ts~n\t=> ~w |~ts|~n",[LineNo, Data1, C4, C4]),
io:format("Expected: ~ts ~w~n", [C4GC, C4GC]),
io:format("Got: ~ts ~w~n", [Other, Other]),
- erlang:raise(_Cl,_R,erlang:get_stacktrace());
- Cl:R ->
+ erlang:raise(_Cl,_R,Stacktrace);
+ Cl:R:Stacktrace ->
io:format("~p: ~ts => |~tp|~n",[LineNo, Data1, C1]),
io:format("Expected: ~p~n", [C3]),
- erlang:raise(Cl,R,erlang:get_stacktrace())
+ erlang:raise(Cl,R,Stacktrace)
end,
ok.
@@ -310,12 +312,23 @@ get(_) ->
add_get_tests.
count(Config) ->
+ Parent = self(),
+ Exec = fun() ->
+ do_measure(Config),
+ Parent ! {test_done, self()}
+ end,
ct:timetrap({minutes,5}),
case ct:get_timetrap_info() of
- {_,{_,Scale}} ->
+ {_,{_,Scale}} when Scale > 1 ->
{skip,{measurments_skipped_debug,Scale}};
- _ -> % No scaling
- do_measure(Config)
+ _ -> % No scaling, run at most 2 min
+ Tester = spawn(Exec),
+ receive {test_done, Tester} -> ok
+ after 120000 ->
+ io:format("Timelimit reached stopping~n",[]),
+ exit(Tester, die)
+ end,
+ ok
end.
do_measure(Config) ->
@@ -323,7 +336,7 @@ do_measure(Config) ->
File = DataDir ++ "/NormalizationTest.txt",
{ok, Bin} = file:read_file(File),
Do = fun(Func, Mode) ->
- {N, Mean, Stddev, Res} = time_count(Func, Mode, Bin),
+ {N, Mean, Stddev, Res} = time_count(Func, Mode, Bin, 10),
io:format("~4w ~6w ~.10w ~.6wms ±~.2wms #~.2w~n",
[Func, Mode, Res, Mean div 1000, Stddev div 1000, N])
end,
@@ -345,19 +358,19 @@ uc_loaded_size([_|Rest]) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-time_count(Fun, Mode, Bin) ->
+time_count(Fun, Mode, Bin, Repeat) ->
timer:sleep(100), %% Let emulator catch up and clean things before test runs
Self = self(),
Pid = spawn_link(fun() ->
Str = mode(Mode, Bin),
- Self ! {self(),do_count(0,0,0, Fun, Str, undefined)}
+ Self ! {self(),do_count(0,0,0, Fun, Str, undefined, Repeat)}
end),
receive {Pid,Msg} -> Msg end.
-do_count(N,Sum,SumSq, Fun, Str, _) when N < 10 ->
+do_count(N,Sum,SumSq, Fun, Str, _, Repeat) when N < Repeat ->
{Time, Res} = do_count(Fun, Str),
- do_count(N+1,Sum+Time,SumSq+Time*Time, Fun, Str, Res);
-do_count(N,Sum,SumSq, _, _, Res) ->
+ do_count(N+1,Sum+Time,SumSq+Time*Time, Fun, Str, Res, Repeat);
+do_count(N,Sum,SumSq, _, _, Res, _) ->
Mean = round(Sum / N),
Stdev = round(math:sqrt((SumSq - (Sum*Sum/N))/(N - 1))),
{N, Mean, Stdev, Res}.
diff --git a/lib/stdlib/test/unicode_util_SUITE_data/GraphemeBreakTest.txt b/lib/stdlib/test/unicode_util_SUITE_data/GraphemeBreakTest.txt
index 4bb4b1369b..d7d8f90de0 100644
--- a/lib/stdlib/test/unicode_util_SUITE_data/GraphemeBreakTest.txt
+++ b/lib/stdlib/test/unicode_util_SUITE_data/GraphemeBreakTest.txt
@@ -1,23 +1,24 @@
-# GraphemeBreakTest-9.0.0.txt
-# Date: 2016-06-02, 18:28:17 GMT
-# © 2016 Unicode®, Inc.
+# GraphemeBreakTest-10.0.0.txt
+# Date: 2017-04-14, 05:40:29 GMT
+# © 2017 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
# Unicode Character Database
# For documentation, see http://www.unicode.org/reports/tr44/
#
-# Default Grapheme Break Test
+# Default Grapheme_Cluster_Break Test
#
# Format:
-# <string> (# <comment>)?
-# <string> contains hex Unicode code points, with
-# ÷ wherever there is a break opportunity, and
+# <string> (# <comment>)?
+# <string> contains hex Unicode code points, with
+# ÷ wherever there is a break opportunity, and
# × wherever there is not.
# <comment> the format can change, but currently it shows:
# - the sample character name
# - (x) the Grapheme_Cluster_Break property value for the sample character
-# - [x] the rule that determines whether there is a break or not
+# - [x] the rule that determines whether there is a break or not,
+# as listed in the Rules section of GraphemeBreakTest.html
#
# These samples may be extended or changed in the future.
#
@@ -53,8 +54,8 @@
÷ 0020 × 0308 ÷ 1F3FB ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ 0020 × 200D ÷ # ÷ [0.2] SPACE (Other) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ 0020 × 0308 × 200D ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ 0020 ÷ 2764 ÷ # ÷ [0.2] SPACE (Other) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ 0020 × 0308 ÷ 2764 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ 0020 ÷ 2640 ÷ # ÷ [0.2] SPACE (Other) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ 0020 × 0308 ÷ 2640 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ 0020 ÷ 1F466 ÷ # ÷ [0.2] SPACE (Other) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 0020 × 0308 ÷ 1F466 ÷ # ÷ [0.2] SPACE (Other) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 0020 ÷ 0378 ÷ # ÷ [0.2] SPACE (Other) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
@@ -93,8 +94,8 @@
÷ 000D ÷ 0308 ÷ 1F3FB ÷ # ÷ [0.2] <CARRIAGE RETURN (CR)> (CR) ÷ [4.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ 000D ÷ 200D ÷ # ÷ [0.2] <CARRIAGE RETURN (CR)> (CR) ÷ [4.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ 000D ÷ 0308 × 200D ÷ # ÷ [0.2] <CARRIAGE RETURN (CR)> (CR) ÷ [4.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ 000D ÷ 2764 ÷ # ÷ [0.2] <CARRIAGE RETURN (CR)> (CR) ÷ [4.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ 000D ÷ 0308 ÷ 2764 ÷ # ÷ [0.2] <CARRIAGE RETURN (CR)> (CR) ÷ [4.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ 000D ÷ 2640 ÷ # ÷ [0.2] <CARRIAGE RETURN (CR)> (CR) ÷ [4.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ 000D ÷ 0308 ÷ 2640 ÷ # ÷ [0.2] <CARRIAGE RETURN (CR)> (CR) ÷ [4.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ 000D ÷ 1F466 ÷ # ÷ [0.2] <CARRIAGE RETURN (CR)> (CR) ÷ [4.0] BOY (EBG) ÷ [0.3]
÷ 000D ÷ 0308 ÷ 1F466 ÷ # ÷ [0.2] <CARRIAGE RETURN (CR)> (CR) ÷ [4.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 000D ÷ 0378 ÷ # ÷ [0.2] <CARRIAGE RETURN (CR)> (CR) ÷ [4.0] <reserved-0378> (Other) ÷ [0.3]
@@ -133,8 +134,8 @@
÷ 000A ÷ 0308 ÷ 1F3FB ÷ # ÷ [0.2] <LINE FEED (LF)> (LF) ÷ [4.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ 000A ÷ 200D ÷ # ÷ [0.2] <LINE FEED (LF)> (LF) ÷ [4.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ 000A ÷ 0308 × 200D ÷ # ÷ [0.2] <LINE FEED (LF)> (LF) ÷ [4.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ 000A ÷ 2764 ÷ # ÷ [0.2] <LINE FEED (LF)> (LF) ÷ [4.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ 000A ÷ 0308 ÷ 2764 ÷ # ÷ [0.2] <LINE FEED (LF)> (LF) ÷ [4.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ 000A ÷ 2640 ÷ # ÷ [0.2] <LINE FEED (LF)> (LF) ÷ [4.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ 000A ÷ 0308 ÷ 2640 ÷ # ÷ [0.2] <LINE FEED (LF)> (LF) ÷ [4.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ 000A ÷ 1F466 ÷ # ÷ [0.2] <LINE FEED (LF)> (LF) ÷ [4.0] BOY (EBG) ÷ [0.3]
÷ 000A ÷ 0308 ÷ 1F466 ÷ # ÷ [0.2] <LINE FEED (LF)> (LF) ÷ [4.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 000A ÷ 0378 ÷ # ÷ [0.2] <LINE FEED (LF)> (LF) ÷ [4.0] <reserved-0378> (Other) ÷ [0.3]
@@ -173,8 +174,8 @@
÷ 0001 ÷ 0308 ÷ 1F3FB ÷ # ÷ [0.2] <START OF HEADING> (Control) ÷ [4.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ 0001 ÷ 200D ÷ # ÷ [0.2] <START OF HEADING> (Control) ÷ [4.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ 0001 ÷ 0308 × 200D ÷ # ÷ [0.2] <START OF HEADING> (Control) ÷ [4.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ 0001 ÷ 2764 ÷ # ÷ [0.2] <START OF HEADING> (Control) ÷ [4.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ 0001 ÷ 0308 ÷ 2764 ÷ # ÷ [0.2] <START OF HEADING> (Control) ÷ [4.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ 0001 ÷ 2640 ÷ # ÷ [0.2] <START OF HEADING> (Control) ÷ [4.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ 0001 ÷ 0308 ÷ 2640 ÷ # ÷ [0.2] <START OF HEADING> (Control) ÷ [4.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ 0001 ÷ 1F466 ÷ # ÷ [0.2] <START OF HEADING> (Control) ÷ [4.0] BOY (EBG) ÷ [0.3]
÷ 0001 ÷ 0308 ÷ 1F466 ÷ # ÷ [0.2] <START OF HEADING> (Control) ÷ [4.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 0001 ÷ 0378 ÷ # ÷ [0.2] <START OF HEADING> (Control) ÷ [4.0] <reserved-0378> (Other) ÷ [0.3]
@@ -213,8 +214,8 @@
÷ 0300 × 0308 ÷ 1F3FB ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ 0300 × 200D ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ 0300 × 0308 × 200D ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ 0300 ÷ 2764 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ 0300 × 0308 ÷ 2764 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ 0300 ÷ 2640 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ 0300 × 0308 ÷ 2640 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ 0300 ÷ 1F466 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 0300 × 0308 ÷ 1F466 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 0300 ÷ 0378 ÷ # ÷ [0.2] COMBINING GRAVE ACCENT (Extend) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
@@ -253,8 +254,8 @@
÷ 0600 × 0308 ÷ 1F3FB ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ 0600 × 200D ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ 0600 × 0308 × 200D ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ 0600 × 2764 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.2] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ 0600 × 0308 ÷ 2764 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ 0600 × 2640 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.2] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ 0600 × 0308 ÷ 2640 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ 0600 × 1F466 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.2] BOY (EBG) ÷ [0.3]
÷ 0600 × 0308 ÷ 1F466 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 0600 × 0378 ÷ # ÷ [0.2] ARABIC NUMBER SIGN (Prepend) × [9.2] <reserved-0378> (Other) ÷ [0.3]
@@ -293,8 +294,8 @@
÷ 0903 × 0308 ÷ 1F3FB ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ 0903 × 200D ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ 0903 × 0308 × 200D ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ 0903 ÷ 2764 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ 0903 × 0308 ÷ 2764 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ 0903 ÷ 2640 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ 0903 × 0308 ÷ 2640 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ 0903 ÷ 1F466 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 0903 × 0308 ÷ 1F466 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 0903 ÷ 0378 ÷ # ÷ [0.2] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
@@ -333,8 +334,8 @@
÷ 1100 × 0308 ÷ 1F3FB ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ 1100 × 200D ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ 1100 × 0308 × 200D ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ 1100 ÷ 2764 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ 1100 × 0308 ÷ 2764 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ 1100 ÷ 2640 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ 1100 × 0308 ÷ 2640 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ 1100 ÷ 1F466 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 1100 × 0308 ÷ 1F466 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 1100 ÷ 0378 ÷ # ÷ [0.2] HANGUL CHOSEONG KIYEOK (L) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
@@ -373,8 +374,8 @@
÷ 1160 × 0308 ÷ 1F3FB ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ 1160 × 200D ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ 1160 × 0308 × 200D ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ 1160 ÷ 2764 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ 1160 × 0308 ÷ 2764 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ 1160 ÷ 2640 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ 1160 × 0308 ÷ 2640 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ 1160 ÷ 1F466 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 1160 × 0308 ÷ 1F466 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 1160 ÷ 0378 ÷ # ÷ [0.2] HANGUL JUNGSEONG FILLER (V) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
@@ -413,8 +414,8 @@
÷ 11A8 × 0308 ÷ 1F3FB ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ 11A8 × 200D ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ 11A8 × 0308 × 200D ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ 11A8 ÷ 2764 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ 11A8 × 0308 ÷ 2764 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ 11A8 ÷ 2640 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ 11A8 × 0308 ÷ 2640 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ 11A8 ÷ 1F466 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 11A8 × 0308 ÷ 1F466 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 11A8 ÷ 0378 ÷ # ÷ [0.2] HANGUL JONGSEONG KIYEOK (T) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
@@ -453,8 +454,8 @@
÷ AC00 × 0308 ÷ 1F3FB ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ AC00 × 200D ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ AC00 × 0308 × 200D ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ AC00 ÷ 2764 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ AC00 × 0308 ÷ 2764 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ AC00 ÷ 2640 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ AC00 × 0308 ÷ 2640 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ AC00 ÷ 1F466 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ AC00 × 0308 ÷ 1F466 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ AC00 ÷ 0378 ÷ # ÷ [0.2] HANGUL SYLLABLE GA (LV) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
@@ -493,8 +494,8 @@
÷ AC01 × 0308 ÷ 1F3FB ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ AC01 × 200D ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ AC01 × 0308 × 200D ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ AC01 ÷ 2764 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ AC01 × 0308 ÷ 2764 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ AC01 ÷ 2640 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ AC01 × 0308 ÷ 2640 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ AC01 ÷ 1F466 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ AC01 × 0308 ÷ 1F466 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ AC01 ÷ 0378 ÷ # ÷ [0.2] HANGUL SYLLABLE GAG (LVT) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
@@ -533,8 +534,8 @@
÷ 1F1E6 × 0308 ÷ 1F3FB ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ 1F1E6 × 200D ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ 1F1E6 × 0308 × 200D ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ 1F1E6 ÷ 2764 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ 1F1E6 × 0308 ÷ 2764 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ 1F1E6 ÷ 2640 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ 1F1E6 × 0308 ÷ 2640 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ 1F1E6 ÷ 1F466 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 1F1E6 × 0308 ÷ 1F466 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 1F1E6 ÷ 0378 ÷ # ÷ [0.2] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
@@ -573,8 +574,8 @@
÷ 261D × 0308 × 1F3FB ÷ # ÷ [0.2] WHITE UP POINTING INDEX (E_Base) × [9.0] COMBINING DIAERESIS (Extend) × [10.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ 261D × 200D ÷ # ÷ [0.2] WHITE UP POINTING INDEX (E_Base) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ 261D × 0308 × 200D ÷ # ÷ [0.2] WHITE UP POINTING INDEX (E_Base) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ 261D ÷ 2764 ÷ # ÷ [0.2] WHITE UP POINTING INDEX (E_Base) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ 261D × 0308 ÷ 2764 ÷ # ÷ [0.2] WHITE UP POINTING INDEX (E_Base) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ 261D ÷ 2640 ÷ # ÷ [0.2] WHITE UP POINTING INDEX (E_Base) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ 261D × 0308 ÷ 2640 ÷ # ÷ [0.2] WHITE UP POINTING INDEX (E_Base) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ 261D ÷ 1F466 ÷ # ÷ [0.2] WHITE UP POINTING INDEX (E_Base) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 261D × 0308 ÷ 1F466 ÷ # ÷ [0.2] WHITE UP POINTING INDEX (E_Base) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 261D ÷ 0378 ÷ # ÷ [0.2] WHITE UP POINTING INDEX (E_Base) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
@@ -613,8 +614,8 @@
÷ 1F3FB × 0308 ÷ 1F3FB ÷ # ÷ [0.2] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ 1F3FB × 200D ÷ # ÷ [0.2] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ 1F3FB × 0308 × 200D ÷ # ÷ [0.2] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ 1F3FB ÷ 2764 ÷ # ÷ [0.2] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ 1F3FB × 0308 ÷ 2764 ÷ # ÷ [0.2] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ 1F3FB ÷ 2640 ÷ # ÷ [0.2] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ 1F3FB × 0308 ÷ 2640 ÷ # ÷ [0.2] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ 1F3FB ÷ 1F466 ÷ # ÷ [0.2] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 1F3FB × 0308 ÷ 1F466 ÷ # ÷ [0.2] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 1F3FB ÷ 0378 ÷ # ÷ [0.2] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
@@ -653,54 +654,54 @@
÷ 200D × 0308 ÷ 1F3FB ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ 200D × 200D ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ 200D × 0308 × 200D ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ 200D × 2764 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ) × [11.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ 200D × 0308 ÷ 2764 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ 200D × 2640 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ) × [11.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ 200D × 0308 ÷ 2640 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ 200D × 1F466 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ) × [11.0] BOY (EBG) ÷ [0.3]
÷ 200D × 0308 ÷ 1F466 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 200D ÷ 0378 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
÷ 200D × 0308 ÷ 0378 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
÷ 200D ÷ D800 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ) ÷ [5.0] <surrogate-D800> (Control) ÷ [0.3]
÷ 200D × 0308 ÷ D800 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ) × [9.0] COMBINING DIAERESIS (Extend) ÷ [5.0] <surrogate-D800> (Control) ÷ [0.3]
-÷ 2764 ÷ 0020 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [999.0] SPACE (Other) ÷ [0.3]
-÷ 2764 × 0308 ÷ 0020 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] SPACE (Other) ÷ [0.3]
-÷ 2764 ÷ 000D ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [5.0] <CARRIAGE RETURN (CR)> (CR) ÷ [0.3]
-÷ 2764 × 0308 ÷ 000D ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [5.0] <CARRIAGE RETURN (CR)> (CR) ÷ [0.3]
-÷ 2764 ÷ 000A ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [5.0] <LINE FEED (LF)> (LF) ÷ [0.3]
-÷ 2764 × 0308 ÷ 000A ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [5.0] <LINE FEED (LF)> (LF) ÷ [0.3]
-÷ 2764 ÷ 0001 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [5.0] <START OF HEADING> (Control) ÷ [0.3]
-÷ 2764 × 0308 ÷ 0001 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [5.0] <START OF HEADING> (Control) ÷ [0.3]
-÷ 2764 × 0300 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING GRAVE ACCENT (Extend) ÷ [0.3]
-÷ 2764 × 0308 × 0300 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] COMBINING GRAVE ACCENT (Extend) ÷ [0.3]
-÷ 2764 ÷ 0600 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3]
-÷ 2764 × 0308 ÷ 0600 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3]
-÷ 2764 × 0903 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3]
-÷ 2764 × 0308 × 0903 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3]
-÷ 2764 ÷ 1100 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3]
-÷ 2764 × 0308 ÷ 1100 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3]
-÷ 2764 ÷ 1160 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3]
-÷ 2764 × 0308 ÷ 1160 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3]
-÷ 2764 ÷ 11A8 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3]
-÷ 2764 × 0308 ÷ 11A8 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3]
-÷ 2764 ÷ AC00 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3]
-÷ 2764 × 0308 ÷ AC00 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3]
-÷ 2764 ÷ AC01 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3]
-÷ 2764 × 0308 ÷ AC01 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3]
-÷ 2764 ÷ 1F1E6 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3]
-÷ 2764 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3]
-÷ 2764 ÷ 261D ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [999.0] WHITE UP POINTING INDEX (E_Base) ÷ [0.3]
-÷ 2764 × 0308 ÷ 261D ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] WHITE UP POINTING INDEX (E_Base) ÷ [0.3]
-÷ 2764 ÷ 1F3FB ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
-÷ 2764 × 0308 ÷ 1F3FB ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
-÷ 2764 × 200D ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ 2764 × 0308 × 200D ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ 2764 ÷ 2764 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ 2764 × 0308 ÷ 2764 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ 2764 ÷ 1F466 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [999.0] BOY (EBG) ÷ [0.3]
-÷ 2764 × 0308 ÷ 1F466 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
-÷ 2764 ÷ 0378 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
-÷ 2764 × 0308 ÷ 0378 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
-÷ 2764 ÷ D800 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [5.0] <surrogate-D800> (Control) ÷ [0.3]
-÷ 2764 × 0308 ÷ D800 ÷ # ÷ [0.2] HEAVY BLACK HEART (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [5.0] <surrogate-D800> (Control) ÷ [0.3]
+÷ 2640 ÷ 0020 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) ÷ [999.0] SPACE (Other) ÷ [0.3]
+÷ 2640 × 0308 ÷ 0020 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] SPACE (Other) ÷ [0.3]
+÷ 2640 ÷ 000D ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) ÷ [5.0] <CARRIAGE RETURN (CR)> (CR) ÷ [0.3]
+÷ 2640 × 0308 ÷ 000D ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [5.0] <CARRIAGE RETURN (CR)> (CR) ÷ [0.3]
+÷ 2640 ÷ 000A ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) ÷ [5.0] <LINE FEED (LF)> (LF) ÷ [0.3]
+÷ 2640 × 0308 ÷ 000A ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [5.0] <LINE FEED (LF)> (LF) ÷ [0.3]
+÷ 2640 ÷ 0001 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) ÷ [5.0] <START OF HEADING> (Control) ÷ [0.3]
+÷ 2640 × 0308 ÷ 0001 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [5.0] <START OF HEADING> (Control) ÷ [0.3]
+÷ 2640 × 0300 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING GRAVE ACCENT (Extend) ÷ [0.3]
+÷ 2640 × 0308 × 0300 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] COMBINING GRAVE ACCENT (Extend) ÷ [0.3]
+÷ 2640 ÷ 0600 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3]
+÷ 2640 × 0308 ÷ 0600 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] ARABIC NUMBER SIGN (Prepend) ÷ [0.3]
+÷ 2640 × 0903 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3]
+÷ 2640 × 0308 × 0903 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) × [9.1] DEVANAGARI SIGN VISARGA (SpacingMark) ÷ [0.3]
+÷ 2640 ÷ 1100 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3]
+÷ 2640 × 0308 ÷ 1100 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HANGUL CHOSEONG KIYEOK (L) ÷ [0.3]
+÷ 2640 ÷ 1160 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3]
+÷ 2640 × 0308 ÷ 1160 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HANGUL JUNGSEONG FILLER (V) ÷ [0.3]
+÷ 2640 ÷ 11A8 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3]
+÷ 2640 × 0308 ÷ 11A8 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HANGUL JONGSEONG KIYEOK (T) ÷ [0.3]
+÷ 2640 ÷ AC00 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3]
+÷ 2640 × 0308 ÷ AC00 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HANGUL SYLLABLE GA (LV) ÷ [0.3]
+÷ 2640 ÷ AC01 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3]
+÷ 2640 × 0308 ÷ AC01 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HANGUL SYLLABLE GAG (LVT) ÷ [0.3]
+÷ 2640 ÷ 1F1E6 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3]
+÷ 2640 × 0308 ÷ 1F1E6 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] REGIONAL INDICATOR SYMBOL LETTER A (RI) ÷ [0.3]
+÷ 2640 ÷ 261D ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) ÷ [999.0] WHITE UP POINTING INDEX (E_Base) ÷ [0.3]
+÷ 2640 × 0308 ÷ 261D ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] WHITE UP POINTING INDEX (E_Base) ÷ [0.3]
+÷ 2640 ÷ 1F3FB ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
+÷ 2640 × 0308 ÷ 1F3FB ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
+÷ 2640 × 200D ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
+÷ 2640 × 0308 × 200D ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
+÷ 2640 ÷ 2640 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ 2640 × 0308 ÷ 2640 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ 2640 ÷ 1F466 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) ÷ [999.0] BOY (EBG) ÷ [0.3]
+÷ 2640 × 0308 ÷ 1F466 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
+÷ 2640 ÷ 0378 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
+÷ 2640 × 0308 ÷ 0378 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
+÷ 2640 ÷ D800 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) ÷ [5.0] <surrogate-D800> (Control) ÷ [0.3]
+÷ 2640 × 0308 ÷ D800 ÷ # ÷ [0.2] FEMALE SIGN (Glue_After_Zwj) × [9.0] COMBINING DIAERESIS (Extend) ÷ [5.0] <surrogate-D800> (Control) ÷ [0.3]
÷ 1F466 ÷ 0020 ÷ # ÷ [0.2] BOY (EBG) ÷ [999.0] SPACE (Other) ÷ [0.3]
÷ 1F466 × 0308 ÷ 0020 ÷ # ÷ [0.2] BOY (EBG) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] SPACE (Other) ÷ [0.3]
÷ 1F466 ÷ 000D ÷ # ÷ [0.2] BOY (EBG) ÷ [5.0] <CARRIAGE RETURN (CR)> (CR) ÷ [0.3]
@@ -733,8 +734,8 @@
÷ 1F466 × 0308 × 1F3FB ÷ # ÷ [0.2] BOY (EBG) × [9.0] COMBINING DIAERESIS (Extend) × [10.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ 1F466 × 200D ÷ # ÷ [0.2] BOY (EBG) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ 1F466 × 0308 × 200D ÷ # ÷ [0.2] BOY (EBG) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ 1F466 ÷ 2764 ÷ # ÷ [0.2] BOY (EBG) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ 1F466 × 0308 ÷ 2764 ÷ # ÷ [0.2] BOY (EBG) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ 1F466 ÷ 2640 ÷ # ÷ [0.2] BOY (EBG) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ 1F466 × 0308 ÷ 2640 ÷ # ÷ [0.2] BOY (EBG) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ 1F466 ÷ 1F466 ÷ # ÷ [0.2] BOY (EBG) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 1F466 × 0308 ÷ 1F466 ÷ # ÷ [0.2] BOY (EBG) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 1F466 ÷ 0378 ÷ # ÷ [0.2] BOY (EBG) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
@@ -773,8 +774,8 @@
÷ 0378 × 0308 ÷ 1F3FB ÷ # ÷ [0.2] <reserved-0378> (Other) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ 0378 × 200D ÷ # ÷ [0.2] <reserved-0378> (Other) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ 0378 × 0308 × 200D ÷ # ÷ [0.2] <reserved-0378> (Other) × [9.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ 0378 ÷ 2764 ÷ # ÷ [0.2] <reserved-0378> (Other) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ 0378 × 0308 ÷ 2764 ÷ # ÷ [0.2] <reserved-0378> (Other) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ 0378 ÷ 2640 ÷ # ÷ [0.2] <reserved-0378> (Other) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ 0378 × 0308 ÷ 2640 ÷ # ÷ [0.2] <reserved-0378> (Other) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ 0378 ÷ 1F466 ÷ # ÷ [0.2] <reserved-0378> (Other) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 0378 × 0308 ÷ 1F466 ÷ # ÷ [0.2] <reserved-0378> (Other) × [9.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ 0378 ÷ 0378 ÷ # ÷ [0.2] <reserved-0378> (Other) ÷ [999.0] <reserved-0378> (Other) ÷ [0.3]
@@ -813,8 +814,8 @@
÷ D800 ÷ 0308 ÷ 1F3FB ÷ # ÷ [0.2] <surrogate-D800> (Control) ÷ [4.0] COMBINING DIAERESIS (Extend) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ D800 ÷ 200D ÷ # ÷ [0.2] <surrogate-D800> (Control) ÷ [4.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
÷ D800 ÷ 0308 × 200D ÷ # ÷ [0.2] <surrogate-D800> (Control) ÷ [4.0] COMBINING DIAERESIS (Extend) × [9.0] ZERO WIDTH JOINER (ZWJ) ÷ [0.3]
-÷ D800 ÷ 2764 ÷ # ÷ [0.2] <surrogate-D800> (Control) ÷ [4.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
-÷ D800 ÷ 0308 ÷ 2764 ÷ # ÷ [0.2] <surrogate-D800> (Control) ÷ [4.0] COMBINING DIAERESIS (Extend) ÷ [999.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ D800 ÷ 2640 ÷ # ÷ [0.2] <surrogate-D800> (Control) ÷ [4.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
+÷ D800 ÷ 0308 ÷ 2640 ÷ # ÷ [0.2] <surrogate-D800> (Control) ÷ [4.0] COMBINING DIAERESIS (Extend) ÷ [999.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ D800 ÷ 1F466 ÷ # ÷ [0.2] <surrogate-D800> (Control) ÷ [4.0] BOY (EBG) ÷ [0.3]
÷ D800 ÷ 0308 ÷ 1F466 ÷ # ÷ [0.2] <surrogate-D800> (Control) ÷ [4.0] COMBINING DIAERESIS (Extend) ÷ [999.0] BOY (EBG) ÷ [0.3]
÷ D800 ÷ 0378 ÷ # ÷ [0.2] <surrogate-D800> (Control) ÷ [4.0] <reserved-0378> (Other) ÷ [0.3]
@@ -840,7 +841,7 @@
÷ 261D × 1F3FB ÷ 261D ÷ # ÷ [0.2] WHITE UP POINTING INDEX (E_Base) × [10.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [999.0] WHITE UP POINTING INDEX (E_Base) ÷ [0.3]
÷ 1F466 × 1F3FB ÷ # ÷ [0.2] BOY (EBG) × [10.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
÷ 200D × 1F466 × 1F3FB ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ) × [11.0] BOY (EBG) × [10.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (E_Modifier) ÷ [0.3]
-÷ 200D × 2764 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ) × [11.0] HEAVY BLACK HEART (Glue_After_Zwj) ÷ [0.3]
+÷ 200D × 2640 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ) × [11.0] FEMALE SIGN (Glue_After_Zwj) ÷ [0.3]
÷ 200D × 1F466 ÷ # ÷ [0.2] ZERO WIDTH JOINER (ZWJ) × [11.0] BOY (EBG) ÷ [0.3]
÷ 1F466 ÷ 1F466 ÷ # ÷ [0.2] BOY (EBG) ÷ [999.0] BOY (EBG) ÷ [0.3]
#
diff --git a/lib/stdlib/test/unicode_util_SUITE_data/LineBreakTest.txt b/lib/stdlib/test/unicode_util_SUITE_data/LineBreakTest.txt
index 05efcf5a44..6715446aba 100644
--- a/lib/stdlib/test/unicode_util_SUITE_data/LineBreakTest.txt
+++ b/lib/stdlib/test/unicode_util_SUITE_data/LineBreakTest.txt
@@ -1,25 +1,28 @@
-# LineBreakTest-9.0.0.txt
-# Date: 2016-06-18, 00:42:06 GMT
-# © 2016 Unicode®, Inc.
+# LineBreakTest-10.0.0.txt
+# Date: 2017-04-14, 05:40:30 GMT
+# © 2017 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
# Unicode Character Database
# For documentation, see http://www.unicode.org/reports/tr44/
#
-# Default Line Break Test
+# Default Line_Break Test
#
# Format:
-# <string> (# <comment>)?
-# <string> contains hex Unicode code points, with
-# ÷ wherever there is a break opportunity, and
+# <string> (# <comment>)?
+# <string> contains hex Unicode code points, with
+# ÷ wherever there is a break opportunity, and
# × wherever there is not.
# <comment> the format can change, but currently it shows:
# - the sample character name
# - (x) the Line_Break property value for the sample character
-# - [x] the rule that determines whether there is a break or not
-# Note: The Line Break tests use tailoring of numbers described in Example 7 of Section 8.2 Examples of Customization.
-# They also differ from the results produced by a pair table implementation in sequences like: ZW SP CL.
+# - [x] the rule that determines whether there is a break or not,
+# as listed in the Rules section of LineBreakTest.html
+#
+# Note:
+# The Line_Break tests use tailoring of numbers described in
+# Example 7 of Section 8.2, "Examples of Customization" of UAX #14.
#
# These samples may be extended or changed in the future.
#
diff --git a/lib/stdlib/test/unicode_util_SUITE_data/NormalizationTest.txt b/lib/stdlib/test/unicode_util_SUITE_data/NormalizationTest.txt
index e133fa8a78..71f2371c5e 100644
--- a/lib/stdlib/test/unicode_util_SUITE_data/NormalizationTest.txt
+++ b/lib/stdlib/test/unicode_util_SUITE_data/NormalizationTest.txt
@@ -1,6 +1,6 @@
-# NormalizationTest-9.0.0.txt
-# Date: 2016-04-04, 11:41:55 GMT
-# © 2016 Unicode®, Inc.
+# NormalizationTest-10.0.0.txt
+# Date: 2017-03-08, 08:41:55 GMT
+# © 2017 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
@@ -17653,6 +17653,10 @@ FFEE;FFEE;FFEE;25CB;25CB; # (○; ○; ○; ○; ○; ) HALFWIDTH WHITE CIRCLE
0061 0CBC 3099 093C 0334 0062;0061 0334 0CBC 093C 3099 0062;0061 0334 0CBC 093C 3099 0062;0061 0334 0CBC 093C 3099 0062;0061 0334 0CBC 093C 3099 0062; # (a◌಼◌゙◌़◌̴b; a◌̴◌಼◌़◌゙b; a◌̴◌಼◌़◌゙b; a◌̴◌಼◌़◌゙b; a◌̴◌಼◌़◌゙b; ) LATIN SMALL LETTER A, KANNADA SIGN NUKTA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, DEVANAGARI SIGN NUKTA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
0061 05B0 094D 3099 0CCD 0062;0061 3099 094D 0CCD 05B0 0062;0061 3099 094D 0CCD 05B0 0062;0061 3099 094D 0CCD 05B0 0062;0061 3099 094D 0CCD 05B0 0062; # (a◌ְ◌्◌゙◌್b; a◌゙◌्◌್◌ְb; a◌゙◌्◌್◌ְb; a◌゙◌्◌್◌ְb; a◌゙◌्◌್◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, KANNADA SIGN VIRAMA, LATIN SMALL LETTER B
0061 0CCD 05B0 094D 3099 0062;0061 3099 0CCD 094D 05B0 0062;0061 3099 0CCD 094D 05B0 0062;0061 3099 0CCD 094D 05B0 0062;0061 3099 0CCD 094D 05B0 0062; # (a◌್◌ְ◌्◌゙b; a◌゙◌್◌्◌ְb; a◌゙◌್◌्◌ְb; a◌゙◌್◌्◌ְb; a◌゙◌್◌्◌ְb; ) LATIN SMALL LETTER A, KANNADA SIGN VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
+0061 05B0 094D 3099 0D3B 0062;0061 3099 094D 0D3B 05B0 0062;0061 3099 094D 0D3B 05B0 0062;0061 3099 094D 0D3B 05B0 0062;0061 3099 094D 0D3B 05B0 0062; # (a◌ְ◌्◌゙◌഻b; a◌゙◌्◌഻◌ְb; a◌゙◌्◌഻◌ְb; a◌゙◌्◌഻◌ְb; a◌゙◌्◌഻◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, MALAYALAM SIGN VERTICAL BAR VIRAMA, LATIN SMALL LETTER B
+0061 0D3B 05B0 094D 3099 0062;0061 3099 0D3B 094D 05B0 0062;0061 3099 0D3B 094D 05B0 0062;0061 3099 0D3B 094D 05B0 0062;0061 3099 0D3B 094D 05B0 0062; # (a◌഻◌ְ◌्◌゙b; a◌゙◌഻◌्◌ְb; a◌゙◌഻◌्◌ְb; a◌゙◌഻◌्◌ְb; a◌゙◌഻◌्◌ְb; ) LATIN SMALL LETTER A, MALAYALAM SIGN VERTICAL BAR VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
+0061 05B0 094D 3099 0D3C 0062;0061 3099 094D 0D3C 05B0 0062;0061 3099 094D 0D3C 05B0 0062;0061 3099 094D 0D3C 05B0 0062;0061 3099 094D 0D3C 05B0 0062; # (a◌ְ◌्◌゙◌഼b; a◌゙◌्◌഼◌ְb; a◌゙◌्◌഼◌ְb; a◌゙◌्◌഼◌ְb; a◌゙◌्◌഼◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, MALAYALAM SIGN CIRCULAR VIRAMA, LATIN SMALL LETTER B
+0061 0D3C 05B0 094D 3099 0062;0061 3099 0D3C 094D 05B0 0062;0061 3099 0D3C 094D 05B0 0062;0061 3099 0D3C 094D 05B0 0062;0061 3099 0D3C 094D 05B0 0062; # (a◌഼◌ְ◌्◌゙b; a◌゙◌഼◌्◌ְb; a◌゙◌഼◌्◌ְb; a◌゙◌഼◌्◌ְb; a◌゙◌഼◌्◌ְb; ) LATIN SMALL LETTER A, MALAYALAM SIGN CIRCULAR VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
0061 05B0 094D 3099 0D4D 0062;0061 3099 094D 0D4D 05B0 0062;0061 3099 094D 0D4D 05B0 0062;0061 3099 094D 0D4D 05B0 0062;0061 3099 094D 0D4D 05B0 0062; # (a◌ְ◌्◌゙◌്b; a◌゙◌्◌്◌ְb; a◌゙◌्◌്◌ְb; a◌゙◌्◌്◌ְb; a◌゙◌्◌്◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, MALAYALAM SIGN VIRAMA, LATIN SMALL LETTER B
0061 0D4D 05B0 094D 3099 0062;0061 3099 0D4D 094D 05B0 0062;0061 3099 0D4D 094D 05B0 0062;0061 3099 0D4D 094D 05B0 0062;0061 3099 0D4D 094D 05B0 0062; # (a◌്◌ְ◌्◌゙b; a◌゙◌്◌्◌ְb; a◌゙◌്◌्◌ְb; a◌゙◌്◌्◌ְb; a◌゙◌്◌्◌ְb; ) LATIN SMALL LETTER A, MALAYALAM SIGN VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
0061 05B0 094D 3099 0DCA 0062;0061 3099 094D 0DCA 05B0 0062;0061 3099 094D 0DCA 05B0 0062;0061 3099 094D 0DCA 05B0 0062;0061 3099 094D 0DCA 05B0 0062; # (a◌ְ◌्◌゙◌්b; a◌゙◌्◌්◌ְb; a◌゙◌्◌්◌ְb; a◌゙◌्◌්◌ְb; a◌゙◌्◌්◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, SINHALA SIGN AL-LAKUNA, LATIN SMALL LETTER B
@@ -17999,6 +18003,14 @@ FFEE;FFEE;FFEE;25CB;25CB; # (○; ○; ○; ○; ○; ) HALFWIDTH WHITE CIRCLE
0061 1DF4 0315 0300 05AE 0062;0061 05AE 1DF4 0300 0315 0062;0061 05AE 1DF4 0300 0315 0062;0061 05AE 1DF4 0300 0315 0062;0061 05AE 1DF4 0300 0315 0062; # (a◌ᷴ◌̕◌̀◌֮b; a◌֮◌ᷴ◌̀◌̕b; a◌֮◌ᷴ◌̀◌̕b; a◌֮◌ᷴ◌̀◌̕b; a◌֮◌ᷴ◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING LATIN SMALL LETTER U WITH DIAERESIS, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1DF5 0062;00E0 05AE 1DF5 0315 0062;0061 05AE 0300 1DF5 0315 0062;00E0 05AE 1DF5 0315 0062;0061 05AE 0300 1DF5 0315 0062; # (a◌̕◌̀◌֮◌᷵b; à◌֮◌᷵◌̕b; a◌֮◌̀◌᷵◌̕b; à◌֮◌᷵◌̕b; a◌֮◌̀◌᷵◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING UP TACK ABOVE, LATIN SMALL LETTER B
0061 1DF5 0315 0300 05AE 0062;0061 05AE 1DF5 0300 0315 0062;0061 05AE 1DF5 0300 0315 0062;0061 05AE 1DF5 0300 0315 0062;0061 05AE 1DF5 0300 0315 0062; # (a◌᷵◌̕◌̀◌֮b; a◌֮◌᷵◌̀◌̕b; a◌֮◌᷵◌̀◌̕b; a◌֮◌᷵◌̀◌̕b; a◌֮◌᷵◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING UP TACK ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 035C 0315 0300 1DF6 0062;00E0 0315 1DF6 035C 0062;0061 0300 0315 1DF6 035C 0062;00E0 0315 1DF6 035C 0062;0061 0300 0315 1DF6 035C 0062; # (a◌͜◌̕◌̀◌᷶b; à◌̕◌᷶◌͜b; a◌̀◌̕◌᷶◌͜b; à◌̕◌᷶◌͜b; a◌̀◌̕◌᷶◌͜b; ) LATIN SMALL LETTER A, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, COMBINING KAVYKA ABOVE RIGHT, LATIN SMALL LETTER B
+0061 1DF6 035C 0315 0300 0062;00E0 1DF6 0315 035C 0062;0061 0300 1DF6 0315 035C 0062;00E0 1DF6 0315 035C 0062;0061 0300 1DF6 0315 035C 0062; # (a◌᷶◌͜◌̕◌̀b; à◌᷶◌̕◌͜b; a◌̀◌᷶◌̕◌͜b; à◌᷶◌̕◌͜b; a◌̀◌᷶◌̕◌͜b; ) LATIN SMALL LETTER A, COMBINING KAVYKA ABOVE RIGHT, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, LATIN SMALL LETTER B
+0061 0300 05AE 1D16D 1DF7 0062;00E0 1D16D 05AE 1DF7 0062;0061 1D16D 05AE 1DF7 0300 0062;00E0 1D16D 05AE 1DF7 0062;0061 1D16D 05AE 1DF7 0300 0062; # (a◌̀◌𝅭֮◌᷷b; à𝅭◌֮◌᷷b; a𝅭◌֮◌᷷◌̀b; à𝅭◌֮◌᷷b; a𝅭◌֮◌᷷◌̀b; ) LATIN SMALL LETTER A, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING AUGMENTATION DOT, COMBINING KAVYKA ABOVE LEFT, LATIN SMALL LETTER B
+0061 1DF7 0300 05AE 1D16D 0062;00E0 1D16D 1DF7 05AE 0062;0061 1D16D 1DF7 05AE 0300 0062;00E0 1D16D 1DF7 05AE 0062;0061 1D16D 1DF7 05AE 0300 0062; # (a◌᷷◌̀◌𝅭֮b; à𝅭◌᷷◌֮b; a𝅭◌᷷◌֮◌̀b; à𝅭◌᷷◌֮b; a𝅭◌᷷◌֮◌̀b; ) LATIN SMALL LETTER A, COMBINING KAVYKA ABOVE LEFT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING AUGMENTATION DOT, LATIN SMALL LETTER B
+0061 0300 05AE 1D16D 1DF8 0062;00E0 1D16D 05AE 1DF8 0062;0061 1D16D 05AE 1DF8 0300 0062;00E0 1D16D 05AE 1DF8 0062;0061 1D16D 05AE 1DF8 0300 0062; # (a◌̀◌𝅭֮◌᷸b; à𝅭◌֮◌᷸b; a𝅭◌֮◌᷸◌̀b; à𝅭◌֮◌᷸b; a𝅭◌֮◌᷸◌̀b; ) LATIN SMALL LETTER A, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING AUGMENTATION DOT, COMBINING DOT ABOVE LEFT, LATIN SMALL LETTER B
+0061 1DF8 0300 05AE 1D16D 0062;00E0 1D16D 1DF8 05AE 0062;0061 1D16D 1DF8 05AE 0300 0062;00E0 1D16D 1DF8 05AE 0062;0061 1D16D 1DF8 05AE 0300 0062; # (a◌᷸◌̀◌𝅭֮b; à𝅭◌᷸◌֮b; a𝅭◌᷸◌֮◌̀b; à𝅭◌᷸◌֮b; a𝅭◌᷸◌֮◌̀b; ) LATIN SMALL LETTER A, COMBINING DOT ABOVE LEFT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING AUGMENTATION DOT, LATIN SMALL LETTER B
+0061 059A 0316 302A 1DF9 0062;0061 302A 0316 1DF9 059A 0062;0061 302A 0316 1DF9 059A 0062;0061 302A 0316 1DF9 059A 0062;0061 302A 0316 1DF9 059A 0062; # (a◌֚◌̖◌〪◌᷹b; a◌〪◌̖◌᷹◌֚b; a◌〪◌̖◌᷹◌֚b; a◌〪◌̖◌᷹◌֚b; a◌〪◌̖◌᷹◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING WIDE INVERTED BRIDGE BELOW, LATIN SMALL LETTER B
+0061 1DF9 059A 0316 302A 0062;0061 302A 1DF9 0316 059A 0062;0061 302A 1DF9 0316 059A 0062;0061 302A 1DF9 0316 059A 0062;0061 302A 1DF9 0316 059A 0062; # (a◌᷹◌֚◌̖◌〪b; a◌〪◌᷹◌̖◌֚b; a◌〪◌᷹◌̖◌֚b; a◌〪◌᷹◌̖◌֚b; a◌〪◌᷹◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING WIDE INVERTED BRIDGE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
0061 0315 0300 05AE 1DFB 0062;00E0 05AE 1DFB 0315 0062;0061 05AE 0300 1DFB 0315 0062;00E0 05AE 1DFB 0315 0062;0061 05AE 0300 1DFB 0315 0062; # (a◌̕◌̀◌֮◌᷻b; à◌֮◌᷻◌̕b; a◌֮◌̀◌᷻◌̕b; à◌֮◌᷻◌̕b; a◌֮◌̀◌᷻◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING DELETION MARK, LATIN SMALL LETTER B
0061 1DFB 0315 0300 05AE 0062;0061 05AE 1DFB 0300 0315 0062;0061 05AE 1DFB 0300 0315 0062;0061 05AE 1DFB 0300 0315 0062;0061 05AE 1DFB 0300 0315 0062; # (a◌᷻◌̕◌̀◌֮b; a◌֮◌᷻◌̀◌̕b; a◌֮◌᷻◌̀◌̕b; a◌֮◌᷻◌̀◌̕b; a◌֮◌᷻◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING DELETION MARK, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 035D 035C 0315 1DFC 0062;0061 0315 035C 1DFC 035D 0062;0061 0315 035C 1DFC 035D 0062;0061 0315 035C 1DFC 035D 0062;0061 0315 035C 1DFC 035D 0062; # (a◌͝◌͜◌̕◌᷼b; a◌̕◌͜◌᷼◌͝b; a◌̕◌͜◌᷼◌͝b; a◌̕◌͜◌᷼◌͝b; a◌̕◌͜◌᷼◌͝b; ) LATIN SMALL LETTER A, COMBINING DOUBLE BREVE, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING DOUBLE INVERTED BREVE BELOW, LATIN SMALL LETTER B
@@ -18397,8 +18409,20 @@ FFEE;FFEE;FFEE;25CB;25CB; # (○; ○; ○; ○; ○; ) HALFWIDTH WHITE CIRCLE
0061 116B7 3099 093C 0334 0062;0061 0334 116B7 093C 3099 0062;0061 0334 116B7 093C 3099 0062;0061 0334 116B7 093C 3099 0062;0061 0334 116B7 093C 3099 0062; # (a◌𑚷◌゙◌़◌̴b; a◌̴◌𑚷◌़◌゙b; a◌̴◌𑚷◌़◌゙b; a◌̴◌𑚷◌़◌゙b; a◌̴◌𑚷◌़◌゙b; ) LATIN SMALL LETTER A, TAKRI SIGN NUKTA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, DEVANAGARI SIGN NUKTA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
0061 05B0 094D 3099 1172B 0062;0061 3099 094D 1172B 05B0 0062;0061 3099 094D 1172B 05B0 0062;0061 3099 094D 1172B 05B0 0062;0061 3099 094D 1172B 05B0 0062; # (a◌ְ◌्◌゙◌𑜫b; a◌゙◌्◌𑜫◌ְb; a◌゙◌्◌𑜫◌ְb; a◌゙◌्◌𑜫◌ְb; a◌゙◌्◌𑜫◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, AHOM SIGN KILLER, LATIN SMALL LETTER B
0061 1172B 05B0 094D 3099 0062;0061 3099 1172B 094D 05B0 0062;0061 3099 1172B 094D 05B0 0062;0061 3099 1172B 094D 05B0 0062;0061 3099 1172B 094D 05B0 0062; # (a◌𑜫◌ְ◌्◌゙b; a◌゙◌𑜫◌्◌ְb; a◌゙◌𑜫◌्◌ְb; a◌゙◌𑜫◌्◌ְb; a◌゙◌𑜫◌्◌ְb; ) LATIN SMALL LETTER A, AHOM SIGN KILLER, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
+0061 05B0 094D 3099 11A34 0062;0061 3099 094D 11A34 05B0 0062;0061 3099 094D 11A34 05B0 0062;0061 3099 094D 11A34 05B0 0062;0061 3099 094D 11A34 05B0 0062; # (a◌ְ◌्◌゙◌𑨴b; a◌゙◌्◌𑨴◌ְb; a◌゙◌्◌𑨴◌ְb; a◌゙◌्◌𑨴◌ְb; a◌゙◌्◌𑨴◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, ZANABAZAR SQUARE SIGN VIRAMA, LATIN SMALL LETTER B
+0061 11A34 05B0 094D 3099 0062;0061 3099 11A34 094D 05B0 0062;0061 3099 11A34 094D 05B0 0062;0061 3099 11A34 094D 05B0 0062;0061 3099 11A34 094D 05B0 0062; # (a◌𑨴◌ְ◌्◌゙b; a◌゙◌𑨴◌्◌ְb; a◌゙◌𑨴◌्◌ְb; a◌゙◌𑨴◌्◌ְb; a◌゙◌𑨴◌्◌ְb; ) LATIN SMALL LETTER A, ZANABAZAR SQUARE SIGN VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
+0061 05B0 094D 3099 11A47 0062;0061 3099 094D 11A47 05B0 0062;0061 3099 094D 11A47 05B0 0062;0061 3099 094D 11A47 05B0 0062;0061 3099 094D 11A47 05B0 0062; # (a◌ְ◌्◌゙◌𑩇b; a◌゙◌्◌𑩇◌ְb; a◌゙◌्◌𑩇◌ְb; a◌゙◌्◌𑩇◌ְb; a◌゙◌्◌𑩇◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, ZANABAZAR SQUARE SUBJOINER, LATIN SMALL LETTER B
+0061 11A47 05B0 094D 3099 0062;0061 3099 11A47 094D 05B0 0062;0061 3099 11A47 094D 05B0 0062;0061 3099 11A47 094D 05B0 0062;0061 3099 11A47 094D 05B0 0062; # (a◌𑩇◌ְ◌्◌゙b; a◌゙◌𑩇◌्◌ְb; a◌゙◌𑩇◌्◌ְb; a◌゙◌𑩇◌्◌ְb; a◌゙◌𑩇◌्◌ְb; ) LATIN SMALL LETTER A, ZANABAZAR SQUARE SUBJOINER, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
+0061 05B0 094D 3099 11A99 0062;0061 3099 094D 11A99 05B0 0062;0061 3099 094D 11A99 05B0 0062;0061 3099 094D 11A99 05B0 0062;0061 3099 094D 11A99 05B0 0062; # (a◌ְ◌्◌゙◌𑪙b; a◌゙◌्◌𑪙◌ְb; a◌゙◌्◌𑪙◌ְb; a◌゙◌्◌𑪙◌ְb; a◌゙◌्◌𑪙◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, SOYOMBO SUBJOINER, LATIN SMALL LETTER B
+0061 11A99 05B0 094D 3099 0062;0061 3099 11A99 094D 05B0 0062;0061 3099 11A99 094D 05B0 0062;0061 3099 11A99 094D 05B0 0062;0061 3099 11A99 094D 05B0 0062; # (a◌𑪙◌ְ◌्◌゙b; a◌゙◌𑪙◌्◌ְb; a◌゙◌𑪙◌्◌ְb; a◌゙◌𑪙◌्◌ְb; a◌゙◌𑪙◌्◌ְb; ) LATIN SMALL LETTER A, SOYOMBO SUBJOINER, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
0061 05B0 094D 3099 11C3F 0062;0061 3099 094D 11C3F 05B0 0062;0061 3099 094D 11C3F 05B0 0062;0061 3099 094D 11C3F 05B0 0062;0061 3099 094D 11C3F 05B0 0062; # (a◌ְ◌्◌゙◌𑰿b; a◌゙◌्◌𑰿◌ְb; a◌゙◌्◌𑰿◌ְb; a◌゙◌्◌𑰿◌ְb; a◌゙◌्◌𑰿◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, BHAIKSUKI SIGN VIRAMA, LATIN SMALL LETTER B
0061 11C3F 05B0 094D 3099 0062;0061 3099 11C3F 094D 05B0 0062;0061 3099 11C3F 094D 05B0 0062;0061 3099 11C3F 094D 05B0 0062;0061 3099 11C3F 094D 05B0 0062; # (a◌𑰿◌ְ◌्◌゙b; a◌゙◌𑰿◌्◌ְb; a◌゙◌𑰿◌्◌ְb; a◌゙◌𑰿◌्◌ְb; a◌゙◌𑰿◌्◌ְb; ) LATIN SMALL LETTER A, BHAIKSUKI SIGN VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
+0061 3099 093C 0334 11D42 0062;0061 0334 093C 11D42 3099 0062;0061 0334 093C 11D42 3099 0062;0061 0334 093C 11D42 3099 0062;0061 0334 093C 11D42 3099 0062; # (a◌゙◌़◌̴◌𑵂b; a◌̴◌़◌𑵂◌゙b; a◌̴◌़◌𑵂◌゙b; a◌̴◌़◌𑵂◌゙b; a◌̴◌़◌𑵂◌゙b; ) LATIN SMALL LETTER A, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, DEVANAGARI SIGN NUKTA, COMBINING TILDE OVERLAY, MASARAM GONDI SIGN NUKTA, LATIN SMALL LETTER B
+0061 11D42 3099 093C 0334 0062;0061 0334 11D42 093C 3099 0062;0061 0334 11D42 093C 3099 0062;0061 0334 11D42 093C 3099 0062;0061 0334 11D42 093C 3099 0062; # (a◌𑵂◌゙◌़◌̴b; a◌̴◌𑵂◌़◌゙b; a◌̴◌𑵂◌़◌゙b; a◌̴◌𑵂◌़◌゙b; a◌̴◌𑵂◌़◌゙b; ) LATIN SMALL LETTER A, MASARAM GONDI SIGN NUKTA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, DEVANAGARI SIGN NUKTA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
+0061 05B0 094D 3099 11D44 0062;0061 3099 094D 11D44 05B0 0062;0061 3099 094D 11D44 05B0 0062;0061 3099 094D 11D44 05B0 0062;0061 3099 094D 11D44 05B0 0062; # (a◌ְ◌्◌゙◌𑵄b; a◌゙◌्◌𑵄◌ְb; a◌゙◌्◌𑵄◌ְb; a◌゙◌्◌𑵄◌ְb; a◌゙◌्◌𑵄◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, MASARAM GONDI SIGN HALANTA, LATIN SMALL LETTER B
+0061 11D44 05B0 094D 3099 0062;0061 3099 11D44 094D 05B0 0062;0061 3099 11D44 094D 05B0 0062;0061 3099 11D44 094D 05B0 0062;0061 3099 11D44 094D 05B0 0062; # (a◌𑵄◌ְ◌्◌゙b; a◌゙◌𑵄◌्◌ְb; a◌゙◌𑵄◌्◌ְb; a◌゙◌𑵄◌्◌ְb; a◌゙◌𑵄◌्◌ְb; ) LATIN SMALL LETTER A, MASARAM GONDI SIGN HALANTA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
+0061 05B0 094D 3099 11D45 0062;0061 3099 094D 11D45 05B0 0062;0061 3099 094D 11D45 05B0 0062;0061 3099 094D 11D45 05B0 0062;0061 3099 094D 11D45 05B0 0062; # (a◌ְ◌्◌゙◌𑵅b; a◌゙◌्◌𑵅◌ְb; a◌゙◌्◌𑵅◌ְb; a◌゙◌्◌𑵅◌ְb; a◌゙◌्◌𑵅◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, MASARAM GONDI VIRAMA, LATIN SMALL LETTER B
+0061 11D45 05B0 094D 3099 0062;0061 3099 11D45 094D 05B0 0062;0061 3099 11D45 094D 05B0 0062;0061 3099 11D45 094D 05B0 0062;0061 3099 11D45 094D 05B0 0062; # (a◌𑵅◌ְ◌्◌゙b; a◌゙◌𑵅◌्◌ְb; a◌゙◌𑵅◌्◌ְb; a◌゙◌𑵅◌्◌ְb; a◌゙◌𑵅◌्◌ְb; ) LATIN SMALL LETTER A, MASARAM GONDI VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
0061 093C 0334 16AF0 0062;0061 0334 16AF0 093C 0062;0061 0334 16AF0 093C 0062;0061 0334 16AF0 093C 0062;0061 0334 16AF0 093C 0062; # (a◌़◌̴◌𖫰b; a◌̴◌𖫰◌़b; a◌̴◌𖫰◌़b; a◌̴◌𖫰◌़b; a◌̴◌𖫰◌़b; ) LATIN SMALL LETTER A, DEVANAGARI SIGN NUKTA, COMBINING TILDE OVERLAY, BASSA VAH COMBINING HIGH TONE, LATIN SMALL LETTER B
0061 16AF0 093C 0334 0062;0061 16AF0 0334 093C 0062;0061 16AF0 0334 093C 0062;0061 16AF0 0334 093C 0062;0061 16AF0 0334 093C 0062; # (a◌𖫰◌़◌̴b; a◌𖫰◌̴◌़b; a◌𖫰◌̴◌़b; a◌𖫰◌̴◌़b; a◌𖫰◌̴◌़b; ) LATIN SMALL LETTER A, BASSA VAH COMBINING HIGH TONE, DEVANAGARI SIGN NUKTA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
0061 093C 0334 16AF1 0062;0061 0334 16AF1 093C 0062;0061 0334 16AF1 093C 0062;0061 0334 16AF1 093C 0062;0061 0334 16AF1 093C 0062; # (a◌़◌̴◌𖫱b; a◌̴◌𖫱◌़b; a◌̴◌𖫱◌़b; a◌̴◌𖫱◌़b; a◌̴◌𖫱◌़b; ) LATIN SMALL LETTER A, DEVANAGARI SIGN NUKTA, COMBINING TILDE OVERLAY, BASSA VAH COMBINING LOW TONE, LATIN SMALL LETTER B
diff --git a/lib/stdlib/test/uri_string_SUITE.erl b/lib/stdlib/test/uri_string_SUITE.erl
new file mode 100644
index 0000000000..4fc0d76be8
--- /dev/null
+++ b/lib/stdlib/test/uri_string_SUITE.erl
@@ -0,0 +1,1164 @@
+%%
+%% %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(uri_string_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+
+-export([all/0, suite/0,groups/0,
+ normalize/1, normalize_map/1, normalize_return_map/1, normalize_negative/1,
+ normalize_binary_pct_encoded_userinfo/1,
+ normalize_binary_pct_encoded_query/1,
+ normalize_binary_pct_encoded_fragment/1,
+ normalize_pct_encoded_userinfo/1,
+ normalize_pct_encoded_query/1,
+ normalize_pct_encoded_fragment/1,
+ parse_binary_fragment/1, parse_binary_host/1, parse_binary_host_ipv4/1,
+ parse_binary_host_ipv6/1,
+ parse_binary_path/1, parse_binary_pct_encoded_fragment/1, parse_binary_pct_encoded_query/1,
+ parse_binary_pct_encoded_userinfo/1, parse_binary_port/1,
+ parse_binary_query/1, parse_binary_scheme/1, parse_binary_userinfo/1,
+ parse_fragment/1, parse_host/1, parse_host_ipv4/1, parse_host_ipv6/1,
+ parse_path/1, parse_pct_encoded_fragment/1, parse_pct_encoded_query/1,
+ parse_pct_encoded_userinfo/1, parse_port/1,
+ parse_query/1, parse_scheme/1, parse_userinfo/1,
+ parse_list/1, parse_binary/1, parse_mixed/1, parse_relative/1,
+ parse_special/1, parse_special2/1, parse_negative/1,
+ recompose_fragment/1, recompose_parse_fragment/1,
+ recompose_query/1, recompose_parse_query/1,
+ recompose_path/1, recompose_parse_path/1,
+ recompose_autogen/1, parse_recompose_autogen/1,
+ transcode_basic/1, transcode_options/1, transcode_mixed/1, transcode_negative/1,
+ compose_query/1, compose_query_latin1/1, compose_query_negative/1,
+ dissect_query/1, dissect_query_negative/1,
+ interop_query_latin1/1, interop_query_utf8/1,
+ regression_parse/1, regression_recompose/1, regression_normalize/1
+ ]).
+
+
+-define(SCHEME, "foo").
+-define(USERINFO, "åsa").
+-define(USERINFO_ENC, "%C3%A5sa").
+-define(HOST, "älvsjö").
+-define(HOST_ENC, "%C3%A4lvsj%C3%B6").
+-define(IPV6, "::127.0.0.1").
+-define(IPV6_ENC, "[::127.0.0.1]").
+-define(PORT, 8042).
+-define(PORT_ENC, ":8042").
+-define(PATH, "/där").
+-define(PATH_ENC, "/d%C3%A4r").
+-define(QUERY, "name=örn").
+-define(QUERY_ENC, "?name=%C3%B6rn").
+-define(FRAGMENT, "näsa").
+-define(FRAGMENT_ENC, "#n%C3%A4sa").
+
+
+suite() ->
+ [{timetrap,{minutes,1}}].
+
+all() ->
+ [
+ normalize,
+ normalize_map,
+ normalize_return_map,
+ normalize_negative,
+ normalize_binary_pct_encoded_userinfo,
+ normalize_binary_pct_encoded_query,
+ normalize_binary_pct_encoded_fragment,
+ normalize_pct_encoded_userinfo,
+ normalize_pct_encoded_query,
+ normalize_pct_encoded_fragment,
+ parse_binary_scheme,
+ parse_binary_userinfo,
+ parse_binary_pct_encoded_userinfo,
+ parse_binary_host,
+ parse_binary_host_ipv4,
+ parse_binary_host_ipv6,
+ parse_binary_port,
+ parse_binary_path,
+ parse_binary_query,
+ parse_binary_pct_encoded_query,
+ parse_binary_fragment,
+ parse_binary_pct_encoded_fragment,
+ parse_scheme,
+ parse_userinfo,
+ parse_pct_encoded_userinfo,
+ parse_host,
+ parse_host_ipv4,
+ parse_host_ipv6,
+ parse_port,
+ parse_path,
+ parse_query,
+ parse_pct_encoded_query,
+ parse_fragment,
+ parse_pct_encoded_fragment,
+ parse_list,
+ parse_binary,
+ parse_mixed,
+ parse_relative,
+ parse_special,
+ parse_special2,
+ parse_negative,
+ recompose_fragment,
+ recompose_parse_fragment,
+ recompose_query,
+ recompose_parse_query,
+ recompose_path,
+ recompose_parse_path,
+ recompose_autogen,
+ parse_recompose_autogen,
+ transcode_basic,
+ transcode_options,
+ transcode_mixed,
+ transcode_negative,
+ compose_query,
+ compose_query_latin1,
+ compose_query_negative,
+ dissect_query,
+ dissect_query_negative,
+ interop_query_latin1,
+ interop_query_utf8,
+ regression_parse,
+ regression_recompose,
+ regression_normalize
+ ].
+
+groups() ->
+ [].
+
+
+%%-------------------------------------------------------------------------
+%% Helper functions
+%%-------------------------------------------------------------------------
+uri_combinations() ->
+ [[Sch,Usr,Hst,Prt,Pat,Qry,Frg] ||
+ Sch <- [fun update_scheme/1, fun update_scheme_binary/1, none],
+ Usr <- [fun update_userinfo/1, fun update_userinfo_binary/1, none],
+ Hst <- [fun update_host/1, fun update_host_binary/1,
+ fun update_ipv6/1, fun update_ipv6_binary/1, none],
+ Prt <- [fun update_port/1, none],
+ Pat <- [fun update_path/1, fun update_path_binary/1],
+ Qry <- [fun update_query/1,fun update_query_binary/1, none],
+ Frg <- [fun update_fragment/1, fun update_fragment_binary/1, none],
+ not (Usr =:= none andalso Hst =:= none andalso Prt =/= none),
+ not (Usr =/= none andalso Hst =:= none andalso Prt =:= none),
+ not (Usr =/= none andalso Hst =:= none andalso Prt =/= none)].
+
+
+generate_test_vector(Comb) ->
+ Fun = fun (F, {Map, URI}) when is_function(F) -> F({Map, URI});
+ (_, Map) -> Map
+ end,
+ lists:foldl(Fun, {#{}, empty}, Comb).
+
+generate_test_vectors(L) ->
+ lists:map(fun generate_test_vector/1, L).
+
+update_fragment({In, empty}) ->
+ {In#{fragment => ?FRAGMENT}, ?FRAGMENT_ENC};
+update_fragment({In, Out}) when is_list(Out) ->
+ {In#{fragment => ?FRAGMENT}, Out ++ ?FRAGMENT_ENC};
+update_fragment({In, Out}) when is_binary(Out) ->
+ {In#{fragment => ?FRAGMENT}, binary_to_list(Out) ++ ?FRAGMENT_ENC}.
+
+update_fragment_binary({In, empty}) ->
+ {In#{fragment => <<?FRAGMENT/utf8>>}, <<?FRAGMENT_ENC>>};
+update_fragment_binary({In, Out}) when is_list(Out) ->
+ {In#{fragment => <<?FRAGMENT/utf8>>}, Out ++ ?FRAGMENT_ENC};
+update_fragment_binary({In, Out}) when is_binary(Out) ->
+ {In#{fragment => <<?FRAGMENT/utf8>>}, <<Out/binary,?FRAGMENT_ENC>>}.
+
+
+update_query({In, empty}) ->
+ {In#{query => ?QUERY}, ?QUERY_ENC};
+update_query({In, Out}) when is_list(Out) ->
+ {In#{query => ?QUERY}, Out ++ ?QUERY_ENC};
+update_query({In, Out}) when is_binary(Out) ->
+ {In#{query => ?QUERY}, binary_to_list(Out) ++ ?QUERY_ENC}.
+
+update_query_binary({In, empty}) ->
+ {In#{query => <<?QUERY/utf8>>}, <<?QUERY_ENC>>};
+update_query_binary({In, Out}) when is_list(Out) ->
+ {In#{query => <<?QUERY/utf8>>}, Out ++ ?QUERY_ENC};
+update_query_binary({In, Out}) when is_binary(Out) ->
+ {In#{query => <<?QUERY/utf8>>}, <<Out/binary,?QUERY_ENC>>}.
+
+update_path({In, empty}) ->
+ {In#{path => ?PATH}, ?PATH_ENC};
+update_path({In, Out}) when is_list(Out) ->
+ {In#{path => ?PATH}, Out ++ ?PATH_ENC};
+update_path({In, Out}) when is_binary(Out) ->
+ {In#{path => ?PATH}, binary_to_list(Out) ++ ?PATH_ENC}.
+
+update_path_binary({In, empty}) ->
+ {In#{path => <<?PATH/utf8>>}, <<?PATH_ENC>>};
+update_path_binary({In, Out}) when is_list(Out) ->
+ {In#{path => <<?PATH/utf8>>}, Out ++ ?PATH_ENC};
+update_path_binary({In, Out}) when is_binary(Out) ->
+ {In#{path => <<?PATH/utf8>>}, <<Out/binary,?PATH_ENC>>}.
+
+update_port({In, Out}) when is_list(Out) ->
+ {In#{port => ?PORT}, Out ++ ?PORT_ENC};
+update_port({In, Out}) when is_binary(Out) ->
+ {In#{port => ?PORT}, <<Out/binary,?PORT_ENC>>}.
+
+update_host({In, empty}) ->
+ {In#{host => ?HOST}, "//" ++ ?HOST_ENC};
+update_host({In, Out}) when is_list(Out) ->
+ case maps:is_key(userinfo, In) of
+ true -> {In#{host => ?HOST}, Out ++ [$@|?HOST_ENC]};
+ false -> {In#{host => ?HOST}, Out ++ [$/,$/|?HOST_ENC]}
+ end;
+update_host({In, Out}) when is_binary(Out) ->
+ case maps:is_key(userinfo, In) of
+ true -> {In#{host => ?HOST}, binary_to_list(Out) ++ [$@|?HOST_ENC]};
+ false -> {In#{host => ?HOST}, binary_to_list(Out) ++ [$/,$/|?HOST_ENC]}
+ end.
+
+update_host_binary({In, empty}) ->
+ {In#{host => <<?HOST/utf8>>}, <<"//",?HOST_ENC>>};
+update_host_binary({In, Out}) when is_list(Out) ->
+ case maps:is_key(userinfo, In) of
+ true -> {In#{host => <<?HOST/utf8>>}, Out ++ [$@|?HOST_ENC]};
+ false -> {In#{host => <<?HOST/utf8>>}, Out ++ [$/,$/|?HOST_ENC]}
+ end;
+update_host_binary({In, Out}) when is_binary(Out) ->
+ case maps:is_key(userinfo, In) of
+ true -> {In#{host => <<?HOST/utf8>>}, <<Out/binary,$@,?HOST_ENC>>};
+ false-> {In#{host => <<?HOST/utf8>>}, <<Out/binary,"//",?HOST_ENC>>}
+ end.
+
+update_ipv6({In, empty}) ->
+ {In#{host => ?IPV6}, "//" ++ ?IPV6_ENC};
+update_ipv6({In, Out}) when is_list(Out) ->
+ case maps:is_key(userinfo, In) of
+ true -> {In#{host => ?IPV6}, Out ++ [$@|?IPV6_ENC]};
+ false -> {In#{host => ?IPV6}, Out ++ [$/,$/|?IPV6_ENC]}
+ end;
+update_ipv6({In, Out}) when is_binary(Out) ->
+ case maps:is_key(userinfo, In) of
+ true -> {In#{host => ?IPV6}, binary_to_list(Out) ++ [$@|?IPV6_ENC]};
+ false -> {In#{host => ?IPV6}, binary_to_list(Out) ++ [$/,$/|?IPV6_ENC]}
+ end.
+
+update_ipv6_binary({In, empty}) ->
+ {In#{host => <<?IPV6/utf8>>}, <<"//",?IPV6_ENC>>};
+update_ipv6_binary({In, Out}) when is_list(Out) ->
+ case maps:is_key(userinfo, In) of
+ true -> {In#{host => <<?IPV6/utf8>>}, Out ++ [$@|?IPV6_ENC]};
+ false -> {In#{host => <<?IPV6/utf8>>}, Out ++ [$/,$/|?IPV6_ENC]}
+ end;
+update_ipv6_binary({In, Out}) when is_binary(Out) ->
+ case maps:is_key(userinfo, In) of
+ true -> {In#{host => <<?IPV6/utf8>>}, <<Out/binary,$@,?IPV6_ENC>>};
+ false-> {In#{host => <<?IPV6/utf8>>}, <<Out/binary,"//",?IPV6_ENC>>}
+ end.
+
+update_userinfo({In, empty}) ->
+ {In#{userinfo => ?USERINFO}, "//" ++ ?USERINFO_ENC};
+update_userinfo({In, Out}) when is_list(Out) ->
+ {In#{userinfo => ?USERINFO}, Out ++ "//" ++ ?USERINFO_ENC};
+update_userinfo({In, Out}) when is_binary(Out) ->
+ {In#{userinfo => ?USERINFO}, binary_to_list(Out) ++ "//" ++ ?USERINFO_ENC}.
+
+update_userinfo_binary({In, empty}) ->
+ {In#{userinfo => <<?USERINFO/utf8>>}, <<"//",?USERINFO_ENC>>};
+update_userinfo_binary({In, Out}) when is_list(Out) ->
+ {In#{userinfo => <<?USERINFO/utf8>>}, Out ++ "//" ++ ?USERINFO_ENC};
+update_userinfo_binary({In, Out}) when is_binary(Out) ->
+ {In#{userinfo => <<?USERINFO/utf8>>}, <<Out/binary,"//",?USERINFO_ENC>>}.
+
+update_scheme({In, empty}) ->
+ {In#{scheme => ?SCHEME}, ?SCHEME ++ ":"}.
+
+update_scheme_binary({In, empty}) ->
+ {In#{scheme => <<?SCHEME/utf8>>}, <<?SCHEME,$:>>}.
+
+
+%% Test recompose on a generated test vector
+run_test_recompose({#{}, empty}) ->
+ try "" = uri_string:recompose(#{}) of
+ _ -> ok
+ catch
+ _:_ -> error({test_failed, #{}, ""})
+ end;
+run_test_recompose({Map, URI}) ->
+ try URI = uri_string:recompose(Map) of
+ URI -> ok
+ catch
+ _:_ -> error({test_failed, Map, URI})
+ end.
+
+%% Test parse - recompose on a generated test vector
+run_test_parse_recompose({#{}, empty}) ->
+ try "" = uri_string:recompose(uri_string:parse("")) of
+ _ -> ok
+ catch
+ _:_ -> error({test_failed, #{}, ""})
+ end;
+run_test_parse_recompose({Map, URI}) ->
+ try URI = uri_string:recompose(uri_string:parse(URI)) of
+ URI -> ok
+ catch
+ _:_ -> error({test_failed, Map, URI})
+ end.
+
+
+%%-------------------------------------------------------------------------
+%% Parse tests
+%%-------------------------------------------------------------------------
+
+parse_binary_scheme(_Config) ->
+ #{} = uri_string:parse(<<>>),
+ #{path := <<"foo">>} = uri_string:parse(<<"foo">>),
+ #{scheme := <<"foo">>} = uri_string:parse(<<"foo:">>),
+ #{scheme := <<"foo">>, path := <<"bar:nisse">>} = uri_string:parse(<<"foo:bar:nisse">>),
+ #{scheme := <<"foo">>, host := <<"">>} = uri_string:parse(<<"foo://">>),
+ #{scheme := <<"foo">>, host := <<"">>, path := <<"/">>} = uri_string:parse(<<"foo:///">>),
+ #{scheme := <<"foo">>, host := <<"">>, path := <<"//">>} = uri_string:parse(<<"foo:////">>),
+
+ #{path := <<"/">>} = uri_string:parse(<<"/">>),
+ #{host := <<>>} = uri_string:parse(<<"//">>),
+ #{host := <<>>, path := <<"/">>} = uri_string:parse(<<"///">>).
+
+parse_binary_userinfo(_Config) ->
+ #{scheme := <<"user">>, path := <<"password@localhost">>} =
+ uri_string:parse(<<"user:password@localhost">>),
+ #{path := <<"user@">>} = uri_string:parse(<<"user@">>),
+ #{path := <<"/user@">>} = uri_string:parse(<<"/user@">>),
+ #{path := <<"user@localhost">>} = uri_string:parse(<<"user@localhost">>),
+ #{userinfo := <<"user">>, host := <<"localhost">>} = uri_string:parse(<<"//user@localhost">>),
+ #{userinfo := <<"user:password">>, host := <<"localhost">>} =
+ uri_string:parse(<<"//user:password@localhost">>),
+ #{scheme := <<"foo">>, path := <<"/user@">>} =
+ uri_string:parse(<<"foo:/user@">>),
+ #{scheme := <<"foo">>, userinfo := <<"user">>, host := <<"localhost">>} =
+ uri_string:parse(<<"foo://user@localhost">>),
+ #{scheme := <<"foo">>, userinfo := <<"user:password">>, host := <<"localhost">>} =
+ uri_string:parse(<<"foo://user:password@localhost">>).
+
+parse_binary_pct_encoded_userinfo(_Config) ->
+ #{scheme := <<"user">>, path := <<"%E5%90%88@%E6%B0%97%E9%81%93">>} =
+ uri_string:parse(<<"user:%E5%90%88@%E6%B0%97%E9%81%93">>),
+ #{path := <<"%E5%90%88%E6%B0%97%E9%81%93@">>} =
+ uri_string:parse(<<"%E5%90%88%E6%B0%97%E9%81%93@">>),
+ #{path := <<"/%E5%90%88%E6%B0%97%E9%81%93@">>} =
+ uri_string:parse(<<"/%E5%90%88%E6%B0%97%E9%81%93@">>),
+ #{path := <<"%E5%90%88@%E6%B0%97%E9%81%93">>} =
+ uri_string:parse(<<"%E5%90%88@%E6%B0%97%E9%81%93">>),
+ #{userinfo := <<"%E5%90%88">>, host := <<"%E6%B0%97%E9%81%93">>} =
+ uri_string:parse(<<"//%E5%90%88@%E6%B0%97%E9%81%93">>),
+ #{userinfo := <<"%E5%90%88:%E6%B0%97">>, host := <<"%E9%81%93">>} =
+ uri_string:parse(<<"//%E5%90%88:%E6%B0%97@%E9%81%93">>),
+ #{scheme := <<"foo">>, path := <<"/%E5%90%88%E6%B0%97%E9%81%93@">>} =
+ uri_string:parse(<<"foo:/%E5%90%88%E6%B0%97%E9%81%93@">>),
+ #{scheme := <<"foo">>, userinfo := <<"%E5%90%88">>, host := <<"%E6%B0%97%E9%81%93">>} =
+ uri_string:parse(<<"foo://%E5%90%88@%E6%B0%97%E9%81%93">>),
+ #{scheme := <<"foo">>, userinfo := <<"%E5%90%88:%E6%B0%97">>, host := <<"%E9%81%93">>} =
+ uri_string:parse(<<"foo://%E5%90%88:%E6%B0%97@%E9%81%93">>),
+ {error,invalid_uri,"@"} = uri_string:parse(<<"//%E5%90%88@%E6%B0%97%E9%81%93@">>),
+ {error,invalid_uri,":"} = uri_string:parse(<<"foo://%E5%90%88@%E6%B0%97%E9%81%93@">>).
+
+parse_binary_host(_Config) ->
+ #{host := <<"hostname">>} = uri_string:parse(<<"//hostname">>),
+ #{host := <<"hostname">>,scheme := <<"foo">>} = uri_string:parse(<<"foo://hostname">>),
+ #{host := <<"hostname">>,scheme := <<"foo">>, userinfo := <<"user">>} =
+ uri_string:parse(<<"foo://user@hostname">>).
+
+parse_binary_host_ipv4(_Config) ->
+ #{host := <<"127.0.0.1">>} = uri_string:parse(<<"//127.0.0.1">>),
+ #{host := <<"127.0.0.1">>, path := <<"/over/there">>} =
+ uri_string:parse(<<"//127.0.0.1/over/there">>),
+ #{host := <<"127.0.0.1">>, query := <<"name=ferret">>} =
+ uri_string:parse(<<"//127.0.0.1?name=ferret">>),
+ #{host := <<"127.0.0.1">>, fragment := <<"nose">>} = uri_string:parse(<<"//127.0.0.1#nose">>),
+ #{host := <<"127.0.0.x">>,path := <<>>} = uri_string:parse(<<"//127.0.0.x">>),
+ #{host := <<"1227.0.0.1">>,path := <<>>} = uri_string:parse(<<"//1227.0.0.1">>).
+
+parse_binary_host_ipv6(_Config) ->
+ #{host := <<"::127.0.0.1">>} = uri_string:parse(<<"//[::127.0.0.1]">>),
+ #{host := <<"2001:0db8:0000:0000:0000:0000:1428:07ab">>} =
+ uri_string:parse(<<"//[2001:0db8:0000:0000:0000:0000:1428:07ab]">>),
+ #{host := <<"::127.0.0.1">>, path := <<"/over/there">>} =
+ uri_string:parse(<<"//[::127.0.0.1]/over/there">>),
+ #{host := <<"::127.0.0.1">>, query := <<"name=ferret">>} =
+ uri_string:parse(<<"//[::127.0.0.1]?name=ferret">>),
+ #{host := <<"::127.0.0.1">>, fragment := <<"nose">>} =
+ uri_string:parse(<<"//[::127.0.0.1]#nose">>),
+ {error,invalid_uri,"x"} = uri_string:parse(<<"//[::127.0.0.x]">>),
+ {error,invalid_uri,"::1227.0.0.1"} = uri_string:parse(<<"//[::1227.0.0.1]">>),
+ {error,invalid_uri,"G"} = uri_string:parse(<<"//[2001:0db8:0000:0000:0000:0000:1428:G7ab]">>).
+
+parse_binary_port(_Config) ->
+ #{path:= <<"/:8042">>} =
+ uri_string:parse(<<"/:8042">>),
+ #{host:= <<>>, port := 8042} =
+ uri_string:parse(<<"//:8042">>),
+ #{host := <<"example.com">>, port:= 8042} =
+ uri_string:parse(<<"//example.com:8042">>),
+ #{scheme := <<"foo">>, path := <<"/:8042">>} =
+ uri_string:parse(<<"foo:/:8042">>),
+ #{scheme := <<"foo">>, host := <<>>, port := 8042} =
+ uri_string:parse(<<"foo://:8042">>),
+ #{scheme := <<"foo">>, host := <<"example.com">>, port := 8042} =
+ uri_string:parse(<<"foo://example.com:8042">>),
+ {error,invalid_uri,":"} = uri_string:parse(":600"),
+ {error,invalid_uri,"x"} = uri_string:parse("//:8042x").
+
+parse_binary_path(_Config) ->
+ #{path := <<"over/there">>} = uri_string:parse(<<"over/there">>),
+ #{path := <<"/over/there">>} = uri_string:parse(<<"/over/there">>),
+ #{scheme := <<"foo">>, path := <<"/over/there">>} =
+ uri_string:parse(<<"foo:/over/there">>),
+ #{scheme := <<"foo">>, host := <<"example.com">>, path := <<"/over/there">>} =
+ uri_string:parse(<<"foo://example.com/over/there">>),
+ #{scheme := <<"foo">>, host := <<"example.com">>, path := <<"/over/there">>, port := 8042} =
+ uri_string:parse(<<"foo://example.com:8042/over/there">>).
+
+parse_binary_query(_Config) ->
+ #{scheme := <<"foo">>, query := <<"name=ferret">>} =
+ uri_string:parse(<<"foo:?name=ferret">>),
+ #{scheme := <<"foo">>, path:= <<"over/there">>, query := <<"name=ferret">>} =
+ uri_string:parse(<<"foo:over/there?name=ferret">>),
+ #{scheme := <<"foo">>, path:= <<"/over/there">>, query := <<"name=ferret">>} =
+ uri_string:parse(<<"foo:/over/there?name=ferret">>),
+ #{scheme := <<"foo">>, host := <<"example.com">>, query := <<"name=ferret">>} =
+ uri_string:parse(<<"foo://example.com?name=ferret">>),
+ #{scheme := <<"foo">>, host := <<"example.com">>, path := <<"/">>, query := <<"name=ferret">>} =
+ uri_string:parse(<<"foo://example.com/?name=ferret">>),
+
+ #{path := <<>>, query := <<"name=ferret">>} =
+ uri_string:parse(<<"?name=ferret">>),
+ #{path := <<"over/there">>, query := <<"name=ferret">>} =
+ uri_string:parse(<<"over/there?name=ferret">>),
+ #{path := <<"/">>, query := <<"name=ferret">>} =
+ uri_string:parse(<<"/?name=ferret">>),
+ #{path := <<"/over/there">>, query := <<"name=ferret">>} =
+ uri_string:parse(<<"/over/there?name=ferret">>),
+ #{host := <<"example.com">>, query := <<"name=ferret">>} =
+ uri_string:parse(<<"//example.com?name=ferret">>),
+ #{host := <<"example.com">>, path := <<"/">>, query := <<"name=ferret">>} =
+ uri_string:parse(<<"//example.com/?name=ferret">>).
+
+parse_binary_pct_encoded_query(_Config) ->
+ #{scheme := <<"foo">>, host := <<"example.com">>, path := <<"/">>,
+ query := <<"name=%E5%90%88%E6%B0%97%E9%81%93">>} =
+ uri_string:parse(<<"foo://example.com/?name=%E5%90%88%E6%B0%97%E9%81%93">>),
+ #{host := <<"example.com">>, path := <<"/">>, query := <<"name=%E5%90%88%E6%B0%97%E9%81%93">>} =
+ uri_string:parse(<<"//example.com/?name=%E5%90%88%E6%B0%97%E9%81%93">>).
+
+parse_binary_fragment(_Config) ->
+ #{scheme := <<"foo">>, fragment := <<"nose">>} =
+ uri_string:parse(<<"foo:#nose">>),
+ #{scheme := <<"foo">>, path:= <<"over/there">>, fragment := <<"nose">>} =
+ uri_string:parse(<<"foo:over/there#nose">>),
+ #{scheme := <<"foo">>, path:= <<"/over/there">>, fragment := <<"nose">>} =
+ uri_string:parse(<<"foo:/over/there#nose">>),
+ #{scheme := <<"foo">>, host := <<"example.com">>, fragment := <<"nose">>} =
+ uri_string:parse(<<"foo://example.com#nose">>),
+ #{scheme := <<"foo">>, host := <<"example.com">>, path := <<"/">>, fragment := <<"nose">>} =
+ uri_string:parse(<<"foo://example.com/#nose">>),
+ #{scheme := <<"foo">>, host := <<"example.com">>, fragment := <<"nose">>} =
+ uri_string:parse(<<"foo://example.com#nose">>),
+
+ #{fragment := <<"nose">>} =
+ uri_string:parse(<<"#nose">>),
+ #{path := <<"over/there">>, fragment := <<"nose">>} =
+ uri_string:parse(<<"over/there#nose">>),
+ #{path := <<"/">>, fragment := <<"nose">>} =
+ uri_string:parse(<<"/#nose">>),
+ #{path := <<"/over/there">>, fragment := <<"nose">>} =
+ uri_string:parse(<<"/over/there#nose">>),
+ #{host := <<"example.com">>, fragment := <<"nose">>} =
+ uri_string:parse(<<"//example.com#nose">>),
+ #{host := <<"example.com">>, path := <<"/">>, fragment := <<"nose">>} =
+ uri_string:parse(<<"//example.com/#nose">>).
+
+parse_binary_pct_encoded_fragment(_Config) ->
+ #{scheme := <<"foo">>, host := <<"example.com">>,
+ fragment := <<"%E5%90%88%E6%B0%97%E9%81%93">>} =
+ uri_string:parse(<<"foo://example.com#%E5%90%88%E6%B0%97%E9%81%93">>),
+ #{host := <<"example.com">>, path := <<"/">>,
+ fragment := <<"%E5%90%88%E6%B0%97%E9%81%93">>} =
+ uri_string:parse(<<"//example.com/#%E5%90%88%E6%B0%97%E9%81%93">>).
+
+parse_scheme(_Config) ->
+ #{} = uri_string:parse(""),
+ #{path := "foo"} = uri_string:parse("foo"),
+ #{scheme := "foo"} = uri_string:parse("foo:"),
+ #{scheme := "foo", path := "bar:nisse"} = uri_string:parse("foo:bar:nisse"),
+ #{scheme := "foo", host := ""} = uri_string:parse("foo://"),
+ #{scheme := "foo", host := "", path := "/"} = uri_string:parse("foo:///"),
+ #{scheme := "foo", host := "", path := "//"} = uri_string:parse("foo:////"),
+
+ #{path := "/"} = uri_string:parse("/"),
+ #{host := ""} = uri_string:parse("//"),
+ #{host := "", path := "/"} = uri_string:parse("///").
+
+parse_userinfo(_Config) ->
+ #{scheme := "user", path := "password@localhost"} = uri_string:parse("user:password@localhost"),
+ #{path := "user@"} = uri_string:parse("user@"),
+ #{path := "/user@"} = uri_string:parse("/user@"),
+ #{path := "user@localhost"} = uri_string:parse("user@localhost"),
+ #{userinfo := "user", host := "localhost"} = uri_string:parse("//user@localhost"),
+ #{userinfo := "user:password", host := "localhost"} =
+ uri_string:parse("//user:password@localhost"),
+ #{scheme := "foo", path := "/user@"} =
+ uri_string:parse("foo:/user@"),
+ #{scheme := "foo", userinfo := "user", host := "localhost"} =
+ uri_string:parse("foo://user@localhost"),
+ #{scheme := "foo", userinfo := "user:password", host := "localhost"} =
+ uri_string:parse("foo://user:password@localhost").
+
+parse_pct_encoded_userinfo(_Config) ->
+ #{scheme := "user", path := "%E5%90%88@%E6%B0%97%E9%81%93"} =
+ uri_string:parse("user:%E5%90%88@%E6%B0%97%E9%81%93"),
+ #{path := "%E5%90%88%E6%B0%97%E9%81%93@"} =
+ uri_string:parse("%E5%90%88%E6%B0%97%E9%81%93@"),
+ #{path := "/%E5%90%88%E6%B0%97%E9%81%93@"} =
+ uri_string:parse("/%E5%90%88%E6%B0%97%E9%81%93@"),
+ #{path := "%E5%90%88@%E6%B0%97%E9%81%93"} =
+ uri_string:parse("%E5%90%88@%E6%B0%97%E9%81%93"),
+ #{userinfo := "%E5%90%88", host := "%E6%B0%97%E9%81%93"} =
+ uri_string:parse("//%E5%90%88@%E6%B0%97%E9%81%93"),
+ #{userinfo := "%E5%90%88:%E6%B0%97", host := "%E9%81%93"} =
+ uri_string:parse("//%E5%90%88:%E6%B0%97@%E9%81%93"),
+ #{scheme := "foo", path := "/%E5%90%88%E6%B0%97%E9%81%93@"} =
+ uri_string:parse("foo:/%E5%90%88%E6%B0%97%E9%81%93@"),
+ #{scheme := "foo", userinfo := "%E5%90%88", host := "%E6%B0%97%E9%81%93"} =
+ uri_string:parse("foo://%E5%90%88@%E6%B0%97%E9%81%93"),
+ #{scheme := "foo", userinfo := "%E5%90%88:%E6%B0%97", host := "%E9%81%93"} =
+ uri_string:parse("foo://%E5%90%88:%E6%B0%97@%E9%81%93"),
+ {error,invalid_uri,"@"} = uri_string:parse("//%E5%90%88@%E6%B0%97%E9%81%93@"),
+ {error,invalid_uri,":"} = uri_string:parse("foo://%E5%90%88@%E6%B0%97%E9%81%93@").
+
+parse_host(_Config) ->
+ #{host := "hostname"} = uri_string:parse("//hostname"),
+ #{host := "hostname",scheme := "foo"} = uri_string:parse("foo://hostname"),
+ #{host := "hostname",scheme := "foo", userinfo := "user"} =
+ uri_string:parse("foo://user@hostname").
+
+parse_host_ipv4(_Config) ->
+ #{host := "127.0.0.1"} = uri_string:parse("//127.0.0.1"),
+ #{host := "2001:0db8:0000:0000:0000:0000:1428:07ab"} =
+ uri_string:parse("//[2001:0db8:0000:0000:0000:0000:1428:07ab]"),
+ #{host := "127.0.0.1", path := "/over/there"} = uri_string:parse("//127.0.0.1/over/there"),
+ #{host := "127.0.0.1", query := "name=ferret"} = uri_string:parse("//127.0.0.1?name=ferret"),
+ #{host := "127.0.0.1", fragment := "nose"} = uri_string:parse("//127.0.0.1#nose"),
+ #{host := "127.0.0.x",path := []} = uri_string:parse("//127.0.0.x"),
+ #{host := "1227.0.0.1",path := []} = uri_string:parse("//1227.0.0.1").
+
+parse_host_ipv6(_Config) ->
+ #{host := "::127.0.0.1"} = uri_string:parse("//[::127.0.0.1]"),
+ #{host := "::127.0.0.1", path := "/over/there"} = uri_string:parse("//[::127.0.0.1]/over/there"),
+ #{host := "::127.0.0.1", query := "name=ferret"} =
+ uri_string:parse("//[::127.0.0.1]?name=ferret"),
+ #{host := "::127.0.0.1", fragment := "nose"} = uri_string:parse("//[::127.0.0.1]#nose"),
+ {error,invalid_uri,"x"} = uri_string:parse("//[::127.0.0.x]"),
+ {error,invalid_uri,"::1227.0.0.1"} = uri_string:parse("//[::1227.0.0.1]"),
+ {error,invalid_uri,"G"} = uri_string:parse("//[2001:0db8:0000:0000:0000:0000:1428:G7ab]").
+
+parse_port(_Config) ->
+ #{path:= "/:8042"} =
+ uri_string:parse("/:8042"),
+ #{host:= "", port := 8042} =
+ uri_string:parse("//:8042"),
+ #{host := "example.com", port:= 8042} =
+ uri_string:parse("//example.com:8042"),
+ #{scheme := "foo", path := "/:8042"} =
+ uri_string:parse("foo:/:8042"),
+ #{scheme := "foo", host := "", port := 8042} =
+ uri_string:parse("foo://:8042"),
+ #{scheme := "foo", host := "example.com", port := 8042} =
+ uri_string:parse("foo://example.com:8042").
+
+parse_path(_Config) ->
+ #{path := "over/there"} = uri_string:parse("over/there"),
+ #{path := "/over/there"} = uri_string:parse("/over/there"),
+ #{scheme := "foo", path := "/over/there"} =
+ uri_string:parse("foo:/over/there"),
+ #{scheme := "foo", host := "example.com", path := "/over/there"} =
+ uri_string:parse("foo://example.com/over/there"),
+ #{scheme := "foo", host := "example.com", path := "/over/there", port := 8042} =
+ uri_string:parse("foo://example.com:8042/over/there").
+
+parse_query(_Config) ->
+ #{scheme := "foo", query := "name=ferret"} =
+ uri_string:parse("foo:?name=ferret"),
+ #{scheme := "foo", path:= "over/there", query := "name=ferret"} =
+ uri_string:parse("foo:over/there?name=ferret"),
+ #{scheme := "foo", path:= "/over/there", query := "name=ferret"} =
+ uri_string:parse("foo:/over/there?name=ferret"),
+ #{scheme := "foo", host := "example.com", query := "name=ferret"} =
+ uri_string:parse("foo://example.com?name=ferret"),
+ #{scheme := "foo", host := "example.com", path := "/", query := "name=ferret"} =
+ uri_string:parse("foo://example.com/?name=ferret"),
+
+ #{path := "", query := "name=ferret"} =
+ uri_string:parse("?name=ferret"),
+ #{path := "over/there", query := "name=ferret"} =
+ uri_string:parse("over/there?name=ferret"),
+ #{path := "/", query := "name=ferret"} =
+ uri_string:parse("/?name=ferret"),
+ #{path := "/over/there", query := "name=ferret"} =
+ uri_string:parse("/over/there?name=ferret"),
+ #{host := "example.com", query := "name=ferret"} =
+ uri_string:parse("//example.com?name=ferret"),
+ #{host := "example.com", path := "/", query := "name=ferret"} =
+ uri_string:parse("//example.com/?name=ferret").
+
+parse_pct_encoded_query(_Config) ->
+ #{scheme := "foo", host := "example.com", path := "/",
+ query := "name=%E5%90%88%E6%B0%97%E9%81%93"} =
+ uri_string:parse("foo://example.com/?name=%E5%90%88%E6%B0%97%E9%81%93"),
+ #{host := "example.com", path := "/", query := "name=%E5%90%88%E6%B0%97%E9%81%93"} =
+ uri_string:parse("//example.com/?name=%E5%90%88%E6%B0%97%E9%81%93").
+
+parse_fragment(_Config) ->
+ #{scheme := "foo", fragment := "nose"} =
+ uri_string:parse("foo:#nose"),
+ #{scheme := "foo", path:= "over/there", fragment := "nose"} =
+ uri_string:parse("foo:over/there#nose"),
+ #{scheme := "foo", path:= "/over/there", fragment := "nose"} =
+ uri_string:parse("foo:/over/there#nose"),
+ #{scheme := "foo", host := "example.com", fragment := "nose"} =
+ uri_string:parse("foo://example.com#nose"),
+ #{scheme := "foo", host := "example.com", path := "/", fragment := "nose"} =
+ uri_string:parse("foo://example.com/#nose"),
+ #{scheme := "foo", host := "example.com", fragment := "nose"} =
+ uri_string:parse("foo://example.com#nose"),
+
+ #{fragment := "nose"} =
+ uri_string:parse("#nose"),
+ #{path := "over/there", fragment := "nose"} =
+ uri_string:parse("over/there#nose"),
+ #{path := "/", fragment := "nose"} =
+ uri_string:parse("/#nose"),
+ #{path := "/over/there", fragment := "nose"} =
+ uri_string:parse("/over/there#nose"),
+ #{host := "example.com", fragment := "nose"} =
+ uri_string:parse("//example.com#nose"),
+ #{host := "example.com", path := "/", fragment := "nose"} =
+ uri_string:parse("//example.com/#nose").
+
+parse_pct_encoded_fragment(_Config) ->
+ #{scheme := "foo", host := "example.com",
+ fragment := "%E5%90%88%E6%B0%97%E9%81%93"} =
+ uri_string:parse("foo://example.com#%E5%90%88%E6%B0%97%E9%81%93"),
+ #{host := "example.com", path := "/",
+ fragment := "%E5%90%88%E6%B0%97%E9%81%93"} =
+ uri_string:parse("//example.com/#%E5%90%88%E6%B0%97%E9%81%93").
+
+parse_list(_Config) ->
+ #{scheme := "foo", path := "bar:nisse"} = uri_string:parse("foo:bar:nisse"),
+ #{scheme := "foo", host := "example.com", port := 8042,
+ path := "/over/there", query := "name=ferret", fragment := "nose"} =
+ uri_string:parse("foo://example.com:8042/over/there?name=ferret#nose"),
+ #{scheme := "foo", userinfo := "admin:admin", host := "example.com", port := 8042,
+ path := "/over/there", query := "name=ferret", fragment := "nose"} =
+ uri_string:parse("foo://admin:[email protected]:8042/over/there?name=ferret#nose").
+
+parse_binary(_Config) ->
+ #{scheme := <<"foo">>, path := <<"bar:nisse">>} = uri_string:parse(<<"foo:bar:nisse">>),
+ #{scheme := <<"foo">>, host := <<"example.com">>, port := 8042,
+ path := <<"/over/there">>, query := <<"name=ferret">>, fragment := <<"nose">>} =
+ uri_string:parse(<<"foo://example.com:8042/over/there?name=ferret#nose">>),
+ #{scheme := <<"foo">>, userinfo := <<"admin:admin">>, host := <<"example.com">>, port := 8042,
+ path := <<"/over/there">>, query := <<"name=ferret">>, fragment := <<"nose">>} =
+ uri_string:parse(<<"foo://admin:[email protected]:8042/over/there?name=ferret#nose">>).
+
+
+parse_mixed(_Config) ->
+ #{scheme := "foo", path := "bar"} =
+ uri_string:parse(lists:append("fo",<<"o:bar">>)),
+ #{scheme := "foo", path := "bar"} =
+ uri_string:parse(lists:append("foo:b",<<"ar">>)),
+ #{scheme := "foo", path := "bar:bar"} =
+ uri_string:parse([[102],[111,111],<<":bar">>,58,98,97,114]).
+
+parse_relative(_Config) ->
+ #{path := "/path"} =
+ uri_string:parse(lists:append("/pa",<<"th">>)),
+ #{path := "foo"} =
+ uri_string:parse(lists:append("fo",<<"o">>)).
+
+parse_special(_Config) ->
+ #{host := [],query := []} = uri_string:parse("//?"),
+ #{fragment := [],host := []} = uri_string:parse("//#"),
+ #{host := [],query := [],scheme := "foo"} = uri_string:parse("foo://?"),
+ #{fragment := [],host := [],scheme := "foo"} = uri_string:parse("foo://#"),
+ #{host := <<>>, path := <<"/">>} = uri_string:parse(<<"///">>),
+ #{host := <<"hostname">>} = uri_string:parse(<<"//hostname">>),
+ #{host := <<>>, path := <<"/hostname">>} = uri_string:parse(<<"///hostname">>),
+ #{host := [],path := "/",query := []} = uri_string:parse("///?"),
+ #{fragment := [],host := [],path := "/"} = uri_string:parse("///#"),
+ #{host := "foo",query := []} = uri_string:parse("//foo?"),
+ #{fragment := [],host := "foo"} = uri_string:parse("//foo#"),
+ #{host := "foo",path := "/"} = uri_string:parse("//foo/"),
+ #{host := "foo",query := [],scheme := "http"} = uri_string:parse("http://foo?"),
+ #{fragment := [],host := "foo",scheme := "http"} = uri_string:parse("http://foo#"),
+ #{host := "foo",path := "/",scheme := "http"} = uri_string:parse("http://foo/"),
+ #{fragment := [],host := "host",port := 80,scheme := "http"} = uri_string:parse("http://host:80#"),
+ #{host := "host",port := 80,query := [],scheme := "http"} = uri_string:parse("http://host:80?"),
+ #{path := [],query := []} = uri_string:parse("?"),
+ #{path := [],query := "?"} = uri_string:parse("??"),
+ #{path := [],query := "??"} = uri_string:parse("???").
+
+parse_special2(_Config) ->
+ #{host := [],path := "/",port := 1,scheme := "a"} = uri_string:parse("a://:1/"),
+ #{path := "/a/",scheme := "a"} = uri_string:parse("a:/a/"),
+ #{host := [],path := [],userinfo := []} = uri_string:parse("//@"),
+ #{host := [],path := [],scheme := "foo",userinfo := []} = uri_string:parse("foo://@"),
+ #{host := [],path := "/",userinfo := []} = uri_string:parse("//@/"),
+ #{host := [],path := "/",scheme := "foo",userinfo := []} = uri_string:parse("foo://@/"),
+ #{host := "localhost",path := "/",port := undefined} = uri_string:parse("//localhost:/"),
+ #{host := [],path := [],port := undefined} = uri_string:parse("//:").
+
+parse_negative(_Config) ->
+ {error,invalid_uri,"å"} = uri_string:parse("å"),
+ {error,invalid_uri,"å"} = uri_string:parse("aå:/foo"),
+ {error,invalid_uri,":"} = uri_string:parse("foo://usär@host"),
+ {error,invalid_uri,"ö"} = uri_string:parse("//host/path?foö=bar"),
+ {error,invalid_uri,"ö"} = uri_string:parse("//host/path#foö"),
+ {error,invalid_uri,":::127.0.0.1"} = uri_string:parse("//[:::127.0.0.1]"),
+ {error,invalid_uri,"A"} = uri_string:parse("//localhost:A8").
+
+
+%%-------------------------------------------------------------------------
+%% Recompose tests
+%%-------------------------------------------------------------------------
+recompose_fragment(_Config) ->
+ <<?FRAGMENT_ENC>> = uri_string:recompose(#{fragment => <<?FRAGMENT/utf8>>, path => <<>>}),
+ ?FRAGMENT_ENC = uri_string:recompose(#{fragment => ?FRAGMENT, path => ""}).
+
+recompose_parse_fragment(_Config) ->
+ <<?FRAGMENT_ENC>> = uri_string:recompose(uri_string:parse(<<?FRAGMENT_ENC>>)),
+ ?FRAGMENT_ENC = uri_string:recompose(uri_string:parse(?FRAGMENT_ENC)).
+
+recompose_query(_Config) ->
+ <<?QUERY_ENC>> =
+ uri_string:recompose(#{query => <<?QUERY/utf8>>, path => <<>>}),
+ <<?QUERY_ENC?FRAGMENT_ENC>> =
+ uri_string:recompose(#{query => <<?QUERY/utf8>>,
+ fragment => <<?FRAGMENT/utf8>>,
+ path => <<>>}),
+ "?name=%C3%B6rn" =
+ uri_string:recompose(#{query => "name=örn", path => ""}),
+ "?name=%C3%B6rn#n%C3%A4sa" =
+ uri_string:recompose(#{query => "name=örn",
+ fragment => "näsa",
+ path => ""}).
+
+recompose_parse_query(_Config) ->
+ <<"?name=%C3%B6rn">> = uri_string:recompose(uri_string:parse(<<"?name=%C3%B6rn">>)),
+ <<"?name=%C3%B6rn#n%C3%A4sa">> =
+ uri_string:recompose(uri_string:parse(<<"?name=%C3%B6rn#n%C3%A4sa">>)),
+ "?name=%C3%B6rn" = uri_string:recompose(uri_string:parse("?name=%C3%B6rn")),
+ "?name=%C3%B6rn#n%C3%A4sa" = uri_string:recompose(uri_string:parse("?name=%C3%B6rn#n%C3%A4sa")).
+
+recompose_path(_Config) ->
+ <<"/d%C3%A4r">> =
+ uri_string:recompose(#{path => <<"/där"/utf8>>}),
+ <<"/d%C3%A4r#n%C3%A4sa">> =
+ uri_string:recompose(#{path => <<"/där"/utf8>>,
+ fragment => <<"näsa"/utf8>>}),
+ <<"/d%C3%A4r?name=%C3%B6rn">> =
+ uri_string:recompose(#{path => <<"/där"/utf8>>,
+ query => <<"name=örn"/utf8>>}),
+ <<"/d%C3%A4r?name=%C3%B6rn#n%C3%A4sa">> =
+ uri_string:recompose(#{path => <<"/där"/utf8>>,
+ query => <<"name=örn"/utf8>>,
+ fragment => <<"näsa"/utf8>>}),
+
+
+ "/d%C3%A4r" =
+ uri_string:recompose(#{path => "/där"}),
+ "/d%C3%A4r#n%C3%A4sa" =
+ uri_string:recompose(#{path => "/där",
+ fragment => "näsa"}),
+ "/d%C3%A4r?name=%C3%B6rn" =
+ uri_string:recompose(#{path => "/där",
+ query => "name=örn"}),
+ "/d%C3%A4r?name=%C3%B6rn#n%C3%A4sa" =
+ uri_string:recompose(#{path => "/där",
+ query => "name=örn",
+ fragment => "näsa"}).
+
+
+recompose_parse_path(_Config) ->
+ <<"/d%C3%A4r">> =
+ uri_string:recompose(uri_string:parse(<<"/d%C3%A4r">>)),
+ <<"/d%C3%A4r#n%C3%A4sa">> =
+ uri_string:recompose(uri_string:parse(<<"/d%C3%A4r#n%C3%A4sa">>)),
+ <<"/d%C3%A4r?name=%C3%B6rn">> =
+ uri_string:recompose(uri_string:parse(<<"/d%C3%A4r?name=%C3%B6rn">>)),
+
+ "/d%C3%A4r" =
+ uri_string:recompose(uri_string:parse("/d%C3%A4r")),
+ "/d%C3%A4r#n%C3%A4sa" =
+ uri_string:recompose(uri_string:parse("/d%C3%A4r#n%C3%A4sa")),
+ "/d%C3%A4r?name=%C3%B6rn" =
+ uri_string:recompose(uri_string:parse("/d%C3%A4r?name=%C3%B6rn")).
+
+
+recompose_autogen(_Config) ->
+ Tests = generate_test_vectors(uri_combinations()),
+ lists:map(fun run_test_recompose/1, Tests).
+
+parse_recompose_autogen(_Config) ->
+ Tests = generate_test_vectors(uri_combinations()),
+ lists:map(fun run_test_parse_recompose/1, Tests).
+
+transcode_basic(_Config) ->
+ <<"foo%C3%B6bar"/utf8>> =
+ uri_string:transcode(<<"foo%00%00%00%F6bar"/utf32>>, [{in_encoding, utf32},{out_encoding, utf8}]),
+ "foo%C3%B6bar" =
+ uri_string:transcode("foo%00%00%00%F6bar", [{in_encoding, utf32},{out_encoding, utf8}]),
+ <<"foo%00%00%00%F6bar"/utf32>> =
+ uri_string:transcode(<<"foo%C3%B6bar"/utf8>>, [{in_encoding, utf8},{out_encoding, utf32}]),
+ "foo%00%00%00%F6bar" =
+ uri_string:transcode("foo%C3%B6bar", [{in_encoding, utf8},{out_encoding, utf32}]),
+ "foo%C3%B6bar" =
+ uri_string:transcode("foo%F6bar", [{in_encoding, latin1},{out_encoding, utf8}]).
+
+transcode_options(_Config) ->
+ <<"foo%C3%B6bar"/utf8>> =
+ uri_string:transcode(<<"foo%C3%B6bar"/utf8>>, []),
+ <<"foo%C3%B6bar"/utf8>> =
+ uri_string:transcode(<<"foo%00%00%00%F6bar"/utf32>>, [{in_encoding, utf32}]),
+ <<"foo%00%00%00%F6bar"/utf32>> =
+ uri_string:transcode(<<"foo%C3%B6bar"/utf8>>, [{out_encoding, utf32}]).
+
+transcode_mixed(_Config) ->
+ "foo%00%00%00%F6bar" =
+ uri_string:transcode(["foo",<<"%C3%B6"/utf8>>,<<"ba"/utf8>>,"r"], [{out_encoding, utf32}]),
+ "foo%00%00%00%F6bar" =
+ uri_string:transcode(["foo",<<"%C3%"/utf8>>,<<"B6ba"/utf8>>,"r"], [{out_encoding, utf32}]),
+ "foo%C3%B6bar" =
+ uri_string:transcode(["foo%00", <<"%00%0"/utf32>>,<<"0%F"/utf32>>,"6bar"], [{in_encoding, utf32},{out_encoding, utf8}]).
+
+transcode_negative(_Config) ->
+ {error,invalid_percent_encoding,"%BXbar"} =
+ uri_string:transcode(<<"foo%C3%BXbar"/utf8>>, [{in_encoding, utf8},{out_encoding, utf32}]),
+ {error,invalid_input,<<"ö">>} =
+ uri_string:transcode("foo%F6bar", [{in_encoding, utf8},{out_encoding, utf8}]).
+
+compose_query(_Config) ->
+ [] = uri_string:compose_query([]),
+ "foo=1&bar=2" = uri_string:compose_query([{<<"foo">>,"1"}, {"bar", "2"}]),
+ "foo=1&b%C3%A4r=2" = uri_string:compose_query([{"foo","1"}, {"bär", "2"}],[{encoding,utf8}]),
+ "foo=1&b%C3%A4r=2" = uri_string:compose_query([{"foo","1"}, {"bär", "2"}],[{encoding,unicode}]),
+ "foo=1&b%E4r=2" = uri_string:compose_query([{"foo","1"}, {"bär", "2"}],[{encoding,latin1}]),
+ "foo+bar=1&%E5%90%88=2" = uri_string:compose_query([{"foo bar","1"}, {"合", "2"}]),
+ "foo+bar=1&%26%2321512%3B=2" =
+ uri_string:compose_query([{"foo bar","1"}, {"合", "2"}],[{encoding,latin1}]),
+ "foo+bar=1&%C3%B6=2" = uri_string:compose_query([{<<"foo bar">>,<<"1">>}, {"ö", <<"2">>}]),
+ <<"foo+bar=1&%C3%B6=2">> =
+ uri_string:compose_query([{<<"foo bar">>,<<"1">>}, {<<"ö"/utf8>>, <<"2">>}]).
+
+compose_query_latin1(_Config) ->
+ Q = uri_string:compose_query([{"合foö bar","1"}, {"合", "合"}],[{encoding,latin1}]),
+ Q1 = uri_string:transcode(Q, [{in_encoding, latin1}]),
+ [{"合foö bar","1"}, {"合", "合"}] = uri_string:dissect_query(Q1),
+ Q2 = uri_string:compose_query([{<<"合foö bar"/utf8>>,<<"1">>}, {<<"合"/utf8>>, <<"合"/utf8>>}],
+ [{encoding,latin1}]),
+ Q3 = uri_string:transcode(Q2, [{in_encoding, latin1}]),
+ [{<<"合foö bar"/utf8>>,<<"1">>}, {<<"合"/utf8>>, <<"合"/utf8>>}] =
+ uri_string:dissect_query(Q3).
+
+compose_query_negative(_Config) ->
+ {error,invalid_input,4} = uri_string:compose_query([{"",4}]),
+ {error,invalid_input,5} = uri_string:compose_query([{5,""}]),
+ {error,invalid_encoding,utf16} =
+ uri_string:compose_query([{"foo bar","1"}, {<<"ö">>, "2"}],[{encoding,utf16}]).
+
+dissect_query(_Config) ->
+ [] = uri_string:dissect_query(""),
+ [{"foo","1"}, {"amp;bar", "2"}] = uri_string:dissect_query("foo=1&amp;bar=2"),
+ [{"foo","1"}, {"bar", "2"}] = uri_string:dissect_query("foo=1&bar=2"),
+ [{"foo","1;bar=2"}] = uri_string:dissect_query("foo=1;bar=2"),
+ [{"foo","1"}, {"bar", "222"}] = uri_string:dissect_query([<<"foo=1&bar=2">>,"22"]),
+ [{"foo","ö"}, {"bar", "2"}] = uri_string:dissect_query("foo=%C3%B6&bar=2"),
+ [{<<"foo">>,<<"ö"/utf8>>}, {<<"bar">>, <<"2">>}] =
+ uri_string:dissect_query(<<"foo=%C3%B6&bar=2">>),
+ [{"foo bar","1"},{"ö","2"}] =
+ uri_string:dissect_query([<<"foo+bar=1&">>,<<"%C3%B6=2">>]),
+ [{"foo bar","1"},{[21512],"2"}] =
+ uri_string:dissect_query("foo+bar=1&%26%2321512%3B=2"),
+ [{<<"foo bar">>,<<"1">>},{<<"合"/utf8>>,<<"2">>}] =
+ uri_string:dissect_query(<<"foo+bar=1&%26%2321512%3B=2">>),
+ [{"föo bar","1"},{"ö","2"}] =
+ uri_string:dissect_query("föo+bar=1&%C3%B6=2"),
+ [{<<"föo bar"/utf8>>,<<"1">>},{<<"ö"/utf8>>,<<"2">>}] =
+ uri_string:dissect_query(<<"föo+bar=1&%C3%B6=2"/utf8>>).
+
+dissect_query_negative(_Config) ->
+ {error,missing_value,"&"} =
+ uri_string:dissect_query("foo1&bar=2"),
+ {error,invalid_percent_encoding,"%XX%B6"} = uri_string:dissect_query("foo=%XX%B6&amp;bar=2"),
+ {error,invalid_input,[153]} =
+ uri_string:dissect_query("foo=%99%B6&amp;bar=2"),
+ {error,invalid_character,"ö"} = uri_string:dissect_query(<<"föo+bar=1&%C3%B6=2">>),
+ {error,invalid_input,<<"ö">>} =
+ uri_string:dissect_query([<<"foo+bar=1&amp;">>,<<"%C3%B6=2ö">>]).
+
+normalize(_Config) ->
+ "/a/g" = uri_string:normalize("/a/b/c/./../../g"),
+ <<"mid/6">> = uri_string:normalize(<<"mid/content=5/../6">>),
+ "http://localhost-%C3%B6rebro/a/g" =
+ uri_string:normalize("http://localhos%74-%c3%b6rebro:80/a/b/c/./../../g"),
+ <<"http://localhost-%C3%B6rebro/a/g">> =
+ uri_string:normalize(<<"http://localhos%74-%c3%b6rebro:80/a/b/c/./../../g">>),
+ <<"https://localhost/">> =
+ uri_string:normalize(<<"https://localhost:443">>),
+ <<"https://localhost:445/">> =
+ uri_string:normalize(<<"https://localhost:445">>),
+ <<"ftp://localhost">> =
+ uri_string:normalize(<<"ftp://localhost:21">>),
+ <<"ssh://localhost">> =
+ uri_string:normalize(<<"ssh://localhost:22">>),
+ <<"sftp://localhost">> =
+ uri_string:normalize(<<"sftp://localhost:22">>),
+ <<"tftp://localhost">> =
+ uri_string:normalize(<<"tftp://localhost:69">>),
+ <<"/foo/%2F/bar">> =
+ uri_string:normalize(<<"/foo/%2f/%62ar">>).
+
+normalize_map(_Config) ->
+ "/a/g" = uri_string:normalize(#{path => "/a/b/c/./../../g"}),
+ <<"mid/6">> = uri_string:normalize(#{path => <<"mid/content=5/../6">>}),
+ "http://localhost-%C3%B6rebro/a/g" =
+ uri_string:normalize(#{scheme => "http",port => 80,path => "/a/b/c/./../../g",
+ host => "localhost-örebro"}),
+ <<"http://localhost-%C3%B6rebro/a/g">> =
+ uri_string:normalize(#{scheme => <<"http">>,port => 80,
+ path => <<"/a/b/c/./../../g">>,
+ host => <<"localhost-örebro"/utf8>>}),
+ <<"https://localhost/">> =
+ uri_string:normalize(#{scheme => <<"https">>,port => 443,path => <<>>,
+ host => <<"localhost">>}),
+ <<"https://localhost:445/">> =
+ uri_string:normalize(#{scheme => <<"https">>,port => 445,path => <<>>,
+ host => <<"localhost">>}),
+ <<"ftp://localhost">> =
+ uri_string:normalize(#{scheme => <<"ftp">>,port => 21,path => <<>>,
+ host => <<"localhost">>}),
+ <<"ssh://localhost">> =
+ uri_string:normalize(#{scheme => <<"ssh">>,port => 22,path => <<>>,
+ host => <<"localhost">>}),
+ <<"sftp://localhost">> =
+ uri_string:normalize(#{scheme => <<"sftp">>,port => 22,path => <<>>,
+ host => <<"localhost">>}),
+ <<"tftp://localhost">> =
+ uri_string:normalize(#{scheme => <<"tftp">>,port => 69,path => <<>>,
+ host => <<"localhost">>}),
+ "/foo/%2F/bar" =
+ uri_string:normalize(#{path => "/foo/%2f/%62ar"}).
+
+normalize_return_map(_Config) ->
+ #{scheme := "http",path := "/a/g",host := "localhost-örebro"} =
+ uri_string:normalize("http://localhos%74-%c3%b6rebro:80/a/b/c/./../../g",
+ [return_map]),
+ #{scheme := <<"http">>,path := <<"/a/g">>, host := <<"localhost-örebro"/utf8>>} =
+ uri_string:normalize(<<"http://localhos%74-%c3%b6rebro:80/a/b/c/./../../g">>,
+ [return_map]),
+ #{scheme := <<"https">>,path := <<"/">>, host := <<"localhost">>} =
+ uri_string:normalize(#{scheme => <<"https">>,port => 443,path => <<>>,
+ host => <<"localhost">>}, [return_map]).
+
+normalize_negative(_Config) ->
+ {error,invalid_uri,":"} =
+ uri_string:normalize("http://local>host"),
+ {error,invalid_uri,":"} =
+ uri_string:normalize(<<"http://local>host">>),
+ {error,invalid_uri,":"} =
+ uri_string:normalize("http://[192.168.0.1]", [return_map]),
+ {error,invalid_uri,":"} =
+ uri_string:normalize(<<"http://[192.168.0.1]">>, [return_map]),
+ {error,invalid_utf8,<<0,0,0,246>>} = uri_string:normalize("//%00%00%00%F6").
+
+normalize_binary_pct_encoded_userinfo(_Config) ->
+ #{scheme := <<"user">>, path := <<"合@気道"/utf8>>} =
+ uri_string:normalize(<<"user:%E5%90%88@%E6%B0%97%E9%81%93">>, [return_map]),
+ #{path := <<"合気道@"/utf8>>} =
+ uri_string:normalize(<<"%E5%90%88%E6%B0%97%E9%81%93@">>, [return_map]),
+ #{path := <<"/合気道@"/utf8>>} =
+ uri_string:normalize(<<"/%E5%90%88%E6%B0%97%E9%81%93@">>, [return_map]),
+ #{path := <<"合@気道"/utf8>>} =
+ uri_string:normalize(<<"%E5%90%88@%E6%B0%97%E9%81%93">>, [return_map]),
+ #{userinfo := <<"合"/utf8>>, host := <<"気道"/utf8>>} =
+ uri_string:normalize(<<"//%E5%90%88@%E6%B0%97%E9%81%93">>, [return_map]),
+ #{userinfo := <<"合:気"/utf8>>, host := <<"道"/utf8>>} =
+ uri_string:normalize(<<"//%E5%90%88:%E6%B0%97@%E9%81%93">>, [return_map]),
+ #{scheme := <<"foo">>, path := <<"/合気道@"/utf8>>} =
+ uri_string:normalize(<<"foo:/%E5%90%88%E6%B0%97%E9%81%93@">>, [return_map]),
+ #{scheme := <<"foo">>, userinfo := <<"合"/utf8>>, host := <<"気道"/utf8>>} =
+ uri_string:normalize(<<"foo://%E5%90%88@%E6%B0%97%E9%81%93">>, [return_map]),
+ #{scheme := <<"foo">>, userinfo := <<"合:気"/utf8>>, host := <<"道"/utf8>>} =
+ uri_string:normalize(<<"foo://%E5%90%88:%E6%B0%97@%E9%81%93">>, [return_map]),
+ {error,invalid_uri,"@"} =
+ uri_string:normalize(<<"//%E5%90%88@%E6%B0%97%E9%81%93@">>, [return_map]),
+ {error,invalid_uri,":"} =
+ uri_string:normalize(<<"foo://%E5%90%88@%E6%B0%97%E9%81%93@">>, [return_map]).
+
+normalize_binary_pct_encoded_query(_Config) ->
+ #{scheme := <<"foo">>, host := <<"example.com">>, path := <<"/">>,
+ query := <<"name=合気道"/utf8>>} =
+ uri_string:normalize(<<"foo://example.com/?name=%E5%90%88%E6%B0%97%E9%81%93">>, [return_map]),
+ #{host := <<"example.com">>, path := <<"/">>, query := <<"name=合気道"/utf8>>} =
+ uri_string:normalize(<<"//example.com/?name=%E5%90%88%E6%B0%97%E9%81%93">>, [return_map]).
+
+normalize_binary_pct_encoded_fragment(_Config) ->
+ #{scheme := <<"foo">>, host := <<"example.com">>, fragment := <<"合気道"/utf8>>} =
+ uri_string:normalize(<<"foo://example.com#%E5%90%88%E6%B0%97%E9%81%93">>, [return_map]),
+ #{host := <<"example.com">>, path := <<"/">>, fragment := <<"合気道"/utf8>>} =
+ uri_string:normalize(<<"//example.com/#%E5%90%88%E6%B0%97%E9%81%93">>, [return_map]).
+
+normalize_pct_encoded_userinfo(_Config) ->
+ #{scheme := "user", path := "合@気道"} =
+ uri_string:normalize("user:%E5%90%88@%E6%B0%97%E9%81%93", [return_map]),
+ #{path := "合気道@"} =
+ uri_string:normalize("%E5%90%88%E6%B0%97%E9%81%93@", [return_map]),
+ #{path := "/合気道@"} =
+ uri_string:normalize("/%E5%90%88%E6%B0%97%E9%81%93@", [return_map]),
+ #{path := "合@気道"} =
+ uri_string:normalize("%E5%90%88@%E6%B0%97%E9%81%93", [return_map]),
+ #{userinfo := "合", host := "気道"} =
+ uri_string:normalize("//%E5%90%88@%E6%B0%97%E9%81%93", [return_map]),
+ #{userinfo := "合:気", host := "道"} =
+ uri_string:normalize("//%E5%90%88:%E6%B0%97@%E9%81%93", [return_map]),
+ #{scheme := "foo", path := "/合気道@"} =
+ uri_string:normalize("foo:/%E5%90%88%E6%B0%97%E9%81%93@", [return_map]),
+ #{scheme := "foo", userinfo := "合", host := "気道"} =
+ uri_string:normalize("foo://%E5%90%88@%E6%B0%97%E9%81%93", [return_map]),
+ #{scheme := "foo", userinfo := "合:気", host := "道"} =
+ uri_string:normalize("foo://%E5%90%88:%E6%B0%97@%E9%81%93", [return_map]),
+ {error,invalid_uri,"@"} =
+ uri_string:normalize("//%E5%90%88@%E6%B0%97%E9%81%93@", [return_map]),
+ {error,invalid_uri,":"} =
+ uri_string:normalize("foo://%E5%90%88@%E6%B0%97%E9%81%93@", [return_map]).
+
+normalize_pct_encoded_query(_Config) ->
+ #{scheme := "foo", host := "example.com", path := "/",
+ query := "name=合気道"} =
+ uri_string:normalize("foo://example.com/?name=%E5%90%88%E6%B0%97%E9%81%93", [return_map]),
+ #{host := "example.com", path := "/", query := "name=合気道"} =
+ uri_string:normalize("//example.com/?name=%E5%90%88%E6%B0%97%E9%81%93", [return_map]).
+
+normalize_pct_encoded_fragment(_Config) ->
+ #{scheme := "foo", host := "example.com", fragment := "合気道"} =
+ uri_string:normalize("foo://example.com#%E5%90%88%E6%B0%97%E9%81%93", [return_map]),
+ #{host := "example.com", path := "/", fragment := "合気道"} =
+ uri_string:normalize("//example.com/#%E5%90%88%E6%B0%97%E9%81%93", [return_map]).
+
+interop_query_utf8(_Config) ->
+ Q = uri_string:compose_query([{"foo bar","1"}, {"合", "2"}]),
+ Uri = uri_string:recompose(#{path => "/", query => Q}),
+ #{query := Q1} = uri_string:parse(Uri),
+ [{"foo bar","1"}, {"合", "2"}] = uri_string:dissect_query(Q1).
+
+interop_query_latin1(_Config) ->
+ Q = uri_string:compose_query([{"foo bar","1"}, {"合", "2"}], [{encoding,latin1}]),
+ Uri = uri_string:recompose(#{path => "/", query => Q}),
+ Uri1 = uri_string:transcode(Uri, [{in_encoding, latin1}]),
+ #{query := Q1} = uri_string:parse(Uri1),
+ [{"foo bar","1"}, {"合", "2"}] = uri_string:dissect_query(Q1).
+
+regression_parse(_Config) ->
+ #{host := "Bar",path := [],scheme := "FOo"} =
+ uri_string:parse("FOo://Bar"),
+ #{host := "bar",path := [],scheme := "foo"} =
+ uri_string:parse("foo://bar"),
+ #{host := "A%2f",path := "/%62ar",scheme := "foo"} =
+ uri_string:parse("foo://A%2f/%62ar"),
+ #{host := "a%2F",path := "/bar",scheme := "foo"} =
+ uri_string:parse("foo://a%2F/bar"),
+ #{host := "%C3%B6",path := [],scheme := "FOo"} =
+ uri_string:parse("FOo://%C3%B6").
+
+regression_recompose(_Config) ->
+ "FOo://Bar" =
+ uri_string:recompose(#{host => "Bar",path => [],scheme => "FOo"}),
+ "foo://bar" =
+ uri_string:recompose(#{host => "bar",path => [],scheme => "foo"}),
+ "foo://A%2f/%62ar" =
+ uri_string:recompose(#{host => "A%2f",path => "/%62ar",scheme => "foo"}),
+ "foo://a%2F/bar" =
+ uri_string:recompose(#{host => "a%2F",path => "/bar",scheme => "foo"}),
+ "FOo://%C3%B6" =
+ uri_string:recompose(#{host => "%C3%B6",path => [],scheme => "FOo"}),
+ "FOo://%C3%B6" =
+ uri_string:recompose(#{host => "ö",path => [],scheme => "FOo"}).
+
+regression_normalize(_Config) ->
+ "foo://bar" =
+ uri_string:normalize("FOo://Bar"),
+ #{host := "bar",path := [],scheme := "foo"} =
+ uri_string:normalize("FOo://Bar", [return_map]),
+
+ "foo://bar" =
+ uri_string:normalize("foo://bar"),
+ #{host := "bar",path := [],scheme := "foo"} =
+ uri_string:normalize("foo://bar", [return_map]),
+
+ "foo://a%2F/bar" =
+ uri_string:normalize("foo://A%2f/%62ar"),
+ #{host := "a%2F",path := "/bar",scheme := "foo"} =
+ uri_string:normalize("foo://A%2f/%62ar", [return_map]),
+
+ "foo://a%2F/bar" =
+ uri_string:normalize("foo://a%2F/bar"),
+ #{host := "a%2F",path := "/bar",scheme := "foo"} =
+ uri_string:normalize("foo://a%2F/bar", [return_map]),
+
+ "foo://%C3%B6" =
+ uri_string:normalize("FOo://%C3%B6"),
+ #{host := "ö",path := [],scheme := "foo"} =
+ uri_string:normalize("FOo://%C3%B6", [return_map]),
+
+
+ "foo://bar" =
+ uri_string:normalize(#{host => "Bar",path => [],scheme => "FOo"}),
+ #{host := "bar",path := [],scheme := "foo"} =
+ uri_string:normalize(#{host => "Bar",path => [],scheme => "FOo"}, [return_map]),
+
+ "foo://bar" =
+ uri_string:normalize(#{host => "bar",path => [],scheme => "foo"}),
+ #{host := "bar",path := [],scheme := "foo"} =
+ uri_string:normalize(#{host => "bar",path => [],scheme => "foo"}, [return_map]),
+
+ "foo://a%2F/bar" =
+ uri_string:normalize(#{host => "A%2f",path => "/%62ar",scheme => "foo"}),
+ #{host := "a%2F",path := "/bar",scheme := "foo"} =
+ uri_string:normalize(#{host => "A%2f",path => "/%62ar",scheme => "foo"}, [return_map]),
+
+ "foo://a%2F/bar" =
+ uri_string:normalize(#{host => "a%2F",path => "/bar",scheme => "foo"}),
+ #{host := "a%2F",path := "/bar",scheme := "foo"} =
+ uri_string:normalize(#{host => "a%2F",path => "/bar",scheme => "foo"}, [return_map]),
+
+ "foo://%C3%B6" =
+ uri_string:normalize(#{host => "%C3%B6",path => [],scheme => "FOo"}),
+ #{host := "ö",path := [],scheme := "foo"} =
+ uri_string:normalize(#{host => "%C3%B6",path => [],scheme => "FOo"}, [return_map]),
+
+ "foo://%C3%B6" =
+ uri_string:normalize(#{host => "ö",path => [],scheme => "FOo"}),
+ #{host := "ö",path := [],scheme := "foo"} =
+ uri_string:normalize(#{host => "ö",path => [],scheme => "FOo"}, [return_map]).
diff --git a/lib/stdlib/test/uri_string_property_test_SUITE.erl b/lib/stdlib/test/uri_string_property_test_SUITE.erl
new file mode 100644
index 0000000000..f1d27924db
--- /dev/null
+++ b/lib/stdlib/test/uri_string_property_test_SUITE.erl
@@ -0,0 +1,44 @@
+%%
+%% %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(uri_string_property_test_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-compile(export_all).
+
+all() -> [recompose, normalize].
+
+init_per_suite(Config) ->
+ ct_property_test:init_per_suite(Config).
+
+end_per_suite(Config) ->
+ Config.
+
+%%%========================================================================
+%%% Test suites
+%%%========================================================================
+recompose(Config) ->
+ ct_property_test:quickcheck(
+ uri_string_recompose:prop_recompose(),
+ Config).
+
+normalize(Config) ->
+ ct_property_test:quickcheck(
+ uri_string_recompose:prop_normalize(),
+ Config).
diff --git a/lib/stdlib/test/zip_SUITE.erl b/lib/stdlib/test/zip_SUITE.erl
index 1dfcda4ed0..081bffa7cb 100644
--- a/lib/stdlib/test/zip_SUITE.erl
+++ b/lib/stdlib/test/zip_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -909,8 +909,7 @@ do_fd_leak(Bad, N) ->
ok ->
do_fd_leak(Bad, N + 1)
catch
- C:R ->
- Stk = erlang:get_stacktrace(),
+ C:R:Stk ->
io:format("Bad error after ~p attempts\n", [N]),
erlang:raise(C, R, Stk)
end.
diff --git a/lib/stdlib/test/zzz_SUITE.erl b/lib/stdlib/test/zzz_SUITE.erl
new file mode 100644
index 0000000000..59c7fd7404
--- /dev/null
+++ b/lib/stdlib/test/zzz_SUITE.erl
@@ -0,0 +1,37 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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(zzz_SUITE).
+
+%% The sole purpose of this test suite is for things we want to run last
+%% before the VM terminates.
+
+-export([all/0]).
+
+-export([lc_graph/1]).
+
+
+all() ->
+ [lc_graph].
+
+lc_graph(_Config) ->
+ %% Create "lc_graph" file in current working dir
+ %% if lock checker is enabled.
+ erts_debug:lc_graph(),
+ ok.
diff --git a/lib/stdlib/uc_spec/CaseFolding.txt b/lib/stdlib/uc_spec/CaseFolding.txt
index 372ee68bd8..efdf18e441 100644
--- a/lib/stdlib/uc_spec/CaseFolding.txt
+++ b/lib/stdlib/uc_spec/CaseFolding.txt
@@ -1,6 +1,6 @@
-# CaseFolding-9.0.0.txt
-# Date: 2016-03-02, 18:54:54 GMT
-# © 2016 Unicode®, Inc.
+# CaseFolding-10.0.0.txt
+# Date: 2017-04-14, 05:40:18 GMT
+# © 2017 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
@@ -24,7 +24,7 @@
#
# NOTE: case folding does not preserve normalization formats!
#
-# For information on case folding, including how to have case folding
+# For information on case folding, including how to have case folding
# preserve normalization formats, see Section 3.13 Default Case Algorithms in
# The Unicode Standard.
#
diff --git a/lib/stdlib/uc_spec/CompositionExclusions.txt b/lib/stdlib/uc_spec/CompositionExclusions.txt
index 1999ed1328..ff42508686 100644
--- a/lib/stdlib/uc_spec/CompositionExclusions.txt
+++ b/lib/stdlib/uc_spec/CompositionExclusions.txt
@@ -1,6 +1,6 @@
-# CompositionExclusions-9.0.0.txt
-# Date: 2016-01-21, 22:00:00 GMT [KW, LI]
-# © 2016 Unicode®, Inc.
+# CompositionExclusions-10.0.0.txt
+# Date: 2017-02-15, 00:00:00 GMT [KW, LI]
+# © 2017 Unicode®, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
# Unicode Character Database
diff --git a/lib/stdlib/uc_spec/GraphemeBreakProperty.txt b/lib/stdlib/uc_spec/GraphemeBreakProperty.txt
index c5e94a3762..32bb12e47e 100644
--- a/lib/stdlib/uc_spec/GraphemeBreakProperty.txt
+++ b/lib/stdlib/uc_spec/GraphemeBreakProperty.txt
@@ -1,6 +1,6 @@
-# GraphemeBreakProperty-9.0.0.txt
-# Date: 2016-06-03, 22:23:55 GMT
-# © 2016 Unicode®, Inc.
+# GraphemeBreakProperty-10.0.0.txt
+# Date: 2017-03-12, 07:03:41 GMT
+# © 2017 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
@@ -25,8 +25,11 @@
0D4E ; Prepend # Lo MALAYALAM LETTER DOT REPH
110BD ; Prepend # Cf KAITHI NUMBER SIGN
111C2..111C3 ; Prepend # Lo [2] SHARADA SIGN JIHVAMULIYA..SHARADA SIGN UPADHMANIYA
+11A3A ; Prepend # Lo ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA
+11A86..11A89 ; Prepend # Lo [4] SOYOMBO CLUSTER-INITIAL LETTER RA..SOYOMBO CLUSTER-INITIAL LETTER SA
+11D46 ; Prepend # Lo MASARAM GONDI REPHA
-# Total code points: 13
+# Total code points: 19
# ================================================
@@ -126,6 +129,7 @@ E01F0..E0FFF ; Control # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
0AC7..0AC8 ; Extend # Mn [2] GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN AI
0ACD ; Extend # Mn GUJARATI SIGN VIRAMA
0AE2..0AE3 ; Extend # Mn [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL
+0AFA..0AFF ; Extend # Mn [6] GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE
0B01 ; Extend # Mn ORIYA SIGN CANDRABINDU
0B3C ; Extend # Mn ORIYA SIGN NUKTA
0B3E ; Extend # Mc ORIYA VOWEL SIGN AA
@@ -154,7 +158,8 @@ E01F0..E0FFF ; Control # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
0CCC..0CCD ; Extend # Mn [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA
0CD5..0CD6 ; Extend # Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK
0CE2..0CE3 ; Extend # Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL
-0D01 ; Extend # Mn MALAYALAM SIGN CANDRABINDU
+0D00..0D01 ; Extend # Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU
+0D3B..0D3C ; Extend # Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA
0D3E ; Extend # Mc MALAYALAM VOWEL SIGN AA
0D41..0D44 ; Extend # Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR
0D4D ; Extend # Mn MALAYALAM SIGN VIRAMA
@@ -243,7 +248,7 @@ E01F0..E0FFF ; Control # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
1CED ; Extend # Mn VEDIC SIGN TIRYAK
1CF4 ; Extend # Mn VEDIC TONE CANDRA ABOVE
1CF8..1CF9 ; Extend # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE
-1DC0..1DF5 ; Extend # Mn [54] COMBINING DOTTED GRAVE ACCENT..COMBINING UP TACK ABOVE
+1DC0..1DF9 ; Extend # Mn [58] COMBINING DOTTED GRAVE ACCENT..COMBINING WIDE INVERTED BRIDGE BELOW
1DFB..1DFF ; Extend # Mn [5] COMBINING DELETION MARK..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW
200C ; Extend # Cf ZERO WIDTH NON-JOINER
20D0..20DC ; Extend # Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE
@@ -353,6 +358,15 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT
1171D..1171F ; Extend # Mn [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA
11722..11725 ; Extend # Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU
11727..1172B ; Extend # Mn [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER
+11A01..11A06 ; Extend # Mn [6] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL SIGN O
+11A09..11A0A ; Extend # Mn [2] ZANABAZAR SQUARE VOWEL SIGN REVERSED I..ZANABAZAR SQUARE VOWEL LENGTH MARK
+11A33..11A38 ; Extend # Mn [6] ZANABAZAR SQUARE FINAL CONSONANT MARK..ZANABAZAR SQUARE SIGN ANUSVARA
+11A3B..11A3E ; Extend # Mn [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA
+11A47 ; Extend # Mn ZANABAZAR SQUARE SUBJOINER
+11A51..11A56 ; Extend # Mn [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE
+11A59..11A5B ; Extend # Mn [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK
+11A8A..11A96 ; Extend # Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA
+11A98..11A99 ; Extend # Mn [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER
11C30..11C36 ; Extend # Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L
11C38..11C3D ; Extend # Mn [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA
11C3F ; Extend # Mn BHAIKSUKI SIGN VIRAMA
@@ -360,6 +374,11 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT
11CAA..11CB0 ; Extend # Mn [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA
11CB2..11CB3 ; Extend # Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E
11CB5..11CB6 ; Extend # Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU
+11D31..11D36 ; Extend # Mn [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R
+11D3A ; Extend # Mn MASARAM GONDI VOWEL SIGN E
+11D3C..11D3D ; Extend # Mn [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O
+11D3F..11D45 ; Extend # Mn [7] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI VIRAMA
+11D47 ; Extend # Mn MASARAM GONDI RA-KARA
16AF0..16AF4 ; Extend # Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE
16B30..16B36 ; Extend # Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM
16F8F..16F92 ; Extend # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW
@@ -387,7 +406,7 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT
E0020..E007F ; Extend # Cf [96] TAG SPACE..CANCEL TAG
E0100..E01EF ; Extend # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
-# Total code points: 1828
+# Total code points: 1901
# ================================================
@@ -472,6 +491,7 @@ E0100..E01EF ; Extend # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
1C34..1C35 ; SpacingMark # Mc [2] LEPCHA CONSONANT SIGN NYIN-DO..LEPCHA CONSONANT SIGN KANG
1CE1 ; SpacingMark # Mc VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA
1CF2..1CF3 ; SpacingMark # Mc [2] VEDIC SIGN ARDHAVISARGA..VEDIC SIGN ROTATED ARDHAVISARGA
+1CF7 ; SpacingMark # Mc VEDIC SIGN ATIKRAMA
A823..A824 ; SpacingMark # Mc [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I
A827 ; SpacingMark # Mc SYLOTI NAGRI VOWEL SIGN OO
A880..A881 ; SpacingMark # Mc [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA
@@ -529,6 +549,10 @@ ABEC ; SpacingMark # Mc MEETEI MAYEK LUM IYEK
116B6 ; SpacingMark # Mc TAKRI SIGN VIRAMA
11720..11721 ; SpacingMark # Mc [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA
11726 ; SpacingMark # Mc AHOM VOWEL SIGN E
+11A07..11A08 ; SpacingMark # Mc [2] ZANABAZAR SQUARE VOWEL SIGN AI..ZANABAZAR SQUARE VOWEL SIGN AU
+11A39 ; SpacingMark # Mc ZANABAZAR SQUARE SIGN VISARGA
+11A57..11A58 ; SpacingMark # Mc [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU
+11A97 ; SpacingMark # Mc SOYOMBO SIGN VISARGA
11C2F ; SpacingMark # Mc BHAIKSUKI VOWEL SIGN AA
11C3E ; SpacingMark # Mc BHAIKSUKI SIGN VISARGA
11CA9 ; SpacingMark # Mc MARCHEN SUBJOINED LETTER YA
@@ -538,7 +562,7 @@ ABEC ; SpacingMark # Mc MEETEI MAYEK LUM IYEK
1D166 ; SpacingMark # Mc MUSICAL SYMBOL COMBINING SPRECHGESANG STEM
1D16D ; SpacingMark # Mc MUSICAL SYMBOL COMBINING AUGMENTATION DOT
-# Total code points: 341
+# Total code points: 348
# ================================================
@@ -1375,8 +1399,9 @@ D789..D7A3 ; LVT # Lo [27] HANGUL SYLLABLE HIG..HANGUL SYLLABLE HIH
26F9 ; E_Base # So PERSON WITH BALL
270A..270D ; E_Base # So [4] RAISED FIST..WRITING HAND
1F385 ; E_Base # So FATHER CHRISTMAS
-1F3C3..1F3C4 ; E_Base # So [2] RUNNER..SURFER
-1F3CA..1F3CB ; E_Base # So [2] SWIMMER..WEIGHT LIFTER
+1F3C2..1F3C4 ; E_Base # So [3] SNOWBOARDER..SURFER
+1F3C7 ; E_Base # So HORSE RACING
+1F3CA..1F3CC ; E_Base # So [3] SWIMMER..GOLFER
1F442..1F443 ; E_Base # So [2] EAR..NOSE
1F446..1F450 ; E_Base # So [11] WHITE UP POINTING BACKHAND INDEX..OPEN HANDS SIGN
1F46E ; E_Base # So POLICE OFFICER
@@ -1385,7 +1410,7 @@ D789..D7A3 ; LVT # Lo [27] HANGUL SYLLABLE HIG..HANGUL SYLLABLE HIH
1F481..1F483 ; E_Base # So [3] INFORMATION DESK PERSON..DANCER
1F485..1F487 ; E_Base # So [3] NAIL POLISH..HAIRCUT
1F4AA ; E_Base # So FLEXED BICEPS
-1F575 ; E_Base # So SLEUTH OR SPY
+1F574..1F575 ; E_Base # So [2] MAN IN BUSINESS SUIT LEVITATING..SLEUTH OR SPY
1F57A ; E_Base # So MAN DANCING
1F590 ; E_Base # So RAISED HAND WITH FINGERS SPLAYED
1F595..1F596 ; E_Base # So [2] REVERSED HAND WITH MIDDLE FINGER EXTENDED..RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERS
@@ -1394,13 +1419,15 @@ D789..D7A3 ; LVT # Lo [27] HANGUL SYLLABLE HIG..HANGUL SYLLABLE HIH
1F6A3 ; E_Base # So ROWBOAT
1F6B4..1F6B6 ; E_Base # So [3] BICYCLIST..PEDESTRIAN
1F6C0 ; E_Base # So BATH
-1F918..1F91E ; E_Base # So [7] SIGN OF THE HORNS..HAND WITH INDEX AND MIDDLE FINGERS CROSSED
+1F6CC ; E_Base # So SLEEPING ACCOMMODATION
+1F918..1F91C ; E_Base # So [5] SIGN OF THE HORNS..RIGHT-FACING FIST
+1F91E..1F91F ; E_Base # So [2] HAND WITH INDEX AND MIDDLE FINGERS CROSSED..I LOVE YOU HAND SIGN
1F926 ; E_Base # So FACE PALM
-1F930 ; E_Base # So PREGNANT WOMAN
-1F933..1F939 ; E_Base # So [7] SELFIE..JUGGLING
-1F93C..1F93E ; E_Base # So [3] WRESTLERS..HANDBALL
+1F930..1F939 ; E_Base # So [10] PREGNANT WOMAN..JUGGLING
+1F93D..1F93E ; E_Base # So [2] WATER POLO..HANDBALL
+1F9D1..1F9DD ; E_Base # So [13] ADULT..ELF
-# Total code points: 79
+# Total code points: 98
# ================================================
@@ -1416,11 +1443,28 @@ D789..D7A3 ; LVT # Lo [27] HANGUL SYLLABLE HIG..HANGUL SYLLABLE HIH
# ================================================
+2640 ; Glue_After_Zwj # So FEMALE SIGN
+2642 ; Glue_After_Zwj # So MALE SIGN
+2695..2696 ; Glue_After_Zwj # So [2] STAFF OF AESCULAPIUS..SCALES
+2708 ; Glue_After_Zwj # So AIRPLANE
2764 ; Glue_After_Zwj # So HEAVY BLACK HEART
+1F308 ; Glue_After_Zwj # So RAINBOW
+1F33E ; Glue_After_Zwj # So EAR OF RICE
+1F373 ; Glue_After_Zwj # So COOKING
+1F393 ; Glue_After_Zwj # So GRADUATION CAP
+1F3A4 ; Glue_After_Zwj # So MICROPHONE
+1F3A8 ; Glue_After_Zwj # So ARTIST PALETTE
+1F3EB ; Glue_After_Zwj # So SCHOOL
+1F3ED ; Glue_After_Zwj # So FACTORY
1F48B ; Glue_After_Zwj # So KISS MARK
+1F4BB..1F4BC ; Glue_After_Zwj # So [2] PERSONAL COMPUTER..BRIEFCASE
+1F527 ; Glue_After_Zwj # So WRENCH
+1F52C ; Glue_After_Zwj # So MICROSCOPE
1F5E8 ; Glue_After_Zwj # So LEFT SPEECH BUBBLE
+1F680 ; Glue_After_Zwj # So ROCKET
+1F692 ; Glue_After_Zwj # So FIRE ENGINE
-# Total code points: 3
+# Total code points: 22
# ================================================
diff --git a/lib/stdlib/uc_spec/PropList.txt b/lib/stdlib/uc_spec/PropList.txt
index a8c0da7135..9a2d0e4b1c 100644
--- a/lib/stdlib/uc_spec/PropList.txt
+++ b/lib/stdlib/uc_spec/PropList.txt
@@ -1,6 +1,6 @@
-# PropList-9.0.0.txt
-# Date: 2016-06-01, 10:34:30 GMT
-# © 2016 Unicode®, Inc.
+# PropList-10.0.0.txt
+# Date: 2017-03-10, 08:25:30 GMT
+# © 2017 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
@@ -199,6 +199,9 @@ FF64 ; Terminal_Punctuation # Po HALFWIDTH IDEOGRAPHIC COMMA
115C9..115D7 ; Terminal_Punctuation # Po [15] SIDDHAM END OF TEXT MARK..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES
11641..11642 ; Terminal_Punctuation # Po [2] MODI DANDA..MODI DOUBLE DANDA
1173C..1173E ; Terminal_Punctuation # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI
+11A42..11A43 ; Terminal_Punctuation # Po [2] ZANABAZAR SQUARE MARK SHAD..ZANABAZAR SQUARE MARK DOUBLE SHAD
+11A9B..11A9C ; Terminal_Punctuation # Po [2] SOYOMBO MARK SHAD..SOYOMBO MARK DOUBLE SHAD
+11AA1..11AA2 ; Terminal_Punctuation # Po [2] SOYOMBO TERMINAL MARK-1..SOYOMBO TERMINAL MARK-2
11C41..11C43 ; Terminal_Punctuation # Po [3] BHAIKSUKI DANDA..BHAIKSUKI WORD SEPARATOR
11C71 ; Terminal_Punctuation # Po MARCHEN MARK SHAD
12470..12474 ; Terminal_Punctuation # Po [5] CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER..CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON
@@ -209,7 +212,7 @@ FF64 ; Terminal_Punctuation # Po HALFWIDTH IDEOGRAPHIC COMMA
1BC9F ; Terminal_Punctuation # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP
1DA87..1DA8A ; Terminal_Punctuation # Po [4] SIGNWRITING COMMA..SIGNWRITING COLON
-# Total code points: 246
+# Total code points: 252
# ================================================
@@ -471,6 +474,7 @@ FF41..FF46 ; Hex_Digit # L& [6] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH L
0AC9 ; Other_Alphabetic # Mc GUJARATI VOWEL SIGN CANDRA O
0ACB..0ACC ; Other_Alphabetic # Mc [2] GUJARATI VOWEL SIGN O..GUJARATI VOWEL SIGN AU
0AE2..0AE3 ; Other_Alphabetic # Mn [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL
+0AFA..0AFC ; Other_Alphabetic # Mn [3] GUJARATI SIGN SUKUN..GUJARATI SIGN MADDAH
0B01 ; Other_Alphabetic # Mn ORIYA SIGN CANDRABINDU
0B02..0B03 ; Other_Alphabetic # Mc [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA
0B3E ; Other_Alphabetic # Mc ORIYA VOWEL SIGN AA
@@ -508,7 +512,7 @@ FF41..FF46 ; Hex_Digit # L& [6] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH L
0CCC ; Other_Alphabetic # Mn KANNADA VOWEL SIGN AU
0CD5..0CD6 ; Other_Alphabetic # Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK
0CE2..0CE3 ; Other_Alphabetic # Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL
-0D01 ; Other_Alphabetic # Mn MALAYALAM SIGN CANDRABINDU
+0D00..0D01 ; Other_Alphabetic # Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU
0D02..0D03 ; Other_Alphabetic # Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA
0D3E..0D40 ; Other_Alphabetic # Mc [3] MALAYALAM VOWEL SIGN AA..MALAYALAM VOWEL SIGN II
0D41..0D44 ; Other_Alphabetic # Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR
@@ -726,6 +730,17 @@ FB1E ; Other_Alphabetic # Mn HEBREW POINT JUDEO-SPANISH VARIKA
11722..11725 ; Other_Alphabetic # Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU
11726 ; Other_Alphabetic # Mc AHOM VOWEL SIGN E
11727..1172A ; Other_Alphabetic # Mn [4] AHOM VOWEL SIGN AW..AHOM VOWEL SIGN AM
+11A01..11A06 ; Other_Alphabetic # Mn [6] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL SIGN O
+11A07..11A08 ; Other_Alphabetic # Mc [2] ZANABAZAR SQUARE VOWEL SIGN AI..ZANABAZAR SQUARE VOWEL SIGN AU
+11A09..11A0A ; Other_Alphabetic # Mn [2] ZANABAZAR SQUARE VOWEL SIGN REVERSED I..ZANABAZAR SQUARE VOWEL LENGTH MARK
+11A35..11A38 ; Other_Alphabetic # Mn [4] ZANABAZAR SQUARE SIGN CANDRABINDU..ZANABAZAR SQUARE SIGN ANUSVARA
+11A39 ; Other_Alphabetic # Mc ZANABAZAR SQUARE SIGN VISARGA
+11A3B..11A3E ; Other_Alphabetic # Mn [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA
+11A51..11A56 ; Other_Alphabetic # Mn [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE
+11A57..11A58 ; Other_Alphabetic # Mc [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU
+11A59..11A5B ; Other_Alphabetic # Mn [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK
+11A8A..11A96 ; Other_Alphabetic # Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA
+11A97 ; Other_Alphabetic # Mc SOYOMBO SIGN VISARGA
11C2F ; Other_Alphabetic # Mc BHAIKSUKI VOWEL SIGN AA
11C30..11C36 ; Other_Alphabetic # Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L
11C38..11C3D ; Other_Alphabetic # Mn [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA
@@ -737,6 +752,12 @@ FB1E ; Other_Alphabetic # Mn HEBREW POINT JUDEO-SPANISH VARIKA
11CB2..11CB3 ; Other_Alphabetic # Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E
11CB4 ; Other_Alphabetic # Mc MARCHEN VOWEL SIGN O
11CB5..11CB6 ; Other_Alphabetic # Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU
+11D31..11D36 ; Other_Alphabetic # Mn [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R
+11D3A ; Other_Alphabetic # Mn MASARAM GONDI VOWEL SIGN E
+11D3C..11D3D ; Other_Alphabetic # Mn [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O
+11D3F..11D41 ; Other_Alphabetic # Mn [3] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI SIGN VISARGA
+11D43 ; Other_Alphabetic # Mn MASARAM GONDI SIGN CANDRA
+11D47 ; Other_Alphabetic # Mn MASARAM GONDI RA-KARA
16B30..16B36 ; Other_Alphabetic # Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM
16F51..16F7E ; Other_Alphabetic # Mc [46] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN NG
1BC9E ; Other_Alphabetic # Mn DUPLOYAN DOUBLE MARK
@@ -750,7 +771,7 @@ FB1E ; Other_Alphabetic # Mn HEBREW POINT JUDEO-SPANISH VARIKA
1F150..1F169 ; Other_Alphabetic # So [26] NEGATIVE CIRCLED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z
1F170..1F189 ; Other_Alphabetic # So [26] NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED LATIN CAPITAL LETTER Z
-# Total code points: 1238
+# Total code points: 1300
# ================================================
@@ -759,18 +780,20 @@ FB1E ; Other_Alphabetic # Mn HEBREW POINT JUDEO-SPANISH VARIKA
3021..3029 ; Ideographic # Nl [9] HANGZHOU NUMERAL ONE..HANGZHOU NUMERAL NINE
3038..303A ; Ideographic # Nl [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY
3400..4DB5 ; Ideographic # Lo [6582] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DB5
-4E00..9FD5 ; Ideographic # Lo [20950] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FD5
+4E00..9FEA ; Ideographic # Lo [20971] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FEA
F900..FA6D ; Ideographic # Lo [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D
FA70..FAD9 ; Ideographic # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9
17000..187EC ; Ideographic # Lo [6125] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187EC
18800..18AF2 ; Ideographic # Lo [755] TANGUT COMPONENT-001..TANGUT COMPONENT-755
+1B170..1B2FB ; Ideographic # Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB
20000..2A6D6 ; Ideographic # Lo [42711] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6D6
2A700..2B734 ; Ideographic # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734
2B740..2B81D ; Ideographic # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
2B820..2CEA1 ; Ideographic # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
+2CEB0..2EBE0 ; Ideographic # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
2F800..2FA1D ; Ideographic # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
-# Total code points: 88284
+# Total code points: 96174
# ================================================
@@ -826,12 +849,14 @@ FA70..FAD9 ; Ideographic # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COM
0A4D ; Diacritic # Mn GURMUKHI SIGN VIRAMA
0ABC ; Diacritic # Mn GUJARATI SIGN NUKTA
0ACD ; Diacritic # Mn GUJARATI SIGN VIRAMA
+0AFD..0AFF ; Diacritic # Mn [3] GUJARATI SIGN THREE-DOT NUKTA ABOVE..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE
0B3C ; Diacritic # Mn ORIYA SIGN NUKTA
0B4D ; Diacritic # Mn ORIYA SIGN VIRAMA
0BCD ; Diacritic # Mn TAMIL SIGN VIRAMA
0C4D ; Diacritic # Mn TELUGU SIGN VIRAMA
0CBC ; Diacritic # Mn KANNADA SIGN NUKTA
0CCD ; Diacritic # Mn KANNADA SIGN VIRAMA
+0D3B..0D3C ; Diacritic # Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA
0D4D ; Diacritic # Mn MALAYALAM SIGN VIRAMA
0DCA ; Diacritic # Mn SINHALA SIGN AL-LAKUNA
0E47..0E4C ; Diacritic # Mn [6] THAI CHARACTER MAITAIKHU..THAI CHARACTER THANTHAKHAT
@@ -871,10 +896,11 @@ FA70..FAD9 ; Ideographic # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COM
1CE2..1CE8 ; Diacritic # Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL
1CED ; Diacritic # Mn VEDIC SIGN TIRYAK
1CF4 ; Diacritic # Mn VEDIC TONE CANDRA ABOVE
+1CF7 ; Diacritic # Mc VEDIC SIGN ATIKRAMA
1CF8..1CF9 ; Diacritic # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE
1D2C..1D6A ; Diacritic # Lm [63] MODIFIER LETTER CAPITAL A..GREEK SUBSCRIPT SMALL LETTER CHI
1DC4..1DCF ; Diacritic # Mn [12] COMBINING MACRON-ACUTE..COMBINING ZIGZAG BELOW
-1DF5 ; Diacritic # Mn COMBINING UP TACK ABOVE
+1DF5..1DF9 ; Diacritic # Mn [5] COMBINING UP TACK ABOVE..COMBINING WIDE INVERTED BRIDGE BELOW
1DFD..1DFF ; Diacritic # Mn [3] COMBINING ALMOST EQUAL TO BELOW..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW
1FBD ; Diacritic # Sk GREEK KORONIS
1FBF..1FC1 ; Diacritic # Sk [3] GREEK PSILI..GREEK DIALYTIKA AND PERISPOMENI
@@ -947,7 +973,12 @@ FFE3 ; Diacritic # Sk FULLWIDTH MACRON
116B6 ; Diacritic # Mc TAKRI SIGN VIRAMA
116B7 ; Diacritic # Mn TAKRI SIGN NUKTA
1172B ; Diacritic # Mn AHOM SIGN KILLER
+11A34 ; Diacritic # Mn ZANABAZAR SQUARE SIGN VIRAMA
+11A47 ; Diacritic # Mn ZANABAZAR SQUARE SUBJOINER
+11A99 ; Diacritic # Mn SOYOMBO SUBJOINER
11C3F ; Diacritic # Mn BHAIKSUKI SIGN VIRAMA
+11D42 ; Diacritic # Mn MASARAM GONDI SIGN NUKTA
+11D44..11D45 ; Diacritic # Mn [2] MASARAM GONDI SIGN HALANTA..MASARAM GONDI VIRAMA
16AF0..16AF4 ; Diacritic # Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE
16F8F..16F92 ; Diacritic # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW
16F93..16F9F ; Diacritic # Lm [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8
@@ -960,7 +991,7 @@ FFE3 ; Diacritic # Sk FULLWIDTH MACRON
1E944..1E946 ; Diacritic # Mn [3] ADLAM ALIF LENGTHENER..ADLAM GEMINATION MARK
1E948..1E94A ; Diacritic # Mn [3] ADLAM CONSONANT MODIFIER..ADLAM NUKTA
-# Total code points: 782
+# Total code points: 798
# ================================================
@@ -989,11 +1020,12 @@ AAF3..AAF4 ; Extender # Lm [2] MEETEI MAYEK SYLLABLE REPETITION MARK..MEETE
FF70 ; Extender # Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK
1135D ; Extender # Lo GRANTHA SIGN PLUTA
115C6..115C8 ; Extender # Po [3] SIDDHAM REPETITION MARK-1..SIDDHAM REPETITION MARK-3
+11A98 ; Extender # Mn SOYOMBO GEMINATION MARK
16B42..16B43 ; Extender # Lm [2] PAHAWH HMONG SIGN VOS NRUA..PAHAWH HMONG SIGN IB YAM
-16FE0 ; Extender # Lm TANGUT ITERATION MARK
+16FE0..16FE1 ; Extender # Lm [2] TANGUT ITERATION MARK..NUSHU ITERATION MARK
1E944..1E946 ; Extender # Mn [3] ADLAM ALIF LENGTHENER..ADLAM GEMINATION MARK
-# Total code points: 42
+# Total code points: 44
# ================================================
@@ -1105,7 +1137,7 @@ E0020..E007F ; Other_Grapheme_Extend # Cf [96] TAG SPACE..CANCEL TAG
# ================================================
3400..4DB5 ; Unified_Ideograph # Lo [6582] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DB5
-4E00..9FD5 ; Unified_Ideograph # Lo [20950] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FD5
+4E00..9FEA ; Unified_Ideograph # Lo [20971] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FEA
FA0E..FA0F ; Unified_Ideograph # Lo [2] CJK COMPATIBILITY IDEOGRAPH-FA0E..CJK COMPATIBILITY IDEOGRAPH-FA0F
FA11 ; Unified_Ideograph # Lo CJK COMPATIBILITY IDEOGRAPH-FA11
FA13..FA14 ; Unified_Ideograph # Lo [2] CJK COMPATIBILITY IDEOGRAPH-FA13..CJK COMPATIBILITY IDEOGRAPH-FA14
@@ -1117,8 +1149,9 @@ FA27..FA29 ; Unified_Ideograph # Lo [3] CJK COMPATIBILITY IDEOGRAPH-FA27..C
2A700..2B734 ; Unified_Ideograph # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734
2B740..2B81D ; Unified_Ideograph # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
2B820..2CEA1 ; Unified_Ideograph # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
+2CEB0..2EBE0 ; Unified_Ideograph # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
-# Total code points: 80388
+# Total code points: 87882
# ================================================
@@ -1277,6 +1310,8 @@ FF61 ; Sentence_Terminal # Po HALFWIDTH IDEOGRAPHIC FULL STOP
115C9..115D7 ; Sentence_Terminal # Po [15] SIDDHAM END OF TEXT MARK..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES
11641..11642 ; Sentence_Terminal # Po [2] MODI DANDA..MODI DOUBLE DANDA
1173C..1173E ; Sentence_Terminal # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI
+11A42..11A43 ; Sentence_Terminal # Po [2] ZANABAZAR SQUARE MARK SHAD..ZANABAZAR SQUARE MARK DOUBLE SHAD
+11A9B..11A9C ; Sentence_Terminal # Po [2] SOYOMBO MARK SHAD..SOYOMBO MARK DOUBLE SHAD
11C41..11C42 ; Sentence_Terminal # Po [2] BHAIKSUKI DANDA..BHAIKSUKI DOUBLE DANDA
16A6E..16A6F ; Sentence_Terminal # Po [2] MRO DANDA..MRO DOUBLE DANDA
16AF5 ; Sentence_Terminal # Po BASSA VAH FULL STOP
@@ -1285,7 +1320,7 @@ FF61 ; Sentence_Terminal # Po HALFWIDTH IDEOGRAPHIC FULL STOP
1BC9F ; Sentence_Terminal # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP
1DA88 ; Sentence_Terminal # Po SIGNWRITING FULL STOP
-# Total code points: 124
+# Total code points: 128
# ================================================
@@ -1402,9 +1437,7 @@ E0100..E01EF ; Variation_Selector # Mn [240] VARIATION SELECTOR-17..VARIATION S
239B..23B3 ; Pattern_Syntax # Sm [25] LEFT PARENTHESIS UPPER HOOK..SUMMATION BOTTOM
23B4..23DB ; Pattern_Syntax # So [40] TOP SQUARE BRACKET..FUSE
23DC..23E1 ; Pattern_Syntax # Sm [6] TOP PARENTHESIS..BOTTOM TORTOISE SHELL BRACKET
-23E2..23FE ; Pattern_Syntax # So [29] WHITE TRAPEZIUM..POWER SLEEP SYMBOL
-23FF ; Pattern_Syntax # Cn <reserved-23FF>
-2400..2426 ; Pattern_Syntax # So [39] SYMBOL FOR NULL..SYMBOL FOR SUBSTITUTE FORM TWO
+23E2..2426 ; Pattern_Syntax # So [69] WHITE TRAPEZIUM..SYMBOL FOR SUBSTITUTE FORM TWO
2427..243F ; Pattern_Syntax # Cn [25] <reserved-2427>..<reserved-243F>
2440..244A ; Pattern_Syntax # So [11] OCR HOOK..OCR DOUBLE BACKSLASH
244B..245F ; Pattern_Syntax # Cn [21] <reserved-244B>..<reserved-245F>
@@ -1492,8 +1525,8 @@ E0100..E01EF ; Variation_Selector # Mn [240] VARIATION SELECTOR-17..VARIATION S
2BBA..2BBC ; Pattern_Syntax # Cn [3] <reserved-2BBA>..<reserved-2BBC>
2BBD..2BC8 ; Pattern_Syntax # So [12] BALLOT BOX WITH LIGHT X..BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED
2BC9 ; Pattern_Syntax # Cn <reserved-2BC9>
-2BCA..2BD1 ; Pattern_Syntax # So [8] TOP HALF BLACK CIRCLE..UNCERTAINTY SIGN
-2BD2..2BEB ; Pattern_Syntax # Cn [26] <reserved-2BD2>..<reserved-2BEB>
+2BCA..2BD2 ; Pattern_Syntax # So [9] TOP HALF BLACK CIRCLE..GROUP MARK
+2BD3..2BEB ; Pattern_Syntax # Cn [25] <reserved-2BD3>..<reserved-2BEB>
2BEC..2BEF ; Pattern_Syntax # So [4] LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS..DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS
2BF0..2BFF ; Pattern_Syntax # Cn [16] <reserved-2BF0>..<reserved-2BFF>
2E00..2E01 ; Pattern_Syntax # Po [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER
@@ -1533,8 +1566,8 @@ E0100..E01EF ; Variation_Selector # Mn [240] VARIATION SELECTOR-17..VARIATION S
2E40 ; Pattern_Syntax # Pd DOUBLE HYPHEN
2E41 ; Pattern_Syntax # Po REVERSED COMMA
2E42 ; Pattern_Syntax # Ps DOUBLE LOW-REVERSED-9 QUOTATION MARK
-2E43..2E44 ; Pattern_Syntax # Po [2] DASH WITH LEFT UPTURN..DOUBLE SUSPENSION MARK
-2E45..2E7F ; Pattern_Syntax # Cn [59] <reserved-2E45>..<reserved-2E7F>
+2E43..2E49 ; Pattern_Syntax # Po [7] DASH WITH LEFT UPTURN..DOUBLE STACKED COMMA
+2E4A..2E7F ; Pattern_Syntax # Cn [54] <reserved-2E4A>..<reserved-2E7F>
3001..3003 ; Pattern_Syntax # Po [3] IDEOGRAPHIC COMMA..DITTO MARK
3008 ; Pattern_Syntax # Ps LEFT ANGLE BRACKET
3009 ; Pattern_Syntax # Pe RIGHT ANGLE BRACKET
@@ -1576,4 +1609,10 @@ FE45..FE46 ; Pattern_Syntax # Po [2] SESAME DOT..WHITE SESAME DOT
# Total code points: 10
+# ================================================
+
+1F1E6..1F1FF ; Regional_Indicator # So [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z
+
+# Total code points: 26
+
# EOF
diff --git a/lib/stdlib/uc_spec/SpecialCasing.txt b/lib/stdlib/uc_spec/SpecialCasing.txt
index b23fa7f768..b9ba0d81c1 100644
--- a/lib/stdlib/uc_spec/SpecialCasing.txt
+++ b/lib/stdlib/uc_spec/SpecialCasing.txt
@@ -1,6 +1,6 @@
-# SpecialCasing-9.0.0.txt
-# Date: 2016-03-02, 18:55:13 GMT
-# © 2016 Unicode®, Inc.
+# SpecialCasing-10.0.0.txt
+# Date: 2017-04-14, 05:40:43 GMT
+# © 2017 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
@@ -197,7 +197,7 @@ FB17; FB17; 0544 056D; 0544 053D; # ARMENIAN SMALL LIGATURE MEN XEH
# ================================================================================
# Conditional Mappings
-# The remainder of this file provides conditional casing data used to produce
+# The remainder of this file provides conditional casing data used to produce
# full case mappings.
# ================================================================================
# Language-Insensitive Mappings
diff --git a/lib/stdlib/uc_spec/UnicodeData.txt b/lib/stdlib/uc_spec/UnicodeData.txt
index a756976461..d89c64f526 100644
--- a/lib/stdlib/uc_spec/UnicodeData.txt
+++ b/lib/stdlib/uc_spec/UnicodeData.txt
@@ -2072,6 +2072,17 @@
085A;MANDAIC VOCALIZATION MARK;Mn;220;NSM;;;;;N;;;;;
085B;MANDAIC GEMINATION MARK;Mn;220;NSM;;;;;N;;;;;
085E;MANDAIC PUNCTUATION;Po;0;R;;;;;N;;;;;
+0860;SYRIAC LETTER MALAYALAM NGA;Lo;0;AL;;;;;N;;;;;
+0861;SYRIAC LETTER MALAYALAM JA;Lo;0;AL;;;;;N;;;;;
+0862;SYRIAC LETTER MALAYALAM NYA;Lo;0;AL;;;;;N;;;;;
+0863;SYRIAC LETTER MALAYALAM TTA;Lo;0;AL;;;;;N;;;;;
+0864;SYRIAC LETTER MALAYALAM NNA;Lo;0;AL;;;;;N;;;;;
+0865;SYRIAC LETTER MALAYALAM NNNA;Lo;0;AL;;;;;N;;;;;
+0866;SYRIAC LETTER MALAYALAM BHA;Lo;0;AL;;;;;N;;;;;
+0867;SYRIAC LETTER MALAYALAM RA;Lo;0;AL;;;;;N;;;;;
+0868;SYRIAC LETTER MALAYALAM LLA;Lo;0;AL;;;;;N;;;;;
+0869;SYRIAC LETTER MALAYALAM LLLA;Lo;0;AL;;;;;N;;;;;
+086A;SYRIAC LETTER MALAYALAM SSA;Lo;0;AL;;;;;N;;;;;
08A0;ARABIC LETTER BEH WITH SMALL V BELOW;Lo;0;AL;;;;;N;;;;;
08A1;ARABIC LETTER BEH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;;;;;
08A2;ARABIC LETTER JEEM WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
@@ -2366,6 +2377,8 @@
09F9;BENGALI CURRENCY DENOMINATOR SIXTEEN;No;0;L;;;;16;N;;;;;
09FA;BENGALI ISSHAR;So;0;L;;;;;N;;;;;
09FB;BENGALI GANDA MARK;Sc;0;ET;;;;;N;;;;;
+09FC;BENGALI LETTER VEDIC ANUSVARA;Lo;0;L;;;;;N;;;;;
+09FD;BENGALI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;;
0A01;GURMUKHI SIGN ADAK BINDI;Mn;0;NSM;;;;;N;;;;;
0A02;GURMUKHI SIGN BINDI;Mn;0;NSM;;;;;N;;;;;
0A03;GURMUKHI SIGN VISARGA;Mc;0;L;;;;;N;;;;;
@@ -2530,6 +2543,12 @@
0AF0;GUJARATI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;;
0AF1;GUJARATI RUPEE SIGN;Sc;0;ET;;;;;N;;;;;
0AF9;GUJARATI LETTER ZHA;Lo;0;L;;;;;N;;;;;
+0AFA;GUJARATI SIGN SUKUN;Mn;0;NSM;;;;;N;;;;;
+0AFB;GUJARATI SIGN SHADDA;Mn;0;NSM;;;;;N;;;;;
+0AFC;GUJARATI SIGN MADDAH;Mn;0;NSM;;;;;N;;;;;
+0AFD;GUJARATI SIGN THREE-DOT NUKTA ABOVE;Mn;0;NSM;;;;;N;;;;;
+0AFE;GUJARATI SIGN CIRCLE NUKTA ABOVE;Mn;0;NSM;;;;;N;;;;;
+0AFF;GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE;Mn;0;NSM;;;;;N;;;;;
0B01;ORIYA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
0B02;ORIYA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;;
0B03;ORIYA SIGN VISARGA;Mc;0;L;;;;;N;;;;;
@@ -2876,6 +2895,7 @@
0CEF;KANNADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
0CF1;KANNADA SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;;
0CF2;KANNADA SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;;
+0D00;MALAYALAM SIGN COMBINING ANUSVARA ABOVE;Mn;0;NSM;;;;;N;;;;;
0D01;MALAYALAM SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
0D02;MALAYALAM SIGN ANUSVARA;Mc;0;L;;;;;N;;;;;
0D03;MALAYALAM SIGN VISARGA;Mc;0;L;;;;;N;;;;;
@@ -2931,6 +2951,8 @@
0D38;MALAYALAM LETTER SA;Lo;0;L;;;;;N;;;;;
0D39;MALAYALAM LETTER HA;Lo;0;L;;;;;N;;;;;
0D3A;MALAYALAM LETTER TTTA;Lo;0;L;;;;;N;;;;;
+0D3B;MALAYALAM SIGN VERTICAL BAR VIRAMA;Mn;9;NSM;;;;;N;;;;;
+0D3C;MALAYALAM SIGN CIRCULAR VIRAMA;Mn;9;NSM;;;;;N;;;;;
0D3D;MALAYALAM SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;;
0D3E;MALAYALAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
0D3F;MALAYALAM VOWEL SIGN I;Mc;0;L;;;;;N;;;;;
@@ -6413,6 +6435,7 @@
1CF4;VEDIC TONE CANDRA ABOVE;Mn;230;NSM;;;;;N;;;;;
1CF5;VEDIC SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;;
1CF6;VEDIC SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;;
+1CF7;VEDIC SIGN ATIKRAMA;Mc;0;L;;;;;N;;;;;
1CF8;VEDIC TONE RING ABOVE;Mn;230;NSM;;;;;N;;;;;
1CF9;VEDIC TONE DOUBLE RING ABOVE;Mn;230;NSM;;;;;N;;;;;
1D00;LATIN LETTER SMALL CAPITAL A;Ll;0;L;;;;;N;;;;;
@@ -6661,6 +6684,10 @@
1DF3;COMBINING LATIN SMALL LETTER O WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;;
1DF4;COMBINING LATIN SMALL LETTER U WITH DIAERESIS;Mn;230;NSM;;;;;N;;;;;
1DF5;COMBINING UP TACK ABOVE;Mn;230;NSM;;;;;N;;;;;
+1DF6;COMBINING KAVYKA ABOVE RIGHT;Mn;232;NSM;;;;;N;;;;;
+1DF7;COMBINING KAVYKA ABOVE LEFT;Mn;228;NSM;;;;;N;;;;;
+1DF8;COMBINING DOT ABOVE LEFT;Mn;228;NSM;;;;;N;;;;;
+1DF9;COMBINING WIDE INVERTED BRIDGE BELOW;Mn;220;NSM;;;;;N;;;;;
1DFB;COMBINING DELETION MARK;Mn;230;NSM;;;;;N;;;;;
1DFC;COMBINING DOUBLE INVERTED BREVE BELOW;Mn;233;NSM;;;;;N;;;;;
1DFD;COMBINING ALMOST EQUAL TO BELOW;Mn;220;NSM;;;;;N;;;;;
@@ -7339,6 +7366,7 @@
20BC;MANAT SIGN;Sc;0;ET;;;;;N;;;;;
20BD;RUBLE SIGN;Sc;0;ET;;;;;N;;;;;
20BE;LARI SIGN;Sc;0;ET;;;;;N;;;;;
+20BF;BITCOIN SIGN;Sc;0;ET;;;;;N;;;;;
20D0;COMBINING LEFT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT HARPOON ABOVE;;;;
20D1;COMBINING RIGHT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT HARPOON ABOVE;;;;
20D2;COMBINING LONG VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG VERTICAL BAR OVERLAY;;;;
@@ -8135,6 +8163,7 @@
23FC;POWER ON-OFF SYMBOL;So;0;ON;;;;;N;;;;;
23FD;POWER ON SYMBOL;So;0;ON;;;;;N;;;;;
23FE;POWER SLEEP SYMBOL;So;0;ON;;;;;N;;;;;
+23FF;OBSERVER EYE SYMBOL;So;0;ON;;;;;N;;;;;
2400;SYMBOL FOR NULL;So;0;ON;;;;;N;GRAPHIC FOR NULL;;;;
2401;SYMBOL FOR START OF HEADING;So;0;ON;;;;;N;GRAPHIC FOR START OF HEADING;;;;
2402;SYMBOL FOR START OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR START OF TEXT;;;;
@@ -10083,6 +10112,7 @@
2BCF;ROTATED WHITE FOUR POINTED CUSP;So;0;ON;;;;;N;;;;;
2BD0;SQUARE POSITION INDICATOR;So;0;ON;;;;;N;;;;;
2BD1;UNCERTAINTY SIGN;So;0;ON;;;;;N;;;;;
+2BD2;GROUP MARK;So;0;ON;;;;;N;;;;;
2BEC;LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;;
2BED;UPWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;;
2BEE;RIGHTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;;
@@ -10615,6 +10645,11 @@
2E42;DOUBLE LOW-REVERSED-9 QUOTATION MARK;Ps;0;ON;;;;;N;;;;;
2E43;DASH WITH LEFT UPTURN;Po;0;ON;;;;;N;;;;;
2E44;DOUBLE SUSPENSION MARK;Po;0;ON;;;;;N;;;;;
+2E45;INVERTED LOW KAVYKA;Po;0;ON;;;;;N;;;;;
+2E46;INVERTED LOW KAVYKA WITH KAVYKA ABOVE;Po;0;ON;;;;;N;;;;;
+2E47;LOW KAVYKA;Po;0;ON;;;;;N;;;;;
+2E48;LOW KAVYKA WITH DOT;Po;0;ON;;;;;N;;;;;
+2E49;DOUBLE STACKED COMMA;Po;0;ON;;;;;N;;;;;
2E80;CJK RADICAL REPEAT;So;0;ON;;;;;N;;;;;
2E81;CJK RADICAL CLIFF;So;0;ON;;;;;N;;;;;
2E82;CJK RADICAL SECOND ONE;So;0;ON;;;;;N;;;;;
@@ -11250,6 +11285,7 @@
312B;BOPOMOFO LETTER NG;Lo;0;L;;;;;N;;;;;
312C;BOPOMOFO LETTER GN;Lo;0;L;;;;;N;;;;;
312D;BOPOMOFO LETTER IH;Lo;0;L;;;;;N;;;;;
+312E;BOPOMOFO LETTER O WITH DOT ABOVE;Lo;0;L;;;;;N;;;;;
3131;HANGUL LETTER KIYEOK;Lo;0;L;<compat> 1100;;;;N;HANGUL LETTER GIYEOG;;;;
3132;HANGUL LETTER SSANGKIYEOK;Lo;0;L;<compat> 1101;;;;N;HANGUL LETTER SSANG GIYEOG;;;;
3133;HANGUL LETTER KIYEOK-SIOS;Lo;0;L;<compat> 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;;
@@ -12016,7 +12052,7 @@
4DFE;HEXAGRAM FOR AFTER COMPLETION;So;0;ON;;;;;N;;;;;
4DFF;HEXAGRAM FOR BEFORE COMPLETION;So;0;ON;;;;;N;;;;;
4E00;<CJK Ideograph, First>;Lo;0;L;;;;;N;;;;;
-9FD5;<CJK Ideograph, Last>;Lo;0;L;;;;;N;;;;;
+9FEA;<CJK Ideograph, Last>;Lo;0;L;;;;;N;;;;;
A000;YI SYLLABLE IT;Lo;0;L;;;;;N;;;;;
A001;YI SYLLABLE IX;Lo;0;L;;;;;N;;;;;
A002;YI SYLLABLE I;Lo;0;L;;;;;N;;;;;
@@ -17093,6 +17129,9 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
10321;OLD ITALIC NUMERAL FIVE;No;0;L;;;;5;N;;;;;
10322;OLD ITALIC NUMERAL TEN;No;0;L;;;;10;N;;;;;
10323;OLD ITALIC NUMERAL FIFTY;No;0;L;;;;50;N;;;;;
+1032D;OLD ITALIC LETTER YE;Lo;0;L;;;;;N;;;;;
+1032E;OLD ITALIC LETTER NORTHERN TSE;Lo;0;L;;;;;N;;;;;
+1032F;OLD ITALIC LETTER SOUTHERN TSE;Lo;0;L;;;;;N;;;;;
10330;GOTHIC LETTER AHSA;Lo;0;L;;;;;N;;;;;
10331;GOTHIC LETTER BAIRKAN;Lo;0;L;;;;;N;;;;;
10332;GOTHIC LETTER GIBA;Lo;0;L;;;;;N;;;;;
@@ -20068,6 +20107,158 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
118F1;WARANG CITI NUMBER EIGHTY;No;0;L;;;;80;N;;;;;
118F2;WARANG CITI NUMBER NINETY;No;0;L;;;;90;N;;;;;
118FF;WARANG CITI OM;Lo;0;L;;;;;N;;;;;
+11A00;ZANABAZAR SQUARE LETTER A;Lo;0;L;;;;;N;;;;;
+11A01;ZANABAZAR SQUARE VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
+11A02;ZANABAZAR SQUARE VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;;
+11A03;ZANABAZAR SQUARE VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+11A04;ZANABAZAR SQUARE VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
+11A05;ZANABAZAR SQUARE VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;;
+11A06;ZANABAZAR SQUARE VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;;
+11A07;ZANABAZAR SQUARE VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
+11A08;ZANABAZAR SQUARE VOWEL SIGN AU;Mc;0;L;;;;;N;;;;;
+11A09;ZANABAZAR SQUARE VOWEL SIGN REVERSED I;Mn;0;NSM;;;;;N;;;;;
+11A0A;ZANABAZAR SQUARE VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;;
+11A0B;ZANABAZAR SQUARE LETTER KA;Lo;0;L;;;;;N;;;;;
+11A0C;ZANABAZAR SQUARE LETTER KHA;Lo;0;L;;;;;N;;;;;
+11A0D;ZANABAZAR SQUARE LETTER GA;Lo;0;L;;;;;N;;;;;
+11A0E;ZANABAZAR SQUARE LETTER GHA;Lo;0;L;;;;;N;;;;;
+11A0F;ZANABAZAR SQUARE LETTER NGA;Lo;0;L;;;;;N;;;;;
+11A10;ZANABAZAR SQUARE LETTER CA;Lo;0;L;;;;;N;;;;;
+11A11;ZANABAZAR SQUARE LETTER CHA;Lo;0;L;;;;;N;;;;;
+11A12;ZANABAZAR SQUARE LETTER JA;Lo;0;L;;;;;N;;;;;
+11A13;ZANABAZAR SQUARE LETTER NYA;Lo;0;L;;;;;N;;;;;
+11A14;ZANABAZAR SQUARE LETTER TTA;Lo;0;L;;;;;N;;;;;
+11A15;ZANABAZAR SQUARE LETTER TTHA;Lo;0;L;;;;;N;;;;;
+11A16;ZANABAZAR SQUARE LETTER DDA;Lo;0;L;;;;;N;;;;;
+11A17;ZANABAZAR SQUARE LETTER DDHA;Lo;0;L;;;;;N;;;;;
+11A18;ZANABAZAR SQUARE LETTER NNA;Lo;0;L;;;;;N;;;;;
+11A19;ZANABAZAR SQUARE LETTER TA;Lo;0;L;;;;;N;;;;;
+11A1A;ZANABAZAR SQUARE LETTER THA;Lo;0;L;;;;;N;;;;;
+11A1B;ZANABAZAR SQUARE LETTER DA;Lo;0;L;;;;;N;;;;;
+11A1C;ZANABAZAR SQUARE LETTER DHA;Lo;0;L;;;;;N;;;;;
+11A1D;ZANABAZAR SQUARE LETTER NA;Lo;0;L;;;;;N;;;;;
+11A1E;ZANABAZAR SQUARE LETTER PA;Lo;0;L;;;;;N;;;;;
+11A1F;ZANABAZAR SQUARE LETTER PHA;Lo;0;L;;;;;N;;;;;
+11A20;ZANABAZAR SQUARE LETTER BA;Lo;0;L;;;;;N;;;;;
+11A21;ZANABAZAR SQUARE LETTER BHA;Lo;0;L;;;;;N;;;;;
+11A22;ZANABAZAR SQUARE LETTER MA;Lo;0;L;;;;;N;;;;;
+11A23;ZANABAZAR SQUARE LETTER TSA;Lo;0;L;;;;;N;;;;;
+11A24;ZANABAZAR SQUARE LETTER TSHA;Lo;0;L;;;;;N;;;;;
+11A25;ZANABAZAR SQUARE LETTER DZA;Lo;0;L;;;;;N;;;;;
+11A26;ZANABAZAR SQUARE LETTER DZHA;Lo;0;L;;;;;N;;;;;
+11A27;ZANABAZAR SQUARE LETTER ZHA;Lo;0;L;;;;;N;;;;;
+11A28;ZANABAZAR SQUARE LETTER ZA;Lo;0;L;;;;;N;;;;;
+11A29;ZANABAZAR SQUARE LETTER -A;Lo;0;L;;;;;N;;;;;
+11A2A;ZANABAZAR SQUARE LETTER YA;Lo;0;L;;;;;N;;;;;
+11A2B;ZANABAZAR SQUARE LETTER RA;Lo;0;L;;;;;N;;;;;
+11A2C;ZANABAZAR SQUARE LETTER LA;Lo;0;L;;;;;N;;;;;
+11A2D;ZANABAZAR SQUARE LETTER VA;Lo;0;L;;;;;N;;;;;
+11A2E;ZANABAZAR SQUARE LETTER SHA;Lo;0;L;;;;;N;;;;;
+11A2F;ZANABAZAR SQUARE LETTER SSA;Lo;0;L;;;;;N;;;;;
+11A30;ZANABAZAR SQUARE LETTER SA;Lo;0;L;;;;;N;;;;;
+11A31;ZANABAZAR SQUARE LETTER HA;Lo;0;L;;;;;N;;;;;
+11A32;ZANABAZAR SQUARE LETTER KSSA;Lo;0;L;;;;;N;;;;;
+11A33;ZANABAZAR SQUARE FINAL CONSONANT MARK;Mn;0;NSM;;;;;N;;;;;
+11A34;ZANABAZAR SQUARE SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
+11A35;ZANABAZAR SQUARE SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
+11A36;ZANABAZAR SQUARE SIGN CANDRABINDU WITH ORNAMENT;Mn;0;NSM;;;;;N;;;;;
+11A37;ZANABAZAR SQUARE SIGN CANDRA WITH ORNAMENT;Mn;0;NSM;;;;;N;;;;;
+11A38;ZANABAZAR SQUARE SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
+11A39;ZANABAZAR SQUARE SIGN VISARGA;Mc;0;L;;;;;N;;;;;
+11A3A;ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA;Lo;0;L;;;;;N;;;;;
+11A3B;ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA;Mn;0;NSM;;;;;N;;;;;
+11A3C;ZANABAZAR SQUARE CLUSTER-FINAL LETTER RA;Mn;0;NSM;;;;;N;;;;;
+11A3D;ZANABAZAR SQUARE CLUSTER-FINAL LETTER LA;Mn;0;NSM;;;;;N;;;;;
+11A3E;ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA;Mn;0;NSM;;;;;N;;;;;
+11A3F;ZANABAZAR SQUARE INITIAL HEAD MARK;Po;0;L;;;;;N;;;;;
+11A40;ZANABAZAR SQUARE CLOSING HEAD MARK;Po;0;L;;;;;N;;;;;
+11A41;ZANABAZAR SQUARE MARK TSHEG;Po;0;L;;;;;N;;;;;
+11A42;ZANABAZAR SQUARE MARK SHAD;Po;0;L;;;;;N;;;;;
+11A43;ZANABAZAR SQUARE MARK DOUBLE SHAD;Po;0;L;;;;;N;;;;;
+11A44;ZANABAZAR SQUARE MARK LONG TSHEG;Po;0;L;;;;;N;;;;;
+11A45;ZANABAZAR SQUARE INITIAL DOUBLE-LINED HEAD MARK;Po;0;L;;;;;N;;;;;
+11A46;ZANABAZAR SQUARE CLOSING DOUBLE-LINED HEAD MARK;Po;0;L;;;;;N;;;;;
+11A47;ZANABAZAR SQUARE SUBJOINER;Mn;9;NSM;;;;;N;;;;;
+11A50;SOYOMBO LETTER A;Lo;0;L;;;;;N;;;;;
+11A51;SOYOMBO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
+11A52;SOYOMBO VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;;
+11A53;SOYOMBO VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+11A54;SOYOMBO VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
+11A55;SOYOMBO VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;;
+11A56;SOYOMBO VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;;
+11A57;SOYOMBO VOWEL SIGN AI;Mc;0;L;;;;;N;;;;;
+11A58;SOYOMBO VOWEL SIGN AU;Mc;0;L;;;;;N;;;;;
+11A59;SOYOMBO VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;;
+11A5A;SOYOMBO VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
+11A5B;SOYOMBO VOWEL LENGTH MARK;Mn;0;NSM;;;;;N;;;;;
+11A5C;SOYOMBO LETTER KA;Lo;0;L;;;;;N;;;;;
+11A5D;SOYOMBO LETTER KHA;Lo;0;L;;;;;N;;;;;
+11A5E;SOYOMBO LETTER GA;Lo;0;L;;;;;N;;;;;
+11A5F;SOYOMBO LETTER GHA;Lo;0;L;;;;;N;;;;;
+11A60;SOYOMBO LETTER NGA;Lo;0;L;;;;;N;;;;;
+11A61;SOYOMBO LETTER CA;Lo;0;L;;;;;N;;;;;
+11A62;SOYOMBO LETTER CHA;Lo;0;L;;;;;N;;;;;
+11A63;SOYOMBO LETTER JA;Lo;0;L;;;;;N;;;;;
+11A64;SOYOMBO LETTER JHA;Lo;0;L;;;;;N;;;;;
+11A65;SOYOMBO LETTER NYA;Lo;0;L;;;;;N;;;;;
+11A66;SOYOMBO LETTER TTA;Lo;0;L;;;;;N;;;;;
+11A67;SOYOMBO LETTER TTHA;Lo;0;L;;;;;N;;;;;
+11A68;SOYOMBO LETTER DDA;Lo;0;L;;;;;N;;;;;
+11A69;SOYOMBO LETTER DDHA;Lo;0;L;;;;;N;;;;;
+11A6A;SOYOMBO LETTER NNA;Lo;0;L;;;;;N;;;;;
+11A6B;SOYOMBO LETTER TA;Lo;0;L;;;;;N;;;;;
+11A6C;SOYOMBO LETTER THA;Lo;0;L;;;;;N;;;;;
+11A6D;SOYOMBO LETTER DA;Lo;0;L;;;;;N;;;;;
+11A6E;SOYOMBO LETTER DHA;Lo;0;L;;;;;N;;;;;
+11A6F;SOYOMBO LETTER NA;Lo;0;L;;;;;N;;;;;
+11A70;SOYOMBO LETTER PA;Lo;0;L;;;;;N;;;;;
+11A71;SOYOMBO LETTER PHA;Lo;0;L;;;;;N;;;;;
+11A72;SOYOMBO LETTER BA;Lo;0;L;;;;;N;;;;;
+11A73;SOYOMBO LETTER BHA;Lo;0;L;;;;;N;;;;;
+11A74;SOYOMBO LETTER MA;Lo;0;L;;;;;N;;;;;
+11A75;SOYOMBO LETTER TSA;Lo;0;L;;;;;N;;;;;
+11A76;SOYOMBO LETTER TSHA;Lo;0;L;;;;;N;;;;;
+11A77;SOYOMBO LETTER DZA;Lo;0;L;;;;;N;;;;;
+11A78;SOYOMBO LETTER ZHA;Lo;0;L;;;;;N;;;;;
+11A79;SOYOMBO LETTER ZA;Lo;0;L;;;;;N;;;;;
+11A7A;SOYOMBO LETTER -A;Lo;0;L;;;;;N;;;;;
+11A7B;SOYOMBO LETTER YA;Lo;0;L;;;;;N;;;;;
+11A7C;SOYOMBO LETTER RA;Lo;0;L;;;;;N;;;;;
+11A7D;SOYOMBO LETTER LA;Lo;0;L;;;;;N;;;;;
+11A7E;SOYOMBO LETTER VA;Lo;0;L;;;;;N;;;;;
+11A7F;SOYOMBO LETTER SHA;Lo;0;L;;;;;N;;;;;
+11A80;SOYOMBO LETTER SSA;Lo;0;L;;;;;N;;;;;
+11A81;SOYOMBO LETTER SA;Lo;0;L;;;;;N;;;;;
+11A82;SOYOMBO LETTER HA;Lo;0;L;;;;;N;;;;;
+11A83;SOYOMBO LETTER KSSA;Lo;0;L;;;;;N;;;;;
+11A86;SOYOMBO CLUSTER-INITIAL LETTER RA;Lo;0;L;;;;;N;;;;;
+11A87;SOYOMBO CLUSTER-INITIAL LETTER LA;Lo;0;L;;;;;N;;;;;
+11A88;SOYOMBO CLUSTER-INITIAL LETTER SHA;Lo;0;L;;;;;N;;;;;
+11A89;SOYOMBO CLUSTER-INITIAL LETTER SA;Lo;0;L;;;;;N;;;;;
+11A8A;SOYOMBO FINAL CONSONANT SIGN G;Mn;0;NSM;;;;;N;;;;;
+11A8B;SOYOMBO FINAL CONSONANT SIGN K;Mn;0;NSM;;;;;N;;;;;
+11A8C;SOYOMBO FINAL CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;;
+11A8D;SOYOMBO FINAL CONSONANT SIGN D;Mn;0;NSM;;;;;N;;;;;
+11A8E;SOYOMBO FINAL CONSONANT SIGN N;Mn;0;NSM;;;;;N;;;;;
+11A8F;SOYOMBO FINAL CONSONANT SIGN B;Mn;0;NSM;;;;;N;;;;;
+11A90;SOYOMBO FINAL CONSONANT SIGN M;Mn;0;NSM;;;;;N;;;;;
+11A91;SOYOMBO FINAL CONSONANT SIGN R;Mn;0;NSM;;;;;N;;;;;
+11A92;SOYOMBO FINAL CONSONANT SIGN L;Mn;0;NSM;;;;;N;;;;;
+11A93;SOYOMBO FINAL CONSONANT SIGN SH;Mn;0;NSM;;;;;N;;;;;
+11A94;SOYOMBO FINAL CONSONANT SIGN S;Mn;0;NSM;;;;;N;;;;;
+11A95;SOYOMBO FINAL CONSONANT SIGN -A;Mn;0;NSM;;;;;N;;;;;
+11A96;SOYOMBO SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
+11A97;SOYOMBO SIGN VISARGA;Mc;0;L;;;;;N;;;;;
+11A98;SOYOMBO GEMINATION MARK;Mn;0;NSM;;;;;N;;;;;
+11A99;SOYOMBO SUBJOINER;Mn;9;NSM;;;;;N;;;;;
+11A9A;SOYOMBO MARK TSHEG;Po;0;L;;;;;N;;;;;
+11A9B;SOYOMBO MARK SHAD;Po;0;L;;;;;N;;;;;
+11A9C;SOYOMBO MARK DOUBLE SHAD;Po;0;L;;;;;N;;;;;
+11A9E;SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME;Po;0;L;;;;;N;;;;;
+11A9F;SOYOMBO HEAD MARK WITH MOON AND SUN AND FLAME;Po;0;L;;;;;N;;;;;
+11AA0;SOYOMBO HEAD MARK WITH MOON AND SUN;Po;0;L;;;;;N;;;;;
+11AA1;SOYOMBO TERMINAL MARK-1;Po;0;L;;;;;N;;;;;
+11AA2;SOYOMBO TERMINAL MARK-2;Po;0;L;;;;;N;;;;;
11AC0;PAU CIN HAU LETTER PA;Lo;0;L;;;;;N;;;;;
11AC1;PAU CIN HAU LETTER KA;Lo;0;L;;;;;N;;;;;
11AC2;PAU CIN HAU LETTER LA;Lo;0;L;;;;;N;;;;;
@@ -20290,6 +20481,81 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
11CB4;MARCHEN VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
11CB5;MARCHEN SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
11CB6;MARCHEN SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
+11D00;MASARAM GONDI LETTER A;Lo;0;L;;;;;N;;;;;
+11D01;MASARAM GONDI LETTER AA;Lo;0;L;;;;;N;;;;;
+11D02;MASARAM GONDI LETTER I;Lo;0;L;;;;;N;;;;;
+11D03;MASARAM GONDI LETTER II;Lo;0;L;;;;;N;;;;;
+11D04;MASARAM GONDI LETTER U;Lo;0;L;;;;;N;;;;;
+11D05;MASARAM GONDI LETTER UU;Lo;0;L;;;;;N;;;;;
+11D06;MASARAM GONDI LETTER E;Lo;0;L;;;;;N;;;;;
+11D08;MASARAM GONDI LETTER AI;Lo;0;L;;;;;N;;;;;
+11D09;MASARAM GONDI LETTER O;Lo;0;L;;;;;N;;;;;
+11D0B;MASARAM GONDI LETTER AU;Lo;0;L;;;;;N;;;;;
+11D0C;MASARAM GONDI LETTER KA;Lo;0;L;;;;;N;;;;;
+11D0D;MASARAM GONDI LETTER KHA;Lo;0;L;;;;;N;;;;;
+11D0E;MASARAM GONDI LETTER GA;Lo;0;L;;;;;N;;;;;
+11D0F;MASARAM GONDI LETTER GHA;Lo;0;L;;;;;N;;;;;
+11D10;MASARAM GONDI LETTER NGA;Lo;0;L;;;;;N;;;;;
+11D11;MASARAM GONDI LETTER CA;Lo;0;L;;;;;N;;;;;
+11D12;MASARAM GONDI LETTER CHA;Lo;0;L;;;;;N;;;;;
+11D13;MASARAM GONDI LETTER JA;Lo;0;L;;;;;N;;;;;
+11D14;MASARAM GONDI LETTER JHA;Lo;0;L;;;;;N;;;;;
+11D15;MASARAM GONDI LETTER NYA;Lo;0;L;;;;;N;;;;;
+11D16;MASARAM GONDI LETTER TTA;Lo;0;L;;;;;N;;;;;
+11D17;MASARAM GONDI LETTER TTHA;Lo;0;L;;;;;N;;;;;
+11D18;MASARAM GONDI LETTER DDA;Lo;0;L;;;;;N;;;;;
+11D19;MASARAM GONDI LETTER DDHA;Lo;0;L;;;;;N;;;;;
+11D1A;MASARAM GONDI LETTER NNA;Lo;0;L;;;;;N;;;;;
+11D1B;MASARAM GONDI LETTER TA;Lo;0;L;;;;;N;;;;;
+11D1C;MASARAM GONDI LETTER THA;Lo;0;L;;;;;N;;;;;
+11D1D;MASARAM GONDI LETTER DA;Lo;0;L;;;;;N;;;;;
+11D1E;MASARAM GONDI LETTER DHA;Lo;0;L;;;;;N;;;;;
+11D1F;MASARAM GONDI LETTER NA;Lo;0;L;;;;;N;;;;;
+11D20;MASARAM GONDI LETTER PA;Lo;0;L;;;;;N;;;;;
+11D21;MASARAM GONDI LETTER PHA;Lo;0;L;;;;;N;;;;;
+11D22;MASARAM GONDI LETTER BA;Lo;0;L;;;;;N;;;;;
+11D23;MASARAM GONDI LETTER BHA;Lo;0;L;;;;;N;;;;;
+11D24;MASARAM GONDI LETTER MA;Lo;0;L;;;;;N;;;;;
+11D25;MASARAM GONDI LETTER YA;Lo;0;L;;;;;N;;;;;
+11D26;MASARAM GONDI LETTER RA;Lo;0;L;;;;;N;;;;;
+11D27;MASARAM GONDI LETTER LA;Lo;0;L;;;;;N;;;;;
+11D28;MASARAM GONDI LETTER VA;Lo;0;L;;;;;N;;;;;
+11D29;MASARAM GONDI LETTER SHA;Lo;0;L;;;;;N;;;;;
+11D2A;MASARAM GONDI LETTER SSA;Lo;0;L;;;;;N;;;;;
+11D2B;MASARAM GONDI LETTER SA;Lo;0;L;;;;;N;;;;;
+11D2C;MASARAM GONDI LETTER HA;Lo;0;L;;;;;N;;;;;
+11D2D;MASARAM GONDI LETTER LLA;Lo;0;L;;;;;N;;;;;
+11D2E;MASARAM GONDI LETTER KSSA;Lo;0;L;;;;;N;;;;;
+11D2F;MASARAM GONDI LETTER JNYA;Lo;0;L;;;;;N;;;;;
+11D30;MASARAM GONDI LETTER TRA;Lo;0;L;;;;;N;;;;;
+11D31;MASARAM GONDI VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;;
+11D32;MASARAM GONDI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
+11D33;MASARAM GONDI VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;;
+11D34;MASARAM GONDI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+11D35;MASARAM GONDI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
+11D36;MASARAM GONDI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;;
+11D3A;MASARAM GONDI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;;
+11D3C;MASARAM GONDI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;;
+11D3D;MASARAM GONDI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;;
+11D3F;MASARAM GONDI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;;
+11D40;MASARAM GONDI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
+11D41;MASARAM GONDI SIGN VISARGA;Mn;0;NSM;;;;;N;;;;;
+11D42;MASARAM GONDI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
+11D43;MASARAM GONDI SIGN CANDRA;Mn;0;NSM;;;;;N;;;;;
+11D44;MASARAM GONDI SIGN HALANTA;Mn;9;NSM;;;;;N;;;;;
+11D45;MASARAM GONDI VIRAMA;Mn;9;NSM;;;;;N;;;;;
+11D46;MASARAM GONDI REPHA;Lo;0;L;;;;;N;;;;;
+11D47;MASARAM GONDI RA-KARA;Mn;0;NSM;;;;;N;;;;;
+11D50;MASARAM GONDI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+11D51;MASARAM GONDI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+11D52;MASARAM GONDI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+11D53;MASARAM GONDI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+11D54;MASARAM GONDI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+11D55;MASARAM GONDI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+11D56;MASARAM GONDI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+11D57;MASARAM GONDI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+11D58;MASARAM GONDI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+11D59;MASARAM GONDI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
12000;CUNEIFORM SIGN A;Lo;0;L;;;;;N;;;;;
12001;CUNEIFORM SIGN A TIMES A;Lo;0;L;;;;;N;;;;;
12002;CUNEIFORM SIGN A TIMES BAD;Lo;0;L;;;;;N;;;;;
@@ -24087,6 +24353,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
16F9E;MIAO LETTER REFORMED TONE-6;Lm;0;L;;;;;N;;;;;
16F9F;MIAO LETTER REFORMED TONE-8;Lm;0;L;;;;;N;;;;;
16FE0;TANGUT ITERATION MARK;Lm;0;L;;;;;N;;;;;
+16FE1;NUSHU ITERATION MARK;Lm;0;L;;;;;N;;;;;
17000;<Tangut Ideograph, First>;Lo;0;L;;;;;N;;;;;
187EC;<Tangut Ideograph, Last>;Lo;0;L;;;;;N;;;;;
18800;TANGUT COMPONENT-001;Lo;0;L;;;;;N;;;;;
@@ -24846,6 +25113,687 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
18AF2;TANGUT COMPONENT-755;Lo;0;L;;;;;N;;;;;
1B000;KATAKANA LETTER ARCHAIC E;Lo;0;L;;;;;N;;;;;
1B001;HIRAGANA LETTER ARCHAIC YE;Lo;0;L;;;;;N;;;;;
+1B002;HENTAIGANA LETTER A-1;Lo;0;L;;;;;N;;;;;
+1B003;HENTAIGANA LETTER A-2;Lo;0;L;;;;;N;;;;;
+1B004;HENTAIGANA LETTER A-3;Lo;0;L;;;;;N;;;;;
+1B005;HENTAIGANA LETTER A-WO;Lo;0;L;;;;;N;;;;;
+1B006;HENTAIGANA LETTER I-1;Lo;0;L;;;;;N;;;;;
+1B007;HENTAIGANA LETTER I-2;Lo;0;L;;;;;N;;;;;
+1B008;HENTAIGANA LETTER I-3;Lo;0;L;;;;;N;;;;;
+1B009;HENTAIGANA LETTER I-4;Lo;0;L;;;;;N;;;;;
+1B00A;HENTAIGANA LETTER U-1;Lo;0;L;;;;;N;;;;;
+1B00B;HENTAIGANA LETTER U-2;Lo;0;L;;;;;N;;;;;
+1B00C;HENTAIGANA LETTER U-3;Lo;0;L;;;;;N;;;;;
+1B00D;HENTAIGANA LETTER U-4;Lo;0;L;;;;;N;;;;;
+1B00E;HENTAIGANA LETTER U-5;Lo;0;L;;;;;N;;;;;
+1B00F;HENTAIGANA LETTER E-2;Lo;0;L;;;;;N;;;;;
+1B010;HENTAIGANA LETTER E-3;Lo;0;L;;;;;N;;;;;
+1B011;HENTAIGANA LETTER E-4;Lo;0;L;;;;;N;;;;;
+1B012;HENTAIGANA LETTER E-5;Lo;0;L;;;;;N;;;;;
+1B013;HENTAIGANA LETTER E-6;Lo;0;L;;;;;N;;;;;
+1B014;HENTAIGANA LETTER O-1;Lo;0;L;;;;;N;;;;;
+1B015;HENTAIGANA LETTER O-2;Lo;0;L;;;;;N;;;;;
+1B016;HENTAIGANA LETTER O-3;Lo;0;L;;;;;N;;;;;
+1B017;HENTAIGANA LETTER KA-1;Lo;0;L;;;;;N;;;;;
+1B018;HENTAIGANA LETTER KA-2;Lo;0;L;;;;;N;;;;;
+1B019;HENTAIGANA LETTER KA-3;Lo;0;L;;;;;N;;;;;
+1B01A;HENTAIGANA LETTER KA-4;Lo;0;L;;;;;N;;;;;
+1B01B;HENTAIGANA LETTER KA-5;Lo;0;L;;;;;N;;;;;
+1B01C;HENTAIGANA LETTER KA-6;Lo;0;L;;;;;N;;;;;
+1B01D;HENTAIGANA LETTER KA-7;Lo;0;L;;;;;N;;;;;
+1B01E;HENTAIGANA LETTER KA-8;Lo;0;L;;;;;N;;;;;
+1B01F;HENTAIGANA LETTER KA-9;Lo;0;L;;;;;N;;;;;
+1B020;HENTAIGANA LETTER KA-10;Lo;0;L;;;;;N;;;;;
+1B021;HENTAIGANA LETTER KA-11;Lo;0;L;;;;;N;;;;;
+1B022;HENTAIGANA LETTER KA-KE;Lo;0;L;;;;;N;;;;;
+1B023;HENTAIGANA LETTER KI-1;Lo;0;L;;;;;N;;;;;
+1B024;HENTAIGANA LETTER KI-2;Lo;0;L;;;;;N;;;;;
+1B025;HENTAIGANA LETTER KI-3;Lo;0;L;;;;;N;;;;;
+1B026;HENTAIGANA LETTER KI-4;Lo;0;L;;;;;N;;;;;
+1B027;HENTAIGANA LETTER KI-5;Lo;0;L;;;;;N;;;;;
+1B028;HENTAIGANA LETTER KI-6;Lo;0;L;;;;;N;;;;;
+1B029;HENTAIGANA LETTER KI-7;Lo;0;L;;;;;N;;;;;
+1B02A;HENTAIGANA LETTER KI-8;Lo;0;L;;;;;N;;;;;
+1B02B;HENTAIGANA LETTER KU-1;Lo;0;L;;;;;N;;;;;
+1B02C;HENTAIGANA LETTER KU-2;Lo;0;L;;;;;N;;;;;
+1B02D;HENTAIGANA LETTER KU-3;Lo;0;L;;;;;N;;;;;
+1B02E;HENTAIGANA LETTER KU-4;Lo;0;L;;;;;N;;;;;
+1B02F;HENTAIGANA LETTER KU-5;Lo;0;L;;;;;N;;;;;
+1B030;HENTAIGANA LETTER KU-6;Lo;0;L;;;;;N;;;;;
+1B031;HENTAIGANA LETTER KU-7;Lo;0;L;;;;;N;;;;;
+1B032;HENTAIGANA LETTER KE-1;Lo;0;L;;;;;N;;;;;
+1B033;HENTAIGANA LETTER KE-2;Lo;0;L;;;;;N;;;;;
+1B034;HENTAIGANA LETTER KE-3;Lo;0;L;;;;;N;;;;;
+1B035;HENTAIGANA LETTER KE-4;Lo;0;L;;;;;N;;;;;
+1B036;HENTAIGANA LETTER KE-5;Lo;0;L;;;;;N;;;;;
+1B037;HENTAIGANA LETTER KE-6;Lo;0;L;;;;;N;;;;;
+1B038;HENTAIGANA LETTER KO-1;Lo;0;L;;;;;N;;;;;
+1B039;HENTAIGANA LETTER KO-2;Lo;0;L;;;;;N;;;;;
+1B03A;HENTAIGANA LETTER KO-3;Lo;0;L;;;;;N;;;;;
+1B03B;HENTAIGANA LETTER KO-KI;Lo;0;L;;;;;N;;;;;
+1B03C;HENTAIGANA LETTER SA-1;Lo;0;L;;;;;N;;;;;
+1B03D;HENTAIGANA LETTER SA-2;Lo;0;L;;;;;N;;;;;
+1B03E;HENTAIGANA LETTER SA-3;Lo;0;L;;;;;N;;;;;
+1B03F;HENTAIGANA LETTER SA-4;Lo;0;L;;;;;N;;;;;
+1B040;HENTAIGANA LETTER SA-5;Lo;0;L;;;;;N;;;;;
+1B041;HENTAIGANA LETTER SA-6;Lo;0;L;;;;;N;;;;;
+1B042;HENTAIGANA LETTER SA-7;Lo;0;L;;;;;N;;;;;
+1B043;HENTAIGANA LETTER SA-8;Lo;0;L;;;;;N;;;;;
+1B044;HENTAIGANA LETTER SI-1;Lo;0;L;;;;;N;;;;;
+1B045;HENTAIGANA LETTER SI-2;Lo;0;L;;;;;N;;;;;
+1B046;HENTAIGANA LETTER SI-3;Lo;0;L;;;;;N;;;;;
+1B047;HENTAIGANA LETTER SI-4;Lo;0;L;;;;;N;;;;;
+1B048;HENTAIGANA LETTER SI-5;Lo;0;L;;;;;N;;;;;
+1B049;HENTAIGANA LETTER SI-6;Lo;0;L;;;;;N;;;;;
+1B04A;HENTAIGANA LETTER SU-1;Lo;0;L;;;;;N;;;;;
+1B04B;HENTAIGANA LETTER SU-2;Lo;0;L;;;;;N;;;;;
+1B04C;HENTAIGANA LETTER SU-3;Lo;0;L;;;;;N;;;;;
+1B04D;HENTAIGANA LETTER SU-4;Lo;0;L;;;;;N;;;;;
+1B04E;HENTAIGANA LETTER SU-5;Lo;0;L;;;;;N;;;;;
+1B04F;HENTAIGANA LETTER SU-6;Lo;0;L;;;;;N;;;;;
+1B050;HENTAIGANA LETTER SU-7;Lo;0;L;;;;;N;;;;;
+1B051;HENTAIGANA LETTER SU-8;Lo;0;L;;;;;N;;;;;
+1B052;HENTAIGANA LETTER SE-1;Lo;0;L;;;;;N;;;;;
+1B053;HENTAIGANA LETTER SE-2;Lo;0;L;;;;;N;;;;;
+1B054;HENTAIGANA LETTER SE-3;Lo;0;L;;;;;N;;;;;
+1B055;HENTAIGANA LETTER SE-4;Lo;0;L;;;;;N;;;;;
+1B056;HENTAIGANA LETTER SE-5;Lo;0;L;;;;;N;;;;;
+1B057;HENTAIGANA LETTER SO-1;Lo;0;L;;;;;N;;;;;
+1B058;HENTAIGANA LETTER SO-2;Lo;0;L;;;;;N;;;;;
+1B059;HENTAIGANA LETTER SO-3;Lo;0;L;;;;;N;;;;;
+1B05A;HENTAIGANA LETTER SO-4;Lo;0;L;;;;;N;;;;;
+1B05B;HENTAIGANA LETTER SO-5;Lo;0;L;;;;;N;;;;;
+1B05C;HENTAIGANA LETTER SO-6;Lo;0;L;;;;;N;;;;;
+1B05D;HENTAIGANA LETTER SO-7;Lo;0;L;;;;;N;;;;;
+1B05E;HENTAIGANA LETTER TA-1;Lo;0;L;;;;;N;;;;;
+1B05F;HENTAIGANA LETTER TA-2;Lo;0;L;;;;;N;;;;;
+1B060;HENTAIGANA LETTER TA-3;Lo;0;L;;;;;N;;;;;
+1B061;HENTAIGANA LETTER TA-4;Lo;0;L;;;;;N;;;;;
+1B062;HENTAIGANA LETTER TI-1;Lo;0;L;;;;;N;;;;;
+1B063;HENTAIGANA LETTER TI-2;Lo;0;L;;;;;N;;;;;
+1B064;HENTAIGANA LETTER TI-3;Lo;0;L;;;;;N;;;;;
+1B065;HENTAIGANA LETTER TI-4;Lo;0;L;;;;;N;;;;;
+1B066;HENTAIGANA LETTER TI-5;Lo;0;L;;;;;N;;;;;
+1B067;HENTAIGANA LETTER TI-6;Lo;0;L;;;;;N;;;;;
+1B068;HENTAIGANA LETTER TI-7;Lo;0;L;;;;;N;;;;;
+1B069;HENTAIGANA LETTER TU-1;Lo;0;L;;;;;N;;;;;
+1B06A;HENTAIGANA LETTER TU-2;Lo;0;L;;;;;N;;;;;
+1B06B;HENTAIGANA LETTER TU-3;Lo;0;L;;;;;N;;;;;
+1B06C;HENTAIGANA LETTER TU-4;Lo;0;L;;;;;N;;;;;
+1B06D;HENTAIGANA LETTER TU-TO;Lo;0;L;;;;;N;;;;;
+1B06E;HENTAIGANA LETTER TE-1;Lo;0;L;;;;;N;;;;;
+1B06F;HENTAIGANA LETTER TE-2;Lo;0;L;;;;;N;;;;;
+1B070;HENTAIGANA LETTER TE-3;Lo;0;L;;;;;N;;;;;
+1B071;HENTAIGANA LETTER TE-4;Lo;0;L;;;;;N;;;;;
+1B072;HENTAIGANA LETTER TE-5;Lo;0;L;;;;;N;;;;;
+1B073;HENTAIGANA LETTER TE-6;Lo;0;L;;;;;N;;;;;
+1B074;HENTAIGANA LETTER TE-7;Lo;0;L;;;;;N;;;;;
+1B075;HENTAIGANA LETTER TE-8;Lo;0;L;;;;;N;;;;;
+1B076;HENTAIGANA LETTER TE-9;Lo;0;L;;;;;N;;;;;
+1B077;HENTAIGANA LETTER TO-1;Lo;0;L;;;;;N;;;;;
+1B078;HENTAIGANA LETTER TO-2;Lo;0;L;;;;;N;;;;;
+1B079;HENTAIGANA LETTER TO-3;Lo;0;L;;;;;N;;;;;
+1B07A;HENTAIGANA LETTER TO-4;Lo;0;L;;;;;N;;;;;
+1B07B;HENTAIGANA LETTER TO-5;Lo;0;L;;;;;N;;;;;
+1B07C;HENTAIGANA LETTER TO-6;Lo;0;L;;;;;N;;;;;
+1B07D;HENTAIGANA LETTER TO-RA;Lo;0;L;;;;;N;;;;;
+1B07E;HENTAIGANA LETTER NA-1;Lo;0;L;;;;;N;;;;;
+1B07F;HENTAIGANA LETTER NA-2;Lo;0;L;;;;;N;;;;;
+1B080;HENTAIGANA LETTER NA-3;Lo;0;L;;;;;N;;;;;
+1B081;HENTAIGANA LETTER NA-4;Lo;0;L;;;;;N;;;;;
+1B082;HENTAIGANA LETTER NA-5;Lo;0;L;;;;;N;;;;;
+1B083;HENTAIGANA LETTER NA-6;Lo;0;L;;;;;N;;;;;
+1B084;HENTAIGANA LETTER NA-7;Lo;0;L;;;;;N;;;;;
+1B085;HENTAIGANA LETTER NA-8;Lo;0;L;;;;;N;;;;;
+1B086;HENTAIGANA LETTER NA-9;Lo;0;L;;;;;N;;;;;
+1B087;HENTAIGANA LETTER NI-1;Lo;0;L;;;;;N;;;;;
+1B088;HENTAIGANA LETTER NI-2;Lo;0;L;;;;;N;;;;;
+1B089;HENTAIGANA LETTER NI-3;Lo;0;L;;;;;N;;;;;
+1B08A;HENTAIGANA LETTER NI-4;Lo;0;L;;;;;N;;;;;
+1B08B;HENTAIGANA LETTER NI-5;Lo;0;L;;;;;N;;;;;
+1B08C;HENTAIGANA LETTER NI-6;Lo;0;L;;;;;N;;;;;
+1B08D;HENTAIGANA LETTER NI-7;Lo;0;L;;;;;N;;;;;
+1B08E;HENTAIGANA LETTER NI-TE;Lo;0;L;;;;;N;;;;;
+1B08F;HENTAIGANA LETTER NU-1;Lo;0;L;;;;;N;;;;;
+1B090;HENTAIGANA LETTER NU-2;Lo;0;L;;;;;N;;;;;
+1B091;HENTAIGANA LETTER NU-3;Lo;0;L;;;;;N;;;;;
+1B092;HENTAIGANA LETTER NE-1;Lo;0;L;;;;;N;;;;;
+1B093;HENTAIGANA LETTER NE-2;Lo;0;L;;;;;N;;;;;
+1B094;HENTAIGANA LETTER NE-3;Lo;0;L;;;;;N;;;;;
+1B095;HENTAIGANA LETTER NE-4;Lo;0;L;;;;;N;;;;;
+1B096;HENTAIGANA LETTER NE-5;Lo;0;L;;;;;N;;;;;
+1B097;HENTAIGANA LETTER NE-6;Lo;0;L;;;;;N;;;;;
+1B098;HENTAIGANA LETTER NE-KO;Lo;0;L;;;;;N;;;;;
+1B099;HENTAIGANA LETTER NO-1;Lo;0;L;;;;;N;;;;;
+1B09A;HENTAIGANA LETTER NO-2;Lo;0;L;;;;;N;;;;;
+1B09B;HENTAIGANA LETTER NO-3;Lo;0;L;;;;;N;;;;;
+1B09C;HENTAIGANA LETTER NO-4;Lo;0;L;;;;;N;;;;;
+1B09D;HENTAIGANA LETTER NO-5;Lo;0;L;;;;;N;;;;;
+1B09E;HENTAIGANA LETTER HA-1;Lo;0;L;;;;;N;;;;;
+1B09F;HENTAIGANA LETTER HA-2;Lo;0;L;;;;;N;;;;;
+1B0A0;HENTAIGANA LETTER HA-3;Lo;0;L;;;;;N;;;;;
+1B0A1;HENTAIGANA LETTER HA-4;Lo;0;L;;;;;N;;;;;
+1B0A2;HENTAIGANA LETTER HA-5;Lo;0;L;;;;;N;;;;;
+1B0A3;HENTAIGANA LETTER HA-6;Lo;0;L;;;;;N;;;;;
+1B0A4;HENTAIGANA LETTER HA-7;Lo;0;L;;;;;N;;;;;
+1B0A5;HENTAIGANA LETTER HA-8;Lo;0;L;;;;;N;;;;;
+1B0A6;HENTAIGANA LETTER HA-9;Lo;0;L;;;;;N;;;;;
+1B0A7;HENTAIGANA LETTER HA-10;Lo;0;L;;;;;N;;;;;
+1B0A8;HENTAIGANA LETTER HA-11;Lo;0;L;;;;;N;;;;;
+1B0A9;HENTAIGANA LETTER HI-1;Lo;0;L;;;;;N;;;;;
+1B0AA;HENTAIGANA LETTER HI-2;Lo;0;L;;;;;N;;;;;
+1B0AB;HENTAIGANA LETTER HI-3;Lo;0;L;;;;;N;;;;;
+1B0AC;HENTAIGANA LETTER HI-4;Lo;0;L;;;;;N;;;;;
+1B0AD;HENTAIGANA LETTER HI-5;Lo;0;L;;;;;N;;;;;
+1B0AE;HENTAIGANA LETTER HI-6;Lo;0;L;;;;;N;;;;;
+1B0AF;HENTAIGANA LETTER HI-7;Lo;0;L;;;;;N;;;;;
+1B0B0;HENTAIGANA LETTER HU-1;Lo;0;L;;;;;N;;;;;
+1B0B1;HENTAIGANA LETTER HU-2;Lo;0;L;;;;;N;;;;;
+1B0B2;HENTAIGANA LETTER HU-3;Lo;0;L;;;;;N;;;;;
+1B0B3;HENTAIGANA LETTER HE-1;Lo;0;L;;;;;N;;;;;
+1B0B4;HENTAIGANA LETTER HE-2;Lo;0;L;;;;;N;;;;;
+1B0B5;HENTAIGANA LETTER HE-3;Lo;0;L;;;;;N;;;;;
+1B0B6;HENTAIGANA LETTER HE-4;Lo;0;L;;;;;N;;;;;
+1B0B7;HENTAIGANA LETTER HE-5;Lo;0;L;;;;;N;;;;;
+1B0B8;HENTAIGANA LETTER HE-6;Lo;0;L;;;;;N;;;;;
+1B0B9;HENTAIGANA LETTER HE-7;Lo;0;L;;;;;N;;;;;
+1B0BA;HENTAIGANA LETTER HO-1;Lo;0;L;;;;;N;;;;;
+1B0BB;HENTAIGANA LETTER HO-2;Lo;0;L;;;;;N;;;;;
+1B0BC;HENTAIGANA LETTER HO-3;Lo;0;L;;;;;N;;;;;
+1B0BD;HENTAIGANA LETTER HO-4;Lo;0;L;;;;;N;;;;;
+1B0BE;HENTAIGANA LETTER HO-5;Lo;0;L;;;;;N;;;;;
+1B0BF;HENTAIGANA LETTER HO-6;Lo;0;L;;;;;N;;;;;
+1B0C0;HENTAIGANA LETTER HO-7;Lo;0;L;;;;;N;;;;;
+1B0C1;HENTAIGANA LETTER HO-8;Lo;0;L;;;;;N;;;;;
+1B0C2;HENTAIGANA LETTER MA-1;Lo;0;L;;;;;N;;;;;
+1B0C3;HENTAIGANA LETTER MA-2;Lo;0;L;;;;;N;;;;;
+1B0C4;HENTAIGANA LETTER MA-3;Lo;0;L;;;;;N;;;;;
+1B0C5;HENTAIGANA LETTER MA-4;Lo;0;L;;;;;N;;;;;
+1B0C6;HENTAIGANA LETTER MA-5;Lo;0;L;;;;;N;;;;;
+1B0C7;HENTAIGANA LETTER MA-6;Lo;0;L;;;;;N;;;;;
+1B0C8;HENTAIGANA LETTER MA-7;Lo;0;L;;;;;N;;;;;
+1B0C9;HENTAIGANA LETTER MI-1;Lo;0;L;;;;;N;;;;;
+1B0CA;HENTAIGANA LETTER MI-2;Lo;0;L;;;;;N;;;;;
+1B0CB;HENTAIGANA LETTER MI-3;Lo;0;L;;;;;N;;;;;
+1B0CC;HENTAIGANA LETTER MI-4;Lo;0;L;;;;;N;;;;;
+1B0CD;HENTAIGANA LETTER MI-5;Lo;0;L;;;;;N;;;;;
+1B0CE;HENTAIGANA LETTER MI-6;Lo;0;L;;;;;N;;;;;
+1B0CF;HENTAIGANA LETTER MI-7;Lo;0;L;;;;;N;;;;;
+1B0D0;HENTAIGANA LETTER MU-1;Lo;0;L;;;;;N;;;;;
+1B0D1;HENTAIGANA LETTER MU-2;Lo;0;L;;;;;N;;;;;
+1B0D2;HENTAIGANA LETTER MU-3;Lo;0;L;;;;;N;;;;;
+1B0D3;HENTAIGANA LETTER MU-4;Lo;0;L;;;;;N;;;;;
+1B0D4;HENTAIGANA LETTER ME-1;Lo;0;L;;;;;N;;;;;
+1B0D5;HENTAIGANA LETTER ME-2;Lo;0;L;;;;;N;;;;;
+1B0D6;HENTAIGANA LETTER ME-MA;Lo;0;L;;;;;N;;;;;
+1B0D7;HENTAIGANA LETTER MO-1;Lo;0;L;;;;;N;;;;;
+1B0D8;HENTAIGANA LETTER MO-2;Lo;0;L;;;;;N;;;;;
+1B0D9;HENTAIGANA LETTER MO-3;Lo;0;L;;;;;N;;;;;
+1B0DA;HENTAIGANA LETTER MO-4;Lo;0;L;;;;;N;;;;;
+1B0DB;HENTAIGANA LETTER MO-5;Lo;0;L;;;;;N;;;;;
+1B0DC;HENTAIGANA LETTER MO-6;Lo;0;L;;;;;N;;;;;
+1B0DD;HENTAIGANA LETTER YA-1;Lo;0;L;;;;;N;;;;;
+1B0DE;HENTAIGANA LETTER YA-2;Lo;0;L;;;;;N;;;;;
+1B0DF;HENTAIGANA LETTER YA-3;Lo;0;L;;;;;N;;;;;
+1B0E0;HENTAIGANA LETTER YA-4;Lo;0;L;;;;;N;;;;;
+1B0E1;HENTAIGANA LETTER YA-5;Lo;0;L;;;;;N;;;;;
+1B0E2;HENTAIGANA LETTER YA-YO;Lo;0;L;;;;;N;;;;;
+1B0E3;HENTAIGANA LETTER YU-1;Lo;0;L;;;;;N;;;;;
+1B0E4;HENTAIGANA LETTER YU-2;Lo;0;L;;;;;N;;;;;
+1B0E5;HENTAIGANA LETTER YU-3;Lo;0;L;;;;;N;;;;;
+1B0E6;HENTAIGANA LETTER YU-4;Lo;0;L;;;;;N;;;;;
+1B0E7;HENTAIGANA LETTER YO-1;Lo;0;L;;;;;N;;;;;
+1B0E8;HENTAIGANA LETTER YO-2;Lo;0;L;;;;;N;;;;;
+1B0E9;HENTAIGANA LETTER YO-3;Lo;0;L;;;;;N;;;;;
+1B0EA;HENTAIGANA LETTER YO-4;Lo;0;L;;;;;N;;;;;
+1B0EB;HENTAIGANA LETTER YO-5;Lo;0;L;;;;;N;;;;;
+1B0EC;HENTAIGANA LETTER YO-6;Lo;0;L;;;;;N;;;;;
+1B0ED;HENTAIGANA LETTER RA-1;Lo;0;L;;;;;N;;;;;
+1B0EE;HENTAIGANA LETTER RA-2;Lo;0;L;;;;;N;;;;;
+1B0EF;HENTAIGANA LETTER RA-3;Lo;0;L;;;;;N;;;;;
+1B0F0;HENTAIGANA LETTER RA-4;Lo;0;L;;;;;N;;;;;
+1B0F1;HENTAIGANA LETTER RI-1;Lo;0;L;;;;;N;;;;;
+1B0F2;HENTAIGANA LETTER RI-2;Lo;0;L;;;;;N;;;;;
+1B0F3;HENTAIGANA LETTER RI-3;Lo;0;L;;;;;N;;;;;
+1B0F4;HENTAIGANA LETTER RI-4;Lo;0;L;;;;;N;;;;;
+1B0F5;HENTAIGANA LETTER RI-5;Lo;0;L;;;;;N;;;;;
+1B0F6;HENTAIGANA LETTER RI-6;Lo;0;L;;;;;N;;;;;
+1B0F7;HENTAIGANA LETTER RI-7;Lo;0;L;;;;;N;;;;;
+1B0F8;HENTAIGANA LETTER RU-1;Lo;0;L;;;;;N;;;;;
+1B0F9;HENTAIGANA LETTER RU-2;Lo;0;L;;;;;N;;;;;
+1B0FA;HENTAIGANA LETTER RU-3;Lo;0;L;;;;;N;;;;;
+1B0FB;HENTAIGANA LETTER RU-4;Lo;0;L;;;;;N;;;;;
+1B0FC;HENTAIGANA LETTER RU-5;Lo;0;L;;;;;N;;;;;
+1B0FD;HENTAIGANA LETTER RU-6;Lo;0;L;;;;;N;;;;;
+1B0FE;HENTAIGANA LETTER RE-1;Lo;0;L;;;;;N;;;;;
+1B0FF;HENTAIGANA LETTER RE-2;Lo;0;L;;;;;N;;;;;
+1B100;HENTAIGANA LETTER RE-3;Lo;0;L;;;;;N;;;;;
+1B101;HENTAIGANA LETTER RE-4;Lo;0;L;;;;;N;;;;;
+1B102;HENTAIGANA LETTER RO-1;Lo;0;L;;;;;N;;;;;
+1B103;HENTAIGANA LETTER RO-2;Lo;0;L;;;;;N;;;;;
+1B104;HENTAIGANA LETTER RO-3;Lo;0;L;;;;;N;;;;;
+1B105;HENTAIGANA LETTER RO-4;Lo;0;L;;;;;N;;;;;
+1B106;HENTAIGANA LETTER RO-5;Lo;0;L;;;;;N;;;;;
+1B107;HENTAIGANA LETTER RO-6;Lo;0;L;;;;;N;;;;;
+1B108;HENTAIGANA LETTER WA-1;Lo;0;L;;;;;N;;;;;
+1B109;HENTAIGANA LETTER WA-2;Lo;0;L;;;;;N;;;;;
+1B10A;HENTAIGANA LETTER WA-3;Lo;0;L;;;;;N;;;;;
+1B10B;HENTAIGANA LETTER WA-4;Lo;0;L;;;;;N;;;;;
+1B10C;HENTAIGANA LETTER WA-5;Lo;0;L;;;;;N;;;;;
+1B10D;HENTAIGANA LETTER WI-1;Lo;0;L;;;;;N;;;;;
+1B10E;HENTAIGANA LETTER WI-2;Lo;0;L;;;;;N;;;;;
+1B10F;HENTAIGANA LETTER WI-3;Lo;0;L;;;;;N;;;;;
+1B110;HENTAIGANA LETTER WI-4;Lo;0;L;;;;;N;;;;;
+1B111;HENTAIGANA LETTER WI-5;Lo;0;L;;;;;N;;;;;
+1B112;HENTAIGANA LETTER WE-1;Lo;0;L;;;;;N;;;;;
+1B113;HENTAIGANA LETTER WE-2;Lo;0;L;;;;;N;;;;;
+1B114;HENTAIGANA LETTER WE-3;Lo;0;L;;;;;N;;;;;
+1B115;HENTAIGANA LETTER WE-4;Lo;0;L;;;;;N;;;;;
+1B116;HENTAIGANA LETTER WO-1;Lo;0;L;;;;;N;;;;;
+1B117;HENTAIGANA LETTER WO-2;Lo;0;L;;;;;N;;;;;
+1B118;HENTAIGANA LETTER WO-3;Lo;0;L;;;;;N;;;;;
+1B119;HENTAIGANA LETTER WO-4;Lo;0;L;;;;;N;;;;;
+1B11A;HENTAIGANA LETTER WO-5;Lo;0;L;;;;;N;;;;;
+1B11B;HENTAIGANA LETTER WO-6;Lo;0;L;;;;;N;;;;;
+1B11C;HENTAIGANA LETTER WO-7;Lo;0;L;;;;;N;;;;;
+1B11D;HENTAIGANA LETTER N-MU-MO-1;Lo;0;L;;;;;N;;;;;
+1B11E;HENTAIGANA LETTER N-MU-MO-2;Lo;0;L;;;;;N;;;;;
+1B170;NUSHU CHARACTER-1B170;Lo;0;L;;;;;N;;;;;
+1B171;NUSHU CHARACTER-1B171;Lo;0;L;;;;;N;;;;;
+1B172;NUSHU CHARACTER-1B172;Lo;0;L;;;;;N;;;;;
+1B173;NUSHU CHARACTER-1B173;Lo;0;L;;;;;N;;;;;
+1B174;NUSHU CHARACTER-1B174;Lo;0;L;;;;;N;;;;;
+1B175;NUSHU CHARACTER-1B175;Lo;0;L;;;;;N;;;;;
+1B176;NUSHU CHARACTER-1B176;Lo;0;L;;;;;N;;;;;
+1B177;NUSHU CHARACTER-1B177;Lo;0;L;;;;;N;;;;;
+1B178;NUSHU CHARACTER-1B178;Lo;0;L;;;;;N;;;;;
+1B179;NUSHU CHARACTER-1B179;Lo;0;L;;;;;N;;;;;
+1B17A;NUSHU CHARACTER-1B17A;Lo;0;L;;;;;N;;;;;
+1B17B;NUSHU CHARACTER-1B17B;Lo;0;L;;;;;N;;;;;
+1B17C;NUSHU CHARACTER-1B17C;Lo;0;L;;;;;N;;;;;
+1B17D;NUSHU CHARACTER-1B17D;Lo;0;L;;;;;N;;;;;
+1B17E;NUSHU CHARACTER-1B17E;Lo;0;L;;;;;N;;;;;
+1B17F;NUSHU CHARACTER-1B17F;Lo;0;L;;;;;N;;;;;
+1B180;NUSHU CHARACTER-1B180;Lo;0;L;;;;;N;;;;;
+1B181;NUSHU CHARACTER-1B181;Lo;0;L;;;;;N;;;;;
+1B182;NUSHU CHARACTER-1B182;Lo;0;L;;;;;N;;;;;
+1B183;NUSHU CHARACTER-1B183;Lo;0;L;;;;;N;;;;;
+1B184;NUSHU CHARACTER-1B184;Lo;0;L;;;;;N;;;;;
+1B185;NUSHU CHARACTER-1B185;Lo;0;L;;;;;N;;;;;
+1B186;NUSHU CHARACTER-1B186;Lo;0;L;;;;;N;;;;;
+1B187;NUSHU CHARACTER-1B187;Lo;0;L;;;;;N;;;;;
+1B188;NUSHU CHARACTER-1B188;Lo;0;L;;;;;N;;;;;
+1B189;NUSHU CHARACTER-1B189;Lo;0;L;;;;;N;;;;;
+1B18A;NUSHU CHARACTER-1B18A;Lo;0;L;;;;;N;;;;;
+1B18B;NUSHU CHARACTER-1B18B;Lo;0;L;;;;;N;;;;;
+1B18C;NUSHU CHARACTER-1B18C;Lo;0;L;;;;;N;;;;;
+1B18D;NUSHU CHARACTER-1B18D;Lo;0;L;;;;;N;;;;;
+1B18E;NUSHU CHARACTER-1B18E;Lo;0;L;;;;;N;;;;;
+1B18F;NUSHU CHARACTER-1B18F;Lo;0;L;;;;;N;;;;;
+1B190;NUSHU CHARACTER-1B190;Lo;0;L;;;;;N;;;;;
+1B191;NUSHU CHARACTER-1B191;Lo;0;L;;;;;N;;;;;
+1B192;NUSHU CHARACTER-1B192;Lo;0;L;;;;;N;;;;;
+1B193;NUSHU CHARACTER-1B193;Lo;0;L;;;;;N;;;;;
+1B194;NUSHU CHARACTER-1B194;Lo;0;L;;;;;N;;;;;
+1B195;NUSHU CHARACTER-1B195;Lo;0;L;;;;;N;;;;;
+1B196;NUSHU CHARACTER-1B196;Lo;0;L;;;;;N;;;;;
+1B197;NUSHU CHARACTER-1B197;Lo;0;L;;;;;N;;;;;
+1B198;NUSHU CHARACTER-1B198;Lo;0;L;;;;;N;;;;;
+1B199;NUSHU CHARACTER-1B199;Lo;0;L;;;;;N;;;;;
+1B19A;NUSHU CHARACTER-1B19A;Lo;0;L;;;;;N;;;;;
+1B19B;NUSHU CHARACTER-1B19B;Lo;0;L;;;;;N;;;;;
+1B19C;NUSHU CHARACTER-1B19C;Lo;0;L;;;;;N;;;;;
+1B19D;NUSHU CHARACTER-1B19D;Lo;0;L;;;;;N;;;;;
+1B19E;NUSHU CHARACTER-1B19E;Lo;0;L;;;;;N;;;;;
+1B19F;NUSHU CHARACTER-1B19F;Lo;0;L;;;;;N;;;;;
+1B1A0;NUSHU CHARACTER-1B1A0;Lo;0;L;;;;;N;;;;;
+1B1A1;NUSHU CHARACTER-1B1A1;Lo;0;L;;;;;N;;;;;
+1B1A2;NUSHU CHARACTER-1B1A2;Lo;0;L;;;;;N;;;;;
+1B1A3;NUSHU CHARACTER-1B1A3;Lo;0;L;;;;;N;;;;;
+1B1A4;NUSHU CHARACTER-1B1A4;Lo;0;L;;;;;N;;;;;
+1B1A5;NUSHU CHARACTER-1B1A5;Lo;0;L;;;;;N;;;;;
+1B1A6;NUSHU CHARACTER-1B1A6;Lo;0;L;;;;;N;;;;;
+1B1A7;NUSHU CHARACTER-1B1A7;Lo;0;L;;;;;N;;;;;
+1B1A8;NUSHU CHARACTER-1B1A8;Lo;0;L;;;;;N;;;;;
+1B1A9;NUSHU CHARACTER-1B1A9;Lo;0;L;;;;;N;;;;;
+1B1AA;NUSHU CHARACTER-1B1AA;Lo;0;L;;;;;N;;;;;
+1B1AB;NUSHU CHARACTER-1B1AB;Lo;0;L;;;;;N;;;;;
+1B1AC;NUSHU CHARACTER-1B1AC;Lo;0;L;;;;;N;;;;;
+1B1AD;NUSHU CHARACTER-1B1AD;Lo;0;L;;;;;N;;;;;
+1B1AE;NUSHU CHARACTER-1B1AE;Lo;0;L;;;;;N;;;;;
+1B1AF;NUSHU CHARACTER-1B1AF;Lo;0;L;;;;;N;;;;;
+1B1B0;NUSHU CHARACTER-1B1B0;Lo;0;L;;;;;N;;;;;
+1B1B1;NUSHU CHARACTER-1B1B1;Lo;0;L;;;;;N;;;;;
+1B1B2;NUSHU CHARACTER-1B1B2;Lo;0;L;;;;;N;;;;;
+1B1B3;NUSHU CHARACTER-1B1B3;Lo;0;L;;;;;N;;;;;
+1B1B4;NUSHU CHARACTER-1B1B4;Lo;0;L;;;;;N;;;;;
+1B1B5;NUSHU CHARACTER-1B1B5;Lo;0;L;;;;;N;;;;;
+1B1B6;NUSHU CHARACTER-1B1B6;Lo;0;L;;;;;N;;;;;
+1B1B7;NUSHU CHARACTER-1B1B7;Lo;0;L;;;;;N;;;;;
+1B1B8;NUSHU CHARACTER-1B1B8;Lo;0;L;;;;;N;;;;;
+1B1B9;NUSHU CHARACTER-1B1B9;Lo;0;L;;;;;N;;;;;
+1B1BA;NUSHU CHARACTER-1B1BA;Lo;0;L;;;;;N;;;;;
+1B1BB;NUSHU CHARACTER-1B1BB;Lo;0;L;;;;;N;;;;;
+1B1BC;NUSHU CHARACTER-1B1BC;Lo;0;L;;;;;N;;;;;
+1B1BD;NUSHU CHARACTER-1B1BD;Lo;0;L;;;;;N;;;;;
+1B1BE;NUSHU CHARACTER-1B1BE;Lo;0;L;;;;;N;;;;;
+1B1BF;NUSHU CHARACTER-1B1BF;Lo;0;L;;;;;N;;;;;
+1B1C0;NUSHU CHARACTER-1B1C0;Lo;0;L;;;;;N;;;;;
+1B1C1;NUSHU CHARACTER-1B1C1;Lo;0;L;;;;;N;;;;;
+1B1C2;NUSHU CHARACTER-1B1C2;Lo;0;L;;;;;N;;;;;
+1B1C3;NUSHU CHARACTER-1B1C3;Lo;0;L;;;;;N;;;;;
+1B1C4;NUSHU CHARACTER-1B1C4;Lo;0;L;;;;;N;;;;;
+1B1C5;NUSHU CHARACTER-1B1C5;Lo;0;L;;;;;N;;;;;
+1B1C6;NUSHU CHARACTER-1B1C6;Lo;0;L;;;;;N;;;;;
+1B1C7;NUSHU CHARACTER-1B1C7;Lo;0;L;;;;;N;;;;;
+1B1C8;NUSHU CHARACTER-1B1C8;Lo;0;L;;;;;N;;;;;
+1B1C9;NUSHU CHARACTER-1B1C9;Lo;0;L;;;;;N;;;;;
+1B1CA;NUSHU CHARACTER-1B1CA;Lo;0;L;;;;;N;;;;;
+1B1CB;NUSHU CHARACTER-1B1CB;Lo;0;L;;;;;N;;;;;
+1B1CC;NUSHU CHARACTER-1B1CC;Lo;0;L;;;;;N;;;;;
+1B1CD;NUSHU CHARACTER-1B1CD;Lo;0;L;;;;;N;;;;;
+1B1CE;NUSHU CHARACTER-1B1CE;Lo;0;L;;;;;N;;;;;
+1B1CF;NUSHU CHARACTER-1B1CF;Lo;0;L;;;;;N;;;;;
+1B1D0;NUSHU CHARACTER-1B1D0;Lo;0;L;;;;;N;;;;;
+1B1D1;NUSHU CHARACTER-1B1D1;Lo;0;L;;;;;N;;;;;
+1B1D2;NUSHU CHARACTER-1B1D2;Lo;0;L;;;;;N;;;;;
+1B1D3;NUSHU CHARACTER-1B1D3;Lo;0;L;;;;;N;;;;;
+1B1D4;NUSHU CHARACTER-1B1D4;Lo;0;L;;;;;N;;;;;
+1B1D5;NUSHU CHARACTER-1B1D5;Lo;0;L;;;;;N;;;;;
+1B1D6;NUSHU CHARACTER-1B1D6;Lo;0;L;;;;;N;;;;;
+1B1D7;NUSHU CHARACTER-1B1D7;Lo;0;L;;;;;N;;;;;
+1B1D8;NUSHU CHARACTER-1B1D8;Lo;0;L;;;;;N;;;;;
+1B1D9;NUSHU CHARACTER-1B1D9;Lo;0;L;;;;;N;;;;;
+1B1DA;NUSHU CHARACTER-1B1DA;Lo;0;L;;;;;N;;;;;
+1B1DB;NUSHU CHARACTER-1B1DB;Lo;0;L;;;;;N;;;;;
+1B1DC;NUSHU CHARACTER-1B1DC;Lo;0;L;;;;;N;;;;;
+1B1DD;NUSHU CHARACTER-1B1DD;Lo;0;L;;;;;N;;;;;
+1B1DE;NUSHU CHARACTER-1B1DE;Lo;0;L;;;;;N;;;;;
+1B1DF;NUSHU CHARACTER-1B1DF;Lo;0;L;;;;;N;;;;;
+1B1E0;NUSHU CHARACTER-1B1E0;Lo;0;L;;;;;N;;;;;
+1B1E1;NUSHU CHARACTER-1B1E1;Lo;0;L;;;;;N;;;;;
+1B1E2;NUSHU CHARACTER-1B1E2;Lo;0;L;;;;;N;;;;;
+1B1E3;NUSHU CHARACTER-1B1E3;Lo;0;L;;;;;N;;;;;
+1B1E4;NUSHU CHARACTER-1B1E4;Lo;0;L;;;;;N;;;;;
+1B1E5;NUSHU CHARACTER-1B1E5;Lo;0;L;;;;;N;;;;;
+1B1E6;NUSHU CHARACTER-1B1E6;Lo;0;L;;;;;N;;;;;
+1B1E7;NUSHU CHARACTER-1B1E7;Lo;0;L;;;;;N;;;;;
+1B1E8;NUSHU CHARACTER-1B1E8;Lo;0;L;;;;;N;;;;;
+1B1E9;NUSHU CHARACTER-1B1E9;Lo;0;L;;;;;N;;;;;
+1B1EA;NUSHU CHARACTER-1B1EA;Lo;0;L;;;;;N;;;;;
+1B1EB;NUSHU CHARACTER-1B1EB;Lo;0;L;;;;;N;;;;;
+1B1EC;NUSHU CHARACTER-1B1EC;Lo;0;L;;;;;N;;;;;
+1B1ED;NUSHU CHARACTER-1B1ED;Lo;0;L;;;;;N;;;;;
+1B1EE;NUSHU CHARACTER-1B1EE;Lo;0;L;;;;;N;;;;;
+1B1EF;NUSHU CHARACTER-1B1EF;Lo;0;L;;;;;N;;;;;
+1B1F0;NUSHU CHARACTER-1B1F0;Lo;0;L;;;;;N;;;;;
+1B1F1;NUSHU CHARACTER-1B1F1;Lo;0;L;;;;;N;;;;;
+1B1F2;NUSHU CHARACTER-1B1F2;Lo;0;L;;;;;N;;;;;
+1B1F3;NUSHU CHARACTER-1B1F3;Lo;0;L;;;;;N;;;;;
+1B1F4;NUSHU CHARACTER-1B1F4;Lo;0;L;;;;;N;;;;;
+1B1F5;NUSHU CHARACTER-1B1F5;Lo;0;L;;;;;N;;;;;
+1B1F6;NUSHU CHARACTER-1B1F6;Lo;0;L;;;;;N;;;;;
+1B1F7;NUSHU CHARACTER-1B1F7;Lo;0;L;;;;;N;;;;;
+1B1F8;NUSHU CHARACTER-1B1F8;Lo;0;L;;;;;N;;;;;
+1B1F9;NUSHU CHARACTER-1B1F9;Lo;0;L;;;;;N;;;;;
+1B1FA;NUSHU CHARACTER-1B1FA;Lo;0;L;;;;;N;;;;;
+1B1FB;NUSHU CHARACTER-1B1FB;Lo;0;L;;;;;N;;;;;
+1B1FC;NUSHU CHARACTER-1B1FC;Lo;0;L;;;;;N;;;;;
+1B1FD;NUSHU CHARACTER-1B1FD;Lo;0;L;;;;;N;;;;;
+1B1FE;NUSHU CHARACTER-1B1FE;Lo;0;L;;;;;N;;;;;
+1B1FF;NUSHU CHARACTER-1B1FF;Lo;0;L;;;;;N;;;;;
+1B200;NUSHU CHARACTER-1B200;Lo;0;L;;;;;N;;;;;
+1B201;NUSHU CHARACTER-1B201;Lo;0;L;;;;;N;;;;;
+1B202;NUSHU CHARACTER-1B202;Lo;0;L;;;;;N;;;;;
+1B203;NUSHU CHARACTER-1B203;Lo;0;L;;;;;N;;;;;
+1B204;NUSHU CHARACTER-1B204;Lo;0;L;;;;;N;;;;;
+1B205;NUSHU CHARACTER-1B205;Lo;0;L;;;;;N;;;;;
+1B206;NUSHU CHARACTER-1B206;Lo;0;L;;;;;N;;;;;
+1B207;NUSHU CHARACTER-1B207;Lo;0;L;;;;;N;;;;;
+1B208;NUSHU CHARACTER-1B208;Lo;0;L;;;;;N;;;;;
+1B209;NUSHU CHARACTER-1B209;Lo;0;L;;;;;N;;;;;
+1B20A;NUSHU CHARACTER-1B20A;Lo;0;L;;;;;N;;;;;
+1B20B;NUSHU CHARACTER-1B20B;Lo;0;L;;;;;N;;;;;
+1B20C;NUSHU CHARACTER-1B20C;Lo;0;L;;;;;N;;;;;
+1B20D;NUSHU CHARACTER-1B20D;Lo;0;L;;;;;N;;;;;
+1B20E;NUSHU CHARACTER-1B20E;Lo;0;L;;;;;N;;;;;
+1B20F;NUSHU CHARACTER-1B20F;Lo;0;L;;;;;N;;;;;
+1B210;NUSHU CHARACTER-1B210;Lo;0;L;;;;;N;;;;;
+1B211;NUSHU CHARACTER-1B211;Lo;0;L;;;;;N;;;;;
+1B212;NUSHU CHARACTER-1B212;Lo;0;L;;;;;N;;;;;
+1B213;NUSHU CHARACTER-1B213;Lo;0;L;;;;;N;;;;;
+1B214;NUSHU CHARACTER-1B214;Lo;0;L;;;;;N;;;;;
+1B215;NUSHU CHARACTER-1B215;Lo;0;L;;;;;N;;;;;
+1B216;NUSHU CHARACTER-1B216;Lo;0;L;;;;;N;;;;;
+1B217;NUSHU CHARACTER-1B217;Lo;0;L;;;;;N;;;;;
+1B218;NUSHU CHARACTER-1B218;Lo;0;L;;;;;N;;;;;
+1B219;NUSHU CHARACTER-1B219;Lo;0;L;;;;;N;;;;;
+1B21A;NUSHU CHARACTER-1B21A;Lo;0;L;;;;;N;;;;;
+1B21B;NUSHU CHARACTER-1B21B;Lo;0;L;;;;;N;;;;;
+1B21C;NUSHU CHARACTER-1B21C;Lo;0;L;;;;;N;;;;;
+1B21D;NUSHU CHARACTER-1B21D;Lo;0;L;;;;;N;;;;;
+1B21E;NUSHU CHARACTER-1B21E;Lo;0;L;;;;;N;;;;;
+1B21F;NUSHU CHARACTER-1B21F;Lo;0;L;;;;;N;;;;;
+1B220;NUSHU CHARACTER-1B220;Lo;0;L;;;;;N;;;;;
+1B221;NUSHU CHARACTER-1B221;Lo;0;L;;;;;N;;;;;
+1B222;NUSHU CHARACTER-1B222;Lo;0;L;;;;;N;;;;;
+1B223;NUSHU CHARACTER-1B223;Lo;0;L;;;;;N;;;;;
+1B224;NUSHU CHARACTER-1B224;Lo;0;L;;;;;N;;;;;
+1B225;NUSHU CHARACTER-1B225;Lo;0;L;;;;;N;;;;;
+1B226;NUSHU CHARACTER-1B226;Lo;0;L;;;;;N;;;;;
+1B227;NUSHU CHARACTER-1B227;Lo;0;L;;;;;N;;;;;
+1B228;NUSHU CHARACTER-1B228;Lo;0;L;;;;;N;;;;;
+1B229;NUSHU CHARACTER-1B229;Lo;0;L;;;;;N;;;;;
+1B22A;NUSHU CHARACTER-1B22A;Lo;0;L;;;;;N;;;;;
+1B22B;NUSHU CHARACTER-1B22B;Lo;0;L;;;;;N;;;;;
+1B22C;NUSHU CHARACTER-1B22C;Lo;0;L;;;;;N;;;;;
+1B22D;NUSHU CHARACTER-1B22D;Lo;0;L;;;;;N;;;;;
+1B22E;NUSHU CHARACTER-1B22E;Lo;0;L;;;;;N;;;;;
+1B22F;NUSHU CHARACTER-1B22F;Lo;0;L;;;;;N;;;;;
+1B230;NUSHU CHARACTER-1B230;Lo;0;L;;;;;N;;;;;
+1B231;NUSHU CHARACTER-1B231;Lo;0;L;;;;;N;;;;;
+1B232;NUSHU CHARACTER-1B232;Lo;0;L;;;;;N;;;;;
+1B233;NUSHU CHARACTER-1B233;Lo;0;L;;;;;N;;;;;
+1B234;NUSHU CHARACTER-1B234;Lo;0;L;;;;;N;;;;;
+1B235;NUSHU CHARACTER-1B235;Lo;0;L;;;;;N;;;;;
+1B236;NUSHU CHARACTER-1B236;Lo;0;L;;;;;N;;;;;
+1B237;NUSHU CHARACTER-1B237;Lo;0;L;;;;;N;;;;;
+1B238;NUSHU CHARACTER-1B238;Lo;0;L;;;;;N;;;;;
+1B239;NUSHU CHARACTER-1B239;Lo;0;L;;;;;N;;;;;
+1B23A;NUSHU CHARACTER-1B23A;Lo;0;L;;;;;N;;;;;
+1B23B;NUSHU CHARACTER-1B23B;Lo;0;L;;;;;N;;;;;
+1B23C;NUSHU CHARACTER-1B23C;Lo;0;L;;;;;N;;;;;
+1B23D;NUSHU CHARACTER-1B23D;Lo;0;L;;;;;N;;;;;
+1B23E;NUSHU CHARACTER-1B23E;Lo;0;L;;;;;N;;;;;
+1B23F;NUSHU CHARACTER-1B23F;Lo;0;L;;;;;N;;;;;
+1B240;NUSHU CHARACTER-1B240;Lo;0;L;;;;;N;;;;;
+1B241;NUSHU CHARACTER-1B241;Lo;0;L;;;;;N;;;;;
+1B242;NUSHU CHARACTER-1B242;Lo;0;L;;;;;N;;;;;
+1B243;NUSHU CHARACTER-1B243;Lo;0;L;;;;;N;;;;;
+1B244;NUSHU CHARACTER-1B244;Lo;0;L;;;;;N;;;;;
+1B245;NUSHU CHARACTER-1B245;Lo;0;L;;;;;N;;;;;
+1B246;NUSHU CHARACTER-1B246;Lo;0;L;;;;;N;;;;;
+1B247;NUSHU CHARACTER-1B247;Lo;0;L;;;;;N;;;;;
+1B248;NUSHU CHARACTER-1B248;Lo;0;L;;;;;N;;;;;
+1B249;NUSHU CHARACTER-1B249;Lo;0;L;;;;;N;;;;;
+1B24A;NUSHU CHARACTER-1B24A;Lo;0;L;;;;;N;;;;;
+1B24B;NUSHU CHARACTER-1B24B;Lo;0;L;;;;;N;;;;;
+1B24C;NUSHU CHARACTER-1B24C;Lo;0;L;;;;;N;;;;;
+1B24D;NUSHU CHARACTER-1B24D;Lo;0;L;;;;;N;;;;;
+1B24E;NUSHU CHARACTER-1B24E;Lo;0;L;;;;;N;;;;;
+1B24F;NUSHU CHARACTER-1B24F;Lo;0;L;;;;;N;;;;;
+1B250;NUSHU CHARACTER-1B250;Lo;0;L;;;;;N;;;;;
+1B251;NUSHU CHARACTER-1B251;Lo;0;L;;;;;N;;;;;
+1B252;NUSHU CHARACTER-1B252;Lo;0;L;;;;;N;;;;;
+1B253;NUSHU CHARACTER-1B253;Lo;0;L;;;;;N;;;;;
+1B254;NUSHU CHARACTER-1B254;Lo;0;L;;;;;N;;;;;
+1B255;NUSHU CHARACTER-1B255;Lo;0;L;;;;;N;;;;;
+1B256;NUSHU CHARACTER-1B256;Lo;0;L;;;;;N;;;;;
+1B257;NUSHU CHARACTER-1B257;Lo;0;L;;;;;N;;;;;
+1B258;NUSHU CHARACTER-1B258;Lo;0;L;;;;;N;;;;;
+1B259;NUSHU CHARACTER-1B259;Lo;0;L;;;;;N;;;;;
+1B25A;NUSHU CHARACTER-1B25A;Lo;0;L;;;;;N;;;;;
+1B25B;NUSHU CHARACTER-1B25B;Lo;0;L;;;;;N;;;;;
+1B25C;NUSHU CHARACTER-1B25C;Lo;0;L;;;;;N;;;;;
+1B25D;NUSHU CHARACTER-1B25D;Lo;0;L;;;;;N;;;;;
+1B25E;NUSHU CHARACTER-1B25E;Lo;0;L;;;;;N;;;;;
+1B25F;NUSHU CHARACTER-1B25F;Lo;0;L;;;;;N;;;;;
+1B260;NUSHU CHARACTER-1B260;Lo;0;L;;;;;N;;;;;
+1B261;NUSHU CHARACTER-1B261;Lo;0;L;;;;;N;;;;;
+1B262;NUSHU CHARACTER-1B262;Lo;0;L;;;;;N;;;;;
+1B263;NUSHU CHARACTER-1B263;Lo;0;L;;;;;N;;;;;
+1B264;NUSHU CHARACTER-1B264;Lo;0;L;;;;;N;;;;;
+1B265;NUSHU CHARACTER-1B265;Lo;0;L;;;;;N;;;;;
+1B266;NUSHU CHARACTER-1B266;Lo;0;L;;;;;N;;;;;
+1B267;NUSHU CHARACTER-1B267;Lo;0;L;;;;;N;;;;;
+1B268;NUSHU CHARACTER-1B268;Lo;0;L;;;;;N;;;;;
+1B269;NUSHU CHARACTER-1B269;Lo;0;L;;;;;N;;;;;
+1B26A;NUSHU CHARACTER-1B26A;Lo;0;L;;;;;N;;;;;
+1B26B;NUSHU CHARACTER-1B26B;Lo;0;L;;;;;N;;;;;
+1B26C;NUSHU CHARACTER-1B26C;Lo;0;L;;;;;N;;;;;
+1B26D;NUSHU CHARACTER-1B26D;Lo;0;L;;;;;N;;;;;
+1B26E;NUSHU CHARACTER-1B26E;Lo;0;L;;;;;N;;;;;
+1B26F;NUSHU CHARACTER-1B26F;Lo;0;L;;;;;N;;;;;
+1B270;NUSHU CHARACTER-1B270;Lo;0;L;;;;;N;;;;;
+1B271;NUSHU CHARACTER-1B271;Lo;0;L;;;;;N;;;;;
+1B272;NUSHU CHARACTER-1B272;Lo;0;L;;;;;N;;;;;
+1B273;NUSHU CHARACTER-1B273;Lo;0;L;;;;;N;;;;;
+1B274;NUSHU CHARACTER-1B274;Lo;0;L;;;;;N;;;;;
+1B275;NUSHU CHARACTER-1B275;Lo;0;L;;;;;N;;;;;
+1B276;NUSHU CHARACTER-1B276;Lo;0;L;;;;;N;;;;;
+1B277;NUSHU CHARACTER-1B277;Lo;0;L;;;;;N;;;;;
+1B278;NUSHU CHARACTER-1B278;Lo;0;L;;;;;N;;;;;
+1B279;NUSHU CHARACTER-1B279;Lo;0;L;;;;;N;;;;;
+1B27A;NUSHU CHARACTER-1B27A;Lo;0;L;;;;;N;;;;;
+1B27B;NUSHU CHARACTER-1B27B;Lo;0;L;;;;;N;;;;;
+1B27C;NUSHU CHARACTER-1B27C;Lo;0;L;;;;;N;;;;;
+1B27D;NUSHU CHARACTER-1B27D;Lo;0;L;;;;;N;;;;;
+1B27E;NUSHU CHARACTER-1B27E;Lo;0;L;;;;;N;;;;;
+1B27F;NUSHU CHARACTER-1B27F;Lo;0;L;;;;;N;;;;;
+1B280;NUSHU CHARACTER-1B280;Lo;0;L;;;;;N;;;;;
+1B281;NUSHU CHARACTER-1B281;Lo;0;L;;;;;N;;;;;
+1B282;NUSHU CHARACTER-1B282;Lo;0;L;;;;;N;;;;;
+1B283;NUSHU CHARACTER-1B283;Lo;0;L;;;;;N;;;;;
+1B284;NUSHU CHARACTER-1B284;Lo;0;L;;;;;N;;;;;
+1B285;NUSHU CHARACTER-1B285;Lo;0;L;;;;;N;;;;;
+1B286;NUSHU CHARACTER-1B286;Lo;0;L;;;;;N;;;;;
+1B287;NUSHU CHARACTER-1B287;Lo;0;L;;;;;N;;;;;
+1B288;NUSHU CHARACTER-1B288;Lo;0;L;;;;;N;;;;;
+1B289;NUSHU CHARACTER-1B289;Lo;0;L;;;;;N;;;;;
+1B28A;NUSHU CHARACTER-1B28A;Lo;0;L;;;;;N;;;;;
+1B28B;NUSHU CHARACTER-1B28B;Lo;0;L;;;;;N;;;;;
+1B28C;NUSHU CHARACTER-1B28C;Lo;0;L;;;;;N;;;;;
+1B28D;NUSHU CHARACTER-1B28D;Lo;0;L;;;;;N;;;;;
+1B28E;NUSHU CHARACTER-1B28E;Lo;0;L;;;;;N;;;;;
+1B28F;NUSHU CHARACTER-1B28F;Lo;0;L;;;;;N;;;;;
+1B290;NUSHU CHARACTER-1B290;Lo;0;L;;;;;N;;;;;
+1B291;NUSHU CHARACTER-1B291;Lo;0;L;;;;;N;;;;;
+1B292;NUSHU CHARACTER-1B292;Lo;0;L;;;;;N;;;;;
+1B293;NUSHU CHARACTER-1B293;Lo;0;L;;;;;N;;;;;
+1B294;NUSHU CHARACTER-1B294;Lo;0;L;;;;;N;;;;;
+1B295;NUSHU CHARACTER-1B295;Lo;0;L;;;;;N;;;;;
+1B296;NUSHU CHARACTER-1B296;Lo;0;L;;;;;N;;;;;
+1B297;NUSHU CHARACTER-1B297;Lo;0;L;;;;;N;;;;;
+1B298;NUSHU CHARACTER-1B298;Lo;0;L;;;;;N;;;;;
+1B299;NUSHU CHARACTER-1B299;Lo;0;L;;;;;N;;;;;
+1B29A;NUSHU CHARACTER-1B29A;Lo;0;L;;;;;N;;;;;
+1B29B;NUSHU CHARACTER-1B29B;Lo;0;L;;;;;N;;;;;
+1B29C;NUSHU CHARACTER-1B29C;Lo;0;L;;;;;N;;;;;
+1B29D;NUSHU CHARACTER-1B29D;Lo;0;L;;;;;N;;;;;
+1B29E;NUSHU CHARACTER-1B29E;Lo;0;L;;;;;N;;;;;
+1B29F;NUSHU CHARACTER-1B29F;Lo;0;L;;;;;N;;;;;
+1B2A0;NUSHU CHARACTER-1B2A0;Lo;0;L;;;;;N;;;;;
+1B2A1;NUSHU CHARACTER-1B2A1;Lo;0;L;;;;;N;;;;;
+1B2A2;NUSHU CHARACTER-1B2A2;Lo;0;L;;;;;N;;;;;
+1B2A3;NUSHU CHARACTER-1B2A3;Lo;0;L;;;;;N;;;;;
+1B2A4;NUSHU CHARACTER-1B2A4;Lo;0;L;;;;;N;;;;;
+1B2A5;NUSHU CHARACTER-1B2A5;Lo;0;L;;;;;N;;;;;
+1B2A6;NUSHU CHARACTER-1B2A6;Lo;0;L;;;;;N;;;;;
+1B2A7;NUSHU CHARACTER-1B2A7;Lo;0;L;;;;;N;;;;;
+1B2A8;NUSHU CHARACTER-1B2A8;Lo;0;L;;;;;N;;;;;
+1B2A9;NUSHU CHARACTER-1B2A9;Lo;0;L;;;;;N;;;;;
+1B2AA;NUSHU CHARACTER-1B2AA;Lo;0;L;;;;;N;;;;;
+1B2AB;NUSHU CHARACTER-1B2AB;Lo;0;L;;;;;N;;;;;
+1B2AC;NUSHU CHARACTER-1B2AC;Lo;0;L;;;;;N;;;;;
+1B2AD;NUSHU CHARACTER-1B2AD;Lo;0;L;;;;;N;;;;;
+1B2AE;NUSHU CHARACTER-1B2AE;Lo;0;L;;;;;N;;;;;
+1B2AF;NUSHU CHARACTER-1B2AF;Lo;0;L;;;;;N;;;;;
+1B2B0;NUSHU CHARACTER-1B2B0;Lo;0;L;;;;;N;;;;;
+1B2B1;NUSHU CHARACTER-1B2B1;Lo;0;L;;;;;N;;;;;
+1B2B2;NUSHU CHARACTER-1B2B2;Lo;0;L;;;;;N;;;;;
+1B2B3;NUSHU CHARACTER-1B2B3;Lo;0;L;;;;;N;;;;;
+1B2B4;NUSHU CHARACTER-1B2B4;Lo;0;L;;;;;N;;;;;
+1B2B5;NUSHU CHARACTER-1B2B5;Lo;0;L;;;;;N;;;;;
+1B2B6;NUSHU CHARACTER-1B2B6;Lo;0;L;;;;;N;;;;;
+1B2B7;NUSHU CHARACTER-1B2B7;Lo;0;L;;;;;N;;;;;
+1B2B8;NUSHU CHARACTER-1B2B8;Lo;0;L;;;;;N;;;;;
+1B2B9;NUSHU CHARACTER-1B2B9;Lo;0;L;;;;;N;;;;;
+1B2BA;NUSHU CHARACTER-1B2BA;Lo;0;L;;;;;N;;;;;
+1B2BB;NUSHU CHARACTER-1B2BB;Lo;0;L;;;;;N;;;;;
+1B2BC;NUSHU CHARACTER-1B2BC;Lo;0;L;;;;;N;;;;;
+1B2BD;NUSHU CHARACTER-1B2BD;Lo;0;L;;;;;N;;;;;
+1B2BE;NUSHU CHARACTER-1B2BE;Lo;0;L;;;;;N;;;;;
+1B2BF;NUSHU CHARACTER-1B2BF;Lo;0;L;;;;;N;;;;;
+1B2C0;NUSHU CHARACTER-1B2C0;Lo;0;L;;;;;N;;;;;
+1B2C1;NUSHU CHARACTER-1B2C1;Lo;0;L;;;;;N;;;;;
+1B2C2;NUSHU CHARACTER-1B2C2;Lo;0;L;;;;;N;;;;;
+1B2C3;NUSHU CHARACTER-1B2C3;Lo;0;L;;;;;N;;;;;
+1B2C4;NUSHU CHARACTER-1B2C4;Lo;0;L;;;;;N;;;;;
+1B2C5;NUSHU CHARACTER-1B2C5;Lo;0;L;;;;;N;;;;;
+1B2C6;NUSHU CHARACTER-1B2C6;Lo;0;L;;;;;N;;;;;
+1B2C7;NUSHU CHARACTER-1B2C7;Lo;0;L;;;;;N;;;;;
+1B2C8;NUSHU CHARACTER-1B2C8;Lo;0;L;;;;;N;;;;;
+1B2C9;NUSHU CHARACTER-1B2C9;Lo;0;L;;;;;N;;;;;
+1B2CA;NUSHU CHARACTER-1B2CA;Lo;0;L;;;;;N;;;;;
+1B2CB;NUSHU CHARACTER-1B2CB;Lo;0;L;;;;;N;;;;;
+1B2CC;NUSHU CHARACTER-1B2CC;Lo;0;L;;;;;N;;;;;
+1B2CD;NUSHU CHARACTER-1B2CD;Lo;0;L;;;;;N;;;;;
+1B2CE;NUSHU CHARACTER-1B2CE;Lo;0;L;;;;;N;;;;;
+1B2CF;NUSHU CHARACTER-1B2CF;Lo;0;L;;;;;N;;;;;
+1B2D0;NUSHU CHARACTER-1B2D0;Lo;0;L;;;;;N;;;;;
+1B2D1;NUSHU CHARACTER-1B2D1;Lo;0;L;;;;;N;;;;;
+1B2D2;NUSHU CHARACTER-1B2D2;Lo;0;L;;;;;N;;;;;
+1B2D3;NUSHU CHARACTER-1B2D3;Lo;0;L;;;;;N;;;;;
+1B2D4;NUSHU CHARACTER-1B2D4;Lo;0;L;;;;;N;;;;;
+1B2D5;NUSHU CHARACTER-1B2D5;Lo;0;L;;;;;N;;;;;
+1B2D6;NUSHU CHARACTER-1B2D6;Lo;0;L;;;;;N;;;;;
+1B2D7;NUSHU CHARACTER-1B2D7;Lo;0;L;;;;;N;;;;;
+1B2D8;NUSHU CHARACTER-1B2D8;Lo;0;L;;;;;N;;;;;
+1B2D9;NUSHU CHARACTER-1B2D9;Lo;0;L;;;;;N;;;;;
+1B2DA;NUSHU CHARACTER-1B2DA;Lo;0;L;;;;;N;;;;;
+1B2DB;NUSHU CHARACTER-1B2DB;Lo;0;L;;;;;N;;;;;
+1B2DC;NUSHU CHARACTER-1B2DC;Lo;0;L;;;;;N;;;;;
+1B2DD;NUSHU CHARACTER-1B2DD;Lo;0;L;;;;;N;;;;;
+1B2DE;NUSHU CHARACTER-1B2DE;Lo;0;L;;;;;N;;;;;
+1B2DF;NUSHU CHARACTER-1B2DF;Lo;0;L;;;;;N;;;;;
+1B2E0;NUSHU CHARACTER-1B2E0;Lo;0;L;;;;;N;;;;;
+1B2E1;NUSHU CHARACTER-1B2E1;Lo;0;L;;;;;N;;;;;
+1B2E2;NUSHU CHARACTER-1B2E2;Lo;0;L;;;;;N;;;;;
+1B2E3;NUSHU CHARACTER-1B2E3;Lo;0;L;;;;;N;;;;;
+1B2E4;NUSHU CHARACTER-1B2E4;Lo;0;L;;;;;N;;;;;
+1B2E5;NUSHU CHARACTER-1B2E5;Lo;0;L;;;;;N;;;;;
+1B2E6;NUSHU CHARACTER-1B2E6;Lo;0;L;;;;;N;;;;;
+1B2E7;NUSHU CHARACTER-1B2E7;Lo;0;L;;;;;N;;;;;
+1B2E8;NUSHU CHARACTER-1B2E8;Lo;0;L;;;;;N;;;;;
+1B2E9;NUSHU CHARACTER-1B2E9;Lo;0;L;;;;;N;;;;;
+1B2EA;NUSHU CHARACTER-1B2EA;Lo;0;L;;;;;N;;;;;
+1B2EB;NUSHU CHARACTER-1B2EB;Lo;0;L;;;;;N;;;;;
+1B2EC;NUSHU CHARACTER-1B2EC;Lo;0;L;;;;;N;;;;;
+1B2ED;NUSHU CHARACTER-1B2ED;Lo;0;L;;;;;N;;;;;
+1B2EE;NUSHU CHARACTER-1B2EE;Lo;0;L;;;;;N;;;;;
+1B2EF;NUSHU CHARACTER-1B2EF;Lo;0;L;;;;;N;;;;;
+1B2F0;NUSHU CHARACTER-1B2F0;Lo;0;L;;;;;N;;;;;
+1B2F1;NUSHU CHARACTER-1B2F1;Lo;0;L;;;;;N;;;;;
+1B2F2;NUSHU CHARACTER-1B2F2;Lo;0;L;;;;;N;;;;;
+1B2F3;NUSHU CHARACTER-1B2F3;Lo;0;L;;;;;N;;;;;
+1B2F4;NUSHU CHARACTER-1B2F4;Lo;0;L;;;;;N;;;;;
+1B2F5;NUSHU CHARACTER-1B2F5;Lo;0;L;;;;;N;;;;;
+1B2F6;NUSHU CHARACTER-1B2F6;Lo;0;L;;;;;N;;;;;
+1B2F7;NUSHU CHARACTER-1B2F7;Lo;0;L;;;;;N;;;;;
+1B2F8;NUSHU CHARACTER-1B2F8;Lo;0;L;;;;;N;;;;;
+1B2F9;NUSHU CHARACTER-1B2F9;Lo;0;L;;;;;N;;;;;
+1B2FA;NUSHU CHARACTER-1B2FA;Lo;0;L;;;;;N;;;;;
+1B2FB;NUSHU CHARACTER-1B2FB;Lo;0;L;;;;;N;;;;;
1BC00;DUPLOYAN LETTER H;Lo;0;L;;;;;N;;;;;
1BC01;DUPLOYAN LETTER X;Lo;0;L;;;;;N;;;;;
1BC02;DUPLOYAN LETTER P;Lo;0;L;;;;;N;;;;;
@@ -28269,6 +29217,12 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1F248;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557;So;0;L;<compat> 3014 6557 3015;;;;N;;;;;
1F250;CIRCLED IDEOGRAPH ADVANTAGE;So;0;L;<circle> 5F97;;;;N;;;;;
1F251;CIRCLED IDEOGRAPH ACCEPT;So;0;L;<circle> 53EF;;;;N;;;;;
+1F260;ROUNDED SYMBOL FOR FU;So;0;ON;;;;;N;;;;;
+1F261;ROUNDED SYMBOL FOR LU;So;0;ON;;;;;N;;;;;
+1F262;ROUNDED SYMBOL FOR SHOU;So;0;ON;;;;;N;;;;;
+1F263;ROUNDED SYMBOL FOR XI;So;0;ON;;;;;N;;;;;
+1F264;ROUNDED SYMBOL FOR SHUANGXI;So;0;ON;;;;;N;;;;;
+1F265;ROUNDED SYMBOL FOR CAI;So;0;ON;;;;;N;;;;;
1F300;CYCLONE;So;0;ON;;;;;N;;;;;
1F301;FOGGY;So;0;ON;;;;;N;;;;;
1F302;CLOSED UMBRELLA;So;0;ON;;;;;N;;;;;
@@ -29248,6 +30202,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1F6D0;PLACE OF WORSHIP;So;0;ON;;;;;N;;;;;
1F6D1;OCTAGONAL SIGN;So;0;ON;;;;;N;;;;;
1F6D2;SHOPPING TROLLEY;So;0;ON;;;;;N;;;;;
+1F6D3;STUPA;So;0;ON;;;;;N;;;;;
+1F6D4;PAGODA;So;0;ON;;;;;N;;;;;
1F6E0;HAMMER AND WRENCH;So;0;ON;;;;;N;;;;;
1F6E1;SHIELD;So;0;ON;;;;;N;;;;;
1F6E2;OIL DRUM;So;0;ON;;;;;N;;;;;
@@ -29268,6 +30224,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1F6F4;SCOOTER;So;0;ON;;;;;N;;;;;
1F6F5;MOTOR SCOOTER;So;0;ON;;;;;N;;;;;
1F6F6;CANOE;So;0;ON;;;;;N;;;;;
+1F6F7;SLED;So;0;ON;;;;;N;;;;;
+1F6F8;FLYING SAUCER;So;0;ON;;;;;N;;;;;
1F700;ALCHEMICAL SYMBOL FOR QUINTESSENCE;So;0;ON;;;;;N;;;;;
1F701;ALCHEMICAL SYMBOL FOR AIR;So;0;ON;;;;;N;;;;;
1F702;ALCHEMICAL SYMBOL FOR FIRE;So;0;ON;;;;;N;;;;;
@@ -29617,6 +30575,18 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1F8AB;RIGHTWARDS FRONT-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;;
1F8AC;WHITE ARROW SHAFT WIDTH ONE;So;0;ON;;;;;N;;;;;
1F8AD;WHITE ARROW SHAFT WIDTH TWO THIRDS;So;0;ON;;;;;N;;;;;
+1F900;CIRCLED CROSS FORMEE WITH FOUR DOTS;So;0;ON;;;;;N;;;;;
+1F901;CIRCLED CROSS FORMEE WITH TWO DOTS;So;0;ON;;;;;N;;;;;
+1F902;CIRCLED CROSS FORMEE;So;0;ON;;;;;N;;;;;
+1F903;LEFT HALF CIRCLE WITH FOUR DOTS;So;0;ON;;;;;N;;;;;
+1F904;LEFT HALF CIRCLE WITH THREE DOTS;So;0;ON;;;;;N;;;;;
+1F905;LEFT HALF CIRCLE WITH TWO DOTS;So;0;ON;;;;;N;;;;;
+1F906;LEFT HALF CIRCLE WITH DOT;So;0;ON;;;;;N;;;;;
+1F907;LEFT HALF CIRCLE;So;0;ON;;;;;N;;;;;
+1F908;DOWNWARD FACING HOOK;So;0;ON;;;;;N;;;;;
+1F909;DOWNWARD FACING NOTCHED HOOK;So;0;ON;;;;;N;;;;;
+1F90A;DOWNWARD FACING HOOK WITH DOT;So;0;ON;;;;;N;;;;;
+1F90B;DOWNWARD FACING NOTCHED HOOK WITH DOT;So;0;ON;;;;;N;;;;;
1F910;ZIPPER-MOUTH FACE;So;0;ON;;;;;N;;;;;
1F911;MONEY-MOUTH FACE;So;0;ON;;;;;N;;;;;
1F912;FACE WITH THERMOMETER;So;0;ON;;;;;N;;;;;
@@ -29632,6 +30602,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1F91C;RIGHT-FACING FIST;So;0;ON;;;;;N;;;;;
1F91D;HANDSHAKE;So;0;ON;;;;;N;;;;;
1F91E;HAND WITH INDEX AND MIDDLE FINGERS CROSSED;So;0;ON;;;;;N;;;;;
+1F91F;I LOVE YOU HAND SIGN;So;0;ON;;;;;N;;;;;
1F920;FACE WITH COWBOY HAT;So;0;ON;;;;;N;;;;;
1F921;CLOWN FACE;So;0;ON;;;;;N;;;;;
1F922;NAUSEATED FACE;So;0;ON;;;;;N;;;;;
@@ -29640,7 +30611,17 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1F925;LYING FACE;So;0;ON;;;;;N;;;;;
1F926;FACE PALM;So;0;ON;;;;;N;;;;;
1F927;SNEEZING FACE;So;0;ON;;;;;N;;;;;
+1F928;FACE WITH ONE EYEBROW RAISED;So;0;ON;;;;;N;;;;;
+1F929;GRINNING FACE WITH STAR EYES;So;0;ON;;;;;N;;;;;
+1F92A;GRINNING FACE WITH ONE LARGE AND ONE SMALL EYE;So;0;ON;;;;;N;;;;;
+1F92B;FACE WITH FINGER COVERING CLOSED LIPS;So;0;ON;;;;;N;;;;;
+1F92C;SERIOUS FACE WITH SYMBOLS COVERING MOUTH;So;0;ON;;;;;N;;;;;
+1F92D;SMILING FACE WITH SMILING EYES AND HAND COVERING MOUTH;So;0;ON;;;;;N;;;;;
+1F92E;FACE WITH OPEN MOUTH VOMITING;So;0;ON;;;;;N;;;;;
+1F92F;SHOCKED FACE WITH EXPLODING HEAD;So;0;ON;;;;;N;;;;;
1F930;PREGNANT WOMAN;So;0;ON;;;;;N;;;;;
+1F931;BREAST-FEEDING;So;0;ON;;;;;N;;;;;
+1F932;PALMS UP TOGETHER;So;0;ON;;;;;N;;;;;
1F933;SELFIE;So;0;ON;;;;;N;;;;;
1F934;PRINCE;So;0;ON;;;;;N;;;;;
1F935;MAN IN TUXEDO;So;0;ON;;;;;N;;;;;
@@ -29665,6 +30646,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1F949;THIRD PLACE MEDAL;So;0;ON;;;;;N;;;;;
1F94A;BOXING GLOVE;So;0;ON;;;;;N;;;;;
1F94B;MARTIAL ARTS UNIFORM;So;0;ON;;;;;N;;;;;
+1F94C;CURLING STONE;So;0;ON;;;;;N;;;;;
1F950;CROISSANT;So;0;ON;;;;;N;;;;;
1F951;AVOCADO;So;0;ON;;;;;N;;;;;
1F952;CUCUMBER;So;0;ON;;;;;N;;;;;
@@ -29680,6 +30662,19 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1F95C;PEANUTS;So;0;ON;;;;;N;;;;;
1F95D;KIWIFRUIT;So;0;ON;;;;;N;;;;;
1F95E;PANCAKES;So;0;ON;;;;;N;;;;;
+1F95F;DUMPLING;So;0;ON;;;;;N;;;;;
+1F960;FORTUNE COOKIE;So;0;ON;;;;;N;;;;;
+1F961;TAKEOUT BOX;So;0;ON;;;;;N;;;;;
+1F962;CHOPSTICKS;So;0;ON;;;;;N;;;;;
+1F963;BOWL WITH SPOON;So;0;ON;;;;;N;;;;;
+1F964;CUP WITH STRAW;So;0;ON;;;;;N;;;;;
+1F965;COCONUT;So;0;ON;;;;;N;;;;;
+1F966;BROCCOLI;So;0;ON;;;;;N;;;;;
+1F967;PIE;So;0;ON;;;;;N;;;;;
+1F968;PRETZEL;So;0;ON;;;;;N;;;;;
+1F969;CUT OF MEAT;So;0;ON;;;;;N;;;;;
+1F96A;SANDWICH;So;0;ON;;;;;N;;;;;
+1F96B;CANNED FOOD;So;0;ON;;;;;N;;;;;
1F980;CRAB;So;0;ON;;;;;N;;;;;
1F981;LION FACE;So;0;ON;;;;;N;;;;;
1F982;SCORPION;So;0;ON;;;;;N;;;;;
@@ -29698,7 +30693,36 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1F98F;RHINOCEROS;So;0;ON;;;;;N;;;;;
1F990;SHRIMP;So;0;ON;;;;;N;;;;;
1F991;SQUID;So;0;ON;;;;;N;;;;;
+1F992;GIRAFFE FACE;So;0;ON;;;;;N;;;;;
+1F993;ZEBRA FACE;So;0;ON;;;;;N;;;;;
+1F994;HEDGEHOG;So;0;ON;;;;;N;;;;;
+1F995;SAUROPOD;So;0;ON;;;;;N;;;;;
+1F996;T-REX;So;0;ON;;;;;N;;;;;
+1F997;CRICKET;So;0;ON;;;;;N;;;;;
1F9C0;CHEESE WEDGE;So;0;ON;;;;;N;;;;;
+1F9D0;FACE WITH MONOCLE;So;0;ON;;;;;N;;;;;
+1F9D1;ADULT;So;0;ON;;;;;N;;;;;
+1F9D2;CHILD;So;0;ON;;;;;N;;;;;
+1F9D3;OLDER ADULT;So;0;ON;;;;;N;;;;;
+1F9D4;BEARDED PERSON;So;0;ON;;;;;N;;;;;
+1F9D5;PERSON WITH HEADSCARF;So;0;ON;;;;;N;;;;;
+1F9D6;PERSON IN STEAMY ROOM;So;0;ON;;;;;N;;;;;
+1F9D7;PERSON CLIMBING;So;0;ON;;;;;N;;;;;
+1F9D8;PERSON IN LOTUS POSITION;So;0;ON;;;;;N;;;;;
+1F9D9;MAGE;So;0;ON;;;;;N;;;;;
+1F9DA;FAIRY;So;0;ON;;;;;N;;;;;
+1F9DB;VAMPIRE;So;0;ON;;;;;N;;;;;
+1F9DC;MERPERSON;So;0;ON;;;;;N;;;;;
+1F9DD;ELF;So;0;ON;;;;;N;;;;;
+1F9DE;GENIE;So;0;ON;;;;;N;;;;;
+1F9DF;ZOMBIE;So;0;ON;;;;;N;;;;;
+1F9E0;BRAIN;So;0;ON;;;;;N;;;;;
+1F9E1;ORANGE HEART;So;0;ON;;;;;N;;;;;
+1F9E2;BILLED CAP;So;0;ON;;;;;N;;;;;
+1F9E3;SCARF;So;0;ON;;;;;N;;;;;
+1F9E4;GLOVES;So;0;ON;;;;;N;;;;;
+1F9E5;COAT;So;0;ON;;;;;N;;;;;
+1F9E6;SOCKS;So;0;ON;;;;;N;;;;;
20000;<CJK Ideograph Extension B, First>;Lo;0;L;;;;;N;;;;;
2A6D6;<CJK Ideograph Extension B, Last>;Lo;0;L;;;;;N;;;;;
2A700;<CJK Ideograph Extension C, First>;Lo;0;L;;;;;N;;;;;
@@ -29707,6 +30731,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
2B81D;<CJK Ideograph Extension D, Last>;Lo;0;L;;;;;N;;;;;
2B820;<CJK Ideograph Extension E, First>;Lo;0;L;;;;;N;;;;;
2CEA1;<CJK Ideograph Extension E, Last>;Lo;0;L;;;;;N;;;;;
+2CEB0;<CJK Ideograph Extension F, First>;Lo;0;L;;;;;N;;;;;
+2EBE0;<CJK Ideograph Extension F, Last>;Lo;0;L;;;;;N;;;;;
2F800;CJK COMPATIBILITY IDEOGRAPH-2F800;Lo;0;L;4E3D;;;;N;;;;;
2F801;CJK COMPATIBILITY IDEOGRAPH-2F801;Lo;0;L;4E38;;;;N;;;;;
2F802;CJK COMPATIBILITY IDEOGRAPH-2F802;Lo;0;L;4E41;;;;N;;;;;
diff --git a/lib/stdlib/uc_spec/gen_unicode_mod.escript b/lib/stdlib/uc_spec/gen_unicode_mod.escript
index fefd7d3b70..fe5a860d45 100755
--- a/lib/stdlib/uc_spec/gen_unicode_mod.escript
+++ b/lib/stdlib/uc_spec/gen_unicode_mod.escript
@@ -65,7 +65,7 @@ main(_) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
parse_unicode_data(Line0, Acc) ->
- Line = string:strip(Line0, right, $\n),
+ Line = string:chomp(Line0),
[CodePoint,Name,_Cat,Class,_BiDi,Decomp,
_N1,_N2,_N3,_BDMirror,_Uni1,_Iso|Case] = tokens(Line, ";"),
{Dec,Comp} = case to_decomp(Decomp) of
@@ -78,14 +78,14 @@ parse_unicode_data(Line0, Acc) ->
|Acc].
to_class(String) ->
- list_to_integer(string:strip(String, both)).
+ list_to_integer(string:trim(String, both)).
to_decomp("") -> [];
to_decomp("<" ++ Str) ->
- [Tag,Rest] = string:tokens(Str, ">"),
+ [Tag,Rest] = string:lexemes(Str, ">"),
{list_to_atom(Tag), to_decomp(Rest)};
to_decomp(CodePoints) ->
- CPL = string:tokens(CodePoints, " "),
+ CPL = string:lexemes(CodePoints, " "),
[hex_to_int(CP) || CP <- CPL].
to_case(["","",""]) -> [];
@@ -105,20 +105,20 @@ parse_special_casing(Line, Table) ->
array:set(CP, Entry#cp{cs=Case}, Table).
to_scase([Lower,Title,Upper|_]) ->
- {unlist([hex_to_int(CP) || CP <- string:strip(string:tokens(Upper, " "), both)]),
- unlist([hex_to_int(CP) || CP <- string:strip(string:tokens(Lower, " "), both)]),
- unlist([hex_to_int(CP) || CP <- string:strip(string:tokens(Title, " "), both)]),
+ {unlist([hex_to_int(CP) || CP <- string:lexemes(Upper, " ")]),
+ unlist([hex_to_int(CP) || CP <- string:lexemes(Lower, " ")]),
+ unlist([hex_to_int(CP) || CP <- string:lexemes(Title, " ")]),
[]}.
parse_case_folding(Line, Table) ->
[CodePoint, Class0, CaseStr |_Comments] = tokens(Line, ";"),
- Class = string:strip(Class0, both),
+ Class = string:trim(Class0, both),
if Class =:= "T" -> Table; %% Do not support localization yet
Class =:= "S" -> Table; %% Ignore simple
true ->
CP = hex_to_int(CodePoint),
Case = unlist([hex_to_int(CPC) ||
- CPC <- string:strip(string:tokens(CaseStr, " "), both)]),
+ CPC <- string:lexemes(CaseStr, " ")]),
#cp{cs={U,L,T,_}} = Entry = array:get(CP, Table),
array:set(CP, Entry#cp{cs={U,L,T,Case}}, Table)
end.
@@ -170,7 +170,7 @@ gen_header(Fd) ->
io:put_chars(Fd, "-export([spec_version/0, lookup/1, get_case/1]).\n"),
io:put_chars(Fd, "-inline([class/1]).\n"),
io:put_chars(Fd, "-compile(nowarn_unused_vars).\n"),
- io:put_chars(Fd, "-dialyzer({no_improper_lists, [cp/1, gc_prepend/2, gc_e_cont/2]}).\n"),
+ io:put_chars(Fd, "-dialyzer({no_improper_lists, [cp/1, gc/1, gc_prepend/2, gc_e_cont/2]}).\n"),
io:put_chars(Fd, "-type gc() :: char()|[char()].\n\n\n"),
ok.
@@ -186,7 +186,7 @@ gen_static(Fd) ->
" {U,L} -> #{upper=>U,lower=>L,title=>U,fold=>L};\n"
" {U,L,T,F} -> #{upper=>U,lower=>L,title=>T,fold=>F}\n"
" end.\n\n"),
- io:put_chars(Fd, "spec_version() -> {9,0}.\n\n\n"),
+ io:put_chars(Fd, "spec_version() -> {10,0}.\n\n\n"),
io:put_chars(Fd, "class(Codepoint) -> {CCC,_,_} = unicode_table(Codepoint),\n CCC.\n\n"),
io:put_chars(Fd, "-spec uppercase(unicode:chardata()) -> "
"maybe_improper_list(gc(),unicode:chardata()).\n"),
@@ -240,7 +240,7 @@ gen_norm(Fd) ->
"-spec nfd(unicode:chardata()) -> maybe_improper_list(gc(),unicode:chardata()) | {error, unicode:chardata()}.\n"
"nfd(Str0) ->\n"
" case gc(Str0) of\n"
- " [GC|R] when GC < 127 -> [GC|R];\n"
+ " [GC|R] when GC < 128 -> [GC|R];\n"
" [GC|Str] -> [decompose(GC)|Str];\n"
" [] -> [];\n"
" {error,_}=Error -> Error\n end.\n\n"
@@ -250,7 +250,7 @@ gen_norm(Fd) ->
"-spec nfkd(unicode:chardata()) -> maybe_improper_list(gc(),unicode:chardata()) | {error, unicode:chardata()}.\n"
"nfkd(Str0) ->\n"
" case gc(Str0) of\n"
- " [GC|R] when GC < 127 -> [GC|R];\n"
+ " [GC|R] when GC < 128 -> [GC|R];\n"
" [GC|Str] -> [decompose_compat(GC)|Str];\n"
" [] -> [];\n"
" {error,_}=Error -> Error\n end.\n\n"
@@ -260,7 +260,7 @@ gen_norm(Fd) ->
"-spec nfc(unicode:chardata()) -> maybe_improper_list(gc(),unicode:chardata()) | {error, unicode:chardata()}.\n"
"nfc(Str0) ->\n"
" case gc(Str0) of\n"
- " [GC|R] when GC < 255 -> [GC|R];\n"
+ " [GC|R] when GC < 256 -> [GC|R];\n"
" [GC|Str] -> [compose(decompose(GC))|Str];\n"
" [] -> [];\n"
" {error,_}=Error -> Error\n end.\n\n"
@@ -270,7 +270,7 @@ gen_norm(Fd) ->
"-spec nfkc(unicode:chardata()) -> maybe_improper_list(gc(),unicode:chardata()) | {error, unicode:chardata()}.\n"
"nfkc(Str0) ->\n"
" case gc(Str0) of\n"
- " [GC|R] when GC < 127 -> [GC|R];\n"
+ " [GC|R] when GC < 128 -> [GC|R];\n"
" [GC|Str] -> [compose_compat_0(decompose_compat(GC))|Str];\n"
" [] -> [];\n"
" {error,_}=Error -> Error\n end.\n\n"
@@ -476,13 +476,30 @@ gen_gc(Fd, GBP) ->
"-spec gc(String::unicode:chardata()) ->"
" maybe_improper_list() | {error, unicode:chardata()}.\n"),
io:put_chars(Fd,
+ "gc([CP1, CP2|_]=T)\n"
+ " when CP1 < 256, CP2 < 256, CP1 =/= $\r -> %% Ascii Fast path\n"
+ " T;\n"
+ "gc(<<CP1/utf8, Rest/binary>>) ->\n"
+ " if CP1 < 256, CP1 =/= $\r ->\n"
+ " case Rest of\n"
+ " <<CP2/utf8, _/binary>> when CP2 < 256 -> %% Ascii Fast path\n"
+ " [CP1|Rest];\n"
+ " _ -> gc_1([CP1|Rest])\n"
+ " end;\n"
+ " true -> gc_1([CP1|Rest])\n"
+ " end;\n"
"gc(Str) ->\n"
" gc_1(cp(Str)).\n\n"
"gc_1([$\\r|R0] = R) ->\n"
" case cp(R0) of % Don't break CRLF\n"
" [$\\n|R1] -> [[$\\r,$\\n]|R1];\n"
" _ -> R\n"
- " end;\n"),
+ " end;\n"
+ %% "gc_1([CP1, CP2|_]=T) when CP1 < 256, CP2 < 256 ->\n"
+ %% " T; %% Fast path\n"
+ %% "gc_1([CP1|<<CP2/utf8, _/binary>>]=T) when CP1 < 256, CP2 < 256 ->\n"
+ %% " T; %% Fast path\n"
+ ),
io:put_chars(Fd, "%% Handle control\n"),
GenControl = fun(Range) -> io:format(Fd, "gc_1~s R0;\n", [gen_clause(Range)]) end,
@@ -490,7 +507,7 @@ gen_gc(Fd, GBP) ->
[R1,R2,R3|Crs] = CRs0,
[GenControl(CP) || CP <- merge_ranges([R1,R2,R3], split), CP =/= {$\r, undefined}],
%%GenControl(R1),GenControl(R2),GenControl(R3),
- io:format(Fd, "gc_1([CP|R]) when CP < 255 -> gc_extend(R,CP);\n", []),
+ io:format(Fd, "gc_1([CP|R]) when CP < 256 -> gc_extend(R,CP);\n", []),
[GenControl(CP) || CP <- Crs],
%% One clause per CP
%% CRs0 = merge_ranges(maps:get(cr, GBP) ++ maps:get(lf, GBP) ++ maps:get(control, GBP)),
@@ -869,10 +886,10 @@ optimize_ranges_1(Rs) ->
hex_to_int([]) -> [];
hex_to_int(HexStr) ->
- list_to_integer(string:strip(HexStr, both), 16).
+ list_to_integer(string:trim(HexStr, both), 16).
to_atom(Str) ->
- list_to_atom(string:to_lower(string:strip(Str, both))).
+ list_to_atom(string:lowercase(string:trim(Str, both))).
foldl(Fun, Acc, Fd) ->
Get = fun() -> file:read_line(Fd) end,
@@ -892,7 +909,7 @@ foldl_1(Fun, Acc, Get) ->
-%% Differs from string:tokens, it returns empty string as token between two delimiters
+%% Differs from string:lexemes, it returns empty string as token between two delimiters
tokens(S, [C]) ->
tokens(lists:reverse(S), C, []).
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index f062c7fe6e..caf5ecdbb4 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1 +1 @@
-STDLIB_VSN = 3.4
+STDLIB_VSN = 3.6
diff --git a/lib/syntax_tools/doc/src/Makefile b/lib/syntax_tools/doc/src/Makefile
index e55222e59c..d953287bad 100644
--- a/lib/syntax_tools/doc/src/Makefile
+++ b/lib/syntax_tools/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2006-2016. All Rights Reserved.
+# Copyright Ericsson AB 2006-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -55,7 +55,7 @@ XML_REF3_FILES = \
merl_transform.xml \
prettypr.xml
-XML_PART_FILES = part.xml part_notes.xml
+XML_PART_FILES = part.xml
XML_CHAPTER_FILES = chapter.xml
XML_NOTES_FILES = notes.xml
@@ -63,10 +63,11 @@ BOOK_FILES = book.xml
XML_FILES=\
- $(BOOK_FILES) $(XML_CHAPTER_FILES) \
- $(XML_PART_FILES) $(XML_REF3_FILES) $(XML_APPLICATION_FILES) \
+ $(BOOK_FILES) $(XML_PART_FILES) $(XML_APPLICATION_FILES) \
$(XML_NOTES_FILES)
+XML_GEN_FILES = $(XML_REF3_FILES:%=$(XMLDIR)/%) $(XML_CHAPTER_FILES:%=$(XMLDIR)/%)
+
# ----------------------------------------------------
INFO_FILE = ../../info
@@ -86,11 +87,11 @@ SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
TOP_SPECS_FILE = specs.xml
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
+XML_FLAGS +=
SPECS_FLAGS = -I../../include
-DVIPS_FLAGS +=
+DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -108,29 +109,32 @@ html: gifs $(HTML_REF_MAN_FILE)
man: $(MAN3_FILES)
-$(XML_REF3_FILES):
- escript $(DOCGEN)/priv/bin/xml_from_edoc.escript $(SRC_DIR)/$(@:%.xml=%.erl)
+$(XML_REF3_FILES:%=$(XMLDIR)/%):
+ $(gen_verbose)escript $(DOCGEN)/priv/bin/xml_from_edoc.escript \
+ -dir $(XMLDIR) $(SRC_DIR)/$(@:$(XMLDIR)/%.xml=%.erl)
-$(XML_CHAPTER_FILES):
- escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(VSN) -chapter ../overview.edoc
+$(XML_CHAPTER_FILES:%=$(XMLDIR)/%):
+ $(gen_verbose)escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(VSN) \
+ -chapter -dir $(XMLDIR) ../overview.edoc
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
xml: $(XML_REF3_FILES) $(XML_CHAPTER_FILES)
-debug opt:
+debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(XML_REF3_FILES) $(XML_CHAPTER_FILES) *.html
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(SPECDIR)/*
- rm -f errs core *~
+ rm -f errs core *~
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
diff --git a/lib/syntax_tools/doc/src/fascicules.xml b/lib/syntax_tools/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/syntax_tools/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/syntax_tools/doc/src/notes.xml b/lib/syntax_tools/doc/src/notes.xml
index f85d963919..dc13fe474b 100644
--- a/lib/syntax_tools/doc/src/notes.xml
+++ b/lib/syntax_tools/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2007</year><year>2017</year>
+ <year>2007</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,105 @@
<p>This document describes the changes made to the Syntax_Tools
application.</p>
+<section><title>Syntax_Tools 2.1.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix the <c>TypeName</c> type in erl_syntax_lib.</p>
+ <p>
+ Own Id: OTP-15207 Aux Id: PR-1888 </p>
+ </item>
+ <item>
+ <p> Correct unfolding of the stacktrace variable. </p>
+ <p>
+ Own Id: OTP-15291 Aux Id: ERL-719 </p>
+ </item>
+ <item>
+ <p> Correct <c>erl_syntax:revert/1</c> bug regarding the
+ types <c>map()</c> and <c>tuple()</c>. </p>
+ <p>
+ Own Id: OTP-15294</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Support bitstrings as literals in module
+ <c>erl_syntax</c>. </p>
+ <p>
+ Own Id: OTP-15165 Aux Id: PR-1842 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Syntax_Tools 2.1.5</title>
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Update to use the new string api instead of the old.</p>
+ <p>
+ Own Id: OTP-15036</p>
+ </item>
+ </list>
+ </section>
+</section>
+
+<section><title>Syntax_Tools 2.1.4.1</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug regarding reverting map types. </p>
+ <p>
+ Own Id: OTP-15098 Aux Id: ERIERL-177 </p>
+ </item>
+ </list>
+ </section>
+</section>
+
+<section><title>Syntax_Tools 2.1.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Syntax_Tools 2.1.3</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ General Unicode improvements.</p>
+ <p>
+ Own Id: OTP-14462</p>
+ </item>
+ <item>
+ <p> A process trapping exits and calling <c>erl_tidy</c>
+ no longer hangs if an error occurs. </p>
+ <p>
+ Own Id: OTP-14471 Aux Id: ERL-413 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Syntax_Tools 2.1.2</title>
<section><title>Improvements and New Features</title>
@@ -47,6 +146,20 @@
</section>
+<section><title>Syntax_Tools 2.1.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug regarding reverting map types. </p>
+ <p>
+ Own Id: OTP-15098 Aux Id: ERIERL-177 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Syntax_Tools 2.1.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/syntax_tools/doc/src/part_notes.xml b/lib/syntax_tools/doc/src/part_notes.xml
deleted file mode 100644
index e02ffddcb2..0000000000
--- a/lib/syntax_tools/doc/src/part_notes.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2007</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Syntax_Tools Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p><em>Syntax_Tools</em> contains modules for handling abstract
- Erlang syntax trees, in a way that is compatible with the "parse
- trees" of the STDLIB module <c>erl_parse</c>, together with
- utilities for reading source files in unusual ways and
- pretty-printing syntax trees. Also included is an amazing module
- merger and renamer called Igor, as well as an automatic
- code-cleaner.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/syntax_tools/src/Makefile b/lib/syntax_tools/src/Makefile
index 8325db45a8..c21d2f49c8 100644
--- a/lib/syntax_tools/src/Makefile
+++ b/lib/syntax_tools/src/Makefile
@@ -75,7 +75,7 @@ $(EBIN)/%.$(EMULATOR):%.erl
# special rules and dependencies to apply the transform to itself
$(EBIN)/merl_transform.beam: $(EBIN)/merl.beam ./merl_transform.beam \
- ../include/merl.hrl \
+ ../include/merl.hrl $(EBIN)/erl_comment_scan.beam \
$(EBIN)/erl_syntax.beam $(EBIN)/erl_syntax_lib.beam
./merl_transform.beam: ./merl_transform.erl $(EBIN)/merl.beam \
../include/merl.hrl
diff --git a/lib/syntax_tools/src/epp_dodger.erl b/lib/syntax_tools/src/epp_dodger.erl
index cf1ba0abfa..7e741cc649 100644
--- a/lib/syntax_tools/src/epp_dodger.erl
+++ b/lib/syntax_tools/src/epp_dodger.erl
@@ -502,6 +502,10 @@ quickscan_form([{'-', _L}, {atom, La, ifdef} | _Ts]) ->
kill_form(La);
quickscan_form([{'-', _L}, {atom, La, ifndef} | _Ts]) ->
kill_form(La);
+quickscan_form([{'-', _L}, {'if', La} | _Ts]) ->
+ kill_form(La);
+quickscan_form([{'-', _L}, {atom, La, elif} | _Ts]) ->
+ kill_form(La);
quickscan_form([{'-', _L}, {atom, La, else} | _Ts]) ->
kill_form(La);
quickscan_form([{'-', _L}, {atom, La, endif} | _Ts]) ->
@@ -615,8 +619,13 @@ filter_form(T) ->
%% ---------------------------------------------------------------------
%% Normal parsing - try to preserve all information
-normal_parser(Ts, Opt) ->
- rewrite_form(parse_tokens(scan_form(Ts, Opt))).
+normal_parser(Ts0, Opt) ->
+ case scan_form(Ts0, Opt) of
+ Ts when is_list(Ts) ->
+ rewrite_form(parse_tokens(Ts));
+ Node ->
+ Node
+ end.
scan_form([{'-', _L}, {atom, La, define} | Ts], Opt) ->
[{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La},
@@ -636,12 +645,26 @@ scan_form([{'-', _L}, {atom, La, ifdef} | Ts], Opt) ->
scan_form([{'-', _L}, {atom, La, ifndef} | Ts], Opt) ->
[{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La},
{atom, La, ifndef} | scan_macros(Ts, Opt)];
+scan_form([{'-', _L}, {'if', La} | Ts], Opt) ->
+ [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La},
+ {atom, La, 'if'} | scan_macros(Ts, Opt)];
+scan_form([{'-', _L}, {atom, La, elif} | Ts], Opt) ->
+ [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La},
+ {atom, La, 'elif'} | scan_macros(Ts, Opt)];
scan_form([{'-', _L}, {atom, La, else} | Ts], Opt) ->
[{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La},
{atom, La, else} | scan_macros(Ts, Opt)];
scan_form([{'-', _L}, {atom, La, endif} | Ts], Opt) ->
[{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La},
{atom, La, endif} | scan_macros(Ts, Opt)];
+scan_form([{'-', _L}, {atom, La, error} | Ts], _Opt) ->
+ Desc = build_info_string("-error", Ts),
+ ErrorInfo = {La, ?MODULE, {error, Desc}},
+ erl_syntax:error_marker(ErrorInfo);
+scan_form([{'-', _L}, {atom, La, warning} | Ts], _Opt) ->
+ Desc = build_info_string("-warning", Ts),
+ ErrorInfo = {La, ?MODULE, {warning, Desc}},
+ erl_syntax:error_marker(ErrorInfo);
scan_form([{'-', L}, {'?', L1}, {Type, _, _}=N | [{'(', _} | _]=Ts], Opt)
when Type =:= atom; Type =:= var ->
%% minus, macro and open parenthesis at start of form - assume that
@@ -657,6 +680,11 @@ scan_form([{'?', L}, {Type, _, _}=N | [{'(', _} | _]=Ts], Opt)
scan_form(Ts, Opt) ->
scan_macros(Ts, Opt).
+build_info_string(Prefix, Ts0) ->
+ Ts = lists:droplast(Ts0),
+ String = lists:droplast(tokens_to_string(Ts)),
+ Prefix ++ " " ++ String ++ ".".
+
scan_macros(Ts, Opt) ->
scan_macros(Ts, [], Opt).
@@ -865,11 +893,15 @@ tokens_to_string([]) ->
format_error(macro_args) ->
errormsg("macro call missing end parenthesis");
+format_error({error, Error}) ->
+ Error;
+format_error({warning, Error}) ->
+ Error;
format_error({unknown, Reason}) ->
- errormsg(io_lib:format("unknown error: ~P", [Reason, 15])).
+ errormsg(io_lib:format("unknown error: ~tP", [Reason, 15])).
errormsg(String) ->
- io_lib:format("~s: ~s", [?MODULE, String]).
+ io_lib:format("~s: ~ts", [?MODULE, String]).
%% =====================================================================
diff --git a/lib/syntax_tools/src/erl_comment_scan.erl b/lib/syntax_tools/src/erl_comment_scan.erl
index a7a2c10b79..e3eb95b819 100644
--- a/lib/syntax_tools/src/erl_comment_scan.erl
+++ b/lib/syntax_tools/src/erl_comment_scan.erl
@@ -208,7 +208,7 @@ scan_comment([], Cs1, L, Col, M, Ack) ->
seen_comment(Cs, Cs1, L, Col, M, Ack) ->
%% Compute indentation and strip trailing spaces
N = Col - M,
- Text = lists:reverse(string:strip(Cs1, left)),
+ Text = lists:reverse(string:trim(Cs1, leading)),
Ack1 = [{L, Col + 1, N, Text} | Ack],
scan_lines(Cs, L + 1, 0, 0, Ack1).
@@ -309,7 +309,7 @@ filename([C|T]) when is_integer(C), C > 0 ->
filename([]) ->
[];
filename(N) ->
- report_error("bad filename: `~P'.", [N, 25]),
+ report_error("bad filename: `~tP'.", [N, 25]),
exit(error).
error_read_file(Name) ->
diff --git a/lib/syntax_tools/src/erl_prettypr.erl b/lib/syntax_tools/src/erl_prettypr.erl
index 40ddd2b22a..6906ef1553 100644
--- a/lib/syntax_tools/src/erl_prettypr.erl
+++ b/lib/syntax_tools/src/erl_prettypr.erl
@@ -675,7 +675,12 @@ lay_2(Node, Ctxt) ->
%% attribute name, without following parentheses.
Ctxt1 = reset_prec(Ctxt),
Args = erl_syntax:attribute_arguments(Node),
- N = erl_syntax:attribute_name(Node),
+ N = case erl_syntax:attribute_name(Node) of
+ {atom, _, 'if'} ->
+ erl_syntax:variable('if');
+ N0 ->
+ N0
+ end,
D = case attribute_type(Node) of
spec ->
[SpecTuple] = Args,
@@ -774,9 +779,16 @@ lay_2(Node, Ctxt) ->
class_qualifier ->
Ctxt1 = set_prec(Ctxt, max_prec()),
D1 = lay(erl_syntax:class_qualifier_argument(Node), Ctxt1),
- D2 = lay(erl_syntax:class_qualifier_body(Node), Ctxt1),
- beside(D1, beside(text(":"), D2));
-
+ D2 = lay(erl_syntax:class_qualifier_body(Node), Ctxt1),
+ Stacktrace = erl_syntax:class_qualifier_stacktrace(Node),
+ case erl_syntax:variable_name(Stacktrace) of
+ '_' ->
+ beside(D1, beside(text(":"), D2));
+ _ ->
+ D3 = lay(Stacktrace, Ctxt1),
+ beside(D1, beside(beside(text(":"), D2),
+ beside(text(":"), D3)))
+ end;
comment ->
D = stack_comment_lines(
erl_syntax:comment_text(Node)),
diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl
index 9b2b503762..1be644c620 100644
--- a/lib/syntax_tools/src/erl_syntax.erl
+++ b/lib/syntax_tools/src/erl_syntax.erl
@@ -342,8 +342,10 @@
typed_record_field_body/1,
typed_record_field_type/1,
class_qualifier/2,
+ class_qualifier/3,
class_qualifier_argument/1,
class_qualifier_body/1,
+ class_qualifier_stacktrace/1,
tuple/1,
tuple_elements/1,
tuple_size/1,
@@ -3884,7 +3886,7 @@ fold_try_clause({clause, Pos, [P], Guard, Body}) ->
class_qualifier ->
{tuple, Pos, [class_qualifier_argument(P),
class_qualifier_body(P),
- {var, Pos, '_'}]};
+ class_qualifier_stacktrace(P)]};
_ ->
{tuple, Pos, [{atom, Pos, throw}, P, {var, Pos, '_'}]}
end,
@@ -3893,12 +3895,14 @@ fold_try_clause({clause, Pos, [P], Guard, Body}) ->
unfold_try_clauses(Cs) ->
[unfold_try_clause(C) || C <- Cs].
-unfold_try_clause({clause, Pos, [{tuple, _, [{atom, _, throw}, V, _]}],
+unfold_try_clause({clause, Pos, [{tuple, _, [{atom, _, throw},
+ V,
+ {var, _, '_'}]}],
Guard, Body}) ->
{clause, Pos, [V], Guard, Body};
-unfold_try_clause({clause, Pos, [{tuple, _, [C, V, _]}],
+unfold_try_clause({clause, Pos, [{tuple, _, [C, V, Stacktrace]}],
Guard, Body}) ->
- {clause, Pos, [class_qualifier(C, V)], Guard, Body}.
+ {clause, Pos, [class_qualifier(C, V, Stacktrace)], Guard, Body}.
%% =====================================================================
@@ -5324,7 +5328,7 @@ revert_map_type_assoc(Node) ->
Pos = get_pos(Node),
Name = map_type_assoc_name(Node),
Value = map_type_assoc_value(Node),
- {type, Pos, map_type_assoc, [Name, Value]}.
+ {type, Pos, map_field_assoc, [Name, Value]}.
%% =====================================================================
@@ -5382,7 +5386,7 @@ revert_map_type_exact(Node) ->
Pos = get_pos(Node),
Name = map_type_exact_name(Node),
Value = map_type_exact_value(Node),
- {type, Pos, map_type_exact, [Name, Value]}.
+ {type, Pos, map_field_exact, [Name, Value]}.
%% =====================================================================
@@ -5451,8 +5455,12 @@ map_type(Fields) ->
revert_map_type(Node) ->
Pos = get_pos(Node),
- {type, Pos, map, map_type_fields(Node)}.
-
+ case map_type_fields(Node) of
+ any_size ->
+ {type, Pos, map, any};
+ Fields ->
+ {type, Pos, map, Fields}
+ end.
%% =====================================================================
%% @doc Returns the list of field subtrees of a `map_type' node.
@@ -5710,7 +5718,12 @@ tuple_type(Elements) ->
revert_tuple_type(Node) ->
Pos = get_pos(Node),
- {type, Pos, tuple, tuple_type_elements(Node)}.
+ case tuple_type_elements(Node) of
+ any_size ->
+ {type, Pos, tuple, any};
+ TypeElements ->
+ {type, Pos, tuple, TypeElements}
+ end.
%% =====================================================================
@@ -6725,9 +6738,12 @@ try_expr_after(Node) ->
%%
%% @see class_qualifier_argument/1
%% @see class_qualifier_body/1
+%% @see class_qualifier_stacktrace/1
%% @see try_expr/4
--record(class_qualifier, {class :: syntaxTree(), body :: syntaxTree()}).
+-record(class_qualifier, {class :: syntaxTree(),
+ body :: syntaxTree(),
+ stacktrace :: syntaxTree()}).
%% type(Node) = class_qualifier
%% data(Node) = #class_qualifier{class :: Class, body :: Body}
@@ -6737,8 +6753,27 @@ try_expr_after(Node) ->
-spec class_qualifier(syntaxTree(), syntaxTree()) -> syntaxTree().
class_qualifier(Class, Body) ->
+ Underscore = {var, get_pos(Body), '_'},
tree(class_qualifier,
- #class_qualifier{class = Class, body = Body}).
+ #class_qualifier{class = Class, body = Body,
+ stacktrace = Underscore}).
+
+%% =====================================================================
+%% @doc Creates an abstract class qualifier. The result represents
+%% "<code><em>Class</em>:<em>Body</em>:<em>Stacktrace</em></code>".
+%%
+%% @see class_qualifier_argument/1
+%% @see class_qualifier_body/1
+%% @see try_expr/4
+
+-spec class_qualifier(syntaxTree(), syntaxTree(), syntaxTree()) ->
+ syntaxTree().
+
+class_qualifier(Class, Body, Stacktrace) ->
+ tree(class_qualifier,
+ #class_qualifier{class = Class,
+ body = Body,
+ stacktrace = Stacktrace}).
%% =====================================================================
@@ -6763,6 +6798,16 @@ class_qualifier_argument(Node) ->
class_qualifier_body(Node) ->
(data(Node))#class_qualifier.body.
+%% =====================================================================
+%% @doc Returns the stacktrace subtree of a `class_qualifier' node.
+%%
+%% @see class_qualifier/2
+
+-spec class_qualifier_stacktrace(syntaxTree()) -> syntaxTree().
+
+class_qualifier_stacktrace(Node) ->
+ (data(Node))#class_qualifier.stacktrace.
+
%% =====================================================================
%% @doc Creates an abstract "implicit fun" expression. If
@@ -7187,7 +7232,7 @@ macro_arguments(Node) ->
%% @doc Returns the syntax tree corresponding to an Erlang term.
%% `Term' must be a literal term, i.e., one that can be
%% represented as a source code literal. Thus, it may not contain a
-%% process identifier, port, reference, binary or function value as a
+%% process identifier, port, reference or function value as a
%% subterm. The function recognises printable strings, in order to get a
%% compact and readable representation. Evaluation fails with reason
%% `badarg' if `Term' is not a literal term.
@@ -7221,6 +7266,13 @@ abstract(T) when is_map(T) ->
|| {Key,Value} <- maps:to_list(T)]);
abstract(T) when is_binary(T) ->
binary([binary_field(integer(B)) || B <- binary_to_list(T)]);
+abstract(T) when is_bitstring(T) ->
+ S = bit_size(T),
+ ByteS = S div 8,
+ BitS = S rem 8,
+ <<Bin:ByteS/binary, I:BitS>> = T,
+ binary([binary_field(integer(B)) || B <- binary_to_list(Bin)]
+ ++ [binary_field(integer(I), integer(BitS), [])]);
abstract(T) ->
erlang:error({badarg, T}).
@@ -7296,15 +7348,20 @@ concrete(Node) ->
Node0 -> maps:merge(concrete(Node0),M0)
end;
binary ->
- Fs = [revert_binary_field(
- binary_field(binary_field_body(F),
- case binary_field_size(F) of
- none -> none;
- S ->
- revert(S)
- end,
- binary_field_types(F)))
- || F <- binary_fields(Node)],
+ Fs = [begin
+ B = binary_field_body(F),
+ {Body, Size} =
+ case type(B) of
+ size_qualifier ->
+ {size_qualifier_body(B),
+ size_qualifier_argument(B)};
+ _ ->
+ {B, none}
+ end,
+ revert_binary_field(
+ binary_field(Body, Size, binary_field_types(F)))
+ end
+ || F <- binary_fields(Node)],
{value, B, _} =
eval_bits:expr_grp(Fs, [],
fun(F, _) ->
@@ -7377,7 +7434,14 @@ is_literal(T) ->
is_literal_binary_field(F) ->
case binary_field_types(F) of
- [] -> is_literal(binary_field_body(F));
+ [] -> B = binary_field_body(F),
+ case type(B) of
+ size_qualifier ->
+ is_literal(size_qualifier_body(B)) andalso
+ is_literal(size_qualifier_argument(B));
+ _ ->
+ is_literal(B)
+ end;
_ -> false
end.
@@ -7727,8 +7791,9 @@ subtrees(T) ->
catch_expr ->
[[catch_expr_body(T)]];
class_qualifier ->
- [[class_qualifier_argument(T)],
- [class_qualifier_body(T)]];
+ [[class_qualifier_argument(T)],
+ [class_qualifier_body(T)],
+ [class_qualifier_stacktrace(T)]];
clause ->
case clause_guard(T) of
none ->
@@ -7949,6 +8014,7 @@ make_tree(block_expr, [B]) -> block_expr(B);
make_tree(case_expr, [[A], C]) -> case_expr(A, C);
make_tree(catch_expr, [[B]]) -> catch_expr(B);
make_tree(class_qualifier, [[A], [B]]) -> class_qualifier(A, B);
+make_tree(class_qualifier, [[A], [B], [C]]) -> class_qualifier(A, B, C);
make_tree(clause, [P, B]) -> clause(P, none, B);
make_tree(clause, [P, [G], B]) -> clause(P, G, B);
make_tree(cond_expr, [C]) -> cond_expr(C);
diff --git a/lib/syntax_tools/src/erl_syntax_lib.erl b/lib/syntax_tools/src/erl_syntax_lib.erl
index c7f477c4d2..352165893f 100644
--- a/lib/syntax_tools/src/erl_syntax_lib.erl
+++ b/lib/syntax_tools/src/erl_syntax_lib.erl
@@ -1317,6 +1317,8 @@ analyze_attribute(Node) ->
include_lib -> preprocessor;
ifdef -> preprocessor;
ifndef -> preprocessor;
+ 'if' -> preprocessor;
+ elif -> preprocessor;
else -> preprocessor;
endif -> preprocessor;
A ->
@@ -1979,7 +1981,7 @@ analyze_application(Node) ->
%%
%% @see analyze_type_name/1
--type typeName() :: atom() | {module(), atom(), arity()} | {atom(), arity()}.
+-type typeName() :: atom() | {module(), {atom(), arity()}} | {atom(), arity()}.
-spec analyze_type_application(erl_syntax:syntaxTree()) -> typeName().
diff --git a/lib/syntax_tools/src/erl_tidy.erl b/lib/syntax_tools/src/erl_tidy.erl
index 1ca60ea73b..5623aa6af3 100644
--- a/lib/syntax_tools/src/erl_tidy.erl
+++ b/lib/syntax_tools/src/erl_tidy.erl
@@ -193,7 +193,7 @@ dir_3(Name, Dir, Regexp, Env) ->
dir_1(Dir1, Regexp, Env).
dir_4(File, Regexp, Env) ->
- case re:run(File, Regexp) of
+ case re:run(File, Regexp, [unicode]) of
{match, _} ->
Opts = [{outfile, File}, {dir, ""} | Env#dir.options],
case catch file(File, Opts) of
@@ -301,6 +301,8 @@ file(Name, Opts) ->
{Child, ok} ->
ok;
{Child, {error, Reason}} ->
+ exit(Reason);
+ {'EXIT', Child, Reason} ->
exit(Reason)
end.
@@ -803,7 +805,7 @@ keep_form(Form, Used, Opts) ->
{F, A} = N,
File = proplists:get_value(file, Opts, ""),
report({File, erl_syntax:get_pos(Form),
- "removing unused function `~w/~w'."},
+ "removing unused function `~tw/~w'."},
[F, A], Opts),
false;
true ->
@@ -868,8 +870,8 @@ update_attribute(F, Imports, Opts) ->
Names ->
File = proplists:get_value(file, Opts, ""),
report({File, erl_syntax:get_pos(F),
- "removing unused imports:~s"},
- [[io_lib:fwrite("\n\t`~w:~w/~w'", [M, N, A])
+ "removing unused imports:~ts"},
+ [[io_lib:fwrite("\n\t`~w:~tw/~w'", [M, N, A])
|| {N, A} <- Names]], Opts)
end,
Is = [make_fname(N) || N <- Ns1],
@@ -1164,7 +1166,7 @@ visit_import_application({N, A} = Name, F, As, Tree, Env, St0) ->
case Expand of
true ->
report({Env#env.file, erl_syntax:get_pos(F),
- "expanding call to imported function `~w:~w/~w'."},
+ "expanding call to imported function `~w:~tw/~w'."},
[M, N, A], Env#env.verbosity),
F1 = erl_syntax:module_qualifier(erl_syntax:atom(M),
erl_syntax:atom(N)),
@@ -1218,7 +1220,7 @@ visit_spawn_call({N, A}, F, Ps, [A1, A2, A3] = As, Tree,
case erl_syntax:is_proper_list(A3) of
true ->
report({Env#env.file, erl_syntax:get_pos(F),
- "changing use of `~w/~w' to `~w/~w' with a fun."},
+ "changing use of `~tw/~w' to `~tw/~w' with a fun."},
[N, A, N, 1 + length(Ps)], Env#env.verbosity),
F1 = case erl_syntax:is_atom(A1, Env#env.module) of
true ->
@@ -1402,8 +1404,8 @@ visit_remote_application({M, N, A} = Name, F, As, Tree, Env, St) ->
case rename_remote_call(Name, St) of
{M1, N1} ->
report({Env#env.file, erl_syntax:get_pos(F),
- "updating obsolete call to `~w:~w/~w' "
- "to use `~w:~w/~w' instead."},
+ "updating obsolete call to `~w:~tw/~w' "
+ "to use `~w:~tw/~w' instead."},
[M, N, A, M1, N1, A], Env#env.verbosity),
M2 = erl_syntax:atom(M1),
N2 = erl_syntax:atom(N1),
@@ -1818,7 +1820,7 @@ filename([]) ->
filename(N) when is_atom(N) ->
atom_to_list(N);
filename(N) ->
- report_error("bad filename: `~P'.", [N, 25]),
+ report_error("bad filename: `~tP'.", [N, 25]),
exit(error).
get_env(Tree) ->
@@ -1909,11 +1911,11 @@ format({warning, D}, Vs) ->
format({recommend, D}, Vs) ->
["recommendation: ", format(D, Vs)];
format({"", L, D}, Vs) when is_integer(L), L > 0 ->
- [io_lib:fwrite("~w: ", [L]), format(D, Vs)];
+ [io_lib:fwrite("~tw: ", [L]), format(D, Vs)];
format({"", _L, D}, Vs) ->
format(D, Vs);
format({F, L, D}, Vs) when is_integer(L), L > 0 ->
- [io_lib:fwrite("~ts:~w: ", [filename(F), L]), format(D, Vs)];
+ [io_lib:fwrite("~ts:~tw: ", [filename(F), L]), format(D, Vs)];
format({F, _L, D}, Vs) ->
[io_lib:fwrite("~ts: ", [filename(F)]), format(D, Vs)];
format(S, Vs) when is_list(S) ->
diff --git a/lib/syntax_tools/src/igor.erl b/lib/syntax_tools/src/igor.erl
index b92cd8d607..16e3511734 100644
--- a/lib/syntax_tools/src/igor.erl
+++ b/lib/syntax_tools/src/igor.erl
@@ -834,7 +834,7 @@ merge_sources_1(Name, Modules, Trees, Opts) ->
dict:from_list(Rs);
false ->
report_error("bad value for `redirect' option: "
- "~P.",
+ "~tP.",
[Rs, 10]),
exit(error)
end,
@@ -1069,7 +1069,7 @@ filter_forms_2(Forms, Env) ->
comment -> kill;
_ ->
report_error("invalid value for option "
- "`file_attributes': ~w.",
+ "`file_attributes': ~tw.",
[FileAttrsOpt]),
exit(error)
end,
@@ -1180,7 +1180,7 @@ merge_namespaces(Modules, Env) ->
[] ->
ok;
Fs ->
- report_warning("interface functions renamed:\n\t~p.", [Fs])
+ report_warning("interface functions renamed:\n\t~tp.", [Fs])
end,
{M4, Acc2} = merge_namespaces_1(M2, Acc1),
Ms = M3 ++ M4,
@@ -1778,7 +1778,7 @@ transform_function(T, Env, St) ->
{maybe_modified(V, T1, 2, Text, Env), St1}.
renaming_note(Name) ->
- [lists:flatten(io_lib:fwrite("renamed function to `~w'",
+ [lists:flatten(io_lib:fwrite("renamed function to `~tw'",
[Name]))].
rename_atom(Node, Atom) ->
@@ -2488,7 +2488,7 @@ rename(Files, Renamings, Opts) ->
true ->
dict:from_list(Renamings);
false ->
- report_error("bad module renaming: ~P.",
+ report_error("bad module renaming: ~tP.",
[Renamings, 10]),
exit(error)
end,
@@ -2672,7 +2672,7 @@ error_text(D, Name) ->
end.
error_text_1(D, Name) ->
- io_lib:fwrite("error: `~w', ~P.", [Name, D, 15]).
+ io_lib:fwrite("error: `~w', ~tP.", [Name, D, 15]).
check_records(Rs, Name) ->
case duplicates([N || {N, _} <- Rs]) of
@@ -2680,7 +2680,7 @@ check_records(Rs, Name) ->
ok;
Ns ->
report_error("in module `~w': "
- "multiply defined records: ~p.",
+ "multiply defined records: ~tp.",
[Name, Ns]),
exit(error)
end.
@@ -2694,7 +2694,7 @@ expand_imports(Is, Name) ->
ordsets:from_list(As);
Ns ->
report_error("in module `~w': "
- "multiply imported functions: ~p.",
+ "multiply imported functions: ~tp.",
[Name, Ns]),
exit(error)
end.
@@ -2968,7 +2968,7 @@ filename([]) ->
filename(N) when is_atom(N) ->
atom_to_list(N);
filename(N) ->
- report_error("bad filename: `~P'.", [N, 25]),
+ report_error("bad filename: `~tP'.", [N, 25]),
exit(error).
duplicates(Xs) ->
@@ -3031,7 +3031,7 @@ split_lines_1(Cs, Cs1, Ls) ->
%% Reporting
warning_unsafe_call(Name, Module, Target) ->
- report_warning("call to `~w' in module `~w' "
+ report_warning("call to `~tw' in module `~w' "
"possibly unsafe in `~s'.", [Name, Module, Target]).
warning_apply_2(Module, Target) ->
diff --git a/lib/syntax_tools/src/merl.erl b/lib/syntax_tools/src/merl.erl
index d6cf208998..b503944442 100644
--- a/lib/syntax_tools/src/merl.erl
+++ b/lib/syntax_tools/src/merl.erl
@@ -565,13 +565,13 @@ parse_5(Ts, Es) ->
-dialyzer({nowarn_function, parse_error/1}). % no local return
parse_error({L, M, R}) when is_atom(M), is_integer(L) ->
- fail("~w: ~s", [L, M:format_error(R)]);
+ fail("~w: ~ts", [L, M:format_error(R)]);
parse_error({{L,C}, M, R}) when is_atom(M), is_integer(L), is_integer(C) ->
- fail("~w:~w: ~s", [L,C,M:format_error(R)]);
+ fail("~w:~w: ~ts", [L,C,M:format_error(R)]);
parse_error({_, M, R}) when is_atom(M) ->
fail(M:format_error(R));
parse_error(R) ->
- fail("unknown parse error: ~p", [R]).
+ fail("unknown parse error: ~tp", [R]).
%% ------------------------------------------------------------------------
%% Templates, substitution and matching
diff --git a/lib/syntax_tools/src/merl_transform.erl b/lib/syntax_tools/src/merl_transform.erl
index b298bc407f..571d7e4d86 100644
--- a/lib/syntax_tools/src/merl_transform.erl
+++ b/lib/syntax_tools/src/merl_transform.erl
@@ -196,7 +196,7 @@ var_name(V) -> V.
var_to_tag(V) when is_integer(V) -> V;
var_to_tag(V) ->
- list_to_atom(string:to_lower(atom_to_list(V))).
+ list_to_atom(string:lowercase(atom_to_list(V))).
pre_expand_case(Expr, Clauses, Line) ->
merl:qquote(Line, "merl:switch(_@expr, _@clauses)",
diff --git a/lib/syntax_tools/src/syntax_tools.app.src b/lib/syntax_tools/src/syntax_tools.app.src
index 5c6008a5f0..af50b7495b 100644
--- a/lib/syntax_tools/src/syntax_tools.app.src
+++ b/lib/syntax_tools/src/syntax_tools.app.src
@@ -18,4 +18,4 @@
{applications, [stdlib]},
{env, []},
{runtime_dependencies,
- ["compiler-7.0","erts-8.0","kernel-5.0","stdlib-3.0"]}]}.
+ ["compiler-7.0","erts-9.0","kernel-5.0","stdlib-3.4"]}]}.
diff --git a/lib/syntax_tools/test/merl_SUITE.erl b/lib/syntax_tools/test/merl_SUITE.erl
index 52bbd9b3b8..6389ad7738 100644
--- a/lib/syntax_tools/test/merl_SUITE.erl
+++ b/lib/syntax_tools/test/merl_SUITE.erl
@@ -30,13 +30,14 @@
%% Test cases
-export([merl_smoke_test/1,
- transform_parse_error_test/1]).
+ transform_parse_error_test/1, otp_15291/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[merl_smoke_test,
- transform_parse_error_test].
+ transform_parse_error_test,
+ otp_15291].
groups() ->
[].
@@ -101,6 +102,15 @@ transform_parse_error_test(_Config) ->
[?Q("merl:qquote(2, \"{\", [{var, V}])")], []))),
ok.
+otp_15291(_Config) ->
+ C0 = merl:quote("() -> ok"),
+ {clause,1,[],[],[{atom,1,ok}]} = C0,
+ C2 = merl:quote("(_,_) -> ok"),
+ {clause,1,[{var,1,'_'},{var,1,'_'}],[],[{atom,1,ok}]} = C2,
+ C1 = merl:quote("(_) -> ok"),
+ {clause,1,[{var,1,'_'}],[],[{atom,1,ok}]} = C1,
+ ok.
+
%% utilities
f(Ts) when is_list(Ts) ->
diff --git a/lib/syntax_tools/test/syntax_tools_SUITE.erl b/lib/syntax_tools/test/syntax_tools_SUITE.erl
index 868f43b8ee..9dbd0e302a 100644
--- a/lib/syntax_tools/test/syntax_tools_SUITE.erl
+++ b/lib/syntax_tools/test/syntax_tools_SUITE.erl
@@ -24,14 +24,15 @@
%% Test cases
-export([app_test/1,appup_test/1,smoke_test/1,revert/1,revert_map/1,
- t_abstract_type/1,t_erl_parse_type/1,t_epp_dodger/1,
+ revert_map_type/1,
+ t_abstract_type/1,t_erl_parse_type/1,t_type/1, t_epp_dodger/1,
t_comment_scan/1,t_igor/1,t_erl_tidy/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [app_test,appup_test,smoke_test,revert,revert_map,
- t_abstract_type,t_erl_parse_type,t_epp_dodger,
+ [app_test,appup_test,smoke_test,revert,revert_map,revert_map_type,
+ t_abstract_type,t_erl_parse_type,t_type,t_epp_dodger,
t_comment_scan,t_igor,t_erl_tidy].
groups() ->
@@ -121,10 +122,97 @@ revert_map(Config) when is_list(Config) ->
{map_field_assoc,{atom,17,name},{var,18,'Value'}}}]),
?t:timetrap_cancel(Dog).
-
+%% Testing bug fix for reverting map_field_assoc in types
+revert_map_type(Config) when is_list(Config) ->
+ Dog = ?t:timetrap(?t:minutes(1)),
+ Form1 = {attribute,4,record,
+ {state,
+ [{typed_record_field,
+ {record_field,5,{atom,5,x}},
+ {type,5,map,
+ [{type,5,map_field_exact,[{atom,5,y},{atom,5,z}]}]}}]}},
+ Mapped1 = erl_syntax_lib:map(fun(X) -> X end, Form1),
+ Form1 = erl_syntax:revert(Mapped1),
+ Form2 = {attribute,4,record,
+ {state,
+ [{typed_record_field,
+ {record_field,5,{atom,5,x}},
+ {type,5,map,
+ [{type,5,map_field_assoc,[{atom,5,y},{atom,5,z}]}]}}]}},
+ Mapped2 = erl_syntax_lib:map(fun(X) -> X end, Form2),
+ Form2 = erl_syntax:revert(Mapped2),
+ ?t:timetrap_cancel(Dog).
%% api tests
+t_type(Config) when is_list(Config) ->
+ F0 = fun validate_basic_type/1,
+ Appl0 = fun(Name) ->
+ Atom = erl_syntax:atom(Name),
+ erl_syntax:type_application(none, Atom, [])
+ end,
+ User0 = fun(Name) ->
+ Atom = erl_syntax:atom(Name),
+ erl_syntax:user_type_application(Atom, [])
+ end,
+ ok = validate(F0,[{"tuple()", erl_syntax:tuple_type()}
+ ,{"{}", erl_syntax:tuple_type([])}
+ ,{"integer()", Appl0(integer)}
+ ,{"foo()", User0(foo)}
+ ,{"map()", erl_syntax:map_type()}
+ ,{"#{}", erl_syntax:map_type([])}
+ ,{"1..2", erl_syntax:integer_range_type
+ (erl_syntax:integer(1), erl_syntax:integer(2))}
+ ,{"<<_:1,_:_*2>>", erl_syntax:bitstring_type
+ (erl_syntax:integer(1), erl_syntax:integer(2))}
+ ,{"fun()", erl_syntax:fun_type()}
+ ]),
+
+ F = fun validate_type/1,
+ ok = validate(F,[{"{}", tuple_type, false}
+ ,{"tuple()", tuple_type, true}
+ ,{"{atom()}", tuple_type, false}
+ ,{"{atom(),integer()}", tuple_type, false}
+ ,{"integer()", type_application, false}
+ ,{"foo()", user_type_application, false}
+ ,{"foo(integer())", user_type_application, false}
+ ,{"module:function()", type_application, false}
+ ,{"map()", map_type, true}
+ ,{"#{}", map_type, false}
+ ,{"#{atom() => integer()}", map_type, false}
+ ,{"#{atom() := integer()}", map_type, false}
+ ,{"#r{}", record_type, false}
+ ,{"#r{a :: integer()}", record_type, false}
+ ,{"[]", type_application, false}
+ ,{"nil()", type_application, false}
+ ,{"[atom()]", type_application, false}
+ ,{"1..2", integer_range_type, false}
+ ,{"<<_:1,_:_*2>>", bitstring_type, false}
+ ,{"fun()", fun_type, true}
+ ,{"integer() | atom()", type_union, false}
+ ,{"A :: fun()", annotated_type, false}
+ ,{"fun((...) -> atom())", function_type, false}
+ ,{"fun((integer()) -> atom())", function_type, false}
+ ,{"V", variable, true}
+ ]),
+ ok.
+
+validate_basic_type({String, Tree}) ->
+ ErlT = string_to_type(String),
+ ErlT = erl_syntax:revert(Tree),
+ ok.
+
+validate_type({String, Type, Leaf}) ->
+ ErlT = string_to_type(String),
+ Type = erl_syntax:type(ErlT),
+ Leaf = erl_syntax:is_leaf(ErlT),
+ Tree = erl_syntax_lib:map(fun(Node) -> Node end, ErlT),
+ Type = erl_syntax:type(Tree),
+ _ = erl_syntax:meta(Tree),
+ RevT = erl_syntax:revert(Tree),
+ Type = erl_syntax:type(RevT),
+ ok.
+
t_abstract_type(Config) when is_list(Config) ->
F = fun validate_abstract_type/1,
ok = validate(F,[{hi,atom},
@@ -137,6 +225,7 @@ t_abstract_type(Config) when is_list(Config) ->
{[$a,$b,$c],string},
{"hello world",string},
{<<1,2,3>>,binary},
+ {<<1,2,3:4>>,binary},
{#{a=>1,"b"=>2},map_expr},
{#{#{i=>1}=>1,"b"=>#{v=>2}},map_expr},
{{a,b,c},tuple}]),
@@ -239,6 +328,12 @@ t_erl_tidy(Config) when is_list(Config) ->
DataDir = ?config(data_dir, Config),
File = filename:join(DataDir,"erl_tidy_tilde.erl"),
ok = erl_tidy:file(File, [{stdout, true}]),
+
+ %% OTP-14471.
+ Old = process_flag(trap_exit, true),
+ NonExisting = filename:join(DataDir,"non_existing_file.erl"),
+ {'EXIT',{error,{0,file,enoent}}} = (catch erl_tidy:file(NonExisting)),
+ true = process_flag(trap_exit, Old),
ok.
test_comment_scan([],_) -> ok;
@@ -424,6 +519,13 @@ string_to_expr(String) ->
{ok,[Expr]} = erl_parse:parse_exprs(Ts),
Expr.
+string_to_type(String) ->
+ io:format("Str: ~p~n", [String]),
+ {ok,Ts,_} = erl_scan:string("-type foo() :: "++String++".", 0),
+ {ok,Form} = erl_parse:parse_form(Ts),
+ {attribute,_,type,{foo,Type,_NoParms=[]}} = Form,
+ Type.
+
p_run(Test, List) ->
N = erlang:system_info(schedulers),
diff --git a/lib/syntax_tools/vsn.mk b/lib/syntax_tools/vsn.mk
index 9b33f1e1f4..8959ebbd04 100644
--- a/lib/syntax_tools/vsn.mk
+++ b/lib/syntax_tools/vsn.mk
@@ -1 +1 @@
-SYNTAX_TOOLS_VSN = 2.1.2
+SYNTAX_TOOLS_VSN = 2.1.6
diff --git a/lib/tftp/AUTHORS b/lib/tftp/AUTHORS
new file mode 100644
index 0000000000..71fc97c4e0
--- /dev/null
+++ b/lib/tftp/AUTHORS
@@ -0,0 +1,11 @@
+Original Authors:
+
+Håkan Mattsson - tftp
+
+Contributors:
+
+Ingela Anderton Andin
+Martin Gustafsson
+Johan Blom
+Torbjörn Törnkvist
+Joe Armstrong \ No newline at end of file
diff --git a/lib/tftp/Makefile b/lib/tftp/Makefile
new file mode 100644
index 0000000000..a4559fbc2e
--- /dev/null
+++ b/lib/tftp/Makefile
@@ -0,0 +1,78 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1996-2018. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# %CopyrightEnd%
+#
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Macros
+# ----------------------------------------------------
+
+SUB_DIRECTORIES = src doc/src
+
+include vsn.mk
+VSN = $(TFTP_VSN)
+
+SPECIAL_TARGETS =
+
+DIA_PLT = ./priv/plt/$(APPLICATION).plt
+DIA_ANALYSIS = $(basename $(DIA_PLT)).dialyzer_analysis
+
+
+# ----------------------------------------------------
+# Default Subdir Targets
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_subdir.mk
+
+.PHONY: info gclean dialyzer dialyzer_plt dclean
+
+info:
+ @echo "OS: $(OS)"
+ @echo "DOCB: $(DOCB)"
+ @echo ""
+ @echo "TFTP_VSN: $(TFTP_VSN)"
+ @echo "APP_VSN: $(APP_VSN)"
+ @echo ""
+ @echo "DIA_PLT: $(DIA_PLT)"
+ @echo "DIA_ANALYSIS: $(DIA_ANALYSIS)"
+ @echo ""
+
+gclean:
+ git clean -fXd
+
+dclean:
+ rm -f $(DIA_PLT)
+ rm -f $(DIA_ANALYSIS)
+
+dialyzer_plt: $(DIA_PLT)
+
+$(DIA_PLT):
+ @echo "Building $(APPLICATION) plt file"
+ @dialyzer --build_plt \
+ --output_plt $@ \
+ -r ../$(APPLICATION)/ebin \
+ --output $(DIA_ANALYSIS) \
+ --verbose
+
+dialyzer: $(DIA_PLT)
+ @echo "Running dialyzer on $(APPLICATION)"
+ @dialyzer --plt $< \
+ ../$(APPLICATION)/ebin \
+ --verbose
diff --git a/lib/cosEvent/include/.gitignore b/lib/tftp/doc/html/.gitignore
index e69de29bb2..e69de29bb2 100644
--- a/lib/cosEvent/include/.gitignore
+++ b/lib/tftp/doc/html/.gitignore
diff --git a/lib/cosEvent/test/idl_output/.gitignore b/lib/tftp/doc/man3/.gitignore
index e69de29bb2..e69de29bb2 100644
--- a/lib/cosEvent/test/idl_output/.gitignore
+++ b/lib/tftp/doc/man3/.gitignore
diff --git a/lib/cosEventDomain/doc/html/.gitignore b/lib/tftp/doc/man6/.gitignore
index e69de29bb2..e69de29bb2 100644
--- a/lib/cosEventDomain/doc/html/.gitignore
+++ b/lib/tftp/doc/man6/.gitignore
diff --git a/lib/cosEventDomain/doc/man3/.gitignore b/lib/tftp/doc/pdf/.gitignore
index e69de29bb2..e69de29bb2 100644
--- a/lib/cosEventDomain/doc/man3/.gitignore
+++ b/lib/tftp/doc/pdf/.gitignore
diff --git a/lib/tftp/doc/src/Makefile b/lib/tftp/doc/src/Makefile
new file mode 100644
index 0000000000..5d76799e41
--- /dev/null
+++ b/lib/tftp/doc/src/Makefile
@@ -0,0 +1,155 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# %CopyrightEnd%
+#
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../../vsn.mk
+VSN=$(TFTP_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
+
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+XML_APPLICATION_FILES = ref_man.xml
+
+XML_CHAPTER_FILES = \
+ introduction.xml \
+ getting_started.xml \
+ notes.xml
+
+XML_REF3_FILES = \
+ tftp.xml
+
+XML_PART_FILES = \
+ usersguide.xml
+
+BOOK_FILES = book.xml
+
+XML_FILES = \
+ $(BOOK_FILES) \
+ $(XML_CHAPTER_FILES) \
+ $(XML_PART_FILES) \
+ $(XML_REF6_FILES) \
+ $(XML_REF3_FILES) \
+ $(XML_APPLICATION_FILES)
+
+# GIF_FILES = tftp.gif
+
+
+# ----------------------------------------------------
+
+HTML_FILES = \
+ $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
+ $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
+
+INFO_FILE = ../../info
+EXTRA_FILES = \
+ $(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html) \
+ $(XML_REF6_FILES:%.xml=$(HTMLDIR)/%.html) \
+ $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html)
+
+MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
+
+HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
+
+TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+XML_FLAGS +=
+DVIPS_FLAGS +=
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+$(HTMLDIR)/%.gif: %.gif
+ $(INSTALL_DATA) $< $@
+
+docs: pdf html man
+
+ldocs: local_docs
+
+$(TOP_PDF_FILE): $(XML_FILES)
+
+pdf: $(TOP_PDF_FILE)
+
+html: gifs $(HTML_REF_MAN_FILE)
+
+clean clean_docs: clean_html clean_man clean_pdf
+ rm -rf $(XMLDIR)
+ rm -f errs core *~
+
+man: $(MAN3_FILES)
+
+gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
+
+debug opt:
+
+clean_pdf:
+ rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+
+clean_html:
+ rm -rf $(TOP_HTML_FILES) $(HTMLDIR)/*
+
+clean_man:
+ rm -f $(MAN3_FILES)
+
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_docs_spec: docs
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(HTMLDIR)/* "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
+ $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
+ $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
+
+release_spec:
+
+info:
+ @echo "GIF_FILES:\n$(GIF_FILES)"
+ @echo ""
+ @echo "EXTRA_FILES:\n$(EXTRA_FILES)"
+ @echo ""
+ @echo "HTML_FILES:\n$(HTML_FILES)"
+ @echo ""
+ @echo "TOP_HTML_FILES:\n$(TOP_HTML_FILES)"
+ @echo ""
+ @echo "XML_REF3_FILES:\n$(XML_REF3_FILES)"
+ @echo ""
+ @echo "XML_REF6_FILES:\n$(XML_REF6_FILES)"
+ @echo ""
+ @echo "XML_CHAPTER_FILES:\n$(XML_CHAPTER_FILES)"
+ @echo ""
diff --git a/lib/tftp/doc/src/book.xml b/lib/tftp/doc/src/book.xml
new file mode 100644
index 0000000000..c0b551d517
--- /dev/null
+++ b/lib/tftp/doc/src/book.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE book SYSTEM "book.dtd">
+
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
+ <header titlestyle="normal">
+ <copyright>
+ <year>1997</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>TFTP</title>
+ <prepared>Péter Dimitrov</prepared>
+ <docno></docno>
+ <date>2018-03-22</date>
+ <rev>1.0</rev>
+ <file>book.sgml</file>
+ </header>
+ <insidecover>
+ </insidecover>
+ <pagetext>TFTP</pagetext>
+ <preamble>
+ <contents level="2"></contents>
+ </preamble>
+ <parts lift="no">
+ <xi:include href="usersguide.xml"/>
+ </parts>
+ <applications>
+ <xi:include href="ref_man.xml"/>
+ </applications>
+ <releasenotes>
+ <xi:include href="notes.xml"/>
+ </releasenotes>
+ <listofterms></listofterms>
+ <index></index>
+</book>
diff --git a/lib/tftp/doc/src/getting_started.xml b/lib/tftp/doc/src/getting_started.xml
new file mode 100644
index 0000000000..9bce52dbe0
--- /dev/null
+++ b/lib/tftp/doc/src/getting_started.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>1997</year>
+ <year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>Getting Started</title>
+ <prepared></prepared>
+ <docno></docno>
+ <approved></approved>
+ <date></date>
+ <rev></rev>
+ <file>getting_started.xml</file>
+ </header>
+
+ <section>
+ <title>General Information</title>
+ <p>The <seealso marker="tftp#start/1">start/1</seealso> function starts
+ a daemon process listening for UDP packets on a port. When it
+ receives a request for read or write, it spawns a temporary server
+ process handling the transfer.</p>
+ <p>On the client side,
+ function <seealso marker="tftp#read_file/3">read_file/3</seealso>
+ and <seealso marker="tftp#write_file/3">write_file/3</seealso>
+ spawn a temporary client process establishing
+ contact with a TFTP daemon and perform the file transfer.</p>
+ <p><c>tftp</c> uses a callback module to handle the file
+ transfer. Two such callback modules are provided,
+ <c>tftp_binary</c> and <c>tftp_file</c>. See
+ <seealso marker="tftp#read_file/3">read_file/3</seealso> and
+ <seealso marker="tftp#write_file/3">write_file/3</seealso> for details.
+ You can also implement your own callback modules, see
+ <seealso marker="tftp#tftp_callback">CALLBACK FUNCTIONS</seealso>.
+ A callback module provided by
+ the user is registered using option <c>callback</c>, see
+ <seealso marker="tftp#options">DATA TYPES</seealso>.</p>
+ </section>
+
+ <section>
+ <title>Using the TFTP client and server</title>
+ <p>This is a simple example of starting the TFTP server and reading the content
+ of a sample file using the TFTP client.</p>
+
+ <p><em>Step 1.</em> Create a sample file to be used for the transfer:</p>
+ <code>
+ $ echo "Erlang/OTP 21" > file.txt
+ </code>
+
+ <p><em>Step 2.</em> Start the TFTP server:</p>
+ <code type="erl" >
+ 1> {ok, Pid} = tftp:start([{port, 19999}]).
+ <![CDATA[{ok,<0.65.0>}]]>
+ </code>
+
+ <p><em>Step 3.</em> Start the TFTP client (in another shell):</p>
+ <code type="erl" >
+ 1> tftp:read_file("file.txt", binary, [{port, 19999}]).
+ <![CDATA[{ok,<<"Erlang/OTP 21\n">>}]]>
+ </code>
+ </section>
+
+</chapter>
diff --git a/lib/tftp/doc/src/introduction.xml b/lib/tftp/doc/src/introduction.xml
new file mode 100644
index 0000000000..70761db0dc
--- /dev/null
+++ b/lib/tftp/doc/src/introduction.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>1997</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>Introduction</title>
+ <prepared>Péter Dimitrov</prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date>2018-03-22</date>
+ <rev>A</rev>
+ <file>introduction.xml</file>
+ </header>
+
+ <section>
+ <title>Purpose</title>
+ <p>The Trivial File Transfer Protocol or TFTP is a very simple protocol
+ used to transfer files.</p>
+ <p>It has been implemented on top of the User Datagram protocol (UDP) so
+ it may be used to move files between machines on different networks
+ implementing UDP. It is designed to be small and easy to implement.
+ Therefore, it lacks most of the features of a regular FTP. The only
+ thing it can do is read and write files (or mail) from/to a remote server.
+ It cannot list directories, and currently has no provisions for user
+ authentication.</p>
+ <p>The <c>tftp</c> application implements the following IETF standards:</p>
+ <list type="bulleted">
+ <item>RFC 1350, The TFTP Protocol (revision 2)</item>
+ <item>RFC 2347, TFTP Option Extension</item>
+ <item>RFC 2348, TFTP Blocksize Option</item>
+ <item>RFC 2349, TFTP Timeout Interval and Transfer Size Options</item>
+ </list>
+ <p>The only feature that not is implemented is the <c>netascii</c> transfer mode.</p>
+ </section>
+
+ <section>
+ <title>Prerequisites</title>
+ <p>It is assumed that the reader is familiar with the Erlang
+ programming language, concepts of OTP, and has a basic
+ understanding of the TFTP protocol.</p>
+ </section>
+</chapter>
diff --git a/lib/tftp/doc/src/notes.xml b/lib/tftp/doc/src/notes.xml
new file mode 100644
index 0000000000..ff6113a89d
--- /dev/null
+++ b/lib/tftp/doc/src/notes.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2002</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>TFTP Release Notes</title>
+ <prepared></prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date>2018-03-22</date>
+ <rev>A</rev>
+ <file>notes.xml</file>
+ </header>
+
+ <section><title>Tftp 1.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>TFTP 1.0</title>
+
+ <section><title>First released version</title>
+ <list>
+ <item>
+ <p>
+ Inets application was split into multiple smaller protocol specific applications.
+ The TFTP application is a standalone TFTP client and server with the same functionality as
+ TFTP in Inets.</p>
+ <p>
+ Own Id: OTP-14113</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+</chapter>
diff --git a/lib/tftp/doc/src/ref_man.xml b/lib/tftp/doc/src/ref_man.xml
new file mode 100644
index 0000000000..41a6cc6d52
--- /dev/null
+++ b/lib/tftp/doc/src/ref_man.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE application SYSTEM "application.dtd">
+
+<application xmlns:xi="http://www.w3.org/2001/XInclude">
+ <header>
+ <copyright>
+ <year>1997</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>TFTP Reference Manual</title>
+ <prepared>Péter Dimitrov</prepared>
+ <docno></docno>
+ <date>2018-03-22</date>
+ <rev>1.0</rev>
+ <file>ref_man.xml</file>
+ </header>
+ <description>
+ <p>The <c>TFTP</c> application.</p>
+ </description>
+ <xi:include href="tftp.xml"/>
+</application>
diff --git a/lib/tftp/doc/src/tftp.xml b/lib/tftp/doc/src/tftp.xml
new file mode 100644
index 0000000000..4ed54bc462
--- /dev/null
+++ b/lib/tftp/doc/src/tftp.xml
@@ -0,0 +1,599 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2006</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>tftp</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ </header>
+ <module>tftp</module>
+ <modulesummary>Trivial FTP.</modulesummary>
+ <description>
+ <p>Interface module for the <c>tftp</c> application.</p>
+ </description>
+
+ <section>
+ <marker id="options"></marker>
+ <title>DATA TYPES</title>
+ <p><c>ServiceConfig = Options</c></p>
+ <p><c>Options = [option()]</c></p>
+ <p>Most of the options are common for both the client and the server
+ side, but some of them differs a little.
+ The available <c>option()</c>s are as follows:</p>
+ <taglist>
+ <tag><c>{debug, Level}</c></tag>
+ <item>
+ <p><c>Level = none | error | warning | brief | normal | verbose | all</c></p>
+ <p>Controls the level of debug printouts.
+ Default is <c>none</c>.</p>
+ </item>
+ <tag><c>{host, Host}</c></tag>
+ <item>
+ <p><c>Host = hostname()</c>, see
+ <seealso marker="kernel:inet">inet(3)</seealso>.</p>
+ <p>The name or IP address of the host where the TFTP daemon
+ resides. This option is only used by the client.</p>
+ </item>
+ <tag><c>{port, Port}</c></tag>
+ <item>
+ <p><c>Port = int()</c></p>
+ <p>The TFTP port where the daemon listens. Defaults is
+ the standardized number 69. On the server side, it can
+ sometimes make sense to set it to 0, meaning that
+ the daemon just picks a free port (which one is
+ returned by function <c>info/1</c>).</p>
+ <p>If a socket is connected already, option
+ <c>{udp, [{fd, integer()}]}</c> can be used to pass the
+ open file descriptor to <c>gen_udp</c>. This can be automated
+ by using a command-line argument stating the
+ prebound file descriptor number. For example, if the
+ port is 69 and file descriptor 22 is opened by
+ <c>setuid_socket_wrap</c>, the command-line argument
+ "-tftpd_69 22" triggers the prebound file
+ descriptor 22 to be used instead of opening port 69.
+ The UDP option <c>{udp, [{fd, 22}]}</c> is automatically added.
+ See <c>init:get_argument/</c> about command-line arguments and
+ <c>gen_udp:open/2</c> about UDP options.</p>
+ </item>
+ <tag><c>{port_policy, Policy}</c></tag>
+ <item>
+ <p><c>Policy = random | Port | {range, MinPort, MaxPort}</c></p>
+ <p><c>Port = MinPort = MaxPort = int()</c></p>
+ <p>Policy for the selection of the temporary port that is used
+ by the server/client during the file transfer. Default is
+ <c>random</c>, which is the standardized policy. With this
+ policy a randomized free port is used. A single port or a range
+ of ports can be useful if the protocol passes through a
+ firewall.</p>
+ </item>
+ <tag><c>{udp, Options}</c></tag>
+ <item>
+ <p><c>Options = [Opt]</c>, see
+ <seealso marker="kernel:gen_udp#open/1">gen_udp:open/2</seealso>.</p>
+ </item>
+ <tag><c>{use_tsize, Bool}</c></tag>
+ <item>
+ <p><c>Bool = bool()</c></p>
+ <p>Flag for automated use of option <c>tsize</c>. With
+ this set to <c>true</c>, the <c>write_file/3</c> client
+ determines the filesize and sends it to the server as
+ the standardized <c>tsize</c> option. A <c>read_file/3</c>
+ client acquires only a filesize from the server by sending
+ a zero <c>tsize</c>.</p>
+ </item>
+ <tag><c>{max_tsize, MaxTsize}</c></tag>
+ <item>
+ <p><c>MaxTsize = int() | infinity</c></p>
+ <p>Threshold for the maximal filesize in bytes. The transfer
+ is aborted if the limit is exceeded.
+ Default is <c>infinity</c>.</p>
+ </item>
+ <tag><c>{max_conn, MaxConn}</c></tag>
+ <item>
+ <p><c>MaxConn = int() | infinity</c></p>
+ <p>Threshold for the maximal number of active connections.
+ The daemon rejects the setup of new connections if
+ the limit is exceeded. Default is <c>infinity</c>.</p>
+ </item>
+ <tag><c>{TftpKey, TftpVal}</c></tag>
+ <item>
+ <p><c>TftpKey = string()</c> <br></br>
+<c>TftpVal = string()</c></p>
+ <p>Name and value of a TFTP option.</p>
+ </item>
+ <tag><c>{reject, Feature}</c></tag>
+ <item>
+ <p><c>Feature = Mode | TftpKey</c> <br></br>
+<c>&nbsp;Mode = read | write</c> <br></br>
+<c>&nbsp;TftpKey = string()</c></p>
+ <p>Controls which features to reject. This is
+ mostly useful for the server as it can restrict the use
+ of certain TFTP options or read/write access.</p>
+ </item>
+ <tag><c>{callback, {RegExp, Module, State}}</c></tag>
+ <item>
+ <p><c>RegExp = string()</c> <br></br>
+<c>Module = atom()</c> <br></br>
+<c>State = term()</c></p>
+ <p>Registration of a callback module. When a file is to be
+ transferred, its local filename is matched to the regular
+ expressions of the registered callbacks. The first matching
+ callback is used during the transfer. See
+ <seealso marker="#read_file/3">read_file/3</seealso> and
+ <seealso marker="#write_file/3">write_file/3</seealso>.
+ </p>
+ <p>The callback module must implement the <c>tftp</c> behavior, see
+ <seealso marker="#tftp_callback">CALLBACK FUNCTIONS</seealso>.</p>
+ </item>
+
+ <tag><c>{logger, Module}</c></tag>
+ <item>
+ <p><c>Module = module()</c></p>
+
+ <p>Callback module for customized logging of errors, warnings, and
+ info messages. The callback module must implement the
+ <c>tftp_logger</c> behavior, see
+ <seealso marker="#tftp_logger">LOGGER FUNCTIONS</seealso>.
+ The default module is <c>tftp_logger</c>.</p>
+ </item>
+
+ <tag><c>{max_retries, MaxRetries}</c></tag>
+ <item>
+ <p><c>MaxRetries = int()</c></p>
+
+ <p>Threshold for the maximal number of retries. By default
+ the server/client tries to resend a message up to
+ five times when the time-out expires.</p>
+ </item>
+ </taglist>
+ </section>
+
+ <funcs>
+ <func>
+ <name>change_config(daemons, Options) -> [{Pid, Result}]</name>
+ <fsummary>Changes configuration for all daemons.
+ </fsummary>
+ <type>
+ <v>Options = [option()]</v>
+ <v>Pid = pid()</v>
+ <v>Result = ok | {error, Reason}</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Changes configuration for all TFTP daemon processes. </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>change_config(servers, Options) -> [{Pid, Result}]</name>
+ <fsummary>Changes configuration for all servers.
+ </fsummary>
+ <type>
+ <v>Options = [option()]</v>
+ <v>Pid = pid()</v>
+ <v>Result = ok | {error, Reason}</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Changes configuration for all TFTP server processes.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>change_config(Pid, Options) -> Result</name>
+ <fsummary>Changes configuration for a TFTP daemon, server,
+ or client process.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ <v>Options = [option()]</v>
+ <v>Result = ok | {error, Reason}</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Changes configuration for a TFTP daemon, server, or client process.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>info(daemons) -> [{Pid, Options}]</name>
+ <fsummary>Returns information about all daemons.</fsummary>
+ <type>
+ <v>Pid = [pid()]</v>
+ <v>Options = [option()]</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Returns information about all TFTP daemon processes.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>info(servers) -> [{Pid, Options}]</name>
+ <fsummary>Returns information about all servers.</fsummary>
+ <type>
+ <v>Pid = [pid()]</v>
+ <v>Options = [option()]</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Returns information about all TFTP server processes. </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>info(Pid) -> {ok, Options} | {error, Reason}</name>
+ <fsummary>Returns information about a daemon, server, or client process.</fsummary>
+ <type>
+ <v>Options = [option()]</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Returns information about a TFTP daemon, server, or client process.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>read_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason}</name>
+ <fsummary>Reads a (virtual) file from a TFTP server.</fsummary>
+ <type>
+ <v>RemoteFilename = string()</v>
+ <v>LocalFilename = binary | string()</v>
+ <v>Options = [option()]</v>
+ <v>LastCallbackState = term()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Reads a (virtual) file <c>RemoteFilename</c> from a TFTP
+ server.</p>
+ <p>If <c>LocalFilename</c> is the atom <c>binary</c>,
+ <c>tftp_binary</c> is used as callback module. It concatenates
+ all transferred blocks and returns them as one single binary
+ in <c>LastCallbackState</c>.</p>
+ <p>If <c>LocalFilename</c> is a string and there are no
+ registered callback modules, <c>tftp_file</c> is used as
+ callback module. It writes each transferred block to the file
+ named <c>LocalFilename</c> and returns the number of
+ transferred bytes in <c>LastCallbackState</c>.</p>
+ <p>If <c>LocalFilename</c> is a string and there are registered
+ callback modules, <c>LocalFilename</c> is tested against
+ the regexps of these and the callback module corresponding to
+ the first match is used, or an error tuple is returned if no
+ matching regexp is found.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>start(Options) -> {ok, Pid} | {error, Reason}</name>
+ <fsummary>Starts a daemon process.</fsummary>
+ <type>
+ <v>Options = [option()]</v>
+ <v>Pid = pid()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Starts a daemon process listening for UDP packets on a
+ port. When it receives a request for read or write, it spawns
+ a temporary server process handling the actual transfer
+ of the (virtual) file.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>write_file(RemoteFilename, LocalFilename, Options) -> {ok, LastCallbackState} | {error, Reason}</name>
+ <fsummary>Writes a (virtual) file to a TFTP server.</fsummary>
+ <type>
+ <v>RemoteFilename = string()</v>
+ <v>LocalFilename = binary() | string()</v>
+ <v>Options = [option()]</v>
+ <v>LastCallbackState = term()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Writes a (virtual) file <c>RemoteFilename</c> to a TFTP
+ server.</p>
+ <p>If <c>LocalFilename</c> is a binary, <c>tftp_binary</c> is
+ used as callback module. The binary is transferred block by
+ block and the number of transferred bytes is returned in
+ <c>LastCallbackState</c>.</p>
+ <p>If <c>LocalFilename</c> is a string and there are no
+ registered callback modules, <c>tftp_file</c> is used as
+ callback module. It reads the file named <c>LocalFilename</c>
+ block by block and returns the number of transferred bytes
+ in <c>LastCallbackState</c>.</p>
+ <p>If <c>LocalFilename</c> is a string and there are registered
+ callback modules, <c>LocalFilename</c> is tested against
+ the regexps of these and the callback module corresponding to
+ the first match is used, or an error tuple is returned if no
+ matching regexp is found.</p>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <marker id="tftp_callback"></marker>
+ <title>CALLBACK FUNCTIONS</title>
+ <p>A <c>tftp</c> callback module is to be implemented as a
+ <c>tftp</c> behavior and export the functions listed
+ in the following.</p>
+ <p>On the server side, the callback interaction starts with a call to
+ <c>open/5</c> with the registered initial callback state.
+ <c>open/5</c> is expected to open the (virtual) file. Then either
+ function <c>read/1</c> or <c>write/2</c> is invoked
+ repeatedly, once per transferred block. At each function call,
+ the state returned from the previous call is obtained. When
+ the last block is encountered, function <c>read/1</c> or
+ <c>write/2</c> is expected to close the (virtual) file
+ and return its last state. Function <c>abort/3</c> is only
+ used in error situations. Function <c>prepare/5</c> is not used on
+ the server side.</p>
+ <p>On the client side, the callback interaction is the same, but it
+ starts and ends a bit differently. It starts with a call to
+ <c>prepare/5</c> with the same arguments as <c>open/5</c> takes.
+ <c>prepare/5</c> is expected to validate the TFTP options
+ suggested by the user and to return the subset of them that it
+ accepts. Then the options are sent to the server, which performs
+ the same TFTP option negotiation procedure. The options that are
+ accepted by the server are forwarded to function <c>open/5</c>
+ on the client side. On the client side, function <c>open/5</c>
+ must accept all option as-is or reject the transfer. Then
+ the callback interaction follows the same pattern as described
+ for the server side. When the last block is encountered in
+ <c>read/1</c> or <c>write/2</c>, the returned state is forwarded to
+ the user and returned from <c>read_file</c>/3 or
+ <c>write_file/3</c>.</p>
+
+ <p> If a callback (performing the file access
+ in the TFTP server) takes too long time (more than
+ the double TFTP time-out), the server aborts the
+ connection and sends an error reply to the client.
+ This implies that the server releases resources
+ attached to the connection faster than before. The
+ server simply assumes that the client has given
+ up.</p>
+
+ <p>If the TFTP server receives yet another request from
+ the same client (same host and port) while it
+ already has an active connection to the client, it
+ ignores the new request if the request is
+ equal to the first one (same filename and options).
+ This implies that the (new) client will be served
+ by the already ongoing connection on the server
+ side. By not setting up yet another connection, in
+ parallel with the ongoing one, the server
+ consumes less resources.</p>
+
+ <marker id="prepare"></marker>
+ </section>
+
+ <funcs>
+ <func>
+ <name>Module:abort(Code, Text, State) -> ok</name>
+ <fsummary>Aborts the file transfer.</fsummary>
+ <type>
+ <v>Code = undef | enoent | eacces | enospc</v>
+ <v>&nbsp;&nbsp;| badop | eexist | baduser | badopt</v>
+ <v>&nbsp;&nbsp;| int()</v>
+ <v>Text = string()</v>
+ <v>State = term()</v>
+ </type>
+ <desc>
+ <p>Invoked when the file transfer is aborted.</p>
+ <p>The callback function is expected to clean
+ up its used resources after the aborted file
+ transfer, such as closing open file
+ descriptors and so on. The function is not
+ invoked if any of the other callback
+ functions returns an error, as it is
+ expected that they already have cleaned up
+ the necessary resources. However, it is
+ invoked if the functions fail (crash).</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:open(Peer, Access, Filename, Mode, SuggestedOptions, State) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}}</name>
+ <fsummary>Opens a file for read or write access.</fsummary>
+ <type>
+ <v>Peer = {PeerType, PeerHost, PeerPort}</v>
+ <v>PeerType = inet | inet6</v>
+ <v>PeerHost = ip_address()</v>
+ <v>PeerPort = integer()</v>
+ <v>Access = read | write</v>
+ <v>Filename = string()</v>
+ <v>Mode = string()</v>
+ <v>SuggestedOptions = AcceptedOptions = [{Key, Value}]</v>
+ <v>&nbsp;Key = Value = string()</v>
+ <v>State = InitialState | term()</v>
+ <v>&nbsp;InitialState = [] | [{root_dir, string()}]</v>
+ <v>NewState = term()</v>
+ <v>Code = undef | enoent | eacces | enospc</v>
+ <v>&nbsp;&nbsp;| badop | eexist | baduser | badopt</v>
+ <v>&nbsp;&nbsp;| int()</v>
+ <v>Text = string()</v>
+ </type>
+ <desc>
+ <p>Opens a file for read or write access.</p>
+ <p>On the client side, where the <c>open/5</c> call has been
+ preceded by a call to <c>prepare/5</c>, all options must be
+ accepted or rejected.</p>
+ <p>On the server side, where there is no preceding
+ <c>prepare/5</c> call, no new options can be added, but
+ those present in <c>SuggestedOptions</c> can be
+ omitted or replaced with new values in <c>AcceptedOptions</c>.</p>
+
+ <marker id="read"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:prepare(Peer, Access, Filename, Mode, SuggestedOptions, InitialState) -> {ok, AcceptedOptions, NewState} | {error, {Code, Text}}</name>
+ <fsummary>Prepares to open a file on the client side.</fsummary>
+ <type>
+ <v>Peer = {PeerType, PeerHost, PeerPort}</v>
+ <v>PeerType = inet | inet6</v>
+ <v>PeerHost = ip_address()</v>
+ <v>PeerPort = integer()</v>
+ <v>Access = read | write</v>
+ <v>Filename = string()</v>
+ <v>Mode = string()</v>
+ <v>SuggestedOptions = AcceptedOptions = [{Key, Value}]</v>
+ <v>&nbsp;Key = Value = string()</v>
+ <v>InitialState = [] | [{root_dir, string()}]</v>
+ <v>NewState = term()</v>
+ <v>Code = undef | enoent | eacces | enospc</v>
+ <v>&nbsp;&nbsp;| badop | eexist | baduser | badopt</v>
+ <v>&nbsp;&nbsp;| int()</v>
+ <v>Text = string()</v>
+ </type>
+ <desc>
+ <p>Prepares to open a file on the client side.</p>
+ <p>No new options can be added, but those present in
+ <c>SuggestedOptions</c> can be omitted or replaced with new
+ values in <c>AcceptedOptions</c>.</p>
+ <p>This is followed by a call to <c>open/4</c> before any
+ read/write access is performed. <c>AcceptedOptions</c> is
+ sent to the server, which replies with the options that it
+ accepts. These are then forwarded to <c>open/4</c> as
+ <c>SuggestedOptions</c>.</p>
+
+ <marker id="open"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:read(State) -> {more, Bin, NewState} | {last, Bin, FileSize} | {error, {Code, Text}}</name>
+ <fsummary>Reads a chunk from the file.</fsummary>
+ <type>
+ <v>State = NewState = term()</v>
+ <v>Bin = binary()</v>
+ <v>FileSize = int()</v>
+ <v>Code = undef | enoent | eacces | enospc</v>
+ <v>&nbsp;&nbsp;| badop | eexist | baduser | badopt</v>
+ <v>&nbsp;&nbsp;| int()</v>
+ <v>Text = string()</v>
+ </type>
+ <desc>
+ <p>Reads a chunk from the file.</p>
+ <p>The callback function is expected to close
+ the file when the last file chunk is
+ encountered. When an error is encountered,
+ the callback function is expected to clean
+ up after the aborted file transfer, such as
+ closing open file descriptors, and so on. In both
+ cases there will be no more calls to any of
+ the callback functions.</p>
+
+ <marker id="write"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:write(Bin, State) -> {more, NewState} | {last, FileSize} | {error, {Code, Text}}</name>
+ <fsummary>Writes a chunk to the file.</fsummary>
+ <type>
+ <v>Bin = binary()</v>
+ <v>State = NewState = term()</v>
+ <v>FileSize = int()</v>
+ <v>Code = undef | enoent | eacces | enospc</v>
+ <v>&nbsp;&nbsp;| badop | eexist | baduser | badopt</v>
+ <v>&nbsp;&nbsp;| int()</v>
+ <v>Text = string()</v>
+ </type>
+ <desc>
+ <p>Writes a chunk to the file.</p>
+ <p>The callback function is expected to close
+ the file when the last file chunk is
+ encountered. When an error is encountered,
+ the callback function is expected to clean
+ up after the aborted file transfer, such as
+ closing open file descriptors, and so on. In both
+ cases there will be no more calls to any of
+ the callback functions.</p>
+
+ <marker id="abort"></marker>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <marker id="tftp_logger"></marker>
+ <title>LOGGER FUNCTIONS</title>
+
+ <p>A <c>tftp_logger</c> callback module is to be implemented as a
+ <c>tftp_logger</c> behavior and export the following functions:</p>
+
+ <marker id="error_msg"></marker>
+ </section>
+
+ <funcs>
+ <func>
+ <name>Logger:error_msg(Format, Data) -> ok | exit(Reason)</name>
+ <fsummary>Logs an error message.</fsummary>
+ <type>
+ <v>Format = string()</v>
+ <v>Data = [term()]</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Logs an error message.
+ See <c>error_logger:error_msg/2</c> for details.</p>
+
+ <marker id="warning_msg"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>Logger:info_msg(Format, Data) -> ok | exit(Reason)</name>
+ <fsummary>Logs an info message.</fsummary>
+ <type>
+ <v>Format = string()</v>
+ <v>Data = [term()]</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Logs an info message.
+ See <c>error_logger:info_msg/2</c> for details.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>Logger:warning_msg(Format, Data) -> ok | exit(Reason)</name>
+ <fsummary>Logs a warning message.</fsummary>
+ <type>
+ <v>Format = string()</v>
+ <v>Data = [term()]</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Logs a warning message.
+ See <c>error_logger:warning_msg/2</c> for details.</p>
+
+ <marker id="info_msg"></marker>
+ </desc>
+ </func>
+ </funcs>
+</erlref>
+
+
diff --git a/lib/tftp/doc/src/usersguide.xml b/lib/tftp/doc/src/usersguide.xml
new file mode 100644
index 0000000000..eb7f7d17c3
--- /dev/null
+++ b/lib/tftp/doc/src/usersguide.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE part SYSTEM "part.dtd">
+
+<part xmlns:xi="http://www.w3.org/2001/XInclude">
+ <header>
+ <copyright>
+ <year>2004</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>TFTP User's Guide</title>
+ <prepared>Péter Dimitrov</prepared>
+ <docno></docno>
+ <date>2018-03-22</date>
+ <rev>A</rev>
+ <file>part.sgml</file>
+ </header>
+ <description>
+ <p>The <c>TFTP</c> application provides a TFTP client and server.</p>
+ </description>
+ <xi:include href="introduction.xml"/>
+ <xi:include href="getting_started.xml"/>
+</part>
diff --git a/lib/cosEventDomain/doc/man6/.gitignore b/lib/tftp/ebin/.gitignore
index e69de29bb2..e69de29bb2 100644
--- a/lib/cosEventDomain/doc/man6/.gitignore
+++ b/lib/tftp/ebin/.gitignore
diff --git a/lib/tftp/info b/lib/tftp/info
new file mode 100644
index 0000000000..1220454351
--- /dev/null
+++ b/lib/tftp/info
@@ -0,0 +1,2 @@
+group: comm
+short: TFTP application
diff --git a/lib/tftp/src/Makefile b/lib/tftp/src/Makefile
new file mode 100644
index 0000000000..602ae845a4
--- /dev/null
+++ b/lib/tftp/src/Makefile
@@ -0,0 +1,110 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2005-2018. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# %CopyrightEnd%
+#
+#
+
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+VSN = $(TFTP_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+BEHAVIOUR_MODULES=
+
+MODULES = \
+ tftp \
+ tftp_app \
+ tftp_binary \
+ tftp_engine \
+ tftp_file \
+ tftp_lib \
+ tftp_logger \
+ tftp_sup
+
+HRL_FILES = tftp.hrl
+
+ERL_FILES= \
+ $(MODULES:%=%.erl) \
+ $(BEHAVIOUR_MODULES:%=%.erl)
+
+TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+BEHAVIOUR_TARGET_FILES= $(BEHAVIOUR_MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+APP_FILE= tftp.app
+APPUP_FILE= tftp.appup
+
+APP_SRC= $(APP_FILE).src
+APP_TARGET= $(EBIN)/$(APP_FILE)
+APPUP_SRC= $(APPUP_FILE).src
+APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+$(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES)
+
+debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+
+clean:
+ rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(BEHAVIOUR_TARGET_FILES)
+ rm -f core
+
+$(APP_TARGET): $(APP_SRC) ../vsn.mk
+ $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
+
+$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
+ $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
+
+docs:
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(BEHAVIOUR_TARGET_FILES) $(TARGET_FILES) $(APP_TARGET) \
+ $(APPUP_TARGET) "$(RELSYSDIR)/ebin"
+
+release_docs_spec:
+
+info:
+ @echo "APPLICATION = $(APPLICATION)"
+ @echo "ERL_COMPILE_FLAGS = $(ERL_COMPILE_FLAGS)"
diff --git a/lib/tftp/src/tftp.app.src b/lib/tftp/src/tftp.app.src
new file mode 100644
index 0000000000..9e79fe32bf
--- /dev/null
+++ b/lib/tftp/src/tftp.app.src
@@ -0,0 +1,22 @@
+{application, tftp,
+ [{description, "TFTP application"},
+ {vsn, "%VSN%"},
+ {registered, []},
+ {mod, { tftp_app, []}},
+ {applications,
+ [kernel,
+ stdlib
+ ]},
+ {env,[]},
+ {modules, [
+ tftp,
+ tftp_app,
+ tftp_binary,
+ tftp_engine,
+ tftp_file,
+ tftp_lib,
+ tftp_logger,
+ tftp_sup
+ ]},
+ {runtime_dependencies, ["stdlib-3.5","kernel-6.0"]}
+ ]}.
diff --git a/lib/tftp/src/tftp.appup.src b/lib/tftp/src/tftp.appup.src
new file mode 100644
index 0000000000..06a0f0f9dc
--- /dev/null
+++ b/lib/tftp/src/tftp.appup.src
@@ -0,0 +1,26 @@
+%% -*- erlang -*-
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+{"%VSN%",
+ [
+ {<<".*">>,[{restart_application, tftp}]}
+ ],
+ [
+ {<<".*">>,[{restart_application, tftp}]}
+ ]
+}.
diff --git a/lib/tftp/src/tftp.erl b/lib/tftp/src/tftp.erl
new file mode 100644
index 0000000000..31e4c651e8
--- /dev/null
+++ b/lib/tftp/src/tftp.erl
@@ -0,0 +1,409 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File : tftp.erl
+%%% Author : Hakan Mattsson <[email protected]>
+%%% Description : Trivial FTP
+%%% Created : 18 May 2004 by Hakan Mattsson <[email protected]>
+%%%-------------------------------------------------------------------
+%%%
+%%% This is a complete implementation of the following IETF standards:
+%%%
+%%% RFC 1350, The TFTP Protocol (revision 2).
+%%% RFC 2347, TFTP Option Extension.
+%%% RFC 2348, TFTP Blocksize Option.
+%%% RFC 2349, TFTP Timeout Interval and Transfer Size Options.
+%%%
+%%% The only feature that not is implemented in this release is
+%%% the "netascii" transfer mode.
+%%%
+%%% The start/1 function starts a daemon process which, listens for
+%%% UDP packets on a port. When it receives a request for read or
+%%% write it spawns a temporary server process which handles the
+%%% actual transfer of the file. On the client side the read_file/3
+%%% and write_file/3 functions spawns a temporary client process which
+%%% establishes contact with a TFTP daemon and performs the actual
+%%% transfer of the file.
+%%%
+%%% Most of the options are common for both the client and the server
+%%% side, but some of them differs a little. Here are the available
+%%% options:
+%%%
+%%% {debug, Level}
+%%%
+%%% Level = none | error | warning brief | normal | verbose | all
+%%%
+%%% Controls the level of debug printouts. The default is none.
+%%%
+%%% {host, Host}
+%%%
+%%% The name or IP address of the host where the TFTP daemon
+%%% resides. This option is only used by the client. See
+%%% 'inet' about valid host names.
+%%%
+%%% {port, Port}
+%%%
+%%% Port = integer()
+%%%
+%%% The TFTP port where the daemon listens. It defaults to the
+%%% standardized number 69. On the server side it may sometimes
+%%% make sense to set it to 0, which means that the daemon just
+%%% will pick a free port (which is returned by the start/1
+%%% function).
+%%%
+%%% If a socket has somehow already has been connected, the
+%%% {udp, [{fd, integer()}]} option can be used to pass the
+%%% open file descriptor to gen_udp. This can be automated
+%%% a bit by using a command line argument stating the
+%%% prebound file descriptor number. For example, if the
+%%% Port is 69 and the file descriptor 22 has been opened by
+%%% setuid_socket_wrap. Then the command line argument
+%%% "-tftpd_69 22" will trigger the prebound file
+%%% descriptor 22 to be used instead of opening port 69.
+%%% The UDP option {udp, [{fd, 22}]} autmatically be added.
+%%% See init:get_argument/ about command line arguments and
+%%% gen_udp:open/2 about UDP options.
+%%%
+%%% {port_policy, Policy}
+%%%
+%%% Policy = random | Port | {range, MinPort, MaxPort}
+%%% Port = MinPort = MaxPort = integer()
+%%%
+%%% Policy for the selection of the temporary port which is used
+%%% by the server/client during the file transfer. It defaults to
+%%% 'random' which is the standardized policy. With this policy a
+%%% randomized free port used. A single port or a range of ports
+%%% can be useful if the protocol should pass thru a firewall.
+%%%
+%%% {prebound_fd, InitArgFlag}
+%%%
+%%% InitArgFlag = atom()
+%%%
+%%% If a socket has somehow already has been connected, the
+%%% {udp, [{fd, integer()}]} option can be used to pass the
+%%% open file descriptor to gen_udp.
+%%%
+%%% The prebound_fd option makes it possible to pass give the
+%%% file descriptor as a command line argument. The typical
+%%% usage is when used in conjunction with setuid_socket_wrap
+%%% to be able to open privileged sockets. For example if the
+%%% file descriptor 22 has been opened by setuid_socket_wrap
+%%% and you have choosen my_tftp_fd as init argument, the
+%%% command line should like this "erl -my_tftp_fd 22" and
+%%% FileDesc should be set to my_tftpd_fd. This would
+%%% automatically imply {fd, 22} to be set as UDP option.
+%%%
+%%% {udp, UdpOptions}
+%%%
+%%% Options to gen_udp:open/2.
+%%%
+%%% {use_tsize, Bool}
+%%%
+%%% Bool = boolean()
+%%%
+%%% Flag for automated usage of the "tsize" option. With this set
+%%% to true, the write_file/3 client will determine the filesize
+%%% and send it to the server as the standardized "tsize" option.
+%%% A read_file/3 client will just acquire filesize from the
+%%% server by sending a zero "tsize".
+%%%
+%%% {max_tsize, MaxTsize}
+%%%
+%%% MaxTsize = integer() | infinity
+%%%
+%%% Threshold for the maximal filesize in bytes. The transfer will
+%%% be aborted if the limit is exceeded. It defaults to
+%%% 'infinity'.
+%%%
+%%% {max_conn, MaxConn}
+%%%
+%%% MaxConn = integer() | infinity
+%%%
+%%% Threshold for the maximal number of active connections. The
+%%% daemon will reject the setup of new connections if the limit
+%%% is exceeded. It defaults to 'infinity'.
+%%%
+%%% {TftpKey, TftpVal}
+%%%
+%%% TftpKey = string()
+%%% TftpVal = string()
+%%%
+%%% The name and value of a TFTP option.
+%%%
+%%% {reject, Feature}
+%%%
+%%% Feature = Mode | TftpKey
+%%% Mode = read | write
+%%% TftpKey = string()
+%%%
+%%% Control which features that should be rejected.
+%%% This is mostly useful for the server as it may restrict
+%%% usage of certain TFTP options or read/write access.
+%%%
+%%% {callback, {RegExp, Module, State}}
+%%%
+%%% RegExp = string()
+%%% Module = atom()
+%%% State = term()
+%%%
+%%% Registration of a callback module. When a file is to be
+%%% transferred, its local filename will be matched to the
+%%% regular expressions of the registered callbacks. The first
+%%% matching callback will be used the during the transfer.The
+%%% callback module must implement the 'tftp' behaviour.
+%%%
+%%% On the server side the callback interaction starts with a
+%%% call to open/5 with the registered initial callback
+%%% state. open/5 is expected to open the (virtual) file. Then
+%%% either the read/1 or write/2 functions are invoked
+%%% repeatedly, once per transfererred block. At each function
+%%% call the state returned from the previous call is
+%%% obtained. When the last block has been encountered the read/1
+%%% or write/2 functions is expected to close the (virtual)
+%%% file.and return its last state. The abort/3 function is only
+%%% used in error situations. prepare/5 is not used on the server
+%%% side.
+%%%
+%%% On the client side the callback interaction is the same, but
+%%% it starts and ends a bit differently. It starts with a call
+%%% to prepare/5 with the same arguments as open/5
+%%% takes. prepare/5 is expected to validate the TFTP options,
+%%% suggested by the user and return the subset of them that it
+%%% accepts. Then the options is sent to the server which will
+%%% perform the same TFTP option negotiation procedure. The
+%%% options that are accepted by the server is forwarded to the
+%%% open/5 function on the client side. On the client side the
+%%% open/5 function must accept all option as is or reject the
+%%% transfer. Then the callback interaction follows the same
+%%% pattern as described above for the server side. When the last
+%%% block is encountered in read/1 or write/2 the returned stated
+%%% is forwarded to the user and returned from read_file/3 or
+%%% write_file/3.
+%%%-------------------------------------------------------------------
+
+-module(tftp).
+
+%%-------------------------------------------------------------------
+%% Interface
+%%-------------------------------------------------------------------
+
+%% Public functions
+-export([
+ read_file/3,
+ write_file/3,
+ start/1,
+ info/1,
+ change_config/2,
+ start/0,
+ stop/0
+ ]).
+
+%% Application local functions
+-export([
+ start_standalone/1,
+ start_service/1,
+ stop_service/1,
+ services/0,
+ service_info/1
+ ]).
+
+
+-type peer() :: {PeerType :: inet | inet6,
+ PeerHost :: inet:ip_address(),
+ PeerPort :: port()}.
+
+-type access() :: read | write.
+
+-type options() :: [{Key :: string(), Value :: string()}].
+
+-type error_code() :: undef | enoent | eacces | enospc |
+ badop | eexist | baduser | badopt |
+ integer().
+
+-callback prepare(Peer :: peer(),
+ Access :: access(),
+ Filename :: file:name(),
+ Mode :: string(),
+ SuggestedOptions :: options(),
+ InitialState :: [] | [{root_dir, string()}]) ->
+ {ok, AcceptedOptions :: options(), NewState :: term()} |
+ {error, {Code :: error_code(), string()}}.
+
+-callback open(Peer :: peer(),
+ Access :: access(),
+ Filename :: file:name(),
+ Mode :: string(),
+ SuggestedOptions :: options(),
+ State :: [] | [{root_dir, string()}] | term()) ->
+ {ok, AcceptedOptions :: options(), NewState :: term()} |
+ {error, {Code :: error_code(), string()}}.
+
+-callback read(State :: term()) -> {more, binary(), NewState :: term()} |
+ {last, binary(), integer()} |
+ {error, {Code :: error_code(), string()}}.
+
+-callback write(binary(), State :: term()) ->
+ {more, NewState :: term()} |
+ {last, FileSize :: integer()} |
+ {error, {Code :: error_code(), string()}}.
+
+-callback abort(Code :: error_code(), string(), State :: term()) -> 'ok'.
+
+-include("tftp.hrl").
+
+
+%%-------------------------------------------------------------------
+%% read_file(RemoteFilename, LocalFilename, Options) ->
+%% {ok, LastCallbackState} | {error, Reason}
+%%
+%% RemoteFilename = string()
+%% LocalFilename = binary | string()
+%% Options = [option()]
+%% LastCallbackState = term()
+%% Reason = term()
+%%
+%% Reads a (virtual) file from a TFTP server
+%%
+%% If LocalFilename is the atom 'binary', tftp_binary will be used as
+%% callback module. It will concatenate all transferred blocks and
+%% return them as one single binary in the CallbackState.
+%%
+%% When LocalFilename is a string, it will be matched to the
+%% registered callback modules and hopefully one of them will be
+%% selected. By default, tftp_file will be used as callback module. It
+%% will write each transferred block to the file named
+%% LocalFilename. The number of transferred bytes will be returned as
+%% LastCallbackState.
+%%-------------------------------------------------------------------
+
+read_file(RemoteFilename, LocalFilename, Options) ->
+ tftp_engine:client_start(read, RemoteFilename, LocalFilename, Options).
+
+%%-------------------------------------------------------------------
+%% write(RemoteFilename, LocalFilename, Options) ->
+%% {ok, LastCallbackState} | {error, Reason}
+%%
+%% RemoteFilename = string()
+%% LocalFilename = binary() | string()
+%% Options = [option()]
+%% LastCallbackState = term()
+%% Reason = term()
+%%
+%% Writes a (virtual) file to a TFTP server
+%%
+%% If LocalFilename is a binary, tftp_binary will be used as callback
+%% module. The binary will be transferred block by block and the number
+%% of transferred bytes will be returned as LastCallbackState.
+%%
+%% When LocalFilename is a string, it will be matched to the
+%% registered callback modules and hopefully one of them will be
+%% selected. By default, tftp_file will be used as callback module. It
+%% will read the file named LocalFilename block by block. The number
+%% of transferred bytes will be returned as LastCallbackState.
+%%-------------------------------------------------------------------
+
+write_file(RemoteFilename, LocalFilename, Options) ->
+ tftp_engine:client_start(write, RemoteFilename, LocalFilename, Options).
+
+%%-------------------------------------------------------------------
+%% start(Options) -> {ok, Pid} | {error, Reason}
+%%
+%% Options = [option()]
+%% Pid = pid()
+%% Reason = term()
+%%
+%% Starts a daemon process which listens for udp packets on a
+%% port. When it receives a request for read or write it spawns
+%% a temporary server process which handles the actual transfer
+%% of the (virtual) file.
+%%-------------------------------------------------------------------
+
+start(Options) ->
+ tftp_engine:daemon_start(Options).
+
+%%-------------------------------------------------------------------
+%% info(Pid) -> {ok, Options} | {error, Reason}
+%%
+%% Options = [option()]
+%% Reason = term()
+%%
+%% Returns info about a tftp daemon, server or client process
+%%-------------------------------------------------------------------
+
+info(Pid) ->
+ tftp_engine:info(Pid).
+
+%%-------------------------------------------------------------------
+%% change_config(Pid, Options) -> ok | {error, Reason}
+%%
+%% Options = [option()]
+%% Reason = term()
+%%
+%% Changes config for a tftp daemon, server or client process
+%% Must be used with care.
+%%-------------------------------------------------------------------
+
+change_config(Pid, Options) ->
+ tftp_engine:change_config(Pid, Options).
+
+%%-------------------------------------------------------------------
+%% start() -> ok | {error, Reason}
+%%
+%% Reason = term()
+%%
+%% Start the application
+%%-------------------------------------------------------------------
+
+start() ->
+ application:start(tftp).
+
+%%-------------------------------------------------------------------
+%% stop() -> ok | {error, Reason}
+%%
+%% Reason = term()
+%%
+%% Stop the application
+%%-------------------------------------------------------------------
+stop() ->
+ application:stop(tftp).
+
+%%-------------------------------------------------------------------
+%% Inets service behavior
+%%-------------------------------------------------------------------
+
+start_standalone(Options) ->
+ start(Options).
+
+start_service(Options) ->
+ tftp_sup:start_child(Options).
+
+stop_service(Pid) ->
+ tftp_sup:stop_child(Pid).
+
+services() ->
+ tftp_sup:which_children().
+
+service_info(Pid) ->
+ info(Pid).
+
+
+
diff --git a/lib/tftp/src/tftp.hrl b/lib/tftp/src/tftp.hrl
new file mode 100644
index 0000000000..a26aeee389
--- /dev/null
+++ b/lib/tftp/src/tftp.hrl
@@ -0,0 +1,69 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%
+%%
+
+%%%-------------------------------------------------------------------
+%%% Defines
+%%%-------------------------------------------------------------------
+
+-define(TFTP_DEFAULT_PORT, 69).% Default server port
+
+-define(TFTP_OPCODE_RRQ, 1). % Read request
+-define(TFTP_OPCODE_WRQ, 2). % Write request
+-define(TFTP_OPCODE_DATA, 3). % Data
+-define(TFTP_OPCODE_ACK, 4). % Acknowledgement
+-define(TFTP_OPCODE_ERROR, 5). % Error
+-define(TFTP_OPCODE_OACK, 6). % Option acknowledgment
+
+-define(TFTP_ERROR_UNDEF, 0). % Not defined, see error message (if any)
+-define(TFTP_ERROR_ENOENT, 1). % File not found.
+-define(TFTP_ERROR_EACCES, 2). % Access violation.
+-define(TFTP_ERROR_ENOSPC, 3). % Disk full or allocation exceeded.
+-define(TFTP_ERROR_BADOP, 4). % Illegal TFTP operation.
+-define(TFTP_ERROR_BADBLK, 5). % Unknown transfer ID.
+-define(TFTP_ERROR_EEXIST, 6). % File already exists.
+-define(TFTP_ERROR_BADUSER, 7). % No such user.
+-define(TFTP_ERROR_BADOPT, 8). % Unrequested or illegal option.
+
+-record(tftp_msg_req, {access, filename, mode, options, local_filename}).
+-record(tftp_msg_data, {block_no, data}).
+-record(tftp_msg_ack, {block_no}).
+-record(tftp_msg_error, {code, text, details}).
+-record(tftp_msg_oack, {options}).
+
+-record(config, {parent_pid = self(),
+ udp_socket,
+ udp_options = [binary, {reuseaddr, true}, {active, once}],
+ udp_host = "localhost",
+ udp_port = ?TFTP_DEFAULT_PORT,
+ port_policy = random,
+ use_tsize = false,
+ max_tsize = infinity, % Filesize
+ max_conn = infinity,
+ rejected = [],
+ polite_ack = false,
+ debug_level = none,
+ timeout,
+ user_options = [],
+ callbacks = [],
+ logger = tftp_logger,
+ max_retries = 5}).
+
+-record(callback, {regexp, internal, module, state, block_no, count}).
diff --git a/lib/tftp/src/tftp_app.erl b/lib/tftp/src/tftp_app.erl
new file mode 100644
index 0000000000..80d54c6cbe
--- /dev/null
+++ b/lib/tftp/src/tftp_app.erl
@@ -0,0 +1,56 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%
+%%
+
+%%%-------------------------------------------------------------------
+%% @doc ftp public API
+%% @end
+%%%-------------------------------------------------------------------
+
+-module(tftp_app).
+
+-behaviour(application).
+
+%% Application callbacks
+-export([start/2, stop/1]).
+
+%%====================================================================
+%% API
+%%====================================================================
+
+start(_StartType, _StartArgs) ->
+ Config = get_configuration(),
+ tftp_sup:start_link(Config).
+
+%%--------------------------------------------------------------------
+stop(_State) ->
+ ok.
+
+%%====================================================================
+%% Internal functions
+%%====================================================================
+
+get_configuration() ->
+ case (catch application:get_env(tftp, services)) of
+ {ok, Services} ->
+ Services;
+ _ ->
+ []
+ end.
diff --git a/lib/tftp/src/tftp_binary.erl b/lib/tftp/src/tftp_binary.erl
new file mode 100644
index 0000000000..3438ba235b
--- /dev/null
+++ b/lib/tftp/src/tftp_binary.erl
@@ -0,0 +1,239 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File : tft_binary.erl
+%%% Author : Hakan Mattsson <[email protected]>
+%%% Description :
+%%%
+%%% Created : 24 May 2004 by Hakan Mattsson <[email protected]>
+%%%-------------------------------------------------------------------
+
+-module(tftp_binary).
+
+%%%-------------------------------------------------------------------
+%%% Interface
+%%%-------------------------------------------------------------------
+
+-behaviour(tftp).
+
+-export([prepare/6, open/6, read/1, write/2, abort/3]).
+
+-record(read_state, {options, blksize, bin, is_native_ascii, is_network_ascii, count}).
+-record(write_state, {options, blksize, list, is_native_ascii, is_network_ascii}).
+
+%%-------------------------------------------------------------------
+%% Prepare
+%%-------------------------------------------------------------------
+
+prepare(_Peer, Access, Filename, Mode, SuggestedOptions, Initial) when is_list(Initial) ->
+ %% Client side
+ IsNativeAscii = is_native_ascii(Initial),
+ case catch handle_options(Access, Filename, Mode, SuggestedOptions, IsNativeAscii) of
+ {ok, IsNetworkAscii, AcceptedOptions} when Access =:= read, is_binary(Filename) ->
+ State = #read_state{options = AcceptedOptions,
+ blksize = lookup_blksize(AcceptedOptions),
+ bin = Filename,
+ is_network_ascii = IsNetworkAscii,
+ count = size(Filename),
+ is_native_ascii = IsNativeAscii},
+ {ok, AcceptedOptions, State};
+ {ok, IsNetworkAscii, AcceptedOptions} when Access =:= write, Filename =:= binary ->
+ State = #write_state{options = AcceptedOptions,
+ blksize = lookup_blksize(AcceptedOptions),
+ list = [],
+ is_network_ascii = IsNetworkAscii,
+ is_native_ascii = IsNativeAscii},
+ {ok, AcceptedOptions, State};
+ {ok, _, _} ->
+ {error, {undef, "Illegal callback usage. Mode and filename is incompatible."}};
+ {error, {Code, Text}} ->
+ {error, {Code, Text}}
+ end;
+prepare(_Peer, _Access, _Bin, _Mode, _SuggestedOptions, _Initial) ->
+ {error, {undef, "Illegal callback options."}}.
+
+%%-------------------------------------------------------------------
+%% Open
+%%-------------------------------------------------------------------
+
+open(Peer, Access, Filename, Mode, SuggestedOptions, Initial) when is_list(Initial) ->
+ %% Server side
+ case prepare(Peer, Access, Filename, Mode, SuggestedOptions, Initial) of
+ {ok, AcceptedOptions, State} ->
+ open(Peer, Access, Filename, Mode, AcceptedOptions, State);
+ {error, {Code, Text}} ->
+ {error, {Code, Text}}
+ end;
+open(_Peer, Access, Filename, Mode, NegotiatedOptions, State) when is_record(State, read_state) ->
+ %% Both sides
+ case catch handle_options(Access, Filename, Mode, NegotiatedOptions, State#read_state.is_native_ascii) of
+ {ok, IsNetworkAscii, Options}
+ when Options =:= NegotiatedOptions,
+ IsNetworkAscii =:= State#read_state.is_network_ascii ->
+ {ok, NegotiatedOptions, State};
+ {error, {Code, Text}} ->
+ {error, {Code, Text}}
+ end;
+open(_Peer, Access, Filename, Mode, NegotiatedOptions, State) when is_record(State, write_state) ->
+ %% Both sides
+ case catch handle_options(Access, Filename, Mode, NegotiatedOptions, State#write_state.is_native_ascii) of
+ {ok, IsNetworkAscii, Options}
+ when Options =:= NegotiatedOptions,
+ IsNetworkAscii =:= State#write_state.is_network_ascii ->
+ {ok, NegotiatedOptions, State};
+ {error, {Code, Text}} ->
+ {error, {Code, Text}}
+ end;
+open(Peer, Access, Filename, Mode, NegotiatedOptions, State) ->
+ %% Handle upgrade from old releases. Please, remove this clause in next release.
+ State2 = upgrade_state(State),
+ open(Peer, Access, Filename, Mode, NegotiatedOptions, State2).
+
+%%-------------------------------------------------------------------
+%% Read
+%%-------------------------------------------------------------------
+
+read(#read_state{bin = Bin} = State) when is_binary(Bin) ->
+ BlkSize = State#read_state.blksize,
+ if
+ size(Bin) >= BlkSize ->
+ <<Block:BlkSize/binary, Bin2/binary>> = Bin,
+ State2 = State#read_state{bin = Bin2},
+ {more, Block, State2};
+ size(Bin) < BlkSize ->
+ {last, Bin, State#read_state.count}
+ end;
+read(State) ->
+ %% Handle upgrade from old releases. Please, remove this clause in next release.
+ State2 = upgrade_state(State),
+ read(State2).
+
+%%-------------------------------------------------------------------
+%% Write
+%%-------------------------------------------------------------------
+
+write(Bin, #write_state{list = List} = State) when is_binary(Bin), is_list(List) ->
+ Size = size(Bin),
+ BlkSize = State#write_state.blksize,
+ if
+ Size =:= BlkSize ->
+ {more, State#write_state{list = [Bin | List]}};
+ Size < BlkSize ->
+ Bin2 = list_to_binary(lists:reverse([Bin | List])),
+ {last, Bin2}
+ end;
+write(Bin, State) ->
+ %% Handle upgrade from old releases. Please, remove this clause in next release.
+ State2 = upgrade_state(State),
+ write(Bin, State2).
+
+%%-------------------------------------------------------------------
+%% Abort
+%%-------------------------------------------------------------------
+
+abort(_Code, _Text, #read_state{bin = Bin} = State)
+ when is_record(State, read_state), is_binary(Bin) ->
+ ok;
+abort(_Code, _Text, #write_state{list = List} = State)
+ when is_record(State, write_state), is_list(List) ->
+ ok;
+abort(Code, Text, State) ->
+ %% Handle upgrade from old releases. Please, remove this clause in next release.
+ State2 = upgrade_state(State),
+ abort(Code, Text, State2).
+
+%%-------------------------------------------------------------------
+%% Process options
+%%-------------------------------------------------------------------
+
+handle_options(Access, Bin, Mode, Options, IsNativeAscii) ->
+ IsNetworkAscii = handle_mode(Mode, IsNativeAscii),
+ Options2 = do_handle_options(Access, Bin, Options),
+ {ok, IsNetworkAscii, Options2}.
+
+handle_mode(Mode, IsNativeAscii) ->
+ case Mode of
+ "netascii" when IsNativeAscii =:= true -> true;
+ "octet" -> false;
+ _ -> throw({error, {badop, "Illegal mode " ++ Mode}})
+ end.
+
+do_handle_options(Access, Bin, [{Key, Val} | T]) ->
+ case Key of
+ "tsize" ->
+ case Access of
+ read when Val =:= "0", is_binary(Bin) ->
+ Tsize = integer_to_list(size(Bin)),
+ [{Key, Tsize} | do_handle_options(Access, Bin, T)];
+ _ ->
+ handle_integer(Access, Bin, Key, Val, T, 0, infinity)
+ end;
+ "blksize" ->
+ handle_integer(Access, Bin, Key, Val, T, 8, 65464);
+ "timeout" ->
+ handle_integer(Access, Bin, Key, Val, T, 1, 255);
+ _ ->
+ do_handle_options(Access, Bin, T)
+ end;
+do_handle_options(_Access, _Bin, []) ->
+ [].
+
+
+handle_integer(Access, Bin, Key, Val, Options, Min, Max) ->
+ case catch list_to_integer(Val) of
+ {'EXIT', _} ->
+ do_handle_options(Access, Bin, Options);
+ Int when Int >= Min, Int =< Max ->
+ [{Key, Val} | do_handle_options(Access, Bin, Options)];
+ Int when Int >= Min, Max =:= infinity ->
+ [{Key, Val} | do_handle_options(Access, Bin, Options)];
+ _Int ->
+ throw({error, {badopt, "Illegal " ++ Key ++ " value " ++ Val}})
+ end.
+
+lookup_blksize(Options) ->
+ case lists:keysearch("blksize", 1, Options) of
+ {value, {_, Val}} ->
+ list_to_integer(Val);
+ false ->
+ 512
+ end.
+
+is_native_ascii([]) ->
+ is_native_ascii();
+is_native_ascii([{native_ascii, Bool}]) ->
+ case Bool of
+ true -> true;
+ false -> false
+ end.
+
+is_native_ascii() ->
+ case os:type() of
+ {win32, _} -> true;
+ _ -> false
+ end.
+
+%% Handle upgrade from old releases. Please, remove this function in next release.
+upgrade_state({read_state, Options, Blksize, Bin, IsNetworkAscii, Count}) ->
+ {read_state, Options, Blksize, Bin, false, IsNetworkAscii, Count};
+upgrade_state({write_state, Options, Blksize, List, IsNetworkAscii}) ->
+ {write_state, Options, Blksize, List, false, IsNetworkAscii}.
diff --git a/lib/tftp/src/tftp_engine.erl b/lib/tftp/src/tftp_engine.erl
new file mode 100644
index 0000000000..78a105bcc8
--- /dev/null
+++ b/lib/tftp/src/tftp_engine.erl
@@ -0,0 +1,1422 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%
+%%-------------------------------------------------------------------
+%% Protocol engine for trivial FTP
+%%-------------------------------------------------------------------
+
+-module(tftp_engine).
+
+%%%-------------------------------------------------------------------
+%%% Interface
+%%%-------------------------------------------------------------------
+
+%% application internal functions
+-export([
+ daemon_start/1,
+ daemon_loop/1,
+ daemon_loop/3, %% Handle upgrade from old releases. Please, remove this function in next release.
+ client_start/4,
+ common_loop/6,
+ info/1,
+ change_config/2
+ ]).
+
+%% module internal
+-export([
+ daemon_init/1,
+ server_init/2,
+ client_init/2,
+ wait_for_msg/3,
+ callback/4
+ ]).
+
+%% sys callback functions
+-export([
+ system_continue/3,
+ system_terminate/4,
+ system_code_change/4
+ ]).
+
+-include("tftp.hrl").
+
+-type prep_status() :: 'error' | 'last' | 'more' | 'terminate'.
+
+-record(daemon_state, {config, n_servers, server_tab, file_tab}).
+-record(server_info, {pid, req, peer}).
+-record(file_info, {peer_req, pid}).
+-record(sys_misc, {module, function, arguments}).
+-record(error, {where, code, text, filename}).
+-record(prepared, {status :: prep_status() | 'undefined',
+ result, block_no, next_data, prev_data}).
+-record(transfer_res, {status, decoded_msg, prepared}).
+-define(ERROR(Where, Code, Text, Filename),
+ #error{where = Where, code = Code, text = Text, filename = Filename}).
+
+%%%-------------------------------------------------------------------
+%%% Info
+%%%-------------------------------------------------------------------
+
+info(daemons) ->
+ Daemons = supervisor:which_children(tftp_sup),
+ [{Pid, info(Pid)} || {_, Pid, _, _} <- Daemons];
+info(servers) ->
+ [{Pid, info(Pid)} || {_, {ok, DeamonInfo}} <- info(daemons),
+ {server, Pid} <- DeamonInfo];
+info(ToPid) when is_pid(ToPid) ->
+ call(info, ToPid, timer:seconds(10)).
+
+change_config(daemons, Options) ->
+ Daemons = supervisor:which_children(tftp_sup),
+ [{Pid, change_config(Pid, Options)} || {_, Pid, _, _} <- Daemons];
+change_config(servers, Options) ->
+ [{Pid, change_config(Pid, Options)} || {_, {ok, DeamonInfo}} <- info(daemons),
+ {server, Pid} <- DeamonInfo];
+change_config(ToPid, Options) when is_pid(ToPid) ->
+ BadKeys = [host, port, udp],
+ BadOptions = [{Key, Val} || {Key, Val} <- Options,
+ BadKey <- BadKeys,
+ Key =:= BadKey],
+ case BadOptions of
+ [] ->
+ call({change_config, Options}, ToPid, timer:seconds(10));
+ [{Key, Val} | _] ->
+ {error, {badarg, {Key, Val}}}
+ end.
+
+call(Req, ToPid, Timeout) when is_pid(ToPid) ->
+ Type = process,
+ Ref = erlang:monitor(Type, ToPid),
+ ToPid ! {Req, Ref, self()},
+ receive
+ {Reply, Ref, FromPid} when FromPid =:= ToPid ->
+ erlang:demonitor(Ref, [flush]),
+ Reply;
+ {'DOWN', Ref, Type, FromPid, _Reason} when FromPid =:= ToPid ->
+ {error, timeout}
+ after Timeout ->
+ {error, timeout}
+ end.
+
+reply(Reply, Ref, ToPid) ->
+ ToPid ! {Reply, Ref, self()}.
+
+%%%-------------------------------------------------------------------
+%%% Daemon
+%%%-------------------------------------------------------------------
+
+%% Returns {ok, Port}
+daemon_start(Options) when is_list(Options) ->
+ Config = tftp_lib:parse_config(Options),
+ proc_lib:start_link(?MODULE, daemon_init, [Config], infinity).
+
+daemon_init(Config) when is_record(Config, config),
+ is_pid(Config#config.parent_pid) ->
+ process_flag(trap_exit, true),
+ {Port, UdpOptions} = prepare_daemon_udp(Config),
+ case catch gen_udp:open(Port, UdpOptions) of
+ {ok, Socket} ->
+ {ok, ActualPort} = inet:port(Socket),
+ proc_lib:init_ack({ok, self()}),
+ Config2 = Config#config{udp_socket = Socket,
+ udp_port = ActualPort},
+ print_debug_info(Config2, daemon, open, #tftp_msg_req{filename = ""}),
+ ServerTab = ets:new(tftp_daemon_servers, [{keypos, 2}]),
+ FileTab = ets:new(tftp_daemon_files, [{keypos, 2}]),
+ State = #daemon_state{config = Config2,
+ n_servers = 0,
+ server_tab = ServerTab,
+ file_tab = FileTab},
+ daemon_loop(State);
+ {error, Reason} ->
+ Text = lists:flatten(io_lib:format("UDP open ~p -> ~p", [UdpOptions, Reason])),
+ print_debug_info(Config, daemon, open, ?ERROR(open, undef, Text, "")),
+ exit({gen_udp_open, UdpOptions, Reason});
+ Reason ->
+ Text = lists:flatten(io_lib:format("UDP open ~p -> ~p", [UdpOptions, Reason])),
+ print_debug_info(Config, daemon, open, ?ERROR(open, undef, Text, "")),
+ exit({gen_udp_open, UdpOptions, Reason})
+ end.
+
+prepare_daemon_udp(#config{udp_port = Port, udp_options = UdpOptions} = Config) ->
+ case lists:keymember(fd, 1, UdpOptions) of
+ true ->
+ %% Use explicit fd
+ {Port, UdpOptions};
+ false ->
+ %% Use fd from setuid_socket_wrap, such as -tftpd_69
+ InitArg = list_to_atom("tftpd_" ++ integer_to_list(Port)),
+ case init:get_argument(InitArg) of
+ {ok, [[FdStr]] = Badarg} when is_list(FdStr) ->
+ case catch list_to_integer(FdStr) of
+ Fd when is_integer(Fd) ->
+ {0, [{fd, Fd} | lists:keydelete(ip, 1, UdpOptions)]};
+ {'EXIT', _} ->
+ Text = lists:flatten(io_lib:format("Illegal prebound fd ~p: ~p", [InitArg, Badarg])),
+ print_debug_info(Config, daemon, open, ?ERROR(open, undef, Text, "")),
+ exit({badarg, {prebound_fd, InitArg, Badarg}})
+ end;
+ {ok, Badarg} ->
+ Text = lists:flatten(io_lib:format("Illegal prebound fd ~p: ~p", [InitArg, Badarg])),
+ print_debug_info(Config, daemon, open, ?ERROR(open, undef, Text, "")),
+ exit({badarg, {prebound_fd, InitArg, Badarg}});
+ error ->
+ {Port, UdpOptions}
+ end
+ end.
+
+daemon_loop(DaemonConfig, N, Servers) when is_list(Servers) ->
+ %% Handle upgrade from old releases. Please, remove this function in next release.
+ ServerTab = ets:new(tftp_daemon_servers, [{keypos, 2}]),
+ FileTab = ets:new(tftp_daemon_files, [{keypos, 2}]),
+ State = #daemon_state{config = DaemonConfig,
+ n_servers = N,
+ server_tab = ServerTab,
+ file_tab = FileTab},
+ Req = #tftp_msg_req{filename = dummy},
+ [ets:insert(ServerTab, #server_info{pid = Pid, req = Req, peer = dummy}) || Pid <- Servers],
+ daemon_loop(State).
+
+daemon_loop(#daemon_state{config = DaemonConfig,
+ n_servers = N,
+ server_tab = ServerTab,
+ file_tab = FileTab} = State) when is_record(DaemonConfig, config) ->
+ %% info_msg(DaemonConfig, "=====> TFTP: Daemon #~p\n", [N]), %% XXX
+ receive
+ {info, Ref, FromPid} when is_pid(FromPid) ->
+ Fun = fun(#server_info{pid = Pid}, Acc) -> [{server, Pid} | Acc] end,
+ ServerInfo = ets:foldl(Fun, [], ServerTab),
+ Info = internal_info(DaemonConfig, daemon) ++ [{n_conn, N}] ++ ServerInfo,
+ _ = reply({ok, Info}, Ref, FromPid),
+ ?MODULE:daemon_loop(State);
+ {{change_config, Options}, Ref, FromPid} when is_pid(FromPid) ->
+ case catch tftp_lib:parse_config(Options, DaemonConfig) of
+ {'EXIT', Reason} ->
+ _ = reply({error, Reason}, Ref, FromPid),
+ ?MODULE:daemon_loop(State);
+ DaemonConfig2 when is_record(DaemonConfig2, config) ->
+ _ = reply(ok, Ref, FromPid),
+ ?MODULE:daemon_loop(State#daemon_state{config = DaemonConfig2})
+ end;
+ {udp, Socket, RemoteHost, RemotePort, Bin} when is_binary(Bin) ->
+ _ = inet:setopts(Socket, [{active, once}]),
+ ServerConfig = DaemonConfig#config{parent_pid = self(),
+ udp_host = RemoteHost,
+ udp_port = RemotePort},
+ Msg = (catch tftp_lib:decode_msg(Bin)),
+ print_debug_info(ServerConfig, daemon, recv, Msg),
+ case Msg of
+ Req when is_record(Req, tftp_msg_req),
+ N =< DaemonConfig#config.max_conn ->
+ Peer = peer_info(ServerConfig),
+ PeerReq = {Peer, Req},
+ PeerInfo = lists:flatten(io_lib:format("~p", [Peer])),
+ case ets:lookup(FileTab, PeerReq) of
+ [] ->
+ Args = [ServerConfig, Req],
+ Pid = proc_lib:spawn_link(?MODULE, server_init, Args),
+ ets:insert(ServerTab, #server_info{pid = Pid, req = Req, peer = Peer}),
+ ets:insert(FileTab, #file_info{peer_req = PeerReq, pid = Pid}),
+ ?MODULE:daemon_loop(State#daemon_state{n_servers = N + 1});
+ [#file_info{pid = Pid}] ->
+ %% Yet another request of the file from same peer
+ warning_msg(DaemonConfig, "~p Reuse connection for ~s\n\t~p\n",
+ [Pid, PeerInfo, Req#tftp_msg_req.filename]),
+ ?MODULE:daemon_loop(State)
+ end;
+ Req when is_record(Req, tftp_msg_req) ->
+ Reply = #tftp_msg_error{code = enospc, text = "Too many connections"},
+ Peer = peer_info(ServerConfig),
+ PeerInfo = lists:flatten(io_lib:format("~p", [Peer])),
+ warning_msg(DaemonConfig,
+ "Daemon has too many connections (~p)."
+ "\n\tRejecting request from ~s\n",
+ [N, PeerInfo]),
+ send_msg(ServerConfig, daemon, Reply),
+ ?MODULE:daemon_loop(State);
+ {'EXIT', Reply} when is_record(Reply, tftp_msg_error) ->
+ send_msg(ServerConfig, daemon, Reply),
+ ?MODULE:daemon_loop(State);
+ Req ->
+ Reply = #tftp_msg_error{code = badop,
+ text = "Illegal TFTP operation"},
+ warning_msg(DaemonConfig, "Daemon received: ~p.\n\tfrom ~p:~p",
+ [Req, RemoteHost, RemotePort]),
+ send_msg(ServerConfig, daemon, Reply),
+ ?MODULE:daemon_loop(State)
+ end;
+ {system, From, Msg} ->
+ Misc = #sys_misc{module = ?MODULE, function = daemon_loop, arguments = [State]},
+ sys:handle_system_msg(Msg, From, DaemonConfig#config.parent_pid, ?MODULE, [], Misc);
+ {'EXIT', Pid, Reason} when DaemonConfig#config.parent_pid =:= Pid ->
+ close_port(DaemonConfig, daemon, #tftp_msg_req{filename = ""}),
+ exit(Reason);
+ {'EXIT', Pid, _Reason} = Info ->
+ case ets:lookup(ServerTab, Pid) of
+ [] ->
+ warning_msg(DaemonConfig, "Daemon received: ~p", [Info]),
+ ?MODULE:daemon_loop(State);
+ [#server_info{req = Req, peer = Peer}] ->
+ PeerReq = {Peer, Req},
+ ets:delete(FileTab, PeerReq),
+ ets:delete(ServerTab, Pid),
+ ?MODULE:daemon_loop(State#daemon_state{n_servers = N - 1})
+ end;
+ Info ->
+ warning_msg(DaemonConfig, "Daemon received: ~p", [Info]),
+ ?MODULE:daemon_loop(State)
+ end;
+daemon_loop(#daemon_state{config = Config} = State) ->
+ %% Handle upgrade from old releases. Please, remove this clause in next release.
+ Config2 = upgrade_config(Config),
+ daemon_loop(State#daemon_state{config = Config2}).
+
+upgrade_config({config, ParentPid, UdpSocket, UdpOptions, UdpHost, UdpPort, PortPolicy,
+ UseTsize, MaxTsize, MaxConn, Rejected, PoliteAck, DebugLevel,
+ Timeout, UserOptions, Callbacks}) ->
+ Callbacks2 = tftp_lib:add_default_callbacks(Callbacks),
+ Logger = tftp_logger,
+ MaxRetries = 5,
+ {config, ParentPid, UdpSocket, UdpOptions, UdpHost, UdpPort, PortPolicy,
+ UseTsize, MaxTsize, MaxConn, Rejected, PoliteAck, DebugLevel,
+ Timeout, UserOptions, Callbacks2, Logger, MaxRetries}.
+
+%%%-------------------------------------------------------------------
+%%% Server
+%%%-------------------------------------------------------------------
+
+server_init(Config, Req) when is_record(Config, config),
+ is_pid(Config#config.parent_pid),
+ is_record(Req, tftp_msg_req) ->
+ process_flag(trap_exit, true),
+ %% Config =
+ %% case os:getenv("TFTPDEBUG") of
+ %% false ->
+ %% Config0;
+ %% DebugLevel ->
+ %% Config0#config{debug_level = list_to_atom(DebugLevel)}
+ %% end,
+ SuggestedOptions = Req#tftp_msg_req.options,
+ UdpOptions = Config#config.udp_options,
+ UdpOptions2 = lists:keydelete(fd, 1, UdpOptions),
+ Config1 = Config#config{udp_options = UdpOptions2},
+ Config2 = tftp_lib:parse_config(SuggestedOptions, Config1),
+ SuggestedOptions2 = Config2#config.user_options,
+ Req2 = Req#tftp_msg_req{options = SuggestedOptions2},
+ case open_free_port(Config2, server, Req2) of
+ {ok, Config3} ->
+ Filename = Req#tftp_msg_req.filename,
+ case match_callback(Filename, Config3#config.callbacks) of
+ {ok, Callback} ->
+ print_debug_info(Config3, server, match, Callback),
+ case pre_verify_options(Config3, Req2) of
+ ok ->
+ case callback({open, server_open}, Config3, Callback, Req2) of
+ {Callback2, {ok, AcceptedOptions}} ->
+ {LocalAccess, _} = local_file_access(Req2),
+ OptText = "Internal error. Not allowed to add new options.",
+ case post_verify_options(Config3, Req2, AcceptedOptions, OptText) of
+ {ok, Config4, Req3} when AcceptedOptions =/= [] ->
+ Reply = #tftp_msg_oack{options = AcceptedOptions},
+ BlockNo =
+ case LocalAccess of
+ read -> 0;
+ write -> 1
+ end,
+ {Config5, Callback3, TransferRes} =
+ transfer(Config4, Callback2, Req3, Reply, LocalAccess, BlockNo, #prepared{}),
+ common_loop(Config5, Callback3, Req3, TransferRes, LocalAccess, BlockNo);
+ {ok, Config4, Req3} when LocalAccess =:= write ->
+ BlockNo = 0,
+ common_ack(Config4, Callback2, Req3, LocalAccess, BlockNo, #prepared{});
+ {ok, Config4, Req3} when LocalAccess =:= read ->
+ BlockNo = 0,
+ common_read(Config4, Callback2, Req3, LocalAccess, BlockNo, BlockNo, #prepared{});
+ {error, {Code, Text}} ->
+ {undefined, Error} =
+ callback({abort, {Code, Text}}, Config3, Callback2, Req2),
+ send_msg(Config3, Req, Error),
+ terminate(Config3, Req2, ?ERROR(post_verify_options, Code, Text, Req2#tftp_msg_req.filename))
+ end;
+ {undefined, #tftp_msg_error{code = Code, text = Text} = Error} ->
+ send_msg(Config3, Req, Error),
+ terminate(Config3, Req, ?ERROR(server_open, Code, Text, Req2#tftp_msg_req.filename))
+ end;
+ {error, {Code, Text}} ->
+ {undefined, Error} =
+ callback({abort, {Code, Text}}, Config2, Callback, Req2),
+ send_msg(Config2, Req, Error),
+ terminate(Config2, Req2, ?ERROR(pre_verify_options, Code, Text, Req2#tftp_msg_req.filename))
+ end;
+ {error, #tftp_msg_error{code = Code, text = Text} = Error} ->
+ send_msg(Config3, Req, Error),
+ terminate(Config3, Req, ?ERROR(match_callback, Code, Text, Req2#tftp_msg_req.filename))
+ end;
+ #error{} = Error ->
+ terminate(Config2, Req, Error)
+ end;
+server_init(Config, Req) when is_record(Req, tftp_msg_req) ->
+ Config2 = upgrade_config(Config),
+ server_init(Config2, Req).
+
+%%%-------------------------------------------------------------------
+%%% Client
+%%%-------------------------------------------------------------------
+
+%% LocalFilename = filename() | 'binary' | binary()
+%% Returns {ok, LastCallbackState} | {error, Reason}
+client_start(Access, RemoteFilename, LocalFilename, Options) ->
+ Config = tftp_lib:parse_config(Options),
+ Config2 = Config#config{parent_pid = self(),
+ udp_socket = undefined},
+ Req = #tftp_msg_req{access = Access,
+ filename = RemoteFilename,
+ mode = lookup_mode(Config2#config.user_options),
+ options = Config2#config.user_options,
+ local_filename = LocalFilename},
+ Args = [Config2, Req],
+ case proc_lib:start_link(?MODULE, client_init, Args, infinity) of
+ {ok, LastCallbackState} ->
+ {ok, LastCallbackState};
+ {error, Error} ->
+ {error, Error}
+ end.
+
+client_init(Config, Req) when is_record(Config, config),
+ is_pid(Config#config.parent_pid),
+ is_record(Req, tftp_msg_req) ->
+ process_flag(trap_exit, true),
+ %% Config =
+ %% case os:getenv("TFTPDEBUG") of
+ %% false ->
+ %% Config0;
+ %% "none" ->
+ %% Config0;
+ %% DebugLevel ->
+ %% info_msg(Config, "TFTPDEBUG: ~s\n", [DebugLevel]),
+ %% Config0#config{debug_level = list_to_atom(DebugLevel)}
+ %% end,
+ case open_free_port(Config, client, Req) of
+ {ok, Config2} ->
+ Req2 =
+ case Config2#config.use_tsize of
+ true ->
+ SuggestedOptions = Req#tftp_msg_req.options,
+ SuggestedOptions2 = tftp_lib:replace_val("tsize", "0", SuggestedOptions),
+ Req#tftp_msg_req{options = SuggestedOptions2};
+ false ->
+ Req
+ end,
+ LocalFilename = Req2#tftp_msg_req.local_filename,
+ case match_callback(LocalFilename, Config2#config.callbacks) of
+ {ok, Callback} ->
+ print_debug_info(Config2, client, match, Callback),
+ client_prepare(Config2, Callback, Req2);
+ {error, #tftp_msg_error{code = Code, text = Text}} ->
+ terminate(Config, Req, ?ERROR(match, Code, Text, Req#tftp_msg_req.filename))
+ end;
+ #error{} = Error ->
+ terminate(Config, Req, Error)
+ end.
+
+client_prepare(Config, Callback, Req) when is_record(Req, tftp_msg_req) ->
+ case pre_verify_options(Config, Req) of
+ ok ->
+ case callback({open, client_prepare}, Config, Callback, Req) of
+ {Callback2, {ok, AcceptedOptions}} ->
+ OptText = "Internal error. Not allowed to add new options.",
+ case post_verify_options(Config, Req, AcceptedOptions, OptText) of
+ {ok, Config2, Req2} ->
+ {LocalAccess, _} = local_file_access(Req2),
+ BlockNo = 0,
+ {Config3, Callback3, TransferRes} =
+ transfer(Config2, Callback2, Req2, Req2, LocalAccess, BlockNo, #prepared{}),
+ client_open(Config3, Callback3, Req2, BlockNo, TransferRes);
+ {error, {Code, Text}} ->
+ _ = callback({abort, {Code, Text}}, Config, Callback2, Req),
+ terminate(Config, Req, ?ERROR(post_verify_options, Code, Text, Req#tftp_msg_req.filename))
+ end;
+ {undefined, #tftp_msg_error{code = Code, text = Text}} ->
+ terminate(Config, Req, ?ERROR(client_prepare, Code, Text, Req#tftp_msg_req.filename))
+ end;
+ {error, {Code, Text}} ->
+ _ = callback({abort, {Code, Text}}, Config, Callback, Req),
+ terminate(Config, Req, ?ERROR(pre_verify_options, Code, Text, Req#tftp_msg_req.filename))
+ end.
+
+client_open(Config, Callback, Req, BlockNo, #transfer_res{status = Status, decoded_msg = DecodedMsg, prepared = Prepared}) ->
+ {LocalAccess, _} = local_file_access(Req),
+ case Status of
+ ok when is_record(Prepared, prepared) ->
+ case DecodedMsg of
+ Msg when is_record(Msg, tftp_msg_oack) ->
+ ServerOptions = Msg#tftp_msg_oack.options,
+ OptText = "Protocol violation. Server is not allowed new options",
+ case post_verify_options(Config, Req, ServerOptions, OptText) of
+ {ok, Config2, Req2} ->
+ {Config3, Callback2, Req3} =
+ do_client_open(Config2, Callback, Req2),
+ case LocalAccess of
+ read ->
+ common_read(Config3, Callback2, Req3, LocalAccess, BlockNo, BlockNo, Prepared);
+ write ->
+ common_ack(Config3, Callback2, Req3, LocalAccess, BlockNo, Prepared)
+ end;
+ {error, {Code, Text}} ->
+ {undefined, Error} =
+ callback({abort, {Code, Text}}, Config, Callback, Req),
+ send_msg(Config, Req, Error),
+ terminate(Config, Req, ?ERROR(verify_server_options, Code, Text, Req#tftp_msg_req.filename))
+ end;
+ #tftp_msg_ack{block_no = ActualBlockNo} when LocalAccess =:= read ->
+ Req2 = Req#tftp_msg_req{options = []},
+ {Config2, Callback2, Req2} = do_client_open(Config, Callback, Req2),
+ ExpectedBlockNo = 0,
+ common_read(Config2, Callback2, Req2, LocalAccess, ExpectedBlockNo, ActualBlockNo, Prepared);
+ #tftp_msg_data{block_no = ActualBlockNo, data = Data} when LocalAccess =:= write ->
+ Req2 = Req#tftp_msg_req{options = []},
+ {Config2, Callback2, Req2} = do_client_open(Config, Callback, Req2),
+ ExpectedBlockNo = 1,
+ common_write(Config2, Callback2, Req2, LocalAccess, ExpectedBlockNo, ActualBlockNo, Data, Prepared);
+ %% #tftp_msg_error{code = Code, text = Text} when Req#tftp_msg_req.options =/= [] ->
+ %% %% Retry without options
+ %% callback({abort, {Code, Text}}, Config, Callback, Req),
+ %% Req2 = Req#tftp_msg_req{options = []},
+ %% client_prepare(Config, Callback, Req2);
+ #tftp_msg_error{code = Code, text = Text} ->
+ _ = callback({abort, {Code, Text}}, Config, Callback, Req),
+ terminate(Config, Req, ?ERROR(client_open, Code, Text, Req#tftp_msg_req.filename));
+ {'EXIT', #tftp_msg_error{code = Code, text = Text}} ->
+ _ = callback({abort, {Code, Text}}, Config, Callback, Req),
+ terminate(Config, Req, ?ERROR(client_open, Code, Text, Req#tftp_msg_req.filename));
+ Msg when is_tuple(Msg) ->
+ Code = badop,
+ Text = "Illegal TFTP operation",
+ {undefined, Error} =
+ callback({abort, {Code, Text}}, Config, Callback, Req),
+ send_msg(Config, Req, Error),
+ Text2 = lists:flatten([Text, ". ", io_lib:format("~p", [element(1, Msg)])]),
+ terminate(Config, Req, ?ERROR(client_open, Code, Text2, Req#tftp_msg_req.filename))
+ end;
+ error when is_record(Prepared, tftp_msg_error) ->
+ #tftp_msg_error{code = Code, text = Text} = Prepared,
+ _ = callback({abort, {Code, Text}}, Config, Callback, Req),
+ terminate(Config, Req, ?ERROR(client_open, Code, Text, Req#tftp_msg_req.filename))
+ end.
+
+do_client_open(Config, Callback, Req) ->
+ case callback({open, client_open}, Config, Callback, Req) of
+ {Callback2, {ok, FinalOptions}} ->
+ OptText = "Internal error. Not allowed to change options.",
+ case post_verify_options(Config, Req, FinalOptions, OptText) of
+ {ok, Config2, Req2} ->
+ {Config2, Callback2, Req2};
+ {error, {Code, Text}} ->
+ {undefined, Error} =
+ callback({abort, {Code, Text}}, Config, Callback2, Req),
+ send_msg(Config, Req, Error),
+ terminate(Config, Req, ?ERROR(post_verify_options, Code, Text, Req#tftp_msg_req.filename))
+ end;
+ {undefined, #tftp_msg_error{code = Code, text = Text} = Error} ->
+ send_msg(Config, Req, Error),
+ terminate(Config, Req, ?ERROR(client_open, Code, Text, Req#tftp_msg_req.filename))
+ end.
+
+%%%-------------------------------------------------------------------
+%%% Common loop for both client and server
+%%%-------------------------------------------------------------------
+
+common_loop(Config, Callback, Req, #transfer_res{status = Status, decoded_msg = DecodedMsg, prepared = Prepared}, LocalAccess, ExpectedBlockNo)
+ when is_record(Config, config)->
+ %% Config =
+ %% case os:getenv("TFTPMAX") of
+ %% false ->
+ %% Config0;
+ %% MaxBlockNoStr when Config0#config.debug_level =/= none ->
+ %% case list_to_integer(MaxBlockNoStr) of
+ %% MaxBlockNo when ExpectedBlockNo > MaxBlockNo ->
+ %% info_msg(Config, "TFTPMAX: ~p\n", [MaxBlockNo]),
+ %% info_msg(Config, "TFTPDEBUG: none\n", []),
+ %% Config0#config{debug_level = none};
+ %% _ ->
+ %% Config0
+ %% end;
+ %% _MaxBlockNoStr ->
+ %% Config0
+ %% end,
+ case Status of
+ ok when is_record(Prepared, prepared) ->
+ case DecodedMsg of
+ #tftp_msg_ack{block_no = ActualBlockNo} when LocalAccess =:= read ->
+ common_read(Config, Callback, Req, LocalAccess, ExpectedBlockNo, ActualBlockNo, Prepared);
+ #tftp_msg_data{block_no = ActualBlockNo, data = Data} when LocalAccess =:= write ->
+ common_write(Config, Callback, Req, LocalAccess, ExpectedBlockNo, ActualBlockNo, Data, Prepared);
+ #tftp_msg_error{code = Code, text = Text} ->
+ _ = callback({abort, {Code, Text}}, Config, Callback, Req),
+ terminate(Config, Req, ?ERROR(common_loop, Code, Text, Req#tftp_msg_req.filename));
+ {'EXIT', #tftp_msg_error{code = Code, text = Text} = Error} ->
+ _ = callback({abort, {Code, Text}}, Config, Callback, Req),
+ send_msg(Config, Req, Error),
+ terminate(Config, Req, ?ERROR(common_loop, Code, Text, Req#tftp_msg_req.filename));
+ Msg when is_tuple(Msg) ->
+ Code = badop,
+ Text = "Illegal TFTP operation",
+ {undefined, Error} =
+ callback({abort, {Code, Text}}, Config, Callback, Req),
+ send_msg(Config, Req, Error),
+ Text2 = lists:flatten([Text, ". ", io_lib:format("~p", [element(1, Msg)])]),
+ terminate(Config, Req, ?ERROR(common_loop, Code, Text2, Req#tftp_msg_req.filename))
+ end;
+ error when is_record(Prepared, tftp_msg_error) ->
+ #tftp_msg_error{code = Code, text = Text} = Prepared,
+ send_msg(Config, Req, Prepared),
+ terminate(Config, Req, ?ERROR(transfer, Code, Text, Req#tftp_msg_req.filename))
+ end;
+common_loop(Config, Callback, Req, TransferRes, LocalAccess, ExpectedBlockNo) ->
+ %% Handle upgrade from old releases. Please, remove this clause in next release.
+ Config2 = upgrade_config(Config),
+ common_loop(Config2, Callback, Req, TransferRes, LocalAccess, ExpectedBlockNo).
+
+-spec common_read(#config{}, #callback{}, _, 'read', _, _, #prepared{}) -> no_return().
+
+common_read(Config, _, Req, _, _, _, #prepared{status = terminate, result = Result}) ->
+ terminate(Config, Req, {ok, Result});
+common_read(Config, Callback, Req, LocalAccess, ExpectedBlockNo, ActualBlockNo, Prepared)
+ when ActualBlockNo =:= ExpectedBlockNo, is_record(Prepared, prepared) ->
+ case early_read(Config, Callback, Req, LocalAccess, ActualBlockNo, Prepared) of
+ {Callback2, #prepared{status = more, next_data = Data} = Prepared2} when is_binary(Data) ->
+ Prepared3 = Prepared2#prepared{prev_data = Data, next_data = undefined},
+ do_common_read(Config, Callback2, Req, LocalAccess, ActualBlockNo, Data, Prepared3);
+ {undefined, #prepared{status = last, next_data = Data} = Prepared2} when is_binary(Data) ->
+ Prepared3 = Prepared2#prepared{status = terminate},
+ do_common_read(Config, undefined, Req, LocalAccess, ActualBlockNo, Data, Prepared3);
+ {undefined, #prepared{status = error, result = Error}} ->
+ #tftp_msg_error{code = Code, text = Text} = Error,
+ send_msg(Config, Req, Error),
+ terminate(Config, Req, ?ERROR(read, Code, Text, Req#tftp_msg_req.filename))
+ end;
+common_read(Config, Callback, Req, LocalAccess, ExpectedBlockNo, ActualBlockNo, Prepared)
+ when ActualBlockNo =:= (ExpectedBlockNo - 1), is_record(Prepared, prepared) ->
+ case Prepared of
+ #prepared{status = more, prev_data = Data} when is_binary(Data) ->
+ do_common_read(Config, Callback, Req, LocalAccess, ActualBlockNo, Data, Prepared);
+ #prepared{status = last, prev_data = Data} when is_binary(Data) ->
+ do_common_read(Config, Callback, Req, LocalAccess, ActualBlockNo, Data, Prepared);
+ #prepared{status = error, result = Error} ->
+ #tftp_msg_error{code = Code, text = Text} = Error,
+ send_msg(Config, Req, Error),
+ terminate(Config, Req, ?ERROR(read, Code, Text, Req#tftp_msg_req.filename))
+ end;
+common_read(Config, Callback, Req, LocalAccess, ExpectedBlockNo, ActualBlockNo, Prepared)
+ when ActualBlockNo =< ExpectedBlockNo, is_record(Prepared, prepared) ->
+ %% error_logger:error_msg("TFTP READ ~s: Expected block ~p but got block ~p - IGNORED\n",
+ %% [Req#tftp_msg_req.filename, ExpectedBlockNo, ActualBlockNo]),
+ case Prepared of
+ #prepared{status = more, prev_data = Data} when is_binary(Data) ->
+ Reply = #tftp_msg_data{block_no = ExpectedBlockNo, data = Data},
+ {Config2, Callback2, TransferRes} =
+ wait_for_msg_and_handle_timeout(Config, Callback, Req, Reply, LocalAccess, ExpectedBlockNo, Prepared),
+ ?MODULE:common_loop(Config2, Callback2, Req, TransferRes, LocalAccess, ExpectedBlockNo);
+ #prepared{status = last, prev_data = Data} when is_binary(Data) ->
+ Reply = #tftp_msg_data{block_no = ExpectedBlockNo, data = Data},
+ {Config2, Callback2, TransferRes} =
+ wait_for_msg_and_handle_timeout(Config, Callback, Req, Reply, LocalAccess, ExpectedBlockNo, Prepared),
+ ?MODULE:common_loop(Config2, Callback2, Req, TransferRes, LocalAccess, ExpectedBlockNo);
+ #prepared{status = error, result = Error} ->
+ #tftp_msg_error{code = Code, text = Text} = Error,
+ send_msg(Config, Req, Error),
+ terminate(Config, Req, ?ERROR(read, Code, Text, Req#tftp_msg_req.filename))
+ end;
+common_read(Config, Callback, Req, _LocalAccess, ExpectedBlockNo, ActualBlockNo, Prepared)
+ when is_record(Prepared, prepared) ->
+ Code = badblk,
+ Text = "Unknown transfer ID = " ++
+ integer_to_list(ActualBlockNo) ++ " (" ++ integer_to_list(ExpectedBlockNo) ++ ")",
+ {undefined, Error} =
+ callback({abort, {Code, Text}}, Config, Callback, Req),
+ send_msg(Config, Req, Error),
+ terminate(Config, Req, ?ERROR(read, Code, Text, Req#tftp_msg_req.filename)).
+
+-spec do_common_read(#config{}, #callback{} | undefined, _, 'read', integer(), binary(), #prepared{}) -> no_return().
+
+do_common_read(Config, Callback, Req, LocalAccess, BlockNo, Data, Prepared)
+ when is_binary(Data), is_record(Prepared, prepared) ->
+ NextBlockNo = (BlockNo + 1) rem 65536,
+ Reply = #tftp_msg_data{block_no = NextBlockNo, data = Data},
+ {Config2, Callback2, TransferRes} =
+ transfer(Config, Callback, Req, Reply, LocalAccess, NextBlockNo, Prepared),
+ ?MODULE:common_loop(Config2, Callback2, Req, TransferRes, LocalAccess, NextBlockNo).
+
+-spec common_write(#config{}, #callback{}, _, 'write', integer(), integer(), _, #prepared{}) -> no_return().
+
+common_write(Config, _, Req, _, _, _, _, #prepared{status = terminate, result = Result}) ->
+ terminate(Config, Req, {ok, Result});
+common_write(Config, Callback, Req, LocalAccess, ExpectedBlockNo, ActualBlockNo, Data, Prepared)
+ when ActualBlockNo =:= ExpectedBlockNo, is_binary(Data), is_record(Prepared, prepared) ->
+ case callback({write, Data}, Config, Callback, Req) of
+ {Callback2, #prepared{status = more} = Prepared2} ->
+ common_ack(Config, Callback2, Req, LocalAccess, ActualBlockNo, Prepared2);
+ {undefined, #prepared{status = last, result = Result} = Prepared2} ->
+ Config2 = pre_terminate(Config, Req, {ok, Result}),
+ Prepared3 = Prepared2#prepared{status = terminate},
+ common_ack(Config2, undefined, Req, LocalAccess, ActualBlockNo, Prepared3);
+ {undefined, #prepared{status = error, result = Error}} ->
+ #tftp_msg_error{code = Code, text = Text} = Error,
+ send_msg(Config, Req, Error),
+ terminate(Config, Req, ?ERROR(write, Code, Text, Req#tftp_msg_req.filename))
+ end;
+common_write(Config, Callback, Req, LocalAccess, ExpectedBlockNo, ActualBlockNo, Data, Prepared)
+ when ActualBlockNo =:= (ExpectedBlockNo - 1), is_binary(Data), is_record(Prepared, prepared) ->
+ common_ack(Config, Callback, Req, LocalAccess, ExpectedBlockNo - 1, Prepared);
+common_write(Config, Callback, Req, LocalAccess, ExpectedBlockNo, ActualBlockNo, Data, Prepared)
+ when ActualBlockNo =< ExpectedBlockNo, is_binary(Data), is_record(Prepared, prepared) ->
+ %% error_logger:error_msg("TFTP WRITE ~s: Expected block ~p but got block ~p - IGNORED\n",
+ %% [Req#tftp_msg_req.filename, ExpectedBlockNo, ActualBlockNo]),
+ Reply = #tftp_msg_ack{block_no = ExpectedBlockNo},
+ {Config2, Callback2, TransferRes} =
+ wait_for_msg_and_handle_timeout(Config, Callback, Req, Reply, LocalAccess, ExpectedBlockNo, Prepared),
+ ?MODULE:common_loop(Config2, Callback2, Req, TransferRes, LocalAccess, ExpectedBlockNo);
+common_write(Config, Callback, Req, _, ExpectedBlockNo, ActualBlockNo, Data, Prepared)
+ when is_binary(Data), is_record(Prepared, prepared) ->
+ Code = badblk,
+ Text = "Unknown transfer ID = " ++
+ integer_to_list(ActualBlockNo) ++ " (" ++ integer_to_list(ExpectedBlockNo) ++ ")",
+ {undefined, Error} =
+ callback({abort, {Code, Text}}, Config, Callback, Req),
+ send_msg(Config, Req, Error),
+ terminate(Config, Req, ?ERROR(write, Code, Text, Req#tftp_msg_req.filename)).
+
+common_ack(Config, Callback, Req, LocalAccess, BlockNo, Prepared)
+ when is_record(Prepared, prepared) ->
+ Reply = #tftp_msg_ack{block_no = BlockNo},
+ NextBlockNo = (BlockNo + 1) rem 65536,
+ {Config2, Callback2, TransferRes} =
+ transfer(Config, Callback, Req, Reply, LocalAccess, NextBlockNo, Prepared),
+ ?MODULE:common_loop(Config2, Callback2, Req, TransferRes, LocalAccess, NextBlockNo).
+
+pre_terminate(Config, Req, Result) ->
+ if
+ Req#tftp_msg_req.local_filename =/= undefined,
+ Config#config.parent_pid =/= undefined ->
+ proc_lib:init_ack(Result),
+ unlink(Config#config.parent_pid),
+ Config#config{parent_pid = undefined, polite_ack = true};
+ true ->
+ Config#config{polite_ack = true}
+ end.
+
+-spec terminate(#config{}, #tftp_msg_req{}, {'ok', _} | #error{}) -> no_return().
+
+terminate(Config, Req, Result) ->
+ Result2 =
+ case Result of
+ {ok, _} ->
+ Result;
+ #error{where = Where, code = Code, text = Text} = Error ->
+ print_debug_info(Config, Req, Where, Error#error{filename = Req#tftp_msg_req.filename}),
+ {error, {Where, Code, Text}}
+ end,
+ if
+ Config#config.parent_pid =:= undefined ->
+ close_port(Config, client, Req),
+ exit(normal);
+ Req#tftp_msg_req.local_filename =/= undefined ->
+ %% Client
+ close_port(Config, client, Req),
+ proc_lib:init_ack(Result2),
+ unlink(Config#config.parent_pid),
+ exit(normal);
+ true ->
+ %% Server
+ close_port(Config, server, Req),
+ exit(shutdown)
+ end.
+
+close_port(Config, Who, Req) when is_record(Req, tftp_msg_req) ->
+ case Config#config.udp_socket of
+ undefined ->
+ ignore;
+ Socket ->
+ print_debug_info(Config, Who, close, Req),
+ gen_udp:close(Socket)
+ end.
+
+open_free_port(Config, Who, Req) when is_record(Config, config), is_record(Req, tftp_msg_req) ->
+ UdpOptions = Config#config.udp_options,
+ case Config#config.port_policy of
+ random ->
+ %% BUGBUG: Should be a random port
+ case catch gen_udp:open(0, UdpOptions) of
+ {ok, Socket} ->
+ Config2 = Config#config{udp_socket = Socket},
+ print_debug_info(Config2, Who, open, Req),
+ {ok, Config2};
+ {error, Reason} ->
+ Text = lists:flatten(io_lib:format("UDP open ~p -> ~p", [[0 | UdpOptions], Reason])),
+ ?ERROR(open, undef, Text, Req#tftp_msg_req.filename);
+ {'EXIT', _} = Reason ->
+ Text = lists:flatten(io_lib:format("UDP open ~p -> ~p", [[0 | UdpOptions], Reason])),
+ ?ERROR(open, undef, Text, Req#tftp_msg_req.filename)
+ end;
+ {range, Port, Max} when Port =< Max ->
+ case catch gen_udp:open(Port, UdpOptions) of
+ {ok, Socket} ->
+ Config2 = Config#config{udp_socket = Socket},
+ print_debug_info(Config2, Who, open, Req),
+ {ok, Config2};
+ {error, eaddrinuse} ->
+ PortPolicy = {range, Port + 1, Max},
+ Config2 = Config#config{port_policy = PortPolicy},
+ open_free_port(Config2, Who, Req);
+ {error, Reason} ->
+ Text = lists:flatten(io_lib:format("UDP open ~p -> ~p", [[Port | UdpOptions], Reason])),
+ ?ERROR(open, undef, Text, Req#tftp_msg_req.filename);
+ {'EXIT', _} = Reason->
+ Text = lists:flatten(io_lib:format("UDP open ~p -> ~p", [[Port | UdpOptions], Reason])),
+ ?ERROR(open, undef, Text, Req#tftp_msg_req.filename)
+ end;
+ {range, Port, _Max} ->
+ Reason = "Port range exhausted",
+ Text = lists:flatten(io_lib:format("UDP open ~p -> ~p", [[Port | UdpOptions], Reason])),
+ ?ERROR(Who, undef, Text, Req#tftp_msg_req.filename)
+ end.
+
+%%-------------------------------------------------------------------
+%% Transfer
+%%-------------------------------------------------------------------
+
+%% Returns {Config, Callback, #transfer_res{}}
+transfer(Config, Callback, Req, Msg, LocalAccess, NextBlockNo, Prepared)
+ when is_record(Prepared, prepared) ->
+ IoList = tftp_lib:encode_msg(Msg),
+ Retries = Config#config.max_retries + 1,
+ do_transfer(Config, Callback, Req, Msg, IoList, LocalAccess, NextBlockNo, Prepared, Retries).
+
+do_transfer(Config, Callback, Req, Msg, IoList, LocalAccess, NextBlockNo, Prepared, Retries)
+ when is_record(Prepared, prepared), is_integer(Retries), Retries >= 0 ->
+ case do_send_msg(Config, Req, Msg, IoList) of
+ ok ->
+ {Callback2, Prepared2} =
+ early_read(Config, Callback, Req, LocalAccess, NextBlockNo, Prepared),
+ do_wait_for_msg_and_handle_timeout(Config, Callback2, Req, Msg, IoList, LocalAccess, NextBlockNo, Prepared2, Retries);
+ {error, _Reason} when Retries > 0 ->
+ Retries2 = 0, % Just retry once when send fails
+ do_transfer(Config, Callback, Req, Msg, IoList, LocalAccess, NextBlockNo, Prepared, Retries2);
+ {error, Reason} ->
+ Code = undef,
+ Text = lists:flatten(io_lib:format("Transfer failed - giving up -> ~p", [Reason])),
+ Error = #tftp_msg_error{code = Code, text = Text},
+ {Config, Callback, #transfer_res{status = error, prepared = Error}}
+ end.
+
+wait_for_msg_and_handle_timeout(Config, Callback, Req, Msg, LocalAccess, NextBlockNo, Prepared) ->
+ IoList = tftp_lib:encode_msg(Msg),
+ Retries = Config#config.max_retries + 1,
+ do_wait_for_msg_and_handle_timeout(Config, Callback, Req, Msg, IoList, LocalAccess, NextBlockNo, Prepared, Retries).
+
+do_wait_for_msg_and_handle_timeout(Config, Callback, Req, Msg, IoList, LocalAccess, NextBlockNo, Prepared, Retries) ->
+ Code = undef,
+ Text = "Transfer timed out.",
+ case wait_for_msg(Config, Callback, Req) of
+ timeout when Config#config.polite_ack =:= true ->
+ do_send_msg(Config, Req, Msg, IoList),
+ case Prepared of
+ #prepared{status = terminate, result = Result} ->
+ terminate(Config, Req, {ok, Result});
+ #prepared{} ->
+ terminate(Config, Req, ?ERROR(transfer, Code, Text, Req#tftp_msg_req.filename))
+ end;
+ timeout when Retries > 0 ->
+ Retries2 = Retries - 1,
+ do_transfer(Config, Callback, Req, Msg, IoList, LocalAccess, NextBlockNo, Prepared, Retries2);
+ timeout ->
+ Error = #tftp_msg_error{code = Code, text = Text},
+ {Config, Callback, #transfer_res{status = error, prepared = Error}};
+ {Config2, DecodedMsg} ->
+ {Config2, Callback, #transfer_res{status = ok, decoded_msg = DecodedMsg, prepared = Prepared}}
+ end.
+
+send_msg(Config, Req, Msg) ->
+ case catch tftp_lib:encode_msg(Msg) of
+ {'EXIT', Reason} ->
+ Code = undef,
+ Text = "Internal error. Encode failed",
+ Msg2 = #tftp_msg_error{code = Code, text = Text, details = Reason},
+ send_msg(Config, Req, Msg2);
+ IoList ->
+ do_send_msg(Config, Req, Msg, IoList)
+ end.
+
+do_send_msg(#config{udp_socket = Socket, udp_host = RemoteHost, udp_port = RemotePort} = Config, Req, Msg, IoList) ->
+ %% {ok, LocalPort} = inet:port(Socket),
+ %% if
+ %% LocalPort =/= ?TFTP_DEFAULT_PORT ->
+ %% ok;
+ %% true ->
+ %% print_debug_info(Config#config{debug_level = all}, Req, send, Msg),
+ %% error(Config,
+ %% "Daemon replies from the default port (~p)\n\t to ~p:~p\n\t¨~p\n",
+ %% [LocalPort, RemoteHost, RemotePort, Msg])
+ %% end,
+
+ print_debug_info(Config, Req, send, Msg),
+
+ %% case os:getenv("TFTPDUMP") of
+ %% false ->
+ %% ignore;
+ %% DumpPath ->
+ %% trace_udp_send(Req, Msg, IoList, DumpPath)
+ %% end,
+ Res = gen_udp:send(Socket, RemoteHost, RemotePort, IoList),
+ case Res of
+ ok ->
+ ok;
+ {error, einval = Reason} ->
+ error_msg(Config,
+ "Stacktrace; ~p\n gen_udp:send(~p, ~p, ~p, ~p) -> ~p\n",
+ [erlang:get_stacktrace(), Socket, RemoteHost, RemotePort, IoList, {error, Reason}]);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+%% trace_udp_send(#tftp_msg_req{filename = [$/ | RelFile]} = Req, Msg, IoList, DumpPath) ->
+%% trace_udp_send(Req#tftp_msg_req{filename = RelFile}, Msg, IoList, DumpPath);
+%% trace_udp_send(#tftp_msg_req{filename = RelFile},
+%% #tftp_msg_data{block_no = BlockNo, data = Data},
+%% _IoList,
+%% DumpPath) ->
+%% File = filename:join([DumpPath, RelFile, "block" ++ string:right(integer_to_list(BlockNo), 5, $0) ++ ".dump"]),
+%% if
+%% (BlockNo rem 1000) =:= 1 ->
+%% info_msg(Config, "TFTPDUMP: Data ~s\n", [File]);
+%% true ->
+%% ignore
+%% end,
+%% ok = filelib:ensure_dir(File),
+%% ok = file:write_file(File, Data);
+%% trace_udp_send(#tftp_msg_req{filename = RelFile}, Msg, _IoList, _DumpPath) ->
+%% info_msg(Config, "TFTPDUMP: No data ~s -> ~p\n", [RelFile, element(1, Msg)]).
+
+wait_for_msg(Config, Callback, Req) ->
+ receive
+ {udp, Socket, RemoteHost, RemotePort, Bin}
+ when is_binary(Bin), Callback#callback.block_no =:= undefined ->
+ %% Client prepare
+ _ = inet:setopts(Socket, [{active, once}]),
+ Config2 = Config#config{udp_host = RemoteHost,
+ udp_port = RemotePort},
+ DecodedMsg = (catch tftp_lib:decode_msg(Bin)),
+ print_debug_info(Config2, Req, recv, DecodedMsg),
+ {Config2, DecodedMsg};
+ {udp, Socket, Host, Port, Bin} when is_binary(Bin),
+ Config#config.udp_host =:= Host,
+ Config#config.udp_port =:= Port ->
+ _ = inet:setopts(Socket, [{active, once}]),
+ DecodedMsg = (catch tftp_lib:decode_msg(Bin)),
+ print_debug_info(Config, Req, recv, DecodedMsg),
+ {Config, DecodedMsg};
+ {info, Ref, FromPid} when is_pid(FromPid) ->
+ Type =
+ case Req#tftp_msg_req.local_filename =/= undefined of
+ true -> client;
+ false -> server
+ end,
+ Info = internal_info(Config, Type),
+ _ = reply({ok, Info}, Ref, FromPid),
+ wait_for_msg(Config, Callback, Req);
+ {{change_config, Options}, Ref, FromPid} when is_pid(FromPid) ->
+ case catch tftp_lib:parse_config(Options, Config) of
+ {'EXIT', Reason} ->
+ _ = reply({error, Reason}, Ref, FromPid),
+ wait_for_msg(Config, Callback, Req);
+ Config2 when is_record(Config2, config) ->
+ _ = reply(ok, Ref, FromPid),
+ wait_for_msg(Config2, Callback, Req)
+ end;
+ {system, From, Msg} ->
+ Misc = #sys_misc{module = ?MODULE, function = wait_for_msg, arguments = [Config, Callback, Req]},
+ sys:handle_system_msg(Msg, From, Config#config.parent_pid, ?MODULE, [], Misc);
+ {'EXIT', Pid, _Reason} when Config#config.parent_pid =:= Pid ->
+ Code = undef,
+ Text = "Parent exited.",
+ terminate(Config, Req, ?ERROR(wait_for_msg, Code, Text, Req#tftp_msg_req.filename));
+ Msg when Req#tftp_msg_req.local_filename =/= undefined ->
+ warning_msg(Config, "Client received : ~p", [Msg]),
+ wait_for_msg(Config, Callback, Req);
+ Msg when Req#tftp_msg_req.local_filename =:= undefined ->
+ warning_msg(Config, "Server received : ~p", [Msg]),
+ wait_for_msg(Config, Callback, Req)
+ after Config#config.timeout * 1000 ->
+ print_debug_info(Config, Req, recv, timeout),
+ timeout
+ end.
+
+early_read(Config, Callback, Req, LocalAccess, _NextBlockNo,
+ #prepared{status = Status, next_data = NextData, prev_data = PrevData} = Prepared) ->
+ if
+ Status =/= terminate,
+ LocalAccess =:= read,
+ Callback#callback.block_no =/= undefined,
+ NextData =:= undefined ->
+ case callback(read, Config, Callback, Req) of
+ {undefined, Error} when is_record(Error, tftp_msg_error) ->
+ {undefined, Error};
+ {Callback2, Prepared2} when is_record(Prepared2, prepared)->
+ {Callback2, Prepared2#prepared{prev_data = PrevData}}
+ end;
+ true ->
+ {Callback, Prepared}
+ end.
+
+%%-------------------------------------------------------------------
+%% Callback
+%%-------------------------------------------------------------------
+
+callback(Access, Config, Callback, Req) ->
+ {Callback2, Result} =
+ do_callback(Access, Config, Callback, Req),
+ print_debug_info(Config, Req, call, {Callback2, Result}),
+ {Callback2, Result}.
+
+do_callback(read = Fun, Config, Callback, Req)
+ when is_record(Config, config),
+ is_record(Callback, callback),
+ is_record(Req, tftp_msg_req) ->
+ Args = [Callback#callback.state],
+ NextBlockNo = Callback#callback.block_no + 1,
+ case catch safe_apply(Callback#callback.module, Fun, Args) of
+ {more, Bin, NewState} when is_binary(Bin) ->
+ Count = Callback#callback.count + size(Bin),
+ Callback2 = Callback#callback{state = NewState,
+ block_no = NextBlockNo,
+ count = Count},
+ Prepared = #prepared{status = more,
+ result = undefined,
+ block_no = NextBlockNo,
+ next_data = Bin},
+ verify_count(Config, Callback2, Req, Prepared);
+ {last, Bin, Result} when is_binary(Bin) ->
+ Prepared = #prepared{status = last,
+ result = Result,
+ block_no = NextBlockNo,
+ next_data = Bin},
+ {undefined, Prepared};
+ {error, {Code, Text}} ->
+ Error = #tftp_msg_error{code = Code, text = Text},
+ Prepared = #prepared{status = error,
+ result = Error},
+ {undefined, Prepared};
+ Illegal ->
+ Code = undef,
+ Text = "Internal error. File handler error.",
+ callback({abort, {Code, Text, Illegal}}, Config, Callback, Req)
+ end;
+do_callback({write = Fun, Bin}, Config, Callback, Req)
+ when is_record(Config, config),
+ is_record(Callback, callback),
+ is_record(Req, tftp_msg_req),
+ is_binary(Bin) ->
+ Args = [Bin, Callback#callback.state],
+ NextBlockNo = Callback#callback.block_no + 1,
+ case catch safe_apply(Callback#callback.module, Fun, Args) of
+ {more, NewState} ->
+ Count = Callback#callback.count + size(Bin),
+ Callback2 = Callback#callback{state = NewState,
+ block_no = NextBlockNo,
+ count = Count},
+ Prepared = #prepared{status = more,
+ block_no = NextBlockNo},
+ verify_count(Config, Callback2, Req, Prepared);
+ {last, Result} ->
+ Prepared = #prepared{status = last,
+ result = Result,
+ block_no = NextBlockNo},
+ {undefined, Prepared};
+ {error, {Code, Text}} ->
+ Error = #tftp_msg_error{code = Code, text = Text},
+ Prepared = #prepared{status = error,
+ result = Error},
+ {undefined, Prepared};
+ Illegal ->
+ Code = undef,
+ Text = "Internal error. File handler error.",
+ callback({abort, {Code, Text, Illegal}}, Config, Callback, Req)
+ end;
+do_callback({open, Type}, Config, Callback, Req)
+ when is_record(Config, config),
+ is_record(Callback, callback),
+ is_record(Req, tftp_msg_req) ->
+ {Access, Filename} = local_file_access(Req),
+ {Fun, BlockNo} =
+ case Type of
+ client_prepare -> {prepare, undefined};
+ client_open -> {open, 0};
+ server_open -> {open, 0}
+ end,
+ Mod = Callback#callback.module,
+ Args = [Access,
+ Filename,
+ Req#tftp_msg_req.mode,
+ Req#tftp_msg_req.options,
+ Callback#callback.state],
+ PeerInfo = peer_info(Config),
+ _ = fast_ensure_loaded(Mod),
+ Args2 =
+ case erlang:function_exported(Mod, Fun, length(Args)) of
+ true -> Args;
+ false -> [PeerInfo | Args]
+ end,
+ case catch safe_apply(Mod, Fun, Args2) of
+ {ok, AcceptedOptions, NewState} ->
+ Callback2 = Callback#callback{state = NewState,
+ block_no = BlockNo,
+ count = 0},
+ {Callback2, {ok, AcceptedOptions}};
+ {error, {Code, Text}} ->
+ {undefined, #tftp_msg_error{code = Code, text = Text}};
+ Illegal ->
+ Code = undef,
+ Text = "Internal error. File handler error.",
+ callback({abort, {Code, Text, Illegal}}, Config, Callback, Req)
+ end;
+do_callback({abort, {Code, Text}}, Config, Callback, Req) ->
+ Error = #tftp_msg_error{code = Code, text = Text},
+ do_callback({abort, Error}, Config, Callback, Req);
+do_callback({abort, {Code, Text, Details}}, Config, Callback, Req) ->
+ Error = #tftp_msg_error{code = Code, text = Text, details = Details},
+ do_callback({abort, Error}, Config, Callback, Req);
+do_callback({abort = Fun, #tftp_msg_error{code = Code, text = Text} = Error}, Config, Callback, Req)
+ when is_record(Config, config),
+ is_record(Callback, callback),
+ is_record(Req, tftp_msg_req) ->
+ Args = [Code, Text, Callback#callback.state],
+ catch safe_apply(Callback#callback.module, Fun, Args),
+ {undefined, Error};
+do_callback({abort, Error}, _Config, undefined, _Req) when is_record(Error, tftp_msg_error) ->
+ {undefined, Error}.
+
+peer_info(#config{udp_host = Host, udp_port = Port}) ->
+ if
+ is_tuple(Host), size(Host) =:= 4 ->
+ {inet, tftp_lib:host_to_string(Host), Port};
+ is_tuple(Host), size(Host) =:= 8 ->
+ {inet6, tftp_lib:host_to_string(Host), Port};
+ true ->
+ {undefined, Host, Port}
+ end.
+
+match_callback(Filename, Callbacks) ->
+ if
+ Filename =:= binary ->
+ lookup_callback_mod(tftp_binary, Callbacks);
+ is_binary(Filename) ->
+ lookup_callback_mod(tftp_binary, Callbacks);
+ true ->
+ do_match_callback(Filename, Callbacks)
+ end.
+
+do_match_callback(Filename, [C | Tail]) when is_record(C, callback) ->
+ case catch re:run(Filename, C#callback.internal, [{capture, none}]) of
+ match ->
+ {ok, C};
+ nomatch ->
+ do_match_callback(Filename, Tail);
+ Details ->
+ Code = baduser,
+ Text = "Internal error. File handler not found",
+ {error, #tftp_msg_error{code = Code, text = Text, details = Details}}
+ end;
+do_match_callback(Filename, []) ->
+ Code = baduser,
+ Text = "Internal error. File handler not found",
+ {error, #tftp_msg_error{code = Code, text = Text, details = Filename}}.
+
+lookup_callback_mod(Mod, Callbacks) ->
+ {value, C} = lists:keysearch(Mod, #callback.module, Callbacks),
+ {ok, C}.
+
+verify_count(Config, Callback, Req, Result) ->
+ case Config#config.max_tsize of
+ infinity ->
+ {Callback, Result};
+ Max when Callback#callback.count =< Max ->
+ {Callback, Result};
+ _Max ->
+ Code = enospc,
+ Text = "Too large file.",
+ callback({abort, {Code, Text}}, Config, Callback, Req)
+ end.
+
+%%-------------------------------------------------------------------
+%% Miscellaneous
+%%-------------------------------------------------------------------
+
+internal_info(Config, Type) when is_record(Config, config) ->
+ {ok, ActualPort} = inet:port(Config#config.udp_socket),
+ [
+ {type, Type},
+ {host, tftp_lib:host_to_string(Config#config.udp_host)},
+ {port, Config#config.udp_port},
+ {local_port, ActualPort},
+ {port_policy, Config#config.port_policy},
+ {udp, Config#config.udp_options},
+ {use_tsize, Config#config.use_tsize},
+ {max_tsize, Config#config.max_tsize},
+ {max_conn, Config#config.max_conn},
+ {rejected, Config#config.rejected},
+ {timeout, Config#config.timeout},
+ {polite_ack, Config#config.polite_ack},
+ {debug, Config#config.debug_level},
+ {parent_pid, Config#config.parent_pid}
+ ] ++ Config#config.user_options ++ Config#config.callbacks.
+
+local_file_access(#tftp_msg_req{access = Access,
+ local_filename = Local,
+ filename = Filename}) ->
+ case Local =:= undefined of
+ true ->
+ %% Server side
+ {Access, Filename};
+ false ->
+ %% Client side
+ case Access of
+ read -> {write, Local};
+ write -> {read, Local}
+ end
+ end.
+
+pre_verify_options(Config, Req) ->
+ Options = Req#tftp_msg_req.options,
+ case catch verify_reject(Config, Req, Options) of
+ ok ->
+ case verify_integer("tsize", 0, Config#config.max_tsize, Options) of
+ true ->
+ case verify_integer("blksize", 0, 65464, Options) of
+ true ->
+ ok;
+ false ->
+ {error, {badopt, "Too large blksize"}}
+ end;
+ false ->
+ {error, {badopt, "Too large tsize"}}
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+post_verify_options(Config, Req, NewOptions, Text) ->
+ OldOptions = Req#tftp_msg_req.options,
+ BadOptions =
+ [Key || {Key, _Val} <- NewOptions,
+ not lists:keymember(Key, 1, OldOptions)],
+ case BadOptions =:= [] of
+ true ->
+ Config2 = Config#config{timeout = lookup_timeout(NewOptions)},
+ Req2 = Req#tftp_msg_req{options = NewOptions},
+ {ok, Config2, Req2};
+ false ->
+ {error, {badopt, Text}}
+ end.
+
+verify_reject(Config, Req, Options) ->
+ Access = Req#tftp_msg_req.access,
+ Rejected = Config#config.rejected,
+ case lists:member(Access, Rejected) of
+ true ->
+ {error, {eacces, atom_to_list(Access) ++ " mode not allowed"}};
+ false ->
+ [throw({error, {badopt, Key ++ " not allowed"}}) ||
+ {Key, _} <- Options, lists:member(Key, Rejected)],
+ ok
+ end.
+
+lookup_timeout(Options) ->
+ case lists:keysearch("timeout", 1, Options) of
+ {value, {_, Val}} ->
+ list_to_integer(Val);
+ false ->
+ 3
+ end.
+
+lookup_mode(Options) ->
+ case lists:keysearch("mode", 1, Options) of
+ {value, {_, Val}} ->
+ Val;
+ false ->
+ "octet"
+ end.
+
+verify_integer(Key, Min, Max, Options) ->
+ case lists:keysearch(Key, 1, Options) of
+ {value, {_, Val}} when is_list(Val) ->
+ case catch list_to_integer(Val) of
+ {'EXIT', _} ->
+ false;
+ Int when Int >= Min, is_integer(Min),
+ Max =:= infinity ->
+ true;
+ Int when Int >= Min, is_integer(Min),
+ Int =< Max, is_integer(Max) ->
+ true;
+ _ ->
+ false
+ end;
+ false ->
+ true
+ end.
+
+error_msg(#config{logger = Logger, debug_level = _Level}, F, A) ->
+ safe_apply(Logger, error_msg, [F, A]).
+
+warning_msg(#config{logger = Logger, debug_level = Level}, F, A) ->
+ case Level of
+ none -> ok;
+ error -> ok;
+ _ -> safe_apply(Logger, warning_msg, [F, A])
+ end.
+
+info_msg(#config{logger = Logger}, F, A) ->
+ safe_apply(Logger, info_msg, [F, A]).
+
+safe_apply(Mod, Fun, Args) ->
+ _ = fast_ensure_loaded(Mod),
+ apply(Mod, Fun, Args).
+
+fast_ensure_loaded(Mod) ->
+ case erlang:function_exported(Mod, module_info, 0) of
+ true ->
+ ok;
+ false ->
+ Res = code:load_file(Mod),
+ %% io:format("tftp: code:load_file(~p) -> ~p\n", [Mod, Res]), %% XXX
+ Res
+ end.
+
+print_debug_info(#config{debug_level = Level} = Config, Who, Where, Data) ->
+ if
+ Level =:= none ->
+ ok;
+ is_record(Data, error) ->
+ do_print_debug_info(Config, Who, Where, Data);
+ Level =:= warning ->
+ ok;
+ Level =:= error ->
+ ok;
+ Level =:= all ->
+ do_print_debug_info(Config, Who, Where, Data);
+ Where =:= open ->
+ do_print_debug_info(Config, Who, Where, Data);
+ Where =:= close ->
+ do_print_debug_info(Config, Who, Where, Data);
+ Level =:= brief ->
+ ok;
+ Where =/= recv, Where =/= send ->
+ ok;
+ is_record(Data, tftp_msg_data), Level =:= normal ->
+ ok;
+ is_record(Data, tftp_msg_ack), Level =:= normal ->
+ ok;
+ true ->
+ do_print_debug_info(Config, Who, Where, Data)
+ end.
+
+do_print_debug_info(Config, Who, Where, #tftp_msg_data{data = Bin} = Msg) when is_binary(Bin) ->
+ Msg2 = Msg#tftp_msg_data{data = {bytes, size(Bin)}},
+ do_print_debug_info(Config, Who, Where, Msg2);
+do_print_debug_info(Config, Who, Where, #tftp_msg_req{local_filename = Filename} = Msg) when is_binary(Filename) ->
+ Msg2 = Msg#tftp_msg_req{local_filename = binary},
+ do_print_debug_info(Config, Who, Where, Msg2);
+do_print_debug_info(Config, Who, Where, Data) ->
+ Local =
+ case catch inet:port(Config#config.udp_socket) of
+ {'EXIT', _Reason} ->
+ 0;
+ {ok, Port} ->
+ Port
+ end,
+ %% Remote = Config#config.udp_port,
+ PeerInfo = lists:flatten(io_lib:format("~p", [peer_info(Config)])),
+ Side =
+ if
+ is_record(Who, tftp_msg_req),
+ Who#tftp_msg_req.local_filename =/= undefined ->
+ client;
+ is_record(Who, tftp_msg_req),
+ Who#tftp_msg_req.local_filename =:= undefined ->
+ server;
+ is_atom(Who) ->
+ Who
+ end,
+ case {Where, Data} of
+ {_, #error{where = Where, code = Code, text = Text, filename = Filename}} ->
+ do_format(Config, Side, Local, "error ~s ->\n\t~p ~p\n\t~p ~p: ~s\n",
+ [PeerInfo, self(), Filename, Where, Code, Text]);
+ {open, #tftp_msg_req{filename = Filename}} ->
+ do_format(Config, Side, Local, "open ~s ->\n\t~p ~p\n",
+ [PeerInfo, self(), Filename]);
+ {close, #tftp_msg_req{filename = Filename}} ->
+ do_format(Config, Side, Local, "close ~s ->\n\t~p ~p\n",
+ [PeerInfo, self(), Filename]);
+ {recv, _} ->
+ do_format(Config, Side, Local, "recv ~s <-\n\t~p\n",
+ [PeerInfo, Data]);
+ {send, _} ->
+ do_format(Config, Side, Local, "send ~s ->\n\t~p\n",
+ [PeerInfo, Data]);
+ {match, _} when is_record(Data, callback) ->
+ Mod = Data#callback.module,
+ State = Data#callback.state,
+ do_format(Config, Side, Local, "match ~s ~p =>\n\t~p\n",
+ [PeerInfo, Mod, State]);
+ {call, _} ->
+ case Data of
+ {Callback, _Result} when is_record(Callback, callback) ->
+ Mod = Callback#callback.module,
+ State = Callback#callback.state,
+ do_format(Config, Side, Local, "call ~s ~p =>\n\t~p\n",
+ [PeerInfo, Mod, State]);
+ {undefined, Result} ->
+ do_format(Config, Side, Local, "call ~s result =>\n\t~p\n",
+ [PeerInfo, Result])
+ end
+ end.
+
+do_format(Config, Side, Local, Format, Args) ->
+ info_msg(Config, "~p(~p): " ++ Format, [Side, Local | Args]).
+
+%%-------------------------------------------------------------------
+%% System upgrade
+%%-------------------------------------------------------------------
+
+system_continue(_Parent, _Debug, #sys_misc{module = Mod, function = Fun, arguments = Args}) ->
+ apply(Mod, Fun, Args);
+system_continue(Parent, Debug, {Fun, Args}) ->
+ %% Handle upgrade from old releases. Please, remove this clause in next release.
+ system_continue(Parent, Debug, #sys_misc{module = ?MODULE, function = Fun, arguments = Args}).
+
+-spec system_terminate(_, _, _, #sys_misc{} | {_, _}) -> no_return().
+
+system_terminate(Reason, _Parent, _Debug, #sys_misc{}) ->
+ exit(Reason);
+system_terminate(Reason, Parent, Debug, {Fun, Args}) ->
+ %% Handle upgrade from old releases. Please, remove this clause in next release.
+ system_terminate(Reason, Parent, Debug, #sys_misc{module = ?MODULE, function = Fun, arguments = Args}).
+
+system_code_change({Fun, Args}, _Module, _OldVsn, _Extra) ->
+ {ok, {Fun, Args}}.
diff --git a/lib/tftp/src/tftp_file.erl b/lib/tftp/src/tftp_file.erl
new file mode 100644
index 0000000000..5922fc9418
--- /dev/null
+++ b/lib/tftp/src/tftp_file.erl
@@ -0,0 +1,390 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File : tft_file.erl
+%%% Author : Hakan Mattsson <[email protected]>
+%%% Description :
+%%%
+%%% Created : 24 May 2004 by Hakan Mattsson <[email protected]>
+%%%-------------------------------------------------------------------
+
+-module(tftp_file).
+
+%%%-------------------------------------------------------------------
+%%% Interface
+%%%-------------------------------------------------------------------
+
+-behaviour(tftp).
+
+-export([prepare/6, open/6, read/1, write/2, abort/3]).
+
+%%%-------------------------------------------------------------------
+%%% Defines
+%%%-------------------------------------------------------------------
+
+-include_lib("kernel/include/file.hrl").
+
+-record(initial,
+ {filename,
+ is_native_ascii}).
+
+-record(state,
+ {access,
+ filename,
+ is_native_ascii,
+ is_network_ascii,
+ root_dir,
+ options,
+ blksize,
+ fd,
+ count,
+ buffer}).
+
+%%-------------------------------------------------------------------
+%% prepare(Peer, Access, Filename, Mode, SuggestedOptions, InitialState) ->
+%% {ok, AcceptedOptions, NewState} | {error, Code, Text}
+%%
+%% Peer = {PeerType, PeerHost, PeerPort}
+%% PeerType = inet | inet6
+%% PeerHost = ip_address()
+%% PeerPort = integer()
+%% Acess = read | write
+%% Filename = string()
+%% Mode = string()
+%% SuggestedOptions = [{Key, Value}]
+%% AcceptedOptions = [{Key, Value}]
+%% Key = string()
+%% Value = string()
+%% InitialState = [] | [{root_dir, string()}]
+%% NewState = term()
+%% Code = undef | enoent | eacces | enospc |
+%% badop | eexist | baduser | badopt |
+%% integer()
+%% Text = string()
+%%
+%% Prepares open of a file on the client side.
+%%
+%% Will be followed by a call to open/4 before any read/write access
+%% is performed. The AcceptedOptions will be sent to the server which
+%% will reply with those options that it accepts. The options that are
+%% accepted by the server will be forwarded to open/4 as SuggestedOptions.
+%%
+%% No new options may be added, but the ones that are present as
+%% SuggestedOptions may be omitted or replaced with new values
+%% in the AcceptedOptions.
+%%-------------------------------------------------------------------
+
+prepare(_Peer, Access, Filename, Mode, SuggestedOptions, Initial) when is_list(Initial) ->
+ %% Client side
+ case catch handle_options(Access, Filename, Mode, SuggestedOptions, Initial) of
+ {ok, Filename2, IsNativeAscii, IsNetworkAscii, AcceptedOptions} ->
+ State = #state{access = Access,
+ filename = Filename2,
+ is_native_ascii = IsNativeAscii,
+ is_network_ascii = IsNetworkAscii,
+ options = AcceptedOptions,
+ blksize = lookup_blksize(AcceptedOptions),
+ count = 0,
+ buffer = []},
+ {ok, AcceptedOptions, State};
+ {error, {Code, Text}} ->
+ {error, {Code, Text}}
+ end.
+
+%% ---------------------------------------------------------
+%% open(Peer, Access, Filename, Mode, SuggestedOptions, State) ->
+%% {ok, AcceptedOptions, NewState} | {error, Code, Text}
+%%
+%% Peer = {PeerType, PeerHost, PeerPort}
+%% PeerType = inet | inet6
+%% PeerHost = ip_address()
+%% PeerPort = integer()
+%% Acess = read | write
+%% Filename = string()
+%% Mode = string()
+%% SuggestedOptions = [{Key, Value}]
+%% AcceptedOptions = [{Key, Value}]
+%% Key = string()
+%% Value = string()
+%% State = InitialState | #state{}
+%% InitialState = [] | [{root_dir, string()}]
+%% NewState = term()
+%% Code = undef | enoent | eacces | enospc |
+%% badop | eexist | baduser | badopt |
+%% integer()
+%% Text = string()
+%%
+%% Opens a file for read or write access.
+%%
+%% On the client side where the open/4 call has been preceeded by a
+%% call to prepare/4, all options must be accepted or rejected.
+%% On the server side, where there are no preceeding prepare/4 call,
+%% noo new options may be added, but the ones that are present as
+%% SuggestedOptions may be omitted or replaced with new values
+%% in the AcceptedOptions.
+%%-------------------------------------------------------------------
+
+open(Peer, Access, Filename, Mode, SuggestedOptions, Initial) when is_list(Initial) ->
+ %% Server side
+ case prepare(Peer, Access, Filename, Mode, SuggestedOptions, Initial) of
+ {ok, AcceptedOptions, State} ->
+ open(Peer, Access, Filename, Mode, AcceptedOptions, State);
+ {error, {Code, Text}} ->
+ {error, {Code, Text}}
+ end;
+open(_Peer, Access, Filename, Mode, NegotiatedOptions, State) when is_record(State, state) ->
+ %% Both sides
+ case catch handle_options(Access, Filename, Mode, NegotiatedOptions, State) of
+ {ok, _Filename2, _IsNativeAscii, _IsNetworkAscii, Options}
+ when Options =:= NegotiatedOptions ->
+ do_open(State);
+ {error, {Code, Text}} ->
+ {error, {Code, Text}}
+ end;
+open(Peer, Access, Filename, Mode, NegotiatedOptions, State) ->
+ %% Handle upgrade from old releases. Please, remove this clause in next release.
+ State2 = upgrade_state(State),
+ open(Peer, Access, Filename, Mode, NegotiatedOptions, State2).
+
+do_open(State) when is_record(State, state) ->
+ case file:open(State#state.filename, file_options(State)) of
+ {ok, Fd} ->
+ {ok, State#state.options, State#state{fd = Fd}};
+ {error, Reason} when is_atom(Reason) ->
+ {error, file_error(Reason)}
+ end.
+
+file_options(State) ->
+ case State#state.access of
+ read -> [read, read_ahead, raw, binary];
+ write -> [write, delayed_write, raw, binary]
+ end.
+
+file_error(Reason) when is_atom(Reason) ->
+ Details = file:format_error(Reason),
+ case Reason of
+ eexist -> {Reason, Details};
+ enoent -> {Reason, Details};
+ eacces -> {Reason, Details};
+ eperm -> {eacces, Details};
+ enospc -> {Reason, Details};
+ _ -> {undef, Details ++ " (" ++ atom_to_list(Reason) ++ ")"}
+ end.
+
+%%-------------------------------------------------------------------
+%% read(State) ->
+%% {more, Bin, NewState} | {last, Bin, FileSize} | {error, {Code, Text}}
+%%
+%% State = term()
+%% NewState = term()
+%% Bin = binary()
+%% FileSize = integer()
+%% Code = undef | enoent | eacces | enospc |
+%% badop | eexist | baduser | badopt |
+%% integer()
+%% Text = string()
+%%
+%% Reads a chunk from the file
+%%
+%% The file is automatically closed when the last chunk is read.
+%%-------------------------------------------------------------------
+
+read(#state{access = read} = State) ->
+ BlkSize = State#state.blksize,
+ case file:read(State#state.fd, BlkSize) of
+ {ok, Bin} when is_binary(Bin), size(Bin) =:= BlkSize ->
+ Count = State#state.count + size(Bin),
+ {more, Bin, State#state{count = Count}};
+ {ok, Bin} when is_binary(Bin), size(Bin) < BlkSize ->
+ _ = file:close(State#state.fd),
+ Count = State#state.count + size(Bin),
+ {last, Bin, Count};
+ eof ->
+ {last, <<>>, State#state.count};
+ {error, Reason} ->
+ _ = file:close(State#state.fd),
+ {error, file_error(Reason)}
+ end;
+read(State) ->
+ %% Handle upgrade from old releases. Please, remove this clause in next release.
+ State2 = upgrade_state(State),
+ read(State2).
+
+%%-------------------------------------------------------------------
+%% write(Bin, State) ->
+%% {more, NewState} | {last, FileSize} | {error, {Code, Text}}
+%%
+%% State = term()
+%% NewState = term()
+%% Bin = binary()
+%% FileSize = integer()
+%% Code = undef | enoent | eacces | enospc |
+%% badop | eexist | baduser | badopt |
+%% integer()
+%% Text = string()
+%%
+%% Writes a chunk to the file
+%%
+%% The file is automatically closed when the last chunk is written
+%%-------------------------------------------------------------------
+
+write(Bin, #state{access = write} = State) when is_binary(Bin) ->
+ Size = size(Bin),
+ BlkSize = State#state.blksize,
+ case file:write(State#state.fd, Bin) of
+ ok when Size =:= BlkSize->
+ Count = State#state.count + Size,
+ {more, State#state{count = Count}};
+ ok when Size < BlkSize->
+ _ = file:close(State#state.fd),
+ Count = State#state.count + Size,
+ {last, Count};
+ {error, Reason} ->
+ _ = file:close(State#state.fd),
+ _ = file:delete(State#state.filename),
+ {error, file_error(Reason)}
+ end;
+write(Bin, State) ->
+ %% Handle upgrade from old releases. Please, remove this clause in next release.
+ State2 = upgrade_state(State),
+ write(Bin, State2).
+
+%%-------------------------------------------------------------------
+%% abort(Code, Text, State) -> ok
+%%
+%% State = term()
+%% Code = undef | enoent | eacces | enospc |
+%% badop | eexist | baduser | badopt |
+%% badblk | integer()
+%% Text = string()
+%%
+%% Aborts the file transfer
+%%-------------------------------------------------------------------
+
+abort(_Code, _Text, #state{fd = Fd, access = Access} = State) ->
+ _ = file:close(Fd),
+ case Access of
+ write ->
+ ok = file:delete(State#state.filename);
+ read ->
+ ok
+ end.
+
+%%-------------------------------------------------------------------
+%% Process options
+%%-------------------------------------------------------------------
+
+handle_options(Access, Filename, Mode, Options, Initial) ->
+ I = #initial{filename = Filename, is_native_ascii = is_native_ascii()},
+ {Filename2, IsNativeAscii} = handle_initial(Initial, I),
+ IsNetworkAscii = handle_mode(Mode, IsNativeAscii),
+ Options2 = do_handle_options(Access, Filename2, Options),
+ {ok, Filename2, IsNativeAscii, IsNetworkAscii, Options2}.
+
+handle_mode(Mode, IsNativeAscii) ->
+ case Mode of
+ "netascii" when IsNativeAscii =:= true -> true;
+ "octet" -> false;
+ _ -> throw({error, {badop, "Illegal mode " ++ Mode}})
+ end.
+
+handle_initial([{root_dir, Dir} | Initial], I) ->
+ case catch filename_join(Dir, I#initial.filename) of
+ {'EXIT', _} ->
+ throw({error, {badop, "Internal error. root_dir is not a string"}});
+ Filename2 ->
+ handle_initial(Initial, I#initial{filename = Filename2})
+ end;
+handle_initial([{native_ascii, Bool} | Initial], I) ->
+ case Bool of
+ true -> handle_initial(Initial, I#initial{is_native_ascii = true});
+ false -> handle_initial(Initial, I#initial{is_native_ascii = false})
+ end;
+handle_initial([], I) when is_record(I, initial) ->
+ {I#initial.filename, I#initial.is_native_ascii};
+handle_initial(State, _) when is_record(State, state) ->
+ {State#state.filename, State#state.is_native_ascii}.
+
+filename_join(Dir, Filename) ->
+ case filename:pathtype(Filename) of
+ absolute ->
+ [_ | RelFilename] = filename:split(Filename),
+ filename:join([Dir, RelFilename]);
+ _ ->
+ filename:join([Dir, Filename])
+ end.
+
+do_handle_options(Access, Filename, [{Key, Val} | T]) ->
+ case Key of
+ "tsize" ->
+ case Access of
+ read when Val =:= "0" ->
+ case file:read_file_info(Filename) of
+ {ok, FI} ->
+ Tsize = integer_to_list(FI#file_info.size),
+ [{Key, Tsize} | do_handle_options(Access, Filename, T)];
+ {error, _} ->
+ do_handle_options(Access, Filename, T)
+ end;
+ _ ->
+ handle_integer(Access, Filename, Key, Val, T, 0, infinity)
+ end;
+ "blksize" ->
+ handle_integer(Access, Filename, Key, Val, T, 8, 65464);
+ "timeout" ->
+ handle_integer(Access, Filename, Key, Val, T, 1, 255);
+ _ ->
+ do_handle_options(Access, Filename, T)
+ end;
+do_handle_options(_Access, _Filename, []) ->
+ [].
+
+
+handle_integer(Access, Filename, Key, Val, Options, Min, Max) ->
+ case catch list_to_integer(Val) of
+ {'EXIT', _} ->
+ do_handle_options(Access, Filename, Options);
+ Int when Int >= Min, Int =< Max ->
+ [{Key, Val} | do_handle_options(Access, Filename, Options)];
+ Int when Int >= Min, Max =:= infinity ->
+ [{Key, Val} | do_handle_options(Access, Filename, Options)];
+ _Int ->
+ throw({error, {badopt, "Illegal " ++ Key ++ " value " ++ Val}})
+ end.
+
+lookup_blksize(Options) ->
+ case lists:keysearch("blksize", 1, Options) of
+ {value, {_, Val}} ->
+ list_to_integer(Val);
+ false ->
+ 512
+ end.
+
+is_native_ascii() ->
+ case os:type() of
+ {win32, _} -> true;
+ _ -> false
+ end.
+
+%% Handle upgrade from old releases. Please, remove this function in next release.
+upgrade_state({state, Access, Filename, RootDir, Options, BlkSize, Fd, Count, Buffer}) ->
+ {state, Access, Filename, false, false, RootDir, Options, BlkSize, Fd, Count, Buffer}.
diff --git a/lib/tftp/src/tftp_lib.erl b/lib/tftp/src/tftp_lib.erl
new file mode 100644
index 0000000000..407a273f58
--- /dev/null
+++ b/lib/tftp/src/tftp_lib.erl
@@ -0,0 +1,474 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File : tftp_lib.erl
+%%% Author : Hakan Mattsson <[email protected]>
+%%% Description : Option parsing, decode, encode etc.
+%%%
+%%% Created : 18 May 2004 by Hakan Mattsson <[email protected]>
+%%%-------------------------------------------------------------------
+
+-module(tftp_lib).
+
+%%-------------------------------------------------------------------
+%% Interface
+%%-------------------------------------------------------------------
+
+%% application internal functions
+-export([
+ parse_config/1,
+ parse_config/2,
+ decode_msg/1,
+ encode_msg/1,
+ replace_val/3,
+ to_lower/1,
+ host_to_string/1,
+ add_default_callbacks/1
+ ]).
+
+%%-------------------------------------------------------------------
+%% Defines
+%%-------------------------------------------------------------------
+
+-include("tftp.hrl").
+
+-define(LOWER(Char),
+ if
+ Char >= $A, Char =< $Z ->
+ Char - ($A - $a);
+ true ->
+ Char
+ end).
+
+%%-------------------------------------------------------------------
+%% Config
+%%-------------------------------------------------------------------
+
+parse_config(Options) ->
+ parse_config(Options, #config{}).
+
+parse_config(Options, Config) ->
+ do_parse_config(Options, Config).
+
+do_parse_config([{Key, Val} | Tail], Config) when is_record(Config, config) ->
+ case Key of
+ debug ->
+ if
+ Val =:= 0; Val =:= none ->
+ do_parse_config(Tail, Config#config{debug_level = none});
+ Val =:= 1; Val =:= error ->
+ do_parse_config(Tail, Config#config{debug_level = error});
+ Val =:= 2; Val =:= warning ->
+ do_parse_config(Tail, Config#config{debug_level = warning});
+ Val =:= 3; Val =:= brief ->
+ do_parse_config(Tail, Config#config{debug_level = brief});
+ Val =:= 4; Val =:= normal ->
+ do_parse_config(Tail, Config#config{debug_level = normal});
+ Val =:= 5; Val =:= verbose ->
+ do_parse_config(Tail, Config#config{debug_level = verbose});
+ Val =:= 6; Val =:= all ->
+ do_parse_config(Tail, Config#config{debug_level = all});
+ true ->
+ exit({badarg, {Key, Val}})
+ end;
+ host ->
+ if
+ is_list(Val) ->
+ do_parse_config(Tail, Config#config{udp_host = Val});
+ is_tuple(Val), size(Val) =:= 4 ->
+ do_parse_config(Tail, Config#config{udp_host = Val});
+ is_tuple(Val), size(Val) =:= 8 ->
+ do_parse_config(Tail, Config#config{udp_host = Val});
+ true ->
+ exit({badarg, {Key, Val}})
+ end;
+ port ->
+ if
+ is_integer(Val), Val >= 0 ->
+ Config2 = Config#config{udp_port = Val, udp_options = Config#config.udp_options},
+ do_parse_config(Tail, Config2);
+ true ->
+ exit({badarg, {Key, Val}})
+ end;
+ port_policy ->
+ case Val of
+ random ->
+ do_parse_config(Tail, Config#config{port_policy = Val});
+ 0 ->
+ do_parse_config(Tail, Config#config{port_policy = random});
+ MinMax when is_integer(MinMax), MinMax > 0 ->
+ do_parse_config(Tail, Config#config{port_policy = {range, MinMax, MinMax}});
+ {range, Min, Max} when Max >= Min,
+ is_integer(Min), Min > 0,
+ is_integer(Max), Max > 0 ->
+ do_parse_config(Tail, Config#config{port_policy = Val});
+ true ->
+ exit({badarg, {Key, Val}})
+ end;
+ udp when is_list(Val) ->
+ Fun =
+ fun({K, V}, List) when K /= active ->
+ replace_val(K, V, List);
+ (V, List) when V /= list, V /= binary ->
+ List ++ [V];
+ (V, _List) ->
+ exit({badarg, {udp, [V]}})
+ end,
+ UdpOptions = lists:foldl(Fun, Config#config.udp_options, Val),
+ do_parse_config(Tail, Config#config{udp_options = UdpOptions});
+ use_tsize ->
+ case Val of
+ true ->
+ do_parse_config(Tail, Config#config{use_tsize = Val});
+ false ->
+ do_parse_config(Tail, Config#config{use_tsize = Val});
+ _ ->
+ exit({badarg, {Key, Val}})
+ end;
+ max_tsize ->
+ if
+ Val =:= infinity ->
+ do_parse_config(Tail, Config#config{max_tsize = Val});
+ is_integer(Val), Val >= 0 ->
+ do_parse_config(Tail, Config#config{max_tsize = Val});
+ true ->
+ exit({badarg, {Key, Val}})
+ end;
+ max_conn ->
+ if
+ Val =:= infinity ->
+ do_parse_config(Tail, Config#config{max_conn = Val});
+ is_integer(Val), Val > 0 ->
+ do_parse_config(Tail, Config#config{max_conn = Val});
+ true ->
+ exit({badarg, {Key, Val}})
+ end;
+ _ when is_list(Key), is_list(Val) ->
+ Key2 = to_lower(Key),
+ Val2 = to_lower(Val),
+ TftpOptions = replace_val(Key2, Val2, Config#config.user_options),
+ do_parse_config(Tail, Config#config{user_options = TftpOptions});
+ reject ->
+ case Val of
+ read ->
+ Rejected = [Val | Config#config.rejected],
+ do_parse_config(Tail, Config#config{rejected = Rejected});
+ write ->
+ Rejected = [Val | Config#config.rejected],
+ do_parse_config(Tail, Config#config{rejected = Rejected});
+ _ when is_list(Val) ->
+ Rejected = [Val | Config#config.rejected],
+ do_parse_config(Tail, Config#config{rejected = Rejected});
+ _ ->
+ exit({badarg, {Key, Val}})
+ end;
+ callback ->
+ case Val of
+ {RegExp, Mod, State} when is_list(RegExp), is_atom(Mod) ->
+ case re:compile(RegExp) of
+ {ok, Internal} ->
+ Callback = #callback{regexp = RegExp,
+ internal = Internal,
+ module = Mod,
+ state = State},
+ Callbacks = Config#config.callbacks ++ [Callback],
+ do_parse_config(Tail, Config#config{callbacks = Callbacks});
+ {error, Reason} ->
+ exit({badarg, {Key, Val}, Reason})
+ end;
+ _ ->
+ exit({badarg, {Key, Val}})
+ end;
+ logger ->
+ if
+ is_atom(Val) ->
+ do_parse_config(Tail, Config#config{logger = Val});
+ true ->
+ exit({badarg, {Key, Val}})
+ end;
+ max_retries ->
+ if
+ is_integer(Val), Val > 0 ->
+ do_parse_config(Tail, Config#config{max_retries = Val});
+ true ->
+ exit({badarg, {Key, Val}})
+ end;
+ _ ->
+ exit({badarg, {Key, Val}})
+ end;
+do_parse_config([], #config{udp_host = Host,
+ udp_options = UdpOptions,
+ user_options = UserOptions,
+ callbacks = Callbacks} = Config) ->
+ IsInet6 = lists:member(inet6, UdpOptions),
+ IsInet = lists:member(inet, UdpOptions),
+ Host2 =
+ if
+ (IsInet and not IsInet6); (not IsInet and not IsInet6) ->
+ case inet:getaddr(Host, inet) of
+ {ok, Addr} ->
+ Addr;
+ {error, Reason} ->
+ exit({badarg, {host, Reason}})
+ end;
+ (IsInet6 and not IsInet) ->
+ case inet:getaddr(Host, inet6) of
+ {ok, Addr} ->
+ Addr;
+ {error, Reason} ->
+ exit({badarg, {host, Reason}})
+ end;
+ true ->
+ %% Conflicting options
+ exit({badarg, {udp, [inet]}})
+ end,
+ UdpOptions2 = lists:reverse(UdpOptions),
+ TftpOptions = lists:reverse(UserOptions),
+ Callbacks2 = add_default_callbacks(Callbacks),
+ Config#config{udp_host = Host2,
+ udp_options = UdpOptions2,
+ user_options = TftpOptions,
+ callbacks = Callbacks2};
+do_parse_config(Options, Config) when is_record(Config, config) ->
+ exit({badarg, Options}).
+
+add_default_callbacks(Callbacks) ->
+ RegExp = "",
+ {ok, Internal} = re:compile(RegExp),
+ File = #callback{regexp = RegExp,
+ internal = Internal,
+ module = tftp_file,
+ state = []},
+ Bin = #callback{regexp = RegExp,
+ internal = Internal,
+ module = tftp_binary,
+ state = []},
+ Callbacks ++ [File, Bin].
+
+host_to_string(Host) ->
+ case Host of
+ String when is_list(String) ->
+ String;
+ {A1, A2, A3, A4} -> % inet
+ lists:concat([A1, ".", A2, ".", A3, ".",A4]);
+ {A1, A2, A3, A4, A5, A6, A7, A8} -> % inet6
+ lists:concat([
+ int16_to_hex(A1), "::",
+ int16_to_hex(A2), "::",
+ int16_to_hex(A3), "::",
+ int16_to_hex(A4), "::",
+ int16_to_hex(A5), "::",
+ int16_to_hex(A6), "::",
+ int16_to_hex(A7), "::",
+ int16_to_hex(A8)
+ ])
+ end.
+
+int16_to_hex(0) ->
+ [$0];
+int16_to_hex(I) ->
+ N1 = ((I bsr 8) band 16#ff),
+ N2 = (I band 16#ff),
+ [code_character(N1 div 16), code_character(N1 rem 16),
+ code_character(N2 div 16), code_character(N2 rem 16)].
+
+code_character(N) when N < 10 ->
+ $0 + N;
+code_character(N) ->
+ $A + (N - 10).
+
+%%-------------------------------------------------------------------
+%% Decode
+%%-------------------------------------------------------------------
+
+decode_msg(Bin) when is_binary(Bin) ->
+ case Bin of
+ <<?TFTP_OPCODE_RRQ:16/integer, Tail/binary>> ->
+ case decode_strings(Tail, [keep_case, lower_case]) of
+ [Filename, Mode | Strings] ->
+ Options = decode_options(Strings),
+ #tftp_msg_req{access = read,
+ filename = Filename,
+ mode = to_lower(Mode),
+ options = Options};
+ [_Filename | _Strings] ->
+ exit(#tftp_msg_error{code = undef,
+ text = "Missing mode"});
+ _ ->
+ exit(#tftp_msg_error{code = undef,
+ text = "Missing filename"})
+ end;
+ <<?TFTP_OPCODE_WRQ:16/integer, Tail/binary>> ->
+ case decode_strings(Tail, [keep_case, lower_case]) of
+ [Filename, Mode | Strings] ->
+ Options = decode_options(Strings),
+ #tftp_msg_req{access = write,
+ filename = Filename,
+ mode = to_lower(Mode),
+ options = Options};
+ [_Filename | _Strings] ->
+ exit(#tftp_msg_error{code = undef,
+ text = "Missing mode"});
+ _ ->
+ exit(#tftp_msg_error{code = undef,
+ text = "Missing filename"})
+ end;
+ <<?TFTP_OPCODE_DATA:16/integer, SeqNo:16/integer, Data/binary>> ->
+ #tftp_msg_data{block_no = SeqNo, data = Data};
+ <<?TFTP_OPCODE_ACK:16/integer, SeqNo:16/integer>> ->
+ #tftp_msg_ack{block_no = SeqNo};
+ <<?TFTP_OPCODE_ERROR:16/integer, ErrorCode:16/integer, Tail/binary>> ->
+ case decode_strings(Tail, [keep_case]) of
+ [ErrorText] ->
+ ErrorCode2 = decode_error_code(ErrorCode),
+ #tftp_msg_error{code = ErrorCode2,
+ text = ErrorText};
+ _ ->
+ exit(#tftp_msg_error{code = undef,
+ text = "Trailing garbage"})
+ end;
+ <<?TFTP_OPCODE_OACK:16/integer, Tail/binary>> ->
+ Strings = decode_strings(Tail, [lower_case]),
+ Options = decode_options(Strings),
+ #tftp_msg_oack{options = Options};
+ _ ->
+ exit(#tftp_msg_error{code = undef,
+ text = "Invalid syntax"})
+ end.
+
+decode_strings(Bin, Cases) when is_binary(Bin), is_list(Cases) ->
+ do_decode_strings(Bin, Cases, []).
+
+do_decode_strings(<<>>, _Cases, Strings) ->
+ lists:reverse(Strings);
+do_decode_strings(Bin, [Case | Cases], Strings) ->
+ {String, Tail} = decode_string(Bin, Case, []),
+ if
+ Cases =:= [] ->
+ do_decode_strings(Tail, [Case], [String | Strings]);
+ true ->
+ do_decode_strings(Tail, Cases, [String | Strings])
+ end.
+
+decode_string(<<Char:8/integer, Tail/binary>>, Case, String) ->
+ if
+ Char =:= 0 ->
+ {lists:reverse(String), Tail};
+ Case =:= keep_case ->
+ decode_string(Tail, Case, [Char | String]);
+ Case =:= lower_case ->
+ Char2 = ?LOWER(Char),
+ decode_string(Tail, Case, [Char2 | String])
+ end;
+decode_string(<<>>, _Case, _String) ->
+ exit(#tftp_msg_error{code = undef, text = "Trailing null missing"}).
+
+decode_options([Key, Value | Strings]) ->
+ [{to_lower(Key), Value} | decode_options(Strings)];
+decode_options([]) ->
+ [].
+
+decode_error_code(Int) ->
+ case Int of
+ ?TFTP_ERROR_UNDEF -> undef;
+ ?TFTP_ERROR_ENOENT -> enoent;
+ ?TFTP_ERROR_EACCES -> eacces;
+ ?TFTP_ERROR_ENOSPC -> enospc;
+ ?TFTP_ERROR_BADOP -> badop;
+ ?TFTP_ERROR_BADBLK -> badblk;
+ ?TFTP_ERROR_EEXIST -> eexist;
+ ?TFTP_ERROR_BADUSER -> baduser;
+ ?TFTP_ERROR_BADOPT -> badopt;
+ Int when is_integer(Int), Int >= 0, Int =< 65535 -> Int;
+ _ -> exit(#tftp_msg_error{code = undef, text = "Error code outside range."})
+ end.
+
+%%-------------------------------------------------------------------
+%% Encode
+%%-------------------------------------------------------------------
+
+encode_msg(#tftp_msg_req{access = Access,
+ filename = Filename,
+ mode = Mode,
+ options = Options}) ->
+ OpCode = case Access of
+ read -> ?TFTP_OPCODE_RRQ;
+ write -> ?TFTP_OPCODE_WRQ
+ end,
+ [
+ <<OpCode:16/integer>>,
+ Filename,
+ 0,
+ Mode,
+ 0,
+ [[Key, 0, Val, 0] || {Key, Val} <- Options]
+ ];
+encode_msg(#tftp_msg_data{block_no = BlockNo, data = Data}) when BlockNo =< 65535 ->
+ [
+ <<?TFTP_OPCODE_DATA:16/integer, BlockNo:16/integer>>,
+ Data
+ ];
+encode_msg(#tftp_msg_ack{block_no = BlockNo}) when BlockNo =< 65535 ->
+ <<?TFTP_OPCODE_ACK:16/integer, BlockNo:16/integer>>;
+encode_msg(#tftp_msg_error{code = Code, text = Text}) ->
+ IntCode = encode_error_code(Code),
+ [
+ <<?TFTP_OPCODE_ERROR:16/integer, IntCode:16/integer>>,
+ Text,
+ 0
+ ];
+encode_msg(#tftp_msg_oack{options = Options}) ->
+ [
+ <<?TFTP_OPCODE_OACK:16/integer>>,
+ [[Key, 0, Val, 0] || {Key, Val} <- Options]
+ ].
+
+encode_error_code(Code) ->
+ case Code of
+ undef -> ?TFTP_ERROR_UNDEF;
+ enoent -> ?TFTP_ERROR_ENOENT;
+ eacces -> ?TFTP_ERROR_EACCES;
+ enospc -> ?TFTP_ERROR_ENOSPC;
+ badop -> ?TFTP_ERROR_BADOP;
+ badblk -> ?TFTP_ERROR_BADBLK;
+ eexist -> ?TFTP_ERROR_EEXIST;
+ baduser -> ?TFTP_ERROR_BADUSER;
+ badopt -> ?TFTP_ERROR_BADOPT;
+ Int when is_integer(Int), Int >= 0, Int =< 65535 -> Int
+ end.
+
+%%-------------------------------------------------------------------
+%% Miscellaneous
+%%-------------------------------------------------------------------
+
+replace_val(Key, Val, List) ->
+ case lists:keysearch(Key, 1, List) of
+ false ->
+ List ++ [{Key, Val}];
+ {value, {_, OldVal}} when OldVal =:= Val ->
+ List;
+ {value, {_, _}} ->
+ lists:keyreplace(Key, 1, List, {Key, Val})
+ end.
+
+to_lower(Chars) ->
+ [?LOWER(Char) || Char <- Chars].
diff --git a/lib/tftp/src/tftp_logger.erl b/lib/tftp/src/tftp_logger.erl
new file mode 100644
index 0000000000..548ed509dc
--- /dev/null
+++ b/lib/tftp/src/tftp_logger.erl
@@ -0,0 +1,99 @@
+%%
+%% %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(tftp_logger).
+
+%%-------------------------------------------------------------------
+%% Interface
+%%-------------------------------------------------------------------
+
+%% public functions
+-export([
+ error_msg/2,
+ warning_msg/2,
+ info_msg/2
+ ]).
+
+-export([behaviour_info/1]).
+
+behaviour_info(callbacks) ->
+ [{error_msg, 2}, {warning_msg, 2}, {info_msg, 2}];
+behaviour_info(_) ->
+ undefined.
+
+%%-------------------------------------------------------------------
+%% error_msg(Format, Data) -> ok | exit(Reason)
+%%
+%% Format = string()
+%% Data = [term()]
+%% Reason = term()
+%%
+%% Log an error message
+%%-------------------------------------------------------------------
+
+error_msg(Format, Data) ->
+ {Format2, Data2} = add_timestamp(Format, Data),
+ error_logger:error_msg(Format2, Data2).
+
+%%-------------------------------------------------------------------
+%% warning_msg(Format, Data) -> ok | exit(Reason)
+%%
+%% Format = string()
+%% Data = [term()]
+%% Reason = term()
+%%
+%% Log a warning message
+%%-------------------------------------------------------------------
+
+warning_msg(Format, Data) ->
+ {Format2, Data2} = add_timestamp(Format, Data),
+ error_logger:warning_msg(Format2, Data2).
+
+%%-------------------------------------------------------------------
+%% info_msg(Format, Data) -> ok | exit(Reason)
+%%
+%% Format = string()
+%% Data = [term()]
+%% Reason = term()
+%%
+%% Log an info message
+%%-------------------------------------------------------------------
+
+info_msg(Format, Data) ->
+ {Format2, Data2} = add_timestamp(Format, Data),
+ io:format(Format2, Data2).
+
+%%-------------------------------------------------------------------
+%% Add timestamp to log message
+%%-------------------------------------------------------------------
+
+add_timestamp(Format, Data) ->
+ Time = erlang:timestamp(),
+ {{_Y, _Mo, _D}, {H, Mi, S}} = calendar:now_to_universal_time(Time),
+ %% {"~p-~s-~sT~s:~s:~sZ,~6.6.0w tftp: " ++ Format ++ "\n",
+ %% [Y, t(Mo), t(D), t(H), t(Mi), t(S), MicroSecs | Data]}.
+ {"~s:~s:~s tftp: " ++ Format, [t(H), t(Mi), t(S) | Data]}.
+
+%% Convert 9 to "09".
+t(Int) ->
+ case integer_to_list(Int) of
+ [Single] -> [$0, Single];
+ Multi -> Multi
+ end.
diff --git a/lib/tftp/src/tftp_sup.erl b/lib/tftp/src/tftp_sup.erl
new file mode 100644
index 0000000000..13b753612b
--- /dev/null
+++ b/lib/tftp/src/tftp_sup.erl
@@ -0,0 +1,111 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+%%----------------------------------------------------------------------
+%% Purpose: The top supervisor for tftp
+%%----------------------------------------------------------------------
+
+-module(tftp_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/1,
+ start_child/1,
+ stop_child/1,
+ which_children/0]).
+
+%% Supervisor callback
+-export([init/1]).
+
+%%%=========================================================================
+%%% API
+%%%=========================================================================
+
+start_link(TftpServices) ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, [TftpServices]).
+
+start_child(Options) ->
+ KillAfter = default_kill_after(),
+ ChildSpec = worker_spec(KillAfter, Options),
+ supervisor:start_child(?MODULE, ChildSpec).
+
+stop_child(Pid) when is_pid(Pid) ->
+ Children = supervisor:which_children(?MODULE),
+ case [Id || {Id, P, _Type, _Modules} <- Children, P =:= Pid] of
+ [] ->
+ {error, not_found};
+ [Id] ->
+ case supervisor:terminate_child(?MODULE, Id) of
+ ok ->
+ supervisor:delete_child(?MODULE, Id);
+ {error, not_found} ->
+ supervisor:delete_child(?MODULE, Id);
+ {error, Reason} ->
+ {error, Reason}
+ end
+ end.
+
+which_children() ->
+ Children = supervisor:which_children(?MODULE),
+ [{tftpd, Pid} || {_Id, Pid, _Type, _Modules} <- Children, Pid =/= undefined].
+
+%%%=========================================================================
+%%% Supervisor callback
+%%%=========================================================================
+
+init([Services]) when is_list(Services) ->
+ RestartStrategy = one_for_one,
+ MaxR = 10,
+ MaxT = 3600,
+ KillAfter = default_kill_after(),
+ Children = [worker_spec(KillAfter, Options) || {tftpd, Options} <- Services],
+ {ok, {{RestartStrategy, MaxR, MaxT}, Children}}.
+
+%%%=========================================================================
+%%% Internal functions
+%%%=========================================================================
+
+worker_spec(KillAfter, Options) ->
+ Modules = [proc_lib, tftp, tftp_engine],
+ KA = supervisor_timeout(KillAfter),
+ Name = unique_name(Options),
+ {Name, {tftp, start, [Options]}, permanent, KA, worker, Modules}.
+
+unique_name(Options) ->
+ case lists:keysearch(port, 1, Options) of
+ {value, {_, Port}} when is_integer(Port), Port > 0 ->
+ {tftpd, Port};
+ _ ->
+ {tftpd, erlang:unique_integer([positive])}
+ end.
+
+default_kill_after() ->
+ timer:seconds(3).
+
+%% supervisor_spec(Name) ->
+%% {Name, {Name, start, []}, permanent, infinity, supervisor,
+%% [Name, supervisor]}.
+
+-ifdef(debug_shutdown).
+supervisor_timeout(_KillAfter) -> timer:hours(24).
+-else.
+supervisor_timeout(KillAfter) -> KillAfter.
+-endif.
diff --git a/lib/tftp/test/Makefile b/lib/tftp/test/Makefile
new file mode 100644
index 0000000000..99f36256b0
--- /dev/null
+++ b/lib/tftp/test/Makefile
@@ -0,0 +1,250 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# 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%
+#
+#
+# For an outline of how this all_SUITE_data stuff works, see the
+# make file ../../ssl/test/Makefile.
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+VSN = $(TFTP_VSN)
+
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
+
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+INCLUDES = -I. \
+ -I$(ERL_TOP)/lib/tftp/src
+
+CP = cp
+
+ifeq ($(TESTROOT_DIR),)
+TESTROOT_DIR = /ldisk/tests/$(USER)/tftp
+endif
+
+ifeq ($(TFTP_DATA_DIR),)
+TFTP_DATA_DIR = $(TESTROOT_DIR)/data_dir
+endif
+
+ifeq ($(TFTP_PRIV_DIR),)
+TFTP_PRIV_DIR = $(TESTROOT_DIR)/priv_dir
+endif
+
+TFTP_FLAGS = -Dtftp__data_dir='"$(TFTP_DATA_DIR)"' \
+ -Dtftp_priv_dir='"$(TFTP_PRIV_DIR)"'
+
+
+###
+### test suite debug flags
+###
+ifeq ($(TFTP_DEBUG_CLIENT),)
+ TFTP_DEBUG_CLIENT = y
+endif
+
+ifeq ($(TFTP_DEBUG_CLIENT),)
+ TFTP_FLAGS += -Dtftp_debug_client
+endif
+
+ifeq ($(TFTP_TRACE_CLIENT),)
+ TFTP_DEBUG_CLIENT = y
+endif
+
+ifeq ($(TFTP_TRACE_CLIENT),y)
+ TFTP_FLAGS += -Dtftp_trace_client
+endif
+
+ifneq ($(TFTP_DEBUG),)
+ TFTP_DEBUG = s
+endif
+
+ifeq ($(TFTP_DEBUG),l)
+ TFTP_FLAGS += -Dtftp_log
+endif
+
+ifeq ($(TFTP_DEBUG),d)
+ TFTP_FLAGS += -Dtftp_debug -Dtftp_log
+endif
+
+
+TFTP_FLAGS += -pa ../tftp/ebin
+
+TFTP_ROOT = ../tftp
+
+MODULES = \
+ tftp_SUITE \
+ tftp_test_lib
+
+
+EBIN = .
+
+HRL_FILES = \
+ ../src/tftp.hrl \
+ tftp_test_lib.hrl
+
+ERL_FILES = $(MODULES:%=%.erl)
+
+SOURCE = $(ERL_FILES) $(HRL_FILES)
+
+TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+TFTP_SPECS = tftp.spec tftp_bench.spec
+COVER_FILE = tftp.cover
+TFTP_FILES = tftp.config $(TFTP_SPECS)
+
+
+TFTP_DATADIRS = tftp_SUITE_data
+
+DATADIRS = $(TFTP_DATADIRS)
+
+EMAKEFILE = Emakefile
+MAKE_EMAKE = $(wildcard $(ERL_TOP)/make/make_emakefile)
+
+ifeq ($(MAKE_EMAKE),)
+BUILDTARGET = $(TARGET_FILES)
+RELTEST_FILES = $(COVER_FILE) $(TFTP_SPECS) $(SOURCE)
+else
+BUILDTARGET = emakebuild
+RELTEST_FILES = $(EMAKEFILE) $(COVER_FILE) $(TFTP_SPECS) $(SOURCE)
+endif
+
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+
+RELTESTSYSDIR = "$(RELEASE_PATH)/tftp_test"
+RELTESTSYSALLDATADIR = $(RELTESTSYSDIR)/all_SUITE_data
+RELTESTSYSBINDIR = $(RELTESTSYSALLDATADIR)/bin
+
+
+# ----------------------------------------------------
+# FLAGS
+# The path to the test_server ebin dir is needed when
+# running the target "targets".
+# ----------------------------------------------------
+ERL_COMPILE_FLAGS += \
+ $(INCLUDES) \
+ $(TFTP_FLAGS)
+
+# ----------------------------------------------------
+# Targets
+# erl -sname kalle -pa ../ebin
+# If you intend to run the test suite locally (private), then
+# there is some requirements:
+# 1) TFTP_PRIV_DIR must be created
+# ----------------------------------------------------
+
+tests debug opt: $(BUILDTARGET)
+
+targets: $(TARGET_FILES)
+
+.PHONY: emakebuild
+
+emakebuild: $(EMAKEFILE)
+
+$(EMAKEFILE):
+ $(MAKE_EMAKE) $(ERL_COMPILE_FLAGS) -o$(EBIN) '*_SUITE_make' | grep -v Warning > $(EMAKEFILE)
+ $(MAKE_EMAKE) $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) | grep -v Warning >> $(EMAKEFILE)
+
+clean:
+ rm -f $(EMAKEFILE)
+ rm -f $(TARGET_FILES)
+ rm -f core *~
+
+docs:
+
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+ $(INSTALL_DIR) "$(RELSYSDIR)/test"
+ $(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) "$(RELSYSDIR)/test"
+ $(INSTALL_DATA) $(TFTP_FILES) "$(RELSYSDIR)/test"
+ @for d in $(DATADIRS); do \
+ echo "installing data dir $$d"; \
+ if test -f $$d/TAR.exclude; then \
+ echo $$d/TAR.exclude2 > $$d/TAR.exclude2; \
+ cat $$d/TAR.exclude >> $$d/TAR.exclude2; \
+ find $$d -name '*.contrib*' >> $$d/TAR.exclude2; \
+ find $$d -name '*.keep*' >> $$d/TAR.exclude2; \
+ find $$d -name '*.mkelem*' >> $$d/TAR.exclude2; \
+ find $$d -name '*~' >> $$d/TAR.exclude2; \
+ find $$d -name 'erl_crash.dump' >> $$d/TAR.exclude2; \
+ find $$d -name 'core' >> $$d/TAR.exclude2; \
+ find $$d -name '.cmake.state' >> $$d/TAR.exclude2; \
+ tar cfX - $$d/TAR.exclude2 $$d | (cd "$(RELSYSDIR)/test"; tar xf -); \
+ else \
+ tar cf - $$d | (cd "$(RELSYSDIR)/test"; tar xf -); \
+ fi; \
+ done
+
+release_tests_spec: opt
+ $(INSTALL_DIR) $(RELTESTSYSDIR)
+ $(INSTALL_DATA) $(RELTEST_FILES) $(RELTESTSYSDIR)
+ chmod -R u+w $(RELTESTSYSDIR)
+ tar chf - $(DATADIRS) | (cd $(RELTESTSYSDIR); tar xf -)
+ $(INSTALL_DIR) $(RELTESTSYSALLDATADIR)
+ $(INSTALL_DIR) $(RELTESTSYSBINDIR)
+ chmod -R +x $(RELTESTSYSBINDIR)
+ $(INSTALL_DIR) $(RELTESTSYSALLDATADIR)/win32/lib
+
+release_docs_spec:
+
+info:
+ @echo "MAKE_EMAKE = $(MAKE_EMAKE)"
+ @echo "EMAKEFILE = $(EMAKEFILE)"
+ @echo "BUILDTARGET = $(BUILDTARGET)"
+ @echo ""
+ @echo "MODULES = $(MODULES)"
+ @echo "ERL_FILES = $(ERL_FILES)"
+ @echo "SOURCE = $(SOURCE)"
+ @echo "TARGET_FILES = $(TARGET_FILES)"
+ @echo ""
+ @echo "TFTP_SPECS = $(TFTP_SPECS)"
+ @echo "TFTP_FILES = $(TFTP_FILES)"
+ @echo ""
+ @echo "RELEASE_PATH = "$(RELEASE_PATH)""
+ @echo "RELSYSDIR = "$(RELSYSDIR)""
+ @echo "RELTESTSYSDIR = $(RELTESTSYSDIR)"
+ @echo "RELTESTSYSALLDATADIR = $(RELTESTSYSALLDATADIR)"
+ @echo "RELTESTSYSBINDIR = $(RELTESTSYSBINDIR)"
+ @echo ""
+ @echo "DATADIRS = $(DATADIRS)"
+ @echo "REL_DATADIRS = $(REL_DATADIRS)"
+ @echo ""
+ @echo "TFTP_DATA_DIR = $(TFTP_DATA_DIR)"
+ @echo "TFTP_PRIV_DIR = $(TFTP_PRIV_DIR)"
+ @echo "TFTP_ROOT = $(TFTP_ROOT)"
+ @echo "TFTP_FLAGS = $(TFTP_FLAGS)"
+
+
diff --git a/lib/tftp/test/tftp.config b/lib/tftp/test/tftp.config
new file mode 100644
index 0000000000..2600237da9
--- /dev/null
+++ b/lib/tftp/test/tftp.config
@@ -0,0 +1 @@
+[]. \ No newline at end of file
diff --git a/lib/tftp/test/tftp.cover b/lib/tftp/test/tftp.cover
new file mode 100644
index 0000000000..22ef5d0dda
--- /dev/null
+++ b/lib/tftp/test/tftp.cover
@@ -0,0 +1,2 @@
+{incl_app,tftp,details}.
+
diff --git a/lib/tftp/test/tftp.spec b/lib/tftp/test/tftp.spec
new file mode 100644
index 0000000000..f3537bc652
--- /dev/null
+++ b/lib/tftp/test/tftp.spec
@@ -0,0 +1 @@
+{suites,"../tftp_test", all}.
diff --git a/lib/tftp/test/tftp_SUITE.erl b/lib/tftp/test/tftp_SUITE.erl
new file mode 100644
index 0000000000..a0f6cb1ca4
--- /dev/null
+++ b/lib/tftp/test/tftp_SUITE.erl
@@ -0,0 +1,1001 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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(tftp_SUITE).
+
+-compile(export_all).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Includes and defines
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-include_lib("common_test/include/ct.hrl").
+-include("tftp_test_lib.hrl").
+
+-define(START_DAEMON(Port, Options),
+ begin
+ {ok, Pid} = ?VERIFY({ok, _Pid}, tftp:start([{port, Port} | Options])),
+ if
+ Port == 0 ->
+ {ok, ActualOptions} = ?IGNORE(tftp:info(Pid)),
+ {value, {port, ActualPort}} =
+ lists:keysearch(port, 1, ActualOptions),
+ {ActualPort, Pid};
+ true ->
+ {Port, Pid}
+ end
+ end).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% API
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+t() ->
+ tftp_test_lib:t([{?MODULE, all}]).
+
+t(Cases) ->
+ tftp_test_lib:t(Cases, default_config()).
+
+t(Cases, Config) ->
+ tftp_test_lib:t(Cases, Config).
+
+default_config() ->
+ [].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Test server callbacks
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+init_per_testcase(Case, Config) ->
+ tftp_test_lib:init_per_testcase(Case, Config).
+
+end_per_testcase(Case, Config) when is_list(Config) ->
+ tftp_test_lib:end_per_testcase(Case, Config).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Top test case
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [
+ simple,
+ extra,
+ reuse_connection,
+ resend_client,
+ resend_server,
+ large_file,
+ app,
+ appup,
+ start_tftpd
+ ].
+
+groups() ->
+ [].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+app() ->
+ [{doc, "Test that the tftp app file is ok"}].
+app(Config) when is_list(Config) ->
+ ok = ?t:app_test(tftp).
+
+%%--------------------------------------------------------------------
+appup() ->
+ [{doc, "Test that the tftp appup file is ok"}].
+appup(Config) when is_list(Config) ->
+ ok = ?t:appup_test(tftp).
+
+start_tftpd() ->
+ [{doc, "Start/stop of tfpd service"}].
+start_tftpd(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ ok = tftp:start(),
+ {ok, Pid0} = tftp:start_service([{host, "localhost"}, {port, 0}]),
+ Pids0 = [ServicePid || {_, ServicePid} <- tftp:services()],
+ true = lists:member(Pid0, Pids0),
+ {ok, [_|_]} = tftp:service_info(Pid0),
+ tftp:stop_service(Pid0),
+ ct:sleep(100),
+ Pids1 = [ServicePid || {_, ServicePid} <- tftp:services()],
+ false = lists:member(Pid0, Pids1),
+
+ {ok, Pid1} =
+ tftp:start_standalone([{host, "localhost"}, {port, 0}]),
+ Pids2 = [ServicePid || {_, ServicePid} <- tftp:services()],
+ false = lists:member(Pid1, Pids2),
+ %% Standalone service is not supervised
+ {error,not_found} = tftp:stop_service(Pid1),
+ ok = tftp:stop(),
+
+ application:load(tftp),
+ application:set_env(tftp, services, [{tftpd, [{host, "localhost"},
+ {port, 0}]}]),
+ ok = tftp:start(),
+ 1 = length(tftp:services()),
+ application:unset_env(tftp, services),
+ ok = tftp:stop().
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Simple
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+simple(doc) ->
+ ["Start the daemon and perform simple a read and write."];
+simple(suite) ->
+ [];
+simple(Config) when is_list(Config) ->
+ ?VERIFY(ok, application:start(tftp)),
+
+ {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, brief}])),
+
+ %% Read fail
+ RemoteFilename = "tftp_temporary_remote_test_file.txt",
+ LocalFilename = "tftp_temporary_local_test_file.txt",
+ Blob = list_to_binary(lists:duplicate(2000, $1)),
+ %% Blob = <<"Some file contents\n">>,
+ Size = size(Blob),
+ ?IGNORE(file:delete(RemoteFilename)),
+ ?VERIFY({error, {client_open, enoent, _}},
+ tftp:read_file(RemoteFilename, binary, [{port, Port}])),
+
+ %% Write and read
+ ?VERIFY({ok, Size}, tftp:write_file(RemoteFilename, Blob, [{port, Port}])),
+ ?VERIFY({ok, Blob}, tftp:read_file(RemoteFilename, binary, [{port, Port}])),
+ ?IGNORE(file:delete(LocalFilename)),
+ ?VERIFY({ok, Size}, tftp:read_file(RemoteFilename, LocalFilename, [{port, Port}])),
+
+ %% Cleanup
+ unlink(DaemonPid),
+ exit(DaemonPid, kill),
+ ?VERIFY(ok, file:delete(LocalFilename)),
+ ?VERIFY(ok, file:delete(RemoteFilename)),
+ ?VERIFY(ok, application:stop(tftp)),
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Extra
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+extra(doc) ->
+ ["Verify new stuff for IS 1.2."];
+extra(suite) ->
+ [];
+extra(Config) when is_list(Config) ->
+ ?VERIFY({'EXIT', {badarg,{fake_key, fake_flag}}},
+ tftp:start([{port, 0}, {fake_key, fake_flag}])),
+
+ {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, brief}])),
+
+ RemoteFilename = "tftp_extra_temporary_remote_test_file.txt",
+ LocalFilename = "tftp_extra_temporary_local_test_file.txt",
+ Blob = <<"Some file contents\n">>,
+ Size = size(Blob),
+ Host = "127.0.0.1",
+ Peer = {inet, Host, Port},
+ Generic =
+ [
+ {state, []},
+ {prepare, fun extra_prepare/6},
+ {open, fun extra_open/6},
+ {read, fun extra_read/1},
+ {write, fun extra_write/2},
+ {abort, fun extra_abort/3 }
+ ],
+ Options = [{host, Host},
+ {port, Port},
+ %%{ debug,all},
+ {callback, {".*", tftp_test_lib, Generic}}],
+ ?VERIFY(ok, file:write_file(LocalFilename, Blob)),
+ ?VERIFY({ok, [{count, Size}, Peer]},
+ tftp:write_file(RemoteFilename, LocalFilename, Options)),
+ ?VERIFY(ok, file:delete(LocalFilename)),
+
+ ?VERIFY({ok,[{bin, Blob}, Peer]},
+ tftp:read_file(RemoteFilename, LocalFilename, Options)),
+
+ %% Cleanup
+ unlink(DaemonPid),
+ exit(DaemonPid, kill),
+ ?VERIFY(ok, file:delete(LocalFilename)),
+ ?VERIFY(ok, file:delete(RemoteFilename)),
+ ok.
+
+-record(extra_state, {file, blksize, count, acc, peer}).
+
+%%-------------------------------------------------------------------
+%% Prepare
+%%-------------------------------------------------------------------
+
+extra_prepare(Peer, Access, LocalFilename, Mode, SuggestedOptions, []) ->
+ %% Client side
+ BlkSize = list_to_integer(tftp_test_lib:lookup_option("blksize", "512", SuggestedOptions)),
+ State = #extra_state{blksize = BlkSize, peer = Peer},
+ extra_open(Peer, Access, LocalFilename, Mode, SuggestedOptions, State),
+ {ok, SuggestedOptions, State};
+extra_prepare(_Peer, _Access, _Bin, _Mode, _SuggestedOptions, _Initial) ->
+ {error, {undef, "Illegal callback options."}}.
+
+%%-------------------------------------------------------------------
+%% Open
+%%-------------------------------------------------------------------
+
+extra_open(Peer, Access, LocalFilename, Mode, SuggestedOptions, []) ->
+ %% Server side
+ case extra_prepare(Peer, Access, LocalFilename, Mode, SuggestedOptions, []) of
+ {ok, AcceptedOptions, []} ->
+ BlkSize = list_to_integer(tftp_test_lib:lookup_option("blksize", "512", AcceptedOptions)),
+ State = #extra_state{blksize = BlkSize, peer = Peer},
+ extra_open(Peer, Access, LocalFilename, Mode, AcceptedOptions, State);
+ {error, {Code, Text}} ->
+ {error, {Code, Text}}
+ end;
+extra_open(_Peer, Access, LocalFilename, _Mode, NegotiatedOptions, #extra_state{} = State) ->
+ {File, Acc} =
+ case Access of
+ read ->
+ if
+ is_binary(LocalFilename) ->
+ {undefined, LocalFilename};
+ is_list(LocalFilename) ->
+ {ok, Bin} = file:read_file(LocalFilename),
+ {LocalFilename, Bin}
+ end;
+ write ->
+ {LocalFilename, []}
+ end,
+ %% Both sides
+ State2 = State#extra_state{file = File, acc = Acc, count = 0},
+ {ok, NegotiatedOptions, State2}.
+
+%%-------------------------------------------------------------------
+%% Read
+%%-------------------------------------------------------------------
+
+extra_read(#extra_state{acc = Bin} = State) when is_binary(Bin) ->
+ BlkSize = State#extra_state.blksize,
+ Count = State#extra_state.count + size(Bin),
+ if
+ size(Bin) >= BlkSize ->
+ <<Block:BlkSize/binary, Bin2/binary>> = Bin,
+ State2 = State#extra_state{acc = Bin2, count = Count},
+ {more, Block, State2};
+ size(Bin) < BlkSize ->
+ Res = [{count, Count}, State#extra_state.peer],
+ {last, Bin, Res}
+ end.
+
+%%-------------------------------------------------------------------
+%% Write
+%%-------------------------------------------------------------------
+
+extra_write(Bin, #extra_state{acc = List} = State) when is_binary(Bin), is_list(List) ->
+ Size = size(Bin),
+ BlkSize = State#extra_state.blksize,
+ if
+ Size == BlkSize ->
+ {more, State#extra_state{acc = [Bin | List]}};
+ Size < BlkSize ->
+ Bin2 = list_to_binary(lists:reverse([Bin | List])),
+ Res = [{bin, Bin2}, State#extra_state.peer],
+ file:write_file(State#extra_state.file, Bin2),
+ {last, Res}
+ end.
+
+%%-------------------------------------------------------------------
+%% Abort
+%%-------------------------------------------------------------------
+
+extra_abort(_Code, _Text, #extra_state{}) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Re-send client
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+resend_client(doc) ->
+ ["Verify that the server behaves correctly when the client re-sends packets."];
+resend_client(suite) ->
+ [];
+resend_client(Config) when is_list(Config) ->
+ Host = {127, 0, 0, 1},
+ {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, all}])),
+
+ ?VERIFY(ok, resend_read_client(Host, Port, 10)),
+ ?VERIFY(ok, resend_read_client(Host, Port, 512)),
+ ?VERIFY(ok, resend_read_client(Host, Port, 1025)),
+
+ ?VERIFY(ok, resend_write_client(Host, Port, 10)),
+ ?VERIFY(ok, resend_write_client(Host, Port, 512)),
+ ?VERIFY(ok, resend_write_client(Host, Port, 1025)),
+
+ %% Cleanup
+ unlink(DaemonPid),
+ exit(DaemonPid, kill),
+ ok.
+
+resend_read_client(Host, Port, BlkSize) ->
+ RemoteFilename = "tftp_resend_read_client.tmp",
+ Block1 = lists:duplicate(BlkSize, $1),
+ Block2 = lists:duplicate(BlkSize, $2),
+ Block3 = lists:duplicate(BlkSize, $3),
+ Block4 = lists:duplicate(BlkSize, $4),
+ Block5 = lists:duplicate(BlkSize, $5),
+ Blocks = [Block1, Block2, Block3, Block4, Block5],
+ Blob = list_to_binary(Blocks),
+ ?VERIFY(ok, file:write_file(RemoteFilename, Blob)),
+
+ Timeout = timer:seconds(3),
+ ?VERIFY(timeout, recv(0)),
+
+ %% Open socket
+ {ok, Socket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
+
+ ReadList = [0, 1, RemoteFilename, 0, "octet", 0],
+ Data1Bin = list_to_binary([0, 3, 0, 1 | Block1]),
+ NewPort =
+ if
+ BlkSize =:= 512 ->
+ %% Send READ
+ ReadBin = list_to_binary(ReadList),
+ ?VERIFY(ok, gen_udp:send(Socket, Host, Port, ReadBin)),
+
+ %% Sleep a while in order to provoke the server to re-send the packet
+ timer:sleep(Timeout + timer:seconds(1)),
+
+ %% Recv DATA #1 (the packet that the server think that we have lost)
+ {udp, _, _, NewPort0, _} = ?VERIFY({udp, Socket, Host, _, Data1Bin}, recv(Timeout)),
+ NewPort0;
+ true ->
+ %% Send READ
+ BlkSizeList = integer_to_list(BlkSize),
+ Options = ["blksize", 0, BlkSizeList, 0],
+ ReadBin = list_to_binary([ReadList | Options]),
+ ?VERIFY(ok, gen_udp:send(Socket, Host, Port, ReadBin)),
+
+ %% Recv OACK
+ OptionAckBin = list_to_binary([0, 6 | Options]),
+ {udp, _, _, NewPort0, _} = ?VERIFY({udp, Socket, Host, _, OptionAckBin}, recv(Timeout)),
+
+ %% Send ACK #0
+ Ack0Bin = <<0, 4, 0, 0>>,
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort0, Ack0Bin)),
+
+ %% Send ACK #0 AGAIN (pretend that we timed out)
+ timer:sleep(timer:seconds(1)),
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort0, Ack0Bin)),
+
+ %% Recv DATA #1 (the packet that the server think that we have lost)
+ ?VERIFY({udp, Socket, Host, NewPort0, Data1Bin}, recv(Timeout)),
+ NewPort0
+ end,
+
+ %% Recv DATA #1 AGAIN (the re-sent package)
+ ?VERIFY({udp, Socket, Host, NewPort, Data1Bin}, recv(Timeout)),
+
+ %% Send ACK #1
+ Ack1Bin = <<0, 4, 0, 1>>,
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack1Bin)),
+
+ %% Recv DATA #2
+ Data2Bin = list_to_binary([0, 3, 0, 2 | Block2]),
+ ?VERIFY({udp, Socket, Host, NewPort, Data2Bin}, recv(Timeout)),
+
+ %% Send ACK #2
+ Ack2Bin = <<0, 4, 0, 2>>,
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack2Bin)),
+
+ %% Recv DATA #3
+ Data3Bin = list_to_binary([0, 3, 0, 3 | Block3]),
+ ?VERIFY({udp, Socket, Host, NewPort, Data3Bin}, recv(Timeout)),
+
+ %% Send ACK #3
+ Ack3Bin = <<0, 4, 0, 3>>,
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack3Bin)),
+
+ %% Send ACK #3 AGAIN (pretend that we timed out)
+ timer:sleep(timer:seconds(1)),
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack3Bin)),
+
+ %% Recv DATA #4 (the packet that the server think that we have lost)
+ Data4Bin = list_to_binary([0, 3, 0, 4 | Block4]),
+ ?VERIFY({udp, Socket, Host, NewPort, Data4Bin}, recv(Timeout)),
+
+ %% Recv DATA #4 AGAIN (the re-sent package)
+ ?VERIFY({udp, Socket, Host, NewPort, Data4Bin}, recv(Timeout)),
+
+ %% Send ACK #2 which is out of range
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack2Bin)),
+
+ %% Send ACK #4
+ Ack4Bin = <<0, 4, 0, 4>>,
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack4Bin)),
+
+ %% Recv DATA #5
+ Data5Bin = list_to_binary([0, 3, 0, 5 | Block5]),
+ ?VERIFY({udp, Socket, Host, NewPort, Data5Bin}, recv(Timeout)),
+
+ %% Send ACK #5
+ Ack5Bin = <<0, 4, 0, 5>>,
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack5Bin)),
+
+ %% Close socket
+ ?VERIFY(ok, gen_udp:close(Socket)),
+
+ ?VERIFY(timeout, recv(Timeout)),
+ ?VERIFY(ok, file:delete(RemoteFilename)),
+ ok.
+
+resend_write_client(Host, Port, BlkSize) ->
+ RemoteFilename = "tftp_resend_write_client.tmp",
+ Block1 = lists:duplicate(BlkSize, $1),
+ Block2 = lists:duplicate(BlkSize, $2),
+ Block3 = lists:duplicate(BlkSize, $3),
+ Block4 = lists:duplicate(BlkSize, $4),
+ Block5 = lists:duplicate(BlkSize, $5),
+ Blocks = [Block1, Block2, Block3, Block4, Block5],
+ Blob = list_to_binary(Blocks),
+ ?IGNORE(file:delete(RemoteFilename)),
+ ?VERIFY({error, enoent}, file:read_file(RemoteFilename)),
+
+ Timeout = timer:seconds(3),
+ ?VERIFY(timeout, recv(0)),
+
+ %% Open socket
+ {ok, Socket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
+
+ WriteList = [0, 2, RemoteFilename, 0, "octet", 0],
+ NewPort =
+ if
+ BlkSize =:= 512 ->
+ %% Send WRITE
+ WriteBin = list_to_binary(WriteList),
+ ?VERIFY(ok, gen_udp:send(Socket, Host, Port, WriteBin)),
+
+ %% Sleep a while in order to provoke the server to re-send the packet
+ timer:sleep(Timeout + timer:seconds(1)),
+
+ %% Recv ACK #0 (the packet that the server think that we have lost)
+ Ack0Bin = <<0, 4, 0, 0>>,
+ ?VERIFY({udp, Socket, Host, _, Ack0Bin}, recv(Timeout)),
+
+ %% Recv ACK #0 AGAIN (the re-sent package)
+ {udp, _, _, NewPort0, _} = ?VERIFY({udp, Socket, Host, _, Ack0Bin}, recv(Timeout)),
+ NewPort0;
+ true ->
+ %% Send WRITE
+ BlkSizeList = integer_to_list(BlkSize),
+ WriteBin = list_to_binary([WriteList, "blksize", 0, BlkSizeList, 0]),
+ ?VERIFY(ok, gen_udp:send(Socket, Host, Port, WriteBin)),
+
+ %% Sleep a while in order to provoke the server to re-send the packet
+ timer:sleep(timer:seconds(1)),
+
+ %% Recv OACK (the packet that the server think that we have lost)
+ OptionAckBin = list_to_binary([0, 6, "blksize",0, BlkSizeList, 0]),
+ ?VERIFY({udp, Socket, Host, _, OptionAckBin}, recv(Timeout)),
+
+ %% Recv OACK AGAIN (the re-sent package)
+ {udp, _, _, NewPort0, _} = ?VERIFY({udp, Socket, Host, _, OptionAckBin}, recv(Timeout)),
+ NewPort0
+ end,
+
+ %% Send DATA #1
+ Data1Bin = list_to_binary([0, 3, 0, 1 | Block1]),
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data1Bin)),
+
+ %% Recv ACK #1
+ Ack1Bin = <<0, 4, 0, 1>>,
+ ?VERIFY({udp, Socket, Host, NewPort, Ack1Bin}, recv(Timeout)),
+
+ %% Send DATA #2
+ Data2Bin = list_to_binary([0, 3, 0, 2 | Block2]),
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data2Bin)),
+
+ %% Recv ACK #2
+ Ack2Bin = <<0, 4, 0, 2>>,
+ ?VERIFY({udp, Socket, Host, NewPort, Ack2Bin}, recv(Timeout)),
+
+ %% Send DATA #3
+ Data3Bin = list_to_binary([0, 3, 0, 3 | Block3]),
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data3Bin)),
+
+ %% Recv ACK #3
+ Ack3Bin = <<0, 4, 0, 3>>,
+ ?VERIFY({udp, Socket, Host, NewPort, Ack3Bin}, recv(Timeout)),
+
+ %% Send DATA #3 AGAIN (pretend that we timed out)
+ timer:sleep(timer:seconds(1)),
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data3Bin)),
+
+ %% Recv ACK #3 AGAIN (the packet that the server think that we have lost)
+ ?VERIFY({udp, Socket, Host, NewPort, Ack3Bin}, recv(Timeout)),
+
+ %% Send DATA #2 which is out of range
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data2Bin)),
+
+ %% Send DATA #4
+ Data4Bin = list_to_binary([0, 3, 0, 4 | Block4]),
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data4Bin)),
+
+ %% Recv ACK #4
+ Ack4Bin = <<0, 4, 0, 4>>,
+ ?VERIFY({udp, Socket, Host, NewPort, Ack4Bin}, recv(Timeout)),
+
+ %% Send DATA #5
+ Data5Bin = list_to_binary([0, 3, 0, 5 | Block5]),
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Data5Bin)),
+
+ %% Recv ACK #5
+ Ack5Bin = <<0, 4, 0, 5>>,
+ ?VERIFY({udp, Socket, Host, NewPort, Ack5Bin}, recv(Timeout)),
+
+ %% Close socket
+ ?VERIFY(ok, gen_udp:close(Socket)),
+
+ ?VERIFY(timeout, recv(Timeout)),
+ ?VERIFY({ok, Blob}, file:read_file(RemoteFilename)),
+ ?VERIFY(ok, file:delete(RemoteFilename)),
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Re-send server
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+resend_server(doc) ->
+ ["Verify that the server behaves correctly when the server re-sends packets."];
+resend_server(suite) ->
+ [];
+resend_server(Config) when is_list(Config) ->
+ Host = {127, 0, 0, 1},
+
+ ?VERIFY(ok, resend_read_server(Host, 10)),
+ ?VERIFY(ok, resend_read_server(Host, 512)),
+ ?VERIFY(ok, resend_read_server(Host, 1025)),
+
+ ?VERIFY(ok, resend_write_server(Host, 10)),
+ ?VERIFY(ok, resend_write_server(Host, 512)),
+ ?VERIFY(ok, resend_write_server(Host, 1025)),
+ ok.
+
+resend_read_server(Host, BlkSize) ->
+ RemoteFilename = "tftp_resend_read_server.tmp",
+ Block1 = lists:duplicate(BlkSize, $1),
+ Block2 = lists:duplicate(BlkSize, $2),
+ Block3 = lists:duplicate(BlkSize, $3),
+ Block4 = lists:duplicate(BlkSize, $4),
+ Block5 = lists:duplicate(BlkSize, $5),
+ Block6 = [],
+ Blocks = [Block1, Block2, Block3, Block4, Block5, Block6],
+ Blob = list_to_binary(Blocks),
+
+ Timeout = timer:seconds(3),
+ ?VERIFY(timeout, recv(0)),
+
+ %% Open daemon socket
+ {ok, DaemonSocket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
+ {ok, DaemonPort} = ?IGNORE(inet:port(DaemonSocket)),
+
+ %% Open server socket
+ {ok, ServerSocket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
+ ?IGNORE(inet:port(ServerSocket)),
+
+ %% Prepare client process
+ ReplyTo = self(),
+ ClientFun =
+ fun(Extra) ->
+ Options = [{port, DaemonPort}, {debug, brief}] ++ Extra,
+ Res = ?VERIFY({ok, Blob}, tftp:read_file(RemoteFilename, binary, Options)),
+ ReplyTo ! {self(), {tftp_client_reply, Res}},
+ exit(normal)
+ end,
+
+ ReadList = [0, 1, RemoteFilename, 0, "octet", 0],
+ Data1Bin = list_to_binary([0, 3, 0, 1 | Block1]),
+ Ack1Bin = <<0, 4, 0, 1>>,
+ {ClientPort, ClientPid} =
+ if
+ BlkSize =:= 512 ->
+ %% Start client process
+ ClientPid0 = spawn_link(fun() -> ClientFun([]) end),
+
+ %% Recv READ
+ ReadBin = list_to_binary(ReadList),
+ {udp, _, _, ClientPort0, _} = ?VERIFY({udp, DaemonSocket, Host, _, ReadBin}, recv(Timeout)),
+
+ %% Send DATA #1
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort0, Data1Bin)),
+
+ %% Sleep a while in order to provoke the client to re-send the packet
+ timer:sleep(Timeout + timer:seconds(1)),
+
+ %% Recv ACK #1 (the packet that the server think that we have lost)
+ ?VERIFY({udp, ServerSocket, Host, ClientPort0, Ack1Bin}, recv(Timeout)),
+
+ %% Recv ACK #1 AGAIN (the re-sent package)
+ ?VERIFY({udp, ServerSocket, Host, _, Ack1Bin}, recv(Timeout)),
+ {ClientPort0, ClientPid0};
+ true ->
+ %% Start client process
+ BlkSizeList = integer_to_list(BlkSize),
+ ClientPid0 = spawn_link(fun() -> ClientFun([{"blksize", BlkSizeList}]) end),
+
+ %% Recv READ
+ Options = ["blksize", 0, BlkSizeList, 0],
+ ReadBin = list_to_binary([ReadList | Options]),
+ {udp, _, _, ClientPort0, _} = ?VERIFY({udp, DaemonSocket, Host, _, ReadBin}, recv(Timeout)),
+
+ %% Send OACK
+ BlkSizeList = integer_to_list(BlkSize),
+ OptionAckBin = list_to_binary([0, 6, "blksize",0, BlkSizeList, 0]),
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort0, OptionAckBin)),
+
+ %% Sleep a while in order to provoke the client to re-send the packet
+ timer:sleep(Timeout + timer:seconds(1)),
+
+ %% Recv ACK #0 (the packet that the server think that we have lost)
+ Ack0Bin = <<0, 4, 0, 0>>,
+ ?VERIFY({udp, ServerSocket, Host, ClientPort0, Ack0Bin}, recv(Timeout)),
+
+ %% Recv ACK #0 AGAIN (the re-sent package)
+ ?VERIFY({udp, ServerSocket, Host, ClientPort0, Ack0Bin}, recv(Timeout)),
+
+ %% Send DATA #1
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort0, Data1Bin)),
+
+ %% Recv ACK #1
+ ?VERIFY({udp, ServerSocket, Host, _, Ack1Bin}, recv(Timeout)),
+ {ClientPort0, ClientPid0}
+ end,
+
+ %% Send DATA #2
+ Data2Bin = list_to_binary([0, 3, 0, 2 | Block2]),
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data2Bin)),
+
+ %% Recv ACK #2
+ Ack2Bin = <<0, 4, 0, 2>>,
+ ?VERIFY({udp, ServerSocket, Host, ClientPort, Ack2Bin}, recv(Timeout)),
+
+ %% Send DATA #3
+ Data3Bin = list_to_binary([0, 3, 0, 3 | Block3]),
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data3Bin)),
+
+ %% Recv ACK #3
+ Ack3Bin = <<0, 4, 0, 3>>,
+ ?VERIFY({udp, ServerSocket, Host, ClientPort, Ack3Bin}, recv(Timeout)),
+
+ %% Send DATA #3 AGAIN (pretend that we timed out)
+ timer:sleep(timer:seconds(1)),
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data3Bin)),
+
+ %% Recv ACK #3 AGAIN (the packet that the server think that we have lost)
+ ?VERIFY({udp, ServerSocket, Host, ClientPort, Ack3Bin}, recv(Timeout)),
+
+ %% Send DATA #4
+ Data4Bin = list_to_binary([0, 3, 0, 4 | Block4]),
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data4Bin)),
+
+ %% Recv ACK #4
+ Ack4Bin = <<0, 4, 0, 4>>,
+ ?VERIFY({udp, ServerSocket, Host, ClientPort, Ack4Bin}, recv(Timeout)),
+
+ %% Send DATA #3 which is out of range
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data3Bin)),
+
+ %% Send DATA #5
+ Data5Bin = list_to_binary([0, 3, 0, 5 | Block5]),
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data5Bin)),
+
+ %% Recv ACK #5
+ Ack5Bin = <<0, 4, 0, 5>>,
+ ?VERIFY({udp, ServerSocket, Host, ClientPort, Ack5Bin}, recv(Timeout)),
+
+ %% Send DATA #6
+ Data6Bin = list_to_binary([0, 3, 0, 6 | Block6]),
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Data6Bin)),
+
+ %% Close daemon and server sockets
+ ?VERIFY(ok, gen_udp:close(ServerSocket)),
+ ?VERIFY(ok, gen_udp:close(DaemonSocket)),
+
+ ?VERIFY({ClientPid, {tftp_client_reply, {ok, Blob}}}, recv(Timeout)),
+
+ ?VERIFY(timeout, recv(Timeout)),
+ ok.
+
+resend_write_server(Host, BlkSize) ->
+ RemoteFilename = "tftp_resend_write_server.tmp",
+ Block1 = lists:duplicate(BlkSize, $1),
+ Block2 = lists:duplicate(BlkSize, $2),
+ Block3 = lists:duplicate(BlkSize, $3),
+ Block4 = lists:duplicate(BlkSize, $4),
+ Block5 = lists:duplicate(BlkSize, $5),
+ Block6 = [],
+ Blocks = [Block1, Block2, Block3, Block4, Block5, Block6],
+ Blob = list_to_binary(Blocks),
+ Size = size(Blob),
+
+ Timeout = timer:seconds(3),
+ ?VERIFY(timeout, recv(0)),
+
+ %% Open daemon socket
+ {ok, DaemonSocket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
+ {ok, DaemonPort} = ?IGNORE(inet:port(DaemonSocket)),
+
+ %% Open server socket
+ {ok, ServerSocket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
+ ?IGNORE(inet:port(ServerSocket)),
+
+ %% Prepare client process
+ ReplyTo = self(),
+ ClientFun =
+ fun(Extra) ->
+ Options = [{port, DaemonPort}, {debug, brief}] ++ Extra,
+ Res = ?VERIFY({ok, Size}, tftp:write_file(RemoteFilename, Blob, Options)),
+ ReplyTo ! {self(), {tftp_client_reply, Res}},
+ exit(normal)
+ end,
+
+ WriteList = [0, 2, RemoteFilename, 0, "octet", 0],
+ Data1Bin = list_to_binary([0, 3, 0, 1 | Block1]),
+ {ClientPort, ClientPid} =
+ if
+ BlkSize =:= 512 ->
+ %% Start client process
+ ClientPid0 = spawn_link(fun() -> ClientFun([]) end),
+
+ %% Recv WRITE
+ WriteBin = list_to_binary(WriteList),
+ io:format("WriteBin ~p\n", [WriteBin]),
+ {udp, _, _, ClientPort0, _} = ?VERIFY({udp, DaemonSocket, Host, _, WriteBin}, recv(Timeout)),
+
+ %% Send ACK #1
+ Ack0Bin = <<0, 4, 0, 0>>,
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort0, Ack0Bin)),
+
+ %% Sleep a while in order to provoke the client to re-send the packet
+ timer:sleep(Timeout + timer:seconds(1)),
+
+ %% Recv DATA #1 (the packet that the server think that we have lost)
+ ?VERIFY({udp, ServerSocket, Host, ClientPort0, Data1Bin}, recv(Timeout)),
+
+ %% Recv DATA #1 AGAIN (the re-sent package)
+ ?VERIFY({udp, ServerSocket, Host, _, Data1Bin}, recv(Timeout)),
+ {ClientPort0, ClientPid0};
+ true ->
+ %% Start client process
+ BlkSizeList = integer_to_list(BlkSize),
+ ClientPid0 = spawn_link(fun() -> ClientFun([{"blksize", BlkSizeList}]) end),
+
+ %% Recv WRITE
+ Options = ["blksize", 0, BlkSizeList, 0],
+ WriteBin = list_to_binary([WriteList | Options]),
+ {udp, _, _, ClientPort0, _} = ?VERIFY({udp, DaemonSocket, Host, _, WriteBin}, recv(Timeout)),
+
+ %% Send OACK
+ BlkSizeList = integer_to_list(BlkSize),
+ OptionAckBin = list_to_binary([0, 6, "blksize",0, BlkSizeList, 0]),
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort0, OptionAckBin)),
+
+ %% Sleep a while in order to provoke the client to re-send the packet
+ timer:sleep(Timeout + timer:seconds(1)),
+
+ %% Recv DATA #1 (the packet that the server think that we have lost)
+ ?VERIFY({udp, ServerSocket, Host, ClientPort0, Data1Bin}, recv(Timeout)),
+
+ %% Recv DATA #1 AGAIN (the re-sent package)
+ ?VERIFY({udp, ServerSocket, Host, ClientPort0, Data1Bin}, recv(Timeout)),
+ {ClientPort0, ClientPid0}
+ end,
+
+ %% Send ACK #1
+ Ack1Bin = <<0, 4, 0, 1>>,
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack1Bin)),
+
+ %% Recv DATA #2
+ Data2Bin = list_to_binary([0, 3, 0, 2 | Block2]),
+ ?VERIFY({udp, ServerSocket, Host, ClientPort, Data2Bin}, recv(Timeout)),
+
+ %% Send ACK #2
+ Ack2Bin = <<0, 4, 0, 2>>,
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack2Bin)),
+
+ %% Recv DATA #3
+ Data3Bin = list_to_binary([0, 3, 0, 3 | Block3]),
+ ?VERIFY({udp, ServerSocket, Host, ClientPort, Data3Bin}, recv(Timeout)),
+
+ %% Send ACK #3
+ Ack3Bin = <<0, 4, 0, 3>>,
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack3Bin)),
+
+ %% Send ACK #3 AGAIN (pretend that we timed out)
+ timer:sleep(timer:seconds(1)),
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack3Bin)),
+
+ %% Recv DATA #4 (the packet that the server think that we have lost)
+ Data4Bin = list_to_binary([0, 3, 0, 4 | Block4]),
+ ?VERIFY({udp, ServerSocket, Host, ClientPort, Data4Bin}, recv(Timeout)),
+
+ %% Recv DATA #4 AGAIN (the re-sent package)
+ ?VERIFY({udp, ServerSocket, Host, ClientPort, Data4Bin}, recv(Timeout)),
+
+ %% Send ACK #4
+ Ack4Bin = <<0, 4, 0, 4>>,
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack4Bin)),
+
+ %% Recv DATA #5
+ Data5Bin = list_to_binary([0, 3, 0, 5 | Block5]),
+ ?VERIFY({udp, ServerSocket, Host, ClientPort, Data5Bin}, recv(Timeout)),
+
+ %% Send ACK #3 which is out of range
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack3Bin)),
+
+ %% Send ACK #5
+ Ack5Bin = <<0, 4, 0, 5>>,
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack5Bin)),
+
+ %% Recv DATA #6
+ Data6Bin = list_to_binary([0, 3, 0, 6 | Block6]),
+ ?VERIFY({udp, ServerSocket, Host, ClientPort, Data6Bin}, recv(Timeout)),
+
+ %% Send ACK #6
+ Ack6Bin = <<0, 4, 0, 6>>,
+ ?VERIFY(ok, gen_udp:send(ServerSocket, Host, ClientPort, Ack6Bin)),
+
+ %% Close daemon and server sockets
+ ?VERIFY(ok, gen_udp:close(ServerSocket)),
+ ?VERIFY(ok, gen_udp:close(DaemonSocket)),
+
+ ?VERIFY({ClientPid, {tftp_client_reply, {ok, Size}}}, recv(Timeout)),
+
+ ?VERIFY(timeout, recv(Timeout)),
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+reuse_connection(doc) ->
+ ["Verify that the server can reuse an ongiong connection when same client resends request."];
+reuse_connection(suite) ->
+ [];
+reuse_connection(Config) when is_list(Config) ->
+ Host = {127, 0, 0, 1},
+ {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, all}])),
+
+ RemoteFilename = "reuse_connection.tmp",
+ BlkSize = 512,
+ Block1 = lists:duplicate(BlkSize, $1),
+ Block2 = lists:duplicate(BlkSize div 2, $2),
+ Blocks = [Block1, Block2],
+ Blob = list_to_binary(Blocks),
+ ?VERIFY(ok, file:write_file(RemoteFilename, Blob)),
+
+ Seconds = 3,
+ Timeout = timer:seconds(Seconds),
+ ?VERIFY(timeout, recv(0)),
+
+ %% Open socket
+ {ok, Socket} = ?VERIFY({ok, _}, gen_udp:open(0, [binary, {reuseaddr, true}, {active, true}])),
+
+ ReadList = [0, 1, RemoteFilename, 0, "octet", 0],
+ Data1Bin = list_to_binary([0, 3, 0, 1 | Block1]),
+
+ %% Send READ
+ TimeoutList = integer_to_list(Seconds),
+ Options = ["timeout", 0, TimeoutList, 0],
+ ReadBin = list_to_binary([ReadList | Options]),
+ ?VERIFY(ok, gen_udp:send(Socket, Host, Port, ReadBin)),
+
+ %% Send yet another READ for same file
+ ?VERIFY(ok, gen_udp:send(Socket, Host, Port, ReadBin)),
+
+ %% Recv OACK
+ OptionAckBin = list_to_binary([0, 6 | Options]),
+ {udp, _, _, NewPort, _} = ?VERIFY({udp, Socket, Host, _, OptionAckBin}, recv(Timeout)),
+
+ %% Send ACK #0
+ Ack0Bin = <<0, 4, 0, 0>>,
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack0Bin)),
+
+ %% Recv DATA #1
+ ?VERIFY({udp, Socket, Host, NewPort, Data1Bin}, recv(Timeout)),
+
+ %% Send ACK #1
+ Ack1Bin = <<0, 4, 0, 1>>,
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack1Bin)),
+
+ %% Recv DATA #2
+ Data2Bin = list_to_binary([0, 3, 0, 2 | Block2]),
+ ?VERIFY({udp, Socket, Host, NewPort, Data2Bin}, recv(Timeout)),
+
+ %% Send ACK #2
+ Ack2Bin = <<0, 4, 0, 2>>,
+ ?VERIFY(ok, gen_udp:send(Socket, Host, NewPort, Ack2Bin)),
+
+ %% Close socket
+ ?VERIFY(ok, gen_udp:close(Socket)),
+
+ ?VERIFY(timeout, recv(Timeout)),
+ ?VERIFY(ok, file:delete(RemoteFilename)),
+
+ %% Cleanup
+ unlink(DaemonPid),
+ exit(DaemonPid, kill),
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Large file: transfer > 65535 blocks
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+large_file(doc) ->
+ ["Start the daemon and test transfer of files greater than 32M."];
+large_file(suite) ->
+ [];
+large_file(Config) when is_list(Config) ->
+ ?VERIFY(ok, application:start(tftp)),
+
+ {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, brief}])),
+
+ %% Read fail
+ RemoteFilename = "tftp_temporary_large_file_remote_test_file.txt",
+ LocalFilename = "tftp_temporary_large_file_local_test_file.txt",
+
+ {ok, FH} = file:open(LocalFilename, [write,exclusive]),
+ {ok, Size} = file:position(FH, {eof, 2*512*65535}),
+ ok = file:truncate(FH),
+ ?IGNORE(file:close(FH)),
+
+ %% Write and read
+ ?VERIFY({ok, Size}, tftp:write_file(RemoteFilename, LocalFilename, [{port, Port}])),
+ ?IGNORE(file:delete(LocalFilename)),
+ ?VERIFY({ok, Size}, tftp:read_file(RemoteFilename, LocalFilename, [{port, Port}])),
+
+ %% Cleanup
+ unlink(DaemonPid),
+ exit(DaemonPid, kill),
+ ?VERIFY(ok, file:delete(LocalFilename)),
+ ?VERIFY(ok, file:delete(RemoteFilename)),
+ ?VERIFY(ok, application:stop(tftp)),
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Goodies
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+recv(Timeout) ->
+ receive
+ Msg ->
+ Msg
+ after Timeout ->
+ timeout
+ end.
diff --git a/lib/tftp/test/tftp_bench.spec b/lib/tftp/test/tftp_bench.spec
new file mode 100644
index 0000000000..43fa385c85
--- /dev/null
+++ b/lib/tftp/test/tftp_bench.spec
@@ -0,0 +1 @@
+{suites,"../tftp_test",[]}.
diff --git a/lib/tftp/test/tftp_test_lib.erl b/lib/tftp/test/tftp_test_lib.erl
new file mode 100644
index 0000000000..04534228c2
--- /dev/null
+++ b/lib/tftp/test/tftp_test_lib.erl
@@ -0,0 +1,308 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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(tftp_test_lib).
+
+-compile(export_all).
+
+-include("tftp_test_lib.hrl").
+
+%%
+%% -----
+%%
+
+init_per_testcase(_Case, Config) when is_list(Config) ->
+ io:format("\n ", []),
+ ?IGNORE(application:stop(tftp)),
+ Config.
+
+end_per_testcase(_Case, Config) when is_list(Config) ->
+ ?IGNORE(application:stop(tftp)),
+ Config.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Infrastructure for test suite
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+error(Actual, Mod, Line) ->
+ (catch global:send(tftp_global_logger, {failed, Mod, Line})),
+ log("<ERROR> Bad result: ~p\n", [Actual], Mod, Line),
+ Label = lists:concat([Mod, "(", Line, ") unexpected result"]),
+ et:report_event(60, Mod, Mod, Label,
+ [{line, Mod, Line}, {error, Actual}]),
+ case global:whereis_name(tftp_test_case_sup) of
+ undefined ->
+ ignore;
+ Pid ->
+ Fail = #'REASON'{mod = Mod, line = Line, desc = Actual},
+ Pid ! {fail, self(), Fail}
+ end,
+ Actual.
+
+log(Format, Args, Mod, Line) ->
+ case global:whereis_name(tftp_global_logger) of
+ undefined ->
+ io:format(user, "~p(~p): " ++ Format,
+ [Mod, Line] ++ Args);
+ Pid ->
+ io:format(Pid, "~p(~p): " ++ Format,
+ [Mod, Line] ++ Args)
+ end.
+
+default_config() ->
+ [].
+
+t() ->
+ t([{?MODULE, all}]).
+
+t(Cases) ->
+ t(Cases, default_config()).
+
+t(Cases, Config) ->
+ process_flag(trap_exit, true),
+ Res = lists:flatten(do_test(Cases, Config)),
+ io:format("Res: ~p\n", [Res]),
+ display_result(Res),
+ Res.
+
+do_test({Mod, Fun}, Config) when is_atom(Mod), is_atom(Fun) ->
+ case catch apply(Mod, Fun, [suite]) of
+ [] ->
+ io:format("Eval: ~p:", [{Mod, Fun}]),
+ Res = eval(Mod, Fun, Config),
+ {R, _, _} = Res,
+ io:format(" ~p\n", [R]),
+ Res;
+
+ Cases when is_list(Cases) ->
+ io:format("Expand: ~p ...\n", [{Mod, Fun}]),
+ Map = fun(Case) when is_atom(Case)-> {Mod, Case};
+ (Case) -> Case
+ end,
+ do_test(lists:map(Map, Cases), Config);
+
+ {req, _, {conf, Init, Cases, Finish}} ->
+ case (catch apply(Mod, Init, [Config])) of
+ Conf when is_list(Conf) ->
+ io:format("Expand: ~p ...\n", [{Mod, Fun}]),
+ Map = fun(Case) when is_atom(Case)-> {Mod, Case};
+ (Case) -> Case
+ end,
+ Res = do_test(lists:map(Map, Cases), Conf),
+ (catch apply(Mod, Finish, [Conf])),
+ Res;
+
+ {'EXIT', {skipped, Reason}} ->
+ io:format(" => skipping: ~p\n", [Reason]),
+ [{skipped, {Mod, Fun}, Reason}];
+
+ Error ->
+ io:format(" => failed: ~p\n", [Error]),
+ [{failed, {Mod, Fun}, Error}]
+ end;
+
+ {'EXIT', {undef, _}} ->
+ io:format("Undefined: ~p\n", [{Mod, Fun}]),
+ [{nyi, {Mod, Fun}, ok}];
+
+ Error ->
+ io:format("Ignoring: ~p: ~p\n", [{Mod, Fun}, Error]),
+ [{failed, {Mod, Fun}, Error}]
+ end;
+do_test(Mod, Config) when is_atom(Mod) ->
+ Res = do_test({Mod, all}, Config),
+ Res;
+do_test(Cases, Config) when is_list(Cases) ->
+ [do_test(Case, Config) || Case <- Cases];
+do_test(Bad, _Config) ->
+ [{badarg, Bad, ok}].
+
+eval(Mod, Fun, Config) ->
+ TestCase = {?MODULE, Mod, Fun},
+ Label = lists:concat(["TEST CASE: ", Fun]),
+ et:report_event(40, ?MODULE, Mod, Label ++ " started",
+ [TestCase, Config]),
+ global:register_name(tftp_test_case_sup, self()),
+ Flag = process_flag(trap_exit, true),
+ Config2 = Mod:init_per_testcase(Fun, Config),
+ Pid = spawn_link(?MODULE, do_eval, [self(), Mod, Fun, Config2]),
+ R = wait_for_evaluator(Pid, Mod, Fun, Config2, []),
+ Mod:end_per_testcase(Fun, Config2),
+ global:unregister_name(tftp_test_case_sup),
+ process_flag(trap_exit, Flag),
+ R.
+
+wait_for_evaluator(Pid, Mod, Fun, Config, Errors) ->
+ TestCase = {?MODULE, Mod, Fun},
+ Label = lists:concat(["TEST CASE: ", Fun]),
+ receive
+ {done, Pid, ok} when Errors == [] ->
+ et:report_event(40, Mod, ?MODULE, Label ++ " ok",
+ [TestCase, Config]),
+ {ok, {Mod, Fun}, Errors};
+ {done, Pid, {ok, _}} when Errors == [] ->
+ et:report_event(40, Mod, ?MODULE, Label ++ " ok",
+ [TestCase, Config]),
+ {ok, {Mod, Fun}, Errors};
+ {done, Pid, Fail} ->
+ et:report_event(20, Mod, ?MODULE, Label ++ " failed",
+ [TestCase, Config, {return, Fail}, Errors]),
+ {failed, {Mod,Fun}, Fail};
+ {'EXIT', Pid, {skipped, Reason}} ->
+ et:report_event(20, Mod, ?MODULE, Label ++ " skipped",
+ [TestCase, Config, {skipped, Reason}]),
+ {skipped, {Mod, Fun}, Errors};
+ {'EXIT', Pid, Reason} ->
+ et:report_event(20, Mod, ?MODULE, Label ++ " crashed",
+ [TestCase, Config, {'EXIT', Reason}]),
+ {crashed, {Mod, Fun}, [{'EXIT', Reason} | Errors]};
+ {fail, Pid, Reason} ->
+ wait_for_evaluator(Pid, Mod, Fun, Config, Errors ++ [Reason])
+ end.
+
+do_eval(ReplyTo, Mod, Fun, Config) ->
+ case (catch apply(Mod, Fun, [Config])) of
+ {'EXIT', {skipped, Reason}} ->
+ ReplyTo ! {'EXIT', self(), {skipped, Reason}};
+ Other ->
+ ReplyTo ! {done, self(), Other}
+ end,
+ unlink(ReplyTo),
+ exit(shutdown).
+
+display_result([]) ->
+ io:format("OK\n", []);
+display_result(Res) when is_list(Res) ->
+ Ok = [MF || {ok, MF, _} <- Res],
+ Nyi = [MF || {nyi, MF, _} <- Res],
+ Skipped = [{MF, Reason} || {skipped, MF, Reason} <- Res],
+ Failed = [{MF, Reason} || {failed, MF, Reason} <- Res],
+ Crashed = [{MF, Reason} || {crashed, MF, Reason} <- Res],
+ display_summary(Ok, Nyi, Skipped, Failed, Crashed),
+ display_skipped(Skipped),
+ display_failed(Failed),
+ display_crashed(Crashed).
+
+display_summary(Ok, Nyi, Skipped, Failed, Crashed) ->
+ io:format("\nTest case summary:\n", []),
+ display_summary(Ok, "successful"),
+ display_summary(Nyi, "not yet implemented"),
+ display_summary(Skipped, "skipped"),
+ display_summary(Failed, "failed"),
+ display_summary(Crashed, "crashed"),
+ io:format("\n", []).
+
+display_summary(Res, Info) ->
+ io:format(" ~w test cases ~s\n", [length(Res), Info]).
+
+display_skipped([]) ->
+ ok;
+display_skipped(Skipped) ->
+ io:format("Skipped test cases:\n", []),
+ F = fun({MF, Reason}) -> io:format(" ~p => ~p\n", [MF, Reason]) end,
+ lists:foreach(F, Skipped),
+ io:format("\n", []).
+
+
+display_failed([]) ->
+ ok;
+display_failed(Failed) ->
+ io:format("Failed test cases:\n", []),
+ F = fun({MF, Reason}) -> io:format(" ~p => ~p\n", [MF, Reason]) end,
+ lists:foreach(F, Failed),
+ io:format("\n", []).
+
+display_crashed([]) ->
+ ok;
+display_crashed(Crashed) ->
+ io:format("Crashed test cases:\n", []),
+ F = fun({MF, Reason}) -> io:format(" ~p => ~p\n", [MF, Reason]) end,
+ lists:foreach(F, Crashed),
+ io:format("\n", []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% generic callback
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-record(generic_state, {state, prepare, open, read, write, abort}).
+
+prepare(Peer, Access, LocalFilename, Mode, SuggestedOptions, Initial) when is_list(Initial) ->
+ State = lookup_option(state, mandatory, Initial),
+ Prepare = lookup_option(prepare, mandatory, Initial),
+ Open = lookup_option(open, mandatory, Initial),
+ Read = lookup_option(read, mandatory, Initial),
+ Write = lookup_option(write, mandatory, Initial),
+ Abort = lookup_option(abort, mandatory, Initial),
+ case Prepare(Peer, Access, LocalFilename, Mode, SuggestedOptions, State) of
+ {ok, AcceptedOptions, NewState} ->
+ {ok,
+ AcceptedOptions,
+ #generic_state{state = NewState,
+ prepare = Prepare,
+ open = Open,
+ read = Read,
+ write = Write,
+ abort = Abort}};
+ Other ->
+ Other
+ end.
+
+open(Peer, Access, LocalFilename, Mode, SuggestedOptions, Initial) when is_list(Initial) ->
+ case prepare(Peer, Access, LocalFilename, Mode, SuggestedOptions, Initial) of
+ {ok, SuggestedOptions2, GenericState} ->
+ open(Peer, Access, LocalFilename, Mode, SuggestedOptions2, GenericState);
+ Other ->
+ Other
+ end;
+open(Peer, Access, LocalFilename, Mode, SuggestedOptions, #generic_state{state = State, open = Open} = GenericState) ->
+ case Open(Peer, Access, LocalFilename, Mode, SuggestedOptions, State) of
+ {ok, SuggestedOptions2, NewState} ->
+ {ok, SuggestedOptions2, GenericState#generic_state{state = NewState}};
+ Other ->
+ Other
+ end.
+
+read(#generic_state{state = State, read = Read} = GenericState) ->
+ case Read(State) of
+ {more, DataBlock, NewState} ->
+ {more, DataBlock, GenericState#generic_state{state = NewState}};
+ Other ->
+ Other
+ end.
+
+write(DataBlock, #generic_state{state = State, write = Write} = GenericState) ->
+ case Write(DataBlock, State) of
+ {more, NewState} ->
+ {more, GenericState#generic_state{state = NewState}};
+ Other ->
+ Other
+ end.
+
+abort(Code, Text, #generic_state{state = State, abort = Abort}) ->
+ Abort(Code, Text, State).
+
+lookup_option(Key, Default, Options) ->
+ case lists:keysearch(Key, 1, Options) of
+ {value, {_, Val}} ->
+ Val;
+ false ->
+ Default
+ end.
+
diff --git a/lib/tftp/test/tftp_test_lib.hrl b/lib/tftp/test/tftp_test_lib.hrl
new file mode 100644
index 0000000000..eb8ed77fc1
--- /dev/null
+++ b/lib/tftp/test/tftp_test_lib.hrl
@@ -0,0 +1,44 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% 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%
+%%
+
+-record('REASON', {mod, line, desc}).
+
+-define(LOG(Format, Args),
+ tftp_test_lib:log(Format, Args, ?MODULE, ?LINE)).
+
+-define(ERROR(Reason),
+ tftp_test_lib:error(Reason, ?MODULE, ?LINE)).
+
+-define(VERIFY(Expected, Expr),
+ fun() ->
+ AcTuAlReS = (catch (Expr)),
+ case AcTuAlReS of
+ Expected -> ?LOG("Ok, ~p\n", [AcTuAlReS]);
+ _ -> ?ERROR(AcTuAlReS)
+ end,
+ AcTuAlReS
+ end()).
+
+-define(IGNORE(Expr),
+ fun() ->
+ AcTuAlReS = (catch (Expr)),
+ ?LOG("Ok, ~p\n", [AcTuAlReS]),
+ AcTuAlReS
+ end()).
diff --git a/lib/tftp/vsn.mk b/lib/tftp/vsn.mk
new file mode 100644
index 0000000000..1a547fbe9b
--- /dev/null
+++ b/lib/tftp/vsn.mk
@@ -0,0 +1,24 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2001-2018. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# 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%
+
+APPLICATION = tftp
+TFTP_VSN = 1.0.1
+PRE_VSN =
+APP_VSN = "$(APPLICATION)-$(TFTP_VSN)$(PRE_VSN)"
diff --git a/lib/tools/doc/specs/.gitignore b/lib/tools/doc/specs/.gitignore
new file mode 100644
index 0000000000..322eebcb06
--- /dev/null
+++ b/lib/tools/doc/specs/.gitignore
@@ -0,0 +1 @@
+specs_*.xml
diff --git a/lib/tools/doc/src/Makefile b/lib/tools/doc/src/Makefile
index d9c3b0ad2a..5ff4fe3113 100644
--- a/lib/tools/doc/src/Makefile
+++ b/lib/tools/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -47,9 +47,9 @@ XML_REF3_FILES = \
make.xml \
tags.xml \
xref.xml \
- erlang_mode.xml
+ erlang_mode.xml
-XML_PART_FILES = part.xml part_notes.xml part_notes_history.xml
+XML_PART_FILES = part.xml
XML_CHAPTER_FILES = \
cover_chapter.xml \
@@ -58,8 +58,7 @@ XML_CHAPTER_FILES = \
lcnt_chapter.xml \
erlang_mode_chapter.xml \
xref_chapter.xml \
- notes.xml \
- notes_history.xml
+ notes.xml
BOOK_FILES = book.xml
@@ -85,10 +84,19 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
+
+TOP_SPECS_FILE = specs.xml
+
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
+XML_FLAGS +=
+
+TOOLS_SRC=$(ERL_TOP)/lib/tools/src
+TOOLS_INCLUDE=$(ERL_TOP)/lib/tools/include
+
+SPECS_FLAGS = -I$(TOOLS_SRC) -I$(TOOLS_INCLUDE)
# ----------------------------------------------------
# Targets
@@ -108,17 +116,23 @@ man: $(MAN3_FILES)
gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
-debug opt:
+debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
+ rm -f $(SPECDIR)/*
+ rm -f errs core *~
+
+# erlang_mode doesn't have erlang source so we generate a dummy file for it.
+$(SPECDIR)/specs_erlang_mode.xml:
+ echo '<module name="erlang_mode"/>' > $(SPECDIR)/specs_erlang_mode.xml
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
@@ -132,4 +146,3 @@ release_docs_spec: docs
$(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
release_spec:
-
diff --git a/lib/tools/doc/src/fascicules.xml b/lib/tools/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/tools/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/tools/doc/src/fprof.xml b/lib/tools/doc/src/fprof.xml
index 4c9e48045e..1fd828d127 100644
--- a/lib/tools/doc/src/fprof.xml
+++ b/lib/tools/doc/src/fprof.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2001</year><year>2016</year>
+ <year>2001</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -328,10 +328,16 @@
purposes. This option is only
allowed with the <c>start</c> option.</item>
<tag><c>cpu_time</c>| <c>{cpu_time, bool()}</c></tag>
- <item>The options <c>cpu_time</c> or <c>{cpu_time, true></c>
+ <item>The options <c>cpu_time</c> or <c>{cpu_time, true}</c>
makes the timestamps in the trace be in CPU time instead
of wallclock time which is the default. This option is
- only allowed with the <c>start</c> option.</item>
+ only allowed with the <c>start</c> option.
+ <warning><p>Getting correct values out of cpu_time can be difficult.
+ The best way to get correct values is to run using a single
+ scheduler and bind that scheduler to a specific CPU,
+ i.e. <c>erl +S 1 +sbt db</c>.</p>
+ </warning>
+ </item>
<tag><c>{procs, PidSpec}</c>| <c>{procs, [PidSpec]}</c></tag>
<item>Specifies which processes that shall be traced. If
this option is not given, the calling process is
diff --git a/lib/tools/doc/src/instrument.xml b/lib/tools/doc/src/instrument.xml
index bb6f9b6100..9fd9332373 100644
--- a/lib/tools/doc/src/instrument.xml
+++ b/lib/tools/doc/src/instrument.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1998</year><year>2016</year>
+ <year>1998</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -41,387 +41,190 @@
<note>
<p>Note that this whole module is experimental, and the representations
used as well as the functionality is likely to change in the future.</p>
- <p>The <c>instrument</c> module interface was slightly changed in
- Erlang/OTP R9C.</p>
</note>
- <p>To start an Erlang runtime system with instrumentation, use the
- <c>+Mi*</c> set of command-line arguments to the <c>erl</c> command (see
- the erts_alloc(3) and erl(1) man pages).</p>
- <p>The basic object of study in the case of memory allocation is a memory
- allocation map. A memory allocation map contains a list of descriptors
- for each allocated memory block. Currently, a descriptor is a 4-tuple</p>
- <pre>
- {TypeNo, Address, Size, PidDesc} </pre>
- <p>where <c>TypeNo</c> is the memory block type number, <c>Address</c>
- is its place in memory, and <c>Size</c> is its size, in bytes.
- <c>PidDesc</c> is either a tuple <c>{X,Y,Z}</c> identifying the
- process which was executing when the block was allocated, or
- <c>undefined</c> if no process was executing. The pid tuple
- <c>{X,Y,Z}</c> can be transformed into a real pid by usage of the
- <c>c:pid/3</c> function.</p>
- <p>Various details about memory allocation:</p>
- <p>Memory blocks are allocated both on the heap segment and on other memory
- segments. This can cause the instrumentation functionality to report
- very large holes. Currently the instrumentation functionality doesn't
- provide any support for distinguishing between holes between memory
- segments, and holes between allocated blocks inside memory segments.
- The current size of the process cannot be obtained from within Erlang,
- but can be seen with one of the system statistics tools, e.g.,
- <c>ps</c> or <c>top</c>. The Solaris utility <c>pmap</c> can be
- useful. It reports currently mapped memory segments. </p>
- <p>Overhead for instrumentation: When the emulator has been started with
- the <seealso marker="erts:erts_alloc#Mim">"+Mim true"</seealso>
- flag, each block is preceded by a 24 bytes large
- header on a 32-bit machine and a 48 bytes large header on a 64-bit
- machine. When the emulator has been started with the
- <seealso marker="erts:erts_alloc#Mis">"+Mis true"</seealso>
- flag, each block is preceded by an 8 bytes large header. These are the header
- sizes used by the Erlang 5.3/OTP R9C emulator. Other versions of the
- emulator may use other header sizes. The function
- <seealso marker="#block_header_size/1">block_header_size/1</seealso>
- can be used for retrieving the header size used for a specific memory
- allocation map. The time overhead for managing the instrumentation
- data is small.</p>
- <p>Sizes presented by the instrumentation functionality are (by the
- emulator) requested sizes, i.e. neither instrumentation headers nor
- headers used by allocators are included.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name name="block_histogram"/>
+ <desc>
+ <p>A histogram of block sizes where each interval's upper bound is
+ twice as high as the one before it.</p>
+ <p>The upper bound of the first interval is provided by the function
+ that returned the histogram, and the last interval has no upper
+ bound.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="allocation_summary"/>
+ <desc>
+ <p>A summary of allocated block sizes (including their headers) grouped
+ by their <c><anno>Origin</anno></c> and <c><anno>Type</anno></c>.</p>
+ <p><c><anno>Origin</anno></c> is generally which NIF or driver that
+ allocated the blocks, or 'system' if it could not be determined.</p>
+ <p><c><anno>Type</anno></c> is the allocation category that the blocks
+ belong to, e.g. <c>db_term</c>, <c>message</c> or <c>binary</c>.</p>
+ <p>If one or more carriers could not be scanned in full without harming
+ the responsiveness of the system, <c><anno>UnscannedSize</anno></c>
+ is the number of bytes that had to be skipped.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="carrier_info_list"/>
+ <desc>
+ <p><c><anno>AllocatorType</anno></c> is the type of the allocator that
+ employs this carrier.</p>
+ <p><c><anno>TotalSize</anno></c> is the total size of the carrier,
+ including its header.</p>
+ <p><c><anno>AllocatedSize</anno></c> is the combined size of the
+ carrier's allocated blocks, including their headers.</p>
+ <p><c><anno>AllocatedCount</anno></c> is the number of allocated
+ blocks in the carrier.</p>
+ <p><c><anno>InPool</anno></c> is whether the carrier is in the
+ migration pool.</p>
+ <p><c><anno>FreeBlocks</anno></c> is a histogram of the free block
+ sizes in the carrier.</p>
+ <p>If the carrier could not be scanned in full without harming the
+ responsiveness of the system, <c><anno>UnscannedSize</anno></c> is
+ the number of bytes that had to be skipped.</p>
+ </desc>
+ </datatype>
+ </datatypes>
<funcs>
+
<func>
- <name>allocator_descr(MemoryData, TypeNo) -> AllocDescr | invalid_type | "unknown"</name>
- <fsummary>Returns a allocator description</fsummary>
- <type>
- <v>MemoryData = {term(), AllocList}</v>
- <v>AllocList = [Desc]</v>
- <v>Desc = {int(), int(), int(), PidDesc}</v>
- <v>PidDesc = {int(), int(), int()} | undefined</v>
- <v>TypeNo = int()</v>
- <v>AllocDescr = atom() | string()</v>
- </type>
- <desc>
- <p>Returns the allocator description of the allocator that
- manages memory blocks of type number <c>TypeNo</c> used in
- <c>MemoryData</c>.
- Valid <c>TypeNo</c>s are in the range returned by
- <seealso marker="#type_no_range/1">type_no_range/1</seealso> on
- this specific memory allocation map. If <c>TypeNo</c> is an
- invalid integer, <c>invalid_type</c> is returned.</p>
- </desc>
- </func>
- <func>
- <name>block_header_size(MemoryData) -> int()</name>
- <fsummary>Returns the memory block header size used by the emulator that generated the memory allocation map</fsummary>
- <type>
- <v>MemoryData = {term(), AllocList}</v>
- <v>AllocList = [Desc]</v>
- <v>Desc = {int(), int(), int(), PidDesc}</v>
- <v>PidDesc = {int(), int(), int()} | undefined</v>
- </type>
- <desc>
- <marker id="block_header_size_1"></marker>
- <p>Returns the memory block header size used by the
- emulator that generated the memory allocation map. The block
- header size may differ between different emulators.</p>
- </desc>
- </func>
- <func>
- <name>class_descr(MemoryData, TypeNo) -> ClassDescr | invalid_type | "unknown"</name>
- <fsummary>Returns a allocator description</fsummary>
- <type>
- <v>MemoryData = {term(), AllocList}</v>
- <v>AllocList = [Desc]</v>
- <v>Desc = {int(), int(), int(), PidDesc}</v>
- <v>PidDesc = {int(), int(), int()} | undefined</v>
- <v>TypeNo = int()</v>
- <v>ClassDescr = atom() | string()</v>
- </type>
- <desc>
- <p>Returns the class description of the class that
- the type number <c>TypeNo</c> used in <c>MemoryData</c> belongs
- to.
- Valid <c>TypeNo</c>s are in the range returned by
- <seealso marker="#type_no_range/1">type_no_range/1</seealso> on
- this specific memory allocation map. If <c>TypeNo</c> is an
- invalid integer, <c>invalid_type</c> is returned.</p>
- </desc>
- </func>
- <func>
- <name>descr(MemoryData) -> DescrMemoryData</name>
- <fsummary>Replace type numbers in memory allocation map with type descriptions</fsummary>
- <type>
- <v>MemoryData = {term(), AllocList}</v>
- <v>AllocList = [Desc]</v>
- <v>Desc = {int(), int(), int(), PidDesc}</v>
- <v>PidDesc = {int(), int(), int()} | undefined</v>
- <v>DescrMemoryData = {term(), DescrAllocList}</v>
- <v>DescrAllocList = [DescrDesc]</v>
- <v>DescrDesc = {TypeDescr, int(), int(), DescrPidDesc}</v>
- <v>TypeDescr = atom() | string()</v>
- <v>DescrPidDesc = pid() | undefined</v>
- </type>
- <desc>
- <p>Returns a memory allocation map where the type numbers (first
- element of <c>Desc</c>) have been replaced by type descriptions,
- and pid tuples (fourth element of <c>Desc</c>) have been
- replaced by real pids.</p>
- </desc>
- </func>
- <func>
- <name>holes(MemoryData) -> ok</name>
- <fsummary>Print out the sizes of unused memory blocks</fsummary>
- <type>
- <v>MemoryData = {term(), AllocList}</v>
- <v>AllocList = [Desc]</v>
- <v>Desc = {int(), int(), int(), PidDesc}</v>
- <v>PidDesc = {int(), int(), int()} | undefined</v>
- </type>
- <desc>
- <p>Prints out the size of each hole (i.e., the space between
- allocated blocks) on the terminal. <em>NOTE:</em> Really large holes
- are probably holes between memory segments.
- The memory allocation map has to be sorted (see
- <seealso marker="#sort/1">sort/1</seealso>).</p>
- </desc>
- </func>
- <func>
- <name>mem_limits(MemoryData) -> {Low, High}</name>
- <fsummary>Return lowest and highest memory address used</fsummary>
- <type>
- <v>MemoryData = {term(), AllocList}</v>
- <v>AllocList = [Desc]</v>
- <v>Desc = {int(), int(), int(), PidDesc}</v>
- <v>PidDesc = {int(), int(), int()} | undefined</v>
- <v>Low = High = int()</v>
- </type>
- <desc>
- <p>Returns a tuple <c>{Low, High}</c> indicating
- the lowest and highest address used.
- The memory allocation map has to be sorted (see
- <seealso marker="#sort/1">sort/1</seealso>).</p>
- </desc>
- </func>
- <func>
- <name>memory_data() -> MemoryData | false</name>
- <fsummary>Return the current memory allocation map</fsummary>
- <type>
- <v>MemoryData = {term(), AllocList}</v>
- <v>AllocList = [Desc]</v>
- <v>Desc = {int(), int(), int(), PidDesc}</v>
- <v>PidDesc = {int(), int(), int()} | undefined</v>
- </type>
- <desc>
- <p>Returns <c>MemoryData</c> (a the memory allocation map)
- if the emulator has been started with the "<c>+Mim true</c>"
- command-line argument; otherwise, <c>false</c>. <em>NOTE:</em><c>memory_data/0</c> blocks execution of other processes while
- the data is collected. The time it takes to collect the data can
- be substantial.</p>
- </desc>
- </func>
- <func>
- <name>memory_status(StatusType) -> [StatusInfo] | false</name>
- <fsummary>Return current memory allocation status</fsummary>
- <type>
- <v>StatusType = total | allocators | classes | types</v>
- <v>StatusInfo = {About, [Info]}</v>
- <v>About = atom()</v>
- <v>Info = {InfoName, Current, MaxSinceLast, MaxEver}</v>
- <v>InfoName = sizes|blocks</v>
- <v>Current = int()</v>
- <v>MaxSinceLast = int()</v>
- <v>MaxEver = int()</v>
- </type>
- <desc>
- <p>Returns a list of <c>StatusInfo</c> if the emulator has been
- started with the "<c>+Mis true</c>" or "<c>+Mim true</c>"
- command-line argument; otherwise, <c>false</c>. </p>
- <p>See the
- <seealso marker="#read_memory_status/1">read_memory_status/1</seealso>
- function for a description of the <c>StatusInfo</c> term.</p>
- </desc>
- </func>
- <func>
- <name>read_memory_data(File) -> MemoryData | {error, Reason}</name>
- <fsummary>Read memory allocation map</fsummary>
- <type>
- <v>File = string()</v>
- <v>MemoryData = {term(), AllocList}</v>
- <v>AllocList = [Desc]</v>
- <v>Desc = {int(), int(), int(), PidDesc}</v>
- <v>PidDesc = {int(), int(), int()} | undefined</v>
- </type>
+ <name name="allocations" arity="0"/>
+ <fsummary>Return a summary of all allocations in the system.</fsummary>
<desc>
- <marker id="read_memory_data_1"></marker>
- <p>Reads a memory allocation map from the file <c>File</c> and
- returns it. The file is assumed to have been created by
- <c>store_memory_data/1</c>. The error codes are the same as for
- <c>file:consult/1</c>.</p>
+ <p>Shorthand for
+ <seealso marker="#allocations/1"><c>allocations(#{})</c>.</seealso></p>
</desc>
</func>
+
<func>
- <name>read_memory_status(File) -> MemoryStatus | {error, Reason}</name>
- <fsummary>Read memory allocation status from a file</fsummary>
- <type>
- <v>File = string()</v>
- <v>MemoryStatus = [{StatusType, [StatusInfo]}]</v>
- <v>StatusType = total | allocators | classes | types</v>
- <v>StatusInfo = {About, [Info]}</v>
- <v>About = atom()</v>
- <v>Info = {InfoName, Current, MaxSinceLast, MaxEver}</v>
- <v>InfoName = sizes|blocks</v>
- <v>Current = int()</v>
- <v>MaxSinceLast = int()</v>
- <v>MaxEver = int()</v>
- </type>
- <desc>
- <marker id="read_memory_status_1"></marker>
- <p>Reads memory allocation status from the file <c>File</c> and
- returns it. The file is assumed to have been created by
- <c>store_memory_status/1</c>. The error codes are the same as
- for <c>file:consult/1</c>.</p>
- <p>When <c>StatusType</c> is <c>allocators</c>, <c>About</c> is
- the allocator that the information is about. When
- <c>StatusType</c> is <c>types</c>, <c>About</c> is
- the memory block type that the information is about. Memory
- block types are not described other than by their name and may
- vary between emulators. When <c>StatusType</c> is <c>classes</c>,
- <c>About</c> is the memory block type class that information is
- presented about. Memory block types are classified after their
- use. Currently the following classes exist:</p>
+ <name name="allocations" arity="1"/>
+ <fsummary>Return a summary of all allocations filtered by allocator type
+ and scheduler id.</fsummary>
+ <desc>
+ <p>Returns a summary of all tagged allocations in the system,
+ optionally filtered by allocator type and scheduler id.</p>
+ <p>Only binaries and allocations made by NIFs and drivers are tagged by
+ default, but this can be configured an a per-allocator basis with the
+ <seealso marker="erts:erts_alloc#M_atags"><c>+M&lt;S&gt;atags</c>
+ </seealso> emulator option.</p>
+ <p>If tagged allocations are not enabled on any of the specified
+ allocator types, the call will fail with
+ <c>{error, not_enabled}</c>.</p>
+ <p>The following options can be used:</p>
<taglist>
- <tag><c>process_data</c></tag>
- <item>Erlang process specific data.</item>
- <tag><c>binary_data</c></tag>
- <item>Erlang binaries.</item>
- <tag><c>atom_data</c></tag>
- <item>Erlang atoms.</item>
- <tag><c>code_data</c></tag>
- <item>Erlang code.</item>
- <tag><c>system_data</c></tag>
- <item>Other data used by the system</item>
+ <tag><c>allocator_types</c></tag>
+ <item>
+ <p>The allocator types that will be searched. Defaults to all
+ <c>alloc_util</c> allocators.</p>
+ </item>
+ <tag><c>scheduler_ids</c></tag>
+ <item>
+ <p>The scheduler ids whose allocator instances will be searched. A
+ scheduler id of 0 will refer to the global instance that is not
+ tied to any particular scheduler. Defaults to all schedulers and
+ the global instance.</p>
+ </item>
+ <tag><c>histogram_start</c></tag>
+ <item>
+ <p>The upper bound of the first interval in the allocated block
+ size histograms. Defaults to 128.</p>
+ </item>
+ <tag><c>histogram_width</c></tag>
+ <item>
+ <p>The number of intervals in the allocated block size histograms.
+ Defaults to 18.</p>
+ </item>
</taglist>
- <p>When <c>InfoName</c> is <c>sizes</c>, <c>Current</c>,
- <c>MaxSinceLast</c>, and <c>MaxEver</c> are, respectively, current
- size, maximum size since last call to
- <c>store_memory_status/1</c> or <c>memory_status/1</c> with the
- specific <c>StatusType</c>, and maximum size since the emulator
- was started. When <c>InfoName</c> is <c>blocks</c>, <c>Current</c>,
- <c>MaxSinceLast</c>, and <c>MaxEver</c> are, respectively, current
- number of blocks, maximum number of blocks since last call to
- <c>store_memory_status/1</c> or <c>memory_status/1</c> with the
- specific <c>StatusType</c>, and maximum number of blocks since the
- emulator was started. </p>
- <p><em>NOTE:</em>A memory block is accounted for at
- "the first level" allocator. E.g. <c>fix_alloc</c> allocates its
- memory pools via <c>ll_alloc</c>. When a <c>fix_alloc</c> block
- is allocated, neither the block nor the pool in which it resides
- are accounted for as memory allocated via <c>ll_alloc</c> even
- though it is.</p>
- </desc>
- </func>
- <func>
- <name>sort(MemoryData) -> MemoryData</name>
- <fsummary>Sort the memory allocation list</fsummary>
- <type>
- <v>MemoryData = {term(), AllocList}</v>
- <v>AllocList = [Desc]</v>
- <v>Desc = {int(), int(), int(), PidDesc}</v>
- <v>PidDesc = {int(), int(), int()} | undefined</v>
- </type>
- <desc>
- <marker id="sort_1"></marker>
- <p>Sorts a memory allocation map so that the addresses are in
- ascending order.</p>
- </desc>
- </func>
- <func>
- <name>store_memory_data(File) -> true|false</name>
- <fsummary>Store the current memory allocation map on a file</fsummary>
- <type>
- <v>File = string()</v>
- </type>
- <desc>
- <p>Stores the current memory allocation map on the file
- <c>File</c>. Returns <c>true</c> if the emulator has been
- started with the "<c>+Mim true</c>" command-line argument, and
- the map was successfully stored; otherwise, <c>false</c>. The
- contents of the file can later be read using
- <seealso marker="#read_memory_data/1">read_memory_data/1</seealso>.
- <em>NOTE:</em><c>store_memory_data/0</c> blocks execution of
- other processes while the data is collected. The time it takes
- to collect the data can be substantial.</p>
- </desc>
- </func>
- <func>
- <name>store_memory_status(File) -> true|false</name>
- <fsummary>Store the current memory allocation status on a file</fsummary>
- <type>
- <v>File = string()</v>
- </type>
- <desc>
- <p>Stores the current memory status on the file
- <c>File</c>. Returns <c>true</c> if the emulator has been
- started with the "<c>+Mis true</c>", or "<c>+Mim true</c>"
- command-line arguments, and the data was successfully stored;
- otherwise, <c>false</c>. The contents of the file can later be
- read using
- <seealso marker="#read_memory_status/1">read_memory_status/1</seealso>.</p>
- </desc>
- </func>
- <func>
- <name>sum_blocks(MemoryData) -> int()</name>
- <fsummary>Return the total amount of memory used</fsummary>
- <type>
- <v>MemoryData = {term(), AllocList}</v>
- <v>AllocList = [Desc]</v>
- <v>Desc = {int(), int(), int(), PidDesc}</v>
- <v>PidDesc = {int(), int(), int()} | undefined</v>
- </type>
- <desc>
- <p>Returns the total size of the memory blocks in the list.</p>
+ <p><em>Example:</em></p>
+ <code type="none"><![CDATA[
+> instrument:allocations(#{ histogram_start => 128, histogram_width => 15 }).
+{ok,{128,0,
+ #{udp_inet =>
+ #{driver_event_state => {0,0,0,0,0,0,0,0,0,1,0,0,0,0,0}},
+ system =>
+ #{heap => {0,0,0,0,20,4,2,2,2,3,0,1,0,0,1},
+ db_term => {271,3,1,52,80,1,0,0,0,0,0,0,0,0,0},
+ code => {0,0,0,5,3,6,11,22,19,20,10,2,1,0,0},
+ binary => {18,0,0,0,7,0,0,1,0,0,0,0,0,0,0},
+ message => {0,40,78,2,2,0,0,0,0,0,0,0,0,0,0},
+ ... }
+ spawn_forker =>
+ #{driver_select_data_state =>
+ {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}},
+ ram_file_drv => #{drv_binary => {0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}},
+ prim_file =>
+ #{process_specific_data => {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ nif_trap_export_entry => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ monitor_extended => {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ drv_binary => {0,0,0,0,0,0,1,0,3,5,0,0,0,1,0},
+ binary => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0}},
+ prim_buffer =>
+ #{nif_internal => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ binary => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0}}}}}
+ ]]></code>
</desc>
</func>
+
<func>
- <name>type_descr(MemoryData, TypeNo) -> TypeDescr | invalid_type</name>
- <fsummary>Returns a type description</fsummary>
- <type>
- <v>MemoryData = {term(), AllocList}</v>
- <v>AllocList = [Desc]</v>
- <v>Desc = {int(), int(), int(), PidDesc}</v>
- <v>PidDesc = {int(), int(), int()} | undefined</v>
- <v>TypeNo = int()</v>
- <v>TypeDescr = atom() | string()</v>
- </type>
+ <name name="carriers" arity="0"/>
+ <fsummary>Return a list of all carriers in the system.</fsummary>
<desc>
- <p>Returns the type description of a type number used in
- <c>MemoryData</c>.
- Valid <c>TypeNo</c>s are in the range returned by
- <seealso marker="#type_no_range/1">type_no_range/1</seealso> on
- this specific memory allocation map. If <c>TypeNo</c> is an
- invalid integer, <c>invalid_type</c> is returned.</p>
+ <p>Shorthand for
+ <seealso marker="#carriers/1"><c>carriers(#{})</c>.</seealso></p>
</desc>
</func>
+
<func>
- <name>type_no_range(MemoryData) -> {Min, Max}</name>
- <fsummary>Returns the memory block type numbers</fsummary>
- <type>
- <v>MemoryData = {term(), AllocList}</v>
- <v>AllocList = [Desc]</v>
- <v>Desc = {int(), int(), int(), PidDesc}</v>
- <v>PidDesc = {int(), int(), int()} | undefined</v>
- <v>Min = int()</v>
- <v>Max = int()</v>
- </type>
+ <name name="carriers" arity="1"/>
+ <fsummary>Return a list of all carriers filtered by allocator type and
+ scheduler id.</fsummary>
<desc>
- <marker id="type_no_range_1"></marker>
- <p>Returns the memory block type number range used in
- <c>MemoryData</c>. When the memory allocation map was generated
- by an Erlang 5.3/OTP R9C or newer emulator, all integers <c>T</c>
- that satisfy <c>Min</c> &lt;= <c>T</c> &lt;= <c>Max</c> are
- valid type numbers. When the memory allocation map was generated
- by a pre Erlang 5.3/OTP R9C emulator, all integers in the
- range are <em>not</em> valid type numbers.</p>
+ <p>Returns a summary of all carriers in the system, optionally filtered
+ by allocator type and scheduler id.</p>
+ <p>If the specified allocator types are not enabled, the call will fail
+ with <c>{error, not_enabled}</c>.</p>
+ <p>The following options can be used:</p>
+ <taglist>
+ <tag><c>allocator_types</c></tag>
+ <item>
+ <p>The allocator types that will be searched. Defaults to all
+ <c>alloc_util</c> allocators.</p>
+ </item>
+ <tag><c>scheduler_ids</c></tag>
+ <item>
+ <p>The scheduler ids whose allocator instances will be searched. A
+ scheduler id of 0 will refer to the global instance that is not
+ tied to any particular scheduler. Defaults to all schedulers and
+ the global instance.</p>
+ </item>
+ <tag><c>histogram_start</c></tag>
+ <item>
+ <p>The upper bound of the first interval in the free block size
+ histograms. Defaults to 512.</p>
+ </item>
+ <tag><c>histogram_width</c></tag>
+ <item>
+ <p>The number of intervals in the free block size histograms.
+ Defaults to 14.</p>
+ </item>
+ </taglist>
+ <p><em>Example:</em></p>
+ <code type="none"><![CDATA[
+> instrument:carriers(#{ histogram_start => 512, histogram_width => 8 }).
+{ok,{512,
+ [{ll_alloc,1048576,0,1048344,71,false,{0,0,0,0,0,0,0,0}},
+ {binary_alloc,1048576,0,324640,13,false,{3,0,0,1,0,0,0,2}},
+ {eheap_alloc,2097152,0,1037200,45,false,{2,1,1,3,4,3,2,2}},
+ {fix_alloc,32768,0,29544,82,false,{22,0,0,0,0,0,0,0}},
+ {...}|...]}}
+ ]]></code>
</desc>
</func>
+
</funcs>
<section>
diff --git a/lib/tools/doc/src/lcnt.xml b/lib/tools/doc/src/lcnt.xml
index 31e5c241e9..d2595cdb60 100644
--- a/lib/tools/doc/src/lcnt.xml
+++ b/lib/tools/doc/src/lcnt.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2009</year>
- <year>2017</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -109,14 +109,6 @@
statistics. If the server held any lock statistics data before the collect then
that data is lost.
</p>
- <note>
- <p>
- When collection occurs the runtime system transitions to a single thread,
- blocking all other threads. No other tasks will be scheduled during this
- operation. Depending on the size of the data this might take a long time
- (several seconds) and cause timeouts in the system.
- </p>
- </note>
</desc>
</func>
@@ -322,24 +314,22 @@
<func>
<name>apply(Fun) -> term()</name>
<fsummary>Same as <c>apply(Fun, [])</c>.</fsummary>
+ <type>
+ <v>Fun = fun()</v>
+ </type>
<desc>
<p>Same as <c>apply(Fun, [])</c>.</p>
</desc>
</func>
<func>
<name>apply(Fun, Args) -> term()</name>
- <fsummary>Clears counters, applies function and collects the profiling results.</fsummary>
+ <fsummary>Same as <c>apply(Module, Function, Args)</c>.</fsummary>
<type>
<v>Fun = fun()</v>
<v>Args = [term()]</v>
</type>
<desc>
- <p> Clears the lock counters and then setups the instrumentation to save all destroyed locks.
- After setup the fun is called, passing the elements in <c>Args</c> as arguments.
- When the fun returns the statistics are immediately collected to the server. After the
- collection the instrumentation is returned to its previous behavior.
- The result of the applied fun is returned.
- </p>
+ <p>Same as <c>apply(Module, Function, Args)</c>.</p>
</desc>
</func>
<func>
@@ -357,6 +347,13 @@
collection the instrumentation is returned to its previous behavior.
The result of the applied function is returned.
</p>
+ <warning>
+ <p>
+ This function should only be used for micro-benchmarks; it sets <c>copy_save</c>
+ to <c>true</c> for the duration of the call, which can quickly lead to running
+ out of memory.
+ </p>
+ </warning>
</desc>
</func>
@@ -374,7 +371,7 @@
<v>Serial = integer()</v>
</type>
<desc>
- <p>Creates a process id with creation 0. Example:</p>
+ <p>Creates a process id with creation 0.</p>
</desc>
</func>
@@ -429,6 +426,68 @@
<desc> <p>Clear the internal counters. Same as <c>lcnt:clear(Node)</c>.</p></desc>
</func>
+ <func>
+ <name>rt_mask() -> [category_atom()]</name>
+ <fsummary>Same as <c>rt_mask(node())</c>.</fsummary>
+ <desc><p>Same as <c>rt_mask(node())</c>.</p></desc>
+ </func>
+
+ <func>
+ <name>rt_mask(Node) -> [category_atom()]</name>
+ <fsummary>Returns the current lock category mask.</fsummary>
+ <type>
+ <v>Node = node()</v>
+ </type>
+ <desc>
+ <p>
+ Refer to <c>rt_mask/2</c> for a list of valid categories. All
+ categories are enabled by default.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>rt_mask(Categories) -> ok | {error, copy_save_enabled}</name>
+ <fsummary>Same as <c>rt_mask(node(), Categories)</c>.</fsummary>
+ <type>
+ <v>Categories = [atom()]</v>
+ </type>
+ <desc><p>Same as <c>rt_mask(node(), Categories)</c>.</p></desc>
+ </func>
+
+ <func>
+ <name>rt_mask(Node, Categories) -> ok | {error, copy_save_enabled}</name>
+ <fsummary>Changes the lock category mask.</fsummary>
+ <type>
+ <v>Node = node()</v>
+ <v>Categories = [atom()]</v>
+ </type>
+ <desc>
+ <p>
+ Sets the lock category mask to the given categories.
+ </p>
+ <p>
+ This will fail if the <c>copy_save</c> option is enabled; see
+ <c>lcnt:rt_opt/2</c>.
+ </p>
+ <p>Valid categories are:</p>
+ <list>
+ <item><c>allocator</c></item>
+ <item><c>db</c> (ETS tables)</item>
+ <item><c>debug</c></item>
+ <item><c>distribution</c></item>
+ <item><c>generic</c></item>
+ <item><c>io</c></item>
+ <item><c>process</c></item>
+ <item><c>scheduler</c></item>
+ </list>
+ <p>
+ This list is subject to change at any time, as is the category any given lock
+ may belong to.
+ </p>
+ </desc>
+ </func>
+
<func>
<name>rt_opt({Type, bool()}) -> bool()</name>
<fsummary>Same as <c>rt_opt(node(), {Type, Opt})</c>.</fsummary>
@@ -442,16 +501,25 @@
<v>Type = copy_save | process_locks</v>
</type>
<desc>
- <p>Changes the lock counter behavior and returns the previous behaviour.</p>
<p>Option description:</p>
<taglist>
<tag><c>{copy_save, bool()}</c></tag>
- <item>Enable statistics saving from destroyed locks by copying. This might consume a lot of memory.
+ <item>Retains the statistics of destroyed locks.
<br/>Default: <c>false</c>
+ <warning>
+ <p>
+ This option will use a lot of memory when enabled, which must be
+ reclaimed with <c>lcnt:rt_clear</c>. Note that it makes no distinction
+ between locks that were destroyed and locks for which counting was
+ disabled, so enabling this option will disable changes to the lock
+ category mask.
+ </p>
+ </warning>
</item>
<tag><c>{process_locks, bool()}</c></tag>
- <item>Profile process locks.
+ <item>Profile process locks, equal to adding <c>process</c> to the lock category mask;
+ see <c>lcnt:rt_mask/2</c>
<br/>Default: <c>true</c>
</item>
</taglist>
diff --git a/lib/tools/doc/src/lcnt_chapter.xml b/lib/tools/doc/src/lcnt_chapter.xml
index c73fcb31e0..24b58136aa 100644
--- a/lib/tools/doc/src/lcnt_chapter.xml
+++ b/lib/tools/doc/src/lcnt_chapter.xml
@@ -29,7 +29,7 @@
<approved>nobody</approved>
<checked>no</checked>
<date>2009-11-26</date>
- <rev>PA1</rev>
+ <rev>PA2</rev>
<file>lcnt_chapter.xml</file>
</header>
<p>
@@ -97,8 +97,11 @@ ok
ok
</pre>
<p>
- Another way to to profile a specific function is to use <c>lcnt:apply/3</c> or <c>lcnt:apply/1</c> which does <c>lcnt:clear/0</c> before the function and <c>lcnt:collect/0</c> after its invocation.
- It also sets <c>copy_save</c> to <c>true</c> for the duration of the function call
+ Another way to to profile a specific function is to use <c>lcnt:apply/3</c> or <c>lcnt:apply/1</c>
+ which does <c>lcnt:clear/0</c> before the function and <c>lcnt:collect/0</c> after its invocation.
+ This method should only be used in micro-benchmarks since it sets <c>copy_save</c> to <c>true</c>
+ for the duration of the function call, which may cause the emulator to run out of memory if
+ attempted under load.
</p>
<pre>
Erlang R13B03 (erts-5.7.4) [source] [smp:8:8] [rq:8] [async-threads:0] [hipe]
diff --git a/lib/tools/doc/src/note.gif b/lib/tools/doc/src/note.gif
deleted file mode 100644
index 6fffe30419..0000000000
--- a/lib/tools/doc/src/note.gif
+++ /dev/null
Binary files differ
diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml
index bdd5455354..f10953774f 100644
--- a/lib/tools/doc/src/notes.xml
+++ b/lib/tools/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,193 @@
</header>
<p>This document describes the changes made to the Tools application.</p>
+<section><title>Tools 3.0.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The HTML pages generated by cover:analyse_to_file/1 and
+ related functions is improved for readability.</p>
+ <p>
+ Own Id: OTP-15213 Aux Id: PR-1807 </p>
+ </item>
+ <item>
+ <p>
+ Add alignment functionality in emacs.</p>
+ <p>
+ Own Id: OTP-15239 Aux Id: PR-1728 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Tools 3.0</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Added <c>instrument:allocations</c> and
+ <c>instrument:carriers</c> for retrieving information
+ about memory utilization and fragmentation.</p>
+ <p>The old <c>instrument</c> interface has been removed,
+ as have the related options <c>+Mim</c> and
+ <c>+Mis</c>.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-14961</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Tools 2.11.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> A counting bug is corrected in <c>Cover</c>. The bug
+ was introduced in Erlang/OTP 18.0. </p>
+ <p>
+ Own Id: OTP-14817 Aux Id: PR 1641 </p>
+ </item>
+ <item>
+ <p>The <c>lcnt</c> server will no longer crash if
+ <c>lcnt:information/0</c> is called before
+ <c>lcnt:collect/0</c>.</p>
+ <p>
+ Own Id: OTP-14912</p>
+ </item>
+ <item>
+ <p><c>lcnt:collect</c> will now implicitly start the
+ <c>lcnt</c> server, as per the documentation.</p>
+ <p>
+ Own Id: OTP-14913</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Improved indentation in emacs and various other updates.</p>
+ <p>
+ Own Id: OTP-14944</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Tools 2.11.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Tools 2.11</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> The predefined Xref analysis <c>locals_not_used</c>
+ no longer reports unused functions with the
+ <c>-on_load()</c> attribute.</p> <p> The new predefined
+ Xref variable <c>OL</c> holds all functions with the
+ <c>-on_load()</c> attribute. </p>
+ <p>
+ Own Id: OTP-14344</p>
+ </item>
+ <item>
+ <p>
+ In fprof when sampling multiple processes and analyzing
+ with totals set to true, the output now sums together all
+ caller and callee entries which concerns the same
+ function. Previous behaviour was to report each
+ contributing entry separately.</p>
+ <p>
+ Own Id: OTP-14500</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Lock counting can now be fully toggled at runtime in
+ the lock counting emulator (<c>-emu_type lcnt</c>).
+ Everything is enabled by default to match the old
+ behavior, but specific categories can be toggled at will
+ with minimal runtime overhead when disabled. Refer to the
+ documentation on <c>lcnt:rt_mask/1</c> for details.</p>
+ <p>
+ Own Id: OTP-13170</p>
+ </item>
+ <item>
+ <p><c>lcnt:collect</c> and <c>lcnt:clear</c> will no
+ longer block all other threads in the runtime system.</p>
+ <p>
+ Own Id: OTP-14412</p>
+ </item>
+ <item>
+ <p>
+ General Unicode improvements.</p>
+ <p>
+ Own Id: OTP-14462</p>
+ </item>
+ <item>
+ <p>
+ Tools are updated to show Unicode atoms correctly.</p>
+ <p>
+ Own Id: OTP-14464</p>
+ </item>
+ <item>
+ <p>Add <c>erlang:iolist_to_iovec/1</c>, which converts an
+ iolist() to an erlang:iovec(), which suitable for use
+ with <c>enif_inspect_iovec</c>.</p>
+ <p>
+ Own Id: OTP-14520</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Tools 2.10.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ In OTP-20.0, the behavior of c, make, and ct_make was
+ changed so that in some cases the beam files by default
+ would be written to the directory where the source files
+ were found. This is now changed back to the old behavior
+ so beam files are by default written to current
+ directory.</p>
+ <p>
+ Own Id: OTP-14489 Aux Id: ERL-438 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Tools 2.10</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/tools/doc/src/part_notes.xml b/lib/tools/doc/src/part_notes.xml
deleted file mode 100644
index c4c6fa4d7d..0000000000
--- a/lib/tools/doc/src/part_notes.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Tools Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p>The <em>Tools</em> application contains a number of stand-alone
- tools, which are useful when developing Erlang programs.</p>
- <p>For information about older versions, see
- <url href="part_notes_history_frame.html">Release Notes History</url>.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/tools/doc/src/part_notes_history.xml b/lib/tools/doc/src/part_notes_history.xml
deleted file mode 100644
index a34e35fc56..0000000000
--- a/lib/tools/doc/src/part_notes_history.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part>
- <header>
- <copyright>
- <year>2006</year>
- <year>2016</year>
- <holder>Ericsson AB, All Rights Reserved</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The Initial Developer of the Original Code is Ericsson AB.
- </legalnotice>
-
- <title>Tools Release Notes History</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p>The <em>Tools</em> application contains a number of stand-alone
- tools, which are useful when developing Erlang programs.</p>
- </description>
- <include file="notes_history"></include>
-</part>
-
diff --git a/lib/tools/doc/src/specs.xml b/lib/tools/doc/src/specs.xml
new file mode 100644
index 0000000000..0b5b7b171c
--- /dev/null
+++ b/lib/tools/doc/src/specs.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<specs xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="../specs/specs_fprof.xml"/>
+ <xi:include href="../specs/specs_make.xml"/>
+ <xi:include href="../specs/specs_lcnt.xml"/>
+ <xi:include href="../specs/specs_eprof.xml"/>
+ <xi:include href="../specs/specs_tags.xml"/>
+ <xi:include href="../specs/specs_cover.xml"/>
+ <xi:include href="../specs/specs_xref.xml"/>
+ <xi:include href="../specs/specs_instrument.xml"/>
+ <xi:include href="../specs/specs_erlang_mode.xml"/>
+</specs>
diff --git a/lib/tools/doc/src/venn2.fig b/lib/tools/doc/src/venn2.fig
index 3694c12f0c..233686a729 100644
--- a/lib/tools/doc/src/venn2.fig
+++ b/lib/tools/doc/src/venn2.fig
@@ -1,4 +1,4 @@
-#FIG 3.2
+#FIG 3.2 Produced by xfig version 3.2.5c
Portrait
Center
Inches
@@ -7,34 +7,7 @@ Letter
Single
-2
1200 2
-6 3392 953 5034 3329
-6 3392 953 5034 2595
-6 3392 953 5034 2595
-5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 2652.489 1773.500 3518 1357 3613 1774 3518 2190
-5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 6306.956 1773.000 4028 2575 3891 1774 4028 971
-5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 2105.283 1773.000 4402 971 4538 1774 4402 2575
-1 1 0 1 -1 7 0 0 -1 0.000 1 0.0000 4214 1774 820 821 4214 1774 3659 1171
-2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 1
- 4821 2325
-2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2
- 4816 1217 4816 2329
-2 1 0 1 -1 7 0 0 -1 0.000 0 0 7 0 0 2
- 3392 1769 4816 1769
-2 1 0 1 0 0 100 0 1 0.000 0 0 -1 0 0 2
- 4816 1982 5008 1982
--6
-2 3 0 0 0 0 101 0 5 0.000 0 0 -1 0 0 36
- 4026 977 4011 1025 3996 1072 3981 1120 3966 1177 3954 1225
- 3944 1272 3929 1327 3919 1412 3909 1477 3899 1540 3894 1592
- 3894 1642 3891 1697 3889 1742 3889 1770 3394 1767 3396 1717
- 3399 1665 3409 1610 3424 1555 3439 1502 3464 1440 3489 1390
- 3516 1340 3551 1292 3584 1250 3631 1200 3679 1150 3731 1110
- 3801 1065 3869 1030 3931 1005 3986 982 4009 980 4026 977
--6
-4 0 0 101 0 0 11 0.0000 4 105 525 3965 3044 X - XU\001
-4 0 0 101 0 0 11 0.0000 4 150 1110 3688 3299 exports_not_used\001
--6
-6 5850 938 7560 3329
+6 5850 938 8070 3344
6 5884 938 7526 2580
6 5884 938 7526 2580
5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 5144.489 1758.500 6010 1342 6105 1759 6010 2175
@@ -63,8 +36,8 @@ Single
7019 1990 7022 1945 7027 1900 7029 1855 7029 1805 7032 1765
7029 1752 7309 1757
-6
-4 0 0 101 0 0 11 0.0000 4 135 1470 6000 3014 L * (UU + (XU - LU))\001
-4 0 0 101 0 0 11 0.0000 4 150 1800 5850 3299 locals_not_used (simplified)\001
+4 0 0 101 0 0 11 0.0000 4 180 2070 6000 3014 (L-OL) * (UU + (XU-LU))\001
+4 0 0 101 0 0 11 0.0000 4 180 2160 5850 3299 locals_not_used (simplified)\001
-6
6 900 900 2550 3600
6 900 900 2550 2625
@@ -91,7 +64,34 @@ Single
2330 1222 2365 1265 2402 1317 2437 1382 2477 1455 2500 1517
2520 1585 2532 1645 2540 1712 2542 1780 2540 1842 2535 1907
2527 1957 2517 1990 2325 1987 2330 1222
-4 0 0 101 0 0 11 0.0000 4 105 780 1331 3044 XU - X - B\001
-4 0 0 101 0 0 11 0.0000 4 150 1260 1113 3314 undefined_functions\001
+4 0 0 101 0 0 11 0.0000 4 135 825 1331 3044 XU - X - B\001
+4 0 0 101 0 0 11 0.0000 4 180 1530 1113 3314 undefined_functions\001
4 0 0 100 0 0 10 0.0000 4 135 1005 1275 3525 (modules mode)\001
-6
+6 3392 953 5034 3329
+6 3392 953 5034 2595
+6 3392 953 5034 2595
+5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 2652.489 1773.500 3518 1357 3613 1774 3518 2190
+5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 6306.956 1773.000 4028 2575 3891 1774 4028 971
+5 1 0 1 -1 7 0 0 -1 0.000 0 0 0 0 2105.283 1773.000 4402 971 4538 1774 4402 2575
+1 1 0 1 -1 7 0 0 -1 0.000 1 0.0000 4214 1774 820 821 4214 1774 3659 1171
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 1
+ 4821 2325
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2
+ 4816 1217 4816 2329
+2 1 0 1 -1 7 0 0 -1 0.000 0 0 7 0 0 2
+ 3392 1769 4816 1769
+2 1 0 1 0 0 100 0 1 0.000 0 0 -1 0 0 2
+ 4816 1982 5008 1982
+-6
+2 3 0 0 0 0 101 0 5 0.000 0 0 -1 0 0 36
+ 4026 977 4011 1025 3996 1072 3981 1120 3966 1177 3954 1225
+ 3944 1272 3929 1327 3919 1412 3909 1477 3899 1540 3894 1592
+ 3894 1642 3891 1697 3889 1742 3889 1770 3394 1767 3396 1717
+ 3399 1665 3409 1610 3424 1555 3439 1502 3464 1440 3489 1390
+ 3516 1340 3551 1292 3584 1250 3631 1200 3679 1150 3731 1110
+ 3801 1065 3869 1030 3931 1005 3986 982 4009 980 4026 977
+-6
+4 0 0 101 0 0 11 0.0000 4 135 555 3965 3044 X - XU\001
+4 0 0 101 0 0 11 0.0000 4 180 1350 3688 3299 exports_not_used\001
+-6
diff --git a/lib/tools/doc/src/venn2.gif b/lib/tools/doc/src/venn2.gif
index 4cfea24646..bb12f4bd1f 100644
--- a/lib/tools/doc/src/venn2.gif
+++ b/lib/tools/doc/src/venn2.gif
Binary files differ
diff --git a/lib/tools/doc/src/warning.gif b/lib/tools/doc/src/warning.gif
deleted file mode 100644
index 96af52360e..0000000000
--- a/lib/tools/doc/src/warning.gif
+++ /dev/null
Binary files differ
diff --git a/lib/tools/doc/src/xref.xml b/lib/tools/doc/src/xref.xml
index 8c49f3a206..6f833246ad 100644
--- a/lib/tools/doc/src/xref.xml
+++ b/lib/tools/doc/src/xref.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2016</year>
+ <year>2000</year><year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -347,6 +347,9 @@ represented by
<item>Locally Used Functions (*). Functions of all modules that have
been used in some local call.
</item>
+ <tag><c>OL</c></tag>
+ <item>Functions with an attribute tag <c>on_load</c> (*).
+ </item>
<tag><c>LC</c></tag>
<item>Local Calls (*).</item>
<tag><c>XC</c></tag>
@@ -393,6 +396,7 @@ facts about the
<c>LU</c> and <c>XU</c> may have elements in common. Put in
another way:</item>
<item><c>V</c> is equal to <c>UU + XU + LU</c>.</item>
+ <item><c>OL</c> is a subset of <c>F</c>.</item>
<item><c>E</c> is equal to <c>LC + XC</c>. Note that <c>LC</c>
and <c>XC</c> may have elements in common, namely if some
function is locally and externally used from one and the same
@@ -559,8 +563,10 @@ Two functions (modules,
analyzing operators:
</p>
<list type="bulleted">
- <item>Expression ::= Expression GraphOp Expression</item>
- <item>GraphOp ::= <c>components</c> | <c>condensation</c> | <c>of</c></item>
+ <item>Expression ::= Expression BinaryGraphOp Expression</item>
+ <item>Expression ::= UnaryGraphOp Expression</item>
+ <item>UnaryGraphOp ::= <c>components</c> | <c>condensation</c></item>
+ <item>BinaryGraphOp ::= <c>of</c></item>
</list>
<p>As was mentioned before, the graph analyses operate on
the <c>digraph</c> representation of graphs.
diff --git a/lib/tools/emacs/Makefile b/lib/tools/emacs/Makefile
index 35c93ba4ed..ea4d6cb723 100644
--- a/lib/tools/emacs/Makefile
+++ b/lib/tools/emacs/Makefile
@@ -54,8 +54,6 @@ EL_FILES = $(EMACS_FILES:%=%.el)
ELC_FILES = $(EMACS_FILES:%=%.elc)
-TEST_FILES = test.erl.indented test.erl.orig
-
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
@@ -75,7 +73,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)/emacs"
- $(INSTALL_DATA) $(EL_FILES) $(README_FILES) $(TEST_FILES) \
+ $(INSTALL_DATA) $(EL_FILES) $(README_FILES) \
"$(RELSYSDIR)/emacs"
ifeq ($(DOCTYPE),pdf)
@@ -89,19 +87,3 @@ release_docs_spec: docs
$(INSTALL_DATA) $(MAN_FILES) "$(RELEASE_PATH)/man/man3"
endif
endif
-
-EMACS ?= emacs
-
-test_indentation:
- @rm -f test.erl
- @rm -f test_indent.el
- @echo '(load "erlang-start")' >> test_indent.el
- @echo '(find-file "test.erl.orig")' >> test_indent.el
- @echo "(require 'cl) ; required with Emacs < 23 for ignore-errors" >> test_indent.el
- @echo '(erlang-mode)' >> test_indent.el
- @echo '(toggle-debug-on-error)' >> test_indent.el
- @echo '(erlang-indent-current-buffer)' >> test_indent.el
- @echo '(write-file "test.erl")' >> test_indent.el
- $(EMACS) --batch -Q -L . -l test_indent.el
- diff -u test.erl.indented test.erl
- @echo "No differences between expected and actual indentation"
diff --git a/lib/tools/emacs/erlang-skels.el b/lib/tools/emacs/erlang-skels.el
index bdb3d9ad4a..534f50ab33 100644
--- a/lib/tools/emacs/erlang-skels.el
+++ b/lib/tools/emacs/erlang-skels.el
@@ -279,7 +279,8 @@ Please see the function `tempo-define-template'.")
'((erlang-skel-include erlang-skel-large-header)
"-behaviour(application)." n n
"%% Application callbacks" n
- "-export([start/2, stop/1])." n n
+ "-export([start/2, start_phase/3, stop/1, prep_stop/1," n>
+ "config_change/3])." n n
(erlang-skel-double-separator-start 3)
"%%% Application callbacks" n
(erlang-skel-double-separator-end 3) n
@@ -291,13 +292,14 @@ Please see the function `tempo-define-template'.")
"%% application. If the application is structured according to the OTP" n
"%% design principles as a supervision tree, this means starting the" n
"%% top supervisor of the tree." n
- "%%" n
- "%% @spec start(StartType, StartArgs) -> {ok, Pid} |" n
- "%% {ok, Pid, State} |" n
- "%% {error, Reason}" n
- "%% StartType = normal | {takeover, Node} | {failover, Node}" n
- "%% StartArgs = term()" n
(erlang-skel-separator-end 2)
+ "-spec start(StartType :: normal |" n>
+ "{takeover, Node :: node()} |" n>
+ "{failover, Node :: node()}," n>
+ "StartArgs :: term()) ->" n>
+ "{ok, Pid :: pid()} |" n>
+ "{ok, Pid :: pid(), State :: term()} |" n>
+ "{error, Reason :: term()}." n
"start(_StartType, _StartArgs) ->" n>
"case 'TopSupervisor':start_link() of" n>
"{ok, Pid} ->" n>
@@ -309,15 +311,52 @@ Please see the function `tempo-define-template'.")
(erlang-skel-separator-start 2)
"%% @private" n
"%% @doc" n
+ "%% top supervisor of the tree." n
+ "%% Starts an application with included applications, when" n
+ "%% synchronization is needed between processes in the different" n
+ "%% applications during startup."
+ (erlang-skel-separator-end 2)
+ "-spec start_phase(Phase :: atom()," n>
+ "StartType :: normal |" n>
+ "{takeover, Node :: node()} |" n>
+ "{failover, Node :: node()}," n>
+ "PhaseArgs :: term()) -> ok | {error, Reason :: term()}." n
+ "start_phase(_Phase, _StartType, _PhaseArgs) ->" n>
+ "ok."n
+ n
+ (erlang-skel-separator-start 2)
+ "%% @private" n
+ "%% @doc" n
"%% This function is called whenever an application has stopped. It" n
"%% is intended to be the opposite of Module:start/2 and should do" n
"%% any necessary cleaning up. The return value is ignored." n
- "%%" n
- "%% @spec stop(State) -> void()" n
(erlang-skel-separator-end 2)
+ "-spec stop(State :: term()) -> any()." n
"stop(_State) ->" n>
"ok." n
n
+ (erlang-skel-separator-start 2)
+ "%% @private" n
+ "%% @doc" n
+ "%% This function is called when an application is about to be stopped," n
+ "%% before shutting down the processes of the application." n
+ (erlang-skel-separator-end 2)
+ "-spec prep_stop(State :: term()) -> NewState :: term()." n
+ "prep_stop(State) ->" n>
+ "State." n
+ n
+ (erlang-skel-separator-start 2)
+ "%% @private" n
+ "%% @doc" n
+ "%% This function is called by an application after a code replacement," n
+ "%% if the configuration parameters have changed." n
+ (erlang-skel-separator-end 2)
+ "-spec config_change(Changed :: [{Par :: atom(), Val :: term()}]," n>
+ "New :: [{Par :: atom(), Val :: term()}]," n>
+ "Removed :: [Par :: atom()]) -> ok." n
+ "config_change(_Changed, _New, _Removed) ->" n>
+ "ok." n
+ n
(erlang-skel-double-separator-start 3)
"%%% Internal functions" n
(erlang-skel-double-separator-end 3)
@@ -343,9 +382,12 @@ Please see the function `tempo-define-template'.")
(erlang-skel-separator-start 2)
"%% @doc" n
"%% Starts the supervisor" n
- "%%" n
- "%% @spec start_link() -> {ok, Pid} | ignore | {error, Error}" n
(erlang-skel-separator-end 2)
+ "-spec start_link() -> {ok, Pid :: pid()} |" n>
+ "{error, {already_started, Pid :: pid()}} |" n>
+ "{error, {shutdown, term()}} |" n>
+ "{error, term()} |" n>
+ "ignore." n
"start_link() ->" n>
"supervisor:start_link({local, ?SERVER}, ?MODULE, [])." n
n
@@ -359,11 +401,11 @@ Please see the function `tempo-define-template'.")
"%% this function is called by the new process to find out about" n
"%% restart strategy, maximum restart intensity, and child" n
"%% specifications." n
- "%%" n
- "%% @spec init(Args) -> {ok, {SupFlags, [ChildSpec]}} |" n
- "%% ignore |" n
- "%% {error, Reason}" n
(erlang-skel-separator-end 2)
+ "-spec init(Args :: term()) ->" n>
+ "{ok, {SupFlags :: supervisor:sup_flags()," n>
+ "[ChildSpec :: supervisor:child_spec()]}} |" n>
+ "ignore." n
"init([]) ->" n
"" n>
"SupFlags = #{strategy => one_for_one," n>
@@ -406,9 +448,11 @@ Please see the function `tempo-define-template'.")
(erlang-skel-separator-start 2)
"%% @doc" n
"%% Starts the supervisor bridge" n
- "%%" n
- "%% @spec start_link() -> {ok, Pid} | ignore | {error, Error}" n
(erlang-skel-separator-end 2)
+ "-spec start_link() -> {ok, Pid :: pid()} |" n>
+ "{error, {already_started, Pid :: pid()}} |" n>
+ "{error, term()} |" n>
+ "ignore." n
"start_link() ->" n>
"supervisor_bridge:start_link({local, ?SERVER}, ?MODULE, [])." n
n
@@ -422,11 +466,10 @@ Please see the function `tempo-define-template'.")
"%% which calls Module:init/1 to start the subsystem. To ensure a" n
"%% synchronized start-up procedure, this function does not return" n
"%% until Module:init/1 has returned." n
- "%%" n
- "%% @spec init(Args) -> {ok, Pid, State} |" n
- "%% ignore |" n
- "%% {error, Reason}" n
(erlang-skel-separator-end 2)
+ "-spec init(Args :: term()) -> {ok, Pid :: pid(), State :: term()} |" n>
+ "{error, Error :: term()} |" n>
+ "ignore." n
"init([]) ->" n>
"case 'AModule':start_link() of" n>
"{ok, Pid} ->" n>
@@ -442,10 +485,9 @@ Please see the function `tempo-define-template'.")
"%% to terminate. It should be the opposite of Module:init/1 and stop" n
"%% the subsystem and do any necessary cleaning up.The return value is" n
"%% ignored." n
- "%%" n
- "%% @spec terminate(Reason, State) -> void()" n
(erlang-skel-separator-end 2)
- "terminate(Reason, State) ->" n>
+ "-spec terminate(Reason :: shutdown | term(), State :: term()) -> any()." n
+ "terminate(_Reason, _State) ->" n>
"'AModule':stop()," n>
"ok." n
n
@@ -464,9 +506,8 @@ Please see the function `tempo-define-template'.")
"-export([start_link/0])." n n
"%% gen_server callbacks" n
- "-export([init/1, handle_call/3, handle_cast/2, "
- "handle_info/2," n>
- "terminate/2, code_change/3])." n n
+ "-export([init/1, handle_call/3, handle_cast/2, handle_info/2," n>
+ "terminate/2, code_change/3, format_status/2])." n n
"-define(SERVER, ?MODULE)." n n
@@ -478,9 +519,11 @@ Please see the function `tempo-define-template'.")
(erlang-skel-separator-start 2)
"%% @doc" n
"%% Starts the server" n
- "%%" n
- "%% @spec start_link() -> {ok, Pid} | ignore | {error, Error}" n
(erlang-skel-separator-end 2)
+ "-spec start_link() -> {ok, Pid :: pid()} |" n>
+ "{error, Error :: {already_started, pid()}} |" n>
+ "{error, Error :: term()} |" n>
+ "ignore." n
"start_link() ->" n>
"gen_server:start_link({local, ?SERVER}, ?MODULE, [], [])." n
n
@@ -492,12 +535,12 @@ Please see the function `tempo-define-template'.")
"%% @private" n
"%% @doc" n
"%% Initializes the server" n
- "%%" n
- "%% @spec init(Args) -> {ok, State} |" n
- "%% {ok, State, Timeout} |" n
- "%% ignore |" n
- "%% {stop, Reason}" n
(erlang-skel-separator-end 2)
+ "-spec init(Args :: term()) -> {ok, State :: term()} |" n>
+ "{ok, State :: term(), Timeout :: timeout()} |" n>
+ "{ok, State :: term(), hibernate} |" n>
+ "{stop, Reason :: term()} |" n>
+ "ignore." n
"init([]) ->" n>
"process_flag(trap_exit, true)," n>
"{ok, #state{}}." n
@@ -506,15 +549,16 @@ Please see the function `tempo-define-template'.")
"%% @private" n
"%% @doc" n
"%% Handling call messages" n
- "%%" n
- "%% @spec handle_call(Request, From, State) ->" n
- "%% {reply, Reply, State} |" n
- "%% {reply, Reply, State, Timeout} |" n
- "%% {noreply, State} |" n
- "%% {noreply, State, Timeout} |" n
- "%% {stop, Reason, Reply, State} |" n
- "%% {stop, Reason, State}" n
(erlang-skel-separator-end 2)
+ "-spec handle_call(Request :: term(), From :: {pid(), term()}, State :: term()) ->" n>
+ "{reply, Reply :: term(), NewState :: term()} |" n>
+ "{reply, Reply :: term(), NewState :: term(), Timeout :: timeout()} |" n>
+ "{reply, Reply :: term(), NewState :: term(), hibernate} |" n>
+ "{noreply, NewState :: term()} |" n>
+ "{noreply, NewState :: term(), Timeout :: timeout()} |" n>
+ "{noreply, NewState :: term(), hibernate} |" n>
+ "{stop, Reason :: term(), Reply :: term(), NewState :: term()} |" n>
+ "{stop, Reason :: term(), NewState :: term()}." n
"handle_call(_Request, _From, State) ->" n>
"Reply = ok," n>
"{reply, Reply, State}." n
@@ -523,23 +567,25 @@ Please see the function `tempo-define-template'.")
"%% @private" n
"%% @doc" n
"%% Handling cast messages" n
- "%%" n
- "%% @spec handle_cast(Msg, State) -> {noreply, State} |" n
- "%% {noreply, State, Timeout} |" n
- "%% {stop, Reason, State}" n
(erlang-skel-separator-end 2)
- "handle_cast(_Msg, State) ->" n>
+ "-spec handle_cast(Request :: term(), State :: term()) ->" n>
+ "{noreply, NewState :: term()} |" n>
+ "{noreply, NewState :: term(), Timeout :: timeout()} |" n>
+ "{noreply, NewState :: term(), hibernate} |" n>
+ "{stop, Reason :: term(), NewState :: term()}." n
+ "handle_cast(_Request, State) ->" n>
"{noreply, State}." n
n
(erlang-skel-separator-start 2)
"%% @private" n
"%% @doc" n
"%% Handling all non call/cast messages" n
- "%%" n
- "%% @spec handle_info(Info, State) -> {noreply, State} |" n
- "%% {noreply, State, Timeout} |" n
- "%% {stop, Reason, State}" n
(erlang-skel-separator-end 2)
+ "-spec handle_info(Info :: timeout() | term(), State :: term()) ->" n>
+ "{noreply, NewState :: term()} |" n>
+ "{noreply, NewState :: term(), Timeout :: timeout()} |" n>
+ "{noreply, NewState :: term(), hibernate} |" n>
+ "{stop, Reason :: normal | term(), NewState :: term()}." n
"handle_info(_Info, State) ->" n>
"{noreply, State}." n
n
@@ -550,9 +596,9 @@ Please see the function `tempo-define-template'.")
"%% terminate. It should be the opposite of Module:init/1 and do any" n
"%% necessary cleaning up. When it returns, the gen_server terminates" n
"%% with Reason. The return value is ignored." n
- "%%" n
- "%% @spec terminate(Reason, State) -> void()" n
(erlang-skel-separator-end 2)
+ "-spec terminate(Reason :: normal | shutdown | {shutdown, term()} | term()," n>
+ "State :: term()) -> any()." n
"terminate(_Reason, _State) ->" n>
"ok." n
n
@@ -560,12 +606,26 @@ Please see the function `tempo-define-template'.")
"%% @private" n
"%% @doc" n
"%% Convert process state when code is changed" n
- "%%" n
- "%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}" n
(erlang-skel-separator-end 2)
+ "-spec code_change(OldVsn :: term() | {down, term()}," n>
+ "State :: term()," n>
+ "Extra :: term()) -> {ok, NewState :: term()} |" n>
+ "{error, Reason :: term()}." n
"code_change(_OldVsn, State, _Extra) ->" n>
"{ok, State}." n
n
+ (erlang-skel-separator-start 2)
+ "%% @private" n
+ "%% @doc" n
+ "%% This function is called for changing the form and appearance" n
+ "%% of gen_server status when it is returned from sys:get_status/1,2" n
+ "%% or when it appears in termination error logs." n
+ (erlang-skel-separator-end 2)
+ "-spec format_status(Opt :: normal | terminate," n>
+ "Status :: list()) -> Status :: term()." n
+ "format_status(_Opt, Status) ->" n>
+ "Status." n
+ n
(erlang-skel-double-separator-start 3)
"%%% Internal functions" n
(erlang-skel-double-separator-end 3)
@@ -581,8 +641,8 @@ Please see the function `tempo-define-template'.")
"-export([start_link/0, add_handler/0])." n n
"%% gen_event callbacks" n
- "-export([init/1, handle_event/2, handle_call/2, " n>
- "handle_info/2, terminate/2, code_change/3])." n n
+ "-export([init/1, handle_event/2, handle_call/2, handle_info/2," n>
+ "terminate/2, code_change/3, format_status/2])." n n
"-define(SERVER, ?MODULE)." n n
@@ -594,18 +654,17 @@ Please see the function `tempo-define-template'.")
(erlang-skel-separator-start 2)
"%% @doc" n
"%% Creates an event manager" n
- "%%" n
- "%% @spec start_link() -> {ok, Pid} | {error, Error}" n
(erlang-skel-separator-end 2)
+ "-spec start_link() -> {ok, Pid :: pid()} |" n>
+ "{error, Error :: {already_started, pid()} | term()}." n
"start_link() ->" n>
"gen_event:start_link({local, ?SERVER})." n
n
(erlang-skel-separator-start 2)
"%% @doc" n
"%% Adds an event handler" n
- "%%" n
- "%% @spec add_handler() -> ok | {'EXIT', Reason} | term()" n
(erlang-skel-separator-end 2)
+ "-spec add_handler() -> ok | {'EXIT', Reason :: term()} | term()." n
"add_handler() ->" n>
"gen_event:add_handler(?SERVER, ?MODULE, [])." n
n
@@ -617,9 +676,11 @@ Please see the function `tempo-define-template'.")
"%% @doc" n
"%% Whenever a new event handler is added to an event manager," n
"%% this function is called to initialize the event handler." n
- "%%" n
- "%% @spec init(Args) -> {ok, State}" n
(erlang-skel-separator-end 2)
+ "-spec init(Args :: term() | {Args :: term(), Term :: term()}) ->" n>
+ "{ok, State :: term()} |" n>
+ "{ok, State :: term(), hibernate} |" n>
+ "{error, Reason :: term()}." n
"init([]) ->" n>
"{ok, #state{}}." n
n
@@ -629,12 +690,13 @@ Please see the function `tempo-define-template'.")
"%% Whenever an event manager receives an event sent using" n
"%% gen_event:notify/2 or gen_event:sync_notify/2, this function is" n
"%% called for each installed event handler to handle the event." n
- "%%" n
- "%% @spec handle_event(Event, State) ->" n
- "%% {ok, State} |" n
- "%% {swap_handler, Args1, State1, Mod2, Args2} |"n
- "%% remove_handler" n
(erlang-skel-separator-end 2)
+ "-spec handle_event(Event :: term(), State :: term()) ->" n>
+ "{ok, NewState :: term()} |" n>
+ "{ok, NewState :: term(), hibernate} |" n>
+ "remove_handler |" n>
+ "{swap_handler, Args1 :: term(), NewState :: term()," n>
+ "Handler2 :: atom() | {atom(), term()} , Args2 :: term()}." n>
"handle_event(_Event, State) ->" n>
"{ok, State}." n
n
@@ -644,12 +706,13 @@ Please see the function `tempo-define-template'.")
"%% Whenever an event manager receives a request sent using" n
"%% gen_event:call/3,4, this function is called for the specified" n
"%% event handler to handle the request." n
- "%%" n
- "%% @spec handle_call(Request, State) ->" n
- "%% {ok, Reply, State} |" n
- "%% {swap_handler, Reply, Args1, State1, Mod2, Args2} |" n
- "%% {remove_handler, Reply}" n
(erlang-skel-separator-end 2)
+ "-spec handle_call(Request :: term(), State :: term()) ->" n>
+ "{ok, Reply :: term(), NewState :: term()} |" n>
+ "{ok, Reply :: term(), NewState :: term(), hibernate} |" n>
+ "{remove_handler, Reply :: term()} |" n>
+ "{swap_handler, Reply :: term(), Args1 :: term(), NewState :: term()," n>
+ "Handler2 :: atom() | {atom(), term()}, Args2 :: term()}." n
"handle_call(_Request, State) ->" n>
"Reply = ok," n>
"{ok, Reply, State}." n
@@ -660,12 +723,13 @@ Please see the function `tempo-define-template'.")
"%% This function is called for each installed event handler when" n
"%% an event manager receives any other message than an event or a" n
"%% synchronous request (or a system message)." n
- "%%" n
- "%% @spec handle_info(Info, State) ->" n
- "%% {ok, State} |" n
- "%% {swap_handler, Args1, State1, Mod2, Args2} |" n
- "%% remove_handler" n
(erlang-skel-separator-end 2)
+ "-spec handle_info(Info :: term(), State :: term()) ->" n>
+ "{ok, NewState :: term()} |" n>
+ "{ok, NewState :: term(), hibernate} |" n>
+ "remove_handler |" n>
+ "{swap_handler, Args1 :: term(), NewState :: term()," n>
+ "Handler2 :: atom() | {atom(), term()}, Args2 :: term()}." n
"handle_info(_Info, State) ->" n>
"{ok, State}." n
n
@@ -675,22 +739,40 @@ Please see the function `tempo-define-template'.")
"%% Whenever an event handler is deleted from an event manager, this" n
"%% function is called. It should be the opposite of Module:init/1 and" n
"%% do any necessary cleaning up." n
- "%%" n
- "%% @spec terminate(Reason, State) -> void()" n
(erlang-skel-separator-end 2)
- "terminate(_Reason, _State) ->" n>
+ "-spec terminate(Arg :: {stop, Reason :: term()} |" n>
+ "stop |" n>
+ "remove_handler |" n>
+ "{error, {'EXIT', Reason :: term()}} |" n>
+ "{error, Term :: term()} |" n>
+ "term()," n>
+ "State :: term()) -> any()." n
+ "terminate(_Arg, _State) ->" n>
"ok." n
n
(erlang-skel-separator-start 2)
"%% @private" n
"%% @doc" n
"%% Convert process state when code is changed" n
- "%%" n
- "%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}" n
(erlang-skel-separator-end 2)
+ "-spec code_change(OldVsn :: term() | {down, term()}," n>
+ "State :: term()," n>
+ "Extra :: term()) -> {ok, NewState :: term()}." n
"code_change(_OldVsn, State, _Extra) ->" n>
"{ok, State}." n
n
+ (erlang-skel-separator-start 2)
+ "%% @private" n
+ "%% @doc" n
+ "%% This function is called for changing the form and appearance" n
+ "%% of gen_event status when it is returned from sys:get_status/1,2" n
+ "%% or when it appears in termination error logs." n
+ (erlang-skel-separator-end 2)
+ "-spec format_status(Opt :: normal | terminate," n>
+ "Status :: list()) -> Status :: term()." n
+ "format_status(_Opt, Status) ->" n>
+ "Status." n
+ n
(erlang-skel-double-separator-start 3)
"%%% Internal functions" n
(erlang-skel-double-separator-end 3)
diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el
index 438abc2d29..82e5c2222d 100644
--- a/lib/tools/emacs/erlang.el
+++ b/lib/tools/emacs/erlang.el
@@ -1,15 +1,15 @@
-;;; erlang.el --- Major modes for editing and running Erlang
+;;; erlang.el --- Major modes for editing and running Erlang -*- lexical-binding: t; -*-
;; Copyright (C) 2004 Free Software Foundation, Inc.
;; Author: Anders Lindgren
;; Keywords: erlang, languages, processes
;; Date: 2011-12-11
-;; Version: 2.7.0
+;; Version: 2.8.1
;; Package-Requires: ((emacs "24.1"))
;; %CopyrightBegin%
;;
-;; Copyright Ericsson AB 1996-2017. All Rights Reserved.
+;; Copyright Ericsson AB 1996-2018. All Rights Reserved.
;;
;; Licensed under the Apache License, Version 2.0 (the "License");
;; you may not use this file except in compliance with the License.
@@ -77,6 +77,7 @@
;;; Code:
(eval-when-compile (require 'cl))
+(require 'align)
;; Variables:
@@ -84,7 +85,7 @@
"The Erlang programming language."
:group 'languages)
-(defconst erlang-version "2.7"
+(defconst erlang-version "2.8.1"
"The version number of Erlang mode.")
(defcustom erlang-root-dir nil
@@ -804,6 +805,7 @@ resulting regexp is surrounded by \\_< and \\_>."
"is_integer"
"is_list"
"is_map"
+ "is_map_key"
"is_number"
"is_pid"
"is_port"
@@ -825,6 +827,7 @@ resulting regexp is surrounded by \\_< and \\_>."
"list_to_tuple"
"load_module"
"make_ref"
+ "map_get"
"map_size"
"max"
"min"
@@ -884,8 +887,6 @@ resulting regexp is surrounded by \\_< and \\_>."
"alloc_sizes"
"append"
"append_element"
- "await_proc_exit"
- "await_sched_wall_time_modifications"
"bump_reductions"
"call_on_load_function"
"cancel_timer"
@@ -895,16 +896,15 @@ resulting regexp is surrounded by \\_< and \\_>."
"decode_packet"
"delay_trap"
"delete_element"
- "dexit"
- "dgroup_leader"
"display"
"display_nl"
"display_string"
- "dist_exit"
- "dlink"
+ "dist_get_stat"
+ "dist_ctrl_get_data"
+ "dist_ctrl_get_data_notification"
+ "dist_ctrl_input_handler"
+ "dist_ctrl_put_data"
"dmonitor_node"
- "dmonitor_p"
- "dsend"
"dt_append_vm_tag_data"
"dt_get_tag"
"dt_get_tag_data"
@@ -912,8 +912,8 @@ resulting regexp is surrounded by \\_< and \\_>."
"dt_put_tag"
"dt_restore_tag"
"dt_spread_tag"
- "dunlink"
"convert_time_unit"
+ "exit_signal"
"external_size"
"finish_after_on_load"
"finish_loading"
@@ -924,13 +924,13 @@ resulting regexp is surrounded by \\_< and \\_>."
"function_exported"
"garbage_collect_message_area"
"gather_gc_info_result"
- "gather_sched_wall_time_result"
"get_cookie"
"get_module_info"
"get_stacktrace"
"has_prepared_code_on_load"
"hibernate"
"insert_element"
+ "iolist_to_iovec"
"is_builtin"
"load_nif"
"loaded"
@@ -1019,26 +1019,15 @@ files written in other languages than Erlang.")
If nil, the inferior shell replaces the window. This is the traditional
behaviour.")
-(defconst inferior-erlang-use-cmm (boundp 'minor-mode-overriding-map-alist)
- "Non-nil means use `compilation-minor-mode' in Erlang shell.")
-
(defvar erlang-mode-map
(let ((map (make-sparse-keymap)))
- (unless (boundp 'indent-line-function)
- (define-key map "\t" 'erlang-indent-command))
(define-key map ";" 'erlang-electric-semicolon)
(define-key map "," 'erlang-electric-comma)
(define-key map "<" 'erlang-electric-lt)
(define-key map ">" 'erlang-electric-gt)
(define-key map "\C-m" 'erlang-electric-newline)
- (if (not (boundp 'delete-key-deletes-forward))
- (define-key map "\177" 'backward-delete-char-untabify)
- (define-key map [(backspace)] 'backward-delete-char-untabify))
- ;;(unless (boundp 'fill-paragraph-function)
+ (define-key map [(backspace)] 'backward-delete-char-untabify)
(define-key map "\M-q" 'erlang-fill-paragraph)
- (unless (boundp 'beginning-of-defun-function)
- (define-key map "\M-\C-a" 'erlang-beginning-of-function)
- (define-key map "\M-\C-e" 'erlang-end-of-function))
(define-key map "\M-\t" 'erlang-complete-tag)
(define-key map "\C-c\M-\t" 'tempo-complete-tag)
(define-key map "\M-+" 'erlang-find-next-tag)
@@ -1057,8 +1046,6 @@ behaviour.")
(define-key map "\C-c\C-y" 'erlang-clone-arguments)
(define-key map "\C-c\C-a" 'erlang-align-arrows)
(define-key map "\C-c\C-z" 'erlang-shell-display)
- (unless inferior-erlang-use-cmm
- (define-key map "\C-x`" 'erlang-next-error))
map)
"Keymap used in Erlang mode.")
(defvar erlang-mode-abbrev-table nil
@@ -1419,6 +1406,19 @@ Other commands:
(add-function :before-until (local 'eldoc-documentation-function)
#'erldoc-eldoc-function))
(run-hooks 'erlang-mode-hook)
+
+ ;; Align maps.
+ (add-to-list 'align-rules-list
+ '(erlang-maps
+ (regexp . "\\(\\s-*\\)\\(=>\\)\\s-*")
+ (modes . '(erlang-mode))
+ (repeat . t)))
+ ;; Align records and :: specs
+ (add-to-list 'align-rules-list
+ '(erlang-record-specs
+ (regexp . "\\(\\s-*\\)\\(=\\).*\\(::\\)*\\s-*")
+ (modes . '(erlang-mode))
+ (repeat . t)))
(if (zerop (buffer-size))
(run-hooks 'erlang-new-file-hook)))
@@ -2083,12 +2083,6 @@ This function is aware of imported functions."
(when funcname
(erlang-man-find-function (current-buffer) funcname))))))
-(defun erlang-default-function-or-module ()
- (let ((id (erlang-get-identifier-at-point)))
- (if (eq (erlang-id-kind id) 'qualified-function)
- (format "%s:%s" (erlang-id-module id) (erlang-id-name id))
- (erlang-id-name id))))
-
;; Should the defadvice be at the top level, the package `advice' would
;; be required. Now it is only required when this functionality
@@ -2763,7 +2757,7 @@ Return nil if inside string, t if in a comment."
(1+ (nth 2 stack-top)))
((= (char-syntax (following-char)) ?\))
(goto-char (nth 1 stack-top))
- (cond ((looking-at "[({]\\s *\\($\\|%\\)")
+ (cond ((erlang-record-or-function-args-p)
;; Line ends with parenthesis.
(let ((previous (erlang-indent-find-preceding-expr))
(stack-pos (nth 2 stack-top)))
@@ -2773,19 +2767,10 @@ Return nil if inside string, t if in a comment."
(nth 2 stack-top))))
((= (following-char) ?,)
;; a comma at the start of the line: line up with opening parenthesis.
- (nth 2 stack-top))
+ (min (nth 2 stack-top)
+ (erlang-indent-element stack-top indent-point token)))
(t
- (goto-char (nth 1 stack-top))
- (let ((base (cond ((looking-at "[({]\\s *\\($\\|%\\)")
- ;; Line ends with parenthesis.
- (erlang-indent-parenthesis (nth 2 stack-top)))
- (t
- ;; Indent to the same column as the first
- ;; argument.
- (goto-char (1+ (nth 1 stack-top)))
- (skip-chars-forward " \t")
- (current-column)))))
- (erlang-indent-standard indent-point token base 't)))))
+ (erlang-indent-element stack-top indent-point token))))
;;
((eq (car stack-top) '<<)
;; Element of binary (possible comprehension) expression,
@@ -2794,13 +2779,11 @@ Return nil if inside string, t if in a comment."
(+ 2 (nth 2 stack-top)))
((looking-at "\\(>>\\)[^_a-zA-Z0-9]")
(nth 2 stack-top))
+ ((= (following-char) ?,)
+ (min (+ (nth 2 stack-top) 1)
+ (- (erlang-indent-to-first-element stack-top 2) 1)))
(t
- (goto-char (nth 1 stack-top))
- ;; Indent to the same column as the first
- ;; argument.
- (goto-char (+ 2 (nth 1 stack-top)))
- (skip-chars-forward " \t")
- (current-column))))
+ (erlang-indent-to-first-element stack-top 2))))
((memq (car stack-top) '(icr fun spec))
;; The default indentation is the column of the option
@@ -2856,12 +2839,13 @@ Return nil if inside string, t if in a comment."
(let ((base (erlang-indent-find-base stack indent-point off skip)))
;; Special cases
(goto-char indent-point)
- (cond ((looking-at "\\(end\\|after\\)\\($\\|[^_a-zA-Z0-9]\\)")
+ (cond ((looking-at "\\(;\\|end\\|after\\)\\($\\|[^_a-zA-Z0-9]\\)")
(if (eq (car stack-top) '->)
(erlang-pop stack))
- (if stack
- (erlang-caddr (car stack))
- 0))
+ (cond ((and stack (looking-at ";"))
+ (+ (erlang-caddr (car stack)) (- erlang-indent-level 2)))
+ (stack (erlang-caddr (car stack)))
+ (t off)))
((looking-at "catch\\b\\($\\|[^_a-zA-Z0-9]\\)")
;; Are we in a try
(let ((start (if (eq (car stack-top) '->)
@@ -2935,6 +2919,22 @@ Return nil if inside string, t if in a comment."
(current-column))) start-alternativ))))))
)))
+(defun erlang-indent-to-first-element (stack-top extra)
+ ;; Indent to the same column as the first
+ ;; argument. extra should be 1 for lists tuples or 2 for binaries
+ (goto-char (+ (nth 1 stack-top) extra))
+ (skip-chars-forward " \t")
+ (current-column))
+
+(defun erlang-indent-element (stack-top indent-point token)
+ (goto-char (nth 1 stack-top))
+ (let ((base (cond ((erlang-record-or-function-args-p)
+ ;; Line ends with parenthesis.
+ (erlang-indent-parenthesis (nth 2 stack-top)))
+ (t
+ (erlang-indent-to-first-element stack-top 1)))))
+ (erlang-indent-standard indent-point token base 't)))
+
(defun erlang-indent-standard (indent-point token base inside-parenthesis)
"Standard indent when in blocks or tuple or arguments.
Look at last thing to see in what state we are, move relative to the base."
@@ -2960,6 +2960,9 @@ Return nil if inside string, t if in a comment."
;; Avoid treating comments a continued line.
((= (following-char) ?%)
base)
+ ((and (= (following-char) ?,) inside-parenthesis)
+ ;; a comma at the start of the line line up with parenthesis
+ (- base 1))
;; Continued line (e.g. line beginning
;; with an operator.)
(t
@@ -3049,11 +3052,21 @@ This assumes that the preceding expression is either simple
(t col)))
col))))
+(defun erlang-record-or-function-args-p ()
+ (and (looking-at "[({]\\s *\\($\\|%\\)")
+ (or (eq (following-char) ?\( )
+ (save-excursion
+ (ignore-errors (forward-sexp (- 1)))
+ (eq (preceding-char) ?#)))))
+
(defun erlang-indent-parenthesis (stack-position)
(let ((previous (erlang-indent-find-preceding-expr)))
- (if (> previous stack-position)
- (+ stack-position erlang-argument-indent)
- (+ previous erlang-argument-indent))))
+ (cond ((eq previous stack-position) ;; tuple or map not a record
+ (1+ stack-position))
+ ((> previous stack-position)
+ (+ stack-position erlang-argument-indent))
+ (t
+ (+ previous erlang-argument-indent)))))
(defun erlang-skip-blank (&optional lim)
"Skip over whitespace and comments until limit reached."
@@ -3396,14 +3409,6 @@ at the end."
;;; Information retrieval functions.
-(defun erlang-buffer-substring (beg end)
- "Like `buffer-substring-no-properties'.
-Although, this function works on all versions of Emacs."
- (if (fboundp 'buffer-substring-no-properties)
- (funcall (symbol-function 'buffer-substring-no-properties) beg end)
- (buffer-substring beg end)))
-
-
(defun erlang-get-module ()
"Return the name of the module as specified by `-module'.
@@ -3421,7 +3426,7 @@ Return nil if file contains no `-module' attribute."
"\\)?\\)\\s *)\\s *\\."))
(point-max) t)
(erlang-remove-quotes
- (erlang-buffer-substring (match-beginning 1)
+ (buffer-substring-no-properties (match-beginning 1)
(match-end 1)))
nil)
(store-match-data md))))))
@@ -3475,10 +3480,10 @@ corresponds to the order of the parsed Erlang list."
(setq res (cons
(cons
(erlang-remove-quotes
- (erlang-buffer-substring
+ (buffer-substring-no-properties
(match-beginning 1) (match-end 1)))
(string-to-number
- (erlang-buffer-substring
+ (buffer-substring-no-properties
(match-beginning
(+ 1 erlang-atom-regexp-matches))
(match-end
@@ -3525,7 +3530,7 @@ function and arity as cdr part."
(erlang-skip-blank)
(if (looking-at erlang-atom-regexp)
(let ((module (erlang-remove-quotes
- (erlang-buffer-substring
+ (buffer-substring-no-properties
(match-beginning 0)
(match-end 0)))))
(goto-char (match-end 0))
@@ -3558,7 +3563,7 @@ Normally used in conjunction with `erlang-beginning-of-clause', e.g.:
(let ((n (if arg 0 1)))
(and (looking-at (eval-when-compile
(concat "^" erlang-atom-regexp "\\s *(")))
- (erlang-buffer-substring (match-beginning n) (match-end n)))))
+ (buffer-substring-no-properties (match-beginning n) (match-end n)))))
(defun erlang-get-function-arrow ()
@@ -3572,7 +3577,7 @@ Normally used in conjunction with `erlang-beginning-of-clause', e.g.:
(and
(save-excursion
(re-search-forward "->" (point-max) t)
- (erlang-buffer-substring (- (point) 2) (+ (point) 1)))))
+ (buffer-substring-no-properties (- (point) 2) (+ (point) 1)))))
(defun erlang-get-function-arity ()
"Return the number of arguments of function at point, or nil."
@@ -3638,12 +3643,14 @@ The return value is a string of the form \"foo/1\"."
(let ((start (match-end 0)))
(goto-char (- start 1))
(forward-sexp)
- (erlang-buffer-substring start (- (point) 1)))
+ (buffer-substring-no-properties start (- (point) 1)))
(error nil)))))
-;; Keeping erlang-get-function-under-point for backward compatibility.
-;; It is used by erldoc.el and maybe other code out there.
+;; erlang-get-function-under-point is replaced by
+;; erlang-get-identifier-at-point as far as internal erlang.el usage
+;; is concerned. But it is kept for backward compatibility. It is
+;; used by erldoc.el and maybe other code out there.
(defun erlang-get-function-under-point ()
"Return the module and function under the point, or nil.
@@ -3701,10 +3708,10 @@ of arguments could be found, otherwise nil."
(defun erlang-get-qualified-function-id-at-point ()
(let ((kind 'qualified-function)
(module (erlang-remove-quotes
- (erlang-buffer-substring
+ (buffer-substring-no-properties
(match-beginning 1) (match-end 1))))
(name (erlang-remove-quotes
- (erlang-buffer-substring
+ (buffer-substring-no-properties
(match-beginning (1+ erlang-atom-regexp-matches))
(match-end (1+ erlang-atom-regexp-matches)))))
(arity (progn
@@ -3716,14 +3723,14 @@ of arguments could be found, otherwise nil."
(let ((kind 'module)
(module nil)
(name (erlang-remove-quotes
- (erlang-buffer-substring (match-beginning 1)
+ (buffer-substring-no-properties (match-beginning 1)
(match-end 1))))
(arity nil))
(list kind module name arity)))
(defun erlang-get-some-other-id-at-point ()
(let ((name (erlang-remove-quotes
- (erlang-buffer-substring
+ (buffer-substring-no-properties
(match-beginning 0) (match-end 0))))
(imports (erlang-get-import))
kind module arity)
@@ -3790,6 +3797,21 @@ of arguments could be found, otherwise nil."
(nth 3 (erlang-id-to-list id)))
+(defun erlang-default-function-or-module ()
+ (erlang-with-id (kind module name) (erlang-get-identifier-at-point)
+ (let ((x (cond ((eq kind 'module)
+ (format "%s:" name))
+ ((eq kind 'record)
+ (format "-record(%s" name))
+ ((eq kind 'macro)
+ (format "-define(%s" name))
+ (t
+ name))))
+ (if module
+ (format "%s:%s" module x)
+ x))))
+
+
;; TODO: Escape single quotes inside the string without
;; replace-regexp-in-string.
(defun erlang-add-quotes-if-needed (str)
@@ -4881,7 +4903,12 @@ considered first when it is time to jump to the definition.")
'(progn
(cl-defmethod xref-backend-identifier-at-point
((_backend (eql erlang-etags)))
- (erlang-id-to-string (erlang-get-identifier-at-point)))
+ (if (eq this-command 'xref-find-references)
+ (if (use-region-p)
+ (buffer-substring-no-properties (region-beginning)
+ (region-end))
+ (thing-at-point 'symbol))
+ (erlang-id-to-string (erlang-get-identifier-at-point))))
(cl-defmethod xref-backend-definitions
((_backend (eql erlang-etags)) identifier)
@@ -4992,9 +5019,10 @@ considered first when it is time to jump to the definition.")
(and (fboundp 'xref-make)
(fboundp 'xref-make-file-location)
(let* ((first-time t)
+ (cbuf (current-buffer))
xrefs matching-files)
(save-excursion
- (while (visit-tags-table-buffer (not first-time))
+ (while (erlang-visit-tags-table-buffer (not first-time) cbuf)
(setq first-time nil)
(let ((files (tags-table-files)))
(while files
@@ -5010,6 +5038,10 @@ considered first when it is time to jump to the definition.")
(setq files (cdr files))))))
(nreverse xrefs))))
+(defun erlang-visit-tags-table-buffer (cont cbuf)
+ (if (< emacs-major-version 26)
+ (visit-tags-table-buffer cont)
+ (visit-tags-table-buffer cont cbuf)))
(defun erlang-xref-find-definitions-module-tag (module
tag
@@ -5113,7 +5145,7 @@ Erlang compilation package.")
"Command to execute to go to the next error.
Change this variable to use your favorite Erlang compilation
-package. Not used in Emacs 21.")
+package.")
;;;###autoload
@@ -5168,61 +5200,43 @@ future, a new shell on an already running host will be started."
;; e.g. it does not assume that we are running an inferior
;; Erlang, there exists a lot of other possibilities.
-
(defvar erlang-shell-buffer-name "*erlang*"
"The name of the Erlang link shell buffer.")
-(defvar erlang-shell-mode-map nil
- "Keymap used by Erlang shells.")
-
-
-(defvar erlang-shell-mode-hook nil
- "User functions to run when an Erlang shell is started.
+(defcustom erlang-shell-prompt-read-only t
+ "If non-nil, the prompt will be read-only.
-This hook is used to change the behaviour of Erlang mode. It is
-normally used by the user to personalise the programming environment.
-When used in a site init file, it could be used to customise Erlang
-mode for all users on the system.
+Also see the description of `ielm-prompt-read-only'."
+ :type 'boolean
+ :package-version '(erlang . "2.8.0"))
-The function added to this hook is run every time a new Erlang
-shell is started.
+(defvar erlang-shell-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map "\M-\t" 'erlang-complete-tag)
-See also `erlang-load-hook', a hook which is run once, when Erlang
-mode is loaded, and `erlang-mode-hook' which is run every time a new
-Erlang source file is loaded into Emacs.")
+ ;; Normally the other way around.
+ (define-key map "\C-a" 'comint-bol)
+ (define-key map "\C-c\C-a" 'beginning-of-line)
+ (define-key map "\C-d" nil) ; Was `comint-delchar-or-maybe-eof'
+ (define-key map "\M-\C-m" 'compile-goto-error)
+ map)
+ "Keymap used by Erlang shells.")
(defvar erlang-input-ring-file-name "~/.erlang_history"
"When non-nil, file name used to store Erlang shell history information.")
-
-(defun erlang-shell-mode ()
+(define-derived-mode erlang-shell-mode comint-mode "Erlang Shell"
"Major mode for interacting with an Erlang shell.
-We assume that we already are in Comint mode.
-
The following special commands are available:
\\{erlang-shell-mode-map}"
- (interactive)
- (setq major-mode 'erlang-shell-mode)
- (setq mode-name "Erlang Shell")
(erlang-mode-variables)
- (if erlang-shell-mode-map
- nil
- (setq erlang-shell-mode-map (copy-keymap comint-mode-map))
- (erlang-shell-mode-commands erlang-shell-mode-map))
- (use-local-map erlang-shell-mode-map)
- (unless inferior-erlang-use-cmm
- ;; This was originally not a marker, but it needs to be, at least
- ;; in Emacs 21, and should be backwards-compatible. Otherwise,
- ;; would need to test whether compilation-parsing-end is a marker
- ;; after requiring `compile'.
- (set (make-local-variable 'compilation-parsing-end) (copy-marker 1))
- (set (make-local-variable 'compilation-error-list) nil)
- (set (make-local-variable 'compilation-old-error-list) nil))
;; Needed when compiling directly from the Erlang shell.
(setq compilation-last-buffer (current-buffer))
(setq comint-prompt-regexp "^[^>=]*> *")
+ (make-local-variable 'comint-prompt-read-only)
+ (setq comint-prompt-read-only erlang-shell-prompt-read-only)
(setq comint-eol-on-send t)
(setq comint-input-ignoredups t)
(setq comint-scroll-show-maximum-output t)
@@ -5231,31 +5245,25 @@ The following special commands are available:
'inferior-erlang-strip-delete nil t)
(add-hook 'comint-output-filter-functions
'inferior-erlang-strip-ctrl-m nil t)
-
(setq comint-input-ring-file-name erlang-input-ring-file-name)
(comint-read-input-ring t)
(make-local-variable 'kill-buffer-hook)
(add-hook 'kill-buffer-hook 'comint-write-input-ring)
- ;; At least in Emacs 21, we need to be in `compilation-minor-mode'
- ;; for `next-error' to work. We can avoid it clobbering the shell
- ;; keys thus.
- (when inferior-erlang-use-cmm
- (compilation-minor-mode 1)
- (set (make-local-variable 'minor-mode-overriding-map-alist)
- `((compilation-minor-mode
- . ,(let ((map (make-sparse-keymap)))
- ;; It would be useful to put keymap properties on the
- ;; error lines so that we could use RET and mouse-2
- ;; on them directly.
- (when (boundp 'compilation-skip-threshold) ; new compile.el
- (define-key map [mouse-2] #'erlang-mouse-2-command)
- (define-key map "\C-m" #'erlang-RET-command))
- (if (boundp 'compilation-menu-map)
- (define-key map [menu-bar compilation]
- (cons "Errors" compilation-menu-map)))
- map)))))
- (erlang-tags-init)
- (run-hooks 'erlang-shell-mode-hook))
+ (compilation-minor-mode 1)
+ (set (make-local-variable 'minor-mode-overriding-map-alist)
+ `((compilation-minor-mode
+ . ,(let ((map (make-sparse-keymap)))
+ ;; It would be useful to put keymap properties on the
+ ;; error lines so that we could use RET and mouse-2
+ ;; on them directly.
+ (when (boundp 'compilation-skip-threshold) ; new compile.el
+ (define-key map [mouse-2] #'erlang-mouse-2-command)
+ (define-key map "\C-m" #'erlang-RET-command))
+ (if (boundp 'compilation-menu-map)
+ (define-key map [menu-bar compilation]
+ (cons "Errors" compilation-menu-map)))
+ map))))
+ (erlang-tags-init))
(defun erlang-mouse-2-command (event)
@@ -5277,15 +5285,6 @@ Selects Comint or Compilation mode command as appropriate."
(call-interactively (lookup-key compilation-mode-map "\C-m"))
(call-interactively (lookup-key comint-mode-map "\C-m"))))
-(defun erlang-shell-mode-commands (map)
- (define-key map "\M-\t" 'erlang-complete-tag)
- (define-key map "\C-a" 'comint-bol) ; Normally the other way around.
- (define-key map "\C-c\C-a" 'beginning-of-line)
- (define-key map "\C-d" nil) ; Was `comint-delchar-or-maybe-eof'
- (define-key map "\M-\C-m" 'compile-goto-error)
- (unless inferior-erlang-use-cmm
- (define-key map "\C-x`" 'erlang-next-error)))
-
;;;
;;; Inferior Erlang -- Run an Erlang shell as a subprocess.
;;;
@@ -5895,35 +5894,6 @@ Tab characters are counted by their visual width."
(if (looking-at "[a-z0-9_]+")
(match-string 0))))
-;; Aliases for backward compatibility with older versions of Erlang Mode.
-;;
-;; Unfortuantely, older versions of Emacs doesn't have `defalias' and
-;; `make-obsolete' so we have to define our own `obsolete' function.
-
-(defun erlang-obsolete (sym newdef)
- "Make the obsolete function SYM refer to the defined function NEWDEF.
-
-Simplified version of a combination `defalias' and `make-obsolete',
-it assumes that NEWDEF is loaded."
- (defalias sym (symbol-function newdef))
- (make-obsolete sym newdef "long ago"))
-
-
-(erlang-obsolete 'calculate-erlang-indent 'erlang-calculate-indent)
-(erlang-obsolete 'calculate-erlang-stack-indent
- 'erlang-calculate-stack-indent)
-(erlang-obsolete 'at-erlang-keyword 'erlang-at-keyword)
-(erlang-obsolete 'at-erlang-operator 'erlang-at-operator)
-(erlang-obsolete 'beginning-of-erlang-clause 'erlang-beginning-of-clause)
-(erlang-obsolete 'end-of-erlang-clause 'erlang-end-of-clause)
-(erlang-obsolete 'mark-erlang-clause 'erlang-mark-clause)
-(erlang-obsolete 'beginning-of-erlang-function 'erlang-beginning-of-function)
-(erlang-obsolete 'end-of-erlang-function 'erlang-end-of-function)
-(erlang-obsolete 'mark-erlang-function 'erlang-mark-function)
-(erlang-obsolete 'pass-over-erlang-clause 'erlang-pass-over-function)
-(erlang-obsolete 'name-of-erlang-function 'erlang-name-of-function)
-
-
(defconst erlang-unload-hook
(list (lambda ()
(ad-unadvise 'Man-notify-when-ready)
diff --git a/lib/tools/emacs/test.erl.indented b/lib/tools/emacs/test.erl.indented
deleted file mode 100644
index 14a4eca7c3..0000000000
--- a/lib/tools/emacs/test.erl.indented
+++ /dev/null
@@ -1,784 +0,0 @@
-%% -*- Mode: erlang; indent-tabs-mode: nil -*-
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-
-%%%-------------------------------------------------------------------
-%%% File : test.erl
-%%% Author : Dan Gudmundsson <[email protected]>
-%%% Description : Test emacs mode indention and font-locking
-%%% this file is intentionally not indented.
-%%% Copy the file and indent it and you should end up with test.erl.indented
-%%% Created : 6 Oct 2009 by Dan Gudmundsson <[email protected]>
-%%%-------------------------------------------------------------------
-
-%% Start off with syntax highlighting you have to verify this by looking here
-%% and see that the code looks alright
-
--module(test).
--compile(export_all).
-
-%% Used to cause an "Unbalanced parentheses" error.
-foo(M) ->
- M#{a :=<<"a">>
- ,b:=1}.
-foo() ->
- #{a =><<"a">>
- ,b=>1}.
-
-%% Module attributes should be highlighted
-
--export([t/1]).
--record(record1, {a,
- b,
- c
- }).
--record(record2, {
- a,
- b
- }).
-
--record(record3, {a = 8#42423 bor
- 8#4234,
- b = 8#5432
- bor 2#1010101
- c = 123 +
- 234,
- d}).
-
--record(record4, {
- a = 8#42423 bor
- 8#4234,
- b = 8#5432
- bor 2#1010101
- c = 123 +
- 234,
- d}).
-
--record(record5, { a = 1 :: integer()
- , b = foobar :: atom()
- }).
-
--define(MACRO_1, macro).
--define(MACRO_2(_), macro).
-
--spec t(integer()) -> any().
-
--type ann() :: Var :: integer().
--type ann2() :: Var ::
- 'return'
- | 'return_white_spaces'
- | 'return_comments'
- | 'text' | ann().
--type paren() ::
- (ann2()).
--type t1() :: atom().
--type t2() :: [t1()].
--type t3(Atom) :: integer(Atom).
--type t4() :: t3(foobar).
--type t5() :: {t1(), t3(foo)}.
--type t6() :: 1 | 2 | 3 |
- 'foo' | 'bar'.
--type t7() :: [].
--type t71() :: [_].
--type t8() :: {any(),none(),pid(),port(),
- reference(),float()}.
--type t9() :: [1|2|3|foo|bar] |
- list(a | b | c) | t71().
--type t10() :: {1|2|3|foo|t9()} | {}.
--type t11() :: 1..2.
--type t13() :: maybe_improper_list(integer(), t11()).
--type t14() :: [erl_scan:foo() |
- %% Should be highlighted
- term() |
- bool() |
- byte() |
- char() |
- non_neg_integer() | nonempty_list() |
- pos_integer() |
- neg_integer() |
- number() |
- list() |
- nonempty_improper_list() | nonempty_maybe_improper_list() |
- maybe_improper_list() | string() | iolist() | byte() |
- module() |
- mfa() |
- node() |
- timeout() |
- no_return() |
- %% Should not be highlighted
- nonempty_() | nonlist() |
- erl_scan:bar(34, 92) | t13() | m:f(integer() | <<_:_*16>>)].
-
-
--type t15() :: {binary(),<<>>,<<_:34>>,<<_:_*42>>,
- <<_:3,_:_*14>>,<<>>} | [<<>>|<<_:34>>|<<_:16>>|
- <<_:3,_:_*1472>>|<<_:19,_:_*14>>| <<_:34>>|
- <<_:34>>|<<_:34>>|<<_:34>>].
--type t16() :: fun().
--type t17() :: fun((...) -> paren()).
--type t18() :: fun(() -> t17() | t16()).
--type t19() :: fun((t18()) -> t16()) |
- fun((nonempty_maybe_improper_list('integer', any())|
- 1|2|3|a|b|<<_:3,_:_*14>>|integer()) ->
- nonempty_maybe_improper_list('integer', any())|
- 1|2|3|a|b|<<_:3,_:_*14>>|integer()).
--type t20() :: [t19(), ...].
--type t21() :: tuple().
--type t21(A) :: A.
--type t22() :: t21(integer()).
--type t23() :: #rec1{}.
--type t24() :: #rec2{a :: t23(), b :: [atom()]}.
--type t25() :: #rec3{f123 :: [t24() |
- 1|2|3|4|a|b|c|d|
- nonempty_maybe_improper_list(integer, any())]}.
--type t26() :: #rec4{ a :: integer()
- , b :: any()
- }.
--type t27() :: { integer()
- , atom()
- }.
--type t99() ::
- {t2(),t4(),t5(),t6(),t7(),t8(),t10(),t14(),
- t15(),t20(),t21(), t22(),t25()}.
--spec t1(FooBar :: t99()) -> t99();
- (t2()) -> t2();
- (t4()) -> t4() when is_subtype(t4(), t24);
- (t23()) -> t23() when is_subtype(t23(), atom()),
- is_subtype(t23(), t14());
- (t24()) -> t24() when is_subtype(t24(), atom()),
- is_subtype(t24(), t14()),
- is_subtype(t24(), t4()).
-
--spec over(I :: integer()) -> R1 :: foo:typen();
- (A :: atom()) -> R2 :: foo:atomen();
- (T :: tuple()) -> R3 :: bar:typen().
-
--spec mod:t2() -> any().
-
--spec handle_cast(Cast :: {'exchange', node(), [[name(),...]]}
- | {'del_member', name(), pid()},
- #state{}) -> {'noreply', #state{}}.
-
--spec handle_cast(Cast ::
- {'exchange', node(), [[name(),...]]}
- | {'del_member', name(), pid()},
- #state{}) -> {'noreply', #state{}}.
-
--spec all(fun((T) -> boolean()), List :: [T]) ->
- boolean() when is_subtype(T, term()). % (*)
-
--spec get_closest_pid(term()) ->
- Return :: pid()
- | {'error', {'no_process', term()}
- | {'no_such_group', term()}}.
-
--spec add( X :: integer()
- , Y :: integer()
- ) -> integer().
-
--opaque attributes_data() ::
- [{'column', column()} | {'line', info_line()} |
- {'text', string()}] | {line(),column()}.
--record(r,{
- f1 :: attributes_data(),
- f222 = foo:bar(34, #rec3{}, 234234234423,
- aassdsfsdfsdf, 2234242323) ::
- [t24() | 1|2|3|4|a|b|c|d|
- nonempty_maybe_improper_list(integer, any())],
- f333 :: [t24() | 1|2|3|4|a|b|c|d|
- nonempty_maybe_improper_list(integer, any())],
- f3 = x:y(),
- f4 = x:z() :: t99(),
- f17 :: 'undefined',
- f18 :: 1 | 2 | 'undefined',
- f19 = 3 :: integer()|undefined,
- f5 = 3 :: undefined|integer()}).
-
--record(state, {
- sequence_number = 1 :: integer()
- }).
-
-
-highlighting(X) % Function definitions should be highlighted
- when is_integer(X) -> % and so should `when' and `is_integer' be
- %% Highlighting
- %% Various characters (we keep an `atom' after to see that highlighting ends)
- $a,atom, % Characters should be marked
- "string",atom, % and strings
- 'asdasd',atom, % quote should be atoms??
- 'VaV',atom,
- 'aVa',atom,
- '\'atom',atom,
- 'atom\'',atom,
- 'at\'om',atom,
- '#1',atom,
-
- $", atom, % atom should be ok
- $', atom,
-
- "string$", atom, "string$", atom, % currently buggy I know...
- "string\$", atom, % workaround for bug above
-
- "char $in string", atom,
-
- 'atom$', atom, 'atom$', atom,
- 'atom\$', atom,
-
- 'char $in atom', atom,
-
- $[, ${, $\\, atom,
- ?MACRO_1,
- ?MACRO_2(foo),
-
- %% Numerical constants
- 16#DD, % AD Should not be highlighted
- 32#dd, % AD Should not be highlighted
- 32#ddAB, % AD Should not be highlighted
- 32#101, % AD Should not be highlighted
- 32#ABTR, % AD Should not be highlighted
-
- %% Variables
- Variables = lists:foo(),
- _Variables = lists:foo(), % AD
- AppSpec = Xyz/2,
- Module42 = Xyz(foo, bar),
- Module:foo(),
- _Module:foo(), % AD
- FooÅÅ = lists:reverse([tl,hd,tl,hd]), % AD Should highlight FooÅÅ
- _FooÅÅ = 42, % AD Should highlight _FooÅÅ
-
- %% Bifs
- erlang:registered(),
- registered(),
- hd(tl(tl(hd([a,b,c])))),
- erlang:anything(lists),
- %% Guards
- is_atom(foo), is_float(2.3), is_integer(32), is_number(4323.3),
- is_function(Fun), is_pid(self()),
- not_a_guard:is_list([]),
- %% Other Types
-
- atom, % not (currently) hightlighted
- 234234,
- 234.43,
-
- [list, are, not, higlighted],
- {nor, is, tuple},
- ok.
-
-%%%
-%%% Indentation
-%%%
-
-%%% Left
-
-%% Indented
-
- % Right
-
-
-indent_basics(X, Y, Z)
- when X > 42,
- Z < 13;
- Y =:= 4711 ->
- %% comments
- % right comments
- case lists:filter(fun(_, AlongName,
- B,
- C) ->
- true
- end,
- [a,v,b])
- of
- [] ->
- Y = 5 * 43,
- ok;
- [_|_] ->
- Y = 5 * 43,
- ok
- end,
- Y,
- %% List, tuples and binaries
- [a,
- b, c
- ],
- [ a,
- b, c
- ],
-
- [
- a,
- b
- ],
- {a,
- b,c
- },
- { a,
- b,c
- },
-
- {
- a,
- b
- },
-
- <<1:8,
- 2:8
- >>,
- <<
- 1:8,
- 2:8
- >>,
- << 1:8,
- 2:8
- >>,
-
- (a,
- b,
- c
- ),
-
- ( a,
- b,
- c
- ),
-
-
- (
- a,
- b,
- c
- ),
-
- call(2#42423 bor
- #4234,
- 2#5432,
- other_arg),
- ok;
-indent_basics(Xlongname,
- #struct{a=Foo,
- b=Bar},
- [X|
- Y]) ->
- testing_next_clause,
- ok;
-indent_basics( % AD added clause
- X, % not sure how this should look
- Y,
- Z)
- when
- X < 42, Z > 13;
- Y =:= 4711 ->
- foo;
-indent_basics(X, Y, Z) when % AD added clause
- X < 42, Z > 13; % testing when indentation
- Y =:= 4711 ->
- foo;
-indent_basics(X, Y, Z) % AD added clause
- when % testing when indentation
- X < 42, Z > 13; % unsure about this one
- Y =:= 4711 ->
- foo.
-
-
-
-indent_nested() ->
- [
- {foo, 2, "string"},
- {bar, 3, "another string"}
- ].
-
-
-indent_icr(Z) -> % icr = if case receive
- %% If
- if Z >= 0 ->
- X = 43 div 4,
- foo(X);
- Z =< 10 ->
- X = 43 div 4,
- foo(X);
- Z == 5 orelse
- Z == 7 ->
- X = 43 div 4,
- foo(X);
- true ->
- if_works
- end,
- %% Case
- case {Z, foo, bar} of
- {Z,_,_} ->
- X = 43 div 4,
- foo(X);
- {Z,_,_} when
- Z =:= 42 -> % AD line should be indented as a when
- X = 43 div 4,
- foo(X);
- {Z,_,_}
- when Z < 10 -> % AD when should be indented
- X = 43 div 4,
- foo(X);
- {Z,_,_}
- when % AD when should be indented
- Z < 10 % and the guards should follow when
- andalso % unsure about how though
- true ->
- X = 43 div 4,
- foo(X)
- end,
- %% begin
- begin
- sune,
- X = 74234 + foo(8456) +
- 345 div 43,
- ok
- end,
-
-
- %% receive
- receive
- {Z,_,_} ->
- X = 43 div 4,
- foo(X);
- Z ->
- X = 43 div 4,
- foo(X)
- end,
- receive
- {Z,_,_} ->
- X = 43 div 4,
- foo(X);
- Z % AD added clause
- when Z =:= 1 -> % This line should be indented by 2
- X = 43 div 4,
- foo(X);
- Z when % AD added clause
- Z =:= 2 -> % This line should be indented by 2
- X = 43 div 4,
- foo(X);
- Z ->
- X = 43 div 4,
- foo(X)
- after infinity ->
- foo(X),
- asd(X),
- 5*43
- end,
- receive
- after 10 ->
- foo(X),
- asd(X),
- 5*43
- end,
- ok.
-
-indent_fun() ->
- %% Changed fun to one indention level
- Var = spawn(fun(X)
- when X == 2;
- X > 10 ->
- hello,
- case Hello() of
- true when is_atom(X) ->
- foo;
- false ->
- bar
- end;
- (Foo) when is_atom(Foo),
- is_integer(X) ->
- X = 6* 45,
- Y = true andalso
- kalle
- end),
- %% check EEP37 named funs
- Fn1 = fun Fact(N) when N > 0 ->
- F = Fact(N-1),
- N * F;
- Fact(0) ->
- 1
- end,
- %% check anonymous funs too
- Fn2 = fun(0) ->
- 1;
- (N) ->
- N
- end,
- ok.
-
-indent_try_catch() ->
- try
- io:format(stdout, "Parsing file ~s, ",
- [St0#leex.xfile]),
- {ok,Line3,REAs,Actions,St3} =
- parse_rules(Xfile, Line2, Macs, St2)
- catch
- exit:{badarg,R} ->
- foo(R),
- io:format(stdout,
- "ERROR reason ~p~n",
- R);
- error:R % AD added clause
- when R =:= 42 -> % when should be indented
- foo(R);
- error:R % AD added clause
- when % when should be indented
- R =:= 42 -> % but unsure about this (maybe 2 more)
- foo(R);
- error:R when % AD added clause
- R =:= foo -> % line should be 2 indented (works)
- foo(R);
- error:R ->
- foo(R),
- io:format(stdout,
- "ERROR reason ~p~n",
- R)
- after
- foo('after'),
- file:close(Xfile)
- end;
-indent_try_catch() ->
- try
- foo(bar)
- of
- X when true andalso
- kalle ->
- io:format(stdout, "Parsing file ~s, ",
- [St0#leex.xfile]),
- {ok,Line3,REAs,Actions,St3} =
- parse_rules(Xfile, Line2, Macs, St2);
- X % AD added clause
- when false andalso % when should be 2 indented
- bengt ->
- gurka();
- X when % AD added clause
- false andalso % line should be 2 indented
- not bengt ->
- gurka();
- X ->
- io:format(stdout, "Parsing file ~s, ",
- [St0#leex.xfile]),
- {ok,Line3,REAs,Actions,St3} =
- parse_rules(Xfile, Line2, Macs, St2)
- catch
- exit:{badarg,R} ->
- foo(R),
- io:format(stdout,
- "ERROR reason ~p~n",
- R);
- error:R ->
- foo(R),
- io:format(stdout,
- "ERROR reason ~p~n",
- R)
- after
- foo('after'),
- file:close(Xfile),
- bar(with_long_arg,
- with_second_arg)
- end;
-indent_try_catch() ->
- try foo()
- after
- foo(),
- bar(with_long_arg,
- with_second_arg)
- end.
-
-indent_catch() ->
- D = B +
- float(43.1),
-
- B = catch oskar(X),
-
- A = catch (baz +
- bax),
- catch foo(),
-
- C = catch B +
- float(43.1),
-
- case catch foo(X) of
- A ->
- B
- end,
-
- case
- catch foo(X)
- of
- A ->
- B
- end,
-
- case
- foo(X)
- of
- A ->
- catch B,
- X
- end,
-
- try sune of
- _ -> foo
- catch _:_ -> baf
- end,
-
- try
- sune
- of
- _ ->
- X = 5,
- (catch foo(X)),
- X + 10
- catch _:_ -> baf
- end,
-
- try
- (catch sune)
- of
- _ ->
- catch foo() %% BUGBUG can't handle catch inside try without parentheses
- catch _:_ ->
- baf
- end,
-
- try
- (catch exit())
- catch
- _ ->
- catch baf()
- end,
- ok.
-
-indent_binary() ->
- X = lists:foldr(fun(M) ->
- <<Ma/binary, " ">>
- end, [], A),
- A = <<X/binary, 0:8>>,
- B.
-
-
-indent_comprehensions() ->
- %% I don't have a good idea how we want to handle this
- %% but they are here to show how they are indented today.
- Result1 = [X ||
- #record{a=X} <- lists:seq(1, 10),
- true = (X rem 2)
- ],
- Result2 = [X || <<X:32,_:32>> <= <<0:512>>,
- true = (X rem 2)
- ],
-
- Binary1 = << <<X:8>> ||
- #record{a=X} <- lists:seq(1, 10),
- true = (X rem 2)
- >>,
-
- Binary2 = << <<X:8>> || <<X:32,_:32>> <= <<0:512>>,
- true = (X rem 2)
- >>,
- ok.
-
-%% This causes an error in earlier erlang-mode versions.
-foo() ->
- [#foo{
- foo = foo}].
-
-%% Record indentation
-some_function_with_a_very_long_name() ->
- #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
- field1=a,
- field2=b},
- case dummy_function_with_a_very_very_long_name(x) of
- #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
- field1=a,
- field2=b} ->
- ok;
- Var = #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
- field1=a,
- field2=b} ->
- Var#'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
- field1=a,
- field2=b};
- #xyz{
- a=1,
- b=2} ->
- ok
- end.
-
-another_function_with_a_very_very_long_name() ->
- #rec{
- field1=1,
- field2=1}.
-
-some_function_name_xyz(xyzzy, #some_record{
- field1=Field1,
- field2=Field2}) ->
- SomeVariable = f(#'Some-long-record-name'{
- field_a = 1,
- 'inter-xyz-parameters' =
- #'Some-other-very-long-record-name'{
- field2 = Field1,
- field2 = Field2}}),
- {ok, SomeVariable}.
-
-commas_first() ->
- {abc, [ {some_var, 1}
- , {some_other_var, 2}
- , {erlang_ftw, 9}
- , {erlang_cookie, 'cookie'}
- , {cmds,
- [ {one, "sudo ls"}
- , {one, "sudo ls"}
- , {two, "sudo ls"}
- , {three, "sudo ls"}
- , {four, "sudo ls"}
- , {three, "sudo ls"}
- ] }
- , {ssh_username, "yow"}
- , {cluster,
- [ {aaaa, [ {"10.198.55.12" , "" }
- , {"10.198.55.13" , "" }
- ] }
- , {bbbb, [ {"10.198.55.151", "" }
- , {"10.198.55.123", "" }
- , {"10.198.55.34" , "" }
- , {"10.198.55.85" , "" }
- , {"10.198.55.67" , "" }
- ] }
- , {cccc, [ {"10.198.55.68" , "" }
- , {"10.198.55.69" , "" }
- ] }
- ] }
- ]
- }.
-
-
-%% this used to result in a scan-sexp error
-[{
- }].
-
-%% this used to result in 2x the correct indentation within the function
-%% body, due to the function name being mistaken for a keyword
-catcher(N) ->
- try generate_exception(N) of
- Val -> {N, normal, Val}
- catch
- throw:X -> {N, caught, thrown, X};
- exit:X -> {N, caught, exited, X};
- error:X -> {N, caught, error, X}
- end.
diff --git a/lib/tools/emacs/test.erl.orig b/lib/tools/emacs/test.erl.orig
deleted file mode 100644
index c0cf1749b6..0000000000
--- a/lib/tools/emacs/test.erl.orig
+++ /dev/null
@@ -1,784 +0,0 @@
-%% -*- Mode: erlang; indent-tabs-mode: nil -*-
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-
-%%%-------------------------------------------------------------------
-%%% File : test.erl
-%%% Author : Dan Gudmundsson <[email protected]>
-%%% Description : Test emacs mode indention and font-locking
-%%% this file is intentionally not indented.
-%%% Copy the file and indent it and you should end up with test.erl.indented
-%%% Created : 6 Oct 2009 by Dan Gudmundsson <[email protected]>
-%%%-------------------------------------------------------------------
-
-%% Start off with syntax highlighting you have to verify this by looking here
-%% and see that the code looks alright
-
--module(test).
--compile(export_all).
-
-%% Used to cause an "Unbalanced parentheses" error.
-foo(M) ->
-M#{a :=<<"a">>
-,b:=1}.
-foo() ->
-#{a =><<"a">>
-,b=>1}.
-
-%% Module attributes should be highlighted
-
--export([t/1]).
--record(record1, {a,
- b,
- c
-}).
--record(record2, {
- a,
- b
- }).
-
--record(record3, {a = 8#42423 bor
- 8#4234,
- b = 8#5432
- bor 2#1010101
- c = 123 +
-234,
- d}).
-
--record(record4, {
- a = 8#42423 bor
- 8#4234,
- b = 8#5432
- bor 2#1010101
- c = 123 +
- 234,
- d}).
-
--record(record5, { a = 1 :: integer()
-, b = foobar :: atom()
-}).
-
--define(MACRO_1, macro).
--define(MACRO_2(_), macro).
-
--spec t(integer()) -> any().
-
--type ann() :: Var :: integer().
--type ann2() :: Var ::
- 'return'
- | 'return_white_spaces'
- | 'return_comments'
- | 'text' | ann().
--type paren() ::
- (ann2()).
--type t1() :: atom().
--type t2() :: [t1()].
--type t3(Atom) :: integer(Atom).
--type t4() :: t3(foobar).
--type t5() :: {t1(), t3(foo)}.
--type t6() :: 1 | 2 | 3 |
- 'foo' | 'bar'.
--type t7() :: [].
--type t71() :: [_].
--type t8() :: {any(),none(),pid(),port(),
- reference(),float()}.
--type t9() :: [1|2|3|foo|bar] |
- list(a | b | c) | t71().
--type t10() :: {1|2|3|foo|t9()} | {}.
--type t11() :: 1..2.
--type t13() :: maybe_improper_list(integer(), t11()).
--type t14() :: [erl_scan:foo() |
- %% Should be highlighted
- term() |
- bool() |
- byte() |
- char() |
- non_neg_integer() | nonempty_list() |
- pos_integer() |
- neg_integer() |
- number() |
- list() |
- nonempty_improper_list() | nonempty_maybe_improper_list() |
- maybe_improper_list() | string() | iolist() | byte() |
- module() |
- mfa() |
- node() |
- timeout() |
- no_return() |
- %% Should not be highlighted
- nonempty_() | nonlist() |
- erl_scan:bar(34, 92) | t13() | m:f(integer() | <<_:_*16>>)].
-
-
--type t15() :: {binary(),<<>>,<<_:34>>,<<_:_*42>>,
- <<_:3,_:_*14>>,<<>>} | [<<>>|<<_:34>>|<<_:16>>|
-<<_:3,_:_*1472>>|<<_:19,_:_*14>>| <<_:34>>|
-<<_:34>>|<<_:34>>|<<_:34>>].
--type t16() :: fun().
--type t17() :: fun((...) -> paren()).
--type t18() :: fun(() -> t17() | t16()).
--type t19() :: fun((t18()) -> t16()) |
- fun((nonempty_maybe_improper_list('integer', any())|
- 1|2|3|a|b|<<_:3,_:_*14>>|integer()) ->
-nonempty_maybe_improper_list('integer', any())|
-1|2|3|a|b|<<_:3,_:_*14>>|integer()).
--type t20() :: [t19(), ...].
--type t21() :: tuple().
--type t21(A) :: A.
--type t22() :: t21(integer()).
--type t23() :: #rec1{}.
--type t24() :: #rec2{a :: t23(), b :: [atom()]}.
--type t25() :: #rec3{f123 :: [t24() |
-1|2|3|4|a|b|c|d|
-nonempty_maybe_improper_list(integer, any())]}.
--type t26() :: #rec4{ a :: integer()
-, b :: any()
-}.
--type t27() :: { integer()
-, atom()
-}.
--type t99() ::
-{t2(),t4(),t5(),t6(),t7(),t8(),t10(),t14(),
-t15(),t20(),t21(), t22(),t25()}.
--spec t1(FooBar :: t99()) -> t99();
-(t2()) -> t2();
- (t4()) -> t4() when is_subtype(t4(), t24);
-(t23()) -> t23() when is_subtype(t23(), atom()),
- is_subtype(t23(), t14());
-(t24()) -> t24() when is_subtype(t24(), atom()),
- is_subtype(t24(), t14()),
- is_subtype(t24(), t4()).
-
--spec over(I :: integer()) -> R1 :: foo:typen();
- (A :: atom()) -> R2 :: foo:atomen();
- (T :: tuple()) -> R3 :: bar:typen().
-
--spec mod:t2() -> any().
-
--spec handle_cast(Cast :: {'exchange', node(), [[name(),...]]}
- | {'del_member', name(), pid()},
- #state{}) -> {'noreply', #state{}}.
-
--spec handle_cast(Cast ::
- {'exchange', node(), [[name(),...]]}
- | {'del_member', name(), pid()},
- #state{}) -> {'noreply', #state{}}.
-
--spec all(fun((T) -> boolean()), List :: [T]) ->
- boolean() when is_subtype(T, term()). % (*)
-
--spec get_closest_pid(term()) ->
- Return :: pid()
- | {'error', {'no_process', term()}
- | {'no_such_group', term()}}.
-
--spec add( X :: integer()
-, Y :: integer()
-) -> integer().
-
--opaque attributes_data() ::
-[{'column', column()} | {'line', info_line()} |
- {'text', string()}] | {line(),column()}.
--record(r,{
- f1 :: attributes_data(),
-f222 = foo:bar(34, #rec3{}, 234234234423,
- aassdsfsdfsdf, 2234242323) ::
-[t24() | 1|2|3|4|a|b|c|d|
- nonempty_maybe_improper_list(integer, any())],
-f333 :: [t24() | 1|2|3|4|a|b|c|d|
- nonempty_maybe_improper_list(integer, any())],
-f3 = x:y(),
-f4 = x:z() :: t99(),
-f17 :: 'undefined',
-f18 :: 1 | 2 | 'undefined',
-f19 = 3 :: integer()|undefined,
-f5 = 3 :: undefined|integer()}).
-
--record(state, {
- sequence_number = 1 :: integer()
- }).
-
-
-highlighting(X) % Function definitions should be highlighted
- when is_integer(X) -> % and so should `when' and `is_integer' be
- %% Highlighting
- %% Various characters (we keep an `atom' after to see that highlighting ends)
- $a,atom, % Characters should be marked
- "string",atom, % and strings
- 'asdasd',atom, % quote should be atoms??
- 'VaV',atom,
- 'aVa',atom,
- '\'atom',atom,
- 'atom\'',atom,
- 'at\'om',atom,
- '#1',atom,
-
- $", atom, % atom should be ok
- $', atom,
-
- "string$", atom, "string$", atom, % currently buggy I know...
- "string\$", atom, % workaround for bug above
-
- "char $in string", atom,
-
- 'atom$', atom, 'atom$', atom,
- 'atom\$', atom,
-
- 'char $in atom', atom,
-
- $[, ${, $\\, atom,
- ?MACRO_1,
- ?MACRO_2(foo),
-
- %% Numerical constants
- 16#DD, % AD Should not be highlighted
- 32#dd, % AD Should not be highlighted
- 32#ddAB, % AD Should not be highlighted
- 32#101, % AD Should not be highlighted
- 32#ABTR, % AD Should not be highlighted
-
- %% Variables
- Variables = lists:foo(),
- _Variables = lists:foo(), % AD
- AppSpec = Xyz/2,
- Module42 = Xyz(foo, bar),
- Module:foo(),
- _Module:foo(), % AD
- FooÅÅ = lists:reverse([tl,hd,tl,hd]), % AD Should highlight FooÅÅ
- _FooÅÅ = 42, % AD Should highlight _FooÅÅ
-
- %% Bifs
- erlang:registered(),
- registered(),
- hd(tl(tl(hd([a,b,c])))),
- erlang:anything(lists),
- %% Guards
- is_atom(foo), is_float(2.3), is_integer(32), is_number(4323.3),
- is_function(Fun), is_pid(self()),
- not_a_guard:is_list([]),
- %% Other Types
-
- atom, % not (currently) hightlighted
- 234234,
- 234.43,
-
- [list, are, not, higlighted],
- {nor, is, tuple},
- ok.
-
-%%%
-%%% Indentation
-%%%
-
-%%% Left
-
-%% Indented
-
-% Right
-
-
-indent_basics(X, Y, Z)
- when X > 42,
-Z < 13;
-Y =:= 4711 ->
- %% comments
- % right comments
- case lists:filter(fun(_, AlongName,
- B,
- C) ->
- true
- end,
- [a,v,b])
- of
- [] ->
- Y = 5 * 43,
- ok;
- [_|_] ->
- Y = 5 * 43,
- ok
- end,
- Y,
- %% List, tuples and binaries
- [a,
- b, c
- ],
- [ a,
- b, c
- ],
-
- [
- a,
- b
-],
- {a,
- b,c
- },
- { a,
- b,c
- },
-
- {
- a,
- b
- },
-
-<<1:8,
- 2:8
- >>,
- <<
- 1:8,
- 2:8
- >>,
- << 1:8,
- 2:8
- >>,
-
- (a,
- b,
- c
- ),
-
- ( a,
- b,
- c
- ),
-
-
- (
- a,
- b,
- c
- ),
-
- call(2#42423 bor
- #4234,
- 2#5432,
- other_arg),
- ok;
-indent_basics(Xlongname,
- #struct{a=Foo,
- b=Bar},
- [X|
- Y]) ->
- testing_next_clause,
- ok;
-indent_basics( % AD added clause
- X, % not sure how this should look
- Y,
- Z)
- when
- X < 42, Z > 13;
- Y =:= 4711 ->
- foo;
-indent_basics(X, Y, Z) when % AD added clause
- X < 42, Z > 13; % testing when indentation
- Y =:= 4711 ->
- foo;
-indent_basics(X, Y, Z) % AD added clause
- when % testing when indentation
- X < 42, Z > 13; % unsure about this one
- Y =:= 4711 ->
- foo.
-
-
-
-indent_nested() ->
- [
- {foo, 2, "string"},
- {bar, 3, "another string"}
- ].
-
-
-indent_icr(Z) -> % icr = if case receive
- %% If
- if Z >= 0 ->
- X = 43 div 4,
- foo(X);
- Z =< 10 ->
- X = 43 div 4,
- foo(X);
- Z == 5 orelse
- Z == 7 ->
- X = 43 div 4,
- foo(X);
- true ->
- if_works
- end,
- %% Case
- case {Z, foo, bar} of
- {Z,_,_} ->
- X = 43 div 4,
- foo(X);
- {Z,_,_} when
- Z =:= 42 -> % AD line should be indented as a when
- X = 43 div 4,
- foo(X);
- {Z,_,_}
- when Z < 10 -> % AD when should be indented
- X = 43 div 4,
- foo(X);
- {Z,_,_}
- when % AD when should be indented
- Z < 10 % and the guards should follow when
- andalso % unsure about how though
- true ->
- X = 43 div 4,
- foo(X)
- end,
- %% begin
- begin
- sune,
- X = 74234 + foo(8456) +
- 345 div 43,
- ok
- end,
-
-
- %% receive
- receive
- {Z,_,_} ->
- X = 43 div 4,
- foo(X);
- Z ->
- X = 43 div 4,
- foo(X)
- end,
- receive
- {Z,_,_} ->
- X = 43 div 4,
- foo(X);
- Z % AD added clause
- when Z =:= 1 -> % This line should be indented by 2
- X = 43 div 4,
- foo(X);
- Z when % AD added clause
- Z =:= 2 -> % This line should be indented by 2
- X = 43 div 4,
- foo(X);
- Z ->
- X = 43 div 4,
- foo(X)
- after infinity ->
- foo(X),
- asd(X),
- 5*43
- end,
- receive
- after 10 ->
- foo(X),
- asd(X),
- 5*43
- end,
- ok.
-
-indent_fun() ->
- %% Changed fun to one indention level
-Var = spawn(fun(X)
- when X == 2;
- X > 10 ->
- hello,
- case Hello() of
- true when is_atom(X) ->
- foo;
- false ->
- bar
- end;
- (Foo) when is_atom(Foo),
- is_integer(X) ->
- X = 6* 45,
- Y = true andalso
- kalle
- end),
-%% check EEP37 named funs
-Fn1 = fun Fact(N) when N > 0 ->
- F = Fact(N-1),
- N * F;
-Fact(0) ->
- 1
- end,
-%% check anonymous funs too
- Fn2 = fun(0) ->
-1;
- (N) ->
- N
- end,
- ok.
-
-indent_try_catch() ->
- try
- io:format(stdout, "Parsing file ~s, ",
- [St0#leex.xfile]),
- {ok,Line3,REAs,Actions,St3} =
- parse_rules(Xfile, Line2, Macs, St2)
- catch
- exit:{badarg,R} ->
- foo(R),
- io:format(stdout,
- "ERROR reason ~p~n",
- R);
- error:R % AD added clause
- when R =:= 42 -> % when should be indented
- foo(R);
- error:R % AD added clause
- when % when should be indented
- R =:= 42 -> % but unsure about this (maybe 2 more)
- foo(R);
- error:R when % AD added clause
- R =:= foo -> % line should be 2 indented (works)
- foo(R);
- error:R ->
- foo(R),
- io:format(stdout,
- "ERROR reason ~p~n",
- R)
- after
- foo('after'),
- file:close(Xfile)
- end;
-indent_try_catch() ->
- try
- foo(bar)
- of
- X when true andalso
- kalle ->
- io:format(stdout, "Parsing file ~s, ",
- [St0#leex.xfile]),
- {ok,Line3,REAs,Actions,St3} =
- parse_rules(Xfile, Line2, Macs, St2);
- X % AD added clause
- when false andalso % when should be 2 indented
- bengt ->
- gurka();
- X when % AD added clause
- false andalso % line should be 2 indented
- not bengt ->
- gurka();
- X ->
- io:format(stdout, "Parsing file ~s, ",
- [St0#leex.xfile]),
- {ok,Line3,REAs,Actions,St3} =
- parse_rules(Xfile, Line2, Macs, St2)
- catch
- exit:{badarg,R} ->
- foo(R),
- io:format(stdout,
- "ERROR reason ~p~n",
- R);
- error:R ->
- foo(R),
- io:format(stdout,
- "ERROR reason ~p~n",
- R)
- after
- foo('after'),
- file:close(Xfile),
- bar(with_long_arg,
- with_second_arg)
- end;
- indent_try_catch() ->
- try foo()
- after
- foo(),
- bar(with_long_arg,
- with_second_arg)
- end.
-
-indent_catch() ->
- D = B +
- float(43.1),
-
- B = catch oskar(X),
-
- A = catch (baz +
- bax),
- catch foo(),
-
- C = catch B +
- float(43.1),
-
- case catch foo(X) of
- A ->
- B
- end,
-
- case
- catch foo(X)
- of
- A ->
- B
- end,
-
- case
- foo(X)
- of
- A ->
- catch B,
- X
- end,
-
- try sune of
- _ -> foo
- catch _:_ -> baf
- end,
-
- try
-sune
- of
- _ ->
- X = 5,
- (catch foo(X)),
- X + 10
- catch _:_ -> baf
- end,
-
- try
- (catch sune)
- of
- _ ->
- catch foo() %% BUGBUG can't handle catch inside try without parentheses
- catch _:_ ->
- baf
- end,
-
- try
-(catch exit())
- catch
-_ ->
- catch baf()
- end,
- ok.
-
-indent_binary() ->
- X = lists:foldr(fun(M) ->
- <<Ma/binary, " ">>
- end, [], A),
- A = <<X/binary, 0:8>>,
- B.
-
-
-indent_comprehensions() ->
-%% I don't have a good idea how we want to handle this
-%% but they are here to show how they are indented today.
-Result1 = [X ||
- #record{a=X} <- lists:seq(1, 10),
- true = (X rem 2)
- ],
-Result2 = [X || <<X:32,_:32>> <= <<0:512>>,
- true = (X rem 2)
- ],
-
-Binary1 = << <<X:8>> ||
- #record{a=X} <- lists:seq(1, 10),
- true = (X rem 2)
- >>,
-
-Binary2 = << <<X:8>> || <<X:32,_:32>> <= <<0:512>>,
- true = (X rem 2)
- >>,
-ok.
-
-%% This causes an error in earlier erlang-mode versions.
-foo() ->
-[#foo{
-foo = foo}].
-
-%% Record indentation
-some_function_with_a_very_long_name() ->
- #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
- field1=a,
- field2=b},
- case dummy_function_with_a_very_very_long_name(x) of
- #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
- field1=a,
- field2=b} ->
- ok;
- Var = #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
- field1=a,
- field2=b} ->
- Var#'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
- field1=a,
- field2=b};
- #xyz{
- a=1,
- b=2} ->
- ok
- end.
-
-another_function_with_a_very_very_long_name() ->
- #rec{
- field1=1,
- field2=1}.
-
-some_function_name_xyz(xyzzy, #some_record{
- field1=Field1,
- field2=Field2}) ->
- SomeVariable = f(#'Some-long-record-name'{
- field_a = 1,
- 'inter-xyz-parameters' =
- #'Some-other-very-long-record-name'{
- field2 = Field1,
- field2 = Field2}}),
- {ok, SomeVariable}.
-
-commas_first() ->
- {abc, [ {some_var, 1}
- , {some_other_var, 2}
- , {erlang_ftw, 9}
- , {erlang_cookie, 'cookie'}
- , {cmds,
- [ {one, "sudo ls"}
- , {one, "sudo ls"}
- , {two, "sudo ls"}
- , {three, "sudo ls"}
- , {four, "sudo ls"}
- , {three, "sudo ls"}
- ] }
- , {ssh_username, "yow"}
- , {cluster,
- [ {aaaa, [ {"10.198.55.12" , "" }
- , {"10.198.55.13" , "" }
- ] }
- , {bbbb, [ {"10.198.55.151", "" }
- , {"10.198.55.123", "" }
- , {"10.198.55.34" , "" }
- , {"10.198.55.85" , "" }
- , {"10.198.55.67" , "" }
- ] }
- , {cccc, [ {"10.198.55.68" , "" }
- , {"10.198.55.69" , "" }
- ] }
- ] }
-]
-}.
-
-
-%% this used to result in a scan-sexp error
-[{
-}].
-
-%% this used to result in 2x the correct indentation within the function
-%% body, due to the function name being mistaken for a keyword
-catcher(N) ->
-try generate_exception(N) of
-Val -> {N, normal, Val}
-catch
-throw:X -> {N, caught, thrown, X};
-exit:X -> {N, caught, exited, X};
-error:X -> {N, caught, error, X}
-end.
diff --git a/lib/tools/priv/styles.css b/lib/tools/priv/styles.css
new file mode 100644
index 0000000000..e10e94e3ad
--- /dev/null
+++ b/lib/tools/priv/styles.css
@@ -0,0 +1,91 @@
+body {
+ font: 14px/1.6 "Helvetica Neue", Helvetica, Arial, sans-serif;
+ margin: 0;
+ padding: 0;
+ color: #000;
+ border-top: 2px solid #ddd;
+ background-color: #fff;
+
+ min-height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+
+h1 {
+ width: 100%;
+ border-bottom: 1px solid #eee;
+ margin-bottom: 0;
+ font-weight: 100;
+ font-size: 1.1em;
+ letter-spacing: 1px;
+}
+
+h1 code {
+ font-size: 0.96em;
+}
+
+code {
+ font: 12px monospace;
+}
+
+footer {
+ background: #eee;
+ width: 100%;
+ padding: 10px 0;
+ text-align: right;
+ border-top: 1px solid #ddd;
+ display: flex;
+ flex: 1;
+ order: 2;
+ justify-content: center;
+}
+
+table {
+ width: 100%;
+ margin-top: 10px;
+ border-collapse: collapse;
+ border: 1px solid #cbcbcb;
+ color: #000;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+}
+table thead {
+ display: none;
+}
+table td.line,
+table td.hits {
+ width: 20px;
+ background: #eaeaea;
+ text-align: center;
+ font-size: 11px;
+ padding: 0 10px;
+ color: #949494;
+}
+table td.hits {
+ width: 10px;
+ padding: 2px 5px;
+ color: rgba(0, 0, 0, 0.6);
+ background-color: #f0f0f0;
+}
+tr.miss td.line,
+tr.miss td.hits {
+ background-color: #ffdce0;
+ border-color: #fdaeb7;
+}
+tr.miss td {
+ background-color: #ffeef0;
+}
+tr.hit td.line,
+tr.hit td.hits {
+ background-color: #cdffd8;
+ border-color: #bef5cb;
+}
+tr.hit td {
+ background-color: #e6ffed;
+}
+td.source {
+ padding-left: 15px;
+ line-height: 15px;
+ white-space: pre;
+ font: 12px monospace;
+}
diff --git a/lib/tools/src/Makefile b/lib/tools/src/Makefile
index 032bd612db..cc5bee9a8f 100644
--- a/lib/tools/src/Makefile
+++ b/lib/tools/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2016. All Rights Reserved.
+# Copyright Ericsson AB 1996-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -72,6 +72,9 @@ APP_TARGET = $(EBIN)/$(APP_FILE)
APPUP_SRC = $(APPUP_FILE).src
APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
+PRIVDIR = ../priv
+CSS = $(PRIVDIR)/styles.css
+
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -110,5 +113,7 @@ release_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)/ebin"
$(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) \
"$(RELSYSDIR)/ebin"
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv"
+ $(INSTALL_DATA) $(CSS) "$(RELSYSDIR)/priv"
release_docs_spec:
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index 5517882ffa..d7269e3f27 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -144,6 +144,8 @@
end).
-define(SPAWN_DBG(Tag,Value),put(Tag,Value)).
+-define(STYLESHEET, "styles.css").
+-define(TOOLS_APP, tools).
-include_lib("stdlib/include/ms_transform.hrl").
@@ -2415,20 +2417,8 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) ->
case file:open(OutFile, [write,raw,delayed_write]) of
{ok, OutFd} ->
Enc = encoding(ErlFile),
- if HTML ->
- Header =
- ["<!DOCTYPE HTML PUBLIC "
- "\"-//W3C//DTD HTML 3.2 Final//EN\">\n"
- "<html>\n"
- "<head>\n"
- "<meta http-equiv=\"Content-Type\""
- " content=\"text/html; charset=",
- html_encoding(Enc),"\"/>\n"
- "<title>",OutFile,"</title>\n"
- "</head>"
- "<body style='background-color: white;"
- " color: black'>\n"
- "<pre>\n"],
+ if HTML ->
+ Header = create_header(OutFile, Enc),
H1Bin = unicode:characters_to_binary(Header,Enc,Enc),
ok = file:write(OutFd,H1Bin);
true -> ok
@@ -2439,28 +2429,35 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) ->
Timestamp =
io_lib:format("~p-~s-~s at ~s:~s:~s",
[Y,
- string:right(integer_to_list(Mo), 2, $0),
- string:right(integer_to_list(D), 2, $0),
- string:right(integer_to_list(H), 2, $0),
- string:right(integer_to_list(Mi), 2, $0),
- string:right(integer_to_list(S), 2, $0)]),
-
- H2Bin = unicode:characters_to_binary(
- ["File generated from ",ErlFile," by COVER ",
- Timestamp,"\n\n"
- "**************************************"
- "**************************************"
- "\n\n"],
- Enc, Enc),
- ok = file:write(OutFd, H2Bin),
+ string:pad(integer_to_list(Mo), 2, leading, $0),
+ string:pad(integer_to_list(D), 2, leading, $0),
+ string:pad(integer_to_list(H), 2, leading, $0),
+ string:pad(integer_to_list(Mi), 2, leading, $0),
+ string:pad(integer_to_list(S), 2, leading, $0)]),
+
+ OutFileInfo =
+ if HTML ->
+ create_footer(ErlFile, Timestamp);
+ true ->
+ ["File generated from ",ErlFile," by COVER ",
+ Timestamp, "\n\n",
+ "**************************************"
+ "**************************************"
+ "\n\n"]
+ end,
+
+ H2Bin = unicode:characters_to_binary(OutFileInfo,Enc,Enc),
+ ok = file:write(OutFd, H2Bin),
Pattern = {#bump{module=Module,line='$1',_='_'},'$2'},
MS = [{Pattern,[{is_integer,'$1'},{'>','$1',0}],[{{'$1','$2'}}]}],
- CovLines = lists:keysort(1,ets:select(?COLLECTION_TABLE, MS)),
+ CovLines0 =
+ lists:keysort(1, ets:select(?COLLECTION_TABLE, MS)),
+ CovLines = merge_dup_lines(CovLines0),
print_lines(Module, CovLines, InFd, OutFd, 1, HTML),
if HTML ->
- ok = file:write(OutFd, "</pre>\n</body>\n</html>\n");
+ ok = file:write(OutFd, close_html());
true -> ok
end,
@@ -2477,28 +2474,31 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) ->
{error, {file, ErlFile, Reason}}
end.
+merge_dup_lines(CovLines) ->
+ merge_dup_lines(CovLines, []).
+merge_dup_lines([{L, N}|T], [{L, NAcc}|TAcc]) ->
+ merge_dup_lines(T, [{L, NAcc + N}|TAcc]);
+merge_dup_lines([{L, N}|T], Acc) ->
+ merge_dup_lines(T, [{L, N}|Acc]);
+merge_dup_lines([], Acc) ->
+ lists:reverse(Acc).
print_lines(Module, CovLines, InFd, OutFd, L, HTML) ->
case file:read_line(InFd) of
eof ->
ignore;
- {ok,"%"++_=Line} -> %Comment line - not executed.
- ok = file:write(OutFd, [tab(),escape_lt_and_gt(Line, HTML)]),
- print_lines(Module, CovLines, InFd, OutFd, L+1, HTML);
{ok,RawLine} ->
Line = escape_lt_and_gt(RawLine,HTML),
case CovLines of
[{L,N}|CovLines1] ->
- %% N = lists:foldl(fun([Ni], Nacc) -> Nacc+Ni end, 0, Ns),
if N=:=0, HTML=:=true ->
- LineNoNL = Line -- "\n",
- Str = " 0",
- %%Str = string:right("0", 6, 32),
- RedLine = ["<font color=red>",Str,fill1(),
- LineNoNL,"</font>\n"],
- ok = file:write(OutFd, RedLine);
+ MissedLine = table_row("miss", Line, L, N),
+ ok = file:write(OutFd, MissedLine);
+ HTML=:=true ->
+ HitLine = table_row("hit", Line, L, N),
+ ok = file:write(OutFd, HitLine);
N < 1000000 ->
- Str = string:right(integer_to_list(N), 6, 32),
+ Str = string:pad(integer_to_list(N), 6, leading, $\s),
ok = file:write(OutFd, [Str,fill1(),Line]);
N < 10000000 ->
Str = integer_to_list(N),
@@ -2508,8 +2508,12 @@ print_lines(Module, CovLines, InFd, OutFd, L, HTML) ->
ok = file:write(OutFd, [Str,fill3(),Line])
end,
print_lines(Module, CovLines1, InFd, OutFd, L+1, HTML);
- _ ->
- ok = file:write(OutFd, [tab(),Line]),
+ _ -> %Including comment lines
+ NonCoveredContent =
+ if HTML -> table_row(Line, L);
+ true -> [tab(),Line]
+ end,
+ ok = file:write(OutFd, NonCoveredContent),
print_lines(Module, CovLines, InFd, OutFd, L+1, HTML)
end
end.
@@ -2519,6 +2523,59 @@ fill1() -> "..| ".
fill2() -> ".| ".
fill3() -> "| ".
+%% HTML sections
+create_header(OutFile, Enc) ->
+ ["<!doctype html>\n"
+ "<html>\n"
+ "<head>\n"
+ "<meta charset=\"",html_encoding(Enc),"\">\n"
+ "<title>",OutFile,"</title>\n"
+ "<style>"] ++
+ read_stylesheet() ++
+ ["</style>\n",
+ "</head>\n"
+ "<body>\n"
+ "<h1><code>",OutFile,"</code></h1>\n"].
+
+create_footer(ErlFile, Timestamp) ->
+ ["<footer><p>File generated from <code>",ErlFile,
+ "</code> by <a href=\"http://erlang.org/doc/man/cover.html\">cover</a> at ",
+ Timestamp,"</p></footer>\n<table>\n<tbody>\n"].
+
+close_html() ->
+ ["</tbody>\n",
+ "<thead>\n",
+ "<tr>\n",
+ "<th>Line</th>\n",
+ "<th>Hits</th>\n",
+ "<th>Source</th>\n",
+ "</tr>\n",
+ "</thead>\n",
+ "</table>\n",
+ "</body>\n"
+ "</html>\n"].
+
+table_row(CssClass, Line, L, N) ->
+ ["<tr class=\"",CssClass,"\">\n", table_data(Line, L, N)].
+table_row(Line, L) ->
+ ["<tr>\n", table_data(Line, L, "")].
+
+table_data(Line, L, N) ->
+ LineNoNL = Line -- "\n",
+ ["<td class=\"line\" id=\"L",integer_to_list(L),"\">",
+ integer_to_list(L),
+ "</td>\n",
+ "<td class=\"hits\">",maybe_integer_to_list(N),"</td>\n",
+ "<td class=\"source\"><code>",LineNoNL,"</code></td>\n</tr>\n"].
+
+maybe_integer_to_list(N) when is_integer(N) -> integer_to_list(N);
+maybe_integer_to_list(_) -> "".
+
+read_stylesheet() ->
+ PrivDir = code:priv_dir(?TOOLS_APP),
+ {ok, Css} = file:read_file(filename:join(PrivDir, ?STYLESHEET)),
+ [Css].
+
%%%--Export--------------------------------------------------------------
do_export(Module, OutFile, From, State) ->
case file:open(OutFile,[write,binary,raw,delayed_write]) of
diff --git a/lib/tools/src/eprof.erl b/lib/tools/src/eprof.erl
index 3ae899a078..535ddbcd04 100644
--- a/lib/tools/src/eprof.erl
+++ b/lib/tools/src/eprof.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -246,7 +246,7 @@ handle_call(profile_stop, _From, #state{ profiling = true } = S) ->
%% logfile
handle_call({logfile, File}, _From, #state{ fd = OldFd } = S) ->
- case file:open(File, [write]) of
+ case file:open(File, [write, {encoding, utf8}]) of
{ok, Fd} ->
case OldFd of
undefined -> ok;
@@ -478,11 +478,11 @@ string_bp_mfa([{Mfa, {Count, Time}}|Mfas], Tus, {MfaW, CountW, PercW, TimeW, TpC
Stpc = s("~.2f", [divide(Time,Count)]),
string_bp_mfa(Mfas, Tus, {
- erlang:max(MfaW, length(Smfa)),
- erlang:max(CountW,length(Scount)),
- erlang:max(PercW, length(Sperc)),
- erlang:max(TimeW, length(Stime)),
- erlang:max(TpCW, length(Stpc))
+ erlang:max(MfaW, string:length(Smfa)),
+ erlang:max(CountW,string:length(Scount)),
+ erlang:max(PercW, string:length(Sperc)),
+ erlang:max(TimeW, string:length(Stime)),
+ erlang:max(TpCW, string:length(Stpc))
}, [[Smfa, Scount, Sperc, Stime, Stpc] | Strings]).
print_bp_mfa(Mfas, {Tn, Tus}, Fd, Opts) ->
@@ -491,11 +491,11 @@ print_bp_mfa(Mfas, {Tn, Tus}, Fd, Opts) ->
TnStr = s(Tn),
TusStr = s(Tus),
TuspcStr = s("~.2f", [divide(Tus,Tn)]),
- Ws = {erlang:max(length("FUNCTION"), MfaW),
- lists:max([length("CALLS"), CountW, length(TnStr)]),
- erlang:max(length(" %"), PercW),
- lists:max([length("TIME"), TimeW, length(TusStr)]),
- lists:max([length("uS / CALLS"), TpCW, length(TuspcStr)])},
+ Ws = {erlang:max(string:length("FUNCTION"), MfaW),
+ lists:max([string:length("CALLS"), CountW, string:length(TnStr)]),
+ erlang:max(string:length(" %"), PercW),
+ lists:max([string:length("TIME"), TimeW, string:length(TusStr)]),
+ lists:max([string:length("uS / CALLS"), TpCW, string:length(TuspcStr)])},
format(Fd, Ws, ["FUNCTION", "CALLS", " %", "TIME", "uS / CALLS"]),
format(Fd, Ws, ["--------", "-----", "-------", "----", "----------"]),
lists:foreach(fun (String) -> format(Fd, Ws, String) end, Strs),
@@ -503,13 +503,13 @@ print_bp_mfa(Mfas, {Tn, Tus}, Fd, Opts) ->
format(Fd, Ws, ["Total:", TnStr, "100.00%", TusStr, TuspcStr]),
ok.
-s({M,F,A}) -> s("~w:~w/~w",[M,F,A]);
-s(Term) -> s("~p", [Term]).
+s({M,F,A}) -> s("~w:~tw/~w",[M,F,A]);
+s(Term) -> s("~tp", [Term]).
s(Format, Terms) -> lists:flatten(io_lib:format(Format, Terms)).
format(Fd, {MfaW, CountW, PercW, TimeW, TpCW}, Strings) ->
- format(Fd, s("~~.~ps ~~~ps ~~~ps ~~~ps [~~~ps]~~n", [MfaW, CountW, PercW, TimeW, TpCW]), Strings);
+ format(Fd, s("~~.~wts ~~~ws ~~~ws ~~~ws [~~~ws]~~n", [MfaW, CountW, PercW, TimeW, TpCW]), Strings);
format(undefined, Format, Strings) ->
io:format(Format, Strings),
ok;
diff --git a/lib/tools/src/fprof.erl b/lib/tools/src/fprof.erl
index d1a4624419..36d4828861 100644
--- a/lib/tools/src/fprof.erl
+++ b/lib/tools/src/fprof.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1136,7 +1136,7 @@ ensure_open(Pid, _Options) when is_pid(Pid) ->
ensure_open([], _Options) ->
{already_open, undefined};
ensure_open(Filename, Options) when is_atom(Filename); is_list(Filename) ->
- file:open(Filename, Options).
+ file:open(Filename, [{encoding, utf8} | Options]).
%%%---------------------------------
%%% Fairly generic utility functions
@@ -1242,8 +1242,7 @@ spawn_3step(Spawn, FunPrelude, FunAck, FunBody)
catch Child ! {Parent, Ref, Go},
Result
catch
- Class:Reason ->
- Stacktrace = erlang:get_stacktrace(),
+ Class:Reason:Stacktrace ->
catch exit(Child, kill),
erlang:raise(Class, Reason, Stacktrace)
end;
@@ -1475,7 +1474,7 @@ info_suspect_call(GroupLeader, GroupLeader, _, _) ->
ok;
info_suspect_call(GroupLeader, _, Func, Pid) ->
io:format(GroupLeader,
- "~nWarning: ~p called in ~p - trace may become corrupt!~n",
+ "~nWarning: ~tp called in ~p - trace may become corrupt!~n",
parsify([Func, Pid])).
info(GroupLeader, GroupLeader, _, _) ->
@@ -1498,13 +1497,13 @@ dump_stack(Dump, Stack, Term) ->
{N, length(hd(Stack))}
end
end,
- io:format(Dump, "~s~p.~n", [lists:duplicate(Depth, " "), parsify(Term)]),
+ io:format(Dump, "~s~tp.~n", [lists:duplicate(Depth, " "), parsify(Term)]),
true.
dump(undefined, _) ->
false;
dump(Dump, Term) ->
- io:format(Dump, "~p.~n", [parsify(Term)]),
+ io:format(Dump, "~tp.~n", [parsify(Term)]),
true.
@@ -2603,17 +2602,17 @@ println({Io, [W1, W2, W3, W4]}, Head,
println({Io, _}, Head,
[],
Tail, Comment) ->
- io:format(Io, "~s~s~s~n",
+ io:format(Io, "~s~ts~ts~n",
[pad(Head, $ , 3), Tail, Comment]);
println({Io, _}, Head,
{Tag, Term},
Tail, Comment) ->
- io:format(Io, "~s~p, ~p~s~s~n",
+ io:format(Io, "~s~tp, ~tp~ts~ts~n",
[pad(Head, $ , 3), parsify(Tag), parsify(Term), Tail, Comment]);
println({Io, _}, Head,
Term,
Tail, Comment) ->
- io:format(Io, "~s~p~s~s~n",
+ io:format(Io, "~s~tp~ts~ts~n",
[pad(Head, $ , 3), parsify(Term), Tail, Comment]).
@@ -2636,22 +2635,32 @@ funcstat_pd(Pid, Func1, Func0, Clocks) ->
#funcstat{callers_sum = CallersSum,
callers = Callers} = FuncstatCallers ->
FuncstatCallers#funcstat{
- callers_sum = clocks_sum(CallersSum, Clocks, Func0),
- callers = [Clocks#clocks{id = Func1} | Callers]}
- end),
+ callers_sum = clocks_sum(CallersSum, Clocks, Func0),
+ callers = insert_call(Clocks, Func1, Callers)}
+ end),
put({Pid, Func1},
case get({Pid, Func1}) of
undefined ->
- #funcstat{callers_sum = #clocks{id = Func1},
+ #funcstat{callers_sum = #clocks{id = Func1},
called_sum = Clocks#clocks{id = Func1},
called = [Clocks#clocks{id = Func0}]};
#funcstat{called_sum = CalledSum,
called = Called} = FuncstatCalled ->
FuncstatCalled#funcstat{
called_sum = clocks_sum(CalledSum, Clocks, Func1),
- called = [Clocks#clocks{id = Func0} | Called]}
+ called = insert_call(Clocks, Func0, Called)}
end).
+insert_call(Clocks, Func, ClocksList) ->
+ insert_call(Clocks, Func, ClocksList, []).
+
+insert_call(Clocks, Func, [#clocks{id = Func} = C | T], Acc) ->
+ [clocks_sum(C, Clocks, Func) | T ++ Acc];
+insert_call(Clocks, Func, [H | T], Acc) ->
+ insert_call(Clocks, Func, T, [H | Acc]);
+insert_call(Clocks, Func, [], Acc) ->
+ [Clocks#clocks{id = Func} | Acc].
+
%% Sort a list of funcstat records,
@@ -2710,7 +2719,7 @@ postsort_r([[_|C] | L], R) ->
flat_format(F, Trailer) when is_float(F) ->
lists:flatten([io_lib:format("~.3f", [F]), Trailer]);
flat_format(W, Trailer) ->
- lists:flatten([io_lib:format("~p", [W]), Trailer]).
+ lists:flatten([io_lib:format("~tp", [W]), Trailer]).
%% Format, flatten, and pad.
flat_format(Term, Trailer, Width) ->
diff --git a/lib/tools/src/instrument.erl b/lib/tools/src/instrument.erl
index 055f4a7afb..0203fefe13 100644
--- a/lib/tools/src/instrument.erl
+++ b/lib/tools/src/instrument.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,410 +19,140 @@
%%
-module(instrument).
--export([holes/1, mem_limits/1, memory_data/0, read_memory_data/1,
- sort/1, store_memory_data/1, sum_blocks/1,
- descr/1, type_descr/2, allocator_descr/2, class_descr/2,
- type_no_range/1, block_header_size/1, store_memory_status/1,
- read_memory_status/1, memory_status/1]).
-
-
--define(OLD_INFO_SIZE, 32). %% (sizeof(mem_link) in pre R9C utils.c)
-
--define(IHMARKER(H), element(1, H)).
--define(VSN(H), element(2, H)).
--define(INFO_SIZE(H), element(3, H)).
--define(TYPEMAP(H), element(4, H)).
-
--define(IHDR(H), is_tuple(H), ?IHMARKER(H) =:= instr_hdr).
--define(IHDRVSN(H, V), ?IHDR(H), ?VSN(H) =:= V).
-
-memory_data() ->
- case catch erlang:system_info(allocated) of
- {'EXIT',{Error,_}} ->
- erlang:error(Error, []);
- {'EXIT',Error} ->
- erlang:error(Error, []);
- Res ->
- Res
+-export([allocations/0, allocations/1,
+ carriers/0, carriers/1]).
+
+-type block_histogram() :: tuple().
+
+-type allocation_summary() ::
+ {HistogramStart :: non_neg_integer(),
+ UnscannedSize :: non_neg_integer(),
+ Allocations :: #{ Origin :: atom() =>
+ #{ Type :: atom() => block_histogram() }}}.
+
+-spec allocations() -> {ok, Result} | {error, Reason} when
+ Result :: allocation_summary(),
+ Reason :: not_enabled.
+allocations() ->
+ allocations(#{}).
+
+-spec allocations(Options) -> {ok, Result} | {error, Reason} when
+ Result :: allocation_summary(),
+ Reason :: not_enabled,
+ Options :: #{ scheduler_ids => list(non_neg_integer()),
+ allocator_types => list(atom()),
+ histogram_start => pos_integer(),
+ histogram_width => pos_integer() }.
+allocations(Options) ->
+ Ref = make_ref(),
+
+ Defaults = #{ scheduler_ids => lists:seq(0, erlang:system_info(schedulers)),
+ allocator_types => erlang:system_info(alloc_util_allocators),
+ histogram_start => 128,
+ histogram_width => 18 },
+
+ {HistStart, MsgCount} =
+ dispatch_gather(maps:merge(Defaults, Options), Ref,
+ fun erts_internal:gather_alloc_histograms/1),
+
+ alloc_hist_receive(HistStart, MsgCount, Ref).
+
+alloc_hist_receive(_HistStart, 0, _Ref) ->
+ {error, not_enabled};
+alloc_hist_receive(HistStart, MsgCount, Ref) when MsgCount > 0 ->
+ {Unscanned, Histograms} = alloc_hist_receive_1(MsgCount, Ref, 0, #{}),
+ {ok, {HistStart, Unscanned, Histograms}}.
+
+alloc_hist_receive_1(0, _Ref, Unscanned, Result) ->
+ {Unscanned, Result};
+alloc_hist_receive_1(MsgCount, Ref, Unscanned0, Result0) ->
+ receive
+ {Ref, Unscanned, Tags} ->
+ Result = lists:foldl(fun alloc_hist_fold_result/2, Result0, Tags),
+ alloc_hist_receive_1(MsgCount - 1, Ref, Unscanned0 + Unscanned, Result)
end.
-store_memory_data(File) ->
- case catch erlang:system_info({allocated, File}) of
- {'EXIT',{Error,_}} ->
- erlang:error(Error, [File]);
- {'EXIT',Error} ->
- erlang:error(Error, [File]);
- Res ->
- Res
+alloc_hist_fold_result({Id, Type, BlockHist}, Result0) ->
+ IdAllocs0 = maps:get(Id, Result0, #{}),
+ MergedHists = case maps:find(Type, IdAllocs0) of
+ {ok, PrevHist} ->
+ alloc_hist_merge_hist(tuple_size(BlockHist),
+ BlockHist,
+ PrevHist);
+ error ->
+ BlockHist
+ end,
+ IdAllocs = IdAllocs0#{ Type => MergedHists },
+ Result0#{ Id => IdAllocs }.
+
+alloc_hist_merge_hist(0, A, _B) ->
+ A;
+alloc_hist_merge_hist(Index, A, B) ->
+ Merged = setelement(Index, A, element(Index, A) + element(Index, B)),
+ alloc_hist_merge_hist(Index - 1, Merged, B).
+
+-type carrier_info_list() ::
+ {HistogramStart :: non_neg_integer(),
+ Carriers :: [{AllocatorType :: atom(),
+ TotalSize :: non_neg_integer(),
+ UnscannedSize :: non_neg_integer(),
+ AllocatedSize :: non_neg_integer(),
+ AllocatedCount :: non_neg_integer(),
+ InPool :: boolean(),
+ FreeBlocks :: block_histogram()}]}.
+
+-spec carriers() -> {ok, Result} | {error, Reason} when
+ Result :: carrier_info_list(),
+ Reason :: not_enabled.
+carriers() ->
+ carriers(#{}).
+
+-spec carriers(Options) -> {ok, Result} | {error, Reason} when
+ Result :: carrier_info_list(),
+ Reason :: not_enabled,
+ Options :: #{ scheduler_ids => list(non_neg_integer()),
+ allocator_types => list(atom()),
+ histogram_start => pos_integer(),
+ histogram_width => pos_integer() }.
+carriers(Options) ->
+ Ref = make_ref(),
+
+ Defaults = #{ scheduler_ids => lists:seq(0, erlang:system_info(schedulers)),
+ allocator_types => erlang:system_info(alloc_util_allocators),
+ histogram_start => 512,
+ histogram_width => 14 },
+
+ {HistStart, MsgCount} =
+ dispatch_gather(maps:merge(Defaults, Options), Ref,
+ fun erts_internal:gather_carrier_info/1),
+
+ carrier_info_receive(HistStart, MsgCount, Ref).
+
+carrier_info_receive(_HistStart, 0, _Ref) ->
+ {error, not_enabled};
+carrier_info_receive(HistStart, MsgCount, Ref) ->
+ {ok, {HistStart, carrier_info_receive_1(MsgCount, Ref, [])}}.
+
+carrier_info_receive_1(0, _Ref, Result) ->
+ lists:flatten(Result);
+carrier_info_receive_1(MsgCount, Ref, Result0) ->
+ receive
+ {Ref, Carriers} ->
+ carrier_info_receive_1(MsgCount - 1, Ref, [Carriers, Result0])
end.
-memory_status(Type) when is_atom(Type) ->
- case catch erlang:system_info({allocated, status, Type}) of
- {'EXIT',{Error,_}} ->
- erlang:error(Error, [Type]);
- {'EXIT',Error} ->
- erlang:error(Error, [Type]);
- Res ->
- Res
- end;
-memory_status(Type) ->
- erlang:error(badarg, [Type]).
-
-store_memory_status(File) when is_list(File) ->
- case catch erlang:system_info({allocated, status, File}) of
- {'EXIT',{Error,_}} ->
- erlang:error(Error, [File]);
- {'EXIT',Error} ->
- erlang:error(Error, [File]);
- Res ->
- Res
- end;
-store_memory_status(File) ->
- erlang:error(badarg, [File]).
-
-read_memory_data(File) when is_list(File) ->
- case file:consult(File) of
- {ok, [Hdr|MD]} when ?IHDR(Hdr) ->
- {Hdr, MD};
- {ok, [{T,A,S,undefined}|_] = MD} when is_integer(T),
- is_integer(A),
- is_integer(S) ->
- {{instr_hdr, 1, ?OLD_INFO_SIZE}, MD};
- {ok, [{T,A,S,{X,Y,Z}}|_] = MD} when is_integer(T),
- is_integer(A),
- is_integer(S),
- is_integer(X),
- is_integer(Y),
- is_integer(Z) ->
- {{instr_hdr, 1, ?OLD_INFO_SIZE}, MD};
- {ok, _} ->
- {error, eio};
- Error ->
- Error
- end;
-read_memory_data(File) ->
- erlang:error(badarg, [File]).
-
-read_memory_status(File) when is_list(File) ->
- case file:consult(File) of
- {ok, [{instr_vsn, _}|Stat]} ->
- Stat;
- {ok, _} ->
- {error, eio};
- Error ->
- Error
- end;
-read_memory_status(File) ->
- erlang:error(badarg, [File]).
-
-holes({Hdr, MD}) when ?IHDR(Hdr) ->
- check_holes(?INFO_SIZE(Hdr), MD).
-
-check_holes(_ISz, []) ->
- ok;
-check_holes(ISz, [E | L]) ->
- check_holes(ISz, E, L).
-
-check_holes(_ISz, _E1, []) ->
- io:format("~n");
-check_holes(ISz, E1, [E2 | Rest]) ->
- check_hole(ISz, E1, E2),
- check_holes(ISz, E2, Rest).
-
-check_hole(ISz, {_,P1,S1,_}, {_,P2,_,_}) ->
- End = P1+S1,
- Hole = P2 - (End + ISz),
- if
- Hole =< 7 ->
- ok;
- true ->
- io:format(" ~p", [Hole])
- end.
-
-sum_blocks({Hdr, L}) when ?IHDR(Hdr) ->
- lists:foldl(fun({_,_,S,_}, Sum) -> S+Sum end,
- 0,
- L).
-
-mem_limits({Hdr, L}) when ?IHDR(Hdr) ->
- {_, P1, _, _} = hd(L),
- {_, P2, S2, _} = lists:last(L),
- {P1, P2+S2}.
-
-sort({Hdr, MD}) when ?IHDR(Hdr) ->
- {Hdr, lists:keysort(2, MD)}.
-
-descr({Hdr, MD} = ID) when ?IHDR(Hdr) ->
- {Hdr, lists:map(fun ({TN, Addr, Sz, {0, N, S}}) ->
- {type_descr(ID, TN),
- Addr,
- Sz,
- list_to_pid("<0."
- ++ integer_to_list(N)
- ++ "."
- ++ integer_to_list(S)
- ++ ">")};
- ({TN, Addr, Sz, undefined}) ->
- {type_descr(ID, TN),
- Addr,
- Sz,
- undefined}
- end,
- MD)}.
-
-block_header_size({Hdr, _}) when ?IHDR(Hdr) ->
- ?INFO_SIZE(Hdr).
-
-type_descr({Hdr, _}, TypeNo) when ?IHDRVSN(Hdr, 2),
- is_integer(TypeNo) ->
- case catch element(1, element(TypeNo, ?TYPEMAP(Hdr))) of
- {'EXIT', _} -> invalid_type;
- Type -> Type
- end;
-type_descr({Hdr, _}, TypeNo) when ?IHDRVSN(Hdr, 1),
- is_integer(TypeNo) ->
- type_string(TypeNo).
-
-
-allocator_descr({Hdr, _}, TypeNo) when ?IHDRVSN(Hdr, 2), is_integer(TypeNo) ->
- case catch element(2, element(TypeNo, ?TYPEMAP(Hdr))) of
- {'EXIT', _} -> invalid_type;
- Type -> Type
- end;
-allocator_descr({Hdr, _}, TypeNo) when ?IHDRVSN(Hdr, 1), is_integer(TypeNo) ->
- "unknown".
-
-class_descr({Hdr, _}, TypeNo) when ?IHDRVSN(Hdr, 2), is_integer(TypeNo) ->
- case catch element(3, element(TypeNo, ?TYPEMAP(Hdr))) of
- {'EXIT', _} -> invalid_type;
- Type -> Type
- end;
-class_descr({Hdr, _}, TypeNo) when ?IHDRVSN(Hdr, 1), is_integer(TypeNo) ->
- "unknown".
-
-type_no_range({Hdr, _}) when ?IHDRVSN(Hdr, 2) ->
- {1, tuple_size(?TYPEMAP(Hdr))};
-type_no_range({Hdr, _}) when ?IHDRVSN(Hdr, 1) ->
- {-1, 1000}.
-
-type_string(-1) ->
- "unknown";
-type_string(1) ->
- "atom text";
-type_string(11) ->
- "atom desc";
-type_string(2) ->
- "bignum (big_to_list)";
-type_string(31) ->
- "fixalloc";
-type_string(32) ->
- "unknown fixalloc block";
-type_string(33) ->
- "message buffer";
-type_string(34) ->
- "message link";
-type_string(4) ->
- "estack";
-type_string(40) ->
- "db table vec";
-type_string(41) ->
- "db tree select buffer";
-type_string(43) ->
- "db hash select buffer";
-type_string(44) ->
- "db hash select list";
-type_string(45) ->
- "db match prog stack";
-type_string(46) ->
- "db match prog heap data";
-type_string(47) ->
- "db temp buffer";
-type_string(48) ->
- "db error";
-type_string(49) ->
- "db error info";
-type_string(50) ->
- "db trans tab";
-type_string(51) ->
- "db segment";
-type_string(52) ->
- "db term";
-type_string(53) ->
- "db add_counter";
-type_string(54) ->
- "db segment table";
-type_string(55) ->
- "db table (fix)";
-type_string(56) ->
- "db bindings";
-type_string(57) ->
- "db counter";
-type_string(58) ->
- "db trace vec";
-type_string(59) ->
- "db fixed deletion";
-type_string(60) ->
- "binary (external.c)";
-type_string(61) ->
- "binary";
-type_string(62) ->
- "procbin (fix)";
-type_string(70) ->
- "driver alloc (io.c)";
-type_string(71) ->
- "binary (io.c)";
-type_string(72) ->
- "binary vec (io.c)";
-type_string(73) ->
- "binary vec 2 (io.c)";
-type_string(74) ->
- "io vec (io.c)";
-type_string(75) ->
- "io vec 2 (io.c)";
-type_string(76) ->
- "temp io buffer (io.c)";
-type_string(77) ->
- "temp io buffer 2 (io.c)";
-type_string(78) ->
- "line buffer (io.c)";
-type_string(8) ->
- "heap";
-type_string(801) ->
- "heap (1)";
-type_string(802) ->
- "heap (2)";
-type_string(803) ->
- "heap (3)";
-type_string(804) ->
- "heap (4)";
-type_string(805) ->
- "heap (5)";
-type_string(821) ->
- "heap fragment (1)";
-type_string(822) ->
- "heap fragment (2)";
-type_string(830) ->
- "sequential store buffer (for vectors)";
-type_string(91) ->
- "process table";
-type_string(92) ->
- "process desc";
-type_string(110) ->
- "hash buckets";
-type_string(111) ->
- "hash table";
-type_string(120) ->
- "index init";
-type_string(121) ->
- "index table";
-type_string(130) ->
- "temp buffer";
-type_string(140) ->
- "timer wheel";
-type_string(150) ->
- "distribution cache";
-type_string(151) ->
- "dmem";
-type_string(152) ->
- "distribution table";
-type_string(153) ->
- "distribution table buckets";
-type_string(154) ->
- "distribution table entry";
-type_string(155) ->
- "node table";
-type_string(156) ->
- "node table buckets";
-type_string(157) ->
- "node table entry";
-type_string(160) ->
- "port table";
-type_string(161) ->
- "driver entry";
-type_string(162) ->
- "port setup";
-type_string(163) ->
- "port wait";
-type_string(170) ->
- "module";
-type_string(171) ->
- "fundef";
-type_string(180) ->
- "file table";
-type_string(181) ->
- "driver table";
-type_string(182) ->
- "poll struct";
-type_string(190) ->
- "inet driver";
-type_string(200) ->
- "efile driver";
-type_string(210) ->
- "gc root set";
-type_string(220) ->
- "breakpoint data";
-type_string(230) ->
- "async queue";
-type_string(231) ->
- "async (exit)";
-type_string(232) ->
- "async (driver)";
-type_string(240) ->
- "bits buffer";
-type_string(241) ->
- "bits temp buffer";
-type_string(250) ->
- "modules (loader)";
-type_string(251) ->
- "code (loader)";
-type_string(252) ->
- "atom tab (loader)";
-type_string(253) ->
- "import tab (loader)";
-type_string(254) ->
- "export tab (loader)";
-type_string(255) ->
- "lable tab (loader)";
-type_string(256) ->
- "gen op (loader)";
-type_string(257) ->
- "gen op args (loader)";
-type_string(258) ->
- "gen op args 2 (loader)";
-type_string(259) ->
- "gen op args 3 (loader)";
-type_string(260) ->
- "lambdas (loader)";
-type_string(261) ->
- "temp int buffer (loader)";
-type_string(262) ->
- "temp heap (loader)";
-type_string(280) ->
- "dist ctrl msg buffer";
-type_string(281) ->
- "dist_buf";
-type_string(290) ->
- "call trace buffer";
-type_string(300) ->
- "bif timer rec";
-type_string(310) ->
- "argument registers";
-type_string(320) ->
- "compressed binary temp buffer";
-type_string(330) ->
- "term_to_binary temp buffer";
-type_string(340) ->
- "proc dict";
-type_string(350) ->
- "trace to port temp buffer";
-type_string(360) ->
- "lists subtract temp buffer";
-type_string(370) ->
- "link (lh)";
-type_string(380) ->
- "port call buffer";
-type_string(400) ->
- "definite_alloc block";
-type_string(_) ->
- invalid_type.
-
+dispatch_gather(#{ allocator_types := AllocatorTypes,
+ scheduler_ids := SchedulerIds,
+ histogram_start := HistStart,
+ histogram_width := HistWidth }, Ref, Gather)
+ when is_list(AllocatorTypes),
+ is_list(SchedulerIds),
+ HistStart >= 1, HistStart =< (1 bsl 28),
+ HistWidth >= 1, HistWidth =< 32 ->
+ MsgCount = lists:sum(
+ [Gather({AllocatorType, SchedId, HistWidth, HistStart, Ref}) ||
+ SchedId <- SchedulerIds,
+ AllocatorType <- AllocatorTypes]),
+ {HistStart, MsgCount};
+dispatch_gather(_, _, _) ->
+ error(badarg).
diff --git a/lib/tools/src/lcnt.erl b/lib/tools/src/lcnt.erl
index d881fedbd5..ee6057e4f5 100644
--- a/lib/tools/src/lcnt.erl
+++ b/lib/tools/src/lcnt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,8 +34,11 @@
-export([start/0,
stop/0]).
-%% erts_debug:lock_counters api
--export([rt_collect/0,
+%% erts_debug:lcnt_xxx api
+-export([rt_mask/0,
+ rt_mask/1,
+ rt_mask/2,
+ rt_collect/0,
rt_collect/1,
rt_clear/0,
rt_clear/1,
@@ -122,7 +125,7 @@
%% -------------------------------------------------------------------- %%
start() -> gen_server:start({local, ?MODULE}, ?MODULE, [], []).
-stop() -> gen_server:call(?MODULE, stop, infinity).
+stop() -> gen_server:stop(?MODULE, normal, infinity).
init([]) -> {ok, #state{ locks = [], duration = 0 } }.
start_internal() ->
@@ -134,27 +137,61 @@ start_internal() ->
%% -------------------------------------------------------------------- %%
%%
-%% API erts_debug:lock_counters
+%% API erts_debug:lcnt_xxx
%%
%% -------------------------------------------------------------------- %%
-rt_collect() ->
- erts_debug:lock_counters(info).
+rt_mask(Node, Categories) when is_atom(Node), is_list(Categories) ->
+ rpc:call(Node, lcnt, rt_mask, [Categories]).
+
+rt_mask(Node) when is_atom(Node) ->
+ rpc:call(Node, lcnt, rt_mask, []);
+
+rt_mask(Categories) when is_list(Categories) ->
+ case erts_debug:lcnt_control(copy_save) of
+ false ->
+ erts_debug:lcnt_control(mask, Categories);
+ true ->
+ {error, copy_save_enabled}
+ end.
+
+rt_mask() ->
+ erts_debug:lcnt_control(mask).
rt_collect(Node) ->
- rpc:call(Node, erts_debug, lock_counters, [info]).
+ rpc:call(Node, lcnt, rt_collect, []).
+rt_collect() ->
+ erts_debug:lcnt_collect().
+rt_clear(Node) ->
+ rpc:call(Node, lcnt, rt_clear, []).
rt_clear() ->
- erts_debug:lock_counters(clear).
+ erts_debug:lcnt_clear().
-rt_clear(Node) ->
- rpc:call(Node, erts_debug, lock_counters, [clear]).
+rt_opt(Node, Arg) ->
+ rpc:call(Node, lcnt, rt_opt, [Arg]).
+
+%% Compatibility shims for the "process/port_locks" options mentioned in the
+%% manual.
+rt_opt({process_locks, Enable}) ->
+ toggle_category(process, Enable);
+rt_opt({port_locks, Enable}) ->
+ toggle_category(io, Enable);
-rt_opt({Type, Opt}) ->
- erts_debug:lock_counters({Type, Opt}).
+rt_opt({Type, NewVal}) ->
+ PreviousVal = erts_debug:lcnt_control(Type),
+ erts_debug:lcnt_control(Type, NewVal),
+ PreviousVal.
-rt_opt(Node, {Type, Opt}) ->
- rpc:call(Node, erts_debug, lock_counters, [{Type, Opt}]).
+toggle_category(Category, true) ->
+ PreviousMask = erts_debug:lcnt_control(mask),
+ erts_debug:lcnt_control(mask, [Category | PreviousMask]),
+ lists:member(Category, PreviousMask);
+
+toggle_category(Category, false) ->
+ PreviousMask = erts_debug:lcnt_control(mask),
+ erts_debug:lcnt_control(mask, lists:delete(Category, PreviousMask)),
+ lists:member(Category, PreviousMask).
%% -------------------------------------------------------------------- %%
%%
@@ -181,9 +218,11 @@ raw() -> call(raw).
set(Option, Value) -> call({set, Option, Value}).
set({Option, Value}) -> call({set, Option, Value}).
save(Filename) -> call({save, Filename}).
-load(Filename) -> ok = start_internal(), call({load, Filename}).
+load(Filename) -> call({load, Filename}).
-call(Msg) -> gen_server:call(?MODULE, Msg, infinity).
+call(Msg) ->
+ ok = start_internal(),
+ gen_server:call(?MODULE, Msg, infinity).
%% -------------------------------------------------------------------- %%
%%
@@ -192,24 +231,21 @@ call(Msg) -> gen_server:call(?MODULE, Msg, infinity).
%% -------------------------------------------------------------------- %%
apply(M,F,As) when is_atom(M), is_atom(F), is_list(As) ->
- ok = start_internal(),
- Opt = lcnt:rt_opt({copy_save, true}),
- lcnt:clear(),
- Res = erlang:apply(M,F,As),
- lcnt:collect(),
- lcnt:rt_opt({copy_save, Opt}),
- Res.
+ apply(fun() ->
+ erlang:apply(M,F,As)
+ end).
apply(Fun) when is_function(Fun) ->
lcnt:apply(Fun, []).
apply(Fun, As) when is_function(Fun) ->
- ok = start_internal(),
Opt = lcnt:rt_opt({copy_save, true}),
lcnt:clear(),
Res = erlang:apply(Fun, As),
lcnt:collect(),
- lcnt:rt_opt({copy_save, Opt}),
+ %% _ is bound to silence a dialyzer warning; it used to fail silently and
+ %% we don't want to change the error semantics.
+ _ = lcnt:rt_opt({copy_save, Opt}),
Res.
all_conflicts() -> all_conflicts(time).
@@ -406,9 +442,6 @@ handle_call({save, Filename}, _From, State) ->
{reply, {error, Error}, State}
end;
-handle_call(stop, _From, State) ->
- {stop, normal, ok, State};
-
handle_call(Command, _From, State) ->
{reply, {error, {undefined, Command}}, State}.
@@ -908,7 +941,7 @@ print_state_information(#state{locks = Locks} = State) ->
print(kv("#tries", s(Stats#stats.tries))),
print(kv("#colls", s(Stats#stats.colls))),
print(kv("wait time", s(Stats#stats.time) ++ " us" ++ " ( " ++ s(Stats#stats.time/1000000) ++ " s)")),
- print(kv("percent of duration", s(Stats#stats.time/State#state.duration*100) ++ " %")),
+ print(kv("percent of duration", s(percent(Stats#stats.time, State#state.duration)) ++ " %")),
ok.
diff --git a/lib/tools/src/make.erl b/lib/tools/src/make.erl
index ce30156db6..6554d338af 100644
--- a/lib/tools/src/make.erl
+++ b/lib/tools/src/make.erl
@@ -267,15 +267,47 @@ include_opt([]) ->
recompile(File, true, _Load, _Opts) ->
io:format("Out of date: ~ts\n",[File]);
-recompile(File, false, noload, Opts) ->
+recompile(File, false, Load, Opts) ->
io:format("Recompile: ~ts\n",[File]),
- compile:file(File, [report_errors, report_warnings, error_summary |Opts]);
-recompile(File, false, load, Opts) ->
- io:format("Recompile: ~ts\n",[File]),
- c:c(File, Opts);
-recompile(File, false, netload, Opts) ->
- io:format("Recompile: ~ts\n",[File]),
- c:nc(File, Opts).
+ case compile:file(File, [report_errors, report_warnings |Opts]) of
+ Ok when is_tuple(Ok), element(1,Ok)==ok ->
+ maybe_load(element(2,Ok), Load, Opts);
+ _Error ->
+ error
+ end.
+
+maybe_load(_Mod, noload, _Opts) ->
+ ok;
+maybe_load(Mod, Load, Opts) ->
+ %% We have compiled File with options Opts. Find out where the
+ %% output file went to, and load it.
+ case compile:output_generated(Opts) of
+ true ->
+ Dir = proplists:get_value(outdir,Opts,"."),
+ do_load(Dir, Mod, Load);
+ false ->
+ io:format("** Warning: No object file created - nothing loaded **~n"),
+ ok
+ end.
+
+do_load(Dir, Mod, load) ->
+ code:purge(Mod),
+ case code:load_abs(filename:join(Dir, Mod),Mod) of
+ {module,Mod} ->
+ {ok,Mod};
+ Other ->
+ Other
+ end;
+do_load(Dir, Mod, netload) ->
+ Obj = atom_to_list(Mod) ++ code:objfile_extension(),
+ Fname = filename:join(Dir, Obj),
+ case file:read_file(Fname) of
+ {ok,Bin} ->
+ rpc:eval_everywhere(code,load_binary,[Mod,Fname,Bin]),
+ {ok,Mod};
+ Other ->
+ Other
+ end.
exists(File) ->
case file:read_file_info(File) of
diff --git a/lib/tools/src/tools.app.src b/lib/tools/src/tools.app.src
index 12f0cfd2df..f8c6aa22cb 100644
--- a/lib/tools/src/tools.app.src
+++ b/lib/tools/src/tools.app.src
@@ -40,7 +40,7 @@
{env, [{file_util_search_methods,[{"", ""}, {"ebin", "esrc"}, {"ebin", "src"}]}
]
},
- {runtime_dependencies, ["stdlib-3.1","runtime_tools-1.8.14",
- "kernel-3.0","erts-7.0","compiler-5.0"]}
+ {runtime_dependencies, ["stdlib-3.4","runtime_tools-1.8.14",
+ "kernel-5.4","erts-9.1","compiler-5.0"]}
]
}.
diff --git a/lib/tools/src/xref.erl b/lib/tools/src/xref.erl
index 32efa36fa2..466ec7d331 100644
--- a/lib/tools/src/xref.erl
+++ b/lib/tools/src/xref.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -182,7 +182,9 @@ split_args(Opts) ->
end.
stop(Name) ->
- gen_server:call(Name, stop, infinity).
+ try gen_server:call(Name, stop, infinity)
+ after catch unregister(Name) % ensure the name is gone
+ end.
add_release(Name, Dir) ->
gen_server:call(Name, {add_release, Dir}, infinity).
diff --git a/lib/tools/src/xref_base.erl b/lib/tools/src/xref_base.erl
index 8d2cc07e40..a28c6ee283 100644
--- a/lib/tools/src/xref_base.erl
+++ b/lib/tools/src/xref_base.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -400,26 +400,28 @@ analysis(locals_not_used, functions) ->
%% used (indirectly) from any export: "(domain EE + range EE) * L".
%% But then we only get locals that make some calls, so we add
%% locals that are not used at all: "L * (UU + XU - LU)".
- "L * ((UU + XU - LU) + domain EE + range EE)";
+ %% We also need to exclude functions with the -on_load() attribute:
+ %% (L - OL) is used rather than just L.
+ "(L - OL) * ((UU + XU - LU) + domain EE + range EE)";
analysis(exports_not_used, _) ->
%% Local calls are not considered here. "X * UU" would do otherwise.
"X - XU";
analysis({call, F}, functions) ->
- make_query("range (E | ~w : Fun)", [F]);
+ make_query("range (E | ~tw : Fun)", [F]);
analysis({use, F}, functions) ->
- make_query("domain (E || ~w : Fun)", [F]);
+ make_query("domain (E || ~tw : Fun)", [F]);
analysis({module_call, M}, _) ->
- make_query("range (ME | ~w : Mod)", [M]);
+ make_query("range (ME | ~tw : Mod)", [M]);
analysis({module_use, M}, _) ->
- make_query("domain (ME || ~w : Mod)", [M]);
+ make_query("domain (ME || ~tw : Mod)", [M]);
analysis({application_call, A}, _) ->
- make_query("range (AE | ~w : App)", [A]);
+ make_query("range (AE | ~tw : App)", [A]);
analysis({application_use, A}, _) ->
- make_query("domain (AE || ~w : App)", [A]);
+ make_query("domain (AE || ~tw : App)", [A]);
analysis({release_call, R}, _) ->
- make_query("range (RE | ~w : Rel)", [R]);
+ make_query("range (RE | ~tw : Rel)", [R]);
analysis({release_use, R}, _) ->
- make_query("domain (RE || ~w : Rel)", [R]);
+ make_query("domain (RE || ~tw : Rel)", [R]);
analysis(deprecated_function_calls, functions) ->
"XC || DF";
analysis({deprecated_function_calls,Flag}, functions) ->
@@ -918,7 +920,7 @@ do_add_module(S, XMod, Unres, Data) ->
{ok, Ms, Bad, NS}.
prepare_module(_Mode = functions, XMod, Unres0, Data) ->
- {DefAt0, LPreCAt0, XPreCAt0, LC0, XC0, X0, Attrs, Depr} = Data,
+ {DefAt0, LPreCAt0, XPreCAt0, LC0, XC0, X0, Attrs, Depr, OL0} = Data,
%% Bad is a list of bad values of 'xref' attributes.
{ALC0,AXC0,Bad0} = Attrs,
FT = [tspec(func)],
@@ -935,6 +937,7 @@ prepare_module(_Mode = functions, XMod, Unres0, Data) ->
ALC1 = xref_utils:xset(ALC0, PCA),
UnresCalls = xref_utils:xset(Unres0, PCA),
Unres = domain(UnresCalls),
+ OL1 = xref_utils:xset(OL0, FT),
DefinedFuns = domain(DefAt),
{AXC, ALC, Bad1, LPreCAt2, XPreCAt2} =
@@ -955,7 +958,7 @@ prepare_module(_Mode = functions, XMod, Unres0, Data) ->
{DF1,DF_11,DF_21,DF_31,DBad} = depr_mod(Depr, X),
{EE, ECallAt} = inter_graph(X, L, LC, XC, CallAt),
{ok, {functions, XMod, [DefAt,L,X,LCallAt,XCallAt,CallAt,LC,XC,EE,ECallAt,
- DF1,DF_11,DF_21,DF_31], NoCalls, Unres},
+ OL1,DF1,DF_11,DF_21,DF_31], NoCalls, Unres},
DBad++Bad};
prepare_module(_Mode = modules, XMod, _Unres, Data) ->
{X0, I0, Depr} = Data,
@@ -967,7 +970,7 @@ prepare_module(_Mode = modules, XMod, _Unres, Data) ->
finish_module({functions, XMod, List, NoCalls, Unres}, S) ->
ok = check_module(XMod, S),
[DefAt2,L2,X2,LCallAt2,XCallAt2,CallAt2,LC2,XC2,EE2,ECallAt2,
- DF2,DF_12,DF_22,DF_32] = pack(List),
+ OL2,DF2,DF_12,DF_22,DF_32] = pack(List),
LU = range(LC2),
@@ -976,7 +979,7 @@ finish_module({functions, XMod, List, NoCalls, Unres}, S) ->
M = XMod#xref_mod.name,
MS = xref_utils:xset(M, atom),
T = from_sets({MS,DefAt2,L2,X2,LCallAt2,XCallAt2,CallAt2,
- LC2,XC2,LU,EE2,ECallAt2,Unres,LPredefined,
+ LC2,XC2,LU,EE2,ECallAt2,Unres,LPredefined,OL2,
DF2,DF_12,DF_22,DF_32}),
NoUnres = XMod#xref_mod.no_unresolved,
@@ -1220,7 +1223,7 @@ do_set_up(S, VerboseOpt) ->
%% If data has been supplied using add_module/9 (and that is the only
%% sanctioned way), then DefAt, L, X, LCallAt, XCallAt, CallAt, XC, LC,
-%% and LU are guaranteed to be functions (with all supplied
+%% LU and OL are guaranteed to be functions (with all supplied
%% modules as domain (disregarding unknown modules, that is, modules
%% not supplied but hosting unknown functions)).
%% As a consequence, V and E are also functions. V is defined for unknown
@@ -1233,8 +1236,8 @@ do_set_up(S, VerboseOpt) ->
do_set_up(S) when S#xref.mode =:= functions ->
ModDictList = dict:to_list(S#xref.modules),
[DefAt0, L, X0, LCallAt, XCallAt, CallAt, LC, XC, LU,
- EE0, ECallAt, UC, LPredefined,
- Mod_DF,Mod_DF_1,Mod_DF_2,Mod_DF_3] = make_families(ModDictList, 18),
+ EE0, ECallAt, UC, LPredefined, OL,
+ Mod_DF,Mod_DF_1,Mod_DF_2,Mod_DF_3] = make_families(ModDictList, 19),
{XC_1, XU, XPredefined} = do_set_up_1(XC),
LC_1 = user_family(union_of_family(LC)),
@@ -1314,13 +1317,14 @@ do_set_up(S) when S#xref.mode =:= functions ->
UC_1 = user_family(union_of_family(UC)),
?FORMAT("DefAt ~p~n", [DefAt]),
- ?FORMAT("U=~p~nLib=~p~nB=~p~nLU=~p~nXU=~p~nUU=~p~n", [U,Lib,B,LU,XU,UU]),
+ ?FORMAT("U=~p~nLib=~p~nB=~p~nLU=~p~nXU=~p~nUU=~p~nOL=~p~n",
+ [U,Lib,B,LU,XU,UU,OL]),
?FORMAT("E_1=~p~nLC_1=~p~nXC_1=~p~n", [E_1,LC_1,XC_1]),
?FORMAT("EE=~p~nEE_1=~p~nECallAt=~p~n", [EE, EE_1, ECallAt]),
?FORMAT("DF=~p~nDF_1=~p~nDF_2=~p~nDF_3=~p~n", [DF, DF_1, DF_2, DF_3]),
Vs = [{'L',L}, {'X',X},{'F',F},{'U',U},{'B',B},{'UU',UU},
- {'XU',XU},{'LU',LU},{'V',V},{v,V},
+ {'XU',XU},{'LU',LU},{'V',V},{v,V},{'OL',OL},
{'LC',{LC,LC_1}},{'XC',{XC,XC_1}},{'E',{E,E_1}},{e,{E,E_1}},
{'EE',{EE,EE_1}},{'UC',{UC,UC_1}},
{'M',M},{'A',A},{'R',R},
@@ -1405,6 +1409,7 @@ var_type('U') -> {function, vertex};
var_type('UU') -> {function, vertex};
var_type('V') -> {function, vertex};
var_type('X') -> {function, vertex};
+var_type('OL') -> {function, vertex};
var_type('XU') -> {function, vertex};
var_type('DF') -> {function, vertex};
var_type('DF_1') -> {function, vertex};
@@ -1833,9 +1838,9 @@ message(true, What, Arg) ->
unreadable ->
io:format("Skipping ~ts (unreadable)~n", [Arg]);
xref_attr ->
- io:format("~ts: Skipping 'xref' attribute ~w~n", Arg);
+ io:format("~ts: Skipping 'xref' attribute ~tw~n", Arg);
depr_attr ->
- io:format("~ts: Skipping 'deprecated' attribute ~w~n", Arg);
+ io:format("~ts: Skipping 'deprecated' attribute ~tw~n", Arg);
lib_search ->
io:format("Scanning library path for BEAM files... ", []);
lib_check ->
diff --git a/lib/tools/src/xref_parser.yrl b/lib/tools/src/xref_parser.yrl
index 0711da79e2..5ee6419ff5 100644
--- a/lib/tools/src/xref_parser.yrl
+++ b/lib/tools/src/xref_parser.yrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -170,7 +170,7 @@ is_prefix_op('#') -> numeric;
is_prefix_op(_) -> false.
check_regexp(String) ->
- case re:compile(String) of
+ case re:compile(String, [unicode]) of
{ok, _Expr} ->
{regexpr, String};
{error, {ErrString, Position}} ->
@@ -274,7 +274,7 @@ mfa2s({M,F,A}) ->
[c2s(M),':',c2s(F),'/',A].
c2s(C) ->
- [S] = io_lib:format("~p", [C]),
+ [S] = io_lib:format("~tp", [C]),
list_to_atom(S).
re(variable) -> ['_'];
diff --git a/lib/tools/src/xref_reader.erl b/lib/tools/src/xref_reader.erl
index 88f92df35a..d28bdb78db 100644
--- a/lib/tools/src/xref_reader.erl
+++ b/lib/tools/src/xref_reader.erl
@@ -42,7 +42,8 @@
%% experimental; -xref(FunEdge) is recognized.
lattrs=[], % local calls, {{mfa(),mfa()},Line}
xattrs=[], % external calls, -"-
- battrs=[] % badly formed xref attributes, term().
+ battrs=[], % badly formed xref attributes, term().
+ on_load % function name
}).
-include("xref.hrl").
@@ -68,15 +69,26 @@ forms([F | Fs], S) ->
forms([], S) ->
#xrefr{module = M, def_at = DefAt,
l_call_at = LCallAt, x_call_at = XCallAt,
- el = LC, ex = XC, x = X, df = Depr,
+ el = LC, ex = XC, x = X, df = Depr, on_load = OnLoad,
+ lattrs = AL, xattrs = AX, battrs = B, unresolved = U} = S,
+ OL = case OnLoad of
+ undefined -> [];
+ F ->
+ [{M, F, 0}]
+ end,
+ #xrefr{def_at = DefAt,
+ l_call_at = LCallAt, x_call_at = XCallAt,
+ el = LC, ex = XC, x = X, df = Depr, on_load = OnLoad,
lattrs = AL, xattrs = AX, battrs = B, unresolved = U} = S,
Attrs = {lists:reverse(AL), lists:reverse(AX), lists:reverse(B)},
- {ok, M, {DefAt, LCallAt, XCallAt, LC, XC, X, Attrs, Depr}, U}.
+ {ok, M, {DefAt, LCallAt, XCallAt, LC, XC, X, Attrs, Depr, OL}, U}.
form({attribute, Line, xref, Calls}, S) -> % experimental
#xrefr{module = M, function = Fun,
lattrs = L, xattrs = X, battrs = B} = S,
attr(Calls, erl_anno:line(Line), M, Fun, L, X, B, S);
+form({attribute, _, on_load, {F, 0}}, S) ->
+ S#xrefr{on_load = F};
form({attribute, _Line, _Attr, _Val}, S) ->
S;
form({function, _, module_info, 0, _Clauses}, S) ->
diff --git a/lib/tools/src/xref_utils.erl b/lib/tools/src/xref_utils.erl
index b0c168e018..eca751337b 100644
--- a/lib/tools/src/xref_utils.erl
+++ b/lib/tools/src/xref_utils.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -557,12 +557,9 @@ subdir(Dir, SubDir, true) ->
%% Avoid "App-01.01" - the zeroes will be lost.
filename2appl(File) ->
- Pos = string:rstr(File, "-"),
- true = Pos > 1,
- V = string:sub_string(File, Pos+1),
- true = string:len(V) > 0,
- VsnT = string:tokens(V, "."),
- ApplName = string:sub_string(File, 1, Pos-1),
+ [ApplName, V] = string:split(File, "-", trailing),
+ true = string:length(V) > 0,
+ VsnT = string:lexemes(V, "."),
Vsn = [list_to_integer(Vsn) || Vsn <- VsnT],
{list_to_atom(ApplName),Vsn}.
@@ -638,14 +635,14 @@ neighbours([], G, Fun, VT, L, _V, Vs) ->
neighbours(Vs, G, Fun, VT, L).
match_list(L, RExpr) ->
- {ok, Expr} = re:compile(RExpr),
+ {ok, Expr} = re:compile(RExpr, [unicode]),
filter(fun(E) -> match(E, Expr) end, L).
match_one(VarL, Con, Col) ->
select_each(VarL, fun(E) -> Con =:= element(Col, E) end).
match_many(VarL, RExpr, Col) ->
- {ok, Expr} = re:compile(RExpr),
+ {ok, Expr} = re:compile(RExpr, [unicode]),
select_each(VarL, fun(E) -> match(element(Col, E), Expr) end).
match(I, Expr) when is_integer(I) ->
@@ -653,7 +650,12 @@ match(I, Expr) when is_integer(I) ->
{match, [{0,length(S)}]} =:= re:run(S, Expr, [{capture, first}]);
match(A, Expr) when is_atom(A) ->
S = atom_to_list(A),
- {match, [{0,length(S)}]} =:= re:run(S, Expr, [{capture, first}]).
+ case re:run(S, Expr, [{capture, first}]) of
+ {match, [{0,Size}]} ->
+ Size =:= byte_size(unicode:characters_to_binary(S));
+ _ ->
+ false
+ end.
select_each([{Mod,Funs} | L], Pred) ->
case filter(Pred, Funs) of
diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl
index 90e113c178..161b0105b9 100644
--- a/lib/tools/test/cover_SUITE.erl
+++ b/lib/tools/test/cover_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@ all() ->
distribution, reconnect, die_and_reconnect,
dont_reconnect_after_stop, stop_node_after_disconnect,
export_import, otp_5031, otp_6115,
- otp_8270, otp_10979_hanging_node],
+ otp_8270, otp_10979_hanging_node, otp_14817],
case whereis(cover_server) of
undefined ->
[coverage,StartStop ++ NoStartStop];
@@ -1574,6 +1574,30 @@ otp_10979_hanging_node(_Config) ->
ok.
+otp_14817(Config) when is_list(Config) ->
+ Test = <<"-module(otp_14817).
+ -export([a/0, b/0, c/0, d/0]).
+ a() -> ok. b() -> ok. c() -> ok.
+ d() -> ok.
+ ">>,
+ File = cc_mod(otp_14817, Test, Config),
+ ok = otp_14817:a(),
+ ok = otp_14817:b(),
+ ok = otp_14817:c(),
+ ok = otp_14817:d(),
+ {ok,[{{otp_14817,3},1},
+ {{otp_14817,3},1},
+ {{otp_14817,3},1},
+ {{otp_14817,4},1}]} =
+ cover:analyse(otp_14817, calls, line),
+ {ok, CovOut} = cover:analyse_to_file(otp_14817),
+ {ok, Bin} = file:read_file(CovOut),
+ <<"3..|",_/binary>> = string:find(Bin, "3..|"),
+ <<"1..|",_/binary>> = string:find(Bin, "1..|"),
+ ok = file:delete(File),
+ ok = file:delete(CovOut),
+ ok.
+
%% Take compiler options from beam in cover:compile_beam
compile_beam_opts(Config) when is_list(Config) ->
{ok, Cwd} = file:get_cwd(),
diff --git a/lib/tools/test/emacs_SUITE.erl b/lib/tools/test/emacs_SUITE.erl
index 77a8813db5..5839f9ce5b 100644
--- a/lib/tools/test/emacs_SUITE.erl
+++ b/lib/tools/test/emacs_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,10 +23,10 @@
-export([all/0, init_per_testcase/2, end_per_testcase/2]).
--export([bif_highlight/1]).
+-export([bif_highlight/1, indent/1]).
-all() ->
- [bif_highlight].
+all() ->
+ [bif_highlight, indent].
init_per_testcase(_Case, Config) ->
ErlangEl = filename:join([code:lib_dir(tools),"emacs","erlang.el"]),
@@ -74,4 +74,69 @@ check_bif_highlight(Bin, Tag, Compare) ->
[] = Compare -- EmacsIntBifs,
[] = EmacsIntBifs -- Compare.
-
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+indent(Config) ->
+ case emacs_version_ok() of
+ false -> {skip, "Old or no emacs found"};
+ true ->
+ Def = filename:dirname(code:which(?MODULE)) ++ "/" ++ ?MODULE_STRING ++ "_data",
+ Dir = proplists:get_value(data_dir, Config, Def),
+ OrigFs = filelib:wildcard(Dir ++ "/*"),
+ io:format("Dir: ~s~nFs: ~p~n", [Dir, OrigFs]),
+ Fs = [{File, unindent(File)} || File <- OrigFs,
+ filename:extension(File) =:= ""],
+ Indent = fun emacs/1,
+ [Indent(File) || {_, File} <- Fs],
+ Res = [diff(Orig, File) || {Orig, File} <- Fs],
+ [file:delete(File) || {ok, File} <- Res], %% Cleanup
+ [] = [Fail || {fail, Fail} <- Res],
+ ok
+ end.
+
+unindent(Input) ->
+ Output = Input ++ ".erl",
+ {ok, Bin} = file:read_file(Input),
+ Lines0 = string:split(Bin, "\n", all),
+ Lines = [string:trim(Line, leading, [$\s,$\t]) || Line <- Lines0],
+ %% io:format("File: ~s lines: ~w~n", [Input, length(Lines0)]),
+ %% [io:format("~s~n", [L]) || L <- Lines],
+ ok = file:write_file(Output, lists:join("\n", Lines)),
+ Output.
+
+diff(Orig, File) ->
+ case os:cmd(["diff ", Orig, " ", File]) of
+ "" -> {ok, File};
+ Diff ->
+ io:format("Fail: ~s vs ~s~n~s~n~n",[Orig, File, Diff]),
+ {fail, File}
+ end.
+
+emacs_version_ok() ->
+ case os:cmd("emacs --version | head -1") of
+ "GNU Emacs " ++ Ver ->
+ case string:to_float(Ver) of
+ {Vsn, _} when Vsn >= 24.1 ->
+ true;
+ _ ->
+ io:format("Emacs version fail~n~s~n~n",[Ver]),
+ false
+ end;
+ Res ->
+ io:format("Emacs version fail~n~s~n~n",[Res]),
+ false
+ end.
+
+emacs(File) ->
+ EmacsErlDir = filename:join([code:lib_dir(tools), "emacs"]),
+ Cmd = ["emacs ",
+ "--batch --quick ",
+ "--directory ", EmacsErlDir, " ",
+ "--eval \"(require 'erlang-start)\" ",
+ File, " ",
+ "--eval '(indent-region (point-min) (point-max) nil)' ",
+ "--eval '(save-buffer 0)'"
+ ],
+ _Res = os:cmd(Cmd),
+ % io:format("cmd ~s:~n=> ~s~n", [Cmd, _Res]),
+ ok.
diff --git a/lib/tools/test/emacs_SUITE_data/comments b/lib/tools/test/emacs_SUITE_data/comments
new file mode 100644
index 0000000000..ff974ca295
--- /dev/null
+++ b/lib/tools/test/emacs_SUITE_data/comments
@@ -0,0 +1,25 @@
+%% -*- Mode: erlang; indent-tabs-mode: nil -*-
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+
+%%% 3 comment chars: always left indented
+%%% 2 comment chars: Context indented
+%%% 1 comment char: Rigth indented
+
+%%% left
+%% context dependent
+ % rigth
+
+func() ->
+%%% left
+ %% context dependent
+ % right indented
+ case get(foo) of
+ undefined ->
+ %% Testing indention
+ ok;
+ %% Catch all
+ Other ->
+ Other
+ end,
+ ok.
+
diff --git a/lib/tools/test/emacs_SUITE_data/comprehensions b/lib/tools/test/emacs_SUITE_data/comprehensions
new file mode 100644
index 0000000000..45279850a5
--- /dev/null
+++ b/lib/tools/test/emacs_SUITE_data/comprehensions
@@ -0,0 +1,47 @@
+%% -*- Mode: erlang; indent-tabs-mode: nil -*-
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+
+%%% indentation of comprehensions
+
+%%% Not everything in these test are set in stone
+%%% better indentation rules can be added but by having
+%%% these tests we can see what changes in new implementations
+%%% and notice when doing unintentional changes
+
+list() ->
+ %% I don't have a good idea how we want to handle this
+ %% but they are here to show how they are indented today.
+ Result1 = [X ||
+ #record{a=X} <- lists:seq(1, 10),
+ true = (X rem 2)
+ ],
+ Result2 = [X || <<X:32,_:32>> <= <<0:512>>,
+ true = (X rem 2)
+ ],
+ Res = [ func(X,
+ arg2)
+ ||
+ #record{a=X} <- lists:seq(1, 10),
+ true = (X rem 2)
+ ],
+ Result1.
+
+binary(B) ->
+ Binary1 = << <<X:8>> ||
+ #record{a=X} <- lists:seq(1, 10),
+ true = (X rem 2)
+ >>,
+
+ Binary2 = << <<X:8>> || <<X:32,_:32>> <= <<0:512>>,
+ true = (X rem 2)
+ >>,
+
+ Bin3 = <<
+ <<
+ X:8,
+ 34:8
+ >>
+ || <<X:32,_:32>> <= <<0:512>>,
+ true = (X rem 2)
+ >>,
+ ok.
diff --git a/lib/tools/test/emacs_SUITE_data/funcs b/lib/tools/test/emacs_SUITE_data/funcs
new file mode 100644
index 0000000000..877f982005
--- /dev/null
+++ b/lib/tools/test/emacs_SUITE_data/funcs
@@ -0,0 +1,174 @@
+%% -*- Mode: erlang; indent-tabs-mode: nil -*-
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+
+%%% Function (and funs) indentation
+
+%%% Not everything in these test are set in stone
+%%% better indentation rules can be added but by having
+%%% these tests we can see what changes in new implementations
+%%% and notice when doing unintentional changes
+
+-export([
+ func1/0,
+ func2/0,
+ a_function_with_a_very_very_long_name/0,
+ when1/2
+ ]).
+
+-compile([nowarn_unused_functions,
+ {inline, [
+ func2/2,
+ func3/2
+ ]
+ }
+ ]).
+
+func1() ->
+ basic.
+
+func2(A1,
+ A2) ->
+ ok.
+
+func3(
+ A1,
+ A2
+ ) ->
+ ok.
+
+%% Okeefe style
+func4(A1
+ ,A2
+ ,A3
+ ) ->
+ ok.
+
+func5(
+ A41
+ ,A42) ->
+ ok.
+
+a_function_with_a_very_very_long_name() ->
+ A00 = #record{
+ field1=1,
+ field2=1
+ },
+ A00.
+
+when1(W1, W2)
+ when is_number(W1),
+ is_number(W2) ->
+ ok.
+
+when2(W1,W2,W3) when
+ W1 > W2,
+ W2 > W3 ->
+ ok.
+
+when3(W1,W2,W3) when
+ W1 > W2,
+ W2 > W3
+ ->
+ ok.
+
+when4(W1,W2,W3)
+ when
+ W1 > W2,
+ W2 > W3 ->
+ ok.
+
+match1({[H|T],
+ Other},
+ M1A2) ->
+ ok.
+
+match2(
+ {
+ [H|T],
+ Other
+ },
+ M2A2
+ ) ->
+ ok.
+
+match3({
+ M3A1,
+ [
+ H |
+ T
+ ],
+ Other
+ },
+ M3A2
+ ) ->
+ ok.
+
+match4(<<
+ M4A:8,
+ M4B:16/unsigned-integer,
+ _/binary
+ >>,
+ M4C) ->
+ ok.
+
+match5(M5A,
+ #record{
+ b=M5B,
+ c=M5C
+ }
+ ) ->
+ ok.
+
+match6(M6A,
+ #{key6a := a6,
+ key6b := b6
+ }) ->
+ ok.
+
+funs(1)
+ when
+ X ->
+ %% Changed fun to one indention level
+ %% 'when' and several clause forces a depth of '4'
+ Var = spawn(fun(X, _)
+ when X == 2;
+ X > 10 ->
+ hello,
+ case Hello() of
+ true when is_atom(X) ->
+ foo;
+ false ->
+ bar
+ end;
+ (Foo) when is_atom(Foo),
+ is_integer(X) ->
+ X = 6 * 45,
+ Y = true andalso
+ kalle
+ end),
+ Var;
+funs(2) ->
+ %% check EEP37 named funs
+ Fn1 = fun
+ Factory(N) when
+ N > 0 ->
+ F = Fact(N-1),
+ N * F;
+ Factory(0) ->
+ 1
+ end,
+ Fn1;
+funs(3) ->
+ %% check anonymous funs too
+ Fn2 = fun(0) ->
+ 1;
+ (N) ->
+ N
+ end,
+ ok;
+funs(4) ->
+ X = lists:foldr(fun(M) ->
+ <<M/binary, " ">>
+ end, [], Z),
+ A = <<X/binary, 0:8>>,
+ A.
diff --git a/lib/tools/test/emacs_SUITE_data/highlight b/lib/tools/test/emacs_SUITE_data/highlight
new file mode 100644
index 0000000000..0719f6516a
--- /dev/null
+++ b/lib/tools/test/emacs_SUITE_data/highlight
@@ -0,0 +1,78 @@
+%% -*- Mode: erlang; indent-tabs-mode: nil -*-
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+
+%%% Open this file in your editor and manually check the colors of
+%%% different types and calls and builtin words
+
+%%% Not everything in these test are set in stone
+%%% better indentation rules can be added but by having
+%%% these tests we can see what changes in new implementations
+%%% and notice when doing unintentional changes
+
+
+highlighting(X) % Function definitions should be highlighted
+ when is_integer(X) -> % and so should `when' and `is_integer' be
+ %% Highlighting
+ %% Various characters (we keep an `atom' after to see that highlighting ends)
+ $a,atom, % Characters should be marked
+ "string",atom, % and strings
+ 'asdasd',atom, % quote should be atoms??
+ 'VaV',atom,
+ 'aVa',atom,
+ '\'atom',atom,
+ 'atom\'',atom,
+ 'at\'om',atom,
+ '#1',atom,
+
+ $", atom, % atom should be ok
+ $', atom,
+
+ "string$", atom, "string$", atom, % currently buggy I know...
+ "string\$", atom, % workaround for bug above
+
+ "char $in string", atom,
+
+ 'atom$', atom, 'atom$', atom,
+ 'atom\$', atom,
+
+ 'char $in atom', atom,
+
+ $[, ${, $\\, atom,
+ ?MACRO_1,
+ ?MACRO_2(foo),
+
+ %% Numerical constants
+ 16#DD, % Should not be highlighted
+ 32#dd, % Should not be highlighted
+ 32#ddAB, % Should not be highlighted
+ 32#101, % Should not be highlighted
+ 32#ABTR, % Should not be highlighted
+
+ %% Variables
+ Variables = lists:foo(),
+ _Variables = lists:foo(),
+ AppSpec = Xyz/2,
+ Module42 = Xyz(foo, bar),
+ Module:foo(),
+ _Module:foo(), %
+ FooÅÅ = lists:reverse([tl,hd,tl,hd]), % Should highlight FooÅÅ
+ _FooÅÅ = 42, % Should highlight _FooÅÅ
+
+ %% Bifs
+ erlang:registered(),
+ registered(),
+ hd(tl(tl(hd([a,b,c])))),
+ erlang:anything(lists),
+ %% Guards
+ is_atom(foo), is_float(2.3), is_integer(32), is_number(4323.3),
+ is_function(Fun), is_pid(self()),
+ not_a_guard:is_list([]),
+ %% Other Types
+
+ atom, % not (currently) hightlighted
+ 234234,
+ 234.43,
+
+ [list, are, not, higlighted],
+ {nor, is, tuple},
+ ok.
diff --git a/lib/tools/test/emacs_SUITE_data/icr b/lib/tools/test/emacs_SUITE_data/icr
new file mode 100644
index 0000000000..8445c1a74d
--- /dev/null
+++ b/lib/tools/test/emacs_SUITE_data/icr
@@ -0,0 +1,157 @@
+%% -*- Mode: erlang; indent-tabs-mode: nil -*-
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+
+%%% indentation of if case receive statements
+
+%%% Not everything in these test are set in stone
+%%% better indentation rules can be added but by having
+%%% these tests we can see what changes in new implementations
+%%% and notice when doing unintentional changes
+
+indent_if(1, Z) ->
+ %% If
+ if Z >= 0 ->
+ X = 43 div Z,
+ X;
+ Z =< 10 ->
+ X = 43 div Z,
+ X;
+ Z == 5 orelse
+ Z == 7 ->
+ X = 43 div Z,
+ X;
+ is_number(Z),
+ Z < 32 ->
+ Z;
+ is_number(Z);
+ Z < 32 ->
+ Z * 32;
+ true ->
+ if_works
+ end;
+indent_if(2, Z) ->
+ %% If
+ if
+ Z >= 0 ->
+ X = 43 div Z,
+ X
+ ; Z =< 10 ->
+ 43 div Z
+ ; Z == 5 orelse
+ Z == 7 ->
+ X = 43 div Z,
+ X
+ ; is_number(Z),
+ Z < 32 ->
+ Z
+ ; true ->
+ if_works
+ end.
+
+indent_case(1, Z) ->
+ %% Case
+ case {Z, foo, bar} of
+ {Z,_,_} ->
+ X = 43 div 4,
+ foo(X);
+ {Z,_,_} when
+ Z =:= 42 -> % line should be indented as a when
+ X = 43 div 4,
+ foo(X);
+ {Z,_,_}
+ when Z < 10 orelse
+ Z =:= foo -> % Binary op alignment here !!!
+ X = 43 div 4,
+ Bool = Z < 5 orelse % Binary op args align differently after when
+ Z =:= foo, % and elsewhere ???
+ foo(X);
+ {Z,_,_}
+ when % when should be indented
+ Z < 10 % and the guards should follow when
+ andalso % unsure about how though
+ true ->
+ X = 43 div 4,
+ foo(X)
+ end;
+indent_case(2, Z) ->
+ %% Case
+ case {Z, foo, bar} of
+ {Z,_,_} ->
+ X = 43 div 4,
+ foo(X)
+ ; {Z,_,_} when
+ Z =:= 42 -> % line should be indented as a when
+ X = 43 div 4,
+ foo(X)
+ ; {Z,_,_}
+ when Z < 10 -> % when should be indented
+ X = 43 div 4,
+ foo(X)
+ ; {Z,_,_}
+ when % when should be indented
+ Z < 10 % and the guards should follow when
+ andalso % unsure about how though
+ true ->
+ X = 43 div 4,
+ foo(X)
+ end.
+
+indent_begin(Z) ->
+ %% Begin
+ begin
+ sune,
+ Z = 74234 +
+ foo(8456) +
+ 345 div 43,
+ Foo = begin
+ ok,
+ foo(234),
+ begin
+ io:format("Down here\n")
+ end
+ end,
+ {Foo,
+ bar}
+ end.
+
+indent_receive(1) ->
+ %% receive
+ receive
+ {Z,_,_} ->
+ X = 43 div 4,
+ foo(X)
+ ; Z ->
+ X = 43 div 4,
+ foo(X)
+ end,
+ ok;
+indent_receive(2) ->
+ receive
+ {Z,_,_} ->
+ X = 43 div 4,
+ foo(X);
+ Z % added clause
+ when Z =:= 1 -> % This line should be indented by 2
+ X = 43 div 4,
+ foo(X);
+ Z when % added clause
+ Z =:= 2 -> % This line should be indented by 2
+ X = 43 div 4,
+ foo(X);
+ Z ->
+ X = 43 div 4,
+ foo(X)
+ after infinity ->
+ foo(X),
+ asd(X),
+ 5*43
+ end,
+ ok;
+indent_receive() ->
+ receive
+ after 10 ->
+ foo(X),
+ asd(X),
+ 5*43
+ end,
+ ok.
diff --git a/lib/tools/test/emacs_SUITE_data/macros b/lib/tools/test/emacs_SUITE_data/macros
new file mode 100644
index 0000000000..6c874e9187
--- /dev/null
+++ b/lib/tools/test/emacs_SUITE_data/macros
@@ -0,0 +1,31 @@
+%% -*- Mode: erlang; indent-tabs-mode: nil -*-
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+
+%%% Macros should be indented as code
+
+-define(M0, ok).
+
+-define(M1,
+ case X of
+ undefined -> error;
+ _ -> ok
+ end).
+
+-define(M2(M2A1,
+ M2A2),
+ func(M2A1,
+ M2A2)
+ ).
+
+-define(
+ M3,
+ undefined
+ ).
+
+-ifdef(DEBUG).
+-define(LOG,
+ logger:log(?MODULE,?LINE)
+ ).
+-else().
+-define(LOG, ok).
+-endif().
diff --git a/lib/tools/test/emacs_SUITE_data/records b/lib/tools/test/emacs_SUITE_data/records
new file mode 100644
index 0000000000..241582718c
--- /dev/null
+++ b/lib/tools/test/emacs_SUITE_data/records
@@ -0,0 +1,35 @@
+%% -*- Mode: erlang; indent-tabs-mode: nil -*-
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+
+%% Test that records are indented correctly
+
+-record(record0,
+ {
+ r0a,
+ r0b,
+ r0c
+ }).
+
+-record(record1, {r1a,
+ r1b,
+ r1c
+ }).
+
+-record(record2, {
+ r2a,
+ r2b
+ }).
+
+-record(record3, {r3a = 8#42423 bor
+ 8#4234,
+ r3b = 8#5432
+ bor 2#1010101,
+ r3c = 123 +
+ 234,
+ r3d}).
+
+-record(record5,
+ { r5a = 1 :: integer()
+ , r5b = foobar :: atom()
+ }).
+
diff --git a/lib/tools/test/emacs_SUITE_data/terms b/lib/tools/test/emacs_SUITE_data/terms
new file mode 100644
index 0000000000..352364a73c
--- /dev/null
+++ b/lib/tools/test/emacs_SUITE_data/terms
@@ -0,0 +1,174 @@
+%% -*- Mode: erlang; indent-tabs-mode: nil -*-
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+
+%%% indentation of terms contain builtin types
+
+%%% Not everything in these test are set in stone
+%%% better indentation rules can be added but by having
+%%% these tests we can see what changes in new implementations
+%%% and notice when doing unintentional changes
+
+
+list(1) ->
+ [a,
+ b,
+ c
+ ];
+list(2) ->
+ [ a,
+ b, c
+ ];
+list(3) ->
+ [
+ a,
+ b, c
+ ];
+list(4) ->
+ [ a
+ , b
+ , c
+ ].
+
+tuple(1) ->
+ {a,
+ b,c
+ };
+tuple(2) ->
+ { a,
+ b,c
+ };
+tuple(3) ->
+ {
+ a,
+ b,c
+ };
+tuple(4) ->
+ { a
+ , b
+ ,c
+ }.
+
+binary(1) ->
+ <<1:8,
+ 2:8
+ >>;
+binary(2) ->
+ <<
+ 1:8,
+ 2:8
+ >>;
+binary(3) ->
+ << 1:8,
+ 2:8
+ >>;
+binary(4) ->
+ <<
+ 1:8
+ ,2:8
+ >>;
+binary(5) ->
+ << 1:8
+ , 2:8
+ >>.
+
+record(1) ->
+ #record{a=1,
+ b=2
+ };
+record(2) ->
+ #record{ a=1,
+ b=2
+ };
+record(3) ->
+ #record{
+ a=1,
+ b=2
+ };
+record(4) ->
+ #record{
+ a=1
+ ,b=2
+ };
+record(Record) ->
+ Record#record{
+ a=1
+ ,b=2
+ }.
+
+map(1) ->
+ #{a=>1,
+ b=>2
+ };
+map(2) ->
+ #{ a=>1,
+ b=>2
+ };
+map(3) ->
+ #{
+ a=>1,
+ b=>2
+ };
+map(4) ->
+ #{
+ a => <<"a">>
+ ,b => 2
+ };
+map(MapVar) ->
+ MapVar = #{a :=<<"a">>
+ ,b:=1}.
+
+deep(Rec) ->
+ Rec#rec{ atom = 'atom',
+ map = #{ k1 => {v,
+ 1},
+ k2 => [
+ 1,
+ 2,
+ 3
+ ],
+ {key,
+ 3}
+ =>
+ <<
+ 123:8,
+ 255:8
+ >>
+ }
+ }.
+
+%% Record indentation
+some_function_with_a_very_long_name() ->
+ #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
+ field1=a,
+ field2=b},
+ case dummy_function_with_a_very_very_long_name(x) of
+ #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
+ field1=a,
+ field2=b} ->
+ ok;
+ Var = #'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
+ field1=a,
+ field2=b} ->
+ Var#'a-long-record-name-like-it-sometimes-is-with-asn.1-records'{
+ field1=a,
+ field2=b};
+ #xyz{
+ a=1,
+ b=2} ->
+ ok
+ end.
+
+some_function_name_xyz(xyzzy, #some_record{
+ field1=Field1,
+ field2=Field2}) ->
+ SomeVariable = f(#'Some-long-record-name'{
+ field_a = 1,
+ 'inter-xyz-parameters' =
+ #'Some-other-very-long-record-name'{
+ field2 = Field1,
+ field2 = Field2}}),
+ {ok, SomeVariable}.
+
+foo() ->
+ [#foo{
+ foo = foo}].
diff --git a/lib/tools/test/emacs_SUITE_data/try_catch b/lib/tools/test/emacs_SUITE_data/try_catch
new file mode 100644
index 0000000000..0005b2003a
--- /dev/null
+++ b/lib/tools/test/emacs_SUITE_data/try_catch
@@ -0,0 +1,166 @@
+%% -*- Mode: erlang; indent-tabs-mode: nil -*-
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+
+%%% Try and catch indentation is hard
+
+%%% Not everything in these test are set in stone
+%%% better indentation rules can be added but by having
+%%% these tests we can see what changes in new implementations
+%%% and notice when doing unintentional changes
+
+try_catch() ->
+ try
+ io:format(stdout, "Parsing file ~s, ",
+ [St0#leex.xfile]),
+ {ok,Line3,REAs,Actions,St3} =
+ parse_rules(Xfile, Line2, Macs, St2)
+ catch
+ exit:{badarg,R} ->
+ foo(R),
+ io:format(stdout,
+ "ERROR reason ~p~n",
+ R);
+ error:R
+ when R =:= 42 -> % when should be indented
+ foo(R);
+ error:R
+ when % when should be indented
+ R =:= 42 -> % but unsure about this (maybe 2 more)
+ foo(R);
+ error:R when
+ R =:= foo -> % line should be 2 indented (works)
+ foo(R);
+ error:R ->
+ foo(R),
+ io:format(stdout,
+ "ERROR reason ~p~n",
+ R)
+ after
+ foo('after'),
+ file:close(Xfile)
+ end;
+try_catch() ->
+ try
+ foo(bar)
+ of
+ X when true andalso
+ kalle ->
+ io:format(stdout, "Parsing file ~s, ",
+ [St0#leex.xfile]),
+ {ok,Line3,REAs,Actions,St3} =
+ parse_rules(Xfile, Line2, Macs, St2);
+ X
+ when false andalso % when should be 2 indented
+ bengt ->
+ gurka();
+ X when
+ false andalso % line should be 2 indented
+ not bengt ->
+ gurka();
+ X ->
+ io:format(stdout, "Parsing file ~s, ",
+ [St0#leex.xfile]),
+ {ok,Line3,REAs,Actions,St3} =
+ parse_rules(Xfile, Line2, Macs, St2)
+ catch
+ exit:{badarg,R} ->
+ foo(R),
+ io:format(stdout,
+ "ERROR reason ~p~n",
+ R);
+ error:R ->
+ foo(R),
+ io:format(stdout,
+ "ERROR reason ~p~n",
+ R)
+ after
+ foo('after'),
+ file:close(Xfile),
+ bar(with_long_arg,
+ with_second_arg)
+ end;
+try_catch() ->
+ try foo()
+ after
+ foo(),
+ bar(with_long_arg,
+ with_second_arg)
+ end.
+
+indent_catch() ->
+ D = B +
+ float(43.1),
+
+ B = catch oskar(X),
+
+ A = catch (baz +
+ bax),
+ catch foo(),
+
+ C = catch B +
+ float(43.1),
+
+ case catch foo(X) of
+ A ->
+ B
+ end,
+
+ case
+ catch foo(X)
+ of
+ A ->
+ B
+ end,
+
+ case
+ foo(X)
+ of
+ A ->
+ catch B,
+ X
+ end,
+
+ try sune of
+ _ -> foo
+ catch _:_ -> baf
+ end,
+
+ Variable = try
+ sune
+ of
+ _ ->
+ X = 5,
+ (catch foo(X)),
+ X + 10
+ catch _:_ -> baf
+ after cleanup()
+ end,
+
+ try
+ (catch sune)
+ of
+ _ ->
+ foo1(),
+ catch foo() %% BUGBUG can't handle catch inside try without parentheses
+ catch _:_ ->
+ baf
+ end,
+
+ try
+ (catch exit())
+ catch
+ _ ->
+ catch baf()
+ end,
+ ok.
+
+%% this used to result in 2x the correct indentation within the function
+%% body, due to the function name being mistaken for a keyword
+catcher(N) ->
+ try generate_exception(N) of
+ Val -> {N, normal, Val}
+ catch
+ throw:X -> {N, caught, thrown, X};
+ exit:X -> {N, caught, exited, X};
+ error:X -> {N, caught, error, X}
+ end.
diff --git a/lib/tools/test/emacs_SUITE_data/type_specs b/lib/tools/test/emacs_SUITE_data/type_specs
new file mode 100644
index 0000000000..e71841cc7a
--- /dev/null
+++ b/lib/tools/test/emacs_SUITE_data/type_specs
@@ -0,0 +1,110 @@
+%% -*- Mode: erlang; indent-tabs-mode: nil -*-
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+
+%% Tests how types and specs are indented (also that the editor can parse them)
+%% May need improvements
+
+
+-type ann() :: Var :: integer().
+-type ann2() ::
+ 'return'
+ | 'return_white_spaces'
+ | 'return_comments'
+ | 'text' | ann().
+-type paren() ::
+ (ann2()).
+
+-type t6() ::
+ 1 | 2 | 3 |
+ 'foo'
+ | 'bar'.
+
+-type t8() :: {any(),none(),pid(),port(),
+ reference(),float()}.
+
+-type t14() :: [erl_scan:foo() |
+ %% Should be highlighted
+ term() |
+ boolean() |
+ byte() |
+ char() |
+ non_neg_integer() | nonempty_list() |
+ pos_integer() |
+ neg_integer() |
+ number() |
+ list() |
+ nonempty_improper_list() | nonempty_maybe_improper_list() |
+ maybe_improper_list() | string() | iolist() | byte() |
+ module() |
+ mfa() |
+ node() |
+ timeout() |
+ no_return() |
+ %% Should not be highlighted
+ nonempty_() | nonlist() |
+ erl_scan:bar(34, 92) | t13() | m:f(integer() | <<_:_*16>>)].
+
+-type t15() :: {binary(),<<>>,<<_:34>>,<<_:_*42>>,
+ <<_:3,_:_*14>>,<<>>} | [<<>>|<<_:34>>|<<_:16>>|
+ <<_:3,_:_*1472>>|<<_:19,_:_*14>>| <<_:34>>|
+ <<_:34>>|<<_:34>>|<<_:34>>].
+
+-type t18() ::
+ fun(() -> t17() | t16()).
+-type t19() ::
+ fun((t18()) -> t16()) |
+ fun((nonempty_maybe_improper_list('integer', any())|
+ 1|2|3|a|b|<<_:3,_:_*14>>|integer())
+ ->
+ nonempty_maybe_improper_list('integer', any())| %% left to col 16?
+ 1|2|3|a|b|<<_:3,_:_*14>>|integer()). %% left to col 16?
+-type t20() :: [t19(), ...].
+-type t25() :: #rec3{f123 :: [t24() |
+ 1|2|3|4|a|b|c|d|
+ nonempty_maybe_improper_list(integer, any())]}.
+-type t26() :: #rec4{ a :: integer()
+ , b :: any()
+ }.
+
+%% Spec
+
+-spec t1(FooBar :: t99()) -> t99();
+ (t2()) -> t2();
+ (t4()) -> t4() when is_subtype(t4(), t24);
+ (t23()) -> t23() when is_subtype(t23(), atom()),
+ is_subtype(t23(), t14());
+ (t24()) -> t24() when is_subtype(t24(), atom()),
+ is_subtype(t24(), t14()),
+ is_subtype(t24(), t4()).
+
+-spec over(I :: integer()) -> R1 :: foo:typen();
+ (A :: atom()) -> R2 :: foo:atomen();
+ (T :: tuple()) -> R3 :: bar:typen().
+
+-spec mod:t2() -> any().
+
+-spec handle_cast(Cast :: {'exchange', node(), [[name(),...]]}
+ | {'del_member', name(), pid()},
+ #state{}) -> {'noreply', #state{}}.
+
+-spec handle_cast(Cast ::
+ {'exchange', node(), [[name(),...]]}
+ | {'del_member', name(), pid()},
+ #state{}) ->
+ {'noreply', #state{}}. %% left to col 10?
+
+-spec all(fun((T) -> boolean()), List :: [T]) ->
+ boolean() when is_subtype(T, term()). % (*)
+
+-spec get_closest_pid(term()) ->
+ Return :: pid() %% left to col 10?
+ | {'error', {'no_process', term()}} %% left to col 10?
+ | {'no_such_group', term()}. %% left to col 10?
+
+-spec add( X :: integer()
+ , Y :: integer()
+ ) -> integer().
+
+-opaque attributes_data() ::
+ [{'column', column()} | {'line', info_line()} |
+ {'text', string()}] | {line(),column()}.
diff --git a/lib/tools/test/eprof_SUITE_data/eed.erl b/lib/tools/test/eprof_SUITE_data/eed.erl
index 5f2a21aa60..9fe49c6f5c 100644
--- a/lib/tools/test/eprof_SUITE_data/eed.erl
+++ b/lib/tools/test/eprof_SUITE_data/eed.erl
@@ -54,7 +54,7 @@ edit(Name) ->
loop(St0) ->
{ok, St1, Cmd} = get_line(St0),
- case catch command(lib:nonl(Cmd), St1) of
+ case catch command(nonl(Cmd), St1) of
{'EXIT', Reason} ->
%% XXX Should clear outstanding global command here.
loop(print_error({'EXIT', Reason}, St1));
@@ -66,6 +66,10 @@ loop(St0) ->
loop(St2)
end.
+nonl([$\n]) -> [];
+nonl([]) -> [];
+nonl([H|T]) -> [H|nonl(T)].
+
command(Cmd, St) ->
case parse_command(Cmd, St) of
quit ->
diff --git a/lib/tools/test/fprof_SUITE.erl b/lib/tools/test/fprof_SUITE.erl
index affb45b7a6..ae0e7253ad 100644
--- a/lib/tools/test/fprof_SUITE.erl
+++ b/lib/tools/test/fprof_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@
%% Test suites
-export([stack_seq/1, tail_seq/1, create_file_slow/1, spawn_simple/1,
imm_tail_seq/1, imm_create_file_slow/1, imm_compile/1,
- cpu_create_file_slow/1]).
+ cpu_create_file_slow/1, unicode/1]).
%% Other exports
-export([create_file_slow/2]).
@@ -51,7 +51,7 @@
suite() ->
[{ct_hooks,[ts_install_cth]},
- {timetrap,{seconds,60}}].
+ {timetrap,{seconds,240}}].
all() ->
case test_server:is_native(fprof_SUITE) of
@@ -59,7 +59,7 @@ all() ->
false ->
[stack_seq, tail_seq, create_file_slow, spawn_simple,
imm_tail_seq, imm_create_file_slow, imm_compile,
- cpu_create_file_slow]
+ cpu_create_file_slow, unicode]
end.
@@ -533,6 +533,17 @@ cpu_create_file_slow(Config) when is_list(Config) ->
TestResult.
+unicode(Config) when is_list(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ SourceFile = filename:join(DataDir, "fprof_unicode.erl"),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ AnalysisFile = filename:join(PrivDir, "fprof_unicode.analysis"),
+ {ok, fprof_unicode} = compile:file(SourceFile, [{outdir, PrivDir}]),
+ true = code:add_path(PrivDir),
+ fprof:apply(fprof_unicode, t, []),
+ ok = fprof:profile(dump, AnalysisFile),
+ ok = fprof:analyse(dest, AnalysisFile).
+
%%%---------------------------------------------------------------------
%%% Functions to test
%%%---------------------------------------------------------------------
@@ -560,7 +571,7 @@ seq_r(Start, Stop, Succ, R) ->
create_file_slow(Name, N) when is_integer(N), N >= 0 ->
{ok, FD} =
- file:open(Name, [raw, write, delayed_write, binary]),
+ file:open(Name, [raw, write, binary]),
if N > 256 ->
ok = file:write(FD,
lists:map(fun (X) -> <<X:32/unsigned>> end,
diff --git a/lib/tools/test/fprof_SUITE_data/fprof_unicode.erl b/lib/tools/test/fprof_SUITE_data/fprof_unicode.erl
new file mode 100644
index 0000000000..8b58efc5fe
--- /dev/null
+++ b/lib/tools/test/fprof_SUITE_data/fprof_unicode.erl
@@ -0,0 +1,36 @@
+-module(fprof_unicode).
+
+-export([t/0, 'кирилли́ческий атом'/0, annan/0, c_break/1,
+ 'кирилли́ческий атомB'/1]).
+
+t() ->
+ _Atom = 'кирилли́ческий атом',
+ 'кирилли́ческий атом'().
+
+'кирилли́ческий атом'() ->
+ 'кирилли́ческий атом'('кирилли́ческий атом').
+
+'кирилли́ческий атом'(_Atom) ->
+ self() ! 'кирилли́ческий атом',
+ G = fun (X) ->
+ catch foo:bar()
+ end,
+ G("кирилли́ческий атом"), % line 17
+ Pid = spawn_link(fun() -> waiting() end),
+ true = register('кирилли́ческий атом', Pid),
+ F = fun() -> 'кирилли́ческий атом' end,
+ F().
+
+annan() ->
+ foo.
+
+waiting() ->
+ receive
+ X -> X
+ end.
+
+c_break(_B) ->
+ true.
+
+'кирилли́ческий атомB'(_B) ->
+ true.
diff --git a/lib/tools/test/instrument_SUITE.erl b/lib/tools/test/instrument_SUITE.erl
index f37d28c277..8c521b2e1a 100644
--- a/lib/tools/test/instrument_SUITE.erl
+++ b/lib/tools/test/instrument_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,89 +20,274 @@
-module(instrument_SUITE).
-export([all/0, suite/0]).
--export(['+Mim true'/1, '+Mis true'/1]).
+
+-export([allocations_enabled/1, allocations_disabled/1, allocations_ramv/1,
+ carriers_enabled/1, carriers_disabled/1]).
+
+-export([test_all_alloc/2, test_per_alloc/2, test_format/3, test_abort/1,
+ generate_test_blocks/0, churn_memory/0]).
-include_lib("common_test/include/ct.hrl").
suite() ->
[{ct_hooks,[ts_install_cth]},
- {timetrap,{seconds,10}}].
+ {timetrap,{minutes,5}}].
all() ->
- ['+Mim true', '+Mis true'].
-
-
-%% Check that memory data can be read and processed
-'+Mim true'(Config) when is_list(Config) ->
- Node = start_slave("+Mim true"),
- MD = rpc:call(Node, instrument, memory_data, []),
- [{total,[{sizes,S1,S2,S3},{blocks,B1,B2,B3}]}]
- = rpc:call(Node, instrument, memory_status, [total]),
- stop_slave(Node),
- true = S1 =< S2,
- true = S2 =< S3,
- true = B1 =< B2,
- true = B2 =< B3,
- MDS = instrument:sort(MD),
- {Low, High} = instrument:mem_limits(MDS),
- true = Low < High,
- {_, AL} = MDS,
- SumBlocks = instrument:sum_blocks(MD),
- case SumBlocks of
- N when is_integer(N) ->
- N = lists:foldl(fun ({_,_,Size,_}, Sum) ->
- Size+Sum
- end, 0, AL),
- true = N =< S3;
- Other ->
- ct:fail(Other)
+ [allocations_enabled, allocations_disabled, allocations_ramv,
+ carriers_enabled, carriers_disabled].
+
+-define(GENERATED_SBC_BLOCK_COUNT, 1000).
+-define(GENERATED_MBC_BLOCK_COUNT, ?GENERATED_SBC_BLOCK_COUNT).
+
+-define(GENERATED_BLOCK_COUNT, (?GENERATED_SBC_BLOCK_COUNT +
+ ?GENERATED_MBC_BLOCK_COUNT)).
+-define(GENERATED_CARRIER_COUNT, ?GENERATED_SBC_BLOCK_COUNT).
+
+allocations_test(Args, Plain, PerAlloc) ->
+ run_test(Args, fun(Node) ->
+ ok = rpc:call(Node, ?MODULE, test_all_alloc,
+ [fun instrument:allocations/0, Plain]),
+ ok = rpc:call(Node, ?MODULE, test_per_alloc,
+ [fun instrument:allocations/1, PerAlloc]),
+ ok = rpc:call(Node, ?MODULE, test_format,
+ [#{ histogram_start => 512,
+ histogram_width => 4 },
+ fun instrument:allocations/1,
+ fun verify_allocations_output/2]),
+ ok = rpc:call(Node, ?MODULE, test_abort,
+ [fun erts_internal:gather_alloc_histograms/1])
+ end).
+
+allocations_enabled(Config) when is_list(Config) ->
+ allocations_test("+Meamax +Muatags true",
+ fun verify_allocations_enabled/1,
+ fun verify_allocations_enabled/2).
+
+allocations_disabled(Config) when is_list(Config) ->
+ allocations_test("+Meamax +Muatags false",
+ fun verify_allocations_disabled/1,
+ fun verify_allocations_disabled/2).
+
+allocations_ramv(Config) when is_list(Config) ->
+ allocations_test("+Meamax +Muatags true +Muramv true",
+ fun verify_allocations_enabled/1,
+ fun verify_allocations_enabled/2).
+
+verify_allocations_disabled(_AllocType, Result) ->
+ verify_allocations_disabled(Result).
+
+verify_allocations_disabled({error, not_enabled}) ->
+ ok.
+
+%% Skip types that have unstable results or are unaffected by +Muatags
+verify_allocations_enabled(literal_alloc, _Result) -> ok;
+verify_allocations_enabled(exec_alloc, _Result) -> ok;
+verify_allocations_enabled(temp_alloc, _Result) -> ok;
+verify_allocations_enabled(sl_alloc, _Result) -> ok;
+verify_allocations_enabled(_AllocType, Result) ->
+ verify_allocations_enabled(Result).
+
+verify_allocations_enabled({ok, {_HistStart, _UnscannedBytes, Allocs}}) ->
+ true = Allocs =/= #{}.
+
+verify_allocations_output(#{ histogram_start := HistStart,
+ histogram_width := HistWidth },
+ {ok, {HistStart, _UnscannedBytes, ByOrigin}}) ->
+ AllHistograms = lists:flatten([maps:values(ByType) ||
+ ByType <- maps:values(ByOrigin)]),
+
+ %% Do the histograms look alright?
+ HistogramSet = ordsets:from_list(AllHistograms),
+ Verified = [H || H <- HistogramSet,
+ tuple_size(H) =:= HistWidth,
+ hist_sum(H) >= 1],
+ [] = ordsets:subtract(HistogramSet, Verified),
+
+ %% Do we have at least as many blocks as we've generated?
+ BlockCount = lists:foldl(fun(Hist, Acc) ->
+ hist_sum(Hist) + Acc
+ end, 0, AllHistograms),
+ GenTotalBlockCount = ?GENERATED_BLOCK_COUNT,
+ GenSBCBlockCount = ?GENERATED_SBC_BLOCK_COUNT,
+ if
+ BlockCount < GenSBCBlockCount ->
+ ct:fail("Found ~p blocks, required at least ~p (SB)." ,
+ [BlockCount, GenSBCBlockCount]);
+ BlockCount >= GenTotalBlockCount ->
+ ct:pal("Found ~p blocks, expected at least ~p (SB + MB).",
+ [BlockCount, GenTotalBlockCount]);
+ BlockCount < GenTotalBlockCount ->
+ ct:pal("Found ~p blocks, expected at least ~p (SB + MB), but this "
+ "may be due to MBCs being skipped if they're about to be "
+ "scanned just as they're fetched from the carrier pool.",
+ [BlockCount, GenTotalBlockCount])
+ end,
+
+ ok;
+verify_allocations_output(#{}, {error, not_enabled}) ->
+ ok.
+
+%% %% %% %% %% %%
+
+carriers_test(Args, Plain, PerAlloc) ->
+ run_test(Args, fun(Node) ->
+ ok = rpc:call(Node, ?MODULE, test_all_alloc,
+ [fun instrument:carriers/0, Plain]),
+ ok = rpc:call(Node, ?MODULE, test_per_alloc,
+ [fun instrument:carriers/1, PerAlloc]),
+ ok = rpc:call(Node, ?MODULE, test_format,
+ [#{ histogram_start => 1024,
+ histogram_width => 4 },
+ fun instrument:carriers/1,
+ fun verify_carriers_output/2]),
+ ok = rpc:call(Node, ?MODULE, test_abort,
+ [fun erts_internal:gather_carrier_info/1])
+ end).
+
+carriers_enabled(Config) when is_list(Config) ->
+ carriers_test("+Meamax",
+ fun verify_carriers_enabled/1,
+ fun verify_carriers_enabled/2).
+
+carriers_disabled(Config) when is_list(Config) ->
+ carriers_test("+Meamin",
+ fun verify_carriers_disabled/1,
+ fun verify_carriers_disabled/2).
+
+verify_carriers_disabled(_AllocType, Result) ->
+ verify_carriers_disabled(Result).
+
+verify_carriers_disabled({error, not_enabled}) ->
+ ok;
+verify_carriers_disabled({ok, {_HistStart, Carriers}}) ->
+ verify_carriers_disabled_1(Carriers).
+
+verify_carriers_disabled_1([]) ->
+ ok;
+%% literal_alloc, exec_alloc, and temp_alloc can't be disabled, so we have to
+%% accept their presence in carriers_disabled/test_all_alloc.
+verify_carriers_disabled_1([Carrier | Rest]) when
+ element(1, Carrier) =:= literal_alloc;
+ element(1, Carrier) =:= exec_alloc;
+ element(1, Carrier) =:= temp_alloc ->
+ verify_carriers_disabled_1(Rest).
+
+%% exec_alloc only has a carrier if it's actually used.
+verify_carriers_enabled(exec_alloc, _Result) -> ok;
+verify_carriers_enabled(_AllocType, Result) -> verify_carriers_enabled(Result).
+
+verify_carriers_enabled({ok, {_HistStart, Carriers}}) when Carriers =/= [] ->
+ ok.
+
+verify_carriers_output(#{ histogram_start := HistStart,
+ histogram_width := HistWidth },
+ {ok, {HistStart, AllCarriers}}) ->
+
+ %% Do the carriers look alright?
+ CarrierSet = ordsets:from_list(AllCarriers),
+ Verified = [C || {AllocType,
+ TotalSize,
+ UnscannedSize,
+ AllocatedSize,
+ AllocatedCount,
+ InPool,
+ FreeBlockHist} = C <- CarrierSet,
+ is_atom(AllocType),
+ is_integer(TotalSize), TotalSize >= 1,
+ is_integer(UnscannedSize), UnscannedSize < TotalSize,
+ UnscannedSize >= 0,
+ is_integer(AllocatedSize), AllocatedSize < TotalSize,
+ AllocatedSize >= 0,
+ is_integer(AllocatedCount), AllocatedCount =< AllocatedSize,
+ AllocatedCount >= 0,
+ is_boolean(InPool),
+ tuple_size(FreeBlockHist) =:= HistWidth,
+ carrier_block_check(AllocatedCount, FreeBlockHist)],
+ [] = ordsets:subtract(CarrierSet, Verified),
+
+ %% Do we have at least as many carriers as we've generated?
+ CarrierCount = length(AllCarriers),
+ GenSBCCount = ?GENERATED_SBC_BLOCK_COUNT,
+ if
+ CarrierCount < GenSBCCount ->
+ ct:fail("Carrier count is ~p, expected at least ~p (SBC).",
+ [CarrierCount, GenSBCCount]);
+ CarrierCount >= GenSBCCount ->
+ ok
end,
- lists:foldl(
- fun ({TDescr,Addr,Size,Proc}, MinAddr) ->
- true = TDescr /= invalid_type,
- true = is_integer(TDescr),
- true = is_integer(Addr),
- true = is_integer(Size),
- true = Addr >= MinAddr,
- case Proc of
- {0, Number, Serial} ->
- true = is_integer(Number),
- true = is_integer(Serial);
- undefined ->
- ok;
- BadProc ->
- ct:fail({badproc, BadProc})
- end,
- NextMinAddr = Addr+Size,
- true = NextMinAddr =< High,
- NextMinAddr
- end, Low, AL),
- {_, DAL} = instrument:descr(MDS),
- lists:foreach(
- fun ({TDescr,_,_,Proc}) ->
- true = TDescr /= invalid_type,
- true = is_atom(TDescr) orelse is_list(TDescr),
- true = is_pid(Proc) orelse Proc == undefined
- end, DAL),
- ASL = lists:map(fun ({_,A,S,_}) -> {A,S} end, AL),
- ASL = lists:map(fun ({_,A,S,_}) -> {A,S} end, DAL),
- instrument:holes(MDS),
- {comment, "total status - sum of blocks = " ++ integer_to_list(S1-SumBlocks)}.
-
-%% Check that memory data can be read and processed
-'+Mis true'(Config) when is_list(Config) ->
- Node = start_slave("+Mis true"),
- [{total,[{sizes,S1,S2,S3},{blocks,B1,B2,B3}]}]
- = rpc:call(Node, instrument, memory_status, [total]),
- true = S1 =< S2,
- true = S2 =< S3,
- true = B1 =< B2,
- true = B2 =< B3,
- true = is_list(rpc:call(Node,instrument,memory_status,[allocators])),
- true = is_list(rpc:call(Node,instrument,memory_status,[classes])),
- true = is_list(rpc:call(Node,instrument,memory_status,[types])),
+
+ ok;
+verify_carriers_output(#{}, {error, not_enabled}) ->
+ ok.
+
+carrier_block_check(AllocCount, FreeHist) ->
+ %% A carrier must contain at least one block, and th. number of free blocks
+ %% must not exceed the number of allocated blocks + 1.
+ FreeCount = hist_sum(FreeHist),
+
+ (AllocCount + FreeCount) >= 1 andalso FreeCount =< (AllocCount + 1).
+
+%% %% %% %% %% %%
+
+test_all_alloc(Gather, Verify) ->
+ Verify(Gather()),
ok.
+test_per_alloc(Gather, Verify) ->
+ [begin
+ Verify(T, Gather(#{ allocator_types => [T] }))
+ end || T <- erlang:system_info(alloc_util_allocators)],
+ ok.
+
+test_format(#{ allocator_types := _ }, _, _) ->
+ error(badarg);
+test_format(Options0, Gather, Verify) ->
+ %% We limit format checking to binary_alloc since we generated the test
+ %% vectors there.
+ Options = Options0#{ allocator_types => [binary_alloc] },
+ Verify(Options, Gather(Options)),
+ ok.
+
+test_abort(Gather) ->
+ %% There's no way for us to tell whether this actually aborted or ran to
+ %% completion, but it might catch a few segfaults.
+ Runner = self(),
+ Ref = make_ref(),
+ spawn_opt(fun() ->
+ [Gather({Type, SchedId, 1, 1, Ref}) ||
+ Type <- erlang:system_info(alloc_util_allocators),
+ SchedId <- lists:seq(0, erlang:system_info(schedulers))],
+ Runner ! Ref
+ end, [{priority, max}]),
+ receive
+ Ref -> ok
+ end.
+
+hist_sum(H) -> hist_sum_1(H, tuple_size(H), 0).
+hist_sum_1(_H, 0, A) -> A;
+hist_sum_1(H, N, A) -> hist_sum_1(H, N - 1, element(N, H) + A).
+
+%%
+
+run_test(Args0, Test) ->
+ %% Override single-block carrier threshold for binaries to ensure we have
+ %% coverage for that path. generate_test_blocks builds a few binaries that
+ %% crosses this threshold.
+ %%
+ %% We also set the abandon carrier threshold to 70% to provoke more
+ %% activity in the carrier pool.
+ Args = Args0 ++ " +MBsbct 1 +Muacul 70",
+ Node = start_slave(Args),
+
+ ok = rpc:call(Node, ?MODULE, generate_test_blocks, []),
+ ok = Test(Node),
+
+ ok = rpc:call(Node, ?MODULE, churn_memory, []),
+ ok = Test(Node),
+
+ true = test_server:stop_node(Node).
+
start_slave(Args) ->
MicroSecs = erlang:monotonic_time(),
Name = "instr" ++ integer_to_list(MicroSecs),
@@ -112,6 +297,60 @@ start_slave(Args) ->
[{args, "-pa " ++ Pa ++ " " ++ Args}]),
Node.
+generate_test_blocks() ->
+ Runner = self(),
+ Ref = make_ref(),
+ spawn(fun() ->
+ %% We've set the single-block carrier threshold to 1KB so one
+ %% ought to land in a SBC and the other in a MBC. Both are kept
+ %% alive forever.
+ SBCs = [<<I, 0:(1 bsl 10)/unit:8>> ||
+ I <- lists:seq(1, ?GENERATED_SBC_BLOCK_COUNT)],
+ MBCs = [<<I, 0:64/unit:8>> ||
+ I <- lists:seq(1, ?GENERATED_MBC_BLOCK_COUNT)],
+ Runner ! Ref,
+ receive after infinity -> ok end,
+ unreachable ! {SBCs, MBCs}
+ end),
+ receive
+ Ref -> ok
+ end.
-stop_slave(Node) ->
- true = test_server:stop_node(Node).
+churn_memory() ->
+ %% All processes spawned from here on have 'low' priority to avoid starving
+ %% others (e.g. the rpc process) which could cause the test to time out.
+ [begin
+ churn_list_to_binary(),
+ churn_processes(),
+ churn_ets()
+ end || _ <- lists:seq(1, erlang:system_info(schedulers))],
+ ok.
+
+churn_processes() ->
+ Pid = spawn_opt(fun churn_processes/0, [{priority, low}]),
+ [Pid ! <<I, 0:128/unit:8>> || I <- lists:seq(1, 128)].
+
+%% Nearly all types have a few allocations at all times but sl_alloc is
+%% often empty. list_to_binary on large inputs will yield and spill the
+%% state into an 'estack' which is allocated through sl_alloc.
+%%
+%% This is inherently unstable so we skip the verification step for this
+%% type, but there's still a point to hammering it.
+churn_list_to_binary() ->
+ List = binary_to_list(<<0:(1 bsl 20)/unit:8>>),
+ spawn_opt(fun() -> churn_list_to_binary_1(List) end, [{priority, low}]).
+
+churn_list_to_binary_1(List) ->
+ _ = id(list_to_binary(List)),
+ churn_list_to_binary_1(List).
+
+churn_ets() ->
+ spawn_opt(fun() -> churn_ets_1(ets:new(gurka, [])) end, [{priority, low}]).
+
+churn_ets_1(Tab) ->
+ ets:insert(Tab, {gaffel, lists:seq(1, 16)}),
+ ets:delete_all_objects(Tab),
+ churn_ets_1(Tab).
+
+id(I) ->
+ I.
diff --git a/lib/tools/test/lcnt_SUITE.erl b/lib/tools/test/lcnt_SUITE.erl
index af3ce88fdd..8a2f6bfc89 100644
--- a/lib/tools/test/lcnt_SUITE.erl
+++ b/lib/tools/test/lcnt_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,6 +30,8 @@
t_conflicts/1,
t_locations/1,
t_swap_keys/1,
+ t_implicit_start/1,
+ t_crash_before_collect/1,
smoke_lcnt/1]).
init_per_testcase(_Case, Config) ->
@@ -44,8 +46,8 @@ suite() ->
{timetrap,{minutes,4}}].
all() ->
- [t_load, t_conflicts, t_locations, t_swap_keys,
- smoke_lcnt].
+ [t_load, t_conflicts, t_locations, t_swap_keys, t_implicit_start,
+ t_crash_before_collect, smoke_lcnt].
%%----------------------------------------------------------------------
%% Tests
@@ -149,12 +151,20 @@ t_swap_keys_file([File|Files]) ->
ok = lcnt:stop(),
t_swap_keys_file(Files).
+%% Prior to OTP-14913 this would crash with 'noproc' as the lcnt server hadn't
+%% been started yet.
+t_implicit_start(Config) when is_list(Config) ->
+ ok = lcnt:conflicts().
+
+t_crash_before_collect(Config) when is_list(Config) ->
+ {ok, _} = lcnt:start(),
+ ok = lcnt:information().
+
%% Simple smoke test of actual lock-counting, if running on
%% a run-time with lock-counting enabled.
-
smoke_lcnt(Config) ->
- case erlang:system_info(build_type) of
- lcnt ->
+ case catch erlang:system_info(lock_counting) of
+ true ->
do_smoke_lcnt(Config);
_ ->
{skip,"Lock counting is not enabled"}
diff --git a/lib/tools/test/make_SUITE.erl b/lib/tools/test/make_SUITE.erl
index 2f6fe1c732..02da4f4ace 100644
--- a/lib/tools/test/make_SUITE.erl
+++ b/lib/tools/test/make_SUITE.erl
@@ -36,7 +36,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [make_all, make_files, recompile_on_changed_include,
+ [make_all, make_files, load, netload, recompile_on_changed_include,
emake_opts, {group, otp_6057}].
groups() ->
@@ -55,6 +55,21 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
otp_6057_end(Config).
+init_per_testcase(_,Config) ->
+ Config.
+
+end_per_testcase(netload,_Config) ->
+ %% Stop slave - in case of failure
+ Nodes = nodes(),
+ case [N || N <- Nodes,
+ "make_SUITE_netload" == hd(string:lexemes(atom_to_list(N),"@"))] of
+ [Node] ->
+ ct_slave:stop(Node);
+ _ ->
+ ok
+ end;
+end_per_testcase(_,_Config) ->
+ ok.
test_files() -> ["test1", "test2", "test3", "test4"].
@@ -83,6 +98,32 @@ make_files(Config) when is_list(Config) ->
ensure_no_messages(),
ok.
+load(Config) ->
+ Current = prepare_data_dir(Config),
+ code:purge(test1),
+ code:delete(test1),
+ false = code:is_loaded(test1),
+ up_to_date = make:files([test1], [load]),
+ {file,_} = code:is_loaded(test1),
+ file:set_cwd(Current),
+ ensure_no_messages(),
+ ok.
+
+netload(Config) ->
+ Current = prepare_data_dir(Config),
+ code:purge(test1),
+ code:delete(test1),
+ false = code:is_loaded(test1),
+ {ok,Node} = ct_slave:start(make_SUITE_netload),
+ up_to_date = make:files([test1], [netload]),
+ timer:sleep(1000), % async, so give some time
+ {file,F} = code:is_loaded(test1),
+ {file,F} = rpc:call(Node,code,is_loaded,[test1]),
+ ct_slave:stop(Node),
+ file:set_cwd(Current),
+ ensure_no_messages(),
+ ok.
+
recompile_on_changed_include(Config) ->
Current = prepare_data_dir(Config),
diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl
index 057449d4a2..da4f56c09b 100644
--- a/lib/tools/test/xref_SUITE.erl
+++ b/lib/tools/test/xref_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -50,7 +50,8 @@
-export([analyze/1, basic/1, md/1, q/1, variables/1, unused_locals/1]).
--export([format_error/1, otp_7423/1, otp_7831/1, otp_10192/1, otp_13708/1]).
+-export([format_error/1, otp_7423/1, otp_7831/1, otp_10192/1, otp_13708/1,
+ otp_14464/1, otp_14344/1]).
-import(lists, [append/2, flatten/1, keysearch/3, member/2, sort/1, usort/1]).
@@ -81,8 +82,10 @@ groups() ->
update, deprecated, trycatch, fun_mfa,
fun_mfa_r14, fun_mfa_vars, qlc]},
{analyses, [],
+
[analyze, basic, md, q, variables, unused_locals]},
- {misc, [], [format_error, otp_7423, otp_7831, otp_10192, otp_13708]}].
+ {misc, [], [format_error, otp_7423, otp_7831, otp_10192, otp_13708,
+ otp_14464, otp_14344]}].
init_per_suite(Conf) when is_list(Conf) ->
@@ -1109,27 +1112,16 @@ read_expected(Version) ->
{POS7+2,{FF,{erlang,spawn_opt,4}}},
{POS8+1,{FF,{hej,san,1}}},
{POS8+4,{FF,{a,b,1}}},
- {POS8+4,{FF,{erlang,apply,2}}},
- {POS8+5,{FF,{erlang,apply,2}}},
{POS8+6,{FF,{m,f,1}}},
{POS9+1,{FF,{read,bi,0}}},
{POS9+2,{FF,{a,b,1}}},
- {POS9+2,{FF,{erlang,apply,2}}},
- {POS9+3,{FF,{erlang,apply,2}}},
- {POS9+4,{FF,{erlang,apply,2}}},
{POS9+4,{FF,{erlang,not_a_function,1}}},
{POS9+5,{FF,{mod,func,2}}},
{POS9+6,{FF,{erlang,apply,1}}},
- {POS9+7,{FF,{erlang,apply,2}}},
{POS9+7,{FF,{math,add3,1}}},
{POS9+8,{FF,{q,f,1}}},
- {POS10+4,{FF,{erlang,apply,2}}},
{POS10+5,{FF,{mod1,fun1,1}}},
- {POS11+6,{FF,{erlang,apply,2}}},
- {POS12+1,{FF,{erlang,apply,2}}},
- {POS12+4,{FF,{erlang,apply,2}}},
{POS12+5,{FF,{m3,f3,2}}},
- {POS12+7,{FF,{erlang,apply,2}}},
{POS13+1,{FF,{dm,df,1}}},
{POS13+6,{{read,bi,0},{foo,module_info,0}}},
{POS13+7,{{read,bi,0},{read,module_info,0}}},
@@ -1159,15 +1151,26 @@ read_expected(Version) ->
{POS3+3, {FF,{erlang,spawn_link,3}}},
{POS3+4, {FF,{erlang,spawn_link,3}}},
{POS6+4, {FF,{erlang,spawn,3}}},
+ {POS8+4,{FF,{erlang,apply,2}}},
+ {POS8+5,{FF,{erlang,apply,2}}},
{POS8+6,{FF,{erlang,apply,3}}},
{POS8+7,{FF,{erlang,apply,3}}},
{POS9+1,{FF,{erlang,apply,3}}},
+ {POS9+2,{FF,{erlang,apply,2}}},
+ {POS9+3,{FF,{erlang,apply,2}}},
+ {POS9+4,{FF,{erlang,apply,2}}},
{POS9+5,{FF,{erlang,apply,3}}},
+ {POS9+7,{FF,{erlang,apply,2}}},
+ {POS10+4,{FF,{erlang,apply,2}}},
{POS11+1,{FF,{erlang,apply,3}}},
{POS11+2,{FF,{erlang,apply,3}}},
{POS11+3,{FF,{erlang,apply,3}}},
{POS11+4,{FF,{erlang,apply,3}}},
+ {POS11+6,{FF,{erlang,apply,2}}},
+ {POS12+1,{FF,{erlang,apply,2}}},
+ {POS12+4,{FF,{erlang,apply,2}}},
{POS12+5,{FF,{erlang,apply,3}}},
+ {POS12+7,{FF,{erlang,apply,2}}},
{POS12+8,{FF,{erlang,apply,3}}},
{POS13+5, {{read,bi,0},{erlang,length,1}}},
{POS14+3, {{read,bi,0},{erlang,length,1}}}],
@@ -2230,18 +2233,18 @@ variables(Conf) when is_list(Conf) ->
{{error, _, _}, _} = xref_base:variables(S108, [{verbose,false}]),
{ok, S109} = xref_base:set_library_path(S108, [], [{verbose,false}]),
- Tabs = length(ets:all()),
+ NoOfTables = erlang:system_info(ets_count),
{ok, S110} = eval("Eplus := closure E, TT := Eplus",
'closure()', S109),
{{ok, [{user, ['Eplus','TT']}]}, S111} = xref_base:variables(S110),
{ok, S112} = xref_base:forget(S111, ['TT','Eplus']),
- true = Tabs =:= length(ets:all()),
+ true = NoOfTables =:= erlang:system_info(ets_count),
{ok, NS0} = eval("Eplus := closure E", 'closure()', S112),
{{ok, [{user, ['Eplus']}]}, NS} = xref_base:variables(NS0),
ok = xref_base:delete(NS),
- true = Tabs =:= length(ets:all()),
+ true = NoOfTables =:= erlang:system_info(ets_count),
ok = file:delete(Beam),
ok.
@@ -2396,7 +2399,6 @@ otp_10192(Conf) when is_list(Conf) ->
xref:stop(s),
ok.
-%% OTP-10192. Allow filenames with character codes greater than 126.
otp_13708(Conf) when is_list(Conf) ->
{ok, _} = start(s),
ok = xref:set_default(s, [{verbose, true}]),
@@ -2409,6 +2411,60 @@ otp_13708(Conf) when is_list(Conf) ->
ok = xref:set_library_path(s, [Dir], [{verbose, true}]),
xref:stop(s).
+%% OTP-14464. Unicode atoms.
+otp_14464(Conf) when is_list(Conf) ->
+ Dir = ?copydir,
+
+ File1 = fname(Dir, "a.erl"),
+ MFile1 = fname(Dir, "a"),
+ Beam1 = fname(Dir, "a.beam"),
+ Test1 = "-module(a).
+ -export([ärlig/0, 'кlирилли́ческий атомB'/0]).
+
+ ärlig() ->
+ 'кlирилли́ческий атомB'.
+
+ 'кlирилли́ческий атомB'() ->
+ foo.
+ ",
+ ok = file:write_file(File1, unicode:characters_to_binary(Test1)),
+ {ok, a} = compile:file(File1, [debug_info,{outdir,Dir}]),
+
+ {ok, _} = xref:start(s),
+ {ok, a} = xref:add_module(s, MFile1),
+
+ {ok, [{a,ärlig,0}]} = xref:q(s, 'a:"ärlig"/0'),
+ {ok, [{a,'кlирилли́ческий атомB',0}]} =
+ xref:q(s, 'a:"кlирилли́ческий атомB"/0'),
+
+ xref:stop(s),
+ ok = file:delete(File1),
+ ok = file:delete(Beam1).
+
+%% OTP-14344. -on_load() attribute.
+otp_14344(Conf) when is_list(Conf) ->
+ Dir = ?copydir,
+
+ File1 = fname(Dir, "a.erl"),
+ MFile1 = fname(Dir, "a"),
+ Beam1 = fname(Dir, "a.beam"),
+ Test1 = <<"-module(a).
+ -on_load(doit/0).
+ doit() -> ok.
+ ">>,
+ ok = file:write_file(File1, Test1),
+ {ok, a} = compile:file(File1, [debug_info,{outdir,Dir}]),
+
+ {ok, _} = xref:start(s),
+ {ok, a} = xref:add_module(s, MFile1),
+
+ {ok, [{a,doit,0}]} = xref:q(s, "OL"),
+ {ok, []} = xref:analyze(s, locals_not_used),
+
+ xref:stop(s),
+ ok = file:delete(File1),
+ ok = file:delete(Beam1).
+
%%%
%%% Utilities
%%%
@@ -2483,7 +2539,8 @@ add_module(S, XMod, DefAt, X, LCallAt, XCallAt, XC, LC) ->
Depr0 = {[], [], [], []},
DBad = [],
Depr = {Depr0,DBad},
- Data = {DefAt, LCallAt, XCallAt, LC, XC, X, Attr, Depr},
+ OL = [],
+ Data = {DefAt, LCallAt, XCallAt, LC, XC, X, Attr, Depr, OL},
Unres = [],
{ok, _Module, _Bad, State} =
xref_base:do_add_module(S, XMod, Unres, Data),
@@ -2564,6 +2621,9 @@ functions_mode_check(S, Info) ->
%% UU subset F
{ok, []} = xref:q(S, "UU - F"),
+ %% OL subset F
+ {ok, []} = xref:q(S, "OL - F"),
+
%% ME = (Mod) E
{ok, ME} = xref:q(S, "ME"),
{ok, ME} = xref:q(S, "(Mod) E"),
diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk
index 8aa7814e1d..1bebb1c421 100644
--- a/lib/tools/vsn.mk
+++ b/lib/tools/vsn.mk
@@ -1 +1 @@
-TOOLS_VSN = 2.10
+TOOLS_VSN = 3.0.1
diff --git a/lib/wx/api_gen/README b/lib/wx/api_gen/README
index dd0c49d227..200ef4c856 100644
--- a/lib/wx/api_gen/README
+++ b/lib/wx/api_gen/README
@@ -3,12 +3,13 @@ API GENERATION:
Users of wxErlang should not normally need to regenerate the generated code,
as it is checked in by wxErlang developers, when changes are made.
- Code checked in is currently generated from wxwidgets 2.8.10.
+ Code checked in is currently generated from wxwidgets 2.8.12.
REQUIREMENTS:
The code generation requires doxygen (1.4.6) which is
used to parse wxWidgets c++ headers and generate xml files (in
wx_xml/).
+ 2017-08-16 doxygen 1.8.11 is working with WXGTK_DIR=/ldisk/src/wxWidgets-2.8.12/include
2012-02-09 doxygen 1.7.4 is working fine
diff --git a/lib/wx/api_gen/gen_util.erl b/lib/wx/api_gen/gen_util.erl
index 5e2f405498..d27a9ae548 100644
--- a/lib/wx/api_gen/gen_util.erl
+++ b/lib/wx/api_gen/gen_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -106,8 +106,8 @@ check_diff(Diff) ->
throw:_ -> diff;
error:{badmatch,_} ->
diff;
- _:What ->
- io:format("~p:~p: ~p ~p~n", [?MODULE,?LINE, What, erlang:get_stacktrace()]),
+ _:What:Stacktrace ->
+ io:format("~p:~p: ~p ~p~n", [?MODULE,?LINE, What, Stacktrace]),
diff
end.
diff --git a/lib/wx/api_gen/gl_gen.erl b/lib/wx/api_gen/gl_gen.erl
index 7e3766a43b..c0509ed802 100644
--- a/lib/wx/api_gen/gl_gen.erl
+++ b/lib/wx/api_gen/gl_gen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -47,9 +47,9 @@ safe(What, QuitOnErr) ->
What(),
io:format("Completed successfully~n~n", []),
QuitOnErr andalso gen_util:halt(0)
- catch Err:Reason ->
+ catch Err:Reason:Stacktrace ->
io:format("Error ~p: ~p:~p~n ~p~n",
- [get(current_func),Err,Reason,erlang:get_stacktrace()]),
+ [get(current_func),Err,Reason,Stacktrace]),
(catch gen_util:close()),
timer:sleep(1999),
QuitOnErr andalso gen_util:halt(1)
diff --git a/lib/wx/api_gen/gl_gen_erl.erl b/lib/wx/api_gen/gl_gen_erl.erl
index 3ad14825dd..e62d182a37 100644
--- a/lib/wx/api_gen/gl_gen_erl.erl
+++ b/lib/wx/api_gen/gl_gen_erl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,6 +35,9 @@
open_write/1, open_write/2, close/0, erl_copyright/0, w/2,
args/3, args/4, strip_name/2]).
+
+-define(HTTP_TOP, "https://www.khronos.org/registry/OpenGL-Refpages/").
+
gl_defines(Defs) ->
open_write("../include/gl.hrl"),
erl_copyright(),
@@ -96,7 +99,7 @@ gl_api(Fs) ->
w("~n%% OPENGL API~n~n", []),
w("%% This file is generated DO NOT EDIT~n~n", []),
w("%% @doc Standard OpenGL api.~n", []),
- w("%% See <a href=\"http://www.opengl.org/sdk/docs/man/\">www.opengl.org</a>~n",[]),
+ w("%% See <a href=\""++ ?HTTP_TOP ++ "\">www.khronos.org</a>~n",[]),
w("%%~n", []),
w("%% Booleans are represented by integers 0 and 1.~n~n", []),
@@ -158,7 +161,7 @@ glu_api(Fs) ->
w("~n%% OPENGL UTILITY API~n~n", []),
w("%% This file is generated DO NOT EDIT~n~n", []),
w("%% @doc A part of the standard OpenGL Utility api.~n", []),
- w("%% See <a href=\"http://www.opengl.org/sdk/docs/man/\">www.opengl.org</a>~n",[]),
+ w("%% See <a href=\""++ ?HTTP_TOP ++ "\">www.khronos.org</a>~n",[]),
w("%%~n", []),
w("%% Booleans are represented by integers 0 and 1.~n~n", []),
@@ -243,8 +246,8 @@ gen_types(Where) ->
gen_export(F) ->
try gen_export_1(F)
- catch E:R ->
- io:format("Crash ~p:~p in ~p ~n",[E,R, erlang:get_stacktrace()]),
+ catch E:R:S ->
+ io:format("Crash ~p:~p in ~p ~n",[E,R,S]),
io:format("Func = ~p~n ~p", [F, get(F)])
end.
@@ -300,8 +303,7 @@ gen_doc(Name0, Alt, Export) ->
Name = doc_name(Name0, Alt),
case get({doc, Name}) of
undefined ->
- GLDoc = "http://www.opengl.org/sdk/docs/man/xhtml/",
- case parse_doc(Name, _Dir1 ="gl_man4", _Dir2="gl_man2") of
+ case parse_doc(Name, Dir1 ="gl_man4", Dir2="gl_man2") of
{error, _} ->
case reverse(Name) of
"BRA" ++ _ -> ok;
@@ -311,13 +313,18 @@ gen_doc(Name0, Alt, Export) ->
%% [Name, Name0, Dir1, Dir2]),
ok
end,
- w("%% @doc ~s~n%%~n%% See <a href=\"~s~s.xml\">external</a> documentation.~n",
- [Name, GLDoc, Name]);
- Doc ->
+ w("%% @doc ~s~n%%~n"
+ "%% See <a href=\"~s\">external</a> documentation.~n",
+ [Name, ?HTTP_TOP]);
+ {Found, Doc} ->
+ {Dir,Ext} = case Found of
+ Dir1 -> {"gl4/html", "xhtml"};
+ Dir2 -> {"gl2.1/xhtml", "xml"}
+ end,
put({doc, Name}, Export),
format_doc(Doc, ?LINE_LEN),
- w("~n%%~n%% See <a href=\"~s~s.xml\">external</a> documentation.~n",
- [GLDoc, Name])
+ w("~n%%~n%% See <a href=\"~s~s/~s.~s\">external</a> documentation.~n",
+ [?HTTP_TOP, Dir, Name, Ext])
end;
Where ->
w("%% @doc ~n", []),
@@ -327,9 +334,12 @@ gen_doc(Name0, Alt, Export) ->
parse_doc(Name, Dir1, Dir2) ->
case gl_scan_doc:file(filename:join(Dir1, Name++".xml"), []) of
{error, {_, "no such" ++ _}} ->
- gl_scan_doc:file(filename:join(Dir2, Name++".xml"), []);
+ case gl_scan_doc:file(filename:join(Dir2, Name++".xml"), []) of
+ {error, _} = Err -> Err;
+ Doc -> {Dir2, Doc}
+ end;
Doc ->
- Doc
+ {Dir1, Doc}
end.
format_doc(Strs, Count) when Count < 0 ->
@@ -479,8 +489,8 @@ doc_return_types2(T, Ps) ->
doc_arg_type(#arg{name=Name,type=T}) ->
try
erl_arg_name(Name) ++ " :: " ++ doc_arg_type2(T)
- catch _:Error ->
- io:format("Error spec: ~p ~p~n~p~n",[Name, Error, erlang:get_stacktrace()]),
+ catch _:Error:Stacktrace ->
+ io:format("Error spec: ~p ~p~n~p~n",[Name, Error, Stacktrace]),
exit(error)
end.
diff --git a/lib/wx/api_gen/gl_scan_doc.erl b/lib/wx/api_gen/gl_scan_doc.erl
index 0a1c25ae13..c793d4940e 100644
--- a/lib/wx/api_gen/gl_scan_doc.erl
+++ b/lib/wx/api_gen/gl_scan_doc.erl
@@ -2,7 +2,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-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.
@@ -209,6 +209,10 @@ gen_output({startElement, _Uri, "para", _QName, _Attributes}, #state{gen_output=
State#state{str=[para|Str]}
end;
+gen_output({endElement, _Uri, "para", _QName}, #state{gen_output=true, str=Str} = State) ->
+ %% Pick only the first paragraph in the descriptions
+ State#state{gen_output=false};
+
%% gen_output({startElement, _Uri, What, _QName, _Attributes}, State) ->
%% io:format("Skipped ~s~n",[What]),
%% State;
diff --git a/lib/wx/api_gen/wx_doxygen.conf b/lib/wx/api_gen/wx_doxygen.conf
index a96db00254..d6a0e9e6a1 100644
--- a/lib/wx/api_gen/wx_doxygen.conf
+++ b/lib/wx/api_gen/wx_doxygen.conf
@@ -71,12 +71,12 @@ WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
-INPUT = @WXGTK_DIR@/wx/ wx_extra/
+INPUT = @WXGTK_DIR@/wx/ @WXGTK_DIR@/../contrib/include/wx/stc/ wx_extra/
# FILE_PATTERNS = *.h
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
-EXCLUDE_PATTERNS = mac/* mgl/* msw/* os2/* x11/* gtk1/* cocoa/* motif/* msdos/* palmos/* private/* vms_x_fix.h
+EXCLUDE_PATTERNS = */mac/* */dfb/* */mgl/* */msw/* */os2/* */x11/* */gtk1/* */cocoa/* */motif/* */msdos/* */palmos/* */private/* */univ/* */vms_x_fix.h
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
@@ -155,8 +155,6 @@ MAN_LINKS = NO
#---------------------------------------------------------------------------
GENERATE_XML = YES
XML_OUTPUT = ./wx_xml/
-XML_SCHEMA =
-XML_DTD =
XML_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
diff --git a/lib/wx/api_gen/wx_extra/wxGraphicsRenderer.c_src b/lib/wx/api_gen/wx_extra/wxGraphicsRenderer.c_src
new file mode 100644
index 0000000000..4718525dd6
--- /dev/null
+++ b/lib/wx/api_gen/wx_extra/wxGraphicsRenderer.c_src
@@ -0,0 +1,58 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+
+<<CreatePen
+case ~s: { // wxGraphicsRenderer::CreatePen taylormade
+ wxGraphicsRenderer *This = (wxGraphicsRenderer *) getPtr(bp,memenv); bp += 4;
+ wxPen *pen = (wxPen *) getPtr(bp,memenv); bp += 4;
+ if(!This) throw wxe_badarg(0);
+#if !wxCHECK_VERSION(3,1,1)
+ wxGraphicsPen * Result = new wxGraphicsPen(This->CreatePen(*pen)); newPtr((void *) Result,4, memenv);
+ rt.addRef(getRef((void *)Result,memenv), "wxGraphicsPen");
+ break;
+#else
+ wxGraphicsPenInfo info = wxGraphicsPenInfo()
+ .Colour(pen->GetColour())
+ .Width(pen->GetWidth())
+ .Style(pen->GetStyle())
+ .Join(pen->GetJoin())
+ .Cap(pen->GetCap())
+ ;
+
+ if ( info.GetStyle() == wxPENSTYLE_USER_DASH )
+ {
+ wxDash *dashes;
+ if ( int nb_dashes = pen->GetDashes(&dashes) )
+ info.Dashes(nb_dashes, dashes);
+ }
+
+ if ( info.GetStyle() == wxPENSTYLE_STIPPLE )
+ {
+ if ( wxBitmap* const stipple = pen->GetStipple() )
+ info.Stipple(*stipple);
+ }
+ wxGraphicsPen * Result = new wxGraphicsPen(This->CreatePen(info));
+ newPtr((void *) Result,4, memenv);
+ rt.addRef(getRef((void *)Result,memenv), "wxGraphicsPen");
+ break;
+#endif
+}
+CreatePen>>
diff --git a/lib/wx/api_gen/wx_gen.erl b/lib/wx/api_gen/wx_gen.erl
index 6979a600f3..cec6ac9ccf 100644
--- a/lib/wx/api_gen/wx_gen.erl
+++ b/lib/wx/api_gen/wx_gen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -47,9 +47,9 @@ safe(What, QuitOnErr) ->
What(),
io:format("Completed successfully~n~n", []),
QuitOnErr andalso gen_util:halt(0)
- catch Err:Reason ->
+ catch Err:Reason:Stacktrace ->
io:format("Error in ~p ~p~n", [get(current_class),get(current_func)]),
- erlang:display({Err,Reason, erlang:get_stacktrace()}),
+ erlang:display({Err,Reason,Stacktrace}),
catch gen_util:close(),
QuitOnErr andalso gen_util:halt(1)
end.
@@ -93,9 +93,10 @@ mangle_info(E={not_const,List}) ->
put(not_const, [atom_to_list(M) || M <- List]),
E;
mangle_info(E={gvars,List}) ->
- A2L = fun({N,{T,C}}) -> {atom_to_list(N), {T,atom_to_list(C)}};
+ A2L = fun({N,{test_if,C}}) -> {atom_to_list(N), {test_if,C}};
+ ({N,{T,C}}) -> {atom_to_list(N), {T,atom_to_list(C)}};
({N,C}) -> {atom_to_list(N), atom_to_list(C)}
- end,
+ end,
put(gvars, map(A2L,List)),
E;
mangle_info({class,CN,P,O,FL}) ->
@@ -501,10 +502,11 @@ parse_member2(_, _,M0) ->
M0.
add_param(InParam, Opts, M0) ->
- Param0 = case InParam#param.name of
- undefined -> InParam#param{name="val"};
+ Param0 = case {InParam#param.name, InParam#param.type} of
+ {undefined, void} -> InParam#param{where=nowhere};
+ {undefined,_} -> InParam#param{name="val"};
_ -> InParam
- end,
+ end,
Param = case Param0#param.type of
#type{base={comp,_,_Comp}} -> Param0;
#type{base={class,_Class}} -> Param0;
diff --git a/lib/wx/api_gen/wx_gen_cpp.erl b/lib/wx/api_gen/wx_gen_cpp.erl
index 573abfa9b8..70a3530526 100644
--- a/lib/wx/api_gen/wx_gen_cpp.erl
+++ b/lib/wx/api_gen/wx_gen_cpp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1127,6 +1127,15 @@ build_gvar({Name, {address,Class}, _Id}, Cnt) ->
w(" rt.addAtom(\"~s\"); rt.addRef(getRef((void *)&~s,memenv), \"~s\");~n",[Name,Name,Class]),
w(" rt.addTupleCount(2);~n"),
Cnt+1;
+build_gvar({Name, {test_if,Test}, _Id}, Cnt) ->
+ w("#if ~s~n", [Test]),
+ w(" rt.addAtom(\"~s\"); rt.addInt(~s);~n", [Name, Name]),
+ w(" rt.addTupleCount(2);~n"),
+ w("#else~n", []),
+ w(" rt.addAtom(\"~s\"); rt.addAtom(\"undefined\");~n", [Name]),
+ w(" rt.addTupleCount(2);~n"),
+ w("#endif~n", []),
+ Cnt+1;
build_gvar({Name, Class, _Id}, Cnt) ->
w(" rt.addAtom(\"~s\"); rt.addRef(getRef((void *)~s,memenv),\"~s\");~n",[Name,Name,Class]),
w(" rt.addTupleCount(2);~n"),
diff --git a/lib/wx/api_gen/wx_gen_erl.erl b/lib/wx/api_gen/wx_gen_erl.erl
index e272c08d90..797533309b 100644
--- a/lib/wx/api_gen/wx_gen_erl.erl
+++ b/lib/wx/api_gen/wx_gen_erl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1106,7 +1106,7 @@ gen_enums_ints() ->
w("-define(wxDefaultSize, {-1,-1}).~n", []),
w("-define(wxDefaultPosition, {-1,-1}).~n", []),
w("~n%% Global Variables~n", []),
- [w("-define(~s, wxe_util:get_const(~s)).~n", [Gvar, Gvar]) ||
+ [w("-define(~s, wxe_util:get_const(~s)).~n", [qoute_atom(Gvar), qoute_atom(Gvar)]) ||
{Gvar,_,_Id} <- get(gvars)],
w("~n%% Enum and defines~n", []),
foldl(fun(Enum= #enum{vals=Vals}, Done) when Vals =/= [] ->
@@ -1115,6 +1115,11 @@ gen_enums_ints() ->
end, gb_sets:empty(), lists:sort(Enums)),
close().
+qoute_atom([Char|_]=Str) when Char < $a ->
+ "'" ++ Str ++ "'";
+qoute_atom(Str) ->
+ Str.
+
build_enum_ints(#enum{from=From, vals=Vals},Done) ->
case From of
{File, undefined, [$@|_]} ->
diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf
index a0dfa61dd1..c1b55b6875 100644
--- a/lib/wx/api_gen/wxapi.conf
+++ b/lib/wx/api_gen/wxapi.conf
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -87,7 +87,27 @@
{wxNullPen, {address,wxPen}},
{wxNullBrush, {address,wxBrush}},
{wxNullPalette, {address,wxPalette}},
- {wxNullFont, {address,wxFont}}]}.
+ {wxNullFont, {address,wxFont}},
+
+ %% New enums needed for gl contexts not static numbers
+ {'WX_GL_SAMPLE_BUFFERS', {test_if, "wxCHECK_VERSION(3,0,0)"}},
+ {'WX_GL_SAMPLES', {test_if, "wxCHECK_VERSION(3,0,0)"}},
+ {'WX_GL_FRAMEBUFFER_SRGB', {test_if, "wxCHECK_VERSION(3,1,0)"}},
+ {'WX_GL_CORE_PROFILE', {test_if, "wxCHECK_VERSION(3,0,3)"}},
+ {'WX_GL_MAJOR_VERSION', {test_if, "wxCHECK_VERSION(3,0,3)"}},
+ {'WX_GL_MINOR_VERSION', {test_if, "wxCHECK_VERSION(3,0,3)"}},
+ {'wx_GL_COMPAT_PROFILE', {test_if, "wxCHECK_VERSION(3,1,0)"}},
+ {'WX_GL_FORWARD_COMPAT', {test_if, "wxCHECK_VERSION(3,1,0)"}},
+ {'WX_GL_ES2', {test_if, "wxCHECK_VERSION(3,1,0)"}},
+ {'WX_GL_DEBUG', {test_if, "wxCHECK_VERSION(3,1,0)"}},
+ {'WX_GL_ROBUST_ACCESS', {test_if, "wxCHECK_VERSION(3,1,0)"}},
+ {'WX_GL_NO_RESET_NOTIFY', {test_if, "wxCHECK_VERSION(3,1,0)"}},
+ {'WX_GL_LOSE_ON_RESET', {test_if, "wxCHECK_VERSION(3,1,0)"}},
+ {'WX_GL_RESET_ISOLATION', {test_if, "wxCHECK_VERSION(3,1,0)"}},
+ {'WX_GL_RELEASE_FLUSH', {test_if, "wxCHECK_VERSION(3,1,0)"}},
+ {'WX_GL_RELEASE_NONE', {test_if, "wxCHECK_VERSION(3,1,0)"}}
+ ]}.
+
{enum, wxBackgroundStyle, "wxBG_STYLE_"}.
{enum, wxWindowVariant, "wxWINDOW_VARIANT_"}.
{enum, wxBitmapType, "wxBITMAP_TYPE_"}.
@@ -401,8 +421,8 @@
['~wxGraphicsContext',
'Create', %%CreateFromNative CreateFromNativeWindow
'CreatePen','CreateBrush',
- {'CreateRadialGradientBrush', [{deprecated, "!wxCHECK_VERSION(2,9,0)"}]},
- {'CreateLinearGradientBrush', [{deprecated, "!wxCHECK_VERSION(2,9,0)"}]},
+ 'CreateRadialGradientBrush',
+ 'CreateLinearGradientBrush',
'CreateFont','CreateMatrix',
'CreatePath','Clip','ResetClip',
'DrawBitmap','DrawEllipse','DrawIcon',
@@ -433,7 +453,8 @@
{class, wxGraphicsRenderer, object, [{ifdef, wxUSE_GRAPHICS_CONTEXT}],
['GetDefaultRenderer','CreateContext',
%%'CreateContextFromNativeContext', 'CreateContextFromNativeWindow',
- 'CreatePen','CreateBrush',
+ {'CreatePen', [{where, taylormade}]},
+ 'CreateBrush',
{'CreateLinearGradientBrush', [{deprecated, "!wxCHECK_VERSION(2,9,0)"}]},
{'CreateRadialGradientBrush', [{deprecated, "!wxCHECK_VERSION(2,9,0)"}]},
'CreateFont',
diff --git a/lib/wx/c_src/gen/wxe_funcs.cpp b/lib/wx/c_src/gen/wxe_funcs.cpp
index 5425e9f3cb..a7bac4cf9d 100644
--- a/lib/wx/c_src/gen/wxe_funcs.cpp
+++ b/lib/wx/c_src/gen/wxe_funcs.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -6177,7 +6177,6 @@ case wxGraphicsContext_CreateBrush: { // wxGraphicsContext::CreateBrush
rt.addRef(getRef((void *)Result,memenv), "wxGraphicsBrush");
break;
}
-#if !wxCHECK_VERSION(2,9,0)
case wxGraphicsContext_CreateRadialGradientBrush: { // wxGraphicsContext::CreateRadialGradientBrush
wxGraphicsContext *This = (wxGraphicsContext *) getPtr(bp,memenv); bp += 4;
bp += 4; /* Align */
@@ -6201,8 +6200,6 @@ case wxGraphicsContext_CreateRadialGradientBrush: { // wxGraphicsContext::Create
rt.addRef(getRef((void *)Result,memenv), "wxGraphicsBrush");
break;
}
-#endif
-#if !wxCHECK_VERSION(2,9,0)
case wxGraphicsContext_CreateLinearGradientBrush: { // wxGraphicsContext::CreateLinearGradientBrush
wxGraphicsContext *This = (wxGraphicsContext *) getPtr(bp,memenv); bp += 4;
bp += 4; /* Align */
@@ -6225,7 +6222,6 @@ case wxGraphicsContext_CreateLinearGradientBrush: { // wxGraphicsContext::Create
rt.addRef(getRef((void *)Result,memenv), "wxGraphicsBrush");
break;
}
-#endif
case wxGraphicsContext_CreateFont: { // wxGraphicsContext::CreateFont
wxColour col= *wxBLACK;
wxGraphicsContext *This = (wxGraphicsContext *) getPtr(bp,memenv); bp += 4;
@@ -7014,13 +7010,41 @@ case wxGraphicsRenderer_CreateContext_1_0: { // wxGraphicsRenderer::CreateContex
rt.addRef(getRef((void *)Result,memenv), "wxGraphicsContext");
break;
}
-case wxGraphicsRenderer_CreatePen: { // wxGraphicsRenderer::CreatePen
+
+case wxGraphicsRenderer_CreatePen: { // wxGraphicsRenderer::CreatePen taylormade
wxGraphicsRenderer *This = (wxGraphicsRenderer *) getPtr(bp,memenv); bp += 4;
wxPen *pen = (wxPen *) getPtr(bp,memenv); bp += 4;
if(!This) throw wxe_badarg(0);
- wxGraphicsPen * Result = new wxGraphicsPen(This->CreatePen(*pen)); newPtr((void *) Result,4, memenv);;
+#if !wxCHECK_VERSION(3,1,1)
+ wxGraphicsPen * Result = new wxGraphicsPen(This->CreatePen(*pen)); newPtr((void *) Result,4, memenv);
rt.addRef(getRef((void *)Result,memenv), "wxGraphicsPen");
break;
+#else
+ wxGraphicsPenInfo info = wxGraphicsPenInfo()
+ .Colour(pen->GetColour())
+ .Width(pen->GetWidth())
+ .Style(pen->GetStyle())
+ .Join(pen->GetJoin())
+ .Cap(pen->GetCap())
+ ;
+
+ if ( info.GetStyle() == wxPENSTYLE_USER_DASH )
+ {
+ wxDash *dashes;
+ if ( int nb_dashes = pen->GetDashes(&dashes) )
+ info.Dashes(nb_dashes, dashes);
+ }
+
+ if ( info.GetStyle() == wxPENSTYLE_STIPPLE )
+ {
+ if ( wxBitmap* const stipple = pen->GetStipple() )
+ info.Stipple(*stipple);
+ }
+ wxGraphicsPen * Result = new wxGraphicsPen(This->CreatePen(info));
+ newPtr((void *) Result,4, memenv);
+ rt.addRef(getRef((void *)Result,memenv), "wxGraphicsPen");
+ break;
+#endif
}
case wxGraphicsRenderer_CreateBrush: { // wxGraphicsRenderer::CreateBrush
wxGraphicsRenderer *This = (wxGraphicsRenderer *) getPtr(bp,memenv); bp += 4;
diff --git a/lib/wx/c_src/gen/wxe_init.cpp b/lib/wx/c_src/gen/wxe_init.cpp
index 1e432e34ce..6ce33a5449 100644
--- a/lib/wx/c_src/gen/wxe_init.cpp
+++ b/lib/wx/c_src/gen/wxe_init.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2015. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -529,6 +529,111 @@ void WxeApp::init_nonconsts(wxeMemEnv *memenv, ErlDrvTermData caller) {
rt.addTupleCount(2);
rt.addAtom("wxCURSOR_MAX"); rt.addInt(wxCURSOR_MAX);
rt.addTupleCount(2);
+#if wxCHECK_VERSION(3,0,3)
+ rt.addAtom("WX_GL_CORE_PROFILE"); rt.addInt(WX_GL_CORE_PROFILE);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("WX_GL_CORE_PROFILE"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,1,0)
+ rt.addAtom("WX_GL_DEBUG"); rt.addInt(WX_GL_DEBUG);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("WX_GL_DEBUG"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,1,0)
+ rt.addAtom("WX_GL_ES2"); rt.addInt(WX_GL_ES2);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("WX_GL_ES2"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,1,0)
+ rt.addAtom("WX_GL_FORWARD_COMPAT"); rt.addInt(WX_GL_FORWARD_COMPAT);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("WX_GL_FORWARD_COMPAT"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,1,0)
+ rt.addAtom("WX_GL_FRAMEBUFFER_SRGB"); rt.addInt(WX_GL_FRAMEBUFFER_SRGB);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("WX_GL_FRAMEBUFFER_SRGB"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,1,0)
+ rt.addAtom("WX_GL_LOSE_ON_RESET"); rt.addInt(WX_GL_LOSE_ON_RESET);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("WX_GL_LOSE_ON_RESET"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,0,3)
+ rt.addAtom("WX_GL_MAJOR_VERSION"); rt.addInt(WX_GL_MAJOR_VERSION);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("WX_GL_MAJOR_VERSION"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,0,3)
+ rt.addAtom("WX_GL_MINOR_VERSION"); rt.addInt(WX_GL_MINOR_VERSION);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("WX_GL_MINOR_VERSION"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,1,0)
+ rt.addAtom("WX_GL_NO_RESET_NOTIFY"); rt.addInt(WX_GL_NO_RESET_NOTIFY);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("WX_GL_NO_RESET_NOTIFY"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,1,0)
+ rt.addAtom("WX_GL_RELEASE_FLUSH"); rt.addInt(WX_GL_RELEASE_FLUSH);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("WX_GL_RELEASE_FLUSH"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,1,0)
+ rt.addAtom("WX_GL_RELEASE_NONE"); rt.addInt(WX_GL_RELEASE_NONE);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("WX_GL_RELEASE_NONE"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,1,0)
+ rt.addAtom("WX_GL_RESET_ISOLATION"); rt.addInt(WX_GL_RESET_ISOLATION);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("WX_GL_RESET_ISOLATION"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,1,0)
+ rt.addAtom("WX_GL_ROBUST_ACCESS"); rt.addInt(WX_GL_ROBUST_ACCESS);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("WX_GL_ROBUST_ACCESS"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,0,0)
+ rt.addAtom("WX_GL_SAMPLES"); rt.addInt(WX_GL_SAMPLES);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("WX_GL_SAMPLES"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+#if wxCHECK_VERSION(3,0,0)
+ rt.addAtom("WX_GL_SAMPLE_BUFFERS"); rt.addInt(WX_GL_SAMPLE_BUFFERS);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("WX_GL_SAMPLE_BUFFERS"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
rt.addAtom("wxBLACK"); rt.add(*(wxBLACK));
rt.addTupleCount(2);
rt.addAtom("wxBLACK_BRUSH"); rt.addRef(getRef((void *)wxBLACK_BRUSH,memenv),"wxBrush");
@@ -611,7 +716,14 @@ void WxeApp::init_nonconsts(wxeMemEnv *memenv, ErlDrvTermData caller) {
rt.addTupleCount(2);
rt.addAtom("wxWHITE_PEN"); rt.addRef(getRef((void *)wxWHITE_PEN,memenv),"wxPen");
rt.addTupleCount(2);
- rt.endList(293);
+#if wxCHECK_VERSION(3,1,0)
+ rt.addAtom("wx_GL_COMPAT_PROFILE"); rt.addInt(wx_GL_COMPAT_PROFILE);
+ rt.addTupleCount(2);
+#else
+ rt.addAtom("wx_GL_COMPAT_PROFILE"); rt.addAtom("undefined");
+ rt.addTupleCount(2);
+#endif
+ rt.endList(309);
rt.addTupleCount(2);
rt.send();
}
diff --git a/lib/wx/c_src/gen/wxe_macros.h b/lib/wx/c_src/gen/wxe_macros.h
index f44fa57053..4c8e52def2 100644
--- a/lib/wx/c_src/gen/wxe_macros.h
+++ b/lib/wx/c_src/gen/wxe_macros.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2017. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1540,10 +1540,10 @@
#define wxStaticBox_destroy 1637
#define wxStaticLine_new_2 1639
#define wxStaticLine_new_0 1640
-#define wxStaticLine_Create 1641
-#define wxStaticLine_IsVertical 1642
-#define wxStaticLine_GetDefaultSize 1643
-#define wxStaticLine_destroy 1644
+#define wxStaticLine_destruct 1641
+#define wxStaticLine_Create 1642
+#define wxStaticLine_IsVertical 1643
+#define wxStaticLine_GetDefaultSize 1644
#define wxListBox_new_3 1647
#define wxListBox_new_0 1648
#define wxListBox_destruct 1650
diff --git a/lib/wx/c_src/wxe_driver.c b/lib/wx/c_src/wxe_driver.c
index 5da71818e5..c9d299e0df 100644
--- a/lib/wx/c_src/wxe_driver.c
+++ b/lib/wx/c_src/wxe_driver.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,14 +33,13 @@
#include <sys/types.h>
#include <fcntl.h>
+#include <assert.h>
#include "wxe_driver.h"
#define TEMP_BINARY_SIZE 512
-static ErlDrvData wxe_driver_start(ErlDrvPort port, char *buff);
-static int wxe_driver_load(void);
+static ErlDrvData wxe_driver_start(ErlDrvPort port, char *command);
static void wxe_driver_stop(ErlDrvData handle);
-static void wxe_driver_unload(void);
static ErlDrvSSizeT wxe_driver_control(ErlDrvData handle,
unsigned int command,
char* buf, ErlDrvSizeT count,
@@ -62,30 +61,30 @@ char * erl_wx_privdir;
** The driver struct
*/
static ErlDrvEntry wxe_driver_entry = {
- wxe_driver_load, /* F_PTR init, called at loading */
- wxe_driver_start, /* L_PTR start, called when port is opened */
- wxe_driver_stop, /* F_PTR stop, called when port is closed */
- NULL, /* F_PTR output, called when erlang has sent */
- NULL, /* F_PTR ready_input, called when input descriptor
- ready */
- NULL, /* F_PTR ready_output, called when output
- descriptor ready */
- "wxe_driver", /* char *driver_name, the argument to open_port */
- wxe_driver_unload, /* F_PTR finish, called when unloaded */
- NULL, /* void * that is not used (BC) */
- wxe_driver_control, /* F_PTR control, port_control callback */
- NULL, /* F_PTR timeout, reserved */
- standard_outputv, /* F_PTR outputv, reserved */
- NULL, /* async */
- NULL, /* flush */
- wxe_driver_call, /* call */
- NULL, /* Event */
+ NULL, /* F_PTR init, called at loading */
+ wxe_driver_start, /* L_PTR start, called when port is opened */
+ wxe_driver_stop, /* F_PTR stop, called when port is closed */
+ NULL, /* F_PTR output, called when erlang has sent */
+ NULL, /* F_PTR ready_input, called when
+ input descriptor ready */
+ NULL, /* F_PTR ready_output, called when
+ output descriptor ready */
+ "wxe_driver", /* char *driver_name, the argument to open_port */
+ NULL, /* F_PTR finish, called when unloaded */
+ NULL, /* void * that is not used (BC) */
+ wxe_driver_control, /* F_PTR control, port_control callback */
+ NULL, /* F_PTR timeout, reserved */
+ standard_outputv, /* F_PTR outputv, reserved */
+ NULL, /* async */
+ NULL, /* flush */
+ wxe_driver_call, /* call */
+ NULL, /* Event */
ERL_DRV_EXTENDED_MARKER,
ERL_DRV_EXTENDED_MAJOR_VERSION,
ERL_DRV_EXTENDED_MINOR_VERSION,
- ERL_DRV_FLAG_USE_PORT_LOCKING, /* Port lock */
- NULL, /* Reserved Handle */
- wxe_process_died, /* Process Exited */
+ ERL_DRV_FLAG_USE_PORT_LOCKING, /* Port lock */
+ NULL, /* Reserved Handle */
+ wxe_process_died, /* Process Exited */
};
DRIVER_INIT(wxe_driver)
@@ -93,60 +92,56 @@ DRIVER_INIT(wxe_driver)
return &wxe_driver_entry;
}
-int wxe_driver_load()
-{
- if(load_native_gui())
- return 0;
- else
- return -1;
-}
-
ErlDrvPort WXE_DRV_PORT_HANDLE = 0;
ErlDrvTermData WXE_DRV_PORT = 0;
static ErlDrvData
-wxe_driver_start(ErlDrvPort port, char *buff)
-{
- wxe_data *data;
-
- data = (wxe_data *) malloc(sizeof(wxe_data));
- wxe_debug = 0;
-
- if (data == NULL) {
- fprintf(stderr, " Couldn't alloc mem\r\n");
- return(ERL_DRV_ERROR_GENERAL); /* ENOMEM */
- } else {
- ErlDrvTermData term_port = driver_mk_port(port);
- set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
- data->driver_data = NULL;
- data->bin = (WXEBinRef*) driver_alloc(sizeof(WXEBinRef)*DEF_BINS);
- data->bin[0].from = 0;
- data->bin[1].from = 0;
- data->bin[2].from = 0;
- data->max_bins = DEF_BINS;
- data->port_handle = port;
- data->port = term_port;
- data->pdl = driver_pdl_create(port);
- if(WXE_DRV_PORT_HANDLE == 0) {
- for(; *buff != 32; buff++);
- buff++;
- erl_wx_privdir = strdup(buff);
-
- WXE_DRV_PORT_HANDLE = port;
- WXE_DRV_PORT = term_port;
- wxe_master = data;
- if(!(start_native_gui(data) == 1))
- return(ERL_DRV_ERROR_GENERAL); /* ENOMEM */
- } else {
- meta_command(CREATE_PORT,data);
- }
- return (ErlDrvData) data;
- }
+wxe_driver_start(ErlDrvPort port, char *command)
+{
+ wxe_data *data;
+
+ data = (wxe_data *) malloc(sizeof(wxe_data));
+ wxe_debug = 0;
+
+ if (data == NULL) {
+ fprintf(stderr, " Couldn't alloc mem\r\n");
+ return(ERL_DRV_ERROR_GENERAL); /* ENOMEM */
+ } else {
+ ErlDrvTermData term_port = driver_mk_port(port);
+ set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
+ data->driver_data = NULL;
+ data->bin = (WXEBinRef*) driver_alloc(sizeof(WXEBinRef)*DEF_BINS);
+ data->bin[0].from = 0;
+ data->bin[1].from = 0;
+ data->bin[2].from = 0;
+ data->max_bins = DEF_BINS;
+ data->port_handle = port;
+ data->port = term_port;
+ data->pdl = driver_pdl_create(port);
+ if(WXE_DRV_PORT_HANDLE == 0) {
+ char *first_space = strchr(command, ' ');
+ if (first_space) {
+ char *priv_dir = first_space + 1;
+ erl_wx_privdir = strdup(priv_dir);
+
+ WXE_DRV_PORT_HANDLE = port;
+ WXE_DRV_PORT = term_port;
+ wxe_master = data;
+ if(start_native_gui(data) != 1)
+ return ERL_DRV_ERROR_GENERAL; /* ENOMEM */
+ } else {
+ return ERL_DRV_ERROR_BADARG;
+ }
+ } else {
+ meta_command(CREATE_PORT, data);
+ }
+ return (ErlDrvData) data;
+ }
}
static void
wxe_driver_stop(ErlDrvData handle)
-{
+{
wxe_data *sd = ((wxe_data *)handle);
if(sd->port_handle != WXE_DRV_PORT_HANDLE) {
// fprintf(stderr, "%s:%d: STOP \r\n", __FILE__,__LINE__);
@@ -154,18 +149,11 @@ wxe_driver_stop(ErlDrvData handle)
} else {
// fprintf(stderr, "%s:%d: STOP \r\n", __FILE__,__LINE__);
stop_native_gui(wxe_master);
- unload_native_gui();
free(wxe_master);
wxe_master = NULL;
}
}
-static void
-wxe_driver_unload(void)
-{
- // fprintf(stderr, "%s:%d: UNLOAD \r\n", __FILE__,__LINE__);
-}
-
static ErlDrvSSizeT
wxe_driver_control(ErlDrvData handle, unsigned op,
char* buf, ErlDrvSizeT count,
@@ -193,7 +181,7 @@ wxe_driver_call(ErlDrvData handle, unsigned int command,
if (len > rlen)
*res = driver_alloc(len);
memcpy((void *) *res, (void *) buf, len);
- return len;
+ return len;
}
@@ -218,29 +206,37 @@ standard_outputv(ErlDrvData drv_data, ErlIOVec* ev)
int i, max;
for(i = 0; i < sd->max_bins; i++) {
- if(sd->bin[i].from == 0) {
- binref = &sd->bin[i];
- break;
- }
+ if(sd->bin[i].from == 0) {
+ binref = &sd->bin[i];
+ break;
+ }
}
if(binref == NULL) { /* realloc */
- max = sd->max_bins + DEF_BINS;
- driver_realloc(sd->bin, sizeof(WXEBinRef)*max);
- for(i=sd->max_bins; i < max; i++) {
- sd->bin[i].from = 0;
- }
- binref = &sd->bin[sd->max_bins];
- sd->max_bins = max;
+ max = sd->max_bins + DEF_BINS;
+ driver_realloc(sd->bin, sizeof(WXEBinRef)*max);
+ for(i=sd->max_bins; i < max; i++) {
+ sd->bin[i].from = 0;
+ }
+ binref = &sd->bin[sd->max_bins];
+ sd->max_bins = max;
}
- if(ev->vsize == 2) {
- binref->base = ev->iov[1].iov_base;
- binref->size = ev->iov[1].iov_len;
- binref->from = driver_caller(sd->port_handle);
- bin = ev->binv[1];
- driver_binary_inc_refc(bin); /* Otherwise it could get deallocated */
- binref->bin = bin;
+ if(ev->size > 0) {
+ assert(ev->vsize == 2 && ev->iov[0].iov_len == 0
+ && "erts changed how the ErlIOVec is structured for outputv");
+ binref->from = driver_caller(sd->port_handle);
+ binref->size = ev->iov[1].iov_len;
+ if(ev->binv[1]) {
+ binref->base = ev->iov[1].iov_base;
+ bin = ev->binv[1];
+ driver_binary_inc_refc(bin); /* Otherwise it could get deallocated */
+ } else {
+ bin = driver_alloc_binary(ev->iov[1].iov_len);
+ memcpy(bin->orig_bytes, ev->iov[1].iov_base, ev->iov[1].iov_len);
+ binref->base = bin->orig_bytes;
+ }
+ binref->bin = bin;
} else { /* Empty binary (becomes NULL) */
binref->base = NULL;
binref->size = 0;
diff --git a/lib/wx/c_src/wxe_driver.h b/lib/wx/c_src/wxe_driver.h
index f9bca049c8..6d6a67fa85 100644
--- a/lib/wx/c_src/wxe_driver.h
+++ b/lib/wx/c_src/wxe_driver.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -56,10 +56,8 @@ typedef struct wxe_data_def {
void init_glexts(wxe_data*);
-int load_native_gui();
int start_native_gui(wxe_data *sd);
void stop_native_gui(wxe_data *sd);
-void unload_native_gui();
#define FUNC_CALL 13
#define CREATE_PORT 14
diff --git a/lib/wx/c_src/wxe_main.cpp b/lib/wx/c_src/wxe_main.cpp
index c7565e33bd..5b65d8a59b 100644
--- a/lib/wx/c_src/wxe_main.cpp
+++ b/lib/wx/c_src/wxe_main.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2014-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2014-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -59,15 +59,9 @@ void *wxe_main_loop(void * );
* START AND STOP of driver thread
* ************************************************************/
-int load_native_gui()
-{
- return 1;
-}
-
int start_native_gui(wxe_data *sd)
{
int res;
- ErlDrvThreadOpts *opts = NULL;
wxe_status_m = erl_drv_mutex_create((char *) "wxe_status_m");
wxe_status_c = erl_drv_cond_create((char *)"wxe_status_c");
@@ -79,7 +73,7 @@ int start_native_gui(wxe_data *sd)
res = erl_drv_steal_main_thread((char *)"wxwidgets",
&wxe_thread,wxe_main_loop,(void *) sd->pdl,NULL);
#else
- opts = erl_drv_thread_opts_create((char *)"wx thread");
+ ErlDrvThreadOpts *opts = erl_drv_thread_opts_create((char *)"wx thread");
opts->suggested_stack_size = 8192;
res = erl_drv_thread_create((char *)"wxwidgets",
&wxe_thread,wxe_main_loop,(void *) sd->pdl,opts);
@@ -116,11 +110,6 @@ void stop_native_gui(wxe_data *sd)
erl_drv_cond_destroy(wxe_batch_locker_c);
}
-void unload_native_gui()
-{
-
-}
-
/* ************************************************************
* wxWidgets Thread
* ************************************************************/
diff --git a/lib/wx/c_src/wxe_ps_init.c b/lib/wx/c_src/wxe_ps_init.c
index e6b677d469..4b3b47a80b 100644
--- a/lib/wx/c_src/wxe_ps_init.c
+++ b/lib/wx/c_src/wxe_ps_init.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -61,13 +61,20 @@ int is_packaged_app() {
void * wxe_ps_init2() {
NSAutoreleasePool *pool;
ProcessSerialNumber psn;
-
+ size_t app_len = 127;
+ char app_title_buf[128];
+ char * app_title;
// Setup and enable gui
pool = [[NSAutoreleasePool alloc] init];
-
+
if( !is_packaged_app() ) {
// Undocumented function (but no documented way of doing this exists)
- char *app_title = getenv("WX_APP_TITLE");
+ int res = erl_drv_getenv("WX_APP_TITLE", app_title_buf, &app_len);
+ if (res >= 0) {
+ app_title = app_title_buf;
+ } else {
+ app_title = NULL;
+ }
if(!GetCurrentProcess(&psn)) {
CPSSetProcessName(&psn, app_title?app_title:"Erlang");
}
diff --git a/lib/wx/doc/src/Makefile b/lib/wx/doc/src/Makefile
index 23890f47f0..f66d63f63b 100644
--- a/lib/wx/doc/src/Makefile
+++ b/lib/wx/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2016. All Rights Reserved.
+# Copyright Ericsson AB 2008-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -39,16 +39,20 @@ ModsNoExt = $(ErlMods:%.erl=%) $(GenMods:%.erl=%)
XML_APPLICATION_FILES = ref_man.xml
XML_REF3_FILES = $(ErlMods:%.erl=%.xml) $(GenMods:%.erl=%.xml)
-XML_PART_FILES = part.xml part_notes.xml
+XML_PART_FILES = part.xml
XML_CHAPTER_FILES = chapter.xml
XML_NOTES_FILES = notes.xml
BOOK_FILES = book.xml
XML_FILES = \
- $(BOOK_FILES) $(XML_CHAPTER_FILES) \
- $(XML_PART_FILES) $(XML_REF3_FILES) \
- $(XML_NOTES_FILES) $(XML_APPLICATION_FILES)
+ $(BOOK_FILES) \
+ $(XML_PART_FILES) $(XML_NOTES_FILES)
+
+XML_GEN_FILES = \
+ $(XML_CHAPTER_FILES:%=$(XMLDIR)/%) \
+ $(XML_REF3_FILES:%=$(XMLDIR)/%) \
+ $(XML_APPLICATION_FILES:%=$(XMLDIR)/%)
# ----------------------------------------------------
INFO_FILE = ../../info
@@ -93,32 +97,37 @@ gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
xml: $(XML_REF3_FILES) $(XML_CHAPTER_FILES)
ref_man.xml: ref_man.xml.src
- @echo Preparing ref_man.xml
- @cat ref_man.xml.src > ref_man.xml
+ @echo Preparing $@
+ @cat ref_man.xml.src > $@
@for d in $(ModsNoExt); do \
- echo " <xi:include href=\"$$d.xml\"/>" >> ref_man.xml ; \
+ echo " <xi:include href=\"$$d.xml\"/>" >> $@ ; \
done
- @echo "</application>" >> ref_man.xml
- @echo
+ @echo "</application>" >> $@
-$(ErlMods:%.erl=%.xml): ../../src/$(@:%.xml=%.erl)
- escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(VSN) -preprocess true -sort_functions false ../../src/$(@:%.xml=%.erl)
+$(ErlMods:%.erl=$(XMLDIR)/%.xml):
+ $(gen_verbose)escript $(DOCGEN)/priv/bin/xml_from_edoc.escript \
+ -def vsn $(VSN) -preprocess true -sort_functions false -dir $(XMLDIR) \
+ ../../src/$(@:$(XMLDIR)/%.xml=%.erl)
-$(GenMods:%.erl=%.xml): ../../src/gen/$(@:%.xml=%.erl)
- escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(VSN) -i ../../src -preprocess true -sort_functions false ../../src/gen/$(@:%.xml=%.erl)
+$(GenMods:%.erl=$(XMLDIR)/%.xml):
+ $(gen_verbose)escript $(DOCGEN)/priv/bin/xml_from_edoc.escript \
+ -def vsn $(VSN) -i ../../src -preprocess true -sort_functions false -dir $(XMLDIR) \
+ ../../src/gen/$(@:$(XMLDIR)/%.xml=%.erl)
-$(XML_CHAPTER_FILES): ../overview.edoc
- escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(VSN) -chapter ../overview.edoc
+$(XML_CHAPTER_FILES:%=$(XMLDIR)/%): ../overview.edoc
+ $(gen_verbose)escript $(DOCGEN)/priv/bin/xml_from_edoc.escript \
+ -def vsn $(VSN) -chapter -dir $(XMLDIR) $<
debug opt:
clean clean_docs:
- rm -rf $(HTMLDIR)/*
+ rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(SPECDIR)/*
rm -f errs core *~ ../html/edoc-info
- rm -f $(XML_REF3_FILES) $(XML_CHAPTER_FILES) *.html
+ rm -f $(XML_GEN_FILES) *.html
# ----------------------------------------------------
# Release Target
diff --git a/lib/wx/doc/src/fascicules.xml b/lib/wx/doc/src/fascicules.xml
deleted file mode 100644
index 154c8a3b6d..0000000000
--- a/lib/wx/doc/src/fascicules.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
-</fascicules>
-
diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml
index d300ab5128..a925cf30d4 100644
--- a/lib/wx/doc/src/notes.xml
+++ b/lib/wx/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2009</year><year>2017</year>
+ <year>2009</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,83 @@
<p>This document describes the changes made to the wxErlang
application.</p>
+<section><title>Wx 1.8.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed compilation warning on Darwin.</p>
+ <p>
+ Own Id: OTP-15230 Aux Id: PR-1860 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Wx 1.8.4</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Changed implementation so wx can now be built towards
+ wxWidgets-3.1.1.</p>
+ <p>
+ Own Id: OTP-15027</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Wx 1.8.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ wx crashes in otp 20.1 if empty binaries was sent down as
+ arguments.</p>
+ <p>
+ Own Id: OTP-14688</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Wx 1.8.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Do not deprecate
+ <c>wxGraphicsContext:createLinearGradientBrush/7</c> and
+ <c>wxGraphicsContext:createRadialGradientBrush/8</c>
+ which are still available in wxWidgets-3.0.</p>
+ <p>
+ Own Id: OTP-14539</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ General Unicode improvements.</p>
+ <p>
+ Own Id: OTP-14462</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Wx 1.8.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/wx/doc/src/part_notes.xml b/lib/wx/doc/src/part_notes.xml
deleted file mode 100644
index 5a5a6494c1..0000000000
--- a/lib/wx/doc/src/part_notes.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2009</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>wxErlang Release Notes</title>
- <prepared></prepared>
- <docno></docno>
- <date></date>
- <rev></rev>
- </header>
- <description>
- <p>The <em>wxErlang</em> application is an api for writing graphical user
- interfaces with wxWidgets.
- </p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/wx/examples/demo/demo.erl b/lib/wx/examples/demo/demo.erl
index 8fb70ad7b0..8f3291305b 100644
--- a/lib/wx/examples/demo/demo.erl
+++ b/lib/wx/examples/demo/demo.erl
@@ -411,7 +411,7 @@ find(Ed) ->
keyWords() ->
L = ["after","begin","case","try","cond","catch","andalso","orelse",
- "end","fun","if","let","of","query","receive","when","bnot","not",
+ "end","fun","if","let","of","receive","when","bnot","not",
"div","rem","band","and","bor","bxor","bsl","bsr","or","xor"],
lists:flatten([K ++ " " || K <- L] ++ [0]).
diff --git a/lib/wx/examples/demo/ex_aui.erl b/lib/wx/examples/demo/ex_aui.erl
index d8fc0021f1..49fa86f630 100644
--- a/lib/wx/examples/demo/ex_aui.erl
+++ b/lib/wx/examples/demo/ex_aui.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -87,8 +87,7 @@ do_init(Config) ->
wxAuiManager:update(Manager),
process_flag(trap_exit, true),
{Panel, #state{parent=Panel, config=Config, aui=Manager}}
- catch Class:Reason ->
- ST = erlang:get_stacktrace(),
+ catch Class:Reason:ST ->
io:format("AUI Crashed ~p ~p~n",[Reason, ST]),
wxAuiManager:unInit(Manager),
wxAuiManager:destroy(Manager),
diff --git a/lib/wx/examples/simple/hello.erl b/lib/wx/examples/simple/hello.erl
index 36bce56329..8491a20af5 100644
--- a/lib/wx/examples/simple/hello.erl
+++ b/lib/wx/examples/simple/hello.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,6 @@
-include_lib("wx/include/wx.hrl").
-export([start/0]).
--compile(export_all).
start() ->
Wx = wx:new(),
diff --git a/lib/wx/examples/simple/hello2.erl b/lib/wx/examples/simple/hello2.erl
index 671b23d892..656c056d9a 100644
--- a/lib/wx/examples/simple/hello2.erl
+++ b/lib/wx/examples/simple/hello2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,8 +29,9 @@
-module(hello2).
-include_lib("wx/include/wx.hrl").
--export([start/0]).
--compile(export_all).
+-export([start/0,
+ init/1, handle_info/2, handle_event/2, handle_call/3,
+ code_change/3, terminate/2]).
-behavoiur(wx_object).
diff --git a/lib/wx/examples/simple/menu.erl b/lib/wx/examples/simple/menu.erl
index 479df1ef98..7c0400bd1e 100644
--- a/lib/wx/examples/simple/menu.erl
+++ b/lib/wx/examples/simple/menu.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,6 @@
-include_lib("wx/include/wx.hrl").
-export([start/0]).
--compile(export_all).
%%%Lots of IDs to declare!
-define(menuID_FILE_QUIT, ?wxID_EXIT).
@@ -228,36 +227,6 @@ create_menubar_menu() ->
%%
%%
%%
-create_submenu_menu() ->
- SubMenuMenu = wxMenu:new(),
- wxMenu:append(SubMenuMenu, wxMenuItem:new([
- {id, ?menuID_SUBMENU_NORMAL},
- {text, "&Normal submenu item"},
- {help, "Disabled submenu item"}
- ])),
- %% note different way of adding check menu item
- wxMenu:appendCheckItem(SubMenuMenu,
- ?menuID_SUBMENU_CHECK,
- "&Check submenu item",
- [{help, "Check submenu item"}]),
- wxMenu:appendRadioItem(SubMenuMenu,
- ?menuID_SUBMENU_RADIO_1,
- "Radio item &1",
- [{help, "Radio item"}]),
- wxMenu:appendRadioItem(SubMenuMenu,
- ?menuID_SUBMENU_RADIO_2,
- "Radio item &2",
- [{help, "Radio item"}]),
- wxMenu:appendRadioItem(SubMenuMenu,
- ?menuID_SUBMENU_RADIO_3,
- "Radio item &3",
- [{help, "Radio item"}]),
- SubMenuMenu.
-
-
-%%
-%%
-%%
create_menu_menu() ->
MenuMenu = wxMenu:new(),
wxMenu:append(MenuMenu, wxMenuItem:new([
diff --git a/lib/wx/examples/simple/minimal.erl b/lib/wx/examples/simple/minimal.erl
index 9f6365e008..45efc06462 100644
--- a/lib/wx/examples/simple/minimal.erl
+++ b/lib/wx/examples/simple/minimal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,7 @@
-include_lib("wx/include/wx.hrl").
-export([start/0]).
--compile(export_all).
+
start() ->
Wx = wx:new(),
diff --git a/lib/wx/examples/sudoku/sudoku.erl b/lib/wx/examples/sudoku/sudoku.erl
index 97f35870de..a6a8d07e57 100644
--- a/lib/wx/examples/sudoku/sudoku.erl
+++ b/lib/wx/examples/sudoku/sudoku.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,9 +26,8 @@
-module(sudoku).
--export([go/0]).
+-export([go/0, start/0]).
--compile(export_all).
-include("sudoku.hrl").
diff --git a/lib/wx/examples/sudoku/sudoku_game.erl b/lib/wx/examples/sudoku/sudoku_game.erl
index 1e579a7c88..6463583e0f 100644
--- a/lib/wx/examples/sudoku/sudoku_game.erl
+++ b/lib/wx/examples/sudoku/sudoku_game.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,7 +18,9 @@
%% %CopyrightEnd%
-module(sudoku_game).
--compile(export_all).
+
+-export([init/1,
+ indx/1, rcm/1, level/1]).
-include("sudoku.hrl").
init(GFX) ->
@@ -128,17 +130,6 @@ rebuild_all(_, S0) ->
add(rcm(Indx),Val,Acc)
end, S1, Solved).
-is_ok({RI,CI,MI}, Vals) ->
- [Ri,Ci,Mi] = all(RI,CI,MI),
- case element(indx(RI,CI),Vals) of
- 0 -> true;
- Val ->
- Vs = [[element(indx(R,C),Vals)||{R,C} <- Obs,
- not ((R == RI) and (C == CI))]
- || Obs <- [Ri,Ci,Mi]],
- not lists:member(Val,lists:flatten(Vs))
- end.
-
test() -> %% Known to solvable
[{{1,2},6}, {{1,4},1}, {{1,6},4}, {{1,8},5},
{{2,3},8}, {{2,4},3}, {{2,6},5}, {{2,7},6},
@@ -377,14 +368,6 @@ get_poss([H|R],What,Tot) ->
%% io:format("~p~n",[H]),
get_poss(R,What, gb_sets:union(element(H,What),Tot)).
-r2rs(R) ->
- R0 = (R-1)*3,
- [R0+1,R0+2,R0+3].
-
-c2cs(C) ->
- C0 = (C-1) rem 9,
- [C0+1, C0+10, C0+19].
-
mindx(row,Indx) ->
{R,_C,M} = rcm(Indx),
mindx(R,M);
diff --git a/lib/wx/examples/sudoku/sudoku_gui.erl b/lib/wx/examples/sudoku/sudoku_gui.erl
index 81d20814e1..e436bf2909 100644
--- a/lib/wx/examples/sudoku/sudoku_gui.erl
+++ b/lib/wx/examples/sudoku/sudoku_gui.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@
-export([init/1, handle_info/2, handle_call/3, handle_cast/2, handle_event/2,
terminate/2, code_change/3]).
--compile(export_all).
+-export([new/1]).
-behaviour(wx_object).
diff --git a/lib/wx/examples/xrc/xrc.erl b/lib/wx/examples/xrc/xrc.erl
index 729f4ad0db..a64e1f33ef 100644
--- a/lib/wx/examples/xrc/xrc.erl
+++ b/lib/wx/examples/xrc/xrc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
%%%-------------------------------------------------------------------
-module(xrc).
--compile(export_all).
+-export([start/0]).
-include("../../include/wx.hrl").
diff --git a/lib/wx/include/wx.hrl b/lib/wx/include/wx.hrl
index a14cc89cee..23f3b95403 100644
--- a/lib/wx/include/wx.hrl
+++ b/lib/wx/include/wx.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -373,6 +373,21 @@
-define(wxDefaultPosition, {-1,-1}).
%% Global Variables
+-define('WX_GL_CORE_PROFILE', wxe_util:get_const('WX_GL_CORE_PROFILE')).
+-define('WX_GL_DEBUG', wxe_util:get_const('WX_GL_DEBUG')).
+-define('WX_GL_ES2', wxe_util:get_const('WX_GL_ES2')).
+-define('WX_GL_FORWARD_COMPAT', wxe_util:get_const('WX_GL_FORWARD_COMPAT')).
+-define('WX_GL_FRAMEBUFFER_SRGB', wxe_util:get_const('WX_GL_FRAMEBUFFER_SRGB')).
+-define('WX_GL_LOSE_ON_RESET', wxe_util:get_const('WX_GL_LOSE_ON_RESET')).
+-define('WX_GL_MAJOR_VERSION', wxe_util:get_const('WX_GL_MAJOR_VERSION')).
+-define('WX_GL_MINOR_VERSION', wxe_util:get_const('WX_GL_MINOR_VERSION')).
+-define('WX_GL_NO_RESET_NOTIFY', wxe_util:get_const('WX_GL_NO_RESET_NOTIFY')).
+-define('WX_GL_RELEASE_FLUSH', wxe_util:get_const('WX_GL_RELEASE_FLUSH')).
+-define('WX_GL_RELEASE_NONE', wxe_util:get_const('WX_GL_RELEASE_NONE')).
+-define('WX_GL_RESET_ISOLATION', wxe_util:get_const('WX_GL_RESET_ISOLATION')).
+-define('WX_GL_ROBUST_ACCESS', wxe_util:get_const('WX_GL_ROBUST_ACCESS')).
+-define('WX_GL_SAMPLES', wxe_util:get_const('WX_GL_SAMPLES')).
+-define('WX_GL_SAMPLE_BUFFERS', wxe_util:get_const('WX_GL_SAMPLE_BUFFERS')).
-define(wxBLACK, wxe_util:get_const(wxBLACK)).
-define(wxBLACK_BRUSH, wxe_util:get_const(wxBLACK_BRUSH)).
-define(wxBLACK_DASHED_PEN, wxe_util:get_const(wxBLACK_DASHED_PEN)).
@@ -414,6 +429,7 @@
-define(wxWHITE, wxe_util:get_const(wxWHITE)).
-define(wxWHITE_BRUSH, wxe_util:get_const(wxWHITE_BRUSH)).
-define(wxWHITE_PEN, wxe_util:get_const(wxWHITE_PEN)).
+-define(wx_GL_COMPAT_PROFILE, wxe_util:get_const(wx_GL_COMPAT_PROFILE)).
%% Enum and defines
% From class wxAuiManager
diff --git a/lib/wx/src/gen/gl.erl b/lib/wx/src/gen/gl.erl
index 4a178ea1e4..47afb25c5d 100644
--- a/lib/wx/src/gen/gl.erl
+++ b/lib/wx/src/gen/gl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@
%% This file is generated DO NOT EDIT
%% @doc Standard OpenGL api.
-%% See <a href="http://www.opengl.org/sdk/docs/man/">www.opengl.org</a>
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">www.khronos.org</a>
%%
%% Booleans are represented by integers 0 and 1.
@@ -324,7 +324,7 @@ send_bin(Tuple) when is_tuple(Tuple) ->
%% value is then masked with 2 m-1, where m is the number of bits in a color index stored
%% in the frame buffer.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearIndex.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glClearIndex.xml">external</a> documentation.
-spec clearIndex(C) -> 'ok' when C :: float().
clearIndex(C) ->
cast(5037, <<C:?GLfloat>>).
@@ -335,7 +335,7 @@ clearIndex(C) ->
%% to clear the color buffers. Values specified by ``gl:clearColor'' are clamped to the
%% range [0 1].
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearColor.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glClearColor.xhtml">external</a> documentation.
-spec clearColor(Red, Green, Blue, Alpha) -> 'ok' when Red :: clamp(),Green :: clamp(),Blue :: clamp(),Alpha :: clamp().
clearColor(Red,Green,Blue,Alpha) ->
cast(5038, <<Red:?GLclampf,Green:?GLclampf,Blue:?GLclampf,Alpha:?GLclampf>>).
@@ -346,26 +346,7 @@ clearColor(Red,Green,Blue,Alpha) ->
%% , ``gl:clearDepth'', and ``gl:clearStencil''. Multiple color buffers can be cleared
%% simultaneously by selecting more than one buffer at a time using {@link gl:drawBuffer/1} .
%%
-%% The pixel ownership test, the scissor test, dithering, and the buffer writemasks affect
-%% the operation of ``gl:clear''. The scissor box bounds the cleared region. Alpha function,
-%% blend function, logical operation, stenciling, texture mapping, and depth-buffering are
-%% ignored by ``gl:clear''.
-%%
-%% ``gl:clear'' takes a single argument that is the bitwise OR of several values indicating
-%% which buffer is to be cleared.
-%%
-%% The values are as follows:
-%%
-%% `?GL_COLOR_BUFFER_BIT': Indicates the buffers currently enabled for color writing.
-%%
-%% `?GL_DEPTH_BUFFER_BIT': Indicates the depth buffer.
-%%
-%% `?GL_STENCIL_BUFFER_BIT': Indicates the stencil buffer.
-%%
-%% The value to which each buffer is cleared depends on the setting of the clear value for
-%% that buffer.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClear.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glClear.xhtml">external</a> documentation.
-spec clear(Mask) -> 'ok' when Mask :: integer().
clear(Mask) ->
cast(5039, <<Mask:?GLbitfield>>).
@@ -378,11 +359,7 @@ clear(Mask) ->
%% to the corresponding bit in the color index buffer (or buffers). Where a 0 (zero) appears,
%% the corresponding bit is write-protected.
%%
-%% This mask is used only in color index mode, and it affects only the buffers currently
-%% selected for writing (see {@link gl:drawBuffer/1} ). Initially, all bits are enabled for
-%% writing.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIndexMask.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glIndexMask.xml">external</a> documentation.
-spec indexMask(Mask) -> 'ok' when Mask :: integer().
indexMask(Mask) ->
cast(5040, <<Mask:?GLuint>>).
@@ -395,10 +372,7 @@ indexMask(Mask) ->
%% is `?GL_FALSE', for example, no change is made to the red component of any pixel
%% in any of the color buffers, regardless of the drawing operation attempted.
%%
-%% Changes to individual bits of components cannot be controlled. Rather, changes are either
-%% enabled or disabled for entire color components.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorMask.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glColorMask.xhtml">external</a> documentation.
-spec colorMask(Red, Green, Blue, Alpha) -> 'ok' when Red :: 0|1,Green :: 0|1,Blue :: 0|1,Alpha :: 0|1.
colorMask(Red,Green,Blue,Alpha) ->
cast(5041, <<Red:?GLboolean,Green:?GLboolean,Blue:?GLboolean,Alpha:?GLboolean>>).
@@ -411,37 +385,7 @@ colorMask(Red,Green,Blue,Alpha) ->
%% testing is enabled. By default, it is not enabled. (See {@link gl:enable/1} and {@link gl:enable/1}
%% of `?GL_ALPHA_TEST'.)
%%
-%% `Func' and `Ref' specify the conditions under which the pixel is drawn. The
-%% incoming alpha value is compared to `Ref' using the function specified by `Func' .
-%% If the value passes the comparison, the incoming fragment is drawn if it also passes subsequent
-%% stencil and depth buffer tests. If the value fails the comparison, no change is made to
-%% the frame buffer at that pixel location. The comparison functions are as follows:
-%%
-%% `?GL_NEVER': Never passes.
-%%
-%% `?GL_LESS': Passes if the incoming alpha value is less than the reference value.
-%%
-%% `?GL_EQUAL': Passes if the incoming alpha value is equal to the reference value.
-%%
-%% `?GL_LEQUAL': Passes if the incoming alpha value is less than or equal to the reference
-%% value.
-%%
-%% `?GL_GREATER': Passes if the incoming alpha value is greater than the reference
-%% value.
-%%
-%% `?GL_NOTEQUAL': Passes if the incoming alpha value is not equal to the reference
-%% value.
-%%
-%% `?GL_GEQUAL': Passes if the incoming alpha value is greater than or equal to the
-%% reference value.
-%%
-%% `?GL_ALWAYS': Always passes (initial value).
-%%
-%% ``gl:alphaFunc'' operates on all pixel write operations, including those resulting from
-%% the scan conversion of points, lines, polygons, and bitmaps, and from pixel draw and copy
-%% operations. ``gl:alphaFunc'' does not affect screen clear operations.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAlphaFunc.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glAlphaFunc.xml">external</a> documentation.
-spec alphaFunc(Func, Ref) -> 'ok' when Func :: enum(),Ref :: clamp().
alphaFunc(Func,Ref) ->
cast(5042, <<Func:?GLenum,Ref:?GLclampf>>).
@@ -453,70 +397,7 @@ alphaFunc(Func,Ref) ->
%% is initially disabled. Use {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_BLEND'
%% to enable and disable blending.
%%
-%% ``gl:blendFunc'' defines the operation of blending for all draw buffers when it is enabled.
-%% ``gl:blendFunci'' defines the operation of blending for a single draw buffer specified
-%% by `Buf' when enabled for that draw buffer. `Sfactor' specifies which method
-%% is used to scale the source color components. `Dfactor' specifies which method is
-%% used to scale the destination color components. Both parameters must be one of the following
-%% symbolic constants: `?GL_ZERO', `?GL_ONE', `?GL_SRC_COLOR', `?GL_ONE_MINUS_SRC_COLOR'
-%% , `?GL_DST_COLOR', `?GL_ONE_MINUS_DST_COLOR', `?GL_SRC_ALPHA', `?GL_ONE_MINUS_SRC_ALPHA'
-%% , `?GL_DST_ALPHA', `?GL_ONE_MINUS_DST_ALPHA', `?GL_CONSTANT_COLOR', `?GL_ONE_MINUS_CONSTANT_COLOR'
-%% , `?GL_CONSTANT_ALPHA', `?GL_ONE_MINUS_CONSTANT_ALPHA', `?GL_SRC_ALPHA_SATURATE'
-%% , `?GL_SRC1_COLOR', `?GL_ONE_MINUS_SRC1_COLOR', `?GL_SRC1_ALPHA', and `?GL_ONE_MINUS_SRC1_ALPHA'
-%% . The possible methods are described in the following table. Each method defines four
-%% scale factors, one each for red, green, blue, and alpha. In the table and in subsequent
-%% equations, first source, second source and destination color components are referred to
-%% as (R s0 G s0 B s0 A s0), (R s1 G s1 B s1 A s1) and (R d G d B d A d), respectively. The color specified by {@link gl:blendColor/4} is referred to
-%% as (R c G c B c A c). They are understood to have integer values between 0 and (k R k G k B k A), where
-%%
-%% k c=2(m c)-1
-%%
-%% and (m R m G m B m A) is the number of red, green, blue, and alpha bitplanes.
-%%
-%% Source and destination scale factors are referred to as (s R s G s B s A) and (d R d G d B d A). The scale factors described
-%% in the table, denoted (f R f G f B f A), represent either source or destination factors. All scale factors
-%% have range [0 1].
-%%
-%% <table><tbody><tr><td>` Parameter '</td><td>(f R f G f B f A)</td></tr></tbody><tbody><tr><td>`?GL_ZERO'
-%% </td><td>(0 0 0 0)</td></tr><tr><td>`?GL_ONE'</td><td>(1 1 1 1)</td></tr><tr><td>`?GL_SRC_COLOR'</td>
-%% <td>(R s0 k/R G s0 k/G B s0 k/B A s0 k/A)</td></tr><tr><td>`?GL_ONE_MINUS_SRC_COLOR'</td><td>(1 1 1 1)-(R s0 k/R G s0 k/G B s0 k/B
-%% A s0 k/A)</td></tr><tr><td>`?GL_DST_COLOR'
-%% </td><td>(R d k/R G d k/G B d k/B A d k/A)</td></tr><tr><td>`?GL_ONE_MINUS_DST_COLOR'</td><td>(1 1 1 1)-(R d k/R G d k/G B d k/B
-%% A d k/A)</td></tr><tr><td>`?GL_SRC_ALPHA'
-%% </td><td>(A s0 k/A A s0 k/A A s0 k/A A s0 k/A)</td></tr><tr><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td>(1 1 1 1)-(A s0 k/A A s0 k/A A s0
-%% k/A A s0 k/A)</td></tr><tr><td>`?GL_DST_ALPHA'
-%% </td><td>(A d k/A A d k/A A d k/A A d k/A)</td></tr><tr><td>`?GL_ONE_MINUS_DST_ALPHA'</td><td>(1 1 1 1)-(A d k/A A d k/A A d k/A
-%% A d k/A)</td></tr><tr><td>`?GL_CONSTANT_COLOR'
-%% </td><td>(R c G c B c A c)</td></tr><tr><td>`?GL_ONE_MINUS_CONSTANT_COLOR'</td><td>(1 1 1 1)-(R c G c B c A c)</td></tr><tr><td>
-%% `?GL_CONSTANT_ALPHA'</td><td>(A c A c A c A c)</td></tr><tr><td>`?GL_ONE_MINUS_CONSTANT_ALPHA'</td>
-%% <td>(1 1 1 1)-(A c A c A c A c)</td></tr><tr><td>`?GL_SRC_ALPHA_SATURATE'</td><td>(i i i 1)</td></tr><tr><td>`?GL_SRC1_COLOR'
-%% </td><td>(R s1 k/R G s1 k/G B s1 k/B A s1 k/A)</td></tr><tr><td>`?GL_ONE_MINUS_SRC1_COLOR'</td><td>(1 1 1 1)-(R s1 k/R G s1 k/G B
-%% s1 k/B A s1 k/A)</td></tr><tr><td>`?GL_SRC1_ALPHA'
-%% </td><td>(A s1 k/A A s1 k/A A s1 k/A A s1 k/A)</td></tr><tr><td>`?GL_ONE_MINUS_SRC1_ALPHA'</td><td>(1 1 1 1)-(A s1 k/A A s1 k/A A
-%% s1 k/A A s1 k/A)</td></tr></tbody></table>
-%%
-%%
-%% In the table,
-%%
-%% i=min(A s k A-A d) k/A
-%%
-%% To determine the blended RGBA values of a pixel, the system uses the following equations:
-%%
-%%
-%% R d=min(k R R s s R+R d d R) G d=min(k G G s s G+G d d G) B d=min(k B B s s B+B d d B) A d=min(k A A s s A+A d d A)
-%%
-%% Despite the apparent precision of the above equations, blending arithmetic is not exactly
-%% specified, because blending operates with imprecise integer color values. However, a blend
-%% factor that should be equal to 1 is guaranteed not to modify its multiplicand, and a blend
-%% factor equal to 0 reduces its multiplicand to 0. For example, when `Sfactor' is `?GL_SRC_ALPHA'
-%% , `Dfactor' is `?GL_ONE_MINUS_SRC_ALPHA', and A s is equal to k A, the equations
-%% reduce to simple replacement:
-%%
-%% R d=R s G d=G s B d=B s A d=A s
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendFunc.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendFunc.xhtml">external</a> documentation.
-spec blendFunc(Sfactor, Dfactor) -> 'ok' when Sfactor :: enum(),Dfactor :: enum().
blendFunc(Sfactor,Dfactor) ->
cast(5043, <<Sfactor:?GLenum,Dfactor:?GLenum>>).
@@ -528,25 +409,7 @@ blendFunc(Sfactor,Dfactor) ->
%% buffer. To enable or disable the logical operation, call {@link gl:enable/1} and {@link gl:enable/1}
%% using the symbolic constant `?GL_COLOR_LOGIC_OP'. The initial value is disabled.
%%
-%% <table><tbody><tr><td>` Opcode '</td><td>` Resulting Operation '</td></tr></tbody>
-%% <tbody><tr><td>`?GL_CLEAR'</td><td> 0 </td></tr><tr><td>`?GL_SET'</td><td> 1 </td>
-%% </tr><tr><td>`?GL_COPY'</td><td> s </td></tr><tr><td>`?GL_COPY_INVERTED'</td><td>
-%% ~s </td></tr><tr><td>`?GL_NOOP'</td><td> d </td></tr><tr><td>`?GL_INVERT'</td><td>
-%% ~d </td></tr><tr><td>`?GL_AND'</td><td> s &amp; d </td></tr><tr><td>`?GL_NAND'</td>
-%% <td> ~(s &amp; d) </td></tr><tr><td>`?GL_OR'</td><td> s | d </td></tr><tr><td>`?GL_NOR'
-%% </td><td> ~(s | d) </td></tr><tr><td>`?GL_XOR'</td><td> s ^ d </td></tr><tr><td>`?GL_EQUIV'
-%% </td><td> ~(s ^ d) </td></tr><tr><td>`?GL_AND_REVERSE'</td><td> s &amp; ~d </td></tr>
-%% <tr><td>`?GL_AND_INVERTED'</td><td> ~s &amp; d </td></tr><tr><td>`?GL_OR_REVERSE'
-%% </td><td> s | ~d </td></tr><tr><td>`?GL_OR_INVERTED'</td><td> ~s | d </td></tr></tbody>
-%% </table>
-%%
-%% `Opcode' is a symbolic constant chosen from the list above. In the explanation of
-%% the logical operations, `s' represents the incoming color and `d' represents
-%% the color in the frame buffer. Standard C-language operators are used. As these bitwise
-%% operators suggest, the logical operation is applied independently to each bit pair of
-%% the source and destination colors.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLogicOp.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glLogicOp.xhtml">external</a> documentation.
-spec logicOp(Opcode) -> 'ok' when Opcode :: enum().
logicOp(Opcode) ->
cast(5044, <<Opcode:?GLenum>>).
@@ -559,10 +422,7 @@ logicOp(Opcode) ->
%% commands with the argument `?GL_CULL_FACE'. Facets include triangles, quadrilaterals,
%% polygons, and rectangles.
%%
-%% {@link gl:frontFace/1} specifies which of the clockwise and counterclockwise facets are
-%% front-facing and back-facing. See {@link gl:frontFace/1} .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCullFace.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCullFace.xhtml">external</a> documentation.
-spec cullFace(Mode) -> 'ok' when Mode :: enum().
cullFace(Mode) ->
cast(5045, <<Mode:?GLenum>>).
@@ -574,18 +434,7 @@ cullFace(Mode) ->
%% rendering of the image. To enable and disable elimination of back-facing polygons, call {@link gl:enable/1}
%% and {@link gl:enable/1} with argument `?GL_CULL_FACE'.
%%
-%% The projection of a polygon to window coordinates is said to have clockwise winding if
-%% an imaginary object following the path from its first vertex, its second vertex, and so
-%% on, to its last vertex, and finally back to its first vertex, moves in a clockwise direction
-%% about the interior of the polygon. The polygon's winding is said to be counterclockwise
-%% if the imaginary object following the same path moves in a counterclockwise direction
-%% about the interior of the polygon. ``gl:frontFace'' specifies whether polygons with
-%% clockwise winding in window coordinates, or counterclockwise winding in window coordinates,
-%% are taken to be front-facing. Passing `?GL_CCW' to `Mode' selects counterclockwise
-%% polygons as front-facing; `?GL_CW' selects clockwise polygons as front-facing. By
-%% default, counterclockwise polygons are taken to be front-facing.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFrontFace.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glFrontFace.xhtml">external</a> documentation.
-spec frontFace(Mode) -> 'ok' when Mode :: enum().
frontFace(Mode) ->
cast(5046, <<Mode:?GLenum>>).
@@ -597,7 +446,7 @@ frontFace(Mode) ->
%% will be used to rasterize points. Otherwise, the value written to the shading language
%% built-in variable gl_PointSize will be used.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPointSize.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPointSize.xhtml">external</a> documentation.
-spec pointSize(Size) -> 'ok' when Size :: float().
pointSize(Size) ->
cast(5047, <<Size:?GLfloat>>).
@@ -609,27 +458,7 @@ pointSize(Size) ->
%% is enabled. To enable and disable line antialiasing, call {@link gl:enable/1} and {@link gl:enable/1}
%% with argument `?GL_LINE_SMOOTH'. Line antialiasing is initially disabled.
%%
-%% If line antialiasing is disabled, the actual width is determined by rounding the supplied
-%% width to the nearest integer. (If the rounding results in the value 0, it is as if the
-%% line width were 1.) If |&amp;Delta; x|&gt;=|&amp;Delta; y|, `i' pixels are filled in each column that is rasterized,
-%% where `i' is the rounded value of `Width' . Otherwise, `i' pixels are filled
-%% in each row that is rasterized.
-%%
-%% If antialiasing is enabled, line rasterization produces a fragment for each pixel square
-%% that intersects the region lying within the rectangle having width equal to the current
-%% line width, length equal to the actual length of the line, and centered on the mathematical
-%% line segment. The coverage value for each fragment is the window coordinate area of the
-%% intersection of the rectangular region with the corresponding pixel square. This value
-%% is saved and used in the final rasterization step.
-%%
-%% Not all widths can be supported when line antialiasing is enabled. If an unsupported
-%% width is requested, the nearest supported width is used. Only width 1 is guaranteed to
-%% be supported; others depend on the implementation. Likewise, there is a range for aliased
-%% line widths as well. To query the range of supported widths and the size difference between
-%% supported widths within the range, call {@link gl:getBooleanv/1} with arguments `?GL_ALIASED_LINE_WIDTH_RANGE'
-%% , `?GL_SMOOTH_LINE_WIDTH_RANGE', and `?GL_SMOOTH_LINE_WIDTH_GRANULARITY'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLineWidth.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glLineWidth.xhtml">external</a> documentation.
-spec lineWidth(Width) -> 'ok' when Width :: float().
lineWidth(Width) ->
cast(5048, <<Width:?GLfloat>>).
@@ -641,27 +470,7 @@ lineWidth(Width) ->
%% stipple pattern `Pattern' , the repeat count `Factor' , and an integer stipple
%% counter s.
%%
-%% Counter s is reset to 0 whenever {@link gl:'begin'/1} is called and before each line segment
-%% of a {@link gl:'begin'/1} (`?GL_LINES')/ {@link gl:'begin'/1} sequence is generated. It is
-%% incremented after each fragment of a unit width aliased line segment is generated or after
-%% each i fragments of an i width line segment are generated. The i fragments associated
-%% with count s are masked out if
-%%
-%% `Pattern' bit (s/factor)% 16
-%%
-%% is 0, otherwise these fragments are sent to the frame buffer. Bit zero of `Pattern'
-%% is the least significant bit.
-%%
-%% Antialiased lines are treated as a sequence of 1×width rectangles for purposes of stippling.
-%% Whether rectangle s is rasterized or not depends on the fragment rule described for
-%% aliased lines, counting rectangles rather than groups of fragments.
-%%
-%% To enable and disable line stippling, call {@link gl:enable/1} and {@link gl:enable/1}
-%% with argument `?GL_LINE_STIPPLE'. When enabled, the line stipple pattern is applied
-%% as described above. When disabled, it is as if the pattern were all 1's. Initially, line
-%% stippling is disabled.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLineStipple.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLineStipple.xml">external</a> documentation.
-spec lineStipple(Factor, Pattern) -> 'ok' when Factor :: integer(),Pattern :: integer().
lineStipple(Factor,Pattern) ->
cast(5049, <<Factor:?GLint,Pattern:?GLushort>>).
@@ -674,22 +483,7 @@ lineStipple(Factor,Pattern) ->
%% polygon's vertices are lit and the polygon is clipped and possibly culled before these
%% modes are applied.
%%
-%% Three modes are defined and can be specified in `Mode' :
-%%
-%% `?GL_POINT': Polygon vertices that are marked as the start of a boundary edge are
-%% drawn as points. Point attributes such as `?GL_POINT_SIZE' and `?GL_POINT_SMOOTH'
-%% control the rasterization of the points. Polygon rasterization attributes other than `?GL_POLYGON_MODE'
-%% have no effect.
-%%
-%% `?GL_LINE': Boundary edges of the polygon are drawn as line segments. Line attributes
-%% such as `?GL_LINE_WIDTH' and `?GL_LINE_SMOOTH' control the rasterization of
-%% the lines. Polygon rasterization attributes other than `?GL_POLYGON_MODE' have no
-%% effect.
-%%
-%% `?GL_FILL': The interior of the polygon is filled. Polygon attributes such as `?GL_POLYGON_SMOOTH'
-%% control the rasterization of the polygon.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPolygonMode.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPolygonMode.xhtml">external</a> documentation.
-spec polygonMode(Face, Mode) -> 'ok' when Face :: enum(),Mode :: enum().
polygonMode(Face,Mode) ->
cast(5050, <<Face:?GLenum,Mode:?GLenum>>).
@@ -704,10 +498,7 @@ polygonMode(Face,Mode) ->
%% a resolvable offset for a given implementation. The offset is added before the depth test
%% is performed and before the value is written into the depth buffer.
%%
-%% ``gl:polygonOffset'' is useful for rendering hidden-line images, for applying decals
-%% to surfaces, and for rendering solids with highlighted edges.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPolygonOffset.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPolygonOffset.xhtml">external</a> documentation.
-spec polygonOffset(Factor, Units) -> 'ok' when Factor :: float(),Units :: float().
polygonOffset(Factor,Units) ->
cast(5051, <<Factor:?GLfloat,Units:?GLfloat>>).
@@ -718,27 +509,7 @@ polygonOffset(Factor,Units) ->
%% fragments produced by rasterization, creating a pattern. Stippling is independent of polygon
%% antialiasing.
%%
-%% `Pattern' is a pointer to a 32×32 stipple pattern that is stored in memory just
-%% like the pixel data supplied to a {@link gl:drawPixels/5} call with height and `width'
-%% both equal to 32, a pixel format of `?GL_COLOR_INDEX', and data type of `?GL_BITMAP'
-%% . That is, the stipple pattern is represented as a 32×32 array of 1-bit color indices
-%% packed in unsigned bytes. {@link gl:pixelStoref/2} parameters like `?GL_UNPACK_SWAP_BYTES'
-%% and `?GL_UNPACK_LSB_FIRST' affect the assembling of the bits into a stipple pattern.
-%% Pixel transfer operations (shift, offset, pixel map) are not applied to the stipple image,
-%% however.
-%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a stipple pattern is specified, `Pattern' is
-%% treated as a byte offset into the buffer object's data store.
-%%
-%% To enable and disable polygon stippling, call {@link gl:enable/1} and {@link gl:enable/1}
-%% with argument `?GL_POLYGON_STIPPLE'. Polygon stippling is initially disabled. If
-%% it's enabled, a rasterized polygon fragment with window coordinates x w and y w is
-%% sent to the next stage of the GL if and only if the ( x w% 32)th bit in the ( y w% 32)th
-%% row of the stipple pattern is 1 (one). When polygon stippling is disabled, it is as if
-%% the stipple pattern consists of all 1's.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPolygonStipple.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPolygonStipple.xml">external</a> documentation.
-spec polygonStipple(Mask) -> 'ok' when Mask :: binary().
polygonStipple(Mask) ->
send_bin(Mask),
@@ -753,11 +524,7 @@ polygonStipple(Mask) ->
%% Unlike {@link gl:readPixels/7} , however, pixel transfer operations (shift, offset, pixel
%% map) are not applied to the returned stipple image.
%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a polygon stipple pattern is requested, `Pattern'
-%% is treated as a byte offset into the buffer object's data store.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetPolygonStipple.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetPolygonStipple.xml">external</a> documentation.
-spec getPolygonStipple() -> binary().
getPolygonStipple() ->
call(5053, <<>>).
@@ -771,13 +538,7 @@ getPolygonStipple() ->
%% of a nonboundary edge. ``gl:edgeFlag'' sets the edge flag bit to `?GL_TRUE' if `Flag'
%% is `?GL_TRUE' and to `?GL_FALSE' otherwise.
%%
-%% The vertices of connected triangles and connected quadrilaterals are always marked as
-%% boundary, regardless of the value of the edge flag.
-%%
-%% Boundary and nonboundary edge flags on vertices are significant only if `?GL_POLYGON_MODE'
-%% is set to `?GL_POINT' or `?GL_LINE'. See {@link gl:polygonMode/2} .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEdgeFlag.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glEdgeFlag.xml">external</a> documentation.
-spec edgeFlag(Flag) -> 'ok' when Flag :: 0|1.
edgeFlag(Flag) ->
cast(5054, <<Flag:?GLboolean>>).
@@ -792,17 +553,7 @@ edgeFlagv({Flag}) -> edgeFlag(Flag).
%% first two arguments, `X' and `Y' , specify the lower left corner of the box. `Width'
%% and `Height' specify the width and height of the box.
%%
-%% To enable and disable the scissor test, call {@link gl:enable/1} and {@link gl:enable/1}
-%% with argument `?GL_SCISSOR_TEST'. The test is initially disabled. While the test
-%% is enabled, only pixels that lie within the scissor box can be modified by drawing commands.
-%% Window coordinates have integer values at the shared corners of frame buffer pixels. glScissor(0,0,1,1)
-%% allows modification of only the lower left pixel in the window, and glScissor(0,0,0,0)
-%% doesn't allow modification of any pixels in the window.
-%%
-%% When the scissor test is disabled, it is as though the scissor box includes the entire
-%% window.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScissor.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glScissor.xhtml">external</a> documentation.
-spec scissor(X, Y, Width, Height) -> 'ok' when X :: integer(),Y :: integer(),Width :: integer(),Height :: integer().
scissor(X,Y,Width,Height) ->
cast(5055, <<X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei>>).
@@ -817,20 +568,7 @@ scissor(X,Y,Width,Height) ->
%% clipping planes. Because the resulting clipping region is the intersection of the defined
%% half-spaces, it is always convex.
%%
-%% ``gl:clipPlane'' specifies a half-space using a four-component plane equation. When ``gl:clipPlane''
-%% is called, `Equation' is transformed by the inverse of the modelview matrix and
-%% stored in the resulting eye coordinates. Subsequent changes to the modelview matrix have
-%% no effect on the stored plane-equation components. If the dot product of the eye coordinates
-%% of a vertex with the stored plane equation components is positive or zero, the vertex is `in'
-%% with respect to that clipping plane. Otherwise, it is `out'.
-%%
-%% To enable and disable clipping planes, call {@link gl:enable/1} and {@link gl:enable/1}
-%% with the argument `?GL_CLIP_PLANE'`i', where `i' is the plane number.
-%%
-%% All clipping planes are initially defined as (0, 0, 0, 0) in eye coordinates and are
-%% disabled.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClipPlane.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glClipPlane.xml">external</a> documentation.
-spec clipPlane(Plane, Equation) -> 'ok' when Plane :: enum(),Equation :: {float(),float(),float(),float()}.
clipPlane(Plane,{E1,E2,E3,E4}) ->
cast(5056, <<Plane:?GLenum,0:32,E1:?GLdouble,E2:?GLdouble,E3:?GLdouble,E4:?GLdouble>>).
@@ -840,7 +578,7 @@ clipPlane(Plane,{E1,E2,E3,E4}) ->
%% ``gl:getClipPlane'' returns in `Equation' the four coefficients of the plane equation
%% for `Plane' .
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetClipPlane.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetClipPlane.xml">external</a> documentation.
-spec getClipPlane(Plane) -> {float(),float(),float(),float()} when Plane :: enum().
getClipPlane(Plane) ->
call(5057, <<Plane:?GLenum>>).
@@ -850,44 +588,7 @@ getClipPlane(Plane) ->
%% When colors are written to the frame buffer, they are written into the color buffers
%% specified by ``gl:drawBuffer''. The specifications are as follows:
%%
-%% `?GL_NONE': No color buffers are written.
-%%
-%% `?GL_FRONT_LEFT': Only the front left color buffer is written.
-%%
-%% `?GL_FRONT_RIGHT': Only the front right color buffer is written.
-%%
-%% `?GL_BACK_LEFT': Only the back left color buffer is written.
-%%
-%% `?GL_BACK_RIGHT': Only the back right color buffer is written.
-%%
-%% `?GL_FRONT': Only the front left and front right color buffers are written. If there
-%% is no front right color buffer, only the front left color buffer is written.
-%%
-%% `?GL_BACK': Only the back left and back right color buffers are written. If there
-%% is no back right color buffer, only the back left color buffer is written.
-%%
-%% `?GL_LEFT': Only the front left and back left color buffers are written. If there
-%% is no back left color buffer, only the front left color buffer is written.
-%%
-%% `?GL_RIGHT': Only the front right and back right color buffers are written. If there
-%% is no back right color buffer, only the front right color buffer is written.
-%%
-%% `?GL_FRONT_AND_BACK': All the front and back color buffers (front left, front right,
-%% back left, back right) are written. If there are no back color buffers, only the front
-%% left and front right color buffers are written. If there are no right color buffers, only
-%% the front left and back left color buffers are written. If there are no right or back
-%% color buffers, only the front left color buffer is written.
-%%
-%% If more than one color buffer is selected for drawing, then blending or logical operations
-%% are computed and applied independently for each color buffer and can produce different
-%% results in each buffer.
-%%
-%% Monoscopic contexts include only `left' buffers, and stereoscopic contexts include
-%% both `left' and `right' buffers. Likewise, single-buffered contexts include
-%% only `front' buffers, and double-buffered contexts include both `front' and `back'
-%% buffers. The context is selected at GL initialization.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawBuffer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawBuffer.xhtml">external</a> documentation.
-spec drawBuffer(Mode) -> 'ok' when Mode :: enum().
drawBuffer(Mode) ->
cast(5058, <<Mode:?GLenum>>).
@@ -904,15 +605,7 @@ drawBuffer(Mode) ->
%% the `i'th color attachment where `i' ranges from zero to the value of `?GL_MAX_COLOR_ATTACHMENTS'
%% minus one.
%%
-%% Nonstereo double-buffered configurations have only a front left and a back left buffer.
-%% Single-buffered configurations have a front left and a front right buffer if stereo, and
-%% only a front left buffer if nonstereo. It is an error to specify a nonexistent buffer to ``gl:readBuffer''
-%% .
-%%
-%% `Mode' is initially `?GL_FRONT' in single-buffered configurations and `?GL_BACK'
-%% in double-buffered configurations.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glReadBuffer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glReadBuffer.xhtml">external</a> documentation.
-spec readBuffer(Mode) -> 'ok' when Mode :: enum().
readBuffer(Mode) ->
cast(5059, <<Mode:?GLenum>>).
@@ -925,104 +618,7 @@ readBuffer(Mode) ->
%% is `?GL_FALSE'. The initial value for `?GL_DITHER' and `?GL_MULTISAMPLE'
%% is `?GL_TRUE'.
%%
-%% Both ``gl:enable'' and {@link gl:enable/1} take a single argument, `Cap' , which
-%% can assume one of the following values:
-%%
-%% Some of the GL's capabilities are indexed. ``gl:enablei'' and ``gl:disablei'' enable
-%% and disable indexed capabilities.
-%%
-%% `?GL_BLEND': If enabled, blend the computed fragment color values with the values
-%% in the color buffers. See {@link gl:blendFunc/2} .
-%%
-%% `?GL_CLIP_DISTANCE'`i': If enabled, clip geometry against user-defined half
-%% space `i'.
-%%
-%% `?GL_COLOR_LOGIC_OP': If enabled, apply the currently selected logical operation
-%% to the computed fragment color and color buffer values. See {@link gl:logicOp/1} .
-%%
-%% `?GL_CULL_FACE': If enabled, cull polygons based on their winding in window coordinates.
-%% See {@link gl:cullFace/1} .
-%%
-%% `?GL_DEPTH_CLAMP': If enabled, the -w c&amp;le; z c&amp;le; w c plane equation is
-%% ignored by view volume clipping (effectively, there is no near or far plane clipping).
-%% See {@link gl:depthRange/2} .
-%%
-%% `?GL_DEPTH_TEST': If enabled, do depth comparisons and update the depth buffer.
-%% Note that even if the depth buffer exists and the depth mask is non-zero, the depth buffer
-%% is not updated if the depth test is disabled. See {@link gl:depthFunc/1} and {@link gl:depthRange/2}
-%% .
-%%
-%% `?GL_DITHER': If enabled, dither color components or indices before they are written
-%% to the color buffer.
-%%
-%% `?GL_FRAMEBUFFER_SRGB': If enabled and the value of `?GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING'
-%% for the framebuffer attachment corresponding to the destination buffer is `?GL_SRGB',
-%% the R, G, and B destination color values (after conversion from fixed-point to floating-point)
-%% are considered to be encoded for the sRGB color space and hence are linearized prior to
-%% their use in blending.
-%%
-%% `?GL_LINE_SMOOTH': If enabled, draw lines with correct filtering. Otherwise, draw
-%% aliased lines. See {@link gl:lineWidth/1} .
-%%
-%% `?GL_MULTISAMPLE': If enabled, use multiple fragment samples in computing the final
-%% color of a pixel. See {@link gl:sampleCoverage/2} .
-%%
-%% `?GL_POLYGON_OFFSET_FILL': If enabled, and if the polygon is rendered in `?GL_FILL'
-%% mode, an offset is added to depth values of a polygon's fragments before the depth comparison
-%% is performed. See {@link gl:polygonOffset/2} .
-%%
-%% `?GL_POLYGON_OFFSET_LINE': If enabled, and if the polygon is rendered in `?GL_LINE'
-%% mode, an offset is added to depth values of a polygon's fragments before the depth comparison
-%% is performed. See {@link gl:polygonOffset/2} .
-%%
-%% `?GL_POLYGON_OFFSET_POINT': If enabled, an offset is added to depth values of a
-%% polygon's fragments before the depth comparison is performed, if the polygon is rendered
-%% in `?GL_POINT' mode. See {@link gl:polygonOffset/2} .
-%%
-%% `?GL_POLYGON_SMOOTH': If enabled, draw polygons with proper filtering. Otherwise,
-%% draw aliased polygons. For correct antialiased polygons, an alpha buffer is needed and
-%% the polygons must be sorted front to back.
-%%
-%% `?GL_PRIMITIVE_RESTART': Enables primitive restarting. If enabled, any one of the
-%% draw commands which transfers a set of generic attribute array elements to the GL will
-%% restart the primitive when the index of the vertex is equal to the primitive restart
-%% index. See {@link gl:primitiveRestartIndex/1} .
-%%
-%% `?GL_SAMPLE_ALPHA_TO_COVERAGE': If enabled, compute a temporary coverage value where
-%% each bit is determined by the alpha value at the corresponding sample location. The temporary
-%% coverage value is then ANDed with the fragment coverage value.
-%%
-%% `?GL_SAMPLE_ALPHA_TO_ONE': If enabled, each sample alpha value is replaced by the
-%% maximum representable alpha value.
-%%
-%% `?GL_SAMPLE_COVERAGE': If enabled, the fragment's coverage is ANDed with the temporary
-%% coverage value. If `?GL_SAMPLE_COVERAGE_INVERT' is set to `?GL_TRUE', invert
-%% the coverage value. See {@link gl:sampleCoverage/2} .
-%%
-%% `?GL_SAMPLE_SHADING': If enabled, the active fragment shader is run once for each
-%% covered sample, or at fraction of this rate as determined by the current value of `?GL_MIN_SAMPLE_SHADING_VALUE'
-%% . See {@link gl:minSampleShading/1} .
-%%
-%% `?GL_SAMPLE_MASK': If enabled, the sample coverage mask generated for a fragment
-%% during rasterization will be ANDed with the value of `?GL_SAMPLE_MASK_VALUE' before
-%% shading occurs. See {@link gl:sampleMaski/2} .
-%%
-%% `?GL_SCISSOR_TEST': If enabled, discard fragments that are outside the scissor rectangle.
-%% See {@link gl:scissor/4} .
-%%
-%% `?GL_STENCIL_TEST': If enabled, do stencil testing and update the stencil buffer.
-%% See {@link gl:stencilFunc/3} and {@link gl:stencilOp/3} .
-%%
-%% `?GL_TEXTURE_CUBE_MAP_SEAMLESS': If enabled, cubemap textures are sampled such that
-%% when linearly sampling from the border between two adjacent faces, texels from both faces
-%% are used to generate the final sample value. When disabled, texels from only a single
-%% face are used to construct the final sample value.
-%%
-%% `?GL_PROGRAM_POINT_SIZE': If enabled and a vertex or geometry shader is active,
-%% then the derived point size is taken from the (potentially clipped) shader builtin `?gl_PointSize'
-%% and clamped to the implementation-dependent point size range.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glEnable.xhtml">external</a> documentation.
-spec enable(Cap) -> 'ok' when Cap :: enum().
enable(Cap) ->
cast(5060, <<Cap:?GLenum>>).
@@ -1042,31 +638,7 @@ disable(Cap) ->
%% all capabilities except `?GL_DITHER' are disabled; `?GL_DITHER' is initially
%% enabled.
%%
-%% The following capabilities are accepted for `Cap' : <table><tbody><tr><td>` Constant '
-%% </td><td>` See '</td></tr></tbody><tbody><tr><td>`?GL_BLEND'</td><td> {@link gl:blendFunc/2}
-%% , {@link gl:logicOp/1} </td></tr><tr><td>`?GL_CLIP_DISTANCE'`i'</td><td> {@link gl:enable/1}
-%% </td></tr><tr><td>`?GL_COLOR_LOGIC_OP'</td><td> {@link gl:logicOp/1} </td></tr><tr><td>`?GL_CULL_FACE'
-%% </td><td> {@link gl:cullFace/1} </td></tr><tr><td>`?GL_DEPTH_CLAMP'</td><td> {@link gl:enable/1}
-%% </td></tr><tr><td>`?GL_DEPTH_TEST'</td><td> {@link gl:depthFunc/1} , {@link gl:depthRange/2}
-%% </td></tr><tr><td>`?GL_DITHER'</td><td> {@link gl:enable/1} </td></tr><tr><td>`?GL_FRAMEBUFFER_SRGB'
-%% </td><td> {@link gl:enable/1} </td></tr><tr><td>`?GL_LINE_SMOOTH'</td><td> {@link gl:lineWidth/1}
-%% </td></tr><tr><td>`?GL_MULTISAMPLE'</td><td> {@link gl:sampleCoverage/2} </td></tr><tr><td>
-%% `?GL_POLYGON_SMOOTH'</td><td> {@link gl:polygonMode/2} </td></tr><tr><td>`?GL_POLYGON_OFFSET_FILL'
-%% </td><td> {@link gl:polygonOffset/2} </td></tr><tr><td>`?GL_POLYGON_OFFSET_LINE'</td><td>
-%% {@link gl:polygonOffset/2} </td></tr><tr><td>`?GL_POLYGON_OFFSET_POINT'</td><td> {@link gl:polygonOffset/2}
-%% </td></tr><tr><td>`?GL_PROGRAM_POINT_SIZE'</td><td> {@link gl:enable/1} </td></tr><tr><td>
-%% `?GL_PRIMITIVE_RESTART'</td><td> {@link gl:enable/1} , {@link gl:primitiveRestartIndex/1} </td>
-%% </tr><tr><td>`?GL_SAMPLE_ALPHA_TO_COVERAGE'</td><td> {@link gl:sampleCoverage/2} </td></tr>
-%% <tr><td>`?GL_SAMPLE_ALPHA_TO_ONE'</td><td> {@link gl:sampleCoverage/2} </td></tr><tr><td>
-%% `?GL_SAMPLE_COVERAGE'</td><td> {@link gl:sampleCoverage/2} </td></tr><tr><td>`?GL_SAMPLE_MASK'
-%% </td><td> {@link gl:enable/1} </td></tr><tr><td>`?GL_SCISSOR_TEST'</td><td> {@link gl:scissor/4}
-%% </td></tr><tr><td>`?GL_STENCIL_TEST'</td><td> {@link gl:stencilFunc/3} , {@link gl:stencilOp/3}
-%% </td></tr><tr><td>`?GL_TEXTURE_CUBEMAP_SEAMLESS'</td><td> {@link gl:enable/1} </td></tr>
-%% </tbody></table>
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsEnabled.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsEnabled.xhtml">external</a> documentation.
-spec isEnabled(Cap) -> 0|1 when Cap :: enum().
isEnabled(Cap) ->
call(5062, <<Cap:?GLenum>>).
@@ -1078,47 +650,7 @@ isEnabled(Cap) ->
%% and {@link gl:enableClientState/1} take a single argument, `Cap' , which can assume
%% one of the following values:
%%
-%% `?GL_COLOR_ARRAY': If enabled, the color array is enabled for writing and used during
-%% rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4} ,
-%% {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements'
-%% is called. See {@link gl:colorPointer/4} .
-%%
-%% `?GL_EDGE_FLAG_ARRAY': If enabled, the edge flag array is enabled for writing and
-%% used during rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4}
-%% , {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements'
-%% is called. See {@link gl:edgeFlagPointer/2} .
-%%
-%% `?GL_FOG_COORD_ARRAY': If enabled, the fog coordinate array is enabled for writing
-%% and used during rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4}
-%% , {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements'
-%% is called. See {@link gl:fogCoordPointer/3} .
-%%
-%% `?GL_INDEX_ARRAY': If enabled, the index array is enabled for writing and used during
-%% rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4} ,
-%% {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements'
-%% is called. See {@link gl:indexPointer/3} .
-%%
-%% `?GL_NORMAL_ARRAY': If enabled, the normal array is enabled for writing and used
-%% during rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4}
-%% , {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements'
-%% is called. See {@link gl:normalPointer/3} .
-%%
-%% `?GL_SECONDARY_COLOR_ARRAY': If enabled, the secondary color array is enabled for
-%% writing and used during rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4}
-%% , {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements'
-%% is called. See {@link gl:colorPointer/4} .
-%%
-%% `?GL_TEXTURE_COORD_ARRAY': If enabled, the texture coordinate array is enabled for
-%% writing and used during rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4}
-%% , {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements'
-%% is called. See {@link gl:texCoordPointer/4} .
-%%
-%% `?GL_VERTEX_ARRAY': If enabled, the vertex array is enabled for writing and used
-%% during rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4}
-%% , {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements'
-%% is called. See {@link gl:vertexPointer/4} .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEnableClientState.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glEnableClientState.xml">external</a> documentation.
-spec enableClientState(Cap) -> 'ok' when Cap :: enum().
enableClientState(Cap) ->
cast(5063, <<Cap:?GLenum>>).
@@ -1135,809 +667,7 @@ disableClientState(Cap) ->
%% symbolic constant indicating the state variable to be returned, and `Params' is a
%% pointer to an array of the indicated type in which to place the returned data.
%%
-%% Type conversion is performed if `Params' has a different type than the state variable
-%% value being requested. If ``gl:getBooleanv'' is called, a floating-point (or integer)
-%% value is converted to `?GL_FALSE' if and only if it is 0.0 (or 0). Otherwise, it
-%% is converted to `?GL_TRUE'. If ``gl:getIntegerv'' is called, boolean values are
-%% returned as `?GL_TRUE' or `?GL_FALSE', and most floating-point values are rounded
-%% to the nearest integer value. Floating-point colors and normals, however, are returned
-%% with a linear mapping that maps 1.0 to the most positive representable integer value and
-%% -1.0 to the most negative representable integer value. If ``gl:getFloatv'' or ``gl:getDoublev''
-%% is called, boolean values are returned as `?GL_TRUE' or `?GL_FALSE', and integer
-%% values are converted to floating-point values.
-%%
-%% The following symbolic constants are accepted by `Pname' :
-%%
-%% `?GL_ACTIVE_TEXTURE': `Params' returns a single value indicating the active
-%% multitexture unit. The initial value is `?GL_TEXTURE0'. See {@link gl:activeTexture/1} .
-%%
-%%
-%% `?GL_ALIASED_LINE_WIDTH_RANGE': `Params' returns a pair of values indicating
-%% the range of widths supported for aliased lines. See {@link gl:lineWidth/1} .
-%%
-%% `?GL_ARRAY_BUFFER_BINDING': `Params' returns a single value, the name of the
-%% buffer object currently bound to the target `?GL_ARRAY_BUFFER'. If no buffer object
-%% is bound to this target, 0 is returned. The initial value is 0. See {@link gl:bindBuffer/2} .
-%%
-%%
-%% `?GL_BLEND': `Params' returns a single boolean value indicating whether blending
-%% is enabled. The initial value is `?GL_FALSE'. See {@link gl:blendFunc/2} .
-%%
-%% `?GL_BLEND_COLOR': `Params' returns four values, the red, green, blue, and alpha
-%% values which are the components of the blend color. See {@link gl:blendColor/4} .
-%%
-%% `?GL_BLEND_DST_ALPHA': `Params' returns one value, the symbolic constant identifying
-%% the alpha destination blend function. The initial value is `?GL_ZERO'. See {@link gl:blendFunc/2}
-%% and {@link gl:blendFuncSeparate/4} .
-%%
-%% `?GL_BLEND_DST_RGB': `Params' returns one value, the symbolic constant identifying
-%% the RGB destination blend function. The initial value is `?GL_ZERO'. See {@link gl:blendFunc/2}
-%% and {@link gl:blendFuncSeparate/4} .
-%%
-%% `?GL_BLEND_EQUATION_RGB': `Params' returns one value, a symbolic constant indicating
-%% whether the RGB blend equation is `?GL_FUNC_ADD', `?GL_FUNC_SUBTRACT', `?GL_FUNC_REVERSE_SUBTRACT'
-%% , `?GL_MIN' or `?GL_MAX'. See {@link gl:blendEquationSeparate/2} .
-%%
-%% `?GL_BLEND_EQUATION_ALPHA': `Params' returns one value, a symbolic constant
-%% indicating whether the Alpha blend equation is `?GL_FUNC_ADD', `?GL_FUNC_SUBTRACT'
-%% , `?GL_FUNC_REVERSE_SUBTRACT', `?GL_MIN' or `?GL_MAX'. See {@link gl:blendEquationSeparate/2}
-%% .
-%%
-%% `?GL_BLEND_SRC_ALPHA': `Params' returns one value, the symbolic constant identifying
-%% the alpha source blend function. The initial value is `?GL_ONE'. See {@link gl:blendFunc/2}
-%% and {@link gl:blendFuncSeparate/4} .
-%%
-%% `?GL_BLEND_SRC_RGB': `Params' returns one value, the symbolic constant identifying
-%% the RGB source blend function. The initial value is `?GL_ONE'. See {@link gl:blendFunc/2}
-%% and {@link gl:blendFuncSeparate/4} .
-%%
-%% `?GL_COLOR_CLEAR_VALUE': `Params' returns four values: the red, green, blue,
-%% and alpha values used to clear the color buffers. Integer values, if requested, are linearly
-%% mapped from the internal floating-point representation such that 1.0 returns the most
-%% positive representable integer value, and -1.0 returns the most negative representable
-%% integer value. The initial value is (0, 0, 0, 0). See {@link gl:clearColor/4} .
-%%
-%% `?GL_COLOR_LOGIC_OP': `Params' returns a single boolean value indicating whether
-%% a fragment's RGBA color values are merged into the framebuffer using a logical operation.
-%% The initial value is `?GL_FALSE'. See {@link gl:logicOp/1} .
-%%
-%% `?GL_COLOR_WRITEMASK': `Params' returns four boolean values: the red, green,
-%% blue, and alpha write enables for the color buffers. The initial value is (`?GL_TRUE',
-%% `?GL_TRUE', `?GL_TRUE', `?GL_TRUE'). See {@link gl:colorMask/4} .
-%%
-%% `?GL_COMPRESSED_TEXTURE_FORMATS': `Params' returns a list of symbolic constants
-%% of length `?GL_NUM_COMPRESSED_TEXTURE_FORMATS' indicating which compressed texture
-%% formats are available. See {@link gl:compressedTexImage2D/8} .
-%%
-%% `?GL_CONTEXT_FLAGS': `Params' returns one value, the flags with which the context
-%% was created (such as debugging functionality).
-%%
-%% `?GL_CULL_FACE': `Params' returns a single boolean value indicating whether
-%% polygon culling is enabled. The initial value is `?GL_FALSE'. See {@link gl:cullFace/1}
-%% .
-%%
-%% `?GL_CURRENT_PROGRAM': `Params' returns one value, the name of the program object
-%% that is currently active, or 0 if no program object is active. See {@link gl:useProgram/1} .
-%%
-%%
-%% `?GL_DEPTH_CLEAR_VALUE': `Params' returns one value, the value that is used
-%% to clear the depth buffer. Integer values, if requested, are linearly mapped from the
-%% internal floating-point representation such that 1.0 returns the most positive representable
-%% integer value, and -1.0 returns the most negative representable integer value. The initial
-%% value is 1. See {@link gl:clearDepth/1} .
-%%
-%% `?GL_DEPTH_FUNC': `Params' returns one value, the symbolic constant that indicates
-%% the depth comparison function. The initial value is `?GL_LESS'. See {@link gl:depthFunc/1}
-%% .
-%%
-%% `?GL_DEPTH_RANGE': `Params' returns two values: the near and far mapping limits
-%% for the depth buffer. Integer values, if requested, are linearly mapped from the internal
-%% floating-point representation such that 1.0 returns the most positive representable integer
-%% value, and -1.0 returns the most negative representable integer value. The initial value
-%% is (0, 1). See {@link gl:depthRange/2} .
-%%
-%% `?GL_DEPTH_TEST': `Params' returns a single boolean value indicating whether
-%% depth testing of fragments is enabled. The initial value is `?GL_FALSE'. See {@link gl:depthFunc/1}
-%% and {@link gl:depthRange/2} .
-%%
-%% `?GL_DEPTH_WRITEMASK': `Params' returns a single boolean value indicating if
-%% the depth buffer is enabled for writing. The initial value is `?GL_TRUE'. See {@link gl:depthMask/1}
-%% .
-%%
-%% `?GL_DITHER': `Params' returns a single boolean value indicating whether dithering
-%% of fragment colors and indices is enabled. The initial value is `?GL_TRUE'.
-%%
-%% `?GL_DOUBLEBUFFER': `Params' returns a single boolean value indicating whether
-%% double buffering is supported.
-%%
-%% `?GL_DRAW_BUFFER': `Params' returns one value, a symbolic constant indicating
-%% which buffers are being drawn to. See {@link gl:drawBuffer/1} . The initial value is `?GL_BACK'
-%% if there are back buffers, otherwise it is `?GL_FRONT'.
-%%
-%% `?GL_DRAW_BUFFER'`i': `Params' returns one value, a symbolic constant indicating
-%% which buffers are being drawn to by the corresponding output color. See {@link gl:drawBuffers/1}
-%% . The initial value of `?GL_DRAW_BUFFER0' is `?GL_BACK' if there are back buffers,
-%% otherwise it is `?GL_FRONT'. The initial values of draw buffers for all other output
-%% colors is `?GL_NONE'.
-%%
-%% `?GL_DRAW_FRAMEBUFFER_BINDING': `Params' returns one value, the name of the
-%% framebuffer object currently bound to the `?GL_DRAW_FRAMEBUFFER' target. If the default
-%% framebuffer is bound, this value will be zero. The initial value is zero. See {@link gl:bindFramebuffer/2}
-%% .
-%%
-%% `?GL_READ_FRAMEBUFFER_BINDING': `Params' returns one value, the name of the
-%% framebuffer object currently bound to the `?GL_READ_FRAMEBUFFER' target. If the default
-%% framebuffer is bound, this value will be zero. The initial value is zero. See {@link gl:bindFramebuffer/2}
-%% .
-%%
-%% `?GL_ELEMENT_ARRAY_BUFFER_BINDING': `Params' returns a single value, the name
-%% of the buffer object currently bound to the target `?GL_ELEMENT_ARRAY_BUFFER'. If
-%% no buffer object is bound to this target, 0 is returned. The initial value is 0. See {@link gl:bindBuffer/2}
-%% .
-%%
-%% `?GL_FRAGMENT_SHADER_DERIVATIVE_HINT': `Params' returns one value, a symbolic
-%% constant indicating the mode of the derivative accuracy hint for fragment shaders. The
-%% initial value is `?GL_DONT_CARE'. See {@link gl:hint/2} .
-%%
-%% `?GL_IMPLEMENTATION_COLOR_READ_FORMAT': `Params' returns a single GLenum value
-%% indicating the implementation's preferred pixel data format. See {@link gl:readPixels/7} .
-%%
-%% `?GL_IMPLEMENTATION_COLOR_READ_TYPE': `Params' returns a single GLenum value
-%% indicating the implementation's preferred pixel data type. See {@link gl:readPixels/7} .
-%%
-%% `?GL_LINE_SMOOTH': `Params' returns a single boolean value indicating whether
-%% antialiasing of lines is enabled. The initial value is `?GL_FALSE'. See {@link gl:lineWidth/1}
-%% .
-%%
-%% `?GL_LINE_SMOOTH_HINT': `Params' returns one value, a symbolic constant indicating
-%% the mode of the line antialiasing hint. The initial value is `?GL_DONT_CARE'. See {@link gl:hint/2}
-%% .
-%%
-%% `?GL_LINE_WIDTH': `Params' returns one value, the line width as specified with {@link gl:lineWidth/1}
-%% . The initial value is 1.
-%%
-%% `?GL_LAYER_PROVOKING_VERTEX': `Params' returns one value, the implementation
-%% dependent specifc vertex of a primitive that is used to select the rendering layer. If
-%% the value returned is equivalent to `?GL_PROVOKING_VERTEX', then the vertex selection
-%% follows the convention specified by {@link gl:provokingVertex/1} . If the value returned
-%% is equivalent to `?GL_FIRST_VERTEX_CONVENTION', then the selection is always taken
-%% from the first vertex in the primitive. If the value returned is equivalent to `?GL_LAST_VERTEX_CONVENTION'
-%% , then the selection is always taken from the last vertex in the primitive. If the value
-%% returned is equivalent to `?GL_UNDEFINED_VERTEX', then the selection is not guaranteed
-%% to be taken from any specific vertex in the primitive.
-%%
-%% `?GL_LINE_WIDTH_GRANULARITY': `Params' returns one value, the width difference
-%% between adjacent supported widths for antialiased lines. See {@link gl:lineWidth/1} .
-%%
-%% `?GL_LINE_WIDTH_RANGE': `Params' returns two values: the smallest and largest
-%% supported widths for antialiased lines. See {@link gl:lineWidth/1} .
-%%
-%% `?GL_LOGIC_OP_MODE': `Params' returns one value, a symbolic constant indicating
-%% the selected logic operation mode. The initial value is `?GL_COPY'. See {@link gl:logicOp/1}
-%% .
-%%
-%% `?GL_MAJOR_VERSION': `Params' returns one value, the major version number of
-%% the OpenGL API supported by the current context.
-%%
-%% `?GL_MAX_3D_TEXTURE_SIZE': `Params' returns one value, a rough estimate of the
-%% largest 3D texture that the GL can handle. The value must be at least 64. Use `?GL_PROXY_TEXTURE_3D'
-%% to determine if a texture is too large. See {@link gl:texImage3D/10} .
-%%
-%% `?GL_MAX_ARRAY_TEXTURE_LAYERS': `Params' returns one value. The value indicates
-%% the maximum number of layers allowed in an array texture, and must be at least 256. See {@link gl:texImage2D/9}
-%% .
-%%
-%% `?GL_MAX_CLIP_DISTANCES': `Params' returns one value, the maximum number of
-%% application-defined clipping distances. The value must be at least 8.
-%%
-%% `?GL_MAX_COLOR_TEXTURE_SAMPLES': `Params' returns one value, the maximum number
-%% of samples in a color multisample texture.
-%%
-%% `?GL_MAX_COMBINED_ATOMIC_COUNTERS': `Params' returns a single value, the maximum
-%% number of atomic counters available to all active shaders.
-%%
-%% `?GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS': `Params' returns one value,
-%% the number of words for fragment shader uniform variables in all uniform blocks (including
-%% default). The value must be at least 1. See {@link gl:uniform1f/2} .
-%%
-%% `?GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS': `Params' returns one value,
-%% the number of words for geometry shader uniform variables in all uniform blocks (including
-%% default). The value must be at least 1. See {@link gl:uniform1f/2} .
-%%
-%% `?GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS': `Params' returns one value, the maximum
-%% supported texture image units that can be used to access texture maps from the vertex
-%% shader and the fragment processor combined. If both the vertex shader and the fragment
-%% processing stage access the same texture image unit, then that counts as using two texture
-%% image units against this limit. The value must be at least 48. See {@link gl:activeTexture/1}
-%% .
-%%
-%% `?GL_MAX_COMBINED_UNIFORM_BLOCKS': `Params' returns one value, the maximum number
-%% of uniform blocks per program. The value must be at least 36. See {@link gl:uniformBlockBinding/3}
-%% .
-%%
-%% `?GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS': `Params' returns one value, the
-%% number of words for vertex shader uniform variables in all uniform blocks (including default).
-%% The value must be at least 1. See {@link gl:uniform1f/2} .
-%%
-%% `?GL_MAX_CUBE_MAP_TEXTURE_SIZE': `Params' returns one value. The value gives
-%% a rough estimate of the largest cube-map texture that the GL can handle. The value must
-%% be at least 1024. Use `?GL_PROXY_TEXTURE_CUBE_MAP' to determine if a texture is too
-%% large. See {@link gl:texImage2D/9} .
-%%
-%% `?GL_MAX_DEPTH_TEXTURE_SAMPLES': `Params' returns one value, the maximum number
-%% of samples in a multisample depth or depth-stencil texture.
-%%
-%% `?GL_MAX_DRAW_BUFFERS': `Params' returns one value, the maximum number of simultaneous
-%% outputs that may be written in a fragment shader. The value must be at least 8. See {@link gl:drawBuffers/1}
-%% .
-%%
-%% `?GL_MAX_DUALSOURCE_DRAW_BUFFERS': `Params' returns one value, the maximum number
-%% of active draw buffers when using dual-source blending. The value must be at least 1.
-%% See {@link gl:blendFunc/2} and {@link gl:blendFuncSeparate/4} .
-%%
-%% `?GL_MAX_ELEMENTS_INDICES': `Params' returns one value, the recommended maximum
-%% number of vertex array indices. See {@link gl:drawRangeElements/6} .
-%%
-%% `?GL_MAX_ELEMENTS_VERTICES': `Params' returns one value, the recommended maximum
-%% number of vertex array vertices. See {@link gl:drawRangeElements/6} .
-%%
-%% `?GL_MAX_FRAGMENT_ATOMIC_COUNTERS': `Params' returns a single value, the maximum
-%% number of atomic counters available to fragment shaders.
-%%
-%% `?GL_MAX_FRAGMENT_INPUT_COMPONENTS': `Params' returns one value, the maximum
-%% number of components of the inputs read by the fragment shader, which must be at least
-%% 128.
-%%
-%% `?GL_MAX_FRAGMENT_UNIFORM_COMPONENTS': `Params' returns one value, the maximum
-%% number of individual floating-point, integer, or boolean values that can be held in uniform
-%% variable storage for a fragment shader. The value must be at least 1024. See {@link gl:uniform1f/2}
-%% .
-%%
-%% `?GL_MAX_FRAGMENT_UNIFORM_VECTORS': `Params' returns one value, the maximum
-%% number of individual 4-vectors of floating-point, integer, or boolean values that can
-%% be held in uniform variable storage for a fragment shader. The value is equal to the value
-%% of `?GL_MAX_FRAGMENT_UNIFORM_COMPONENTS' divided by 4 and must be at least 256. See {@link gl:uniform1f/2}
-%% .
-%%
-%% `?GL_MAX_FRAGMENT_UNIFORM_BLOCKS': `Params' returns one value, the maximum number
-%% of uniform blocks per fragment shader. The value must be at least 12. See {@link gl:uniformBlockBinding/3}
-%% .
-%%
-%% `?GL_MAX_GEOMETRY_ATOMIC_COUNTERS': `Params' returns a single value, the maximum
-%% number of atomic counters available to geometry shaders.
-%%
-%% `?GL_MAX_GEOMETRY_INPUT_COMPONENTS': `Params' returns one value, the maximum
-%% number of components of inputs read by a geometry shader, which must be at least 64.
-%%
-%% `?GL_MAX_GEOMETRY_OUTPUT_COMPONENTS': `Params' returns one value, the maximum
-%% number of components of outputs written by a geometry shader, which must be at least 128.
-%%
-%%
-%% `?GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS': `Params' returns one value, the maximum
-%% supported texture image units that can be used to access texture maps from the geometry
-%% shader. The value must be at least 16. See {@link gl:activeTexture/1} .
-%%
-%% `?GL_MAX_GEOMETRY_UNIFORM_BLOCKS': `Params' returns one value, the maximum number
-%% of uniform blocks per geometry shader. The value must be at least 12. See {@link gl:uniformBlockBinding/3}
-%% .
-%%
-%% `?GL_MAX_GEOMETRY_UNIFORM_COMPONENTS': `Params' returns one value, the maximum
-%% number of individual floating-point, integer, or boolean values that can be held in uniform
-%% variable storage for a geometry shader. The value must be at least 1024. See {@link gl:uniform1f/2}
-%% .
-%%
-%% `?GL_MAX_INTEGER_SAMPLES': `Params' returns one value, the maximum number of
-%% samples supported in integer format multisample buffers.
-%%
-%% `?GL_MIN_MAP_BUFFER_ALIGNMENT': `Params' returns one value, the minimum alignment
-%% in basic machine units of pointers returned fromsee `glMapBuffer' and see `glMapBufferRange'
-%% . This value must be a power of two and must be at least 64.
-%%
-%% `?GL_MAX_PROGRAM_TEXEL_OFFSET': `Params' returns one value, the maximum texel
-%% offset allowed in a texture lookup, which must be at least 7.
-%%
-%% `?GL_MIN_PROGRAM_TEXEL_OFFSET': `Params' returns one value, the minimum texel
-%% offset allowed in a texture lookup, which must be at most -8.
-%%
-%% `?GL_MAX_RECTANGLE_TEXTURE_SIZE': `Params' returns one value. The value gives
-%% a rough estimate of the largest rectangular texture that the GL can handle. The value
-%% must be at least 1024. Use `?GL_PROXY_RECTANGLE_TEXTURE' to determine if a texture
-%% is too large. See {@link gl:texImage2D/9} .
-%%
-%% `?GL_MAX_RENDERBUFFER_SIZE': `Params' returns one value. The value indicates
-%% the maximum supported size for renderbuffers. See {@link gl:framebufferRenderbuffer/4} .
-%%
-%% `?GL_MAX_SAMPLE_MASK_WORDS': `Params' returns one value, the maximum number
-%% of sample mask words.
-%%
-%% `?GL_MAX_SERVER_WAIT_TIMEOUT': `Params' returns one value, the maximum {@link gl:waitSync/3}
-%% timeout interval.
-%%
-%% `?GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS': `Params' returns a single value, the
-%% maximum number of atomic counters available to tessellation control shaders.
-%%
-%% `?GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS': `Params' returns a single value,
-%% the maximum number of atomic counters available to tessellation evaluation shaders.
-%%
-%% `?GL_MAX_TEXTURE_BUFFER_SIZE': `Params' returns one value. The value gives the
-%% maximum number of texels allowed in the texel array of a texture buffer object. Value
-%% must be at least 65536.
-%%
-%% `?GL_MAX_TEXTURE_IMAGE_UNITS': `Params' returns one value, the maximum supported
-%% texture image units that can be used to access texture maps from the fragment shader.
-%% The value must be at least 16. See {@link gl:activeTexture/1} .
-%%
-%% `?GL_MAX_TEXTURE_LOD_BIAS': `Params' returns one value, the maximum, absolute
-%% value of the texture level-of-detail bias. The value must be at least 2.0.
-%%
-%% `?GL_MAX_TEXTURE_SIZE': `Params' returns one value. The value gives a rough
-%% estimate of the largest texture that the GL can handle. The value must be at least 1024.
-%% Use a proxy texture target such as `?GL_PROXY_TEXTURE_1D' or `?GL_PROXY_TEXTURE_2D'
-%% to determine if a texture is too large. See {@link gl:texImage1D/8} and {@link gl:texImage2D/9}
-%% .
-%%
-%% `?GL_MAX_UNIFORM_BUFFER_BINDINGS': `Params' returns one value, the maximum number
-%% of uniform buffer binding points on the context, which must be at least 36.
-%%
-%% `?GL_MAX_UNIFORM_BLOCK_SIZE': `Params' returns one value, the maximum size in
-%% basic machine units of a uniform block, which must be at least 16384.
-%%
-%% `?GL_MAX_VARYING_COMPONENTS': `Params' returns one value, the number components
-%% for varying variables, which must be at least 60.
-%%
-%% `?GL_MAX_VARYING_VECTORS': `Params' returns one value, the number 4-vectors
-%% for varying variables, which is equal to the value of `?GL_MAX_VARYING_COMPONENTS'
-%% and must be at least 15.
-%%
-%% `?GL_MAX_VARYING_FLOATS': `Params' returns one value, the maximum number of
-%% interpolators available for processing varying variables used by vertex and fragment shaders.
-%% This value represents the number of individual floating-point values that can be interpolated;
-%% varying variables declared as vectors, matrices, and arrays will all consume multiple
-%% interpolators. The value must be at least 32.
-%%
-%% `?GL_MAX_VERTEX_ATOMIC_COUNTERS': `Params' returns a single value, the maximum
-%% number of atomic counters available to vertex shaders.
-%%
-%% `?GL_MAX_VERTEX_ATTRIBS': `Params' returns one value, the maximum number of
-%% 4-component generic vertex attributes accessible to a vertex shader. The value must be
-%% at least 16. See {@link gl:vertexAttrib1d/2} .
-%%
-%% `?GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS': `Params' returns one value, the maximum
-%% supported texture image units that can be used to access texture maps from the vertex
-%% shader. The value may be at least 16. See {@link gl:activeTexture/1} .
-%%
-%% `?GL_MAX_VERTEX_UNIFORM_COMPONENTS': `Params' returns one value, the maximum
-%% number of individual floating-point, integer, or boolean values that can be held in uniform
-%% variable storage for a vertex shader. The value must be at least 1024. See {@link gl:uniform1f/2}
-%% .
-%%
-%% `?GL_MAX_VERTEX_UNIFORM_VECTORS': `Params' returns one value, the maximum number
-%% of 4-vectors that may be held in uniform variable storage for the vertex shader. The value
-%% of `?GL_MAX_VERTEX_UNIFORM_VECTORS' is equal to the value of `?GL_MAX_VERTEX_UNIFORM_COMPONENTS'
-%% and must be at least 256.
-%%
-%% `?GL_MAX_VERTEX_OUTPUT_COMPONENTS': `Params' returns one value, the maximum
-%% number of components of output written by a vertex shader, which must be at least 64.
-%%
-%% `?GL_MAX_VERTEX_UNIFORM_BLOCKS': `Params' returns one value, the maximum number
-%% of uniform blocks per vertex shader. The value must be at least 12. See {@link gl:uniformBlockBinding/3}
-%% .
-%%
-%% `?GL_MAX_VIEWPORT_DIMS': `Params' returns two values: the maximum supported
-%% width and height of the viewport. These must be at least as large as the visible dimensions
-%% of the display being rendered to. See {@link gl:viewport/4} .
-%%
-%% `?GL_MAX_VIEWPORTS': `Params' returns one value, the maximum number of simultaneous
-%% viewports that are supported. The value must be at least 16. See {@link gl:viewportIndexedf/5}
-%% .
-%%
-%% `?GL_MINOR_VERSION': `Params' returns one value, the minor version number of
-%% the OpenGL API supported by the current context.
-%%
-%% `?GL_NUM_COMPRESSED_TEXTURE_FORMATS': `Params' returns a single integer value
-%% indicating the number of available compressed texture formats. The minimum value is 4.
-%% See {@link gl:compressedTexImage2D/8} .
-%%
-%% `?GL_NUM_EXTENSIONS': `Params' returns one value, the number of extensions supported
-%% by the GL implementation for the current context. See {@link gl:getString/1} .
-%%
-%% `?GL_NUM_PROGRAM_BINARY_FORMATS': `Params' returns one value, the number of
-%% program binary formats supported by the implementation.
-%%
-%% `?GL_NUM_SHADER_BINARY_FORMATS': `Params' returns one value, the number of binary
-%% shader formats supported by the implementation. If this value is greater than zero, then
-%% the implementation supports loading binary shaders. If it is zero, then the loading of
-%% binary shaders by the implementation is not supported.
-%%
-%% `?GL_PACK_ALIGNMENT': `Params' returns one value, the byte alignment used for
-%% writing pixel data to memory. The initial value is 4. See {@link gl:pixelStoref/2} .
-%%
-%% `?GL_PACK_IMAGE_HEIGHT': `Params' returns one value, the image height used for
-%% writing pixel data to memory. The initial value is 0. See {@link gl:pixelStoref/2} .
-%%
-%% `?GL_PACK_LSB_FIRST': `Params' returns a single boolean value indicating whether
-%% single-bit pixels being written to memory are written first to the least significant bit
-%% of each unsigned byte. The initial value is `?GL_FALSE'. See {@link gl:pixelStoref/2} .
-%%
-%%
-%% `?GL_PACK_ROW_LENGTH': `Params' returns one value, the row length used for writing
-%% pixel data to memory. The initial value is 0. See {@link gl:pixelStoref/2} .
-%%
-%% `?GL_PACK_SKIP_IMAGES': `Params' returns one value, the number of pixel images
-%% skipped before the first pixel is written into memory. The initial value is 0. See {@link gl:pixelStoref/2}
-%% .
-%%
-%% `?GL_PACK_SKIP_PIXELS': `Params' returns one value, the number of pixel locations
-%% skipped before the first pixel is written into memory. The initial value is 0. See {@link gl:pixelStoref/2}
-%% .
-%%
-%% `?GL_PACK_SKIP_ROWS': `Params' returns one value, the number of rows of pixel
-%% locations skipped before the first pixel is written into memory. The initial value is
-%% 0. See {@link gl:pixelStoref/2} .
-%%
-%% `?GL_PACK_SWAP_BYTES': `Params' returns a single boolean value indicating whether
-%% the bytes of two-byte and four-byte pixel indices and components are swapped before being
-%% written to memory. The initial value is `?GL_FALSE'. See {@link gl:pixelStoref/2} .
-%%
-%% `?GL_PIXEL_PACK_BUFFER_BINDING': `Params' returns a single value, the name of
-%% the buffer object currently bound to the target `?GL_PIXEL_PACK_BUFFER'. If no buffer
-%% object is bound to this target, 0 is returned. The initial value is 0. See {@link gl:bindBuffer/2}
-%% .
-%%
-%% `?GL_PIXEL_UNPACK_BUFFER_BINDING': `Params' returns a single value, the name
-%% of the buffer object currently bound to the target `?GL_PIXEL_UNPACK_BUFFER'. If
-%% no buffer object is bound to this target, 0 is returned. The initial value is 0. See {@link gl:bindBuffer/2}
-%% .
-%%
-%% `?GL_POINT_FADE_THRESHOLD_SIZE': `Params' returns one value, the point size
-%% threshold for determining the point size. See {@link gl:pointParameterf/2} .
-%%
-%% `?GL_PRIMITIVE_RESTART_INDEX': `Params' returns one value, the current primitive
-%% restart index. The initial value is 0. See {@link gl:primitiveRestartIndex/1} .
-%%
-%% `?GL_PROGRAM_BINARY_FORMATS': `Params' an array of `?GL_NUM_PROGRAM_BINARY_FORMATS'
-%% values, indicating the proram binary formats supported by the implementation.
-%%
-%% `?GL_PROGRAM_PIPELINE_BINDING': `Params' a single value, the name of the currently
-%% bound program pipeline object, or zero if no program pipeline object is bound. See {@link gl:bindProgramPipeline/1}
-%% .
-%%
-%% `?GL_PROVOKING_VERTEX': `Params' returns one value, the currently selected provoking
-%% vertex convention. The initial value is `?GL_LAST_VERTEX_CONVENTION'. See {@link gl:provokingVertex/1}
-%% .
-%%
-%% `?GL_POINT_SIZE': `Params' returns one value, the point size as specified by {@link gl:pointSize/1}
-%% . The initial value is 1.
-%%
-%% `?GL_POINT_SIZE_GRANULARITY': `Params' returns one value, the size difference
-%% between adjacent supported sizes for antialiased points. See {@link gl:pointSize/1} .
-%%
-%% `?GL_POINT_SIZE_RANGE': `Params' returns two values: the smallest and largest
-%% supported sizes for antialiased points. The smallest size must be at most 1, and the largest
-%% size must be at least 1. See {@link gl:pointSize/1} .
-%%
-%% `?GL_POLYGON_OFFSET_FACTOR': `Params' returns one value, the scaling factor
-%% used to determine the variable offset that is added to the depth value of each fragment
-%% generated when a polygon is rasterized. The initial value is 0. See {@link gl:polygonOffset/2}
-%% .
-%%
-%% `?GL_POLYGON_OFFSET_UNITS': `Params' returns one value. This value is multiplied
-%% by an implementation-specific value and then added to the depth value of each fragment
-%% generated when a polygon is rasterized. The initial value is 0. See {@link gl:polygonOffset/2}
-%% .
-%%
-%% `?GL_POLYGON_OFFSET_FILL': `Params' returns a single boolean value indicating
-%% whether polygon offset is enabled for polygons in fill mode. The initial value is `?GL_FALSE'
-%% . See {@link gl:polygonOffset/2} .
-%%
-%% `?GL_POLYGON_OFFSET_LINE': `Params' returns a single boolean value indicating
-%% whether polygon offset is enabled for polygons in line mode. The initial value is `?GL_FALSE'
-%% . See {@link gl:polygonOffset/2} .
-%%
-%% `?GL_POLYGON_OFFSET_POINT': `Params' returns a single boolean value indicating
-%% whether polygon offset is enabled for polygons in point mode. The initial value is `?GL_FALSE'
-%% . See {@link gl:polygonOffset/2} .
-%%
-%% `?GL_POLYGON_SMOOTH': `Params' returns a single boolean value indicating whether
-%% antialiasing of polygons is enabled. The initial value is `?GL_FALSE'. See {@link gl:polygonMode/2}
-%% .
-%%
-%% `?GL_POLYGON_SMOOTH_HINT': `Params' returns one value, a symbolic constant indicating
-%% the mode of the polygon antialiasing hint. The initial value is `?GL_DONT_CARE'.
-%% See {@link gl:hint/2} .
-%%
-%% `?GL_READ_BUFFER': `Params' returns one value, a symbolic constant indicating
-%% which color buffer is selected for reading. The initial value is `?GL_BACK' if there
-%% is a back buffer, otherwise it is `?GL_FRONT'. See {@link gl:readPixels/7} .
-%%
-%% `?GL_RENDERBUFFER_BINDING': `Params' returns a single value, the name of the
-%% renderbuffer object currently bound to the target `?GL_RENDERBUFFER'. If no renderbuffer
-%% object is bound to this target, 0 is returned. The initial value is 0. See {@link gl:bindRenderbuffer/2}
-%% .
-%%
-%% `?GL_SAMPLE_BUFFERS': `Params' returns a single integer value indicating the
-%% number of sample buffers associated with the framebuffer. See {@link gl:sampleCoverage/2} .
-%%
-%%
-%% `?GL_SAMPLE_COVERAGE_VALUE': `Params' returns a single positive floating-point
-%% value indicating the current sample coverage value. See {@link gl:sampleCoverage/2} .
-%%
-%% `?GL_SAMPLE_COVERAGE_INVERT': `Params' returns a single boolean value indicating
-%% if the temporary coverage value should be inverted. See {@link gl:sampleCoverage/2} .
-%%
-%% `?GL_SAMPLER_BINDING': `Params' returns a single value, the name of the sampler
-%% object currently bound to the active texture unit. The initial value is 0. See {@link gl:bindSampler/2}
-%% .
-%%
-%% `?GL_SAMPLES': `Params' returns a single integer value indicating the coverage
-%% mask size. See {@link gl:sampleCoverage/2} .
-%%
-%% `?GL_SCISSOR_BOX': `Params' returns four values: the x and y window coordinates
-%% of the scissor box, followed by its width and height. Initially the x and y window
-%% coordinates are both 0 and the width and height are set to the size of the window. See {@link gl:scissor/4}
-%% .
-%%
-%% `?GL_SCISSOR_TEST': `Params' returns a single boolean value indicating whether
-%% scissoring is enabled. The initial value is `?GL_FALSE'. See {@link gl:scissor/4} .
-%%
-%% `?GL_SHADER_COMPILER': `Params' returns a single boolean value indicating whether
-%% an online shader compiler is present in the implementation. All desktop OpenGL implementations
-%% must support online shader compilations, and therefore the value of `?GL_SHADER_COMPILER'
-%% will always be `?GL_TRUE'.
-%%
-%% `?GL_SMOOTH_LINE_WIDTH_RANGE': `Params' returns a pair of values indicating
-%% the range of widths supported for smooth (antialiased) lines. See {@link gl:lineWidth/1} .
-%%
-%% `?GL_SMOOTH_LINE_WIDTH_GRANULARITY': `Params' returns a single value indicating
-%% the level of quantization applied to smooth line width parameters.
-%%
-%% `?GL_STENCIL_BACK_FAIL': `Params' returns one value, a symbolic constant indicating
-%% what action is taken for back-facing polygons when the stencil test fails. The initial
-%% value is `?GL_KEEP'. See {@link gl:stencilOpSeparate/4} .
-%%
-%% `?GL_STENCIL_BACK_FUNC': `Params' returns one value, a symbolic constant indicating
-%% what function is used for back-facing polygons to compare the stencil reference value
-%% with the stencil buffer value. The initial value is `?GL_ALWAYS'. See {@link gl:stencilFuncSeparate/4}
-%% .
-%%
-%% `?GL_STENCIL_BACK_PASS_DEPTH_FAIL': `Params' returns one value, a symbolic constant
-%% indicating what action is taken for back-facing polygons when the stencil test passes,
-%% but the depth test fails. The initial value is `?GL_KEEP'. See {@link gl:stencilOpSeparate/4}
-%% .
-%%
-%% `?GL_STENCIL_BACK_PASS_DEPTH_PASS': `Params' returns one value, a symbolic constant
-%% indicating what action is taken for back-facing polygons when the stencil test passes
-%% and the depth test passes. The initial value is `?GL_KEEP'. See {@link gl:stencilOpSeparate/4}
-%% .
-%%
-%% `?GL_STENCIL_BACK_REF': `Params' returns one value, the reference value that
-%% is compared with the contents of the stencil buffer for back-facing polygons. The initial
-%% value is 0. See {@link gl:stencilFuncSeparate/4} .
-%%
-%% `?GL_STENCIL_BACK_VALUE_MASK': `Params' returns one value, the mask that is
-%% used for back-facing polygons to mask both the stencil reference value and the stencil
-%% buffer value before they are compared. The initial value is all 1's. See {@link gl:stencilFuncSeparate/4}
-%% .
-%%
-%% `?GL_STENCIL_BACK_WRITEMASK': `Params' returns one value, the mask that controls
-%% writing of the stencil bitplanes for back-facing polygons. The initial value is all 1's.
-%% See {@link gl:stencilMaskSeparate/2} .
-%%
-%% `?GL_STENCIL_CLEAR_VALUE': `Params' returns one value, the index to which the
-%% stencil bitplanes are cleared. The initial value is 0. See {@link gl:clearStencil/1} .
-%%
-%% `?GL_STENCIL_FAIL': `Params' returns one value, a symbolic constant indicating
-%% what action is taken when the stencil test fails. The initial value is `?GL_KEEP'.
-%% See {@link gl:stencilOp/3} . This stencil state only affects non-polygons and front-facing
-%% polygons. Back-facing polygons use separate stencil state. See {@link gl:stencilOpSeparate/4}
-%% .
-%%
-%% `?GL_STENCIL_FUNC': `Params' returns one value, a symbolic constant indicating
-%% what function is used to compare the stencil reference value with the stencil buffer value.
-%% The initial value is `?GL_ALWAYS'. See {@link gl:stencilFunc/3} . This stencil state
-%% only affects non-polygons and front-facing polygons. Back-facing polygons use separate
-%% stencil state. See {@link gl:stencilFuncSeparate/4} .
-%%
-%% `?GL_STENCIL_PASS_DEPTH_FAIL': `Params' returns one value, a symbolic constant
-%% indicating what action is taken when the stencil test passes, but the depth test fails.
-%% The initial value is `?GL_KEEP'. See {@link gl:stencilOp/3} . This stencil state only
-%% affects non-polygons and front-facing polygons. Back-facing polygons use separate stencil
-%% state. See {@link gl:stencilOpSeparate/4} .
-%%
-%% `?GL_STENCIL_PASS_DEPTH_PASS': `Params' returns one value, a symbolic constant
-%% indicating what action is taken when the stencil test passes and the depth test passes.
-%% The initial value is `?GL_KEEP'. See {@link gl:stencilOp/3} . This stencil state only
-%% affects non-polygons and front-facing polygons. Back-facing polygons use separate stencil
-%% state. See {@link gl:stencilOpSeparate/4} .
-%%
-%% `?GL_STENCIL_REF': `Params' returns one value, the reference value that is compared
-%% with the contents of the stencil buffer. The initial value is 0. See {@link gl:stencilFunc/3}
-%% . This stencil state only affects non-polygons and front-facing polygons. Back-facing
-%% polygons use separate stencil state. See {@link gl:stencilFuncSeparate/4} .
-%%
-%% `?GL_STENCIL_TEST': `Params' returns a single boolean value indicating whether
-%% stencil testing of fragments is enabled. The initial value is `?GL_FALSE'. See {@link gl:stencilFunc/3}
-%% and {@link gl:stencilOp/3} .
-%%
-%% `?GL_STENCIL_VALUE_MASK': `Params' returns one value, the mask that is used
-%% to mask both the stencil reference value and the stencil buffer value before they are
-%% compared. The initial value is all 1's. See {@link gl:stencilFunc/3} . This stencil state
-%% only affects non-polygons and front-facing polygons. Back-facing polygons use separate
-%% stencil state. See {@link gl:stencilFuncSeparate/4} .
-%%
-%% `?GL_STENCIL_WRITEMASK': `Params' returns one value, the mask that controls
-%% writing of the stencil bitplanes. The initial value is all 1's. See {@link gl:stencilMask/1}
-%% . This stencil state only affects non-polygons and front-facing polygons. Back-facing
-%% polygons use separate stencil state. See {@link gl:stencilMaskSeparate/2} .
-%%
-%% `?GL_STEREO': `Params' returns a single boolean value indicating whether stereo
-%% buffers (left and right) are supported.
-%%
-%% `?GL_SUBPIXEL_BITS': `Params' returns one value, an estimate of the number of
-%% bits of subpixel resolution that are used to position rasterized geometry in window coordinates.
-%% The value must be at least 4.
-%%
-%% `?GL_TEXTURE_BINDING_1D': `Params' returns a single value, the name of the texture
-%% currently bound to the target `?GL_TEXTURE_1D'. The initial value is 0. See {@link gl:bindTexture/2}
-%% .
-%%
-%% `?GL_TEXTURE_BINDING_1D_ARRAY': `Params' returns a single value, the name of
-%% the texture currently bound to the target `?GL_TEXTURE_1D_ARRAY'. The initial value
-%% is 0. See {@link gl:bindTexture/2} .
-%%
-%% `?GL_TEXTURE_BINDING_2D': `Params' returns a single value, the name of the texture
-%% currently bound to the target `?GL_TEXTURE_2D'. The initial value is 0. See {@link gl:bindTexture/2}
-%% .
-%%
-%% `?GL_TEXTURE_BINDING_2D_ARRAY': `Params' returns a single value, the name of
-%% the texture currently bound to the target `?GL_TEXTURE_2D_ARRAY'. The initial value
-%% is 0. See {@link gl:bindTexture/2} .
-%%
-%% `?GL_TEXTURE_BINDING_2D_MULTISAMPLE': `Params' returns a single value, the name
-%% of the texture currently bound to the target `?GL_TEXTURE_2D_MULTISAMPLE'. The initial
-%% value is 0. See {@link gl:bindTexture/2} .
-%%
-%% `?GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY': `Params' returns a single value,
-%% the name of the texture currently bound to the target `?GL_TEXTURE_2D_MULTISAMPLE_ARRAY'
-%% . The initial value is 0. See {@link gl:bindTexture/2} .
-%%
-%% `?GL_TEXTURE_BINDING_3D': `Params' returns a single value, the name of the texture
-%% currently bound to the target `?GL_TEXTURE_3D'. The initial value is 0. See {@link gl:bindTexture/2}
-%% .
-%%
-%% `?GL_TEXTURE_BINDING_BUFFER': `Params' returns a single value, the name of the
-%% texture currently bound to the target `?GL_TEXTURE_BUFFER'. The initial value is
-%% 0. See {@link gl:bindTexture/2} .
-%%
-%% `?GL_TEXTURE_BINDING_CUBE_MAP': `Params' returns a single value, the name of
-%% the texture currently bound to the target `?GL_TEXTURE_CUBE_MAP'. The initial value
-%% is 0. See {@link gl:bindTexture/2} .
-%%
-%% `?GL_TEXTURE_BINDING_RECTANGLE': `Params' returns a single value, the name of
-%% the texture currently bound to the target `?GL_TEXTURE_RECTANGLE'. The initial value
-%% is 0. See {@link gl:bindTexture/2} .
-%%
-%% `?GL_TEXTURE_COMPRESSION_HINT': `Params' returns a single value indicating the
-%% mode of the texture compression hint. The initial value is `?GL_DONT_CARE'.
-%%
-%% `?GL_TEXTURE_BUFFER_BINDING': `Params' returns a single value, the name of the
-%% texture buffer object currently bound. The initial value is 0. See {@link gl:bindBuffer/2} .
-%%
-%%
-%% `?GL_TIMESTAMP': `Params' returns a single value, the 64-bit value of the current
-%% GL time. See {@link gl:queryCounter/2} .
-%%
-%% `?GL_TRANSFORM_FEEDBACK_BUFFER_BINDING': When used with non-indexed variants of ``gl:get''
-%% (such as ``gl:getIntegerv''), `Params' returns a single value, the name of the
-%% buffer object currently bound to the target `?GL_TRANSFORM_FEEDBACK_BUFFER'. If no
-%% buffer object is bound to this target, 0 is returned. When used with indexed variants of ``gl:get''
-%% (such as ``gl:getIntegeri_v''), `Params' returns a single value, the name of the
-%% buffer object bound to the indexed transform feedback attribute stream. The initial value
-%% is 0 for all targets. See {@link gl:bindBuffer/2} , {@link gl:bindBufferBase/3} , and {@link gl:bindBufferRange/5}
-%% .
-%%
-%% `?GL_TRANSFORM_FEEDBACK_BUFFER_START': When used with indexed variants of ``gl:get''
-%% (such as ``gl:getInteger64i_v''), `Params' returns a single value, the start offset
-%% of the binding range for each transform feedback attribute stream. The initial value is
-%% 0 for all streams. See {@link gl:bindBufferRange/5} .
-%%
-%% `?GL_TRANSFORM_FEEDBACK_BUFFER_SIZE': When used with indexed variants of ``gl:get''
-%% (such as ``gl:getInteger64i_v''), `Params' returns a single value, the size of
-%% the binding range for each transform feedback attribute stream. The initial value is 0
-%% for all streams. See {@link gl:bindBufferRange/5} .
-%%
-%% `?GL_UNIFORM_BUFFER_BINDING': When used with non-indexed variants of ``gl:get''
-%% (such as ``gl:getIntegerv''), `Params' returns a single value, the name of the
-%% buffer object currently bound to the target `?GL_UNIFORM_BUFFER'. If no buffer object
-%% is bound to this target, 0 is returned. When used with indexed variants of ``gl:get''
-%% (such as ``gl:getIntegeri_v''), `Params' returns a single value, the name of the
-%% buffer object bound to the indexed uniform buffer binding point. The initial value is
-%% 0 for all targets. See {@link gl:bindBuffer/2} , {@link gl:bindBufferBase/3} , and {@link gl:bindBufferRange/5}
-%% .
-%%
-%% `?GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT': `Params' returns a single value, the
-%% minimum required alignment for uniform buffer sizes and offset. The initial value is 1.
-%% See {@link gl:uniformBlockBinding/3} .
-%%
-%% `?GL_UNIFORM_BUFFER_SIZE': When used with indexed variants of ``gl:get'' (such
-%% as ``gl:getInteger64i_v''), `Params' returns a single value, the size of the binding
-%% range for each indexed uniform buffer binding. The initial value is 0 for all bindings.
-%% See {@link gl:bindBufferRange/5} .
-%%
-%% `?GL_UNIFORM_BUFFER_START': When used with indexed variants of ``gl:get'' (such
-%% as ``gl:getInteger64i_v''), `Params' returns a single value, the start offset of
-%% the binding range for each indexed uniform buffer binding. The initial value is 0 for
-%% all bindings. See {@link gl:bindBufferRange/5} .
-%%
-%% `?GL_UNPACK_ALIGNMENT': `Params' returns one value, the byte alignment used
-%% for reading pixel data from memory. The initial value is 4. See {@link gl:pixelStoref/2} .
-%%
-%% `?GL_UNPACK_IMAGE_HEIGHT': `Params' returns one value, the image height used
-%% for reading pixel data from memory. The initial is 0. See {@link gl:pixelStoref/2} .
-%%
-%% `?GL_UNPACK_LSB_FIRST': `Params' returns a single boolean value indicating whether
-%% single-bit pixels being read from memory are read first from the least significant bit
-%% of each unsigned byte. The initial value is `?GL_FALSE'. See {@link gl:pixelStoref/2} .
-%%
-%%
-%% `?GL_UNPACK_ROW_LENGTH': `Params' returns one value, the row length used for
-%% reading pixel data from memory. The initial value is 0. See {@link gl:pixelStoref/2} .
-%%
-%% `?GL_UNPACK_SKIP_IMAGES': `Params' returns one value, the number of pixel images
-%% skipped before the first pixel is read from memory. The initial value is 0. See {@link gl:pixelStoref/2}
-%% .
-%%
-%% `?GL_UNPACK_SKIP_PIXELS': `Params' returns one value, the number of pixel locations
-%% skipped before the first pixel is read from memory. The initial value is 0. See {@link gl:pixelStoref/2}
-%% .
-%%
-%% `?GL_UNPACK_SKIP_ROWS': `Params' returns one value, the number of rows of pixel
-%% locations skipped before the first pixel is read from memory. The initial value is 0.
-%% See {@link gl:pixelStoref/2} .
-%%
-%% `?GL_UNPACK_SWAP_BYTES': `Params' returns a single boolean value indicating
-%% whether the bytes of two-byte and four-byte pixel indices and components are swapped after
-%% being read from memory. The initial value is `?GL_FALSE'. See {@link gl:pixelStoref/2} .
-%%
-%%
-%% `?GL_VERTEX_PROGRAM_POINT_SIZE': `Params' returns a single boolean value indicating
-%% whether vertex program point size mode is enabled. If enabled, and a vertex shader is
-%% active, then the point size is taken from the shader built-in gl_PointSize. If disabled,
-%% and a vertex shader is active, then the point size is taken from the point state as specified
-%% by {@link gl:pointSize/1} . The initial value is `?GL_FALSE'.
-%%
-%% `?GL_VIEWPORT': When used with non-indexed variants of ``gl:get'' (such as ``gl:getIntegerv''
-%% ), `Params' returns four values: the x and y window coordinates of the viewport,
-%% followed by its width and height. Initially the x and y window coordinates are both
-%% set to 0, and the width and height are set to the width and height of the window into
-%% which the GL will do its rendering. See {@link gl:viewport/4} . When used with indexed
-%% variants of ``gl:get'' (such as ``gl:getIntegeri_v''), `Params' returns four
-%% values: the x and y window coordinates of the indexed viewport, followed by its width
-%% and height. Initially the x and y window coordinates are both set to 0, and the width
-%% and height are set to the width and height of the window into which the GL will do its
-%% rendering. See {@link gl:viewportIndexedf/5} .
-%%
-%% `?GL_VIEWPORT_BOUNDS_RANGE': `Params' returns two values, the minimum and maximum
-%% viewport bounds range. The minimum range should be at least [-32768, 32767].
-%%
-%% `?GL_VIEWPORT_INDEX_PROVOKING_VERTEX': `Params' returns one value, the implementation
-%% dependent specifc vertex of a primitive that is used to select the viewport index. If
-%% the value returned is equivalent to `?GL_PROVOKING_VERTEX', then the vertex selection
-%% follows the convention specified by {@link gl:provokingVertex/1} . If the value returned
-%% is equivalent to `?GL_FIRST_VERTEX_CONVENTION', then the selection is always taken
-%% from the first vertex in the primitive. If the value returned is equivalent to `?GL_LAST_VERTEX_CONVENTION'
-%% , then the selection is always taken from the last vertex in the primitive. If the value
-%% returned is equivalent to `?GL_UNDEFINED_VERTEX', then the selection is not guaranteed
-%% to be taken from any specific vertex in the primitive.
-%%
-%% `?GL_VIEWPORT_SUBPIXEL_BITS': `Params' returns a single value, the number of
-%% bits of sub-pixel precision which the GL uses to interpret the floating point viewport
-%% bounds. The minimum value is 0.
-%%
-%% Many of the boolean parameters can also be queried more easily using {@link gl:isEnabled/1}
-%% .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGet.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGet.xhtml">external</a> documentation.
-spec getBooleanv(Pname) -> [0|1] when Pname :: enum().
getBooleanv(Pname) ->
call(5065, <<Pname:?GLenum>>).
@@ -1968,131 +698,7 @@ getIntegerv(Pname) ->
%% together. The special mask `?GL_ALL_ATTRIB_BITS' can be used to save all stackable
%% states.
%%
-%% The symbolic mask constants and their associated GL state are as follows (the second
-%% column lists which attributes are saved):
-%%
-%% <table><tbody><tr><td>`?GL_ACCUM_BUFFER_BIT'</td><td> Accumulation buffer clear value
-%% </td></tr><tr><td>`?GL_COLOR_BUFFER_BIT'</td><td>`?GL_ALPHA_TEST' enable bit </td>
-%% </tr><tr><td></td><td> Alpha test function and reference value </td></tr><tr><td></td><td>
-%% `?GL_BLEND' enable bit </td></tr><tr><td></td><td> Blending source and destination
-%% functions </td></tr><tr><td></td><td> Constant blend color </td></tr><tr><td></td><td>
-%% Blending equation </td></tr><tr><td></td><td>`?GL_DITHER' enable bit </td></tr><tr><td>
-%% </td><td>`?GL_DRAW_BUFFER' setting </td></tr><tr><td></td><td>`?GL_COLOR_LOGIC_OP'
-%% enable bit </td></tr><tr><td></td><td>`?GL_INDEX_LOGIC_OP' enable bit </td></tr><tr>
-%% <td></td><td> Logic op function </td></tr><tr><td></td><td> Color mode and index mode
-%% clear values </td></tr><tr><td></td><td> Color mode and index mode writemasks </td></tr><tr>
-%% <td>`?GL_CURRENT_BIT'</td><td> Current RGBA color </td></tr><tr><td></td><td> Current
-%% color index </td></tr><tr><td></td><td> Current normal vector </td></tr><tr><td></td><td>
-%% Current texture coordinates </td></tr><tr><td></td><td> Current raster position </td></tr>
-%% <tr><td></td><td>`?GL_CURRENT_RASTER_POSITION_VALID' flag </td></tr><tr><td></td><td>
-%% RGBA color associated with current raster position </td></tr><tr><td></td><td> Color
-%% index associated with current raster position </td></tr><tr><td></td><td> Texture coordinates
-%% associated with current raster position </td></tr><tr><td></td><td>`?GL_EDGE_FLAG'
-%% flag </td></tr><tr><td>`?GL_DEPTH_BUFFER_BIT'</td><td>`?GL_DEPTH_TEST' enable
-%% bit </td></tr><tr><td></td><td> Depth buffer test function </td></tr><tr><td></td><td>
-%% Depth buffer clear value </td></tr><tr><td></td><td>`?GL_DEPTH_WRITEMASK' enable
-%% bit </td></tr><tr><td>`?GL_ENABLE_BIT'</td><td>`?GL_ALPHA_TEST' flag </td></tr><tr>
-%% <td></td><td>`?GL_AUTO_NORMAL' flag </td></tr><tr><td></td><td>`?GL_BLEND' flag
-%% </td></tr><tr><td></td><td> Enable bits for the user-definable clipping planes </td></tr><tr>
-%% <td></td><td>`?GL_COLOR_MATERIAL'</td></tr><tr><td></td><td>`?GL_CULL_FACE'
-%% flag </td></tr><tr><td></td><td>`?GL_DEPTH_TEST' flag </td></tr><tr><td></td><td>`?GL_DITHER'
-%% flag </td></tr><tr><td></td><td>`?GL_FOG' flag </td></tr><tr><td></td><td>`?GL_LIGHT'
-%% `i' where `?0' &lt;= `i' &lt; `?GL_MAX_LIGHTS'</td></tr>
-%% <tr><td></td><td>`?GL_LIGHTING' flag </td></tr><tr><td></td><td>`?GL_LINE_SMOOTH'
-%% flag </td></tr><tr><td></td><td>`?GL_LINE_STIPPLE' flag </td></tr><tr><td></td><td>`?GL_COLOR_LOGIC_OP'
-%% flag </td></tr><tr><td></td><td>`?GL_INDEX_LOGIC_OP' flag </td></tr><tr><td></td><td>
-%% `?GL_MAP1_'`x' where `x' is a map type </td></tr><tr><td></td><td>`?GL_MAP2_'
-%% `x' where `x' is a map type </td></tr><tr><td></td><td>`?GL_MULTISAMPLE'
-%% flag </td></tr><tr><td></td><td>`?GL_NORMALIZE' flag </td></tr><tr><td></td><td>`?GL_POINT_SMOOTH'
-%% flag </td></tr><tr><td></td><td>`?GL_POLYGON_OFFSET_LINE' flag </td></tr><tr><td></td>
-%% <td>`?GL_POLYGON_OFFSET_FILL' flag </td></tr><tr><td></td><td>`?GL_POLYGON_OFFSET_POINT'
-%% flag </td></tr><tr><td></td><td>`?GL_POLYGON_SMOOTH' flag </td></tr><tr><td></td><td>
-%% `?GL_POLYGON_STIPPLE' flag </td></tr><tr><td></td><td>`?GL_SAMPLE_ALPHA_TO_COVERAGE'
-%% flag </td></tr><tr><td></td><td>`?GL_SAMPLE_ALPHA_TO_ONE' flag </td></tr><tr><td></td>
-%% <td>`?GL_SAMPLE_COVERAGE' flag </td></tr><tr><td></td><td>`?GL_SCISSOR_TEST'
-%% flag </td></tr><tr><td></td><td>`?GL_STENCIL_TEST' flag </td></tr><tr><td></td><td>`?GL_TEXTURE_1D'
-%% flag </td></tr><tr><td></td><td>`?GL_TEXTURE_2D' flag </td></tr><tr><td></td><td>`?GL_TEXTURE_3D'
-%% flag </td></tr><tr><td></td><td> Flags `?GL_TEXTURE_GEN_'`x' where `x'
-%% is S, T, R, or Q </td></tr><tr><td>`?GL_EVAL_BIT'</td><td>`?GL_MAP1_'`x'
-%% enable bits, where `x' is a map type </td></tr><tr><td></td><td>`?GL_MAP2_'`x'
-%% enable bits, where `x' is a map type </td></tr><tr><td></td><td> 1D grid endpoints
-%% and divisions </td></tr><tr><td></td><td> 2D grid endpoints and divisions </td></tr><tr><td>
-%% </td><td>`?GL_AUTO_NORMAL' enable bit </td></tr><tr><td>`?GL_FOG_BIT'</td><td>`?GL_FOG'
-%% enable bit </td></tr><tr><td></td><td> Fog color </td></tr><tr><td></td><td> Fog density
-%% </td></tr><tr><td></td><td> Linear fog start </td></tr><tr><td></td><td> Linear fog end </td>
-%% </tr><tr><td></td><td> Fog index </td></tr><tr><td></td><td>`?GL_FOG_MODE' value </td>
-%% </tr><tr><td>`?GL_HINT_BIT'</td><td>`?GL_PERSPECTIVE_CORRECTION_HINT' setting </td>
-%% </tr><tr><td></td><td>`?GL_POINT_SMOOTH_HINT' setting </td></tr><tr><td></td><td>`?GL_LINE_SMOOTH_HINT'
-%% setting </td></tr><tr><td></td><td>`?GL_POLYGON_SMOOTH_HINT' setting </td></tr><tr><td>
-%% </td><td>`?GL_FOG_HINT' setting </td></tr><tr><td></td><td>`?GL_GENERATE_MIPMAP_HINT'
-%% setting </td></tr><tr><td></td><td>`?GL_TEXTURE_COMPRESSION_HINT' setting </td></tr>
-%% <tr><td>`?GL_LIGHTING_BIT'</td><td>`?GL_COLOR_MATERIAL' enable bit </td></tr><tr>
-%% <td></td><td>`?GL_COLOR_MATERIAL_FACE' value </td></tr><tr><td></td><td> Color material
-%% parameters that are tracking the current color </td></tr><tr><td></td><td> Ambient scene
-%% color </td></tr><tr><td></td><td>`?GL_LIGHT_MODEL_LOCAL_VIEWER' value </td></tr><tr><td>
-%% </td><td>`?GL_LIGHT_MODEL_TWO_SIDE' setting </td></tr><tr><td></td><td>`?GL_LIGHTING'
-%% enable bit </td></tr><tr><td></td><td> Enable bit for each light </td></tr><tr><td></td><td>
-%% Ambient, diffuse, and specular intensity for each light </td></tr><tr><td></td><td> Direction,
-%% position, exponent, and cutoff angle for each light </td></tr><tr><td></td><td> Constant,
-%% linear, and quadratic attenuation factors for each light </td></tr><tr><td></td><td> Ambient,
-%% diffuse, specular, and emissive color for each material </td></tr><tr><td></td><td> Ambient,
-%% diffuse, and specular color indices for each material </td></tr><tr><td></td><td> Specular
-%% exponent for each material </td></tr><tr><td></td><td>`?GL_SHADE_MODEL' setting </td>
-%% </tr><tr><td>`?GL_LINE_BIT'</td><td>`?GL_LINE_SMOOTH' flag </td></tr><tr><td></td>
-%% <td>`?GL_LINE_STIPPLE' enable bit </td></tr><tr><td></td><td> Line stipple pattern
-%% and repeat counter </td></tr><tr><td></td><td> Line width </td></tr><tr><td>`?GL_LIST_BIT'
-%% </td><td>`?GL_LIST_BASE' setting </td></tr><tr><td>`?GL_MULTISAMPLE_BIT'</td><td>
-%% `?GL_MULTISAMPLE' flag </td></tr><tr><td></td><td>`?GL_SAMPLE_ALPHA_TO_COVERAGE'
-%% flag </td></tr><tr><td></td><td>`?GL_SAMPLE_ALPHA_TO_ONE' flag </td></tr><tr><td></td>
-%% <td>`?GL_SAMPLE_COVERAGE' flag </td></tr><tr><td></td><td>`?GL_SAMPLE_COVERAGE_VALUE'
-%% value </td></tr><tr><td></td><td>`?GL_SAMPLE_COVERAGE_INVERT' value </td></tr><tr><td>
-%% `?GL_PIXEL_MODE_BIT'</td><td>`?GL_RED_BIAS' and `?GL_RED_SCALE' settings </td>
-%% </tr><tr><td></td><td>`?GL_GREEN_BIAS' and `?GL_GREEN_SCALE' values </td></tr><tr>
-%% <td></td><td>`?GL_BLUE_BIAS' and `?GL_BLUE_SCALE'</td></tr><tr><td></td><td>`?GL_ALPHA_BIAS'
-%% and `?GL_ALPHA_SCALE'</td></tr><tr><td></td><td>`?GL_DEPTH_BIAS' and `?GL_DEPTH_SCALE'
-%% </td></tr><tr><td></td><td>`?GL_INDEX_OFFSET' and `?GL_INDEX_SHIFT' values </td>
-%% </tr><tr><td></td><td>`?GL_MAP_COLOR' and `?GL_MAP_STENCIL' flags </td></tr><tr>
-%% <td></td><td>`?GL_ZOOM_X' and `?GL_ZOOM_Y' factors </td></tr><tr><td></td><td>`?GL_READ_BUFFER'
-%% setting </td></tr><tr><td>`?GL_POINT_BIT'</td><td>`?GL_POINT_SMOOTH' flag </td>
-%% </tr><tr><td></td><td> Point size </td></tr><tr><td>`?GL_POLYGON_BIT'</td><td>`?GL_CULL_FACE'
-%% enable bit </td></tr><tr><td></td><td>`?GL_CULL_FACE_MODE' value </td></tr><tr><td></td>
-%% <td>`?GL_FRONT_FACE' indicator </td></tr><tr><td></td><td>`?GL_POLYGON_MODE'
-%% setting </td></tr><tr><td></td><td>`?GL_POLYGON_SMOOTH' flag </td></tr><tr><td></td><td>
-%% `?GL_POLYGON_STIPPLE' enable bit </td></tr><tr><td></td><td>`?GL_POLYGON_OFFSET_FILL'
-%% flag </td></tr><tr><td></td><td>`?GL_POLYGON_OFFSET_LINE' flag </td></tr><tr><td></td>
-%% <td>`?GL_POLYGON_OFFSET_POINT' flag </td></tr><tr><td></td><td>`?GL_POLYGON_OFFSET_FACTOR'
-%% </td></tr><tr><td></td><td>`?GL_POLYGON_OFFSET_UNITS'</td></tr><tr><td>`?GL_POLYGON_STIPPLE_BIT'
-%% </td><td> Polygon stipple image </td></tr><tr><td>`?GL_SCISSOR_BIT'</td><td>`?GL_SCISSOR_TEST'
-%% flag </td></tr><tr><td></td><td> Scissor box </td></tr><tr><td>`?GL_STENCIL_BUFFER_BIT'
-%% </td><td>`?GL_STENCIL_TEST' enable bit </td></tr><tr><td></td><td> Stencil function
-%% and reference value </td></tr><tr><td></td><td> Stencil value mask </td></tr><tr><td></td>
-%% <td> Stencil fail, pass, and depth buffer pass actions </td></tr><tr><td></td><td> Stencil
-%% buffer clear value </td></tr><tr><td></td><td> Stencil buffer writemask </td></tr><tr><td>
-%% `?GL_TEXTURE_BIT'</td><td> Enable bits for the four texture coordinates </td></tr><tr>
-%% <td></td><td> Border color for each texture image </td></tr><tr><td></td><td> Minification
-%% function for each texture image </td></tr><tr><td></td><td> Magnification function for
-%% each texture image </td></tr><tr><td></td><td> Texture coordinates and wrap mode for each
-%% texture image </td></tr><tr><td></td><td> Color and mode for each texture environment </td>
-%% </tr><tr><td></td><td> Enable bits `?GL_TEXTURE_GEN_'`x', `x' is S, T,
-%% R, and Q </td></tr><tr><td></td><td>`?GL_TEXTURE_GEN_MODE' setting for S, T, R, and
-%% Q </td></tr><tr><td></td><td> {@link gl:texGend/3} plane equations for S, T, R, and Q </td></tr>
-%% <tr><td></td><td> Current texture bindings (for example, `?GL_TEXTURE_BINDING_2D') </td>
-%% </tr><tr><td>`?GL_TRANSFORM_BIT'</td><td> Coefficients of the six clipping planes </td>
-%% </tr><tr><td></td><td> Enable bits for the user-definable clipping planes </td></tr><tr><td>
-%% </td><td>`?GL_MATRIX_MODE' value </td></tr><tr><td></td><td>`?GL_NORMALIZE'
-%% flag </td></tr><tr><td></td><td>`?GL_RESCALE_NORMAL' flag </td></tr><tr><td>`?GL_VIEWPORT_BIT'
-%% </td><td> Depth range (near and far) </td></tr><tr><td></td><td> Viewport origin and extent
-%% </td></tr></tbody></table>
-%%
-%% {@link gl:pushAttrib/1} restores the values of the state variables saved with the last ``gl:pushAttrib''
-%% command. Those not saved are left unchanged.
-%%
-%% It is an error to push attributes onto a full stack or to pop attributes off an empty
-%% stack. In either case, the error flag is set and no other change is made to GL state.
-%%
-%% Initially, the attribute stack is empty.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPushAttrib.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPushAttrib.xml">external</a> documentation.
-spec pushAttrib(Mask) -> 'ok' when Mask :: integer().
pushAttrib(Mask) ->
cast(5069, <<Mask:?GLbitfield>>).
@@ -2111,22 +717,7 @@ popAttrib() ->
%% of these constants together. The special mask `?GL_CLIENT_ALL_ATTRIB_BITS' can
%% be used to save all stackable client state.
%%
-%% The symbolic mask constants and their associated GL client state are as follows (the
-%% second column lists which attributes are saved):
-%%
-%% `?GL_CLIENT_PIXEL_STORE_BIT' Pixel storage modes `?GL_CLIENT_VERTEX_ARRAY_BIT'
-%% Vertex arrays (and enables)
-%%
-%% {@link gl:pushClientAttrib/1} restores the values of the client-state variables saved with
-%% the last ``gl:pushClientAttrib''. Those not saved are left unchanged.
-%%
-%% It is an error to push attributes onto a full client attribute stack or to pop attributes
-%% off an empty stack. In either case, the error flag is set, and no other change is made
-%% to GL state.
-%%
-%% Initially, the client attribute stack is empty.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPushClientAttrib.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPushClientAttrib.xml">external</a> documentation.
-spec pushClientAttrib(Mask) -> 'ok' when Mask :: integer().
pushClientAttrib(Mask) ->
cast(5071, <<Mask:?GLbitfield>>).
@@ -2142,37 +733,7 @@ popClientAttrib() ->
%% ``gl:renderMode'' sets the rasterization mode. It takes one argument, `Mode' , which
%% can assume one of three predefined values:
%%
-%% `?GL_RENDER': Render mode. Primitives are rasterized, producing pixel fragments,
-%% which are written into the frame buffer. This is the normal mode and also the default
-%% mode.
-%%
-%% `?GL_SELECT': Selection mode. No pixel fragments are produced, and no change to
-%% the frame buffer contents is made. Instead, a record of the names of primitives that would
-%% have been drawn if the render mode had been `?GL_RENDER' is returned in a select
-%% buffer, which must be created (see {@link gl:selectBuffer/2} ) before selection mode is
-%% entered.
-%%
-%% `?GL_FEEDBACK': Feedback mode. No pixel fragments are produced, and no change to
-%% the frame buffer contents is made. Instead, the coordinates and attributes of vertices
-%% that would have been drawn if the render mode had been `?GL_RENDER' is returned in
-%% a feedback buffer, which must be created (see {@link gl:feedbackBuffer/3} ) before feedback
-%% mode is entered.
-%%
-%% The return value of ``gl:renderMode'' is determined by the render mode at the time ``gl:renderMode''
-%% is called, rather than by `Mode' . The values returned for the three render modes
-%% are as follows:
-%%
-%% `?GL_RENDER': 0.
-%%
-%% `?GL_SELECT': The number of hit records transferred to the select buffer.
-%%
-%% `?GL_FEEDBACK': The number of values (not vertices) transferred to the feedback
-%% buffer.
-%%
-%% See the {@link gl:selectBuffer/2} and {@link gl:feedbackBuffer/3} reference pages for more
-%% details concerning selection and feedback operation.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRenderMode.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glRenderMode.xml">external</a> documentation.
-spec renderMode(Mode) -> integer() when Mode :: enum().
renderMode(Mode) ->
call(5073, <<Mode:?GLenum>>).
@@ -2186,44 +747,7 @@ renderMode(Mode) ->
%% returns `?GL_NO_ERROR', there has been no detectable error since the last call to ``gl:getError''
%% , or since the GL was initialized.
%%
-%% To allow for distributed implementations, there may be several error flags. If any single
-%% error flag has recorded an error, the value of that flag is returned and that flag is
-%% reset to `?GL_NO_ERROR' when ``gl:getError'' is called. If more than one flag has
-%% recorded an error, ``gl:getError'' returns and clears an arbitrary error flag value.
-%% Thus, ``gl:getError'' should always be called in a loop, until it returns `?GL_NO_ERROR'
-%% , if all error flags are to be reset.
-%%
-%% Initially, all error flags are set to `?GL_NO_ERROR'.
-%%
-%% The following errors are currently defined:
-%%
-%% `?GL_NO_ERROR': No error has been recorded. The value of this symbolic constant
-%% is guaranteed to be 0.
-%%
-%% `?GL_INVALID_ENUM': An unacceptable value is specified for an enumerated argument.
-%% The offending command is ignored and has no other side effect than to set the error flag.
-%%
-%%
-%% `?GL_INVALID_VALUE': A numeric argument is out of range. The offending command is
-%% ignored and has no other side effect than to set the error flag.
-%%
-%% `?GL_INVALID_OPERATION': The specified operation is not allowed in the current state.
-%% The offending command is ignored and has no other side effect than to set the error flag.
-%%
-%%
-%% `?GL_INVALID_FRAMEBUFFER_OPERATION': The framebuffer object is not complete. The
-%% offending command is ignored and has no other side effect than to set the error flag.
-%%
-%% `?GL_OUT_OF_MEMORY': There is not enough memory left to execute the command. The
-%% state of the GL is undefined, except for the state of the error flags, after this error
-%% is recorded.
-%%
-%% When an error flag is set, results of a GL operation are undefined only if `?GL_OUT_OF_MEMORY'
-%% has occurred. In all other cases, the command generating the error is ignored and has
-%% no effect on the GL state or frame buffer contents. If the generating command returns
-%% a value, it returns 0. If ``gl:getError'' itself generates an error, it returns 0.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetError.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetError.xhtml">external</a> documentation.
-spec getError() -> enum().
getError() ->
call(5074, <<>>).
@@ -2233,40 +757,7 @@ getError() ->
%% ``gl:getString'' returns a pointer to a static string describing some aspect of the
%% current GL connection. `Name' can be one of the following:
%%
-%% `?GL_VENDOR': Returns the company responsible for this GL implementation. This name
-%% does not change from release to release.
-%%
-%% `?GL_RENDERER': Returns the name of the renderer. This name is typically specific
-%% to a particular configuration of a hardware platform. It does not change from release
-%% to release.
-%%
-%% `?GL_VERSION': Returns a version or release number.
-%%
-%% `?GL_SHADING_LANGUAGE_VERSION': Returns a version or release number for the shading
-%% language.
-%%
-%% ``gl:getStringi'' returns a pointer to a static string indexed by `Index' . `Name'
-%% can be one of the following:
-%%
-%% `?GL_EXTENSIONS': For ``gl:getStringi'' only, returns the extension string supported
-%% by the implementation at `Index' .
-%%
-%% Strings `?GL_VENDOR' and `?GL_RENDERER' together uniquely specify a platform.
-%% They do not change from release to release and should be used by platform-recognition
-%% algorithms.
-%%
-%% The `?GL_VERSION' and `?GL_SHADING_LANGUAGE_VERSION' strings begin with a version
-%% number. The version number uses one of these forms:
-%%
-%% `major_number.minor_number'`major_number.minor_number.release_number'
-%%
-%% Vendor-specific information may follow the version number. Its format depends on the
-%% implementation, but a space always separates the version number and the vendor-specific
-%% information.
-%%
-%% All strings are null-terminated.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetString.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetString.xhtml">external</a> documentation.
-spec getString(Name) -> string() when Name :: enum().
getString(Name) ->
call(5075, <<Name:?GLenum>>).
@@ -2277,7 +768,7 @@ getString(Name) ->
%% are complete. Such effects include all changes to GL state, all changes to connection
%% state, and all changes to the frame buffer contents.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFinish.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glFinish.xhtml">external</a> documentation.
-spec finish() -> 'ok'.
finish() ->
cast(5076, <<>>).
@@ -2290,12 +781,7 @@ finish() ->
%% the actual rendering engine. Though this execution may not be completed in any particular
%% time period, it does complete in finite time.
%%
-%% Because any GL program might be executed over a network, or on an accelerator that buffers
-%% commands, all programs should call ``gl:flush'' whenever they count on having all of
-%% their previously issued commands completed. For example, call ``gl:flush'' before waiting
-%% for user input that depends on the generated image.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFlush.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glFlush.xhtml">external</a> documentation.
-spec flush() -> 'ok'.
flush() ->
cast(5077, <<>>).
@@ -2308,36 +794,7 @@ flush() ->
%% indicating the desired behavior. The initial value for each `Target' is `?GL_DONT_CARE'
%% . `Mode' can be one of the following:
%%
-%% `?GL_FASTEST': The most efficient option should be chosen.
-%%
-%% `?GL_NICEST': The most correct, or highest quality, option should be chosen.
-%%
-%% `?GL_DONT_CARE': No preference.
-%%
-%% Though the implementation aspects that can be hinted are well defined, the interpretation
-%% of the hints depends on the implementation. The hint aspects that can be specified with `Target'
-%% , along with suggested semantics, are as follows:
-%%
-%% `?GL_FRAGMENT_SHADER_DERIVATIVE_HINT': Indicates the accuracy of the derivative
-%% calculation for the GL shading language fragment processing built-in functions: `?dFdx'
-%% , `?dFdy', and `?fwidth'.
-%%
-%% `?GL_LINE_SMOOTH_HINT': Indicates the sampling quality of antialiased lines. If
-%% a larger filter function is applied, hinting `?GL_NICEST' can result in more pixel
-%% fragments being generated during rasterization.
-%%
-%% `?GL_POLYGON_SMOOTH_HINT': Indicates the sampling quality of antialiased polygons.
-%% Hinting `?GL_NICEST' can result in more pixel fragments being generated during rasterization,
-%% if a larger filter function is applied.
-%%
-%% `?GL_TEXTURE_COMPRESSION_HINT': Indicates the quality and performance of the compressing
-%% texture images. Hinting `?GL_FASTEST' indicates that texture images should be compressed
-%% as quickly as possible, while `?GL_NICEST' indicates that texture images should be
-%% compressed with as little image quality loss as possible. `?GL_NICEST' should be
-%% selected if the texture is to be retrieved by {@link gl:getCompressedTexImage/3} for reuse.
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glHint.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glHint.xhtml">external</a> documentation.
-spec hint(Target, Mode) -> 'ok' when Target :: enum(),Mode :: enum().
hint(Target,Mode) ->
cast(5078, <<Target:?GLenum,Mode:?GLenum>>).
@@ -2347,7 +804,7 @@ hint(Target,Mode) ->
%% ``gl:clearDepth'' specifies the depth value used by {@link gl:clear/1} to clear the depth
%% buffer. Values specified by ``gl:clearDepth'' are clamped to the range [0 1].
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearDepth.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glClearDepth.xhtml">external</a> documentation.
-spec clearDepth(Depth) -> 'ok' when Depth :: clamp().
clearDepth(Depth) ->
cast(5079, <<Depth:?GLclampd>>).
@@ -2359,36 +816,7 @@ clearDepth(Depth) ->
%% depth testing is enabled. (See {@link gl:enable/1} and {@link gl:enable/1} of `?GL_DEPTH_TEST'
%% .)
%%
-%% `Func' specifies the conditions under which the pixel will be drawn. The comparison
-%% functions are as follows:
-%%
-%% `?GL_NEVER': Never passes.
-%%
-%% `?GL_LESS': Passes if the incoming depth value is less than the stored depth value.
-%%
-%%
-%% `?GL_EQUAL': Passes if the incoming depth value is equal to the stored depth value.
-%%
-%%
-%% `?GL_LEQUAL': Passes if the incoming depth value is less than or equal to the stored
-%% depth value.
-%%
-%% `?GL_GREATER': Passes if the incoming depth value is greater than the stored depth
-%% value.
-%%
-%% `?GL_NOTEQUAL': Passes if the incoming depth value is not equal to the stored depth
-%% value.
-%%
-%% `?GL_GEQUAL': Passes if the incoming depth value is greater than or equal to the
-%% stored depth value.
-%%
-%% `?GL_ALWAYS': Always passes.
-%%
-%% The initial value of `Func' is `?GL_LESS'. Initially, depth testing is disabled.
-%% If depth testing is disabled or if no depth buffer exists, it is as if the depth test
-%% always passes.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthFunc.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDepthFunc.xhtml">external</a> documentation.
-spec depthFunc(Func) -> 'ok' when Func :: enum().
depthFunc(Func) ->
cast(5080, <<Func:?GLenum>>).
@@ -2399,7 +827,7 @@ depthFunc(Func) ->
%% is `?GL_FALSE', depth buffer writing is disabled. Otherwise, it is enabled. Initially,
%% depth buffer writing is enabled.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthMask.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDepthMask.xhtml">external</a> documentation.
-spec depthMask(Flag) -> 'ok' when Flag :: 0|1.
depthMask(Flag) ->
cast(5081, <<Flag:?GLboolean>>).
@@ -2413,10 +841,7 @@ depthMask(Flag) ->
%% as though they range from 0 through 1 (like color components). Thus, the values accepted
%% by ``gl:depthRange'' are both clamped to this range before they are accepted.
%%
-%% The setting of (0,1) maps the near plane to 0 and the far plane to 1. With this mapping,
-%% the depth buffer range is fully utilized.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthRange.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDepthRange.xhtml">external</a> documentation.
-spec depthRange(Near_val, Far_val) -> 'ok' when Near_val :: clamp(),Far_val :: clamp().
depthRange(Near_val,Far_val) ->
cast(5082, <<Near_val:?GLclampd,Far_val:?GLclampd>>).
@@ -2426,9 +851,7 @@ depthRange(Near_val,Far_val) ->
%% ``gl:clearAccum'' specifies the red, green, blue, and alpha values used by {@link gl:clear/1}
%% to clear the accumulation buffer.
%%
-%% Values specified by ``gl:clearAccum'' are clamped to the range [-1 1].
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearAccum.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glClearAccum.xml">external</a> documentation.
-spec clearAccum(Red, Green, Blue, Alpha) -> 'ok' when Red :: float(),Green :: float(),Blue :: float(),Alpha :: float().
clearAccum(Red,Green,Blue,Alpha) ->
cast(5083, <<Red:?GLfloat,Green:?GLfloat,Blue:?GLfloat,Alpha:?GLfloat>>).
@@ -2441,53 +864,7 @@ clearAccum(Red,Green,Blue,Alpha) ->
%% and polygons), motion blur, and depth of field can be created by accumulating images generated
%% with different transformation matrices.
%%
-%% Each pixel in the accumulation buffer consists of red, green, blue, and alpha values.
-%% The number of bits per component in the accumulation buffer depends on the implementation.
-%% You can examine this number by calling {@link gl:getBooleanv/1} four times, with arguments
-%% `?GL_ACCUM_RED_BITS', `?GL_ACCUM_GREEN_BITS', `?GL_ACCUM_BLUE_BITS', and `?GL_ACCUM_ALPHA_BITS'
-%% . Regardless of the number of bits per component, the range of values stored by each component
-%% is [-1 1]. The accumulation buffer pixels are mapped one-to-one with frame buffer pixels.
-%%
-%% ``gl:accum'' operates on the accumulation buffer. The first argument, `Op' , is
-%% a symbolic constant that selects an accumulation buffer operation. The second argument, `Value'
-%% , is a floating-point value to be used in that operation. Five operations are specified: `?GL_ACCUM'
-%% , `?GL_LOAD', `?GL_ADD', `?GL_MULT', and `?GL_RETURN'.
-%%
-%% All accumulation buffer operations are limited to the area of the current scissor box
-%% and applied identically to the red, green, blue, and alpha components of each pixel. If
-%% a ``gl:accum'' operation results in a value outside the range [-1 1], the contents of an
-%% accumulation buffer pixel component are undefined.
-%%
-%% The operations are as follows:
-%%
-%% `?GL_ACCUM': Obtains R, G, B, and A values from the buffer currently selected for
-%% reading (see {@link gl:readBuffer/1} ). Each component value is divided by 2 n-1, where
-%% n is the number of bits allocated to each color component in the currently selected buffer.
-%% The result is a floating-point value in the range [0 1], which is multiplied by `Value'
-%% and added to the corresponding pixel component in the accumulation buffer, thereby updating
-%% the accumulation buffer.
-%%
-%% `?GL_LOAD': Similar to `?GL_ACCUM', except that the current value in the accumulation
-%% buffer is not used in the calculation of the new value. That is, the R, G, B, and A values
-%% from the currently selected buffer are divided by 2 n-1, multiplied by `Value' ,
-%% and then stored in the corresponding accumulation buffer cell, overwriting the current
-%% value.
-%%
-%% `?GL_ADD': Adds `Value' to each R, G, B, and A in the accumulation buffer.
-%%
-%% `?GL_MULT': Multiplies each R, G, B, and A in the accumulation buffer by `Value'
-%% and returns the scaled component to its corresponding accumulation buffer location.
-%%
-%% `?GL_RETURN': Transfers accumulation buffer values to the color buffer or buffers
-%% currently selected for writing. Each R, G, B, and A component is multiplied by `Value'
-%% , then multiplied by 2 n-1, clamped to the range [0 2 n-1], and stored in the corresponding
-%% display buffer cell. The only fragment operations that are applied to this transfer are
-%% pixel ownership, scissor, dithering, and color writemasks.
-%%
-%% To clear the accumulation buffer, call {@link gl:clearAccum/4} with R, G, B, and A values
-%% to set it to, then call {@link gl:clear/1} with the accumulation buffer enabled.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAccum.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glAccum.xml">external</a> documentation.
-spec accum(Op, Value) -> 'ok' when Op :: enum(),Value :: float().
accum(Op,Value) ->
cast(5084, <<Op:?GLenum,Value:?GLfloat>>).
@@ -2497,20 +874,7 @@ accum(Op,Value) ->
%% ``gl:matrixMode'' sets the current matrix mode. `Mode' can assume one of four values:
%%
%%
-%% `?GL_MODELVIEW': Applies subsequent matrix operations to the modelview matrix stack.
-%%
-%%
-%% `?GL_PROJECTION': Applies subsequent matrix operations to the projection matrix
-%% stack.
-%%
-%% `?GL_TEXTURE': Applies subsequent matrix operations to the texture matrix stack.
-%%
-%% `?GL_COLOR': Applies subsequent matrix operations to the color matrix stack.
-%%
-%% To find out which matrix stack is currently the target of all matrix operations, call {@link gl:getBooleanv/1}
-%% with argument `?GL_MATRIX_MODE'. The initial value is `?GL_MODELVIEW'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMatrixMode.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glMatrixMode.xml">external</a> documentation.
-spec matrixMode(Mode) -> 'ok' when Mode :: enum().
matrixMode(Mode) ->
cast(5085, <<Mode:?GLenum>>).
@@ -2522,20 +886,7 @@ matrixMode(Mode) ->
%% the current matrix, as if {@link gl:multMatrixd/1} were called with the following matrix
%% as its argument:
%%
-%% ((2/(right-left)) 0 0(t x) 0(2/(top-bottom)) 0(t y) 0 0(-2/(farVal-nearVal))(t z) 0 0 0 1)
-%%
-%% where t x=-((right+left)/(right-left)) t y=-((top+bottom)/(top-bottom)) t z=-((farVal+nearVal)/(farVal-nearVal))
-%%
-%% Typically, the matrix mode is `?GL_PROJECTION', and (left bottom-nearVal) and (right top-nearVal) specify the points on
-%% the near clipping plane that are mapped to the lower left and upper right corners of the
-%% window, respectively, assuming that the eye is located at (0, 0, 0). -farVal specifies
-%% the location of the far clipping plane. Both `NearVal' and `FarVal' can be either
-%% positive or negative.
-%%
-%% Use {@link gl:pushMatrix/0} and {@link gl:pushMatrix/0} to save and restore the current
-%% matrix stack.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml">external</a> documentation.
-spec ortho(Left, Right, Bottom, Top, Near_val, Far_val) -> 'ok' when Left :: float(),Right :: float(),Bottom :: float(),Top :: float(),Near_val :: float(),Far_val :: float().
ortho(Left,Right,Bottom,Top,Near_val,Far_val) ->
cast(5086, <<Left:?GLdouble,Right:?GLdouble,Bottom:?GLdouble,Top:?GLdouble,Near_val:?GLdouble,Far_val:?GLdouble>>).
@@ -2547,25 +898,7 @@ ortho(Left,Right,Bottom,Top,Near_val,Far_val) ->
%% replaces the current matrix, as if {@link gl:multMatrixd/1} were called with the following
%% matrix as its argument:
%%
-%% [((2 nearVal)/(right-left)) 0 A 0 0((2 nearVal)/(top-bottom)) B 0 0 0 C D 0 0 -1 0]
-%%
-%% A=(right+left)/(right-left)
-%%
-%% B=(top+bottom)/(top-bottom)
-%%
-%% C=-((farVal+nearVal)/(farVal-nearVal))
-%%
-%% D=-((2 farVal nearVal)/(farVal-nearVal))
-%%
-%% Typically, the matrix mode is `?GL_PROJECTION', and (left bottom-nearVal) and (right top-nearVal) specify the points on
-%% the near clipping plane that are mapped to the lower left and upper right corners of the
-%% window, assuming that the eye is located at (0, 0, 0). -farVal specifies the location
-%% of the far clipping plane. Both `NearVal' and `FarVal' must be positive.
-%%
-%% Use {@link gl:pushMatrix/0} and {@link gl:pushMatrix/0} to save and restore the current
-%% matrix stack.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFrustum.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glFrustum.xml">external</a> documentation.
-spec frustum(Left, Right, Bottom, Top, Near_val, Far_val) -> 'ok' when Left :: float(),Right :: float(),Bottom :: float(),Top :: float(),Near_val :: float(),Far_val :: float().
frustum(Left,Right,Bottom,Top,Near_val,Far_val) ->
cast(5087, <<Left:?GLdouble,Right:?GLdouble,Bottom:?GLdouble,Top:?GLdouble,Near_val:?GLdouble,Far_val:?GLdouble>>).
@@ -2576,14 +909,7 @@ frustum(Left,Right,Bottom,Top,Near_val,Far_val) ->
%% coordinates to window coordinates. Let (x nd y nd) be normalized device coordinates. Then the window
%% coordinates (x w y w) are computed as follows:
%%
-%% x w=(x nd+1) (width/2)+x
-%%
-%% y w=(y nd+1) (height/2)+y
-%%
-%% Viewport width and height are silently clamped to a range that depends on the implementation.
-%% To query this range, call {@link gl:getBooleanv/1} with argument `?GL_MAX_VIEWPORT_DIMS'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glViewport.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glViewport.xhtml">external</a> documentation.
-spec viewport(X, Y, Width, Height) -> 'ok' when X :: integer(),Y :: integer(),Width :: integer(),Height :: integer().
viewport(X,Y,Width,Height) ->
cast(5088, <<X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei>>).
@@ -2595,20 +921,7 @@ viewport(X,Y,Width,Height) ->
%% , and `?GL_TEXTURE', the depth is at least 2. The current matrix in any mode is the
%% matrix on the top of the stack for that mode.
%%
-%% ``gl:pushMatrix'' pushes the current matrix stack down by one, duplicating the current
-%% matrix. That is, after a ``gl:pushMatrix'' call, the matrix on top of the stack is identical
-%% to the one below it.
-%%
-%% {@link gl:pushMatrix/0} pops the current matrix stack, replacing the current matrix with
-%% the one below it on the stack.
-%%
-%% Initially, each of the stacks contains one matrix, an identity matrix.
-%%
-%% It is an error to push a full matrix stack or to pop a matrix stack that contains only
-%% a single matrix. In either case, the error flag is set and no other change is made to
-%% GL state.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPushMatrix.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPushMatrix.xml">external</a> documentation.
-spec pushMatrix() -> 'ok'.
pushMatrix() ->
cast(5089, <<>>).
@@ -2624,11 +937,7 @@ popMatrix() ->
%% ``gl:loadIdentity'' replaces the current matrix with the identity matrix. It is semantically
%% equivalent to calling {@link gl:loadMatrixd/1} with the identity matrix
%%
-%% ((1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1))
-%%
-%% but in some cases it is more efficient.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadIdentity.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLoadIdentity.xml">external</a> documentation.
-spec loadIdentity() -> 'ok'.
loadIdentity() ->
cast(5091, <<>>).
@@ -2639,16 +948,7 @@ loadIdentity() ->
%% by `M' . The current matrix is the projection matrix, modelview matrix, or texture
%% matrix, depending on the current matrix mode (see {@link gl:matrixMode/1} ).
%%
-%% The current matrix, M, defines a transformation of coordinates. For instance, assume
-%% M refers to the modelview matrix. If v=(v[0] v[1] v[2] v[3]) is the set of object coordinates of a vertex,
-%% and `M' points to an array of 16 single- or double-precision floating-point values
-%% m={m[0] m[1] ... m[15]}, then the modelview transformation M(v) does the following:
-%%
-%% M(v)=(m[0] m[4] m[8] m[12] m[1] m[5] m[9] m[13] m[2] m[6] m[10] m[14] m[3] m[7] m[11] m[15])×(v[0] v[1] v[2] v[3])
-%%
-%% Projection and texture transformations are similarly defined.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadMatrix.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLoadMatrix.xml">external</a> documentation.
-spec loadMatrixd(M) -> 'ok' when M :: matrix().
loadMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
cast(5092, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble>>);
@@ -2668,10 +968,7 @@ loadMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
%% ``gl:multMatrix'' multiplies the current matrix with the one specified using `M' ,
%% and replaces the current matrix with the product.
%%
-%% The current matrix is determined by the current matrix mode (see {@link gl:matrixMode/1} ).
-%% It is either the projection matrix, modelview matrix, or the texture matrix.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultMatrix.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glMultMatrix.xml">external</a> documentation.
-spec multMatrixd(M) -> 'ok' when M :: matrix().
multMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
cast(5094, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble>>);
@@ -2693,16 +990,7 @@ multMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
%% replacing the current matrix, as if {@link gl:multMatrixd/1} were called with the following
%% matrix as its argument:
%%
-%% (x 2(1-c)+c x y(1-c)-z s x z(1-c)+y s 0 y x(1-c)+z s y 2(1-c)+c y z(1-c)-x s 0 x z(1-c)-y s y z(1-c)+x s z 2(1-c)+c 0 0 0 0
-%% 1)
-%%
-%% Where c=cos(angle), s=sin(angle), and ||(x y z)||=1 (if not, the GL will normalize this vector).
-%%
-%% If the matrix mode is either `?GL_MODELVIEW' or `?GL_PROJECTION', all objects
-%% drawn after ``gl:rotate'' is called are rotated. Use {@link gl:pushMatrix/0} and {@link gl:pushMatrix/0}
-%% to save and restore the unrotated coordinate system.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRotate.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glRotate.xml">external</a> documentation.
-spec rotated(Angle, X, Y, Z) -> 'ok' when Angle :: float(),X :: float(),Y :: float(),Z :: float().
rotated(Angle,X,Y,Z) ->
cast(5096, <<Angle:?GLdouble,X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>).
@@ -2719,19 +1007,7 @@ rotatef(Angle,X,Y,Z) ->
%% axes. The three parameters indicate the desired scale factor along each of the three axes.
%%
%%
-%% The current matrix (see {@link gl:matrixMode/1} ) is multiplied by this scale matrix, and
-%% the product replaces the current matrix as if {@link gl:multMatrixd/1} were called with
-%% the following matrix as its argument:
-%%
-%% (x 0 0 0 0 y 0 0 0 0 z 0 0 0 0 1)
-%%
-%% If the matrix mode is either `?GL_MODELVIEW' or `?GL_PROJECTION', all objects
-%% drawn after ``gl:scale'' is called are scaled.
-%%
-%% Use {@link gl:pushMatrix/0} and {@link gl:pushMatrix/0} to save and restore the unscaled
-%% coordinate system.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScale.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glScale.xml">external</a> documentation.
-spec scaled(X, Y, Z) -> 'ok' when X :: float(),Y :: float(),Z :: float().
scaled(X,Y,Z) ->
cast(5098, <<X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>).
@@ -2748,15 +1024,7 @@ scalef(X,Y,Z) ->
%% ) is multiplied by this translation matrix, with the product replacing the current matrix,
%% as if {@link gl:multMatrixd/1} were called with the following matrix for its argument:
%%
-%% (1 0 0 x 0 1 0 y 0 0 1 z 0 0 0 1)
-%%
-%% If the matrix mode is either `?GL_MODELVIEW' or `?GL_PROJECTION', all objects
-%% drawn after a call to ``gl:translate'' are translated.
-%%
-%% Use {@link gl:pushMatrix/0} and {@link gl:pushMatrix/0} to save and restore the untranslated
-%% coordinate system.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTranslate.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTranslate.xml">external</a> documentation.
-spec translated(X, Y, Z) -> 'ok' when X :: float(),Y :: float(),Z :: float().
translated(X,Y,Z) ->
cast(5100, <<X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>).
@@ -2772,10 +1040,7 @@ translatef(X,Y,Z) ->
%% ``gl:isList'' returns `?GL_TRUE' if `List' is the name of a display list and
%% returns `?GL_FALSE' if it is not, or if an error occurs.
%%
-%% A name returned by {@link gl:genLists/1} , but not yet associated with a display list by
-%% calling {@link gl:newList/2} , is not the name of a display list.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsList.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glIsList.xml">external</a> documentation.
-spec isList(List) -> 0|1 when List :: integer().
isList(List) ->
call(5102, <<List:?GLuint>>).
@@ -2787,11 +1052,7 @@ isList(List) ->
%% display lists to delete. All display lists d with list&lt;= d&lt;= list+range-1 are
%% deleted.
%%
-%% All storage locations allocated to the specified display lists are freed, and the names
-%% are available for reuse at a later time. Names within the range that do not have an associated
-%% display list are ignored. If `Range' is 0, nothing happens.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteLists.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glDeleteLists.xml">external</a> documentation.
-spec deleteLists(List, Range) -> 'ok' when List :: integer(),Range :: integer().
deleteLists(List,Range) ->
cast(5103, <<List:?GLuint,Range:?GLsizei>>).
@@ -2804,7 +1065,7 @@ deleteLists(List,Range) ->
%% available, or if any error is generated, no display lists are generated, and 0 is returned.
%%
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenLists.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGenLists.xml">external</a> documentation.
-spec genLists(Range) -> integer() when Range :: integer().
genLists(Range) ->
call(5104, <<Range:?GLsizei>>).
@@ -2815,53 +1076,14 @@ genLists(Range) ->
%% Display lists are created with ``gl:newList''. All subsequent commands are placed in
%% the display list, in the order issued, until {@link gl:endList/0} is called.
%%
-%% ``gl:newList'' has two arguments. The first argument, `List' , is a positive integer
-%% that becomes the unique name for the display list. Names can be created and reserved with
-%% {@link gl:genLists/1} and tested for uniqueness with {@link gl:isList/1} . The second argument,
-%% `Mode' , is a symbolic constant that can assume one of two values:
-%%
-%% `?GL_COMPILE': Commands are merely compiled.
-%%
-%% `?GL_COMPILE_AND_EXECUTE': Commands are executed as they are compiled into the display
-%% list.
-%%
-%% Certain commands are not compiled into the display list but are executed immediately,
-%% regardless of the display-list mode. These commands are {@link gl:areTexturesResident/1} , {@link gl:colorPointer/4}
-%% , {@link gl:deleteLists/2} , {@link gl:deleteTextures/1} , {@link gl:enableClientState/1} , {@link gl:edgeFlagPointer/2}
-%% , {@link gl:enableClientState/1} , {@link gl:feedbackBuffer/3} , {@link gl:finish/0} , {@link gl:flush/0}
-%% , {@link gl:genLists/1} , {@link gl:genTextures/1} , {@link gl:indexPointer/3} , {@link gl:interleavedArrays/3}
-%% , {@link gl:isEnabled/1} , {@link gl:isList/1} , {@link gl:isTexture/1} , {@link gl:normalPointer/3}
-%% , {@link gl:pushClientAttrib/1} , {@link gl:pixelStoref/2} , {@link gl:pushClientAttrib/1} , {@link gl:readPixels/7}
-%% , {@link gl:renderMode/1} , {@link gl:selectBuffer/2} , {@link gl:texCoordPointer/4} , {@link gl:vertexPointer/4}
-%% , and all of the {@link gl:getBooleanv/1} commands.
-%%
-%% Similarly, {@link gl:texImage1D/8} , {@link gl:texImage2D/9} , and {@link gl:texImage3D/10}
-%% are executed immediately and not compiled into the display list when their first argument
-%% is `?GL_PROXY_TEXTURE_1D', `?GL_PROXY_TEXTURE_1D', or `?GL_PROXY_TEXTURE_3D'
-%% , respectively.
-%%
-%% When the ARB_imaging extension is supported, {@link gl:histogram/4} executes immediately
-%% when its argument is `?GL_PROXY_HISTOGRAM'. Similarly, {@link gl:colorTable/6} executes
-%% immediately when its first argument is `?GL_PROXY_COLOR_TABLE', `?GL_PROXY_POST_CONVOLUTION_COLOR_TABLE'
-%% , or `?GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE'.
-%%
-%% For OpenGL versions 1.3 and greater, or when the ARB_multitexture extension is supported,
-%% {@link gl:clientActiveTexture/1} is not compiled into display lists, but executed immediately.
-%%
-%%
-%% When {@link gl:endList/0} is encountered, the display-list definition is completed by
-%% associating the list with the unique name `List' (specified in the ``gl:newList''
-%% command). If a display list with name `List' already exists, it is replaced only
-%% when {@link gl:endList/0} is called.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNewList.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glNewList.xml">external</a> documentation.
-spec newList(List, Mode) -> 'ok' when List :: integer(),Mode :: enum().
newList(List,Mode) ->
cast(5105, <<List:?GLuint,Mode:?GLenum>>).
%% @doc glBeginList
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginList.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec endList() -> 'ok'.
endList() ->
cast(5106, <<>>).
@@ -2873,17 +1095,7 @@ endList() ->
%% list. If `List' has not been defined as a display list, ``gl:callList'' is ignored.
%%
%%
-%% ``gl:callList'' can appear inside a display list. To avoid the possibility of infinite
-%% recursion resulting from display lists calling one another, a limit is placed on the nesting
-%% level of display lists during display-list execution. This limit is at least 64, and it
-%% depends on the implementation.
-%%
-%% GL state is not saved and restored across a call to ``gl:callList''. Thus, changes
-%% made to GL state during the execution of a display list remain after execution of the
-%% display list is completed. Use {@link gl:pushAttrib/1} , {@link gl:pushAttrib/1} , {@link gl:pushMatrix/0}
-%% , and {@link gl:pushMatrix/0} to preserve GL state across ``gl:callList'' calls.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCallList.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glCallList.xml">external</a> documentation.
-spec callList(List) -> 'ok' when List :: integer().
callList(List) ->
cast(5107, <<List:?GLuint>>).
@@ -2895,62 +1107,7 @@ callList(List) ->
%% just as if they were called without using a display list. Names of display lists that
%% have not been defined are ignored.
%%
-%% ``gl:callLists'' provides an efficient means for executing more than one display list. `Type'
-%% allows lists with various name formats to be accepted. The formats are as follows:
-%%
-%% `?GL_BYTE': `Lists' is treated as an array of signed bytes, each in the range
-%% -128 through 127.
-%%
-%% `?GL_UNSIGNED_BYTE': `Lists' is treated as an array of unsigned bytes, each
-%% in the range 0 through 255.
-%%
-%% `?GL_SHORT': `Lists' is treated as an array of signed two-byte integers, each
-%% in the range -32768 through 32767.
-%%
-%% `?GL_UNSIGNED_SHORT': `Lists' is treated as an array of unsigned two-byte integers,
-%% each in the range 0 through 65535.
-%%
-%% `?GL_INT': `Lists' is treated as an array of signed four-byte integers.
-%%
-%% `?GL_UNSIGNED_INT': `Lists' is treated as an array of unsigned four-byte integers.
-%%
-%%
-%% `?GL_FLOAT': `Lists' is treated as an array of four-byte floating-point values.
-%%
-%%
-%% `?GL_2_BYTES': `Lists' is treated as an array of unsigned bytes. Each pair of
-%% bytes specifies a single display-list name. The value of the pair is computed as 256 times
-%% the unsigned value of the first byte plus the unsigned value of the second byte.
-%%
-%% `?GL_3_BYTES': `Lists' is treated as an array of unsigned bytes. Each triplet
-%% of bytes specifies a single display-list name. The value of the triplet is computed as
-%% 65536 times the unsigned value of the first byte, plus 256 times the unsigned value of
-%% the second byte, plus the unsigned value of the third byte.
-%%
-%% `?GL_4_BYTES': `Lists' is treated as an array of unsigned bytes. Each quadruplet
-%% of bytes specifies a single display-list name. The value of the quadruplet is computed
-%% as 16777216 times the unsigned value of the first byte, plus 65536 times the unsigned
-%% value of the second byte, plus 256 times the unsigned value of the third byte, plus the
-%% unsigned value of the fourth byte.
-%%
-%% The list of display-list names is not null-terminated. Rather, `N' specifies how
-%% many names are to be taken from `Lists' .
-%%
-%% An additional level of indirection is made available with the {@link gl:listBase/1} command,
-%% which specifies an unsigned offset that is added to each display-list name specified in `Lists'
-%% before that display list is executed.
-%%
-%% ``gl:callLists'' can appear inside a display list. To avoid the possibility of infinite
-%% recursion resulting from display lists calling one another, a limit is placed on the nesting
-%% level of display lists during display-list execution. This limit must be at least 64,
-%% and it depends on the implementation.
-%%
-%% GL state is not saved and restored across a call to ``gl:callLists''. Thus, changes
-%% made to GL state during the execution of the display lists remain after execution is completed.
-%% Use {@link gl:pushAttrib/1} , {@link gl:pushAttrib/1} , {@link gl:pushMatrix/0} , and {@link gl:pushMatrix/0}
-%% to preserve GL state across ``gl:callLists'' calls.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCallLists.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glCallLists.xml">external</a> documentation.
-spec callLists(Lists) -> 'ok' when Lists :: [integer()].
callLists(Lists) ->
ListsLen = length(Lists),
@@ -2965,7 +1122,7 @@ callLists(Lists) ->
%% by adding `Base' to each offset. Names that reference valid display lists are executed;
%% the others are ignored.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glListBase.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glListBase.xml">external</a> documentation.
-spec listBase(Base) -> 'ok' when Base :: integer().
listBase(Base) ->
cast(5109, <<Base:?GLuint>>).
@@ -2977,66 +1134,7 @@ listBase(Base) ->
%% ten ways the vertices are interpreted. Taking n as an integer count starting at one,
%% and N as the total number of vertices specified, the interpretations are as follows:
%%
-%% `?GL_POINTS': Treats each vertex as a single point. Vertex n defines point n.
-%% N points are drawn.
-%%
-%% `?GL_LINES': Treats each pair of vertices as an independent line segment. Vertices
-%% 2 n-1 and 2 n define line n. N/2 lines are drawn.
-%%
-%% `?GL_LINE_STRIP': Draws a connected group of line segments from the first vertex
-%% to the last. Vertices n and n+1 define line n. N-1 lines are drawn.
-%%
-%% `?GL_LINE_LOOP': Draws a connected group of line segments from the first vertex
-%% to the last, then back to the first. Vertices n and n+1 define line n. The last
-%% line, however, is defined by vertices N and 1. N lines are drawn.
-%%
-%% `?GL_TRIANGLES': Treats each triplet of vertices as an independent triangle. Vertices
-%% 3 n-2, 3 n-1, and 3 n define triangle n. N/3 triangles are drawn.
-%%
-%% `?GL_TRIANGLE_STRIP': Draws a connected group of triangles. One triangle is defined
-%% for each vertex presented after the first two vertices. For odd n, vertices n, n+1,
-%% and n+2 define triangle n. For even n, vertices n+1, n, and n+2 define triangle
-%% n. N-2 triangles are drawn.
-%%
-%% `?GL_TRIANGLE_FAN': Draws a connected group of triangles. One triangle is defined
-%% for each vertex presented after the first two vertices. Vertices 1, n+1, and n+2
-%% define triangle n. N-2 triangles are drawn.
-%%
-%% `?GL_QUADS': Treats each group of four vertices as an independent quadrilateral.
-%% Vertices 4 n-3, 4 n-2, 4 n-1, and 4 n define quadrilateral n. N/4 quadrilaterals
-%% are drawn.
-%%
-%% `?GL_QUAD_STRIP': Draws a connected group of quadrilaterals. One quadrilateral is
-%% defined for each pair of vertices presented after the first pair. Vertices 2 n-1, 2
-%% n, 2 n+2, and 2 n+1 define quadrilateral n. N/2-1 quadrilaterals are drawn. Note
-%% that the order in which vertices are used to construct a quadrilateral from strip data
-%% is different from that used with independent data.
-%%
-%% `?GL_POLYGON': Draws a single, convex polygon. Vertices 1 through N define this
-%% polygon.
-%%
-%% Only a subset of GL commands can be used between ``gl:'begin''' and {@link gl:'begin'/1} .
-%% The commands are {@link gl:vertex2d/2} , {@link gl:color3b/3} , {@link gl:secondaryColor3b/3} , {@link gl:indexd/1}
-%% , {@link gl:normal3b/3} , {@link gl:fogCoordf/1} , {@link gl:texCoord1d/1} , {@link gl:multiTexCoord1d/2}
-%% , {@link gl:vertexAttrib1d/2} , {@link gl:evalCoord1d/1} , {@link gl:evalPoint1/1} , {@link gl:arrayElement/1}
-%% , {@link gl:materialf/3} , and {@link gl:edgeFlag/1} . Also, it is acceptable to use {@link gl:callList/1}
-%% or {@link gl:callLists/1} to execute display lists that include only the preceding commands.
-%% If any other GL command is executed between ``gl:'begin''' and {@link gl:'begin'/1} , the error
-%% flag is set and the command is ignored.
-%%
-%% Regardless of the value chosen for `Mode' , there is no limit to the number of vertices
-%% that can be defined between ``gl:'begin''' and {@link gl:'begin'/1} . Lines, triangles, quadrilaterals,
-%% and polygons that are incompletely specified are not drawn. Incomplete specification results
-%% when either too few vertices are provided to specify even a single primitive or when an
-%% incorrect multiple of vertices is specified. The incomplete primitive is ignored; the
-%% rest are drawn.
-%%
-%% The minimum specification of vertices for each primitive is as follows: 1 for a point,
-%% 2 for a line, 3 for a triangle, 4 for a quadrilateral, and 3 for a polygon. Modes that
-%% require a certain multiple of vertices are `?GL_LINES' (2), `?GL_TRIANGLES'
-%% (3), `?GL_QUADS' (4), and `?GL_QUAD_STRIP' (2).
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBegin.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glBegin.xml">external</a> documentation.
-spec 'begin'(Mode) -> 'ok' when Mode :: enum().
'begin'(Mode) ->
cast(5110, <<Mode:?GLenum>>).
@@ -3053,10 +1151,7 @@ listBase(Base) ->
%% point, line, and polygon vertices. The current color, normal, texture coordinates, and
%% fog coordinate are associated with the vertex when ``gl:vertex'' is called.
%%
-%% When only x and y are specified, z defaults to 0 and w defaults to 1. When x,
-%% y, and z are specified, w defaults to 1.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glVertex.xml">external</a> documentation.
-spec vertex2d(X, Y) -> 'ok' when X :: float(),Y :: float().
vertex2d(X,Y) ->
cast(5112, <<X:?GLdouble,Y:?GLdouble>>).
@@ -3182,16 +1277,7 @@ vertex4sv({X,Y,Z,W}) -> vertex4s(X,Y,Z,W).
%% mapping that maps the most positive representable integer value to 1.0 and the most negative
%% representable integer value to -1.0.
%%
-%% Normals specified with ``gl:normal'' need not have unit length. If `?GL_NORMALIZE'
-%% is enabled, then normals of any length specified with ``gl:normal'' are normalized after
-%% transformation. If `?GL_RESCALE_NORMAL' is enabled, normals are scaled by a scaling
-%% factor derived from the modelview matrix. `?GL_RESCALE_NORMAL' requires that the
-%% originally specified normals were of unit length, and that the modelview matrix contain
-%% only uniform scales for proper results. To enable and disable normalization, call {@link gl:enable/1}
-%% and {@link gl:enable/1} with either `?GL_NORMALIZE' or `?GL_RESCALE_NORMAL'.
-%% Normalization is initially disabled.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glNormal.xml">external</a> documentation.
-spec normal3b(Nx, Ny, Nz) -> 'ok' when Nx :: integer(),Ny :: integer(),Nz :: integer().
normal3b(Nx,Ny,Nz) ->
cast(5124, <<Nx:?GLbyte,Ny:?GLbyte,Nz:?GLbyte>>).
@@ -3245,15 +1331,7 @@ normal3sv({Nx,Ny,Nz}) -> normal3s(Nx,Ny,Nz).
%% ``gl:index'' updates the current (single-valued) color index. It takes one argument,
%% the new value for the current color index.
%%
-%% The current index is stored as a floating-point value. Integer values are converted directly
-%% to floating-point values, with no special mapping. The initial value is 1.
-%%
-%% Index values outside the representable range of the color index buffer are not clamped.
-%% However, before an index is dithered (if enabled) and written to the frame buffer, it
-%% is converted to fixed-point format. Any bits in the integer portion of the resulting fixed-point
-%% value that do not correspond to bits in the frame buffer are masked out.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glIndex.xml">external</a> documentation.
-spec indexd(C) -> 'ok' when C :: float().
indexd(C) ->
cast(5129, <<C:?GLdouble>>).
@@ -3310,24 +1388,7 @@ indexubv({C}) -> indexub(C).
%% green, and blue values explicitly and set the current alpha value to 1.0 (full intensity)
%% implicitly. ``gl:color4'' variants specify all four color components explicitly.
%%
-%% ``gl:color3b'', ``gl:color4b'', ``gl:color3s'', ``gl:color4s'', ``gl:color3i'',
-%% and ``gl:color4i'' take three or four signed byte, short, or long integers as arguments.
-%% When `v' is appended to the name, the color commands can take a pointer to an array
-%% of such values.
-%%
-%% Current color values are stored in floating-point format, with unspecified mantissa and
-%% exponent sizes. Unsigned integer color components, when specified, are linearly mapped
-%% to floating-point values such that the largest representable value maps to 1.0 (full intensity),
-%% and 0 maps to 0.0 (zero intensity). Signed integer color components, when specified, are
-%% linearly mapped to floating-point values such that the most positive representable value
-%% maps to 1.0, and the most negative representable value maps to -1.0. (Note that this
-%% mapping does not convert 0 precisely to 0.0.) Floating-point values are mapped directly.
-%%
-%% Neither floating-point nor signed integer values are clamped to the range [0 1] before the
-%% current color is updated. However, color components are clamped to this range before they
-%% are interpolated or written into a color buffer.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glColor.xml">external</a> documentation.
-spec color3b(Red, Green, Blue) -> 'ok' when Red :: integer(),Green :: integer(),Blue :: integer().
color3b(Red,Green,Blue) ->
cast(5134, <<Red:?GLbyte,Green:?GLbyte,Blue:?GLbyte>>).
@@ -3494,13 +1555,7 @@ color4usv({Red,Green,Blue,Alpha}) -> color4us(Red,Green,Blue,Alpha).
%% Similarly, ``gl:texCoord3'' specifies the texture coordinates as (s t r 1), and ``gl:texCoord4''
%% defines all four components explicitly as (s t r q).
%%
-%% The current texture coordinates are part of the data that is associated with each vertex
-%% and with the current raster position. Initially, the values for `s', `t', `r'
-%% , and `q' are (0, 0, 0, 1).
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTexCoord.xml">external</a> documentation.
-spec texCoord1d(S) -> 'ok' when S :: float().
texCoord1d(S) ->
cast(5150, <<S:?GLdouble>>).
@@ -3666,41 +1721,7 @@ texCoord4sv({S,T,R,Q}) -> texCoord4s(S,T,R,Q).
%% subpixel accuracy. See {@link gl:bitmap/7} , {@link gl:drawPixels/5} , and {@link gl:copyPixels/5}
%% .
%%
-%% The current raster position consists of three window coordinates ( x, y, z), a clip
-%% coordinate value ( w), an eye coordinate distance, a valid bit, and associated color
-%% data and texture coordinates. The w coordinate is a clip coordinate, because w is
-%% not projected to window coordinates. ``gl:rasterPos4'' specifies object coordinates x,
-%% y, z, and w explicitly. ``gl:rasterPos3'' specifies object coordinate x, y, and
-%% z explicitly, while w is implicitly set to 1. ``gl:rasterPos2'' uses the argument
-%% values for x and y while implicitly setting z and w to 0 and 1.
-%%
-%% The object coordinates presented by ``gl:rasterPos'' are treated just like those of a {@link gl:vertex2d/2}
-%% command: They are transformed by the current modelview and projection matrices and passed
-%% to the clipping stage. If the vertex is not culled, then it is projected and scaled to
-%% window coordinates, which become the new current raster position, and the `?GL_CURRENT_RASTER_POSITION_VALID'
-%% flag is set. If the vertex `is' culled, then the valid bit is cleared and the current
-%% raster position and associated color and texture coordinates are undefined.
-%%
-%% The current raster position also includes some associated color data and texture coordinates.
-%% If lighting is enabled, then `?GL_CURRENT_RASTER_COLOR' (in RGBA mode) or `?GL_CURRENT_RASTER_INDEX'
-%% (in color index mode) is set to the color produced by the lighting calculation (see {@link gl:lightf/3}
-%% , {@link gl:lightModelf/2} , and {@link gl:shadeModel/1} ). If lighting is disabled, current
-%% color (in RGBA mode, state variable `?GL_CURRENT_COLOR') or color index (in color
-%% index mode, state variable `?GL_CURRENT_INDEX') is used to update the current raster
-%% color. `?GL_CURRENT_RASTER_SECONDARY_COLOR' (in RGBA mode) is likewise updated.
-%%
-%% Likewise, `?GL_CURRENT_RASTER_TEXTURE_COORDS' is updated as a function of `?GL_CURRENT_TEXTURE_COORDS'
-%% , based on the texture matrix and the texture generation functions (see {@link gl:texGend/3} ).
-%% Finally, the distance from the origin of the eye coordinate system to the vertex as transformed
-%% by only the modelview matrix replaces `?GL_CURRENT_RASTER_DISTANCE'.
-%%
-%% Initially, the current raster position is (0, 0, 0, 1), the current raster distance is
-%% 0, the valid bit is set, the associated RGBA color is (1, 1, 1, 1), the associated color
-%% index is 1, and the associated texture coordinates are (0, 0, 0, 1). In RGBA mode, `?GL_CURRENT_RASTER_INDEX'
-%% is always 1; in color index mode, the current raster RGBA color always maintains its
-%% initial value.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glRasterPos.xml">external</a> documentation.
-spec rasterPos2d(X, Y) -> 'ok' when X :: float(),Y :: float().
rasterPos2d(X,Y) ->
cast(5166, <<X:?GLdouble,Y:?GLdouble>>).
@@ -3826,13 +1847,7 @@ rasterPos4sv({X,Y,Z,W}) -> rasterPos4s(X,Y,Z,W).
%% coordinates or as two pointers to arrays, each containing an (x y) pair. The resulting rectangle
%% is defined in the z=0 plane.
%%
-%% ``gl:rect''( `X1' , `Y1' , `X2' , `Y2' ) is exactly equivalent to the
-%% following sequence: glBegin(`?GL_POLYGON'); glVertex2( `X1' , `Y1' ); glVertex2(
-%% `X2' , `Y1' ); glVertex2( `X2' , `Y2' ); glVertex2( `X1' , `Y2' );
-%% glEnd(); Note that if the second vertex is above and to the right of the first vertex,
-%% the rectangle is constructed with a counterclockwise winding.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glRect.xml">external</a> documentation.
-spec rectd(X1, Y1, X2, Y2) -> 'ok' when X1 :: float(),Y1 :: float(),X2 :: float(),Y2 :: float().
rectd(X1,Y1,X2,Y2) ->
cast(5178, <<X1:?GLdouble,Y1:?GLdouble,X2:?GLdouble,Y2:?GLdouble>>).
@@ -3888,21 +1903,7 @@ rectsv({V1,V2},{V1,V2}) ->
%% to be packed into a single array or stored in separate arrays. (Single-array storage may
%% be more efficient on some implementations; see {@link gl:interleavedArrays/3} .)
%%
-%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2}
-%% ) while a vertex array is specified, `Pointer' is treated as a byte offset into the
-%% buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING'
-%% ) is saved as vertex array client-side state (`?GL_VERTEX_ARRAY_BUFFER_BINDING').
-%%
-%% When a vertex array is specified, `Size' , `Type' , `Stride' , and `Pointer'
-%% are saved as client-side state, in addition to the current vertex array buffer object
-%% binding.
-%%
-%% To enable and disable the vertex array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1}
-%% with the argument `?GL_VERTEX_ARRAY'. If enabled, the vertex array is used when {@link gl:arrayElement/1}
-%% , {@link gl:drawArrays/3} , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements'
-%% , or {@link gl:drawRangeElements/6} is called.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexPointer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glVertexPointer.xml">external</a> documentation.
-spec vertexPointer(Size, Type, Stride, Ptr) -> 'ok' when Size :: integer(),Type :: enum(),Stride :: integer(),Ptr :: offset()|mem().
vertexPointer(Size,Type,Stride,Ptr) when is_integer(Ptr) ->
cast(5186, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei,Ptr:?GLuint>>);
@@ -3918,22 +1919,7 @@ vertexPointer(Size,Type,Stride,Ptr) ->
%% to be packed into a single array or stored in separate arrays. (Single-array storage may
%% be more efficient on some implementations; see {@link gl:interleavedArrays/3} .)
%%
-%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2}
-%% ) while a normal array is specified, `Pointer' is treated as a byte offset into the
-%% buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING'
-%% ) is saved as normal vertex array client-side state (`?GL_NORMAL_ARRAY_BUFFER_BINDING'
-%% ).
-%%
-%% When a normal array is specified, `Type' , `Stride' , and `Pointer' are
-%% saved as client-side state, in addition to the current vertex array buffer object binding.
-%%
-%%
-%% To enable and disable the normal array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1}
-%% with the argument `?GL_NORMAL_ARRAY'. If enabled, the normal array is used when {@link gl:drawArrays/3}
-%% , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements', {@link gl:drawRangeElements/6}
-%% , or {@link gl:arrayElement/1} is called.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNormalPointer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glNormalPointer.xml">external</a> documentation.
-spec normalPointer(Type, Stride, Ptr) -> 'ok' when Type :: enum(),Stride :: integer(),Ptr :: offset()|mem().
normalPointer(Type,Stride,Ptr) when is_integer(Ptr) ->
cast(5188, <<Type:?GLenum,Stride:?GLsizei,Ptr:?GLuint>>);
@@ -3950,22 +1936,7 @@ normalPointer(Type,Stride,Ptr) ->
%% to be packed into a single array or stored in separate arrays. (Single-array storage may
%% be more efficient on some implementations; see {@link gl:interleavedArrays/3} .)
%%
-%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2}
-%% ) while a color array is specified, `Pointer' is treated as a byte offset into the
-%% buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING'
-%% ) is saved as color vertex array client-side state (`?GL_COLOR_ARRAY_BUFFER_BINDING').
-%%
-%%
-%% When a color array is specified, `Size' , `Type' , `Stride' , and `Pointer'
-%% are saved as client-side state, in addition to the current vertex array buffer object
-%% binding.
-%%
-%% To enable and disable the color array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1}
-%% with the argument `?GL_COLOR_ARRAY'. If enabled, the color array is used when {@link gl:drawArrays/3}
-%% , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements', {@link gl:drawRangeElements/6}
-%% , or {@link gl:arrayElement/1} is called.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorPointer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glColorPointer.xml">external</a> documentation.
-spec colorPointer(Size, Type, Stride, Ptr) -> 'ok' when Size :: integer(),Type :: enum(),Stride :: integer(),Ptr :: offset()|mem().
colorPointer(Size,Type,Stride,Ptr) when is_integer(Ptr) ->
cast(5190, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei,Ptr:?GLuint>>);
@@ -3980,22 +1951,7 @@ colorPointer(Size,Type,Stride,Ptr) ->
%% specifies the byte stride from one color index to the next, allowing vertices and attributes
%% to be packed into a single array or stored in separate arrays.
%%
-%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2}
-%% ) while a color index array is specified, `Pointer' is treated as a byte offset into
-%% the buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING'
-%% ) is saved as color index vertex array client-side state (`?GL_INDEX_ARRAY_BUFFER_BINDING'
-%% ).
-%%
-%% When a color index array is specified, `Type' , `Stride' , and `Pointer'
-%% are saved as client-side state, in addition to the current vertex array buffer object
-%% binding.
-%%
-%% To enable and disable the color index array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1}
-%% with the argument `?GL_INDEX_ARRAY'. If enabled, the color index array is used when
-%% {@link gl:drawArrays/3} , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements'
-%% , {@link gl:drawRangeElements/6} , or {@link gl:arrayElement/1} is called.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIndexPointer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glIndexPointer.xml">external</a> documentation.
-spec indexPointer(Type, Stride, Ptr) -> 'ok' when Type :: enum(),Stride :: integer(),Ptr :: offset()|mem().
indexPointer(Type,Stride,Ptr) when is_integer(Ptr) ->
cast(5192, <<Type:?GLenum,Stride:?GLsizei,Ptr:?GLuint>>);
@@ -4013,23 +1969,7 @@ indexPointer(Type,Stride,Ptr) ->
%% array or stored in separate arrays. (Single-array storage may be more efficient on some
%% implementations; see {@link gl:interleavedArrays/3} .)
%%
-%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2}
-%% ) while a texture coordinate array is specified, `Pointer' is treated as a byte offset
-%% into the buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING'
-%% ) is saved as texture coordinate vertex array client-side state (`?GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING'
-%% ).
-%%
-%% When a texture coordinate array is specified, `Size' , `Type' , `Stride' ,
-%% and `Pointer' are saved as client-side state, in addition to the current vertex array
-%% buffer object binding.
-%%
-%% To enable and disable a texture coordinate array, call {@link gl:enableClientState/1}
-%% and {@link gl:enableClientState/1} with the argument `?GL_TEXTURE_COORD_ARRAY'. If
-%% enabled, the texture coordinate array is used when {@link gl:arrayElement/1} , {@link gl:drawArrays/3}
-%% , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements',
-%% or {@link gl:drawRangeElements/6} is called.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoordPointer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTexCoordPointer.xml">external</a> documentation.
-spec texCoordPointer(Size, Type, Stride, Ptr) -> 'ok' when Size :: integer(),Type :: enum(),Stride :: integer(),Ptr :: offset()|mem().
texCoordPointer(Size,Type,Stride,Ptr) when is_integer(Ptr) ->
cast(5194, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei,Ptr:?GLuint>>);
@@ -4044,21 +1984,7 @@ texCoordPointer(Size,Type,Stride,Ptr) ->
%% flag to the next, allowing vertices and attributes to be packed into a single array or
%% stored in separate arrays.
%%
-%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2}
-%% ) while an edge flag array is specified, `Pointer' is treated as a byte offset into
-%% the buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING'
-%% ) is saved as edge flag vertex array client-side state (`?GL_EDGE_FLAG_ARRAY_BUFFER_BINDING'
-%% ).
-%%
-%% When an edge flag array is specified, `Stride' and `Pointer' are saved as client-side
-%% state, in addition to the current vertex array buffer object binding.
-%%
-%% To enable and disable the edge flag array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1}
-%% with the argument `?GL_EDGE_FLAG_ARRAY'. If enabled, the edge flag array is used
-%% when {@link gl:drawArrays/3} , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements'
-%% , {@link gl:drawRangeElements/6} , or {@link gl:arrayElement/1} is called.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEdgeFlagPointer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glEdgeFlagPointer.xml">external</a> documentation.
-spec edgeFlagPointer(Stride, Ptr) -> 'ok' when Stride :: integer(),Ptr :: offset()|mem().
edgeFlagPointer(Stride,Ptr) when is_integer(Ptr) ->
cast(5196, <<Stride:?GLsizei,Ptr:?GLuint>>);
@@ -4075,18 +2001,7 @@ edgeFlagPointer(Stride,Ptr) ->
%% is not enabled, no drawing occurs but the attributes corresponding to the enabled arrays
%% are modified.
%%
-%% Use ``gl:arrayElement'' to construct primitives by indexing vertex data, rather than
-%% by streaming through arrays of data in first-to-last order. Because each call specifies
-%% only a single vertex, it is possible to explicitly specify per-primitive attributes such
-%% as a single normal for each triangle.
-%%
-%% Changes made to array data between the execution of {@link gl:'begin'/1} and the corresponding
-%% execution of {@link gl:'begin'/1} may affect calls to ``gl:arrayElement'' that are made within
-%% the same {@link gl:'begin'/1} / {@link gl:'begin'/1} period in nonsequential ways. That is, a call
-%% to ``gl:arrayElement'' that precedes a change to array data may access the changed data,
-%% and a call that follows a change to array data may access original data.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glArrayElement.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glArrayElement.xml">external</a> documentation.
-spec arrayElement(I) -> 'ok' when I :: integer().
arrayElement(I) ->
cast(5198, <<I:?GLint>>).
@@ -4099,15 +2014,7 @@ arrayElement(I) ->
%% and use them to construct a sequence of primitives with a single call to ``gl:drawArrays''
%% .
%%
-%% When ``gl:drawArrays'' is called, it uses `Count' sequential elements from each
-%% enabled array to construct a sequence of geometric primitives, beginning with element `First'
-%% . `Mode' specifies what kind of primitives are constructed and how the array elements
-%% construct those primitives.
-%%
-%% Vertex attributes that are modified by ``gl:drawArrays'' have an unspecified value
-%% after ``gl:drawArrays'' returns. Attributes that aren't modified remain well defined.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawArrays.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawArrays.xhtml">external</a> documentation.
-spec drawArrays(Mode, First, Count) -> 'ok' when Mode :: enum(),First :: integer(),Count :: integer().
drawArrays(Mode,First,Count) ->
cast(5199, <<Mode:?GLenum,First:?GLint,Count:?GLsizei>>).
@@ -4120,16 +2027,7 @@ drawArrays(Mode,First,Count) ->
%% and so on, and use them to construct a sequence of primitives with a single call to ``gl:drawElements''
%% .
%%
-%% When ``gl:drawElements'' is called, it uses `Count' sequential elements from an
-%% enabled array, starting at `Indices' to construct a sequence of geometric primitives.
-%% `Mode' specifies what kind of primitives are constructed and how the array elements
-%% construct these primitives. If more than one array is enabled, each is used.
-%%
-%% Vertex attributes that are modified by ``gl:drawElements'' have an unspecified value
-%% after ``gl:drawElements'' returns. Attributes that aren't modified maintain their previous
-%% values.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElements.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElements.xhtml">external</a> documentation.
-spec drawElements(Mode, Count, Type, Indices) -> 'ok' when Mode :: enum(),Count :: integer(),Type :: enum(),Indices :: offset()|mem().
drawElements(Mode,Count,Type,Indices) when is_integer(Indices) ->
cast(5200, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint>>);
@@ -4143,21 +2041,7 @@ drawElements(Mode,Count,Type,Indices) ->
%% and vertex arrays whose elements are part of a larger aggregate array element. For some
%% implementations, this is more efficient than specifying the arrays separately.
%%
-%% If `Stride' is 0, the aggregate elements are stored consecutively. Otherwise, `Stride'
-%% bytes occur between the beginning of one aggregate array element and the beginning of
-%% the next aggregate array element.
-%%
-%% `Format' serves as a ``key'' describing the extraction of individual arrays from
-%% the aggregate array. If `Format' contains a T, then texture coordinates are extracted
-%% from the interleaved array. If C is present, color values are extracted. If N is present,
-%% normal coordinates are extracted. Vertex coordinates are always extracted.
-%%
-%% The digits 2, 3, and 4 denote how many values are extracted. F indicates that values
-%% are extracted as floating-point values. Colors may also be extracted as 4 unsigned bytes
-%% if 4UB follows the C. If a color is extracted as 4 unsigned bytes, the vertex array element
-%% which follows is located at the first possible floating-point aligned address.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glInterleavedArrays.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glInterleavedArrays.xml">external</a> documentation.
-spec interleavedArrays(Format, Stride, Pointer) -> 'ok' when Format :: enum(),Stride :: integer(),Pointer :: offset()|mem().
interleavedArrays(Format,Stride,Pointer) when is_integer(Pointer) ->
cast(5202, <<Format:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>);
@@ -4175,23 +2059,7 @@ interleavedArrays(Format,Stride,Pointer) ->
%% result of lighting if lighting is enabled, or it is the current color at the time the
%% vertex was specified if lighting is disabled.
%%
-%% Flat and smooth shading are indistinguishable for points. Starting when {@link gl:'begin'/1}
-%% is issued and counting vertices and primitives from 1, the GL gives each flat-shaded line
-%% segment i the computed color of vertex i+1, its second vertex. Counting similarly
-%% from 1, the GL gives each flat-shaded polygon the computed color of the vertex listed
-%% in the following table. This is the last vertex to specify the polygon in all cases except
-%% single polygons, where the first vertex specifies the flat-shaded color.
-%%
-%% <table><tbody><tr><td>` Primitive Type of Polygon ' i</td><td>` Vertex '</td></tr>
-%% </tbody><tbody><tr><td> Single polygon ( i== 1) </td><td> 1 </td></tr><tr><td> Triangle
-%% strip </td><td> i+2</td></tr><tr><td> Triangle fan </td><td> i+2</td></tr><tr><td> Independent
-%% triangle </td><td> 3 i</td></tr><tr><td> Quad strip </td><td> 2 i+2</td></tr><tr><td>
-%% Independent quad </td><td> 4 i</td></tr></tbody></table>
-%%
-%% Flat and smooth shading are specified by ``gl:shadeModel'' with `Mode' set to `?GL_FLAT'
-%% and `?GL_SMOOTH', respectively.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShadeModel.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glShadeModel.xml">external</a> documentation.
-spec shadeModel(Mode) -> 'ok' when Mode :: enum().
shadeModel(Mode) ->
cast(5204, <<Mode:?GLenum>>).
@@ -4204,88 +2072,7 @@ shadeModel(Mode) ->
%% parameters, again by symbolic name. `Params' is either a single value or a pointer
%% to an array that contains the new values.
%%
-%% To enable and disable lighting calculation, call {@link gl:enable/1} and {@link gl:enable/1}
-%% with argument `?GL_LIGHTING'. Lighting is initially disabled. When it is enabled,
-%% light sources that are enabled contribute to the lighting calculation. Light source i
-%% is enabled and disabled using {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_LIGHT'
-%% i.
-%%
-%% The ten light parameters are as follows:
-%%
-%% `?GL_AMBIENT': `Params' contains four integer or floating-point values that
-%% specify the ambient RGBA intensity of the light. Integer values are mapped linearly such
-%% that the most positive representable value maps to 1.0, and the most negative representable
-%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point
-%% values are clamped. The initial ambient light intensity is (0, 0, 0, 1).
-%%
-%% `?GL_DIFFUSE': `Params' contains four integer or floating-point values that
-%% specify the diffuse RGBA intensity of the light. Integer values are mapped linearly such
-%% that the most positive representable value maps to 1.0, and the most negative representable
-%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point
-%% values are clamped. The initial value for `?GL_LIGHT0' is (1, 1, 1, 1); for other
-%% lights, the initial value is (0, 0, 0, 1).
-%%
-%% `?GL_SPECULAR': `Params' contains four integer or floating-point values that
-%% specify the specular RGBA intensity of the light. Integer values are mapped linearly such
-%% that the most positive representable value maps to 1.0, and the most negative representable
-%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point
-%% values are clamped. The initial value for `?GL_LIGHT0' is (1, 1, 1, 1); for other
-%% lights, the initial value is (0, 0, 0, 1).
-%%
-%% `?GL_POSITION': `Params' contains four integer or floating-point values that
-%% specify the position of the light in homogeneous object coordinates. Both integer and
-%% floating-point values are mapped directly. Neither integer nor floating-point values are
-%% clamped.
-%%
-%% The position is transformed by the modelview matrix when ``gl:light'' is called (just
-%% as if it were a point), and it is stored in eye coordinates. If the w component of the
-%% position is 0, the light is treated as a directional source. Diffuse and specular lighting
-%% calculations take the light's direction, but not its actual position, into account, and
-%% attenuation is disabled. Otherwise, diffuse and specular lighting calculations are based
-%% on the actual location of the light in eye coordinates, and attenuation is enabled. The
-%% initial position is (0, 0, 1, 0); thus, the initial light source is directional, parallel
-%% to, and in the direction of the -z axis.
-%%
-%% `?GL_SPOT_DIRECTION': `Params' contains three integer or floating-point values
-%% that specify the direction of the light in homogeneous object coordinates. Both integer
-%% and floating-point values are mapped directly. Neither integer nor floating-point values
-%% are clamped.
-%%
-%% The spot direction is transformed by the upper 3x3 of the modelview matrix when ``gl:light''
-%% is called, and it is stored in eye coordinates. It is significant only when `?GL_SPOT_CUTOFF'
-%% is not 180, which it is initially. The initial direction is (0 0 -1).
-%%
-%% `?GL_SPOT_EXPONENT': `Params' is a single integer or floating-point value that
-%% specifies the intensity distribution of the light. Integer and floating-point values are
-%% mapped directly. Only values in the range [0 128] are accepted.
-%%
-%% Effective light intensity is attenuated by the cosine of the angle between the direction
-%% of the light and the direction from the light to the vertex being lighted, raised to the
-%% power of the spot exponent. Thus, higher spot exponents result in a more focused light
-%% source, regardless of the spot cutoff angle (see `?GL_SPOT_CUTOFF', next paragraph).
-%% The initial spot exponent is 0, resulting in uniform light distribution.
-%%
-%% `?GL_SPOT_CUTOFF': `Params' is a single integer or floating-point value that
-%% specifies the maximum spread angle of a light source. Integer and floating-point values
-%% are mapped directly. Only values in the range [0 90] and the special value 180 are accepted.
-%% If the angle between the direction of the light and the direction from the light to the
-%% vertex being lighted is greater than the spot cutoff angle, the light is completely masked.
-%% Otherwise, its intensity is controlled by the spot exponent and the attenuation factors.
-%% The initial spot cutoff is 180, resulting in uniform light distribution.
-%%
-%% `?GL_CONSTANT_ATTENUATION'
-%%
-%% `?GL_LINEAR_ATTENUATION'
-%%
-%% `?GL_QUADRATIC_ATTENUATION': `Params' is a single integer or floating-point
-%% value that specifies one of the three light attenuation factors. Integer and floating-point
-%% values are mapped directly. Only nonnegative values are accepted. If the light is positional,
-%% rather than directional, its intensity is attenuated by the reciprocal of the sum of the
-%% constant factor, the linear factor times the distance between the light and the vertex
-%% being lighted, and the quadratic factor times the square of the same distance. The initial
-%% attenuation factors are (1, 0, 0), resulting in no attenuation.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLight.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLight.xml">external</a> documentation.
-spec lightf(Light, Pname, Param) -> 'ok' when Light :: enum(),Pname :: enum(),Param :: float().
lightf(Light,Pname,Param) ->
cast(5205, <<Light:?GLenum,Pname:?GLenum,Param:?GLfloat>>).
@@ -4318,73 +2105,7 @@ lightiv(Light,Pname,Params) ->
%% implementation dependent constant that is greater than or equal to eight. `Pname'
%% specifies one of ten light source parameters, again by symbolic name.
%%
-%% The following parameters are defined:
-%%
-%% `?GL_AMBIENT': `Params' returns four integer or floating-point values representing
-%% the ambient intensity of the light source. Integer values, when requested, are linearly
-%% mapped from the internal floating-point representation such that 1.0 maps to the most
-%% positive representable integer value, and -1.0 maps to the most negative representable
-%% integer value. If the internal value is outside the range [-1 1], the corresponding integer
-%% return value is undefined. The initial value is (0, 0, 0, 1).
-%%
-%% `?GL_DIFFUSE': `Params' returns four integer or floating-point values representing
-%% the diffuse intensity of the light source. Integer values, when requested, are linearly
-%% mapped from the internal floating-point representation such that 1.0 maps to the most
-%% positive representable integer value, and -1.0 maps to the most negative representable
-%% integer value. If the internal value is outside the range [-1 1], the corresponding integer
-%% return value is undefined. The initial value for `?GL_LIGHT0' is (1, 1, 1, 1); for
-%% other lights, the initial value is (0, 0, 0, 0).
-%%
-%% `?GL_SPECULAR': `Params' returns four integer or floating-point values representing
-%% the specular intensity of the light source. Integer values, when requested, are linearly
-%% mapped from the internal floating-point representation such that 1.0 maps to the most
-%% positive representable integer value, and -1.0 maps to the most negative representable
-%% integer value. If the internal value is outside the range [-1 1], the corresponding integer
-%% return value is undefined. The initial value for `?GL_LIGHT0' is (1, 1, 1, 1); for
-%% other lights, the initial value is (0, 0, 0, 0).
-%%
-%% `?GL_POSITION': `Params' returns four integer or floating-point values representing
-%% the position of the light source. Integer values, when requested, are computed by rounding
-%% the internal floating-point values to the nearest integer value. The returned values are
-%% those maintained in eye coordinates. They will not be equal to the values specified using
-%% {@link gl:lightf/3} , unless the modelview matrix was identity at the time {@link gl:lightf/3}
-%% was called. The initial value is (0, 0, 1, 0).
-%%
-%% `?GL_SPOT_DIRECTION': `Params' returns three integer or floating-point values
-%% representing the direction of the light source. Integer values, when requested, are computed
-%% by rounding the internal floating-point values to the nearest integer value. The returned
-%% values are those maintained in eye coordinates. They will not be equal to the values specified
-%% using {@link gl:lightf/3} , unless the modelview matrix was identity at the time {@link gl:lightf/3}
-%% was called. Although spot direction is normalized before being used in the lighting equation,
-%% the returned values are the transformed versions of the specified values prior to normalization.
-%% The initial value is (0 0 -1).
-%%
-%% `?GL_SPOT_EXPONENT': `Params' returns a single integer or floating-point value
-%% representing the spot exponent of the light. An integer value, when requested, is computed
-%% by rounding the internal floating-point representation to the nearest integer. The initial
-%% value is 0.
-%%
-%% `?GL_SPOT_CUTOFF': `Params' returns a single integer or floating-point value
-%% representing the spot cutoff angle of the light. An integer value, when requested, is
-%% computed by rounding the internal floating-point representation to the nearest integer.
-%% The initial value is 180.
-%%
-%% `?GL_CONSTANT_ATTENUATION': `Params' returns a single integer or floating-point
-%% value representing the constant (not distance-related) attenuation of the light. An integer
-%% value, when requested, is computed by rounding the internal floating-point representation
-%% to the nearest integer. The initial value is 1.
-%%
-%% `?GL_LINEAR_ATTENUATION': `Params' returns a single integer or floating-point
-%% value representing the linear attenuation of the light. An integer value, when requested,
-%% is computed by rounding the internal floating-point representation to the nearest integer.
-%% The initial value is 0.
-%%
-%% `?GL_QUADRATIC_ATTENUATION': `Params' returns a single integer or floating-point
-%% value representing the quadratic attenuation of the light. An integer value, when requested,
-%% is computed by rounding the internal floating-point representation to the nearest integer.
-%% The initial value is 0.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetLight.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetLight.xml">external</a> documentation.
-spec getLightfv(Light, Pname) -> {float(),float(),float(),float()} when Light :: enum(),Pname :: enum().
getLightfv(Light,Pname) ->
call(5209, <<Light:?GLenum,Pname:?GLenum>>).
@@ -4400,63 +2121,7 @@ getLightiv(Light,Pname) ->
%% ``gl:lightModel'' sets the lighting model parameter. `Pname' names a parameter
%% and `Params' gives the new value. There are three lighting model parameters:
%%
-%% `?GL_LIGHT_MODEL_AMBIENT': `Params' contains four integer or floating-point
-%% values that specify the ambient RGBA intensity of the entire scene. Integer values are
-%% mapped linearly such that the most positive representable value maps to 1.0, and the most
-%% negative representable value maps to -1.0. Floating-point values are mapped directly.
-%% Neither integer nor floating-point values are clamped. The initial ambient scene intensity
-%% is (0.2, 0.2, 0.2, 1.0).
-%%
-%% `?GL_LIGHT_MODEL_COLOR_CONTROL': `Params' must be either `?GL_SEPARATE_SPECULAR_COLOR'
-%% or `?GL_SINGLE_COLOR'. `?GL_SINGLE_COLOR' specifies that a single color is
-%% generated from the lighting computation for a vertex. `?GL_SEPARATE_SPECULAR_COLOR'
-%% specifies that the specular color computation of lighting be stored separately from the
-%% remainder of the lighting computation. The specular color is summed into the generated
-%% fragment's color after the application of texture mapping (if enabled). The initial value
-%% is `?GL_SINGLE_COLOR'.
-%%
-%% `?GL_LIGHT_MODEL_LOCAL_VIEWER': `Params' is a single integer or floating-point
-%% value that specifies how specular reflection angles are computed. If `Params' is
-%% 0 (or 0.0), specular reflection angles take the view direction to be parallel to and in
-%% the direction of the -`z' axis, regardless of the location of the vertex in eye coordinates.
-%% Otherwise, specular reflections are computed from the origin of the eye coordinate system.
-%% The initial value is 0.
-%%
-%% `?GL_LIGHT_MODEL_TWO_SIDE': `Params' is a single integer or floating-point value
-%% that specifies whether one- or two-sided lighting calculations are done for polygons.
-%% It has no effect on the lighting calculations for points, lines, or bitmaps. If `Params'
-%% is 0 (or 0.0), one-sided lighting is specified, and only the `front' material parameters
-%% are used in the lighting equation. Otherwise, two-sided lighting is specified. In this
-%% case, vertices of back-facing polygons are lighted using the `back' material parameters
-%% and have their normals reversed before the lighting equation is evaluated. Vertices of
-%% front-facing polygons are always lighted using the `front' material parameters, with
-%% no change to their normals. The initial value is 0.
-%%
-%% In RGBA mode, the lighted color of a vertex is the sum of the material emission intensity,
-%% the product of the material ambient reflectance and the lighting model full-scene ambient
-%% intensity, and the contribution of each enabled light source. Each light source contributes
-%% the sum of three terms: ambient, diffuse, and specular. The ambient light source contribution
-%% is the product of the material ambient reflectance and the light's ambient intensity.
-%% The diffuse light source contribution is the product of the material diffuse reflectance,
-%% the light's diffuse intensity, and the dot product of the vertex's normal with the normalized
-%% vector from the vertex to the light source. The specular light source contribution is
-%% the product of the material specular reflectance, the light's specular intensity, and
-%% the dot product of the normalized vertex-to-eye and vertex-to-light vectors, raised to
-%% the power of the shininess of the material. All three light source contributions are attenuated
-%% equally based on the distance from the vertex to the light source and on light source
-%% direction, spread exponent, and spread cutoff angle. All dot products are replaced with
-%% 0 if they evaluate to a negative value.
-%%
-%% The alpha component of the resulting lighted color is set to the alpha value of the material
-%% diffuse reflectance.
-%%
-%% In color index mode, the value of the lighted index of a vertex ranges from the ambient
-%% to the specular values passed to {@link gl:materialf/3} using `?GL_COLOR_INDEXES'.
-%% Diffuse and specular coefficients, computed with a (.30, .59, .11) weighting of the lights'
-%% colors, the shininess of the material, and the same reflection and attenuation equations
-%% as in the RGBA case, determine how much above ambient the resulting index is.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLightModel.xml">external</a> documentation.
-spec lightModelf(Pname, Param) -> 'ok' when Pname :: enum(),Param :: float().
lightModelf(Pname,Param) ->
cast(5211, <<Pname:?GLenum,Param:?GLfloat>>).
@@ -4490,60 +2155,7 @@ lightModeliv(Pname,Params) ->
%% to shade back-facing polygons only when two-sided lighting is enabled. Refer to the {@link gl:lightModelf/2}
%% reference page for details concerning one- and two-sided lighting calculations.
%%
-%% ``gl:material'' takes three arguments. The first, `Face' , specifies whether the `?GL_FRONT'
-%% materials, the `?GL_BACK' materials, or both `?GL_FRONT_AND_BACK' materials
-%% will be modified. The second, `Pname' , specifies which of several parameters in one
-%% or both sets will be modified. The third, `Params' , specifies what value or values
-%% will be assigned to the specified parameter.
-%%
-%% Material parameters are used in the lighting equation that is optionally applied to each
-%% vertex. The equation is discussed in the {@link gl:lightModelf/2} reference page. The parameters
-%% that can be specified using ``gl:material'', and their interpretations by the lighting
-%% equation, are as follows:
-%%
-%% `?GL_AMBIENT': `Params' contains four integer or floating-point values that
-%% specify the ambient RGBA reflectance of the material. Integer values are mapped linearly
-%% such that the most positive representable value maps to 1.0, and the most negative representable
-%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point
-%% values are clamped. The initial ambient reflectance for both front- and back-facing materials
-%% is (0.2, 0.2, 0.2, 1.0).
-%%
-%% `?GL_DIFFUSE': `Params' contains four integer or floating-point values that
-%% specify the diffuse RGBA reflectance of the material. Integer values are mapped linearly
-%% such that the most positive representable value maps to 1.0, and the most negative representable
-%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point
-%% values are clamped. The initial diffuse reflectance for both front- and back-facing materials
-%% is (0.8, 0.8, 0.8, 1.0).
-%%
-%% `?GL_SPECULAR': `Params' contains four integer or floating-point values that
-%% specify the specular RGBA reflectance of the material. Integer values are mapped linearly
-%% such that the most positive representable value maps to 1.0, and the most negative representable
-%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point
-%% values are clamped. The initial specular reflectance for both front- and back-facing materials
-%% is (0, 0, 0, 1).
-%%
-%% `?GL_EMISSION': `Params' contains four integer or floating-point values that
-%% specify the RGBA emitted light intensity of the material. Integer values are mapped linearly
-%% such that the most positive representable value maps to 1.0, and the most negative representable
-%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point
-%% values are clamped. The initial emission intensity for both front- and back-facing materials
-%% is (0, 0, 0, 1).
-%%
-%% `?GL_SHININESS': `Params' is a single integer or floating-point value that specifies
-%% the RGBA specular exponent of the material. Integer and floating-point values are mapped
-%% directly. Only values in the range [0 128] are accepted. The initial specular exponent for both
-%% front- and back-facing materials is 0.
-%%
-%% `?GL_AMBIENT_AND_DIFFUSE': Equivalent to calling ``gl:material'' twice with the
-%% same parameter values, once with `?GL_AMBIENT' and once with `?GL_DIFFUSE'.
-%%
-%% `?GL_COLOR_INDEXES': `Params' contains three integer or floating-point values
-%% specifying the color indices for ambient, diffuse, and specular lighting. These three
-%% values, and `?GL_SHININESS', are the only material values used by the color index
-%% mode lighting equation. Refer to the {@link gl:lightModelf/2} reference page for a discussion
-%% of color index lighting.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMaterial.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glMaterial.xml">external</a> documentation.
-spec materialf(Face, Pname, Param) -> 'ok' when Face :: enum(),Pname :: enum(),Param :: float().
materialf(Face,Pname,Param) ->
cast(5215, <<Face:?GLenum,Pname:?GLenum,Param:?GLfloat>>).
@@ -4573,46 +2185,7 @@ materialiv(Face,Pname,Params) ->
%% ``gl:getMaterial'' returns in `Params' the value or values of parameter `Pname'
%% of material `Face' . Six parameters are defined:
%%
-%% `?GL_AMBIENT': `Params' returns four integer or floating-point values representing
-%% the ambient reflectance of the material. Integer values, when requested, are linearly
-%% mapped from the internal floating-point representation such that 1.0 maps to the most
-%% positive representable integer value, and -1.0 maps to the most negative representable
-%% integer value. If the internal value is outside the range [-1 1], the corresponding integer
-%% return value is undefined. The initial value is (0.2, 0.2, 0.2, 1.0)
-%%
-%% `?GL_DIFFUSE': `Params' returns four integer or floating-point values representing
-%% the diffuse reflectance of the material. Integer values, when requested, are linearly
-%% mapped from the internal floating-point representation such that 1.0 maps to the most
-%% positive representable integer value, and -1.0 maps to the most negative representable
-%% integer value. If the internal value is outside the range [-1 1], the corresponding integer
-%% return value is undefined. The initial value is (0.8, 0.8, 0.8, 1.0).
-%%
-%% `?GL_SPECULAR': `Params' returns four integer or floating-point values representing
-%% the specular reflectance of the material. Integer values, when requested, are linearly
-%% mapped from the internal floating-point representation such that 1.0 maps to the most
-%% positive representable integer value, and -1.0 maps to the most negative representable
-%% integer value. If the internal value is outside the range [-1 1], the corresponding integer
-%% return value is undefined. The initial value is (0, 0, 0, 1).
-%%
-%% `?GL_EMISSION': `Params' returns four integer or floating-point values representing
-%% the emitted light intensity of the material. Integer values, when requested, are linearly
-%% mapped from the internal floating-point representation such that 1.0 maps to the most
-%% positive representable integer value, and -1.0 maps to the most negative representable
-%% integer value. If the internal value is outside the range [-1 1], the corresponding integer
-%% return value is undefined. The initial value is (0, 0, 0, 1).
-%%
-%% `?GL_SHININESS': `Params' returns one integer or floating-point value representing
-%% the specular exponent of the material. Integer values, when requested, are computed by
-%% rounding the internal floating-point value to the nearest integer value. The initial value
-%% is 0.
-%%
-%% `?GL_COLOR_INDEXES': `Params' returns three integer or floating-point values
-%% representing the ambient, diffuse, and specular indices of the material. These indices
-%% are used only for color index lighting. (All the other parameters are used only for RGBA
-%% lighting.) Integer values, when requested, are computed by rounding the internal floating-point
-%% values to the nearest integer values.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMaterial.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetMaterial.xml">external</a> documentation.
-spec getMaterialfv(Face, Pname) -> {float(),float(),float(),float()} when Face :: enum(),Pname :: enum().
getMaterialfv(Face,Pname) ->
call(5219, <<Face:?GLenum,Pname:?GLenum>>).
@@ -4629,11 +2202,7 @@ getMaterialiv(Face,Pname) ->
%% is enabled, the material parameter or parameters specified by `Mode' , of the material
%% or materials specified by `Face' , track the current color at all times.
%%
-%% To enable and disable `?GL_COLOR_MATERIAL', call {@link gl:enable/1} and {@link gl:enable/1}
-%% with argument `?GL_COLOR_MATERIAL'. `?GL_COLOR_MATERIAL' is initially disabled.
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorMaterial.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glColorMaterial.xml">external</a> documentation.
-spec colorMaterial(Face, Mode) -> 'ok' when Face :: enum(),Mode :: enum().
colorMaterial(Face,Mode) ->
cast(5221, <<Face:?GLenum,Mode:?GLenum>>).
@@ -4645,17 +2214,7 @@ colorMaterial(Face,Mode) ->
%% position, and a given element is in the mth row and nth column of the pixel rectangle,
%% then pixels whose centers are in the rectangle with corners at
%%
-%% ( xr+n. xfactor, yr+m. yfactor)
-%%
-%% ( xr+(n+1). xfactor, yr+(m+1). yfactor)
-%%
-%% are candidates for replacement. Any pixel whose center lies on the bottom or left edge
-%% of this rectangular region is also modified.
-%%
-%% Pixel zoom factors are not limited to positive values. Negative zoom factors reflect
-%% the resulting image about the current raster position.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelZoom.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPixelZoom.xml">external</a> documentation.
-spec pixelZoom(Xfactor, Yfactor) -> 'ok' when Xfactor :: float(),Yfactor :: float().
pixelZoom(Xfactor,Yfactor) ->
cast(5222, <<Xfactor:?GLfloat,Yfactor:?GLfloat>>).
@@ -4669,181 +2228,7 @@ pixelZoom(Xfactor,Yfactor) ->
%% , {@link gl:compressedTexSubImage1D/7} , {@link gl:compressedTexSubImage2D/9} or {@link gl:compressedTexSubImage1D/7}
%% .
%%
-%% `Pname' is a symbolic constant indicating the parameter to be set, and `Param'
-%% is the new value. Six of the twelve storage parameters affect how pixel data is returned
-%% to client memory. They are as follows:
-%%
-%% `?GL_PACK_SWAP_BYTES': If true, byte ordering for multibyte color components, depth
-%% components, or stencil indices is reversed. That is, if a four-byte component consists
-%% of bytes b 0, b 1, b 2, b 3, it is stored in memory as b 3, b 2, b 1, b 0 if `?GL_PACK_SWAP_BYTES'
-%% is true. `?GL_PACK_SWAP_BYTES' has no effect on the memory order of components within
-%% a pixel, only on the order of bytes within components or indices. For example, the three
-%% components of a `?GL_RGB' format pixel are always stored with red first, green second,
-%% and blue third, regardless of the value of `?GL_PACK_SWAP_BYTES'.
-%%
-%% `?GL_PACK_LSB_FIRST': If true, bits are ordered within a byte from least significant
-%% to most significant; otherwise, the first bit in each byte is the most significant one.
-%%
-%% `?GL_PACK_ROW_LENGTH': If greater than 0, `?GL_PACK_ROW_LENGTH' defines the
-%% number of pixels in a row. If the first pixel of a row is placed at location p in memory,
-%% then the location of the first pixel of the next row is obtained by skipping
-%%
-%% k={n l(a/s) |(s n l)/a| s&gt;= a s&lt; a)
-%%
-%% components or indices, where n is the number of components or indices in a pixel, l
-%% is the number of pixels in a row (`?GL_PACK_ROW_LENGTH' if it is greater than 0,
-%% the width argument to the pixel routine otherwise), a is the value of `?GL_PACK_ALIGNMENT'
-%% , and s is the size, in bytes, of a single component (if a&lt; s, then it is as if a=
-%% s). In the case of 1-bit values, the location of the next row is obtained by skipping
-%%
-%% k=8 a |(n l)/(8 a)|
-%%
-%% components or indices.
-%%
-%% The word `component' in this description refers to the nonindex values red, green,
-%% blue, alpha, and depth. Storage format `?GL_RGB', for example, has three components
-%% per pixel: first red, then green, and finally blue.
-%%
-%% `?GL_PACK_IMAGE_HEIGHT': If greater than 0, `?GL_PACK_IMAGE_HEIGHT' defines
-%% the number of pixels in an image three-dimensional texture volume, where ``image'' is
-%% defined by all pixels sharing the same third dimension index. If the first pixel of a
-%% row is placed at location p in memory, then the location of the first pixel of the next
-%% row is obtained by skipping
-%%
-%% k={n l h(a/s) |(s n l h)/a| s&gt;= a s&lt; a)
-%%
-%% components or indices, where n is the number of components or indices in a pixel, l
-%% is the number of pixels in a row (`?GL_PACK_ROW_LENGTH' if it is greater than 0,
-%% the width argument to {@link gl:texImage3D/10} otherwise), h is the number of rows in
-%% a pixel image (`?GL_PACK_IMAGE_HEIGHT' if it is greater than 0, the height argument
-%% to the {@link gl:texImage3D/10} routine otherwise), a is the value of `?GL_PACK_ALIGNMENT'
-%% , and s is the size, in bytes, of a single component (if a&lt; s, then it is as if
-%% a=s).
-%%
-%% The word `component' in this description refers to the nonindex values red, green,
-%% blue, alpha, and depth. Storage format `?GL_RGB', for example, has three components
-%% per pixel: first red, then green, and finally blue.
-%%
-%% `?GL_PACK_SKIP_PIXELS', `?GL_PACK_SKIP_ROWS', and `?GL_PACK_SKIP_IMAGES'
-%%
-%% These values are provided as a convenience to the programmer; they provide no functionality
-%% that cannot be duplicated simply by incrementing the pointer passed to {@link gl:readPixels/7}
-%% . Setting `?GL_PACK_SKIP_PIXELS' to i is equivalent to incrementing the pointer
-%% by i n components or indices, where n is the number of components or indices in each
-%% pixel. Setting `?GL_PACK_SKIP_ROWS' to j is equivalent to incrementing the pointer
-%% by j m components or indices, where m is the number of components or indices per
-%% row, as just computed in the `?GL_PACK_ROW_LENGTH' section. Setting `?GL_PACK_SKIP_IMAGES'
-%% to k is equivalent to incrementing the pointer by k p, where p is the number of
-%% components or indices per image, as computed in the `?GL_PACK_IMAGE_HEIGHT' section.
-%%
-%%
-%% `?GL_PACK_ALIGNMENT': Specifies the alignment requirements for the start of each
-%% pixel row in memory. The allowable values are 1 (byte-alignment), 2 (rows aligned to even-numbered
-%% bytes), 4 (word-alignment), and 8 (rows start on double-word boundaries).
-%%
-%% The other six of the twelve storage parameters affect how pixel data is read from client
-%% memory. These values are significant for {@link gl:texImage1D/8} , {@link gl:texImage2D/9} , {@link gl:texImage3D/10}
-%% , {@link gl:texSubImage1D/7} , {@link gl:texSubImage1D/7} , and {@link gl:texSubImage1D/7}
-%%
-%% They are as follows:
-%%
-%% `?GL_UNPACK_SWAP_BYTES': If true, byte ordering for multibyte color components,
-%% depth components, or stencil indices is reversed. That is, if a four-byte component consists
-%% of bytes b 0, b 1, b 2, b 3, it is taken from memory as b 3, b 2, b 1, b 0 if `?GL_UNPACK_SWAP_BYTES'
-%% is true. `?GL_UNPACK_SWAP_BYTES' has no effect on the memory order of components
-%% within a pixel, only on the order of bytes within components or indices. For example,
-%% the three components of a `?GL_RGB' format pixel are always stored with red first,
-%% green second, and blue third, regardless of the value of `?GL_UNPACK_SWAP_BYTES'.
-%%
-%% `?GL_UNPACK_LSB_FIRST': If true, bits are ordered within a byte from least significant
-%% to most significant; otherwise, the first bit in each byte is the most significant one.
-%%
-%% `?GL_UNPACK_ROW_LENGTH': If greater than 0, `?GL_UNPACK_ROW_LENGTH' defines
-%% the number of pixels in a row. If the first pixel of a row is placed at location p in
-%% memory, then the location of the first pixel of the next row is obtained by skipping
-%%
-%% k={n l(a/s) |(s n l)/a| s&gt;= a s&lt; a)
-%%
-%% components or indices, where n is the number of components or indices in a pixel, l
-%% is the number of pixels in a row (`?GL_UNPACK_ROW_LENGTH' if it is greater than 0,
-%% the width argument to the pixel routine otherwise), a is the value of `?GL_UNPACK_ALIGNMENT'
-%% , and s is the size, in bytes, of a single component (if a&lt; s, then it is as if a=
-%% s). In the case of 1-bit values, the location of the next row is obtained by skipping
-%%
-%% k=8 a |(n l)/(8 a)|
-%%
-%% components or indices.
-%%
-%% The word `component' in this description refers to the nonindex values red, green,
-%% blue, alpha, and depth. Storage format `?GL_RGB', for example, has three components
-%% per pixel: first red, then green, and finally blue.
-%%
-%% `?GL_UNPACK_IMAGE_HEIGHT': If greater than 0, `?GL_UNPACK_IMAGE_HEIGHT' defines
-%% the number of pixels in an image of a three-dimensional texture volume. Where ``image''
-%% is defined by all pixel sharing the same third dimension index. If the first pixel of
-%% a row is placed at location p in memory, then the location of the first pixel of the
-%% next row is obtained by skipping
-%%
-%% k={n l h(a/s) |(s n l h)/a| s&gt;= a s&lt; a)
-%%
-%% components or indices, where n is the number of components or indices in a pixel, l
-%% is the number of pixels in a row (`?GL_UNPACK_ROW_LENGTH' if it is greater than 0,
-%% the width argument to {@link gl:texImage3D/10} otherwise), h is the number of rows in
-%% an image (`?GL_UNPACK_IMAGE_HEIGHT' if it is greater than 0, the height argument
-%% to {@link gl:texImage3D/10} otherwise), a is the value of `?GL_UNPACK_ALIGNMENT',
-%% and s is the size, in bytes, of a single component (if a&lt; s, then it is as if a=s).
-%%
-%%
-%% The word `component' in this description refers to the nonindex values red, green,
-%% blue, alpha, and depth. Storage format `?GL_RGB', for example, has three components
-%% per pixel: first red, then green, and finally blue.
-%%
-%% `?GL_UNPACK_SKIP_PIXELS' and `?GL_UNPACK_SKIP_ROWS'
-%%
-%% These values are provided as a convenience to the programmer; they provide no functionality
-%% that cannot be duplicated by incrementing the pointer passed to {@link gl:texImage1D/8} , {@link gl:texImage2D/9}
-%% , {@link gl:texSubImage1D/7} or {@link gl:texSubImage1D/7} . Setting `?GL_UNPACK_SKIP_PIXELS'
-%% to i is equivalent to incrementing the pointer by i n components or indices, where
-%% n is the number of components or indices in each pixel. Setting `?GL_UNPACK_SKIP_ROWS'
-%% to j is equivalent to incrementing the pointer by j k components or indices, where
-%% k is the number of components or indices per row, as just computed in the `?GL_UNPACK_ROW_LENGTH'
-%% section.
-%%
-%% `?GL_UNPACK_ALIGNMENT': Specifies the alignment requirements for the start of each
-%% pixel row in memory. The allowable values are 1 (byte-alignment), 2 (rows aligned to even-numbered
-%% bytes), 4 (word-alignment), and 8 (rows start on double-word boundaries).
-%%
-%% The following table gives the type, initial value, and range of valid values for each
-%% storage parameter that can be set with ``gl:pixelStore''.
-%%
-%% <table><tbody><tr><td> `Pname' </td><td>` Type '</td><td>` Initial Value '</td>
-%% <td>` Valid Range '</td></tr></tbody><tbody><tr><td>`?GL_PACK_SWAP_BYTES'</td><td>
-%% boolean </td><td> false </td><td> true or false </td></tr><tr><td>`?GL_PACK_LSB_FIRST'
-%% </td><td> boolean </td><td> false </td><td> true or false </td></tr><tr><td>`?GL_PACK_ROW_LENGTH'
-%% </td><td> integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_PACK_IMAGE_HEIGHT'</td>
-%% <td> integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_PACK_SKIP_ROWS'</td><td>
-%% integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_PACK_SKIP_PIXELS'</td><td> integer
-%% </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_PACK_SKIP_IMAGES'</td><td> integer </td><td>
-%% 0 </td><td>[0)</td></tr><tr><td>`?GL_PACK_ALIGNMENT'</td><td> integer </td><td> 4 </td>
-%% <td> 1, 2, 4, or 8 </td></tr><tr><td>`?GL_UNPACK_SWAP_BYTES'</td><td> boolean </td><td>
-%% false </td><td> true or false </td></tr><tr><td>`?GL_UNPACK_LSB_FIRST'</td><td>
-%% boolean </td><td> false </td><td> true or false </td></tr><tr><td>`?GL_UNPACK_ROW_LENGTH'
-%% </td><td> integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_UNPACK_IMAGE_HEIGHT'</td>
-%% <td> integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_UNPACK_SKIP_ROWS'</td><td>
-%% integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_UNPACK_SKIP_PIXELS'</td><td>
-%% integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_UNPACK_SKIP_IMAGES'</td><td>
-%% integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_UNPACK_ALIGNMENT'</td><td> integer
-%% </td><td> 4 </td><td> 1, 2, 4, or 8 </td></tr></tbody></table>
-%%
-%% ``gl:pixelStoref'' can be used to set any pixel store parameter. If the parameter type
-%% is boolean, then if `Param' is 0, the parameter is false; otherwise it is set to
-%% true. If `Pname' is a integer type parameter, `Param' is rounded to the nearest
-%% integer.
-%%
-%% Likewise, ``gl:pixelStorei'' can also be used to set any of the pixel store parameters.
-%% Boolean parameters are set to false if `Param' is 0 and true otherwise.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelStore.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPixelStore.xhtml">external</a> documentation.
-spec pixelStoref(Pname, Param) -> 'ok' when Pname :: enum(),Param :: float().
pixelStoref(Pname,Param) ->
cast(5223, <<Pname:?GLenum,Param:?GLfloat>>).
@@ -4874,134 +2259,7 @@ pixelStorei(Pname,Param) ->
%% ) control the unpacking of pixels being read from client memory and the packing of pixels
%% being written back into client memory.
%%
-%% Pixel transfer operations handle four fundamental pixel types: `color', `color index'
-%% , `depth', and `stencil'. `Color' pixels consist of four floating-point
-%% values with unspecified mantissa and exponent sizes, scaled such that 0 represents zero
-%% intensity and 1 represents full intensity. `Color indices' comprise a single fixed-point
-%% value, with unspecified precision to the right of the binary point. `Depth' pixels
-%% comprise a single floating-point value, with unspecified mantissa and exponent sizes,
-%% scaled such that 0.0 represents the minimum depth buffer value, and 1.0 represents the
-%% maximum depth buffer value. Finally, `stencil' pixels comprise a single fixed-point
-%% value, with unspecified precision to the right of the binary point.
-%%
-%% The pixel transfer operations performed on the four basic pixel types are as follows:
-%%
-%% `Color': Each of the four color components is multiplied by a scale factor, then
-%% added to a bias factor. That is, the red component is multiplied by `?GL_RED_SCALE',
-%% then added to `?GL_RED_BIAS'; the green component is multiplied by `?GL_GREEN_SCALE'
-%% , then added to `?GL_GREEN_BIAS'; the blue component is multiplied by `?GL_BLUE_SCALE'
-%% , then added to `?GL_BLUE_BIAS'; and the alpha component is multiplied by `?GL_ALPHA_SCALE'
-%% , then added to `?GL_ALPHA_BIAS'. After all four color components are scaled and
-%% biased, each is clamped to the range [0 1]. All color, scale, and bias values are specified
-%% with ``gl:pixelTransfer''.
-%%
-%% If `?GL_MAP_COLOR' is true, each color component is scaled by the size of the corresponding
-%% color-to-color map, then replaced by the contents of that map indexed by the scaled component.
-%% That is, the red component is scaled by `?GL_PIXEL_MAP_R_TO_R_SIZE', then replaced
-%% by the contents of `?GL_PIXEL_MAP_R_TO_R' indexed by itself. The green component
-%% is scaled by `?GL_PIXEL_MAP_G_TO_G_SIZE', then replaced by the contents of `?GL_PIXEL_MAP_G_TO_G'
-%% indexed by itself. The blue component is scaled by `?GL_PIXEL_MAP_B_TO_B_SIZE',
-%% then replaced by the contents of `?GL_PIXEL_MAP_B_TO_B' indexed by itself. And the
-%% alpha component is scaled by `?GL_PIXEL_MAP_A_TO_A_SIZE', then replaced by the contents
-%% of `?GL_PIXEL_MAP_A_TO_A' indexed by itself. All components taken from the maps are
-%% then clamped to the range [0 1]. `?GL_MAP_COLOR' is specified with ``gl:pixelTransfer''.
-%% The contents of the various maps are specified with {@link gl:pixelMapfv/3} .
-%%
-%% If the ARB_imaging extension is supported, each of the four color components may be scaled
-%% and biased after transformation by the color matrix. That is, the red component is multiplied
-%% by `?GL_POST_COLOR_MATRIX_RED_SCALE', then added to `?GL_POST_COLOR_MATRIX_RED_BIAS'
-%% ; the green component is multiplied by `?GL_POST_COLOR_MATRIX_GREEN_SCALE', then
-%% added to `?GL_POST_COLOR_MATRIX_GREEN_BIAS'; the blue component is multiplied by `?GL_POST_COLOR_MATRIX_BLUE_SCALE'
-%% , then added to `?GL_POST_COLOR_MATRIX_BLUE_BIAS'; and the alpha component is multiplied
-%% by `?GL_POST_COLOR_MATRIX_ALPHA_SCALE', then added to `?GL_POST_COLOR_MATRIX_ALPHA_BIAS'
-%% . After all four color components are scaled and biased, each is clamped to the range [0
-%% 1].
-%%
-%% Similarly, if the ARB_imaging extension is supported, each of the four color components
-%% may be scaled and biased after processing by the enabled convolution filter. That is,
-%% the red component is multiplied by `?GL_POST_CONVOLUTION_RED_SCALE', then added to `?GL_POST_CONVOLUTION_RED_BIAS'
-%% ; the green component is multiplied by `?GL_POST_CONVOLUTION_GREEN_SCALE', then added
-%% to `?GL_POST_CONVOLUTION_GREEN_BIAS'; the blue component is multiplied by `?GL_POST_CONVOLUTION_BLUE_SCALE'
-%% , then added to `?GL_POST_CONVOLUTION_BLUE_BIAS'; and the alpha component is multiplied
-%% by `?GL_POST_CONVOLUTION_ALPHA_SCALE', then added to `?GL_POST_CONVOLUTION_ALPHA_BIAS'
-%% . After all four color components are scaled and biased, each is clamped to the range [0
-%% 1].
-%%
-%% `Color index': Each color index is shifted left by `?GL_INDEX_SHIFT' bits;
-%% any bits beyond the number of fraction bits carried by the fixed-point index are filled
-%% with zeros. If `?GL_INDEX_SHIFT' is negative, the shift is to the right, again zero
-%% filled. Then `?GL_INDEX_OFFSET' is added to the index. `?GL_INDEX_SHIFT' and `?GL_INDEX_OFFSET'
-%% are specified with ``gl:pixelTransfer''.
-%%
-%% From this point, operation diverges depending on the required format of the resulting
-%% pixels. If the resulting pixels are to be written to a color index buffer, or if they
-%% are being read back to client memory in `?GL_COLOR_INDEX' format, the pixels continue
-%% to be treated as indices. If `?GL_MAP_COLOR' is true, each index is masked by 2 n-1
-%% , where n is `?GL_PIXEL_MAP_I_TO_I_SIZE', then replaced by the contents of `?GL_PIXEL_MAP_I_TO_I'
-%% indexed by the masked value. `?GL_MAP_COLOR' is specified with ``gl:pixelTransfer''
-%% . The contents of the index map is specified with {@link gl:pixelMapfv/3} .
-%%
-%% If the resulting pixels are to be written to an RGBA color buffer, or if they are read
-%% back to client memory in a format other than `?GL_COLOR_INDEX', the pixels are converted
-%% from indices to colors by referencing the four maps `?GL_PIXEL_MAP_I_TO_R', `?GL_PIXEL_MAP_I_TO_G'
-%% , `?GL_PIXEL_MAP_I_TO_B', and `?GL_PIXEL_MAP_I_TO_A'. Before being dereferenced,
-%% the index is masked by 2 n-1, where n is `?GL_PIXEL_MAP_I_TO_R_SIZE' for the
-%% red map, `?GL_PIXEL_MAP_I_TO_G_SIZE' for the green map, `?GL_PIXEL_MAP_I_TO_B_SIZE'
-%% for the blue map, and `?GL_PIXEL_MAP_I_TO_A_SIZE' for the alpha map. All components
-%% taken from the maps are then clamped to the range [0 1]. The contents of the four maps is
-%% specified with {@link gl:pixelMapfv/3} .
-%%
-%% `Depth': Each depth value is multiplied by `?GL_DEPTH_SCALE', added to `?GL_DEPTH_BIAS'
-%% , then clamped to the range [0 1].
-%%
-%% `Stencil': Each index is shifted `?GL_INDEX_SHIFT' bits just as a color index
-%% is, then added to `?GL_INDEX_OFFSET'. If `?GL_MAP_STENCIL' is true, each index
-%% is masked by 2 n-1, where n is `?GL_PIXEL_MAP_S_TO_S_SIZE', then replaced by
-%% the contents of `?GL_PIXEL_MAP_S_TO_S' indexed by the masked value.
-%%
-%% The following table gives the type, initial value, and range of valid values for each
-%% of the pixel transfer parameters that are set with ``gl:pixelTransfer''.
-%%
-%% <table><tbody><tr><td> `Pname' </td><td>` Type '</td><td>` Initial Value '</td>
-%% <td>` Valid Range '</td></tr></tbody><tbody><tr><td>`?GL_MAP_COLOR'</td><td>
-%% boolean </td><td> false </td><td> true/false </td></tr><tr><td>`?GL_MAP_STENCIL'</td>
-%% <td> boolean </td><td> false </td><td> true/false </td></tr><tr><td>`?GL_INDEX_SHIFT'</td>
-%% <td> integer </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_INDEX_OFFSET'</td><td> integer
-%% </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_RED_SCALE'</td><td> float </td><td> 1 </td>
-%% <td>(-)</td></tr><tr><td>`?GL_GREEN_SCALE'</td><td> float </td><td> 1 </td><td>(-)</td></tr>
-%% <tr><td>`?GL_BLUE_SCALE'</td><td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_ALPHA_SCALE'
-%% </td><td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_DEPTH_SCALE'</td><td>
-%% float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_RED_BIAS'</td><td> float </td><td>
-%% 0 </td><td>(-)</td></tr><tr><td>`?GL_GREEN_BIAS'</td><td> float </td><td> 0 </td><td>(-)</td>
-%% </tr><tr><td>`?GL_BLUE_BIAS'</td><td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_ALPHA_BIAS'
-%% </td><td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_DEPTH_BIAS'</td><td>
-%% float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_RED_SCALE'</td><td>
-%% float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_GREEN_SCALE'</td>
-%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_BLUE_SCALE'</td>
-%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_ALPHA_SCALE'</td>
-%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_RED_BIAS'</td>
-%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_GREEN_BIAS'</td>
-%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_BLUE_BIAS'</td>
-%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_ALPHA_BIAS'</td>
-%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_RED_SCALE'</td>
-%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_GREEN_SCALE'</td>
-%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_BLUE_SCALE'</td>
-%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_ALPHA_SCALE'</td>
-%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_RED_BIAS'</td>
-%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_GREEN_BIAS'</td>
-%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_BLUE_BIAS'</td>
-%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_ALPHA_BIAS'</td>
-%% <td> float </td><td> 0 </td><td>(-)</td></tr></tbody></table>
-%%
-%% ``gl:pixelTransferf'' can be used to set any pixel transfer parameter. If the parameter
-%% type is boolean, 0 implies false and any other value implies true. If `Pname' is
-%% an integer parameter, `Param' is rounded to the nearest integer.
-%%
-%% Likewise, ``gl:pixelTransferi'' can be used to set any of the pixel transfer parameters.
-%% Boolean parameters are set to false if `Param' is 0 and to true otherwise. `Param'
-%% is converted to floating point before being assigned to real-valued parameters.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelTransfer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPixelTransfer.xml">external</a> documentation.
-spec pixelTransferf(Pname, Param) -> 'ok' when Pname :: enum(),Param :: float().
pixelTransferf(Pname,Param) ->
cast(5225, <<Pname:?GLenum,Param:?GLfloat>>).
@@ -5025,72 +2283,7 @@ pixelTransferi(Pname,Param) ->
%% page, and partly in the reference pages for the pixel and texture image commands. Only
%% the specification of the maps is described in this reference page.
%%
-%% `Map' is a symbolic map name, indicating one of ten maps to set. `Mapsize' specifies
-%% the number of entries in the map, and `Values' is a pointer to an array of `Mapsize'
-%% map values.
-%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a pixel transfer map is specified, `Values' is
-%% treated as a byte offset into the buffer object's data store.
-%%
-%% The ten maps are as follows:
-%%
-%% `?GL_PIXEL_MAP_I_TO_I': Maps color indices to color indices.
-%%
-%% `?GL_PIXEL_MAP_S_TO_S': Maps stencil indices to stencil indices.
-%%
-%% `?GL_PIXEL_MAP_I_TO_R': Maps color indices to red components.
-%%
-%% `?GL_PIXEL_MAP_I_TO_G': Maps color indices to green components.
-%%
-%% `?GL_PIXEL_MAP_I_TO_B': Maps color indices to blue components.
-%%
-%% `?GL_PIXEL_MAP_I_TO_A': Maps color indices to alpha components.
-%%
-%% `?GL_PIXEL_MAP_R_TO_R': Maps red components to red components.
-%%
-%% `?GL_PIXEL_MAP_G_TO_G': Maps green components to green components.
-%%
-%% `?GL_PIXEL_MAP_B_TO_B': Maps blue components to blue components.
-%%
-%% `?GL_PIXEL_MAP_A_TO_A': Maps alpha components to alpha components.
-%%
-%% The entries in a map can be specified as single-precision floating-point numbers, unsigned
-%% short integers, or unsigned int integers. Maps that store color component values (all
-%% but `?GL_PIXEL_MAP_I_TO_I' and `?GL_PIXEL_MAP_S_TO_S') retain their values in
-%% floating-point format, with unspecified mantissa and exponent sizes. Floating-point values
-%% specified by ``gl:pixelMapfv'' are converted directly to the internal floating-point
-%% format of these maps, then clamped to the range [0,1]. Unsigned integer values specified
-%% by ``gl:pixelMapusv'' and ``gl:pixelMapuiv'' are converted linearly such that the
-%% largest representable integer maps to 1.0, and 0 maps to 0.0.
-%%
-%% Maps that store indices, `?GL_PIXEL_MAP_I_TO_I' and `?GL_PIXEL_MAP_S_TO_S',
-%% retain their values in fixed-point format, with an unspecified number of bits to the right
-%% of the binary point. Floating-point values specified by ``gl:pixelMapfv'' are converted
-%% directly to the internal fixed-point format of these maps. Unsigned integer values specified
-%% by ``gl:pixelMapusv'' and ``gl:pixelMapuiv'' specify integer values, with all 0's
-%% to the right of the binary point.
-%%
-%% The following table shows the initial sizes and values for each of the maps. Maps that
-%% are indexed by either color or stencil indices must have `Mapsize' = 2 n for some
-%% n or the results are undefined. The maximum allowable size for each map depends on the
-%% implementation and can be determined by calling {@link gl:getBooleanv/1} with argument `?GL_MAX_PIXEL_MAP_TABLE'
-%% . The single maximum applies to all maps; it is at least 32. <table><tbody><tr><td> `Map'
-%% </td><td>` Lookup Index '</td><td>` Lookup Value '</td><td>` Initial Size '</td>
-%% <td>` Initial Value '</td></tr></tbody><tbody><tr><td>`?GL_PIXEL_MAP_I_TO_I'</td>
-%% <td> color index </td><td> color index </td><td> 1 </td><td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_S_TO_S'
-%% </td><td> stencil index </td><td> stencil index </td><td> 1 </td><td> 0 </td></tr><tr><td>
-%% `?GL_PIXEL_MAP_I_TO_R'</td><td> color index </td><td> R </td><td> 1 </td><td> 0 </td>
-%% </tr><tr><td>`?GL_PIXEL_MAP_I_TO_G'</td><td> color index </td><td> G </td><td> 1 </td>
-%% <td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_I_TO_B'</td><td> color index </td><td> B </td>
-%% <td> 1 </td><td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_I_TO_A'</td><td> color index </td>
-%% <td> A </td><td> 1 </td><td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_R_TO_R'</td><td> R </td>
-%% <td> R </td><td> 1 </td><td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_G_TO_G'</td><td> G </td>
-%% <td> G </td><td> 1 </td><td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_B_TO_B'</td><td> B </td>
-%% <td> B </td><td> 1 </td><td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_A_TO_A'</td><td> A </td>
-%% <td> A </td><td> 1 </td><td> 0 </td></tr></tbody></table>
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelMap.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPixelMap.xml">external</a> documentation.
-spec pixelMapfv(Map, Mapsize, Values) -> 'ok' when Map :: enum(),Mapsize :: integer(),Values :: binary().
pixelMapfv(Map,Mapsize,Values) ->
send_bin(Values),
@@ -5121,19 +2314,7 @@ pixelMapusv(Map,Mapsize,Values) ->
%% , and {@link gl:copyTexSubImage3D/9} . to map color indices, stencil indices, color components,
%% and depth components to other values.
%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a pixel map is requested, `Data' is treated as
-%% a byte offset into the buffer object's data store.
-%%
-%% Unsigned integer values, if requested, are linearly mapped from the internal fixed or
-%% floating-point representation such that 1.0 maps to the largest representable integer
-%% value, and 0.0 maps to 0. Return unsigned integer values are undefined if the map value
-%% was not in the range [0,1].
-%%
-%% To determine the required size of `Map' , call {@link gl:getBooleanv/1} with the appropriate
-%% symbolic constant.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetPixelMap.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetPixelMap.xml">external</a> documentation.
-spec getPixelMapfv(Map, Values) -> 'ok' when Map :: enum(),Values :: mem().
getPixelMapfv(Map,Values) ->
send_bin(Values),
@@ -5160,42 +2341,7 @@ getPixelMapusv(Map,Values) ->
%% using the current raster color or index. Frame buffer pixels corresponding to 0's in the
%% bitmap are not modified.
%%
-%% ``gl:bitmap'' takes seven arguments. The first pair specifies the width and height of
-%% the bitmap image. The second pair specifies the location of the bitmap origin relative
-%% to the lower left corner of the bitmap image. The third pair of arguments specifies `x'
-%% and `y' offsets to be added to the current raster position after the bitmap has
-%% been drawn. The final argument is a pointer to the bitmap image itself.
-%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a bitmap image is specified, `Bitmap' is treated
-%% as a byte offset into the buffer object's data store.
-%%
-%% The bitmap image is interpreted like image data for the {@link gl:drawPixels/5} command,
-%% with `Width' and `Height' corresponding to the width and height arguments of
-%% that command, and with `type' set to `?GL_BITMAP' and `format' set to `?GL_COLOR_INDEX'
-%% . Modes specified using {@link gl:pixelStoref/2} affect the interpretation of bitmap image
-%% data; modes specified using {@link gl:pixelTransferf/2} do not.
-%%
-%% If the current raster position is invalid, ``gl:bitmap'' is ignored. Otherwise, the
-%% lower left corner of the bitmap image is positioned at the window coordinates
-%%
-%% x w=|x r-x o|
-%%
-%% y w=|y r-y o|
-%%
-%% where (x r y r) is the raster position and (x o y o) is the bitmap origin. Fragments are then generated
-%% for each pixel corresponding to a 1 (one) in the bitmap image. These fragments are generated
-%% using the current raster `z' coordinate, color or color index, and current raster
-%% texture coordinates. They are then treated just as if they had been generated by a point,
-%% line, or polygon, including texture mapping, fogging, and all per-fragment operations
-%% such as alpha and depth testing.
-%%
-%% After the bitmap has been drawn, the `x' and `y' coordinates of the current
-%% raster position are offset by `Xmove' and `Ymove' . No change is made to the `z'
-%% coordinate of the current raster position, or to the current raster color, texture coordinates,
-%% or index.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBitmap.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glBitmap.xml">external</a> documentation.
-spec bitmap(Width, Height, Xorig, Yorig, Xmove, Ymove, Bitmap) -> 'ok' when Width :: integer(),Height :: integer(),Xorig :: float(),Yorig :: float(),Xmove :: float(),Ymove :: float(),Bitmap :: offset()|mem().
bitmap(Width,Height,Xorig,Yorig,Xmove,Ymove,Bitmap) when is_integer(Bitmap) ->
cast(5233, <<Width:?GLsizei,Height:?GLsizei,Xorig:?GLfloat,Yorig:?GLfloat,Xmove:?GLfloat,Ymove:?GLfloat,Bitmap:?GLuint>>);
@@ -5212,91 +2358,7 @@ bitmap(Width,Height,Xorig,Yorig,Xmove,Ymove,Bitmap) ->
%% This reference page describes the effects on ``gl:readPixels'' of most, but not all
%% of the parameters specified by these three commands.
%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a block of pixels is requested, `Data' is treated
-%% as a byte offset into the buffer object's data store rather than a pointer to client memory.
-%%
-%%
-%% ``gl:readPixels'' returns values from each pixel with lower left corner at (x+i y+j) for 0&lt;=
-%% i&lt; width and 0&lt;= j&lt; height. This pixel is said to be the ith pixel in the
-%% jth row. Pixels are returned in row order from the lowest to the highest row, left to
-%% right in each row.
-%%
-%% `Format' specifies the format for the returned pixel values; accepted values are:
-%%
-%% `?GL_STENCIL_INDEX': Stencil values are read from the stencil buffer. Each index
-%% is converted to fixed point, shifted left or right depending on the value and sign of `?GL_INDEX_SHIFT'
-%% , and added to `?GL_INDEX_OFFSET'. If `?GL_MAP_STENCIL' is `?GL_TRUE',
-%% indices are replaced by their mappings in the table `?GL_PIXEL_MAP_S_TO_S'.
-%%
-%% `?GL_DEPTH_COMPONENT': Depth values are read from the depth buffer. Each component
-%% is converted to floating point such that the minimum depth value maps to 0 and the maximum
-%% value maps to 1. Each component is then multiplied by `?GL_DEPTH_SCALE', added to `?GL_DEPTH_BIAS'
-%% , and finally clamped to the range [0 1].
-%%
-%% `?GL_DEPTH_STENCIL': Values are taken from both the depth and stencil buffers. The `Type'
-%% parameter must be `?GL_UNSIGNED_INT_24_8' or `?GL_FLOAT_32_UNSIGNED_INT_24_8_REV'
-%% .
-%%
-%% `?GL_RED'
-%%
-%% `?GL_GREEN'
-%%
-%% `?GL_BLUE'
-%%
-%% `?GL_RGB'
-%%
-%% `?GL_BGR'
-%%
-%% `?GL_RGBA'
-%%
-%% `?GL_BGRA': Finally, the indices or components are converted to the proper format,
-%% as specified by `Type' . If `Format' is `?GL_STENCIL_INDEX' and `Type'
-%% is not `?GL_FLOAT', each index is masked with the mask value given in the following
-%% table. If `Type' is `?GL_FLOAT', then each integer index is converted to single-precision
-%% floating-point format.
-%%
-%% If `Format' is `?GL_RED', `?GL_GREEN', `?GL_BLUE', `?GL_RGB', `?GL_BGR'
-%% , `?GL_RGBA', or `?GL_BGRA' and `Type' is not `?GL_FLOAT', each component
-%% is multiplied by the multiplier shown in the following table. If type is `?GL_FLOAT',
-%% then each component is passed as is (or converted to the client's single-precision floating-point
-%% format if it is different from the one used by the GL).
-%%
-%% <table><tbody><tr><td> `Type' </td><td>` Index Mask '</td><td>` Component Conversion '
-%% </td></tr></tbody><tbody><tr><td>`?GL_UNSIGNED_BYTE'</td><td> 2 8-1</td><td>(2 8-1) c</td></tr>
-%% <tr><td>`?GL_BYTE'</td><td> 2 7-1</td><td>((2 8-1) c-1)/2</td></tr><tr><td>`?GL_UNSIGNED_SHORT'
-%% </td><td> 2 16-1</td><td>(2 16-1) c</td></tr><tr><td>`?GL_SHORT'</td><td> 2 15-1</td><td>((2
-%% 16-1)
-%% c-1)/2</td>
-%% </tr><tr><td>`?GL_UNSIGNED_INT'</td><td> 2 32-1</td><td>(2 32-1) c</td></tr><tr><td>`?GL_INT'
-%% </td><td> 2 31-1</td><td>((2 32-1) c-1)/2</td></tr><tr><td>`?GL_HALF_FLOAT'</td><td> none </td><td>
-%% c</td></tr><tr><td>`?GL_FLOAT'</td><td> none </td><td> c</td></tr><tr><td>`?GL_UNSIGNED_BYTE_3_3_2'
-%% </td><td> 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_BYTE_2_3_3_REV'</td><td>
-%% 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_SHORT_5_6_5'</td><td> 2 N-1</td><td>
-%% (2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_SHORT_5_6_5_REV'</td><td> 2 N-1</td><td>(2 N-1) c</td></tr>
-%% <tr><td>`?GL_UNSIGNED_SHORT_4_4_4_4'</td><td> 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_SHORT_4_4_4_4_REV'
-%% </td><td> 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_SHORT_5_5_5_1'</td><td> 2
-%% N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_SHORT_1_5_5_5_REV'</td><td> 2 N-1</td>
-%% <td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_INT_8_8_8_8'</td><td> 2 N-1</td><td>(2 N-1) c</td></tr>
-%% <tr><td>`?GL_UNSIGNED_INT_8_8_8_8_REV'</td><td> 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_INT_10_10_10_2'
-%% </td><td> 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_INT_2_10_10_10_REV'</td><td>
-%% 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_INT_24_8'</td><td> 2 N-1</td><td>(2
-%% N-1)
-%% c</td></tr><tr><td>`?GL_UNSIGNED_INT_10F_11F_11F_REV'</td><td> -- </td><td> Special </td>
-%% </tr><tr><td>`?GL_UNSIGNED_INT_5_9_9_9_REV'</td><td> -- </td><td> Special </td></tr><tr>
-%% <td>`?GL_FLOAT_32_UNSIGNED_INT_24_8_REV'</td><td> none </td><td> c (Depth Only) </td>
-%% </tr></tbody></table>
-%%
-%% Return values are placed in memory as follows. If `Format' is `?GL_STENCIL_INDEX'
-%% , `?GL_DEPTH_COMPONENT', `?GL_RED', `?GL_GREEN', or `?GL_BLUE', a
-%% single value is returned and the data for the ith pixel in the jth row is placed in
-%% location (j) width+i. `?GL_RGB' and `?GL_BGR' return three values, `?GL_RGBA'
-%% and `?GL_BGRA' return four values for each pixel, with all values corresponding
-%% to a single pixel occupying contiguous space in `Data' . Storage parameters set by {@link gl:pixelStoref/2}
-%% , such as `?GL_PACK_LSB_FIRST' and `?GL_PACK_SWAP_BYTES', affect the way that
-%% data is written into memory. See {@link gl:pixelStoref/2} for a description.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glReadPixels.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glReadPixels.xhtml">external</a> documentation.
-spec readPixels(X, Y, Width, Height, Format, Type, Pixels) -> 'ok' when X :: integer(),Y :: integer(),Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Pixels :: mem().
readPixels(X,Y,Width,Height,Format,Type,Pixels) ->
send_bin(Pixels),
@@ -5311,237 +2373,7 @@ readPixels(X,Y,Width,Height,Format,Type,Pixels) ->
%% position is valid, and {@link gl:getBooleanv/1} with argument `?GL_CURRENT_RASTER_POSITION'
%% to query the raster position.
%%
-%% Several parameters define the encoding of pixel data in memory and control the processing
-%% of the pixel data before it is placed in the frame buffer. These parameters are set with
-%% four commands: {@link gl:pixelStoref/2} , {@link gl:pixelTransferf/2} , {@link gl:pixelMapfv/3} ,
-%% and {@link gl:pixelZoom/2} . This reference page describes the effects on ``gl:drawPixels''
-%% of many, but not all, of the parameters specified by these four commands.
-%%
-%% Data is read from `Data' as a sequence of signed or unsigned bytes, signed or unsigned
-%% shorts, signed or unsigned integers, or single-precision floating-point values, depending
-%% on `Type' . When `Type' is one of `?GL_UNSIGNED_BYTE', `?GL_BYTE', `?GL_UNSIGNED_SHORT'
-%% , `?GL_SHORT', `?GL_UNSIGNED_INT', `?GL_INT', or `?GL_FLOAT' each
-%% of these bytes, shorts, integers, or floating-point values is interpreted as one color
-%% or depth component, or one index, depending on `Format' . When `Type' is one of `?GL_UNSIGNED_BYTE_3_3_2'
-%% , `?GL_UNSIGNED_SHORT_5_6_5', `?GL_UNSIGNED_SHORT_4_4_4_4', `?GL_UNSIGNED_SHORT_5_5_5_1'
-%% , `?GL_UNSIGNED_INT_8_8_8_8', or `?GL_UNSIGNED_INT_10_10_10_2', each unsigned
-%% value is interpreted as containing all the components for a single pixel, with the color
-%% components arranged according to `Format' . When `Type' is one of `?GL_UNSIGNED_BYTE_2_3_3_REV'
-%% , `?GL_UNSIGNED_SHORT_5_6_5_REV', `?GL_UNSIGNED_SHORT_4_4_4_4_REV', `?GL_UNSIGNED_SHORT_1_5_5_5_REV'
-%% , `?GL_UNSIGNED_INT_8_8_8_8_REV', or `?GL_UNSIGNED_INT_2_10_10_10_REV', each
-%% unsigned value is interpreted as containing all color components, specified by `Format'
-%% , for a single pixel in a reversed order. Indices are always treated individually. Color
-%% components are treated as groups of one, two, three, or four values, again based on `Format'
-%% . Both individual indices and groups of components are referred to as pixels. If `Type'
-%% is `?GL_BITMAP', the data must be unsigned bytes, and `Format' must be either `?GL_COLOR_INDEX'
-%% or `?GL_STENCIL_INDEX'. Each unsigned byte is treated as eight 1-bit pixels, with
-%% bit ordering determined by `?GL_UNPACK_LSB_FIRST' (see {@link gl:pixelStoref/2} ).
-%%
-%% width×height pixels are read from memory, starting at location `Data' . By default,
-%% these pixels are taken from adjacent memory locations, except that after all `Width'
-%% pixels are read, the read pointer is advanced to the next four-byte boundary. The four-byte
-%% row alignment is specified by {@link gl:pixelStoref/2} with argument `?GL_UNPACK_ALIGNMENT'
-%% , and it can be set to one, two, four, or eight bytes. Other pixel store parameters specify
-%% different read pointer advancements, both before the first pixel is read and after all `Width'
-%% pixels are read. See the {@link gl:pixelStoref/2} reference page for details on these options.
-%%
-%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a block of pixels is specified, `Data' is treated
-%% as a byte offset into the buffer object's data store.
-%%
-%% The width×height pixels that are read from memory are each operated on in the same
-%% way, based on the values of several parameters specified by {@link gl:pixelTransferf/2}
-%% and {@link gl:pixelMapfv/3} . The details of these operations, as well as the target buffer
-%% into which the pixels are drawn, are specific to the format of the pixels, as specified
-%% by `Format' . `Format' can assume one of 13 symbolic values:
-%%
-%% `?GL_COLOR_INDEX': Each pixel is a single value, a color index. It is converted
-%% to fixed-point format, with an unspecified number of bits to the right of the binary point,
-%% regardless of the memory data type. Floating-point values convert to true fixed-point
-%% values. Signed and unsigned integer data is converted with all fraction bits set to 0.
-%% Bitmap data convert to either 0 or 1.
-%%
-%% Each fixed-point index is then shifted left by `?GL_INDEX_SHIFT' bits and added to `?GL_INDEX_OFFSET'
-%% . If `?GL_INDEX_SHIFT' is negative, the shift is to the right. In either case, zero
-%% bits fill otherwise unspecified bit locations in the result.
-%%
-%% If the GL is in RGBA mode, the resulting index is converted to an RGBA pixel with the
-%% help of the `?GL_PIXEL_MAP_I_TO_R', `?GL_PIXEL_MAP_I_TO_G', `?GL_PIXEL_MAP_I_TO_B'
-%% , and `?GL_PIXEL_MAP_I_TO_A' tables. If the GL is in color index mode, and if `?GL_MAP_COLOR'
-%% is true, the index is replaced with the value that it references in lookup table `?GL_PIXEL_MAP_I_TO_I'
-%% . Whether the lookup replacement of the index is done or not, the integer part of the
-%% index is then ANDed with 2 b-1, where b is the number of bits in a color index buffer.
-%%
-%%
-%% The GL then converts the resulting indices or RGBA colors to fragments by attaching the
-%% current raster position `z' coordinate and texture coordinates to each pixel, then
-%% assigning x and y window coordinates to the nth fragment such that x n=x r+n% width
-%%
-%%
-%% y n=y r+|n/width|
-%%
-%% where (x r y r) is the current raster position. These pixel fragments are then treated just like
-%% the fragments generated by rasterizing points, lines, or polygons. Texture mapping, fog,
-%% and all the fragment operations are applied before the fragments are written to the frame
-%% buffer.
-%%
-%% `?GL_STENCIL_INDEX': Each pixel is a single value, a stencil index. It is converted
-%% to fixed-point format, with an unspecified number of bits to the right of the binary point,
-%% regardless of the memory data type. Floating-point values convert to true fixed-point
-%% values. Signed and unsigned integer data is converted with all fraction bits set to 0.
-%% Bitmap data convert to either 0 or 1.
-%%
-%% Each fixed-point index is then shifted left by `?GL_INDEX_SHIFT' bits, and added
-%% to `?GL_INDEX_OFFSET'. If `?GL_INDEX_SHIFT' is negative, the shift is to the
-%% right. In either case, zero bits fill otherwise unspecified bit locations in the result.
-%% If `?GL_MAP_STENCIL' is true, the index is replaced with the value that it references
-%% in lookup table `?GL_PIXEL_MAP_S_TO_S'. Whether the lookup replacement of the index
-%% is done or not, the integer part of the index is then ANDed with 2 b-1, where b is
-%% the number of bits in the stencil buffer. The resulting stencil indices are then written
-%% to the stencil buffer such that the nth index is written to location
-%%
-%% x n=x r+n% width
-%%
-%% y n=y r+|n/width|
-%%
-%% where (x r y r) is the current raster position. Only the pixel ownership test, the scissor test,
-%% and the stencil writemask affect these write operations.
-%%
-%% `?GL_DEPTH_COMPONENT': Each pixel is a single-depth component. Floating-point data
-%% is converted directly to an internal floating-point format with unspecified precision.
-%% Signed integer data is mapped linearly to the internal floating-point format such that
-%% the most positive representable integer value maps to 1.0, and the most negative representable
-%% value maps to -1.0. Unsigned integer data is mapped similarly: the largest integer value
-%% maps to 1.0, and 0 maps to 0.0. The resulting floating-point depth value is then multiplied
-%% by `?GL_DEPTH_SCALE' and added to `?GL_DEPTH_BIAS'. The result is clamped to
-%% the range [0 1].
-%%
-%% The GL then converts the resulting depth components to fragments by attaching the current
-%% raster position color or color index and texture coordinates to each pixel, then assigning
-%% x and y window coordinates to the nth fragment such that
-%%
-%% x n=x r+n% width
-%%
-%% y n=y r+|n/width|
-%%
-%% where (x r y r) is the current raster position. These pixel fragments are then treated just like
-%% the fragments generated by rasterizing points, lines, or polygons. Texture mapping, fog,
-%% and all the fragment operations are applied before the fragments are written to the frame
-%% buffer.
-%%
-%% `?GL_RGBA'
-%%
-%% `?GL_BGRA': Each pixel is a four-component group: For `?GL_RGBA', the red component
-%% is first, followed by green, followed by blue, followed by alpha; for `?GL_BGRA'
-%% the order is blue, green, red and then alpha. Floating-point values are converted directly
-%% to an internal floating-point format with unspecified precision. Signed integer values
-%% are mapped linearly to the internal floating-point format such that the most positive
-%% representable integer value maps to 1.0, and the most negative representable value maps
-%% to -1.0. (Note that this mapping does not convert 0 precisely to 0.0.) Unsigned integer
-%% data is mapped similarly: The largest integer value maps to 1.0, and 0 maps to 0.0. The
-%% resulting floating-point color values are then multiplied by `?GL_c_SCALE' and added
-%% to `?GL_c_BIAS', where `c' is RED, GREEN, BLUE, and ALPHA for the respective
-%% color components. The results are clamped to the range [0 1].
-%%
-%% If `?GL_MAP_COLOR' is true, each color component is scaled by the size of lookup
-%% table `?GL_PIXEL_MAP_c_TO_c', then replaced by the value that it references in that
-%% table. `c' is R, G, B, or A respectively.
-%%
-%% The GL then converts the resulting RGBA colors to fragments by attaching the current
-%% raster position `z' coordinate and texture coordinates to each pixel, then assigning
-%% x and y window coordinates to the nth fragment such that
-%%
-%% x n=x r+n% width
-%%
-%% y n=y r+|n/width|
-%%
-%% where (x r y r) is the current raster position. These pixel fragments are then treated just like
-%% the fragments generated by rasterizing points, lines, or polygons. Texture mapping, fog,
-%% and all the fragment operations are applied before the fragments are written to the frame
-%% buffer.
-%%
-%% `?GL_RED': Each pixel is a single red component. This component is converted to
-%% the internal floating-point format in the same way the red component of an RGBA pixel
-%% is. It is then converted to an RGBA pixel with green and blue set to 0, and alpha set
-%% to 1. After this conversion, the pixel is treated as if it had been read as an RGBA pixel.
-%%
-%%
-%% `?GL_GREEN': Each pixel is a single green component. This component is converted
-%% to the internal floating-point format in the same way the green component of an RGBA pixel
-%% is. It is then converted to an RGBA pixel with red and blue set to 0, and alpha set to
-%% 1. After this conversion, the pixel is treated as if it had been read as an RGBA pixel.
-%%
-%% `?GL_BLUE': Each pixel is a single blue component. This component is converted to
-%% the internal floating-point format in the same way the blue component of an RGBA pixel
-%% is. It is then converted to an RGBA pixel with red and green set to 0, and alpha set to
-%% 1. After this conversion, the pixel is treated as if it had been read as an RGBA pixel.
-%%
-%% `?GL_ALPHA': Each pixel is a single alpha component. This component is converted
-%% to the internal floating-point format in the same way the alpha component of an RGBA pixel
-%% is. It is then converted to an RGBA pixel with red, green, and blue set to 0. After this
-%% conversion, the pixel is treated as if it had been read as an RGBA pixel.
-%%
-%% `?GL_RGB'
-%%
-%% `?GL_BGR': Each pixel is a three-component group: red first, followed by green,
-%% followed by blue; for `?GL_BGR', the first component is blue, followed by green and
-%% then red. Each component is converted to the internal floating-point format in the same
-%% way the red, green, and blue components of an RGBA pixel are. The color triple is converted
-%% to an RGBA pixel with alpha set to 1. After this conversion, the pixel is treated as if
-%% it had been read as an RGBA pixel.
-%%
-%% `?GL_LUMINANCE': Each pixel is a single luminance component. This component is converted
-%% to the internal floating-point format in the same way the red component of an RGBA pixel
-%% is. It is then converted to an RGBA pixel with red, green, and blue set to the converted
-%% luminance value, and alpha set to 1. After this conversion, the pixel is treated as if
-%% it had been read as an RGBA pixel.
-%%
-%% `?GL_LUMINANCE_ALPHA': Each pixel is a two-component group: luminance first, followed
-%% by alpha. The two components are converted to the internal floating-point format in the
-%% same way the red component of an RGBA pixel is. They are then converted to an RGBA pixel
-%% with red, green, and blue set to the converted luminance value, and alpha set to the converted
-%% alpha value. After this conversion, the pixel is treated as if it had been read as an
-%% RGBA pixel.
-%%
-%% The following table summarizes the meaning of the valid constants for the `type'
-%% parameter:
-%%
-%% <table><tbody><tr><td>` Type '</td><td>` Corresponding Type '</td></tr></tbody><tbody>
-%% <tr><td>`?GL_UNSIGNED_BYTE'</td><td> unsigned 8-bit integer </td></tr><tr><td>`?GL_BYTE'
-%% </td><td> signed 8-bit integer </td></tr><tr><td>`?GL_BITMAP'</td><td> single bits
-%% in unsigned 8-bit integers </td></tr><tr><td>`?GL_UNSIGNED_SHORT'</td><td> unsigned
-%% 16-bit integer </td></tr><tr><td>`?GL_SHORT'</td><td> signed 16-bit integer </td></tr>
-%% <tr><td>`?GL_UNSIGNED_INT'</td><td> unsigned 32-bit integer </td></tr><tr><td>`?GL_INT'
-%% </td><td> 32-bit integer </td></tr><tr><td>`?GL_FLOAT'</td><td> single-precision
-%% floating-point </td></tr><tr><td>`?GL_UNSIGNED_BYTE_3_3_2'</td><td> unsigned 8-bit
-%% integer </td></tr><tr><td>`?GL_UNSIGNED_BYTE_2_3_3_REV'</td><td> unsigned 8-bit
-%% integer with reversed component ordering </td></tr><tr><td>`?GL_UNSIGNED_SHORT_5_6_5'</td>
-%% <td> unsigned 16-bit integer </td></tr><tr><td>`?GL_UNSIGNED_SHORT_5_6_5_REV'</td><td>
-%% unsigned 16-bit integer with reversed component ordering </td></tr><tr><td>`?GL_UNSIGNED_SHORT_4_4_4_4'
-%% </td><td> unsigned 16-bit integer </td></tr><tr><td>`?GL_UNSIGNED_SHORT_4_4_4_4_REV'</td>
-%% <td> unsigned 16-bit integer with reversed component ordering </td></tr><tr><td>`?GL_UNSIGNED_SHORT_5_5_5_1'
-%% </td><td> unsigned 16-bit integer </td></tr><tr><td>`?GL_UNSIGNED_SHORT_1_5_5_5_REV'</td>
-%% <td> unsigned 16-bit integer with reversed component ordering </td></tr><tr><td>`?GL_UNSIGNED_INT_8_8_8_8'
-%% </td><td> unsigned 32-bit integer </td></tr><tr><td>`?GL_UNSIGNED_INT_8_8_8_8_REV'</td>
-%% <td> unsigned 32-bit integer with reversed component ordering </td></tr><tr><td>`?GL_UNSIGNED_INT_10_10_10_2'
-%% </td><td> unsigned 32-bit integer </td></tr><tr><td>`?GL_UNSIGNED_INT_2_10_10_10_REV'</td>
-%% <td> unsigned 32-bit integer with reversed component ordering </td></tr></tbody></table>
-%%
-%% The rasterization described so far assumes pixel zoom factors of 1. If {@link gl:pixelZoom/2}
-%% is used to change the x and y pixel zoom factors, pixels are converted to fragments
-%% as follows. If (x r y r) is the current raster position, and a given pixel is in the nth column
-%% and mth row of the pixel rectangle, then fragments are generated for pixels whose centers
-%% are in the rectangle with corners at
-%%
-%% (x r+(zoom x) n y r+(zoom y) m)
-%%
-%% (x r+(zoom x)(n+1) y r+(zoom y)(m+1))
-%%
-%% where zoom x is the value of `?GL_ZOOM_X' and zoom y is the value of `?GL_ZOOM_Y'
-%% .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawPixels.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glDrawPixels.xml">external</a> documentation.
-spec drawPixels(Width, Height, Format, Type, Pixels) -> 'ok' when Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem().
drawPixels(Width,Height,Format,Type,Pixels) when is_integer(Pixels) ->
cast(5236, <<Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
@@ -5557,98 +2389,7 @@ drawPixels(Width,Height,Format,Type,Pixels) ->
%% window. Results of copies from outside the window, or from regions of the window that
%% are not exposed, are hardware dependent and undefined.
%%
-%% `X' and `Y' specify the window coordinates of the lower left corner of the rectangular
-%% region to be copied. `Width' and `Height' specify the dimensions of the rectangular
-%% region to be copied. Both `Width' and `Height' must not be negative.
-%%
-%% Several parameters control the processing of the pixel data while it is being copied.
-%% These parameters are set with three commands: {@link gl:pixelTransferf/2} , {@link gl:pixelMapfv/3}
-%% , and {@link gl:pixelZoom/2} . This reference page describes the effects on ``gl:copyPixels''
-%% of most, but not all, of the parameters specified by these three commands.
-%%
-%% ``gl:copyPixels'' copies values from each pixel with the lower left-hand corner at (x+i
-%% y+j)
-%% for 0&lt;= i&lt; width and 0&lt;= j&lt; height. This pixel is said to be the ith
-%% pixel in the jth row. Pixels are copied in row order from the lowest to the highest
-%% row, left to right in each row.
-%%
-%% `Type' specifies whether color, depth, or stencil data is to be copied. The details
-%% of the transfer for each data type are as follows:
-%%
-%% `?GL_COLOR': Indices or RGBA colors are read from the buffer currently specified
-%% as the read source buffer (see {@link gl:readBuffer/1} ). If the GL is in color index mode,
-%% each index that is read from this buffer is converted to a fixed-point format with an
-%% unspecified number of bits to the right of the binary point. Each index is then shifted
-%% left by `?GL_INDEX_SHIFT' bits, and added to `?GL_INDEX_OFFSET'. If `?GL_INDEX_SHIFT'
-%% is negative, the shift is to the right. In either case, zero bits fill otherwise unspecified
-%% bit locations in the result. If `?GL_MAP_COLOR' is true, the index is replaced with
-%% the value that it references in lookup table `?GL_PIXEL_MAP_I_TO_I'. Whether the
-%% lookup replacement of the index is done or not, the integer part of the index is then
-%% ANDed with 2 b-1, where b is the number of bits in a color index buffer.
-%%
-%% If the GL is in RGBA mode, the red, green, blue, and alpha components of each pixel that
-%% is read are converted to an internal floating-point format with unspecified precision.
-%% The conversion maps the largest representable component value to 1.0, and component value
-%% 0 to 0.0. The resulting floating-point color values are then multiplied by `?GL_c_SCALE'
-%% and added to `?GL_c_BIAS', where `c' is RED, GREEN, BLUE, and ALPHA for the
-%% respective color components. The results are clamped to the range [0,1]. If `?GL_MAP_COLOR'
-%% is true, each color component is scaled by the size of lookup table `?GL_PIXEL_MAP_c_TO_c'
-%% , then replaced by the value that it references in that table. `c' is R, G, B, or
-%% A.
-%%
-%% If the ARB_imaging extension is supported, the color values may be additionally processed
-%% by color-table lookups, color-matrix transformations, and convolution filters.
-%%
-%% The GL then converts the resulting indices or RGBA colors to fragments by attaching the
-%% current raster position `z' coordinate and texture coordinates to each pixel, then
-%% assigning window coordinates (x r+i y r+j), where (x r y r) is the current raster position, and the pixel was
-%% the ith pixel in the jth row. These pixel fragments are then treated just like the
-%% fragments generated by rasterizing points, lines, or polygons. Texture mapping, fog, and
-%% all the fragment operations are applied before the fragments are written to the frame
-%% buffer.
-%%
-%% `?GL_DEPTH': Depth values are read from the depth buffer and converted directly
-%% to an internal floating-point format with unspecified precision. The resulting floating-point
-%% depth value is then multiplied by `?GL_DEPTH_SCALE' and added to `?GL_DEPTH_BIAS'
-%% . The result is clamped to the range [0,1].
-%%
-%% The GL then converts the resulting depth components to fragments by attaching the current
-%% raster position color or color index and texture coordinates to each pixel, then assigning
-%% window coordinates (x r+i y r+j), where (x r y r) is the current raster position, and the pixel was the ith
-%% pixel in the jth row. These pixel fragments are then treated just like the fragments
-%% generated by rasterizing points, lines, or polygons. Texture mapping, fog, and all the
-%% fragment operations are applied before the fragments are written to the frame buffer.
-%%
-%% `?GL_STENCIL': Stencil indices are read from the stencil buffer and converted to
-%% an internal fixed-point format with an unspecified number of bits to the right of the
-%% binary point. Each fixed-point index is then shifted left by `?GL_INDEX_SHIFT' bits,
-%% and added to `?GL_INDEX_OFFSET'. If `?GL_INDEX_SHIFT' is negative, the shift
-%% is to the right. In either case, zero bits fill otherwise unspecified bit locations in
-%% the result. If `?GL_MAP_STENCIL' is true, the index is replaced with the value that
-%% it references in lookup table `?GL_PIXEL_MAP_S_TO_S'. Whether the lookup replacement
-%% of the index is done or not, the integer part of the index is then ANDed with 2 b-1,
-%% where b is the number of bits in the stencil buffer. The resulting stencil indices are
-%% then written to the stencil buffer such that the index read from the ith location of
-%% the jth row is written to location (x r+i y r+j), where (x r y r) is the current raster position. Only the
-%% pixel ownership test, the scissor test, and the stencil writemask affect these write operations.
-%%
-%%
-%% The rasterization described thus far assumes pixel zoom factors of 1.0. If {@link gl:pixelZoom/2}
-%% is used to change the x and y pixel zoom factors, pixels are converted to fragments
-%% as follows. If (x r y r) is the current raster position, and a given pixel is in the ith location
-%% in the jth row of the source pixel rectangle, then fragments are generated for pixels
-%% whose centers are in the rectangle with corners at
-%%
-%% (x r+(zoom x) i y r+(zoom y) j)
-%%
-%% and
-%%
-%% (x r+(zoom x)(i+1) y r+(zoom y)(j+1))
-%%
-%% where zoom x is the value of `?GL_ZOOM_X' and zoom y is the value of `?GL_ZOOM_Y'
-%% .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyPixels.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glCopyPixels.xml">external</a> documentation.
-spec copyPixels(X, Y, Width, Height, Type) -> 'ok' when X :: integer(),Y :: integer(),Width :: integer(),Height :: integer(),Type :: enum().
copyPixels(X,Y,Width,Height,Type) ->
cast(5238, <<X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei,Type:?GLenum>>).
@@ -5661,57 +2402,7 @@ copyPixels(X,Y,Width,Height,Type) ->
%% typically used in multipass rendering algorithms to achieve special effects, such as decals,
%% outlining, and constructive solid geometry rendering.
%%
-%% The stencil test conditionally eliminates a pixel based on the outcome of a comparison
-%% between the reference value and the value in the stencil buffer. To enable and disable
-%% the test, call {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_STENCIL_TEST'
-%% . To specify actions based on the outcome of the stencil test, call {@link gl:stencilOp/3}
-%% or {@link gl:stencilOpSeparate/4} .
-%%
-%% There can be two separate sets of `Func' , `Ref' , and `Mask' parameters;
-%% one affects back-facing polygons, and the other affects front-facing polygons as well
-%% as other non-polygon primitives. {@link gl:stencilFunc/3} sets both front and back stencil
-%% state to the same values. Use {@link gl:stencilFuncSeparate/4} to set front and back stencil
-%% state to different values.
-%%
-%% `Func' is a symbolic constant that determines the stencil comparison function. It
-%% accepts one of eight values, shown in the following list. `Ref' is an integer reference
-%% value that is used in the stencil comparison. It is clamped to the range [0 2 n-1], where n
-%% is the number of bitplanes in the stencil buffer. `Mask' is bitwise ANDed with both
-%% the reference value and the stored stencil value, with the ANDed values participating
-%% in the comparison.
-%%
-%% If `stencil' represents the value stored in the corresponding stencil buffer location,
-%% the following list shows the effect of each comparison function that can be specified by `Func'
-%% . Only if the comparison succeeds is the pixel passed through to the next stage in the
-%% rasterization process (see {@link gl:stencilOp/3} ). All tests treat `stencil' values
-%% as unsigned integers in the range [0 2 n-1], where n is the number of bitplanes in the stencil
-%% buffer.
-%%
-%% The following values are accepted by `Func' :
-%%
-%% `?GL_NEVER': Always fails.
-%%
-%% `?GL_LESS': Passes if ( `Ref' &amp; `Mask' ) &lt; ( `stencil' &amp; `Mask'
-%% ).
-%%
-%% `?GL_LEQUAL': Passes if ( `Ref' &amp; `Mask' ) &lt;= ( `stencil'
-%% &amp; `Mask' ).
-%%
-%% `?GL_GREATER': Passes if ( `Ref' &amp; `Mask' ) &gt; ( `stencil'
-%% &amp; `Mask' ).
-%%
-%% `?GL_GEQUAL': Passes if ( `Ref' &amp; `Mask' ) &gt;= ( `stencil'
-%% &amp; `Mask' ).
-%%
-%% `?GL_EQUAL': Passes if ( `Ref' &amp; `Mask' ) = ( `stencil' &amp; `Mask'
-%% ).
-%%
-%% `?GL_NOTEQUAL': Passes if ( `Ref' &amp; `Mask' ) != ( `stencil' &amp;
-%% `Mask' ).
-%%
-%% `?GL_ALWAYS': Always passes.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilFunc.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glStencilFunc.xhtml">external</a> documentation.
-spec stencilFunc(Func, Ref, Mask) -> 'ok' when Func :: enum(),Ref :: integer(),Mask :: integer().
stencilFunc(Func,Ref,Mask) ->
cast(5239, <<Func:?GLenum,Ref:?GLint,Mask:?GLuint>>).
@@ -5724,12 +2415,7 @@ stencilFunc(Func,Ref,Mask) ->
%% bit in the stencil buffer. Where a 0 appears, the corresponding bit is write-protected.
%% Initially, all bits are enabled for writing.
%%
-%% There can be two separate `Mask' writemasks; one affects back-facing polygons, and
-%% the other affects front-facing polygons as well as other non-polygon primitives. {@link gl:stencilMask/1}
-%% sets both front and back stencil writemasks to the same values. Use {@link gl:stencilMaskSeparate/2}
-%% to set front and back stencil writemasks to different values.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilMask.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glStencilMask.xhtml">external</a> documentation.
-spec stencilMask(Mask) -> 'ok' when Mask :: integer().
stencilMask(Mask) ->
cast(5240, <<Mask:?GLuint>>).
@@ -5742,55 +2428,7 @@ stencilMask(Mask) ->
%% used in multipass rendering algorithms to achieve special effects, such as decals, outlining,
%% and constructive solid geometry rendering.
%%
-%% The stencil test conditionally eliminates a pixel based on the outcome of a comparison
-%% between the value in the stencil buffer and a reference value. To enable and disable the
-%% test, call {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_STENCIL_TEST'
-%% ; to control it, call {@link gl:stencilFunc/3} or {@link gl:stencilFuncSeparate/4} .
-%%
-%% There can be two separate sets of `Sfail' , `Dpfail' , and `Dppass' parameters;
-%% one affects back-facing polygons, and the other affects front-facing polygons as well
-%% as other non-polygon primitives. {@link gl:stencilOp/3} sets both front and back stencil
-%% state to the same values. Use {@link gl:stencilOpSeparate/4} to set front and back stencil
-%% state to different values.
-%%
-%% ``gl:stencilOp'' takes three arguments that indicate what happens to the stored stencil
-%% value while stenciling is enabled. If the stencil test fails, no change is made to the
-%% pixel's color or depth buffers, and `Sfail' specifies what happens to the stencil
-%% buffer contents. The following eight actions are possible.
-%%
-%% `?GL_KEEP': Keeps the current value.
-%%
-%% `?GL_ZERO': Sets the stencil buffer value to 0.
-%%
-%% `?GL_REPLACE': Sets the stencil buffer value to `ref', as specified by {@link gl:stencilFunc/3}
-%% .
-%%
-%% `?GL_INCR': Increments the current stencil buffer value. Clamps to the maximum representable
-%% unsigned value.
-%%
-%% `?GL_INCR_WRAP': Increments the current stencil buffer value. Wraps stencil buffer
-%% value to zero when incrementing the maximum representable unsigned value.
-%%
-%% `?GL_DECR': Decrements the current stencil buffer value. Clamps to 0.
-%%
-%% `?GL_DECR_WRAP': Decrements the current stencil buffer value. Wraps stencil buffer
-%% value to the maximum representable unsigned value when decrementing a stencil buffer value
-%% of zero.
-%%
-%% `?GL_INVERT': Bitwise inverts the current stencil buffer value.
-%%
-%% Stencil buffer values are treated as unsigned integers. When incremented and decremented,
-%% values are clamped to 0 and 2 n-1, where n is the value returned by querying `?GL_STENCIL_BITS'
-%% .
-%%
-%% The other two arguments to ``gl:stencilOp'' specify stencil buffer actions that depend
-%% on whether subsequent depth buffer tests succeed ( `Dppass' ) or fail ( `Dpfail' )
-%% (see {@link gl:depthFunc/1} ). The actions are specified using the same eight symbolic constants
-%% as `Sfail' . Note that `Dpfail' is ignored when there is no depth buffer, or
-%% when the depth buffer is not enabled. In these cases, `Sfail' and `Dppass' specify
-%% stencil action when the stencil test fails and passes, respectively.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilOp.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glStencilOp.xhtml">external</a> documentation.
-spec stencilOp(Fail, Zfail, Zpass) -> 'ok' when Fail :: enum(),Zfail :: enum(),Zpass :: enum().
stencilOp(Fail,Zfail,Zpass) ->
cast(5241, <<Fail:?GLenum,Zfail:?GLenum,Zpass:?GLenum>>).
@@ -5801,7 +2439,7 @@ stencilOp(Fail,Zfail,Zpass) ->
%% buffer. `S' is masked with 2 m-1, where m is the number of bits in the stencil
%% buffer.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearStencil.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glClearStencil.xhtml">external</a> documentation.
-spec clearStencil(S) -> 'ok' when S :: integer().
clearStencil(S) ->
cast(5242, <<S:?GLint>>).
@@ -5818,69 +2456,7 @@ clearStencil(S) ->
%% is either `?GL_OBJECT_PLANE' or `?GL_EYE_PLANE', `Params' contains coefficients
%% for the corresponding texture generation function.
%%
-%% If the texture generation function is `?GL_OBJECT_LINEAR', the function
-%%
-%% g=p 1×x o+p 2×y o+p 3×z o+p 4×w o
-%%
-%% is used, where g is the value computed for the coordinate named in `Coord' , p 1,
-%% p 2, p 3, and p 4 are the four values supplied in `Params' , and x o, y o, z o,
-%% and w o are the object coordinates of the vertex. This function can be used, for example,
-%% to texture-map terrain using sea level as a reference plane (defined by p 1, p 2, p
-%% 3, and p 4). The altitude of a terrain vertex is computed by the `?GL_OBJECT_LINEAR'
-%% coordinate generation function as its distance from sea level; that altitude can then
-%% be used to index the texture image to map white snow onto peaks and green grass onto foothills.
-%%
-%%
-%% If the texture generation function is `?GL_EYE_LINEAR', the function
-%%
-%% g=(p 1)"×x e+(p 2)"×y e+(p 3)"×z e+(p 4)"×w e
-%%
-%% is used, where
-%%
-%% ((p 1)" (p 2)" (p 3)" (p 4)")=(p 1 p 2 p 3 p 4) M -1
-%%
-%% and x e, y e, z e, and w e are the eye coordinates of the vertex, p 1, p 2, p 3,
-%% and p 4 are the values supplied in `Params' , and M is the modelview matrix when ``gl:texGen''
-%% is invoked. If M is poorly conditioned or singular, texture coordinates generated by
-%% the resulting function may be inaccurate or undefined.
-%%
-%% Note that the values in `Params' define a reference plane in eye coordinates. The
-%% modelview matrix that is applied to them may not be the same one in effect when the polygon
-%% vertices are transformed. This function establishes a field of texture coordinates that
-%% can produce dynamic contour lines on moving objects.
-%%
-%% If the texture generation function is `?GL_SPHERE_MAP' and `Coord' is either `?GL_S'
-%% or `?GL_T', s and t texture coordinates are generated as follows. Let `u'
-%% be the unit vector pointing from the origin to the polygon vertex (in eye coordinates).
-%% Let `n' sup prime be the current normal, after transformation to eye coordinates.
-%% Let
-%%
-%% f=(f x f y f z) T be the reflection vector such that
-%%
-%% f=u-2 n" (n") T u
-%%
-%% Finally, let m=2 ((f x) 2+(f y) 2+(f z+1) 2). Then the values assigned to the s and t texture coordinates
-%% are
-%%
-%% s=f x/m+1/2
-%%
-%% t=f y/m+1/2
-%%
-%% To enable or disable a texture-coordinate generation function, call {@link gl:enable/1}
-%% or {@link gl:enable/1} with one of the symbolic texture-coordinate names (`?GL_TEXTURE_GEN_S'
-%% , `?GL_TEXTURE_GEN_T', `?GL_TEXTURE_GEN_R', or `?GL_TEXTURE_GEN_Q') as
-%% the argument. When enabled, the specified texture coordinate is computed according to
-%% the generating function associated with that coordinate. When disabled, subsequent vertices
-%% take the specified texture coordinate from the current set of texture coordinates. Initially,
-%% all texture generation functions are set to `?GL_EYE_LINEAR' and are disabled. Both
-%% s plane equations are (1, 0, 0, 0), both t plane equations are (0, 1, 0, 0), and all
-%% r and q plane equations are (0, 0, 0, 0).
-%%
-%% When the ARB_multitexture extension is supported, ``gl:texGen'' sets the texture generation
-%% parameters for the currently active texture unit, selected with {@link gl:activeTexture/1} .
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTexGen.xml">external</a> documentation.
-spec texGend(Coord, Pname, Param) -> 'ok' when Coord :: enum(),Pname :: enum(),Param :: float().
texGend(Coord,Pname,Param) ->
cast(5243, <<Coord:?GLenum,Pname:?GLenum,Param:?GLdouble>>).
@@ -5925,22 +2501,7 @@ texGeniv(Coord,Pname,Params) ->
%% of the (`s', `t', `r', `q') texture coordinates, using the symbolic
%% constant `?GL_S', `?GL_T', `?GL_R', or `?GL_Q'.
%%
-%% `Pname' specifies one of three symbolic names:
-%%
-%% `?GL_TEXTURE_GEN_MODE': `Params' returns the single-valued texture generation
-%% function, a symbolic constant. The initial value is `?GL_EYE_LINEAR'.
-%%
-%% `?GL_OBJECT_PLANE': `Params' returns the four plane equation coefficients that
-%% specify object linear-coordinate generation. Integer values, when requested, are mapped
-%% directly from the internal floating-point representation.
-%%
-%% `?GL_EYE_PLANE': `Params' returns the four plane equation coefficients that
-%% specify eye linear-coordinate generation. Integer values, when requested, are mapped directly
-%% from the internal floating-point representation. The returned values are those maintained
-%% in eye coordinates. They are not equal to the values specified using {@link gl:texGend/3} ,
-%% unless the modelview matrix was identity when {@link gl:texGend/3} was called.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexGen.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetTexGen.xml">external</a> documentation.
-spec getTexGendv(Coord, Pname) -> {float(),float(),float(),float()} when Coord :: enum(),Pname :: enum().
getTexGendv(Coord,Pname) ->
call(5249, <<Coord:?GLenum,Pname:?GLenum>>).
@@ -5959,14 +2520,14 @@ getTexGeniv(Coord,Pname) ->
%% @doc glTexEnvf
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexEnvf.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec texEnvf(Target, Pname, Param) -> 'ok' when Target :: enum(),Pname :: enum(),Param :: float().
texEnvf(Target,Pname,Param) ->
cast(5252, <<Target:?GLenum,Pname:?GLenum,Param:?GLfloat>>).
%% @doc glTexEnvi
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexEnvi.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec texEnvi(Target, Pname, Param) -> 'ok' when Target :: enum(),Pname :: enum(),Param :: integer().
texEnvi(Target,Pname,Param) ->
cast(5253, <<Target:?GLenum,Pname:?GLenum,Param:?GLint>>).
@@ -5980,158 +2541,7 @@ texEnvi(Target,Pname,Param) ->
%% , `?GL_ALPHA_SCALE', `?GL_SRC0_RGB', `?GL_SRC1_RGB', `?GL_SRC2_RGB', `?GL_SRC0_ALPHA'
%% , `?GL_SRC1_ALPHA', or `?GL_SRC2_ALPHA'.
%%
-%% If `Pname' is `?GL_TEXTURE_ENV_MODE', then `Params' is (or points to)
-%% the symbolic name of a texture function. Six texture functions may be specified: `?GL_ADD'
-%% , `?GL_MODULATE', `?GL_DECAL', `?GL_BLEND', `?GL_REPLACE', or `?GL_COMBINE'
-%% .
-%%
-%% The following table shows the correspondence of filtered texture values R t, G t, B t,
-%% A t, L t, I t to texture source components. C s and A s are used by the texture functions
-%% described below.
-%%
-%% <table><tbody><tr><td> Texture Base Internal Format </td><td> C s</td><td> A s</td></tr></tbody>
-%% <tbody><tr><td>`?GL_ALPHA'</td><td> (0, 0, 0) </td><td> A t</td></tr><tr><td>`?GL_LUMINANCE'
-%% </td><td> ( L t, L t, L t ) </td><td> 1 </td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td>
-%% <td> ( L t, L t, L t ) </td><td> A t</td></tr><tr><td>`?GL_INTENSITY'</td><td> (
-%% I t, I t, I t ) </td><td> I t</td></tr><tr><td>`?GL_RGB'</td><td> ( R t, G t, B
-%% t ) </td><td> 1 </td></tr><tr><td>`?GL_RGBA'</td><td> ( R t, G t, B t ) </td><td>
-%% A t</td></tr></tbody></table>
-%%
-%% A texture function acts on the fragment to be textured using the texture image value
-%% that applies to the fragment (see {@link gl:texParameterf/3} ) and produces an RGBA color
-%% for that fragment. The following table shows how the RGBA color is produced for each of
-%% the first five texture functions that can be chosen. C is a triple of color values (RGB)
-%% and A is the associated alpha value. RGBA values extracted from a texture image are in
-%% the range [0,1]. The subscript p refers to the color computed from the previous texture
-%% stage (or the incoming fragment if processing texture stage 0), the subscript s to the
-%% texture source color, the subscript c to the texture environment color, and the subscript
-%% v indicates a value produced by the texture function.
-%%
-%% <table><tbody><tr><td> Texture Base Internal Format </td><td>`?Value'</td><td>`?GL_REPLACE'
-%% Function </td><td>`?GL_MODULATE' Function </td><td>`?GL_DECAL' Function </td><td>
-%% `?GL_BLEND' Function </td><td>`?GL_ADD' Function </td></tr></tbody><tbody><tr><td>
-%% `?GL_ALPHA'</td><td> C v=</td><td> C p</td><td> C p</td><td> undefined </td><td> C p</td>
-%% <td> C p</td></tr><tr><td></td><td> A v=</td><td> A s</td><td> A p A s</td><td></td><td>
-%% A v=A p A s</td><td> A p A s</td></tr><tr><td>`?GL_LUMINANCE'</td><td> C v=</td><td>
-%% C s</td><td> C p C s</td><td> undefined </td><td> C p (1-C s)+C c C s</td><td> C p+C s</td></tr>
-%% <tr><td> (or 1) </td><td> A v=</td><td> A p</td><td> A p</td><td></td><td> A p</td><td> A
-%% p</td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td> C v=</td><td> C s</td><td> C p C
-%% s</td><td> undefined </td><td> C p (1-C s)+C c C s</td><td> C p+C s</td></tr><tr><td> (or 2) </td>
-%% <td> A v=</td><td> A s</td><td> A p A s</td><td></td><td> A p A s</td><td> A p A s</td>
-%% </tr><tr><td>`?GL_INTENSITY'</td><td> C v=</td><td> C s</td><td> C p C s</td><td>
-%% undefined </td><td> C p (1-C s)+C c C s</td><td> C p+C s</td></tr><tr><td></td><td> A v=</td><td>
-%% A s</td><td> A p A s</td><td></td><td> A p (1-A s)+A c A s</td><td> A p+A s</td></tr><tr><td>`?GL_RGB'
-%% </td><td> C v=</td><td> C s</td><td> C p C s</td><td> C s</td><td> C p (1-C s)+C c C s</td><td>
-%% C p+C s</td></tr><tr><td> (or 3) </td><td> A v=</td><td> A p</td><td> A p</td><td> A p</td>
-%% <td> A p</td><td> A p</td></tr><tr><td>`?GL_RGBA'</td><td> C v=</td><td> C s</td><td>
-%% C p C s</td><td> C p (1-A s)+C s A s</td><td> C p (1-C s)+C c C s</td><td> C p+C s</td></tr><tr><td>
-%% (or 4) </td><td> A v=</td><td> A s</td><td> A p A s</td><td> A p</td><td> A p A s</td><td>
-%% A p A s</td></tr></tbody></table>
-%%
-%% If `Pname' is `?GL_TEXTURE_ENV_MODE', and `Params' is `?GL_COMBINE',
-%% the form of the texture function depends on the values of `?GL_COMBINE_RGB' and `?GL_COMBINE_ALPHA'
-%% .
-%%
-%% The following describes how the texture sources, as specified by `?GL_SRC0_RGB', `?GL_SRC1_RGB'
-%% , `?GL_SRC2_RGB', `?GL_SRC0_ALPHA', `?GL_SRC1_ALPHA', and `?GL_SRC2_ALPHA'
-%% , are combined to produce a final texture color. In the following tables, `?GL_SRC0_c'
-%% is represented by Arg0, `?GL_SRC1_c' is represented by Arg1, and `?GL_SRC2_c'
-%% is represented by Arg2.
-%%
-%% `?GL_COMBINE_RGB' accepts any of `?GL_REPLACE', `?GL_MODULATE', `?GL_ADD'
-%% , `?GL_ADD_SIGNED', `?GL_INTERPOLATE', `?GL_SUBTRACT', `?GL_DOT3_RGB',
-%% or `?GL_DOT3_RGBA'.
-%%
-%% <table><tbody><tr><td>`?GL_COMBINE_RGB'</td><td>` Texture Function '</td></tr></tbody>
-%% <tbody><tr><td>`?GL_REPLACE'</td><td> Arg0</td></tr><tr><td>`?GL_MODULATE'</td><td>
-%% Arg0×Arg1</td></tr><tr><td>`?GL_ADD'</td><td> Arg0+Arg1</td></tr><tr><td>`?GL_ADD_SIGNED'
-%% </td><td> Arg0+Arg1-0.5</td></tr><tr><td>`?GL_INTERPOLATE'</td><td> Arg0×Arg2+Arg1×(1-
-%% Arg2)</td>
-%% </tr><tr><td>`?GL_SUBTRACT'</td><td> Arg0-Arg1</td></tr><tr><td>`?GL_DOT3_RGB'
-%% or `?GL_DOT3_RGBA'</td><td> 4×((((Arg0 r)-0.5)×((Arg1 r)-0.5))+(((Arg0 g)-0.5)×((Arg1 g)-0.5))+(((Arg0 b)-0.5)×((Arg1 b)-0.5)))</td></tr></tbody></table>
-%%
-%% The scalar results for `?GL_DOT3_RGB' and `?GL_DOT3_RGBA' are placed into each
-%% of the 3 (RGB) or 4 (RGBA) components on output.
-%%
-%% Likewise, `?GL_COMBINE_ALPHA' accepts any of `?GL_REPLACE', `?GL_MODULATE',
-%% `?GL_ADD', `?GL_ADD_SIGNED', `?GL_INTERPOLATE', or `?GL_SUBTRACT'.
-%% The following table describes how alpha values are combined:
-%%
-%% <table><tbody><tr><td>`?GL_COMBINE_ALPHA'</td><td>` Texture Function '</td></tr>
-%% </tbody><tbody><tr><td>`?GL_REPLACE'</td><td> Arg0</td></tr><tr><td>`?GL_MODULATE'
-%% </td><td> Arg0×Arg1</td></tr><tr><td>`?GL_ADD'</td><td> Arg0+Arg1</td></tr><tr><td>`?GL_ADD_SIGNED'
-%% </td><td> Arg0+Arg1-0.5</td></tr><tr><td>`?GL_INTERPOLATE'</td><td> Arg0×Arg2+Arg1×(1-
-%% Arg2)</td>
-%% </tr><tr><td>`?GL_SUBTRACT'</td><td> Arg0-Arg1</td></tr></tbody></table>
-%%
-%% In the following tables, the value C s represents the color sampled from the currently
-%% bound texture, C c represents the constant texture-environment color, C f represents
-%% the primary color of the incoming fragment, and C p represents the color computed from
-%% the previous texture stage or C f if processing texture stage 0. Likewise, A s, A c,
-%% A f, and A p represent the respective alpha values.
-%%
-%% The following table describes the values assigned to Arg0, Arg1, and Arg2 based upon
-%% the RGB sources and operands:
-%%
-%% <table><tbody><tr><td>`?GL_SRCn_RGB'</td><td>`?GL_OPERANDn_RGB'</td><td>` Argument Value '
-%% </td></tr></tbody><tbody><tr><td>`?GL_TEXTURE'</td><td>`?GL_SRC_COLOR'</td><td>(C
-%% s)</td>
-%% </tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_COLOR'</td><td> 1-(C s)</td></tr><tr><td></td><td>
-%% `?GL_SRC_ALPHA'</td><td>(A s)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'</td>
-%% <td> 1-(A s)</td></tr><tr><td>`?GL_TEXTUREn'</td><td>`?GL_SRC_COLOR'</td><td>(C s)</td></tr>
-%% <tr><td></td><td>`?GL_ONE_MINUS_SRC_COLOR'</td><td> 1-(C s)</td></tr><tr><td></td><td>`?GL_SRC_ALPHA'
-%% </td><td>(A s)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td> 1-(A s)</td></tr><tr>
-%% <td>`?GL_CONSTANT'</td><td>`?GL_SRC_COLOR'</td><td>(C c)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_COLOR'
-%% </td><td> 1-(C c)</td></tr><tr><td></td><td>`?GL_SRC_ALPHA'</td><td>(A c)</td></tr><tr><td></td>
-%% <td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td> 1-(A c)</td></tr><tr><td>`?GL_PRIMARY_COLOR'</td>
-%% <td>`?GL_SRC_COLOR'</td><td>(C f)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_COLOR'</td>
-%% <td> 1-(C f)</td></tr><tr><td></td><td>`?GL_SRC_ALPHA'</td><td>(A f)</td></tr><tr><td></td><td>
-%% `?GL_ONE_MINUS_SRC_ALPHA'</td><td> 1-(A f)</td></tr><tr><td>`?GL_PREVIOUS'</td><td>`?GL_SRC_COLOR'
-%% </td><td>(C p)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_COLOR'</td><td> 1-(C p)</td></tr><tr>
-%% <td></td><td>`?GL_SRC_ALPHA'</td><td>(A p)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'
-%% </td><td> 1-(A p)</td></tr></tbody></table>
-%%
-%% For `?GL_TEXTUREn' sources, C s and A s represent the color and alpha, respectively,
-%% produced from texture stage n.
-%%
-%% The follow table describes the values assigned to Arg0, Arg1, and Arg2 based upon
-%% the alpha sources and operands:
-%%
-%% <table><tbody><tr><td>`?GL_SRCn_ALPHA'</td><td>`?GL_OPERANDn_ALPHA'</td><td>` Argument Value '
-%% </td></tr></tbody><tbody><tr><td>`?GL_TEXTURE'</td><td>`?GL_SRC_ALPHA'</td><td>(A
-%% s)</td>
-%% </tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td> 1-(A s)</td></tr><tr><td>`?GL_TEXTUREn'
-%% </td><td>`?GL_SRC_ALPHA'</td><td>(A s)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'
-%% </td><td> 1-(A s)</td></tr><tr><td>`?GL_CONSTANT'</td><td>`?GL_SRC_ALPHA'</td><td>(A
-%% c)</td>
-%% </tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td> 1-(A c)</td></tr><tr><td>`?GL_PRIMARY_COLOR'
-%% </td><td>`?GL_SRC_ALPHA'</td><td>(A f)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'
-%% </td><td> 1-(A f)</td></tr><tr><td>`?GL_PREVIOUS'</td><td>`?GL_SRC_ALPHA'</td><td>(A
-%% p)</td>
-%% </tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td> 1-(A p)</td></tr></tbody></table>
-%%
-%%
-%% The RGB and alpha results of the texture function are multipled by the values of `?GL_RGB_SCALE'
-%% and `?GL_ALPHA_SCALE', respectively, and clamped to the range [0 1].
-%%
-%% If `Pname' is `?GL_TEXTURE_ENV_COLOR', `Params' is a pointer to an array
-%% that holds an RGBA color consisting of four values. Integer color components are interpreted
-%% linearly such that the most positive integer maps to 1.0, and the most negative integer
-%% maps to -1.0. The values are clamped to the range [0,1] when they are specified. C c
-%% takes these four values.
-%%
-%% If `Pname' is `?GL_TEXTURE_LOD_BIAS', the value specified is added to the texture
-%% level-of-detail parameter, that selects which mipmap, or mipmaps depending upon the selected
-%% `?GL_TEXTURE_MIN_FILTER', will be sampled.
-%%
-%% `?GL_TEXTURE_ENV_MODE' defaults to `?GL_MODULATE' and `?GL_TEXTURE_ENV_COLOR'
-%% defaults to (0, 0, 0, 0).
-%%
-%% If `Target' is `?GL_POINT_SPRITE' and `Pname' is `?GL_COORD_REPLACE',
-%% the boolean value specified is used to either enable or disable point sprite texture coordinate
-%% replacement. The default value is `?GL_FALSE'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTexEnv.xml">external</a> documentation.
-spec texEnvfv(Target, Pname, Params) -> 'ok' when Target :: enum(),Pname :: enum(),Params :: tuple().
texEnvfv(Target,Pname,Params) ->
cast(5254, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
@@ -6149,80 +2559,7 @@ texEnviv(Target,Pname,Params) ->
%% ``gl:getTexEnv'' returns in `Params' selected values of a texture environment that
%% was specified with {@link gl:texEnvfv/3} . `Target' specifies a texture environment.
%%
-%% When `Target' is `?GL_TEXTURE_FILTER_CONTROL', `Pname' must be `?GL_TEXTURE_LOD_BIAS'
-%% . When `Target' is `?GL_POINT_SPRITE', `Pname' must be `?GL_COORD_REPLACE'
-%% . When `Target' is `?GL_TEXTURE_ENV', `Pname' can be `?GL_TEXTURE_ENV_MODE'
-%% , `?GL_TEXTURE_ENV_COLOR', `?GL_COMBINE_RGB', `?GL_COMBINE_ALPHA', `?GL_RGB_SCALE'
-%% , `?GL_ALPHA_SCALE', `?GL_SRC0_RGB', `?GL_SRC1_RGB', `?GL_SRC2_RGB',
-%% `?GL_SRC0_ALPHA', `?GL_SRC1_ALPHA', or `?GL_SRC2_ALPHA'.
-%%
-%% `Pname' names a specific texture environment parameter, as follows:
-%%
-%% `?GL_TEXTURE_ENV_MODE': `Params' returns the single-valued texture environment
-%% mode, a symbolic constant. The initial value is `?GL_MODULATE'.
-%%
-%% `?GL_TEXTURE_ENV_COLOR': `Params' returns four integer or floating-point values
-%% that are the texture environment color. Integer values, when requested, are linearly mapped
-%% from the internal floating-point representation such that 1.0 maps to the most positive
-%% representable integer, and -1.0 maps to the most negative representable integer. The
-%% initial value is (0, 0, 0, 0).
-%%
-%% `?GL_TEXTURE_LOD_BIAS': `Params' returns a single floating-point value that
-%% is the texture level-of-detail bias. The initial value is 0.
-%%
-%% `?GL_COMBINE_RGB': `Params' returns a single symbolic constant value representing
-%% the current RGB combine mode. The initial value is `?GL_MODULATE'.
-%%
-%% `?GL_COMBINE_ALPHA': `Params' returns a single symbolic constant value representing
-%% the current alpha combine mode. The initial value is `?GL_MODULATE'.
-%%
-%% `?GL_SRC0_RGB': `Params' returns a single symbolic constant value representing
-%% the texture combiner zero's RGB source. The initial value is `?GL_TEXTURE'.
-%%
-%% `?GL_SRC1_RGB': `Params' returns a single symbolic constant value representing
-%% the texture combiner one's RGB source. The initial value is `?GL_PREVIOUS'.
-%%
-%% `?GL_SRC2_RGB': `Params' returns a single symbolic constant value representing
-%% the texture combiner two's RGB source. The initial value is `?GL_CONSTANT'.
-%%
-%% `?GL_SRC0_ALPHA': `Params' returns a single symbolic constant value representing
-%% the texture combiner zero's alpha source. The initial value is `?GL_TEXTURE'.
-%%
-%% `?GL_SRC1_ALPHA': `Params' returns a single symbolic constant value representing
-%% the texture combiner one's alpha source. The initial value is `?GL_PREVIOUS'.
-%%
-%% `?GL_SRC2_ALPHA': `Params' returns a single symbolic constant value representing
-%% the texture combiner two's alpha source. The initial value is `?GL_CONSTANT'.
-%%
-%% `?GL_OPERAND0_RGB': `Params' returns a single symbolic constant value representing
-%% the texture combiner zero's RGB operand. The initial value is `?GL_SRC_COLOR'.
-%%
-%% `?GL_OPERAND1_RGB': `Params' returns a single symbolic constant value representing
-%% the texture combiner one's RGB operand. The initial value is `?GL_SRC_COLOR'.
-%%
-%% `?GL_OPERAND2_RGB': `Params' returns a single symbolic constant value representing
-%% the texture combiner two's RGB operand. The initial value is `?GL_SRC_ALPHA'.
-%%
-%% `?GL_OPERAND0_ALPHA': `Params' returns a single symbolic constant value representing
-%% the texture combiner zero's alpha operand. The initial value is `?GL_SRC_ALPHA'.
-%%
-%% `?GL_OPERAND1_ALPHA': `Params' returns a single symbolic constant value representing
-%% the texture combiner one's alpha operand. The initial value is `?GL_SRC_ALPHA'.
-%%
-%% `?GL_OPERAND2_ALPHA': `Params' returns a single symbolic constant value representing
-%% the texture combiner two's alpha operand. The initial value is `?GL_SRC_ALPHA'.
-%%
-%% `?GL_RGB_SCALE': `Params' returns a single floating-point value representing
-%% the current RGB texture combiner scaling factor. The initial value is 1.0.
-%%
-%% `?GL_ALPHA_SCALE': `Params' returns a single floating-point value representing
-%% the current alpha texture combiner scaling factor. The initial value is 1.0.
-%%
-%% `?GL_COORD_REPLACE': `Params' returns a single boolean value representing the
-%% current point sprite texture coordinate replacement enable state. The initial value is `?GL_FALSE'
-%% .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexEnv.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetTexEnv.xml">external</a> documentation.
-spec getTexEnvfv(Target, Pname) -> {float(),float(),float(),float()} when Target :: enum(),Pname :: enum().
getTexEnvfv(Target,Pname) ->
call(5256, <<Target:?GLenum,Pname:?GLenum>>).
@@ -6240,218 +2577,7 @@ getTexEnviv(Target,Pname) ->
%% , `?GL_TEXTURE_2D', `?GL_TEXTURE_1D_ARRAY', `?GL_TEXTURE_2D_ARRAY', `?GL_TEXTURE_RECTANGLE'
%% , or `?GL_TEXTURE_3D'. The following symbols are accepted in `Pname' :
%%
-%% `?GL_TEXTURE_BASE_LEVEL': Specifies the index of the lowest defined mipmap level.
-%% This is an integer value. The initial value is 0.
-%%
-%%
-%%
-%% `?GL_TEXTURE_BORDER_COLOR': The data in `Params' specifies four values that
-%% define the border values that should be used for border texels. If a texel is sampled
-%% from the border of the texture, the values of `?GL_TEXTURE_BORDER_COLOR' are interpreted
-%% as an RGBA color to match the texture's internal format and substituted for the non-existent
-%% texel data. If the texture contains depth components, the first component of `?GL_TEXTURE_BORDER_COLOR'
-%% is interpreted as a depth value. The initial value is ( 0.0, 0.0, 0.0, 0.0 ).
-%%
-%% If the values for `?GL_TEXTURE_BORDER_COLOR' are specified with ``gl:texParameterIiv''
-%% or ``gl:texParameterIuiv'', the values are stored unmodified with an internal data
-%% type of integer. If specified with ``gl:texParameteriv'', they are converted to floating
-%% point with the following equation: f=2 c+1 2 b-/1. If specified with ``gl:texParameterfv''
-%% , they are stored unmodified as floating-point values.
-%%
-%% `?GL_TEXTURE_COMPARE_FUNC': Specifies the comparison operator used when `?GL_TEXTURE_COMPARE_MODE'
-%% is set to `?GL_COMPARE_REF_TO_TEXTURE'. Permissible values are: <table><tbody><tr><td>
-%% ` Texture Comparison Function '</td><td>` Computed result '</td></tr></tbody><tbody>
-%% <tr><td>`?GL_LEQUAL'</td><td> result={1.0 0.0 r&lt;=(D t) r&gt;(D t))</td></tr><tr><td>`?GL_GEQUAL'</td><td>
-%% result={1.0 0.0 r&gt;=(D t) r&lt;(D t))</td></tr><tr><td>`?GL_LESS'</td><td> result={1.0 0.0 r&lt;(D t) r&gt;=(D t))</td></tr><tr><td>`?GL_GREATER'
-%% </td><td> result={1.0 0.0 r&gt;(D t) r&lt;=(D t))</td></tr><tr><td>`?GL_EQUAL'</td><td> result={1.0 0.0 r=(D t) r&amp;ne;
-%% (D t))</td></tr><tr><td>`?GL_NOTEQUAL'
-%% </td><td> result={1.0 0.0 r&amp;ne;(D t) r=(D t))</td></tr><tr><td>`?GL_ALWAYS'</td><td> result=1.0</td></tr><tr><td>
-%% `?GL_NEVER'</td><td> result=0.0</td></tr></tbody></table> where r is the current
-%% interpolated texture coordinate, and D t is the depth texture value sampled from the
-%% currently bound depth texture. result is assigned to the the red channel.
-%%
-%% `?GL_TEXTURE_COMPARE_MODE': Specifies the texture comparison mode for currently
-%% bound depth textures. That is, a texture whose internal format is `?GL_DEPTH_COMPONENT_*'
-%% ; see {@link gl:texImage2D/9} ) Permissible values are:
-%%
-%% `?GL_COMPARE_REF_TO_TEXTURE': Specifies that the interpolated and clamped r texture
-%% coordinate should be compared to the value in the currently bound depth texture. See the
-%% discussion of `?GL_TEXTURE_COMPARE_FUNC' for details of how the comparison is evaluated.
-%% The result of the comparison is assigned to the red channel.
-%%
-%% `?GL_NONE': Specifies that the red channel should be assigned the appropriate value
-%% from the currently bound depth texture.
-%%
-%% `?GL_TEXTURE_LOD_BIAS': `Params' specifies a fixed bias value that is to be
-%% added to the level-of-detail parameter for the texture before texture sampling. The specified
-%% value is added to the shader-supplied bias value (if any) and subsequently clamped into
-%% the implementation-defined range [( - bias max)(bias max)], where bias max is the value of the implementation
-%% defined constant `?GL_MAX_TEXTURE_LOD_BIAS'. The initial value is 0.0.
-%%
-%% `?GL_TEXTURE_MIN_FILTER': The texture minifying function is used whenever the level-of-detail
-%% function used when sampling from the texture determines that the texture should be minified.
-%% There are six defined minifying functions. Two of them use either the nearest texture
-%% elements or a weighted average of multiple texture elements to compute the texture value.
-%% The other four use mipmaps.
-%%
-%% A mipmap is an ordered set of arrays representing the same image at progressively lower
-%% resolutions. If the texture has dimensions 2 n×2 m, there are max(n m)+1 mipmaps. The first
-%% mipmap is the original texture, with dimensions 2 n×2 m. Each subsequent mipmap has
-%% dimensions 2(k-1)×2(l-1), where 2 k×2 l are the dimensions of the previous mipmap, until either
-%% k=0 or l=0. At that point, subsequent mipmaps have dimension 1×2(l-1) or 2(k-1)×1 until
-%% the final mipmap, which has dimension 1×1. To define the mipmaps, call {@link gl:texImage1D/8}
-%% , {@link gl:texImage2D/9} , {@link gl:texImage3D/10} , {@link gl:copyTexImage1D/7} , or {@link gl:copyTexImage2D/8}
-%% with the `level' argument indicating the order of the mipmaps. Level 0 is the original
-%% texture; level max(n m) is the final 1×1 mipmap.
-%%
-%% `Params' supplies a function for minifying the texture as one of the following:
-%%
-%% `?GL_NEAREST': Returns the value of the texture element that is nearest (in Manhattan
-%% distance) to the specified texture coordinates.
-%%
-%% `?GL_LINEAR': Returns the weighted average of the four texture elements that are
-%% closest to the specified texture coordinates. These can include items wrapped or repeated
-%% from other parts of a texture, depending on the values of `?GL_TEXTURE_WRAP_S' and `?GL_TEXTURE_WRAP_T'
-%% , and on the exact mapping.
-%%
-%% `?GL_NEAREST_MIPMAP_NEAREST': Chooses the mipmap that most closely matches the size
-%% of the pixel being textured and uses the `?GL_NEAREST' criterion (the texture element
-%% closest to the specified texture coordinates) to produce a texture value.
-%%
-%% `?GL_LINEAR_MIPMAP_NEAREST': Chooses the mipmap that most closely matches the size
-%% of the pixel being textured and uses the `?GL_LINEAR' criterion (a weighted average
-%% of the four texture elements that are closest to the specified texture coordinates) to
-%% produce a texture value.
-%%
-%% `?GL_NEAREST_MIPMAP_LINEAR': Chooses the two mipmaps that most closely match the
-%% size of the pixel being textured and uses the `?GL_NEAREST' criterion (the texture
-%% element closest to the specified texture coordinates ) to produce a texture value from
-%% each mipmap. The final texture value is a weighted average of those two values.
-%%
-%% `?GL_LINEAR_MIPMAP_LINEAR': Chooses the two mipmaps that most closely match the
-%% size of the pixel being textured and uses the `?GL_LINEAR' criterion (a weighted
-%% average of the texture elements that are closest to the specified texture coordinates)
-%% to produce a texture value from each mipmap. The final texture value is a weighted average
-%% of those two values.
-%%
-%% As more texture elements are sampled in the minification process, fewer aliasing artifacts
-%% will be apparent. While the `?GL_NEAREST' and `?GL_LINEAR' minification functions
-%% can be faster than the other four, they sample only one or multiple texture elements to
-%% determine the texture value of the pixel being rendered and can produce moire patterns
-%% or ragged transitions. The initial value of `?GL_TEXTURE_MIN_FILTER' is `?GL_NEAREST_MIPMAP_LINEAR'
-%% .
-%%
-%%
-%%
-%% `?GL_TEXTURE_MAG_FILTER': The texture magnification function is used whenever the
-%% level-of-detail function used when sampling from the texture determines that the texture
-%% should be magified. It sets the texture magnification function to either `?GL_NEAREST'
-%% or `?GL_LINEAR' (see below). `?GL_NEAREST' is generally faster than `?GL_LINEAR'
-%% , but it can produce textured images with sharper edges because the transition between
-%% texture elements is not as smooth. The initial value of `?GL_TEXTURE_MAG_FILTER' is `?GL_LINEAR'
-%% .
-%%
-%% `?GL_NEAREST': Returns the value of the texture element that is nearest (in Manhattan
-%% distance) to the specified texture coordinates.
-%%
-%% `?GL_LINEAR': Returns the weighted average of the texture elements that are closest
-%% to the specified texture coordinates. These can include items wrapped or repeated from
-%% other parts of a texture, depending on the values of `?GL_TEXTURE_WRAP_S' and `?GL_TEXTURE_WRAP_T'
-%% , and on the exact mapping.
-%%
-%%
-%%
-%% `?GL_TEXTURE_MIN_LOD': Sets the minimum level-of-detail parameter. This floating-point
-%% value limits the selection of highest resolution mipmap (lowest mipmap level). The initial
-%% value is -1000.
-%%
-%%
-%%
-%% `?GL_TEXTURE_MAX_LOD': Sets the maximum level-of-detail parameter. This floating-point
-%% value limits the selection of the lowest resolution mipmap (highest mipmap level). The
-%% initial value is 1000.
-%%
-%%
-%%
-%% `?GL_TEXTURE_MAX_LEVEL': Sets the index of the highest defined mipmap level. This
-%% is an integer value. The initial value is 1000.
-%%
-%%
-%%
-%% `?GL_TEXTURE_SWIZZLE_R': Sets the swizzle that will be applied to the r component
-%% of a texel before it is returned to the shader. Valid values for `Param' are `?GL_RED'
-%% , `?GL_GREEN', `?GL_BLUE', `?GL_ALPHA', `?GL_ZERO' and `?GL_ONE'.
-%% If `?GL_TEXTURE_SWIZZLE_R' is `?GL_RED', the value for r will be taken from
-%% the first channel of the fetched texel. If `?GL_TEXTURE_SWIZZLE_R' is `?GL_GREEN'
-%% , the value for r will be taken from the second channel of the fetched texel. If `?GL_TEXTURE_SWIZZLE_R'
-%% is `?GL_BLUE', the value for r will be taken from the third channel of the fetched
-%% texel. If `?GL_TEXTURE_SWIZZLE_R' is `?GL_ALPHA', the value for r will be taken
-%% from the fourth channel of the fetched texel. If `?GL_TEXTURE_SWIZZLE_R' is `?GL_ZERO'
-%% , the value for r will be subtituted with 0.0. If `?GL_TEXTURE_SWIZZLE_R' is `?GL_ONE'
-%% , the value for r will be subtituted with 1.0. The initial value is `?GL_RED'.
-%%
-%%
-%%
-%% `?GL_TEXTURE_SWIZZLE_G': Sets the swizzle that will be applied to the g component
-%% of a texel before it is returned to the shader. Valid values for `Param' and their
-%% effects are similar to those of `?GL_TEXTURE_SWIZZLE_R'. The initial value is `?GL_GREEN'
-%% .
-%%
-%%
-%%
-%% `?GL_TEXTURE_SWIZZLE_B': Sets the swizzle that will be applied to the b component
-%% of a texel before it is returned to the shader. Valid values for `Param' and their
-%% effects are similar to those of `?GL_TEXTURE_SWIZZLE_R'. The initial value is `?GL_BLUE'
-%% .
-%%
-%%
-%%
-%% `?GL_TEXTURE_SWIZZLE_A': Sets the swizzle that will be applied to the a component
-%% of a texel before it is returned to the shader. Valid values for `Param' and their
-%% effects are similar to those of `?GL_TEXTURE_SWIZZLE_R'. The initial value is `?GL_ALPHA'
-%% .
-%%
-%%
-%%
-%% `?GL_TEXTURE_SWIZZLE_RGBA': Sets the swizzles that will be applied to the r, g,
-%% b, and a components of a texel before they are returned to the shader. Valid values for `Params'
-%% and their effects are similar to those of `?GL_TEXTURE_SWIZZLE_R', except that all
-%% channels are specified simultaneously. Setting the value of `?GL_TEXTURE_SWIZZLE_RGBA'
-%% is equivalent (assuming no errors are generated) to setting the parameters of each of `?GL_TEXTURE_SWIZZLE_R'
-%% , `?GL_TEXTURE_SWIZZLE_G', `?GL_TEXTURE_SWIZZLE_B', and `?GL_TEXTURE_SWIZZLE_A'
-%% successively.
-%%
-%%
-%%
-%% `?GL_TEXTURE_WRAP_S': Sets the wrap parameter for texture coordinate s to either `?GL_CLAMP_TO_EDGE'
-%% , `?GL_CLAMP_TO_BORDER', `?GL_MIRRORED_REPEAT', or `?GL_REPEAT'. `?GL_CLAMP_TO_EDGE'
-%% causes s coordinates to be clamped to the range [(1 2/N) 1-(1 2/N)], where N is the size of the texture
-%% in the direction of clamping. `?GL_CLAMP_TO_BORDER' evaluates s coordinates in a
-%% similar manner to `?GL_CLAMP_TO_EDGE'. However, in cases where clamping would have
-%% occurred in `?GL_CLAMP_TO_EDGE' mode, the fetched texel data is substituted with
-%% the values specified by `?GL_TEXTURE_BORDER_COLOR'. `?GL_REPEAT' causes the
-%% integer part of the s coordinate to be ignored; the GL uses only the fractional part,
-%% thereby creating a repeating pattern. `?GL_MIRRORED_REPEAT' causes the s coordinate
-%% to be set to the fractional part of the texture coordinate if the integer part of s
-%% is even; if the integer part of s is odd, then the s texture coordinate is set to 1-
-%% frac(s), where frac(s) represents the fractional part of s. Initially, `?GL_TEXTURE_WRAP_S'
-%% is set to `?GL_REPEAT'.
-%%
-%%
-%%
-%% `?GL_TEXTURE_WRAP_T': Sets the wrap parameter for texture coordinate t to either `?GL_CLAMP_TO_EDGE'
-%% , `?GL_CLAMP_TO_BORDER', `?GL_MIRRORED_REPEAT', or `?GL_REPEAT'. See the
-%% discussion under `?GL_TEXTURE_WRAP_S'. Initially, `?GL_TEXTURE_WRAP_T' is set
-%% to `?GL_REPEAT'.
-%%
-%%
-%%
-%% `?GL_TEXTURE_WRAP_R': Sets the wrap parameter for texture coordinate r to either `?GL_CLAMP_TO_EDGE'
-%% , `?GL_CLAMP_TO_BORDER', `?GL_MIRRORED_REPEAT', or `?GL_REPEAT'. See the
-%% discussion under `?GL_TEXTURE_WRAP_S'. Initially, `?GL_TEXTURE_WRAP_R' is set
-%% to `?GL_REPEAT'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexParameter.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexParameter.xhtml">external</a> documentation.
-spec texParameterf(Target, Pname, Param) -> 'ok' when Target :: enum(),Pname :: enum(),Param :: float().
texParameterf(Target,Pname,Param) ->
cast(5258, <<Target:?GLenum,Pname:?GLenum,Param:?GLfloat>>).
@@ -6486,70 +2612,7 @@ texParameteriv(Target,Pname,Params) ->
%% rectangle, cube-mapped or cube-mapped array texturing, respectively. `Pname' accepts
%% the same symbols as {@link gl:texParameterf/3} , with the same interpretations:
%%
-%% `?GL_TEXTURE_MAG_FILTER': Returns the single-valued texture magnification filter,
-%% a symbolic constant. The initial value is `?GL_LINEAR'.
-%%
-%% `?GL_TEXTURE_MIN_FILTER': Returns the single-valued texture minification filter,
-%% a symbolic constant. The initial value is `?GL_NEAREST_MIPMAP_LINEAR'.
-%%
-%% `?GL_TEXTURE_MIN_LOD': Returns the single-valued texture minimum level-of-detail
-%% value. The initial value is -1000.
-%%
-%% `?GL_TEXTURE_MAX_LOD': Returns the single-valued texture maximum level-of-detail
-%% value. The initial value is 1000.
-%%
-%% `?GL_TEXTURE_BASE_LEVEL': Returns the single-valued base texture mipmap level. The
-%% initial value is 0.
-%%
-%% `?GL_TEXTURE_MAX_LEVEL': Returns the single-valued maximum texture mipmap array
-%% level. The initial value is 1000.
-%%
-%% `?GL_TEXTURE_SWIZZLE_R': Returns the red component swizzle. The initial value is `?GL_RED'
-%% .
-%%
-%% `?GL_TEXTURE_SWIZZLE_G': Returns the green component swizzle. The initial value is `?GL_GREEN'
-%% .
-%%
-%% `?GL_TEXTURE_SWIZZLE_B': Returns the blue component swizzle. The initial value is `?GL_BLUE'
-%% .
-%%
-%% `?GL_TEXTURE_SWIZZLE_A': Returns the alpha component swizzle. The initial value is `?GL_ALPHA'
-%% .
-%%
-%% `?GL_TEXTURE_SWIZZLE_RGBA': Returns the component swizzle for all channels in a
-%% single query.
-%%
-%% `?GL_TEXTURE_WRAP_S': Returns the single-valued wrapping function for texture coordinate
-%% s, a symbolic constant. The initial value is `?GL_REPEAT'.
-%%
-%% `?GL_TEXTURE_WRAP_T': Returns the single-valued wrapping function for texture coordinate
-%% t, a symbolic constant. The initial value is `?GL_REPEAT'.
-%%
-%% `?GL_TEXTURE_WRAP_R': Returns the single-valued wrapping function for texture coordinate
-%% r, a symbolic constant. The initial value is `?GL_REPEAT'.
-%%
-%% `?GL_TEXTURE_BORDER_COLOR': Returns four integer or floating-point numbers that
-%% comprise the RGBA color of the texture border. Floating-point values are returned in the
-%% range [0 1]. Integer values are returned as a linear mapping of the internal floating-point
-%% representation such that 1.0 maps to the most positive representable integer and -1.0
-%% maps to the most negative representable integer. The initial value is (0, 0, 0, 0).
-%%
-%% `?GL_TEXTURE_COMPARE_MODE': Returns a single-valued texture comparison mode, a symbolic
-%% constant. The initial value is `?GL_NONE'. See {@link gl:texParameterf/3} .
-%%
-%% `?GL_TEXTURE_COMPARE_FUNC': Returns a single-valued texture comparison function,
-%% a symbolic constant. The initial value is `?GL_LEQUAL'. See {@link gl:texParameterf/3} .
-%%
-%%
-%% In addition to the parameters that may be set with {@link gl:texParameterf/3} , ``gl:getTexParameter''
-%% accepts the following read-only parameters:
-%%
-%% `?GL_TEXTURE_IMMUTABLE_FORMAT': Returns non-zero if the texture has an immutable
-%% format. Textures become immutable if their storage is specified with {@link gl:texStorage1D/4}
-%% , {@link gl:texStorage2D/5} or {@link gl:texStorage3D/6} . The initial value is `?GL_FALSE'
-%% .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexParameter.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetTexParameter.xhtml">external</a> documentation.
-spec getTexParameterfv(Target, Pname) -> {float(),float(),float(),float()} when Target :: enum(),Pname :: enum().
getTexParameterfv(Target,Pname) ->
call(5262, <<Target:?GLenum,Pname:?GLenum>>).
@@ -6570,67 +2633,7 @@ getTexParameteriv(Target,Pname) ->
%% , `?GL_TEXTURE_CUBE_MAP_POSITIVE_Z', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Z', or `?GL_PROXY_TEXTURE_CUBE_MAP'
%% .
%%
-%% `?GL_MAX_TEXTURE_SIZE', and `?GL_MAX_3D_TEXTURE_SIZE' are not really descriptive
-%% enough. It has to report the largest square texture image that can be accommodated with
-%% mipmaps and borders, but a long skinny texture, or a texture without mipmaps and borders,
-%% may easily fit in texture memory. The proxy targets allow the user to more accurately
-%% query whether the GL can accommodate a texture of a given configuration. If the texture
-%% cannot be accommodated, the texture state variables, which may be queried with ``gl:getTexLevelParameter''
-%% , are set to 0. If the texture can be accommodated, the texture state values will be set
-%% as they would be set for a non-proxy target.
-%%
-%% `Pname' specifies the texture parameter whose value or values will be returned.
-%%
-%% The accepted parameter names are as follows:
-%%
-%% `?GL_TEXTURE_WIDTH': `Params' returns a single value, the width of the texture
-%% image. This value includes the border of the texture image. The initial value is 0.
-%%
-%% `?GL_TEXTURE_HEIGHT': `Params' returns a single value, the height of the texture
-%% image. This value includes the border of the texture image. The initial value is 0.
-%%
-%% `?GL_TEXTURE_DEPTH': `Params' returns a single value, the depth of the texture
-%% image. This value includes the border of the texture image. The initial value is 0.
-%%
-%% `?GL_TEXTURE_INTERNAL_FORMAT': `Params' returns a single value, the internal
-%% format of the texture image.
-%%
-%% `?GL_TEXTURE_RED_TYPE',
-%%
-%% `?GL_TEXTURE_GREEN_TYPE',
-%%
-%% `?GL_TEXTURE_BLUE_TYPE',
-%%
-%% `?GL_TEXTURE_ALPHA_TYPE',
-%%
-%% `?GL_TEXTURE_DEPTH_TYPE': The data type used to store the component. The types `?GL_NONE'
-%% , `?GL_SIGNED_NORMALIZED', `?GL_UNSIGNED_NORMALIZED', `?GL_FLOAT', `?GL_INT'
-%% , and `?GL_UNSIGNED_INT' may be returned to indicate signed normalized fixed-point,
-%% unsigned normalized fixed-point, floating-point, integer unnormalized, and unsigned integer
-%% unnormalized components, respectively.
-%%
-%% `?GL_TEXTURE_RED_SIZE',
-%%
-%% `?GL_TEXTURE_GREEN_SIZE',
-%%
-%% `?GL_TEXTURE_BLUE_SIZE',
-%%
-%% `?GL_TEXTURE_ALPHA_SIZE',
-%%
-%% `?GL_TEXTURE_DEPTH_SIZE': The internal storage resolution of an individual component.
-%% The resolution chosen by the GL will be a close match for the resolution requested by
-%% the user with the component argument of {@link gl:texImage1D/8} , {@link gl:texImage2D/9} , {@link gl:texImage3D/10}
-%% , {@link gl:copyTexImage1D/7} , and {@link gl:copyTexImage2D/8} . The initial value is 0.
-%%
-%% `?GL_TEXTURE_COMPRESSED': `Params' returns a single boolean value indicating
-%% if the texture image is stored in a compressed internal format. The initiali value is `?GL_FALSE'
-%% .
-%%
-%% `?GL_TEXTURE_COMPRESSED_IMAGE_SIZE': `Params' returns a single integer value,
-%% the number of unsigned bytes of the compressed texture image that would be returned from {@link gl:getCompressedTexImage/3}
-%% .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexLevelParameter.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetTexLevelParameter.xhtml">external</a> documentation.
-spec getTexLevelParameterfv(Target, Level, Pname) -> {float()} when Target :: enum(),Level :: integer(),Pname :: enum().
getTexLevelParameterfv(Target,Level,Pname) ->
call(5264, <<Target:?GLenum,Level:?GLint,Pname:?GLenum>>).
@@ -6647,107 +2650,7 @@ getTexLevelParameteriv(Target,Level,Pname) ->
%% which texturing is enabled. To enable and disable one-dimensional texturing, call {@link gl:enable/1}
%% and {@link gl:enable/1} with argument `?GL_TEXTURE_1D'.
%%
-%% Texture images are defined with ``gl:texImage1D''. The arguments describe the parameters
-%% of the texture image, such as width, width of the border, level-of-detail number (see {@link gl:texParameterf/3}
-%% ), and the internal resolution and format used to store the image. The last three arguments
-%% describe how the image is represented in memory.
-%%
-%% If `Target' is `?GL_PROXY_TEXTURE_1D', no data is read from `Data' , but
-%% all of the texture image state is recalculated, checked for consistency, and checked against
-%% the implementation's capabilities. If the implementation cannot handle a texture of the
-%% requested texture size, it sets all of the image state to 0, but does not generate an
-%% error (see {@link gl:getError/0} ). To query for an entire mipmap array, use an image array
-%% level greater than or equal to 1.
-%%
-%% If `Target' is `?GL_TEXTURE_1D', data is read from `Data' as a sequence
-%% of signed or unsigned bytes, shorts, or longs, or single-precision floating-point values,
-%% depending on `Type' . These values are grouped into sets of one, two, three, or four
-%% values, depending on `Format' , to form elements. Each data byte is treated as eight
-%% 1-bit elements, with bit ordering determined by `?GL_UNPACK_LSB_FIRST' (see {@link gl:pixelStoref/2}
-%% ).
-%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated
-%% as a byte offset into the buffer object's data store.
-%%
-%% The first element corresponds to the left end of the texture array. Subsequent elements
-%% progress left-to-right through the remaining texels in the texture array. The final element
-%% corresponds to the right end of the texture array.
-%%
-%% `Format' determines the composition of each element in `Data' . It can assume
-%% one of these symbolic values:
-%%
-%% `?GL_RED': Each element is a single red component. The GL converts it to floating
-%% point and assembles it into an RGBA element by attaching 0 for green and blue, and 1 for
-%% alpha. Each component is then multiplied by the signed scale factor `?GL_c_SCALE',
-%% added to the signed bias `?GL_c_BIAS', and clamped to the range [0,1].
-%%
-%% `?GL_RG': Each element is a single red/green double The GL converts it to floating
-%% point and assembles it into an RGBA element by attaching 0 for blue, and 1 for alpha.
-%% Each component is then multiplied by the signed scale factor `?GL_c_SCALE', added
-%% to the signed bias `?GL_c_BIAS', and clamped to the range [0,1].
-%%
-%% `?GL_RGB'
-%%
-%% `?GL_BGR': Each element is an RGB triple. The GL converts it to floating point and
-%% assembles it into an RGBA element by attaching 1 for alpha. Each component is then multiplied
-%% by the signed scale factor `?GL_c_SCALE', added to the signed bias `?GL_c_BIAS',
-%% and clamped to the range [0,1].
-%%
-%% `?GL_RGBA'
-%%
-%% `?GL_BGRA': Each element contains all four components. Each component is multiplied
-%% by the signed scale factor `?GL_c_SCALE', added to the signed bias `?GL_c_BIAS',
-%% and clamped to the range [0,1].
-%%
-%% `?GL_DEPTH_COMPONENT': Each element is a single depth value. The GL converts it
-%% to floating point, multiplies by the signed scale factor `?GL_DEPTH_SCALE', adds
-%% the signed bias `?GL_DEPTH_BIAS', and clamps to the range [0,1].
-%%
-%% If an application wants to store the texture at a certain resolution or in a certain
-%% format, it can request the resolution and format with `InternalFormat' . The GL will
-%% choose an internal representation that closely approximates that requested by `InternalFormat'
-%% , but it may not match exactly. (The representations specified by `?GL_RED', `?GL_RG'
-%% , `?GL_RGB' and `?GL_RGBA' must match exactly.)
-%%
-%% `InternalFormat' may be one of the base internal formats shown in Table 1, below
-%%
-%% `InternalFormat' may also be one of the sized internal formats shown in Table 2,
-%% below
-%%
-%% Finally, `InternalFormat' may also be one of the generic or compressed compressed
-%% texture formats shown in Table 3 below
-%%
-%% If the `InternalFormat' parameter is one of the generic compressed formats, `?GL_COMPRESSED_RED'
-%% , `?GL_COMPRESSED_RG', `?GL_COMPRESSED_RGB', or `?GL_COMPRESSED_RGBA',
-%% the GL will replace the internal format with the symbolic constant for a specific internal
-%% format and compress the texture before storage. If no corresponding internal format is
-%% available, or the GL can not compress that image for any reason, the internal format is
-%% instead replaced with a corresponding base internal format.
-%%
-%% If the `InternalFormat' parameter is `?GL_SRGB', `?GL_SRGB8', `?GL_SRGB_ALPHA'
-%% or `?GL_SRGB8_ALPHA8', the texture is treated as if the red, green, or blue components
-%% are encoded in the sRGB color space. Any alpha component is left unchanged. The conversion
-%% from the sRGB encoded component c s to a linear component c l is:
-%%
-%% c l={ c s/12.92if c s&amp;le; 0.04045( c s+0.055/1.055) 2.4if c s&gt; 0.04045
-%%
-%% Assume c s is the sRGB component in the range [0,1].
-%%
-%% Use the `?GL_PROXY_TEXTURE_1D' target to try out a resolution and format. The implementation
-%% will update and recompute its best match for the requested storage resolution and format.
-%% To then query this state, call {@link gl:getTexLevelParameterfv/3} . If the texture cannot
-%% be accommodated, texture state is set to 0.
-%%
-%% A one-component texture image uses only the red component of the RGBA color from `Data'
-%% . A two-component image uses the R and A values. A three-component image uses the R, G,
-%% and B values. A four-component image uses all of the RGBA components.
-%%
-%% Image-based shadowing can be enabled by comparing texture r coordinates to depth texture
-%% values to generate a boolean result. See {@link gl:texParameterf/3} for details on texture
-%% comparison.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage1D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage1D.xhtml">external</a> documentation.
-spec texImage1D(Target, Level, InternalFormat, Width, Border, Format, Type, Pixels) -> 'ok' when Target :: enum(),Level :: integer(),InternalFormat :: integer(),Width :: integer(),Border :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem().
texImage1D(Target,Level,InternalFormat,Width,Border,Format,Type,Pixels) when is_integer(Pixels) ->
cast(5266, <<Target:?GLenum,Level:?GLint,InternalFormat:?GLint,Width:?GLsizei,Border:?GLint,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
@@ -6759,117 +2662,7 @@ texImage1D(Target,Level,InternalFormat,Width,Border,Format,Type,Pixels) ->
%%
%% Texturing allows elements of an image array to be read by shaders.
%%
-%% To define texture images, call ``gl:texImage2D''. The arguments describe the parameters
-%% of the texture image, such as height, width, width of the border, level-of-detail number
-%% (see {@link gl:texParameterf/3} ), and number of color components provided. The last three
-%% arguments describe how the image is represented in memory.
-%%
-%% If `Target' is `?GL_PROXY_TEXTURE_2D', `?GL_PROXY_TEXTURE_1D_ARRAY', `?GL_PROXY_TEXTURE_CUBE_MAP'
-%% , or `?GL_PROXY_TEXTURE_RECTANGLE', no data is read from `Data' , but all of
-%% the texture image state is recalculated, checked for consistency, and checked against
-%% the implementation's capabilities. If the implementation cannot handle a texture of the
-%% requested texture size, it sets all of the image state to 0, but does not generate an
-%% error (see {@link gl:getError/0} ). To query for an entire mipmap array, use an image array
-%% level greater than or equal to 1.
-%%
-%% If `Target' is `?GL_TEXTURE_2D', `?GL_TEXTURE_RECTANGLE' or one of the `?GL_TEXTURE_CUBE_MAP'
-%% targets, data is read from `Data' as a sequence of signed or unsigned bytes, shorts,
-%% or longs, or single-precision floating-point values, depending on `Type' . These values
-%% are grouped into sets of one, two, three, or four values, depending on `Format' ,
-%% to form elements. Each data byte is treated as eight 1-bit elements, with bit ordering
-%% determined by `?GL_UNPACK_LSB_FIRST' (see {@link gl:pixelStoref/2} ).
-%%
-%% If `Target' is `?GL_TEXTURE_1D_ARRAY', data is interpreted as an array of one-dimensional
-%% images.
-%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated
-%% as a byte offset into the buffer object's data store.
-%%
-%% The first element corresponds to the lower left corner of the texture image. Subsequent
-%% elements progress left-to-right through the remaining texels in the lowest row of the
-%% texture image, and then in successively higher rows of the texture image. The final element
-%% corresponds to the upper right corner of the texture image.
-%%
-%% `Format' determines the composition of each element in `Data' . It can assume
-%% one of these symbolic values:
-%%
-%% `?GL_RED': Each element is a single red component. The GL converts it to floating
-%% point and assembles it into an RGBA element by attaching 0 for green and blue, and 1 for
-%% alpha. Each component is then multiplied by the signed scale factor `?GL_c_SCALE',
-%% added to the signed bias `?GL_c_BIAS', and clamped to the range [0,1].
-%%
-%% `?GL_RG': Each element is a red/green double. The GL converts it to floating point
-%% and assembles it into an RGBA element by attaching 0 for blue, and 1 for alpha. Each component
-%% is then multiplied by the signed scale factor `?GL_c_SCALE', added to the signed
-%% bias `?GL_c_BIAS', and clamped to the range [0,1].
-%%
-%% `?GL_RGB'
-%%
-%% `?GL_BGR': Each element is an RGB triple. The GL converts it to floating point and
-%% assembles it into an RGBA element by attaching 1 for alpha. Each component is then multiplied
-%% by the signed scale factor `?GL_c_SCALE', added to the signed bias `?GL_c_BIAS',
-%% and clamped to the range [0,1].
-%%
-%% `?GL_RGBA'
-%%
-%% `?GL_BGRA': Each element contains all four components. Each component is multiplied
-%% by the signed scale factor `?GL_c_SCALE', added to the signed bias `?GL_c_BIAS',
-%% and clamped to the range [0,1].
-%%
-%% `?GL_DEPTH_COMPONENT': Each element is a single depth value. The GL converts it
-%% to floating point, multiplies by the signed scale factor `?GL_DEPTH_SCALE', adds
-%% the signed bias `?GL_DEPTH_BIAS', and clamps to the range [0,1].
-%%
-%% `?GL_DEPTH_STENCIL': Each element is a pair of depth and stencil values. The depth
-%% component of the pair is interpreted as in `?GL_DEPTH_COMPONENT'. The stencil component
-%% is interpreted based on specified the depth + stencil internal format.
-%%
-%% If an application wants to store the texture at a certain resolution or in a certain
-%% format, it can request the resolution and format with `InternalFormat' . The GL will
-%% choose an internal representation that closely approximates that requested by `InternalFormat'
-%% , but it may not match exactly. (The representations specified by `?GL_RED', `?GL_RG'
-%% , `?GL_RGB', and `?GL_RGBA' must match exactly.)
-%%
-%% `InternalFormat' may be one of the base internal formats shown in Table 1, below
-%%
-%% `InternalFormat' may also be one of the sized internal formats shown in Table 2,
-%% below
-%%
-%% Finally, `InternalFormat' may also be one of the generic or compressed compressed
-%% texture formats shown in Table 3 below
-%%
-%% If the `InternalFormat' parameter is one of the generic compressed formats, `?GL_COMPRESSED_RED'
-%% , `?GL_COMPRESSED_RG', `?GL_COMPRESSED_RGB', or `?GL_COMPRESSED_RGBA',
-%% the GL will replace the internal format with the symbolic constant for a specific internal
-%% format and compress the texture before storage. If no corresponding internal format is
-%% available, or the GL can not compress that image for any reason, the internal format is
-%% instead replaced with a corresponding base internal format.
-%%
-%% If the `InternalFormat' parameter is `?GL_SRGB', `?GL_SRGB8', `?GL_SRGB_ALPHA'
-%% , or `?GL_SRGB8_ALPHA8', the texture is treated as if the red, green, or blue components
-%% are encoded in the sRGB color space. Any alpha component is left unchanged. The conversion
-%% from the sRGB encoded component c s to a linear component c l is:
-%%
-%% c l={ c s/12.92if c s&amp;le; 0.04045( c s+0.055/1.055) 2.4if c s&gt; 0.04045
-%%
-%% Assume c s is the sRGB component in the range [0,1].
-%%
-%% Use the `?GL_PROXY_TEXTURE_2D', `?GL_PROXY_TEXTURE_1D_ARRAY', `?GL_PROXY_TEXTURE_RECTANGLE'
-%% , or `?GL_PROXY_TEXTURE_CUBE_MAP' target to try out a resolution and format. The
-%% implementation will update and recompute its best match for the requested storage resolution
-%% and format. To then query this state, call {@link gl:getTexLevelParameterfv/3} . If the texture
-%% cannot be accommodated, texture state is set to 0.
-%%
-%% A one-component texture image uses only the red component of the RGBA color extracted
-%% from `Data' . A two-component image uses the R and G values. A three-component image
-%% uses the R, G, and B values. A four-component image uses all of the RGBA components.
-%%
-%% Image-based shadowing can be enabled by comparing texture r coordinates to depth texture
-%% values to generate a boolean result. See {@link gl:texParameterf/3} for details on texture
-%% comparison.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml">external</a> documentation.
-spec texImage2D(Target, Level, InternalFormat, Width, Height, Border, Format, Type, Pixels) -> 'ok' when Target :: enum(),Level :: integer(),InternalFormat :: integer(),Width :: integer(),Height :: integer(),Border :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem().
texImage2D(Target,Level,InternalFormat,Width,Height,Border,Format,Type,Pixels) when is_integer(Pixels) ->
cast(5268, <<Target:?GLenum,Level:?GLint,InternalFormat:?GLint,Width:?GLsizei,Height:?GLsizei,Border:?GLint,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
@@ -6888,33 +2681,7 @@ texImage2D(Target,Level,InternalFormat,Width,Height,Border,Format,Type,Pixels) -
%% array. See the reference page for {@link gl:texImage1D/8} for a description of the acceptable
%% values for the `Format' and `Type' parameters, respectively.
%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a texture image is requested, `Img' is treated
-%% as a byte offset into the buffer object's data store.
-%%
-%% To understand the operation of ``gl:getTexImage'', consider the selected internal four-component
-%% texture image to be an RGBA color buffer the size of the image. The semantics of ``gl:getTexImage''
-%% are then identical to those of {@link gl:readPixels/7} , with the exception that no pixel
-%% transfer operations are performed, when called with the same `Format' and `Type' ,
-%% with `x' and `y' set to 0, `width' set to the width of the texture image
-%% and `height' set to 1 for 1D images, or to the height of the texture image for 2D
-%% images.
-%%
-%% If the selected texture image does not contain four components, the following mappings
-%% are applied. Single-component textures are treated as RGBA buffers with red set to the
-%% single-component value, green set to 0, blue set to 0, and alpha set to 1. Two-component
-%% textures are treated as RGBA buffers with red set to the value of component zero, alpha
-%% set to the value of component one, and green and blue set to 0. Finally, three-component
-%% textures are treated as RGBA buffers with red set to component zero, green set to component
-%% one, blue set to component two, and alpha set to 1.
-%%
-%% To determine the required size of `Img' , use {@link gl:getTexLevelParameterfv/3} to
-%% determine the dimensions of the internal texture image, then scale the required number
-%% of pixels by the storage required for each pixel, based on `Format' and `Type' .
-%% Be sure to take the pixel storage parameters into account, especially `?GL_PACK_ALIGNMENT'
-%% .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexImage.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetTexImage.xhtml">external</a> documentation.
-spec getTexImage(Target, Level, Format, Type, Pixels) -> 'ok' when Target :: enum(),Level :: integer(),Format :: enum(),Type :: enum(),Pixels :: mem().
getTexImage(Target,Level,Format,Type,Pixels) ->
send_bin(Pixels),
@@ -6926,13 +2693,7 @@ getTexImage(Target,Level,Format,Type,Pixels) ->
%% that the names form a contiguous set of integers; however, it is guaranteed that none
%% of the returned names was in use immediately before the call to ``gl:genTextures''.
%%
-%% The generated textures have no dimensionality; they assume the dimensionality of the
-%% texture target to which they are first bound (see {@link gl:bindTexture/2} ).
-%%
-%% Texture names returned by a call to ``gl:genTextures'' are not returned by subsequent
-%% calls, unless they are first deleted with {@link gl:deleteTextures/1} .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenTextures.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenTextures.xhtml">external</a> documentation.
-spec genTextures(N) -> [integer()] when N :: integer().
genTextures(N) ->
call(5271, <<N:?GLsizei>>).
@@ -6944,10 +2705,7 @@ genTextures(N) ->
%% for reuse (for example by {@link gl:genTextures/1} ). If a texture that is currently bound
%% is deleted, the binding reverts to 0 (the default texture).
%%
-%% ``gl:deleteTextures'' silently ignores 0's and names that do not correspond to existing
-%% textures.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteTextures.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteTextures.xhtml">external</a> documentation.
-spec deleteTextures(Textures) -> 'ok' when Textures :: [integer()].
deleteTextures(Textures) ->
TexturesLen = length(Textures),
@@ -6964,43 +2722,7 @@ deleteTextures(Textures) ->
%% When a texture is bound to a target, the previous binding for that target is automatically
%% broken.
%%
-%% Texture names are unsigned integers. The value zero is reserved to represent the default
-%% texture for each texture target. Texture names and the corresponding texture contents
-%% are local to the shared object space of the current GL rendering context; two rendering
-%% contexts share texture names only if they explicitly enable sharing between contexts through
-%% the appropriate GL windows interfaces functions.
-%%
-%% You must use {@link gl:genTextures/1} to generate a set of new texture names.
-%%
-%% When a texture is first bound, it assumes the specified target: A texture first bound
-%% to `?GL_TEXTURE_1D' becomes one-dimensional texture, a texture first bound to `?GL_TEXTURE_2D'
-%% becomes two-dimensional texture, a texture first bound to `?GL_TEXTURE_3D' becomes
-%% three-dimensional texture, a texture first bound to `?GL_TEXTURE_1D_ARRAY' becomes
-%% one-dimensional array texture, a texture first bound to `?GL_TEXTURE_2D_ARRAY' becomes
-%% two-dimensional arary texture, a texture first bound to `?GL_TEXTURE_RECTANGLE' becomes
-%% rectangle texture, a, texture first bound to `?GL_TEXTURE_CUBE_MAP' becomes a cube-mapped
-%% texture, a texture first bound to `?GL_TEXTURE_2D_MULTISAMPLE' becomes a two-dimensional
-%% multisampled texture, and a texture first bound to `?GL_TEXTURE_2D_MULTISAMPLE_ARRAY'
-%% becomes a two-dimensional multisampled array texture. The state of a one-dimensional texture
-%% immediately after it is first bound is equivalent to the state of the default `?GL_TEXTURE_1D'
-%% at GL initialization, and similarly for the other texture types.
-%%
-%% While a texture is bound, GL operations on the target to which it is bound affect the
-%% bound texture, and queries of the target to which it is bound return state from the bound
-%% texture. In effect, the texture targets become aliases for the textures currently bound
-%% to them, and the texture name zero refers to the default textures that were bound to them
-%% at initialization.
-%%
-%% A texture binding created with ``gl:bindTexture'' remains active until a different
-%% texture is bound to the same target, or until the bound texture is deleted with {@link gl:deleteTextures/1}
-%% .
-%%
-%% Once created, a named texture may be re-bound to its same original target as often as
-%% needed. It is usually much faster to use ``gl:bindTexture'' to bind an existing named
-%% texture to one of the texture targets than it is to reload the texture image using {@link gl:texImage1D/8}
-%% , {@link gl:texImage2D/9} , {@link gl:texImage3D/10} or another similar function.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindTexture.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindTexture.xhtml">external</a> documentation.
-spec bindTexture(Target, Texture) -> 'ok' when Target :: enum(),Texture :: integer().
bindTexture(Target,Texture) ->
cast(5273, <<Target:?GLenum,Texture:?GLuint>>).
@@ -7010,26 +2732,7 @@ bindTexture(Target,Texture) ->
%% ``gl:prioritizeTextures'' assigns the `N' texture priorities given in `Priorities'
%% to the `N' textures named in `Textures' .
%%
-%% The GL establishes a ``working set'' of textures that are resident in texture memory.
-%% These textures may be bound to a texture target much more efficiently than textures that
-%% are not resident. By specifying a priority for each texture, ``gl:prioritizeTextures''
-%% allows applications to guide the GL implementation in determining which textures should
-%% be resident.
-%%
-%% The priorities given in `Priorities' are clamped to the range [0 1] before they are
-%% assigned. 0 indicates the lowest priority; textures with priority 0 are least likely to
-%% be resident. 1 indicates the highest priority; textures with priority 1 are most likely
-%% to be resident. However, textures are not guaranteed to be resident until they are used.
-%%
-%% ``gl:prioritizeTextures'' silently ignores attempts to prioritize texture 0 or any texture
-%% name that does not correspond to an existing texture.
-%%
-%% ``gl:prioritizeTextures'' does not require that any of the textures named by `Textures'
-%% be bound to a texture target. {@link gl:texParameterf/3} may also be used to set a texture's
-%% priority, but only if the texture is currently bound. This is the only way to set the
-%% priority of a default texture.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPrioritizeTextures.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPrioritizeTextures.xml">external</a> documentation.
-spec prioritizeTextures(Textures, Priorities) -> 'ok' when Textures :: [integer()],Priorities :: [clamp()].
prioritizeTextures(Textures,Priorities) ->
TexturesLen = length(Textures),
@@ -7044,20 +2747,7 @@ prioritizeTextures(Textures,Priorities) ->
%% textures can be bound to a texture target much more efficiently than textures that are
%% not resident.
%%
-%% ``gl:areTexturesResident'' queries the texture residence status of the `N' textures
-%% named by the elements of `Textures' . If all the named textures are resident, ``gl:areTexturesResident''
-%% returns `?GL_TRUE', and the contents of `Residences' are undisturbed. If not
-%% all the named textures are resident, ``gl:areTexturesResident'' returns `?GL_FALSE',
-%% and detailed status is returned in the `N' elements of `Residences' . If an element
-%% of `Residences' is `?GL_TRUE', then the texture named by the corresponding element
-%% of `Textures' is resident.
-%%
-%% The residence status of a single bound texture may also be queried by calling {@link gl:getTexParameterfv/2}
-%% with the `target' argument set to the target to which the texture is bound, and
-%% the `pname' argument set to `?GL_TEXTURE_RESIDENT'. This is the only way that
-%% the residence status of a default texture can be queried.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAreTexturesResident.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glAreTexturesResident.xml">external</a> documentation.
-spec areTexturesResident(Textures) -> {0|1,Residences :: [0|1]} when Textures :: [integer()].
areTexturesResident(Textures) ->
TexturesLen = length(Textures),
@@ -7070,17 +2760,14 @@ areTexturesResident(Textures) ->
%% a texture. If `Texture' is zero, or is a non-zero value that is not currently the
%% name of a texture, or if an error occurs, ``gl:isTexture'' returns `?GL_FALSE'.
%%
-%% A name returned by {@link gl:genTextures/1} , but not yet associated with a texture by
-%% calling {@link gl:bindTexture/2} , is not the name of a texture.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsTexture.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsTexture.xhtml">external</a> documentation.
-spec isTexture(Texture) -> 0|1 when Texture :: integer().
isTexture(Texture) ->
call(5276, <<Texture:?GLuint>>).
%% @doc glTexSubImage
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec texSubImage1D(Target, Level, Xoffset, Width, Format, Type, Pixels) -> 'ok' when Target :: enum(),Level :: integer(),Xoffset :: integer(),Width :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem().
texSubImage1D(Target,Level,Xoffset,Width,Format,Type,Pixels) when is_integer(Pixels) ->
cast(5277, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Width:?GLsizei,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
@@ -7090,7 +2777,7 @@ texSubImage1D(Target,Level,Xoffset,Width,Format,Type,Pixels) ->
%% @doc glTexSubImage
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec texSubImage2D(Target, Level, Xoffset, Yoffset, Width, Height, Format, Type, Pixels) -> 'ok' when Target :: enum(),Level :: integer(),Xoffset :: integer(),Yoffset :: integer(),Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem().
texSubImage2D(Target,Level,Xoffset,Yoffset,Width,Height,Format,Type,Pixels) when is_integer(Pixels) ->
cast(5279, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
@@ -7103,30 +2790,7 @@ texSubImage2D(Target,Level,Xoffset,Yoffset,Width,Height,Format,Type,Pixels) ->
%% ``gl:copyTexImage1D'' defines a one-dimensional texture image with pixels from the current
%% `?GL_READ_BUFFER'.
%%
-%% The screen-aligned pixel row with left corner at (x y) and with a length of width+2(border) defines
-%% the texture array at the mipmap level specified by `Level' . `Internalformat'
-%% specifies the internal format of the texture array.
-%%
-%% The pixels in the row are processed exactly as if {@link gl:readPixels/7} had been called,
-%% but the process stops just before final conversion. At this point all pixel component
-%% values are clamped to the range [0 1] and then converted to the texture's internal format
-%% for storage in the texel array.
-%%
-%% Pixel ordering is such that lower x screen coordinates correspond to lower texture
-%% coordinates.
-%%
-%% If any of the pixels within the specified row of the current `?GL_READ_BUFFER' are
-%% outside the window associated with the current rendering context, then the values obtained
-%% for those pixels are undefined.
-%%
-%% ``gl:copyTexImage1D'' defines a one-dimensional texture image with pixels from the current
-%% `?GL_READ_BUFFER'.
-%%
-%% When `Internalformat' is one of the sRGB types, the GL does not automatically convert
-%% the source pixels to the sRGB color space. In this case, the ``gl:pixelMap'' function
-%% can be used to accomplish the conversion.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexImage1D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCopyTexImage1D.xhtml">external</a> documentation.
-spec copyTexImage1D(Target, Level, Internalformat, X, Y, Width, Border) -> 'ok' when Target :: enum(),Level :: integer(),Internalformat :: enum(),X :: integer(),Y :: integer(),Width :: integer(),Border :: integer().
copyTexImage1D(Target,Level,Internalformat,X,Y,Width,Border) ->
cast(5281, <<Target:?GLenum,Level:?GLint,Internalformat:?GLenum,X:?GLint,Y:?GLint,Width:?GLsizei,Border:?GLint>>).
@@ -7136,28 +2800,7 @@ copyTexImage1D(Target,Level,Internalformat,X,Y,Width,Border) ->
%% ``gl:copyTexImage2D'' defines a two-dimensional texture image, or cube-map texture image
%% with pixels from the current `?GL_READ_BUFFER'.
%%
-%% The screen-aligned pixel rectangle with lower left corner at ( `X' , `Y' ) and
-%% with a width of width+2(border) and a height of height+2(border) defines the texture array at the mipmap
-%% level specified by `Level' . `Internalformat' specifies the internal format of
-%% the texture array.
-%%
-%% The pixels in the rectangle are processed exactly as if {@link gl:readPixels/7} had been
-%% called, but the process stops just before final conversion. At this point all pixel component
-%% values are clamped to the range [0 1] and then converted to the texture's internal format
-%% for storage in the texel array.
-%%
-%% Pixel ordering is such that lower x and y screen coordinates correspond to lower s
-%% and t texture coordinates.
-%%
-%% If any of the pixels within the specified rectangle of the current `?GL_READ_BUFFER'
-%% are outside the window associated with the current rendering context, then the values
-%% obtained for those pixels are undefined.
-%%
-%% When `Internalformat' is one of the sRGB types, the GL does not automatically convert
-%% the source pixels to the sRGB color space. In this case, the ``gl:pixelMap'' function
-%% can be used to accomplish the conversion.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexImage2D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCopyTexImage2D.xhtml">external</a> documentation.
-spec copyTexImage2D(Target, Level, Internalformat, X, Y, Width, Height, Border) -> 'ok' when Target :: enum(),Level :: integer(),Internalformat :: enum(),X :: integer(),Y :: integer(),Width :: integer(),Height :: integer(),Border :: integer().
copyTexImage2D(Target,Level,Internalformat,X,Y,Width,Height,Border) ->
cast(5282, <<Target:?GLenum,Level:?GLint,Internalformat:?GLenum,X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei,Border:?GLint>>).
@@ -7168,25 +2811,7 @@ copyTexImage2D(Target,Level,Internalformat,X,Y,Width,Height,Border) ->
%% pixels from the current `?GL_READ_BUFFER' (rather than from main memory, as is the
%% case for {@link gl:texSubImage1D/7} ).
%%
-%% The screen-aligned pixel row with left corner at ( `X' , `Y' ), and with length `Width'
-%% replaces the portion of the texture array with x indices `Xoffset' through xoffset
-%% +width-1, inclusive. The destination in the texture array may not include any texels outside
-%% the texture array as it was originally specified.
-%%
-%% The pixels in the row are processed exactly as if {@link gl:readPixels/7} had been called,
-%% but the process stops just before final conversion. At this point, all pixel component
-%% values are clamped to the range [0 1] and then converted to the texture's internal format
-%% for storage in the texel array.
-%%
-%% It is not an error to specify a subtexture with zero width, but such a specification
-%% has no effect. If any of the pixels within the specified row of the current `?GL_READ_BUFFER'
-%% are outside the read window associated with the current rendering context, then the values
-%% obtained for those pixels are undefined.
-%%
-%% No change is made to the `internalformat', `width', or `border' parameters
-%% of the specified texture array or to texel values outside the specified subregion.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage1D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCopyTexSubImage1D.xhtml">external</a> documentation.
-spec copyTexSubImage1D(Target, Level, Xoffset, X, Y, Width) -> 'ok' when Target :: enum(),Level :: integer(),Xoffset :: integer(),X :: integer(),Y :: integer(),Width :: integer().
copyTexSubImage1D(Target,Level,Xoffset,X,Y,Width) ->
cast(5283, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,X:?GLint,Y:?GLint,Width:?GLsizei>>).
@@ -7197,36 +2822,14 @@ copyTexSubImage1D(Target,Level,Xoffset,X,Y,Width) ->
%% image or cube-map texture image with pixels from the current `?GL_READ_BUFFER' (rather
%% than from main memory, as is the case for {@link gl:texSubImage1D/7} ).
%%
-%% The screen-aligned pixel rectangle with lower left corner at (x y) and with width `Width'
-%% and height `Height' replaces the portion of the texture array with x indices `Xoffset'
-%% through xoffset+width-1, inclusive, and y indices `Yoffset' through yoffset+height
-%% -1, inclusive, at the mipmap level specified by `Level' .
-%%
-%% The pixels in the rectangle are processed exactly as if {@link gl:readPixels/7} had been
-%% called, but the process stops just before final conversion. At this point, all pixel component
-%% values are clamped to the range [0 1] and then converted to the texture's internal format
-%% for storage in the texel array.
-%%
-%% The destination rectangle in the texture array may not include any texels outside the
-%% texture array as it was originally specified. It is not an error to specify a subtexture
-%% with zero width or height, but such a specification has no effect.
-%%
-%% If any of the pixels within the specified rectangle of the current `?GL_READ_BUFFER'
-%% are outside the read window associated with the current rendering context, then the values
-%% obtained for those pixels are undefined.
-%%
-%% No change is made to the `internalformat', `width', `height', or `border'
-%% parameters of the specified texture array or to texel values outside the specified subregion.
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage2D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCopyTexSubImage2D.xhtml">external</a> documentation.
-spec copyTexSubImage2D(Target, Level, Xoffset, Yoffset, X, Y, Width, Height) -> 'ok' when Target :: enum(),Level :: integer(),Xoffset :: integer(),Yoffset :: integer(),X :: integer(),Y :: integer(),Width :: integer(),Height :: integer().
copyTexSubImage2D(Target,Level,Xoffset,Yoffset,X,Y,Width,Height) ->
cast(5284, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei>>).
%% @doc glMap
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMap.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec map1d(Target, U1, U2, Stride, Order, Points) -> 'ok' when Target :: enum(),U1 :: float(),U2 :: float(),Stride :: integer(),Order :: integer(),Points :: binary().
map1d(Target,U1,U2,Stride,Order,Points) ->
send_bin(Points),
@@ -7234,7 +2837,7 @@ map1d(Target,U1,U2,Stride,Order,Points) ->
%% @doc glMap
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMap.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec map1f(Target, U1, U2, Stride, Order, Points) -> 'ok' when Target :: enum(),U1 :: float(),U2 :: float(),Stride :: integer(),Order :: integer(),Points :: binary().
map1f(Target,U1,U2,Stride,Order,Points) ->
send_bin(Points),
@@ -7242,7 +2845,7 @@ map1f(Target,U1,U2,Stride,Order,Points) ->
%% @doc glMap
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMap.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec map2d(Target, U1, U2, Ustride, Uorder, V1, V2, Vstride, Vorder, Points) -> 'ok' when Target :: enum(),U1 :: float(),U2 :: float(),Ustride :: integer(),Uorder :: integer(),V1 :: float(),V2 :: float(),Vstride :: integer(),Vorder :: integer(),Points :: binary().
map2d(Target,U1,U2,Ustride,Uorder,V1,V2,Vstride,Vorder,Points) ->
send_bin(Points),
@@ -7250,7 +2853,7 @@ map2d(Target,U1,U2,Ustride,Uorder,V1,V2,Vstride,Vorder,Points) ->
%% @doc glMap
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMap.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec map2f(Target, U1, U2, Ustride, Uorder, V1, V2, Vstride, Vorder, Points) -> 'ok' when Target :: enum(),U1 :: float(),U2 :: float(),Ustride :: integer(),Uorder :: integer(),V1 :: float(),V2 :: float(),Vstride :: integer(),Vorder :: integer(),Points :: binary().
map2f(Target,U1,U2,Ustride,Uorder,V1,V2,Vstride,Vorder,Points) ->
send_bin(Points),
@@ -7262,31 +2865,7 @@ map2f(Target,U1,U2,Ustride,Uorder,V1,V2,Vstride,Vorder,Points) ->
%% parameters. `Target' chooses a map, `Query' selects a specific parameter, and `V'
%% points to storage where the values will be returned.
%%
-%% The acceptable values for the `Target' parameter are described in the {@link gl:map1d/6}
-%% and {@link gl:map1d/6} reference pages.
-%%
-%% `Query' can assume the following values:
-%%
-%% `?GL_COEFF': `V' returns the control points for the evaluator function. One-dimensional
-%% evaluators return order control points, and two-dimensional evaluators return uorder×vorder
-%% control points. Each control point consists of one, two, three, or four integer, single-precision
-%% floating-point, or double-precision floating-point values, depending on the type of the
-%% evaluator. The GL returns two-dimensional control points in row-major order, incrementing
-%% the uorder index quickly and the vorder index after each row. Integer values, when
-%% requested, are computed by rounding the internal floating-point values to the nearest
-%% integer values.
-%%
-%% `?GL_ORDER': `V' returns the order of the evaluator function. One-dimensional
-%% evaluators return a single value, order. The initial value is 1. Two-dimensional evaluators
-%% return two values, uorder and vorder. The initial value is 1,1.
-%%
-%% `?GL_DOMAIN': `V' returns the linear u and v mapping parameters. One-dimensional
-%% evaluators return two values, u1 and u2, as specified by {@link gl:map1d/6} . Two-dimensional
-%% evaluators return four values ( u1, u2, v1, and v2) as specified by {@link gl:map1d/6} .
-%% Integer values, when requested, are computed by rounding the internal floating-point values
-%% to the nearest integer values.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMap.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetMap.xml">external</a> documentation.
-spec getMapdv(Target, Query, V) -> 'ok' when Target :: enum(),Query :: enum(),V :: mem().
getMapdv(Target,Query,V) ->
send_bin(V),
@@ -7313,45 +2892,7 @@ getMapiv(Target,Query,V) ->
%% To define a map, call {@link gl:map1d/6} and {@link gl:map1d/6} ; to enable and disable it,
%% call {@link gl:enable/1} and {@link gl:enable/1} .
%%
-%% When one of the ``gl:evalCoord'' commands is issued, all currently enabled maps of
-%% the indicated dimension are evaluated. Then, for each enabled map, it is as if the corresponding
-%% GL command had been issued with the computed value. That is, if `?GL_MAP1_INDEX' or `?GL_MAP2_INDEX'
-%% is enabled, a {@link gl:indexd/1} command is simulated. If `?GL_MAP1_COLOR_4' or `?GL_MAP2_COLOR_4'
-%% is enabled, a {@link gl:color3b/3} command is simulated. If `?GL_MAP1_NORMAL' or `?GL_MAP2_NORMAL'
-%% is enabled, a normal vector is produced, and if any of `?GL_MAP1_TEXTURE_COORD_1', `?GL_MAP1_TEXTURE_COORD_2'
-%% , `?GL_MAP1_TEXTURE_COORD_3', `?GL_MAP1_TEXTURE_COORD_4', `?GL_MAP2_TEXTURE_COORD_1'
-%% , `?GL_MAP2_TEXTURE_COORD_2', `?GL_MAP2_TEXTURE_COORD_3', or `?GL_MAP2_TEXTURE_COORD_4'
-%% is enabled, then an appropriate {@link gl:texCoord1d/1} command is simulated.
-%%
-%% For color, color index, normal, and texture coordinates the GL uses evaluated values
-%% instead of current values for those evaluations that are enabled, and current values otherwise,
-%% However, the evaluated values do not update the current values. Thus, if {@link gl:vertex2d/2}
-%% commands are interspersed with ``gl:evalCoord'' commands, the color, normal, and texture
-%% coordinates associated with the {@link gl:vertex2d/2} commands are not affected by the values
-%% generated by the ``gl:evalCoord'' commands, but only by the most recent {@link gl:color3b/3}
-%% , {@link gl:indexd/1} , {@link gl:normal3b/3} , and {@link gl:texCoord1d/1} commands.
-%%
-%% No commands are issued for maps that are not enabled. If more than one texture evaluation
-%% is enabled for a particular dimension (for example, `?GL_MAP2_TEXTURE_COORD_1' and `?GL_MAP2_TEXTURE_COORD_2'
-%% ), then only the evaluation of the map that produces the larger number of coordinates
-%% (in this case, `?GL_MAP2_TEXTURE_COORD_2') is carried out. `?GL_MAP1_VERTEX_4'
-%% overrides `?GL_MAP1_VERTEX_3', and `?GL_MAP2_VERTEX_4' overrides `?GL_MAP2_VERTEX_3'
-%% , in the same manner. If neither a three- nor a four-component vertex map is enabled for
-%% the specified dimension, the ``gl:evalCoord'' command is ignored.
-%%
-%% If you have enabled automatic normal generation, by calling {@link gl:enable/1} with argument
-%% `?GL_AUTO_NORMAL', ``gl:evalCoord2'' generates surface normals analytically, regardless
-%% of the contents or enabling of the `?GL_MAP2_NORMAL' map. Let
-%%
-%% m=((&amp;PartialD; p)/(&amp;PartialD; u))×((&amp;PartialD; p)/(&amp;PartialD; v))
-%%
-%% Then the generated normal n is n=m/(||m||)
-%%
-%% If automatic normal generation is disabled, the corresponding normal map `?GL_MAP2_NORMAL'
-%% , if enabled, is used to produce a normal. If neither automatic normal generation nor
-%% a normal map is enabled, no normal is generated for ``gl:evalCoord2'' commands.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glEvalCoord.xml">external</a> documentation.
-spec evalCoord1d(U) -> 'ok' when U :: float().
evalCoord1d(U) ->
cast(5292, <<U:?GLdouble>>).
@@ -7397,31 +2938,7 @@ evalCoord2fv({U,V}) -> evalCoord2f(U,V).
%% the integer domain of a one- or two-dimensional grid, whose range is the domain of the
%% evaluation maps specified by {@link gl:map1d/6} and {@link gl:map1d/6} .
%%
-%% ``gl:mapGrid1'' and ``gl:mapGrid2'' specify the linear grid mappings between the i
-%% (or i and j) integer grid coordinates, to the u (or u and v) floating-point
-%% evaluation map coordinates. See {@link gl:map1d/6} and {@link gl:map1d/6} for details of how
-%% u and v coordinates are evaluated.
-%%
-%% ``gl:mapGrid1'' specifies a single linear mapping such that integer grid coordinate
-%% 0 maps exactly to `U1' , and integer grid coordinate `Un' maps exactly to `U2'
-%% . All other integer grid coordinates i are mapped so that
-%%
-%% u=i(u2-u1)/un+u1
-%%
-%% ``gl:mapGrid2'' specifies two such linear mappings. One maps integer grid coordinate
-%% i=0 exactly to `U1' , and integer grid coordinate i=un exactly to `U2' . The
-%% other maps integer grid coordinate j=0 exactly to `V1' , and integer grid coordinate
-%% j=vn exactly to `V2' . Other integer grid coordinates i and j are mapped such
-%% that
-%%
-%% u=i(u2-u1)/un+u1
-%%
-%% v=j(v2-v1)/vn+v1
-%%
-%% The mappings specified by ``gl:mapGrid'' are used identically by {@link gl:evalMesh1/3}
-%% and {@link gl:evalPoint1/1} .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMapGrid.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glMapGrid.xml">external</a> documentation.
-spec mapGrid1d(Un, U1, U2) -> 'ok' when Un :: integer(),U1 :: float(),U2 :: float().
mapGrid1d(Un,U1,U2) ->
cast(5296, <<Un:?GLint,0:32,U1:?GLdouble,U2:?GLdouble>>).
@@ -7452,23 +2969,7 @@ mapGrid2f(Un,U1,U2,Vn,V1,V2) ->
%% . Calling ``gl:evalPoint1'' is equivalent to calling glEvalCoord1( i.&amp;Delta; u+u
%% 1 ); where &amp;Delta; u=(u 2-u 1)/n
%%
-%% and n, u 1, and u 2 are the arguments to the most recent {@link gl:mapGrid1d/3} command.
-%% The one absolute numeric requirement is that if i=n, then the value computed from i.&amp;Delta;
-%% u+u 1 is exactly u 2.
-%%
-%% In the two-dimensional case, ``gl:evalPoint2'', let
-%%
-%% &amp;Delta; u=(u 2-u 1)/n
-%%
-%% &amp;Delta; v=(v 2-v 1)/m
-%%
-%% where n, u 1, u 2, m, v 1, and v 2 are the arguments to the most recent {@link gl:mapGrid1d/3}
-%% command. Then the ``gl:evalPoint2'' command is equivalent to calling glEvalCoord2( i.
-%% &amp;Delta; u+u 1, j.&amp;Delta; v+v 1 ); The only absolute numeric requirements are
-%% that if i=n, then the value computed from i.&amp;Delta; u+u 1 is exactly u 2, and
-%% if j=m, then the value computed from j.&amp;Delta; v+v 1 is exactly v 2.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEvalPoint.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glEvalPoint.xml">external</a> documentation.
-spec evalPoint1(I) -> 'ok' when I :: integer().
evalPoint1(I) ->
cast(5300, <<I:?GLint>>).
@@ -7487,53 +2988,7 @@ evalPoint2(I,J) ->
%% evaluation maps specified by {@link gl:map1d/6} and {@link gl:map1d/6} . `Mode' determines
%% whether the resulting vertices are connected as points, lines, or filled polygons.
%%
-%% In the one-dimensional case, ``gl:evalMesh1'', the mesh is generated as if the following
-%% code fragment were executed:
-%%
-%% glBegin( `Type' ); for ( i = `I1' ; i &lt;= `I2' ; i += 1 ) glEvalCoord1(
-%% i.&amp;Delta; u+u 1 ); glEnd(); where
-%%
-%% &amp;Delta; u=(u 2-u 1)/n
-%%
-%% and n, u 1, and u 2 are the arguments to the most recent {@link gl:mapGrid1d/3} command.
-%% `type' is `?GL_POINTS' if `Mode' is `?GL_POINT', or `?GL_LINES'
-%% if `Mode' is `?GL_LINE'.
-%%
-%% The one absolute numeric requirement is that if i=n, then the value computed from i.&amp;Delta;
-%% u+u 1 is exactly u 2.
-%%
-%% In the two-dimensional case, ``gl:evalMesh2'', let .cp &amp;Delta; u=(u 2-u 1)/n
-%%
-%% &amp;Delta; v=(v 2-v 1)/m
-%%
-%% where n, u 1, u 2, m, v 1, and v 2 are the arguments to the most recent {@link gl:mapGrid1d/3}
-%% command. Then, if `Mode' is `?GL_FILL', the ``gl:evalMesh2'' command is equivalent
-%% to:
-%%
-%% for ( j = `J1' ; j &lt; `J2' ; j += 1 ) { glBegin( GL_QUAD_STRIP ); for ( i = `I1'
-%% ; i &lt;= `I2' ; i += 1 ) { glEvalCoord2( i.&amp;Delta; u+u 1, j.&amp;Delta; v+v 1
-%% ); glEvalCoord2( i.&amp;Delta; u+u 1,(j+1).&amp;Delta; v+v 1 ); } glEnd(); }
-%%
-%% If `Mode' is `?GL_LINE', then a call to ``gl:evalMesh2'' is equivalent to:
-%%
-%% for ( j = `J1' ; j &lt;= `J2' ; j += 1 ) { glBegin( GL_LINE_STRIP ); for ( i = `I1'
-%% ; i &lt;= `I2' ; i += 1 ) glEvalCoord2( i.&amp;Delta; u+u 1, j.&amp;Delta; v+v 1
-%% ); glEnd(); } for ( i = `I1' ; i &lt;= `I2' ; i += 1 ) { glBegin( GL_LINE_STRIP
-%% ); for ( j = `J1' ; j &lt;= `J1' ; j += 1 ) glEvalCoord2( i.&amp;Delta; u+u 1, j.
-%% &amp;Delta; v+v 1 ); glEnd(); }
-%%
-%% And finally, if `Mode' is `?GL_POINT', then a call to ``gl:evalMesh2'' is
-%% equivalent to:
-%%
-%% glBegin( GL_POINTS ); for ( j = `J1' ; j &lt;= `J2' ; j += 1 ) for ( i = `I1'
-%% ; i &lt;= `I2' ; i += 1 ) glEvalCoord2( i.&amp;Delta; u+u 1, j.&amp;Delta; v+v 1
-%% ); glEnd();
-%%
-%% In all three cases, the only absolute numeric requirements are that if i=n, then the
-%% value computed from i.&amp;Delta; u+u 1 is exactly u 2, and if j=m, then the value
-%% computed from j.&amp;Delta; v+v 1 is exactly v 2.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEvalMesh.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glEvalMesh.xml">external</a> documentation.
-spec evalMesh1(Mode, I1, I2) -> 'ok' when Mode :: enum(),I1 :: integer(),I2 :: integer().
evalMesh1(Mode,I1,I2) ->
cast(5302, <<Mode:?GLenum,I1:?GLint,I2:?GLint>>).
@@ -7550,66 +3005,7 @@ evalMesh2(Mode,I1,I2,J1,J2) ->
%% pixel blocks, but not buffer clear operations. To enable and disable fog, call {@link gl:enable/1}
%% and {@link gl:enable/1} with argument `?GL_FOG'.
%%
-%% ``gl:fog'' assigns the value or values in `Params' to the fog parameter specified
-%% by `Pname' . The following values are accepted for `Pname' :
-%%
-%% `?GL_FOG_MODE': `Params' is a single integer or floating-point value that specifies
-%% the equation to be used to compute the fog blend factor, f. Three symbolic constants
-%% are accepted: `?GL_LINEAR', `?GL_EXP', and `?GL_EXP2'. The equations corresponding
-%% to these symbolic constants are defined below. The initial fog mode is `?GL_EXP'.
-%%
-%% `?GL_FOG_DENSITY': `Params' is a single integer or floating-point value that
-%% specifies density, the fog density used in both exponential fog equations. Only nonnegative
-%% densities are accepted. The initial fog density is 1.
-%%
-%% `?GL_FOG_START': `Params' is a single integer or floating-point value that specifies
-%% start, the near distance used in the linear fog equation. The initial near distance
-%% is 0.
-%%
-%% `?GL_FOG_END': `Params' is a single integer or floating-point value that specifies
-%% end, the far distance used in the linear fog equation. The initial far distance is 1.
-%%
-%% `?GL_FOG_INDEX': `Params' is a single integer or floating-point value that specifies
-%% i f, the fog color index. The initial fog index is 0.
-%%
-%% `?GL_FOG_COLOR': `Params' contains four integer or floating-point values that
-%% specify C f, the fog color. Integer values are mapped linearly such that the most positive
-%% representable value maps to 1.0, and the most negative representable value maps to -1.0.
-%% Floating-point values are mapped directly. After conversion, all color components are
-%% clamped to the range [0 1]. The initial fog color is (0, 0, 0, 0).
-%%
-%% `?GL_FOG_COORD_SRC': `Params' contains either of the following symbolic constants:
-%% `?GL_FOG_COORD' or `?GL_FRAGMENT_DEPTH'. `?GL_FOG_COORD' specifies that
-%% the current fog coordinate should be used as distance value in the fog color computation.
-%% `?GL_FRAGMENT_DEPTH' specifies that the current fragment depth should be used as
-%% distance value in the fog computation.
-%%
-%% Fog blends a fog color with each rasterized pixel fragment's post-texturing color using
-%% a blending factor f. Factor f is computed in one of three ways, depending on the fog
-%% mode. Let c be either the distance in eye coordinate from the origin (in the case that
-%% the `?GL_FOG_COORD_SRC' is `?GL_FRAGMENT_DEPTH') or the current fog coordinate
-%% (in the case that `?GL_FOG_COORD_SRC' is `?GL_FOG_COORD'). The equation for `?GL_LINEAR'
-%% fog is f=(end-c)/(end-start)
-%%
-%% The equation for `?GL_EXP' fog is f=e(-(density. c))
-%%
-%% The equation for `?GL_EXP2' fog is f=e(-(density. c)) 2
-%%
-%% Regardless of the fog mode, f is clamped to the range [0 1] after it is computed. Then,
-%% if the GL is in RGBA color mode, the fragment's red, green, and blue colors, represented
-%% by C r, are replaced by
-%%
-%% (C r)"=f×C r+(1-f)×C f
-%%
-%% Fog does not affect a fragment's alpha component.
-%%
-%% In color index mode, the fragment's color index i r is replaced by
-%%
-%% (i r)"=i r+(1-f)×i f
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFog.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glFog.xml">external</a> documentation.
-spec fogf(Pname, Param) -> 'ok' when Pname :: enum(),Param :: float().
fogf(Pname,Param) ->
cast(5304, <<Pname:?GLenum,Param:?GLfloat>>).
@@ -7642,106 +3038,7 @@ fogiv(Pname,Params) ->
%% about primitives that would have been rasterized is fed back to the application using
%% the GL.
%%
-%% ``gl:feedbackBuffer'' has three arguments: `Buffer' is a pointer to an array of
-%% floating-point values into which feedback information is placed. `Size' indicates
-%% the size of the array. `Type' is a symbolic constant describing the information that
-%% is fed back for each vertex. ``gl:feedbackBuffer'' must be issued before feedback mode
-%% is enabled (by calling {@link gl:renderMode/1} with argument `?GL_FEEDBACK'). Setting
-%% `?GL_FEEDBACK' without establishing the feedback buffer, or calling ``gl:feedbackBuffer''
-%% while the GL is in feedback mode, is an error.
-%%
-%% When {@link gl:renderMode/1} is called while in feedback mode, it returns the number of
-%% entries placed in the feedback array and resets the feedback array pointer to the base
-%% of the feedback buffer. The returned value never exceeds `Size' . If the feedback
-%% data required more room than was available in `Buffer' , {@link gl:renderMode/1} returns
-%% a negative value. To take the GL out of feedback mode, call {@link gl:renderMode/1} with
-%% a parameter value other than `?GL_FEEDBACK'.
-%%
-%% While in feedback mode, each primitive, bitmap, or pixel rectangle that would be rasterized
-%% generates a block of values that are copied into the feedback array. If doing so would
-%% cause the number of entries to exceed the maximum, the block is partially written so as
-%% to fill the array (if there is any room left at all), and an overflow flag is set. Each
-%% block begins with a code indicating the primitive type, followed by values that describe
-%% the primitive's vertices and associated data. Entries are also written for bitmaps and
-%% pixel rectangles. Feedback occurs after polygon culling and {@link gl:polygonMode/2} interpretation
-%% of polygons has taken place, so polygons that are culled are not returned in the feedback
-%% buffer. It can also occur after polygons with more than three edges are broken up into
-%% triangles, if the GL implementation renders polygons by performing this decomposition.
-%%
-%% The {@link gl:passThrough/1} command can be used to insert a marker into the feedback
-%% buffer. See {@link gl:passThrough/1} .
-%%
-%% Following is the grammar for the blocks of values written into the feedback buffer. Each
-%% primitive is indicated with a unique identifying value followed by some number of vertices.
-%% Polygon entries include an integer value indicating how many vertices follow. A vertex
-%% is fed back as some number of floating-point values, as determined by `Type' . Colors
-%% are fed back as four values in RGBA mode and one value in color index mode.
-%%
-%% feedbackList ← feedbackItem feedbackList | feedbackItem
-%%
-%% feedbackItem ← point | lineSegment | polygon | bitmap | pixelRectangle | passThru
-%%
-%% point ←`?GL_POINT_TOKEN' vertex
-%%
-%% lineSegment ←`?GL_LINE_TOKEN' vertex vertex | `?GL_LINE_RESET_TOKEN' vertex
-%% vertex
-%%
-%% polygon ←`?GL_POLYGON_TOKEN' n polySpec
-%%
-%% polySpec ← polySpec vertex | vertex vertex vertex
-%%
-%% bitmap ←`?GL_BITMAP_TOKEN' vertex
-%%
-%% pixelRectangle ←`?GL_DRAW_PIXEL_TOKEN' vertex | `?GL_COPY_PIXEL_TOKEN' vertex
-%%
-%%
-%% passThru ←`?GL_PASS_THROUGH_TOKEN' value
-%%
-%% vertex ← 2d | 3d | 3dColor | 3dColorTexture | 4dColorTexture
-%%
-%% 2d ← value value
-%%
-%% 3d ← value value value
-%%
-%% 3dColor ← value value value color
-%%
-%% 3dColorTexture ← value value value color tex
-%%
-%% 4dColorTexture ← value value value value color tex
-%%
-%% color ← rgba | index
-%%
-%% rgba ← value value value value
-%%
-%% index ← value
-%%
-%% tex ← value value value value
-%%
-%% `value' is a floating-point number, and `n' is a floating-point integer giving
-%% the number of vertices in the polygon. `?GL_POINT_TOKEN', `?GL_LINE_TOKEN', `?GL_LINE_RESET_TOKEN'
-%% , `?GL_POLYGON_TOKEN', `?GL_BITMAP_TOKEN', `?GL_DRAW_PIXEL_TOKEN', `?GL_COPY_PIXEL_TOKEN'
-%% and `?GL_PASS_THROUGH_TOKEN' are symbolic floating-point constants. `?GL_LINE_RESET_TOKEN'
-%% is returned whenever the line stipple pattern is reset. The data returned as a vertex
-%% depends on the feedback `Type' .
-%%
-%% The following table gives the correspondence between `Type' and the number of values
-%% per vertex. `k' is 1 in color index mode and 4 in RGBA mode.
-%%
-%% <table><tbody><tr><td>` Type '</td><td>` Coordinates '</td><td>` Color '</td>
-%% <td>` Texture '</td><td>` Total Number of Values '</td></tr></tbody><tbody><tr><td>
-%% `?GL_2D'</td><td>`x', `y'</td><td></td><td></td><td> 2 </td></tr><tr><td>`?GL_3D'
-%% </td><td>`x', `y', `z'</td><td></td><td></td><td> 3 </td></tr><tr><td>`?GL_3D_COLOR'
-%% </td><td>`x', `y', `z'</td><td> k</td><td></td><td> 3+k</td></tr><tr><td>`?GL_3D_COLOR_TEXTURE'
-%% </td><td>`x', `y', `z'</td><td> k</td><td> 4 </td><td> 7+k</td></tr><tr><td>
-%% `?GL_4D_COLOR_TEXTURE'</td><td>`x', `y', `z', `w'</td><td> k</td>
-%% <td> 4 </td><td> 8+k</td></tr></tbody></table>
-%%
-%% Feedback vertex coordinates are in window coordinates, except `w', which is in clip
-%% coordinates. Feedback colors are lighted, if lighting is enabled. Feedback texture coordinates
-%% are generated, if texture coordinate generation is enabled. They are always transformed
-%% by the texture matrix.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFeedbackBuffer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glFeedbackBuffer.xml">external</a> documentation.
-spec feedbackBuffer(Size, Type, Buffer) -> 'ok' when Size :: integer(),Type :: enum(),Buffer :: mem().
feedbackBuffer(Size,Type,Buffer) ->
send_bin(Buffer),
@@ -7749,18 +3046,9 @@ feedbackBuffer(Size,Type,Buffer) ->
%% @doc Place a marker in the feedback buffer
%%
-%% Feedback is a GL render mode. The mode is selected by calling {@link gl:renderMode/1}
-%% with `?GL_FEEDBACK'. When the GL is in feedback mode, no pixels are produced by rasterization.
-%% Instead, information about primitives that would have been rasterized is fed back to the
-%% application using the GL. See the {@link gl:feedbackBuffer/3} reference page for a description
-%% of the feedback buffer and the values in it.
-%%
-%% ``gl:passThrough'' inserts a user-defined marker in the feedback buffer when it is executed
-%% in feedback mode. `Token' is returned as if it were a primitive; it is indicated
-%% with its own unique identifying value: `?GL_PASS_THROUGH_TOKEN'. The order of ``gl:passThrough''
-%% commands with respect to the specification of graphics primitives is maintained.
+%%
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPassThrough.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPassThrough.xml">external</a> documentation.
-spec passThrough(Token) -> 'ok' when Token :: float().
passThrough(Token) ->
cast(5309, <<Token:?GLfloat>>).
@@ -7774,38 +3062,7 @@ passThrough(Token) ->
%% must be issued before selection mode is enabled, and it must not be issued while the
%% rendering mode is `?GL_SELECT'.
%%
-%% A programmer can use selection to determine which primitives are drawn into some region
-%% of a window. The region is defined by the current modelview and perspective matrices.
-%%
-%% In selection mode, no pixel fragments are produced from rasterization. Instead, if a
-%% primitive or a raster position intersects the clipping volume defined by the viewing frustum
-%% and the user-defined clipping planes, this primitive causes a selection hit. (With polygons,
-%% no hit occurs if the polygon is culled.) When a change is made to the name stack, or when
-%% {@link gl:renderMode/1} is called, a hit record is copied to `Buffer' if any hits
-%% have occurred since the last such event (name stack change or {@link gl:renderMode/1} call).
-%% The hit record consists of the number of names in the name stack at the time of the event,
-%% followed by the minimum and maximum depth values of all vertices that hit since the previous
-%% event, followed by the name stack contents, bottom name first.
-%%
-%% Depth values (which are in the range [0,1]) are multiplied by 2 32-1, before being
-%% placed in the hit record.
-%%
-%% An internal index into `Buffer' is reset to 0 whenever selection mode is entered.
-%% Each time a hit record is copied into `Buffer' , the index is incremented to point
-%% to the cell just past the end of the block of names(emthat is, to the next available cell
-%% If the hit record is larger than the number of remaining locations in `Buffer' , as
-%% much data as can fit is copied, and the overflow flag is set. If the name stack is empty
-%% when a hit record is copied, that record consists of 0 followed by the minimum and maximum
-%% depth values.
-%%
-%% To exit selection mode, call {@link gl:renderMode/1} with an argument other than `?GL_SELECT'
-%% . Whenever {@link gl:renderMode/1} is called while the render mode is `?GL_SELECT',
-%% it returns the number of hit records copied to `Buffer' , resets the overflow flag
-%% and the selection buffer pointer, and initializes the name stack to be empty. If the overflow
-%% bit was set when {@link gl:renderMode/1} was called, a negative hit record count is returned.
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSelectBuffer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glSelectBuffer.xml">external</a> documentation.
-spec selectBuffer(Size, Buffer) -> 'ok' when Size :: integer(),Buffer :: mem().
selectBuffer(Size,Buffer) ->
send_bin(Buffer),
@@ -7817,10 +3074,7 @@ selectBuffer(Size,Buffer) ->
%% uniquely identified. It consists of an ordered set of unsigned integers. ``gl:initNames''
%% causes the name stack to be initialized to its default empty state.
%%
-%% The name stack is always empty while the render mode is not `?GL_SELECT'. Calls to ``gl:initNames''
-%% while the render mode is not `?GL_SELECT' are ignored.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glInitNames.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glInitNames.xml">external</a> documentation.
-spec initNames() -> 'ok'.
initNames() ->
cast(5311, <<>>).
@@ -7831,12 +3085,7 @@ initNames() ->
%% uniquely identified. It consists of an ordered set of unsigned integers and is initially
%% empty.
%%
-%% ``gl:loadName'' causes `Name' to replace the value on the top of the name stack.
-%%
-%% The name stack is always empty while the render mode is not `?GL_SELECT'. Calls to ``gl:loadName''
-%% while the render mode is not `?GL_SELECT' are ignored.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadName.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLoadName.xml">external</a> documentation.
-spec loadName(Name) -> 'ok' when Name :: integer().
loadName(Name) ->
cast(5312, <<Name:?GLuint>>).
@@ -7847,20 +3096,7 @@ loadName(Name) ->
%% uniquely identified. It consists of an ordered set of unsigned integers and is initially
%% empty.
%%
-%% ``gl:pushName'' causes `Name' to be pushed onto the name stack. {@link gl:pushName/1}
-%% pops one name off the top of the stack.
-%%
-%% The maximum name stack depth is implementation-dependent; call `?GL_MAX_NAME_STACK_DEPTH'
-%% to find out the value for a particular implementation. It is an error to push a name
-%% onto a full stack or to pop a name off an empty stack. It is also an error to manipulate
-%% the name stack between the execution of {@link gl:'begin'/1} and the corresponding execution
-%% of {@link gl:'begin'/1} . In any of these cases, the error flag is set and no other change is
-%% made to GL state.
-%%
-%% The name stack is always empty while the render mode is not `?GL_SELECT'. Calls to ``gl:pushName''
-%% or {@link gl:pushName/1} while the render mode is not `?GL_SELECT' are ignored.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPushName.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPushName.xml">external</a> documentation.
-spec pushName(Name) -> 'ok' when Name :: integer().
pushName(Name) ->
cast(5313, <<Name:?GLuint>>).
@@ -7878,7 +3114,7 @@ popName() ->
%% for a complete description of the blending operations. Initially the `?GL_BLEND_COLOR'
%% is set to (0, 0, 0, 0).
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendColor.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendColor.xhtml">external</a> documentation.
-spec blendColor(Red, Green, Blue, Alpha) -> 'ok' when Red :: clamp(),Green :: clamp(),Blue :: clamp(),Alpha :: clamp().
blendColor(Red,Green,Blue,Alpha) ->
cast(5315, <<Red:?GLclampf,Green:?GLclampf,Blue:?GLclampf,Alpha:?GLclampf>>).
@@ -7891,35 +3127,7 @@ blendColor(Red,Green,Blue,Alpha) ->
%% specifies the blend equation for a single draw buffer whereas ``gl:blendEquation''
%% sets the blend equation for all draw buffers.
%%
-%% These equations use the source and destination blend factors specified by either {@link gl:blendFunc/2}
-%% or {@link gl:blendFuncSeparate/4} . See {@link gl:blendFunc/2} or {@link gl:blendFuncSeparate/4}
-%% for a description of the various blend factors.
-%%
-%% In the equations that follow, source and destination color components are referred to
-%% as (R s G s B s A s) and (R d G d B d A d), respectively. The result color is referred to as (R r G r B r A r). The source and destination
-%% blend factors are denoted (s R s G s B s A) and (d R d G d B d A), respectively. For these equations all color components
-%% are understood to have values in the range [0 1]. <table><tbody><tr><td>` Mode '</td><td>
-%% ` RGB Components '</td><td>` Alpha Component '</td></tr></tbody><tbody><tr><td>`?GL_FUNC_ADD'
-%% </td><td> Rr=R s s R+R d d R Gr=G s s G+G d d G Br=B s s B+B d d B</td><td> Ar=A s
-%% s A+A d d A</td></tr><tr><td>`?GL_FUNC_SUBTRACT'</td><td> Rr=R s s R-R d d R Gr=G
-%% s s G-G d d G Br=B s s B-B d d B</td><td> Ar=A s s A-A d d A</td></tr><tr><td>`?GL_FUNC_REVERSE_SUBTRACT'
-%% </td><td> Rr=R d d R-R s s R Gr=G d d G-G s s G Br=B d d B-B s s B</td><td> Ar=A d
-%% d A-A s s A</td></tr><tr><td>`?GL_MIN'</td><td> Rr=min(R s R d) Gr=min(G s G d) Br=min(B s B d)</td><td> Ar=min
-%% (A s A d)</td></tr><tr><td>`?GL_MAX'</td><td> Rr=max(R s R d) Gr=max(G s G d) Br=max(B s B d)</td><td> Ar=max(A s A d)</td></tr></tbody>
-%% </table>
-%%
-%% The results of these equations are clamped to the range [0 1].
-%%
-%% The `?GL_MIN' and `?GL_MAX' equations are useful for applications that analyze
-%% image data (image thresholding against a constant color, for example). The `?GL_FUNC_ADD'
-%% equation is useful for antialiasing and transparency, among other things.
-%%
-%% Initially, both the RGB blend equation and the alpha blend equation are set to `?GL_FUNC_ADD'
-%% .
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquation.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendEquation.xhtml">external</a> documentation.
-spec blendEquation(Mode) -> 'ok' when Mode :: enum().
blendEquation(Mode) ->
cast(5316, <<Mode:?GLenum>>).
@@ -7931,24 +3139,7 @@ blendEquation(Mode) ->
%% , with the additional constraint that all values in the arrays `Count' must lie between
%% `Start' and `End' , inclusive.
%%
-%% Implementations denote recommended maximum amounts of vertex and index data, which may
-%% be queried by calling {@link gl:getBooleanv/1} with argument `?GL_MAX_ELEMENTS_VERTICES' and `?GL_MAX_ELEMENTS_INDICES'
-%% . If end-start+1 is greater than the value of `?GL_MAX_ELEMENTS_VERTICES', or if `Count'
-%% is greater than the value of `?GL_MAX_ELEMENTS_INDICES', then the call may operate
-%% at reduced performance. There is no requirement that all vertices in the range [start end] be referenced.
-%% However, the implementation may partially process unused vertices, reducing performance
-%% from what could be achieved with an optimal index set.
-%%
-%% When ``gl:drawRangeElements'' is called, it uses `Count' sequential elements from
-%% an enabled array, starting at `Start' to construct a sequence of geometric primitives.
-%% `Mode' specifies what kind of primitives are constructed, and how the array elements
-%% construct these primitives. If more than one array is enabled, each is used.
-%%
-%% Vertex attributes that are modified by ``gl:drawRangeElements'' have an unspecified
-%% value after ``gl:drawRangeElements'' returns. Attributes that aren't modified maintain
-%% their previous values.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawRangeElements.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawRangeElements.xhtml">external</a> documentation.
-spec drawRangeElements(Mode, Start, End, Count, Type, Indices) -> 'ok' when Mode :: enum(),Start :: integer(),End :: integer(),Count :: integer(),Type :: enum(),Indices :: offset()|mem().
drawRangeElements(Mode,Start,End,Count,Type,Indices) when is_integer(Indices) ->
cast(5317, <<Mode:?GLenum,Start:?GLuint,End:?GLuint,Count:?GLsizei,Type:?GLenum,Indices:?GLuint>>);
@@ -7962,101 +3153,7 @@ drawRangeElements(Mode,Start,End,Count,Type,Indices) ->
%% which texturing is enabled. To enable and disable three-dimensional texturing, call {@link gl:enable/1}
%% and {@link gl:enable/1} with argument `?GL_TEXTURE_3D'.
%%
-%% To define texture images, call ``gl:texImage3D''. The arguments describe the parameters
-%% of the texture image, such as height, width, depth, width of the border, level-of-detail
-%% number (see {@link gl:texParameterf/3} ), and number of color components provided. The last
-%% three arguments describe how the image is represented in memory.
-%%
-%% If `Target' is `?GL_PROXY_TEXTURE_3D', no data is read from `Data' , but
-%% all of the texture image state is recalculated, checked for consistency, and checked against
-%% the implementation's capabilities. If the implementation cannot handle a texture of the
-%% requested texture size, it sets all of the image state to 0, but does not generate an
-%% error (see {@link gl:getError/0} ). To query for an entire mipmap array, use an image array
-%% level greater than or equal to 1.
-%%
-%% If `Target' is `?GL_TEXTURE_3D', data is read from `Data' as a sequence
-%% of signed or unsigned bytes, shorts, or longs, or single-precision floating-point values,
-%% depending on `Type' . These values are grouped into sets of one, two, three, or four
-%% values, depending on `Format' , to form elements. Each data byte is treated as eight
-%% 1-bit elements, with bit ordering determined by `?GL_UNPACK_LSB_FIRST' (see {@link gl:pixelStoref/2}
-%% ).
-%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated
-%% as a byte offset into the buffer object's data store.
-%%
-%% The first element corresponds to the lower left corner of the texture image. Subsequent
-%% elements progress left-to-right through the remaining texels in the lowest row of the
-%% texture image, and then in successively higher rows of the texture image. The final element
-%% corresponds to the upper right corner of the texture image.
-%%
-%% `Format' determines the composition of each element in `Data' . It can assume
-%% one of these symbolic values:
-%%
-%% `?GL_RED': Each element is a single red component. The GL converts it to floating
-%% point and assembles it into an RGBA element by attaching 0 for green and blue, and 1 for
-%% alpha. Each component is then multiplied by the signed scale factor `?GL_c_SCALE',
-%% added to the signed bias `?GL_c_BIAS', and clamped to the range [0,1].
-%%
-%% `?GL_RG': Each element is a red and green pair. The GL converts each to floating
-%% point and assembles it into an RGBA element by attaching 0 for blue, and 1 for alpha.
-%% Each component is then multiplied by the signed scale factor `?GL_c_SCALE', added
-%% to the signed bias `?GL_c_BIAS', and clamped to the range [0,1].
-%%
-%% `?GL_RGB'
-%%
-%% `?GL_BGR': Each element is an RGB triple. The GL converts it to floating point and
-%% assembles it into an RGBA element by attaching 1 for alpha. Each component is then multiplied
-%% by the signed scale factor `?GL_c_SCALE', added to the signed bias `?GL_c_BIAS',
-%% and clamped to the range [0,1].
-%%
-%% `?GL_RGBA'
-%%
-%% `?GL_BGRA': Each element contains all four components. Each component is multiplied
-%% by the signed scale factor `?GL_c_SCALE', added to the signed bias `?GL_c_BIAS',
-%% and clamped to the range [0,1].
-%%
-%% If an application wants to store the texture at a certain resolution or in a certain
-%% format, it can request the resolution and format with `InternalFormat' . The GL will
-%% choose an internal representation that closely approximates that requested by `InternalFormat'
-%% , but it may not match exactly. (The representations specified by `?GL_RED', `?GL_RG'
-%% , `?GL_RGB', and `?GL_RGBA' must match exactly.)
-%%
-%% `InternalFormat' may be one of the base internal formats shown in Table 1, below
-%%
-%% `InternalFormat' may also be one of the sized internal formats shown in Table 2,
-%% below
-%%
-%% Finally, `InternalFormat' may also be one of the generic or compressed compressed
-%% texture formats shown in Table 3 below
-%%
-%% If the `InternalFormat' parameter is one of the generic compressed formats, `?GL_COMPRESSED_RED'
-%% , `?GL_COMPRESSED_RG', `?GL_COMPRESSED_RGB', or `?GL_COMPRESSED_RGBA',
-%% the GL will replace the internal format with the symbolic constant for a specific internal
-%% format and compress the texture before storage. If no corresponding internal format is
-%% available, or the GL can not compress that image for any reason, the internal format is
-%% instead replaced with a corresponding base internal format.
-%%
-%% If the `InternalFormat' parameter is `?GL_SRGB', `?GL_SRGB8', `?GL_SRGB_ALPHA'
-%% , or `?GL_SRGB8_ALPHA8', the texture is treated as if the red, green, blue, or
-%% luminance components are encoded in the sRGB color space. Any alpha component is left
-%% unchanged. The conversion from the sRGB encoded component c s to a linear component
-%% c l is:
-%%
-%% c l={ c s/12.92if c s&amp;le; 0.04045( c s+0.055/1.055) 2.4if c s&gt; 0.04045
-%%
-%% Assume c s is the sRGB component in the range [0,1].
-%%
-%% Use the `?GL_PROXY_TEXTURE_3D' target to try out a resolution and format. The implementation
-%% will update and recompute its best match for the requested storage resolution and format.
-%% To then query this state, call {@link gl:getTexLevelParameterfv/3} . If the texture cannot
-%% be accommodated, texture state is set to 0.
-%%
-%% A one-component texture image uses only the red component of the RGBA color extracted
-%% from `Data' . A two-component image uses the R and A values. A three-component image
-%% uses the R, G, and B values. A four-component image uses all of the RGBA components.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage3D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage3D.xhtml">external</a> documentation.
-spec texImage3D(Target, Level, InternalFormat, Width, Height, Depth, Border, Format, Type, Pixels) -> 'ok' when Target :: enum(),Level :: integer(),InternalFormat :: integer(),Width :: integer(),Height :: integer(),Depth :: integer(),Border :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem().
texImage3D(Target,Level,InternalFormat,Width,Height,Depth,Border,Format,Type,Pixels) when is_integer(Pixels) ->
cast(5319, <<Target:?GLenum,Level:?GLint,InternalFormat:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Border:?GLint,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
@@ -8066,7 +3163,7 @@ texImage3D(Target,Level,InternalFormat,Width,Height,Depth,Border,Format,Type,Pix
%% @doc glTexSubImage
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec texSubImage3D(Target, Level, Xoffset, Yoffset, Zoffset, Width, Height, Depth, Format, Type, Pixels) -> 'ok' when Target :: enum(),Level :: integer(),Xoffset :: integer(),Yoffset :: integer(),Zoffset :: integer(),Width :: integer(),Height :: integer(),Depth :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem().
texSubImage3D(Target,Level,Xoffset,Yoffset,Zoffset,Width,Height,Depth,Format,Type,Pixels) when is_integer(Pixels) ->
cast(5321, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Zoffset:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>);
@@ -8080,30 +3177,7 @@ texSubImage3D(Target,Level,Xoffset,Yoffset,Zoffset,Width,Height,Depth,Format,Typ
%% image with pixels from the current `?GL_READ_BUFFER' (rather than from main memory,
%% as is the case for {@link gl:texSubImage1D/7} ).
%%
-%% The screen-aligned pixel rectangle with lower left corner at ( `X' , `Y' ) and
-%% with width `Width' and height `Height' replaces the portion of the texture array
-%% with x indices `Xoffset' through xoffset+width-1, inclusive, and y indices `Yoffset'
-%% through yoffset+height-1, inclusive, at z index `Zoffset' and at the mipmap level
-%% specified by `Level' .
-%%
-%% The pixels in the rectangle are processed exactly as if {@link gl:readPixels/7} had been
-%% called, but the process stops just before final conversion. At this point, all pixel component
-%% values are clamped to the range [0 1] and then converted to the texture's internal format
-%% for storage in the texel array.
-%%
-%% The destination rectangle in the texture array may not include any texels outside the
-%% texture array as it was originally specified. It is not an error to specify a subtexture
-%% with zero width or height, but such a specification has no effect.
-%%
-%% If any of the pixels within the specified rectangle of the current `?GL_READ_BUFFER'
-%% are outside the read window associated with the current rendering context, then the values
-%% obtained for those pixels are undefined.
-%%
-%% No change is made to the `internalformat', `width', `height', `depth',
-%% or `border' parameters of the specified texture array or to texel values outside
-%% the specified subregion.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage3D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCopyTexSubImage3D.xhtml">external</a> documentation.
-spec copyTexSubImage3D(Target, Level, Xoffset, Yoffset, Zoffset, X, Y, Width, Height) -> 'ok' when Target :: enum(),Level :: integer(),Xoffset :: integer(),Yoffset :: integer(),Zoffset :: integer(),X :: integer(),Y :: integer(),Width :: integer(),Height :: integer().
copyTexSubImage3D(Target,Level,Xoffset,Yoffset,Zoffset,X,Y,Width,Height) ->
cast(5323, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Zoffset:?GLint,X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei>>).
@@ -8115,95 +3189,7 @@ copyTexSubImage3D(Target,Level,Xoffset,Yoffset,Zoffset,X,Y,Width,Height) ->
%% lookup table. Use the targets `?GL_PROXY_*' for the first case and the other targets
%% for the second case.
%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a color table is specified, `Data' is treated
-%% as a byte offset into the buffer object's data store.
-%%
-%% If `Target' is `?GL_COLOR_TABLE', `?GL_POST_CONVOLUTION_COLOR_TABLE', or `?GL_POST_COLOR_MATRIX_COLOR_TABLE'
-%% , ``gl:colorTable'' builds a color lookup table from an array of pixels. The pixel array
-%% specified by `Width' , `Format' , `Type' , and `Data' is extracted from
-%% memory and processed just as if {@link gl:drawPixels/5} were called, but processing stops
-%% after the final expansion to RGBA is completed.
-%%
-%% The four scale parameters and the four bias parameters that are defined for the table
-%% are then used to scale and bias the R, G, B, and A components of each pixel. (Use ``gl:colorTableParameter''
-%% to set these scale and bias parameters.)
-%%
-%% Next, the R, G, B, and A values are clamped to the range [0 1]. Each pixel is then converted
-%% to the internal format specified by `Internalformat' . This conversion simply maps
-%% the component values of the pixel (R, G, B, and A) to the values included in the internal
-%% format (red, green, blue, alpha, luminance, and intensity). The mapping is as follows:
-%%
-%% <table><tbody><tr><td>` Internal Format '</td><td>` Red '</td><td>` Green '</td>
-%% <td>` Blue '</td><td>` Alpha '</td><td>` Luminance '</td><td>` Intensity '
-%% </td></tr></tbody><tbody><tr><td>`?GL_ALPHA'</td><td></td><td></td><td></td><td> A </td>
-%% <td></td><td></td></tr><tr><td>`?GL_LUMINANCE'</td><td></td><td></td><td></td><td></td>
-%% <td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td></td><td></td><td></td>
-%% <td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'</td><td></td><td></td><td>
-%% </td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td><td> R </td><td> G </td>
-%% <td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'</td><td> R </td><td>
-%% G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table>
-%%
-%% Finally, the red, green, blue, alpha, luminance, and/or intensity components of the resulting
-%% pixels are stored in the color table. They form a one-dimensional table with indices in
-%% the range [0 width-1].
-%%
-%% If `Target' is `?GL_PROXY_*', ``gl:colorTable'' recomputes and stores the
-%% values of the proxy color table's state variables `?GL_COLOR_TABLE_FORMAT', `?GL_COLOR_TABLE_WIDTH'
-%% , `?GL_COLOR_TABLE_RED_SIZE', `?GL_COLOR_TABLE_GREEN_SIZE', `?GL_COLOR_TABLE_BLUE_SIZE'
-%% , `?GL_COLOR_TABLE_ALPHA_SIZE', `?GL_COLOR_TABLE_LUMINANCE_SIZE', and `?GL_COLOR_TABLE_INTENSITY_SIZE'
-%% . There is no effect on the image or state of any actual color table. If the specified
-%% color table is too large to be supported, then all the proxy state variables listed above
-%% are set to zero. Otherwise, the color table could be supported by ``gl:colorTable''
-%% using the corresponding non-proxy target, and the proxy state variables are set as if
-%% that target were being defined.
-%%
-%% The proxy state variables can be retrieved by calling {@link gl:getColorTableParameterfv/2}
-%% with a target of `?GL_PROXY_*'. This allows the application to decide if a particular
-%% ``gl:colorTable'' command would succeed, and to determine what the resulting color table
-%% attributes would be.
-%%
-%% If a color table is enabled, and its width is non-zero, then its contents are used to
-%% replace a subset of the components of each RGBA pixel group, based on the internal format
-%% of the table.
-%%
-%% Each pixel group has color components (R, G, B, A) that are in the range [0.0 1.0]. The color
-%% components are rescaled to the size of the color lookup table to form an index. Then a
-%% subset of the components based on the internal format of the table are replaced by the
-%% table entry selected by that index. If the color components and contents of the table
-%% are represented as follows:
-%%
-%% <table><tbody><tr><td>` Representation '</td><td>` Meaning '</td></tr></tbody><tbody>
-%% <tr><td>r</td><td> Table index computed from R</td></tr><tr><td>g</td><td> Table index
-%% computed from G</td></tr><tr><td>b</td><td> Table index computed from B</td></tr><tr><td>a
-%% </td><td> Table index computed from A</td></tr><tr><td>L[i]</td><td> Luminance value at
-%% table index i</td></tr><tr><td>I[i]</td><td> Intensity value at table index i</td></tr><tr>
-%% <td>R[i]</td><td> Red value at table index i</td></tr><tr><td>G[i]</td><td> Green value
-%% at table index i</td></tr><tr><td>B[i]</td><td> Blue value at table index i</td></tr><tr><td>
-%% A[i]</td><td> Alpha value at table index i</td></tr></tbody></table>
-%%
-%% then the result of color table lookup is as follows:
-%%
-%% <table><tbody><tr><td></td><td>` Resulting Texture Components '</td></tr><tr><td>` Table Internal Format '
-%% </td><td>` R '</td><td>` G '</td><td>` B '</td><td>` A '</td></tr></tbody>
-%% <tbody><tr><td>`?GL_ALPHA'</td><td>R</td><td>G</td><td>B</td><td>A[a]</td></tr><tr><td>
-%% `?GL_LUMINANCE'</td><td>L[r]</td><td>L[g]</td><td>L[b]</td><td>At</td></tr><tr><td>`?GL_LUMINANCE_ALPHA'
-%% </td><td>L[r]</td><td>L[g]</td><td>L[b]</td><td>A[a]</td></tr><tr><td>`?GL_INTENSITY'</td>
-%% <td>I[r]</td><td>I[g]</td><td>I[b]</td><td>I[a]</td></tr><tr><td>`?GL_RGB'</td><td>R[r]
-%% </td><td>G[g]</td><td>B[b]</td><td>A</td></tr><tr><td>`?GL_RGBA'</td><td>R[r]</td><td>
-%% G[g]</td><td>B[b]</td><td>A[a]</td></tr></tbody></table>
-%%
-%% When `?GL_COLOR_TABLE' is enabled, the colors resulting from the pixel map operation
-%% (if it is enabled) are mapped by the color lookup table before being passed to the convolution
-%% operation. The colors resulting from the convolution operation are modified by the post
-%% convolution color lookup table when `?GL_POST_CONVOLUTION_COLOR_TABLE' is enabled.
-%% These modified colors are then sent to the color matrix operation. Finally, if `?GL_POST_COLOR_MATRIX_COLOR_TABLE'
-%% is enabled, the colors resulting from the color matrix operation are mapped by the post
-%% color matrix color lookup table before being used by the histogram operation.
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorTable.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glColorTable.xml">external</a> documentation.
-spec colorTable(Target, Internalformat, Width, Format, Type, Table) -> 'ok' when Target :: enum(),Internalformat :: enum(),Width :: integer(),Format :: enum(),Type :: enum(),Table :: offset()|mem().
colorTable(Target,Internalformat,Width,Format,Type,Table) when is_integer(Table) ->
cast(5324, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Format:?GLenum,Type:?GLenum,Table:?GLuint>>);
@@ -8218,17 +3204,7 @@ colorTable(Target,Internalformat,Width,Format,Type,Table) ->
%% color table the scale and bias terms apply to; it must be set to `?GL_COLOR_TABLE', `?GL_POST_CONVOLUTION_COLOR_TABLE'
%% , or `?GL_POST_COLOR_MATRIX_COLOR_TABLE'.
%%
-%% `Pname' must be `?GL_COLOR_TABLE_SCALE' to set the scale factors. In this case,
-%% `Params' points to an array of four values, which are the scale factors for red,
-%% green, blue, and alpha, in that order.
-%%
-%% `Pname' must be `?GL_COLOR_TABLE_BIAS' to set the bias terms. In this case, `Params'
-%% points to an array of four values, which are the bias terms for red, green, blue, and
-%% alpha, in that order.
-%%
-%% The color tables themselves are specified by calling {@link gl:colorTable/6} .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorTableParameter.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glColorTableParameter.xml">external</a> documentation.
-spec colorTableParameterfv(Target, Pname, Params) -> 'ok' when Target :: enum(),Pname :: enum(),Params :: {float(),float(),float(),float()}.
colorTableParameterfv(Target,Pname,{P1,P2,P3,P4}) ->
cast(5326, <<Target:?GLenum,Pname:?GLenum,P1:?GLfloat,P2:?GLfloat,P3:?GLfloat,P4:?GLfloat>>).
@@ -8244,41 +3220,7 @@ colorTableParameteriv(Target,Pname,{P1,P2,P3,P4}) ->
%% ``gl:copyColorTable'' loads a color table with pixels from the current `?GL_READ_BUFFER'
%% (rather than from main memory, as is the case for {@link gl:colorTable/6} ).
%%
-%% The screen-aligned pixel rectangle with lower-left corner at ( `X' , `Y' ) having
-%% width `Width' and height 1 is loaded into the color table. If any pixels within this
-%% region are outside the window that is associated with the GL context, the values obtained
-%% for those pixels are undefined.
-%%
-%% The pixels in the rectangle are processed just as if {@link gl:readPixels/7} were called,
-%% with `Internalformat' set to RGBA, but processing stops after the final conversion
-%% to RGBA.
-%%
-%% The four scale parameters and the four bias parameters that are defined for the table
-%% are then used to scale and bias the R, G, B, and A components of each pixel. The scale
-%% and bias parameters are set by calling {@link gl:colorTableParameterfv/3} .
-%%
-%% Next, the R, G, B, and A values are clamped to the range [0 1]. Each pixel is then converted
-%% to the internal format specified by `Internalformat' . This conversion simply maps
-%% the component values of the pixel (R, G, B, and A) to the values included in the internal
-%% format (red, green, blue, alpha, luminance, and intensity). The mapping is as follows:
-%%
-%% <table><tbody><tr><td>` Internal Format '</td><td>` Red '</td><td>` Green '</td>
-%% <td>` Blue '</td><td>` Alpha '</td><td>` Luminance '</td><td>` Intensity '
-%% </td></tr></tbody><tbody><tr><td>`?GL_ALPHA'</td><td></td><td></td><td></td><td> A </td>
-%% <td></td><td></td></tr><tr><td>`?GL_LUMINANCE'</td><td></td><td></td><td></td><td></td>
-%% <td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td></td><td></td><td></td>
-%% <td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'</td><td></td><td></td><td>
-%% </td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td><td> R </td><td> G </td>
-%% <td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'</td><td> R </td><td>
-%% G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table>
-%%
-%% Finally, the red, green, blue, alpha, luminance, and/or intensity components of the resulting
-%% pixels are stored in the color table. They form a one-dimensional table with indices in
-%% the range [0 width-1].
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyColorTable.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glCopyColorTable.xml">external</a> documentation.
-spec copyColorTable(Target, Internalformat, X, Y, Width) -> 'ok' when Target :: enum(),Internalformat :: enum(),X :: integer(),Y :: integer(),Width :: integer().
copyColorTable(Target,Internalformat,X,Y,Width) ->
cast(5328, <<Target:?GLenum,Internalformat:?GLenum,X:?GLint,Y:?GLint,Width:?GLsizei>>).
@@ -8289,21 +3231,7 @@ copyColorTable(Target,Internalformat,X,Y,Width) ->
%% by `Target' . No pixel transfer operations are performed, but pixel storage modes
%% that are applicable to {@link gl:readPixels/7} are performed.
%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a histogram table is requested, `Table' is treated
-%% as a byte offset into the buffer object's data store.
-%%
-%% Color components that are requested in the specified `Format' , but which are not
-%% included in the internal format of the color lookup table, are returned as zero. The assignments
-%% of internal color components to the components requested by `Format' are <table><tbody>
-%% <tr><td>` Internal Component '</td><td>` Resulting Component '</td></tr></tbody>
-%% <tbody><tr><td> Red </td><td> Red </td></tr><tr><td> Green </td><td> Green </td></tr><tr><td>
-%% Blue </td><td> Blue </td></tr><tr><td> Alpha </td><td> Alpha </td></tr><tr><td> Luminance
-%% </td><td> Red </td></tr><tr><td> Intensity </td><td> Red </td></tr></tbody></table>
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetColorTable.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetColorTable.xml">external</a> documentation.
-spec getColorTable(Target, Format, Type, Table) -> 'ok' when Target :: enum(),Format :: enum(),Type :: enum(),Table :: mem().
getColorTable(Target,Format,Type,Table) ->
send_bin(Table),
@@ -8313,36 +3241,7 @@ getColorTable(Target,Format,Type,Table) ->
%%
%% Returns parameters specific to color table `Target' .
%%
-%% When `Pname' is set to `?GL_COLOR_TABLE_SCALE' or `?GL_COLOR_TABLE_BIAS',
-%% ``gl:getColorTableParameter'' returns the color table scale or bias parameters for the
-%% table specified by `Target' . For these queries, `Target' must be set to `?GL_COLOR_TABLE'
-%% , `?GL_POST_CONVOLUTION_COLOR_TABLE', or `?GL_POST_COLOR_MATRIX_COLOR_TABLE'
-%% and `Params' points to an array of four elements, which receive the scale or bias
-%% factors for red, green, blue, and alpha, in that order.
-%%
-%% ``gl:getColorTableParameter'' can also be used to retrieve the format and size parameters
-%% for a color table. For these queries, set `Target' to either the color table target
-%% or the proxy color table target. The format and size parameters are set by {@link gl:colorTable/6}
-%% .
-%%
-%% The following table lists the format and size parameters that may be queried. For each
-%% symbolic constant listed below for `Pname' , `Params' must point to an array
-%% of the given length and receive the values indicated.
-%%
-%% <table><tbody><tr><td>` Parameter '</td><td>` N '</td><td>` Meaning '</td></tr>
-%% </tbody><tbody><tr><td>`?GL_COLOR_TABLE_FORMAT'</td><td> 1 </td><td> Internal format
-%% (e.g., `?GL_RGBA') </td></tr><tr><td>`?GL_COLOR_TABLE_WIDTH'</td><td> 1 </td><td>
-%% Number of elements in table </td></tr><tr><td>`?GL_COLOR_TABLE_RED_SIZE'</td><td>
-%% 1 </td><td> Size of red component, in bits </td></tr><tr><td>`?GL_COLOR_TABLE_GREEN_SIZE'
-%% </td><td> 1 </td><td> Size of green component </td></tr><tr><td>`?GL_COLOR_TABLE_BLUE_SIZE'
-%% </td><td> 1 </td><td> Size of blue component </td></tr><tr><td>`?GL_COLOR_TABLE_ALPHA_SIZE'
-%% </td><td> 1 </td><td> Size of alpha component </td></tr><tr><td>`?GL_COLOR_TABLE_LUMINANCE_SIZE'
-%% </td><td> 1 </td><td> Size of luminance component </td></tr><tr><td>`?GL_COLOR_TABLE_INTENSITY_SIZE'
-%% </td><td> 1 </td><td> Size of intensity component </td></tr></tbody></table>
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetColorTableParameter.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetColorTableParameter.xml">external</a> documentation.
-spec getColorTableParameterfv(Target, Pname) -> {float(),float(),float(),float()} when Target :: enum(),Pname :: enum().
getColorTableParameterfv(Target,Pname) ->
call(5330, <<Target:?GLenum,Pname:?GLenum>>).
@@ -8362,11 +3261,7 @@ getColorTableParameteriv(Target,Pname) ->
%% originally specified. It is not an error to specify a subtexture with width of 0, but
%% such a specification has no effect.
%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a portion of a color table is respecified, `Data'
-%% is treated as a byte offset into the buffer object's data store.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorSubTable.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glColorSubTable.xml">external</a> documentation.
-spec colorSubTable(Target, Start, Count, Format, Type, Data) -> 'ok' when Target :: enum(),Start :: integer(),Count :: integer(),Format :: enum(),Type :: enum(),Data :: offset()|mem().
colorSubTable(Target,Start,Count,Format,Type,Data) when is_integer(Data) ->
cast(5332, <<Target:?GLenum,Start:?GLsizei,Count:?GLsizei,Format:?GLenum,Type:?GLenum,Data:?GLuint>>);
@@ -8383,7 +3278,7 @@ colorSubTable(Target,Start,Count,Format,Type,Data) ->
%% specified. It is not an error to specify a subtexture with width of 0, but such a specification
%% has no effect.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyColorSubTable.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glCopyColorSubTable.xml">external</a> documentation.
-spec copyColorSubTable(Target, Start, X, Y, Width) -> 'ok' when Target :: enum(),Start :: integer(),X :: integer(),Y :: integer(),Width :: integer().
copyColorSubTable(Target,Start,X,Y,Width) ->
cast(5334, <<Target:?GLenum,Start:?GLsizei,X:?GLint,Y:?GLint,Width:?GLsizei>>).
@@ -8393,50 +3288,7 @@ copyColorSubTable(Target,Start,X,Y,Width) ->
%% ``gl:convolutionFilter1D'' builds a one-dimensional convolution filter kernel from an
%% array of pixels.
%%
-%% The pixel array specified by `Width' , `Format' , `Type' , and `Data'
-%% is extracted from memory and processed just as if {@link gl:drawPixels/5} were called,
-%% but processing stops after the final expansion to RGBA is completed.
-%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a convolution filter is specified, `Data' is
-%% treated as a byte offset into the buffer object's data store.
-%%
-%% The R, G, B, and A components of each pixel are next scaled by the four 1D `?GL_CONVOLUTION_FILTER_SCALE'
-%% parameters and biased by the four 1D `?GL_CONVOLUTION_FILTER_BIAS' parameters. (The
-%% scale and bias parameters are set by {@link gl:convolutionParameterf/3} using the `?GL_CONVOLUTION_1D'
-%% target and the names `?GL_CONVOLUTION_FILTER_SCALE' and `?GL_CONVOLUTION_FILTER_BIAS'
-%% . The parameters themselves are vectors of four values that are applied to red, green,
-%% blue, and alpha, in that order.) The R, G, B, and A values are not clamped to [0,1] at
-%% any time during this process.
-%%
-%% Each pixel is then converted to the internal format specified by `Internalformat' .
-%% This conversion simply maps the component values of the pixel (R, G, B, and A) to the
-%% values included in the internal format (red, green, blue, alpha, luminance, and intensity).
-%% The mapping is as follows:
-%%
-%% <table><tbody><tr><td>` Internal Format '</td><td>` Red '</td><td>` Green '</td>
-%% <td>` Blue '</td><td>` Alpha '</td><td>` Luminance '</td><td>` Intensity '
-%% </td></tr></tbody><tbody><tr><td>`?GL_ALPHA'</td><td></td><td></td><td></td><td> A </td>
-%% <td></td><td></td></tr><tr><td>`?GL_LUMINANCE'</td><td></td><td></td><td></td><td></td>
-%% <td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td></td><td></td><td></td>
-%% <td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'</td><td></td><td></td><td>
-%% </td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td><td> R </td><td> G </td>
-%% <td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'</td><td> R </td><td>
-%% G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table>
-%%
-%% The red, green, blue, alpha, luminance, and/or intensity components of the resulting
-%% pixels are stored in floating-point rather than integer format. They form a one-dimensional
-%% filter kernel image indexed with coordinate `i' such that `i' starts at 0 and
-%% increases from left to right. Kernel location `i' is derived from the `i'th
-%% pixel, counting from 0.
-%%
-%% Note that after a convolution is performed, the resulting color components are also scaled
-%% by their corresponding `?GL_POST_CONVOLUTION_c_SCALE' parameters and biased by their
-%% corresponding `?GL_POST_CONVOLUTION_c_BIAS' parameters (where `c' takes on the
-%% values `RED', `GREEN', `BLUE', and `ALPHA'). These parameters are
-%% set by {@link gl:pixelTransferf/2} .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionFilter1D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glConvolutionFilter1D.xml">external</a> documentation.
-spec convolutionFilter1D(Target, Internalformat, Width, Format, Type, Image) -> 'ok' when Target :: enum(),Internalformat :: enum(),Width :: integer(),Format :: enum(),Type :: enum(),Image :: offset()|mem().
convolutionFilter1D(Target,Internalformat,Width,Format,Type,Image) when is_integer(Image) ->
cast(5335, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Format:?GLenum,Type:?GLenum,Image:?GLuint>>);
@@ -8449,51 +3301,7 @@ convolutionFilter1D(Target,Internalformat,Width,Format,Type,Image) ->
%% ``gl:convolutionFilter2D'' builds a two-dimensional convolution filter kernel from an
%% array of pixels.
%%
-%% The pixel array specified by `Width' , `Height' , `Format' , `Type' ,
-%% and `Data' is extracted from memory and processed just as if {@link gl:drawPixels/5}
-%% were called, but processing stops after the final expansion to RGBA is completed.
-%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a convolution filter is specified, `Data' is
-%% treated as a byte offset into the buffer object's data store.
-%%
-%% The R, G, B, and A components of each pixel are next scaled by the four 2D `?GL_CONVOLUTION_FILTER_SCALE'
-%% parameters and biased by the four 2D `?GL_CONVOLUTION_FILTER_BIAS' parameters. (The
-%% scale and bias parameters are set by {@link gl:convolutionParameterf/3} using the `?GL_CONVOLUTION_2D'
-%% target and the names `?GL_CONVOLUTION_FILTER_SCALE' and `?GL_CONVOLUTION_FILTER_BIAS'
-%% . The parameters themselves are vectors of four values that are applied to red, green,
-%% blue, and alpha, in that order.) The R, G, B, and A values are not clamped to [0,1] at
-%% any time during this process.
-%%
-%% Each pixel is then converted to the internal format specified by `Internalformat' .
-%% This conversion simply maps the component values of the pixel (R, G, B, and A) to the
-%% values included in the internal format (red, green, blue, alpha, luminance, and intensity).
-%% The mapping is as follows:
-%%
-%% <table><tbody><tr><td>` Internal Format '</td><td>` Red '</td><td>` Green '</td>
-%% <td>` Blue '</td><td>` Alpha '</td><td>` Luminance '</td><td>` Intensity '
-%% </td></tr></tbody><tbody><tr><td>`?GL_ALPHA'</td><td></td><td></td><td></td><td> A </td>
-%% <td></td><td></td></tr><tr><td>`?GL_LUMINANCE'</td><td></td><td></td><td></td><td></td>
-%% <td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td></td><td></td><td></td>
-%% <td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'</td><td></td><td></td><td>
-%% </td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td><td> R </td><td> G </td>
-%% <td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'</td><td> R </td><td>
-%% G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table>
-%%
-%% The red, green, blue, alpha, luminance, and/or intensity components of the resulting
-%% pixels are stored in floating-point rather than integer format. They form a two-dimensional
-%% filter kernel image indexed with coordinates `i' and `j' such that `i'
-%% starts at zero and increases from left to right, and `j' starts at zero and increases
-%% from bottom to top. Kernel location `i,j' is derived from the `N'th pixel, where
-%% `N' is `i'+`j'* `Width' .
-%%
-%% Note that after a convolution is performed, the resulting color components are also scaled
-%% by their corresponding `?GL_POST_CONVOLUTION_c_SCALE' parameters and biased by their
-%% corresponding `?GL_POST_CONVOLUTION_c_BIAS' parameters (where `c' takes on the
-%% values `RED', `GREEN', `BLUE', and `ALPHA'). These parameters are
-%% set by {@link gl:pixelTransferf/2} .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionFilter2D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glConvolutionFilter2D.xml">external</a> documentation.
-spec convolutionFilter2D(Target, Internalformat, Width, Height, Format, Type, Image) -> 'ok' when Target :: enum(),Internalformat :: enum(),Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Image :: offset()|mem().
convolutionFilter2D(Target,Internalformat,Width,Height,Format,Type,Image) when is_integer(Image) ->
cast(5337, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum,Image:?GLuint>>);
@@ -8505,36 +3313,7 @@ convolutionFilter2D(Target,Internalformat,Width,Height,Format,Type,Image) ->
%%
%% ``gl:convolutionParameter'' sets the value of a convolution parameter.
%%
-%% `Target' selects the convolution filter to be affected: `?GL_CONVOLUTION_1D', `?GL_CONVOLUTION_2D'
-%% , or `?GL_SEPARABLE_2D' for the 1D, 2D, or separable 2D filter, respectively.
-%%
-%% `Pname' selects the parameter to be changed. `?GL_CONVOLUTION_FILTER_SCALE'
-%% and `?GL_CONVOLUTION_FILTER_BIAS' affect the definition of the convolution filter
-%% kernel; see {@link gl:convolutionFilter1D/6} , {@link gl:convolutionFilter2D/7} , and {@link gl:separableFilter2D/8}
-%% for details. In these cases, `Params' v is an array of four values to be applied
-%% to red, green, blue, and alpha values, respectively. The initial value for `?GL_CONVOLUTION_FILTER_SCALE'
-%% is (1, 1, 1, 1), and the initial value for `?GL_CONVOLUTION_FILTER_BIAS' is (0,
-%% 0, 0, 0).
-%%
-%% A `Pname' value of `?GL_CONVOLUTION_BORDER_MODE' controls the convolution border
-%% mode. The accepted modes are:
-%%
-%% `?GL_REDUCE': The image resulting from convolution is smaller than the source image.
-%% If the filter width is Wf and height is Hf, and the source image width is Ws and
-%% height is Hs, then the convolved image width will be Ws-Wf+1 and height will be Hs-Hf
-%% +1. (If this reduction would generate an image with zero or negative width and/or height,
-%% the output is simply null, with no error generated.) The coordinates of the image resulting
-%% from convolution are zero through Ws-Wf in width and zero through Hs-Hf in height.
-%%
-%% `?GL_CONSTANT_BORDER': The image resulting from convolution is the same size as
-%% the source image, and processed as if the source image were surrounded by pixels with
-%% their color specified by the `?GL_CONVOLUTION_BORDER_COLOR'.
-%%
-%% `?GL_REPLICATE_BORDER': The image resulting from convolution is the same size as
-%% the source image, and processed as if the outermost pixel on the border of the source
-%% image were replicated.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionParameter.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glConvolutionParameter.xml">external</a> documentation.
-spec convolutionParameterf(Target, Pname, Params) -> 'ok' when Target :: enum(),Pname :: enum(),Params :: tuple().
convolutionParameterf(Target,Pname,Params) ->
cast(5339, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
@@ -8561,49 +3340,7 @@ convolutionParameteriv(Target,Pname,{Params}) -> convolutionParameteri(Target,P
%% pixels from the current `?GL_READ_BUFFER' (rather than from main memory, as is the
%% case for {@link gl:convolutionFilter1D/6} ).
%%
-%% The screen-aligned pixel rectangle with lower-left corner at ( `X' , `Y' ), width
-%% `Width' and height 1 is used to define the convolution filter. If any pixels within
-%% this region are outside the window that is associated with the GL context, the values
-%% obtained for those pixels are undefined.
-%%
-%% The pixels in the rectangle are processed exactly as if {@link gl:readPixels/7} had been
-%% called with `format' set to RGBA, but the process stops just before final conversion.
-%% The R, G, B, and A components of each pixel are next scaled by the four 1D `?GL_CONVOLUTION_FILTER_SCALE'
-%% parameters and biased by the four 1D `?GL_CONVOLUTION_FILTER_BIAS' parameters. (The
-%% scale and bias parameters are set by {@link gl:convolutionParameterf/3} using the `?GL_CONVOLUTION_1D'
-%% target and the names `?GL_CONVOLUTION_FILTER_SCALE' and `?GL_CONVOLUTION_FILTER_BIAS'
-%% . The parameters themselves are vectors of four values that are applied to red, green,
-%% blue, and alpha, in that order.) The R, G, B, and A values are not clamped to [0,1] at
-%% any time during this process.
-%%
-%% Each pixel is then converted to the internal format specified by `Internalformat' .
-%% This conversion simply maps the component values of the pixel (R, G, B, and A) to the
-%% values included in the internal format (red, green, blue, alpha, luminance, and intensity).
-%% The mapping is as follows:
-%%
-%% <table><tbody><tr><td>` Internal Format '</td><td>` Red '</td><td>` Green '</td>
-%% <td>` Blue '</td><td>` Alpha '</td><td>` Luminance '</td><td>` Intensity '
-%% </td></tr></tbody><tbody><tr><td>`?GL_ALPHA'</td><td></td><td></td><td></td><td> A </td>
-%% <td></td><td></td></tr><tr><td>`?GL_LUMINANCE'</td><td></td><td></td><td></td><td></td>
-%% <td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td></td><td></td><td></td>
-%% <td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'</td><td></td><td></td><td>
-%% </td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td><td> R </td><td> G </td>
-%% <td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'</td><td> R </td><td>
-%% G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table>
-%%
-%% The red, green, blue, alpha, luminance, and/or intensity components of the resulting
-%% pixels are stored in floating-point rather than integer format.
-%%
-%% Pixel ordering is such that lower x screen coordinates correspond to lower `i' filter
-%% image coordinates.
-%%
-%% Note that after a convolution is performed, the resulting color components are also scaled
-%% by their corresponding `?GL_POST_CONVOLUTION_c_SCALE' parameters and biased by their
-%% corresponding `?GL_POST_CONVOLUTION_c_BIAS' parameters (where `c' takes on the
-%% values `RED', `GREEN', `BLUE', and `ALPHA'). These parameters are
-%% set by {@link gl:pixelTransferf/2} .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyConvolutionFilter1D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glCopyConvolutionFilter1D.xml">external</a> documentation.
-spec copyConvolutionFilter1D(Target, Internalformat, X, Y, Width) -> 'ok' when Target :: enum(),Internalformat :: enum(),X :: integer(),Y :: integer(),Width :: integer().
copyConvolutionFilter1D(Target,Internalformat,X,Y,Width) ->
cast(5341, <<Target:?GLenum,Internalformat:?GLenum,X:?GLint,Y:?GLint,Width:?GLsizei>>).
@@ -8614,50 +3351,7 @@ copyConvolutionFilter1D(Target,Internalformat,X,Y,Width) ->
%% pixels from the current `?GL_READ_BUFFER' (rather than from main memory, as is the
%% case for {@link gl:convolutionFilter2D/7} ).
%%
-%% The screen-aligned pixel rectangle with lower-left corner at ( `X' , `Y' ), width
-%% `Width' and height `Height' is used to define the convolution filter. If any
-%% pixels within this region are outside the window that is associated with the GL context,
-%% the values obtained for those pixels are undefined.
-%%
-%% The pixels in the rectangle are processed exactly as if {@link gl:readPixels/7} had been
-%% called with `format' set to RGBA, but the process stops just before final conversion.
-%% The R, G, B, and A components of each pixel are next scaled by the four 2D `?GL_CONVOLUTION_FILTER_SCALE'
-%% parameters and biased by the four 2D `?GL_CONVOLUTION_FILTER_BIAS' parameters. (The
-%% scale and bias parameters are set by {@link gl:convolutionParameterf/3} using the `?GL_CONVOLUTION_2D'
-%% target and the names `?GL_CONVOLUTION_FILTER_SCALE' and `?GL_CONVOLUTION_FILTER_BIAS'
-%% . The parameters themselves are vectors of four values that are applied to red, green,
-%% blue, and alpha, in that order.) The R, G, B, and A values are not clamped to [0,1] at
-%% any time during this process.
-%%
-%% Each pixel is then converted to the internal format specified by `Internalformat' .
-%% This conversion simply maps the component values of the pixel (R, G, B, and A) to the
-%% values included in the internal format (red, green, blue, alpha, luminance, and intensity).
-%% The mapping is as follows:
-%%
-%% <table><tbody><tr><td>` Internal Format '</td><td>` Red '</td><td>` Green '</td>
-%% <td>` Blue '</td><td>` Alpha '</td><td>` Luminance '</td><td>` Intensity '
-%% </td></tr></tbody><tbody><tr><td>`?GL_ALPHA'</td><td></td><td></td><td></td><td> A </td>
-%% <td></td><td></td></tr><tr><td>`?GL_LUMINANCE'</td><td></td><td></td><td></td><td></td>
-%% <td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td></td><td></td><td></td>
-%% <td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'</td><td></td><td></td><td>
-%% </td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td><td> R </td><td> G </td>
-%% <td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'</td><td> R </td><td>
-%% G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table>
-%%
-%% The red, green, blue, alpha, luminance, and/or intensity components of the resulting
-%% pixels are stored in floating-point rather than integer format.
-%%
-%% Pixel ordering is such that lower x screen coordinates correspond to lower `i' filter
-%% image coordinates, and lower y screen coordinates correspond to lower `j' filter
-%% image coordinates.
-%%
-%% Note that after a convolution is performed, the resulting color components are also scaled
-%% by their corresponding `?GL_POST_CONVOLUTION_c_SCALE' parameters and biased by their
-%% corresponding `?GL_POST_CONVOLUTION_c_BIAS' parameters (where `c' takes on the
-%% values `RED', `GREEN', `BLUE', and `ALPHA'). These parameters are
-%% set by {@link gl:pixelTransferf/2} .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyConvolutionFilter2D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glCopyConvolutionFilter2D.xml">external</a> documentation.
-spec copyConvolutionFilter2D(Target, Internalformat, X, Y, Width, Height) -> 'ok' when Target :: enum(),Internalformat :: enum(),X :: integer(),Y :: integer(),Width :: integer(),Height :: integer().
copyConvolutionFilter2D(Target,Internalformat,X,Y,Width,Height) ->
cast(5342, <<Target:?GLenum,Internalformat:?GLenum,X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei>>).
@@ -8669,21 +3363,7 @@ copyConvolutionFilter2D(Target,Internalformat,X,Y,Width,Height) ->
%% specifications in `Format' and `Type' . No pixel transfer operations are performed
%% on this image, but the relevant pixel storage modes are applied.
%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a convolution filter is requested, `Image' is
-%% treated as a byte offset into the buffer object's data store.
-%%
-%% Color components that are present in `Format' but not included in the internal format
-%% of the filter are returned as zero. The assignments of internal color components to the
-%% components of `Format' are as follows. <table><tbody><tr><td>` Internal Component '
-%% </td><td>` Resulting Component '</td></tr></tbody><tbody><tr><td> Red </td><td> Red </td>
-%% </tr><tr><td> Green </td><td> Green </td></tr><tr><td> Blue </td><td> Blue </td></tr><tr><td>
-%% Alpha </td><td> Alpha </td></tr><tr><td> Luminance </td><td> Red </td></tr><tr><td> Intensity
-%% </td><td> Red </td></tr></tbody></table>
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetConvolutionFilter.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetConvolutionFilter.xml">external</a> documentation.
-spec getConvolutionFilter(Target, Format, Type, Image) -> 'ok' when Target :: enum(),Format :: enum(),Type :: enum(),Image :: mem().
getConvolutionFilter(Target,Format,Type,Image) ->
send_bin(Image),
@@ -8695,34 +3375,7 @@ getConvolutionFilter(Target,Format,Type,Image) ->
%% which convolution filter is queried. `Pname' determines which parameter is returned:
%%
%%
-%% `?GL_CONVOLUTION_BORDER_MODE': The convolution border mode. See {@link gl:convolutionParameterf/3}
-%% for a list of border modes.
-%%
-%% `?GL_CONVOLUTION_BORDER_COLOR': The current convolution border color. `Params'
-%% must be a pointer to an array of four elements, which will receive the red, green, blue,
-%% and alpha border colors.
-%%
-%% `?GL_CONVOLUTION_FILTER_SCALE': The current filter scale factors. `Params'
-%% must be a pointer to an array of four elements, which will receive the red, green, blue,
-%% and alpha filter scale factors in that order.
-%%
-%% `?GL_CONVOLUTION_FILTER_BIAS': The current filter bias factors. `Params' must
-%% be a pointer to an array of four elements, which will receive the red, green, blue, and
-%% alpha filter bias terms in that order.
-%%
-%% `?GL_CONVOLUTION_FORMAT': The current internal format. See {@link gl:convolutionFilter1D/6}
-%% , {@link gl:convolutionFilter2D/7} , and {@link gl:separableFilter2D/8} for lists of allowable
-%% formats.
-%%
-%% `?GL_CONVOLUTION_WIDTH': The current filter image width.
-%%
-%% `?GL_CONVOLUTION_HEIGHT': The current filter image height.
-%%
-%% `?GL_MAX_CONVOLUTION_WIDTH': The maximum acceptable filter image width.
-%%
-%% `?GL_MAX_CONVOLUTION_HEIGHT': The maximum acceptable filter image height.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetConvolutionParameter.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetConvolutionParameter.xml">external</a> documentation.
-spec getConvolutionParameterfv(Target, Pname) -> {float(),float(),float(),float()} when Target :: enum(),Pname :: enum().
getConvolutionParameterfv(Target,Pname) ->
call(5344, <<Target:?GLenum,Pname:?GLenum>>).
@@ -8738,52 +3391,7 @@ getConvolutionParameteriv(Target,Pname) ->
%% ``gl:separableFilter2D'' builds a two-dimensional separable convolution filter kernel
%% from two arrays of pixels.
%%
-%% The pixel arrays specified by ( `Width' , `Format' , `Type' , `Row' )
-%% and ( `Height' , `Format' , `Type' , `Column' ) are processed just as if
-%% they had been passed to {@link gl:drawPixels/5} , but processing stops after the final expansion
-%% to RGBA is completed.
-%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a convolution filter is specified, `Row' and `Column'
-%% are treated as byte offsets into the buffer object's data store.
-%%
-%% Next, the R, G, B, and A components of all pixels in both arrays are scaled by the four
-%% separable 2D `?GL_CONVOLUTION_FILTER_SCALE' parameters and biased by the four separable
-%% 2D `?GL_CONVOLUTION_FILTER_BIAS' parameters. (The scale and bias parameters are set
-%% by {@link gl:convolutionParameterf/3} using the `?GL_SEPARABLE_2D' target and the names
-%% `?GL_CONVOLUTION_FILTER_SCALE' and `?GL_CONVOLUTION_FILTER_BIAS'. The parameters
-%% themselves are vectors of four values that are applied to red, green, blue, and alpha,
-%% in that order.) The R, G, B, and A values are not clamped to [0,1] at any time during
-%% this process.
-%%
-%% Each pixel is then converted to the internal format specified by `Internalformat' .
-%% This conversion simply maps the component values of the pixel (R, G, B, and A) to the
-%% values included in the internal format (red, green, blue, alpha, luminance, and intensity).
-%% The mapping is as follows: <table><tbody><tr><td>` Internal Format '</td><td>` Red '
-%% </td><td>` Green '</td><td>` Blue '</td><td>` Alpha '</td><td>` Luminance '
-%% </td><td>` Intensity '</td></tr></tbody><tbody><tr><td>`?GL_LUMINANCE'</td><td></td>
-%% <td></td><td></td><td></td><td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td>
-%% <td></td><td></td><td></td><td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'
-%% </td><td></td><td></td><td></td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td>
-%% <td> R </td><td> G </td><td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'
-%% </td><td> R </td><td> G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table>
-%%
-%%
-%% The red, green, blue, alpha, luminance, and/or intensity components of the resulting
-%% pixels are stored in floating-point rather than integer format. They form two one-dimensional
-%% filter kernel images. The row image is indexed by coordinate `i' starting at zero
-%% and increasing from left to right. Each location in the row image is derived from element
-%% `i' of `Row' . The column image is indexed by coordinate `j' starting at
-%% zero and increasing from bottom to top. Each location in the column image is derived from
-%% element `j' of `Column' .
-%%
-%% Note that after a convolution is performed, the resulting color components are also scaled
-%% by their corresponding `?GL_POST_CONVOLUTION_c_SCALE' parameters and biased by their
-%% corresponding `?GL_POST_CONVOLUTION_c_BIAS' parameters (where `c' takes on the
-%% values `RED', `GREEN', `BLUE', and `ALPHA'). These parameters are
-%% set by {@link gl:pixelTransferf/2} .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSeparableFilter2D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glSeparableFilter2D.xml">external</a> documentation.
-spec separableFilter2D(Target, Internalformat, Width, Height, Format, Type, Row, Column) -> 'ok' when Target :: enum(),Internalformat :: enum(),Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Row :: offset()|mem(),Column :: offset()|mem().
separableFilter2D(Target,Internalformat,Width,Height,Format,Type,Row,Column) when is_integer(Row), is_integer(Column) ->
cast(5346, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum,Row:?GLuint,Column:?GLuint>>);
@@ -8798,21 +3406,7 @@ separableFilter2D(Target,Internalformat,Width,Height,Format,Type,Row,Column) ->
%% the same width as the histogram. No pixel transfer operations are performed on this image,
%% but pixel storage modes that are applicable to 1D images are honored.
%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a histogram table is requested, `Values' is treated
-%% as a byte offset into the buffer object's data store.
-%%
-%% Color components that are requested in the specified `Format' , but which are not
-%% included in the internal format of the histogram, are returned as zero. The assignments
-%% of internal color components to the components requested by `Format' are: <table><tbody>
-%% <tr><td>` Internal Component '</td><td>` Resulting Component '</td></tr></tbody>
-%% <tbody><tr><td> Red </td><td> Red </td></tr><tr><td> Green </td><td> Green </td></tr><tr><td>
-%% Blue </td><td> Blue </td></tr><tr><td> Alpha </td><td> Alpha </td></tr><tr><td> Luminance
-%% </td><td> Red </td></tr></tbody></table>
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetHistogram.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetHistogram.xml">external</a> documentation.
-spec getHistogram(Target, Reset, Format, Type, Values) -> 'ok' when Target :: enum(),Reset :: 0|1,Format :: enum(),Type :: enum(),Values :: mem().
getHistogram(Target,Reset,Format,Type,Values) ->
send_bin(Values),
@@ -8826,19 +3420,7 @@ getHistogram(Target,Reset,Format,Type,Values) ->
%% table) or `?GL_PROXY_HISTOGRAM' (to obtain information from the most recent proxy
%% request) and one of the following values for the `Pname' argument:
%%
-%% <table><tbody><tr><td>` Parameter '</td><td>` Description '</td></tr></tbody><tbody>
-%% <tr><td>`?GL_HISTOGRAM_WIDTH'</td><td> Histogram table width </td></tr><tr><td>`?GL_HISTOGRAM_FORMAT'
-%% </td><td> Internal format </td></tr><tr><td>`?GL_HISTOGRAM_RED_SIZE'</td><td> Red
-%% component counter size, in bits </td></tr><tr><td>`?GL_HISTOGRAM_GREEN_SIZE'</td><td>
-%% Green component counter size, in bits </td></tr><tr><td>`?GL_HISTOGRAM_BLUE_SIZE'</td>
-%% <td> Blue component counter size, in bits </td></tr><tr><td>`?GL_HISTOGRAM_ALPHA_SIZE'
-%% </td><td> Alpha component counter size, in bits </td></tr><tr><td>`?GL_HISTOGRAM_LUMINANCE_SIZE'
-%% </td><td> Luminance component counter size, in bits </td></tr><tr><td>`?GL_HISTOGRAM_SINK'
-%% </td><td> Value of the `sink' parameter </td></tr></tbody></table>
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetHistogramParameter.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetHistogramParameter.xml">external</a> documentation.
-spec getHistogramParameterfv(Target, Pname) -> {float()} when Target :: enum(),Pname :: enum().
getHistogramParameterfv(Target,Pname) ->
call(5349, <<Target:?GLenum,Pname:?GLenum>>).
@@ -8857,26 +3439,7 @@ getHistogramParameteriv(Target,Pname) ->
%% of the return values is determined by `Format' , and their type is determined by `Types'
%% .
%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while minimum and maximum pixel values are requested, `Values'
-%% is treated as a byte offset into the buffer object's data store.
-%%
-%% No pixel transfer operations are performed on the return values, but pixel storage modes
-%% that are applicable to one-dimensional images are performed. Color components that are
-%% requested in the specified `Format' , but that are not included in the internal format
-%% of the minmax table, are returned as zero. The assignment of internal color components
-%% to the components requested by `Format' are as follows:
-%%
-%% <table><tbody><tr><td>` Internal Component '</td><td>` Resulting Component '</td>
-%% </tr></tbody><tbody><tr><td> Red </td><td> Red </td></tr><tr><td> Green </td><td> Green </td>
-%% </tr><tr><td> Blue </td><td> Blue </td></tr><tr><td> Alpha </td><td> Alpha </td></tr><tr><td>
-%% Luminance </td><td> Red </td></tr></tbody></table>
-%%
-%% If `Reset' is `?GL_TRUE', the minmax table entries corresponding to the return
-%% values are reset to their initial values. Minimum and maximum values that are not returned
-%% are not modified, even if `Reset' is `?GL_TRUE'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMinmax.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetMinmax.xml">external</a> documentation.
-spec getMinmax(Target, Reset, Format, Types, Values) -> 'ok' when Target :: enum(),Reset :: 0|1,Format :: enum(),Types :: enum(),Values :: mem().
getMinmax(Target,Reset,Format,Types,Values) ->
send_bin(Values),
@@ -8887,14 +3450,7 @@ getMinmax(Target,Reset,Format,Types,Values) ->
%% ``gl:getMinmaxParameter'' retrieves parameters for the current minmax table by setting `Pname'
%% to one of the following values:
%%
-%% <table><tbody><tr><td>` Parameter '</td><td>` Description '</td></tr></tbody><tbody>
-%% <tr><td>`?GL_MINMAX_FORMAT'</td><td> Internal format of minmax table </td></tr><tr><td>
-%% `?GL_MINMAX_SINK'</td><td> Value of the `sink' parameter </td></tr></tbody></table>
-%%
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMinmaxParameter.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetMinmaxParameter.xml">external</a> documentation.
-spec getMinmaxParameterfv(Target, Pname) -> {float()} when Target :: enum(),Pname :: enum().
getMinmaxParameterfv(Target,Pname) ->
call(5352, <<Target:?GLenum,Pname:?GLenum>>).
@@ -8915,26 +3471,7 @@ getMinmaxParameteriv(Target,Pname) ->
%% to be incremented.) If a histogram table entry is incremented beyond its maximum value,
%% then its value becomes undefined. (This is not an error.)
%%
-%% Histogramming is performed only for RGBA pixels (though these may be specified originally
-%% as color indices and converted to RGBA by index table lookup). Histogramming is enabled
-%% with {@link gl:enable/1} and disabled with {@link gl:enable/1} .
-%%
-%% When `Target' is `?GL_HISTOGRAM', ``gl:histogram'' redefines the current
-%% histogram table to have `Width' entries of the format specified by `Internalformat'
-%% . The entries are indexed 0 through width-1, and all entries are initialized to zero.
-%% The values in the previous histogram table, if any, are lost. If `Sink' is `?GL_TRUE'
-%% , then pixels are discarded after histogramming; no further processing of the pixels takes
-%% place, and no drawing, texture loading, or pixel readback will result.
-%%
-%% When `Target' is `?GL_PROXY_HISTOGRAM', ``gl:histogram'' computes all state
-%% information as if the histogram table were to be redefined, but does not actually define
-%% the new table. If the requested histogram table is too large to be supported, then the
-%% state information will be set to zero. This provides a way to determine if a histogram
-%% table with the given parameters can be supported.
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glHistogram.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glHistogram.xml">external</a> documentation.
-spec histogram(Target, Width, Internalformat, Sink) -> 'ok' when Target :: enum(),Width :: integer(),Internalformat :: enum(),Sink :: 0|1.
histogram(Target,Width,Internalformat,Sink) ->
cast(5354, <<Target:?GLenum,Width:?GLsizei,Internalformat:?GLenum,Sink:?GLboolean>>).
@@ -8954,16 +3491,7 @@ histogram(Target,Width,Internalformat,Sink) ->
%% calling {@link gl:enable/1} or {@link gl:enable/1} , respectively, with an argument of `?GL_MINMAX'
%% .
%%
-%% ``gl:minmax'' redefines the current minmax table to have entries of the format specified
-%% by `Internalformat' . The maximum element is initialized with the smallest possible
-%% component values, and the minimum element is initialized with the largest possible component
-%% values. The values in the previous minmax table, if any, are lost. If `Sink' is `?GL_TRUE'
-%% , then pixels are discarded after minmax; no further processing of the pixels takes place,
-%% and no drawing, texture loading, or pixel readback will result.
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMinmax.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glMinmax.xml">external</a> documentation.
-spec minmax(Target, Internalformat, Sink) -> 'ok' when Target :: enum(),Internalformat :: enum(),Sink :: 0|1.
minmax(Target,Internalformat,Sink) ->
cast(5355, <<Target:?GLenum,Internalformat:?GLenum,Sink:?GLboolean>>).
@@ -8972,7 +3500,7 @@ minmax(Target,Internalformat,Sink) ->
%%
%% ``gl:resetHistogram'' resets all the elements of the current histogram table to zero.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glResetHistogram.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glResetHistogram.xml">external</a> documentation.
-spec resetHistogram(Target) -> 'ok' when Target :: enum().
resetHistogram(Target) ->
cast(5356, <<Target:?GLenum>>).
@@ -8983,7 +3511,7 @@ resetHistogram(Target) ->
%% values: the ``maximum'' element receives the minimum possible component values, and the
%% ``minimum'' element receives the maximum possible component values.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glResetMinmax.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glResetMinmax.xml">external</a> documentation.
-spec resetMinmax(Target) -> 'ok' when Target :: enum().
resetMinmax(Target) ->
cast(5357, <<Target:?GLenum>>).
@@ -8994,7 +3522,7 @@ resetMinmax(Target) ->
%% affect. The number of texture units an implementation supports is implementation dependent,
%% but must be at least 80.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glActiveTexture.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glActiveTexture.xhtml">external</a> documentation.
-spec activeTexture(Texture) -> 'ok' when Texture :: enum().
activeTexture(Texture) ->
cast(5358, <<Texture:?GLenum>>).
@@ -9005,22 +3533,7 @@ activeTexture(Texture) ->
%% locations to generate antialiasing effects. Multisampling transparently antialiases points,
%% lines, polygons, and images if it is enabled.
%%
-%% `Value' is used in constructing a temporary mask used in determining which samples
-%% will be used in resolving the final fragment color. This mask is bitwise-anded with the
-%% coverage mask generated from the multisampling computation. If the `Invert' flag
-%% is set, the temporary mask is inverted (all bits flipped) and then the bitwise-and is
-%% computed.
-%%
-%% If an implementation does not have any multisample buffers available, or multisampling
-%% is disabled, rasterization occurs with only a single sample computing a pixel's final
-%% RGB color.
-%%
-%% Provided an implementation supports multisample buffers, and multisampling is enabled,
-%% then a pixel's final color is generated by combining several samples per pixel. Each sample
-%% contains color, depth, and stencil information, allowing those operations to be performed
-%% on each sample.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSampleCoverage.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glSampleCoverage.xhtml">external</a> documentation.
-spec sampleCoverage(Value, Invert) -> 'ok' when Value :: clamp(),Invert :: 0|1.
sampleCoverage(Value,Invert) ->
cast(5359, <<Value:?GLclampf,Invert:?GLboolean>>).
@@ -9029,56 +3542,7 @@ sampleCoverage(Value,Invert) ->
%%
%% Texturing allows elements of an image array to be read by shaders.
%%
-%% ``gl:compressedTexImage3D'' loads a previously defined, and retrieved, compressed three-dimensional
-%% texture image if `Target' is `?GL_TEXTURE_3D' (see {@link gl:texImage3D/10} ).
-%%
-%% If `Target' is `?GL_TEXTURE_2D_ARRAY', `Data' is treated as an array of
-%% compressed 2D textures.
-%%
-%% If `Target' is `?GL_PROXY_TEXTURE_3D' or `?GL_PROXY_TEXTURE_2D_ARRAY',
-%% no data is read from `Data' , but all of the texture image state is recalculated,
-%% checked for consistency, and checked against the implementation's capabilities. If the
-%% implementation cannot handle a texture of the requested texture size, it sets all of the
-%% image state to 0, but does not generate an error (see {@link gl:getError/0} ). To query
-%% for an entire mipmap array, use an image array level greater than or equal to 1.
-%%
-%% `Internalformat' must be a known compressed image format (such as `?GL_RGTC')
-%% or an extension-specified compressed-texture format. When a texture is loaded with {@link gl:texImage2D/9}
-%% using a generic compressed texture format (e.g., `?GL_COMPRESSED_RGB'), the GL selects
-%% from one of its extensions supporting compressed textures. In order to load the compressed
-%% texture image using ``gl:compressedTexImage3D'', query the compressed texture image's
-%% size and format using {@link gl:getTexLevelParameterfv/3} .
-%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated
-%% as a byte offset into the buffer object's data store.
-%%
-%% If the compressed data are arranged into fixed-size blocks of texels, the pixel storage
-%% modes can be used to select a sub-rectangle from a larger containing rectangle. These
-%% pixel storage modes operate in the same way as they do for {@link gl:texImage1D/8} . In
-%% the following description, denote by b s, b w, b h, and b d, the values of pixel storage
-%% modes `?GL_UNPACK_COMPRESSED_BLOCK_SIZE', `?GL_UNPACK_COMPRESSED_BLOCK_WIDTH', `?GL_UNPACK_COMPRESSED_BLOCK_HEIGHT'
-%% , and `?GL_UNPACK_COMPRESSED_BLOCK_DEPTH', respectively. b s is the compressed block
-%% size in bytes; b w, b h, and b d are the compressed block width, height, and depth
-%% in pixels.
-%%
-%% By default the pixel storage modes `?GL_UNPACK_ROW_LENGTH', `?GL_UNPACK_SKIP_ROWS'
-%% , `?GL_UNPACK_SKIP_PIXELS', `?GL_UNPACK_IMAGE_HEIGHT' and `?GL_UNPACK_SKIP_IMAGES'
-%% are ignored for compressed images. To enable `?GL_UNPACK_SKIP_PIXELS' and `?GL_UNPACK_ROW_LENGTH'
-%% , b s and b w must both be non-zero. To also enable `?GL_UNPACK_SKIP_ROWS' and `?GL_UNPACK_IMAGE_HEIGHT'
-%% , b h must be non-zero. To also enable `?GL_UNPACK_SKIP_IMAGES', b d must be non-zero.
-%% All parameters must be consistent with the compressed format to produce the desired results.
-%%
-%%
-%% When selecting a sub-rectangle from a compressed image: the value of `?GL_UNPACK_SKIP_PIXELS'
-%% must be a multiple of b w;the value of `?GL_UNPACK_SKIP_ROWS' must be a multiple
-%% of b w;the value of `?GL_UNPACK_SKIP_IMAGES' must be a multiple of b w.
-%%
-%% `ImageSize' must be equal to:
-%%
-%% b s×|width b/w|×|height b/h|×|depth b/d|
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexImage3D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCompressedTexImage3D.xhtml">external</a> documentation.
-spec compressedTexImage3D(Target, Level, Internalformat, Width, Height, Depth, Border, ImageSize, Data) -> 'ok' when Target :: enum(),Level :: integer(),Internalformat :: enum(),Width :: integer(),Height :: integer(),Depth :: integer(),Border :: integer(),ImageSize :: integer(),Data :: offset()|mem().
compressedTexImage3D(Target,Level,Internalformat,Width,Height,Depth,Border,ImageSize,Data) when is_integer(Data) ->
cast(5360, <<Target:?GLenum,Level:?GLint,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Border:?GLint,ImageSize:?GLsizei,Data:?GLuint>>);
@@ -9090,57 +3554,7 @@ compressedTexImage3D(Target,Level,Internalformat,Width,Height,Depth,Border,Image
%%
%% Texturing allows elements of an image array to be read by shaders.
%%
-%% ``gl:compressedTexImage2D'' loads a previously defined, and retrieved, compressed two-dimensional
-%% texture image if `Target' is `?GL_TEXTURE_2D', or one of the cube map faces
-%% such as `?GL_TEXTURE_CUBE_MAP_POSITIVE_X'. (see {@link gl:texImage2D/9} ).
-%%
-%% If `Target' is `?GL_TEXTURE_1D_ARRAY', `Data' is treated as an array of
-%% compressed 1D textures.
-%%
-%% If `Target' is `?GL_PROXY_TEXTURE_2D', `?GL_PROXY_TEXTURE_1D_ARRAY' or `?GL_PROXY_CUBE_MAP'
-%% , no data is read from `Data' , but all of the texture image state is recalculated,
-%% checked for consistency, and checked against the implementation's capabilities. If the
-%% implementation cannot handle a texture of the requested texture size, it sets all of the
-%% image state to 0, but does not generate an error (see {@link gl:getError/0} ). To query
-%% for an entire mipmap array, use an image array level greater than or equal to 1.
-%%
-%% `Internalformat' must be a known compressed image format (such as `?GL_RGTC')
-%% or an extension-specified compressed-texture format. When a texture is loaded with {@link gl:texImage2D/9}
-%% using a generic compressed texture format (e.g., `?GL_COMPRESSED_RGB'), the GL selects
-%% from one of its extensions supporting compressed textures. In order to load the compressed
-%% texture image using ``gl:compressedTexImage2D'', query the compressed texture image's
-%% size and format using {@link gl:getTexLevelParameterfv/3} .
-%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated
-%% as a byte offset into the buffer object's data store.
-%%
-%% If the compressed data are arranged into fixed-size blocks of texels, the pixel storage
-%% modes can be used to select a sub-rectangle from a larger containing rectangle. These
-%% pixel storage modes operate in the same way as they do for {@link gl:texImage2D/9} . In
-%% the following description, denote by b s, b w, b h, and b d, the values of pixel storage
-%% modes `?GL_UNPACK_COMPRESSED_BLOCK_SIZE', `?GL_UNPACK_COMPRESSED_BLOCK_WIDTH', `?GL_UNPACK_COMPRESSED_BLOCK_HEIGHT'
-%% , and `?GL_UNPACK_COMPRESSED_BLOCK_DEPTH', respectively. b s is the compressed block
-%% size in bytes; b w, b h, and b d are the compressed block width, height, and depth
-%% in pixels.
-%%
-%% By default the pixel storage modes `?GL_UNPACK_ROW_LENGTH', `?GL_UNPACK_SKIP_ROWS'
-%% , `?GL_UNPACK_SKIP_PIXELS', `?GL_UNPACK_IMAGE_HEIGHT' and `?GL_UNPACK_SKIP_IMAGES'
-%% are ignored for compressed images. To enable `?GL_UNPACK_SKIP_PIXELS' and `?GL_UNPACK_ROW_LENGTH'
-%% , b s and b w must both be non-zero. To also enable `?GL_UNPACK_SKIP_ROWS' and `?GL_UNPACK_IMAGE_HEIGHT'
-%% , b h must be non-zero. To also enable `?GL_UNPACK_SKIP_IMAGES', b d must be non-zero.
-%% All parameters must be consistent with the compressed format to produce the desired results.
-%%
-%%
-%% When selecting a sub-rectangle from a compressed image: the value of `?GL_UNPACK_SKIP_PIXELS'
-%% must be a multiple of b w;the value of `?GL_UNPACK_SKIP_ROWS' must be a multiple
-%% of b w.
-%%
-%% `ImageSize' must be equal to:
-%%
-%% b s×|width b/w|×|height b/h|
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexImage2D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCompressedTexImage2D.xhtml">external</a> documentation.
-spec compressedTexImage2D(Target, Level, Internalformat, Width, Height, Border, ImageSize, Data) -> 'ok' when Target :: enum(),Level :: integer(),Internalformat :: enum(),Width :: integer(),Height :: integer(),Border :: integer(),ImageSize :: integer(),Data :: offset()|mem().
compressedTexImage2D(Target,Level,Internalformat,Width,Height,Border,ImageSize,Data) when is_integer(Data) ->
cast(5362, <<Target:?GLenum,Level:?GLint,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Border:?GLint,ImageSize:?GLsizei,Data:?GLuint>>);
@@ -9152,52 +3566,7 @@ compressedTexImage2D(Target,Level,Internalformat,Width,Height,Border,ImageSize,D
%%
%% Texturing allows elements of an image array to be read by shaders.
%%
-%% ``gl:compressedTexImage1D'' loads a previously defined, and retrieved, compressed one-dimensional
-%% texture image if `Target' is `?GL_TEXTURE_1D' (see {@link gl:texImage1D/8} ).
-%%
-%% If `Target' is `?GL_PROXY_TEXTURE_1D', no data is read from `Data' , but
-%% all of the texture image state is recalculated, checked for consistency, and checked against
-%% the implementation's capabilities. If the implementation cannot handle a texture of the
-%% requested texture size, it sets all of the image state to 0, but does not generate an
-%% error (see {@link gl:getError/0} ). To query for an entire mipmap array, use an image array
-%% level greater than or equal to 1.
-%%
-%% `Internalformat' must be an extension-specified compressed-texture format. When a
-%% texture is loaded with {@link gl:texImage1D/8} using a generic compressed texture format
-%% (e.g., `?GL_COMPRESSED_RGB') the GL selects from one of its extensions supporting
-%% compressed textures. In order to load the compressed texture image using ``gl:compressedTexImage1D''
-%% , query the compressed texture image's size and format using {@link gl:getTexLevelParameterfv/3}
-%% .
-%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated
-%% as a byte offset into the buffer object's data store.
-%%
-%% If the compressed data are arranged into fixed-size blocks of texels, the pixel storage
-%% modes can be used to select a sub-rectangle from a larger containing rectangle. These
-%% pixel storage modes operate in the same way as they do for {@link gl:texImage1D/8} . In
-%% the following description, denote by b s, b w, b h, and b d, the values of pixel storage
-%% modes `?GL_UNPACK_COMPRESSED_BLOCK_SIZE', `?GL_UNPACK_COMPRESSED_BLOCK_WIDTH', `?GL_UNPACK_COMPRESSED_BLOCK_HEIGHT'
-%% , and `?GL_UNPACK_COMPRESSED_BLOCK_DEPTH', respectively. b s is the compressed block
-%% size in bytes; b w, b h, and b d are the compressed block width, height, and depth
-%% in pixels.
-%%
-%% By default the pixel storage modes `?GL_UNPACK_ROW_LENGTH', `?GL_UNPACK_SKIP_ROWS'
-%% , `?GL_UNPACK_SKIP_PIXELS', `?GL_UNPACK_IMAGE_HEIGHT' and `?GL_UNPACK_SKIP_IMAGES'
-%% are ignored for compressed images. To enable `?GL_UNPACK_SKIP_PIXELS' and `?GL_UNPACK_ROW_LENGTH'
-%% , b s and b w must both be non-zero. To also enable `?GL_UNPACK_SKIP_ROWS' and `?GL_UNPACK_IMAGE_HEIGHT'
-%% , b h must be non-zero. To also enable `?GL_UNPACK_SKIP_IMAGES', b d must be non-zero.
-%% All parameters must be consistent with the compressed format to produce the desired results.
-%%
-%%
-%% When selecting a sub-rectangle from a compressed image: the value of `?GL_UNPACK_SKIP_PIXELS'
-%% must be a multiple of b w;
-%%
-%% `ImageSize' must be equal to:
-%%
-%% b s×|width b/w|
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexImage1D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCompressedTexImage1D.xhtml">external</a> documentation.
-spec compressedTexImage1D(Target, Level, Internalformat, Width, Border, ImageSize, Data) -> 'ok' when Target :: enum(),Level :: integer(),Internalformat :: enum(),Width :: integer(),Border :: integer(),ImageSize :: integer(),Data :: offset()|mem().
compressedTexImage1D(Target,Level,Internalformat,Width,Border,ImageSize,Data) when is_integer(Data) ->
cast(5364, <<Target:?GLenum,Level:?GLint,Internalformat:?GLenum,Width:?GLsizei,Border:?GLint,ImageSize:?GLsizei,Data:?GLuint>>);
@@ -9209,25 +3578,7 @@ compressedTexImage1D(Target,Level,Internalformat,Width,Border,ImageSize,Data) ->
%%
%% Texturing allows elements of an image array to be read by shaders.
%%
-%% ``gl:compressedTexSubImage3D'' redefines a contiguous subregion of an existing three-dimensional
-%% texture image. The texels referenced by `Data' replace the portion of the existing
-%% texture array with x indices `Xoffset' and xoffset+width-1, and the y indices `Yoffset'
-%% and yoffset+height-1, and the z indices `Zoffset' and zoffset+depth-1, inclusive.
-%% This region may not include any texels outside the range of the texture array as it was
-%% originally specified. It is not an error to specify a subtexture with width of 0, but
-%% such a specification has no effect.
-%%
-%% `Internalformat' must be a known compressed image format (such as `?GL_RGTC')
-%% or an extension-specified compressed-texture format. The `Format' of the compressed
-%% texture image is selected by the GL implementation that compressed it (see {@link gl:texImage3D/10}
-%% ) and should be queried at the time the texture was compressed with {@link gl:getTexLevelParameterfv/3}
-%% .
-%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated
-%% as a byte offset into the buffer object's data store.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexSubImage3D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCompressedTexSubImage3D.xhtml">external</a> documentation.
-spec compressedTexSubImage3D(Target, Level, Xoffset, Yoffset, Zoffset, Width, Height, Depth, Format, ImageSize, Data) -> 'ok' when Target :: enum(),Level :: integer(),Xoffset :: integer(),Yoffset :: integer(),Zoffset :: integer(),Width :: integer(),Height :: integer(),Depth :: integer(),Format :: enum(),ImageSize :: integer(),Data :: offset()|mem().
compressedTexSubImage3D(Target,Level,Xoffset,Yoffset,Zoffset,Width,Height,Depth,Format,ImageSize,Data) when is_integer(Data) ->
cast(5366, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Zoffset:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Format:?GLenum,ImageSize:?GLsizei,Data:?GLuint>>);
@@ -9239,24 +3590,7 @@ compressedTexSubImage3D(Target,Level,Xoffset,Yoffset,Zoffset,Width,Height,Depth,
%%
%% Texturing allows elements of an image array to be read by shaders.
%%
-%% ``gl:compressedTexSubImage2D'' redefines a contiguous subregion of an existing two-dimensional
-%% texture image. The texels referenced by `Data' replace the portion of the existing
-%% texture array with x indices `Xoffset' and xoffset+width-1, and the y indices `Yoffset'
-%% and yoffset+height-1, inclusive. This region may not include any texels outside the
-%% range of the texture array as it was originally specified. It is not an error to specify
-%% a subtexture with width of 0, but such a specification has no effect.
-%%
-%% `Internalformat' must be a known compressed image format (such as `?GL_RGTC')
-%% or an extension-specified compressed-texture format. The `Format' of the compressed
-%% texture image is selected by the GL implementation that compressed it (see {@link gl:texImage2D/9}
-%% ) and should be queried at the time the texture was compressed with {@link gl:getTexLevelParameterfv/3}
-%% .
-%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated
-%% as a byte offset into the buffer object's data store.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexSubImage2D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCompressedTexSubImage2D.xhtml">external</a> documentation.
-spec compressedTexSubImage2D(Target, Level, Xoffset, Yoffset, Width, Height, Format, ImageSize, Data) -> 'ok' when Target :: enum(),Level :: integer(),Xoffset :: integer(),Yoffset :: integer(),Width :: integer(),Height :: integer(),Format :: enum(),ImageSize :: integer(),Data :: offset()|mem().
compressedTexSubImage2D(Target,Level,Xoffset,Yoffset,Width,Height,Format,ImageSize,Data) when is_integer(Data) ->
cast(5368, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,ImageSize:?GLsizei,Data:?GLuint>>);
@@ -9268,24 +3602,7 @@ compressedTexSubImage2D(Target,Level,Xoffset,Yoffset,Width,Height,Format,ImageSi
%%
%% Texturing allows elements of an image array to be read by shaders.
%%
-%% ``gl:compressedTexSubImage1D'' redefines a contiguous subregion of an existing one-dimensional
-%% texture image. The texels referenced by `Data' replace the portion of the existing
-%% texture array with x indices `Xoffset' and xoffset+width-1, inclusive. This region
-%% may not include any texels outside the range of the texture array as it was originally
-%% specified. It is not an error to specify a subtexture with width of 0, but such a specification
-%% has no effect.
-%%
-%% `Internalformat' must be a known compressed image format (such as `?GL_RGTC')
-%% or an extension-specified compressed-texture format. The `Format' of the compressed
-%% texture image is selected by the GL implementation that compressed it (see {@link gl:texImage1D/8}
-%% ), and should be queried at the time the texture was compressed with {@link gl:getTexLevelParameterfv/3}
-%% .
-%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated
-%% as a byte offset into the buffer object's data store.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexSubImage1D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCompressedTexSubImage1D.xhtml">external</a> documentation.
-spec compressedTexSubImage1D(Target, Level, Xoffset, Width, Format, ImageSize, Data) -> 'ok' when Target :: enum(),Level :: integer(),Xoffset :: integer(),Width :: integer(),Format :: enum(),ImageSize :: integer(),Data :: offset()|mem().
compressedTexSubImage1D(Target,Level,Xoffset,Width,Format,ImageSize,Data) when is_integer(Data) ->
cast(5370, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Width:?GLsizei,Format:?GLenum,ImageSize:?GLsizei,Data:?GLuint>>);
@@ -9302,20 +3619,7 @@ compressedTexSubImage1D(Target,Level,Xoffset,Width,Format,ImageSize,Data) ->
%% ), or {@link gl:texImage3D/10} (`?GL_TEXTURE_3D'). `Lod' specifies the level-of-detail
%% number of the desired image.
%%
-%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target
-%% (see {@link gl:bindBuffer/2} ) while a texture image is requested, `Img' is treated
-%% as a byte offset into the buffer object's data store.
-%%
-%% To minimize errors, first verify that the texture is compressed by calling {@link gl:getTexLevelParameterfv/3}
-%% with argument `?GL_TEXTURE_COMPRESSED'. If the texture is compressed, then determine
-%% the amount of memory required to store the compressed texture by calling {@link gl:getTexLevelParameterfv/3}
-%% with argument `?GL_TEXTURE_COMPRESSED_IMAGE_SIZE'. Finally, retrieve the internal
-%% format of the texture by calling {@link gl:getTexLevelParameterfv/3} with argument `?GL_TEXTURE_INTERNAL_FORMAT'
-%% . To store the texture for later use, associate the internal format and size with the
-%% retrieved texture image. These data can be used by the respective texture or subtexture
-%% loading routine used for loading `Target' textures.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetCompressedTexImage.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetCompressedTexImage.xhtml">external</a> documentation.
-spec getCompressedTexImage(Target, Lod, Img) -> 'ok' when Target :: enum(),Lod :: integer(),Img :: mem().
getCompressedTexImage(Target,Lod,Img) ->
send_bin(Img),
@@ -9328,7 +3632,7 @@ getCompressedTexImage(Target,Lod,Img) ->
%% or {@link gl:enableClientState/1} , respectively, when called with a parameter of `?GL_TEXTURE_COORD_ARRAY'
%% .
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClientActiveTexture.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glClientActiveTexture.xml">external</a> documentation.
-spec clientActiveTexture(Texture) -> 'ok' when Texture :: enum().
clientActiveTexture(Texture) ->
cast(5373, <<Texture:?GLenum>>).
@@ -9341,12 +3645,7 @@ clientActiveTexture(Texture) ->
%% t r 1),
%% and ``gl:multiTexCoord4'' defines all four components explicitly as (s t r q).
%%
-%% The current texture coordinates are part of the data that is associated with each vertex
-%% and with the current raster position. Initially, the values for (s t r q) are (0 0 0 1).
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glMultiTexCoord.xml">external</a> documentation.
-spec multiTexCoord1d(Target, S) -> 'ok' when Target :: enum(),S :: float().
multiTexCoord1d(Target,S) ->
cast(5374, <<Target:?GLenum,0:32,S:?GLdouble>>).
@@ -9511,19 +3810,7 @@ multiTexCoord4sv(Target,{S,T,R,Q}) -> multiTexCoord4s(Target,S,T,R,Q).
%% specified by `M' . The current matrix is the projection matrix, modelview matrix,
%% or texture matrix, depending on the current matrix mode (see {@link gl:matrixMode/1} ).
%%
-%% The current matrix, M, defines a transformation of coordinates. For instance, assume
-%% M refers to the modelview matrix. If v=(v[0] v[1] v[2] v[3]) is the set of object coordinates of a vertex,
-%% and `M' points to an array of 16 single- or double-precision floating-point values
-%% m={m[0] m[1] ... m[15]}, then the modelview transformation M(v) does the following:
-%%
-%% M(v)=(m[0] m[1] m[2] m[3] m[4] m[5] m[6] m[7] m[8] m[9] m[10] m[11] m[12] m[13] m[14] m[15])×(v[0] v[1] v[2] v[3])
-%%
-%% Projection and texture transformations are similarly defined.
-%%
-%% Calling ``gl:loadTransposeMatrix'' with matrix M is identical in operation to {@link gl:loadMatrixd/1}
-%% with M T, where T represents the transpose.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadTransposeMatrix.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLoadTransposeMatrix.xml">external</a> documentation.
-spec loadTransposeMatrixf(M) -> 'ok' when M :: matrix().
loadTransposeMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
cast(5390, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,M13:?GLfloat,M14:?GLfloat,M15:?GLfloat,M16:?GLfloat>>);
@@ -9543,10 +3830,7 @@ loadTransposeMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
%% ``gl:multTransposeMatrix'' multiplies the current matrix with the one specified using `M'
%% , and replaces the current matrix with the product.
%%
-%% The current matrix is determined by the current matrix mode (see {@link gl:matrixMode/1} ).
-%% It is either the projection matrix, modelview matrix, or the texture matrix.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultTransposeMatrix.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glMultTransposeMatrix.xml">external</a> documentation.
-spec multTransposeMatrixf(M) -> 'ok' when M :: matrix().
multTransposeMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
cast(5392, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,M13:?GLfloat,M14:?GLfloat,M15:?GLfloat,M16:?GLfloat>>);
@@ -9568,72 +3852,7 @@ multTransposeMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
%% is initially disabled. Use {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_BLEND'
%% to enable and disable blending.
%%
-%% ``gl:blendFuncSeparate'' defines the operation of blending for all draw buffers when
-%% it is enabled. ``gl:blendFuncSeparatei'' defines the operation of blending for a single
-%% draw buffer specified by `Buf' when enabled for that draw buffer. `SrcRGB' specifies
-%% which method is used to scale the source RGB-color components. `DstRGB' specifies
-%% which method is used to scale the destination RGB-color components. Likewise, `SrcAlpha'
-%% specifies which method is used to scale the source alpha color component, and `DstAlpha'
-%% specifies which method is used to scale the destination alpha component. The possible
-%% methods are described in the following table. Each method defines four scale factors,
-%% one each for red, green, blue, and alpha.
-%%
-%% In the table and in subsequent equations, first source, second source and destination
-%% color components are referred to as (R s0 G s0 B s0 A s0), (R s1 G s1 B s1 A s1), and (R d G d B d A d), respectively. The color specified by {@link gl:blendColor/4}
-%% is referred to as (R c G c B c A c). They are understood to have integer values between 0 and (k R k G k B
-%% k A), where
-%%
-%% k c=2(m c)-1
-%%
-%% and (m R m G m B m A) is the number of red, green, blue, and alpha bitplanes.
-%%
-%% Source and destination scale factors are referred to as (s R s G s B s A) and (d R d G d B d A). All scale factors have
-%% range [0 1].
-%%
-%% <table><tbody><tr><td>` Parameter '</td><td>` RGB Factor '</td><td>` Alpha Factor '
-%% </td></tr></tbody><tbody><tr><td>`?GL_ZERO'</td><td>(0 0 0)</td><td> 0</td></tr><tr><td>`?GL_ONE'
-%% </td><td>(1 1 1)</td><td> 1</td></tr><tr><td>`?GL_SRC_COLOR'</td><td>(R s0 k/R G s0 k/G B s0
-%% k/B)</td><td> A s0 k/A</td>
-%% </tr><tr><td>`?GL_ONE_MINUS_SRC_COLOR'</td><td>(1 1 1 1)-(R s0 k/R G s0 k/G B s0 k/B)</td><td> 1-A s0 k/A</td></tr><tr><td>
-%% `?GL_DST_COLOR'</td><td>(R d k/R G d k/G B d k/B)</td><td> A d k/A</td></tr><tr><td>`?GL_ONE_MINUS_DST_COLOR'
-%% </td><td>(1 1 1)-(R d k/R G d k/G B d k/B)</td><td> 1-A d k/A</td></tr><tr><td>`?GL_SRC_ALPHA'</td><td>(A s0 k/A A s0
-%% k/A A s0 k/A)</td><td> A
-%% s0 k/A</td></tr><tr><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td>(1 1 1)-(A s0 k/A A s0 k/A A s0 k/A
-%% )</td><td> 1-A s0 k/A</td></tr>
-%% <tr><td>`?GL_DST_ALPHA'</td><td>(A d k/A A d k/A A d k/A)</td><td> A d k/A</td></tr><tr><td>`?GL_ONE_MINUS_DST_ALPHA'
-%% </td><td>(1 1 1)-(A d k/A A d k/A A d k/A)</td><td> 1-A d k/A</td></tr><tr><td>`?GL_CONSTANT_COLOR'</td><td>(R c G c
-%% B c)</td><td>
-%% A c</td></tr><tr><td>`?GL_ONE_MINUS_CONSTANT_COLOR'</td><td>(1 1 1)-(R c G c B c)</td><td> 1-A c</td></tr>
-%% <tr><td>`?GL_CONSTANT_ALPHA'</td><td>(A c A c A c)</td><td> A c</td></tr><tr><td>`?GL_ONE_MINUS_CONSTANT_ALPHA'
-%% </td><td>(1 1 1)-(A c A c A c)</td><td> 1-A c</td></tr><tr><td>`?GL_SRC_ALPHA_SATURATE'</td><td>(i i i)</td><td>
-%% 1</td></tr><tr><td>`?GL_SRC1_COLOR'</td><td>(R s1 k/R G s1 k/G B s1 k/B)</td><td> A s1 k/A</td></tr><tr><td>`?GL_ONE_MINUS_SRC_COLOR'
-%% </td><td>(1 1 1 1)-(R s1 k/R G s1 k/G B s1 k/B)</td><td> 1-A s1 k/A</td></tr><tr><td>`?GL_SRC1_ALPHA'</td><td>(A s1 k/A A
-%% s1 k/A A s1 k/A)</td><td> A
-%% s1 k/A</td></tr><tr><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td>(1 1 1)-(A s1 k/A A s1 k/A A s1 k/A
-%% )</td><td> 1-A s1 k/A</td></tr>
-%% </tbody></table>
-%%
-%% In the table,
-%%
-%% i=min(A s 1-(A d))
-%%
-%% To determine the blended RGBA values of a pixel, the system uses the following equations:
-%%
-%%
-%% R d=min(k R R s s R+R d d R) G d=min(k G G s s G+G d d G) B d=min(k B B s s B+B d d B) A d=min(k A A s s A+A d d A)
-%%
-%% Despite the apparent precision of the above equations, blending arithmetic is not exactly
-%% specified, because blending operates with imprecise integer color values. However, a blend
-%% factor that should be equal to 1 is guaranteed not to modify its multiplicand, and a blend
-%% factor equal to 0 reduces its multiplicand to 0. For example, when `SrcRGB' is `?GL_SRC_ALPHA'
-%% , `DstRGB' is `?GL_ONE_MINUS_SRC_ALPHA', and A s is equal to k A, the equations
-%% reduce to simple replacement:
-%%
-%% R d=R s G d=G s B d=B s A d=A s
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendFuncSeparate.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendFuncSeparate.xhtml">external</a> documentation.
-spec blendFuncSeparate(SfactorRGB, DfactorRGB, SfactorAlpha, DfactorAlpha) -> 'ok' when SfactorRGB :: enum(),DfactorRGB :: enum(),SfactorAlpha :: enum(),DfactorAlpha :: enum().
blendFuncSeparate(SfactorRGB,DfactorRGB,SfactorAlpha,DfactorAlpha) ->
cast(5394, <<SfactorRGB:?GLenum,DfactorRGB:?GLenum,SfactorAlpha:?GLenum,DfactorAlpha:?GLenum>>).
@@ -9646,19 +3865,7 @@ blendFuncSeparate(SfactorRGB,DfactorRGB,SfactorAlpha,DfactorAlpha) ->
%% normals, and colors and use them to construct a sequence of primitives with a single call
%% to ``gl:multiDrawArrays''.
%%
-%% ``gl:multiDrawArrays'' behaves identically to {@link gl:drawArrays/3} except that `Primcount'
-%% separate ranges of elements are specified instead.
-%%
-%% When ``gl:multiDrawArrays'' is called, it uses `Count' sequential elements from
-%% each enabled array to construct a sequence of geometric primitives, beginning with element
-%% `First' . `Mode' specifies what kind of primitives are constructed, and how the
-%% array elements construct those primitives.
-%%
-%% Vertex attributes that are modified by ``gl:multiDrawArrays'' have an unspecified value
-%% after ``gl:multiDrawArrays'' returns. Attributes that aren't modified remain well defined.
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiDrawArrays.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMultiDrawArrays.xhtml">external</a> documentation.
-spec multiDrawArrays(Mode, First, Count) -> 'ok' when Mode :: enum(),First :: [integer()]|mem(),Count :: [integer()]|mem().
multiDrawArrays(Mode,First,Count) when is_list(First), is_list(Count) ->
FirstLen = length(First),
@@ -9677,15 +3884,7 @@ multiDrawArrays(Mode,First,Count) ->
%%
%% The following values are accepted for `Pname' :
%%
-%% `?GL_POINT_FADE_THRESHOLD_SIZE': `Params' is a single floating-point value that
-%% specifies the threshold value to which point sizes are clamped if they exceed the specified
-%% value. The default value is 1.0.
-%%
-%% `?GL_POINT_SPRITE_COORD_ORIGIN': `Params' is a single enum specifying the point
-%% sprite texture coordinate origin, either `?GL_LOWER_LEFT' or `?GL_UPPER_LEFT'.
-%% The default value is `?GL_UPPER_LEFT'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPointParameter.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPointParameter.xhtml">external</a> documentation.
-spec pointParameterf(Pname, Param) -> 'ok' when Pname :: enum(),Param :: float().
pointParameterf(Pname,Param) ->
cast(5397, <<Pname:?GLenum,Param:?GLfloat>>).
@@ -9716,7 +3915,7 @@ pointParameteriv(Pname,Params) ->
%% the current raster position. The value specified is interpolated and used in computing
%% the fog color (see {@link gl:fogf/2} ).
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFogCoord.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glFogCoord.xml">external</a> documentation.
-spec fogCoordf(Coord) -> 'ok' when Coord :: float().
fogCoordf(Coord) ->
cast(5401, <<Coord:?GLfloat>>).
@@ -9742,22 +3941,7 @@ fogCoorddv({Coord}) -> fogCoordd(Coord).
%% specifies the byte stride from one fog coordinate to the next, allowing vertices and
%% attributes to be packed into a single array or stored in separate arrays.
%%
-%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2}
-%% ) while a fog coordinate array is specified, `Pointer' is treated as a byte offset
-%% into the buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING'
-%% ) is saved as fog coordinate vertex array client-side state (`?GL_FOG_COORD_ARRAY_BUFFER_BINDING'
-%% ).
-%%
-%% When a fog coordinate array is specified, `Type' , `Stride' , and `Pointer'
-%% are saved as client-side state, in addition to the current vertex array buffer object
-%% binding.
-%%
-%% To enable and disable the fog coordinate array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1}
-%% with the argument `?GL_FOG_COORD_ARRAY'. If enabled, the fog coordinate array is
-%% used when {@link gl:drawArrays/3} , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements'
-%% , {@link gl:drawRangeElements/6} , or {@link gl:arrayElement/1} is called.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFogCoordPointer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glFogCoordPointer.xml">external</a> documentation.
-spec fogCoordPointer(Type, Stride, Pointer) -> 'ok' when Type :: enum(),Stride :: integer(),Pointer :: offset()|mem().
fogCoordPointer(Type,Stride,Pointer) when is_integer(Pointer) ->
cast(5403, <<Type:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>);
@@ -9770,31 +3954,7 @@ fogCoordPointer(Type,Stride,Pointer) ->
%% The GL stores both a primary four-valued RGBA color and a secondary four-valued RGBA
%% color (where alpha is always set to 0.0) that is associated with every vertex.
%%
-%% The secondary color is interpolated and applied to each fragment during rasterization
-%% when `?GL_COLOR_SUM' is enabled. When lighting is enabled, and `?GL_SEPARATE_SPECULAR_COLOR'
-%% is specified, the value of the secondary color is assigned the value computed from the
-%% specular term of the lighting computation. Both the primary and secondary current colors
-%% are applied to each fragment, regardless of the state of `?GL_COLOR_SUM', under such
-%% conditions. When `?GL_SEPARATE_SPECULAR_COLOR' is specified, the value returned from
-%% querying the current secondary color is undefined.
-%%
-%% ``gl:secondaryColor3b'', ``gl:secondaryColor3s'', and ``gl:secondaryColor3i'' take
-%% three signed byte, short, or long integers as arguments. When `v' is appended to
-%% the name, the color commands can take a pointer to an array of such values.
-%%
-%% Color values are stored in floating-point format, with unspecified mantissa and exponent
-%% sizes. Unsigned integer color components, when specified, are linearly mapped to floating-point
-%% values such that the largest representable value maps to 1.0 (full intensity), and 0 maps
-%% to 0.0 (zero intensity). Signed integer color components, when specified, are linearly
-%% mapped to floating-point values such that the most positive representable value maps to
-%% 1.0, and the most negative representable value maps to -1.0. (Note that this mapping
-%% does not convert 0 precisely to 0.0). Floating-point values are mapped directly.
-%%
-%% Neither floating-point nor signed integer values are clamped to the range [0 1] before the
-%% current color is updated. However, color components are clamped to this range before they
-%% are interpolated or written into a color buffer.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glSecondaryColor.xml">external</a> documentation.
-spec secondaryColor3b(Red, Green, Blue) -> 'ok' when Red :: integer(),Green :: integer(),Blue :: integer().
secondaryColor3b(Red,Green,Blue) ->
cast(5405, <<Red:?GLbyte,Green:?GLbyte,Blue:?GLbyte>>).
@@ -9881,23 +4041,7 @@ secondaryColor3usv({Red,Green,Blue}) -> secondaryColor3us(Red,Green,Blue).
%% specifies the byte stride from one color to the next, allowing vertices and attributes
%% to be packed into a single array or stored in separate arrays.
%%
-%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2}
-%% ) while a secondary color array is specified, `Pointer' is treated as a byte offset
-%% into the buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING'
-%% ) is saved as secondary color vertex array client-side state (`?GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING'
-%% ).
-%%
-%% When a secondary color array is specified, `Size' , `Type' , `Stride' , and `Pointer'
-%% are saved as client-side state, in addition to the current vertex array buffer object
-%% binding.
-%%
-%% To enable and disable the secondary color array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1}
-%% with the argument `?GL_SECONDARY_COLOR_ARRAY'. If enabled, the secondary color array
-%% is used when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:multiDrawArrays/3} ,
-%% {@link gl:drawElements/4} , see `glMultiDrawElements', or {@link gl:drawRangeElements/6}
-%% is called.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColorPointer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glSecondaryColorPointer.xml">external</a> documentation.
-spec secondaryColorPointer(Size, Type, Stride, Pointer) -> 'ok' when Size :: integer(),Type :: enum(),Stride :: integer(),Pointer :: offset()|mem().
secondaryColorPointer(Size,Type,Stride,Pointer) when is_integer(Pointer) ->
cast(5413, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>);
@@ -9912,38 +4056,7 @@ secondaryColorPointer(Size,Type,Stride,Pointer) ->
%% subpixel accuracy. See {@link gl:bitmap/7} , {@link gl:drawPixels/5} , and {@link gl:copyPixels/5}
%% .
%%
-%% ``gl:windowPos2'' specifies the x and y coordinates, while z is implicitly set
-%% to 0. ``gl:windowPos3'' specifies all three coordinates. The w coordinate of the current
-%% raster position is always set to 1.0.
-%%
-%% ``gl:windowPos'' directly updates the x and y coordinates of the current raster
-%% position with the values specified. That is, the values are neither transformed by the
-%% current modelview and projection matrices, nor by the viewport-to-window transform. The
-%% z coordinate of the current raster position is updated in the following manner:
-%%
-%% z={n f(n+z×(f-n)) if z&lt;= 0 if z&gt;= 1(otherwise))
-%%
-%% where n is `?GL_DEPTH_RANGE''s near value, and f is `?GL_DEPTH_RANGE''s
-%% far value. See {@link gl:depthRange/2} .
-%%
-%% The specified coordinates are not clip-tested, causing the raster position to always
-%% be valid.
-%%
-%% The current raster position also includes some associated color data and texture coordinates.
-%% If lighting is enabled, then `?GL_CURRENT_RASTER_COLOR' (in RGBA mode) or `?GL_CURRENT_RASTER_INDEX'
-%% (in color index mode) is set to the color produced by the lighting calculation (see {@link gl:lightf/3}
-%% , {@link gl:lightModelf/2} , and {@link gl:shadeModel/1} ). If lighting is disabled, current
-%% color (in RGBA mode, state variable `?GL_CURRENT_COLOR') or color index (in color
-%% index mode, state variable `?GL_CURRENT_INDEX') is used to update the current raster
-%% color. `?GL_CURRENT_RASTER_SECONDARY_COLOR' (in RGBA mode) is likewise updated.
-%%
-%% Likewise, `?GL_CURRENT_RASTER_TEXTURE_COORDS' is updated as a function of `?GL_CURRENT_TEXTURE_COORDS'
-%% , based on the texture matrix and the texture generation functions (see {@link gl:texGend/3} ).
-%% The `?GL_CURRENT_RASTER_DISTANCE' is set to the `?GL_CURRENT_FOG_COORD'.
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glWindowPos.xml">external</a> documentation.
-spec windowPos2d(X, Y) -> 'ok' when X :: float(),Y :: float().
windowPos2d(X,Y) ->
cast(5415, <<X:?GLdouble,Y:?GLdouble>>).
@@ -10028,13 +4141,7 @@ windowPos3sv({X,Y,Z}) -> windowPos3s(X,Y,Z).
%% that the names form a contiguous set of integers; however, it is guaranteed that none
%% of the returned names was in use immediately before the call to ``gl:genQueries''.
%%
-%% Query object names returned by a call to ``gl:genQueries'' are not returned by subsequent
-%% calls, unless they are first deleted with {@link gl:deleteQueries/1} .
-%%
-%% No query objects are associated with the returned query object names until they are first
-%% used by calling {@link gl:beginQuery/2} .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenQueries.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenQueries.xhtml">external</a> documentation.
-spec genQueries(N) -> [integer()] when N :: integer().
genQueries(N) ->
call(5423, <<N:?GLsizei>>).
@@ -10045,10 +4152,7 @@ genQueries(N) ->
%% . After a query object is deleted, it has no contents, and its name is free for reuse
%% (for example by {@link gl:genQueries/1} ).
%%
-%% ``gl:deleteQueries'' silently ignores 0's and names that do not correspond to existing
-%% query objects.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteQueries.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteQueries.xhtml">external</a> documentation.
-spec deleteQueries(Ids) -> 'ok' when Ids :: [integer()].
deleteQueries(Ids) ->
IdsLen = length(Ids),
@@ -10061,10 +4165,7 @@ deleteQueries(Ids) ->
%% object. If `Id' is zero, or is a non-zero value that is not currently the name of
%% a query object, or if an error occurs, ``gl:isQuery'' returns `?GL_FALSE'.
%%
-%% A name returned by {@link gl:genQueries/1} , but not yet associated with a query object
-%% by calling {@link gl:beginQuery/2} , is not the name of a query object.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsQuery.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsQuery.xhtml">external</a> documentation.
-spec isQuery(Id) -> 0|1 when Id :: integer().
isQuery(Id) ->
call(5425, <<Id:?GLuint>>).
@@ -10078,60 +4179,7 @@ isQuery(Id) ->
%% , `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN', or `?GL_TIME_ELAPSED'. The behavior
%% of the query object depends on its type and is as follows.
%%
-%% If `Target' is `?GL_SAMPLES_PASSED', `Id' must be an unused name, or the
-%% name of an existing occlusion query object. When ``gl:beginQuery'' is executed, the
-%% query object's samples-passed counter is reset to 0. Subsequent rendering will increment
-%% the counter for every sample that passes the depth test. If the value of `?GL_SAMPLE_BUFFERS'
-%% is 0, then the samples-passed count is incremented by 1 for each fragment. If the value
-%% of `?GL_SAMPLE_BUFFERS' is 1, then the samples-passed count is incremented by the
-%% number of samples whose coverage bit is set. However, implementations, at their discression
-%% may instead increase the samples-passed count by the value of `?GL_SAMPLES' if any
-%% sample in the fragment is covered. When ``gl:endQuery'' is executed, the samples-passed
-%% counter is assigned to the query object's result value. This value can be queried by calling
-%% {@link gl:getQueryObjectiv/2} with `Pname' `?GL_QUERY_RESULT'.
-%%
-%% If `Target' is `?GL_ANY_SAMPLES_PASSED', `Id' must be an unused name,
-%% or the name of an existing boolean occlusion query object. When ``gl:beginQuery'' is
-%% executed, the query object's samples-passed flag is reset to `?GL_FALSE'. Subsequent
-%% rendering causes the flag to be set to `?GL_TRUE' if any sample passes the depth
-%% test. When ``gl:endQuery'' is executed, the samples-passed flag is assigned to the query
-%% object's result value. This value can be queried by calling {@link gl:getQueryObjectiv/2}
-%% with `Pname' `?GL_QUERY_RESULT'.
-%%
-%% If `Target' is `?GL_PRIMITIVES_GENERATED', `Id' must be an unused name,
-%% or the name of an existing primitive query object previously bound to the `?GL_PRIMITIVES_GENERATED'
-%% query binding. When ``gl:beginQuery'' is executed, the query object's primitives-generated
-%% counter is reset to 0. Subsequent rendering will increment the counter once for every
-%% vertex that is emitted from the geometry shader, or from the vertex shader if no geometry
-%% shader is present. When ``gl:endQuery'' is executed, the primitives-generated counter
-%% is assigned to the query object's result value. This value can be queried by calling {@link gl:getQueryObjectiv/2}
-%% with `Pname' `?GL_QUERY_RESULT'.
-%%
-%% If `Target' is `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN', `Id' must
-%% be an unused name, or the name of an existing primitive query object previously bound
-%% to the `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN' query binding. When ``gl:beginQuery''
-%% is executed, the query object's primitives-written counter is reset to 0. Subsequent
-%% rendering will increment the counter once for every vertex that is written into the bound
-%% transform feedback buffer(s). If transform feedback mode is not activated between the
-%% call to ``gl:beginQuery'' and ``gl:endQuery'', the counter will not be incremented.
-%% When ``gl:endQuery'' is executed, the primitives-written counter is assigned to the
-%% query object's result value. This value can be queried by calling {@link gl:getQueryObjectiv/2}
-%% with `Pname' `?GL_QUERY_RESULT'.
-%%
-%% If `Target' is `?GL_TIME_ELAPSED', `Id' must be an unused name, or the
-%% name of an existing timer query object previously bound to the `?GL_TIME_ELAPSED'
-%% query binding. When ``gl:beginQuery'' is executed, the query object's time counter is
-%% reset to 0. When ``gl:endQuery'' is executed, the elapsed server time that has passed
-%% since the call to ``gl:beginQuery'' is written into the query object's time counter.
-%% This value can be queried by calling {@link gl:getQueryObjectiv/2} with `Pname' `?GL_QUERY_RESULT'
-%% .
-%%
-%% Querying the `?GL_QUERY_RESULT' implicitly flushes the GL pipeline until the rendering
-%% delimited by the query object has completed and the result is available. `?GL_QUERY_RESULT_AVAILABLE'
-%% can be queried to determine if the result is immediately available or if the rendering
-%% is not yet complete.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginQuery.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBeginQuery.xhtml">external</a> documentation.
-spec beginQuery(Target, Id) -> 'ok' when Target :: enum(),Id :: integer().
beginQuery(Target,Id) ->
cast(5426, <<Target:?GLenum,Id:?GLuint>>).
@@ -10144,7 +4192,7 @@ endQuery(Target) ->
%% @doc glGetQuery
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQuery.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getQueryiv(Target, Pname) -> integer() when Target :: enum(),Pname :: enum().
getQueryiv(Target,Pname) ->
call(5428, <<Target:?GLenum,Pname:?GLenum>>).
@@ -10154,17 +4202,7 @@ getQueryiv(Target,Pname) ->
%% ``gl:getQueryObject'' returns in `Params' a selected parameter of the query object
%% specified by `Id' .
%%
-%% `Pname' names a specific query object parameter. `Pname' can be as follows:
-%%
-%% `?GL_QUERY_RESULT': `Params' returns the value of the query object's passed
-%% samples counter. The initial value is 0.
-%%
-%% `?GL_QUERY_RESULT_AVAILABLE': `Params' returns whether the passed samples counter
-%% is immediately available. If a delay would occur waiting for the query result, `?GL_FALSE'
-%% is returned. Otherwise, `?GL_TRUE' is returned, which also indicates that the results
-%% of all previous queries are available as well.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryObject.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetQueryObject.xhtml">external</a> documentation.
-spec getQueryObjectiv(Id, Pname) -> integer() when Id :: integer(),Pname :: enum().
getQueryObjectiv(Id,Pname) ->
call(5429, <<Id:?GLuint,Pname:?GLenum>>).
@@ -10183,77 +4221,7 @@ getQueryObjectuiv(Id,Pname) ->
%% object with name `Buffer' exists, one is created with that name. When a buffer object
%% is bound to a target, the previous binding for that target is automatically broken.
%%
-%% Buffer object names are unsigned integers. The value zero is reserved, but there is no
-%% default buffer object for each buffer object target. Instead, `Buffer' set to zero
-%% effectively unbinds any buffer object previously bound, and restores client memory usage
-%% for that buffer object target (if supported for that target). Buffer object names and
-%% the corresponding buffer object contents are local to the shared object space of the current
-%% GL rendering context; two rendering contexts share buffer object names only if they explicitly
-%% enable sharing between contexts through the appropriate GL windows interfaces functions.
-%%
-%% {@link gl:genBuffers/1} must be used to generate a set of unused buffer object names.
-%%
-%% The state of a buffer object immediately after it is first bound is an unmapped zero-sized
-%% memory buffer with `?GL_READ_WRITE' access and `?GL_STATIC_DRAW' usage.
-%%
-%% While a non-zero buffer object name is bound, GL operations on the target to which it
-%% is bound affect the bound buffer object, and queries of the target to which it is bound
-%% return state from the bound buffer object. While buffer object name zero is bound, as
-%% in the initial state, attempts to modify or query state on the target to which it is bound
-%% generates an `?GL_INVALID_OPERATION' error.
-%%
-%% When a non-zero buffer object is bound to the `?GL_ARRAY_BUFFER' target, the vertex
-%% array pointer parameter is interpreted as an offset within the buffer object measured
-%% in basic machine units.
-%%
-%% When a non-zero buffer object is bound to the `?GL_DRAW_INDIRECT_BUFFER' target,
-%% parameters for draws issued through {@link gl:drawArraysIndirect/2} and {@link gl:drawElementsIndirect/3}
-%% are sourced from that buffer object.
-%%
-%% While a non-zero buffer object is bound to the `?GL_ELEMENT_ARRAY_BUFFER' target,
-%% the indices parameter of {@link gl:drawElements/4} , {@link gl:drawElementsInstanced/5} , {@link gl:drawElementsBaseVertex/5}
-%% , {@link gl:drawRangeElements/6} , {@link gl:drawRangeElementsBaseVertex/7} , see `glMultiDrawElements'
-%% , or see `glMultiDrawElementsBaseVertex' is interpreted as an offset within the
-%% buffer object measured in basic machine units.
-%%
-%% While a non-zero buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target,
-%% the following commands are affected: {@link gl:getCompressedTexImage/3} , {@link gl:getTexImage/5}
-%% , and {@link gl:readPixels/7} . The pointer parameter is interpreted as an offset within
-%% the buffer object measured in basic machine units.
-%%
-%% While a non-zero buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target,
-%% the following commands are affected: {@link gl:compressedTexImage1D/7} , {@link gl:compressedTexImage2D/8}
-%% , {@link gl:compressedTexImage3D/9} , {@link gl:compressedTexSubImage1D/7} , {@link gl:compressedTexSubImage2D/9}
-%% , {@link gl:compressedTexSubImage3D/11} , {@link gl:texImage1D/8} , {@link gl:texImage2D/9} , {@link gl:texImage3D/10}
-%% , {@link gl:texSubImage1D/7} , {@link gl:texSubImage1D/7} , and {@link gl:texSubImage1D/7} .
-%% The pointer parameter is interpreted as an offset within the buffer object measured in
-%% basic machine units.
-%%
-%% The buffer targets `?GL_COPY_READ_BUFFER' and `?GL_COPY_WRITE_BUFFER' are provided
-%% to allow {@link gl:copyBufferSubData/5} to be used without disturbing the state of other
-%% bindings. However, {@link gl:copyBufferSubData/5} may be used with any pair of buffer binding
-%% points.
-%%
-%% The `?GL_TRANSFORM_FEEDBACK_BUFFER' buffer binding point may be passed to ``gl:bindBuffer''
-%% , but will not directly affect transform feedback state. Instead, the indexed `?GL_TRANSFORM_FEEDBACK_BUFFER'
-%% bindings must be used through a call to {@link gl:bindBufferBase/3} or {@link gl:bindBufferRange/5}
-%% . This will affect the generic `?GL_TRANSFORM_FEEDABCK_BUFFER' binding.
-%%
-%% Likewise, the `?GL_UNIFORM_BUFFER' and `?GL_ATOMIC_COUNTER_BUFFER' buffer binding
-%% points may be used, but do not directly affect uniform buffer or atomic counter buffer
-%% state, respectively. {@link gl:bindBufferBase/3} or {@link gl:bindBufferRange/5} must be
-%% used to bind a buffer to an indexed uniform buffer or atomic counter buffer binding point.
-%%
-%%
-%% A buffer object binding created with ``gl:bindBuffer'' remains active until a different
-%% buffer object name is bound to the same target, or until the bound buffer object is deleted
-%% with {@link gl:deleteBuffers/1} .
-%%
-%% Once created, a named buffer object may be re-bound to any target as often as needed.
-%% However, the GL implementation may make choices about how to optimize the storage of a
-%% buffer object based on its initial binding target.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindBuffer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindBuffer.xhtml">external</a> documentation.
-spec bindBuffer(Target, Buffer) -> 'ok' when Target :: enum(),Buffer :: integer().
bindBuffer(Target,Buffer) ->
cast(5431, <<Target:?GLenum,Buffer:?GLuint>>).
@@ -10265,10 +4233,7 @@ bindBuffer(Target,Buffer) ->
%% free for reuse (for example by {@link gl:genBuffers/1} ). If a buffer object that is currently
%% bound is deleted, the binding reverts to 0 (the absence of any buffer object).
%%
-%% ``gl:deleteBuffers'' silently ignores 0's and names that do not correspond to existing
-%% buffer objects.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteBuffers.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteBuffers.xhtml">external</a> documentation.
-spec deleteBuffers(Buffers) -> 'ok' when Buffers :: [integer()].
deleteBuffers(Buffers) ->
BuffersLen = length(Buffers),
@@ -10282,13 +4247,7 @@ deleteBuffers(Buffers) ->
%% that none of the returned names was in use immediately before the call to ``gl:genBuffers''
%% .
%%
-%% Buffer object names returned by a call to ``gl:genBuffers'' are not returned by subsequent
-%% calls, unless they are first deleted with {@link gl:deleteBuffers/1} .
-%%
-%% No buffer objects are associated with the returned buffer object names until they are
-%% first bound by calling {@link gl:bindBuffer/2} .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenBuffers.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenBuffers.xhtml">external</a> documentation.
-spec genBuffers(N) -> [integer()] when N :: integer().
genBuffers(N) ->
call(5433, <<N:?GLsizei>>).
@@ -10300,10 +4259,7 @@ genBuffers(N) ->
%% the name of a buffer object, or if an error occurs, ``gl:isBuffer'' returns `?GL_FALSE'
%% .
%%
-%% A name returned by {@link gl:genBuffers/1} , but not yet associated with a buffer object
-%% by calling {@link gl:bindBuffer/2} , is not the name of a buffer object.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsBuffer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsBuffer.xhtml">external</a> documentation.
-spec isBuffer(Buffer) -> 0|1 when Buffer :: integer().
isBuffer(Buffer) ->
call(5434, <<Buffer:?GLuint>>).
@@ -10317,31 +4273,7 @@ isBuffer(Buffer) ->
%% is not mapped, it has a `?NULL' mapped pointer, and its mapped access is `?GL_READ_WRITE'
%% .
%%
-%% `Usage' is a hint to the GL implementation as to how a buffer object's data store
-%% will be accessed. This enables the GL implementation to make more intelligent decisions
-%% that may significantly impact buffer object performance. It does not, however, constrain
-%% the actual usage of the data store. `Usage' can be broken down into two parts: first,
-%% the frequency of access (modification and usage), and second, the nature of that access.
-%% The frequency of access may be one of these:
-%%
-%% STREAM: The data store contents will be modified once and used at most a few times.
-%%
-%% STATIC: The data store contents will be modified once and used many times.
-%%
-%% DYNAMIC: The data store contents will be modified repeatedly and used many times.
-%%
-%% The nature of access may be one of these:
-%%
-%% DRAW: The data store contents are modified by the application, and used as the source
-%% for GL drawing and image specification commands.
-%%
-%% READ: The data store contents are modified by reading data from the GL, and used to return
-%% that data when queried by the application.
-%%
-%% COPY: The data store contents are modified by reading data from the GL, and used as the
-%% source for GL drawing and image specification commands.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBufferData.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferData.xhtml">external</a> documentation.
-spec bufferData(Target, Size, Data, Usage) -> 'ok' when Target :: enum(),Size :: integer(),Data :: offset()|mem(),Usage :: enum().
bufferData(Target,Size,Data,Usage) when is_integer(Data) ->
cast(5435, <<Target:?GLenum,0:32,Size:?GLsizeiptr,Data:?GLuint,Usage:?GLenum>>);
@@ -10357,7 +4289,7 @@ bufferData(Target,Size,Data,Usage) ->
%% is thrown if `Offset' and `Size' together define a range beyond the bounds of
%% the buffer object's data store.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBufferSubData.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferSubData.xhtml">external</a> documentation.
-spec bufferSubData(Target, Offset, Size, Data) -> 'ok' when Target :: enum(),Offset :: integer(),Size :: integer(),Data :: offset()|mem().
bufferSubData(Target,Offset,Size,Data) when is_integer(Data) ->
cast(5437, <<Target:?GLenum,0:32,Offset:?GLintptr,Size:?GLsizeiptr,Data:?GLuint>>);
@@ -10373,7 +4305,7 @@ bufferSubData(Target,Offset,Size,Data) ->
%% is thrown if the buffer object is currently mapped, or if `Offset' and `Size'
%% together define a range beyond the bounds of the buffer object's data store.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferSubData.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetBufferSubData.xhtml">external</a> documentation.
-spec getBufferSubData(Target, Offset, Size, Data) -> 'ok' when Target :: enum(),Offset :: integer(),Size :: integer(),Data :: mem().
getBufferSubData(Target,Offset,Size,Data) ->
send_bin(Data),
@@ -10384,21 +4316,7 @@ getBufferSubData(Target,Offset,Size,Data) ->
%% ``gl:getBufferParameteriv'' returns in `Data' a selected parameter of the buffer
%% object specified by `Target' .
%%
-%% `Value' names a specific buffer object parameter, as follows:
-%%
-%% `?GL_BUFFER_ACCESS': `Params' returns the access policy set while mapping the
-%% buffer object. The initial value is `?GL_READ_WRITE'.
-%%
-%% `?GL_BUFFER_MAPPED': `Params' returns a flag indicating whether the buffer object
-%% is currently mapped. The initial value is `?GL_FALSE'.
-%%
-%% `?GL_BUFFER_SIZE': `Params' returns the size of the buffer object, measured
-%% in bytes. The initial value is 0.
-%%
-%% `?GL_BUFFER_USAGE': `Params' returns the buffer object's usage pattern. The
-%% initial value is `?GL_STATIC_DRAW'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferParameteriv.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetBufferParameteriv.xml">external</a> documentation.
-spec getBufferParameteriv(Target, Pname) -> integer() when Target :: enum(),Pname :: enum().
getBufferParameteriv(Target,Pname) ->
call(5440, <<Target:?GLenum,Pname:?GLenum>>).
@@ -10412,35 +4330,7 @@ getBufferParameteriv(Target,Pname) ->
%% draw buffer whereas ``gl:blendEquationSeparate'' sets the blend equations for all draw
%% buffers.
%%
-%% The blend equations use the source and destination blend factors specified by either {@link gl:blendFunc/2}
-%% or {@link gl:blendFuncSeparate/4} . See {@link gl:blendFunc/2} or {@link gl:blendFuncSeparate/4}
-%% for a description of the various blend factors.
-%%
-%% In the equations that follow, source and destination color components are referred to
-%% as (R s G s B s A s) and (R d G d B d A d), respectively. The result color is referred to as (R r G r B r A r). The source and destination
-%% blend factors are denoted (s R s G s B s A) and (d R d G d B d A), respectively. For these equations all color components
-%% are understood to have values in the range [0 1]. <table><tbody><tr><td>` Mode '</td><td>
-%% ` RGB Components '</td><td>` Alpha Component '</td></tr></tbody><tbody><tr><td>`?GL_FUNC_ADD'
-%% </td><td> Rr=R s s R+R d d R Gr=G s s G+G d d G Br=B s s B+B d d B</td><td> Ar=A s
-%% s A+A d d A</td></tr><tr><td>`?GL_FUNC_SUBTRACT'</td><td> Rr=R s s R-R d d R Gr=G
-%% s s G-G d d G Br=B s s B-B d d B</td><td> Ar=A s s A-A d d A</td></tr><tr><td>`?GL_FUNC_REVERSE_SUBTRACT'
-%% </td><td> Rr=R d d R-R s s R Gr=G d d G-G s s G Br=B d d B-B s s B</td><td> Ar=A d
-%% d A-A s s A</td></tr><tr><td>`?GL_MIN'</td><td> Rr=min(R s R d) Gr=min(G s G d) Br=min(B s B d)</td><td> Ar=min
-%% (A s A d)</td></tr><tr><td>`?GL_MAX'</td><td> Rr=max(R s R d) Gr=max(G s G d) Br=max(B s B d)</td><td> Ar=max(A s A d)</td></tr></tbody>
-%% </table>
-%%
-%% The results of these equations are clamped to the range [0 1].
-%%
-%% The `?GL_MIN' and `?GL_MAX' equations are useful for applications that analyze
-%% image data (image thresholding against a constant color, for example). The `?GL_FUNC_ADD'
-%% equation is useful for antialiasing and transparency, among other things.
-%%
-%% Initially, both the RGB blend equation and the alpha blend equation are set to `?GL_FUNC_ADD'
-%% .
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquationSeparate.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendEquationSeparate.xhtml">external</a> documentation.
-spec blendEquationSeparate(ModeRGB, ModeAlpha) -> 'ok' when ModeRGB :: enum(),ModeAlpha :: enum().
blendEquationSeparate(ModeRGB,ModeAlpha) ->
cast(5441, <<ModeRGB:?GLenum,ModeAlpha:?GLenum>>).
@@ -10455,32 +4345,7 @@ blendEquationSeparate(ModeRGB,ModeAlpha) ->
%% or equal to `N' is implicitly set to `?GL_NONE' and any data written to such
%% an output is discarded.
%%
-%% The symbolic constants contained in `Bufs' may be any of the following:
-%%
-%% `?GL_NONE': The fragment shader output value is not written into any color buffer.
-%%
-%% `?GL_FRONT_LEFT': The fragment shader output value is written into the front left
-%% color buffer.
-%%
-%% `?GL_FRONT_RIGHT': The fragment shader output value is written into the front right
-%% color buffer.
-%%
-%% `?GL_BACK_LEFT': The fragment shader output value is written into the back left color
-%% buffer.
-%%
-%% `?GL_BACK_RIGHT': The fragment shader output value is written into the back right
-%% color buffer.
-%%
-%% `?GL_COLOR_ATTACHMENT'`n': The fragment shader output value is written into
-%% the `n'th color attachment of the current framebuffer. `n' may range from 0
-%% to the value of `?GL_MAX_COLOR_ATTACHMENTS'.
-%%
-%% Except for `?GL_NONE', the preceding symbolic constants may not appear more than
-%% once in `Bufs' . The maximum number of draw buffers supported is implementation dependent
-%% and can be queried by calling {@link gl:getBooleanv/1} with the argument `?GL_MAX_DRAW_BUFFERS'
-%% .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawBuffers.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawBuffers.xhtml">external</a> documentation.
-spec drawBuffers(Bufs) -> 'ok' when Bufs :: [enum()].
drawBuffers(Bufs) ->
BufsLen = length(Bufs),
@@ -10495,55 +4360,7 @@ drawBuffers(Bufs) ->
%% used in multipass rendering algorithms to achieve special effects, such as decals, outlining,
%% and constructive solid geometry rendering.
%%
-%% The stencil test conditionally eliminates a pixel based on the outcome of a comparison
-%% between the value in the stencil buffer and a reference value. To enable and disable the
-%% test, call {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_STENCIL_TEST'
-%% ; to control it, call {@link gl:stencilFunc/3} or {@link gl:stencilFuncSeparate/4} .
-%%
-%% There can be two separate sets of `Sfail' , `Dpfail' , and `Dppass' parameters;
-%% one affects back-facing polygons, and the other affects front-facing polygons as well
-%% as other non-polygon primitives. {@link gl:stencilOp/3} sets both front and back stencil
-%% state to the same values, as if {@link gl:stencilOpSeparate/4} were called with `Face'
-%% set to `?GL_FRONT_AND_BACK'.
-%%
-%% ``gl:stencilOpSeparate'' takes three arguments that indicate what happens to the stored
-%% stencil value while stenciling is enabled. If the stencil test fails, no change is made
-%% to the pixel's color or depth buffers, and `Sfail' specifies what happens to the
-%% stencil buffer contents. The following eight actions are possible.
-%%
-%% `?GL_KEEP': Keeps the current value.
-%%
-%% `?GL_ZERO': Sets the stencil buffer value to 0.
-%%
-%% `?GL_REPLACE': Sets the stencil buffer value to `ref', as specified by {@link gl:stencilFunc/3}
-%% .
-%%
-%% `?GL_INCR': Increments the current stencil buffer value. Clamps to the maximum representable
-%% unsigned value.
-%%
-%% `?GL_INCR_WRAP': Increments the current stencil buffer value. Wraps stencil buffer
-%% value to zero when incrementing the maximum representable unsigned value.
-%%
-%% `?GL_DECR': Decrements the current stencil buffer value. Clamps to 0.
-%%
-%% `?GL_DECR_WRAP': Decrements the current stencil buffer value. Wraps stencil buffer
-%% value to the maximum representable unsigned value when decrementing a stencil buffer value
-%% of zero.
-%%
-%% `?GL_INVERT': Bitwise inverts the current stencil buffer value.
-%%
-%% Stencil buffer values are treated as unsigned integers. When incremented and decremented,
-%% values are clamped to 0 and 2 n-1, where n is the value returned by querying `?GL_STENCIL_BITS'
-%% .
-%%
-%% The other two arguments to ``gl:stencilOpSeparate'' specify stencil buffer actions
-%% that depend on whether subsequent depth buffer tests succeed ( `Dppass' ) or fail ( `Dpfail'
-%% ) (see {@link gl:depthFunc/1} ). The actions are specified using the same eight symbolic
-%% constants as `Sfail' . Note that `Dpfail' is ignored when there is no depth buffer,
-%% or when the depth buffer is not enabled. In these cases, `Sfail' and `Dppass'
-%% specify stencil action when the stencil test fails and passes, respectively.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilOpSeparate.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glStencilOpSeparate.xhtml">external</a> documentation.
-spec stencilOpSeparate(Face, Sfail, Dpfail, Dppass) -> 'ok' when Face :: enum(),Sfail :: enum(),Dpfail :: enum(),Dppass :: enum().
stencilOpSeparate(Face,Sfail,Dpfail,Dppass) ->
cast(5443, <<Face:?GLenum,Sfail:?GLenum,Dpfail:?GLenum,Dppass:?GLenum>>).
@@ -10556,57 +4373,7 @@ stencilOpSeparate(Face,Sfail,Dpfail,Dppass) ->
%% used in multipass rendering algorithms to achieve special effects, such as decals, outlining,
%% and constructive solid geometry rendering.
%%
-%% The stencil test conditionally eliminates a pixel based on the outcome of a comparison
-%% between the reference value and the value in the stencil buffer. To enable and disable
-%% the test, call {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_STENCIL_TEST'
-%% . To specify actions based on the outcome of the stencil test, call {@link gl:stencilOp/3}
-%% or {@link gl:stencilOpSeparate/4} .
-%%
-%% There can be two separate sets of `Func' , `Ref' , and `Mask' parameters;
-%% one affects back-facing polygons, and the other affects front-facing polygons as well
-%% as other non-polygon primitives. {@link gl:stencilFunc/3} sets both front and back stencil
-%% state to the same values, as if {@link gl:stencilFuncSeparate/4} were called with `Face'
-%% set to `?GL_FRONT_AND_BACK'.
-%%
-%% `Func' is a symbolic constant that determines the stencil comparison function. It
-%% accepts one of eight values, shown in the following list. `Ref' is an integer reference
-%% value that is used in the stencil comparison. It is clamped to the range [0 2 n-1], where n
-%% is the number of bitplanes in the stencil buffer. `Mask' is bitwise ANDed with both
-%% the reference value and the stored stencil value, with the ANDed values participating
-%% in the comparison.
-%%
-%% If `stencil' represents the value stored in the corresponding stencil buffer location,
-%% the following list shows the effect of each comparison function that can be specified by `Func'
-%% . Only if the comparison succeeds is the pixel passed through to the next stage in the
-%% rasterization process (see {@link gl:stencilOp/3} ). All tests treat `stencil' values
-%% as unsigned integers in the range [0 2 n-1], where n is the number of bitplanes in the stencil
-%% buffer.
-%%
-%% The following values are accepted by `Func' :
-%%
-%% `?GL_NEVER': Always fails.
-%%
-%% `?GL_LESS': Passes if ( `Ref' &amp; `Mask' ) &lt; ( `stencil' &amp; `Mask'
-%% ).
-%%
-%% `?GL_LEQUAL': Passes if ( `Ref' &amp; `Mask' ) &lt;= ( `stencil'
-%% &amp; `Mask' ).
-%%
-%% `?GL_GREATER': Passes if ( `Ref' &amp; `Mask' ) &gt; ( `stencil'
-%% &amp; `Mask' ).
-%%
-%% `?GL_GEQUAL': Passes if ( `Ref' &amp; `Mask' ) &gt;= ( `stencil'
-%% &amp; `Mask' ).
-%%
-%% `?GL_EQUAL': Passes if ( `Ref' &amp; `Mask' ) = ( `stencil' &amp; `Mask'
-%% ).
-%%
-%% `?GL_NOTEQUAL': Passes if ( `Ref' &amp; `Mask' ) != ( `stencil' &amp;
-%% `Mask' ).
-%%
-%% `?GL_ALWAYS': Always passes.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilFuncSeparate.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glStencilFuncSeparate.xhtml">external</a> documentation.
-spec stencilFuncSeparate(Face, Func, Ref, Mask) -> 'ok' when Face :: enum(),Func :: enum(),Ref :: integer(),Mask :: integer().
stencilFuncSeparate(Face,Func,Ref,Mask) ->
cast(5444, <<Face:?GLenum,Func:?GLenum,Ref:?GLint,Mask:?GLuint>>).
@@ -10619,12 +4386,7 @@ stencilFuncSeparate(Face,Func,Ref,Mask) ->
%% to the corresponding bit in the stencil buffer. Where a 0 appears, the corresponding bit
%% is write-protected. Initially, all bits are enabled for writing.
%%
-%% There can be two separate `Mask' writemasks; one affects back-facing polygons, and
-%% the other affects front-facing polygons as well as other non-polygon primitives. {@link gl:stencilMask/1}
-%% sets both front and back stencil writemasks to the same values, as if {@link gl:stencilMaskSeparate/2}
-%% were called with `Face' set to `?GL_FRONT_AND_BACK'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilMaskSeparate.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glStencilMaskSeparate.xhtml">external</a> documentation.
-spec stencilMaskSeparate(Face, Mask) -> 'ok' when Face :: enum(),Mask :: integer().
stencilMaskSeparate(Face,Mask) ->
cast(5445, <<Face:?GLenum,Mask:?GLuint>>).
@@ -10638,17 +4400,7 @@ stencilMaskSeparate(Face,Mask) ->
%% the program object specified by `Program' . This indicates that `Shader' will
%% be included in link operations that will be performed on `Program' .
%%
-%% All operations that can be performed on a shader object are valid whether or not the
-%% shader object is attached to a program object. It is permissible to attach a shader object
-%% to a program object before source code has been loaded into the shader object or before
-%% the shader object has been compiled. It is permissible to attach multiple shader objects
-%% of the same type because each may contain a portion of the complete shader. It is also
-%% permissible to attach a shader object to more than one program object. If a shader object
-%% is deleted while it is attached to a program object, it will be flagged for deletion,
-%% and deletion will not occur until {@link gl:detachShader/2} is called to detach it from
-%% all program objects to which it is attached.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAttachShader.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glAttachShader.xhtml">external</a> documentation.
-spec attachShader(Program, Shader) -> 'ok' when Program :: integer(),Shader :: integer().
attachShader(Program,Shader) ->
cast(5446, <<Program:?GLuint,Shader:?GLuint>>).
@@ -10663,29 +4415,7 @@ attachShader(Program,Shader) ->
%% attribute `Index' will modify the value of the user-defined attribute variable specified
%% by `Name' .
%%
-%% If `Name' refers to a matrix attribute variable, `Index' refers to the first
-%% column of the matrix. Other matrix columns are then automatically bound to locations `Index+1'
-%% for a matrix of type `mat2'; `Index+1' and `Index+2' for a matrix of type
-%% `mat3'; and `Index+1' , `Index+2' , and `Index+3' for a matrix of type `mat4'
-%% .
-%%
-%% This command makes it possible for vertex shaders to use descriptive names for attribute
-%% variables rather than generic variables that are numbered from 0 to `?GL_MAX_VERTEX_ATTRIBS'
-%% -1. The values sent to each generic attribute index are part of current state. If a different
-%% program object is made current by calling {@link gl:useProgram/1} , the generic vertex attributes
-%% are tracked in such a way that the same values will be observed by attributes in the new
-%% program object that are also bound to `Index' .
-%%
-%% Attribute variable name-to-generic attribute index bindings for a program object can be
-%% explicitly assigned at any time by calling ``gl:bindAttribLocation''. Attribute bindings
-%% do not go into effect until {@link gl:linkProgram/1} is called. After a program object
-%% has been linked successfully, the index values for generic attributes remain fixed (and
-%% their values can be queried) until the next link command occurs.
-%%
-%% Any attribute binding that occurs after the program object has been linked will not take
-%% effect until the next time the program object is linked.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindAttribLocation.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindAttribLocation.xhtml">external</a> documentation.
-spec bindAttribLocation(Program, Index, Name) -> 'ok' when Program :: integer(),Index :: integer(),Name :: string().
bindAttribLocation(Program,Index,Name) ->
NameLen = length(Name),
@@ -10696,17 +4426,7 @@ bindAttribLocation(Program,Index,Name) ->
%% ``gl:compileShader'' compiles the source code strings that have been stored in the shader
%% object specified by `Shader' .
%%
-%% The compilation status will be stored as part of the shader object's state. This value
-%% will be set to `?GL_TRUE' if the shader was compiled without errors and is ready
-%% for use, and `?GL_FALSE' otherwise. It can be queried by calling {@link gl:getShaderiv/2}
-%% with arguments `Shader' and `?GL_COMPILE_STATUS'.
-%%
-%% Compilation of a shader can fail for a number of reasons as specified by the OpenGL Shading
-%% Language Specification. Whether or not the compilation was successful, information about
-%% the compilation can be obtained from the shader object's information log by calling {@link gl:getShaderInfoLog/2}
-%% .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompileShader.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCompileShader.xhtml">external</a> documentation.
-spec compileShader(Shader) -> 'ok' when Shader :: integer().
compileShader(Shader) ->
cast(5448, <<Shader:?GLuint>>).
@@ -10721,15 +4441,7 @@ compileShader(Shader) ->
%% between a vertex shader and a fragment shader). When no longer needed as part of a program
%% object, shader objects can be detached.
%%
-%% One or more executables are created in a program object by successfully attaching shader
-%% objects to it with {@link gl:attachShader/2} , successfully compiling the shader objects
-%% with {@link gl:compileShader/1} , and successfully linking the program object with {@link gl:linkProgram/1}
-%% . These executables are made part of current state when {@link gl:useProgram/1} is called.
-%% Program objects can be deleted by calling {@link gl:deleteProgram/1} . The memory associated
-%% with the program object will be deleted when it is no longer part of current rendering
-%% state for any context.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateProgram.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCreateProgram.xhtml">external</a> documentation.
-spec createProgram() -> integer().
createProgram() ->
call(5449, <<>>).
@@ -10748,11 +4460,7 @@ createProgram() ->
%% programmable geometry processor. A shader of type `?GL_FRAGMENT_SHADER' is a shader
%% that is intended to run on the programmable fragment processor.
%%
-%% When created, a shader object's `?GL_SHADER_TYPE' parameter is set to either `?GL_VERTEX_SHADER'
-%% , `?GL_TESS_CONTROL_SHADER', `?GL_TESS_EVALUATION_SHADER', `?GL_GEOMETRY_SHADER'
-%% or `?GL_FRAGMENT_SHADER', depending on the value of `ShaderType' .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateShader.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCreateShader.xhtml">external</a> documentation.
-spec createShader(Type) -> integer() when Type :: enum().
createShader(Type) ->
call(5450, <<Type:?GLenum>>).
@@ -10763,17 +4471,7 @@ createShader(Type) ->
%% object specified by `Program.' This command effectively undoes the effects of a call
%% to {@link gl:createProgram/0} .
%%
-%% If a program object is in use as part of current rendering state, it will be flagged for
-%% deletion, but it will not be deleted until it is no longer part of current state for any
-%% rendering context. If a program object to be deleted has shader objects attached to it,
-%% those shader objects will be automatically detached but not deleted unless they have already
-%% been flagged for deletion by a previous call to {@link gl:deleteShader/1} . A value of 0
-%% for `Program' will be silently ignored.
-%%
-%% To determine whether a program object has been flagged for deletion, call {@link gl:getProgramiv/2}
-%% with arguments `Program' and `?GL_DELETE_STATUS'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteProgram.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteProgram.xhtml">external</a> documentation.
-spec deleteProgram(Program) -> 'ok' when Program :: integer().
deleteProgram(Program) ->
cast(5451, <<Program:?GLuint>>).
@@ -10784,15 +4482,7 @@ deleteProgram(Program) ->
%% object specified by `Shader' . This command effectively undoes the effects of a call
%% to {@link gl:createShader/1} .
%%
-%% If a shader object to be deleted is attached to a program object, it will be flagged for
-%% deletion, but it will not be deleted until it is no longer attached to any program object,
-%% for any rendering context (i.e., it must be detached from wherever it was attached before
-%% it will be deleted). A value of 0 for `Shader' will be silently ignored.
-%%
-%% To determine whether an object has been flagged for deletion, call {@link gl:getShaderiv/2}
-%% with arguments `Shader' and `?GL_DELETE_STATUS'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteShader.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteShader.xhtml">external</a> documentation.
-spec deleteShader(Shader) -> 'ok' when Shader :: integer().
deleteShader(Shader) ->
cast(5452, <<Shader:?GLuint>>).
@@ -10803,11 +4493,7 @@ deleteShader(Shader) ->
%% object specified by `Program' . This command can be used to undo the effect of the
%% command {@link gl:attachShader/2} .
%%
-%% If `Shader' has already been flagged for deletion by a call to {@link gl:deleteShader/1}
-%% and it is not attached to any other program object, it will be deleted after it has been
-%% detached.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDetachShader.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDetachShader.xhtml">external</a> documentation.
-spec detachShader(Program, Shader) -> 'ok' when Program :: integer(),Shader :: integer().
detachShader(Program,Shader) ->
cast(5453, <<Program:?GLuint,Shader:?GLuint>>).
@@ -10822,7 +4508,7 @@ detachShader(Program,Shader) ->
%% such as {@link gl:drawArrays/3} , {@link gl:drawElements/4} , {@link gl:drawRangeElements/6} , see `glMultiDrawElements'
%% , or {@link gl:multiDrawArrays/3} .
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEnableVertexAttribArray.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glEnableVertexAttribArray.xhtml">external</a> documentation.
-spec disableVertexAttribArray(Index) -> 'ok' when Index :: integer().
disableVertexAttribArray(Index) ->
cast(5454, <<Index:?GLuint>>).
@@ -10841,52 +4527,7 @@ enableVertexAttribArray(Index) ->
%% of 0 for `Index' selects the first active attribute variable. Permissible values
%% for `Index' range from 0 to the number of active attribute variables minus 1.
%%
-%% A vertex shader may use either built-in attribute variables, user-defined attribute variables,
-%% or both. Built-in attribute variables have a prefix of "gl_" and reference conventional
-%% OpenGL vertex attribtes (e.g., `Gl_Vertex' , `Gl_Normal' , etc., see the OpenGL
-%% Shading Language specification for a complete list.) User-defined attribute variables
-%% have arbitrary names and obtain their values through numbered generic vertex attributes.
-%% An attribute variable (either built-in or user-defined) is considered active if it is
-%% determined during the link operation that it may be accessed during program execution.
-%% Therefore, `Program' should have previously been the target of a call to {@link gl:linkProgram/1}
-%% , but it is not necessary for it to have been linked successfully.
-%%
-%% The size of the character buffer required to store the longest attribute variable name
-%% in `Program' can be obtained by calling {@link gl:getProgramiv/2} with the value `?GL_ACTIVE_ATTRIBUTE_MAX_LENGTH'
-%% . This value should be used to allocate a buffer of sufficient size to store the returned
-%% attribute name. The size of this character buffer is passed in `BufSize' , and a pointer
-%% to this character buffer is passed in `Name' .
-%%
-%% ``gl:getActiveAttrib'' returns the name of the attribute variable indicated by `Index'
-%% , storing it in the character buffer specified by `Name' . The string returned will
-%% be null terminated. The actual number of characters written into this buffer is returned
-%% in `Length' , and this count does not include the null termination character. If the
-%% length of the returned string is not required, a value of `?NULL' can be passed in
-%% the `Length' argument.
-%%
-%% The `Type' argument specifies a pointer to a variable into which the attribute variable's
-%% data type will be written. The symbolic constants `?GL_FLOAT', `?GL_FLOAT_VEC2',
-%% `?GL_FLOAT_VEC3', `?GL_FLOAT_VEC4', `?GL_FLOAT_MAT2', `?GL_FLOAT_MAT3',
-%% `?GL_FLOAT_MAT4', `?GL_FLOAT_MAT2x3', `?GL_FLOAT_MAT2x4', `?GL_FLOAT_MAT3x2'
-%% , `?GL_FLOAT_MAT3x4', `?GL_FLOAT_MAT4x2', `?GL_FLOAT_MAT4x3', `?GL_INT'
-%% , `?GL_INT_VEC2', `?GL_INT_VEC3', `?GL_INT_VEC4', `?GL_UNSIGNED_INT_VEC'
-%% , `?GL_UNSIGNED_INT_VEC2', `?GL_UNSIGNED_INT_VEC3', `?GL_UNSIGNED_INT_VEC4',
-%% `?DOUBLE', `?DOUBLE_VEC2', `?DOUBLE_VEC3', `?DOUBLE_VEC4', `?DOUBLE_MAT2'
-%% , `?DOUBLE_MAT3', `?DOUBLE_MAT4', `?DOUBLE_MAT2x3', `?DOUBLE_MAT2x4',
-%% `?DOUBLE_MAT3x2', `?DOUBLE_MAT3x4', `?DOUBLE_MAT4x2', or `?DOUBLE_MAT4x3'
-%% may be returned. The `Size' argument will return the size of the attribute, in units
-%% of the type returned in `Type' .
-%%
-%% The list of active attribute variables may include both built-in attribute variables (which
-%% begin with the prefix "gl_") as well as user-defined attribute variable names.
-%%
-%% This function will return as much information as it can about the specified active attribute
-%% variable. If no information is available, `Length' will be 0, and `Name' will
-%% be an empty string. This situation could occur if this function is called after a link
-%% operation that failed. If an error occurs, the return values `Length' , `Size' , `Type'
-%% , and `Name' will be unmodified.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveAttrib.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveAttrib.xhtml">external</a> documentation.
-spec getActiveAttrib(Program, Index, BufSize) -> {Size :: integer(),Type :: enum(),Name :: string()} when Program :: integer(),Index :: integer(),BufSize :: integer().
getActiveAttrib(Program,Index,BufSize) ->
call(5456, <<Program:?GLuint,Index:?GLuint,BufSize:?GLsizei>>).
@@ -10899,141 +4540,7 @@ getActiveAttrib(Program,Index,BufSize) ->
%% A value of 0 for `Index' selects the first active uniform variable. Permissible values
%% for `Index' range from 0 to the number of active uniform variables minus 1.
%%
-%% Shaders may use either built-in uniform variables, user-defined uniform variables, or
-%% both. Built-in uniform variables have a prefix of "gl_" and reference existing OpenGL
-%% state or values derived from such state (e.g., `Gl_DepthRangeParameters' , see the
-%% OpenGL Shading Language specification for a complete list.) User-defined uniform variables
-%% have arbitrary names and obtain their values from the application through calls to {@link gl:uniform1f/2}
-%% . A uniform variable (either built-in or user-defined) is considered active if it is determined
-%% during the link operation that it may be accessed during program execution. Therefore, `Program'
-%% should have previously been the target of a call to {@link gl:linkProgram/1} , but it is
-%% not necessary for it to have been linked successfully.
-%%
-%% The size of the character buffer required to store the longest uniform variable name in `Program'
-%% can be obtained by calling {@link gl:getProgramiv/2} with the value `?GL_ACTIVE_UNIFORM_MAX_LENGTH'
-%% . This value should be used to allocate a buffer of sufficient size to store the returned
-%% uniform variable name. The size of this character buffer is passed in `BufSize' ,
-%% and a pointer to this character buffer is passed in `Name.'
-%%
-%% ``gl:getActiveUniform'' returns the name of the uniform variable indicated by `Index'
-%% , storing it in the character buffer specified by `Name' . The string returned will
-%% be null terminated. The actual number of characters written into this buffer is returned
-%% in `Length' , and this count does not include the null termination character. If the
-%% length of the returned string is not required, a value of `?NULL' can be passed in
-%% the `Length' argument.
-%%
-%% The `Type' argument will return a pointer to the uniform variable's data type. The
-%% symbolic constants returned for uniform types are shown in the table below. <table><tbody>
-%% <tr><td>` Returned Symbolic Contant '</td><td>` Shader Uniform Type '</td></tr></tbody>
-%% <tbody><tr><td>`?GL_FLOAT'</td><td>`?float'</td></tr><tr><td>`?GL_FLOAT_VEC2'
-%% </td><td>`?vec2'</td></tr><tr><td>`?GL_FLOAT_VEC3'</td><td>`?vec3'</td></tr>
-%% <tr><td>`?GL_FLOAT_VEC4'</td><td>`?vec4'</td></tr><tr><td>`?GL_DOUBLE'</td>
-%% <td>`?double'</td></tr><tr><td>`?GL_DOUBLE_VEC2'</td><td>`?dvec2'</td></tr>
-%% <tr><td>`?GL_DOUBLE_VEC3'</td><td>`?dvec3'</td></tr><tr><td>`?GL_DOUBLE_VEC4'
-%% </td><td>`?dvec4'</td></tr><tr><td>`?GL_INT'</td><td>`?int'</td></tr><tr><td>
-%% `?GL_INT_VEC2'</td><td>`?ivec2'</td></tr><tr><td>`?GL_INT_VEC3'</td><td>`?ivec3'
-%% </td></tr><tr><td>`?GL_INT_VEC4'</td><td>`?ivec4'</td></tr><tr><td>`?GL_UNSIGNED_INT'
-%% </td><td>`?unsigned int'</td></tr><tr><td>`?GL_UNSIGNED_INT_VEC2'</td><td>`?uvec2'
-%% </td></tr><tr><td>`?GL_UNSIGNED_INT_VEC3'</td><td>`?uvec3'</td></tr><tr><td>`?GL_UNSIGNED_INT_VEC4'
-%% </td><td>`?uvec4'</td></tr><tr><td>`?GL_BOOL'</td><td>`?bool'</td></tr><tr>
-%% <td>`?GL_BOOL_VEC2'</td><td>`?bvec2'</td></tr><tr><td>`?GL_BOOL_VEC3'</td><td>
-%% `?bvec3'</td></tr><tr><td>`?GL_BOOL_VEC4'</td><td>`?bvec4'</td></tr><tr><td>
-%% `?GL_FLOAT_MAT2'</td><td>`?mat2'</td></tr><tr><td>`?GL_FLOAT_MAT3'</td><td>
-%% `?mat3'</td></tr><tr><td>`?GL_FLOAT_MAT4'</td><td>`?mat4'</td></tr><tr><td>
-%% `?GL_FLOAT_MAT2x3'</td><td>`?mat2x3'</td></tr><tr><td>`?GL_FLOAT_MAT2x4'</td>
-%% <td>`?mat2x4'</td></tr><tr><td>`?GL_FLOAT_MAT3x2'</td><td>`?mat3x2'</td></tr>
-%% <tr><td>`?GL_FLOAT_MAT3x4'</td><td>`?mat3x4'</td></tr><tr><td>`?GL_FLOAT_MAT4x2'
-%% </td><td>`?mat4x2'</td></tr><tr><td>`?GL_FLOAT_MAT4x3'</td><td>`?mat4x3'</td>
-%% </tr><tr><td>`?GL_DOUBLE_MAT2'</td><td>`?dmat2'</td></tr><tr><td>`?GL_DOUBLE_MAT3'
-%% </td><td>`?dmat3'</td></tr><tr><td>`?GL_DOUBLE_MAT4'</td><td>`?dmat4'</td></tr>
-%% <tr><td>`?GL_DOUBLE_MAT2x3'</td><td>`?dmat2x3'</td></tr><tr><td>`?GL_DOUBLE_MAT2x4'
-%% </td><td>`?dmat2x4'</td></tr><tr><td>`?GL_DOUBLE_MAT3x2'</td><td>`?dmat3x2'</td>
-%% </tr><tr><td>`?GL_DOUBLE_MAT3x4'</td><td>`?dmat3x4'</td></tr><tr><td>`?GL_DOUBLE_MAT4x2'
-%% </td><td>`?dmat4x2'</td></tr><tr><td>`?GL_DOUBLE_MAT4x3'</td><td>`?dmat4x3'</td>
-%% </tr><tr><td>`?GL_SAMPLER_1D'</td><td>`?sampler1D'</td></tr><tr><td>`?GL_SAMPLER_2D'
-%% </td><td>`?sampler2D'</td></tr><tr><td>`?GL_SAMPLER_3D'</td><td>`?sampler3D'
-%% </td></tr><tr><td>`?GL_SAMPLER_CUBE'</td><td>`?samplerCube'</td></tr><tr><td>`?GL_SAMPLER_1D_SHADOW'
-%% </td><td>`?sampler1DShadow'</td></tr><tr><td>`?GL_SAMPLER_2D_SHADOW'</td><td>`?sampler2DShadow'
-%% </td></tr><tr><td>`?GL_SAMPLER_1D_ARRAY'</td><td>`?sampler1DArray'</td></tr><tr>
-%% <td>`?GL_SAMPLER_2D_ARRAY'</td><td>`?sampler2DArray'</td></tr><tr><td>`?GL_SAMPLER_1D_ARRAY_SHADOW'
-%% </td><td>`?sampler1DArrayShadow'</td></tr><tr><td>`?GL_SAMPLER_2D_ARRAY_SHADOW'</td>
-%% <td>`?sampler2DArrayShadow'</td></tr><tr><td>`?GL_SAMPLER_2D_MULTISAMPLE'</td><td>
-%% `?sampler2DMS'</td></tr><tr><td>`?GL_SAMPLER_2D_MULTISAMPLE_ARRAY'</td><td>`?sampler2DMSArray'
-%% </td></tr><tr><td>`?GL_SAMPLER_CUBE_SHADOW'</td><td>`?samplerCubeShadow'</td></tr>
-%% <tr><td>`?GL_SAMPLER_BUFFER'</td><td>`?samplerBuffer'</td></tr><tr><td>`?GL_SAMPLER_2D_RECT'
-%% </td><td>`?sampler2DRect'</td></tr><tr><td>`?GL_SAMPLER_2D_RECT_SHADOW'</td><td>
-%% `?sampler2DRectShadow'</td></tr><tr><td>`?GL_INT_SAMPLER_1D'</td><td>`?isampler1D'
-%% </td></tr><tr><td>`?GL_INT_SAMPLER_2D'</td><td>`?isampler2D'</td></tr><tr><td>`?GL_INT_SAMPLER_3D'
-%% </td><td>`?isampler3D'</td></tr><tr><td>`?GL_INT_SAMPLER_CUBE'</td><td>`?isamplerCube'
-%% </td></tr><tr><td>`?GL_INT_SAMPLER_1D_ARRAY'</td><td>`?isampler1DArray'</td></tr>
-%% <tr><td>`?GL_INT_SAMPLER_2D_ARRAY'</td><td>`?isampler2DArray'</td></tr><tr><td>`?GL_INT_SAMPLER_2D_MULTISAMPLE'
-%% </td><td>`?isampler2DMS'</td></tr><tr><td>`?GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY'</td>
-%% <td>`?isampler2DMSArray'</td></tr><tr><td>`?GL_INT_SAMPLER_BUFFER'</td><td>`?isamplerBuffer'
-%% </td></tr><tr><td>`?GL_INT_SAMPLER_2D_RECT'</td><td>`?isampler2DRect'</td></tr><tr>
-%% <td>`?GL_UNSIGNED_INT_SAMPLER_1D'</td><td>`?usampler1D'</td></tr><tr><td>`?GL_UNSIGNED_INT_SAMPLER_2D'
-%% </td><td>`?usampler2D'</td></tr><tr><td>`?GL_UNSIGNED_INT_SAMPLER_3D'</td><td>`?usampler3D'
-%% </td></tr><tr><td>`?GL_UNSIGNED_INT_SAMPLER_CUBE'</td><td>`?usamplerCube'</td></tr>
-%% <tr><td>`?GL_UNSIGNED_INT_SAMPLER_1D_ARRAY'</td><td>`?usampler2DArray'</td></tr>
-%% <tr><td>`?GL_UNSIGNED_INT_SAMPLER_2D_ARRAY'</td><td>`?usampler2DArray'</td></tr>
-%% <tr><td>`?GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE'</td><td>`?usampler2DMS'</td></tr>
-%% <tr><td>`?GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY'</td><td>`?usampler2DMSArray'
-%% </td></tr><tr><td>`?GL_UNSIGNED_INT_SAMPLER_BUFFER'</td><td>`?usamplerBuffer'</td>
-%% </tr><tr><td>`?GL_UNSIGNED_INT_SAMPLER_2D_RECT'</td><td>`?usampler2DRect'</td></tr>
-%% <tr><td>`?GL_IMAGE_1D'</td><td>`?image1D'</td></tr><tr><td>`?GL_IMAGE_2D'</td>
-%% <td>`?image2D'</td></tr><tr><td>`?GL_IMAGE_3D'</td><td>`?image3D'</td></tr>
-%% <tr><td>`?GL_IMAGE_2D_RECT'</td><td>`?image2DRect'</td></tr><tr><td>`?GL_IMAGE_CUBE'
-%% </td><td>`?imageCube'</td></tr><tr><td>`?GL_IMAGE_BUFFER'</td><td>`?imageBuffer'
-%% </td></tr><tr><td>`?GL_IMAGE_1D_ARRAY'</td><td>`?image1DArray'</td></tr><tr><td>
-%% `?GL_IMAGE_2D_ARRAY'</td><td>`?image2DArray'</td></tr><tr><td>`?GL_IMAGE_2D_MULTISAMPLE'
-%% </td><td>`?image2DMS'</td></tr><tr><td>`?GL_IMAGE_2D_MULTISAMPLE_ARRAY'</td><td>
-%% `?image2DMSArray'</td></tr><tr><td>`?GL_INT_IMAGE_1D'</td><td>`?iimage1D'</td>
-%% </tr><tr><td>`?GL_INT_IMAGE_2D'</td><td>`?iimage2D'</td></tr><tr><td>`?GL_INT_IMAGE_3D'
-%% </td><td>`?iimage3D'</td></tr><tr><td>`?GL_INT_IMAGE_2D_RECT'</td><td>`?iimage2DRect'
-%% </td></tr><tr><td>`?GL_INT_IMAGE_CUBE'</td><td>`?iimageCube'</td></tr><tr><td>`?GL_INT_IMAGE_BUFFER'
-%% </td><td>`?iimageBuffer'</td></tr><tr><td>`?GL_INT_IMAGE_1D_ARRAY'</td><td>`?iimage1DArray'
-%% </td></tr><tr><td>`?GL_INT_IMAGE_2D_ARRAY'</td><td>`?iimage2DArray'</td></tr><tr>
-%% <td>`?GL_INT_IMAGE_2D_MULTISAMPLE'</td><td>`?iimage2DMS'</td></tr><tr><td>`?GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY'
-%% </td><td>`?iimage2DMSArray'</td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_1D'</td><td>
-%% `?uimage1D'</td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_2D'</td><td>`?uimage2D'
-%% </td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_3D'</td><td>`?uimage3D'</td></tr><tr><td>
-%% `?GL_UNSIGNED_INT_IMAGE_2D_RECT'</td><td>`?uimage2DRect'</td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_CUBE'
-%% </td><td>`?uimageCube'</td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_BUFFER'</td><td>
-%% `?uimageBuffer'</td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_1D_ARRAY'</td><td>`?uimage1DArray'
-%% </td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_2D_ARRAY'</td><td>`?uimage2DArray'</td>
-%% </tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE'</td><td>`?uimage2DMS'</td></tr>
-%% <tr><td>`?GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY'</td><td>`?uimage2DMSArray'</td>
-%% </tr><tr><td>`?GL_UNSIGNED_INT_ATOMIC_COUNTER'</td><td>`?atomic_uint'</td></tr></tbody>
-%% </table>
-%%
-%% If one or more elements of an array are active, the name of the array is returned in `Name'
-%% , the type is returned in `Type' , and the `Size' parameter returns the highest
-%% array element index used, plus one, as determined by the compiler and/or linker. Only
-%% one active uniform variable will be reported for a uniform array.
-%%
-%% Uniform variables that are declared as structures or arrays of structures will not be
-%% returned directly by this function. Instead, each of these uniform variables will be reduced
-%% to its fundamental components containing the "." and "[]" operators such that each of
-%% the names is valid as an argument to {@link gl:getUniformLocation/2} . Each of these reduced
-%% uniform variables is counted as one active uniform variable and is assigned an index.
-%% A valid name cannot be a structure, an array of structures, or a subcomponent of a vector
-%% or matrix.
-%%
-%% The size of the uniform variable will be returned in `Size' . Uniform variables other
-%% than arrays will have a size of 1. Structures and arrays of structures will be reduced
-%% as described earlier, such that each of the names returned will be a data type in the
-%% earlier list. If this reduction results in an array, the size returned will be as described
-%% for uniform arrays; otherwise, the size returned will be 1.
-%%
-%% The list of active uniform variables may include both built-in uniform variables (which
-%% begin with the prefix "gl_") as well as user-defined uniform variable names.
-%%
-%% This function will return as much information as it can about the specified active uniform
-%% variable. If no information is available, `Length' will be 0, and `Name' will
-%% be an empty string. This situation could occur if this function is called after a link
-%% operation that failed. If an error occurs, the return values `Length' , `Size' , `Type'
-%% , and `Name' will be unmodified.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniform.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveUniform.xhtml">external</a> documentation.
-spec getActiveUniform(Program, Index, BufSize) -> {Size :: integer(),Type :: enum(),Name :: string()} when Program :: integer(),Index :: integer(),BufSize :: integer().
getActiveUniform(Program,Index,BufSize) ->
call(5457, <<Program:?GLuint,Index:?GLuint,BufSize:?GLsizei>>).
@@ -11047,13 +4554,7 @@ getActiveUniform(Program,Index,BufSize) ->
%% number of shader names that may be returned in `Shaders' is specified by `MaxCount'
%% .
%%
-%% If the number of names actually returned is not required (for instance, if it has just
-%% been obtained by calling {@link gl:getProgramiv/2} ), a value of `?NULL' may be passed
-%% for count. If no shader objects are attached to `Program' , a value of 0 will be returned
-%% in `Count' . The actual number of attached shaders can be obtained by calling {@link gl:getProgramiv/2}
-%% with the value `?GL_ATTACHED_SHADERS'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetAttachedShaders.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetAttachedShaders.xhtml">external</a> documentation.
-spec getAttachedShaders(Program, MaxCount) -> [integer()] when Program :: integer(),MaxCount :: integer().
getAttachedShaders(Program,MaxCount) ->
call(5458, <<Program:?GLuint,MaxCount:?GLsizei>>).
@@ -11067,17 +4568,7 @@ getAttachedShaders(Program,MaxCount) ->
%% attribute variable is not an active attribute in the specified program object or if `Name'
%% starts with the reserved prefix "gl_", a value of -1 is returned.
%%
-%% The association between an attribute variable name and a generic attribute index can be
-%% specified at any time by calling {@link gl:bindAttribLocation/3} . Attribute bindings do
-%% not go into effect until {@link gl:linkProgram/1} is called. After a program object has
-%% been linked successfully, the index values for attribute variables remain fixed until
-%% the next link command occurs. The attribute values can only be queried after a link if
-%% the link was successful. ``gl:getAttribLocation'' returns the binding that actually
-%% went into effect the last time {@link gl:linkProgram/1} was called for the specified program
-%% object. Attribute bindings that have been specified since the last link operation are
-%% not returned by ``gl:getAttribLocation''.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetAttribLocation.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetAttribLocation.xhtml">external</a> documentation.
-spec getAttribLocation(Program, Name) -> integer() when Program :: integer(),Name :: string().
getAttribLocation(Program,Name) ->
NameLen = length(Name),
@@ -11088,68 +4579,7 @@ getAttribLocation(Program,Name) ->
%% ``gl:getProgram'' returns in `Params' the value of a parameter for a specific program
%% object. The following parameters are defined:
%%
-%% `?GL_DELETE_STATUS': `Params' returns `?GL_TRUE' if `Program' is currently
-%% flagged for deletion, and `?GL_FALSE' otherwise.
-%%
-%% `?GL_LINK_STATUS': `Params' returns `?GL_TRUE' if the last link operation
-%% on `Program' was successful, and `?GL_FALSE' otherwise.
-%%
-%% `?GL_VALIDATE_STATUS': `Params' returns `?GL_TRUE' or if the last validation
-%% operation on `Program' was successful, and `?GL_FALSE' otherwise.
-%%
-%% `?GL_INFO_LOG_LENGTH': `Params' returns the number of characters in the information
-%% log for `Program' including the null termination character (i.e., the size of the
-%% character buffer required to store the information log). If `Program' has no information
-%% log, a value of 0 is returned.
-%%
-%% `?GL_ATTACHED_SHADERS': `Params' returns the number of shader objects attached
-%% to `Program' .
-%%
-%% `?GL_ACTIVE_ATOMIC_COUNTER_BUFFERS': `Params' returns the number of active attribute
-%% atomic counter buffers used by `Program' .
-%%
-%% `?GL_ACTIVE_ATTRIBUTES': `Params' returns the number of active attribute variables
-%% for `Program' .
-%%
-%% `?GL_ACTIVE_ATTRIBUTE_MAX_LENGTH': `Params' returns the length of the longest
-%% active attribute name for `Program' , including the null termination character (i.e.,
-%% the size of the character buffer required to store the longest attribute name). If no
-%% active attributes exist, 0 is returned.
-%%
-%% `?GL_ACTIVE_UNIFORMS': `Params' returns the number of active uniform variables
-%% for `Program' .
-%%
-%% `?GL_ACTIVE_UNIFORM_MAX_LENGTH': `Params' returns the length of the longest
-%% active uniform variable name for `Program' , including the null termination character
-%% (i.e., the size of the character buffer required to store the longest uniform variable
-%% name). If no active uniform variables exist, 0 is returned.
-%%
-%% `?GL_PROGRAM_BINARY_LENGTH': `Params' returns the length of the program binary,
-%% in bytes that will be returned by a call to {@link gl:getProgramBinary/2} . When a progam's
-%% `?GL_LINK_STATUS' is `?GL_FALSE', its program binary length is zero.
-%%
-%% `?GL_TRANSFORM_FEEDBACK_BUFFER_MODE': `Params' returns a symbolic constant indicating
-%% the buffer mode used when transform feedback is active. This may be `?GL_SEPARATE_ATTRIBS'
-%% or `?GL_INTERLEAVED_ATTRIBS'.
-%%
-%% `?GL_TRANSFORM_FEEDBACK_VARYINGS': `Params' returns the number of varying variables
-%% to capture in transform feedback mode for the program.
-%%
-%% `?GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH': `Params' returns the length of
-%% the longest variable name to be used for transform feedback, including the null-terminator.
-%%
-%%
-%% `?GL_GEOMETRY_VERTICES_OUT': `Params' returns the maximum number of vertices
-%% that the geometry shader in `Program' will output.
-%%
-%% `?GL_GEOMETRY_INPUT_TYPE': `Params' returns a symbolic constant indicating the
-%% primitive type accepted as input to the geometry shader contained in `Program' .
-%%
-%% `?GL_GEOMETRY_OUTPUT_TYPE': `Params' returns a symbolic constant indicating
-%% the primitive type that will be output by the geometry shader contained in `Program' .
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgram.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetProgram.xhtml">external</a> documentation.
-spec getProgramiv(Program, Pname) -> integer() when Program :: integer(),Pname :: enum().
getProgramiv(Program,Pname) ->
call(5460, <<Program:?GLuint,Pname:?GLenum>>).
@@ -11160,21 +4590,7 @@ getProgramiv(Program,Pname) ->
%% The information log for a program object is modified when the program object is linked
%% or validated. The string that is returned will be null terminated.
%%
-%% ``gl:getProgramInfoLog'' returns in `InfoLog' as much of the information log as
-%% it can, up to a maximum of `MaxLength' characters. The number of characters actually
-%% returned, excluding the null termination character, is specified by `Length' . If
-%% the length of the returned string is not required, a value of `?NULL' can be passed
-%% in the `Length' argument. The size of the buffer required to store the returned
-%% information log can be obtained by calling {@link gl:getProgramiv/2} with the value `?GL_INFO_LOG_LENGTH'
-%% .
-%%
-%% The information log for a program object is either an empty string, or a string containing
-%% information about the last link operation, or a string containing information about the
-%% last validation operation. It may contain diagnostic messages, warning messages, and
-%% other information. When a program object is created, its information log will be a string
-%% of length 0.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramInfoLog.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetProgramInfoLog.xhtml">external</a> documentation.
-spec getProgramInfoLog(Program, BufSize) -> string() when Program :: integer(),BufSize :: integer().
getProgramInfoLog(Program,BufSize) ->
call(5461, <<Program:?GLuint,BufSize:?GLsizei>>).
@@ -11184,28 +4600,7 @@ getProgramInfoLog(Program,BufSize) ->
%% ``gl:getShader'' returns in `Params' the value of a parameter for a specific
%% shader object. The following parameters are defined:
%%
-%% `?GL_SHADER_TYPE': `Params' returns `?GL_VERTEX_SHADER' if `Shader'
-%% is a vertex shader object, `?GL_GEOMETRY_SHADER' if `Shader' is a geometry
-%% shader object, and `?GL_FRAGMENT_SHADER' if `Shader' is a fragment shader
-%% object.
-%%
-%% `?GL_DELETE_STATUS': `Params' returns `?GL_TRUE' if `Shader' is
-%% currently flagged for deletion, and `?GL_FALSE' otherwise.
-%%
-%% `?GL_COMPILE_STATUS': `Params' returns `?GL_TRUE' if the last compile
-%% operation on `Shader' was successful, and `?GL_FALSE' otherwise.
-%%
-%% `?GL_INFO_LOG_LENGTH': `Params' returns the number of characters in the information
-%% log for `Shader' including the null termination character (i.e., the size of
-%% the character buffer required to store the information log). If `Shader' has
-%% no information log, a value of 0 is returned.
-%%
-%% `?GL_SHADER_SOURCE_LENGTH': `Params' returns the length of the concatenation
-%% of the source strings that make up the shader source for the `Shader' , including
-%% the null termination character. (i.e., the size of the character buffer required to
-%% store the shader source). If no source code exists, 0 is returned.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShader.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetShader.xhtml">external</a> documentation.
-spec getShaderiv(Shader, Pname) -> integer() when Shader :: integer(),Pname :: enum().
getShaderiv(Shader,Pname) ->
call(5462, <<Shader:?GLuint,Pname:?GLenum>>).
@@ -11216,19 +4611,7 @@ getShaderiv(Shader,Pname) ->
%% The information log for a shader object is modified when the shader is compiled. The
%% string that is returned will be null terminated.
%%
-%% ``gl:getShaderInfoLog'' returns in `InfoLog' as much of the information log as
-%% it can, up to a maximum of `MaxLength' characters. The number of characters actually
-%% returned, excluding the null termination character, is specified by `Length' . If
-%% the length of the returned string is not required, a value of `?NULL' can be passed
-%% in the `Length' argument. The size of the buffer required to store the returned
-%% information log can be obtained by calling {@link gl:getShaderiv/2} with the value `?GL_INFO_LOG_LENGTH'
-%% .
-%%
-%% The information log for a shader object is a string that may contain diagnostic messages,
-%% warning messages, and other information about the last compile operation. When a shader
-%% object is created, its information log will be a string of length 0.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderInfoLog.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetShaderInfoLog.xhtml">external</a> documentation.
-spec getShaderInfoLog(Shader, BufSize) -> string() when Shader :: integer(),BufSize :: integer().
getShaderInfoLog(Shader,BufSize) ->
call(5463, <<Shader:?GLuint,BufSize:?GLsizei>>).
@@ -11240,15 +4623,7 @@ getShaderInfoLog(Shader,BufSize) ->
%% are the result of a previous call to {@link gl:shaderSource/2} . The string returned by
%% the function will be null terminated.
%%
-%% ``gl:getShaderSource'' returns in `Source' as much of the source code string as
-%% it can, up to a maximum of `BufSize' characters. The number of characters actually
-%% returned, excluding the null termination character, is specified by `Length' . If
-%% the length of the returned string is not required, a value of `?NULL' can be passed
-%% in the `Length' argument. The size of the buffer required to store the returned source
-%% code string can be obtained by calling {@link gl:getShaderiv/2} with the value `?GL_SHADER_SOURCE_LENGTH'
-%% .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderSource.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetShaderSource.xhtml">external</a> documentation.
-spec getShaderSource(Shader, BufSize) -> string() when Shader :: integer(),BufSize :: integer().
getShaderSource(Shader,BufSize) ->
call(5464, <<Shader:?GLuint,BufSize:?GLsizei>>).
@@ -11263,25 +4638,7 @@ getShaderSource(Shader,BufSize) ->
%% in `Program' , if `Name' starts with the reserved prefix "gl_", or if `Name'
%% is associated with an atomic counter or a named uniform block.
%%
-%% Uniform variables that are structures or arrays of structures may be queried by calling ``gl:getUniformLocation''
-%% for each field within the structure. The array element operator "[]" and the structure
-%% field operator "." may be used in `Name' in order to select elements within an array
-%% or fields within a structure. The result of using these operators is not allowed to be
-%% another structure, an array of structures, or a subcomponent of a vector or a matrix.
-%% Except if the last part of `Name' indicates a uniform variable array, the location
-%% of the first element of an array can be retrieved by using the name of the array, or by
-%% using the name appended by "[0]".
-%%
-%% The actual locations assigned to uniform variables are not known until the program object
-%% is linked successfully. After linking has occurred, the command ``gl:getUniformLocation''
-%% can be used to obtain the location of a uniform variable. This location value can then
-%% be passed to {@link gl:uniform1f/2} to set the value of the uniform variable or to {@link gl:getUniformfv/2}
-%% in order to query the current value of the uniform variable. After a program object has
-%% been linked successfully, the index values for uniform variables remain fixed until the
-%% next link command occurs. Uniform variable locations and values can only be queried after
-%% a link if the link was successful.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformLocation.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetUniformLocation.xhtml">external</a> documentation.
-spec getUniformLocation(Program, Name) -> integer() when Program :: integer(),Name :: string().
getUniformLocation(Program,Name) ->
NameLen = length(Name),
@@ -11300,15 +4657,7 @@ getUniformLocation(Program,Name) ->
%% The values for uniform variables declared as a matrix will be returned in column major
%% order.
%%
-%% The locations assigned to uniform variables are not known until the program object is
-%% linked. After linking has occurred, the command {@link gl:getUniformLocation/2} can be
-%% used to obtain the location of a uniform variable. This location value can then be passed
-%% to ``gl:getUniform'' in order to query the current value of the uniform variable. After
-%% a program object has been linked successfully, the index values for uniform variables
-%% remain fixed until the next link command occurs. The uniform variable values can only
-%% be queried after a link if the link was successful.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniform.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetUniform.xhtml">external</a> documentation.
-spec getUniformfv(Program, Location) -> matrix() when Program :: integer(),Location :: integer().
getUniformfv(Program,Location) ->
call(5466, <<Program:?GLuint,Location:?GLint>>).
@@ -11325,63 +4674,7 @@ getUniformiv(Program,Location) ->
%% parameter. The generic vertex attribute to be queried is specified by `Index' , and
%% the parameter to be queried is specified by `Pname' .
%%
-%% The accepted parameter names are as follows:
-%%
-%% `?GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING': `Params' returns a single value, the
-%% name of the buffer object currently bound to the binding point corresponding to generic
-%% vertex attribute array `Index' . If no buffer object is bound, 0 is returned. The
-%% initial value is 0.
-%%
-%% `?GL_VERTEX_ATTRIB_ARRAY_ENABLED': `Params' returns a single value that is non-zero
-%% (true) if the vertex attribute array for `Index' is enabled and 0 (false) if it is
-%% disabled. The initial value is `?GL_FALSE'.
-%%
-%% `?GL_VERTEX_ATTRIB_ARRAY_SIZE': `Params' returns a single value, the size of
-%% the vertex attribute array for `Index' . The size is the number of values for each
-%% element of the vertex attribute array, and it will be 1, 2, 3, or 4. The initial value
-%% is 4.
-%%
-%% `?GL_VERTEX_ATTRIB_ARRAY_STRIDE': `Params' returns a single value, the array
-%% stride for (number of bytes between successive elements in) the vertex attribute array
-%% for `Index' . A value of 0 indicates that the array elements are stored sequentially
-%% in memory. The initial value is 0.
-%%
-%% `?GL_VERTEX_ATTRIB_ARRAY_TYPE': `Params' returns a single value, a symbolic
-%% constant indicating the array type for the vertex attribute array for `Index' . Possible
-%% values are `?GL_BYTE', `?GL_UNSIGNED_BYTE', `?GL_SHORT', `?GL_UNSIGNED_SHORT'
-%% , `?GL_INT', `?GL_UNSIGNED_INT', `?GL_FLOAT', and `?GL_DOUBLE'. The
-%% initial value is `?GL_FLOAT'.
-%%
-%% `?GL_VERTEX_ATTRIB_ARRAY_NORMALIZED': `Params' returns a single value that is
-%% non-zero (true) if fixed-point data types for the vertex attribute array indicated by `Index'
-%% are normalized when they are converted to floating point, and 0 (false) otherwise. The
-%% initial value is `?GL_FALSE'.
-%%
-%% `?GL_VERTEX_ATTRIB_ARRAY_INTEGER': `Params' returns a single value that is non-zero
-%% (true) if fixed-point data types for the vertex attribute array indicated by `Index'
-%% have integer data types, and 0 (false) otherwise. The initial value is 0 (`?GL_FALSE').
-%%
-%%
-%% `?GL_VERTEX_ATTRIB_ARRAY_DIVISOR': `Params' returns a single value that is the
-%% frequency divisor used for instanced rendering. See {@link gl:vertexAttribDivisor/2} . The
-%% initial value is 0.
-%%
-%% `?GL_CURRENT_VERTEX_ATTRIB': `Params' returns four values that represent the
-%% current value for the generic vertex attribute specified by index. Generic vertex attribute
-%% 0 is unique in that it has no current state, so an error will be generated if `Index'
-%% is 0. The initial value for all other generic vertex attributes is (0,0,0,1).
-%%
-%% ``gl:getVertexAttribdv'' and ``gl:getVertexAttribfv'' return the current attribute
-%% values as four single-precision floating-point values; ``gl:getVertexAttribiv'' reads
-%% them as floating-point values and converts them to four integer values; ``gl:getVertexAttribIiv''
-%% and ``gl:getVertexAttribIuiv'' read and return them as signed or unsigned integer values,
-%% respectively; ``gl:getVertexAttribLdv'' reads and returns them as four double-precision
-%% floating-point values.
-%%
-%% All of the parameters except `?GL_CURRENT_VERTEX_ATTRIB' represent state stored in
-%% the currently bound vertex array object.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttrib.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetVertexAttrib.xhtml">external</a> documentation.
-spec getVertexAttribdv(Index, Pname) -> {float(),float(),float(),float()} when Index :: integer(),Pname :: enum().
getVertexAttribdv(Index,Pname) ->
call(5468, <<Index:?GLuint,Pname:?GLenum>>).
@@ -11405,7 +4698,7 @@ getVertexAttribiv(Index,Pname) ->
%% . If `Program' is zero or a non-zero value that is not the name of a program object,
%% or if an error occurs, ``gl:isProgram'' returns `?GL_FALSE'.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsProgram.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsProgram.xhtml">external</a> documentation.
-spec isProgram(Program) -> 0|1 when Program :: integer().
isProgram(Program) ->
call(5471, <<Program:?GLuint>>).
@@ -11417,7 +4710,7 @@ isProgram(Program) ->
%% . If `Shader' is zero or a non-zero value that is not the name of a shader object,
%% or if an error occurs, ``gl:isShader '' returns `?GL_FALSE'.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsShader.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsShader.xhtml">external</a> documentation.
-spec isShader(Shader) -> 0|1 when Shader :: integer().
isShader(Shader) ->
call(5472, <<Shader:?GLuint>>).
@@ -11433,111 +4726,7 @@ isShader(Shader) ->
%% they will be used to create an executable that will run on the programmable fragment processor.
%%
%%
-%% The status of the link operation will be stored as part of the program object's state.
-%% This value will be set to `?GL_TRUE' if the program object was linked without errors
-%% and is ready for use, and `?GL_FALSE' otherwise. It can be queried by calling {@link gl:getProgramiv/2}
-%% with arguments `Program' and `?GL_LINK_STATUS'.
-%%
-%% As a result of a successful link operation, all active user-defined uniform variables
-%% belonging to `Program' will be initialized to 0, and each of the program object's
-%% active uniform variables will be assigned a location that can be queried by calling {@link gl:getUniformLocation/2}
-%% . Also, any active user-defined attribute variables that have not been bound to a generic
-%% vertex attribute index will be bound to one at this time.
-%%
-%% Linking of a program object can fail for a number of reasons as specified in the `OpenGL Shading Language Specification'
-%% . The following lists some of the conditions that will cause a link error.
-%%
-%% The number of active attribute variables supported by the implementation has been exceeded.
-%%
-%%
-%% The storage limit for uniform variables has been exceeded.
-%%
-%% The number of active uniform variables supported by the implementation has been exceeded.
-%%
-%% The `main' function is missing for the vertex, geometry or fragment shader.
-%%
-%% A varying variable actually used in the fragment shader is not declared in the same way
-%% (or is not declared at all) in the vertex shader, or geometry shader shader if present.
-%%
-%% A reference to a function or variable name is unresolved.
-%%
-%% A shared global is declared with two different types or two different initial values.
-%%
-%% One or more of the attached shader objects has not been successfully compiled.
-%%
-%% Binding a generic attribute matrix caused some rows of the matrix to fall outside the
-%% allowed maximum of `?GL_MAX_VERTEX_ATTRIBS'.
-%%
-%% Not enough contiguous vertex attribute slots could be found to bind attribute matrices.
-%%
-%% The program object contains objects to form a fragment shader but does not contain objects
-%% to form a vertex shader.
-%%
-%% The program object contains objects to form a geometry shader but does not contain objects
-%% to form a vertex shader.
-%%
-%% The program object contains objects to form a geometry shader and the input primitive
-%% type, output primitive type, or maximum output vertex count is not specified in any compiled
-%% geometry shader object.
-%%
-%% The program object contains objects to form a geometry shader and the input primitive
-%% type, output primitive type, or maximum output vertex count is specified differently in
-%% multiple geometry shader objects.
-%%
-%% The number of active outputs in the fragment shader is greater than the value of `?GL_MAX_DRAW_BUFFERS'
-%% .
-%%
-%% The program has an active output assigned to a location greater than or equal to the value
-%% of `?GL_MAX_DUAL_SOURCE_DRAW_BUFFERS' and has an active output assigned an index
-%% greater than or equal to one.
-%%
-%% More than one varying out variable is bound to the same number and index.
-%%
-%% The explicit binding assigments do not leave enough space for the linker to automatically
-%% assign a location for a varying out array, which requires multiple contiguous locations.
-%%
-%% The `Count' specified by {@link gl:transformFeedbackVaryings/3} is non-zero, but the
-%% program object has no vertex or geometry shader.
-%%
-%% Any variable name specified to {@link gl:transformFeedbackVaryings/3} in the `Varyings'
-%% array is not declared as an output in the vertex shader (or the geometry shader, if active).
-%%
-%%
-%% Any two entries in the `Varyings' array given {@link gl:transformFeedbackVaryings/3}
-%% specify the same varying variable.
-%%
-%% The total number of components to capture in any transform feedback varying variable is
-%% greater than the constant `?GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS' and the
-%% buffer mode is `?SEPARATE_ATTRIBS'.
-%%
-%% When a program object has been successfully linked, the program object can be made part
-%% of current state by calling {@link gl:useProgram/1} . Whether or not the link operation
-%% was successful, the program object's information log will be overwritten. The information
-%% log can be retrieved by calling {@link gl:getProgramInfoLog/2} .
-%%
-%% ``gl:linkProgram'' will also install the generated executables as part of the current
-%% rendering state if the link operation was successful and the specified program object
-%% is already currently in use as a result of a previous call to {@link gl:useProgram/1} .
-%% If the program object currently in use is relinked unsuccessfully, its link status will
-%% be set to `?GL_FALSE' , but the executables and associated state will remain part
-%% of the current state until a subsequent call to ``gl:useProgram'' removes it from use.
-%% After it is removed from use, it cannot be made part of current state until it has been
-%% successfully relinked.
-%%
-%% If `Program' contains shader objects of type `?GL_VERTEX_SHADER', and optionally
-%% of type `?GL_GEOMETRY_SHADER', but does not contain shader objects of type `?GL_FRAGMENT_SHADER'
-%% , the vertex shader executable will be installed on the programmable vertex processor,
-%% the geometry shader executable, if present, will be installed on the programmable geometry
-%% processor, but no executable will be installed on the fragment processor. The results
-%% of rasterizing primitives with such a program will be undefined.
-%%
-%% The program object's information log is updated and the program is generated at the time
-%% of the link operation. After the link operation, applications are free to modify attached
-%% shader objects, compile attached shader objects, detach shader objects, delete shader
-%% objects, and attach additional shader objects. None of these operations affects the information
-%% log or the program that is part of the program object.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLinkProgram.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glLinkProgram.xhtml">external</a> documentation.
-spec linkProgram(Program) -> 'ok' when Program :: integer().
linkProgram(Program) ->
cast(5473, <<Program:?GLuint>>).
@@ -11555,7 +4744,7 @@ linkProgram(Program) ->
%% than 0 to indicate that the string is null terminated. The source code strings are not
%% scanned or parsed at this time; they are simply copied into the specified shader object.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShaderSource.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glShaderSource.xhtml">external</a> documentation.
-spec shaderSource(Shader, String) -> 'ok' when Shader :: integer(),String :: iolist().
shaderSource(Shader,String) ->
StringTemp = list_to_binary([[Str|[0]] || Str <- String ]),
@@ -11570,35 +4759,7 @@ shaderSource(Shader,String) ->
%% compiling the shader objects with {@link gl:compileShader/1} , and successfully linking
%% the program object with {@link gl:linkProgram/1} .
%%
-%% A program object will contain an executable that will run on the vertex processor if
-%% it contains one or more shader objects of type `?GL_VERTEX_SHADER' that have been
-%% successfully compiled and linked. A program object will contain an executable that will
-%% run on the geometry processor if it contains one or more shader objects of type `?GL_GEOMETRY_SHADER'
-%% that have been successfully compiled and linked. Similarly, a program object will contain
-%% an executable that will run on the fragment processor if it contains one or more shader
-%% objects of type `?GL_FRAGMENT_SHADER' that have been successfully compiled and
-%% linked.
-%%
-%% While a program object is in use, applications are free to modify attached shader objects,
-%% compile attached shader objects, attach additional shader objects, and detach or delete
-%% shader objects. None of these operations will affect the executables that are part of
-%% the current state. However, relinking the program object that is currently in use will
-%% install the program object as part of the current rendering state if the link operation
-%% was successful (see {@link gl:linkProgram/1} ). If the program object currently in use
-%% is relinked unsuccessfully, its link status will be set to `?GL_FALSE', but the
-%% executables and associated state will remain part of the current state until a subsequent
-%% call to ``gl:useProgram'' removes it from use. After it is removed from use, it cannot
-%% be made part of current state until it has been successfully relinked.
-%%
-%% If `Program' is zero, then the current rendering state refers to an `invalid'
-%% program object and the results of shader execution are undefined. However, this is not
-%% an error.
-%%
-%% If `Program' does not contain shader objects of type `?GL_FRAGMENT_SHADER',
-%% an executable will be installed on the vertex, and possibly geometry processors, but
-%% the results of fragment shader execution will be undefined.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUseProgram.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUseProgram.xhtml">external</a> documentation.
-spec useProgram(Program) -> 'ok' when Program :: integer().
useProgram(Program) ->
cast(5475, <<Program:?GLuint>>).
@@ -11611,62 +4772,7 @@ useProgram(Program) ->
%% on the program object that was made part of current state by calling {@link gl:useProgram/1}
%% .
%%
-%% The commands ``gl:uniform{1|2|3|4}{f|i|ui}'' are used to change the value of the uniform
-%% variable specified by `Location' using the values passed as arguments. The number
-%% specified in the command should match the number of components in the data type of the
-%% specified uniform variable (e.g., `1' for float, int, unsigned int, bool; `2'
-%% for vec2, ivec2, uvec2, bvec2, etc.). The suffix `f' indicates that floating-point
-%% values are being passed; the suffix `i' indicates that integer values are being passed;
-%% the suffix `ui' indicates that unsigned integer values are being passed, and this
-%% type should also match the data type of the specified uniform variable. The `i' variants
-%% of this function should be used to provide values for uniform variables defined as int, ivec2
-%% , ivec3, ivec4, or arrays of these. The `ui' variants of this function should be
-%% used to provide values for uniform variables defined as unsigned int, uvec2, uvec3, uvec4,
-%% or arrays of these. The `f' variants should be used to provide values for uniform
-%% variables of type float, vec2, vec3, vec4, or arrays of these. Either the `i', `ui'
-%% or `f' variants may be used to provide values for uniform variables of type bool, bvec2
-%% , bvec3, bvec4, or arrays of these. The uniform variable will be set to false if the input
-%% value is 0 or 0.0f, and it will be set to true otherwise.
-%%
-%% All active uniform variables defined in a program object are initialized to 0 when the
-%% program object is linked successfully. They retain the values assigned to them by a call
-%% to ``gl:uniform '' until the next successful link operation occurs on the program object,
-%% when they are once again initialized to 0.
-%%
-%% The commands ``gl:uniform{1|2|3|4}{f|i|ui}v'' can be used to modify a single uniform
-%% variable or a uniform variable array. These commands pass a count and a pointer to the
-%% values to be loaded into a uniform variable or a uniform variable array. A count of 1
-%% should be used if modifying the value of a single uniform variable, and a count of 1 or
-%% greater can be used to modify an entire array or part of an array. When loading `n'
-%% elements starting at an arbitrary position `m' in a uniform variable array, elements
-%% `m' + `n' - 1 in the array will be replaced with the new values. If `M' + `N'
-%% - 1 is larger than the size of the uniform variable array, values for all array elements
-%% beyond the end of the array will be ignored. The number specified in the name of the command
-%% indicates the number of components for each element in `Value' , and it should match
-%% the number of components in the data type of the specified uniform variable (e.g., `1'
-%% for float, int, bool; `2' for vec2, ivec2, bvec2, etc.). The data type specified
-%% in the name of the command must match the data type for the specified uniform variable
-%% as described previously for ``gl:uniform{1|2|3|4}{f|i|ui}''.
-%%
-%% For uniform variable arrays, each element of the array is considered to be of the type
-%% indicated in the name of the command (e.g., ``gl:uniform3f'' or ``gl:uniform3fv''
-%% can be used to load a uniform variable array of type vec3). The number of elements of
-%% the uniform variable array to be modified is specified by `Count'
-%%
-%% The commands ``gl:uniformMatrix{2|3|4|2x3|3x2|2x4|4x2|3x4|4x3}fv'' are used to modify
-%% a matrix or an array of matrices. The numbers in the command name are interpreted as the
-%% dimensionality of the matrix. The number `2' indicates a 2 × 2 matrix (i.e., 4 values),
-%% the number `3' indicates a 3 × 3 matrix (i.e., 9 values), and the number `4'
-%% indicates a 4 × 4 matrix (i.e., 16 values). Non-square matrix dimensionality is explicit,
-%% with the first number representing the number of columns and the second number representing
-%% the number of rows. For example, `2x4' indicates a 2 × 4 matrix with 2 columns and
-%% 4 rows (i.e., 8 values). If `Transpose' is `?GL_FALSE', each matrix is assumed
-%% to be supplied in column major order. If `Transpose' is `?GL_TRUE', each matrix
-%% is assumed to be supplied in row major order. The `Count' argument indicates the
-%% number of matrices to be passed. A count of 1 should be used if modifying the value of
-%% a single matrix, and a count greater than 1 can be used to modify an array of matrices.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUniform.xhtml">external</a> documentation.
-spec uniform1f(Location, V0) -> 'ok' when Location :: integer(),V0 :: float().
uniform1f(Location,V0) ->
cast(5476, <<Location:?GLint,V0:?GLfloat>>).
@@ -11811,19 +4917,7 @@ uniformMatrix4fv(Location,Transpose,Value) ->
%% a way for OpenGL implementers to convey more information about why the current program
%% is inefficient, suboptimal, failing to execute, and so on.
%%
-%% The status of the validation operation will be stored as part of the program object's
-%% state. This value will be set to `?GL_TRUE' if the validation succeeded, and `?GL_FALSE'
-%% otherwise. It can be queried by calling {@link gl:getProgramiv/2} with arguments `Program'
-%% and `?GL_VALIDATE_STATUS'. If validation is successful, `Program' is guaranteed
-%% to execute given the current state. Otherwise, `Program' is guaranteed to not execute.
-%%
-%%
-%% This function is typically useful only during application development. The informational
-%% string stored in the information log is completely implementation dependent; therefore,
-%% an application should not expect different OpenGL implementations to produce identical
-%% information strings.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgram.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glValidateProgram.xhtml">external</a> documentation.
-spec validateProgram(Program) -> 'ok' when Program :: integer().
validateProgram(Program) ->
cast(5495, <<Program:?GLuint>>).
@@ -11833,72 +4927,7 @@ validateProgram(Program) ->
%% The ``gl:vertexAttrib'' family of entry points allows an application to pass generic
%% vertex attributes in numbered locations.
%%
-%% Generic attributes are defined as four-component values that are organized into an array.
-%% The first entry of this array is numbered 0, and the size of the array is specified by
-%% the implementation-dependent constant `?GL_MAX_VERTEX_ATTRIBS'. Individual elements
-%% of this array can be modified with a ``gl:vertexAttrib'' call that specifies the index
-%% of the element to be modified and a value for that element.
-%%
-%% These commands can be used to specify one, two, three, or all four components of the generic
-%% vertex attribute specified by `Index' . A `1' in the name of the command indicates
-%% that only one value is passed, and it will be used to modify the first component of the
-%% generic vertex attribute. The second and third components will be set to 0, and the fourth
-%% component will be set to 1. Similarly, a `2' in the name of the command indicates
-%% that values are provided for the first two components, the third component will be set
-%% to 0, and the fourth component will be set to 1. A `3' in the name of the command
-%% indicates that values are provided for the first three components and the fourth component
-%% will be set to 1, whereas a `4' in the name indicates that values are provided for
-%% all four components.
-%%
-%% The letters `s', `f', `i', `d', `ub', `us', and `ui'
-%% indicate whether the arguments are of type short, float, int, double, unsigned byte, unsigned
-%% short, or unsigned int. When `v' is appended to the name, the commands can take a
-%% pointer to an array of such values.
-%%
-%% Additional capitalized letters can indicate further alterations to the default behavior
-%% of the glVertexAttrib function:
-%%
-%% The commands containing `N' indicate that the arguments will be passed as fixed-point
-%% values that are scaled to a normalized range according to the component conversion rules
-%% defined by the OpenGL specification. Signed values are understood to represent fixed-point
-%% values in the range [-1,1], and unsigned values are understood to represent fixed-point
-%% values in the range [0,1].
-%%
-%% The commands containing `I' indicate that the arguments are extended to full signed
-%% or unsigned integers.
-%%
-%% The commands containing `P' indicate that the arguments are stored as packed components
-%% within a larger natural type.
-%%
-%% The commands containing `L' indicate that the arguments are full 64-bit quantities
-%% and should be passed directly to shader inputs declared as 64-bit double precision types.
-%%
-%%
-%% OpenGL Shading Language attribute variables are allowed to be of type mat2, mat3, or mat4.
-%% Attributes of these types may be loaded using the ``gl:vertexAttrib'' entry points.
-%% Matrices must be loaded into successive generic attribute slots in column major order,
-%% with one column of the matrix in each generic attribute slot.
-%%
-%% A user-defined attribute variable declared in a vertex shader can be bound to a generic
-%% attribute index by calling {@link gl:bindAttribLocation/3} . This allows an application
-%% to use more descriptive variable names in a vertex shader. A subsequent change to the
-%% specified generic vertex attribute will be immediately reflected as a change to the corresponding
-%% attribute variable in the vertex shader.
-%%
-%% The binding between a generic vertex attribute index and a user-defined attribute variable
-%% in a vertex shader is part of the state of a program object, but the current value of
-%% the generic vertex attribute is not. The value of each generic vertex attribute is part
-%% of current state, just like standard vertex attributes, and it is maintained even if a
-%% different program object is used.
-%%
-%% An application may freely modify generic vertex attributes that are not bound to a named
-%% vertex shader attribute variable. These values are simply maintained as part of current
-%% state and will not be accessed by the vertex shader. If a generic vertex attribute bound
-%% to an attribute variable in a vertex shader is not updated while the vertex shader is
-%% executing, the vertex shader will repeatedly use the current value for the generic vertex
-%% attribute.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glVertexAttrib.xhtml">external</a> documentation.
-spec vertexAttrib1d(Index, X) -> 'ok' when Index :: integer(),X :: float().
vertexAttrib1d(Index,X) ->
cast(5496, <<Index:?GLuint,0:32,X:?GLdouble>>).
@@ -12096,37 +5125,7 @@ vertexAttrib4usv(Index,{V1,V2,V3,V4}) ->
%% and `Stride' specifies the byte stride from one attribute to the next, allowing vertices
%% and attributes to be packed into a single array or stored in separate arrays.
%%
-%% For ``gl:vertexAttribPointer'', if `Normalized' is set to `?GL_TRUE', it
-%% indicates that values stored in an integer format are to be mapped to the range [-1,1]
-%% (for signed values) or [0,1] (for unsigned values) when they are accessed and converted
-%% to floating point. Otherwise, values will be converted to floats directly without normalization.
-%%
-%%
-%% For ``gl:vertexAttribIPointer'', only the integer types `?GL_BYTE', `?GL_UNSIGNED_BYTE'
-%% , `?GL_SHORT', `?GL_UNSIGNED_SHORT', `?GL_INT', `?GL_UNSIGNED_INT'
-%% are accepted. Values are always left as integer values.
-%%
-%% ``gl:vertexAttribLPointer'' specifies state for a generic vertex attribute array associated
-%% with a shader attribute variable declared with 64-bit double precision components. `Type'
-%% must be `?GL_DOUBLE'. `Index' , `Size' , and `Stride' behave as described
-%% for ``gl:vertexAttribPointer'' and ``gl:vertexAttribIPointer''.
-%%
-%% If `Pointer' is not NULL, a non-zero named buffer object must be bound to the `?GL_ARRAY_BUFFER'
-%% target (see {@link gl:bindBuffer/2} ), otherwise an error is generated. `Pointer'
-%% is treated as a byte offset into the buffer object's data store. The buffer object binding
-%% (`?GL_ARRAY_BUFFER_BINDING') is saved as generic vertex attribute array state (`?GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING'
-%% ) for index `Index' .
-%%
-%% When a generic vertex attribute array is specified, `Size' , `Type' , `Normalized'
-%% , `Stride' , and `Pointer' are saved as vertex array state, in addition to the
-%% current vertex array buffer object binding.
-%%
-%% To enable and disable a generic vertex attribute array, call {@link gl:disableVertexAttribArray/1}
-%% and {@link gl:disableVertexAttribArray/1} with `Index' . If enabled, the generic vertex
-%% attribute array is used when {@link gl:drawArrays/3} , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4}
-%% , see `glMultiDrawElements', or {@link gl:drawRangeElements/6} is called.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribPointer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glVertexAttribPointer.xhtml">external</a> documentation.
-spec vertexAttribPointer(Index, Size, Type, Normalized, Stride, Pointer) -> 'ok' when Index :: integer(),Size :: integer(),Type :: enum(),Normalized :: 0|1,Stride :: integer(),Pointer :: offset()|mem().
vertexAttribPointer(Index,Size,Type,Normalized,Stride,Pointer) when is_integer(Pointer) ->
cast(5519, <<Index:?GLuint,Size:?GLint,Type:?GLenum,Normalized:?GLboolean,0:24,Stride:?GLsizei,Pointer:?GLuint>>);
@@ -12184,7 +5183,7 @@ uniformMatrix4x3fv(Location,Transpose,Value) ->
%% @doc glColorMaski
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorMaski.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec colorMaski(Index, R, G, B, A) -> 'ok' when Index :: integer(),R :: 0|1,G :: 0|1,B :: 0|1,A :: 0|1.
colorMaski(Index,R,G,B,A) ->
cast(5527, <<Index:?GLuint,R:?GLboolean,G:?GLboolean,B:?GLboolean,A:?GLboolean>>).
@@ -12209,14 +5208,14 @@ enablei(Target,Index) ->
%% @doc glEnablei
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEnablei.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec disablei(Target, Index) -> 'ok' when Target :: enum(),Index :: integer().
disablei(Target,Index) ->
cast(5531, <<Target:?GLenum,Index:?GLuint>>).
%% @doc glIsEnabledi
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsEnabledi.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec isEnabledi(Target, Index) -> 0|1 when Target :: enum(),Index :: integer().
isEnabledi(Target,Index) ->
call(5532, <<Target:?GLenum,Index:?GLuint>>).
@@ -12228,23 +5227,7 @@ isEnabledi(Target,Index) ->
%% a call to ``gl:beginTransformFeedback'' until a subsequent call to {@link gl:beginTransformFeedback/1}
%% . Transform feedback commands must be paired.
%%
-%% If no geometry shader is present, while transform feedback is active the `Mode'
-%% parameter to {@link gl:drawArrays/3} must match those specified in the following table: <table>
-%% <tbody><tr><td>` Transform Feedback ' `PrimitiveMode' </td><td>` Allowed Render Primitive '
-%% `Modes' </td></tr></tbody><tbody><tr><td>`?GL_POINTS'</td><td>`?GL_POINTS'</td>
-%% </tr><tr><td>`?GL_LINES'</td><td>`?GL_LINES', `?GL_LINE_LOOP', `?GL_LINE_STRIP'
-%% , `?GL_LINES_ADJACENCY', `?GL_LINE_STRIP_ADJACENCY'</td></tr><tr><td>`?GL_TRIANGLES'
-%% </td><td>`?GL_TRIANGLES', `?GL_TRIANGLE_STRIP', `?GL_TRIANGLE_FAN', `?GL_TRIANGLES_ADJACENCY'
-%% , `?GL_TRIANGLE_STRIP_ADJACENCY'</td></tr></tbody></table>
-%%
-%% If a geometry shader is present, the output primitive type from the geometry shader must
-%% match those provided in the following table: <table><tbody><tr><td>` Transform Feedback '
-%% `PrimitiveMode' </td><td>` Allowed Geometry Shader Output Primitive Type '</td></tr>
-%% </tbody><tbody><tr><td>`?GL_POINTS'</td><td>`?points'</td></tr><tr><td>`?GL_LINES'
-%% </td><td>`?line_strip'</td></tr><tr><td>`?GL_TRIANGLES'</td><td>`?triangle_strip'
-%% </td></tr></tbody></table>
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginTransformFeedback.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBeginTransformFeedback.xhtml">external</a> documentation.
-spec beginTransformFeedback(PrimitiveMode) -> 'ok' when PrimitiveMode :: enum().
beginTransformFeedback(PrimitiveMode) ->
cast(5533, <<PrimitiveMode:?GLenum>>).
@@ -12265,11 +5248,7 @@ endTransformFeedback() ->
%% a range of `Buffer' to the indexed buffer binding target, ``gl:bindBufferBase''
%% also binds the range to the generic buffer binding point specified by `Target' .
%%
-%% `Offset' specifies the offset in basic machine units into the buffer object `Buffer'
-%% and `Size' specifies the amount of data that can be read from the buffer object
-%% while used as an indexed target.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindBufferRange.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindBufferRange.xhtml">external</a> documentation.
-spec bindBufferRange(Target, Index, Buffer, Offset, Size) -> 'ok' when Target :: enum(),Index :: integer(),Buffer :: integer(),Offset :: integer(),Size :: integer().
bindBufferRange(Target,Index,Buffer,Offset,Size) ->
cast(5535, <<Target:?GLenum,Index:?GLuint,Buffer:?GLuint,0:32,Offset:?GLintptr,Size:?GLsizeiptr>>).
@@ -12284,7 +5263,7 @@ bindBufferRange(Target,Index,Buffer,Offset,Size) ->
%% binding target, ``gl:bindBufferBase'' also binds `Buffer' to the generic buffer
%% binding point specified by `Target' .
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindBufferBase.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindBufferBase.xhtml">external</a> documentation.
-spec bindBufferBase(Target, Index, Buffer) -> 'ok' when Target :: enum(),Index :: integer(),Buffer :: integer().
bindBufferBase(Target,Index,Buffer) ->
cast(5536, <<Target:?GLenum,Index:?GLuint,Buffer:?GLuint>>).
@@ -12297,32 +5276,7 @@ bindBufferBase(Target,Index,Buffer) ->
%% from the emitted vertices. Otherwise, the values of the selected vertex shader outputs
%% are recorded.
%%
-%% The state set by ``gl:tranformFeedbackVaryings'' is stored and takes effect next time {@link gl:linkProgram/1}
-%% is called on `Program' . When {@link gl:linkProgram/1} is called, `Program' is
-%% linked so that the values of the specified varying variables for the vertices of each
-%% primitive generated by the GL are written to a single buffer object if `BufferMode'
-%% is `?GL_INTERLEAVED_ATTRIBS' or multiple buffer objects if `BufferMode' is `?GL_SEPARATE_ATTRIBS'
-%% .
-%%
-%% In addition to the errors generated by ``gl:transformFeedbackVaryings'', the program `Program'
-%% will fail to link if:
-%%
-%% The count specified by ``gl:transformFeedbackVaryings'' is non-zero, but the program
-%% object has no vertex or geometry shader.
-%%
-%% Any variable name specified in the `Varyings' array is not declared as an output
-%% in the vertex shader (or the geometry shader, if active).
-%%
-%% Any two entries in the `Varyings' array specify the same varying variable.
-%%
-%% The total number of components to capture in any varying variable in `Varyings'
-%% is greater than the constant `?GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS' and
-%% the buffer mode is `?GL_SEPARATE_ATTRIBS'.
-%%
-%% The total number of components to capture is greater than the constant `?GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS'
-%% and the buffer mode is `?GL_INTERLEAVED_ATTRIBS'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTransformFeedbackVaryings.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTransformFeedbackVaryings.xhtml">external</a> documentation.
-spec transformFeedbackVaryings(Program, Varyings, BufferMode) -> 'ok' when Program :: integer(),Varyings :: iolist(),BufferMode :: enum().
transformFeedbackVaryings(Program,Varyings,BufferMode) ->
VaryingsTemp = list_to_binary([[Str|[0]] || Str <- Varyings ]),
@@ -12338,26 +5292,7 @@ transformFeedbackVaryings(Program,Varyings,BufferMode) ->
%% the `Varyings' array passed to {@link gl:transformFeedbackVaryings/3} , and an `Index'
%% of `?GL_TRANSFORM_FEEDBACK_VARYINGS-1' selects the last such variable.
%%
-%% The name of the selected varying is returned as a null-terminated string in `Name' .
-%% The actual number of characters written into `Name' , excluding the null terminator,
-%% is returned in `Length' . If `Length' is NULL, no length is returned. The maximum
-%% number of characters that may be written into `Name' , including the null terminator,
-%% is specified by `BufSize' .
-%%
-%% The length of the longest varying name in program is given by `?GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH'
-%% , which can be queried with {@link gl:getProgramiv/2} .
-%%
-%% For the selected varying variable, its type is returned into `Type' . The size of
-%% the varying is returned into `Size' . The value in `Size' is in units of the
-%% type returned in `Type' . The type returned can be any of the scalar, vector, or matrix
-%% attribute types returned by {@link gl:getActiveAttrib/3} . If an error occurred, the return
-%% parameters `Length' , `Size' , `Type' and `Name' will be unmodified.
-%% This command will return as much information about the varying variables as possible.
-%% If no information is available, `Length' will be set to zero and `Name' will
-%% be an empty string. This situation could arise if ``gl:getTransformFeedbackVarying''
-%% is called after a failed link.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTransformFeedbackVarying.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetTransformFeedbackVarying.xhtml">external</a> documentation.
-spec getTransformFeedbackVarying(Program, Index, BufSize) -> {Size :: integer(),Type :: enum(),Name :: string()} when Program :: integer(),Index :: integer(),BufSize :: integer().
getTransformFeedbackVarying(Program,Index,BufSize) ->
call(5538, <<Program:?GLuint,Index:?GLuint,BufSize:?GLsizei>>).
@@ -12372,7 +5307,7 @@ getTransformFeedbackVarying(Program,Index,BufSize) ->
%% is disabled. If `Clamp' is `?GL_FIXED_ONLY', read color clamping is enabled
%% only if the selected read buffer has fixed point components and disabled otherwise.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClampColor.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glClampColor.xhtml">external</a> documentation.
-spec clampColor(Target, Clamp) -> 'ok' when Target :: enum(),Clamp :: enum().
clampColor(Target,Clamp) ->
cast(5539, <<Target:?GLenum,Clamp:?GLenum>>).
@@ -12393,18 +5328,7 @@ clampColor(Target,Clamp) ->
%% is `?GL_QUERY_NO_WAIT', the GL may choose to unconditionally execute the subsequent
%% rendering commands without waiting for the query to complete.
%%
-%% If `Mode' is `?GL_QUERY_BY_REGION_WAIT', the GL will also wait for occlusion
-%% query results and discard rendering commands if the result of the occlusion query is zero.
-%% If the query result is non-zero, subsequent rendering commands are executed, but the GL
-%% may discard the results of the commands for any region of the framebuffer that did not
-%% contribute to the sample count in the specified occlusion query. Any such discarding is
-%% done in an implementation-dependent manner, but the rendering command results may not
-%% be discarded for any samples that contributed to the occlusion query sample count. If `Mode'
-%% is `?GL_QUERY_BY_REGION_NO_WAIT', the GL operates as in `?GL_QUERY_BY_REGION_WAIT'
-%% , but may choose to unconditionally execute the subsequent rendering commands without
-%% waiting for the query to complete.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginConditionalRender.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBeginConditionalRender.xhtml">external</a> documentation.
-spec beginConditionalRender(Id, Mode) -> 'ok' when Id :: integer(),Mode :: enum().
beginConditionalRender(Id,Mode) ->
cast(5540, <<Id:?GLuint,Mode:?GLenum>>).
@@ -12417,7 +5341,7 @@ endConditionalRender() ->
%% @doc glVertexAttribIPointer
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribIPointer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec vertexAttribIPointer(Index, Size, Type, Stride, Pointer) -> 'ok' when Index :: integer(),Size :: integer(),Type :: enum(),Stride :: integer(),Pointer :: offset()|mem().
vertexAttribIPointer(Index,Size,Type,Stride,Pointer) when is_integer(Pointer) ->
cast(5542, <<Index:?GLuint,Size:?GLint,Type:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>);
@@ -12433,7 +5357,7 @@ getVertexAttribIiv(Index,Pname) ->
%% @doc glGetVertexAttribI
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttribI.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getVertexAttribIuiv(Index, Pname) -> {integer(),integer(),integer(),integer()} when Index :: integer(),Pname :: enum().
getVertexAttribIuiv(Index,Pname) ->
call(5545, <<Index:?GLuint,Pname:?GLenum>>).
@@ -12556,21 +5480,7 @@ getUniformuiv(Program,Location) ->
%% . `Name' must be a null-terminated string. `ColorNumber' must be less than `?GL_MAX_DRAW_BUFFERS'
%% .
%%
-%% The bindings specified by ``gl:bindFragDataLocation'' have no effect until `Program'
-%% is next linked. Bindings may be specified at any time after `Program' has been created.
-%% Specifically, they may be specified before shader objects are attached to the program.
-%% Therefore, any name may be specified in `Name' , including a name that is never used
-%% as a varying out variable in any fragment shader object. Names beginning with `?gl_'
-%% are reserved by the GL.
-%%
-%% In addition to the errors generated by ``gl:bindFragDataLocation'', the program `Program'
-%% will fail to link if:
-%%
-%% The number of active outputs is greater than the value `?GL_MAX_DRAW_BUFFERS'.
-%%
-%% More than one varying out variable is bound to the same color number.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindFragDataLocation.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindFragDataLocation.xhtml">external</a> documentation.
-spec bindFragDataLocation(Program, Color, Name) -> 'ok' when Program :: integer(),Color :: integer(),Name :: string().
bindFragDataLocation(Program,Color,Name) ->
NameLen = length(Name),
@@ -12584,7 +5494,7 @@ bindFragDataLocation(Program,Color,Name) ->
%% not the name of an active user-defined varying out fragment shader variable within `Program'
%% , -1 will be returned.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetFragDataLocation.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetFragDataLocation.xhtml">external</a> documentation.
-spec getFragDataLocation(Program, Name) -> integer() when Program :: integer(),Name :: string().
getFragDataLocation(Program,Name) ->
NameLen = length(Name),
@@ -12655,7 +5565,7 @@ texParameterIiv(Target,Pname,Params) ->
%% @doc glTexParameterI
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexParameterI.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec texParameterIuiv(Target, Pname, Params) -> 'ok' when Target :: enum(),Pname :: enum(),Params :: tuple().
texParameterIuiv(Target,Pname,Params) ->
cast(5570, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,
@@ -12669,7 +5579,7 @@ getTexParameterIiv(Target,Pname) ->
%% @doc glGetTexParameterI
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexParameterI.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getTexParameterIuiv(Target, Pname) -> {integer(),integer(),integer(),integer()} when Target :: enum(),Pname :: enum().
getTexParameterIuiv(Target,Pname) ->
call(5572, <<Target:?GLenum,Pname:?GLenum>>).
@@ -12685,24 +5595,7 @@ getTexParameterIuiv(Target,Pname) ->
%% and conversion for fixed-point color buffers are performed in the same fashion as {@link gl:clearColor/4}
%% .
%%
-%% If `Buffer' is `?GL_DEPTH', `DrawBuffer' must be zero, and `Value'
-%% points to a single value to clear the depth buffer to. Only ``gl:clearBufferfv'' should
-%% be used to clear depth buffers. Clamping and conversion for fixed-point depth buffers
-%% are performed in the same fashion as {@link gl:clearDepth/1} .
-%%
-%% If `Buffer' is `?GL_STENCIL', `DrawBuffer' must be zero, and `Value'
-%% points to a single value to clear the stencil buffer to. Only ``gl:clearBufferiv'' should
-%% be used to clear stencil buffers. Masing and type conversion are performed in the same
-%% fashion as {@link gl:clearStencil/1} .
-%%
-%% ``gl:clearBufferfi'' may be used to clear the depth and stencil buffers. `Buffer'
-%% must be `?GL_DEPTH_STENCIL' and `DrawBuffer' must be zero. `Depth' and `Stencil'
-%% are the depth and stencil values, respectively.
-%%
-%% The result of ``gl:clearBuffer'' is undefined if no conversion between the type of `Value'
-%% and the buffer being cleared is defined. However, this is not an error.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearBuffer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glClearBuffer.xhtml">external</a> documentation.
-spec clearBufferiv(Buffer, Drawbuffer, Value) -> 'ok' when Buffer :: enum(),Drawbuffer :: integer(),Value :: tuple().
clearBufferiv(Buffer,Drawbuffer,Value) ->
cast(5573, <<Buffer:?GLenum,Drawbuffer:?GLint,(size(Value)):?GLuint,
@@ -12724,7 +5617,7 @@ clearBufferfv(Buffer,Drawbuffer,Value) ->
%% @doc glClearBufferfi
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearBufferfi.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec clearBufferfi(Buffer, Drawbuffer, Depth, Stencil) -> 'ok' when Buffer :: enum(),Drawbuffer :: integer(),Depth :: float(),Stencil :: integer().
clearBufferfi(Buffer,Drawbuffer,Depth,Stencil) ->
cast(5576, <<Buffer:?GLenum,Drawbuffer:?GLint,Depth:?GLfloat,Stencil:?GLint>>).
@@ -12737,14 +5630,14 @@ getStringi(Name,Index) ->
%% @doc glDrawArraysInstance
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawArraysInstance.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec drawArraysInstanced(Mode, First, Count, Primcount) -> 'ok' when Mode :: enum(),First :: integer(),Count :: integer(),Primcount :: integer().
drawArraysInstanced(Mode,First,Count,Primcount) ->
cast(5578, <<Mode:?GLenum,First:?GLint,Count:?GLsizei,Primcount:?GLsizei>>).
%% @doc glDrawElementsInstance
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsInstance.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec drawElementsInstanced(Mode, Count, Type, Indices, Primcount) -> 'ok' when Mode :: enum(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(),Primcount :: integer().
drawElementsInstanced(Mode,Count,Type,Indices,Primcount) when is_integer(Indices) ->
cast(5579, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint,Primcount:?GLsizei>>);
@@ -12760,62 +5653,9 @@ drawElementsInstanced(Mode,Count,Type,Indices,Primcount) ->
%% buffer texture is detached and no new buffer object is attached. If `Buffer' is non-zero,
%% it must be the name of an existing buffer object. `Target' must be `?GL_TEXTURE_BUFFER'
%% . `Internalformat' specifies the storage format, and must be one of the following
-%% sized internal formats: <table><tbody><tr><td></td><td></td><td></td><td></td><td>` Component '
-%% </td></tr></tbody><tbody><tr><td>`Sized Internal Format'</td><td>`Base Type'</td>
-%% <td>`Components'</td><td>`Norm'</td><td>0</td><td>1</td><td>2</td><td>3</td></tr>
-%% <tr><td>`?GL_R8'</td><td>ubyte</td><td>1</td><td>YES</td><td>R</td><td>0</td><td>0</td>
-%% <td>1</td></tr><tr><td>`?GL_R16'</td><td>ushort</td><td>1</td><td>YES</td><td>R</td><td>
-%% 0</td><td>0</td><td>1</td></tr><tr><td>`?GL_R16F'</td><td>half</td><td>1</td><td>NO</td>
-%% <td>R</td><td>0</td><td>0</td><td>1</td></tr><tr><td>`?GL_R32F'</td><td>float</td><td>
-%% 1</td><td>NO</td><td>R</td><td>0</td><td>0</td><td>1</td></tr><tr><td>`?GL_R8I'</td><td>
-%% byte</td><td>1</td><td>NO</td><td>R</td><td>0</td><td>0</td><td>1</td></tr><tr><td>`?GL_R16I'
-%% </td><td>short</td><td>1</td><td>NO</td><td>R</td><td>0</td><td>0</td><td>1</td></tr><tr><td>
-%% `?GL_R32I'</td><td>int</td><td>1</td><td>NO</td><td>R</td><td>0</td><td>0</td><td>1</td>
-%% </tr><tr><td>`?GL_R8UI'</td><td>ubyte</td><td>1</td><td>NO</td><td>R</td><td>0</td><td>
-%% 0</td><td>1</td></tr><tr><td>`?GL_R16UI'</td><td>ushort</td><td>1</td><td>NO</td><td>
-%% R</td><td>0</td><td>0</td><td>1</td></tr><tr><td>`?GL_R32UI'</td><td>uint</td><td>1</td>
-%% <td>NO</td><td>R</td><td>0</td><td>0</td><td>1</td></tr><tr><td>`?GL_RG8'</td><td>ubyte
-%% </td><td>2</td><td>YES</td><td>R</td><td>G</td><td>0</td><td>1</td></tr><tr><td>`?GL_RG16'
-%% </td><td>ushort</td><td>2</td><td>YES</td><td>R</td><td>G</td><td>0</td><td>1</td></tr><tr>
-%% <td>`?GL_RG16F'</td><td>half</td><td>2</td><td>NO</td><td>R</td><td>G</td><td>0</td><td>
-%% 1</td></tr><tr><td>`?GL_RG32F'</td><td>float</td><td>2</td><td>NO</td><td>R</td><td>G
-%% </td><td>0</td><td>1</td></tr><tr><td>`?GL_RG8I'</td><td>byte</td><td>2</td><td>NO</td>
-%% <td>R</td><td>G</td><td>0</td><td>1</td></tr><tr><td>`?GL_RG16I'</td><td>short</td><td>
-%% 2</td><td>NO</td><td>R</td><td>G</td><td>0</td><td>1</td></tr><tr><td>`?GL_RG32I'</td>
-%% <td>int</td><td>2</td><td>NO</td><td>R</td><td>G</td><td>0</td><td>1</td></tr><tr><td>`?GL_RG8UI'
-%% </td><td>ubyte</td><td>2</td><td>NO</td><td>R</td><td>G</td><td>0</td><td>1</td></tr><tr><td>
-%% `?GL_RG16UI'</td><td>ushort</td><td>2</td><td>NO</td><td>R</td><td>G</td><td>0</td><td>
-%% 1</td></tr><tr><td>`?GL_RG32UI'</td><td>uint</td><td>2</td><td>NO</td><td>R</td><td>G
-%% </td><td>0</td><td>1</td></tr><tr><td>`?GL_RGB32F'</td><td>float</td><td>3</td><td>NO
-%% </td><td>R</td><td>G</td><td>B</td><td>1</td></tr><tr><td>`?GL_RGB32I'</td><td>int</td>
-%% <td>3</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>1</td></tr><tr><td>`?GL_RGB32UI'
-%% </td><td>uint</td><td>3</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>1</td></tr><tr><td>
-%% `?GL_RGBA8'</td><td>uint</td><td>4</td><td>YES</td><td>R</td><td>G</td><td>B</td><td>
-%% A</td></tr><tr><td>`?GL_RGBA16'</td><td>short</td><td>4</td><td>YES</td><td>R</td><td>
-%% G</td><td>B</td><td>A</td></tr><tr><td>`?GL_RGBA16F'</td><td>half</td><td>4</td><td>NO
-%% </td><td>R</td><td>G</td><td>B</td><td>A</td></tr><tr><td>`?GL_RGBA32F'</td><td>float
-%% </td><td>4</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>A</td></tr><tr><td>`?GL_RGBA8I'
-%% </td><td>byte</td><td>4</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>A</td></tr><tr><td>
-%% `?GL_RGBA16I'</td><td>short</td><td>4</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>
-%% A</td></tr><tr><td>`?GL_RGBA32I'</td><td>int</td><td>4</td><td>NO</td><td>R</td><td>G
-%% </td><td>B</td><td>A</td></tr><tr><td>`?GL_RGBA8UI'</td><td>ubyte</td><td>4</td><td>NO
-%% </td><td>R</td><td>G</td><td>B</td><td>A</td></tr><tr><td>`?GL_RGBA16UI'</td><td>ushort
-%% </td><td>4</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>A</td></tr><tr><td>`?GL_RGBA32UI'
-%% </td><td>uint</td><td>4</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>A</td></tr></tbody>
-%% </table>
-%%
-%% When a buffer object is attached to a buffer texture, the buffer object's data store
-%% is taken as the texture's texel array. The number of texels in the buffer texture's texel
-%% array is given by buffer_size components×sizeof( base_type/)
-%%
-%% where `buffer_size' is the size of the buffer object, in basic machine units and
-%% components and base type are the element count and base data type for elements, as specified
-%% in the table above. The number of texels in the texel array is then clamped to the implementation-dependent
-%% limit `?GL_MAX_TEXTURE_BUFFER_SIZE'. When a buffer texture is accessed in a shader,
-%% the results of a texel fetch are undefined if the specified texel coordinate is negative,
-%% or greater than or equal to the clamped number of texels in the texel array.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexBuffer.xml">external</a> documentation.
+%% sized internal formats:
+%%
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexBuffer.xhtml">external</a> documentation.
-spec texBuffer(Target, Internalformat, Buffer) -> 'ok' when Target :: enum(),Internalformat :: enum(),Buffer :: integer().
texBuffer(Target,Internalformat,Buffer) ->
cast(5581, <<Target:?GLenum,Internalformat:?GLenum,Buffer:?GLuint>>).
@@ -12825,19 +5665,7 @@ texBuffer(Target,Internalformat,Buffer) ->
%% ``gl:primitiveRestartIndex'' specifies a vertex array element that is treated specially
%% when primitive restarting is enabled. This is known as the primitive restart index.
%%
-%% When one of the `Draw*' commands transfers a set of generic attribute array elements
-%% to the GL, if the index within the vertex arrays corresponding to that set is equal to
-%% the primitive restart index, then the GL does not process those elements as a vertex.
-%% Instead, it is as if the drawing command ended with the immediately preceding transfer,
-%% and another drawing command is immediately started with the same parameters, but only
-%% transferring the immediately following element through the end of the originally specified
-%% elements.
-%%
-%% When either {@link gl:drawElementsBaseVertex/5} , {@link gl:drawElementsInstancedBaseVertex/6}
-%% or see `glMultiDrawElementsBaseVertex' is used, the primitive restart comparison
-%% occurs before the basevertex offset is added to the array index.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPrimitiveRestartIndex.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPrimitiveRestartIndex.xhtml">external</a> documentation.
-spec primitiveRestartIndex(Index) -> 'ok' when Index :: integer().
primitiveRestartIndex(Index) ->
cast(5582, <<Index:?GLuint>>).
@@ -12850,7 +5678,7 @@ getInteger64i_v(Target,Index) ->
%% @doc glGetBufferParameteri64v
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferParameteri64v.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getBufferParameteri64v(Target, Pname) -> [integer()] when Target :: enum(),Pname :: enum().
getBufferParameteri64v(Target,Pname) ->
call(5584, <<Target:?GLenum,Pname:?GLenum>>).
@@ -12863,51 +5691,7 @@ getBufferParameteri64v(Target,Pname) ->
%% `Target' must be `?GL_DRAW_FRAMEBUFFER', `?GL_READ_FRAMEBUFFER', or `?GL_FRAMEBUFFER'
%% . `?GL_FRAMEBUFFER' is equivalent to `?GL_DRAW_FRAMEBUFFER'.
%%
-%% `Attachment' specifies the logical attachment of the framebuffer and must be `?GL_COLOR_ATTACHMENT'
-%% `i', `?GL_DEPTH_ATTACHMENT', `?GL_STENCIL_ATTACHMENT' or `?GL_DEPTH_STENCIL_ATTACHMMENT'
-%% . `i' in `?GL_COLOR_ATTACHMENT'`i' may range from zero to the value of `?GL_MAX_COLOR_ATTACHMENTS'
-%% - 1. Attaching a level of a texture to `?GL_DEPTH_STENCIL_ATTACHMENT' is equivalent
-%% to attaching that level to both the `?GL_DEPTH_ATTACHMENT'`and' the `?GL_STENCIL_ATTACHMENT'
-%% attachment points simultaneously.
-%%
-%% `Textarget' specifies what type of texture is named by `Texture' , and for cube
-%% map textures, specifies the face that is to be attached. If `Texture' is not zero,
-%% it must be the name of an existing texture with type `Textarget' , unless it is a
-%% cube map texture, in which case `Textarget' must be `?GL_TEXTURE_CUBE_MAP_POSITIVE_X'
-%% `?GL_TEXTURE_CUBE_MAP_NEGATIVE_X', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Y', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Y'
-%% , `?GL_TEXTURE_CUBE_MAP_POSITIVE_Z', or `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Z'.
-%%
-%% If `Texture' is non-zero, the specified `Level' of the texture object named `Texture'
-%% is attached to the framebfufer attachment point named by `Attachment' . For ``gl:framebufferTexture1D''
-%% , ``gl:framebufferTexture2D'', and ``gl:framebufferTexture3D'', `Texture' must
-%% be zero or the name of an existing texture with a target of `Textarget' , or `Texture'
-%% must be the name of an existing cube-map texture and `Textarget' must be one of `?GL_TEXTURE_CUBE_MAP_POSITIVE_X'
-%% , `?GL_TEXTURE_CUBE_MAP_POSITIVE_Y', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Z', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_X'
-%% , `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Y', or `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Z'.
-%%
-%% If `Textarget' is `?GL_TEXTURE_RECTANGLE', `?GL_TEXTURE_2D_MULTISAMPLE',
-%% or `?GL_TEXTURE_2D_MULTISAMPLE_ARRAY', then `Level' must be zero. If `Textarget'
-%% is `?GL_TEXTURE_3D', then level must be greater than or equal to zero and less than
-%% or equal to log2 of the value of `?GL_MAX_3D_TEXTURE_SIZE'. If `Textarget' is
-%% one of `?GL_TEXTURE_CUBE_MAP_POSITIVE_X', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Y', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Z'
-%% , `?GL_TEXTURE_CUBE_MAP_NEGATIVE_X', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Y', or `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Z'
-%% , then `Level' must be greater than or equal to zero and less than or equal to log2
-%% of the value of `?GL_MAX_CUBE_MAP_TEXTURE_SIZE'. For all other values of `Textarget'
-%% , `Level' must be greater than or equal to zero and no larger than log2 of the value
-%% of `?GL_MAX_TEXTURE_SIZE'.
-%%
-%% `Layer' specifies the layer of a 2-dimensional image within a 3-dimensional texture.
-%%
-%%
-%% For ``gl:framebufferTexture1D'', if `Texture' is not zero, then `Textarget'
-%% must be `?GL_TEXTURE_1D'. For ``gl:framebufferTexture2D'', if `Texture' is
-%% not zero, `Textarget' must be one of `?GL_TEXTURE_2D', `?GL_TEXTURE_RECTANGLE'
-%% , `?GL_TEXTURE_CUBE_MAP_POSITIVE_X', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Y', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Z'
-%% , `?GL_TEXTURE_CUBE_MAP_NEGATIVE_X', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Y', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Z'
-%% , or `?GL_TEXTURE_2D_MULTISAMPLE'. For ``gl:framebufferTexture3D'', if `Texture'
-%% is not zero, then `Textarget' must be `?GL_TEXTURE_3D'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFramebufferTexture.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glFramebufferTexture.xhtml">external</a> documentation.
-spec framebufferTexture(Target, Attachment, Texture, Level) -> 'ok' when Target :: enum(),Attachment :: enum(),Texture :: integer(),Level :: integer().
framebufferTexture(Target,Attachment,Texture,Level) ->
cast(5585, <<Target:?GLenum,Attachment:?GLenum,Texture:?GLuint,Level:?GLint>>).
@@ -12921,9 +5705,7 @@ framebufferTexture(Target,Attachment,Texture,Level) ->
%% vertices being rendered. An attribute is referred to as instanced if its `?GL_VERTEX_ATTRIB_ARRAY_DIVISOR'
%% value is non-zero.
%%
-%% `Index' must be less than the value of `?GL_MAX_VERTEX_ATTRIBUTES'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribDivisor.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glVertexAttribDivisor.xhtml">external</a> documentation.
-spec vertexAttribDivisor(Index, Divisor) -> 'ok' when Index :: integer(),Divisor :: integer().
vertexAttribDivisor(Index,Divisor) ->
cast(5586, <<Index:?GLuint,Divisor:?GLuint>>).
@@ -12938,13 +5720,7 @@ vertexAttribDivisor(Index,Divisor) ->
%% is the value of `?GL_SAMPLES' for the current framebuffer. At least 1 sample for
%% each covered fragment is generated.
%%
-%% A `Value' of 1.0 indicates that each sample in the framebuffer should be indpendently
-%% shaded. A `Value' of 0.0 effectively allows the GL to ignore sample rate shading.
-%% Any value between 0.0 and 1.0 allows the GL to shade only a subset of the total samples
-%% within each covered fragment. Which samples are shaded and the algorithm used to select
-%% that subset of the fragment's samples is implementation dependent.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMinSampleShading.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMinSampleShading.xhtml">external</a> documentation.
-spec minSampleShading(Value) -> 'ok' when Value :: clamp().
minSampleShading(Value) ->
cast(5587, <<Value:?GLclampf>>).
@@ -12963,7 +5739,7 @@ blendEquationSeparatei(Buf,ModeRGB,ModeAlpha) ->
%% @doc glBlendFunci
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendFunci.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec blendFunci(Buf, Src, Dst) -> 'ok' when Buf :: integer(),Src :: enum(),Dst :: enum().
blendFunci(Buf,Src,Dst) ->
cast(5590, <<Buf:?GLuint,Src:?GLenum,Dst:?GLenum>>).
@@ -12976,7 +5752,7 @@ blendFuncSeparatei(Buf,SrcRGB,DstRGB,SrcAlpha,DstAlpha) ->
%% @doc glLoadTransposeMatrixARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadTransposeMatrixARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec loadTransposeMatrixfARB(M) -> 'ok' when M :: matrix().
loadTransposeMatrixfARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
cast(5592, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,M13:?GLfloat,M14:?GLfloat,M15:?GLfloat,M16:?GLfloat>>);
@@ -12985,7 +5761,7 @@ loadTransposeMatrixfARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
%% @doc glLoadTransposeMatrixARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadTransposeMatrixARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec loadTransposeMatrixdARB(M) -> 'ok' when M :: matrix().
loadTransposeMatrixdARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
cast(5593, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble>>);
@@ -12994,7 +5770,7 @@ loadTransposeMatrixdARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
%% @doc glMultTransposeMatrixARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultTransposeMatrixARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec multTransposeMatrixfARB(M) -> 'ok' when M :: matrix().
multTransposeMatrixfARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
cast(5594, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,M13:?GLfloat,M14:?GLfloat,M15:?GLfloat,M16:?GLfloat>>);
@@ -13003,7 +5779,7 @@ multTransposeMatrixfARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
%% @doc glMultTransposeMatrixARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultTransposeMatrixARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec multTransposeMatrixdARB(M) -> 'ok' when M :: matrix().
multTransposeMatrixdARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) ->
cast(5595, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble>>);
@@ -13012,7 +5788,7 @@ multTransposeMatrixdARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) ->
%% @doc glWeightARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec weightbvARB(Weights) -> 'ok' when Weights :: [integer()].
weightbvARB(Weights) ->
WeightsLen = length(Weights),
@@ -13021,7 +5797,7 @@ weightbvARB(Weights) ->
%% @doc glWeightARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec weightsvARB(Weights) -> 'ok' when Weights :: [integer()].
weightsvARB(Weights) ->
WeightsLen = length(Weights),
@@ -13030,7 +5806,7 @@ weightsvARB(Weights) ->
%% @doc glWeightARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec weightivARB(Weights) -> 'ok' when Weights :: [integer()].
weightivARB(Weights) ->
WeightsLen = length(Weights),
@@ -13039,7 +5815,7 @@ weightivARB(Weights) ->
%% @doc glWeightARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec weightfvARB(Weights) -> 'ok' when Weights :: [float()].
weightfvARB(Weights) ->
WeightsLen = length(Weights),
@@ -13048,7 +5824,7 @@ weightfvARB(Weights) ->
%% @doc glWeightARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec weightdvARB(Weights) -> 'ok' when Weights :: [float()].
weightdvARB(Weights) ->
WeightsLen = length(Weights),
@@ -13057,7 +5833,7 @@ weightdvARB(Weights) ->
%% @doc glWeightARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec weightubvARB(Weights) -> 'ok' when Weights :: [integer()].
weightubvARB(Weights) ->
WeightsLen = length(Weights),
@@ -13066,7 +5842,7 @@ weightubvARB(Weights) ->
%% @doc glWeightARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec weightusvARB(Weights) -> 'ok' when Weights :: [integer()].
weightusvARB(Weights) ->
WeightsLen = length(Weights),
@@ -13075,7 +5851,7 @@ weightusvARB(Weights) ->
%% @doc glWeightARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec weightuivARB(Weights) -> 'ok' when Weights :: [integer()].
weightuivARB(Weights) ->
WeightsLen = length(Weights),
@@ -13084,21 +5860,21 @@ weightuivARB(Weights) ->
%% @doc glVertexBlenARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexBlenARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec vertexBlendARB(Count) -> 'ok' when Count :: integer().
vertexBlendARB(Count) ->
cast(5604, <<Count:?GLint>>).
%% @doc glCurrentPaletteMatrixARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCurrentPaletteMatrixARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec currentPaletteMatrixARB(Index) -> 'ok' when Index :: integer().
currentPaletteMatrixARB(Index) ->
cast(5605, <<Index:?GLint>>).
%% @doc glMatrixIndexARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMatrixIndexARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec matrixIndexubvARB(Indices) -> 'ok' when Indices :: [integer()].
matrixIndexubvARB(Indices) ->
IndicesLen = length(Indices),
@@ -13107,7 +5883,7 @@ matrixIndexubvARB(Indices) ->
%% @doc glMatrixIndexARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMatrixIndexARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec matrixIndexusvARB(Indices) -> 'ok' when Indices :: [integer()].
matrixIndexusvARB(Indices) ->
IndicesLen = length(Indices),
@@ -13116,7 +5892,7 @@ matrixIndexusvARB(Indices) ->
%% @doc glMatrixIndexARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMatrixIndexARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec matrixIndexuivARB(Indices) -> 'ok' when Indices :: [integer()].
matrixIndexuivARB(Indices) ->
IndicesLen = length(Indices),
@@ -13125,7 +5901,7 @@ matrixIndexuivARB(Indices) ->
%% @doc glProgramStringARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramStringARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec programStringARB(Target, Format, String) -> 'ok' when Target :: enum(),Format :: enum(),String :: string().
programStringARB(Target,Format,String) ->
StringLen = length(String),
@@ -13133,14 +5909,14 @@ programStringARB(Target,Format,String) ->
%% @doc glBindProgramARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindProgramARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec bindProgramARB(Target, Program) -> 'ok' when Target :: enum(),Program :: integer().
bindProgramARB(Target,Program) ->
cast(5610, <<Target:?GLenum,Program:?GLuint>>).
%% @doc glDeleteProgramsARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteProgramsARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec deleteProgramsARB(Programs) -> 'ok' when Programs :: [integer()].
deleteProgramsARB(Programs) ->
ProgramsLen = length(Programs),
@@ -13149,98 +5925,98 @@ deleteProgramsARB(Programs) ->
%% @doc glGenProgramsARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenProgramsARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec genProgramsARB(N) -> [integer()] when N :: integer().
genProgramsARB(N) ->
call(5612, <<N:?GLsizei>>).
%% @doc glProgramEnvParameterARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramEnvParameterARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec programEnvParameter4dARB(Target, Index, X, Y, Z, W) -> 'ok' when Target :: enum(),Index :: integer(),X :: float(),Y :: float(),Z :: float(),W :: float().
programEnvParameter4dARB(Target,Index,X,Y,Z,W) ->
cast(5613, <<Target:?GLenum,Index:?GLuint,X:?GLdouble,Y:?GLdouble,Z:?GLdouble,W:?GLdouble>>).
%% @doc glProgramEnvParameterARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramEnvParameterARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec programEnvParameter4dvARB(Target, Index, Params) -> 'ok' when Target :: enum(),Index :: integer(),Params :: {float(),float(),float(),float()}.
programEnvParameter4dvARB(Target,Index,{P1,P2,P3,P4}) ->
cast(5614, <<Target:?GLenum,Index:?GLuint,P1:?GLdouble,P2:?GLdouble,P3:?GLdouble,P4:?GLdouble>>).
%% @doc glProgramEnvParameterARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramEnvParameterARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec programEnvParameter4fARB(Target, Index, X, Y, Z, W) -> 'ok' when Target :: enum(),Index :: integer(),X :: float(),Y :: float(),Z :: float(),W :: float().
programEnvParameter4fARB(Target,Index,X,Y,Z,W) ->
cast(5615, <<Target:?GLenum,Index:?GLuint,X:?GLfloat,Y:?GLfloat,Z:?GLfloat,W:?GLfloat>>).
%% @doc glProgramEnvParameterARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramEnvParameterARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec programEnvParameter4fvARB(Target, Index, Params) -> 'ok' when Target :: enum(),Index :: integer(),Params :: {float(),float(),float(),float()}.
programEnvParameter4fvARB(Target,Index,{P1,P2,P3,P4}) ->
cast(5616, <<Target:?GLenum,Index:?GLuint,P1:?GLfloat,P2:?GLfloat,P3:?GLfloat,P4:?GLfloat>>).
%% @doc glProgramLocalParameterARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramLocalParameterARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec programLocalParameter4dARB(Target, Index, X, Y, Z, W) -> 'ok' when Target :: enum(),Index :: integer(),X :: float(),Y :: float(),Z :: float(),W :: float().
programLocalParameter4dARB(Target,Index,X,Y,Z,W) ->
cast(5617, <<Target:?GLenum,Index:?GLuint,X:?GLdouble,Y:?GLdouble,Z:?GLdouble,W:?GLdouble>>).
%% @doc glProgramLocalParameterARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramLocalParameterARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec programLocalParameter4dvARB(Target, Index, Params) -> 'ok' when Target :: enum(),Index :: integer(),Params :: {float(),float(),float(),float()}.
programLocalParameter4dvARB(Target,Index,{P1,P2,P3,P4}) ->
cast(5618, <<Target:?GLenum,Index:?GLuint,P1:?GLdouble,P2:?GLdouble,P3:?GLdouble,P4:?GLdouble>>).
%% @doc glProgramLocalParameterARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramLocalParameterARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec programLocalParameter4fARB(Target, Index, X, Y, Z, W) -> 'ok' when Target :: enum(),Index :: integer(),X :: float(),Y :: float(),Z :: float(),W :: float().
programLocalParameter4fARB(Target,Index,X,Y,Z,W) ->
cast(5619, <<Target:?GLenum,Index:?GLuint,X:?GLfloat,Y:?GLfloat,Z:?GLfloat,W:?GLfloat>>).
%% @doc glProgramLocalParameterARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramLocalParameterARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec programLocalParameter4fvARB(Target, Index, Params) -> 'ok' when Target :: enum(),Index :: integer(),Params :: {float(),float(),float(),float()}.
programLocalParameter4fvARB(Target,Index,{P1,P2,P3,P4}) ->
cast(5620, <<Target:?GLenum,Index:?GLuint,P1:?GLfloat,P2:?GLfloat,P3:?GLfloat,P4:?GLfloat>>).
%% @doc glGetProgramEnvParameterARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramEnvParameterARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getProgramEnvParameterdvARB(Target, Index) -> {float(),float(),float(),float()} when Target :: enum(),Index :: integer().
getProgramEnvParameterdvARB(Target,Index) ->
call(5621, <<Target:?GLenum,Index:?GLuint>>).
%% @doc glGetProgramEnvParameterARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramEnvParameterARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getProgramEnvParameterfvARB(Target, Index) -> {float(),float(),float(),float()} when Target :: enum(),Index :: integer().
getProgramEnvParameterfvARB(Target,Index) ->
call(5622, <<Target:?GLenum,Index:?GLuint>>).
%% @doc glGetProgramLocalParameterARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramLocalParameterARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getProgramLocalParameterdvARB(Target, Index) -> {float(),float(),float(),float()} when Target :: enum(),Index :: integer().
getProgramLocalParameterdvARB(Target,Index) ->
call(5623, <<Target:?GLenum,Index:?GLuint>>).
%% @doc glGetProgramLocalParameterARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramLocalParameterARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getProgramLocalParameterfvARB(Target, Index) -> {float(),float(),float(),float()} when Target :: enum(),Index :: integer().
getProgramLocalParameterfvARB(Target,Index) ->
call(5624, <<Target:?GLenum,Index:?GLuint>>).
%% @doc glGetProgramStringARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramStringARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getProgramStringARB(Target, Pname, String) -> 'ok' when Target :: enum(),Pname :: enum(),String :: mem().
getProgramStringARB(Target,Pname,String) ->
send_bin(String),
@@ -13248,42 +6024,42 @@ getProgramStringARB(Target,Pname,String) ->
%% @doc glGetBufferParameterARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferParameterARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getBufferParameterivARB(Target, Pname) -> [integer()] when Target :: enum(),Pname :: enum().
getBufferParameterivARB(Target,Pname) ->
call(5626, <<Target:?GLenum,Pname:?GLenum>>).
%% @doc glDeleteObjectARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteObjectARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec deleteObjectARB(Obj) -> 'ok' when Obj :: integer().
deleteObjectARB(Obj) ->
cast(5627, <<Obj:?GLhandleARB>>).
%% @doc glGetHandleARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetHandleARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getHandleARB(Pname) -> integer() when Pname :: enum().
getHandleARB(Pname) ->
call(5628, <<Pname:?GLenum>>).
%% @doc glDetachObjectARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDetachObjectARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec detachObjectARB(ContainerObj, AttachedObj) -> 'ok' when ContainerObj :: integer(),AttachedObj :: integer().
detachObjectARB(ContainerObj,AttachedObj) ->
cast(5629, <<ContainerObj:?GLhandleARB,AttachedObj:?GLhandleARB>>).
%% @doc glCreateShaderObjectARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateShaderObjectARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec createShaderObjectARB(ShaderType) -> integer() when ShaderType :: enum().
createShaderObjectARB(ShaderType) ->
call(5630, <<ShaderType:?GLenum>>).
%% @doc glShaderSourceARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShaderSourceARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec shaderSourceARB(ShaderObj, String) -> 'ok' when ShaderObj :: integer(),String :: iolist().
shaderSourceARB(ShaderObj,String) ->
StringTemp = list_to_binary([[Str|[0]] || Str <- String ]),
@@ -13292,77 +6068,77 @@ shaderSourceARB(ShaderObj,String) ->
%% @doc glCompileShaderARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompileShaderARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec compileShaderARB(ShaderObj) -> 'ok' when ShaderObj :: integer().
compileShaderARB(ShaderObj) ->
cast(5632, <<ShaderObj:?GLhandleARB>>).
%% @doc glCreateProgramObjectARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateProgramObjectARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec createProgramObjectARB() -> integer().
createProgramObjectARB() ->
call(5633, <<>>).
%% @doc glAttachObjectARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAttachObjectARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec attachObjectARB(ContainerObj, Obj) -> 'ok' when ContainerObj :: integer(),Obj :: integer().
attachObjectARB(ContainerObj,Obj) ->
cast(5634, <<ContainerObj:?GLhandleARB,Obj:?GLhandleARB>>).
%% @doc glLinkProgramARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLinkProgramARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec linkProgramARB(ProgramObj) -> 'ok' when ProgramObj :: integer().
linkProgramARB(ProgramObj) ->
cast(5635, <<ProgramObj:?GLhandleARB>>).
%% @doc glUseProgramObjectARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUseProgramObjectARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec useProgramObjectARB(ProgramObj) -> 'ok' when ProgramObj :: integer().
useProgramObjectARB(ProgramObj) ->
cast(5636, <<ProgramObj:?GLhandleARB>>).
%% @doc glValidateProgramARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgramARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec validateProgramARB(ProgramObj) -> 'ok' when ProgramObj :: integer().
validateProgramARB(ProgramObj) ->
cast(5637, <<ProgramObj:?GLhandleARB>>).
%% @doc glGetObjectParameterARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetObjectParameterARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getObjectParameterfvARB(Obj, Pname) -> float() when Obj :: integer(),Pname :: enum().
getObjectParameterfvARB(Obj,Pname) ->
call(5638, <<Obj:?GLhandleARB,Pname:?GLenum>>).
%% @doc glGetObjectParameterARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetObjectParameterARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getObjectParameterivARB(Obj, Pname) -> integer() when Obj :: integer(),Pname :: enum().
getObjectParameterivARB(Obj,Pname) ->
call(5639, <<Obj:?GLhandleARB,Pname:?GLenum>>).
%% @doc glGetInfoLogARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetInfoLogARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getInfoLogARB(Obj, MaxLength) -> string() when Obj :: integer(),MaxLength :: integer().
getInfoLogARB(Obj,MaxLength) ->
call(5640, <<Obj:?GLhandleARB,MaxLength:?GLsizei>>).
%% @doc glGetAttachedObjectsARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetAttachedObjectsARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getAttachedObjectsARB(ContainerObj, MaxCount) -> [integer()] when ContainerObj :: integer(),MaxCount :: integer().
getAttachedObjectsARB(ContainerObj,MaxCount) ->
call(5641, <<ContainerObj:?GLhandleARB,MaxCount:?GLsizei>>).
%% @doc glGetUniformLocationARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformLocationARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getUniformLocationARB(ProgramObj, Name) -> integer() when ProgramObj :: integer(),Name :: string().
getUniformLocationARB(ProgramObj,Name) ->
NameLen = length(Name),
@@ -13370,35 +6146,35 @@ getUniformLocationARB(ProgramObj,Name) ->
%% @doc glGetActiveUniformARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniformARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getActiveUniformARB(ProgramObj, Index, MaxLength) -> {Size :: integer(),Type :: enum(),Name :: string()} when ProgramObj :: integer(),Index :: integer(),MaxLength :: integer().
getActiveUniformARB(ProgramObj,Index,MaxLength) ->
call(5643, <<ProgramObj:?GLhandleARB,Index:?GLuint,MaxLength:?GLsizei>>).
%% @doc glGetUniformARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getUniformfvARB(ProgramObj, Location) -> matrix() when ProgramObj :: integer(),Location :: integer().
getUniformfvARB(ProgramObj,Location) ->
call(5644, <<ProgramObj:?GLhandleARB,Location:?GLint>>).
%% @doc glGetUniformARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getUniformivARB(ProgramObj, Location) -> {integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer()} when ProgramObj :: integer(),Location :: integer().
getUniformivARB(ProgramObj,Location) ->
call(5645, <<ProgramObj:?GLhandleARB,Location:?GLint>>).
%% @doc glGetShaderSourceARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderSourceARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getShaderSourceARB(Obj, MaxLength) -> string() when Obj :: integer(),MaxLength :: integer().
getShaderSourceARB(Obj,MaxLength) ->
call(5646, <<Obj:?GLhandleARB,MaxLength:?GLsizei>>).
%% @doc glBindAttribLocationARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindAttribLocationARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec bindAttribLocationARB(ProgramObj, Index, Name) -> 'ok' when ProgramObj :: integer(),Index :: integer(),Name :: string().
bindAttribLocationARB(ProgramObj,Index,Name) ->
NameLen = length(Name),
@@ -13406,14 +6182,14 @@ bindAttribLocationARB(ProgramObj,Index,Name) ->
%% @doc glGetActiveAttribARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveAttribARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getActiveAttribARB(ProgramObj, Index, MaxLength) -> {Size :: integer(),Type :: enum(),Name :: string()} when ProgramObj :: integer(),Index :: integer(),MaxLength :: integer().
getActiveAttribARB(ProgramObj,Index,MaxLength) ->
call(5648, <<ProgramObj:?GLhandleARB,Index:?GLuint,MaxLength:?GLsizei>>).
%% @doc glGetAttribLocationARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetAttribLocationARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getAttribLocationARB(ProgramObj, Name) -> integer() when ProgramObj :: integer(),Name :: string().
getAttribLocationARB(ProgramObj,Name) ->
NameLen = length(Name),
@@ -13429,7 +6205,7 @@ getAttribLocationARB(ProgramObj,Name) ->
%% , then the name is not a renderbuffer object and ``gl:isRenderbuffer'' returns `?GL_FALSE'
%% .
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsRenderbuffer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsRenderbuffer.xhtml">external</a> documentation.
-spec isRenderbuffer(Renderbuffer) -> 0|1 when Renderbuffer :: integer().
isRenderbuffer(Renderbuffer) ->
call(5650, <<Renderbuffer:?GLuint>>).
@@ -13442,7 +6218,7 @@ isRenderbuffer(Renderbuffer) ->
%% call to {@link gl:genRenderbuffers/1} , or zero to break the existing binding of a renderbuffer
%% object to `Target' .
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindRenderbuffer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindRenderbuffer.xhtml">external</a> documentation.
-spec bindRenderbuffer(Target, Renderbuffer) -> 'ok' when Target :: enum(),Renderbuffer :: integer().
bindRenderbuffer(Target,Renderbuffer) ->
cast(5651, <<Target:?GLenum,Renderbuffer:?GLuint>>).
@@ -13457,14 +6233,7 @@ bindRenderbuffer(Target,Renderbuffer) ->
%% it is as though {@link gl:bindRenderbuffer/2} had been executed with a `Target' of `?GL_RENDERBUFFER'
%% and a `Name' of zero.
%%
-%% If a renderbuffer object is attached to one or more attachment points in the currently
-%% bound framebuffer, then it as if {@link gl:framebufferRenderbuffer/4} had been called,
-%% with a `Renderbuffer' of zero for each attachment point to which this image was attached
-%% in the currently bound framebuffer. In other words, this renderbuffer object is first
-%% detached from all attachment ponits in the currently bound framebuffer. Note that the
-%% renderbuffer image is specifically `not' detached from any non-bound framebuffers.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteRenderbuffers.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteRenderbuffers.xhtml">external</a> documentation.
-spec deleteRenderbuffers(Renderbuffers) -> 'ok' when Renderbuffers :: [integer()].
deleteRenderbuffers(Renderbuffers) ->
RenderbuffersLen = length(Renderbuffers),
@@ -13478,13 +6247,7 @@ deleteRenderbuffers(Renderbuffers) ->
%% is guaranteed that none of the returned names was in use immediately before the call to ``gl:genRenderbuffers''
%% .
%%
-%% Renderbuffer object names returned by a call to ``gl:genRenderbuffers'' are not returned
-%% by subsequent calls, unless they are first deleted with {@link gl:deleteRenderbuffers/1} .
-%%
-%% The names returned in `Renderbuffers' are marked as used, for the purposes of ``gl:genRenderbuffers''
-%% only, but they acquire state and type only when they are first bound.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenRenderbuffers.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenRenderbuffers.xhtml">external</a> documentation.
-spec genRenderbuffers(N) -> [integer()] when N :: integer().
genRenderbuffers(N) ->
call(5653, <<N:?GLsizei>>).
@@ -13494,18 +6257,7 @@ genRenderbuffers(N) ->
%% ``gl:renderbufferStorage'' is equivalent to calling {@link gl:renderbufferStorageMultisample/5}
%% with the `Samples' set to zero.
%%
-%% The target of the operation, specified by `Target' must be `?GL_RENDERBUFFER'.
-%% `Internalformat' specifies the internal format to be used for the renderbuffer object's
-%% storage and must be a color-renderable, depth-renderable, or stencil-renderable format. `Width'
-%% and `Height' are the dimensions, in pixels, of the renderbuffer. Both `Width'
-%% and `Height' must be less than or equal to the value of `?GL_MAX_RENDERBUFFER_SIZE'
-%% .
-%%
-%% Upon success, ``gl:renderbufferStorage'' deletes any existing data store for the renderbuffer
-%% image and the contents of the data store after calling ``gl:renderbufferStorage'' are
-%% undefined.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRenderbufferStorage.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glRenderbufferStorage.xhtml">external</a> documentation.
-spec renderbufferStorage(Target, Internalformat, Width, Height) -> 'ok' when Target :: enum(),Internalformat :: enum(),Width :: integer(),Height :: integer().
renderbufferStorage(Target,Internalformat,Width,Height) ->
cast(5654, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei>>).
@@ -13520,20 +6272,7 @@ renderbufferStorage(Target,Internalformat,Width,Height) ->
%% , `?GL_RENDERBUFFER_DEPTH_SIZE', `?GL_RENDERBUFFER_DEPTH_SIZE', `?GL_RENDERBUFFER_STENCIL_SIZE'
%% , or `?GL_RENDERBUFFER_SAMPLES'.
%%
-%% Upon a successful return from ``gl:getRenderbufferParameteriv'', if `Pname' is `?GL_RENDERBUFFER_WIDTH'
-%% , `?GL_RENDERBUFFER_HEIGHT', `?GL_RENDERBUFFER_INTERNAL_FORMAT', or `?GL_RENDERBUFFER_SAMPLES'
-%% , then `Params' will contain the width in pixels, the height in pixels, the internal
-%% format, or the number of samples, respectively, of the image of the renderbuffer currently
-%% bound to `Target' .
-%%
-%% If `Pname' is `?GL_RENDERBUFFER_RED_SIZE', `?GL_RENDERBUFFER_GREEN_SIZE',
-%% `?GL_RENDERBUFFER_BLUE_SIZE', `?GL_RENDERBUFFER_ALPHA_SIZE', `?GL_RENDERBUFFER_DEPTH_SIZE'
-%% , or `?GL_RENDERBUFFER_STENCIL_SIZE', then `Params' will contain the actual
-%% resolutions (not the resolutions specified when the image array was defined) for the red,
-%% green, blue, alpha depth, or stencil components, respectively, of the image of the renderbuffer
-%% currently bound to `Target' .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetRenderbufferParameter.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetRenderbufferParameter.xhtml">external</a> documentation.
-spec getRenderbufferParameteriv(Target, Pname) -> integer() when Target :: enum(),Pname :: enum().
getRenderbufferParameteriv(Target,Pname) ->
call(5655, <<Target:?GLenum,Pname:?GLenum>>).
@@ -13547,7 +6286,7 @@ getRenderbufferParameteriv(Target,Pname) ->
%% , by that has not yet been bound through a call to {@link gl:bindFramebuffer/2} , then the
%% name is not a framebuffer object and ``gl:isFramebuffer'' returns `?GL_FALSE'.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsFramebuffer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsFramebuffer.xhtml">external</a> documentation.
-spec isFramebuffer(Framebuffer) -> 0|1 when Framebuffer :: integer().
isFramebuffer(Framebuffer) ->
call(5656, <<Framebuffer:?GLuint>>).
@@ -13565,7 +6304,7 @@ isFramebuffer(Framebuffer) ->
%% a call to {@link gl:genFramebuffers/1} , or zero to break the existing binding of a framebuffer
%% object to `Target' .
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindFramebuffer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindFramebuffer.xhtml">external</a> documentation.
-spec bindFramebuffer(Target, Framebuffer) -> 'ok' when Target :: enum(),Framebuffer :: integer().
bindFramebuffer(Target,Framebuffer) ->
cast(5657, <<Target:?GLenum,Framebuffer:?GLuint>>).
@@ -13580,7 +6319,7 @@ bindFramebuffer(Target,Framebuffer) ->
%% or `?GL_READ_FRAMEBUFFER' is deleted, it is as though {@link gl:bindFramebuffer/2}
%% had been executed with the corresponding `Target' and `Framebuffer' zero.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteFramebuffers.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteFramebuffers.xhtml">external</a> documentation.
-spec deleteFramebuffers(Framebuffers) -> 'ok' when Framebuffers :: [integer()].
deleteFramebuffers(Framebuffers) ->
FramebuffersLen = length(Framebuffers),
@@ -13594,13 +6333,7 @@ deleteFramebuffers(Framebuffers) ->
%% that none of the returned names was in use immediately before the call to ``gl:genFramebuffers''
%% .
%%
-%% Framebuffer object names returned by a call to ``gl:genFramebuffers'' are not returned
-%% by subsequent calls, unless they are first deleted with {@link gl:deleteFramebuffers/1} .
-%%
-%% The names returned in `Ids' are marked as used, for the purposes of ``gl:genFramebuffers''
-%% only, but they acquire state and type only when they are first bound.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenFramebuffers.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenFramebuffers.xhtml">external</a> documentation.
-spec genFramebuffers(N) -> [integer()] when N :: integer().
genFramebuffers(N) ->
call(5659, <<N:?GLsizei>>).
@@ -13612,46 +6345,7 @@ genFramebuffers(N) ->
%% or `?GL_FRAMEBUFFER'. `?GL_FRAMEBUFFER' is equivalent to `?GL_DRAW_FRAMEBUFFER'
%% .
%%
-%% The return value is `?GL_FRAMEBUFFER_COMPLETE' if the framebuffer bound to `Target'
-%% is complete. Otherwise, the return value is determined as follows:
-%%
-%% `?GL_FRAMEBUFFER_UNDEFINED' is returned if `Target' is the default framebuffer,
-%% but the default framebuffer does not exist.
-%%
-%% `?GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT' is returned if any of the framebuffer attachment
-%% points are framebuffer incomplete.
-%%
-%% `?GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT' is returned if the framebuffer does
-%% not have at least one image attached to it.
-%%
-%% `?GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER' is returned if the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE'
-%% is `?GL_NONE' for any color attachment point(s) named by `?GL_DRAWBUFFERi'.
-%%
-%% `?GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER' is returned if `?GL_READ_BUFFER' is
-%% not `?GL_NONE' and the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' is `?GL_NONE'
-%% for the color attachment point named by `?GL_READ_BUFFER'.
-%%
-%% `?GL_FRAMEBUFFER_UNSUPPORTED' is returned if the combination of internal formats
-%% of the attached images violates an implementation-dependent set of restrictions.
-%%
-%% `?GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE' is returned if the value of `?GL_RENDERBUFFER_SAMPLES'
-%% is not the same for all attached renderbuffers; if the value of `?GL_TEXTURE_SAMPLES'
-%% is the not same for all attached textures; or, if the attached images are a mix of renderbuffers
-%% and textures, the value of `?GL_RENDERBUFFER_SAMPLES' does not match the value of `?GL_TEXTURE_SAMPLES'
-%% .
-%%
-%% `?GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE' is also returned if the value of `?GL_TEXTURE_FIXED_SAMPLE_LOCATIONS'
-%% is not the same for all attached textures; or, if the attached images are a mix of renderbuffers
-%% and textures, the value of `?GL_TEXTURE_FIXED_SAMPLE_LOCATIONS' is not `?GL_TRUE'
-%% for all attached textures.
-%%
-%% `?GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS' is returned if any framebuffer attachment
-%% is layered, and any populated attachment is not layered, or if all populated color attachments
-%% are not from textures of the same target.
-%%
-%% Additionally, if an error occurs, zero is returned.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCheckFramebufferStatus.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCheckFramebufferStatus.xhtml">external</a> documentation.
-spec checkFramebufferStatus(Target) -> enum() when Target :: enum().
checkFramebufferStatus(Target) ->
call(5660, <<Target:?GLenum>>).
@@ -13684,24 +6378,7 @@ framebufferTexture3D(Target,Attachment,Textarget,Texture,Level,Zoffset) ->
%% buffer identified by `Attachment' of the framebuffer currently bound to `Target' .
%%
%%
-%% The value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' for the specified attachment
-%% point is set to `?GL_RENDERBUFFER' and the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME'
-%% is set to `Renderbuffer' . All other state values of the attachment point specified
-%% by `Attachment' are set to their default values. No change is made to the state of
-%% the renderbuuffer object and any previous attachment to the `Attachment' logical
-%% buffer of the framebuffer `Target' is broken.
-%%
-%% Calling ``gl:framebufferRenderbuffer'' with the renderbuffer name zero will detach
-%% the image, if any, identified by `Attachment' , in the framebuffer currently bound
-%% to `Target' . All state values of the attachment point specified by attachment in
-%% the object bound to target are set to their default values.
-%%
-%% Setting `Attachment' to the value `?GL_DEPTH_STENCIL_ATTACHMENT' is a special
-%% case causing both the depth and stencil attachments of the framebuffer object to be set
-%% to `Renderbuffer' , which should have the base internal format `?GL_DEPTH_STENCIL'
-%% .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFramebufferRenderbuffer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glFramebufferRenderbuffer.xhtml">external</a> documentation.
-spec framebufferRenderbuffer(Target, Attachment, Renderbuffertarget, Renderbuffer) -> 'ok' when Target :: enum(),Attachment :: enum(),Renderbuffertarget :: enum(),Renderbuffer :: integer().
framebufferRenderbuffer(Target,Attachment,Renderbuffertarget,Renderbuffer) ->
cast(5664, <<Target:?GLenum,Attachment:?GLenum,Renderbuffertarget:?GLenum,Renderbuffer:?GLuint>>).
@@ -13713,91 +6390,7 @@ framebufferRenderbuffer(Target,Attachment,Renderbuffertarget,Renderbuffer) ->
%% be `?GL_DRAW_FRAMEBUFFER', `?GL_READ_FRAMEBUFFER' or `?GL_FRAMEBUFFER'. `?GL_FRAMEBUFFER'
%% is equivalent to `?GL_DRAW_FRAMEBUFFER'.
%%
-%% If the default framebuffer is bound to `Target' then `Attachment' must be one
-%% of `?GL_FRONT_LEFT', `?GL_FRONT_RIGHT', `?GL_BACK_LEFT', or `?GL_BACK_RIGHT'
-%% , identifying a color buffer, `?GL_DEPTH', identifying the depth buffer, or `?GL_STENCIL'
-%% , identifying the stencil buffer.
-%%
-%% If a framebuffer object is bound, then `Attachment' must be one of `?GL_COLOR_ATTACHMENT'
-%% `i', `?GL_DEPTH_ATTACHMENT', `?GL_STENCIL_ATTACHMENT', or `?GL_DEPTH_STENCIL_ATTACHMENT'
-%% . `i' in `?GL_COLOR_ATTACHMENT'`i' must be in the range zero to the value
-%% of `?GL_MAX_COLOR_ATTACHMENTS' - 1.
-%%
-%% If `Attachment' is `?GL_DEPTH_STENCIL_ATTACHMENT' and different objects are
-%% bound to the depth and stencil attachment points of `Target' the query will fail.
-%% If the same object is bound to both attachment points, information about that object will
-%% be returned.
-%%
-%% Upon successful return from ``gl:getFramebufferAttachmentParameteriv'', if `Pname'
-%% is `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE', then `Params' will contain one of `?GL_NONE'
-%% , `?GL_FRAMEBUFFER_DEFAULT', `?GL_TEXTURE', or `?GL_RENDERBUFFER', identifying
-%% the type of object which contains the attached image. Other values accepted for `Pname'
-%% depend on the type of object, as described below.
-%%
-%% If the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' is `?GL_NONE', no
-%% framebuffer is bound to `Target' . In this case querying `Pname' `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME'
-%% will return zero, and all other queries will generate an error.
-%%
-%% If the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' is not `?GL_NONE',
-%% these queries apply to all other framebuffer types:
-%%
-%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE', `?GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE'
-%% , `?GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE', `?GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE'
-%% , `?GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE', or `?GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE'
-%% , then `Params' will contain the number of bits in the corresponding red, green,
-%% blue, alpha, depth, or stencil component of the specified attachment. Zero is returned
-%% if the requested component is not present in `Attachment' .
-%%
-%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE', `Params' will
-%% contain the format of components of the specified attachment, one of `?GL_FLOAT', `GL_INT'
-%% , `GL_UNSIGNED_INT' , `GL_SIGNED_NORMALIZED' , or `GL_UNSIGNED_NORMALIZED'
-%% for floating-point, signed integer, unsigned integer, signed normalized fixed-point, or
-%% unsigned normalized fixed-point components respectively. Only color buffers may have integer
-%% components.
-%%
-%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING', `Param' will
-%% contain the encoding of components of the specified attachment, one of `?GL_LINEAR'
-%% or `?GL_SRGB' for linear or sRGB-encoded components, respectively. Only color buffer
-%% components may be sRGB-encoded; such components are treated as described in sections 4.1.7
-%% and 4.1.8. For the default framebuffer, color encoding is determined by the implementation.
-%% For framebuffer objects, components are sRGB-encoded if the internal format of a color
-%% attachment is one of the color-renderable SRGB formats.
-%%
-%% If the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' is `?GL_RENDERBUFFER',
-%% then:
-%%
-%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME', `Params' will
-%% contain the name of the renderbuffer object which contains the attached image.
-%%
-%% If the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' is `?GL_TEXTURE',
-%% then:
-%%
-%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME', then `Params'
-%% will contain the name of the texture object which contains the attached image.
-%%
-%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL', then `Params'
-%% will contain the mipmap level of the texture object which contains the attached image.
-%%
-%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE' and the texture
-%% object named `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME' is a cube map texture, then `Params'
-%% will contain the cube map face of the cubemap texture object which contains the attached
-%% image. Otherwise `Params' will contain the value zero.
-%%
-%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER' and the texture object
-%% named `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME' is a layer of a three-dimensional
-%% texture or a one-or two-dimensional array texture, then `Params' will contain the
-%% number of the texture layer which contains the attached image. Otherwise `Params'
-%% will contain the value zero.
-%%
-%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_LAYERED', then `Params' will
-%% contain `?GL_TRUE' if an entire level of a three-dimesional texture, cube map texture,
-%% or one-or two-dimensional array texture is attached. Otherwise, `Params' will contain
-%% `?GL_FALSE'.
-%%
-%% Any combinations of framebuffer type and `Pname' not described above will generate
-%% an error.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetFramebufferAttachmentParameter.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetFramebufferAttachmentParameter.xhtml">external</a> documentation.
-spec getFramebufferAttachmentParameteriv(Target, Attachment, Pname) -> integer() when Target :: enum(),Attachment :: enum(),Pname :: enum().
getFramebufferAttachmentParameteriv(Target,Attachment,Pname) ->
call(5665, <<Target:?GLenum,Attachment:?GLenum,Pname:?GLenum>>).
@@ -13808,16 +6401,7 @@ getFramebufferAttachmentParameteriv(Target,Attachment,Pname) ->
%% the active texture unit. For cube map textures, a `?GL_INVALID_OPERATION' error is
%% generated if the texture attached to `Target' is not cube complete.
%%
-%% Mipmap generation replaces texel array levels level base+1 through q with arrays derived
-%% from the level base array, regardless of their previous contents. All other mimap arrays,
-%% including the level base array, are left unchanged by this computation.
-%%
-%% The internal formats of the derived mipmap arrays all match those of the level base
-%% array. The contents of the derived arrays are computed by repeated, filtered reduction
-%% of the level base array. For one- and two-dimensional texture arrays, each layer is filtered
-%% independently.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenerateMipmap.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenerateMipmap.xhtml">external</a> documentation.
-spec generateMipmap(Target) -> 'ok' when Target :: enum().
generateMipmap(Target) ->
cast(5666, <<Target:?GLenum>>).
@@ -13833,33 +6417,7 @@ generateMipmap(Target) ->
%% by the locations ( `DstX0' ; `DstY0' ) and ( `DstX1' ; `DstY1' ). The lower
%% bounds of the rectangle are inclusive, while the upper bounds are exclusive.
%%
-%% The actual region taken from the read framebuffer is limited to the intersection of the
-%% source buffers being transferred, which may include the color buffer selected by the read
-%% buffer, the depth buffer, and/or the stencil buffer depending on mask. The actual region
-%% written to the draw framebuffer is limited to the intersection of the destination buffers
-%% being written, which may include multiple draw buffers, the depth buffer, and/or the stencil
-%% buffer depending on mask. Whether or not the source or destination regions are altered
-%% due to these limits, the scaling and offset applied to pixels being transferred is performed
-%% as though no such limits were present.
-%%
-%% If the sizes of the source and destination rectangles are not equal, `Filter' specifies
-%% the interpolation method that will be applied to resize the source image , and must be `?GL_NEAREST'
-%% or `?GL_LINEAR'. `?GL_LINEAR' is only a valid interpolation method for the
-%% color buffer. If `Filter' is not `?GL_NEAREST' and `Mask' includes `?GL_DEPTH_BUFFER_BIT'
-%% or `?GL_STENCIL_BUFFER_BIT', no data is transferred and a `?GL_INVALID_OPERATION'
-%% error is generated.
-%%
-%% If `Filter' is `?GL_LINEAR' and the source rectangle would require sampling
-%% outside the bounds of the source framebuffer, values are read as if the `?GL_CLAMP_TO_EDGE'
-%% texture wrapping mode were applied.
-%%
-%% When the color buffer is transferred, values are taken from the read buffer of the read
-%% framebuffer and written to each of the draw buffers of the draw framebuffer.
-%%
-%% If the source and destination rectangles overlap or are the same, and the read and draw
-%% buffers are the same, the result of the operation is undefined.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlitFramebuffer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlitFramebuffer.xhtml">external</a> documentation.
-spec blitFramebuffer(SrcX0, SrcY0, SrcX1, SrcY1, DstX0, DstY0, DstX1, DstY1, Mask, Filter) -> 'ok' when SrcX0 :: integer(),SrcY0 :: integer(),SrcX1 :: integer(),SrcY1 :: integer(),DstX0 :: integer(),DstY0 :: integer(),DstX1 :: integer(),DstY1 :: integer(),Mask :: integer(),Filter :: enum().
blitFramebuffer(SrcX0,SrcY0,SrcX1,SrcY1,DstX0,DstY0,DstX1,DstY1,Mask,Filter) ->
cast(5667, <<SrcX0:?GLint,SrcY0:?GLint,SrcX1:?GLint,SrcY1:?GLint,DstX0:?GLint,DstY0:?GLint,DstX1:?GLint,DstY1:?GLint,Mask:?GLbitfield,Filter:?GLenum>>).
@@ -13869,21 +6427,7 @@ blitFramebuffer(SrcX0,SrcY0,SrcX1,SrcY1,DstX0,DstY0,DstX1,DstY1,Mask,Filter) ->
%% ``gl:renderbufferStorageMultisample'' establishes the data storage, format, dimensions
%% and number of samples of a renderbuffer object's image.
%%
-%% The target of the operation, specified by `Target' must be `?GL_RENDERBUFFER'.
-%% `Internalformat' specifies the internal format to be used for the renderbuffer object's
-%% storage and must be a color-renderable, depth-renderable, or stencil-renderable format. `Width'
-%% and `Height' are the dimensions, in pixels, of the renderbuffer. Both `Width'
-%% and `Height' must be less than or equal to the value of `?GL_MAX_RENDERBUFFER_SIZE'
-%% . `Samples' specifies the number of samples to be used for the renderbuffer object's
-%% image, and must be less than or equal to the value of `?GL_MAX_SAMPLES'. If `Internalformat'
-%% is a signed or unsigned integer format then `Samples' must be less than or equal
-%% to the value of `?GL_MAX_INTEGER_SAMPLES'.
-%%
-%% Upon success, ``gl:renderbufferStorageMultisample'' deletes any existing data store
-%% for the renderbuffer image and the contents of the data store after calling ``gl:renderbufferStorageMultisample''
-%% are undefined.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRenderbufferStorageMultisample.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glRenderbufferStorageMultisample.xhtml">external</a> documentation.
-spec renderbufferStorageMultisample(Target, Samples, Internalformat, Width, Height) -> 'ok' when Target :: enum(),Samples :: integer(),Internalformat :: enum(),Width :: integer(),Height :: integer().
renderbufferStorageMultisample(Target,Samples,Internalformat,Width,Height) ->
cast(5668, <<Target:?GLenum,Samples:?GLsizei,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei>>).
@@ -13909,7 +6453,7 @@ framebufferTextureFaceARB(Target,Attachment,Texture,Level,Face) ->
%% mapped range of the buffer. ``gl:flushMappedBufferRange'' may be called multiple times
%% to indicate distinct subranges of the mapping which require flushing.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFlushMappedBufferRange.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glFlushMappedBufferRange.xhtml">external</a> documentation.
-spec flushMappedBufferRange(Target, Offset, Length) -> 'ok' when Target :: enum(),Offset :: integer(),Length :: integer().
flushMappedBufferRange(Target,Offset,Length) ->
cast(5671, <<Target:?GLenum,0:32,Offset:?GLintptr,Length:?GLsizeiptr>>).
@@ -13920,11 +6464,7 @@ flushMappedBufferRange(Target,Offset,Length) ->
%% is the name of a vertex array object previously returned from a call to {@link gl:genVertexArrays/1}
%% , or zero to break the existing vertex array object binding.
%%
-%% If no vertex array object with name `Array' exists, one is created when `Array'
-%% is first bound. If the bind is successful no change is made to the state of the vertex
-%% array object, and any previous vertex array object binding is broken.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindVertexArray.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindVertexArray.xhtml">external</a> documentation.
-spec bindVertexArray(Array) -> 'ok' when Array :: integer().
bindVertexArray(Array) ->
cast(5672, <<Array:?GLuint>>).
@@ -13937,7 +6477,7 @@ bindVertexArray(Array) ->
%% is deleted, the binding for that object reverts to zero and the default vertex array becomes
%% current. Unused names in `Arrays' are silently ignored, as is the value zero.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteVertexArrays.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteVertexArrays.xhtml">external</a> documentation.
-spec deleteVertexArrays(Arrays) -> 'ok' when Arrays :: [integer()].
deleteVertexArrays(Arrays) ->
ArraysLen = length(Arrays),
@@ -13951,13 +6491,7 @@ deleteVertexArrays(Arrays) ->
%% guaranteed that none of the returned names was in use immediately before the call to ``gl:genVertexArrays''
%% .
%%
-%% Vertex array object names returned by a call to ``gl:genVertexArrays'' are not returned
-%% by subsequent calls, unless they are first deleted with {@link gl:deleteVertexArrays/1} .
-%%
-%% The names returned in `Arrays' are marked as used, for the purposes of ``gl:genVertexArrays''
-%% only, but they acquire state and type only when they are first bound.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenVertexArrays.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenVertexArrays.xhtml">external</a> documentation.
-spec genVertexArrays(N) -> [integer()] when N :: integer().
genVertexArrays(N) ->
call(5674, <<N:?GLsizei>>).
@@ -13971,7 +6505,7 @@ genVertexArrays(N) ->
%% been bound through a call to {@link gl:bindVertexArray/1} , then the name is not a vertex
%% array object and ``gl:isVertexArray'' returns `?GL_FALSE'.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsVertexArray.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsVertexArray.xhtml">external</a> documentation.
-spec isVertexArray(Array) -> 0|1 when Array :: integer().
isVertexArray(Array) ->
call(5675, <<Array:?GLuint>>).
@@ -13981,24 +6515,7 @@ isVertexArray(Array) ->
%% ``gl:getUniformIndices'' retrieves the indices of a number of uniforms within `Program'
%% .
%%
-%% `Program' must be the name of a program object for which the command {@link gl:linkProgram/1}
-%% must have been called in the past, although it is not required that {@link gl:linkProgram/1}
-%% must have succeeded. The link could have failed because the number of active uniforms
-%% exceeded the limit.
-%%
-%% `UniformCount' indicates both the number of elements in the array of names `UniformNames'
-%% and the number of indices that may be written to `UniformIndices' .
-%%
-%% `UniformNames' contains a list of `UniformCount' name strings identifying the
-%% uniform names to be queried for indices. For each name string in `UniformNames' ,
-%% the index assigned to the active uniform of that name will be written to the corresponding
-%% element of `UniformIndices' . If a string in `UniformNames' is not the name of
-%% an active uniform, the special value `?GL_INVALID_INDEX' will be written to the corresponding
-%% element of `UniformIndices' .
-%%
-%% If an error occurs, nothing is written to `UniformIndices' .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformIndices.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetUniformIndices.xhtml">external</a> documentation.
-spec getUniformIndices(Program, UniformNames) -> [integer()] when Program :: integer(),UniformNames :: iolist().
getUniformIndices(Program,UniformNames) ->
UniformNamesTemp = list_to_binary([[Str|[0]] || Str <- UniformNames ]),
@@ -14007,7 +6524,7 @@ getUniformIndices(Program,UniformNames) ->
%% @doc glGetActiveUniforms
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniforms.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getActiveUniformsiv(Program, UniformIndices, Pname) -> [integer()] when Program :: integer(),UniformIndices :: [integer()],Pname :: enum().
getActiveUniformsiv(Program,UniformIndices,Pname) ->
UniformIndicesLen = length(UniformIndices),
@@ -14026,19 +6543,7 @@ getActiveUniformsiv(Program,UniformIndices,Pname) ->
%% is given by the value of `?GL_ACTIVE_UNIFORM_MAX_LENGTH', which can be queried with {@link gl:getProgramiv/2}
%% .
%%
-%% If ``gl:getActiveUniformName'' is not successful, nothing is written to `Length'
-%% or `UniformName' .
-%%
-%% `Program' must be the name of a program for which the command {@link gl:linkProgram/1}
-%% has been issued in the past. It is not necessary for `Program' to have been linked
-%% successfully. The link could have failed because the number of active uniforms exceeded
-%% the limit.
-%%
-%% `UniformIndex' must be an active uniform index of the program `Program' , in
-%% the range zero to `?GL_ACTIVE_UNIFORMS' - 1. The value of `?GL_ACTIVE_UNIFORMS'
-%% can be queried with {@link gl:getProgramiv/2} .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniformName.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveUniformName.xhtml">external</a> documentation.
-spec getActiveUniformName(Program, UniformIndex, BufSize) -> string() when Program :: integer(),UniformIndex :: integer(),BufSize :: integer().
getActiveUniformName(Program,UniformIndex,BufSize) ->
call(5678, <<Program:?GLuint,UniformIndex:?GLuint,BufSize:?GLsizei>>).
@@ -14048,21 +6553,7 @@ getActiveUniformName(Program,UniformIndex,BufSize) ->
%% ``gl:getUniformBlockIndex'' retrieves the index of a uniform block within `Program' .
%%
%%
-%% `Program' must be the name of a program object for which the command {@link gl:linkProgram/1}
-%% must have been called in the past, although it is not required that {@link gl:linkProgram/1}
-%% must have succeeded. The link could have failed because the number of active uniforms
-%% exceeded the limit.
-%%
-%% `UniformBlockName' must contain a nul-terminated string specifying the name of the
-%% uniform block.
-%%
-%% ``gl:getUniformBlockIndex'' returns the uniform block index for the uniform block named
-%% `UniformBlockName' of `Program' . If `UniformBlockName' does not identify
-%% an active uniform block of `Program' , ``gl:getUniformBlockIndex'' returns the special
-%% identifier, `?GL_INVALID_INDEX'. Indices of the active uniform blocks of a program
-%% are assigned in consecutive order, beginning with zero.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformBlockIndex.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetUniformBlockIndex.xhtml">external</a> documentation.
-spec getUniformBlockIndex(Program, UniformBlockName) -> integer() when Program :: integer(),UniformBlockName :: string().
getUniformBlockIndex(Program,UniformBlockName) ->
UniformBlockNameLen = length(UniformBlockName),
@@ -14073,49 +6564,7 @@ getUniformBlockIndex(Program,UniformBlockName) ->
%% ``gl:getActiveUniformBlockiv'' retrieves information about an active uniform block within
%% `Program' .
%%
-%% `Program' must be the name of a program object for which the command {@link gl:linkProgram/1}
-%% must have been called in the past, although it is not required that {@link gl:linkProgram/1}
-%% must have succeeded. The link could have failed because the number of active uniforms
-%% exceeded the limit.
-%%
-%% `UniformBlockIndex' is an active uniform block index of `Program' , and must
-%% be less than the value of `?GL_ACTIVE_UNIFORM_BLOCKS'.
-%%
-%% Upon success, the uniform block parameter(s) specified by `Pname' are returned in `Params'
-%% . If an error occurs, nothing will be written to `Params' .
-%%
-%% If `Pname' is `?GL_UNIFORM_BLOCK_BINDING', then the index of the uniform buffer
-%% binding point last selected by the uniform block specified by `UniformBlockIndex'
-%% for `Program' is returned. If no uniform block has been previously specified, zero
-%% is returned.
-%%
-%% If `Pname' is `?GL_UNIFORM_BLOCK_DATA_SIZE', then the implementation-dependent
-%% minimum total buffer object size, in basic machine units, required to hold all active
-%% uniforms in the uniform block identified by `UniformBlockIndex' is returned. It is
-%% neither guaranteed nor expected that a given implementation will arrange uniform values
-%% as tightly packed in a buffer object. The exception to this is the `std140 uniform block layout'
-%% , which guarantees specific packing behavior and does not require the application to query
-%% for offsets and strides. In this case the minimum size may still be queried, even though
-%% it is determined in advance based only on the uniform block declaration.
-%%
-%% If `Pname' is `?GL_UNIFORM_BLOCK_NAME_LENGTH', then the total length (including
-%% the nul terminator) of the name of the uniform block identified by `UniformBlockIndex'
-%% is returned.
-%%
-%% If `Pname' is `?GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS', then the number of active
-%% uniforms in the uniform block identified by `UniformBlockIndex' is returned.
-%%
-%% If `Pname' is `?GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES', then a list of the
-%% active uniform indices for the uniform block identified by `UniformBlockIndex' is
-%% returned. The number of elements that will be written to `Params' is the value of `?GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS'
-%% for `UniformBlockIndex' .
-%%
-%% If `Pname' is `?GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER', `?GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER'
-%% , or `?GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER', then a boolean value indicating
-%% whether the uniform block identified by `UniformBlockIndex' is referenced by the
-%% vertex, geometry, or fragment programming stages of program, respectively, is returned.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniformBlock.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveUniformBlock.xhtml">external</a> documentation.
-spec getActiveUniformBlockiv(Program, UniformBlockIndex, Pname, Params) -> 'ok' when Program :: integer(),UniformBlockIndex :: integer(),Pname :: enum(),Params :: mem().
getActiveUniformBlockiv(Program,UniformBlockIndex,Pname,Params) ->
send_bin(Params),
@@ -14126,26 +6575,7 @@ getActiveUniformBlockiv(Program,UniformBlockIndex,Pname,Params) ->
%% ``gl:getActiveUniformBlockName'' retrieves the name of the active uniform block at `UniformBlockIndex'
%% within `Program' .
%%
-%% `Program' must be the name of a program object for which the command {@link gl:linkProgram/1}
-%% must have been called in the past, although it is not required that {@link gl:linkProgram/1}
-%% must have succeeded. The link could have failed because the number of active uniforms
-%% exceeded the limit.
-%%
-%% `UniformBlockIndex' is an active uniform block index of `Program' , and must
-%% be less than the value of `?GL_ACTIVE_UNIFORM_BLOCKS'.
-%%
-%% Upon success, the name of the uniform block identified by `UnifomBlockIndex' is
-%% returned into `UniformBlockName' . The name is nul-terminated. The actual number of
-%% characters written into `UniformBlockName' , excluding the nul terminator, is returned
-%% in `Length' . If `Length' is NULL, no length is returned.
-%%
-%% `BufSize' contains the maximum number of characters (including the nul terminator)
-%% that will be written into `UniformBlockName' .
-%%
-%% If an error occurs, nothing will be written to `UniformBlockName' or `Length' .
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniformBlockName.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveUniformBlockName.xhtml">external</a> documentation.
-spec getActiveUniformBlockName(Program, UniformBlockIndex, BufSize) -> string() when Program :: integer(),UniformBlockIndex :: integer(),BufSize :: integer().
getActiveUniformBlockName(Program,UniformBlockIndex,BufSize) ->
call(5681, <<Program:?GLuint,UniformBlockIndex:?GLuint,BufSize:?GLsizei>>).
@@ -14157,15 +6587,7 @@ getActiveUniformBlockName(Program,UniformBlockIndex,BufSize) ->
%% `Program' is the name of a program object for which the command {@link gl:linkProgram/1}
%% has been issued in the past.
%%
-%% If successful, ``gl:uniformBlockBinding'' specifies that `Program' will use the
-%% data store of the buffer object bound to the binding point `UniformBlockBinding'
-%% to extract the values of the uniforms in the uniform block identified by `UniformBlockIndex'
-%% .
-%%
-%% When a program object is linked or re-linked, the uniform buffer object binding point
-%% assigned to each of its active uniform blocks is reset to zero.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformBlockBinding.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUniformBlockBinding.xhtml">external</a> documentation.
-spec uniformBlockBinding(Program, UniformBlockIndex, UniformBlockBinding) -> 'ok' when Program :: integer(),UniformBlockIndex :: integer(),UniformBlockBinding :: integer().
uniformBlockBinding(Program,UniformBlockIndex,UniformBlockBinding) ->
cast(5682, <<Program:?GLuint,UniformBlockIndex:?GLuint,UniformBlockBinding:?GLuint>>).
@@ -14177,21 +6599,7 @@ uniformBlockBinding(Program,UniformBlockIndex,UniformBlockBinding) ->
%% by `Size' is copied from the source, at offset `Readoffset' to the destination
%% at `Writeoffset' , also in basic machine units.
%%
-%% `Readtarget' and `Writetarget' must be `?GL_ARRAY_BUFFER', `?GL_COPY_READ_BUFFER'
-%% , `?GL_COPY_WRITE_BUFFER', `?GL_ELEMENT_ARRAY_BUFFER', `?GL_PIXEL_PACK_BUFFER'
-%% , `?GL_PIXEL_UNPACK_BUFFER', `?GL_TEXTURE_BUFFER', `?GL_TRANSFORM_FEEDBACK_BUFFER'
-%% or `?GL_UNIFORM_BUFFER'. Any of these targets may be used, although the targets `?GL_COPY_READ_BUFFER'
-%% and `?GL_COPY_WRITE_BUFFER' are provided specifically to allow copies between buffers
-%% without disturbing other GL state.
-%%
-%% `Readoffset' , `Writeoffset' and `Size' must all be greater than or equal
-%% to zero. Furthermore, `Readoffset' + `Size' must not exceeed the size of the
-%% buffer object bound to `Readtarget' , and `Readoffset' + `Size' must not
-%% exceeed the size of the buffer bound to `Writetarget' . If the same buffer object
-%% is bound to both `Readtarget' and `Writetarget' , then the ranges specified by `Readoffset'
-%% , `Writeoffset' and `Size' must not overlap.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyBufferSubData.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCopyBufferSubData.xhtml">external</a> documentation.
-spec copyBufferSubData(ReadTarget, WriteTarget, ReadOffset, WriteOffset, Size) -> 'ok' when ReadTarget :: enum(),WriteTarget :: enum(),ReadOffset :: integer(),WriteOffset :: integer(),Size :: integer().
copyBufferSubData(ReadTarget,WriteTarget,ReadOffset,WriteOffset,Size) ->
cast(5683, <<ReadTarget:?GLenum,WriteTarget:?GLenum,ReadOffset:?GLintptr,WriteOffset:?GLintptr,Size:?GLsizeiptr>>).
@@ -14205,7 +6613,7 @@ copyBufferSubData(ReadTarget,WriteTarget,ReadOffset,WriteOffset,Size) ->
%% were upconverted to 32-bit unsigned integers (with wrapping on overflow conditions). The
%% operation is undefined if the sum would be negative.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsBaseVertex.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElementsBaseVertex.xhtml">external</a> documentation.
-spec drawElementsBaseVertex(Mode, Count, Type, Indices, Basevertex) -> 'ok' when Mode :: enum(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(),Basevertex :: integer().
drawElementsBaseVertex(Mode,Count,Type,Indices,Basevertex) when is_integer(Indices) ->
cast(5684, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint,Basevertex:?GLint>>);
@@ -14227,7 +6635,7 @@ drawElementsBaseVertex(Mode,Count,Type,Indices,Basevertex) ->
%% to 32-bit unsigned integers (with wrapping on overflow conditions). The operation is undefined
%% if the sum would be negative.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawRangeElementsBaseVertex.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawRangeElementsBaseVertex.xhtml">external</a> documentation.
-spec drawRangeElementsBaseVertex(Mode, Start, End, Count, Type, Indices, Basevertex) -> 'ok' when Mode :: enum(),Start :: integer(),End :: integer(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(),Basevertex :: integer().
drawRangeElementsBaseVertex(Mode,Start,End,Count,Type,Indices,Basevertex) when is_integer(Indices) ->
cast(5686, <<Mode:?GLenum,Start:?GLuint,End:?GLuint,Count:?GLsizei,Type:?GLenum,Indices:?GLuint,Basevertex:?GLint>>);
@@ -14244,7 +6652,7 @@ drawRangeElementsBaseVertex(Mode,Start,End,Count,Type,Indices,Basevertex) ->
%% if the calculation were upconverted to 32-bit unsigned integers (with wrapping on overflow
%% conditions). The operation is undefined if the sum would be negative.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsInstancedBaseVertex.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElementsInstancedBaseVertex.xhtml">external</a> documentation.
-spec drawElementsInstancedBaseVertex(Mode, Count, Type, Indices, Primcount, Basevertex) -> 'ok' when Mode :: enum(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(),Primcount :: integer(),Basevertex :: integer().
drawElementsInstancedBaseVertex(Mode,Count,Type,Indices,Primcount,Basevertex) when is_integer(Indices) ->
cast(5688, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint,Primcount:?GLsizei,Basevertex:?GLint>>);
@@ -14259,29 +6667,7 @@ drawElementsInstancedBaseVertex(Mode,Count,Type,Indices,Primcount,Basevertex) ->
%% as the `provoking vertex' and ``gl:provokingVertex'' specifies which vertex is
%% to be used as the source of data for flat shaded varyings.
%%
-%% `ProvokeMode' must be either `?GL_FIRST_VERTEX_CONVENTION' or `?GL_LAST_VERTEX_CONVENTION'
-%% , and controls the selection of the vertex whose values are assigned to flatshaded varying
-%% outputs. The interpretation of these values for the supported primitive types is: <table><tbody>
-%% <tr><td>` Primitive Type of Polygon '`i'</td><td>` First Vertex Convention '
-%% </td><td>` Last Vertex Convention '</td></tr><tr><td> point </td><td>`i'</td><td>
-%% `i'</td></tr><tr><td> independent line </td><td> 2`i' - 1 </td><td> 2`i'</td>
-%% </tr><tr><td> line loop </td><td>`i'</td><td>
-%%
-%% `i' + 1, if `i' &lt; `n'
-%%
-%% 1, if `i' = `n'</td></tr><tr><td> line strip </td><td>`i'</td><td>`i'
-%% + 1 </td></tr><tr><td> independent triangle </td><td> 3`i' - 2 </td><td> 3`i'</td>
-%% </tr><tr><td> triangle strip </td><td>`i'</td><td>`i' + 2 </td></tr><tr><td>
-%% triangle fan </td><td>`i' + 1 </td><td>`i' + 2 </td></tr><tr><td> line adjacency
-%% </td><td> 4`i' - 2 </td><td> 4`i' - 1 </td></tr><tr><td> line strip adjacency </td>
-%% <td>`i' + 1 </td><td>`i' + 2 </td></tr><tr><td> triangle adjacency </td><td> 6`i'
-%% - 5 </td><td> 6`i' - 1 </td></tr><tr><td> triangle strip adjacency </td><td> 2`i'
-%% - 1 </td><td> 2`i' + 3 </td></tr></tbody></table>
-%%
-%% If a vertex or geometry shader is active, user-defined varying outputs may be flatshaded
-%% by using the flat qualifier when declaring the output.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProvokingVertex.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glProvokingVertex.xhtml">external</a> documentation.
-spec provokingVertex(Mode) -> 'ok' when Mode :: enum().
provokingVertex(Mode) ->
cast(5690, <<Mode:?GLenum>>).
@@ -14292,20 +6678,7 @@ provokingVertex(Mode) ->
%% command stream and associates it with that sync object, and returns a non-zero name corresponding
%% to the sync object.
%%
-%% When the specified `Condition' of the sync object is satisfied by the fence command,
-%% the sync object is signaled by the GL, causing any {@link gl:waitSync/3} , {@link gl:clientWaitSync/3}
-%% commands blocking in `Sync' to `unblock'. No other state is affected by ``gl:fenceSync''
-%% or by the execution of the associated fence command.
-%%
-%% `Condition' must be `?GL_SYNC_GPU_COMMANDS_COMPLETE'. This condition is satisfied
-%% by completion of the fence command corresponding to the sync object and all preceding
-%% commands in the same command stream. The sync object will not be signaled until all effects
-%% from these commands on GL client and server state and the framebuffer are fully realized.
-%% Note that completion of the fence command occurs once the state of the corresponding sync
-%% object has been changed, but commands waiting on that sync object may not be unblocked
-%% until after the fence command completes.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFenceSync.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glFenceSync.xhtml">external</a> documentation.
-spec fenceSync(Condition, Flags) -> integer() when Condition :: enum(),Flags :: integer().
fenceSync(Condition,Flags) ->
call(5691, <<Condition:?GLenum,Flags:?GLbitfield>>).
@@ -14316,7 +6689,7 @@ fenceSync(Condition,Flags) ->
%% object. If `Sync' is not the name of a sync object, or if an error occurs, ``gl:isSync''
%% returns `?GL_FALSE'. Note that zero is not the name of a sync object.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsSync.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsSync.xhtml">external</a> documentation.
-spec isSync(Sync) -> 0|1 when Sync :: integer().
isSync(Sync) ->
call(5692, <<Sync:?GLsync>>).
@@ -14331,9 +6704,7 @@ isSync(Sync) ->
%% or {@link gl:clientWaitSync/3} command. In either case, after ``gl:deleteSync'' returns,
%% the name `Sync' is invalid and can no longer be used to refer to the sync object.
%%
-%% ``gl:deleteSync'' will silently ignore a `Sync' value of zero.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteSync.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteSync.xhtml">external</a> documentation.
-spec deleteSync(Sync) -> 'ok' when Sync :: integer().
deleteSync(Sync) ->
cast(5693, <<Sync:?GLsync>>).
@@ -14345,21 +6716,7 @@ deleteSync(Sync) ->
%% is called, ``gl:clientWaitSync'' returns immediately, otherwise it will block and wait
%% for up to `Timeout' nanoseconds for `Sync' to become signaled.
%%
-%% The return value is one of four status values:
-%%
-%% `?GL_ALREADY_SIGNALED' indicates that `Sync' was signaled at the time that ``gl:clientWaitSync''
-%% was called.
-%%
-%% `?GL_TIMEOUT_EXPIRED' indicates that at least `Timeout' nanoseconds passed and `Sync'
-%% did not become signaled.
-%%
-%% `?GL_CONDITION_SATISFIED' indicates that `Sync' was signaled before the timeout
-%% expired.
-%%
-%% `?GL_WAIT_FAILED' indicates that an error occurred. Additionally, an OpenGL error
-%% will be generated.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClientWaitSync.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glClientWaitSync.xhtml">external</a> documentation.
-spec clientWaitSync(Sync, Flags, Timeout) -> enum() when Sync :: integer(),Flags :: integer(),Timeout :: integer().
clientWaitSync(Sync,Flags,Timeout) ->
call(5694, <<Sync:?GLsync,Flags:?GLbitfield,0:32,Timeout:?GLuint64>>).
@@ -14373,15 +6730,9 @@ clientWaitSync(Sync,Flags,Timeout) ->
%%
%% `Flags' and `Timeout' are placeholders for anticipated future extensions of
%% sync object capabilities. They must have these reserved values in order that existing
-%% code calling ``gl:waitSync'' operate properly in the presence of such extensions.. ``gl:waitSync''
-%% will always wait no longer than an implementation-dependent timeout. The duration of
-%% this timeout in nanoseconds may be queried by calling {@link gl:getBooleanv/1} with the parameter `?GL_MAX_SERVER_WAIT_TIMEOUT'
-%% . There is currently no way to determine whether ``gl:waitSync'' unblocked because the
-%% timeout expired or because the sync object being waited on was signaled.
-%%
-%% If an error occurs, ``gl:waitSync'' does not cause the GL server to block.
+%% code calling ``gl:waitSync'' operate properly in the presence of such extensions.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWaitSync.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glWaitSync.xhtml">external</a> documentation.
-spec waitSync(Sync, Flags, Timeout) -> 'ok' when Sync :: integer(),Flags :: integer(),Timeout :: integer().
waitSync(Sync,Flags,Timeout) ->
cast(5695, <<Sync:?GLsync,Flags:?GLbitfield,0:32,Timeout:?GLuint64>>).
@@ -14397,32 +6748,7 @@ getInteger64v(Pname) ->
%% ``gl:getSynciv'' retrieves properties of a sync object. `Sync' specifies the name
%% of the sync object whose properties to retrieve.
%%
-%% On success, ``gl:getSynciv'' replaces up to `BufSize' integers in `Values'
-%% with the corresponding property values of the object being queried. The actual number
-%% of integers replaced is returned in the variable whose address is specified in `Length'
-%% . If `Length' is NULL, no length is returned.
-%%
-%% If `Pname' is `?GL_OBJECT_TYPE', a single value representing the specific type
-%% of the sync object is placed in `Values' . The only type supported is `?GL_SYNC_FENCE'
-%% .
-%%
-%% If `Pname' is `?GL_SYNC_STATUS', a single value representing the status of
-%% the sync object (`?GL_SIGNALED' or `?GL_UNSIGNALED') is placed in `Values' .
-%%
-%%
-%% If `Pname' is `?GL_SYNC_CONDITION', a single value representing the condition
-%% of the sync object is placed in `Values' . The only condition supported is `?GL_SYNC_GPU_COMMANDS_COMPLETE'
-%% .
-%%
-%% If `Pname' is `?GL_SYNC_FLAGS', a single value representing the flags with
-%% which the sync object was created is placed in `Values' . No flags are currently supported
-%%
-%%
-%% `Flags' is expected to be used in future extensions to the sync objects..
-%%
-%% If an error occurs, nothing will be written to `Values' or `Length' .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSync.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetSync.xhtml">external</a> documentation.
-spec getSynciv(Sync, Pname, BufSize) -> [integer()] when Sync :: integer(),Pname :: enum(),BufSize :: integer().
getSynciv(Sync,Pname,BufSize) ->
call(5697, <<Sync:?GLsync,Pname:?GLenum,BufSize:?GLsizei>>).
@@ -14432,25 +6758,7 @@ getSynciv(Sync,Pname,BufSize) ->
%% ``gl:texImage2DMultisample'' establishes the data storage, format, dimensions and number
%% of samples of a multisample texture's image.
%%
-%% `Target' must be `?GL_TEXTURE_2D_MULTISAMPLE' or `?GL_PROXY_TEXTURE_2D_MULTISAMPLE'
-%% . `Width' and `Height' are the dimensions in texels of the texture, and must
-%% be in the range zero to `?GL_MAX_TEXTURE_SIZE' - 1. `Samples' specifies the
-%% number of samples in the image and must be in the range zero to `?GL_MAX_SAMPLES'
-%% - 1.
-%%
-%% `Internalformat' must be a color-renderable, depth-renderable, or stencil-renderable
-%% format.
-%%
-%% If `Fixedsamplelocations' is `?GL_TRUE', the image will use identical sample
-%% locations and the same number of samples for all texels in the image, and the sample locations
-%% will not depend on the internal format or size of the image.
-%%
-%% When a multisample texture is accessed in a shader, the access takes one vector of integers
-%% describing which texel to fetch and an integer corresponding to the sample numbers describing
-%% which sample within the texel to fetch. No standard sampling instructions are allowed
-%% on the multisample texture targets.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2DMultisample.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage2DMultisample.xhtml">external</a> documentation.
-spec texImage2DMultisample(Target, Samples, Internalformat, Width, Height, Fixedsamplelocations) -> 'ok' when Target :: enum(),Samples :: integer(),Internalformat :: integer(),Width :: integer(),Height :: integer(),Fixedsamplelocations :: 0|1.
texImage2DMultisample(Target,Samples,Internalformat,Width,Height,Fixedsamplelocations) ->
cast(5698, <<Target:?GLenum,Samples:?GLsizei,Internalformat:?GLint,Width:?GLsizei,Height:?GLsizei,Fixedsamplelocations:?GLboolean>>).
@@ -14460,25 +6768,7 @@ texImage2DMultisample(Target,Samples,Internalformat,Width,Height,Fixedsampleloca
%% ``gl:texImage3DMultisample'' establishes the data storage, format, dimensions and number
%% of samples of a multisample texture's image.
%%
-%% `Target' must be `?GL_TEXTURE_2D_MULTISAMPLE_ARRAY' or `?GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY'
-%% . `Width' and `Height' are the dimensions in texels of the texture, and must
-%% be in the range zero to `?GL_MAX_TEXTURE_SIZE' - 1. `Depth' is the number of
-%% array slices in the array texture's image. `Samples' specifies the number of samples
-%% in the image and must be in the range zero to `?GL_MAX_SAMPLES' - 1.
-%%
-%% `Internalformat' must be a color-renderable, depth-renderable, or stencil-renderable
-%% format.
-%%
-%% If `Fixedsamplelocations' is `?GL_TRUE', the image will use identical sample
-%% locations and the same number of samples for all texels in the image, and the sample locations
-%% will not depend on the internal format or size of the image.
-%%
-%% When a multisample texture is accessed in a shader, the access takes one vector of integers
-%% describing which texel to fetch and an integer corresponding to the sample numbers describing
-%% which sample within the texel to fetch. No standard sampling instructions are allowed
-%% on the multisample texture targets.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage3DMultisample.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage3DMultisample.xhtml">external</a> documentation.
-spec texImage3DMultisample(Target, Samples, Internalformat, Width, Height, Depth, Fixedsamplelocations) -> 'ok' when Target :: enum(),Samples :: integer(),Internalformat :: integer(),Width :: integer(),Height :: integer(),Depth :: integer(),Fixedsamplelocations :: 0|1.
texImage3DMultisample(Target,Samples,Internalformat,Width,Height,Depth,Fixedsamplelocations) ->
cast(5699, <<Target:?GLenum,Samples:?GLsizei,Internalformat:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Fixedsamplelocations:?GLboolean>>).
@@ -14493,10 +6783,7 @@ texImage3DMultisample(Target,Samples,Internalformat,Width,Height,Depth,Fixedsamp
%% space of that sample. (0.5, 0.5) this corresponds to the pixel center. `Index' must
%% be between zero and the value of `?GL_SAMPLES' - 1.
%%
-%% If the multisample mode does not have fixed sample locations, the returned values may
-%% only reflect the locations of samples within some pixels.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMultisample.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetMultisample.xhtml">external</a> documentation.
-spec getMultisamplefv(Pname, Index) -> {float(),float()} when Pname :: enum(),Index :: integer().
getMultisamplefv(Pname,Index) ->
call(5700, <<Pname:?GLenum,Index:?GLuint>>).
@@ -14506,19 +6793,14 @@ getMultisamplefv(Pname,Index) ->
%% ``gl:sampleMaski'' sets one 32-bit sub-word of the multi-word sample mask, `?GL_SAMPLE_MASK_VALUE'
%% .
%%
-%% `MaskIndex' specifies which 32-bit sub-word of the sample mask to update, and `Mask'
-%% specifies the new value to use for that sub-word. `MaskIndex' must be less than
-%% the value of `?GL_MAX_SAMPLE_MASK_WORDS'. Bit `B' of mask word `M' corresponds
-%% to sample 32 x `M' + `B'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSampleMaski.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glSampleMaski.xhtml">external</a> documentation.
-spec sampleMaski(Index, Mask) -> 'ok' when Index :: integer(),Mask :: integer().
sampleMaski(Index,Mask) ->
cast(5701, <<Index:?GLuint,Mask:?GLbitfield>>).
%% @doc glNamedStringARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNamedStringARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec namedStringARB(Type, Name, String) -> 'ok' when Type :: enum(),Name :: string(),String :: string().
namedStringARB(Type,Name,String) ->
NameLen = length(Name),
@@ -14527,7 +6809,7 @@ namedStringARB(Type,Name,String) ->
%% @doc glDeleteNamedStringARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteNamedStringARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec deleteNamedStringARB(Name) -> 'ok' when Name :: string().
deleteNamedStringARB(Name) ->
NameLen = length(Name),
@@ -14535,7 +6817,7 @@ deleteNamedStringARB(Name) ->
%% @doc glCompileShaderIncludeARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompileShaderIncludeARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec compileShaderIncludeARB(Shader, Path) -> 'ok' when Shader :: integer(),Path :: iolist().
compileShaderIncludeARB(Shader,Path) ->
PathTemp = list_to_binary([[Str|[0]] || Str <- Path ]),
@@ -14544,7 +6826,7 @@ compileShaderIncludeARB(Shader,Path) ->
%% @doc glIsNamedStringARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsNamedStringARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec isNamedStringARB(Name) -> 0|1 when Name :: string().
isNamedStringARB(Name) ->
NameLen = length(Name),
@@ -14552,7 +6834,7 @@ isNamedStringARB(Name) ->
%% @doc glGetNamedStringARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetNamedStringARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getNamedStringARB(Name, BufSize) -> string() when Name :: string(),BufSize :: integer().
getNamedStringARB(Name,BufSize) ->
NameLen = length(Name),
@@ -14560,7 +6842,7 @@ getNamedStringARB(Name,BufSize) ->
%% @doc glGetNamedStringARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetNamedStringARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getNamedStringivARB(Name, Pname) -> integer() when Name :: string(),Pname :: enum().
getNamedStringivARB(Name,Pname) ->
NameLen = length(Name),
@@ -14568,7 +6850,7 @@ getNamedStringivARB(Name,Pname) ->
%% @doc glBindFragDataLocationIndexe
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindFragDataLocationIndexe.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec bindFragDataLocationIndexed(Program, ColorNumber, Index, Name) -> 'ok' when Program :: integer(),ColorNumber :: integer(),Index :: integer(),Name :: string().
bindFragDataLocationIndexed(Program,ColorNumber,Index,Name) ->
NameLen = length(Name),
@@ -14580,7 +6862,7 @@ bindFragDataLocationIndexed(Program,ColorNumber,Index,Name) ->
%% was bound when the program object `Program' was last linked. If `Name' is not
%% a varying out variable of `Program' , or if an error occurs, -1 will be returned.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetFragDataIndex.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetFragDataIndex.xhtml">external</a> documentation.
-spec getFragDataIndex(Program, Name) -> integer() when Program :: integer(),Name :: string().
getFragDataIndex(Program,Name) ->
NameLen = length(Name),
@@ -14593,13 +6875,7 @@ getFragDataIndex(Program,Name) ->
%% that none of the returned names was in use immediately before the call to ``gl:genSamplers''
%% .
%%
-%% Sampler object names returned by a call to ``gl:genSamplers'' are not returned by subsequent
-%% calls, unless they are first deleted with {@link gl:deleteSamplers/1} .
-%%
-%% The names returned in `Samplers' are marked as used, for the purposes of ``gl:genSamplers''
-%% only, but they acquire state and type only when they are first bound.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenSamplers.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenSamplers.xhtml">external</a> documentation.
-spec genSamplers(Count) -> [integer()] when Count :: integer().
genSamplers(Count) ->
call(5710, <<Count:?GLsizei>>).
@@ -14612,7 +6888,7 @@ genSamplers(Count) ->
%% is called with unit set to the unit the sampler is bound to and sampler zero. Unused
%% names in samplers are silently ignored, as is the reserved name zero.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteSamplers.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteSamplers.xhtml">external</a> documentation.
-spec deleteSamplers(Samplers) -> 'ok' when Samplers :: [integer()].
deleteSamplers(Samplers) ->
SamplersLen = length(Samplers),
@@ -14625,9 +6901,7 @@ deleteSamplers(Samplers) ->
%% object. If `Id' is zero, or is a non-zero value that is not currently the name of
%% a sampler object, or if an error occurs, ``gl:isSampler'' returns `?GL_FALSE'.
%%
-%% A name returned by {@link gl:genSamplers/1} , is the name of a sampler object.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsSampler.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsSampler.xhtml">external</a> documentation.
-spec isSampler(Sampler) -> 0|1 when Sampler :: integer().
isSampler(Sampler) ->
call(5712, <<Sampler:?GLuint>>).
@@ -14639,12 +6913,7 @@ isSampler(Sampler) ->
%% . `Unit' must be less than the value of `?GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS'.
%%
%%
-%% When a sampler object is bound to a texture unit, its state supersedes that of the texture
-%% object bound to that texture unit. If the sampler name zero is bound to a texture unit,
-%% the currently bound texture's sampler state becomes active. A single sampler object may
-%% be bound to multiple texture units simultaneously.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindSampler.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindSampler.xhtml">external</a> documentation.
-spec bindSampler(Unit, Sampler) -> 'ok' when Unit :: integer(),Sampler :: integer().
bindSampler(Unit,Sampler) ->
cast(5713, <<Unit:?GLuint,Sampler:?GLuint>>).
@@ -14656,141 +6925,7 @@ bindSampler(Unit,Sampler) ->
%% modified, and must be the name of a sampler object previously returned from a call to {@link gl:genSamplers/1}
%% . The following symbols are accepted in `Pname' :
%%
-%% `?GL_TEXTURE_MIN_FILTER': The texture minifying function is used whenever the pixel
-%% being textured maps to an area greater than one texture element. There are six defined
-%% minifying functions. Two of them use the nearest one or nearest four texture elements
-%% to compute the texture value. The other four use mipmaps.
-%%
-%% A mipmap is an ordered set of arrays representing the same image at progressively lower
-%% resolutions. If the texture has dimensions 2 n×2 m, there are max(n m)+1 mipmaps. The first
-%% mipmap is the original texture, with dimensions 2 n×2 m. Each subsequent mipmap has
-%% dimensions 2(k-1)×2(l-1), where 2 k×2 l are the dimensions of the previous mipmap, until either
-%% k=0 or l=0. At that point, subsequent mipmaps have dimension 1×2(l-1) or 2(k-1)×1 until
-%% the final mipmap, which has dimension 1×1. To define the mipmaps, call {@link gl:texImage1D/8}
-%% , {@link gl:texImage2D/9} , {@link gl:texImage3D/10} , {@link gl:copyTexImage1D/7} , or {@link gl:copyTexImage2D/8}
-%% with the `level' argument indicating the order of the mipmaps. Level 0 is the original
-%% texture; level max(n m) is the final 1×1 mipmap.
-%%
-%% `Params' supplies a function for minifying the texture as one of the following:
-%%
-%% `?GL_NEAREST': Returns the value of the texture element that is nearest (in Manhattan
-%% distance) to the center of the pixel being textured.
-%%
-%% `?GL_LINEAR': Returns the weighted average of the four texture elements that are
-%% closest to the center of the pixel being textured. These can include border texture elements,
-%% depending on the values of `?GL_TEXTURE_WRAP_S' and `?GL_TEXTURE_WRAP_T', and
-%% on the exact mapping.
-%%
-%% `?GL_NEAREST_MIPMAP_NEAREST': Chooses the mipmap that most closely matches the size
-%% of the pixel being textured and uses the `?GL_NEAREST' criterion (the texture element
-%% nearest to the center of the pixel) to produce a texture value.
-%%
-%% `?GL_LINEAR_MIPMAP_NEAREST': Chooses the mipmap that most closely matches the size
-%% of the pixel being textured and uses the `?GL_LINEAR' criterion (a weighted average
-%% of the four texture elements that are closest to the center of the pixel) to produce a
-%% texture value.
-%%
-%% `?GL_NEAREST_MIPMAP_LINEAR': Chooses the two mipmaps that most closely match the
-%% size of the pixel being textured and uses the `?GL_NEAREST' criterion (the texture
-%% element nearest to the center of the pixel) to produce a texture value from each mipmap.
-%% The final texture value is a weighted average of those two values.
-%%
-%% `?GL_LINEAR_MIPMAP_LINEAR': Chooses the two mipmaps that most closely match the
-%% size of the pixel being textured and uses the `?GL_LINEAR' criterion (a weighted
-%% average of the four texture elements that are closest to the center of the pixel) to produce
-%% a texture value from each mipmap. The final texture value is a weighted average of those
-%% two values.
-%%
-%% As more texture elements are sampled in the minification process, fewer aliasing artifacts
-%% will be apparent. While the `?GL_NEAREST' and `?GL_LINEAR' minification functions
-%% can be faster than the other four, they sample only one or four texture elements to determine
-%% the texture value of the pixel being rendered and can produce moire patterns or ragged
-%% transitions. The initial value of `?GL_TEXTURE_MIN_FILTER' is `?GL_NEAREST_MIPMAP_LINEAR'
-%% .
-%%
-%% `?GL_TEXTURE_MAG_FILTER': The texture magnification function is used when the pixel
-%% being textured maps to an area less than or equal to one texture element. It sets the
-%% texture magnification function to either `?GL_NEAREST' or `?GL_LINEAR' (see
-%% below). `?GL_NEAREST' is generally faster than `?GL_LINEAR', but it can produce
-%% textured images with sharper edges because the transition between texture elements is
-%% not as smooth. The initial value of `?GL_TEXTURE_MAG_FILTER' is `?GL_LINEAR'.
-%%
-%% `?GL_NEAREST': Returns the value of the texture element that is nearest (in Manhattan
-%% distance) to the center of the pixel being textured.
-%%
-%% `?GL_LINEAR': Returns the weighted average of the four texture elements that are
-%% closest to the center of the pixel being textured. These can include border texture elements,
-%% depending on the values of `?GL_TEXTURE_WRAP_S' and `?GL_TEXTURE_WRAP_T', and
-%% on the exact mapping.
-%%
-%%
-%%
-%% `?GL_TEXTURE_MIN_LOD': Sets the minimum level-of-detail parameter. This floating-point
-%% value limits the selection of highest resolution mipmap (lowest mipmap level). The initial
-%% value is -1000.
-%%
-%%
-%%
-%% `?GL_TEXTURE_MAX_LOD': Sets the maximum level-of-detail parameter. This floating-point
-%% value limits the selection of the lowest resolution mipmap (highest mipmap level). The
-%% initial value is 1000.
-%%
-%%
-%%
-%% `?GL_TEXTURE_WRAP_S': Sets the wrap parameter for texture coordinate s to either `?GL_CLAMP_TO_EDGE'
-%% , `?GL_MIRRORED_REPEAT', or `?GL_REPEAT'. `?GL_CLAMP_TO_BORDER' causes
-%% the s coordinate to be clamped to the range [(-1 2/N) 1+(1 2/N)], where N is the size of the texture in
-%% the direction of clamping.`?GL_CLAMP_TO_EDGE' causes s coordinates to be clamped
-%% to the range [(1 2/N) 1-(1 2/N)], where N is the size of the texture in the direction of clamping. `?GL_REPEAT'
-%% causes the integer part of the s coordinate to be ignored; the GL uses only the fractional
-%% part, thereby creating a repeating pattern. `?GL_MIRRORED_REPEAT' causes the s
-%% coordinate to be set to the fractional part of the texture coordinate if the integer part
-%% of s is even; if the integer part of s is odd, then the s texture coordinate is
-%% set to 1-frac(s), where frac(s) represents the fractional part of s. Initially, `?GL_TEXTURE_WRAP_S'
-%% is set to `?GL_REPEAT'.
-%%
-%%
-%%
-%% `?GL_TEXTURE_WRAP_T': Sets the wrap parameter for texture coordinate t to either `?GL_CLAMP_TO_EDGE'
-%% , `?GL_MIRRORED_REPEAT', or `?GL_REPEAT'. See the discussion under `?GL_TEXTURE_WRAP_S'
-%% . Initially, `?GL_TEXTURE_WRAP_T' is set to `?GL_REPEAT'.
-%%
-%% `?GL_TEXTURE_WRAP_R': Sets the wrap parameter for texture coordinate r to either `?GL_CLAMP_TO_EDGE'
-%% , `?GL_MIRRORED_REPEAT', or `?GL_REPEAT'. See the discussion under `?GL_TEXTURE_WRAP_S'
-%% . Initially, `?GL_TEXTURE_WRAP_R' is set to `?GL_REPEAT'.
-%%
-%% `?GL_TEXTURE_BORDER_COLOR': The data in `Params' specifies four values that
-%% define the border values that should be used for border texels. If a texel is sampled
-%% from the border of the texture, the values of `?GL_TEXTURE_BORDER_COLOR' are interpreted
-%% as an RGBA color to match the texture's internal format and substituted for the non-existent
-%% texel data. If the texture contains depth components, the first component of `?GL_TEXTURE_BORDER_COLOR'
-%% is interpreted as a depth value. The initial value is (0.0, 0.0, 0.0, 0.0).
-%%
-%% `?GL_TEXTURE_COMPARE_MODE': Specifies the texture comparison mode for currently
-%% bound textures. That is, a texture whose internal format is `?GL_DEPTH_COMPONENT_*';
-%% see {@link gl:texImage2D/9} ) Permissible values are:
-%%
-%% `?GL_COMPARE_REF_TO_TEXTURE': Specifies that the interpolated and clamped r texture
-%% coordinate should be compared to the value in the currently bound texture. See the discussion
-%% of `?GL_TEXTURE_COMPARE_FUNC' for details of how the comparison is evaluated. The
-%% result of the comparison is assigned to the red channel.
-%%
-%% `?GL_NONE': Specifies that the red channel should be assigned the appropriate value
-%% from the currently bound texture.
-%%
-%% `?GL_TEXTURE_COMPARE_FUNC': Specifies the comparison operator used when `?GL_TEXTURE_COMPARE_MODE'
-%% is set to `?GL_COMPARE_REF_TO_TEXTURE'. Permissible values are: <table><tbody><tr><td>
-%% ` Texture Comparison Function '</td><td>` Computed result '</td></tr></tbody><tbody>
-%% <tr><td>`?GL_LEQUAL'</td><td> result={1.0 0.0 r&lt;=(D t) r&gt;(D t))</td></tr><tr><td>`?GL_GEQUAL'</td><td>
-%% result={1.0 0.0 r&gt;=(D t) r&lt;(D t))</td></tr><tr><td>`?GL_LESS'</td><td> result={1.0 0.0 r&lt;(D t) r&gt;=(D t))</td></tr><tr><td>`?GL_GREATER'
-%% </td><td> result={1.0 0.0 r&gt;(D t) r&lt;=(D t))</td></tr><tr><td>`?GL_EQUAL'</td><td> result={1.0 0.0 r=(D t) r&amp;ne;
-%% (D t))</td></tr><tr><td>`?GL_NOTEQUAL'
-%% </td><td> result={1.0 0.0 r&amp;ne;(D t) r=(D t))</td></tr><tr><td>`?GL_ALWAYS'</td><td> result=1.0</td></tr><tr><td>
-%% `?GL_NEVER'</td><td> result=0.0</td></tr></tbody></table> where r is the current
-%% interpolated texture coordinate, and D t is the texture value sampled from the currently
-%% bound texture. result is assigned to R t.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSamplerParameter.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glSamplerParameter.xhtml">external</a> documentation.
-spec samplerParameteri(Sampler, Pname, Param) -> 'ok' when Sampler :: integer(),Pname :: enum(),Param :: integer().
samplerParameteri(Sampler,Pname,Param) ->
cast(5714, <<Sampler:?GLuint,Pname:?GLenum,Param:?GLint>>).
@@ -14827,7 +6962,7 @@ samplerParameterIiv(Sampler,Pname,Param) ->
%% @doc glSamplerParameterI
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSamplerParameterI.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec samplerParameterIuiv(Sampler, Pname, Param) -> 'ok' when Sampler :: integer(),Pname :: enum(),Param :: [integer()].
samplerParameterIuiv(Sampler,Pname,Param) ->
ParamLen = length(Param),
@@ -14842,41 +6977,7 @@ samplerParameterIuiv(Sampler,Pname,Param) ->
%% . `Pname' accepts the same symbols as {@link gl:samplerParameteri/3} , with the same
%% interpretations:
%%
-%% `?GL_TEXTURE_MAG_FILTER': Returns the single-valued texture magnification filter,
-%% a symbolic constant. The initial value is `?GL_LINEAR'.
-%%
-%% `?GL_TEXTURE_MIN_FILTER': Returns the single-valued texture minification filter,
-%% a symbolic constant. The initial value is `?GL_NEAREST_MIPMAP_LINEAR'.
-%%
-%% `?GL_TEXTURE_MIN_LOD': Returns the single-valued texture minimum level-of-detail
-%% value. The initial value is -1000.
-%%
-%% `?GL_TEXTURE_MAX_LOD': Returns the single-valued texture maximum level-of-detail
-%% value. The initial value is 1000.
-%%
-%% `?GL_TEXTURE_WRAP_S': Returns the single-valued wrapping function for texture coordinate
-%% s, a symbolic constant. The initial value is `?GL_REPEAT'.
-%%
-%% `?GL_TEXTURE_WRAP_T': Returns the single-valued wrapping function for texture coordinate
-%% t, a symbolic constant. The initial value is `?GL_REPEAT'.
-%%
-%% `?GL_TEXTURE_WRAP_R': Returns the single-valued wrapping function for texture coordinate
-%% r, a symbolic constant. The initial value is `?GL_REPEAT'.
-%%
-%% `?GL_TEXTURE_BORDER_COLOR': Returns four integer or floating-point numbers that
-%% comprise the RGBA color of the texture border. Floating-point values are returned in the
-%% range [0 1]. Integer values are returned as a linear mapping of the internal floating-point
-%% representation such that 1.0 maps to the most positive representable integer and -1.0
-%% maps to the most negative representable integer. The initial value is (0, 0, 0, 0).
-%%
-%% `?GL_TEXTURE_COMPARE_MODE': Returns a single-valued texture comparison mode, a symbolic
-%% constant. The initial value is `?GL_NONE'. See {@link gl:samplerParameteri/3} .
-%%
-%% `?GL_TEXTURE_COMPARE_FUNC': Returns a single-valued texture comparison function,
-%% a symbolic constant. The initial value is `?GL_LEQUAL'. See {@link gl:samplerParameteri/3}
-%% .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSamplerParameter.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetSamplerParameter.xhtml">external</a> documentation.
-spec getSamplerParameteriv(Sampler, Pname) -> [integer()] when Sampler :: integer(),Pname :: enum().
getSamplerParameteriv(Sampler,Pname) ->
call(5720, <<Sampler:?GLuint,Pname:?GLenum>>).
@@ -14895,7 +6996,7 @@ getSamplerParameterfv(Sampler,Pname) ->
%% @doc glGetSamplerParameterI
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSamplerParameterI.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getSamplerParameterIuiv(Sampler, Pname) -> [integer()] when Sampler :: integer(),Pname :: enum().
getSamplerParameterIuiv(Sampler,Pname) ->
call(5723, <<Sampler:?GLuint,Pname:?GLenum>>).
@@ -14910,21 +7011,21 @@ getSamplerParameterIuiv(Sampler,Pname) ->
%% block where the target is `?GL_TIME_ELAPSED' and it does not affect the result of
%% that query object.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glQueryCounter.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glQueryCounter.xhtml">external</a> documentation.
-spec queryCounter(Id, Target) -> 'ok' when Id :: integer(),Target :: enum().
queryCounter(Id,Target) ->
cast(5724, <<Id:?GLuint,Target:?GLenum>>).
%% @doc glGetQueryObjecti64v
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryObjecti64v.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getQueryObjecti64v(Id, Pname) -> integer() when Id :: integer(),Pname :: enum().
getQueryObjecti64v(Id,Pname) ->
call(5725, <<Id:?GLuint,Pname:?GLenum>>).
%% @doc glGetQueryObjectui64v
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryObjectui64v.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getQueryObjectui64v(Id, Pname) -> integer() when Id :: integer(),Pname :: enum().
getQueryObjectui64v(Id,Pname) ->
call(5726, <<Id:?GLuint,Pname:?GLenum>>).
@@ -14936,25 +7037,7 @@ getQueryObjectui64v(Id,Pname) ->
%% , execept that the parameters to {@link gl:drawArraysInstancedBaseInstance/5} are stored
%% in memory at the address given by `Indirect' .
%%
-%% The parameters addressed by `Indirect' are packed into a structure that takes the
-%% form (in C): typedef struct { uint count; uint primCount; uint first; uint baseInstance;
-%% } DrawArraysIndirectCommand; const DrawArraysIndirectCommand *cmd = (const DrawArraysIndirectCommand
-%% *)indirect; glDrawArraysInstancedBaseInstance(mode, cmd-&gt;first, cmd-&gt;count, cmd-&gt;primCount,
-%% cmd-&gt;baseInstance);
-%%
-%% If a buffer is bound to the `?GL_DRAW_INDIRECT_BUFFER' binding at the time of a
-%% call to ``gl:drawArraysIndirect'', `Indirect' is interpreted as an offset, in basic
-%% machine units, into that buffer and the parameter data is read from the buffer rather
-%% than from client memory.
-%%
-%% In contrast to {@link gl:drawArraysInstancedBaseInstance/5} , the first member of the parameter
-%% structure is unsigned, and out-of-range indices do not generate an error.
-%%
-%% Vertex attributes that are modified by ``gl:drawArraysIndirect'' have an unspecified
-%% value after ``gl:drawArraysIndirect'' returns. Attributes that aren't modified remain
-%% well defined.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawArraysIndirect.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawArraysIndirect.xhtml">external</a> documentation.
-spec drawArraysIndirect(Mode, Indirect) -> 'ok' when Mode :: enum(),Indirect :: offset()|mem().
drawArraysIndirect(Mode,Indirect) when is_integer(Indirect) ->
cast(5727, <<Mode:?GLenum,Indirect:?GLuint>>);
@@ -14969,32 +7052,7 @@ drawArraysIndirect(Mode,Indirect) ->
%% , execpt that the parameters to {@link gl:drawElementsInstancedBaseVertexBaseInstance/7}
%% are stored in memory at the address given by `Indirect' .
%%
-%% The parameters addressed by `Indirect' are packed into a structure that takes the
-%% form (in C): typedef struct { uint count; uint primCount; uint firstIndex; uint baseVertex;
-%% uint baseInstance; } DrawElementsIndirectCommand;
-%%
-%% ``gl:drawElementsIndirect'' is equivalent to: void glDrawElementsIndirect(GLenum mode,
-%% GLenum type, const void * indirect) { const DrawElementsIndirectCommand *cmd = (const
-%% DrawElementsIndirectCommand *)indirect; glDrawElementsInstancedBaseVertexBaseInstance(mode,
-%% cmd-&gt;count, type, cmd-&gt;firstIndex + size-of-type, cmd-&gt;primCount, cmd-&gt;baseVertex,
-%% cmd-&gt;baseInstance); }
-%%
-%% If a buffer is bound to the `?GL_DRAW_INDIRECT_BUFFER' binding at the time of a
-%% call to ``gl:drawElementsIndirect'', `Indirect' is interpreted as an offset, in
-%% basic machine units, into that buffer and the parameter data is read from the buffer rather
-%% than from client memory.
-%%
-%% Note that indices stored in client memory are not supported. If no buffer is bound to
-%% the `?GL_ELEMENT_ARRAY_BUFFER' binding, an error will be generated.
-%%
-%% The results of the operation are undefined if the reservedMustBeZero member of the parameter
-%% structure is non-zero. However, no error is generated in this case.
-%%
-%% Vertex attributes that are modified by ``gl:drawElementsIndirect'' have an unspecified
-%% value after ``gl:drawElementsIndirect'' returns. Attributes that aren't modified remain
-%% well defined.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsIndirect.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElementsIndirect.xhtml">external</a> documentation.
-spec drawElementsIndirect(Mode, Type, Indirect) -> 'ok' when Mode :: enum(),Type :: enum(),Indirect :: offset()|mem().
drawElementsIndirect(Mode,Type,Indirect) when is_integer(Indirect) ->
cast(5729, <<Mode:?GLenum,Type:?GLenum,Indirect:?GLuint>>);
@@ -15142,15 +7200,7 @@ getUniformdv(Program,Location) ->
%% `Name' in the shader stage of type `Shadertype' attached to `Program' ,
%% with behavior otherwise identical to {@link gl:getUniformLocation/2} .
%%
-%% If `Name' is not the name of a subroutine uniform in the shader stage, -1 is returned,
-%% but no error is generated. If `Name' is the name of a subroutine uniform in the shader
-%% stage, a value between zero and the value of `?GL_ACTIVE_SUBROUTINE_LOCATIONS' minus
-%% one will be returned. Subroutine locations are assigned using consecutive integers in
-%% the range from zero to the value of `?GL_ACTIVE_SUBROUTINE_LOCATIONS' minus one for
-%% the shader stage. For active subroutine uniforms declared as arrays, the declared array
-%% elements are assigned consecutive locations.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSubroutineUniformLocation.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetSubroutineUniformLocation.xhtml">external</a> documentation.
-spec getSubroutineUniformLocation(Program, Shadertype, Name) -> integer() when Program :: integer(),Shadertype :: enum(),Name :: string().
getSubroutineUniformLocation(Program,Shadertype,Name) ->
NameLen = length(Name),
@@ -15164,14 +7214,7 @@ getSubroutineUniformLocation(Program,Shadertype,Name) ->
%% shader subroutine index. `Name' contains the null-terminated name of the subroutine
%% uniform whose name to query.
%%
-%% If `Name' is not the name of a subroutine uniform in the shader stage, `?GL_INVALID_INDEX'
-%% is returned, but no error is generated. If `Name' is the name of a subroutine uniform
-%% in the shader stage, a value between zero and the value of `?GL_ACTIVE_SUBROUTINES'
-%% minus one will be returned. Subroutine indices are assigned using consecutive integers
-%% in the range from zero to the value of `?GL_ACTIVE_SUBROUTINES' minus one for the
-%% shader stage.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSubroutineIndex.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetSubroutineIndex.xhtml">external</a> documentation.
-spec getSubroutineIndex(Program, Shadertype, Name) -> integer() when Program :: integer(),Shadertype :: enum(),Name :: string().
getSubroutineIndex(Program,Shadertype,Name) ->
NameLen = length(Name),
@@ -15185,15 +7228,7 @@ getSubroutineIndex(Program,Shadertype,Name) ->
%% `Index' must be between zero and the value of `?GL_ACTIVE_SUBROUTINE_UNIFORMS'
%% minus one for the shader stage.
%%
-%% The uniform name is returned as a null-terminated string in `Name' . The actual number
-%% of characters written into `Name' , excluding the null terminator is returned in `Length'
-%% . If `Length' is `?NULL', no length is returned. The maximum number of characters
-%% that may be written into `Name' , including the null terminator, is specified by `Bufsize'
-%% . The length of the longest subroutine uniform name in `Program' and `Shadertype'
-%% is given by the value of `?GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH', which can be
-%% queried with {@link gl:getProgramStageiv/3} .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveSubroutineUniformName.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveSubroutineUniformName.xhtml">external</a> documentation.
-spec getActiveSubroutineUniformName(Program, Shadertype, Index, Bufsize) -> string() when Program :: integer(),Shadertype :: enum(),Index :: integer(),Bufsize :: integer().
getActiveSubroutineUniformName(Program,Shadertype,Index,Bufsize) ->
call(5751, <<Program:?GLuint,Shadertype:?GLenum,Index:?GLuint,Bufsize:?GLsizei>>).
@@ -15205,13 +7240,7 @@ getActiveSubroutineUniformName(Program,Shadertype,Index,Bufsize) ->
%% shader subroutine uniform within the shader stage given by `Stage' , and must between
%% zero and the value of `?GL_ACTIVE_SUBROUTINES' minus one for the shader stage.
%%
-%% The name of the selected subroutine is returned as a null-terminated string in `Name'
-%% . The actual number of characters written into `Name' , not including the null-terminator,
-%% is is returned in `Length' . If `Length' is `?NULL', no length is returned.
-%% The maximum number of characters that may be written into `Name' , including the null-terminator,
-%% is given in `Bufsize' .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveSubroutineName.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveSubroutineName.xhtml">external</a> documentation.
-spec getActiveSubroutineName(Program, Shadertype, Index, Bufsize) -> string() when Program :: integer(),Shadertype :: enum(),Index :: integer(),Bufsize :: integer().
getActiveSubroutineName(Program,Shadertype,Index,Bufsize) ->
call(5752, <<Program:?GLuint,Shadertype:?GLenum,Index:?GLuint,Bufsize:?GLsizei>>).
@@ -15225,7 +7254,7 @@ getActiveSubroutineName(Program,Shadertype,Index,Bufsize) ->
%% values in `Indices' must be less than the value of `?GL_ACTIVE_SUBROUTINES'
%% for the shader stage.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformSubroutines.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUniformSubroutines.xhtml">external</a> documentation.
-spec uniformSubroutinesuiv(Shadertype, Indices) -> 'ok' when Shadertype :: enum(),Indices :: [integer()].
uniformSubroutinesuiv(Shadertype,Indices) ->
IndicesLen = length(Indices),
@@ -15240,7 +7269,7 @@ uniformSubroutinesuiv(Shadertype,Indices) ->
%% in use at shader stage `Shadertype' . The value of the subroutine uniform is returned
%% in `Values' .
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformSubroutine.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetUniformSubroutine.xhtml">external</a> documentation.
-spec getUniformSubroutineuiv(Shadertype, Location) -> {integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer()} when Shadertype :: enum(),Location :: integer().
getUniformSubroutineuiv(Shadertype,Location) ->
call(5754, <<Shadertype:?GLenum,Location:?GLint>>).
@@ -15253,26 +7282,7 @@ getUniformSubroutineuiv(Shadertype,Location) ->
%% should be queried. The value or values of the parameter to be queried is returned in the
%% variable whose address is given in `Values' .
%%
-%% If `Pname' is `?GL_ACTIVE_SUBROUTINE_UNIFORMS', the number of active subroutine
-%% variables in the stage is returned in `Values' .
-%%
-%% If `Pname' is `?GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS', the number of active
-%% subroutine variable locations in the stage is returned in `Values' .
-%%
-%% If `Pname' is `?GL_ACTIVE_SUBROUTINES', the number of active subroutines in
-%% the stage is returned in `Values' .
-%%
-%% If `Pname' is `?GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH', the length of the
-%% longest subroutine uniform for the stage is returned in `Values' .
-%%
-%% If `Pname' is `?GL_ACTIVE_SUBROUTINE_MAX_LENGTH', the length of the longest
-%% subroutine name for the stage is returned in `Values' . The returned name length includes
-%% space for the null-terminator.
-%%
-%% If there is no shader present of type `Shadertype' , the returned value will be consistent
-%% with a shader containing no subroutines or subroutine uniforms.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramStage.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetProgramStage.xhtml">external</a> documentation.
-spec getProgramStageiv(Program, Shadertype, Pname) -> integer() when Program :: integer(),Shadertype :: enum(),Pname :: enum().
getProgramStageiv(Program,Shadertype,Pname) ->
call(5755, <<Program:?GLuint,Shadertype:?GLenum,Pname:?GLenum>>).
@@ -15286,20 +7296,7 @@ getProgramStageiv(Program,Shadertype,Pname) ->
%% `Values' specifies the address of an array containing the new values for the parameter
%% specified by `Pname' .
%%
-%% When `Pname' is `?GL_PATCH_VERTICES', `Value' specifies the number of
-%% vertices that will be used to make up a single patch primitive. Patch primitives are consumed
-%% by the tessellation control shader (if present) and subsequently used for tessellation.
-%% When primitives are specified using {@link gl:drawArrays/3} or a similar function, each
-%% patch will be made from `Parameter' control points, each represented by a vertex
-%% taken from the enabeld vertex arrays. `Parameter' must be greater than zero, and
-%% less than or equal to the value of `?GL_MAX_PATCH_VERTICES'.
-%%
-%% When `Pname' is `?GL_PATCH_DEFAULT_OUTER_LEVEL' or `?GL_PATCH_DEFAULT_INNER_LEVEL'
-%% , `Values' contains the address of an array contiaining the default outer or inner
-%% tessellation levels, respectively, to be used when no tessellation control shader is present.
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPatchParameter.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPatchParameter.xhtml">external</a> documentation.
-spec patchParameteri(Pname, Value) -> 'ok' when Pname :: enum(),Value :: integer().
patchParameteri(Pname,Value) ->
cast(5756, <<Pname:?GLenum,Value:?GLint>>).
@@ -15319,18 +7316,7 @@ patchParameterfv(Pname,Values) ->
%% . If `Id' has not previously been bound, a new transform feedback object with name `Id'
%% and initialized with with the default transform state vector is created.
%%
-%% In the initial state, a default transform feedback object is bound and treated as a transform
-%% feedback object with a name of zero. If the name zero is subsequently bound, the default
-%% transform feedback object is again bound to the GL state.
-%%
-%% While a transform feedback buffer object is bound, GL operations on the target to which
-%% it is bound affect the bound transform feedback object, and queries of the target to which
-%% a transform feedback object is bound return state from the bound object. When buffer objects
-%% are bound for transform feedback, they are attached to the currently bound transform feedback
-%% object. Buffer objects are used for trans- form feedback only if they are attached to
-%% the currently bound transform feedback object.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindTransformFeedback.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindTransformFeedback.xhtml">external</a> documentation.
-spec bindTransformFeedback(Target, Id) -> 'ok' when Target :: enum(),Id :: integer().
bindTransformFeedback(Target,Id) ->
cast(5758, <<Target:?GLenum,Id:?GLuint>>).
@@ -15343,7 +7329,7 @@ bindTransformFeedback(Target,Id) ->
%% and it has no contents. If an active transform feedback object is deleted, its name immediately
%% becomes unused, but the underlying object is not deleted until it is no longer active.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteTransformFeedbacks.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteTransformFeedbacks.xhtml">external</a> documentation.
-spec deleteTransformFeedbacks(Ids) -> 'ok' when Ids :: [integer()].
deleteTransformFeedbacks(Ids) ->
IdsLen = length(Ids),
@@ -15356,7 +7342,7 @@ deleteTransformFeedbacks(Ids) ->
%% names in `Ids' . These names are marked as used, for the purposes of ``gl:genTransformFeedbacks''
%% only, but they acquire transform feedback state only when they are first bound.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenTransformFeedbacks.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenTransformFeedbacks.xhtml">external</a> documentation.
-spec genTransformFeedbacks(N) -> [integer()] when N :: integer().
genTransformFeedbacks(N) ->
call(5760, <<N:?GLsizei>>).
@@ -15371,7 +7357,7 @@ genTransformFeedbacks(N) ->
%% the name is not a transform feedback object and ``gl:isTransformFeedback'' returns `?GL_FALSE'
%% .
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsTransformFeedback.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsTransformFeedback.xhtml">external</a> documentation.
-spec isTransformFeedback(Id) -> 0|1 when Id :: integer().
isTransformFeedback(Id) ->
call(5761, <<Id:?GLuint>>).
@@ -15384,7 +7370,7 @@ isTransformFeedback(Id) ->
%% to the object results in an error. However, a new transform feedback object may be bound
%% while transform feedback is paused.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPauseTransformFeedback.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPauseTransformFeedback.xhtml">external</a> documentation.
-spec pauseTransformFeedback() -> 'ok'.
pauseTransformFeedback() ->
cast(5762, <<>>).
@@ -15397,7 +7383,7 @@ pauseTransformFeedback() ->
%% to the object results in an error. However, a new transform feedback object may be bound
%% while transform feedback is paused.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glResumeTransformFeedback.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glResumeTransformFeedback.xhtml">external</a> documentation.
-spec resumeTransformFeedback() -> 'ok'.
resumeTransformFeedback() ->
cast(5763, <<>>).
@@ -15411,7 +7397,7 @@ resumeTransformFeedback() ->
%% zero the last time transform feedback was active on the transform feedback object named
%% by `Id' .
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawTransformFeedback.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawTransformFeedback.xhtml">external</a> documentation.
-spec drawTransformFeedback(Mode, Id) -> 'ok' when Mode :: enum(),Id :: integer().
drawTransformFeedback(Mode,Id) ->
cast(5764, <<Mode:?GLenum,Id:?GLuint>>).
@@ -15426,17 +7412,14 @@ drawTransformFeedback(Mode,Id) ->
%% the last time transform feedback was active on the transform feedback object named by `Id'
%% .
%%
-%% Calling {@link gl:drawTransformFeedback/2} is equivalent to calling ``gl:drawTransformFeedbackStream''
-%% with `Stream' set to zero.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawTransformFeedbackStream.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawTransformFeedbackStream.xhtml">external</a> documentation.
-spec drawTransformFeedbackStream(Mode, Id, Stream) -> 'ok' when Mode :: enum(),Id :: integer(),Stream :: integer().
drawTransformFeedbackStream(Mode,Id,Stream) ->
cast(5765, <<Mode:?GLenum,Id:?GLuint,Stream:?GLuint>>).
%% @doc glBeginQueryIndexe
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginQueryIndexe.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec beginQueryIndexed(Target, Index, Id) -> 'ok' when Target :: enum(),Index :: integer(),Id :: integer().
beginQueryIndexed(Target,Index,Id) ->
cast(5766, <<Target:?GLenum,Index:?GLuint,Id:?GLuint>>).
@@ -15450,70 +7433,7 @@ beginQueryIndexed(Target,Index,Id) ->
%% , `?GL_PRIMITIVES_GENERATED', `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN', or `?GL_TIME_ELAPSED'
%% . The behavior of the query object depends on its type and is as follows.
%%
-%% `Index' specifies the index of the query target and must be between a `Target' -specific
-%% maximum.
-%%
-%% If `Target' is `?GL_SAMPLES_PASSED', `Id' must be an unused name, or the
-%% name of an existing occlusion query object. When ``gl:beginQueryIndexed'' is executed,
-%% the query object's samples-passed counter is reset to 0. Subsequent rendering will increment
-%% the counter for every sample that passes the depth test. If the value of `?GL_SAMPLE_BUFFERS'
-%% is 0, then the samples-passed count is incremented by 1 for each fragment. If the value
-%% of `?GL_SAMPLE_BUFFERS' is 1, then the samples-passed count is incremented by the
-%% number of samples whose coverage bit is set. However, implementations, at their discression
-%% may instead increase the samples-passed count by the value of `?GL_SAMPLES' if any
-%% sample in the fragment is covered. When ``gl:endQueryIndexed'' is executed, the samples-passed
-%% counter is assigned to the query object's result value. This value can be queried by calling
-%% {@link gl:getQueryObjectiv/2} with `Pname' `?GL_QUERY_RESULT'. When `Target'
-%% is `?GL_SAMPLES_PASSED', `Index' must be zero.
-%%
-%% If `Target' is `?GL_ANY_SAMPLES_PASSED', `Id' must be an unused name,
-%% or the name of an existing boolean occlusion query object. When ``gl:beginQueryIndexed''
-%% is executed, the query object's samples-passed flag is reset to `?GL_FALSE'. Subsequent
-%% rendering causes the flag to be set to `?GL_TRUE' if any sample passes the depth
-%% test. When ``gl:endQueryIndexed'' is executed, the samples-passed flag is assigned to
-%% the query object's result value. This value can be queried by calling {@link gl:getQueryObjectiv/2}
-%% with `Pname' `?GL_QUERY_RESULT'. When `Target' is `?GL_ANY_SAMPLES_PASSED'
-%% , `Index' must be zero.
-%%
-%% If `Target' is `?GL_PRIMITIVES_GENERATED', `Id' must be an unused name,
-%% or the name of an existing primitive query object previously bound to the `?GL_PRIMITIVES_GENERATED'
-%% query binding. When ``gl:beginQueryIndexed'' is executed, the query object's primitives-generated
-%% counter is reset to 0. Subsequent rendering will increment the counter once for every
-%% vertex that is emitted from the geometry shader to the stream given by `Index' , or
-%% from the vertex shader if `Index' is zero and no geometry shader is present. When ``gl:endQueryIndexed''
-%% is executed, the primitives-generated counter for stream `Index' is assigned to
-%% the query object's result value. This value can be queried by calling {@link gl:getQueryObjectiv/2}
-%% with `Pname' `?GL_QUERY_RESULT'. When `Target' is `?GL_PRIMITIVES_GENERATED'
-%% , `Index' must be less than the value of `?GL_MAX_VERTEX_STREAMS'.
-%%
-%% If `Target' is `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN', `Id' must
-%% be an unused name, or the name of an existing primitive query object previously bound
-%% to the `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN' query binding. When ``gl:beginQueryIndexed''
-%% is executed, the query object's primitives-written counter for the stream specified by `Index'
-%% is reset to 0. Subsequent rendering will increment the counter once for every vertex
-%% that is written into the bound transform feedback buffer(s) for stream `Index' . If
-%% transform feedback mode is not activated between the call to ``gl:beginQueryIndexed''
-%% and ``gl:endQueryIndexed'', the counter will not be incremented. When ``gl:endQueryIndexed''
-%% is executed, the primitives-written counter for stream `Index' is assigned to the
-%% query object's result value. This value can be queried by calling {@link gl:getQueryObjectiv/2}
-%% with `Pname' `?GL_QUERY_RESULT'. When `Target' is `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN'
-%% , `Index' must be less than the value of `?GL_MAX_VERTEX_STREAMS'.
-%%
-%% If `Target' is `?GL_TIME_ELAPSED', `Id' must be an unused name, or the
-%% name of an existing timer query object previously bound to the `?GL_TIME_ELAPSED'
-%% query binding. When ``gl:beginQueryIndexed'' is executed, the query object's time counter
-%% is reset to 0. When ``gl:endQueryIndexed'' is executed, the elapsed server time that
-%% has passed since the call to ``gl:beginQueryIndexed'' is written into the query object's
-%% time counter. This value can be queried by calling {@link gl:getQueryObjectiv/2} with `Pname'
-%% `?GL_QUERY_RESULT'. When `Target' is `?GL_TIME_ELAPSED', `Index' must
-%% be zero.
-%%
-%% Querying the `?GL_QUERY_RESULT' implicitly flushes the GL pipeline until the rendering
-%% delimited by the query object has completed and the result is available. `?GL_QUERY_RESULT_AVAILABLE'
-%% can be queried to determine if the result is immediately available or if the rendering
-%% is not yet complete.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginQueryIndexed.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBeginQueryIndexed.xhtml">external</a> documentation.
-spec endQueryIndexed(Target, Index) -> 'ok' when Target :: enum(),Index :: integer().
endQueryIndexed(Target,Index) ->
cast(5767, <<Target:?GLenum,Index:?GLuint>>).
@@ -15525,13 +7445,7 @@ endQueryIndexed(Target,Index) ->
%% the index of the query object target and must be between zero and a target-specific maxiumum.
%%
%%
-%% `Pname' names a specific query object target parameter. When `Pname' is `?GL_CURRENT_QUERY'
-%% , the name of the currently active query for the specified `Index' of `Target' ,
-%% or zero if no query is active, will be placed in `Params' . If `Pname' is `?GL_QUERY_COUNTER_BITS'
-%% , the implementation-dependent number of bits used to hold the result of queries for `Target'
-%% is returned in `Params' .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryIndexed.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetQueryIndexed.xhtml">external</a> documentation.
-spec getQueryIndexediv(Target, Index, Pname) -> integer() when Target :: enum(),Index :: integer(),Pname :: enum().
getQueryIndexediv(Target,Index,Pname) ->
call(5768, <<Target:?GLenum,Index:?GLuint,Pname:?GLenum>>).
@@ -15543,7 +7457,7 @@ getQueryIndexediv(Target,Index,Pname) ->
%% subsequently be called and the implementation may at that time reallocate resources previously
%% freed by the call to ``gl:releaseShaderCompiler''.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glReleaseShaderCompiler.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glReleaseShaderCompiler.xhtml">external</a> documentation.
-spec releaseShaderCompiler() -> 'ok'.
releaseShaderCompiler() ->
cast(5769, <<>>).
@@ -15555,17 +7469,7 @@ releaseShaderCompiler() ->
%% bytes of binary shader code stored in client memory. `BinaryFormat' specifies the
%% format of the pre-compiled code.
%%
-%% The binary image contained in `Binary' will be decoded according to the extension
-%% specification defining the specified `BinaryFormat' token. OpenGL does not define
-%% any specific binary formats, but it does provide a mechanism to obtain token vaues for
-%% such formats provided by such extensions.
-%%
-%% Depending on the types of the shader objects in `Shaders' , ``gl:shaderBinary''
-%% will individually load binary vertex or fragment shaders, or load an executable binary
-%% that contains an optimized pair of vertex and fragment shaders stored in the same binary.
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShaderBinary.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glShaderBinary.xhtml">external</a> documentation.
-spec shaderBinary(Shaders, Binaryformat, Binary) -> 'ok' when Shaders :: [integer()],Binaryformat :: enum(),Binary :: binary().
shaderBinary(Shaders,Binaryformat,Binary) ->
ShadersLen = length(Shaders),
@@ -15583,17 +7487,7 @@ shaderBinary(Shaders,Binaryformat,Binary) ->
%% `?GL_HIGH_FLOAT', `?GL_LOW_INT', `?GL_MEDIUM_INT', or `?GL_HIGH_INT'.
%%
%%
-%% `Range' points to an array of two integers into which the format's numeric range
-%% will be returned. If min and max are the smallest values representable in the format,
-%% then the values returned are defined to be: `Range' [0] = floor(log2(|min|)) and `Range'
-%% [1] = floor(log2(|max|)).
-%%
-%% `Precision' specifies the address of an integer into which will be written the log2
-%% value of the number of bits of precision of the format. If the smallest representable
-%% value greater than 1 is 1 + `eps', then the integer addressed by `Precision'
-%% will contain floor(-log2(eps)).
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderPrecisionFormat.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetShaderPrecisionFormat.xhtml">external</a> documentation.
-spec getShaderPrecisionFormat(Shadertype, Precisiontype) -> {Range :: {integer(),integer()},Precision :: integer()} when Shadertype :: enum(),Precisiontype :: enum().
getShaderPrecisionFormat(Shadertype,Precisiontype) ->
call(5771, <<Shadertype:?GLenum,Precisiontype:?GLenum>>).
@@ -15606,7 +7500,7 @@ depthRangef(N,F) ->
%% @doc glClearDepthf
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearDepthf.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec clearDepthf(D) -> 'ok' when D :: clamp().
clearDepthf(D) ->
cast(5773, <<D:?GLclampf>>).
@@ -15621,13 +7515,7 @@ clearDepthf(D) ->
%% in the variable whose address is given by `Length' . If `Length' is `?NULL',
%% then no length is returned.
%%
-%% The format of the program binary written into `Binary' is returned in the variable
-%% whose address is given by `BinaryFormat' , and may be implementation dependent. The
-%% binary produced by the GL may subsequently be returned to the GL by calling {@link gl:programBinary/3}
-%% , with `BinaryFormat' and `Length' set to the values returned by ``gl:getProgramBinary''
-%% , and passing the returned binary data in the `Binary' parameter.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramBinary.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetProgramBinary.xhtml">external</a> documentation.
-spec getProgramBinary(Program, BufSize) -> {BinaryFormat :: enum(),Binary :: binary()} when Program :: integer(),BufSize :: integer().
getProgramBinary(Program,BufSize) ->
call(5774, <<Program:?GLuint,BufSize:?GLsizei>>).
@@ -15642,19 +7530,7 @@ getProgramBinary(Program,BufSize) ->
%% are not met, loading the program binary will fail and `Program' 's `?GL_LINK_STATUS'
%% will be set to `?GL_FALSE'.
%%
-%% A program object's program binary is replaced by calls to {@link gl:linkProgram/1} or ``gl:programBinary''
-%% . When linking success or failure is concerned, ``gl:programBinary'' can be considered
-%% to perform an implicit linking operation. {@link gl:linkProgram/1} and ``gl:programBinary''
-%% both set the program object's `?GL_LINK_STATUS' to `?GL_TRUE' or `?GL_FALSE'
-%% .
-%%
-%% A successful call to ``gl:programBinary'' will reset all uniform variables to their
-%% initial values. The initial value is either the value of the variable's initializer as
-%% specified in the original shader source, or zero if no initializer was present. Additionally,
-%% all vertex shader input and fragment shader output assignments that were in effect when
-%% the program was linked before saving are restored with ``gl:programBinary'' is called.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramBinary.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glProgramBinary.xhtml">external</a> documentation.
-spec programBinary(Program, BinaryFormat, Binary) -> 'ok' when Program :: integer(),BinaryFormat :: enum(),Binary :: binary().
programBinary(Program,BinaryFormat,Binary) ->
send_bin(Binary),
@@ -15665,22 +7541,7 @@ programBinary(Program,BinaryFormat,Binary) ->
%% ``gl:programParameter'' specifies a new value for the parameter nameed by `Pname'
%% for the program object `Program' .
%%
-%% If `Pname' is `?GL_PROGRAM_BINARY_RETRIEVABLE_HINT', `Value' should be `?GL_FALSE'
-%% or `?GL_TRUE' to indicate to the implementation the intention of the application
-%% to retrieve the program's binary representation with {@link gl:getProgramBinary/2} . The
-%% implementation may use this information to store information that may be useful for a
-%% future query of the program's binary. It is recommended to set `?GL_PROGRAM_BINARY_RETRIEVABLE_HINT'
-%% for the program to `?GL_TRUE' before calling {@link gl:linkProgram/1} , and using
-%% the program at run-time if the binary is to be retrieved later.
-%%
-%% If `Pname' is `?GL_PROGRAM_SEPARABLE', `Value' must be `?GL_TRUE'
-%% or `?GL_FALSE' and indicates whether `Program' can be bound to individual pipeline
-%% stages via {@link gl:useProgramStages/3} . A program's `?GL_PROGRAM_SEPARABLE' parameter
-%% must be set to `?GL_TRUE'`before' {@link gl:linkProgram/1} is called in order
-%% for it to be usable with a program pipeline object. The initial state of `?GL_PROGRAM_SEPARABLE'
-%% is `?GL_FALSE'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramParameter.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glProgramParameter.xhtml">external</a> documentation.
-spec programParameteri(Program, Pname, Value) -> 'ok' when Program :: integer(),Pname :: enum(),Value :: integer().
programParameteri(Program,Pname,Value) ->
cast(5776, <<Program:?GLuint,Pname:?GLenum,Value:?GLint>>).
@@ -15697,15 +7558,7 @@ programParameteri(Program,Pname,Value) ->
%% special value `?GL_ALL_SHADER_BITS' may be specified to indicate that all executables
%% contained in `Program' should be installed in `Pipeline' .
%%
-%% If `Program' refers to a program object with a valid shader attached for an indicated
-%% shader stage, ``gl:useProgramStages'' installs the executable code for that stage in
-%% the indicated program pipeline object `Pipeline' . If `Program' is zero, or refers
-%% to a program object with no valid shader executable for a given stage, it is as if the
-%% pipeline object has no programmable stage configured for the indicated shader stages. If `Stages'
-%% contains bits other than those listed above, and is not equal to `?GL_ALL_SHADER_BITS'
-%% , an error is generated.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUseProgramStages.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUseProgramStages.xhtml">external</a> documentation.
-spec useProgramStages(Pipeline, Stages, Program) -> 'ok' when Pipeline :: integer(),Stages :: integer(),Program :: integer().
useProgramStages(Pipeline,Stages,Program) ->
cast(5777, <<Pipeline:?GLuint,Stages:?GLbitfield,Program:?GLuint>>).
@@ -15717,14 +7570,14 @@ useProgramStages(Pipeline,Stages,Program) ->
%% the active program pipeline object is the target of calls to {@link gl:uniform1f/2} when
%% no program has been made current through a call to {@link gl:useProgram/1} .
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glActiveShaderProgram.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glActiveShaderProgram.xhtml">external</a> documentation.
-spec activeShaderProgram(Pipeline, Program) -> 'ok' when Pipeline :: integer(),Program :: integer().
activeShaderProgram(Pipeline,Program) ->
cast(5778, <<Pipeline:?GLuint,Program:?GLuint>>).
%% @doc glCreateShaderProgramv
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateShaderProgramv.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec createShaderProgramv(Type, Strings) -> integer() when Type :: enum(),Strings :: iolist().
createShaderProgramv(Type,Strings) ->
StringsTemp = list_to_binary([[Str|[0]] || Str <- Strings ]),
@@ -15738,17 +7591,7 @@ createShaderProgramv(Type,Strings) ->
%% no program pipeline exists with name `Pipeline' then a new pipeline object is created
%% with that name and initialized to the default state vector.
%%
-%% When a program pipeline object is bound using ``gl:bindProgramPipeline'', any previous
-%% binding is broken and is replaced with a binding to the specified pipeline object. If `Pipeline'
-%% is zero, the previous binding is broken and is not replaced, leaving no pipeline object
-%% bound. If no current program object has been established by {@link gl:useProgram/1} , the
-%% program objects used for each stage and for uniform updates are taken from the bound program
-%% pipeline object, if any. If there is a current program object established by {@link gl:useProgram/1}
-%% , the bound program pipeline object has no effect on rendering or uniform updates. When
-%% a bound program pipeline object is used for rendering, individual shader executables are
-%% taken from its program objects.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindProgramPipeline.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindProgramPipeline.xhtml">external</a> documentation.
-spec bindProgramPipeline(Pipeline) -> 'ok' when Pipeline :: integer().
bindProgramPipeline(Pipeline) ->
cast(5780, <<Pipeline:?GLuint>>).
@@ -15762,7 +7605,7 @@ bindProgramPipeline(Pipeline) ->
%% the binding for that object reverts to zero and no program pipeline object becomes current.
%%
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteProgramPipelines.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteProgramPipelines.xhtml">external</a> documentation.
-spec deleteProgramPipelines(Pipelines) -> 'ok' when Pipelines :: [integer()].
deleteProgramPipelines(Pipelines) ->
PipelinesLen = length(Pipelines),
@@ -15775,7 +7618,7 @@ deleteProgramPipelines(Pipelines) ->
%% names in `Pipelines' . These names are marked as used, for the purposes of ``gl:genProgramPipelines''
%% only, but they acquire program pipeline state only when they are first bound.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenProgramPipelines.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenProgramPipelines.xhtml">external</a> documentation.
-spec genProgramPipelines(N) -> [integer()] when N :: integer().
genProgramPipelines(N) ->
call(5782, <<N:?GLsizei>>).
@@ -15790,7 +7633,7 @@ genProgramPipelines(N) ->
%% the name is not a program pipeline object and ``gl:isProgramPipeline'' returns `?GL_FALSE'
%% .
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsProgramPipeline.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsProgramPipeline.xhtml">external</a> documentation.
-spec isProgramPipeline(Pipeline) -> 0|1 when Pipeline :: integer().
isProgramPipeline(Pipeline) ->
call(5783, <<Pipeline:?GLuint>>).
@@ -15802,33 +7645,7 @@ isProgramPipeline(Pipeline) ->
%% retrieve. The value of the parameter is written to the variable whose address is given
%% by `Params' .
%%
-%% If `Pname' is `?GL_ACTIVE_PROGRAM', the name of the active program object of
-%% the program pipeline object is returned in `Params' .
-%%
-%% If `Pname' is `?GL_VERTEX_SHADER', the name of the current program object for
-%% the vertex shader type of the program pipeline object is returned in `Params' .
-%%
-%% If `Pname' is `?GL_TESS_CONTROL_SHADER', the name of the current program object
-%% for the tessellation control shader type of the program pipeline object is returned in `Params'
-%% .
-%%
-%% If `Pname' is `?GL_TESS_EVALUATION_SHADER', the name of the current program
-%% object for the tessellation evaluation shader type of the program pipeline object is returned
-%% in `Params' .
-%%
-%% If `Pname' is `?GL_GEOMETRY_SHADER', the name of the current program object
-%% for the geometry shader type of the program pipeline object is returned in `Params' .
-%%
-%%
-%% If `Pname' is `?GL_FRAGMENT_SHADER', the name of the current program object
-%% for the fragment shader type of the program pipeline object is returned in `Params' .
-%%
-%%
-%% If `Pname' is `?GL_INFO_LOG_LENGTH', the length of the info log, including
-%% the null terminator, is returned in `Params' . If there is no info log, zero is returned.
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramPipeline.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetProgramPipeline.xhtml">external</a> documentation.
-spec getProgramPipelineiv(Pipeline, Pname) -> integer() when Pipeline :: integer(),Pname :: enum().
getProgramPipelineiv(Pipeline,Pname) ->
call(5784, <<Pipeline:?GLuint,Pname:?GLenum>>).
@@ -15840,62 +7657,7 @@ getProgramPipelineiv(Pipeline,Pname) ->
%% which should be a value returned by {@link gl:getUniformLocation/2} . ``gl:programUniform''
%% operates on the program object specified by `Program' .
%%
-%% The commands ``gl:programUniform{1|2|3|4}{f|i|ui}'' are used to change the value of
-%% the uniform variable specified by `Location' using the values passed as arguments.
-%% The number specified in the command should match the number of components in the data
-%% type of the specified uniform variable (e.g., `1' for float, int, unsigned int, bool;
-%% `2' for vec2, ivec2, uvec2, bvec2, etc.). The suffix `f' indicates that floating-point
-%% values are being passed; the suffix `i' indicates that integer values are being passed;
-%% the suffix `ui' indicates that unsigned integer values are being passed, and this
-%% type should also match the data type of the specified uniform variable. The `i' variants
-%% of this function should be used to provide values for uniform variables defined as int, ivec2
-%% , ivec3, ivec4, or arrays of these. The `ui' variants of this function should be
-%% used to provide values for uniform variables defined as unsigned int, uvec2, uvec3, uvec4,
-%% or arrays of these. The `f' variants should be used to provide values for uniform
-%% variables of type float, vec2, vec3, vec4, or arrays of these. Either the `i', `ui'
-%% or `f' variants may be used to provide values for uniform variables of type bool, bvec2
-%% , bvec3, bvec4, or arrays of these. The uniform variable will be set to false if the input
-%% value is 0 or 0.0f, and it will be set to true otherwise.
-%%
-%% All active uniform variables defined in a program object are initialized to 0 when the
-%% program object is linked successfully. They retain the values assigned to them by a call
-%% to ``gl:programUniform'' until the next successful link operation occurs on the program
-%% object, when they are once again initialized to 0.
-%%
-%% The commands ``gl:programUniform{1|2|3|4}{f|i|ui}v'' can be used to modify a single
-%% uniform variable or a uniform variable array. These commands pass a count and a pointer
-%% to the values to be loaded into a uniform variable or a uniform variable array. A count
-%% of 1 should be used if modifying the value of a single uniform variable, and a count of
-%% 1 or greater can be used to modify an entire array or part of an array. When loading `n'
-%% elements starting at an arbitrary position `m' in a uniform variable array, elements
-%% `m' + `n' - 1 in the array will be replaced with the new values. If `M' + `N'
-%% - 1 is larger than the size of the uniform variable array, values for all array elements
-%% beyond the end of the array will be ignored. The number specified in the name of the command
-%% indicates the number of components for each element in `Value' , and it should match
-%% the number of components in the data type of the specified uniform variable (e.g., `1'
-%% for float, int, bool; `2' for vec2, ivec2, bvec2, etc.). The data type specified
-%% in the name of the command must match the data type for the specified uniform variable
-%% as described previously for ``gl:programUniform{1|2|3|4}{f|i|ui}''.
-%%
-%% For uniform variable arrays, each element of the array is considered to be of the type
-%% indicated in the name of the command (e.g., ``gl:programUniform3f'' or ``gl:programUniform3fv''
-%% can be used to load a uniform variable array of type vec3). The number of elements of
-%% the uniform variable array to be modified is specified by `Count'
-%%
-%% The commands ``gl:programUniformMatrix{2|3|4|2x3|3x2|2x4|4x2|3x4|4x3}fv'' are used
-%% to modify a matrix or an array of matrices. The numbers in the command name are interpreted
-%% as the dimensionality of the matrix. The number `2' indicates a 2 × 2 matrix (i.e.,
-%% 4 values), the number `3' indicates a 3 × 3 matrix (i.e., 9 values), and the number `4'
-%% indicates a 4 × 4 matrix (i.e., 16 values). Non-square matrix dimensionality is explicit,
-%% with the first number representing the number of columns and the second number representing
-%% the number of rows. For example, `2x4' indicates a 2 × 4 matrix with 2 columns and
-%% 4 rows (i.e., 8 values). If `Transpose' is `?GL_FALSE', each matrix is assumed
-%% to be supplied in column major order. If `Transpose' is `?GL_TRUE', each matrix
-%% is assumed to be supplied in row major order. The `Count' argument indicates the
-%% number of matrices to be passed. A count of 1 should be used if modifying the value of
-%% a single matrix, and a count greater than 1 can be used to modify an array of matrices.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glProgramUniform.xhtml">external</a> documentation.
-spec programUniform1i(Program, Location, V0) -> 'ok' when Program :: integer(),Location :: integer(),V0 :: integer().
programUniform1i(Program,Location,V0) ->
cast(5785, <<Program:?GLuint,Location:?GLint,V0:?GLint>>).
@@ -16269,15 +8031,7 @@ programUniformMatrix4x3dv(Program,Location,Transpose,Value) ->
%% this as an opportunity to perform any internal shader modifications that may be required
%% to ensure correct operation of the installed shaders given the current GL state.
%%
-%% After a program pipeline has been validated, its validation status is set to `?GL_TRUE'
-%% . The validation status of a program pipeline object may be queried by calling {@link gl:getProgramPipelineiv/2}
-%% with parameter `?GL_VALIDATE_STATUS'.
-%%
-%% If `Pipeline' is a name previously returned from a call to {@link gl:genProgramPipelines/1}
-%% but that has not yet been bound by a call to {@link gl:bindProgramPipeline/1} , a new program
-%% pipeline object is created with name `Pipeline' and the default state vector.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgramPipeline.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glValidateProgramPipeline.xhtml">external</a> documentation.
-spec validateProgramPipeline(Pipeline) -> 'ok' when Pipeline :: integer().
validateProgramPipeline(Pipeline) ->
cast(5835, <<Pipeline:?GLuint>>).
@@ -16291,38 +8045,35 @@ validateProgramPipeline(Pipeline) ->
%% of characters written into `InfoLog' is returned in the integer whose address is
%% given by `Length' . If `Length' is `?NULL', no length is returned.
%%
-%% The actual length of the info log for the program pipeline may be determined by calling {@link gl:getProgramPipelineiv/2}
-%% with `Pname' set to `?GL_INFO_LOG_LENGTH'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramPipelineInfoLog.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetProgramPipelineInfoLog.xhtml">external</a> documentation.
-spec getProgramPipelineInfoLog(Pipeline, BufSize) -> string() when Pipeline :: integer(),BufSize :: integer().
getProgramPipelineInfoLog(Pipeline,BufSize) ->
call(5836, <<Pipeline:?GLuint,BufSize:?GLsizei>>).
%% @doc glVertexAttribL
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribL.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec vertexAttribL1d(Index, X) -> 'ok' when Index :: integer(),X :: float().
vertexAttribL1d(Index,X) ->
cast(5837, <<Index:?GLuint,0:32,X:?GLdouble>>).
%% @doc glVertexAttribL
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribL.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec vertexAttribL2d(Index, X, Y) -> 'ok' when Index :: integer(),X :: float(),Y :: float().
vertexAttribL2d(Index,X,Y) ->
cast(5838, <<Index:?GLuint,0:32,X:?GLdouble,Y:?GLdouble>>).
%% @doc glVertexAttribL
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribL.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec vertexAttribL3d(Index, X, Y, Z) -> 'ok' when Index :: integer(),X :: float(),Y :: float(),Z :: float().
vertexAttribL3d(Index,X,Y,Z) ->
cast(5839, <<Index:?GLuint,0:32,X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>).
%% @doc glVertexAttribL
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribL.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec vertexAttribL4d(Index, X, Y, Z, W) -> 'ok' when Index :: integer(),X :: float(),Y :: float(),Z :: float(),W :: float().
vertexAttribL4d(Index,X,Y,Z,W) ->
cast(5840, <<Index:?GLuint,0:32,X:?GLdouble,Y:?GLdouble,Z:?GLdouble,W:?GLdouble>>).
@@ -16345,7 +8096,7 @@ vertexAttribL4dv(Index,{X,Y,Z,W}) -> vertexAttribL4d(Index,X,Y,Z,W).
%% @doc glVertexAttribLPointer
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribLPointer.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec vertexAttribLPointer(Index, Size, Type, Stride, Pointer) -> 'ok' when Index :: integer(),Size :: integer(),Type :: enum(),Stride :: integer(),Pointer :: offset()|mem().
vertexAttribLPointer(Index,Size,Type,Stride,Pointer) when is_integer(Pointer) ->
cast(5841, <<Index:?GLuint,Size:?GLint,Type:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>);
@@ -16355,14 +8106,14 @@ vertexAttribLPointer(Index,Size,Type,Stride,Pointer) ->
%% @doc glGetVertexAttribL
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttribL.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getVertexAttribLdv(Index, Pname) -> {float(),float(),float(),float()} when Index :: integer(),Pname :: enum().
getVertexAttribLdv(Index,Pname) ->
call(5843, <<Index:?GLuint,Pname:?GLenum>>).
%% @doc glViewportArrayv
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glViewportArrayv.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec viewportArrayv(First, V) -> 'ok' when First :: integer(),V :: [{float(),float(),float(),float()}].
viewportArrayv(First,V) ->
VLen = length(V),
@@ -16383,27 +8134,7 @@ viewportArrayv(First,V) ->
%% coordinates to window coordinates. Let (x nd y nd) be normalized device coordinates. Then the window
%% coordinates (x w y w) are computed as follows:
%%
-%% x w=(x nd+1) (width/2)+x
-%%
-%% y w=(y nd+1) (height/2)+y
-%%
-%% The location of the viewport's bottom left corner, given by ( x, y) is clamped to be
-%% within the implementaiton-dependent viewport bounds range. The viewport bounds range [
-%% min, max] can be determined by calling {@link gl:getBooleanv/1} with argument `?GL_VIEWPORT_BOUNDS_RANGE'
-%% . Viewport width and height are silently clamped to a range that depends on the implementation.
-%% To query this range, call {@link gl:getBooleanv/1} with argument `?GL_MAX_VIEWPORT_DIMS'.
-%%
-%% The precision with which the GL interprets the floating point viewport bounds is implementation-dependent
-%% and may be determined by querying the impementation-defined constant `?GL_VIEWPORT_SUBPIXEL_BITS'
-%% .
-%%
-%% Calling ``gl:viewportIndexedfv'' is equivalent to calling see `glViewportArray'
-%% with `First' set to `Index' , `Count' set to 1 and `V' passsed directly.
-%% ``gl:viewportIndexedf'' is equivalent to: void glViewportIndexedf(GLuint index, GLfloat
-%% x, GLfloat y, GLfloat w, GLfloat h) { const float v[4] = { x, y, w, h }; glViewportArrayv(index,
-%% 1, v); }
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glViewportIndexed.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glViewportIndexed.xhtml">external</a> documentation.
-spec viewportIndexedf(Index, X, Y, W, H) -> 'ok' when Index :: integer(),X :: float(),Y :: float(),W :: float(),H :: float().
viewportIndexedf(Index,X,Y,W,H) ->
cast(5845, <<Index:?GLuint,X:?GLfloat,Y:?GLfloat,W:?GLfloat,H:?GLfloat>>).
@@ -16416,7 +8147,7 @@ viewportIndexedfv(Index,{V1,V2,V3,V4}) ->
%% @doc glScissorArrayv
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScissorArrayv.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec scissorArrayv(First, V) -> 'ok' when First :: integer(),V :: [{integer(),integer(),integer(),integer()}].
scissorArrayv(First,V) ->
VLen = length(V),
@@ -16425,21 +8156,21 @@ scissorArrayv(First,V) ->
%% @doc glScissorIndexe
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScissorIndexe.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec scissorIndexed(Index, Left, Bottom, Width, Height) -> 'ok' when Index :: integer(),Left :: integer(),Bottom :: integer(),Width :: integer(),Height :: integer().
scissorIndexed(Index,Left,Bottom,Width,Height) ->
cast(5848, <<Index:?GLuint,Left:?GLint,Bottom:?GLint,Width:?GLsizei,Height:?GLsizei>>).
%% @doc glScissorIndexe
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScissorIndexe.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec scissorIndexedv(Index, V) -> 'ok' when Index :: integer(),V :: {integer(),integer(),integer(),integer()}.
scissorIndexedv(Index,{V1,V2,V3,V4}) ->
cast(5849, <<Index:?GLuint,V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>>).
%% @doc glDepthRangeArrayv
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthRangeArrayv.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec depthRangeArrayv(First, V) -> 'ok' when First :: integer(),V :: [{clamp(),clamp()}].
depthRangeArrayv(First,V) ->
VLen = length(V),
@@ -16448,7 +8179,7 @@ depthRangeArrayv(First,V) ->
%% @doc glDepthRangeIndexe
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthRangeIndexe.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec depthRangeIndexed(Index, N, F) -> 'ok' when Index :: integer(),N :: clamp(),F :: clamp().
depthRangeIndexed(Index,N,F) ->
cast(5851, <<Index:?GLuint,0:32,N:?GLclampd,F:?GLclampd>>).
@@ -16467,7 +8198,7 @@ getDoublei_v(Target,Index) ->
%% @doc glDebugMessageControlARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDebugMessageControlARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec debugMessageControlARB(Source, Type, Severity, Ids, Enabled) -> 'ok' when Source :: enum(),Type :: enum(),Severity :: enum(),Ids :: [integer()],Enabled :: 0|1.
debugMessageControlARB(Source,Type,Severity,Ids,Enabled) ->
IdsLen = length(Ids),
@@ -16476,7 +8207,7 @@ debugMessageControlARB(Source,Type,Severity,Ids,Enabled) ->
%% @doc glDebugMessageInsertARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDebugMessageInsertARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec debugMessageInsertARB(Source, Type, Id, Severity, Buf) -> 'ok' when Source :: enum(),Type :: enum(),Id :: integer(),Severity :: enum(),Buf :: string().
debugMessageInsertARB(Source,Type,Id,Severity,Buf) ->
BufLen = length(Buf),
@@ -16484,14 +8215,14 @@ debugMessageInsertARB(Source,Type,Id,Severity,Buf) ->
%% @doc glGetDebugMessageLogARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetDebugMessageLogARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getDebugMessageLogARB(Count, Bufsize) -> {integer(),Sources :: [enum()],Types :: [enum()],Ids :: [integer()],Severities :: [enum()],MessageLog :: [string()]} when Count :: integer(),Bufsize :: integer().
getDebugMessageLogARB(Count,Bufsize) ->
call(5856, <<Count:?GLuint,Bufsize:?GLsizei>>).
%% @doc glGetGraphicsResetStatusARB
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetGraphicsResetStatusARB.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getGraphicsResetStatusARB() -> enum().
getGraphicsResetStatusARB() ->
call(5857, <<>>).
@@ -16504,17 +8235,7 @@ getGraphicsResetStatusARB() ->
%% is an internal 32-bit integer counter that may be read by a vertex shader as `?gl_InstanceID'
%% .
%%
-%% ``gl:drawArraysInstancedBaseInstance'' has the same effect as: if ( mode or count is
-%% invalid ) generate appropriate error else { for (int i = 0; i &lt; primcount ; i++) {
-%% instanceID = i; glDrawArrays(mode, first, count); } instanceID = 0; }
-%%
-%% Specific vertex attributes may be classified as `instanced' through the use of {@link gl:vertexAttribDivisor/2}
-%% . Instanced vertex attributes supply per-instance vertex data to the vertex shader. The
-%% index of the vertex fetched from the enabled instanced vertex attribute arrays is calculated
-%% as: |gl_ InstanceID/divisor|&amp;plus; baseInstance. Note that `Baseinstance' does not affect the shader-visible
-%% value of `?gl_InstanceID'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawArraysInstancedBaseInstance.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawArraysInstancedBaseInstance.xhtml">external</a> documentation.
-spec drawArraysInstancedBaseInstance(Mode, First, Count, Primcount, Baseinstance) -> 'ok' when Mode :: enum(),First :: integer(),Count :: integer(),Primcount :: integer(),Baseinstance :: integer().
drawArraysInstancedBaseInstance(Mode,First,Count,Primcount,Baseinstance) ->
cast(5858, <<Mode:?GLenum,First:?GLint,Count:?GLsizei,Primcount:?GLsizei,Baseinstance:?GLuint>>).
@@ -16527,17 +8248,7 @@ drawArraysInstancedBaseInstance(Mode,First,Count,Primcount,Baseinstance) ->
%% is an internal 32-bit integer counter that may be read by a vertex shader as `?gl_InstanceID'
%% .
%%
-%% ``gl:drawElementsInstancedBaseInstance'' has the same effect as: if (mode, count, or
-%% type is invalid ) generate appropriate error else { for (int i = 0; i &lt; primcount ;
-%% i++) { instanceID = i; glDrawElements(mode, count, type, indices); } instanceID = 0; }
-%%
-%% Specific vertex attributes may be classified as `instanced' through the use of {@link gl:vertexAttribDivisor/2}
-%% . Instanced vertex attributes supply per-instance vertex data to the vertex shader. The
-%% index of the vertex fetched from the enabled instanced vertex attribute arrays is calculated
-%% as |gl_ InstanceID/divisor|&amp;plus; baseInstance. Note that `Baseinstance' does not affect the shader-visible
-%% value of `?gl_InstanceID'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsInstancedBaseInstance.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElementsInstancedBaseInstance.xhtml">external</a> documentation.
-spec drawElementsInstancedBaseInstance(Mode, Count, Type, Indices, Primcount, Baseinstance) -> 'ok' when Mode :: enum(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(),Primcount :: integer(),Baseinstance :: integer().
drawElementsInstancedBaseInstance(Mode,Count,Type,Indices,Primcount,Baseinstance) when is_integer(Indices) ->
cast(5859, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint,Primcount:?GLsizei,Baseinstance:?GLuint>>);
@@ -16555,13 +8266,7 @@ drawElementsInstancedBaseInstance(Mode,Count,Type,Indices,Primcount,Baseinstance
%% conditions). The operation is undefined if the sum would be negative. The `Basevertex'
%% has no effect on the shader-visible value of `?gl_VertexID'.
%%
-%% Specific vertex attributes may be classified as `instanced' through the use of {@link gl:vertexAttribDivisor/2}
-%% . Instanced vertex attributes supply per-instance vertex data to the vertex shader. The
-%% index of the vertex fetched from the enabled instanced vertex attribute arrays is calculated
-%% as |gl_ InstanceID/divisor|&amp;plus; baseInstance. Note that `Baseinstance' does not affect the shader-visible
-%% value of `?gl_InstanceID'.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsInstancedBaseVertexBaseInstance.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElementsInstancedBaseVertexBaseInstance.xhtml">external</a> documentation.
-spec drawElementsInstancedBaseVertexBaseInstance(Mode, Count, Type, Indices, Primcount, Basevertex, Baseinstance) -> 'ok' when Mode :: enum(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(),Primcount :: integer(),Basevertex :: integer(),Baseinstance :: integer().
drawElementsInstancedBaseVertexBaseInstance(Mode,Count,Type,Indices,Primcount,Basevertex,Baseinstance) when is_integer(Indices) ->
cast(5861, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint,Primcount:?GLsizei,Basevertex:?GLint,Baseinstance:?GLuint>>);
@@ -16571,21 +8276,21 @@ drawElementsInstancedBaseVertexBaseInstance(Mode,Count,Type,Indices,Primcount,Ba
%% @doc glDrawTransformFeedbackInstance
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawTransformFeedbackInstance.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec drawTransformFeedbackInstanced(Mode, Id, Primcount) -> 'ok' when Mode :: enum(),Id :: integer(),Primcount :: integer().
drawTransformFeedbackInstanced(Mode,Id,Primcount) ->
cast(5863, <<Mode:?GLenum,Id:?GLuint,Primcount:?GLsizei>>).
%% @doc glDrawTransformFeedbackStreamInstance
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawTransformFeedbackStreamInstance.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec drawTransformFeedbackStreamInstanced(Mode, Id, Stream, Primcount) -> 'ok' when Mode :: enum(),Id :: integer(),Stream :: integer(),Primcount :: integer().
drawTransformFeedbackStreamInstanced(Mode,Id,Stream,Primcount) ->
cast(5864, <<Mode:?GLenum,Id:?GLuint,Stream:?GLuint,Primcount:?GLsizei>>).
%% @doc glGetInternalformat
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetInternalformat.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec getInternalformativ(Target, Internalformat, Pname, BufSize) -> [integer()] when Target :: enum(),Internalformat :: enum(),Pname :: enum(),BufSize :: integer().
getInternalformativ(Target,Internalformat,Pname,BufSize) ->
call(5865, <<Target:?GLenum,Internalformat:?GLenum,Pname:?GLenum,BufSize:?GLsizei>>).
@@ -16599,55 +8304,7 @@ getInternalformativ(Target,Internalformat,Pname,BufSize) ->
%% any existing binding to the image unit is broken. `Level' specifies the level of
%% the texture to bind to the image unit.
%%
-%% If `Texture' is the name of a one-, two-, or three-dimensional array texture, a
-%% cube map or cube map array texture, or a two-dimensional multisample array texture, then
-%% it is possible to bind either the entire array, or only a single layer of the array to
-%% the image unit. In such cases, if `Layered' is `?GL_TRUE', the entire array
-%% is attached to the image unit and `Layer' is ignored. However, if `Layered' is `?GL_FALSE'
-%% then `Layer' specifies the layer of the array to attach to the image unit.
-%%
-%% `Access' specifies the access types to be performed by shaders and may be set to `?GL_READ_ONLY'
-%% , `?GL_WRITE_ONLY', or `?GL_READ_WRITE' to indicate read-only, write-only or
-%% read-write access, respectively. Violation of the access type specified in `Access'
-%% (for example, if a shader writes to an image bound with `Access' set to `?GL_READ_ONLY'
-%% ) will lead to undefined results, possibly including program termination.
-%%
-%% `Format' specifies the format that is to be used when performing formatted stores
-%% into the image from shaders. `Format' must be compatible with the texture's internal
-%% format and must be one of the formats listed in the following table.
-%%
-%% <table><tbody><tr><td>` Image Unit Format '</td><td>` Format Qualifier '</td></tr>
-%% </tbody><tbody><tr><td>`?GL_RGBA32F'</td><td>rgba32f</td></tr><tr><td>`?GL_RGBA16F'
-%% </td><td>rgba16f</td></tr><tr><td>`?GL_RG32F'</td><td>rg32f</td></tr><tr><td>`?GL_RG16F'
-%% </td><td>rg16f</td></tr><tr><td>`?GL_R11F_G11F_B10F'</td><td>r11f_g11f_b10f</td></tr>
-%% <tr><td>`?GL_R32F'</td><td>r32f</td></tr><tr><td>`?GL_R16F'</td><td>r16f</td></tr>
-%% <tr><td>`?GL_RGBA32UI'</td><td>rgba32ui</td></tr><tr><td>`?GL_RGBA16UI'</td><td>
-%% rgba16ui</td></tr><tr><td>`?GL_RGB10_A2UI'</td><td>rgb10_a2ui</td></tr><tr><td>`?GL_RGBA8UI'
-%% </td><td>rgba8ui</td></tr><tr><td>`?GL_RG32UI'</td><td>rg32ui</td></tr><tr><td>`?GL_RG16UI'
-%% </td><td>rg16ui</td></tr><tr><td>`?GL_RG8UI'</td><td>rg8ui</td></tr><tr><td>`?GL_R32UI'
-%% </td><td>r32ui</td></tr><tr><td>`?GL_R16UI'</td><td>r16ui</td></tr><tr><td>`?GL_R8UI'
-%% </td><td>r8ui</td></tr><tr><td>`?GL_RGBA32I'</td><td>rgba32i</td></tr><tr><td>`?GL_RGBA16I'
-%% </td><td>rgba16i</td></tr><tr><td>`?GL_RGBA8I'</td><td>rgba8i</td></tr><tr><td>`?GL_RG32I'
-%% </td><td>rg32i</td></tr><tr><td>`?GL_RG16I'</td><td>rg16i</td></tr><tr><td>`?GL_RG8I'
-%% </td><td>rg8i</td></tr><tr><td>`?GL_R32I'</td><td>r32i</td></tr><tr><td>`?GL_R16I'
-%% </td><td>r16i</td></tr><tr><td>`?GL_R8I'</td><td>r8i</td></tr><tr><td>`?GL_RGBA16'
-%% </td><td>rgba16</td></tr><tr><td>`?GL_RGB10_A2'</td><td>rgb10_a2</td></tr><tr><td>`?GL_RGBA8'
-%% </td><td>rgba8</td></tr><tr><td>`?GL_RG16'</td><td>rg16</td></tr><tr><td>`?GL_RG8'
-%% </td><td>rg8</td></tr><tr><td>`?GL_R16'</td><td>r16</td></tr><tr><td>`?GL_R8'</td>
-%% <td>r8</td></tr><tr><td>`?GL_RGBA16_SNORM'</td><td>rgba16_snorm</td></tr><tr><td>`?GL_RGBA8_SNORM'
-%% </td><td>rgba8_snorm</td></tr><tr><td>`?GL_RG16_SNORM'</td><td>rg16_snorm</td></tr><tr>
-%% <td>`?GL_RG8_SNORM'</td><td>rg8_snorm</td></tr><tr><td>`?GL_R16_SNORM'</td><td>r16_snorm
-%% </td></tr><tr><td>`?GL_R8_SNORM'</td><td>r8_snorm</td></tr></tbody></table>
-%%
-%% When a texture is bound to an image unit, the `Format' parameter for the image unit
-%% need not exactly match the texture internal format as long as the formats are considered
-%% compatible as defined in the OpenGL Specification. The matching criterion used for a given
-%% texture may be determined by calling {@link gl:getTexParameterfv/2} with `Value' set
-%% to `?GL_IMAGE_FORMAT_COMPATIBILITY_TYPE', with return values of `?GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE'
-%% and `?GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS', specifying matches by size and class,
-%% respectively.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindImageTexture.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindImageTexture.xhtml">external</a> documentation.
-spec bindImageTexture(Unit, Texture, Level, Layered, Layer, Access, Format) -> 'ok' when Unit :: integer(),Texture :: integer(),Level :: integer(),Layered :: 0|1,Layer :: integer(),Access :: enum(),Format :: enum().
bindImageTexture(Unit,Texture,Level,Layered,Layer,Access,Format) ->
cast(5866, <<Unit:?GLuint,Texture:?GLuint,Level:?GLint,Layered:?GLboolean,0:24,Layer:?GLint,Access:?GLenum,Format:?GLenum>>).
@@ -16661,120 +8318,7 @@ bindImageTexture(Unit,Texture,Level,Layered,Layer,Access,Format) ->
%% the set of operations that are synchronized with shader stores; the bits used in `Barriers'
%% are as follows:
%%
-%%
-%%
-%% `?GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT': If set, vertex data sourced from buffer objects
-%% after the barrier will reflect data written by shaders prior to the barrier. The set of
-%% buffer objects affected by this bit is derived from the buffer object bindings used for
-%% generic vertex attributes derived from the `?GL_VERTEX_ATTRIB_ARRAY_BUFFER' bindings.
-%%
-%%
-%% `?GL_ELEMENT_ARRAY_BARRIER_BIT': If set, vertex array indices sourced from buffer
-%% objects after the barrier will reflect data written by shaders prior to the barrier. The
-%% buffer objects affected by this bit are derived from the `?GL_ELEMENT_ARRAY_BUFFER'
-%% binding.
-%%
-%% `?GL_UNIFORM_BARRIER_BIT': Shader uniforms sourced from buffer objects after the
-%% barrier will reflect data written by shaders prior to the barrier.
-%%
-%% `?GL_TEXTURE_FETCH_BARRIER_BIT': Texture fetches from shaders, including fetches
-%% from buffer object memory via buffer textures, after the barrier will reflect data written
-%% by shaders prior to the barrier.
-%%
-%% `?GL_SHADER_IMAGE_ACCESS_BARRIER_BIT': Memory accesses using shader image load,
-%% store, and atomic built-in functions issued after the barrier will reflect data written
-%% by shaders prior to the barrier. Additionally, image stores and atomics issued after the
-%% barrier will not execute until all memory accesses (e.g., loads, stores, texture fetches,
-%% vertex fetches) initiated prior to the barrier complete.
-%%
-%% `?GL_COMMAND_BARRIER_BIT': Command data sourced from buffer objects by Draw*Indirect
-%% commands after the barrier will reflect data written by shaders prior to the barrier.
-%% The buffer objects affected by this bit are derived from the `?GL_DRAW_INDIRECT_BUFFER'
-%% binding.
-%%
-%% `?GL_PIXEL_BUFFER_BARRIER_BIT': Reads and writes of buffer objects via the `?GL_PIXEL_PACK_BUFFER'
-%% and `?GL_PIXEL_UNPACK_BUFFER' bindings (via {@link gl:readPixels/7} , {@link gl:texSubImage1D/7}
-%% , etc.) after the barrier will reflect data written by shaders prior to the barrier. Additionally,
-%% buffer object writes issued after the barrier will wait on the completion of all shader
-%% writes initiated prior to the barrier.
-%%
-%% `?GL_TEXTURE_UPDATE_BARRIER_BIT': Writes to a texture via ``gl:tex(Sub)Image*'', ``gl:copyTex(Sub)Image*''
-%% , ``gl:compressedTex(Sub)Image*'', and reads via {@link gl:getTexImage/5} after the barrier
-%% will reflect data written by shaders prior to the barrier. Additionally, texture writes
-%% from these commands issued after the barrier will not execute until all shader writes
-%% initiated prior to the barrier complete.
-%%
-%% `?GL_BUFFER_UPDATE_BARRIER_BIT': Reads or writes via {@link gl:bufferSubData/4} , {@link gl:copyBufferSubData/5}
-%% , or {@link gl:getBufferSubData/4} , or to buffer object memory mapped by see `glMapBuffer'
-%% or see `glMapBufferRange' after the barrier will reflect data written by shaders
-%% prior to the barrier. Additionally, writes via these commands issued after the barrier
-%% will wait on the completion of any shader writes to the same memory initiated prior to
-%% the barrier.
-%%
-%% `?GL_FRAMEBUFFER_BARRIER_BIT': Reads and writes via framebuffer object attachments
-%% after the barrier will reflect data written by shaders prior to the barrier. Additionally,
-%% framebuffer writes issued after the barrier will wait on the completion of all shader
-%% writes issued prior to the barrier.
-%%
-%% `?GL_TRANSFORM_FEEDBACK_BARRIER_BIT': Writes via transform feedback bindings after
-%% the barrier will reflect data written by shaders prior to the barrier. Additionally, transform
-%% feedback writes issued after the barrier will wait on the completion of all shader writes
-%% issued prior to the barrier.
-%%
-%% `?GL_ATOMIC_COUNTER_BARRIER_BIT': Accesses to atomic counters after the barrier
-%% will reflect writes prior to the barrier.
-%%
-%% If `Barriers' is `?GL_ALL_BARRIER_BITS', shader memory accesses will be synchronized
-%% relative to all the operations described above.
-%%
-%% Implementations may cache buffer object and texture image memory that could be written
-%% by shaders in multiple caches; for example, there may be separate caches for texture,
-%% vertex fetching, and one or more caches for shader memory accesses. Implementations are
-%% not required to keep these caches coherent with shader memory writes. Stores issued by
-%% one invocation may not be immediately observable by other pipeline stages or other shader
-%% invocations because the value stored may remain in a cache local to the processor executing
-%% the store, or because data overwritten by the store is still in a cache elsewhere in the
-%% system. When ``gl:memoryBarrier'' is called, the GL flushes and/or invalidates any caches
-%% relevant to the operations specified by the `Barriers' parameter to ensure consistent
-%% ordering of operations across the barrier.
-%%
-%% To allow for independent shader invocations to communicate by reads and writes to a common
-%% memory address, image variables in the OpenGL Shading Language may be declared as "coherent".
-%% Buffer object or texture image memory accessed through such variables may be cached only
-%% if caches are automatically updated due to stores issued by any other shader invocation.
-%% If the same address is accessed using both coherent and non-coherent variables, the accesses
-%% using variables declared as coherent will observe the results stored using coherent variables
-%% in other invocations. Using variables declared as "coherent" guarantees only that the
-%% results of stores will be immediately visible to shader invocations using similarly-declared
-%% variables; calling ``gl:memoryBarrier'' is required to ensure that the stores are visible
-%% to other operations.
-%%
-%% The following guidelines may be helpful in choosing when to use coherent memory accesses
-%% and when to use barriers.
-%%
-%% Data that are read-only or constant may be accessed without using coherent variables or
-%% calling MemoryBarrier(). Updates to the read-only data via API calls such as BufferSubData
-%% will invalidate shader caches implicitly as required.
-%%
-%% Data that are shared between shader invocations at a fine granularity (e.g., written by
-%% one invocation, consumed by another invocation) should use coherent variables to read
-%% and write the shared data.
-%%
-%% Data written by one shader invocation and consumed by other shader invocations launched
-%% as a result of its execution ("dependent invocations") should use coherent variables in
-%% the producing shader invocation and call memoryBarrier() after the last write. The consuming
-%% shader invocation should also use coherent variables.
-%%
-%% Data written to image variables in one rendering pass and read by the shader in a later
-%% pass need not use coherent variables or memoryBarrier(). Calling MemoryBarrier() with
-%% the SHADER_IMAGE_ACCESS_BARRIER_BIT set in `Barriers' between passes is necessary.
-%%
-%% Data written by the shader in one rendering pass and read by another mechanism (e.g.,
-%% vertex or index buffer pulling) in a later pass need not use coherent variables or memoryBarrier().
-%% Calling ``gl:memoryBarrier'' with the appropriate bits set in `Barriers' between
-%% passes is necessary.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMemoryBarrier.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMemoryBarrier.xhtml">external</a> documentation.
-spec memoryBarrier(Barriers) -> 'ok' when Barriers :: integer().
memoryBarrier(Barriers) ->
cast(5867, <<Barriers:?GLbitfield>>).
@@ -16787,27 +8331,7 @@ memoryBarrier(Barriers) ->
%% the image may still be modified, however, its storage requirements may not change. Such
%% a texture is referred to as an `immutable-format' texture.
%%
-%% Calling ``gl:texStorage1D'' is equivalent, assuming no errors are generated, to executing
-%% the following pseudo-code: for (i = 0; i &lt; levels; i++) { glTexImage1D(target, i,
-%% internalformat, width, 0, format, type, NULL); width = max(1, (width / 2)); }
-%%
-%% Since no texture data is actually provided, the values used in the pseudo-code for `Format'
-%% and `Type' are irrelevant and may be considered to be any values that are legal
-%% for the chosen `Internalformat' enumerant. `Internalformat' must be one of the
-%% sized internal formats given in Table 1 below, one of the sized depth-component formats `?GL_DEPTH_COMPONENT32F'
-%% , `?GL_DEPTH_COMPONENT24', or `?GL_DEPTH_COMPONENT16', or one of the combined
-%% depth-stencil formats, `?GL_DEPTH32F_STENCIL8', or `?GL_DEPTH24_STENCIL8'. Upon
-%% success, the value of `?GL_TEXTURE_IMMUTABLE_FORMAT' becomes `?GL_TRUE'. The
-%% value of `?GL_TEXTURE_IMMUTABLE_FORMAT' may be discovered by calling {@link gl:getTexParameterfv/2}
-%% with `Pname' set to `?GL_TEXTURE_IMMUTABLE_FORMAT'. No further changes to the
-%% dimensions or format of the texture object may be made. Using any command that might alter
-%% the dimensions or format of the texture object (such as {@link gl:texImage1D/8} or another
-%% call to ``gl:texStorage1D'') will result in the generation of a `?GL_INVALID_OPERATION'
-%% error, even if it would not, in fact, alter the dimensions or format of the object.
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexStorage1D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexStorage1D.xhtml">external</a> documentation.
-spec texStorage1D(Target, Levels, Internalformat, Width) -> 'ok' when Target :: enum(),Levels :: integer(),Internalformat :: enum(),Width :: integer().
texStorage1D(Target,Levels,Internalformat,Width) ->
cast(5868, <<Target:?GLenum,Levels:?GLsizei,Internalformat:?GLenum,Width:?GLsizei>>).
@@ -16820,39 +8344,7 @@ texStorage1D(Target,Levels,Internalformat,Width) ->
%% proxy texture. The contents of the image may still be modified, however, its storage requirements
%% may not change. Such a texture is referred to as an `immutable-format' texture.
%%
-%% The behavior of ``gl:texStorage2D'' depends on the `Target' parameter. When `Target'
-%% is `?GL_TEXTURE_2D', `?GL_PROXY_TEXTURE_2D', `?GL_TEXTURE_RECTANGLE', `?GL_PROXY_TEXTURE_RECTANGLE'
-%% or `?GL_PROXY_TEXTURE_CUBE_MAP', calling ``gl:texStorage2D'' is equivalent, assuming
-%% no errors are generated, to executing the following pseudo-code: for (i = 0; i &lt; levels;
-%% i++) { glTexImage2D(target, i, internalformat, width, height, 0, format, type, NULL);
-%% width = max(1, (width / 2)); height = max(1, (height / 2)); }
-%%
-%% When `Target' is `?GL_TEXTURE_CUBE_MAP', ``gl:texStorage2D'' is equivalent
-%% to: for (i = 0; i &lt; levels; i++) { for (face in (+X, -X, +Y, -Y, +Z, -Z)) { glTexImage2D(face,
-%% i, internalformat, width, height, 0, format, type, NULL); } width = max(1, (width / 2));
-%% height = max(1, (height / 2)); }
-%%
-%% When `Target' is `?GL_TEXTURE_1D' or `?GL_TEXTURE_1D_ARRAY', ``gl:texStorage2D''
-%% is equivalent to: for (i = 0; i &lt; levels; i++) { glTexImage2D(target, i, internalformat,
-%% width, height, 0, format, type, NULL); width = max(1, (width / 2)); }
-%%
-%% Since no texture data is actually provided, the values used in the pseudo-code for `Format'
-%% and `Type' are irrelevant and may be considered to be any values that are legal
-%% for the chosen `Internalformat' enumerant. `Internalformat' must be one of the
-%% sized internal formats given in Table 1 below, one of the sized depth-component formats `?GL_DEPTH_COMPONENT32F'
-%% , `?GL_DEPTH_COMPONENT24', or `?GL_DEPTH_COMPONENT16', or one of the combined
-%% depth-stencil formats, `?GL_DEPTH32F_STENCIL8', or `?GL_DEPTH24_STENCIL8'. Upon
-%% success, the value of `?GL_TEXTURE_IMMUTABLE_FORMAT' becomes `?GL_TRUE'. The
-%% value of `?GL_TEXTURE_IMMUTABLE_FORMAT' may be discovered by calling {@link gl:getTexParameterfv/2}
-%% with `Pname' set to `?GL_TEXTURE_IMMUTABLE_FORMAT'. No further changes to the
-%% dimensions or format of the texture object may be made. Using any command that might alter
-%% the dimensions or format of the texture object (such as {@link gl:texImage2D/9} or another
-%% call to ``gl:texStorage2D'') will result in the generation of a `?GL_INVALID_OPERATION'
-%% error, even if it would not, in fact, alter the dimensions or format of the object.
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexStorage2D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexStorage2D.xhtml">external</a> documentation.
-spec texStorage2D(Target, Levels, Internalformat, Width, Height) -> 'ok' when Target :: enum(),Levels :: integer(),Internalformat :: enum(),Width :: integer(),Height :: integer().
texStorage2D(Target,Levels,Internalformat,Width,Height) ->
cast(5869, <<Target:?GLenum,Levels:?GLsizei,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei>>).
@@ -16866,50 +8358,21 @@ texStorage2D(Target,Levels,Internalformat,Width,Height) ->
%% requirements may not change. Such a texture is referred to as an `immutable-format'
%% texture.
%%
-%% The behavior of ``gl:texStorage3D'' depends on the `Target' parameter. When `Target'
-%% is `?GL_TEXTURE_3D', or `?GL_PROXY_TEXTURE_3D', calling ``gl:texStorage3D''
-%% is equivalent, assuming no errors are generated, to executing the following pseudo-code:
-%% for (i = 0; i &lt; levels; i++) { glTexImage3D(target, i, internalformat, width, height,
-%% depth, 0, format, type, NULL); width = max(1, (width / 2)); height = max(1, (height /
-%% 2)); depth = max(1, (depth / 2)); }
-%%
-%% When `Target' is `?GL_TEXTURE_2D_ARRAY', `?GL_PROXY_TEXTURE_2D_ARRAY', `?GL_TEXTURE_CUBE_MAP_ARRAY'
-%% , or `?GL_PROXY_TEXTURE_CUBE_MAP_ARRAY', ``gl:texStorage3D'' is equivalent to:
-%% for (i = 0; i &lt; levels; i++) { glTexImage3D(target, i, internalformat, width, height,
-%% depth, 0, format, type, NULL); width = max(1, (width / 2)); height = max(1, (height /
-%% 2)); }
-%%
-%% Since no texture data is actually provided, the values used in the pseudo-code for `Format'
-%% and `Type' are irrelevant and may be considered to be any values that are legal
-%% for the chosen `Internalformat' enumerant. `Internalformat' must be one of the
-%% sized internal formats given in Table 1 below, one of the sized depth-component formats `?GL_DEPTH_COMPONENT32F'
-%% , `?GL_DEPTH_COMPONENT24', or `?GL_DEPTH_COMPONENT16', or one of the combined
-%% depth-stencil formats, `?GL_DEPTH32F_STENCIL8', or `?GL_DEPTH24_STENCIL8'. Upon
-%% success, the value of `?GL_TEXTURE_IMMUTABLE_FORMAT' becomes `?GL_TRUE'. The
-%% value of `?GL_TEXTURE_IMMUTABLE_FORMAT' may be discovered by calling {@link gl:getTexParameterfv/2}
-%% with `Pname' set to `?GL_TEXTURE_IMMUTABLE_FORMAT'. No further changes to the
-%% dimensions or format of the texture object may be made. Using any command that might alter
-%% the dimensions or format of the texture object (such as {@link gl:texImage3D/10} or another
-%% call to ``gl:texStorage3D'') will result in the generation of a `?GL_INVALID_OPERATION'
-%% error, even if it would not, in fact, alter the dimensions or format of the object.
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexStorage3D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexStorage3D.xhtml">external</a> documentation.
-spec texStorage3D(Target, Levels, Internalformat, Width, Height, Depth) -> 'ok' when Target :: enum(),Levels :: integer(),Internalformat :: enum(),Width :: integer(),Height :: integer(),Depth :: integer().
texStorage3D(Target,Levels,Internalformat,Width,Height,Depth) ->
cast(5870, <<Target:?GLenum,Levels:?GLsizei,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei>>).
%% @doc glDepthBoundsEXT
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthBoundsEXT.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec depthBoundsEXT(Zmin, Zmax) -> 'ok' when Zmin :: clamp(),Zmax :: clamp().
depthBoundsEXT(Zmin,Zmax) ->
cast(5871, <<Zmin:?GLclampd,Zmax:?GLclampd>>).
%% @doc glStencilClearTagEXT
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilClearTagEXT.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation.
-spec stencilClearTagEXT(StencilTagBits, StencilClearTag) -> 'ok' when StencilTagBits :: integer(),StencilClearTag :: integer().
stencilClearTagEXT(StencilTagBits,StencilClearTag) ->
cast(5872, <<StencilTagBits:?GLsizei,StencilClearTag:?GLuint>>).
diff --git a/lib/wx/src/gen/glu.erl b/lib/wx/src/gen/glu.erl
index f641f41262..5e5f01874f 100644
--- a/lib/wx/src/gen/glu.erl
+++ b/lib/wx/src/gen/glu.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@
%% This file is generated DO NOT EDIT
%% @doc A part of the standard OpenGL Utility api.
-%% See <a href="http://www.opengl.org/sdk/docs/man/">www.opengl.org</a>
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">www.khronos.org</a>
%%
%% Booleans are represented by integers 0 and 1.
@@ -92,29 +92,7 @@ tesselate({Nx,Ny,Nz}, Vs) ->
%% of decreasing resolutions called a mipmap. This is used for the antialiasing of texture
%% mapped primitives.
%%
-%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1}
-%% ).
-%%
-%% A series of mipmap levels from `Base' to `Max' is built by decimating `Data'
-%% in half until size 1×1 is reached. At each level, each texel in the halved mipmap
-%% level is an average of the corresponding two texels in the larger mipmap level. {@link gl:texImage1D/8}
-%% is called to load these mipmap levels from `Base' to `Max' . If `Max' is
-%% larger than the highest mipmap level for the texture of the specified size, then a GLU
-%% error code is returned (see {@link glu:errorString/1} ) and nothing is loaded.
-%%
-%% For example, if `Level' is 2 and `Width' is 16, the following levels are possible:
-%% 16×1, 8×1, 4×1, 2×1, 1×1. These correspond to levels 2 through 6 respectively.
-%% If `Base' is 3 and `Max' is 5, then only mipmap levels 8×1, 4×1 and 2×1
-%% are loaded. However, if `Max' is 7, then an error is returned and nothing is loaded
-%% since `Max' is larger than the highest mipmap level which is, in this case, 6.
-%%
-%% The highest mipmap level can be derived from the formula log 2(width×2 level).
-%%
-%% See the {@link gl:texImage1D/8} reference page for a description of the acceptable values
-%% for `Type' parameter. See the {@link gl:drawPixels/5} reference page for a description
-%% of the acceptable values for `Level' parameter.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild1DMipmapLevels.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluBuild1DMipmapLevels.xml">external</a> documentation.
-spec build1DMipmapLevels(Target, InternalFormat, Width, Format, Type, Level, Base, Max, Data) -> integer() when Target :: enum(),InternalFormat :: integer(),Width :: integer(),Format :: enum(),Type :: enum(),Level :: integer(),Base :: integer(),Max :: integer(),Data :: binary().
build1DMipmapLevels(Target,InternalFormat,Width,Format,Type,Level,Base,Max,Data) ->
send_bin(Data),
@@ -126,33 +104,7 @@ build1DMipmapLevels(Target,InternalFormat,Width,Format,Type,Level,Base,Max,Data)
%% decreasing resolutions called a mipmap. This is used for the antialiasing of texture mapped
%% primitives.
%%
-%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1}
-%% ).
-%%
-%% Initially, the `Width' of `Data' is checked to see if it is a power of 2. If
-%% not, a copy of `Data' is scaled up or down to the nearest power of 2. (If `Width'
-%% is exactly between powers of 2, then the copy of `Data' will scale upwards.) This
-%% copy will be used for subsequent mipmapping operations described below. For example, if `Width'
-%% is 57, then a copy of `Data' will scale up to 64 before mipmapping takes place.
-%%
-%% Then, proxy textures (see {@link gl:texImage1D/8} ) are used to determine if the implementation
-%% can fit the requested texture. If not, `Width' is continually halved until it fits.
-%%
-%% Next, a series of mipmap levels is built by decimating a copy of `Data' in half
-%% until size 1×1 is reached. At each level, each texel in the halved mipmap level is an
-%% average of the corresponding two texels in the larger mipmap level.
-%%
-%% {@link gl:texImage1D/8} is called to load each of these mipmap levels. Level 0 is a copy
-%% of `Data' . The highest level is (log 2)(width). For example, if `Width' is 64 and the implementation
-%% can store a texture of this size, the following mipmap levels are built: 64×1, 32×1,
-%% 16×1, 8×1, 4×1, 2×1, and 1×1. These correspond to levels 0 through 6, respectively.
-%%
-%%
-%% See the {@link gl:texImage1D/8} reference page for a description of the acceptable values
-%% for the `Type' parameter. See the {@link gl:drawPixels/5} reference page for a description
-%% of the acceptable values for the `Data' parameter.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild1DMipmaps.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluBuild1DMipmaps.xml">external</a> documentation.
-spec build1DMipmaps(Target, InternalFormat, Width, Format, Type, Data) -> integer() when Target :: enum(),InternalFormat :: integer(),Width :: integer(),Format :: enum(),Type :: enum(),Data :: binary().
build1DMipmaps(Target,InternalFormat,Width,Format,Type,Data) ->
send_bin(Data),
@@ -164,32 +116,7 @@ build1DMipmaps(Target,InternalFormat,Width,Format,Type,Data) ->
%% of decreasing resolutions called a mipmap. This is used for the antialiasing of texture
%% mapped primitives.
%%
-%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1}
-%% ).
-%%
-%% A series of mipmap levels from `Base' to `Max' is built by decimating `Data'
-%% in half along both dimensions until size 1×1 is reached. At each level, each texel
-%% in the halved mipmap level is an average of the corresponding four texels in the larger
-%% mipmap level. (In the case of rectangular images, the decimation will ultimately reach
-%% an N×1 or 1×N configuration. Here, two texels are averaged instead.) {@link gl:texImage2D/9}
-%% is called to load these mipmap levels from `Base' to `Max' . If `Max' is
-%% larger than the highest mipmap level for the texture of the specified size, then a GLU
-%% error code is returned (see {@link glu:errorString/1} ) and nothing is loaded.
-%%
-%% For example, if `Level' is 2 and `Width' is 16 and `Height' is 8, the
-%% following levels are possible: 16×8, 8×4, 4×2, 2×1, 1×1. These correspond to
-%% levels 2 through 6 respectively. If `Base' is 3 and `Max' is 5, then only mipmap
-%% levels 8×4, 4×2, and 2×1 are loaded. However, if `Max' is 7, then an error is
-%% returned and nothing is loaded since `Max' is larger than the highest mipmap level
-%% which is, in this case, 6.
-%%
-%% The highest mipmap level can be derived from the formula log 2(max(width height)×2 level).
-%%
-%% See the {@link gl:texImage1D/8} reference page for a description of the acceptable values
-%% for `Format' parameter. See the {@link gl:drawPixels/5} reference page for a description
-%% of the acceptable values for `Type' parameter.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild2DMipmapLevels.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluBuild2DMipmapLevels.xml">external</a> documentation.
-spec build2DMipmapLevels(Target, InternalFormat, Width, Height, Format, Type, Level, Base, Max, Data) -> integer() when Target :: enum(),InternalFormat :: integer(),Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Level :: integer(),Base :: integer(),Max :: integer(),Data :: binary().
build2DMipmapLevels(Target,InternalFormat,Width,Height,Format,Type,Level,Base,Max,Data) ->
send_bin(Data),
@@ -201,40 +128,7 @@ build2DMipmapLevels(Target,InternalFormat,Width,Height,Format,Type,Level,Base,Ma
%% decreasing resolutions called a mipmap. This is used for the antialiasing of texture-mapped
%% primitives.
%%
-%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1}
-%% ).
-%%
-%% Initially, the `Width' and `Height' of `Data' are checked to see if they
-%% are a power of 2. If not, a copy of `Data' (not `Data' ), is scaled up or down
-%% to the nearest power of 2. This copy will be used for subsequent mipmapping operations
-%% described below. (If `Width' or `Height' is exactly between powers of 2, then
-%% the copy of `Data' will scale upwards.) For example, if `Width' is 57 and `Height'
-%% is 23, then a copy of `Data' will scale up to 64 in `Width' and down to 16
-%% in depth, before mipmapping takes place.
-%%
-%% Then, proxy textures (see {@link gl:texImage2D/9} ) are used to determine if the implementation
-%% can fit the requested texture. If not, both dimensions are continually halved until it
-%% fits. (If the OpenGL version is (&lt;= 1.0, both maximum texture dimensions are clamped
-%% to the value returned by {@link gl:getBooleanv/1} with the argument `?GLU_MAX_TEXTURE_SIZE'
-%% .)
-%%
-%% Next, a series of mipmap levels is built by decimating a copy of `Data' in half
-%% along both dimensions until size 1×1 is reached. At each level, each texel in the halved
-%% mipmap level is an average of the corresponding four texels in the larger mipmap level.
-%% (In the case of rectangular images, the decimation will ultimately reach an N×1 or 1×N
-%% configuration. Here, two texels are averaged instead.)
-%%
-%% {@link gl:texImage2D/9} is called to load each of these mipmap levels. Level 0 is a copy
-%% of `Data' . The highest level is (log 2)(max(width height)). For example, if `Width' is 64 and `Height'
-%% is 16 and the implementation can store a texture of this size, the following mipmap levels
-%% are built: 64×16, 32×8, 16×4, 8×2, 4×1, 2×1, and 1×1 These correspond to
-%% levels 0 through 6, respectively.
-%%
-%% See the {@link gl:texImage1D/8} reference page for a description of the acceptable values
-%% for `Format' parameter. See the {@link gl:drawPixels/5} reference page for a description
-%% of the acceptable values for `Type' parameter.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild2DMipmaps.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluBuild2DMipmaps.xml">external</a> documentation.
-spec build2DMipmaps(Target, InternalFormat, Width, Height, Format, Type, Data) -> integer() when Target :: enum(),InternalFormat :: integer(),Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Data :: binary().
build2DMipmaps(Target,InternalFormat,Width,Height,Format,Type,Data) ->
send_bin(Data),
@@ -246,32 +140,7 @@ build2DMipmaps(Target,InternalFormat,Width,Height,Format,Type,Data) ->
%% maps of decreasing resolutions called a mipmap. This is used for the antialiasing of texture
%% mapped primitives.
%%
-%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1}
-%% ).
-%%
-%% A series of mipmap levels from `Base' to `Max' is built by decimating `Data'
-%% in half along both dimensions until size 1×1×1 is reached. At each level, each texel
-%% in the halved mipmap level is an average of the corresponding eight texels in the larger
-%% mipmap level. (If exactly one of the dimensions is 1, four texels are averaged. If exactly
-%% two of the dimensions are 1, two texels are averaged.) {@link gl:texImage3D/10} is called
-%% to load these mipmap levels from `Base' to `Max' . If `Max' is larger than
-%% the highest mipmap level for the texture of the specified size, then a GLU error code
-%% is returned (see {@link glu:errorString/1} ) and nothing is loaded.
-%%
-%% For example, if `Level' is 2 and `Width' is 16, `Height' is 8 and `Depth'
-%% is 4, the following levels are possible: 16×8×4, 8×4×2, 4×2×1, 2×1×1, 1×1×1.
-%% These correspond to levels 2 through 6 respectively. If `Base' is 3 and `Max'
-%% is 5, then only mipmap levels 8×4×2, 4×2×1, and 2×1×1 are loaded. However, if `Max'
-%% is 7, then an error is returned and nothing is loaded, since `Max' is larger than
-%% the highest mipmap level which is, in this case, 6.
-%%
-%% The highest mipmap level can be derived from the formula log 2(max(width height depth)×2 level).
-%%
-%% See the {@link gl:texImage1D/8} reference page for a description of the acceptable values
-%% for `Format' parameter. See the {@link gl:drawPixels/5} reference page for a description
-%% of the acceptable values for `Type' parameter.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild3DMipmapLevels.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluBuild3DMipmapLevels.xml">external</a> documentation.
-spec build3DMipmapLevels(Target, InternalFormat, Width, Height, Depth, Format, Type, Level, Base, Max, Data) -> integer() when Target :: enum(),InternalFormat :: integer(),Width :: integer(),Height :: integer(),Depth :: integer(),Format :: enum(),Type :: enum(),Level :: integer(),Base :: integer(),Max :: integer(),Data :: binary().
build3DMipmapLevels(Target,InternalFormat,Width,Height,Depth,Format,Type,Level,Base,Max,Data) ->
send_bin(Data),
@@ -283,39 +152,7 @@ build3DMipmapLevels(Target,InternalFormat,Width,Height,Depth,Format,Type,Level,B
%% of decreasing resolutions called a mipmap. This is used for the antialiasing of texture-mapped
%% primitives.
%%
-%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1}
-%% ).
-%%
-%% Initially, the `Width' , `Height' and `Depth' of `Data' are checked
-%% to see if they are a power of 2. If not, a copy of `Data' is made and scaled up or
-%% down to the nearest power of 2. (If `Width' , `Height' , or `Depth' is exactly
-%% between powers of 2, then the copy of `Data' will scale upwards.) This copy will
-%% be used for subsequent mipmapping operations described below. For example, if `Width'
-%% is 57, `Height' is 23, and `Depth' is 24, then a copy of `Data' will scale
-%% up to 64 in width, down to 16 in height, and up to 32 in depth before mipmapping takes
-%% place.
-%%
-%% Then, proxy textures (see {@link gl:texImage3D/10} ) are used to determine if the implementation
-%% can fit the requested texture. If not, all three dimensions are continually halved until
-%% it fits.
-%%
-%% Next, a series of mipmap levels is built by decimating a copy of `Data' in half
-%% along all three dimensions until size 1×1×1 is reached. At each level, each texel in
-%% the halved mipmap level is an average of the corresponding eight texels in the larger
-%% mipmap level. (If exactly one of the dimensions is 1, four texels are averaged. If exactly
-%% two of the dimensions are 1, two texels are averaged.)
-%%
-%% {@link gl:texImage3D/10} is called to load each of these mipmap levels. Level 0 is a copy
-%% of `Data' . The highest level is (log 2)(max(width height depth)). For example, if `Width' is 64, `Height'
-%% is 16, and `Depth' is 32, and the implementation can store a texture of this size,
-%% the following mipmap levels are built: 64×16×32, 32×8×16, 16×4×8, 8×2×4, 4×1×2,
-%% 2×1×1, and 1×1×1. These correspond to levels 0 through 6, respectively.
-%%
-%% See the {@link gl:texImage1D/8} reference page for a description of the acceptable values
-%% for `Format' parameter. See the {@link gl:drawPixels/5} reference page for a description
-%% of the acceptable values for `Type' parameter.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild3DMipmaps.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluBuild3DMipmaps.xml">external</a> documentation.
-spec build3DMipmaps(Target, InternalFormat, Width, Height, Depth, Format, Type, Data) -> integer() when Target :: enum(),InternalFormat :: integer(),Width :: integer(),Height :: integer(),Depth :: integer(),Format :: enum(),Type :: enum(),Data :: binary().
build3DMipmaps(Target,InternalFormat,Width,Height,Depth,Format,Type,Data) ->
send_bin(Data),
@@ -326,12 +163,7 @@ build3DMipmaps(Target,InternalFormat,Width,Height,Depth,Format,Type,Data) ->
%% ``glu:checkExtension'' returns `?GLU_TRUE' if `ExtName' is supported otherwise
%% `?GLU_FALSE' is returned.
%%
-%% This is used to check for the presence for OpenGL, GLU, or GLX extension names by passing
-%% the extension strings returned by {@link gl:getString/1} , {@link glu:getString/1} , see `glXGetClientString'
-%% , see `glXQueryExtensionsString', or see `glXQueryServerString', respectively,
-%% as `ExtString' .
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluCheckExtension.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluCheckExtension.xml">external</a> documentation.
-spec checkExtension(ExtName, ExtString) -> 0|1 when ExtName :: string(),ExtString :: string().
checkExtension(ExtName,ExtString) ->
ExtNameLen = length(ExtName),
@@ -345,19 +177,7 @@ checkExtension(ExtName,ExtString) ->
%% is subdivided around the `z' axis into slices and along the `z' axis into stacks.
%%
%%
-%% Note that if `Top' is set to 0.0, this routine generates a cone.
-%%
-%% If the orientation is set to `?GLU_OUTSIDE' (with {@link glu:quadricOrientation/2} ),
-%% then any generated normals point away from the `z' axis. Otherwise, they point toward
-%% the `z' axis.
-%%
-%% If texturing is turned on (with {@link glu:quadricTexture/2} ), then texture coordinates
-%% are generated so that `t' ranges linearly from 0.0 at `z' = 0 to 1.0 at `z'
-%% = `Height' , and `s' ranges from 0.0 at the +`y' axis, to 0.25 at the +`x'
-%% axis, to 0.5 at the -`y' axis, to 0.75 at the -`x' axis, and back to 1.0
-%% at the +`y' axis.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluCylinder.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluCylinder.xml">external</a> documentation.
-spec cylinder(Quad, Base, Top, Height, Slices, Stacks) -> 'ok' when Quad :: integer(),Base :: float(),Top :: float(),Height :: float(),Slices :: integer(),Stacks :: integer().
cylinder(Quad,Base,Top,Height,Slices,Stacks) ->
cast(5017, <<Quad:?GLUquadric,Base:?GLdouble,Top:?GLdouble,Height:?GLdouble,Slices:?GLint,Stacks:?GLint>>).
@@ -368,7 +188,7 @@ cylinder(Quad,Base,Top,Height,Slices,Stacks) ->
%% and frees any memory it uses. Once ``glu:deleteQuadric'' has been called, `Quad'
%% cannot be used again.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluDeleteQuadric.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluDeleteQuadric.xml">external</a> documentation.
-spec deleteQuadric(Quad) -> 'ok' when Quad :: integer().
deleteQuadric(Quad) ->
cast(5018, <<Quad:?GLUquadric>>).
@@ -381,17 +201,7 @@ deleteQuadric(Quad) ->
%% slices (like pizza slices) and also about the `z' axis into rings (as specified by `Slices'
%% and `Loops' , respectively).
%%
-%% With respect to orientation, the +`z' side of the disk is considered to be ``outside''
-%% (see {@link glu:quadricOrientation/2} ). This means that if the orientation is set to `?GLU_OUTSIDE'
-%% , then any normals generated point along the +`z' axis. Otherwise, they point along
-%% the -`z' axis.
-%%
-%% If texturing has been turned on (with {@link glu:quadricTexture/2} ), texture coordinates
-%% are generated linearly such that where r=outer, the value at (`r', 0, 0) is (1,
-%% 0.5), at (0, `r', 0) it is (0.5, 1), at (-`r', 0, 0) it is (0, 0.5), and at
-%% (0, -`r', 0) it is (0.5, 0).
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluDisk.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluDisk.xml">external</a> documentation.
-spec disk(Quad, Inner, Outer, Slices, Loops) -> 'ok' when Quad :: integer(),Inner :: float(),Outer :: float(),Slices :: integer(),Loops :: integer().
disk(Quad,Inner,Outer,Slices,Loops) ->
cast(5019, <<Quad:?GLUquadric,Inner:?GLdouble,Outer:?GLdouble,Slices:?GLint,Loops:?GLint>>).
@@ -402,12 +212,7 @@ disk(Quad,Inner,Outer,Slices,Loops) ->
%% is in ISO Latin 1 format. For example, ``glu:errorString''(`?GLU_OUT_OF_MEMORY')
%% returns the string `out of memory'.
%%
-%% The standard GLU error codes are `?GLU_INVALID_ENUM', `?GLU_INVALID_VALUE',
-%% and `?GLU_OUT_OF_MEMORY'. Certain other GLU functions can return specialized error
-%% codes through callbacks. See the {@link gl:getError/0} reference page for the list of
-%% GL error codes.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluErrorString.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluErrorString.xml">external</a> documentation.
-spec errorString(Error) -> string() when Error :: enum().
errorString(Error) ->
call(5020, <<Error:?GLenum>>).
@@ -417,25 +222,7 @@ errorString(Error) ->
%% ``glu:getString'' returns a pointer to a static string describing the GLU version or
%% the GLU extensions that are supported.
%%
-%% The version number is one of the following forms:
-%%
-%% `major_number.minor_number'`major_number.minor_number.release_number'.
-%%
-%% The version string is of the following form:
-%%
-%% `version number&lt;space&gt;vendor-specific information'
-%%
-%% Vendor-specific information is optional. Its format and contents depend on the implementation.
-%%
-%%
-%% The standard GLU contains a basic set of features and capabilities. If a company or group
-%% of companies wish to support other features, these may be included as extensions to the
-%% GLU. If `Name' is `?GLU_EXTENSIONS', then ``glu:getString'' returns a space-separated
-%% list of names of supported GLU extensions. (Extension names never contain spaces.)
-%%
-%% All strings are null-terminated.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluGetString.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluGetString.xml">external</a> documentation.
-spec getString(Name) -> string() when Name :: enum().
getString(Name) ->
call(5021, <<Name:?GLenum>>).
@@ -445,31 +232,7 @@ getString(Name) ->
%% ``glu:lookAt'' creates a viewing matrix derived from an eye point, a reference point
%% indicating the center of the scene, and an `UP' vector.
%%
-%% The matrix maps the reference point to the negative `z' axis and the eye point to
-%% the origin. When a typical projection matrix is used, the center of the scene therefore
-%% maps to the center of the viewport. Similarly, the direction described by the `UP'
-%% vector projected onto the viewing plane is mapped to the positive `y' axis so that
-%% it points upward in the viewport. The `UP' vector must not be parallel to the line
-%% of sight from the eye point to the reference point.
-%%
-%% Let
-%%
-%% F=(centerX-eyeX centerY-eyeY centerZ-eyeZ)
-%%
-%% Let `UP' be the vector (upX upY upZ).
-%%
-%% Then normalize as follows: f=F/(||F||)
-%%
-%% UP"=UP/(||UP||)
-%%
-%% Finally, let s=f×UP", and u=s×f.
-%%
-%% M is then constructed as follows: M=(s[0] s[1] s[2] 0 u[0] u[1] u[2] 0-f[0]-f[1]-f[2] 0 0 0 0 1)
-%%
-%% and ``glu:lookAt'' is equivalent to glMultMatrixf(M); glTranslated(-eyex, -eyey,
-%% -eyez);
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluLookAt.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluLookAt.xml">external</a> documentation.
-spec lookAt(EyeX, EyeY, EyeZ, CenterX, CenterY, CenterZ, UpX, UpY, UpZ) -> 'ok' when EyeX :: float(),EyeY :: float(),EyeZ :: float(),CenterX :: float(),CenterY :: float(),CenterZ :: float(),UpX :: float(),UpY :: float(),UpZ :: float().
lookAt(EyeX,EyeY,EyeZ,CenterX,CenterY,CenterZ,UpX,UpY,UpZ) ->
cast(5022, <<EyeX:?GLdouble,EyeY:?GLdouble,EyeZ:?GLdouble,CenterX:?GLdouble,CenterY:?GLdouble,CenterZ:?GLdouble,UpX:?GLdouble,UpY:?GLdouble,UpZ:?GLdouble>>).
@@ -480,7 +243,7 @@ lookAt(EyeX,EyeY,EyeZ,CenterX,CenterY,CenterZ,UpX,UpY,UpZ) ->
%% must be referred to when calling quadrics rendering and control functions. A return value
%% of 0 means that there is not enough memory to allocate the object.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluNewQuadric.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluNewQuadric.xml">external</a> documentation.
-spec newQuadric() -> integer().
newQuadric() ->
call(5023, <<>>).
@@ -490,7 +253,7 @@ newQuadric() ->
%% ``glu:ortho2D'' sets up a two-dimensional orthographic viewing region. This is equivalent
%% to calling {@link gl:ortho/6} with near=-1 and far=1.
%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluOrtho2D.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluOrtho2D.xml">external</a> documentation.
-spec ortho2D(Left, Right, Bottom, Top) -> 'ok' when Left :: float(),Right :: float(),Bottom :: float(),Top :: float().
ortho2D(Left,Right,Bottom,Top) ->
cast(5024, <<Left:?GLdouble,Right:?GLdouble,Bottom:?GLdouble,Top:?GLdouble>>).
@@ -503,23 +266,7 @@ ortho2D(Left,Right,Bottom,Top) ->
%% the +`x' axis, 180 degrees along the -`y' axis, and 270 degrees along the -`x'
%% axis).
%%
-%% The partial disk has a radius of `Outer' and contains a concentric circular hole
-%% with a radius of `Inner' . If `Inner' is 0, then no hole is generated. The partial
-%% disk is subdivided around the `z' axis into slices (like pizza slices) and also about
-%% the `z' axis into rings (as specified by `Slices' and `Loops' , respectively).
-%%
-%%
-%% With respect to orientation, the +`z' side of the partial disk is considered to
-%% be outside (see {@link glu:quadricOrientation/2} ). This means that if the orientation
-%% is set to `?GLU_OUTSIDE', then any normals generated point along the +`z' axis.
-%% Otherwise, they point along the -`z' axis.
-%%
-%% If texturing is turned on (with {@link glu:quadricTexture/2} ), texture coordinates are
-%% generated linearly such that where r=outer, the value at (`r', 0, 0) is (1.0,
-%% 0.5), at (0, `r', 0) it is (0.5, 1.0), at (-`r', 0, 0) it is (0.0, 0.5), and
-%% at (0, -`r', 0) it is (0.5, 0.0).
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluPartialDisk.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPartialDisk.xml">external</a> documentation.
-spec partialDisk(Quad, Inner, Outer, Slices, Loops, Start, Sweep) -> 'ok' when Quad :: integer(),Inner :: float(),Outer :: float(),Slices :: integer(),Loops :: integer(),Start :: float(),Sweep :: float().
partialDisk(Quad,Inner,Outer,Slices,Loops,Start,Sweep) ->
cast(5025, <<Quad:?GLUquadric,Inner:?GLdouble,Outer:?GLdouble,Slices:?GLint,Loops:?GLint,Start:?GLdouble,Sweep:?GLdouble>>).
@@ -532,18 +279,7 @@ partialDisk(Quad,Inner,Outer,Slices,Loops,Start,Sweep) ->
%% as wide in `x' as it is in `y'. If the viewport is twice as wide as it is tall,
%% it displays the image without distortion.
%%
-%% The matrix generated by ``glu:perspective'' is multipled by the current matrix, just
-%% as if {@link gl:multMatrixd/1} were called with the generated matrix. To load the perspective
-%% matrix onto the current matrix stack instead, precede the call to ``glu:perspective''
-%% with a call to {@link gl:loadIdentity/0} .
-%%
-%% Given `f' defined as follows:
-%%
-%% f=cotangent(fovy/2) The generated matrix is
-%%
-%% (f/aspect 0 0 0 0 f 0 0 0 0(zFar+zNear)/(zNear-zFar)(2×zFar×zNear)/(zNear-zFar) 0 0 -1 0)
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluPerspective.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml">external</a> documentation.
-spec perspective(Fovy, Aspect, ZNear, ZFar) -> 'ok' when Fovy :: float(),Aspect :: float(),ZNear :: float(),ZFar :: float().
perspective(Fovy,Aspect,ZNear,ZFar) ->
cast(5026, <<Fovy:?GLdouble,Aspect:?GLdouble,ZNear:?GLdouble,ZFar:?GLdouble>>).
@@ -557,19 +293,7 @@ perspective(Fovy,Aspect,ZNear,ZFar) ->
%% rerender the scene. All primitives that would have been drawn near the cursor are identified
%% and stored in the selection buffer.
%%
-%% The matrix created by ``glu:pickMatrix'' is multiplied by the current matrix just as
-%% if {@link gl:multMatrixd/1} is called with the generated matrix. To effectively use the
-%% generated pick matrix for picking, first call {@link gl:loadIdentity/0} to load an identity
-%% matrix onto the perspective matrix stack. Then call ``glu:pickMatrix'', and, finally,
-%% call a command (such as {@link glu:perspective/4} ) to multiply the perspective matrix by
-%% the pick matrix.
-%%
-%% When using ``glu:pickMatrix'' to pick NURBS, be careful to turn off the NURBS property
-%% `?GLU_AUTO_LOAD_MATRIX'. If `?GLU_AUTO_LOAD_MATRIX' is not turned off, then
-%% any NURBS surface rendered is subdivided differently with the pick matrix than the way
-%% it was subdivided without the pick matrix.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluPickMatrix.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPickMatrix.xml">external</a> documentation.
-spec pickMatrix(X, Y, DelX, DelY, Viewport) -> 'ok' when X :: float(),Y :: float(),DelX :: float(),DelY :: float(),Viewport :: {integer(),integer(),integer(),integer()}.
pickMatrix(X,Y,DelX,DelY,{V1,V2,V3,V4}) ->
cast(5027, <<X:?GLdouble,Y:?GLdouble,DelX:?GLdouble,DelY:?GLdouble,V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>>).
@@ -581,25 +305,7 @@ pickMatrix(X,Y,DelX,DelY,{V1,V2,V3,V4}) ->
%% , and `WinZ' . A return value of `?GLU_TRUE' indicates success, a return value
%% of `?GLU_FALSE' indicates failure.
%%
-%% To compute the coordinates, let v=(objX objY objZ 1.0) represented as a matrix with 4 rows and 1 column.
-%% Then ``glu:project'' computes v" as follows:
-%%
-%% v"=P×M×v
-%%
-%% where P is the current projection matrix `Proj' and M is the current modelview
-%% matrix `Model' (both represented as 4×4 matrices in column-major order).
-%%
-%% The window coordinates are then computed as follows:
-%%
-%% winX=view(0)+view(2)×(v"(0)+1)/2
-%%
-%% winY=view(1)+view(3)×(v"(1)+1)/2
-%%
-%% winZ=(v"(2)+1)/2
-%%
-%%
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluProject.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluProject.xml">external</a> documentation.
-spec project(ObjX, ObjY, ObjZ, Model, Proj, View) -> {integer(),WinX :: float(),WinY :: float(),WinZ :: float()} when ObjX :: float(),ObjY :: float(),ObjZ :: float(),Model :: matrix(),Proj :: matrix(),View :: {integer(),integer(),integer(),integer()}.
project(ObjX,ObjY,ObjZ,{M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16},{P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16},{V1,V2,V3,V4}) ->
call(5028, <<ObjX:?GLdouble,ObjY:?GLdouble,ObjZ:?GLdouble,M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble,P1:?GLdouble,P2:?GLdouble,P3:?GLdouble,P4:?GLdouble,P5:?GLdouble,P6:?GLdouble,P7:?GLdouble,P8:?GLdouble,P9:?GLdouble,P10:?GLdouble,P11:?GLdouble,P12:?GLdouble,P13:?GLdouble,P14:?GLdouble,P15:?GLdouble,P16:?GLdouble,V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>>);
@@ -611,18 +317,7 @@ project(ObjX,ObjY,ObjZ,{M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12},{P1,P2,P3,P4,P5,
%% ``glu:quadricDrawStyle'' specifies the draw style for quadrics rendered with `Quad' .
%% The legal values are as follows:
%%
-%% `?GLU_FILL': Quadrics are rendered with polygon primitives. The polygons are drawn
-%% in a counterclockwise fashion with respect to their normals (as defined with {@link glu:quadricOrientation/2}
-%% ).
-%%
-%% `?GLU_LINE': Quadrics are rendered as a set of lines.
-%%
-%% `?GLU_SILHOUETTE': Quadrics are rendered as a set of lines, except that edges separating
-%% coplanar faces will not be drawn.
-%%
-%% `?GLU_POINT': Quadrics are rendered as a set of points.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricDrawStyle.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluQuadricDrawStyle.xml">external</a> documentation.
-spec quadricDrawStyle(Quad, Draw) -> 'ok' when Quad :: integer(),Draw :: enum().
quadricDrawStyle(Quad,Draw) ->
cast(5029, <<Quad:?GLUquadric,Draw:?GLenum>>).
@@ -632,14 +327,7 @@ quadricDrawStyle(Quad,Draw) ->
%% ``glu:quadricNormals'' specifies what kind of normals are desired for quadrics rendered
%% with `Quad' . The legal values are as follows:
%%
-%% `?GLU_NONE': No normals are generated.
-%%
-%% `?GLU_FLAT': One normal is generated for every facet of a quadric.
-%%
-%% `?GLU_SMOOTH': One normal is generated for every vertex of a quadric. This is the
-%% initial value.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricNormals.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluQuadricNormals.xml">external</a> documentation.
-spec quadricNormals(Quad, Normal) -> 'ok' when Quad :: integer(),Normal :: enum().
quadricNormals(Quad,Normal) ->
cast(5030, <<Quad:?GLUquadric,Normal:?GLenum>>).
@@ -649,15 +337,7 @@ quadricNormals(Quad,Normal) ->
%% ``glu:quadricOrientation'' specifies what kind of orientation is desired for quadrics
%% rendered with `Quad' . The `Orientation' values are as follows:
%%
-%% `?GLU_OUTSIDE': Quadrics are drawn with normals pointing outward (the initial value).
-%%
-%%
-%% `?GLU_INSIDE': Quadrics are drawn with normals pointing inward.
-%%
-%% Note that the interpretation of `outward' and `inward' depends on the quadric
-%% being drawn.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricOrientation.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluQuadricOrientation.xml">external</a> documentation.
-spec quadricOrientation(Quad, Orientation) -> 'ok' when Quad :: integer(),Orientation :: enum().
quadricOrientation(Quad,Orientation) ->
cast(5031, <<Quad:?GLUquadric,Orientation:?GLenum>>).
@@ -669,10 +349,7 @@ quadricOrientation(Quad,Orientation) ->
%% coordinates are generated, and if `Texture' is `?GLU_FALSE', they are not.
%% The initial value is `?GLU_FALSE'.
%%
-%% The manner in which texture coordinates are generated depends upon the specific quadric
-%% rendered.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricTexture.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluQuadricTexture.xml">external</a> documentation.
-spec quadricTexture(Quad, Texture) -> 'ok' when Quad :: integer(),Texture :: 0|1.
quadricTexture(Quad,Texture) ->
cast(5032, <<Quad:?GLUquadric,Texture:?GLboolean>>).
@@ -682,17 +359,7 @@ quadricTexture(Quad,Texture) ->
%% ``glu:scaleImage'' scales a pixel image using the appropriate pixel store modes to
%% unpack data from the source image and pack data into the destination image.
%%
-%% When shrinking an image, ``glu:scaleImage'' uses a box filter to sample the source
-%% image and create pixels for the destination image. When magnifying an image, the pixels
-%% from the source image are linearly interpolated to create the destination image.
-%%
-%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1}
-%% ).
-%%
-%% See the {@link gl:readPixels/7} reference page for a description of the acceptable values
-%% for the `Format' , `TypeIn' , and `TypeOut' parameters.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluScaleImage.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluScaleImage.xml">external</a> documentation.
-spec scaleImage(Format, WIn, HIn, TypeIn, DataIn, WOut, HOut, TypeOut, DataOut) -> integer() when Format :: enum(),WIn :: integer(),HIn :: integer(),TypeIn :: enum(),DataIn :: binary(),WOut :: integer(),HOut :: integer(),TypeOut :: enum(),DataOut :: mem().
scaleImage(Format,WIn,HIn,TypeIn,DataIn,WOut,HOut,TypeOut,DataOut) ->
send_bin(DataIn),
@@ -705,17 +372,7 @@ scaleImage(Format,WIn,HIn,TypeIn,DataIn,WOut,HOut,TypeOut,DataOut) ->
%% is subdivided around the `z' axis into slices and along the `z' axis into
%% stacks (similar to lines of longitude and latitude).
%%
-%% If the orientation is set to `?GLU_OUTSIDE' (with {@link glu:quadricOrientation/2} ),
-%% then any normals generated point away from the center of the sphere. Otherwise, they
-%% point toward the center of the sphere.
-%%
-%% If texturing is turned on (with {@link glu:quadricTexture/2} ), then texture coordinates
-%% are generated so that `t' ranges from 0.0 at z=-radius to 1.0 at z=radius (`t'
-%% increases linearly along longitudinal lines), and `s' ranges from 0.0 at the +`y'
-%% axis, to 0.25 at the +`x' axis, to 0.5 at the -`y' axis, to 0.75 at the -`x'
-%% axis, and back to 1.0 at the +`y' axis.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluSphere.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluSphere.xml">external</a> documentation.
-spec sphere(Quad, Radius, Slices, Stacks) -> 'ok' when Quad :: integer(),Radius :: float(),Slices :: integer(),Stacks :: integer().
sphere(Quad,Radius,Slices,Stacks) ->
cast(5034, <<Quad:?GLUquadric,Radius:?GLdouble,Slices:?GLint,Stacks:?GLint>>).
@@ -727,13 +384,7 @@ sphere(Quad,Radius,Slices,Stacks) ->
%% . A return value of `?GLU_TRUE' indicates success; a return value of `?GLU_FALSE'
%% indicates failure.
%%
-%% To compute the coordinates (objX objY objZ), ``glu:unProject'' multiplies the normalized device coordinates
-%% by the inverse of `Model' * `Proj' as follows:
-%%
-%% (objX objY objZ W)=INV(P M) ((2(winX-view[0]))/(view[2])-1(2(winY-view[1]))/(view[3])-1 2(winZ)-1 1) INV denotes matrix inversion. W is an unused variable, included for consistent
-%% matrix notation.
-%%
-%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluUnProject.xml">external</a> documentation.
+%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluUnProject.xml">external</a> documentation.
-spec unProject(WinX, WinY, WinZ, Model, Proj, View) -> {integer(),ObjX :: float(),ObjY :: float(),ObjZ :: float()} when WinX :: float(),WinY :: float(),WinZ :: float(),Model :: matrix(),Proj :: matrix(),View :: {integer(),integer(),integer(),integer()}.
unProject(WinX,WinY,WinZ,{M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16},{P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16},{V1,V2,V3,V4}) ->
call(5035, <<WinX:?GLdouble,WinY:?GLdouble,WinZ:?GLdouble,M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble,P1:?GLdouble,P2:?GLdouble,P3:?GLdouble,P4:?GLdouble,P5:?GLdouble,P6:?GLdouble,P7:?GLdouble,P8:?GLdouble,P9:?GLdouble,P10:?GLdouble,P11:?GLdouble,P12:?GLdouble,P13:?GLdouble,P14:?GLdouble,P15:?GLdouble,P16:?GLdouble,V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>>);
diff --git a/lib/wx/src/gen/wxGraphicsContext.erl b/lib/wx/src/gen/wxGraphicsContext.erl
index 2d0271ac48..5d371ecd7a 100644
--- a/lib/wx/src/gen/wxGraphicsContext.erl
+++ b/lib/wx/src/gen/wxGraphicsContext.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -41,8 +41,6 @@
-export([getRenderer/1,isNull/1,parent_class/1]).
-export_type([wxGraphicsContext/0]).
--deprecated([createLinearGradientBrush/7,createRadialGradientBrush/8]).
-
%% @hidden
parent_class(wxGraphicsObject) -> true;
parent_class(_Class) -> erlang:error({badtype, ?MODULE}).
diff --git a/lib/wx/src/gen/wxe_debug.hrl b/lib/wx/src/gen/wxe_debug.hrl
index 58cb5298e6..533f9f2df0 100644
--- a/lib/wx/src/gen/wxe_debug.hrl
+++ b/lib/wx/src/gen/wxe_debug.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1491,10 +1491,10 @@ wxdebug_table() ->
{1637, {wxStaticBox, 'Destroy', undefined}},
{1639, {wxStaticLine, new_2, 2}},
{1640, {wxStaticLine, new_0, 0}},
- {1641, {wxStaticLine, create, 2}},
- {1642, {wxStaticLine, isVertical, 0}},
- {1643, {wxStaticLine, getDefaultSize, 0}},
- {1644, {wxStaticLine, 'Destroy', undefined}},
+ {1641, {wxStaticLine, destruct, 0}},
+ {1642, {wxStaticLine, create, 2}},
+ {1643, {wxStaticLine, isVertical, 0}},
+ {1644, {wxStaticLine, getDefaultSize, 0}},
{1647, {wxListBox, new_3, 3}},
{1648, {wxListBox, new_0, 0}},
{1650, {wxListBox, destruct, 0}},
diff --git a/lib/wx/src/gen/wxe_funcs.hrl b/lib/wx/src/gen/wxe_funcs.hrl
index af0cee0dcd..14b5545676 100644
--- a/lib/wx/src/gen/wxe_funcs.hrl
+++ b/lib/wx/src/gen/wxe_funcs.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1488,10 +1488,10 @@
-define(wxStaticBox_destroy, 1637).
-define(wxStaticLine_new_2, 1639).
-define(wxStaticLine_new_0, 1640).
--define(wxStaticLine_Create, 1641).
--define(wxStaticLine_IsVertical, 1642).
--define(wxStaticLine_GetDefaultSize, 1643).
--define(wxStaticLine_destroy, 1644).
+-define(wxStaticLine_destruct, 1641).
+-define(wxStaticLine_Create, 1642).
+-define(wxStaticLine_IsVertical, 1643).
+-define(wxStaticLine_GetDefaultSize, 1644).
-define(wxListBox_new_3, 1647).
-define(wxListBox_new_0, 1648).
-define(wxListBox_destruct, 1650).
diff --git a/lib/wx/src/wx.erl b/lib/wx/src/wx.erl
index 34bf06cf46..a20758c826 100644
--- a/lib/wx/src/wx.erl
+++ b/lib/wx/src/wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -183,7 +183,7 @@ batch(Fun) ->
ok = wxe_util:cast(?BATCH_BEGIN, <<>>),
try Fun()
catch
- error:W -> erlang:exit({W, erlang:get_stacktrace()});
+ error:W:S -> erlang:exit({W, S});
throw:W -> erlang:throw(W);
exit:W -> erlang:exit(W)
after
@@ -196,7 +196,7 @@ foreach(Fun, List) ->
ok = wxe_util:cast(?BATCH_BEGIN, <<>>),
try lists:foreach(Fun, List)
catch
- error:W -> erlang:exit({W, erlang:get_stacktrace()});
+ error:W:S -> erlang:exit({W, S});
throw:W -> erlang:throw(W);
exit:W -> erlang:exit(W)
after
@@ -209,7 +209,7 @@ map(Fun, List) ->
ok = wxe_util:cast(?BATCH_BEGIN, <<>>),
try lists:map(Fun, List)
catch
- error:W -> erlang:exit({W, erlang:get_stacktrace()});
+ error:W:S -> erlang:exit({W, S});
throw:W -> erlang:throw(W);
exit:W -> erlang:exit(W)
after
@@ -222,7 +222,7 @@ foldl(Fun, Acc, List) ->
ok = wxe_util:cast(?BATCH_BEGIN, <<>>),
try lists:foldl(Fun, Acc, List)
catch
- error:W -> erlang:exit({W, erlang:get_stacktrace()});
+ error:W:S -> erlang:exit({W, S});
throw:W -> erlang:throw(W);
exit:W -> erlang:exit(W)
after
@@ -235,7 +235,7 @@ foldr(Fun, Acc, List) ->
ok = wxe_util:cast(?BATCH_BEGIN, <<>>),
try lists:foldr(Fun, Acc, List)
catch
- error:W -> erlang:exit({W, erlang:get_stacktrace()});
+ error:W:S -> erlang:exit({W, S});
throw:W -> erlang:throw(W);
exit:W -> erlang:exit(W)
after
diff --git a/lib/wx/src/wx_object.erl b/lib/wx/src/wx_object.erl
index 42973335b4..cc19ff9770 100644
--- a/lib/wx/src/wx_object.erl
+++ b/lib/wx/src/wx_object.erl
@@ -561,21 +561,21 @@ system_code_change([Name, State, Mod, Time], _Module, OldVsn, Extra) ->
print_event(Dev, {in, Msg}, Name) ->
case Msg of
{'$gen_call', {From, _Tag}, Call} ->
- io:format(Dev, "*DBG* ~p got call ~p from ~w~n",
+ io:format(Dev, "*DBG* ~tp got call ~tp from ~w~n",
[Name, Call, From]);
{'$gen_cast', Cast} ->
- io:format(Dev, "*DBG* ~p got cast ~p~n",
+ io:format(Dev, "*DBG* ~tp got cast ~tp~n",
[Name, Cast]);
_ ->
- io:format(Dev, "*DBG* ~p got ~p~n", [Name, Msg])
+ io:format(Dev, "*DBG* ~tp got ~tp~n", [Name, Msg])
end;
print_event(Dev, {out, Msg, To, State}, Name) ->
- io:format(Dev, "*DBG* ~p sent ~p to ~w, new state ~w~n",
+ io:format(Dev, "*DBG* ~tp sent ~tp to ~w, new state ~tp~n",
[Name, Msg, To, State]);
print_event(Dev, {noreply, State}, Name) ->
- io:format(Dev, "*DBG* ~p new state ~w~n", [Name, State]);
+ io:format(Dev, "*DBG* ~tp new state ~tp~n", [Name, State]);
print_event(Dev, Event, Name) ->
- io:format(Dev, "*DBG* ~p dbg ~p~n", [Name, Event]).
+ io:format(Dev, "*DBG* ~tp dbg ~tp~n", [Name, Event]).
%%% ---------------------------------------------------
%%% Terminate the server.
@@ -629,10 +629,10 @@ error_info(Reason, Name, Msg, State, Debug) ->
_ ->
Reason
end,
- format("** wx object server ~p terminating \n"
- "** Last message in was ~p~n"
- "** When Server state == ~p~n"
- "** Reason for termination == ~n** ~p~n",
+ format("** wx object server ~tp terminating \n"
+ "** Last message in was ~tp~n"
+ "** When Server state == ~tp~n"
+ "** Reason for termination == ~n** ~tp~n",
[Name, Msg, State, Reason1]),
sys:print_log(Debug),
ok.
@@ -657,7 +657,7 @@ debug_options(Name, Opts) ->
dbg_opts(Name, Opts) ->
case catch sys:debug_options(Opts) of
{'EXIT',_} ->
- format("~p: ignoring erroneous debug options - ~p~n",
+ format("~tp: ignoring erroneous debug options - ~tp~n",
[Name, Opts]),
[];
Dbg ->
diff --git a/lib/wx/src/wxe_master.erl b/lib/wx/src/wxe_master.erl
index ce859b3eb3..edef6b3613 100644
--- a/lib/wx/src/wxe_master.erl
+++ b/lib/wx/src/wxe_master.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -122,16 +122,9 @@ init([SilentStart]) ->
erlang:error(not_smp)
end,
- case os:type() of
- {win32,_} -> %% Needed for mingwm10.dll
- Path = os:getenv("PATH"),
- os:putenv("PATH", PrivDir ++ ";" ++ Path);
- _ -> ok
- end,
-
case erl_ddll:load_driver(PrivDir,DriverName) of
ok -> ok;
- {error, What} ->
+ {error, What} ->
wxe_util:opt_error_log(SilentStart,
"WX Failed loading ~p@~p ~n",
[DriverName,PrivDir]),
@@ -139,8 +132,8 @@ init([SilentStart]) ->
erlang:error({load_driver,Str})
end,
process_flag(trap_exit, true),
- DriverWithArgs = DriverName ++ " " ++ code:priv_dir(wx) ++ [0],
-
+ DriverWithArgs = DriverName ++ " " ++ code:priv_dir(wx),
+
try
Port = open_port({spawn, DriverWithArgs},[binary]),
wx_debug_info = ets:new(wx_debug_info, [named_table]),
diff --git a/lib/wx/src/wxe_server.erl b/lib/wx/src/wxe_server.erl
index 58fcaf8f23..e241a11e8b 100644
--- a/lib/wx/src/wxe_server.erl
+++ b/lib/wx/src/wxe_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -283,10 +283,10 @@ invoke_callback(Pid, Ev, Ref) ->
Return -> exit({bad_return, Return})
end
end
- catch _:Reason ->
+ catch _:Reason:Stacktrace ->
wxEvent:skip(Ref),
?log("Callback fun crashed with {'EXIT, ~p, ~p}~n",
- [Reason, erlang:get_stacktrace()])
+ [Reason, Stacktrace])
end,
wxe_util:cast(?WXE_CB_RETURN, <<>>)
end,
@@ -299,9 +299,9 @@ invoke_callback_fun(Fun) ->
Return = Fun(),
true = is_binary(Return),
Return
- catch _:Reason ->
+ catch _:Reason:Stacktrace ->
?log("Callback fun crashed with {'EXIT, ~p, ~p}~n",
- [Reason, erlang:get_stacktrace()]),
+ [Reason, Stacktrace]),
<<>>
end,
wxe_util:cast(?WXE_CB_RETURN, Res).
diff --git a/lib/wx/test/wx_app_SUITE.erl b/lib/wx/test/wx_app_SUITE.erl
index 3fd5bf689d..99c8ef0416 100644
--- a/lib/wx/test/wx_app_SUITE.erl
+++ b/lib/wx/test/wx_app_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,7 +24,12 @@
%%----------------------------------------------------------------------
-module(wx_app_SUITE).
--compile(export_all).
+-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
+ init_per_suite/1, end_per_suite/1,
+ init_per_testcase/2, end_per_testcase/2]).
+
+-export([t/0, t/1, fields/1, modules/1, exportall/1, app_depend/1,
+ undef_funcs/0, undef_funcs/1, appup/1]).
-include("wx_test_lib.hrl").
-include_lib("common_test/include/ct.hrl").
diff --git a/lib/wx/test/wx_basic_SUITE.erl b/lib/wx/test/wx_basic_SUITE.erl
index d53bd3c15a..ad03a378de 100644
--- a/lib/wx/test/wx_basic_SUITE.erl
+++ b/lib/wx/test/wx_basic_SUITE.erl
@@ -28,7 +28,11 @@
init_per_suite/1, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2]).
--compile(export_all).
+-export([silent_start/1, create_window/1, several_apps/1, wx_api/1, wx_misc/1,
+ data_types/1, wx_object/1, undef_in_handle_info/1, undef_in_terminate/1,
+ undef_handle_event/1, undef_handle_call/1, undef_handle_cast/1, undef_handle_info/1,
+ undef_code_change/1, undef_terminate1/1, undef_terminate2/1
+ ]).
-include("wx_test_lib.hrl").
diff --git a/lib/wx/test/wx_class_SUITE.erl b/lib/wx/test/wx_class_SUITE.erl
index 0a3c4659bf..56749ba72b 100644
--- a/lib/wx/test/wx_class_SUITE.erl
+++ b/lib/wx/test/wx_class_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,10 @@
init_per_suite/1, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2]).
--compile(export_all).
+-export([calendarCtrl/1, treeCtrl/1, notebook/1, staticBoxSizer/1,
+ clipboard/1, helpFrame/1, htmlWindow/1, listCtrlSort/1, listCtrlVirtual/1,
+ radioBox/1, systemSettings/1, taskBarIcon/1, toolbar/1, popup/1, modal/1,
+ textCtrl/1, locale/1]).
-include("wx_test_lib.hrl").
@@ -51,7 +54,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap,{minutes,2}}].
all() ->
[calendarCtrl, treeCtrl, notebook, staticBoxSizer,
clipboard, helpFrame, htmlWindow, listCtrlSort, listCtrlVirtual,
- radioBox, systemSettings, taskBarIcon, toolbar, popup, modal].
+ radioBox, systemSettings, taskBarIcon, toolbar, popup, modal,
+ textCtrl, locale].
groups() ->
[].
@@ -614,7 +618,7 @@ lang_env() ->
Env0 = os:getenv(),
Env = [[R,"\n"]||R <- Env0],
%%io:format("~p~n",[lists:sort(Env)]),
- Opts = [global, multiline, {capture, all, list}],
+ Opts = [global, multiline, {capture, all, list}, unicode],
format_env(re:run(Env, "LC_ALL.*", Opts)),
format_env(re:run(Env, "^LANG.*=.*$", Opts)),
ok.
diff --git a/lib/wx/test/wx_event_SUITE.erl b/lib/wx/test/wx_event_SUITE.erl
index 6512cedaf2..7ecd9b7283 100644
--- a/lib/wx/test/wx_event_SUITE.erl
+++ b/lib/wx/test/wx_event_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,7 +27,10 @@
init_per_suite/1, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2]).
--compile(export_all).
+-export([connect/1, disconnect/1, disconnect_cb/1, connect_msg_20/1, connect_cb_20/1,
+ mouse_on_grid/1, spin_event/1, connect_in_callback/1, recursive/1,
+ dialog/1, char_events/1, callback_clean/1, handler_clean/1
+ ]).
-include("wx_test_lib.hrl").
@@ -49,7 +52,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap,{minutes,2}}].
all() ->
[connect, disconnect, disconnect_cb, connect_msg_20, connect_cb_20,
mouse_on_grid, spin_event, connect_in_callback, recursive,
- dialog, char_events, callback_clean
+ dialog, char_events, callback_clean, handler_clean
].
groups() ->
@@ -577,6 +580,7 @@ handler_clean(_Config) ->
Frame1 = wx_obj_test:start([{init, Init}]),
?mt(wxFrame, Frame1),
wxWindow:show(Frame1),
+ timer:sleep(500),
?m([_|_], lists:sort(wx_test_lib:flush())),
?m(ok, wx_obj_test:stop(Frame1)),
?m([{terminate,normal}], lists:sort(wx_test_lib:flush())),
@@ -584,6 +588,7 @@ handler_clean(_Config) ->
Terminate = fun({Frame,_}) -> wxWindow:destroy(Frame) end,
Frame2 = wx_obj_test:start([{init, Init}, {terminate, Terminate}]),
wxWindow:show(Frame2),
+ timer:sleep(500),
?m([_|_], lists:sort(wx_test_lib:flush())),
?m(ok, wx_obj_test:stop(Frame2)),
?m([{terminate,normal}], lists:sort(wx_test_lib:flush())),
diff --git a/lib/wx/test/wx_oc_object.erl b/lib/wx/test/wx_oc_object.erl
index 3924202410..bc9b7d48d0 100644
--- a/lib/wx/test/wx_oc_object.erl
+++ b/lib/wx/test/wx_oc_object.erl
@@ -20,9 +20,9 @@
-module(wx_oc_object).
-include_lib("wx/include/wx.hrl").
--behaviour(wx_object).
+%%-behaviour(wx_object). %% commented out avoid warnings
-%% gen_server callbacks
+%% wx_object callbacks
-export([init/1]).
-record(state, {}).
diff --git a/lib/wx/test/wx_opengl_SUITE.erl b/lib/wx/test/wx_opengl_SUITE.erl
index 3de9209fae..053740ed8b 100644
--- a/lib/wx/test/wx_opengl_SUITE.erl
+++ b/lib/wx/test/wx_opengl_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@
init_per_suite/1, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2]).
--compile(export_all).
+-export([canvas/1, glu_tesselation/1]).
-include("wx_test_lib.hrl").
-include_lib("wx/include/gl.hrl").
diff --git a/lib/wx/test/wx_test_lib.erl b/lib/wx/test/wx_test_lib.erl
index 9f26b8cb9d..7bf2bb11bb 100644
--- a/lib/wx/test/wx_test_lib.erl
+++ b/lib/wx/test/wx_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,7 +24,10 @@
%%% Created : 30 Oct 2008 by Dan Gudmundsson <[email protected]>
%%%-------------------------------------------------------------------
-module(wx_test_lib).
--compile(export_all).
+-export([init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2]).
+-export([tc_info/1, log/2, log/4, verbose/4, error/4,
+ flush/0, pick_msg/0, user_available/1, wx_destroy/2, wx_close/2, wait_for_close/0,
+ run_test/2, run_test/3, test_case_evaluator/3]).
-include("wx_test_lib.hrl").
@@ -182,11 +185,15 @@ run_test([], _Config) -> [].
run_test(Module, all, Config) ->
All = [{Module, Test} || Test <- Module:all()],
run_test(All, Config);
+run_test(Module, {group, Group}, Config) ->
+ {_, _, TCs} = lists:keyfind(Group, 1, Module:groups()),
+ All = [{Module, Test} || Test <- TCs],
+ run_test(All, Config);
+
run_test(Module, TestCase, Config) ->
log("Eval test case: ~w~n", [{Module, TestCase}]),
Sec = timer:seconds(1) * 1000,
- {T, Res} =
- timer:tc(?MODULE, eval_test_case, [Module, TestCase, Config]),
+ {T, Res} = timer:tc(fun() -> eval_test_case(Module, TestCase, Config) end),
log("Tested ~w in ~w sec~n", [TestCase, T div Sec]),
{T div Sec, Res}.
diff --git a/lib/wx/test/wx_xtra_SUITE.erl b/lib/wx/test/wx_xtra_SUITE.erl
index c6268a7f46..8142d9566f 100644
--- a/lib/wx/test/wx_xtra_SUITE.erl
+++ b/lib/wx/test/wx_xtra_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,7 +28,8 @@
init_per_suite/1, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2]).
--compile(export_all).
+-export([destroy_app/1, multiple_add_in_sizer/1, app_dies/1,
+ menu_item_debug/1]).
-include("wx_test_lib.hrl").
diff --git a/lib/wx/test/wxt b/lib/wx/test/wxt
index e720ed94f4..94513e88e9 100755
--- a/lib/wx/test/wxt
+++ b/lib/wx/test/wxt
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2016. All Rights Reserved.
+# Copyright Ericsson AB 2008-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
#
# %CopyrightEnd%
#
-# Usage: mt <args to erlang startup script>
+# Usage: wxt <args to erlang startup script>
log=test_log_$$
latest=test_log_latest
@@ -27,7 +27,7 @@ erlcmd="erl -sname test_server -smp -pa ../ebin $p $args -wx_test_verbose true -
echo "Give the following command in order to see the outcome:"
echo ""
-echo " less test_log$$"
+echo " less $log"
rm "$latest" 2>/dev/null
ln -s "$log" "$latest"
diff --git a/lib/wx/test/wxt.erl b/lib/wx/test/wxt.erl
index 265cd5c981..280443404f 100644
--- a/lib/wx/test/wxt.erl
+++ b/lib/wx/test/wxt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@
%% Description : Shortcuts for running tests with wx internal test_server
%%-------------------------------------------------------------------
-module(wxt).
--compile(export_all).
+-export([t/0, t/1, t/2, user/0, user/1,user/2]).
%% Modules or suites can be shortcuts i.e. basic expands to wx_basic_SUITE.
%%
@@ -83,36 +83,6 @@ alias(Suite) when is_atom(Suite) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-config_fname() ->
- "wx_test_case_config".
-
-%% Read default config file
-read_config() ->
- Fname = config_fname(),
- wx_test_lib:log("Consulting file ~s...~n", [Fname]),
- case file:consult(Fname) of
- {ok, Config} ->
- wx_test_lib:log("Read config ~w~n", [Config]),
- Config;
- _Error ->
- Config = wx_test_lib:default_config(),
- wx_test_lib:log("<>WARNING<> Using default config: ~w~n", [Config]),
- Config
- end.
-
-%% Write new default config file
-write_config(Config) when is_list(Config) ->
- Fname = config_fname(),
- {ok, Fd} = file:open(Fname, write),
- write_list(Fd, Config),
- file:close(Fd).
-
-write_list(Fd, [H | T]) ->
- ok = io:format(Fd, "~p.~n",[H]),
- write_list(Fd, T);
-write_list(_, []) ->
- ok.
-
test_case_fname() ->
"wx_test_case_info".
diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk
index b9100e7c87..e539ad36f6 100644
--- a/lib/wx/vsn.mk
+++ b/lib/wx/vsn.mk
@@ -1 +1 @@
-WX_VSN = 1.8.1
+WX_VSN = 1.8.5
diff --git a/lib/xmerl/doc/src/Makefile b/lib/xmerl/doc/src/Makefile
index 2465217e8e..0def492246 100644
--- a/lib/xmerl/doc/src/Makefile
+++ b/lib/xmerl/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2016. All Rights Reserved.
+# Copyright Ericsson AB 2004-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -54,21 +54,20 @@ XMERL_MODULES = \
XML_APPLICATION_FILES = ref_man.xml
-XMERL_XML_FILES = $(XMERL_MODULES:=.xml)
+XMERL_XML_FILES = $(XMERL_MODULES:%=$(XMLDIR)/%.xml)
-XML_REF3_FILES = $(XMERL_XML_FILES) \
- xmerl_sax_parser.xml
+XML_REF3_FILES = xmerl_sax_parser.xml
-XML_PART_FILES = \
- part.xml \
- part_notes.xml
+XML_PART_FILES = \
+ part.xml
XML_REF6_FILES =
XML_CHAPTER_FILES = \
- xmerl_ug.xml \
notes.xml
+XML_CHAPTER_GEN_FILES = \
+ $(XMLDIR)/xmerl_ug.xml
HTML_EXAMPLE_FILES = \
xmerl_examples.html \
@@ -90,6 +89,8 @@ XML_FILES= \
$(BOOK_FILES) $(XML_CHAPTER_FILES) \
$(XML_PART_FILES) $(XML_REF3_FILES) $(XML_APPLICATION_FILES)
+XML_GEN_FILES = $(XMERL_XML_FILES) $(XML_CHAPTER_GEN_FILES)
+
# ----------------------------------------------------
INFO_FILE = ../../info
@@ -98,7 +99,7 @@ HTML_FILES = $(XML_REF_MAN:%.xml=$(HTMLDIR)/%.html) \
$(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
-MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
+MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3) $(XMERL_MODULES:%=$(MAN3DIR)/%.3)
MAN6_FILES = $(XML_REF6_FILES:%_app.xml=$(MAN6DIR)/%.6)
HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
@@ -107,10 +108,10 @@ TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
# ----------------------------------------------------
-# FLAGS
+# FLAGS
# ----------------------------------------------------
-XML_FLAGS +=
-DVIPS_FLAGS +=
+XML_FLAGS +=
+DVIPS_FLAGS +=
# ----------------------------------------------------
# Targets
@@ -120,14 +121,14 @@ $(HTMLDIR)/%.gif: %.gif
docs: pdf html man
-$(TOP_PDF_FILE): $(XML_FILES)
+$(TOP_PDF_FILE): $(XML_FILES)
pdf: $(TOP_PDF_FILE)
html: gifs $(HTML_REF_MAN_FILE)
-$(XMERL_XML_FILES):
- escript $(DOCGEN)/priv/bin/xml_from_edoc.escript $(XMERL_DIR)/$(@:%.xml=%.erl)
+$(XMERL_XML_FILES):
+ $(gen_verbose)escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -dir $(XMLDIR) $(XMERL_DIR)/$(@:$(XMLDIR)/%.xml=%.erl)
man: $(MAN3_FILES) $(MAN6_FILES)
@@ -135,15 +136,16 @@ gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
xml: $(XMERL_XML_FILES)
-debug opt:
+debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
- rm -f $(MAN3DIR)/*
- rm -f $(MAN6DIR)/*
+ rm -rf $(XMLDIR)
+ rm -f $(MAN3DIR)/*
+ rm -f $(MAN6DIR)/*
rm -f $(XMERL_XML_FILES)
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
- rm -f errs core *~
+ rm -f errs core *~
info:
@@ -158,7 +160,7 @@ info:
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_docs_spec: docs
@@ -177,6 +179,3 @@ release_spec:
release_tests_spec:
-
-
-
diff --git a/lib/xmerl/doc/src/fascicules.xml b/lib/xmerl/doc/src/fascicules.xml
deleted file mode 100644
index 37feca543f..0000000000
--- a/lib/xmerl/doc/src/fascicules.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
-
-<fascicules>
- <fascicule file="part" href="part_frame.html" entry="no">
- User's Guide
- </fascicule>
- <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
- Reference Manual
- </fascicule>
- <fascicule file="part_notes" href="part_notes_frame.html" entry="no">
- Release Notes
- </fascicule>
- <fascicule file="" href="../../../../doc/print.html" entry="no">
- Off-Print
- </fascicule>
-</fascicules>
-
diff --git a/lib/xmerl/doc/src/notes.xml b/lib/xmerl/doc/src/notes.xml
index 1162561225..a97036127e 100644
--- a/lib/xmerl/doc/src/notes.xml
+++ b/lib/xmerl/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,51 @@
<p>This document describes the changes made to the Xmerl application.</p>
+<section><title>Xmerl 1.3.18</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Xmerl 1.3.17</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix typos in documentation.</p>
+ <p>
+ Own Id: OTP-15039</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Xmerl 1.3.16</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Xmerl 1.3.15</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/xmerl/doc/src/part_notes.xml b/lib/xmerl/doc/src/part_notes.xml
deleted file mode 100644
index 4ed441c7d4..0000000000
--- a/lib/xmerl/doc/src/part_notes.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE part SYSTEM "part.dtd">
-
-<part xmlns:xi="http://www.w3.org/2001/XInclude">
- <header>
- <copyright>
- <year>2004</year><year>2016</year>
- <holder>Ericsson AB. All Rights Reserved.</holder>
- </copyright>
- <legalnotice>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- </legalnotice>
-
- <title>Xmerl Release Notes</title>
- <prepared>Bertil Karlsson</prepared>
- <docno></docno>
- <date>>2004-12-15</date>
- <rev></rev>
- <file>part_notes.xml</file>
- </header>
- <description>
- <p>The <em>Xmerl</em> application
- contains modules with support for processing of xml files compliant to XML 1.0.</p>
- <p>There are also release notes for
- <url href="notes_history.html">older versions</url>.</p>
- </description>
- <xi:include href="notes.xml"/>
-</part>
-
diff --git a/lib/xmerl/src/xmerl_scan.erl b/lib/xmerl/src/xmerl_scan.erl
index a1f6ad4e2c..e543a5a11e 100644
--- a/lib/xmerl/src/xmerl_scan.erl
+++ b/lib/xmerl/src/xmerl_scan.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -279,7 +279,7 @@ int_file_decl(F, Options,_ExtCharset) ->
%% @spec string(Text::list()) -> {xmlElement(),Rest}
%% Rest = list()
-%% @equiv string(Test, [])
+%% @equiv string(Text, [])
string(Str) ->
string(Str, []).
diff --git a/lib/xmerl/src/xmerl_xsd.erl b/lib/xmerl/src/xmerl_xsd.erl
index a89b3159ec..2836bb0e5b 100644
--- a/lib/xmerl/src/xmerl_xsd.erl
+++ b/lib/xmerl/src/xmerl_xsd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
%%
-%% @doc Interface module for XML Schema vlidation.
+%% @doc Interface module for XML Schema validation.
%% It handles the W3.org
%% <a href="http://www.w3.org/XML/Schema#dev">specifications</a>
%% of XML Schema second edition 28 october 2004. For an introduction to
diff --git a/lib/xmerl/test/xmerl_SUITE_data/eventp/CMOM.xml b/lib/xmerl/test/xmerl_SUITE_data/eventp/CMOM.xml
index 7c64046897..c2533248d1 100644
--- a/lib/xmerl/test/xmerl_SUITE_data/eventp/CMOM.xml
+++ b/lib/xmerl/test/xmerl_SUITE_data/eventp/CMOM.xml
@@ -10264,7 +10264,7 @@ Note! This attribute cannot have a value larger than for 'egressAtmPcr'.</descri
<attribute name="ingressAtmMcr">
<description>Ingress minimum desired cell rate (cells/s).
-Only positive vaues allowed. This attribute is mandatory only when serviceCategory is UBR+.
+Only positive values allowed. This attribute is mandatory only when serviceCategory is UBR+.
Note! When 'serviceCategory' is set to CBR or UBR this attribute has no relevance and the value submitted is ignored by the system.
diff --git a/lib/xmerl/test/xmerl_SUITE_data/eventp/CelloMOM.xml b/lib/xmerl/test/xmerl_SUITE_data/eventp/CelloMOM.xml
index 8f8cf54505..3b5d8ae2ad 100644
--- a/lib/xmerl/test/xmerl_SUITE_data/eventp/CelloMOM.xml
+++ b/lib/xmerl/test/xmerl_SUITE_data/eventp/CelloMOM.xml
@@ -10264,7 +10264,7 @@ Note! This attribute cannot have a value larger than for 'egressAtmPcr'.</descri
<attribute name="ingressAtmMcr">
<description>Ingress minimum desired cell rate (cells/s).
-Only positive vaues allowed. This attribute is mandatory only when serviceCategory is UBR+.
+Only positive values allowed. This attribute is mandatory only when serviceCategory is UBR+.
Note! When 'serviceCategory' is set to CBR or UBR this attribute has no relevance and the value submitted is ignored by the system.
diff --git a/lib/xmerl/vsn.mk b/lib/xmerl/vsn.mk
index 2e9c9061d9..3a266a56bd 100644
--- a/lib/xmerl/vsn.mk
+++ b/lib/xmerl/vsn.mk
@@ -1 +1 @@
-XMERL_VSN = 1.3.15
+XMERL_VSN = 1.3.18